diff --git a/.gitattributes b/.gitattributes index e58996311..d523ee98a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,16 @@ *.odin linguist-language=Odin * text=auto - # These files must always have *nix line-endings Makefile text eol=lf -*.sh text eol=lf \ No newline at end of file +*.sh text eol=lf +vendor/box2d/lib/box2d_windows_amd64_avx2.lib filter=lfs diff=lfs merge=lfs -text +vendor/box2d/lib/box2d_windows_amd64_sse2.lib filter=lfs diff=lfs merge=lfs -text +vendor/miniaudio/lib/miniaudio.lib filter=lfs diff=lfs merge=lfs -text +vendor/sdl3/SDL3.dll filter=lfs diff=lfs merge=lfs -text +vendor/sdl3/SDL3.lib filter=lfs diff=lfs merge=lfs -text +vendor/sdl3/mixer/*.dll filter=lfs diff=lfs merge=lfs -text +vendor/sdl3/mixer/*.lib filter=lfs diff=lfs merge=lfs -text +vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll filter=lfs diff=lfs merge=lfs -text +vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib filter=lfs diff=lfs merge=lfs -text +vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib filter=lfs diff=lfs merge=lfs -text +vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.pdb filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfd9f03ce..9e52074d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ jobs: name: NetBSD Build, Check, and Test runs-on: ubuntu-latest env: - PKGSRC_BRANCH: 2024Q3 + PKGSRC_BRANCH: 2025Q4 steps: - uses: actions/checkout@v4 - name: Build, Check, and Test @@ -30,14 +30,14 @@ jobs: gmake -C vendor/stb/src gmake -C vendor/cgltf/src gmake -C vendor/miniaudio/src - ./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_amd64 - ./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_arm64 - ./odin check vendor/sdl3 -vet -strict-style -disallow-do -target:netbsd_amd64 -no-entry-point - ./odin check vendor/sdl3 -vet -strict-style -disallow-do -target:netbsd_arm64 -no-entry-point + ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_amd64 + ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_arm64 + ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_amd64 -no-entry-point + ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_arm64 -no-entry-point ./odin run tests/heap_allocator -vet -strict-style -disallow-do -debug -- -allocator=feoramalloc -vmem-tests -serial-tests -parallel-tests - ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true - ./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true - ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/core/normal.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/core/speed.odin -file -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true (cd tests/issues; ./run.sh) ./odin check tests/benchmark -vet -strict-style -no-entry-point @@ -64,52 +64,64 @@ jobs: gmake -C vendor/stb/src gmake -C vendor/cgltf/src gmake -C vendor/miniaudio/src - ./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64 - ./odin check vendor/sdl3 -vet -strict-style -disallow-do -target:freebsd_amd64 -no-entry-point + ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_amd64 + ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_amd64 -no-entry-point ./odin run tests/heap_allocator -vet -strict-style -disallow-do -debug -- -allocator=feoramalloc -vmem-tests -serial-tests -parallel-tests - ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true - ./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true - ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/core/normal.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/core/speed.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + ./odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true (cd tests/issues; ./run.sh) ./odin check tests/benchmark -vet -strict-style -no-entry-point ci: strategy: fail-fast: false matrix: - # MacOS 13 runs on Intel, 14 runs on ARM - os: [ubuntu-latest, macos-13, macos-14] + os: [macos-15-intel, macos-latest, ubuntu-latest, ubuntu-24.04-arm] runs-on: ${{ matrix.os }} - name: ${{ matrix.os == 'macos-14' && 'MacOS ARM' || (matrix.os == 'macos-13' && 'MacOS Intel' || 'Ubuntu') }} Build, Check, and Test + name: ${{ matrix.os == 'macos-latest' && 'MacOS ARM' || (matrix.os == 'macos-15-intel' && 'MacOS Intel') || (matrix.os == 'ubuntu-latest' && 'Ubuntu') || (matrix.os == 'ubuntu-24.04-arm' && 'Ubuntu ARM') }} Build, Check, and Test timeout-minutes: 15 steps: + - uses: actions/checkout@v4 - - name: Download LLVM (Linux) - if: matrix.os == 'ubuntu-latest' + - name: Download LLVM (MacOS Intel) + if: matrix.os == 'macos-15-intel' + run: | + brew update + brew install llvm@20 lua@5.4 lld + echo "$(brew --prefix llvm@20)/bin" >> $GITHUB_PATH + + - name: Download LLVM (MacOS ARM) + if: matrix.os == 'macos-latest' + run: | + brew update + brew install llvm@22 wasmtime lua@5.4 lld + echo "$(brew --prefix llvm@22)/bin" >> $GITHUB_PATH + + - name: Download LLVM (Ubuntu) + if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm' run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 20 echo "/usr/lib/llvm-20/bin" >> $GITHUB_PATH - - - name: Download LLVM (MacOS Intel) - if: matrix.os == 'macos-13' - run: | - brew update - brew install llvm@20 lua@5.4 lld - - - name: Download LLVM (MacOS ARM) - if: matrix.os == 'macos-14' - run: | - brew update - brew install llvm@20 wasmtime lua@5.4 lld - - name: Build Odin run: ./build_odin.sh release - name: Odin version run: ./odin version - name: Odin report run: ./odin report + - name: Get needed vendor libs + if: matrix.os == 'ubuntu-24.04-arm' + run: sudo apt-get install -y liblua5.4-dev + - name: Install libcurl (Ubuntu) + if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm' + run: | + sudo apt-get install libcurl4-openssl-dev libmbedtls-dev + - name: Install libcurl (macOS) + if: matrix.os == 'macos-15-intel' || matrix.os == 'macos-latest' + run: | + brew install curl mbedtls - name: Compile needed Vendor run: | make -C vendor/stb/src @@ -122,58 +134,65 @@ jobs: - name: Odin run -debug run: ./odin run examples/demo -debug - name: Odin check examples/all - run: ./odin check examples/all -strict-style -vet -disallow-do - - name: Odin check vendor/sdl3 - run: ./odin check vendor/sdl3 -strict-style -vet -disallow-do -no-entry-point + run: ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do + - name: Odin check examples/all/sdl3 + run: ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point - name: Odin heap allocator tests run: ./odin run tests/heap_allocator -vet -strict-style -disallow-do -debug -sanitize:thread -- -allocator=feoramalloc -vmem-tests -serial-tests -parallel-tests - name: Normal Core library tests - run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + run: ./odin test tests/core/normal.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address - name: Optimized Core library tests - run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + - name: Wycheproof tests + run: ./odin test tests/core/crypto/wycheproof -vet -vet-tabs -strict-style -vet-style -vet-cast -warnings-as-errors -disallow-do -o:speed + - name: Noise Protocol Framework tests + run: ./odin test tests/core/crypto/noise -vet -vet-tabs -strict-style -vet-style -vet-cast -warnings-as-errors -disallow-do -o:speed - name: Vendor library tests - run: ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + run: ./odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address + if: matrix.os != 'macos-15-intel' && matrix.os != 'macos-latest' + - name: Vendor library tests (MacOS ARM) + run: ./odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address -extra-linker-flags:"-L/opt/homebrew/opt/lua@5.4/lib" + if: matrix.os == 'macos-latest' + - name: Vendor library tests (MacOS Intel) + run: ./odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address -extra-linker-flags:"-L/usr/local/opt/lua@5.4/lib" + if: matrix.os == 'macos-15-intel' + - name: Internals tests - run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + run: ./odin test tests/internal -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address - name: GitHub Issue tests run: | cd tests/issues ./run.sh - - name: Check benchmarks - run: ./odin check tests/benchmark -vet -strict-style -no-entry-point - - name: Odin check examples/all for Linux i386 - run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_i386 - if: matrix.os == 'ubuntu-latest' - - name: Odin check examples/all for Linux arm64 - run: ./odin check examples/all -vet -strict-style -disallow-do -target:linux_arm64 - if: matrix.os == 'ubuntu-latest' - - name: Odin check examples/all for FreeBSD amd64 - run: ./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64 - if: matrix.os == 'ubuntu-latest' - - name: Odin check examples/all for OpenBSD amd64 - run: ./odin check examples/all -vet -strict-style -disallow-do -target:openbsd_amd64 - if: matrix.os == 'ubuntu-latest' - - - name: Odin check vendor/sdl3 for Linux i386 - run: ./odin check vendor/sdl3 -vet -strict-style -disallow-do -no-entry-point -target:linux_i386 - if: matrix.os == 'ubuntu-latest' - - name: Odin check vendor/sdl3 for Linux arm64 - run: ./odin check vendor/sdl3 -vet -strict-style -disallow-do -no-entry-point -target:linux_arm64 - if: matrix.os == 'ubuntu-latest' - - name: Odin check vendor/sdl3 for FreeBSD amd64 - run: ./odin check vendor/sdl3 -vet -strict-style -disallow-do -no-entry-point -target:freebsd_amd64 - if: matrix.os == 'ubuntu-latest' - - name: Odin check vendor/sdl3 for OpenBSD amd64 - run: ./odin check vendor/sdl3 -vet -strict-style -disallow-do -no-entry-point -target:openbsd_amd64 - if: matrix.os == 'ubuntu-latest' - - - name: Run demo on WASI WASM32 run: | - ./odin build examples/demo -target:wasi_wasm32 -vet -strict-style -disallow-do -out:demo + ./odin build examples/demo -target:wasi_wasm32 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -out:demo wasmtime ./demo.wasm - if: matrix.os == 'macos-14' + if: matrix.os == 'macos-latest' + + - name: Check benchmarks + run: ./odin check tests/benchmark -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point + + - name: Odin check examples/all for Linux i386 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_i386 + - name: Odin check examples/all for OpenBSD amd64 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:openbsd_amd64 + + - name: Odin check examples/all for js_wasm32 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point -target:js_wasm32 + - name: Odin check examples/all for js_wasm64p32 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point -target:js_wasm64p32 + + - name: Odin check examples/all/sdl3 for Linux i386 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point -target:linux_i386 + - name: Odin check examples/all/sdl3 for OpenBSD amd64 + if: matrix.os == 'ubuntu-latest' + run: ./odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point -target:openbsd_amd64 build_windows: name: Windows Build, Check, and Test @@ -184,7 +203,7 @@ jobs: - name: build Odin shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" ./build.bat 1 - name: Odin version run: ./odin version @@ -193,28 +212,28 @@ jobs: - name: Odin check shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" odin check examples/demo -vet - name: Odin run shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" odin run examples/demo - name: Odin run -debug shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin run examples/demo -debug -vet -strict-style -disallow-do + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin run examples/demo -debug -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do - name: Odin check examples/all shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin check examples/all -vet -strict-style -disallow-do - - name: Odin check vendor/sdl3 + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do + - name: Odin check examples/all/sdl3 shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin check vendor/sdl3 -vet -strict-style -disallow-do -no-entry-point + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin check examples/all/sdl3 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point - name: Odin heap allocator tests shell: cmd run: | @@ -223,51 +242,55 @@ jobs: - name: Core library tests shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin test tests/core/normal.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address - name: Optimized core library tests shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin test tests/core/speed.odin -o:speed -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + - name: Wycheproof tests + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin test tests/core/crypto/wycheproof -vet -vet-tabs -strict-style -vet-style -vet-cast -warnings-as-errors -disallow-do -o:speed -microarch:native + - name: Noise Protocol Framework tests + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin test tests/core/crypto/noise -vet -vet-tabs -strict-style -vet-style -vet-cast -warnings-as-errors -disallow-do -o:speed -microarch:native - name: Vendor library tests shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" copy vendor\lua\5.4\windows\*.dll . - odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + odin test tests/vendor -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address - name: Odin internals tests shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + odin test tests/internal -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -sanitize:address - name: Check issues shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cd tests/issues call run.bat - name: Check benchmarks shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" odin check tests/benchmark -vet -strict-style -no-entry-point - name: Odin documentation tests shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cd tests\documentation call build.bat - - name: core:math/big tests - shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat - cd tests\core\math\big - call build.bat - name: Odin check examples/all for Windows 32bits shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" odin check examples/all -strict-style -target:windows_i386 build_linux_riscv64: @@ -284,6 +307,10 @@ jobs: sudo ./llvm.sh 18 echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH + - name: Install libcurl + run: | + sudo apt-get install libcurl4-openssl-dev libmbedtls-dev + - name: Build Odin run: ./build_odin.sh release @@ -300,28 +327,28 @@ jobs: make -C vendor/miniaudio/src - name: Odin check examples/all - run: ./odin check examples/all -target:linux_riscv64 -vet -strict-style -disallow-do + run: ./odin check examples/all -target:linux_riscv64 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do - - name: Odin check vendor/sdl3 - run: ./odin check vendor/sdl3 -target:linux_riscv64 -vet -strict-style -disallow-do -no-entry-point + - name: Odin check examples/all/sdl3 + run: ./odin check examples/all/sdl3 -target:linux_riscv64 -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -no-entry-point - name: Install riscv64 toolchain and qemu run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross - name: Odin run - run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath + run: ./odin run examples/demo -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath - name: Odin run -debug - run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath + run: ./odin run examples/demo -debug -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath - name: Odin heap allocator tests run: ./odin run tests/heap_allocator -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath -debug -- -allocator=feoramalloc -vmem-tests -serial-tests -parallel-tests - name: Normal Core library tests - run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath + run: ./odin test tests/core/normal.odin -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath - name: Optimized Core library tests - run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath + run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath - name: Internals tests - run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath + run: ./odin test tests/internal -all-packages -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index eb67eb209..5d8fe2e8e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -12,6 +12,8 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@v4 + with: + lfs: true - name: build Odin shell: cmd run: | @@ -42,30 +44,34 @@ jobs: name: windows_artifacts path: dist build_linux: - name: Linux Build + strategy: + matrix: + arch: [amd64, arm64] + env: + ARCH: ${{ matrix.arch }} + DOCKER_IMAGE: ${{ matrix.arch == 'amd64' && 'alpine:3.24' || 'arm64v8/alpine:3.24' }} + name: Linux Build ${{ matrix.arch }} if: github.repository == 'odin-lang/Odin' - runs-on: ubuntu-latest + runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} steps: - uses: actions/checkout@v4 - - uses: jirutka/setup-alpine@v1 with: - branch: edge - - name: (Linux) Download LLVM + lfs: true + - name: (Linux) Download LLVM and Build Odin run: | - apk add --no-cache \ - musl-dev llvm20-dev clang20 git mold lz4 \ - libxml2-static llvm20-static zlib-static zstd-static \ - make - shell: alpine.sh --root {0} - - name: build odin - # NOTE: this build does slow compile times because of musl - run: ci/build_linux_static.sh - shell: alpine.sh {0} + docker run --rm -v "$PWD:/src" -w /src $DOCKER_IMAGE sh -c ' + apk add --no-cache \ + musl-dev llvm20-dev clang20 build-base git mold lz4 \ + libxml2-static llvm20-static zlib-static zstd-static \ + make && + git config --global --add safe.directory /src && + ./ci/build_linux_static.sh + ' - name: Odin run run: ./odin run examples/demo - name: Copy artifacts run: | - FILE="odin-linux-amd64-nightly+$(date -I)" + FILE="odin-linux-$ARCH-nightly+$(date -I)" mkdir $FILE cp odin $FILE cp LICENSE $FILE @@ -74,27 +80,36 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE - name: Odin run run: | - FILE="odin-linux-amd64-nightly+$(date -I)" + FILE="odin-linux-$ARCH-nightly+$(date -I)" $FILE/odin run examples/demo - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: linux_artifacts + name: ${{ matrix.arch == 'amd64' && 'linux_artifacts' || 'linux_arm_artifacts' }} path: dist.tar.gz build_macos: - name: MacOS Build + strategy: + matrix: + arch: [amd64, arm64] + env: + ARCH: ${{ matrix.arch }} + name: Macos Build ${{ matrix.arch }} if: github.repository == 'odin-lang/Odin' - runs-on: macos-13 + runs-on: ${{ matrix.arch == 'amd64' && 'macos-15-intel' || 'macos-latest' }} steps: - uses: actions/checkout@v4 + with: + lfs: true - name: Download LLVM and setup PATH run: | brew update - brew install llvm@20 dylibbundler lld + brew install llvm@20 dylibbundler lld@20 + brew link llvm@20 - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to @@ -102,7 +117,7 @@ jobs: run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly - name: Bundle run: | - FILE="odin-macos-amd64-nightly+$(date -I)" + FILE="odin-macos-$ARCH-nightly+$(date -I)" mkdir $FILE cp odin $FILE cp LICENSE $FILE @@ -111,59 +126,22 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE - name: Odin run run: | - FILE="odin-macos-amd64-nightly+$(date -I)" + FILE="odin-macos-$ARCH-nightly+$(date -I)" $FILE/odin run examples/demo - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: macos_artifacts - path: dist.tar.gz - build_macos_arm: - name: MacOS ARM Build - if: github.repository == 'odin-lang/Odin' - runs-on: macos-14 # ARM machine - steps: - - uses: actions/checkout@v4 - - name: Download LLVM and setup PATH - run: | - brew update - brew install llvm@20 dylibbundler lld - - - name: build odin - # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to - # not link with libunwind bundled with LLVM but link with libunwind on the system. - run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly - - name: Bundle - run: | - FILE="odin-macos-arm64-nightly+$(date -I)" - mkdir $FILE - cp odin $FILE - cp LICENSE $FILE - cp -r shared $FILE - cp -r base $FILE - cp -r core $FILE - cp -r vendor $FILE - cp -r examples $FILE - dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs - # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 - tar -czvf dist.tar.gz $FILE - - name: Odin run - run: | - FILE="odin-macos-arm64-nightly+$(date -I)" - $FILE/odin run examples/demo - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: macos_arm_artifacts + name: ${{ matrix.arch == 'amd64' && 'macos_artifacts' || 'macos_arm_artifacts' }} path: dist.tar.gz upload_b2: runs-on: [ubuntu-latest] - needs: [build_windows, build_macos, build_macos_arm, build_linux] + needs: [build_windows, build_macos, build_linux] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -192,6 +170,12 @@ jobs: name: linux_artifacts path: linux_artifacts + - name: Download Ubuntu ARM artifacts + uses: actions/download-artifact@v4.1.7 + with: + name: linux_arm_artifacts + path: linux_arm_artifacts + - name: Download macOS artifacts uses: actions/download-artifact@v4.1.7 with: @@ -219,6 +203,7 @@ jobs: file linux_artifacts/dist.tar.gz python3 ci/nightly.py artifact windows-amd64 windows_artifacts/ python3 ci/nightly.py artifact linux-amd64 linux_artifacts/dist.tar.gz + python3 ci/nightly.py artifact linux-arm64 linux_arm_artifacts/dist.tar.gz python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.tar.gz python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.tar.gz python3 ci/nightly.py prune diff --git a/.gitignore b/.gitignore index 32e5f5b0f..00dbcc2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -277,6 +277,10 @@ odin *.bin demo.bin libLLVM*.so* +*.a + +# WASM +*.wasm # shared collection shared/ @@ -293,5 +297,17 @@ build.sh # RAD debugger project file *.raddbg - +*.rdi +tests/issues/build/* misc/featuregen/featuregen + +# Clangd stuff +.cache/ +.clangd +compile_commands.json + +# Dev cmake helpers +build/ +cmake-build*/ +CMakeLists.txt +sandbox/ diff --git a/LICENSE b/LICENSE index 4d155def4..919f29937 100644 --- a/LICENSE +++ b/LICENSE @@ -1,26 +1,17 @@ -Copyright (c) 2016-2024 Ginger Bill. All rights reserved. +Copyright (c) 2016-2025 Ginger Bill. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/base/builtin/builtin.odin b/base/builtin/builtin.odin index 227ceeb49..2dd214321 100644 --- a/base/builtin/builtin.odin +++ b/base/builtin/builtin.odin @@ -7,13 +7,232 @@ nil :: nil false :: 0!=0 true :: 0==0 -ODIN_OS :: ODIN_OS -ODIN_ARCH :: ODIN_ARCH -ODIN_ENDIAN :: ODIN_ENDIAN -ODIN_VENDOR :: ODIN_VENDOR -ODIN_VERSION :: ODIN_VERSION -ODIN_ROOT :: ODIN_ROOT -ODIN_DEBUG :: ODIN_DEBUG +// The following constants are added in `checker.cpp`'s `init_universal` procedure. + +/* + An `enum` value indicating the target's CPU architecture. + Possible values are: `.amd64`, `.i386`, `.arm32`, `.arm64`, `.wasm32`, `.wasm64p32`, and `.riscv64`. +*/ +ODIN_ARCH :: ODIN_ARCH + +/* + A `string` indicating the target's CPU architecture. + Possible values are: "amd64", "i386", "arm32", "arm64", "wasm32", "wasm64p32", "riscv64". +*/ +ODIN_ARCH_STRING :: ODIN_ARCH_STRING + +/* + An `enum` value indicating the type of compiled output, chosen using `-build-mode`. + Possible values are: `.Executable`, `.Dynamic`, `.Static`, `.Object`, `.Assembly`, and `.LLVM_IR`. +*/ +ODIN_BUILD_MODE :: ODIN_BUILD_MODE + +/* + A `string` containing the name of the folder that contains the entry point, + e.g. for `%ODIN_ROOT%/examples/demo`, this would contain `demo`. +*/ +ODIN_BUILD_PROJECT_NAME :: ODIN_BUILD_PROJECT_NAME + +/* + An `i64` containing the time at which the executable was compiled, in nanoseconds. + This is compatible with the `time.Time` type, i.e. `time.Time{_nsec=ODIN_COMPILE_TIMESTAMP}` +*/ +ODIN_COMPILE_TIMESTAMP :: ODIN_COMPILE_TIMESTAMP + +/* + `true` if the `-debug` command line switch is passed, which enables debug info generation. +*/ +ODIN_DEBUG :: ODIN_DEBUG + +/* + `true` if the `-default-to-nil-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that does nothing. +*/ +ODIN_DEFAULT_TO_NIL_ALLOCATOR :: ODIN_DEFAULT_TO_NIL_ALLOCATOR + +/* + `true` if the `-default-to-panic-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that panics if allocated from. +*/ +ODIN_DEFAULT_TO_PANIC_ALLOCATOR :: ODIN_DEFAULT_TO_PANIC_ALLOCATOR + +/* + `true` if the `-disable-assert` command line switch is passed, + which removes all calls to `assert` from the program. +*/ +ODIN_DISABLE_ASSERT :: ODIN_DISABLE_ASSERT + +/* + An `enum` value indicating the endianness of the target. + Possible values are: `.Little` and `.Big`. +*/ +ODIN_ENDIAN :: ODIN_ENDIAN + +/* + An `string` indicating the endianness of the target. + Possible values are: "little" and "big". +*/ +ODIN_ENDIAN_STRING :: ODIN_ENDIAN_STRING + +/* + An `enum` value set using the `-error-pos-style` switch, indicating the source location style used for compile errors and warnings. + Possible values are: `.Default` (Odin-style) and `.Unix`. +*/ +ODIN_ERROR_POS_STYLE :: ODIN_ERROR_POS_STYLE + +/* + `true` if the `-foreign-error-procedures` command line switch is passed, + which inhibits generation of runtime error procedures, so that they can be in a separate compilation unit. +*/ +ODIN_FOREIGN_ERROR_PROCEDURES :: ODIN_FOREIGN_ERROR_PROCEDURES + +/* + A `string` describing the microarchitecture used for code generation. + If not set using the `-microarch` command line switch, the compiler will pick a default. + Possible values include, but are not limited to: "sandybridge", "x86-64-v2". +*/ +ODIN_MICROARCH_STRING :: ODIN_MICROARCH_STRING + +/* + An `int` value representing the minimum OS version given to the linker, calculated as `major * 10_000 + minor * 100 + revision`. + If not set using the `-minimum-os-version` command line switch, it defaults to `0`, except on Darwin, where it's `11_00_00`. +*/ +ODIN_MINIMUM_OS_VERSION :: ODIN_MINIMUM_OS_VERSION + +/* + `true` if the `-no-bounds-check` command line switch is passed, which disables bounds checking at runtime. +*/ +ODIN_NO_BOUNDS_CHECK :: ODIN_NO_BOUNDS_CHECK + +/* + `true` if the `-no-crt` command line switch is passed, which inhibits linking with the C Runtime Library, a.k.a. LibC. +*/ +ODIN_NO_CRT :: ODIN_NO_CRT + +/* + `true` if the `-no-entry-point` command line switch is passed, which makes the declaration of a `main` procedure optional. +*/ +ODIN_NO_ENTRY_POINT :: ODIN_NO_ENTRY_POINT + +/* + `true` if the `-no-rtti` command line switch is passed, which inhibits generation of full Runtime Type Information. +*/ +ODIN_NO_RTTI :: ODIN_NO_RTTI + +/* + `true` if the `-no-type-assert` command line switch is passed, which disables type assertion checking program wide. +*/ +ODIN_NO_TYPE_ASSERT :: ODIN_NO_TYPE_ASSERT + +/* + An `enum` value indicating the optimization level selected using the `-o` command line switch. + Possible values are: `.None`, `.Minimal`, `.Size`, `.Speed`, and `.Aggressive`. + + If `ODIN_OPTIMIZATION_MODE` is anything other than `.None` or `.Minimal`, the compiler will also perform a unity build, + and `ODIN_USE_SEPARATE_MODULES` will be set to `false` as a result. +*/ +ODIN_OPTIMIZATION_MODE :: ODIN_OPTIMIZATION_MODE + +/* + An `enum` value indicating what the target operating system is. +*/ +ODIN_OS :: ODIN_OS + +/* + A `string` indicating what the target operating system is. +*/ +ODIN_OS_STRING :: ODIN_OS_STRING + +/* + An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch. + Possible values are: `.Default` `.iPhone`, .iPhoneSimulator, and `.Android`. +*/ +ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET + +/* + A `string` representing the path of the folder containing the Odin compiler, + relative to which we expect to find the `base` and `core` package collections. +*/ +ODIN_ROOT :: ODIN_ROOT + +/* + A `bit_set` indicating the sanitizer flags set using the `-sanitize` command line switch. + Supported flags are `.Address`, `.Memory`, and `.Thread`. +*/ +ODIN_SANITIZER_FLAGS :: ODIN_SANITIZER_FLAGS + +/* + `true` if the code is being compiled via an invocation of `odin test`. +*/ +ODIN_TEST :: ODIN_TEST + +/* + `true` if built using the experimental Tilde backend. +*/ +ODIN_TILDE :: ODIN_TILDE + +/* + `true` by default, meaning each each package is built into its own object file, and then linked together. + `false` if the `-use-single-module` command line switch to force a unity build is provided. + + If `ODIN_OPTIMIZATION_MODE` is anything other than `.None` or `.Minimal`, the compiler will also perform a unity build, + and this constant will also be set to `false`. +*/ +ODIN_USE_SEPARATE_MODULES :: ODIN_USE_SEPARATE_MODULES + +/* + `true` if Valgrind integration is supported on the target. +*/ +ODIN_VALGRIND_SUPPORT :: ODIN_VALGRIND_SUPPORT + +/* + A `string` which identifies the compiler being used. The official compiler sets this to `"odin"`. +*/ +ODIN_VENDOR :: ODIN_VENDOR + +/* + A `string` containing the version of the Odin compiler, typically in the format `dev-YYYY-MM`. +*/ +ODIN_VERSION :: ODIN_VERSION + +/* + A `string` containing the Git hash part of the Odin version. + Empty if `.git` could not be detected at the time the compiler was built. +*/ +ODIN_VERSION_HASH :: ODIN_VERSION_HASH + +/* + An `enum` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + `.Unknown` - Default and only value on non-Windows platforms + `.Console` - Default on Windows + `.Windows` - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM :: ODIN_WINDOWS_SUBSYSTEM + +/* + An `string` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + "UNKNOWN" - Default and only value on non-Windows platforms + "CONSOLE" - Default on Windows + "WINDOWS" - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM_STRING :: ODIN_WINDOWS_SUBSYSTEM_STRING + +/* + `true` if LLVM supports the f16 type. +*/ +__ODIN_LLVM_F16_SUPPORTED :: __ODIN_LLVM_F16_SUPPORTED + + byte :: u8 // alias @@ -119,7 +338,8 @@ jmag :: proc(value: Quaternion) -> Float --- kmag :: proc(value: Quaternion) -> Float --- conj :: proc(value: Complex_Or_Quaternion) -> Complex_Or_Quaternion --- -expand_values :: proc(value: Struct_Or_Array) -> (A, B, C, ...) --- +expand_values :: proc(value: Struct_Or_Array) -> (A, B, C, ...) --- +compress_values :: proc(values: ...) -> Struct_Or_Array_Like_Type --- min :: proc(values: ..T) -> T --- max :: proc(values: ..T) -> T --- @@ -130,3 +350,6 @@ soa_zip :: proc(slices: ...) -> #soa[]Struct --- soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) --- unreachable :: proc() -> ! --- + +// Where T is a string, slice, dynamic array, or pointer to an array type +raw_data :: proc(t: $T) -> rawptr \ No newline at end of file diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 0e2746a3f..e639aadbd 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -4,6 +4,7 @@ package intrinsics import "base:runtime" + // Package-Related is_package_imported :: proc(package_name: string) -> bool --- @@ -32,11 +33,14 @@ trap :: proc() -> ! --- alloca :: proc(size, align: int) -> [^]u8 --- cpu_relax :: proc() --- read_cycle_counter :: proc() -> i64 --- +read_cycle_counter_frequency :: proc() -> i64 --- count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- +count_trailing_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- +count_leading_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) --- @@ -74,7 +78,9 @@ prefetch_write_instruction :: proc(address: rawptr, #const locality: i32 /* 0..= prefetch_write_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) --- // Compiler Hints -expect :: proc(val, expected_val: $T) -> T --- +expect :: proc(val, expected_val: $T) -> T --- +likely :: proc(val: $T) -> T where type_is_boolean(T) --- +unlikely :: proc(val: $T) -> T where type_is_boolean(T) --- // Linux and Darwin Only syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr --- @@ -137,9 +143,13 @@ type_is_rune :: proc($T: typeid) -> bool --- type_is_float :: proc($T: typeid) -> bool --- type_is_complex :: proc($T: typeid) -> bool --- type_is_quaternion :: proc($T: typeid) -> bool --- -type_is_string :: proc($T: typeid) -> bool --- type_is_typeid :: proc($T: typeid) -> bool --- type_is_any :: proc($T: typeid) -> bool --- +type_is_string :: proc($T: typeid) -> bool --- +type_is_string16 :: proc($T: typeid) -> bool --- +type_is_cstring :: proc($T: typeid) -> bool --- +type_is_cstring16 :: proc($T: typeid) -> bool --- + type_is_endian_platform :: proc($T: typeid) -> bool --- type_is_endian_little :: proc($T: typeid) -> bool --- @@ -152,6 +162,7 @@ type_is_indexable :: proc($T: typeid) -> bool --- type_is_sliceable :: proc($T: typeid) -> bool --- type_is_comparable :: proc($T: typeid) -> bool --- type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=) +type_is_nearly_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (including floats) type_is_dereferenceable :: proc($T: typeid) -> bool --- type_is_valid_map_key :: proc($T: typeid) -> bool --- type_is_valid_matrix_elements :: proc($T: typeid) -> bool --- @@ -169,8 +180,12 @@ type_is_union :: proc($T: typeid) -> bool --- type_is_enum :: proc($T: typeid) -> bool --- type_is_proc :: proc($T: typeid) -> bool --- type_is_bit_set :: proc($T: typeid) -> bool --- +type_is_bit_field :: proc($T: typeid) -> bool --- type_is_simd_vector :: proc($T: typeid) -> bool --- type_is_matrix :: proc($T: typeid) -> bool --- +type_is_fixed_capacity_dynamic_array :: proc($T: typeid) -> bool --- + +type_is_internally_pointer_like :: proc($T: typeid) -> bool --- type_has_nil :: proc($T: typeid) -> bool --- @@ -193,12 +208,17 @@ type_bit_set_underlying_type :: proc($T: typeid) -> typeid where type_is_bit_set type_has_field :: proc($T: typeid, $name: string) -> bool --- type_field_type :: proc($T: typeid, $name: string) -> typeid --- +type_field_bit_size :: proc($T: typeid, $name: string) -> int where type_is_bit_field(T) --- +type_field_bit_offset :: proc($T: typeid, $name: string) -> int where type_is_bit_field(T) --- + type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) --- type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) --- type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) --- type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) --- +type_proc_calling_convention :: proc($T: typeid) -> Odin_Calling_Convention where type_is_proc(T) --- + type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) --- type_struct_has_implicit_padding :: proc($T: typeid) -> bool where type_is_struct(T) --- @@ -208,10 +228,17 @@ type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V -- type_is_specialized_polymorphic_record :: proc($T: typeid) -> bool --- type_is_unspecialized_polymorphic_record :: proc($T: typeid) -> bool --- -type_is_subtype_of :: proc($T, $U: typeid) -> bool --- +type_is_subtype_of :: proc($T, $U: typeid) -> bool --- +type_is_superset_of :: proc($Super, $Sub: typeid) -> bool --- type_field_index_of :: proc($T: typeid, $name: string) -> uintptr --- +type_fixed_capacity_dynamic_array_len_offset :: proc($T: typeid/[dynamic; $N]$E) -> uintptr --- + +// "Contiguous" means that the set of enum constants, when sorted, have a difference of either 0 or 1 between consecutive values. +// This is the exact opposite of "sparse". +type_enum_is_contiguous :: proc($T: typeid) -> bool where type_is_enum(T) --- + type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) --- type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) --- @@ -221,12 +248,25 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info --- type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) --- type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) --- +type_integer_to_unsigned :: proc($T: typeid) -> type where type_is_integer(T), !type_is_unsigned(T) --- +type_integer_to_signed :: proc($T: typeid) -> type where type_is_integer(T), type_is_unsigned(T) --- + type_has_shared_fields :: proc($U, $V: typeid) -> bool where type_is_struct(U), type_is_struct(V) --- + + +// Returns the canonicalized name of the type, of which is used to produce the pseudo-unique 'typeid' +type_canonical_name :: proc($T: typeid) -> string --- + constant_utf16_cstring :: proc($literal: string) -> [^]u16 --- constant_log2 :: proc($v: $T) -> T where type_is_integer(T) --- +constant_floor :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) --- +constant_trunc :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) --- +constant_ceil :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) --- +constant_round :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) --- + // SIMD related simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T --- simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T --- @@ -306,6 +346,7 @@ simd_indices :: proc($T: typeid/#simd[$N]$E) -> T where type_is_numeric(T) --- simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T --- simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T --- +simd_runtime_swizzle :: proc(table: #simd[N]T, indices: #simd[N]T) -> #simd[N]T where type_is_integer(T) --- // Lane-wise operations simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float --- @@ -314,7 +355,11 @@ simd_trunc :: proc(a: #simd[N]any_float) -> #simd[N]any_float --- // rounding to the nearest integral value; if two values are equally near, rounds to the even one simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float --- -simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) --- +simd_approx_recip :: proc(x: #simd[N]T) -> #simd[N]T where type_is_float(T)) --- +simd_approx_recip_sqrt :: proc(x: #simd[N]T) -> #simd[N]T where type_is_float(T)) --- + +simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) --- +simd_to_bits_signed :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), !type_is_unsigned(Integer) --- // equivalent to a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0) simd_lanes_reverse :: proc(a: #simd[N]T) -> #simd[N]T --- @@ -322,6 +367,19 @@ simd_lanes_reverse :: proc(a: #simd[N]T) -> #simd[N]T --- simd_lanes_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T --- simd_lanes_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T --- +// return {b[0], a[1], b[2], a[3], ...} +simd_odd_even :: proc(a, b: #simd[N]T) -> #simd[N]T --- + +// Returns the sums of N consecutive lanes +simd_sums_of_n :: proc(a: #simd[LANES]T, $N: uint) -> #simd[LANES/N]T where is_power_of_two(N) --- + +simd_pairwise_add :: proc(a, b: #simd[LANES]T) -> #simd[LANES]T where LANES % 2 == 0 --- +simd_pairwise_sub :: proc(a, b: #simd[LANES]T) -> #simd[LANES]T where LANES % 2 == 0 --- + +simd_interleave :: proc(a, ..#simd[LANES/N]T) -> #simd[LANES]T where N >= 1 --- +simd_deinterleave :: proc(a: #simd[LANES]T, $N: uint) -> (..#simd[LANES/N]T) where N >= 1, LANES % N == 0 --- // returns N multiple vectors + + // Checks if the current target supports the given target features. // // Takes a constant comma-seperated string (eg: "sha512,sse4.1"), or a procedure type which has either @@ -330,6 +388,9 @@ simd_lanes_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T --- has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) --- +// Utility Calls +concatenate :: proc(x, y: $T, z: ..T) -> T where type_is_array(T) || type_is_slice(T) --- + // Returns the value of the procedure where `x` must be a call expression procedure_of :: proc(x: $T) -> T where type_is_proc(T) --- @@ -353,22 +414,34 @@ x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) --- x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- +// C specific things +c_va_list :: struct{/*platform specific implementation*/} + +c_va_start :: proc(list: ^c_va_list, /*#c_vararg parameter*/ args: ..$T) --- +c_va_end :: proc(list: ^c_va_list) --- +c_va_copy :: proc(dst, src: ^c_va_list) --- +c_va_arg :: proc(list: ^c_va_list, $T: typeid) -> T --- + + // Darwin targets only objc_object :: struct{} objc_selector :: struct{} objc_class :: struct{} objc_ivar :: struct{} -objc_id :: ^objc_object -objc_SEL :: ^objc_selector -objc_Class :: ^objc_class -objc_Ivar :: ^objc_ivar +objc_id :: ^objc_object +objc_SEL :: ^objc_selector +objc_Class :: ^objc_class +objc_Ivar :: ^objc_ivar +objc_instancetype :: distinct objc_id objc_find_selector :: proc($name: string) -> objc_SEL --- objc_register_selector :: proc($name: string) -> objc_SEL --- objc_find_class :: proc($name: string) -> objc_Class --- objc_register_class :: proc($name: string) -> objc_Class --- objc_ivar_get :: proc(self: ^$T) -> ^$U --- +objc_block :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) --- +objc_super :: proc(obj: ^$T) -> ^$U where type_is_subtype_of(T, objc_object) && type_is_subtype_of(U, objc_object) --- valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr --- diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 1dadbbf6f..41d620bdd 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -15,7 +15,7 @@ // // IMPORTANT NOTE(bill): `type_info_of` cannot be used within a // #shared_global_scope due to the internals of the compiler. -// This could change at a later date if the all these data structures are +// This could change at a later date if all these data structures are // implemented within the compiler rather than in this "preload" file // #+no-instrumentation @@ -23,8 +23,27 @@ package runtime import "base:intrinsics" +/* +Fast_Math_Flag :: enum u8 { + Allow_Reassoc = 0, + No_NaNs = 1, + No_Infs = 2, + No_Signed_Zeros = 3, + Allow_Reciprocal = 4, + Allow_Contract = 5, + Approx_Func = 6, +} +*/ +Fast_Math_Flag :: intrinsics.Fast_Math_Flag + +// Fast_Math_Flags :: distinct bit_set[Fast_Math_Flag; u32] +Fast_Math_Flags :: intrinsics.Fast_Math_Flags + + // NOTE(bill): This must match the compiler's -Calling_Convention :: enum u8 { + +/* +enum u8 { Invalid = 0, Odin = 1, Contextless = 2, @@ -39,7 +58,13 @@ Calling_Convention :: enum u8 { Win64 = 9, SysV = 10, + + Preserve_None = 11, + Preserve_Most = 12, + Preserve_All = 13, } +*/ +Calling_Convention :: type_of(ODIN_DEFAULT_CALLING_CONVENTION) Type_Info_Enum_Value :: distinct i64 @@ -61,6 +86,11 @@ Type_Info_Struct_Soa_Kind :: enum u8 { Dynamic = 3, } +Type_Info_String_Encoding_Kind :: enum u8 { + UTF_8 = 0, + UTF_16 = 1, +} + // Variant Types Type_Info_Named :: struct { name: string, @@ -73,7 +103,7 @@ Type_Info_Rune :: struct {} Type_Info_Float :: struct {endianness: Platform_Endianness} Type_Info_Complex :: struct {} Type_Info_Quaternion :: struct {} -Type_Info_String :: struct {is_cstring: bool} +Type_Info_String :: struct {is_cstring: bool, encoding: Type_Info_String_Encoding_Kind} Type_Info_Boolean :: struct {} Type_Info_Any :: struct {} Type_Info_Type_Id :: struct {} @@ -113,10 +143,11 @@ Type_Info_Parameters :: struct { // Only used for procedures parameters and resu Type_Info_Struct_Flags :: distinct bit_set[Type_Info_Struct_Flag; u8] Type_Info_Struct_Flag :: enum u8 { - packed = 0, - raw_union = 1, - no_copy = 2, - align = 3, + packed = 0, + raw_union = 1, + all_or_none = 2, + align = 3, + simple = 4, } Type_Info_Struct :: struct { @@ -131,7 +162,7 @@ Type_Info_Struct :: struct { flags: Type_Info_Struct_Flags, - // These are only set iff this structure is an SOA structure + // These are only set if and only if (⟺) this structure is an SOA structure soa_kind: Type_Info_Struct_Soa_Kind, soa_len: i32, soa_base_type: ^Type_Info, @@ -160,10 +191,11 @@ Type_Info_Map :: struct { map_info: ^Map_Info, } Type_Info_Bit_Set :: struct { - elem: ^Type_Info, - underlying: ^Type_Info, // Possibly nil - lower: i64, - upper: i64, + elem: ^Type_Info, + underlying: ^Type_Info, + explicit_underlying: bool, // false = bit_set[T], true = bit_set[T, U] + lower: i64, + upper: i64, } Type_Info_Simd_Vector :: struct { elem: ^Type_Info, @@ -195,6 +227,14 @@ Type_Info_Bit_Field :: struct { field_count: int, } +Type_Info_Fixed_Capacity_Dynamic_Array :: struct { + elem: ^Type_Info, + elem_size: int, + capacity: int, + len_offset: uintptr, +} + + Type_Info_Flag :: enum u8 { Comparable = 0, Simple_Compare = 1, @@ -235,6 +275,7 @@ Type_Info :: struct { Type_Info_Matrix, Type_Info_Soa_Pointer, Type_Info_Bit_Field, + Type_Info_Fixed_Capacity_Dynamic_Array, }, } @@ -259,7 +300,79 @@ when ODIN_OS == .Windows { dll_instance: rawptr } -// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) + +// This is safe to change. The log2 size of a cache-line. At minimum it has to +// be six though. Higher cache line sizes are permitted. +MAP_CACHE_LINE_LOG2 :: 6 + +// The size of a cache-line. +MAP_CACHE_LINE_SIZE :: 1 << MAP_CACHE_LINE_LOG2 + +// The minimum cache-line size allowed by this implementation is 64 bytes since +// we need 6 bits in the base pointer to store the integer log2 capacity, which +// at maximum is 63. Odin uses signed integers to represent length and capacity, +// so only 63 bits are needed in the maximum case. +#assert(MAP_CACHE_LINE_SIZE >= 64) + +// Map_Cell type that packs multiple T in such a way to ensure that each T stays +// aligned by align_of(T) and such that align_of(Map_Cell(T)) % MAP_CACHE_LINE_SIZE == 0 +// +// This means a value of type T will never straddle a cache-line. +// +// When multiple Ts can fit in a single cache-line the data array will have more +// than one element. When it cannot, the data array will have one element and +// an array of Map_Cell(T) will be padded to stay a multiple of MAP_CACHE_LINE_SIZE. +// +// We rely on the type system to do all the arithmetic and padding for us here. +// +// The usual array[index] indexing for []T backed by a []Map_Cell(T) becomes a bit +// more involved as there now may be internal padding. The indexing now becomes +// +// N :: len(Map_Cell(T){}.data) +// i := index / N +// j := index % N +// cell[i].data[j] +// +// However, since len(Map_Cell(T){}.data) is a compile-time constant, there are some +// optimizations we can do to eliminate the need for any divisions as N will +// be bounded by [1, 64). +// +// In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated +// as a regular array of T, which is the case for hashes. +Map_Cell :: struct($T: typeid) #align(MAP_CACHE_LINE_SIZE) { + data: [MAP_CACHE_LINE_SIZE / size_of(T) when 0 < size_of(T) && size_of(T) < MAP_CACHE_LINE_SIZE else 1]T, +} + +// So we can operate on a cell data structure at runtime without any type +// information, we have a simple table that stores some traits about the cell. +// +// 32-bytes on 64-bit +// 16-bytes on 32-bit +Map_Cell_Info :: struct { + size_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits + align_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits + size_of_cell: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits + elements_per_cell: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits +} + +Map_Hash :: uintptr + +// When working with the type-erased structure at runtime we need information +// about the map to make working with it possible. This info structure stores +// that. +// +// `Map_Info` and `Map_Cell_Info` are read only data structures and cannot be +// modified after creation +// +// 32-bytes on 64-bit +// 16-bytes on 32-bit +Map_Info :: struct { + ks: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit + vs: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit + key_hasher: proc "contextless" (key: rawptr, seed: Map_Hash) -> Map_Hash, // 8-bytes on 64-bit, 4-bytes on 32-bit + key_equal: proc "contextless" (lhs, rhs: rawptr) -> bool, // 8-bytes on 64-bit, 4-bytes on 32-bit +} + Source_Code_Location :: struct { @@ -397,6 +510,11 @@ Raw_String :: struct { len: int, } +Raw_String16 :: struct { + data: [^]u16, + len: int, +} + Raw_Slice :: struct { data: rawptr, len: int, @@ -409,6 +527,11 @@ Raw_Dynamic_Array :: struct { allocator: Allocator, } +Raw_Fixed_Capacity_Dynamic_Array :: struct($Capacity: uint, $T: typeid) { + data: [Capacity]T, + len: int, +} + // The raw, type-erased representation of a map. // // 32-bytes on 64-bit @@ -450,6 +573,12 @@ Raw_Cstring :: struct { } #assert(size_of(Raw_Cstring) == size_of(cstring)) +Raw_Cstring16 :: struct { + data: [^]u16, +} +#assert(size_of(Raw_Cstring16) == size_of(cstring16)) + + Raw_Soa_Pointer :: struct { data: rawptr, index: int, @@ -473,11 +602,9 @@ Raw_Quaternion256_Vector_Scalar :: struct {vector: [3]f64, scalar: f64} Windows, Darwin, Linux, - Essence, FreeBSD, OpenBSD, NetBSD, - Haiku, WASI, JS, Orca, @@ -529,7 +656,6 @@ Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE) /* // Defined internally by the compiler Odin_Endian_Type :: enum int { - Unknown, Little, Big, } @@ -542,11 +668,9 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{ .Windows, .Darwin, .Linux, - .Essence, .FreeBSD, .OpenBSD, .NetBSD, - .Haiku, .WASI, .JS, .Orca, @@ -557,7 +681,8 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{ // Defined internally by the compiler Odin_Platform_Subtarget_Type :: enum int { Default, - iOS, + iPhone, + iPhoneSimulator Android, } */ @@ -565,6 +690,8 @@ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET) Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type] +@(builtin) +ODIN_PLATFORM_SUBTARGET_IOS :: ODIN_PLATFORM_SUBTARGET == .iPhone || ODIN_PLATFORM_SUBTARGET == .iPhoneSimulator /* // Defined internally by the compiler @@ -617,6 +744,8 @@ _cleanup_runtime_contextless :: proc "contextless" () { ///////////////////////////// +// type_info_base returns the base-type of a `^Type_Info` stripping the `distinct`ness from the first level +@(require_results) type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { if info == nil { return nil @@ -632,7 +761,10 @@ type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { return base } - +// type_info_core returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR +// returns the backing integer type of an enum `^Type_Info`. +// This is also aliased as `type_info_base_without_enum` +@(require_results) type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { if info == nil { return nil @@ -649,8 +781,36 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { } return base } + + + +// type_info_underlying returns the underlying (backing) type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR +// returns the backing integer type of an enum `^Type_Info` AND/OR the underlying integer type of a bit_set or bit_field. +@(require_results) +type_info_underlying :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { + if info == nil { + return nil + } + + base := info + loop: for { + #partial switch i in base.variant { + case Type_Info_Named: base = i.base + case Type_Info_Enum: base = i.base + case Type_Info_Bit_Set: base = i.underlying + case Type_Info_Bit_Field: base = i.backing_type + case: break loop + } + } + return base +} + +// `type_info_base_without_enum` returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR +// returns the backing integer type of an enum or bit_set `^Type_Info`. +// This is also aliased as `type_info_core` type_info_base_without_enum :: type_info_core +@(require_results) __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check { n := u64(len(type_table)) i := transmute(u64)id % n @@ -665,16 +825,32 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check } when !ODIN_NO_RTTI { + // typeid_base returns the base-type of a `typeid` stripping the `distinct`ness from the first level + @(require_results) typeid_base :: proc "contextless" (id: typeid) -> typeid { ti := type_info_of(id) ti = type_info_base(ti) return ti.id } + // typeid_core returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR + // returns the backing integer type of an enum `typeid`. + // This is also aliased as `typeid_base_without_enum` + @(require_results) typeid_core :: proc "contextless" (id: typeid) -> typeid { ti := type_info_core(type_info_of(id)) return ti.id } + + // typeid_base_without_enum returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR + // returns the backing integer type of an enum or bit_set `typeid`. + // This is also aliased as `typeid_core` typeid_base_without_enum :: typeid_core + + @(require_results) + typeid_underlying :: proc "contextless" (id: typeid) -> typeid { + ti := type_info_underlying(type_info_of(id)) + return ti.id + } } @@ -689,11 +865,15 @@ default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, opt // Nothing } +// Returns the default logger used by `context.logger` +@(require_results) default_logger :: proc() -> Logger { return Logger{default_logger_proc, nil, Logger_Level.Debug, nil} } +// Returns the default `context` +@(require_results) default_context :: proc "contextless" () -> Context { c: Context __init_context(&c) diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin index cf379aacb..8c522413f 100644 --- a/base/runtime/core_builtin.odin +++ b/base/runtime/core_builtin.odin @@ -2,9 +2,16 @@ package runtime import "base:intrinsics" +MAP_ENABLED :: !ODIN_BEDROCK + @builtin Maybe :: union($T: typeid) {T} +/* +Represents an Objective-C block with a given procedure signature T +*/ +@builtin +Objc_Block :: struct($T: typeid) where intrinsics.type_is_proc(T) { using _: intrinsics.objc_object } /* Recovers the containing/parent struct from a pointer to one of its fields. @@ -49,59 +56,79 @@ container_of :: #force_inline proc "contextless" (ptr: $P/^$Field_Type, $T: type when !NO_DEFAULT_TEMP_ALLOCATOR { - @thread_local global_default_temp_allocator_data: Default_Temp_Allocator + when ODIN_ARCH == .i386 && ODIN_OS == .Windows { + // Thread-local storage is problematic on Windows i386 + global_default_temp_allocator_data: Default_Temp_Allocator + } else { + @thread_local global_default_temp_allocator_data: Default_Temp_Allocator + } } +// Initializes the global temporary allocator used as the default `context.temp_allocator`. +// This is ignored when `NO_DEFAULT_TEMP_ALLOCATOR` is true. @(builtin, disabled=NO_DEFAULT_TEMP_ALLOCATOR) -init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) { +init_global_temporary_allocator :: proc "odin" (size: int, backup_allocator := context.allocator) { when !NO_DEFAULT_TEMP_ALLOCATOR { default_temp_allocator_init(&global_default_temp_allocator_data, size, backup_allocator) } } +@(require_results) +copy_slice_raw :: proc "contextless" (dst, src: rawptr, dst_len, src_len, elem_size: int) -> int { + n := min(dst_len, src_len) + if n > 0 { + intrinsics.mem_copy(dst, src, n*elem_size) + } + return n +} + // `copy_slice` is a built-in procedure that copies elements from a source slice `src` to a destination slice `dst`. // The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum // of len(src) and len(dst). // // Prefer the procedure group `copy`. @builtin -copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { - n := max(0, min(len(dst), len(src))) - if n > 0 { - intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(E)) - } - return n +copy_slice :: #force_inline proc "contextless" (dst, src: $T/[]$E) -> int { + return copy_slice_raw(raw_data(dst), raw_data(src), len(dst), len(src), size_of(E)) } + // `copy_from_string` is a built-in procedure that copies elements from a source string `src` to a destination slice `dst`. // The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum // of len(src) and len(dst). // // Prefer the procedure group `copy`. @builtin -copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int { - n := max(0, min(len(dst), len(src))) - if n > 0 { - intrinsics.mem_copy(raw_data(dst), raw_data(src), n) - } - return n +copy_from_string :: #force_inline proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int { + return copy_slice_raw(raw_data(dst), raw_data(src), len(dst), len(src), 1) } + +// `copy_from_string16` is a built-in procedure that copies elements from a source string `src` to a destination slice `dst`. +// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum +// of len(src) and len(dst). +// +// Prefer the procedure group `copy`. +@builtin +copy_from_string16 :: #force_inline proc "contextless" (dst: $T/[]$E/u16, src: $S/string16) -> int { + return copy_slice_raw(raw_data(dst), raw_data(src), len(dst), len(src), 2) +} + // `copy` is a built-in procedure that copies elements from a source slice/string `src` to a destination slice `dst`. // The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum // of len(src) and len(dst). @builtin -copy :: proc{copy_slice, copy_from_string} +copy :: proc{copy_slice, copy_from_string, copy_from_string16} -// `unordered_remove` removed the element at the specified `index`. It does so by replacing the current end value +// `unordered_remove_dynamic_array` removed the element at the specified `index`. It does so by replacing the current end value // with the old value, and reducing the length of the dynamic array by 1. // // Note: This is an O(1) operation. // Note: If you want the elements to remain in their order, use `ordered_remove`. // Note: If the index is out of bounds, this procedure will panic. @builtin -unordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check { +unordered_remove_dynamic_array :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check { bounds_check_error_loc(loc, index, len(array)) n := len(array)-1 if index != n { @@ -109,13 +136,13 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #ca } (^Raw_Dynamic_Array)(array).len -= 1 } -// `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements. +// `ordered_remove_dynamic_array` removed the element at the specified `index` whilst keeping the order of the other elements. // // Note: This is an O(N) operation. // Note: If the elements do not have to remain in their order, prefer `unordered_remove`. // Note: If the index is out of bounds, this procedure will panic. @builtin -ordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check { +ordered_remove_dynamic_array :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check { bounds_check_error_loc(loc, index, len(array)) if index+1 < len(array) { copy(array[index:], array[index+1:]) @@ -123,12 +150,12 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #call (^Raw_Dynamic_Array)(array).len -= 1 } -// `remove_range` removes a range of elements specified by the range `lo` and `hi`, whilst keeping the order of the other elements. +// `remove_range_dynamic_array` removes a range of elements specified by the range `lo` and `hi`, whilst keeping the order of the other elements. // // Note: This is an O(N) operation. // Note: If the range is out of bounds, this procedure will panic. @builtin -remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check { +remove_range_dynamic_array :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check { slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)) n := max(hi-lo, 0) if n > 0 { @@ -139,23 +166,117 @@ remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #calle } } +// `unordered_remove_fixed_capacity_dynamic_array` removed the element at the specified `index`. It does so by replacing the current end value +// with the old value, and reducing the length of the dynamic array by 1. +// +// Note: This is an O(1) operation. +// Note: If you want the elements to remain in their order, use `ordered_remove`. +// Note: If the index is out of bounds, this procedure will panic. +@builtin +unordered_remove_fixed_capacity_dynamic_array :: proc(array: ^$D/[dynamic; $N]$E, #any_int index: int, loc := #caller_location) #no_bounds_check { + bounds_check_error_loc(loc, index, len(array)) + n := len(array)-1 + if index != n { + array[index] = array[n] + } + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 +} +// `ordered_remove_fixed_capacity_dynamic_array` removed the element at the specified `index` whilst keeping the order of the other elements. +// +// Note: This is an O(N) operation. +// Note: If the elements do not have to remain in their order, prefer `unordered_remove`. +// Note: If the index is out of bounds, this procedure will panic. +@builtin +ordered_remove_fixed_capacity_dynamic_array :: proc(array: ^$D/[dynamic; $N]$E, #any_int index: int, loc := #caller_location) #no_bounds_check { + bounds_check_error_loc(loc, index, len(array)) + if index+1 < len(array) { + copy(array[index:], array[index+1:]) + } + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 +} + +// `remove_range_fixed_capacity_dynamic_array` removes a range of elements specified by the range `lo` and `hi`, whilst keeping the order of the other elements. +// +// Note: This is an O(N) operation. +// Note: If the range is out of bounds, this procedure will panic. +@builtin +remove_range_fixed_capacity_dynamic_array :: proc(array: ^$D/[dynamic; $N]$E, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check { + slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)) + n := max(hi-lo, 0) + if n > 0 { + if hi != len(array) { + copy(array[lo:], array[hi:]) + } + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= n + } +} + +@builtin +unordered_remove :: proc{ + unordered_remove_dynamic_array, + unordered_remove_fixed_capacity_dynamic_array, +} + + +@builtin +ordered_remove :: proc{ + ordered_remove_dynamic_array, + ordered_remove_fixed_capacity_dynamic_array, +} + +@builtin +remove_range :: proc{ + remove_range_dynamic_array, + remove_range_fixed_capacity_dynamic_array, +} + + + +// `pop_dynamic_array` will remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the dynamic array has no elements (`len(array) == 0`), this procedure will panic. +@builtin +pop_dynamic_array :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { + assert(len(array) > 0, loc=loc) + _pop_dynamic_array_type_erased(&res, (^Raw_Dynamic_Array)(array), size_of(E)) + return res +} + +_pop_dynamic_array_type_erased :: proc(res: rawptr, array: ^Raw_Dynamic_Array, elem_size: int) { + end := rawptr(uintptr(array.data) + uintptr(elem_size*(array.len-1))) + intrinsics.mem_copy_non_overlapping(res, end, elem_size) + array.len -= 1 +} + + +// `pop_fixed_capacity_dynamic_array` will remove and return the end value of fixed capacity dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the fixed capacity dynamic array has no elements (`len(array) == 0`), this procedure will panic. +@builtin +pop_fixed_capacity_dynamic_array :: proc(array: ^$T/[dynamic; $N]$E, loc := #caller_location) -> (res: E) #no_bounds_check { + assert(len(array) > 0, loc=loc) + + elem_size :: size_of(E) + end := rawptr(uintptr(array) + uintptr(elem_size*(len(array)-1))) + intrinsics.mem_copy_non_overlapping(&res, end, elem_size) + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 + return res +} + // `pop` will remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. // // Note: If the dynamic array has no elements (`len(array) == 0`), this procedure will panic. @builtin -pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { - assert(len(array) > 0, loc=loc) - res = array[len(array)-1] - (^Raw_Dynamic_Array)(array).len -= 1 - return res +pop :: proc{ + pop_dynamic_array, + pop_fixed_capacity_dynamic_array, } - -// `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// `pop_safe_dynamic_array` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. // If the operation is not possible, it will return false. @builtin -pop_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { +pop_safe_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { return } @@ -164,11 +285,32 @@ pop_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #n return } -// `pop_front` will remove and return the first value of dynamic array `array` and reduces the length of `array` by 1. +// `pop_safe_fixed_capacity_dynamic_array` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. +@builtin +pop_safe_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E) -> (res: E, ok: bool) #no_bounds_check { + if len(array) == 0 { + return + } + res, ok = array[len(array)-1], true + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 + return +} + +// `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. +@builtin +pop_safe :: proc{ + pop_safe_dynamic_array, + pop_safe_fixed_capacity_dynamic_array, +} + + +// `pop_front_dynamic_array` will remove and return the first value of dynamic array `array` and reduces the length of `array` by 1. // // Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic. @builtin -pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { +pop_front_dynamic_array :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { assert(len(array) > 0, loc=loc) res = array[0] if len(array) > 1 { @@ -178,10 +320,35 @@ pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) # return res } -// `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1. +// `pop_front_fixed_capacity_dynamic_array` will remove and return the first value of fixed capacity dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the fixed capacity dynamic array as no elements (`len(array) == 0`), this procedure will panic. +@builtin +pop_front_fixed_capacity_dynamic_array :: proc(array: ^$T/[dynamic; $N]$E, loc := #caller_location) -> (res: E) #no_bounds_check { + assert(len(array) > 0, loc=loc) + res = array[0] + if len(array) > 1 { + copy(array[0:], array[1:]) + } + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 + return res +} + + +// `pop_front` will remove and return the first value of dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic. +@builtin +pop_front :: proc{ + pop_front_dynamic_array, + pop_front_fixed_capacity_dynamic_array, +} + + +// `pop_front_safe_dynamic_array` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1. // If the operation is not possible, it will return false. @builtin -pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { +pop_front_safe_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { return } @@ -193,12 +360,37 @@ pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bo return } +// `pop_front_safe_fixed_capacity_dynamic_array` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. +@builtin +pop_front_safe_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E) -> (res: E, ok: bool) #no_bounds_check { + if len(array) == 0 { + return + } + res, ok = array[0], true + if len(array) > 1 { + copy(array[0:], array[1:]) + } + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len -= 1 + return +} + +// `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. +@builtin +pop_front_safe :: proc { + pop_front_safe_dynamic_array, + pop_front_safe_fixed_capacity_dynamic_array, +} + + // `clear` will set the length of a passed dynamic array or map to `0` @builtin clear :: proc{ clear_dynamic_array, - clear_map, + clear_map where MAP_ENABLED, + clear_fixed_capacity_dynamic_array, clear_soa_dynamic_array, } @@ -207,7 +399,7 @@ clear :: proc{ @builtin reserve :: proc{ reserve_dynamic_array, - reserve_map, + reserve_map where MAP_ENABLED, reserve_soa, } @@ -223,6 +415,7 @@ non_zero_reserve :: proc{ @builtin resize :: proc{ resize_dynamic_array, + resize_fixed_capacity_dynamic_array, resize_soa, } @@ -230,13 +423,17 @@ resize :: proc{ @builtin non_zero_resize :: proc{ non_zero_resize_dynamic_array, + non_zero_resize_fixed_capacity_dynamic_array, non_zero_resize_soa, } // Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity. @builtin -shrink :: proc{shrink_dynamic_array, shrink_map} +shrink :: proc{ + shrink_dynamic_array, + shrink_map where MAP_ENABLED, +} // `free` will try to free the passed pointer, with the given `allocator` if the allocator supports this operation. @builtin @@ -276,14 +473,25 @@ delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { return mem_free_with_size(raw_data(array), len(array)*size_of(E), allocator, loc) } -// `delete_map` will try to free the underlying data of the passed map, with the given `allocator` if the allocator supports this operation. -// -// Note: Prefer the procedure group `delete`. + @builtin -delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { - return map_free_dynamic(transmute(Raw_Map)m, map_info(T), loc) +delete_string16 :: proc(str: string16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + return mem_free_with_size(raw_data(str), len(str)*size_of(u16), allocator, loc) +} +@builtin +delete_cstring16 :: proc(str: cstring16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + return mem_free((^u16)(str), allocator, loc) } +when MAP_ENABLED { + // `delete_map` will try to free the underlying data of the passed map, with the given `allocator` if the allocator supports this operation. + // + // Note: Prefer the procedure group `delete`. + @builtin + delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { + return map_free_dynamic(transmute(Raw_Map)m, map_info(T), loc) + } +} // `delete` will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given `allocator` if the allocator supports this operation. // @@ -294,29 +502,30 @@ delete :: proc{ delete_cstring, delete_dynamic_array, delete_slice, - delete_map, + delete_map where MAP_ENABLED, delete_soa_slice, delete_soa_dynamic_array, + delete_string16, + delete_cstring16, } // The new built-in procedure allocates memory. The first argument is a type, not a value, and the value // return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator @(builtin, require_results) -new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_allocator_error { - return new_aligned(T, align_of(T), allocator, loc) +new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_allocator_error { + t = (^T)(raw_data(mem_alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return)) + return } -@(require_results) +@(builtin, require_results) new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) { - data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return - t = (^T)(raw_data(data)) + t = (^T)(raw_data(mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return)) return } @(builtin, require_results) new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_allocator_error { - t_data := mem_alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return - t = (^T)(raw_data(t_data)) + t = (^T)(raw_data(mem_alloc_non_zeroed(size_of(T), align_of(T), allocator, loc) or_return)) if t != nil { t^ = data } @@ -325,15 +534,22 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat DEFAULT_DYNAMIC_ARRAY_CAPACITY :: 8 +@(builtin, require_results) +make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (res: T, err: Allocator_Error) #optional_allocator_error { + err = _make_aligned_type_erased(&res, size_of(E), len, alignment, allocator, loc) + return +} + @(require_results) -make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { +_make_aligned_type_erased :: proc(slice: rawptr, elem_size: int, len: int, alignment: int, allocator: Allocator, loc := #caller_location) -> Allocator_Error { make_slice_error_loc(loc, len) - data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc) - if data == nil && size_of(E) != 0 { - return nil, err + data, err := mem_alloc_bytes(elem_size*len, alignment, allocator, loc) + if data == nil && elem_size != 0 { + return err } - s := Raw_Slice{raw_data(data), len} - return transmute(T)s, err + (^Raw_Slice)(slice).data = raw_data(data) + (^Raw_Slice)(slice).len = len + return err } // `make_slice` allocates and initializes a slice. Like `new`, the first argument is a type, not a value. @@ -341,24 +557,27 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat // // Note: Prefer using the procedure group `make`. @(builtin, require_results) -make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { - return make_aligned(T, len, align_of(E), allocator, loc) +make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (res: T, err: Allocator_Error) #optional_allocator_error { + err = _make_aligned_type_erased(&res, size_of(E), len, align_of(E), allocator, loc) + return } // `make_dynamic_array` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. // // Note: Prefer using the procedure group `make`. @(builtin, require_results) -make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { - return make_dynamic_array_len_cap(T, 0, 0, allocator, loc) +make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { + err = _make_dynamic_array_len_cap((^Raw_Dynamic_Array)(&array), size_of(E), align_of(E), 0, 0, allocator, loc) + return } // `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. // // Note: Prefer using the procedure group `make`. @(builtin, require_results) -make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { - return make_dynamic_array_len_cap(T, len, len, allocator, loc) +make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { + err = _make_dynamic_array_len_cap((^Raw_Dynamic_Array)(&array), size_of(E), align_of(E), len, len, allocator, loc) + return } // `make_dynamic_array_len_cap` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. @@ -379,33 +598,35 @@ _make_dynamic_array_len_cap :: proc(array: ^Raw_Dynamic_Array, size_of_elem, ali array.data = raw_data(data) array.len = 0 if use_zero else len array.cap = 0 if use_zero else cap - array.allocator = allocator return } -// `make_map` initializes a map with an allocator. Like `new`, the first argument is a type, not a value. -// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. -// -// Note: Prefer using the procedure group `make`. -@(builtin, require_results) -make_map :: proc($T: typeid/map[$K]$E, allocator := context.allocator, loc := #caller_location) -> (m: T) { - m.allocator = allocator - return m +when MAP_ENABLED { + // `make_map` initializes a map with an allocator. Like `new`, the first argument is a type, not a value. + // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. + // + // Note: Prefer using the procedure group `make`. + @(builtin, require_results) + make_map :: proc($T: typeid/map[$K]$E, allocator := context.allocator, loc := #caller_location) -> (m: T) { + m.allocator = allocator + return m + } + + // `make_map_cap` initializes a map with an allocator and allocates space using `capacity`. + // Like `new`, the first argument is a type, not a value. + // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. + // + // Note: Prefer using the procedure group `make`. + @(builtin, require_results) + make_map_cap :: proc($T: typeid/map[$K]$E, #any_int capacity: int, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error { + make_map_expr_error_loc(loc, capacity) + context.allocator = allocator + + err = reserve_map(&m, capacity, loc) + return + } } -// `make_map_cap` initializes a map with an allocator and allocates space using `capacity`. -// Like `new`, the first argument is a type, not a value. -// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. -// -// Note: Prefer using the procedure group `make`. -@(builtin, require_results) -make_map_cap :: proc($T: typeid/map[$K]$E, #any_int capacity: int, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error { - make_map_expr_error_loc(loc, capacity) - context.allocator = allocator - - err = reserve_map(&m, capacity, loc) - return -} // `make_multi_pointer` allocates and initializes a multi-pointer. Like `new`, the first argument is a type, not a value. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. // @@ -435,8 +656,8 @@ make :: proc{ make_dynamic_array, make_dynamic_array_len, make_dynamic_array_len_cap, - make_map, - make_map_cap, + make_map where MAP_ENABLED, + make_map_cap where MAP_ENABLED, make_multi_pointer, make_soa_slice, @@ -445,64 +666,67 @@ make :: proc{ make_soa_dynamic_array_len_cap, } +when MAP_ENABLED { + // `clear_map` will set the length of a passed map to `0` + // + // Note: Prefer the procedure group `clear` + @builtin + clear_map :: proc "contextless" (m: ^$T/map[$K]$V) { + if m == nil { + return + } + map_clear_dynamic((^Raw_Map)(m), map_info(T)) + } -// `clear_map` will set the length of a passed map to `0` -// -// Note: Prefer the procedure group `clear` -@builtin -clear_map :: proc "contextless" (m: ^$T/map[$K]$V) { - if m == nil { + // `reserve_map` will try to reserve memory of a passed map to the requested element count (setting the `cap`). + // + // Note: Prefer the procedure group `reserve` + @builtin + reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error { + return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) + } + + // Shrinks the capacity of a map down to the current length. + // + // Note: Prefer the procedure group `shrink` + @builtin + shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { + if m != nil { + return map_shrink_dynamic((^Raw_Map)(m), map_info(T), loc) + } return } - map_clear_dynamic((^Raw_Map)(m), map_info(T)) -} -// `reserve_map` will try to reserve memory of a passed map to the requested element count (setting the `cap`). -// -// Note: Prefer the procedure group `reserve` -@builtin -reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error { - return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil -} - -// Shrinks the capacity of a map down to the current length. -// -// Note: Prefer the procedure group `shrink` -@builtin -shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { - if m != nil { - return map_shrink_dynamic((^Raw_Map)(m), map_info(T), loc) - } - return -} - -// The delete_key built-in procedure deletes the element with the specified key (m[key]) from the map. -// If m is nil, or there is no such element, this procedure is a no-op -@builtin -delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: V) { - if m != nil { - key := key - old_k, old_v, ok := map_erase_dynamic((^Raw_Map)(m), map_info(T), uintptr(&key)) - if ok { - deleted_key = (^K)(old_k)^ - deleted_value = (^V)(old_v)^ + // The delete_key built-in procedure deletes the element with the specified key (m[key]) from the map. + // If m is nil, or there is no such element, this procedure is a no-op + // It is safe to use `delete_key` while iterating a map. + // But if you iterate across a map and insert a new key, it could resize which means you are not iterating across all of the elements. + @builtin + delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: V) { + if m != nil { + key := key + old_k, old_v, ok := map_erase_dynamic((^Raw_Map)(m), map_info(T), uintptr(&key)) + if ok { + deleted_key = (^K)(old_k)^ + deleted_value = (^V)(old_v)^ + } } + return } - return } -_append_elem :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, arg_ptr: rawptr, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +_append_elem :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, arg_ptr: rawptr, should_zero: bool, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return } if array.cap < array.len+1 { // Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY. - cap := 2 * array.cap + DEFAULT_DYNAMIC_ARRAY_CAPACITY + cap := max(2 * array.cap, DEFAULT_DYNAMIC_ARRAY_CAPACITY) // do not 'or_return' here as it could be a partial success - err = _reserve_dynamic_array(array, size_of_elem, align_of_elem, cap, should_zero, loc) + err = _reserve_dynamic_array_unsafe(array, size_of_elem, align_of_elem, cap, should_zero, loc) } if array.cap-array.len > 0 { data := ([^]byte)(array.data) @@ -510,34 +734,114 @@ _append_elem :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, alig data = data[array.len*size_of_elem:] intrinsics.mem_copy_non_overlapping(data, arg_ptr, size_of_elem) array.len += 1 - n = 1 + num_appended = 1 } return } +_append_elem_ptr :: #force_no_inline proc(array: ^Raw_Dynamic_Array, arg: rawptr, should_zero: bool, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { + if array == nil { + return + } + + if array.cap < array.len+1 { + // Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY. + cap := max(2 * array.cap, DEFAULT_DYNAMIC_ARRAY_CAPACITY) + + // do not 'or_return' here as it could be a partial success + err = _reserve_dynamic_array_unsafe(array, size_of(rawptr), align_of(rawptr), cap, should_zero, loc) + } + if array.cap-array.len > 0 { + data := ([^]rawptr)(array.data) + assert(data != nil, loc=loc) + data[array.len] = arg + array.len += 1 + num_appended = 1 + } + return +} + + +// `append_elem` appends an element to the end of a dynamic array. @builtin -append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { when size_of(E) == 0 { + if array == nil { + return + } (^Raw_Dynamic_Array)(array).len += 1 return 1, nil - } else { + } else when intrinsics.type_is_internally_pointer_like(E) { + return _append_elem_ptr((^Raw_Dynamic_Array)(array), rawptr(arg), should_zero=true, loc=loc) + } else when ODIN_OPTIMIZATION_MODE <= .Size { arg := arg - return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, true, loc=loc) + return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, should_zero=true, loc=loc) + } else { + if array == nil { + return + } + arg := arg + arr := (^Raw_Dynamic_Array)(array) + if arr.cap < arr.len+1 { + // Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY. + cap := max(2 * arr.cap, DEFAULT_DYNAMIC_ARRAY_CAPACITY) + + // do not 'or_return' here as it could be a partial success + err = _reserve_dynamic_array_unsafe(arr, size_of(E), align_of(E), cap, should_zero=true, loc=loc) + } + if arr.cap-arr.len > 0 { + // NOTE(bill, 2026-06-19): When this is in the hot path with -o:speed or -o:aggressive enabled, + // this code path cannot rely on type erasure and `mem_copy_non_overlapping`. + // So directly inlining the call and storing the argument like this helps the optimize a lot + assert(arr.data != nil, loc=loc) + ([^]E)(arr.data)[arr.len] = arg + arr.len += 1 + num_appended = 1 + } + return } } +// `non_zero_append_elem` appends an element to the end of a dynamic array, without zeroing any reserved memory +// +// Note: Prefer using the procedure group `non_zero_append @builtin -non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { when size_of(E) == 0 { (^Raw_Dynamic_Array)(array).len += 1 return 1, nil - } else { + } else when intrinsics.type_is_internally_pointer_like(E) { + return _append_elem_ptr((^Raw_Dynamic_Array)(array), rawptr(arg), should_zero=false, loc=loc) + } else when ODIN_OPTIMIZATION_MODE <= .Size { arg := arg - return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, false, loc=loc) + return _append_elem((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), &arg, should_zero=false, loc=loc) + } else { + if array == nil { + return + } + arg := arg + arr := (^Raw_Dynamic_Array)(array) + if arr.cap < arr.len+1 { + // Same behavior as _append_elems but there's only one arg, so we always just add DEFAULT_DYNAMIC_ARRAY_CAPACITY. + cap := max(2 * arr.cap, DEFAULT_DYNAMIC_ARRAY_CAPACITY) + + // do not 'or_return' here as it could be a partial success + err = _reserve_dynamic_array_unsafe(arr, size_of(E), align_of(E), cap, should_zero=false, loc=loc) + } + if arr.cap-arr.len > 0 { + // NOTE(bill, 2026-06-19): When this is in the hot path with -o:speed or -o:aggressive enabled, + // this code path cannot rely on type erasure and `mem_copy_non_overlapping`. + // So directly inlining the call and storing the argument like this helps the optimize a lot + assert(arr.data != nil, loc=loc) + ([^]E)(arr.data)[arr.len] = arg + arr.len += 1 + num_appended = 1 + } + return } } -_append_elems :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, should_zero: bool, loc := #caller_location, args: rawptr, arg_len: int) -> (n: int, err: Allocator_Error) #optional_allocator_error { +_append_elems :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, should_zero: bool, loc := #caller_location, args: rawptr, arg_len: int) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return 0, nil } @@ -564,8 +868,11 @@ _append_elems :: #force_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, ali return arg_len, err } +// `append_elems` appends `args` to the end of a dynamic array. +// +// Note: Prefer using the procedure group `append`. @builtin -append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { when size_of(E) == 0 { a := (^Raw_Dynamic_Array)(array) a.len += len(args) @@ -575,8 +882,11 @@ append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #ca } } +// `non_zero_append_elems` appends `args` to the end of a dynamic array, without zeroing any reserved memory +// +// Note: Prefer using the procedure group `non_zero_append @builtin -non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { when size_of(E) == 0 { a := (^Raw_Dynamic_Array)(array) a.len += len(args) @@ -587,27 +897,44 @@ non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, l } // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type -_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_zero: bool, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { return _append_elems((^Raw_Dynamic_Array)(array), 1, 1, should_zero, loc, raw_data(arg), len(arg)) } +// `append_elem_string` appends a string to the end of a dynamic array of bytes +// +// Note: Prefer using the procedure group `append`. @builtin -append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { return _append_elem_string(array, arg, true, loc) } +// `non_zero_append_elem_string` appends a string to the end of a dynamic array of bytes, without zeroing any reserved memory +// +// Note: Prefer using the procedure group `non_zero_append`. @builtin -non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { return _append_elem_string(array, arg, false, loc) } +// `non_zero_append_elem_fixed_capacity_string` appends a string to the end of a dynamic array of bytes, without zeroing any reserved memory +// +// Note: Prefer using the procedure group `non_zero_append`. +@builtin +non_zero_append_elem_fixed_capacity_string :: proc "contextless" (array: ^$T/[dynamic; $N]$E/u8, arg: $A/string) -> (num_appended: int) { + return append_fixed_capacity_elem(array, transmute([]byte)arg) +} + + // The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type +// +// Note: Prefer using the procedure group `append`. @builtin -append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (num_appended: int, err: Allocator_Error) #optional_allocator_error { n_arg: int for arg in args { n_arg, err = append(array, ..transmute([]E)(arg), loc=loc) - n += n_arg + num_appended += n_arg if err != nil { return } @@ -615,28 +942,91 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_ return } + +// `append_fixed_capacity_elem` appends an element to the end of a fixed capacity dynamic array. Returns 0 on failure +@builtin +append_fixed_capacity_elem :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #no_broadcast arg: E) -> (num_appended: int) { + Raw :: Raw_Fixed_Capacity_Dynamic_Array(N, E) + + if (^Raw)(array).len >= N { + return 0 + } + + when size_of(E) != 0 { + #no_bounds_check (^Raw)(array).data[(^Raw)(array).len] = arg + } + (^Raw)(array).len += 1 + return 1 +} + + +// `append_fixed_capacity_elem` appends an element to the end of a fixed capacity dynamic array. Returns 0 on failure +@builtin +append_fixed_capacity_elems :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #no_broadcast args: ..E) -> (num_appended: int) { + Raw :: Raw_Fixed_Capacity_Dynamic_Array(N, E) + raw := (^Raw)(array) + + num_appended = min(N - len(array), len(args)) + + #no_bounds_check when size_of(E) != 0 { + intrinsics.mem_copy(&raw.data[raw.len], raw_data(args), num_appended*size_of(E)) + } + + raw.len += num_appended + return num_appended +} + +// The append_fixed_capacity_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type +// +// Note: Prefer using the procedure group `append`. +@builtin +append_fixed_capacity_string :: proc "contextless" (array: ^$T/[dynamic; $N]$E/u8, args: ..string) -> (num_appended: int) { + n_arg: int + for arg in args { + n_arg = append_fixed_capacity_elems(array, ..transmute([]E)(arg)) + num_appended += n_arg + if n_arg < len(arg) { + return + } + } + return +} + + // The append built-in procedure appends elements to the end of a dynamic array -@builtin append :: proc{ +@builtin +append :: proc{ append_elem, append_elems, append_elem_string, + append_fixed_capacity_elem, + append_fixed_capacity_elems, + append_fixed_capacity_string, + append_soa_elem, append_soa_elems, } -@builtin non_zero_append :: proc{ +@builtin +non_zero_append :: proc{ non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string, + append_fixed_capacity_elem, + append_fixed_capacity_elems, + non_zero_append_elem_fixed_capacity_string, + non_zero_append_soa_elem, non_zero_append_soa_elems, } +// `append_nothing` appends an empty value to a dynamic array. It returns `1, nil` if successful, and `0, err` when it was not possible, +// whatever `err` happens to be. @builtin -append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { +append_nothing_dynamic_array :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error { if array == nil { return 0, nil } @@ -645,9 +1035,34 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i return len(array)-prev_len, nil } +// `append_nothing` appends an empty value to a dynamic array. It returns `1, nil` if successful, and `0, err` when it was not possible, +// whatever `err` happens to be. +@builtin +append_nothing_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E) -> (n: int, ok: bool) { + if array == nil { + return 0, true + } + prev_len := len(array) + resize_fixed_capacity_dynamic_array(array, len(array)+1) or_return + return len(array)-prev_len, true +} + +// `append_nothing` appends an empty value to a dynamic array. It returns `1, nil` if successful, and `0, err` when it was not possible, +// whatever `err` happens to be. +@builtin +append_nothing :: proc{ + append_nothing_dynamic_array, + append_nothing_fixed_capacity_dynamic_array, +} + + +// `inject_at_elem` injects an element in a dynamic array at a specified index and moves the previous elements after that index "across" @builtin inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } if array == nil { return } @@ -664,8 +1079,12 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcas return } +// `inject_at_elems` injects multiple elements in a dynamic array at a specified index and moves the previous elements after that index "across" @builtin inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } if array == nil { return } @@ -687,8 +1106,12 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca return } +// `inject_at_elem_string` injects a string into a dynamic array at a specified index and moves the previous elements after that index "across" @builtin inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } if array == nil { return } @@ -708,10 +1131,93 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar return } -@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string} + +// `inject_at_elem_fixed_capacity_dynamic_array` injects an element in a dynamic array at a specified index and moves the previous elements after that index "across" +@builtin +inject_at_elem_fixed_capacity_dynamic_array :: proc(array: ^$T/[dynamic; $N]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } + if array == nil { + return false + } + n := max(len(array), index) + m :: 1 + new_size := n + m + + resize(array, new_size) or_return + when size_of(E) != 0 { + copy(array[index + m:], array[index:]) + array[index] = arg + } + return true +} + +// `inject_at_elems_fixed_capacity_dynamic_array` injects multiple elements in a dynamic array at a specified index and moves the previous elements after that index "across" +@builtin +inject_at_elems_fixed_capacity_dynamic_array :: proc(array: ^$T/[dynamic; $N]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } + if array == nil { + return false + } + if len(args) == 0 { + return true + } + + n := max(len(array), index) + m := len(args) + new_size := n + m + + resize(array, new_size) or_return + when size_of(E) != 0 { + copy(array[index + m:], array[index:]) + copy(array[index:], args) + } + return true +} + +// `inject_at_elem_string_fixed_capacity_dynamic_array` injects a string into a dynamic array at a specified index and moves the previous elements after that index "across" +@builtin +inject_at_elem_string_fixed_capacity_dynamic_array :: proc(array: ^$T/[dynamic; $N]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } + if array == nil { + return false + } + if len(arg) == 0 { + return true + } + + n := max(len(array), index) + m := len(arg) + new_size := n + m + + resize(array, new_size) or_return + copy(array[index+m:], array[index:]) + copy(array[index:], arg) + return true +} + + +// `inject_at` injects something into a dynamic array at a specified index and moves the previous elements after that index "across" +@builtin +inject_at :: proc{ + inject_at_elem, + inject_at_elems, + inject_at_elem_string, + + inject_at_elem_fixed_capacity_dynamic_array, + inject_at_elems_fixed_capacity_dynamic_array, + inject_at_elem_string_fixed_capacity_dynamic_array, +} +// `assign_at_elem` assigns a value at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+1` and then assign as `index`. @builtin assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { if index < len(array) { @@ -726,6 +1232,8 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc } +// `assign_at_elems` assigns a values at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(args)` and then assign as `index`. @builtin assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { new_size := index + len(args) @@ -742,7 +1250,8 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca return } - +// `assign_at_elem_string` assigns a string at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(arg)` and then assign as `index`. @builtin assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { new_size := index + len(arg) @@ -759,8 +1268,72 @@ assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar return } -@builtin assign_at :: proc{assign_at_elem, assign_at_elems, assign_at_elem_string} +// `assign_at_elem_fixed_capacity_dynamic_array` assigns a value at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+1` and then assign as `index`. +@builtin +assign_at_elem_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #any_int index: int, arg: E) -> (ok: bool) #no_bounds_check { + if index < len(array) { + array[index] = arg + ok = true + } else { + resize(array, index+1, loc) or_return + array[index] = arg + ok = true + } + return +} + + +// `assign_at_elems_fixed_capacity_dynamic_array` assigns a values at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(args)` and then assign as `index`. +@builtin +assign_at_elems_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #any_int index: int, #no_broadcast args: ..E) -> (ok: bool) #no_bounds_check { + new_size := index + len(args) + if len(args) == 0 { + ok = true + } else if new_size < len(array) { + copy(array[index:], args) + ok = true + } else { + resize(array, new_size, loc) or_return + copy(array[index:], args) + ok = true + } + return +} + +// `assign_at_elem_string_fixed_capacity_dynamic_array` assigns a string at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(arg)` and then assign as `index`. +@builtin +assign_at_elem_string_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E/u8, #any_int index: int, arg: string) -> (ok: bool) #no_bounds_check { + new_size := index + len(arg) + if len(arg) == 0 { + ok = true + } else if new_size < len(array) { + copy(array[index:], arg) + ok = true + } else { + resize(array, new_size, loc) or_return + copy(array[index:], arg) + ok = true + } + return +} + + +// `assign_at` assigns a value at a given index. If the requested index is past the end of the current +// size of the dynamic array, it will attempt to `resize` the a new length of `index+size_needed` and then assign as `index`. +@builtin +assign_at :: proc{ + assign_at_elem, + assign_at_elems, + assign_at_elem_string, + + assign_at_elem_fixed_capacity_dynamic_array, + assign_at_elems_fixed_capacity_dynamic_array, + assign_at_elem_string_fixed_capacity_dynamic_array, +} @@ -774,10 +1347,22 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) { } } +// `clear_fixed_capacity_dynamic_array` will set the length of a passed dynamic array to `0` +// +// Note: Prefer the procedure group `clear`. +@builtin +clear_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E) { + if array != nil { + (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array).len = 0 + } +} + // `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). // +// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`). +// // Note: Prefer the procedure group `reserve`. -_reserve_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { +_reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { if a == nil { return nil } @@ -788,8 +1373,8 @@ _reserve_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem if a.allocator.procedure == nil { a.allocator = context.allocator + assert(a.allocator.procedure != nil) } - assert(a.allocator.procedure != nil) old_size := a.cap * size_of_elem new_size := capacity * size_of_elem @@ -810,18 +1395,57 @@ _reserve_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem return nil } +_reserve_dynamic_array_unsafe :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { + if capacity <= a.cap { + return nil + } + + if a.allocator.procedure == nil { + a.allocator = context.allocator + assert(a.allocator.procedure != nil) + } + + old_size := a.cap * size_of_elem + new_size := capacity * size_of_elem + allocator := a.allocator + + new_data: []byte + if should_zero { + new_data = mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return + } else { + new_data = non_zero_mem_resize(a.data, old_size, new_size, align_of_elem, allocator, loc) or_return + } + if new_data == nil && new_size > 0 { + return .Out_Of_Memory + } + + a.data = raw_data(new_data) + a.cap = capacity + return nil +} + +// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). +// +// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`). +// +// Note: Prefer the procedure group `reserve`. @builtin reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error { return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, true, loc) } +// `non_zero_reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). +// +// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`). +// +// Note: Prefer the procedure group `non_zero_reserve`. @builtin non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error { return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, false, loc) } -_resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { +_resize_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, length: int, should_zero: bool, loc := #caller_location) -> Allocator_Error { if a == nil { return nil } @@ -838,8 +1462,8 @@ _resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, if a.allocator.procedure == nil { a.allocator = context.allocator + assert(a.allocator.procedure != nil) } - assert(a.allocator.procedure != nil) old_size := a.cap * size_of_elem new_size := length * size_of_elem @@ -863,28 +1487,71 @@ _resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, // `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). // +// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`). +// // Note: Prefer the procedure group `resize` @builtin resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error { return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, true, loc=loc) } +// `non_zero_resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). +// +// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`). +// +// Note: Prefer the procedure group `non_zero_resize` @builtin non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error { return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, false, loc=loc) } -/* - Shrinks the capacity of a dynamic array down to the current length, or the given capacity. - If `new_cap` is negative, then `len(array)` is used. - Returns false if `cap(array) < new_cap`, or the allocator report failure. +// `resize_fixed_capacity_dynamic_array` will try to resize memory of a passed fixed capacity dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). +// +// Note: Prefer the procedure group `resize` +@builtin +resize_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #any_int length: int) -> bool { + if array == nil { + return false + } + if len(array) < length { + size_of_elem :: size_of(E) - If `len(array) < new_cap`, then `len(array)` will be left unchanged. + num_reused := min(N, length) - len(array) + intrinsics.mem_zero(([^]byte)(array)[len(array)*size_of_elem:], num_reused*size_of_elem) + } - Note: Prefer the procedure group `shrink` -*/ + raw := (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array) + new_length := clamp(length, 0, N) + raw.len = new_length + return true +} + +// `non_zero_resize_fixed_capacity_dynamic_array` will try to resize memory of a passed fixed capacity dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). +// +// Note: Prefer the procedure group `resize` +@builtin +non_zero_resize_fixed_capacity_dynamic_array :: proc "contextless" (array: ^$T/[dynamic; $N]$E, #any_int length: int) -> bool { + if array == nil { + return false + } + raw := (^Raw_Fixed_Capacity_Dynamic_Array(N, E))(array) + new_length := clamp(length, 0, N) + raw.len = new_length + return true +} + +// Shrinks the capacity of a dynamic array down to the current length, or the given capacity. +// +// If `new_cap` is negative, then `len(array)` is used. +// +// Returns false if `cap(array) < new_cap`, or the allocator report failure. +// +// If `len(array) < new_cap`, then `len(array)` will be left unchanged. +// +// Note: Prefer the procedure group `shrink` +@builtin shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc) } @@ -902,8 +1569,8 @@ _shrink_dynamic_array :: proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem if a.allocator.procedure == nil { a.allocator = context.allocator + assert(a.allocator.procedure != nil) } - assert(a.allocator.procedure != nil) old_size := a.cap * size_of_elem new_size := new_cap * size_of_elem @@ -916,55 +1583,58 @@ _shrink_dynamic_array :: proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem return true, nil } -@builtin -map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) { - key, value := key, value - return (^V)(__dynamic_map_set_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc)) -} - -// Explicitly inserts a key and value into a map `m`, the same as `map_insert`, but the return values differ. -// - `prev_key` will return the previous pointer of a key if it exists, check `found_previous` if was previously found -// - `value_ptr` will return the pointer of the memory where the insertion happens, and `nil` if the map failed to resize -// - `found_previous` will be true a previous key was found -@(builtin, require_results) -map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (prev_key: K, value_ptr: ^V, found_previous: bool) { - key, value := key, value - kp, vp := __dynamic_map_set_extra_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc) - if kp != nil { - prev_key = (^K)(kp)^ - found_previous = true +when MAP_ENABLED { + @builtin + map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) { + key, value := key, value + return (^V)(__dynamic_map_set_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc)) } - value_ptr = (^V)(vp) - return -} -/* -Retrieves a pointer to the key and value for a possibly just inserted entry into the map. + // Explicitly inserts a key and value into a map `m`, the same as `map_insert`, but the return values differ. + // - `prev_key` will return the previous pointer of a key if it exists, check `found_previous` if was previously found + // - `value_ptr` will return the pointer of the memory where the insertion happens, and `nil` if the map failed to resize + // - `found_previous` will be true a previous key was found + @(builtin, require_results) + map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (prev_key: K, value_ptr: ^V, found_previous: bool) { + key, value := key, value + kp, vp := __dynamic_map_set_extra_without_hash((^Raw_Map)(m), map_info(T), rawptr(&key), rawptr(&value), loc) + if kp != nil { + prev_key = (^K)(kp)^ + found_previous = true + } + value_ptr = (^V)(vp) + return + } -If the `key` was not in the map `m`, an entry is inserted with the zero value and `just_inserted` will be `true`. -Otherwise the existing entry is left untouched and pointers to its key and value are returned. + /* + Retrieves a pointer to the key and value for a possibly just inserted entry into the map. -If the map has to grow in order to insert the entry and the allocation fails, `err` is set and returned. + If the `key` was not in the map `m`, an entry is inserted with the zero value and `just_inserted` will be `true`. + Otherwise the existing entry is left untouched and pointers to its key and value are returned. -If `err` is `nil`, `key_ptr` and `value_ptr` are valid pointers and will not be `nil`. + If the map has to grow in order to insert the entry and the allocation fails, `err` is set and returned. -WARN: User modification of the key pointed at by `key_ptr` should only be done if the new key is equal to (in hash) the old key. -If that is not the case you will corrupt the map. -*/ -@(builtin, require_results) -map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr: ^K, value_ptr: ^V, just_inserted: bool, err: Allocator_Error) { - key := key - zero: V + If `err` is `nil`, `key_ptr` and `value_ptr` are valid pointers and will not be `nil`. - _key_ptr, _value_ptr: rawptr - _key_ptr, _value_ptr, just_inserted, err = __dynamic_map_entry((^Raw_Map)(m), map_info(T), &key, &zero, loc) + WARN: User modification of the key pointed at by `key_ptr` should only be done if the new key is equal to (in hash) the old key. + If that is not the case you will corrupt the map. + */ + @(builtin, require_results) + map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr: ^K, value_ptr: ^V, just_inserted: bool, err: Allocator_Error) { + key := key + zero: V - key_ptr = (^K)(_key_ptr) - value_ptr = (^V)(_value_ptr) - return + _key_ptr, _value_ptr: rawptr + _key_ptr, _value_ptr, just_inserted, err = __dynamic_map_entry((^Raw_Map)(m), map_info(T), &key, &zero, loc) + + key_ptr = (^K)(_key_ptr) + value_ptr = (^V)(_value_ptr) + return + } } +// `card` returns the number of bits that are set in a bit_set—its cardinality @builtin card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int { return int(intrinsics.count_ones(transmute(intrinsics.type_bit_set_underlying_type(S))s)) @@ -972,6 +1642,10 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int { +// Evaluates the condition and panics the program if and only if (⟺) the condition is false. +// This uses the `context.assertion_failure_procedure` to assert. +// +// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true. @builtin @(disabled=ODIN_DISABLE_ASSERT) assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) { @@ -992,9 +1666,9 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc := } } -// Evaluates the condition and aborts the program iff the condition is -// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always -// execute. +// Evaluates the condition and panics the program if and only if (⟺) the condition is false. +// This uses the `context.assertion_failure_procedure` to assert. +// This routine ignores `ODIN_DISABLE_ASSERT`, and will always execute. @builtin ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) { if !condition { @@ -1010,6 +1684,8 @@ ensure :: proc(condition: bool, message := #caller_expression(condition), loc := } } +// Panics the program with a message. +// This uses the `context.assertion_failure_procedure` to panic. @builtin panic :: proc(message: string, loc := #caller_location) -> ! { p := context.assertion_failure_proc @@ -1019,6 +1695,8 @@ panic :: proc(message: string, loc := #caller_location) -> ! { p("panic", message, loc) } +// Panics the program with a message to indicate something has yet to be implemented. +// This uses the `context.assertion_failure_procedure` to assert. @builtin unimplemented :: proc(message := "", loc := #caller_location) -> ! { p := context.assertion_failure_proc @@ -1028,7 +1706,10 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! { p("not yet implemented", message, loc) } - +// Evaluates the condition and panics the program if and only if (⟺) the condition is false. +// This uses the `default_assertion_contextless_failure_proc` to assert. +// +// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true. @builtin @(disabled=ODIN_DISABLE_ASSERT) assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) { @@ -1045,6 +1726,8 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex } } +// Evaluates the condition and panics the program if and only if (⟺) the condition is false. +// This uses the `default_assertion_contextless_failure_proc` to assert. @builtin ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) { if !condition { @@ -1056,11 +1739,15 @@ ensure_contextless :: proc "contextless" (condition: bool, message := #caller_ex } } +// Panics the program with a message. +// This uses the `default_assertion_contextless_failure_proc` to assert. @builtin panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! { default_assertion_contextless_failure_proc("panic", message, loc) } +// Panics the program with a message to indicate something has yet to be implemented. +// This uses the `default_assertion_contextless_failure_proc` to assert. @builtin unimplemented_contextless :: proc "contextless" (message := "", loc := #caller_location) -> ! { default_assertion_contextless_failure_proc("not yet implemented", message, loc) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index ff27a4559..e9a284a04 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -105,8 +105,8 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, a allocator := allocator if allocator.procedure == nil { allocator = context.allocator + assert(allocator.procedure != nil) } - assert(allocator.procedure != nil) new_bytes: []byte new_bytes, err = allocator.procedure( @@ -178,8 +178,31 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #cal if array == nil { return nil } - reserve_soa(array, length, loc) or_return + footer := raw_soa_footer(array) + + if length > footer.cap { + reserve_soa(array, length, loc) or_return + } else if size_of(E) > 0 && length > footer.len { + ti := type_info_base(type_info_of(typeid_of(T))) + si := &ti.variant.(Type_Info_Struct) + + field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) + + data := (^rawptr)(array)^ + + soa_offset := 0 + for i in 0.. (n: int, err: Allocator_Error) #optional_allocator_error { + if array == nil { + return 0, nil + } + prev_len := len(array) + resize_soa(array, len(array)+1, loc) or_return + return len(array)-prev_len, nil +} + + +// `inject_at_elem_soa` injects an element in a dynamic SOA array at a specified index and moves the previous elements after that index "across" +@builtin +inject_at_elem_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } + if array == nil { + return + } + n := max(len(array), index) + m :: 1 + new_len := n + m + + resize_soa(array, new_len, loc) or_return + + when size_of(E) != 0 { + ti := type_info_base(type_info_of(typeid_of(T))) + si := &ti.variant.(Type_Info_Struct) + + field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) + + item_offset := 0 + + arg_copy := arg + arg_ptr := &arg_copy + + for i in 0.. (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error { + when !ODIN_NO_BOUNDS_CHECK { + ensure(index >= 0, "Index must be positive.", loc) + } + if array == nil { + return + } + if len(args) == 0 { + ok = true + return + } + + n := max(len(array), index) + m := len(args) + new_len := n + m + + resize_soa(array, new_len, loc) or_return + + when size_of(E) != 0 { + ti := type_info_base(type_info_of(typeid_of(T))) + si := &ti.variant.(Type_Info_Struct) + + field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) + + item_offset := 0 + + args_ptr := &args[0] + + for i in 0.. Allocator_Error { field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) when field_count != 0 { @@ -426,6 +626,7 @@ delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc return nil } +@builtin delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error { field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) when field_count != 0 { @@ -444,7 +645,7 @@ delete_soa :: proc{ delete_soa_dynamic_array, } - +@builtin clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) { field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) when field_count != 0 { diff --git a/base/runtime/default_allocators_nil.odin b/base/runtime/default_allocators_nil.odin index e7a1b1a74..2f2edb40a 100644 --- a/base/runtime/default_allocators_nil.odin +++ b/base/runtime/default_allocators_nil.odin @@ -23,7 +23,16 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, .None } -nil_allocator :: proc() -> Allocator { +// nil_allocator returns an allocator which will return `nil` for any result. +// * `.Alloc`, `.Alloc_Non_Zero`, `.Resize`, `.Resize_Non_Zeroed` will return `nil, .Out_Of_Memory` +// * `.Free` will return `nil, .None` +// * `.Free_All` will return `nil, .Mode_Not_Implemented` +// * `.Query_Features`, `.Query_Info` will return `nil, .Mode_Not_Implemented` +// +// This is extremely useful for creating a dynamic array from a buffer which does not nothing +// on a resize/reserve beyond the originally allocated memory. +@(require_results) +nil_allocator :: proc "contextless" () -> Allocator { return Allocator{ procedure = nil_allocator_proc, data = nil, @@ -72,6 +81,10 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil } +// panic_allocator returns an allocator which will panic for any non-zero-sized allocation or `query_info` +// +// This is extremely useful for to check when something does a memory operation when it should not, and thus panic. +@(require_results) panic_allocator :: proc() -> Allocator { return Allocator{ procedure = panic_allocator_proc, diff --git a/base/runtime/default_temp_allocator_arena.odin b/base/runtime/default_temp_allocator_arena.odin index 74994344a..f1d09792a 100644 --- a/base/runtime/default_temp_allocator_arena.odin +++ b/base/runtime/default_temp_allocator_arena.odin @@ -1,7 +1,7 @@ package runtime import "base:intrinsics" -import "base:sanitizer" +// import "base:sanitizer" DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: uint(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE) @@ -44,7 +44,7 @@ memory_block_alloc :: proc(allocator: Allocator, capacity: uint, alignment: uint block.base = ([^]byte)(uintptr(block) + base_offset) block.capacity = uint(end - uintptr(block.base)) - sanitizer.address_poison(block.base, block.capacity) + // sanitizer.address_poison(block.base, block.capacity) // Should be zeroed assert(block.used == 0) @@ -52,10 +52,13 @@ memory_block_alloc :: proc(allocator: Allocator, capacity: uint, alignment: uint return } -memory_block_dealloc :: proc(block_to_free: ^Memory_Block, loc := #caller_location) { +memory_block_dealloc :: proc "contextless" (block_to_free: ^Memory_Block, loc := #caller_location) { if block_to_free != nil { + allocator := block_to_free.allocator - sanitizer.address_unpoison(block_to_free.base, block_to_free.capacity) + // sanitizer.address_unpoison(block_to_free.base, block_to_free.capacity) + context = default_context() + context.allocator = allocator mem_free(block_to_free, allocator, loc) } } @@ -87,22 +90,13 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) return } data = block.base[block.used+alignment_offset:][:min_size] - sanitizer.address_unpoison(block.base[block.used:block.used+size]) + // sanitizer.address_unpoison(block.base[block.used:block.used+size]) block.used += size return } @(require_results) arena_alloc :: proc(arena: ^Arena, size, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { - align_forward_uint :: proc "contextless" (ptr, align: uint) -> uint { - p := ptr - modulo := p & (align-1) - if modulo != 0 { - p += align - modulo - } - return p - } - assert(alignment & (alignment-1) == 0, "non-power of two alignment", loc) size := size @@ -167,12 +161,12 @@ arena_free_all :: proc(arena: ^Arena, loc := #caller_location) { if arena.curr_block != nil { intrinsics.mem_zero(arena.curr_block.base, arena.curr_block.used) arena.curr_block.used = 0 - sanitizer.address_poison(arena.curr_block.base, arena.curr_block.capacity) + // sanitizer.address_poison(arena.curr_block.base, arena.curr_block.capacity) } arena.total_used = 0 } -arena_destroy :: proc(arena: ^Arena, loc := #caller_location) { +arena_destroy :: proc "contextless" (arena: ^Arena, loc := #caller_location) { for arena.curr_block != nil { free_block := arena.curr_block arena.curr_block = free_block.prev @@ -184,6 +178,7 @@ arena_destroy :: proc(arena: ^Arena, loc := #caller_location) { arena.total_capacity = 0 } +@(require_results) arena_allocator :: proc(arena: ^Arena) -> Allocator { return Allocator{arena_allocator_proc, arena} } @@ -231,8 +226,9 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if start < old_end && old_end == block.used && new_end <= block.capacity { // grow data in-place, adjusting next allocation block.used = uint(new_end) + arena.total_used = uint(new_end) data = block.base[start:new_end] - sanitizer.address_unpoison(data) + // sanitizer.address_unpoison(data) return } } @@ -306,7 +302,7 @@ arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { assert(block.used >= temp.used, "out of order use of arena_temp_end", loc) amount_to_zero := block.used-temp.used intrinsics.mem_zero(block.base[temp.used:], amount_to_zero) - sanitizer.address_poison(block.base[temp.used:block.capacity]) + // sanitizer.address_poison(block.base[temp.used:block.capacity]) block.used = temp.used arena.total_used -= amount_to_zero } diff --git a/base/runtime/default_temporary_allocator.odin b/base/runtime/default_temporary_allocator.odin index b355ded70..857463912 100644 --- a/base/runtime/default_temporary_allocator.odin +++ b/base/runtime/default_temporary_allocator.odin @@ -4,11 +4,12 @@ DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKIN NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR when NO_DEFAULT_TEMP_ALLOCATOR { + // `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`. Default_Temp_Allocator :: struct {} - default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {} + default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator: Allocator) {} - default_temp_allocator_destroy :: proc(s: ^Default_Temp_Allocator) {} + default_temp_allocator_destroy :: proc "contextless" (s: ^Default_Temp_Allocator) {} default_temp_allocator_proc :: nil_allocator_proc @@ -20,15 +21,20 @@ when NO_DEFAULT_TEMP_ALLOCATOR { default_temp_allocator_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { } } else { + // `Default_Temp_Allocator` is an `Arena` based type of allocator. See `runtime.Arena` for its implementation. + // The default `context.temp_allocator` is typically called with `free_all(context.temp_allocator)` once per "frame-loop" + // to prevent it from "leaking" memory. + // + // Note: `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`. Default_Temp_Allocator :: struct { arena: Arena, } - default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) { + default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator: Allocator) { _ = arena_init(&s.arena, uint(size), backing_allocator) } - default_temp_allocator_destroy :: proc(s: ^Default_Temp_Allocator) { + default_temp_allocator_destroy :: proc "contextless" (s: ^Default_Temp_Allocator) { if s != nil { arena_destroy(&s.arena) s^ = {} @@ -56,7 +62,7 @@ when NO_DEFAULT_TEMP_ALLOCATOR { } @(fini, private) - _destroy_temp_allocator_fini :: proc() { + _destroy_temp_allocator_fini :: proc "contextless" () { default_temp_allocator_destroy(&global_default_temp_allocator_data) } } @@ -70,7 +76,7 @@ DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD :: #force_inline proc(ignore := false, loc := } } - +@(require_results) default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator { return Allocator{ procedure = default_temp_allocator_proc, diff --git a/base/runtime/doc.odin b/base/runtime/doc.odin new file mode 100644 index 000000000..7369e36b5 --- /dev/null +++ b/base/runtime/doc.odin @@ -0,0 +1,244 @@ + +/* +Declarations which are required by the compiler + +## Descriptions of files + +There are a lot of files in this package and below is described roughly what +kind of functionality is placed in different files: + +| File pattern | Description +|----------------------|------------------------------------------------------| +| `core.odin` | Contains the declarations that compiler will require to be present. Contains context-related declarations, `Type_Info` declarations and some other types used to implement the runtime and other packages. | +| `core_builtin*.odin` | Contain `@(builtin)` declarations that can be used without importing the package. Most of them aren't required by the compiler | +| `default_*.odin` | Contain default implementations for context allocators | +| `entry_*.odin` | Contain OS-specific entry points | +| `os_specific_*.odin` | Contain OS-specific utility procedures | +| `*internal*.odin` | Contain implementations for internal procedures that can be called by the compiler | + +## Implementing custom runtime + +For embedded and kernel development it might be required to re-implement parts +of the `base:runtime` package. This can include changing the default printing +procedures that handle console output when the program panics, custom +entry-points, tailored for a specific platform or execution environment, or +simply switching up implementations of some procedures. + +In case this is required, the following is suggested: + +1. Define `$ODIN_ROOT` environment variable to point to a directory within your + project that contains the following directories: `base/`, `core/` and `vendor/`. +2. Inside the `$ODIN_ROOT/base` subdirectory, implement the *necessary + declarations*. + +What constitutes the necessary definitions is described below. + +### Context-related + +The compiler will require these declarations as they concern the `context` +variable. + +* `Maybe` +* `Source_Code_Location` +* `Context` +* `Allocator` +* `Random_Generator` +* `Logger` +* `__init_context` + +### Runtime initialization/cleanup + +These are not strictly required for compilation, but if global variables or +`@(init)`/`@(fini)` blocks are used, these procedures need to be called inside +the entry point. + +* `_startup_runtime` +* `_cleanup_runtime` + +### Type assertion check + +These procedures are called every time `.(Type)` expressions are used in order +to check the union tag or the underlying type of `any` before returning the +value of the underlying type. These are not required if `-no-type-assert` is +specified. + +* `type_assertion_check` +* `type_assertion_check2` (takes in typeid) + +### Bounds checking procedures + +These procedures are called every time index or slicing expression are used in +order to perform bounds-checking before the actual operation. These are not +required if the `-no-bounds-check` option is specified. + +* `bounds_check_error` +* `matrix_bounds_check_error` +* `slice_expr_error_hi` +* `slice_expr_error_lo_hi` +* `multi_pointer_slice_expr_error` + +### cstring calls + +If `cstring` or `cstring16` types are used, these procedures are required. + +* `cstring_to_string` +* `cstring_len` +* `cstring16_to_string16` +* `cstring16_len` + +### Comparison + +These procedures are required for comparison operators between strings and other +compound types to function properly. If strings, structs nor unions are compared, +only `string_eq` procedure is required. + +* `memory_equal` +* `memory_compare` +* `memory_compare_zero` +* `cstring_eq` +* `cstring16_eq` +* `cstring_ne` +* `cstring16_ne` +* `cstring_lt` +* `cstring16_lt` +* `cstring_gt` +* `cstring16_gt` +* `cstring_le` +* `cstring16_le` +* `cstring_ge` +* `cstring16_ge` +* `string_eq` +* `string16_eq` +* `string_ne` +* `string16_ne` +* `string_lt` +* `string16_lt` +* `string_gt` +* `string16_gt` +* `string_le` +* `string16_le` +* `string_ge` +* `string16_ge` +* `complex32_eq` +* `complex32_ne` +* `complex64_eq` +* `complex64_ne` +* `complex128_eq` +* `complex128_ne` +* `quaternion64_eq` +* `quaternion64_ne` +* `quaternion128_eq` +* `quaternion128_ne` +* `quaternion256_eq` +* `quaternion256_ne` + +### for-in `string` type + +These procedures are required to iterate strings using `for ... in` loop. If this +kind of loop isn't used, these procedures aren't required. + +* `string_decode_rune` +* `string_decode_last_rune` (for `#reverse for`) + +### Required when RTTI is enabled (the vast majority of targets) + +These declarations are required unless the `-no-rtti` compiler option is +specified. Note that in order to be useful, some other procedures need to be +implemented. Those procedures aren't mentioned here as the compiler won't +complain if they're missing. + +* `Type_Info` +* `type_table` +* `__type_info_of` + +### Hashing + +Required if maps are used + +* `default_hasher` +* `default_hasher_cstring` +* `default_hasher_string` + +### Pseudo-CRT required procedured due to LLVM but useful in general + +* `memset` +* `memcpy` +* `memove` + +### Procedures required by the LLVM backend if u128/i128 is used + +* `umodti3` +* `udivti3` +* `modti3` +* `divti3` +* `fixdfti` +* `fixunsdfti` +* `fixunsdfdi` +* `floattidf` +* `floattidf_unsigned` +* `truncsfhf2` +* `truncdfhf2` +* `gnu_h2f_ieee` +* `gnu_f2h_ieee` +* `extendhfsf2` + +### Procedures required by the LLVM backend if f16 is used (WASM only) + +* `__ashlti3` +* `__multi3` + +### When -no-crt is defined (windows only) + +* `_tls_index` +* `_fltused` + +### Arithmetic + +* `quo_complex32` +* `quo_complex64` +* `quo_complex128` + +* `mul_quaternion64` +* `mul_quaternion128` +* `mul_quaternion256` + +* `quo_quaternion64` +* `quo_quaternion128` +* `quo_quaternion256` + +* `abs_complex32` +* `abs_complex64` +* `abs_complex128` + +* `abs_quaternion64` +* `abs_quaternion128` +* `abs_quaternion256` + +## Map specific calls + +* `map_seed_from_map_data` +* `__dynamic_map_check_grow` (for static map calls) +* `map_insert_hash_dynamic` (for static map calls) +* `__dynamic_map_get` (for dynamic map calls) +* `__dynamic_map_set` (for dynamic map calls) + +## Dynamic literals (`[dynamic]T` and `map[K]V`) (can be disabled with `-no-dynamic-literals`) + +* `__dynamic_array_reserve` +* `__dynamic_array_append` +* `__dynamic_map_reserve` + +### Objective-C specific + +* `objc_lookUpClass` +* `sel_registerName` +* `objc_allocateClassPair` + +### Other required declarations + +This is required without conditions. + +* `Load_Directory_File` + +*/ +package runtime diff --git a/base/runtime/docs.odin b/base/runtime/docs.odin deleted file mode 100644 index f6b439aa0..000000000 --- a/base/runtime/docs.odin +++ /dev/null @@ -1,180 +0,0 @@ -package runtime - -/* - -package runtime has numerous entities (declarations) which are required by the compiler to function. - - -## Basic types and calls (and anything they rely on) - -Source_Code_Location -Context -Allocator -Logger - -__init_context -_cleanup_runtime - - -## cstring calls - -cstring_to_string -cstring_len - - - -## Required when RTTI is enabled (the vast majority of targets) - -Type_Info - -type_table -__type_info_of - - -## Hashing - -default_hasher -default_hasher_cstring -default_hasher_string - - -## Pseudo-CRT required procedured due to LLVM but useful in general -memset -memcpy -memove - - -## Procedures required by the LLVM backend if u128/i128 is used -umodti3 -udivti3 -modti3 -divti3 -fixdfti -fixunsdfti -fixunsdfdi -floattidf -floattidf_unsigned -truncsfhf2 -truncdfhf2 -gnu_h2f_ieee -gnu_f2h_ieee -extendhfsf2 - -## Procedures required by the LLVM backend if f16 is used -__ashlti3 // wasm specific -__multi3 // wasm specific - - -## Required an entry point is defined (i.e. 'main') - -args__ - - -## When -no-crt is defined (and not a wasm target) (mostly due to LLVM) -_tls_index -_fltused - - -## Bounds checking procedures (when not disabled with -no-bounds-check) - -bounds_check_error -matrix_bounds_check_error -slice_expr_error_hi -slice_expr_error_lo_hi -multi_pointer_slice_expr_error - - -## Type assertion check - -type_assertion_check -type_assertion_check2 // takes in typeid - - -## Arithmetic - -quo_complex32 -quo_complex64 -quo_complex128 - -mul_quaternion64 -mul_quaternion128 -mul_quaternion256 - -quo_quaternion64 -quo_quaternion128 -quo_quaternion256 - -abs_complex32 -abs_complex64 -abs_complex128 - -abs_quaternion64 -abs_quaternion128 -abs_quaternion256 - - -## Comparison - -memory_equal -memory_compare -memory_compare_zero - -cstring_eq -cstring_ne -cstring_lt -cstring_gt -cstring_le -cstring_gt - -string_eq -string_ne -string_lt -string_gt -string_le -string_gt - -complex32_eq -complex32_ne -complex64_eq -complex64_ne -complex128_eq -complex128_ne - -quaternion64_eq -quaternion64_ne -quaternion128_eq -quaternion128_ne -quaternion256_eq -quaternion256_ne - - -## Map specific calls - -map_seed_from_map_data -__dynamic_map_check_grow // static map calls -map_insert_hash_dynamic // static map calls -__dynamic_map_get // dynamic map calls -__dynamic_map_set // dynamic map calls - - -## Dynamic literals ([dynamic]T and map[K]V) (can be disabled with -no-dynamic-literals) - -__dynamic_array_reserve -__dynamic_array_append - -__dynamic_map_reserve - - -## Objective-C specific - -objc_lookUpClass -sel_registerName -objc_allocateClassPair - - -## for-in `string` type - -string_decode_rune -string_decode_last_rune // #reverse for - -*/ \ No newline at end of file diff --git a/base/runtime/dynamic_array_internal.odin b/base/runtime/dynamic_array_internal.odin index 267ee0785..514e0e782 100644 --- a/base/runtime/dynamic_array_internal.odin +++ b/base/runtime/dynamic_array_internal.odin @@ -18,8 +18,8 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: // assuming that appending/reserving will set the allocator, if it is not already set. if array.allocator.procedure == nil { array.allocator = context.allocator + assert(array.allocator.procedure != nil) } - assert(array.allocator.procedure != nil) if cap <= array.cap { return true @@ -52,8 +52,8 @@ __dynamic_array_shrink :: proc(array_: rawptr, elem_size, elem_align: int, new_c // assuming that appending/reserving will set the allocator, if it is not already set. if array.allocator.procedure == nil { array.allocator = context.allocator + assert(array.allocator.procedure != nil) } - assert(array.allocator.procedure != nil) if new_cap > array.cap { return diff --git a/base/runtime/dynamic_map_internal.odin b/base/runtime/dynamic_map_internal.odin index 7b65a2fa0..c9b3668c3 100644 --- a/base/runtime/dynamic_map_internal.odin +++ b/base/runtime/dynamic_map_internal.odin @@ -1,3 +1,4 @@ +#+build !bedrock package runtime import "base:intrinsics" @@ -6,8 +7,6 @@ _ :: intrinsics // High performance, cache-friendly, open-addressed Robin Hood hashing hash map // data structure with various optimizations for Odin. // -// Copyright 2022 (c) Dale Weiler -// // The core of the hash map data structure is the Raw_Map struct which is a // type-erased representation of the map. This type-erased representation is // used in two ways: static and dynamic. When static type information is known, @@ -49,60 +48,6 @@ MAP_MIN_LOG2_CAPACITY :: 3 // 8 elements // Has to be less than 100% though. #assert(MAP_LOAD_FACTOR < 100) -// This is safe to change. The log2 size of a cache-line. At minimum it has to -// be six though. Higher cache line sizes are permitted. -MAP_CACHE_LINE_LOG2 :: 6 - -// The size of a cache-line. -MAP_CACHE_LINE_SIZE :: 1 << MAP_CACHE_LINE_LOG2 - -// The minimum cache-line size allowed by this implementation is 64 bytes since -// we need 6 bits in the base pointer to store the integer log2 capacity, which -// at maximum is 63. Odin uses signed integers to represent length and capacity, -// so only 63 bits are needed in the maximum case. -#assert(MAP_CACHE_LINE_SIZE >= 64) - -// Map_Cell type that packs multiple T in such a way to ensure that each T stays -// aligned by align_of(T) and such that align_of(Map_Cell(T)) % MAP_CACHE_LINE_SIZE == 0 -// -// This means a value of type T will never straddle a cache-line. -// -// When multiple Ts can fit in a single cache-line the data array will have more -// than one element. When it cannot, the data array will have one element and -// an array of Map_Cell(T) will be padded to stay a multiple of MAP_CACHE_LINE_SIZE. -// -// We rely on the type system to do all the arithmetic and padding for us here. -// -// The usual array[index] indexing for []T backed by a []Map_Cell(T) becomes a bit -// more involved as there now may be internal padding. The indexing now becomes -// -// N :: len(Map_Cell(T){}.data) -// i := index / N -// j := index % N -// cell[i].data[j] -// -// However, since len(Map_Cell(T){}.data) is a compile-time constant, there are some -// optimizations we can do to eliminate the need for any divisions as N will -// be bounded by [1, 64). -// -// In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated -// as a regular array of T, which is the case for hashes. -Map_Cell :: struct($T: typeid) #align(MAP_CACHE_LINE_SIZE) { - data: [MAP_CACHE_LINE_SIZE / size_of(T) when 0 < size_of(T) && size_of(T) < MAP_CACHE_LINE_SIZE else 1]T, -} - -// So we can operate on a cell data structure at runtime without any type -// information, we have a simple table that stores some traits about the cell. -// -// 32-bytes on 64-bit -// 16-bytes on 32-bit -Map_Cell_Info :: struct { - size_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits - align_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits - size_of_cell: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits - elements_per_cell: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits -} - // map_cell_info :: proc "contextless" ($T: typeid) -> ^Map_Cell_Info {...} map_cell_info :: intrinsics.type_map_cell_info @@ -228,8 +173,6 @@ map_data :: #force_inline proc "contextless" (m: Raw_Map) -> uintptr { } -Map_Hash :: uintptr - TOMBSTONE_MASK :: 1<<(size_of(Map_Hash)*8 - 1) // Procedure to check if a slot is empty for a given hash. This is represented @@ -285,26 +228,11 @@ map_desired_position :: #force_inline proc "contextless" (m: Raw_Map, hash: Map_ map_probe_distance :: #force_inline proc "contextless" (m: Raw_Map, hash: Map_Hash, slot: uintptr) -> uintptr { // We do not use map_cap since we know the capacity will not be zero here. capacity := uintptr(1) << map_log2_cap(m) - return (slot + capacity - map_desired_position(m, hash)) & (capacity - 1) -} -// When working with the type-erased structure at runtime we need information -// about the map to make working with it possible. This info structure stores -// that. -// -// `Map_Info` and `Map_Cell_Info` are read only data structures and cannot be -// modified after creation -// -// 32-bytes on 64-bit -// 16-bytes on 32-bit -Map_Info :: struct { - ks: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit - vs: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit - key_hasher: proc "contextless" (key: rawptr, seed: Map_Hash) -> Map_Hash, // 8-bytes on 64-bit, 4-bytes on 32-bit - key_equal: proc "contextless" (lhs, rhs: rawptr) -> bool, // 8-bytes on 64-bit, 4-bytes on 32-bit + // return (slot + capacity - map_desired_position(m, hash)) & (capacity - 1) + return (slot - uintptr(hash)) & (capacity - 1) // NOTE(bill): this is equivalent to the above, but less operations } - // The Map_Info structure is basically a pseudo-table of information for a given K and V pair. // map_info :: proc "contextless" ($T: typeid/map[$K]$V) -> ^Map_Info {...} map_info :: intrinsics.type_map_info @@ -905,22 +833,22 @@ __dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: return nil, false } -__dynamic_map_set_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr { +__dynamic_map_set_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (value_ptr: rawptr, err: Allocator_Error) #optional_allocator_error { return __dynamic_map_set(m, info, info.key_hasher(key, map_seed(m^)), key, value, loc) } // IMPORTANT: USED WITHIN THE COMPILER -__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, hash: Map_Hash, key, value: rawptr, loc := #caller_location) -> rawptr { +__dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, hash: Map_Hash, key, value: rawptr, loc := #caller_location) -> (value_ptr: rawptr, err: Allocator_Error) #optional_allocator_error { if found := __dynamic_map_get(m, info, hash, key); found != nil { intrinsics.mem_copy_non_overlapping(found, value, info.vs.size_of_type) - return found + return found, nil } hash := hash - err, has_grown := __dynamic_map_check_grow(m, info, loc) - if err != nil { - return nil + err_grow, has_grown := __dynamic_map_check_grow(m, info, loc) + if err_grow != nil { + return nil, err_grow } if has_grown { hash = info.key_hasher(key, map_seed(m^)) @@ -930,7 +858,7 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In if result != 0 { m.len += 1 } - return rawptr(result) + return rawptr(result), nil } __dynamic_map_set_extra_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) { return __dynamic_map_set_extra(m, info, info.key_hasher(key, map_seed(m^)), key, value, loc) @@ -985,6 +913,9 @@ __dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_ // IMPORTANT: USED WITHIN THE COMPILER @(private) __dynamic_map_reserve :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uint, loc := #caller_location) -> Allocator_Error { + if m == nil { + return nil + } return map_reserve_dynamic(m, info, uintptr(new_capacity), loc) } @@ -1057,4 +988,4 @@ default_hasher_quaternion256 :: proc "contextless" (x, y, z, w: f64, seed: uintp seed = default_hasher_f64(z, seed) seed = default_hasher_f64(w, seed) return seed -} \ No newline at end of file +} diff --git a/base/runtime/entry_unix.odin b/base/runtime/entry_unix.odin index d188dd40e..5acb1449b 100644 --- a/base/runtime/entry_unix.odin +++ b/base/runtime/entry_unix.odin @@ -1,5 +1,5 @@ #+private -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd #+no-instrumentation package runtime @@ -10,13 +10,15 @@ when ODIN_BUILD_MODE == .Dynamic { _odin_entry_point :: proc "c" (argc: i32, argv: [^]cstring) { args__ = argv[:argc] context = default_context() - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() } @(link_name="_odin_exit_point", linkage="strong", require/*, link_section=".fini"*/) _odin_exit_point :: proc "c" () { context = default_context() - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { + #force_no_inline _cleanup_runtime() + } } @(link_name="main", linkage="strong", require) main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 { @@ -43,9 +45,9 @@ when ODIN_BUILD_MODE == .Dynamic { _start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! { args__ = argv[:argc] context = default_context() - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } intrinsics.syscall(SYS_exit, 0) unreachable() } @@ -54,9 +56,9 @@ when ODIN_BUILD_MODE == .Dynamic { main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 { args__ = argv[:argc] context = default_context() - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } return 0 } } diff --git a/base/runtime/entry_unix_no_crt_amd64.asm b/base/runtime/entry_unix_no_crt_amd64.asm index f0bdce8d7..225356a2f 100644 --- a/base/runtime/entry_unix_no_crt_amd64.asm +++ b/base/runtime/entry_unix_no_crt_amd64.asm @@ -3,6 +3,7 @@ bits 64 extern _start_odin global _start +section .note.GNU-stack section .text ;; Entry point for programs that specify -no-crt option @@ -35,7 +36,7 @@ _start: xor rbp, rbp ;; Load argc into 1st param reg, argv into 2nd param reg pop rdi - mov rdx, rsi + mov rsi, rsp ;; Align stack pointer down to 16-bytes (sysv calling convention) and rsp, -16 ;; Call into odin entry point diff --git a/base/runtime/entry_windows.odin b/base/runtime/entry_windows.odin index 8eb4cc7d1..d3b38bc9c 100644 --- a/base/runtime/entry_windows.odin +++ b/base/runtime/entry_windows.odin @@ -16,10 +16,10 @@ when ODIN_BUILD_MODE == .Dynamic { switch dll_forward_reason { case .Process_Attach: - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() case .Process_Detach: - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } case .Thread_Attach: break case .Thread_Detach: @@ -28,13 +28,25 @@ when ODIN_BUILD_MODE == .Dynamic { return true } } else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT { - when ODIN_ARCH == .i386 || ODIN_NO_CRT { + when ODIN_ARCH == .i386 && !ODIN_NO_CRT { + // Windows i386 with CRT: libcmt provides mainCRTStartup which calls _main + // Note: "c" calling convention adds underscore prefix automatically on i386 + @(link_name="main", linkage="strong", require) + main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 { + args__ = argv[:argc] + context = default_context() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } + intrinsics.__entry_point() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + return 0 + } + } else when ODIN_NO_CRT { @(link_name="mainCRTStartup", linkage="strong", require) mainCRTStartup :: proc "system" () -> i32 { context = default_context() - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } return 0 } } else { @@ -42,9 +54,9 @@ when ODIN_BUILD_MODE == .Dynamic { main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 { args__ = argv[:argc] context = default_context() - #force_no_inline _startup_runtime() + when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } intrinsics.__entry_point() - #force_no_inline _cleanup_runtime() + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } return 0 } } diff --git a/base/runtime/error_checks.odin b/base/runtime/error_checks.odin index 32a895c3f..46a8f9b1d 100644 --- a/base/runtime/error_checks.odin +++ b/base/runtime/error_checks.odin @@ -12,7 +12,7 @@ bounds_trap :: proc "contextless" () -> ! { } @(no_instrumentation) -type_assertion_trap :: proc "contextless" () -> ! { +type_assertion_trap_contextless :: proc "contextless" () -> ! { when ODIN_OS == .Windows { windows_trap_type_assertion() } else when ODIN_OS == .Orca { @@ -137,20 +137,22 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32 when ODIN_NO_RTTI { - type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) { + type_assertion_check_with_context :: proc "odin" (ok: bool, file: string, line, column: i32) { if ok { return } @(cold, no_instrumentation) - handle_error :: proc "contextless" (file: string, line, column: i32) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid type assertion\n") - type_assertion_trap() + handle_error :: proc "odin" (file: string, line, column: i32) -> ! { + p := context.assertion_failure_proc + if p == nil { + p = default_assertion_failure_proc + } + p("type assertion", "Invalid type assertion", Source_Code_Location{file, line, column, ""}) } handle_error(file, line, column) } - type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32) { + type_assertion_check_contextless :: proc "contextless" (ok: bool, file: string, line, column: i32) { if ok { return } @@ -158,12 +160,71 @@ when ODIN_NO_RTTI { handle_error :: proc "contextless" (file: string, line, column: i32) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion\n") - type_assertion_trap() + type_assertion_trap_contextless() + } + handle_error(file, line, column) + } + + type_assertion_check2_with_context :: proc "odin" (ok: bool, file: string, line, column: i32) { + if ok { + return + } + @(cold, no_instrumentation) + handle_error :: proc "odin" (file: string, line, column: i32) -> ! { + p := context.assertion_failure_proc + if p == nil { + p = default_assertion_failure_proc + } + p("type assertion", "Invalid type assertion", Source_Code_Location{file, line, column, ""}) + } + + handle_error(file, line, column) + } + + type_assertion_check2_contextless :: proc "contextless" (ok: bool, file: string, line, column: i32) { + if ok { + return + } + @(cold, no_instrumentation) + handle_error :: proc "contextless" (file: string, line, column: i32) -> ! { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion\n") + type_assertion_trap_contextless() } handle_error(file, line, column) } } else { - type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { + @(private="file") + TYPE_ASSERTION_BUFFER_SIZE :: 1024 + + type_assertion_check_with_context :: proc "odin" (ok: bool, file: string, line, column: i32, from, to: typeid) { + if ok { + return + } + @(cold, no_instrumentation) + handle_error :: proc "odin" (file: string, line, column: i32, from, to: typeid) -> ! { + do_msg :: proc "contextless" (i: ^int, buf: []byte, file: string, line, column: i32, from, to: typeid) -> bool { + write_string(i, buf, "Invalid type assertion from ") or_return + write_typeid(i, buf, from) or_return + write_string(i, buf, " to ") or_return + write_typeid(i, buf, to) or_return + return true + } + + buf: [TYPE_ASSERTION_BUFFER_SIZE]byte + i := 0 + _ = do_msg(&i, buf[:], file, line, column, from, to) + + p := context.assertion_failure_proc + if p == nil { + p = default_assertion_failure_proc + } + p("type assertion", string(buf[:i]), Source_Code_Location{file, line, column, ""}) + } + handle_error(file, line, column, from, to) + } + + type_assertion_check_contextless :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { if ok { return } @@ -175,47 +236,90 @@ when ODIN_NO_RTTI { print_string(" to ") print_typeid(to) print_byte('\n') - type_assertion_trap() + type_assertion_trap_contextless() } handle_error(file, line, column, from, to) } - type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { + @(private="file") + type_assertion_variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid { + if id == nil || data == nil { + return id + } + ti := type_info_base(type_info_of(id)) + #partial switch v in ti.variant { + case Type_Info_Any: + return (^any)(data).id + case Type_Info_Union: + if v.tag_type == nil { + if (^rawptr)(data)^ == nil { + return nil + } + return v.variants[0].id + + } + + tag_ptr := uintptr(data) + v.tag_offset + idx := 0 + switch v.tag_type.size { + case 1: idx = int( (^u8)(tag_ptr)^); if !v.no_nil { idx -= 1 } + case 2: idx = int( (^u16)(tag_ptr)^); if !v.no_nil { idx -= 1 } + case 4: idx = int( (^u32)(tag_ptr)^); if !v.no_nil { idx -= 1 } + case 8: idx = int( (^u64)(tag_ptr)^); if !v.no_nil { idx -= 1 } + case 16: idx = int((^u128)(tag_ptr)^); if !v.no_nil { idx -= 1 } + } + if idx < 0 { + return nil + } else if idx < len(v.variants) { + return v.variants[idx].id + } + } + return id + } + + type_assertion_check2_with_context :: proc "odin" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { if ok { return } - variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid { - if id == nil || data == nil { - return id - } - ti := type_info_base(type_info_of(id)) - #partial switch v in ti.variant { - case Type_Info_Any: - return (^any)(data).id - case Type_Info_Union: - tag_ptr := uintptr(data) + v.tag_offset - idx := 0 - switch v.tag_type.size { - case 1: idx = int((^u8)(tag_ptr)^) - 1 - case 2: idx = int((^u16)(tag_ptr)^) - 1 - case 4: idx = int((^u32)(tag_ptr)^) - 1 - case 8: idx = int((^u64)(tag_ptr)^) - 1 - case 16: idx = int((^u128)(tag_ptr)^) - 1 - } - if idx < 0 { - return nil - } else if idx < len(v.variants) { - return v.variants[idx].id + @(cold, no_instrumentation) + handle_error :: proc "odin" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! { + do_msg :: proc "contextless" (i: ^int, buf: []byte, file: string, line, column: i32, from, to, actual: typeid) -> bool { + write_string(i, buf, "Invalid type assertion from ") or_return + write_typeid(i, buf, from) or_return + write_string(i, buf, " to ") or_return + write_typeid(i, buf, to) or_return + if actual != from { + write_string(i, buf, ", actual type: ") or_return + write_typeid(i, buf, actual) or_return } + return true } - return id + + actual := type_assertion_variant_type(from, from_data) + + buf: [TYPE_ASSERTION_BUFFER_SIZE]byte + i := 0 + _ = do_msg(&i, buf[:], file, line, column, from, to, actual) + + p := context.assertion_failure_proc + if p == nil { + p = default_assertion_failure_proc + } + p("type assertion", string(buf[:i]), Source_Code_Location{file, line, column, ""}) + } + handle_error(file, line, column, from, to, from_data) + } + + type_assertion_check2_contextless :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { + if ok { + return } @(cold, no_instrumentation) handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! { - actual := variant_type(from, from_data) + actual := type_assertion_variant_type(from, from_data) print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion from ") @@ -227,7 +331,7 @@ when ODIN_NO_RTTI { print_typeid(actual) } print_byte('\n') - type_assertion_trap() + type_assertion_trap_contextless() } handle_error(file, line, column, from, to, from_data) } diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index bff5b8380..e08d0e01d 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -7,21 +7,58 @@ import "base:intrinsics" IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 @(private) -RUNTIME_LINKAGE :: "strong" when ( - ODIN_USE_SEPARATE_MODULES || - ODIN_BUILD_MODE == .Dynamic || - !ODIN_NO_CRT) else "internal" +RUNTIME_LINKAGE :: "strong" when ODIN_USE_SEPARATE_MODULES else + "internal" when ODIN_NO_ENTRY_POINT && (ODIN_BUILD_MODE == .Static || ODIN_BUILD_MODE == .Dynamic || ODIN_BUILD_MODE == .Object) else + "strong" when ODIN_BUILD_MODE == .Dynamic else + "strong" when !ODIN_NO_CRT else + "internal" RUNTIME_REQUIRE :: false // !ODIN_TILDE @(private) __float16 :: f16 when __ODIN_LLVM_F16_SUPPORTED else u16 +HAS_HARDWARE_SIMD :: false when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else + false when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else + false when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else + false when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else + true + +// Size of a native SIMD register for the current compilation target +NATIVE_SIMD_BIT_WIDTH :: + 512 when (ODIN_ARCH == .amd64) && intrinsics.has_target_feature("avx512f") else + 256 when (ODIN_ARCH == .amd64) && (intrinsics.has_target_feature("avx2") || intrinsics.has_target_feature("avx")) else + // Fallback for no hardware SIMD, but also SSE, NEON, SVE, RVV and WASM SIMD128. + 128 @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { return ([^]byte)(data)[:max(len, 0)] } +@(require_results) +align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint { + assert(is_power_of_two_uint(align)) + return (ptr + align-1) & ~(align-1) +} + +@(require_results) +align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int { + assert(is_power_of_two_int(align)) + return int(align_forward_uint(uint(ptr), uint(align))) +} + +@(require_results) +align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr { + return uintptr(align_forward_uint(uint(ptr), uint(align))) +} + +align_forward :: proc { + align_forward_int, + align_forward_uint, + align_forward_uintptr, +} + +@(require_results) is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool { if x <= 0 { return false @@ -29,51 +66,17 @@ is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool { return (x & (x-1)) == 0 } -align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int { - assert(is_power_of_two_int(align)) - - p := ptr - modulo := p & (align-1) - if modulo != 0 { - p += align - modulo - } - return p -} - +@(require_results) is_power_of_two_uint :: #force_inline proc "contextless" (x: uint) -> bool { - if x <= 0 { + if x == 0 { return false } return (x & (x-1)) == 0 } -align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint { - assert(is_power_of_two_uint(align)) - - p := ptr - modulo := p & (align-1) - if modulo != 0 { - p += align - modulo - } - return p -} - +@(require_results) is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool { - if x <= 0 { - return false - } - return (x & (x-1)) == 0 -} - -align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr { - assert(is_power_of_two_uintptr(align)) - - p := ptr - modulo := p & (align-1) - if modulo != 0 { - p += align - modulo - } - return p + return is_power_of_two_uint(uint(x)) } is_power_of_two :: proc { @@ -82,12 +85,6 @@ is_power_of_two :: proc { is_power_of_two_uintptr, } -align_forward :: proc { - align_forward_int, - align_forward_uint, - align_forward_uintptr, -} - mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr { if data == nil { return nil @@ -117,7 +114,7 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r DEFAULT_ALIGNMENT :: 2*align_of(rawptr) -mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { +mem_alloc_bytes :: #force_no_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc) if size == 0 || allocator.procedure == nil{ return nil, nil @@ -125,7 +122,7 @@ mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNM return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) } -mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { +mem_alloc :: #force_no_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc) if size == 0 || allocator.procedure == nil { return nil, nil @@ -133,7 +130,7 @@ mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, a return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) } -mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { +mem_alloc_non_zeroed :: #force_no_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc) if size == 0 || allocator.procedure == nil { return nil, nil @@ -141,7 +138,8 @@ mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_A return allocator.procedure(allocator.data, .Alloc_Non_Zeroed, size, alignment, nil, 0, loc) } -mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { +@builtin +mem_free :: #force_no_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if ptr == nil || allocator.procedure == nil { return nil } @@ -149,7 +147,7 @@ mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc return err } -mem_free_with_size :: #force_inline proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { +mem_free_with_size :: #force_no_inline proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if ptr == nil || allocator.procedure == nil { return nil } @@ -157,7 +155,7 @@ mem_free_with_size :: #force_inline proc(ptr: rawptr, byte_count: int, allocator return err } -mem_free_bytes :: #force_inline proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { +mem_free_bytes :: #force_no_inline proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { if bytes == nil || allocator.procedure == nil { return nil } @@ -165,15 +163,15 @@ mem_free_bytes :: #force_inline proc(bytes: []byte, allocator := context.allocat return err } - -mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) { +@builtin +mem_free_all :: #force_no_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) { if allocator.procedure != nil { _, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc) } return } -_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { +_mem_resize :: #force_no_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc) if allocator.procedure == nil { return nil, nil @@ -224,156 +222,296 @@ non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc) } +conditional_mem_zero :: proc "contextless" (data: rawptr, n_: int) #no_bounds_check { + // When acquiring memory from the OS for the first time it's likely that the + // OS already gives the zero page mapped multiple times for the request. The + // actual allocation does not have physical pages allocated to it until those + // pages are written to which causes a page-fault. This is often called COW + // (Copy on Write) + // + // You do not want to actually zero out memory in this case because it would + // cause a bunch of page faults decreasing the speed of allocations and + // increase the amount of actual resident physical memory used. + // + // Instead a better technique is to check if memory is zerored before zeroing + // it. This turns out to be an important optimization in practice, saving + // nearly half (or more) the amount of physical memory used by an application. + // This is why every implementation of calloc in libc does this optimization. + // + // It may seem counter-intuitive but most allocations in an application are + // wasted and never used. When you consider something like a [dynamic]T which + // always doubles in capacity on resize but you rarely ever actually use the + // full capacity of a dynamic array it means you have a lot of resident waste + // if you actually zeroed the remainder of the memory. + // + // Keep in mind the OS is already guaranteed to give you zeroed memory by + // mapping in this zero page multiple times so in the best case there is no + // need to actually zero anything. As for testing all this memory for a zero + // value, it costs nothing because the the same zero page is used for the + // whole allocation and will exist in L1 cache for the entire zero checking + // process. + + if n_ <= 0 { + return + } + n := uint(n_) + + n_words := n / size_of(uintptr) + p_words := ([^]uintptr)(data)[:n_words] + p_bytes := ([^]byte)(data)[size_of(uintptr) * n_words:n] + for &p_word in p_words { + if p_word != 0 { + p_word = 0 + } + } + for &p_byte in p_bytes { + if p_byte != 0 { + p_byte = 0 + } + } +} + memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { switch { case n == 0: return true case x == y: return true } - a, b := ([^]byte)(x), ([^]byte)(y) - length := uint(n) + a, b := cast([^]byte)x, cast([^]byte)y - for i := uint(0); i < length; i += 1 { + n := uint(n) + i := uint(0) + m := uint(0) + + if n >= 8 { + when HAS_HARDWARE_SIMD { + // Avoid using 256-bit SIMD on platforms where its emulation is + // likely to be less than ideal. + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + ne := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(ne) != 0 { + return false + } + } + } + } + + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + ne := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(ne) != 0 { + return false + } + } + + m = (n-i) / size_of(uintptr) * size_of(uintptr) + for /**/; i < m; i += size_of(uintptr) { + if intrinsics.unaligned_load(cast(^uintptr)&a[i]) != intrinsics.unaligned_load(cast(^uintptr)&b[i]) { + return false + } + } + } + + for /**/; i < n; i += 1 { if a[i] != b[i] { return false } } return true - -/* - - when size_of(uint) == 8 { - if word_length := length >> 3; word_length != 0 { - for _ in 0..> 2; word_length != 0 { - for _ in 0.. int #no_bounds_check { + +memory_compare :: proc "contextless" (x, y: rawptr, n: int) -> int #no_bounds_check { switch { - case a == b: return 0 - case a == nil: return -1 - case b == nil: return +1 + case x == y: return 0 + case x == nil: return -1 + case y == nil: return +1 } + a, b := cast([^]byte)x, cast([^]byte)y - x := uintptr(a) - y := uintptr(b) - n := uintptr(n) + n := uint(n) + i := uint(0) + m := uint(0) - SU :: size_of(uintptr) - fast := n/SU + 1 - offset := (fast-1)*SU - curr_block := uintptr(0) - if n < SU { - fast = 0 - } - - for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^ - vb := (^uintptr)(y + curr_block * size_of(uintptr))^ - if va ~ vb != 0 { - for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^ - b := (^byte)(y+pos)^ - if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1 + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[32]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[32]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 } } } } - for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^ - b := (^byte)(y+offset)^ - if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[16]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[16]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 } } + // 64-bit SIMD is faster than using a `uintptr` to detect a difference then + // re-iterating with the byte-by-byte loop, at least on AMD64. + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + load_a := intrinsics.unaligned_load(cast(^#simd[8]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[8]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[8]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[8]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 + } + } + + for /**/; i < n; i += 1 { + if a[i] ~ b[i] != 0 { + return -1 if int(a[i]) - int(b[i]) < 0 else +1 + } + } return 0 } memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check { - x := uintptr(a) - n := uintptr(n) + n := uint(n) + i := uint(0) + m := uint(0) - SU :: size_of(uintptr) - fast := n/SU + 1 - offset := (fast-1)*SU - curr_block := uintptr(0) - if n < SU { - fast = 0 + // Because we're comparing against zero, we never return -1, as that would + // indicate the compared value is less than zero. + // + // Note that a zero return value here means equality. + + bytes := ([^]u8)(a) + + if n >= 8 { + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + scanner32: #simd[32]u8 + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load := intrinsics.unaligned_load(cast(^#simd[32]u8)&bytes[i]) + ne := intrinsics.simd_lanes_ne(scanner32, load) + if intrinsics.simd_reduce_or(ne) > 0 { + return 1 + } + } + } + } + + scanner16: #simd[16]u8 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load := intrinsics.unaligned_load(cast(^#simd[16]u8)&bytes[i]) + ne := intrinsics.simd_lanes_ne(scanner16, load) + if intrinsics.simd_reduce_or(ne) != 0 { + return 1 + } + } + + m = (n-i) / size_of(uintptr) * size_of(uintptr) + for /**/; i < m; i += size_of(uintptr) { + if intrinsics.unaligned_load(cast(^uintptr)&bytes[i]) != 0 { + return 1 + } + } } - for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^ - if va ~ 0 != 0 { - for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^ - if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1 + for /**/; i < n; i += 1 { + if bytes[i] != 0 { + return 1 + } + } + return 0 +} + +memory_prefix_length :: proc "contextless" (x, y: rawptr, n: int) -> (idx: int) #no_bounds_check { + switch { + case x == y: return n + case x == nil: return 0 + case y == nil: return 0 + } + a, b := cast([^]byte)x, cast([^]byte)y + + n := uint(n) + i := uint(0) + m := uint(0) + + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[32]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[32]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) } } } } - for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^ - if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[16]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[16]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) } } - return 0 + // 64-bit SIMD is faster than using a `uintptr` to detect a difference then + // re-iterating with the byte-by-byte loop, at least on AMD64. + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + load_a := intrinsics.unaligned_load(cast(^#simd[8]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[8]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[8]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[8]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) + } + } + + for /**/; i < n; i += 1 { + if a[i] ~ b[i] != 0 { + return int(i) + } + } + return int(n) } string_eq :: proc "contextless" (lhs, rhs: string) -> bool { @@ -396,12 +534,40 @@ string_cmp :: proc "contextless" (a, b: string) -> int { return ret } + +string16_eq :: proc "contextless" (lhs, rhs: string16) -> bool { + x := transmute(Raw_String16)lhs + y := transmute(Raw_String16)rhs + if x.len != y.len { + return false + } + return #force_inline memory_equal(x.data, y.data, x.len*size_of(u16)) +} + +string16_cmp :: proc "contextless" (a, b: string16) -> int { + x := transmute(Raw_String16)a + y := transmute(Raw_String16)b + + ret := memory_compare(x.data, y.data, min(x.len, y.len)*size_of(u16)) + if ret == 0 && x.len != y.len { + return -1 if x.len < y.len else +1 + } + return ret +} + string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b) } string_lt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) < 0 } string_gt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) > 0 } string_le :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) <= 0 } string_ge :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) >= 0 } +string16_ne :: #force_inline proc "contextless" (a, b: string16) -> bool { return !string16_eq(a, b) } +string16_lt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) < 0 } +string16_gt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) > 0 } +string16_le :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) <= 0 } +string16_ge :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) >= 0 } + + cstring_len :: proc "contextless" (s: cstring) -> int { p0 := uintptr((^byte)(s)) p := p0 @@ -411,6 +577,16 @@ cstring_len :: proc "contextless" (s: cstring) -> int { return int(p - p0) } +cstring16_len :: proc "contextless" (s: cstring16) -> int { + p := ([^]u16)(s) + n := 0 + for p != nil && p[0] != 0 { + p = p[1:] + n += 1 + } + return n +} + cstring_to_string :: proc "contextless" (s: cstring) -> string { if s == nil { return "" @@ -420,6 +596,15 @@ cstring_to_string :: proc "contextless" (s: cstring) -> string { return transmute(string)Raw_String{ptr, n} } +cstring16_to_string16 :: proc "contextless" (s: cstring16) -> string16 { + if s == nil { + return "" + } + ptr := (^u16)(s) + n := cstring16_len(s) + return transmute(string16)Raw_String16{ptr, n} +} + cstring_eq :: proc "contextless" (lhs, rhs: cstring) -> bool { x := ([^]byte)(lhs) @@ -462,6 +647,46 @@ cstring_gt :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_le :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) <= 0 } cstring_ge :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) >= 0 } +cstring16_eq :: proc "contextless" (lhs, rhs: cstring16) -> bool { + x := ([^]u16)(lhs) + y := ([^]u16)(rhs) + if x == y { + return true + } + if (x == nil) ~ (y == nil) { + return false + } + xn := cstring16_len(lhs) + yn := cstring16_len(rhs) + if xn != yn { + return false + } + return #force_inline memory_equal(x, y, xn*size_of(u16)) +} + +cstring16_cmp :: proc "contextless" (lhs, rhs: cstring16) -> int { + x := ([^]u16)(lhs) + y := ([^]u16)(rhs) + if x == y { + return 0 + } + if (x == nil) ~ (y == nil) { + return -1 if x == nil else +1 + } + xn := cstring16_len(lhs) + yn := cstring16_len(rhs) + ret := memory_compare(x, y, min(xn, yn)*size_of(u16)) + if ret == 0 && xn != yn { + return -1 if xn < yn else +1 + } + return ret +} + +cstring16_ne :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return !cstring16_eq(a, b) } +cstring16_lt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) < 0 } +cstring16_gt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) > 0 } +cstring16_le :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) <= 0 } +cstring16_ge :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) >= 0 } complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) } complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) } @@ -483,7 +708,7 @@ quaternion256_eq :: #force_inline proc "contextless" (a, b: quaternion256) -> bo quaternion256_ne :: #force_inline proc "contextless" (a, b: quaternion256) -> bool { return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b) } -string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int) { +string_decode_rune :: proc "contextless" (s: string) -> (rune, int) #no_bounds_check { // NOTE(bill): Duplicated here to remove dependency on package unicode/utf8 @(static, rodata) accept_sizes := [256]u8{ @@ -562,7 +787,7 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4 } -string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) { +string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) #no_bounds_check { RUNE_ERROR :: '\ufffd' RUNE_SELF :: 0x80 UTF_MAX :: 4 @@ -597,6 +822,68 @@ string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) { return r, size } + +string16_decode_rune :: proc "contextless" (s: string16) -> (rune, int) #no_bounds_check { + REPLACEMENT_CHAR :: '\ufffd' + _surr1 :: 0xd800 + _surr2 :: 0xdc00 + _surr3 :: 0xe000 + _surr_self :: 0x10000 + + r := rune(REPLACEMENT_CHAR) + + if len(s) < 1 { + return r, 0 + } + + w := 1 + switch c := s[0]; { + case c < _surr1, _surr3 <= c: + r = rune(c) + case _surr1 <= c && c < _surr2 && 1 < len(s) && + _surr2 <= s[1] && s[1] < _surr3: + r1, r2 := rune(c), rune(s[1]) + if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 { + r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self + } + w += 1 + } + return r, w +} + +string16_decode_last_rune :: proc "contextless" (s: string16) -> (rune, int) #no_bounds_check { + REPLACEMENT_CHAR :: '\ufffd' + _surr1 :: 0xd800 + _surr2 :: 0xdc00 + _surr3 :: 0xe000 + _surr_self :: 0x10000 + + r := rune(REPLACEMENT_CHAR) + + if len(s) < 1 { + return r, 0 + } + + n := len(s)-1 + c := s[n] + w := 1 + if _surr2 <= c && c < _surr3 { + if n >= 1 { + r1 := rune(s[n-1]) + r2 := rune(c) + if _surr1 <= r1 && r1 < _surr2 { + r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self + } + w = 2 + } + } else if c < _surr1 || _surr3 <= c { + r = rune(c) + } + return r, w +} + + + abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 { p, q := abs(real(x)), abs(imag(x)) if p < q { @@ -877,239 +1164,9 @@ extendhfsf2 :: proc "c" (value: __float16) -> f32 { return gnu_h2f_ieee(value) } - - -@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -floattidf :: proc "c" (a: i128) -> f64 { - DBL_MANT_DIG :: 53 - if a == 0 { - return 0.0 - } - a := a - N :: size_of(i128) * 8 - s := a >> (N-1) - a = (a ~ s) - s - sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits - e := i32(sd - 1) // exponent - if sd > DBL_MANT_DIG { - switch sd { - case DBL_MANT_DIG + 1: - a <<= 1 - case DBL_MANT_DIG + 2: - // okay - case: - a = i128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | - i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) - } - - a |= i128((a & 4) != 0) - a += 1 - a >>= 2 - - if a & (i128(1) << DBL_MANT_DIG) != 0 { - a >>= 1 - e += 1 - } - } else { - a <<= u128(DBL_MANT_DIG - sd) & 127 - } - fb: [2]u32 - fb[1] = (u32(s) & 0x80000000) | // sign - (u32(e + 1023) << 20) | // exponent - u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high - fb[0] = u32(a) // mantissa-low - return transmute(f64)fb -} - - -@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -floattidf_unsigned :: proc "c" (a: u128) -> f64 { - DBL_MANT_DIG :: 53 - if a == 0 { - return 0.0 - } - a := a - N :: size_of(u128) * 8 - sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits - e := i32(sd - 1) // exponent - if sd > DBL_MANT_DIG { - switch sd { - case DBL_MANT_DIG + 1: - a <<= 1 - case DBL_MANT_DIG + 2: - // okay - case: - a = u128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | - u128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) - } - - a |= u128((a & 4) != 0) - a += 1 - a >>= 2 - - if a & (1 << DBL_MANT_DIG) != 0 { - a >>= 1 - e += 1 - } - } else { - a <<= u128(DBL_MANT_DIG - sd) - } - fb: [2]u32 - fb[1] = (0) | // sign - u32((e + 1023) << 20) | // exponent - u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high - fb[0] = u32(a) // mantissa-low - return transmute(f64)fb -} - - - -@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 { - // TODO(bill): implement `fixunsdfti` correctly - x := u64(a) - return u128(x) -} - -@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { - // TODO(bill): implement `fixunsdfdi` correctly - x := i64(a) - return i128(x) -} - - - - -@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -umodti3 :: proc "c" (a, b: u128) -> u128 { - r: u128 = --- - _ = udivmod128(a, b, &r) - return r -} - - -@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - return udivmod128(a, b, rem) -} - -when !IS_WASM { - @(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) - udivti3 :: proc "c" (a, b: u128) -> u128 { - return udivmodti4(a, b, nil) - } -} - - -@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -modti3 :: proc "c" (a, b: i128) -> i128 { - s_a := a >> (128 - 1) - s_b := b >> (128 - 1) - an := (a ~ s_a) - s_a - bn := (b ~ s_b) - s_b - - r: u128 = --- - _ = udivmod128(u128(an), u128(bn), &r) - return (i128(r) ~ s_a) - s_a -} - - -@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { - s_a := a >> (128 - 1) // -1 if negative or 0 - s_b := b >> (128 - 1) - an := (a ~ s_a) - s_a // absolute - bn := (b ~ s_b) - s_b - - s_b ~= s_a // quotient sign - u_s_b := u128(s_b) - u_s_a := u128(s_a) - - r: u128 = --- - u := i128((udivmodti4(u128(an), u128(bn), &r) ~ u_s_b) - u_s_b) // negate if negative - rem^ = i128((r ~ u_s_a) - u_s_a) - return u -} - -@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -divti3 :: proc "c" (a, b: i128) -> i128 { - s_a := a >> (128 - 1) // -1 if negative or 0 - s_b := b >> (128 - 1) - an := (a ~ s_a) - s_a // absolute - bn := (b ~ s_b) - s_b - - s_a ~= s_b // quotient sign - u_s_a := u128(s_a) - - return i128((udivmodti4(u128(an), u128(bn), nil) ~ u_s_a) - u_s_a) // negate if negative -} - - -@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) -fixdfti :: proc "c" (a: u64) -> i128 { - significandBits :: 52 - typeWidth :: (size_of(u64)*8) - exponentBits :: (typeWidth - significandBits - 1) - maxExponent :: ((1 << exponentBits) - 1) - exponentBias :: (maxExponent >> 1) - - implicitBit :: (u64(1) << significandBits) - significandMask :: (implicitBit - 1) - signBit :: (u64(1) << (significandBits + exponentBits)) - absMask :: (signBit - 1) - exponentMask :: (absMask ~ significandMask) - - // Break a into sign, exponent, significand - aRep := a - aAbs := aRep & absMask - sign := i128(-1 if aRep & signBit != 0 else 1) - exponent := u64((aAbs >> significandBits) - exponentBias) - significand := u64((aAbs & significandMask) | implicitBit) - - // If exponent is negative, the result is zero. - if exponent < 0 { - return 0 - } - - // If the value is too large for the integer type, saturate. - if exponent >= size_of(i128) * 8 { - return max(i128) if sign == 1 else min(i128) - } - - // If 0 <= exponent < significandBits, right shift to get the result. - // Otherwise, shift left. - if exponent < significandBits { - return sign * i128(significand >> (significandBits - exponent)) - } else { - return sign * (i128(significand) << (exponent - significandBits)) - } - -} - - - -__write_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) { - for i in 0..>3]) & (1<<(i&7)) != 0) - dst[j>>3] &~= 1<<(j&7) - dst[j>>3] |= the_bit<<(j&7) - } -} - -__read_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) { - for j in 0..>3]) & (1<<(i&7)) != 0) - dst[j>>3] &~= 1<<(j&7) - dst[j>>3] |= the_bit<<(j&7) - } -} - when .Address in ODIN_SANITIZER_FLAGS { foreign { + @(require) __asan_unpoison_memory_region :: proc "system" (address: rawptr, size: uint) --- } } - diff --git a/base/runtime/internal_i128.odin b/base/runtime/internal_i128.odin new file mode 100644 index 000000000..f4a0f90ed --- /dev/null +++ b/base/runtime/internal_i128.odin @@ -0,0 +1,217 @@ +#+vet !cast +#+build !bedrock +package runtime + +import "base:intrinsics" + +@(private="file") +IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 + +@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +floattidf :: proc "c" (a: i128) -> f64 { + DBL_MANT_DIG :: 53 + if a == 0 { + return 0.0 + } + a := a + N :: size_of(i128) * 8 + s := a >> (N-1) + a = (a ~ s) - s + sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits + e := i32(sd - 1) // exponent + if sd > DBL_MANT_DIG { + switch sd { + case DBL_MANT_DIG + 1: + a <<= 1 + case DBL_MANT_DIG + 2: + // okay + case: + a = i128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | + i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) + } + + a |= i128((a & 4) != 0) + a += 1 + a >>= 2 + + if a & (i128(1) << DBL_MANT_DIG) != 0 { + a >>= 1 + e += 1 + } + } else { + a <<= u128(DBL_MANT_DIG - sd) & 127 + } + fb: [2]u32 + fb[1] = (u32(s) & 0x80000000) | // sign + (u32(e + 1023) << 20) | // exponent + u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high + fb[0] = u32(a) // mantissa-low + return transmute(f64)fb +} + + +@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +floattidf_unsigned :: proc "c" (a: u128) -> f64 { + DBL_MANT_DIG :: 53 + if a == 0 { + return 0.0 + } + a := a + N :: size_of(u128) * 8 + sd: = N - intrinsics.count_leading_zeros(a) // number of significant digits + e := i32(sd - 1) // exponent + if sd > DBL_MANT_DIG { + switch sd { + case DBL_MANT_DIG + 1: + a <<= 1 + case DBL_MANT_DIG + 2: + // okay + case: + a = u128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) | + u128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0) + } + + a |= u128((a & 4) != 0) + a += 1 + a >>= 2 + + if a & (1 << DBL_MANT_DIG) != 0 { + a >>= 1 + e += 1 + } + } else { + a <<= u128(DBL_MANT_DIG - sd) + } + fb: [2]u32 + fb[1] = (0) | // sign + u32((e + 1023) << 20) | // exponent + u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high + fb[0] = u32(a) // mantissa-low + return transmute(f64)fb +} + + + +@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 { + // TODO(bill): implement `fixunsdfti` correctly + x := u64(a) + return u128(x) +} + +@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { + // TODO(bill): implement `fixunsdfdi` correctly + x := i64(a) + return i128(x) +} + + + + +@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +umodti3 :: proc "c" (a, b: u128) -> u128 { + r: u128 = --- + _ = udivmod128(a, b, &r) + return r +} + + +@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { + return udivmod128(a, b, rem) +} + +when !IS_WASM { + @(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) + udivti3 :: proc "c" (a, b: u128) -> u128 { + return udivmodti4(a, b, nil) + } +} + + +@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +modti3 :: proc "c" (a, b: i128) -> i128 { + s_a := a >> (128 - 1) + s_b := b >> (128 - 1) + an := (a ~ s_a) - s_a + bn := (b ~ s_b) - s_b + + r: u128 = --- + _ = udivmod128(u128(an), u128(bn), &r) + return (i128(r) ~ s_a) - s_a +} + + +@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { + s_a := a >> (128 - 1) // -1 if negative or 0 + s_b := b >> (128 - 1) + an := (a ~ s_a) - s_a // absolute + bn := (b ~ s_b) - s_b + + s_b ~= s_a // quotient sign + u_s_b := u128(s_b) + u_s_a := u128(s_a) + + r: u128 = --- + u := i128((udivmodti4(u128(an), u128(bn), &r) ~ u_s_b) - u_s_b) // negate if negative + rem^ = i128((r ~ u_s_a) - u_s_a) + return u +} + +@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +divti3 :: proc "c" (a, b: i128) -> i128 { + s_a := a >> (128 - 1) // -1 if negative or 0 + s_b := b >> (128 - 1) + an := (a ~ s_a) - s_a // absolute + bn := (b ~ s_b) - s_b + + s_a ~= s_b // quotient sign + u_s_a := u128(s_a) + + return i128((udivmodti4(u128(an), u128(bn), nil) ~ u_s_a) - u_s_a) // negate if negative +} + + +@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) +fixdfti :: proc "c" (a: u64) -> i128 { + significandBits :: 52 + typeWidth :: (size_of(u64)*8) + exponentBits :: (typeWidth - significandBits - 1) + maxExponent :: ((1 << exponentBits) - 1) + exponentBias :: (maxExponent >> 1) + + implicitBit :: (u64(1) << significandBits) + significandMask :: (implicitBit - 1) + signBit :: (u64(1) << (significandBits + exponentBits)) + absMask :: (signBit - 1) + exponentMask :: (absMask ~ significandMask) + + // Break a into sign, exponent, significand + aRep := a + aAbs := aRep & absMask + sign := i128(-1 if aRep & signBit != 0 else 1) + exponent := u64((aAbs >> significandBits) - exponentBias) + significand := u64((aAbs & significandMask) | implicitBit) + + // If exponent is negative, the result is zero. + if exponent < 0 { + return 0 + } + + // If the value is too large for the integer type, saturate. + if exponent >= size_of(i128) * 8 { + return max(i128) if sign == 1 else min(i128) + } + + // If 0 <= exponent < significandBits, right shift to get the result. + // Otherwise, shift left. + if exponent < significandBits { + return sign * i128(significand >> (significandBits - exponent)) + } else { + return sign * (i128(significand) << (exponent - significandBits)) + } + +} + diff --git a/base/runtime/os_specific.odin b/base/runtime/os_specific.odin index 2807eaf90..16e7e4751 100644 --- a/base/runtime/os_specific.odin +++ b/base/runtime/os_specific.odin @@ -2,6 +2,20 @@ package runtime _OS_Errno :: distinct int +HAS_RAND_BYTES :: _HAS_RAND_BYTES + stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return _stderr_write(data) } + +rand_bytes :: proc "contextless" (dst: []byte) { + when HAS_RAND_BYTES { + _rand_bytes(dst) + } else { + panic_contextless("base/runtime: no runtime entropy source") + } +} + +exit :: proc "contextless" (code: int) -> ! { + _exit(code) +} \ No newline at end of file diff --git a/base/runtime/os_specific_bsd.odin b/base/runtime/os_specific_bsd.odin index 466001ada..ab8eabb6c 100644 --- a/base/runtime/os_specific_bsd.odin +++ b/base/runtime/os_specific_bsd.odin @@ -4,6 +4,8 @@ package runtime foreign import libc "system:c" +_HAS_RAND_BYTES :: true + @(default_calling_convention="c") foreign libc { @(link_name="write") @@ -14,6 +16,8 @@ foreign libc { } else { __error :: proc() -> ^i32 --- } + + arc4random_buf :: proc(buf: [^]byte, nbytes: uint) --- } _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { @@ -24,3 +28,15 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { } return int(ret), 0 } + +_rand_bytes :: proc "contextless" (dst: []byte) { + arc4random_buf(raw_data(dst), len(dst)) +} + +_exit :: proc "contextless" (code: int) -> ! { + @(default_calling_convention="c") + foreign libc { + exit :: proc(status: i32) -> ! --- + } + exit(i32(code)) +} \ No newline at end of file diff --git a/base/runtime/os_specific_darwin.odin b/base/runtime/os_specific_darwin.odin index 907899d7c..576725a1c 100644 --- a/base/runtime/os_specific_darwin.odin +++ b/base/runtime/os_specific_darwin.odin @@ -4,6 +4,8 @@ package runtime import "base:intrinsics" +_HAS_RAND_BYTES :: true + _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { STDERR :: 2 when ODIN_NO_CRT { @@ -26,3 +28,25 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return 0, _OS_Errno(__error()^) } } + +foreign import libc "system:System" + +_rand_bytes :: proc "contextless" (dst: []byte) { + // This process used to use Security/RandomCopyBytes, however + // on every version of MacOS (>= 10.12) that we care about, + // arc4random is implemented securely. + + @(default_calling_convention="c") + foreign libc { + arc4random_buf :: proc(buf: [^]byte, nbytes: uint) --- + } + arc4random_buf(raw_data(dst), len(dst)) +} + +_exit :: proc "contextless" (code: int) -> ! { + @(default_calling_convention="c") + foreign libc { + exit :: proc(status: i32) -> ! --- + } + exit(i32(code)) +} \ No newline at end of file diff --git a/base/runtime/os_specific_freestanding.odin b/base/runtime/os_specific_freestanding.odin index f975f61b8..3b2b5a714 100644 --- a/base/runtime/os_specific_freestanding.odin +++ b/base/runtime/os_specific_freestanding.odin @@ -2,7 +2,13 @@ #+private package runtime +_HAS_RAND_BYTES :: false + // TODO(bill): reimplement `os.write` _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return 0, -1 } + +_exit :: proc "contextless" (code: int) -> ! { + trap() +} \ No newline at end of file diff --git a/base/runtime/os_specific_haiku.odin b/base/runtime/os_specific_haiku.odin deleted file mode 100644 index 0d1ec7a03..000000000 --- a/base/runtime/os_specific_haiku.odin +++ /dev/null @@ -1,21 +0,0 @@ -#+build haiku -#+private -package runtime - -foreign import libc "system:c" - -foreign libc { - @(link_name="write") - _unix_write :: proc(fd: i32, buf: rawptr, size: int) -> int --- - - _errnop :: proc() -> ^i32 --- -} - -_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { - ret := _unix_write(2, raw_data(data), len(data)) - if ret < len(data) { - err := _errnop() - return int(ret), _OS_Errno(err^ if err != nil else 0) - } - return int(ret), 0 -} diff --git a/base/runtime/os_specific_js.odin b/base/runtime/os_specific_js.odin index f1d12c808..8676f3a6e 100644 --- a/base/runtime/os_specific_js.odin +++ b/base/runtime/os_specific_js.odin @@ -4,6 +4,8 @@ package runtime foreign import "odin_env" +_HAS_RAND_BYTES :: true + _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { foreign odin_env { write :: proc "contextless" (fd: u32, p: []byte) --- @@ -11,3 +13,24 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { write(1, data) return len(data), 0 } + +_rand_bytes :: proc "contextless" (dst: []byte) { + foreign odin_env { + @(link_name = "rand_bytes") + env_rand_bytes :: proc "contextless" (buf: []byte) --- + } + + MAX_PER_CALL_BYTES :: 65536 // 64kiB + + dst := dst + for len(dst) > 0 { + to_read := min(len(dst), MAX_PER_CALL_BYTES) + env_rand_bytes(dst[:to_read]) + + dst = dst[to_read:] + } +} + +_exit :: proc "contextless" (code: int) -> ! { + trap() +} \ No newline at end of file diff --git a/base/runtime/os_specific_linux.odin b/base/runtime/os_specific_linux.odin index d7b7371a7..1abcc03e5 100644 --- a/base/runtime/os_specific_linux.odin +++ b/base/runtime/os_specific_linux.odin @@ -3,6 +3,8 @@ package runtime import "base:intrinsics" +_HAS_RAND_BYTES :: true + _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { when ODIN_ARCH == .amd64 { SYS_write :: uintptr(1) @@ -24,3 +26,64 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { } return ret, 0 } + +_rand_bytes :: proc "contextless" (dst: []byte) { + when ODIN_ARCH == .amd64 { + SYS_getrandom :: uintptr(318) + } else when ODIN_ARCH == .arm64 { + SYS_getrandom :: uintptr(278) + } else when ODIN_ARCH == .i386 { + SYS_getrandom :: uintptr(355) + } else when ODIN_ARCH == .arm32 { + SYS_getrandom :: uintptr(384) + } else when ODIN_ARCH == .riscv64 { + SYS_getrandom :: uintptr(278) + } else { + #panic("base/runtime: no SYS_getrandom definition for target") + } + + ERR_EINTR :: 4 + ERR_ENOSYS :: 38 + + MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1 + + dst := dst + l := len(dst) + + for l > 0 { + to_read := min(l, MAX_PER_CALL_BYTES) + ret := int(intrinsics.syscall(SYS_getrandom, uintptr(raw_data(dst[:to_read])), uintptr(to_read), uintptr(0))) + switch ret { + case -ERR_EINTR: + // Call interupted by a signal handler, just retry the + // request. + continue + case -ERR_ENOSYS: + // The kernel is apparently prehistoric (< 3.17 circa 2014) + // and does not support getrandom. + panic_contextless("base/runtime: getrandom not available in kernel") + case: + if ret < 0 { + // All other failures are things that should NEVER happen + // unless the kernel interface changes (ie: the Linux + // developers break userland). + panic_contextless("base/runtime: getrandom failed") + } + } + l -= ret + dst = dst[ret:] + } +} + +_exit :: proc "contextless" (code: int) -> ! { + SYS_exit_group :: + 231 when ODIN_ARCH == .amd64 else + 248 when ODIN_ARCH == .arm32 else + 94 when ODIN_ARCH == .arm64 else + 252 when ODIN_ARCH == .i386 else + 94 when ODIN_ARCH == .riscv64 else + 0 + + intrinsics.syscall(uintptr(SYS_exit_group), uintptr(i32(code))) + unreachable() +} diff --git a/base/runtime/os_specific_orca.odin b/base/runtime/os_specific_orca.odin index 876d7d44b..f5ce50411 100644 --- a/base/runtime/os_specific_orca.odin +++ b/base/runtime/os_specific_orca.odin @@ -4,6 +4,8 @@ package runtime import "base:intrinsics" +_HAS_RAND_BYTES :: false + // Constants allowing to specify the level of logging verbosity. log_level :: enum u32 { // Only errors are logged. @@ -41,3 +43,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return len(data), 0 } + + +_exit :: proc "contextless" (code: int) -> ! { + trap() +} \ No newline at end of file diff --git a/base/runtime/os_specific_wasi.odin b/base/runtime/os_specific_wasi.odin index aa562050c..c5e94653a 100644 --- a/base/runtime/os_specific_wasi.odin +++ b/base/runtime/os_specific_wasi.odin @@ -4,6 +4,8 @@ package runtime foreign import wasi "wasi_snapshot_preview1" +_HAS_RAND_BYTES :: true + @(default_calling_convention="contextless") foreign wasi { fd_write :: proc( @@ -23,6 +25,12 @@ foreign wasi { argv: [^]cstring, argv_buf: [^]byte, ) -> u16 --- + + @(private="file") + proc_exit :: proc(rval: u32) -> ! --- + + @(private ="file") + random_get :: proc(buf: []u8) -> u16 --- } _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { @@ -31,6 +39,12 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return int(n), _OS_Errno(err) } +_rand_bytes :: proc "contextless" (dst: []byte) { + if errno := random_get(dst); errno != 0 { + panic_contextless("base/runtime: wasi.random_get failed") + } +} + _wasi_setup_args :: proc() { num_of_args, size_of_args: uint if errno := args_sizes_get(&num_of_args, &size_of_args); errno != 0 { @@ -53,3 +67,8 @@ _wasi_setup_args :: proc() { delete(args_buf) } } + + +_exit :: proc "contextless" (code: int) -> ! { + proc_exit(u32(code)) +} \ No newline at end of file diff --git a/base/runtime/os_specific_windows.odin b/base/runtime/os_specific_windows.odin index b966193ca..d938e87ea 100644 --- a/base/runtime/os_specific_windows.odin +++ b/base/runtime/os_specific_windows.odin @@ -2,8 +2,11 @@ #+private package runtime +foreign import bcrypt "system:Bcrypt.lib" foreign import kernel32 "system:Kernel32.lib" +_HAS_RAND_BYTES :: true + @(private="file") @(default_calling_convention="system") foreign kernel32 { @@ -14,6 +17,14 @@ foreign kernel32 { SetHandleInformation :: proc(hObject: rawptr, dwMask: u32, dwFlags: u32) -> b32 --- WriteFile :: proc(hFile: rawptr, lpBuffer: rawptr, nNumberOfBytesToWrite: u32, lpNumberOfBytesWritten: ^u32, lpOverlapped: rawptr) -> b32 --- GetLastError :: proc() -> u32 --- + + ExitProcess :: proc(code: u32) -> ! --- +} + +@(private="file") +@(default_calling_convention="system") +foreign bcrypt { + BCryptGenRandom :: proc(hAlgorithm: rawptr, pBuffer: [^]u8, cbBuffer: u32, dwFlags: u32) -> i32 --- } _stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #no_bounds_check { @@ -49,3 +60,31 @@ _stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) # n = int(total_write) return } + +_rand_bytes :: proc "contextless" (dst: []byte) { + ensure_contextless(u64(len(dst)) <= u64(max(u32)), "base/runtime: oversized rand_bytes request") + + BCRYPT_USE_SYSTEM_PREFERRED_RNG :: 0x00000002 + + ERROR_INVALID_HANDLE :: 6 + ERROR_INVALID_PARAMETER :: 87 + + ret := BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), BCRYPT_USE_SYSTEM_PREFERRED_RNG) + switch ret { + case 0: + case ERROR_INVALID_HANDLE: + // The handle to the first parameter is invalid. + // This should not happen here, since we explicitly pass nil to it + panic_contextless("base/runtime: BCryptGenRandom Invalid handle for hAlgorithm") + case ERROR_INVALID_PARAMETER: + // One of the parameters was invalid + panic_contextless("base/runtime: BCryptGenRandom Invalid parameter") + case: + // Unknown error + panic_contextless("base/runtime: BCryptGenRandom failed") + } +} + +_exit :: proc "contextless" (code: int) -> ! { + ExitProcess(u32(code)) +} \ No newline at end of file diff --git a/base/runtime/print.odin b/base/runtime/print.odin index c28fd593d..ad205d887 100644 --- a/base/runtime/print.odin +++ b/base/runtime/print.odin @@ -184,10 +184,11 @@ print_rune :: #force_no_inline proc "contextless" (r: rune) -> int #no_bounds_ch print_u64 :: #force_no_inline proc "contextless" (x: u64) #no_bounds_check { + b :: u64(10) + u := x + a: [129]byte i := len(a) - b := u64(10) - u := x for u >= b { i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b] u /= b @@ -199,11 +200,9 @@ print_u64 :: #force_no_inline proc "contextless" (x: u64) #no_bounds_check { print_i64 :: #force_no_inline proc "contextless" (x: i64) #no_bounds_check { - b :: i64(10) - - u := x - neg := u < 0 - u = abs(u) + b :: u64(10) + u := u64(abs(x)) + neg := x < 0 a: [129]byte i := len(a) @@ -281,11 +280,22 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_byte('i' if info.signed else 'u') print_u64(u64(8*ti.size)) } + switch info.endianness { + case .Platform: // nothing + case .Little: print_string("le") + case .Big: print_string("be") + } + case Type_Info_Rune: print_string("rune") case Type_Info_Float: print_byte('f') print_u64(u64(8*ti.size)) + switch info.endianness { + case .Platform: // nothing + case .Little: print_string("le") + case .Big: print_string("be") + } case Type_Info_Complex: print_string("complex") print_u64(u64(8*ti.size)) @@ -293,7 +303,14 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_string("quaternion") print_u64(u64(8*ti.size)) case Type_Info_String: + if info.is_cstring { + print_byte('c') + } print_string("string") + switch info.encoding { + case .UTF_8: /**/ + case .UTF_16: print_string("16") + } case Type_Info_Boolean: switch ti.id { case bool: print_string("bool") @@ -375,6 +392,12 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_string("[]") print_type(info.elem) + case Type_Info_Fixed_Capacity_Dynamic_Array: + print_string("[dynamic; ") + print_u64(u64(info.capacity)) + print_string("]") + print_type(info.elem) + case Type_Info_Map: print_string("map[") print_type(info.key) @@ -401,9 +424,10 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_string("struct ") - if .packed in info.flags { print_string("#packed ") } - if .raw_union in info.flags { print_string("#raw_union ") } - if .no_copy in info.flags { print_string("#no_copy ") } + if .packed in info.flags { print_string("#packed ") } + if .raw_union in info.flags { print_string("#raw_union ") } + if .all_or_none in info.flags { print_string("#all_or_none ") } + if .simple in info.flags { print_string("#simple ") } if .align in info.flags { print_string("#align(") print_u64(u64(ti.align)) @@ -460,7 +484,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_string("..") print_i64(info.upper) } - if info.underlying != nil { + if info.explicit_underlying { print_string("; ") print_type(info.underlying) } @@ -488,6 +512,9 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_type(info.elem) case Type_Info_Matrix: + if info.layout == .Row_Major { + print_string("#row_major ") + } print_string("matrix[") print_u64(u64(info.row_count)) print_string(", ") @@ -496,3 +523,425 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_type(info.elem) } } + + +@(require_results) +write_string :: proc "contextless" (i: ^int, dst: []byte, src: string) -> bool { + if i^ < len(dst) { + i^ += copy(dst[i^:], src) + return true + } + return false +} + + +@(require_results) +write_byte :: proc "contextless" (i: ^int, dst: []byte, src: byte) -> bool { + if i^ < len(dst) { + dst[i^] = src + i^ += 1 + return true + } + return false +} + + +@(require_results) +write_u64 :: proc "contextless" (j: ^int, dst: []byte, x: u64) -> bool { + if j^ < len(dst) { + b :: u64(10) + u := x + + a: [129]byte + i := len(a) + for u >= b { + i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b] + u /= b + } + i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b] + + return write_string(j, dst, string(a[i:])) + } + return false +} + +@(require_results) +write_i64 :: proc "contextless" (j: ^int, dst: []byte, x: i64) -> bool { + if j^ < len(dst) { + b :: u64(10) + u := u64(abs(x)) + neg := x < 0 + + a: [129]byte + i := len(a) + for u >= b { + i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b] + u /= b + } + i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b] + if neg { + i -= 1; a[i] = '-' + } + + return write_string(j, dst, string(a[i:])) + } + return false +} + + +@(require_results) +write_caller_location :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, loc: Source_Code_Location) -> bool { + write_string(i, buf, loc.file_path) or_return + + when ODIN_ERROR_POS_STYLE == .Default { + write_byte(i, buf, '(') or_return + write_u64 (i, buf, u64(loc.line)) or_return + if loc.column != 0 { + write_byte(i, buf, ':') or_return + write_u64 (i, buf, u64(loc.column)) or_return + } + write_byte(i, buf, ')') or_return + return true + } else when ODIN_ERROR_POS_STYLE == .Unix { + write_byte(i, buf, ':') or_return + write_u64 (i, buf, u64(loc.line)) or_return + if loc.column != 0 { + write_byte(i, buf, ':') or_return + write_u64 (i, buf, u64(loc.column)) or_return + } + write_byte(i, buf, ':') or_return + return true + } else { + #panic("unhandled ODIN_ERROR_POS_STYLE") + } +} + +@(require_results) +write_typeid :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, id: typeid) -> bool { + when ODIN_NO_RTTI { + if id == nil { + write_string(i, buf, "nil") or_return + } else { + write_string(i, buf, "") or_return + } + } else { + if id == nil { + write_string(i, buf, "nil") or_return + } else { + ti := type_info_of(id) + write_write_type(i, buf, ti) or_return + } + } + return true +} + + +@(require_results) +write_rune :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, r: rune) -> (written: int, ok: bool) #no_bounds_check { + RUNE_SELF :: 0x80 + + if r < RUNE_SELF { + write_byte(i, buf,byte(r)) or_return + return 1, true + } + + b, n := encode_rune(r) + prev := i^ + write_string(i, buf, string(b[:n])) or_return + return i^ - prev, true +} + +@(require_results) +write_encoded_rune :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, r: rune) -> bool { + write_byte(i, buf, '\'') or_return + + switch r { + case '\a': write_string(i, buf, "\\a") or_return + case '\b': write_string(i, buf, "\\b") or_return + case '\e': write_string(i, buf, "\\e") or_return + case '\f': write_string(i, buf, "\\f") or_return + case '\n': write_string(i, buf, "\\n") or_return + case '\r': write_string(i, buf, "\\r") or_return + case '\t': write_string(i, buf, "\\t") or_return + case '\v': write_string(i, buf, "\\v") or_return + case: + if r <= 0 { + write_string(i, buf, "\\x00") or_return + } else if r < 32 { + n0, n1 := u8(r) >> 4, u8(r) & 0xf + write_string(i, buf, "\\x") or_return + write_byte (i, buf, _INTEGER_DIGITS_VAR[n0]) or_return + write_byte (i, buf, _INTEGER_DIGITS_VAR[n1]) or_return + } else { + _ = write_rune(i, buf, r) or_return + } + } + + write_byte(i, buf, '\'') or_return + return true +} + +@(optimization_mode="favor_size") +write_write_type :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, ti: ^Type_Info) -> bool { + if ti == nil { + write_string(i, buf, "nil") or_return + return true + } + + switch info in ti.variant { + case Type_Info_Named: + write_string(i, buf, info.name) or_return + case Type_Info_Integer: + switch ti.id { + case int: write_string(i, buf, "int") or_return + case uint: write_string(i, buf, "uint") or_return + case uintptr: write_string(i, buf, "uintptr") or_return + case: + write_byte(i, buf, 'i' if info.signed else 'u') or_return + write_u64 (i, buf, u64(8*ti.size)) or_return + } + switch info.endianness { + case .Platform: // nothing + case .Little: write_string(i, buf, "le") or_return + case .Big: write_string(i, buf, "be") or_return + } + + case Type_Info_Rune: + write_string(i, buf, "rune") or_return + case Type_Info_Float: + write_byte(i, buf, 'f') or_return + write_u64(i, buf, u64(8*ti.size)) or_return + switch info.endianness { + case .Platform: // nothing + case .Little: write_string(i, buf, "le") or_return + case .Big: write_string(i, buf, "be") or_return + } + + case Type_Info_Complex: + write_string(i, buf, "complex") or_return + write_u64 (i, buf, u64(8*ti.size)) or_return + case Type_Info_Quaternion: + write_string(i, buf, "quaternion") or_return + write_u64 (i, buf, u64(8*ti.size)) or_return + case Type_Info_String: + if info.is_cstring { + write_byte(i, buf, 'c') or_return + } + write_string(i, buf, "string") or_return + switch info.encoding { + case .UTF_8: /**/ + case .UTF_16: write_string(i, buf, "16") or_return + } + case Type_Info_Boolean: + switch ti.id { + case bool: write_string(i, buf, "bool") or_return + case: + write_byte(i, buf, 'b') or_return + write_u64 (i, buf, u64(8*ti.size)) or_return + } + case Type_Info_Any: + write_string(i, buf, "any") or_return + case Type_Info_Type_Id: + write_string(i, buf, "typeid") or_return + + case Type_Info_Pointer: + if info.elem == nil { + write_string(i, buf, "rawptr") or_return + } else { + write_string (i, buf, "^") or_return + write_write_type(i, buf, info.elem) or_return + } + case Type_Info_Multi_Pointer: + write_string (i, buf, "[^]") or_return + write_write_type(i, buf, info.elem) or_return + case Type_Info_Soa_Pointer: + write_string (i, buf, "#soa ^") or_return + write_write_type(i, buf, info.elem) or_return + case Type_Info_Procedure: + write_string(i, buf, "proc") or_return + if info.params == nil { + write_string(i, buf, "()") or_return + } else { + t := info.params.variant.(Type_Info_Parameters) + write_byte(i, buf, '(') or_return + for t, j in t.types { + if j > 0 { write_string(i, buf, ", ") or_return } + write_write_type(i, buf, t) or_return + } + write_string(i, buf, ")") or_return + } + if info.results != nil { + write_string (i, buf, " -> ") or_return + write_write_type(i, buf, info.results) or_return + } + case Type_Info_Parameters: + count := len(info.names) + if count != 1 { write_byte(i, buf, '(') or_return } + for name, j in info.names { + if j > 0 { write_string(i, buf, ", ") or_return } + + t := info.types[j] + + if len(name) > 0 { + write_string(i, buf, name) or_return + write_string(i, buf, ": ") or_return + } + write_write_type(i, buf, t) or_return + } + if count != 1 { write_string(i, buf, ")") or_return } + + case Type_Info_Array: + write_byte (i, buf, '[') or_return + write_u64 (i, buf, u64(info.count)) or_return + write_byte (i, buf, ']') or_return + write_write_type(i, buf, info.elem) or_return + + case Type_Info_Enumerated_Array: + if info.is_sparse { + write_string(i, buf, "#sparse") or_return + } + write_byte (i, buf, '[') or_return + write_write_type(i, buf, info.index) or_return + write_byte (i, buf, ']') or_return + write_write_type(i, buf, info.elem) or_return + + + case Type_Info_Dynamic_Array: + write_string (i, buf, "[dynamic]") or_return + write_write_type(i, buf, info.elem) or_return + case Type_Info_Slice: + write_string (i, buf, "[]") or_return + write_write_type(i, buf, info.elem) or_return + + case Type_Info_Fixed_Capacity_Dynamic_Array: + write_string (i, buf, "[dynamic; ") or_return + write_u64 (i, buf, u64(info.capacity)) or_return + write_string (i, buf, "]") or_return + write_write_type(i, buf, info.elem) or_return + + case Type_Info_Map: + write_string (i, buf, "map[") or_return + write_write_type(i, buf, info.key) or_return + write_byte (i, buf, ']') or_return + write_write_type(i, buf, info.value) or_return + + case Type_Info_Struct: + switch info.soa_kind { + case .None: // Ignore + case .Fixed: + write_string (i, buf, "#soa[") or_return + write_u64 (i, buf, u64(info.soa_len)) or_return + write_byte (i, buf, ']') or_return + write_write_type(i, buf, info.soa_base_type) or_return + return true + case .Slice: + write_string (i, buf, "#soa[]") or_return + write_write_type(i, buf, info.soa_base_type) or_return + return true + case .Dynamic: + write_string (i, buf, "#soa[dynamic]") or_return + write_write_type(i, buf, info.soa_base_type) or_return + return true + } + + write_string(i, buf, "struct ") or_return + if .packed in info.flags { write_string(i, buf, "#packed ") or_return } + if .raw_union in info.flags { write_string(i, buf, "#raw_union ") or_return } + if .all_or_none in info.flags { write_string(i, buf, "#all_or_none ") or_return } + if .simple in info.flags { write_string(i, buf, "#simple ") or_return } + if .align in info.flags { + write_string(i, buf, "#align(") or_return + write_u64(i, buf, u64(ti.align)) or_return + write_string(i, buf, ") ") or_return + } + write_byte(i, buf, '{') or_return + for name, j in info.names[:info.field_count] { + if j > 0 { write_string(i, buf, ", ") or_return } + write_string (i, buf, name) or_return + write_string (i, buf, ": ") or_return + write_write_type(i, buf, info.types[j]) or_return + } + write_byte(i, buf, '}') or_return + + case Type_Info_Union: + write_string(i, buf, "union ") or_return + if info.custom_align { + write_string(i, buf, "#align(") or_return + write_u64 (i, buf, u64(ti.align)) or_return + write_string(i, buf, ") ") or_return + } + if info.no_nil { + write_string(i, buf, "#no_nil ") or_return + } + write_byte(i, buf, '{') or_return + for variant, j in info.variants { + if j > 0 { write_string(i, buf, ", ") or_return } + write_write_type(i, buf, variant) or_return + } + write_string(i, buf, "}") or_return + + case Type_Info_Enum: + write_string (i, buf, "enum ") or_return + write_write_type(i, buf, info.base) or_return + write_string (i, buf, " {") or_return + for name, j in info.names { + if j > 0 { write_string(i, buf, ", ") or_return } + write_string(i, buf, name) or_return + } + write_string(i, buf, "}") or_return + + case Type_Info_Bit_Set: + write_string(i, buf, "bit_set[") or_return + + #partial switch elem in type_info_base(info.elem).variant { + case Type_Info_Enum: + write_write_type(i, buf, info.elem) or_return + case Type_Info_Rune: + write_encoded_rune(i, buf, rune(info.lower)) or_return + write_string (i, buf, "..") or_return + write_encoded_rune(i, buf, rune(info.upper)) or_return + case: + write_i64 (i, buf, info.lower) or_return + write_string(i, buf, "..") or_return + write_i64 (i, buf, info.upper) or_return + } + if info.explicit_underlying { + write_string (i, buf, "; ") or_return + write_write_type(i, buf, info.underlying) or_return + } + write_byte(i, buf, ']') or_return + + case Type_Info_Bit_Field: + write_string (i, buf, "bit_field ") or_return + write_write_type(i, buf, info.backing_type) or_return + write_string (i, buf, " {") or_return + for name, j in info.names[:info.field_count] { + if j > 0 { write_string(i, buf, ", ") or_return } + write_string (i, buf, name) or_return + write_string (i, buf, ": ") or_return + write_write_type(i, buf, info.types[j]) or_return + write_string (i, buf, " | ") or_return + write_u64 (i, buf, u64(info.bit_sizes[j])) or_return + } + write_byte(i, buf, '}') or_return + + + case Type_Info_Simd_Vector: + write_string (i, buf, "#simd[") or_return + write_u64 (i, buf, u64(info.count)) or_return + write_byte (i, buf, ']') or_return + write_write_type(i, buf, info.elem) or_return + + case Type_Info_Matrix: + if info.layout == .Row_Major { + write_string(i, buf, "#row_major ") or_return + } + write_string (i, buf, "matrix[") or_return + write_u64 (i, buf, u64(info.row_count)) or_return + write_string (i, buf, ", ") or_return + write_u64 (i, buf, u64(info.column_count)) or_return + write_string (i, buf, "]") or_return + write_write_type(i, buf, info.elem) or_return + } + return true +} \ No newline at end of file diff --git a/base/runtime/procs_darwin.odin b/base/runtime/procs_darwin.odin index 0aec57e80..0ffe68e49 100644 --- a/base/runtime/procs_darwin.odin +++ b/base/runtime/procs_darwin.odin @@ -1,9 +1,12 @@ #+private package runtime -@(priority_index=-1e6) +@(priority_index=-1e5) foreign import ObjC "system:objc" +@(priority_index=-1e6) +foreign import libSystem "system:System" + import "base:intrinsics" objc_id :: ^intrinsics.objc_object @@ -12,16 +15,25 @@ objc_SEL :: ^intrinsics.objc_selector objc_Ivar :: ^intrinsics.objc_ivar objc_BOOL :: bool +objc_super :: struct { + receiver: objc_id, + super_class: objc_Class, +} objc_IMP :: proc "c" (object: objc_id, sel: objc_SEL, #c_vararg args: ..any) -> objc_id foreign ObjC { sel_registerName :: proc "c" (name: cstring) -> objc_SEL --- - objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) --- - objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 --- - objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 --- - objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) --- + objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) --- + objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 --- + objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 --- + objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) --- + + // See: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-abi.h#L111 + objc_msgSendSuper2 :: proc "c" (super: rawptr, op: objc_SEL, #c_vararg args: ..any) -> objc_id --- + objc_msgSendSuper2_stret :: proc "c" (super: ^objc_super, op: objc_SEL, #c_vararg args: ..any) --- + objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class --- objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class --- @@ -30,6 +42,15 @@ foreign ObjC { class_addIvar :: proc "c" (cls: objc_Class, name: cstring, size: uint, alignment: u8, types: cstring) -> objc_BOOL --- class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar --- class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint --- + class_getSuperclass :: proc "c" (cls : objc_Class) -> objc_Class --- ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr --- + object_getClass :: proc "c" (obj: objc_id) -> objc_Class --- } +foreign libSystem { + _NSConcreteGlobalBlock: intrinsics.objc_class + _NSConcreteStackBlock: intrinsics.objc_class + + _Block_object_assign :: proc "c" (rawptr, rawptr, i32) --- + _Block_object_dispose :: proc "c" (rawptr, i32) --- +} diff --git a/base/runtime/procs_js.odin b/base/runtime/procs_js.odin index 58bed808d..3690f9436 100644 --- a/base/runtime/procs_js.odin +++ b/base/runtime/procs_js.odin @@ -3,8 +3,8 @@ package runtime init_default_context_for_js: Context @(init, private="file") -init_default_context :: proc() { - init_default_context_for_js = context +init_default_context :: proc "contextless" () { + __init_context(&init_default_context_for_js) } @(export) diff --git a/base/runtime/random_generator.odin b/base/runtime/random_generator.odin index 81432b330..7d873fe33 100644 --- a/base/runtime/random_generator.odin +++ b/base/runtime/random_generator.odin @@ -41,88 +41,3 @@ random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) { rg.procedure(rg.data, .Reset, ([^]byte)(&p)[:size_of(p)]) } } - - -Default_Random_State :: struct { - state: u64, - inc: u64, -} - -default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) { - @(require_results) - read_u64 :: proc "contextless" (r: ^Default_Random_State) -> u64 { - old_state := r.state - r.state = old_state * 6364136223846793005 + (r.inc|1) - xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081 - rot := (old_state >> 59) - return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63)) - } - - @(thread_local) - global_rand_seed: Default_Random_State - - init :: proc "contextless" (r: ^Default_Random_State, seed: u64) { - seed := seed - if seed == 0 { - seed = u64(intrinsics.read_cycle_counter()) - } - r.state = 0 - r.inc = (seed << 1) | 1 - _ = read_u64(r) - r.state += seed - _ = read_u64(r) - } - - r: ^Default_Random_State = --- - if data == nil { - r = &global_rand_seed - } else { - r = cast(^Default_Random_State)data - } - - switch mode { - case .Read: - if r.state == 0 && r.inc == 0 { - init(r, 0) - } - - switch len(p) { - case size_of(u64): - // Fast path for a 64-bit destination. - intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r)) - case: - // All other cases. - pos := i8(0) - val := u64(0) - for &v in p { - if pos == 0 { - val = read_u64(r) - pos = 7 - } - v = byte(val) - val >>= 8 - pos -= 1 - } - } - - case .Reset: - seed: u64 - mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p))) - init(r, seed) - - case .Query_Info: - if len(p) != size_of(Random_Generator_Query_Info) { - return - } - info := (^Random_Generator_Query_Info)(raw_data(p)) - info^ += {.Uniform, .Resettable} - } -} - -@(require_results) -default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator { - return { - procedure = default_random_generator_proc, - data = state, - } -} \ No newline at end of file diff --git a/base/runtime/random_generator_chacha8.odin b/base/runtime/random_generator_chacha8.odin new file mode 100644 index 000000000..02acb4e9f --- /dev/null +++ b/base/runtime/random_generator_chacha8.odin @@ -0,0 +1,164 @@ +package runtime + +import "base:intrinsics" + +// This is an implementation of the Chacha8Rand DRBG, as specified +// in https://github.com/C2SP/C2SP/blob/main/chacha8rand.md +// +// There is a tradeoff to be made between state-size and performance, +// in terms of the amount of rng output buffered. +// +// The sensible buffer sizes are: +// - 256-bytes: 128-bit SIMD with 16x vector registers (SSE2) +// - 512-bytes: 128-bit SIMD with 32x vector registers (ARMv8), +// 256-bit SIMD with 16x vector registers (AVX2), +// - 1024-bytes: AVX-512 +// +// Notes: +// - Smaller than 256-bytes is possible but would require redundant +// calls to the ChaCha8 function, which is prohibitively expensive. +// - Larger than 1024-bytes is possible but pointless as the construct +// is defined around 992-bytes of RNG output and 32-bytes of input +// per iteration. +// +// This implementation opts for a 1024-byte buffer for simplicity, +// under the rationale that modern extremely memory constrained targets +// provide suitable functionality in hardware, and the language makes +// supporting the various SIMD flavors easy. + +@(private = "file") +RNG_SEED_SIZE :: 32 +@(private) +RNG_OUTPUT_PER_ITER :: 1024 - RNG_SEED_SIZE + +@(private) +CHACHA_SIGMA_0: u32 : 0x61707865 +@(private) +CHACHA_SIGMA_1: u32 : 0x3320646e +@(private) +CHACHA_SIGMA_2: u32 : 0x79622d32 +@(private) +CHACHA_SIGMA_3: u32 : 0x6b206574 +@(private) +CHACHA_ROUNDS :: 8 + +Default_Random_State :: struct { + _buf: [1024]byte, + _off: int, + _seeded: bool, +} + +@(require_results) +default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator { + return { + procedure = default_random_generator_proc, + data = state, + } +} + +default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) { + @(thread_local) + state: Default_Random_State + + r: ^Default_Random_State = &state + if data != nil { + r = cast(^Default_Random_State)data + } + next_seed := r._buf[RNG_OUTPUT_PER_ITER:] + + switch mode { + case .Read: + if !r._seeded { // Unlikely. + rand_bytes(next_seed) + r._off = RNG_OUTPUT_PER_ITER // Force refill. + r._seeded = true + } + + assert(r._off <= RNG_OUTPUT_PER_ITER, "chacha8rand/BUG: outputed key material") + if r._off >= RNG_OUTPUT_PER_ITER { // Unlikely. + chacha8rand_refill(r) + } + + // We are guaranteed to have at least some RNG output buffered. + // + // As an invariant each read will consume a multiple of 8-bytes + // of output at a time. + assert(r._off <= RNG_OUTPUT_PER_ITER - 8, "chacha8rand/BUG: less than 8-bytes of output available") + assert(r._off % 8 == 0, "chacha8rand/BUG: buffered output is not a multiple of 8-bytes") + + p_len := len(p) + if p_len == size_of(u64) { + #no_bounds_check { + // Fast path for a 64-bit destination. + src := (^u64)(raw_data(r._buf[r._off:])) + intrinsics.unaligned_store((^u64)(raw_data(p)), src^) + src^ = 0 // Erasure (backtrack resistance) + r._off += 8 + } + return + } + + p_ := p + for remaining := p_len; remaining > 0; { + sz := min(remaining, RNG_OUTPUT_PER_ITER - r._off) + #no_bounds_check { + copy(p_[:sz], r._buf[r._off:]) + p_ = p_[sz:] + remaining -= sz + } + rounded_sz := ((sz + 7) / 8) * 8 + new_off := r._off + rounded_sz + #no_bounds_check if new_off < RNG_OUTPUT_PER_ITER { + // Erasure (backtrack resistance) + intrinsics.mem_zero(raw_data(r._buf[r._off:]), rounded_sz) + r._off = new_off + } else { + // Can omit erasure since we are overwriting the entire + // buffer. + chacha8rand_refill(r) + } + } + + case .Reset: + // If no seed is passed, the next call to .Read will attempt to + // reseed from the system entropy source. + if len(p) == 0 { + r._seeded = false + return + } + + // The cryptographic security of the output depends entirely + // on the quality of the entropy in the seed, we will allow + // re-seeding (as it makes testing easier), but callers that + // decide to provide arbitrary seeds are on their own as far + // as ensuring high-quality entropy. + intrinsics.mem_zero(raw_data(next_seed), RNG_SEED_SIZE) + copy(next_seed, p) + r._seeded = true + r._off = RNG_OUTPUT_PER_ITER // Force a refill. + + case .Query_Info: + if len(p) != size_of(Random_Generator_Query_Info) { + return + } + info := (^Random_Generator_Query_Info)(raw_data(p)) + info^ += {.Uniform, .Cryptographic, .Resettable} + } +} + +@(private = "file") +chacha8rand_refill :: proc(r: ^Default_Random_State) { + assert(r._seeded == true, "chacha8rand/BUG: unseeded refill") + + // i386 has insufficient vector registers to use the + // accelerated path at the moment. + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + chacha8rand_refill_simd256(r) + } else when HAS_HARDWARE_SIMD && ODIN_ARCH != .i386 { + chacha8rand_refill_simd128(r) + } else { + chacha8rand_refill_ref(r) + } + + r._off = 0 +} diff --git a/base/runtime/random_generator_chacha8_ref.odin b/base/runtime/random_generator_chacha8_ref.odin new file mode 100644 index 000000000..b1e812c3f --- /dev/null +++ b/base/runtime/random_generator_chacha8_ref.odin @@ -0,0 +1,145 @@ +package runtime + +import "base:intrinsics" + +@(private) +chacha8rand_refill_ref :: proc(r: ^Default_Random_State) { + // Initialize the base state. + k: [^]u32 = (^u32)(raw_data(r._buf[RNG_OUTPUT_PER_ITER:])) + when ODIN_ENDIAN == .Little { + s4 := k[0] + s5 := k[1] + s6 := k[2] + s7 := k[3] + s8 := k[4] + s9 := k[5] + s10 := k[6] + s11 := k[7] + } else { + s4 := intrinsics.byte_swap(k[0]) + s5 := intrinsics.byte_swap(k[1]) + s6 := intrinsics.byte_swap(k[2]) + s7 := intrinsics.byte_swap(k[3]) + s8 := intrinsics.byte_swap(k[4]) + s9 := intrinsics.byte_swap(k[5]) + s10 := intrinsics.byte_swap(k[6]) + s11 := intrinicss.byte_swap(k[7]) + } + s12: u32 // Counter starts at 0. + s13, s14, s15: u32 // IV of all 0s. + + dst: [^]u32 = (^u32)(raw_data(r._buf[:])) + + // At least with LLVM21 force_inline produces identical perf to + // manual inlining, yay. + quarter_round := #force_inline proc "contextless" (a, b, c, d: u32) -> (u32, u32, u32, u32) { + a, b, c, d := a, b, c, d + + a += b + d ~= a + d = rotl(d, 16) + + c += d + b ~= c + b = rotl(b, 12) + + a += b + d ~= a + d = rotl(d, 8) + + c += d + b ~= c + b = rotl(b, 7) + + return a, b, c, d + } + + // Filippo Valsorda made an observation that only one of the column + // round depends on the counter (s12), so it is worth precomputing + // and reusing across multiple blocks. As far as I know, only Go's + // chacha implementation does this. + + p1, p5, p9, p13 := quarter_round(CHACHA_SIGMA_1, s5, s9, s13) + p2, p6, p10, p14 := quarter_round(CHACHA_SIGMA_2, s6, s10, s14) + p3, p7, p11, p15 := quarter_round(CHACHA_SIGMA_3, s7, s11, s15) + + // 4 groups + for g := 0; g < 4; g = g + 1 { + // 4 blocks per group + for n := 0; n < 4; n = n + 1 { + // First column round that depends on the counter + p0, p4, p8, p12 := quarter_round(CHACHA_SIGMA_0, s4, s8, s12) + + // First diagonal round + x0, x5, x10, x15 := quarter_round(p0, p5, p10, p15) + x1, x6, x11, x12 := quarter_round(p1, p6, p11, p12) + x2, x7, x8, x13 := quarter_round(p2, p7, p8, p13) + x3, x4, x9, x14 := quarter_round(p3, p4, p9, p14) + + for i := CHACHA_ROUNDS - 2; i > 0; i = i - 2 { + x0, x4, x8, x12 = quarter_round(x0, x4, x8, x12) + x1, x5, x9, x13 = quarter_round(x1, x5, x9, x13) + x2, x6, x10, x14 = quarter_round(x2, x6, x10, x14) + x3, x7, x11, x15 = quarter_round(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarter_round(x0, x5, x10, x15) + x1, x6, x11, x12 = quarter_round(x1, x6, x11, x12) + x2, x7, x8, x13 = quarter_round(x2, x7, x8, x13) + x3, x4, x9, x14 = quarter_round(x3, x4, x9, x14) + } + + // Interleave 4 blocks + // NB: The additions of sigma and the counter are omitted + STRIDE :: 4 + d_ := dst[n:] + when ODIN_ENDIAN == .Little { + d_[STRIDE*0] = x0 + d_[STRIDE*1] = x1 + d_[STRIDE*2] = x2 + d_[STRIDE*3] = x3 + d_[STRIDE*4] = x4 + s4 + d_[STRIDE*5] = x5 + s5 + d_[STRIDE*6] = x6 + s6 + d_[STRIDE*7] = x7 + s7 + d_[STRIDE*8] = x8 + s8 + d_[STRIDE*9] = x9 + s9 + d_[STRIDE*10] = x10 + s10 + d_[STRIDE*11] = x11 + s11 + d_[STRIDE*12] = x12 + d_[STRIDE*13] = x13 + s13 + d_[STRIDE*14] = x14 + s14 + d_[STRIDE*15] = x15 + s15 + } else { + d_[STRIDE*0] = intrinsics.byte_swap(x0) + d_[STRIDE*1] = intrinsics.byte_swap(x1) + d_[STRIDE*2] = intrinsics.byte_swap(x2) + d_[STRIDE*3] = intrinsics.byte_swap(x3) + d_[STRIDE*4] = intrinsics.byte_swap(x4 + s4) + d_[STRIDE*5] = intrinsics.byte_swap(x5 + s5) + d_[STRIDE*6] = intrinsics.byte_swap(x6 + s6) + d_[STRIDE*7] = intrinsics.byte_swap(x7 + s7) + d_[STRIDE*8] = intrinsics.byte_swap(x8 + s8) + d_[STRIDE*9] = intrinsics.byte_swap(x9 + s9) + d_[STRIDE*10] = intrinsics.byte_swap(x10 + s10) + d_[STRIDE*11] = intrinsics.byte_swap(x11 + s11) + d_[STRIDE*12] = intrinsics.byte_swap(x12) + d_[STRIDE*13] = intrinsics.byte_swap(x13 + s13) + d_[STRIDE*14] = intrinsics.byte_swap(x14 + s14) + d_[STRIDE*15] = intrinsics.byte_swap(x15 + s15) + } + + s12 = s12 + 1 // Increment the counter + } + + dst = dst[16*4:] + } +} + +// This replicates `rotate_left32` from `core:math/bits`, under the +// assumption that this will live in `base:runtime`. +@(require_results, private = "file") +rotl :: #force_inline proc "contextless" (x: u32, k: int) -> u32 { + n :: 32 + s := uint(k) & (n-1) + return x << s | x >> (n-s) +} diff --git a/base/runtime/random_generator_chacha8_simd128.odin b/base/runtime/random_generator_chacha8_simd128.odin new file mode 100644 index 000000000..d63d92620 --- /dev/null +++ b/base/runtime/random_generator_chacha8_simd128.odin @@ -0,0 +1,290 @@ +#+build !i386 +package runtime + +import "base:intrinsics" + +@(private = "file") +u32x4 :: #simd[4]u32 + +@(private = "file") +S0: u32x4 : {CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0} +@(private = "file") +S1: u32x4 : {CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1} +@(private = "file") +S2: u32x4 : {CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2} +@(private = "file") +S3: u32x4 : {CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3} + +@(private = "file") +_ROT_7L: u32x4 : {7, 7, 7, 7} +@(private = "file") +_ROT_7R: u32x4 : {25, 25, 25, 25} +@(private = "file") +_ROT_12L: u32x4 : {12, 12, 12, 12} +@(private = "file") +_ROT_12R: u32x4 : {20, 20, 20, 20} +@(private = "file") +_ROT_8L: u32x4 : {8, 8, 8, 8} +@(private = "file") +_ROT_8R: u32x4 : {24, 24, 24, 24} +@(private = "file") +_ROT_16: u32x4 : {16, 16, 16, 16} +@(private = "file") +_CTR_INC_4: u32x4 : {4, 4, 4, 4} +@(private = "file") +_CTR_INC_8: u32x4 : {8, 8, 8, 8} + +when ODIN_ENDIAN == .Big { + @(private = "file") + _byteswap_u32x4 :: #force_inline proc "contextless" (v: u32x4) -> u32x4 { + u8x16 :: #simd[16]u8 + return( + transmute(u32x4)simd.shuffle( + transmute(u8x16)v, + transmute(u8x16)v, + 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, + ) + ) + } +} + +@(private) +chacha8rand_refill_simd128 :: proc(r: ^Default_Random_State) { + // Initialize the base state. + k: [^]u32 = (^u32)(raw_data(r._buf[RNG_OUTPUT_PER_ITER:])) + when ODIN_ENDIAN == .Little { + s4_ := k[0] + s5_ := k[1] + s6_ := k[2] + s7_ := k[3] + s8_ := k[4] + s9_ := k[5] + s10_ := k[6] + s11_ := k[7] + } else { + s4_ := intrinsics.byte_swap(k[0]) + s5_ := intrinsics.byte_swap(k[1]) + s6_ := intrinsics.byte_swap(k[2]) + s7_ := intrinsics.byte_swap(k[3]) + s8_ := intrinsics.byte_swap(k[4]) + s9_ := intrinsics.byte_swap(k[5]) + s10_ := intrinsics.byte_swap(k[6]) + s11_ := intrinicss.byte_swap(k[7]) + } + + // 4-lane ChaCha8. + s4 := u32x4{s4_, s4_, s4_, s4_} + s5 := u32x4{s5_, s5_, s5_, s5_} + s6 := u32x4{s6_, s6_, s6_, s6_} + s7 := u32x4{s7_, s7_, s7_, s7_} + s8 := u32x4{s8_, s8_, s8_, s8_} + s9 := u32x4{s9_, s9_, s9_, s9_} + s10 := u32x4{s10_, s10_, s10_, s10_} + s11 := u32x4{s11_, s11_, s11_, s11_} + s12 := u32x4{0, 1, 2, 3} + s13, s14, s15: u32x4 + + dst: [^]u32x4 = (^u32x4)(raw_data(r._buf[:])) + + quarter_round := #force_inline proc "contextless" (a, b, c, d: u32x4) -> (u32x4, u32x4, u32x4, u32x4) { + a, b, c, d := a, b, c, d + + a = intrinsics.simd_add(a, b) + d = intrinsics.simd_bit_xor(d, a) + d = intrinsics.simd_bit_xor(intrinsics.simd_shl(d, _ROT_16), intrinsics.simd_shr(d, _ROT_16)) + + c = intrinsics.simd_add(c, d) + b = intrinsics.simd_bit_xor(b, c) + b = intrinsics.simd_bit_xor(intrinsics.simd_shl(b, _ROT_12L), intrinsics.simd_shr(b, _ROT_12R)) + + a = intrinsics.simd_add(a, b) + d = intrinsics.simd_bit_xor(d, a) + d = intrinsics.simd_bit_xor(intrinsics.simd_shl(d, _ROT_8L), intrinsics.simd_shr(d, _ROT_8R)) + + c = intrinsics.simd_add(c, d) + b = intrinsics.simd_bit_xor(b, c) + b = intrinsics.simd_bit_xor(intrinsics.simd_shl(b, _ROT_7L), intrinsics.simd_shr(b, _ROT_7R)) + + return a, b, c, d + } + + // 8 blocks at a time. + // + // Note: + // This uses a ton of registers so it is only worth it on targets + // that have something like 32 128-bit registers. This is currently + // all ARMv8 targets, and RISC-V Zvl128b (`V` application profile) + // targets. + // + // While our current definition of `.arm32` is 32-bit ARMv8, this + // may change in the future (ARMv7 is still relevant), and things + // like Cortex-A8/A9 does "pretend" 128-bit SIMD 64-bits at a time + // thus needs bemchmarking. + when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 { + for _ in 0..<2 { + x0_0, x1_0, x2_0, x3_0 := S0, S1, S2, S3 + x4_0, x5_0, x6_0, x7_0 := s4, s5, s6, s7 + x8_0, x9_0, x10_0, x11_0 := s8, s9, s10, s11 + x12_0, x13_0, x14_0, x15_0 := s12, s13, s14, s15 + + x0_1, x1_1, x2_1, x3_1 := S0, S1, S2, S3 + x4_1, x5_1, x6_1, x7_1 := s4, s5, s6, s7 + x8_1, x9_1, x10_1, x11_1 := s8, s9, s10, s11 + x12_1 := intrinsics.simd_add(s12, _CTR_INC_4) + x13_1, x14_1, x15_1 := s13, s14, s15 + + for i := CHACHA_ROUNDS; i > 0; i = i - 2 { + x0_0, x4_0, x8_0, x12_0 = quarter_round(x0_0, x4_0, x8_0, x12_0) + x0_1, x4_1, x8_1, x12_1 = quarter_round(x0_1, x4_1, x8_1, x12_1) + x1_0, x5_0, x9_0, x13_0 = quarter_round(x1_0, x5_0, x9_0, x13_0) + x1_1, x5_1, x9_1, x13_1 = quarter_round(x1_1, x5_1, x9_1, x13_1) + x2_0, x6_0, x10_0, x14_0 = quarter_round(x2_0, x6_0, x10_0, x14_0) + x2_1, x6_1, x10_1, x14_1 = quarter_round(x2_1, x6_1, x10_1, x14_1) + x3_0, x7_0, x11_0, x15_0 = quarter_round(x3_0, x7_0, x11_0, x15_0) + x3_1, x7_1, x11_1, x15_1 = quarter_round(x3_1, x7_1, x11_1, x15_1) + + x0_0, x5_0, x10_0, x15_0 = quarter_round(x0_0, x5_0, x10_0, x15_0) + x0_1, x5_1, x10_1, x15_1 = quarter_round(x0_1, x5_1, x10_1, x15_1) + x1_0, x6_0, x11_0, x12_0 = quarter_round(x1_0, x6_0, x11_0, x12_0) + x1_1, x6_1, x11_1, x12_1 = quarter_round(x1_1, x6_1, x11_1, x12_1) + x2_0, x7_0, x8_0, x13_0 = quarter_round(x2_0, x7_0, x8_0, x13_0) + x2_1, x7_1, x8_1, x13_1 = quarter_round(x2_1, x7_1, x8_1, x13_1) + x3_0, x4_0, x9_0, x14_0 = quarter_round(x3_0, x4_0, x9_0, x14_0) + x3_1, x4_1, x9_1, x14_1 = quarter_round(x3_1, x4_1, x9_1, x14_1) + } + + when ODIN_ENDIAN == .Little { + intrinsics.unaligned_store((^u32x4)(dst[0:]), x0_0) + intrinsics.unaligned_store((^u32x4)(dst[1:]), x1_0) + intrinsics.unaligned_store((^u32x4)(dst[2:]), x2_0) + intrinsics.unaligned_store((^u32x4)(dst[3:]), x3_0) + intrinsics.unaligned_store((^u32x4)(dst[4:]), intrinsics.simd_add(x4_0, s4)) + intrinsics.unaligned_store((^u32x4)(dst[5:]), intrinsics.simd_add(x5_0, s5)) + intrinsics.unaligned_store((^u32x4)(dst[6:]), intrinsics.simd_add(x6_0, s6)) + intrinsics.unaligned_store((^u32x4)(dst[7:]), intrinsics.simd_add(x7_0, s7)) + intrinsics.unaligned_store((^u32x4)(dst[8:]), intrinsics.simd_add(x8_0, s8)) + intrinsics.unaligned_store((^u32x4)(dst[9:]), intrinsics.simd_add(x9_0, s9)) + intrinsics.unaligned_store((^u32x4)(dst[10:]), intrinsics.simd_add(x10_0, s10)) + intrinsics.unaligned_store((^u32x4)(dst[11:]), intrinsics.simd_add(x11_0, s11)) + intrinsics.unaligned_store((^u32x4)(dst[12:]), x12_0) + intrinsics.unaligned_store((^u32x4)(dst[13:]), intrinsics.simd_add(x13_0, s13)) + intrinsics.unaligned_store((^u32x4)(dst[14:]), intrinsics.simd_add(x14_0, s14)) + intrinsics.unaligned_store((^u32x4)(dst[15:]), intrinsics.simd_add(x15_0, s15)) + + intrinsics.unaligned_store((^u32x4)(dst[16:]), x0_1) + intrinsics.unaligned_store((^u32x4)(dst[17:]), x1_1) + intrinsics.unaligned_store((^u32x4)(dst[18:]), x2_1) + intrinsics.unaligned_store((^u32x4)(dst[19:]), x3_1) + intrinsics.unaligned_store((^u32x4)(dst[20:]), intrinsics.simd_add(x4_1, s4)) + intrinsics.unaligned_store((^u32x4)(dst[21:]), intrinsics.simd_add(x5_1, s5)) + intrinsics.unaligned_store((^u32x4)(dst[22:]), intrinsics.simd_add(x6_1, s6)) + intrinsics.unaligned_store((^u32x4)(dst[23:]), intrinsics.simd_add(x7_1, s7)) + intrinsics.unaligned_store((^u32x4)(dst[24:]), intrinsics.simd_add(x8_1, s8)) + intrinsics.unaligned_store((^u32x4)(dst[25:]), intrinsics.simd_add(x9_1, s9)) + intrinsics.unaligned_store((^u32x4)(dst[26:]), intrinsics.simd_add(x10_1, s10)) + intrinsics.unaligned_store((^u32x4)(dst[27:]), intrinsics.simd_add(x11_1, s11)) + intrinsics.unaligned_store((^u32x4)(dst[28:]), x12_1) + intrinsics.unaligned_store((^u32x4)(dst[29:]), intrinsics.simd_add(x13_1, s13)) + intrinsics.unaligned_store((^u32x4)(dst[30:]), intrinsics.simd_add(x14_1, s14)) + intrinsics.unaligned_store((^u32x4)(dst[31:]), intrinsics.simd_add(x15_1, s15)) + } else { + intrinsics.unaligned_store((^u32x4)(dst[0:]), _byteswap_u32x4(x0_0)) + intrinsics.unaligned_store((^u32x4)(dst[1:]), _byteswap_u32x4(x1_0)) + intrinsics.unaligned_store((^u32x4)(dst[2:]), _byteswap_u32x4(x2_0)) + intrinsics.unaligned_store((^u32x4)(dst[3:]), _byteswap_u32x4(x3_0)) + intrinsics.unaligned_store((^u32x4)(dst[4:]), _byteswap_u32x4(intrinsics.simd_add(x4_0, s4))) + intrinsics.unaligned_store((^u32x4)(dst[5:]), _byteswap_u32x4(intrinsics.simd_add(x5_0, s5))) + intrinsics.unaligned_store((^u32x4)(dst[6:]), _byteswap_u32x4(intrinsics.simd_add(x6_0, s6))) + intrinsics.unaligned_store((^u32x4)(dst[7:]), _byteswap_u32x4(intrinsics.simd_add(x7_0, s7))) + intrinsics.unaligned_store((^u32x4)(dst[8:]), _byteswap_u32x4(intrinsics.simd_add(x8_0, s8))) + intrinsics.unaligned_store((^u32x4)(dst[9:]), _byteswap_u32x4(intrinsics.simd_add(x9_0, s9))) + intrinsics.unaligned_store((^u32x4)(dst[10:]), _byteswap_u32x4(intrinsics.simd_add(x10_0, s10))) + intrinsics.unaligned_store((^u32x4)(dst[11:]), _byteswap_u32x4(intrinsics.simd_add(x11_0, s11))) + intrinsics.unaligned_store((^u32x4)(dst[12:]), _byteswap_u32x4(x12_0)) + intrinsics.unaligned_store((^u32x4)(dst[13:]), _byteswap_u32x4(intrinsics.simd_add(x13_0, s13))) + intrinsics.unaligned_store((^u32x4)(dst[14:]), _byteswap_u32x4(intrinsics.simd_add(x14_0, s14))) + intrinsics.unaligned_store((^u32x4)(dst[15:]), _byteswap_u32x4(intrinsics.simd_add(x15_0, s15))) + + intrinsics.unaligned_store((^u32x4)(dst[16:]), _byteswap_u32x4(x0_1)) + intrinsics.unaligned_store((^u32x4)(dst[17:]), _byteswap_u32x4(x1_1)) + intrinsics.unaligned_store((^u32x4)(dst[18:]), _byteswap_u32x4(x2_1)) + intrinsics.unaligned_store((^u32x4)(dst[19:]), _byteswap_u32x4(x3_1)) + intrinsics.unaligned_store((^u32x4)(dst[20:]), _byteswap_u32x4(intrinsics.simd_add(x4_1, s4))) + intrinsics.unaligned_store((^u32x4)(dst[21:]), _byteswap_u32x4(intrinsics.simd_add(x5_1, s5))) + intrinsics.unaligned_store((^u32x4)(dst[22:]), _byteswap_u32x4(intrinsics.simd_add(x6_1, s6))) + intrinsics.unaligned_store((^u32x4)(dst[23:]), _byteswap_u32x4(intrinsics.simd_add(x7_1, s7))) + intrinsics.unaligned_store((^u32x4)(dst[24:]), _byteswap_u32x4(intrinsics.simd_add(x8_1, s8))) + intrinsics.unaligned_store((^u32x4)(dst[25:]), _byteswap_u32x4(intrinsics.simd_add(x9_1, s9))) + intrinsics.unaligned_store((^u32x4)(dst[26:]), _byteswap_u32x4(intrinsics.simd_add(x10_1, s10))) + intrinsics.unaligned_store((^u32x4)(dst[27:]), _byteswap_u32x4(intrinsics.simd_add(x11_1, s11))) + intrinsics.unaligned_store((^u32x4)(dst[28:]), _byteswap_u32x4(x12_1)) + intrinsics.unaligned_store((^u32x4)(dst[29:]), _byteswap_u32x4(intrinsics.simd_add(x13_1, s13))) + intrinsics.unaligned_store((^u32x4)(dst[30:]), _byteswap_u32x4(intrinsics.simd_add(x14_1, s14))) + intrinsics.unaligned_store((^u32x4)(dst[31:]), _byteswap_u32x4(intrinsics.simd_add(x15_1, s15))) + } + + s12 = intrinsics.simd_add(s12, _CTR_INC_8) + + dst = dst[32:] + } + } else { + for _ in 0..<4 { + x0, x1, x2, x3 := S0, S1, S2, S3 + x4, x5, x6, x7 := s4, s5, s6, s7 + x8, x9, x10, x11 := s8, s9, s10, s11 + x12, x13, x14, x15 := s12, s13, s14, s15 + + for i := CHACHA_ROUNDS; i > 0; i = i - 2 { + x0, x4, x8, x12 = quarter_round(x0, x4, x8, x12) + x1, x5, x9, x13 = quarter_round(x1, x5, x9, x13) + x2, x6, x10, x14 = quarter_round(x2, x6, x10, x14) + x3, x7, x11, x15 = quarter_round(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarter_round(x0, x5, x10, x15) + x1, x6, x11, x12 = quarter_round(x1, x6, x11, x12) + x2, x7, x8, x13 = quarter_round(x2, x7, x8, x13) + x3, x4, x9, x14 = quarter_round(x3, x4, x9, x14) + } + + when ODIN_ENDIAN == .Little { + intrinsics.unaligned_store((^u32x4)(dst[0:]), x0) + intrinsics.unaligned_store((^u32x4)(dst[1:]), x1) + intrinsics.unaligned_store((^u32x4)(dst[2:]), x2) + intrinsics.unaligned_store((^u32x4)(dst[3:]), x3) + intrinsics.unaligned_store((^u32x4)(dst[4:]), intrinsics.simd_add(x4, s4)) + intrinsics.unaligned_store((^u32x4)(dst[5:]), intrinsics.simd_add(x5, s5)) + intrinsics.unaligned_store((^u32x4)(dst[6:]), intrinsics.simd_add(x6, s6)) + intrinsics.unaligned_store((^u32x4)(dst[7:]), intrinsics.simd_add(x7, s7)) + intrinsics.unaligned_store((^u32x4)(dst[8:]), intrinsics.simd_add(x8, s8)) + intrinsics.unaligned_store((^u32x4)(dst[9:]), intrinsics.simd_add(x9, s9)) + intrinsics.unaligned_store((^u32x4)(dst[10:]), intrinsics.simd_add(x10, s10)) + intrinsics.unaligned_store((^u32x4)(dst[11:]), intrinsics.simd_add(x11, s11)) + intrinsics.unaligned_store((^u32x4)(dst[12:]), x12) + intrinsics.unaligned_store((^u32x4)(dst[13:]), intrinsics.simd_add(x13, s13)) + intrinsics.unaligned_store((^u32x4)(dst[14:]), intrinsics.simd_add(x14, s14)) + intrinsics.unaligned_store((^u32x4)(dst[15:]), intrinsics.simd_add(x15, s15)) + } else { + intrinsics.unaligned_store((^u32x4)(dst[0:]), _byteswap_u32x4(x0)) + intrinsics.unaligned_store((^u32x4)(dst[1:]), _byteswap_u32x4(x1)) + intrinsics.unaligned_store((^u32x4)(dst[2:]), _byteswap_u32x4(x2)) + intrinsics.unaligned_store((^u32x4)(dst[3:]), _byteswap_u32x4(x3)) + intrinsics.unaligned_store((^u32x4)(dst[4:]), _byteswap_u32x4(intrinsics.simd_add(x4, s4))) + intrinsics.unaligned_store((^u32x4)(dst[5:]), _byteswap_u32x4(intrinsics.simd_add(x5, s5))) + intrinsics.unaligned_store((^u32x4)(dst[6:]), _byteswap_u32x4(intrinsics.simd_add(x6, s6))) + intrinsics.unaligned_store((^u32x4)(dst[7:]), _byteswap_u32x4(intrinsics.simd_add(x7, s7))) + intrinsics.unaligned_store((^u32x4)(dst[8:]), _byteswap_u32x4(intrinsics.simd_add(x8, s8))) + intrinsics.unaligned_store((^u32x4)(dst[9:]), _byteswap_u32x4(intrinsics.simd_add(x9, s9))) + intrinsics.unaligned_store((^u32x4)(dst[10:]), _byteswap_u32x4(intrinsics.simd_add(x10, s10))) + intrinsics.unaligned_store((^u32x4)(dst[11:]), _byteswap_u32x4(intrinsics.simd_add(x11, s11))) + intrinsics.unaligned_store((^u32x4)(dst[12:]), _byteswap_u32x4(x12)) + intrinsics.unaligned_store((^u32x4)(dst[13:]), _byteswap_u32x4(intrinsics.simd_add(x13, s13))) + intrinsics.unaligned_store((^u32x4)(dst[14:]), _byteswap_u32x4(intrinsics.simd_add(x14, s14))) + intrinsics.unaligned_store((^u32x4)(dst[15:]), _byteswap_u32x4(intrinsics.simd_add(x15, s15))) + } + + s12 = intrinsics.simd_add(s12, _CTR_INC_4) + + dst = dst[16:] + } + } +} diff --git a/base/runtime/random_generator_chacha8_simd256.odin b/base/runtime/random_generator_chacha8_simd256.odin new file mode 100644 index 000000000..f2ccb6934 --- /dev/null +++ b/base/runtime/random_generator_chacha8_simd256.odin @@ -0,0 +1,197 @@ +#+build amd64 +package runtime + +import "base:intrinsics" + +#assert(ODIN_ENDIAN == .Little) + +@(private = "file") +u32x8 :: #simd[8]u32 +@(private = "file") +u32x4 :: #simd[4]u32 + +@(private = "file") +S0: u32x8 : { + CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0, + CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0, CHACHA_SIGMA_0, +} +@(private = "file") +S1: u32x8 : { + CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1, + CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1, CHACHA_SIGMA_1, +} +@(private = "file") +S2: u32x8 : { + CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2, + CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2, CHACHA_SIGMA_2, +} +@(private = "file") +S3: u32x8 : { + CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3, + CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3, CHACHA_SIGMA_3, +} + +@(private = "file") +_ROT_7L: u32x8 : {7, 7, 7, 7, 7, 7, 7, 7} +@(private = "file") +_ROT_7R: u32x8 : {25, 25, 25, 25, 25, 25, 25, 25} +@(private = "file") +_ROT_12L: u32x8 : {12, 12, 12, 12, 12, 12, 12, 12} +@(private = "file") +_ROT_12R: u32x8 : {20, 20, 20, 20, 20, 20, 20, 20} +@(private = "file") +_ROT_8L: u32x8 : {8, 8, 8, 8, 8, 8, 8, 8} +@(private = "file") +_ROT_8R: u32x8 : {24, 24, 24, 24, 24, 24, 24, 24} +@(private = "file") +_ROT_16: u32x8 : {16, 16, 16, 16, 16, 16, 16, 16} +@(private = "file") +_CTR_INC_8: u32x8 : {8, 8, 8, 8, 8, 8, 8, 8} + +// To the best of my knowledge this is only really useful on +// modern x86-64 as most ARM silicon is missing support for SVE2. + +@(private, enable_target_feature = "avx,avx2") +chacha8rand_refill_simd256 :: proc(r: ^Default_Random_State) { + // Initialize the base state. + k: [^]u32 = (^u32)(raw_data(r._buf[RNG_OUTPUT_PER_ITER:])) + s4_ := k[0] + s5_ := k[1] + s6_ := k[2] + s7_ := k[3] + s8_ := k[4] + s9_ := k[5] + s10_ := k[6] + s11_ := k[7] + + // 8-lane ChaCha8. + s4 := u32x8{s4_, s4_, s4_, s4_, s4_, s4_, s4_, s4_} + s5 := u32x8{s5_, s5_, s5_, s5_, s5_, s5_, s5_, s5_} + s6 := u32x8{s6_, s6_, s6_, s6_, s6_, s6_, s6_, s6_} + s7 := u32x8{s7_, s7_, s7_, s7_, s7_, s7_, s7_, s7_} + s8 := u32x8{s8_, s8_, s8_, s8_, s8_, s8_, s8_, s8_} + s9 := u32x8{s9_, s9_, s9_, s9_, s9_, s9_, s9_, s9_} + s10 := u32x8{s10_, s10_, s10_, s10_, s10_, s10_, s10_, s10_} + s11 := u32x8{s11_, s11_, s11_, s11_, s11_, s11_, s11_, s11_} + s12 := u32x8{0, 1, 2, 3, 4, 5, 6, 7} + s13, s14, s15: u32x8 + + u32x4 :: #simd[4]u32 + dst: [^]u32x4 = (^u32x4)(raw_data(r._buf[:])) + + quarter_round := #force_inline proc "contextless" (a, b, c, d: u32x8) -> (u32x8, u32x8, u32x8, u32x8) { + a, b, c, d := a, b, c, d + + a = intrinsics.simd_add(a, b) + d = intrinsics.simd_bit_xor(d, a) + d = intrinsics.simd_bit_xor(intrinsics.simd_shl(d, _ROT_16), intrinsics.simd_shr(d, _ROT_16)) + + c = intrinsics.simd_add(c, d) + b = intrinsics.simd_bit_xor(b, c) + b = intrinsics.simd_bit_xor(intrinsics.simd_shl(b, _ROT_12L), intrinsics.simd_shr(b, _ROT_12R)) + + a = intrinsics.simd_add(a, b) + d = intrinsics.simd_bit_xor(d, a) + d = intrinsics.simd_bit_xor(intrinsics.simd_shl(d, _ROT_8L), intrinsics.simd_shr(d, _ROT_8R)) + + c = intrinsics.simd_add(c, d) + b = intrinsics.simd_bit_xor(b, c) + b = intrinsics.simd_bit_xor(intrinsics.simd_shl(b, _ROT_7L), intrinsics.simd_shr(b, _ROT_7R)) + + return a, b, c, d + } + + for _ in 0..<2 { + x0, x1, x2, x3 := S0, S1, S2, S3 + x4, x5, x6, x7 := s4, s5, s6, s7 + x8, x9, x10, x11 := s8, s9, s10, s11 + x12, x13, x14, x15 := s12, s13, s14, s15 + + for i := CHACHA_ROUNDS; i > 0; i = i - 2 { + x0, x4, x8, x12 = quarter_round(x0, x4, x8, x12) + x1, x5, x9, x13 = quarter_round(x1, x5, x9, x13) + x2, x6, x10, x14 = quarter_round(x2, x6, x10, x14) + x3, x7, x11, x15 = quarter_round(x3, x7, x11, x15) + + x0, x5, x10, x15 = quarter_round(x0, x5, x10, x15) + x1, x6, x11, x12 = quarter_round(x1, x6, x11, x12) + x2, x7, x8, x13 = quarter_round(x2, x7, x8, x13) + x3, x4, x9, x14 = quarter_round(x3, x4, x9, x14) + } + + x4 = intrinsics.simd_add(x4, s4) + x5 = intrinsics.simd_add(x5, s5) + x6 = intrinsics.simd_add(x6, s6) + x7 = intrinsics.simd_add(x7, s7) + x8 = intrinsics.simd_add(x8, s8) + x9 = intrinsics.simd_add(x9, s9) + x10 = intrinsics.simd_add(x10, s10) + x11 = intrinsics.simd_add(x11, s11) + x13 = intrinsics.simd_add(x13, s13) + x14 = intrinsics.simd_add(x14, s14) + x15 = intrinsics.simd_add(x15, s15) + + // Ok, now we have x0->x15 with 8 lanes, but we need to + // output the first 4 blocks, then the second 4 blocks. + // + // LLVM appears not to consider "this instruction is totally + // awful on the given microarchitcture", which leads to + // `VPCOMPRESSED` being generated if and only if (⟺) AVX512 support is + // enabled for `intrinsics.simd_masked_compress_store`. + // On Zen 4, this leads to a 50% performance regression vs + // the 128-bit SIMD code. + // + // The fake intrinsic (because LLVM doesn't appear to have + // an amd64 specific one), doesn't generate `VEXTRACTI128`, + // but instead does cleverness without horrible regressions. + + intrinsics.unaligned_store((^u32x4)(dst[0:]), _mm_mm256_extracti128_si256(x0, 0)) + intrinsics.unaligned_store((^u32x4)(dst[1:]), _mm_mm256_extracti128_si256(x1, 0)) + intrinsics.unaligned_store((^u32x4)(dst[2:]), _mm_mm256_extracti128_si256(x2, 0)) + intrinsics.unaligned_store((^u32x4)(dst[3:]), _mm_mm256_extracti128_si256(x3, 0)) + intrinsics.unaligned_store((^u32x4)(dst[4:]), _mm_mm256_extracti128_si256(x4, 0)) + intrinsics.unaligned_store((^u32x4)(dst[5:]), _mm_mm256_extracti128_si256(x5, 0)) + intrinsics.unaligned_store((^u32x4)(dst[6:]), _mm_mm256_extracti128_si256(x6, 0)) + intrinsics.unaligned_store((^u32x4)(dst[7:]), _mm_mm256_extracti128_si256(x7, 0)) + intrinsics.unaligned_store((^u32x4)(dst[8:]), _mm_mm256_extracti128_si256(x8, 0)) + intrinsics.unaligned_store((^u32x4)(dst[9:]), _mm_mm256_extracti128_si256(x9, 0)) + intrinsics.unaligned_store((^u32x4)(dst[10:]), _mm_mm256_extracti128_si256(x10, 0)) + intrinsics.unaligned_store((^u32x4)(dst[11:]), _mm_mm256_extracti128_si256(x11, 0)) + intrinsics.unaligned_store((^u32x4)(dst[12:]), _mm_mm256_extracti128_si256(x12, 0)) + intrinsics.unaligned_store((^u32x4)(dst[13:]), _mm_mm256_extracti128_si256(x13, 0)) + intrinsics.unaligned_store((^u32x4)(dst[14:]), _mm_mm256_extracti128_si256(x14, 0)) + intrinsics.unaligned_store((^u32x4)(dst[15:]), _mm_mm256_extracti128_si256(x15, 0)) + + intrinsics.unaligned_store((^u32x4)(dst[16:]), _mm_mm256_extracti128_si256(x0, 1)) + intrinsics.unaligned_store((^u32x4)(dst[17:]), _mm_mm256_extracti128_si256(x1, 1)) + intrinsics.unaligned_store((^u32x4)(dst[18:]), _mm_mm256_extracti128_si256(x2, 1)) + intrinsics.unaligned_store((^u32x4)(dst[19:]), _mm_mm256_extracti128_si256(x3, 1)) + intrinsics.unaligned_store((^u32x4)(dst[20:]), _mm_mm256_extracti128_si256(x4, 1)) + intrinsics.unaligned_store((^u32x4)(dst[21:]), _mm_mm256_extracti128_si256(x5, 1)) + intrinsics.unaligned_store((^u32x4)(dst[22:]), _mm_mm256_extracti128_si256(x6, 1)) + intrinsics.unaligned_store((^u32x4)(dst[23:]), _mm_mm256_extracti128_si256(x7, 1)) + intrinsics.unaligned_store((^u32x4)(dst[24:]), _mm_mm256_extracti128_si256(x8, 1)) + intrinsics.unaligned_store((^u32x4)(dst[25:]), _mm_mm256_extracti128_si256(x9, 1)) + intrinsics.unaligned_store((^u32x4)(dst[26:]), _mm_mm256_extracti128_si256(x10, 1)) + intrinsics.unaligned_store((^u32x4)(dst[27:]), _mm_mm256_extracti128_si256(x11, 1)) + intrinsics.unaligned_store((^u32x4)(dst[28:]), _mm_mm256_extracti128_si256(x12, 1)) + intrinsics.unaligned_store((^u32x4)(dst[29:]), _mm_mm256_extracti128_si256(x13, 1)) + intrinsics.unaligned_store((^u32x4)(dst[30:]), _mm_mm256_extracti128_si256(x14, 1)) + intrinsics.unaligned_store((^u32x4)(dst[31:]), _mm_mm256_extracti128_si256(x15, 1)) + + s12 = intrinsics.simd_add(s12, _CTR_INC_8) + + dst = dst[32:] + } +} + +@(private = "file", require_results, enable_target_feature="avx2") +_mm_mm256_extracti128_si256 :: #force_inline proc "c" (a: u32x8, $OFFSET: int) -> u32x4 { + when OFFSET == 0 { + return intrinsics.simd_shuffle(a, a, 0, 1, 2, 3) + } else when OFFSET == 1 { + return intrinsics.simd_shuffle(a, a, 4, 5, 6, 7) + } else { + #panic("chacha8rand: invalid offset") + } +} diff --git a/base/runtime/threading.odin b/base/runtime/threading.odin index 778d7e900..97dcbc8f5 100644 --- a/base/runtime/threading.odin +++ b/base/runtime/threading.odin @@ -1,23 +1,13 @@ package runtime -Thread_Local_Cleaner :: #type proc "odin" () +Thread_Local_Cleaner_Odin :: #type proc "odin" () +Thread_Local_Cleaner_Contextless :: #type proc "contextless" () + +Thread_Local_Cleaner :: union #shared_nil {Thread_Local_Cleaner_Odin, Thread_Local_Cleaner_Contextless} @(private="file") thread_local_cleaners: [8]Thread_Local_Cleaner -// The thread ID is cached here to save time from making syscalls with every -// call. -@(thread_local) local_thread_id: int - -// Return the current thread ID. -@(require_results) -get_current_thread_id :: proc "contextless" () -> int { - if local_thread_id == 0 { - local_thread_id = _get_current_thread_id() - assert_contextless(local_thread_id != 0, "_get_current_thread_id returned 0.") - } - return local_thread_id -} // Add a procedure that will be run at the end of a thread for the purpose of // deallocating state marked as `thread_local`. @@ -43,6 +33,9 @@ run_thread_local_cleaners :: proc "odin" () { if p == nil { break } - p() + switch v in p { + case Thread_Local_Cleaner_Odin: v() + case Thread_Local_Cleaner_Contextless: v() + } } } diff --git a/base/runtime/udivmod128.odin b/base/runtime/udivmod128.odin index 8cc70df55..107dc605d 100644 --- a/base/runtime/udivmod128.odin +++ b/base/runtime/udivmod128.odin @@ -1,3 +1,4 @@ +#+build !bedrock package runtime import "base:intrinsics" diff --git a/base/runtime/wasm_allocator.odin b/base/runtime/wasm_allocator.odin index c4799fcbe..a16af87db 100644 --- a/base/runtime/wasm_allocator.odin +++ b/base/runtime/wasm_allocator.odin @@ -44,7 +44,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -WASM_Allocator :: struct #no_copy { +WASM_Allocator :: struct { // The minimum alignment of allocations. alignment: uint, // A region that contains as payload a single forward linked list of pointers to @@ -90,10 +90,12 @@ wasm_allocator_init :: proc(a: ^WASM_Allocator, alignment: uint = 8) { global_default_wasm_allocator_data: WASM_Allocator +@(require_results) default_wasm_allocator :: proc() -> Allocator { return wasm_allocator(&global_default_wasm_allocator_data) } +@(require_results) wasm_allocator :: proc(a: ^WASM_Allocator) -> Allocator { return { data = a, diff --git a/base/sanitizer/memory.odin b/base/sanitizer/memory.odin new file mode 100644 index 000000000..b16309a49 --- /dev/null +++ b/base/sanitizer/memory.odin @@ -0,0 +1,74 @@ +#+no-instrumentation +package sanitizer + +@(private="file") +MSAN_ENABLED :: .Memory in ODIN_SANITIZER_FLAGS + +@(private="file") +@(default_calling_convention="system") +foreign { + __msan_unpoison :: proc(addr: rawptr, size: uint) --- +} + +/* +Marks a slice as fully initialized. + +Code instrumented with `-sanitize:memory` will be permitted to access any +address within the slice as if it had already been initialized. + +When msan is not enabled this procedure does nothing. +*/ +memory_unpoison_slice :: proc "contextless" (region: $T/[]$E) { + when MSAN_ENABLED { + __msan_unpoison(raw_data(region), size_of(E) * len(region)) + } +} + +/* +Marks a pointer as fully initialized. + +Code instrumented with `-sanitize:memory` will be permitted to access memory +within the region the pointer points to as if it had already been initialized. + +When msan is not enabled this procedure does nothing. +*/ +memory_unpoison_ptr :: proc "contextless" (ptr: ^$T) { + when MSAN_ENABLED { + __msan_unpoison(ptr, size_of(T)) + } +} + +/* +Marks the region covering `[ptr, ptr+len)` as fully initialized. + +Code instrumented with `-sanitize:memory` will be permitted to access memory +within this range as if it had already been initialized. + +When msan is not enabled this procedure does nothing. +*/ +memory_unpoison_rawptr :: proc "contextless" (ptr: rawptr, len: int) { + when MSAN_ENABLED { + __msan_unpoison(ptr, uint(len)) + } +} + +/* +Marks the region covering `[ptr, ptr+len)` as fully initialized. + +Code instrumented with `-sanitize:memory` will be permitted to access memory +within this range as if it had already been initialized. + +When msan is not enabled this procedure does nothing. +*/ +memory_unpoison_rawptr_uint :: proc "contextless" (ptr: rawptr, len: uint) { + when MSAN_ENABLED { + __msan_unpoison(ptr, len) + } +} + +memory_unpoison :: proc { + memory_unpoison_slice, + memory_unpoison_ptr, + memory_unpoison_rawptr, + memory_unpoison_rawptr_uint, +} diff --git a/bin/radlink.exe b/bin/radlink.exe index bb2fd206e..8fb74fcd7 100644 Binary files a/bin/radlink.exe and b/bin/radlink.exe differ diff --git a/build.bat b/build.bat index ae733ff2a..9cddcc375 100644 --- a/build.bat +++ b/build.bat @@ -19,16 +19,27 @@ if "%VSCMD_ARG_TGT_ARCH%" neq "x64" ( ) ) +where /Q git.exe || goto skip_git_hash +if not exist .git\ goto skip_git_hash +for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m-%%d" --no-patch --no-notes HEAD') do ( + set CURR_DATE_TIME=%%i + set GIT_SHA=%%j +) +if %ERRORLEVEL% equ 0 ( + goto have_git_hash_and_date +) +:skip_git_hash pushd misc cl /nologo get-date.c -popd - -for /f %%i in ('misc\get-date') do ( +for /f %%i in ('get-date') do ( set CURR_DATE_TIME=%%i + rem Don't set GIT_SHA ) +popd +:have_git_hash_and_date set curr_year=%CURR_DATE_TIME:~0,4% -set curr_month=%CURR_DATE_TIME:~4,2% -set curr_day=%CURR_DATE_TIME:~6,2% +set curr_month=%CURR_DATE_TIME:~5,2% +set curr_day=%CURR_DATE_TIME:~8,2% :: Make sure this is a decent name and not generic set exe_name=odin.exe @@ -61,31 +72,14 @@ if %release_mode% equ 0 ( set V4=0 set odin_version_full="%V1%.%V2%.%V3%.%V4%" set odin_version_raw="dev-%V1%-%V2%" - set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF rem Parse source code as utf-8 even on shift-jis and other codepages rem See https://learn.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170 set compiler_flags= %compiler_flags% /utf-8 -set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\" +set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\" -DGIT_SHA=\"%GIT_SHA%\" rem fileversion is defined as {Major,Minor,Build,Private: u16} so a bit limited -set rc_flags=-nologo ^ --DV1=%V1% -DV2=%V2% -DV3=%V3% -DV4=%V4% ^ --DVF=%odin_version_full% -DNIGHTLY=%nightly% - -where /Q git.exe || goto skip_git_hash -if not exist .git\ goto skip_git_hash -for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m" --no-patch --no-notes HEAD') do ( - set odin_version_raw=dev-%%i - set GIT_SHA=%%j -) -if %ERRORLEVEL% equ 0 ( - set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\" - set rc_flags=%rc_flags% -DGIT_SHA=%GIT_SHA% -DVP=%odin_version_raw%:%GIT_SHA% -) else ( - set rc_flags=%rc_flags% -DVP=%odin_version_raw% -) -:skip_git_hash +set rc_flags=-nologo "-DGIT_SHA=%GIT_SHA% -DVP=dev-%V1%-%V2%:%GIT_SHA% nologo -DV1=%V1% -DV2=%V2% -DV3=%V3% -DV4=%V4% -DVF=%odin_version_full% -DNIGHTLY=%nightly%" if %nightly% equ 1 set compiler_defines=%compiler_defines% -DNIGHTLY @@ -100,6 +94,7 @@ if %release_mode% EQU 0 ( rem Debug set compiler_warnings= ^ -W4 -WX ^ -wd4100 -wd4101 -wd4127 -wd4146 ^ + -wd4324 ^ -wd4505 ^ -wd4456 -wd4457 @@ -112,16 +107,6 @@ set libs= ^ set odin_res=misc\odin.res set odin_rc=misc\odin.rc -rem DO NOT TOUCH! -rem THIS TILDE STUFF IS FOR DEVELOPMENT ONLY! -set tilde_backend=0 -if %tilde_backend% EQU 1 ( - set libs=%libs% src\tilde\tb.lib - set compiler_defines=%compiler_defines% -DODIN_TILDE_BACKEND -) -rem DO NOT TOUCH! - - set linker_flags= -incremental:no -opt:ref -subsystem:console -MANIFEST:EMBED if %release_mode% EQU 0 ( rem Debug @@ -153,4 +138,4 @@ if %release_mode% EQU 0 echo: & echo Debug compiler built. Note: run "build.bat del *.obj > NUL 2> NUL -:end_of_build +:end_of_build \ No newline at end of file diff --git a/build_odin.sh b/build_odin.sh index 19bb82a11..65e74120a 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -6,7 +6,6 @@ set -eu : ${LDFLAGS=} : ${LLVM_CONFIG=} -CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\"" CXXFLAGS="$CXXFLAGS -std=c++14" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" LDFLAGS="$LDFLAGS -pthread -lm" @@ -15,47 +14,54 @@ OS_NAME="$(uname -s)" if [ -d ".git" ] && [ -n "$(command -v git)" ]; then GIT_SHA=$(git show --pretty='%h' --no-patch --no-notes HEAD) + GIT_DATE=$(git show "--pretty=%cd" "--date=format:%Y-%m" --no-patch --no-notes HEAD) CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\"" +else + GIT_DATE=$(date +"%Y-%m") fi +CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$GIT_DATE\"" error() { printf "ERROR: %s\n" "$1" exit 1 } +SUPPORTED_LLVM_VERSIONS="22 21 20 19 18 17 14" + # Brew advises people not to add llvm to their $PATH, so try and use brew to find it. if [ -z "$LLVM_CONFIG" ] && [ -n "$(command -v brew)" ]; then - if [ -n "$(command -v $(brew --prefix llvm@20)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@20)/bin/llvm-config" - elif [ -n "$(command -v $(brew --prefix llvm@19)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@19)/bin/llvm-config" - elif [ -n "$(command -v $(brew --prefix llvm@18)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@18)/bin/llvm-config" - elif [ -n "$(command -v $(brew --prefix llvm@17)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@17)/bin/llvm-config" - elif [ -n "$(command -v $(brew --prefix llvm@14)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@14)/bin/llvm-config" - fi + for V in $SUPPORTED_LLVM_VERSIONS; do + if [ -n "$(command -v $(brew --prefix llvm@$V)/bin/llvm-config)" ]; then + LLVM_CONFIG="$(brew --prefix llvm@$V)/bin/llvm-config" + break + fi + done fi if [ -z "$LLVM_CONFIG" ]; then - # darwin, linux, openbsd - if [ -n "$(command -v llvm-config-20)" ]; then LLVM_CONFIG="llvm-config-20" - elif [ -n "$(command -v llvm-config-19)" ]; then LLVM_CONFIG="llvm-config-19" - elif [ -n "$(command -v llvm-config-18)" ]; then LLVM_CONFIG="llvm-config-18" - elif [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17" - elif [ -n "$(command -v llvm-config-14)" ]; then LLVM_CONFIG="llvm-config-14" - elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13" - elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12" - elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11" - # freebsd - elif [ -n "$(command -v llvm-config20)" ]; then LLVM_CONFIG="llvm-config20" - elif [ -n "$(command -v llvm-config19)" ]; then LLVM_CONFIG="llvm-config19" - elif [ -n "$(command -v llvm-config18)" ]; then LLVM_CONFIG="llvm-config18" - elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config17" - elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config14" - elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config13" - elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config12" - elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config11" - # fallback - elif [ -n "$(command -v llvm-config)" ]; then LLVM_CONFIG="llvm-config" - else - error "No llvm-config command found. Set LLVM_CONFIG to proceed." + DEFAULT_VERSION="" + + if [ -n "$(command -v llvm-config)" ]; then + DEFAULT_VERSION=$(llvm-config --version | awk -F. '{print $1}') + fi + + for V in $SUPPORTED_LLVM_VERSIONS; do + if [ "$DEFAULT_VERSION" = "$V" ]; then + LLVM_CONFIG="llvm-config" + break + # darwin, linux, openbsd + elif [ -n "$(command -v "llvm-config-$V")" ]; then + LLVM_CONFIG="llvm-config-$V" + break + # freebsd + elif [ -n "$(command -v "llvm-config$V")" ]; then + LLVM_CONFIG="llvm-config$V" + break + fi + done + + if [ -z "$LLVM_CONFIG" ]; then + error "No supported llvm-config command found. Set LLVM_CONFIG to proceed." fi fi @@ -72,18 +78,12 @@ LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')" LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')" LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')" -if [ $LLVM_VERSION_MAJOR -lt 11 ] || ([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]) || [ $LLVM_VERSION_MAJOR -gt 20 ]; then - error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14, 17, 18, 19 or 20" +if [ $LLVM_VERSION_MAJOR -lt 14 ] || ([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]) || [ $LLVM_VERSION_MAJOR -gt 22 ]; then + error "Invalid LLVM version $LLVM_VERSION: must be 14, 17, 18, 19, 20, 21 or 22" fi case "$OS_NAME" in Darwin) - if [ "$OS_ARCH" = "arm64" ]; then - if [ $LLVM_VERSION_MAJOR -lt 13 ]; then - error "Invalid LLVM version $LLVM_VERSION: Darwin Arm64 requires LLVM 13, 14, 17, 18, 19 or 20" - fi - fi - darwin_sysroot= if [ $(which xcrun) ]; then darwin_sysroot="--sysroot $(xcrun --sdk macosx --show-sdk-path)" @@ -114,12 +114,7 @@ Linux) ;; OpenBSD) CXXFLAGS="$CXXFLAGS -I/usr/local/include $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -lstdc++ -L/usr/local/lib -liconv" - LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" - ;; -Haiku) - CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel" - LDFLAGS="$LDFLAGS -lstdc++ -liconv" + LDFLAGS="$LDFLAGS -lstdc++ -L/usr/local/lib -Wl,-rpath,$($LLVM_CONFIG --libdir) -liconv" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" ;; *) diff --git a/check_all.bat b/check_all.bat new file mode 100644 index 000000000..aaf612d65 --- /dev/null +++ b/check_all.bat @@ -0,0 +1,71 @@ +@echo off + +if "%1" == "" ( + echo Checking darwin_amd64 - expect vendor:cgltf panic + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:darwin_amd64 + echo Checking darwin_arm64 - expect vendor:cgltf panic + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:darwin_arm64 + echo Checking linux_i386 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_i386 + echo Checking linux_amd64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_amd64 + echo Checking linux_arm64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_arm64 + echo Checking linux_arm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_arm32 + echo Checking linux_riscv64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_riscv64 + echo Checking windows_i386 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:windows_i386 + echo Checking windows_amd64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:windows_amd64 + echo Checking freebsd_amd64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_amd64 + echo Checking freebsd_arm64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_arm64 + echo Checking netbsd_amd64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_amd64 + echo Checking netbsd_arm64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_arm64 + echo Checking openbsd_amd64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:openbsd_amd64 +) + +if "%1" == "freestanding" ( + echo Checking freestanding_wasm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm32 + echo Checking freestanding_wasm64p32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm64p32 + echo Checking freestanding_amd64_sysv + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_amd64_sysv + echo Checking freestanding_amd64_win64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_amd64_win64 + echo Checking freestanding_arm64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_arm64 + echo Checking freestanding_arm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_arm32 + echo Checking freestanding_riscv64 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_riscv64 +) + +if "%1" == "rare" ( + echo Checking freebsd_i386 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_i386 +) + +if "%1" == "wasm" ( + echo Checking freestanding_wasm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm32 + echo Checking freestanding_wasm64p32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm64p32 + echo Checking wasi_wasm64p32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:wasi_wasm64p32 + echo Checking wasi_wasm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:wasi_wasm32 + echo Checking js_wasm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:js_wasm32 + echo Checking orca_wasm32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:orca_wasm32 + echo Checking js_wasm64p32 + odin check examples\all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:js_wasm64p32 +) diff --git a/check_all.sh b/check_all.sh new file mode 100755 index 000000000..eee08790e --- /dev/null +++ b/check_all.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +case $1 in +freestanding) + echo Checking freestanding_wasm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm32 + echo Checking freestanding_wasm64p32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm64p32 + echo Checking freestanding_amd64_sysv + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_amd64_sysv + echo Checking freestanding_amd64_win64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_amd64_win64 + echo Checking freestanding_arm64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_arm64 + echo Checking freestanding_arm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_arm32 + echo Checking freestanding_riscv64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_riscv64 + ;; + +rare) + echo Checking freebsd_i386 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_i386 + ;; + +wasm) + echo Checking freestanding_wasm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm32 + echo Checking freestanding_wasm64p32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freestanding_wasm64p32 + echo Checking wasi_wasm64p32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:wasi_wasm64p32 + echo Checking wasi_wasm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:wasi_wasm32 + echo Checking js_wasm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:js_wasm32 + echo Checking orca_wasm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:orca_wasm32 + echo Checking js_wasm64p32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:js_wasm64p32 + ;; + +*) + echo Checking darwin_amd64 - expect vendor:cgltf panic + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:darwin_amd64 + echo Checking darwin_arm64 - expect vendor:cgltf panic + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:darwin_arm64 + echo Checking linux_i386 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_i386 + echo Checking linux_amd64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_amd64 + echo Checking linux_arm64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_arm64 + echo Checking linux_arm32 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_arm32 + echo Checking linux_riscv64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:linux_riscv64 + echo Checking windows_i386 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:windows_i386 + echo Checking windows_amd64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:windows_amd64 + echo Checking freebsd_amd64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_amd64 + echo Checking freebsd_arm64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:freebsd_arm64 + echo Checking netbsd_amd64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_amd64 + echo Checking netbsd_arm64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:netbsd_arm64 + echo Checking openbsd_amd64 + odin check examples/all -vet -vet-tabs -strict-style -vet-style -warnings-as-errors -disallow-do -target:openbsd_amd64 + ;; + +esac diff --git a/ci/build_linux_static.sh b/ci/build_linux_static.sh index 2eb99116e..d88081f1e 100755 --- a/ci/build_linux_static.sh +++ b/ci/build_linux_static.sh @@ -6,7 +6,14 @@ LLVM_CONFIG="llvm-config-20" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" -CPPFLAGS="-DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\"" +if [ -d ".git" ] && [ -n "$(command -v git)" ]; then + GIT_SHA=$(git show --pretty='%h' --no-patch --no-notes HEAD) + GIT_DATE=$(git show "--pretty=%cd" "--date=format:%Y-%m" --no-patch --no-notes HEAD) + CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\"" +else + GIT_DATE=$(date +"%Y-%m") +fi +CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$GIT_DATE\"" CXXFLAGS="-std=c++14 $($LLVM_CONFIG --cxxflags --ldflags)" LDFLAGS="-static -lm -lzstd -lz -lffi -pthread -ldl -fuse-ld=mold" diff --git a/ci/remove_windows_binaries.sh b/ci/remove_windows_binaries.sh new file mode 100755 index 000000000..0722fc455 --- /dev/null +++ b/ci/remove_windows_binaries.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +find "$1" -type f \(\ + -iname "*.exe" \ + -o -iname "*.dll" \ + -o -iname "*.lib" \ + -o -iname "*.pdb" \ + \) -delete diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..da629b510 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,6 @@ +comment: false +coverage: + status: + project: + default: + threshold: 1% \ No newline at end of file diff --git a/core/bufio/doc.odin b/core/bufio/doc.odin new file mode 100644 index 000000000..683f68f07 --- /dev/null +++ b/core/bufio/doc.odin @@ -0,0 +1,2 @@ +// Wraps an `io.Stream` interface to provide buffered I/O. +package bufio \ No newline at end of file diff --git a/core/bufio/read_writer.odin b/core/bufio/read_writer.odin index 3e6bd3aa0..84769b9a6 100644 --- a/core/bufio/read_writer.odin +++ b/core/bufio/read_writer.odin @@ -38,5 +38,5 @@ _read_writer_procedure := proc(stream_data: rawptr, mode: io.Stream_Mode, p: []b case .Query: return io.query_utility({.Flush, .Read, .Write, .Query}) } - return 0, .Empty + return 0, .Unsupported } \ No newline at end of file diff --git a/core/bufio/reader.odin b/core/bufio/reader.odin index b78cac6e1..f949bbd85 100644 --- a/core/bufio/reader.odin +++ b/core/bufio/reader.odin @@ -1,14 +1,14 @@ package bufio +import "base:runtime" import "core:io" -import "core:mem" import "core:unicode/utf8" import "core:bytes" // Reader is a buffered wrapper for an io.Reader Reader :: struct { buf: []byte, - buf_allocator: mem.Allocator, + buf_allocator: runtime.Allocator, rd: io.Reader, // reader r, w: int, // read and write positions for buf @@ -29,6 +29,7 @@ MIN_READ_BUFFER_SIZE :: 16 @(private) DEFAULT_MAX_CONSECUTIVE_EMPTY_READS :: 128 +// reader_init initializes using an `allocator` reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator, loc := #caller_location) { size := size size = max(size, MIN_READ_BUFFER_SIZE) @@ -37,22 +38,25 @@ reader_init :: proc(b: ^Reader, rd: io.Reader, size: int = DEFAULT_BUF_SIZE, all b.buf = make([]byte, size, allocator, loc) } +// reader_init initializes using a user provided bytes buffer `buf` reader_init_with_buf :: proc(b: ^Reader, rd: io.Reader, buf: []byte) { reader_reset(b, rd) b.buf_allocator = {} b.buf = buf } -// reader_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set +// reader_destroy destroys the underlying buffer with its associated allocator if and only if (⟺) that allocator has been set reader_destroy :: proc(b: ^Reader) { delete(b.buf, b.buf_allocator) b^ = {} } +// reader_size returns the number of bytes in the backing buffer reader_size :: proc(b: ^Reader) -> int { return len(b.buf) } +// reader_reset resets the read and write positions, and the error values reader_reset :: proc(b: ^Reader, r: io.Reader) { b.rd = r b.r, b.w = 0, 0 @@ -343,7 +347,7 @@ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse case .Query: return io.query_utility({.Read, .Destroy, .Query}) } - return 0, .Empty + return 0, .Unsupported } // @@ -351,16 +355,15 @@ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse // -// reader_read_slice reads until the first occurrence of delim from the reader -// It returns a slice pointing at the bytes in the buffer -// The bytes stop being valid at the next read -// If reader_read_slice encounters an error before finding a delimiter -// reader_read_slice fails with error .Buffer_Full if the buffer fills without a delim -// Because the data returned from reader_read_slice will be overwritten on the -// next IO operation, reader_read_bytes or reader_read_string is usually preferred -// -// reader_read_slice returns err != nil if and only if line does not end in delim +// reader_read_slice reads until the first occurrence of delim in the input, +// returning a slice pointing at the bytes in the internal buffer. +// The returned slice is only valid until the next read call. +// If the buffer fills without finding delim, it returns .Buffer_Full. +// If the underlying reader returns an error before finding delim, that error is returned. +// Because the returned data will be overwritten by the next I/O operation, +// reader_read_bytes or reader_read_string is usually preferred. // +// reader_read_slice returns err != nil if and only if line does not end in delim. reader_read_slice :: proc(b: ^Reader, delim: byte) -> (line: []byte, err: io.Error) { s := 0 for { diff --git a/core/bufio/scanner.odin b/core/bufio/scanner.odin index ee2d5d1f6..b03437866 100644 --- a/core/bufio/scanner.odin +++ b/core/bufio/scanner.odin @@ -1,10 +1,10 @@ package bufio -import "core:bytes" -import "core:io" -import "core:mem" -import "core:unicode/utf8" +import "base:runtime" import "base:intrinsics" +import "core:io" +import "core:bytes" +import "core:unicode/utf8" // Extra errors returns by scanning procedures Scanner_Extra_Error :: enum i32 { @@ -46,6 +46,7 @@ DEFAULT_MAX_SCAN_TOKEN_SIZE :: 1<<16 @(private) _INIT_BUF_SIZE :: 4096 +// Initializes a Scanner buffer an allocator `buf_allocator` scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocator) -> ^Scanner { s.r = r s.split = scan_lines @@ -53,11 +54,21 @@ scanner_init :: proc(s: ^Scanner, r: io.Reader, buf_allocator := context.allocat s.buf.allocator = buf_allocator return s } + +// Initializes a Scanner buffer a user provided bytes buffer `buf` scanner_init_with_buffer :: proc(s: ^Scanner, r: io.Reader, buf: []byte) -> ^Scanner { s.r = r s.split = scan_lines s.max_token_size = DEFAULT_MAX_SCAN_TOKEN_SIZE - s.buf = mem.buffer_from_slice(buf) + s.buf = transmute([dynamic]byte)runtime.Raw_Dynamic_Array{ + data = raw_data(buf), + len = 0, + cap = len(buf), + allocator = runtime.Allocator{ + procedure = runtime.nil_allocator_proc, + data = nil, + }, + } resize(&s.buf, cap(s.buf)) return s } @@ -75,24 +86,27 @@ scanner_error :: proc(s: ^Scanner) -> Scanner_Error { return s._err } -// Returns the most recent token created by scanner_scan. +// Returns the most recent token created by 'scan'. // The underlying array may point to data that may be overwritten -// by another call to scanner_scan. +// by another call to 'scan'. // Treat the returned value as if it is immutable. scanner_bytes :: proc(s: ^Scanner) -> []byte { return s.token } -// Returns the most recent token created by scanner_scan. +// Returns the most recent token created by 'scan'. // The underlying array may point to data that may be overwritten -// by another call to scanner_scan. +// by another call to 'scan'. // Treat the returned value as if it is immutable. scanner_text :: proc(s: ^Scanner) -> string { return string(s.token) } -// scanner_scan advances the scanner -scanner_scan :: proc(s: ^Scanner) -> bool { +// scanner_scan is an alias of scan +scanner_scan :: scan + +// scan advances the Scanner +scan :: proc(s: ^Scanner) -> bool { set_err :: proc(s: ^Scanner, err: Scanner_Error) { switch s._err { case nil, .EOF: @@ -229,6 +243,7 @@ scanner_scan :: proc(s: ^Scanner) -> bool { } } +// scan_bytes is a splitting procedure that returns each byte as a token scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { if at_eof && len(data) == 0 { return @@ -236,6 +251,10 @@ scan_bytes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, return 1, data[0:1], nil, false } +// scan_runes is a splitting procedure that returns each UTF-8 encoded rune as a token. +// The lsit of runes return is equivalent to that of iterating over a string in a 'for in' loop, meaning any +// erroneous UTF-8 encodings will be returned as U+FFFD. Unfortunately this means it is impossible for the "client" +// to know whether a U+FFFD is an expected replacement rune or an encoding of an error. scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { if at_eof && len(data) == 0 { return @@ -264,7 +283,8 @@ scan_runes :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, token = ERROR_RUNE return } - +// scan_words is a splitting procedure that returns each Unicode-space-separated word of text, excluding the surrounded spaces. +// It will never return return an empty string. scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { is_space :: proc "contextless" (r: rune) -> bool { switch r { @@ -312,6 +332,8 @@ scan_words :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, return } +// scan_lines is a splitting procedure that returns each line of text stripping of any trailing newline and an optional preceding carriage return (\r?\n). +// A new line is allowed to be empty. scan_lines :: proc(data: []byte, at_eof: bool) -> (advance: int, token: []byte, err: Scanner_Error, final_token: bool) { trim_carriage_return :: proc "contextless" (data: []byte) -> []byte { if len(data) > 0 && data[len(data)-1] == '\r' { diff --git a/core/bufio/writer.odin b/core/bufio/writer.odin index 5edd3dd6b..9d5ef3481 100644 --- a/core/bufio/writer.odin +++ b/core/bufio/writer.odin @@ -1,14 +1,14 @@ package bufio +import "base:runtime" import "core:io" -import "core:mem" import "core:unicode/utf8" // import "core:bytes" // Writer is a buffered wrapper for an io.Writer Writer :: struct { buf: []byte, - buf_allocator: mem.Allocator, + buf_allocator: runtime.Allocator, wr: io.Writer, n: int, @@ -19,6 +19,7 @@ Writer :: struct { } +// Initialized a Writer with an `allocator` writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, allocator := context.allocator) { size := size size = max(size, MIN_READ_BUFFER_SIZE) @@ -27,13 +28,14 @@ writer_init :: proc(b: ^Writer, wr: io.Writer, size: int = DEFAULT_BUF_SIZE, all b.buf = make([]byte, size, allocator) } +// Initialized a Writer with a user provided buffer `buf` writer_init_with_buf :: proc(b: ^Writer, wr: io.Writer, buf: []byte) { writer_reset(b, wr) b.buf_allocator = {} b.buf = buf } -// writer_destroy destroys the underlying buffer with its associated allocator IFF that allocator has been set +// writer_destroy destroys the underlying buffer with its associated allocator if and only if (⟺) that allocator has been set writer_destroy :: proc(b: ^Writer) { delete(b.buf, b.buf_allocator) b^ = {} @@ -247,5 +249,5 @@ _writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse case .Query: return io.query_utility({.Flush, .Write, .Destroy, .Query}) } - return 0, .Empty + return 0, .Unsupported } diff --git a/core/bytes/buffer.odin b/core/bytes/buffer.odin index f4d883353..5fd3145b7 100644 --- a/core/bytes/buffer.odin +++ b/core/bytes/buffer.odin @@ -176,6 +176,11 @@ buffer_write_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int, loc := #caller_loca return buffer_write(b, ([^]byte)(ptr)[:size], loc=loc) } +buffer_write_slice :: proc(b: ^Buffer, slice: $S/[]$T, loc := #caller_location) -> (n: int, err: io.Error) { + size := len(slice)*size_of(T) + return buffer_write(b, ([^]byte)(raw_data(slice))[:size], loc=loc) +} + buffer_write_string :: proc(b: ^Buffer, s: string, loc := #caller_location) -> (n: int, err: io.Error) { b.last_read = .Invalid m, ok := _buffer_try_grow(b, len(s), loc=loc) @@ -248,6 +253,12 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io. return buffer_read(b, ([^]byte)(ptr)[:size]) } +buffer_read_slice :: proc(b: ^Buffer, slice: $S/[]$T) -> (n: int, err: io.Error) { + size := len(slice)*size_of(T) + return buffer_read(b, ([^]byte)(raw_data(slice))[:size]) +} + + buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) { if len(p) == 0 { return 0, nil @@ -434,5 +445,5 @@ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Destroy, .Query}) } - return 0, .Empty + return 0, .Unsupported } diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin index c0d25bcce..55eca5386 100644 --- a/core/bytes/bytes.odin +++ b/core/bytes/bytes.odin @@ -1,7 +1,8 @@ +// Procedures for manipulation of `[]byte` slices. package bytes +import "base:runtime" import "base:intrinsics" -import "core:mem" import "core:simd" import "core:unicode" import "core:unicode/utf8" @@ -34,20 +35,20 @@ SCANNER_SENTINEL_MIN_128: simd.u8x16 : u8(0xff) SIMD_REG_SIZE_128 :: 16 clone :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { - c := make([]byte, len(s), allocator, loc) + c := make([]byte, len(s), allocator, loc=loc) copy(c, s) return c[:len(s)] } -clone_safe :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: mem.Allocator_Error) { - c := make([]byte, len(s), allocator, loc) or_return +clone_safe :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: runtime.Allocator_Error) { + c := make([]byte, len(s), allocator, loc=loc) or_return copy(c, s) return c[:len(s)], nil } ptr_from_slice :: ptr_from_bytes ptr_from_bytes :: proc(str: []byte) -> ^byte { - d := transmute(mem.Raw_String)str + d := transmute(runtime.Raw_String)str return d.data } @@ -66,10 +67,16 @@ truncate_to_rune :: proc(str: []byte, r: rune) -> []byte { return str[:n] } -// Compares two strings, returning a value representing which one comes first lexiographically. -// -1 for `a`; 1 for `b`, or 0 if they are equal. +// Compares two []byte, returning a value representing which one comes first lexiographically. +// Returns: -1 for `lhs`, 1 for `rhs`, or 0 if they are equal. compare :: proc(lhs, rhs: []byte) -> int { - return mem.compare(lhs, rhs) + res := runtime.memory_compare(raw_data(lhs), raw_data(rhs), min(len(lhs), len(rhs))) + if res == 0 && len(lhs) != len(rhs) { + return len(lhs) <= len(rhs) ? -1 : +1 + } else if len(lhs) == 0 && len(rhs) == 0 { + return 0 + } + return res } contains_rune :: proc(s: []byte, r: rune) -> int { @@ -134,8 +141,13 @@ equal_fold :: proc(u, v: []byte) -> bool { return false } - // TODO(bill): Unicode folding - + r := unicode.simple_fold(sr) + for r != sr && r < tr { + r = unicode.simple_fold(sr) + } + if r == tr { + continue loop + } return false } @@ -151,7 +163,7 @@ has_suffix :: proc(s, suffix: []byte) -> bool { } -join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte { +join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { if len(a) == 0 { return nil } @@ -161,7 +173,7 @@ join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte n += len(s) } - b := make([]byte, n, allocator) + b := make([]byte, n, allocator, loc=loc) i := copy(b, a[0]) for s in a[1:] { i += copy(b[i:], sep) @@ -170,7 +182,7 @@ join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte return b } -join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) { +join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: runtime.Allocator_Error) { if len(a) == 0 { return nil, nil } @@ -180,7 +192,7 @@ join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> ( n += len(s) } - b := make([]byte, n, allocator) or_return + b := make([]byte, n, allocator, loc=loc) or_return i := copy(b, a[0]) for s in a[1:] { i += copy(b[i:], sep) @@ -189,7 +201,7 @@ join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> ( return b, nil } -concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { +concatenate :: proc(a: [][]byte, allocator := context.allocator, loc := #caller_location) -> []byte { if len(a) == 0 { return nil } @@ -198,7 +210,7 @@ concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { for s in a { n += len(s) } - b := make([]byte, n, allocator) + b := make([]byte, n, allocator, loc=loc) i := 0 for s in a { i += copy(b[i:], s) @@ -206,7 +218,7 @@ concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte { return b } -concatenate_safe :: proc(a: [][]byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) { +concatenate_safe :: proc(a: [][]byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: runtime.Allocator_Error) { if len(a) == 0 { return nil, nil } @@ -215,7 +227,7 @@ concatenate_safe :: proc(a: [][]byte, allocator := context.allocator) -> (data: for s in a { n += len(s) } - b := make([]byte, n, allocator) or_return + b := make([]byte, n, allocator, loc=loc) or_return i := 0 for s in a { i += copy(b[i:], s) @@ -225,7 +237,7 @@ concatenate_safe :: proc(a: [][]byte, allocator := context.allocator) -> (data: @private -_split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) -> [][]byte { +_split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator, loc := #caller_location) -> [][]byte { s, n := s, n if n == 0 { @@ -238,7 +250,7 @@ _split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) n = l } - res := make([dynamic][]byte, n, allocator) + res := make([dynamic][]byte, n, allocator, loc=loc) for i := 0; i < n-1; i += 1 { _, w := utf8.decode_rune(s) res[i] = s[:w] @@ -254,7 +266,7 @@ _split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) n = count(s, sep) + 1 } - res := make([dynamic][]byte, n, allocator) + res := make([dynamic][]byte, n, allocator, loc=loc) n -= 1 @@ -272,20 +284,20 @@ _split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) return res[:i+1] } -split :: proc(s, sep: []byte, allocator := context.allocator) -> [][]byte { - return _split(s, sep, 0, -1, allocator) +split :: proc(s, sep: []byte, allocator := context.allocator, loc := #caller_location) -> [][]byte { + return _split(s, sep, 0, -1, allocator, loc) } -split_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) -> [][]byte { - return _split(s, sep, 0, n, allocator) +split_n :: proc(s, sep: []byte, n: int, allocator := context.allocator, loc := #caller_location) -> [][]byte { + return _split(s, sep, 0, n, allocator, loc) } -split_after :: proc(s, sep: []byte, allocator := context.allocator) -> [][]byte { - return _split(s, sep, len(sep), -1, allocator) +split_after :: proc(s, sep: []byte, allocator := context.allocator, loc := #caller_location) -> [][]byte { + return _split(s, sep, len(sep), -1, allocator, loc) } -split_after_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) -> [][]byte { - return _split(s, sep, len(sep), n, allocator) +split_after_n :: proc(s, sep: []byte, n: int, allocator := context.allocator, loc := #caller_location) -> [][]byte { + return _split(s, sep, len(sep), n, allocator, loc) } @@ -350,7 +362,7 @@ index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds } c_vec: simd.u8x16 = c - when !simd.IS_EMULATED { + when simd.HAS_HARDWARE_SIMD { // Note: While this is something that could also logically take // advantage of AVX512, the various downclocking and power // consumption related woes make premature to have a dedicated @@ -485,7 +497,7 @@ last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_che } c_vec: simd.u8x16 = c - when !simd.IS_EMULATED { + when simd.HAS_HARDWARE_SIMD { // Note: While this is something that could also logically take // advantage of AVX512, the various downclocking and power // consumption related woes make premature to have a dedicated @@ -762,14 +774,14 @@ count :: proc(s, substr: []byte) -> int { } -repeat :: proc(s: []byte, count: int, allocator := context.allocator) -> []byte { +repeat :: proc(s: []byte, count: int, allocator := context.allocator, loc := #caller_location) -> []byte { if count < 0 { panic("bytes: negative repeat count") } else if count > 0 && (len(s)*count)/count != len(s) { panic("bytes: repeat count will cause an overflow") } - b := make([]byte, len(s)*count, allocator) + b := make([]byte, len(s)*count, allocator, loc=loc) i := copy(b, s) for i < len(b) { // 2^N trick to reduce the need to copy copy(b[i:], b[:i]) @@ -778,12 +790,12 @@ repeat :: proc(s: []byte, count: int, allocator := context.allocator) -> []byte return b } -replace_all :: proc(s, old, new: []byte, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return replace(s, old, new, -1, allocator) +replace_all :: proc(s, old, new: []byte, allocator := context.allocator, loc := #caller_location) -> (output: []byte, was_allocation: bool) { + return replace(s, old, new, -1, allocator, loc) } // if n < 0, no limit on the number of replacements -replace :: proc(s, old, new: []byte, n: int, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { +replace :: proc(s, old, new: []byte, n: int, allocator := context.allocator, loc := #caller_location) -> (output: []byte, was_allocation: bool) { if string(old) == string(new) || n == 0 { was_allocation = false output = s @@ -799,7 +811,7 @@ replace :: proc(s, old, new: []byte, n: int, allocator := context.allocator) -> } - t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator) + t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator, loc=loc) was_allocation = true w := 0 @@ -823,12 +835,12 @@ replace :: proc(s, old, new: []byte, n: int, allocator := context.allocator) -> return } -remove :: proc(s, key: []byte, n: int, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return replace(s, key, {}, n, allocator) +remove :: proc(s, key: []byte, n: int, allocator := context.allocator, loc := #caller_location) -> (output: []byte, was_allocation: bool) { + return replace(s, key, {}, n, allocator, loc) } -remove_all :: proc(s, key: []byte, allocator := context.allocator) -> (output: []byte, was_allocation: bool) { - return remove(s, key, -1, allocator) +remove_all :: proc(s, key: []byte, allocator := context.allocator, loc := #caller_location) -> (output: []byte, was_allocation: bool) { + return remove(s, key, -1, allocator, loc) } @(private) _ascii_space := [256]u8{'\t' = 1, '\n' = 1, '\v' = 1, '\f' = 1, '\r' = 1, ' ' = 1} @@ -985,16 +997,18 @@ trim_left :: proc(s: []byte, cutset: []byte) -> []byte { if s == nil || cutset == nil { return s } - state := cutset - return trim_left_proc_with_state(s, is_in_cutset, &state) + begin := 0; end := len(s) + for ; begin < end && index_byte(cutset, s[begin]) >= 0; begin += 1 {} + return s[begin:] } trim_right :: proc(s: []byte, cutset: []byte) -> []byte { if s == nil || cutset == nil { return s } - state := cutset - return trim_right_proc_with_state(s, is_in_cutset, &state) + begin := 0; end := len(s) + for ; end > begin && index_byte(cutset, s[end - 1]) >= 0; end -= 1 {} + return s[:end] } trim :: proc(s: []byte, cutset: []byte) -> []byte { @@ -1040,7 +1054,7 @@ trim_suffix :: proc(s, suffix: []byte) -> []byte { return s } -split_multi :: proc(s: []byte, substrs: [][]byte, skip_empty := false, allocator := context.allocator) -> [][]byte #no_bounds_check { +split_multi :: proc(s: []byte, substrs: [][]byte, skip_empty := false, allocator := context.allocator, loc := #caller_location) -> [][]byte #no_bounds_check { if s == nil || len(substrs) <= 0 { return nil } @@ -1088,7 +1102,7 @@ split_multi :: proc(s: []byte, substrs: [][]byte, skip_empty := false, allocator return nil } - buf := make([][]byte, n, allocator) + buf := make([][]byte, n, allocator, loc=loc) n, i, l = 0, 0, 0 @@ -1175,10 +1189,10 @@ split_multi_iterator :: proc(s: ^[]byte, substrs: [][]byte, skip_empty := false) // Scrubs invalid utf-8 characters and replaces them with the replacement string // Adjacent invalid bytes are only replaced once -scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator) -> []byte { +scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { str := s b: Buffer - buffer_init_allocator(&b, 0, len(s), allocator) + buffer_init_allocator(&b, 0, len(s), allocator, loc) has_error := false cursor := 0 @@ -1190,11 +1204,11 @@ scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator) -> if r == utf8.RUNE_ERROR { if !has_error { has_error = true - buffer_write(&b, origin[:cursor]) + buffer_write(&b, origin[:cursor], loc) } } else if has_error { has_error = false - buffer_write(&b, replacement) + buffer_write(&b, replacement, loc) origin = origin[cursor:] cursor = 0 @@ -1208,10 +1222,10 @@ scrub :: proc(s: []byte, replacement: []byte, allocator := context.allocator) -> } -reverse :: proc(s: []byte, allocator := context.allocator) -> []byte { +reverse :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { str := s n := len(str) - buf := make([]byte, n) + buf := make([]byte, n, loc=loc) i := n for len(str) > 0 { @@ -1223,7 +1237,7 @@ reverse :: proc(s: []byte, allocator := context.allocator) -> []byte { return buf } -expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator) -> []byte { +expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator, loc := #caller_location) -> []byte { if tab_size <= 0 { panic("tab size must be positive") } @@ -1234,7 +1248,7 @@ expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator) -> } b: Buffer - buffer_init_allocator(&b, 0, len(s), allocator) + buffer_init_allocator(&b, 0, len(s), allocator, loc=loc) str := s column: int @@ -1246,7 +1260,7 @@ expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator) -> expand := tab_size - column%tab_size for i := 0; i < expand; i += 1 { - buffer_write_byte(&b, ' ') + buffer_write_byte(&b, ' ', loc) } column += expand @@ -1257,7 +1271,7 @@ expand_tabs :: proc(s: []byte, tab_size: int, allocator := context.allocator) -> column += w } - buffer_write_rune(&b, r) + buffer_write_rune(&b, r, loc) } str = str[w:] @@ -1282,59 +1296,59 @@ partition :: proc(str, sep: []byte) -> (head, match, tail: []byte) { center_justify :: centre_justify // NOTE(bill): Because Americans exist // centre_justify returns a byte slice with a pad byte slice at boths sides if the str's rune length is smaller than length -centre_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { +centre_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-1 pad_len := rune_count(pad) b: Buffer - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) write_pad_string(&b, pad, pad_len, remains/2) - buffer_write(&b, str) + buffer_write(&b, str, loc) write_pad_string(&b, pad, pad_len, (remains+1)/2) return buffer_to_bytes(&b) } // left_justify returns a byte slice with a pad byte slice at left side if the str's rune length is smaller than length -left_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { +left_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-1 pad_len := rune_count(pad) b: Buffer - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) - buffer_write(&b, str) + buffer_write(&b, str, loc) write_pad_string(&b, pad, pad_len, remains) return buffer_to_bytes(&b) } // right_justify returns a byte slice with a pad byte slice at right side if the str's rune length is smaller than length -right_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator) -> []byte { +right_justify :: proc(str: []byte, length: int, pad: []byte, allocator := context.allocator, loc := #caller_location) -> []byte { n := rune_count(str) if n >= length || pad == nil { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-1 pad_len := rune_count(pad) b: Buffer - buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) + buffer_init_allocator(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) write_pad_string(&b, pad, pad_len, remains) - buffer_write(&b, str) + buffer_write(&b, str, loc) return buffer_to_bytes(&b) } @@ -1343,11 +1357,11 @@ right_justify :: proc(str: []byte, length: int, pad: []byte, allocator := contex @private -write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int) { +write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int, loc := #caller_location) { repeats := remains / pad_len for i := 0; i < repeats; i += 1 { - buffer_write(b, pad) + buffer_write(b, pad, loc) } n := remains % pad_len @@ -1355,7 +1369,7 @@ write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int) { for i := 0; i < n; i += 1 { r, width := utf8.decode_rune(p) - buffer_write_rune(b, r) + buffer_write_rune(b, r, loc) p = p[width:] } } @@ -1363,7 +1377,7 @@ write_pad_string :: proc(b: ^Buffer, pad: []byte, pad_len, remains: int) { // fields splits the byte slice s around each instance of one or more consecutive white space character, defined by unicode.is_space // returning a slice of subslices of s or an empty slice if s only contains white space -fields :: proc(s: []byte, allocator := context.allocator) -> [][]byte #no_bounds_check { +fields :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> [][]byte #no_bounds_check { n := 0 was_space := 1 set_bits := u8(0) @@ -1378,14 +1392,14 @@ fields :: proc(s: []byte, allocator := context.allocator) -> [][]byte #no_bounds } if set_bits >= utf8.RUNE_SELF { - return fields_proc(s, unicode.is_space, allocator) + return fields_proc(s, unicode.is_space, allocator, loc) } if n == 0 { return nil } - a := make([][]byte, n, allocator) + a := make([][]byte, n, allocator, loc=loc) na := 0 field_start := 0 i := 0 @@ -1419,15 +1433,15 @@ fields :: proc(s: []byte, allocator := context.allocator) -> [][]byte #no_bounds // // fields_proc makes no guarantee about the order in which it calls f(ch) // it assumes that `f` always returns the same value for a given ch -fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.allocator) -> [][]byte #no_bounds_check { - subslices := make([dynamic][]byte, 0, 32, allocator) +fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.allocator, loc := #caller_location) -> [][]byte #no_bounds_check { + subslices := make([dynamic][]byte, 0, 32, allocator, loc=loc) start, end := -1, -1 for r, offset in string(s) { end = offset if f(r) { if start >= 0 { - append(&subslices, s[start : end]) + append(&subslices, s[start : end], loc=loc) // -1 could be used, but just speed it up through bitwise not // gotta love 2's complement start = ~start @@ -1440,13 +1454,13 @@ fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.alloc } if start >= 0 { - append(&subslices, s[start : len(s)]) + append(&subslices, s[start : len(s)], loc=loc) } return subslices[:] } -// alias returns true iff a and b have a non-zero length, and any part of +// alias returns true if and only if (⟺) a and b have a non-zero length, and any part of // a overlaps with b. alias :: proc "contextless" (a, b: []byte) -> bool { a_len, b_len := len(a), len(b) @@ -1460,7 +1474,7 @@ alias :: proc "contextless" (a, b: []byte) -> bool { return a_start <= b_end && b_start <= a_end } -// alias_inexactly returns true iff a and b have a non-zero length, +// alias_inexactly returns true if and only if (⟺) a and b have a non-zero length, // the base pointer of a and b are NOT equal, and any part of a overlaps // with b (ie: `alias(a, b)` with an exception that returns false for // `a == b`, `b = a[:len(a)-69]` and similar conditions). diff --git a/core/bytes/reader.odin b/core/bytes/reader.odin index 2e1c5ed42..189a269ed 100644 --- a/core/bytes/reader.odin +++ b/core/bytes/reader.odin @@ -61,6 +61,27 @@ reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Erro } return } +reader_read_slice :: proc(r: ^Reader, slice: $T/[]$S) -> (n: int, err: io.Error) { + b := ([^]byte)(raw_data(slice))[:len(slice)*size_of(S)] + return reader_read(r, b) +} + +reader_read_slice_at :: proc(r: ^Reader, slice: $T/[]$S, off: i64) -> (n: int, err: io.Error) { + b := ([^]byte)(raw_data(slice))[:len(slice)*size_of(S)] + return reader_read_at(r, b, off) +} + +reader_read_ptr :: proc(r: ^Reader, data: rawptr, len: int) -> (n: int, err: io.Error) { + b := ([^]byte)(data)[:len] + return reader_read(r, b) +} + +reader_read_ptr_at :: proc(r: ^Reader, data: rawptr, len: int, off: i64) -> (n: int, err: io.Error) { + b := ([^]byte)(data)[:len] + return reader_read_at(r, b, off) +} + + reader_read_byte :: proc(r: ^Reader) -> (byte, io.Error) { r.prev_rune = -1 if r.i >= i64(len(r.s)) { @@ -160,6 +181,6 @@ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse case .Query: return io.query_utility({.Read, .Read_At, .Seek, .Size, .Query}) } - return 0, .Empty + return 0, .Unsupported } diff --git a/core/c/c.odin b/core/c/c.odin index 73727d8d5..cbff10e66 100644 --- a/core/c/c.odin +++ b/core/c/c.odin @@ -1,6 +1,8 @@ +// Defines the basic types used by `C` programs for foreign function and data structure interop. package c -import builtin "base:builtin" +import builtin "base:builtin" +import intrinsics "base:intrinsics" char :: builtin.u8 // assuming -funsigned-char @@ -48,7 +50,7 @@ int_least64_t :: builtin.i64 uint_least64_t :: builtin.u64 // Same on Windows, Linux, and FreeBSD -when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 { +when ODIN_ARCH == .i386 { int_fast8_t :: builtin.i8 uint_fast8_t :: builtin.u8 int_fast16_t :: builtin.i32 @@ -57,6 +59,15 @@ when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 { uint_fast32_t :: builtin.u32 int_fast64_t :: builtin.i64 uint_fast64_t :: builtin.u64 +} else when ODIN_ARCH == .amd64 { + int_fast8_t :: builtin.i8 + uint_fast8_t :: builtin.u8 + int_fast16_t :: long + uint_fast16_t :: ulong + int_fast32_t :: long + uint_fast32_t :: ulong + int_fast64_t :: builtin.i64 + uint_fast64_t :: builtin.u64 } else { int_fast8_t :: builtin.i8 uint_fast8_t :: builtin.u8 @@ -105,14 +116,6 @@ NDEBUG :: !ODIN_DEBUG CHAR_BIT :: 8 -// Since there are no types in C with an alignment larger than that of -// max_align_t, which cannot be larger than sizeof(long double) as any other -// exposed type wouldn't be valid C, the maximum alignment possible in a -// strictly conformant C implementation is 16 on the platforms we care about. -// The choice of 4096 bytes for storage of this type is more than enough on all -// relevant platforms. -va_list :: struct #align(16) { - _: [4096]u8, -} +va_list :: intrinsics.c_va_list FILE :: struct {} diff --git a/core/c/libc/complex.odin b/core/c/libc/complex.odin index 98fd7b1bb..7b6ac6417 100644 --- a/core/c/libc/complex.odin +++ b/core/c/libc/complex.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/core/c/libc/ctype.odin b/core/c/libc/ctype.odin index 185385a5e..d156f1ed7 100644 --- a/core/c/libc/ctype.odin +++ b/core/c/libc/ctype.odin @@ -3,7 +3,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/core/c/libc/doc.odin b/core/c/libc/doc.odin new file mode 100644 index 000000000..856ee41c6 --- /dev/null +++ b/core/c/libc/doc.odin @@ -0,0 +1,2 @@ +// Declares the commonly used things in `libc` (`C` standard library). +package libc diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin index 5d1ca8248..1f6df52f7 100644 --- a/core/c/libc/errno.odin +++ b/core/c/libc/errno.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -80,25 +80,6 @@ when ODIN_OS == .Darwin { ERANGE :: 34 } -when ODIN_OS == .Haiku { - @(private="file") - @(default_calling_convention="c") - foreign libc { - @(link_name="_errnop") - _get_errno :: proc() -> ^int --- - } - - _HAIKU_USE_POSITIVE_POSIX_ERRORS :: #config(HAIKU_USE_POSITIVE_POSIX_ERRORS, false) - _POSIX_ERROR_FACTOR :: -1 when _HAIKU_USE_POSITIVE_POSIX_ERRORS else 1 - - @(private="file") _GENERAL_ERROR_BASE :: min(int) - @(private="file") _POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000 - - EDOM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 16) - EILSEQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 38) - ERANGE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 17) -} - when ODIN_OS == .JS { _ :: libc _get_errno :: proc "c" () -> ^int { diff --git a/core/c/libc/locale.odin b/core/c/libc/locale.odin index d95f5c164..59cbc6c6d 100644 --- a/core/c/libc/locale.odin +++ b/core/c/libc/locale.odin @@ -5,7 +5,7 @@ import "core:c" when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -72,14 +72,14 @@ when ODIN_OS == .Windows { n_sep_by_space: c.char, p_sign_posn: c.char, n_sign_posn: c.char, - _W_decimal_point: [^]u16 `fmt:"s,0"`, - _W_thousands_sep: [^]u16 `fmt:"s,0"`, - _W_int_curr_symbol: [^]u16 `fmt:"s,0"`, - _W_currency_symbol: [^]u16 `fmt:"s,0"`, - _W_mon_decimal_point: [^]u16 `fmt:"s,0"`, - _W_mon_thousands_sep: [^]u16 `fmt:"s,0"`, - _W_positive_sign: [^]u16 `fmt:"s,0"`, - _W_negative_sign: [^]u16 `fmt:"s,0"`, + _W_decimal_point: cstring16, + _W_thousands_sep: cstring16, + _W_int_curr_symbol: cstring16, + _W_currency_symbol: cstring16, + _W_mon_decimal_point: cstring16, + _W_mon_thousands_sep: cstring16, + _W_positive_sign: cstring16, + _W_negative_sign: cstring16, } } else { lconv :: struct { @@ -110,7 +110,7 @@ when ODIN_OS == .Windows { } } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Windows { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Windows { LC_ALL :: 0 LC_COLLATE :: 1 diff --git a/core/c/libc/math.odin b/core/c/libc/math.odin index 81d51728d..bc3dd9034 100644 --- a/core/c/libc/math.odin +++ b/core/c/libc/math.odin @@ -7,7 +7,7 @@ import "base:intrinsics" when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -154,12 +154,12 @@ _nan_bit_pattern := ~u64(0) // On amd64 Windows and Linux, float_t and double_t are respectively both // their usual types. On x86 it's not possible to define these types correctly -// since they would be long double which Odin does have support for. +// since they would be long double which Odin does NOT have support for. float_t :: float double_t :: double NAN := transmute(double)(_nan_bit_pattern) -INFINITY :: 1e5000 +INFINITY :: 0h7ff00000_00000000 // +Inf HUGE_VALF :: INFINITY HUGE_VAL :: double(INFINITY) diff --git a/core/c/libc/setjmp.odin b/core/c/libc/setjmp.odin index 101b614b3..4f5319316 100644 --- a/core/c/libc/setjmp.odin +++ b/core/c/libc/setjmp.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/core/c/libc/signal.odin b/core/c/libc/signal.odin index c447e3cc3..cfe9768c9 100644 --- a/core/c/libc/signal.odin +++ b/core/c/libc/signal.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -34,7 +34,7 @@ when ODIN_OS == .Windows { SIGTERM :: 15 } -when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Darwin { +when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Darwin { SIG_ERR :: rawptr(~uintptr(0)) SIG_DFL :: rawptr(uintptr(0)) SIG_IGN :: rawptr(uintptr(1)) diff --git a/core/c/libc/stdarg.odin b/core/c/libc/stdarg.odin index 232471713..339e4cb54 100644 --- a/core/c/libc/stdarg.odin +++ b/core/c/libc/stdarg.odin @@ -4,29 +4,12 @@ package libc import "base:intrinsics" -import "core:c" +va_list :: intrinsics.c_va_list -@(private="file") -@(default_calling_convention="none") -foreign _ { - @(link_name="llvm.va_start") _va_start :: proc(arglist: ^i8) --- - @(link_name="llvm.va_end") _va_end :: proc(arglist: ^i8) --- - @(link_name="llvm.va_copy") _va_copy :: proc(dst, src: ^i8) --- -} +va_start :: intrinsics.c_va_start +va_end :: intrinsics.c_va_end +va_copy :: intrinsics.c_va_copy -va_list :: c.va_list - -va_start :: #force_inline proc(ap: ^va_list, _: any) { - _va_start(cast(^i8)ap) -} - -va_end :: #force_inline proc(ap: ^va_list) { - _va_end(cast(^i8)ap) -} - -va_copy :: #force_inline proc(dst, src: ^va_list) { - _va_copy(cast(^i8)dst, cast(^i8)src) -} // We cannot provide va_arg as there is no way to create "C" style procedures // in Odin which take variable arguments the C way. The #c_vararg attribute only diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index 56e4e8f66..ffdb06f67 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -9,7 +9,7 @@ when ODIN_OS == .Windows { "system:legacy_stdio_definitions.lib", } } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -200,36 +200,6 @@ when ODIN_OS == .Darwin { } } -when ODIN_OS == .Haiku { - fpos_t :: distinct i64 - - _IOFBF :: 0 - _IOLBF :: 1 - _IONBF :: 2 - - BUFSIZ :: 8192 - - EOF :: int(-1) - - FOPEN_MAX :: 128 - - FILENAME_MAX :: 256 - - L_tmpnam :: 512 - - SEEK_SET :: 0 - SEEK_CUR :: 1 - SEEK_END :: 2 - - TMP_MAX :: 32768 - - foreign libc { - stderr: ^FILE - stdin: ^FILE - stdout: ^FILE - } -} - when ODIN_OS == .NetBSD { @(private) LRENAME :: "__posix_rename" @(private) LFGETPOS :: "__fgetpos50" @@ -275,7 +245,7 @@ foreign libc { // 7.21.7 Character input/output functions fgetc :: proc(stream: ^FILE) -> int --- fgets :: proc(s: [^]char, n: int, stream: ^FILE) -> [^]char --- - fputc :: proc(s: cstring, stream: ^FILE) -> int --- + fputc :: proc(s: c.int, stream: ^FILE) -> int --- getc :: proc(stream: ^FILE) -> int --- getchar :: proc() -> int --- putc :: proc(c: int, stream: ^FILE) -> int --- @@ -390,7 +360,7 @@ to_stream :: proc(file: ^FILE) -> io.Stream { } case .Destroy: - return 0, .Empty + return 0, .Unsupported case .Query: return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query }) diff --git a/core/c/libc/stdlib.odin b/core/c/libc/stdlib.odin index c0e273872..f63f40cd0 100644 --- a/core/c/libc/stdlib.odin +++ b/core/c/libc/stdlib.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -42,22 +42,6 @@ when ODIN_OS == .Linux { } } -when ODIN_OS == .Haiku { - RAND_MAX :: 0x7fffffff - - // GLIBC and MUSL only - @(private="file") - @(default_calling_convention="c") - foreign libc { - __ctype_get_mb_cur_max :: proc() -> ushort --- - } - - MB_CUR_MAX :: #force_inline proc() -> size_t { - return size_t(__ctype_get_mb_cur_max()) - } -} - - when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD { RAND_MAX :: 0x7fffffff diff --git a/core/c/libc/string.odin b/core/c/libc/string.odin index 4ec4f3a7a..2ea54579c 100644 --- a/core/c/libc/string.odin +++ b/core/c/libc/string.odin @@ -7,7 +7,7 @@ import "base:runtime" when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin index 33f8dc3af..d431a84d7 100644 --- a/core/c/libc/time.odin +++ b/core/c/libc/time.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -45,7 +45,7 @@ when ODIN_OS == .Windows { } } -when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS { +when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .JS { @(default_calling_convention="c") foreign libc { // 7.27.2 Time manipulation functions @@ -95,7 +95,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS = time_t :: distinct i64 - when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku { + when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { clock_t :: distinct int32_t } else { clock_t :: distinct long diff --git a/core/c/libc/uchar.odin b/core/c/libc/uchar.odin index a10969ceb..997b99b46 100644 --- a/core/c/libc/uchar.odin +++ b/core/c/libc/uchar.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/core/c/libc/wchar.odin b/core/c/libc/wchar.odin index f0dae720e..73db7296c 100644 --- a/core/c/libc/wchar.odin +++ b/core/c/libc/wchar.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -17,12 +17,12 @@ foreign libc { fwscanf :: proc(stream: ^FILE, format: [^]wchar_t, #c_vararg arg: ..any) -> int --- swprintf :: proc(stream: ^FILE, n: size_t, format: [^]wchar_t, #c_vararg arg: ..any) -> int --- swscanf :: proc(s, format: [^]wchar_t, #c_vararg arg: ..any) -> int --- - vfwprintf :: proc(stream: ^FILE, format: [^]wchar_t, arg: va_list) -> int --- - vfwscanf :: proc(stream: ^FILE, format: [^]wchar_t, arg: va_list) -> int --- - vswprintf :: proc(s: [^]wchar_t, n: size_t, format: [^]wchar_t, arg: va_list) -> int --- - vswscanf :: proc(s, format: [^]wchar_t, arg: va_list) -> int --- - vwprintf :: proc(format: [^]wchar_t, arg: va_list) -> int --- - vwscanf :: proc(format: [^]wchar_t, arg: va_list) -> int --- + vfwprintf :: proc(stream: ^FILE, format: [^]wchar_t, arg: ^va_list) -> int --- + vfwscanf :: proc(stream: ^FILE, format: [^]wchar_t, arg: ^va_list) -> int --- + vswprintf :: proc(s: [^]wchar_t, n: size_t, format: [^]wchar_t, arg: ^va_list) -> int --- + vswscanf :: proc(s, format: [^]wchar_t, arg: ^va_list) -> int --- + vwprintf :: proc(format: [^]wchar_t, arg: ^va_list) -> int --- + vwscanf :: proc(format: [^]wchar_t, arg: ^va_list) -> int --- wprintf :: proc(format: [^]wchar_t, #c_vararg arg: ..any) -> int --- wscanf :: proc(format: [^]wchar_t, #c_vararg arg: ..any) -> int --- diff --git a/core/c/libc/wctype.odin b/core/c/libc/wctype.odin index b96410b4c..7d39e75c0 100644 --- a/core/c/libc/wctype.odin +++ b/core/c/libc/wctype.odin @@ -5,7 +5,7 @@ package libc when ODIN_OS == .Windows { foreign import libc "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -30,10 +30,6 @@ when ODIN_OS == .Windows { wctrans_t :: distinct int wctype_t :: distinct ulong -} else when ODIN_OS == .Haiku { - wctrans_t :: distinct i32 - wctype_t :: distinct i32 - } @(default_calling_convention="c") diff --git a/core/compress/common.odin b/core/compress/common.odin index 242538e78..fcda3fc20 100644 --- a/core/compress/common.odin +++ b/core/compress/common.odin @@ -1,15 +1,14 @@ +// A collection of utilities to aid with other `compress`ion packages. +package compress + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation, optimization. */ - -// package compress is a collection of utilities to aid with other compression packages -package compress - import "core:io" import "core:bytes" import "base:runtime" @@ -139,9 +138,6 @@ Context_Memory_Input :: struct #packed { } when size_of(rawptr) == 8 { #assert(size_of(Context_Memory_Input) == 64) -} else { - // e.g. `-target:windows_i386` - #assert(size_of(Context_Memory_Input) == 52) } Context_Stream_Input :: struct #packed { @@ -301,7 +297,7 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid curr := z.input->impl_seek(0, .Current) or_return r, e1 := io.to_reader_at(z.input) if !e1 { - return T{}, .Empty + return T{}, .Unsupported } when size <= 128 { b: [size]u8 @@ -310,7 +306,7 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid } _, e2 := io.read_at(r, b[:], curr) if e2 != .None { - return T{}, .Empty + return T{}, .Unsupported } res = (^T)(&b[0])^ @@ -328,7 +324,7 @@ peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input, r, e3 := io.to_reader_at(z.input) if !e3 { - return T{}, .Empty + return T{}, .Unsupported } when size <= 128 { b: [size]u8 @@ -337,7 +333,7 @@ peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input, } _, e4 := io.read_at(r, b[:], pos) if e4 != .None { - return T{}, .Empty + return T{}, .Unsupported } // Return read head to original position. @@ -364,23 +360,26 @@ refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width := refill := u64(width) b := u64(0) - if z.num_bits > refill { - return - } - for { + if z.num_bits > refill { + break + } + if z.code_buffer == 0 && z.num_bits > 63 { + z.num_bits = 0 + } + if z.code_buffer >= 1 << uint(z.num_bits) { + // Code buffer is malformed. + z.num_bits = max(u64) + return + } if len(z.input_data) != 0 { b = u64(z.input_data[0]) z.input_data = z.input_data[1:] } else { - b = 0 + return } - z.code_buffer |= b << u8(z.num_bits) z.num_bits += 8 - if z.num_bits > refill { - break - } } } diff --git a/core/compress/gzip/doc.odin b/core/compress/gzip/doc.odin index fd7ef5a19..e4b1929dd 100644 --- a/core/compress/gzip/doc.odin +++ b/core/compress/gzip/doc.odin @@ -1,19 +1,11 @@ /* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. +A small `GZIP` unpacker. - List of contributors: - Jeroen van Rijn: Initial implementation. - Ginger Bill: Cosmetic changes. - - A small GZIP implementation as an example. -*/ - -/* Example: import "core:bytes" import "core:os" import "core:compress" + import "core:compress/gzip" import "core:fmt" // Small GZIP file with fextra, fname and fcomment present. @@ -31,7 +23,8 @@ Example: main :: proc() { // Set up output buffer. - buf := bytes.Buffer{} + buf: bytes.Buffer + defer bytes.buffer_destroy(&buf) stdout :: proc(s: string) { os.write_string(os.stdout, s) @@ -40,15 +33,13 @@ Example: os.write_string(os.stderr, s) } - args := os.args - - if len(args) < 2 { + if len(os.args) < 2 { stderr("No input file specified.\n") - err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST)) + err := gzip.load(data=TEST, buf=&buf, known_gzip_size=len(TEST)) if err == nil { - stdout("Displaying test vector: ") + stdout("Displaying test vector: \"") stdout(bytes.buffer_to_string(&buf)) - stdout("\n") + stdout("\"\n") } else { fmt.printf("gzip.load returned %v\n", err) } @@ -56,35 +47,42 @@ Example: os.exit(0) } - // The rest are all files. - args = args[1:] - err: Error + for file in os.args[1:] { + err: gzip.Error - for file in args { if file == "-" { // Read from stdin - s := os.stream_from_handle(os.stdin) ctx := &compress.Context_Stream_Input{ - input = s, + input = os.stdin.stream, } - err = load(ctx, &buf) + err = gzip.load(ctx, &buf) } else { - err = load(file, &buf) + err = gzip.load(file, &buf) } - if err != nil { - if err != E_General.File_Not_Found { - stderr("File not found: ") - stderr(file) - stderr("\n") - os.exit(1) - } + switch err { + case nil: + stdout(bytes.buffer_to_string(&buf)) + case gzip.E_General.File_Not_Found: + stderr("File not found: ") + stderr(file) + stderr("\n") + os.exit(1) + case: stderr("GZIP returned an error.\n") - bytes.buffer_destroy(&buf) os.exit(2) } - stdout(bytes.buffer_to_string(&buf)) } - bytes.buffer_destroy(&buf) } */ package compress_gzip + +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. + Ginger Bill: Cosmetic changes. + + A small GZIP implementation as an example. +*/ \ No newline at end of file diff --git a/core/compress/gzip/gzip.odin b/core/compress/gzip/gzip.odin index 57ed3c3c5..aedbe3a83 100644 --- a/core/compress/gzip/gzip.odin +++ b/core/compress/gzip/gzip.odin @@ -2,7 +2,7 @@ package compress_gzip /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. @@ -107,14 +107,10 @@ load :: proc{load_from_bytes, load_from_file, load_from_context} load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { context.allocator = allocator - data, ok := os.read_entire_file(filename) - defer delete(data) + file_data, file_err := os.read_entire_file(filename, allocator) + defer delete(file_data) - err = E_General.File_Not_Found - if ok { - err = load_from_bytes(data, buf, len(data), expected_output_size) - } - return + return load_from_bytes(file_data, buf, len(file_data), expected_output_size) if file_err == nil else E_General.File_Not_Found } load_from_bytes :: proc(data: []byte, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) { diff --git a/core/compress/shoco/model.odin b/core/compress/shoco/model.odin index 919563441..bca58386b 100644 --- a/core/compress/shoco/model.odin +++ b/core/compress/shoco/model.odin @@ -1,11 +1,11 @@ +package compress_shoco + /* This file was generated, so don't edit this by hand. Transliterated from https://github.com/Ed-von-Schleck/shoco/blob/master/shoco_model.h, which is an English word model. */ -package compress_shoco - DEFAULT_MODEL :: Shoco_Model { min_char = 39, max_char = 122, diff --git a/core/compress/shoco/shoco.odin b/core/compress/shoco/shoco.odin index b393b8356..b112ddb04 100644 --- a/core/compress/shoco/shoco.odin +++ b/core/compress/shoco/shoco.odin @@ -1,6 +1,9 @@ +// `Shoco` short string compression and decompression. +package compress_shoco + /* Copyright 2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. @@ -8,9 +11,6 @@ An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm. */ -// package shoco is an implementation of the shoco short string compressor. -package compress_shoco - import "base:intrinsics" import "core:compress" diff --git a/core/compress/zlib/doc.odin b/core/compress/zlib/doc.odin index 6ae537a87..8dac17587 100644 --- a/core/compress/zlib/doc.odin +++ b/core/compress/zlib/doc.odin @@ -1,14 +1,6 @@ /* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. +`Deflate` decompression of raw and `ZLIB`-type streams. - List of contributors: - Jeroen van Rijn: Initial implementation. - - An example of how to use `zlib.inflate`. -*/ - -/* Example: package main @@ -49,3 +41,13 @@ Example: } */ package compress_zlib + +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. + + An example of how to use `zlib.inflate`. +*/ \ No newline at end of file diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin index be8a7d7d3..efa9cb906 100644 --- a/core/compress/zlib/zlib.odin +++ b/core/compress/zlib/zlib.odin @@ -1,9 +1,9 @@ -#+vet !using-param +#+feature using-stmt package compress_zlib /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation, optimization. @@ -322,9 +322,6 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro @(optimization_mode="favor_size") decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check { if z.num_bits < 16 { - if z.num_bits > 63 { - return 0, .Code_Buffer_Malformed - } compress.refill_lsb(z) if z.num_bits > 63 { return 0, .Stream_Too_Short diff --git a/core/container/avl/avl.odin b/core/container/avl/avl.odin index 8a9d1f3d9..1208cd213 100644 --- a/core/container/avl/avl.odin +++ b/core/container/avl/avl.odin @@ -1,8 +1,4 @@ -/* -package avl implements an AVL tree. - -The implementation is non-intrusive, and non-recursive. -*/ +// A non-intrusive and non-recursive implementation of `AVL` trees. package container_avl @(require) import "base:intrinsics" @@ -104,20 +100,20 @@ len :: proc "contextless" (t: ^$T/Tree($Value)) -> int { return t._size } -// first returns the first node in the tree (in-order) or nil iff +// first returns the first node in the tree (in-order) or nil if and only if (⟺) // the tree is empty. first :: proc "contextless" (t: ^$T/Tree($Value)) -> ^Node(Value) { return tree_first_or_last_in_order(t, Direction.Backward) } -// last returns the last element in the tree (in-order) or nil iff +// last returns the last element in the tree (in-order) or nil if and only if (⟺) // the tree is empty. last :: proc "contextless" (t: ^$T/Tree($Value)) -> ^Node(Value) { return tree_first_or_last_in_order(t, Direction.Forward) } // find finds the value in the tree, and returns the corresponding -// node or nil iff the value is not present. +// node or nil if and only if (⟺) the value is not present. find :: proc(t: ^$T/Tree($Value), value: Value) -> ^Node(Value) { cur := t._root descend_loop: for cur != nil { @@ -172,7 +168,7 @@ find_or_insert :: proc( return } -// remove removes a node or value from the tree, and returns true iff the +// remove removes a node or value from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's value will be left intact, // the node itself will be freed via the tree's node allocator. remove :: proc { @@ -180,7 +176,7 @@ remove :: proc { remove_node, } -// remove_value removes a value from the tree, and returns true iff the +// remove_value removes a value from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's value will be left intact, // the node itself will be freed via the tree's node allocator. remove_value :: proc(t: ^$T/Tree($Value), value: Value, call_on_remove: bool = true) -> bool { @@ -191,7 +187,7 @@ remove_value :: proc(t: ^$T/Tree($Value), value: Value, call_on_remove: bool = t return remove_node(t, n, call_on_remove) } -// remove_node removes a node from the tree, and returns true iff the +// remove_node removes a node from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's value will be left intact, // the node itself will be freed via the tree's node allocator. remove_node :: proc(t: ^$T/Tree($Value), node: ^Node(Value), call_on_remove: bool = true) -> bool { @@ -285,14 +281,14 @@ iterator_from_pos :: proc "contextless" ( } // iterator_get returns the node currently pointed to by the iterator, -// or nil iff the node has been removed, the tree is empty, or the end +// or nil if and only if (⟺) the node has been removed, the tree is empty, or the end // of the tree has been reached. iterator_get :: proc "contextless" (it: ^$I/Iterator($Value)) -> ^Node(Value) { return it._cur } // iterator_remove removes the node currently pointed to by the iterator, -// and returns true iff the removal was successful. Semantics are the +// and returns true if and only if (⟺) the removal was successful. Semantics are the // same as the Tree remove. iterator_remove :: proc(it: ^$I/Iterator($Value), call_on_remove: bool = true) -> bool { if it._cur == nil { @@ -308,7 +304,7 @@ iterator_remove :: proc(it: ^$I/Iterator($Value), call_on_remove: bool = true) - } // iterator_next advances the iterator and returns the (node, true) or -// or (nil, false) iff the end of the tree has been reached. +// or (nil, false) if and only if (⟺) the end of the tree has been reached. // // Note: The first call to iterator_next will return the first node instead // of advancing the iterator. diff --git a/core/container/bit_array/bit_array.odin b/core/container/bit_array/bit_array.odin index 85b941d12..7d74d9ba7 100644 --- a/core/container/bit_array/bit_array.odin +++ b/core/container/bit_array/bit_array.odin @@ -2,7 +2,6 @@ package container_dynamic_bit_array import "base:builtin" import "base:intrinsics" -import "core:mem" /* Note that these constants are dependent on the backing being a u64. @@ -329,7 +328,7 @@ Inputs: */ clear :: proc(ba: ^Bit_Array) { if ba == nil { return } - mem.zero_slice(ba.bits[:]) + intrinsics.mem_zero(raw_data(ba.bits), builtin.len(ba.bits) * NUM_BITS / 8) } /* Gets the length of set and unset valid bits in the Bit_Array. diff --git a/core/container/bit_array/doc.odin b/core/container/bit_array/doc.odin index 36bf90002..e86059ecd 100644 --- a/core/container/bit_array/doc.odin +++ b/core/container/bit_array/doc.odin @@ -1,7 +1,9 @@ /* +A dynamically-sized array of bits. + The Bit Array can be used in several ways: -By default you don't need to instantiate a Bit Array. +By default you don't need to instantiate a `Bit_Array`. Example: package test @@ -18,11 +20,11 @@ Example: // returns `false`, `false`, because this Bit Array wasn't created to allow negative indices. was_set, was_retrieved := get(&bits, -1) - fmt.println(was_set, was_retrieved) + fmt.println(was_set, was_retrieved) destroy(&bits) } -A Bit Array can optionally allow for negative indices, if the minimum value was given during creation. +A `Bit_Array` can optionally allow for negative indices, if the minimum value was given during creation. Example: package test @@ -49,4 +51,4 @@ Example: fmt.printf("Freed.\n") } */ -package container_dynamic_bit_array +package container_dynamic_bit_array \ No newline at end of file diff --git a/core/container/handle_map/doc.odin b/core/container/handle_map/doc.odin new file mode 100644 index 000000000..16b285982 --- /dev/null +++ b/core/container/handle_map/doc.odin @@ -0,0 +1,60 @@ +/* +Handle-based map using either fixed-length arrays, or exponential arrays from "core:container/xar". + +Example: + import hm "core:container/handle_map" + + Handle :: hm.Handle32 + + Entity :: struct { + handle: Handle, + pos: [2]f32, + } + + { // static map + entities: hm.Static_Handle_Map(1024, Entity, Handle) + + h1 := hm.add(&entities, Entity{pos = {1, 4}}) + h2 := hm.add(&entities, Entity{pos = {9, 16}}) + + if e, ok := hm.get(&entities, h2); ok { + e.pos.x += 32 + } + + hm.remove(&entities, h1) + + h3 := hm.add(&entities, Entity{pos = {6, 7}}) + assert(hm.is_valid(entities, h3)) + + it := hm.iterator_make(&entities) + for e, h in hm.iterate(&it) { + assert(hm.is_valid(entities, h)) + e.pos += {1, 2} + } + } + + { // dynamic map + entities: hm.Dynamic_Handle_Map(Entity, Handle) + hm.dynamic_init(&entities, context.allocator) + defer hm.dynamic_destroy(&entities) + + h1 := hm.add(&entities, Entity{pos = {1, 4}}) + h2 := hm.add(&entities, Entity{pos = {9, 16}}) + + if e, ok := hm.get(&entities, h2); ok { + e.pos.x += 32 + } + + hm.remove(&entities, h1) + + h3 := hm.add(&entities, Entity{pos = {6, 7}}) + assert(hm.is_valid(entities, h3)) + + it := hm.iterator_make(&entities) + for e, h in hm.iterate(&it) { + assert(hm.is_valid(entities, h)) + e.pos += {1, 2} + } + } +*/ +package container_handle_map \ No newline at end of file diff --git a/core/container/handle_map/dynamic_handle_map.odin b/core/container/handle_map/dynamic_handle_map.odin new file mode 100644 index 000000000..09ea92f82 --- /dev/null +++ b/core/container/handle_map/dynamic_handle_map.odin @@ -0,0 +1,142 @@ +package container_handle_map + +import "base:runtime" +import "base:builtin" +import "base:intrinsics" +@(require) import "core:container/xar" + +Dynamic_Handle_Map :: struct($T: typeid, $Handle_Type: typeid) + where + intrinsics.type_has_field(Handle_Type, "idx"), + intrinsics.type_has_field(Handle_Type, "gen"), + intrinsics.type_is_unsigned(intrinsics.type_field_type(Handle_Type, "idx")), + intrinsics.type_is_unsigned(intrinsics.type_field_type(Handle_Type, "gen")), + intrinsics.type_field_type(Handle_Type, "idx") == intrinsics.type_field_type(Handle_Type, "gen"), + + intrinsics.type_has_field (T, "handle"), + intrinsics.type_field_type(T, "handle") == Handle_Type { + + items: xar.Array(T, 4), + unused_items: xar.Array(u32, 4), +} + +dynamic_init :: proc(m: ^$D/Dynamic_Handle_Map($T, $Handle_Type), allocator: runtime.Allocator) { + xar.init(&m.items, allocator) + xar.init(&m.unused_items, allocator) +} + +dynamic_destroy :: proc(m: ^$D/Dynamic_Handle_Map($T, $Handle_Type)) { + xar.destroy(&m.unused_items) + xar.destroy(&m.items) +} + +@(require_results) +dynamic_add :: proc(m: ^$D/Dynamic_Handle_Map($T, $Handle_Type), item: T, loc := #caller_location) -> (handle: Handle_Type, err: runtime.Allocator_Error) #optional_allocator_error { + if xar.len(m.unused_items) > 0 { + i := xar.pop(&m.unused_items) + ptr := xar.get_ptr_unsafe(&m.items, i) + prev_gen := ptr.handle.gen + ptr^ = item + + ptr.handle.idx = auto_cast i + ptr.handle.gen = auto_cast (prev_gen + 1) + return ptr.handle, nil + } + + if xar.len(m.items) == 0 { + // initialize the zero-value sentinel + xar.append(&m.items, T{}, loc) or_return + } + + _ = xar.append(&m.items, item, loc) or_return + i := xar.len(m.items)-1 + + ptr := xar.get_ptr_unsafe(&m.items, i) + + ptr.handle.idx = auto_cast i + ptr.handle.gen = 1 + return ptr.handle, nil +} + +@(require_results) +dynamic_get :: proc "contextless" (m: ^$D/Dynamic_Handle_Map($T, $Handle_Type), h: Handle_Type) -> (^T, bool) #optional_ok { + if h.idx <= 0 || int(u32(h.idx)) >= xar.len(m.items) { + return nil, false + } + if e := xar.get_ptr_unsafe(&m.items, h.idx); e.handle == h { + return e, true + } + return nil, false +} + +dynamic_remove :: proc(m: ^$D/Dynamic_Handle_Map($T, $Handle_Type), h: Handle_Type, loc := #caller_location) -> (found: bool, err: runtime.Allocator_Error) { + if h.idx <= 0 || int(u32(h.idx)) >= xar.len(m.items) { + return false, nil + } + + if item := xar.get_ptr(&m.items, h.idx); item.handle == h { + xar.append(&m.unused_items, u32(h.idx), loc) or_return + item.handle.idx = 0 + return true, nil + } + + return false, nil +} + +@(require_results) +dynamic_is_valid :: proc "contextless" (m: ^$D/Dynamic_Handle_Map($T, $Handle_Type), h: Handle_Type) -> bool { + return h.idx > 0 && int(u32(h.idx)) < xar.len(m.items) && xar.get_ptr_unsafe(&m.items, h.idx).handle == h +} + +// Returns the number of possibly valid items in the handle map. +@(require_results) +dynamic_len :: proc "contextless" (m: $D/Dynamic_Handle_Map($T, $Handle_Type)) -> uint { + n := xar.len(m.items) - xar.len(m.unused_items) + return uint(n-1 if n > 0 else 0) +} + +@(require_results) +dynamic_cap :: proc "contextless" (m: $D/Dynamic_Handle_Map($T, $Handle_Type)) -> uint { + n := xar.cap(m.items) + return uint(n-1 if n > 0 else 0) +} + +dynamic_clear :: proc "contextless" (m: ^$D/Dynamic_Handle_Map($T, $Handle_Type)) { + xar.clear(&m.items) + xar.clear(&m.unused_items) +} + + +// An iterator for a handle map. +Dynamic_Handle_Map_Iterator :: struct($D: typeid) { + m: ^D, + index: int, +} + +// Makes an iterator from a handle map. +@(require_results) +dynamic_iterator_make :: proc "contextless" (m: ^$D/Dynamic_Handle_Map($T, $Handle_Type)) -> Dynamic_Handle_Map_Iterator(D) { + return {m, 1} +} + +/* + Iterate over a handle map. It will skip over unused item slots (e.g. handle.idx == 0). + Usage: + it := hm.dynamic_iterator_make(&the_dynamic_handle_map) + for item, handle in hm.iterate(&it) { + ... + } +*/ +@(require_results) +dynamic_iterate :: proc "contextless" (it: ^$DHI/Dynamic_Handle_Map_Iterator($D/Dynamic_Handle_Map($T, $Handle_Type))) -> (val: ^T, h: Handle_Type, ok: bool) { + for _ in it.index.. (handle: Handle_Type, ok: bool) #optional_ok { + if i := m.next_unused; i != 0 { + ptr := &m.items[i] + + m.next_unused = m.unused_items[i] + m.unused_items[i] = 0 + + prev_gen := ptr.handle.gen + ptr^ = item + + ptr.handle.idx = auto_cast i + ptr.handle.gen = auto_cast (prev_gen + 1) + m.unused_len -= 1 + return ptr.handle, true + } + + if m.used_len == 0 { + // initialize the zero-value sentinel + m.items[0] = {} + m.used_len += 1 + } + + if m.used_len == builtin.len(m.items) { + return {}, false + } + + ptr := &m.items[m.used_len] + ptr^ = item + + ptr.handle.idx = auto_cast m.used_len + ptr.handle.gen = 1 + m.used_len += 1 + return ptr.handle, true +} + +// `get` a stable pointer of type `^T` by resolving the handle `h`. If the handle is not valid, then `nil, false` is returned. +@(require_results) +static_get :: proc "contextless" (m: ^$H/Static_Handle_Map($N, $T, $Handle_Type), h: Handle_Type) -> (^T, bool) #optional_ok { + if h.idx <= 0 || u32(h.idx) >= m.used_len { + return nil, false + } + if e := &m.items[h.idx]; e.handle == h { + return e, true + } + return nil, false +} + +// `remove` an item from the handle map from the handle `h`. +static_remove :: proc "contextless" (m: ^$H/Static_Handle_Map($N, $T, $Handle_Type), h: Handle_Type) -> bool { + if h.idx <= 0 || u32(h.idx) >= m.used_len { + return false + } + + if item := &m.items[h.idx]; item.handle == h { + m.unused_items[h.idx] = m.next_unused + m.next_unused = u32(h.idx) + m.unused_len += 1 + item.handle.idx = 0 + return true + } + + return false +} + +// Returns true when the handle `h` is valid relating to the handle map. +@(require_results) +static_is_valid :: proc "contextless" (m: $H/Static_Handle_Map($N, $T, $Handle_Type), h: Handle_Type) -> bool { + return h.idx > 0 && u32(h.idx) < m.used_len && m.items[h.idx].handle == h +} + +// Returns the number of possibly valid items in the handle map. +@(require_results) +static_len :: proc "contextless" (m: $H/Static_Handle_Map($N, $T, $Handle_Type)) -> uint { + n := uint(m.used_len) - uint(m.unused_len) + return n-1 if n > 0 else 0 +} + +// Returns the capacity of the items in a handle map. +// This is equivalent to `N-1` as the zero value is reserved for the zero-value sentinel. +@(require_results) +static_cap :: proc "contextless" (m: $H/Static_Handle_Map($N, $T, $Handle_Type)) -> uint { + // We could just return `N` but I am doing this for clarity + return builtin.len(m.items)-1 +} + +// `clear` the handle map by zeroing all of the memory. +// Internally this does not do `m^ = {}` but rather uses `intrinsics.mem_zero` explicitly improve performance. +static_clear :: proc "contextless" (m: ^$H/Static_Handle_Map($N, $T, $Handle_Type)) { + intrinsics.mem_zero(m, size_of(m^)) +} + +// An iterator for a handle map. +Static_Handle_Map_Iterator :: struct($H: typeid) { + m: ^H, + index: u32, +} + +// Makes an iterator from a handle map. +@(require_results) +static_iterator_make :: proc "contextless" (m: ^$H/Static_Handle_Map($N, $T, $Handle_Type)) -> Static_Handle_Map_Iterator(H) { + return {m, 1} +} + +/* + Iterate over a handle map. It will skip over unused item slots (e.g. handle.idx == 0). + Usage: + it := hm.iterator_make(&the_handle_map) + for item, handle in hm.iterate(&it) { + ... + } +*/ +@(require_results) +static_iterate :: proc "contextless" (it: ^$HI/Static_Handle_Map_Iterator($H/Static_Handle_Map($N, $T, $Handle_Type))) -> (val: ^T, h: Handle_Type, ok: bool) { + for _ in it.index.. (err: runtime.Allocator_Error) + where intrinsics.type_has_field(T, link_field), + intrinsics.type_field_type(T, link_field) == ^T { + p.link_off = offset_of_by_string(T, link_field) + return _pool_arena_init(&p.arena, block_size) +} + +destroy :: proc(p: ^Pool($T)) { + elem := sync.atomic_exchange_explicit(&p.free_list, nil, .Acquire) + + sync.atomic_store_explicit(&p.num_ready, 0, .Relaxed) + + when .Address in ODIN_SANITIZER_FLAGS { + for ; elem != nil; elem = _get_next(p, elem) { + _unpoison_elem(p, elem) + } + } else { + _ = elem + } + + _pool_arena_destroy(&p.arena) + p.arena = {} +} + +@(require_results) +get :: proc(p: ^Pool($T)) -> (elem: ^T, err: runtime.Allocator_Error) #optional_allocator_error { + defer sync.atomic_add_explicit(&p.num_outstanding, 1, .Relaxed) + + sync.mutex_lock(&p.mu) + elem = p.free_list + if elem == nil { + sync.mutex_unlock(&p.mu) + // NOTE: pool arena has an internal lock. + return new(T, _pool_arena_allocator(&p.arena)) + } + p.free_list = _get_next(p, elem) + sync.mutex_unlock(&p.mu) + + _set_next(p, elem, nil) + _unpoison_elem(p, elem) + sync.atomic_sub_explicit(&p.num_ready, 1, .Relaxed) + return +} + +put :: proc(p: ^Pool($T), elem: ^T) { + intrinsics.mem_zero(elem, size_of(T)) + _poison_elem(p, elem) + + defer sync.atomic_sub_explicit(&p.num_outstanding, 1, .Relaxed) + defer sync.atomic_add_explicit(&p.num_ready, 1, .Relaxed) + + sync.mutex_lock(&p.mu) + _set_next(p, elem, p.free_list) + p.free_list = elem + sync.mutex_unlock(&p.mu) +} + +num_outstanding :: proc(p: ^Pool($T)) -> int { + return sync.atomic_load(&p.num_outstanding) +} + +num_ready :: proc(p: ^Pool($T)) -> int { + return sync.atomic_load(&p.num_ready) +} + +cap :: proc(p: ^Pool($T)) -> int { + return sync.atomic_load(&p.num_ready) + sync.atomic_load(&p.num_outstanding) +} + +_get_next :: proc(p: ^Pool($T), elem: ^T) -> ^T { + return (^^T)(uintptr(elem) + p.link_off)^ +} + +_set_next :: proc(p: ^Pool($T), elem: ^T, next: ^T) { + (^^T)(uintptr(elem) + p.link_off)^ = next +} + +_poison_elem :: proc(p: ^Pool($T), elem: ^T) { + when .Address in ODIN_SANITIZER_FLAGS { + if p.link_off > 0 { + sanitizer.address_poison_rawptr(elem, int(p.link_off)) + } + + len := size_of(T) - p.link_off - size_of(rawptr) + if len > 0 { + ptr := rawptr(uintptr(elem) + p.link_off + size_of(rawptr)) + sanitizer.address_poison_rawptr(ptr, int(len)) + } + } +} + +_unpoison_elem :: proc(p: ^Pool($T), elem: ^T) { + when .Address in ODIN_SANITIZER_FLAGS { + if p.link_off > 0 { + sanitizer.address_unpoison_rawptr(elem, int(p.link_off)) + } + + len := size_of(T) - p.link_off - size_of(rawptr) + if len > 0 { + ptr := rawptr(uintptr(elem) + p.link_off + size_of(rawptr)) + sanitizer.address_unpoison_rawptr(ptr, int(len)) + } + } +} diff --git a/core/container/pool/pool_arena_others.odin b/core/container/pool/pool_arena_others.odin new file mode 100644 index 000000000..d2e01ffb7 --- /dev/null +++ b/core/container/pool/pool_arena_others.odin @@ -0,0 +1,27 @@ +#+build !darwin +#+build !freebsd +#+build !openbsd +#+build !netbsd +#+build !linux +#+build !windows +#+private +package container_pool + +import "base:runtime" + +_Pool_Arena :: runtime.Arena + +_DEFAULT_BLOCK_SIZE :: runtime.Megabyte + +_pool_arena_init :: proc(arena: ^Pool_Arena, block_size: uint = DEFAULT_BLOCK_SIZE) -> (err: runtime.Allocator_Error) { + runtime.arena_init(arena, block_size, runtime.default_allocator()) or_return + return +} + +_pool_arena_allocator :: proc(arena: ^Pool_Arena) -> runtime.Allocator { + return runtime.arena_allocator(arena) +} + +_pool_arena_destroy :: proc(arena: ^Pool_Arena) { + runtime.arena_destroy(arena) +} diff --git a/core/container/pool/pool_arena_virtual.odin b/core/container/pool/pool_arena_virtual.odin new file mode 100644 index 000000000..d622990fd --- /dev/null +++ b/core/container/pool/pool_arena_virtual.odin @@ -0,0 +1,22 @@ +#+build darwin, freebsd, openbsd, netbsd, linux, windows +package container_pool + +import "base:runtime" +import "core:mem/virtual" + +_Pool_Arena :: virtual.Arena + +_DEFAULT_BLOCK_SIZE :: runtime.Gigabyte + +_pool_arena_init :: proc(arena: ^Pool_Arena, block_size: uint = DEFAULT_BLOCK_SIZE) -> (err: runtime.Allocator_Error) { + virtual.arena_init_growing(arena, block_size) or_return + return +} + +_pool_arena_allocator :: proc(arena: ^Pool_Arena) -> runtime.Allocator { + return virtual.arena_allocator(arena) +} + +_pool_arena_destroy :: proc(arena: ^Pool_Arena) { + virtual.arena_destroy(arena) +} diff --git a/core/container/priority_queue/doc.odin b/core/container/priority_queue/doc.odin new file mode 100644 index 000000000..7779e6e0a --- /dev/null +++ b/core/container/priority_queue/doc.odin @@ -0,0 +1,53 @@ +/* +A priority queue data structure. + +Important: It needs to be initialized with `less` and `swap` procedures, see `init` and `init_from_dynamic_array`. + +Example: + import "base:runtime" + import pq "core:container/priority_queue" + + main :: proc() { + Printer_Job :: struct { + user_id: u64, + weight: enum u8 {Highest, High, Normal, Low, Idle}, + } + + q: pq.Priority_Queue(Printer_Job) + pq.init( + pq = &q, + less = proc(a, b: Printer_Job) -> bool { + // Jobs will be sorted in order of increasing weight + return a.weight < b.weight + }, + swap = pq.default_swap_proc(Printer_Job), + ) + defer pq.destroy(&q) + + // Add jobs with random weights + for _ in 0..<100 { + job: Printer_Job = --- + assert(runtime.random_generator_read_ptr(context.random_generator, &job, size_of(job))) + pq.push(&q, job) + } + + // Drain jobs in order of importance + last: Printer_Job + for pq.len(q) > 0 { + v := pq.pop(&q) + assert(v.weight >= last.weight) + last = v + } + + // Queue empty? + assert(pq.len(q) == 0) + + // Add one more job + pq.push(&q, Printer_Job{user_id = 42, weight = .Idle}) + + // Cancel all jobs + pq.clear(&q) + assert(pq.len(q) == 0) + } +*/ +package container_priority_queue \ No newline at end of file diff --git a/core/container/priority_queue/priority_queue.odin b/core/container/priority_queue/priority_queue.odin index 7387a8d09..c7e9f61dc 100644 --- a/core/container/priority_queue/priority_queue.odin +++ b/core/container/priority_queue/priority_queue.odin @@ -3,6 +3,10 @@ package container_priority_queue import "base:builtin" import "base:runtime" +// Priority Queue. +// +// Important: It needs to be initialized with `less` and `swap` procedures, see `init` and `init_from_dynamic_array`. +// See `doc.odin` for an example. Priority_Queue :: struct($T: typeid) { queue: [dynamic]T, @@ -133,12 +137,10 @@ pop_safe :: proc(pq: ^$Q/Priority_Queue($T), loc := #caller_location) -> (value: remove :: proc(pq: ^$Q/Priority_Queue($T), i: int) -> (value: T, ok: bool) { n := builtin.len(pq.queue) if 0 <= i && i < n { - if n != i { - pq.swap(pq.queue[:], i, n) - _shift_down(pq, i, n) - _shift_up(pq, i) - } - value, ok = builtin.pop_safe(&pq.queue) + pq.swap(pq.queue[:], i, n-1) + _shift_down(pq, i, n-1) + _shift_up(pq, i) + value, ok = builtin.pop(&pq.queue), true } return } diff --git a/core/container/queue/queue.odin b/core/container/queue/queue.odin index d1040a7c9..6790e825a 100644 --- a/core/container/queue/queue.odin +++ b/core/container/queue/queue.odin @@ -1,10 +1,17 @@ +// A dynamically resizable double-ended queue/ring-buffer. package container_queue import "base:builtin" import "base:runtime" _ :: runtime -// Dynamically resizable double-ended queue/ring-buffer +/* +`Queue` is a dynamically resizable double-ended queue/ring-buffer. + +Being double-ended means that either end may be pushed onto or popped from +across the same block of memory, in any order, thus providing both stack and +queue-like behaviors in the same data structure. +*/ Queue :: struct($T: typeid) { data: [dynamic]T, len: uint, @@ -13,18 +20,31 @@ Queue :: struct($T: typeid) { DEFAULT_CAPACITY :: 16 -// Procedure to initialize a queue -init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error { - if q.data.allocator.procedure == nil { - q.data.allocator = allocator - } +/* +Initialize a `Queue` with a starting `capacity` and an `allocator`. +*/ +init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error { clear(q) - return reserve(q, capacity) + q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ + data = nil, + len = 0, + cap = 0, + allocator = allocator, + } + return reserve(q, capacity, loc) } -// Procedure to initialize a queue from a fixed backing slice. -// The contents of the `backing` will be overwritten as items are pushed onto the `Queue`. -// Any previous contents are not available. +/* +Initialize a `Queue` from a fixed `backing` slice into which modifications are +made directly. + +The contents of the `backing` will be overwritten as items are pushed onto the +`Queue`. Any previous contents will not be available through the API but are +not explicitly zeroed either. + +Note that procedures which need space to work (`push_back`, ...) will fail if +the backing slice runs out of space. +*/ init_from_slice :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { clear(q) q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ @@ -36,8 +56,14 @@ init_from_slice :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { return true } -// Procedure to initialize a queue from a fixed backing slice. -// Existing contents are preserved and available on the queue. +/* +Initialize a `Queue` from a fixed `backing` slice into which modifications are +made directly. + +The contents of the queue will start out with all of the elements in `backing`, +effectively creating a full queue from the slice. As such, no procedures will +be able to add more elements to the queue until some are taken off. +*/ init_with_contents :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { clear(q) q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ @@ -50,87 +76,193 @@ init_with_contents :: proc(q: ^$Q/Queue($T), backing: []T) -> bool { return true } -// Procedure to destroy a queue +/* +Delete memory that has been dynamically allocated from a `Queue` that was setup with `init`. + +Note that this procedure should not be used on queues setup with +`init_from_slice` or `init_with_contents`, as neither of those procedures keep +track of the allocator state of the underlying `backing` slice. +*/ destroy :: proc(q: ^$Q/Queue($T)) { delete(q.data) } -// The length of the queue +/* +Return the length of the queue. +*/ len :: proc(q: $Q/Queue($T)) -> int { return int(q.len) } -// The current capacity of the queue +/* +Return the capacity of the queue. +*/ cap :: proc(q: $Q/Queue($T)) -> int { return builtin.len(q.data) } -// Remaining space in the queue (cap-len) +/* +Return the remaining space in the queue. + +This will be `cap() - len()`. +*/ space :: proc(q: $Q/Queue($T)) -> int { return builtin.len(q.data) - int(q.len) } -// Reserve enough space for at least the specified capacity -reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error { +/* +Reserve enough space in the queue for at least the specified capacity. + +This may return an error if allocation failed. +*/ +reserve :: proc(q: ^$Q/Queue($T), capacity: int, loc := #caller_location) -> runtime.Allocator_Error { if capacity > space(q^) { - return _grow(q, uint(capacity)) + return _grow(q, uint(capacity), loc) } return nil } +/* +Shrink a queue's dynamically allocated array. +This has no effect if the queue was initialized with a backing slice. +*/ +shrink :: proc(q: ^$Q/Queue($T), temp_allocator := context.temp_allocator, loc := #caller_location) { + if q.data.allocator.procedure == runtime.nil_allocator_proc { + return + } + + if q.len > 0 && q.offset > 0 { + // Make the array contiguous again. + buffer := make([]T, q.len, temp_allocator) + defer delete(buffer, temp_allocator) + + right := uint(builtin.len(q.data)) - q.offset + copy(buffer[:], q.data[q.offset:]) + copy(buffer[right:], q.data[:q.offset]) + + copy(q.data[:], buffer[:]) + + q.offset = 0 + } + + builtin.shrink(&q.data, q.len, loc) +} + +/* +Get the element at index `i`. + +This will raise a bounds checking error if `i` is an invalid index. +*/ get :: proc(q: ^$Q/Queue($T), #any_int i: int, loc := #caller_location) -> T { - runtime.bounds_check_error_loc(loc, i, builtin.len(q.data)) + runtime.bounds_check_error_loc(loc, i, int(q.len)) idx := (uint(i)+q.offset)%builtin.len(q.data) return q.data[idx] } -front :: proc(q: ^$Q/Queue($T)) -> T { - return q.data[q.offset] -} -front_ptr :: proc(q: ^$Q/Queue($T)) -> ^T { - return &q.data[q.offset] -} +/* +Get a pointer to the element at index `i`. -back :: proc(q: ^$Q/Queue($T)) -> T { - idx := (q.offset+uint(q.len - 1))%builtin.len(q.data) - return q.data[idx] -} -back_ptr :: proc(q: ^$Q/Queue($T)) -> ^T { - idx := (q.offset+uint(q.len - 1))%builtin.len(q.data) +This will raise a bounds checking error if `i` is an invalid index. +*/ +get_ptr :: proc(q: ^$Q/Queue($T), #any_int i: int, loc := #caller_location) -> ^T { + runtime.bounds_check_error_loc(loc, i, int(q.len)) + + idx := (uint(i)+q.offset)%builtin.len(q.data) return &q.data[idx] } +/* +Set the element at index `i` to `val`. + +This will raise a bounds checking error if `i` is an invalid index. +*/ set :: proc(q: ^$Q/Queue($T), #any_int i: int, val: T, loc := #caller_location) { - runtime.bounds_check_error_loc(loc, i, builtin.len(q.data)) - + runtime.bounds_check_error_loc(loc, i, int(q.len)) + idx := (uint(i)+q.offset)%builtin.len(q.data) q.data[idx] = val } -get_ptr :: proc(q: ^$Q/Queue($T), #any_int i: int, loc := #caller_location) -> ^T { - runtime.bounds_check_error_loc(loc, i, builtin.len(q.data)) - - idx := (uint(i)+q.offset)%builtin.len(q.data) + +/* +Get the element at the front of the queue. + +This will raise a bounds checking error if the queue is empty. +*/ +front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> T { + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } + return q.data[q.offset] +} + +/* +Get a pointer to the element at the front of the queue. + +This will raise a bounds checking error if the queue is empty. +*/ +front_ptr :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T { + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } + return &q.data[q.offset] +} + +/* +Get the element at the back of the queue. + +This will raise a bounds checking error if the queue is empty. +*/ +back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> T { + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } + idx := (q.offset+uint(q.len - 1))%builtin.len(q.data) + return q.data[idx] +} + +/* +Get a pointer to the element at the back of the queue. + +This will raise a bounds checking error if the queue is empty. +*/ +back_ptr :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T { + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } + idx := (q.offset+uint(q.len - 1))%builtin.len(q.data) return &q.data[idx] } -peek_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T { - runtime.bounds_check_error_loc(loc, 0, builtin.len(q.data)) - idx := q.offset%builtin.len(q.data) - return &q.data[idx] -} -peek_back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T { - runtime.bounds_check_error_loc(loc, int(q.len - 1), builtin.len(q.data)) - idx := (uint(q.len - 1)+q.offset)%builtin.len(q.data) - return &q.data[idx] -} +/* +Push an element to the back of the queue. -// Push an element to the back of the queue -push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) { +If there is no more space left and allocation fails to get more, this will +return false with an `Allocator_Error`. + +Example: + + import "base:runtime" + import "core:container/queue" + + // This demonstrates typical queue behavior (First-In First-Out). + main :: proc() { + q: queue.Queue(int) + queue.init(&q) + queue.push_back(&q, 1) + queue.push_back(&q, 2) + queue.push_back(&q, 3) + // q.data is now [1, 2, 3, ...] + assert(queue.pop_front(&q) == 1) + assert(queue.pop_front(&q) == 2) + assert(queue.pop_front(&q) == 3) + } +*/ +push_back :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { if space(q^) == 0 { - _grow(q) or_return + _grow(q, loc = loc) or_return } idx := (q.offset+uint(q.len))%builtin.len(q.data) q.data[idx] = elem @@ -138,27 +270,78 @@ push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocato return true, nil } -// Push an element to the front of the queue -push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) { +/* +Push an element to the front of the queue. + +If there is no more space left and allocation fails to get more, this will +return false with an `Allocator_Error`. + +Example: + + import "base:runtime" + import "core:container/queue" + + // This demonstrates stack behavior (First-In Last-Out). + main :: proc() { + q: queue.Queue(int) + queue.init(&q) + queue.push_back(&q, 1) + queue.push_back(&q, 2) + queue.push_back(&q, 3) + // q.data is now [1, 2, 3, ...] + assert(queue.pop_back(&q) == 3) + assert(queue.pop_back(&q) == 2) + assert(queue.pop_back(&q) == 1) + } +*/ +push_front :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { if space(q^) == 0 { - _grow(q) or_return - } + _grow(q, loc = loc) or_return + } q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data) q.len += 1 q.data[q.offset] = elem return true, nil } +/* +Pop an element from the back of the queue. -// Pop an element from the back of the queue +This will raise a bounds checking error if the queue is empty. + +Example: + + import "base:runtime" + import "core:container/queue" + + // This demonstrates stack behavior (First-In Last-Out) at the far end of the data array. + main :: proc() { + q: queue.Queue(int) + queue.init(&q) + queue.push_front(&q, 1) + queue.push_front(&q, 2) + queue.push_front(&q, 3) + // q.data is now [..., 3, 2, 1] + log.infof("%#v", q) + assert(queue.pop_front(&q) == 3) + assert(queue.pop_front(&q) == 2) + assert(queue.pop_front(&q) == 1) + } +*/ pop_back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) { - assert(condition=q.len > 0, loc=loc) + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } q.len -= 1 idx := (q.offset+uint(q.len))%builtin.len(q.data) elem = q.data[idx] return } -// Safely pop an element from the back of the queue + +/* +Pop an element from the back of the queue if one exists and return true. +Otherwise, return a nil element and false. +*/ pop_back_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) { if q.len > 0 { q.len -= 1 @@ -169,15 +352,25 @@ pop_back_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) { return } -// Pop an element from the front of the queue +/* +Pop an element from the front of the queue + +This will raise a bounds checking error if the queue is empty. +*/ pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) { - assert(condition=q.len > 0, loc=loc) + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len > 0, "Queue is empty.", loc) + } elem = q.data[q.offset] q.offset = (q.offset+1)%builtin.len(q.data) q.len -= 1 return } -// Safely pop an element from the front of the queue + +/* +Pop an element from the front of the queue if one exists and return true. +Otherwise, return a nil element and false. +*/ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) { if q.len > 0 { elem = q.data[q.offset] @@ -188,13 +381,18 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) { return } -// Push multiple elements to the back of the queue -push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) { +/* +Push many elements at once to the back of the queue. + +If there is not enough space left and allocation fails to get more, this will +return false with an `Allocator_Error`. +*/ +push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { n := uint(builtin.len(elems)) if space(q^) < int(n) { - _grow(q, q.len + n) or_return + _grow(q, q.len + n, loc) or_return } - + sz := uint(builtin.len(q.data)) insert_from := (q.offset + q.len) % sz insert_to := n @@ -207,19 +405,31 @@ push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime return true, nil } -// Consume `n` elements from the front of the queue +/* +Consume `n` elements from the back of the queue. + +This will raise a bounds checking error if the queue does not have enough elements. +*/ consume_front :: proc(q: ^$Q/Queue($T), n: int, loc := #caller_location) { - assert(condition=int(q.len) >= n, loc=loc) + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len >= uint(n), "Queue does not have enough elements to consume.", loc) + } if n > 0 { nu := uint(n) q.offset = (q.offset + nu) % builtin.len(q.data) - q.len -= nu + q.len -= nu } } -// Consume `n` elements from the back of the queue +/* +Consume `n` elements from the back of the queue. + +This will raise a bounds checking error if the queue does not have enough elements. +*/ consume_back :: proc(q: ^$Q/Queue($T), n: int, loc := #caller_location) { - assert(condition=int(q.len) >= n, loc=loc) + when !ODIN_NO_BOUNDS_CHECK { + ensure(q.len >= uint(n), "Queue does not have enough elements to consume.", loc) + } if n > 0 { q.len -= uint(n) } @@ -231,9 +441,14 @@ append_elem :: push_back append_elems :: push_back_elems push :: proc{push_back, push_back_elems} append :: proc{push_back, push_back_elems} +enqueue :: push_back +dequeue :: pop_front -// Clear the contents of the queue +/* +Reset the queue's length and offset to zero, letting it write new elements over +old memory, in effect clearing the accessible contents. +*/ clear :: proc(q: ^$Q/Queue($T)) { q.len = 0 q.offset = 0 @@ -241,10 +456,10 @@ clear :: proc(q: ^$Q/Queue($T)) { // Internal growing procedure -_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error { +_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0, loc := #caller_location) -> runtime.Allocator_Error { new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2) n := uint(builtin.len(q.data)) - builtin.resize(&q.data, int(new_capacity)) or_return + builtin.resize(&q.data, int(new_capacity), loc) or_return if q.offset + q.len > n { diff := n - q.offset copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff]) diff --git a/core/container/rbtree/rbtree.odin b/core/container/rbtree/rbtree.odin index 090551367..c138838df 100644 --- a/core/container/rbtree/rbtree.odin +++ b/core/container/rbtree/rbtree.odin @@ -1,4 +1,4 @@ -// This package implements a red-black tree +// A red-black tree with the same API as our AVL tree. package container_rbtree @(require) import "base:intrinsics" @@ -91,24 +91,24 @@ destroy :: proc(t: ^$T/Tree($Key, $Value), call_on_remove: bool = true) { } } -len :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> (node_count: int) { +len :: proc "contextless" (t: $T/Tree($Key, $Value)) -> (node_count: int) { return t._size } -// first returns the first node in the tree (in-order) or nil iff +// first returns the first node in the tree (in-order) or nil if and only if (⟺) // the tree is empty. first :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> ^Node(Key, Value) { return tree_first_or_last_in_order(t, Direction.Backward) } -// last returns the last element in the tree (in-order) or nil iff +// last returns the last element in the tree (in-order) or nil if and only if (⟺) // the tree is empty. last :: proc "contextless" (t: ^$T/Tree($Key, $Value)) -> ^Node(Key, Value) { return tree_first_or_last_in_order(t, Direction.Forward) } -// find finds the key in the tree, and returns the corresponding node, or nil iff the value is not present. -find :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (node: ^Node(Key, Value)) { +// find finds the key in the tree, and returns the corresponding node, or nil if and only if (⟺) the value is not present. +find :: proc(t: $T/Tree($Key, $Value), key: Key) -> (node: ^Node(Key, Value)) { node = t._root for node != nil { switch t._cmp_fn(key, node.key) { @@ -120,17 +120,17 @@ find :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (node: ^Node(Key, Value)) { return node } -// find_value finds the key in the tree, and returns the corresponding value, or nil iff the value is not present. -find_value :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok { +// find_value finds the key in the tree, and returns the corresponding value, or nil if and only if (⟺) the value is not present. +find_value :: proc(t: $T/Tree($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok { if n := find(t, key); n != nil { return n.value, true } return } -// find_or_insert attempts to insert the value into the tree, and returns -// the node, a boolean indicating if the value was inserted, and the -// node allocator error if relevant. If the value is already present, the existing node is updated. +// find_or_insert attempts to insert the key-value pair into the tree, and returns +// the node, a boolean indicating if a new node was inserted, and the +// node allocator error if relevant. If the key is already present, the existing node is updated and returned. find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: ^Node(Key, Value), inserted: bool, err: runtime.Allocator_Error) { n_ptr := &t._root for n_ptr^ != nil { @@ -141,6 +141,7 @@ find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: case .Greater: n_ptr = &n._right case .Equal: + n.value = value return } } @@ -153,7 +154,7 @@ find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: return n, true, nil } -// remove removes a node or value from the tree, and returns true iff the +// remove removes a node or value from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's value will be left intact, // the node itself will be freed via the tree's node allocator. remove :: proc { @@ -161,18 +162,18 @@ remove :: proc { remove_node, } -// remove_value removes a value from the tree, and returns true iff the +// remove_value removes a value from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's key + value will be left intact, // the node itself will be freed via the tree's node allocator. remove_key :: proc(t: ^$T/Tree($Key, $Value), key: Key, call_on_remove := true) -> bool { - n := find(t, key) + n := find(t^, key) if n == nil { return false // Key not found, nothing to do } return remove_node(t, n, call_on_remove) } -// remove_node removes a node from the tree, and returns true iff the +// remove_node removes a node from the tree, and returns true if and only if (⟺) the // removal was successful. While the node's key + value will be left intact, // the node itself will be freed via the tree's node allocator. remove_node :: proc(t: ^$T/Tree($Key, $Value), node: ^$N/Node(Key, Value), call_on_remove := true) -> (found: bool) { @@ -234,14 +235,14 @@ iterator_from_pos :: proc "contextless" (t: ^$T/Tree($Key, $Value), pos: ^Node(K } // iterator_get returns the node currently pointed to by the iterator, -// or nil iff the node has been removed, the tree is empty, or the end +// or nil if and only if (⟺) the node has been removed, the tree is empty, or the end // of the tree has been reached. iterator_get :: proc "contextless" (it: ^$I/Iterator($Key, $Value)) -> ^Node(Key, Value) { return it._cur } // iterator_remove removes the node currently pointed to by the iterator, -// and returns true iff the removal was successful. Semantics are the +// and returns true if and only if (⟺) the removal was successful. Semantics are the // same as the Tree remove. iterator_remove :: proc(it: ^$I/Iterator($Key, $Value), call_on_remove: bool = true) -> bool { if it._cur == nil { @@ -257,7 +258,7 @@ iterator_remove :: proc(it: ^$I/Iterator($Key, $Value), call_on_remove: bool = t } // iterator_next advances the iterator and returns the (node, true) or -// or (nil, false) iff the end of the tree has been reached. +// or (nil, false) if and only if (⟺) the end of the tree has been reached. // // Note: The first call to iterator_next will return the first node instead // of advancing the iterator. diff --git a/core/container/small_array/doc.odin b/core/container/small_array/doc.odin index f3e9acd57..5696ae58c 100644 --- a/core/container/small_array/doc.odin +++ b/core/container/small_array/doc.odin @@ -1,8 +1,9 @@ /* -Package small_array implements a dynamic array like -interface on a stack-allocated, fixed-size array. +Deprecation Notice: Prefer using `[dynamic; N]T` (fixed capacity dynamic arrays). -The Small_Array type is optimal for scenarios where you need +A dynamic array-like interface on a stack-allocated, fixed-size array. + +The `Small_Array` type is optimal for scenarios where you need a container for a fixed number of elements of a specific type, with the total number known at compile time but the exact number to be used determined at runtime. @@ -33,7 +34,7 @@ Example: return } - // the Small_Array can be an ordinary parameter 'generic' over + // the `Small_Array` can be an ordinary parameter 'generic' over // the actual length to be usable with different sizes print_elements :: proc(arr: ^small_array.Small_Array($N, rune)) { for r in small_array.slice(arr) { @@ -52,4 +53,4 @@ Output: Hellope */ -package container_small_array +package container_small_array \ No newline at end of file diff --git a/core/container/small_array/small_array.odin b/core/container/small_array/small_array.odin index 49d441079..901ed419e 100644 --- a/core/container/small_array/small_array.odin +++ b/core/container/small_array/small_array.odin @@ -1,8 +1,8 @@ package container_small_array import "base:builtin" -import "base:runtime" -_ :: runtime +@require import "base:intrinsics" +@require import "base:runtime" /* A fixed-size stack-allocated array operated on in a dynamic fashion. @@ -21,7 +21,7 @@ Example: } */ Small_Array :: struct($N: int, $T: typeid) where N >= 0 { - data: [N]T, + data: [N]T `fmt:",len"`, len: int, } @@ -105,8 +105,13 @@ This operation assumes that the small-array is large enough. This will result in: - the value if 0 <= index < len - - the zero value of the type if len < index < capacity - - 'crash' if capacity < index or index < 0 + - raise a bounds check error if capacity <= index + - the previous value if len < index < capacity, which defauls to T's zero value. + + e.g. if you call `small_array.push(&a, 0, 1, 2)`, and `i := pop_back(&a)`, + then `get(a, 2)` will return the earlier value `2` at that location. + + See also `get_safe`, which returns T's zero value and `false` if `index` is out of bounds. **Inputs** - `a`: The small-array @@ -125,8 +130,13 @@ This operation assumes that the small-array is large enough. This will result in: - the pointer if 0 <= index < len - - the pointer to the zero value if len < index < capacity - - 'crash' if capacity < index or index < 0 + - raise a bounds check error if capacity <= index + - a pointer to the previous value if len < index < capacity, which defauls to T's zero value. + + e.g. if you call `small_array.push(&a, 0, 1, 2)`, and `i := pop_back(&a)`, + then `get_ptr(a, 2)` will return a pointer to the slot containing the earlier value `2` at that location. + + See also `get_ptr_safe`, which returns a nil pointer, and `false` if `index` is out of bounds. **Inputs** - `a`: A pointer to the small-array @@ -169,7 +179,7 @@ Output: x */ -get_safe :: proc(a: $A/Small_Array($N, $T), index: int) -> (T, bool) #no_bounds_check { +get_safe :: proc "contextless" (a: $A/Small_Array($N, $T), index: int) -> (T, bool) #no_bounds_check { if index < 0 || index >= a.len { return {}, false } @@ -183,11 +193,11 @@ Get a pointer to the item at the specified position. - `a`: A pointer to the small-array - `index`: The position of the item to get -**Returns** +**Returns** - the pointer to the element at the specified position - true if element exists, false otherwise */ -get_ptr_safe :: proc(a: ^$A/Small_Array($N, $T), index: int) -> (^T, bool) #no_bounds_check { +get_ptr_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int) -> (^T, bool) #no_bounds_check { if index < 0 || index >= a.len { return {}, false } @@ -231,7 +241,7 @@ Example: fmt.println(small_array.slice(&a)) // resizing makes the change visible - small_array.resize(&a, 100) + small_array.non_zero_resize(&a, 100) fmt.println(small_array.slice(&a)) } @@ -250,6 +260,8 @@ set :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, item: T) { /* Tries to resize the small-array to the specified length. +The memory of added elements will be zeroed out. + The new length will be: - `length` if `length` <= capacity - capacity if length > capacity @@ -259,7 +271,7 @@ The new length will be: - `length`: The new desired length Example: - + import "core:container/small_array" import "core:fmt" @@ -269,7 +281,7 @@ Example: small_array.push_back(&a, 1) small_array.push_back(&a, 2) fmt.println(small_array.slice(&a)) - + small_array.resize(&a, 1) fmt.println(small_array.slice(&a)) @@ -278,12 +290,56 @@ Example: } Output: - + + [1, 2] + [1] + [1, 0, 0, 0, 0] +*/ +resize :: proc "contextless" (a: ^$A/Small_Array($N, $T), length: int) { + prev_len := a.len + a.len = min(length, builtin.len(a.data)) + if prev_len < a.len { + intrinsics.mem_zero(&a.data[prev_len], size_of(T)*(a.len-prev_len)) + } +} + +/* +Tries to resize the small-array to the specified length. + +The new length will be: + - `length` if `length` <= capacity + - capacity if length > capacity + +**Inputs** +- `a`: A pointer to the small-array +- `length`: The new desired length + +Example: + + import "core:container/small_array" + import "core:fmt" + + non_zero_resize_example :: proc() { + a: small_array.Small_Array(5, int) + + small_array.push_back(&a, 1) + small_array.push_back(&a, 2) + fmt.println(small_array.slice(&a)) + + small_array.non_zero_resize(&a, 1) + fmt.println(small_array.slice(&a)) + + small_array.non_zero_resize(&a, 100) + fmt.println(small_array.slice(&a)) + } + +Output: + [1, 2] [1] [1, 2, 0, 0, 0] */ -resize :: proc "contextless" (a: ^$A/Small_Array, length: int) { +non_zero_resize :: proc "contextless" (a: ^$A/Small_Array, length: int) { a.len = min(length, builtin.len(a.data)) } @@ -330,7 +386,7 @@ Attempts to add the given element at the beginning. This operation assumes that the small-array is not empty. Note: Performing this operation will cause pointers obtained -through get_ptr(_save) to reference incorrect elements. +through get_ptr(_safe) to reference incorrect elements. **Inputs** - `a`: A pointer to the small-array @@ -410,7 +466,7 @@ Removes and returns the first element of the small-array. This operation assumes that the small-array is not empty. Note: Performing this operation will cause pointers obtained -through get_ptr(_save) to reference incorrect elements. +through get_ptr(_safe) to reference incorrect elements. **Inputs** - `a`: A pointer to the small-array @@ -486,7 +542,7 @@ Attempts to remove and return the first element of the small array. Unlike `pop_front`, it does not assume that the array is non-empty. Note: Performing this operation will cause pointers obtained -through get_ptr(_save) to reference incorrect elements. +through get_ptr(_safe) to reference incorrect elements. **Inputs** - `a`: A pointer to the small-array @@ -560,7 +616,7 @@ consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_l Removes the element at the specified index while retaining order. Note: Performing this operation will cause pointers obtained -through get_ptr(_save) to reference incorrect elements. +through get_ptr(_safe) to reference incorrect elements. **Inputs** - `a`: A pointer to the small-array @@ -698,7 +754,7 @@ push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) - Tries to insert an element at the specified position. Note: Performing this operation will cause pointers obtained -through get_ptr(_save) to reference incorrect elements. +through get_ptr(_safe) to reference incorrect elements. **Inputs** - `a`: A pointer to the small-array diff --git a/core/container/topological_sort/topological_sort.odin b/core/container/topological_sort/topological_sort.odin index 10765958e..a49d04b49 100644 --- a/core/container/topological_sort/topological_sort.odin +++ b/core/container/topological_sort/topological_sort.odin @@ -1,6 +1,5 @@ -// The following is a generic O(V+E) topological sorter implementation. -// This is the fastest known method for topological sorting and Odin's -// map type is being used to accelerate lookups. +// A generic `O(V+E)` topological sorter implementation. This is the fastest known method for topological sorting. +// Odin's map type is being used to accelerate lookups. package container_topological_sort import "base:intrinsics" diff --git a/core/container/xar/freelist.odin b/core/container/xar/freelist.odin new file mode 100644 index 000000000..4b11014f5 --- /dev/null +++ b/core/container/xar/freelist.odin @@ -0,0 +1,157 @@ +package container_xar + +@(require) import "base:runtime" + +Freelist_Array :: struct($T: typeid, $SHIFT: uint) where + 0 < SHIFT, + SHIFT <= MAX_SHIFT, + size_of(T) >= size_of(^T) { + array: Array(T, SHIFT), + freelist: ^T, +} + +freelist_init :: proc(x: ^$X/Freelist_Array($T, $SHIFT), allocator := context.allocator) { + init(&x.array, allocator) + x.freelist = nil +} + +freelist_destroy :: proc(x: ^$X/Freelist_Array($T, $SHIFT)) { + destroy(&x.array) + x.freelist = nil +} + +freelist_clear :: proc(x: ^$X/Freelist_Array($T, $SHIFT)) { + clear(&x.array) + x.freelist = nil +} + +@(require_results) +freelist_push_with_index :: proc(x: ^$X/Freelist_Array($T, $SHIFT), value: T, loc := #caller_location) -> (ptr: ^T, index: int, err: runtime.Allocator_Error) { + if x.freelist != nil { + slot := x.freelist + idx, found := freelist_linear_search(x, slot) + assert(found) + x.freelist = (^^T)(slot)^ + slot^ = value + return slot, idx, nil + } + idx := x.array.len + ptr = array_push_back_elem_and_get_ptr(&x.array, value, loc) or_return + return ptr, idx, nil +} + +@(require_results) +freelist_push :: proc(x: ^$X/Freelist_Array($T, $SHIFT), value: T, loc := #caller_location) -> (ptr: ^T, err: runtime.Allocator_Error) { + ptr, _, err = freelist_push_with_index(x, value, loc) + return +} + +freelist_pop :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int, loc := #caller_location) -> T { + item := array_get_ptr(&x.array, index, loc) + result := item^ + (^^T)(item)^ = x.freelist + x.freelist = item + return result +} + +freelist_release :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int, loc := #caller_location) { + item := array_get_ptr(&x.array, index, loc) + (^^T)(item)^ = x.freelist + x.freelist = item +} + +@(require_results) +freelist_linear_search :: proc(x: ^$X/Freelist_Array($T, $SHIFT), ptr: ^T) -> (index: int, found: bool) { + base := 0 + for chunk, c in x.array.chunks { + if chunk == nil { + break + } + chunk_cap := 1 << (SHIFT + uint(c if c > 0 else 1) - 1) + ptr_addr := uintptr(ptr) + chunk_start_addr := uintptr(chunk) + chunk_end_addr := chunk_start_addr + uintptr(chunk_cap * size_of(T)) + if chunk_start_addr <= ptr_addr && ptr_addr < chunk_end_addr { + offset := int(ptr_addr - chunk_start_addr) / size_of(T) + return base + offset, true + } + base += chunk_cap + } + return -1, false +} + +@(require_results) +freelist_get :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int, loc := #caller_location) -> T { + return array_get(&x.array, index, loc) +} + +@(require_results) +freelist_get_ptr :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int, loc := #caller_location) -> ^T { + return array_get_ptr(&x.array, index, loc) +} + +freelist_set :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int, value: T, loc := #caller_location) { + array_set(&x.array, index, value, loc) +} + +@(require_results) +freelist_len :: proc(x: $X/Freelist_Array($T, $SHIFT)) -> int { + return x.array.len +} + +@(require_results) +freelist_cap :: proc(x: $X/Freelist_Array($T, $SHIFT)) -> int { + return array_cap(x.array) +} + +@(require_results) +freelist_is_freed :: proc(x: ^$X/Freelist_Array($T, $SHIFT), #any_int index: int) -> bool { + ptr := array_get_ptr(&x.array, index) + current := x.freelist + for current != nil { + if current == ptr { + return true + } + current = (^^T)(current)^ + } + return false +} + +Freelist_Iterator :: struct($T: typeid, $SHIFT: uint) { + freelist_array: ^Freelist_Array(T, SHIFT), + idx: int, +} + +freelist_iterator :: proc(x: ^$X/Freelist_Array($T, $SHIFT)) -> Freelist_Iterator(T, SHIFT) { + return {freelist_array = x, idx = 0} +} + +@(require_results) +freelist_iterate_by_val :: proc(it: ^Freelist_Iterator($T, $SHIFT)) -> (val: T, idx: int, ok: bool) { + for it.idx < it.freelist_array.array.len { + if !freelist_is_freed(it.freelist_array, it.idx) { + val = array_get(&it.freelist_array.array, it.idx) + idx = it.idx + it.idx += 1 + return val, idx, true + } + it.idx += 1 + } + it.idx = 0 + return +} + +@(require_results) +freelist_iterate_by_ptr :: proc(it: ^Freelist_Iterator($T, $SHIFT)) -> (val: ^T, idx: int, ok: bool) { + for it.idx < it.freelist_array.array.len { + if !freelist_is_freed(it.freelist_array, it.idx) { + val = array_get_ptr(&it.freelist_array.array, it.idx) + idx = it.idx + it.idx += 1 + return val, idx, true + } + it.idx += 1 + } + it.idx = 0 + return +} diff --git a/core/container/xar/xar.odin b/core/container/xar/xar.odin new file mode 100644 index 000000000..9f0b6e90c --- /dev/null +++ b/core/container/xar/xar.odin @@ -0,0 +1,538 @@ +/* + Exponential Array (Xar). + + A dynamically growing array using exponentially-sized chunks, providing stable + memory addresses for all elements. Unlike `[dynamic]T`, elements are never + moved once allocated, making it safe to hold pointers to elements. + + For more information: https://azmr.uk/dyn/#exponential-arrayxar + + Example: + + import "core:container/xar" + + example :: proc() { + x: xar.Array(int, 4) + defer xar.destroy(&x) + + xar.push_back(&x, 10) + xar.push_back(&x, 20) + xar.push_back(&x, 30) + + ptr := xar.get_ptr(&x, 1) // ptr remains valid after more push_backs + xar.push_back(&x, 40) + fmt.println(ptr^) // prints 20 + } +*/ +package container_xar + +@(require) import "base:intrinsics" +@(require) import "base:runtime" + +PLATFORM_BITS :: 8*size_of(uint) +_LOG2_PLATFORM_BITS :: intrinsics.constant_log2(PLATFORM_BITS) + +MAX_SHIFT :: PLATFORM_BITS>>1 + +/* + An Exponential Array with stable element addresses. + + Unlike `[dynamic]T` which reallocates and moves elements when growing, `Array` + allocates separate chunks of exponentially increasing size. This guarantees + that pointers to elements remain valid for the lifetime of the container. + + Fields: + - `chunks`: Fixed array of multi-pointers to allocated chunks + - `len`: Number of elements currently stored + - `allocator`: Allocator used for chunk allocations + + Type Parameters: + - `T`: The element type + - `SHIFT`: Controls initial chunk size (1 << SHIFT). Must be in range (0, MAX_SHIFT]. + Larger values mean fewer, bigger chunks. Recommended: 4-8. + + Chunk sizes grow as: + - `chunks[0]`: 1 << SHIFT elements + - `chunks[1]`: 1 << SHIFT elements + - `chunks[2]`: 1 << (SHIFT + 1) elements + - `chunks[3]`: 1 << (SHIFT + 2) elements + - `chunks[4]`: 1 << (SHIFT + 3) elements + - ...and so on + + Example: + + import "core:container/xar" + + example :: proc() { + // Xar with initial chunk size of 16 (1 << 4) + x: xar.Array(My_Struct, 4) + defer xar.destroy(&x) + } +*/ +Array :: struct($T: typeid, $SHIFT: uint) where 0 < SHIFT, SHIFT <= MAX_SHIFT { + chunks: [(1 << (_LOG2_PLATFORM_BITS - intrinsics.constant_log2(SHIFT))) + 1][^]T, + len: int, + allocator: runtime.Allocator, +} + + +/* +Initializes an exponential array with the given allocator. + +**Inputs** +- `x`: Pointer to the exponential array to initialize +- `allocator`: Allocator to use for chunk allocations (defaults to context.allocator) +*/ +array_init :: proc(x: ^$X/Array($T, $SHIFT), allocator := context.allocator) { + x^ = {allocator = allocator} +} + +/* +Frees all allocated chunks and resets the exponential array. + +**Inputs** +- `x`: Pointer to the exponential array to destroy +*/ +array_destroy :: proc(x: ^$X/Array($T, $SHIFT)) { + #reverse for c, i in x.chunks { + if c != nil { + n := 1 << (SHIFT + uint(i if i > 0 else 1) - 1) + size_in_bytes := n * size_of(T) + runtime.mem_free_with_size(c, size_in_bytes, x.allocator) + } + } + x^ = {} +} + +/* +Resets the array's length to zero without freeing memory. +Allocated chunks are retained for reuse. +*/ +array_clear :: proc "contextless" (x: ^$X/Array($T, $SHIFT)) { + x.len = 0 +} + +// Returns the length of the exponential-array +@(require_results) +array_len :: proc "contextless" (x: $X/Array($T, $SHIFT)) -> int { + return x.len +} + +// Returns the number of allocated elements +@(require_results) +array_cap :: proc "contextless" (x: $X/Array($T, $SHIFT)) -> int { + #reverse for c, i in x.chunks { + if c != nil { + return 1 << (SHIFT + uint(i if i > 0 else 1)) + } + } + return 0 +} + +// Internal: computes chunk index, element index within chunk, and chunk capacity for a given index. +@(require_results) +_meta_get :: #force_inline proc "contextless" ($SHIFT: uint, index: uint) -> (chunk_idx, elem_idx, chunk_cap: uint) { + elem_idx = index + chunk_cap = uint(1) << SHIFT + chunk_idx = 0 + + index_shift := index >> SHIFT + if index_shift > 0 { + N :: 8*size_of(uint)-1 + CLZ :: intrinsics.count_leading_zeros + chunk_idx = N-CLZ(index_shift) // MSB(index_shift) + + chunk_cap = 1 << (chunk_idx + SHIFT) + elem_idx -= chunk_cap + chunk_idx += 1 + } + + return +} +/* +Get a copy of the element at the specified index. + +**Inputs** +- `x`: Pointer to the exponential array +- `index`: Position of the element (0-indexed) + +**Returns** +- a copy of the element +*/ +@(require_results) +array_get :: proc(x: ^$X/Array($T, $SHIFT), #any_int index: int, loc := #caller_location) -> (val: T) #no_bounds_check { + runtime.bounds_check_error_loc(loc, index, x.len) + chunk_idx, elem_idx, _ := _meta_get(SHIFT, uint(index)) + return x.chunks[chunk_idx][elem_idx] +} + +/* +Get a pointer to the element at the specified index. + +The returned pointer remains valid even after additional elements are added, +as long as the element is not removed and the array is not destroyed. + +**Inputs** +- `x`: Pointer to the exponential array +- `index`: Position of the element (0-indexed) + +**Returns** +- a stable pointer to the element + +Example: + + import "core:container/xar" + + get_ptr_example :: proc() { + x: xar.Array(int, 4) + defer xar.destroy(&x) + + xar.push_back(&x, 100) + ptr := xar.get_ptr(&x, 0) + + // Pointer remains valid after growing + for i in 0..<1000 { + xar.push_back(&x, i) + } + + fmt.println(ptr^) // Still prints 100 + } +*/ +@(require_results) +array_get_ptr :: proc(x: ^$X/Array($T, $SHIFT), #any_int index: int, loc := #caller_location) -> (val: ^T) #no_bounds_check { + runtime.bounds_check_error_loc(loc, index, x.len) + chunk_idx, elem_idx, _ := _meta_get(SHIFT, uint(index)) + return &x.chunks[chunk_idx][elem_idx] +} + +// No bounds checking +@(require_results) +array_get_ptr_unsafe :: proc "contextless" (x: ^$X/Array($T, $SHIFT), #any_int index: int) -> (val: ^T) #no_bounds_check { + chunk_idx, elem_idx, _ := _meta_get(SHIFT, uint(index)) + return &x.chunks[chunk_idx][elem_idx] +} + +/* +Set the element at the specified index to the given value. + +**Inputs** +- `x`: Pointer to the exponential array +- `index`: Position of the element (0-indexed) +- `value`: The value to set +*/ +array_set :: proc(x: ^$X/Array($T, $SHIFT), #any_int index: int, value: T, loc := #caller_location) #no_bounds_check { + runtime.bounds_check_error_loc(loc, index, x.len) + chunk_idx, elem_idx, _ := _meta_get(SHIFT, uint(index)) + x.chunks[chunk_idx][elem_idx] = value +} + +array_append :: proc{array_push_back_elem, array_push_back_elems} +array_push_back :: proc{array_push_back_elem, array_push_back_elems} + + +/* +Append an element to the end of the exponential array. +Allocates a new chunk if necessary. Existing elements aren't moved, and their pointers remain stable. + +**Inputs** +- `x`: Pointer to the exponential array +- `value`: The element to append + +**Returns** +- number of elements added (always 1 on success) +- allocation error if chunk allocation failed + +Example: + + import "core:container/xar" + + push_back_example :: proc() { + x: xar.Array(string, 4) + defer xar.destroy(&x) + + xar.push_back(&x, "hello") + xar.push_back(&x, "world") + + fmt.println(xar.get(&x, 0)) // hello + fmt.println(xar.get(&x, 1)) // world + } +*/ +array_push_back_elem :: proc(x: ^$X/Array($T, $SHIFT), value: T, loc := #caller_location) -> (n: int, err: runtime.Allocator_Error) { + if x.allocator.procedure == nil { + // to minic `[dynamic]T` behaviour + x.allocator = context.allocator + } + + chunk_idx, elem_idx, chunk_cap := _meta_get(SHIFT, uint(x.len)) + if x.chunks[chunk_idx] == nil { + x.chunks[chunk_idx] = make([^]T, chunk_cap, x.allocator) or_return + } + x.chunks[chunk_idx][elem_idx] = value + x.len += 1 + n = 1 + return +} + +/* +Append multiple elements to the end of the exponential array. + +**Inputs** +- `x`: Pointer to the exponential array +- `values`: The elements to append + +**Returns** +- number of elements successfully added +- allocation error if chunk allocation failed (partial append possible) +*/ +array_push_back_elems :: proc(x: ^$X/Array($T, $SHIFT), values: ..T, loc := #caller_location) -> (n: int, err: runtime.Allocator_Error) { + for value in values { + n += array_push_back_elem(x, value, loc) or_return + } + return +} + +array_append_and_get_ptr :: array_push_back_elem_and_get_ptr +append_and_get_ptr :: array_push_back_elem_and_get_ptr + +/* +Append an element and return a stable pointer to it. +This is useful when you need to initialize a complex struct in-place or +retain a reference to the newly added element. + +**Inputs** +- `x`: Pointer to the exponential array +- `value`: The element to append + +**Returns** +- a stable pointer to the newly added element +- allocation error if chunk allocation failed + +Example: + + import "core:container/xar" + + push_back_and_get_ptr_example :: proc() { + x: xar.Array(My_Struct, 4) + defer xar.destroy(&x) + + ptr := xar.push_back_elem_and_get_ptr(&x, My_Struct{}) or_else panic("alloc failed") + ptr.field = 42 // Initialize in-place + } +*/ +@(require_results) +array_push_back_elem_and_get_ptr :: proc(x: ^$X/Array($T, $SHIFT), value: T, loc := #caller_location) -> (ptr: ^T, err: runtime.Allocator_Error) { + if x.allocator.procedure == nil { + // to minic `[dynamic]T` behaviour + x.allocator = context.allocator + } + + chunk_idx, elem_idx, chunk_cap := _meta_get(SHIFT, uint(x.len)) + if x.chunks[chunk_idx] == nil { + x.chunks[chunk_idx] = make([^]T, chunk_cap, x.allocator) or_return + } + x.chunks[chunk_idx][elem_idx] = value + x.len += 1 + ptr = &x.chunks[chunk_idx][elem_idx] + return +} + +// `pop` will remove and return the end value of an exponential array `x` and reduces the length of the array by 1. +// +// Note: If the exponential array has no elements (`xar.len(x) == 0`), this procedure will panic. +array_pop :: proc(x: ^$X/Array($T, $SHIFT), loc := #caller_location) -> (val: T) { + assert(x.len > 0, loc=loc) + index := uint(x.len-1) + chunk_idx, elem_idx, _ := _meta_get(SHIFT, index) + x.len -= 1 + return x.chunks[chunk_idx][elem_idx] +} + +// `pop_safe` trys to remove and return the end value of dynamic array `x` and reduces the length of the array by 1. +// If the operation is not possible, it will return false. +@(require_results) +array_pop_safe :: proc(x: ^$X/Array($T, $SHIFT)) -> (val: T, ok: bool) { + if x.len == 0 { + return + } + index := uint(x.len-1) + chunk_idx, elem_idx, _ := _meta_get(SHIFT, index) + x.len -= 1 + + val = x.chunks[chunk_idx][elem_idx] + ok = true + return +} + +/* + `unordered_remove` removed the element at the specified `index`. It does so by replacing the current end value + with the old value, and reducing the length of the exponential array by 1. + + Note: This is an O(1) operation. + Note: This is currently no procedure that is the equivalent of an "ordered_remove" + Note: If the index is out of bounds, this procedure will panic. + + Note: Pointers to the last element become invalid (it gets moved). Pointers to other elements remain valid. + + Example: + + import "core:container/xar" + + unordered_remove_example :: proc() { + x: xar.Array(int, 4) + defer xar.destroy(&x) + + xar.push_back(&x, 10) + xar.push_back(&x, 20) + xar.push_back(&x, 30) + + xar.unordered_remove(&x, 0) // Removes 10, replaces with 30 + + // Array now contains [30, 20] + fmt.println(xar.get(&x, 0)) // 30 + fmt.println(xar.get(&x, 1)) // 20 + } +*/ +array_unordered_remove :: proc(x: ^$X/Array($T, $SHIFT), #any_int index: int, loc := #caller_location) { + runtime.bounds_check_error_loc(loc, index, x.len) + n := x.len-1 + if index != n { + end := array_get(x, n) + array_set(x, index, end) + } + x.len -= 1 +} + +@(require_results) +array_linear_search :: proc(x: ^$X/Array($T, $SHIFT), elem: T) -> (index: int, found: bool) where intrinsics.type_is_comparable(T) { + it := array_iterator(x) + for val, i in array_iterate_by_val(it) { + if val == elem { + return i, true + } + } + return -1, false +} + + +/* +Iterator state for traversing a `Xar`. + +Fields: +- `xar`: Pointer to the exponential array being iterated +- `idx`: Current iteration index +*/ +Array_Iterator :: struct($T: typeid, $SHIFT: uint) { + xar: ^Array(T, SHIFT), + idx: int, +} + +/* +Create an iterator for traversing the exponential array. + +**Inputs** +- `xar`: Pointer to the exponential array + +**Returns** +- an iterator positioned at the start + +Example: + + import "core:container/xar" + import "core:fmt" + + iterator_example :: proc() { + x: xar.Array(int, 4) + defer xar.destroy(&x) + + xar.push_back(&x, 10) + xar.push_back(&x, 20) + xar.push_back(&x, 30) + + it := xar.iterator(&x) + for val in xar.iterate_by_ptr(&it) { + fmt.println(val^) + } + } + +Output: + + 10 + 20 + 30 +*/ +array_iterator :: proc(xar: ^$X/Array($T, $SHIFT)) -> Array_Iterator(T, SHIFT) { + return {xar = auto_cast xar, idx = 0} +} + +/* +Advance the iterator and returns the next element. + +**Inputs** +- `it`: Pointer to the iterator + +**Returns** +- current element +- `true` if an element was returned, `false` if iteration is complete +*/ +array_iterate_by_val :: proc(it: ^Array_Iterator($T, $SHIFT)) -> (val: T, idx: int, ok: bool) { + if it.idx >= it.xar.len { + it.idx = 0 + return + } + val = array_get(it.xar, it.idx) + idx = it.idx + it.idx += 1 + return val, idx, true +} + + +/* +Advance the iterator and returns a pointer to the next element. + +**Inputs** +- `it`: Pointer to the iterator + +**Returns** +- pointer to the current element +- `true` if an element was returned, `false` if iteration is complete +*/ +array_iterate_by_ptr :: proc(it: ^Array_Iterator($T, $SHIFT)) -> (val: ^T, idx: int, ok: bool) { + if it.idx >= it.xar.len { + it.idx = 0 + return + } + val = array_get_ptr(it.xar, it.idx) + idx = it.idx + it.idx += 1 + return val, idx, true +} + + + + +init :: proc{array_init, freelist_init} +destroy :: proc{array_destroy, freelist_destroy} +clear :: proc{array_clear, freelist_clear} +len :: proc{array_len, freelist_len} +cap :: proc{array_cap, freelist_cap} +get :: proc{array_get, freelist_get} +get_ptr_unsafe :: proc{array_get_ptr_unsafe} +get_ptr :: proc{array_get_ptr, freelist_get_ptr} +set :: proc{array_set, freelist_set} +append :: proc{array_push_back_elem, array_push_back_elems} +push_back :: proc{array_push_back_elem, array_push_back_elems} +push_back_elem :: proc{array_push_back_elem} +push_back_elems :: proc{array_push_back_elems} +push_back_elem_and_get_ptr:: proc{array_push_back_elem_and_get_ptr} +pop :: proc{array_pop, freelist_pop} +pop_safe :: proc{array_pop_safe} +unordered_remove :: proc{array_unordered_remove} +iterator :: proc{array_iterator, freelist_iterator} +iterate_by_val :: proc{array_iterate_by_val, freelist_iterate_by_val} +iterate_by_ptr :: proc{array_iterate_by_ptr, freelist_iterate_by_ptr} + +push_with_index :: proc{freelist_push_with_index} +push :: proc{freelist_push} +release :: proc{freelist_release} +linear_search :: proc{array_linear_search, freelist_linear_search} +is_freed :: proc{freelist_is_freed} \ No newline at end of file diff --git a/core/crypto/README.md b/core/crypto/README.md index 303b1f625..5065a6d02 100644 --- a/core/crypto/README.md +++ b/core/crypto/README.md @@ -29,4 +29,4 @@ constant-time byte comparison. ## License -This library is made available under the BSD-3 license. \ No newline at end of file +This library is made available under the zlib license. \ No newline at end of file diff --git a/core/crypto/_aes/ct64/api.odin b/core/crypto/_aes/ct64/api.odin index f57a630b1..08acd37ed 100644 --- a/core/crypto/_aes/ct64/api.odin +++ b/core/crypto/_aes/ct64/api.odin @@ -1,7 +1,6 @@ package aes_ct64 -import "base:intrinsics" -import "core:mem" +import "core:crypto" STRIDE :: 4 @@ -82,5 +81,5 @@ decrypt_blocks :: proc(ctx: ^Context, dst, src: [][]byte) { // reset sanitizes the Context. The Context must be re-initialized to // be used again. reset :: proc(ctx: ^Context) { - mem.zero_explicit(ctx, size_of(ctx)) -} + crypto.zero_explicit(ctx, size_of(ctx)) +} \ No newline at end of file diff --git a/core/crypto/_aes/ct64/ct64_dec.odin b/core/crypto/_aes/ct64/ct64_dec.odin index 408ee6002..6fca7a5f2 100644 --- a/core/crypto/_aes/ct64/ct64_dec.odin +++ b/core/crypto/_aes/ct64/ct64_dec.odin @@ -22,8 +22,6 @@ package aes_ct64 -import "base:intrinsics" - inv_sub_bytes :: proc "contextless" (q: ^[8]u64) { // AES S-box is: // S(x) = A(I(x)) ^ 0x63 diff --git a/core/crypto/_aes/ct64/ct64_keysched.odin b/core/crypto/_aes/ct64/ct64_keysched.odin index 0f00bba57..d0004dd5a 100644 --- a/core/crypto/_aes/ct64/ct64_keysched.odin +++ b/core/crypto/_aes/ct64/ct64_keysched.odin @@ -22,9 +22,9 @@ package aes_ct64 +import "core:crypto" import "core:crypto/_aes" import "core:encoding/endian" -import "core:mem" @(private, require_results) sub_word :: proc "contextless" (x: u32) -> u32 { @@ -35,7 +35,7 @@ sub_word :: proc "contextless" (x: u32) -> u32 { orthogonalize(&q) ret := u32(q[0]) - mem.zero_explicit(&q[0], size_of(u64)) + crypto.zero_explicit(&q[0], size_of(u64)) return ret } @@ -97,8 +97,8 @@ keysched :: proc "contextless" (comp_skey: []u64, key: []byte) -> int { (q[7] & 0x8888888888888888) } - mem.zero_explicit(&skey, size_of(skey)) - mem.zero_explicit(&q, size_of(q)) + crypto.zero_explicit(&skey, size_of(skey)) + crypto.zero_explicit(&q, size_of(q)) return num_rounds } diff --git a/core/crypto/_aes/hw/api.odin b/core/crypto/_aes/hw/api.odin new file mode 100644 index 000000000..09f674657 --- /dev/null +++ b/core/crypto/_aes/hw/api.odin @@ -0,0 +1,69 @@ +package aes_hw + +@(require) import "core:sys/info" + +// is_supported returns true if and only if (⟺) hardware accelerated AES +// is supported. +is_supported :: proc "contextless" () -> bool { + when ODIN_ARCH == .amd64 { + // Note: Everything with AES-NI has support for + // the required SSE extxtensions. + req_features :: info.CPU_Features{ + .sse2, + .ssse3, + .sse41, + .aes, + } + return info.cpu_features() >= req_features + } else when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { + req_features :: info.CPU_Features{ + .asimd, + .aes, + } + return info.cpu_features() >= req_features + } else { + return false + } +} + +// is_ghash_supported returns true if and only if (⟺) hardware accelerated +// GHASH is supported. +is_ghash_supported :: proc "contextless" () -> bool { + // Just having hardware GHASH is silly. + if !is_supported() { + return false + } + + when ODIN_ARCH == .amd64 { + return info.cpu_features() >= info.CPU_Features{ + .pclmulqdq, + } + } else when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32{ + // Once we can actually use this, we can re-enable this. + // + // return info.cpu_features() >= info.CPU_Features{ + // .pmull, + // } + return false + } else { + return false + } +} + +// Context is a keyed AES (ECB) instance. +Context :: struct { + // Note: The ideal thing to do is for the expanded round keys to be + // arrays of `u8x16`, however that implies alignment (or using AVX). + // + // All the people using e-waste processors that don't support an + // instruction set that has been around for over 10 years are why + // we can't have nice things. + _sk_exp_enc: [15][16]byte, + _sk_exp_dec: [15][16]byte, + _num_rounds: int, +} + +// init initializes a context for AES with the provided key. +init :: proc(ctx: ^Context, key: []byte) { + keysched(ctx, key) +} diff --git a/core/crypto/_aes/hw_intel/ghash.odin b/core/crypto/_aes/hw/ghash_intel.odin similarity index 99% rename from core/crypto/_aes/hw_intel/ghash.odin rename to core/crypto/_aes/hw/ghash_intel.odin index 5f51b614b..d80816d5d 100644 --- a/core/crypto/_aes/hw_intel/ghash.odin +++ b/core/crypto/_aes/hw/ghash_intel.odin @@ -21,7 +21,7 @@ // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #+build amd64 -package aes_hw_intel +package aes_hw import "base:intrinsics" import "core:crypto/_aes" diff --git a/core/crypto/_aes/hw/intrinsics_arm.odin b/core/crypto/_aes/hw/intrinsics_arm.odin new file mode 100644 index 000000000..ccd8efa8f --- /dev/null +++ b/core/crypto/_aes/hw/intrinsics_arm.odin @@ -0,0 +1,115 @@ +#+build arm64,arm32 +package aes_hw + +import "core:simd" +import "core:simd/arm" + +// https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a/ + +TARGET_FEATURES :: "neon,aes" +HAS_GHASH :: false // Temporary + +@(require_results, enable_target_feature = "aes") +aesdec :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return simd.bit_xor(arm.vaesimcq_u8(arm.vaesdq_u8(data, simd.u8x16{})), key) +} + +@(require_results, enable_target_feature = "aes") +aesdeclast :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return simd.bit_xor(arm.vaesdq_u8(data, simd.u8x16{}), key) +} + +@(require_results, enable_target_feature = "aes") +aesenc :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return simd.bit_xor(arm.vaesmcq_u8(arm.vaeseq_u8(data, simd.u8x16{})), key) +} + +@(require_results, enable_target_feature = "aes") +aesenclast :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return simd.bit_xor(arm.vaeseq_u8(data, simd.u8x16{}), key) +} + +aesimc :: arm.vaesimcq_u8 + +@(require_results, enable_target_feature = "aes") +aeskeygenassist :: #force_inline proc "c" (data: simd.u8x16, $IMM8: u8) -> simd.u8x16 { + a := arm.vaeseq_u8(data, simd.u8x16{}) // AESE does ShiftRows and SubBytes on A + + // Undo ShiftRows step from AESE and extract X1 and X3 + dest := simd.swizzle( + a, + 0x04, 0x01, 0x0e, 0x0b, // SubBytes(X1) + 0x01, 0x0e, 0x0b, 0x04, // ROT(SubBytes(X1)) + 0x0c, 0x09, 0x06, 0x03, // SubBytes(X3) + 0x09, 0x06, 0x03, 0x0c, // ROT(SubBytes(X3)) + ) + + rcons := simd.u8x16{ + 0, 0, 0, 0, + IMM8, 0, 0, 0, + 0, 0, 0, 0, + IMM8, 0, 0, 0, + } + + return simd.bit_xor(dest, rcons) +} + +// The keyschedule implementation is easier to read with some extra +// Intel intrinsics that are emulated by built-in LLVM ops anyway. + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_slli_si128 :: #force_inline proc "c" (a: simd.u8x16, $IMM8: u32) -> simd.u8x16 { + shift :: IMM8 & 0xff + + // This needs to emit behavior identical to PSLLDQ which is as follows: + // + // TEMP := COUNT + // IF (TEMP > 15) THEN TEMP := 16; FI + // DEST := DEST << (TEMP * 8) + // DEST[MAXVL-1:128] (Unmodified) + + return simd.shuffle( + simd.u8x16{}, + a, + 0 when shift > 15 else (16 - shift + 0), + 1 when shift > 15 else (16 - shift + 1), + 2 when shift > 15 else (16 - shift + 2), + 3 when shift > 15 else (16 - shift + 3), + 4 when shift > 15 else (16 - shift + 4), + 5 when shift > 15 else (16 - shift + 5), + 6 when shift > 15 else (16 - shift + 6), + 7 when shift > 15 else (16 - shift + 7), + 8 when shift > 15 else (16 - shift + 8), + 9 when shift > 15 else (16 - shift + 9), + 10 when shift > 15 else (16 - shift + 10), + 11 when shift > 15 else (16 - shift + 11), + 12 when shift > 15 else (16 - shift + 12), + 13 when shift > 15 else (16 - shift + 13), + 14 when shift > 15 else (16 - shift + 14), + 15 when shift > 15 else (16 - shift + 15), + ) +} + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_shuffle_epi32 :: #force_inline proc "c" (a: simd.u8x16, $IMM8: u32) -> simd.u8x16 { + v := transmute(simd.i32x4)a + return transmute(simd.u8x16)simd.shuffle( + v, + v, + IMM8 & 0b11, + (IMM8 >> 2) & 0b11, + (IMM8 >> 4) & 0b11, + (IMM8 >> 6) & 0b11, + ) +} + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_shuffle_ps :: #force_inline proc "c" (a, b: simd.u8x16, $MASK: u32) -> simd.u8x16 { + return transmute(simd.u8x16)simd.shuffle( + transmute(simd.u32x4)(a), + transmute(simd.u32x4)(b), + u32(MASK) & 0b11, + (u32(MASK)>>2) & 0b11, + ((u32(MASK)>>4) & 0b11)+4, + ((u32(MASK)>>6) & 0b11)+4) +} diff --git a/core/crypto/_aes/hw/intrinsics_intel.odin b/core/crypto/_aes/hw/intrinsics_intel.odin new file mode 100644 index 000000000..25399dfae --- /dev/null +++ b/core/crypto/_aes/hw/intrinsics_intel.odin @@ -0,0 +1,55 @@ +#+build amd64 +package aes_hw + +import "core:simd" +import "core:simd/x86" + +// Intel/RISC-V semantics. + +TARGET_FEATURES :: "sse,sse2,ssse3,sse4.1,aes" +HAS_GHASH :: true + +@(require_results, enable_target_feature = "aes") +aesdec :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aesdec_si128(transmute(x86.__m128i)(data), transmute(x86.__m128i)(key))) +} + +@(require_results, enable_target_feature = "aes") +aesdeclast :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aesdeclast_si128(transmute(x86.__m128i)(data), transmute(x86.__m128i)(key))) +} + +@(require_results, enable_target_feature = "aes") +aesenc :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aesenc_si128(transmute(x86.__m128i)(data), transmute(x86.__m128i)(key))) +} + +@(require_results, enable_target_feature = "aes") +aesenclast :: #force_inline proc "c" (data, key: simd.u8x16) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aesenclast_si128(transmute(x86.__m128i)(data), transmute(x86.__m128i)(key))) +} + +@(require_results, enable_target_feature = "aes") +aesimc :: #force_inline proc "c" (data: simd.u8x16) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aesimc_si128(transmute(x86.__m128i)(data))) +} + +@(require_results, enable_target_feature = "aes") +aeskeygenassist :: #force_inline proc "c" (data: simd.u8x16, $IMM8: u8) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_aeskeygenassist_si128(transmute(x86.__m128i)(data), IMM8)) +} + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_slli_si128 :: #force_inline proc "c" (a: simd.u8x16, $IMM8: u32) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_slli_si128(transmute(x86.__m128i)(a), IMM8)) +} + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_shuffle_epi32 :: #force_inline proc "c" (a: simd.u8x16, $IMM8: u32) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_shuffle_epi32(transmute(x86.__m128i)(a), IMM8)) +} + +@(private, require_results, enable_target_feature = TARGET_FEATURES) +_mm_shuffle_ps :: #force_inline proc "c" (a, b: simd.u8x16, $MASK: u32) -> simd.u8x16 { + return transmute(simd.u8x16)(x86._mm_shuffle_ps(transmute(x86.__m128)(a), transmute(x86.__m128)(b), MASK)) +} diff --git a/core/crypto/_aes/hw/keysched_hw.odin b/core/crypto/_aes/hw/keysched_hw.odin new file mode 100644 index 000000000..7d85c43b7 --- /dev/null +++ b/core/crypto/_aes/hw/keysched_hw.odin @@ -0,0 +1,181 @@ +// Copyright (c) 2017 Thomas Pornin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#+build amd64,arm64,arm32 +package aes_hw + +import "base:intrinsics" +import "core:crypto" +import "core:crypto/_aes" +import "core:simd" + +// Inspiration taken from BearSSL's AES-NI implementation. +// +// Note: This assumes that the SROA optimization pass is enabled to be +// anything resembling performant otherwise, LLVM will not elide a massive +// number of redundant loads/stores it generates for every intrinsic call. + +@(private = "file", require_results, enable_target_feature = TARGET_FEATURES) +expand_step128 :: #force_inline proc(k1, k2: simd.u8x16) -> simd.u8x16 { + k1, k2 := k1, k2 + + k2 = _mm_shuffle_epi32(k2, 0xff) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + return simd.bit_xor(k1, k2) +} + +@(private = "file", require_results, enable_target_feature = TARGET_FEATURES) +expand_step192a :: #force_inline proc (k1_, k2_: ^simd.u8x16, k3: simd.u8x16) -> (simd.u8x16, simd.u8x16) { + k1, k2, k3 := k1_^, k2_^, k3 + + k3 = _mm_shuffle_epi32(k3, 0x55) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, k3) + + tmp := k2 + k2 = simd.bit_xor(k2, _mm_slli_si128(k2, 0x04)) + k2 = simd.bit_xor(k2, _mm_shuffle_epi32(k1, 0xff)) + + k1_, k2_ := k1_, k2_ + k1_^, k2_^ = k1, k2 + + r1 := _mm_shuffle_ps(tmp, k1, 0x44) + r2 := _mm_shuffle_ps(k1, k2, 0x4e) + + return r1, r2 +} + +@(private = "file", require_results, enable_target_feature = TARGET_FEATURES) +expand_step192b :: #force_inline proc (k1_, k2_: ^simd.u8x16, k3: simd.u8x16) -> simd.u8x16 { + k1, k2, k3 := k1_^, k2_^, k3 + + k3 = _mm_shuffle_epi32(k3, 0x55) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, k3) + + k2 = simd.bit_xor(k2, _mm_slli_si128(k2, 0x04)) + k2 = simd.bit_xor(k2, _mm_shuffle_epi32(k1, 0xff)) + + k1_, k2_ := k1_, k2_ + k1_^, k2_^ = k1, k2 + + return k1 +} + +@(private = "file", require_results, enable_target_feature = TARGET_FEATURES) +expand_step256b :: #force_inline proc(k1, k2: simd.u8x16) -> simd.u8x16 { + k1, k2 := k1, k2 + + k2 = _mm_shuffle_epi32(k2, 0xaa) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + k1 = simd.bit_xor(k1, _mm_slli_si128(k1, 0x04)) + return simd.bit_xor(k1, k2) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +derive_dec_keys :: proc(ctx: ^Context, sks: ^[15]simd.u8x16, num_rounds: int) { + intrinsics.unaligned_store((^simd.u8x16)(&ctx._sk_exp_dec[0]), sks[num_rounds]) + for i in 1 ..< num_rounds { + tmp := aesimc(sks[i]) + intrinsics.unaligned_store((^simd.u8x16)(&ctx._sk_exp_dec[num_rounds - i]), tmp) + } + intrinsics.unaligned_store((^simd.u8x16)(&ctx._sk_exp_dec[num_rounds]), sks[0]) +} + +@(private, enable_target_feature = TARGET_FEATURES) +keysched :: proc(ctx: ^Context, key: []byte) { + sks: [15]simd.u8x16 = --- + + // Compute the encryption keys. + num_rounds, key_len := 0, len(key) + switch key_len { + case _aes.KEY_SIZE_128: + sks[0] = intrinsics.unaligned_load((^simd.u8x16)(raw_data(key))) + sks[1] = expand_step128(sks[0], aeskeygenassist(sks[0], 0x01)) + sks[2] = expand_step128(sks[1], aeskeygenassist(sks[1], 0x02)) + sks[3] = expand_step128(sks[2], aeskeygenassist(sks[2], 0x04)) + sks[4] = expand_step128(sks[3], aeskeygenassist(sks[3], 0x08)) + sks[5] = expand_step128(sks[4], aeskeygenassist(sks[4], 0x10)) + sks[6] = expand_step128(sks[5], aeskeygenassist(sks[5], 0x20)) + sks[7] = expand_step128(sks[6], aeskeygenassist(sks[6], 0x40)) + sks[8] = expand_step128(sks[7], aeskeygenassist(sks[7], 0x80)) + sks[9] = expand_step128(sks[8], aeskeygenassist(sks[8], 0x1b)) + sks[10] = expand_step128(sks[9], aeskeygenassist(sks[9], 0x36)) + num_rounds = _aes.ROUNDS_128 + case _aes.KEY_SIZE_192: + k0 := intrinsics.unaligned_load((^simd.u8x16)(raw_data(key))) + + k1_tmp: [16]byte + copy(k1_tmp[:], key[16:24]) + k1 := intrinsics.unaligned_load((^simd.u8x16)(&k1_tmp)) + crypto.zero_explicit(&k1_tmp, size_of(k1_tmp)) + + sks[0] = k0 + sks[1], sks[2] = expand_step192a(&k0, &k1, aeskeygenassist(k1, 0x01)) + sks[3] = expand_step192b(&k0, &k1, aeskeygenassist(k1, 0x02)) + sks[4], sks[5] = expand_step192a(&k0, &k1, aeskeygenassist(k1, 0x04)) + sks[6] = expand_step192b(&k0, &k1, aeskeygenassist(k1, 0x08)) + sks[7], sks[8] = expand_step192a(&k0, &k1, aeskeygenassist(k1, 0x10)) + sks[9] = expand_step192b(&k0, &k1, aeskeygenassist(k1, 0x20)) + sks[10], sks[11] = expand_step192a(&k0, &k1, aeskeygenassist(k1, 0x40)) + sks[12] = expand_step192b(&k0, &k1, aeskeygenassist(k1, 0x80)) + num_rounds = _aes.ROUNDS_192 + + case _aes.KEY_SIZE_256: + sks[0] = intrinsics.unaligned_load((^simd.u8x16)(raw_data(key))) + sks[1] = intrinsics.unaligned_load((^simd.u8x16)(raw_data(key[16:]))) + sks[2] = expand_step128(sks[0], aeskeygenassist(sks[1], 0x01)) + sks[3] = expand_step256b(sks[1], aeskeygenassist(sks[2], 0x01)) + sks[4] = expand_step128(sks[2], aeskeygenassist(sks[3], 0x02)) + sks[5] = expand_step256b(sks[3], aeskeygenassist(sks[4], 0x02)) + sks[6] = expand_step128(sks[4], aeskeygenassist(sks[5], 0x04)) + sks[7] = expand_step256b(sks[5], aeskeygenassist(sks[6], 0x04)) + sks[8] = expand_step128(sks[6], aeskeygenassist(sks[7], 0x08)) + sks[9] = expand_step256b(sks[7], aeskeygenassist(sks[8], 0x08)) + sks[10] = expand_step128(sks[8], aeskeygenassist(sks[9], 0x10)) + sks[11] = expand_step256b(sks[9], aeskeygenassist(sks[10], 0x10)) + sks[12] = expand_step128(sks[10], aeskeygenassist(sks[11], 0x20)) + sks[13] = expand_step256b(sks[11], aeskeygenassist(sks[12], 0x20)) + sks[14] = expand_step128(sks[12], aeskeygenassist(sks[13], 0x40)) + num_rounds = _aes.ROUNDS_256 + case: + panic("crypto/aes: invalid AES key size") + } + for i in 0 ..= num_rounds { + intrinsics.unaligned_store((^simd.u8x16)(&ctx._sk_exp_enc[i]), sks[i]) + } + + // Compute the decryption keys. GCM and CTR do not need this, however + // ECB, CBC, OCB3, etc do. + derive_dec_keys(ctx, &sks, num_rounds) + + ctx._num_rounds = num_rounds + + crypto.zero_explicit(&sks, size_of(sks)) +} diff --git a/core/crypto/_aes/hw/unsupported.odin b/core/crypto/_aes/hw/unsupported.odin new file mode 100644 index 000000000..3fb31b6b8 --- /dev/null +++ b/core/crypto/_aes/hw/unsupported.odin @@ -0,0 +1,11 @@ +#+build !amd64 +#+build !arm64 +#+build !arm32 +package aes_hw + +HAS_GHASH :: false + +@(private) +keysched :: proc(ctx: ^Context, key: []byte) { + panic("crypto/aes: hardware implementation unsupported") +} diff --git a/core/crypto/_aes/hw_intel/api.odin b/core/crypto/_aes/hw_intel/api.odin deleted file mode 100644 index 52669cb35..000000000 --- a/core/crypto/_aes/hw_intel/api.odin +++ /dev/null @@ -1,43 +0,0 @@ -#+build amd64 -package aes_hw_intel - -import "core:sys/info" - -// is_supported returns true iff hardware accelerated AES -// is supported. -is_supported :: proc "contextless" () -> bool { - features, ok := info.cpu_features.? - if !ok { - return false - } - - // Note: Everything with AES-NI and PCLMULQDQ has support for - // the required SSE extxtensions. - req_features :: info.CPU_Features{ - .sse2, - .ssse3, - .sse41, - .aes, - .pclmulqdq, - } - return features >= req_features -} - -// Context is a keyed AES (ECB) instance. -Context :: struct { - // Note: The ideal thing to do is for the expanded round keys to be - // arrays of `__m128i`, however that implies alignment (or using AVX). - // - // All the people using e-waste processors that don't support an - // insturction set that has been around for over 10 years are why - // we can't have nice things. - _sk_exp_enc: [15][16]byte, - _sk_exp_dec: [15][16]byte, - _num_rounds: int, -} - -// init initializes a context for AES with the provided key. -init :: proc(ctx: ^Context, key: []byte) { - keysched(ctx, key) -} - diff --git a/core/crypto/_aes/hw_intel/hw_intel_keysched.odin b/core/crypto/_aes/hw_intel/hw_intel_keysched.odin deleted file mode 100644 index bdf0d3066..000000000 --- a/core/crypto/_aes/hw_intel/hw_intel_keysched.odin +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2017 Thomas Pornin -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#+build amd64 -package aes_hw_intel - -import "base:intrinsics" -import "core:crypto/_aes" -import "core:mem" -import "core:simd/x86" - -// Intel AES-NI based implementation. Inspiration taken from BearSSL. -// -// Note: This assumes that the SROA optimization pass is enabled to be -// anything resembling performat otherwise, LLVM will not elide a massive -// number of redundant loads/stores it generates for every intrinsic call. - -@(private = "file", require_results, enable_target_feature = "sse2") -expand_step128 :: #force_inline proc(k1, k2: x86.__m128i) -> x86.__m128i { - k1, k2 := k1, k2 - - k2 = x86._mm_shuffle_epi32(k2, 0xff) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - return x86._mm_xor_si128(k1, k2) -} - -@(private = "file", require_results, enable_target_feature = "sse,sse2") -expand_step192a :: #force_inline proc (k1_, k2_: ^x86.__m128i, k3: x86.__m128i) -> (x86.__m128i, x86.__m128i) { - k1, k2, k3 := k1_^, k2_^, k3 - - k3 = x86._mm_shuffle_epi32(k3, 0x55) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, k3) - - tmp := k2 - k2 = x86._mm_xor_si128(k2, x86._mm_slli_si128(k2, 0x04)) - k2 = x86._mm_xor_si128(k2, x86._mm_shuffle_epi32(k1, 0xff)) - - k1_, k2_ := k1_, k2_ - k1_^, k2_^ = k1, k2 - - r1 := transmute(x86.__m128i)(x86._mm_shuffle_ps(transmute(x86.__m128)(tmp), transmute(x86.__m128)(k1), 0x44)) - r2 := transmute(x86.__m128i)(x86._mm_shuffle_ps(transmute(x86.__m128)(k1), transmute(x86.__m128)(k2), 0x4e)) - - return r1, r2 -} - -@(private = "file", require_results, enable_target_feature = "sse2") -expand_step192b :: #force_inline proc (k1_, k2_: ^x86.__m128i, k3: x86.__m128i) -> x86.__m128i { - k1, k2, k3 := k1_^, k2_^, k3 - - k3 = x86._mm_shuffle_epi32(k3, 0x55) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, k3) - - k2 = x86._mm_xor_si128(k2, x86._mm_slli_si128(k2, 0x04)) - k2 = x86._mm_xor_si128(k2, x86._mm_shuffle_epi32(k1, 0xff)) - - k1_, k2_ := k1_, k2_ - k1_^, k2_^ = k1, k2 - - return k1 -} - -@(private = "file", require_results, enable_target_feature = "sse2") -expand_step256b :: #force_inline proc(k1, k2: x86.__m128i) -> x86.__m128i { - k1, k2 := k1, k2 - - k2 = x86._mm_shuffle_epi32(k2, 0xaa) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - k1 = x86._mm_xor_si128(k1, x86._mm_slli_si128(k1, 0x04)) - return x86._mm_xor_si128(k1, k2) -} - -@(private = "file", enable_target_feature = "aes") -derive_dec_keys :: proc(ctx: ^Context, sks: ^[15]x86.__m128i, num_rounds: int) { - intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[0]), sks[num_rounds]) - for i in 1 ..< num_rounds { - tmp := x86._mm_aesimc_si128(sks[i]) - intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[num_rounds - i]), tmp) - } - intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_dec[num_rounds]), sks[0]) -} - -@(private, enable_target_feature = "sse,sse2,aes") -keysched :: proc(ctx: ^Context, key: []byte) { - sks: [15]x86.__m128i = --- - - // Compute the encryption keys. - num_rounds, key_len := 0, len(key) - switch key_len { - case _aes.KEY_SIZE_128: - sks[0] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key))) - sks[1] = expand_step128(sks[0], x86._mm_aeskeygenassist_si128(sks[0], 0x01)) - sks[2] = expand_step128(sks[1], x86._mm_aeskeygenassist_si128(sks[1], 0x02)) - sks[3] = expand_step128(sks[2], x86._mm_aeskeygenassist_si128(sks[2], 0x04)) - sks[4] = expand_step128(sks[3], x86._mm_aeskeygenassist_si128(sks[3], 0x08)) - sks[5] = expand_step128(sks[4], x86._mm_aeskeygenassist_si128(sks[4], 0x10)) - sks[6] = expand_step128(sks[5], x86._mm_aeskeygenassist_si128(sks[5], 0x20)) - sks[7] = expand_step128(sks[6], x86._mm_aeskeygenassist_si128(sks[6], 0x40)) - sks[8] = expand_step128(sks[7], x86._mm_aeskeygenassist_si128(sks[7], 0x80)) - sks[9] = expand_step128(sks[8], x86._mm_aeskeygenassist_si128(sks[8], 0x1b)) - sks[10] = expand_step128(sks[9], x86._mm_aeskeygenassist_si128(sks[9], 0x36)) - num_rounds = _aes.ROUNDS_128 - case _aes.KEY_SIZE_192: - k0 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(key))) - k1 := x86.__m128i{ - intrinsics.unaligned_load((^i64)(raw_data(key[16:]))), - 0, - } - sks[0] = k0 - sks[1], sks[2] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x01)) - sks[3] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x02)) - sks[4], sks[5] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x04)) - sks[6] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x08)) - sks[7], sks[8] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x10)) - sks[9] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x20)) - sks[10], sks[11] = expand_step192a(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x40)) - sks[12] = expand_step192b(&k0, &k1, x86._mm_aeskeygenassist_si128(k1, 0x80)) - num_rounds = _aes.ROUNDS_192 - case _aes.KEY_SIZE_256: - sks[0] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key))) - sks[1] = intrinsics.unaligned_load((^x86.__m128i)(raw_data(key[16:]))) - sks[2] = expand_step128(sks[0], x86._mm_aeskeygenassist_si128(sks[1], 0x01)) - sks[3] = expand_step256b(sks[1], x86._mm_aeskeygenassist_si128(sks[2], 0x01)) - sks[4] = expand_step128(sks[2], x86._mm_aeskeygenassist_si128(sks[3], 0x02)) - sks[5] = expand_step256b(sks[3], x86._mm_aeskeygenassist_si128(sks[4], 0x02)) - sks[6] = expand_step128(sks[4], x86._mm_aeskeygenassist_si128(sks[5], 0x04)) - sks[7] = expand_step256b(sks[5], x86._mm_aeskeygenassist_si128(sks[6], 0x04)) - sks[8] = expand_step128(sks[6], x86._mm_aeskeygenassist_si128(sks[7], 0x08)) - sks[9] = expand_step256b(sks[7], x86._mm_aeskeygenassist_si128(sks[8], 0x08)) - sks[10] = expand_step128(sks[8], x86._mm_aeskeygenassist_si128(sks[9], 0x10)) - sks[11] = expand_step256b(sks[9], x86._mm_aeskeygenassist_si128(sks[10], 0x10)) - sks[12] = expand_step128(sks[10], x86._mm_aeskeygenassist_si128(sks[11], 0x20)) - sks[13] = expand_step256b(sks[11], x86._mm_aeskeygenassist_si128(sks[12], 0x20)) - sks[14] = expand_step128(sks[12], x86._mm_aeskeygenassist_si128(sks[13], 0x40)) - num_rounds = _aes.ROUNDS_256 - case: - panic("crypto/aes: invalid AES key size") - } - for i in 0 ..= num_rounds { - intrinsics.unaligned_store((^x86.__m128i)(&ctx._sk_exp_enc[i]), sks[i]) - } - - // Compute the decryption keys. GCM and CTR do not need this, however - // ECB, CBC, OCB3, etc do. - derive_dec_keys(ctx, &sks, num_rounds) - - ctx._num_rounds = num_rounds - - mem.zero_explicit(&sks, size_of(sks)) -} diff --git a/core/crypto/_blake2/blake2.odin b/core/crypto/_blake2/blake2.odin index 89fbe3a7a..cf7111c70 100644 --- a/core/crypto/_blake2/blake2.odin +++ b/core/crypto/_blake2/blake2.odin @@ -2,7 +2,7 @@ package _blake2 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -10,25 +10,21 @@ package _blake2 Implementation of the BLAKE2 hashing algorithm, as defined in and */ +import "base:intrinsics" +import "core:crypto" import "core:encoding/endian" -import "core:mem" BLAKE2S_BLOCK_SIZE :: 64 BLAKE2S_SIZE :: 32 BLAKE2B_BLOCK_SIZE :: 128 BLAKE2B_SIZE :: 64 -MAX_SIZE :: 255 - Blake2s_Context :: struct { h: [8]u32, t: [2]u32, f: [2]u32, x: [BLAKE2S_BLOCK_SIZE]byte, nx: int, - ih: [8]u32, - padded_key: [BLAKE2S_BLOCK_SIZE]byte, - is_keyed: bool, size: byte, is_last_node: bool, @@ -41,9 +37,6 @@ Blake2b_Context :: struct { f: [2]u64, x: [BLAKE2B_BLOCK_SIZE]byte, nx: int, - ih: [8]u64, - padded_key: [BLAKE2B_BLOCK_SIZE]byte, - is_keyed: bool, size: byte, is_last_node: bool, @@ -86,11 +79,12 @@ BLAKE2B_IV := [8]u64 { init :: proc "contextless" (ctx: ^$T, cfg: ^Blake2_Config) { when T == Blake2s_Context { - max_size :: BLAKE2S_SIZE + MAX_SIZE :: BLAKE2S_SIZE } else when T == Blake2b_Context { - max_size :: BLAKE2B_SIZE + MAX_SIZE :: BLAKE2B_SIZE } - ensure_contextless(cfg.size <= max_size, "blake2: requested output size exceeeds algorithm max") + ensure_contextless(cfg.size <= MAX_SIZE, "blake2: requested output size exceeeds algorithm max") + ensure_contextless(len(cfg.key) <= MAX_SIZE, "blake2: requested key size exceeeds algorithm max") // To save having to allocate a scratch buffer, use the internal // data buffer (`ctx.x`), as it is exactly the correct size. @@ -133,7 +127,7 @@ init :: proc "contextless" (ctx: ^$T, cfg: ^Blake2_Config) { p[17] = cfg.tree.(Blake2_Tree).inner_hash_size } } else { - p[2], p[3] = 1, 1 + p[2], p[3], p[4], p[5], p[6], p[7] = 1, 1, 0, 0, 0, 0 } ctx.size = cfg.size for i := 0; i < 8; i += 1 { @@ -145,23 +139,17 @@ init :: proc "contextless" (ctx: ^$T, cfg: ^Blake2_Config) { } } - mem.zero(&ctx.x, size_of(ctx.x)) // Done with the scratch space, no barrier. + intrinsics.mem_zero(&ctx.x, size_of(ctx.x)) // Done with the scratch space, no barrier. if cfg.tree != nil && cfg.tree.(Blake2_Tree).is_last_node { ctx.is_last_node = true } if len(cfg.key) > 0 { - copy(ctx.padded_key[:], cfg.key) - update(ctx, ctx.padded_key[:]) - ctx.is_keyed = true + copy(ctx.x[:], cfg.key) + ctx.nx = len(ctx.x) + } else { + ctx.nx = 0 } - copy(ctx.ih[:], ctx.h[:]) - copy(ctx.h[:], ctx.ih[:]) - if ctx.is_keyed { - update(ctx, ctx.padded_key[:]) - } - - ctx.nx = 0 ctx.is_initialized = true } @@ -171,22 +159,22 @@ update :: proc "contextless" (ctx: ^$T, p: []byte) { p := p when T == Blake2s_Context { - block_size :: BLAKE2S_BLOCK_SIZE + BLOCK_SIZE :: BLAKE2S_BLOCK_SIZE } else when T == Blake2b_Context { - block_size :: BLAKE2B_BLOCK_SIZE + BLOCK_SIZE :: BLAKE2B_BLOCK_SIZE } - left := block_size - ctx.nx + left := BLOCK_SIZE - ctx.nx if len(p) > left { copy(ctx.x[ctx.nx:], p[:left]) p = p[left:] blocks(ctx, ctx.x[:]) ctx.nx = 0 } - if len(p) > block_size { - n := len(p) &~ (block_size - 1) + if len(p) > BLOCK_SIZE { + n := len(p) &~ (BLOCK_SIZE - 1) if n == len(p) { - n -= block_size + n -= BLOCK_SIZE } blocks(ctx, p[:n]) p = p[n:] @@ -222,17 +210,11 @@ reset :: proc "contextless" (ctx: ^$T) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } @(private) blake2s_final :: proc "contextless" (ctx: ^Blake2s_Context, hash: []byte) { - if ctx.is_keyed { - for i := 0; i < len(ctx.padded_key); i += 1 { - ctx.padded_key[i] = 0 - } - } - dec := BLAKE2S_BLOCK_SIZE - u32(ctx.nx) if ctx.t[0] < dec { ctx.t[1] -= 1 @@ -244,23 +226,20 @@ blake2s_final :: proc "contextless" (ctx: ^Blake2s_Context, hash: []byte) { ctx.f[1] = 0xffffffff } + for i := ctx.nx; i < BLAKE2S_BLOCK_SIZE; i+= 1 { + ctx.x[i] = 0 + } blocks(ctx, ctx.x[:]) dst: [BLAKE2S_SIZE]byte for i := 0; i < BLAKE2S_SIZE / 4; i += 1 { endian.unchecked_put_u32le(dst[i * 4:], ctx.h[i]) } - copy(hash, dst[:]) + copy(hash, dst[:ctx.size]) } @(private) blake2b_final :: proc "contextless" (ctx: ^Blake2b_Context, hash: []byte) { - if ctx.is_keyed { - for i := 0; i < len(ctx.padded_key); i += 1 { - ctx.padded_key[i] = 0 - } - } - dec := BLAKE2B_BLOCK_SIZE - u64(ctx.nx) if ctx.t[0] < dec { ctx.t[1] -= 1 @@ -272,6 +251,9 @@ blake2b_final :: proc "contextless" (ctx: ^Blake2b_Context, hash: []byte) { ctx.f[1] = 0xffffffffffffffff } + for i := ctx.nx; i < BLAKE2B_BLOCK_SIZE; i+= 1 { + ctx.x[i] = 0 + } blocks(ctx, ctx.x[:]) dst: [BLAKE2B_SIZE]byte diff --git a/core/crypto/_chacha20/chacha20.odin b/core/crypto/_chacha20/chacha20.odin index 1a4b5a507..7d94d8a95 100644 --- a/core/crypto/_chacha20/chacha20.odin +++ b/core/crypto/_chacha20/chacha20.odin @@ -1,8 +1,8 @@ package _chacha20 +import "core:crypto" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // KEY_SIZE is the (X)ChaCha20 key size in bytes. KEY_SIZE :: 32 @@ -88,8 +88,8 @@ seek :: proc(ctx: ^Context, block_nr: u64) { // reset sanitizes the Context. The Context must be re-initialized to // be used again. reset :: proc(ctx: ^Context) { - mem.zero_explicit(&ctx._s, size_of(ctx._s)) - mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer)) + crypto.zero_explicit(&ctx._s, size_of(ctx._s)) + crypto.zero_explicit(&ctx._buffer, size_of(ctx._buffer)) ctx._is_initialized = false } @@ -116,4 +116,4 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) { } ensure(ctr_ok, "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached") -} +} \ No newline at end of file diff --git a/core/crypto/_chacha20/ref/chacha20_ref.odin b/core/crypto/_chacha20/ref/chacha20_ref.odin index c111c1c76..c4e6bca98 100644 --- a/core/crypto/_chacha20/ref/chacha20_ref.odin +++ b/core/crypto/_chacha20/ref/chacha20_ref.odin @@ -4,133 +4,68 @@ import "core:crypto/_chacha20" import "core:encoding/endian" import "core:math/bits" +// At least with LLVM21 force_inline produces identical perf to +// manual inlining, yay. +@(private) +quarter_round :: #force_inline proc "contextless" (a, b, c, d: u32) -> (u32, u32, u32, u32) { + a, b, c, d := a, b, c, d + + a += b + d ~= a + d = bits.rotate_left32(d, 16) + + c += d + b ~= c + b = bits.rotate_left32(b, 12) + + a += b + d ~= a + d = bits.rotate_left32(d, 8) + + c += d + b ~= c + b = bits.rotate_left32(b, 7) + + return a, b, c, d +} + stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) { // Enforce the maximum consumed keystream per IV. _chacha20.check_counter_limit(ctx, nr_blocks) dst, src := dst, src x := &ctx._s + + + // Filippo Valsorda made an observation that only one of the column + // round depends on the counter (s12), so it is worth precomputing + // and reusing across multiple blocks. As far as I know, only Go's + // chacha implementation does this. + + p1, p5, p9, p13 := quarter_round(_chacha20.SIGMA_1, x[5], x[9], x[13]) + p2, p6, p10, p14 := quarter_round(_chacha20.SIGMA_2, x[6], x[10], x[14]) + p3, p7, p11, p15 := quarter_round(_chacha20.SIGMA_3, x[7], x[11], x[15]) + for n := 0; n < nr_blocks; n = n + 1 { - x0, x1, x2, x3 := - _chacha20.SIGMA_0, _chacha20.SIGMA_1, _chacha20.SIGMA_2, _chacha20.SIGMA_3 - x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := - x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15] + // First column round that depends on the counter + p0, p4, p8, p12 := quarter_round(_chacha20.SIGMA_0, x[4], x[8], x[12]) - for i := _chacha20.ROUNDS; i > 0; i = i - 2 { - // Even when forcing inlining manually inlining all of - // these is decently faster. + // First diagonal round + x0, x5, x10, x15 := quarter_round(p0, p5, p10, p15) + x1, x6, x11, x12 := quarter_round(p1, p6, p11, p12) + x2, x7, x8, x13 := quarter_round(p2, p7, p8, p13) + x3, x4, x9, x14 := quarter_round(p3, p4, p9, p14) - // quarterround(x, 0, 4, 8, 12) - x0 += x4 - x12 ~= x0 - x12 = bits.rotate_left32(x12, 16) - x8 += x12 - x4 ~= x8 - x4 = bits.rotate_left32(x4, 12) - x0 += x4 - x12 ~= x0 - x12 = bits.rotate_left32(x12, 8) - x8 += x12 - x4 ~= x8 - x4 = bits.rotate_left32(x4, 7) + for i := _chacha20.ROUNDS - 2; i > 0; i = i - 2 { + x0, x4, x8, x12 = quarter_round(x0, x4, x8, x12) + x1, x5, x9, x13 = quarter_round(x1, x5, x9, x13) + x2, x6, x10, x14 = quarter_round(x2, x6, x10, x14) + x3, x7, x11, x15 = quarter_round(x3, x7, x11, x15) - // quarterround(x, 1, 5, 9, 13) - x1 += x5 - x13 ~= x1 - x13 = bits.rotate_left32(x13, 16) - x9 += x13 - x5 ~= x9 - x5 = bits.rotate_left32(x5, 12) - x1 += x5 - x13 ~= x1 - x13 = bits.rotate_left32(x13, 8) - x9 += x13 - x5 ~= x9 - x5 = bits.rotate_left32(x5, 7) - - // quarterround(x, 2, 6, 10, 14) - x2 += x6 - x14 ~= x2 - x14 = bits.rotate_left32(x14, 16) - x10 += x14 - x6 ~= x10 - x6 = bits.rotate_left32(x6, 12) - x2 += x6 - x14 ~= x2 - x14 = bits.rotate_left32(x14, 8) - x10 += x14 - x6 ~= x10 - x6 = bits.rotate_left32(x6, 7) - - // quarterround(x, 3, 7, 11, 15) - x3 += x7 - x15 ~= x3 - x15 = bits.rotate_left32(x15, 16) - x11 += x15 - x7 ~= x11 - x7 = bits.rotate_left32(x7, 12) - x3 += x7 - x15 ~= x3 - x15 = bits.rotate_left32(x15, 8) - x11 += x15 - x7 ~= x11 - x7 = bits.rotate_left32(x7, 7) - - // quarterround(x, 0, 5, 10, 15) - x0 += x5 - x15 ~= x0 - x15 = bits.rotate_left32(x15, 16) - x10 += x15 - x5 ~= x10 - x5 = bits.rotate_left32(x5, 12) - x0 += x5 - x15 ~= x0 - x15 = bits.rotate_left32(x15, 8) - x10 += x15 - x5 ~= x10 - x5 = bits.rotate_left32(x5, 7) - - // quarterround(x, 1, 6, 11, 12) - x1 += x6 - x12 ~= x1 - x12 = bits.rotate_left32(x12, 16) - x11 += x12 - x6 ~= x11 - x6 = bits.rotate_left32(x6, 12) - x1 += x6 - x12 ~= x1 - x12 = bits.rotate_left32(x12, 8) - x11 += x12 - x6 ~= x11 - x6 = bits.rotate_left32(x6, 7) - - // quarterround(x, 2, 7, 8, 13) - x2 += x7 - x13 ~= x2 - x13 = bits.rotate_left32(x13, 16) - x8 += x13 - x7 ~= x8 - x7 = bits.rotate_left32(x7, 12) - x2 += x7 - x13 ~= x2 - x13 = bits.rotate_left32(x13, 8) - x8 += x13 - x7 ~= x8 - x7 = bits.rotate_left32(x7, 7) - - // quarterround(x, 3, 4, 9, 14) - x3 += x4 - x14 ~= x3 - x14 = bits.rotate_left32(x14, 16) - x9 += x14 - x4 ~= x9 - x4 = bits.rotate_left32(x4, 12) - x3 += x4 - x14 ~= x3 - x14 = bits.rotate_left32(x14, 8) - x9 += x14 - x4 ~= x9 - x4 = bits.rotate_left32(x4, 7) + x0, x5, x10, x15 = quarter_round(x0, x5, x10, x15) + x1, x6, x11, x12 = quarter_round(x1, x6, x11, x12) + x2, x7, x8, x13 = quarter_round(x2, x7, x8, x13) + x3, x4, x9, x14 = quarter_round(x3, x4, x9, x14) } x0 += _chacha20.SIGMA_0 @@ -236,117 +171,15 @@ hchacha20 :: proc "contextless" (dst, key, iv: []byte) { x15 := endian.unchecked_get_u32le(iv[12:16]) for i := _chacha20.ROUNDS; i > 0; i = i - 2 { - // quarterround(x, 0, 4, 8, 12) - x0 += x4 - x12 ~= x0 - x12 = bits.rotate_left32(x12, 16) - x8 += x12 - x4 ~= x8 - x4 = bits.rotate_left32(x4, 12) - x0 += x4 - x12 ~= x0 - x12 = bits.rotate_left32(x12, 8) - x8 += x12 - x4 ~= x8 - x4 = bits.rotate_left32(x4, 7) + x0, x4, x8, x12 = quarter_round(x0, x4, x8, x12) + x1, x5, x9, x13 = quarter_round(x1, x5, x9, x13) + x2, x6, x10, x14 = quarter_round(x2, x6, x10, x14) + x3, x7, x11, x15 = quarter_round(x3, x7, x11, x15) - // quarterround(x, 1, 5, 9, 13) - x1 += x5 - x13 ~= x1 - x13 = bits.rotate_left32(x13, 16) - x9 += x13 - x5 ~= x9 - x5 = bits.rotate_left32(x5, 12) - x1 += x5 - x13 ~= x1 - x13 = bits.rotate_left32(x13, 8) - x9 += x13 - x5 ~= x9 - x5 = bits.rotate_left32(x5, 7) - - // quarterround(x, 2, 6, 10, 14) - x2 += x6 - x14 ~= x2 - x14 = bits.rotate_left32(x14, 16) - x10 += x14 - x6 ~= x10 - x6 = bits.rotate_left32(x6, 12) - x2 += x6 - x14 ~= x2 - x14 = bits.rotate_left32(x14, 8) - x10 += x14 - x6 ~= x10 - x6 = bits.rotate_left32(x6, 7) - - // quarterround(x, 3, 7, 11, 15) - x3 += x7 - x15 ~= x3 - x15 = bits.rotate_left32(x15, 16) - x11 += x15 - x7 ~= x11 - x7 = bits.rotate_left32(x7, 12) - x3 += x7 - x15 ~= x3 - x15 = bits.rotate_left32(x15, 8) - x11 += x15 - x7 ~= x11 - x7 = bits.rotate_left32(x7, 7) - - // quarterround(x, 0, 5, 10, 15) - x0 += x5 - x15 ~= x0 - x15 = bits.rotate_left32(x15, 16) - x10 += x15 - x5 ~= x10 - x5 = bits.rotate_left32(x5, 12) - x0 += x5 - x15 ~= x0 - x15 = bits.rotate_left32(x15, 8) - x10 += x15 - x5 ~= x10 - x5 = bits.rotate_left32(x5, 7) - - // quarterround(x, 1, 6, 11, 12) - x1 += x6 - x12 ~= x1 - x12 = bits.rotate_left32(x12, 16) - x11 += x12 - x6 ~= x11 - x6 = bits.rotate_left32(x6, 12) - x1 += x6 - x12 ~= x1 - x12 = bits.rotate_left32(x12, 8) - x11 += x12 - x6 ~= x11 - x6 = bits.rotate_left32(x6, 7) - - // quarterround(x, 2, 7, 8, 13) - x2 += x7 - x13 ~= x2 - x13 = bits.rotate_left32(x13, 16) - x8 += x13 - x7 ~= x8 - x7 = bits.rotate_left32(x7, 12) - x2 += x7 - x13 ~= x2 - x13 = bits.rotate_left32(x13, 8) - x8 += x13 - x7 ~= x8 - x7 = bits.rotate_left32(x7, 7) - - // quarterround(x, 3, 4, 9, 14) - x3 += x4 - x14 ~= x3 - x14 = bits.rotate_left32(x14, 16) - x9 += x14 - x4 ~= x9 - x4 = bits.rotate_left32(x4, 12) - x3 += x4 - x14 ~= x3 - x14 = bits.rotate_left32(x14, 8) - x9 += x14 - x4 ~= x9 - x4 = bits.rotate_left32(x4, 7) + x0, x5, x10, x15 = quarter_round(x0, x5, x10, x15) + x1, x6, x11, x12 = quarter_round(x1, x6, x11, x12) + x2, x7, x8, x13 = quarter_round(x2, x7, x8, x13) + x3, x4, x9, x14 = quarter_round(x3, x4, x9, x14) } endian.unchecked_put_u32le(dst[0:4], x0) diff --git a/core/crypto/_chacha20/simd128/chacha20_simd128.odin b/core/crypto/_chacha20/simd128/chacha20_simd128.odin index cf78541d1..fd48074df 100644 --- a/core/crypto/_chacha20/simd128/chacha20_simd128.odin +++ b/core/crypto/_chacha20/simd128/chacha20_simd128.odin @@ -39,7 +39,7 @@ when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { // Some targets lack runtime feature detection, and will flat out refuse // to load binaries that have unknown instructions. This is distinct from -// `simd.IS_EMULATED` as actually good designs support runtime feature +// `simd.HAS_HARDWARE_SIMD` as actually good designs support runtime feature // detection and that constant establishes a baseline. // // See: @@ -215,7 +215,7 @@ _store_simd128 :: #force_inline proc "contextless" ( intrinsics.unaligned_store((^simd.u32x4)(dst[3:]), v3) } -// is_performant returns true iff the target and current host both support +// is_performant returns true if and only if (⟺) the target and current host both support // "enough" 128-bit SIMD to make this implementation performant. is_performant :: proc "contextless" () -> bool { when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 || ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .riscv64 { @@ -227,12 +227,7 @@ is_performant :: proc "contextless" () -> bool { req_features :: info.CPU_Features{.V} } - features, ok := info.cpu_features.? - if !ok { - return false - } - - return features >= req_features + return info.cpu_features() >= req_features } else when ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32 { return intrinsics.has_target_feature("simd128") } else { diff --git a/core/crypto/_chacha20/simd256/chacha20_simd256.odin b/core/crypto/_chacha20/simd256/chacha20_simd256.odin index ccb02a947..c2f709aec 100644 --- a/core/crypto/_chacha20/simd256/chacha20_simd256.odin +++ b/core/crypto/_chacha20/simd256/chacha20_simd256.odin @@ -36,17 +36,12 @@ _VEC_ZERO_ONE: simd.u64x4 : {0, 0, 1, 0} @(private = "file") _VEC_TWO: simd.u64x4 : {2, 0, 2, 0} -// is_performant returns true iff the target and current host both support +// is_performant returns true if and only if (⟺) the target and current host both support // "enough" SIMD to make this implementation performant. is_performant :: proc "contextless" () -> bool { req_features :: info.CPU_Features{.avx, .avx2} - features, ok := info.cpu_features.? - if !ok { - return false - } - - return features >= req_features + return info.cpu_features() >= req_features } @(private = "file") diff --git a/core/crypto/_edwards25519/edwards25519.odin b/core/crypto/_edwards25519/edwards25519.odin index d6f01d497..dddfaef02 100644 --- a/core/crypto/_edwards25519/edwards25519.odin +++ b/core/crypto/_edwards25519/edwards25519.odin @@ -13,7 +13,8 @@ See: import "core:crypto" import field "core:crypto/_fiat/field_curve25519" -import "core:mem" + +zero_explicit :: crypto.zero_explicit // Group_Element is an edwards25519 group element, as extended homogenous // coordinates, which represents the affine point `(x, y)` as `(X, Y, Z, T)`, @@ -96,7 +97,7 @@ Group_Element :: struct { } ge_clear :: proc "contextless" (ge: ^Group_Element) { - mem.zero_explicit(ge, size_of(Group_Element)) + zero_explicit(ge, size_of(Group_Element)) } ge_set :: proc "contextless" (ge, a: ^Group_Element) { @@ -159,7 +160,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { ge_cond_assign(ge, &tmp, is_canonical) - mem.zero_explicit(&buf, size_of(buf)) + zero_explicit(&buf, size_of(buf)) return is_canonical == 1 } @@ -195,7 +196,6 @@ ge_generator :: proc "contextless" (ge: ^Group_Element) { ge_set(ge, &GE_BASEPOINT) } -@(private) Addend_Group_Element :: struct { y2_minus_x2: field.Loose_Field_Element, // t1 y2_plus_x2: field.Loose_Field_Element, // t3 @@ -203,7 +203,6 @@ Addend_Group_Element :: struct { two_times_z2: field.Loose_Field_Element, // t5 } -@(private) ge_addend_set :: proc "contextless" (ge_a: ^Addend_Group_Element, ge: ^Group_Element) { field.fe_sub(&ge_a.y2_minus_x2, &ge.y, &ge.x) field.fe_add(&ge_a.y2_plus_x2, &ge.y, &ge.x) @@ -233,8 +232,8 @@ ge_add :: proc "contextless" (ge, a, b: ^Group_Element) { scratch: Add_Scratch = --- ge_add_addend(ge, a, &b_, &scratch) - mem.zero_explicit(&b_, size_of(Addend_Group_Element)) - mem.zero_explicit(&scratch, size_of(Add_Scratch)) + zero_explicit(&b_, size_of(Addend_Group_Element)) + zero_explicit(&scratch, size_of(Add_Scratch)) } @(private) @@ -354,7 +353,7 @@ ge_double :: proc "contextless" (ge, a: ^Group_Element, scratch: ^Double_Scratch field.fe_carry_mul(&ge.z, F, G_) if sanitize { - mem.zero_explicit(scratch, size_of(Double_Scratch)) + zero_explicit(scratch, size_of(Double_Scratch)) } } @@ -420,6 +419,6 @@ ge_in_prime_order_subgroup_vartime :: proc "contextless" (ge: ^Group_Element) -> // that is a ~50% speedup, and a lot of added complexity for something // that is better solved by "just use ristretto255". tmp: Group_Element = --- - _ge_scalarmult(&tmp, ge, &SC_ELL, true) + ge_scalarmult_raw(&tmp, ge, &SC_ELL, true) return ge_equal(&tmp, &GE_IDENTITY) == 1 -} +} \ No newline at end of file diff --git a/core/crypto/_edwards25519/edwards25519_scalar.odin b/core/crypto/_edwards25519/edwards25519_scalar.odin index 68c79a6e8..5dff03f67 100644 --- a/core/crypto/_edwards25519/edwards25519_scalar.odin +++ b/core/crypto/_edwards25519/edwards25519_scalar.odin @@ -1,7 +1,6 @@ package _edwards25519 import field "core:crypto/_fiat/field_scalar25519" -import "core:mem" Scalar :: field.Montgomery_Domain_Field_Element @@ -19,7 +18,7 @@ sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) { tmp := field.Non_Montgomery_Domain_Field_Element{i, 0, 0, 0} field.fe_to_montgomery(sc, &tmp) - mem.zero_explicit(&tmp, size_of(tmp)) + zero_explicit(&tmp, size_of(tmp)) } @(require_results) @@ -36,7 +35,7 @@ sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) { } sc_clear :: proc "contextless" (sc: ^Scalar) { - mem.zero_explicit(sc, size_of(Scalar)) + zero_explicit(sc, size_of(Scalar)) } sc_set :: field.fe_set diff --git a/core/crypto/_edwards25519/edwards25519_scalar_mul.odin b/core/crypto/_edwards25519/edwards25519_scalar_mul.odin index 757a51257..548062c78 100644 --- a/core/crypto/_edwards25519/edwards25519_scalar_mul.odin +++ b/core/crypto/_edwards25519/edwards25519_scalar_mul.odin @@ -1,130 +1,23 @@ package _edwards25519 +import "core:crypto" import field "core:crypto/_fiat/field_scalar25519" -import "core:math/bits" -import "core:mem" - -// GE_BASEPOINT_TABLE is 1 * G, ... 15 * G, in precomputed format. -// -// Note: When generating, the values were reduced to Tight_Field_Element -// ranges, even though that is not required. -@(private) -GE_BASEPOINT_TABLE := Multiply_Table { - { - {62697248952638, 204681361388450, 631292143396476, 338455783676468, 1213667448819585}, - {1288382639258501, 245678601348599, 269427782077623, 1462984067271730, 137412439391563}, - {301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142}, - {2, 0, 0, 0, 0}, - }, - { - {1519297034332653, 1098796920435767, 1823476547744119, 808144629470969, 2110930855619772}, - {338005982828284, 1667856962156925, 100399270107451, 1604566703601691, 1950338038771369}, - {1920505767731247, 1443759578976892, 1659852098357048, 1484431291070208, 275018744912646}, - {763163817085987, 2195095074806923, 2167883174351839, 1868059999999762, 911071066608705}, - }, - { - {960627541894068, 1314966688943942, 1126875971034044, 2059608312958945, 605975666152586}, - {1714478358025626, 2209607666607510, 1600912834284834, 496072478982142, 481970031861896}, - {851735079403194, 1088965826757164, 141569479297499, 602804610059257, 2004026468601520}, - {197585529552380, 324719066578543, 564481854250498, 1173818332764578, 35452976395676}, - }, - { - {1152980410747203, 2196804280851952, 25745194962557, 1915167295473129, 1266299690309224}, - {809905889679060, 979732230071345, 1509972345538142, 188492426534402, 818965583123815}, - {997685409185036, 1451818320876327, 2126681166774509, 2000509606057528, 235432372486854}, - {887734189279642, 1460338685162044, 877378220074262, 102436391401299, 153369156847490}, - }, - { - {2056621900836770, 1821657694132497, 1627986892909426, 1163363868678833, 1108873376459226}, - {1187697490593623, 1066539945237335, 885654531892000, 1357534489491782, 359370291392448}, - {1509033452137525, 1305318174298508, 613642471748944, 1987256352550234, 1044283663101541}, - {220105720697037, 387661783287620, 328296827867762, 360035589590664, 795213236824054}, - }, - { - {1820794733038396, 1612235121681074, 757405923441402, 1094031020892801, 231025333128907}, - {1639067873254194, 1484176557946322, 300800382144789, 1329915446659183, 1211704578730455}, - {641900794791527, 1711751746971612, 179044712319955, 576455585963824, 1852617592509865}, - {743549047192397, 685091042550147, 1952415336873496, 1965124675654685, 513364998442917}, - }, - { - {1004557076870448, 1762911374844520, 1330807633622723, 384072910939787, 953849032243810}, - {2178275058221458, 257933183722891, 376684351537894, 2010189102001786, 1981824297484148}, - {1332915663881114, 1286540505502549, 1741691283561518, 977214932156314, 1764059494778091}, - {429702949064027, 1368332611650677, 2019867176450999, 2212258376161746, 526160996742554}, - }, - { - {2098932988258576, 2203688382075948, 2120400160059479, 1748488020948146, 1203264167282624}, - {677131386735829, 1850249298025188, 672782146532031, 2144145693078904, 2088656272813787}, - {1065622343976192, 1573853211848116, 223560413590068, 333846833073379, 27832122205830}, - {1781008836504573, 917619542051793, 544322748939913, 882577394308384, 1720521246471195}, - }, - { - {660120928379860, 2081944024858618, 1878411111349191, 424587356517195, 2111317439894005}, - {1834193977811532, 1864164086863319, 797334633289424, 150410812403062, 2085177078466389}, - {1438117271371866, 783915531014482, 388731514584658, 292113935417795, 1945855002546714}, - {1678140823166658, 679103239148744, 614102761596238, 1052962498997885, 1863983323810390}, - }, - { - {1690309392496233, 1116333140326275, 1377242323631039, 717196888780674, 82724646713353}, - {1722370213432106, 74265192976253, 264239578448472, 1714909985012994, 2216984958602173}, - {2010482366920922, 1294036471886319, 566466395005815, 1631955803657320, 1751698647538458}, - {1073230604155753, 1159087041338551, 1664057985455483, 127472702826203, 1339591128522371}, - }, - { - {478053307175577, 2179515791720985, 21146535423512, 1831683844029536, 462805561553981}, - {1945267486565588, 1298536818409655, 2214511796262989, 1904981051429012, 252904800782086}, - {268945954671210, 222740425595395, 1208025911856230, 1080418823003555, 75929831922483}, - {1884784014268948, 643868448202966, 978736549726821, 46385971089796, 1296884812292320}, - }, - { - {1861159462859103, 7077532564710, 963010365896826, 1938780006785270, 766241051941647}, - {1778966986051906, 1713995999765361, 1394565822271816, 1366699246468722, 1213407027149475}, - {1978989286560907, 2135084162045594, 1951565508865477, 671788336314416, 293123929458176}, - {902608944504080, 2167765718046481, 1285718473078022, 1222562171329269, 492109027844479}, - }, - { - {1820807832746213, 1029220580458586, 1101997555432203, 1039081975563572, 202477981158221}, - {1866134980680205, 2222325502763386, 1830284629571201, 1046966214478970, 418381946936795}, - {1783460633291322, 1719505443254998, 1810489639976220, 877049370713018, 2187801198742619}, - {197118243000763, 305493867565736, 518814410156522, 1656246186645170, 901894734874934}, - }, - { - {225454942125915, 478410476654509, 600524586037746, 643450007230715, 1018615928259319}, - {1733330584845708, 881092297970296, 507039890129464, 496397090721598, 2230888519577628}, - {690155664737246, 1010454785646677, 753170144375012, 1651277613844874, 1622648796364156}, - {1321310321891618, 1089655277873603, 235891750867089, 815878279563688, 1709264240047556}, - }, - { - {805027036551342, 1387174275567452, 1156538511461704, 1465897486692171, 1208567094120903}, - {2228417017817483, 202885584970535, 2182114782271881, 2077405042592934, 1029684358182774}, - {460447547653983, 627817697755692, 524899434670834, 1228019344939427, 740684787777653}, - {849757462467675, 447476306919899, 422618957298818, 302134659227815, 675831828440895}, - }, -} +import subtle "core:crypto/_subtle" ge_scalarmult :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) { tmp: field.Non_Montgomery_Domain_Field_Element field.fe_from_montgomery(&tmp, sc) - _ge_scalarmult(ge, p, &tmp) + ge_scalarmult_raw(ge, p, &tmp) - mem.zero_explicit(&tmp, size_of(tmp)) -} - -ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) { - // Something like the comb method from "Fast and compact elliptic-curve - // cryptography" Section 3.3, would be more performant, but more - // complex. - // - // - https://eprint.iacr.org/2012/309 - ge_scalarmult(ge, &GE_BASEPOINT, sc) + zero_explicit(&tmp, size_of(tmp)) } ge_scalarmult_vartime :: proc "contextless" (ge, p: ^Group_Element, sc: ^Scalar) { tmp: field.Non_Montgomery_Domain_Field_Element field.fe_from_montgomery(&tmp, sc) - _ge_scalarmult(ge, p, &tmp, true) + ge_scalarmult_raw(ge, p, &tmp, true) } ge_double_scalarmult_basepoint_vartime :: proc "contextless" ( @@ -147,6 +40,12 @@ ge_double_scalarmult_basepoint_vartime :: proc "contextless" ( A_tbl: Multiply_Table = --- mul_tbl_set(&A_tbl, A, &tmp_add) + when crypto.COMPACT_IMPLS == true { + G_tbl: Multiply_Table = --- + mul_tbl_set(&G_tbl, &GE_BASEPOINT, &tmp_add) + } else { + tmp_bp_addend: Basepoint_Addend_Group_Element = --- + } sc_a, sc_b: field.Non_Montgomery_Domain_Field_Element field.fe_from_montgomery(&sc_a, a) @@ -170,21 +69,28 @@ ge_double_scalarmult_basepoint_vartime :: proc "contextless" ( ge_double(&tmp, &tmp, &tmp_dbl) } mul_tbl_add(&tmp, &A_tbl, hi_a, &tmp_add, &tmp_addend, true) - mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_addend, true) + when crypto.COMPACT_IMPLS == true { + mul_tbl_add(&tmp, &G_tbl, hi_b, &tmp_add, &tmp_addend, true) + } else { + mul_bp_tbl_add(&tmp, GE_BASEPOINT_TABLE, hi_b, &tmp_add, &tmp_bp_addend, true) + } ge_double(&tmp, &tmp, &tmp_dbl) ge_double(&tmp, &tmp, &tmp_dbl) ge_double(&tmp, &tmp, &tmp_dbl) ge_double(&tmp, &tmp, &tmp_dbl) mul_tbl_add(&tmp, &A_tbl, lo_a, &tmp_add, &tmp_addend, true) - mul_tbl_add(&tmp, &GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_addend, true) + when crypto.COMPACT_IMPLS == true { + mul_tbl_add(&tmp, &G_tbl, lo_b, &tmp_add, &tmp_addend, true) + } else { + mul_bp_tbl_add(&tmp, GE_BASEPOINT_TABLE, lo_b, &tmp_add, &tmp_bp_addend, true) + } } ge_set(ge, &tmp) } -@(private) -_ge_scalarmult :: proc "contextless" ( +ge_scalarmult_raw :: proc "contextless" ( ge, p: ^Group_Element, sc: ^field.Non_Montgomery_Domain_Field_Element, unsafe_is_vartime := false, @@ -227,9 +133,9 @@ _ge_scalarmult :: proc "contextless" ( if !unsafe_is_vartime { ge_clear(&tmp) - mem.zero_explicit(&tmp_add, size_of(Add_Scratch)) - mem.zero_explicit(&tmp_addend, size_of(Addend_Group_Element)) - mem.zero_explicit(&tmp_dbl, size_of(Double_Scratch)) + zero_explicit(&tmp_add, size_of(Add_Scratch)) + zero_explicit(&tmp_addend, size_of(Addend_Group_Element)) + zero_explicit(&tmp_dbl, size_of(Double_Scratch)) } } @@ -281,8 +187,8 @@ mul_tbl_add :: proc "contextless" ( {2, 0, 0, 0, 0}, // z * 2 } for i := u64(1); i < 16; i = i + 1 { - _, ctrl := bits.sub_u64(0, (i ~ idx), 0) - ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(~ctrl) & 1) + ctrl := subtle.eq(i, idx) + ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(ctrl)) } ge_add_addend(ge, ge, tmp_addend, tmp_add) } diff --git a/core/crypto/_edwards25519/edwards25519_scalar_mul_base.odin b/core/crypto/_edwards25519/edwards25519_scalar_mul_base.odin new file mode 100644 index 000000000..51305af2a --- /dev/null +++ b/core/crypto/_edwards25519/edwards25519_scalar_mul_base.odin @@ -0,0 +1,146 @@ +package _edwards25519 + +import "core:crypto" +import field "core:crypto/_fiat/field_curve25519" +import scalar "core:crypto/_fiat/field_scalar25519" +import subtle "core:crypto/_subtle" + +ge_scalarmult_basepoint :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) { + when crypto.COMPACT_IMPLS == true { + ge_scalarmult(ge, &GE_BASEPOINT, sc) + } else { + tmp_sc: scalar.Non_Montgomery_Domain_Field_Element + scalar.fe_from_montgomery(&tmp_sc, sc) + + tmp_add: Add_Scratch = --- + tmp_addend: Basepoint_Addend_Group_Element = --- + + ge_identity(ge) + for i in 0..<32 { + limb := i / 8 + shift := uint(i & 7) * 8 + limb_byte := tmp_sc[limb] >> shift + + hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f + mul_bp_tbl_add(ge, &Gen_Multiply_Table_edwards25519_lo[i], lo, &tmp_add, &tmp_addend, false) + mul_bp_tbl_add(ge, &Gen_Multiply_Table_edwards25519_hi[i], hi, &tmp_add, &tmp_addend, false) + } + + zero_explicit(&tmp_sc, size_of(tmp_sc)) + zero_explicit(&tmp_add, size_of(Add_Scratch)) + zero_explicit(&tmp_addend, size_of(Basepoint_Addend_Group_Element)) + } +} + +when crypto.COMPACT_IMPLS == false { + @(private="file",rodata) + TWO_TIMES_Z2 := field.Loose_Field_Element{2, 0, 0, 0, 0} + + @(private) + Basepoint_Addend_Group_Element :: struct { + y2_minus_x2: field.Loose_Field_Element, // t1 + y2_plus_x2: field.Loose_Field_Element, // t3 + k_times_t2: field.Tight_Field_Element, // t4 + } + + @(private) + Basepoint_Multiply_Table :: [15]Basepoint_Addend_Group_Element + + @(private) + ge_bp_addend_conditional_assign :: proc "contextless" (ge_a, a: ^Basepoint_Addend_Group_Element, ctrl: int) { + field.fe_cond_select(&ge_a.y2_minus_x2, &ge_a.y2_minus_x2, &a.y2_minus_x2, ctrl) + field.fe_cond_select(&ge_a.y2_plus_x2, &ge_a.y2_plus_x2, &a.y2_plus_x2, ctrl) + field.fe_cond_select(&ge_a.k_times_t2, &ge_a.k_times_t2, &a.k_times_t2, ctrl) + } + + @(private) + ge_add_bp_addend :: proc "contextless" ( + ge, a: ^Group_Element, + b: ^Basepoint_Addend_Group_Element, + scratch: ^Add_Scratch, + ) { + // https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3 + // Assumptions: k=2*d, z = 1 (precomputation ftw) + // + // t0 = Y1-X1 + // t1 = Y2-X2 + // A = t0*t1 + // t2 = Y1+X1 + // t3 = Y2+X2 + // B = t2*t3 + // t4 = k*T2 + // C = T1*t4 + // t5 = 2*Z2 + // D = Z1*t5 + // E = B-A + // F = D-C + // G = D+C + // H = B+A + // X3 = E*F + // Y3 = G*H + // T3 = E*H + // Z3 = F*G + // + // In order to make the scalar multiply faster, the addend is provided + // as a `Addend_Group_Element` with t1, t3, t4, and t5 precomputed, as + // it is trivially obvious that those are the only values used by the + // formula that are directly dependent on `b`, and are only dependent + // on `b` and constants. This saves 1 sub, 2 adds, and 1 multiply, + // each time the intermediate representation can be reused. + + A, B, C, D := &scratch.A, &scratch.B, &scratch.C, &scratch.D + E, F, G, H := &scratch.E, &scratch.F, &scratch.G, &scratch.H + t0, t2 := &scratch.t0, &scratch.t2 + + field.fe_sub(t0, &a.y, &a.x) + t1 := &b.y2_minus_x2 + field.fe_carry_mul(A, t0, t1) + field.fe_add(t2, &a.y, &a.x) + t3 := &b.y2_plus_x2 + field.fe_carry_mul(B, t2, t3) + t4 := &b.k_times_t2 + field.fe_carry_mul(C, field.fe_relax_cast(&a.t), field.fe_relax_cast(t4)) + field.fe_carry_mul(D, field.fe_relax_cast(&a.z), &TWO_TIMES_Z2) + field.fe_sub(E, B, A) + field.fe_sub(F, D, C) + field.fe_add(G, D, C) + field.fe_add(H, B, A) + field.fe_carry_mul(&ge.x, E, F) + field.fe_carry_mul(&ge.y, G, H) + field.fe_carry_mul(&ge.t, E, H) + field.fe_carry_mul(&ge.z, F, G) + } + + @(private) + mul_bp_tbl_add :: proc "contextless" ( + ge: ^Group_Element, + tbl: ^Basepoint_Multiply_Table, + idx: u64, + tmp_add: ^Add_Scratch, + tmp_addend: ^Basepoint_Addend_Group_Element, + unsafe_is_vartime: bool, + ) { + // Variable time lookup, with the addition omitted entirely if idx == 0. + if unsafe_is_vartime { + // Skip adding the point at infinity. + if idx != 0 { + ge_add_bp_addend(ge, ge, &tbl[idx-1], tmp_add) + } + return + } + + // Constant time lookup. + tmp_addend^ = { + // Point at infinity (0, 1, 1, 0) in precomputed form, note + // that the precomputed tables rescale so that `Z = 1`. + {1, 0, 0, 0, 0}, // y - x + {1, 0, 0, 0, 0}, // y + x + {0, 0, 0, 0, 0}, // t * 2d + } + for i := u64(1); i < 16; i = i + 1 { + ctrl := subtle.eq(i, idx) + ge_bp_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(ctrl)) + } + ge_add_bp_addend(ge, ge, tmp_addend, tmp_add) + } +} diff --git a/core/crypto/_edwards25519/edwards25519_table.odin b/core/crypto/_edwards25519/edwards25519_table.odin new file mode 100644 index 000000000..029b08418 --- /dev/null +++ b/core/crypto/_edwards25519/edwards25519_table.odin @@ -0,0 +1,4947 @@ +package _edwards25519 + +/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ + +import "core:crypto" + +when crypto.COMPACT_IMPLS == false { + @(private,rodata) + Gen_Multiply_Table_edwards25519_lo := [32]Basepoint_Multiply_Table { + { + { + {4566296876323096, 4708280988758944, 2883091957081722, 4842055411046963, 5717267076190079}, + {3540182452943730, 2497478415033846, 2521227595762870, 1462984067271729, 2389212253076811}, + {301289933810280, 1259582250014073, 1422107436869536, 796239922652654, 1953934009299142}, + }, + { + {4966907458672021, 4936584233144657, 6114240989277698, 5254498676225494, 4146642117106832}, + {3632771708514775, 790832306631235, 2067202295274102, 1995808275510000, 1566530869037010}, + {748439484463711, 1033211726465151, 1396005112841647, 1611506220286469, 1972177495910992}, + }, + { + {4820158664987218, 4429624038632138, 3711242400124238, 3713328211397903, 3003390509798844}, + {1601611775252272, 1720807796594148, 1132070835939856, 3512254832574799, 2147779492816910}, + {1850748884277385, 1200145853858453, 1068094770532492, 672251375690438, 1586055907191707}, + }, + { + {3946190272469145, 6239505675006654, 5208669189437987, 5151632689063553, 5199813637784664}, + {934282339813791, 1846903124198670, 1172395437954843, 1007037127761661, 1830588347719256}, + {1121406372216585, 192876649532226, 190294192191717, 1994165897297032, 2245000007398739}, + }, + { + {4928851390486164, 2860263086157808, 4946162173083730, 5341365721927258, 4878154719998387}, + {769950342298400, 2384754244604994, 3095885746880802, 3225892188161580, 2977876099231263}, + {1086255230780037, 274979815921559, 1960002765731872, 929474102396301, 1190409889297339}, + }, + { + {4510980453010577, 4649810060060977, 4808503203819400, 5702468951241614, 3249489646904341}, + {1388594989461809, 316767091099457, 2646098655878230, 1230079486801004, 1440737038838979}, + {1181317918772081, 114573476638901, 262805072233344, 265712217171332, 294181933805782}, + }, + { + {4271167442657675, 2928511714391884, 4614310625181828, 3360446656227271, 5021391587042608}, + {2916800678241215, 2065379846933858, 2622030924071124, 2602788184473875, 1233371373142984}, + {965130719900578, 247011430587952, 526356006571389, 91986625355052, 2157223321444601}, + }, + { + {4325401225737414, 4534620752133203, 4768100597167576, 4751634318022197, 3282052041613534}, + {4320419353804412, 4218074731744053, 957728544705548, 729906502578991, 2411634706750414}, + {551790716293402, 1989538725166328, 801169423371717, 2052451893578887, 678432056995012}, + }, + { + {6229274597883966, 4185445767544427, 3794144352961029, 6271388400944242, 5801047593299399}, + {1802695059464988, 1664899123557221, 2845359304426105, 2160434469266658, 3179370264440279}, + {1381809363726107, 1430341051343062, 2061843536018959, 1551778050872521, 2036394857967624}, + }, + { + {3190293695332791, 4165728475672253, 4346255112396895, 3238346181288697, 4562115113555210}, + {1569908045411451, 706723917266915, 1500941167088851, 2522858060362189, 3442327746686552}, + {1454533688490200, 416156769327623, 1344514353803379, 1816391251363763, 259908591619060}, + }, + { + {4322190032257826, 3710718875543082, 5127771470387916, 5558932420078259, 4937587148103002}, + {4222693909998302, 2779866139518454, 1619374932191226, 2207306624415883, 1169170329061080}, + {893653801273833, 1168026499324677, 1242553501121234, 1306366254304474, 1086752658510815}, + }, + { + {4366666225767590, 5094682881462444, 5444160766003964, 2663859630225193, 4386427788371457}, + {1548398643541286, 3090755542662214, 2368065889335542, 1878116023572279, 2384475613352909}, + {1571032457823571, 1253760059932116, 665829584253800, 109400965270906, 981221002823741}, + }, + { + {6475278226276205, 4841626135259659, 5265997707342765, 5158696113477971, 4545898660066816}, + {2465253816303469, 3191571337672685, 1159882208056013, 2569188183312765, 621213314200686}, + {177130678690680, 1754759263300204, 1864311296286618, 1180675631479880, 1292726903152791}, + }, + { + {3248252964508250, 5061531253750778, 5542769770211014, 4619085244233909, 5311803534193606}, + {2375959787421170, 2263885670311134, 2822409136676350, 3122669455540755, 1947192330052816}, + {498660636760962, 1605652986893012, 893278769679967, 1769999239723039, 646478004325289}, + }, + { + {5574001150447352, 3524291821486207, 4161953422248557, 4327379335382018, 3442969602526468}, + {1913163449625248, 2712579013977241, 2193883288642313, 1008900146920800, 1721983679009502}, + {692896803108118, 500174642072499, 2068223309439677, 1162190621851337, 1426986007309901}, + }, + }, + { + { + {5457238221803851, 3344133750480297, 5923374394087185, 3057477798065323, 3111028807187760}, + {1368953770187805, 3042147450398169, 2689308289352409, 2142576377050579, 1932081720066286}, + {1200766035879111, 20142053207432, 1465634435977050, 1645256912097844, 295121984874596}, + }, + { + {5563698449899448, 3838625675758736, 4715900944610621, 4227102525088801, 5170323687134830}, + {1735718747031538, 1248237894295956, 1204753118328107, 976066523550493, 2317743583219840}, + {1091990273418756, 1572899409348578, 80968014455247, 306009358661350, 1520450739132526}, + }, + { + {4403130087311393, 3013844998431429, 3939874146236762, 3074845922691006, 3159402582764738}, + {3732317023121341, 1511153322193951, 3496143672676420, 2556587964178488, 2620936670181690}, + {2047386910586836, 168470092900250, 1552838872594810, 340951180073789, 360819374702533}, + }, + { + {5483833971283375, 6215856366616550, 5092534899560758, 4707898440462492, 3093598134728534}, + {1982622644432037, 2014393600336956, 2380709022489462, 3869592437614438, 2357094095599062}, + {197561292938973, 454817274782871, 1963754960082318, 2113372252160468, 971377527342673}, + }, + { + {5235862574050758, 3926212577912309, 4434256219348056, 5854494381844745, 2810258686980493}, + {2416499262514576, 2254927265442919, 3451304785234000, 1766155447043651, 1899238924683527}, + {2103305098582922, 1960809151316468, 715134605001343, 1454892949167181, 40827143824949}, + }, + { + {4483855840793217, 3239143728269862, 4367394306679708, 4071397886477406, 3371105467700097}, + {1239289043050193, 1744654158124578, 758702410031698, 4048562808759936, 2253402870349013}, + {320153677847348, 939613871605645, 641883205761567, 1930009789398224, 329165806634126}, + }, + { + {4780421392687930, 3788635404873276, 3557012555097608, 4565073531580670, 4303176850668304}, + {3232730304159378, 1242488692177892, 1251446316964684, 1086618677993530, 1961430968465772}, + {833449923882501, 1750270368490475, 1123347002068295, 185477424765687, 278090826653186}, + }, + { + {3756645926444593, 3454896102689928, 5065739048841913, 4777932644822338, 3536143867460687}, + {794524995833413, 1849907304548286, 2305148486158393, 1272368559505216, 1147304168324779}, + {483048732424432, 2116063063343382, 30120189902313, 292451576741007, 1156379271702225}, + }, + { + {5884070579505425, 5535277330947453, 5603542025663670, 4776593639127153, 4995715838681551}, + {2505290486961759, 2288457607049763, 1322694247668132, 2996684795874985, 1441775943403867}, + {1862130357601747, 1576563056403606, 1053598539514442, 836379099899856, 1745075449649052}, + }, + { + {4271432792719273, 4354519732898601, 3841949260311002, 4278872468826501, 3182588946344969}, + {994086190120795, 2265566763472579, 1778668799717474, 1759565368702851, 1705243805775865}, + {208457126969992, 1306788169067141, 1504881061177412, 778305094530678, 286650467791603}, + }, + { + {3704308183084302, 4667642921024280, 3735446294701327, 4710970560312866, 5219863835152358}, + {1155946475009464, 1378854908418478, 3050476655608427, 738141412602796, 1805371589338096}, + {1627667107954997, 2038498693464737, 380348381597727, 693747096546728, 1241364634477378}, + }, + { + {4610118268113321, 3236474426265456, 4804410568671572, 4099577866548348, 3504102383946080}, + {748123900738723, 2239140288387656, 322477057520882, 2644973441419796, 1290933190145308}, + {2218076336525385, 339947754397137, 1735892619490, 1441988709036711, 932991353908008}, + }, + { + {5176295056640358, 3403895808063209, 3860193783232080, 4018349594328251, 4528337169205809}, + {2638983432827646, 2268258692789757, 3287339174338050, 1299412654822337, 936917254750873}, + {430804656367208, 1812394904738259, 550528638373630, 2103769550939254, 443986453677108}, + }, + { + {4019814909194368, 2925457503142305, 3944973873459804, 4250278944002558, 4031746156495663}, + {3925945607985574, 2164215477088927, 2286513560718006, 3385980103702156, 1734257170111047}, + {38890723392351, 853701573154564, 966467672212375, 417321296433946, 554926061377915}, + }, + { + {5000002949084352, 4896484517581292, 5148976024567894, 4815058842461170, 4176010608048328}, + {1720782684885150, 798987029915204, 1610161967147136, 3970529737234552, 936254274515738}, + {562662523022136, 737396420860869, 1964828496205405, 271079414894445, 1393713695470127}, + }, + }, + { + { + {4641332589184683, 2958470737602587, 5890637714236266, 6469243441056846, 3636576929381593}, + {3180171966714267, 2147692869914563, 1455665844462196, 1986737809425946, 2437006863943337}, + {481144981981577, 2053319313589856, 2065402289827512, 617954271490316, 1106602634668125}, + }, + { + {5160989980743332, 3250299780570808, 5495492964276292, 5314069834477255, 2594939618294032}, + {2948097833334040, 3145099472726142, 1148636718636008, 2278533891034865, 2203955659340680}, + {791736669492960, 934767652997115, 824656780392914, 1759463253018643, 361530362383518}, + }, + { + {5791086827335700, 4467111755065554, 3804728204617233, 6168459157050691, 3376804788950489}, + {2022541353055578, 4346500076272714, 3802807888710933, 2494585331103411, 2947785218648809}, + {677434665154918, 989582503122485, 1817429540898386, 1052904935475344, 1143826298169798}, + }, + { + {3025160502526487, 6318980957908565, 4867373065037870, 5043229614440699, 3035080247933683}, + {2619066141993637, 2570231002607651, 2947429167440602, 2885885471266079, 2276381426249673}, + {180820816194166, 168937968377394, 748416242794470, 1227281252254508, 1567587861004268}, + }, + { + {4236540720225255, 5582763806770724, 3307821162947907, 3911758370168910, 3340328882710774}, + {2730575372268893, 2062896624554806, 2951191072970647, 2609899222113120, 1277310261461760}, + {580736401511151, 1842931091388998, 1177201471228238, 2075460256527244, 1301133425678027}, + }, + { + {3547095551954881, 3966542127392273, 5049182669833076, 6538011303633046, 3765047903698852}, + {1515728832059163, 1575261009617579, 1510246567196186, 2442877836294952, 2368461529974388}, + {230710545179830, 30821514358353, 760704303452229, 390668103790604, 573437871383156}, + }, + { + {4354054137171033, 3822632479902001, 4538296533915119, 4245013553492583, 4574238179641958}, + {3421179921230875, 2514967047430861, 4274701112739695, 3071700566936367, 4275698278559832}, + {894132856735058, 548675863558441, 845349339503395, 1942269668326667, 1615682209874691}, + }, + { + {5296988143897756, 3567256897335281, 4224086813027664, 4153625766737702, 4841869104592905}, + {3539470031223082, 1222355136884919, 1846481788678694, 1150426571265110, 1613523400722047}, + {550201530671806, 778605267108140, 2063911101902983, 115500557286349, 2041641272971022}, + }, + { + {2639140850252425, 3988225053741778, 4109492541046027, 4467731762307139, 4788525019017799}, + {1956266817271455, 2914237312642832, 2018010448016151, 4042065159660719, 3422400064417223}, + {1185820244523867, 953640094456191, 1426524678517613, 1191533398208458, 1993578549159852}, + }, + { + {4724762102005390, 3941768459309593, 3168985852401486, 5230753070525336, 5120855380354436}, + {2162922301975048, 2584871642802941, 2903836488265486, 2034914383000476, 1973107217149520}, + {1225503059018859, 1744932331605022, 393061606917651, 2045141059558447, 1187823695528756}, + }, + { + {3873867956612972, 5901886943623014, 4214442512189194, 3726570129804851, 4003114175771373}, + {2499971111138236, 1856344473990516, 2851460465748678, 1490509710033167, 3414551741933391}, + {1569106592395768, 1670704805332568, 2011861983976474, 822492307064908, 1138495702641636}, + }, + { + {4611233673112936, 4109919865110418, 3874636387071312, 4304609757893158, 4158539624577373}, + {3888656531434102, 3371559592472684, 2495053387333630, 3579436360572308, 1114431352259831}, + {2209993507106795, 1762615018349199, 1687296090930185, 9491601628221, 870532128794902}, + }, + { + {4833972836221169, 5399132877586271, 4606616407949355, 4080860583790927, 4239964386503137}, + {1305913677624121, 3558400184075999, 3275823038503467, 3454063433790229, 1309514508446881}, + {1566723549675548, 1397175496983691, 504231980459915, 306990234666329, 1744893526714441}, + }, + { + {4014795958128859, 5054570465100501, 3081378639295577, 5833550217358299, 3899560884622359}, + {972376391789061, 1850852472634117, 2719443704140285, 2186622623776515, 3209686661433313}, + {2171782442569495, 1594104418173184, 1848207566547320, 2195471209947031, 1091928745815642}, + }, + { + {4698583634348737, 4028817484747578, 3922491723357167, 4921897981297279, 5070174707952522}, + {3952749170677737, 509151538148928, 2600240333845125, 2270835069234179, 3790913978189516}, + {1587050028613976, 1757976429633698, 440367736554514, 102469500615778, 1293087093446941}, + }, + }, + { + { + {4765314848902696, 4047154143755239, 3748677840535530, 5003339347891547, 4892630780044264}, + {717255318455100, 519313764361315, 2080406977303708, 541981206705521, 774328150311600}, + {1997217696294013, 1717306351628065, 1684313917746180, 1644426076011410, 1857378133465451}, + }, + { + {4274106452868777, 5229895690942370, 4818944681819138, 3310533142834467, 5951800763431172}, + {3727234538477877, 2328731709971226, 3368528843456914, 2002544139318041, 2977347647489186}, + {1710065158525665, 1895094923036397, 123988286168546, 1145519900776355, 1607510767693874}, + }, + { + {6052094801116259, 4945910156597034, 3249872360685630, 5056653985755776, 5148423953746665}, + {2813405189107769, 1071733543815036, 2383296312486238, 1946868434569998, 3079937947649451}, + {1445526537029440, 2225519789662536, 914628859347385, 1064754194555068, 1660295614401091}, + }, + { + {5380526401591301, 2806418790173460, 3263856123526812, 3091761635239858, 3666299153992924}, + {3451490036797185, 2275827949507588, 2318438102929588, 2309425969971222, 2816893781664854}, + {703047626104145, 1266841406201770, 165556500219173, 486991595001879, 1011325891650656}, + }, + { + {4838486554794399, 4993110726592022, 4632760493337220, 3972608926828727, 2871500009334501}, + {1622861044480487, 1156394801573634, 4120932379100752, 2578903799462977, 2095342781472283}, + {1646545795166119, 1758370782583567, 714746174550637, 1472693650165135, 898994790308209}, + }, + { + {4062996033667232, 5572569452904097, 4793202602203933, 4240755857296838, 5367161970768862}, + {2585203586724508, 2547572356138185, 1693106465353609, 912330357530760, 2723035471635610}, + {906282429780072, 2108672665779781, 432396390473936, 150625823801893, 1708930497638539}, + }, + { + {3731585820952935, 6242481486437170, 4572245823847061, 4398306869785574, 5751262444905966}, + {925664675702309, 2273216662253932, 4083236455546587, 601157008940112, 2623617868729744}, + {52035296774456, 939969390708103, 312023458773250, 59873523517659, 1231345905848899}, + }, + { + {4632957969763174, 4184611431390023, 5680349018170176, 4901639977232284, 5674379295460919}, + {2895154920100990, 2541986621181021, 2013561737429022, 2571447883196794, 2645536492181409}, + {2051980782668029, 121859921510665, 2048329875753063, 1235229850149665, 519062146124755}, + }, + { + {4207228868621988, 4953881226819951, 4139842782246336, 4298958943276773, 3359727402165629}, + {947983997565204, 1512975730400883, 4017071259732234, 765863411195419, 2287620622340759}, + {2248717923990509, 953644234015146, 118881148429301, 1244045737066019, 519708790776758}, + }, + { + {5697680122778496, 6228365759267448, 4861216723530833, 4702869303488893, 5552489090348314}, + {1440754265571108, 2717772629254708, 2851948946836421, 3389483713931559, 1448786922664578}, + {843777949621211, 1435525643946674, 1087149831109219, 1794919173070415, 1112222323032617}, + }, + { + {5102037877608319, 4652686712219969, 3897951345871191, 3585818368367414, 5206224086433126}, + {1659077274827511, 3292962448731851, 3877468219103951, 1516723029470630, 2756801757695330}, + {1080269027468022, 217052522911549, 1656325362355128, 1627927536138189, 547476742306034}, + }, + { + {4629572650764889, 5482991583454262, 5026118951697692, 3386284302539994, 4183091862778757}, + {4049116095173975, 2853051218008192, 874408124299498, 2811479573934506, 3061819813989639}, + {1673853233469462, 2069508754540826, 444570721431342, 318669192295723, 1286647860911061}, + }, + { + {5230179910306733, 4570722910725029, 2679420725332655, 3219299251684998, 5101899978929471}, + {3368016050367733, 1864179846991811, 2025579249953153, 2185933453914170, 3081358815633795}, + {1120488984292940, 268864491510849, 230793761352121, 54153081190951, 1544798876643945}, + }, + { + {4594071143939477, 4032573207368795, 3586642054806445, 2633280388282362, 4204685405148786}, + {3215023450765629, 1989745848107067, 2317683847606295, 2073505048594828, 792770882411102}, + {213368529611304, 716996641453362, 1913278462832177, 1585475497182388, 563601091454134}, + }, + { + {2835663672936090, 4829603014808807, 3487022863582034, 2792788055117753, 4407939774570859}, + {1893732627269868, 2896260158734549, 1988156739597398, 2606708976150985, 1947694156880429}, + {1687313081048019, 7705508083870, 487993091259388, 560742684726806, 779697153923449}, + }, + }, + { + { + {4089455896800313, 6013733676182565, 5409863301562555, 4072864011490980, 5068974752046796}, + {3859970785658325, 2667608874045675, 1350468408164765, 2038620059057678, 3278704299674360}, + {578027192365650, 2034800251375322, 2128954087207123, 478816193810521, 2196171989962750}, + }, + { + {4965788985850512, 4036616547844474, 3863134115336615, 3555738077628787, 5211189187689919}, + {1633188840273120, 3104586986058956, 1548762607215795, 1266275218902681, 3359018017010381}, + {1038829280972848, 38176604650029, 753193246598573, 1136076426528122, 595709990562434}, + }, + { + {4508300680732578, 6151240693672842, 5551152629612579, 4175434827081223, 4710569942272560}, + {3660251634545082, 2194984964010832, 2198361797561729, 1061962440055713, 1645147963442934}, + {1750479161778571, 1362553355169293, 1891721260220598, 966109370862782, 1024913988299801}, + }, + { + {5140408161043668, 3514001525352806, 4894551007701094, 3915220506382540, 5065550949127901}, + {2464498862816952, 1117950018299774, 1873945661751056, 3655602735669306, 2382695896337945}, + {520731594438141, 1446301499955692, 273753264629267, 1565101517999256, 1019411827004672}, + }, + { + {3716451775537782, 3735537109406964, 3771250375020764, 3413229645449032, 4909514625550472}, + {3178327305714638, 3443653291096626, 734233225181170, 2435838701226518, 4042225960010590}, + {996126634382301, 796204125879525, 127517800546509, 344155944689303, 615279846169038}, + }, + { + {5126516964784293, 5722588804459529, 5788457340217086, 5474101689079853, 4854624835487584}, + {2990523894660505, 2188666632415295, 1961313708559162, 1506545807547587, 3403101452654988}, + {2067814584765580, 1677855129927492, 2086109782475197, 235286517313238, 1416314046739645}, + }, + { + {5182089550298661, 4268457398409278, 4594577010420123, 5530431534605076, 5118871120313016}, + {2838644076315587, 2559244195637442, 458399356043425, 2853867838192310, 3280348017100490}, + {301225714012278, 1094837270268560, 1202288391010439, 644352775178361, 1647055902137983}, + }, + { + {5639203700568665, 3935121894170720, 5272747431747178, 4338487944274660, 5404045310490874}, + {1210746697896459, 1416608304244708, 2938287290903104, 3496931005119382, 3303038150540984}, + {1971518477615628, 401909519527336, 448627091057375, 1409486868273821, 1214789035034363}, + }, + { + {5099963449143288, 5521329395009146, 5925708408867572, 4221709339736212, 4612387286592975}, + {1894554173291056, 3439387781984292, 2885767225889068, 620075308547710, 1923191105660691}, + {2193142205372254, 2249202758109308, 136771833945490, 2136446252990850, 1913453314551631}, + }, + { + {3519416739470062, 5800837512824035, 5629830750568439, 3858242948002290, 4384918516791051}, + {1031287572005306, 2743053635058531, 1307200063174499, 886968262945288, 322139622562321}, + {1603190765881197, 1131168289986667, 1851325240689452, 1811918922856612, 1688789764638099}, + }, + { + {5675121438563826, 3813646429348722, 6155915780969232, 4550135853787182, 3281226794470063}, + {1227916715088978, 3565721991039408, 2825753167382054, 446650609575830, 3201068492916497}, + {465975618381320, 1757724298980204, 2172737911773281, 1844204403201116, 367200393612929}, + }, + { + {4053304559591831, 4763567221009860, 6256382270106074, 5569940279565028, 4297628970970611}, + {522695684014153, 2454309386747442, 1812320598717590, 1790060723730286, 513480358702681}, + {1695032670616248, 1588968761785032, 699742416328216, 547685855993128, 1790235994988743}, + }, + { + {3776137870634381, 3800031162558423, 5542451196069607, 4330978223940644, 5450131593237007}, + {3411403847639229, 1506626399353463, 2324339461338721, 1195836709245006, 2829489236982793}, + {263703254267006, 1082588170565097, 2024394221181425, 46543794553459, 2110417854356146}, + }, + { + {5712489756196259, 4857601027744288, 4243491518458906, 4901936639181452, 4456074323550475}, + {2520601556174181, 1164555774547222, 2770926848501726, 3208860864993280, 497236288525621}, + {247502314830666, 1623351904090299, 1162047175878913, 1697644630093486, 776531516340321}, + }, + { + {2686302584388573, 3722578779150130, 6045187633044733, 3467509394641570, 3302975571798606}, + {2408284467064191, 2899235622132542, 2270755745458389, 1460665123127634, 2622446416668442}, + {625008843842459, 305089228555404, 1124988453243439, 123919845855976, 788637610781258}, + }, + }, + { + { + {3297030136943183, 5321806228516302, 2882313002761349, 3923846342683379, 5310803644932932}, + {1364039144731711, 1897497433586190, 2203097701135459, 2397261210496499, 1349844460790698}, + {439961968385997, 386362664488986, 1382706320807688, 309894000125359, 2207801346498567}, + }, + { + {4255565910583278, 4673673686605660, 3392924072653217, 3737219707166220, 3825562634713972}, + {3480804500082836, 3172443782216110, 2375775707596425, 2933223806901024, 1400559197080972}, + {729905708611432, 1270323270673202, 123353058984288, 426460209632942, 2195574535456672}, + }, + { + {4013408251151364, 5086960474897299, 3838506203370739, 4408856413264508, 3422492183371019}, + {1271140255321216, 2044363183174497, 2303925201319937, 3696920060379952, 3194341800024331}, + {871476219910823, 1878769545097794, 2241832391238412, 548957640601001, 690047440233174}, + }, + { + {3251428812313581, 5636436335863895, 4336541488202699, 4972942980386107, 5182382616078529}, + {2548994545820755, 1366347803776819, 3552985325930849, 561849853336293, 1533554921345731}, + {2189427607417022, 699801937082607, 412764402319267, 1478091893643349, 2244675696854460}, + }, + { + {5012160783311108, 5470528103057159, 4488517614835378, 2676343672262544, 4341072770671390}, + {3964091869651792, 2456213404310121, 3657538451018088, 2660781114515010, 3112882032961968}, + {221245220129925, 1156020201681217, 491145634799213, 542422431960839, 828100817819207}, + }, + { + {2810886626483710, 5076777331583206, 6133336711186896, 3651619527147841, 3898754191951285}, + {2405556784925632, 1299874139923976, 2644898978945750, 1058234455773021, 996989038681183}, + {1887963056288059, 228507035730124, 1468368348640282, 930557653420194, 613513962454686}, + }, + { + {5579887344422086, 5618055197913529, 4690896687085975, 4754046511662615, 4136987326235786}, + {1224529808187534, 1577022856702685, 2206946542980843, 625883007765001, 2531730607197406}, + {902497362940219, 76749815795675, 1657927525633846, 1420238379745202, 1340321636548352}, + }, + { + {5132340287409247, 4194838312213087, 4971385975164381, 5596941055673869, 4739013486883497}, + {1129576631190765, 3533793823712575, 996844254743017, 2509676177174497, 3402650555740265}, + {237425418909360, 469614029179605, 1512389769174935, 1241726368345357, 441602891065214}, + }, + { + {5266234055777943, 3166499093963215, 4159587332862448, 3232787848503690, 6261694765772425}, + {2508069708566903, 2982887287210837, 1712829089863354, 1739545432690564, 1853100260794477}, + {4642168584761, 1314096799362798, 1620739012635580, 444075187404753, 76135520441225}, + }, + { + {5167832514805982, 5410004641404511, 3809624149844670, 4773980049888932, 3778278866830004}, + {1717340294466846, 3145810307460687, 1904170181110298, 3950114374260626, 2248427553137502}, + {1356583144121446, 1439603152129038, 880464721166116, 426511648446184, 1044401386572766}, + }, + { + {3827273464157640, 5470853620720833, 4235776821907793, 5432246822532161, 4674460658804935}, + {3682691082267936, 1935676112917301, 3170276622979891, 2876033130676637, 1596266630249199}, + {1484505136430423, 343818915658679, 1066931341976591, 1574952097402529, 895157643469052}, + }, + { + {6636210482709397, 2566644085561849, 4278449441656290, 5708653335234549, 6540605640281063}, + {2193735258244385, 2265742668153213, 2801601661178220, 1573679250261669, 2218164822512395}, + {125908919015544, 908539856510216, 254196493329521, 1841783557943867, 1826956209112337}, + }, + { + {4015848574593688, 5374261932338028, 4759505940569418, 5686761164384680, 3410517186063399}, + {1218465765165754, 1222399589933778, 4149598104194804, 2307999947285970, 2530437726498307}, + {1352017428769842, 1226345478088737, 1834808987089176, 171935268241134, 1252599135760918}, + }, + { + {4391913968320982, 5643346087738336, 3260878495624279, 6345563729780486, 6485738780527396}, + {269241043449612, 1713401415896622, 3060740655644691, 2228155591500882, 2273523243235430}, + {994025955714788, 1395495501299355, 1717525291885154, 64780760930213, 1492125616744822}, + }, + { + {4496571738540020, 6137682561017990, 4165346179942417, 4589212756752962, 5249152453870163}, + {2859457773452122, 2592803086422694, 761249806099561, 4355723617152898, 2688955778843975}, + {686675614020084, 1129369471718576, 1361332769753183, 814390480194826, 1958437091006724}, + }, + }, + { + { + {4212554477605918, 5000640585259457, 4161632664968341, 3523231950682073, 4471580181706187}, + {3988217766743784, 726531315520507, 1833335034432527, 1629442561574747, 2876218732971333}, + {1537037379417136, 1358865369268262, 2130838645654099, 828733687040705, 1999987652890901}, + }, + { + {4063362146350583, 3753681832692920, 4465563314774246, 4863172707090131, 4539970192419610}, + {629042105241795, 1098854999137608, 887281544569320, 3674901833560025, 2259711072636808}, + {218907117361280, 1209298913016966, 1944312619096112, 1130690631451061, 1342327389191701}, + }, + { + {4482501699248035, 5851772807709469, 4424655942309844, 5930138373494266, 4947793108696645}, + {1369976867854685, 1396479602419169, 4017456468084104, 2203659200586298, 3250127649802489}, + {784210426627951, 918204562375674, 1284546780452985, 1324534636134684, 1872449409642708}, + }, + { + {4153660020381144, 4256288935750983, 3877646875253483, 3225329557085126, 4327087498998152}, + {2571438643225542, 2848082470493653, 2037902696412607, 1557219121643918, 341938082688094}, + {1371853944110545, 1042332820512553, 1949855697918254, 1791195775521505, 37487364849293}, + }, + { + {4334516943269102, 4531429052909917, 4649254694042464, 3942327023530758, 6368860137043973}, + {687200189577836, 1082536651125675, 2896024754556794, 2592723009743198, 2595381160432643}, + {1059729620568824, 2163709103470266, 1440302280256872, 1769143160546397, 869830310425069}, + }, + { + {4276621734726805, 4930548302820644, 2846933097770719, 4975460488256465, 2852121493098246}, + {3861316033464273, 777277757338816, 2101121130363987, 550762194946473, 1905542338659364}, + {598474602406721, 1468128276358244, 1191923149557635, 1501376424093216, 1281662691293476}, + }, + { + {2971320059272372, 4896980339002840, 4635950028233875, 3795071084495975, 4071343109483907}, + {1721138489890688, 1264336102277790, 2684864359106535, 1359988423149465, 3813671107094695}, + {396397949784152, 1811354474471839, 1362679985304303, 2117033964846756, 498041172552279}, + }, + { + {5154223559778472, 3389351102095821, 4377023217300786, 3977457826906518, 4386692778803043}, + {1812471844975748, 1856491995543149, 126579494584102, 3288044672967868, 1975108050082549}, + {522584000310195, 1241762481390450, 1743702789495384, 2227404127826575, 1686746002148897}, + }, + { + {4080889153606423, 5116319911316914, 4006591728131774, 4350736921528591, 4198995697088691}, + {3932341308304797, 1612580099028530, 2937385230920440, 1836672506516533, 517164940700103}, + {1413348606155183, 810499206093511, 1138057743946731, 1556315649471799, 993617155135620}, + }, + { + {5656453792030509, 6079591987914126, 5929179648294721, 5230798899043491, 3370342887971873}, + {2735841961308013, 2116601197688202, 2652241807415589, 1945152844924315, 2885012584681659}, + {551620533268687, 1182887684657061, 1043366705332762, 944140538303658, 2240921917214007}, + }, + { + {2427888929082724, 4467682652740956, 5335339067201761, 5550886290485514, 5050956980777821}, + {2247945978763224, 215736457901546, 1047424049356243, 1389596126698944, 816935367913617}, + {1146743855918524, 1418503734887175, 843342293437400, 1502230097098390, 1240491010654824}, + }, + { + {6701933119211633, 5059229274152685, 4982837924778640, 4159052306481152, 4290369756778959}, + {2204538589507457, 3142843240983995, 2451576614290660, 3204217003708084, 2887474477188681}, + {510455031824465, 465163402943305, 2022658124081289, 1881132727821470, 31746160856543}, + }, + { + {5097091659825113, 2826376647382075, 3998920599703675, 3513481695405562, 5076475699131519}, + {1330330618013145, 2313004235002329, 3963525218487729, 2303930585911304, 2755772190474933}, + {944243695677568, 255912283647788, 1855489019383837, 1244636060478392, 1911682985774639}, + }, + { + {5024454158738700, 2514912085825565, 3852574473189297, 4034915921452192, 3904120669219782}, + {3843903221055742, 2416642267747155, 1715729591405051, 1735036083660438, 1182009761997504}, + {1140604273028187, 1352033415206334, 1448886815181311, 941652546197192, 1001542060535421}, + }, + { + {4277058348919964, 5364603224614130, 5366326037527057, 4814184001945705, 5895346951506596}, + {3602696745610322, 2198425366751348, 1768623515003979, 2456584282641319, 3022619356175890}, + {1305849451281975, 726672899606505, 2105928429843370, 246834240873219, 1573506984361288}, + }, + }, + { + { + {4821701574825479, 4751738035366345, 3733704008989173, 4812878081681692, 3510316573903125}, + {427904865186293, 1703211129693455, 1585368107547509, 3688784302429584, 3012988348299225}, + {1275068538599310, 513726919533379, 349926553492294, 688428871968420, 1702400196000666}, + }, + { + {3810616250567627, 4214696146321770, 5841309449432647, 3753213644462184, 4798035793202427}, + {3313663849950481, 3213411074010628, 2573659446386085, 3297400443644764, 1985130202504037}, + {818359826554971, 1862173000996177, 626821592884859, 573655738872376, 1749691246745455}, + }, + { + {4398313517418541, 5088388527765162, 4968565284650452, 4435773453041373, 4741970786827285}, + {1988022651432119, 3333911312271288, 1834020786104820, 3706626690108935, 692929915223121}, + {1129007025494441, 2197883144413266, 265142755578169, 971864464758890, 1983715884903702}, + }, + { + {4948148597287912, 3704086267538602, 4365531255192057, 2896988087581106, 5313917252680007}, + {1291366624493056, 2633256531874362, 1711482489312443, 1815233647702022, 3144079596677715}, + {2242724082797924, 1373354730327868, 1006520110883049, 2147330369940688, 1151816104883620}, + }, + { + {4667323107306775, 4619024517173644, 3407816205266473, 6398541848123859, 4222349233671575}, + {3997520014069025, 4163522956860564, 2056329390702073, 2607026987995097, 3131032608056347}, + {681981452362484, 267208874112496, 1374683991933094, 638600984916117, 646178654558546}, + }, + { + {2512483707152304, 5357659933447732, 5417239179350606, 4508304204210617, 2532054624493958}, + {2265178468539480, 2358037120714814, 1944412051589650, 4093776581610705, 2482502633520820}, + {715374893080287, 1173334812210491, 1806524662079626, 1894596008000979, 398905715033393}, + }, + { + {4348221360643351, 4174322814635610, 5293430650247335, 4930894772059273, 4824523600532224}, + {2751826223412909, 3848231101880618, 1420380351989369, 3237011375206737, 392444930785632}, + {1927770723575450, 1485792977512719, 1850996108474547, 551696031508956, 2126047405475647}, + }, + { + {2635705015322199, 3111746811317117, 5359223495008139, 3268925594263041, 3046050645563056}, + {2112099158080129, 2994370617594963, 2258284371762679, 1951119898618915, 2344890196388664}, + {77571826285752, 999304298101753, 487841111777762, 1038031143212339, 339066367948762}, + }, + { + {5619164208408509, 4079972709845361, 3927824185200012, 3681293890692042, 5452751544406703}, + {2191882696778049, 531264700870777, 3039670365049278, 1359665656266722, 3162072763716517}, + {1570940255668145, 688547574737286, 1632136413236589, 2053774689811525, 676669102580803}, + }, + { + {5183231995448322, 4155796849234556, 4791323788081582, 4471675968988079, 5711715782924180}, + {3207409007530338, 935702897763596, 729948770061474, 1584905172662705, 2425339805308626}, + {288239669792058, 2152796035840109, 162317061559789, 1257054119617939, 421141027109762}, + }, + { + {4958697699223355, 3221953471379609, 2818398572467973, 5875894486831009, 3850357049774603}, + {642422906756119, 3171839279489789, 1695193497886789, 3040583315302385, 3362141503479163}, + {1042979452017909, 1774768735282920, 464726722030945, 1465185933073826, 1382968477576580}, + }, + { + {3858506126065685, 4410239993278318, 3464562222229353, 3841799127123745, 3236074797259687}, + {3342987691574741, 2002872538662690, 3240810091817983, 3479310152893167, 2490884376592639}, + {2139337814897324, 178720275772072, 596052025976159, 666224594355251, 630639510547398}, + }, + { + {2744437082123657, 4441348097375482, 3869182720347428, 4304304367735980, 3086995265547722}, + {2392789380667179, 812658446707360, 1599624958311986, 214741817968452, 1436587626236000}, + {130387450082061, 1779587373012878, 417414670169839, 716150862374041, 154849814949784}, + }, + { + {4442837550688441, 4997631045842130, 5291735080737359, 4549950120656089, 4456650325708853}, + {2746366883922045, 2305345226446032, 2885706560860073, 4092938150156125, 656228807731693}, + {1456049106825164, 137394514200521, 2140871605490631, 1643256698410764, 679389221519059}, + }, + { + {3925184987729414, 3825370065750239, 2928329430708313, 5366989011209685, 4444246216420488}, + {2346187442256272, 1014027377437197, 2069628555505675, 1559427210701775, 1456229816012936}, + {2009324336353948, 1468073297564484, 1969534512584396, 827056802549955, 104599952309039}, + }, + }, + { + { + {5505012288893163, 2599996010752544, 3918414180409193, 3140224808718007, 2832547501486604}, + {2926794589205781, 2517835660016036, 826951213393477, 1405007746162285, 1781791018620876}, + {1939560076207777, 1409892634407635, 552574736069277, 383854338280405, 190706709864139}, + }, + { + {5180561690600497, 4132075350834054, 4298520825287953, 5392062874453498, 5821901179394561}, + {2177087163428741, 1439255351721944, 3459870654068041, 2230616362004768, 1396886392021913}, + {1466980508178206, 617045217998949, 652303580573628, 757303753529064, 207583137376902}, + }, + { + {4105782219090338, 4130463869936394, 6031610648174487, 5523226095524059, 5632038039559529}, + {3762856566592150, 2357202940576524, 2745234706458093, 1091943425335975, 1802717338077427}, + {1963939888391106, 293456433791664, 697897559513649, 985882796904380, 796244541237972}, + }, + { + {3680158110175880, 5530714909790973, 4808440325428831, 4945009801397122, 4071158169963819}, + {2668570812315008, 2641455366112301, 1314476859406755, 1749382513022778, 3413705412424739}, + {204943430200135, 1554861433819175, 216426658514651, 264149070665950, 2047097371738319}, + }, + { + {5165635210954903, 4790335732463592, 5635372627881110, 5322093841581933, 4976543419424973}, + {1934415182909015, 1393285083565062, 2768209145458208, 3409490548679139, 2372839480279515}, + {665784778135882, 1893179629898606, 808313193813106, 276797254706413, 1563426179676396}, + }, + { + {4283233217201481, 4707596242598657, 4674086796207577, 5485113232161884, 3095373778602077}, + {945205108984213, 2778077376644543, 1324180513733565, 1666970227868664, 2405347422974421}, + {1476570093962618, 838514669399805, 1857930577281364, 2017007352225784, 317085545220047}, + }, + { + {3545343323078703, 4395424422887793, 5561961194168003, 4717696754764488, 3198688329157975}, + {1461557121912823, 1600674043318359, 2157134900399597, 1670641601940616, 2379565397488531}, + {357067959932916, 1290876214345711, 521245575443703, 1494975468601005, 800942377643885}, + }, + { + {5120856274973686, 3903907574784685, 4109012860330718, 3337396988900217, 3069232573515769}, + {2817916472785262, 820247422481739, 994464017954148, 2578957425371613, 2344391131796991}, + {771808161440705, 1323510426395069, 680497615846440, 851580615547985, 1320806384849017}, + }, + { + {6662756671601401, 5055771079546289, 4642910898897859, 4274227027260534, 5833718441044794}, + {2335519494956627, 3820365010713627, 1944201046475949, 1640913863967574, 2358631279976586}, + {990528501134234, 1330224017810407, 1573804236508381, 942270438439677, 25201841708767}, + }, + { + {5526427987749634, 4518401023168866, 4921120012283882, 4779318497665973, 4555652731610533}, + {2646721458762538, 1247587116821480, 2586827199616378, 3932021497491885, 969339720975687}, + {1595456591254808, 1919330451560855, 265402806641622, 1560117962587834, 1169927205192232}, + }, + { + {4189409997656536, 4659089518495636, 6000827340603279, 5702161301408170, 5941261317517041}, + {3317917962903276, 1668664191271588, 1899844145838597, 1696011444672828, 2282054748309227}, + {2126527989994119, 1465890683922518, 416427350021352, 1618807264846944, 1588324622180673}, + }, + { + {4009588676432813, 4225252562340771, 5138392626199289, 6147384375179966, 4323738229760897}, + {2550824143198317, 3724772924079255, 2640826097206085, 2805004284285778, 3725892598967957}, + {901870527597111, 1300831444709451, 1795706127510368, 1590464383227069, 60287918150860}, + }, + { + {4260735023331218, 2752239523202930, 4432983289513289, 6073621772440017, 5069964246448815}, + {2411640257311042, 2404639281373100, 935718519552991, 2182928933394409, 3181304181386605}, + {301088722784222, 902977224984285, 1485824849826196, 864674789855395, 2204280040105719}, + }, + { + {5294452585150653, 4378774784126084, 2684611835446325, 6054460125397337, 3113938028918105}, + {1102630701890799, 2202327440719776, 1844385418066207, 1719220574774295, 3022438833862057}, + {1192644591215061, 1951970263153038, 182489349589207, 1072483329544407, 1425993434915257}, + }, + { + {3759682407110969, 4757463391782573, 6126440026160055, 4699689556446215, 5715476431941391}, + {2696424379059465, 2927324693839557, 2595575928464217, 3964369572567959, 2720628440266425}, + {786193544150213, 816842401151828, 2071842707112420, 581055055128968, 310970557266803}, + }, + }, + { + { + {3579768107573076, 3587300666628503, 3653386978219511, 5061736939322935, 6054960176639396}, + {1219260086131896, 2898968820282063, 2331400938444953, 2161724213426747, 2656661710745446}, + {417621685193956, 1429953819744454, 396157358457099, 1940470778873255, 214000046234152}, + }, + { + {3878872728667188, 4463402894965320, 4164169415301751, 3443570249906556, 4439109571211107}, + {1268047918491954, 2172375426948536, 1533916099229249, 1761293575457130, 3842422480712013}, + {1149147819689533, 378692712667677, 828475842424202, 2218619146419342, 70688125792186}, + }, + { + {4292523638342576, 4903155265245570, 5136143002823489, 3124449750693297, 5738994354400728}, + {3551539230764990, 3690416477138006, 3788528892189659, 2053896748919837, 3260220846276494}, + {2211311599327900, 2139787259888175, 938706616835350, 12609661139114, 2081897930719789}, + }, + { + {4097322728303089, 5725797875706037, 4654440700130628, 4178828883626228, 5693513031868506}, + {1324994503390431, 2588782144267879, 1183998925654176, 3343454479598522, 2300527487656566}, + {1079559557592645, 2215338383666441, 1903569501302605, 49033973033940, 305703433934152}, + }, + { + {3683815626821508, 4943964422665864, 3647446876506747, 4228674336449825, 5438052000093847}, + {2346453219102138, 3637921163538246, 3313930291577009, 2288353761164521, 3085469462634093}, + {1296625309219774, 2068273464883862, 1858621048097805, 1492281814208508, 2235868981918946}, + }, + { + {3534262737397977, 5245485311356750, 4279554456512807, 2770789343226274, 4078409823241192}, + {1490330266465551, 1858795661361448, 3688040948655011, 2546373032584894, 3459939824714180}, + {1525827120027511, 723686461809551, 1597702369236987, 244802101764964, 1502833890372311}, + }, + { + {6545268376680796, 4436205135889147, 3885200451296283, 4362482319222146, 6551744017455139}, + {2365421849929742, 3485539881431101, 2925909765963743, 2114345180342964, 2418564326541511}, + {503058759232932, 760293024620937, 2027152777219493, 666858468148475, 1539184379870952}, + }, + { + {2929839349119735, 5074186917559835, 3857102490299366, 4399562376560948, 3957863610776951}, + {1916168475367211, 3167426246226591, 883217071712574, 363427871374304, 1976029821251593}, + {1439489648586438, 2194580753290951, 832380563557396, 561521973970522, 584497280718389}, + }, + { + {4107979200870526, 4899400547785857, 5175087145170849, 5761419237914916, 2674185367684618}, + {1133946710417756, 499737269360777, 1645961935513831, 2259932248870354, 2394185034627430}, + {2211650710341615, 1916525167795392, 2219254718801699, 1123275886572725, 2065912631812720}, + }, + { + {2942743383283030, 4661681143781323, 4853180648224206, 3984362536169634, 3769046963947699}, + {2547466619616960, 1599890997313053, 1767449403100900, 3146589914609346, 2442645855602917}, + {1023269497317835, 1006858415503750, 2159836138753919, 1535892167365222, 826474553854585}, + }, + { + {4044410514205452, 4788613576788997, 4922881390894542, 4505428839963076, 3254381502973105}, + {2881011303685958, 323260022642283, 2392511825935364, 2680218607241472, 2086628284323147}, + {1011041096783712, 1570461284958064, 399516828994561, 1037957371973381, 293292885426852}, + }, + { + {3922699440356983, 4166667378343946, 4637678914861614, 4901406304713256, 5486018227566634}, + {3894750463833161, 836931108663410, 4007195920412586, 1173057924841174, 2662523305285872}, + {2047497366930440, 1249020434696646, 353399299276962, 1824831452522161, 1950016482901783}, + }, + { + {6367491312268994, 5392176809230541, 4683379383522741, 4425977262002237, 5566950871345983}, + {2375227161224824, 2257267128164595, 1056955680380401, 2844088942852363, 1386644755985081}, + {1251794829999036, 1772886866476173, 955066187540246, 1232293719330892, 396636503102089}, + }, + { + {5348918388440793, 5110360065015040, 4585673363095533, 4391593798666572, 4556880644633940}, + {2531431177429893, 1987695830473810, 227622233346307, 1010967397553478, 1341018389661594}, + {83039271672929, 423138535583767, 1183109031328467, 165324254826210, 1340545562288681}, + }, + { + {4651180052187971, 4721139042433965, 4397263424421690, 3818446426246947, 4163799598655846}, + {1971810452973589, 1766684231420693, 299216980507446, 1405770006429853, 3505404036582454}, + {814876839307346, 1973981610718707, 715190907115349, 1240128743335375, 100752655285750}, + }, + }, + { + { + {5917065716904928, 4914443718136124, 5900862973774566, 4911826770493904, 3846361616833057}, + {2439789269177838, 681223515948274, 1933493571072456, 1872921007304880, 2739962177820919}, + {2102170800973153, 719462588665004, 1479649438510153, 1097529543970028, 1302363283777685}, + }, + { + {5650165172926835, 3913771113130458, 4910281332119388, 5068052063776583, 5612709493199633}, + {3193865531532443, 3321113493038208, 2007341951411050, 2322773230131539, 1419433790163705}, + {2214421081775077, 1165671861210569, 1890453018796184, 3556249878661, 442116172656317}, + }, + { + {5118771546583273, 6027449032225062, 3106360274232749, 4318897183975962, 4017125662271289}, + {3005630360306059, 1666955059895018, 1530775289309243, 3371786842789394, 2164156153857579}, + {1094538949313667, 1796592198908825, 870221004284388, 2025558921863561, 1699010892802384}, + }, + { + {3266123011223623, 3120950453625853, 6259609570067094, 3586752371060918, 6048545006453369}, + {1951351290725195, 1916457206844795, 2449824998123274, 1909076887557594, 1938542290318919}, + {764055910920305, 1603590757375439, 146805246592357, 1843313433854297, 954279890114939}, + }, + { + {4578096739917745, 5243693780562643, 3997054445402827, 5231313513873625, 3534834178102174}, + {80113526615731, 764536758732259, 3306939158785481, 2721052465444637, 2869697326116762}, + {525892105991110, 1723776830270342, 1476444848991936, 573789489857760, 133864092632978}, + }, + { + {4567722854714830, 3491727534333040, 3612522797131151, 4726210441025156, 4566029114558485}, + {2794411533877810, 1986812262899320, 1162535242465837, 2733298779828712, 2796400347268869}, + {1793193323953132, 91096687857833, 70945970938921, 2158587638946380, 1537042406482111}, + }, + { + {4644957907857340, 4595035516942998, 5590808199923137, 4081399466208167, 3445106834328894}, + {1895854577604590, 3646695522634664, 1728548428495943, 3392664713925397, 2815445147288308}, + {1611230858525381, 950720175540785, 499589887488610, 2001656988495019, 88977313255908}, + }, + { + {5377566504324214, 5594237977720934, 3960359138874383, 2924144408487157, 5824037597070734}, + {3440880315164906, 2184348804772596, 3292618539427567, 2018318290311833, 1712060030915354}, + {1508590048271766, 1131769479776094, 101550868699323, 428297785557897, 561791648661744}, + }, + { + {4856954879111275, 4243615896786977, 5034997993102829, 5162125577354786, 4490078142041683}, + {432920540217177, 290770592514699, 627484756484379, 3076610223383366, 982836063036305}, + {1857779135539838, 1774848070278290, 1383862392183037, 1948805685118077, 1143607656457264}, + }, + { + {5925968830616980, 5475584226682352, 5076614308992012, 5422447722241084, 4871259074999718}, + {1741735203658460, 2040511596280954, 3245879940788742, 1750904751318660, 1289068422789788}, + {103031326341235, 1843731695283489, 1066974994445109, 1210433521778964, 118970268237578}, + }, + { + {5029675928196841, 3837944199959690, 3856667351331398, 4299101000305422, 4340504849680591}, + {1990983617046169, 3106460878930032, 1275461113767736, 1443049000516840, 1724142301140669}, + {888262946735860, 1859763056800716, 714395964694532, 57820586821189, 354182478325612}, + }, + { + {3800325421725661, 5577357186452733, 3783169523012609, 5425955064608896, 6347571520159237}, + {1658219197861187, 1494360717755939, 1921505970326949, 3049386312266838, 2475279382922093}, + {1290766154788448, 1600589032610209, 784792370088015, 423204440383515, 459184860068298}, + }, + { + {3425205252763663, 5240056527358710, 4140356292677088, 4578393707504979, 5259386798582854}, + {2215101089214073, 1997062079162084, 1249116849924618, 465107085276733, 1293244424458276}, + {880894898454805, 639667973647762, 200272726605326, 297199521205209, 1640420309599773}, + }, + { + {4024399276644653, 4828207338948134, 4459991457755541, 6377452215012324, 4100282940590511}, + {658635179203333, 3717891363165700, 3673816673290121, 2129566854376278, 1443087419989351}, + {1532654097308642, 1958497386525981, 111717506991097, 1708848284574815, 1306115185198907}, + }, + { + {6112399743594082, 4482370964094274, 5295504988778619, 4900443159383520, 4202262340818045}, + {2039429018914652, 3043146685732704, 1364716986897875, 1031303003048000, 1123429638631433}, + {765045651502510, 451621180435426, 15885268584069, 767513226653014, 768056106241896}, + }, + }, + { + { + {4032987623010691, 3949423965177593, 3633193504625235, 4678793759655164, 3734854480100484}, + {3008217384184691, 2489682092917849, 2136263418594015, 1701968045454886, 2955512998822720}, + {2175517777364616, 708781536456029, 955668231122942, 1967557500069555, 2021208005604118}, + }, + { + {3694962906564668, 2643675345331409, 4432646948339879, 4968138170389248, 3845898010522424}, + {3366935780292116, 2476017186636029, 915967306279221, 593866251291540, 2813546907893254}, + {850858855888869, 319436476624586, 327807784938441, 740785849558761, 17128415486016}, + }, + { + {3776976050663564, 5477805104091557, 2545236069347884, 4651869248468534, 4641561625804457}, + {2132756334090048, 2788047633840893, 2300706964962114, 2860273011285942, 3513489358708031}, + {1121075518299410, 2071745529082111, 1265567917414828, 1648196578317805, 496232102750820}, + }, + { + {5158525177930532, 3420610809262104, 2827455773116173, 5409358332231883, 5000374192034028}, + {2374121042985030, 3274721891178932, 2001275453369483, 2017441881607947, 3245005694463250}, + {1954109525779738, 2117022646152485, 338102630417180, 1194140505732026, 107881734943492}, + }, + { + {4610031103869799, 4566082599491057, 6017046282479905, 5310858379140016, 4504138118839608}, + {1714785840001267, 4288299832366837, 1876380234251965, 2056717182974196, 1645855254384642}, + {2002850762893643, 1243624520538135, 1486040410574605, 2184752338181213, 378495998083531}, + }, + { + {4119798625761979, 5219024680951196, 4543568213831910, 4424867828271409, 5157422279171799}, + {922510868424903, 1089502620807680, 402544072617374, 1131446598479839, 1290278588136533}, + {162892278589453, 182585796682149, 75093073137630, 497037941226502, 133871727117371}, + }, + { + {4201115364782060, 3320803158679711, 4190964847185163, 3800027019416103, 4185567469546654}, + {4166396390264918, 1608999621851577, 1987629837704609, 1519655314857977, 1819193753409464}, + {1730519386931635, 1393284965610134, 1597143735726030, 416032382447158, 1429665248828629}, + }, + { + {4551201741097278, 3774114323393256, 2689506075058172, 3065835144123274, 2587730464618792}, + {360275475604546, 2799635544748326, 2467160717872776, 2848446553564254, 2584509464110332}, + {1291597595523886, 1058020588994081, 402837842324045, 1363323695882781, 2105763393033193}, + }, + { + {5895867926878639, 6191714343966274, 3878657686711880, 3772412065246579, 5254560912358513}, + {1828399243003455, 2730967851207580, 2809663501613790, 3291961475373747, 2085819249159773}, + {1604304703501714, 1563946362290690, 2128875205288733, 257625874150601, 2149102916187814}, + }, + { + {5883573429799187, 4805272859062230, 2886195180819460, 4460210052098162, 3528150621150027}, + {1960233741679201, 2996857902780426, 2245274121401778, 4454263006625692, 1110175461750907}, + {1392548583294657, 697289852607029, 746483005053522, 734366559550160, 929768637070953}, + }, + { + {5047299589947009, 4992620901798841, 5716112978503343, 3741839332315327, 4983937719789158}, + {1673816614349955, 3255360796858239, 2753984593405885, 2969035246796379, 2420194805583742}, + {1159863250954626, 1438000622355742, 254045494246044, 1734996482788294, 484539502358623}, + }, + { + {3740619537304301, 4538691700403019, 5325131682689719, 4744914552382795, 3720848390661317}, + {1212935253295623, 2026300849238541, 3447883684227245, 1364910689032303, 3019520894163467}, + {2014517785153097, 1607430272140319, 1855018731367383, 2200629261829065, 987339037980209}, + }, + { + {4426735416351775, 4348191232564971, 5508438055207952, 2420023948055060, 6131298111765032}, + {2763109171958591, 4020627496535071, 3147539030064750, 2177710318971894, 2463269685396658}, + {831460863845953, 1946524324541207, 761958653274011, 1366775091595921, 1187427455457947}, + }, + { + {3125773853625002, 4814913241945202, 4262512130702308, 3321059176595839, 3567623941809388}, + {2822285257464218, 607639870769094, 2857291392676774, 2362021242026611, 3328398883102618}, + {1972329598509655, 34473001166350, 1728817301333588, 1539479676009467, 1694458836743324}, + }, + { + {4805304108915754, 5125985383393506, 5019883131944028, 4580919291870093, 4156575634700942}, + {1575955157633628, 3067048601687650, 2501496271474334, 4193474980184415, 3288209175931426}, + {1442686188453203, 1751694580158105, 824989332883473, 614995267948452, 1497907423783166}, + }, + }, + { + { + {4408790844622027, 4479344310838572, 4120849908116869, 3006675674164362, 4006042157952305}, + {2361321796251793, 3967057562270386, 1112231216891515, 2046641005101484, 2386048970842261}, + {1846089562873800, 98894784984326, 1412430299204844, 171351226625762, 1100604760929008}, + }, + { + {5371908961903233, 6206610140112367, 4204489822423303, 4507924897296559, 4322883368647362}, + {2335972195815721, 2751510784385293, 425749630620777, 1762872794206857, 2864642415813208}, + {523094549451158, 401938899487815, 1407690589076010, 2022387426254453, 158660516411257}, + }, + { + {3975648787468681, 4460622334219928, 3970548136462187, 4226068267807189, 3446012315943388}, + {612867287630009, 2700012425789062, 2823428891104443, 1466796750919375, 1728478129663858}, + {1254114807944608, 977770684047110, 2010756238954993, 1783628927194099, 1525962994408256}, + }, + { + {5270938303411141, 3005889362003651, 3774991859324322, 4939345652492557, 5016292135810879}, + {2484263871921055, 1948628555342433, 1835348780427694, 1031609499437291, 2316271920603621}, + {1255955808701983, 1700487367990941, 1166401238800299, 1175121994891534, 1190934801395380}, + }, + { + {5381119574505877, 4424637839817897, 4775904018594624, 3906943141245230, 5389829033800309}, + {2600943821853521, 1337012557669161, 1475912332999108, 3573418268585706, 2299411105589567}, + {375806028254706, 214463229793940, 572906353144089, 572168269875638, 697556386112979}, + }, + { + {4199915895763317, 4306698118173043, 4456738998669147, 4714126432522633, 3038393400292872}, + {1168827102357825, 823864273033637, 4323338565789945, 788062026895923, 2851378154428610}, + {1915320147894736, 156481169009469, 655050471180417, 592917090415421, 2165897438660879}, + }, + { + {3081796668531198, 4720661405375633, 3938365723488886, 5850548444590341, 6227423178100675}, + {1726336468579724, 1119932070398949, 1929199510967666, 2285718602008207, 1836837863503149}, + {384301494966394, 687038900403062, 2211195391021739, 254684538421383, 1245698430589680}, + }, + { + {3700877198419411, 4541885072828491, 4388337472863078, 4398292814526820, 5228760778493620}, + {1247567493562669, 4229981908141095, 2435671288478202, 806570235643434, 2540261331753164}, + {1201928866368855, 800415690605445, 1703146756828343, 997278587541744, 1858284414104014}, + }, + { + {3752846457602541, 6051774917153047, 3492614771149749, 5278195549012933, 3851678670548516}, + {1251637423994861, 2037585266091733, 1171182249847439, 1503770304884899, 1938920423810268}, + {2232651154426557, 514116965743385, 983369998596377, 1516132019440103, 1692302360068816}, + }, + { + {4860689994687041, 4138464101331517, 4969836424606600, 3370757908330089, 3017690336853320}, + {3753543276036939, 3037198013841237, 3063121586956950, 2967087171212783, 2388800428725970}, + {1485716675407214, 1159619625081800, 197549418633523, 776030397384998, 252064880140599}, + }, + { + {4116450327020509, 4602447751059104, 4624188822504437, 3786392386215792, 4018069243702311}, + {3871066258534097, 182982139320960, 3846997414183091, 1246347657803786, 966334158538299}, + {2049526525941781, 1431983169228179, 3669291297222, 769041933664973, 1760968694339914}, + }, + { + {5411552533375856, 4680723354107633, 5764453140711672, 3663956673248104, 5834177820168369}, + {2029548972200054, 541413050113871, 2564963424993232, 3150712544977872, 2699322542672271}, + {513500031822581, 836561902873502, 82127696349010, 1591221763097659, 725989684331322}, + }, + { + {4424236584915172, 3098952863411429, 2785705377786181, 4107549518995786, 5362683219257666}, + {1071376590195254, 1910139340535847, 1936705400579295, 3523841068963764, 2356086500199738}, + {357287898232758, 1026512116626804, 1875958986125314, 1743551742697910, 1876232951311596}, + }, + { + {4332669232306147, 5882550009365637, 3881970305785489, 6570990168178499, 3489314838073396}, + {294975596735049, 2145292931466411, 3320625656613141, 2284954433570209, 3090254877821144}, + {1234852195927098, 3815763342761, 2085449281682153, 516098044852331, 164426832090235}, + }, + { + {3292223948318582, 4463121371440286, 5163264330075513, 4550237542693388, 4544934760614835}, + {2590122580645644, 1011386629068498, 960875975353535, 3791419723576010, 2273772136048635}, + {1749858954947675, 1561651915395372, 1738700200168191, 397865176422134, 1467025336447738}, + }, + }, + { + { + {3011428551915689, 3264493287961099, 4857379860456993, 4749679688758046, 4282178671364408}, + {2608268623334125, 3034173730618399, 1718002439402869, 3644022065904502, 663171266061950}, + {2040672435071076, 888593182036908, 1298443657189359, 1804780278521327, 354070726137060}, + }, + { + {4711536788361604, 4516566538409613, 5324597415653586, 3262240285890532, 3953172703826057}, + {1894938527423184, 3715012855162525, 2726210319182898, 2499094776718546, 877975941029127}, + {218882774543183, 533427444716285, 1233243976733245, 435054256891319, 1509568989549904}, + }, + { + {4802737216830789, 3846171402668813, 5371658121409568, 4761371218007175, 4056812806828167}, + {4140638349397055, 3303977572025869, 3465353617009382, 2420981822812579, 2715174081801119}, + {1806842755664364, 2098896946025095, 1356630998422878, 1458279806348064, 347755825962072}, + }, + { + {5169106331623846, 4777370102540357, 5302836601573124, 5351928617448052, 4063248596493177}, + {1402334161391744, 3811883484731547, 1008585416617746, 1147797150908892, 1420416683642459}, + {1468412523962641, 771866649897997, 1931766110147832, 799561180078482, 524837559150077}, + }, + { + {5770203524895319, 4659978036228594, 3527448837914025, 4951338033258915, 4756786089433589}, + {2223212657821831, 2882216061048914, 2144451165500327, 3068710944633039, 3276150872095279}, + {2022215964509735, 136144366993649, 1800716593296582, 1193970603800203, 871675847064218}, + }, + { + {5731767721917939, 4837733510733388, 5091167195790575, 4937212217651675, 5106990027743699}, + {1862751661970309, 851596246739884, 1519315554814041, 3794598280232697, 3669775149586767}, + {121893973206505, 1843345804916664, 1703118377384911, 497810164760654, 101150811654673}, + }, + { + {2836122124869624, 4884260866172613, 4618439021898554, 2906882084185319, 4363655839720099}, + {2710146069631716, 2542709749304591, 1452768413850678, 2802722688939463, 1537286854336537}, + {996965581008991, 2148998626477022, 1012273164934654, 1073876063914522, 1688031788934939}, + }, + { + {3949497701489527, 5838943331198768, 5334888242577534, 5453016312620545, 4792359904762516}, + {3175286832534829, 2085106799623354, 2779882615305384, 1606206360876187, 2987706905397772}, + {1419122478109648, 1325574567803701, 602393874111094, 2107893372601700, 1314159682671307}, + }, + { + {4954618339278337, 3422305785425208, 4565328836139485, 3192891441493866, 4836379953614308}, + {855396458506247, 2470294140783466, 4436061492213979, 1754097632720488, 4112391040574456}, + {985511568884890, 583904209238998, 516128993365349, 1235577837475387, 1449904660690748}, + }, + { + {5895940682517746, 4393238442290827, 4244687834629046, 5245476345580864, 4795864303032094}, + {1477173810966796, 3207978347793495, 2656860913951054, 825157489520718, 2782873637674750}, + {12931323257125, 562700432679180, 780577595442459, 440747171628074, 31993258894121}, + }, + { + {5231235667053925, 5090675513104692, 4933657013889560, 5325938777525481, 4583903281916140}, + {2159229926833831, 1114556221271056, 2050697214928106, 2553796628978461, 2874553280901592}, + {1487427059839672, 1966052937474419, 398866894053509, 2040723626090668, 1223074007342359}, + }, + { + {3294796902098517, 3902877656361122, 4227499257540629, 5627711142390550, 5038311124292534}, + {2677874505039557, 678833394869758, 3687464289589147, 1992670845292812, 654778477108270}, + {651854196246431, 2602668557028, 1822678077647200, 2072267608435533, 435243653222236}, + }, + { + {4313218743534013, 3972172746637215, 5399714135650344, 5547659251980199, 4837224811093838}, + {2487053592812311, 2315738098787275, 1210583464083714, 1056644723032111, 781277197910636}, + {864616322745343, 1362699579128647, 1361407419724038, 495664202671974, 662016549521786}, + }, + { + {6154029469581357, 5498138279894180, 3281752713530018, 3501917375982713, 4910547940594210}, + {2672416110637939, 3245298985644332, 1344078619347414, 2037703067415133, 2697812769645364}, + {325041473989085, 842410640177049, 1052993540865892, 2093280369201601, 361408260911216}, + }, + { + {4388597398802075, 4997551911436129, 2851157853262017, 4795345418726848, 4139150667184165}, + {1519253497716003, 3826826078266703, 2262276529333275, 1386373334348474, 3240242941348023}, + {763973845167102, 1151501355459051, 1283654593302800, 584312404348728, 1219116745359281}, + }, + }, + { + { + {5676939182921069, 5322204711648077, 4551121131734783, 5427708347935459, 5239023033125000}, + {2201150872731785, 2180241023425241, 2349463270108411, 1633405770247823, 3100744856129234}, + {830104860549448, 1886653193241086, 1600929509383773, 1475051275443631, 286679780900937}, + }, + { + {4781988283280724, 4990742996470332, 5431361832879221, 4684617167544704, 3868686514426533}, + {3828911108518224, 3282698983453994, 2396700729978777, 4216472406664814, 2820189914640497}, + {1191033906638969, 940823957346562, 1606870843663445, 861684761499847, 658674867251089}, + }, + { + {5126469419668815, 4155719092635613, 4174388435346876, 3772374525285681, 5590700387545135}, + {1875032594195527, 1427106132796197, 2976536204647406, 3153660325729987, 2887068310954007}, + {25465949416618, 1693639527318811, 1526153382657203, 125943137857169, 145276964043999}, + }, + { + {4258045666458167, 5238362362206654, 4758242557133921, 3658013106441212, 2491103563202933}, + {2466539671654587, 920212862967914, 4191701364657517, 3463662605460468, 2336897329405367}, + {1619678837192149, 1919424032779215, 1357391272956794, 1525634040073113, 1310226789796241}, + }, + { + {4248523125120879, 4096142580252307, 5489055327836539, 3417724495086206, 4815108317240624}, + {3292563523447371, 1704449869235351, 2857062884141577, 1998838089036354, 1312142911487502}, + {43173156290518, 2202883069785309, 1137787467085917, 1733636061944606, 1394992037553852}, + }, + { + {4449014387058033, 5297853724611810, 5533789687884231, 2519432329227148, 4292277862887871}, + {670078326344559, 2807454838744604, 2723759199967685, 2141455487356408, 849015953823125}, + {1812516004670529, 1609256702920783, 1706897079364493, 258549904773295, 996051247540686}, + }, + { + {5827060326775227, 5766290385251485, 3123576947163146, 5563678522359472, 3964036703348132}, + {1540374301420565, 1764656898914615, 1810104162020396, 3175608592848336, 2916189887881826}, + {1696163952057966, 1391710137550823, 608793846867416, 1034391509472039, 1780770894075012}, + }, + { + {5101135942842208, 4543974686113080, 4194056217641295, 5689084272866427, 2564466095709391}, + {1367603834210822, 4383788460268472, 890353773628143, 1908908219165595, 2522636708938139}, + {1919411405316294, 1234508526402192, 1066863051997083, 1008444703737597, 1348810787701552}, + }, + { + {4132340278436948, 4005982088010057, 3308609415246807, 3692550296463618, 3956871570338410}, + {1096972188133236, 3816049499915451, 1251976741328773, 1219603529073670, 1078899265206338}, + {950202511700693, 1240039391743494, 1169033682725545, 1423696267961315, 86935143579550}, + }, + { + {4756214981813576, 5522632333569959, 3862983342357100, 4309495274365548, 5713360895956932}, + {2683363149107878, 1470385524874179, 725539084456484, 3271790833618750, 1222340934084308}, + {200587706310533, 896271240996831, 1147839003219597, 673448965331479, 548900916085084}, + }, + { + {3550032568832337, 4838968015489313, 4675889877479625, 3212531632461645, 4765584451232964}, + {1405860849520605, 738725235942165, 399531320766275, 3195580921007755, 1958618144816834}, + {94349687650983, 306368484955948, 1759034073892087, 2030110332880331, 1270749214795711}, + }, + { + {2967631947537871, 4383349957254579, 3922288445505558, 5226885511958431, 3995794596785200}, + {1753118377928377, 3368465588051047, 1755914948419738, 3441455854862245, 647766692547292}, + {2005162920381704, 1507493192705080, 1430523618875617, 131673490468702, 662093487452573}, + }, + { + {2747463689102953, 5007357876041009, 5072033195962826, 4670246809435049, 5673751346141763}, + {2718321167227969, 855141819034537, 1769780985173952, 3439183400564947, 1192259870209089}, + {747964066233340, 2037427400347459, 49693847757217, 2003202980691532, 2230561945728266}, + }, + { + {4747984612298188, 4723422270130357, 4628272886928943, 3839214906514725, 5200339299152060}, + {1424576382204282, 350051250024461, 3895326653518337, 3070821812734749, 3346444741017048}, + {2021002858021100, 839958875652478, 2080082610761570, 1282995787185392, 313106058533657}, + }, + { + {5293324356940491, 3886891387640488, 5386021427475165, 4491415749098830, 3988924707585306}, + {2136145829133251, 713070507515938, 1951333115623761, 3770252317439440, 1824831508473442}, + {2203533335083089, 2130417962449796, 217179607020589, 153498131255469, 1884913426826060}, + }, + }, + { + { + {6357530995067419, 4511707601241201, 4853814131499793, 3027006748267833, 4004117462852039}, + {2102881477513865, 3822074379630609, 1573617900503707, 2270462449417831, 2232324307922097}, + {1417148368003523, 721357181628282, 505725498207811, 373232277872983, 261634707184480}, + }, + { + {3519916180986434, 5063756715513304, 5306226466970938, 4461989750290959, 5633593412950483}, + {2186733281493248, 2250694917008620, 1014829812957440, 2731797975137637, 2335366007561721}, + {615183387352312, 917611676109240, 878893615973325, 978940963313282, 938686890583575}, + }, + { + {4051478965894094, 5415732403270882, 4529567395411473, 4935730075960955, 4778168617632490}, + {522024729211672, 3296859129001056, 1892245413707789, 1907891107684253, 2059998109500714}, + {98698809797682, 2144627600856209, 1907959298569602, 811491302610148, 1262481774981493}, + }, + { + {5721409450692386, 4425747098618406, 6490527463642820, 3639914744810785, 4516285758530664}, + {1791451399743152, 1713538728337276, 2370149810942738, 1882306388849953, 158235232210248}, + {1650875518872272, 1136263858253897, 1732115601395988, 734312880662190, 1252904681142109}, + }, + { + {5306746809205765, 3120741251682392, 2568099116674910, 5447095217001045, 2823024101589818}, + {2624786269799113, 2777230729143418, 2116279931702134, 2753222527273063, 1907002872974924}, + {227742695588364, 1776969298667369, 628602552821802, 457210915378118, 2041906378111140}, + }, + { + {3832015885289562, 4129797318027691, 5360746788631408, 5207122354148972, 4434563787896849}, + {815000523470260, 3164885502413555, 3303859931956420, 1345536665214222, 541623413135555}, + {1870080310923419, 71988220958492, 1783225432016732, 615915287105016, 1035570475990230}, + }, + { + {4881216209018060, 3833780216763759, 5307643745501116, 4286182636729437, 5147443675842680}, + {2982787564515398, 857613889540279, 1083813157271766, 1002817255970169, 1719228484436074}, + {176957326463017, 1573744060478586, 528642225008045, 1816109618372371, 1515140189765006}, + }, + { + {2695191990687280, 4737393024215632, 4451306435997662, 3263658520201184, 3226476650748376}, + {1888911448245718, 3638910709296328, 4176303607751676, 1731539523700948, 2230378382645454}, + {1846351103143623, 1949984838808427, 671247021915253, 1946756846184401, 1929296930380217}, + }, + { + {4257691815043557, 4587099125055339, 4378829326829150, 4530783676112038, 5088169500723328}, + {2633154847819111, 2373317802678415, 4226812651282694, 3531985668346704, 3254298087102270}, + {1896123626988797, 1131351092678624, 1831358114864483, 1263257519094555, 153161823153575}, + }, + { + {5013999188326350, 5342051120597129, 5658875547575315, 4993589587822012, 3418484323529615}, + {2875848054604140, 2609079967536269, 3221396114275243, 1330649045956928, 1828925625187427}, + {85523512650066, 1145743424577874, 270900922559567, 1781500837265517, 1998986005265292}, + }, + { + {4300315009401728, 4620112123771453, 2612760971016545, 3052063778972094, 4706549333122035}, + {2904227921845290, 4267364811643403, 1994336236107343, 2172724361186958, 2854607055726693}, + {2127639189718319, 2205729457048157, 1849555339256920, 1751645797856968, 1883138982486949}, + }, + { + {3989916020510698, 4741941595447558, 5214589701377240, 4351148330446081, 3428672470823222}, + {762600272699964, 2753498328779892, 3316416370655704, 526788695246361, 3062867170941268}, + {1503368613839734, 2009362771486879, 495897391474535, 1905468005297555, 272387388531978}, + }, + { + {5813046901089551, 5050432868964283, 4705275668110217, 4196337029208819, 5257156494192722}, + {1830890930331365, 3828112268992685, 3895633691902557, 3356965264729727, 2386741853982022}, + {995710478389517, 1430833880042694, 1172677663947400, 1545257382741759, 1798260148494462}, + }, + { + {5205850356707429, 4686811868434220, 5616916192509070, 4494846080958018, 5419646380822597}, + {1276458355120913, 2527187906858810, 1130163473530636, 3533175711581762, 2161750040536619}, + {1025062667466023, 43711902086443, 2210112172846377, 233136450830559, 1412931651896051}, + }, + { + {3560341629038503, 4545538003102686, 5283269045082286, 4816839347899222, 4801547130939062}, + {2448047678851139, 599053419172738, 3080495073729726, 1198848441856844, 1359787207816262}, + {555971766815523, 2160228751293088, 266579216919501, 408880354152864, 2184471346102790}, + }, + }, + { + { + {5195617294728737, 5226905206197221, 3889841953548511, 5251818933360801, 4838188827894395}, + {849646212451983, 1410198775302919, 2325567699868943, 1641663456615811, 3014056086137659}, + {22893968530686, 2235758574399251, 1661465835630252, 925707319443452, 1203475116966621}, + }, + { + {3154905071699595, 4930741522303542, 5064786644540271, 4136130058087200, 4165945522107466}, + {3053098849470395, 3985092410411378, 1664508947088595, 2719548934677170, 3899298398220870}, + {1344191060517578, 1960935031767890, 1518838929955259, 1781502350597190, 1564784025565682}, + }, + { + {4168985401048642, 5601942199123232, 4509535428414908, 4252327476037085, 6042239923552064}, + {2925523165433334, 1979969272514922, 3427087126180756, 1187589090978665, 1881897672213940}, + {2495540013192, 678856913479236, 224998292422872, 219635787698590, 1972465269000940}, + }, + { + {4698182657338567, 5017916408838259, 3081477769920918, 3928215500558329, 5313704211766335}, + {271413961212179, 3604851875156899, 2596511104968730, 2014925838520661, 2006221033113941}, + {1980510813313589, 1948645276483975, 152063780665900, 129968026417582, 256984195613935}, + }, + { + {5300264442994823, 3794960652558197, 6004497419208260, 6170915605358895, 5102903504401205}, + {1860190562533083, 1936576191345085, 2712900106391212, 1811043097042829, 3209286562992083}, + {1151480509533204, 2136010406720455, 738796060240027, 319298003765044, 1150614464349587}, + }, + { + {5520821677598445, 4505587343518853, 4486119403320947, 5124882310463887, 4384352945448272}, + {1731069268103131, 2987442261301335, 1364750481334267, 2669032653668119, 3178908082812908}, + {1567828528453324, 1017807205202360, 565295260895298, 829541698429100, 307243822276582}, + }, + { + {4341766796632437, 4105940157601428, 4403780572905254, 4391581105946996, 4661670073235412}, + {249079270936229, 1501514259790706, 3199709537890096, 944551802437486, 2804458577667728}, + {1338766321464554, 1906702607371284, 1519569445519894, 115384726262267, 1393058953390992}, + }, + { + {4136644411018817, 5105079697639574, 5123803130450031, 3331327213803161, 3453876506817262}, + {3616421371950629, 3764188048593604, 1926731583198685, 2041482526432505, 3172200936019022}, + {840922919763324, 727955812569642, 1303406629750194, 522898432152867, 294161410441865}, + }, + { + {5565570118069330, 4591619629413879, 3505524267391659, 5911065393515679, 5626780252302286}, + {2954349327665336, 2875421537282295, 1177907047549607, 2315244756624323, 3303388475971642}, + {1193532613439179, 1341357357703238, 1857522674746129, 587336359047056, 1462817734082691}, + }, + { + {5032608083579310, 5556680383291862, 4639031978972564, 2550751933150061, 4661900946642239}, + {981709001326388, 2228829982452486, 1195252744174570, 1961335123791201, 473922585791741}, + {158547452916311, 1806851940249257, 1888549274109445, 1234535032385844, 755999937979748}, + }, + { + {5099505633219587, 3654947652195304, 4632839805758299, 3516983533390311, 3156502843280841}, + {2235936902666817, 1844821659342916, 4255944160143733, 2705728103151199, 1360010073190141}, + {1966276380904262, 1243659846916250, 1230287549611464, 1790496592504769, 385075881855087}, + }, + { + {5102974111125320, 5352605641984611, 4254853167292498, 4166876022626639, 4692858050734664}, + {808958715657412, 2787760179369277, 2812754371047796, 3109195163271007, 3174221799565416}, + {1970356456788069, 1887106101566224, 2120741856788965, 1887465058487327, 166078852378175}, + }, + { + {5268074145727905, 3102961204581063, 5775739741243707, 6623549226998551, 5355512520264473}, + {1475882426726637, 2923995069592105, 2595116660588037, 2134573872614909, 2857982748479313}, + {957649428811476, 1521919451665798, 1487878569331559, 1715152263604455, 2000934618350472}, + }, + { + {3462276468747197, 4403243110229213, 5274708467449337, 4946143993185919, 6100123938510411}, + {2624197675552195, 2160845895419703, 991891416996825, 2705836223851003, 2307139020684469}, + {231885416467149, 648441606302746, 1371491506634443, 193373311482025, 2106953050161716}, + }, + { + {2408565470230034, 4633147941257550, 4425551739809483, 4183865634168848, 4784444305258783}, + {2307403528152576, 3136574081495182, 3694424861021853, 1950918571001278, 1747697954472435}, + {931185174846608, 872635055344100, 1155298897916392, 1344438153479985, 863698029056587}, + }, + }, + { + { + {2611656183523465, 4684513982859178, 5365326100017121, 4722407564633480, 2827426586917747}, + {2605560604520539, 1598361541848742, 3374705511887547, 4174333403844152, 2670907514351827}, + {755467689082474, 909202735047934, 730078068932500, 936309075711518, 2007798262842972}, + }, + { + {3236138991462016, 3067527600191131, 3896954399398994, 3910874778063800, 3938401465669403}, + {1609384177904054, 2614544999293875, 1335318541768200, 3052765584121496, 2799677792952659}, + {1697863093781930, 599794399429786, 1104556219769607, 830560774794755, 12812858601017}, + }, + { + {4108730476499120, 5181690479373092, 4171978954440413, 3511327647445115, 4559140599266006}, + {1168737550514982, 897832437380552, 463140296333799, 2554364413707795, 2008360505135500}, + {1158643631044921, 476554103621892, 178447851439725, 1305025542653569, 103433927680625}, + }, + { + {3077203098880308, 4396008401246031, 4177351818329890, 6418777467377480, 5519551756318358}, + {2176793111709008, 3828525530035639, 2009350167273522, 2012390194631546, 2125297410909580}, + {1807108316634472, 1534392066433717, 347342975407218, 1153820745616376, 7375003497471}, + }, + { + {4732167545780233, 5368693586150714, 2609883700135802, 4663217517029815, 3612437739977844}, + {3234860815484973, 2683011703586488, 2201903782961092, 3069193724749589, 2214616493042166}, + {234147501399755, 2229469128637390, 2175289352258889, 1397401514549353, 1885288963089922}, + }, + { + {5617390325210756, 5554766767336738, 5549530285921438, 6514965868913137, 3937966638306001}, + {3363562226636810, 2504649386192636, 3300514047508588, 2397910909286693, 1237505378776769}, + {1054097349305049, 1872495070333352, 182121071220717, 1064378906787311, 100273572924182}, + }, + { + {4607833422014698, 3800719604873494, 4476341726952553, 4306709190801725, 3295603202700400}, + {3558210666856834, 1627717417672446, 2302783034773665, 1109249951172249, 3122001602766640}, + {216762189468802, 707284285441622, 190678557969733, 973969342604308, 1403009538434867}, + }, + { + {4847405480488793, 3554016671099447, 2818672356908788, 4302938753224251, 4825028485754775}, + {3530824104723725, 2596576648903557, 2525521909702446, 4086000250496689, 634517197663803}, + {470067171324852, 1618629234173951, 2000092177515639, 7307679772789, 1117521120249968}, + }, + { + {4032307292940140, 4855742012511787, 4007061004220393, 4186026976205829, 5188147460015837}, + {1726290253928048, 2108179153379055, 3599306339052623, 3804322907336713, 740669388116407}, + {1893601910775915, 1893561171028788, 174914675480509, 2073460144115735, 250678301747773}, + }, + { + {5696478198308385, 3135077959467853, 5039986204304988, 5696739636381970, 5163380137461980}, + {1473356281060031, 1850501243620073, 559809451272168, 2164039335364390, 2799937740729438}, + {506406583155327, 1903499899096002, 445887262445598, 866962765497367, 55809365421254}, + }, + { + {5290224396694939, 4705669579710662, 4614921349557141, 5027610124814334, 5088773866023979}, + {2009707214072007, 3490160897828618, 275706542492147, 1283471147003836, 2026672645131195}, + {1123457689056584, 2213608670005209, 1379370540202855, 2074314852377531, 864461310144552}, + }, + { + {5111150460891680, 4275734012505621, 4206718452855061, 3888755110807716, 5005016151412877}, + {2967787444233740, 1413004988964951, 690605351712577, 3813861694171786, 728516486273669}, + {2016155040846069, 1480238949730910, 882386999623863, 1367342654128568, 589184047321896}, + }, + { + {3850772783035735, 4143292076634522, 5556861502206409, 4279143658707597, 3550043180479289}, + {3493927566017921, 3571431901909570, 2627286406743953, 2047641118374561, 1730233493072697}, + {272317805124786, 1812925138663726, 1217316351219782, 1182300795957412, 1252963393607199}, + }, + { + {5371799854215572, 3393967588858477, 5067027508227680, 3852577519740789, 4734905175716170}, + {3515527020405104, 2159318542704715, 1058260913419646, 2981918447395233, 1340478002453928}, + {896362445577855, 1547885531466434, 942263962614365, 1148475609702329, 2122889133222112}, + }, + { + {5312477093520487, 3952229351525915, 5253212242457428, 4756871683292235, 4134773488559657}, + {2735014629385533, 1581591485505255, 1720528958990566, 4161950575359359, 2332085424554487}, + {704970088806441, 1168889861388831, 354811087636935, 1536113135588939, 2212112893107236}, + }, + }, + { + { + {2828809211088312, 6295039889156786, 4429443549656884, 4678145777282455, 5916104705152820}, + {2529951391976704, 1810282338562946, 1771599529530998, 3635459223356879, 2937173228157088}, + {893719721537457, 1201282458018197, 1522349501711173, 58011597740583, 1130406465887139}, + }, + { + {4766083398225008, 5494110682478710, 2778685366456944, 2823464210331405, 4857685817649218}, + {412607348255434, 1280455764199780, 2233277987330768, 2265979894086913, 2583384512102412}, + {1820352417585487, 24495617171480, 1547899057533253, 10041836186225, 480457105094042}, + }, + { + {5647768329980203, 5108044017780681, 3796340935441384, 4177115363811274, 5130001056264497}, + {2023310314989233, 2889705151211129, 2106474638900686, 2809620524769320, 1687858215057825}, + {1922168257351784, 2018674099908659, 1776454117494445, 956539191509034, 36031129147635}, + }, + { + {4561842048916374, 4287612509327089, 4370291679808170, 5695284091186768, 4550521144824593}, + {2796444352433270, 1039872944430373, 3128550222815858, 2962457525011798, 3468752501170219}, + {272268252444639, 1374166457774292, 2230115177009552, 1053149803909880, 1354288411641016}, + }, + { + {5697036697171416, 5404706777075284, 5503272547981905, 4981184452172701, 4867839206068339}, + {1857910905368338, 1754729879288912, 3137745277795125, 1516096106802165, 1602902393369811}, + {886299989548838, 1538292895758047, 1590564179491896, 1944527126709657, 837344427345298}, + }, + { + {3561647617580592, 3713951676498321, 4714970494042065, 3796394966388927, 5531291426324585}, + {3006358179063534, 1712186480903617, 3955456640022779, 3002110732175033, 2770795853936147}, + {803217563745370, 1884799722343599, 1357706345069218, 2244955901722095, 730869460037413}, + }, + { + {5199950995983500, 5997984878609744, 5241636760987426, 5139985135222038, 5431082849981900}, + {2941099284981214, 1831210565161070, 3626987155270686, 3358084791231418, 1893781834054268}, + {1949114198209333, 1104419699537997, 783495707664463, 1747473107602770, 2002634765788641}, + }, + { + {3320700462489453, 4258691810757797, 5637648896716044, 3890560459865337, 4307195898311025}, + {1607325776830197, 2782683755100581, 1451089452727894, 3833490970768671, 496100432831153}, + {2222475519314561, 1870703901472013, 1884051508440561, 1344072275216753, 1318025677799069}, + }, + { + {4037612142179094, 2987286320918074, 5334840876971305, 3892287190264789, 5794263680951471}, + {471926402845486, 2814813543274642, 3620200888572759, 1728489506884653, 3177161343196207}, + {1819395223745913, 594758877920007, 1653753349717506, 242640844960873, 963869472910932}, + }, + { + {2936569169465705, 6049214516933086, 5963733906800640, 4231427100807371, 4853047066834829}, + {2548596925868729, 2662135700065828, 2088163736824992, 2331981460676031, 2771125203890139}, + {780634400476978, 637764048158951, 901014587909154, 1354805333992459, 2018934308296179}, + }, + { + {2797688906622325, 3428210403110380, 5022584852934687, 3295825468273441, 5705393166486691}, + {2111199241475135, 1851629318616336, 1992578166276991, 2095428925801999, 1218266125748465}, + {1810680242312559, 952287178947563, 681241246062059, 1252456339225424, 1959931529139639}, + }, + { + {4919536354167776, 4843044804249283, 4705930511557457, 5262690042745614, 4386984625976838}, + {3747081830160208, 1520760409479969, 1598412209810121, 1654404133831532, 437659257098574}, + {744124236937047, 1544378156616778, 715829909389559, 2120659842894185, 72002654880101}, + }, + { + {4563826663843359, 5185090504058247, 5145727029702249, 5011944329783380, 5313803489832094}, + {244278499662023, 2000287644883357, 3512120660608951, 1998820466139820, 2107051881706162}, + {1061541907539207, 1129143356143074, 459133314948729, 1177985907118634, 1224368687812524}, + }, + { + {3152842550820126, 4081984728409524, 3254259750651619, 4604329179757860, 4471438744025494}, + {2383716445654654, 2845501105364248, 3179274641918483, 2181012191586748, 4055424112922904}, + {1792270341351139, 2065266134997868, 51895527839218, 798734893906822, 992253836606399}, + }, + { + {4950351600164207, 5298895157252043, 5150281689404603, 4544152582549862, 5356669996354042}, + {1927020266981541, 1747143248428675, 1588706088137551, 1077596294054796, 1170976366872068}, + {1001666581039191, 1742276948383877, 1379478310433234, 767654427573973, 2047968425937961}, + }, + }, + { + { + {4511412834337187, 4698043828798044, 4323205223211753, 5569204703546807, 6149086417101785}, + {155711679280637, 681100400509288, 389811735211209, 2135723811340709, 2660533024889373}, + {16625790644959, 1647648827778410, 1579910185572704, 436452271048548, 121070048451050}, + }, + { + {4694164895067901, 2924655519713304, 4842396181739721, 4841286895864398, 5356846476062228}, + {3289062842237779, 2820185594063076, 2549752917829677, 3810384325616458, 2238221839292470}, + {1763863028400139, 766498079432444, 1321118624818005, 69494294452268, 858786744165651}, + }, + { + {4869852729848717, 5029275869879305, 3701410808950684, 3435100659007430, 4689559933862040}, + {3543856582248253, 1456632109855637, 3352431060735432, 1386133165675320, 3484698163879000}, + {28315355815982, 460422265558930, 1799675876678724, 1969256312504498, 1051823843138725}, + }, + { + {4558284163736209, 4461809852221468, 5698584425525803, 5038838655144199, 3768154892986607}, + {2408714813047231, 3857948219405196, 1665208410108429, 2569443092377519, 1383783705665319}, + {1484387703771650, 198537510937949, 2186282186359116, 617687444857508, 647477376402122}, + }, + { + {4662985813836019, 4129426407048187, 5122336824431007, 5530273911701301, 3409921574477931}, + {2147715541830533, 2751832352131065, 2898179830570073, 2604027669016369, 1488268620408051}, + {1744544377739822, 1964054180355661, 1685781755873170, 2169740670377448, 1286112621104591}, + }, + { + {3854053602374273, 4943141672260381, 4472148111349729, 5161477038123364, 4661051199882732}, + {2333777063470241, 3919742931398333, 3920783633320113, 1605016835177614, 1353960708075544}, + {1029287186166717, 65860128430192, 525298368814832, 1491902500801986, 1461064796385400}, + }, + { + {3437283298068479, 3608139386273800, 5088531994686943, 4605732407316964, 6296522248487285}, + {2660016802414475, 2121095722306988, 913562102267595, 1879708920318308, 2492861262121979}, + {1966196870701923, 2230044620318636, 1425982460745905, 261167817826569, 46517743394330}, + }, + { + {6233793835087996, 4935389669690266, 6335114860649961, 3623880366453827, 5578113556752255}, + {2358877405280588, 3136759755857592, 2279106683482647, 2224911448949389, 3216151871930471}, + {1450880638731607, 1019861580989005, 1229729455116861, 1174945729836143, 826083146840706}, + }, + { + {3994140066248694, 3181522224560048, 3364322700715335, 6108496090134019, 4266308196944062}, + {978398934730796, 1804963209584982, 2902083217855803, 2011728779166715, 3070976799182328}, + {494691910923538, 1903565874798025, 2115181773831520, 2000771501496645, 2163753695162256}, + }, + { + {4499039401984510, 2919282610904813, 3371698570925682, 3170519001059914, 5250127479378489}, + {1654039515014884, 2484661430680993, 2620692000541228, 2669599656280070, 2398652280696967}, + {2019971150480802, 2112841493625261, 237154577131804, 1674207955014809, 1389703158284583}, + }, + { + {4706814366157303, 5336609175411517, 4757963599977030, 4060364649415927, 3640669095240911}, + {780624938414169, 3404608320205059, 1982958325444026, 3570514777233615, 984254926012775}, + {1463658959517057, 1983397723547684, 41055560978805, 424638764130418, 491755157953272}, + }, + { + {3257295355011901, 4096776962011503, 4487597369409850, 5876979850901767, 6030505591690325}, + {2935104701953453, 3989681641092319, 3306366339882358, 2374391350196501, 1896075761392399}, + {1262337399368722, 1039133447611747, 917288766852537, 1931663063827599, 386956994697158}, + }, + { + {5865485955051801, 4898975626365390, 5709055439582716, 3072783210395629, 4352817622936409}, + {2724577252043037, 1050316213165918, 2370342271552724, 2792859709284319, 2760145987712013}, + {1677351910521822, 152891770438727, 738510373109788, 1296476386064424, 1219545250565005}, + }, + { + {2955221061271345, 5973180148171190, 3740903689178612, 4255579446112404, 4178816467357894}, + {1908022307626643, 2469819122662084, 1583327987932656, 3442462106139746, 599498145240366}, + {220308000962909, 460573332431611, 732078470162760, 467340602781483, 1127652895548970}, + }, + { + {4256843681823156, 4695170685669586, 4012905106498514, 5492595949894092, 4822219141250098}, + {1289113762003406, 2808167474320130, 1666802361626320, 1051654028271354, 1724653376239634}, + {1695390634076771, 1517610099990508, 1248456812719894, 2178282202616225, 905038523003109}, + }, + }, + { + { + {4388488268525257, 4351308814649541, 3942600308931722, 3469443492260723, 3080520458769465}, + {1899935429242705, 1602068751520477, 940583196550370, 2334230882739107, 1540863155745695}, + {765548025667841, 462473984016099, 998061409979798, 546353034089527, 2212508972466858}, + }, + { + {6305035755313584, 3986236631593136, 5772327717715563, 4670602724441205, 4485397579520202}, + {2298375097456408, 3144370785258318, 1281983193144089, 1491520128287375, 75847005908304}, + {1997562060465113, 1048700225534011, 7615603985628, 1855310849546841, 2242557647635213}, + }, + { + {3608844722049986, 2980930458947685, 6266068700289474, 3617433430563704, 4684882533775436}, + {1161017320376250, 2744424393854291, 2169815802355236, 3228296595417790, 1770879511019628}, + {1080413443139865, 1155205815510486, 1848782073549786, 622566975152580, 124965574467971}, + }, + { + {4272336182688229, 4705861119105631, 3304969482836130, 4308331792957791, 5281765142064806}, + {1184526762066993, 247622751762817, 2943928830891604, 3071818503097743, 2188697339828084}, + {237404399610207, 1308324858405118, 1229680749538400, 720131409105291, 1958958863624906}, + }, + { + {4785126936528543, 2288770346086770, 3118706734562790, 4474082416637981, 5793198356960377}, + {2767383321724075, 2269456792542436, 1717918437373988, 1568052070792483, 2298775616809171}, + {1278207464902042, 494742455008756, 1262082121427081, 1577236621659884, 1888786707293291}, + }, + { + {4316050955753838, 6170021230760201, 3671071179000687, 2720567588588102, 4695134757737078}, + {353042527954210, 1830056151907359, 1111731275799225, 2426760769524072, 404312815582674}, + {1716987058588002, 1859366439773457, 1767194234188234, 64476199777924, 1117233614485261}, + }, + { + {4802445580021739, 5669686216323056, 5683496153608928, 3599612573083939, 3664745203781455}, + {3236091949205521, 2386938060636506, 2220652137473166, 1722843421165029, 2442282371698157}, + {1143239552672925, 906436640714209, 2177000572812152, 2075299936108548, 325186347798433}, + }, + { + {4921698295511420, 2966865811406529, 3723715952061302, 4420370150973604, 5441412310007539}, + {2972824668060020, 2936287674948563, 3625238557779406, 2193186935276994, 1387043709851261}, + {1043584187226485, 2143395746619356, 2209558562919611, 482427979307092, 847556718384018}, + }, + { + {6539978005364395, 5005405360675302, 4390281321854973, 5817765520609028, 2885569505406129}, + {2401607320460403, 912267207660896, 2797776548107885, 1401692837350636, 2770414290856347}, + {904627574235583, 366582160013268, 1919276459982818, 683852563070972, 849013528013132}, + }, + { + {4382884022719489, 3331418080941236, 4472875449005139, 4019500438389598, 4463034067898545}, + {314313360314847, 1556311374160012, 3420403310565817, 1814168775579274, 3865931899404825}, + {2211811396782717, 1987727116500422, 1201194143426517, 1988979712261853, 884086138400803}, + }, + { + {3928195125806252, 4506628847593763, 4871806493038737, 5468133301160088, 4718975813247195}, + {3157237349544610, 2087027997220233, 1635119994381095, 1685873597006198, 3264645977099821}, + {554990822829571, 1043610604169755, 239155874009083, 1207029530220679, 1248980877883503}, + }, + { + {2330609380614712, 5282631639681642, 3679411410269759, 2770673432637308, 3778717181908177}, + {2321085204756486, 3204498878947842, 1897195179818497, 2221896934640248, 2249233024322127}, + {1100828805329651, 38323682820671, 233339076341529, 570439134676859, 373923102906827}, + }, + { + {4822469807205745, 4578534577854527, 3814578293772758, 6210971875752572, 3469875307698085}, + {650556138336187, 1140806781381529, 1319490550148986, 2443218412602398, 2092597895198457}, + {24874372349398, 672413878008022, 2109618619032869, 617580455983017, 643082448965145}, + }, + { + {3702942502950483, 4221261673998955, 4525315300848625, 5031967728773077, 4411934662665867}, + {895116466708821, 2311360532554913, 1331906084934491, 1442649827370867, 985339602059253}, + {1101806460504208, 48906420814555, 455540794156723, 777238833441277, 678815750013174}, + }, + { + {4956217544664282, 4411017504484405, 3654474138314413, 5155000128389593, 4413650344518487}, + {1203258470211606, 2883266356628027, 1508156827359997, 3638270983429361, 1401834110583505}, + {928961391578986, 832907369443124, 468987297840672, 1558723144077997, 1418280592841651}, + }, + }, + { + { + {3309129437554730, 5123933694799617, 4965300486638528, 6516081243872351, 2549068382794184}, + {1248731221520740, 1465200936117687, 2792603306395388, 2304778448366139, 2513234303861356}, + {1055352180870759, 1553151421852298, 1510903185371259, 1470458349428097, 1226259419062731}, + }, + { + {4550600281784187, 3256554237859110, 4119844627242950, 4676836561429904, 5092370827107509}, + {3744788603986897, 3042126439258578, 3441906842094992, 3641194565844440, 3872208010289441}, + {30498470091663, 1082245510489825, 576771653181956, 806509986132686, 1317634017056939}, + }, + { + {5619235959382811, 4106140804649401, 4587392324740009, 4223977265679267, 2709254929742834}, + {2672107869436803, 3745154677001249, 2417006535213335, 4136645508605033, 2065456951573058}, + {1698968457310898, 1435137169051090, 1083661677032510, 938363267483709, 340103887207182}, + }, + { + {4745319008032005, 4813628148687644, 3467681137065440, 3660014790178871, 4392941970152610}, + {1995325341336555, 911500251774648, 2415810569088940, 855378419194761, 3825401211214090}, + {1315157046163473, 727368447885818, 1363466668108618, 1668921439990361, 1398483384337907}, + }, + { + {6557196758364187, 4276231499541578, 4485350770690107, 4264207089194792, 3124346806789687}, + {2326829491984875, 3267188020145720, 1849729037055211, 4191614430138232, 2696204044080201}, + {1217269667678610, 599909351968693, 1390077048548598, 1471879360694802, 739586172317596}, + }, + { + {4384302481090479, 4717978973545909, 3754548127453306, 4211871514743047, 3605771636328385}, + {3970118453066023, 1560510726633957, 3156262694845170, 1418028351780051, 2346204163137185}, + {319394212043702, 2127459436033571, 717646691535162, 663366796076914, 318459064945314}, + }, + { + {3198885719919217, 2575084544179354, 3737578377662447, 5232176448882889, 5405183975072780}, + {2657789238608841, 1960452633787082, 2919148848086913, 3744474074452359, 1451061489880786}, + {1575783124125742, 2126210792434375, 1569430791264065, 1402582372904727, 1891780248341114}, + }, + { + {5242752265626106, 4326735213088803, 5009083294116390, 3863683170199334, 2880454449080125}, + {3090232019245924, 4249503325136911, 3270591693593114, 1662001808174330, 2330127946643001}, + {1822054032121349, 643057948186973, 7306757352712, 577249257962099, 284735863382083}, + }, + { + {3757294655239106, 4149870483813681, 3943074023634421, 5011331412913659, 4204233544524725}, + {765300458944758, 1962420935223063, 1006865922596525, 556125259357651, 517324314261719}, + {947503289917657, 1503416272497360, 836151367440855, 2025240512839119, 1506056841382176}, + }, + { + {3987605469554571, 4216854847559852, 4606485208582710, 4025002076531210, 5771502720173311}, + {789866795586711, 1219783998007690, 3399339961859034, 1430246873258510, 2263938746297911}, + {272907227620417, 585056874977936, 374400386458564, 1047259762290717, 466584497787787}, + }, + { + {4513305810099276, 3713543936920641, 5881885803512264, 4985359422621344, 5854329220017841}, + {2489594831593530, 2868670421452777, 2653264259914146, 778139640543916, 2896054888052141}, + {67965761977879, 1140658137927248, 1433664110101982, 1907417172350895, 1009746387131234}, + }, + { + {4657525718512496, 4017020332264511, 5032007516852528, 4196574218153666, 4558814287479470}, + {3191788312902362, 1662632170533261, 3849731434302862, 816384760006536, 2103376627071646}, + {98516339668203, 1987095201806236, 109825731538912, 249333174781555, 868887613476084}, + }, + { + {4551570896172554, 4811478172541458, 3661911804185849, 2859956435208139, 3775782540863495}, + {4251836217943410, 1527544805122594, 1416199226269029, 2604023934400523, 2761395386595757}, + {1642831683324706, 1693640639567753, 543897185448748, 1014750779914025, 2000933536049400}, + }, + { + {5616692888384001, 4085181778999311, 5359480780192985, 4168165762634953, 3706985665716275}, + {3046363118074651, 1033878254661623, 1432711896868579, 565399048183279, 1486610644259929}, + {1956000744629083, 2124722115672587, 1869890027060221, 1779425010763214, 2251549887150752}, + }, + { + {5403435201118585, 6603374055023538, 4448450050924979, 4204020352279014, 3319690980306662}, + {1147686993699695, 2183664403489392, 3736291649220767, 3475178747642004, 1656820196694734}, + {993108364179144, 45592857828226, 1223718961690034, 1931120528549047, 1402978202475587}, + }, + }, + { + { + {4707745854342560, 3882311012719969, 4467035027860010, 2426465723968789, 5459727301387711}, + {3618358370049178, 1448606567552085, 3730680834630016, 2417602993041145, 1115718458123497}, + {1562934578796716, 1070893489712745, 11324610642270, 958989751581897, 2172552325473805}, + }, + { + {2875482372335866, 3589666323156759, 5493912977577144, 3566036429447715, 3416572787955522}, + {1770564423056008, 2987323445349813, 1326060113795288, 1509650369341127, 2317692235267932}, + {223256821462517, 723690150104139, 1000261663630601, 933280913953265, 254872671543046}, + }, + { + {5739703102637456, 4089685696952464, 5529672212600950, 5529465141325467, 4053764715117380}, + {1969087237026022, 2876595539132372, 1335555107635968, 2069986355593023, 3963899963027150}, + {1115241013365517, 1712251818829143, 2148864332502771, 2096001471438138, 2235017246626125}, + }, + { + {4621952399709001, 5571208339175198, 5938396303563992, 3935039984233637, 4734466397277932}, + {3551068012286861, 2047148477845620, 2165648650132450, 1612539282026145, 2765997725314138}, + {1850689576796636, 1601590730430274, 1139674615958142, 1954384401440257, 76039205311}, + }, + { + {4398511437540326, 5006878555391994, 2877652875936652, 3360921192078354, 5537453437282356}, + {1723387471374172, 3249101280723658, 2785727448808904, 2272728458379212, 1756575222802512}, + {571005965509422, 2005213373292546, 1016697270349626, 56607856974274, 914438579435146}, + }, + { + {4021767746362864, 3947693133441663, 5655463017046415, 4032842598082935, 4903887401788780}, + {1346698876211176, 2076651707527589, 3336561384795453, 2517134292513653, 1068954492309670}, + {1851867764003121, 403841933237558, 820549523771987, 761292590207581, 1743735048551143}, + }, + { + {4789545034251916, 5151774024717947, 3350203576317227, 5870147068473486, 3757676696824463}, + {410915148140008, 2107072311871739, 3256167275561751, 2351484709082008, 1180818713503223}, + {672095903120153, 1675918957959872, 636236529315028, 1569297300327696, 2164144194785875}, + }, + { + {3867157095427632, 4907857238986876, 4412001163466224, 5664547006559450, 3829838433234787}, + {1902708175321798, 3287143344600686, 1178560808893262, 2552895497743394, 1280977479761117}, + {2013087639791217, 822734930507457, 1785668418619014, 1668650702946164, 389450875221715}, + }, + { + {5139170412209073, 4498594321446990, 3403045096731472, 3523999116931205, 4892973820656308}, + {3100339582931283, 3780065035763732, 3107854667684806, 1176538847728659, 2470425204007084}, + {1439699951361262, 2030141811121675, 1327540074439450, 98760879510567, 2124055188161162}, + }, + { + {5069757928527025, 4269771696870248, 3491008216607494, 2929486207919899, 2963259194922213}, + {1719771161855965, 3899474813414394, 1311077187368436, 1710977333891379, 2936225820601205}, + {630007537003875, 1879755431232807, 1841434412649072, 139825159320909, 1444684178970403}, + }, + { + {4165024628959566, 3986473160684857, 4482720357638229, 3477188964410991, 6063532098390286}, + {2735367442263082, 3037388464741161, 708840305892227, 3376016746983163, 2424461132835430}, + {1692345998026512, 1336264953003836, 472200476738834, 443198297543894, 865332172690922}, + }, + { + {3583240374232032, 6672838339902029, 3302719127491245, 4817707424315947, 3846209753841235}, + {1940518928195986, 2204192709398575, 2559878786338619, 1240694154295451, 3150360999940643}, + {978334155462452, 259156758770697, 1998397384612038, 868981902819036, 526720567050341}, + }, + { + {6295419175112392, 5922842429035919, 3280130237310527, 6154864010584464, 4672381744259604}, + {2495384380697450, 2529087473815087, 3152074437283087, 2705660594301054, 3756859018180124}, + {2829664309620, 1216345963700610, 1352213880784545, 1343440385603407, 1678896558555000}, + }, + { + {4462327178876654, 4861692839162759, 4026088282699843, 4559864737475196, 4141921357362458}, + {970323584385428, 1841886145157987, 771455069751873, 2995416444511372, 1381697279273918}, + {833881464516252, 722547189080954, 1385674139934263, 1947516117258013, 237073770273705}, + }, + { + {4933913084823421, 4670123363141682, 4900446203904881, 4055286352327374, 4290448492223496}, + {2942776662601173, 2578009269314716, 544737250664645, 2975699597442162, 2099680134205576}, + {452946908538500, 838029561099231, 448300214621162, 402872419278705, 704999550269611}, + }, + }, + { + { + {5798682425720784, 4343644325181242, 6354948599958312, 4506974667055090, 5293040366083331}, + {2705718263383616, 2358206633614248, 2072540975937134, 308588860670238, 1304394580755385}, + {2083069137186154, 848523102004566, 993982213589257, 1405313299916317, 1532824818698468}, + }, + { + {4034211192773531, 5600324567335276, 4531193018091912, 2794041663976599, 3792137612125120}, + {3747761112537659, 1397203457344778, 4026750030752190, 2391102557240943, 2318403398028034}, + {693543956581437, 171507720360750, 1557908942697227, 1074697073443438, 1104093109037196}, + }, + { + {4735029189573542, 3778090050106418, 6524974691396918, 6024554123028535, 3058137605210362}, + {345288228393400, 3351443383432420, 2386681722088990, 1740551994106739, 2500011992985018}, + {1079623667189886, 872403650198613, 766894200588288, 2163700860774109, 2023464507911816}, + }, + { + {3748938635589832, 3296620064200837, 3994393700108731, 5740803740117332, 5352647078187481}, + {854645372543796, 1936406001954827, 2403260476226501, 3077125552956802, 1554306377287555}, + {667962773375330, 1897271816877105, 1399712621683474, 1143302161683099, 2081798441209593}, + }, + { + {3324209478486170, 4398737310762775, 3760579922605898, 5439367229755348, 5616400060914562}, + {2378947665252234, 1936114012888109, 1704424366552046, 3108474694401560, 2968403435020606}, + {333549023751292, 280219272863308, 2104176666454852, 1036466864875785, 536135186520207}, + }, + { + {5689714689958878, 4503409610653732, 5602544085249448, 3404912574886620, 4043425317102514}, + {2625466093568366, 2398257055215356, 2555916080813104, 2667888562832962, 3510376944868638}, + {1870078460219737, 2129630962183380, 852283639691142, 292865602592851, 401904317342226}, + }, + { + {3798100817109506, 4962694127433334, 3349468332060557, 6283897397500138, 2972563107372854}, + {1361070124828016, 815664541425524, 3278598711049919, 1951790935390646, 2807674705520038}, + {1212405311403990, 1536693382542438, 61028431067459, 1863929423417129, 1223219538638038}, + }, + { + {4842650611581872, 5104986353880267, 4917334859504562, 3217991068822474, 6343075526828654}, + {1294303766540260, 3435357279640341, 3134071170918340, 2315654383110622, 2213283684565086}, + {235605972169408, 2174055643032978, 1538335001838863, 1281866796917192, 1815940222628465}, + }, + { + {6283914285320299, 4538885684827819, 5272821644392905, 4741145486323262, 3695595414404375}, + {2328903345630831, 383243669352281, 873975569357849, 1167517986625404, 1819176154401511}, + {1015569285123052, 366271559910559, 607712860974980, 1151136439806917, 1092279314442070}, + }, + { + {4644837603275095, 4182486257496369, 5680847280055574, 5281364304268108, 4017310458808244}, + {608363524539665, 1518910856395189, 2487752246555640, 1408491254860196, 1242950972146918}, + {724510145626490, 1990648995683735, 1234513756420164, 776971151906420, 1819715569230741}, + }, + { + {4025210576522653, 5037391877366464, 6220723743247171, 4107687904850403, 5536810198272054}, + {1367586897505451, 2009604536185136, 2660752171350541, 2665866783498593, 3368014404783418}, + {1205287993924177, 1639266049462139, 1103796806037893, 1538960177870822, 829889727712499}, + }, + { + {4793558625576028, 3882027570562344, 4207241179173547, 5281023204511977, 6361433483438371}, + {3281892459792280, 1933131048782198, 2351228493867205, 2032809616708977, 2534356983068777}, + {909754464411828, 785219392684958, 1338541457752162, 826789969638535, 2048189131938215}, + }, + { + {5399590275296719, 3849598676683261, 3407829328170797, 4201689601652353, 3895190733841783}, + {1015687460377127, 2173401063127799, 2017987633047477, 748955581941445, 630511527938929}, + {2101074774193018, 2001243087608708, 801641610437734, 1519697986446082, 594845713523709}, + }, + { + {4827244732148509, 4706350784965857, 3625459412499055, 5917778693464512, 5372808769862558}, + {1452942110247071, 1201823364506117, 2330240170803201, 2907618912660148, 2069141053434694}, + {745779946397307, 916664696261756, 1535477642186117, 1334763610638931, 1366843744138046}, + }, + { + {4176014068905464, 4252766041468492, 3589174288259552, 3776062686798003, 4986282119113185}, + {1092579010212274, 1203724605936750, 2270767453066752, 2458071886656347, 2443647576082745}, + {318795329870799, 185430882319687, 1286511919273276, 657817007383756, 40641447918263}, + }, + }, + { + { + {4538870843995520, 3964150480707053, 5487263883039355, 4602170887743532, 5736245235930330}, + {1632352921721536, 1833328609514701, 2092779091951987, 4175756015558474, 2210068022482918}, + {1998172393429622, 1798947921427073, 784387737563581, 1589352214827263, 1589861734168180}, + }, + { + {5350015016975595, 2997963309224426, 3081458566511327, 5095667333327441, 5460842165191887}, + {1733739258725305, 2283515530744786, 2453769758904107, 3243892858242237, 1194308773174555}, + {1758148849754419, 619249044817679, 168089007997045, 1371497636330523, 1867101418880350}, + }, + { + {3965982201013836, 5981456109444663, 5078495317312678, 4410918223912516, 3807332263401822}, + {2578433797894864, 2513559319756263, 1700682323676192, 1577907266349064, 3469447477068264}, + {853828206885131, 998498946036955, 1835887550391235, 207627336608048, 258363815956050}, + }, + { + {3753463041754121, 3606679279252159, 3696232489183494, 3149612277537848, 5358662226124843}, + {2392941288336925, 3488528558590503, 2894901233585134, 1646615130509172, 1208239602291765}, + {714380763546606, 1032824444965790, 1774073483745338, 1063840874947367, 1738680636537158}, + }, + { + {3423450128487239, 6070685071936072, 3705460605693651, 3009714346694508, 6123110970148691}, + {1640635546696233, 2884968766877360, 2212651044092395, 2282390772269100, 2620315074574625}, + {420958967093237, 971103481109486, 2169549185607107, 1301191633558497, 1661514101014240}, + }, + { + {5625132717515116, 5524850964392681, 4614069623317915, 3762859588443640, 4361835721816909}, + {3158923465503550, 1332556122804145, 4075855067109735, 3619414031128206, 1982558335973171}, + {303213233384524, 2061932261128138, 352862124777736, 40828818670255, 249879468482660}, + }, + { + {3697491154222530, 4544214010492622, 4905703930515359, 4988733897248726, 6163038950957920}, + {856559257852200, 2760317478634258, 3629993581580163, 3975258940632376, 1962275756614520}, + {20057458979482, 1183363722525800, 2140003847237215, 2053873950687614, 2112017736174909}, + }, + { + {2961281310713750, 5035281843536219, 4820563396802425, 4066115702139011, 4762159869794599}, + {2228654250927986, 3735391177100515, 1368661293910955, 3328311098862539, 526650682059607}, + {1053447823660455, 1955135194248683, 1010900954918985, 1182614026976701, 1240051576966610}, + }, + { + {3576347446000839, 3504021369715234, 3286921249007623, 6268908633911267, 4898262353027354}, + {2053850994061963, 1755999209417110, 2842496597997123, 1978798188794297, 1107741233360060}, + {1587558591633082, 1224310153016076, 373416710356490, 733639236443698, 365919571874338}, + }, + { + {4922046667787666, 5384603941382862, 3355282705253058, 5052638190916511, 4442324355401649}, + {716350205934888, 1153032590403764, 2797021656648850, 1143194352934997, 4271302979058629}, + {1588274760900072, 933817618340883, 731655082380959, 688238385999711, 637984915480250}, + }, + { + {4217060480329358, 4374528391636951, 5478312030233942, 5051281083802439, 5405881257383323}, + {413138784837996, 173345891427747, 1873100191622562, 899752727618929, 3454430648436331}, + {830072102529414, 1185948406051604, 1521170049452316, 1259798181998483, 735064905966282}, + }, + { + {5515669600102047, 5759134783811579, 4357089500282138, 5244472517255288, 5695631524373921}, + {2842166480737527, 2947367283673209, 2706356593419314, 2971106642583260, 2444234893549177}, + {1396164055858898, 2228551364195726, 611382817170935, 1662418665433346, 1079098567119990}, + }, + { + {3828208352345746, 5742603493540025, 5912515684826959, 5415942702105867, 4409414272784258}, + {2895166868245672, 3153594867376981, 2883799413649215, 1877187137914547, 1124004944737352}, + {1249379796419407, 1201460644559526, 1259226742776869, 583948750717161, 1178519968480157}, + }, + { + {4715510278636375, 4324771002227588, 4218850944267831, 4037187367673896, 4505301806813551}, + {660737143139077, 1635830759165556, 795647058595473, 2117049403264300, 2692853476865573}, + {1654844956375931, 767321709128720, 475080629455448, 116932684758291, 96451917556060}, + }, + { + {5797033177541322, 5021581754974953, 4978830133961786, 5973534325336756, 4105099431310062}, + {1777561190222404, 3757586069945925, 2868096822929350, 1968746982919962, 1089633650980574}, + {833672890421142, 647759906668054, 572517465546269, 402134952667751, 2083275174687780}, + }, + }, + { + { + {6352542060466074, 3833809696215741, 4101092554705390, 3320298136988035, 4253202043484731}, + {1957943897155478, 1788667368028035, 2389492723714354, 2252839333292309, 3078204576998275}, + {1528282417624269, 2142492439828191, 2179662545816034, 362568973150328, 1591374675250271}, + }, + { + {4265077968872559, 2914460285039701, 3045781039391514, 4915306233356239, 5308090560495285}, + {2411826493119617, 2484141002903963, 2149181472355544, 598041771119831, 2435658815595421}, + {2051892037280204, 488391251096321, 2230187337030708, 930221970662692, 679002758255210}, + }, + { + {3713635732994642, 4207056293821675, 4684465815183558, 6055578880035022, 5061343489334444}, + {1530723630438670, 875873929577927, 2593359947955236, 2701702933216000, 1055551308214178}, + {359179641731115, 1324915145732949, 902828372691474, 294254275669987, 1887036027752957}, + }, + { + {4324702538941745, 2563932266428659, 4813530513012704, 5499843939988947, 3842301114037549}, + {4295071423139571, 2038225437857463, 1317528426475850, 1398989128982787, 2027639881006861}, + {1397254305160710, 695734355138021, 2233992044438756, 1776180593969996, 1085588199351115}, + }, + { + {4202522275076530, 6411445226225292, 4074557295320773, 4373367518435491, 4577411558841716}, + {2692366865016258, 2506694600041928, 2745669038615469, 1556322069683365, 3819256354004466}, + {387139307395758, 2058036430315676, 1220915649965325, 1794832055328951, 1230009312169328}, + }, + { + {3379372614866712, 3476543574256943, 5779819517217769, 3781538535387827, 3841619480557100}, + {1765973779329498, 2911143873132225, 2271621715291913, 3553728154996461, 3368065817761132}, + {2181229378964934, 2190885205260020, 1511536077659137, 1246504208580490, 668883326494241}, + }, + { + {4227237865914097, 5575401147370301, 5098251926594813, 4129497466354055, 3741435180672532}, + {2689666469258543, 2920826224880015, 2333696811665585, 523874406393177, 2496851874620484}, + {958592545673770, 233048016518599, 851568750216589, 567703851596087, 1740300006094761}, + }, + { + {3792569420294954, 4400089757531324, 6101403783497940, 5734203344054362, 3067223272494699}, + {2014540178270324, 192672779514432, 2465676996326778, 2194819933853410, 1716422829364835}, + {1738560251245018, 1779576754536888, 1783765347671392, 1880170990446751, 1088225159617541}, + }, + { + {4447695422728303, 2418292515870024, 5595971144063629, 5081870838292807, 5209525481880645}, + {2916521632160477, 2343112140697014, 1601700300762337, 1763148914953177, 2708190975156259}, + {1339021042945816, 1840804708066696, 877961221559635, 1281458842745501, 1950851850845276}, + }, + { + {4786922334540966, 4955024641438784, 2989160972656404, 5186429632708936, 4984389249074409}, + {1020393680308960, 3834711966547082, 2322726956159582, 995949551108034, 3035172379117141}, + {2248087612518599, 173333799263920, 1744928838552182, 957368524885377, 1722980339454003}, + }, + { + {3826226586501329, 4985391470235567, 3706778387862153, 5001039432994919, 3643485069381971}, + {2453664361158331, 3658664111645897, 2133047286876873, 2891246599919261, 1077039773701841}, + {1403674776792037, 176114870970230, 204752269254815, 823265703401663, 973549049711641}, + }, + { + {4428694302478430, 4279516097530892, 4558829707092394, 4506689423374814, 3060727770678082}, + {3511507258617268, 2341694334736402, 3023178443373630, 4119452783133958, 1541883672814480}, + {273175012476053, 353915697751570, 1920076197363975, 2096923665433891, 694182114426694}, + }, + { + {4184692084971979, 4134060280811983, 3170779668973105, 4456307003709940, 4308299286729100}, + {2273158812011175, 3253770145986191, 1455430838863125, 1701216872600126, 1994907074166318}, + {854928709890819, 247698160098706, 1293104197995963, 648230677212306, 784063325867838}, + }, + { + {4504036913969323, 5450574207835078, 6042071388766678, 4918868602774744, 5356088910233627}, + {2995726671480383, 3106924626287182, 2718750693945174, 3268809265740618, 1129470954185503}, + {2104894828289916, 873144584667742, 506537740149646, 646077767532773, 1966868865211605}, + }, + { + {6048446108790732, 5524115631172029, 4165751037432881, 4331639016561072, 5291322591785068}, + {2269347023399866, 1910686315635227, 654955394153571, 2857416503175088, 847850165913280}, + {836953051260559, 1769743545147988, 699239118029628, 825806019782225, 1990070083297713}, + }, + }, + { + { + {3395265304118584, 3783994539881306, 5596876372865192, 4984641333486582, 4373205247246409}, + {2911103727614740, 1956447718227572, 1830568515922666, 3092868863429656, 1669607124206367}, + {1686424298744462, 1451806974487153, 266296068846582, 1834686947542675, 1720762336132256}, + }, + { + {3458195995174227, 4836757775805549, 3654433306506668, 5623690819092521, 4197273928235755}, + {3141016840074207, 3295090436969907, 3107924901237156, 1669272323124635, 1603340330827879}, + {766720088232571, 1512222781191002, 1189719893490790, 2091302129467914, 2141418006894941}, + }, + { + {5441759705376431, 3673576132738420, 4193443048427021, 4683601810691313, 3666180150435792}, + {2671463460991841, 1998875112167986, 3678399683938955, 3406728169064757, 2738338345823434}, + {398001940109652, 1577721237663248, 1012748649830402, 1540516006905144, 1011684812884559}, + }, + { + {3248461355092589, 5959477015323422, 2996112620542523, 4642813523567241, 5503882535918283}, + {1653276489969611, 2257881638852872, 1921777941170835, 1604139841794531, 3113010867325889}, + {1450817495603008, 1476865707053229, 1030490562252053, 620966950353376, 1744760161539058}, + }, + { + {3213965769821056, 5620199287619286, 4685689805377309, 5959205094392245, 4699653216173778}, + {2811528223687828, 2288856475326432, 2038622963352005, 1637244893271723, 3278365165924196}, + {796863823080135, 1897365583584155, 420466939481601, 2165972651724672, 932177357788289}, + }, + { + {4468743695984567, 4898440950560817, 4474456712004917, 5061786181321024, 3329036690710436}, + {877047233620613, 1375632631944375, 2895573425567369, 2911822552533124, 2271153746017078}, + {801118384953213, 1914330175515892, 574541023311511, 1471123787903705, 1526158900256288}, + }, + { + {3726318200450545, 4012593435854444, 5660999417843231, 3874664121744144, 4669027921793287}, + {3201417702772463, 2207116611267330, 3164719852826535, 2752958352884036, 2314162374456719}, + {1961673048027128, 102619413083113, 1051982726768458, 1603657989805485, 1941613251499678}, + }, + { + {3486506407007189, 5586943518586412, 3150073788000181, 3892658932084745, 4661178025941644}, + {1401939116319247, 2587106153588320, 2323846009771033, 862423201496005, 3102318568216632}, + {1143483057726416, 1992614991758919, 674268662140796, 1773370048077526, 674318359920189}, + }, + { + {5249032546684913, 4376477734728695, 5192833668695386, 3879528383130666, 4673544232718438}, + {2001586827113779, 3745189534067065, 1944288247515270, 3801531181100442, 2035001711257644}, + {1821331151892312, 1302058705892077, 1823533497142581, 1477427445977593, 1256884978338733}, + }, + { + {3816568398797501, 4280523703434080, 5575370580457579, 6556193442157265, 5400032142723120}, + {3676887960291627, 2721875544375886, 1949386962401535, 2062484445640651, 1831148391448868}, + {1098621584553762, 479766126028979, 50128556582829, 1793185955386011, 957643491878541}, + }, + { + {5624964178025902, 5881679035334285, 5337334188128135, 3373245272349238, 6030340196395357}, + {1686491261026354, 2930481776329103, 2527067703865047, 1879410757156738, 2416602562794561}, + {1954783342191961, 1776196854323048, 1073865783628317, 126006585556188, 551111053703277}, + }, + { + {5863020639436884, 5014608403303800, 3487461172336056, 4625089084538493, 3002443292699384}, + {1844293295362196, 3776383490821424, 1827935191421176, 1761145652561373, 2654244832682184}, + {2163920127813722, 1809848067831371, 1226486593520438, 6568253441272, 318658165188350}, + }, + { + {5229528028782988, 3740161041125714, 3628427289315213, 5072860979211871, 5962952384148406}, + {1112209403436618, 3603724598892882, 3004743983803641, 1636637612372587, 1910870598142670}, + {1139920697586991, 989775023258908, 1562720488536799, 1457380545841604, 910097567659210}, + }, + { + {3041059796685021, 3926553231646481, 4587262528244901, 5282743084605635, 4777345624727557}, + {2431004626164709, 3854783312160059, 3273298459729433, 3386841277003151, 3777213922766615}, + {295894405919626, 1325594150172422, 673838771367222, 604280180076012, 485577818727658}, + }, + { + {3793091552131313, 4374989255749447, 4298473526457935, 3586546830561382, 4785727997920673}, + {3556189185732659, 4013352737062889, 2854416081619439, 1896415948116520, 654670146226537}, + {139962000945005, 2246840272939065, 40902718655534, 1533074280944617, 1032382655251714}, + }, + }, + { + { + {3758431901841840, 4379281609207426, 5017412546860750, 4644243343298864, 4946076247670812}, + {1835401379538542, 173900035308392, 818247630716732, 4013900225838034, 1021506399448290}, + {2056683376856736, 219094741662735, 2193541883188309, 1841182310235800, 556477468664293}, + }, + { + {4597695873914911, 5426082008537486, 4528117456116057, 4391230322227749, 4348938857916251}, + {3566819241596075, 1049075855992602, 4318372866671791, 2518704280870781, 2040482348591519}, + {537697207950515, 1399352016347350, 1563663552106345, 2148749520888918, 549922092988516}, + }, + { + {4827183563480027, 4225372812262903, 3444018843651805, 4582954431755768, 5877642652930841}, + {1747985413252415, 680511052635695, 1809559829982725, 2846074064615302, 2453472984431229}, + {213277331329947, 416202017849623, 1950535221091783, 1313441578103244, 2171386783823658}, + }, + { + {6124178045615487, 5044634958558963, 4487585538139111, 4406665622773445, 4226427082437073}, + {2440888617915079, 993969372859109, 3147669935222235, 3799101348983503, 1477373024911349}, + {1346805451740245, 1350981335690626, 942744349501813, 2155094562545502, 1012483751693409}, + }, + { + {3326465926121696, 4752879014110088, 3426137740310600, 3810813345691727, 3724087589204368}, + {2107080134091762, 1132567062788208, 1824935377687210, 769194804343737, 1857941799971888}, + {1872620123779532, 1892932666768992, 1921559078394978, 1270573311796160, 1438913646755037}, + }, + { + {3280128640868324, 3962843103655104, 3602632284060180, 4174964503289574, 5999255996217406}, + {3089190001333428, 3264053113908846, 989780015893986, 1351393287739814, 2580427560230798}, + {1900828492104143, 430212361082163, 687437570852799, 832514536673512, 1685641495940794}, + }, + { + {5679936010824454, 3977277108025017, 4516300250042949, 2929815522503454, 4666323705890374}, + {3094432661621646, 605670026766215, 290836444839585, 2415010588577604, 2213815011799644}, + {1448049969043497, 1789411762943521, 385587766217753, 90201620913498, 832999441066823}, + }, + { + {3515424710267724, 5606202029043823, 5029901811084866, 4403815652814045, 3735639122175257}, + {2767886146978542, 2240508292484615, 3603469341851756, 3475055379001735, 3002035638112385}, + {442991718646863, 1599275157036458, 1925389027579192, 899514691371390, 350263251085160}, + }, + { + {5324956849177719, 3429271620480873, 5513927382492506, 4069478768490913, 4487763984887828}, + {1005736577196489, 1703778335600507, 1256787933200658, 1273583601164519, 4154995520392582}, + {1181460621741892, 515102888370257, 660560226785527, 1121970691511835, 1609869229541589}, + }, + { + {5276536763892090, 4684953471965519, 6139261731383556, 3763310979241977, 3999629994843744}, + {3197840386614072, 2673429719431285, 2328666993391622, 1601604658039797, 754388419948612}, + {2189230067083086, 574898679774723, 1093556583385601, 1590603941933467, 1876625616519950}, + }, + { + {3739860822512771, 4605148533211466, 4174048138272099, 4387338734269228, 2880424850917010}, + {2359748764236743, 2750393191088290, 1526008165088803, 1669725971211966, 2233234520219112}, + {42208074517808, 919916618772548, 1864146060012263, 405874007551625, 167276017170589}, + }, + { + {4682022353746882, 6009429539947866, 2947942480787000, 5087407628431820, 4667285753466106}, + {1939674698340922, 2060465757190214, 2418157875657274, 1687699771189262, 236132178171812}, + {674205207435332, 837990472116301, 1170756550883494, 611962296440926, 1446026806940794}, + }, + { + {4797835609201808, 3649645875831679, 5195894411777247, 3424984715982399, 5322304250778016}, + {3454576586408064, 2256192384569215, 2864444376813541, 2134820396191597, 1047034985188490}, + {1582224761030916, 260261512990929, 1131518591198333, 94648525453241, 270083062170054}, + }, + { + {5595107036983877, 4494054900752656, 3263812520261324, 5044525307237686, 3722017695712965}, + {1188525422166779, 3589855283768506, 1782193012394260, 2155228647422980, 3120862178456839}, + {1981581840102891, 142303636665554, 2039535378650111, 1181156234198923, 1967834468546111}, + }, + { + {5706915977082882, 3753081378072469, 2510190141605996, 4045103810631250, 4992176450645285}, + {1947964231400572, 2169451112529873, 2463002605422706, 3228930307152278, 597158871609891}, + {1385883488372791, 1890958046379947, 2126979282588918, 17215697802179, 562809648160246}, + }, + }, + { + { + {6060806645993160, 4844231320170097, 3729525723161433, 2866535765304666, 4285036937432013}, + {1689713572022124, 2845654372939621, 3229894858477217, 1985127338729498, 3927868934032873}, + {968764929340557, 1225534776710944, 662967304013036, 1155521416178595, 791142883466590}, + }, + { + {5626780938473300, 5189175572245936, 2759405279195173, 3664390275802720, 2819817138913873}, + {1487081286167458, 3244839255500182, 1792378982844639, 2950452258685122, 2153908693179753}, + {560258797465417, 2193971151466401, 1824086900849026, 579056363542056, 1690063960036441}, + }, + { + {4383124982462505, 3428436472114155, 6260522268883476, 3642043430861258, 4218124990723630}, + {1918407319222397, 2605567366745211, 1930426334528098, 1564816146005724, 4113142195393344}, + {2063958120364491, 2140267332393533, 699896251574968, 273268351312140, 375580724713232}, + }, + { + {4285699823073660, 3996702683556035, 4442379901602887, 6453074611624616, 4734649381664242}, + {2024297515263178, 2668759143407935, 3330814048702549, 2423412039258430, 1031677520051052}, + {343868674606581, 550155864008088, 1450580864229630, 481603765195050, 896972360018042}, + }, + { + {6032529693711055, 6108603534430070, 3306860895022921, 5961918729318160, 5737795472583636}, + {2151139328380127, 2566545695770176, 2311556639460451, 1676664391494650, 2048348075599360}, + {830430507734812, 1780282976102377, 1425386760709037, 362399353095425, 2168861579799910}, + }, + { + {3935550130401342, 5155878315656623, 3473598574878785, 4149160495161916, 4823257793397838}, + {3407562046415562, 980662895504005, 2053766700883521, 2742766027762854, 2762205690726604}, + {618808732869972, 72755186759744, 2060379135624181, 1730731526741822, 48862757828238}, + }, + { + {4481933078376341, 5067550582461519, 4294715789111644, 5330913983663967, 5175628607523309}, + {3714971784278753, 3394840525452699, 614590986558882, 1409210575145591, 1882816996436803}, + {264204366029760, 1654686424479449, 2185050199932931, 2207056159091748, 506015669043634}, + }, + { + {4317070754263612, 4535076723640848, 4810021506483985, 4685558271307180, 4158905350371329}, + {1784446333136550, 1973746527984364, 334856327359575, 3408569589569858, 3275749938360725}, + {1496516440779464, 1748485652986458, 872778352227340, 818358834654919, 97932669284220}, + }, + { + {3850207796558603, 3727422831028406, 3797434477252654, 4293213262701836, 4516227523843066}, + {2048146359190201, 2164495845485630, 1987127118350888, 3702022928556186, 1248356726771194}, + {1517919028451878, 1390653207300047, 480997424969526, 463880049786815, 1566994328535414}, + }, + { + {4207292859242158, 4439237956877375, 6466630861755493, 6117169411664878, 6203775439423042}, + {2630289459558480, 2051409995957989, 2137890426251559, 2865150520767226, 2183646505352378}, + {250950165450403, 2108575357747549, 1858230594483734, 184468003072844, 1358638013010624}, + }, + { + {4795165927742161, 3556821674590553, 4452234877886028, 4063350508177236, 4357194618603124}, + {1363161060275889, 2019577584627825, 655391965916958, 2833727353647238, 2341948580614770}, + {1778982619924496, 1328609079558951, 1163827266617015, 1019320353990254, 830400209170522}, + }, + { + {3688756718408583, 4561393289356786, 5750092980695080, 4477840229539135, 3932387371938841}, + {891039147350711, 498786796467410, 3025350790192290, 652448826471937, 3394872208963829}, + {913282769158846, 347533899935257, 99606006705773, 1452035970297517, 2212487011762079}, + }, + { + {3066351608928554, 4959266561713426, 3505484480779672, 3313237988086280, 3214107063996871}, + {2440372328053980, 3986555651364494, 2478020726949882, 3029257951861872, 1322928669372349}, + {1259703414196061, 804804682694258, 2147323977049515, 252131006189623, 2246814133555350}, + }, + { + {4603288585029083, 4275494842669350, 4559975392494094, 5326825482142171, 4885471931566349}, + {616470521493849, 390707946935204, 1334622907385598, 2029831529830923, 2813735341554671}, + {1307353080865175, 1065210115652369, 1698012640184922, 2095589265946492, 688919666182564}, + }, + { + {4119409763828209, 5174415249772511, 6589359183715483, 3474134685034925, 3261800548024222}, + {3800663179733707, 1510662538907767, 2305029203181277, 1120480520235783, 2745749397969076}, + {959187641997964, 1919963359331922, 1067802756608566, 851276549968152, 2180947835690309}, + }, + }, + { + { + {5516816602304168, 5042521547053092, 4167576536206804, 6246422068954372, 4138350501601902}, + {2723435829455580, 2924255216478824, 1804995246884102, 1842309243470804, 3753662318666930}, + {2094270000643336, 303971879192276, 40801275554748, 649448917027930, 1818544418535447}, + }, + { + {5719674169295574, 4553720561304003, 3817628817819056, 2973527969819827, 4852805692036683}, + {2241737709499146, 549397817447461, 838180519319392, 1725686958520781, 3957438894582995}, + {948617110470858, 346222547451945, 1126511960599975, 1759386906004538, 493053284802266}, + }, + { + {4357186931049660, 4248263218811680, 5806608241664995, 5355507743318703, 5857341677159129}, + {1454933046815146, 3126495827951610, 1467170975468587, 1432316382418897, 2111710746366763}, + {750300956351719, 1487736556065813, 15158817002104, 1511998221598392, 971739901354129}, + }, + { + {3486884278433110, 3417910960117329, 3997194671566838, 3657316287568287, 4508063131522112}, + {1874648163531674, 2124487685930551, 1810030029384882, 918400043048335, 2838148440985898}, + {1663810156463827, 327797390285791, 1341846161759410, 1964121122800605, 1747470312055380}, + }, + { + {4458441089863460, 3942387623406751, 3851973436510373, 4407895911319668, 3358622222233463}, + {660005247548214, 2071860029952887, 3610548013635355, 911703252219106, 3266179736709079}, + {1344788193552206, 1949552134239140, 1735915881729557, 675891104100469, 1834220014427292}, + }, + { + {5125820669443841, 3461946287724414, 3994046236028930, 5907438988749520, 4920789118266230}, + {1920949492387945, 2410685102072778, 2322108077349280, 2877838278583064, 3719881539786256}, + {22727256592983, 168471543384997, 1324340989803650, 1839310709638189, 504999476432775}, + }, + { + {3589266475777094, 5791244982040267, 6521619274146678, 2903981043059491, 5401611380582210}, + {3565040332441556, 1721896294296941, 2304063388272514, 2065069734239231, 3056710287109878}, + {1969792547910734, 779969968247557, 2011350094423418, 1823964252907487, 1058949448296945}, + }, + { + {5777164948769480, 3890309495649820, 5262835493859430, 5169614751717201, 5401583088313899}, + {2459143550747250, 1118176942430252, 3010694408233412, 806764629546265, 1157700123092949}, + {1717263794012298, 1059601762860786, 1837819172257618, 1054130665797229, 680893204263559}, + }, + { + {2942680342150880, 4278613828995852, 5350213167690156, 2989120782966715, 4123142629949771}, + {2556444502235146, 1613361869622030, 1402717375340694, 2348339985765731, 3489511500408293}, + {1426750262638336, 314863572574246, 1394348337483702, 1967765724676815, 1262927622887481}, + }, + { + {4948972567610721, 4760459340435499, 4508373064131856, 4400791580495755, 3326118030989422}, + {2602109836867459, 1003276938441793, 244450874677932, 2495574856155249, 3110870831093824}, + {1089876164348856, 610853718362589, 290946077126125, 1189633635903067, 238116851513210}, + }, + { + {5818313990376412, 3745131403850386, 4984633161305300, 4588134365279068, 5605706152381173}, + {2574353462387544, 1744531678913296, 2081810750651984, 1255482175291668, 1579377192487289}, + {1077984189936462, 1101581309304165, 229118769946835, 213129071862971, 1105903869282826}, + }, + { + {4244657319305304, 4848112240284328, 4808999745724375, 4645297205085174, 4469873257565411}, + {2568686941901236, 1277107033850968, 2743723193537219, 3580901504461986, 430697021449829}, + {5110283730621, 236925008060043, 590130982419942, 541274580551940, 2155487465178420}, + }, + { + {4504922761302740, 3620992509914934, 3198533798350925, 3770782329534318, 5363163230411568}, + {275387113122210, 3501532982637668, 2704624275342757, 1489585626413894, 3573009822045302}, + {1859877583133149, 1445451213294944, 309288119160981, 1843441717427399, 584114977316234}, + }, + { + {4103673694186728, 6461574165907240, 3718162222127163, 6247603847194471, 5772831446786927}, + {2087653679988656, 2238424089144458, 2130407033226307, 1889280872742259, 2146873922212313}, + {500701236542790, 1839091700792145, 218488889984877, 1301749778593414, 614810966957821}, + }, + { + {4649730463510780, 3151390162038927, 5365410818081747, 5007340477551264, 5551016597277571}, + {2300360039943938, 1529233553127717, 3500096717284879, 3664531564773424, 3173693672061933}, + {882756809520167, 998774482479105, 593908492257531, 1132796830151366, 1780707297956298}, + }, + }, + { + { + {4583071810090063, 6354729884420668, 4077544622618353, 3073467147166315, 5285394920882441}, + {2237039662793603, 2249022333361206, 2058613546633703, 2401253908530527, 2215176649164581}, + {755822026485370, 152464789723500, 1178207602290608, 410307889503239, 156581253571278}, + }, + { + {3747179848085639, 4828649103787668, 4549946522264427, 3805208654040102, 5332579729206178}, + {3669985309815545, 2736319981413860, 3898537095128197, 3653287498355512, 1349185550126960}, + {1280337889310282, 2070832742866672, 1640940617225222, 2098284908289951, 450929509534434}, + }, + { + {5758557848470941, 5656835588370337, 3194707518654080, 2888905217772639, 5652892897517762}, + {2659503167684029, 2378371955168899, 2537839641198868, 1999255076709337, 2030511179441770}, + {894249020470196, 400291701616810, 406878712230981, 1599128793487393, 1145868722604026}, + }, + { + {4956087140669123, 3603920362709815, 3425295697596203, 4250911519607256, 4870927757824721}, + {3749755063888563, 2361916158338507, 1128535642171975, 1900106496009660, 2381592531146157}, + {1717539401269642, 1475188995688487, 891921989653942, 836824441505699, 1885988485608364}, + }, + { + {4274232174887052, 5592415718055546, 4229643212225114, 4106634029575971, 5067838489399852}, + {3493583935107776, 2439136865632830, 3370281625921440, 2680547565621609, 2282158712612572}, + {938868489100585, 1100285072929025, 1017806255688848, 1957262154788833, 152787950560442}, + }, + { + {3546872176125197, 5434827532059909, 3607531246326933, 5425835363204530, 5395826856780703}, + {3119119231364171, 2872271776627789, 2477832016990963, 2593801257642876, 1761675818237335}, + {1680989767906154, 535362787031440, 2136691276706570, 1942228485381244, 1267350086882274}, + }, + { + {2787309244260446, 2798685347422569, 6028275236918294, 4389895566536949, 3512537903582074}, + {2617818047455756, 2684460443440843, 2378209521329782, 1973842949591661, 2897427157127624}, + {1159906385590467, 2198530004321610, 714559485023225, 81880727882151, 1484020820037082}, + }, + { + {4265412029331945, 4082570389605622, 2787935123905079, 2861072139265641, 4774283971865508}, + {1377485731340769, 2046328105512000, 1802058637158797, 2313945950453421, 1356993908853900}, + {1237542585982777, 2228682050256790, 1385281931622824, 593183794882890, 493654978552689}, + }, + { + {4433747840806046, 3721621780348463, 4999137013220096, 4950695012032930, 2963731882329120}, + {3700733741689868, 2019165860436683, 839545028551310, 954045289946680, 2857671609142350}, + {2031235379883797, 946220755552074, 1457648474415011, 1222951728743327, 1610191601040290}, + }, + { + {4162295633314539, 4747504508371898, 5420102803358852, 5241263790326999, 4652112494046944}, + {3713236670706339, 1708249553383010, 1441184960961852, 2138372449656361, 2208801341603864}, + {743176047113998, 1210025633688996, 1298930577649249, 2241929289171655, 319185600078644}, + }, + { + {2463674019917897, 4802840710289795, 3812247475965604, 5281339404908102, 6114735096224475}, + {2361755477281753, 3920079557094249, 1772761852174940, 2188727617473580, 1972330964627961}, + {2224894613062235, 459022333460366, 853633232091964, 42662368548958, 1428459390829900}, + }, + { + {5876939711261840, 5483557082287477, 3340896169956977, 4741202975388493, 3246978129870096}, + {1888400628800904, 3246442970371919, 2048876033526183, 418388094414663, 2174354817875660}, + {1865410028261408, 627467389699032, 146077987303115, 1698467014229834, 2014393109530681}, + }, + { + {3339126822971782, 5967460547143544, 4911389289674917, 4202215034765918, 5578073611339204}, + {2670644791837462, 2651763434193316, 2285020046276825, 2227807589256768, 1464013488829088}, + {1806473647942365, 538787999504182, 512973154409687, 1944932181085518, 1069910541821032}, + }, + { + {2634758329364868, 4859512915801802, 4928387675794414, 4438135586288705, 5912306986153546}, + {2593937978996354, 2409464365976668, 2076140577147016, 4427101675063297, 1879995664155906}, + {407209884855019, 2088464831333939, 2111856537862679, 1631244096914416, 1074707055277992}, + }, + { + {4379690451347501, 4147722372858437, 6043474882489476, 3830885552726038, 5483938823325814}, + {502401202015803, 2110371415921011, 2529666734456328, 2767243204597450, 2341774206366416}, + {1547018311600067, 615783499206767, 485547569767288, 1517514580034299, 457611163959317}, + }, + }, + { + { + {6197629798333913, 2753838380751446, 3942959878910714, 3201428133247434, 4778709814063561}, + {2299141301692989, 1891414891220256, 983894663308928, 2427961581972066, 3378060928864955}, + {1124515748676336, 1661673816593408, 1499640319059718, 1584929449166988, 558148594103306}, + }, + { + {3540740886557976, 3183587715724649, 4694330636229537, 4258659768352436, 5509531109592197}, + {1784525599998356, 1619698033617383, 2097300287550715, 2510065271789004, 1905684794832757}, + {1465551264822703, 152905080555927, 680334307368453, 173227184634745, 666407097159852}, + }, + { + {4674947851286115, 5166365727170883, 4965938571130991, 4970517390710808, 2908711106554361}, + {2111017076203943, 3630560299479595, 1248583954016455, 3604089008549670, 1895180776543895}, + {488623681976577, 866497561541722, 1708105560937768, 1673781214218839, 1506146329818807}, + }, + { + {5492578995360943, 3611529141261548, 3553634070931276, 4797740788199803, 4532947899647969}, + {2412225278142205, 950394373239688, 2682296937026182, 711676555398831, 320964687779005}, + {1434382743317910, 100082049942065, 221102347892623, 186982837860588, 1305765053501834}, + }, + { + {3443537155111802, 4098841848663610, 3634013358734303, 3291752209395695, 5292412486267354}, + {2205916462268190, 2751663643476068, 961960554686615, 2409862576442233, 1841471168298304}, + {1346965964571152, 1291881610839830, 2142916164336056, 786821641205979, 1571709146321039}, + }, + { + {4996047770903428, 2555904966356003, 4013566981986303, 4737382312068285, 4233095136791335}, + {787164375951248, 2454669019058437, 3608390234717387, 1431233331032509, 786341368775957}, + {665807507761866, 1343384868355425, 895831046139653, 439338948736892, 1986828765695105}, + }, + { + {5356490725342733, 4068788685039808, 6047372383097019, 3426510449207690, 4705728718095123}, + {3007896024559801, 1721699973539148, 2510565115413133, 1390588532210644, 1212530909934781}, + {1205281565824323, 22430498399418, 992947814485516, 1392458699738672, 688441466734558}, + }, + { + {3538981275120648, 2874522279215958, 5384551777942367, 2992835507144444, 4815164902360267}, + {3302427242100220, 1955849529137134, 2171162376368357, 2343545681983462, 447733118757825}, + {1003649078149734, 545233927396469, 1849786171789880, 1318943684880434, 280345687170552}, + }, + { + {3979319739304371, 3173810108641712, 3480574285526200, 3800294424979384, 3983333585686372}, + {2754253003222887, 2275532945921888, 3105484814506120, 2795714951112672, 3618146930096140}, + {247596824353536, 285396193673154, 686289557053653, 399468081949262, 249109087231255}, + }, + { + {2723125664053674, 3464927193948491, 5445834280101391, 5612124161635761, 2933099654237696}, + {2672303537844268, 2038791134455123, 3285678115022383, 2900519586434405, 1978453542160588}, + {1705147526637648, 1274613803517124, 1602845665731412, 1064073198174681, 1486788069078519}, + }, + { + {4077390367222227, 3800932136610666, 4160144924974108, 3561238039866711, 5997919559096945}, + {819031393505739, 2088275424107290, 1796234646803442, 1388708737598893, 2937136216710939}, + {944757498200715, 2015594302768299, 813220261760372, 867002775164821, 501734915431717}, + }, + { + {4424498381651951, 4370145165962473, 4303795913232316, 4673352990886468, 3539252307041619}, + {4258052207216187, 3760480385682185, 3206156011228824, 4088908699869294, 3011569459811111}, + {1187304510804619, 1384816718516187, 514455602674227, 392638325371554, 588228521113051}, + }, + { + {4219797873858933, 4958627631706417, 4511020049341415, 3218925652522905, 5097166154822735}, + {2789655568104153, 4038602698967181, 1701909246528643, 2824012136983963, 2400715389506309}, + {1130277769648576, 1946206888578836, 1343266549795147, 2083590873042325, 264064594409097}, + }, + { + {3196954689864360, 3706526534080788, 3004981697061754, 5970179548131185, 5036616655131901}, + {1526130015031824, 3071067159569878, 2312643039801922, 2400491084238785, 2092334718179931}, + {1720808849496600, 410920656934828, 864594478015792, 229141760159822, 2037677155881017}, + }, + { + {5749040666310109, 2431937887261040, 3580364244969437, 4752008191428386, 4786853370158738}, + {1789863266178839, 2202012677135000, 2680121806416879, 1722812656485926, 572531509973556}, + {2175782751601278, 1608407337873936, 816706054544173, 258225706360159, 1478818623198000}, + }, + }, + } + + @(private,rodata) + Gen_Multiply_Table_edwards25519_hi := [32]Basepoint_Multiply_Table { + { + { + {4593529082752461, 4913481494458327, 5105340091484689, 3450213179198615, 5857240422918567}, + {1412482364088803, 4062389850048069, 923779398567547, 2023841154802081, 2607705760638543}, + {1825728698698411, 497946242397168, 105715611816086, 968568072676853, 592999326381074}, + }, + { + {4495184218325789, 5289073944532264, 4218636788579151, 4988461406676953, 4686478434934441}, + {2949190053601679, 1979948019919136, 2471186112468189, 3573963359061221, 2216896082446061}, + {743917567567859, 870447381138646, 392196079309387, 1786878704882853, 1520161635991866}, + }, + { + {4744444857419634, 3144662423000833, 2994206879871174, 4901643262699391, 4923693546628412}, + {3089537977529994, 1888948267748045, 1789290739253972, 2597750135306899, 3142762081370390}, + {1764333363430455, 898309455329908, 1381444383468949, 620561614151766, 158377983927494}, + }, + { + {5941345963042037, 3413323930288462, 5115763723871020, 3248416926384114, 5473315945632476}, + {2269111888817457, 3231588657429924, 3123230781695332, 1299656894822778, 1180051671372258}, + {407953783981, 1647278360877740, 584504284208188, 906066565536232, 1341016264992694}, + }, + { + {2432346762050178, 4412970725632038, 3922648159237080, 3005442494216723, 4442116552336937}, + {2381425302937802, 1387820520945502, 3125986768243210, 2463732477189113, 4185413214185067}, + {286790540720370, 376171092666609, 1535083117539001, 143466475958698, 1595136426572043}, + }, + { + {4277560779811042, 4605632954767560, 4619246140475080, 3484505719110307, 4989421629835765}, + {2829089547178292, 1790256014216198, 1797656649279268, 2562891052522691, 493980515519391}, + {62004126799683, 1668357417723485, 402010966421038, 827662362499868, 620754241677270}, + }, + { + {3919396572999125, 3838658814915336, 3750839246192093, 3726674239012627, 3831212626851778}, + {1227888687423439, 2913177985394946, 2412294236854021, 2805130984485539, 1308360976872086}, + {1643929373822818, 59659873139317, 1165353313134798, 2003225793255085, 1953102130608543}, + }, + { + {4114999970343247, 3274056679568382, 3954123294817179, 3769263204026901, 4245068682986802}, + {898618711827587, 1314215296781160, 1302503840208753, 3496738988099889, 1698289814254750}, + {1392999845620760, 634309693840701, 815492400002072, 340703897996290, 2038693787178716}, + }, + { + {5214250944985254, 5214298257940112, 3933846341585754, 5894386249523842, 5770685254784336}, + {1934541077562988, 2222946897208970, 2251242179056732, 1591285457544104, 2747813687509638}, + {1016675746743198, 874873189324170, 1360411561434916, 1581878592793672, 1548505102984557}, + }, + { + {4769452847684060, 4913417142027999, 4139599914472574, 5727971436547121, 5162246544117082}, + {2615904366263746, 737197398316645, 1602932940462504, 2167985252180769, 2559960808783062}, + {1882565165016312, 1581434850744420, 1900290919378503, 1985953844470085, 2168995994538833}, + }, + { + {4554120491153816, 4069860035617982, 4340413640826432, 3211862620694644, 5818608637282174}, + {1544885394173400, 1572082853154176, 1022098019061266, 2766927411109582, 2094149897716596}, + {1565161503379169, 1009067677698409, 1758464151571027, 1604769367828030, 1207412426608003}, + }, + { + {4015717287484591, 5253478309058146, 4070204443357591, 4445835852409645, 4665111518123177}, + {2854833619490147, 3573568625503236, 536183518454769, 2263990573554737, 4044861757799243}, + {1398840935273285, 790488576331737, 33415624257391, 1637374533896247, 2205752015162110}, + }, + { + {4260625486568009, 4637770924690903, 6480430642402074, 5542751059832424, 5622960391176990}, + {3715812780985479, 1012232238437221, 2466752896497024, 2611001871592954, 2143269004082900}, + {1886046851462393, 702395341735300, 737389004224425, 943477665979721, 723064819201181}, + }, + { + {5226062982149706, 4477280967632100, 3095356746333787, 4567645348066962, 4846495995079660}, + {2444351104229624, 212638631228834, 2148034812459853, 1041500100514044, 3853826660522166}, + {273084620529389, 1358348733025497, 1143735162114047, 1683813303234668, 2163735276562013}, + }, + { + {5320556456798805, 4779694419891170, 4876824494496501, 5903452387913251, 4729985500450036}, + {3477960290395163, 2468183980355970, 2936794001231177, 2308108181814059, 1969019168758558}, + {2160310767797410, 344164523453241, 83129919763985, 1315117733435601, 945559910324390}, + }, + }, + { + { + {4363327446469061, 2701839972520523, 6527685309871122, 4056456213766895, 3880569128224647}, + {423177393665983, 2333545232306939, 2028971153113312, 2728157354019203, 3777730507929771}, + {1435691822393684, 1850026012837208, 2218717487026642, 81859254010196, 244808221751742}, + }, + { + {4151019106002309, 4804743010530635, 3757223421954400, 4766036153424381, 6107544569595961}, + {821837003520359, 4010299059749559, 2863227431802226, 4078726431091997, 2442551264358059}, + {1428688544729295, 109069749881410, 270830364539996, 1755181768867140, 162349670944771}, + }, + { + {4642027397896088, 5510058210884768, 4553756231196669, 5068441159437344, 6370925538331183}, + {2639121586131590, 2408957406336796, 3986248100020063, 2989795052558558, 2164082093074357}, + {309881142350067, 2106019349943259, 816133263871674, 2018031260992166, 1563425406132832}, + }, + { + {4395494918929745, 3011447404605211, 3917145931603942, 2759967153620848, 6379442527779295}, + {1498799085180043, 1744340656397133, 2064851197592072, 2429833814776112, 2145324400616903}, + {614788980313577, 1501513053451003, 1472055221710495, 1920317897819127, 2208964791748263}, + }, + { + {3560784093342680, 4994362478801752, 3255476397621627, 4445556105981925, 4954471675599246}, + {2150595732685700, 3115920468099904, 1640951315905191, 3465930332728019, 2707896919197916}, + {612249867445962, 159208429955777, 563950177277347, 561041393363217, 1270750549218661}, + }, + { + {4520180469529123, 3948074172686157, 4376189225516076, 4643310756673520, 5392469157863016}, + {2055033216205027, 2461832572574425, 2742691255886072, 1052243367900374, 2752099767668600}, + {1827261746419924, 1468053133723229, 425022050209163, 1161272199376693, 589189496874922}, + }, + { + {4438522896195229, 5675329383977909, 4882438618733149, 5825827678555036, 4497535703422370}, + {2005207463235253, 2001528853385595, 1602253387656095, 3101879903751894, 2375325873201006}, + {847469444462207, 318959830531389, 408429171873782, 1661514071773102, 909441091898553}, + }, + { + {4102243665939998, 4215863334856383, 4408378320450327, 4622977479151665, 4039328475229204}, + {2174491994328136, 493557282042709, 3602705188549813, 3249913558677235, 2748481399349512}, + {758760864397232, 1830650226770835, 326981597370189, 1345979301472296, 174985669849506}, + }, + { + {3114038058163888, 4115257910705954, 5304962337604028, 4942520420915651, 4570979005352829}, + {1616868525778916, 2685769941228860, 1500533033491414, 2505164168102999, 2558430770009979}, + {2210398167996316, 2029125611734957, 1527318329127090, 226535237621728, 757747276478551}, + }, + { + {5660830910412470, 4039716640180729, 3468207460119772, 4614076381392168, 2442548670982292}, + {2039774403824382, 3183946537620297, 1982095153858182, 1293586830098836, 2438708503064038}, + {1357360519318812, 2045548381976834, 1766860667272665, 994521972889149, 393185631961961}, + }, + { + {6365035791876788, 3957527440519852, 4079038689927398, 4319831229004816, 3943934873019078}, + {2354388502926730, 2133757859975250, 3747940319461896, 1050624714408746, 3528225787559372}, + {1423510913950154, 1407788039482417, 761922275972375, 1783557942644647, 464730646959110}, + }, + { + {5146524748212414, 5035960985653238, 5028883959266913, 3282581313444735, 3905335483972979}, + {950694750709616, 2909132113066654, 2692353349246129, 2659905077175497, 978201784181073}, + {1078796318026741, 2070782433025097, 1700702188087909, 1447652546515478, 2144027848464236}, + }, + { + {4464099897473286, 3120477039861599, 5276369827125764, 3567131403687606, 4968190256098962}, + {4085811716920468, 2616309657099343, 775638006452370, 3253232221169984, 2587485588949578}, + {1012423034220617, 2045371869775344, 1260737445157584, 1833095526522043, 1066294173319533}, + }, + { + {5773192417487042, 4517701999097386, 4655557572427803, 5616698382540752, 3371552871839388}, + {2877566362774786, 4401330265553408, 3208625757371899, 1399785720487456, 2531340752609210}, + {1640471888126382, 1014801052117284, 1178704129888297, 982929852576812, 981292318502343}, + }, + { + {6476452238344334, 4693003674971858, 5211751500997938, 4121351294551163, 3152533251509898}, + {2011936343019114, 1133486795463590, 2647435457385352, 2628952425675517, 2374701464984626}, + {1245374341789768, 946202302464214, 1370924353088231, 682015131982855, 1275473548530510}, + }, + }, + { + { + {4235275101318885, 4886666925763093, 3781172458925008, 4774837350787537, 4519905633498379}, + {4159636855200485, 3150221611558687, 1363421772307006, 4120947913313657, 252053503603381}, + {45902352975738, 1246446699820833, 173320410042641, 1542230462600972, 692910725375140}, + }, + { + {4486356754653352, 5011982731057698, 2800477110646540, 4053556040992402, 5267180761554575}, + {710084928405448, 2105676789486896, 2420643007484910, 2605134634368896, 3302669631199693}, + {2191680341805656, 1972509245077282, 981795995975654, 852454486043614, 1189735660434765}, + }, + { + {4897930998338676, 4879106310620971, 4682586750207620, 6132197307461033, 4233426591406375}, + {3995777047683048, 3833719910688599, 2444044754441170, 2232313400412571, 1420975603500953}, + {1931343025077052, 1393738210614177, 622857924319466, 1123524882306454, 1963513295012502}, + }, + { + {4596722267439639, 4583990247552416, 3156713638372258, 5382313953040853, 4261038954366871}, + {1850504730697909, 4381679472853618, 2011448898092860, 2090154061858281, 1857166627539261}, + {1509035496076582, 1583601071466027, 421912810565136, 1678479534084506, 2033502297510813}, + }, + { + {5152283091655165, 5421718026722430, 3997156174417042, 5001987993936945, 4470112047504242}, + {2238137325796915, 1165391281982950, 2048774700033766, 1309041739154703, 3204681887791132}, + {520151332809519, 1588829471961614, 2166353389460390, 404024831468766, 1335244071323823}, + }, + { + {4644249663336450, 4507701753581319, 3592182426303562, 3683130545837732, 4598992005732335}, + {2528474489315892, 2071299735249833, 2619224970187272, 3271465188079442, 1519932762444249}, + {1935180256227856, 250757393177447, 1959439731378182, 1297506762666169, 575184640324100}, + }, + { + {3998007896814392, 4789639746579090, 5427007329099910, 5561733860472916, 4408133776555178}, + {3563813919863414, 1486712601904120, 2979081810490774, 1807789883906314, 3546555493967378}, + {1438068615152094, 34949160848567, 1911746456436447, 1412684293826264, 1046374507505090}, + }, + { + {3358198622960838, 3580145032458308, 6285906454262483, 4413045221104222, 5178477068028319}, + {1493476678908308, 3319155065445914, 2088667670293411, 3599225826407670, 3126758502479837}, + {1428599160764785, 602821281250279, 1877258833313507, 333285098655770, 740310036947361}, + }, + { + {4437738381533964, 4511430215080912, 4623800711093479, 3858159170572748, 3792114250503483}, + {2569231089452712, 3770152139328302, 3269539085929031, 2383025095054982, 2248498609425137}, + {375535123602711, 924645774628115, 2045840727994073, 766250909414083, 1069698092749769}, + }, + { + {4435294130703604, 4934879817377642, 3598080452693711, 4396369088299832, 6194434176750643}, + {3899859044211942, 3058237431324156, 1669265990252613, 3808823766704698, 1861135005644935}, + {1352954153117419, 632457759471481, 85028188501619, 1852310027888311, 1569233778435479}, + }, + { + {4994607739226691, 3549890051462689, 4602469939135293, 5262974664864567, 5829540047772287}, + {1177033227220429, 1414982090591775, 1722841418062421, 3232176376002923, 1625133154241833}, + {478074309368979, 623121553345246, 885068774570210, 117698677138481, 109006840646140}, + }, + { + {3228583777446740, 3685494966163883, 3859895584510878, 4132565491795209, 3602518465644145}, + {1476961150268616, 2321154243603617, 737795879830106, 3409730959236147, 2062873179003703}, + {1329749333731727, 46254713998516, 373767480531871, 1933047124368118, 430092326122748}, + }, + { + {4068619402415723, 3955796447715502, 3724578346370833, 4337532310052478, 4252452058492903}, + {2483442550312325, 3615812911108800, 2858427288312835, 2135393495237610, 596254727540093}, + {8959488931169, 1768025271694380, 2157573235225770, 292082063715064, 330646837880843}, + }, + { + {5129020796146722, 5575913156701592, 4643684154507286, 5052753294034768, 4627882199658166}, + {1682783588724042, 2651474877391040, 965357158907406, 1910483514645702, 1644451034905796}, + {976078747227308, 1952905065031031, 949292862704054, 1492592732072346, 1010921457352162}, + }, + { + {4006410514827696, 4367363852356865, 3108174070644550, 3399842446392251, 3651405461962036}, + {2963842949036336, 1110443523197923, 2370466150687958, 2051405852060769, 1998735788124574}, + {629291283140720, 1484410172308977, 1230690465849055, 1563468011476927, 1425159147311735}, + }, + }, + { + { + {5585239563455525, 4610636723895044, 5486382712767880, 5982393863492935, 4225244847092674}, + {2874785617528993, 1037465406252872, 3296887051144680, 2286839599744315, 786748793374778}, + {1152063960223905, 1495207756023516, 403624329924470, 288757773501508, 634701074033280}, + }, + { + {4288607522123402, 4846896146524989, 4707359298406332, 5135207568875886, 3789334229842457}, + {2917883701302634, 2925085599109681, 4014710226846848, 912132719741982, 2714081319314151}, + {204576686258175, 1916354881141604, 2182213405559566, 836541881049164, 1393662576855498}, + }, + { + {5759444997810940, 4193440837630205, 2993247029494710, 4574723038696780, 5462384317223070}, + {1429326167011008, 3849536799125309, 2267296904452424, 3653618160132546, 2008400870233860}, + {1583200791922713, 581155064879634, 776749520692821, 82151283071376, 1733847968592305}, + }, + { + {5824219020582313, 4082583579489045, 5236716515955319, 4695754388607834, 4087929633004663}, + {2723457493421297, 2288104271131495, 1889807602666693, 571526543144584, 2151183507738315}, + {216379584390389, 359329711860756, 2220840445637019, 1935487238453911, 314381139238943}, + }, + { + {6324432942393073, 3866303010803999, 3020114267775140, 4943018510078408, 2696166744880915}, + {2134908988986295, 2962507202980067, 1681144354786142, 1678261855220080, 2165079891714277}, + {839191618399610, 151822034158330, 65272611705697, 938153274860627, 14360318777459}, + }, + { + {3118414549517527, 4750668024533744, 4389573074356623, 3687569756425714, 5338903547055573}, + {1473478682616257, 3633382583874766, 1909784146543313, 3349986706799106, 993668408613515}, + {364270308207016, 667227739516977, 122427551474936, 957177061876827, 1110258403339423}, + }, + { + {4256211953323020, 5655880769308112, 5147711084133693, 3515346496193909, 3997285326966523}, + {3727619641010474, 1181551732606964, 2600588673325403, 2469054944509579, 3385365618247725}, + {858909692206820, 61057235030988, 1105898533486092, 2202030785898301, 1422234761465688}, + }, + { + {4566369519147140, 3936942479708331, 4946651352770194, 5597737572220025, 4038789996699983}, + {1354120322856538, 3567014996875285, 3125649205892726, 3221576024570935, 3804405204938131}, + {758252632702114, 914226082256766, 434171717412081, 779505540917105, 51590353584795}, + }, + { + {4416135541622855, 4651530410104026, 3833614791957416, 6714310821280595, 6038964345007539}, + {3122819969959355, 1154192626573742, 3197914057178582, 2213609121110881, 2415518693959367}, + {1900133378602138, 577297894556411, 1975904780443420, 367702995667978, 971695605371773}, + }, + { + {5691739211507754, 3947360890016266, 6002902486092077, 2925962297163746, 4016189592321792}, + {1294948213915982, 1859247234048810, 2826079115120605, 2717796469093276, 1254328736376524}, + {1309911522909577, 1419436642934017, 1066858837800204, 1932820656369018, 1183788306261091}, + }, + { + {4373293771099146, 6029412334349101, 4603988300239160, 2779063318785645, 3538182001391078}, + {354784062716014, 2960996156215287, 737478213901140, 2448765213738437, 2443710778345986}, + {37327849111839, 283459044945755, 353933224898901, 1645288254358965, 1295375429334450}, + }, + { + {3677292170794769, 3117650463171591, 4719239493455234, 4362161261080430, 5717636534074846}, + {2663608264759869, 2105855808111831, 3795920549032608, 3588992239888494, 2806554331792318}, + {2036310356419974, 1862941437683537, 2122628002305950, 427826430955887, 291402007632220}, + }, + { + {3100956993836596, 4149163064979557, 5785693523916593, 4751072583726928, 3316412298207139}, + {2400585099524078, 845178406557315, 1712123121349035, 1518690883002826, 2049951197688491}, + {1805653877101595, 2041224626272278, 851063029095866, 1497753468187708, 1406228898239886}, + }, + { + {5260996583106547, 4838608075273405, 5366327117123850, 4982440029922063, 5698050109664171}, + {3676073115087797, 2883668558141193, 2503071760256012, 1640618939206309, 3001604944016599}, + {463897193543924, 852129647033757, 2185610432355774, 914719594057928, 342067349817283}, + }, + { + {3765905247379871, 6338723143452534, 4484328730824797, 5536719681008311, 2764639921823257}, + {1030797243840613, 2110720517661432, 1415230398470209, 2977956931886379, 1982287306571007}, + {2180738906930659, 1806951067450075, 36005005692651, 303238055099928, 190139573853343}, + }, + }, + { + { + {4025496086329564, 5028184343166740, 4304607245262868, 5977861543210978, 5975943712754890}, + {1773953341907106, 1826809791300708, 924874532383668, 2964289914628984, 3000051694532148}, + {1048828262296911, 626018299495748, 1536855937015065, 557005099579827, 205000143299648}, + }, + { + {3686649646834702, 3431735540864864, 3540678075266127, 4755119958422340, 4426577953698517}, + {941815577996700, 1930911276112812, 3001621068228165, 1967675522206374, 892948220720651}, + {39364207708032, 54077643340559, 47072300438335, 484490203728205, 330170579231628}, + }, + { + {4702834568738627, 3291678731018536, 5642230899808367, 3758646432111623, 5155137589229851}, + {1020447780607279, 2803044870250806, 1618835409581889, 2925650123847541, 2605959132875331}, + {1190283817822151, 29815862110548, 1401771831527381, 1814017508050437, 751331585591881}, + }, + { + {5109595606310342, 4551817631663576, 4964640045962167, 2568185324125768, 6484076393091613}, + {2159866514586362, 1758376548473728, 1635569740383557, 2443910752037966, 2023235829583533}, + {535848012622913, 543536404720769, 149076814975879, 1567757637416350, 1002851193383852}, + }, + { + {3815561875504886, 4987304354260221, 4882489851059671, 5118054256243381, 4641807084989976}, + {850247344591352, 3894610597706487, 1974409276090169, 1605973976114297, 3601811238228268}, + {66796032196982, 83108349878636, 1058512765854606, 355785880766958, 2173660513649027}, + }, + { + {5137434473036957, 5769675136285847, 5436511544403722, 4264839407576387, 4266175067727596}, + {1941123290917747, 2316977311376991, 2913763383192580, 1172954226263395, 1951085968954154}, + {1331723279107642, 360406964548232, 602431788387748, 1292398959539176, 347247628588850}, + }, + { + {5432516922132898, 3078886318864995, 4583513191179486, 5867019372106709, 3411264839291911}, + {2170226002806030, 1739335733478471, 4017472424997012, 2918660155665329, 2793865679796361}, + {245885669910192, 255454579697350, 869246923980317, 823008017430135, 2047987637517532}, + }, + { + {4988197221931747, 4124266159815332, 4025663002514467, 4403069876409057, 2825978174946111}, + {3615548446949869, 2386240595324376, 1969460953567929, 2939417927358269, 1831662708850445}, + {1325588019367749, 1763566216507756, 445592400440775, 1009027711126237, 1471076108623188}, + }, + { + {3535455324868691, 4187842716980314, 6000482158112321, 3740505414106560, 5271856051582847}, + {1181816564414671, 1156678021972118, 2682384137206273, 2260248858296388, 1100324256765571}, + {1487590095774723, 277659353917859, 1381509894936782, 1061130669028904, 1364761503808628}, + }, + { + {4778189969823672, 4001451898457449, 6113563635354943, 3279804336055010, 3551539211588960}, + {3358253142401746, 2070882729090991, 2076758122179069, 2612730216279296, 2875157527961954}, + {1082784010061460, 1534894036268453, 1852407202514802, 2109696474131863, 1530718911157644}, + }, + { + {4923904010378051, 4401333064112293, 4345896142363128, 4462036896398403, 4199434117360330}, + {3404425764066199, 790431937118435, 2117892820897492, 1747418170252123, 2322149428381644}, + {1548552607325007, 2020524571521392, 198565314654983, 490668591018400, 531050967405176}, + }, + { + {5145969570912646, 3496492300608685, 4069590843971303, 4335556955800239, 3325377629546533}, + {2623126033999932, 3437252355580701, 1673392257908819, 1954440682865467, 2560737733895255}, + {516406018439380, 1624367135427190, 1319745729116992, 1076628515910554, 819495581575694}, + }, + { + {4005978810673255, 3160053273427578, 4474659303213566, 4173935427495701, 5201857712754300}, + {843136030895887, 1929944939303616, 884551308418834, 1356687291240061, 2259204804361506}, + {1461715846997541, 2038281458208083, 2119767535863762, 636224052565171, 1712721429371389}, + }, + { + {4975731433879692, 3888553624589664, 5228917373823987, 5038386998880250, 4707655682255612}, + {3409114563124612, 1820064381354618, 2421007346773091, 3239920960596314, 3726969650504610}, + {475869807928836, 887669112822100, 481835223948027, 1468799954696850, 1370247723645687}, + }, + { + {5954383345631578, 3742995524386402, 3611065523713845, 4447231480190211, 4725820376570018}, + {1943063487159002, 2890245371286974, 2837035330843453, 1080549927676027, 867285909606140}, + {1413582027032622, 1273926892909999, 726179076119442, 699229594605794, 406422835715518}, + }, + }, + { + { + {4513888950241631, 3212738446973608, 4558390526464820, 4859080230791315, 5273416148656656}, + {1326059070986753, 1683859889439034, 3052200172327874, 3805600625804475, 3687690452819464}, + {1081752225631401, 201284952113932, 1619339403526661, 1533363030164674, 1727571790703503}, + }, + { + {4206177554516483, 5468031785191800, 5978090949319557, 4899439545685678, 3929672195094815}, + {3151535789445747, 1741766716299828, 1742063303545331, 2027626928190420, 2245203856982753}, + {868012933261061, 1472665613225898, 1744063644616181, 1350305502884983, 2227467074628670}, + }, + { + {4669057309967741, 5650515638764201, 3042033906165361, 4078124455841206, 5666341739515191}, + {3587030559572189, 2850528363281919, 2974216851298661, 3227895056003248, 1349661756105253}, + {1313383948772993, 1074655824143287, 20040386640896, 305794891855170, 2123092901229151}, + }, + { + {4199945629383318, 3594320984526977, 4229880092041671, 6384664478996443, 4732837782434517}, + {2744443256254860, 1013874505344583, 1972732629285783, 1936827407065469, 1830481951704579}, + {634737804354539, 422989080575800, 1774993942417585, 688011718282303, 581542014403477}, + }, + { + {2816888940207091, 3903781507184007, 3616069829367681, 5525450216549915, 3780846206608878}, + {2517199667227667, 856367096857961, 2630571629218547, 1768604592283813, 3688963458794126}, + {1683677903016217, 2036167240589310, 262287609979509, 977873833112269, 433284640623898}, + }, + { + {5477402921384451, 3117269161199628, 6049837891653338, 6034999812243824, 5356551064760510}, + {1755760392036121, 2130115351478138, 2694425247498002, 2043622709923142, 2338295058055586}, + {1425112218383847, 329346717672590, 378517748485393, 1806152114945447, 1211275024279312}, + }, + { + {3594715588472482, 3844045487620198, 4484578538777484, 3113667148844230, 4337495224693479}, + {1968587687914188, 2881021730370090, 1429009633828432, 2770076641127580, 2012343565772575}, + {1629969809602186, 1106234784906336, 863587490378700, 1792807263239898, 1429043938024750}, + }, + { + {5737804770941067, 5078013196347608, 3898224610791405, 4804530531188967, 3180800540121608}, + {1973106012015851, 2593923400059844, 833516958919695, 2182197879897069, 1721403407106648}, + {1591076166555979, 849361769125080, 1443799738863429, 166584794343739, 1861773413238536}, + }, + { + {5730227718465208, 5596273386383722, 4195854427433762, 4069266668520101, 4524280540784068}, + {1968981310480276, 1950975116204498, 2592307802896060, 3813918534870745, 2620661073133464}, + {936764653391291, 1452448249608980, 1312847510424692, 1846051928374105, 531372961271999}, + }, + { + {5549943196407418, 3432818760073271, 3449244033859606, 5283577488399029, 4864604608008479}, + {1733819728686816, 2936024966547233, 1590816041651632, 3163811004299109, 2676757470677367}, + {1319097278964637, 787422552977413, 1599496421811883, 1959379193761008, 1506646670818903}, + }, + { + {4227254412838170, 4548570321204425, 4285644009760393, 3751016940211786, 4098838617641914}, + {1732471582908700, 1866076266304485, 2819215151172481, 3074745073420508, 2774887501545996}, + {717261628309176, 1858796230699344, 551077134877547, 149402535309098, 2105648961714394}, + }, + { + {3871916223505114, 4749816457502813, 5358561311326743, 4112663885073414, 4137415642080692}, + {1127279535151728, 1199265744257977, 1248562495202825, 1868357952639788, 917052103965266}, + {25664888255034, 1628004430886188, 1439984389498414, 1961957176184883, 182596205772698}, + }, + { + {4179077756813138, 5647690538147405, 3274850245594335, 4319226212135161, 3864148139899748}, + {1739387701061410, 3112148637704823, 3028846916651989, 3700388643798173, 2412185850016002}, + {975143220058337, 825243809988211, 515186464897625, 1179464291552333, 2112614471328036}, + }, + { + {4947873049161087, 4901033700427489, 6675583808729484, 4941667050946228, 3120269525234559}, + {2996598747660015, 449189546044795, 2197501482114022, 3158206489499126, 2705800926920583}, + {96737353895103, 1534044505139178, 563303281603459, 407703386650348, 1821870774469537}, + }, + { + {5049500432849751, 6040441932911013, 5618655093441099, 5061587505104794, 3837175101097290}, + {2654088892951999, 2871006956063187, 1742690076584393, 921899537851044, 1870021525725886}, + {1637444308641066, 1472124432669136, 741811397216072, 1252880060061292, 423564866101658}, + }, + }, + { + { + {4796818337004571, 6222611117014093, 3083419469630983, 3862822099971652, 6509664209117283}, + {1171837083014025, 2516532715963947, 1770010974323603, 2517908022038722, 2020794083615321}, + {762321251771152, 1460210191529427, 2248797163104578, 217468651569622, 63003536153574}, + }, + { + {4259858178043342, 5554955317979561, 3911791110113593, 5525892988208900, 5545696994818748}, + {391588043113892, 2202456919563943, 3869688632614537, 2945959779196464, 2143606811138354}, + {719793864170869, 1411477466905009, 1515019021063010, 1483421690183889, 1704042941619334}, + }, + { + {3034963268199750, 5870224135513779, 4115305817554936, 5421579290342892, 3835694901998808}, + {2769635787032504, 2958323523618463, 1537480429839772, 1483278086593314, 1378968978067758}, + {1315034452637574, 1172434640681242, 1135533609020364, 253349230877293, 161211572823476}, + }, + { + {3942650253210285, 3918824117103583, 4001647299508483, 5240554545879312, 5035373070605317}, + {2659408003097885, 2049444491227493, 2594690944032877, 3421228755254048, 848234126951057}, + {437225545901468, 888271756229202, 903344393515123, 162913205438885, 1475178706291532}, + }, + { + {4287921885063088, 5041248821201299, 5585484729625036, 5534367719396511, 4532272822475758}, + {3707293450173872, 751219268219695, 1525065253586106, 2054680090861517, 1393874745922970}, + {1910711495320594, 321017884248758, 1651671690842787, 527123817162741, 847944616444202}, + }, + { + {3415231495445846, 4190597015532201, 4905073239386883, 4940927269911495, 5980840029199164}, + {1474221667712446, 3068688770339565, 1358088375247373, 1853329794010803, 2931295009606082}, + {70084211861389, 1248863300280704, 1009402227613886, 1445171656255193, 728732085908498}, + }, + { + {3340501878764401, 5410923356778271, 6030788584012822, 5594611759355304, 5267577702264329}, + {2869750492870027, 1153392601340917, 2754776472841130, 1100510641818700, 2870221151280913}, + {1481950048975238, 97096668186528, 429204027887699, 1510003697018425, 2114825823462494}, + }, + { + {5159850395392603, 5067743945456882, 4551909910661973, 4393814096795878, 6145580658249508}, + {1440929316705129, 1633730452330828, 3657204567294737, 3657918436987822, 2561724546723194}, + {809017030155597, 1831934834657405, 58189812416765, 1517873507099267, 889681994437792}, + }, + { + {4153444167566628, 4372997703941365, 4839161526733376, 2653398635504610, 5324373835991045}, + {4007354401668216, 1201450641763461, 1526795422335006, 2273741230894754, 2130356372280991}, + {1057020591512462, 1324094020999413, 655956927766596, 659874727272243, 2024954110083652}, + }, + { + {5839605326568475, 3831434019746100, 4883240784156331, 3880003889048305, 4841910074653809}, + {2844236939823231, 3043783621566488, 3890227240890757, 3800769469380331, 3175183419371011}, + {863608592350445, 1111828464904337, 322487356734403, 60843367779474, 775147863897458}, + }, + { + {4129677439236364, 4363616958764152, 3255333433286932, 4071265658640216, 5527560633207578}, + {3501906805856088, 2995655036831742, 1989943322549290, 3334534687075832, 3371315397704424}, + {471893887981193, 1459834432249674, 229072407724256, 1165980516905022, 1036865507138076}, + }, + { + {5587927329012785, 4196019533185475, 3488244055775669, 4788679066807545, 3936797203887245}, + {2334971095120001, 1054095219722721, 1729452124624259, 3446754994849569, 3835890504040419}, + {883720982539262, 2126174835830047, 1858128110066030, 1402309396930944, 1358212283922371}, + }, + { + {5437236132245684, 2619202868264644, 4266616048403094, 3779544081061673, 3472381895789909}, + {1158559475833858, 2227035258871772, 2170552210791850, 1087363571520417, 2867304161007231}, + {116357390237056, 38114324586368, 853586347213800, 1638943134635811, 1882124412005945}, + }, + { + {2871025108215057, 3893039278529517, 3878244260089116, 3893554424872522, 4708186328386966}, + {1760242418163439, 3855738944127473, 2877581036561996, 3253911846338252, 671018190326366}, + {1641735698439468, 1630160111859414, 1920036824528970, 346120100914920, 385076471695398}, + }, + { + {3934974918427731, 3807320560303621, 5860456491598573, 5199210868384009, 5781319959443384}, + {819456425532597, 2215390016559513, 2301197053109143, 771274648900875, 1303516882225152}, + {1530178090161037, 1646502716614548, 1058228190532635, 1522572712238470, 991147078780643}, + }, + }, + { + { + {3763364100157977, 4436158450653533, 3664705850096563, 4592883978910063, 4855668048892712}, + {3431442042489897, 3670457457720097, 2927483669898581, 2847896260114069, 3422237175305894}, + {1907217462504765, 679044428705663, 1371479879514675, 1420793148384765, 190685345044087}, + }, + { + {5140896563326095, 4954544354938625, 5148671791011404, 4813313238272129, 4814788700593711}, + {3528505813008031, 3913030166310689, 3457534787545946, 784019563379975, 1449546143149561}, + {2213525665395526, 146358659614731, 1573034916169973, 1131167148341295, 1194403623212224}, + }, + { + {3034590507214084, 3771531416844161, 4279939895181473, 5778619660734332, 4308244183318381}, + {2105305689409168, 1932040296635725, 2559301608776867, 1653053081843050, 3498476220207615}, + {1916484225176, 1896106466807315, 1279953155660650, 1725386140841619, 757101416534772}, + }, + { + {6555214085737347, 2980588876755702, 4785845115539682, 4430693817238987, 4107141749770380}, + {2133488547373079, 2884934342093682, 1652284377802152, 4287340267215791, 2741073463083472}, + {655928016394658, 1087485647128905, 1281789693328119, 2088439151211398, 1863153332596984}, + }, + { + {5220143354789533, 4303392603719785, 3697665521216293, 5367115036779017, 3354674257103145}, + {2461817469666051, 4062983661511151, 1323101412046937, 1360571080713195, 1716626899554003}, + {1790273650925445, 2180187262630477, 28219260774301, 1951582862584504, 1059160821201578}, + }, + { + {3706860118974125, 6182298149062642, 3206841902738667, 4986080379139384, 3223876357324169}, + {3108934357344473, 2823383892309930, 2709776767813967, 2732378265738840, 1695118712507849}, + {95538772778706, 1914880923031197, 417513632407841, 1767845086605839, 832379724270193}, + }, + { + {5132941124964776, 4798553016886828, 4052101096460607, 4475816634870178, 3176602159556433}, + {1456443406045738, 4161184975160682, 816382632051403, 3678387736600146, 2166890266198131}, + {393110820654303, 662371396172458, 1370237312917823, 2034119121136113, 904928937827}, + }, + { + {5075422185081409, 4699433492834214, 5948286955155472, 5933498265459676, 6441657203628461}, + {1257344135899307, 2776494249972420, 1637109398723534, 1801319038042246, 2082644998926031}, + {189274223123103, 2188109173279445, 1461570511269332, 151886143484743, 1557837550414982}, + }, + { + {4365365818590957, 5180206223815189, 5035374537630803, 5955216889373899, 4177347431591518}, + {4105224954841159, 3814048291702159, 1805828417935849, 1548444252518409, 3761242775865814}, + {966697507230426, 1689614203301123, 867370120071235, 563108996765880, 1552869095947518}, + }, + { + {6190612622769392, 5262116783421509, 5770823033954832, 4892678801476142, 3789326136184388}, + {2680510164419078, 3125272296703659, 2480535210869218, 464721098622880, 1141684153257222}, + {1871952745325912, 144470913279784, 434631777342778, 552837449330893, 642852750438644}, + }, + { + {4755508755993467, 3653868693631672, 5880862524139354, 3244860344044728, 4481011039901531}, + {1809358219650823, 2339660560948574, 2410584439137912, 1286742564054194, 3633419878206029}, + {64765075641768, 68764899017819, 1968408548264810, 2037002115471749, 211556643344747}, + }, + { + {5543625841706618, 4560629261024327, 4731751483103768, 6307249547601622, 5012757099435702}, + {3301009531661216, 2677459079264873, 2707326467220240, 2261655438430016, 2962646350850358}, + {1579401584164790, 1951017356653076, 1801209077919862, 1153368800641031, 1775772413220140}, + }, + { + {3556317598507403, 5934251293404526, 4176527831714322, 5239968931380200, 4506603999756496}, + {2798836099557035, 2002468979873228, 1132424890166086, 2388404451698808, 664387721246094}, + {1947208168676528, 1750536949518976, 835780038339521, 1802624114603814, 1867663782159356}, + }, + { + {5351331441108046, 4901733280572801, 5434846723443585, 4372148225205494, 4376250516119689}, + {2519667781375866, 1132412577764719, 2322930879998983, 1660817657158452, 2806576583179867}, + {1273923691469553, 1862566872300733, 2236121435313308, 274949363314112, 477088969758259}, + }, + { + {3358480296518006, 3814827118577810, 5033804317047304, 4803399909431456, 4940637069622359}, + {1965761504739774, 3200209926214852, 3722168784530754, 3464219522306102, 1953662369491229}, + {1946412430894973, 2031215026716789, 1150845535883051, 749273986980949, 1433091314912259}, + }, + }, + { + { + {4565135018699993, 4952235844716789, 4332776238462736, 3944983589420527, 3534528668424353}, + {875483311206731, 1070293195031859, 1281389774974538, 2234860500431395, 3030484939064537}, + {2191861413872447, 1998107865473216, 135161483760725, 1133778951112075, 2177808149908975}, + }, + { + {4472607877838387, 4680291079417999, 5266381476904463, 5448529984859500, 6037873358663623}, + {1355285592679599, 3216332013847453, 2858567121370219, 2432376038574376, 2734263724238645}, + {449706520184472, 2214233011551797, 684523848529734, 431843026966950, 1758835924810462}, + }, + { + {3413242279346498, 4524603375434282, 2637627437993422, 4373910262118552, 5420094068912965}, + {1617166089281188, 448710947316786, 2017034644293574, 1886691422085664, 2375442150405559}, + {1239614751060180, 254449956067847, 1915952567259905, 391989559805324, 853553448301328}, + }, + { + {4142542119790983, 4675453183245373, 3888287250251838, 5522078723840086, 5552692716915124}, + {1381495390544381, 584763141985101, 3131504846670548, 2565162572339012, 2037973653370614}, + {762375715838646, 553562190209386, 1146347552263484, 824188464596685, 1830942666102590}, + }, + { + {5823375217862555, 4240127004291848, 4611065015006224, 3518908128296096, 4915429068500234}, + {1348374701112873, 3953700554194482, 3402331094627540, 2804779645909956, 2204826476892034}, + {2119092558617159, 1045482671389213, 690197889240825, 471826136635342, 1637923217880356}, + }, + { + {4059066650158007, 5141565698162354, 3733026015817812, 4875063676054927, 2832005231346927}, + {2181081937454965, 1121830291087960, 2832579231299976, 3124836269482413, 2225668708158199}, + {1193994157146400, 1628108083694642, 1021885296427132, 816068909639879, 2088480068848711}, + }, + { + {3180618525607636, 5342429333917474, 5008239417572170, 3506064373977331, 4538653079573275}, + {1673050054377632, 1765054067091528, 2962973405879830, 2339273872052899, 3950931503569149}, + {2229241184614921, 2107352800266199, 77312115078922, 2151892262530718, 947910914861383}, + }, + { + {5320544374459840, 4141095319362425, 3313360370605015, 5185507100540960, 3283266576250376}, + {1528297312537716, 2187935649407647, 2967731417391411, 3155021192657576, 1577434241618944}, + {1385713524190245, 153942078459639, 747467190641094, 1446053675113471, 429215290527338}, + }, + { + {4130033413775598, 5253437474448919, 5186743122906330, 3072446418934431, 4486276088811881}, + {3865635552262096, 2111934227084997, 1803460783795098, 2595364764305293, 4294038033412459}, + {1939054538963024, 1515892461529143, 2145315228101212, 206131396483318, 1207808442703235}, + }, + { + {4285235833599064, 5004869505494285, 5398338412388895, 5145057161859867, 6219558308357834}, + {2122251221692966, 1686529461497383, 3592144721245791, 946103181235971, 2261774551055452}, + {1519512635495115, 1879830706415200, 631994832099345, 90552542491442, 1074938948794598}, + }, + { + {4349405123860786, 3135193611243628, 4214940643324649, 5373877724549797, 3499285433136967}, + {699708361184464, 2781323063917462, 1664177773796467, 2129061781951253, 2929310224293355}, + {881819301152893, 1404208553713523, 1706641996539966, 685345252606027, 879987031868371}, + }, + { + {2629920833708073, 3077736686198199, 6153945246604194, 5109883364128321, 4007866927409167}, + {2201062670972485, 2517508956278887, 2681660437016124, 2026769404043331, 1562746334284849}, + {2029537774099989, 798336123274982, 962765795717174, 1441375461370721, 595792417755859}, + }, + { + {6147148440188849, 3255264873123981, 3737719663259093, 4820083084252873, 5252844759112604}, + {2825984342500049, 2739886905391569, 1677188826435105, 1932192000687991, 3155126576093338}, + {75347910850483, 59335245365512, 2051925237105745, 2044824231668461, 970303688628601}, + }, + { + {5763564504160432, 5421442243725773, 3588496091914407, 5369436266097375, 3995085142922692}, + {2488955180168268, 1799719498283103, 3012193868704087, 3191119683274303, 1313407450591024}, + {1669605168509235, 1046380333598262, 8317204728147, 1002144485955824, 1980712166998785}, + }, + { + {5208877095968696, 4101472145123500, 4547654469901586, 4596473001183302, 5108183921345691}, + {1614319198851918, 1592777501272444, 2078178842786638, 1134074463419502, 3406886179792273}, + {46520703266015, 1463053727782106, 1641431035629451, 1167993397224604, 1860200763335910}, + }, + }, + { + { + {3011332796830409, 3293305844851756, 4350706657635174, 6528175041183782, 5633500660447495}, + {1684548552982151, 2512680297050328, 2151565475089600, 2240257948464080, 2357334086387757}, + {2245889758290233, 1304556815701186, 1427348922813143, 221464961710041, 2149077757654506}, + }, + { + {5021889171679330, 4462128123863397, 5496067810219064, 3884382915013647, 4592260500935750}, + {1200977971745538, 679604753110803, 2370440117588934, 2264961098110051, 1017048311556208}, + {1190992926530423, 1046016291129455, 1934369009614752, 958221374199446, 762751542850234}, + }, + { + {3460977055305417, 5402529018730102, 3060601098222640, 3497142554641379, 4775614304897016}, + {1196600994744545, 1547369290503378, 2035231477477616, 1257032246257935, 2729013549752394}, + {1316355169784636, 2159471323343549, 195437001734225, 1784725127680235, 23628188515854}, + }, + { + {4414887133757738, 4702915728776787, 4098231006823107, 4707645820548353, 4031420634244190}, + {4034197670769956, 2299895540249251, 3720313013014369, 1169924369129605, 1452708652401532}, + {246845927125542, 475207520380026, 1495857355234583, 1332907410765356, 1137190823002655}, + }, + { + {4619638086363716, 5112231939480403, 3430351651754637, 4072797244384643, 5452815353333736}, + {402770419372162, 3130948749709529, 2422951975073025, 1521258543891683, 3268450338566556}, + {122249525311324, 1126352422834922, 929325077009082, 782368628240853, 94217591211022}, + }, + { + {4962635153104108, 5274135403834507, 4755774461820061, 4383546262262835, 5457666487690905}, + {2990995606289826, 3021922427972001, 302802129599791, 1502244105829111, 1773114045409669}, + {156241863414061, 496518516536107, 402847929676013, 1139792271454333, 1977247161507402}, + }, + { + {5032814130431534, 4760678921877281, 4442869438253961, 5565429687944605, 4317400766530169}, + {2463323770855702, 3896470221755473, 756431515781897, 3201672938286523, 2288460277235041}, + {1855056967762827, 1495181328549832, 966278130514841, 758391654071223, 467588501531856}, + }, + { + {4817034814919500, 4208076967893683, 5868839484739037, 5852497340094076, 4630054499608831}, + {2436900424213206, 1954148435588967, 1712385658617173, 2723793304425402, 681838917243489}, + {1439947543028469, 885225692302481, 1285222886469976, 1588398795428018, 1298691185892088}, + }, + { + {3166915207030205, 4221727132556131, 5745276646060520, 5830694990900872, 4237998343894079}, + {1368851636374513, 585540725726993, 2239345036245042, 3124363364569248, 2914970196697053}, + {1206666555409985, 1789371104267935, 1925466428785716, 378678703847709, 378978574609534}, + }, + { + {3049990186077834, 4282707068721497, 4031467457902549, 5045270642251952, 5619239366726696}, + {2247218341382540, 3733105160936895, 1542123681165149, 3690639696246556, 2686757663719606}, + {1131525507915411, 151967851358587, 1334045685598637, 1807594577522576, 1666949318203671}, + }, + { + {5317642436905001, 4262905497079623, 3806587609027544, 3162214737577195, 4598325819108034}, + {2322709256244499, 3364701239080335, 1085438519194966, 2211341194954781, 2734280485747362}, + {547075051672667, 1927631982974242, 603999740914722, 1974345687792190, 310412755046628}, + }, + { + {3092260334664458, 6358353190373839, 4150234089958180, 4141601803005412, 4164851538431420}, + {2480565549840732, 2510439995547619, 2534702111260990, 2561344597955166, 619102460354386}, + {1996829248620682, 1059563669319507, 2240440638640706, 1599145288747177, 407659118560947}, + }, + { + {3115383537041122, 4344887992692310, 5501863024972572, 3993241570720752, 3416751871823654}, + {1717619697579090, 3621794853637170, 2666986311609642, 3029150476191498, 2414353362640396}, + {2142003785026841, 2167906365984504, 1742773278204754, 812925480008831, 429368090247755}, + }, + { + {4184856094603567, 5404235283771230, 3764176438258862, 4280121628742729, 3445790640140600}, + {2656068733977443, 2976637537776442, 1238993222325972, 1554795161393303, 2131523863405492}, + {1574345185045103, 2079161140310195, 2092484433153763, 1408980124437971, 44981420431371}, + }, + { + {6193742471986890, 3621814037880206, 5498721010846514, 4536848636334539, 4762288817182267}, + {2703599140394458, 1961129680427764, 3192043467883058, 4259887504588631, 2455375021790255}, + {1758602597767485, 709830862658938, 931608374711636, 2198476269423406, 69272189710304}, + }, + }, + { + { + {3960691793618422, 4697205665896081, 4233023106925560, 3551947497905370, 3667490775726784}, + {2716251404526112, 1631117916585969, 4014857913931082, 2213037729836094, 1396521499150134}, + {296206175452724, 658879322369119, 97943562265366, 1761747874053347, 665498744562262}, + }, + { + {4542146017866057, 2313615921887147, 4181202139006694, 4414799599657545, 5341405847272363}, + {1200760264207189, 2304738880112015, 1927960174691144, 1569518880089323, 1152309979337507}, + {2038947849479643, 237162323211423, 2065816839891168, 419806183479203, 384865548997533}, + }, + { + {4632532202820720, 6679838284939842, 5003934316625137, 4209971835933588, 5519581415427037}, + {1152764853239608, 2282089860477202, 1601380253073465, 898105377854964, 1583948862629235}, + {1558193059260245, 1778073808602536, 402624851529717, 66752783641769, 824353727713740}, + }, + { + {4121947878564012, 3974762513146561, 4400688676047089, 3750758292493538, 5582121141429898}, + {1987770197713484, 751549594590657, 4130774294058181, 2772087960475462, 2398377455469772}, + {1021194340773145, 2214506742467645, 1946787888944335, 2047968106648641, 1821857137920583}, + }, + { + {4817011285691457, 3821500381976103, 5867746283021767, 5892999478528259, 3614975724251316}, + {520345345283715, 993525428347841, 3082505540027545, 1401316007351695, 2524441889115400}, + {540709883326476, 664748033877723, 77460650157458, 1882229467398241, 1217186023704288}, + }, + { + {3888704843022071, 3022592939512474, 5839771089230787, 4705593175556810, 4617871784452989}, + {1148904473568401, 2292434344833748, 2860017655924869, 896886146116790, 1793557015614071}, + {738867948290551, 1113067062951318, 2239418068162676, 2235388618772922, 321946428440080}, + }, + { + {5186369799189058, 3697173555759488, 4262727107695046, 3185380591286776, 4149807772745719}, + {2507278187062390, 1965300287234722, 1455241861966706, 2358026574953040, 2356583034323921}, + {1141974899967420, 1197500508248512, 1725264994009043, 1639228663875285, 1766256613674282}, + }, + { + {4859130511022316, 3438619274603782, 4274393918753007, 4542539306472407, 5021829178357491}, + {1473307785816396, 2183888493524504, 3592230148429221, 2872086545946123, 718894511556159}, + {200438687964996, 1579389594103736, 1144999901302662, 1292188560016150, 1342060233269448}, + }, + { + {5322785092917218, 3564464821553428, 2465159528975281, 5838118438127962, 4862308511365583}, + {2206232904105334, 2908798660147806, 2169658158959269, 2724132358944628, 392390928972895}, + {883459081700629, 1602090588151437, 768552508263143, 1181944834979084, 1796139787109480}, + }, + { + {5591293901585158, 5161437494483979, 4307878889760969, 4546298250229339, 4189604893397730}, + {2182554744233356, 926666458178889, 2790825304990041, 2529147957716171, 951582391464256}, + {187571578269437, 1207365261045700, 1671287753495621, 128062601272884, 1097620007687094}, + }, + { + {5979255840859055, 5170212343908976, 6251571908864416, 4044340797680332, 5873982661311143}, + {1856097540852989, 989253754708050, 2232404724159712, 538127825012338, 2301974812680125}, + {875553341339604, 2202671771469035, 1916683928798488, 1628926854796717, 2104927509529811}, + }, + { + {4738081053584946, 2875665464097852, 4082354471082712, 3079977082389326, 4643006842643895}, + {4085499965974240, 2403823491084742, 3352533311494316, 2981802103584372, 2409154352569497}, + {822917758900752, 1019777701975664, 1564136027018780, 1218107309963297, 1014127758290355}, + }, + { + {4211670720265322, 5260586114139374, 4117778612287885, 5761523698172883, 4942445429900242}, + {2233928901439648, 3249090656816698, 2685023842449397, 2515328324903077, 2780554742949852}, + {1119507853423473, 902873322434013, 1683813506511239, 99271672214794, 1043609318229518}, + }, + { + {4881172173279202, 3599812968457896, 5389450859587312, 4590538673755018, 5926347639505399}, + {2643454724039014, 1385194776028482, 3573341970152704, 2554149121763820, 2626184303949707}, + {1041863798926969, 1989079677249410, 910600041636905, 172639986070412, 958797345271109}, + }, + { + {4102514793801097, 3799057862785664, 3089506143944932, 2968464716766741, 4933382932746089}, + {2671084000631505, 3069928136724336, 1615118202102194, 2860128525830493, 1072943882334681}, + {2239551548278550, 1569208624262185, 270318489599140, 666224807173956, 272660472277513}, + }, + }, + { + { + {3788400011322929, 5238791757709216, 4201438471307196, 5718998504437804, 4699660978114753}, + {831848399557275, 2203944328508070, 1205773492199750, 2947899883606056, 1258775953756159}, + {801855642469056, 1726062700700587, 1064722548099106, 1128997468587175, 1368420390253860}, + }, + { + {5220756346668707, 4207778951928942, 4451591079714714, 5561602467108901, 3701332347939515}, + {1095027470911861, 1309452919940954, 2417363745862806, 3417231569067727, 1895316643922203}, + {2142749866659158, 1962490102531981, 1691447155265793, 1827079035266074, 3803331638058}, + }, + { + {4981668826515757, 5644770367578110, 5443857182354756, 3149391452129516, 4066238206100559}, + {3356282538281353, 2251921811216688, 2887149285344786, 1384857237573084, 4057072468959031}, + {399619403797256, 1517816986720610, 1503473770785461, 1650204761619743, 2016574488970872}, + }, + { + {4082671840470154, 3874834197714005, 4437883298126266, 4222220664757293, 2316031680718393}, + {1452497321657782, 1539338328736177, 4156757905713634, 1587402592924883, 2189645592400953}, + {481460971838645, 495603062939192, 2081146895236470, 971761350637757, 742727604094484}, + }, + { + {5515673501962670, 4546389793895825, 5000269413610660, 4603828815474748, 3900836987569214}, + {2460924811417180, 3521984551624439, 1511404974611240, 375249799211988, 3782407540620780}, + {2048665788177445, 1408893800498572, 1918636993246022, 317961445367427, 656800592778138}, + }, + { + {2426976075633155, 3651600221015543, 3234264849290625, 2473309309095632, 4407296503206636}, + {2422350949934017, 943103623278343, 1291301021890213, 2346315203451818, 4112725099426082}, + {269878912827170, 1290670313639785, 2170448731381563, 1730590899024060, 665688666929019}, + }, + { + {5000413361992888, 3347912965056552, 5787242209541388, 3819792442922756, 4847625000360540}, + {1580177441875156, 2506058297611016, 2934789696579346, 1061310370544480, 596660656376680}, + {1957905575869340, 963138800079095, 1346185076450932, 33814819376238, 1624717058267694}, + }, + { + {2861980301667765, 3354887551296141, 3948074513800240, 4019265998902801, 4754514631586968}, + {1661216359883315, 1198665005326425, 3475476495296842, 881743418686047, 635325796191538}, + {1196599610725063, 2100294611545468, 412113633351820, 925880965367657, 519930913383517}, + }, + { + {5571468672275863, 5188072583684019, 4251873319339365, 2576514881889354, 4045293404267572}, + {2133507738629437, 1327217318093765, 1889369311142453, 2479101608310052, 4045149986308216}, + {703846410484025, 1348842341032186, 1685275777321460, 1615795108904065, 1475415532006380}, + }, + { + {5398949984609248, 3762655856514160, 2412712349948059, 5169973908847336, 4334869322214508}, + {2999632416625302, 3110726069588902, 2228895586394623, 2800522251491198, 2224895404394358}, + {1399061587160944, 1205421803029276, 519683572464804, 340023786200115, 2172700699519595}, + }, + { + {3574689489677767, 5335925023065998, 5369256661040087, 3129592424352108, 5388737531811449}, + {2700892402458353, 2743476698281872, 1953844576554527, 1836651043988628, 2962536972306493}, + {1357694877428531, 1765161852606993, 1167042823088862, 1400958578522448, 1847208195529391}, + }, + { + {3867728253589687, 3773111053869328, 4368860594965835, 6133882052967679, 2533060702765705}, + {2290736769578191, 3757556884488538, 782075793204873, 1953945334364505, 2306213589322841}, + {1820300206186415, 335405661683482, 1092574996911739, 2062461927997493, 39506950020151}, + }, + { + {5534612992751919, 3746157517504511, 4108089392798474, 5131771932089590, 5617809945843001}, + {1342645331878441, 2000053418116353, 2168383944146424, 681027567941522, 1213562615764099}, + {379321638440622, 996302411355145, 1880571763884906, 1004856333759537, 501836588196832}, + }, + { + {4231662813561705, 4640318983129989, 3064518357303150, 5343343094006261, 6450142130522077}, + {1145892199839501, 1078673486712789, 3022417549910920, 1612895247211701, 2324179764588241}, + {1972676776834949, 44492199500322, 1456097929669866, 211262343295697, 1045510624803264}, + }, + { + {5968931973016112, 6019428128447854, 5757013441564652, 4431402751536781, 3192943415309330}, + {1480229165025206, 2054505377286776, 3099784048655970, 3055900157449953, 1375885673210420}, + {1812738520892942, 2084676765238369, 510773948276259, 934572202757904, 537600238103234}, + }, + }, + { + { + {3613080834135665, 5774088788979550, 4480966629462376, 4981692702949983, 5531898286124606}, + {1941100238292769, 1530763972357988, 2941717574786124, 517834246099701, 3268301290369396}, + {402477551873128, 1206353712079331, 1931900782149571, 353151698548753, 227661813611943}, + }, + { + {5770945118915754, 5544555209532203, 5448202195803091, 2841016429831070, 4428081881985983}, + {3042160696267866, 1193039775906917, 2708874250955853, 1880772252763310, 1647664574467171}, + {1801318854301087, 529217444026518, 41439150499132, 1819497139150034, 1914318279506430}, + }, + { + {4617843866085510, 3963473780045850, 4530695843220841, 5152831422757274, 6255165884461126}, + {3653392334037390, 2119290268348412, 1662789932544495, 3712853444146946, 1761023449047586}, + {1892648843913435, 1079776332626104, 1111039290977790, 1827479485396386, 859677304170245}, + }, + { + {6135115193251795, 4578420287793605, 3485955900327480, 5405600312155654, 4983545824887909}, + {1955745180210457, 1703319703537271, 2019166049085294, 3363246542620192, 3873119138750761}, + {1700391063795585, 361747633083750, 1216968456947850, 1993842710713264, 601267006969711}, + }, + { + {4925286822096059, 5955810075280268, 4224518592023607, 4497079033823924, 4700697585549198}, + {1335348453199749, 2692696552964594, 3243268312448681, 1958567111536422, 1194502970771976}, + {1656217138482787, 491628805607466, 1679451179466805, 970181505842258, 1534105889461948}, + }, + { + {4204969625278834, 2839735694548476, 5311815348914771, 3424730456556302, 5437312551033891}, + {1051919605857270, 2689758516764280, 3195630903391853, 2321619474659180, 1445811115388039}, + {1160289603260459, 1956223108351205, 1733312353955470, 208731931777063, 2163609865075088}, + }, + { + {6171922307530267, 3416689909413961, 4398780048782414, 3348704297294309, 4794281577167533}, + {2605760676899691, 2518935989171471, 1655039766011588, 2352706753121153, 1606429966007503}, + {1142834714776341, 85770505106288, 713866520631433, 440023537352050, 178697006218663}, + }, + { + {5369775152479351, 2976619105904851, 4320166487861154, 4349283416973378, 5052617030572584}, + {1815823837273367, 2562753791013569, 1539789395052836, 3647749880076906, 1631063017998020}, + {534961844628464, 1393583055120721, 1748351260324708, 1375538226727024, 2193309623120304}, + }, + { + {4362511965756519, 3334861441534551, 3560279110881819, 4504033277345817, 3695270180099552}, + {872424258749169, 3269419467389617, 2236476348626173, 2024356220545311, 2898783963621386}, + {1239822839121281, 1734625037061034, 1644113104753887, 838912630061655, 2165081997489666}, + }, + { + {4719668160615989, 4954232553381592, 3407504093515639, 6056696583065019, 4080126483053229}, + {2648578609770085, 3690844259333424, 2082598280716609, 2564691042641275, 1346520144951773}, + {1979149515238517, 717801405945362, 2104011649567412, 1561125545440573, 2157118688047562}, + }, + { + {4177174713439601, 5431484182531219, 4912403072956818, 3423215719262779, 6067629588380508}, + {1808742790957793, 2747803311617739, 3845306078978452, 1924084822718509, 2264852519642740}, + {1767189866398838, 835676264200014, 201596448765126, 1979907908451931, 1442810524651041}, + }, + { + {4409296057792696, 4346067875211154, 3459237364299404, 4853798679576266, 4468808308660588}, + {128841748532646, 4150186054273698, 3256924437045680, 4019614742906956, 337338633748078}, + {1077226425497346, 607378044682866, 1485491791574172, 1074180848747199, 1023053128705595}, + }, + { + {5804603278915694, 2796027819585631, 5011026665884139, 5833743165576011, 5103566912764066}, + {2493359374165148, 2464080592904187, 1933101226851633, 1880342534882667, 2417917477223840}, + {1284426144747169, 2005093245564178, 229493920382094, 1642769566056222, 1596652614163344}, + }, + { + {4478501502615841, 5105996638711000, 4307245809257853, 2912192821294412, 4442483575340114}, + {3490678780709549, 2722972627744756, 4141726367382933, 2626667232874306, 3706338015195278}, + {978951056774557, 1610590016630807, 2160020521521822, 2222969528403014, 1290838415735858}, + }, + { + {4233395101645091, 4760048839668621, 3419853204404814, 3555462417010423, 4295491197124032}, + {3136023326660957, 3195581484142287, 2364500047372050, 978391045278571, 2088093684065312}, + {319754006496675, 2078141843592369, 1381704035073408, 2135424637477137, 1217419566529670}, + }, + }, + { + { + {5290773769928918, 4793813444262905, 4720763845546248, 4081316225438835, 4093406366409350}, + {2219813055094868, 3751054103166673, 764148091645988, 3042364539660805, 2174498914560536}, + {1346839273131020, 1947175237418499, 2130499171815608, 841760904333801, 793011313347544}, + }, + { + {3890099439122631, 5436725454634839, 3526358179473960, 4130205528836253, 4143183670329231}, + {2705685430041151, 1931337763813343, 1867986078235466, 963301853857219, 3203544659615889}, + {548016394257586, 1770170736821935, 883041007523403, 1244492123782548, 1874837894534970}, + }, + { + {6107029440448048, 3899130796270571, 5350832732145407, 5288086135111572, 5016688224136320}, + {2322745137203416, 3712079434453421, 1656136902347805, 1063047643279494, 2347290530652372}, + {1585044732618145, 79674660750176, 2047172033863331, 558016866726219, 1811700039750197}, + }, + { + {2903508896190354, 3572836747669154, 5671992452104047, 3145254132994495, 4870698970274559}, + {1980868732324310, 2459850087283418, 1500353534094477, 1977074025846907, 686785408890947}, + {1977199595236300, 927859862391871, 2045825765550850, 1189431662969386, 451125616133550}, + }, + { + {4264958907260919, 4637613300323186, 4723189721727247, 6439587034668993, 4270210266819895}, + {1981177153373343, 1776706813610008, 2956634306768875, 2113399644330229, 364175990188877}, + {1473984112024647, 2212143402178000, 1913009700964560, 489799262080055, 1390546130501803}, + }, + { + {4617432771154388, 2768922884406316, 3194759053322417, 3846588214005790, 4684848439540931}, + {3696338004009516, 2296500736839486, 1483385825107721, 732704435299560, 4093200809844903}, + {781495195344331, 819872919567170, 2058369589741763, 131552040816437, 1143952030551876}, + }, + { + {6045398880892501, 3274164683120730, 3537206235588588, 4953070760072151, 4494335279262109}, + {1632591054957791, 1584029964350608, 1679919371947982, 3412378076716233, 2572356071530817}, + {118276417181988, 2048136038162801, 1736078553924029, 677257986431580, 711847529279284}, + }, + { + {3634115225339518, 3407128374975375, 2997970212274081, 3493862836273928, 3535607408159120}, + {3574732327388664, 2600283522407089, 2877235052318169, 1647316986471086, 1495874784707614}, + {889518489432828, 1216748566987677, 2027061052060458, 268044074097160, 1539610510772867}, + }, + { + {4611501240201625, 4770963666624495, 4338415201879424, 4860883825935208, 4028006785359735}, + {259543849715615, 3116307281996357, 1555340861337048, 2140193697629416, 1035789313751911}, + {1026218773492650, 930245039288082, 1822875264087643, 479782375672284, 1931812455503119}, + }, + { + {4148807861057856, 5812728864755237, 4601316267327746, 6043565150382029, 4199151665681887}, + {3394871127325058, 3191785534223821, 2085795470524552, 2385926585602461, 399655200529949}, + {1057229833653287, 1828041669558530, 1006577782987596, 2162474092618005, 1568476132284973}, + }, + { + {5547684346917888, 4989218016843942, 4586613652979209, 4863124308009928, 6207570019680129}, + {2566237642336854, 3970491812994094, 2598212316441047, 2240782240471054, 2552742376593093}, + {716486226259134, 773421749453144, 1784612269854183, 1741938572500414, 1834164482186148}, + }, + { + {3117421109623856, 3461685839753353, 4955306417606165, 4558294861196235, 5602064404959934}, + {2273224772261066, 1223111129900149, 1584682650834635, 2022200125401455, 1373728084078920}, + {913182622593832, 2001872744868184, 882970207556847, 299806317329996, 1726046908726060}, + }, + { + {6249588231739606, 3368998262120903, 5239047789721372, 3406210943086424, 4754518606052966}, + {2248618336554706, 1339184282498129, 769038678141320, 3217160515726744, 1715873134108166}, + {1976228100247818, 1272400462149307, 1572190226615598, 852044049472028, 1055275428347366}, + }, + { + {5284373775928701, 3618431820022764, 4020557586503952, 4433032839002146, 4171326821228907}, + {2417108732168755, 2170003784635000, 3518440054867754, 3152772966589030, 704341378948759}, + {1290493724571150, 2122276831263561, 1747969631590180, 1399718798480988, 139803941068636}, + }, + { + {4427994415528072, 5149611644022833, 5193849655888518, 3398788549762908, 6113634201730634}, + {216319500947386, 1455486684654953, 828483179169328, 2183296040357724, 2625210482982860}, + {478303205586551, 304131100485205, 248369703081454, 371320991720787, 1635813582756365}, + }, + }, + { + { + {5252346966668309, 5639208782676701, 4075417215389880, 4364690112290244, 3384680235809138}, + {2429491642409009, 1283094434250487, 3316839113847160, 4229629869361324, 2675780619596520}, + {2176454779743876, 931093459142961, 2244697379845986, 723779257225747, 962795008037376}, + }, + { + {4164637625281563, 5566305816206016, 4655415916130208, 4180775155367792, 5707768410211632}, + {1861517597691605, 1772481620932890, 2629476438960640, 2705827759458320, 2107910124630170}, + {683279446283480, 2167544438614321, 1975855992985379, 780955320484514, 780910621778643}, + }, + { + {3955544259328322, 4458238333874171, 5864190420414532, 4345033257929994, 2857162289792042}, + {2686358254975148, 4179751356732233, 2499687248272490, 1241163995738960, 2778131269016956}, + {1074884828909420, 432905047961772, 1185537826254838, 52144045776742, 1826277929133963}, + }, + { + {5684453359674447, 4877177488298427, 2422407833284604, 4605478777171110, 4729984701613103}, + {2156715047802967, 1276772803921323, 2380233522537438, 1960794365816568, 2680384519257273}, + {1862177374063425, 1873700738552432, 308885709393483, 2100622082080360, 1104535253282502}, + }, + { + {3931149063775879, 4254429699498962, 6662929352488607, 4079587572542558, 4855364761755442}, + {3711640686247983, 421582154826228, 2220646689506683, 1208894292386914, 2152820272048462}, + {1565335522994081, 54406341126738, 599331788389250, 1486039135212823, 940991227185565}, + }, + { + {4398457498029638, 4929754658751446, 3952574300737926, 4493043596943885, 5305461811863411}, + {3849064215739384, 4001520908708098, 3463231867051918, 3642198741522237, 1030072339730421}, + {225800753248600, 1001289196776939, 1570695157447337, 474142387326152, 1860241406570283}, + }, + { + {4817367953033495, 5599987240264127, 4736311445242884, 5430531336232182, 4460173530026570}, + {1052973111938531, 2823516883980375, 662638871434014, 2738994056625648, 563864123356550}, + {823857549390635, 2207592640971793, 1855512257490888, 1911413747439725, 1853809846918105}, + }, + { + {6194718989753531, 3626032976625365, 3751630707315810, 4477700840286220, 5452904257109698}, + {2036109024667887, 3040585821349743, 2780985384011476, 1970818175728284, 2968438634461420}, + {695616701038646, 20368455765111, 619664083096696, 723635083382804, 1023760209767255}, + }, + { + {5008707213573776, 2859949901187285, 4290065003741713, 5151870738966180, 3127611889915462}, + {574462324973718, 2125329428751385, 570545018291281, 1476031513731508, 2680835412613570}, + {1517596182333361, 1429983941782802, 1900615890395770, 1911469027059364, 1851356681596334}, + }, + { + {4891662727757105, 6078189791872620, 4341252688115798, 4009612276132060, 4158882628774497}, + {2178830616846417, 2794898270987790, 2339865206643716, 2923242275980220, 1745466521002355}, + {841969861771844, 1234567333486718, 2104638753106763, 1445233761721300, 2209267998342752}, + }, + { + {6440345201923204, 5723637287574387, 5903930483115066, 5778502423080164, 5079904071191760}, + {2035275243828198, 2745418930619871, 2632830605513978, 2519743098631716, 707209224772602}, + {2049800384050253, 382336843047910, 1465264697408643, 242728978654073, 1821420259893325}, + }, + { + {3385848358825911, 2850931104925851, 3458310588278305, 4579597908985563, 4607881337942919}, + {1816700573507985, 2213627388818419, 2637198541463171, 3087473887817081, 2837589033715179}, + {1073720617318924, 1636814037227948, 1227321319951543, 598345156599653, 544027576937438}, + }, + { + {3741365114761762, 3465142572701024, 4346453033629668, 3800732328304411, 5207004929940855}, + {3530134215235346, 1497788707695478, 3538247705814828, 1425334926184197, 3292646832985731}, + {368165631658486, 1427424960871770, 667823977725231, 123986789130850, 789476314816796}, + }, + { + {5183377371949700, 4172584964939172, 4687335701106073, 2534986101578472, 4297053492878574}, + {2375597255557748, 846038920993436, 1398943082722053, 2179038637021886, 325133433602556}, + {1814357252172511, 1812991482130874, 1545461112716185, 2228739665628687, 1030416912136148}, + }, + { + {4102150726478441, 5089888860858732, 3167069131929673, 3336166645247640, 4708635432875520}, + {1325239906989203, 2989936170895398, 2414201768248283, 1851733918704382, 3428546124237928}, + {296568059020374, 1937661788490502, 1994712548479216, 1341415580517821, 919259617560208}, + }, + }, + { + { + {6274182990169406, 4386048988056353, 4097025350643424, 5127499815238002, 5572164902186574}, + {1895408474337392, 1335954976788533, 3236941534902540, 2378721630147940, 1461766309882914}, + {1291953286798969, 2102679466898679, 1596002078575263, 1387588817990761, 2143444637427225}, + }, + { + {5996694561997207, 5683227612437284, 4899213524992592, 4856689735436656, 6404791836913969}, + {2772496102790967, 2917238652453944, 1731727230740742, 2247887220248582, 2143609474706149}, + {923819152192005, 1415712944791087, 1125410698033067, 788009900900011, 869993295869018}, + }, + { + {4786795669239288, 3398808358640920, 4513626939909643, 5985598090247291, 2945790096837940}, + {2456756643078196, 3060894189290238, 3759434421535873, 2442805763764489, 2819028797217160}, + {1757819380032415, 1458259160758992, 404747119062789, 1242483165113555, 1521264843142355}, + }, + { + {4457446227801342, 6427880138295914, 6656730008666805, 3937171933580687, 5754864538579708}, + {1177246463904108, 2488433613267172, 2328478208484747, 3802230570654315, 2344609059443716}, + {1519155588261854, 483899768651806, 1235345257217886, 467640517750393, 1224438957323827}, + }, + { + {5102603430061893, 3128470923287158, 5801341356388264, 4525678559978591, 4718363529583899}, + {1246208485680505, 2848653521425806, 2416405253631000, 3077610602170527, 831805919056409}, + {2045656886162419, 2245569838876242, 1361334406977685, 1370170063372453, 1784586163491838}, + }, + { + {4556063502635342, 5531207665521536, 4057497943029825, 4507014901377590, 3148382369498868}, + {737891874041388, 2451689755512888, 2972729929575783, 1153163677723624, 2631153364835664}, + {1021578499394252, 2003506226907156, 1906928204664703, 617432881327189, 487770381544088}, + }, + { + {2772215428108171, 4464024296635705, 4854458470465137, 4051326172605262, 4041843916653002}, + {1808240492311657, 683215352347115, 2786075502512133, 2784661866757750, 3917451132840122}, + {956648481954026, 2096247164218896, 1027480742584033, 928233599700570, 2122240338574709}, + }, + { + {4629946233006760, 5291553581528148, 3270843847622640, 6572477208034336, 6154625523788459}, + {629205712253428, 2948018954745502, 2240941577462354, 2419373201820060, 2682153541398885}, + {948811544154236, 95827271348811, 971972540788513, 1752656910961976, 1577613288465037}, + }, + { + {5687495579915904, 5920739705585144, 3623686905482864, 4279799360588693, 4937051703985742}, + {2733819029729102, 2941383700719094, 2344126789319304, 272099344396033, 3469931440006564}, + {1155109808876838, 498663775049656, 2009409241380161, 1654861553852237, 2195711930770443}, + }, + { + {4562514450276878, 3610360397280214, 3754786033717112, 6274151337271952, 4102082344471456}, + {3779237395015718, 2531855739502292, 1076300728317328, 2341702386635930, 2037036009072308}, + {357187236460800, 1343207422743391, 1557831743447331, 138875622916216, 2073308474766668}, + }, + { + {4318248447888802, 5457191060945059, 3575720381879889, 5537122891348075, 4658291618481620}, + {1058927027601226, 2097000197595935, 3018484019405255, 1294660112618737, 2932877913314978}, + {216145844764492, 1876995804123388, 1188737931982599, 1588244200049402, 1850009625550870}, + }, + { + {3352537291082093, 5839102984451201, 2319458858510810, 5312519694669356, 2539572161961088}, + {1971880260906249, 2590822963635857, 2283171542295386, 888730652847270, 2069077006720618}, + {986114249350619, 899447833294837, 753796294360457, 1686315816498457, 1484432111173806}, + }, + { + {5781412563046772, 2829048727661187, 4098529237644982, 5146692071916491, 4319033371720950}, + {2231959129524362, 2353147866489543, 1361542642038984, 3436571318049649, 613122764422636}, + {1553151906564201, 42706246613546, 1656634422023210, 337580524133816, 1382068281260380}, + }, + { + {4318188098974879, 4190975253205867, 5053353859489555, 3624409471895100, 5734877817656224}, + {339244995001665, 1760160432424305, 2510143032086917, 900873257630652, 1381243383153778}, + {1027887039599863, 645983151773049, 940633405940384, 791297293294468, 113951612418342}, + }, + { + {4421127861301280, 3227473132618256, 3897823766346675, 4531675054348192, 2597262173415879}, + {497984229256388, 1528193624284798, 3083402776323261, 2834076054300848, 2004534517066737}, + {707308783184531, 1723910086807466, 791458836921758, 441590831592448, 1945299136569002}, + }, + }, + { + { + {5139590791061503, 5074296034161507, 3861111523264964, 4286794753368429, 4613589462411916}, + {1370912655100557, 2279879075953359, 1535348789227130, 2242808749632369, 3061442465980918}, + {2128769772677977, 2142654242576520, 2016094652496998, 2132031230853467, 725434888027655}, + }, + { + {4677803618766960, 5273930469290190, 4617970826042730, 4133081282480847, 4583310983505940}, + {2135073895739904, 3472442449797848, 1493509767807810, 3843639135014989, 1420071562059334}, + {1420603492551010, 679640550295814, 1617533903828801, 780154362635607, 1319780020899258}, + }, + { + {3937068127551315, 5594824685351819, 4538337787238312, 3523378410763828, 5437114214061846}, + {3695575212053185, 2594449599707103, 2742930959436192, 1161286236132678, 2345020968733648}, + {194815921686333, 1256736762545940, 1408742447743650, 304562218341097, 2021464306176092}, + }, + { + {3212222966285493, 3266851872779616, 4336733687401440, 4794872810759007, 4424169619295461}, + {2759763070229743, 2724175318859802, 3031057691838938, 3431189823632909, 2961517144339711}, + {440075250919582, 694825884103652, 2159700403414911, 116894270435230, 1425927073727904}, + }, + { + {4841955313295828, 3461757100553382, 4305435906781420, 3691116875116057, 5298851817605162}, + {1064910415642974, 3095607189587094, 3908971853500052, 2189460887246833, 1354043476687700}, + {1262675707031055, 1219816744922490, 519257628155087, 1497570437960201, 1372594887264798}, + }, + { + {5466094472208141, 5012579346250577, 4661027376097750, 4434802656317810, 3968075278352583}, + {3315525263287981, 943900907578117, 1225723797770692, 4182671057889152, 2697481958411475}, + {1933555860608921, 1275569655188916, 234812135397482, 96042287368239, 386392083574324}, + }, + { + {3319477981428303, 4681888525996228, 6591617607940267, 2604452186053658, 2972488992219816}, + {2831773176554005, 3864996001314642, 2395563170308483, 2090271503443448, 1893990359510416}, + {1681588555670186, 980191207008201, 2154581399538671, 540872424183046, 1943954489289499}, + }, + { + {5977124761029192, 4538331973533215, 5533519881915667, 3479901172100047, 4656405250637608}, + {2363082790805374, 4242757803000485, 2669759818118169, 3333816374844969, 1325118659202748}, + {183359648873960, 382111728086623, 1969766109298473, 2071169946252387, 242935538497060}, + }, + { + {5188738692165469, 2664732629276594, 4968279324223179, 4960443399326301, 4436427572176893}, + {3490990196257229, 2560345203268680, 794851537166791, 1532423795715657, 621302931359813}, + {440189527159075, 2095498912423497, 1575373142262611, 744594360742511, 1157079567398109}, + }, + { + {4869958177792820, 3889970905101269, 4570550615789326, 4496205440964732, 3848931098885666}, + {3870071548603662, 3041096274835181, 2350925463456272, 1091637746528482, 1355815234248438}, + {927792763323382, 1304575354366273, 612939300770904, 1630367810979451, 174107168815644}, + }, + { + {6136927367908702, 5203222247970547, 4888252310796559, 4897189790028520, 4586519387439588}, + {2831448685067634, 1668205588574421, 3161976938852725, 1027424964992432, 2026369259616642}, + {1735694076750726, 1266349638286480, 1493849675863588, 296961022463490, 1483126610434799}, + }, + { + {4654087895073878, 3931119431920957, 3810992402627745, 4571904269427127, 4481981159091504}, + {2466558329032204, 2314404658847041, 2524639581935109, 805442192808499, 1270294344302086}, + {750996510156456, 401855193068398, 58073276915611, 87767580153872, 241880537805683}, + }, + { + {6336062814229381, 5495468976405173, 3085611334327622, 3929566749867368, 4056705138744772}, + {2170745323194467, 1059898966987983, 1821678094574528, 3224522071822304, 3177794562815748}, + {697769608468752, 1369430004061620, 1388586673198089, 909114275708814, 1146450457999407}, + }, + { + {4238043779316857, 3868604149115822, 3602737573195351, 4491948926777684, 2593111277688382}, + {1942420724187743, 1230266918978492, 2950156777850293, 1491177343837674, 2151732388834046}, + {1552628609460396, 385059438618066, 1935679554618991, 1586643703562239, 274738755241324}, + }, + { + {3708634080771636, 3376471647619972, 4144079859874091, 5260099970974267, 5044960426451952}, + {1260464362728368, 2320200151112594, 3280988120127265, 1454370155862373, 3222503455600234}, + {1286187906300863, 286639393218233, 960541512944676, 756511343610150, 732619979206969}, + }, + }, + { + { + {5720776037989329, 3408557855252881, 2836745411300455, 4905300285896935, 2440518813003965}, + {2216608521812979, 1133671267609171, 1886801270451833, 693723450681229, 2177664326279079}, + {2233307833752057, 720411965215730, 1519169695491573, 1249545629073374, 42274079495163}, + }, + { + {5289248568149457, 3817875509053716, 4457685664702894, 4876101051290378, 4294494794724040}, + {3280020244834293, 1318628129209810, 3119398368735896, 391516159010622, 618793687544686}, + {354305362086679, 1512134460741612, 359672307646707, 182487842123724, 70434142068276}, + }, + { + {3945557653570869, 3088092003227000, 5454351386185562, 3234451172420338, 4724702104276340}, + {3276624651778803, 2433844765263326, 2790865929084436, 1963658167580138, 3140414260467690}, + {46706548238824, 1986500518838735, 2027136585204085, 1143580830274421, 237034819567290}, + }, + { + {3929429576586958, 2793383744028645, 5887317021163886, 3203394573309402, 4670385004087593}, + {3462257554153900, 2215903401275259, 1545855048122212, 1560256833448838, 235678314205821}, + {1032532177573683, 1507169914894481, 893954872249259, 1464210961075811, 2248024514969267}, + }, + { + {2517873563818259, 5567259846017152, 4253295986752699, 5558170137710973, 4039120007239859}, + {2215196432839229, 1453988298479780, 3162959582154309, 1417180860727485, 1916001465630095}, + {1593076635649167, 613414152324278, 1398118686752976, 1550186634066418, 2024312475795755}, + }, + { + {4524027900175525, 4847878416694692, 3091409665235077, 4862578993236379, 5350599804185218}, + {1611115816843085, 1564686497935112, 2631443498765253, 2543391790063645, 1070282314438176}, + {1370619542022553, 13593976629245, 670888839522668, 29909561835083, 1113994299778657}, + }, + { + {2995680265327027, 5241715165954044, 3953258701883675, 3989602332635833, 3953848187775337}, + {2462467670415027, 3084380814586442, 979195344857407, 761623507948939, 2354116769190033}, + {1653806661942935, 798938977173667, 1204504651898865, 2012775328403335, 959133953735021}, + }, + { + {4988340255562522, 6250762111649497, 4210027774413747, 4281026073914171, 4124289570254779}, + {3308091097868222, 2438171792492677, 666572176305849, 2221533064225315, 1302577527793701}, + {2246982488380161, 704048527252770, 449031029656446, 2000971659049725, 1830758195793359}, + }, + { + {3190675561821798, 6722820056714491, 5018399111078811, 5991624407670525, 4249280343842061}, + {3052270247598664, 2252472217742059, 2434081171992329, 2672797197928279, 2602890651310523}, + {2144671346446832, 542864631780587, 1155108742000404, 1404732713614448, 240293866423412}, + }, + { + {5121381423145567, 4833873167604293, 4028173334112257, 5524034306881884, 6230562353876706}, + {1307308592059221, 784383479594685, 1720750519626457, 1912081034355222, 2024784929774716}, + {22174994285057, 375276401373336, 1210941030392323, 1903374444438123, 1011323371888298}, + }, + { + {4798470629258750, 3939993567755513, 3967862752630070, 3290332526819821, 3061464921693387}, + {2998794565294986, 2057935584763381, 2899577223808862, 1519188817940759, 1842063844888831}, + {892208073348264, 1880270486117637, 1866139692669281, 577642276098528, 159304923876906}, + }, + { + {4601033632870689, 5799253896657058, 5779104046600604, 4218473381777077, 5066296163965867}, + {3118817410699903, 1416293682313136, 1358642285736990, 4016697695252823, 3785048363131621}, + {841452637470330, 509851329084465, 315943768852800, 745051417948746, 1317978823624451}, + }, + { + {2960724265045759, 3581409910547792, 4757575913235420, 6009932939538924, 4725476498610383}, + {2216474880678649, 1883045416719140, 3557095587267860, 2414252121862082, 3019618269128831}, + {1790146986408439, 1266311794146205, 923857310756466, 2043374401317120, 726369229085659}, + }, + { + {4878312571596775, 4222794967531206, 3321677379160160, 3406594510676891, 4743132105473153}, + {1047639500605479, 3268483579465284, 2206428670313250, 1688287562131353, 1668007864663417}, + {1777656298881359, 367886496899263, 1134571758927624, 161297709883194, 864111924164392}, + }, + { + {4770637647109604, 5356580318440110, 6456410085143486, 5251963198009528, 4612863117603799}, + {3459496839496426, 1172866796116672, 2087657719164010, 3611579473502448, 2226199443508323}, + {179962092093812, 1434865358203901, 1509301171184812, 465007053005824, 1606826267425619}, + }, + }, + { + { + {4321570421086801, 5728967329483361, 3790752945733902, 4440201295898093, 4632192800649486}, + {477207916553285, 1488064260202941, 1661453866463954, 1141228074051855, 672072650786576}, + {916404312971536, 1000014350915647, 1498754584389763, 67530592482209, 1667646385756724}, + }, + { + {3838511633005352, 3067059108181153, 5859654687359949, 4517853996250692, 5491933645129578}, + {810369747020164, 2237618141036509, 2282241440976077, 396142955464532, 2314156456627292}, + {498205650210982, 2029447832739442, 1287708517665602, 2063154761502015, 592549403529808}, + }, + { + {4850172605519114, 4864656344540316, 4532814144934823, 3437824613452670, 4812474608554159}, + {1466752538541840, 2035538193320560, 138132610685025, 1256421706559322, 2431850955679681}, + {1297525937307453, 1360474818962172, 1057976529132470, 481516036122456, 1284896343639676}, + }, + { + {5776741280656995, 5103737594811281, 3360081478971068, 6111393754727746, 4779680024426854}, + {2645933668955707, 3274005597891379, 2656619141981518, 1746214054851430, 3053032647501696}, + {1625278703177771, 652272403287866, 1130860155562117, 1467718191751280, 170296377586353}, + }, + { + {5094219073783849, 5735075135248235, 5606322495206271, 3754059419692243, 4180105537366398}, + {1002349488419261, 3232903243006485, 1398184721429427, 3601262477434907, 4062926820203090}, + {1577778325058339, 2215369962281551, 1331723269758849, 1939632256423674, 52886968354553}, + }, + { + {4933187999581607, 5092493367263378, 3356435735616918, 5217407324510779, 5497406740649621}, + {2729077630033003, 1888615867921888, 2296393402013134, 839924021249031, 1005736290727363}, + {1035587952296453, 772571610990610, 1703146381743864, 447715678256778, 1714287687955168}, + }, + { + {3002761637349276, 4331640081948673, 3834120280377754, 5089609293083651, 3261373019366335}, + {2386307482062396, 240967146617557, 971317535064000, 2019271157069067, 1502539203059821}, + {1328811798417377, 1232170334974369, 1723370191641238, 2166559558468187, 1898556240276951}, + }, + { + {3941047590826269, 4239692035015583, 4490403838767533, 6564872456977192, 4670461766802655}, + {1386180360119611, 3273074614881159, 1729880193705623, 2228606406348098, 1592392117444361}, + {419731549689034, 1989626747750813, 1591278351630992, 1092786235861584, 177178675215960}, + }, + { + {3436683241673758, 3662206674778039, 4373967447323555, 4097363846812803, 4031597646782708}, + {2639672814451512, 3326947991249179, 1680625793199947, 2034248047548953, 721741001003862}, + {1591050698007192, 1091674239474205, 394086386458446, 652864259466208, 252826649880832}, + }, + { + {6202959881484310, 3301137131128391, 3338332791366416, 4386834101046813, 4586134902683138}, + {1761951583445986, 1682354370625515, 1311814077921538, 2232552485157187, 352715570060390}, + {1983847550347734, 1877133028995354, 991701922936357, 942306684083689, 199141297262892}, + }, + { + {4356558984118475, 5693420396107718, 2518386381195401, 4410955637518553, 6067546162903212}, + {748677842691767, 2802469894128656, 2167458034960803, 3580904381157207, 1663021749531972}, + {672345752527423, 987721649439917, 75559353638139, 1202381658061142, 2218885179346238}, + }, + { + {4510531718276206, 5025970311617705, 4298550255570023, 4702464919238073, 3154067300975759}, + {874026063340854, 581394977884979, 2805876061084699, 3945101577343195, 1873084195329207}, + {262642087469467, 394043452244726, 1877384193205089, 135064540003798, 932774458922892}, + }, + { + {3677176615657209, 5004677940509387, 5802006239792640, 4988806137854665, 3142553109499622}, + {2906530412387425, 538942497799423, 3006485045211118, 2701192894331127, 1774793046411044}, + {2163097510860120, 1657639324428092, 324536800194710, 2127826550215010, 1492179302504548}, + }, + { + {4271383757866077, 5161359851331481, 4409665194889791, 3535427764785290, 4743868535366280}, + {2870306695118697, 854883599481521, 1175220622088095, 2190379234235038, 2693308800279672}, + {1469265779048270, 1543845332050728, 2202017995300452, 1928013995331013, 1762032763505452}, + }, + { + {4636656908840010, 5500309513430418, 4897834655713547, 3941193903783821, 4553608952670061}, + {4333916659134460, 1850388591545996, 3627944035206357, 918659547384777, 3374247281351833}, + {2000039510485295, 1183834045401091, 1338556774925931, 1549179790309018, 394428288927656}, + }, + }, + { + { + {3733446780128548, 4970314905751830, 6278139198254466, 4792154002496454, 5723581693713173}, + {1185838263017942, 1658025814770644, 2664414501602854, 2015508295646822, 2967017530049915}, + {1569664128884381, 407663338845983, 2002256010544711, 671085899312035, 984282527793076}, + }, + { + {6341328981945826, 6310526850187699, 3023871274454732, 5578860681574207, 4775900505114104}, + {2574316560560394, 2331223963461233, 2542672004494602, 3174853647927431, 3104624426621216}, + {946711433665760, 2239987349934557, 803861660898522, 2156551410386926, 1502787654920122}, + }, + { + {5437578969471140, 5951179206758851, 5248530961634439, 6426502251854756, 4209704034918088}, + {1002763931894790, 2216555692070697, 3344391891538061, 2095372815347836, 831620519830306}, + {2050669866355306, 2190774465449013, 2058969733807763, 270320273862327, 1870514939355617}, + }, + { + {5155857617776227, 4397988213497465, 3243709928117524, 5944645730694783, 4773063750957235}, + {1975814150439887, 3149875793027583, 1261444197722906, 2760429640974761, 1552966352555279}, + {1633514016507671, 758793436105214, 1666766843388618, 1223902548045585, 233185566290059}, + }, + { + {6335824036525539, 5936753389140468, 4473577463180534, 4906816011267918, 4087654058111774}, + {2368975804221909, 2457041955704880, 3876216785098924, 563819279426048, 3675362390258876}, + {2039348563488973, 248927546652694, 729506739622176, 397171022735714, 1644628056647629}, + }, + { + {5425812761915260, 3810529789490661, 5049333453822998, 4123755530302819, 5615639585264776}, + {2534643198043490, 3071062759450233, 3687767943508924, 594097030236781, 2123224284522922}, + {1869384197190792, 1569592234203114, 2196362163965849, 1717386471659459, 39685498183014}, + }, + { + {4635535175474129, 4605530976221652, 3458801108619450, 4871255059096226, 3508659268324931}, + {1421109370612225, 2276342051030278, 1620731107586926, 2516053916114754, 1357365806509465}, + {985026127753438, 120648499984234, 3776067837201, 1121956503069595, 1317952564469757}, + }, + { + {4522971017836409, 4687828520937668, 5703673191623277, 2940799383081666, 2787006346014769}, + {339460334667999, 3256039500082500, 1203428024902643, 1634973881827916, 2329743371713673}, + {1781496335107774, 734939096367772, 1979958937781877, 860043149833798, 2198713547814584}, + }, + { + {4721820132212972, 5501981664895244, 5264058468541187, 3740873078980979, 5716647821232484}, + {4072332661836284, 1169250173411574, 2007338871529421, 2541018716077961, 3008200101154560}, + {1725071616252177, 449990873352396, 128827658985361, 673241280853224, 751856515144447}, + }, + { + {3453037913720095, 3978754968490530, 3848210473954340, 4246376002566406, 5322220851863886}, + {2584349971388389, 535927716206948, 1961578137923504, 2896060138321356, 2010651373680674}, + {1156080784099315, 481555143811545, 967562545637573, 1677675896966263, 907265960192535}, + }, + { + {4332897500521172, 5216833051048471, 3346087018588415, 4384949392542339, 3375716091409272}, + {3883496497463828, 2136509343818925, 2434189290622529, 429179343434029, 2077816145810058}, + {1658461349569569, 1605536581882396, 1366404149694713, 1196969327840593, 1143971682907018}, + }, + { + {5400721311066691, 4902133966014442, 5147618958116264, 4262202967114947, 5920636443351740}, + {3544460334984043, 1818177095892812, 1745908205006280, 4216608321683323, 1892854460405668}, + {665225119661694, 619309150141627, 1122802004923883, 2010090924812740, 381608939276442}, + }, + { + {3196661699712892, 3684791960878407, 5290400087132528, 4583612441617304, 4269495094598113}, + {1614570977912342, 1623735166790269, 2524803999133080, 2496475358487958, 1935280705616725}, + {1092465046248360, 2063398303783148, 1002343547076250, 391684155494682, 1710560533943348}, + }, + { + {4070608883224340, 3070202986942604, 4904606928783937, 3666937738681094, 5479190180948687}, + {535566969681230, 1737993760203276, 701172348317595, 1733855888978568, 2134615712849277}, + {606893040022944, 2129386574985473, 1699765919891957, 528478848080626, 79217852843510}, + }, + { + {2896556608610982, 6055695907875122, 3732440132349395, 5309166170174244, 2721831575240156}, + {2885737548308128, 2508747900193688, 3606366888469287, 2465312058009042, 1828731582217566}, + {1349811289350391, 1890659682051631, 851360755267261, 2227128394068535, 1024384097528052}, + }, + }, + { + { + {4787547620178774, 3158654330243465, 4256768153665325, 5186246574371168, 4755687815664005}, + {997854281022512, 2623211910140591, 385221936050651, 1659016544729114, 609442868038809}, + {1619428378651736, 1579845830028655, 3625310117685, 170605089295866, 1149673757755609}, + }, + { + {3771360214195724, 3008816652878868, 5465610693671022, 3583291267492728, 4869891036079898}, + {1431189333362726, 2522236815322768, 1841157954619916, 2384464325206820, 2357706544622962}, + {437646608465794, 2094793895484999, 1468162389698058, 248477625893392, 1999708435919408}, + }, + { + {3334695520371433, 3812203917821368, 4517495595943886, 3819008971940261, 3192333158392848}, + {2403562525071701, 3731091650393632, 28706304084430, 2945476990326655, 1695373042660190}, + {11430723322929, 1391830113841252, 1337273140327877, 418617211527096, 2156223821909844}, + }, + { + {3474862062180912, 3882457043015231, 4997421855422554, 3623087331366693, 3980925476191710}, + {2057796043232644, 2263408613360807, 3848582899143280, 1729533403820747, 3162991736601526}, + {43999776827657, 989331901442862, 147120313740048, 495021300047603, 2007031690017476}, + }, + { + {4569310600539567, 3932567990833912, 3385323568255113, 4454797311017655, 5850805500278008}, + {166834800897807, 3648978260893606, 1512008134852981, 3519745367019255, 2891621521405984}, + {1308871835809784, 2116706717414875, 56029465436904, 467188187972025, 1826981082270550}, + }, + { + {4470097619807732, 4636615835029003, 5384758368025606, 3313145881106330, 4330528852662105}, + {1956939819397260, 3815569263781231, 1153022458216286, 2428547349977954, 223633771534995}, + {277297371046776, 1016671322777094, 1912173712739697, 1941234701885292, 1286651577841525}, + }, + { + {5516226444917799, 3864412772019280, 3317545876897683, 3844965839466476, 3985391436490214}, + {2680601238774939, 761018381922150, 3233893633186507, 710728397015564, 1856525231801054}, + {634704084825404, 2129536576841980, 1242863233687290, 1573321106629022, 128474589505663}, + }, + { + {4461600283819019, 5688762331492453, 3571771069068464, 3623234953171514, 5735065250408243}, + {129496500081781, 1790297098324227, 1302842166366374, 1122296729486616, 3168849968185895}, + {627678063257079, 716314893721428, 1223825394014331, 504272345435927, 1599415310067837}, + }, + { + {4497146074973338, 4258524581640411, 3327175345569250, 2988994176227077, 5267912111147682}, + {1802641032705090, 1392499306540523, 1496089620367494, 2312128812044035, 3539470476015736}, + {1352081061607517, 1142882484908029, 664622054563474, 278618602320570, 1557574337895879}, + }, + { + {6186532378029907, 2657902210141327, 3418543318248038, 4786173749208350, 3954647920849896}, + {2160964425547565, 2522131549551103, 2469825005211132, 304256310615628, 1406273379451890}, + {66232156124863, 1741674194899368, 1229742843930407, 260078220485178, 2065725536502563}, + }, + { + {4851046938453980, 3469458552849808, 4088972952218884, 2434262635154865, 5173422452060032}, + {2864583883600790, 1179256560411448, 605392730024768, 2131319985409857, 1797303368136290}, + {1658701641668087, 42705500105455, 1620862321227524, 1064411845535234, 1929505696020986}, + }, + { + {4163795150867629, 5312083389544253, 5442631052553893, 4817195733891862, 3463190319377281}, + {1759675286353623, 1663207329829539, 2312695704742071, 376287419379108, 3196993252356633}, + {1986557906737275, 810826505070108, 96017120328357, 1696299441261906, 1606104856145766}, + }, + { + {3549586047215341, 4636877962062236, 3055155796794642, 2987219577785020, 3528907845687172}, + {3376650841822935, 1032192126856158, 2069071282143034, 2845533170222998, 2607538492640606}, + {1660552858343061, 1231765925349274, 796446050473330, 1786065193241069, 1494189638115097}, + }, + { + {4395801598993052, 5237162742484602, 4130001086185514, 4318996219007855, 6361901289989183}, + {2175013070553356, 3320762044970614, 1143129099999600, 1532959129324381, 2553098860474181}, + {745372522040276, 1748456103797955, 2181743850112213, 796241938657904, 1942989014453742}, + }, + { + {4940563260328687, 3680309631021837, 5780417720128217, 4290252794057113, 4860748118629541}, + {1446945700457117, 3425847613673611, 1973622627786407, 1807324498582473, 848150045623407}, + {1097351026844646, 982517101132756, 149747537095472, 442788546176214, 1331800448358921}, + }, + }, + { + { + {3048999410076971, 3892379313272499, 4501182485180276, 6013415726786911, 3538900302869245}, + {1912748982362695, 3472588964406961, 2955977531735648, 2975418449611955, 1539793845278547}, + {2120957025321772, 1416788979770990, 1248163529640000, 1057479098339217, 1345904049070916}, + }, + { + {4595431001667912, 3778027149812221, 3607566563474045, 5108294493186449, 4683353521871733}, + {1020723204932740, 3177502390904871, 993238884888759, 1734688533140183, 2122148469059677}, + {1672839208916523, 1716495024680343, 1707076061183264, 765180466790910, 2017432747304428}, + }, + { + {4097011095397840, 4818396343707634, 3336533547899513, 4282281512848069, 4911825398741721}, + {2414052521429936, 1593372837632108, 2670905511225157, 3908207528779377, 2363908827003723}, + {192171151121229, 1275967732855104, 1864584199775891, 1693406950762857, 451756333138903}, + }, + { + {4727218507536765, 6731370918172898, 4514881522289443, 4346751476412392, 5345399511692591}, + {1612422054090625, 2236845889213344, 2363747608937251, 1594023725720586, 2961152477238633}, + {1485832258557624, 680071864680695, 1288498699771584, 258483455916573, 1782424270254224}, + }, + { + {4145911876469356, 3824464555215015, 4696287494265278, 5681915693477289, 3460241462730997}, + {2899290323536300, 2148582833270035, 4306072922611340, 2565743726502417, 1518458853723029}, + {1953522143805027, 882595907666496, 958109305864079, 1523427692628869, 1741273556819203}, + }, + { + {6076430972133454, 5015736489916628, 3553768171633221, 4610709058364067, 5082978176345714}, + {2177453523879316, 3719629127010202, 1578609310805205, 3246652757763105, 1948868370865272}, + {2160967413246114, 497546389595616, 235866284515227, 1209326819476215, 385381334474653}, + }, + { + {3922495052587829, 4494539022460083, 4247467603322628, 4394626550110741, 4540112411631648}, + {2794088217731505, 3925821314042297, 3967932263264306, 599992304591101, 3777014795396442}, + {2143663924692386, 1851559468934078, 1845266597269129, 477022990956902, 2179267609261901}, + }, + { + {2757964045702557, 3562399862100370, 5308617563064155, 3110477941637017, 5056214367828129}, + {1958983221377553, 2178877734404748, 1849996731612977, 1835657059247969, 2041180109654311}, + {724524272708234, 661221141789934, 1298795839460575, 1322772218421097, 837427426454482}, + }, + { + {4223608019735549, 5288655260236562, 4785575153888318, 4056483408937593, 3471372655277242}, + {2219315301228611, 1125545597629890, 951081168531596, 568553052705851, 1412860720276020}, + {1137419035579219, 1404302123897914, 70650994795979, 286534554383837, 1248950723208565}, + }, + { + {4430704978424231, 4715040112563554, 3462858870799989, 3675716202870984, 4333024567010524}, + {142500909440961, 3483510976010918, 1633124654372333, 2818821059903848, 1198913332019644}, + {752727997883595, 729011045815856, 344467882917129, 1083479075474047, 1987011026378575}, + }, + { + {4459355955251918, 4177516598428064, 5081135773938774, 3284517801964245, 5485650974376915}, + {928716952855914, 4109673353080708, 989163284951296, 2771681491221325, 1739599539253359}, + {884564007355359, 1882230710793852, 1848620432404050, 211924733371920, 1690861583639863}, + }, + { + {3370568370567081, 5191721693684414, 4210754480734108, 6164440545771688, 5649472005268314}, + {1901455587402533, 813369714566932, 4131962295906966, 1890594180896940, 2481388378410460}, + {226931392632329, 1641783547024066, 245880824976242, 244030597682497, 308840717750219}, + }, + { + {4699529728790440, 3682875431198511, 3687823620487174, 2935047689154352, 3634282712140374}, + {3094491104014232, 1130377028133465, 857472228100160, 2846610482750732, 1997728196650988}, + {832395901935430, 2063621809284227, 195191804737031, 1295260648818684, 140470149874586}, + }, + { + {3598626358333843, 5555876347138442, 3551001516031801, 5418563562930746, 3796685043861386}, + {1119383319424479, 3370445532080284, 2202737095147899, 2643552313073446, 2526474007824020}, + {436475423231066, 206987015606375, 214066996087725, 524361410769522, 1866248992304042}, + }, + { + {5215692725695751, 3669441050652411, 4674665916750844, 5316221279699436, 6443632653069401}, + {1081002530185607, 2909820960350251, 3592240835659126, 2824950488355670, 2408518769691813}, + {2202470261312694, 1511198785606944, 1434711629178163, 1742102768767586, 1282697956395292}, + }, + }, + { + { + {5324690866715337, 5533327845613105, 4036930034597607, 4638490931056674, 5650412235017737}, + {1638260469631915, 1786040878698661, 3158389239420729, 3835314628196980, 2413700758553481}, + {960395712488566, 1090263312831733, 1493488072165035, 718337273853885, 140550395520083}, + }, + { + {4569832948050874, 4985100205291785, 3844846206585447, 3819690642434847, 2746468303866686}, + {2833809135953840, 3714738963129863, 1699035707213511, 1260336843200283, 2274544359656356}, + {447501697246828, 643764017641830, 598739660833153, 477276555234445, 722964385617133}, + }, + { + {5743873914285031, 3319094314541157, 4059899116934908, 4330486197588569, 3357811959011823}, + {1468688697571051, 2930932730830707, 2981359468083280, 2467829883996923, 1572642054261959}, + {601523810297856, 895074627148937, 773977692709653, 1905383167427875, 1540507530397039}, + }, + { + {2901461178567113, 4994292130181829, 3331309663039004, 5793381747506001, 5040143301404956}, + {2651347872114579, 1239727848347325, 3161955024122276, 2712053429837225, 3725184595174532}, + {1148448246837183, 1915539016170074, 727268432049334, 838952046766961, 1100979659516489}, + }, + { + {4313788896597005, 3731391587318928, 5481675874227619, 5342116794928851, 4858074158134343}, + {2801484252789311, 1308243333207398, 3101163188310017, 2902551501956635, 1782136170508091}, + {1354449553272043, 1085110494903468, 2224048655022783, 1932600057639272, 200912869737304}, + }, + { + {3988802802744946, 3054267513827163, 5506469409446024, 5207893419318903, 6705457585999423}, + {768379161979176, 2950328772092937, 1384131174334606, 2825110025249585, 2256845801064479}, + {1328818899805024, 1356396048253838, 60665341223248, 1567700157316511, 290562887661571}, + }, + { + {4789838652012215, 4990599721334973, 5868836171113556, 5456092296292492, 4808665632941719}, + {2083771618977947, 3859777942731437, 1586868936731178, 2520556279463752, 2196980677006699}, + {1179288489475667, 394266093483806, 2023843107238627, 906600297586329, 1987935808498095}, + }, + { + {4852377011852760, 4268226436451965, 5725799343439052, 4170083215192005, 4497273560337215}, + {2190648163527070, 1182302286459911, 1698709705179966, 2858053760026903, 512030280417031}, + {1766029976663583, 578113072554872, 1407762358462124, 1251410333318914, 1519685697291309}, + }, + { + {2425211004658582, 3219329122771349, 4160786304284559, 4915538208049169, 4859858046454066}, + {2165465146173096, 1900611060212209, 1042730545588351, 2014093929109019, 1810920073473014}, + {2188210814895132, 862494540176239, 429026747909695, 420692388686242, 398456856483386}, + }, + { + {5384113697440972, 4249326538414056, 3736088109548391, 4776181701890428, 4340637335144904}, + {2182481135659358, 1214620204337280, 1322637461359405, 3608648111407434, 919105498759084}, + {825616994407031, 220978982016139, 419943662189285, 2047052177976116, 183513451940769}, + }, + { + {4383853436467396, 5616868348446865, 2380427384672103, 4007620388627955, 4745758889436972}, + {3034925520134716, 2558549339328923, 2273570634299175, 2355590727329921, 1721435535499274}, + {397259122369220, 1632965024772390, 1358524229763907, 634652123170537, 1300732316858513}, + }, + { + {4537722552642641, 4406953311574034, 4747655843802439, 4621074214609984, 4656289262373784}, + {3211235434961971, 649442782529810, 632841582251763, 3220605671079152, 3939184634719634}, + {596504540509310, 1411595783429460, 320205765945468, 1703829528897671, 791135694264620}, + }, + { + {3935303504608645, 5231587761610764, 4492307054736833, 4099267906214233, 3895141043651931}, + {2905973217158121, 3180461607923868, 3881652820548741, 1616810006326533, 2007934577851039}, + {1723586093910128, 42167711405468, 711328489930847, 1802621686437750, 138939056743574}, + }, + { + {3535285454280039, 4143874578497438, 4378537178006869, 5183808895312002, 4029558557190188}, + {2822051371235755, 1171790929970038, 2832133858385125, 3449345178331124, 1343246277400448}, + {201514708798683, 714458960438240, 193526864900221, 289856941669808, 677692044183495}, + }, + { + {3390373253525299, 5571978408447513, 3881939102950573, 5664584550774172, 3541416731496846}, + {3067220342787603, 1318716141230895, 859940092247599, 2796965663112684, 1325031219234520}, + {520206601828502, 827736556609109, 1548115289807569, 226762337353952, 901425653289102}, + }, + }, + { + { + {3876784047658153, 3427402741453803, 4260413043643610, 5364266100628625, 4512454692213601}, + {3846988412720927, 1464526558278043, 4150028797303466, 3612037356861449, 561355623244019}, + {427225699371050, 88989906931284, 374954954790275, 1891881595245671, 72849256625193}, + }, + { + {3916811195383628, 3630554563432754, 4990637953666720, 3851134441999325, 2556181869064802}, + {2335839984116276, 1931214780001052, 3695690881878730, 1666635094108941, 2394874384507690}, + {487618024041635, 1610635862259296, 1930277174961405, 2060246530132043, 471988063294585}, + }, + { + {5204676678666455, 6002573394041257, 5469218649554576, 5103810246282644, 5450232393144287}, + {2223680929791699, 2255695602856973, 2223372744379624, 2581758136991750, 1157672051964719}, + {1191620799152162, 584262428445493, 1654487633336816, 80589900150873, 1778885798645876}, + }, + { + {3804876885771689, 3030718867413702, 5084806164730577, 4351829583495248, 4696365675416595}, + {3277232365416075, 1648743746278574, 2268484584766767, 347896520603034, 3388269197255745}, + {437947250844137, 170970937295705, 294909197597269, 2210849722009323, 1802271999575202}, + }, + { + {6229784974313861, 4445187233108198, 4141897661886957, 4112739300676286, 4973450766687119}, + {2452873695124259, 3183518466635188, 3225011157480339, 1530254508436786, 2236389510678133}, + {1718640585909930, 289464657861405, 256448940553760, 1840710967168708, 1367355358576031}, + }, + { + {4418094237484866, 3862166158397851, 6312584233293658, 4170168684472692, 3205101920356659}, + {845231506816104, 3749601727822635, 2431461776355856, 2145415545771870, 1633953832787249}, + {1855071951306216, 234835319416374, 608676288546844, 311106921331784, 1424607004261872}, + }, + { + {5534887235292980, 4955913319898744, 4436282654044178, 5157071574798331, 5799145956361697}, + {3127590738217404, 2607909890139434, 625984861031328, 898713331800149, 1867577233264451}, + {865238419718368, 2167660602098967, 849033435333870, 1879862001988212, 2194604163295964}, + }, + { + {5028901701646599, 4744711118820448, 3470202116031185, 5070974802044518, 5029459282472967}, + {2597573876967117, 3500480183251406, 3245567533116125, 2884144221342044, 2745802723161587}, + {1262037831799441, 1761445988918060, 1818282615037362, 643977010061831, 1670449776207217}, + }, + { + {3900064283125076, 2932367474353790, 3722342375883231, 3973709010425436, 4168589452466075}, + {1182011269637170, 1702301475425876, 1754593023447641, 1069325582888970, 3665084705482905}, + {1389152123534754, 679131622889370, 1335753122628610, 2193861582528949, 1750442867995809}, + }, + { + {5195225631658915, 4626594891714746, 5530846200979591, 5835469573794033, 6108601962615813}, + {2118803625617181, 1938389959549060, 3158628651247723, 2603939933464505, 1887075807282899}, + {1094771758119662, 1784696951595960, 1586111086846247, 1024621381632866, 1336860396265070}, + }, + { + {4962714218495987, 4686221014092595, 2854843506884281, 5460710344297905, 3609844163230280}, + {3350136365379549, 514082045997139, 1809601258343901, 1359082981819817, 2325132321451910}, + {816435505147956, 959029754172122, 1905562189095432, 809602990954940, 205405869295}, + }, + { + {4658319919071161, 5037557822453179, 3052863244608605, 4920651274442715, 4594868309263967}, + {2357418342397899, 1599797957446167, 1723240952262061, 1521319741808023, 1244021174200017}, + {1682663787527018, 508342182938395, 1334960042435994, 788285033210835, 1620852797020940}, + }, + { + {4468831118271270, 5037652592706325, 3842859113890724, 5119527774959881, 6070895395223645}, + {2858969631689118, 3774837200669161, 3030920205974308, 3569621881524763, 2272136016309579}, + {1457792005629762, 1504843532852533, 117754270187566, 1653728802150419, 956441650806976}, + }, + { + {3858799123389730, 4813864196253754, 3424673118223091, 3586667532616773, 4976228037682591}, + {1240797555104590, 3504953395544138, 2270523358088921, 1192446004554973, 1265977430218831}, + {209033356623489, 521030133202188, 2210759687093959, 1391735568682749, 2066024683275958}, + }, + { + {4447381514683745, 3805818101586919, 5048484781457783, 3805764540626535, 4979430662961349}, + {4372830229780273, 3385211896687553, 1322477629921689, 1744994285972241, 2453525332947167}, + {469280089327132, 1530255390484981, 1847838662987617, 2225747405410001, 1682362262024675}, + }, + }, + { + { + {4202827224002136, 3028138102214431, 3666469969152450, 2607795400549083, 3461406593763699}, + {2143318224651032, 2985185441001099, 2506505238926850, 2498470302228395, 1442295963272081}, + {2200224066087308, 1167051805827953, 161446888552827, 1516422365939770, 1942535836845300}, + }, + { + {5171889208942910, 4780829163437052, 5016462198638337, 6470156341077032, 3046275441821918}, + {3482226206224520, 997104644926830, 3305574633418067, 2147764348670690, 1676514761128454}, + {1628314393858778, 1997743320994668, 1561201521750924, 1869590045554733, 1810714681142288}, + }, + { + {4681454419314826, 3433609902051237, 2919531098016978, 4380876633130549, 3072926890864646}, + {1675422916543594, 2672408744787477, 2759217149054666, 640362125760161, 2799605921604096}, + {1484872832783728, 72255685107270, 1098972476164964, 1732914770170238, 145186792002379}, + }, + { + {3935383441158753, 4973709539651372, 4161806475746733, 2598419220788322, 4556716999515219}, + {1372652207334635, 2531888280983978, 3771287204988285, 2258792327010408, 640671581341507}, + {156581553787681, 307978851206907, 1451582278870485, 442722234791876, 662472042575165}, + }, + { + {2866740058396235, 3493635817947651, 2400937210085123, 3122677618181344, 4447500274280321}, + {2082652078388943, 2745645971502049, 2295760696601975, 2362848920638954, 2370414183207021}, + {1712668510139487, 784271226274642, 827073136956465, 1001465329762964, 1662630974562798}, + }, + { + {5156175574821430, 4359502037960358, 5222120068062442, 4645531980214215, 4676244221442153}, + {818080711416948, 3611895686544640, 2535691662679364, 3086441935441805, 787978368976315}, + {1509857525874286, 1496970584948645, 399828714647739, 1863753979948441, 2149707660031809}, + }, + { + {4144865997618639, 5339859640465925, 4438288719418715, 4715011715150674, 3610459694506906}, + {2952195132229463, 3345568150314393, 1768906295222689, 2025477905414216, 2995593107979034}, + {1951144383031056, 1085048452592587, 499199223423315, 2055889411465929, 698006601614245}, + }, + { + {4183964222033211, 4817865139479783, 6220809882369837, 3643181163556103, 5929569705519063}, + {700816495675241, 1165569165048171, 2172597164236109, 1071655796287173, 2392628493878193}, + {1862104717906915, 1752261107932084, 1874923294613947, 1008681858018398, 628821150989939}, + }, + { + {4161348428018682, 4510282473079517, 4817307873546246, 3901464805798077, 5820970885668019}, + {2393760120508366, 2923675062487769, 3447512431195440, 3853675368087017, 2900110716170471}, + {271735680629051, 645447398246691, 1438808971583999, 792432482423730, 947645802664175}, + }, + { + {5548911597254848, 4313111803014757, 4159094458160020, 3906456530516599, 4703406736341543}, + {2468698810952212, 4159587806133767, 3895277333299798, 2370621230252749, 366242246574179}, + {1891237336529861, 2200322075990278, 1389309370267760, 1284260243869154, 2019396638376055}, + }, + { + {6612681523843925, 4270864305450289, 3731318918021201, 3544862780769488, 5178202040634906}, + {2135755065262843, 1122607271257525, 923542923082409, 2860818598984322, 1922554972749380}, + {242471180181642, 559887731579688, 2072408437063313, 1092425853708654, 1508919031894623}, + }, + { + {5872377157668488, 4408911728296550, 4215455815151923, 4350437538061339, 4304102307657902}, + {3016579539029836, 3430456847285690, 2439572409111001, 3210834728649259, 3775979784664836}, + {681181014012506, 1995504690201206, 1747715035603252, 100305442172708, 1898381133318416}, + }, + { + {3131841243480282, 5236372530773376, 5021877536268058, 4866190361541948, 3290429298804025}, + {1471590353308208, 967056793878588, 3802522075784380, 4004598771731972, 2024618065937019}, + {1109658864423422, 2103734444560570, 2073023657041166, 369769649281723, 817132219307245}, + }, + { + {5632635968843701, 4247258704551623, 6265280169576672, 4815811703628991, 4268679712320579}, + {2186780367255445, 4183850462668485, 2677999934662660, 2880987810780319, 4113828005081983}, + {1441842413844030, 161967823757178, 143843657267759, 468984586211790, 1403635869302761}, + }, + { + {4465016058776751, 5317359619864273, 5237005983845137, 3609875861871372, 3464614715951065}, + {2238448064725901, 3110619177809235, 2162294075762619, 2319911679772150, 2285011619226311}, + {19804365830533, 1686591959644968, 641957734952114, 1534607041731245, 2021106986001419}, + }, + }, + { + { + {4685063337509321, 4828498939602920, 5252037453775058, 5946493173698145, 5385655016202805}, + {944214205150673, 2365379166371694, 3557291173836860, 2962349586178017, 1508433893219247}, + {99837384801727, 2128746966172064, 1728087272474317, 1660968164341303, 2094478837305487}, + }, + { + {5059816654277047, 4494318859907208, 5234935703112714, 5064000806734505, 4673368238982494}, + {1045092786794937, 922156857253434, 2823065772236182, 3280047208436923, 400144133024674}, + {1350540322092981, 428507123444697, 863081413402232, 950089447398951, 118865435494230}, + }, + { + {4685872193140817, 2986094649249487, 3994164430284207, 4339988837278092, 5456344527489565}, + {1863120758931529, 2615255562194237, 2546630581550601, 3581241606812888, 3495878108380709}, + {317239144147936, 1378693805440304, 1613995646839215, 1790616997152168, 1664744641804674}, + }, + { + {5168378766438094, 5613439416641824, 4644053531787994, 3823661418550054, 4036137961950509}, + {3162078769819650, 3145982897294820, 830213734772942, 1343060696486484, 611721765217825}, + {220994375354681, 1633125608855915, 2233079832150828, 144297568151940, 217868145580028}, + }, + { + {6394803792754188, 6132368335021053, 5067197744306631, 5563640033331609, 3502674887523375}, + {2185253522527390, 1722061079589371, 929518249744037, 2473172243807197, 3427214482375105}, + {579681536856473, 1962714631533051, 518559321779053, 971489356480100, 509262501560864}, + }, + { + {3925113491817113, 2597442932750426, 4547336592857079, 3567634098715516, 4305879739481027}, + {3780232691597615, 2387499794027268, 780855157188913, 1744928736206446, 1837149863417515}, + {1612827416827303, 1149821613065205, 1844912308905994, 429769677786205, 1866058244678788}, + }, + { + {5323969415910835, 5007501896425241, 4051100888248418, 6293526281093731, 4819708586854638}, + {1087967203355487, 1504313118437159, 1271975234407042, 2125305808015759, 1278369242007838}, + {2109491846902798, 1459244188614787, 1145316246074802, 537401043713173, 2076110035136585}, + }, + { + {5420343519672736, 5167540178478133, 5227270808193702, 3857502656954627, 5090553389549522}, + {2543056198437618, 3682981507069573, 1492922137755706, 2553269698918225, 3362719634517442}, + {641798503068060, 129975789967638, 2167736719761015, 31631641435626, 350785183214734}, + }, + { + {5066057417347081, 4106102383764030, 4636402204189217, 3166449457097492, 6512612113974837}, + {2326671091720579, 1608331768972414, 2153369779460415, 2214666295188594, 2144539481917009}, + {467300109694399, 1693264194394125, 270333528447105, 650109201517682, 1183509432017698}, + }, + { + {4980219730800404, 4347683389360629, 3797217994168414, 3968193844610984, 5065496827863311}, + {1399648064845078, 1606346276621799, 2881852436764688, 2553259795593478, 3428187511626105}, + {301865991723133, 208252052427984, 51972802328726, 2021710333754506, 1378508945174500}, + }, + { + {3184436513057976, 3574184872992923, 3980701068825082, 5420309832432621, 4126883464345483}, + {1378603098333140, 3238698568766207, 2846856431574260, 3096436218915115, 3811649319155499}, + {847831302663356, 1506598425567944, 1109350264779453, 1031639907526886, 1887329321191319}, + }, + { + {2729102328832984, 5496148280158443, 4624803589574900, 4730709608222510, 6347472137270048}, + {2243355286660512, 3259846408864417, 1913072889496856, 753019988978676, 2074854260894060}, + {1050426720469833, 301805153257576, 1393268630450121, 1286505995795045, 1587323866723540}, + }, + { + {5177553689561919, 4133777550475335, 3692495435897478, 3458719135916346, 4458613993531757}, + {2247714139881915, 2782180885900161, 2312112468846576, 1680267679651832, 1590058688526667}, + {714977855392027, 2020332496651261, 1788558438911234, 1873232632822523, 503071332489421}, + }, + { + {3928537419758315, 4962617917721336, 5009684278125795, 5080330424879792, 4736452659996568}, + {1885791717393579, 3608519904666432, 3804656767054515, 3734399316619142, 280860879781734}, + {222453425419780, 1881231455372494, 356159674087381, 2031436073565603, 1587722788974501}, + }, + { + {5557830146603019, 3189235339941465, 4073380612031396, 4406171020530468, 3729384279482635}, + {1262604590990019, 2611597233679237, 1167025725287256, 4282778604598424, 782190165854895}, + {2186405536221393, 1904322539012708, 152608078674767, 560457311616919, 22952815837658}, + }, + }, + { + { + {5410522905087843, 3457067311541871, 3734790664132962, 5317892036251255, 5789103873795877}, + {1051236049852089, 3090035912523931, 3653329677163146, 3071361720175865, 1695547314615009}, + {342012360452061, 1887029215668228, 1155449753977691, 310762800506541, 1868750527042639}, + }, + { + {6005811139638228, 5026414264668887, 4377100252408278, 4270582517957803, 3422272486715601}, + {2698577143176842, 1182111476573107, 2613378546611642, 3220851371976805, 2803670963190147}, + {883746203814773, 276737323512287, 2229390196673160, 2155663378443822, 635390057802745}, + }, + { + {4097156896954595, 4786624081470779, 3512858804636033, 4586748051134289, 3866073874774231}, + {840689961188261, 2918655679606741, 2236632145763387, 553161305644429, 3021893411965909}, + {1649953183870355, 2176771717569818, 1233096109604549, 1152511702037810, 560573824644263}, + }, + { + {3626792084314328, 3138501138424139, 5501515071454841, 3948607545905590, 5453543250308683}, + {3279453112825750, 2682669747401601, 2291239772155005, 3644653666115630, 3532224357711467}, + {380965098906693, 835788132761480, 2232989119976139, 2205277179143298, 1175904351372329}, + }, + { + {5088419201363648, 3175894686165450, 5299797135086175, 2983523363221301, 4220825923293130}, + {1276840412816828, 2771169526519092, 2136012615148103, 2431893903507465, 1217611106137226}, + {2073239372536943, 30649016949678, 644492521678981, 305840627193069, 109901429265295}, + }, + { + {5139707358045825, 4688671704193624, 4352852502302345, 6384641621021538, 3836551482242832}, + {1192657509706017, 2505894684845872, 2556098156240875, 2309411544504528, 1820864150951982}, + {1002466072624564, 1231676492638173, 1795061881446222, 564780581799518, 2025621015597595}, + }, + { + {4858692159454824, 3985618384769197, 4768611969748369, 3070997304216167, 4648245907091308}, + {3367644801750200, 3754604094141859, 1751381457602879, 2418709533236081, 3882122160708146}, + {374714050779396, 405289438859672, 1963133877676048, 2112584561135192, 1143185401022561}, + }, + { + {3846711807981435, 4505402219442327, 5146862869313170, 4623705187751987, 5565609289355471}, + {1926650836092769, 1141267952622767, 3387976667434360, 2038056869767013, 1320936551384977}, + {283489509389185, 614480115735096, 278795579529276, 1166609138076060, 1715497286463476}, + }, + { + {4275758633577087, 3861278996194559, 4466252217383748, 3665496078445880, 4058888268167473}, + {3871692294074427, 1764539273907035, 2887939385751194, 2243961968498350, 871865948439469}, + {2109468136302879, 794757759853720, 236685909745726, 1503678842333224, 2147818470882973}, + }, + { + {6104878619412512, 3485890441294438, 4220586739682332, 4017322426737508, 6001128289990864}, + {2677372099733352, 3437936829126546, 1424452207982980, 3507913002098314, 1735468130831162}, + {1938075620777682, 1762081466410536, 1564991344244054, 1376297777594771, 248036172502508}, + }, + { + {3778095331789531, 4910813465857036, 5137553967349467, 4984396828084641, 3687371747598377}, + {1479550570874507, 2294055327463876, 3724831818626703, 1654245262468829, 3019040190597313}, + {1873423061916096, 248167770548070, 903648623666602, 2087943940366473, 547940262578569}, + }, + { + {4725001988101218, 6546220549270451, 3469130078731384, 5687075187757928, 3413336519371176}, + {1413358533598756, 2252005803690891, 1458088388485468, 1671589233622260, 1797166284473808}, + {523276182513223, 343307024193534, 937383689926833, 1330219799726239, 2232356434433501}, + }, + { + {3569532147039540, 4195918401728545, 5115321889044388, 6609417783186476, 3958938427322120}, + {2397395505704106, 1262743052475361, 2547892063055852, 2321536665849090, 2021113849426924}, + {141428615990698, 1565258204511290, 2188430123291708, 1781055032390171, 763358600759749}, + }, + { + {3906824289179955, 5654339223566203, 5504976063361072, 6361176910130113, 5155227057638370}, + {721005728190537, 2847737995575099, 3056729868442396, 2393716554993649, 3467469336561398}, + {160800301986322, 534920738504617, 1465194074759867, 132949302971740, 1176455782582044}, + }, + { + {3433889410020031, 3665956712149865, 5366646390977683, 5367384152674927, 4795948454618784}, + {1902504950598053, 1202752625490289, 2565725054888499, 3023474686925025, 3059561010324150}, + {1935479944158543, 1102588664377385, 1651606970291190, 1048887489959304, 1677042940335362}, + }, + }, + { + { + {3858553186233324, 4192597543704949, 4422265554716229, 5060918874051413, 4251667779718110}, + {2960733565044348, 2107676482823115, 1657279889267301, 1609984394439769, 1082526754413784}, + {1823622181083017, 408967151178094, 2033143529389867, 2209724434343478, 918118538477317}, + }, + { + {6088716933512995, 6116095372188681, 4275776721065459, 4475819482692536, 4685952285527508}, + {2842268335288737, 1888183319191451, 3692488899816305, 1677336684221250, 4176880757505444}, + {463491021439363, 1750609461077078, 1169967881279297, 474253519600450, 901070375860211}, + }, + { + {4400692422952866, 4659690717529996, 4722795303748102, 4016471577087528, 3702653606869112}, + {3485976485792634, 1118156106770038, 3653108520059592, 2301046652704138, 2381698882921202}, + {288029433804634, 1918327772711516, 1858109617364668, 1548745667412753, 1635036158704975}, + }, + { + {4899918186072737, 5587073618198231, 5408433162977742, 4217274871182020, 3058703542950255}, + {1915560744141461, 3219944346867669, 1684794323668364, 813038486884416, 2736974530406253}, + {131383425958682, 1726194406199626, 1195125520329959, 1269440178344704, 1934708138886976}, + }, + { + {2560939345231273, 4301322442066007, 4073130192422468, 4440850393019204, 4883344655404735}, + {2185121667669569, 1115206785572251, 704158439711004, 2133851508118048, 1251130304627637}, + {1895230235031468, 1896812472261458, 768470747222158, 1996242383935516, 1420798451369434}, + }, + { + {5839795121226482, 2867951589507385, 4636256264448023, 3052659764389740, 5026931603960818}, + {1579856931436900, 2447051767839229, 2868067823655589, 1688893962924788, 2116170079089324}, + {556211501812000, 449190026847667, 2036295767110360, 128995208617458, 1118467502984960}, + }, + { + {5602461071232607, 3307918487728174, 2854017338064603, 5855272157497266, 6150895900635822}, + {3398390622800229, 1820230761045332, 2690748155578623, 3095835968664066, 2530217218349662}, + {1878982227582804, 1431346083601994, 1534977024077189, 2155113334662581, 1782950372830762}, + }, + { + {4697661970186985, 3763132135142867, 5033467660349912, 2907155321697052, 4660465007863417}, + {2604312744349849, 2452708102821815, 3230466926286856, 2118488738947708, 2304478471957885}, + {1390885694073460, 1816639772663275, 1066627353945560, 1454561122724455, 848860562366790}, + }, + { + {5540829116940004, 3948748499449809, 5260550454870879, 4676389564943908, 4383546683050662}, + {2563789831020858, 3343718595008637, 2259025389677919, 1392665428080842, 3671467539073936}, + {981545110828877, 510698765880228, 2161678679515528, 1436791773758609, 1673597748298096}, + }, + { + {4329713062953095, 4939339976361997, 4958702235647932, 3268883154176961, 6391544885910171}, + {3614223297666549, 3897390208178715, 2811994039134574, 2958689501074087, 2363866533687133}, + {1294858674770242, 529668890256843, 2030539078163824, 294693146073477, 969527805905143}, + }, + { + {4670371383742225, 4002936514889177, 4966859846610707, 4736741110602146, 4760957427324248}, + {1176127152490445, 1894013131106171, 1812632908007715, 3751034747324574, 2289873378487758}, + {61868149975749, 236120696290007, 608351327055311, 1829919587421069, 1627340269896729}, + }, + { + {5062259960708944, 2689430826280744, 4108030288846956, 3316359330121699, 5641758926485313}, + {3722896082959268, 1863222026681564, 2044934869352810, 1385880696113195, 1308481967864035}, + {1796753889379582, 2232245583163596, 176790521107364, 133826841897595, 1041041183235991}, + }, + { + {3537934576014922, 2998428847270897, 5788967881664907, 4283416153137820, 3545722873501844}, + {3424639235617092, 2530506041245943, 3202402279176211, 1867524240141886, 1078908361802522}, + {1442655471934418, 1764674447040318, 316317796980033, 318184491515700, 1168933061547497}, + }, + { + {3599845082833499, 3896846545871592, 4303714095196951, 4532827504261802, 6020561742040974}, + {1580156396502051, 3208244370687690, 223926404960589, 565074765027696, 2169726994764050}, + {1942280341359651, 50425926664281, 1816034234875212, 880607828368837, 2092912650330571}, + }, + { + {5512765861463031, 4125716632501591, 4924530697112776, 5238255918415337, 3653602071478327}, + {1344167653424867, 1048535312223495, 1948741777806718, 3072730820612467, 1645288196866883}, + {1745152490874503, 1836336442271605, 2042898833391948, 1540893062903555, 1183365031475960}, + }, + }, + { + { + {5866266958495514, 5059063420853561, 4485040531648720, 3733835905319672, 3149359201467933}, + {2684460961013652, 3709949712072759, 1783966662497692, 1338383483986408, 1938129546538183}, + {40033251972751, 73885946378640, 1935473366247146, 1461619709267546, 1211799649582059}, + }, + { + {5250457209059169, 6625476149991574, 2830402208757038, 2943786524207392, 4303078760549837}, + {2301225069080269, 2184860938031358, 2273332051328548, 1704804667098002, 1911735781256473}, + {2217303387266656, 2227853943602075, 1384266551040407, 847818056628355, 1874126181291960}, + }, + { + {5228171959238562, 2572808713483427, 4818692310321808, 3983994866935258, 3614639592657195}, + {2763608237796206, 2346801614322209, 3045306834104040, 1893958852943478, 1490859261541415}, + {247688480299164, 1512873113726713, 1351630747308477, 937439467136054, 1030677695284257}, + }, + { + {3673708668048072, 4665314801263177, 6233349558231934, 6339984458236183, 4552548914816150}, + {3247306673138258, 2425869243107473, 2622484905091774, 2040657700179409, 1450858492090282}, + {1636572211186580, 2000987144770729, 1893417472062746, 196779160527558, 1557344243161357}, + }, + { + {6493926578942193, 4543542057302668, 3472731731448002, 3629201377772109, 5141975006754257}, + {2310006248725699, 1647962485872618, 2823143389536034, 2192050419207497, 1818655878772515}, + {1024434193686880, 2242250021719251, 564307645117404, 690001361734624, 239056809198959}, + }, + { + {4713019913612655, 4128228433667681, 5028024885108113, 5705734794679268, 3306562584580656}, + {3717108646348257, 4084515682195001, 3812051722646527, 1684888211341314, 1618372056987552}, + {1877409538331051, 337692456674055, 879114692044355, 2186377676371749, 1343387843321657}, + }, + { + {4142192651183813, 3524721259616285, 3594705099270661, 3959153982160586, 5413021910706886}, + {3669516570196207, 2121969005742829, 1652467606544375, 2698034847882520, 3275951535145684}, + {535664786267626, 858000264335400, 1392803193793530, 460772165692459, 1244185301942167}, + }, + { + {4502106313596470, 6443346829525378, 5721231993875900, 4681113914034302, 5472479613319256}, + {1495731174651276, 2532746921337410, 2156800382632014, 1987445924091844, 3448117379338544}, + {483117633444291, 1721449975252800, 2014677970681898, 2079902425951169, 117285229800651}, + }, + { + {3261832527463430, 3508653912421559, 5988429677058390, 5333822038484553, 3271080652355482}, + {2204547407113574, 2042779888674267, 2424936780736806, 1416144793524967, 2647730853119196}, + {417006946097712, 816142170165382, 321665320486095, 1120596382678137, 995334532083163}, + }, + { + {5667435300952982, 4583050105149113, 3937627982933697, 2917941244133350, 3746324610420174}, + {1654154218632292, 2424649854522191, 2118483268871125, 2658103876978958, 3351121693690514}, + {1757087236610187, 114932695265885, 1498710897730185, 1732388966595209, 145995973897689}, + }, + { + {3747574781762871, 3444173068370155, 2989065545095348, 5144077823603124, 5597474176298234}, + {808058917355435, 1642072317689253, 1764756051109168, 1619463984060522, 2971052737331444}, + {344784500521841, 753070981245028, 1021287645349333, 896645545453199, 449568974542070}, + }, + { + {5037125630216086, 4317087092146610, 4394758621519137, 3169411347551391, 3200762148534134}, + {3758879149962654, 2267958484085658, 725842773817223, 2203610500470887, 1640888914156664}, + {1753063336824455, 1632699439142352, 654655992711894, 254878945844677, 1142235737877277}, + }, + { + {3668977677139265, 4332641682100108, 3590347451295966, 5242849066395039, 2727116665213341}, + {3248235630095651, 1380466035309490, 1790683862609512, 3542725848725101, 2663722245169429}, + {863640852068414, 1530602868551714, 1707160942886152, 54230982937714, 122819573759751}, + }, + { + {5532810941110268, 4585437113624970, 5116705204102219, 3665108856301161, 3445572551989045}, + {2829139259902194, 3388923696568854, 2569841942150467, 2697982670988693, 2163914772008849}, + {2076653457069888, 1193685867720358, 1325584969753937, 1501472994346955, 87079528165998}, + }, + { + {4556025881223574, 5720430347742651, 6074363308505144, 4027406626756934, 2527767620430889}, + {2142131119871606, 2984501701896371, 2717746191530066, 2203225891573820, 2175517225379719}, + {897107227346093, 455907621058237, 864390863340574, 316655721359786, 1688391871841069}, + }, + }, + { + { + {5225107848603314, 3997985175873023, 2901647838494787, 3895284350008311, 5682946636557185}, + {3523031484358436, 2824636666213863, 2395141832526945, 770528850757883, 2501907940021781}, + {722866669050453, 648025000876863, 272387785321835, 1191578896340587, 133025146298323}, + }, + { + {4430018927628058, 5528149113975034, 3884602704599257, 4041974594447505, 3905022194274965}, + {82857304500618, 1554338034359360, 760468202446199, 2344834461467455, 688719719651551}, + {2128452325542740, 952454207454828, 1516099560539414, 1362377470631451, 1181280467630705}, + }, + { + {3877905624740973, 5612025444592814, 3620377076227448, 3557624466809644, 5794884625077990}, + {1234316951156125, 2774803744202148, 3038336850143346, 2839603046584234, 1645722164542234}, + {894237486099210, 1516039905189318, 1740044048087400, 593444525063043, 2109764897178862}, + }, + { + {3625360958175610, 5708422748846073, 3787265901576189, 6157656721094708, 5961588011087405}, + {1482109974932762, 1512691293799179, 3308418655922299, 1669766513116242, 1645628848588889}, + {134048702591674, 1512942576919112, 1666722043826583, 1830910766776036, 90483195207340}, + }, + { + {3762249153136541, 5419647444574112, 5020263484993746, 3697437793067561, 3831953348456062}, + {2494438010166937, 1432383122970498, 3625127628421620, 1764585753875763, 2715866922646858}, + {914153294895020, 1485178337004016, 1172992438642136, 742396957515979, 1460451697085215}, + }, + { + {3293341585462216, 4914585647995248, 3425647660888775, 3851476795826281, 2935952374714235}, + {2881676317687314, 3127597808111770, 1680974550469383, 2631492786928655, 2080467460645229}, + {1084836891982052, 405373371974756, 392292573225522, 1228291428535054, 196706224397467}, + }, + { + {5422966393229312, 3517798661028565, 3491057102408135, 5349612585124235, 5098313025804708}, + {2181085219797570, 2438267619893703, 1398091257339579, 1543623638852333, 2275879750497956}, + {1451708073273912, 640663458576442, 472967005176057, 1940369909273489, 1650816055376110}, + }, + { + {5775591770146864, 4809727687563635, 4066767569195787, 3927850608944429, 5542524111957037}, + {2856057239056516, 3899713821492127, 1178627125851433, 3276833765573271, 1528786153297881}, + {1406590024268518, 1220852036090080, 364949301397175, 1654716393716139, 143122595639438}, + }, + { + {3092682960222618, 5760168522994174, 4966136799494047, 6183321071200806, 5955160799299141}, + {1679800253914106, 1418780742199926, 3419507991072325, 2296436046846462, 2072736467396911}, + {882943817583285, 484844826182032, 423720125645701, 79705330082926, 518433021584838}, + }, + { + {4303808439591566, 4492049110308958, 5005208589399660, 3449528090765045, 3218284505011813}, + {3283940803229324, 4459508559485836, 940189907838090, 1705424518756533, 2039165337931945}, + {892563649969864, 218618659831677, 483384434921296, 1959503286788495, 846111377588119}, + }, + { + {3736052427633640, 3240841928280071, 4678563487154791, 3752373267871112, 4181937274986806}, + {2003615224309886, 1453829786196949, 4170849260029473, 2196915936737576, 3465659437703250}, + {870814358129174, 1509533025339595, 2053081266530331, 1737753718216259, 77875205064950}, + }, + { + {6295693526685959, 4477016414498074, 4045516627237016, 5610462754780940, 5285590675711912}, + {2091650387347437, 4186999032385018, 3695680781345242, 1318896896580492, 3133525015024966}, + {2057751622403208, 2124826136415213, 2162400122701924, 512312961318735, 2072953190856236}, + }, + { + {3421075047723659, 5902999844007244, 5257660560322253, 4411230485782045, 3851018473810833}, + {1356912041975431, 2088651341684568, 2115599337938785, 4037573216393849, 2652908467965391}, + {356251628924273, 2088769627568139, 187882754343055, 394347310503797, 1449630398452630}, + }, + { + {3682820885194585, 5173915763318849, 2521868910298419, 4165015930825951, 4883528324075009}, + {1067127578201981, 2883441503009643, 2032675011298617, 3963320928045487, 1183903438950389}, + {1431421126152216, 738544074023370, 2193830823196529, 1671561335663722, 717735409657132}, + }, + { + {4201586389811353, 4375880219104829, 4192199017276052, 4416844421544609, 3903714904213483}, + {1449584304781523, 3077329128471461, 2135282471631868, 3283981709093825, 2025731372310411}, + {1183319077995597, 1294226945214786, 1175504892926680, 1065468559536653, 2201437139069262}, + }, + }, + { + { + {3505559764260479, 6013086951275753, 5081911139396344, 4716516055339902, 4005184608137658}, + {1941635877650331, 2292936607701027, 802548087270426, 553714331402352, 2637835706093694}, + {1415499622184076, 11739232724558, 1448526577403933, 77973485783393, 148463223858677}, + }, + { + {3556556070469100, 6104580777770606, 3153395731542438, 4746347503688425, 3530835687615003}, + {2563241728545350, 2900457320970642, 2021653799300720, 4081786454058715, 1684057546885165}, + {531432570362576, 1071513573823369, 449672118652203, 98547521251379, 260579416510065}, + }, + { + {3113402949202118, 3224343282781895, 6393340053990193, 4574021187583530, 4354743893457091}, + {2098297300858722, 1637995723173513, 2132191683177015, 592134746032938, 1044637126699087}, + {607038018090674, 1768950085932612, 1176147243379098, 1239851308662055, 1164850159859507}, + }, + { + {6544624144736846, 3158440120316048, 4122467747600782, 3270454787206357, 5173743677397902}, + {2302101840952822, 2675605826160506, 3431414289057246, 2525090851992001, 1591101869035052}, + {67986117053250, 143032219413988, 187059126532888, 1606721935579222, 2108737133289470}, + }, + { + {5726022544095362, 3724045113988627, 3515582956648241, 4176155101637246, 5525745188146662}, + {1710358734492362, 2952544254120043, 2348808532032187, 3458396516769880, 1537007452608630}, + {63942543002426, 322070337950512, 1601643046070686, 1223905889282175, 1741111665223434}, + }, + { + {5315895417052113, 4828375526334729, 4444010786735381, 5993309905616190, 3640401138113649}, + {2860407040121293, 1177142915116463, 3145140653940871, 1733521080031482, 3186874796199337}, + {731527977617797, 464892677638406, 850380242165564, 1707297435867315, 797914062581028}, + }, + { + {4481445847621310, 4194775426039896, 4717484155432068, 3203129625283069, 3774741254649070}, + {2200385186612512, 3830080434695126, 3332312936597714, 1819075993402941, 3697021137208346}, + {1808087344592199, 1917986815291197, 1736625562156353, 1691009053422774, 699554104203468}, + }, + { + {5048623459093582, 3345582890430421, 3965077987869649, 4640623371578895, 4912032720993151}, + {2302864341793270, 2363316925891845, 1559429527589511, 2124275860379685, 1685170275648173}, + {567087552892581, 1562927351866469, 299640978917608, 868196882482839, 81953139898216}, + }, + { + {4967323480101032, 4012272011745302, 3862894427518599, 4308636686245327, 5217499651112315}, + {1252667495912574, 926763760798846, 829943705996489, 1227324880932263, 964621170655609}, + {955876088496614, 2071382636271538, 1339562676294470, 1915921082315197, 857114822306108}, + }, + { + {3257326910061677, 5127439013196396, 4310630254544639, 4686443315427179, 4724730249377907}, + {2936128018106963, 1695470026893168, 2973127512604355, 1666309508011309, 2226049713730899}, + {1512722216346670, 113316334999619, 1851114541854723, 1700671412068281, 1858477808352196}, + }, + { + {5998097796107191, 4771418173207581, 4274779313964863, 6374384720876343, 3691059377431806}, + {1747059722842985, 1151985779666741, 2579873034214805, 2259025270175461, 1104167228907676}, + {1120011747324768, 1881628887342023, 2214290331844435, 486356580332714, 2162135539567334}, + }, + { + {5415017211564966, 4131956504736867, 4606393482137328, 4786286211324892, 4752001899018321}, + {3516707084985218, 3646421870194647, 1944208348735794, 2748388507091938, 2933933255585587}, + {939102610898658, 657762889309704, 1555084457788919, 1150153333777593, 1006706590082496}, + }, + { + {3543688234603472, 4194712450230855, 3880927772745797, 3426761679103243, 3127058186392728}, + {3187981953742084, 2855163365535635, 2396035850573347, 3426339364174055, 2041647909167010}, + {463905214510220, 1910840871806134, 115888611524937, 1537009142155618, 880221457903699}, + }, + { + {5589672840238728, 3432294293459350, 5387677215955058, 6169144676112659, 5379715338757042}, + {1784370156336156, 2235499907922716, 2025309612181078, 2188885065316605, 3233083367725482}, + {417210119430620, 1641361429213146, 1508617462812435, 1831075688628217, 1813350286884393}, + }, + { + {3676762525127118, 5016274613231870, 5279594930346407, 2746860593795830, 4531082394479975}, + {2603791557859206, 567981304762832, 3180006238725203, 2675077654404820, 258215834034235}, + {1643563927005454, 1423516315292419, 46523883479803, 1501791298376850, 1157127033006661}, + }, + }, + { + { + {4640633429716646, 4436352535262760, 5042663907988027, 4328339913162644, 4318409930240684}, + {1650059244213924, 1415687339027798, 3751941600642035, 2204874486713656, 3546077689782506}, + {1247200432261975, 265507035905438, 1620404126253617, 117362009527087, 1746435297969059}, + }, + { + {5340736267872142, 3295470429174750, 4407135163398927, 3488366482378904, 3746520348111790}, + {1068629703061668, 3236562504536698, 3481748917474479, 2110232841828030, 1092532788851750}, + {1306097687903586, 1372543655508231, 1658076721821581, 2200003583698537, 780636112677937}, + }, + { + {5226077937175337, 5692428823576533, 5689014150777050, 3908825240466348, 6345259720261058}, + {3066336104509029, 2314860930152579, 3056640011863338, 2260092480216528, 2073254466378784}, + {479894784370716, 1925880613677947, 2183487522494884, 625094381313712, 854845126872293}, + }, + { + {5197618157762598, 4433464121961190, 3260681654961795, 4120975634792281, 5835262176061498}, + {817093479351430, 4088761935787052, 3171716785010059, 2728541872107727, 1520644895959802}, + {1207982418891449, 1577854720087533, 2009037012572541, 1476807775109585, 764858983320152}, + }, + { + {4643752207568541, 4177425086748798, 2717351689863297, 4063904331524798, 6079476938692958}, + {292623621294171, 1087309087737456, 2573455597713993, 859400146466928, 2565065720265056}, + {1960514462005953, 1030291725190195, 357278058611993, 503261352420903, 409647200988996}, + }, + { + {4137436424426920, 3760583205467834, 5814704535202459, 3679343367155289, 3544651677301793}, + {1640564024541742, 3450104780081118, 1372955845260037, 2487953912194947, 1964015174577549}, + {1832104727099167, 996069167520846, 1100729754186688, 1771584084767106, 2117261745027080}, + }, + { + {4431020636065029, 5503695293870154, 4553592025467096, 4019460577334316, 4832018945114183}, + {1199122074926019, 2522059134402784, 397875262207322, 3119865606750668, 1432109594857765}, + {1875633950147766, 1109790076082089, 897660652998513, 1428078707156757, 908826481148722}, + }, + { + {5054013235620828, 5378852271051704, 4293253473160895, 4319499063151422, 5340758119594162}, + {2634018106321626, 2505108247629684, 3126341578772617, 2016974307899050, 1468999769476078}, + {2013224690617610, 881120726963113, 2087874148443678, 930634847072563, 2100154549645766}, + }, + { + {4096027168378681, 4674912073837464, 4651610619813038, 4659750027669693, 4079639323873143}, + {651560684224625, 2530373654189494, 3125510882371828, 1936741789282769, 4026872663838631}, + {1094258812694036, 1294242138409324, 1090035173467081, 1763568378228799, 1431407300427851}, + }, + { + {5901866474833548, 4953841416438018, 5227230958845012, 5669922347444024, 5683271169352586}, + {2172262341405882, 2561868572136046, 3688730950551326, 2503867014426524, 2213093161812464}, + {1951192547947024, 851119993124706, 1847432304733109, 1277897613708864, 601543383482271}, + }, + { + {3631710539670242, 3768950590313261, 5303952111138864, 5325131792733564, 5315344346171139}, + {3338513542876810, 3006290156706597, 1350992246942434, 903865514364164, 3147437075515383}, + {2230520732543357, 1272781658952307, 896500518331525, 1553870550296913, 1174834176365255}, + }, + { + {4212629881454302, 3511449460350501, 3310343538794185, 3281266357642722, 4487974828971768}, + {2969785173831624, 1505727885325259, 2813024274382127, 1442092766966006, 2775912811267378}, + {1226820412291019, 1429525834475644, 2118443840955994, 611048578379551, 1393279248359119}, + }, + { + {2549845597186375, 3623100753864553, 3499310120841001, 3967554171599715, 5734430215634972}, + {1995271425552231, 3083791126213951, 3279752729240055, 1320836376731637, 2619696559790542}, + {209938911194598, 1168941097549542, 1505719700014288, 296602403362327, 585510095036421}, + }, + { + {4596693410811983, 3239555606447835, 5319792910601399, 5807716310972140, 4978776737081211}, + {4298118886570999, 2595714642338047, 2582204981507639, 2283950348816052, 2880808000087105}, + {1625024000487589, 1577328585741835, 1748162688303583, 1508135442094103, 494130659185316}, + }, + { + {5133202328939711, 5161068400634691, 4982689133170151, 5479854286391464, 3974357722065660}, + {2759508860286693, 3544879646603215, 2393702940511177, 1786833813469860, 2879003887330732}, + {374825657994223, 798281160160783, 1037106323566812, 1491213365794340, 786385610113834}, + }, + }, + } + + GE_BASEPOINT_TABLE := &Gen_Multiply_Table_edwards25519_lo[0] +} diff --git a/core/crypto/_edwards25519/tools/edwards_gen_tables.odin b/core/crypto/_edwards25519/tools/edwards_gen_tables.odin new file mode 100644 index 000000000..a204e6ac6 --- /dev/null +++ b/core/crypto/_edwards25519/tools/edwards_gen_tables.odin @@ -0,0 +1,138 @@ +package edwards_tools + +import ed "core:crypto/_edwards25519" +import field "core:crypto/_fiat/field_curve25519" +import scalar "core:crypto/_fiat/field_scalar25519" +import "core:encoding/endian" +import "core:fmt" +import path "core:path/filepath" +import "core:os" +import "core:strings" + +// Yes this leaks memory, fite me IRL. + +GENERATED :: `/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/` + +@(private, rodata) +FE_D2 := field.Tight_Field_Element { + 1859910466990425, + 932731440258426, + 1072319116312658, + 1815898335770999, + 633789495995903, +} + +main :: proc() { + Basepoint_Addend_Group_Element :: struct { + y2_minus_x2: field.Loose_Field_Element, // t1 + y2_plus_x2: field.Loose_Field_Element, // t3 + k_times_t2: field.Tight_Field_Element, // t4 + } + Basepoint_Multiply_Table :: [15]Basepoint_Addend_Group_Element + + ge_bp_addend_set := proc(ge_a: ^Basepoint_Addend_Group_Element, ge: ^ed.Group_Element) { + // We rescale so Z == 1, so T = X * Y + x_, y_, z_inv: field.Tight_Field_Element + field.fe_carry_inv(&z_inv, field.fe_relax_cast(&ge.z)) + field.fe_carry_mul(&x_, field.fe_relax_cast(&ge.x), field.fe_relax_cast(&z_inv)) + field.fe_carry_mul(&y_, field.fe_relax_cast(&ge.y), field.fe_relax_cast(&z_inv)) + + field.fe_sub(&ge_a.y2_minus_x2, &y_, &x_) + field.fe_add(&ge_a.y2_plus_x2, &y_, &x_) + field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&x_), field.fe_relax_cast(&y_)) + field.fe_carry_mul(&ge_a.k_times_t2, field.fe_relax_cast(&ge_a.k_times_t2), field.fe_relax_cast(&FE_D2)) + } + + Multiply_Table_hi: [32]Basepoint_Multiply_Table + Multiply_Table_lo: [32]Basepoint_Multiply_Table + + sc_set_unchecked := proc(sc: ^scalar.Non_Montgomery_Domain_Field_Element, b: []byte) { + sc[0] = endian.unchecked_get_u64le(b[0:]) + sc[1] = endian.unchecked_get_u64le(b[8:]) + sc[2] = endian.unchecked_get_u64le(b[16:]) + sc[3] = endian.unchecked_get_u64le(b[24:]) + } + + g, p: ed.Group_Element + ed.ge_generator(&g) + + sc: scalar.Non_Montgomery_Domain_Field_Element + + // Precompute ([1,15] << n) * G multiples of G, LSB->MSB + for i in 0..<32 { + b: [32]byte + for j in 1..<16 { + b[i] = u8(j) + sc_set_unchecked(&sc, b[:]) + ed.ge_scalarmult_raw(&p, &g, &sc, true) + ge_bp_addend_set(&Multiply_Table_lo[i][j-1], &p) + + b[i] = u8(j) << 4 + sc_set_unchecked(&sc, b[:]) + ed.ge_scalarmult_raw(&p, &g, &sc, true) + ge_bp_addend_set(&Multiply_Table_hi[i][j-1], &p) + + b[i] = 0 + } + } + + fn, err := path.join({ODIN_ROOT, "core", "crypto", "_edwards25519", "edwards25519_table.odin"}, context.allocator) + if err != .None { + fmt.eprintfln("Join path error for edwards25519_table.odin: %v", err); + os.exit(1); + } + bld: strings.Builder + w := strings.to_writer(&bld) + + fmt.wprintln(w, "package _edwards25519") + fmt.wprintln(w, "") + fmt.wprintln(w, GENERATED) + fmt.wprintln(w, "") + fmt.wprintln(w, "import \"core:crypto\"") + fmt.wprintln(w, "") + fmt.wprintln(w, "when crypto.COMPACT_IMPLS == false {") + + fmt.wprintln(w, "\t@(private,rodata)") + fmt.wprintln(w, "\tGen_Multiply_Table_edwards25519_lo := [32]Basepoint_Multiply_Table {") + for &v in Multiply_Table_lo { + fmt.wprintln(w, "\t\t{") + for &ap in v { + fmt.wprintln(w, "\t\t\t{") + + t1, t3, t4 := &ap.y2_minus_x2, &ap.y2_plus_x2, &ap.k_times_t2 + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t1[0], t1[1], t1[2], t1[3], t1[4]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t3[0], t3[1], t3[2], t3[3], t3[4]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t4[0], t4[1], t4[2], t4[3], t4[4]) + + fmt.wprintln(w, "\t\t\t},") + } + fmt.wprintln(w, "\t\t},") + } + fmt.wprintln(w, "\t}\n") + + fmt.wprintln(w, "\t@(private,rodata)") + fmt.wprintln(w, "\tGen_Multiply_Table_edwards25519_hi := [32]Basepoint_Multiply_Table {") + for &v in Multiply_Table_hi { + fmt.wprintln(w, "\t\t{") + for &ap in v { + fmt.wprintln(w, "\t\t\t{") + + t1, t3, t4 := &ap.y2_minus_x2, &ap.y2_plus_x2, &ap.k_times_t2 + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t1[0], t1[1], t1[2], t1[3], t1[4]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t3[0], t3[1], t3[2], t3[3], t3[4]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d, %d},\n", t4[0], t4[1], t4[2], t4[3], t4[4]) + + fmt.wprintln(w, "\t\t\t},") + } + fmt.wprintln(w, "\t\t},") + } + fmt.wprintln(w, "\t}\n") + + fmt.wprintln(w, "\tGE_BASEPOINT_TABLE := &Gen_Multiply_Table_edwards25519_lo[0]") + + fmt.wprintln(w, "}") + + _ = os.write_entire_file(fn, transmute([]byte)(strings.to_string(bld))) +} diff --git a/core/crypto/_fiat/field_curve25519/field.odin b/core/crypto/_fiat/field_curve25519/field.odin index 04fc87659..ac6e284b7 100644 --- a/core/crypto/_fiat/field_curve25519/field.odin +++ b/core/crypto/_fiat/field_curve25519/field.odin @@ -1,7 +1,8 @@ package field_curve25519 import "core:crypto" -import "core:mem" + +zero_explicit :: crypto.zero_explicit fe_relax_cast :: #force_inline proc "contextless" ( arg1: ^Tight_Field_Element, @@ -18,7 +19,7 @@ fe_tighten_cast :: #force_inline proc "contextless" ( fe_clear :: proc "contextless" ( arg1: $T, ) where T == ^Tight_Field_Element || T == ^Loose_Field_Element { - mem.zero_explicit(arg1, size_of(arg1^)) + zero_explicit(arg1, size_of(arg1^)) } fe_clear_vec :: proc "contextless" ( @@ -38,7 +39,7 @@ fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[32]byte _fe_from_bytes(out1, &tmp1) - mem.zero_explicit(&tmp1, size_of(tmp1)) + zero_explicit(&tmp1, size_of(tmp1)) } fe_is_negative :: proc "contextless" (arg1: ^Tight_Field_Element) -> int { @@ -47,7 +48,7 @@ fe_is_negative :: proc "contextless" (arg1: ^Tight_Field_Element) -> int { fe_to_bytes(&tmp1, arg1) ret := tmp1[0] & 1 - mem.zero_explicit(&tmp1, size_of(tmp1)) + zero_explicit(&tmp1, size_of(tmp1)) return int(ret) } @@ -59,8 +60,8 @@ fe_equal :: proc "contextless" (arg1, arg2: ^Tight_Field_Element) -> int { fe_to_bytes(&tmp2, arg2) ret := crypto.compare_constant_time(tmp1[:], tmp2[:]) - mem.zero_explicit(&tmp1, size_of(tmp1)) - mem.zero_explicit(&tmp2, size_of(tmp2)) + zero_explicit(&tmp1, size_of(tmp1)) + zero_explicit(&tmp2, size_of(tmp2)) return ret } @@ -72,7 +73,7 @@ fe_equal_bytes :: proc "contextless" (arg1: ^Tight_Field_Element, arg2: ^[32]byt ret := crypto.compare_constant_time(tmp1[:], arg2[:]) - mem.zero_explicit(&tmp1, size_of(tmp1)) + zero_explicit(&tmp1, size_of(tmp1)) return ret } @@ -175,7 +176,7 @@ fe_carry_sqrt_ratio_m1 :: proc "contextless" ( fe_carry_abs(out1, r) fe_clear_vec([]^Tight_Field_Element{&w, &tmp1, &tmp2, &tmp3}) - mem.zero_explicit(&b, size_of(b)) + zero_explicit(&b, size_of(b)) return correct_sign_sqrt | flipped_sign_sqrt } diff --git a/core/crypto/_fiat/field_curve448/field.odin b/core/crypto/_fiat/field_curve448/field.odin index 540d88f28..bb077cb1e 100644 --- a/core/crypto/_fiat/field_curve448/field.odin +++ b/core/crypto/_fiat/field_curve448/field.odin @@ -1,6 +1,6 @@ package field_curve448 -import "core:mem" +import "core:crypto" fe_relax_cast :: #force_inline proc "contextless" ( arg1: ^Tight_Field_Element, @@ -17,7 +17,7 @@ fe_tighten_cast :: #force_inline proc "contextless" ( fe_clear :: proc "contextless" ( arg1: $T, ) where T == ^Tight_Field_Element || T == ^Loose_Field_Element { - mem.zero_explicit(arg1, size_of(arg1^)) + crypto.zero_explicit(arg1, size_of(arg1^)) } fe_clear_vec :: proc "contextless" ( diff --git a/core/crypto/_fiat/field_p256r1/field.odin b/core/crypto/_fiat/field_p256r1/field.odin new file mode 100644 index 000000000..f7dd978aa --- /dev/null +++ b/core/crypto/_fiat/field_p256r1/field.odin @@ -0,0 +1,345 @@ +package field_p256r1 + +import "core:crypto" +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + crypto.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, + unsafe_assume_canonical := false, +) -> bool { + ensure_contextless(len(arg1) == 32, "p256r1: invalid fe input buffer") + + // Note: We assume the input is in big-endian. + tmp := Non_Montgomery_Domain_Field_Element { + endian.unchecked_get_u64be(arg1[24:]), + endian.unchecked_get_u64be(arg1[16:]), + endian.unchecked_get_u64be(arg1[8:]), + endian.unchecked_get_u64be(arg1[0:]), + } + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + // Check that tmp is in the the range [0, ELL). + if !unsafe_assume_canonical { + _, borrow := bits.sub_u64(ELL[0] - 1, tmp[0], 0) + _, borrow = bits.sub_u64(ELL[1], tmp[1], borrow) + _, borrow = bits.sub_u64(ELL[2], tmp[2], borrow) + _, borrow = bits.sub_u64(ELL[3], tmp[3], borrow) + if borrow != 0 { + return false + } + } + + fe_to_montgomery(out1, &tmp) + + return true +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 32, "p256r1: invalid fe output buffer") + + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[24:], tmp[0]) + endian.unchecked_put_u64be(out1[16:], tmp[1]) + endian.unchecked_put_u64be(out1[8:], tmp[2]) + endian.unchecked_put_u64be(out1[0:], tmp[3]) + + crypto.zero_explicit(&tmp, size_of(tmp)) +} + +@(require_results) +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element = --- + fe_sub(&tmp, arg1, arg2) + + // This will only underflow if and only if (⟺) arg1 == arg2, and we return the borrow, + // which will be 1. + is_eq := subtle.u64_is_zero(fe_non_zero(&tmp)) + + fe_clear(&tmp) + + return int(is_eq) +} + +@(require_results) +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element = --- + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_pow2k :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_square(out1, out1) + } +} + +fe_inv :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x15 = x12 << 3 + _111 + // x16 = 2*x15 + 1 + // x32 = x16 << 16 + x16 + // i53 = x32 << 15 + // x47 = x15 + i53 + // i263 = ((i53 << 17 + 1) << 143 + x47) << 47 + // return (x47 + i263) << 2 + // + // Operations: 255 squares 11 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Note: Need to stash `arg1` (`xx`) in the case that `out1`/`arg1` alias, + // as `arg1` is used after `out1` has been altered. + t0, t1, xx: Montgomery_Domain_Field_Element = ---, ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 3: z = x^0x6 + fe_square(out1, out1) + + // Step 4: z = x^0x7 + fe_mul(out1, &xx, out1) + + // Step 7: t0 = x^0x38 + fe_pow2k(&t0, out1, 3) + + // Step 8: t0 = x^0x3f + fe_mul(&t0, out1, &t0) + + // Step 14: t1 = x^0xfc0 + fe_pow2k(&t1, &t0, 6) + + // Step 15: t0 = x^0xfff + fe_mul(&t0, &t0, &t1) + + // Step 18: t0 = x^0x7ff8 + fe_pow2k(&t0, &t0, 3) + + // Step 19: z = x^0x7fff + fe_mul(out1, out1, &t0) + + // Step 20: t0 = x^0xfffe + fe_square(&t0, out1) + + // Step 21: t0 = x^0xffff + fe_mul(&t0, &xx, &t0) + + // Step 37: t1 = x^0xffff0000 + fe_pow2k(&t1, &t0, 16) + + // Step 38: t0 = x^0xffffffff + fe_mul(&t0, &t0, &t1) + + // Step 53: t0 = x^0x7fffffff8000 + fe_pow2k(&t0, &t0, 15) + + // Step 54: z = x^0x7fffffffffff + fe_mul(out1, out1, &t0) + + // Step 71: t0 = x^0xffffffff00000000 + fe_pow2k(&t0, &t0, 17) + + // Step 72: t0 = x^0xffffffff00000001 + fe_mul(&t0, &xx, &t0) + + // Step 215: t0 = x^0x7fffffff80000000800000000000000000000000000000000000 + fe_pow2k(&t0, &t0, 143) + + // Step 216: t0 = x^0x7fffffff800000008000000000000000000000007fffffffffff + fe_mul(&t0, out1, &t0) + + // Step 263: t0 = x^0x3fffffffc00000004000000000000000000000003fffffffffff800000000000 + fe_pow2k(&t0, &t0, 47) + + // Step 264: z = x^0x3fffffffc00000004000000000000000000000003fffffffffffffffffffffff + fe_mul(out1, out1, &t0) + + // Step 266: z = x^0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc + fe_pow2k(out1, out1, 2) + + fe_mul(out1, out1, &xx) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &xx}) +} + +@(require_results) +fe_sqrt :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) -> int { + // Square root candidate can be derived via exponentiation by `(p + 1) / 4` + // From sage: 28948022302589062190674361737351893382521535853822578548883407827216774463488 + // + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _1100 = _11 << 2 + // _1111 = _11 + _1100 + // _11110000 = _1111 << 4 + // _11111111 = _1111 + _11110000 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // return ((x32 << 32 + 1) << 96 + 1) << 94 + // + // Operations: 253 squares 7 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Likewise this tramples over arg1, so stash another copy. + t0, xx: Montgomery_Domain_Field_Element = ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 4: t0 = x^0xc + fe_pow2k(&t0, &xx, 2) + + // Step 5: z = x^0xf + fe_mul(out1, out1, &t0) + + // Step 9: t0 = x^0xf0 + fe_pow2k(&t0, out1, 4) + + // Step 10: z = x^0xff + fe_mul(out1, out1, &t0) + + // Step 18: t0 = x^0xff00 + fe_pow2k(&t0, out1, 8) + + // Step 19: z = x^0xffff + fe_mul(out1, out1, &t0) + + // Step 35: t0 = x^0xffff0000 + fe_pow2k(&t0, out1, 16) + + // Step 36: z = x^0xffffffff + fe_mul(out1, out1, &t0) + + // Step 68: z = x^0xffffffff00000000 + fe_pow2k(out1, out1, 32) + + // Step 69: z = x^0xffffffff00000001 + fe_mul(out1, &xx, out1) + + // Step 165: z = x^0xffffffff00000001000000000000000000000000 + fe_pow2k(out1, out1, 96) + + // Step 166: z = x^0xffffffff00000001000000000000000000000001 + fe_mul(out1, &xx, out1) + + // Step 260: z = x^0x3fffffffc0000000400000000000000000000000400000000000000000000000 + fe_pow2k(out1, out1, 94) + + // Ensure that our candidate is actually the square root. + check, zero: Montgomery_Domain_Field_Element + fe_square(&check, out1) + + is_valid := fe_equal(&check, &xx) + fe_cond_select(out1, &zero, out1, is_valid) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &xx, &check}) + + return is_valid +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^Montgomery_Domain_Field_Element, + arg3: int, +) { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} diff --git a/core/crypto/_fiat/field_p256r1/field64.odin b/core/crypto/_fiat/field_p256r1/field64.odin new file mode 100644 index 000000000..940f2cd07 --- /dev/null +++ b/core/crypto/_fiat/field_p256r1/field64.odin @@ -0,0 +1,501 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_p256r1 + +// The file provides arithmetic on the field Z/(2^256 - 2^224 + 2^192 + 2^96 - 1) +// using a 64-bit Montgomery form internal representation. It is derived +// primarily from the machine generated Golang output from the fiat-crypto +// project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [4]u64{0xffffffffffffffff, 0xffffffff, 0x0, 0xffffffff00000001} + +Montgomery_Domain_Field_Element :: distinct [4]u64 +Non_Montgomery_Domain_Field_Element :: distinct [4]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg2[3]) + x8, x7 := bits.mul_u64(x4, arg2[2]) + x10, x9 := bits.mul_u64(x4, arg2[1]) + x12, x11 := bits.mul_u64(x4, arg2[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + x21, x20 := bits.mul_u64(x11, 0xffffffff00000001) + x23, x22 := bits.mul_u64(x11, 0xffffffff) + x25, x24 := bits.mul_u64(x11, 0xffffffffffffffff) + x26, x27 := bits.add_u64(x25, x22, u64(0x0)) + x28 := (u64(fiat.u1(x27)) + x23) + _, x30 := bits.add_u64(x11, x24, u64(0x0)) + x31, x32 := bits.add_u64(x13, x26, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x15, x28, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64(x17, x20, u64(fiat.u1(x34))) + x37, x38 := bits.add_u64(x19, x21, u64(fiat.u1(x36))) + x40, x39 := bits.mul_u64(x1, arg2[3]) + x42, x41 := bits.mul_u64(x1, arg2[2]) + x44, x43 := bits.mul_u64(x1, arg2[1]) + x46, x45 := bits.mul_u64(x1, arg2[0]) + x47, x48 := bits.add_u64(x46, x43, u64(0x0)) + x49, x50 := bits.add_u64(x44, x41, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x42, x39, u64(fiat.u1(x50))) + x53 := (u64(fiat.u1(x52)) + x40) + x54, x55 := bits.add_u64(x31, x45, u64(0x0)) + x56, x57 := bits.add_u64(x33, x47, u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59))) + x62, x63 := bits.add_u64(u64(fiat.u1(x38)), x53, u64(fiat.u1(x61))) + x65, x64 := bits.mul_u64(x54, 0xffffffff00000001) + x67, x66 := bits.mul_u64(x54, 0xffffffff) + x69, x68 := bits.mul_u64(x54, 0xffffffffffffffff) + x70, x71 := bits.add_u64(x69, x66, u64(0x0)) + x72 := (u64(fiat.u1(x71)) + x67) + _, x74 := bits.add_u64(x54, x68, u64(0x0)) + x75, x76 := bits.add_u64(x56, x70, u64(fiat.u1(x74))) + x77, x78 := bits.add_u64(x58, x72, u64(fiat.u1(x76))) + x79, x80 := bits.add_u64(x60, x64, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x62, x65, u64(fiat.u1(x80))) + x83 := (u64(fiat.u1(x82)) + u64(fiat.u1(x63))) + x85, x84 := bits.mul_u64(x2, arg2[3]) + x87, x86 := bits.mul_u64(x2, arg2[2]) + x89, x88 := bits.mul_u64(x2, arg2[1]) + x91, x90 := bits.mul_u64(x2, arg2[0]) + x92, x93 := bits.add_u64(x91, x88, u64(0x0)) + x94, x95 := bits.add_u64(x89, x86, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x87, x84, u64(fiat.u1(x95))) + x98 := (u64(fiat.u1(x97)) + x85) + x99, x100 := bits.add_u64(x75, x90, u64(0x0)) + x101, x102 := bits.add_u64(x77, x92, u64(fiat.u1(x100))) + x103, x104 := bits.add_u64(x79, x94, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106))) + x110, x109 := bits.mul_u64(x99, 0xffffffff00000001) + x112, x111 := bits.mul_u64(x99, 0xffffffff) + x114, x113 := bits.mul_u64(x99, 0xffffffffffffffff) + x115, x116 := bits.add_u64(x114, x111, u64(0x0)) + x117 := (u64(fiat.u1(x116)) + x112) + _, x119 := bits.add_u64(x99, x113, u64(0x0)) + x120, x121 := bits.add_u64(x101, x115, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x103, x117, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x105, x109, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x107, x110, u64(fiat.u1(x125))) + x128 := (u64(fiat.u1(x127)) + u64(fiat.u1(x108))) + x130, x129 := bits.mul_u64(x3, arg2[3]) + x132, x131 := bits.mul_u64(x3, arg2[2]) + x134, x133 := bits.mul_u64(x3, arg2[1]) + x136, x135 := bits.mul_u64(x3, arg2[0]) + x137, x138 := bits.add_u64(x136, x133, u64(0x0)) + x139, x140 := bits.add_u64(x134, x131, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x132, x129, u64(fiat.u1(x140))) + x143 := (u64(fiat.u1(x142)) + x130) + x144, x145 := bits.add_u64(x120, x135, u64(0x0)) + x146, x147 := bits.add_u64(x122, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x124, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x126, x141, u64(fiat.u1(x149))) + x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151))) + x155, x154 := bits.mul_u64(x144, 0xffffffff00000001) + x157, x156 := bits.mul_u64(x144, 0xffffffff) + x159, x158 := bits.mul_u64(x144, 0xffffffffffffffff) + x160, x161 := bits.add_u64(x159, x156, u64(0x0)) + x162 := (u64(fiat.u1(x161)) + x157) + _, x164 := bits.add_u64(x144, x158, u64(0x0)) + x165, x166 := bits.add_u64(x146, x160, u64(fiat.u1(x164))) + x167, x168 := bits.add_u64(x148, x162, u64(fiat.u1(x166))) + x169, x170 := bits.add_u64(x150, x154, u64(fiat.u1(x168))) + x171, x172 := bits.add_u64(x152, x155, u64(fiat.u1(x170))) + x173 := (u64(fiat.u1(x172)) + u64(fiat.u1(x153))) + x174, x175 := bits.sub_u64(x165, 0xffffffffffffffff, u64(0x0)) + x176, x177 := bits.sub_u64(x167, 0xffffffff, u64(fiat.u1(x175))) + x178, x179 := bits.sub_u64(x169, u64(0x0), u64(fiat.u1(x177))) + x180, x181 := bits.sub_u64(x171, 0xffffffff00000001, u64(fiat.u1(x179))) + _, x183 := bits.sub_u64(x173, u64(0x0), u64(fiat.u1(x181))) + x184 := fiat.cmovznz_u64(fiat.u1(x183), x174, x165) + x185 := fiat.cmovznz_u64(fiat.u1(x183), x176, x167) + x186 := fiat.cmovznz_u64(fiat.u1(x183), x178, x169) + x187 := fiat.cmovznz_u64(fiat.u1(x183), x180, x171) + out1[0] = x184 + out1[1] = x185 + out1[2] = x186 + out1[3] = x187 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg1[3]) + x8, x7 := bits.mul_u64(x4, arg1[2]) + x10, x9 := bits.mul_u64(x4, arg1[1]) + x12, x11 := bits.mul_u64(x4, arg1[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + x21, x20 := bits.mul_u64(x11, 0xffffffff00000001) + x23, x22 := bits.mul_u64(x11, 0xffffffff) + x25, x24 := bits.mul_u64(x11, 0xffffffffffffffff) + x26, x27 := bits.add_u64(x25, x22, u64(0x0)) + x28 := (u64(fiat.u1(x27)) + x23) + _, x30 := bits.add_u64(x11, x24, u64(0x0)) + x31, x32 := bits.add_u64(x13, x26, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x15, x28, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64(x17, x20, u64(fiat.u1(x34))) + x37, x38 := bits.add_u64(x19, x21, u64(fiat.u1(x36))) + x40, x39 := bits.mul_u64(x1, arg1[3]) + x42, x41 := bits.mul_u64(x1, arg1[2]) + x44, x43 := bits.mul_u64(x1, arg1[1]) + x46, x45 := bits.mul_u64(x1, arg1[0]) + x47, x48 := bits.add_u64(x46, x43, u64(0x0)) + x49, x50 := bits.add_u64(x44, x41, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x42, x39, u64(fiat.u1(x50))) + x53 := (u64(fiat.u1(x52)) + x40) + x54, x55 := bits.add_u64(x31, x45, u64(0x0)) + x56, x57 := bits.add_u64(x33, x47, u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59))) + x62, x63 := bits.add_u64(u64(fiat.u1(x38)), x53, u64(fiat.u1(x61))) + x65, x64 := bits.mul_u64(x54, 0xffffffff00000001) + x67, x66 := bits.mul_u64(x54, 0xffffffff) + x69, x68 := bits.mul_u64(x54, 0xffffffffffffffff) + x70, x71 := bits.add_u64(x69, x66, u64(0x0)) + x72 := (u64(fiat.u1(x71)) + x67) + _, x74 := bits.add_u64(x54, x68, u64(0x0)) + x75, x76 := bits.add_u64(x56, x70, u64(fiat.u1(x74))) + x77, x78 := bits.add_u64(x58, x72, u64(fiat.u1(x76))) + x79, x80 := bits.add_u64(x60, x64, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x62, x65, u64(fiat.u1(x80))) + x83 := (u64(fiat.u1(x82)) + u64(fiat.u1(x63))) + x85, x84 := bits.mul_u64(x2, arg1[3]) + x87, x86 := bits.mul_u64(x2, arg1[2]) + x89, x88 := bits.mul_u64(x2, arg1[1]) + x91, x90 := bits.mul_u64(x2, arg1[0]) + x92, x93 := bits.add_u64(x91, x88, u64(0x0)) + x94, x95 := bits.add_u64(x89, x86, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x87, x84, u64(fiat.u1(x95))) + x98 := (u64(fiat.u1(x97)) + x85) + x99, x100 := bits.add_u64(x75, x90, u64(0x0)) + x101, x102 := bits.add_u64(x77, x92, u64(fiat.u1(x100))) + x103, x104 := bits.add_u64(x79, x94, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106))) + x110, x109 := bits.mul_u64(x99, 0xffffffff00000001) + x112, x111 := bits.mul_u64(x99, 0xffffffff) + x114, x113 := bits.mul_u64(x99, 0xffffffffffffffff) + x115, x116 := bits.add_u64(x114, x111, u64(0x0)) + x117 := (u64(fiat.u1(x116)) + x112) + _, x119 := bits.add_u64(x99, x113, u64(0x0)) + x120, x121 := bits.add_u64(x101, x115, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x103, x117, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x105, x109, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x107, x110, u64(fiat.u1(x125))) + x128 := (u64(fiat.u1(x127)) + u64(fiat.u1(x108))) + x130, x129 := bits.mul_u64(x3, arg1[3]) + x132, x131 := bits.mul_u64(x3, arg1[2]) + x134, x133 := bits.mul_u64(x3, arg1[1]) + x136, x135 := bits.mul_u64(x3, arg1[0]) + x137, x138 := bits.add_u64(x136, x133, u64(0x0)) + x139, x140 := bits.add_u64(x134, x131, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x132, x129, u64(fiat.u1(x140))) + x143 := (u64(fiat.u1(x142)) + x130) + x144, x145 := bits.add_u64(x120, x135, u64(0x0)) + x146, x147 := bits.add_u64(x122, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x124, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x126, x141, u64(fiat.u1(x149))) + x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151))) + x155, x154 := bits.mul_u64(x144, 0xffffffff00000001) + x157, x156 := bits.mul_u64(x144, 0xffffffff) + x159, x158 := bits.mul_u64(x144, 0xffffffffffffffff) + x160, x161 := bits.add_u64(x159, x156, u64(0x0)) + x162 := (u64(fiat.u1(x161)) + x157) + _, x164 := bits.add_u64(x144, x158, u64(0x0)) + x165, x166 := bits.add_u64(x146, x160, u64(fiat.u1(x164))) + x167, x168 := bits.add_u64(x148, x162, u64(fiat.u1(x166))) + x169, x170 := bits.add_u64(x150, x154, u64(fiat.u1(x168))) + x171, x172 := bits.add_u64(x152, x155, u64(fiat.u1(x170))) + x173 := (u64(fiat.u1(x172)) + u64(fiat.u1(x153))) + x174, x175 := bits.sub_u64(x165, 0xffffffffffffffff, u64(0x0)) + x176, x177 := bits.sub_u64(x167, 0xffffffff, u64(fiat.u1(x175))) + x178, x179 := bits.sub_u64(x169, u64(0x0), u64(fiat.u1(x177))) + x180, x181 := bits.sub_u64(x171, 0xffffffff00000001, u64(fiat.u1(x179))) + _, x183 := bits.sub_u64(x173, u64(0x0), u64(fiat.u1(x181))) + x184 := fiat.cmovznz_u64(fiat.u1(x183), x174, x165) + x185 := fiat.cmovznz_u64(fiat.u1(x183), x176, x167) + x186 := fiat.cmovznz_u64(fiat.u1(x183), x178, x169) + x187 := fiat.cmovznz_u64(fiat.u1(x183), x180, x171) + out1[0] = x184 + out1[1] = x185 + out1[2] = x186 + out1[3] = x187 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(x1, 0xffffffffffffffff, u64(0x0)) + x11, x12 := bits.sub_u64(x3, 0xffffffff, u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x5, u64(0x0), u64(fiat.u1(x12))) + x15, x16 := bits.sub_u64(x7, 0xffffffff00000001, u64(fiat.u1(x14))) + _, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16))) + x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1) + x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3) + x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5) + x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, x9, u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xffffffff), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000001), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, x9, u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xffffffff), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000001), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0x1 + out1[1] = 0xffffffff00000000 + out1[2] = 0xffffffffffffffff + out1[3] = 0xfffffffe +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return arg1[0] | (arg1[1] | (arg1[2] | arg1[3])) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + x3, x2 := bits.mul_u64(x1, 0xffffffff00000001) + x5, x4 := bits.mul_u64(x1, 0xffffffff) + x7, x6 := bits.mul_u64(x1, 0xffffffffffffffff) + x8, x9 := bits.add_u64(x7, x4, u64(0x0)) + _, x11 := bits.add_u64(x1, x6, u64(0x0)) + x12, x13 := bits.add_u64(u64(0x0), x8, u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x12, arg1[1], u64(0x0)) + x17, x16 := bits.mul_u64(x14, 0xffffffff00000001) + x19, x18 := bits.mul_u64(x14, 0xffffffff) + x21, x20 := bits.mul_u64(x14, 0xffffffffffffffff) + x22, x23 := bits.add_u64(x21, x18, u64(0x0)) + _, x25 := bits.add_u64(x14, x20, u64(0x0)) + x26, x27 := bits.add_u64((u64(fiat.u1(x15)) + (u64(fiat.u1(x13)) + (u64(fiat.u1(x9)) + x5))), x22, u64(fiat.u1(x25))) + x28, x29 := bits.add_u64(x2, (u64(fiat.u1(x23)) + x19), u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(x3, x16, u64(fiat.u1(x29))) + x32, x33 := bits.add_u64(x26, arg1[2], u64(0x0)) + x34, x35 := bits.add_u64(x28, u64(0x0), u64(fiat.u1(x33))) + x36, x37 := bits.add_u64(x30, u64(0x0), u64(fiat.u1(x35))) + x39, x38 := bits.mul_u64(x32, 0xffffffff00000001) + x41, x40 := bits.mul_u64(x32, 0xffffffff) + x43, x42 := bits.mul_u64(x32, 0xffffffffffffffff) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + _, x47 := bits.add_u64(x32, x42, u64(0x0)) + x48, x49 := bits.add_u64(x34, x44, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x36, (u64(fiat.u1(x45)) + x41), u64(fiat.u1(x49))) + x52, x53 := bits.add_u64((u64(fiat.u1(x37)) + (u64(fiat.u1(x31)) + x17)), x38, u64(fiat.u1(x51))) + x54, x55 := bits.add_u64(x48, arg1[3], u64(0x0)) + x56, x57 := bits.add_u64(x50, u64(0x0), u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x52, u64(0x0), u64(fiat.u1(x57))) + x61, x60 := bits.mul_u64(x54, 0xffffffff00000001) + x63, x62 := bits.mul_u64(x54, 0xffffffff) + x65, x64 := bits.mul_u64(x54, 0xffffffffffffffff) + x66, x67 := bits.add_u64(x65, x62, u64(0x0)) + _, x69 := bits.add_u64(x54, x64, u64(0x0)) + x70, x71 := bits.add_u64(x56, x66, u64(fiat.u1(x69))) + x72, x73 := bits.add_u64(x58, (u64(fiat.u1(x67)) + x63), u64(fiat.u1(x71))) + x74, x75 := bits.add_u64((u64(fiat.u1(x59)) + (u64(fiat.u1(x53)) + x39)), x60, u64(fiat.u1(x73))) + x76 := (u64(fiat.u1(x75)) + x61) + x77, x78 := bits.sub_u64(x70, 0xffffffffffffffff, u64(0x0)) + x79, x80 := bits.sub_u64(x72, 0xffffffff, u64(fiat.u1(x78))) + x81, x82 := bits.sub_u64(x74, u64(0x0), u64(fiat.u1(x80))) + x83, x84 := bits.sub_u64(x76, 0xffffffff00000001, u64(fiat.u1(x82))) + _, x86 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x84))) + x87 := fiat.cmovznz_u64(fiat.u1(x86), x77, x70) + x88 := fiat.cmovznz_u64(fiat.u1(x86), x79, x72) + x89 := fiat.cmovznz_u64(fiat.u1(x86), x81, x74) + x90 := fiat.cmovznz_u64(fiat.u1(x86), x83, x76) + out1[0] = x87 + out1[1] = x88 + out1[2] = x89 + out1[3] = x90 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, 0x4fffffffd) + x8, x7 := bits.mul_u64(x4, 0xfffffffffffffffe) + x10, x9 := bits.mul_u64(x4, 0xfffffffbffffffff) + x12, x11 := bits.mul_u64(x4, 0x3) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x20, x19 := bits.mul_u64(x11, 0xffffffff00000001) + x22, x21 := bits.mul_u64(x11, 0xffffffff) + x24, x23 := bits.mul_u64(x11, 0xffffffffffffffff) + x25, x26 := bits.add_u64(x24, x21, u64(0x0)) + _, x28 := bits.add_u64(x11, x23, u64(0x0)) + x29, x30 := bits.add_u64(x13, x25, u64(fiat.u1(x28))) + x31, x32 := bits.add_u64(x15, (u64(fiat.u1(x26)) + x22), u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x17, x19, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64((u64(fiat.u1(x18)) + x6), x20, u64(fiat.u1(x34))) + x38, x37 := bits.mul_u64(x1, 0x4fffffffd) + x40, x39 := bits.mul_u64(x1, 0xfffffffffffffffe) + x42, x41 := bits.mul_u64(x1, 0xfffffffbffffffff) + x44, x43 := bits.mul_u64(x1, 0x3) + x45, x46 := bits.add_u64(x44, x41, u64(0x0)) + x47, x48 := bits.add_u64(x42, x39, u64(fiat.u1(x46))) + x49, x50 := bits.add_u64(x40, x37, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x29, x43, u64(0x0)) + x53, x54 := bits.add_u64(x31, x45, u64(fiat.u1(x52))) + x55, x56 := bits.add_u64(x33, x47, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(x35, x49, u64(fiat.u1(x56))) + x60, x59 := bits.mul_u64(x51, 0xffffffff00000001) + x62, x61 := bits.mul_u64(x51, 0xffffffff) + x64, x63 := bits.mul_u64(x51, 0xffffffffffffffff) + x65, x66 := bits.add_u64(x64, x61, u64(0x0)) + _, x68 := bits.add_u64(x51, x63, u64(0x0)) + x69, x70 := bits.add_u64(x53, x65, u64(fiat.u1(x68))) + x71, x72 := bits.add_u64(x55, (u64(fiat.u1(x66)) + x62), u64(fiat.u1(x70))) + x73, x74 := bits.add_u64(x57, x59, u64(fiat.u1(x72))) + x75, x76 := bits.add_u64(((u64(fiat.u1(x58)) + u64(fiat.u1(x36))) + (u64(fiat.u1(x50)) + x38)), x60, u64(fiat.u1(x74))) + x78, x77 := bits.mul_u64(x2, 0x4fffffffd) + x80, x79 := bits.mul_u64(x2, 0xfffffffffffffffe) + x82, x81 := bits.mul_u64(x2, 0xfffffffbffffffff) + x84, x83 := bits.mul_u64(x2, 0x3) + x85, x86 := bits.add_u64(x84, x81, u64(0x0)) + x87, x88 := bits.add_u64(x82, x79, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x80, x77, u64(fiat.u1(x88))) + x91, x92 := bits.add_u64(x69, x83, u64(0x0)) + x93, x94 := bits.add_u64(x71, x85, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x73, x87, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x75, x89, u64(fiat.u1(x96))) + x100, x99 := bits.mul_u64(x91, 0xffffffff00000001) + x102, x101 := bits.mul_u64(x91, 0xffffffff) + x104, x103 := bits.mul_u64(x91, 0xffffffffffffffff) + x105, x106 := bits.add_u64(x104, x101, u64(0x0)) + _, x108 := bits.add_u64(x91, x103, u64(0x0)) + x109, x110 := bits.add_u64(x93, x105, u64(fiat.u1(x108))) + x111, x112 := bits.add_u64(x95, (u64(fiat.u1(x106)) + x102), u64(fiat.u1(x110))) + x113, x114 := bits.add_u64(x97, x99, u64(fiat.u1(x112))) + x115, x116 := bits.add_u64(((u64(fiat.u1(x98)) + u64(fiat.u1(x76))) + (u64(fiat.u1(x90)) + x78)), x100, u64(fiat.u1(x114))) + x118, x117 := bits.mul_u64(x3, 0x4fffffffd) + x120, x119 := bits.mul_u64(x3, 0xfffffffffffffffe) + x122, x121 := bits.mul_u64(x3, 0xfffffffbffffffff) + x124, x123 := bits.mul_u64(x3, 0x3) + x125, x126 := bits.add_u64(x124, x121, u64(0x0)) + x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126))) + x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128))) + x131, x132 := bits.add_u64(x109, x123, u64(0x0)) + x133, x134 := bits.add_u64(x111, x125, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x113, x127, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x115, x129, u64(fiat.u1(x136))) + x140, x139 := bits.mul_u64(x131, 0xffffffff00000001) + x142, x141 := bits.mul_u64(x131, 0xffffffff) + x144, x143 := bits.mul_u64(x131, 0xffffffffffffffff) + x145, x146 := bits.add_u64(x144, x141, u64(0x0)) + _, x148 := bits.add_u64(x131, x143, u64(0x0)) + x149, x150 := bits.add_u64(x133, x145, u64(fiat.u1(x148))) + x151, x152 := bits.add_u64(x135, (u64(fiat.u1(x146)) + x142), u64(fiat.u1(x150))) + x153, x154 := bits.add_u64(x137, x139, u64(fiat.u1(x152))) + x155, x156 := bits.add_u64(((u64(fiat.u1(x138)) + u64(fiat.u1(x116))) + (u64(fiat.u1(x130)) + x118)), x140, u64(fiat.u1(x154))) + x157, x158 := bits.sub_u64(x149, 0xffffffffffffffff, u64(0x0)) + x159, x160 := bits.sub_u64(x151, 0xffffffff, u64(fiat.u1(x158))) + x161, x162 := bits.sub_u64(x153, u64(0x0), u64(fiat.u1(x160))) + x163, x164 := bits.sub_u64(x155, 0xffffffff00000001, u64(fiat.u1(x162))) + _, x166 := bits.sub_u64(u64(fiat.u1(x156)), u64(0x0), u64(fiat.u1(x164))) + x167 := fiat.cmovznz_u64(fiat.u1(x166), x157, x149) + x168 := fiat.cmovznz_u64(fiat.u1(x166), x159, x151) + x169 := fiat.cmovznz_u64(fiat.u1(x166), x161, x153) + x170 := fiat.cmovznz_u64(fiat.u1(x166), x163, x155) + out1[0] = x167 + out1[1] = x168 + out1[2] = x169 + out1[3] = x170 +} diff --git a/core/crypto/_fiat/field_p384r1/field.odin b/core/crypto/_fiat/field_p384r1/field.odin new file mode 100644 index 000000000..2bddff18c --- /dev/null +++ b/core/crypto/_fiat/field_p384r1/field.odin @@ -0,0 +1,436 @@ +package field_p384r1 + +import "core:crypto" +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + crypto.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, + unsafe_assume_canonical := false, +) -> bool { + ensure_contextless(len(arg1) == 48, "p384r1: invalid fe input buffer") + + // Note: We assume the input is in big-endian. + tmp := Non_Montgomery_Domain_Field_Element { + endian.unchecked_get_u64be(arg1[40:]), + endian.unchecked_get_u64be(arg1[32:]), + endian.unchecked_get_u64be(arg1[24:]), + endian.unchecked_get_u64be(arg1[16:]), + endian.unchecked_get_u64be(arg1[8:]), + endian.unchecked_get_u64be(arg1[0:]), + } + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + // Check that tmp is in the the range [0, ELL). + if !unsafe_assume_canonical { + _, borrow := bits.sub_u64(ELL[0] - 1, tmp[0], 0) + _, borrow = bits.sub_u64(ELL[1], tmp[1], borrow) + _, borrow = bits.sub_u64(ELL[2], tmp[2], borrow) + _, borrow = bits.sub_u64(ELL[3], tmp[3], borrow) + _, borrow = bits.sub_u64(ELL[4], tmp[4], borrow) + _, borrow = bits.sub_u64(ELL[5], tmp[5], borrow) + if borrow != 0 { + return false + } + } + + fe_to_montgomery(out1, &tmp) + + return true +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 48, "p384r1: invalid fe output buffer") + + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[40:], tmp[0]) + endian.unchecked_put_u64be(out1[32:], tmp[1]) + endian.unchecked_put_u64be(out1[24:], tmp[2]) + endian.unchecked_put_u64be(out1[16:], tmp[3]) + endian.unchecked_put_u64be(out1[8:], tmp[4]) + endian.unchecked_put_u64be(out1[0:], tmp[5]) + + crypto.zero_explicit(&tmp, size_of(tmp)) +} + +@(require_results) +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element = --- + fe_sub(&tmp, arg1, arg2) + + // This will only underflow if and only if (⟺) arg1 == arg2, and we return the borrow, + // which will be 1. + is_eq := subtle.u64_is_zero(fe_non_zero(&tmp)) + + fe_clear(&tmp) + + return int(is_eq) +} + +@(require_results) +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element = --- + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_pow2k :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_square(out1, out1) + } +} + +fe_inv :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x24 = x12 << 12 + x12 + // x30 = x24 << 6 + _111111 + // x31 = 2*x30 + 1 + // x32 = 2*x31 + 1 + // x63 = x32 << 31 + x31 + // x126 = x63 << 63 + x63 + // x252 = x126 << 126 + x126 + // x255 = x252 << 3 + _111 + // return ((x255 << 33 + x32) << 94 + x30) << 2 + // + // Operations: 383 squares 14 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Note: Need to stash `arg1` (`xx`) in the case that `out1`/`arg1` alias, + // as `arg1` is used after `out1` has been altered. + t0, t1, t2, t3, xx: Montgomery_Domain_Field_Element = ---, ---, ---, ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 3: z = x^0x6 + fe_square(out1, out1) + + // Step 4: t1 = x^0x7 + fe_mul(&t1, &xx, out1) + + // Step 7: z = x^0x38 + fe_pow2k(out1, &t1, 3) + + // Step 8: z = x^0x3f + fe_mul(out1, &t1, out1) + + // Step 14: t0 = x^0xfc0 + fe_pow2k(&t0, out1, 6) + + // Step 15: t0 = x^0xfff + fe_mul(&t0, out1, &t0) + + // Step 27: t2 = x^0xfff000 + fe_pow2k(&t2, &t0, 12) + + // Step 28: t0 = x^0xffffff + fe_mul(&t0, &t0, &t2) + + // Step 34: t0 = x^0x3fffffc0 + fe_pow2k(&t0, &t0, 6) + + // Step 35: z = x^0x3fffffff + fe_mul(out1, out1, &t0) + + // Step 36: t0 = x^0x7ffffffe + fe_square(&t0, out1) + + // Step 37: t2 = x^0x7fffffff + fe_mul(&t2, &xx, &t0) + + // Step 38: t0 = x^0xfffffffe + fe_square(&t0, &t2) + + // Step 39: t0 = x^0xffffffff + fe_mul(&t0, &xx, &t0) + + // Step 70: t3 = x^0x7fffffff80000000 + fe_pow2k(&t3, &t0, 31) + + // Step 71: t2 = x^0x7fffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 134: t3 = x^0x3fffffffffffffff8000000000000000 + fe_pow2k(&t3, &t2, 63) + + // Step 135: t2 = x^0x3fffffffffffffffffffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 261: t3 = x^0xfffffffffffffffffffffffffffffffc0000000000000000000000000000000 + fe_pow2k(&t3, &t2, 126) + + // Step 262: t2 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 265: t2 = x^0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 + fe_pow2k(&t2, &t2, 3) + + // Step 266: t1 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t1, &t1, &t2) + + // Step 299: t1 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 + fe_pow2k(&t1, &t1, 33) + + // Step 300: t0 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff + fe_mul(&t0, &t0, &t1) + + // Step 394: t0 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000000000000 + fe_pow2k(&t0, &t0, 94) + + // Step 395: z = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc0000000000000003fffffff + fe_mul(out1, out1, &t0) + + // Step 397: z = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc + fe_pow2k(out1, out1, 2) + + fe_mul(out1, out1, &xx) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &t2, &t3, &xx}) +} + +@(require_results) +fe_sqrt :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) -> int { + // Square root candidate can be derived via exponentiation by `(p + 1) / 4` + // From sage: 9850501549098619803069760025035903451269934817616361666987073351061430442874217582261816522064734500465401743278080 + // + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x24 = x12 << 12 + x12 + // x30 = x24 << 6 + _111111 + // x31 = 2*x30 + 1 + // x32 = 2*x31 + 1 + // x63 = x32 << 31 + x31 + // x126 = x63 << 63 + x63 + // x252 = x126 << 126 + x126 + // x255 = x252 << 3 + _111 + // return ((x255 << 33 + x32) << 94 + x30) << 2 + // + // Operations: 383 squares 14 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Likewise this tramples over arg1, so stash another copy. + t0, t1, t2, t3, xx: Montgomery_Domain_Field_Element = ---, ---, ---, ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 3: z = x^0x6 + fe_square(out1, out1) + + // Step 4: t1 = x^0x7 + fe_mul(&t1, &xx, out1) + + // Step 7: z = x^0x38 + fe_pow2k(out1, &t1, 3) + + // Step 8: z = x^0x3f + fe_mul(out1, &t1, out1) + + // Step 14: t0 = x^0xfc0 + fe_pow2k(&t0, out1, 6) + + // Step 15: t0 = x^0xfff + fe_mul(&t0, out1, &t0) + + // Step 27: t2 = x^0xfff000 + fe_pow2k(&t2, &t0, 12) + + // Step 28: t0 = x^0xffffff + fe_mul(&t0, &t0, &t2) + + // Step 34: t0 = x^0x3fffffc0 + fe_pow2k(&t0, &t0, 6) + + // Step 35: z = x^0x3fffffff + fe_mul(out1, out1, &t0) + + // Step 36: t0 = x^0x7ffffffe + fe_square(&t0, out1) + + // Step 37: t2 = x^0x7fffffff + fe_mul(&t2, &xx, &t0) + + // Step 38: t0 = x^0xfffffffe + fe_square(&t0, &t2) + + // Step 39: t0 = x^0xffffffff + fe_mul(&t0, &xx, &t0) + + // Step 70: t3 = x^0x7fffffff80000000 + fe_pow2k(&t3, &t0, 31) + + // Step 71: t2 = x^0x7fffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 134: t3 = x^0x3fffffffffffffff8000000000000000 + fe_pow2k(&t3, &t2, 63) + + // Step 135: t2 = x^0x3fffffffffffffffffffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 261: t3 = x^0xfffffffffffffffffffffffffffffffc0000000000000000000000000000000 + fe_pow2k(&t3, &t2, 126) + + // Step 262: t2 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t2, &t2, &t3) + + // Step 265: t2 = x^0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 + fe_pow2k(&t2, &t2, 3) + + // Step 266: t1 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t1, &t1, &t2) + + // Step 299: t1 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 + fe_pow2k(&t1, &t1, 33) + + // Step 300: t0 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff + fe_mul(&t0, &t0, &t1) + + // Step 394: t0 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000000000000 + fe_pow2k(&t0, &t0, 94) + + // Step 395: z = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc0000000000000003fffffff + fe_mul(out1, out1, &t0) + + // Step 397: z = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc + fe_pow2k(out1, out1, 2) + + // Ensure that our candidate is actually the square root. + check, zero: Montgomery_Domain_Field_Element + fe_square(&check, out1) + + is_valid := fe_equal(&check, &xx) + fe_cond_select(out1, &zero, out1, is_valid) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &t2, &t3, &xx, &check}) + + return is_valid +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 + out1[4] = 0 + out1[5] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + x5 := arg1[4] + x6 := arg1[5] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + x = (out1[4] ~ out2[4]) & mask + x5, y5 := out1[4] ~ x, out2[4] ~ x + x = (out1[5] ~ out2[5]) & mask + x6, y6 := out1[5] ~ x, out2[5] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 + out1[4], out2[4] = x5, y5 + out1[5], out2[5] = x6, y6 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^Montgomery_Domain_Field_Element, + arg3: int, +) { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + x5 := ((mask & arg2[4]) | ((~mask) & arg1[4])) + x6 := ((mask & arg2[5]) | ((~mask) & arg1[5])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} diff --git a/core/crypto/_fiat/field_p384r1/field64.odin b/core/crypto/_fiat/field_p384r1/field64.odin new file mode 100644 index 000000000..493f24b17 --- /dev/null +++ b/core/crypto/_fiat/field_p384r1/field64.odin @@ -0,0 +1,1063 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_p384r1 + +// The file provides arithmetic on the field Z/(2^384 - 2^128 - 2^96 + 2^32 - 1) +// using a 64-bit Montgomery form internal representation. It is derived +// primarily from the machine generated Golang output from the fiat-crypto +// project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [6]u64{0xffffffff, 0xffffffff00000000, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff} + +Montgomery_Domain_Field_Element :: distinct [6]u64 +Non_Montgomery_Domain_Field_Element :: distinct [6]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, arg2[5]) + x10, x9 := bits.mul_u64(x6, arg2[4]) + x12, x11 := bits.mul_u64(x6, arg2[3]) + x14, x13 := bits.mul_u64(x6, arg2[2]) + x16, x15 := bits.mul_u64(x6, arg2[1]) + x18, x17 := bits.mul_u64(x6, arg2[0]) + x19, x20 := bits.add_u64(x18, x15, u64(0x0)) + x21, x22 := bits.add_u64(x16, x13, u64(fiat.u1(x20))) + x23, x24 := bits.add_u64(x14, x11, u64(fiat.u1(x22))) + x25, x26 := bits.add_u64(x12, x9, u64(fiat.u1(x24))) + x27, x28 := bits.add_u64(x10, x7, u64(fiat.u1(x26))) + x29 := (u64(fiat.u1(x28)) + x8) + _, x30 := bits.mul_u64(x17, 0x100000001) + x33, x32 := bits.mul_u64(x30, 0xffffffffffffffff) + x35, x34 := bits.mul_u64(x30, 0xffffffffffffffff) + x37, x36 := bits.mul_u64(x30, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x30, 0xfffffffffffffffe) + x41, x40 := bits.mul_u64(x30, 0xffffffff00000000) + x43, x42 := bits.mul_u64(x30, 0xffffffff) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + x46, x47 := bits.add_u64(x41, x38, u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x39, x36, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x37, x34, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x35, x32, u64(fiat.u1(x51))) + x54 := (u64(fiat.u1(x53)) + x33) + _, x56 := bits.add_u64(x17, x42, u64(0x0)) + x57, x58 := bits.add_u64(x19, x44, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x21, x46, u64(fiat.u1(x58))) + x61, x62 := bits.add_u64(x23, x48, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x25, x50, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x27, x52, u64(fiat.u1(x64))) + x67, x68 := bits.add_u64(x29, x54, u64(fiat.u1(x66))) + x70, x69 := bits.mul_u64(x1, arg2[5]) + x72, x71 := bits.mul_u64(x1, arg2[4]) + x74, x73 := bits.mul_u64(x1, arg2[3]) + x76, x75 := bits.mul_u64(x1, arg2[2]) + x78, x77 := bits.mul_u64(x1, arg2[1]) + x80, x79 := bits.mul_u64(x1, arg2[0]) + x81, x82 := bits.add_u64(x80, x77, u64(0x0)) + x83, x84 := bits.add_u64(x78, x75, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x76, x73, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x74, x71, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x72, x69, u64(fiat.u1(x88))) + x91 := (u64(fiat.u1(x90)) + x70) + x92, x93 := bits.add_u64(x57, x79, u64(0x0)) + x94, x95 := bits.add_u64(x59, x81, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x61, x83, u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x63, x85, u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x65, x87, u64(fiat.u1(x99))) + x102, x103 := bits.add_u64(x67, x89, u64(fiat.u1(x101))) + x104, x105 := bits.add_u64(u64(fiat.u1(x68)), x91, u64(fiat.u1(x103))) + _, x106 := bits.mul_u64(x92, 0x100000001) + x109, x108 := bits.mul_u64(x106, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x106, 0xffffffffffffffff) + x113, x112 := bits.mul_u64(x106, 0xffffffffffffffff) + x115, x114 := bits.mul_u64(x106, 0xfffffffffffffffe) + x117, x116 := bits.mul_u64(x106, 0xffffffff00000000) + x119, x118 := bits.mul_u64(x106, 0xffffffff) + x120, x121 := bits.add_u64(x119, x116, u64(0x0)) + x122, x123 := bits.add_u64(x117, x114, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x115, x112, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x113, x110, u64(fiat.u1(x125))) + x128, x129 := bits.add_u64(x111, x108, u64(fiat.u1(x127))) + x130 := (u64(fiat.u1(x129)) + x109) + _, x132 := bits.add_u64(x92, x118, u64(0x0)) + x133, x134 := bits.add_u64(x94, x120, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x96, x122, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x98, x124, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x100, x126, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x102, x128, u64(fiat.u1(x140))) + x143, x144 := bits.add_u64(x104, x130, u64(fiat.u1(x142))) + x145 := (u64(fiat.u1(x144)) + u64(fiat.u1(x105))) + x147, x146 := bits.mul_u64(x2, arg2[5]) + x149, x148 := bits.mul_u64(x2, arg2[4]) + x151, x150 := bits.mul_u64(x2, arg2[3]) + x153, x152 := bits.mul_u64(x2, arg2[2]) + x155, x154 := bits.mul_u64(x2, arg2[1]) + x157, x156 := bits.mul_u64(x2, arg2[0]) + x158, x159 := bits.add_u64(x157, x154, u64(0x0)) + x160, x161 := bits.add_u64(x155, x152, u64(fiat.u1(x159))) + x162, x163 := bits.add_u64(x153, x150, u64(fiat.u1(x161))) + x164, x165 := bits.add_u64(x151, x148, u64(fiat.u1(x163))) + x166, x167 := bits.add_u64(x149, x146, u64(fiat.u1(x165))) + x168 := (u64(fiat.u1(x167)) + x147) + x169, x170 := bits.add_u64(x133, x156, u64(0x0)) + x171, x172 := bits.add_u64(x135, x158, u64(fiat.u1(x170))) + x173, x174 := bits.add_u64(x137, x160, u64(fiat.u1(x172))) + x175, x176 := bits.add_u64(x139, x162, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x141, x164, u64(fiat.u1(x176))) + x179, x180 := bits.add_u64(x143, x166, u64(fiat.u1(x178))) + x181, x182 := bits.add_u64(x145, x168, u64(fiat.u1(x180))) + _, x183 := bits.mul_u64(x169, 0x100000001) + x186, x185 := bits.mul_u64(x183, 0xffffffffffffffff) + x188, x187 := bits.mul_u64(x183, 0xffffffffffffffff) + x190, x189 := bits.mul_u64(x183, 0xffffffffffffffff) + x192, x191 := bits.mul_u64(x183, 0xfffffffffffffffe) + x194, x193 := bits.mul_u64(x183, 0xffffffff00000000) + x196, x195 := bits.mul_u64(x183, 0xffffffff) + x197, x198 := bits.add_u64(x196, x193, u64(0x0)) + x199, x200 := bits.add_u64(x194, x191, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x192, x189, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x190, x187, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x188, x185, u64(fiat.u1(x204))) + x207 := (u64(fiat.u1(x206)) + x186) + _, x209 := bits.add_u64(x169, x195, u64(0x0)) + x210, x211 := bits.add_u64(x171, x197, u64(fiat.u1(x209))) + x212, x213 := bits.add_u64(x173, x199, u64(fiat.u1(x211))) + x214, x215 := bits.add_u64(x175, x201, u64(fiat.u1(x213))) + x216, x217 := bits.add_u64(x177, x203, u64(fiat.u1(x215))) + x218, x219 := bits.add_u64(x179, x205, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x181, x207, u64(fiat.u1(x219))) + x222 := (u64(fiat.u1(x221)) + u64(fiat.u1(x182))) + x224, x223 := bits.mul_u64(x3, arg2[5]) + x226, x225 := bits.mul_u64(x3, arg2[4]) + x228, x227 := bits.mul_u64(x3, arg2[3]) + x230, x229 := bits.mul_u64(x3, arg2[2]) + x232, x231 := bits.mul_u64(x3, arg2[1]) + x234, x233 := bits.mul_u64(x3, arg2[0]) + x235, x236 := bits.add_u64(x234, x231, u64(0x0)) + x237, x238 := bits.add_u64(x232, x229, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x230, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x228, x225, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x226, x223, u64(fiat.u1(x242))) + x245 := (u64(fiat.u1(x244)) + x224) + x246, x247 := bits.add_u64(x210, x233, u64(0x0)) + x248, x249 := bits.add_u64(x212, x235, u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x214, x237, u64(fiat.u1(x249))) + x252, x253 := bits.add_u64(x216, x239, u64(fiat.u1(x251))) + x254, x255 := bits.add_u64(x218, x241, u64(fiat.u1(x253))) + x256, x257 := bits.add_u64(x220, x243, u64(fiat.u1(x255))) + x258, x259 := bits.add_u64(x222, x245, u64(fiat.u1(x257))) + _, x260 := bits.mul_u64(x246, 0x100000001) + x263, x262 := bits.mul_u64(x260, 0xffffffffffffffff) + x265, x264 := bits.mul_u64(x260, 0xffffffffffffffff) + x267, x266 := bits.mul_u64(x260, 0xffffffffffffffff) + x269, x268 := bits.mul_u64(x260, 0xfffffffffffffffe) + x271, x270 := bits.mul_u64(x260, 0xffffffff00000000) + x273, x272 := bits.mul_u64(x260, 0xffffffff) + x274, x275 := bits.add_u64(x273, x270, u64(0x0)) + x276, x277 := bits.add_u64(x271, x268, u64(fiat.u1(x275))) + x278, x279 := bits.add_u64(x269, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x267, x264, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x265, x262, u64(fiat.u1(x281))) + x284 := (u64(fiat.u1(x283)) + x263) + _, x286 := bits.add_u64(x246, x272, u64(0x0)) + x287, x288 := bits.add_u64(x248, x274, u64(fiat.u1(x286))) + x289, x290 := bits.add_u64(x250, x276, u64(fiat.u1(x288))) + x291, x292 := bits.add_u64(x252, x278, u64(fiat.u1(x290))) + x293, x294 := bits.add_u64(x254, x280, u64(fiat.u1(x292))) + x295, x296 := bits.add_u64(x256, x282, u64(fiat.u1(x294))) + x297, x298 := bits.add_u64(x258, x284, u64(fiat.u1(x296))) + x299 := (u64(fiat.u1(x298)) + u64(fiat.u1(x259))) + x301, x300 := bits.mul_u64(x4, arg2[5]) + x303, x302 := bits.mul_u64(x4, arg2[4]) + x305, x304 := bits.mul_u64(x4, arg2[3]) + x307, x306 := bits.mul_u64(x4, arg2[2]) + x309, x308 := bits.mul_u64(x4, arg2[1]) + x311, x310 := bits.mul_u64(x4, arg2[0]) + x312, x313 := bits.add_u64(x311, x308, u64(0x0)) + x314, x315 := bits.add_u64(x309, x306, u64(fiat.u1(x313))) + x316, x317 := bits.add_u64(x307, x304, u64(fiat.u1(x315))) + x318, x319 := bits.add_u64(x305, x302, u64(fiat.u1(x317))) + x320, x321 := bits.add_u64(x303, x300, u64(fiat.u1(x319))) + x322 := (u64(fiat.u1(x321)) + x301) + x323, x324 := bits.add_u64(x287, x310, u64(0x0)) + x325, x326 := bits.add_u64(x289, x312, u64(fiat.u1(x324))) + x327, x328 := bits.add_u64(x291, x314, u64(fiat.u1(x326))) + x329, x330 := bits.add_u64(x293, x316, u64(fiat.u1(x328))) + x331, x332 := bits.add_u64(x295, x318, u64(fiat.u1(x330))) + x333, x334 := bits.add_u64(x297, x320, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x299, x322, u64(fiat.u1(x334))) + _, x337 := bits.mul_u64(x323, 0x100000001) + x340, x339 := bits.mul_u64(x337, 0xffffffffffffffff) + x342, x341 := bits.mul_u64(x337, 0xffffffffffffffff) + x344, x343 := bits.mul_u64(x337, 0xffffffffffffffff) + x346, x345 := bits.mul_u64(x337, 0xfffffffffffffffe) + x348, x347 := bits.mul_u64(x337, 0xffffffff00000000) + x350, x349 := bits.mul_u64(x337, 0xffffffff) + x351, x352 := bits.add_u64(x350, x347, u64(0x0)) + x353, x354 := bits.add_u64(x348, x345, u64(fiat.u1(x352))) + x355, x356 := bits.add_u64(x346, x343, u64(fiat.u1(x354))) + x357, x358 := bits.add_u64(x344, x341, u64(fiat.u1(x356))) + x359, x360 := bits.add_u64(x342, x339, u64(fiat.u1(x358))) + x361 := (u64(fiat.u1(x360)) + x340) + _, x363 := bits.add_u64(x323, x349, u64(0x0)) + x364, x365 := bits.add_u64(x325, x351, u64(fiat.u1(x363))) + x366, x367 := bits.add_u64(x327, x353, u64(fiat.u1(x365))) + x368, x369 := bits.add_u64(x329, x355, u64(fiat.u1(x367))) + x370, x371 := bits.add_u64(x331, x357, u64(fiat.u1(x369))) + x372, x373 := bits.add_u64(x333, x359, u64(fiat.u1(x371))) + x374, x375 := bits.add_u64(x335, x361, u64(fiat.u1(x373))) + x376 := (u64(fiat.u1(x375)) + u64(fiat.u1(x336))) + x378, x377 := bits.mul_u64(x5, arg2[5]) + x380, x379 := bits.mul_u64(x5, arg2[4]) + x382, x381 := bits.mul_u64(x5, arg2[3]) + x384, x383 := bits.mul_u64(x5, arg2[2]) + x386, x385 := bits.mul_u64(x5, arg2[1]) + x388, x387 := bits.mul_u64(x5, arg2[0]) + x389, x390 := bits.add_u64(x388, x385, u64(0x0)) + x391, x392 := bits.add_u64(x386, x383, u64(fiat.u1(x390))) + x393, x394 := bits.add_u64(x384, x381, u64(fiat.u1(x392))) + x395, x396 := bits.add_u64(x382, x379, u64(fiat.u1(x394))) + x397, x398 := bits.add_u64(x380, x377, u64(fiat.u1(x396))) + x399 := (u64(fiat.u1(x398)) + x378) + x400, x401 := bits.add_u64(x364, x387, u64(0x0)) + x402, x403 := bits.add_u64(x366, x389, u64(fiat.u1(x401))) + x404, x405 := bits.add_u64(x368, x391, u64(fiat.u1(x403))) + x406, x407 := bits.add_u64(x370, x393, u64(fiat.u1(x405))) + x408, x409 := bits.add_u64(x372, x395, u64(fiat.u1(x407))) + x410, x411 := bits.add_u64(x374, x397, u64(fiat.u1(x409))) + x412, x413 := bits.add_u64(x376, x399, u64(fiat.u1(x411))) + _, x414 := bits.mul_u64(x400, 0x100000001) + x417, x416 := bits.mul_u64(x414, 0xffffffffffffffff) + x419, x418 := bits.mul_u64(x414, 0xffffffffffffffff) + x421, x420 := bits.mul_u64(x414, 0xffffffffffffffff) + x423, x422 := bits.mul_u64(x414, 0xfffffffffffffffe) + x425, x424 := bits.mul_u64(x414, 0xffffffff00000000) + x427, x426 := bits.mul_u64(x414, 0xffffffff) + x428, x429 := bits.add_u64(x427, x424, u64(0x0)) + x430, x431 := bits.add_u64(x425, x422, u64(fiat.u1(x429))) + x432, x433 := bits.add_u64(x423, x420, u64(fiat.u1(x431))) + x434, x435 := bits.add_u64(x421, x418, u64(fiat.u1(x433))) + x436, x437 := bits.add_u64(x419, x416, u64(fiat.u1(x435))) + x438 := (u64(fiat.u1(x437)) + x417) + _, x440 := bits.add_u64(x400, x426, u64(0x0)) + x441, x442 := bits.add_u64(x402, x428, u64(fiat.u1(x440))) + x443, x444 := bits.add_u64(x404, x430, u64(fiat.u1(x442))) + x445, x446 := bits.add_u64(x406, x432, u64(fiat.u1(x444))) + x447, x448 := bits.add_u64(x408, x434, u64(fiat.u1(x446))) + x449, x450 := bits.add_u64(x410, x436, u64(fiat.u1(x448))) + x451, x452 := bits.add_u64(x412, x438, u64(fiat.u1(x450))) + x453 := (u64(fiat.u1(x452)) + u64(fiat.u1(x413))) + x454, x455 := bits.sub_u64(x441, 0xffffffff, u64(0x0)) + x456, x457 := bits.sub_u64(x443, 0xffffffff00000000, u64(fiat.u1(x455))) + x458, x459 := bits.sub_u64(x445, 0xfffffffffffffffe, u64(fiat.u1(x457))) + x460, x461 := bits.sub_u64(x447, 0xffffffffffffffff, u64(fiat.u1(x459))) + x462, x463 := bits.sub_u64(x449, 0xffffffffffffffff, u64(fiat.u1(x461))) + x464, x465 := bits.sub_u64(x451, 0xffffffffffffffff, u64(fiat.u1(x463))) + _, x467 := bits.sub_u64(x453, u64(0x0), u64(fiat.u1(x465))) + x468 := fiat.cmovznz_u64(fiat.u1(x467), x454, x441) + x469 := fiat.cmovznz_u64(fiat.u1(x467), x456, x443) + x470 := fiat.cmovznz_u64(fiat.u1(x467), x458, x445) + x471 := fiat.cmovznz_u64(fiat.u1(x467), x460, x447) + x472 := fiat.cmovznz_u64(fiat.u1(x467), x462, x449) + x473 := fiat.cmovznz_u64(fiat.u1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, arg1[5]) + x10, x9 := bits.mul_u64(x6, arg1[4]) + x12, x11 := bits.mul_u64(x6, arg1[3]) + x14, x13 := bits.mul_u64(x6, arg1[2]) + x16, x15 := bits.mul_u64(x6, arg1[1]) + x18, x17 := bits.mul_u64(x6, arg1[0]) + x19, x20 := bits.add_u64(x18, x15, u64(0x0)) + x21, x22 := bits.add_u64(x16, x13, u64(fiat.u1(x20))) + x23, x24 := bits.add_u64(x14, x11, u64(fiat.u1(x22))) + x25, x26 := bits.add_u64(x12, x9, u64(fiat.u1(x24))) + x27, x28 := bits.add_u64(x10, x7, u64(fiat.u1(x26))) + x29 := (u64(fiat.u1(x28)) + x8) + _, x30 := bits.mul_u64(x17, 0x100000001) + x33, x32 := bits.mul_u64(x30, 0xffffffffffffffff) + x35, x34 := bits.mul_u64(x30, 0xffffffffffffffff) + x37, x36 := bits.mul_u64(x30, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x30, 0xfffffffffffffffe) + x41, x40 := bits.mul_u64(x30, 0xffffffff00000000) + x43, x42 := bits.mul_u64(x30, 0xffffffff) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + x46, x47 := bits.add_u64(x41, x38, u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x39, x36, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x37, x34, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x35, x32, u64(fiat.u1(x51))) + x54 := (u64(fiat.u1(x53)) + x33) + _, x56 := bits.add_u64(x17, x42, u64(0x0)) + x57, x58 := bits.add_u64(x19, x44, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x21, x46, u64(fiat.u1(x58))) + x61, x62 := bits.add_u64(x23, x48, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x25, x50, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x27, x52, u64(fiat.u1(x64))) + x67, x68 := bits.add_u64(x29, x54, u64(fiat.u1(x66))) + x70, x69 := bits.mul_u64(x1, arg1[5]) + x72, x71 := bits.mul_u64(x1, arg1[4]) + x74, x73 := bits.mul_u64(x1, arg1[3]) + x76, x75 := bits.mul_u64(x1, arg1[2]) + x78, x77 := bits.mul_u64(x1, arg1[1]) + x80, x79 := bits.mul_u64(x1, arg1[0]) + x81, x82 := bits.add_u64(x80, x77, u64(0x0)) + x83, x84 := bits.add_u64(x78, x75, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x76, x73, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x74, x71, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x72, x69, u64(fiat.u1(x88))) + x91 := (u64(fiat.u1(x90)) + x70) + x92, x93 := bits.add_u64(x57, x79, u64(0x0)) + x94, x95 := bits.add_u64(x59, x81, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x61, x83, u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x63, x85, u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x65, x87, u64(fiat.u1(x99))) + x102, x103 := bits.add_u64(x67, x89, u64(fiat.u1(x101))) + x104, x105 := bits.add_u64(u64(fiat.u1(x68)), x91, u64(fiat.u1(x103))) + _, x106 := bits.mul_u64(x92, 0x100000001) + x109, x108 := bits.mul_u64(x106, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x106, 0xffffffffffffffff) + x113, x112 := bits.mul_u64(x106, 0xffffffffffffffff) + x115, x114 := bits.mul_u64(x106, 0xfffffffffffffffe) + x117, x116 := bits.mul_u64(x106, 0xffffffff00000000) + x119, x118 := bits.mul_u64(x106, 0xffffffff) + x120, x121 := bits.add_u64(x119, x116, u64(0x0)) + x122, x123 := bits.add_u64(x117, x114, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x115, x112, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x113, x110, u64(fiat.u1(x125))) + x128, x129 := bits.add_u64(x111, x108, u64(fiat.u1(x127))) + x130 := (u64(fiat.u1(x129)) + x109) + _, x132 := bits.add_u64(x92, x118, u64(0x0)) + x133, x134 := bits.add_u64(x94, x120, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x96, x122, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x98, x124, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x100, x126, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x102, x128, u64(fiat.u1(x140))) + x143, x144 := bits.add_u64(x104, x130, u64(fiat.u1(x142))) + x145 := (u64(fiat.u1(x144)) + u64(fiat.u1(x105))) + x147, x146 := bits.mul_u64(x2, arg1[5]) + x149, x148 := bits.mul_u64(x2, arg1[4]) + x151, x150 := bits.mul_u64(x2, arg1[3]) + x153, x152 := bits.mul_u64(x2, arg1[2]) + x155, x154 := bits.mul_u64(x2, arg1[1]) + x157, x156 := bits.mul_u64(x2, arg1[0]) + x158, x159 := bits.add_u64(x157, x154, u64(0x0)) + x160, x161 := bits.add_u64(x155, x152, u64(fiat.u1(x159))) + x162, x163 := bits.add_u64(x153, x150, u64(fiat.u1(x161))) + x164, x165 := bits.add_u64(x151, x148, u64(fiat.u1(x163))) + x166, x167 := bits.add_u64(x149, x146, u64(fiat.u1(x165))) + x168 := (u64(fiat.u1(x167)) + x147) + x169, x170 := bits.add_u64(x133, x156, u64(0x0)) + x171, x172 := bits.add_u64(x135, x158, u64(fiat.u1(x170))) + x173, x174 := bits.add_u64(x137, x160, u64(fiat.u1(x172))) + x175, x176 := bits.add_u64(x139, x162, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x141, x164, u64(fiat.u1(x176))) + x179, x180 := bits.add_u64(x143, x166, u64(fiat.u1(x178))) + x181, x182 := bits.add_u64(x145, x168, u64(fiat.u1(x180))) + _, x183 := bits.mul_u64(x169, 0x100000001) + x186, x185 := bits.mul_u64(x183, 0xffffffffffffffff) + x188, x187 := bits.mul_u64(x183, 0xffffffffffffffff) + x190, x189 := bits.mul_u64(x183, 0xffffffffffffffff) + x192, x191 := bits.mul_u64(x183, 0xfffffffffffffffe) + x194, x193 := bits.mul_u64(x183, 0xffffffff00000000) + x196, x195 := bits.mul_u64(x183, 0xffffffff) + x197, x198 := bits.add_u64(x196, x193, u64(0x0)) + x199, x200 := bits.add_u64(x194, x191, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x192, x189, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x190, x187, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x188, x185, u64(fiat.u1(x204))) + x207 := (u64(fiat.u1(x206)) + x186) + _, x209 := bits.add_u64(x169, x195, u64(0x0)) + x210, x211 := bits.add_u64(x171, x197, u64(fiat.u1(x209))) + x212, x213 := bits.add_u64(x173, x199, u64(fiat.u1(x211))) + x214, x215 := bits.add_u64(x175, x201, u64(fiat.u1(x213))) + x216, x217 := bits.add_u64(x177, x203, u64(fiat.u1(x215))) + x218, x219 := bits.add_u64(x179, x205, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x181, x207, u64(fiat.u1(x219))) + x222 := (u64(fiat.u1(x221)) + u64(fiat.u1(x182))) + x224, x223 := bits.mul_u64(x3, arg1[5]) + x226, x225 := bits.mul_u64(x3, arg1[4]) + x228, x227 := bits.mul_u64(x3, arg1[3]) + x230, x229 := bits.mul_u64(x3, arg1[2]) + x232, x231 := bits.mul_u64(x3, arg1[1]) + x234, x233 := bits.mul_u64(x3, arg1[0]) + x235, x236 := bits.add_u64(x234, x231, u64(0x0)) + x237, x238 := bits.add_u64(x232, x229, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x230, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x228, x225, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x226, x223, u64(fiat.u1(x242))) + x245 := (u64(fiat.u1(x244)) + x224) + x246, x247 := bits.add_u64(x210, x233, u64(0x0)) + x248, x249 := bits.add_u64(x212, x235, u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x214, x237, u64(fiat.u1(x249))) + x252, x253 := bits.add_u64(x216, x239, u64(fiat.u1(x251))) + x254, x255 := bits.add_u64(x218, x241, u64(fiat.u1(x253))) + x256, x257 := bits.add_u64(x220, x243, u64(fiat.u1(x255))) + x258, x259 := bits.add_u64(x222, x245, u64(fiat.u1(x257))) + _, x260 := bits.mul_u64(x246, 0x100000001) + x263, x262 := bits.mul_u64(x260, 0xffffffffffffffff) + x265, x264 := bits.mul_u64(x260, 0xffffffffffffffff) + x267, x266 := bits.mul_u64(x260, 0xffffffffffffffff) + x269, x268 := bits.mul_u64(x260, 0xfffffffffffffffe) + x271, x270 := bits.mul_u64(x260, 0xffffffff00000000) + x273, x272 := bits.mul_u64(x260, 0xffffffff) + x274, x275 := bits.add_u64(x273, x270, u64(0x0)) + x276, x277 := bits.add_u64(x271, x268, u64(fiat.u1(x275))) + x278, x279 := bits.add_u64(x269, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x267, x264, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x265, x262, u64(fiat.u1(x281))) + x284 := (u64(fiat.u1(x283)) + x263) + _, x286 := bits.add_u64(x246, x272, u64(0x0)) + x287, x288 := bits.add_u64(x248, x274, u64(fiat.u1(x286))) + x289, x290 := bits.add_u64(x250, x276, u64(fiat.u1(x288))) + x291, x292 := bits.add_u64(x252, x278, u64(fiat.u1(x290))) + x293, x294 := bits.add_u64(x254, x280, u64(fiat.u1(x292))) + x295, x296 := bits.add_u64(x256, x282, u64(fiat.u1(x294))) + x297, x298 := bits.add_u64(x258, x284, u64(fiat.u1(x296))) + x299 := (u64(fiat.u1(x298)) + u64(fiat.u1(x259))) + x301, x300 := bits.mul_u64(x4, arg1[5]) + x303, x302 := bits.mul_u64(x4, arg1[4]) + x305, x304 := bits.mul_u64(x4, arg1[3]) + x307, x306 := bits.mul_u64(x4, arg1[2]) + x309, x308 := bits.mul_u64(x4, arg1[1]) + x311, x310 := bits.mul_u64(x4, arg1[0]) + x312, x313 := bits.add_u64(x311, x308, u64(0x0)) + x314, x315 := bits.add_u64(x309, x306, u64(fiat.u1(x313))) + x316, x317 := bits.add_u64(x307, x304, u64(fiat.u1(x315))) + x318, x319 := bits.add_u64(x305, x302, u64(fiat.u1(x317))) + x320, x321 := bits.add_u64(x303, x300, u64(fiat.u1(x319))) + x322 := (u64(fiat.u1(x321)) + x301) + x323, x324 := bits.add_u64(x287, x310, u64(0x0)) + x325, x326 := bits.add_u64(x289, x312, u64(fiat.u1(x324))) + x327, x328 := bits.add_u64(x291, x314, u64(fiat.u1(x326))) + x329, x330 := bits.add_u64(x293, x316, u64(fiat.u1(x328))) + x331, x332 := bits.add_u64(x295, x318, u64(fiat.u1(x330))) + x333, x334 := bits.add_u64(x297, x320, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x299, x322, u64(fiat.u1(x334))) + _, x337 := bits.mul_u64(x323, 0x100000001) + x340, x339 := bits.mul_u64(x337, 0xffffffffffffffff) + x342, x341 := bits.mul_u64(x337, 0xffffffffffffffff) + x344, x343 := bits.mul_u64(x337, 0xffffffffffffffff) + x346, x345 := bits.mul_u64(x337, 0xfffffffffffffffe) + x348, x347 := bits.mul_u64(x337, 0xffffffff00000000) + x350, x349 := bits.mul_u64(x337, 0xffffffff) + x351, x352 := bits.add_u64(x350, x347, u64(0x0)) + x353, x354 := bits.add_u64(x348, x345, u64(fiat.u1(x352))) + x355, x356 := bits.add_u64(x346, x343, u64(fiat.u1(x354))) + x357, x358 := bits.add_u64(x344, x341, u64(fiat.u1(x356))) + x359, x360 := bits.add_u64(x342, x339, u64(fiat.u1(x358))) + x361 := (u64(fiat.u1(x360)) + x340) + _, x363 := bits.add_u64(x323, x349, u64(0x0)) + x364, x365 := bits.add_u64(x325, x351, u64(fiat.u1(x363))) + x366, x367 := bits.add_u64(x327, x353, u64(fiat.u1(x365))) + x368, x369 := bits.add_u64(x329, x355, u64(fiat.u1(x367))) + x370, x371 := bits.add_u64(x331, x357, u64(fiat.u1(x369))) + x372, x373 := bits.add_u64(x333, x359, u64(fiat.u1(x371))) + x374, x375 := bits.add_u64(x335, x361, u64(fiat.u1(x373))) + x376 := (u64(fiat.u1(x375)) + u64(fiat.u1(x336))) + x378, x377 := bits.mul_u64(x5, arg1[5]) + x380, x379 := bits.mul_u64(x5, arg1[4]) + x382, x381 := bits.mul_u64(x5, arg1[3]) + x384, x383 := bits.mul_u64(x5, arg1[2]) + x386, x385 := bits.mul_u64(x5, arg1[1]) + x388, x387 := bits.mul_u64(x5, arg1[0]) + x389, x390 := bits.add_u64(x388, x385, u64(0x0)) + x391, x392 := bits.add_u64(x386, x383, u64(fiat.u1(x390))) + x393, x394 := bits.add_u64(x384, x381, u64(fiat.u1(x392))) + x395, x396 := bits.add_u64(x382, x379, u64(fiat.u1(x394))) + x397, x398 := bits.add_u64(x380, x377, u64(fiat.u1(x396))) + x399 := (u64(fiat.u1(x398)) + x378) + x400, x401 := bits.add_u64(x364, x387, u64(0x0)) + x402, x403 := bits.add_u64(x366, x389, u64(fiat.u1(x401))) + x404, x405 := bits.add_u64(x368, x391, u64(fiat.u1(x403))) + x406, x407 := bits.add_u64(x370, x393, u64(fiat.u1(x405))) + x408, x409 := bits.add_u64(x372, x395, u64(fiat.u1(x407))) + x410, x411 := bits.add_u64(x374, x397, u64(fiat.u1(x409))) + x412, x413 := bits.add_u64(x376, x399, u64(fiat.u1(x411))) + _, x414 := bits.mul_u64(x400, 0x100000001) + x417, x416 := bits.mul_u64(x414, 0xffffffffffffffff) + x419, x418 := bits.mul_u64(x414, 0xffffffffffffffff) + x421, x420 := bits.mul_u64(x414, 0xffffffffffffffff) + x423, x422 := bits.mul_u64(x414, 0xfffffffffffffffe) + x425, x424 := bits.mul_u64(x414, 0xffffffff00000000) + x427, x426 := bits.mul_u64(x414, 0xffffffff) + x428, x429 := bits.add_u64(x427, x424, u64(0x0)) + x430, x431 := bits.add_u64(x425, x422, u64(fiat.u1(x429))) + x432, x433 := bits.add_u64(x423, x420, u64(fiat.u1(x431))) + x434, x435 := bits.add_u64(x421, x418, u64(fiat.u1(x433))) + x436, x437 := bits.add_u64(x419, x416, u64(fiat.u1(x435))) + x438 := (u64(fiat.u1(x437)) + x417) + _, x440 := bits.add_u64(x400, x426, u64(0x0)) + x441, x442 := bits.add_u64(x402, x428, u64(fiat.u1(x440))) + x443, x444 := bits.add_u64(x404, x430, u64(fiat.u1(x442))) + x445, x446 := bits.add_u64(x406, x432, u64(fiat.u1(x444))) + x447, x448 := bits.add_u64(x408, x434, u64(fiat.u1(x446))) + x449, x450 := bits.add_u64(x410, x436, u64(fiat.u1(x448))) + x451, x452 := bits.add_u64(x412, x438, u64(fiat.u1(x450))) + x453 := (u64(fiat.u1(x452)) + u64(fiat.u1(x413))) + x454, x455 := bits.sub_u64(x441, 0xffffffff, u64(0x0)) + x456, x457 := bits.sub_u64(x443, 0xffffffff00000000, u64(fiat.u1(x455))) + x458, x459 := bits.sub_u64(x445, 0xfffffffffffffffe, u64(fiat.u1(x457))) + x460, x461 := bits.sub_u64(x447, 0xffffffffffffffff, u64(fiat.u1(x459))) + x462, x463 := bits.sub_u64(x449, 0xffffffffffffffff, u64(fiat.u1(x461))) + x464, x465 := bits.sub_u64(x451, 0xffffffffffffffff, u64(fiat.u1(x463))) + _, x467 := bits.sub_u64(x453, u64(0x0), u64(fiat.u1(x465))) + x468 := fiat.cmovznz_u64(fiat.u1(x467), x454, x441) + x469 := fiat.cmovznz_u64(fiat.u1(x467), x456, x443) + x470 := fiat.cmovznz_u64(fiat.u1(x467), x458, x445) + x471 := fiat.cmovznz_u64(fiat.u1(x467), x460, x447) + x472 := fiat.cmovznz_u64(fiat.u1(x467), x462, x449) + x473 := fiat.cmovznz_u64(fiat.u1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.add_u64(arg1[4], arg2[4], u64(fiat.u1(x8))) + x11, x12 := bits.add_u64(arg1[5], arg2[5], u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x1, 0xffffffff, u64(0x0)) + x15, x16 := bits.sub_u64(x3, 0xffffffff00000000, u64(fiat.u1(x14))) + x17, x18 := bits.sub_u64(x5, 0xfffffffffffffffe, u64(fiat.u1(x16))) + x19, x20 := bits.sub_u64(x7, 0xffffffffffffffff, u64(fiat.u1(x18))) + x21, x22 := bits.sub_u64(x9, 0xffffffffffffffff, u64(fiat.u1(x20))) + x23, x24 := bits.sub_u64(x11, 0xffffffffffffffff, u64(fiat.u1(x22))) + _, x26 := bits.sub_u64(u64(fiat.u1(x12)), u64(0x0), u64(fiat.u1(x24))) + x27 := fiat.cmovznz_u64(fiat.u1(x26), x13, x1) + x28 := fiat.cmovznz_u64(fiat.u1(x26), x15, x3) + x29 := fiat.cmovznz_u64(fiat.u1(x26), x17, x5) + x30 := fiat.cmovznz_u64(fiat.u1(x26), x19, x7) + x31 := fiat.cmovznz_u64(fiat.u1(x26), x21, x9) + x32 := fiat.cmovznz_u64(fiat.u1(x26), x23, x11) + out1[0] = x27 + out1[1] = x28 + out1[2] = x29 + out1[3] = x30 + out1[4] = x31 + out1[5] = x32 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(arg1[4], arg2[4], u64(fiat.u1(x8))) + x11, x12 := bits.sub_u64(arg1[5], arg2[5], u64(fiat.u1(x10))) + x13 := fiat.cmovznz_u64(fiat.u1(x12), u64(0x0), 0xffffffffffffffff) + x14, x15 := bits.add_u64(x1, (x13 & 0xffffffff), u64(0x0)) + x16, x17 := bits.add_u64(x3, (x13 & 0xffffffff00000000), u64(fiat.u1(x15))) + x18, x19 := bits.add_u64(x5, (x13 & 0xfffffffffffffffe), u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x7, x13, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x13, u64(fiat.u1(x21))) + x24, _ := bits.add_u64(x11, x13, u64(fiat.u1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(u64(0x0), arg1[4], u64(fiat.u1(x8))) + x11, x12 := bits.sub_u64(u64(0x0), arg1[5], u64(fiat.u1(x10))) + x13 := fiat.cmovznz_u64(fiat.u1(x12), u64(0x0), 0xffffffffffffffff) + x14, x15 := bits.add_u64(x1, (x13 & 0xffffffff), u64(0x0)) + x16, x17 := bits.add_u64(x3, (x13 & 0xffffffff00000000), u64(fiat.u1(x15))) + x18, x19 := bits.add_u64(x5, (x13 & 0xfffffffffffffffe), u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x7, x13, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x13, u64(fiat.u1(x21))) + x24, _ := bits.add_u64(x11, x13, u64(fiat.u1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0xffffffff00000001 + out1[1] = 0xffffffff + out1[2] = 0x1 + out1[3] = 0x0 + out1[4] = 0x0 + out1[5] = 0x0 +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return (arg1[0] | (arg1[1] | (arg1[2] | (arg1[3] | (arg1[4] | arg1[5]))))) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + x5 := fiat.cmovznz_u64(fiat.u1(arg2), out1[4], arg1[4]) + x6 := fiat.cmovznz_u64(fiat.u1(arg2), out1[5], arg1[5]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + _, x2 := bits.mul_u64(x1, 0x100000001) + x5, x4 := bits.mul_u64(x2, 0xffffffffffffffff) + x7, x6 := bits.mul_u64(x2, 0xffffffffffffffff) + x9, x8 := bits.mul_u64(x2, 0xffffffffffffffff) + x11, x10 := bits.mul_u64(x2, 0xfffffffffffffffe) + x13, x12 := bits.mul_u64(x2, 0xffffffff00000000) + x15, x14 := bits.mul_u64(x2, 0xffffffff) + x16, x17 := bits.add_u64(x15, x12, u64(0x0)) + x18, x19 := bits.add_u64(x13, x10, u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x11, x8, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x6, u64(fiat.u1(x21))) + x24, x25 := bits.add_u64(x7, x4, u64(fiat.u1(x23))) + _, x27 := bits.add_u64(x1, x14, u64(0x0)) + x28, x29 := bits.add_u64(u64(0x0), x16, u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(u64(0x0), x18, u64(fiat.u1(x29))) + x32, x33 := bits.add_u64(u64(0x0), x20, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(u64(0x0), x22, u64(fiat.u1(x33))) + x36, x37 := bits.add_u64(u64(0x0), x24, u64(fiat.u1(x35))) + x38, x39 := bits.add_u64(u64(0x0), (u64(fiat.u1(x25)) + x5), u64(fiat.u1(x37))) + x40, x41 := bits.add_u64(x28, arg1[1], u64(0x0)) + x42, x43 := bits.add_u64(x30, u64(0x0), u64(fiat.u1(x41))) + x44, x45 := bits.add_u64(x32, u64(0x0), u64(fiat.u1(x43))) + x46, x47 := bits.add_u64(x34, u64(0x0), u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x36, u64(0x0), u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x38, u64(0x0), u64(fiat.u1(x49))) + _, x52 := bits.mul_u64(x40, 0x100000001) + x55, x54 := bits.mul_u64(x52, 0xffffffffffffffff) + x57, x56 := bits.mul_u64(x52, 0xffffffffffffffff) + x59, x58 := bits.mul_u64(x52, 0xffffffffffffffff) + x61, x60 := bits.mul_u64(x52, 0xfffffffffffffffe) + x63, x62 := bits.mul_u64(x52, 0xffffffff00000000) + x65, x64 := bits.mul_u64(x52, 0xffffffff) + x66, x67 := bits.add_u64(x65, x62, u64(0x0)) + x68, x69 := bits.add_u64(x63, x60, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(x61, x58, u64(fiat.u1(x69))) + x72, x73 := bits.add_u64(x59, x56, u64(fiat.u1(x71))) + x74, x75 := bits.add_u64(x57, x54, u64(fiat.u1(x73))) + _, x77 := bits.add_u64(x40, x64, u64(0x0)) + x78, x79 := bits.add_u64(x42, x66, u64(fiat.u1(x77))) + x80, x81 := bits.add_u64(x44, x68, u64(fiat.u1(x79))) + x82, x83 := bits.add_u64(x46, x70, u64(fiat.u1(x81))) + x84, x85 := bits.add_u64(x48, x72, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x50, x74, u64(fiat.u1(x85))) + x88, x89 := bits.add_u64((u64(fiat.u1(x51)) + u64(fiat.u1(x39))), (u64(fiat.u1(x75)) + x55), u64(fiat.u1(x87))) + x90, x91 := bits.add_u64(x78, arg1[2], u64(0x0)) + x92, x93 := bits.add_u64(x80, u64(0x0), u64(fiat.u1(x91))) + x94, x95 := bits.add_u64(x82, u64(0x0), u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x84, u64(0x0), u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x86, u64(0x0), u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x88, u64(0x0), u64(fiat.u1(x99))) + _, x102 := bits.mul_u64(x90, 0x100000001) + x105, x104 := bits.mul_u64(x102, 0xffffffffffffffff) + x107, x106 := bits.mul_u64(x102, 0xffffffffffffffff) + x109, x108 := bits.mul_u64(x102, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x102, 0xfffffffffffffffe) + x113, x112 := bits.mul_u64(x102, 0xffffffff00000000) + x115, x114 := bits.mul_u64(x102, 0xffffffff) + x116, x117 := bits.add_u64(x115, x112, u64(0x0)) + x118, x119 := bits.add_u64(x113, x110, u64(fiat.u1(x117))) + x120, x121 := bits.add_u64(x111, x108, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x109, x106, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x107, x104, u64(fiat.u1(x123))) + _, x127 := bits.add_u64(x90, x114, u64(0x0)) + x128, x129 := bits.add_u64(x92, x116, u64(fiat.u1(x127))) + x130, x131 := bits.add_u64(x94, x118, u64(fiat.u1(x129))) + x132, x133 := bits.add_u64(x96, x120, u64(fiat.u1(x131))) + x134, x135 := bits.add_u64(x98, x122, u64(fiat.u1(x133))) + x136, x137 := bits.add_u64(x100, x124, u64(fiat.u1(x135))) + x138, x139 := bits.add_u64((u64(fiat.u1(x101)) + u64(fiat.u1(x89))), (u64(fiat.u1(x125)) + x105), u64(fiat.u1(x137))) + x140, x141 := bits.add_u64(x128, arg1[3], u64(0x0)) + x142, x143 := bits.add_u64(x130, u64(0x0), u64(fiat.u1(x141))) + x144, x145 := bits.add_u64(x132, u64(0x0), u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x134, u64(0x0), u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x136, u64(0x0), u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x138, u64(0x0), u64(fiat.u1(x149))) + _, x152 := bits.mul_u64(x140, 0x100000001) + x155, x154 := bits.mul_u64(x152, 0xffffffffffffffff) + x157, x156 := bits.mul_u64(x152, 0xffffffffffffffff) + x159, x158 := bits.mul_u64(x152, 0xffffffffffffffff) + x161, x160 := bits.mul_u64(x152, 0xfffffffffffffffe) + x163, x162 := bits.mul_u64(x152, 0xffffffff00000000) + x165, x164 := bits.mul_u64(x152, 0xffffffff) + x166, x167 := bits.add_u64(x165, x162, u64(0x0)) + x168, x169 := bits.add_u64(x163, x160, u64(fiat.u1(x167))) + x170, x171 := bits.add_u64(x161, x158, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x159, x156, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x157, x154, u64(fiat.u1(x173))) + _, x177 := bits.add_u64(x140, x164, u64(0x0)) + x178, x179 := bits.add_u64(x142, x166, u64(fiat.u1(x177))) + x180, x181 := bits.add_u64(x144, x168, u64(fiat.u1(x179))) + x182, x183 := bits.add_u64(x146, x170, u64(fiat.u1(x181))) + x184, x185 := bits.add_u64(x148, x172, u64(fiat.u1(x183))) + x186, x187 := bits.add_u64(x150, x174, u64(fiat.u1(x185))) + x188, x189 := bits.add_u64((u64(fiat.u1(x151)) + u64(fiat.u1(x139))), (u64(fiat.u1(x175)) + x155), u64(fiat.u1(x187))) + x190, x191 := bits.add_u64(x178, arg1[4], u64(0x0)) + x192, x193 := bits.add_u64(x180, u64(0x0), u64(fiat.u1(x191))) + x194, x195 := bits.add_u64(x182, u64(0x0), u64(fiat.u1(x193))) + x196, x197 := bits.add_u64(x184, u64(0x0), u64(fiat.u1(x195))) + x198, x199 := bits.add_u64(x186, u64(0x0), u64(fiat.u1(x197))) + x200, x201 := bits.add_u64(x188, u64(0x0), u64(fiat.u1(x199))) + _, x202 := bits.mul_u64(x190, 0x100000001) + x205, x204 := bits.mul_u64(x202, 0xffffffffffffffff) + x207, x206 := bits.mul_u64(x202, 0xffffffffffffffff) + x209, x208 := bits.mul_u64(x202, 0xffffffffffffffff) + x211, x210 := bits.mul_u64(x202, 0xfffffffffffffffe) + x213, x212 := bits.mul_u64(x202, 0xffffffff00000000) + x215, x214 := bits.mul_u64(x202, 0xffffffff) + x216, x217 := bits.add_u64(x215, x212, u64(0x0)) + x218, x219 := bits.add_u64(x213, x210, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x211, x208, u64(fiat.u1(x219))) + x222, x223 := bits.add_u64(x209, x206, u64(fiat.u1(x221))) + x224, x225 := bits.add_u64(x207, x204, u64(fiat.u1(x223))) + _, x227 := bits.add_u64(x190, x214, u64(0x0)) + x228, x229 := bits.add_u64(x192, x216, u64(fiat.u1(x227))) + x230, x231 := bits.add_u64(x194, x218, u64(fiat.u1(x229))) + x232, x233 := bits.add_u64(x196, x220, u64(fiat.u1(x231))) + x234, x235 := bits.add_u64(x198, x222, u64(fiat.u1(x233))) + x236, x237 := bits.add_u64(x200, x224, u64(fiat.u1(x235))) + x238, x239 := bits.add_u64((u64(fiat.u1(x201)) + u64(fiat.u1(x189))), (u64(fiat.u1(x225)) + x205), u64(fiat.u1(x237))) + x240, x241 := bits.add_u64(x228, arg1[5], u64(0x0)) + x242, x243 := bits.add_u64(x230, u64(0x0), u64(fiat.u1(x241))) + x244, x245 := bits.add_u64(x232, u64(0x0), u64(fiat.u1(x243))) + x246, x247 := bits.add_u64(x234, u64(0x0), u64(fiat.u1(x245))) + x248, x249 := bits.add_u64(x236, u64(0x0), u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x238, u64(0x0), u64(fiat.u1(x249))) + _, x252 := bits.mul_u64(x240, 0x100000001) + x255, x254 := bits.mul_u64(x252, 0xffffffffffffffff) + x257, x256 := bits.mul_u64(x252, 0xffffffffffffffff) + x259, x258 := bits.mul_u64(x252, 0xffffffffffffffff) + x261, x260 := bits.mul_u64(x252, 0xfffffffffffffffe) + x263, x262 := bits.mul_u64(x252, 0xffffffff00000000) + x265, x264 := bits.mul_u64(x252, 0xffffffff) + x266, x267 := bits.add_u64(x265, x262, u64(0x0)) + x268, x269 := bits.add_u64(x263, x260, u64(fiat.u1(x267))) + x270, x271 := bits.add_u64(x261, x258, u64(fiat.u1(x269))) + x272, x273 := bits.add_u64(x259, x256, u64(fiat.u1(x271))) + x274, x275 := bits.add_u64(x257, x254, u64(fiat.u1(x273))) + _, x277 := bits.add_u64(x240, x264, u64(0x0)) + x278, x279 := bits.add_u64(x242, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x244, x268, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x246, x270, u64(fiat.u1(x281))) + x284, x285 := bits.add_u64(x248, x272, u64(fiat.u1(x283))) + x286, x287 := bits.add_u64(x250, x274, u64(fiat.u1(x285))) + x288, x289 := bits.add_u64((u64(fiat.u1(x251)) + u64(fiat.u1(x239))), (u64(fiat.u1(x275)) + x255), u64(fiat.u1(x287))) + x290, x291 := bits.sub_u64(x278, 0xffffffff, u64(0x0)) + x292, x293 := bits.sub_u64(x280, 0xffffffff00000000, u64(fiat.u1(x291))) + x294, x295 := bits.sub_u64(x282, 0xfffffffffffffffe, u64(fiat.u1(x293))) + x296, x297 := bits.sub_u64(x284, 0xffffffffffffffff, u64(fiat.u1(x295))) + x298, x299 := bits.sub_u64(x286, 0xffffffffffffffff, u64(fiat.u1(x297))) + x300, x301 := bits.sub_u64(x288, 0xffffffffffffffff, u64(fiat.u1(x299))) + _, x303 := bits.sub_u64(u64(fiat.u1(x289)), u64(0x0), u64(fiat.u1(x301))) + x304 := fiat.cmovznz_u64(fiat.u1(x303), x290, x278) + x305 := fiat.cmovznz_u64(fiat.u1(x303), x292, x280) + x306 := fiat.cmovznz_u64(fiat.u1(x303), x294, x282) + x307 := fiat.cmovznz_u64(fiat.u1(x303), x296, x284) + x308 := fiat.cmovznz_u64(fiat.u1(x303), x298, x286) + x309 := fiat.cmovznz_u64(fiat.u1(x303), x300, x288) + out1[0] = x304 + out1[1] = x305 + out1[2] = x306 + out1[3] = x307 + out1[4] = x308 + out1[5] = x309 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, 0x200000000) + x10, x9 := bits.mul_u64(x6, 0xfffffffe00000000) + x12, x11 := bits.mul_u64(x6, 0x200000000) + x14, x13 := bits.mul_u64(x6, 0xfffffffe00000001) + x15, x16 := bits.add_u64(x14, x11, u64(0x0)) + x17, x18 := bits.add_u64(x12, x9, u64(fiat.u1(x16))) + x19, x20 := bits.add_u64(x10, x7, u64(fiat.u1(x18))) + x21, x22 := bits.add_u64(x8, x6, u64(fiat.u1(x20))) + _, x23 := bits.mul_u64(x13, 0x100000001) + x26, x25 := bits.mul_u64(x23, 0xffffffffffffffff) + x28, x27 := bits.mul_u64(x23, 0xffffffffffffffff) + x30, x29 := bits.mul_u64(x23, 0xffffffffffffffff) + x32, x31 := bits.mul_u64(x23, 0xfffffffffffffffe) + x34, x33 := bits.mul_u64(x23, 0xffffffff00000000) + x36, x35 := bits.mul_u64(x23, 0xffffffff) + x37, x38 := bits.add_u64(x36, x33, u64(0x0)) + x39, x40 := bits.add_u64(x34, x31, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x32, x29, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64(x30, x27, u64(fiat.u1(x42))) + x45, x46 := bits.add_u64(x28, x25, u64(fiat.u1(x44))) + _, x48 := bits.add_u64(x13, x35, u64(0x0)) + x49, x50 := bits.add_u64(x15, x37, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x17, x39, u64(fiat.u1(x50))) + x53, x54 := bits.add_u64(x19, x41, u64(fiat.u1(x52))) + x55, x56 := bits.add_u64(x21, x43, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(u64(fiat.u1(x22)), x45, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(u64(0x0), (u64(fiat.u1(x46)) + x26), u64(fiat.u1(x58))) + x62, x61 := bits.mul_u64(x1, 0x200000000) + x64, x63 := bits.mul_u64(x1, 0xfffffffe00000000) + x66, x65 := bits.mul_u64(x1, 0x200000000) + x68, x67 := bits.mul_u64(x1, 0xfffffffe00000001) + x69, x70 := bits.add_u64(x68, x65, u64(0x0)) + x71, x72 := bits.add_u64(x66, x63, u64(fiat.u1(x70))) + x73, x74 := bits.add_u64(x64, x61, u64(fiat.u1(x72))) + x75, x76 := bits.add_u64(x62, x1, u64(fiat.u1(x74))) + x77, x78 := bits.add_u64(x49, x67, u64(0x0)) + x79, x80 := bits.add_u64(x51, x69, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x53, x71, u64(fiat.u1(x80))) + x83, x84 := bits.add_u64(x55, x73, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x57, x75, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x59, u64(fiat.u1(x76)), u64(fiat.u1(x86))) + _, x89 := bits.mul_u64(x77, 0x100000001) + x92, x91 := bits.mul_u64(x89, 0xffffffffffffffff) + x94, x93 := bits.mul_u64(x89, 0xffffffffffffffff) + x96, x95 := bits.mul_u64(x89, 0xffffffffffffffff) + x98, x97 := bits.mul_u64(x89, 0xfffffffffffffffe) + x100, x99 := bits.mul_u64(x89, 0xffffffff00000000) + x102, x101 := bits.mul_u64(x89, 0xffffffff) + x103, x104 := bits.add_u64(x102, x99, u64(0x0)) + x105, x106 := bits.add_u64(x100, x97, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x98, x95, u64(fiat.u1(x106))) + x109, x110 := bits.add_u64(x96, x93, u64(fiat.u1(x108))) + x111, x112 := bits.add_u64(x94, x91, u64(fiat.u1(x110))) + _, x114 := bits.add_u64(x77, x101, u64(0x0)) + x115, x116 := bits.add_u64(x79, x103, u64(fiat.u1(x114))) + x117, x118 := bits.add_u64(x81, x105, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x83, x107, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x85, x109, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x87, x111, u64(fiat.u1(x122))) + x125, x126 := bits.add_u64((u64(fiat.u1(x88)) + u64(fiat.u1(x60))), (u64(fiat.u1(x112)) + x92), u64(fiat.u1(x124))) + x128, x127 := bits.mul_u64(x2, 0x200000000) + x130, x129 := bits.mul_u64(x2, 0xfffffffe00000000) + x132, x131 := bits.mul_u64(x2, 0x200000000) + x134, x133 := bits.mul_u64(x2, 0xfffffffe00000001) + x135, x136 := bits.add_u64(x134, x131, u64(0x0)) + x137, x138 := bits.add_u64(x132, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x130, x127, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x128, x2, u64(fiat.u1(x140))) + x143, x144 := bits.add_u64(x115, x133, u64(0x0)) + x145, x146 := bits.add_u64(x117, x135, u64(fiat.u1(x144))) + x147, x148 := bits.add_u64(x119, x137, u64(fiat.u1(x146))) + x149, x150 := bits.add_u64(x121, x139, u64(fiat.u1(x148))) + x151, x152 := bits.add_u64(x123, x141, u64(fiat.u1(x150))) + x153, x154 := bits.add_u64(x125, u64(fiat.u1(x142)), u64(fiat.u1(x152))) + _, x155 := bits.mul_u64(x143, 0x100000001) + x158, x157 := bits.mul_u64(x155, 0xffffffffffffffff) + x160, x159 := bits.mul_u64(x155, 0xffffffffffffffff) + x162, x161 := bits.mul_u64(x155, 0xffffffffffffffff) + x164, x163 := bits.mul_u64(x155, 0xfffffffffffffffe) + x166, x165 := bits.mul_u64(x155, 0xffffffff00000000) + x168, x167 := bits.mul_u64(x155, 0xffffffff) + x169, x170 := bits.add_u64(x168, x165, u64(0x0)) + x171, x172 := bits.add_u64(x166, x163, u64(fiat.u1(x170))) + x173, x174 := bits.add_u64(x164, x161, u64(fiat.u1(x172))) + x175, x176 := bits.add_u64(x162, x159, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x160, x157, u64(fiat.u1(x176))) + _, x180 := bits.add_u64(x143, x167, u64(0x0)) + x181, x182 := bits.add_u64(x145, x169, u64(fiat.u1(x180))) + x183, x184 := bits.add_u64(x147, x171, u64(fiat.u1(x182))) + x185, x186 := bits.add_u64(x149, x173, u64(fiat.u1(x184))) + x187, x188 := bits.add_u64(x151, x175, u64(fiat.u1(x186))) + x189, x190 := bits.add_u64(x153, x177, u64(fiat.u1(x188))) + x191, x192 := bits.add_u64((u64(fiat.u1(x154)) + u64(fiat.u1(x126))), (u64(fiat.u1(x178)) + x158), u64(fiat.u1(x190))) + x194, x193 := bits.mul_u64(x3, 0x200000000) + x196, x195 := bits.mul_u64(x3, 0xfffffffe00000000) + x198, x197 := bits.mul_u64(x3, 0x200000000) + x200, x199 := bits.mul_u64(x3, 0xfffffffe00000001) + x201, x202 := bits.add_u64(x200, x197, u64(0x0)) + x203, x204 := bits.add_u64(x198, x195, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x196, x193, u64(fiat.u1(x204))) + x207, x208 := bits.add_u64(x194, x3, u64(fiat.u1(x206))) + x209, x210 := bits.add_u64(x181, x199, u64(0x0)) + x211, x212 := bits.add_u64(x183, x201, u64(fiat.u1(x210))) + x213, x214 := bits.add_u64(x185, x203, u64(fiat.u1(x212))) + x215, x216 := bits.add_u64(x187, x205, u64(fiat.u1(x214))) + x217, x218 := bits.add_u64(x189, x207, u64(fiat.u1(x216))) + x219, x220 := bits.add_u64(x191, u64(fiat.u1(x208)), u64(fiat.u1(x218))) + _, x221 := bits.mul_u64(x209, 0x100000001) + x224, x223 := bits.mul_u64(x221, 0xffffffffffffffff) + x226, x225 := bits.mul_u64(x221, 0xffffffffffffffff) + x228, x227 := bits.mul_u64(x221, 0xffffffffffffffff) + x230, x229 := bits.mul_u64(x221, 0xfffffffffffffffe) + x232, x231 := bits.mul_u64(x221, 0xffffffff00000000) + x234, x233 := bits.mul_u64(x221, 0xffffffff) + x235, x236 := bits.add_u64(x234, x231, u64(0x0)) + x237, x238 := bits.add_u64(x232, x229, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x230, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x228, x225, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x226, x223, u64(fiat.u1(x242))) + _, x246 := bits.add_u64(x209, x233, u64(0x0)) + x247, x248 := bits.add_u64(x211, x235, u64(fiat.u1(x246))) + x249, x250 := bits.add_u64(x213, x237, u64(fiat.u1(x248))) + x251, x252 := bits.add_u64(x215, x239, u64(fiat.u1(x250))) + x253, x254 := bits.add_u64(x217, x241, u64(fiat.u1(x252))) + x255, x256 := bits.add_u64(x219, x243, u64(fiat.u1(x254))) + x257, x258 := bits.add_u64((u64(fiat.u1(x220)) + u64(fiat.u1(x192))), (u64(fiat.u1(x244)) + x224), u64(fiat.u1(x256))) + x260, x259 := bits.mul_u64(x4, 0x200000000) + x262, x261 := bits.mul_u64(x4, 0xfffffffe00000000) + x264, x263 := bits.mul_u64(x4, 0x200000000) + x266, x265 := bits.mul_u64(x4, 0xfffffffe00000001) + x267, x268 := bits.add_u64(x266, x263, u64(0x0)) + x269, x270 := bits.add_u64(x264, x261, u64(fiat.u1(x268))) + x271, x272 := bits.add_u64(x262, x259, u64(fiat.u1(x270))) + x273, x274 := bits.add_u64(x260, x4, u64(fiat.u1(x272))) + x275, x276 := bits.add_u64(x247, x265, u64(0x0)) + x277, x278 := bits.add_u64(x249, x267, u64(fiat.u1(x276))) + x279, x280 := bits.add_u64(x251, x269, u64(fiat.u1(x278))) + x281, x282 := bits.add_u64(x253, x271, u64(fiat.u1(x280))) + x283, x284 := bits.add_u64(x255, x273, u64(fiat.u1(x282))) + x285, x286 := bits.add_u64(x257, u64(fiat.u1(x274)), u64(fiat.u1(x284))) + _, x287 := bits.mul_u64(x275, 0x100000001) + x290, x289 := bits.mul_u64(x287, 0xffffffffffffffff) + x292, x291 := bits.mul_u64(x287, 0xffffffffffffffff) + x294, x293 := bits.mul_u64(x287, 0xffffffffffffffff) + x296, x295 := bits.mul_u64(x287, 0xfffffffffffffffe) + x298, x297 := bits.mul_u64(x287, 0xffffffff00000000) + x300, x299 := bits.mul_u64(x287, 0xffffffff) + x301, x302 := bits.add_u64(x300, x297, u64(0x0)) + x303, x304 := bits.add_u64(x298, x295, u64(fiat.u1(x302))) + x305, x306 := bits.add_u64(x296, x293, u64(fiat.u1(x304))) + x307, x308 := bits.add_u64(x294, x291, u64(fiat.u1(x306))) + x309, x310 := bits.add_u64(x292, x289, u64(fiat.u1(x308))) + _, x312 := bits.add_u64(x275, x299, u64(0x0)) + x313, x314 := bits.add_u64(x277, x301, u64(fiat.u1(x312))) + x315, x316 := bits.add_u64(x279, x303, u64(fiat.u1(x314))) + x317, x318 := bits.add_u64(x281, x305, u64(fiat.u1(x316))) + x319, x320 := bits.add_u64(x283, x307, u64(fiat.u1(x318))) + x321, x322 := bits.add_u64(x285, x309, u64(fiat.u1(x320))) + x323, x324 := bits.add_u64((u64(fiat.u1(x286)) + u64(fiat.u1(x258))), (u64(fiat.u1(x310)) + x290), u64(fiat.u1(x322))) + x326, x325 := bits.mul_u64(x5, 0x200000000) + x328, x327 := bits.mul_u64(x5, 0xfffffffe00000000) + x330, x329 := bits.mul_u64(x5, 0x200000000) + x332, x331 := bits.mul_u64(x5, 0xfffffffe00000001) + x333, x334 := bits.add_u64(x332, x329, u64(0x0)) + x335, x336 := bits.add_u64(x330, x327, u64(fiat.u1(x334))) + x337, x338 := bits.add_u64(x328, x325, u64(fiat.u1(x336))) + x339, x340 := bits.add_u64(x326, x5, u64(fiat.u1(x338))) + x341, x342 := bits.add_u64(x313, x331, u64(0x0)) + x343, x344 := bits.add_u64(x315, x333, u64(fiat.u1(x342))) + x345, x346 := bits.add_u64(x317, x335, u64(fiat.u1(x344))) + x347, x348 := bits.add_u64(x319, x337, u64(fiat.u1(x346))) + x349, x350 := bits.add_u64(x321, x339, u64(fiat.u1(x348))) + x351, x352 := bits.add_u64(x323, u64(fiat.u1(x340)), u64(fiat.u1(x350))) + _, x353 := bits.mul_u64(x341, 0x100000001) + x356, x355 := bits.mul_u64(x353, 0xffffffffffffffff) + x358, x357 := bits.mul_u64(x353, 0xffffffffffffffff) + x360, x359 := bits.mul_u64(x353, 0xffffffffffffffff) + x362, x361 := bits.mul_u64(x353, 0xfffffffffffffffe) + x364, x363 := bits.mul_u64(x353, 0xffffffff00000000) + x366, x365 := bits.mul_u64(x353, 0xffffffff) + x367, x368 := bits.add_u64(x366, x363, u64(0x0)) + x369, x370 := bits.add_u64(x364, x361, u64(fiat.u1(x368))) + x371, x372 := bits.add_u64(x362, x359, u64(fiat.u1(x370))) + x373, x374 := bits.add_u64(x360, x357, u64(fiat.u1(x372))) + x375, x376 := bits.add_u64(x358, x355, u64(fiat.u1(x374))) + _, x378 := bits.add_u64(x341, x365, u64(0x0)) + x379, x380 := bits.add_u64(x343, x367, u64(fiat.u1(x378))) + x381, x382 := bits.add_u64(x345, x369, u64(fiat.u1(x380))) + x383, x384 := bits.add_u64(x347, x371, u64(fiat.u1(x382))) + x385, x386 := bits.add_u64(x349, x373, u64(fiat.u1(x384))) + x387, x388 := bits.add_u64(x351, x375, u64(fiat.u1(x386))) + x389, x390 := bits.add_u64((u64(fiat.u1(x352)) + u64(fiat.u1(x324))), (u64(fiat.u1(x376)) + x356), u64(fiat.u1(x388))) + x391, x392 := bits.sub_u64(x379, 0xffffffff, u64(0x0)) + x393, x394 := bits.sub_u64(x381, 0xffffffff00000000, u64(fiat.u1(x392))) + x395, x396 := bits.sub_u64(x383, 0xfffffffffffffffe, u64(fiat.u1(x394))) + x397, x398 := bits.sub_u64(x385, 0xffffffffffffffff, u64(fiat.u1(x396))) + x399, x400 := bits.sub_u64(x387, 0xffffffffffffffff, u64(fiat.u1(x398))) + x401, x402 := bits.sub_u64(x389, 0xffffffffffffffff, u64(fiat.u1(x400))) + _, x404 := bits.sub_u64(u64(fiat.u1(x390)), u64(0x0), u64(fiat.u1(x402))) + x405 := fiat.cmovznz_u64(fiat.u1(x404), x391, x379) + x406 := fiat.cmovznz_u64(fiat.u1(x404), x393, x381) + x407 := fiat.cmovznz_u64(fiat.u1(x404), x395, x383) + x408 := fiat.cmovznz_u64(fiat.u1(x404), x397, x385) + x409 := fiat.cmovznz_u64(fiat.u1(x404), x399, x387) + x410 := fiat.cmovznz_u64(fiat.u1(x404), x401, x389) + out1[0] = x405 + out1[1] = x406 + out1[2] = x407 + out1[3] = x408 + out1[4] = x409 + out1[5] = x410 +} diff --git a/core/crypto/_fiat/field_poly1305/field.odin b/core/crypto/_fiat/field_poly1305/field.odin index caaece98e..244ddceb8 100644 --- a/core/crypto/_fiat/field_poly1305/field.odin +++ b/core/crypto/_fiat/field_poly1305/field.odin @@ -1,7 +1,7 @@ package field_poly1305 +import "core:crypto" import "core:encoding/endian" -import "core:mem" fe_relax_cast :: #force_inline proc "contextless" ( arg1: ^Tight_Field_Element, @@ -57,7 +57,7 @@ fe_from_u64s :: proc "contextless" (out1: ^Tight_Field_Element, lo, hi: u64) { _fe_from_bytes(out1, &tmp) // This routine is only used to deserialize `r` which is confidential. - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tmp, size_of(tmp)) } fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) { diff --git a/core/crypto/_fiat/field_scalar25519/field.odin b/core/crypto/_fiat/field_scalar25519/field.odin index 933637c54..181a6ce8d 100644 --- a/core/crypto/_fiat/field_scalar25519/field.odin +++ b/core/crypto/_fiat/field_scalar25519/field.odin @@ -1,8 +1,9 @@ package field_scalar25519 +import "core:crypto" +import subtle "core:crypto/_subtle" import "core:encoding/endian" import "core:math/bits" -import "core:mem" @(private, rodata) _TWO_168 := Montgomery_Domain_Field_Element { @@ -20,7 +21,7 @@ _TWO_336 := Montgomery_Domain_Field_Element { } fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { - mem.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) + crypto.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) } fe_from_bytes :: proc "contextless" ( @@ -34,7 +35,7 @@ fe_from_bytes :: proc "contextless" ( endian.unchecked_get_u64le(arg1[16:]), endian.unchecked_get_u64le(arg1[24:]), } - defer mem.zero_explicit(&tmp, size_of(tmp)) + defer crypto.zero_explicit(&tmp, size_of(tmp)) // Check that tmp is in the the range [0, ELL). if !unsafe_assume_canonical { @@ -66,7 +67,7 @@ fe_from_bytes_rfc8032 :: proc "contextless" ( fe_from_bytes_wide(out1, &tmp) - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tmp, size_of(tmp)) } fe_from_bytes_wide :: proc "contextless" ( @@ -100,7 +101,7 @@ _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Eleme copy(tmp[:], arg1) _ = fe_from_bytes(out1, &tmp, true) - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tmp, size_of(tmp)) } fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { @@ -114,20 +115,18 @@ fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_ endian.unchecked_put_u64le(out1[16:], tmp[2]) endian.unchecked_put_u64le(out1[24:], tmp[3]) - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tmp, size_of(tmp)) } fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { tmp: Montgomery_Domain_Field_Element fe_sub(&tmp, arg1, arg2) - // This will only underflow iff arg1 == arg2, and we return the borrow, - // which will be 1. - _, borrow := bits.sub_u64(fe_non_zero(&tmp), 1, 0) + is_eq := subtle.eq(fe_non_zero(&tmp), 0) fe_clear(&tmp) - return int(borrow) + return int(is_eq) } fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { diff --git a/core/crypto/_fiat/field_scalarp256r1/field.odin b/core/crypto/_fiat/field_scalarp256r1/field.odin new file mode 100644 index 000000000..802f3382e --- /dev/null +++ b/core/crypto/_fiat/field_scalarp256r1/field.odin @@ -0,0 +1,478 @@ +package field_scalarp256r1 + +import "core:crypto" +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" + +@(private, rodata) +TWO_192 := Montgomery_Domain_Field_Element{ + 2482910415990817935, + 2879494685571067143, + 8732918506673730078, + 85565669603516024, +} +@(private, rodata) +TWO_384 := Montgomery_Domain_Field_Element{ + 2127524300190691059, + 17014302137236182484, + 16604910261202196099, + 3621421107472562910, +} +// 2^384 % p (From sage) +// 0x431905529c0166ce652e96b7ccca0a99679b73e19ad16947f01cf013fc632551 + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + crypto.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, +) -> bool { + ensure_contextless(len(out1) <= 64, "p256r1: invalid scalar input buffer") + + is_canonical := false + s_len := len(arg1) + switch { + case s_len < 32: + // No way this can be greater than the order. + fe_unchecked_set(out1, arg1) + is_canonical = true + case s_len == 32: + // It is quite likely that a reduction mod p is required, + // as the order of the curve is sufficiently smaller than + // 2^256-1, so just check if we actually needed to reduced + // and do the reduction anyway, so that things that require + // canonical scalars can reject non-canonical encodings. + is_canonical = fe_is_canonical(arg1) + fallthrough + case: + // Use Frank Denis' trick, as documented by Filippo Valsorda + // at https://words.filippo.io/dispatches/wide-reduction/ + // + // "I represent the value as a+b*2^192+c*2^384" + // + // Note: Omitting the `c` computation is fine as, reduction + // being length dependent provides no useful timing information. + + // Zero extend to 512-bits. + src_512: [64]byte + copy(src_512[64-s_len:], arg1) + defer crypto.zero_explicit(&src_512, size_of(src_512)) + + fe_unchecked_set(out1, src_512[40:]) // a + b: Montgomery_Domain_Field_Element + fe_unchecked_set(&b, src_512[16:40]) // b + + fe_mul(&b, &b, &TWO_192) + fe_add(out1, out1, &b) + if s_len >= 48 { + c: Montgomery_Domain_Field_Element + fe_unchecked_set(&c, src_512[:16]) // c + fe_mul(&c, &c, &TWO_384) + fe_add(out1, out1, &c) + + fe_clear(&c) + } + + fe_clear(&b) + } + + return !is_canonical +} + +@(private) +fe_is_canonical :: proc "contextless" (arg1: []byte) -> bool { + _, borrow := bits.sub_u64(ELL[0] - 1, endian.unchecked_get_u64be(arg1[24:]), 0) + _, borrow = bits.sub_u64(ELL[1], endian.unchecked_get_u64be(arg1[16:]), borrow) + _, borrow = bits.sub_u64(ELL[2], endian.unchecked_get_u64be(arg1[8:]), borrow) + _, borrow = bits.sub_u64(ELL[3], endian.unchecked_get_u64be(arg1[0:]), borrow) + return borrow == 0 +} + +@(private) +fe_unchecked_set :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { + arg1_256: [32]byte + defer crypto.zero_explicit(&arg1_256, size_of(arg1_256)) + copy(arg1_256[32-len(arg1):], arg1) + + tmp := Non_Montgomery_Domain_Field_Element { + endian.unchecked_get_u64be(arg1_256[24:]), + endian.unchecked_get_u64be(arg1_256[16:]), + endian.unchecked_get_u64be(arg1_256[8:]), + endian.unchecked_get_u64be(arg1_256[0:]), + } + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_to_montgomery(out1, &tmp) +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 32, "p256r1: invalid scalar output buffer") + + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[24:], tmp[0]) + endian.unchecked_put_u64be(out1[16:], tmp[1]) + endian.unchecked_put_u64be(out1[8:], tmp[2]) + endian.unchecked_put_u64be(out1[0:], tmp[3]) + + crypto.zero_explicit(&tmp, size_of(tmp)) +} + +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element = --- + fe_sub(&tmp, arg1, arg2) + + is_eq := subtle.eq(fe_non_zero(&tmp), 0) + + fe_clear(&tmp) + + return int(is_eq) +} + +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element = --- + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^Montgomery_Domain_Field_Element, + arg3: int, +) { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} + +fe_pow2k :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_square(out1, out1) + } +} + +fe_inv :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _100 = 2*_10 + // _101 = 1 + _100 + // _110 = 1 + _101 + // _1001 = _100 + _101 + // _1111 = _110 + _1001 + // _10010 = 2*_1001 + // _10101 = _110 + _1111 + // _11000 = _110 + _10010 + // _11010 = _10 + _11000 + // _101111 = _10101 + _11010 + // _111000 = _1001 + _101111 + // _111101 = _101 + _111000 + // _111111 = _10 + _111101 + // _1001111 = _10010 + _111101 + // _1100001 = _10010 + _1001111 + // _1100011 = _10 + _1100001 + // _1110011 = _10010 + _1100001 + // _1110111 = _100 + _1110011 + // _1111101 = _110 + _1110111 + // _10010101 = _11000 + _1111101 + // _10100111 = _10010 + _10010101 + // _10101101 = _110 + _10100111 + // _11100101 = _111000 + _10101101 + // _11111111 = _11010 + _11100101 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // i133 = ((x32 << 48 + x16) << 16 + x16) << 16 + // i158 = ((x16 + i133) << 16 + x16) << 6 + _101111 + // i186 = ((i158 << 9 + _1110011) << 8 + _1111101) << 9 + // i206 = ((_10101101 + i186) << 8 + _10100111) << 9 + _101111 + // i236 = ((i206 << 8 + _111101) << 11 + _1001111) << 9 + // i257 = ((_1110111 + i236) << 10 + _11100101) << 8 + _1100001 + // i286 = ((i257 << 7 + _111111) << 10 + _1100011) << 10 + // return (_10010101 + i286) << 6 + _1111 + // + // Operations: 251 squares 43 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Note: Need to stash `arg1` (`xx`) in the case that `out1`/`arg1` alias, + // as `arg1` is used after `out1` has been altered. + t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, xx: Montgomery_Domain_Field_Element = ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, arg1^ + + // Step 1: t1 = x^0x2 + fe_square(&t1, arg1) + + // Step 2: t5 = x^0x4 + fe_square(&t5, &t1) + + // Step 3: t2 = x^0x5 + fe_mul(&t2, arg1, &t5) + + // Step 4: t10 = x^0x6 + fe_mul(&t10, arg1, &t2) + + // Step 5: t3 = x^0x9 + fe_mul(&t3, &t5, &t2) + + // Step 6: z = x^0xf + fe_mul(out1, &t10, &t3) + + // Step 7: t9 = x^0x12 + fe_square(&t9, &t3) + + // Step 8: t4 = x^0x15 + fe_mul(&t4, &t10, out1) + + // Step 9: t0 = x^0x18 + fe_mul(&t0, &t10, &t9) + + // Step 10: t13 = x^0x1a + fe_mul(&t13, &t1, &t0) + + // Step 11: t8 = x^0x2f + fe_mul(&t8, &t4, &t13) + + // Step 12: t4 = x^0x38 + fe_mul(&t4, &t3, &t8) + + // Step 13: t7 = x^0x3d + fe_mul(&t7, &t2, &t4) + + // Step 14: t2 = x^0x3f + fe_mul(&t2, &t1, &t7) + + // Step 15: t6 = x^0x4f + fe_mul(&t6, &t9, &t7) + + // Step 16: t3 = x^0x61 + fe_mul(&t3, &t9, &t6) + + // Step 17: t1 = x^0x63 + fe_mul(&t1, &t1, &t3) + + // Step 18: t12 = x^0x73 + fe_mul(&t12, &t9, &t3) + + // Step 19: t5 = x^0x77 + fe_mul(&t5, &t5, &t12) + + // Step 20: t11 = x^0x7d + fe_mul(&t11, &t10, &t5) + + // Step 21: t0 = x^0x95 + fe_mul(&t0, &t0, &t11) + + // Step 22: t9 = x^0xa7 + fe_mul(&t9, &t9, &t0) + + // Step 23: t10 = x^0xad + fe_mul(&t10, &t10, &t9) + + // Step 24: t4 = x^0xe5 + fe_mul(&t4, &t4, &t10) + + // Step 25: t13 = x^0xff + fe_mul(&t13, &t13, &t4) + + // Step 33: t14 = x^0xff00 + fe_pow2k(&t14, &t13, 8) + + // Step 34: t13 = x^0xffff + fe_mul(&t13, &t13, &t14) + + // Step 50: t14 = x^0xffff0000 + fe_pow2k(&t14, &t13, 16) + + // Step 51: t14 = x^0xffffffff + fe_mul(&t14, &t13, &t14) + + // Step 99: t14 = x^0xffffffff000000000000 + fe_pow2k(&t14, &t14, 48) + + // Step 100: t14 = x^0xffffffff00000000ffff + fe_mul(&t14, &t13, &t14) + + // Step 116: t14 = x^0xffffffff00000000ffff0000 + fe_pow2k(&t14, &t14, 16) + + // Step 117: t14 = x^0xffffffff00000000ffffffff + fe_mul(&t14, &t13, &t14) + + // Step 133: t14 = x^0xffffffff00000000ffffffff0000 + fe_pow2k(&t14, &t14, 16) + + // Step 134: t14 = x^0xffffffff00000000ffffffffffff + fe_mul(&t14, &t13, &t14) + + // Step 150: t14 = x^0xffffffff00000000ffffffffffff0000 + fe_pow2k(&t14, &t14, 16) + + // Step 151: t13 = x^0xffffffff00000000ffffffffffffffff + fe_mul(&t13, &t13, &t14) + + // Step 157: t13 = x^0x3fffffffc00000003fffffffffffffffc0 + fe_pow2k(&t13, &t13, 6) + + // Step 158: t13 = x^0x3fffffffc00000003fffffffffffffffef + fe_mul(&t13, &t8, &t13) + + // Step 167: t13 = x^0x7fffffff800000007fffffffffffffffde00 + fe_pow2k(&t13, &t13, 9) + + // Step 168: t12 = x^0x7fffffff800000007fffffffffffffffde73 + fe_mul(&t12, &t12, &t13) + + // Step 176: t12 = x^0x7fffffff800000007fffffffffffffffde7300 + fe_pow2k(&t12, &t12, 8) + + // Step 177: t11 = x^0x7fffffff800000007fffffffffffffffde737d + fe_mul(&t11, &t11, &t12) + + // Step 186: t11 = x^0xffffffff00000000ffffffffffffffffbce6fa00 + fe_pow2k(&t11, &t11, 9) + + // Step 187: t10 = x^0xffffffff00000000ffffffffffffffffbce6faad + fe_mul(&t10, &t10, &t11) + + // Step 195: t10 = x^0xffffffff00000000ffffffffffffffffbce6faad00 + fe_pow2k(&t10, &t10, 8) + + // Step 196: t9 = x^0xffffffff00000000ffffffffffffffffbce6faada7 + fe_mul(&t9, &t9, &t10) + + // Step 205: t9 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e00 + fe_pow2k(&t9, &t9, 9) + + // Step 206: t8 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e2f + fe_mul(&t8, &t8, &t9) + + // Step 214: t8 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e2f00 + fe_pow2k(&t8, &t8, 8) + + // Step 215: t7 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e2f3d + fe_mul(&t7, &t7, &t8) + + // Step 226: t7 = x^0xffffffff00000000ffffffffffffffffbce6faada7179e800 + fe_pow2k(&t7, &t7, 11) + + // Step 227: t6 = x^0xffffffff00000000ffffffffffffffffbce6faada7179e84f + fe_mul(&t6, &t6, &t7) + + // Step 236: t6 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e00 + fe_pow2k(&t6, &t6, 9) + + // Step 237: t5 = x^0x1fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e77 + fe_mul(&t5, &t5, &t6) + + // Step 247: t5 = x^0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dc00 + fe_pow2k(&t5, &t5, 10) + + // Step 248: t4 = x^0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5 + fe_mul(&t4, &t4, &t5) + + // Step 256: t4 = x^0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce500 + fe_pow2k(&t4, &t4, 8) + + // Step 257: t3 = x^0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce561 + fe_mul(&t3, &t3, &t4) + + // Step 264: t3 = x^0x3fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b080 + fe_pow2k(&t3, &t3, 7) + + // Step 265: t2 = x^0x3fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf + fe_mul(&t2, &t2, &t3) + + // Step 275: t2 = x^0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc00 + fe_pow2k(&t2, &t2, 10) + + // Step 276: t1 = x^0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63 + fe_mul(&t1, &t1, &t2) + + // Step 286: t1 = x^0x3fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c00 + fe_pow2k(&t1, &t1, 10) + + // Step 287: t0 = x^0x3fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c95 + fe_mul(&t0, &t0, &t1) + + // Step 293: t0 = x^0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 + fe_pow2k(&t0, &t0, 6) + + // Step 294: z = x^0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f + fe_mul(out1, out1, &t0) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9, &t10, &t11, &t12, &t13, &t14, &xx}) +} diff --git a/core/crypto/_fiat/field_scalarp256r1/field64.odin b/core/crypto/_fiat/field_scalarp256r1/field64.odin new file mode 100644 index 000000000..4217374a7 --- /dev/null +++ b/core/crypto/_fiat/field_scalarp256r1/field64.odin @@ -0,0 +1,569 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_scalarp256r1 + +// The file provides arithmetic on the field Z/(2^256 - 2^224 + 2^192 - +// 89188191075325690597107910205041859247) using a 64-bit Montgomery form +// internal representation. It is derived primarily from the machine +// generated Golang output from the fiat-crypto project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [4]u64{0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000} + +Montgomery_Domain_Field_Element :: distinct [4]u64 +Non_Montgomery_Domain_Field_Element :: distinct [4]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg2[3]) + x8, x7 := bits.mul_u64(x4, arg2[2]) + x10, x9 := bits.mul_u64(x4, arg2[1]) + x12, x11 := bits.mul_u64(x4, arg2[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + _, x20 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x23, x22 := bits.mul_u64(x20, 0xffffffff00000000) + x25, x24 := bits.mul_u64(x20, 0xffffffffffffffff) + x27, x26 := bits.mul_u64(x20, 0xbce6faada7179e84) + x29, x28 := bits.mul_u64(x20, 0xf3b9cac2fc632551) + x30, x31 := bits.add_u64(x29, x26, u64(0x0)) + x32, x33 := bits.add_u64(x27, x24, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(x25, x22, u64(fiat.u1(x33))) + x36 := (u64(fiat.u1(x35)) + x23) + _, x38 := bits.add_u64(x11, x28, u64(0x0)) + x39, x40 := bits.add_u64(x13, x30, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x15, x32, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64(x17, x34, u64(fiat.u1(x42))) + x45, x46 := bits.add_u64(x19, x36, u64(fiat.u1(x44))) + x48, x47 := bits.mul_u64(x1, arg2[3]) + x50, x49 := bits.mul_u64(x1, arg2[2]) + x52, x51 := bits.mul_u64(x1, arg2[1]) + x54, x53 := bits.mul_u64(x1, arg2[0]) + x55, x56 := bits.add_u64(x54, x51, u64(0x0)) + x57, x58 := bits.add_u64(x52, x49, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x50, x47, u64(fiat.u1(x58))) + x61 := (u64(fiat.u1(x60)) + x48) + x62, x63 := bits.add_u64(x39, x53, u64(0x0)) + x64, x65 := bits.add_u64(x41, x55, u64(fiat.u1(x63))) + x66, x67 := bits.add_u64(x43, x57, u64(fiat.u1(x65))) + x68, x69 := bits.add_u64(x45, x59, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(u64(fiat.u1(x46)), x61, u64(fiat.u1(x69))) + _, x72 := bits.mul_u64(x62, 0xccd1c8aaee00bc4f) + x75, x74 := bits.mul_u64(x72, 0xffffffff00000000) + x77, x76 := bits.mul_u64(x72, 0xffffffffffffffff) + x79, x78 := bits.mul_u64(x72, 0xbce6faada7179e84) + x81, x80 := bits.mul_u64(x72, 0xf3b9cac2fc632551) + x82, x83 := bits.add_u64(x81, x78, u64(0x0)) + x84, x85 := bits.add_u64(x79, x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x77, x74, u64(fiat.u1(x85))) + x88 := (u64(fiat.u1(x87)) + x75) + _, x90 := bits.add_u64(x62, x80, u64(0x0)) + x91, x92 := bits.add_u64(x64, x82, u64(fiat.u1(x90))) + x93, x94 := bits.add_u64(x66, x84, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x68, x86, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x70, x88, u64(fiat.u1(x96))) + x99 := (u64(fiat.u1(x98)) + u64(fiat.u1(x71))) + x101, x100 := bits.mul_u64(x2, arg2[3]) + x103, x102 := bits.mul_u64(x2, arg2[2]) + x105, x104 := bits.mul_u64(x2, arg2[1]) + x107, x106 := bits.mul_u64(x2, arg2[0]) + x108, x109 := bits.add_u64(x107, x104, u64(0x0)) + x110, x111 := bits.add_u64(x105, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x103, x100, u64(fiat.u1(x111))) + x114 := (u64(fiat.u1(x113)) + x101) + x115, x116 := bits.add_u64(x91, x106, u64(0x0)) + x117, x118 := bits.add_u64(x93, x108, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x95, x110, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x97, x112, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x99, x114, u64(fiat.u1(x122))) + _, x125 := bits.mul_u64(x115, 0xccd1c8aaee00bc4f) + x128, x127 := bits.mul_u64(x125, 0xffffffff00000000) + x130, x129 := bits.mul_u64(x125, 0xffffffffffffffff) + x132, x131 := bits.mul_u64(x125, 0xbce6faada7179e84) + x134, x133 := bits.mul_u64(x125, 0xf3b9cac2fc632551) + x135, x136 := bits.add_u64(x134, x131, u64(0x0)) + x137, x138 := bits.add_u64(x132, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x130, x127, u64(fiat.u1(x138))) + x141 := (u64(fiat.u1(x140)) + x128) + _, x143 := bits.add_u64(x115, x133, u64(0x0)) + x144, x145 := bits.add_u64(x117, x135, u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x119, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x121, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x123, x141, u64(fiat.u1(x149))) + x152 := (u64(fiat.u1(x151)) + u64(fiat.u1(x124))) + x154, x153 := bits.mul_u64(x3, arg2[3]) + x156, x155 := bits.mul_u64(x3, arg2[2]) + x158, x157 := bits.mul_u64(x3, arg2[1]) + x160, x159 := bits.mul_u64(x3, arg2[0]) + x161, x162 := bits.add_u64(x160, x157, u64(0x0)) + x163, x164 := bits.add_u64(x158, x155, u64(fiat.u1(x162))) + x165, x166 := bits.add_u64(x156, x153, u64(fiat.u1(x164))) + x167 := (u64(fiat.u1(x166)) + x154) + x168, x169 := bits.add_u64(x144, x159, u64(0x0)) + x170, x171 := bits.add_u64(x146, x161, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x148, x163, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x150, x165, u64(fiat.u1(x173))) + x176, x177 := bits.add_u64(x152, x167, u64(fiat.u1(x175))) + _, x178 := bits.mul_u64(x168, 0xccd1c8aaee00bc4f) + x181, x180 := bits.mul_u64(x178, 0xffffffff00000000) + x183, x182 := bits.mul_u64(x178, 0xffffffffffffffff) + x185, x184 := bits.mul_u64(x178, 0xbce6faada7179e84) + x187, x186 := bits.mul_u64(x178, 0xf3b9cac2fc632551) + x188, x189 := bits.add_u64(x187, x184, u64(0x0)) + x190, x191 := bits.add_u64(x185, x182, u64(fiat.u1(x189))) + x192, x193 := bits.add_u64(x183, x180, u64(fiat.u1(x191))) + x194 := (u64(fiat.u1(x193)) + x181) + _, x196 := bits.add_u64(x168, x186, u64(0x0)) + x197, x198 := bits.add_u64(x170, x188, u64(fiat.u1(x196))) + x199, x200 := bits.add_u64(x172, x190, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x174, x192, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x176, x194, u64(fiat.u1(x202))) + x205 := (u64(fiat.u1(x204)) + u64(fiat.u1(x177))) + x206, x207 := bits.sub_u64(x197, 0xf3b9cac2fc632551, u64(0x0)) + x208, x209 := bits.sub_u64(x199, 0xbce6faada7179e84, u64(fiat.u1(x207))) + x210, x211 := bits.sub_u64(x201, 0xffffffffffffffff, u64(fiat.u1(x209))) + x212, x213 := bits.sub_u64(x203, 0xffffffff00000000, u64(fiat.u1(x211))) + _, x215 := bits.sub_u64(x205, u64(0x0), u64(fiat.u1(x213))) + x216 := fiat.cmovznz_u64(fiat.u1(x215), x206, x197) + x217 := fiat.cmovznz_u64(fiat.u1(x215), x208, x199) + x218 := fiat.cmovznz_u64(fiat.u1(x215), x210, x201) + x219 := fiat.cmovznz_u64(fiat.u1(x215), x212, x203) + out1[0] = x216 + out1[1] = x217 + out1[2] = x218 + out1[3] = x219 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg1[3]) + x8, x7 := bits.mul_u64(x4, arg1[2]) + x10, x9 := bits.mul_u64(x4, arg1[1]) + x12, x11 := bits.mul_u64(x4, arg1[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + _, x20 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x23, x22 := bits.mul_u64(x20, 0xffffffff00000000) + x25, x24 := bits.mul_u64(x20, 0xffffffffffffffff) + x27, x26 := bits.mul_u64(x20, 0xbce6faada7179e84) + x29, x28 := bits.mul_u64(x20, 0xf3b9cac2fc632551) + x30, x31 := bits.add_u64(x29, x26, u64(0x0)) + x32, x33 := bits.add_u64(x27, x24, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(x25, x22, u64(fiat.u1(x33))) + x36 := (u64(fiat.u1(x35)) + x23) + _, x38 := bits.add_u64(x11, x28, u64(0x0)) + x39, x40 := bits.add_u64(x13, x30, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x15, x32, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64(x17, x34, u64(fiat.u1(x42))) + x45, x46 := bits.add_u64(x19, x36, u64(fiat.u1(x44))) + x48, x47 := bits.mul_u64(x1, arg1[3]) + x50, x49 := bits.mul_u64(x1, arg1[2]) + x52, x51 := bits.mul_u64(x1, arg1[1]) + x54, x53 := bits.mul_u64(x1, arg1[0]) + x55, x56 := bits.add_u64(x54, x51, u64(0x0)) + x57, x58 := bits.add_u64(x52, x49, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x50, x47, u64(fiat.u1(x58))) + x61 := (u64(fiat.u1(x60)) + x48) + x62, x63 := bits.add_u64(x39, x53, u64(0x0)) + x64, x65 := bits.add_u64(x41, x55, u64(fiat.u1(x63))) + x66, x67 := bits.add_u64(x43, x57, u64(fiat.u1(x65))) + x68, x69 := bits.add_u64(x45, x59, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(u64(fiat.u1(x46)), x61, u64(fiat.u1(x69))) + _, x72 := bits.mul_u64(x62, 0xccd1c8aaee00bc4f) + x75, x74 := bits.mul_u64(x72, 0xffffffff00000000) + x77, x76 := bits.mul_u64(x72, 0xffffffffffffffff) + x79, x78 := bits.mul_u64(x72, 0xbce6faada7179e84) + x81, x80 := bits.mul_u64(x72, 0xf3b9cac2fc632551) + x82, x83 := bits.add_u64(x81, x78, u64(0x0)) + x84, x85 := bits.add_u64(x79, x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x77, x74, u64(fiat.u1(x85))) + x88 := (u64(fiat.u1(x87)) + x75) + _, x90 := bits.add_u64(x62, x80, u64(0x0)) + x91, x92 := bits.add_u64(x64, x82, u64(fiat.u1(x90))) + x93, x94 := bits.add_u64(x66, x84, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x68, x86, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x70, x88, u64(fiat.u1(x96))) + x99 := (u64(fiat.u1(x98)) + u64(fiat.u1(x71))) + x101, x100 := bits.mul_u64(x2, arg1[3]) + x103, x102 := bits.mul_u64(x2, arg1[2]) + x105, x104 := bits.mul_u64(x2, arg1[1]) + x107, x106 := bits.mul_u64(x2, arg1[0]) + x108, x109 := bits.add_u64(x107, x104, u64(0x0)) + x110, x111 := bits.add_u64(x105, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x103, x100, u64(fiat.u1(x111))) + x114 := (u64(fiat.u1(x113)) + x101) + x115, x116 := bits.add_u64(x91, x106, u64(0x0)) + x117, x118 := bits.add_u64(x93, x108, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x95, x110, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x97, x112, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x99, x114, u64(fiat.u1(x122))) + _, x125 := bits.mul_u64(x115, 0xccd1c8aaee00bc4f) + x128, x127 := bits.mul_u64(x125, 0xffffffff00000000) + x130, x129 := bits.mul_u64(x125, 0xffffffffffffffff) + x132, x131 := bits.mul_u64(x125, 0xbce6faada7179e84) + x134, x133 := bits.mul_u64(x125, 0xf3b9cac2fc632551) + x135, x136 := bits.add_u64(x134, x131, u64(0x0)) + x137, x138 := bits.add_u64(x132, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x130, x127, u64(fiat.u1(x138))) + x141 := (u64(fiat.u1(x140)) + x128) + _, x143 := bits.add_u64(x115, x133, u64(0x0)) + x144, x145 := bits.add_u64(x117, x135, u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x119, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x121, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x123, x141, u64(fiat.u1(x149))) + x152 := (u64(fiat.u1(x151)) + u64(fiat.u1(x124))) + x154, x153 := bits.mul_u64(x3, arg1[3]) + x156, x155 := bits.mul_u64(x3, arg1[2]) + x158, x157 := bits.mul_u64(x3, arg1[1]) + x160, x159 := bits.mul_u64(x3, arg1[0]) + x161, x162 := bits.add_u64(x160, x157, u64(0x0)) + x163, x164 := bits.add_u64(x158, x155, u64(fiat.u1(x162))) + x165, x166 := bits.add_u64(x156, x153, u64(fiat.u1(x164))) + x167 := (u64(fiat.u1(x166)) + x154) + x168, x169 := bits.add_u64(x144, x159, u64(0x0)) + x170, x171 := bits.add_u64(x146, x161, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x148, x163, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x150, x165, u64(fiat.u1(x173))) + x176, x177 := bits.add_u64(x152, x167, u64(fiat.u1(x175))) + _, x178 := bits.mul_u64(x168, 0xccd1c8aaee00bc4f) + x181, x180 := bits.mul_u64(x178, 0xffffffff00000000) + x183, x182 := bits.mul_u64(x178, 0xffffffffffffffff) + x185, x184 := bits.mul_u64(x178, 0xbce6faada7179e84) + x187, x186 := bits.mul_u64(x178, 0xf3b9cac2fc632551) + x188, x189 := bits.add_u64(x187, x184, u64(0x0)) + x190, x191 := bits.add_u64(x185, x182, u64(fiat.u1(x189))) + x192, x193 := bits.add_u64(x183, x180, u64(fiat.u1(x191))) + x194 := (u64(fiat.u1(x193)) + x181) + _, x196 := bits.add_u64(x168, x186, u64(0x0)) + x197, x198 := bits.add_u64(x170, x188, u64(fiat.u1(x196))) + x199, x200 := bits.add_u64(x172, x190, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x174, x192, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x176, x194, u64(fiat.u1(x202))) + x205 := (u64(fiat.u1(x204)) + u64(fiat.u1(x177))) + x206, x207 := bits.sub_u64(x197, 0xf3b9cac2fc632551, u64(0x0)) + x208, x209 := bits.sub_u64(x199, 0xbce6faada7179e84, u64(fiat.u1(x207))) + x210, x211 := bits.sub_u64(x201, 0xffffffffffffffff, u64(fiat.u1(x209))) + x212, x213 := bits.sub_u64(x203, 0xffffffff00000000, u64(fiat.u1(x211))) + _, x215 := bits.sub_u64(x205, u64(0x0), u64(fiat.u1(x213))) + x216 := fiat.cmovznz_u64(fiat.u1(x215), x206, x197) + x217 := fiat.cmovznz_u64(fiat.u1(x215), x208, x199) + x218 := fiat.cmovznz_u64(fiat.u1(x215), x210, x201) + x219 := fiat.cmovznz_u64(fiat.u1(x215), x212, x203) + out1[0] = x216 + out1[1] = x217 + out1[2] = x218 + out1[3] = x219 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(x1, 0xf3b9cac2fc632551, u64(0x0)) + x11, x12 := bits.sub_u64(x3, 0xbce6faada7179e84, u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x5, 0xffffffffffffffff, u64(fiat.u1(x12))) + x15, x16 := bits.sub_u64(x7, 0xffffffff00000000, u64(fiat.u1(x14))) + _, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16))) + x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1) + x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3) + x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5) + x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, (x9 & 0xf3b9cac2fc632551), u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xbce6faada7179e84), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, x9, u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000000), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, (x9 & 0xf3b9cac2fc632551), u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xbce6faada7179e84), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, x9, u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000000), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0xc46353d039cdaaf + out1[1] = 0x4319055258e8617b + out1[2] = u64(0x0) + out1[3] = 0xffffffff +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return arg1[0] | (arg1[1] | (arg1[2] | arg1[3])) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + _, x2 := bits.mul_u64(x1, 0xccd1c8aaee00bc4f) + x5, x4 := bits.mul_u64(x2, 0xffffffff00000000) + x7, x6 := bits.mul_u64(x2, 0xffffffffffffffff) + x9, x8 := bits.mul_u64(x2, 0xbce6faada7179e84) + x11, x10 := bits.mul_u64(x2, 0xf3b9cac2fc632551) + x12, x13 := bits.add_u64(x11, x8, u64(0x0)) + x14, x15 := bits.add_u64(x9, x6, u64(fiat.u1(x13))) + x16, x17 := bits.add_u64(x7, x4, u64(fiat.u1(x15))) + _, x19 := bits.add_u64(x1, x10, u64(0x0)) + x20, x21 := bits.add_u64(u64(0x0), x12, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(u64(0x0), x14, u64(fiat.u1(x21))) + x24, x25 := bits.add_u64(u64(0x0), x16, u64(fiat.u1(x23))) + x26, x27 := bits.add_u64(x20, arg1[1], u64(0x0)) + x28, x29 := bits.add_u64(x22, u64(0x0), u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(x24, u64(0x0), u64(fiat.u1(x29))) + _, x32 := bits.mul_u64(x26, 0xccd1c8aaee00bc4f) + x35, x34 := bits.mul_u64(x32, 0xffffffff00000000) + x37, x36 := bits.mul_u64(x32, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x32, 0xbce6faada7179e84) + x41, x40 := bits.mul_u64(x32, 0xf3b9cac2fc632551) + x42, x43 := bits.add_u64(x41, x38, u64(0x0)) + x44, x45 := bits.add_u64(x39, x36, u64(fiat.u1(x43))) + x46, x47 := bits.add_u64(x37, x34, u64(fiat.u1(x45))) + _, x49 := bits.add_u64(x26, x40, u64(0x0)) + x50, x51 := bits.add_u64(x28, x42, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x30, x44, u64(fiat.u1(x51))) + x54, x55 := bits.add_u64((u64(fiat.u1(x31)) + (u64(fiat.u1(x25)) + (u64(fiat.u1(x17)) + x5))), x46, u64(fiat.u1(x53))) + x56, x57 := bits.add_u64(x50, arg1[2], u64(0x0)) + x58, x59 := bits.add_u64(x52, u64(0x0), u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x54, u64(0x0), u64(fiat.u1(x59))) + _, x62 := bits.mul_u64(x56, 0xccd1c8aaee00bc4f) + x65, x64 := bits.mul_u64(x62, 0xffffffff00000000) + x67, x66 := bits.mul_u64(x62, 0xffffffffffffffff) + x69, x68 := bits.mul_u64(x62, 0xbce6faada7179e84) + x71, x70 := bits.mul_u64(x62, 0xf3b9cac2fc632551) + x72, x73 := bits.add_u64(x71, x68, u64(0x0)) + x74, x75 := bits.add_u64(x69, x66, u64(fiat.u1(x73))) + x76, x77 := bits.add_u64(x67, x64, u64(fiat.u1(x75))) + _, x79 := bits.add_u64(x56, x70, u64(0x0)) + x80, x81 := bits.add_u64(x58, x72, u64(fiat.u1(x79))) + x82, x83 := bits.add_u64(x60, x74, u64(fiat.u1(x81))) + x84, x85 := bits.add_u64((u64(fiat.u1(x61)) + (u64(fiat.u1(x55)) + (u64(fiat.u1(x47)) + x35))), x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x80, arg1[3], u64(0x0)) + x88, x89 := bits.add_u64(x82, u64(0x0), u64(fiat.u1(x87))) + x90, x91 := bits.add_u64(x84, u64(0x0), u64(fiat.u1(x89))) + _, x92 := bits.mul_u64(x86, 0xccd1c8aaee00bc4f) + x95, x94 := bits.mul_u64(x92, 0xffffffff00000000) + x97, x96 := bits.mul_u64(x92, 0xffffffffffffffff) + x99, x98 := bits.mul_u64(x92, 0xbce6faada7179e84) + x101, x100 := bits.mul_u64(x92, 0xf3b9cac2fc632551) + x102, x103 := bits.add_u64(x101, x98, u64(0x0)) + x104, x105 := bits.add_u64(x99, x96, u64(fiat.u1(x103))) + x106, x107 := bits.add_u64(x97, x94, u64(fiat.u1(x105))) + _, x109 := bits.add_u64(x86, x100, u64(0x0)) + x110, x111 := bits.add_u64(x88, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x90, x104, u64(fiat.u1(x111))) + x114, x115 := bits.add_u64((u64(fiat.u1(x91)) + (u64(fiat.u1(x85)) + (u64(fiat.u1(x77)) + x65))), x106, u64(fiat.u1(x113))) + x116 := (u64(fiat.u1(x115)) + (u64(fiat.u1(x107)) + x95)) + x117, x118 := bits.sub_u64(x110, 0xf3b9cac2fc632551, u64(0x0)) + x119, x120 := bits.sub_u64(x112, 0xbce6faada7179e84, u64(fiat.u1(x118))) + x121, x122 := bits.sub_u64(x114, 0xffffffffffffffff, u64(fiat.u1(x120))) + x123, x124 := bits.sub_u64(x116, 0xffffffff00000000, u64(fiat.u1(x122))) + _, x126 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x124))) + x127 := fiat.cmovznz_u64(fiat.u1(x126), x117, x110) + x128 := fiat.cmovznz_u64(fiat.u1(x126), x119, x112) + x129 := fiat.cmovznz_u64(fiat.u1(x126), x121, x114) + x130 := fiat.cmovznz_u64(fiat.u1(x126), x123, x116) + out1[0] = x127 + out1[1] = x128 + out1[2] = x129 + out1[3] = x130 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, 0x66e12d94f3d95620) + x8, x7 := bits.mul_u64(x4, 0x2845b2392b6bec59) + x10, x9 := bits.mul_u64(x4, 0x4699799c49bd6fa6) + x12, x11 := bits.mul_u64(x4, 0x83244c95be79eea2) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + _, x19 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x22, x21 := bits.mul_u64(x19, 0xffffffff00000000) + x24, x23 := bits.mul_u64(x19, 0xffffffffffffffff) + x26, x25 := bits.mul_u64(x19, 0xbce6faada7179e84) + x28, x27 := bits.mul_u64(x19, 0xf3b9cac2fc632551) + x29, x30 := bits.add_u64(x28, x25, u64(0x0)) + x31, x32 := bits.add_u64(x26, x23, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x24, x21, u64(fiat.u1(x32))) + _, x36 := bits.add_u64(x11, x27, u64(0x0)) + x37, x38 := bits.add_u64(x13, x29, u64(fiat.u1(x36))) + x39, x40 := bits.add_u64(x15, x31, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x17, x33, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64((u64(fiat.u1(x18)) + x6), (u64(fiat.u1(x34)) + x22), u64(fiat.u1(x42))) + x46, x45 := bits.mul_u64(x1, 0x66e12d94f3d95620) + x48, x47 := bits.mul_u64(x1, 0x2845b2392b6bec59) + x50, x49 := bits.mul_u64(x1, 0x4699799c49bd6fa6) + x52, x51 := bits.mul_u64(x1, 0x83244c95be79eea2) + x53, x54 := bits.add_u64(x52, x49, u64(0x0)) + x55, x56 := bits.add_u64(x50, x47, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(x48, x45, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x37, x51, u64(0x0)) + x61, x62 := bits.add_u64(x39, x53, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x41, x55, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x43, x57, u64(fiat.u1(x64))) + _, x67 := bits.mul_u64(x59, 0xccd1c8aaee00bc4f) + x70, x69 := bits.mul_u64(x67, 0xffffffff00000000) + x72, x71 := bits.mul_u64(x67, 0xffffffffffffffff) + x74, x73 := bits.mul_u64(x67, 0xbce6faada7179e84) + x76, x75 := bits.mul_u64(x67, 0xf3b9cac2fc632551) + x77, x78 := bits.add_u64(x76, x73, u64(0x0)) + x79, x80 := bits.add_u64(x74, x71, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x72, x69, u64(fiat.u1(x80))) + _, x84 := bits.add_u64(x59, x75, u64(0x0)) + x85, x86 := bits.add_u64(x61, x77, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x63, x79, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x65, x81, u64(fiat.u1(x88))) + x91, x92 := bits.add_u64(((u64(fiat.u1(x66)) + u64(fiat.u1(x44))) + (u64(fiat.u1(x58)) + x46)), (u64(fiat.u1(x82)) + x70), u64(fiat.u1(x90))) + x94, x93 := bits.mul_u64(x2, 0x66e12d94f3d95620) + x96, x95 := bits.mul_u64(x2, 0x2845b2392b6bec59) + x98, x97 := bits.mul_u64(x2, 0x4699799c49bd6fa6) + x100, x99 := bits.mul_u64(x2, 0x83244c95be79eea2) + x101, x102 := bits.add_u64(x100, x97, u64(0x0)) + x103, x104 := bits.add_u64(x98, x95, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x96, x93, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x85, x99, u64(0x0)) + x109, x110 := bits.add_u64(x87, x101, u64(fiat.u1(x108))) + x111, x112 := bits.add_u64(x89, x103, u64(fiat.u1(x110))) + x113, x114 := bits.add_u64(x91, x105, u64(fiat.u1(x112))) + _, x115 := bits.mul_u64(x107, 0xccd1c8aaee00bc4f) + x118, x117 := bits.mul_u64(x115, 0xffffffff00000000) + x120, x119 := bits.mul_u64(x115, 0xffffffffffffffff) + x122, x121 := bits.mul_u64(x115, 0xbce6faada7179e84) + x124, x123 := bits.mul_u64(x115, 0xf3b9cac2fc632551) + x125, x126 := bits.add_u64(x124, x121, u64(0x0)) + x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126))) + x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128))) + _, x132 := bits.add_u64(x107, x123, u64(0x0)) + x133, x134 := bits.add_u64(x109, x125, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x111, x127, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x113, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(((u64(fiat.u1(x114)) + u64(fiat.u1(x92))) + (u64(fiat.u1(x106)) + x94)), (u64(fiat.u1(x130)) + x118), u64(fiat.u1(x138))) + x142, x141 := bits.mul_u64(x3, 0x66e12d94f3d95620) + x144, x143 := bits.mul_u64(x3, 0x2845b2392b6bec59) + x146, x145 := bits.mul_u64(x3, 0x4699799c49bd6fa6) + x148, x147 := bits.mul_u64(x3, 0x83244c95be79eea2) + x149, x150 := bits.add_u64(x148, x145, u64(0x0)) + x151, x152 := bits.add_u64(x146, x143, u64(fiat.u1(x150))) + x153, x154 := bits.add_u64(x144, x141, u64(fiat.u1(x152))) + x155, x156 := bits.add_u64(x133, x147, u64(0x0)) + x157, x158 := bits.add_u64(x135, x149, u64(fiat.u1(x156))) + x159, x160 := bits.add_u64(x137, x151, u64(fiat.u1(x158))) + x161, x162 := bits.add_u64(x139, x153, u64(fiat.u1(x160))) + _, x163 := bits.mul_u64(x155, 0xccd1c8aaee00bc4f) + x166, x165 := bits.mul_u64(x163, 0xffffffff00000000) + x168, x167 := bits.mul_u64(x163, 0xffffffffffffffff) + x170, x169 := bits.mul_u64(x163, 0xbce6faada7179e84) + x172, x171 := bits.mul_u64(x163, 0xf3b9cac2fc632551) + x173, x174 := bits.add_u64(x172, x169, u64(0x0)) + x175, x176 := bits.add_u64(x170, x167, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x168, x165, u64(fiat.u1(x176))) + _, x180 := bits.add_u64(x155, x171, u64(0x0)) + x181, x182 := bits.add_u64(x157, x173, u64(fiat.u1(x180))) + x183, x184 := bits.add_u64(x159, x175, u64(fiat.u1(x182))) + x185, x186 := bits.add_u64(x161, x177, u64(fiat.u1(x184))) + x187, x188 := bits.add_u64(((u64(fiat.u1(x162)) + u64(fiat.u1(x140))) + (u64(fiat.u1(x154)) + x142)), (u64(fiat.u1(x178)) + x166), u64(fiat.u1(x186))) + x189, x190 := bits.sub_u64(x181, 0xf3b9cac2fc632551, u64(0x0)) + x191, x192 := bits.sub_u64(x183, 0xbce6faada7179e84, u64(fiat.u1(x190))) + x193, x194 := bits.sub_u64(x185, 0xffffffffffffffff, u64(fiat.u1(x192))) + x195, x196 := bits.sub_u64(x187, 0xffffffff00000000, u64(fiat.u1(x194))) + _, x198 := bits.sub_u64(u64(fiat.u1(x188)), u64(0x0), u64(fiat.u1(x196))) + x199 := fiat.cmovznz_u64(fiat.u1(x198), x189, x181) + x200 := fiat.cmovznz_u64(fiat.u1(x198), x191, x183) + x201 := fiat.cmovznz_u64(fiat.u1(x198), x193, x185) + x202 := fiat.cmovznz_u64(fiat.u1(x198), x195, x187) + out1[0] = x199 + out1[1] = x200 + out1[2] = x201 + out1[3] = x202 +} diff --git a/core/crypto/_fiat/field_scalarp384r1/field.odin b/core/crypto/_fiat/field_scalarp384r1/field.odin new file mode 100644 index 000000000..cfc27f322 --- /dev/null +++ b/core/crypto/_fiat/field_scalarp384r1/field.odin @@ -0,0 +1,607 @@ +package field_scalarp384r1 + +import "core:crypto" +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" + +@(private, rodata) +TWO_256 := Montgomery_Domain_Field_Element{ + 17975668497346362272, + 12895982994901192340, + 1913828944324294218, + 902107514168524577, + 1374695839762142861, + 12098342389602539653, +} + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + crypto.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, +) -> bool { + ensure_contextless(len(out1) <= 64, "p384r1: invalid scalar input buffer") + + is_canonical := false + s_len := len(arg1) + switch { + case s_len < 48: + // No way this can be greater than the order. + fe_unchecked_set(out1, arg1) + is_canonical = true + case s_len == 48: + // There is no way for any 384-bit value to be >= 2n, so + // the reduction can be done by `src - n` and a conditional + // select based on the underflow. + // + // It is *extremely* unlikely that the reduction is actually + // needed. + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_unchecked_set_saturated(&tmp, arg1) + reduced := tmp + defer crypto.zero_explicit(&tmp, size_of(tmp)) + defer crypto.zero_explicit(&reduced, size_of(reduced)) + + borrow: u64 + reduced[0], borrow = bits.sub_u64(tmp[0], ELL[0], borrow) + reduced[1], borrow = bits.sub_u64(tmp[1], ELL[1], borrow) + reduced[2], borrow = bits.sub_u64(tmp[2], ELL[2], borrow) + reduced[3], borrow = bits.sub_u64(tmp[3], ELL[3], borrow) + reduced[4], borrow = bits.sub_u64(tmp[4], ELL[4], borrow) + reduced[5], borrow = bits.sub_u64(tmp[5], ELL[5], borrow) + need_reduced := subtle.u64_is_zero(borrow) + + fe_cond_select(&tmp, &tmp, &reduced, int(need_reduced)) + fe_to_montgomery(out1, &tmp) + + is_canonical = need_reduced == 0 + case: + // Use Frank Denis' trick, as documented by Filippo Valsorda + // at https://words.filippo.io/dispatches/wide-reduction/ + // + // "I represent the value as a+b*2^192+c*2^384" + // + // Since digests beyond 512-bits are unrealistic, we do + // "a+b*2^256" + + // Zero extend to 512-bits. + src_512: [64]byte + copy(src_512[64-s_len:], arg1) + defer crypto.zero_explicit(&src_512, size_of(src_512)) + + fe_unchecked_set(out1, src_512[32:]) // a + b: Montgomery_Domain_Field_Element + fe_unchecked_set(&b, src_512[:32]) // b + + fe_mul(&b, &b, &TWO_256) + fe_add(out1, out1, &b) + + fe_clear(&b) + } + + return !is_canonical +} + +@(private) +fe_is_canonical :: proc "contextless" (arg1: []byte) -> bool { + _, borrow := bits.sub_u64(ELL[0] - 1, endian.unchecked_get_u64be(arg1[40:]), 0) + _, borrow = bits.sub_u64(ELL[1], endian.unchecked_get_u64be(arg1[32:]), borrow) + _, borrow = bits.sub_u64(ELL[2], endian.unchecked_get_u64be(arg1[24:]), borrow) + _, borrow = bits.sub_u64(ELL[3], endian.unchecked_get_u64be(arg1[16:]), borrow) + _, borrow = bits.sub_u64(ELL[4], endian.unchecked_get_u64be(arg1[8:]), borrow) + _, borrow = bits.sub_u64(ELL[5], endian.unchecked_get_u64be(arg1[0:]), borrow) + return borrow == 0 +} + +@(private="file") +fe_unchecked_set_saturated :: proc "contextless" (out1: ^Non_Montgomery_Domain_Field_Element, arg1: []byte) { + out1[0] = endian.unchecked_get_u64be(arg1[40:]) + out1[1] = endian.unchecked_get_u64be(arg1[32:]) + out1[2] = endian.unchecked_get_u64be(arg1[24:]) + out1[3] = endian.unchecked_get_u64be(arg1[16:]) + out1[4] = endian.unchecked_get_u64be(arg1[8:]) + out1[5] = endian.unchecked_get_u64be(arg1[0:]) +} + +@(private) +fe_unchecked_set :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { + arg1_384: [48]byte + defer crypto.zero_explicit(&arg1_384, size_of(arg1_384)) + copy(arg1_384[48-len(arg1):], arg1) + + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_unchecked_set_saturated(&tmp, arg1_384[:]) + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_to_montgomery(out1, &tmp) +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 48, "p384r1: invalid scalar output buffer") + + tmp: Non_Montgomery_Domain_Field_Element = --- + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[40:], tmp[0]) + endian.unchecked_put_u64be(out1[32:], tmp[1]) + endian.unchecked_put_u64be(out1[24:], tmp[2]) + endian.unchecked_put_u64be(out1[16:], tmp[3]) + endian.unchecked_put_u64be(out1[8:], tmp[4]) + endian.unchecked_put_u64be(out1[0:], tmp[5]) + + crypto.zero_explicit(&tmp, size_of(tmp)) +} + +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element = --- + fe_sub(&tmp, arg1, arg2) + + is_eq := subtle.eq(fe_non_zero(&tmp), 0) + + fe_clear(&tmp) + + return int(is_eq) +} + +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element = --- + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 + out1[4] = 0 + out1[5] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + x5 := arg1[4] + x6 := arg1[5] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + x = (out1[4] ~ out2[4]) & mask + x5, y5 := out1[4] ~ x, out2[4] ~ x + x = (out1[5] ~ out2[5]) & mask + x6, y6 := out1[5] ~ x, out2[5] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 + out1[4], out2[4] = x5, y5 + out1[5], out2[5] = x6, y6 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^$T, + arg3: int, +) where T == Montgomery_Domain_Field_Element || T == Non_Montgomery_Domain_Field_Element { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + x5 := ((mask & arg2[4]) | ((~mask) & arg1[4])) + x6 := ((mask & arg2[5]) | ((~mask) & arg1[5])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} + +fe_pow2k :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_square(out1, out1) + } +} + +fe_inv :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _101 = _10 + _11 + // _111 = _10 + _101 + // _1001 = _10 + _111 + // _1011 = _10 + _1001 + // _1101 = _10 + _1011 + // _1111 = _10 + _1101 + // _11110 = 2*_1111 + // _11111 = 1 + _11110 + // _1111100 = _11111 << 2 + // i14 = _1111100 << 2 + // i26 = (i14 << 3 + _1111100) << 7 + i14 + // i42 = i26 << 15 + i26 + // x64 = i42 << 30 + i42 + _1111 + // x128 = x64 << 64 + x64 + // x192 = x128 << 64 + x64 + // x194 = x192 << 2 + _11 + // i225 = ((x194 << 6 + _111) << 3 + _11) << 7 + // i235 = 2*((_1101 + i225) << 6 + _1101) + 1 + // i258 = ((i235 << 11 + _11111) << 2 + 1) << 8 + // i269 = ((_1101 + i258) << 2 + _11) << 6 + _1011 + // i286 = ((i269 << 4 + _111) << 6 + _11111) << 5 + // i308 = ((_1011 + i286) << 10 + _1101) << 9 + _1101 + // i323 = ((i308 << 4 + _1011) << 6 + _1001) << 3 + // i340 = ((1 + i323) << 7 + _1011) << 7 + _101 + // i357 = ((i340 << 5 + _111) << 5 + _1111) << 5 + // i369 = ((_1011 + i357) << 4 + _1011) << 5 + _111 + // i387 = ((i369 << 3 + _11) << 7 + _11) << 6 + // i397 = ((_1011 + i387) << 4 + _101) << 3 + _11 + // i413 = ((i397 << 4 + _11) << 4 + _11) << 6 + // i427 = ((_101 + i413) << 5 + _101) << 6 + _1011 + // return (2*i427 + 1) << 4 + 1 + // + // Operations: 381 squares 53 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Note: Need to stash `arg1` (`xx`) in the case that `out1`/`arg1` alias, + // as `arg1` is used after `out1` has been altered. + t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, xx: Montgomery_Domain_Field_Element = ---, ---, ---, ---, ---, ---, ---, ---, ---, ---, arg1^ + + // Step 1: t3 = x^0x2 + fe_square(&t3, arg1) + + // Step 2: t1 = x^0x3 + fe_mul(&t1, arg1, &t3) + + // Step 3: t0 = x^0x5 + fe_mul(&t0, &t3, &t1) + + // Step 4: t2 = x^0x7 + fe_mul(&t2, &t3, &t0) + + // Step 5: t4 = x^0x9 + fe_mul(&t4, &t3, &t2) + + // Step 6: z = x^0xb + fe_mul(out1, &t3, &t4) + + // Step 7: t5 = x^0xd + fe_mul(&t5, &t3, out1) + + // Step 8: t3 = x^0xf + fe_mul(&t3, &t3, &t5) + + // Step 9: t6 = x^0x1e + fe_square(&t6, &t3) + + // Step 10: t6 = x^0x1f + fe_mul(&t6, &xx, &t6) + + // Step 12: t8 = x^0x7c + fe_pow2k(&t8, &t6, 2) + + // Step 14: t7 = x^0x1f0 + fe_pow2k(&t7, &t8, 2) + + // Step 17: t9 = x^0xf80 + fe_pow2k(&t9, &t7, 3) + + // Step 18: t8 = x^0xffc + fe_mul(&t8, &t8, &t9) + + // Step 25: t8 = x^0x7fe00 + fe_pow2k(&t8, &t8, 7) + + // Step 26: t7 = x^0x7fff0 + fe_mul(&t7, &t7, &t8) + + // Step 41: t8 = x^0x3fff80000 + fe_pow2k(&t8, &t7, 15) + + // Step 42: t7 = x^0x3fffffff0 + fe_mul(&t7, &t7, &t8) + + // Step 72: t8 = x^0xfffffffc00000000 + fe_pow2k(&t8, &t7, 30) + + // Step 73: t7 = x^0xfffffffffffffff0 + fe_mul(&t7, &t7, &t8) + + // Step 74: t7 = x^0xffffffffffffffff + fe_mul(&t7, &t3, &t7) + + // Step 138: t8 = x^0xffffffffffffffff0000000000000000 + fe_pow2k(&t8, &t7, 64) + + // Step 139: t8 = x^0xffffffffffffffffffffffffffffffff + fe_mul(&t8, &t7, &t8) + + // Step 203: t8 = x^0xffffffffffffffffffffffffffffffff0000000000000000 + fe_pow2k(&t8, &t8, 64) + + // Step 204: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t7, &t7, &t8) + + // Step 206: t7 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffc + fe_pow2k(&t7, &t7, 2) + + // Step 207: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff + fe_mul(&t7, &t1, &t7) + + // Step 213: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc0 + fe_pow2k(&t7, &t7, 6) + + // Step 214: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7 + fe_mul(&t7, &t2, &t7) + + // Step 217: t7 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe38 + fe_pow2k(&t7, &t7, 3) + + // Step 218: t7 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b + fe_mul(&t7, &t1, &t7) + + // Step 225: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d80 + fe_pow2k(&t7, &t7, 7) + + // Step 226: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d + fe_mul(&t7, &t5, &t7) + + // Step 232: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc76340 + fe_pow2k(&t7, &t7, 6) + + // Step 233: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d + fe_mul(&t7, &t5, &t7) + + // Step 234: t7 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69a + fe_square(&t7, &t7) + + // Step 235: t7 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b + fe_mul(&t7, &xx, &t7) + + // Step 246: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d800 + fe_pow2k(&t7, &t7, 11) + + // Step 247: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f + fe_mul(&t7, &t6, &t7) + + // Step 249: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607c + fe_pow2k(&t7, &t7, 2) + + // Step 250: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d + fe_mul(&t7, &xx, &t7) + + // Step 258: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d00 + fe_pow2k(&t7, &t7, 8) + + // Step 259: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0d + fe_mul(&t7, &t5, &t7) + + // Step 261: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f434 + fe_pow2k(&t7, &t7, 2) + + // Step 262: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f437 + fe_mul(&t7, &t1, &t7) + + // Step 268: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dc0 + fe_pow2k(&t7, &t7, 6) + + // Step 269: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb + fe_mul(&t7, out1, &t7) + + // Step 273: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb0 + fe_pow2k(&t7, &t7, 4) + + // Step 274: t7 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb7 + fe_mul(&t7, &t2, &t7) + + // Step 280: t7 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372dc0 + fe_pow2k(&t7, &t7, 6) + + // Step 281: t6 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf + fe_mul(&t6, &t6, &t7) + + // Step 286: t6 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbe0 + fe_pow2k(&t6, &t6, 5) + + // Step 287: t6 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb + fe_mul(&t6, out1, &t6) + + // Step 297: t6 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac00 + fe_pow2k(&t6, &t6, 10) + + // Step 298: t6 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d + fe_mul(&t6, &t5, &t6) + + // Step 307: t6 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a00 + fe_pow2k(&t6, &t6, 9) + + // Step 308: t5 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0d + fe_mul(&t5, &t5, &t6) + + // Step 312: t5 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0d0 + fe_pow2k(&t5, &t5, 4) + + // Step 313: t5 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db + fe_mul(&t5, out1, &t5) + + // Step 319: t5 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c0 + fe_pow2k(&t5, &t5, 6) + + // Step 320: t4 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c9 + fe_mul(&t4, &t4, &t5) + + // Step 323: t4 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b648 + fe_pow2k(&t4, &t4, 3) + + // Step 324: t4 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b649 + fe_mul(&t4, &xx, &t4) + + // Step 331: t4 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db2480 + fe_pow2k(&t4, &t4, 7) + + // Step 332: t4 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b + fe_mul(&t4, out1, &t4) + + // Step 339: t4 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d924580 + fe_pow2k(&t4, &t4, 7) + + // Step 340: t4 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d924585 + fe_mul(&t4, &t0, &t4) + + // Step 345: t4 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a0 + fe_pow2k(&t4, &t4, 5) + + // Step 346: t4 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a7 + fe_mul(&t4, &t2, &t4) + + // Step 351: t4 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614e0 + fe_pow2k(&t4, &t4, 5) + + // Step 352: t3 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614ef + fe_mul(&t3, &t3, &t4) + + // Step 357: t3 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29de0 + fe_pow2k(&t3, &t3, 5) + + // Step 358: t3 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29deb + fe_mul(&t3, out1, &t3) + + // Step 362: t3 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29deb0 + fe_pow2k(&t3, &t3, 4) + + // Step 363: t3 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb + fe_mul(&t3, out1, &t3) + + // Step 368: t3 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd760 + fe_pow2k(&t3, &t3, 5) + + // Step 369: t2 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd767 + fe_mul(&t2, &t2, &t3) + + // Step 372: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb38 + fe_pow2k(&t2, &t2, 3) + + // Step 373: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b + fe_mul(&t2, &t1, &t2) + + // Step 380: t2 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614ef5d9d80 + fe_pow2k(&t2, &t2, 7) + + // Step 381: t2 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614ef5d9d83 + fe_mul(&t2, &t1, &t2) + + // Step 387: t2 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760c0 + fe_pow2k(&t2, &t2, 6) + + // Step 388: t2 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb + fe_mul(&t2, out1, &t2) + + // Step 392: t2 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb0 + fe_pow2k(&t2, &t2, 4) + + // Step 393: t2 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb5 + fe_mul(&t2, &t0, &t2) + + // Step 396: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065a8 + fe_pow2k(&t2, &t2, 3) + + // Step 397: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065ab + fe_mul(&t2, &t1, &t2) + + // Step 401: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065ab0 + fe_pow2k(&t2, &t2, 4) + + // Step 402: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065ab3 + fe_mul(&t2, &t1, &t2) + + // Step 406: t2 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065ab30 + fe_pow2k(&t2, &t2, 4) + + // Step 407: t1 = x^0x3ffffffffffffffffffffffffffffffffffffffffffffffff1d8d3607d0dcb77d606836c922c29debb3b065ab33 + fe_mul(&t1, &t1, &t2) + + // Step 413: t1 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc0 + fe_pow2k(&t1, &t1, 6) + + // Step 414: t1 = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc5 + fe_mul(&t1, &t0, &t1) + + // Step 419: t1 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614ef5d9d832d5998a0 + fe_pow2k(&t1, &t1, 5) + + // Step 420: t0 = x^0x1ffffffffffffffffffffffffffffffffffffffffffffffff8ec69b03e86e5bbeb0341b6491614ef5d9d832d5998a5 + fe_mul(&t0, &t0, &t1) + + // Step 426: t0 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb56662940 + fe_pow2k(&t0, &t0, 6) + + // Step 427: z = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffe3b1a6c0fa1b96efac0d06d9245853bd76760cb5666294b + fe_mul(out1, out1, &t0) + + // Step 428: z = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc5296 + fe_square(out1, out1) + + // Step 429: z = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc5297 + fe_mul(out1, &xx, out1) + + // Step 433: z = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52970 + fe_pow2k(out1, out1, 4) + + // Step 434: z = x^0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52971 + fe_mul(out1, &xx, out1) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9, &xx}) +} diff --git a/core/crypto/_fiat/field_scalarp384r1/field64.odin b/core/crypto/_fiat/field_scalarp384r1/field64.odin new file mode 100644 index 000000000..ce29060e8 --- /dev/null +++ b/core/crypto/_fiat/field_scalarp384r1/field64.odin @@ -0,0 +1,1081 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_scalarp384r1 + +// The file provides arithmetic on the field Z/(2^384 - 1388124618062372383947042015309946732620727252194336364173) +// using a 64-bit Montgomery form internal representation. It is derived +// primarily from the machine generated Golang output from the fiat-crypto +// project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [6]u64{0xecec196accc52973, 0x581a0db248b0a77a, 0xc7634d81f4372ddf, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff} + +Montgomery_Domain_Field_Element :: distinct [6]u64 +Non_Montgomery_Domain_Field_Element :: distinct [6]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, arg2[5]) + x10, x9 := bits.mul_u64(x6, arg2[4]) + x12, x11 := bits.mul_u64(x6, arg2[3]) + x14, x13 := bits.mul_u64(x6, arg2[2]) + x16, x15 := bits.mul_u64(x6, arg2[1]) + x18, x17 := bits.mul_u64(x6, arg2[0]) + x19, x20 := bits.add_u64(x18, x15, u64(0x0)) + x21, x22 := bits.add_u64(x16, x13, u64(fiat.u1(x20))) + x23, x24 := bits.add_u64(x14, x11, u64(fiat.u1(x22))) + x25, x26 := bits.add_u64(x12, x9, u64(fiat.u1(x24))) + x27, x28 := bits.add_u64(x10, x7, u64(fiat.u1(x26))) + x29 := (u64(fiat.u1(x28)) + x8) + _, x30 := bits.mul_u64(x17, 0x6ed46089e88fdc45) + x33, x32 := bits.mul_u64(x30, 0xffffffffffffffff) + x35, x34 := bits.mul_u64(x30, 0xffffffffffffffff) + x37, x36 := bits.mul_u64(x30, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x30, 0xc7634d81f4372ddf) + x41, x40 := bits.mul_u64(x30, 0x581a0db248b0a77a) + x43, x42 := bits.mul_u64(x30, 0xecec196accc52973) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + x46, x47 := bits.add_u64(x41, x38, u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x39, x36, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x37, x34, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x35, x32, u64(fiat.u1(x51))) + x54 := (u64(fiat.u1(x53)) + x33) + _, x56 := bits.add_u64(x17, x42, u64(0x0)) + x57, x58 := bits.add_u64(x19, x44, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x21, x46, u64(fiat.u1(x58))) + x61, x62 := bits.add_u64(x23, x48, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x25, x50, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x27, x52, u64(fiat.u1(x64))) + x67, x68 := bits.add_u64(x29, x54, u64(fiat.u1(x66))) + x70, x69 := bits.mul_u64(x1, arg2[5]) + x72, x71 := bits.mul_u64(x1, arg2[4]) + x74, x73 := bits.mul_u64(x1, arg2[3]) + x76, x75 := bits.mul_u64(x1, arg2[2]) + x78, x77 := bits.mul_u64(x1, arg2[1]) + x80, x79 := bits.mul_u64(x1, arg2[0]) + x81, x82 := bits.add_u64(x80, x77, u64(0x0)) + x83, x84 := bits.add_u64(x78, x75, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x76, x73, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x74, x71, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x72, x69, u64(fiat.u1(x88))) + x91 := (u64(fiat.u1(x90)) + x70) + x92, x93 := bits.add_u64(x57, x79, u64(0x0)) + x94, x95 := bits.add_u64(x59, x81, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x61, x83, u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x63, x85, u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x65, x87, u64(fiat.u1(x99))) + x102, x103 := bits.add_u64(x67, x89, u64(fiat.u1(x101))) + x104, x105 := bits.add_u64(u64(fiat.u1(x68)), x91, u64(fiat.u1(x103))) + _, x106 := bits.mul_u64(x92, 0x6ed46089e88fdc45) + x109, x108 := bits.mul_u64(x106, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x106, 0xffffffffffffffff) + x113, x112 := bits.mul_u64(x106, 0xffffffffffffffff) + x115, x114 := bits.mul_u64(x106, 0xc7634d81f4372ddf) + x117, x116 := bits.mul_u64(x106, 0x581a0db248b0a77a) + x119, x118 := bits.mul_u64(x106, 0xecec196accc52973) + x120, x121 := bits.add_u64(x119, x116, u64(0x0)) + x122, x123 := bits.add_u64(x117, x114, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x115, x112, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x113, x110, u64(fiat.u1(x125))) + x128, x129 := bits.add_u64(x111, x108, u64(fiat.u1(x127))) + x130 := (u64(fiat.u1(x129)) + x109) + _, x132 := bits.add_u64(x92, x118, u64(0x0)) + x133, x134 := bits.add_u64(x94, x120, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x96, x122, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x98, x124, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x100, x126, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x102, x128, u64(fiat.u1(x140))) + x143, x144 := bits.add_u64(x104, x130, u64(fiat.u1(x142))) + x145 := (u64(fiat.u1(x144)) + u64(fiat.u1(x105))) + x147, x146 := bits.mul_u64(x2, arg2[5]) + x149, x148 := bits.mul_u64(x2, arg2[4]) + x151, x150 := bits.mul_u64(x2, arg2[3]) + x153, x152 := bits.mul_u64(x2, arg2[2]) + x155, x154 := bits.mul_u64(x2, arg2[1]) + x157, x156 := bits.mul_u64(x2, arg2[0]) + x158, x159 := bits.add_u64(x157, x154, u64(0x0)) + x160, x161 := bits.add_u64(x155, x152, u64(fiat.u1(x159))) + x162, x163 := bits.add_u64(x153, x150, u64(fiat.u1(x161))) + x164, x165 := bits.add_u64(x151, x148, u64(fiat.u1(x163))) + x166, x167 := bits.add_u64(x149, x146, u64(fiat.u1(x165))) + x168 := (u64(fiat.u1(x167)) + x147) + x169, x170 := bits.add_u64(x133, x156, u64(0x0)) + x171, x172 := bits.add_u64(x135, x158, u64(fiat.u1(x170))) + x173, x174 := bits.add_u64(x137, x160, u64(fiat.u1(x172))) + x175, x176 := bits.add_u64(x139, x162, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x141, x164, u64(fiat.u1(x176))) + x179, x180 := bits.add_u64(x143, x166, u64(fiat.u1(x178))) + x181, x182 := bits.add_u64(x145, x168, u64(fiat.u1(x180))) + _, x183 := bits.mul_u64(x169, 0x6ed46089e88fdc45) + x186, x185 := bits.mul_u64(x183, 0xffffffffffffffff) + x188, x187 := bits.mul_u64(x183, 0xffffffffffffffff) + x190, x189 := bits.mul_u64(x183, 0xffffffffffffffff) + x192, x191 := bits.mul_u64(x183, 0xc7634d81f4372ddf) + x194, x193 := bits.mul_u64(x183, 0x581a0db248b0a77a) + x196, x195 := bits.mul_u64(x183, 0xecec196accc52973) + x197, x198 := bits.add_u64(x196, x193, u64(0x0)) + x199, x200 := bits.add_u64(x194, x191, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x192, x189, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x190, x187, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x188, x185, u64(fiat.u1(x204))) + x207 := (u64(fiat.u1(x206)) + x186) + _, x209 := bits.add_u64(x169, x195, u64(0x0)) + x210, x211 := bits.add_u64(x171, x197, u64(fiat.u1(x209))) + x212, x213 := bits.add_u64(x173, x199, u64(fiat.u1(x211))) + x214, x215 := bits.add_u64(x175, x201, u64(fiat.u1(x213))) + x216, x217 := bits.add_u64(x177, x203, u64(fiat.u1(x215))) + x218, x219 := bits.add_u64(x179, x205, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x181, x207, u64(fiat.u1(x219))) + x222 := (u64(fiat.u1(x221)) + u64(fiat.u1(x182))) + x224, x223 := bits.mul_u64(x3, arg2[5]) + x226, x225 := bits.mul_u64(x3, arg2[4]) + x228, x227 := bits.mul_u64(x3, arg2[3]) + x230, x229 := bits.mul_u64(x3, arg2[2]) + x232, x231 := bits.mul_u64(x3, arg2[1]) + x234, x233 := bits.mul_u64(x3, arg2[0]) + x235, x236 := bits.add_u64(x234, x231, u64(0x0)) + x237, x238 := bits.add_u64(x232, x229, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x230, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x228, x225, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x226, x223, u64(fiat.u1(x242))) + x245 := (u64(fiat.u1(x244)) + x224) + x246, x247 := bits.add_u64(x210, x233, u64(0x0)) + x248, x249 := bits.add_u64(x212, x235, u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x214, x237, u64(fiat.u1(x249))) + x252, x253 := bits.add_u64(x216, x239, u64(fiat.u1(x251))) + x254, x255 := bits.add_u64(x218, x241, u64(fiat.u1(x253))) + x256, x257 := bits.add_u64(x220, x243, u64(fiat.u1(x255))) + x258, x259 := bits.add_u64(x222, x245, u64(fiat.u1(x257))) + _, x260 := bits.mul_u64(x246, 0x6ed46089e88fdc45) + x263, x262 := bits.mul_u64(x260, 0xffffffffffffffff) + x265, x264 := bits.mul_u64(x260, 0xffffffffffffffff) + x267, x266 := bits.mul_u64(x260, 0xffffffffffffffff) + x269, x268 := bits.mul_u64(x260, 0xc7634d81f4372ddf) + x271, x270 := bits.mul_u64(x260, 0x581a0db248b0a77a) + x273, x272 := bits.mul_u64(x260, 0xecec196accc52973) + x274, x275 := bits.add_u64(x273, x270, u64(0x0)) + x276, x277 := bits.add_u64(x271, x268, u64(fiat.u1(x275))) + x278, x279 := bits.add_u64(x269, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x267, x264, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x265, x262, u64(fiat.u1(x281))) + x284 := (u64(fiat.u1(x283)) + x263) + _, x286 := bits.add_u64(x246, x272, u64(0x0)) + x287, x288 := bits.add_u64(x248, x274, u64(fiat.u1(x286))) + x289, x290 := bits.add_u64(x250, x276, u64(fiat.u1(x288))) + x291, x292 := bits.add_u64(x252, x278, u64(fiat.u1(x290))) + x293, x294 := bits.add_u64(x254, x280, u64(fiat.u1(x292))) + x295, x296 := bits.add_u64(x256, x282, u64(fiat.u1(x294))) + x297, x298 := bits.add_u64(x258, x284, u64(fiat.u1(x296))) + x299 := (u64(fiat.u1(x298)) + u64(fiat.u1(x259))) + x301, x300 := bits.mul_u64(x4, arg2[5]) + x303, x302 := bits.mul_u64(x4, arg2[4]) + x305, x304 := bits.mul_u64(x4, arg2[3]) + x307, x306 := bits.mul_u64(x4, arg2[2]) + x309, x308 := bits.mul_u64(x4, arg2[1]) + x311, x310 := bits.mul_u64(x4, arg2[0]) + x312, x313 := bits.add_u64(x311, x308, u64(0x0)) + x314, x315 := bits.add_u64(x309, x306, u64(fiat.u1(x313))) + x316, x317 := bits.add_u64(x307, x304, u64(fiat.u1(x315))) + x318, x319 := bits.add_u64(x305, x302, u64(fiat.u1(x317))) + x320, x321 := bits.add_u64(x303, x300, u64(fiat.u1(x319))) + x322 := (u64(fiat.u1(x321)) + x301) + x323, x324 := bits.add_u64(x287, x310, u64(0x0)) + x325, x326 := bits.add_u64(x289, x312, u64(fiat.u1(x324))) + x327, x328 := bits.add_u64(x291, x314, u64(fiat.u1(x326))) + x329, x330 := bits.add_u64(x293, x316, u64(fiat.u1(x328))) + x331, x332 := bits.add_u64(x295, x318, u64(fiat.u1(x330))) + x333, x334 := bits.add_u64(x297, x320, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x299, x322, u64(fiat.u1(x334))) + _, x337 := bits.mul_u64(x323, 0x6ed46089e88fdc45) + x340, x339 := bits.mul_u64(x337, 0xffffffffffffffff) + x342, x341 := bits.mul_u64(x337, 0xffffffffffffffff) + x344, x343 := bits.mul_u64(x337, 0xffffffffffffffff) + x346, x345 := bits.mul_u64(x337, 0xc7634d81f4372ddf) + x348, x347 := bits.mul_u64(x337, 0x581a0db248b0a77a) + x350, x349 := bits.mul_u64(x337, 0xecec196accc52973) + x351, x352 := bits.add_u64(x350, x347, u64(0x0)) + x353, x354 := bits.add_u64(x348, x345, u64(fiat.u1(x352))) + x355, x356 := bits.add_u64(x346, x343, u64(fiat.u1(x354))) + x357, x358 := bits.add_u64(x344, x341, u64(fiat.u1(x356))) + x359, x360 := bits.add_u64(x342, x339, u64(fiat.u1(x358))) + x361 := (u64(fiat.u1(x360)) + x340) + _, x363 := bits.add_u64(x323, x349, u64(0x0)) + x364, x365 := bits.add_u64(x325, x351, u64(fiat.u1(x363))) + x366, x367 := bits.add_u64(x327, x353, u64(fiat.u1(x365))) + x368, x369 := bits.add_u64(x329, x355, u64(fiat.u1(x367))) + x370, x371 := bits.add_u64(x331, x357, u64(fiat.u1(x369))) + x372, x373 := bits.add_u64(x333, x359, u64(fiat.u1(x371))) + x374, x375 := bits.add_u64(x335, x361, u64(fiat.u1(x373))) + x376 := (u64(fiat.u1(x375)) + u64(fiat.u1(x336))) + x378, x377 := bits.mul_u64(x5, arg2[5]) + x380, x379 := bits.mul_u64(x5, arg2[4]) + x382, x381 := bits.mul_u64(x5, arg2[3]) + x384, x383 := bits.mul_u64(x5, arg2[2]) + x386, x385 := bits.mul_u64(x5, arg2[1]) + x388, x387 := bits.mul_u64(x5, arg2[0]) + x389, x390 := bits.add_u64(x388, x385, u64(0x0)) + x391, x392 := bits.add_u64(x386, x383, u64(fiat.u1(x390))) + x393, x394 := bits.add_u64(x384, x381, u64(fiat.u1(x392))) + x395, x396 := bits.add_u64(x382, x379, u64(fiat.u1(x394))) + x397, x398 := bits.add_u64(x380, x377, u64(fiat.u1(x396))) + x399 := (u64(fiat.u1(x398)) + x378) + x400, x401 := bits.add_u64(x364, x387, u64(0x0)) + x402, x403 := bits.add_u64(x366, x389, u64(fiat.u1(x401))) + x404, x405 := bits.add_u64(x368, x391, u64(fiat.u1(x403))) + x406, x407 := bits.add_u64(x370, x393, u64(fiat.u1(x405))) + x408, x409 := bits.add_u64(x372, x395, u64(fiat.u1(x407))) + x410, x411 := bits.add_u64(x374, x397, u64(fiat.u1(x409))) + x412, x413 := bits.add_u64(x376, x399, u64(fiat.u1(x411))) + _, x414 := bits.mul_u64(x400, 0x6ed46089e88fdc45) + x417, x416 := bits.mul_u64(x414, 0xffffffffffffffff) + x419, x418 := bits.mul_u64(x414, 0xffffffffffffffff) + x421, x420 := bits.mul_u64(x414, 0xffffffffffffffff) + x423, x422 := bits.mul_u64(x414, 0xc7634d81f4372ddf) + x425, x424 := bits.mul_u64(x414, 0x581a0db248b0a77a) + x427, x426 := bits.mul_u64(x414, 0xecec196accc52973) + x428, x429 := bits.add_u64(x427, x424, u64(0x0)) + x430, x431 := bits.add_u64(x425, x422, u64(fiat.u1(x429))) + x432, x433 := bits.add_u64(x423, x420, u64(fiat.u1(x431))) + x434, x435 := bits.add_u64(x421, x418, u64(fiat.u1(x433))) + x436, x437 := bits.add_u64(x419, x416, u64(fiat.u1(x435))) + x438 := (u64(fiat.u1(x437)) + x417) + _, x440 := bits.add_u64(x400, x426, u64(0x0)) + x441, x442 := bits.add_u64(x402, x428, u64(fiat.u1(x440))) + x443, x444 := bits.add_u64(x404, x430, u64(fiat.u1(x442))) + x445, x446 := bits.add_u64(x406, x432, u64(fiat.u1(x444))) + x447, x448 := bits.add_u64(x408, x434, u64(fiat.u1(x446))) + x449, x450 := bits.add_u64(x410, x436, u64(fiat.u1(x448))) + x451, x452 := bits.add_u64(x412, x438, u64(fiat.u1(x450))) + x453 := (u64(fiat.u1(x452)) + u64(fiat.u1(x413))) + x454, x455 := bits.sub_u64(x441, 0xecec196accc52973, u64(0x0)) + x456, x457 := bits.sub_u64(x443, 0x581a0db248b0a77a, u64(fiat.u1(x455))) + x458, x459 := bits.sub_u64(x445, 0xc7634d81f4372ddf, u64(fiat.u1(x457))) + x460, x461 := bits.sub_u64(x447, 0xffffffffffffffff, u64(fiat.u1(x459))) + x462, x463 := bits.sub_u64(x449, 0xffffffffffffffff, u64(fiat.u1(x461))) + x464, x465 := bits.sub_u64(x451, 0xffffffffffffffff, u64(fiat.u1(x463))) + _, x467 := bits.sub_u64(x453, u64(0x0), u64(fiat.u1(x465))) + x468 := fiat.cmovznz_u64(fiat.u1(x467), x454, x441) + x469 := fiat.cmovznz_u64(fiat.u1(x467), x456, x443) + x470 := fiat.cmovznz_u64(fiat.u1(x467), x458, x445) + x471 := fiat.cmovznz_u64(fiat.u1(x467), x460, x447) + x472 := fiat.cmovznz_u64(fiat.u1(x467), x462, x449) + x473 := fiat.cmovznz_u64(fiat.u1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, arg1[5]) + x10, x9 := bits.mul_u64(x6, arg1[4]) + x12, x11 := bits.mul_u64(x6, arg1[3]) + x14, x13 := bits.mul_u64(x6, arg1[2]) + x16, x15 := bits.mul_u64(x6, arg1[1]) + x18, x17 := bits.mul_u64(x6, arg1[0]) + x19, x20 := bits.add_u64(x18, x15, u64(0x0)) + x21, x22 := bits.add_u64(x16, x13, u64(fiat.u1(x20))) + x23, x24 := bits.add_u64(x14, x11, u64(fiat.u1(x22))) + x25, x26 := bits.add_u64(x12, x9, u64(fiat.u1(x24))) + x27, x28 := bits.add_u64(x10, x7, u64(fiat.u1(x26))) + x29 := (u64(fiat.u1(x28)) + x8) + _, x30 := bits.mul_u64(x17, 0x6ed46089e88fdc45) + x33, x32 := bits.mul_u64(x30, 0xffffffffffffffff) + x35, x34 := bits.mul_u64(x30, 0xffffffffffffffff) + x37, x36 := bits.mul_u64(x30, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x30, 0xc7634d81f4372ddf) + x41, x40 := bits.mul_u64(x30, 0x581a0db248b0a77a) + x43, x42 := bits.mul_u64(x30, 0xecec196accc52973) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + x46, x47 := bits.add_u64(x41, x38, u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x39, x36, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x37, x34, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x35, x32, u64(fiat.u1(x51))) + x54 := (u64(fiat.u1(x53)) + x33) + _, x56 := bits.add_u64(x17, x42, u64(0x0)) + x57, x58 := bits.add_u64(x19, x44, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x21, x46, u64(fiat.u1(x58))) + x61, x62 := bits.add_u64(x23, x48, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x25, x50, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x27, x52, u64(fiat.u1(x64))) + x67, x68 := bits.add_u64(x29, x54, u64(fiat.u1(x66))) + x70, x69 := bits.mul_u64(x1, arg1[5]) + x72, x71 := bits.mul_u64(x1, arg1[4]) + x74, x73 := bits.mul_u64(x1, arg1[3]) + x76, x75 := bits.mul_u64(x1, arg1[2]) + x78, x77 := bits.mul_u64(x1, arg1[1]) + x80, x79 := bits.mul_u64(x1, arg1[0]) + x81, x82 := bits.add_u64(x80, x77, u64(0x0)) + x83, x84 := bits.add_u64(x78, x75, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x76, x73, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x74, x71, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x72, x69, u64(fiat.u1(x88))) + x91 := (u64(fiat.u1(x90)) + x70) + x92, x93 := bits.add_u64(x57, x79, u64(0x0)) + x94, x95 := bits.add_u64(x59, x81, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x61, x83, u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x63, x85, u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x65, x87, u64(fiat.u1(x99))) + x102, x103 := bits.add_u64(x67, x89, u64(fiat.u1(x101))) + x104, x105 := bits.add_u64(u64(fiat.u1(x68)), x91, u64(fiat.u1(x103))) + _, x106 := bits.mul_u64(x92, 0x6ed46089e88fdc45) + x109, x108 := bits.mul_u64(x106, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x106, 0xffffffffffffffff) + x113, x112 := bits.mul_u64(x106, 0xffffffffffffffff) + x115, x114 := bits.mul_u64(x106, 0xc7634d81f4372ddf) + x117, x116 := bits.mul_u64(x106, 0x581a0db248b0a77a) + x119, x118 := bits.mul_u64(x106, 0xecec196accc52973) + x120, x121 := bits.add_u64(x119, x116, u64(0x0)) + x122, x123 := bits.add_u64(x117, x114, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x115, x112, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x113, x110, u64(fiat.u1(x125))) + x128, x129 := bits.add_u64(x111, x108, u64(fiat.u1(x127))) + x130 := (u64(fiat.u1(x129)) + x109) + _, x132 := bits.add_u64(x92, x118, u64(0x0)) + x133, x134 := bits.add_u64(x94, x120, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x96, x122, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x98, x124, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x100, x126, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x102, x128, u64(fiat.u1(x140))) + x143, x144 := bits.add_u64(x104, x130, u64(fiat.u1(x142))) + x145 := (u64(fiat.u1(x144)) + u64(fiat.u1(x105))) + x147, x146 := bits.mul_u64(x2, arg1[5]) + x149, x148 := bits.mul_u64(x2, arg1[4]) + x151, x150 := bits.mul_u64(x2, arg1[3]) + x153, x152 := bits.mul_u64(x2, arg1[2]) + x155, x154 := bits.mul_u64(x2, arg1[1]) + x157, x156 := bits.mul_u64(x2, arg1[0]) + x158, x159 := bits.add_u64(x157, x154, u64(0x0)) + x160, x161 := bits.add_u64(x155, x152, u64(fiat.u1(x159))) + x162, x163 := bits.add_u64(x153, x150, u64(fiat.u1(x161))) + x164, x165 := bits.add_u64(x151, x148, u64(fiat.u1(x163))) + x166, x167 := bits.add_u64(x149, x146, u64(fiat.u1(x165))) + x168 := (u64(fiat.u1(x167)) + x147) + x169, x170 := bits.add_u64(x133, x156, u64(0x0)) + x171, x172 := bits.add_u64(x135, x158, u64(fiat.u1(x170))) + x173, x174 := bits.add_u64(x137, x160, u64(fiat.u1(x172))) + x175, x176 := bits.add_u64(x139, x162, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x141, x164, u64(fiat.u1(x176))) + x179, x180 := bits.add_u64(x143, x166, u64(fiat.u1(x178))) + x181, x182 := bits.add_u64(x145, x168, u64(fiat.u1(x180))) + _, x183 := bits.mul_u64(x169, 0x6ed46089e88fdc45) + x186, x185 := bits.mul_u64(x183, 0xffffffffffffffff) + x188, x187 := bits.mul_u64(x183, 0xffffffffffffffff) + x190, x189 := bits.mul_u64(x183, 0xffffffffffffffff) + x192, x191 := bits.mul_u64(x183, 0xc7634d81f4372ddf) + x194, x193 := bits.mul_u64(x183, 0x581a0db248b0a77a) + x196, x195 := bits.mul_u64(x183, 0xecec196accc52973) + x197, x198 := bits.add_u64(x196, x193, u64(0x0)) + x199, x200 := bits.add_u64(x194, x191, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x192, x189, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x190, x187, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x188, x185, u64(fiat.u1(x204))) + x207 := (u64(fiat.u1(x206)) + x186) + _, x209 := bits.add_u64(x169, x195, u64(0x0)) + x210, x211 := bits.add_u64(x171, x197, u64(fiat.u1(x209))) + x212, x213 := bits.add_u64(x173, x199, u64(fiat.u1(x211))) + x214, x215 := bits.add_u64(x175, x201, u64(fiat.u1(x213))) + x216, x217 := bits.add_u64(x177, x203, u64(fiat.u1(x215))) + x218, x219 := bits.add_u64(x179, x205, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x181, x207, u64(fiat.u1(x219))) + x222 := (u64(fiat.u1(x221)) + u64(fiat.u1(x182))) + x224, x223 := bits.mul_u64(x3, arg1[5]) + x226, x225 := bits.mul_u64(x3, arg1[4]) + x228, x227 := bits.mul_u64(x3, arg1[3]) + x230, x229 := bits.mul_u64(x3, arg1[2]) + x232, x231 := bits.mul_u64(x3, arg1[1]) + x234, x233 := bits.mul_u64(x3, arg1[0]) + x235, x236 := bits.add_u64(x234, x231, u64(0x0)) + x237, x238 := bits.add_u64(x232, x229, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x230, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x228, x225, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x226, x223, u64(fiat.u1(x242))) + x245 := (u64(fiat.u1(x244)) + x224) + x246, x247 := bits.add_u64(x210, x233, u64(0x0)) + x248, x249 := bits.add_u64(x212, x235, u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x214, x237, u64(fiat.u1(x249))) + x252, x253 := bits.add_u64(x216, x239, u64(fiat.u1(x251))) + x254, x255 := bits.add_u64(x218, x241, u64(fiat.u1(x253))) + x256, x257 := bits.add_u64(x220, x243, u64(fiat.u1(x255))) + x258, x259 := bits.add_u64(x222, x245, u64(fiat.u1(x257))) + _, x260 := bits.mul_u64(x246, 0x6ed46089e88fdc45) + x263, x262 := bits.mul_u64(x260, 0xffffffffffffffff) + x265, x264 := bits.mul_u64(x260, 0xffffffffffffffff) + x267, x266 := bits.mul_u64(x260, 0xffffffffffffffff) + x269, x268 := bits.mul_u64(x260, 0xc7634d81f4372ddf) + x271, x270 := bits.mul_u64(x260, 0x581a0db248b0a77a) + x273, x272 := bits.mul_u64(x260, 0xecec196accc52973) + x274, x275 := bits.add_u64(x273, x270, u64(0x0)) + x276, x277 := bits.add_u64(x271, x268, u64(fiat.u1(x275))) + x278, x279 := bits.add_u64(x269, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x267, x264, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x265, x262, u64(fiat.u1(x281))) + x284 := (u64(fiat.u1(x283)) + x263) + _, x286 := bits.add_u64(x246, x272, u64(0x0)) + x287, x288 := bits.add_u64(x248, x274, u64(fiat.u1(x286))) + x289, x290 := bits.add_u64(x250, x276, u64(fiat.u1(x288))) + x291, x292 := bits.add_u64(x252, x278, u64(fiat.u1(x290))) + x293, x294 := bits.add_u64(x254, x280, u64(fiat.u1(x292))) + x295, x296 := bits.add_u64(x256, x282, u64(fiat.u1(x294))) + x297, x298 := bits.add_u64(x258, x284, u64(fiat.u1(x296))) + x299 := (u64(fiat.u1(x298)) + u64(fiat.u1(x259))) + x301, x300 := bits.mul_u64(x4, arg1[5]) + x303, x302 := bits.mul_u64(x4, arg1[4]) + x305, x304 := bits.mul_u64(x4, arg1[3]) + x307, x306 := bits.mul_u64(x4, arg1[2]) + x309, x308 := bits.mul_u64(x4, arg1[1]) + x311, x310 := bits.mul_u64(x4, arg1[0]) + x312, x313 := bits.add_u64(x311, x308, u64(0x0)) + x314, x315 := bits.add_u64(x309, x306, u64(fiat.u1(x313))) + x316, x317 := bits.add_u64(x307, x304, u64(fiat.u1(x315))) + x318, x319 := bits.add_u64(x305, x302, u64(fiat.u1(x317))) + x320, x321 := bits.add_u64(x303, x300, u64(fiat.u1(x319))) + x322 := (u64(fiat.u1(x321)) + x301) + x323, x324 := bits.add_u64(x287, x310, u64(0x0)) + x325, x326 := bits.add_u64(x289, x312, u64(fiat.u1(x324))) + x327, x328 := bits.add_u64(x291, x314, u64(fiat.u1(x326))) + x329, x330 := bits.add_u64(x293, x316, u64(fiat.u1(x328))) + x331, x332 := bits.add_u64(x295, x318, u64(fiat.u1(x330))) + x333, x334 := bits.add_u64(x297, x320, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x299, x322, u64(fiat.u1(x334))) + _, x337 := bits.mul_u64(x323, 0x6ed46089e88fdc45) + x340, x339 := bits.mul_u64(x337, 0xffffffffffffffff) + x342, x341 := bits.mul_u64(x337, 0xffffffffffffffff) + x344, x343 := bits.mul_u64(x337, 0xffffffffffffffff) + x346, x345 := bits.mul_u64(x337, 0xc7634d81f4372ddf) + x348, x347 := bits.mul_u64(x337, 0x581a0db248b0a77a) + x350, x349 := bits.mul_u64(x337, 0xecec196accc52973) + x351, x352 := bits.add_u64(x350, x347, u64(0x0)) + x353, x354 := bits.add_u64(x348, x345, u64(fiat.u1(x352))) + x355, x356 := bits.add_u64(x346, x343, u64(fiat.u1(x354))) + x357, x358 := bits.add_u64(x344, x341, u64(fiat.u1(x356))) + x359, x360 := bits.add_u64(x342, x339, u64(fiat.u1(x358))) + x361 := (u64(fiat.u1(x360)) + x340) + _, x363 := bits.add_u64(x323, x349, u64(0x0)) + x364, x365 := bits.add_u64(x325, x351, u64(fiat.u1(x363))) + x366, x367 := bits.add_u64(x327, x353, u64(fiat.u1(x365))) + x368, x369 := bits.add_u64(x329, x355, u64(fiat.u1(x367))) + x370, x371 := bits.add_u64(x331, x357, u64(fiat.u1(x369))) + x372, x373 := bits.add_u64(x333, x359, u64(fiat.u1(x371))) + x374, x375 := bits.add_u64(x335, x361, u64(fiat.u1(x373))) + x376 := (u64(fiat.u1(x375)) + u64(fiat.u1(x336))) + x378, x377 := bits.mul_u64(x5, arg1[5]) + x380, x379 := bits.mul_u64(x5, arg1[4]) + x382, x381 := bits.mul_u64(x5, arg1[3]) + x384, x383 := bits.mul_u64(x5, arg1[2]) + x386, x385 := bits.mul_u64(x5, arg1[1]) + x388, x387 := bits.mul_u64(x5, arg1[0]) + x389, x390 := bits.add_u64(x388, x385, u64(0x0)) + x391, x392 := bits.add_u64(x386, x383, u64(fiat.u1(x390))) + x393, x394 := bits.add_u64(x384, x381, u64(fiat.u1(x392))) + x395, x396 := bits.add_u64(x382, x379, u64(fiat.u1(x394))) + x397, x398 := bits.add_u64(x380, x377, u64(fiat.u1(x396))) + x399 := (u64(fiat.u1(x398)) + x378) + x400, x401 := bits.add_u64(x364, x387, u64(0x0)) + x402, x403 := bits.add_u64(x366, x389, u64(fiat.u1(x401))) + x404, x405 := bits.add_u64(x368, x391, u64(fiat.u1(x403))) + x406, x407 := bits.add_u64(x370, x393, u64(fiat.u1(x405))) + x408, x409 := bits.add_u64(x372, x395, u64(fiat.u1(x407))) + x410, x411 := bits.add_u64(x374, x397, u64(fiat.u1(x409))) + x412, x413 := bits.add_u64(x376, x399, u64(fiat.u1(x411))) + _, x414 := bits.mul_u64(x400, 0x6ed46089e88fdc45) + x417, x416 := bits.mul_u64(x414, 0xffffffffffffffff) + x419, x418 := bits.mul_u64(x414, 0xffffffffffffffff) + x421, x420 := bits.mul_u64(x414, 0xffffffffffffffff) + x423, x422 := bits.mul_u64(x414, 0xc7634d81f4372ddf) + x425, x424 := bits.mul_u64(x414, 0x581a0db248b0a77a) + x427, x426 := bits.mul_u64(x414, 0xecec196accc52973) + x428, x429 := bits.add_u64(x427, x424, u64(0x0)) + x430, x431 := bits.add_u64(x425, x422, u64(fiat.u1(x429))) + x432, x433 := bits.add_u64(x423, x420, u64(fiat.u1(x431))) + x434, x435 := bits.add_u64(x421, x418, u64(fiat.u1(x433))) + x436, x437 := bits.add_u64(x419, x416, u64(fiat.u1(x435))) + x438 := (u64(fiat.u1(x437)) + x417) + _, x440 := bits.add_u64(x400, x426, u64(0x0)) + x441, x442 := bits.add_u64(x402, x428, u64(fiat.u1(x440))) + x443, x444 := bits.add_u64(x404, x430, u64(fiat.u1(x442))) + x445, x446 := bits.add_u64(x406, x432, u64(fiat.u1(x444))) + x447, x448 := bits.add_u64(x408, x434, u64(fiat.u1(x446))) + x449, x450 := bits.add_u64(x410, x436, u64(fiat.u1(x448))) + x451, x452 := bits.add_u64(x412, x438, u64(fiat.u1(x450))) + x453 := (u64(fiat.u1(x452)) + u64(fiat.u1(x413))) + x454, x455 := bits.sub_u64(x441, 0xecec196accc52973, u64(0x0)) + x456, x457 := bits.sub_u64(x443, 0x581a0db248b0a77a, u64(fiat.u1(x455))) + x458, x459 := bits.sub_u64(x445, 0xc7634d81f4372ddf, u64(fiat.u1(x457))) + x460, x461 := bits.sub_u64(x447, 0xffffffffffffffff, u64(fiat.u1(x459))) + x462, x463 := bits.sub_u64(x449, 0xffffffffffffffff, u64(fiat.u1(x461))) + x464, x465 := bits.sub_u64(x451, 0xffffffffffffffff, u64(fiat.u1(x463))) + _, x467 := bits.sub_u64(x453, u64(0x0), u64(fiat.u1(x465))) + x468 := fiat.cmovznz_u64(fiat.u1(x467), x454, x441) + x469 := fiat.cmovznz_u64(fiat.u1(x467), x456, x443) + x470 := fiat.cmovznz_u64(fiat.u1(x467), x458, x445) + x471 := fiat.cmovznz_u64(fiat.u1(x467), x460, x447) + x472 := fiat.cmovznz_u64(fiat.u1(x467), x462, x449) + x473 := fiat.cmovznz_u64(fiat.u1(x467), x464, x451) + out1[0] = x468 + out1[1] = x469 + out1[2] = x470 + out1[3] = x471 + out1[4] = x472 + out1[5] = x473 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.add_u64(arg1[4], arg2[4], u64(fiat.u1(x8))) + x11, x12 := bits.add_u64(arg1[5], arg2[5], u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x1, 0xecec196accc52973, u64(0x0)) + x15, x16 := bits.sub_u64(x3, 0x581a0db248b0a77a, u64(fiat.u1(x14))) + x17, x18 := bits.sub_u64(x5, 0xc7634d81f4372ddf, u64(fiat.u1(x16))) + x19, x20 := bits.sub_u64(x7, 0xffffffffffffffff, u64(fiat.u1(x18))) + x21, x22 := bits.sub_u64(x9, 0xffffffffffffffff, u64(fiat.u1(x20))) + x23, x24 := bits.sub_u64(x11, 0xffffffffffffffff, u64(fiat.u1(x22))) + _, x26 := bits.sub_u64(u64(fiat.u1(x12)), u64(0x0), u64(fiat.u1(x24))) + x27 := fiat.cmovznz_u64(fiat.u1(x26), x13, x1) + x28 := fiat.cmovznz_u64(fiat.u1(x26), x15, x3) + x29 := fiat.cmovznz_u64(fiat.u1(x26), x17, x5) + x30 := fiat.cmovznz_u64(fiat.u1(x26), x19, x7) + x31 := fiat.cmovznz_u64(fiat.u1(x26), x21, x9) + x32 := fiat.cmovznz_u64(fiat.u1(x26), x23, x11) + out1[0] = x27 + out1[1] = x28 + out1[2] = x29 + out1[3] = x30 + out1[4] = x31 + out1[5] = x32 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(arg1[4], arg2[4], u64(fiat.u1(x8))) + x11, x12 := bits.sub_u64(arg1[5], arg2[5], u64(fiat.u1(x10))) + x13 := fiat.cmovznz_u64(fiat.u1(x12), u64(0x0), 0xffffffffffffffff) + x14, x15 := bits.add_u64(x1, (x13 & 0xecec196accc52973), u64(0x0)) + x16, x17 := bits.add_u64(x3, (x13 & 0x581a0db248b0a77a), u64(fiat.u1(x15))) + x18, x19 := bits.add_u64(x5, (x13 & 0xc7634d81f4372ddf), u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x7, x13, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x13, u64(fiat.u1(x21))) + x24, _ := bits.add_u64(x11, x13, u64(fiat.u1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(u64(0x0), arg1[4], u64(fiat.u1(x8))) + x11, x12 := bits.sub_u64(u64(0x0), arg1[5], u64(fiat.u1(x10))) + x13 := fiat.cmovznz_u64(fiat.u1(x12), u64(0x0), 0xffffffffffffffff) + x14, x15 := bits.add_u64(x1, (x13 & 0xecec196accc52973), u64(0x0)) + x16, x17 := bits.add_u64(x3, (x13 & 0x581a0db248b0a77a), u64(fiat.u1(x15))) + x18, x19 := bits.add_u64(x5, (x13 & 0xc7634d81f4372ddf), u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x7, x13, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x13, u64(fiat.u1(x21))) + x24, _ := bits.add_u64(x11, x13, u64(fiat.u1(x23))) + out1[0] = x14 + out1[1] = x16 + out1[2] = x18 + out1[3] = x20 + out1[4] = x22 + out1[5] = x24 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0x1313e695333ad68d + out1[1] = 0xa7e5f24db74f5885 + out1[2] = 0x389cb27e0bc8d220 + out1[3] = 0x0 + out1[4] = 0x0 + out1[5] = 0x0 +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return (arg1[0] | (arg1[1] | (arg1[2] | (arg1[3] | (arg1[4] | arg1[5]))))) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + x5 := fiat.cmovznz_u64(fiat.u1(arg2), out1[4], arg1[4]) + x6 := fiat.cmovznz_u64(fiat.u1(arg2), out1[5], arg1[5]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + _, x2 := bits.mul_u64(x1, 0x6ed46089e88fdc45) + x5, x4 := bits.mul_u64(x2, 0xffffffffffffffff) + x7, x6 := bits.mul_u64(x2, 0xffffffffffffffff) + x9, x8 := bits.mul_u64(x2, 0xffffffffffffffff) + x11, x10 := bits.mul_u64(x2, 0xc7634d81f4372ddf) + x13, x12 := bits.mul_u64(x2, 0x581a0db248b0a77a) + x15, x14 := bits.mul_u64(x2, 0xecec196accc52973) + x16, x17 := bits.add_u64(x15, x12, u64(0x0)) + x18, x19 := bits.add_u64(x13, x10, u64(fiat.u1(x17))) + x20, x21 := bits.add_u64(x11, x8, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(x9, x6, u64(fiat.u1(x21))) + x24, x25 := bits.add_u64(x7, x4, u64(fiat.u1(x23))) + _, x27 := bits.add_u64(x1, x14, u64(0x0)) + x28, x29 := bits.add_u64(u64(0x0), x16, u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(u64(0x0), x18, u64(fiat.u1(x29))) + x32, x33 := bits.add_u64(u64(0x0), x20, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(u64(0x0), x22, u64(fiat.u1(x33))) + x36, x37 := bits.add_u64(u64(0x0), x24, u64(fiat.u1(x35))) + x38, x39 := bits.add_u64(u64(0x0), (u64(fiat.u1(x25)) + x5), u64(fiat.u1(x37))) + x40, x41 := bits.add_u64(x28, arg1[1], u64(0x0)) + x42, x43 := bits.add_u64(x30, u64(0x0), u64(fiat.u1(x41))) + x44, x45 := bits.add_u64(x32, u64(0x0), u64(fiat.u1(x43))) + x46, x47 := bits.add_u64(x34, u64(0x0), u64(fiat.u1(x45))) + x48, x49 := bits.add_u64(x36, u64(0x0), u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x38, u64(0x0), u64(fiat.u1(x49))) + _, x52 := bits.mul_u64(x40, 0x6ed46089e88fdc45) + x55, x54 := bits.mul_u64(x52, 0xffffffffffffffff) + x57, x56 := bits.mul_u64(x52, 0xffffffffffffffff) + x59, x58 := bits.mul_u64(x52, 0xffffffffffffffff) + x61, x60 := bits.mul_u64(x52, 0xc7634d81f4372ddf) + x63, x62 := bits.mul_u64(x52, 0x581a0db248b0a77a) + x65, x64 := bits.mul_u64(x52, 0xecec196accc52973) + x66, x67 := bits.add_u64(x65, x62, u64(0x0)) + x68, x69 := bits.add_u64(x63, x60, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(x61, x58, u64(fiat.u1(x69))) + x72, x73 := bits.add_u64(x59, x56, u64(fiat.u1(x71))) + x74, x75 := bits.add_u64(x57, x54, u64(fiat.u1(x73))) + _, x77 := bits.add_u64(x40, x64, u64(0x0)) + x78, x79 := bits.add_u64(x42, x66, u64(fiat.u1(x77))) + x80, x81 := bits.add_u64(x44, x68, u64(fiat.u1(x79))) + x82, x83 := bits.add_u64(x46, x70, u64(fiat.u1(x81))) + x84, x85 := bits.add_u64(x48, x72, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x50, x74, u64(fiat.u1(x85))) + x88, x89 := bits.add_u64((u64(fiat.u1(x51)) + u64(fiat.u1(x39))), (u64(fiat.u1(x75)) + x55), u64(fiat.u1(x87))) + x90, x91 := bits.add_u64(x78, arg1[2], u64(0x0)) + x92, x93 := bits.add_u64(x80, u64(0x0), u64(fiat.u1(x91))) + x94, x95 := bits.add_u64(x82, u64(0x0), u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x84, u64(0x0), u64(fiat.u1(x95))) + x98, x99 := bits.add_u64(x86, u64(0x0), u64(fiat.u1(x97))) + x100, x101 := bits.add_u64(x88, u64(0x0), u64(fiat.u1(x99))) + _, x102 := bits.mul_u64(x90, 0x6ed46089e88fdc45) + x105, x104 := bits.mul_u64(x102, 0xffffffffffffffff) + x107, x106 := bits.mul_u64(x102, 0xffffffffffffffff) + x109, x108 := bits.mul_u64(x102, 0xffffffffffffffff) + x111, x110 := bits.mul_u64(x102, 0xc7634d81f4372ddf) + x113, x112 := bits.mul_u64(x102, 0x581a0db248b0a77a) + x115, x114 := bits.mul_u64(x102, 0xecec196accc52973) + x116, x117 := bits.add_u64(x115, x112, u64(0x0)) + x118, x119 := bits.add_u64(x113, x110, u64(fiat.u1(x117))) + x120, x121 := bits.add_u64(x111, x108, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x109, x106, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x107, x104, u64(fiat.u1(x123))) + _, x127 := bits.add_u64(x90, x114, u64(0x0)) + x128, x129 := bits.add_u64(x92, x116, u64(fiat.u1(x127))) + x130, x131 := bits.add_u64(x94, x118, u64(fiat.u1(x129))) + x132, x133 := bits.add_u64(x96, x120, u64(fiat.u1(x131))) + x134, x135 := bits.add_u64(x98, x122, u64(fiat.u1(x133))) + x136, x137 := bits.add_u64(x100, x124, u64(fiat.u1(x135))) + x138, x139 := bits.add_u64((u64(fiat.u1(x101)) + u64(fiat.u1(x89))), (u64(fiat.u1(x125)) + x105), u64(fiat.u1(x137))) + x140, x141 := bits.add_u64(x128, arg1[3], u64(0x0)) + x142, x143 := bits.add_u64(x130, u64(0x0), u64(fiat.u1(x141))) + x144, x145 := bits.add_u64(x132, u64(0x0), u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x134, u64(0x0), u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x136, u64(0x0), u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x138, u64(0x0), u64(fiat.u1(x149))) + _, x152 := bits.mul_u64(x140, 0x6ed46089e88fdc45) + x155, x154 := bits.mul_u64(x152, 0xffffffffffffffff) + x157, x156 := bits.mul_u64(x152, 0xffffffffffffffff) + x159, x158 := bits.mul_u64(x152, 0xffffffffffffffff) + x161, x160 := bits.mul_u64(x152, 0xc7634d81f4372ddf) + x163, x162 := bits.mul_u64(x152, 0x581a0db248b0a77a) + x165, x164 := bits.mul_u64(x152, 0xecec196accc52973) + x166, x167 := bits.add_u64(x165, x162, u64(0x0)) + x168, x169 := bits.add_u64(x163, x160, u64(fiat.u1(x167))) + x170, x171 := bits.add_u64(x161, x158, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x159, x156, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x157, x154, u64(fiat.u1(x173))) + _, x177 := bits.add_u64(x140, x164, u64(0x0)) + x178, x179 := bits.add_u64(x142, x166, u64(fiat.u1(x177))) + x180, x181 := bits.add_u64(x144, x168, u64(fiat.u1(x179))) + x182, x183 := bits.add_u64(x146, x170, u64(fiat.u1(x181))) + x184, x185 := bits.add_u64(x148, x172, u64(fiat.u1(x183))) + x186, x187 := bits.add_u64(x150, x174, u64(fiat.u1(x185))) + x188, x189 := bits.add_u64((u64(fiat.u1(x151)) + u64(fiat.u1(x139))), (u64(fiat.u1(x175)) + x155), u64(fiat.u1(x187))) + x190, x191 := bits.add_u64(x178, arg1[4], u64(0x0)) + x192, x193 := bits.add_u64(x180, u64(0x0), u64(fiat.u1(x191))) + x194, x195 := bits.add_u64(x182, u64(0x0), u64(fiat.u1(x193))) + x196, x197 := bits.add_u64(x184, u64(0x0), u64(fiat.u1(x195))) + x198, x199 := bits.add_u64(x186, u64(0x0), u64(fiat.u1(x197))) + x200, x201 := bits.add_u64(x188, u64(0x0), u64(fiat.u1(x199))) + _, x202 := bits.mul_u64(x190, 0x6ed46089e88fdc45) + x205, x204 := bits.mul_u64(x202, 0xffffffffffffffff) + x207, x206 := bits.mul_u64(x202, 0xffffffffffffffff) + x209, x208 := bits.mul_u64(x202, 0xffffffffffffffff) + x211, x210 := bits.mul_u64(x202, 0xc7634d81f4372ddf) + x213, x212 := bits.mul_u64(x202, 0x581a0db248b0a77a) + x215, x214 := bits.mul_u64(x202, 0xecec196accc52973) + x216, x217 := bits.add_u64(x215, x212, u64(0x0)) + x218, x219 := bits.add_u64(x213, x210, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x211, x208, u64(fiat.u1(x219))) + x222, x223 := bits.add_u64(x209, x206, u64(fiat.u1(x221))) + x224, x225 := bits.add_u64(x207, x204, u64(fiat.u1(x223))) + _, x227 := bits.add_u64(x190, x214, u64(0x0)) + x228, x229 := bits.add_u64(x192, x216, u64(fiat.u1(x227))) + x230, x231 := bits.add_u64(x194, x218, u64(fiat.u1(x229))) + x232, x233 := bits.add_u64(x196, x220, u64(fiat.u1(x231))) + x234, x235 := bits.add_u64(x198, x222, u64(fiat.u1(x233))) + x236, x237 := bits.add_u64(x200, x224, u64(fiat.u1(x235))) + x238, x239 := bits.add_u64((u64(fiat.u1(x201)) + u64(fiat.u1(x189))), (u64(fiat.u1(x225)) + x205), u64(fiat.u1(x237))) + x240, x241 := bits.add_u64(x228, arg1[5], u64(0x0)) + x242, x243 := bits.add_u64(x230, u64(0x0), u64(fiat.u1(x241))) + x244, x245 := bits.add_u64(x232, u64(0x0), u64(fiat.u1(x243))) + x246, x247 := bits.add_u64(x234, u64(0x0), u64(fiat.u1(x245))) + x248, x249 := bits.add_u64(x236, u64(0x0), u64(fiat.u1(x247))) + x250, x251 := bits.add_u64(x238, u64(0x0), u64(fiat.u1(x249))) + _, x252 := bits.mul_u64(x240, 0x6ed46089e88fdc45) + x255, x254 := bits.mul_u64(x252, 0xffffffffffffffff) + x257, x256 := bits.mul_u64(x252, 0xffffffffffffffff) + x259, x258 := bits.mul_u64(x252, 0xffffffffffffffff) + x261, x260 := bits.mul_u64(x252, 0xc7634d81f4372ddf) + x263, x262 := bits.mul_u64(x252, 0x581a0db248b0a77a) + x265, x264 := bits.mul_u64(x252, 0xecec196accc52973) + x266, x267 := bits.add_u64(x265, x262, u64(0x0)) + x268, x269 := bits.add_u64(x263, x260, u64(fiat.u1(x267))) + x270, x271 := bits.add_u64(x261, x258, u64(fiat.u1(x269))) + x272, x273 := bits.add_u64(x259, x256, u64(fiat.u1(x271))) + x274, x275 := bits.add_u64(x257, x254, u64(fiat.u1(x273))) + _, x277 := bits.add_u64(x240, x264, u64(0x0)) + x278, x279 := bits.add_u64(x242, x266, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x244, x268, u64(fiat.u1(x279))) + x282, x283 := bits.add_u64(x246, x270, u64(fiat.u1(x281))) + x284, x285 := bits.add_u64(x248, x272, u64(fiat.u1(x283))) + x286, x287 := bits.add_u64(x250, x274, u64(fiat.u1(x285))) + x288, x289 := bits.add_u64((u64(fiat.u1(x251)) + u64(fiat.u1(x239))), (u64(fiat.u1(x275)) + x255), u64(fiat.u1(x287))) + x290, x291 := bits.sub_u64(x278, 0xecec196accc52973, u64(0x0)) + x292, x293 := bits.sub_u64(x280, 0x581a0db248b0a77a, u64(fiat.u1(x291))) + x294, x295 := bits.sub_u64(x282, 0xc7634d81f4372ddf, u64(fiat.u1(x293))) + x296, x297 := bits.sub_u64(x284, 0xffffffffffffffff, u64(fiat.u1(x295))) + x298, x299 := bits.sub_u64(x286, 0xffffffffffffffff, u64(fiat.u1(x297))) + x300, x301 := bits.sub_u64(x288, 0xffffffffffffffff, u64(fiat.u1(x299))) + _, x303 := bits.sub_u64(u64(fiat.u1(x289)), u64(0x0), u64(fiat.u1(x301))) + x304 := fiat.cmovznz_u64(fiat.u1(x303), x290, x278) + x305 := fiat.cmovznz_u64(fiat.u1(x303), x292, x280) + x306 := fiat.cmovznz_u64(fiat.u1(x303), x294, x282) + x307 := fiat.cmovznz_u64(fiat.u1(x303), x296, x284) + x308 := fiat.cmovznz_u64(fiat.u1(x303), x298, x286) + x309 := fiat.cmovznz_u64(fiat.u1(x303), x300, x288) + out1[0] = x304 + out1[1] = x305 + out1[2] = x306 + out1[3] = x307 + out1[4] = x308 + out1[5] = x309 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[4] + x5 := arg1[5] + x6 := arg1[0] + x8, x7 := bits.mul_u64(x6, 0xc84ee012b39bf21) + x10, x9 := bits.mul_u64(x6, 0x3fb05b7a28266895) + x12, x11 := bits.mul_u64(x6, 0xd40d49174aab1cc5) + x14, x13 := bits.mul_u64(x6, 0xbc3e483afcb82947) + x16, x15 := bits.mul_u64(x6, 0xff3d81e5df1aa419) + x18, x17 := bits.mul_u64(x6, 0x2d319b2419b409a9) + x19, x20 := bits.add_u64(x18, x15, u64(0x0)) + x21, x22 := bits.add_u64(x16, x13, u64(fiat.u1(x20))) + x23, x24 := bits.add_u64(x14, x11, u64(fiat.u1(x22))) + x25, x26 := bits.add_u64(x12, x9, u64(fiat.u1(x24))) + x27, x28 := bits.add_u64(x10, x7, u64(fiat.u1(x26))) + _, x29 := bits.mul_u64(x17, 0x6ed46089e88fdc45) + x32, x31 := bits.mul_u64(x29, 0xffffffffffffffff) + x34, x33 := bits.mul_u64(x29, 0xffffffffffffffff) + x36, x35 := bits.mul_u64(x29, 0xffffffffffffffff) + x38, x37 := bits.mul_u64(x29, 0xc7634d81f4372ddf) + x40, x39 := bits.mul_u64(x29, 0x581a0db248b0a77a) + x42, x41 := bits.mul_u64(x29, 0xecec196accc52973) + x43, x44 := bits.add_u64(x42, x39, u64(0x0)) + x45, x46 := bits.add_u64(x40, x37, u64(fiat.u1(x44))) + x47, x48 := bits.add_u64(x38, x35, u64(fiat.u1(x46))) + x49, x50 := bits.add_u64(x36, x33, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x34, x31, u64(fiat.u1(x50))) + _, x54 := bits.add_u64(x17, x41, u64(0x0)) + x55, x56 := bits.add_u64(x19, x43, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(x21, x45, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x23, x47, u64(fiat.u1(x58))) + x61, x62 := bits.add_u64(x25, x49, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x27, x51, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64((u64(fiat.u1(x28)) + x8), (u64(fiat.u1(x52)) + x32), u64(fiat.u1(x64))) + x68, x67 := bits.mul_u64(x1, 0xc84ee012b39bf21) + x70, x69 := bits.mul_u64(x1, 0x3fb05b7a28266895) + x72, x71 := bits.mul_u64(x1, 0xd40d49174aab1cc5) + x74, x73 := bits.mul_u64(x1, 0xbc3e483afcb82947) + x76, x75 := bits.mul_u64(x1, 0xff3d81e5df1aa419) + x78, x77 := bits.mul_u64(x1, 0x2d319b2419b409a9) + x79, x80 := bits.add_u64(x78, x75, u64(0x0)) + x81, x82 := bits.add_u64(x76, x73, u64(fiat.u1(x80))) + x83, x84 := bits.add_u64(x74, x71, u64(fiat.u1(x82))) + x85, x86 := bits.add_u64(x72, x69, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x70, x67, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x55, x77, u64(0x0)) + x91, x92 := bits.add_u64(x57, x79, u64(fiat.u1(x90))) + x93, x94 := bits.add_u64(x59, x81, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x61, x83, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x63, x85, u64(fiat.u1(x96))) + x99, x100 := bits.add_u64(x65, x87, u64(fiat.u1(x98))) + _, x101 := bits.mul_u64(x89, 0x6ed46089e88fdc45) + x104, x103 := bits.mul_u64(x101, 0xffffffffffffffff) + x106, x105 := bits.mul_u64(x101, 0xffffffffffffffff) + x108, x107 := bits.mul_u64(x101, 0xffffffffffffffff) + x110, x109 := bits.mul_u64(x101, 0xc7634d81f4372ddf) + x112, x111 := bits.mul_u64(x101, 0x581a0db248b0a77a) + x114, x113 := bits.mul_u64(x101, 0xecec196accc52973) + x115, x116 := bits.add_u64(x114, x111, u64(0x0)) + x117, x118 := bits.add_u64(x112, x109, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x110, x107, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x108, x105, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x106, x103, u64(fiat.u1(x122))) + _, x126 := bits.add_u64(x89, x113, u64(0x0)) + x127, x128 := bits.add_u64(x91, x115, u64(fiat.u1(x126))) + x129, x130 := bits.add_u64(x93, x117, u64(fiat.u1(x128))) + x131, x132 := bits.add_u64(x95, x119, u64(fiat.u1(x130))) + x133, x134 := bits.add_u64(x97, x121, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x99, x123, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(((u64(fiat.u1(x100)) + u64(fiat.u1(x66))) + (u64(fiat.u1(x88)) + x68)), (u64(fiat.u1(x124)) + x104), u64(fiat.u1(x136))) + x140, x139 := bits.mul_u64(x2, 0xc84ee012b39bf21) + x142, x141 := bits.mul_u64(x2, 0x3fb05b7a28266895) + x144, x143 := bits.mul_u64(x2, 0xd40d49174aab1cc5) + x146, x145 := bits.mul_u64(x2, 0xbc3e483afcb82947) + x148, x147 := bits.mul_u64(x2, 0xff3d81e5df1aa419) + x150, x149 := bits.mul_u64(x2, 0x2d319b2419b409a9) + x151, x152 := bits.add_u64(x150, x147, u64(0x0)) + x153, x154 := bits.add_u64(x148, x145, u64(fiat.u1(x152))) + x155, x156 := bits.add_u64(x146, x143, u64(fiat.u1(x154))) + x157, x158 := bits.add_u64(x144, x141, u64(fiat.u1(x156))) + x159, x160 := bits.add_u64(x142, x139, u64(fiat.u1(x158))) + x161, x162 := bits.add_u64(x127, x149, u64(0x0)) + x163, x164 := bits.add_u64(x129, x151, u64(fiat.u1(x162))) + x165, x166 := bits.add_u64(x131, x153, u64(fiat.u1(x164))) + x167, x168 := bits.add_u64(x133, x155, u64(fiat.u1(x166))) + x169, x170 := bits.add_u64(x135, x157, u64(fiat.u1(x168))) + x171, x172 := bits.add_u64(x137, x159, u64(fiat.u1(x170))) + _, x173 := bits.mul_u64(x161, 0x6ed46089e88fdc45) + x176, x175 := bits.mul_u64(x173, 0xffffffffffffffff) + x178, x177 := bits.mul_u64(x173, 0xffffffffffffffff) + x180, x179 := bits.mul_u64(x173, 0xffffffffffffffff) + x182, x181 := bits.mul_u64(x173, 0xc7634d81f4372ddf) + x184, x183 := bits.mul_u64(x173, 0x581a0db248b0a77a) + x186, x185 := bits.mul_u64(x173, 0xecec196accc52973) + x187, x188 := bits.add_u64(x186, x183, u64(0x0)) + x189, x190 := bits.add_u64(x184, x181, u64(fiat.u1(x188))) + x191, x192 := bits.add_u64(x182, x179, u64(fiat.u1(x190))) + x193, x194 := bits.add_u64(x180, x177, u64(fiat.u1(x192))) + x195, x196 := bits.add_u64(x178, x175, u64(fiat.u1(x194))) + _, x198 := bits.add_u64(x161, x185, u64(0x0)) + x199, x200 := bits.add_u64(x163, x187, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x165, x189, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x167, x191, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x169, x193, u64(fiat.u1(x204))) + x207, x208 := bits.add_u64(x171, x195, u64(fiat.u1(x206))) + x209, x210 := bits.add_u64(((u64(fiat.u1(x172)) + u64(fiat.u1(x138))) + (u64(fiat.u1(x160)) + x140)), (u64(fiat.u1(x196)) + x176), u64(fiat.u1(x208))) + x212, x211 := bits.mul_u64(x3, 0xc84ee012b39bf21) + x214, x213 := bits.mul_u64(x3, 0x3fb05b7a28266895) + x216, x215 := bits.mul_u64(x3, 0xd40d49174aab1cc5) + x218, x217 := bits.mul_u64(x3, 0xbc3e483afcb82947) + x220, x219 := bits.mul_u64(x3, 0xff3d81e5df1aa419) + x222, x221 := bits.mul_u64(x3, 0x2d319b2419b409a9) + x223, x224 := bits.add_u64(x222, x219, u64(0x0)) + x225, x226 := bits.add_u64(x220, x217, u64(fiat.u1(x224))) + x227, x228 := bits.add_u64(x218, x215, u64(fiat.u1(x226))) + x229, x230 := bits.add_u64(x216, x213, u64(fiat.u1(x228))) + x231, x232 := bits.add_u64(x214, x211, u64(fiat.u1(x230))) + x233, x234 := bits.add_u64(x199, x221, u64(0x0)) + x235, x236 := bits.add_u64(x201, x223, u64(fiat.u1(x234))) + x237, x238 := bits.add_u64(x203, x225, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x205, x227, u64(fiat.u1(x238))) + x241, x242 := bits.add_u64(x207, x229, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x209, x231, u64(fiat.u1(x242))) + _, x245 := bits.mul_u64(x233, 0x6ed46089e88fdc45) + x248, x247 := bits.mul_u64(x245, 0xffffffffffffffff) + x250, x249 := bits.mul_u64(x245, 0xffffffffffffffff) + x252, x251 := bits.mul_u64(x245, 0xffffffffffffffff) + x254, x253 := bits.mul_u64(x245, 0xc7634d81f4372ddf) + x256, x255 := bits.mul_u64(x245, 0x581a0db248b0a77a) + x258, x257 := bits.mul_u64(x245, 0xecec196accc52973) + x259, x260 := bits.add_u64(x258, x255, u64(0x0)) + x261, x262 := bits.add_u64(x256, x253, u64(fiat.u1(x260))) + x263, x264 := bits.add_u64(x254, x251, u64(fiat.u1(x262))) + x265, x266 := bits.add_u64(x252, x249, u64(fiat.u1(x264))) + x267, x268 := bits.add_u64(x250, x247, u64(fiat.u1(x266))) + _, x270 := bits.add_u64(x233, x257, u64(0x0)) + x271, x272 := bits.add_u64(x235, x259, u64(fiat.u1(x270))) + x273, x274 := bits.add_u64(x237, x261, u64(fiat.u1(x272))) + x275, x276 := bits.add_u64(x239, x263, u64(fiat.u1(x274))) + x277, x278 := bits.add_u64(x241, x265, u64(fiat.u1(x276))) + x279, x280 := bits.add_u64(x243, x267, u64(fiat.u1(x278))) + x281, x282 := bits.add_u64(((u64(fiat.u1(x244)) + u64(fiat.u1(x210))) + (u64(fiat.u1(x232)) + x212)), (u64(fiat.u1(x268)) + x248), u64(fiat.u1(x280))) + x284, x283 := bits.mul_u64(x4, 0xc84ee012b39bf21) + x286, x285 := bits.mul_u64(x4, 0x3fb05b7a28266895) + x288, x287 := bits.mul_u64(x4, 0xd40d49174aab1cc5) + x290, x289 := bits.mul_u64(x4, 0xbc3e483afcb82947) + x292, x291 := bits.mul_u64(x4, 0xff3d81e5df1aa419) + x294, x293 := bits.mul_u64(x4, 0x2d319b2419b409a9) + x295, x296 := bits.add_u64(x294, x291, u64(0x0)) + x297, x298 := bits.add_u64(x292, x289, u64(fiat.u1(x296))) + x299, x300 := bits.add_u64(x290, x287, u64(fiat.u1(x298))) + x301, x302 := bits.add_u64(x288, x285, u64(fiat.u1(x300))) + x303, x304 := bits.add_u64(x286, x283, u64(fiat.u1(x302))) + x305, x306 := bits.add_u64(x271, x293, u64(0x0)) + x307, x308 := bits.add_u64(x273, x295, u64(fiat.u1(x306))) + x309, x310 := bits.add_u64(x275, x297, u64(fiat.u1(x308))) + x311, x312 := bits.add_u64(x277, x299, u64(fiat.u1(x310))) + x313, x314 := bits.add_u64(x279, x301, u64(fiat.u1(x312))) + x315, x316 := bits.add_u64(x281, x303, u64(fiat.u1(x314))) + _, x317 := bits.mul_u64(x305, 0x6ed46089e88fdc45) + x320, x319 := bits.mul_u64(x317, 0xffffffffffffffff) + x322, x321 := bits.mul_u64(x317, 0xffffffffffffffff) + x324, x323 := bits.mul_u64(x317, 0xffffffffffffffff) + x326, x325 := bits.mul_u64(x317, 0xc7634d81f4372ddf) + x328, x327 := bits.mul_u64(x317, 0x581a0db248b0a77a) + x330, x329 := bits.mul_u64(x317, 0xecec196accc52973) + x331, x332 := bits.add_u64(x330, x327, u64(0x0)) + x333, x334 := bits.add_u64(x328, x325, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x326, x323, u64(fiat.u1(x334))) + x337, x338 := bits.add_u64(x324, x321, u64(fiat.u1(x336))) + x339, x340 := bits.add_u64(x322, x319, u64(fiat.u1(x338))) + _, x342 := bits.add_u64(x305, x329, u64(0x0)) + x343, x344 := bits.add_u64(x307, x331, u64(fiat.u1(x342))) + x345, x346 := bits.add_u64(x309, x333, u64(fiat.u1(x344))) + x347, x348 := bits.add_u64(x311, x335, u64(fiat.u1(x346))) + x349, x350 := bits.add_u64(x313, x337, u64(fiat.u1(x348))) + x351, x352 := bits.add_u64(x315, x339, u64(fiat.u1(x350))) + x353, x354 := bits.add_u64(((u64(fiat.u1(x316)) + u64(fiat.u1(x282))) + (u64(fiat.u1(x304)) + x284)), (u64(fiat.u1(x340)) + x320), u64(fiat.u1(x352))) + x356, x355 := bits.mul_u64(x5, 0xc84ee012b39bf21) + x358, x357 := bits.mul_u64(x5, 0x3fb05b7a28266895) + x360, x359 := bits.mul_u64(x5, 0xd40d49174aab1cc5) + x362, x361 := bits.mul_u64(x5, 0xbc3e483afcb82947) + x364, x363 := bits.mul_u64(x5, 0xff3d81e5df1aa419) + x366, x365 := bits.mul_u64(x5, 0x2d319b2419b409a9) + x367, x368 := bits.add_u64(x366, x363, u64(0x0)) + x369, x370 := bits.add_u64(x364, x361, u64(fiat.u1(x368))) + x371, x372 := bits.add_u64(x362, x359, u64(fiat.u1(x370))) + x373, x374 := bits.add_u64(x360, x357, u64(fiat.u1(x372))) + x375, x376 := bits.add_u64(x358, x355, u64(fiat.u1(x374))) + x377, x378 := bits.add_u64(x343, x365, u64(0x0)) + x379, x380 := bits.add_u64(x345, x367, u64(fiat.u1(x378))) + x381, x382 := bits.add_u64(x347, x369, u64(fiat.u1(x380))) + x383, x384 := bits.add_u64(x349, x371, u64(fiat.u1(x382))) + x385, x386 := bits.add_u64(x351, x373, u64(fiat.u1(x384))) + x387, x388 := bits.add_u64(x353, x375, u64(fiat.u1(x386))) + _, x389 := bits.mul_u64(x377, 0x6ed46089e88fdc45) + x392, x391 := bits.mul_u64(x389, 0xffffffffffffffff) + x394, x393 := bits.mul_u64(x389, 0xffffffffffffffff) + x396, x395 := bits.mul_u64(x389, 0xffffffffffffffff) + x398, x397 := bits.mul_u64(x389, 0xc7634d81f4372ddf) + x400, x399 := bits.mul_u64(x389, 0x581a0db248b0a77a) + x402, x401 := bits.mul_u64(x389, 0xecec196accc52973) + x403, x404 := bits.add_u64(x402, x399, u64(0x0)) + x405, x406 := bits.add_u64(x400, x397, u64(fiat.u1(x404))) + x407, x408 := bits.add_u64(x398, x395, u64(fiat.u1(x406))) + x409, x410 := bits.add_u64(x396, x393, u64(fiat.u1(x408))) + x411, x412 := bits.add_u64(x394, x391, u64(fiat.u1(x410))) + _, x414 := bits.add_u64(x377, x401, u64(0x0)) + x415, x416 := bits.add_u64(x379, x403, u64(fiat.u1(x414))) + x417, x418 := bits.add_u64(x381, x405, u64(fiat.u1(x416))) + x419, x420 := bits.add_u64(x383, x407, u64(fiat.u1(x418))) + x421, x422 := bits.add_u64(x385, x409, u64(fiat.u1(x420))) + x423, x424 := bits.add_u64(x387, x411, u64(fiat.u1(x422))) + x425, x426 := bits.add_u64(((u64(fiat.u1(x388)) + u64(fiat.u1(x354))) + (u64(fiat.u1(x376)) + x356)), (u64(fiat.u1(x412)) + x392), u64(fiat.u1(x424))) + x427, x428 := bits.sub_u64(x415, 0xecec196accc52973, u64(0x0)) + x429, x430 := bits.sub_u64(x417, 0x581a0db248b0a77a, u64(fiat.u1(x428))) + x431, x432 := bits.sub_u64(x419, 0xc7634d81f4372ddf, u64(fiat.u1(x430))) + x433, x434 := bits.sub_u64(x421, 0xffffffffffffffff, u64(fiat.u1(x432))) + x435, x436 := bits.sub_u64(x423, 0xffffffffffffffff, u64(fiat.u1(x434))) + x437, x438 := bits.sub_u64(x425, 0xffffffffffffffff, u64(fiat.u1(x436))) + _, x440 := bits.sub_u64(u64(fiat.u1(x426)), u64(0x0), u64(fiat.u1(x438))) + x441 := fiat.cmovznz_u64(fiat.u1(x440), x427, x415) + x442 := fiat.cmovznz_u64(fiat.u1(x440), x429, x417) + x443 := fiat.cmovznz_u64(fiat.u1(x440), x431, x419) + x444 := fiat.cmovznz_u64(fiat.u1(x440), x433, x421) + x445 := fiat.cmovznz_u64(fiat.u1(x440), x435, x423) + x446 := fiat.cmovznz_u64(fiat.u1(x440), x437, x425) + out1[0] = x441 + out1[1] = x442 + out1[2] = x443 + out1[3] = x444 + out1[4] = x445 + out1[5] = x446 +} diff --git a/core/crypto/_mldsa/constants.odin b/core/crypto/_mldsa/constants.odin new file mode 100644 index 000000000..6a9b6e096 --- /dev/null +++ b/core/crypto/_mldsa/constants.odin @@ -0,0 +1,72 @@ +#+private +package _mldsa + +CRHBYTES :: 64 +TRBYTES :: 64 + +N :: 256 +Q :: 8380417 +D :: 13 + +K_MAX :: 8 +L_MAX :: 7 + +POLYZ_PACKEDBYTES_MAX :: 640 + +POLYT1_PACKEDBYTES :: 320 +POLYT0_PACKEDBYTES :: 416 + +POLYVECT1_PACKEDBYTES_MAX :: K_MAX * POLYT1_PACKEDBYTES +POLYW1_PACKEDBYTES_MAX :: 192 + +CTILDBYTES_MAX :: 64 + +@(require_results) +polyeta_packedbytes :: #force_inline proc "contextless" (params: ^Params) -> int { + POLYETA_PACKEDBYTES_2 :: 96 + POLYETA_PACKEDBYTES_4 :: 128 + + switch params.eta { + case 2: + return POLYETA_PACKEDBYTES_2 + case 4: + return POLYETA_PACKEDBYTES_4 + case: + unreachable() + } +} + +@(require_results) +polyz_packedbytes :: #force_inline proc "contextless" (params: ^Params) -> int { + POLYZ_PACKEDBYTES_GAMMA1_17 :: 576 + POLYZ_PACKEDBYTES_GAMMA1_19 :: 640 + + switch params.gamma1 { + case 1 << 17: + return POLYZ_PACKEDBYTES_GAMMA1_17 + case 1 << 19: + return POLYZ_PACKEDBYTES_GAMMA1_19 + case: + unreachable() + } +} + +@(require_results) +polyw1_packedbytes :: #force_inline proc "contextless" (params: ^Params) -> int { + POLYW1_PACKEDBYTES_GAMMA2_95232 :: 192 + POLYW1_PACKEDBYTES_GAMMA2_261888 :: 128 + + switch params.gamma2 { + case (Q-1)/88: + return POLYW1_PACKEDBYTES_GAMMA2_95232 + case (Q-1)/32: + return POLYW1_PACKEDBYTES_GAMMA2_261888 + case: + unreachable() + } +} + +@(require_results) +polyvech_packedbytes :: #force_inline proc "contextless" (params: ^Params) -> int { + return params.omega + params.k +} diff --git a/core/crypto/_mldsa/dsa_internal.odin b/core/crypto/_mldsa/dsa_internal.odin new file mode 100644 index 000000000..bfb6b7508 --- /dev/null +++ b/core/crypto/_mldsa/dsa_internal.odin @@ -0,0 +1,394 @@ +package _mldsa + +import "core:crypto" +import "core:crypto/shake" + +// This implementation is derived from the PQ-CRYSTALS reference +// implementation [[ https://github.com/pq-crystals/dilithium ]], +// primarily for licensing reasons. Arguably mldsa-native is +// a more "up to date" codebase, but the changes to the +// ref code is minor and they slapped an attribution-required +// license on something that was originally CC-0/Apache 2.0. + +SEEDBYTES :: 32 +RNDBYTES :: 32 +CTXBYTES_MAX :: 255 + +Params :: struct { + k: int, + l: int, + eta: i32, + tau: int, + beta: i32, + gamma1: i32, + gamma2: i32, + omega: int, + ctild_bytes: int, +} + +@(rodata) +Params_44 := Params{ + k = 4, + l = 4, + eta = 2, + tau = 39, + beta = 78, + gamma1 = 1 << 17, + gamma2 = (Q-1)/88, + omega = 80, + ctild_bytes = 32, +} + +@(rodata) +Params_65 := Params{ + k = 6, + l = 5, + eta = 4, + tau = 49, + beta = 196, + gamma1 = 1 << 19, + gamma2 = (Q-1)/32, + omega = 55, + ctild_bytes = 48, +} + +@(rodata) +Params_87 := Params{ + k = 8, + l = 7, + eta = 2, + tau = 60, + beta = 120, + gamma1 = 1 << 19, + gamma2 = (Q-1)/32, + omega = 75, + ctild_bytes = 64, +} + +Private_Key :: struct { + params: ^Params, + + rho: [SEEDBYTES]byte, + tr: [TRBYTES]byte, + key: [SEEDBYTES]byte, + t0: Polyvec_K, + s1: Polyvec_L, + s2: Polyvec_K, + + pub_key: Public_Key, + seed: [SEEDBYTES]byte, +} + +Public_Key :: struct { + params: ^Params, + + t1: Polyvec_K, + rho: [SEEDBYTES]byte, + mu: [TRBYTES]byte, +} + +@(private) +Signature :: struct { + params: ^Params, + + c: [CTILDBYTES_MAX]byte, + z: Polyvec_L, + h: Polyvec_K, +} + +dsa_keygen_internal :: proc( + priv_key: ^Private_Key, + seed: []byte, + params: ^Params, +) { + ensure(len(seed) == SEEDBYTES, "crypto/mldsa: invalid seed") + + pub_key := &priv_key.pub_key + pub_key.params = params + priv_key.params = params + + copy(priv_key.seed[:], seed) + + seedbuf: [2*SEEDBYTES + CRHBYTES]byte = --- + mat_: [K_MAX]Polyvec_L = --- + defer crypto.zero_explicit(&seedbuf, size_of(seedbuf)) + defer crypto.zero_explicit(&mat_, size_of(mat_)) + + // Expand randomness for rho, rhoprime and key + copy(seedbuf[:], seed) + seedbuf[SEEDBYTES] = byte(params.k) + seedbuf[SEEDBYTES+1] = byte(params.l) + shake256(seedbuf[:], seedbuf[:SEEDBYTES+2]) + copy(priv_key.rho[:], seedbuf[:SEEDBYTES]) + rhoprime := seedbuf[SEEDBYTES:SEEDBYTES+CRHBYTES] + copy(priv_key.key[:], seedbuf[SEEDBYTES+CRHBYTES:]) + + // Expand matrix + mat := mat_[:params.k] + polyvec_matrix_expand(mat, priv_key.rho[:], params) + + // Sample short vectors s1 and s2 + polyvec_l_uniform_eta(&priv_key.s1, rhoprime, 0, params) + polyvec_k_uniform_eta(&priv_key.s2, rhoprime, u16(params.l), params) + + // Matrix-vector multiplication + s1hat: Polyvec_L = --- + defer crypto.zero_explicit(&s1hat, size_of(Polyvec_L)) + polyvec_copy(&s1hat, &priv_key.s1, params) + polyvec_l_ntt(&s1hat, params) + polyvec_matrix_pointwise_montgomery(&pub_key.t1, mat, &s1hat, params) + polyvec_k_reduce(&pub_key.t1, params) + polyvec_k_invntt_tomont(&pub_key.t1, params) + + // Add error vector s2 + polyvec_k_add(&pub_key.t1, &pub_key.t1, &priv_key.s2, params) + + // Extract t1 and write public key + pk_bytes_: [SEEDBYTES+POLYVECT1_PACKEDBYTES_MAX]byte = --- + pk_bytes := pk_bytes_[:public_key_size(params)] + polyvec_k_caddq(&pub_key.t1, params) + polyvec_k_power2round(&pub_key.t1, &priv_key.t0, &pub_key.t1, params) + copy(pub_key.rho[:], priv_key.rho[:]) + _ = pack_pk(pk_bytes, pub_key) + + // Compute H(rho, t1) and write secret key + shake256(pub_key.mu[:], pk_bytes) + copy(priv_key.tr[:], pub_key.mu[:]) +} + +dsa_sign_internal :: proc( + sig_bytes: []byte, + m: []byte, + ctx: []byte, + rnd: []byte, + priv_key: ^Private_Key, + external_mu: []byte = nil +) -> bool { + params := priv_key.params + switch params { + case &Params_44, &Params_65, &Params_87: + case: + return false + } + if len(sig_bytes) != signature_size(params) { + return false + } + ensure(len(ctx) <= CTXBYTES_MAX, "crypto/mlkem: invalid contxt size") + ensure(len(rnd) == RNDBYTES, "crypto/mlkem: invalid rnd size") + + mu, rhoprime: [CRHBYTES]byte = ---, --- + mat_: [K_MAX]Polyvec_L + w1_bytes_: [SEEDBYTES+POLYVECT1_PACKEDBYTES_MAX]byte = --- + s1, y: Polyvec_L = ---, --- + t0, s2, w1, w0: Polyvec_K = ---, ---, ---, --- + cp: Poly + + polyvec_copy(&s1, &priv_key.s1, params) + polyvec_copy(&s2, &priv_key.s2, params) + polyvec_copy(&t0, &priv_key.t0, params) + + defer crypto.zero_explicit(&mu, size_of(mu)) + defer crypto.zero_explicit(&rhoprime, size_of(rhoprime)) + defer crypto.zero_explicit(&mat_, size_of(mat_)) + defer crypto.zero_explicit(&w1_bytes_, size_of(w1_bytes_)) + defer polyvec_clear([]^Polyvec_L{&s1, &y}) + defer polyvec_clear([]^Polyvec_K{&t0, &s2, &w1, &w0}) + defer crypto.zero_explicit(&cp, size_of(cp)) + + sig: Signature = --- + sig.params = params + h := &sig.h + z := &sig.z + c := sig.c[:params.ctild_bytes] + + w1_bytes := w1_bytes_[:params.k*polyw1_packedbytes(params)] + + // Compute mu = CRH(tr, pre, msg) + if len(external_mu) == 0 { + // The FIPS publication handles the shake prefix + // in the public sign operation, but doing it + // here makes more sense. + ctx_buf: [2]byte + shake_ctx: shake.Context = --- + defer shake.reset(&shake_ctx) + + ctx_len := len(ctx) + + shake.init_256(&shake_ctx) + shake.write(&shake_ctx, priv_key.tr[:]) + if ctx_len > 0 { + ctx_buf[1] = byte(ctx_len) + } + shake.write(&shake_ctx, ctx_buf[:]) + if ctx_len > 0 { + shake.write(&shake_ctx, ctx) + } + shake.write(&shake_ctx, m) + shake.read(&shake_ctx, mu[:]) + } else { + ensure(len(external_mu) == CRHBYTES, "crypto/mlkem: invalid external mu") + copy(mu[:], external_mu) + } + + // Compute rhoprime = CRH(key, rnd, mu) + shake256(rhoprime[:], priv_key.key[:], rnd, mu[:]) + + // Expand matrix and transform vectors + mat := mat_[:params.k] + polyvec_matrix_expand(mat, priv_key.rho[:], params) + polyvec_l_ntt(&s1, params) + polyvec_k_ntt(&s2, params) + polyvec_k_ntt(&t0, params) + + // Rejection-sampling loop + iv: u32 // ref uses u16, but ML-DSA-87 will reuse the IV at p = ~2^{-23400} + for { + // Sample intermediate vector y + polyvec_l_uniform_gamma1(&y, rhoprime[:], iv, params) + iv += 1 + + // Matrix-vector multiplication + polyvec_copy(z, &y, params) + polyvec_l_ntt(z, params) + polyvec_matrix_pointwise_montgomery(&w1, mat, z, params) + polyvec_k_reduce(&w1, params) + polyvec_k_invntt_tomont(&w1, params) + + // Decompose w and call the random oracle + polyvec_k_caddq(&w1, params) + polyvec_k_decompose(&w1, &w0, &w1, params) + polyvec_k_pack_w1(w1_bytes, &w1, params) + + shake256(c, mu[:], w1_bytes) + poly_challenge(&cp, c, params) + poly_ntt(&cp) + + // Compute z, reject if it reveals secret + polyvec_l_pointwise_poly_montgomery(z, &cp, &s1, params) + polyvec_l_invntt_tomont(z, params) + polyvec_l_add(z, z, &y, params) + polyvec_l_reduce(z, params) + if polyvec_l_chknorm(z, params.gamma1 - params.beta, params) { + continue + } + + // Check that subtracting cs2 does not change high bits of w + // and low bits do not reveal secret information + polyvec_k_pointwise_poly_montgomery(h, &cp, &s2, params) + polyvec_k_invntt_tomont(h, params) + polyvec_k_sub(&w0, &w0, h, params) + polyvec_k_reduce(&w0, params) + if polyvec_k_chknorm(&w0, params.gamma2 - params.beta, params) { + continue + } + + // Compute hints for w1 + polyvec_k_pointwise_poly_montgomery(h, &cp, &t0, params) + polyvec_k_invntt_tomont(h, params) + polyvec_k_reduce(h, params) + if polyvec_k_chknorm(h, params.gamma2, params) { + continue + } + + polyvec_k_add(&w0, &w0, h, params) + n := polyvec_k_make_hint(h, &w0, &w1, params) + if n <= uint(params.omega) { + break + } + } + + // Write signature + return pack_sig(sig_bytes, &sig) +} + +dsa_verify_internal :: proc( + sig_bytes: []byte, + m: []byte, + ctx: []byte, + pub_key: ^Public_Key, +) -> bool { + ensure(len(ctx) <= CTXBYTES_MAX, "crypto/mlkem: invalid contxt size") + + params := pub_key.params + switch params { + case &Params_44, &Params_65, &Params_87: + case: + return false + } + + sig: Signature = --- + if !unpack_sig(&sig, sig_bytes, params) { + return false + } + if polyvec_l_chknorm(&sig.z, params.gamma1 - params.beta, params) { + return false + } + c := sig.c[:params.ctild_bytes] + z := &sig.z + h := &sig.h + + t1: Polyvec_K = --- + polyvec_copy(&t1, &pub_key.t1, params) + rho := pub_key.rho[:] + + // Compute CRH(H(rho, t1), pre, msg) + mu: [CRHBYTES]byte + { + // The FIPS publication handles the shake prefix + // in the public sign operation, but doing it + // here makes more sense. + ctx_buf: [2]byte + shake_ctx: shake.Context = --- + defer shake.reset(&shake_ctx) + + ctx_len := len(ctx) + + shake.init_256(&shake_ctx) + shake.write(&shake_ctx, pub_key.mu[:]) + if ctx_len > 0 { + ctx_buf[1] = byte(ctx_len) + } + shake.write(&shake_ctx, ctx_buf[:]) + if ctx_len > 0 { + shake.write(&shake_ctx, ctx) + } + shake.write(&shake_ctx, m) + shake.read(&shake_ctx, mu[:]) + } + + // Matrix-vector multiplication; compute Az - c2^dt1 + mat_: [K_MAX]Polyvec_L + w1: Polyvec_K = --- + cp: Poly = --- + mat := mat_[:params.l] + + poly_challenge(&cp, c, params) + polyvec_matrix_expand(mat, rho, params) + + polyvec_l_ntt(z, params) + polyvec_matrix_pointwise_montgomery(&w1, mat, z, params) + + poly_ntt(&cp) + polyvec_k_shiftl(&t1, params) + polyvec_k_ntt(&t1, params) + polyvec_k_pointwise_poly_montgomery(&t1, &cp, &t1, params) + + polyvec_k_sub(&w1, &w1, &t1, params) + polyvec_k_reduce(&w1, params) + polyvec_k_invntt_tomont(&w1, params) + + // Reconstruct w1 + buf_: [K_MAX*POLYW1_PACKEDBYTES_MAX]byte = --- + buf := buf_[:params.k*polyw1_packedbytes(params)] + polyvec_k_caddq(&w1, params) + polyvec_k_use_hint(&w1, &w1, h, params) + polyvec_k_pack_w1(buf, &w1, params) + + // Call random oracle and verify challenge + c2_: [CTILDBYTES_MAX]byte + c2 := c2_[:params.ctild_bytes] + shake256(c2, mu[:], buf) + + // Note/perf: Can be vartime + return crypto.compare_constant_time(c, c2) == 1 +} diff --git a/core/crypto/_mldsa/ntt.odin b/core/crypto/_mldsa/ntt.odin new file mode 100644 index 000000000..c36f88327 --- /dev/null +++ b/core/crypto/_mldsa/ntt.odin @@ -0,0 +1,75 @@ +#+private +package _mldsa + +@(rodata) +ZETAS := [N]i32 { + 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, + 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, + 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, + -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, + -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, + -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, + -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, + -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, + 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, + -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, + -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, + -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, + 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, + 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782, +} + +ntt :: proc "contextless" (a: ^[N]i32) #no_bounds_check { + j, k := 0, 1 + for l := 128; l > 0; l >>= 1 { + for start := 0; start < N; start = j + l { + zeta := ZETAS[k] + k += 1 + for j = start; j < start + l; j += 1 { + t := montgomery_reduce(i64(zeta) * i64(a[j + l])) + a[j + l] = a[j] - t + a[j] = a[j] + t + } + } + } +} + +invntt_tomont :: proc "contextless" (a: ^[N]i32) #no_bounds_check { + F :: 41978 // mont^2/256 + + j, k := 0, 255 + for l := 1; l < N; l <<= 1 { + for start := 0; start < N; start = j + l { + zeta := -ZETAS[k] + k -= 1 + for j = start; j < start + l; j += 1 { + t := a[j] + a[j] = t + a[j + l] + a[j + l] = t - a[j + l] + a[j + l] = montgomery_reduce(i64(zeta) * i64(a[j + l])) + } + } + } + + for i in 0.. bool { + if len(pk_bytes) != public_key_size(pub_key.params) { + return false + } + + seed_bytes, t1_bytes := pk_bytes[:SEEDBYTES], pk_bytes[SEEDBYTES:] + + copy(seed_bytes, pub_key.rho[:]) + + for i in 0.. bool { + if len(pk_bytes) != public_key_size(params) { + return false + } + + seed_bytes, t1_bytes := pk_bytes[:SEEDBYTES], pk_bytes[SEEDBYTES:] + + pub_key.params = params + + copy(pub_key.rho[:], seed_bytes) + + for i in 0.. bool { + params := priv_key.params + if len(sk_bytes) != private_key_size(params) { + return false + } + + sk_bytes := sk_bytes + polyeta_len := polyeta_packedbytes(params) + + copy(sk_bytes, priv_key.rho[:]) + sk_bytes = sk_bytes[SEEDBYTES:] + + copy(sk_bytes, priv_key.key[:]) + sk_bytes = sk_bytes[SEEDBYTES:] + + copy(sk_bytes, priv_key.tr[:]) + sk_bytes = sk_bytes[TRBYTES:] + + for i in 0.. bool { + if len(sig_bytes) != signature_size(sig.params) { + return false + } + + sig_bytes := sig_bytes + polyz_len := polyz_packedbytes(sig.params) + + copy(sig_bytes, sig.c[:sig.params.ctild_bytes]) + sig_bytes = sig_bytes[sig.params.ctild_bytes:] + + for i in 0.. bool { + if len(sig_bytes) != signature_size(params) { + return false + } + + intrinsics.mem_zero(sig, size_of(Signature)) + + sig_bytes := sig_bytes + polyz_len := polyz_packedbytes(params) + omega := params.omega + + copy(sig.c[:], sig_bytes[:params.ctild_bytes]) + sig_bytes = sig_bytes[params.ctild_bytes:] + + for i in 0.. byte(omega) { + return false + } + + for j := k; j < int(sig_bytes[omega + i]); j += 1 { + // Coefficients are ordered for strong unforgeability + if j > k && sig_bytes[j] <= sig_bytes[j-1] { + return false + } + sig.h.vec[i].coeffs[sig_bytes[j]] = 1 + } + + k = int(sig_bytes[omega + i]) + } + + // Extra indices are zero for strong unforgeability + for j := k; j < omega; j += 1 { + if sig_bytes[j] != 0 { + return false + } + } + + sig.params = params + + return true +} + +@(private,require_results) +public_key_size :: #force_inline proc "contextless" (params: ^Params) -> int { + return SEEDBYTES + params.k * POLYT1_PACKEDBYTES +} + +@(private,require_results) +private_key_size :: #force_inline proc "contextless" (params: ^Params) -> int { + return 2*SEEDBYTES + TRBYTES + (params.l + params.k) * polyeta_packedbytes(params) + params.k * POLYT0_PACKEDBYTES +} + +@(private,require_results) +signature_size :: #force_inline proc "contextless" (params: ^Params) -> int { + return params.ctild_bytes + params.l * polyz_packedbytes(params) + polyvech_packedbytes(params) +} diff --git a/core/crypto/_mldsa/poly.odin b/core/crypto/_mldsa/poly.odin new file mode 100644 index 000000000..985a807d2 --- /dev/null +++ b/core/crypto/_mldsa/poly.odin @@ -0,0 +1,564 @@ +#+private +package _mldsa + +import "base:intrinsics" +import "core:crypto" +import "core:crypto/shake" + +Poly :: struct { + coeffs: [N]i32, +} + +poly_reduce :: proc "contextless" (a: ^Poly) { + for v, i in a.coeffs { + a.coeffs[i] = reduce32(v) + } +} + +poly_caddq :: proc "contextless" (a: ^Poly) { + for v, i in a.coeffs { + a.coeffs[i] = caddq(v) + } +} + +poly_add :: proc "contextless" (c, a, b: ^Poly) #no_bounds_check { + for i in 0.. uint #no_bounds_check { + s: uint + + for i in 0.. bool #no_bounds_check { + // It is ok to leak which coefficient violates the bound since + // the probability for each coefficient is independent of secret + // data but we must not leak the sign of the centralized + // representative. + for i in 0..> 31 + t = a.coeffs[i] - (t & 2 * a.coeffs[i]) + + if t >= bound { + return true + } + } + + return false +} + +unchecked_get_u24le :: #force_inline proc "contextless" (b: []byte) -> u32 #no_bounds_check { + r := u32(b[0]) + r |= u32(b[1]) << 8 + r |= u32(b[2]) << 16 + return r +} + +rej_uniform :: proc "contextless" (a: []i32, buf: []byte) -> int #no_bounds_check { + ctr, pos: int + + a_len, b_len := len(a), len(buf) + for ctr < a_len && pos + 3 <= b_len { + t := unchecked_get_u24le(buf[pos:]) + t &= 0x7FFFFF + pos += 3 + + if t < Q { + a[ctr] = i32(t) + ctr += 1 + } + } + + return ctr +} + +poly_uniform :: proc(a: ^Poly, seed: []byte, iv: u16) #no_bounds_check { + // Note/yawning: The dilithium reference code does something + // inexplicably more complicated, but this is identical in + // behavior, and simpler. + #assert(STREAM128_BLOCKBYTES % 3 == 0) + POLY_UNIFORM_NBLOCKS :: ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) + + buf: [POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + ctx: shake.Context = --- + defer shake.reset(&ctx) + stream128_init(&ctx, seed, iv) + + shake.read(&ctx, buf[:]) + ctr := rej_uniform(a.coeffs[:], buf[:]) + + b := buf[:STREAM128_BLOCKBYTES] + for ctr < N { + shake.read(&ctx, b) + ctr += rej_uniform(a.coeffs[ctr:], b) + } +} + +rej_eta :: proc "contextless" (a: []i32, buf: []byte, params: ^Params) -> int { + ctr, pos: int + a_len, b_len := len(a), len(buf) + switch params.eta { + case 2: + for ctr < a_len && pos < b_len { + t0 := u32(buf[pos] & 0x0F) + t1 := u32(buf[pos] >> 4) + pos += 1 + + if t0 < 15 { + t0 = t0 - (205 * t0 >> 10) * 5 + a[ctr] = i32(2 - t0) + ctr += 1 + } + if t1 < 15 && ctr < a_len { + t1 = t1 - (205 * t1 >> 10) * 5 + a[ctr] = i32(2 - t1) + ctr += 1 + } + } + case 4: + for ctr < a_len && pos < b_len { + t0 := u32(buf[pos] & 0x0F) + t1 := u32(buf[pos] >> 4) + pos += 1 + + if t0 < 9 { + a[ctr] = i32(4 - t0) + ctr += 1 + } + if t1 < 9 && ctr < a_len { + a[ctr] = i32(4 - t1) + ctr += 1 + } + } + case: + unreachable() + } + + return ctr +} + +poly_uniform_eta :: proc(a: ^Poly, seed: []byte, iv: u16, params: ^Params) { + POLY_UNIFORM_ETA2_NBLOCKS :: ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) + POLY_UNIFORM_ETA4_NBLOCKS :: ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) + + buf_: [POLY_UNIFORM_ETA4_NBLOCKS*STREAM256_BLOCKBYTES]byte = --- + buf: []byte + switch params.eta { + case 2: + buf = buf_[:POLY_UNIFORM_ETA2_NBLOCKS*STREAM256_BLOCKBYTES] + case 4: + buf = buf_[:POLY_UNIFORM_ETA4_NBLOCKS*STREAM256_BLOCKBYTES] + case: + unreachable() + } + defer crypto.zero_explicit(&buf_, size_of(buf_)) + + ctx: shake.Context = --- + defer shake.reset(&ctx) + stream256_init(&ctx, seed, iv) + + shake.read(&ctx, buf) + ctr := rej_eta(a.coeffs[:], buf, params) + + b := buf[:STREAM256_BLOCKBYTES] + for ctr < N { + shake.read(&ctx, b) + ctr += rej_eta(a.coeffs[ctr:], b, params) + } +} + +poly_uniform_gamma1 :: proc(a: ^Poly, seed: []byte, iv: u16, params: ^Params) { + POLY_UNIFORM_GAMMA1_NBLOCKS_MAX :: ((POLYZ_PACKEDBYTES_MAX + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) + + n_blocks := (polyz_packedbytes(params) + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES + + buf_: [POLY_UNIFORM_GAMMA1_NBLOCKS_MAX*STREAM256_BLOCKBYTES]byte = --- + buf := buf_[:n_blocks*STREAM256_BLOCKBYTES] + defer crypto.zero_explicit(&buf_, size_of(buf_)) + + ctx: shake.Context = --- + defer shake.reset(&ctx) + stream256_init(&ctx, seed, iv) + + shake.read(&ctx, buf) + polyz_unpack(a, buf, params) +} + +poly_challenge :: proc(c: ^Poly, seed: []byte, params: ^Params) #no_bounds_check { + buf: [STREAM256_BLOCKBYTES]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + ctx: shake.Context = --- + defer shake.reset(&ctx) + + shake.init_256(&ctx) + shake.write(&ctx, seed) + shake.read(&ctx, buf[:]) + + signs: u64 + for i in uint(0)..<8 { + signs |= u64(buf[i]) << (8*i) + } + pos := 8 + + b: int + intrinsics.mem_zero(c, size_of(Poly)) + for i := N - params.tau; i < N; i+= 1 { + for { + if pos >= STREAM256_BLOCKBYTES { + shake.read(&ctx, buf[:]) + pos = 0 + } + + b = int(buf[pos]) + pos += 1 + if b <= i { + break + } + } + + c.coeffs[i] = c.coeffs[b] + c.coeffs[b] = i32(1 - 2 * (signs & 1)) + signs >>= 1 + } +} + +polyeta_pack :: proc "contextless" (r: []byte, a: ^Poly, params: ^Params) #no_bounds_check { + t: [8]byte = --- + defer crypto.zero_explicit(&t, size_of(t)) + + eta := params.eta + switch eta { + case 2: + for i in 0..> 0) | (t[1] << 3) | (t[2] << 6) + r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7) + r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5) + } + case 4: + for i in 0..> 0) & 7) + r.coeffs[8*i+1] = i32((a[3*i+0] >> 3) & 7) + r.coeffs[8*i+2] = i32(((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7) + r.coeffs[8*i+3] = i32((a[3*i+1] >> 1) & 7) + r.coeffs[8*i+4] = i32((a[3*i+1] >> 4) & 7) + r.coeffs[8*i+5] = i32(((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7) + r.coeffs[8*i+6] = i32((a[3*i+2] >> 2) & 7) + r.coeffs[8*i+7] = i32((a[3*i+2] >> 5) & 7) + + r.coeffs[8*i+0] = eta - r.coeffs[8*i+0] + r.coeffs[8*i+1] = eta - r.coeffs[8*i+1] + r.coeffs[8*i+2] = eta - r.coeffs[8*i+2] + r.coeffs[8*i+3] = eta - r.coeffs[8*i+3] + r.coeffs[8*i+4] = eta - r.coeffs[8*i+4] + r.coeffs[8*i+5] = eta - r.coeffs[8*i+5] + r.coeffs[8*i+6] = eta - r.coeffs[8*i+6] + r.coeffs[8*i+7] = eta - r.coeffs[8*i+7] + } + case 4: + for i in 0..> 4) + r.coeffs[2*i+0] = eta - r.coeffs[2*i+0] + r.coeffs[2*i+1] = eta - r.coeffs[2*i+1] + } + case: + unreachable() + } +} + +polyt1_pack :: proc "contextless" (r: []byte, a: ^Poly) #no_bounds_check { + for i in 0..> 0) + r[5*i+1] = byte((a.coeffs[4*i+0] >> 8) | (a.coeffs[4*i+1] << 2)) + r[5*i+2] = byte((a.coeffs[4*i+1] >> 6) | (a.coeffs[4*i+2] << 4)) + r[5*i+3] = byte((a.coeffs[4*i+2] >> 4) | (a.coeffs[4*i+3] << 6)) + r[5*i+4] = byte(a.coeffs[4*i+3] >> 2) + } +} + +polyt1_unpack :: proc "contextless" (r: ^Poly, a: []byte) #no_bounds_check { + for i in 0..> 0) | (u32(a[5*i+1]) << 8)) & 0x3FF) + r.coeffs[4*i+1] = i32((u32(a[5*i+1] >> 2) | (u32(a[5*i+2]) << 6)) & 0x3FF) + r.coeffs[4*i+2] = i32((u32(a[5*i+2] >> 4) | (u32(a[5*i+3]) << 4)) & 0x3FF) + r.coeffs[4*i+3] = i32((u32(a[5*i+3] >> 6) | (u32(a[5*i+4]) << 2)) & 0x3FF) + } +} + +polyt0_pack :: proc "contextless" (r: []byte, a: ^Poly) #no_bounds_check { + t: [8]byte = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 8 + r[13*i+ 1] |= t[1] << 5 + r[13*i+ 2] = t[1] >> 3 + r[13*i+ 3] = t[1] >> 11 + r[13*i+ 3] |= t[2] << 2 + r[13*i+ 4] = t[2] >> 6 + r[13*i+ 4] |= t[3] << 7 + r[13*i+ 5] = t[3] >> 1 + r[13*i+ 6] = t[3] >> 9 + r[13*i+ 6] |= t[4] << 4 + r[13*i+ 7] = t[4] >> 4 + r[13*i+ 8] = t[4] >> 12 + r[13*i+ 8] |= t[5] << 1 + r[13*i+ 9] = t[5] >> 7 + r[13*i+ 9] |= t[6] << 6 + r[13*i+10] = t[6] >> 2 + r[13*i+11] = t[6] >> 10 + r[13*i+11] |= t[7] << 3 + r[13*i+12] = t[7] >> 5 + } +} + +polyt0_unpack :: proc "contextless" (r: ^Poly, a: []byte) #no_bounds_check { + for i in 0..> 5) + r.coeffs[8*i+1] |= i32(u32(a[13*i+2]) << 3) + r.coeffs[8*i+1] |= i32(u32(a[13*i+3]) << 11) + r.coeffs[8*i+1] &= 0x1FFF + + r.coeffs[8*i+2] = i32(a[13*i+3] >> 2) + r.coeffs[8*i+2] |= i32(u32(a[13*i+4]) << 6) + r.coeffs[8*i+2] &= 0x1FFF + + r.coeffs[8*i+3] = i32(a[13*i+4] >> 7) + r.coeffs[8*i+3] |= i32(u32(a[13*i+5]) << 1) + r.coeffs[8*i+3] |= i32(u32(a[13*i+6]) << 9) + r.coeffs[8*i+3] &= 0x1FFF + + r.coeffs[8*i+4] = i32(a[13*i+6] >> 4) + r.coeffs[8*i+4] |= i32(u32(a[13*i+7]) << 4) + r.coeffs[8*i+4] |= i32(u32(a[13*i+8]) << 12) + r.coeffs[8*i+4] &= 0x1FFF + + r.coeffs[8*i+5] = i32(a[13*i+8] >> 1) + r.coeffs[8*i+5] |= i32(u32(a[13*i+9]) << 7) + r.coeffs[8*i+5] &= 0x1FFF + + r.coeffs[8*i+6] = i32(a[13*i+9] >> 6) + r.coeffs[8*i+6] |= i32(u32(a[13*i+10]) << 2) + r.coeffs[8*i+6] |= i32(u32(a[13*i+11]) << 10) + r.coeffs[8*i+6] &= 0x1FFF + + r.coeffs[8*i+7] = i32(a[13*i+11] >> 3) + r.coeffs[8*i+7] |= i32(u32(a[13*i+12]) << 5) + r.coeffs[8*i+7] &= 0x1FFF + + r.coeffs[8*i+0] = (1 << (D-1)) - r.coeffs[8*i+0] + r.coeffs[8*i+1] = (1 << (D-1)) - r.coeffs[8*i+1] + r.coeffs[8*i+2] = (1 << (D-1)) - r.coeffs[8*i+2] + r.coeffs[8*i+3] = (1 << (D-1)) - r.coeffs[8*i+3] + r.coeffs[8*i+4] = (1 << (D-1)) - r.coeffs[8*i+4] + r.coeffs[8*i+5] = (1 << (D-1)) - r.coeffs[8*i+5] + r.coeffs[8*i+6] = (1 << (D-1)) - r.coeffs[8*i+6] + r.coeffs[8*i+7] = (1 << (D-1)) - r.coeffs[8*i+7] + } +} + +polyz_pack :: proc "contextless" (r: []byte, a: ^Poly, params: ^Params) #no_bounds_check { + t: [4]u32 = --- + defer crypto.zero_explicit(&t, size_of(t)) + + gamma1 := params.gamma1 + switch gamma1 { + case 1 << 17: + for i in 0..> 8) + r[9*i+2] = byte(t[0] >> 16) + r[9*i+2] |= byte(t[1] << 2) + r[9*i+3] = byte(t[1] >> 6) + r[9*i+4] = byte(t[1] >> 14) + r[9*i+4] |= byte(t[2] << 4) + r[9*i+5] = byte(t[2] >> 4) + r[9*i+6] = byte(t[2] >> 12) + r[9*i+6] |= byte(t[3] << 6) + r[9*i+7] = byte(t[3] >> 2) + r[9*i+8] = byte(t[3] >> 10) + } + case 1 << 19: + for i in 0..> 8) + r[5*i+2] = byte(t[0] >> 16) + r[5*i+2] |= byte(t[1] << 4) + r[5*i+3] = byte(t[1] >> 4) + r[5*i+4] = byte(t[1] >> 12) + } + case: + unreachable() + } +} + +polyz_unpack :: proc "contextless" (r: ^Poly, a: []byte, params: ^Params) #no_bounds_check { + gamma1 := params.gamma1 + switch gamma1 { + case 1 << 17: + for i in 0..> 2) + r.coeffs[4*i+1] |= i32(u32(a[9*i+3]) << 6) + r.coeffs[4*i+1] |= i32(u32(a[9*i+4]) << 14) + r.coeffs[4*i+1] &= 0x3FFFF + + r.coeffs[4*i+2] = i32(a[9*i+4] >> 4) + r.coeffs[4*i+2] |= i32(u32(a[9*i+5]) << 4) + r.coeffs[4*i+2] |= i32(u32(a[9*i+6]) << 12) + r.coeffs[4*i+2] &= 0x3FFFF + + r.coeffs[4*i+3] = i32(a[9*i+6] >> 6) + r.coeffs[4*i+3] |= i32(u32(a[9*i+7]) << 2) + r.coeffs[4*i+3] |= i32(u32(a[9*i+8]) << 10) + r.coeffs[4*i+3] &= 0x3FFFF + + r.coeffs[4*i+0] = gamma1 - r.coeffs[4*i+0] + r.coeffs[4*i+1] = gamma1 - r.coeffs[4*i+1] + r.coeffs[4*i+2] = gamma1 - r.coeffs[4*i+2] + r.coeffs[4*i+3] = gamma1 - r.coeffs[4*i+3] + } + case 1 << 19: + for i in 0..> 4) + r.coeffs[2*i+1] |= i32(u32(a[5*i+3]) << 4) + r.coeffs[2*i+1] |= i32(u32(a[5*i+4]) << 12) + /* r.coeffs[2*i+1] &= 0xFFFFF */ /* No effect, since we're anyway at 20 bits */ + + r.coeffs[2*i+0] = gamma1 - r.coeffs[2*i+0] + r.coeffs[2*i+1] = gamma1 - r.coeffs[2*i+1] + } + case: + unreachable() + } +} + +polyw1_pack :: proc "contextless" (r: []byte, a: ^Poly, params: ^Params) #no_bounds_check { + switch params.gamma2 { + case (Q-1)/88: + for i in 0..> 2) + r[3*i+1] |= byte(a.coeffs[4*i+2] << 4) + r[3*i+2] = byte(a.coeffs[4*i+2] >> 4) + r[3*i+2] |= byte(a.coeffs[4*i+3] << 2) + } + case (Q-1)/32: + for i in 0.. bool #no_bounds_check { + for i in 0.. bool #no_bounds_check { + for i in 0.. uint #no_bounds_check { + s: uint + + for i in 0.. i32 { + QINV :: 58728449 // q^(-1) mod 2^32 + + t := i32(i64(i32(a)) * QINV) + t = i32((a - i64(t) * Q) >> 32) + return t +} + +@(require_results) +reduce32 :: #force_inline proc "contextless" (a: i32) -> i32 { + t := (a + (1 << 22)) >> 23 + t = a - t * Q + return t +} + +@(require_results) +caddq :: #force_inline proc "contextless" (a: i32) -> i32 { + a := a + a += (a >> 31) & Q + return a +} + +// @(require_results) +// freeze :: #force_inline proc "contextless" (a: i32) -> i32 { +// a := a +// a = reduce32(a) +// a = caddq(a) +// return a +// } diff --git a/core/crypto/_mldsa/rounding.odin b/core/crypto/_mldsa/rounding.odin new file mode 100644 index 000000000..a879d6159 --- /dev/null +++ b/core/crypto/_mldsa/rounding.odin @@ -0,0 +1,56 @@ +#+private +package _mldsa + +power2round :: proc "contextless" (a: i32) -> (i32, i32) { + a1 := (a + (1 << (D-1)) - 1) >> D + a0 := a - (a1 << D) + return a0, a1 +} + +decompose :: proc "contextless" (a: i32, gamma2: i32) -> (i32, i32) { + a1 := (a + 127) >> 7 + switch gamma2 { + case (Q - 1)/32: + a1 = (a1 * 1025 + (1 << 21)) >> 22 + a1 &= 15 + case (Q - 1)/88: + a1 = (a1 * 11275 + (1 << 23)) >> 24 + a1 ~= ((43 - a1) >> 31) & a1 + } + + a0 := a - a1 * 2 * gamma2 + a0 -= (((Q - 1)/2 - a0) >> 31) & Q + return a0, a1 +} + +make_hint :: proc "contextless" (a0, a1: i32, gamma2: i32) -> uint { + if (a0 > gamma2 || a0 < -gamma2 || (a0 == -gamma2 && a1 != 0)) { + return 1 + } + return 0 +} + +use_hint :: proc "contextless" (a: i32, hint: uint, gamma2: i32) -> i32 { + a0, a1 := decompose(a, gamma2) + if hint == 0 { + return a1 + } + + switch gamma2 { + case (Q - 1)/32: + if (a0 > 0) { + return (a1 + 1) & 15 + } else { + return (a1 -1) & 15 + } + case (Q - 1)/88: + if (a0 > 0) { + return (a1 == 43) ? 0 : a1 + 1 + } else { + return (a1 == 0) ? 43 : a1 - 1 + } + } + + unreachable() +} + diff --git a/core/crypto/_mldsa/symmetric_shake.odin b/core/crypto/_mldsa/symmetric_shake.odin new file mode 100644 index 000000000..5c0aa99d6 --- /dev/null +++ b/core/crypto/_mldsa/symmetric_shake.odin @@ -0,0 +1,39 @@ +#+private +package _mldsa + +import "core:crypto/_sha3" +import "core:crypto/shake" + +STREAM128_BLOCKBYTES :: _sha3.RATE_128 +STREAM256_BLOCKBYTES :: _sha3.RATE_256 + +stream128_init :: proc(ctx: ^shake.Context, seed: []byte, iv: u16) { + t: [2]byte = --- + t[0] = byte(iv) + t[1] = byte(iv >> 8) + + shake.init_128(ctx) + shake.write(ctx, seed) + shake.write(ctx, t[:]) +} + +stream256_init :: proc(ctx: ^shake.Context, seed: []byte, iv: u16) { + t: [2]byte = --- + t[0] = byte(iv) + t[1] = byte(iv >> 8) + + shake.init_256(ctx) + shake.write(ctx, seed) + shake.write(ctx, t[:]) +} + +shake256 :: proc(dst: []byte, srcs: ..[]byte) { + ctx: shake.Context = --- + defer shake.reset(&ctx) + + shake.init_256(&ctx) + for src in srcs { + shake.write(&ctx, src) + } + shake.read(&ctx, dst) +} diff --git a/core/crypto/_mlkem/cbd.odin b/core/crypto/_mlkem/cbd.odin new file mode 100644 index 000000000..301551ff5 --- /dev/null +++ b/core/crypto/_mlkem/cbd.odin @@ -0,0 +1,52 @@ +#+private +package _mlkem + +import "core:encoding/endian" + +unchecked_get_u24le :: #force_inline proc "contextless" (b: []byte) -> u32 #no_bounds_check { + r := u32(b[0]) + r |= u32(b[1]) << 8 + r |= u32(b[2]) << 16 + return r +} + +cbd3 :: proc "contextless" (r: ^Poly, buf: ^[3*N/4]byte) #no_bounds_check { + for i in 0..>1) & 0x00249249 + d += (t>>2) & 0x00249249 + + for j in uint(0)..<4 { + a := i16((d >> (6*j+0)) & 0x7) + b := i16((d >> (6*j+3)) & 0x7) + r.coeffs[4*i+int(j)] = a - b + } + } +} + +cbd2 :: proc "contextless" (r: ^Poly, buf: ^[2*N/4]byte) #no_bounds_check { + for i in 0..>1) & 0x55555555 + + for j in uint(0)..<8 { + a := i16((d >> (4*j+0)) & 0x3) + b := i16((d >> (4*j+2)) & 0x3) + r.coeffs[8*i+int(j)] = a - b + } + } +} + +poly_cbd_eta1_512 :: proc "contextless" (r: ^Poly, buf: ^[ETA1_512*N/4]byte) { + cbd3(r, buf) +} + +poly_cbd_eta1 :: proc "contextless" (r: ^Poly, buf: ^[ETA1*N/4]byte) { + cbd2(r, buf) +} + +poly_cbd_eta2 :: proc "contextless" (r: ^Poly, buf: ^[ETA2*N/4]byte) { + cbd2(r, buf) +} diff --git a/core/crypto/_mlkem/constants.odin b/core/crypto/_mlkem/constants.odin new file mode 100644 index 000000000..7195d8b61 --- /dev/null +++ b/core/crypto/_mlkem/constants.odin @@ -0,0 +1,53 @@ +package _mlkem + +K_512 :: 2 +K_768 :: 3 +K_1024 :: 4 +K_MAX :: K_1024 + +N :: 256 +Q :: 3329 + +ETA1_512 :: 3 +ETA1 :: 2 +ETA2 :: 2 + +POLYBYTES :: 384 +SYMBYTES :: 32 + +POLYCOMPRESSEDBYTES_512 :: 128 +POLYCOMPRESSEDBYTES_768 :: 128 +POLYCOMPRESSEDBYTES_1024 :: 160 + +POLYVECBYTES_512 :: K_512 * POLYBYTES +POLYVECBYTES_768 :: K_768 * POLYBYTES +POLYVECBYTES_1024 :: K_1024 * POLYBYTES + +POLYVECCOMPRESSEDBYTES_512 :: K_512 * 320 +POLYVECCOMPRESSEDBYTES_768 :: K_768 * 320 +POLYVECCOMPRESSEDBYTES_1024 :: K_1024 * 352 + +INDCPA_MSGBYTES :: SYMBYTES +INDCPA_PUBLICKEYBYTES_512 :: POLYVECBYTES_512 + SYMBYTES +INDCPA_SECRETKEYBYTES_512 :: POLYVECBYTES_512 +INDCPA_PUBLICKEYBYTES_768 :: POLYVECBYTES_768 + SYMBYTES +INDCPA_SECRETKEYBYTES_768 :: POLYVECBYTES_768 +INDCPA_PUBLICKEYBYTES_1024 :: POLYVECBYTES_1024 + SYMBYTES +INDCPA_SECRETKEYBYTES_1024 :: POLYVECBYTES_1024 +INDCPA_PUBLICKEYBYTES_MAX :: INDCPA_PUBLICKEYBYTES_1024 +INDCPA_BYTES_512 :: POLYVECCOMPRESSEDBYTES_512 + POLYCOMPRESSEDBYTES_512 +INDCPA_BYTES_768 :: POLYVECCOMPRESSEDBYTES_768 + POLYCOMPRESSEDBYTES_768 +INDCPA_BYTES_1024 :: POLYVECCOMPRESSEDBYTES_1024 + POLYCOMPRESSEDBYTES_1024 + +ENCAPSKEYBYTES_512 :: INDCPA_PUBLICKEYBYTES_512 +ENCAPSKEYBYTES_768 :: INDCPA_PUBLICKEYBYTES_768 +ENCAPSKEYBYTES_1024 :: INDCPA_PUBLICKEYBYTES_1024 + +DECAPSKEYBYTES_512 :: INDCPA_SECRETKEYBYTES_512 + INDCPA_PUBLICKEYBYTES_512 + 2 * SYMBYTES +DECAPSKEYBYTES_768 :: INDCPA_SECRETKEYBYTES_768 + INDCPA_PUBLICKEYBYTES_768 + 2 * SYMBYTES +DECAPSKEYBYTES_1024 :: INDCPA_SECRETKEYBYTES_1024 + INDCPA_PUBLICKEYBYTES_1024 + 2 * SYMBYTES + +CIPHERTEXTBYTES_512 :: INDCPA_BYTES_512 +CIPHERTEXTBYTES_768 :: INDCPA_BYTES_768 +CIPHERTEXTBYTES_1024 :: INDCPA_BYTES_1024 +CIPHERTEXTBYTES_MAX :: INDCPA_BYTES_1024 diff --git a/core/crypto/_mlkem/k_pke.odin b/core/crypto/_mlkem/k_pke.odin new file mode 100644 index 000000000..d8b87ad7a --- /dev/null +++ b/core/crypto/_mlkem/k_pke.odin @@ -0,0 +1,349 @@ +#+private +package _mlkem + +import "core:crypto" +import "core:crypto/shake" + +@(require_results) +pack_pk :: proc "contextless" (r: []byte, pk: ^Polyvec, seed: []byte, k: int) -> bool { + pk_len := polyvec_byte_size(k) + switch { + case pk_len == 0: + return false + case len(seed) != SYMBYTES || len(r) != pk_len + SYMBYTES: + return false + } + + polyvec_tobytes(r[:pk_len], pk, k) + copy(r[pk_len:], seed) + + return true +} + +@(require_results) +unpack_pk :: proc "contextless" (pk: ^Polyvec, seed, packedpk: []byte) -> bool { + pk_len := len(packedpk) - SYMBYTES + k: int + switch { + case pk_len == POLYVECBYTES_512: + k = K_512 + case pk_len == POLYVECBYTES_768: + k = K_768 + case pk_len == POLYVECBYTES_1024: + k = K_1024 + case len(packedpk) - pk_len != SYMBYTES: + return false + case len(seed) != SYMBYTES: + return false + } + if k == 0 { + return false + } + + ok := polyvec_frombytes(pk, packedpk[:pk_len], k) + copy(seed, packedpk[pk_len:]) + + return ok +} + +@(require_results) +pack_sk :: proc "contextless" (r: []byte, sk: ^Polyvec, k: int) -> bool { + r_len := len(r) + if r_len == 0 || r_len != polyvec_byte_size(k) { + return false + } + + polyvec_tobytes(r, sk, k) + + return true +} + +@(require_results) +unpack_sk :: proc "contextless" (sk: ^Polyvec, packedsk: []byte) -> bool { + k: int + switch len(packedsk) { + case POLYVECBYTES_512: + k = K_512 + case POLYVECBYTES_768: + k = K_768 + case POLYVECBYTES_1024: + k = K_1024 + case: + return false + } + if k == 0 { + return false + } + + return polyvec_frombytes(sk, packedsk, k) +} + +@(require_results) +pack_ciphertext :: proc "contextless" (r: []byte, b: ^Polyvec, v: ^Poly, k: int) -> bool { + b_len := polyvec_compressed_byte_size(k) + if len(r) != b_len + poly_compressed_bytes(k) { + return false + } + + polyvec_compress(r[:b_len], b, k) + poly_compress(r[b_len:], v) + + return true +} + +@(require_results) +unpack_ciphertext :: proc "contextless" (b: ^Polyvec, v: ^Poly, c: []byte) -> int { + b_len: int + k: int + switch len(c) { + case INDCPA_BYTES_512: + b_len = POLYVECCOMPRESSEDBYTES_512 + k = K_512 + case INDCPA_BYTES_768: + b_len = POLYVECCOMPRESSEDBYTES_768 + k = K_768 + case INDCPA_BYTES_1024: + b_len = POLYVECCOMPRESSEDBYTES_1024 + k = K_1024 + case: + return 0 + } + + polyvec_decompress(b, c[:b_len], k) + poly_decompress(v, c[b_len:]) + + return k +} + +@(require_results) +rej_uniform :: proc "contextless" (r: []i16, buf: []byte) -> int { + r_len, b_len := len(r), len(buf) + + ctr, pos: int + for ctr < r_len && pos + 3 <= b_len { + val0 := (u16(buf[pos+0] >> 0) | (u16(buf[pos+1]) << 8)) & 0xFFF + val1 := (u16(buf[pos+1] >> 4) | (u16(buf[pos+2]) << 4)) & 0xFFF + pos += 3 + + if val0 < Q { + r[ctr] = i16(val0) + ctr += 1 + } + if(ctr < r_len && val1 < Q) { + r[ctr] = i16(val1) + ctr += 1 + } + } + + return ctr +} + +gen_matrix :: proc(a: []Polyvec, seed: []byte, transposed: bool, k: int) { + GEN_MATRIX_NBLOCKS :: ((12*N/8*(1 << 12)/Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES) + + buf: [GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES]byte = --- + ctx: shake.Context = --- + ctr: int + + defer shake.reset(&ctx) + defer crypto.zero_explicit(&buf, size_of(buf)) + + for i in 0.. bool { + ensure(len(m) == INDCPA_MSGBYTES, "crypto/mlkem: invalid K-PKE m") + ensure(len(r) == SYMBYTES, "crypto/mlkem: invalid K-PKE r") + + k := ek.k + + at_: [K_MAX]Polyvec = --- + sp, ep, b: Polyvec = ---, ---, --- + kay, epp, v: Poly = ---, ---, --- + defer crypto.zero_explicit(&at_, size_of(Polyvec) * k) + defer polyvec_clear(&sp, &ep, &b) + defer poly_clear(&kay, &epp, &v) + + poly_frommsg(&kay, m) + + at := at_[:k] + + gen_matrix(at, ek.p[:], true, k) + + n := byte(0) + for i in 0.. bool { + if len(plaintext) != INDCPA_MSGBYTES { + return false + } + + k := dk.k + + b: Polyvec = --- + v, mp: Poly = ---, --- + defer poly_clear(&v, &mp) + + if unpack_ciphertext(&b, &v, c) != k { + return false + } + + polyvec_ntt(&b, k) + polyvec_basemul_acc_montgomery(&mp, &dk.pv, &b, k) + poly_invntt_tomont(&mp) + + poly_sub(&mp, &v, &mp) + poly_reduce(&mp) + + poly_tomsg(plaintext, &mp) + + return true +} diff --git a/core/crypto/_mlkem/kem_internal.odin b/core/crypto/_mlkem/kem_internal.odin new file mode 100644 index 000000000..b50aa4b58 --- /dev/null +++ b/core/crypto/_mlkem/kem_internal.odin @@ -0,0 +1,195 @@ +package _mlkem + +import "core:crypto" +import subtle "core:crypto/_subtle" + +// This implementation is derived from the PQ-CRYSTALS reference +// implementation [[ https://github.com/pq-crystals/kyber ]], +// primarily for licensing reasons. Arguably mlkem-native is +// a more "up to date" codebase, but the changes to the +// ref code is minor and they slapped an attribution-required +// license on something that was originally CC-0/Apache 2.0. + +// "Private Key" +Decapsulation_Key :: struct { + pke_dk: K_PKE_Decryption_Key, + ek: Encapsulation_Key, + seed: [SYMBYTES*2]byte, // (d, z) +} + +// "Public Key" +Encapsulation_Key :: struct { + pke_ek: K_PKE_Encryption_Key, + raw_bytes: [INDCPA_PUBLICKEYBYTES_MAX]byte, + h: [SYMBYTES]byte, +} + +decapsulation_key_expanded_bytes :: proc( + dk: ^Decapsulation_Key, + dst: []byte, +) { + sk := &dk.pke_dk + pv_len := polyvec_byte_size(sk.k) + ek_len := pv_len + SYMBYTES + + ek_bytes := dk.ek.raw_bytes[:ek_len] + + dst := dst + _ = pack_sk(dst[:pv_len], &sk.pv, sk.k) + + dst = dst[pv_len:] + copy(dst, ek_bytes) + dst = dst[ek_len:] + hash_h(dst[:SYMBYTES], ek_bytes) + dst = dst[SYMBYTES:] + copy(dst, dk.seed[SYMBYTES:]) +} + +@(require_results) +encapsulation_key_set_bytes :: proc( + ek: ^Encapsulation_Key, + k: int, + b: []byte, +) -> bool { + k_len: int + switch k { + case K_512: + k_len = ENCAPSKEYBYTES_512 + case K_768: + k_len = ENCAPSKEYBYTES_768 + case K_1024: + k_len = ENCAPSKEYBYTES_1024 + case: + return false + } + if len(b) != k_len { + return false + } + + pke_ek := &ek.pke_ek + ok := unpack_pk(&pke_ek.pv, pke_ek.p[:], b) + pke_ek.k = k + copy(ek.raw_bytes[:k_len], b) + hash_h(ek.h[:], b) + + // FIPS 203 unlike Kyber requires canonical encoding of + // encapsulation keys (Section 7,2), which is checked in + // unpack_pk. + + if !ok { + crypto.zero_explicit(ek, size_of(Encapsulation_Key)) + } + + return ok +} + +encapsulation_key_set_decaps :: proc(ek: ^Encapsulation_Key, dk: ^Decapsulation_Key) { + dk_ek := &dk.ek.pke_ek + ensure(dk_ek.k == K_512 || dk_ek.k == K_768 || dk_ek.k == K_1024, "crypto/mlkem: invalid decaps k") + + k_pke_encryption_key_set(&ek.pke_ek, dk_ek) + copy(ek.raw_bytes[:], dk.ek.raw_bytes[:]) + copy(ek.h[:], dk.ek.h[:]) +} + +// NIST's version of this also returns an encapsulation key, but our +// internal representation includes it as part of the decapsulation key +// in a more traditional "keypair" approach. +kem_keygen_internal :: proc( + dk: ^Decapsulation_Key, + seed: []byte, // (d, z) + k: int, +) { + ensure(len(seed) == 2 * SYMBYTES, "crypto/mlkem: invalid seed") + + dk_ek := &dk.ek + d, z := seed[:SYMBYTES], seed[SYMBYTES:] + + k_pke_keygen(&dk_ek.pke_ek, &dk.pke_dk, d, k) + + ek_len := polyvec_byte_size(k) + SYMBYTES + ek_bytes := dk_ek.raw_bytes[:ek_len] + ensure( + pack_pk(ek_bytes, &dk_ek.pke_ek.pv, dk_ek.pke_ek.p[:], k), + "crypto/mlkem: failed to pack K-PKE ek", + ) + hash_h(dk_ek.h[:], ek_bytes) + copy(dk.seed[:SYMBYTES], d) + copy(dk.seed[SYMBYTES:], z) +} + +// The `_internal` "de-randomized" versions of ML-KEM.Encaps and +// ML-KEM.Decaps are only ever to be called by the actual non-interal +// implementation or test cases. + +kem_encaps_internal :: proc( + shared_secret: []byte, + ciphertext: []byte, + ek: ^Encapsulation_Key, + randomness: []byte, +) { + ensure(len(shared_secret) == SYMBYTES, "crypto/mlkem: invalid K") + ensure(len(randomness) == SYMBYTES, "crypto/mlkem: invalid m") + ensure( + len(ciphertext) == ct_len_for_k(ek.pke_ek.k), + "crypto/mlkem: invalid ciphertext length", + ) + + buf: [2*SYMBYTES]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + hash_g(buf[:], randomness, ek.h[:]) + + // Can't fail, ciphertext length is valid. + _ = k_pke_encrypt(ciphertext, &ek.pke_ek, randomness, buf[SYMBYTES:]) + + copy(shared_secret, buf[:SYMBYTES]) +} + +kem_decaps_internal :: proc( + shared_secret: []byte, + dk: ^Decapsulation_Key, + ciphertext: []byte, +) { + ct_len := ct_len_for_k(dk.pke_dk.k) + ensure( + len(ciphertext) == ct_len, + "crypto/mlkem: invalid ciphertext length", + ) + + m_: [SYMBYTES]byte + defer crypto.zero_explicit(&m_, size_of(m_)) + + // Can't fail, ciphertext length is valid. + _ = k_pke_decrypt(m_[:], &dk.pke_dk, ciphertext) + + buf: [2*SYMBYTES]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + ek := &dk.ek + hash_g(buf[:], m_[:], ek.h[:]) + + rkprf(shared_secret, dk.seed[SYMBYTES:], ciphertext) + + ct_buf: [CIPHERTEXTBYTES_MAX]byte = --- + defer crypto.zero_explicit(&ct_buf, size_of(ct_buf)) + ct_ := ct_buf[:ct_len] + _ = k_pke_encrypt(ct_, &ek.pke_ek, m_[:], buf[SYMBYTES:]) + + ok := crypto.compare_constant_time(ciphertext, ct_) + subtle.cmov_bytes(shared_secret, buf[:SYMBYTES], ok) +} + +@(private="file") +ct_len_for_k :: proc(k: int) -> int { + switch k { + case K_512: + return CIPHERTEXTBYTES_512 + case K_768: + return CIPHERTEXTBYTES_768 + case K_1024: + return CIPHERTEXTBYTES_1024 + case: + panic("crypto/mlkem: invalid k for ciphertext length") + } +} diff --git a/core/crypto/_mlkem/ntt.odin b/core/crypto/_mlkem/ntt.odin new file mode 100644 index 000000000..c99c73487 --- /dev/null +++ b/core/crypto/_mlkem/ntt.odin @@ -0,0 +1,75 @@ +#+private +package _mlkem + +@(rodata) +ZETAS := [128]i16 { + -1044, -758, -359, -1517, 1493, 1422, 287, 202, + -171, 622, 1577, 182, 962, -1202, -1474, 1468, + 573, -1325, 264, 383, -829, 1458, -1602, -130, + -681, 1017, 732, 608, -1542, 411, -205, -1571, + 1223, 652, -552, 1015, -1293, 1491, -282, -1544, + 516, -8, -320, -666, -1618, -1162, 126, 1469, + -853, -90, -271, 830, 107, -1421, -247, -951, + -398, 961, -1508, -725, 448, -1065, 677, -1275, + -1103, 430, 555, 843, -1251, 871, 1550, 105, + 422, 587, 177, -235, -291, -460, 1574, 1653, + -246, 778, 1159, -147, -777, 1483, -602, 1119, + -1590, 644, -872, 349, 418, 329, -156, -75, + 817, 1097, 603, 610, 1322, -1285, -1465, 384, + -1215, -136, 1218, -1335, -874, 220, -1187, -1659, + -1185, -1530, -1278, 794, -1510, -854, -870, 478, + -108, -308, 996, 991, 958, -1460, 1522, 1628, +} + +@(require_results) +fqmul :: #force_inline proc "contextless" (a, b: i16) -> i16 { + return montgomery_reduce(i32(a) * i32(b)) +} + +ntt :: proc "contextless" (r: ^[N]i16) #no_bounds_check { + j, k := 0, 1 + for l := 128; l >= 2; l >>= 1 { + for start := 0; start < N; start = j + l { + zeta := ZETAS[k] + k += 1 + for j = start; j < start + l; j += 1 { + t := fqmul(zeta, r[j+l]) + r[j+l] = r[j] - t + r[j] = r[j] + t + } + } + } +} + +invntt :: proc "contextless" (r: ^[N]i16) #no_bounds_check { + F : i16 : 1441 // mont^2/128 + + j, k := 0, 127 + for l := 2; l <= 128; l <<= 1 { + for start := 0; start < 256; start = j+l { + zeta := ZETAS[k] + k -= 1 + for j = start; j < start + l; j += 1 { + t := r[j] + r[j] = barrett_reduce(t + r[j+l]) + r[j+l] = r[j+l] - t + r[j+l] = fqmul(zeta, r[j+l]) + } + } + } + + for v, i in r { + r[i] = fqmul(v, F) + } +} + +@(require_results) +base_case_multiply :: proc "contextless" (a_0, a_1, b_0, b_1, zeta: i16) -> (i16, i16) { + r_0 := fqmul(a_1, b_1) + r_0 = fqmul(r_0, zeta) + r_0 += fqmul(a_0, b_0) + r_1 := fqmul(a_0, b_1) + r_1 += fqmul(a_1, b_0) + + return r_0, r_1 +} diff --git a/core/crypto/_mlkem/poly.odin b/core/crypto/_mlkem/poly.odin new file mode 100644 index 000000000..1982f9102 --- /dev/null +++ b/core/crypto/_mlkem/poly.odin @@ -0,0 +1,241 @@ +#+private +package _mlkem + +import "core:crypto" +import subtle "core:crypto/_subtle" + +// Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial +// coeffs[0] + X*coeffs[1] + X^2*coeffs[2] + ... + X^{n-1}*coeffs[n-1] +Poly :: struct { + coeffs: [N]i16, +} + +poly_compress :: proc "contextless" (r: []byte, a: ^Poly) #no_bounds_check { + t: [8]byte = --- + defer crypto.zero_explicit(&t, size_of(t)) + + r := r + switch len(r) { + case POLYCOMPRESSEDBYTES_768: // Also covers _512 + for i in 0..> 15) & Q + // t[j] = ((((uint16_t)u << 4) + Q/2)/Q) & 15 + d0 := u32(u) << 4 + d0 += 1665 + d0 *= 80635 + d0 >>= 28 + t[j] = byte(d0) & 0xf + } + + r[0] = t[0] | (t[1] << 4) + r[1] = t[2] | (t[3] << 4) + r[2] = t[4] | (t[5] << 4) + r[3] = t[6] | (t[7] << 4) + r = r[4:] + } + case POLYCOMPRESSEDBYTES_1024: + for i in 0..> 15) & Q + // t[j] = ((((uint16_t)u << 5) + Q/2)/Q) & 31 + d0 := u32(u) << 5 + d0 += 1664 + d0 *= 40318 + d0 >>= 27 + t[j] = byte(d0) & 0x1f + } + + r[0] = (t[0] >> 0) | (t[1] << 5) + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7) + r[2] = (t[3] >> 1) | (t[4] << 4) + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6) + r[4] = (t[6] >> 2) | (t[7] << 3) + r = r[5:] + } + case: + unreachable() + } +} + +poly_decompress :: proc "contextless" (r: ^Poly, a: []byte) { + a := a + switch len(a) { + case POLYCOMPRESSEDBYTES_768: // Also covers _512 + for i in 0..> 4) + r.coeffs[2*i+1] = i16(((u16(a[0] >> 4) * Q) + 8) >> 4) + a = a[1:] + } + case POLYCOMPRESSEDBYTES_1024: + t: [8]byte = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 0) + t[1] = (a[0] >> 5) | (a[1] << 3) + t[2] = (a[1] >> 2) + t[3] = (a[1] >> 7) | (a[2] << 1) + t[4] = (a[2] >> 4) | (a[3] << 4) + t[5] = (a[3] >> 1) + t[6] = (a[3] >> 6) | (a[4] << 2) + t[7] = (a[4] >> 3) + a = a[5:] + + for j in 0..<8 { + r.coeffs[8*i+j] = i16((u32(t[j] & 31) * Q + 16) >> 5) + } + } + case: + unreachable() + } +} + +poly_tobytes :: proc "contextless" (r: []byte, a: ^Poly) #no_bounds_check { + ensure_contextless(len(r) >= POLYBYTES) + + for i in 0..> 15) & Q) + t1 := u16(a.coeffs[2*i+1]) + t1 += u16((i16(t1) >> 15) & Q) + r[3*i+0] = byte(t0 >> 0) + r[3*i+1] = byte(t0 >> 8) | byte(t1 << 4) + r[3*i+2] = byte(t1 >> 4) + } +} + +@(require_results) +poly_frombytes :: proc "contextless" (r: ^Poly, a: []byte) -> bool #no_bounds_check { + ensure_contextless(len(a) >= POLYBYTES) + + ok := true + for i in 0..> 0) | (u16(a[3*i+1]) << 8)) & 0xFFF) + r.coeffs[2*i+1] = i16(((u16(a[3*i+1]) >> 4) | (u16(a[3*i+2]) << 4)) & 0xFFF) + ok &= r.coeffs[2*i] < Q && r.coeffs[2*i+1] < Q + } + + return ok +} + +poly_frommsg :: proc "contextless" (r: ^Poly, msg: []byte) #no_bounds_check { + #assert(INDCPA_MSGBYTES == N/8) + ensure_contextless(len(msg) == INDCPA_MSGBYTES) + + for i in 0..> uint(j))&1) + } + } +} + +poly_tomsg :: proc "contextless" (msg: []byte, a: ^Poly) #no_bounds_check { + ensure_contextless(len(msg) == INDCPA_MSGBYTES) + + for i in 0..> 15) & Q + // t = (((t << 1) + Q/2)/Q) & 1 + t <<= 1 + t += 1665 + t *= 80635 + t >>= 28 + t &= 1 + msg[i] |= byte(t << j) + } + } +} + +poly_getnoise_eta1_512 :: proc(r: ^Poly, seed: []byte, iv: byte) { + buf: [ETA1_512*N/4]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + prf(buf[:], seed, iv) + poly_cbd_eta1_512(r, &buf) +} + +poly_getnoise_eta1 :: proc(r: ^Poly, seed: []byte, iv: byte) { + buf: [ETA1*N/4]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + prf(buf[:], seed, iv) + poly_cbd_eta1(r, &buf) +} + +poly_getnoise_eta2 :: proc(r: ^Poly, seed: []byte, iv: byte) { + buf: [ETA2*N/4]byte = --- + defer crypto.zero_explicit(&buf, size_of(buf)) + + prf(buf[:], seed, iv) + poly_cbd_eta2(r, &buf) +} + +poly_ntt :: proc "contextless" (r: ^Poly) { + ntt(&r.coeffs) + poly_reduce(r) +} + +poly_invntt_tomont :: proc "contextless" (r: ^Poly) { + invntt(&r.coeffs) +} + +poly_basemul_montgomery :: proc "contextless" (r, a, b: ^Poly) #no_bounds_check { + for i in 0.. int { + switch k { + case K_512: + return POLYCOMPRESSEDBYTES_512 + case K_768: + return POLYCOMPRESSEDBYTES_768 + case K_1024: + return POLYCOMPRESSEDBYTES_1024 + case: + unreachable() + } +} diff --git a/core/crypto/_mlkem/polyvec.odin b/core/crypto/_mlkem/polyvec.odin new file mode 100644 index 000000000..2b971d2df --- /dev/null +++ b/core/crypto/_mlkem/polyvec.odin @@ -0,0 +1,224 @@ +#+private +package _mlkem + +import "core:crypto" + +Polyvec :: struct { + vec: [K_MAX]Poly, +} + +polyvec_compress :: proc "contextless" (r: []byte, a: ^Polyvec, kay: int) #no_bounds_check { + d0: u64 + + r := r + switch len(r) { + case POLYVECCOMPRESSEDBYTES_512, POLYVECCOMPRESSEDBYTES_768: + ensure_contextless(kay == K_512 || kay == K_768) + + t: [4]u16 = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 15) & Q) + // t[k] = ((((uint32_t)t[k] << 10) + Q/2)/Q) & 0x3ff + d0 = u64(t[k]) + d0 <<= 10 + d0 += 1665 + d0 *= 1290167 + d0 >>= 32 + t[k] = u16(d0 & 0x3ff) + } + + r[0] = byte(t[0] >> 0) + r[1] = byte((t[0] >> 8) | (t[1] << 2)) + r[2] = byte((t[1] >> 6) | (t[2] << 4)) + r[3] = byte((t[2] >> 4) | (t[3] << 6)) + r[4] = byte(t[3] >> 2) + r = r[5:] + } + } + case POLYVECCOMPRESSEDBYTES_1024: + ensure_contextless(kay == K_1024) + + t: [8]u16 = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 15) & Q) + // t[k] = ((((uint32_t)t[k] << 11) + Q/2)/Q) & 0x7ff + d0 = u64(t[k]) + d0 <<= 11 + d0 += 1664 + d0 *= 645084 + d0 >>= 31 + t[k] = u16(d0 & 0x7ff) + } + + r[0] = byte(t[0] >> 0) + r[1] = byte((t[0] >> 8) | (t[1] << 3)) + r[2] = byte((t[1] >> 5) | (t[2] << 6)) + r[3] = byte(t[2] >> 2) + r[4] = byte((t[2] >> 10) | (t[3] << 1)) + r[5] = byte((t[3] >> 7) | (t[4] << 4)) + r[6] = byte((t[4] >> 4) | (t[5] << 7)) + r[7] = byte(t[5] >> 1) + r[8] = byte((t[5] >> 9) | (t[6] << 2)) + r[9] = byte((t[6] >> 6) | (t[7] << 5)) + r[10] = byte(t[7] >> 3) + r = r[11:] + } + } + case: + unreachable() + } +} + +polyvec_decompress :: proc "contextless" (r: ^Polyvec, a: []byte, kay: int) #no_bounds_check { + a := a + switch len(a) { + case POLYVECCOMPRESSEDBYTES_512, POLYVECCOMPRESSEDBYTES_768: + ensure_contextless(kay == K_512 || kay == K_768) + + t: [4]u16 = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 0) | (u16(a[1]) << 8) + t[1] = u16(a[1] >> 2) | (u16(a[2]) << 6) + t[2] = u16(a[2] >> 4) | (u16(a[3]) << 4) + t[3] = u16(a[3] >> 6) | (u16(a[4]) << 2) + a = a[5:] + + for k in 0..<4 { + r.vec[i].coeffs[4*j+k] = i16((u32(t[k] & 0x3FF) * Q + 512) >> 10) + } + } + } + case POLYVECCOMPRESSEDBYTES_1024: + t: [8]u16 = --- + defer crypto.zero_explicit(&t, size_of(t)) + + for i in 0..> 0) | (u16(a[1]) << 8) + t[1] = u16(a[1] >> 3) | (u16(a[2]) << 5) + t[2] = u16(a[2] >> 6) | (u16(a[3]) << 2) | (u16(a[4]) << 10) + t[3] = u16(a[4] >> 1) | (u16(a[5]) << 7) + t[4] = u16(a[5] >> 4) | (u16(a[6]) << 4) + t[5] = u16(a[6] >> 7) | (u16(a[7]) << 1) | (u16(a[8]) << 9) + t[6] = u16(a[8] >> 2) | (u16(a[9]) << 6) + t[7] = u16(a[9] >> 5) | (u16(a[10]) << 3) + a = a[11:] + + for k in 0..<8 { + r.vec[i].coeffs[8*j+k] = i16((u32(t[k] & 0x7FF) * Q + 1024) >> 11) + } + } + } + case: + unreachable() + } +} + +polyvec_tobytes :: proc "contextless" (r: []byte, a: ^Polyvec, k: int) #no_bounds_check { + ensure_contextless(len(r) == k * POLYBYTES, "crypto/mlkem: invalid buffer") + + r := r + for i in 0.. bool #no_bounds_check { + switch k { + case K_512, K_768, K_1024: + case: + panic_contextless("crypto/mlkem: invalid POLYVECBYTES") + } + ensure_contextless(len(a) == k * POLYBYTES, "crypto/mlkem: invalid buffer") + + a := a + ok := true + for i in 0.. int { + switch k { + case K_512, K_768, K_1024: + return k * POLYBYTES + case: + return 0 + } +} + +@(require_results) +polyvec_compressed_byte_size :: #force_inline proc "contextless" (k: int) -> int { + switch k { + case K_512: + return POLYVECCOMPRESSEDBYTES_512 + case K_768: + return POLYVECCOMPRESSEDBYTES_768 + case K_1024: + return POLYVECCOMPRESSEDBYTES_1024 + case: + return 0 + } +} + +polyvec_ntt :: proc "contextless" (r: ^Polyvec, k: int) { + for i in 0.. i16 { + QINV :: -3327 // q^-1 mod 2^16 + + t := i16(a) * QINV + return i16((a - i32(t) * Q) >> 16) +} + +@(require_results) +barrett_reduce :: #force_inline proc "contextless" (a: i16) -> i16 { + V : i16 : ((1<<26) + Q / 2) / Q + + t := i16((i32(V)*i32(a) + (1<<25)) >> 26) + t *= Q + return a - t +} diff --git a/core/crypto/_mlkem/symmetric_shake.odin b/core/crypto/_mlkem/symmetric_shake.odin new file mode 100644 index 000000000..bf851f6f6 --- /dev/null +++ b/core/crypto/_mlkem/symmetric_shake.odin @@ -0,0 +1,61 @@ +#+private +package _mlkem + +import "core:crypto" +import "core:crypto/_sha3" +import "core:crypto/sha3" +import "core:crypto/shake" + +XOF_BLOCKBYTES :: _sha3.RATE_128 +#assert(XOF_BLOCKBYTES % 3 == 0) + +prf :: proc(out, key: []byte, iv: byte) { + ctx: shake.Context = --- + defer shake.reset(&ctx) + + shake.init_256(&ctx) + shake.write(&ctx, key) + shake.write(&ctx, []byte{iv}) + shake.read(&ctx, out) +} + +rkprf :: proc(out, key, input: []byte) { + ctx: shake.Context = --- + defer shake.reset(&ctx) + + shake.init_256(&ctx) + shake.write(&ctx, key) + shake.write(&ctx, input) + shake.read(&ctx, out) +} + +xof_absorb :: proc(ctx: ^shake.Context, seed: []byte, x, y: byte) { + shake.init_128(ctx) + + extseed: [SYMBYTES+2]byte = --- + defer crypto.zero_explicit(&extseed, size_of(extseed)) + + copy(extseed[:], seed) + extseed[SYMBYTES+0] = x + extseed[SYMBYTES+1] = y + + shake.write(ctx, extseed[:]) +} + +hash_h :: proc(dst, src: []byte) { + ctx: sha3.Context = --- + + sha3.init_256(&ctx) + sha3.update(&ctx, src) + sha3.final(&ctx, dst) +} + +hash_g :: proc(dst: []byte, srcs: ..[]byte) { + ctx: sha3.Context = --- + + sha3.init_512(&ctx) + for src in srcs { + sha3.update(&ctx, src) + } + sha3.final(&ctx, dst) +} diff --git a/core/crypto/_sha3/sha3.odin b/core/crypto/_sha3/sha3.odin index 52b3fbda9..b2d032b31 100644 --- a/core/crypto/_sha3/sha3.odin +++ b/core/crypto/_sha3/sha3.odin @@ -2,7 +2,7 @@ package _sha3 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -16,7 +16,7 @@ package _sha3 */ import "core:math/bits" -import "core:mem" +import "core:crypto" ROUNDS :: 24 @@ -179,7 +179,7 @@ reset :: proc "contextless" (ctx: ^Context) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } shake_xof :: proc "contextless" (ctx: ^Context) { diff --git a/core/crypto/_subtle/subtle.odin b/core/crypto/_subtle/subtle.odin new file mode 100644 index 000000000..01c84cf2a --- /dev/null +++ b/core/crypto/_subtle/subtle.odin @@ -0,0 +1,81 @@ +/* +Various useful bit operations in constant time. +*/ +package _subtle + +import "core:crypto/_fiat" +import "core:math/bits" + +// byte_eq returns 1 if and only if (⟺) a == b, 0 otherwise. +@(optimization_mode="none") +byte_eq :: proc "contextless" (a, b: byte) -> int { + v := a ~ b + + // v == 0 if and only if (⟺) a == b. The subtraction will underflow, setting the + // sign bit, which will get returned. + return int((u32(v)-1) >> 31) +} + +// u64_eq returns 1 if and only if (⟺) a == b, 0 otherwise. +@(optimization_mode="none") +u64_eq :: proc "contextless" (a, b: u64) -> u64 { + _, borrow := bits.sub_u64(0, a ~ b, 0) + return (~borrow) & 1 +} + +eq :: proc { + byte_eq, + u64_eq, +} + +// u64_is_zero returns 1 if and only if (⟺) a == 0, 0 otherwise. +@(optimization_mode="none") +u64_is_zero :: proc "contextless" (a: u64) -> u64 { + _, borrow := bits.sub_u64(a, 1, 0) + return borrow +} + +// u64_is_non_zero returns 1 if and only if (⟺) a != 0, 0 otherwise. +@(optimization_mode="none") +u64_is_non_zero :: proc "contextless" (a: u64) -> u64 { + is_zero := u64_is_zero(a) + return (~is_zero) & 1 +} + +@(optimization_mode="none") +cmov_bytes :: proc "contextless" (dst, src: []byte, ctrl: int) { + s_len := len(src) + ensure_contextless(s_len == len(dst), "crypto: cmov length mismatch") + + c := -(byte)(ctrl) + for i in 0.. i16 { + c := -(u16)(ctrl) + return a ~ i16(c & u16(a ~ b)) +} + +@(optimization_mode="none") +csel_u16 :: proc "contextless" (a, b: u16, ctrl: int) -> u16 { + c := -(u16)(ctrl) + return a ~ (c & (a ~ b)) +} + +csel_u32 :: proc "contextless" (a, b: u32, ctrl: int) -> u32 { + return _fiat.cmovznz_u32(_fiat.u1(ctrl), a, b) +} + +csel_u64 :: proc "contextless" (a, b: u64, ctrl: int) -> u64 { + return _fiat.cmovznz_u64(_fiat.u1(ctrl), a, b) +} + +csel :: proc { + csel_i16, + csel_u16, + csel_u32, + csel_u64, +} diff --git a/core/crypto/_weierstrass/fe.odin b/core/crypto/_weierstrass/fe.odin new file mode 100644 index 000000000..8ff6fe346 --- /dev/null +++ b/core/crypto/_weierstrass/fe.odin @@ -0,0 +1,205 @@ +package _weierstrass + +import p256r1 "core:crypto/_fiat/field_p256r1" +import p384r1 "core:crypto/_fiat/field_p384r1" +import subtle "core:crypto/_subtle" + +Field_Element_p256r1 :: p256r1.Montgomery_Domain_Field_Element +Field_Element_p384r1 :: p384r1.Montgomery_Domain_Field_Element + +FE_SIZE_P256R1 :: 32 +FE_SIZE_P384R1 :: 48 + +fe_clear :: proc { + p256r1.fe_clear, + p384r1.fe_clear, +} + +fe_clear_vec :: proc { + p256r1.fe_clear_vec, + p384r1.fe_clear_vec, +} + +fe_set_bytes :: proc { + p256r1.fe_from_bytes, + p384r1.fe_from_bytes, +} + +fe_bytes :: proc { + p256r1.fe_to_bytes, + p384r1.fe_to_bytes, +} + +fe_set :: proc { + p256r1.fe_set, + p384r1.fe_set, +} + +fe_zero :: proc { + p256r1.fe_zero, + p384r1.fe_zero, +} + +fe_a :: proc { + fe_a_p256r1, + fe_a_p384r1, +} + +fe_b :: proc { + fe_b_p256r1, + fe_b_p384r1, +} + +fe_gen_x :: proc { + fe_gen_x_p256r1, + fe_gen_x_p384r1, +} + +fe_gen_y :: proc { + fe_gen_y_p256r1, + fe_gen_y_p384r1, +} + +fe_one :: proc { + p256r1.fe_one, + p384r1.fe_one, +} + +fe_add :: proc { + p256r1.fe_add, + p384r1.fe_add, +} + +fe_sub :: proc { + p256r1.fe_sub, + p384r1.fe_sub, +} + +fe_negate :: proc { + p256r1.fe_opp, + p384r1.fe_opp, +} + +fe_mul :: proc { + p256r1.fe_mul, + p384r1.fe_mul, +} + +fe_square :: proc { + p256r1.fe_square, + p384r1.fe_square, +} + +fe_inv :: proc { + p256r1.fe_inv, + p384r1.fe_inv, +} + +fe_sqrt :: proc { + p256r1.fe_sqrt, + p384r1.fe_sqrt, +} + +fe_equal :: proc { + p256r1.fe_equal, + p384r1.fe_equal, +} + +fe_is_odd :: proc { + p256r1.fe_is_odd, + p384r1.fe_is_odd, +} + +fe_is_zero :: proc { + fe_is_zero_p256r1, + fe_is_zero_p384r1, +} + +fe_cond_select :: proc { + p256r1.fe_cond_select, + p384r1.fe_cond_select, +} + +fe_a_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc + // = -3 mod p + fe[0] = 18446744073709551612 + fe[1] = 17179869183 + fe[2] = 0 + fe[3] = 18446744056529682436 +} + +fe_b_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + fe[0] = 15608596021259845087 + fe[1] = 12461466548982526096 + fe[2] = 16546823903870267094 + fe[3] = 15866188208926050356 +} + +fe_gen_x_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // G_x = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 + fe[0] = 8784043285714375740 + fe[1] = 8483257759279461889 + fe[2] = 8789745728267363600 + fe[3] = 1770019616739251654 +} + +fe_gen_y_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // G_y = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 + fe[0] = 15992936863339206154 + fe[1] = 10037038012062884956 + fe[2] = 15197544864945402661 + fe[3] = 9615747158586711429 +} + +fe_a_p384r1 :: proc "contextless" (fe: ^Field_Element_p384r1) { + // a = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc + // = -3 mod p + fe[0] = 17179869180 + fe[1] = 18446744056529682432 + fe[2] = 18446744073709551611 + fe[3] = 18446744073709551615 + fe[4] = 18446744073709551615 + fe[5] = 18446744073709551615 +} + +fe_b_p384r1 :: proc "contextless" (fe: ^Field_Element_p384r1) { + // b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef + fe[0] = 581395848458481100 + fe[1] = 17809957346689692396 + fe[2] = 8643006485390950958 + fe[3] = 16372638458395724514 + fe[4] = 13126622871277412500 + fe[5] = 14774077593024970745 +} + +fe_gen_x_p384r1 :: proc "contextless" (fe: ^Field_Element_p384r1) { + // G_x = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7 + fe[0] = 4454189113653900584 + fe[1] = 2369870743683386936 + fe[2] = 9771750146904378734 + fe[3] = 7229551204834152191 + fe[4] = 9308930686126579243 + fe[5] = 5564951339003155731 +} + +fe_gen_y_p384r1 :: proc "contextless" (fe: ^Field_Element_p384r1) { + // G_y = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f + fe[0] = 2523209505731486974 + fe[1] = 11655219901025790380 + fe[2] = 10064955099576512592 + fe[3] = 14322381509056856025 + fe[4] = 15960759442596276288 + fe[5] = 3132442392059561449 +} + +@(require_results) +fe_is_zero_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) -> int { + return int(subtle.u64_is_zero(p256r1.fe_non_zero(fe))) +} + +@(require_results) +fe_is_zero_p384r1 :: proc "contextless" (fe: ^Field_Element_p384r1) -> int { + return int(subtle.u64_is_zero(p384r1.fe_non_zero(fe))) +} diff --git a/core/crypto/_weierstrass/point.odin b/core/crypto/_weierstrass/point.odin new file mode 100644 index 000000000..0e6e48678 --- /dev/null +++ b/core/crypto/_weierstrass/point.odin @@ -0,0 +1,580 @@ +package _weierstrass + +/* +This implements prime order short Weierstrass curves defined over a field +k with char(k) != 2, 3 (`y^2 = x^3 + ax + b`). for the purpose of +implementing ECDH and ECDSA. Use of this package for other purposes is +NOT RECOMMENDED. + +As an explicit simplicity/performance tradeoff, projective representation +was chosen so that it is possible to use the complete addition +formulas. + +See: +- https://eprint.iacr.org/2015/1060.pdf +- https://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html + +WARNING: The point addition and doubling formulas are specialized for +`a = -3`, which covers secp256r1, secp384r1, secp521r1, FRP256v1, SM2, +and GOST 34.10. The brainpool curves and secp256k1 are NOT SUPPORTED +and would require slightly different formulas. +*/ + +Point_p256r1 :: struct { + x: Field_Element_p256r1, + y: Field_Element_p256r1, + z: Field_Element_p256r1, +} + +Point_p384r1 :: struct { + x: Field_Element_p384r1, + y: Field_Element_p384r1, + z: Field_Element_p384r1, +} + +@(require_results) +pt_set_xy_bytes :: proc "contextless" (p: ^$T, x_raw, y_raw: []byte) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + x, y: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&x, &y}) + } else when T == Point_p384r1 { + FE_SZ :: FE_SIZE_P384R1 + x, y: Field_Element_p384r1 + defer fe_clear_vec([]^Field_Element_p384r1{&x, &y}) + } else { + #panic("weierstrass: invalid curve") + } + + if len(x_raw) != FE_SZ || len(y_raw) != FE_SZ { + return false + } + + if !fe_set_bytes(&x, x_raw) { + return false + } + if !fe_set_bytes(&y, y_raw) { + return false + } + if !is_on_curve(&x, &y) { + return false + } + + fe_set(&p.x, &x) + fe_set(&p.y, &y) + fe_one(&p.z) + + return true +} + +@(require_results) +pt_set_x_bytes :: proc "contextless" (p: ^$T, x_raw: []byte, y_is_odd: int) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + x, y, yy, y_neg: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&x, &y, &yy, &y_neg}) + } else when T == Point_p384r1 { + FE_SZ :: FE_SIZE_P384R1 + x, y, yy, y_neg: Field_Element_p384r1 + defer fe_clear_vec([]^Field_Element_p384r1{&x, &y, &yy, &y_neg}) + } else { + #panic("weierstrass: invalid curve") + } + + if len(x_raw) != FE_SZ { + return false + } + + if !fe_set_bytes(&x, x_raw) { + return false + } + set_yy_candidate(&yy, &x) + if fe_sqrt(&y, &yy) != 1 { + return false + } + + // Pick the correct y-coordinate. + fe_negate(&y_neg, &y) + parity_neq := (y_is_odd ~ fe_is_odd(&y)) & 1 + + fe_set(&p.x, &x) + fe_cond_select(&p.y, &y, &y_neg, parity_neq) + fe_one(&p.z) + + return true +} + +@(require_results) +pt_bytes :: proc "contextless" (x, y: []byte, p: ^$T) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else when T == Point_p384r1 { + FE_SZ :: FE_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + if pt_is_identity(p) == 1 { + return false + } + + // Convert to affine coordinates. + pt_rescale(p, p) + + switch len(x) { + case 0: + case FE_SZ: + fe_bytes(x, &p.x) + case: + panic_contextless("weierstrass: invalid x buffer") + } + switch len(y) { + case 0: + case FE_SZ: + fe_bytes(y, &p.y) + case: + panic_contextless("weierstrass: invalid y buffer") + } + + return true +} + +pt_set :: proc "contextless" (p, q: ^$T) { + fe_set(&p.x, &q.x) + fe_set(&p.y, &q.y) + fe_set(&p.z, &q.z) +} + +pt_identity :: proc "contextless" (p: ^$T) { + fe_zero(&p.x) + fe_one(&p.y) + fe_zero(&p.z) +} + +pt_generator :: proc "contextless" (p: ^$T) { + fe_gen_x(&p.x) + fe_gen_y(&p.y) + fe_one(&p.z) +} + +pt_clear :: proc "contextless" (p: ^$T) { + fe_clear(&p.x) + fe_clear(&p.y) + fe_clear(&p.z) +} + +pt_clear_vec :: proc "contextless" (arg: []^$T) { + for p in arg { + pt_clear(p) + } +} + +pt_add :: proc "contextless" (p, a, b: ^$T) { + // Algorithm 4 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is complete in that it is valid for all a and b, + // without exceptions or extra assumptions about the inputs. + // + // The operation costs are `12M + 2mb + 29a`. + + when T == Point_p256r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else when T == Point_p384r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p384r1 + x3, y3, z3: Field_Element_p384r1 + defer fe_clear_vec([]^Field_Element_p384r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x1, y1, z1 := &a.x, &a.y, &a.z + x2, y2, z2 := &b.x, &b.y, &b.z + + fe_b(&b_fe) + + // t0 := X1 * X2 ; t1 := Y1 * Y2 ; t2 := Z1 * Z2 ; + fe_mul(&t0, x1, x2) + fe_mul(&t1, y1, y2) + fe_mul(&t2, z1, z2) + + // t3 := X1 + Y1 ; t4 := X2 + Y2 ; t3 := t3 * t4 ; + fe_add(&t3, x1, y1) + fe_add(&t4, x2, y2) + fe_mul(&t3, &t3, &t4) + + // t4 := t0 + t1 ; t3 := t3 - t4 ; t4 := Y1 + Z1 ; + fe_add(&t4, &t0, &t1) + fe_sub(&t3, &t3, &t4) + fe_add(&t4, y1, z1) + + // X3 := Y2 + Z2 ; t4 := t4 * X3 ; X3 := t1 + t2 ; + fe_add(&x3, y2, z2) + fe_mul(&t4, &t4, &x3) + fe_add(&x3, &t1, &t2) + + // t4 := t4 - X3 ; X3 := X1 + Z1 ; Y3 := X2 + Z2 ; + fe_sub(&t4, &t4, &x3) + fe_add(&x3, x1, z1) + fe_add(&y3, x2, z2) + + // X3 := X3 * Y3 ; Y3 := t0 + t2 ; Y3 := X3 - Y3 ; + fe_mul(&x3, &x3, &y3) + fe_add(&y3, &t0, &t2) + fe_sub(&y3, &x3, &y3) + + // Z3 := b * t2 ; X3 := Y3 - Z3 ; Z3 := X3 + X3 ; + fe_mul(&z3, &b_fe, &t2) + fe_sub(&x3, &y3, &z3) + fe_add(&z3, &x3, &x3) + + // X3 := X3 + Z3 ; Z3 := t1 - X3 ; X3 := t1 + X3 ; + fe_add(&x3, &x3, &z3) + fe_sub(&z3, &t1, &x3) + fe_add(&x3, &t1, &x3) + + // Y3 := b * Y3 ; t1 := t2 + t2 ; t2 := t1 + t2 ; + fe_mul(&y3, &b_fe, &y3) + fe_add(&t1, &t2, &t2) + fe_add(&t2, &t1, &t2) + + // Y3 := Y3 - t2 ; Y3 := Y3 - t0 ; t1 := Y3 + Y3 ; + fe_sub(&y3, &y3, &t2) + fe_sub(&y3, &y3, &t0) + fe_add(&t1, &y3, &y3) + + // Y3 := t1 + Y3 ; t1 := t0 + t0 ; t0 := t1 + t0 ; + fe_add(&y3, &t1, &y3) + fe_add(&t1, &t0, &t0) + fe_add(&t0, &t1, &t0) + + // t0 := t0 - t2 ; t1 := t4 * Y3 ; t2 := t0 * Y3 ; + fe_sub(&t0, &t0, &t2) + fe_mul(&t1, &t4, &y3) + fe_mul(&t2, &t0, &y3) + + // Y3 := X3 * Z3 ; Y3 := Y3 + t2 ; X3 := t3 * X3 ; + fe_mul(&y3, &x3, &z3) + fe_add(&y3, &y3, &t2) + fe_mul(&x3, &t3, &x3) + + // X3 := X3 - t1 ; Z3 := t4 * Z3 ; t1 := t3 * t0 ; + fe_sub(&x3, &x3, &t1) + fe_mul(&z3, &t4, &z3) + fe_mul(&t1, &t3, &t0) + + // Z3 := Z3 + t1 ; + fe_add(&z3, &z3, &t1) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +@(private) +pt_add_mixed :: proc "contextless" (p, a: ^$T, x2, y2: ^$U) { + // Algorithm 5 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is mixed in that it assumes the z-coordinate + // of the addend (`Z2`) is `1`, meaning that it CAN NOT + // handle the addend being the point at infinity. + // + // The operation costs are `11M + 2mb + 23a` saving + // `1M + 6a` over `pt_add`. + + when T == Point_p256r1 && U == Field_Element_p256r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else when T == Point_p384r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p384r1 + x3, y3, z3: Field_Element_p384r1 + defer fe_clear_vec([]^Field_Element_p384r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x1, y1, z1 := &a.x, &a.y, &a.z + + fe_b(&b_fe) + + // t0 := X1 * X2 ; t1 := Y1 * Y2 ; t3 := X2 + Y2 ; + fe_mul(&t0, x1, x2) + fe_mul(&t1, y1, y2) + fe_add(&t3, x2, y2) + + // t4 := X1 + Y1 ; t3 := t3 * t4 ; t4 := t0 + t1 ; + fe_add(&t4, x1, y1) + fe_mul(&t3, &t3, &t4) + fe_add(&t4, &t0, &t1) + + // t3 := t3 − t4 ; t4 := Y2 * Z1 ; t4 := t4 + Y1 ; + fe_sub(&t3, &t3, &t4) + fe_mul(&t4, y2, z1) + fe_add(&t4, &t4, y1) + + // Y3 := X2 * Z1 ; Y3 := Y3 + X1 ; Z3 := b * Z1 ; + fe_mul(&y3, x2, z1) + fe_add(&y3, &y3, x1) + fe_mul(&z3, &b_fe, z1) + + // X3 := Y3 − Z3 ; Z3 := X3 + X3 ; X3 := X3 + Z3 ; + fe_sub(&x3, &y3, &z3) + fe_add(&z3, &x3, &x3) + fe_add(&x3, &x3, &z3) + + // Z3 := t1 − X3 ; X3 := t1 + X3 ;. Y3 := b * Y3 ; + fe_sub(&z3, &t1, &x3) + fe_add(&x3, &t1, &x3) + fe_mul(&y3, &b_fe, &y3) + + // t1 := Z1 + Z1 ; t2 := t1 + Z1 ; Y3 := Y3 − t2 ; + fe_add(&t1, z1, z1) + fe_add(&t2, &t1, z1) + fe_sub(&y3, &y3, &t2) + + // Y3 := Y3 − t0 ; t1 := Y3 + Y3 ; Y3 := t1 + Y3 ; + fe_sub(&y3, &y3, &t0) + fe_add(&t1, &y3, &y3) + fe_add(&y3, &t1, &y3) + + // t1 := t0 + t0 ; t0 := t1 + t0 ; t0 := t0 − t2 ; + fe_add(&t1, &t0, &t0) + fe_add(&t0, &t1, &t0) + fe_sub(&t0, &t0, &t2) + + // t1 := t4 * Y3 ; t2 := t0 * Y3 ; Y3 := X3 * Z3 ; + fe_mul(&t1, &t4, &y3) + fe_mul(&t2, &t0, &y3) + fe_mul(&y3, &x3, &z3) + + // Y3 := Y3 + t2 ; X3 := t3 * X3 ; X3 := X3 − t1 ; + fe_add(&y3, &y3, &t2) + fe_mul(&x3, &t3, &x3) + fe_sub(&x3, &x3, &t1) + + // Z3 := t4 * Z3 ; t1 := t3 * t0 ; Z3 := Z3 + t1 ; + fe_mul(&z3, &t4, &z3) + fe_mul(&t1, &t3, &t0) + fe_add(&z3, &z3, &t1) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +pt_double :: proc "contextless" (p, a: ^$T) { + // Algorithm 6 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is complete in that it is valid for all a, + // without exceptions or extra assumptions about the inputs. + // + // The operation costs are `8M + 3S + 2mb + 21a`. + + when T == Point_p256r1 { + t0, t1, t2, t3, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &x3, &y3, &z3}) + } else when T == Point_p384r1 { + t0, t1, t2, t3, b_fe: Field_Element_p384r1 + x3, y3, z3: Field_Element_p384r1 + defer fe_clear_vec([]^Field_Element_p384r1{&t0, &t1, &t2, &t3, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x, y, z := &a.x, &a.y, &a.z + + fe_b(&b_fe) + + // t0 := X ^2; t1 := Y ^2; t2 := Z ^2; + fe_square(&t0, x) + fe_square(&t1, y) + fe_square(&t2, z) + + // t3 := X * Y ; t3 := t3 + t3 ; Z3 := X * Z ; + fe_mul(&t3, x, y) + fe_add(&t3, &t3, &t3) + fe_mul(&z3, x, z) + + // Z3 := Z3 + Z3 ; Y3 := b * t2 ; Y3 := Y3 - Z3 ; + fe_add(&z3, &z3, &z3) + fe_mul(&y3, &b_fe, &t2) + fe_sub(&y3, &y3, &z3) + + // X3 := Y3 + Y3 ; Y3 := X3 + Y3 ; X3 := t1 - Y3 ; + fe_add(&x3, &y3, &y3) + fe_add(&y3, &x3, &y3) + fe_sub(&x3, &t1, &y3) + + // Y3 := t1 + Y3 ; Y3 := X3 * Y3 ; X3 := X3 * t3 ; + fe_add(&y3, &t1, &y3) + fe_mul(&y3, &x3, &y3) + fe_mul(&x3, &x3, &t3) + + // t3 := t2 + t2 ; t2 := t2 + t3 ; Z3 := b * Z3 ; + fe_add(&t3, &t2, &t2) + fe_add(&t2, &t2, &t3) + fe_mul(&z3, &b_fe, &z3) + + // Z3 := Z3 - t2 ; Z3 := Z3 - t0 ; t3 := Z3 + Z3 ; + fe_sub(&z3, &z3, &t2) + fe_sub(&z3, &z3, &t0) + fe_add(&t3, &z3, &z3) + + // Z3 := Z3 + t3 ; t3 := t0 + t0 ; t0 := t3 + t0 ; + fe_add(&z3, &z3, &t3) + fe_add(&t3, &t0, &t0) + fe_add(&t0, &t3, &t0) + + // t0 := t0 - t2 ; t0 := t0 * Z3 ; Y3 := Y3 + t0 ; + fe_sub(&t0, &t0, &t2) + fe_mul(&t0, &t0, &z3) + fe_add(&y3, &y3, &t0) + + // t0 := Y * Z ; t0 := t0 + t0 ; Z3 := t0 * Z3 ; + fe_mul(&t0, y, z) + fe_add(&t0, &t0, &t0) + fe_mul(&z3, &t0, &z3) + + // X3 := X3 - Z3 ; Z3 := t0 * t1 ; Z3 := Z3 + Z3 ; + fe_sub(&x3, &x3, &z3) + fe_mul(&z3, &t0, &t1) + fe_add(&z3, &z3, &z3) + + // Z3 := Z3 + Z3 ; + fe_add(&z3, &z3, &z3) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +pt_sub :: proc "contextless" (p, a, b: ^$T) { + b_neg: T + pt_negate(&b_neg, b) + pt_add(p, a, &b_neg) + + fe_clear(&b_neg) +} + +pt_negate :: proc "contextless" (p, a: ^$T) { + fe_set(&p.x, &a.x) + fe_negate(&p.y, &a.y) + fe_set(&p.z, &a.z) +} + +pt_rescale :: proc "contextless" (p, a: ^$T) { + // A = 1/Z1 + // X3 = A*X1 + // Y3 = A*Y1 + // Z3 = 1 + // + // As per "From A to Z: Projective coordinates leakage in the wild" + // leaking the Z-coordinate is bad. The modular inversion algorithm + // used in this library is based on Fermat's Little Theorem. + // + // See: https://eprint.iacr.org/2020/432.pdf + + was_identity := pt_is_identity(a) + + when T == Point_p256r1 { + z_inv: Field_Element_p256r1 + } else when T == Point_p384r1 { + z_inv: Field_Element_p384r1 + } else { + #panic("weierstrass: invalid curve") + } + + ident: T + fe_inv(&z_inv, &a.z) + fe_mul(&p.x, &a.x, &z_inv) + fe_mul(&p.y, &a.y, &z_inv) + fe_one(&p.z) + + pt_identity(&ident) + pt_cond_select(p, p, &ident, was_identity) + + fe_clear(&z_inv) +} + +pt_cond_select :: proc "contextless" (p, a, b: ^$T, ctrl: int) { + fe_cond_select(&p.x, &a.x, &b.x, ctrl) + fe_cond_select(&p.y, &a.y, &b.y, ctrl) + fe_cond_select(&p.z, &a.z, &b.z, ctrl) +} + +@(require_results) +pt_equal :: proc "contextless" (a, b: ^$T) -> int { + when T == Point_p256r1 { + x1z2, x2z1, y1z2, y2z1: Field_Element_p256r1 + } else when T == Point_p384r1 { + x1z2, x2z1, y1z2, y2z1: Field_Element_p384r1 + } else { + #panic("weierstrass: invalid curve") + } + + // Check X1Z2 == X2Z1 && Y1Z2 == Y2Z1 + fe_mul(&x1z2, &a.x, &b.z) + fe_mul(&x2z1, &b.x, &a.z) + + fe_mul(&y1z2, &a.y, &b.z) + fe_mul(&y2z1, &b.y, &a.z) + + return fe_equal(&x1z2, &x2z1) & fe_equal(&y1z2, &y2z1) +} + +@(require_results) +pt_is_identity :: proc "contextless" (p: ^$T) -> int { + return fe_is_zero(&p.z) +} + +@(require_results) +pt_is_y_odd :: proc "contextless" (p: ^$T) -> int { + tmp: T + defer pt_clear(&tmp) + + fe_set(&tmp, p) + pt_rescale(&tmp) + + return fe_is_odd(&tmp.y) +} + +@(private) +is_on_curve :: proc "contextless" (x, y: ^$T) -> bool { + maybe_yy, yy: T + defer fe_clear_vec([]^T{&maybe_yy, &yy}) + + // RHS: x^3 + ax + b + set_yy_candidate(&maybe_yy, x) + + // LHS: y^2 + fe_square(&yy, y) + + return fe_equal(&maybe_yy, &yy) == 1 +} + +@(private) +set_yy_candidate :: proc "contextless" (maybe_yy, x: ^$T) { + // RHS: x^3 + ax + b + rhs, tmp: T + + fe_square(&tmp, x) + fe_mul(&rhs, &tmp, x) + + fe_a(&tmp) + fe_mul(&tmp, &tmp, x) + fe_add(&rhs, &rhs, &tmp) + + fe_b(&tmp) + fe_add(maybe_yy, &rhs, &tmp) + + fe_clear(&rhs) +} diff --git a/core/crypto/_weierstrass/point_s11n_sec.odin b/core/crypto/_weierstrass/point_s11n_sec.odin new file mode 100644 index 000000000..56d017e5e --- /dev/null +++ b/core/crypto/_weierstrass/point_s11n_sec.odin @@ -0,0 +1,99 @@ +package _weierstrass + +@(require) import "core:crypto" + +@(private) +SEC_PREFIX_IDENTITY :: 0x00 +@(private) +SEC_PREFIX_COMPRESSED_EVEN :: 0x02 +@(private) +SEC_PREFIX_COMPRESSED_ODD :: 0x03 +SEC_PREFIX_UNCOMPRESSED :: 0x04 + +@(require_results) +pt_set_sec_bytes :: proc "contextless" (p: ^$T, b: []byte) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else when T == Point_p384r1 { + FE_SZ :: FE_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + b_len := len(b) + if b_len < 1 { + return false + } + + switch b[0] { + case SEC_PREFIX_IDENTITY: + if b_len != 1 { + return false + } + pt_identity(p) + return true + case SEC_PREFIX_COMPRESSED_EVEN, SEC_PREFIX_COMPRESSED_ODD: + if b_len != 1 + FE_SZ { + return false + } + y_is_odd := b[0] - SEC_PREFIX_COMPRESSED_EVEN + return pt_set_x_bytes(p, b[1:], int(y_is_odd)) + case SEC_PREFIX_UNCOMPRESSED: + if b_len != 1 + 2 * FE_SZ { + return false + } + x, y := b[1:1+FE_SZ], b[1+FE_SZ:] + return pt_set_xy_bytes(p, x, y) + case: + return false + } +} + +@(require_results) +pt_sec_bytes :: proc "contextless" (b: []byte, p: ^$T, compressed: bool) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else when T == Point_p384r1 { + FE_SZ :: FE_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + b_len := len(b) + if pt_is_identity(p) == 1 { + if b_len != 1 { + return false + } + b[0] = SEC_PREFIX_IDENTITY + return true + } + + x, y: []byte + y_: [FE_SZ]byte + switch compressed { + case true: + if b_len != 1 + FE_SZ { + return false + } + x, y = b[1:], y_[:] + case false: + if b_len != 1 + 2 * FE_SZ { + return false + } + b[0]= SEC_PREFIX_UNCOMPRESSED + x, y = b[1:1+FE_SZ], b[1+FE_SZ:] + } + if !pt_bytes(x, y, p) { + return false + } + if compressed { + // Instead of calling pt_is_y_odd, just serializing + // y into a temp buffer and checking the parity saves + // 1 redundant rescale call. + y_is_odd := byte(y[FE_SZ-1] & 1) + b[0] = SEC_PREFIX_COMPRESSED_EVEN + y_is_odd + crypto.zero_explicit(&y_, size_of(y_)) + } + + return true +} diff --git a/core/crypto/_weierstrass/sc.odin b/core/crypto/_weierstrass/sc.odin new file mode 100644 index 000000000..1ecfea6f9 --- /dev/null +++ b/core/crypto/_weierstrass/sc.odin @@ -0,0 +1,142 @@ +package _weierstrass + +@(require) import "core:crypto" +import p256r1 "core:crypto/_fiat/field_scalarp256r1" +import p384r1 "core:crypto/_fiat/field_scalarp384r1" +import subtle "core:crypto/_subtle" + +Scalar_p256r1 :: p256r1.Montgomery_Domain_Field_Element +Scalar_p384r1 :: p384r1.Montgomery_Domain_Field_Element + +SC_SIZE_P256R1 :: 32 +SC_SIZE_P384R1 :: 48 +SC_SIZE_MAX :: SC_SIZE_P384R1 + +sc_size :: proc "contextless" (sc: ^$T) -> int where T == Scalar_p256r1 || T == Scalar_p384r1 { + when T == Scalar_p256r1 { + return SC_SIZE_P256R1 + } else when T == Scalar_p384r1 { + return SC_SIZE_P384R1 + } +} + +sc_set_random :: proc(sc: ^$T) where T == Scalar_p256r1 || T == Scalar_p384r1 { + ensure(crypto.HAS_RAND_BYTES, "weierstrass: entropy source required") + + b: [48]byte = --- + defer crypto.zero_explicit(&b, size_of(b)) + + when T == Scalar_p256r1 { + // 384-bits reduced makes the modulo bias insignificant + for { + crypto.rand_bytes(b[:]) + _ = sc_set_bytes(sc, b[:]) + if sc_is_zero(sc) == 0 { // Likely + break + } + } + } else when T == Scalar_p384r1 { + for { + crypto.rand_bytes(b[:]) + did_reduce := sc_set_bytes(sc, b[:]) + if !did_reduce && sc_is_zero(sc) == 0 { // Likely + break + } + } + } +} + +sc_clear :: proc { + p256r1.fe_clear, + p384r1.fe_clear, +} + +sc_clear_vec :: proc { + p256r1.fe_clear_vec, + p384r1.fe_clear_vec, +} + +sc_set_bytes :: proc { + p256r1.fe_from_bytes, + p384r1.fe_from_bytes, +} + +sc_bytes :: proc { + p256r1.fe_to_bytes, + p384r1.fe_to_bytes, +} + +sc_set :: proc { + p256r1.fe_set, + p384r1.fe_set, +} + +sc_zero :: proc { + p256r1.fe_zero, + p384r1.fe_zero, +} + +sc_one :: proc { + p256r1.fe_one, + p384r1.fe_one, +} + +sc_add :: proc { + p256r1.fe_add, + p384r1.fe_add, +} + +sc_sub :: proc { + p256r1.fe_sub, + p384r1.fe_sub, +} + +sc_negate :: proc { + p256r1.fe_opp, + p384r1.fe_opp, +} + +sc_mul :: proc { + p256r1.fe_mul, + p384r1.fe_mul, +} + +sc_square :: proc { + p256r1.fe_square, + p384r1.fe_square, +} + +sc_inv :: proc { + p256r1.fe_inv, + p384r1.fe_inv, +} + +sc_cond_assign :: proc { + p256r1.fe_cond_assign, + p384r1.fe_cond_assign, +} + +sc_equal :: proc { + p256r1.fe_equal, + p384r1.fe_equal, +} + +sc_is_odd :: proc { + p256r1.fe_is_odd, + p384r1.fe_is_odd, +} + +sc_is_zero :: proc { + sc_is_zero_p256r1, + sc_is_zero_p384r1, +} + +@(require_results) +sc_is_zero_p256r1 :: proc "contextless" (fe: ^Scalar_p256r1) -> int { + return int(subtle.u64_is_zero(p256r1.fe_non_zero(fe))) +} + +@(require_results) +sc_is_zero_p384r1 :: proc "contextless" (fe: ^Scalar_p384r1) -> int { + return int(subtle.u64_is_zero(p384r1.fe_non_zero(fe))) +} diff --git a/core/crypto/_weierstrass/scalar_mul.odin b/core/crypto/_weierstrass/scalar_mul.odin new file mode 100644 index 000000000..eb3fa1459 --- /dev/null +++ b/core/crypto/_weierstrass/scalar_mul.odin @@ -0,0 +1,299 @@ +package _weierstrass + +import "core:crypto" +@(require) import subtle "core:crypto/_subtle" + +pt_scalar_mul :: proc "contextless" ( + p, a: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, +) { + when T == Point_p256r1 && S == Scalar_p256r1 { + SC_SZ :: SC_SIZE_P256R1 + } else when T == Point_p384r1 && S == Scalar_p384r1 { + SC_SZ :: SC_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + b: [SC_SZ]byte = --- + sc_bytes(b[:], sc) + + pt_scalar_mul_bytes(p, a, b[:], unsafe_is_vartime) + + if !unsafe_is_vartime { + crypto.zero_explicit(&b, size_of(b)) + } +} + +pt_scalar_mul_bytes :: proc "contextless" ( + p, a: ^$T, + sc: []byte, + unsafe_is_vartime: bool = false, +) { + when T == Point_p256r1 { + p_tbl: Multiply_Table_p256r1 = --- + q, tmp: Point_p256r1 = ---, --- + SC_SZ :: SC_SIZE_P256R1 + } else when T == Point_p384r1 { + p_tbl: Multiply_Table_p384r1 = --- + q, tmp: Point_p384r1 = ---, --- + SC_SZ :: SC_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + assert_contextless(len(sc) == SC_SZ, "weierstrass: invalid scalar size") + mul_tbl_set(&p_tbl, a, unsafe_is_vartime) + + pt_identity(&q) + for limb_byte, i in sc { + hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f + + if i != 0 { + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + } + mul_tbl_lookup_add(&q, &tmp, &p_tbl, u64(hi), unsafe_is_vartime) + + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + mul_tbl_lookup_add(&q, &tmp, &p_tbl, u64(lo), unsafe_is_vartime) + } + + pt_set(p, &q) + + if !unsafe_is_vartime { + crypto.zero_explicit(&p_tbl, size_of(p_tbl)) + pt_clear_vec([]^T{&q, &tmp}) + } +} + +pt_double_scalar_mul_generator_vartime :: proc "contextless" ( + p, q: ^$T, + sc_g, sc_q: ^$Q, +) { + // Strauss-Shamir, commonly referred to as the "Shamir trick", + // saves half the doublings, relative to doing this the naive way. + // + // Note: In the unlikely event where we support curves with an + // efficent endomorphism (secp256k1), scalarmul + GLV is faster. + when T == Point_p256r1 && Q == Scalar_p256r1 { + q_tbl: Multiply_Table_p256r1 = --- + SC_SZ :: SC_SIZE_P256R1 + } else when T == Point_p384r1 && Q == Scalar_p384r1 { + q_tbl: Multiply_Table_p384r1 = --- + SC_SZ :: SC_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + sc_q_bytes, sc_g_bytes: [SC_SZ]byte = ---, --- + sc_bytes(sc_q_bytes[:], sc_q) + sc_bytes(sc_g_bytes[:], sc_g) + + r, tmp: T = ---, --- + when crypto.COMPACT_IMPLS == true { + pt_generator(&r) + when T == Point_p256r1 { + g_tbl: Multiply_Table_p256r1 = --- + } else when T == Point_p384r1 { + g_tbl: Multiply_Table_p384r1 = --- + } + mul_tbl_set(&g_tbl, &r, true) + } else { + when T == Point_p256r1 { + g_tbl := &Gen_Multiply_Table_p256r1_lo[31] + } else when T == Point_p384r1 { + g_tbl := &Gen_Multiply_Table_p384r1_lo[47] + } + } + mul_tbl_set(&q_tbl, q, true) + + pt_identity(&r) + for i in 0..> 4) & 0x0f, limb_byte_q & 0x0f + hi_g, lo_g := (limb_byte_g >> 4) & 0x0f, limb_byte_g & 0x0f + + if i != 0 { + pt_double(&r, &r) + pt_double(&r, &r) + pt_double(&r, &r) + pt_double(&r, &r) + } + mul_tbl_lookup_add(&r, &tmp, &q_tbl, u64(hi_q), true) + when crypto.COMPACT_IMPLS == true { + mul_tbl_lookup_add(&r, &tmp, &g_tbl, u64(hi_g), true) + } else { + mul_affine_tbl_lookup_add(&r, &tmp, g_tbl, u64(hi_g), true) + } + + pt_double(&r, &r) + pt_double(&r, &r) + pt_double(&r, &r) + pt_double(&r, &r) + mul_tbl_lookup_add(&r, &tmp, &q_tbl, u64(lo_q), true) + when crypto.COMPACT_IMPLS == true { + mul_tbl_lookup_add(&r, &tmp, &g_tbl, u64(lo_g), true) + } else { + mul_affine_tbl_lookup_add(&r, &tmp, g_tbl, u64(lo_g), true) + } + } + + pt_set(p, &r) +} + +when crypto.COMPACT_IMPLS == true { + pt_scalar_mul_generator :: proc "contextless" ( + p: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, + ) { + g: T + pt_generator(&g) + + pt_scalar_mul(p, &g, sc, unsafe_is_vartime) + } +} else { + pt_scalar_mul_generator :: proc "contextless" ( + p: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, + ) { + when T == Point_p256r1 && S == Scalar_p256r1 { + p_tbl_hi := &Gen_Multiply_Table_p256r1_hi + p_tbl_lo := &Gen_Multiply_Table_p256r1_lo + tmp: Point_p256r1 = --- + SC_SZ :: SC_SIZE_P256R1 + } else when T == Point_p384r1 && S == Scalar_p384r1 { + p_tbl_hi := &Gen_Multiply_Table_p384r1_hi + p_tbl_lo := &Gen_Multiply_Table_p384r1_lo + tmp: Point_p384r1 = --- + SC_SZ :: SC_SIZE_P384R1 + } else { + #panic("weierstrass: invalid curve") + } + + b: [SC_SZ]byte + sc_bytes(b[:], sc) + + pt_identity(p) + for limb_byte, i in b { + hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f + mul_affine_tbl_lookup_add(p, &tmp, &p_tbl_hi[i], u64(hi), unsafe_is_vartime) + mul_affine_tbl_lookup_add(p, &tmp, &p_tbl_lo[i], u64(lo), unsafe_is_vartime) + } + + if !unsafe_is_vartime { + crypto.zero_explicit(&b, size_of(b)) + pt_clear(&tmp) + } + } +} + +@(private="file") +Multiply_Table_p256r1 :: [15]Point_p256r1 +@(private="file") +Multiply_Table_p384r1 :: [15]Point_p384r1 + +@(private="file") +mul_tbl_set :: proc "contextless"( + tbl: ^$T, + point: ^$U, + unsafe_is_vartime: bool, +) { + when T == Multiply_Table_p256r1 && U == Point_p256r1{ + tmp: Point_p256r1 + } else when T == Multiply_Table_p384r1 && U == Point_p384r1{ + tmp: Point_p384r1 + } else { + #panic("weierstrass: invalid curve") + } + + pt_set(&tmp, point) + pt_set(&tbl[0], &tmp) + for i in 1 ..<15 { + pt_add(&tmp, &tmp, point) + pt_set(&tbl[i], &tmp) + } + + if !unsafe_is_vartime { + pt_clear(&tmp) + } +} + +@(private="file") +mul_tbl_lookup_add :: proc "contextless" ( + point, tmp: ^$T, + tbl: ^$U, + idx: u64, + unsafe_is_vartime: bool, + ) { + if unsafe_is_vartime { + switch idx { + case 0: + case: + pt_add(point, point, &tbl[idx - 1]) + } + return + } + + pt_identity(tmp) + for i in u64(1)..<16 { + ctrl := subtle.eq(i, idx) + pt_cond_select(tmp, tmp, &tbl[i - 1], int(ctrl)) + } + + pt_add(point, point, tmp) +} + +when crypto.COMPACT_IMPLS == false { + @(private) + Affine_Point_p256r1 :: struct { + x: Field_Element_p256r1, + y: Field_Element_p256r1, + } + + @(private) + Affine_Point_p384r1 :: struct { + x: Field_Element_p384r1, + y: Field_Element_p384r1, + } + + @(private="file") + mul_affine_tbl_lookup_add :: proc "contextless" ( + point, tmp: ^$T, + tbl: ^$U, + idx: u64, + unsafe_is_vartime: bool, + ) { + if unsafe_is_vartime { + switch idx { + case 0: + case: + pt_add_mixed(point, point, &tbl[idx - 1].x, &tbl[idx - 1].y) + } + return + } + + pt_identity(tmp) + for i in u64(1)..<16 { + ctrl := int(subtle.eq(i, idx)) + fe_cond_select(&tmp.x, &tmp.x, &tbl[i - 1].x, ctrl) + fe_cond_select(&tmp.y, &tmp.y, &tbl[i - 1].y, ctrl) + } + + // The mixed addition formula assumes that the addend is not + // the neutral element. Do the addition regardless, and then + // conditionally select the right result. + pt_add_mixed(tmp, point, &tmp.x, &tmp.y) + + ctrl := subtle.u64_is_non_zero(idx) + pt_cond_select(point, point, tmp, int(ctrl)) + } +} diff --git a/core/crypto/_weierstrass/secp256r1_table.odin b/core/crypto/_weierstrass/secp256r1_table.odin new file mode 100644 index 000000000..1a6bc3ef6 --- /dev/null +++ b/core/crypto/_weierstrass/secp256r1_table.odin @@ -0,0 +1,3985 @@ +package _weierstrass + +/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ + +import "core:crypto" + +when crypto.COMPACT_IMPLS == false { + @(private,rodata) + Gen_Multiply_Table_p256r1_hi := [32][15]Affine_Point_p256r1 { + { + { + {9259451175701532574, 15597985540941612547, 4541553034987877619, 8927802479718285609}, + {14672230714928802576, 14284617950605306700, 13339970812390782046, 787078889494395850}, + }, + { + {18165439414433063919, 14693282888419586094, 14992616289789993230, 13232208150801553912}, + {16850347485914337693, 223364064845089224, 7302899015436300563, 4391216311540396088}, + }, + { + {12558388403188680537, 10687978569513354810, 9373570856564649772, 4079327722512691465}, + {5372437374337150740, 3297421622932790851, 9326853593823854687, 8305371884938201251}, + }, + { + {13121472331750731303, 323745485980480220, 15110308702528119977, 4696302365805118372}, + {9859094500834571602, 5315656270700787939, 4187063204400651801, 1695695129564818327}, + }, + { + {12817586844019849804, 15425488216915741929, 15293562913126043054, 11770898970765978555}, + {6806103820345670787, 17789094149138630459, 3807781571713999192, 5823254011289457198}, + }, + { + {10112524230916015604, 13571143908656270599, 6031089010487808103, 5774558171390644848}, + {1808959243244841573, 14071312530426692155, 9241399242704553402, 9836150050655369231}, + }, + { + {14083007972403535491, 16009534514129505275, 12481249112231139039, 10309390659262581143}, + {5782517315325366794, 16717384553294759530, 4578392002424884134, 239005024949492645}, + }, + { + {1836857790164349346, 11263074778654917115, 4786985732596838094, 10525445084936097674}, + {1484357665966453236, 3110871407036679558, 1668700683093601768, 2736269131339849752}, + }, + { + {9249362594190920246, 8088172462140746331, 4080107866285682736, 16205599538438551353}, + {18312943145606312277, 9100632964181080418, 3969991115337154345, 5340098959750368315}, + }, + { + {12122448407048035645, 2891250339380982359, 12794212052932523400, 7166035112141500392}, + {15777441312724841162, 4552528682229856831, 2210391301762911476, 16410254680957321386}, + }, + { + {6910044784455706429, 11951245774670922855, 207795885948948810, 3884359690300962405}, + {4578772752480772344, 2948797025787714138, 16774444535658202808, 1388183483009000463}, + }, + { + {16561979129019905420, 1881862411760441386, 15441950514711322010, 12933020223458438856}, + {5570341451312029630, 18172638959728259059, 9074261777549091198, 6171200053222754816}, + }, + { + {10126435102176037237, 1545112930055760251, 11563139991870561593, 10766754172364938834}, + {5116781688621052838, 14471715119500781375, 4724882615229687192, 10031687030722046325}, + }, + { + {15016829467434780812, 6777508689306592732, 3811682306063049290, 11475361222871876387}, + {6080948654298953274, 11612742274762615033, 5268311600240325047, 9147351973710519861}, + }, + { + {12130203770930472759, 3880998309361490881, 8807462332494735511, 9291388074337055133}, + {18165312304248982432, 12733144434841535979, 18090195697688236271, 5825342884125782172}, + }, + }, + { + { + {194633990068625151, 1028128699653523895, 7436102537486268753, 1855520454959348468}, + {5098690958966904466, 3342676718901330604, 6942212660412942406, 16510188838209674083}, + }, + { + {7963995066277321795, 14986230345162551366, 10616366460602472778, 16186943329215681149}, + {9522855644164647723, 9858336437877021178, 16344942402271072884, 18027353494090590022}, + }, + { + {13392726161043192788, 7606793939450765773, 9543984695709321129, 6135912406103198328}, + {10903991926178685177, 529801710637680784, 8207012095420105234, 4590962949922268360}, + }, + { + {13175608910844763921, 11168387468381338510, 5555873864224342205, 17780559602571640345}, + {1582669533588472814, 8145133762789622706, 1625372887980692455, 4576809104068554285}, + }, + { + {17616803153811079355, 17809794753465712025, 10788493879428408032, 1263026253532745742}, + {331896291298606534, 13299145463579793142, 8951131463540898010, 11121758705853021600}, + }, + { + {17015522374255846157, 7155392284047197223, 1248775493117789546, 9199472299655737207}, + {13126885324657282947, 12092989376083683289, 2035698983314262432, 835441512024005104}, + }, + { + {12481871371020004325, 15786477648044981224, 2586272424816191689, 4208704695692543659}, + {16940467964964992440, 11207566805119564978, 2858987625603639630, 9561510646236248154}, + }, + { + {2900978533555060931, 1749946807863203576, 11705734511931072459, 4446980691693419424}, + {14437524160594907241, 12795912566640000773, 10400036254697939154, 8356113088668925361}, + }, + { + {3770654812111500682, 7723332701546321657, 12057007323752084660, 11871339027463593983}, + {8927366002257844381, 331175455338905356, 6085376066711046662, 195998713859126244}, + }, + { + {15888580251537997623, 14253909833728698978, 14445538492667230716, 4028538972354525849}, + {7720263170150940477, 1190890222876864097, 8657188516818851005, 1987613286973742753}, + }, + { + {1556082539082087499, 9191446579576007527, 16923484407567577707, 4662661048159090855}, + {12760778972220173745, 3942937056545553996, 12952479961991875179, 8914103212381870290}, + }, + { + {8900726473285671992, 890209742292473781, 16059468388719373167, 16577940938542233221}, + {17381766864962227733, 231915274132518769, 16477817024012878700, 15646021286310268545}, + }, + { + {10104554368814337641, 170400126349943750, 16051269335758964391, 7842493858299913771}, + {9246756702190574744, 110682656515867335, 11402798562961521905, 17325237240525801251}, + }, + { + {15837018286366797690, 18114413810565810328, 9441874034567150801, 14075941137889189393}, + {12786763055047269260, 9121030808281463204, 1713778999270814105, 17015261864438490667}, + }, + { + {12997570542605430113, 5500897611058123544, 4160129407772614089, 13768264346635084004}, + {6638654171187871203, 6080635069726153281, 2255431148803290413, 3789670411999607189}, + }, + }, + { + { + {1830819081327272165, 11951292080860646547, 18002500803418629938, 13317986695217403840}, + {5005574200470766330, 10138179785738652504, 1610518863105278224, 13309443265578956954}, + }, + { + {14192194428653714479, 11578618567931657764, 6032668189933768881, 15981535562386193924}, + {8925792218631314923, 9408714146004183681, 8859017894477140398, 1675606340537058506}, + }, + { + {3265119697568866078, 13753322853248061974, 15435163376825672274, 13646180516491714938}, + {15620545622955090250, 18241486585498394565, 459566729126467878, 9728217493753855944}, + }, + { + {9883406233903270985, 17184231210468300584, 5498903678702785900, 6903833261382863389}, + {11489138095102981636, 9021901931786177471, 3227433089132150317, 16639455550797627042}, + }, + { + {839045372102318861, 2032615141683118500, 1921816835840256924, 504869150737570005}, + {15932184001422473505, 7849475855313305697, 1189994394722618598, 9874798350548229684}, + }, + { + {4636201671610663345, 16662311204732135584, 12398897461787695675, 1355753199357412657}, + {14695655628527768564, 1692838776852698754, 7346906782826540912, 14869028424564984700}, + }, + { + {14240080119980315297, 4751983902385717684, 7941412103662252178, 4796803816695225123}, + {9327986654018000413, 15111345676387005726, 3582558555283734415, 11913156735178831102}, + }, + { + {12915868875134296756, 3071143582305760275, 10848717856747030010, 10973183887638314967}, + {5983269487036236823, 9885184706933333413, 14509493669845681951, 9669608065801379977}, + }, + { + {7848634325810890057, 4356492357483949442, 8777700982672429871, 447737364627887590}, + {2892466086138453900, 12013259293340538023, 3423275627272380730, 11171074631447548946}, + }, + { + {14593553227914306527, 7393098159726367793, 959457858782426605, 12924066827318848802}, + {14790800265003508462, 13805969419986022239, 4408523909823076864, 16722715416825698787}, + }, + { + {8554182115079118694, 17233907570567075631, 12336560627384786590, 5123566378696582545}, + {96401035522143140, 10138155491929979850, 17651328686428132420, 3453390145222258032}, + }, + { + {16197242500758474188, 3349369240724295499, 9422940308750670637, 16888844525585804807}, + {14045424784406071799, 13180603138700207746, 2683581192503868543, 3842875784859878}, + }, + { + {17498073686183419231, 6922314891526280784, 16083733402282932920, 15425477806093217459}, + {12425976625898608391, 16458101989314253841, 10013521940061058050, 10858868879196007236}, + }, + { + {123600201037598181, 6690762836954208162, 17157040810691942664, 15263405971805161132}, + {8685477170453562173, 10331174323986544033, 5789045082422148337, 3007978469441468974}, + }, + { + {2402095889286816125, 18054120920831753009, 11753130221915918396, 10341553510464463050}, + {280903370426929900, 14994955837151914025, 13551362401871479612, 14711789630561753093}, + }, + }, + { + { + {14086745261650819748, 17953107869776717888, 1777725846494438428, 2765314406831814212}, + {2603997194371852991, 2223517025105045134, 15579901335531749634, 6571733615332171148}, + }, + { + {5478465698516556930, 287443454357750768, 12201204663663129285, 782849770204658255}, + {11270045035009204251, 18152683972363144337, 10463300037926642739, 14363641589598863851}, + }, + { + {3790592075869665284, 5120320091554329756, 15361581282394028709, 14360464660911164915}, + {15249656958991931940, 2563751872827049233, 13745792006936646733, 14572943674933168173}, + }, + { + {3167679014977537749, 3417445004776702290, 1709246158507866266, 5861367897285174360}, + {8437429877561342262, 17231607446243478748, 16047596399306766948, 17656438585829685897}, + }, + { + {12977336347094692192, 13723871955002954132, 17399919575273038847, 16163973860244779675}, + {14997921584659740746, 6543247361992425067, 4675926398794487109, 17580512382853194054}, + }, + { + {10778828023580771765, 9812611440536367405, 14168149065325522570, 6692229110872358750}, + {11010962724400581057, 13055203605065073902, 11396463140731730116, 16969789651736772232}, + }, + { + {3285258013801327520, 14114268241282882888, 5367399533198476395, 17277410244918727028}, + {2751895479568588421, 751309667192066167, 13038472116718581917, 16013586354334596135}, + }, + { + {12364168614988940500, 13194367252463423118, 12223406606527741280, 5014139294736037086}, + {11244699482831816093, 5336498572491451990, 14268404582568856142, 14502318820969599316}, + }, + { + {13295673091232554814, 313981772853781347, 11829785736449464030, 13341198421333360997}, + {16787450350663111566, 6525407229623764159, 2012189087039636323, 2110887590404698758}, + }, + { + {16984895766311549717, 1057465499230843916, 13565444352859773343, 1019268943988786852}, + {2190009140530404855, 10045598732295352970, 4789803496780829836, 10700158388954091321}, + }, + { + {14840255112988420500, 10066628133368048408, 6527354835873855384, 16106607076894419125}, + {3989024604987083046, 10713316697020150694, 16811389107269552264, 11294596059797019619}, + }, + { + {622403023838932676, 11423409007234191765, 17086830255702454786, 1213655124481948199}, + {3976593910085142945, 6315875935390432543, 17947502153968859628, 18031540937011531543}, + }, + { + {342675887578148289, 18366454547938469828, 3853530442390999217, 7499455395579634652}, + {768597405171336502, 1636271570683567151, 16786205337983572309, 13056241332863199715}, + }, + { + {15991153618414855143, 803325462494472241, 5709347424437559249, 10138502962472290727}, + {4675124205115228106, 9599016746550345197, 2769443894695609085, 12311020551315051087}, + }, + { + {11470964304318784059, 17313372553735202469, 10686997186364536871, 9228453594798060121}, + {57933324335302024, 8931389936300346353, 17823596478938529898, 1126996688113949835}, + }, + }, + { + { + {15804957839814547154, 7924193945337173678, 1080401129055171214, 10816444561878528576}, + {13171610473229361771, 8099842733764406841, 9284741070210451667, 9245195215372025289}, + }, + { + {7185947197544988797, 13306809398790059447, 11440959253278285287, 15084384140482244570}, + {5059824327869316332, 7585354587200615362, 6801884469610571467, 6427162399794357267}, + }, + { + {1505501490785526604, 6062033360335279190, 13214531355927393851, 8869230490276248430}, + {11596558698255017116, 6698268011950867978, 15445165013361223076, 4910055064120213146}, + }, + { + {1453348772281274490, 13028088570940491471, 16100623112750251840, 5210244400259879874}, + {9443916155735416174, 16869520919318450506, 7479400208826706574, 14374970913352602458}, + }, + { + {13057495656815142976, 1743194961605203063, 15733599697884179267, 3501754291485677593}, + {7405256272105757266, 12344297842308545819, 3389605493339498760, 3092252531918600248}, + }, + { + {5038191990715247960, 2723916483244871576, 4891019526710760134, 11094632341133260369}, + {6274429941353136467, 1408871421293516065, 12455625869488488781, 3401549469990652817}, + }, + { + {4716563932720198201, 1584625214845878997, 13213357619008940082, 13122950207230795185}, + {12303370001794463898, 6725033180592084698, 12302152314224424594, 6139100303374835750}, + }, + { + {10149597276931117465, 5778043705364022356, 13888443605241209218, 6889225091714429810}, + {16209363638493043975, 8516350006446457646, 9214830076046105138, 8894115046323798175}, + }, + { + {161027176918876103, 2287100732338401479, 16561946444121779293, 9805329436091376243}, + {11473978632757961256, 1245289731366992705, 7338435771556366282, 15749864527919116005}, + }, + { + {2753237807828198865, 11508305846735597339, 9058745440380813449, 3960739040735759442}, + {17921955885187582871, 10231929062430218022, 18115018235326517243, 17854413167898372208}, + }, + { + {638684488109167329, 14596365931372343092, 1917271942976854297, 12291978018935761003}, + {5076527739384635812, 7833625460571766680, 17060902137821849350, 17134703695475138982}, + }, + { + {13026208197163596446, 1935567165776196957, 17296090833026336866, 8461284827078097590}, + {14545382879887213077, 3302103559307506085, 16026840048628844803, 4599071908983273604}, + }, + { + {9156540407095300222, 7598243263658987831, 1996711254516517688, 13013193687414837552}, + {116495354444693499, 12803585308662671588, 8278106437192580735, 3374263264867687146}, + }, + { + {4318910866113560561, 8122780372606489166, 11952351993471767425, 9581759925599323445}, + {12268585667545114307, 7286163136539353394, 12697490728074784421, 7270019569202782882}, + }, + { + {16247467139569457576, 14043942371464607677, 6338399572126720647, 9528527345786650933}, + {16344656963096275115, 13804658662065732334, 2991248997774547140, 12174436388699549119}, + }, + }, + { + { + {1169887957113173798, 4936710663791789838, 8029349457377894665, 3317691225106441967}, + {3622769674498678594, 1954144360900150482, 1432045977341997899, 934737636789214593}, + }, + { + {9646181593082190523, 16068017411165381498, 13319927590045936565, 6113055520205251774}, + {5576373032696512038, 13880344501714804196, 12022206929479211261, 7387979357081975315}, + }, + { + {13553890993911526641, 1237937561304731611, 11053651340854998814, 8737874920379363783}, + {15414508226001886918, 9311523317130687807, 12080742822716708234, 4715194040021784977}, + }, + { + {17182132836049601530, 1486820395924546410, 14089047182364760490, 5375431386740917568}, + {2352352269256972682, 6220398075470064021, 11444733678216077372, 8173002234516562536}, + }, + { + {7896339057146013415, 17613745684396593735, 4238258305077796259, 15438639564771394288}, + {1482402451684594916, 3104492350488980260, 5195487229736262641, 1361150797580203482}, + }, + { + {15949855327936545010, 15892613064802301412, 7776232754624386979, 2193423430757249310}, + {10751855334513902678, 13772090376350944100, 5644047706587449960, 370992037484721524}, + }, + { + {16329953561108738383, 14553061366216182492, 5112198484879130320, 1893048255589705004}, + {11469678860036344015, 8992526488267920066, 18208245559304821518, 8980963391041920447}, + }, + { + {5783711159088718530, 3503029393593618754, 10736192136662142256, 15443859608128978668}, + {271805305647187927, 8244170003029416464, 17017071503038388446, 2536084345379259313}, + }, + { + {9850291665987916519, 6499970366121170030, 7001995026899086280, 9961826319039756858}, + {7497823327397141096, 6975352931548332265, 4068344268340314997, 15888973419716629698}, + }, + { + {3982898776583485812, 10403233710814076420, 8681461491810344216, 4116685619183896910}, + {18192868132325233114, 17377077437999490605, 17997716263755054576, 10376686656480866118}, + }, + { + {3479412946560984795, 5044366097675527819, 13707564929638264911, 5666779920208401261}, + {10137470376683230183, 2075467328249870088, 11457126564907274413, 13701087332649256159}, + }, + { + {12574253652565934836, 8388159655344384255, 16127953452716629313, 1877819316325313228}, + {8945746653921217760, 4616678606113198065, 1336330019150074567, 11910289150769410280}, + }, + { + {9565592090082898867, 1968790057506790036, 4797721149040405609, 13125809848505545280}, + {14122665390767023537, 17271175538744290850, 16007653062195668190, 16371835205840876479}, + }, + { + {10409691258933377688, 13736467137095186370, 2757793467881882435, 12443439690522935631}, + {17601924849565694404, 988048065500720515, 7554063443268400107, 4274248596892038508}, + }, + { + {8972162505776549196, 16209364130421564220, 13018196697272262431, 418388148277092169}, + {11645493996879973039, 5024734975063482607, 3708889997144620499, 11208942121415360714}, + }, + }, + { + { + {17596113920958619489, 11920824479658301378, 3786905428099710821, 11112764289322906111}, + {8817260450068629272, 6518847791514184438, 14593687325057339783, 18018581321332807475}, + }, + { + {2056254186648603335, 12143016575009965669, 3290271983033386616, 4338404082685850854}, + {12660444972475266123, 6345409453044955404, 13278869140778657354, 10063005167581762786}, + }, + { + {5303950317664091150, 17409642188139937758, 12135894348302287058, 16444741243419918751}, + {13935885817311324323, 8496908197501732703, 12163317723288843510, 16891353436915314685}, + }, + { + {4168420842704770545, 338440394515115377, 2102734009665481092, 9772725684473416465}, + {1247616337419130000, 4222072446972129729, 4836898447189504007, 9154346000276664999}, + }, + { + {14649401370738987318, 10044081678892811795, 1306517740393103656, 16586067283450489622}, + {8211832777731897494, 12849393859171286949, 17327526552807783018, 14171704619529498238}, + }, + { + {12849053390245557890, 12693731077061619694, 5891211584023409476, 1008960642219209210}, + {15593393872187214387, 7381248773473326001, 16559656086795428559, 2106025108820858934}, + }, + { + {4347667984894353308, 2129883711661222690, 1076488804494872856, 15059968377755299195}, + {12380937310378496242, 16425480883270944108, 4769192332535557551, 10388305045430499744}, + }, + { + {8553482596123775980, 12627020622203381515, 10774788686070344669, 6271789114731522097}, + {6270586844349642345, 5584690155569770537, 9478526526319537174, 3405597782572827563}, + }, + { + {10255408065071335198, 2384996481315588922, 10679447117297819075, 3734157461055440416}, + {1635042286365643780, 11321809677772938996, 2373960964139986040, 4869129159740273704}, + }, + { + {16681657814739017038, 2045405432090866328, 9473434018957974472, 5549808619751464269}, + {3650191693776946828, 15805634549736708741, 16764187297356548667, 6849534466635874363}, + }, + { + {15295973549776084894, 8150873746601283651, 8017271980921908229, 4899654767305073834}, + {15257501950484641691, 17365331272978440066, 14582514748324426172, 14727798284858071666}, + }, + { + {3180828552573045472, 17698570278585440462, 8986722854533057232, 4518665117523514004}, + {1718699978312382231, 16973074530347269964, 5684175730451960274, 17228649521631238473}, + }, + { + {2897180423141326703, 13691273076814343144, 2967066815351306232, 1032540647518716635}, + {16365716239989474776, 9503666134295232767, 4599017511227366879, 14475021161770955579}, + }, + { + {4512626226592149712, 13575110216387069176, 13488662643497927183, 9673147324484250604}, + {143936220816719815, 2307325398241477161, 468315224038772027, 17743582630124600591}, + }, + { + {1476494936296433813, 3408612621327299295, 11632756669813257564, 14296719897220703576}, + {2241234207239321749, 12237974399755684219, 16253635131573079566, 11892871179872526079}, + }, + }, + { + { + {9440495138081785154, 17328162383695942099, 1870751290505230781, 17987066187778049275}, + {9952223038481207705, 10126409487298126876, 1181369784146909444, 8158422380540037915}, + }, + { + {10892870009313407934, 5709686117526627488, 16343828906887149047, 16063790174205876315}, + {9076070192754075075, 4639156357669822592, 4904064385440242264, 5942264027390072320}, + }, + { + {14586043427955633062, 1886633882927769308, 12786104261802569226, 17414735423561048102}, + {3869682486341171982, 17146691898427698057, 9886217016173201579, 17515773620461053745}, + }, + { + {17271984572727555145, 2097715321690717305, 5328035183708920909, 13206781766168781008}, + {5915693606819932446, 3870849056297265622, 18070792155150730518, 7786839743829304936}, + }, + { + {14091274565690260814, 5039742420071412611, 2322945829654574283, 7678395717670225646}, + {17396071770599775867, 4747582460834310767, 13387178106758137047, 7224458787360678986}, + }, + { + {2020583809775623843, 3803516109208330416, 10492323079463714031, 18244921722581618682}, + {6400055933742731191, 18370212581946723247, 11415812944884122048, 5987324147127294665}, + }, + { + {3106709870210381627, 3437108621064387068, 3265644153772373951, 14353255805499610949}, + {11329727508866046420, 5461257448868659690, 8139681370942905079, 8439558396411914298}, + }, + { + {7939886940063870939, 3597929036186322512, 12732772396498766041, 13300425267730247515}, + {2345112231224079293, 12327614629296314761, 17106102937162407683, 1702694317559034053}, + }, + { + {4276582831142955483, 1304336253044853784, 18317056640605949326, 11200473213973297420}, + {3937030502759894542, 2315314353886242360, 2673827662906962132, 9781744582918546067}, + }, + { + {17837268310687096164, 10122495457633601623, 11985150009870152981, 11282144500794610389}, + {13999168735732598559, 9030771445951876212, 6423904381826094276, 6148980837201061250}, + }, + { + {14621142736654260750, 1806201536162806753, 12562675185535659971, 5326177198980139868}, + {8675433132905478434, 10796034085894917871, 7562073626744691385, 1491977564717017512}, + }, + { + {8821632341545057929, 16708916351043551467, 9171560460858577216, 5711973041149612575}, + {15808302665077457285, 8412173943543358851, 12602476370021215716, 4778674887660148537}, + }, + { + {7524796586818405222, 5468491023058834244, 7965536127579551161, 9575670558568595724}, + {4020611179055350793, 186082735900253826, 11198349470461895384, 2693853052562145978}, + }, + { + {7977371007734934919, 1442746893361509157, 15080044066626816201, 9179319344686817504}, + {17927184654813605164, 16541635384799094673, 1663389722548868092, 9157422724003022421}, + }, + { + {4167146676307544690, 12042136744739037957, 6606952994938338836, 7554398412699794678}, + {11844277247778765775, 8165791089025933303, 14954338535964037723, 16693854111477654477}, + }, + }, + { + { + {5841260956815214452, 9461234662498869948, 4761949640006529525, 18229823346336752572}, + {16055957459773168413, 4272222475092786627, 18249888117586812770, 4531982814021269346}, + }, + { + {7270238601276019194, 7318279377964882079, 5226788506940171017, 16838449902078450273}, + {3375184937745100689, 16320655850583231520, 2173229791272659780, 9816381971766204380}, + }, + { + {17113448198982970082, 8879656883528014268, 15215762680430094206, 15232212751792759071}, + {13699137317730183483, 11815206710130297569, 12298409691055054593, 2192455093917691024}, + }, + { + {9742819322069712752, 8779224519997661749, 2591205872359340025, 9144644967919881415}, + {10495832103710459914, 4557264342687723360, 935865282128150338, 7120324256648044882}, + }, + { + {4683169301229531061, 14940390399739549639, 13128742567354398401, 15222231511210090535}, + {7352694898928671332, 1221555526903686446, 8697118143614336514, 14515400523185205597}, + }, + { + {10239864229747754958, 12477284975467600510, 14054830413782031834, 17752968481181892755}, + {16082713391521411762, 17191329716867535304, 11245514405315337909, 15159733745232554536}, + }, + { + {15444441705629456398, 12030687282161152512, 16500102437404896225, 11467410246278043769}, + {14031300093087427598, 14458597378298191386, 9434445586505481169, 18221119130471329822}, + }, + { + {12694666558858009121, 10992313774737315187, 6046508760845509477, 16818819584649823054}, + {10464090160691032219, 1221502600750419478, 8658907655588546849, 16110628890984509877}, + }, + { + {14304143349839262251, 13048055876309896774, 8676204847923624352, 8365498293767636038}, + {13565995665971214654, 10895028049457785231, 5911971723937387023, 8436244239466286317}, + }, + { + {11501032393232899227, 3895174794911924947, 3230698222875450976, 7264134402609589101}, + {18091100044992147344, 13252184705645692134, 8424205723200969631, 5731735154358029264}, + }, + { + {12163905774765001813, 3911227235818691672, 9833792088244333742, 6413344327541478453}, + {15325942369130325853, 12629318625161567307, 8784755949357111975, 9462269284575183222}, + }, + { + {2157617452419341992, 3753997642171159286, 6553292364671628995, 4814048166016850277}, + {6152139240994642263, 14066819599579263267, 7377541740373798192, 17830582976167057789}, + }, + { + {6906089045659836134, 17967958089618664024, 13353206790928340833, 14671934547763383296}, + {12187232481950713594, 8718528695481423527, 18137604428804898613, 17758096361511845106}, + }, + { + {17646581888040948752, 8252837592394234071, 2508742924483223473, 5332070238932154531}, + {13165985796861395246, 4409584176627274781, 9230253121183107430, 8784052955551358471}, + }, + { + {5394535031187713437, 5279515585052353937, 14159976884067043134, 10130852155763718010}, + {13777927158878861230, 14015445621678244733, 3350717438960860318, 7071836838770144750}, + }, + }, + { + { + {10708602749843635238, 8046488591192123621, 11391158257016334553, 2512908912806916201}, + {14760224624269838038, 2631910198880826809, 2387247811669872033, 2048193899742148806}, + }, + { + {17392983665205025720, 12603331233691760840, 3752711326309791976, 8281544857330094164}, + {17004651346561270106, 10399322540256775923, 9721299450284863176, 3725182263994944884}, + }, + { + {13643198694788276032, 8127425924819487897, 14165945065582850538, 16520977003164405917}, + {1941948502806705647, 12390949208067741787, 17112117376594486408, 10232906951259490042}, + }, + { + {74190110112564319, 11227229657066745164, 10151080599595091944, 16591051376074591375}, + {8256332495682655293, 7127985739945537626, 5708687346183367016, 18310921046455023281}, + }, + { + {10040565835468209502, 3986586816478505371, 7957179672896506016, 13347112914739722590}, + {14099734293320932556, 13921950344400895005, 17478414833301838037, 961445463330402797}, + }, + { + {10553899634420153414, 4215979268474142438, 3643081140297634139, 11620906704125380460}, + {17733628678553828301, 137473878710304143, 6211837577294956591, 13926110616399428016}, + }, + { + {15203257341351417031, 11597829209697937782, 17317571979811895272, 15929491640570317745}, + {5731227916276913121, 17093153916149088230, 3908757069480556294, 18211818355208735794}, + }, + { + {6887629766078662088, 15330755394432598442, 14144608177273202986, 13258654996547018856}, + {8975611270007504091, 16869834856279102361, 12707970875852047823, 8520055680055874514}, + }, + { + {1643407997152867899, 5400650551136488814, 14663391437159245064, 4743209938058826866}, + {1728998201888511561, 11238331920657195520, 11617984741897247805, 13858029141809651878}, + }, + { + {14003691155137683825, 14641672309228817657, 4031783205073356111, 7414359968614421153}, + {8166814052414482491, 5209260157266028169, 17555696996149558694, 9780166780476833956}, + }, + { + {16029688335186691281, 4244772808651443261, 6450459413414527821, 695875191412722741}, + {11104054226249884864, 146461617619843327, 17480214580411209436, 11285418463967817315}, + }, + { + {4922928863857449168, 7226901725606965824, 7568276305032368752, 6253457805758596797}, + {14345040877576203078, 1718759302498746946, 3544444746772280646, 17880302727399449566}, + }, + { + {10693864548794383214, 736148233485985101, 5241869061152863453, 7166954323782542739}, + {16861482585847848251, 11483636939866570861, 5950529069765100144, 700887039653157350}, + }, + { + {3906969739692830848, 5546431121705298614, 10491799900914853406, 5871175286230239238}, + {2851574662174517162, 5511397532379144624, 17409985391224790540, 319012646822749823}, + }, + { + {15269778527761027251, 16471737837294177924, 8830398856035267114, 8206807757132984992}, + {1421214226977370752, 14233751335943482739, 9668238787333455452, 8700964319357541954}, + }, + }, + { + { + {16477698187919702699, 2757160833848759781, 5976267476122243443, 7375951277779829055}, + {6525111513935493528, 9969722922172879681, 12582700753056539952, 3861958159147836631}, + }, + { + {6001837395299394988, 7545846298204709215, 6662102781970969966, 12696054550672669874}, + {7436995610194789060, 9042605089262227561, 11621508125069628605, 7289479057360149973}, + }, + { + {9447061002880879247, 14620964119546151815, 12310553083192998735, 15923694411935453454}, + {7392925129127637753, 14135139889986895975, 12760571438361221130, 17000514617803354735}, + }, + { + {15555649500689005370, 7857014165815014600, 4664069234996337119, 8058230521837307501}, + {18090421626009183450, 9278179697462444898, 17138879353097908770, 18285223269807746171}, + }, + { + {6099842409325199202, 2732701612070195412, 18229871238556385053, 10275023622778520796}, + {5986266691884320152, 9796109565274465130, 8132405984970989382, 4521405733027618902}, + }, + { + {7427469853953577123, 9581104712231034671, 1702722776800247878, 12656779221313783543}, + {17977155285174544822, 7208039998659519604, 16978428797146101290, 4487821481774245164}, + }, + { + {8040999562333134211, 6854344540855006667, 2481534773419348751, 15571316619985340537}, + {10089854957334316687, 4775911690791701632, 15619815835608539594, 336338508421162031}, + }, + { + {12741225973381753432, 5461579923265799106, 4348015554411389960, 14970536173310927872}, + {11568371199139699619, 11748662751675667230, 15495664823061891700, 670495577617908409}, + }, + { + {6065163107315563308, 10179715614080542168, 15046885616273736618, 3965401047645186422}, + {7013093813183571821, 6087826007582017410, 14469686436525543908, 9620661780899615891}, + }, + { + {4469547109588409455, 11124190799085603197, 7471495874998642156, 14754586999614006506}, + {88849924092797594, 3031352551776027825, 15701321561580429717, 783416358537121491}, + }, + { + {16899538363784443428, 1224176808212436099, 8044883358999763192, 8119246882922976226}, + {1602185320898819533, 7795133078900055750, 15379182653822915088, 11717676755990779936}, + }, + { + {9865772269601493999, 7325690007062740244, 18437964667185475354, 9546360111100619473}, + {6266116854923135821, 295905071295541234, 16037468634731642095, 16602609756229843150}, + }, + { + {9871952371310035629, 16929106233175362415, 3445554197529258762, 1598752868683659684}, + {10123732080482057842, 2393692486932623922, 2380673894473467164, 14578017559552626408}, + }, + { + {16688239163561330036, 11170579336923472003, 3699145675255553709, 3266133724446548264}, + {13646430870088709566, 9802235972068927845, 4016187574117121322, 8646347483626678378}, + }, + { + {3473609455134319994, 8666646689587058890, 10588670228528079578, 1636194164122827747}, + {10443498896203771168, 1711092164750178258, 3641509682909832777, 11037852869436666140}, + }, + }, + { + { + {15254713655124736464, 6283719686609422435, 5417864180357938798, 14010638809605797246}, + {10873690600705871523, 15014239467130590294, 15765460219545280655, 6048061577845125750}, + }, + { + {12012729503226546642, 4811951115754240681, 2652621264600062520, 1108958391967017223}, + {2508980100759035797, 9023233544151778447, 11183557587641545146, 10726727280840759519}, + }, + { + {396296174223428093, 16763788748988621834, 10606803701784640909, 2399987183687936561}, + {3641562114746393614, 8536687357022564742, 14532545286961725758, 14658331097531946901}, + }, + { + {2386026063595321071, 9144724461940169335, 13121187420621518554, 17351696676224980491}, + {143495028693925520, 4590642171152119027, 8655406817079059692, 10005507077955932112}, + }, + { + {2047964090310465728, 14133690277069748515, 8287749071957055844, 16821270580974431218}, + {10324684883587585565, 9652498187344172497, 2461802306013063247, 15048850312040680643}, + }, + { + {105705035058376953, 7541598459498134635, 6627685529861836787, 5724525771392188178}, + {13865897118300842617, 627652561624109853, 167084371112939132, 14192831153344015422}, + }, + { + {12837696619944805389, 13470316523008526719, 3074966674353053986, 2630814767089382743}, + {13353767941686870870, 11405513520090968568, 3071969598389884693, 8212421686942839224}, + }, + { + {3464453985305889088, 7486900500389940957, 8944303108517222303, 18319933556403836918}, + {6782476025105836770, 12822840946923377510, 2799592944286097404, 8737598030273298051}, + }, + { + {170025682710985810, 13049055489275530431, 1714038719952287416, 8470425667049459662}, + {15692449588624337561, 6306908925988159475, 7292362624201217567, 10084542069209889549}, + }, + { + {5788423445465760069, 7489854375947810149, 2512436350424132958, 18422682564857699600}, + {5177251288327577128, 13879051611542381588, 12430182880452441435, 16367520376757404605}, + }, + { + {1828702178325893477, 504110179554648546, 13285173922848349127, 15811513724231368560}, + {5009291056218383875, 12726125712718222937, 2511326207435121241, 4878070763721166868}, + }, + { + {3151967592390934907, 8745573685636820318, 6591530195811780291, 2269684725432150574}, + {7575618284647930930, 14430170051221190457, 17370623489799706048, 17190167628015666439}, + }, + { + {13971505255871035961, 14447456703883945351, 7749508685925819836, 12281701633335081378}, + {4638096293890044597, 16388439049639616700, 2805317369196495081, 5611057071508020450}, + }, + { + {3416635149605340108, 10996030428276056653, 14121021550848949146, 17748729969482499931}, + {12079053778595035959, 7473419378019222577, 1862205264236631673, 13655366704192015583}, + }, + { + {4817911180954611512, 14468615228783100826, 5900448495927012352, 2522071476550218088}, + {15649024877429766334, 3445298745493942789, 2295617386899137580, 18376023059372246253}, + }, + }, + { + { + {5228416958727036186, 12534300056259911378, 6859045937063682340, 16561718753727911412}, + {9427589074776024847, 4167904055656501509, 10156691045253563236, 17557096561606923049}, + }, + { + {12847261474293104380, 15935635664155479706, 11956861064550631146, 11743590506948225647}, + {15973092866215748716, 8269726904881958353, 15639962392523441528, 15171417818360069012}, + }, + { + {2605212343977737441, 18393471024186189813, 2302707671753008158, 8606549841034095192}, + {3842822953634987820, 3094721493917442423, 6408313759447502937, 13486364200254727287}, + }, + { + {2191808101092881088, 128992526124656216, 738676021426139131, 10157323147642681558}, + {11221959943853120586, 18255489816550713347, 10885231659068427649, 12104397395119665023}, + }, + { + {7707807226411417919, 16609863548699265350, 17639371636697428128, 8755472387723764172}, + {164779854477783265, 9714199241756765614, 3491355372893948450, 17683742455036967163}, + }, + { + {13595758632462338296, 14515163666150177917, 6720823780841221770, 15071435664343609336}, + {9016075014492765983, 16881277609836316886, 6969993988115170067, 15419704786434737070}, + }, + { + {14933348768149415725, 8499210770493553168, 6778840616148281272, 13282837866452012488}, + {12007326272174861053, 11172739862019218274, 15202495365302649711, 8797477675597086120}, + }, + { + {17862558746132168231, 4941846130090682869, 17131557654945008226, 5312800819142473968}, + {5818269467205924209, 13458582047859447022, 2683428091382447153, 12956887954464730664}, + }, + { + {11820752998821943867, 5623379642132478491, 11666807493120740820, 7241997274572162616}, + {17165010508995490690, 1769225877906480182, 3814296306467163522, 1913823003062817434}, + }, + { + {11936813336110488997, 3878433838529606580, 6540053284493149566, 10610279324743393563}, + {14079852809920102066, 9176732841330794388, 14287311909822853963, 7146204303626670196}, + }, + { + {1222343790928490335, 2199405396044383670, 14080919887213592148, 7341303626667347624}, + {11784881532696657518, 17307742911086150556, 6036132721599132043, 12167106497065306941}, + }, + { + {13817073203406999359, 7220729284169210756, 14908407498603601482, 13536224989620701632}, + {1615171540711527931, 2063856048260214664, 10622581435417474559, 16378505765730768032}, + }, + { + {6855676470217754770, 9517149712286624325, 11080380031068971680, 667425509348698033}, + {6136243307299269825, 5326577850303193160, 16120190278345757447, 1982981965726975383}, + }, + { + {15399454106099176868, 3988744407816581672, 3596277710300384050, 15129113714633923498}, + {1554582462382333698, 3164553872715651710, 12729140363982748426, 16366728035709811784}, + }, + { + {11647936211409428873, 14704462653811533865, 10005129575282387925, 1526194796943187368}, + {10906326807488904308, 18256878690674435807, 13093574545395154003, 12352810226542367406}, + }, + }, + { + { + {17055119974261943875, 6266720893662254540, 13102139953381148874, 5249314164321788611}, + {7157525732140787612, 15381277459195914226, 17265025258266710353, 17573500432599548120}, + }, + { + {940679263188661008, 14653357165718140350, 15439920797347843673, 9415587255510557494}, + {18115037054677722678, 8165849408798239027, 17369387099667572407, 17619066457126678815}, + }, + { + {8649149223282317557, 7756351751136698462, 18239772072009739451, 9817506578949224559}, + {18378033667730800420, 16794121140066562876, 5288247581483071333, 12402303517382928119}, + }, + { + {11047138821675365077, 8918121441180891972, 26692501222219426, 15248413052700323978}, + {7305399157133896461, 7065644238942265367, 3949166834387057064, 14178248206708015607}, + }, + { + {2031270890855333638, 16982096442429440651, 16686304398848635900, 5829842366016448839}, + {14111080098472974183, 12565301877743332219, 1685254887702201709, 10638099573980009130}, + }, + { + {9618597135962048429, 4323708363301758294, 1934098864729515110, 12038442338797726450}, + {8373847126955513333, 3300151407444969023, 15888126952439796914, 1426880256839266097}, + }, + { + {6428576619669681259, 7657770350257045071, 17839413659396163406, 4702043961312931605}, + {8200928556018997183, 13282376860743810804, 13005614455417667639, 17419029631791664639}, + }, + { + {69860179712677448, 15464996655458230480, 15095351218136595554, 3792171085643513009}, + {3187131848664503636, 12713332789590787064, 6278731049699775392, 1597379696359884724}, + }, + { + {15673011075664376010, 15519225812231888543, 1336371877669824820, 4354970830277120843}, + {8744720488959125220, 17541792919601146935, 14299260104084112815, 16082554294713598652}, + }, + { + {13540612390708052286, 10213354985487483900, 11366371415587713866, 10334937577432263044}, + {13368390835254255145, 13453645319717588760, 6303196127329783110, 1204334422768264234}, + }, + { + {18221540219239501535, 8536815826205784644, 17328509446048600304, 13923028809228258331}, + {13984621134784540482, 10254983270679630247, 17457131706329229663, 927850905006752032}, + }, + { + {3952205381894147962, 11371446109407143937, 7231851263356642380, 11612512368538303138}, + {5227214975837085115, 10737565048439707166, 6333629542995218640, 12386725921557807638}, + }, + { + {3772067962000745672, 4436468403847408320, 10612599615182677580, 13738755391074136269}, + {13665557786177426407, 14568219921857752, 2691062926825113708, 14666515738377567975}, + }, + { + {5392936538333570234, 10526292103645946001, 14132494129869423619, 7207059073717065545}, + {283545293669631007, 15845011600683983526, 5081287846871250008, 17931854980704528162}, + }, + { + {8364400939527235175, 7959571573625351093, 15849019287994534535, 6982609389731776566}, + {6287382484291579264, 16496145344132275167, 12062306229709713775, 312030175316686885}, + }, + }, + { + { + {17224650011872599657, 11430188086182976152, 12892063618843720029, 5912993124689510433}, + {7069617917494051681, 1298012103142698333, 7943359430865057535, 9329776843721719539}, + }, + { + {9464085603669036454, 7848014338005901108, 2368914226155404065, 11578416111848517850}, + {6323647866244499941, 14399589996703947996, 2824522520842155768, 391310842153371124}, + }, + { + {9948650801233133770, 5836115460383443197, 11404170696974449207, 4791020823967734476}, + {423024247809958592, 11251668387880260801, 5562546584223492723, 578572156618131794}, + }, + { + {13988854693674964723, 10817154032069031941, 3171651998645961547, 5518712225783687705}, + {14706905091132091970, 13960758460934966876, 12141035142079693145, 3149939820435101269}, + }, + { + {2505301881938098126, 9962323478923652140, 9312199523950444342, 12957822502673689705}, + {8060810607849163143, 737408553843844193, 8143568733429881786, 18003168270780769476}, + }, + { + {4460927228453411137, 16058422703785787527, 8016770980039986075, 11450941100964860520}, + {2742597710491507274, 16940752978671801273, 5897441526901650840, 5926672707007682446}, + }, + { + {5772778048593061508, 15424756817708323928, 11842041259277183807, 17669952685051160523}, + {5405007811515938363, 4415223809135251038, 2223192286456742546, 15742105795795272774}, + }, + { + {11809342655313500273, 16822704101813284237, 13097372075606737923, 5463281428453250615}, + {11967866991673525562, 6828790575157689223, 12568831962097805646, 8385980093725157349}, + }, + { + {8090324765778815982, 15997433100218204643, 7771766025433829989, 914551143312324786}, + {4640358803642182649, 17428148208737756210, 12144967737399770998, 15075125743380741412}, + }, + { + {5954807828598238451, 3186352433639831389, 333598278340882889, 8647732331490039308}, + {3706589107409903019, 7338319463305947507, 3829684452513478938, 8551967121356509963}, + }, + { + {16753777599759754869, 12028154198579512953, 7911616552276519044, 789841268294170739}, + {8228995103825761982, 14293958931719060336, 2778055819582565008, 1399082948378499882}, + }, + { + {12492565198527218900, 17337285577296730202, 15088344513573802417, 4272568906387671217}, + {2365541522321646412, 678395397666822608, 437334842774934301, 13443327606166079837}, + }, + { + {1266313952277763194, 11470850617813390661, 10426389264474337810, 2996447663006153747}, + {15218295359022152122, 14634539952819815592, 1775270187047190460, 2942637199921677956}, + }, + { + {4952377176677649521, 7473631065005310719, 7363684030854414233, 12556891399998587233}, + {2190850394642244911, 5458637782288631421, 270926994697866523, 5528436328062366401}, + }, + { + {9497175173535366966, 25345745857275253, 5047829133239508177, 5340238103822773099}, + {3133339556064328840, 666970525709876149, 15575505473500291502, 12769675806855640654}, + }, + }, + { + { + {7669790431656261769, 2776517632462593286, 11694025667665633506, 9533794089008895277}, + {2895611631120558023, 11551410655448788956, 10026541900772270925, 6243136875017000843}, + }, + { + {9434484992529186384, 16435748047660609525, 16190660694150989986, 7083965852434071085}, + {4216306437741910756, 2698742177539497614, 5199793642504009017, 17298424769819019160}, + }, + { + {4041169394784902550, 5699517344009382913, 5306272267462320559, 15846674482556330025}, + {2606351264228884283, 4162585980422107281, 3715151019132039005, 6607223447043258693}, + }, + { + {8168579295855409503, 16727569921530031841, 6182114460261837773, 8940603165471931374}, + {6081572078077526926, 5890840443923124563, 11215305828294759727, 2875117534361804712}, + }, + { + {9045974983664041829, 905036705033699463, 6962033946652121779, 3027264198782618401}, + {13786415307358010100, 3643342525745067473, 13641958783381681886, 15675065537779359584}, + }, + { + {7507377696839752642, 1061259379811757443, 10276590160392917813, 6889137095037822679}, + {16373913505782725550, 12287733095803524526, 5695917172259210496, 6360958736925918808}, + }, + { + {7459854586357006968, 702429387211615855, 8231296036461604410, 628323703857882004}, + {1059802628602873385, 12517208225099517507, 2368172548334856593, 4792344750094708709}, + }, + { + {18352334786472886037, 7096021570596476676, 17045407505128867173, 2467670847537319400}, + {2225663888244226889, 1876713214939672742, 5329943993157142620, 12168650975912182188}, + }, + { + {6639850268372381409, 2284514769224558945, 15390110317831975716, 13933785559694229008}, + {12787641603764341997, 793886210532292741, 3222136169196008839, 11104892506868626444}, + }, + { + {12660547967989039787, 2109392063597767300, 9889743271997754037, 11803327596624324036}, + {6940409327849314286, 1466399127363116843, 2572333022681966275, 4216097356402537802}, + }, + { + {16858757460581672909, 5838407119753001493, 4453405435911954669, 2828665451507432751}, + {13657966632733241760, 6875986784381874300, 2390233934255482553, 17386653779125555159}, + }, + { + {2976756344404126744, 17032556609402836559, 16348907464011574182, 2196781021202618892}, + {8270822867494340805, 4738372358350764889, 6088256422707334932, 17121369334507507505}, + }, + { + {2081729301541563384, 5577186154173396778, 1865152567701500436, 1422284589642218069}, + {2489023909725140903, 276494395149046869, 17420927169263487236, 8292343688801608074}, + }, + { + {7819174654675104600, 12778055482430336726, 14615848543490171611, 17498415175263742825}, + {4785899184222234034, 5227136636239697699, 1570704808469050246, 2858953380860123257}, + }, + { + {4323577007857413306, 10524228743339400397, 5418808897687027557, 5939367271366264075}, + {3569359126353670574, 12961495213964770607, 8906990808988099905, 261084295374207271}, + }, + }, + { + { + {14408045416865494124, 2442199381796557002, 10475326303775862953, 13637445125954159957}, + {3778313603630758744, 9247460369874272772, 17572237597883145087, 11338350096360776602}, + }, + { + {4336697789732072031, 16054848662858822197, 17934449813415035557, 14518380622432694666}, + {14100582434152190048, 6262866632984449325, 18069160441815400774, 9798342103009260692}, + }, + { + {17244020587062193870, 7625407515295016845, 12692919397126044801, 739129074276464779}, + {977900962655641355, 1516169712468716336, 16875961107875019625, 1582931498538195018}, + }, + { + {687104890149081183, 1938816743979859301, 11342071981175913904, 4270322127259097184}, + {4964776270155503160, 17849333582861534767, 15814479527332819692, 8083943565773123408}, + }, + { + {7977186743666958490, 3126199553548085949, 16879636338977836444, 16647578924708995556}, + {5526017172393528596, 11328754652335568585, 8095074058116436597, 14648690727521713743}, + }, + { + {18335678403814425235, 13764304056086998207, 18139296224460762074, 17620705673387523052}, + {16059975647897396183, 14392541906869470064, 13641721532745636092, 6122032872822720831}, + }, + { + {13983401929934353021, 13860725962778449344, 11760533704789481157, 12566657951327299627}, + {14697122142882732522, 1606632877136342124, 7872716135734366961, 18220536079227927821}, + }, + { + {3986890035154628803, 15316660330065019741, 11560940574529263780, 12576851520091035878}, + {10883944418224886092, 9908329441525486205, 11238684990962507809, 12900626758810151662}, + }, + { + {2629393050548942288, 6363222898077806203, 18404650886731368903, 2691451856029551156}, + {5104932743043229112, 1302939624985069019, 11820239270922660661, 16228045717328023331}, + }, + { + {778457530134061801, 4290661013056586404, 12033745869654330486, 17833837257536520292}, + {950548111600899172, 16026254932420015523, 14620989142158250051, 8236598933984161995}, + }, + { + {8828068000936861634, 10901971915827198521, 15635295283164640480, 352740455954411610}, + {4853015383138960329, 2945696874639059776, 7204307993540375148, 11980890732241054979}, + }, + { + {4077800412543228484, 7173833470188867493, 4604439809988262876, 8090706047559948234}, + {6117166546062912279, 15748537214854486946, 16719594636199001564, 563850925691991999}, + }, + { + {4802884399593912281, 13437020732272033050, 12197788481695720547, 2162699662292229581}, + {4193517889478995518, 8610646873096992408, 9485787089338760040, 12392145097158647056}, + }, + { + {18079795516810465755, 15723042000668265475, 12488322519570427659, 14012836221417650412}, + {6534900133691249330, 8115921632235353076, 4093907116172233459, 16784728000548766561}, + }, + { + {6262200118048820167, 12719453838344002789, 5526427573572313315, 8520226123932607126}, + {3618116539863181413, 14020033065434801713, 15675496263723836857, 11987954535452978647}, + }, + }, + { + { + {10847249691051757241, 13332329214721571156, 12457628412284474075, 17044657510482764070}, + {5218221397478351943, 6922630493693541156, 6207927102810766143, 5644846665334649748}, + }, + { + {6506371904134856034, 9541373683805144018, 3149037850125132851, 7111810601994573897}, + {16732445693192247884, 4994069681898274622, 7223719243730104348, 5649174084086150712}, + }, + { + {16562962997045986629, 1977585352264948582, 15588655103333244279, 253344970359156714}, + {12939363813291366775, 12548224526376199974, 14450582788883748364, 5869541533939881460}, + }, + { + {13970586842647892965, 3680317572634289692, 3416494470839852757, 8341497967750607131}, + {5522860734580749818, 6847292760525096386, 9317394708872196559, 8522252330730808934}, + }, + { + {6838341670149165895, 12326189699069923388, 9258908232339348843, 17297038041466207989}, + {5242182985453021593, 9648294165629935142, 9715128265517308395, 2662662536493743894}, + }, + { + {6790869670806738567, 4499989093713728199, 17496748050437205626, 7194829324969293638}, + {18432532588985091708, 12041300075343806904, 7788543067151959941, 13703334460383638224}, + }, + { + {5996381448168274884, 8108757135223610234, 8067369725584584297, 7184925262427750366}, + {8199341143188441284, 13031376443169557016, 16036606349050125404, 11958720833222295864}, + }, + { + {9293668142017263584, 17134656749295164870, 5879480323258506465, 4788695233340705697}, + {17809277710857366810, 15157733645094688870, 14143869691462709080, 3162286338158090229}, + }, + { + {16056959590901591813, 1082823161154599460, 10221040439441372421, 18283403891485112294}, + {17582486701671091218, 6489397700174053547, 3952499348250646760, 4381145145005361247}, + }, + { + {464321249842430028, 11444362575253049653, 2734975360475017776, 4746579078625212558}, + {11326126526565916100, 7840007639237722362, 7545779893877671555, 8952053274372957788}, + }, + { + {9171324502111757965, 11245577625425383295, 15294815109909975990, 12306264653913762086}, + {5906268309303228662, 2685370982867857233, 5470203265560800284, 1354105134944127233}, + }, + { + {10610818607308010986, 1017341076592473937, 13259969743043862138, 1850907007366751943}, + {7689302552902672401, 15375957693502270090, 13877050204486881614, 16441247744335371320}, + }, + { + {18161720198110725057, 14887135440336057963, 6790952723850964648, 15120775513153544155}, + {11797493458812299470, 9090758778610315656, 605835259544633945, 14755333155432393992}, + }, + { + {14967102006962978091, 4301508725220174920, 11299977101982031802, 14410789725331022027}, + {17005709003661351591, 9843840931527318478, 11917612896070173894, 12007179364072802553}, + }, + { + {15913542135925395264, 2830138374220921671, 6395020779026969444, 1239443258852925290}, + {4519359001030231260, 9606729174209623750, 14291346135557028396, 16179513817501558495}, + }, + }, + { + { + {10223936123327786454, 2321887803300626936, 13607747528117965743, 10456421630388400123}, + {3266519591187534953, 1053691207967834494, 7151443045753788549, 18124688636664828399}, + }, + { + {6946488664257064464, 9775328903143754150, 58700362449753229, 7901817271072273406}, + {5074738678159003249, 18397239731906005785, 15911102965988125888, 9277654580204145348}, + }, + { + {1874700306906525099, 7337351570334852732, 7954195906114335343, 17230226427261850070}, + {5181329498860909261, 107167242193237170, 4364856176182710332, 14611171841443342914}, + }, + { + {10990327814895720476, 16588412771027628390, 2850177278998422188, 11569813740328484871}, + {3922148781422941186, 3581659216490446242, 3646872304052351376, 10887870617200051198}, + }, + { + {8175121141368087217, 15079393830876652065, 16766987879267543828, 10582796406546815217}, + {16832256009371376870, 10042650470778064892, 17867163453935683780, 7123418345572641116}, + }, + { + {1782651072016504775, 11033882508408412333, 11105300284232190625, 3276372405089292929}, + {6399472468041061588, 15319690780388315076, 4928530863063375966, 11596222198340277418}, + }, + { + {5452424185619067445, 12050433097586021281, 15018766900844679217, 273234254926088220}, + {15426383635547379531, 5213762666043737626, 2829185842069118470, 3230799283770935127}, + }, + { + {280030342772428106, 17354882606189694746, 17455445295460080284, 18076709382926018941}, + {9895982528034548913, 13681172423928175330, 1656433131309057012, 11935757350437721114}, + }, + { + {14437472586336929440, 17387041914242263390, 14861577074379746687, 5146556788377906297}, + {13036814755814090195, 15108836859245573802, 1667563994642521213, 14722845469958372258}, + }, + { + {7781061995240980266, 2066078418484154391, 4089376589847114892, 2434843609506038666}, + {18376509832460312721, 7187709121160627756, 2455436656049651823, 14419116837518875372}, + }, + { + {1270185079976403265, 9214436628411717184, 15450450827683432913, 2880014804806096082}, + {15448799931519826757, 10080240282127928735, 10673974088219619287, 12998944469117087518}, + }, + { + {18028691745165748687, 8931519595829275195, 18379893031942930865, 12120980098075498008}, + {9596371470855895261, 4133427878071274570, 13159312399982591699, 1639865074052258019}, + }, + { + {1661696187746428348, 2656198437014978712, 13769477291975851694, 12512848714492869444}, + {5980926616932344693, 15821983893144953005, 5816015630031200526, 15887565799959254415}, + }, + { + {16463929919291729278, 14920112063826664828, 10056471508435050704, 10696267144984026763}, + {12049530292963090991, 11926086636123189182, 9464890378472966538, 9719194510330239601}, + }, + { + {18110249193861022779, 5612784685592189906, 11360454032996393150, 6795401682138043705}, + {1961398978248902107, 8999847457729547905, 8941741619641401180, 6086938661427918241}, + }, + }, + { + { + {1119490156854665483, 16772836556735128526, 8607715508817325509, 9931017263385440911}, + {8799481055779587022, 11740562709785257943, 1956849872282864970, 595288629437737005}, + }, + { + {11601570184515356415, 11247678357869162156, 8415095559389686315, 9625816053586466047}, + {11807876143163335372, 15690209134241397733, 8684637224468015605, 15974968144193406020}, + }, + { + {6498861108824484382, 4670555282769381189, 6606014320886832914, 17078765892830617318}, + {546267528591230105, 17808649363082080722, 3219358059129920687, 9180845247506322192}, + }, + { + {11275984449259340674, 14922638629881602958, 17186426309348732477, 2094500549052461127}, + {1245672419927595636, 7529921141299797945, 3181089597449057707, 7749529014968942143}, + }, + { + {11277133910568934671, 4278895672933635880, 5062049475469993812, 2827897582327968966}, + {2992831031801695571, 13244636528396736375, 11509629662092358067, 9385849226639579800}, + }, + { + {8454236707620433029, 10192313737667573051, 18232259474515025711, 6196538652828521245}, + {6326999652188467228, 7611130140249634596, 5729331023083628955, 9386297316005425714}, + }, + { + {7621274909358193632, 3619625095597194913, 18038386254997645285, 17262892689028255302}, + {17953989125460428814, 4571031913557658215, 12218524221515562809, 12016327352942264220}, + }, + { + {12842581296013847382, 7845624487558348664, 8747439372999364825, 849305823897878133}, + {2217292264321907974, 8173534404179332054, 3588643190593022889, 12047811416592660080}, + }, + { + {8121746263843271081, 10363835147942471345, 312023379108980148, 17191823034761670562}, + {315776409136454719, 8322002171533871918, 659256727451485128, 6073539214057006838}, + }, + { + {5999134638957620752, 14196265207258829507, 5400793612736232063, 16259338359738368573}, + {11179852704740695306, 3486799782309774463, 3060529319750906379, 3540275797284687957}, + }, + { + {5485176043812882513, 10727553589889164848, 5617457077214333092, 15937493816713568462}, + {6287330459840726949, 5451240171054977850, 3524414944972920777, 8740440597273129486}, + }, + { + {6959527445237219799, 17170778245769606301, 807762173031474321, 9151445233487017286}, + {15103411489939446333, 7976669669591851659, 14824323986579638641, 1535817133122800221}, + }, + { + {13993486080187419934, 14882121651768660644, 7947881871819932407, 1364312030151957949}, + {10673187305202558690, 15038997055055408315, 9268330880459316485, 4319340556575124142}, + }, + { + {12846922591360496097, 15518450931549829779, 3843880753372237176, 11741559986398913430}, + {16974382348775305594, 7085384294841794242, 10278478682851578175, 16997904984485898637}, + }, + { + {13670930062027115328, 9912297966339314023, 17061419147322177635, 6220676237879734303}, + {12723388668517709225, 14967294924815531226, 7286002704046609276, 2105494380036834916}, + }, + }, + { + { + {17955247196574331290, 285928599571507431, 11902987704297070981, 2841167725097799100}, + {9281167410796848363, 16444340476026142274, 3423202423051178709, 9101021305726472246}, + }, + { + {8869273893561412239, 10349812081309865197, 8913824872487209090, 3148808685596180274}, + {530908416884501807, 10284103744075805979, 13606889938905754722, 2418062398586758364}, + }, + { + {2298603653884322501, 601221199968240092, 1285112712738261659, 13882709760355308533}, + {13563254433762438170, 13447718334658435053, 13493687958886238103, 11032778298151679283}, + }, + { + {8626760324117733843, 16403951745962159364, 5837394731212322914, 6847167719031297053}, + {2888142337636247281, 3409818743436360750, 1677113113408664401, 1222157560539217476}, + }, + { + {2294668553308381923, 17165287249067859297, 9897724011823072967, 17409851874231284314}, + {13888575318617508639, 12092766090379658603, 8412268183255186961, 8046572777745318483}, + }, + { + {13178439025428734594, 16388038968589028071, 16165750006742628176, 17903639397633243161}, + {9560319088110737392, 7888974492854359310, 16116323630343158496, 10177829649622711030}, + }, + { + {2378363646789710539, 494954399989334038, 6915496914984330558, 757197055392642378}, + {9097171378505823650, 12104288338329241488, 1905673690814481722, 13011078677095066032}, + }, + { + {12712274459771886808, 15748114764509451764, 1994630377849062253, 564390855806287868}, + {135493276425567450, 4305883520257541088, 4842008929542073044, 7035106970720249617}, + }, + { + {4772079965696324995, 15925041062593990538, 2818172089014580505, 11304215074611546986}, + {10130691823118346040, 11796228810049908587, 9262801389703476249, 6629344122525229781}, + }, + { + {11045983914861167112, 14106148195606833916, 4442596873181225087, 15627975325288846806}, + {8173496855557146242, 6061080385918934423, 5233260187121969538, 17554093556474728494}, + }, + { + {12122792368758575262, 810814789452398299, 6387727669765211854, 3304731719391402237}, + {15296845834923103160, 3685348582131767195, 12636335057478947340, 16971253767099552987}, + }, + { + {12345454807632743424, 11546569651702761483, 8873100774001529421, 7001975923028025552}, + {8129283832066039281, 18147888225504425296, 3510907297028745651, 897602195837260824}, + }, + { + {17896345382362222994, 2167374959533815311, 5029128091600127895, 1770543276160593316}, + {17234124146043512942, 5338191548265818047, 15676046602975694398, 1943153641089805200}, + }, + { + {11084819495273800718, 12966507689731825252, 15026437832429189138, 2506312683689776139}, + {7417463323869895004, 9819555221238697390, 1250200244896601539, 1394555910521460172}, + }, + { + {2221512141494043286, 9203854585477888176, 12171379127551511504, 10667358469120985695}, + {3795093165005123272, 6129005969593025264, 8738204659003189419, 5273583671698415302}, + }, + }, + { + { + {16549155412115374305, 75977962737081600, 8870825488941031605, 7403557657089993256}, + {5825394234709429518, 11978746413791918409, 1876293130790608838, 9416631623519692610}, + }, + { + {12346821858361333862, 6352722970730511156, 9920942104315084988, 10492373916708072181}, + {11163323626947992791, 17035282992056675772, 835685192553490421, 12792459312570503983}, + }, + { + {10447922451077327640, 1515090998837129975, 13498807582085718212, 1212623301098019779}, + {11573518650162536086, 4823461685803772444, 7289704908733783271, 13167881392748327839}, + }, + { + {16959954449957105311, 11051594981465026138, 16062472412226411858, 1976004115345602080}, + {3630495248560019222, 12698191555196404138, 10107923614229901155, 1597725222698864118}, + }, + { + {3416019089997140849, 3011417601086561495, 6275242351124667286, 14197557183081060761}, + {5633711018871057458, 9723496411345030748, 13910057756335530832, 7285051335492395815}, + }, + { + {16774605620279328247, 10223834398868957807, 15781733027568799739, 2607095622729296315}, + {16499590296954181006, 7576646116121533069, 16638313875339315529, 14296194207652471696}, + }, + { + {12874411821611501068, 1998417862388106640, 13882642435422318946, 5791129521978463837}, + {7512934139125398199, 6966283273373526248, 5475728301311080129, 13542211842758381589}, + }, + { + {7798993150530415596, 3288770257171840452, 13373286069558329631, 9784279046496345014}, + {15725032660238528813, 16038931923358478835, 6921788930154218900, 6093507035435214187}, + }, + { + {12194839527972802101, 8376199250979271449, 9055995864116790217, 8125030124567662718}, + {1070812422878398727, 3950906148308170707, 10121516919638719072, 813471384549762068}, + }, + { + {7610605259962047827, 14617655900985224117, 16089669078196617440, 10594009761533811214}, + {3425971360520359121, 1245021768718221594, 16690372892586114152, 9933179766195044175}, + }, + { + {15142732720676276463, 17435583143726694663, 6030257647680338377, 243683009289621849}, + {3064238900429394982, 7655019927497549159, 4484400084400458429, 11650860345018651068}, + }, + { + {16203650576183697977, 17614744533772112337, 1119292890050870301, 4574885263986729787}, + {8108207498737924504, 9708434439316056191, 10676823369888368482, 1078311554675991883}, + }, + { + {6876202174636220158, 18057502510666060150, 7821730895845187783, 8882321799602877790}, + {16220624224336230256, 15562800387021280583, 3043825293109091520, 697130162105054983}, + }, + { + {5394549491776704087, 14795348078061113966, 14206080764200897220, 4623073019242398493}, + {5850602047109930316, 13783531993760979209, 14764346975698048641, 8951680172224205890}, + }, + { + {7302725075484262769, 12572584665857403749, 6499691362933905099, 14476353114356185371}, + {7381716148644532401, 1573798302334388880, 8128390307766282880, 14547454176248589604}, + }, + }, + { + { + {4477325369345373420, 299141931133875776, 6787652129916359301, 2498016036564260464}, + {13342319943892943548, 11124287719737492205, 2456333599771808442, 5084719026388755304}, + }, + { + {12246932755942887931, 10842213418139067847, 1827392608284960926, 6961756951208563550}, + {14626966634382828071, 12653808277900379805, 3359368990539585596, 1190255644328095727}, + }, + { + {14845756090430871381, 1260135108359348096, 18373249503604334230, 14931345532671487262}, + {8304897926217252744, 16639705302116302354, 14578633917159176703, 5624357498623418462}, + }, + { + {10836955050615624183, 6228108794259714192, 3769609579318360527, 1481673673659326756}, + {301329772189110029, 3574710782304999603, 3037244905687722509, 14442941761397229485}, + }, + { + {3863379967423475252, 4598414140150397553, 13498347034161095546, 5995458763090398343}, + {8994138995797612256, 1053878477247308872, 16525881906724873538, 16597989933510424042}, + }, + { + {18195618552940791509, 12801347400921689158, 13372055618013067129, 14929951832730936581}, + {2563109394536979589, 3392102243539970867, 2978145866937578695, 15809561751101461921}, + }, + { + {6470844231261685519, 4860920111547376221, 6133864928365904793, 8914566156785557227}, + {8258394874597607714, 4464810914649217913, 120457844518757378, 18209291810039348360}, + }, + { + {7739110373965523311, 11019153332996240080, 7346010155518751797, 14853737521111213548}, + {2542883237207113209, 11015136828834421504, 1998601666328316353, 1540417751495800469}, + }, + { + {3376092179741497360, 12221254335784366861, 5282973200516004163, 11372960528472533628}, + {8188139842572259074, 3946305224334575645, 16643338862665650950, 5859492058050333909}, + }, + { + {14916042081488114271, 3303190861468284762, 14234546272335492538, 5776190344932209905}, + {16339988209459724195, 10022514953301624769, 7878363685856556300, 3127365206552843780}, + }, + { + {8340102858481562978, 5401806343794775245, 12619159636229742566, 16221085737347795155}, + {1241298364136442056, 9142635103215118982, 14403222699038355211, 12145678822325215894}, + }, + { + {599034134015360884, 11263317530774995092, 6667501365379084069, 9844276013103312691}, + {7566306886180438990, 13702768345615509363, 12525031963170717968, 8463786212988210464}, + }, + { + {7279390679700007004, 10579602100702377479, 4366146547587324748, 6962092370680728424}, + {16372420580520124739, 4597019194685908384, 13217149760366044828, 7222487257194391332}, + }, + { + {8454830421421057736, 4100731209937375984, 18348214289895908213, 6778376865226169852}, + {12945227893790929647, 1818657910008686277, 3629900123705314093, 2861658388952811590}, + }, + { + {15882969890737930334, 5849157078791136995, 10068103243390577755, 13131421240079433547}, + {10404642120419399290, 8199866428750316037, 1032443962738597455, 15582122438927179496}, + }, + }, + { + { + {6390361653475754940, 1093882175267357438, 3784079074949811167, 17343872969822169769}, + {3359715652121662979, 16808529787251986583, 5169730697018536870, 52766949850965558}, + }, + { + {13147212495082910072, 5628914243538540648, 439989514095330941, 7620472329041817834}, + {4272251824771633288, 16564977601507013119, 5441117136715882317, 5622571730905974389}, + }, + { + {4207421531032215145, 7924589143024019458, 5496622772676523695, 7061817399179278712}, + {7371689806847905735, 8282663810521090335, 11422487361383982601, 6397294642072086677}, + }, + { + {960381383357168877, 16774709963697143275, 17896181076874992240, 1150415168189819777}, + {5498481130530161530, 6895900060791069290, 2079514944189747822, 3428689507902936354}, + }, + { + {12056920178557394302, 5131253251712581899, 16251877995882633963, 10883064494054484051}, + {9473274815269607947, 8874308005470196739, 4412709653190846630, 16469366225886156991}, + }, + { + {3547198835521135552, 9940690805769919242, 15170549880149605690, 10701681269101530298}, + {5914809102954412895, 15790219349994701461, 13664049285300230863, 5735249081148743651}, + }, + { + {14753645881295168970, 9410794713982813264, 13485977523338061503, 14267793994973767571}, + {15813187206361118954, 16449603969001878152, 17705410933007144731, 10960511750491378082}, + }, + { + {4669722990542640772, 10017368027073540045, 13392819319228640800, 1070815632453829996}, + {7274130058405640448, 4460835865761538026, 15283885107956150892, 5815884817303156137}, + }, + { + {3469614802230980914, 18060080625283048965, 580464295809221798, 3338153928139206412}, + {9845192339392693455, 13250323899168115720, 11058696855422647818, 9665232062806155902}, + }, + { + {14461336556325939926, 16946363864290460645, 17546878353664479567, 17949437676666656135}, + {7932367178689988878, 4806368097560008659, 3460529608269790679, 6065321700046177254}, + }, + { + {16883816924971606835, 5486714189826473375, 15204267662844332028, 17199232837602035696}, + {15958749676770074119, 5540664038667498053, 15914281753951743318, 12225053486711127081}, + }, + { + {15346266095840263783, 14129675453960658911, 1781465630073142581, 12398710533895277470}, + {17697074063253841985, 13826156613321578228, 8855030685964401164, 3749659313217692983}, + }, + { + {14888039192306165275, 11233459160096048886, 709252573146299872, 17614748022803380926}, + {10853790173866038588, 2988411430602910678, 1343284586410250367, 4491892393582674365}, + }, + { + {5653853395031137185, 11847098886335071270, 15046954358935848863, 490763079643421287}, + {3113500211585712650, 15997550469331041114, 5281575885072775975, 2887311255648554506}, + }, + { + {5376335754670737023, 13164671289498247151, 6846569847526260467, 5496656304894178122}, + {2009132493403453913, 17250524577747091030, 2315376314333653245, 142024984008484689}, + }, + }, + { + { + {7237168574323016859, 17908810107504968137, 16225708127838178121, 11127095986977103648}, + {9346291308317410251, 7381283458277047010, 15168602815371846943, 9193719743691734294}, + }, + { + {9607254959726458411, 16837156817186931862, 16178143308706847393, 10970721795101931539}, + {10840376278605273092, 8298765077094727469, 15520543037910966843, 11484620381947762562}, + }, + { + {17395070963094117711, 7608132718922490881, 6531178971071758016, 1302814667007331361}, + {4002629363862769670, 14649492495298089937, 6868174210142585697, 15456170652716048683}, + }, + { + {3688308493559609536, 5123828159813683938, 6245436817220183971, 13062234263274605325}, + {1313395302496832996, 4961840797708687855, 4990192311341859196, 5283131006216350959}, + }, + { + {16952735659396950704, 1249482796824289329, 17859504101404809981, 13260403650830168625}, + {1583343855370236084, 11389120333403185826, 13676599385745755008, 5066667130137739346}, + }, + { + {4799264864906918301, 18347145714884655971, 17034125441088681346, 11828378178487279470}, + {1759038296522081901, 9582407833575609381, 4195817009050503354, 12618256395967210055}, + }, + { + {6486755100213398364, 5270923715575268322, 9268255346880651103, 3147724493117082267}, + {16710318779269985633, 1240462642985509644, 2400811796254219369, 13670743068809614358}, + }, + { + {11437779990773246594, 13609113239383378152, 31268927496646090, 11618772705165035208}, + {3078024460365036167, 12138983306908962712, 4779157919015181380, 11901698850260672002}, + }, + { + {14642787507945832432, 16258081639927585935, 2560321462542164242, 16286882196975458174}, + {4328159372518768969, 14313553865397841147, 13769372656320240568, 8950675126435331579}, + }, + { + {1309709344837422378, 18403288028608342631, 17102350491414677993, 1133523394849437315}, + {12526496222782003755, 5447309058259018864, 17311120581405946631, 3760058661125144368}, + }, + { + {17891474172606596407, 320094264574086461, 93927075222964142, 14355817838636249140}, + {1777882427773785068, 8237021421587560510, 11520559469641852991, 10567910693910023157}, + }, + { + {9164300764173563614, 12322279811717869943, 2768902015676238485, 7761799112151133995}, + {5740162933856370894, 8043946608495226840, 8923704438836381869, 15189322655373943849}, + }, + { + {12046275966378825708, 5909386969214935556, 1201990704907881028, 12128549009950617306}, + {10773478878317625320, 4554854625564648958, 14029736945871573056, 1353247251064221090}, + }, + { + {11909123603272307101, 5517949035179831783, 3295386484950432959, 5605137795524476293}, + {10718654547602473221, 4984952409581272095, 883267724006996723, 17328431094026829348}, + }, + { + {13671210467347025770, 9980617617519781731, 8339868735163579231, 2150724314757661915}, + {8571153021065445899, 9146903697769397191, 9122246102814640373, 7744779513085605450}, + }, + }, + { + { + {9508384588323002196, 4786531415304518048, 2690306308552249535, 12208815515689370850}, + {5145548243685871201, 1536915039528215765, 709289946127949333, 7152734178531880864}, + }, + { + {9627905753364576437, 12776456422166281355, 2851899644189834214, 16998174196920379994}, + {9001602524188761177, 8960294999163663712, 6580949973363012183, 7568306074815116797}, + }, + { + {7686633626025788546, 8110394872630496906, 8482210436161892079, 16882855163559885891}, + {1154081680627148904, 12804224766760790394, 1850455828762691082, 14191115350906359627}, + }, + { + {13345381996769253014, 6278048669175242345, 15990349685835870151, 16358261962292186792}, + {8505261070637963021, 9396725065098564446, 15331953351049782155, 16194796339208321205}, + }, + { + {15505898598362934929, 16825210854979603981, 4697782190623959274, 9370503401456774242}, + {12874840227707962403, 6119547445810629810, 9764164009057494220, 5416853666956021065}, + }, + { + {7699498684510298360, 16542285627069734869, 200751785530104649, 6985944962584804095}, + {7365545959109847649, 14865387755379324112, 4167319688751668987, 12162483513847343974}, + }, + { + {1039980316046001816, 7207503221801597145, 10591680158322288825, 11266400320575557454}, + {10706275395641440317, 9288394947884616208, 10167533985006762418, 1456585988309878747}, + }, + { + {7076257175157660597, 13221730879315432464, 4499548735964119085, 7559253754663705944}, + {10196808438730350168, 2391718471837563931, 914409564589897387, 6649744842278078706}, + }, + { + {10039057354622246685, 7195562849416781100, 17696866082062058984, 3668253949076972503}, + {3291647709604288622, 14581068695089559804, 10104544037456163379, 5446494334499941155}, + }, + { + {11083442423555675697, 16463352501129765262, 8326106600927169880, 14461723217830443766}, + {8960039240507947123, 6112452535158412156, 16298251376476091126, 5185774007776019173}, + }, + { + {5801222283949474418, 13946418525037992779, 2275515160040674505, 3244981365190546382}, + {9460698310301428534, 14807942233170768102, 6180104492182570514, 4695926909096500015}, + }, + { + {5502356275170104522, 12750322860129485966, 9581277511584938955, 3872282844937972630}, + {13668854758739140874, 15020438121087800965, 4581631138384430657, 13296613956093963588}, + }, + { + {7394309355461523862, 5374161350639568117, 2763783634295242959, 10215168014269656712}, + {10862202275249464165, 16813773246956503013, 4644566761082532589, 15300517379307655907}, + }, + { + {10894319502247195436, 16018449015752583379, 7936971022695592164, 8273950599391165937}, + {1130484969598457981, 10652972605389048300, 5964985167476071140, 1178111465674979168}, + }, + { + {3215460690308212256, 13044009109542950831, 1248575312568743704, 5805472854961471970}, + {16935262056111009166, 14323719510498371522, 4137201278518680629, 9262447671880633672}, + }, + }, + { + { + {10228366644420455452, 12084265406352277347, 10265869676493821892, 3560143954870272139}, + {14368775225608592689, 13173522067191372913, 3592475039513249949, 11243554718624931135}, + }, + { + {6543255501112359319, 6063422531520498671, 17228726254778244409, 7570754775709645369}, + {18222396492501523182, 14903937974816691813, 1216646642383641441, 7602781158453005929}, + }, + { + {14568782576170814716, 17582848432122737506, 1079387064102681806, 17278567874821675408}, + {3094302191119669899, 3730448048895347901, 3508894590334961422, 14091660942919228106}, + }, + { + {13329033749048978810, 4765695903433858377, 4452680451529163940, 5638854187414651620}, + {7897503022043776206, 17187635538005569019, 17766753195497526986, 13201529234556380285}, + }, + { + {8934119620399766972, 4226481091885914732, 16000709195004445297, 14687868180928846933}, + {16269913392757896907, 18294005838441325342, 17625669613551023126, 10864307042201644469}, + }, + { + {14722530431277419104, 12333728409662476827, 4162946257347548625, 7052045338975163666}, + {16435875989376103923, 527141841571514699, 8480360258792897962, 4322786951393806781}, + }, + { + {14380803034817149259, 11042134597430846555, 9992762805140200547, 9895143575678511242}, + {3228768306004664915, 16153114680219541243, 12036181641761325912, 491369524302296324}, + }, + { + {12320933424684960076, 8906954611339502145, 16931708732547376267, 6446897311644431583}, + {13749563256713530203, 11522599770043814384, 14455556215959342791, 9022955938835504923}, + }, + { + {8738648866901281761, 4688741093801776285, 17069682640810525423, 7158141773766072053}, + {11460933790638879246, 687134766504463570, 7796313120876518884, 11150451731319135164}, + }, + { + {13652684811535265600, 8494726433844453583, 15999979552047212740, 16433235792902853942}, + {13641303900302396790, 418630713805776951, 13090797093697365883, 6529658430803752768}, + }, + { + {3944614182924380177, 9542495129087581473, 6699683662731923419, 5017219913619823514}, + {17045736494588140273, 3578045824537114332, 15234910011456151711, 4392310298224006475}, + }, + { + {13050963220563520130, 16311879939705207639, 12461297624582251388, 9677731599265769222}, + {5160679975931966230, 3218707041599533629, 17098083534384492023, 2330141721984719029}, + }, + { + {8245975647138927146, 11496799090887525271, 1709462103065191917, 18401529677683893204}, + {13971543411749700717, 15107687167816783802, 7171906080161032790, 2549191081579169610}, + }, + { + {17251496610557148115, 13056982918233222110, 16321077587645226911, 15873643227887663856}, + {7790198561388957118, 9539520576306975575, 15234893276112958324, 12999697377068360422}, + }, + { + {16169560456946825943, 18091964243071526492, 4341876361632902705, 7532668331381251135}, + {15346381760818990405, 18301333564088079147, 6565096728885044125, 2494845330727350075}, + }, + }, + { + { + {16319476863352440541, 10283930715856640343, 17675054544532098447, 11261132162985242084}, + {13712716897981761400, 2681907143459288706, 6930256922080133347, 1445069157579547822}, + }, + { + {16928574868467385886, 166417019993787654, 5882811520342817815, 14106304179344008065}, + {3747123724781081800, 197109533566874475, 14303280595714789450, 15457633026018307066}, + }, + { + {10773597511592584859, 12552868588431074640, 13500771767160426835, 8002499270056378440}, + {13792839099998553174, 12949371255843262119, 1713974340992291550, 16150173130483658061}, + }, + { + {14745984256428057001, 9333707338036985191, 15365925315303462, 11789129028059619744}, + {7873100217437235208, 5289763977161829145, 17731215200358323788, 8876377479309635703}, + }, + { + {265950821974454804, 5047467530470542278, 17523044368516619801, 10054436503372765176}, + {10321185867287373431, 1212061937729015591, 15311258419138633926, 11236518538207084768}, + }, + { + {10904693956407098222, 9013418755007070130, 15510005599846320670, 995378633446250700}, + {12234095025518917836, 6689106237771514188, 2809193993744369126, 548124799387888260}, + }, + { + {267350765778774337, 2853877351938464055, 3677119082593358544, 7685335121077514739}, + {6491980094762370981, 1384870316654548002, 10568872345228996498, 241629538659623878}, + }, + { + {5839400175629113441, 5238299193248381245, 16787876416022887315, 6051613843621920008}, + {9219569873668974552, 5916753090530931032, 13390630214643423749, 3265335490455191268}, + }, + { + {1507475744849985303, 2597075068965622770, 14968669113917266926, 597606442423659891}, + {44293923912414886, 3832651144752540816, 17438860065613195810, 782112340603343331}, + }, + { + {9050896199196733903, 6427608033444590004, 13787696679536621857, 9682087046920409188}, + {4519093754155995429, 13564098392055667371, 10512507082236058799, 5289934424008191746}, + }, + { + {3477191607403300916, 18283244229745029067, 8462159792484018099, 3056576498976014760}, + {7259283167233712785, 12530251965039903998, 10232104933720625111, 14190745998092156987}, + }, + { + {15759362035410895911, 16075598437961371531, 4651513528876405575, 7694151626503869614}, + {14468862724637972284, 1838601521755586245, 4168957446435305706, 8694905613027663664}, + }, + { + {14825552838983151434, 8639609968952840931, 15547914584352392016, 2313507499500708287}, + {6902543375698033684, 9987468886016348918, 9068175779860656258, 6899641689193116297}, + }, + { + {7449110402827616954, 5689206471789540768, 12722069021950813669, 16017131401246233663}, + {2240977975275954837, 4794705713606614946, 5734937900461809607, 118285984764445639}, + }, + { + {13917685647531721740, 2432096911145792817, 17733637484624159521, 3848601825403209903}, + {8192433211051054683, 17388066421914150767, 14336306308847565282, 7501625553608785022}, + }, + }, + { + { + {9194523390605857831, 2335161171394626054, 12290490336543843159, 12464172604156286188}, + {15842196578033029974, 9081285134201585379, 6123406461662038242, 5504260508195082396}, + }, + { + {9599159247384506427, 13011559959971256245, 6331802547989957841, 2642320882309956905}, + {9140255367820630480, 6883541786494880896, 9560822438260750771, 9273862677291701694}, + }, + { + {12578940088863451089, 4698579870843180556, 13634180401794570924, 15763130743395284022}, + {7444441842547931942, 4944622454458561492, 9589156490791486440, 14762328488235724618}, + }, + { + {6185067974942684922, 6452325785873503452, 15247257292915812252, 3689324664200339196}, + {3264129576054154137, 14977721630214750038, 10720913377937894256, 15914487080763816378}, + }, + { + {8926126498606164569, 12956394005759769716, 16902149488499586013, 7841840983349613625}, + {10587053251468526108, 696362153501209498, 9784750880259098186, 1207696323194229080}, + }, + { + {6366297849225708271, 1653728037493780302, 924103820671018926, 2050213326049184692}, + {5527413390519421127, 129805527414320490, 11550889572378802302, 15667992622431666977}, + }, + { + {3759028419971240833, 201899490644698259, 16787882148977818573, 3755266958958128460}, + {16997526157701685291, 6920710029293447897, 14077301651040071328, 10880144992445166875}, + }, + { + {5498621600689515064, 11498885804037952971, 12697073118321478539, 13999008478737234463}, + {4324885099420360642, 14021182496192299466, 10763088992583373843, 12898585157666243299}, + }, + { + {9367059860785010847, 15787147891143727655, 2519720658767337732, 11593809545681651942}, + {11966083811953753216, 12761111316475086277, 5681625861426437827, 15920587591610358813}, + }, + { + {390729441391219522, 16780558466241830343, 1374488446906327562, 10865131913700232628}, + {10115076211715532468, 18184016780675566832, 8365356477197603014, 672096097598251136}, + }, + { + {2393424067712509928, 16879911507754196299, 6441307574161100589, 2818743579517374412}, + {7083174841445248189, 3410683030590349702, 14697584027599531676, 8328975445543175696}, + }, + { + {11622402383521841588, 18271726976204770291, 4805501248621435402, 13483122453682180759}, + {9288143526654965614, 4688427612851085031, 3280806057528512375, 2249349779106893174}, + }, + { + {6807440366000180651, 16399452121226315247, 5098169947999459087, 3558234272787006753}, + {1792969085845015294, 5524357634740353242, 9429244535996516945, 3937357214017147760}, + }, + { + {15504868609044485967, 6752328153557303622, 3778610801922734369, 13830970685441980645}, + {8715733351182855585, 13970559751738714496, 11410776131378170826, 5487441016062951646}, + }, + { + {13162254303511925286, 1500183854026947752, 6344593292969383689, 13968537166293685529}, + {3100593991852309751, 464141462036312207, 5107705843278430088, 1965835506583809167}, + }, + }, + { + { + {12081034000518110752, 2773740877021737013, 6429475399936543899, 6804412599792308979}, + {16082860502313571182, 10013838454082912732, 7176778953927883654, 8065751639278576331}, + }, + { + {17741525051518363144, 1374267330336191942, 4677891169679898540, 9639823611685431337}, + {5482431056894095950, 6629146695374718376, 3884574854221819712, 13266790928096813258}, + }, + { + {17505459029376928465, 14087658194607915364, 12240552390931686885, 1809009366037859941}, + {9468395484396723291, 9446052656478984520, 3720796795453397330, 18035355127900871187}, + }, + { + {18221138344920380175, 16761112742545021198, 14421639991115588619, 9419167563943683547}, + {6237248361283446238, 889754338720059891, 2289880386545166424, 4280148734121099084}, + }, + { + {5259165122317589354, 6306061166879114159, 2622163270351284906, 15212813592118086979}, + {11497359168652342849, 7085380391293263482, 11799059272489792659, 4912160901181298022}, + }, + { + {10512473611770099290, 11735037909076331019, 2922606398008539984, 2599799834378751770}, + {10226702495047936424, 6109026252412854338, 15572556822827169237, 11993701786788749663}, + }, + { + {5106897453764491321, 10540479232768400094, 3938246597140945859, 13156157265138481529}, + {4932443191001849637, 11374218582626530502, 2907557293167002437, 6807344711257391317}, + }, + { + {3993197157612782947, 14810882170056329119, 3476738916713041107, 1512933700383846542}, + {17820889751141311776, 9132720567660500233, 17598924894608972696, 9704537908665702455}, + }, + { + {12121941964759747109, 161674837074510172, 2599887134944602725, 10582301831176576187}, + {17746858667522793487, 10735346620578591475, 90382511151212475, 8756617880518165297}, + }, + { + {13269854730742674802, 16128423099443070808, 3557230428644480193, 9637953317416090984}, + {6295039911768726240, 7019479692290635445, 11667616931857432446, 7159479331923350611}, + }, + { + {14416651741118525418, 10180867452897498870, 5073925566889872021, 17399294023945814271}, + {2042657564518230341, 3364886656428812718, 6324877312192616572, 12778324589036538810}, + }, + { + {10574237360751578123, 5116798422805306054, 14491722292795290218, 10799156134310323684}, + {12689926633011134844, 2658342468671191169, 15293758403109373386, 16248058473163364262}, + }, + { + {17412396133163580666, 6474892296180387693, 3334160446575187305, 12749216946172573968}, + {18160154520597666127, 8818156595950176943, 16077267238396508593, 12651459389529897136}, + }, + { + {7837268594975894598, 3733413917041538879, 9408433334074005916, 9807113299110084489}, + {673053561909802023, 10235823672366472244, 9197803481286702511, 5670973022205283920}, + }, + { + {4435804333677545569, 12530066828083700918, 14652119799285589695, 7610189145859517535}, + {16049951379406478991, 1895939661259683634, 10886955028200106760, 10575752015672416378}, + }, + }, + { + { + {7454214833719424418, 2128900810399984335, 8254953962723841408, 5341529923812819418}, + {11486532916552139238, 4528331821405917357, 5048485034448492541, 4189495710753944825}, + }, + { + {9223539587116638677, 879142711399260546, 2878829560233905572, 13081522393987952773}, + {3067261963348061547, 16008150780594711643, 5466468631453287640, 16659147898971349582}, + }, + { + {8047766502132608624, 8715815570878148809, 9093649079884580138, 3437267783531715968}, + {17562225708466062266, 3512667182749067601, 9223059995161026858, 1366690634827047376}, + }, + { + {17929132376737482163, 5565926714491294456, 5252303555134107501, 8169975563698132305}, + {1829326230943509100, 13780918661853274468, 17736665596871232627, 4246797342334307384}, + }, + { + {5113556452592134569, 7304867793218750141, 6016631926489320290, 16471860203547627727}, + {3444471410714850041, 16571738096215232488, 2003912224952639024, 4203884000388032492}, + }, + { + {16858425223672505353, 3192567884201479579, 1688923188642613263, 4159042130811153987}, + {14900413503869744297, 7521485042788722327, 14038093805562042641, 14713051866364662650}, + }, + { + {3738774192924465076, 14037618828827556145, 12882915396530927286, 10882862194263941815}, + {13115222579444494605, 18244214260845794346, 17217867059738274194, 2458870331386500577}, + }, + { + {8768788172344064509, 2761897497254272960, 1400167175024837359, 2591319596670212133}, + {1499652044223484974, 6820326453941021707, 9701009499879906773, 6897435972338565418}, + }, + { + {8314355711464256163, 8435944020779763783, 1814803522962187872, 1875253356755380905}, + {8214588085484192137, 18062045700553127821, 6649947905482043494, 3119726140944397531}, + }, + { + {11881571666857493523, 6300786026612414187, 4928573492087752294, 18343550313462089203}, + {6770642120472453960, 11296815027803718740, 17312916793783562794, 13028515123652649961}, + }, + { + {583508939637547757, 3195115082527873085, 8497784022800549923, 15135719419829981016}, + {1180291993378114150, 5447281494912347899, 4710517655176242215, 606503081693490000}, + }, + { + {17732293765863716052, 853971165248416821, 2022886284923413326, 7522564752651732633}, + {1417954193520965954, 5046659528429172066, 11426939225844711305, 17687206690616539318}, + }, + { + {6518552374736169438, 7940416740434530770, 15228615103587329007, 10662504584317997513}, + {18370800756791469891, 5564085264882124489, 51043856061444814, 11996026931884728651}, + }, + { + {7009195269496826002, 18330778751427846129, 7903886241001925539, 8198930484643879628}, + {5453546027419466587, 10378692433982210944, 2242412603379120569, 14762161396393277464}, + }, + { + {6146718865488327808, 8559779132928137805, 14001994895150170346, 9915701789711858841}, + {17119408219089522083, 4345363585985782988, 7559492126634131602, 17074565022279033371}, + }, + }, + { + { + {9262509587234749312, 6377906816499461739, 15415592259881792841, 6113140067088447267}, + {17505803833889144731, 3922849788840338823, 6180172597177093790, 7272741317181956640}, + }, + { + {15620168851912893400, 13762314693487747007, 13577625382054330775, 4116976667540664996}, + {712200332640207605, 9098568002202933512, 8905476951567380032, 7075673514150314660}, + }, + { + {7724870937269356050, 12054277107553403808, 1881284905431205309, 14429595888039183277}, + {4176419490283315185, 803567059653412279, 12138878637145159139, 9651152331113389250}, + }, + { + {15811459837282651008, 4038049993244767161, 9054218236388056577, 10807376403937048775}, + {11113869110590438959, 10336442539492421506, 9228056645601479672, 2983388754829658480}, + }, + { + {5272549712777700740, 3890998652469537324, 2338530655383446899, 13889100994494825258}, + {2605827345546331653, 1946537408424111099, 5960128674616374312, 2996461229050766944}, + }, + { + {9235630643187100528, 7874836741106774683, 1509645736063284557, 1291934408179243533}, + {2170879231846765016, 18243888082459973651, 266993053446290594, 4551583084211481457}, + }, + { + {7680050744092380106, 10728235076013009138, 5020205498410121740, 8174117988374987111}, + {15823303896577313648, 6268651341788131847, 16646239256422284672, 7277830349937654337}, + }, + { + {7189376137127712298, 9147574701720272724, 3983921661449444789, 12479790317447783959}, + {13221020976679959405, 13001868979553711359, 17918176319017234744, 18030393246529651080}, + }, + { + {1277346094474678251, 9498303380775859142, 5384923668452161486, 1780647986160100011}, + {8642790494747200341, 9734232043260261391, 5142834828615817260, 13851307413031336094}, + }, + { + {13856162196947802633, 8991033151317963811, 9758143338284799726, 16669930361261935141}, + {2769693485089420097, 14961618614592883242, 6027973048684521312, 339045855685213514}, + }, + { + {4705473345956039571, 17384553086897199761, 4490030246274451948, 1509996255726148943}, + {13542663230247432557, 15148026535112827520, 10014941605271261089, 5488071105468657298}, + }, + { + {13903368497828271814, 8050546449078305498, 6932373216915935575, 16010012759059004304}, + {15451708272653450375, 211711129247219149, 10435723642185827585, 17790507800712341232}, + }, + { + {11196283625212661460, 11223173364796389182, 15927254202510526683, 15939111530538795368}, + {3486548927974609940, 8233744837082586587, 7138041412908951164, 12863368836600604627}, + }, + { + {587498550288996803, 9937849083717302378, 17460580580397185843, 16850270092759302710}, + {8661654791709545973, 2350686583325065432, 14816283856648791595, 13021196930055398267}, + }, + { + {9641099975481205848, 5936405208377074167, 16926315209235053832, 9612898534540818137}, + {17782980290875306043, 4118599702370009503, 5379494204096737612, 10529123509904334042}, + }, + }, + } + + @(private,rodata) + Gen_Multiply_Table_p256r1_lo := [32][15]Affine_Point_p256r1 { + { + { + {17511864284462479051, 4391315454785363822, 16633389246499252566, 4290325975494843430}, + {15912670649662225191, 14172733821603328367, 12709802627494541709, 9648238681838878635}, + }, + { + {12840624483048662115, 13614226123606379619, 15087571995173849344, 1395488309690794621}, + {7173958427217959878, 1198561064176820332, 16821886260165681626, 10019479169661217935}, + }, + { + {9901328250515532535, 12796305315632203942, 10819069447660403847, 12542238242508661240}, + {17077777737462854238, 4364294351375777648, 8335244153165894685, 8863541604979427311}, + }, + { + {11029520456752683158, 2297291237551781454, 7934683676555855479, 1563954733146546128}, + {2252805128528536255, 10523375695822939112, 4598652721256818062, 17493379105069761435}, + }, + { + {2747551692916263132, 3151123035150683281, 13938314333309683791, 11970864255483579560}, + {7894236725861110998, 10515613623232567716, 10445557830757066839, 11155097727742050955}, + }, + { + {9569762631377921701, 10341967309273270300, 4697570564829842013, 16684762125903667303}, + {5281929071085172097, 13027961546412671127, 18398764602992176314, 3872796039504642974}, + }, + { + {5035609627965208105, 6338722048255995169, 11594969687968475335, 5639340633771742838}, + {6928934109570365590, 11589609913085167707, 18353534295019770247, 6879412911232288750}, + }, + { + {10042008593756684008, 6713471518385846030, 10961845838926538977, 855334359173719954}, + {7598642325962297361, 18006511265377032901, 6844179774752820363, 248341098560552116}, + }, + { + {12797853895127133352, 17314687680589848148, 4801569699821499927, 9711604734594547217}, + {8212610645535363590, 17221681508724305642, 11398663136094709935, 14918164175449979798}, + }, + { + {14940688064094792027, 10874356086032303420, 9942334156288812894, 18314945846365913248}, + {2026773265909278528, 13079907189666226787, 2413436844382479762, 17172916412715413729}, + }, + { + {6906211734178583215, 2568977141255648055, 12122130143181371713, 828440041422552532}, + {9361946962651414191, 8982763378443381215, 13842936470438971226, 14726899303190381422}, + }, + { + {15233793159839573220, 7091365221489488397, 7026505041428577564, 7614138360854053029}, + {5906758210005848219, 18266182645583974519, 15465977441750183309, 15365799046100584430}, + }, + { + {5523310814149808824, 11103439607538154330, 10292039577546071548, 1169663949743807030}, + {902203905701917473, 12346725749938989079, 17633270407605278415, 6960688675023695455}, + }, + { + {4505161139988645144, 10689463780805884897, 9379083335142738351, 1333253488693735633}, + {16044931735888519844, 16145584549427855743, 15405407720239538978, 11239573776554839202}, + }, + { + {6975554318981968975, 15982286720404911512, 1685931425716796252, 17715405440768877495}, + {4827607732096558544, 6375626601740689475, 3502039151843227915, 12085565714635174559}, + }, + }, + { + { + {1190044221726873109, 732025666411072563, 7781096808432277694, 13079879637655900365}, + {9048680577986693793, 12528346194104542124, 10575369576322629835, 14068913038053465964}, + }, + { + {3297775431071502652, 7947266993949467566, 6161673381820779563, 10604626734847205996}, + {17669018066064502925, 2386071939136502354, 1076023928806956187, 16075459682742916440}, + }, + { + {12387028018538599950, 5791681577936683396, 7536922194386052138, 15377770247350254336}, + {6564316170002440575, 10629371267149545956, 16125760269901494382, 16051398044897962024}, + }, + { + {6237354803374899565, 1782400080026955610, 16115027077529639342, 17907259814836219524}, + {13179234383592426160, 7302978467158243198, 13607720993463749225, 6693531817169120736}, + }, + { + {9659467198848065929, 13765104107473534739, 820057324758632016, 16604163594878267405}, + {15321524555426147294, 14524167419333362957, 157291234996957911, 3689488130722730671}, + }, + { + {13896531645245568605, 13598412639648980920, 3875086557856143664, 9242105512956135595}, + {17410265178284161091, 14904754836127450463, 2354327747158525902, 3858493849578874654}, + }, + { + {17288438225198818690, 15275190140700748774, 14532856272428522409, 2192294551011758591}, + {4275966798014984695, 13252812474545742114, 8604705074440591847, 504054699541924162}, + }, + { + {3623027910997185067, 15957466839356832933, 3504133700071704955, 4135728439139397021}, + {1160600455691338871, 4431928072859292239, 1542956305318065546, 14109181184369694855}, + }, + { + {9135041378474229537, 15626265487594878380, 2645257479784082878, 8105679948445763432}, + {8579715781576202730, 13437359533149316300, 4344754720520585005, 13326372852934103673}, + }, + { + {11341622086474305983, 17104958945811183278, 8154944722722765678, 6696975609844549775}, + {10895966360082878017, 2277686037575837054, 12236842881540344526, 2086470279064067791}, + }, + { + {2942668817124399651, 11439025398519255779, 17477264434671471242, 9606507094132585461}, + {1771475584689465869, 10791261379080046759, 12901998265727968789, 16423426725595035468}, + }, + { + {555419805011031621, 13715683285513290290, 15526654591995532751, 7023761423093873354}, + {15093366433178982304, 8625749648874372840, 6412297471587129206, 12161114204724955762}, + }, + { + {9362623422820895267, 6491356159483508885, 8543224082493101588, 17290929683278258587}, + {17348088672546490894, 3323350644823701753, 398525379151271104, 17794417664139368677}, + }, + { + {5880914635028486784, 2898124605786107494, 7953506026198179840, 2189477357380899574}, + {11207122442953694293, 9288539232660208671, 13527697625010979453, 448462453367651162}, + }, + { + {11262205719433170585, 7539606872920196479, 492385789142086954, 16036594120332851267}, + {8084547797138041354, 10063336189771527714, 2484395715469739911, 4879298610504146231}, + }, + }, + { + { + {10457697409306668434, 7830477435299250296, 7772379952622394912, 6109610138112185532}, + {4382803614711332911, 286231563340803504, 14408860285425706036, 9445290615796219321}, + }, + { + {8838210194055479741, 16190279688839291456, 16520121358582757556, 16768959728701970634}, + {17279896910204983538, 3582816187015369256, 372137484481226748, 12972230207718993241}, + }, + { + {5372953569411270487, 17808033035436856194, 18122397266105109983, 7100719381161799491}, + {14789750485957107776, 7797117101197801156, 3512936690589352328, 17020065099624467120}, + }, + { + {11480031272463364121, 2525856087688686375, 5875255653057452580, 5606696614467440464}, + {12094715534218447962, 6173479337351577758, 18244015404482482803, 13199349349511499695}, + }, + { + {15137716704658930971, 10986987873306909694, 1939043496821343401, 831824210330752494}, + {1056638569496361761, 1714583153436391847, 5183439003162975519, 1665087783666164342}, + }, + { + {8618628902870211609, 18064648431799903596, 7274877928823092285, 5660734703123876155}, + {17178150811821260605, 5485275535084805985, 12607767610318589165, 2215859519135800862}, + }, + { + {14525253431314563485, 18061438239992695424, 3753059877845742067, 6434164734885086330}, + {7925955539869645215, 5236273722884803492, 17135463959633855728, 1885217581414238490}, + }, + { + {6097225965006328457, 2630336000831717722, 7049638698786526134, 4203465038263485233}, + {4677974565964393904, 16044036678123636261, 7266049959100300634, 11339674070148504929}, + }, + { + {8932509163442546090, 15088719838810504543, 16380598316811388529, 11816509227456545305}, + {16117098651837966507, 6506253137957995237, 7842840841723336777, 14854630695614255489}, + }, + { + {13319400996902371533, 7582870533150862327, 3853021819016824068, 1553148791440569506}, + {1383156799113954152, 15192818247458559870, 16096167687117464686, 6356494963887209448}, + }, + { + {16159738883836847557, 12797888767862801410, 14516904553705186948, 13070086184381080434}, + {916885380224317954, 9486576895096666538, 2320292919516422975, 5019772534786350963}, + }, + { + {1979992348876614621, 7494083465935166973, 16035723662722831744, 6820849908885211777}, + {16740735239901023053, 2017530162004533409, 3087262288875984227, 9072904925376793991}, + }, + { + {11716934526135332476, 433379719600995157, 14981324743710487461, 16580162143428931768}, + {17678216037230646787, 2252837520490636634, 15914299694597684738, 15253999728204986937}, + }, + { + {15673599333229961794, 8862902775863712472, 7565222536246787763, 6724910605061440481}, + {5835390808530098179, 9647776340035782792, 1038074137838521743, 3352456378381259564}, + }, + { + {13166325906224116930, 10408481058915151795, 13583679214409957982, 13238337156927685694}, + {16088785436819834700, 15860660615594092228, 6472158593272826810, 15600310172166391652}, + }, + }, + { + { + {16375505785562641226, 4903074653735993511, 10355787845763031761, 3188849033041803587}, + {3145147452182864049, 13878747873108378466, 2798650520315922121, 2325962694441538199}, + }, + { + {11530583608023224967, 15979155166527001287, 592931868138800645, 5361781029549479856}, + {11246418752830406096, 11882251984248471436, 12026389461944629423, 12289077922798223820}, + }, + { + {1328339467113622233, 13374824154992864223, 12057132015324007824, 8507647484414695512}, + {9286016370798146986, 9083798709648036612, 4312959727577073260, 3732271624824420608}, + }, + { + {14129872794455315922, 16354810591314135702, 3177417010197743958, 16494351130927698692}, + {16557765056328447818, 3139394196704738651, 16891813998271303650, 7374470997276173905}, + }, + { + {1547814412223404746, 14194709348405912167, 15771028929623393801, 10945048172868684389}, + {11234483878611528405, 9542605377580701681, 4555391547268120796, 14916872217451960022}, + }, + { + {15490131882364039637, 5140304620645573547, 9403655757498826823, 9824850954989176893}, + {6366139388903157264, 1981838834216345294, 14659870286877979556, 12091578124492612524}, + }, + { + {6832171775190531128, 7903951882621813138, 13717573220828409267, 15400575122727850054}, + {6101307565293576434, 17226772767105983314, 3485283905347036760, 18439321272895583847}, + }, + { + {6289130721434350290, 16129337673129720846, 6648351866142453445, 7705983837166554199}, + {8120136556582544814, 7924417299222764443, 7821995671300500892, 17697662726179084739}, + }, + { + {6669506511185916061, 7036555931205961476, 15471324228012955656, 1075869467462424743}, + {14834182808856841386, 9481869408708862398, 193651363902981365, 3496053494343565969}, + }, + { + {15198290782478916101, 16205293865829644684, 2104596565474767471, 7783918193658109501}, + {1567469099169331732, 11324634977690198924, 1374141643017900909, 18368642394438425630}, + }, + { + {13389638006727712302, 17518324493263447682, 13178832200681259657, 8955667391164524441}, + {9331759525815425703, 12920722511913101049, 15807602761711044426, 17873219821625976662}, + }, + { + {12103811390374960600, 2801185238127939998, 16289223959107648345, 17243660994858386104}, + {14818957729322960498, 10018491794651971206, 5502065678180783560, 4158378425043433526}, + }, + { + {10278921174996593635, 4630624563386647486, 11179643216044347020, 8701826069861381281}, + {5839989039471676569, 3060138177923841885, 11279648082143612852, 15207786733412131883}, + }, + { + {18277950978951138342, 2577918906618404946, 11684553042740786163, 3082582313241836872}, + {5222056779189126973, 7794579876203167869, 8527673475629739407, 9851790541007784515}, + }, + { + {671618501514350673, 3455246317052893537, 18161533457452722900, 8968434886308785175}, + {8445049055511813064, 16897132794064300993, 14420937999674600470, 11110627336577683437}, + }, + }, + { + { + {11535283160083833975, 15102917952496589829, 12909095696891909745, 4611119212602854744}, + {4195756524232932570, 3754603965149529000, 11539276962358607816, 4401424391553230481}, + }, + { + {6842993463058627120, 2708745114617181146, 3832382691810282630, 10333834458057320812}, + {15028197197004077388, 7681293343255119354, 16227537691626587485, 6703363869832495607}, + }, + { + {17567108285065737529, 8693245930330183070, 4025672038042952121, 3491067119247522844}, + {2100799837993193702, 9579542950705774054, 5091525285265581997, 1806757015709820088}, + }, + { + {7757354840118131559, 16227348978414023262, 5800861674805516343, 16486235803248700961}, + {15646700163023677309, 504258765210816549, 13724147899924699697, 13588899538317277096}, + }, + { + {15895596198730294923, 12513494396374459899, 13552575153453342654, 11312160635199213507}, + {12446618129881485796, 11286186116805515445, 1584191291800429567, 10188741008566636830}, + }, + { + {10157626021970320469, 6580688164585715207, 17158416694471177787, 2873484006255074946}, + {14852216457444863041, 7463041347566136496, 2190030775722958628, 1116223035803602728}, + }, + { + {8598875756176012541, 2146658618778432566, 17575736667490551813, 3602654209723135985}, + {7223347129734689099, 7256921024940026570, 12249118963297692963, 18168532365040819099}, + }, + { + {7585174044375463988, 2491923406404093282, 9355733262044036112, 11484079611349577325}, + {13145030009254943291, 1234932884591406048, 479845670619308618, 87735010308690865}, + }, + { + {17307641427543377277, 5862898330718319545, 485176909118483750, 9845223919324484076}, + {4293549583740204024, 12765124043303931186, 17870894781132657382, 6508172378961793849}, + }, + { + {14234156373312856400, 16210939788814051708, 6478880037923038392, 10435512103812909561}, + {18142844321802359753, 3243996803126554757, 395603619159523019, 10213589535656704607}, + }, + { + {13256075137060741204, 991285459654295161, 7857174835799942102, 16201105040554625727}, + {18398612085349994216, 4512860776717176840, 3521452275695011919, 10622137733045360311}, + }, + { + {14993897771652736376, 3320388672992783302, 18421556740970114213, 7438967127794745135}, + {15048397725789819354, 12721899159423777001, 1135125102123667189, 6637485660805148630}, + }, + { + {205606553319362431, 15484041062449893984, 12896720585684759529, 16675624014916513672}, + {7579112430564108390, 4602460356900251082, 2677787525524280838, 16723483619407414479}, + }, + { + {17981939084373319995, 3989926231875116241, 15342509934701840045, 12999252495311233519}, + {15389919024942778009, 6136335679373143315, 4117381415379544275, 13342256463740646775}, + }, + { + {7622769999043907199, 15227992053145045634, 2719412067263856950, 17811161335980566241}, + {15036003689029442301, 4919601685231030712, 6756893600905532338, 18029567067112075531}, + }, + }, + { + { + {8492025373682814159, 9341562763134230960, 10104358220305514878, 17545404790574939459}, + {15737064134098795026, 3880597485411313924, 388663918823974597, 15032915458906101183}, + }, + { + {9452334891928331309, 15207477416486363718, 8081596400773698461, 7528187414539292243}, + {4773782664413845594, 9435822414884353799, 2722451711480791323, 13642248100035410269}, + }, + { + {14202843175914986568, 9421566354325954710, 8667368258699634314, 8733557788892402517}, + {331451278037425751, 1109013653863287548, 8802742738207038150, 4667769857523050796}, + }, + { + {16570512961992288509, 15784840936011612960, 17797638261217375128, 10589124475671334830}, + {16848440972121709899, 697679021479737566, 1456738239410270672, 7214966028857473701}, + }, + { + {13782421991242364698, 14661156263311647121, 4726455119103158850, 5026680986111581594}, + {15610213195880130268, 13703306863846075517, 1371700218221235399, 16792392307217237043}, + }, + { + {3250188629442787152, 2728518744775098354, 3140694818026767341, 17566141747707001105}, + {9569291890730505101, 4439949820491175035, 13751802166620923317, 6602549032413906269}, + }, + { + {1067242659333881602, 11852011445832610026, 10644339539182752718, 15519552867360295119}, + {8817864336906465495, 8844034637292547409, 8850766994595652906, 5299330403389585218}, + }, + { + {11434157439953722433, 9090860151661100670, 8407869262026581159, 17882547383849407986}, + {5277257988019769029, 11463853580825342183, 13607489835500075467, 16878800997498950751}, + }, + { + {11526703690786988415, 6919770449526881259, 6713486711636442468, 14697284704991333147}, + {5405738839499060129, 4737011393825878948, 8707677918280383477, 16881185094380241198}, + }, + { + {9056014389564242176, 13179419520216397988, 9815298409700670396, 15302091100015307530}, + {12552178314548371153, 3975519917079954227, 17211203317279781814, 17755252427177154090}, + }, + { + {14056502343958951437, 9570378325961888046, 18335930130582329417, 12188057598786655680}, + {605832426765150582, 15265028749599155713, 4881763628803375168, 425422732543303669}, + }, + { + {16059297404709367406, 8426877510924536482, 15269952608796785555, 6256768900860981984}, + {13142655793714702073, 14566340391957173918, 17147065283704191109, 879106195264399}, + }, + { + {14152733561556558931, 6788431167332998309, 2303657738205239031, 12712406085467592411}, + {1740483284496903693, 7206807366776489586, 13420608648010812358, 9180900918550128115}, + }, + { + {7193311017682954852, 7916342489073401148, 7990830552202175554, 15066065171478273830}, + {15601436495559985484, 11056245839590890541, 15963012082312968312, 7270947051909344657}, + }, + { + {5010740583028703301, 15413348048560455978, 2028314374959411194, 16685660750422250777}, + {14284468905357216559, 13715859397068327775, 400943255937053645, 15390787503961331119}, + }, + }, + { + { + {2707032230021934480, 14943945588296447659, 13333962501998857701, 10603744732015256400}, + {3386903941135274495, 8507451908469049716, 9231176235773710950, 995464562185179329}, + }, + { + {1497127512412966214, 11292269970549257426, 13920714718237672232, 1363993524078475237}, + {3687544717271789391, 14097532154250414203, 8367320351336033564, 11089672460564007700}, + }, + { + {16993953276024768829, 12025590727803527383, 2672535181364381995, 2183111709986676538}, + {14822521615475063339, 10618745739454592027, 9957515072444869664, 4797521918890127374}, + }, + { + {18097777493026370528, 398882723487597643, 10462164796529820357, 7704526739683689547}, + {12438059168025171393, 8163001730991802064, 3319372757738711275, 11518015261707325261}, + }, + { + {7809927122217534998, 6003738786706135597, 16541272992243715653, 11352602417510156921}, + {6070703545889058045, 3742828100079104877, 9416263310824977145, 1406892456840131842}, + }, + { + {4005088727670892586, 10215872293486093012, 7634075494800881158, 7707144163086802537}, + {7085702388211248163, 12168208652772836726, 16347414703478252736, 9386623607672009940}, + }, + { + {16530167766100505402, 14672843572926881623, 10752276706209340624, 6888427606311779724}, + {9060900993058482991, 10439396339124215720, 17640982730425880863, 12916411341252677116}, + }, + { + {11776245660806714247, 18129100488268011560, 15389929343761297429, 14544292652959164154}, + {18063319363114104433, 13433144948667100183, 462314076175867487, 1862686058702915115}, + }, + { + {17306422602774323327, 17272002328208118653, 9314885036861009829, 7485631191912561636}, + {1933835651414138452, 15231897024969540970, 507247317572839552, 10741595984991150047}, + }, + { + {18297797979313130180, 16976628082093243813, 13059060093619519046, 6865085966096869228}, + {15021840537243000183, 17843637254308940381, 13122764022765250336, 12556030904692962295}, + }, + { + {11175787671000337381, 17757097628648374409, 13408571223487217321, 2720103532070247452}, + {3237822932023459208, 10155101091021157316, 13910068101949253623, 648579517754264097}, + }, + { + {16597587101652675879, 3941450686064909756, 17635514250964078220, 13107347044039852240}, + {8910347370050088758, 3114023981351548745, 5209360756412143979, 8990623441581200588}, + }, + { + {7692284195082081732, 15977071788000084350, 3594719301791478282, 16545490512039598136}, + {7629535887569375952, 3241949087900065139, 170526822997903747, 3422990592513330514}, + }, + { + {5473399325468482480, 2511351254139828397, 1124856552206019504, 210074180589003934}, + {9693298849967626723, 16185054013081266938, 16070865229793723400, 734500463998096984}, + }, + { + {4895849847827915947, 15252720925614851036, 5944268852782996266, 8171510665067151601}, + {10594809041696466609, 4377920841124876663, 3816206760439007336, 17150624011379500381}, + }, + }, + { + { + {6266830413981331818, 10890859480409122410, 738708598357264321, 9241173142142102299}, + {9152169484987657321, 12122430118903337055, 14270062735458703743, 13877635605034675649}, + }, + { + {4572419849863661964, 16330741525817240677, 5456771007607263420, 8798510164381810403}, + {16547183593064549865, 11355135595370359779, 17581910791451710925, 11684604415749005488}, + }, + { + {2766130068233451740, 15909689412657372214, 3272828023364980896, 12907534005596438003}, + {7065629942275705493, 10609982651084321649, 17330343421617897811, 1746246157222856918}, + }, + { + {13168953859078137190, 9072500190247791267, 11090199374278127099, 3503847851309060744}, + {14395788825673846582, 15073993563711333791, 12879874391706003251, 15417028700542288171}, + }, + { + {2686132933630431595, 334448852204016400, 5636563341880055087, 3897420469445246068}, + {10569177829735084588, 8244586887721364305, 17973493209847502315, 18083956436923498083}, + }, + { + {15514509130323617046, 9833490355170899102, 12028021566105512521, 6349458533674010018}, + {13470024118569549588, 7867188201997717819, 6110792121234766402, 9917858515766574695}, + }, + { + {8273062939911446888, 1936638151089648185, 44602505720759914, 7839132833110815763}, + {13045756168264521992, 5375972549477973022, 16964151563535745964, 2871770426902555432}, + }, + { + {14164643693563803212, 6386904235704679249, 931435629437735510, 4496152555914735639}, + {820099532545743339, 13419988718062417698, 8948965620484833159, 7238410427920554862}, + }, + { + {4387941928212462673, 8023190031094282215, 12322462122895470016, 17311901330042910195}, + {16445894183838823370, 690424095855074674, 12820742226551488738, 227935274674223825}, + }, + { + {17437729542205914525, 8439533239207225162, 2862942422640746698, 7340866642549630610}, + {6770451500989398335, 17262212260581413381, 2156505157624055602, 12195119268846383898}, + }, + { + {13685370053507732180, 8304030489296890211, 7042719123662732989, 12115154796394040286}, + {10496877583013829980, 8909625177349683785, 5268451666475070682, 8910488385056259560}, + }, + { + {8874918984373509240, 6652428549855789281, 14866714872885601270, 12093494664302554643}, + {10149999253136441007, 1611873554177023520, 10271627298853910516, 15171882630355491729}, + }, + { + {17085353800722834618, 3271271583189511718, 9338466116389304614, 4685545953421459012}, + {5059702655119414343, 201476627889215522, 6388612869673101372, 8357217932305360896}, + }, + { + {1836621694151238424, 11438765101326043062, 5537182303007083642, 2657011195641217678}, + {15370176245454161308, 1478361893117141052, 8729368992402422055, 4807782542738120272}, + }, + { + {5084555197036037383, 500829604818691390, 8128181767026348964, 17895639808733462562}, + {4138748420878083709, 267892430674902987, 8954358455330696651, 1946224964877667668}, + }, + }, + { + { + {17561670470565298976, 9524122142014309347, 12619871254022879995, 4098610542031538614}, + {8338691110372464881, 4378598564044777665, 16435680634249352743, 12067828180476756532}, + }, + { + {12574920924242276218, 18146097977073890534, 18281543194137545725, 4432773597060264867}, + {797962164984225968, 13432184750641235201, 12394976215803938078, 3054137600383896411}, + }, + { + {12910897300898239001, 14116919300756610521, 9737100313909655285, 8792063194563201934}, + {924297264228895146, 975866810375743708, 14953819883516375119, 9992561966868201517}, + }, + { + {18270562314314829224, 17574550722906577917, 15522987576586641271, 4200899284963891561}, + {15719788437321868967, 18390235318178988753, 17371818886753265385, 4583380351670429228}, + }, + { + {11290716045321163897, 423611636875887759, 8716385793549629027, 8029377844845093468}, + {16573848460451650185, 15094868140191104543, 14624483608434776103, 9086586764934160662}, + }, + { + {1320522168839874087, 6395673054871725696, 7793960979093413321, 11402054451286901177}, + {17278080290632229040, 3823680337747309837, 7840042035002848151, 17839593774203285281}, + }, + { + {10024545625018137606, 3780616370895328213, 1516632588067435378, 13846630703933575818}, + {14323905768888574358, 16062987352815864444, 13444338098535013457, 13400662018607341910}, + }, + { + {10102001197913431240, 6211688443233768420, 1986665099237206297, 9248907879269017005}, + {3081890249882755206, 7828527646248386813, 12676034092230326487, 14655968027461080131}, + }, + { + {3763532248936424432, 13507960710132312440, 2003243330622949364, 8723351916784911918}, + {17411870179533482591, 495549359712213584, 6958432541445845486, 7674356092204128350}, + }, + { + {11814337248412299972, 9347461245743305200, 15456560932072269534, 9579754357941936175}, + {2098168907840746456, 2063921976437345588, 9267808714920405578, 6482702408130663270}, + }, + { + {3313415711246730386, 4607422129142883607, 278072683866121896, 830840258180061490}, + {16961959739026004139, 7896385585906900106, 7610238284391475173, 7231671772874233939}, + }, + { + {11464797300361906821, 1444449385286554508, 12433005157477847389, 964895564896662942}, + {8457290958728547067, 7044433897330872257, 12292673928275053405, 13679355097865192207}, + }, + { + {15352304695586484723, 1527883079108513336, 5890042963344522083, 13407971103520766077}, + {12385239629152188662, 315706510218287516, 5361117161753711484, 8824676525356150938}, + }, + { + {4555925933619499493, 14889603365479712329, 15898222225673484215, 878884802170861101}, + {430001626591485427, 881428142547721183, 653855015067704092, 11378990354467312809}, + }, + { + {10219225570653005145, 9205374019534090202, 16828986596058027743, 1089575570166892706}, + {3079144130112884386, 4682944567048139400, 7674497449298779575, 14137535283566239898}, + }, + }, + { + { + {13266892287530449189, 2232961926857263527, 5934654989155432442, 5415975493246016158}, + {17117784386882463158, 3875398271691758986, 15755743581177209843, 11380746535012415659}, + }, + { + {10162459499000477259, 7534168794800651527, 6320985751131807192, 9263840233901040421}, + {12178625283764017250, 13143797113231152006, 13089053551699608219, 13480464010111258056}, + }, + { + {11426681347395118622, 17135867298562042628, 10870734720453621112, 13803364322975322217}, + {9740527283062276630, 13765238480893165263, 4792349632705804116, 18359029140065847048}, + }, + { + {1420251412241033168, 6449255753238336368, 7468624722117319576, 5716072259994197219}, + {8165015263320602150, 4757529151848960259, 2040364517493350115, 11069642333484542749}, + }, + { + {9434687670958330812, 4808705744496679962, 13910334628239183613, 2628594509406050235}, + {10055911465166862298, 8069256921143792190, 11886968715847498191, 6351594160398684406}, + }, + { + {5472832021993175857, 6120966193470238758, 13156950075464061259, 14833372202848630444}, + {5760885723102571027, 18022572190906170343, 9870918995920897221, 9546055667466056471}, + }, + { + {17124591880405051324, 3379747334483646957, 2084957978131092947, 2413497199486596627}, + {2867893699156486423, 1357836849049583382, 13607307985344221035, 18039194570940763745}, + }, + { + {13230815692170010235, 10662664037814374845, 10120384214921531334, 8892863196093018212}, + {4443096401408136417, 1896901619181196514, 739574867683694091, 11233952771600927581}, + }, + { + {13885878918475208407, 18415131106660406656, 14362601436612948914, 5740711586144226035}, + {220574937152712384, 16774016249557318959, 4658351269477373440, 7890975779439252404}, + }, + { + {16628715286876183012, 5300385226682547206, 4493053153469218188, 6690552861098862065}, + {9359345201611660030, 17390357193161728482, 9283655448484665614, 13747647357786913441}, + }, + { + {3101241556869117917, 4731590937333975732, 8347709942856514723, 580858462407103829}, + {8937550160715031857, 563888416351720575, 6928865729903641398, 8295908905021542009}, + }, + { + {2219303446125808132, 7766409607764464233, 4492816761527421087, 1687012079818776091}, + {9967512906892097592, 8099397263797608226, 264054732854154094, 14515622825083967497}, + }, + { + {10586626338424063837, 11285305220583812031, 1552873676034063335, 7108571382532772330}, + {12077600502438115659, 4925647731241250576, 887903929602864140, 3575833277214438245}, + }, + { + {14685642695197717757, 4830460343095831969, 1748938116371486214, 3212377924501398108}, + {7575821759023381902, 4416593227203343304, 17810665332121047202, 5387420006905173437}, + }, + { + {8644732068940188724, 17116805484232699355, 6611042643736763845, 12686480611232016266}, + {13422256101258226329, 15901664205323922499, 100273141428472746, 3184681836469139902}, + }, + }, + { + { + {2754563581284692865, 11257360722362829387, 8254261291934606879, 10023569920325096229}, + {7980898855627864603, 17162063449612285703, 9275759455936104363, 15936804738099638644}, + }, + { + {303387668469489035, 7978391052264888020, 15413722057350324494, 508608987485166058}, + {5585753287556892522, 1344134516582665443, 15144279405777509214, 17014353449841567149}, + }, + { + {12518577022215294774, 11347384788122950558, 17122718824958020364, 5431993665805279177}, + {1445831254446028321, 9845654210244803480, 18315778529692612284, 930563922336183289}, + }, + { + {4894710987714215219, 15704993603878996107, 1606204036324478223, 14308635149530198932}, + {5026736228773269251, 2911689442372084137, 9004077539360196849, 7770049130277452000}, + }, + { + {2745120518194234905, 17255944807561408883, 7371907591838942770, 11781525288383871227}, + {7814952754785494862, 15022715213812536212, 4112388658963418656, 13703771908397991335}, + }, + { + {17455440140812341569, 16738670164475421762, 13259904130186215994, 2168106064304872507}, + {1969289843772256992, 9025317999701057831, 5835661391798891929, 3826587698101558069}, + }, + { + {9149648374608464235, 7248346993716635643, 17283919168525322365, 10107681064815728795}, + {12176813938029507719, 15110337574289033068, 2436453685316043712, 5876967059744625564}, + }, + { + {6197919059881189313, 3300993078638782623, 9357667752372201437, 17688129755135009447}, + {5477090746558113696, 12602024521188880300, 15889961935507293355, 7135039746373941272}, + }, + { + {12561063426893244305, 3079971284510744316, 15695857190375815873, 16730673956207425338}, + {12065477821845465116, 13846158368121919228, 2126156187526559500, 3005167441915916768}, + }, + { + {3858987859895327040, 17043903959888117395, 5861237635520080595, 3292646198413575902}, + {14286644557048422360, 14346409530388980974, 12583555046601155161, 4665981927428063991}, + }, + { + {7657686120974201842, 2388299767028319466, 17934808017791217639, 16708640707026372313}, + {14122341266134976486, 9547124998857374491, 11194069918436025923, 14657538980930727877}, + }, + { + {18115789712912297420, 6543740714573413570, 1955886376702349613, 14736853369719086334}, + {3914330395250768396, 7607848156418885173, 18220633528980056514, 11930952850158858930}, + }, + { + {17010681753474701341, 6961088634819162945, 18395881317121515295, 11611411242007267179}, + {7996717433149311639, 2687736005475404867, 15340214362731923149, 7116441414289074727}, + }, + { + {14302198697220662403, 11915041511943922518, 12363437164440173650, 4047410026894059083}, + {11439743031696133447, 8776097395071907030, 6851061783357383945, 16484733576581941012}, + }, + { + {2861660066704264713, 16453202148771053225, 10039035813504063627, 6275446616881871868}, + {7150609984920482782, 11100941755544354363, 6219760433202580646, 2875377482232912143}, + }, + }, + { + { + {15290817014272444879, 8012864091692295774, 7591940515496590516, 9299619125326026848}, + {7297256232167521068, 17861204372399797627, 3100022958796565106, 15313770879200204613}, + }, + { + {9902363248877274636, 15776195244792726061, 1935342462634574355, 16572507349421626602}, + {7503944294807242065, 7454248748618678609, 2837392985175901475, 16494567631149775512}, + }, + { + {7821919851875204434, 3437243050078433703, 16281279739393410040, 3105985403882097775}, + {6392071520880083076, 2042340026857542253, 2492719020444109453, 7325465357665053546}, + }, + { + {12299242278498309265, 117303082144788574, 18382936515565701803, 7941141688858846015}, + {14923823358299367958, 15681089039073030752, 16878721085421212785, 3933697483394042011}, + }, + { + {17669228922922186836, 6423621568318435743, 16298886067880336557, 11009276012664659704}, + {2934438101395245878, 7492928446481808311, 1311515713186855284, 4493146166488261630}, + }, + { + {14009653500169461120, 12982754496644678513, 14586034645437015762, 18126832542767444974}, + {627541781236454235, 3801503508930355635, 14654684147782092084, 4179096323459534629}, + }, + { + {14829342742512426992, 12453047655591346244, 13146459409240287380, 18077963306248855764}, + {17149389409735171474, 13591892902058002302, 13872587256559899629, 15878632005942819501}, + }, + { + {2878536922988449879, 8819365314325664735, 2696760638950720974, 11357179421800829605}, + {14730809809256560583, 16277258726425730599, 13189689275745970592, 13769784951430309444}, + }, + { + {14706229979050107962, 8679247682181027680, 9705538653507374238, 12793525936716723768}, + {10022723640772366793, 2224403391050849804, 11511158380587667232, 3250960576892370870}, + }, + { + {17671892277522139639, 1384260767972381005, 7623504419117295292, 11197930232971575240}, + {14867469242175831789, 897596747715880677, 3892483173599058531, 13453254609965163080}, + }, + { + {2690362926234343281, 12134546410412600166, 15715872358030533545, 18160163251393343275}, + {12233720002415141519, 556081697748597124, 1099809960955937522, 15489604457800724223}, + }, + { + {10292669945637125918, 13595563061674492799, 18301330068714272653, 16981073598172019270}, + {4022713583718555211, 847970754090163894, 12867993617169467387, 10021141621864633865}, + }, + { + {5408393826294570360, 16896935186698126584, 13028972412622343885, 7850626233281656805}, + {962076344521148275, 12332350290936839731, 1774588207039851940, 17877147526933423087}, + }, + { + {11625440764115934244, 17372224561416726989, 13457342366450471135, 1569549943944038472}, + {17753658357081801983, 14093490077993040859, 1282770820260996510, 16402793994329437670}, + }, + { + {13086054618104175873, 11714492854942191582, 1743587223054035136, 5474094059388998723}, + {13150833497051757606, 17129392131927259958, 5739140380294248045, 10239738807213437974}, + }, + }, + { + { + {3631886121917081375, 14286411187847401959, 1546298555066841633, 4790996540037176549}, + {9541492152219486842, 12304868498960755609, 11426775785781090329, 10793898029125361155}, + }, + { + {10932352970046201499, 5875690226460998551, 3699681560657289718, 8665743594825198441}, + {10232089728487302472, 15664572298733091969, 7267222702489958195, 10552093353886118696}, + }, + { + {4008236965647744142, 8547116629188387980, 13874587567755370880, 12696453513706541959}, + {10752386832421030566, 365775083075323708, 14295272684753058141, 11024897725724291722}, + }, + { + {2399232949134869057, 16408469118941953277, 17229778225562184411, 15990256768949242309}, + {10694906341686584836, 2816242351659628719, 10794163145486835660, 15601904974333104002}, + }, + { + {1158521281204350113, 6232098057848694897, 12517518152351190341, 17852831094628421272}, + {11653774695260269881, 4420518556213490728, 13835371272800239099, 12119809446886544909}, + }, + { + {5143546864201185527, 6400878864024957342, 15513803558106064076, 6712861984922181478}, + {15623960351786428150, 3094277713920675576, 6184647748693682810, 7857605928718754519}, + }, + { + {2219152199405421709, 5367881810186787185, 9606063680551349934, 18233690822105957780}, + {9941441403610160291, 14996958158691873775, 4936282940888570414, 16608409936766385729}, + }, + { + {13270099407878039596, 11569032926557804346, 7759575992876193458, 8239088820951102451}, + {9633607727685959064, 9775909232917811341, 12297921731498614906, 14756100221590046549}, + }, + { + {3076166255574886489, 5587891405059542759, 2449830540875545916, 15616237426524550707}, + {17820334717580127167, 11506219580693301288, 15242532286743473103, 3266057695402840388}, + }, + { + {7193168093115966016, 8050992763687139302, 9734357192061785185, 15553552690657851227}, + {4632257996795951659, 1007158456255834509, 17052740163052114844, 15619284827675470063}, + }, + { + {4224824291132201768, 5709863556852834901, 13539485156399791894, 10330250853413634451}, + {2817020820518906625, 14306724568884734914, 10421968182740721623, 6943068506740047695}, + }, + { + {10830476567180688368, 10003074695797360184, 5589380226277136479, 14952961630386717087}, + {6354514974022878533, 3426762794422332369, 17950815054280597743, 14940277403242978595}, + }, + { + {14582622177810553114, 2819236216667324430, 11333005326119114902, 15900677556115860419}, + {12265999577465855236, 14521351376076108710, 3999293994697120555, 2365385934872188434}, + }, + { + {1803647016552158312, 12981833819573589527, 11371133227762071, 8210800033974528109}, + {16927172347295306236, 11674533305143999306, 1514600283696801303, 17036724058500952986}, + }, + { + {15551380071341300893, 1378878534597097794, 16601031904934455368, 14515377519758777108}, + {7039813638645241317, 12524221355672362377, 10483072291636269482, 5711815649533531303}, + }, + }, + { + { + {9246769514475702626, 5788284997389507365, 15857897362850327403, 13864676801095094218}, + {12881526722328523267, 2620841421323221200, 12599981775316397124, 12820989846844560040}, + }, + { + {13066648645100247757, 16727492115601921665, 15749471761440498106, 937594351871983779}, + {8381111811209734349, 10884357918725639691, 781591570669492079, 12778743765298428266}, + }, + { + {1797915488494232282, 17274756142259274463, 14207994319179101777, 9405903752538915237}, + {9001743317941152797, 15048752608061590843, 4925745663463425863, 17143694017177138485}, + }, + { + {11613437975225156304, 8619196433402562266, 11907033287998837424, 5056904365610561965}, + {7637552956459333558, 2827449950719061527, 9998507085256853501, 9238562885525900325}, + }, + { + {13246436769495027717, 5445015753017977819, 16266739009580878036, 15566606095998238977}, + {12196078605380432771, 4854324313875295137, 10974170498288217052, 6425550765546527417}, + }, + { + {14574824159194628650, 16992289415800830701, 3499062703303067574, 11220872042664151226}, + {18135860701984580530, 13630928571014923388, 2913126838766947469, 15869180955632349704}, + }, + { + {10621010745328025245, 14637275395423748577, 12928463178963493980, 3270672471462681194}, + {11765440832075775157, 8138439106739837848, 10004644076263261924, 12582897670868871780}, + }, + { + {9605391611675301152, 14014632424042523224, 4638465078692570733, 3013469722048440965}, + {10972600060210514686, 4497572559400894366, 2652629676209366276, 15827846806499715082}, + }, + { + {216774559418075105, 7056732230404238374, 4342481467357759950, 16143194646968227790}, + {12304857685680249595, 5021239809847286634, 745754913624924064, 1603290801266214539}, + }, + { + {2784418922013631805, 3554650219010546629, 8896448905401216908, 13445015286698819482}, + {6508982623352460996, 3322529327934132311, 18417788670080975365, 17554108945303789353}, + }, + { + {17620122226715347133, 9738429733440215024, 15577771434516492888, 12422193389576942718}, + {18383756008252443605, 12736926759685644351, 16981429110294392086, 11999528928951986433}, + }, + { + {14489177617081844909, 15995916840320959685, 6361381313838994395, 11146176143708648759}, + {17190512001934479207, 8406914945663974955, 18073221191428103088, 14075266763636071788}, + }, + { + {11493260321718935244, 7134447477334726345, 10489281872281557152, 6145540581503915475}, + {4002857892747271740, 5167943945955725680, 2892864850826359384, 16887114279977647596}, + }, + { + {16493058314197913501, 14642843949567816202, 8421201635021034279, 3645913604138483317}, + {6127272877310948153, 3660286308390076870, 14343325047340052700, 5355450922054278073}, + }, + { + {8426383571761073988, 17627146217941553397, 7396223609641674418, 2402241526082789613}, + {4067059813672963823, 10306840429023537942, 18342506396531908477, 7249869764848707701}, + }, + }, + { + { + {13937553904380032591, 9165760362893872288, 14159606902675650669, 7794101517494576908}, + {11994596892880464164, 16211278212275417034, 1568324133241165712, 6579463633356173526}, + }, + { + {369660229032730089, 11851915833529805698, 13485269529443969890, 1270120511649175022}, + {9128783725626301238, 6173048611666804214, 14151404531169195672, 18241008099921643437}, + }, + { + {16331025972320545471, 6852381640421896437, 9324740413214863495, 15718339035381717722}, + {1521756232012903545, 5431459367124818841, 5364830919043042094, 11104748870982011750}, + }, + { + {16226789363155700046, 13734705589524056856, 9629995513492843231, 2636144377026081617}, + {1233405076007260313, 2119672919365858964, 4932766292290315579, 4185117177904214366}, + }, + { + {6556637108078954923, 854911879338322327, 17335608616262058670, 8212786550755149003}, + {8111194132924193031, 15689965289081013375, 16641361924274000294, 13131032775030004856}, + }, + { + {8653575060724839982, 11482527594744353256, 10837608928215660048, 3651629796762058243}, + {7098570919231943894, 16903422906687575782, 6449467519885582678, 14455694979526406871}, + }, + { + {781149662684377075, 9606778745577048892, 16642923833572014687, 6804945833779567806}, + {7749938807818369385, 4119995592971432914, 17172069782410404367, 11558710124840085255}, + }, + { + {16996170392430604056, 2476294162951949891, 6677439492116109133, 1649550562276235959}, + {7307278264575968221, 17128676264244010843, 9768062299436691373, 3825325732056225433}, + }, + { + {6593955722549970555, 17069122731812152854, 9033349482403834703, 17728559655579364768}, + {16586780540128534825, 13307658170018069777, 3129405955501687685, 11183053750385689524}, + }, + { + {396019325068553604, 11523268935121791712, 15099363117146465288, 15263791092270534216}, + {13442484747453660303, 9234120847672647934, 12419564747087042045, 11765927783051357577}, + }, + { + {6946885342337567475, 7614129273290805579, 5593360004251714058, 12661112521307810378}, + {3109170497657341517, 17179338146382046416, 10757457188650866858, 6777926602245453235}, + }, + { + {5861627228365499618, 5011684805137210454, 1579621475012951778, 11535371650014354624}, + {12847902922833318241, 4997014846790385136, 9875988184618650628, 13094082946822736823}, + }, + { + {2372542806512167707, 4770713673953713652, 14348746494327256696, 7497346441434630132}, + {8937635379675246570, 8485257033326447249, 9021969910533595955, 17083952234675640995}, + }, + { + {15253158548483712314, 10967825792345015198, 9742716807127259344, 14359543366972625129}, + {6622650705673586588, 10738437674137632549, 1628663686364470696, 6788821495127737255}, + }, + { + {10456049238997614164, 3762844951386993276, 489305084297229810, 1360312650067674972}, + {11869321173985817492, 5817931657599210177, 16741327479242559412, 1205037582258757668}, + }, + }, + { + { + {7109145612337154341, 10502845970727626855, 6527587047878193251, 7049690136888681718}, + {16750703006415156202, 2559311261501721445, 1222802194566919230, 18019462938525560766}, + }, + { + {2592184418896595488, 1723751460114310463, 11198512454461769811, 6203707848404803677}, + {2601731234271436477, 18186700975610533226, 4757569424831899615, 13359873383138312209}, + }, + { + {13904640252203718708, 10747313134117021792, 14667070697514384141, 2600977347774743546}, + {15498986940124021079, 14740645313274577011, 17403811028932224808, 8060102076475954685}, + }, + { + {12990649636107730851, 13002224935892458030, 4380799638612122791, 7935443787987894924}, + {10438069978940053126, 302419699431148366, 551508078777729872, 366155636877501719}, + }, + { + {14734735764746786753, 1378251478826083755, 13509550209468602124, 14458158239096821346}, + {5681313138148713219, 9054039627425609375, 4235536482830620712, 1502753755874778370}, + }, + { + {8914021876030553161, 9071747156187788379, 14974736924255494885, 17070198435868341999}, + {3643991391224035758, 260637732328275649, 17609644917816078225, 2302996326941944665}, + }, + { + {5888744936142942064, 17277140802638358763, 10290028650289820825, 1940657436863195045}, + {10796401239257150661, 7788083050548605852, 13474393003015663489, 8961936186303685357}, + }, + { + {16407225233842256953, 13423683834633513951, 17454464203550700633, 6033758555290610449}, + {5063673994339442907, 12250392784929419939, 5954485814444410119, 10099095370725442279}, + }, + { + {4687621216548073298, 12683256962895584277, 1406415612737291460, 3991320149877222007}, + {403384179417053146, 7072351635192146705, 14388831570324308780, 2518546598792352745}, + }, + { + {2866701220158780648, 14345701180700655413, 10383205903323525163, 14561034237887346332}, + {4525630512028460468, 7470042867870921036, 12498636959757093905, 14959680069767374094}, + }, + { + {939355076355747784, 236998652239230884, 7862332576114728232, 3008745396212765985}, + {16892515157128448879, 1688671543548974140, 582235491724828261, 2879861045707356356}, + }, + { + {5793581539270397654, 12067972155882240315, 1914416028486337582, 2044052608129533771}, + {1045680055817519578, 6183307954634642810, 1115903654002488241, 9729229622559998051}, + }, + { + {11505233554542243613, 13650372171621554098, 11886401428750724176, 2616122636264787282}, + {9807875738265530891, 2065326856613209663, 3841177149705795822, 12478836916087572836}, + }, + { + {8725096612265348131, 16959754534248500306, 3934616751368449170, 887912345061829880}, + {11410178859948957868, 12867384504930748729, 4367798270196663137, 4359910421693489126}, + }, + { + {18221589825782480868, 15875305463032670629, 1054133002549446970, 2220911650204683784}, + {10874691797030180071, 13903803155513130100, 14873882741737344436, 9374498718172057556}, + }, + }, + { + { + {4471613312912718060, 13601785177495103328, 8083849806888905297, 9053545412554844461}, + {1876605639999952155, 6124537911475118673, 16877891074567085688, 16541720065079132344}, + }, + { + {18138305348849897995, 11498878557125400853, 14125346336359365201, 11991638807788804369}, + {13935355764550912568, 16209147067155729660, 11086190285777019292, 16727288863943596410}, + }, + { + {8873152377611229668, 6260821826956744083, 11489383533808918262, 6585112195310961861}, + {7365821041919648819, 1936165695028211587, 16164747634991415711, 17957320776652490392}, + }, + { + {13065030057172289846, 7278765836407486850, 383827150208081081, 7832055893191054601}, + {5249323286889945617, 1631661912887095912, 4431088469837785451, 2866263172993336891}, + }, + { + {6140213328062333551, 16704025329777067037, 5839832043209342792, 9196354634862869885}, + {2735762290983671190, 5323501742548818139, 3199127466610501482, 6719610946615763192}, + }, + { + {4032564124345275293, 240208626666701335, 10264845378648897042, 15608289126091352415}, + {17866864241918154829, 6207477318890336372, 491708931325462670, 7002400618323099260}, + }, + { + {11507747783030541234, 13683043390668171754, 9924966309328785763, 5549516466627385909}, + {3724001483041449858, 2408778220985427590, 10510707601023430105, 12862520912519186496}, + }, + { + {5012372868660694231, 12033652755433827667, 5960732801180177919, 6089487525155575261}, + {18400192045204062277, 12754175136438960528, 6170965736016609163, 10141374482047067946}, + }, + { + {11781193922347227447, 16937876011211881637, 2982972111293427964, 1728244726890919596}, + {3327997232304084768, 4754833121145407334, 5871027825507908591, 15772493911709624273}, + }, + { + {5862944033912881884, 11132730978666088350, 12167180155548291888, 16449838286695349787}, + {14399676610730016345, 17071083123672650337, 13727728787831175379, 7507765123422748291}, + }, + { + {4883057314704644529, 6606742732149784343, 16070555141087563722, 8408294891669305261}, + {4298316003054547788, 1573237855902568238, 5357176885445018289, 5855732582172939202}, + }, + { + {11721126538980357625, 7216004194033429913, 12765889884935948315, 6003399149613653734}, + {4571046290325663920, 15023470461830485075, 11463513436288928362, 16135217522406374542}, + }, + { + {14300855104129153291, 11491527690078786162, 5674183453812271017, 5044682546652747711}, + {9153978680942338831, 400454762074409409, 12351470849648616331, 10559229320903248832}, + }, + { + {11839166519633311143, 16489041153719856002, 4820713204385149226, 13768001962143023630}, + {13107713406478328396, 15471245828032402460, 6733652296473831544, 7665657127090105428}, + }, + { + {6114372925011600760, 13061069979571997963, 12156991017966837826, 12403009591138383583}, + {5761958709898299258, 1907771304051897263, 3007439379929412593, 18410854883912163962}, + }, + }, + { + { + {10153847769616409178, 16591913677701651064, 11369151065084080884, 9493662847124813178}, + {14299126668179023903, 2451525064998641745, 16055696673728703463, 7600736037142850105}, + }, + { + {3339871688614476269, 2937156932445032796, 2071344655111136329, 509603454456841298}, + {10929109734329673813, 4531629375826317764, 1802431569220697099, 7971315018970882891}, + }, + { + {831440329504272059, 17398063681351066636, 14954668702259408996, 5717183520144440084}, + {5683898996859918421, 9613688159291425744, 14476049487507222229, 3689544236835488368}, + }, + { + {4307546666223047416, 13914498777427309061, 6812156124789414732, 1680174913762530491}, + {6756325174405757110, 2535144759174364990, 11263393915003278429, 14767595249676286403}, + }, + { + {16671897597823309975, 8846923580617118936, 16420413907022376284, 2344779928765541883}, + {13727655669851883280, 934227091954463432, 4722713881950047653, 11812583008287470589}, + }, + { + {5321392406277114518, 347488367118035707, 13877286915167943316, 9829617275563347891}, + {12220860524024630629, 12190721936758412489, 7308208895364574537, 1525158119497637419}, + }, + { + {12984508126047021344, 13884472939864196037, 7382834581395586970, 11638480609720520178}, + {3822030693056621440, 16565826187005934945, 8411123762207988382, 1177726217844912325}, + }, + { + {6981289090623415465, 8930069945493884157, 8223216504978132408, 796477795300774057}, + {3120155459209743472, 14825603392456550470, 3711879425019804830, 11041054473536223927}, + }, + { + {6533202055887887500, 8435346764005128028, 14910943752455571727, 12906760590440667071}, + {6009159206340842586, 15232286290711710102, 13101554303130256987, 9535887764075322183}, + }, + { + {2364828287094520952, 12465747625792776806, 2520175043973011525, 17224593222741233568}, + {1891958595100476046, 14167979679885431508, 6587293950576996181, 438078840840804918}, + }, + { + {3740623254035318453, 2026091438664349886, 10842473205058238690, 5471257179527938221}, + {7725900701946760330, 2830662433803069280, 17799722315873409980, 10759084277615005300}, + }, + { + {14135544350792474553, 6171419888118563156, 12495035851387242130, 2843310747449412555}, + {5668766087526340552, 10117858698838396246, 5181027414039980750, 13247490124270426}, + }, + { + {5630566354382744149, 13019515676216329576, 5170054423571001981, 6980215251505169036}, + {12147009277250683724, 5685374899516102781, 10470553909247052379, 13479624060240397189}, + }, + { + {9352291669847160009, 8941401423217216209, 14488820078509299610, 16185610851702419585}, + {11995025321082820298, 8447817180287020945, 5861763576711981236, 14278368152612939946}, + }, + { + {17266177108677586607, 54295173557875478, 6565771227548453510, 11327083086584790599}, + {2516266639353612660, 16450448808532150212, 4693041555468884719, 10262468795248362309}, + }, + }, + { + { + {2365455792963674834, 2249234228455309648, 5237136544555745182, 8814246419234451463}, + {13017813702607013347, 2241193992640629733, 17982226236989862510, 9800528153239873634}, + }, + { + {17271890190678399664, 284117971978206043, 14999643475704678808, 6264699496666119083}, + {8859934981351804429, 8300880062060532031, 3667839168820458685, 17133003164910522197}, + }, + { + {17791633957402883820, 5938849497629314459, 8356801465373786047, 3163889445599730677}, + {9723709910898285412, 2841967670768995554, 10896757438566636700, 7434996874241771203}, + }, + { + {14086272070125896854, 12009239107306499026, 6592816798466831203, 11371087141421707743}, + {16277593907837607793, 16449564916599232060, 17471042072158213549, 11953382410698485455}, + }, + { + {14613304240735929191, 7658770973133328064, 3028731168325633068, 1486737152001467114}, + {16715835021406106944, 15214200823642287507, 18441898204110447697, 5669963154424393607}, + }, + { + {8381651800836461905, 275661552864412688, 5548629401959193001, 7174991431295718071}, + {7441251258233899268, 14052832476485122412, 301250917807487282, 17797202428295526090}, + }, + { + {16448089571044203401, 1396460397790470601, 9796571033221459545, 8162511506983092708}, + {13893406727199803081, 16188892369453405032, 16023105002157964343, 7061289566170423383}, + }, + { + {8743817608749172620, 7804846024944300667, 507107926259802795, 5258061329638283805}, + {15071070675288472598, 1848743106176521296, 16295570828486620412, 7409462376590083349}, + }, + { + {2825832734356158434, 10662490421734807455, 6363563030616301959, 16552149102037287266}, + {8852342875874616869, 16848248230809388411, 6581680050166700198, 245046966305064563}, + }, + { + {7828655274510399422, 8354801505584011854, 17818478328917068523, 17325245990806811268}, + {750899848242404370, 6729023687199559366, 5406329621088392947, 9196565205678366888}, + }, + { + {8064539304829538257, 6441901327220658696, 17278408443193767018, 6094106832683864460}, + {9824329910822370076, 5272517980512991724, 8211352561755619726, 16303987070546290759}, + }, + { + {16798983177239698753, 12189491924433050580, 9517619110936281609, 17570406314312177597}, + {9873809692789257777, 7539953961664846819, 14652839873293130968, 11082914471633564328}, + }, + { + {5471221015674785794, 8844747884377425274, 10084666525179707178, 11340747033059217003}, + {7295797213045550755, 8395678759725657352, 9654316500807954493, 9062353099996695484}, + }, + { + {4588282548354659427, 7317148840331807496, 1344326657487996813, 1542409176821028318}, + {16178223850158437787, 14916858636047869579, 13512744779273961596, 13549205429423761570}, + }, + { + {12307321769285447055, 293357554223804370, 1007020265087773203, 701738899338647839}, + {12276634770118212432, 14777553112070534726, 4541693432120405052, 9103025487888313415}, + }, + }, + { + { + {5757832545805155636, 17609080533053427627, 13855662030602089892, 9622498683452213297}, + {12281586442064581946, 610529441714948581, 14740357477019436626, 16983190111725558863}, + }, + { + {8470173855499872166, 15915210069852758660, 12368087246231545517, 3867174158581293223}, + {9082358201271846042, 16663463402757176964, 13740908859955866819, 7748969412274962298}, + }, + { + {13375424826931892789, 8508645806391261552, 18359272328758476903, 16433208398005282080}, + {13071423254987294580, 7999383023651164492, 14514701556577587750, 4848295889377673720}, + }, + { + {1020519568493754982, 10467781020270669620, 17607771250627508499, 6620300538436640218}, + {3858527175523168333, 13798129597334232823, 12495322651937391008, 3926713306087152023}, + }, + { + {5116038770086590715, 9943789276328255827, 13715439407309914230, 4887040860130243503}, + {18288477612078228131, 7640050573721350378, 14537362862524718973, 1658575506924200900}, + }, + { + {18400486168653423966, 18026904540891591040, 2037921821724043966, 18010956304511658647}, + {3751340308708032971, 16275459031633957091, 17177866831427164840, 1635431811339422016}, + }, + { + {3897330996014812355, 14347736534650088376, 16862404119462964612, 12216005411754788835}, + {11561909516001453735, 6261639657930189859, 9101978764314050064, 12280333151331067982}, + }, + { + {910276569977357717, 2872810615152156462, 1942106118995935911, 8734004121981822024}, + {13862118436432879698, 1912639548162720505, 13060137938875924732, 10642216911059510120}, + }, + { + {5132232031613377471, 3053931945527415993, 2695169719602504430, 11855046366025891084}, + {16462491222215366712, 16664416596202206835, 3077124688577987843, 7109495326459366311}, + }, + { + {3858762384693274897, 7520194928987242278, 4496744297661574884, 16159343214247089321}, + {6441167128044578145, 3604951495694157848, 3072075325567814428, 1964798869371174506}, + }, + { + {13689578474000942304, 8998724267038772595, 3350174507425430811, 15015413657749135511}, + {4848907595494161497, 7935644131326131098, 385849363817229511, 10087353746314516691}, + }, + { + {6067717601858189468, 10438404859927821308, 9991403870358837471, 17728358586134467771}, + {13476949968946830198, 7311235997042381570, 4429835371823736972, 17463216455983091974}, + }, + { + {3446799583712077997, 6763499387263152328, 9231082163128267527, 7733182914440272884}, + {17225092062157610409, 8163842076250628108, 14230171836718858439, 8195740716303697476}, + }, + { + {57759226194841354, 14962480748390190557, 2047254208877381876, 2830450574091058648}, + {14905486147404440754, 15792397930637469157, 16383409053580142957, 8686506861607761226}, + }, + { + {11120178572139812895, 11534611317577597022, 10437856602660752754, 13925966850017814278}, + {16776862023867799947, 17362554889424346260, 3408825299914455645, 2606150045870067742}, + }, + }, + { + { + {12109367644744157376, 18037756988516427980, 814572839386760074, 913616818805172815}, + {12974490864633240943, 5228203788953366069, 11458421156905635350, 14534725545904442520}, + }, + { + {13918155529832261002, 12953608416498491778, 4285102780598248527, 15853935066983430239}, + {2610351403194505517, 14905969693015035277, 12043976761492019990, 3883507340167876094}, + }, + { + {5439519346074792827, 2176389624009388617, 2631244572392601375, 15049241095214776941}, + {16292195309463965431, 4379169091046493311, 2454237863606964835, 16333960950959567989}, + }, + { + {10994470105201067642, 16033352651464686189, 15774427704233149170, 4596106024708523955}, + {8854068685612048031, 13529126595187822090, 11509928293490788309, 11620850709434334690}, + }, + { + {267621988570094461, 10587206279243947181, 11593510291287574067, 14787400314862354894}, + {4136983718443464652, 2976380359687256413, 11142324903811863489, 4610908641771667701}, + }, + { + {296274281547444433, 3085587185113256560, 12609265193181717917, 4535801536028989527}, + {3096496338675531142, 9292526016029159200, 13112825412047135381, 16663099831183411702}, + }, + { + {2767353193349225715, 8712112934471091092, 608599382922156785, 4028449356066786979}, + {17542394472389324402, 8680897831809226389, 7666317335732585298, 17261030852301003617}, + }, + { + {2068337952936280662, 6856444059219131741, 17213926210819196459, 513413453513211652}, + {5520465604253824995, 12970886588014924605, 12296275668437451137, 16808287251356954962}, + }, + { + {15914937173048753781, 12510295026185206015, 15954705664179129326, 9689253582699600268}, + {15356442010394775998, 2438265211465631320, 15141425278420483672, 17026865278332658671}, + }, + { + {775118291486058191, 14811108570252044526, 1277462327112210144, 1303109520734915949}, + {17662756477349124684, 3447822852149651619, 6150341860560710757, 13223916277431807977}, + }, + { + {9324118164416603919, 86833914568469678, 16815316898277944489, 5015780480822908208}, + {4077581079810359659, 6644887514971920354, 4892606269782662646, 12780428915404556278}, + }, + { + {3413637388791433603, 16937929882486384885, 11215805046681294327, 11559398419268924015}, + {11697258172757450737, 6137795229387768085, 3190984692021653574, 15347236891154706739}, + }, + { + {12504195828868930633, 14311735968635225029, 3580069346315758668, 12909891866007218579}, + {10780120525711488015, 17942431687417272891, 4966616543136223651, 11565637729828595342}, + }, + { + {12013939709036934636, 4233656138400235608, 5744753585886244254, 7800398410233442143}, + {15609887409465530711, 11633197710359969914, 4221051249637072360, 11317958694020095179}, + }, + { + {5703670472856822602, 8043375474958283103, 2470834322231268196, 13020386017071254236}, + {13795230438353673114, 9108571599173545401, 10145331563807416240, 17474439008571566321}, + }, + }, + { + { + {16430555432520738762, 11225321696360643709, 11777973654353154098, 13133115227828884393}, + {17678738157022850345, 1586660156856830642, 840647763693221003, 8645742354464326466}, + }, + { + {3598736754916501501, 4827022662021197854, 8203180748141933720, 10283251600632599041}, + {16186680658340956808, 15183393398087319142, 8714402370450665212, 13217902016653171217}, + }, + { + {11743016372336018414, 6125536020759642301, 16563280170798047733, 14529052521060111789}, + {15253502329174644388, 1556763737841306861, 3041940064290508531, 18020881359462953336}, + }, + { + {2297585344913389180, 13965959247788377604, 11341378863608387800, 9890953382689640379}, + {10443523266835246852, 9631856696811288063, 6944503116553031744, 10030824122780966395}, + }, + { + {6636244234467769744, 18284390012667441869, 722929822219329257, 3274166388651987221}, + {13177791837760949480, 2568122970128111127, 3477167651270374316, 11371867850093288299}, + }, + { + {12876460969864886954, 4692925517843901006, 17390372170975588763, 14692578774429957295}, + {1759864963511373267, 12016553435172103063, 13015881292003590351, 16187569590073958370}, + }, + { + {5868176722765418764, 8429364877332796959, 7785756492654137899, 14975349488807886278}, + {3272010964035218775, 8946396491617515063, 3774503492701710541, 2113917870331282160}, + }, + { + {13276631120161396750, 16968574704982977753, 2376454925072971568, 9477134218094425043}, + {13784622991820528988, 2074505569780291922, 14294803056569335889, 8759684036994631222}, + }, + { + {9884417819806228161, 10473583853313294601, 14339795822328931094, 8504498283323826917}, + {526127293629665058, 10891388783681447537, 4568472708151557518, 10369081088106148862}, + }, + { + {14875690099724520068, 15708131372860771936, 15063351920655636623, 13673754555867312132}, + {15920462627529593070, 9885706734937065436, 16823591115242423655, 1258777215756511827}, + }, + { + {8202515950988182345, 14546423651242108828, 14227698061016162353, 10918615690964448766}, + {17106085332738434415, 16355746637376756806, 990444867181428081, 15553043817355146246}, + }, + { + {3823475181283510630, 10848691050793796395, 6491636971888772243, 757676231362735550}, + {8973136455980928416, 6503381298194573307, 7834237673135397878, 10787325521157907075}, + }, + { + {455211601892268020, 1552688795129565862, 8165081519906588268, 5446810663215253742}, + {6750786745561416995, 6997284811902307211, 16012972729607911414, 9114458230677816387}, + }, + { + {10975008541567105079, 3750365577590028809, 13516995106985748006, 8919511738051569176}, + {12930984911878205493, 14293252788401143455, 1989517604536428154, 10167748824687611261}, + }, + { + {4403033949751056724, 8371165401092074176, 4457099049748166877, 18160854660487137945}, + {18090711188318162626, 2052332783995780991, 10990843822512572670, 8096670640545581193}, + }, + }, + { + { + {987127652983079722, 6872208513691823695, 10110578719299008714, 16457381243184327116}, + {10779072738879347999, 5965282398006505989, 18251577267494363268, 9321323379108563422}, + }, + { + {6119049170407437179, 12938407708038792521, 10105420405825346383, 3416306788177016826}, + {330648587825212481, 125568991290568141, 13857127346570918649, 4376080986981308805}, + }, + { + {5930434126597036589, 11240994623469578584, 839346533006694594, 10015087329724081709}, + {6285097815938761787, 17244606485954860090, 11523249727882012981, 7178451948850151803}, + }, + { + {16733615335426327004, 14833564736134873977, 15736159435317472941, 17560193966711884894}, + {4670172300306758374, 9477713670983496835, 14243955354032737980, 6459864769649694970}, + }, + { + {16053517698989562256, 2069464650596796670, 18305730134729303993, 1090863611964008044}, + {10595928817546105363, 11743183506441120484, 8584767248013363683, 9187452830514379903}, + }, + { + {6938579711827578880, 16268282168771714072, 4567473305742437221, 754548046014059669}, + {7773636946295303572, 8132380485366854656, 5054542590195827722, 6074347500754248128}, + }, + { + {3955857908381474930, 11852678900999621852, 13783017203403417097, 13616745777931267488}, + {13189924588414196918, 14519927295809952876, 9334100965942760501, 15172548734242885286}, + }, + { + {4869852132020793901, 14921212823114724347, 14342559113353033349, 13336827701782657309}, + {11168346789878684452, 9790480725902426052, 9171116079841529936, 9268902731763220711}, + }, + { + {4417372365016540659, 17280138652899703220, 6650972319709075180, 11252221422799491438}, + {6825784270383052414, 18308562203755695191, 4237445205082731447, 8485872406483449772}, + }, + { + {11718726714045105993, 2624508790343569765, 5794111482300008213, 12819216567095091385}, + {285329842793152354, 17257707863943097374, 16912487373614458842, 9501952033607497057}, + }, + { + {13074643344738491288, 8505193022029238118, 9932652098552590323, 267408114280737600}, + {14802861246220332716, 17506028737327736269, 15929083591675282371, 10937680132245212187}, + }, + { + {16688733766460131050, 12777635326299184071, 7769405825716531061, 12435979606514844725}, + {2767987141420672349, 6723940414217341603, 16114182069580717377, 4541113259200434040}, + }, + { + {8506371389960537559, 18031198550689409305, 11510251852995503442, 1923472385053944821}, + {6189904387119195613, 345664413118550356, 6439003191582953600, 18344385760549575361}, + }, + { + {5320548958745018096, 8341561189829530680, 3327828110998403156, 17981346269177513223}, + {14254804273025688074, 11111147827704077234, 9093333670517437191, 7272552282364063165}, + }, + { + {7587268797387514088, 4402481408866840263, 11260815389095334885, 14391444701764948710}, + {4224880318604689771, 2472148458660279030, 961218007313548745, 13826356220879831691}, + }, + }, + { + { + {5733697799130763963, 962857090393715865, 10538932452511329419, 3413281437172590207}, + {6635428480179771287, 4404718679994229138, 329074170931436370, 17746708206910902139}, + }, + { + {179238781994802586, 9017860544212172426, 16179187983079961859, 1380105261896053495}, + {6187003332254463653, 9896593306091975718, 17181949235068293496, 6820143159816507763}, + }, + { + {4652378169433586070, 2069013165869224423, 13972912433480425078, 2248203233787863058}, + {12819880125496785064, 12462800229583867169, 7969192387226362512, 15450728326339004590}, + }, + { + {11156900805411912784, 1737275748212365168, 16993486692205800040, 12538938066475152524}, + {13167476167764338790, 17373319366642541595, 6054831428930905282, 7118452124011953000}, + }, + { + {15319323094268250368, 15751569639563379275, 9174762389399453601, 5359273060607997116}, + {7548480167962649047, 4093535200286790152, 18255003581953064302, 17037929372197430710}, + }, + { + {3640693116491518731, 9689920283410066894, 16070225083132083168, 13505008973802466003}, + {750230942699692016, 15522838682331888368, 112268476925002814, 17491605970126192984}, + }, + { + {16769567946241955549, 17099752525969374817, 14041401861628609700, 13883170585376164878}, + {1568639950869924595, 7305902646691031157, 12536573783075304502, 12490145094151973568}, + }, + { + {743288751022377974, 9226164090128370715, 17669221687181604232, 1117842260351396541}, + {17697784451833850722, 14382209306891991103, 16951372733687268016, 188390802712613066}, + }, + { + {7332583781810119624, 11974900502289827649, 9825039434151224666, 13612433455140779130}, + {11167094757836568968, 148858902984029622, 4325547061862811500, 8439987427904092212}, + }, + { + {9775040802880336170, 2183956155792599391, 10102475962557589963, 14902149990037881859}, + {7528893974593517583, 18271333130592009124, 11812759747597590978, 3931581515688264350}, + }, + { + {7368734173241076742, 12419301291748626639, 10534790951032501149, 16676926058266807225}, + {13614593066288445663, 5547469267128540754, 5071513241190976074, 6206141439571986364}, + }, + { + {13268209255833199938, 16633146482265079265, 6044233937395578074, 1733872861371247406}, + {14239198956565602758, 4036306057099495106, 1778912298053970082, 6174082695927204648}, + }, + { + {9563897475320169888, 3828463449263891363, 4522408683909966848, 10085044841903958270}, + {15115863363467748291, 3921763467143122522, 3241611744432406503, 16149166019569794702}, + }, + { + {13355027832202142668, 13259310595418810737, 16638224598838046396, 388655643128437049}, + {6131988039969669992, 16758867465997134050, 793705445085763779, 16225736542798627427}, + }, + { + {12060616483613851492, 11185023117529741833, 15286366164051065546, 5407795227432242447}, + {3261413161331398298, 7182873809282605970, 2155509494582452911, 16998725707829879258}, + }, + }, + { + { + {14380343880230315251, 6834909096379668102, 15975839936772635678, 7738230945027714388}, + {7971648870467745046, 8320128435052726628, 10820026056424631461, 7058118462476293754}, + }, + { + {11165438517321289842, 8661037418831619311, 4401480924846865713, 9355650368902126256}, + {14352422544185763829, 12268031594529744663, 17607497268577344783, 12698954426769962214}, + }, + { + {5091534986326281709, 8005812102849517353, 17366496686564185717, 3658878980438307796}, + {8455810244524637026, 7649393961871195909, 8629386422022530934, 507133797409068858}, + }, + { + {10098955144981013765, 4095621933458866623, 313357785962326778, 14880249056209398407}, + {10605627454111004262, 7841561005378789988, 5015399193497762029, 5818383539901203899}, + }, + { + {829322392873083372, 3459913121476606612, 4547714508342797986, 5801286056105229312}, + {11591136160675314269, 17965845487226778560, 7022309609363885527, 5990586084398664157}, + }, + { + {6288277991521986035, 12231480617236286340, 8633990423689180869, 13535190275290488690}, + {13419223868164389899, 17622732596713666209, 10071779220640400024, 9451660464882303005}, + }, + { + {11761084765182152401, 9226969173242076459, 5445719591917489914, 9371133174853825566}, + {18381867235964583187, 17262888224001222346, 1934253649802391267, 3574888052111089863}, + }, + { + {15270079546607712667, 8471883658965202468, 10333206241569264742, 7414741159725097798}, + {7709713706668701850, 4461310100162632915, 10099194304024685274, 4760203118683828795}, + }, + { + {784143359277603248, 15514589681861498400, 4131024411374659852, 3624433493936743696}, + {3251402229976672212, 4649659622203715244, 926933500763282104, 6444675794782453444}, + }, + { + {3756269038539504739, 7020323719189662644, 9035687928909659722, 10611580746254894906}, + {6310976205075048332, 11776014447017145895, 18193543588427463707, 12941703752632419110}, + }, + { + {13258346207952257162, 14737306929596267614, 139896257833059475, 5049568122463438631}, + {12260461320589066027, 46497756452454082, 15185750105748824007, 3681406295924007900}, + }, + { + {2833339165549332500, 18300762432878821923, 13251805801497937312, 17798840894981774941}, + {10659715417364364943, 9241413425866019176, 9144746556705463526, 18018473193185776281}, + }, + { + {7436336871105679313, 3718902224813103412, 8186181643677715434, 17182578567975462342}, + {659724975715028710, 9425698860660002856, 796351253238186633, 18323943433898241577}, + }, + { + {13500588337778130334, 15143039800006025480, 5471884014140775766, 8599189774825271733}, + {14063442714998210193, 17130659899212878144, 2181888550891204616, 13594088124987533554}, + }, + { + {16216101853436910766, 13302132899821289315, 8876723129840557561, 2026846371223185778}, + {7753254296964005427, 16607365864296868674, 1800351426181020953, 12473523172043936884}, + }, + }, + { + { + {14734199666349771791, 4159865781008764547, 4413963548436270853, 4489431649937855880}, + {2824856157476907519, 5111945927271461159, 9825486821405155220, 7657332565522279292}, + }, + { + {8798422177670065832, 1250388939918922012, 5145324733132743026, 3716299737175574168}, + {14387202892738514375, 10255681359895407489, 8563822744122397080, 18430417713920116013}, + }, + { + {7857399215288147901, 2593284350589299949, 10086687882410147351, 14407837835956327624}, + {4469878646287387405, 6845712208092605310, 3019047164798827279, 2760591274816994522}, + }, + { + {10930605176025081830, 5850835312463207607, 9603163404664606781, 15623771803942139684}, + {4096748595672894276, 13060617166821837740, 11222939712741281346, 18445178894593253710}, + }, + { + {7976335583419810431, 16568954524837045521, 5581116346602990350, 18369129318179031997}, + {1930478946186473631, 14255806344323769850, 5302512325798050097, 10008570767203424472}, + }, + { + {929118050943456183, 445163760697913504, 7208246135487165437, 13565354217377841149}, + {3835063466770003968, 8214155842021576753, 2078717035803259674, 12502657820500987763}, + }, + { + {17741004372977419914, 16320851348541958575, 11853008901690968430, 9954777341381304447}, + {14274892887030297417, 10721339848307167540, 8731332510371325649, 13676383433520290197}, + }, + { + {6251805914672095769, 1063060143452094078, 16647397170554915088, 15454955736319919321}, + {11509235104607349098, 8441647766544589978, 956121464218389431, 10752793912033728149}, + }, + { + {14879603883666664508, 11158422912437249402, 8667988090392051507, 12702057193823135575}, + {13234479167199208223, 13752955092077643608, 1117550756888145931, 1184967682872965330}, + }, + { + {7004802666964716824, 395433501626287206, 16674151908279399004, 2279551165611331131}, + {18032555740803644790, 3573953642384243989, 9892480504006025100, 2397759375236735831}, + }, + { + {15032723931727013905, 4176673226777913017, 7270920367565154969, 8867675920919464620}, + {8174119413251699506, 15030539680120439131, 12325981936900309518, 2932283844656871802}, + }, + { + {3227890727136855788, 10772277744280338071, 10065219931092397730, 17233706446636791341}, + {1372997838851103811, 14430098741859995846, 3290287064497023581, 13054133915521430696}, + }, + { + {3404625123065318735, 11884832674715736469, 16513753127836546671, 2355202492840722899}, + {2182039060332057784, 17942518439766613327, 16731345075928062112, 5501869092504492134}, + }, + { + {15704211025163561149, 14596679078416770266, 10262177146233936833, 12443005669252298316}, + {1541294166390346144, 2952804996209068760, 15358481016273272880, 1321729586231860999}, + }, + { + {6862865331233391228, 15106279167311639122, 3283008666555627541, 13405610967904725343}, + {9845239597399801983, 10764942720093673542, 6506992344666983370, 2483131164245259278}, + }, + }, + { + { + {9844707592410952215, 8167497709587672711, 18115463401502884199, 8471563375691441535}, + {17525405040226359165, 2460181803833371342, 3375780580907171205, 3024376384135966552}, + }, + { + {18138724984190926809, 4154767406604950048, 5209478936276366634, 15469512148904762872}, + {3613429290324777670, 12631812917445459751, 10280179062385049041, 19656860716268566}, + }, + { + {14203862032167128161, 13470939927320077756, 10327441827790615277, 10318573137694660185}, + {14560780313347476436, 17088464982837309355, 733937949060316950, 14069325810788446179}, + }, + { + {12030193727051241373, 13981191132445467472, 18205169646206905593, 12162181194046583886}, + {10929925499200074058, 15291772758590352491, 8452344520852919320, 8199821440451878776}, + }, + { + {702956275289752726, 11856189935311796245, 14185745521831658392, 4370665693013677718}, + {4339320942948136612, 7422618440224759582, 871840009976682819, 1758213746931263134}, + }, + { + {7463305936638691553, 10552402742907536443, 9732741351132553899, 194397927117005699}, + {12837197785265289115, 4412933472643099429, 12440864981406580998, 17072316007921211511}, + }, + { + {5025653014579399483, 6266285559889618786, 17667439302823084142, 8837073500207072384}, + {16230880878690171580, 8966359704103918073, 2671625161783975934, 5761959268140569579}, + }, + { + {9876482463501409337, 17331045017548147052, 17542726936580732548, 8299195336372136083}, + {12891767721269002608, 14062358772374813347, 4165127680073507756, 16350672737379495431}, + }, + { + {15987859092221739938, 10999006767011320329, 16931834873460681704, 40989027820989117}, + {16439290771012023473, 6900965556474667785, 7253680936177336810, 17240235510851599487}, + }, + { + {4114449005477323279, 11333071244606712260, 5639227616302034307, 15107257128889549417}, + {5046122977641767311, 17558812465185003134, 18137671581165086239, 4382776603153058089}, + }, + { + {18024760665596162063, 4581156045659391508, 968287218068232238, 9228777525067749703}, + {17309990917327276325, 7114941925430814300, 16735731670154258613, 6290532662018771504}, + }, + { + {7595271959296927018, 15286771623821390629, 980612661413312852, 5738158184597378995}, + {6972117550390447038, 6246497134979772260, 2935831443692029059, 12837371529160496660}, + }, + { + {10790135298802805255, 7259368218310211690, 12050916808246223984, 2030323364779525994}, + {12824594050397534312, 4098150364864727064, 15604500991562385767, 2831443658783115116}, + }, + { + {6469454686530052235, 2594644969515545140, 5284951626835069400, 14441180041267617906}, + {16001664398759990060, 13049178223054879255, 3268931999230968043, 3072360434503949622}, + }, + { + {4565530397071857053, 857029374864691712, 15955478286869670604, 17781316921869181573}, + {16457191703043818907, 5989113593649065091, 4425872606756635499, 4532030700973621003}, + }, + }, + { + { + {2317249352525369754, 15030797481081533168, 12237590576308284360, 15660076992611440873}, + {11341015819700735887, 8280257602754365719, 9212501234696283343, 9673375202141178099}, + }, + { + {9762534010701623728, 15349113802811029024, 8305297169667044246, 18013018210154476198}, + {18414050009163335761, 2190126859433916996, 5444481274452218807, 13415988647365667724}, + }, + { + {11641532224340210206, 71261001011952801, 2321745415903209397, 6595984444855093239}, + {10341299657770272718, 11529878689049370930, 14381510695605158203, 6869272773579747365}, + }, + { + {1073778278665127828, 301289653767944933, 11482324780950168317, 10626716202328004967}, + {7258024014655363102, 12597648090458567878, 2617914106162603499, 12324652644266476584}, + }, + { + {13957732574177025801, 1100344278733481546, 12156946932617203965, 2007756425747006287}, + {16454508610548016441, 18058668363064769203, 15619001054652658323, 1201476243910931863}, + }, + { + {16341334571424533804, 4657494880554316004, 18092783076286521475, 19832895869027143}, + {8667365497283429486, 11501953273367138162, 5832487631687776985, 664754160781757174}, + }, + { + {13524719886605363170, 11553593166914861649, 12034020205580665813, 985175984881624722}, + {11040631342644137311, 12107496606245418129, 7328748654066365904, 14741972847454326011}, + }, + { + {12828567388121500364, 2264959796189127526, 6222205589523394088, 8827682270015065013}, + {2619170858745203321, 14835030117099398518, 5960028394532808010, 2233397097850889639}, + }, + { + {3879642723354138203, 5439355518658448857, 14194463322012776543, 14947367699252203702}, + {11497182458118153903, 16347396442451668378, 16912659817226286851, 6972297461053626970}, + }, + { + {14953681219966965709, 18116944572750863844, 16774540053916392198, 6518998682436778354}, + {11207035159486725904, 17279266785091386830, 15987732680339874714, 4953887381255790681}, + }, + { + {18128055290529398111, 4838636144867908799, 17655818333374840693, 5013823741985131317}, + {1920449774281311783, 13898340137609808546, 861099289958274037, 12441596565887895930}, + }, + { + {7244015348755525626, 13520825180887535513, 9165067445392785660, 9250553550156732893}, + {15663564389384259196, 5724018088820370997, 11379531752316746866, 17687565409319417941}, + }, + { + {11050714794366707475, 12230144450501707996, 12363862313107363407, 6348205119671766380}, + {14263471584626838352, 7350100163762375926, 1902788311165167298, 11691126042005505984}, + }, + { + {3948847772791576201, 11933738159609952054, 15749315384347059669, 8831922078851474178}, + {8463496071867925621, 12756218686011120865, 4691766390469398064, 5252134452066688477}, + }, + { + {4880806069791899809, 11099088460364672063, 12627384861893315861, 4239079797011518662}, + {14560690935803003234, 15267325636353169132, 16919582304973803583, 10073876067858458517}, + }, + }, + { + { + {15695265447782578013, 15506558718447241194, 12341861439298989232, 18400958156300100845}, + {13704811286967591150, 5802260047239067846, 3266013253411255445, 9892957742319181954}, + }, + { + {6053458788987550519, 3243549259991905443, 17990025476026266205, 3918149716414968130}, + {562225565996136148, 12175287017902713154, 16317970834262634990, 5431198806775607012}, + }, + { + {15123186170178367264, 3054913246068400920, 8130663466272395280, 2852812622149318730}, + {6747630551931917110, 18302049774259156971, 3663865061939346221, 12340091610704678811}, + }, + { + {17453312277789785069, 1148609799196055657, 5931758962926317381, 5297597381576544508}, + {9136842287749269744, 3007653173299649609, 12364677607049679091, 3656932227466449489}, + }, + { + {17732801126130995365, 16093023291975796560, 17028512234142609413, 6293028118993952199}, + {4019599708379609715, 3557632583507755601, 16737140015288442165, 7041678499288317736}, + }, + { + {5187842645752673199, 14914432544387315508, 4944360914161982641, 4177329533692612281}, + {18423887817846407126, 11935898134550505219, 9191754399457615042, 962223885189306707}, + }, + { + {5467152559317256227, 13407023128339380091, 656806207084558176, 10823228592509573890}, + {282802378108427873, 13003319652664166176, 11501612671901244594, 8595770155487539951}, + }, + { + {1805255869285898834, 11676967700876044626, 3486630203654875772, 8366336693945605431}, + {17874084888474647879, 8803709150655606891, 680993178667234696, 1603785777136148315}, + }, + { + {3637712241808318043, 1673622542455477465, 14468899013751477571, 6607241816357171779}, + {2332200248940843815, 14077155355848738174, 17298155509321457563, 13624623885136011130}, + }, + { + {12550073596584561722, 13898852145577133829, 31360866049197404, 12629522544897401454}, + {4563446134761510332, 7272813487383198495, 16767195814334178362, 13600498026689482359}, + }, + { + {5170414136067325373, 10875290278133558518, 7331268231382198947, 4082234313337835514}, + {11725295114019619895, 6488017511603508543, 11399466652931338200, 2898113599278666684}, + }, + { + {7553418756944942759, 2324485560009697358, 16004009784734101843, 8345371056076551939}, + {7377284629098981027, 11049718262343754276, 8021605820736410979, 8175349759714152494}, + }, + { + {805625092558946929, 11996029844853502332, 1725029464967101849, 8189609560660709539}, + {10396089572662865065, 1756007811373736605, 7645529329516777410, 2608132938055260111}, + }, + { + {17014595621244604813, 1574499958190108567, 8684546755761322906, 9997538531915911005}, + {5652402150243592363, 6315865356369667235, 8687115108443972047, 12369176255146729475}, + }, + { + {5117004045853299762, 2238407612548002914, 12392667457861900490, 10614312910576266709}, + {6446577503758597410, 3767883614425995197, 17954966454260719539, 5233322901463099}, + }, + }, + { + { + {1081257522368061155, 16144982029632101790, 2280210790959566458, 5000326950136078873}, + {10441086845859171982, 5717080014740953823, 16816253740467637151, 5185838557034755093}, + }, + { + {3897734650128449985, 3892478283047854402, 153850176068596076, 4448963435449755938}, + {9911011406822436713, 6379744721342779297, 360324666931028426, 8002086405015565067}, + }, + { + {13662666854424521459, 17028614494600252018, 13372166182804100759, 8978661571842967509}, + {1689945315009228820, 9997133634912151808, 4070075534875432478, 5780712439158341418}, + }, + { + {18068291112584812890, 10288580446655316879, 16866690514199445805, 15458664010538199871}, + {17175925202246173890, 12208778610361755998, 927739404697616036, 10330183209424493139}, + }, + { + {4422872630455196261, 14815650254807917367, 9426346157598724768, 17764302665164113296}, + {9474027272970951461, 3048886202121388617, 7073604597785890399, 9516006646305083675}, + }, + { + {16541317581647968302, 7221753201217091047, 554497992080233562, 12743131795939254731}, + {6113032707000257613, 4448176364247161206, 738044254484725063, 3096942233684051465}, + }, + { + {2801392933730991479, 15502003900939246745, 11340323610824656109, 13690394827169426680}, + {2298413291804124677, 12243772219106809119, 9550327342593445260, 18354548835264437008}, + }, + { + {17095781462759061506, 13984950766342782369, 7038608479806172868, 7073471193601880894}, + {9212126909381119712, 15865851343492198107, 3874039137971369196, 15366505242302572319}, + }, + { + {10476508037395688256, 5905562397524931472, 15147896444621280595, 3856601647293477321}, + {4204909177546012159, 17515684210872904454, 12561834979880779760, 6477848309789627185}, + }, + { + {3226022509034031128, 5771385963704757771, 17861700165696478115, 14976034400726774156}, + {17945959497662269352, 6322288130414861016, 3008853024335853994, 5599925939427067989}, + }, + { + {15408448007738805625, 3855259080280453396, 11776434265478354726, 11784885919111239520}, + {8108981861486003291, 16553896039002150783, 5694423121092647200, 16414563259092889693}, + }, + { + {3235058267792568155, 8030551941244615429, 12851363585510555514, 9786973022560471711}, + {4901414898060251968, 13240438628487941170, 4707852389766057435, 6503805666511566831}, + }, + { + {1178073204986944698, 10685133932326477495, 11710162005310407793, 11019188929725710305}, + {16244991946372165706, 3272168887117805467, 15045747299972144833, 8155681972478369649}, + }, + { + {12308450869393289693, 14268794937571237354, 9141189178824378983, 11605207657904000518}, + {17071770108549330148, 11045960524457021256, 13807710432855107212, 8427718050873363613}, + }, + { + {16762196363426636910, 7316863360113205703, 7937998445095491508, 3946557199536080470}, + {16019910399697645039, 11522845950519380293, 2362453023191035102, 6547077716792082654}, + }, + }, + { + { + {5218985848865375996, 5835476376320976237, 9096499658845542933, 8952489298840360492}, + {16605895184424459659, 505731104315931813, 17784248872812610986, 4151555707609374291}, + }, + { + {4963953120977916566, 6585250545846301109, 4490972754776862709, 10674499592300479120}, + {17494988318349821345, 1814042777264686189, 8938395423478059768, 9062966010283426056}, + }, + { + {3879469818714011415, 11493820457829716643, 10091807027724827301, 5032134849078736052}, + {18015749204009276046, 9667758283246223357, 4629693773460610802, 3807196436109718946}, + }, + { + {5724217930909760221, 15420221591912350415, 9910465013739250802, 12511683773790779491}, + {2841532862707547306, 16614426471009646589, 407574220261191228, 17422057170120224031}, + }, + { + {3725101809714764432, 2995111022132376824, 9338883729618021504, 8824923738291347476}, + {3745497072215538317, 3576446898425965872, 2350077748663612773, 15793255155885543355}, + }, + { + {12904339001067417585, 1972265247859388742, 8908590936681392405, 10320719400504224158}, + {8298368064038407143, 2105745729886511647, 16509751074757847095, 15156289751671616565}, + }, + { + {885617946245226760, 17871561572095909264, 16413308527330544768, 2938750343525834336}, + {6332736376778563648, 16772687696658236231, 9760470695949399178, 17420556823805232882}, + }, + { + {4407657041250297528, 13832960959347315977, 15056546959967740939, 4350443362134191429}, + {8013419913016572733, 8888684099801298477, 15401479253620745715, 18279947201669400847}, + }, + { + {16774767206504477529, 15784248755460218800, 890363416232172440, 6798249980336291014}, + {1295939576916968887, 14501516576359061383, 5181286196215569291, 8884842683907072200}, + }, + { + {12906144535917740163, 4179201185048577793, 8949647323841299627, 2168773816567792706}, + {1715683170634778607, 9901501903322086192, 7624633731287546358, 10530124063631858009}, + }, + { + {14199956317346734484, 13250211595320054421, 18197952479293091552, 16161313407818957084}, + {17435507292968186894, 6560268436714668609, 1299607057816966726, 8157462320016248727}, + }, + { + {3603583288706717651, 17387128326071547512, 17907604816622771553, 17853094381965037384}, + {12273843852205811233, 13840584476006398280, 2018654168596055410, 11549248055135584644}, + }, + { + {4742377140579111706, 845465928037625085, 12028953960657292824, 16438644767032965255}, + {17377088622232632294, 1631558517096568450, 11363064014018667511, 6006029335296807862}, + }, + { + {8877393780281438935, 9848923171251074575, 1554975198005028643, 2251034043951525516}, + {9696558687758873050, 3889942916226212472, 8326933892612496812, 7463785348361544799}, + }, + { + {4205364996189816688, 5453611962777060261, 16993840011943171053, 11689161310506207011}, + {16699173739044458906, 6254168288000491517, 12642281218300963313, 10028950653175051753}, + }, + }, + { + { + {8784043285714375740, 8483257759279461889, 8789745728267363600, 1770019616739251654}, + {15992936863339206154, 10037038012062884956, 15197544864945402661, 9615747158586711429}, + }, + { + {9583737883674400333, 12279877754802111101, 8296198976379850969, 17778859909846088251}, + {3401986641240187301, 1525831644595056632, 1849003687033449918, 8702493044913179195}, + }, + { + {18423170064697770279, 12693387071620743675, 7398701556189346968, 2779682216903406718}, + {12703629940499916779, 6358598532389273114, 8683512038509439374, 15415938252666293255}, + }, + { + {8408419572923862476, 5066733120953500019, 926242532005776114, 6301489109130024811}, + {3285079390283344806, 1685054835664548935, 7740622190510199342, 9561507292862134371}, + }, + { + {13698695174800826869, 10442832251048252285, 10672604962207744524, 14485711676978308040}, + {16947216143812808464, 8342189264337602603, 3837253281927274344, 8331789856935110934}, + }, + { + {4627808394696681034, 6174000022702321214, 15351247319787348909, 1371147458593240691}, + {10651965436787680331, 2998319090323362997, 17592419471314886417, 11874181791118522207}, + }, + { + {524165018444839759, 3157588572894920951, 17599692088379947784, 1421537803477597699}, + {2902517390503550285, 7440776657136679901, 17263207614729765269, 16928425260420958311}, + }, + { + {2878166099891431311, 5056053391262430293, 10345032411278802027, 13214556496570163981}, + {17698482058276194679, 2441850938900527637, 1314061001345252336, 6263402014353842038}, + }, + { + {8487436533858443496, 12386798851261442113, 3224748875345095424, 16166568617729909099}, + {2213369110503306004, 6246347469485852131, 3129440554298978074, 605269941184323483}, + }, + { + {3177531230451277512, 11022989490494865721, 8321856985295555401, 14727273563873821327}, + {876865438755954294, 14139765236890058248, 6880705719513638354, 8678887646434118325}, + }, + { + {16896703203004244996, 11377226897030111200, 2302364246994590389, 4499255394192625779}, + {1906858144627445384, 2670515414718439880, 868537809054295101, 7535366755622172814}, + }, + { + {339769604981749608, 12384581172556225075, 2596838235904096350, 5684069910326796630}, + {913125548148611907, 1661497269948077623, 2892028918424825190, 9220412792897768138}, + }, + { + {14754959387565938441, 1023838193204581133, 13599978343236540433, 8323909593307920217}, + {3852032956982813055, 7526785533690696419, 8993798556223495105, 18140648187477079959}, + }, + { + {11692087196810962506, 1328079167955601379, 1664008958165329504, 18063501818261063470}, + {2861243404839114859, 13702578580056324034, 16781565866279299035, 1524194541633674171}, + }, + { + {8267721299596412251, 273633183929630283, 17164190306640434032, 16332882679719778825}, + {4663567915067622493, 15521151801790569253, 7273215397645141911, 2324445691280731636}, + }, + }, + } +} diff --git a/core/crypto/_weierstrass/secp384r1_table.odin b/core/crypto/_weierstrass/secp384r1_table.odin new file mode 100644 index 000000000..338e7b9b9 --- /dev/null +++ b/core/crypto/_weierstrass/secp384r1_table.odin @@ -0,0 +1,5969 @@ +package _weierstrass + +/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ + +import "core:crypto" + +when crypto.COMPACT_IMPLS == false { + @(private,rodata) + Gen_Multiply_Table_p384r1_hi := [48][15]Affine_Point_p384r1 { + { + { + {3349844787980918824, 5700721700487043153, 1581288787708942329, 17304888540980539863, 3234495129650039747, 11694852976059594522}, + {11454526365474276483, 17280055605583648274, 11483041770187710052, 15064860306174908787, 9425940298043390756, 7831029453110477537}, + }, + { + {10854210904801992286, 8255439613636595718, 1316348857406525596, 2282633625581246438, 14438173431932387987, 5673747503677604393}, + {8960903665589529841, 14030078906563026478, 466971755747792240, 16909751879911376491, 8261483486653352128, 12597935804442306524}, + }, + { + {6447508696227153408, 2759028665179735381, 794515856920409590, 14869397668262921446, 10588017418631076914, 12633095840797167228}, + {6607496461698970477, 6359006165521880122, 16663268705047656412, 18219762716186036953, 13315075775889493847, 6546871415552527515}, + }, + { + {4250815476678138550, 17073439466111852958, 3750529698426925825, 1904641224225602431, 7274009899457528107, 9209596034767199086}, + {6863361867383511223, 4099555040981761624, 16013520265914987211, 17330863835225155437, 15236683723773407531, 9886066912739647523}, + }, + { + {6548020115141006009, 2051287398488083721, 18013217855858620214, 17512108880758082211, 9657257807517110121, 13349423389223700059}, + {11448378503671870177, 16607356707891652776, 17986139470446831883, 2256897346286898360, 7779521166731257394, 14734261666263853530}, + }, + { + {16451156334851086799, 10433346012762661878, 1154088382826340721, 13920053107889463035, 12824812460638933002, 5771020232226448223}, + {10182053156369870491, 9953188423679889138, 3623574174398550414, 6539131418856354537, 4739863922718165110, 13968548469751179186}, + }, + { + {5057596744164756370, 12108644536263189339, 15628783732405749711, 9182850460131890127, 7755150145219327164, 12512487145101794871}, + {9783765255428637296, 17231411912625418137, 3031503376230558613, 3001321323125863884, 3711029936425287900, 18364899108493632271}, + }, + { + {4364170143483158168, 3837420327812895040, 11153877356291905762, 8627127623255240713, 10258093926722597263, 6966392554053872709}, + {13838494481389844004, 12447754423026187562, 14673290292701904554, 6888547195036401202, 3349351868797716527, 6817319933710697746}, + }, + { + {18016384373848540113, 7565820187757705205, 16185660972256070888, 2502822820839506307, 3880408517672548187, 4194119666426113160}, + {15694892319489811154, 4832422690840974597, 900725859486443418, 10265913502031862890, 1864821221915885738, 3700988259937570428}, + }, + { + {8488064655818993057, 13159008538953946469, 11028809874392449897, 11486244481861659915, 8569628704299090359, 2892252873674546430}, + {2941671072611665985, 9930810186813308033, 10852463932839803129, 6122756170654615426, 13303416592882569572, 6113713156059966484}, + }, + { + {10029451401870245184, 17181275891609445610, 1563464611048571891, 9249056941485261951, 15488363863106956591, 17426032626929358463}, + {3624362630716884995, 17733027703464349615, 12615837230382222165, 2899993379581625588, 10641197672343453466, 6876651786059986401}, + }, + { + {12941176093218387209, 18012784992688854716, 17630514364742901970, 7489207242388660276, 3300101790738216151, 165750267447677843}, + {17420203378203929547, 18429168937941287247, 12685766409811315467, 17062737254687688913, 11583537930945240085, 374101281300528640}, + }, + { + {16294845494152982505, 7182435875615992692, 3318017447157242087, 6087688366366383495, 328984259793137604, 14904070120287703952}, + {565244652741101966, 4951466181341698004, 11866318921579101416, 6194578547220221350, 15631557042652121752, 10545898140965819968}, + }, + { + {15745305462398415447, 6816971438675772065, 1075554629877262698, 8234899837982726223, 3512560196005219004, 17693290669008338152}, + {14638482525770633011, 15865918008670368297, 11359271142073926365, 17074664191994857570, 15613938350520725613, 17352596771318223922}, + }, + { + {6627628274763979245, 6430867977390741183, 16640991507592485950, 13915161472308593069, 9005635619537074355, 17136188005588780957}, + {6349032855227933129, 13790585653547635104, 6107878840283566203, 17101678754123509440, 4589529453987745844, 8778990861876837520}, + }, + }, + { + { + {8752339740764879889, 17204670892025727113, 13948917001537480663, 6015237120129105404, 12568825630768815527, 17098885903057916524}, + {3196947359408104404, 10557260209896054933, 15941743809901771731, 11319635393284889026, 15404036538896402776, 1823888675766330133}, + }, + { + {469276640564380241, 10942708362323945260, 5172129155405724574, 17521202989307779782, 285237824018528197, 14755519896084931015}, + {13450199151338167480, 4987469637889591012, 11072253743028383225, 4126494248833488207, 10403393469323319433, 14468451395906602570}, + }, + { + {10409556101848104492, 2312052479304391304, 8367833927637255749, 12718782815503837000, 12586549663603169139, 10099896633356211470}, + {7897182246145608734, 6279866437607856313, 15077509973591020067, 1920596236429885894, 8944171611482738124, 468560753431799278}, + }, + { + {14398196793687807397, 8276491336766244001, 16962771698246445022, 8043838882426521864, 3609036178188456346, 17961572587511875610}, + {10659300691638275682, 12905326140192521229, 651286293824175704, 6550291910155090287, 10359196978363721745, 8054349679302352396}, + }, + { + {14267646986135279321, 8023233762563366251, 3277224320191152598, 2431726775717059350, 3733051418604042579, 11078740418949781682}, + {4641466211631370887, 5972034612476576125, 11061332758238937654, 565694857032650296, 15196808723752961845, 5493285531974069465}, + }, + { + {18369275680877034088, 3644498253900435800, 5207654447363684810, 15054017021149325074, 13441959779061156291, 10801557030657187731}, + {5488228865522937525, 10042916063344664944, 16628991126352116102, 13399733271269739520, 7919096844168308660, 12224871956968387142}, + }, + { + {9406504212815497730, 6315084170282838751, 1538052392585176449, 3287788394884246045, 11684015502339439334, 774607932742351547}, + {13523687029812911694, 8970259436187285903, 516344689739437046, 8879385705799553570, 15472954217075584115, 17165612419994903190}, + }, + { + {6153906285028789904, 4881581827835548877, 9088581243877761387, 8673828452274153145, 3729691157199039232, 14763971970770720159}, + {11125946843031387253, 16893034180060177406, 11028878025260215404, 13414446456552306577, 15673952559920934625, 8227747155230402213}, + }, + { + {4019194246965870655, 15651844969361453739, 14943903262285431608, 16531569415823118894, 12811244602177600058, 13239818034282515750}, + {5449698701210370930, 10791866857788139766, 5646650868879525525, 13293667095645494023, 12241262662724597658, 13853472368070253083}, + }, + { + {4116627791673898568, 5326753363832360760, 11600148105162668652, 16022425070120634880, 12379564163937803418, 18403278989519500037}, + {3838756056494870539, 9746510470453080454, 15196381880087604041, 1324266274153753608, 1934910704818180248, 16192237923261768598}, + }, + { + {5766511464995673783, 8244831189622490542, 8170343088439188103, 6232835306175447562, 5263728916489688559, 11717533286834875}, + {12241226361813518908, 13563045206906982275, 6620157279318203022, 5949784687776791647, 2638510331637305823, 8202404349400972534}, + }, + { + {17137086209956005801, 204428026461370733, 3234178205969960017, 1143006718786815780, 7294365920988646447, 3430748893910901229}, + {15644744495324135074, 6526193849034702994, 15311692696436479485, 100536624425234142, 2072137864950345134, 2838362248079960254}, + }, + { + {3864766173433820636, 1971303109201164903, 5674191275610292510, 1729560487462795155, 10192657450724834454, 13552365051012392948}, + {6029200215919341904, 15607499798945720199, 9235384391078164863, 13115797159041968899, 11473304030559673981, 6717143313334294198}, + }, + { + {16073198989296538507, 1260522085794207919, 2484833084695527559, 16663233906141730979, 16370173418105654173, 15941588275532048355}, + {15264482454100651294, 1530324904307833661, 5346522558909751820, 168718846601743143, 12733323453851106540, 15054596367649585566}, + }, + { + {8779244963536382258, 14774177152181331880, 4385874624061025062, 1164231020920773885, 18441595039555055892, 10628161864427821209}, + {314776300789919008, 15953928246882392341, 11239013102079015593, 12105564780074077722, 14167815415915669462, 1359490032240618238}, + }, + }, + { + { + {17495831655399754328, 5174414647671185898, 11318938235462267547, 10600238109237010238, 3808662780947456733, 9982761271652922419}, + {9825065447185105695, 17201221608158777066, 8386702419239390647, 6669452484318451541, 9948181677775458542, 10854356442296663251}, + }, + { + {9814807791324751977, 12296930083946621987, 10307437404349332723, 9109385710605983143, 14812805821653280276, 9073050103164402930}, + {13867323253290964163, 4560904001274587374, 8320427990736234822, 16081927245724423233, 5738004521721590874, 6293359268685952360}, + }, + { + {1102440177859885328, 6433584039832869723, 5220624537358960047, 13680706619037828486, 8111463461178477715, 8222960733395115842}, + {17599283693164557341, 15090346558134489779, 4538679599583135375, 15042688490235051776, 13835441515025117083, 16073809881077304026}, + }, + { + {10047787296578964584, 2965381022962740423, 16294614689730458159, 9190282415235004744, 2690723303600845570, 2433913875956636400}, + {314860987985756378, 17256734903814295206, 15934782378906162714, 430963730343504134, 11136098731840913906, 17571316264889158941}, + }, + { + {13751698910353501324, 13510591610088790493, 7296230476386677951, 15771194764882310216, 7071348632181406726, 4016223392586971068}, + {5697427461676860171, 8233597763060359382, 11010267185618729313, 3415981542645755022, 5457294468077244468, 225392490383371832}, + }, + { + {15646693844663402255, 3326571016557891145, 11654470234122088961, 15157961803112063987, 2993882145665175656, 8636467418941461771}, + {6779513489978476950, 5971261203840109208, 12247590628659552873, 17305918993021939273, 16119245356860371088, 1321130712911895728}, + }, + { + {11483973417069062031, 6037224851072625784, 15557951376706404252, 2470679358159540669, 12238331311548942969, 8726725576681513552}, + {9571412658072452963, 13081411829441971381, 11182177874732199472, 4596163123987649855, 2508633440203353096, 13386883764628321276}, + }, + { + {13238425823862395570, 9364555424927625812, 13036757456625831933, 17258175170914518289, 10977661896195155237, 2108108449570745277}, + {9531888381573748695, 871050091524626285, 5415169211299494043, 12856340691567607896, 13004810147483829082, 16238406080182275763}, + }, + { + {15371919503521995592, 1023245974044194281, 7465441369206311123, 1659176121116069520, 14352885355523706915, 12313186690485283196}, + {16829625273347829325, 14329982894690398353, 13430769608769996200, 14433580840835616212, 1575399656250103267, 5631450320997959585}, + }, + { + {1308927832832721864, 7645300720509257753, 394821027033666361, 1405179974140973893, 9998561471841590974, 740549317055684310}, + {9206896584584034779, 14330288277576019540, 5482705534907018177, 1134228745870193564, 14319406255178735919, 6723548280696025825}, + }, + { + {7488031393132578836, 4827301471138388705, 13879957958516433613, 8914235600795497221, 9625930790436045227, 14346277439968844011}, + {8799754665963613196, 17445816559731029471, 1345966680255046785, 2291437085360476682, 17887362986581489890, 11089873753828852787}, + }, + { + {2786087897073892568, 3104846214576331224, 16466749382591438860, 18025871964671977774, 11073207410569350939, 15738740251530786465}, + {13634745416070217585, 5695916567870375377, 3278890813204002656, 436738283047315052, 7668575393144640681, 4923414004094995102}, + }, + { + {14851753411270223421, 2820295503131879793, 17134510985746317750, 6635507126737913572, 2826933808807957093, 14392615754844885363}, + {2507906658398669588, 10780876428782550273, 10380620345441284945, 7886790170905380501, 10231944265771711398, 16476655346301721654}, + }, + { + {13070800538562112677, 9974973058199179811, 17174935952981795715, 11396839698540407513, 6936502055882250851, 14166262455025754064}, + {8364117452854843552, 6706032581969460855, 18006192088730697620, 14578422357554768654, 8987670312607011721, 12637025718236942994}, + }, + { + {3558937619125289797, 5542434901402954033, 5561316942068979218, 3053265417595846608, 17622647805733278772, 13078656474266295183}, + {4792933921067825163, 12438312561223885381, 4069107248810180056, 14562883583229266197, 15526204878824637024, 13971448521721856329}, + }, + }, + { + { + {13881233885713608853, 18310267182505878203, 9666283410481579841, 7622892083109029242, 7627364883537502737, 7711280318302167400}, + {2653916418723521679, 2132538432068103232, 7384809380579857215, 3976377314823384782, 6302545514324279629, 4766374634552375286}, + }, + { + {14275770317741623555, 13472206961963184891, 14882629621446810331, 4745461955502981496, 13430642232042183996, 18385303470562194476}, + {3828360326258537309, 5628323622401545900, 10617176218500988509, 3376138133187194596, 1896232731466588191, 4015792813110298739}, + }, + { + {17520011058000060892, 13282870058194119308, 2970088605549251468, 559824469192815928, 13074959133117617173, 13965335622649006598}, + {14278086476506718074, 15679496005431490447, 7405358540117832269, 11499896947138894959, 6967445910717609773, 2473509465854660680}, + }, + { + {14218645527427232303, 16094073974715081351, 14550346839806249740, 17359042213091334869, 8243736883827664451, 19411709369106904}, + {17360637257722902309, 13524203219993551359, 17248055348998851403, 818508604090109170, 17862494632117412800, 7597397595500206950}, + }, + { + {355637953695091928, 13365105901469090585, 11160916490622410120, 2871346391173754292, 6750400526492046394, 211127482213137910}, + {549443043401466743, 11744212739472559234, 4600076762405256377, 12166210043154281415, 11432931513593152138, 17057353378977209047}, + }, + { + {11045556636417587304, 15797122882916606544, 9857941873608458027, 15587445337518508161, 16747134094270843369, 1942895756873835958}, + {16926974666046519651, 17530543788685554725, 1482855329287158678, 4473134732938867843, 16205916098480860897, 14394504722885977211}, + }, + { + {11278672676047883003, 3127364840791393317, 14661695642506572763, 11327535520461364742, 16295126143649156464, 9195965710616161195}, + {2883629345650458713, 1172057357528370502, 3611546183472157852, 13774548359392334165, 13259339647748906816, 629600286834219016}, + }, + { + {7869123316056211366, 8912948800190134731, 7048222560394935760, 5384815822636674013, 8276041929283508860, 10387125700457001021}, + {5152418287465476363, 10375890927386960077, 17017201689085708686, 17352090541805918837, 12744013506722056115, 16512473688480987896}, + }, + { + {13274024037452373469, 13088421719716579977, 6488831580186260168, 12167840477765829729, 4048926237756853262, 10042315437016580210}, + {16990037843046932062, 11650375436582455716, 336515426783093448, 5621387034989961497, 16227625293517574482, 1675664794019173789}, + }, + { + {8998700262199537435, 3948126232667015745, 6110307257346779364, 1830671386111562275, 17929406846170452655, 6510115356319508860}, + {11701924621820907518, 624276597106916110, 7769841773667732717, 12604366378926560515, 8005398115052195134, 293463208231752797}, + }, + { + {3901247269240974390, 8083958895346723402, 13047079326090925018, 10022566546990307546, 16068843007491877327, 10422873494559390104}, + {6431582432115208832, 7003752929540397423, 751812828597354449, 13448257234944313700, 17160453016917581253, 224281597487448015}, + }, + { + {15505836579778927831, 12536765066489116061, 7911004464200661773, 4589459948731631618, 1352286392773861838, 6489162408280759760}, + {6654011263605559897, 8851080956163569570, 14795264073060462823, 14859036427142293159, 7090935575643363067, 15615386349502020600}, + }, + { + {13497550669973445610, 776655080972150030, 3491366472103751840, 16846118274841047081, 13565352443717216734, 16762453283994907024}, + {12654927015632301198, 15345461380888405279, 4403814052111981055, 17852880245807884583, 14115340613623856930, 4860085117378061039}, + }, + { + {6433917609890801577, 10685400209354089382, 10418542423521959747, 3946310041240688418, 9635492151118952286, 9917954643840099262}, + {15291273590135926152, 4720885519447161005, 17166594277722852696, 3334399947768089986, 17999815131740278301, 8130038528325353891}, + }, + { + {6629307447971988422, 5335548022504527311, 12146427842799104389, 8972801394900876948, 14555534637545481678, 1004424158638645771}, + {6032457518228329693, 15568108340121417066, 8949689274415917695, 4542026629771725374, 7740306014723477514, 16661552339503449836}, + }, + }, + { + { + {9224203646647229025, 12662711716512669786, 12163889523034683189, 2867493967382851716, 8230710800753936196, 207192902851491327}, + {9006096280315984413, 10727939396825569390, 7414333640665166734, 8831661749780045475, 10577657048648935168, 7340987637726578721}, + }, + { + {16819901085357815109, 1200308257500709808, 17900351623796430109, 421922693020621282, 4799108745080418673, 2867647093297445986}, + {4820563775913927012, 5975941317603369967, 14072742165336817571, 2287502568922658853, 9587001235227187358, 4290334145148904430}, + }, + { + {3832022561932601686, 7513971564898549429, 7265952414186567449, 5571401045684531851, 5917838096882845075, 9020054854027355230}, + {17666670175994672478, 14849859059336890140, 16575133114891581747, 18181109587632733552, 9353137766555932790, 14224517063829047201}, + }, + { + {11379736539869871663, 14064395773240508269, 15376587550927055762, 12366734842807406024, 7399730532330594511, 16291653033248048665}, + {17533123140589700114, 16874629705534527689, 2772413922918237986, 17100246637189895662, 12295986277440111980, 9880401782043035390}, + }, + { + {4600239529793568865, 13314440057685353765, 5513099208751614902, 10672101316916498735, 7845480375626361331, 13210044038654501689}, + {9289518081528298195, 11080913979513349207, 17396978866245763032, 6250395789173560880, 16771707236585087336, 2590734212198297899}, + }, + { + {930462897994518978, 9217181672387315942, 17307812439812166569, 3609084933939549829, 16131501236725989478, 8757759376648884060}, + {16339503747609931114, 17221587404154414579, 7488052216073421601, 4518526255668709375, 16947062963375159993, 18380636145787033322}, + }, + { + {3629310135461852726, 14261574859150072195, 12180309193984885578, 10259672401517896031, 6494810599317794988, 17046762876694577034}, + {12098574628862673469, 10378154311416559487, 12750606156573867456, 8663374335352934709, 4693992916394743961, 357493171015036757}, + }, + { + {11833317211185183313, 10488624928285281625, 3077329497649896790, 8470872799795652062, 18163548998316849229, 7886285029156450668}, + {18270578357826845759, 15548792140868659315, 193286806456843076, 16001981975120132135, 5119039709260849665, 9668247383740756817}, + }, + { + {9031752377320763641, 242818397681257852, 18241906657254956110, 13839428244885956520, 9537688327632448482, 2680760180422680034}, + {1140834959571490287, 9218649627789651517, 5215286326434684525, 9085211375997438966, 14681078397199707995, 6543087453410959651}, + }, + { + {12771546520335765761, 8608812848025739593, 11046738517958961200, 2102753437152423641, 14544186608765681553, 17802705546689279874}, + {16807367192212923198, 5264409545529952952, 18278421807570260973, 5724995243518092238, 1214809321092318114, 10853502413658374973}, + }, + { + {16212300912408911066, 1517529852090653420, 4886194125638679873, 1212252738684378336, 11831701727622714538, 7716816927665980895}, + {17295498200608277293, 13425634643770440583, 15749163629045239603, 7303838501526289106, 14498496375761955339, 6454509847858940644}, + }, + { + {18202283120945286395, 2039362142522516476, 18347665142857106533, 17305114143802821185, 11943785292295778029, 2743738074951986737}, + {4994513738578570266, 6348689099302941658, 15173738691317246698, 11558529557606048315, 4106465899018522358, 8424813643021743657}, + }, + { + {10424551593037483425, 17413812589282410500, 705854651896543614, 6898508513214864618, 145837834970548303, 2863236542933854914}, + {12835826729643090586, 1958115997725533394, 280738023943547097, 6087206023074646703, 4265323126954195996, 8619647725472919222}, + }, + { + {5732596994419719701, 9319740642492016182, 8478607680989525873, 17406976540323360541, 14044433736883338890, 5843487408713771306}, + {17866336923428882759, 6507956087423256715, 9144061297371615776, 3240732467142651847, 5257579294906270467, 13872281309975586392}, + }, + { + {12720761491485366396, 6776966272901501581, 11463518450782265334, 17251569553757868971, 6624504318270596406, 11185165932902536570}, + {12227483127918029728, 6324632225240663892, 9478714313429082812, 12835053263906838560, 6450777494445586817, 5700121989629794103}, + }, + }, + { + { + {15147392016261929612, 2592171191975946442, 7902428577086443761, 18094018070971638928, 17125131301575142676, 10403369618039505987}, + {7782580376688466610, 4703006815182908293, 5606766158256046999, 9775555907755921362, 18306579346372695468, 18162177355143222738}, + }, + { + {12724835834640470632, 9147221313705790092, 7170406708748588612, 4886504410000298099, 17202448621988755776, 13271672497061292325}, + {17599074313590505725, 3164548778567106464, 14831945487181112151, 10047709902632560980, 80312838214623996, 4488377331349129562}, + }, + { + {16935158672435590850, 3414074563213825020, 14976003461413697269, 16596700862409772375, 1410879114739726020, 1257343276542464557}, + {12595581628483328246, 18321480388540739538, 16111335550040023466, 18371700889666820459, 5114856790954063486, 12702332139456970834}, + }, + { + {9865043235042057824, 6029147174750169487, 4293853667229843866, 9112439374197776924, 14635415243831213657, 16684692725807653987}, + {6007944397888869536, 10548392254307770404, 7913056855243428884, 6568756587625967278, 595480320951638110, 15988239687909198680}, + }, + { + {6682713213932946292, 7716189363132191471, 6386782149539319850, 9799679847346926198, 12768758919818342081, 12149412740097346866}, + {15963729003660447748, 9187947812534491537, 15358865564388966319, 17453292715073688659, 6185316189136789449, 12625900424403229246}, + }, + { + {1176014715697049427, 10940632468289921525, 1316897139158742923, 4659486690798028078, 6789215229361554544, 6689879531142462158}, + {9044301377244887283, 3631078536826367378, 7428358043384314342, 1014081592875127196, 9053433738331035978, 8688971663426964781}, + }, + { + {13620164954367910528, 9966976914653058965, 4659720763711269903, 6933780758465588457, 8151676732205446269, 8752412244536117943}, + {2214917853338768919, 12945088371494225060, 4601901579622551791, 15942583889923574471, 7281044701092345103, 17030848736008966572}, + }, + { + {7835462182282043081, 6752736874837396136, 1692977477997399163, 6932537288585414532, 14477842662688910095, 15049850015849067234}, + {6173531860463995642, 15846342177339735029, 1597137878407950850, 5502938210031734458, 7415040766859401533, 1338338807883996623}, + }, + { + {140753466411001702, 2297914471247852879, 1028738292103309951, 17823758766646087018, 15769363817186087193, 4910055743319677712}, + {15419773815255457739, 12240682779047476716, 18282251230655960630, 16713544303549254380, 13083613671678892706, 3210908138315425474}, + }, + { + {3793265829253063392, 417218602524327002, 4908064786314635338, 1898100452518531755, 2568510715793833230, 14120149645664052105}, + {18146362507954308672, 2545351352320443286, 5008353042150968046, 10916578200202739329, 13715068559100727645, 17156509812140536028}, + }, + { + {9838244599212892470, 12509523685653687922, 10577600670943532011, 15106554186241242699, 12631690473512788728, 9169152683892800174}, + {729650498691277361, 12159677075966957800, 1876936289057209821, 253712351947999722, 194325639412533985, 9244721047496417443}, + }, + { + {2482116316041585169, 2104186195194786493, 7202193418181832678, 15057368806550291031, 8766969826300985526, 14582594738267145235}, + {16362045180297581158, 14472742906561159645, 14204095959602911743, 12991159482136232910, 5359117497638310078, 17218381012207861896}, + }, + { + {1272816448120968979, 9359442561097893921, 3623593162723332560, 8905232475783332533, 5169888391258441059, 8811080810485397684}, + {653572848361898632, 16110636390338543963, 13671121912701413366, 4560998650645223117, 10962017893531637465, 12770222065189975065}, + }, + { + {3116586205508178734, 2050508606805777592, 675566623125517728, 5812215637185565400, 16747763503048114993, 979095159683344417}, + {4422968182455831938, 2371155931114840425, 4264880153383139392, 2245458832441390704, 4962056465731516764, 13785630336035383669}, + }, + { + {11608620191053318010, 3148547465913113704, 4334059326127053351, 3242751952971024244, 15779619493269214681, 16028659557022656525}, + {10258993644149710167, 6956689905416847195, 1219361474591302664, 15358800427564853076, 18412522508913131917, 11320199778311670341}, + }, + }, + { + { + {1763123866941591327, 16900027656783472578, 11315458126277126494, 14678873114899664069, 16385889875309589997, 9608350753469446028}, + {8365156417390395208, 9518773903920392233, 15517769310656023055, 15557612401839384612, 6818638793384298196, 4689490629614769647}, + }, + { + {7029169502144566380, 15357026717875887823, 10958228541568110205, 12991311448110316375, 18163413024255486907, 4423132467880086538}, + {14329574318939096952, 15986250779104246749, 5149023581841912567, 857692231877427831, 6766579494828030413, 13297528373249043274}, + }, + { + {8833286985133922820, 1422352152750949632, 17916971651207587120, 9852959168575954132, 720074577693725724, 16992164406778833274}, + {13658912852753184715, 15995732835663412588, 109169432375935263, 7153134127152350339, 1740708231718983481, 10096352175613178615}, + }, + { + {8898444536197899229, 7363197234870550392, 13859502656863853529, 16353929722932824154, 3563926877908575789, 7083332022656946846}, + {1192602583272042541, 11691701210306654678, 17768977285493519026, 1325595029028298323, 6083154463528028942, 9420136318321879646}, + }, + { + {9357643633468667166, 9777626262221569724, 13091931063589755125, 7867107412773768943, 15020623651884666147, 12089257806028258277}, + {10848050713527447877, 5954793401847436243, 11016251893792937739, 3094692726578056666, 13335998362365960105, 4456549853200134134}, + }, + { + {6615550875184532162, 17802299024252154693, 9829209431047041336, 12066910166505767332, 9658085204117106784, 628187108833105552}, + {4704248642052554113, 6397156614024370344, 11345180222991965460, 6233845157183108927, 9777374421972523308, 5874678333002996612}, + }, + { + {7822288722540972332, 7952138195439261347, 11169290659098881849, 3042519944988229158, 5405508523428790131, 17939670977762776799}, + {2939158258373740623, 12697341633646165676, 13062397760872702525, 17176707327834230530, 15615175546165608557, 8494997402872669401}, + }, + { + {15755839765779794871, 4360301701503507242, 18156570609668386254, 5119543763469609383, 16128603506838286124, 8332918297114938687}, + {2581195955267651639, 4444333459878089434, 14369377281187161259, 8296332340199089840, 16659639448818898530, 18345037457345897147}, + }, + { + {4758277028832022225, 11683847788382241419, 515925726413885095, 3693914633629232851, 1334049558186740102, 9903363943316486178}, + {6186305948183309326, 9076841023132049489, 2269793805693240470, 5838292741631995685, 15624692348115370947, 5174016497034202999}, + }, + { + {13050258405219282279, 16752510433331299519, 16577830848329560188, 14788323970814757487, 3531220681642194883, 10450279241367329525}, + {2241246527454921768, 5961237379972381806, 17018546346619625080, 4693825024640504146, 1766972201817885924, 12382031514930570953}, + }, + { + {14186663977554217418, 15921452897246352532, 1670746882987574783, 10569214187154214751, 8735916617091829853, 4778008137059793493}, + {12230336867909671050, 4713018484448365389, 17202143122302469643, 709747344404349977, 11975499930396914498, 17122512072780824252}, + }, + { + {18302357690866390301, 7110969485339785348, 13942032347351245328, 5693499076189202693, 12668677863581132895, 12259773033298583409}, + {9466495933006422543, 11511978512020081294, 2926450004721272470, 13153116633565406229, 11631506386728977206, 16476012745611483528}, + }, + { + {3807014191641283110, 18120911889946646293, 6904037019088813739, 8534576748083079369, 7162583560481993923, 8819640486580967436}, + {440118242100524191, 6463206891372223528, 547302312933082159, 16377841440620731411, 13653804506016223223, 11521845620308131867}, + }, + { + {5885835281685587260, 14732488327182469839, 9123122330185964050, 7188708702276480952, 11527895050614825468, 16851231088680010599}, + {16816057606689618333, 11155368217836023835, 12624177727172231086, 16592926329340617105, 15223575869568336594, 7273522873166632571}, + }, + { + {5641683582398435967, 4216323241605386457, 3341345023369259125, 5445036994137252291, 5739257813022814747, 14500775521438222305}, + {11851051397499831538, 8952633600654017343, 16150283802430207733, 14278765209911766161, 10318996485999417200, 17994297809574684578}, + }, + }, + { + { + {12250833825141170631, 8405485792690252918, 12864232748520003516, 10788258468673581522, 11856270866800692413, 17612133403939424877}, + {6699634647130975491, 3731182997054981008, 3644858741145969783, 15278087383684100287, 12254545970866866689, 15919262562293099205}, + }, + { + {8514722413728667145, 18324970319650698111, 1140876005394585162, 14935735778864688897, 13574593964511010162, 5249313883818330346}, + {7116828599638239878, 15508924984182297327, 4202376624751087766, 17328701599850278205, 3030575546715635832, 10545614704608166749}, + }, + { + {1712884901460314968, 9844020979159339847, 6421369648072212416, 15296006715190099259, 14597799127028308590, 14859929927669149364}, + {6921131700509172807, 2364609551036929704, 6856710389833844455, 12969257838905572572, 15852094516432192950, 18132001333910704096}, + }, + { + {17180792802575253493, 12600911473819356885, 3979738952931545371, 897682737326728136, 3061890262390512969, 15521523824750041606}, + {332654518124076169, 10307766275571297144, 15915817537662916802, 8907165492937349795, 7857497823831313277, 691902339344201455}, + }, + { + {18398586274195528059, 15773719058798786758, 12837048689216171565, 11953182511721889201, 5401493090861388884, 18440361993747252486}, + {5508661908202617743, 12788348494283175173, 12802197537676893221, 13389178143916130308, 538230151218415613, 16302560609031790145}, + }, + { + {8617925644825956245, 4355127854548976134, 14887476132899231451, 18298212220260618556, 373812720990200546, 18003600147222108981}, + {9609711738554496849, 14532030487725870587, 7449281719849717093, 8469200687346562573, 10559473347725150336, 12054655914827657608}, + }, + { + {3996011418975128202, 6210410771156724227, 16016243241151657273, 17559838693774705198, 18254204752477848622, 5017013903626038628}, + {11728280652213039591, 18003698909909675482, 5616545407832730442, 3102086566055618083, 5927895418024958106, 18268521772846570919}, + }, + { + {4353949603957647042, 9085101501655849465, 12908896052138981424, 17855767860621714692, 9492202381046329533, 6493982940855119418}, + {920636089493927515, 7492445422033208514, 15300073048779302285, 14892838342609729650, 7806275110911940261, 18060719008911082625}, + }, + { + {11178478997628375018, 2538869944843427535, 1225616675740174641, 262785678366031569, 7237556322327894647, 9013462934359109785}, + {13984952488792193847, 11393155007624702919, 7707447211005168284, 9473882403030139097, 3744543934645693007, 552942797664059813}, + }, + { + {8830021259611276202, 14238468777507748310, 8084636387556533453, 16267493202640556542, 11525587568835060457, 10481188297824139279}, + {1115271124367336174, 311879893672637356, 9462111876944106068, 13040825816840411547, 2701770737309674052, 1508687001335391359}, + }, + { + {18280457447310560954, 1268638543685594562, 17105501920321557826, 8343192844895939858, 10103219901911409344, 5772380144868336032}, + {3999072919154635477, 16332682335690661625, 17160109792742439915, 5532275933255506759, 11912464980270406151, 15340700818574378247}, + }, + { + {7968741417565336095, 4204348514802527406, 10647577904042939816, 18088419244287416759, 17463728543868140844, 8457835342186140450}, + {8996396783317142351, 11593744928362394165, 1118739296758409498, 14422226999371433227, 12625902505025381474, 3115381790871861597}, + }, + { + {13500267717482823695, 12826999588757664414, 9339382239162750836, 8128243301916864690, 12056736855957358028, 8196723657625083381}, + {13279394920737824036, 2958586812346659937, 17330699213847682717, 16087607133092967162, 16401864758434998681, 10039877192861155006}, + }, + { + {671802191804153328, 4139782484917432247, 2458696726707986631, 13509154007102964993, 17371423440074958223, 1797826281916833787}, + {11733261849393823747, 4590492414496687225, 11885892654308987107, 10686151607542826668, 1505341691600550175, 14056863349008723570}, + }, + { + {15792482088894033762, 5480086515083249209, 11855064859109876087, 17787767953015637343, 12667533478417710162, 7387754975679279919}, + {1207308571340156947, 16667444176920164891, 15975281376773688805, 12572215559198527609, 14287924549904848354, 15022984237456793014}, + }, + }, + { + { + {44405927858177408, 5350377411887964085, 14455423006632940030, 5051888284479827915, 18289264027550181045, 8742179469806049698}, + {1965293239814067675, 6296618101654059964, 3622639221300896262, 13683273513375487727, 4967193303260329462, 11081296004911608832}, + }, + { + {9099612492305855642, 13667366445618114651, 2368345502115408891, 355808025346965495, 6486699240755468623, 17662463045646732595}, + {13873320631421175736, 5934257143872775779, 5746672378903457427, 3704713689249420299, 12753304704606405263, 3217678872185309915}, + }, + { + {16414774628626628182, 32433971592372646, 4545225813507032103, 6836784835149171090, 5605550610705879937, 5548109210523028334}, + {15540467984433628639, 2461569588551261176, 7976753374299459545, 7581883501804398076, 4495381352011398463, 14281052217405746417}, + }, + { + {11076024185715957092, 3756765523882542942, 16665914572503891748, 14424567262466352621, 3717953767462280879, 16707839638391689758}, + {16892433804273414193, 8340332951294898930, 16313859462232353177, 13057798224010923708, 2523399837778976306, 12671960932364471005}, + }, + { + {17680998608405488653, 16454370296773597713, 13745267107063112083, 17812400946273208067, 6537239167722644731, 18154061302206627196}, + {14732093356815809073, 5178617476103754703, 13809803262147327548, 8824415336739118563, 17720661792494399232, 332116945344768606}, + }, + { + {5904671783816032987, 12111663325909606562, 6880618626717651658, 15875709066691863243, 11314665215817792920, 17321877266325783037}, + {15530273438553475601, 13979895649836346625, 9161871406971555955, 8903894066085514940, 6153387203496648040, 12571794686069326995}, + }, + { + {13016093613163620702, 11300489640845417680, 12781125362901831503, 801538149314788550, 2606593691508046519, 3163799746260716745}, + {7990809893160984636, 14408985047470077797, 347123455262478363, 13992131173035179306, 11786974102048305024, 11698441235974567349}, + }, + { + {11403599927368253583, 3279567955763272667, 7486403755075843180, 14522524358510212243, 14041846160447403772, 6435799871106467417}, + {14030691594486470451, 7790983720309604281, 6582028046670807563, 2822694964154013291, 16463582068215434850, 15072905663834443911}, + }, + { + {3407741673335114913, 11737534300849159723, 6401636175760439089, 12664954507386771017, 9946081910621171804, 5351127802521315559}, + {3173915260803124860, 10290055371665382209, 1714775078878069738, 10809651193197592847, 7937909731024783757, 10117809777580180877}, + }, + { + {16234864712073389023, 5314806349780370870, 4543488410858487687, 16873514203217580096, 10926710397504298767, 9299654171185615615}, + {15666939264737647752, 631855467695092014, 12193734327123054559, 17500404761181864020, 5421672177931299996, 3181351099583887620}, + }, + { + {9865914660144246756, 679604583562241462, 12921501903321601694, 13643679714879784509, 9802439286503205145, 3566349991748818559}, + {3712245593303086298, 13460846416004687749, 9489981526591301543, 3123337991328400667, 4486301121585605289, 8667920552833478113}, + }, + { + {11007825084924597849, 3874134660444866478, 7483283914474628520, 2947665680662261000, 18206338370303112208, 6893224180612988447}, + {15534747185067764117, 14985089178434671491, 3753309356845273643, 15570826499824234809, 4279214973488175555, 9593222558729075908}, + }, + { + {8602395341968076463, 15871701026135700965, 3712441164876432259, 7899892413623964244, 2712639600130105811, 12974295924845123944}, + {12399828322355686123, 18332014219357823799, 16863123510502888446, 771187562270410330, 8994686144476825705, 8686520534353888933}, + }, + { + {5941138557129179410, 16597018407758618077, 11490599640002981607, 3438708541253264112, 2003804289091704123, 16058751440908460062}, + {12804590885840718391, 1477090995170106511, 6149788628468626331, 1665866219994921367, 674399758826895796, 3022438717214642932}, + }, + { + {12649661972779445664, 4013263712261539431, 14554669017811351896, 13226091073296320692, 15697669929212159615, 10884886018241841834}, + {7538090638724339870, 17307058199744561660, 10160210242875571595, 18329720837322489027, 6424491245976098107, 11439659459774047524}, + }, + }, + { + { + {7518960189446694562, 6993197482502760102, 3624948335487031629, 3298603013801970257, 4557303586291885385, 513965581431450258}, + {15631936952275006776, 17646865581595831452, 356541621832294767, 13550122502020347389, 14318884666702203958, 10960356269253451077}, + }, + { + {18088774058581706331, 13144474494348168686, 7944684987556043669, 14803417489453188919, 9523674128757303753, 11078534252464233827}, + {12388996124243602932, 7847055437820113788, 8655700446678160057, 8000087902999810104, 6845432560166828222, 12293660227730163310}, + }, + { + {4121836826461176490, 6993311364897236225, 5980001915532870045, 9191387104629167574, 610736785956912723, 16369608744481332444}, + {8192853368245745564, 7830351299822135372, 7708271704384679284, 8692236521179851966, 4729288028381163761, 15087261038869840952}, + }, + { + {12359675760240320823, 5017343929380605284, 13074869016670236859, 15189571864632066092, 16437432446366423946, 10450373967097078613}, + {6473521102572105839, 10479204864703445101, 9531740430353536824, 16747435491821370083, 13590492053866597783, 13972781732492559558}, + }, + { + {13526124267573528663, 8270416783887521310, 12350520572663083733, 8457342880502864923, 9576612715781561966, 15585819794980473675}, + {12920791615644428441, 14682599939111671380, 4336061001815369200, 12825352708863745934, 13689910154205327554, 1285753843825672638}, + }, + { + {16260954862601212942, 15141701739798325327, 3469367818986501585, 12433553164601433194, 13397654412997304037, 9513462516209648688}, + {8806424456394813714, 3283666376713533561, 12560245143465260449, 17855428090864138328, 9493604162795122493, 12112034994090758518}, + }, + { + {7529184601583900565, 11129864964563043004, 7211397676801058227, 1363637554105090981, 17895272493932277282, 3646615785541938193}, + {5125329656455924528, 4567149614941497190, 11074336456476606030, 15476194487447194466, 7180704409380789299, 13835694922459390849}, + }, + { + {6367771991991911192, 8601334531593085019, 4312076039860441887, 3349991553201651706, 9823362064268535912, 13889910441974079325}, + {15204812249791097149, 6041265790239125946, 12691543265160543238, 10306665514263435988, 14767325902815340861, 10379404251573981879}, + }, + { + {5287451048506707013, 4348959316051807494, 2195731310084877410, 10147908105969953285, 6603704322303743751, 945595692043651424}, + {8176294556983740459, 3760024494015990869, 1596032494450454490, 9532812003368449590, 11266525576652515928, 17675618372058806611}, + }, + { + {13713835993913486801, 7766578236545921171, 14534805690298336184, 5666909695385346186, 8839507885361423259, 4694981751780603071}, + {17723407317459630378, 4443283331360111884, 15519272406098385785, 17520713768065915126, 5696872215251363099, 17703348601524604831}, + }, + { + {2164215638320833038, 17121084597475879972, 953559170830523874, 9824463983667276307, 14122056531227172478, 17378911366973403187}, + {11224042629539202120, 9891688504526640813, 17195883541507550243, 6329564008856258694, 10930601382660244797, 7336662048169067742}, + }, + { + {995921546101717569, 5828224904318233156, 8250787968679150139, 18216596344319934990, 11999487189021985197, 12415115477515701118}, + {15186145702255030700, 2113607545324837959, 15288422804320951323, 6325938775505173826, 10420910094419414217, 1927106976056222556}, + }, + { + {168373835175327962, 5954547085671796454, 17463611069868415386, 225394552152764446, 2307768634143069290, 8042600063379354713}, + {8117902579268801666, 10832127345976105061, 13664993000566573485, 16355061628853536029, 11258951867911128064, 13533986249738933070}, + }, + { + {2256466623088827889, 11490136642947524148, 10955178908605173832, 370819964681409304, 10493984649757869556, 5132627896758472655}, + {6336091067505438921, 10780074837814789259, 16645850939014586085, 8079913953781307235, 4062116077218792165, 9366190569985953070}, + }, + { + {7040462669310098393, 5297122089825027264, 17836763057295674752, 8661859425168585511, 4207236964581867607, 16977003945502762190}, + {13639729604193903699, 3075230971516641826, 12603679116623626959, 17929390171247529438, 4340045624055496198, 12958507460470817783}, + }, + }, + { + { + {13603267959306598193, 8693043305222262466, 8385036129731204785, 17301749092100773230, 17293119319290412054, 7997938435970033452}, + {17626685223448488356, 12525034788314564340, 14661668164222586257, 3322104272345643135, 1609592810955141849, 2549513802617457284}, + }, + { + {8798435167269930640, 13070514712052083568, 4736461614042760363, 14206975230185412328, 133298083050190689, 3881702371340834770}, + {9708307132029784886, 1190148038752103456, 6413103290824094803, 13481632314215227255, 13825269422873963023, 10412305108920689107}, + }, + { + {15788775674106557193, 2647031410423879993, 11824234196304518021, 16508012954631132049, 2851858215553102032, 9031676847819265350}, + {17056269066330629533, 16578781453141932588, 12149327146251727097, 5603735625820741662, 6198349307184960758, 15317416179414320750}, + }, + { + {12101899190913284916, 9608769495503265584, 15201140684891239564, 6542484635045229965, 2916993459978592676, 4802334108209352673}, + {1973336680768349386, 12679196129410828967, 13463385388413200455, 9654153036115837558, 16342609945030294957, 13480152702062555703}, + }, + { + {2899711161363462805, 13301605990446182752, 13405176039316030122, 12694240906495353636, 6028874869507943666, 17436011221762298446}, + {3799912876591532513, 3287947124836704136, 5920239729516121972, 4658851572162401105, 16206677545960268727, 11754748256988512736}, + }, + { + {14829746466477852272, 8785495584277675921, 6423194551544767939, 692454830006456519, 231353646984097766, 10478691929706490052}, + {13187510740839857109, 6329453754316993892, 16082691749983710504, 9140500440454110398, 1359919744529707405, 5867635887532143880}, + }, + { + {8283409025155305021, 8326153006408425638, 8192125950875031557, 12491925510388767602, 15318184472466947145, 17174845401039236071}, + {4024628118229282985, 15541859898701908579, 14997151867577432677, 2742910007129941237, 11281936698759777841, 4053513648766184443}, + }, + { + {17504540629335028708, 10934158903032446529, 10440102841886099171, 14945242719790343095, 9216441307898357664, 9638980805394197765}, + {17980359344968817157, 7448102317851383292, 6074361339806645900, 13629660188149307441, 13004652602731784581, 11547813582289855464}, + }, + { + {5835495230485007597, 14350772393378726062, 8747233229858209651, 3317935002292804215, 1073070181947964939, 7460355407911594663}, + {13395345232316724375, 10346078775799124075, 13798478435639795560, 1629058324627559163, 14747763100431935680, 15299073526901740916}, + }, + { + {15651423385292143727, 4846110050285526280, 8366261324209130800, 18348748562705004572, 1191482937147378439, 14318163684990419654}, + {5828426112534678889, 15752453922521080195, 788797916869961805, 1050155050965406592, 16245505178409635417, 4624404334332384586}, + }, + { + {9519649412281579636, 15518026566172043316, 8230071711608174064, 15501328228846578396, 15538051064956598926, 8638696845481203911}, + {6545591773917305375, 5939294308617001483, 5916517198820221821, 2183353220433638210, 6608710467805325002, 6375674496051123629}, + }, + { + {14599741493080584733, 265043095998502009, 15590157843765788733, 16283462652920133690, 127450980034769700, 8101994233918053876}, + {4354404904705327864, 10527772165440476297, 3472213175562207788, 14083669454947716927, 13275423539077686885, 5338095862941712423}, + }, + { + {1235012355674231855, 2090134554838509585, 11863415298782072711, 18023496095060787824, 8410498900143253177, 10594109983238360693}, + {17550081202781797913, 2173651076708559007, 1186671825722566228, 15233030551314777921, 9888771203060958359, 15468843840302879988}, + }, + { + {11461190636282409817, 14308116091595492374, 15509337886967718014, 3305520874657987597, 7626903910031076977, 3082923764612175270}, + {14811303431165168732, 8838542203092895295, 16984937260064502824, 11714999386942378861, 4897363879848520603, 1001099817032265897}, + }, + { + {3637674483014131572, 3117885916559390287, 13017322864107767485, 11567467141438885182, 4996993546175421383, 1767669170792783157}, + {6426400534208188423, 18081501770343787332, 6628088911946069490, 15549150917856099952, 14206743374618728130, 14181348296669151521}, + }, + }, + { + { + {7989198143366045630, 7010829800355578048, 8546053455940578601, 6881887443026808498, 15042102422681491309, 5420645403520488369}, + {10849333199099746435, 12113569487191320877, 3246658105605143184, 6336537385102402345, 4597429228667676601, 5272271520244435977}, + }, + { + {14306638724632781511, 5757106316922152519, 17125373792178988648, 1583100757864258958, 17360083944987639843, 3920600288799646538}, + {3331960036348075865, 16584227479356001542, 17306396376373940447, 14759099067984370905, 5812518892646247762, 15782678322655568927}, + }, + { + {5413193268301814099, 10713883248352187164, 13410675108716405078, 3585734128190446197, 2777085511140743921, 1755162931158100151}, + {14101275991297185856, 1707557804525078570, 1967729659696736336, 4823950423327664451, 862801022254850239, 12435639820717247064}, + }, + { + {306679465712635984, 12152848986799385191, 6883719236152567513, 12305822533289967588, 18402162608409722972, 11108631399674712772}, + {2571321336657345725, 5282906424085283199, 14072199601206037589, 6326969628422378510, 7257345697465293614, 15327414546710657910}, + }, + { + {12201144960808694291, 2266284960898988252, 8424553153700131642, 9167059607375209949, 7355136040026239658, 2541478780035614622}, + {16506463005253913043, 6582690723164939915, 6599951765449856592, 2404559737777750863, 8780347760287852096, 17846128204113467575}, + }, + { + {14860969561074928871, 4809849983665237968, 12242711789150271258, 13843481869678455226, 14175051524655250463, 14334810640036579932}, + {11575444057028938068, 1682341910648266103, 10938858063273491391, 4341242396287801217, 7613196676950010801, 2500752005513253600}, + }, + { + {12440061027889587972, 13927371198268500445, 16154935051556123915, 18096961537601388555, 8424464497516729675, 2313786208528450307}, + {6509771027110309267, 3390162382665127855, 14587068644788920599, 1328169351793106371, 10509868205576387317, 2765759870517196435}, + }, + { + {2900406544253496059, 7303698760912649984, 8691265875763036027, 9197553224083694706, 18352617242438717063, 14750961326114925844}, + {2499601025675361076, 8368427257901887897, 18132146080106643208, 1110936544903604055, 16261680704811161606, 15090938849013897133}, + }, + { + {5870727586880606917, 3817524309119245910, 10695436097727319065, 16784573325267031769, 168386867463964139, 18415971011491165889}, + {13492479568749674699, 15834291406704295009, 15705574100744201096, 2398014061321015822, 12468258805517123137, 13991053711847966585}, + }, + { + {4169557306961711707, 4015219248181969243, 12214392270444620774, 16050078587473704262, 2784750252993704422, 17395896913298686268}, + {12843958296305025565, 369831555843170916, 11677678398942896027, 6641755134933316997, 9109097098896451407, 4781721487698386903}, + }, + { + {1392099397992149225, 6653317869794434155, 8261302057061700743, 17076785984088590530, 12214500026419464516, 8183114113550743923}, + {7219173278975390146, 13854678885102808519, 52819572796104662, 14959508682837821268, 4666245422256363222, 526398188884660107}, + }, + { + {146377064121748072, 11117625842528721265, 16508297934345517505, 13963807611317318780, 15513104757270430459, 9486443679271300608}, + {8499000076286979115, 6314693643347125094, 15660966474005923460, 4849442041573028425, 4417660487771261375, 13534789771025100765}, + }, + { + {14165452728554216170, 13694105377023575661, 12112553140758207627, 13499340770701043478, 10416006904191195926, 3543462727896098709}, + {4066244216336615064, 6569278217794074558, 387967286518318157, 270108989062251217, 16349063922035707389, 12438514695154831396}, + }, + { + {587040577811041823, 6936770533105343364, 16776134995012734224, 10277362302644779257, 14649614714574251627, 15051066325824432588}, + {8291129711414316681, 9551002213274431576, 6676196382269508743, 6874374105452669031, 14751197759974741889, 9029571467065764667}, + }, + { + {14428258617344372219, 9908056332586719435, 3405976719581642508, 11387547871499772614, 2994350212903836640, 16490884790412572450}, + {11355150127282843741, 753093375853717498, 3493937923504423687, 8754398622695613018, 10230143170990690589, 8594587862090207256}, + }, + }, + { + { + {12025065147930696764, 16395321909258498666, 17254275975074883492, 8698446818264119462, 13921708813901601023, 11317527677055938762}, + {8372735897264020153, 3995509821790542114, 17844440857746011127, 7150508535332996970, 7856356095447891107, 18425881274930431587}, + }, + { + {3868179882159761840, 2264438469296879600, 14040732472308090308, 6176899669975159097, 7687708097392128226, 15700212396478219258}, + {14432188665158358139, 14093430104632320380, 6658435239629637912, 16817255952598430533, 4042186219830704930, 5581603010754890001}, + }, + { + {4194420838030196541, 1333911740513429952, 18216514596089176140, 5522562721578975413, 14019454638832409935, 16180950399634304052}, + {7874407470843020638, 16700170713448853543, 13238545221113708433, 17341343942946679971, 2492905945545894244, 6150964092835885281}, + }, + { + {9160207688035903546, 10421934692844981887, 12973343349121023222, 4588457373452478724, 8930230292368920615, 8764471311578947963}, + {2287273259416958217, 7105649602824330442, 18442962768087545765, 6705276737238885061, 577380682084602753, 596787676998246106}, + }, + { + {663478452777260243, 16283602145029174982, 11124685403360893629, 4781563535459832423, 9323851769832103844, 18097969442952761286}, + {7837190984970827968, 6643489635464035580, 17874774866954327612, 16430201046158097201, 12045640219457858446, 6223326808284158866}, + }, + { + {1657492744835373106, 14305521459309102400, 3869067393311496051, 10037235265268002078, 795960391565742762, 15570341341842321230}, + {1416215615272420305, 3844160609182024535, 5420451137511849586, 1949162974936638642, 8451435764323596076, 8788000062158561339}, + }, + { + {13928009376574601896, 7291171400028186761, 16473025605005992076, 16638477947212814985, 12047811767976047467, 6878298473296735831}, + {14902080744924353595, 11030229314796494659, 12098457778174714596, 9424760405850702049, 1497914805837158259, 3249894799792534256}, + }, + { + {3590247938838498240, 8806692635119047359, 1698761057036684647, 6343574101558802001, 3746591523512207350, 16046850941587493893}, + {9375703075091035250, 11484732524515574701, 10605373578002057385, 1718556460448813872, 228246291976542303, 10311368155034743860}, + }, + { + {13497031464860502366, 9397761439599875485, 1318541732049664766, 15374121346380046672, 17717429548790284664, 5159388673283835821}, + {13355298244502234884, 9645381144552778188, 15577838213165745473, 17224721347234155862, 440552977874015809, 3485586753351733297}, + }, + { + {3516261141390918044, 4335927420212454420, 9153235025059865419, 17728981115683781993, 5407851417900531604, 15034043952911725703}, + {8360898999522732095, 14154807375320553311, 12720119837506596047, 17979696399481662488, 1503715168515766653, 5169207090054716326}, + }, + { + {12162980084934091895, 4233957881103578519, 17170356997174783866, 4243094926092018555, 16613894431916307329, 6606193115702532471}, + {11789634164556738593, 996991792386448418, 6962245779712200787, 4974442952401074444, 10897550856395547118, 10995646432875528213}, + }, + { + {17102632525353385033, 4726908628368929907, 4247885372815903947, 1788394963141125417, 15102348628480678182, 15128367306207476457}, + {3972599649912410141, 3921603030106002483, 161288956218192081, 7338348096295758314, 7143236202635983396, 8624888890090620099}, + }, + { + {6331943491044463866, 14228029352154794719, 2947037856011623469, 11772679753184455432, 7465692292318631028, 14289953244793202905}, + {5134250825128073664, 17656488618598423937, 16854119307556681012, 2421796355445999202, 15424387029136720472, 7987182987578392406}, + }, + { + {2608951835161989111, 14588356830133736122, 787581713316032185, 9896238476586952494, 4431066364605451791, 2903280281635265356}, + {8247495622914418748, 11683109383984515972, 11561088616384052872, 1149723125258168883, 14529556212737756877, 8912094569277399627}, + }, + { + {12789135954360228010, 6780075827365568571, 8810224435698828502, 13446476233477343302, 7214376817335187762, 14458570598448093615}, + {15615130062596991276, 17246585199766548683, 6890348740309790991, 2462037107533762815, 14348419451565630896, 5342642686877329738}, + }, + }, + { + { + {2905464083126352106, 15382523776645615659, 4208326436876253066, 18269526693635159971, 5790854390728730522, 10746880826459375258}, + {8662248081050622522, 13826611872785505390, 16436929138283976510, 6326154269244482967, 2880171501306902421, 6678386436918333169}, + }, + { + {4081558640315641247, 1910870639571469881, 6877171221443835842, 14157529767685404063, 7740037116920621887, 14764919955763458331}, + {10267569861886921827, 2529844482184019983, 3259055836051436011, 12721359948163822535, 9659485045930382444, 2682511237837334805}, + }, + { + {6257278162168451228, 14804471928370352903, 17266243102614466221, 1834384770768531640, 1291836003048662370, 6034253395610136614}, + {8743066898222911631, 10312528166509794599, 15491664890314077124, 9459311605542100872, 18188244670802339459, 11837284714306023066}, + }, + { + {7384073074546884058, 13342536901934035362, 1796642291707654196, 14924003300567702780, 17696513874113839739, 2170126944979395945}, + {15655425421070558346, 9046927642313144782, 2539141704545898189, 2313651783662755544, 10988582385563170062, 10708895281446879013}, + }, + { + {8049823402121284107, 1015261354744953141, 11001601026371351857, 5188408555842360927, 238307893716713840, 9306355674483778871}, + {4882696385991861541, 10855316230146219920, 7297309210275934874, 2129929538911047623, 6105877736586220144, 16540174430975243109}, + }, + { + {3846553462991609521, 18287444857448547300, 4860654016674888150, 12102465094571524845, 9665319422122056880, 7341976002114379270}, + {11450690261526312033, 14359620265055539834, 2129613678351742251, 4154310935547659871, 17819794191738178105, 12470777076380361738}, + }, + { + {1820231603330482333, 8197912473886688932, 17564410961062418802, 5547060850511847496, 14784446920715373986, 6744079834192692285}, + {8045763461421446101, 10946745933502697155, 3334195578263537309, 4155813158460651681, 16304254047867190720, 9129755894729457353}, + }, + { + {5858270368901180686, 5650671310031369526, 17358036986724164367, 12272486751450316321, 8118942123504245440, 7605341247988122771}, + {6460053483168551327, 13974980628946427300, 15265461046774765196, 1434115779622874584, 18256968071394468929, 162814016140883808}, + }, + { + {2332162608871511375, 1868148336815015635, 10688622518437469162, 4535570520634779462, 5558414024910369005, 12846608910105978921}, + {10182583164281883737, 10225962215828780864, 6647302228613027609, 13926246345815428275, 16444874778110264906, 12426728125906820495}, + }, + { + {7319356743643981758, 17290801891240533282, 13680538635395325509, 9431898857998460284, 9654052594732493588, 11216128628361019165}, + {5480652586120031716, 12264251589473554648, 629460023613249876, 13888625092415164277, 5982727213326537179, 4575309381338208673}, + }, + { + {9318690217895942273, 3885888063527830607, 9646742812304452818, 18262479706556902502, 3620133047155459299, 18388160719790129736}, + {1914761448944519470, 9758008627466255788, 18418420068679038400, 12896122466120836747, 10890035278343231294, 3646620616965601722}, + }, + { + {7320055252736060853, 1303381685630079106, 1389396534790493913, 2784451395900022634, 12504771187503822515, 4227927385881340861}, + {12071605771892533802, 2754948426319968897, 11085204177816817620, 182697453064193454, 9227505917134720328, 10621984715679088732}, + }, + { + {6220826937720121878, 13229947210201087101, 16420906931171635230, 4228069687275537145, 10649909068460962812, 14974797380841429985}, + {2099387861104913886, 17576472277696906704, 11384913496578412357, 6794363617398915145, 4335808821084623592, 9733284623560895058}, + }, + { + {1755145516295475548, 15247893042361836531, 5738179788894433569, 11279068420917658317, 4290389521159722087, 14365410757465934654}, + {7291605289247002500, 11812770986542211322, 48289046067440439, 1233419001099601995, 13182799439408327769, 3066909062077171440}, + }, + { + {9251396949650789431, 10964669964980210420, 18441875565843264347, 10766527953487419221, 2053504370587058697, 1120548999764652480}, + {13156388621520434359, 9488348829267331096, 471226560476910099, 16729073468825516463, 6843824047113762587, 932518740561235009}, + }, + }, + { + { + {8005022716490156292, 172470276668278570, 12027061491585017361, 12668206184074529368, 2383566891938055597, 15146733507906754355}, + {7778895097740687136, 14251829674046124789, 12738613561581015447, 12051618485845136097, 9897878846738638320, 7907234926402663579}, + }, + { + {10065252555514097915, 6386861198439688962, 2775722427207394938, 17952746237366567827, 16390357373389037601, 13972513434252720715}, + {14700210881752165375, 15185652113659869954, 1923970725644198719, 12211789976130827254, 2585886428464543151, 5288489885799434816}, + }, + { + {10567691911424697649, 16971243382477786521, 10251841113143443125, 1687737920922643646, 3746145726913279586, 4786791138611857452}, + {8476041976560261273, 15570593593290952605, 17648077308436960175, 5839063770228102907, 9706501119134890748, 6475897123160711932}, + }, + { + {16272681470773409672, 18157143820860266346, 6874350001337166182, 13501252460259511743, 17259688624947069488, 17317925810681384843}, + {17458673210103455399, 8293651101654188440, 4287591827563518608, 17477963865483680843, 927677871568183454, 4257762449075391782}, + }, + { + {8076033399227106890, 16533143032280607906, 13521927650080284497, 11510742235496409044, 773074617642472847, 5480268378661415914}, + {10560774877949781007, 1551950937282276704, 699681785268341449, 139399977164437031, 6186795762861491620, 10490971431428917955}, + }, + { + {9190090661907342314, 10353817139393866538, 13722719350565763089, 8086989101739556304, 11831125735426804282, 6527360398769008658}, + {15661687200097987699, 17883372000534567314, 18228449294037686953, 16276062303086046777, 11067473153184484205, 5270793026007762758}, + }, + { + {4644322026860926003, 13840860549436432899, 773219189435319969, 4214545261061108721, 7349178605060789384, 14108663996709041985}, + {15086368808776131018, 5873313287260733157, 10958955294835479142, 1029190239709350397, 16575148148212140239, 548824197340738121}, + }, + { + {10538023507650655080, 6405097420742099168, 3772328850901597675, 13431850381701237922, 17301482879787833065, 10960182504575418989}, + {3458141607490423836, 15983729892825441020, 6674827306666597406, 6998631059837206710, 10452310379665360233, 12442577005422810090}, + }, + { + {6357449289782518654, 5562676255948928403, 4267773668505879348, 17042466998439942315, 15445173922414204273, 5045693191253100284}, + {10888452729312376066, 7286005702779769520, 6310396517254538489, 17973884204765258948, 8552375160420880806, 9676186921102873385}, + }, + { + {5132936755125381856, 13632397944410194731, 1195217251618711717, 14192521157173466766, 7136777102122506464, 4992685048206006386}, + {12758444670751645174, 14211008273195363585, 15176937626622599827, 17548458272828201751, 5057260891126473883, 9952036262648196850}, + }, + { + {16078498188091009803, 1162033447512069931, 10059309132406299500, 8829937177340388978, 14448159399458657941, 374069359661101813}, + {13367213118297441109, 5274140197674632268, 16907854435294080281, 10813040207319437761, 17981016036466195869, 7390729432234187734}, + }, + { + {927041625307275433, 8960709029455529859, 10831922670190955819, 18290821865497267571, 15356340336167722251, 1277117312667074566}, + {11345332917031878869, 14333153309564749909, 4757616462511080414, 15371264136186622670, 16048790410218032652, 6253972033361590906}, + }, + { + {13515732918257273776, 13723630809424897822, 1256040724895856748, 741241381320040022, 4179658714379202158, 7700440732059923700}, + {12620782566472061643, 8647092247759141584, 14556418162370042196, 10398569400923172183, 2942763850561441253, 13510474539740910285}, + }, + { + {9284152513908444951, 13364815009916075834, 4919960874500389956, 11846737451875562809, 6206281447342218811, 16898214858205632546}, + {4777300224767696450, 16738332457351222374, 2425414676554916356, 10738169294712527458, 8592315599382595498, 779347662452931693}, + }, + { + {12657704884116037495, 16629278614392996531, 16644595643705514648, 13083603858484073418, 5531378660228117371, 1072715305930583874}, + {16281698922290258814, 17101495949789370442, 697325071236988515, 6834733894203542328, 16874883980138472052, 13765652846823513818}, + }, + }, + { + { + {1443983809817335050, 5159436179287288748, 8718823893455992642, 13859422481759839054, 16821370532543822004, 11312232963165366867}, + {16799784256686916142, 11063086467296440173, 5409640362054745615, 1744861157419261406, 9159074957446964246, 14640106507936810200}, + }, + { + {2855230597739850155, 13620723665924576268, 15633539828476547165, 12790587404740345825, 14929382470136573230, 11024875668098768390}, + {9757666174600838731, 2232369412498935956, 5843374372613155338, 15919240107279516647, 16925041227711211671, 10150031711225457751}, + }, + { + {167838721727610261, 7541800216831159956, 18111323457358615697, 1375214001809563574, 12793193868391341616, 18288999141676090200}, + {13741005234449322878, 11213622750935649716, 1522802528596667168, 15269019072730025083, 10719991413129377137, 15521380803604598551}, + }, + { + {718529776434363422, 12683359777452057212, 2804554777590895595, 13664120639095226495, 13598640112814221798, 15241444675921322490}, + {8810840946828957504, 7811396362330849266, 9645885245397761208, 679907887946404609, 13039332546165252336, 8209508558765517234}, + }, + { + {4626158970998280523, 17779366207669178780, 14066716967377837836, 5541345249351270224, 71760835438433145, 1781108686838293059}, + {11015261109851457791, 16129646178084531488, 10669691012640045245, 18184224459278962224, 668895765928111620, 18347537117071351865}, + }, + { + {5383950189451203046, 10844133140951324068, 2374979840933487414, 18242105404652163653, 2153887761192573295, 3314974606006034191}, + {13575532204571281217, 2247071187256305144, 448195274692108969, 2053979169079271594, 13812860435287696334, 1732389448089431296}, + }, + { + {4284546519240384782, 18250416328676695864, 6075393821764526355, 6803234443690359332, 2308015705795216965, 14282768041402275649}, + {14692234199015945763, 10982825331872323691, 16257836708673068915, 9290937795903983017, 13215156669957704998, 13581066011281717289}, + }, + { + {726662160657361021, 12794593883926219472, 7861799432245846591, 14620923059626590643, 13564033114045541206, 12056825063290520144}, + {9319654440973526666, 13306574040007137554, 12383704628262510604, 16837061611201648320, 5148924680488916382, 757589831530246899}, + }, + { + {11260142852359901856, 2910994799586619654, 8190175402543023708, 10282746214391918351, 6197128196041568622, 12103744805432714925}, + {2754925794608765953, 7213719752583096226, 12149382823057292581, 6622803011412572659, 1043029140538289242, 2160363121257772533}, + }, + { + {3959688648190130918, 8473581564018232725, 8102575542433283254, 17478136759519300612, 10782499745742339984, 15960018897339834420}, + {16254514834142148732, 7808901449511931787, 18330166307905077063, 10432644456391460073, 12246398526421152951, 16631198455707802675}, + }, + { + {3447922898029507114, 16051230154621670189, 16072905312851388355, 15031563884401549512, 14706198388315798396, 7847298879472932181}, + {14334929624882962482, 4207755459965567091, 2727607546440637589, 11028268195413273994, 65681139350480862, 10388523824998445409}, + }, + { + {13621028160954218188, 9189281248079816548, 6559689192872320191, 12511220059980672697, 15021931978161570527, 14942251476194345708}, + {8032030039336040011, 15968186657808771957, 9377328317206799246, 11373269023340235305, 14864609151221526904, 12259184676083236409}, + }, + { + {4993001240436128010, 14622033823485440043, 1269131542761241152, 3340746980531933825, 7474601841448992000, 6720228020507007935}, + {7637406401737657019, 7627450969186809480, 16514017994864839608, 4814188734303098279, 2484761716517021839, 8799093000399717716}, + }, + { + {12269127574265060145, 9724465093155898416, 15873065313448764429, 8761869776521026054, 13485847957822391857, 2439524426319009706}, + {2196722629873916930, 16606975023104026874, 14395842146577003711, 8980633514374222856, 14337391476390507239, 3245539094489483683}, + }, + { + {4586284023246783172, 2578135446952921534, 16829066520710412866, 703408518185354273, 1484970151848468921, 4187259876483048418}, + {16026918465565392877, 12845800470973132882, 3563015620264375279, 16242852718263860671, 13711297870624837478, 10327260052313469500}, + }, + }, + { + { + {11907264597133981686, 5345484317343243432, 3526298189589605651, 14941494503371346641, 4390348405627321537, 3075441678856402034}, + {9143920156043167932, 1663991502233570797, 11411151526779617123, 6295062208334296723, 11167953874910400669, 2847239470361941655}, + }, + { + {12048307220520866404, 10548739433510366959, 5828937682586289028, 8259138483713638196, 1664521593180101667, 15076565371876670808}, + {9031856040208856894, 7347877633160823775, 2684001693679752997, 1187394758632407893, 2023471202170921576, 11368770613720851227}, + }, + { + {17683555864724676435, 13968533138851757949, 1943437173787895091, 15827749049763045012, 6987423277000309812, 4926724831615296075}, + {17103731276906243966, 10968826448844601259, 16352070254497671124, 16551824619482611318, 10381849412124093967, 9436665416229949512}, + }, + { + {7048379827497088065, 7443977613807482377, 15322620479477551149, 5013135385875340566, 5747364795223736553, 7862606879963470164}, + {12609816404493593258, 88582923555110046, 9264042141620870961, 12622483743145618453, 36832241874005927, 11846454950663675962}, + }, + { + {10498869048482452833, 10139776276152664444, 15056732056726485889, 15099480040493702355, 5399073333783908255, 18182172735172720788}, + {13323470181256898728, 7293540973022589120, 1981283917056275351, 1683846209255518469, 10681059793003383268, 16940960671858675128}, + }, + { + {11079616827562091047, 6298929519625833683, 467167558554168186, 4358762903022032877, 3416306995690695388, 14393771751405339556}, + {8542268838893846242, 13985040364793095543, 15595485032978442778, 13710848327370489861, 12647895656520219232, 18141386123053510590}, + }, + { + {7421011150990207232, 11463423897464684083, 11777398400930295903, 12887147976139911049, 13452389883052007052, 4276539450334756600}, + {17003232901404646154, 5648172435840152002, 9060551298958599769, 9865768386391095478, 2380928329972073322, 16806909077051674163}, + }, + { + {6879794746887651427, 15191659499793488108, 15434300527081888859, 7856295689590209271, 6774603981548851786, 14620245528126721402}, + {17675423419823628072, 5010454868432987998, 9315026554545892356, 15171741100035630176, 13503881861133354654, 13836586572609238772}, + }, + { + {2081093758072482234, 2160302331720847475, 1771001500045437109, 524929417164114132, 948139338327583506, 13116239640907621525}, + {2067558540785058447, 16015346840737264408, 8998465241460291405, 3205597488226039915, 13132850068494171809, 12550638131827261524}, + }, + { + {11487678613186732166, 12226538283374456197, 386046383678908710, 261136384486182248, 6073820936063889754, 338089910147739013}, + {2204520790471760666, 13225443348522804886, 5533826822105659739, 8067241596100405272, 17056747808692642524, 7928554988750665570}, + }, + { + {6926667811451225445, 11361726998764751598, 11858255027279547942, 12874828932074051770, 13844212609147206062, 9229674123496154728}, + {2157148641194346791, 7533189974437599411, 3818533723919763688, 17102113454166535674, 11957918589822377676, 199286897588186765}, + }, + { + {18098297521262853561, 2549150080497419905, 1920476418432176737, 12406241507983538977, 9994324328270480744, 6865216726931218199}, + {10882517499218691272, 3878271624739672851, 2651991057058067418, 8041121093439073066, 2863398953389074916, 14090287437597767123}, + }, + { + {15691539065269187690, 15926915037487623140, 10414347487737173015, 4830265708288246683, 11328595530368816451, 4903535768556567628}, + {12008565653438033332, 1571218720864129835, 1840887482550755461, 6912046034772469524, 3644063824758321256, 2126322707583833546}, + }, + { + {12169143892540109486, 6002799381834121764, 9166177939527749537, 2717071050858554, 14132387690398409212, 9461668085670424152}, + {4615175463679096657, 2777593348175259115, 1086524210167200873, 3727975968832889444, 259602294277541227, 3220284105548094890}, + }, + { + {7567574313834290099, 8145437034220375349, 10888802157352801074, 15444274935766241808, 7033566652389697721, 15084515844524348642}, + {15010111241306351000, 14537704976709260010, 13901878997182787975, 11697236875339079364, 16516786017890903855, 1661580686211855443}, + }, + }, + { + { + {15463648276913935878, 4382144021532630330, 5071136388542935899, 898357497003506891, 6306262877201485580, 7503267895380498351}, + {12209894407081504812, 13537298049306094654, 684729356387257364, 7075405619352396484, 15714299178550944331, 15696888615882072580}, + }, + { + {7477407170849995021, 13555863987096416386, 8646006234528633039, 10219427423139282479, 16098841852404237961, 8497637134921782372}, + {5309688570092265610, 3976413109977205320, 14825158186275338256, 18330027746161861298, 8379597551709481692, 7776375825952465168}, + }, + { + {17368205043853313911, 11366480305058719483, 3986491568217663545, 17776307296855398379, 18166640678790561016, 12400054106979718042}, + {14701884885297130131, 11997630432923609339, 2316884967752005589, 899451448914269587, 12320093108807155483, 13224130717820204708}, + }, + { + {2301120181151250930, 7134427926629173419, 13652391877351066163, 14358476347223217001, 7720954555948039363, 16079187223864015439}, + {16130714394389204488, 15060521357793404892, 6157723303371622460, 388433905262539304, 6397942210441116350, 15870010555361278310}, + }, + { + {8386588512253237744, 12398600073071431889, 15704645810442703641, 13918516392916317159, 4048204874387041555, 14789502552726712590}, + {10953546364075891631, 307391290824075890, 4085950680975341402, 8528936851895154413, 16191803140891684852, 694681636582541066}, + }, + { + {4052072016637665509, 10815871552988988571, 8015406219413895615, 1996664536108251392, 15055672969658133547, 11345388978032390658}, + {3833741327008156172, 8078127745144700769, 18219007769895676040, 12373542083253387973, 10749960526614124693, 5297937097120834946}, + }, + { + {6473608164798697997, 1704324113009551078, 313510886399003784, 7482485442761088384, 3630467062499177474, 17889206319568130728}, + {17813422549220613506, 13365489546100356563, 3642293795923051505, 13366391632389811062, 9309608098424960759, 15583860066261322393}, + }, + { + {3920285757492003115, 969197763731201452, 16178147428848039825, 6611676964264587135, 4670040846705473526, 9965087165592606467}, + {9385067634888736531, 17301457722800757500, 6213258855206728473, 8445301014191943446, 8142518927165972910, 16360532488199989251}, + }, + { + {5265906353635046495, 4989115549924370545, 7716029377102384472, 581999053178428771, 1927216309428257662, 16726029285829946215}, + {13608385105784378405, 16390741907364333262, 2050639151388485496, 11880595111878011177, 11418095767233061977, 6193391483702304675}, + }, + { + {983944277502152387, 17618013366706679742, 13527856424316363938, 17809004578576556920, 16807595463159644124, 12659014490378234561}, + {16660215596018323668, 1845548200977670934, 14981347628825634975, 3292665052105349975, 1255560706381478700, 16841318968187590600}, + }, + { + {2665344548535488753, 10749679950323224770, 14480048826753464948, 8103744201764603054, 4292621633536097205, 17368247036505307539}, + {8629653144199349731, 15713695068648974367, 1391688109689860259, 17209900783908384199, 16396814162862442509, 5977962909365766241}, + }, + { + {1765723133486333001, 13553591410290383834, 17120307789275811780, 5867585200918539797, 10340378507202539704, 10417992971032525897}, + {5521483192544399925, 13339071700237022049, 619482636797119427, 3159013689121603910, 5024096637477394285, 398928734167456668}, + }, + { + {13703486582158429978, 4835870969542931590, 13849753374989811859, 1366566739320000236, 17404228716488772409, 5130516311326930222}, + {6137130478942191139, 17716584582497907230, 16134870936885120581, 12112071202840308227, 7545387975022640244, 13816774847829473152}, + }, + { + {971030984593369643, 3220347373596070794, 13959149202405537534, 15516864884375555266, 12029622495808712626, 6647055389116471320}, + {11132585267709726879, 9838206173776721087, 1787590871969783091, 4539972049341594577, 6034675663835419496, 17293055497219064814}, + }, + { + {17570642940564731459, 8213552062444081653, 15593226808110603739, 3879030828893359677, 13433601001024396878, 4211122738890174635}, + {17934189169765241763, 10790041884906581465, 4207951857220635543, 12628418922625498827, 3341984002885074575, 6259488712494116991}, + }, + }, + { + { + {13403761680618042221, 16536343759299396957, 17972613761828085938, 13333143634871897494, 8217080844173300090, 8327319758336938056}, + {11266549251857186424, 5632462193213183426, 12437134888406006072, 18063700593397823279, 18150635335174302985, 8092211028476756137}, + }, + { + {1207108350681107077, 6429062998832911556, 8673250477723521447, 18170583393512312328, 3550801055781941700, 11719672827257672268}, + {9655111182266878395, 3132327691752397108, 14419687084811747991, 13073348421646940420, 5049344006922558667, 14000517852372127517}, + }, + { + {9716991597801328457, 9345079756027796093, 11200045987212678732, 8772280601358427821, 8639259441726405566, 12571033841874242820}, + {17715089933168590527, 11095491120411888771, 13347464584416454324, 485046159821099087, 571976757247075453, 10200902628607063580}, + }, + { + {8660499117188074779, 14226599538335222514, 8340352780522593400, 1946310520997776236, 6787355814568168885, 5153689776891688054}, + {5667308841323258461, 11049803545816366962, 5483549481076210859, 2650281183298359631, 10767231237699743035, 9742809143935952370}, + }, + { + {9986140370114486237, 7466209585105907907, 1754679179647126464, 17945009041507108637, 12527902125314539776, 6140813986326054524}, + {16393207997039569607, 17870467338953320569, 11842665547915567264, 13006120953816441470, 3548078985168965983, 16007487616892315454}, + }, + { + {988676199292814316, 13795038563960075881, 16898044307644951136, 1804989563201918949, 2415690271309649768, 1403951095677177318}, + {6559788013277581301, 4206972693543414726, 18371258651929788196, 16216427380122603337, 17635684431775122262, 9400941069599463959}, + }, + { + {34276850896178184, 9065645945697227102, 13317573345776592985, 601525926235193053, 9217981927592209636, 12309969749608407478}, + {10546130936371370328, 8868787171248972574, 10889253363563606858, 6066708084552745229, 7944441856950188066, 5353076020090917453}, + }, + { + {14598544504315957518, 7432571723098985759, 10858597307591799424, 10923605445845404997, 13436652897726474200, 13271716260984755076}, + {11746484360997594567, 18260883576159652569, 16536705360207159365, 11555128771579375669, 12265809109975236207, 8710014081931635373}, + }, + { + {9533947271063157362, 3972341891231849936, 9209964459552097719, 7267309578223077779, 13770805495144557607, 14101871822520603545}, + {12718640989104832837, 8947514731845143756, 14070551777157757491, 536892280925814178, 15747030266203480092, 18200278268968621690}, + }, + { + {7077130438749295216, 6779238826822620474, 10474903966971522019, 6820278386136128934, 7255072249237041, 12514067474090301555}, + {7241461786197226059, 6467732564131199867, 3747183394163351948, 16770929168264693834, 17085066469289276480, 9143407880258729982}, + }, + { + {290347547239938735, 15468258237582113955, 660408138412436868, 1302684185031722990, 16641837582246495972, 13735740180315027614}, + {6557401589512433778, 17846464164436659617, 9246161196630668218, 6890950256970483725, 6402204265992443022, 10338073060862145258}, + }, + { + {15430861178767026114, 6156963833198612703, 18365332210313898228, 3325534901104799446, 10271591932915681474, 18275367409906466678}, + {2067293804126060977, 15233366967537526098, 5396097640022364444, 1000014498192944822, 2327452880062984343, 12841411739269464963}, + }, + { + {3385350950958430684, 606441855443472767, 13033776423762098262, 2439357857147383084, 18252952076577877678, 16120810045031173460}, + {15157581942921822634, 4215996528362266156, 6476897491406537975, 5275043577903261598, 17454296124704487863, 17027978976524912289}, + }, + { + {8644752755484142871, 7520506767179250566, 9386137872506045147, 9782131010687153158, 4578495700127020092, 4136883695294906150}, + {11998149667575356581, 11059056827970704042, 12270233192667197003, 2455222920699340298, 9618999184986094275, 6116998915343032425}, + }, + { + {3193697934884363730, 10140335243666665118, 4870491066049398271, 637453714006877933, 14709075847235147331, 13193262757253144996}, + {17938884861655126589, 15835455202328116116, 16378047501426682850, 13063459063154887816, 8093827040207265175, 14470652935631573504}, + }, + }, + { + { + {16034112998441587883, 63845002635443002, 4593001182702153658, 8670578084218703882, 15774651180914872398, 13011991283112025000}, + {15423226930432745692, 4127345328586917270, 1602656434526331459, 3487999218598710668, 1255208198000959867, 10109403147260388638}, + }, + { + {10562160444642241972, 4693105869372484085, 17703834603739267248, 9021680918874890901, 15481929100325334120, 6845602054990892604}, + {16898382896248806202, 5343640296806331476, 6915303502069874700, 12691955589654230714, 13119484603892573302, 444753398747923872}, + }, + { + {17283295680731918382, 10382975592516681859, 10060598265400044655, 1313342669690321024, 15676629915621228473, 14015433292309842706}, + {3722541864418588142, 14316642109988396582, 9534209643602653706, 13980670620545874771, 7954420611695152174, 9814225047068930652}, + }, + { + {248374788036866218, 17964913720605794071, 16982718660501411011, 16539334441772479951, 5999220954131990982, 4565255831754507469}, + {15763389274228509815, 6793638010832842884, 17795140448628569794, 4610627011608977927, 13484317218426525831, 2384269128785251439}, + }, + { + {2064700530864965515, 10923886096271221890, 3965781226482780927, 1349539335778141934, 12283277140753198011, 14288291926557028409}, + {4755291516376942338, 14961944343518391105, 14986331171481011377, 2502562775678124281, 16690683782834868128, 18249446433878083968}, + }, + { + {10500343217363396563, 14604642486751688903, 14821582350585533209, 4360682754333123179, 17373258282956363535, 6560652026876217517}, + {5925790258489013411, 12382625725858582375, 8191985561612267659, 8311548657817207535, 3006895680396725527, 3424975657919705430}, + }, + { + {786181852668121822, 3801037947411321795, 2585057011854260354, 12788225394892184473, 12121545804172165809, 11694085950174284847}, + {1454296081340454152, 12662133117530554350, 15386954396026382518, 12188364006311053755, 14067469636462237943, 6286019250473603394}, + }, + { + {4641661046536668968, 15004063183056394436, 15294276007335774446, 8657963759909427419, 8639015101221632772, 17792395880030705551}, + {11362725454724497258, 14875854967673364453, 16443994946864117237, 16738074345499328534, 11771999957157378351, 14373743150670458553}, + }, + { + {7451471218366369279, 684245731125347196, 15398340817834830921, 11295766022223517867, 13796419334827571161, 2612443196993735753}, + {7266302045333075703, 17867476614955463252, 5444704239473117280, 357656867535988264, 15166074865462198557, 3395143793729939538}, + }, + { + {9509682271313714077, 9145094498501491985, 13014758147649818691, 4392894942493592724, 11373886379849938565, 16136200415791294662}, + {15645599976658644512, 14840712622512041213, 3362514637218698312, 15450726990483884945, 3596435004543257072, 4415992810307073795}, + }, + { + {436726982121698239, 13056502432887055088, 15945046688454709231, 6523495243194823485, 9810653958526702955, 9848069844181259583}, + {16826626473951948582, 231037515307333908, 16194400318485741693, 3341139243875410050, 7198330632933430971, 7499173440340466946}, + }, + { + {7368601478194798007, 12230035070325836486, 3516680325632927852, 3369692206924057126, 3839719055081332823, 12595556495411997471}, + {8654493585319068452, 12397958396131600158, 6963511070567779898, 12454283910184705082, 15562030337854730099, 15142592400258359045}, + }, + { + {8837809708004032486, 13277037412298218780, 16996196458911291717, 15020576394594692202, 7172043530412198673, 8471665740380245865}, + {11048001909658695452, 1722104415157885624, 16816688571596127304, 326278451259665665, 16226792594575388803, 11568977043541034616}, + }, + { + {8456421891774413106, 16587861652105824697, 14920803257030657404, 12140658454692956011, 2890921724026031732, 12248872106995059646}, + {592841531535126012, 9580494709626759695, 6803986786165840954, 3665682418447597915, 8504060701005800264, 12144369197475287665}, + }, + { + {5922269777496758330, 14836479545831353112, 8253590747960613367, 7431627931206560621, 7537389025408568437, 6545197178800609703}, + {4783858952421044028, 8590095805578721626, 1536842665057149294, 8541415499733223192, 314926954266960247, 2029622086554107518}, + }, + }, + { + { + {4552857008992046677, 7742982176237677764, 12614777762761021709, 17623070834843911177, 7352134649339042116, 6424241685372912961}, + {18284550672507410602, 4854060557681920993, 10258397549646077684, 3584018295573283683, 17668477552040944899, 13192004216363332229}, + }, + { + {17395497660961887899, 16009800729326461553, 3265273913749573846, 9525956475609557354, 8008893070464926044, 3999458899476097125}, + {5718380022945515412, 17235833906403176472, 13454747352995042112, 7452239822974730986, 4102392695939993093, 2803000540861803936}, + }, + { + {16618737600557794728, 2033973305346022392, 13031336632325068307, 7832039322814057742, 12529462370460373850, 15738577000088471938}, + {277987228557519899, 2457326519366423538, 4962659838606449004, 6462045821947637749, 14278115896296845634, 5493465508681078002}, + }, + { + {11771918065257941348, 15959999845581824982, 8970191473775898411, 11027278633783758541, 9400158449323034551, 947901598666525928}, + {16512757415387632108, 12706593809124338887, 6988242886781123197, 16531083476591412578, 12943906174817632915, 7656648959205801931}, + }, + { + {9950095340907991327, 18323483036824977356, 8826742511566055218, 17289678119472024221, 16533507249962244789, 15598631885516380765}, + {11278387603777833774, 15536595680256820784, 15785905710436386503, 906326985858832835, 17435036139151677190, 6061369501778984272}, + }, + { + {9936222309360295519, 612751096165259792, 6985140021370817962, 1577482019780095971, 18261512140175647300, 2268925111829825997}, + {8997280151950305277, 15099942588201541647, 11975082702124791135, 10350894913803197836, 3939026946439666522, 15071423278799975648}, + }, + { + {11100833451065161224, 6687431061458662316, 13938739712482703228, 9097524113006971645, 11310108789698970481, 7263803389930912069}, + {7579732541402969223, 4427494314869998923, 17444201060244136886, 16922365472232600409, 4405012916660752532, 12070687041452080974}, + }, + { + {15647519617270108164, 117991711471445854, 6393176877020591891, 12580017776760024469, 5697272146318734492, 6061004989930742460}, + {2473756929649050129, 6642185257675347189, 11657278544254761788, 7595244572280804026, 16987026974396265658, 7603680608840671838}, + }, + { + {4641817200788130074, 11411582570279978213, 14271172827338073307, 983033021155616654, 8960364147838313835, 1083015732588609826}, + {1497200903677486726, 10353458850981831261, 2374066392391409216, 14420375504998989822, 2686838733391603031, 8314093359533890676}, + }, + { + {17496508456763250145, 3725851402903874990, 5215356232054038476, 8626178798561231122, 7346081438096983294, 5668902882044010550}, + {12691479253178408400, 11602632369474788625, 15888416067375784848, 5084998651123071836, 17687638434614023978, 4748093935259778032}, + }, + { + {7012591365105857634, 2874880375540929348, 3220174710965004795, 3059517961108662801, 782775158531417858, 5458085543118651718}, + {1041626186007335450, 1540954764582416518, 9157012689553456216, 6955405647089997424, 5200809672173570153, 11421235046137546582}, + }, + { + {4523124602653947973, 5836966919029851883, 15986368381641127657, 15621634437004074460, 10729890475855047355, 15294257247680785512}, + {11285439807747745101, 11111809578467323610, 14892047086560953694, 11048499802178473817, 2516056791328163076, 16852268565013832233}, + }, + { + {16471199282876861755, 13210632438290224271, 7489191141275166803, 1018062459034819295, 10390278673880097194, 8531679383922148028}, + {10429530876679392022, 16263107527863893420, 16501163786286139551, 13280134735187206873, 1020285771945898492, 9886235265786298880}, + }, + { + {3953361034531375110, 7386122381239091719, 14255034285668453820, 15785522167361485422, 515961023718038653, 15929890586479205538}, + {6439493683049357704, 8056685472536938535, 15913828424728076669, 7849931732449815279, 8828673947015448236, 17381185117791234015}, + }, + { + {6935262837758552669, 7238290685472994963, 12638530517079483671, 1598710569731665524, 980245562699768920, 877454677177454227}, + {13771635882215066620, 16040753974649338826, 7896323269797579290, 788789760541962817, 1510803060770395652, 1869615403943907757}, + }, + }, + { + { + {5531580499851611686, 13083938152796080580, 8093925535259937316, 17200389625360018863, 14842037215178251796, 11988119859109137475}, + {12263909710787132014, 13130916007869632497, 10441881769690738090, 16476642241864490775, 13984242664609457262, 14845292102137925557}, + }, + { + {12517076146320333530, 10291406855889954894, 12064707867419687573, 1502641198165310419, 5109759070771650866, 10320287993169153654}, + {8399783621045104794, 4798114569651528165, 13755067856098540412, 16302764698541317278, 1003238627835525562, 12928911232568933328}, + }, + { + {16493640364904216538, 16952576493628188735, 8338786068864117560, 8893685516440999887, 11383847562341498629, 5266455800998421009}, + {11752729420077323639, 3693269312053900188, 2099384749139572854, 18271582031918815784, 4429897358715577578, 3927504374421523062}, + }, + { + {8698070787678755125, 15703050641810248638, 18420332370057065886, 6522943156759230092, 8207665535041398772, 18112327861657685869}, + {2673396578153201579, 4785641887391457008, 3201343168686834345, 10594426270740968521, 6137975018005068614, 8967572499474389126}, + }, + { + {16980781357310728815, 9400368845185156373, 10978677447297186946, 9679748460996475145, 12732154117709762699, 11885892661392904979}, + {13639001668971925003, 8287641087844004413, 9636673197644968413, 11135961857199331499, 1593345137419156162, 6112607232727638903}, + }, + { + {1618121961524149483, 7125019653217610280, 4135046824878421576, 5280859186376679590, 5657048372118791602, 2933466611636648975}, + {5805664612181580903, 1205209836997769509, 6806945599172222398, 15385614052211122330, 5146598126955318559, 8075018016062999662}, + }, + { + {7764055997887316625, 3096247021063747628, 3855058303686011896, 8368825559451644110, 8834573136185883032, 11962274012645814108}, + {3892254476562240873, 17250665319194659862, 8912259066218683223, 165112253005842692, 7958059294996660528, 2841248137703216850}, + }, + { + {3680472053937419225, 15818262971662536925, 13906534632021415373, 10388162304643816807, 15630768198665438636, 15299740983304379113}, + {15444479968420088661, 4725578511733068322, 6592797451123590955, 12644252808393788891, 3368737811520598812, 2557827868369225502}, + }, + { + {8738552487289663521, 12798020703054253540, 16285176121985392361, 8515295685945774862, 13775150004805130289, 5480066442593566352}, + {1832062561221016724, 11474440365914311748, 12840477284251180526, 9418012590905495131, 10980357385153192796, 11175435945147283367}, + }, + { + {12031563579597435632, 9205196637096882542, 11184135606984465931, 1401305294056001956, 4011048655023979025, 6048353554978805897}, + {9981078758998137503, 2677269315040497841, 8661895209193888174, 2176295311480160014, 1399949325842755013, 1287167020178538381}, + }, + { + {14989416317733195928, 5215645857684328926, 7743823977182561807, 16035950733196346339, 17265966818360956995, 8141738386272537518}, + {15308740448260040102, 4819506016918069818, 10426746682594017119, 792592082078639440, 9734028579320469106, 4168164141775623240}, + }, + { + {15110332316914443547, 2454995031938088056, 8681564356238928114, 8347098831687234549, 7523258191196591151, 3959358611912316605}, + {9351830676079593795, 7428833308286598266, 1416453949629038883, 13547349981311301086, 10428277550264282650, 3606337116602082651}, + }, + { + {5899820503488869883, 11958490906970962079, 16075475723156804884, 9886958163106570293, 2336860573252008348, 13927573664175717710}, + {16197429394630719701, 3637410335075415017, 11999182092087635021, 1303728926256486256, 11862646426072718672, 12350194941729076911}, + }, + { + {11908703473110352895, 2298157340739520546, 12948782415344060130, 3891804988944198780, 11457024627994711505, 9170264692053088570}, + {13049916205169787428, 1232888971483236977, 408187673144451089, 9362353849122321485, 2376369338115959747, 14275353516415817459}, + }, + { + {13799005322110561814, 3601529694367639643, 11106772392590283339, 14056629906511810342, 13572576527799392856, 3487092026537252918}, + {8004945340194339537, 12604327154304882576, 9170501006502176061, 7882459238319530612, 10231971368325328570, 12291029816500597144}, + }, + }, + { + { + {12016493313669998017, 12933290028169404494, 7574629307155081194, 11064769132776585661, 14341813749429263738, 15283735852995564728}, + {5619619958275981377, 4050556776362198952, 3177576231622277940, 8943006541554009372, 7305626035911810624, 2218764583069172594}, + }, + { + {9566598936438275016, 1524065942898634278, 6538402437371981825, 7619146568983786789, 4056320053847575406, 12732024686662415782}, + {17127152314608074825, 15674977896298098134, 17387546565573344457, 5579093677326322780, 12742505204554944005, 9270656236439021505}, + }, + { + {9662754095902029984, 11052177687755266491, 6564855675021815294, 3737820401397024623, 9158763078587705755, 18065064980820239052}, + {1653796274043149373, 8013850902639245573, 10214534956928427486, 9886536041863638379, 436480483045091770, 11299718318113762234}, + }, + { + {967339059085129682, 13104166305190785688, 4270323337549419783, 5748057697199097523, 8577924642091241283, 3581915858994574733}, + {16286952775270696590, 10080909121150901764, 14969905990810770951, 16982777697014839521, 10781115824630384652, 10066879780630943259}, + }, + { + {92896671827781235, 2887243649264806545, 15833385588487728320, 123691791239786979, 11763384358781563166, 2158831843887588802}, + {8596741012506330566, 13826523457635717537, 6540594903680582753, 13793962889582160991, 5269794365508943505, 12066409262788357582}, + }, + { + {14160395515480751096, 4804393992065108318, 5865339760971292592, 16944867750437583884, 12346156586123862268, 13893983071198461568}, + {8669655392775136330, 16391668238375635128, 15081288913073483485, 14651450622111663417, 10940438561578281261, 1459769045883260702}, + }, + { + {4763396496514922336, 11162734181090584219, 6254038965156999258, 7654502220362726613, 2599074756235434712, 4175520862838218020}, + {5532712110222397779, 6663653809301337170, 11279470997460625805, 18326970986868768181, 9974042098100537539, 13917964898357259770}, + }, + { + {15546191471293518390, 2963849438433690733, 1598685141972719458, 8898856010516215467, 8627198789811864809, 18213029019475870781}, + {14333200464642291702, 11308787646021527497, 18050331911988613311, 6162173240162706538, 5132865581846192726, 12525247456279358053}, + }, + { + {11888520648547343281, 494917248976844922, 18138185753471197483, 12035073496965460264, 1674990322514407384, 5436485227695752804}, + {5110912561716495333, 3540271208711945312, 16423892434973715102, 12964671785499501176, 9148547701868918153, 8452102921910430935}, + }, + { + {10550849065095437067, 10753053363341312814, 1074211954227515445, 10020702799800602789, 12864406763293784387, 2698115192684535328}, + {2660806710140858085, 6972138123836745017, 15756537040022601667, 3441297371570217231, 15992662632802735446, 14962954137941778116}, + }, + { + {4348443051639929958, 635118108731535045, 2015655861614690138, 7353522871311274501, 7204918312248323903, 16297291314051374567}, + {819730982198770845, 12608785952359657870, 8576080532289806827, 3009710480834492730, 16107946955600658269, 6618414758853382272}, + }, + { + {3553937582483580592, 748557765063505988, 13881146308285141838, 1352625613370615861, 9547466942139744787, 2062114793498335002}, + {14124993439348982791, 16102858923929790336, 11804652514462156585, 5732609751578720530, 714375047010554356, 6431147290667166077}, + }, + { + {16907430455802407338, 651092243779400541, 5558490953571514703, 421524543072162879, 9495583213289666453, 13989694091243449064}, + {12986952796935468504, 16698463546003412945, 8012703590208385816, 7886765190319975434, 10751493468002030133, 6515081698151754556}, + }, + { + {6087474257130132004, 4181631832640612201, 6923834817653851052, 13172825904549355364, 11686731712296308893, 8288122396407189675}, + {12024088251429940990, 3651003894223587872, 1019304847301994100, 9991022902762889112, 16582922336964107294, 16110644774675481098}, + }, + { + {5498126896868064142, 4836747456186980397, 14439451922445606120, 2540627828887613339, 14545261008261773051, 11467969799607449102}, + {6475133878892579834, 11091521615198288188, 2782411639442406711, 5318254024968417786, 5859257904336594124, 2341590642428951702}, + }, + }, + { + { + {14518481408695687669, 2095771038881695915, 15826157616849474498, 7631060871632259188, 7943802148536381101, 9960658929149574973}, + {14220929306479180052, 6691269956130908121, 11961714924677727754, 9368323637302814513, 7291095832678254036, 1472432228204364122}, + }, + { + {296235288120767705, 15980896506163657127, 9062593919771909466, 16125661299672370182, 9635461578488266018, 1155136620315591386}, + {15542837136824990624, 12143968280527693151, 11763598774950389381, 6763568060848908383, 9078265856423831300, 11111306292226892543}, + }, + { + {3439881221278078059, 14900693561020779474, 5254088415616219888, 6252474065701086141, 9557647970998076314, 16557080478909731651}, + {17984691969139760073, 6920275699694311708, 11586093772939554855, 10567368687255256163, 5080233168822419117, 4328516116216989313}, + }, + { + {4596402599231671431, 18270370190796421118, 2306869450531067189, 14899242618385405087, 5573077655838651504, 14786962047597110553}, + {8824292366761823595, 4280831893742429953, 15856753721134043278, 6520053395038611912, 18021729931870278099, 6369767037287702722}, + }, + { + {2092756234911620351, 12191998366985012384, 7450107522245627844, 13887131358456374402, 8075627236568549243, 2080029865308854734}, + {14564437191532160823, 1248159409055904140, 11241915899684752873, 374881929831255064, 13433377109261039811, 4864742963124465747}, + }, + { + {16241148550837149451, 7822351548402593379, 8309026501457287155, 5103819580434410766, 9108794158669260903, 16488989256917731421}, + {654044319854628751, 4653846517548435917, 17199712750191435016, 4845695359451199828, 8117219445563926224, 12507860620472651305}, + }, + { + {7653070797102301348, 5941550290626705984, 17158569969337658821, 9643823508741141673, 1522997131282064389, 14961110431686131034}, + {11802659136406721500, 12306955104612554951, 9514149419806882461, 14375242488313250733, 5052075298187092512, 7410174133191576572}, + }, + { + {4358758092801908863, 7341423105081917858, 10291109018391718430, 16808750129865208976, 8165688726053843552, 6688211068991597475}, + {17960382836450267765, 4303165753492267405, 7660091042153170442, 3855051391425497455, 10928187542174197484, 13179854521947504240}, + }, + { + {11914960295850256028, 736894971573607460, 12038994816721001602, 15765970801138452754, 4004778617735408471, 13131827739122379797}, + {17423943862970446994, 11783909998933696219, 8224961911959792292, 16132329169568881376, 2487867689899583885, 15018657522918867674}, + }, + { + {8657571447411467172, 14465724378300467677, 7456925156021131657, 10099394822944333635, 1108995305500533003, 14670621046876829893}, + {13859265344673965228, 12642756285805199588, 10618371399223472359, 10368789075142392456, 17024775460445275303, 4836741220623357252}, + }, + { + {13978074604430806636, 18407681732775924476, 8539556435113599518, 12436983718097546564, 12305195225429220776, 14562179379065953930}, + {6423549542556077018, 5040755781466160241, 17482453842942123143, 16447448498858010488, 11479552475069053178, 1277752221540085617}, + }, + { + {920233764095776718, 3319139992705676642, 10862716399636326975, 9064714243076616640, 14300958971895109720, 9740515883782303421}, + {6704838650099908790, 13781706302104941529, 2159164314515365763, 2657942042243527314, 8728543051894613622, 2325932806770059428}, + }, + { + {1967422502593875213, 7041760415173107577, 9050221304247474093, 6387184238732181908, 5042857585504795697, 8540152121523996010}, + {12903368152967462170, 12590063752208819611, 1933648838835739903, 14309714702251501120, 3968656691162699954, 7006655092536063292}, + }, + { + {4234961586345538709, 4555151906871493852, 3232985920750903052, 4244526539796687845, 9377328776465632031, 7060246266590210233}, + {2853784874472922126, 12423531525688330431, 5274221307163072241, 8471968438469831965, 5168569868577424241, 13738202276372145637}, + }, + { + {11027740333858210397, 14805109795564990231, 18001404758531034531, 8113634300017707290, 7136773249584072726, 6460937237419466983}, + {11113010926555478983, 8211408909041649548, 12479292053761376428, 4353008690987758386, 8859777315867880266, 15451653478486520306}, + }, + }, + { + { + {13818182961147912906, 16111231902964497105, 5753266394530009372, 17616272516546069710, 7303352128999517861, 5933646202109354624}, + {5921806076173096907, 13896009253778745778, 11309023928924737855, 4469463255182812436, 11037920326247304138, 1421676035563246889}, + }, + { + {9963872303672903223, 10215244336266366950, 15328675269518615753, 122600537279116424, 7616143723151064557, 10569183306278169313}, + {7031003844724741558, 14407986305911385591, 11788159030526689129, 3609241791309434129, 13905596487394238209, 17665966721516237541}, + }, + { + {2594699758954057096, 11341478545067279123, 17990597733287642429, 15246802590252455327, 8353870017669333748, 12614437615817297240}, + {6394781505133818163, 7425571888170698179, 10395654478962895608, 28575799984957524, 2682124171246326926, 3197867099218106953}, + }, + { + {11244734218150742610, 10723159354785424855, 7484860387130692692, 2467563150354920554, 17551980904639200483, 18441274508899025558}, + {3676988885705600635, 1865990625010728131, 10102149234595216040, 1252552252382716358, 684792256577566866, 6943047702176820428}, + }, + { + {12653542557867698652, 1142433072335098633, 3314552015716235100, 12422430364987401619, 15277043111900184721, 15734019630472200325}, + {15919711988870913647, 10725565601222767370, 11290906213530487192, 4662157581039009933, 11015350972696669275, 8208086286380460938}, + }, + { + {8149565212922680035, 9567944225255802618, 12487131892260634436, 7443172048029929426, 4305538689986215677, 4430546250909191430}, + {10741221950240759364, 16545153560365439267, 6755029137094727228, 81110724808247078, 5717471797282522877, 1486218088878517808}, + }, + { + {9544854622790528047, 10769761497113177908, 1502686769356489564, 11081322603706834961, 13364711539216168883, 5094854373914013146}, + {16200855071998899478, 11725976297239923532, 3061711654331076059, 2493583541459486142, 16389197377130664032, 1243320213701794262}, + }, + { + {8357050367418458359, 5525355159387149167, 17747090324964588952, 15694673113104643586, 7307621991317580676, 1289366645950419281}, + {528742783924328467, 12856892207404403478, 7148581103958210921, 1069895320583652302, 8428983332864385655, 12605554700259997922}, + }, + { + {2487016972575222431, 707675339208452706, 13435953217565346444, 10759388806374516776, 11194720901200530938, 7026549091209652010}, + {9613174021959686236, 4467223759668079541, 1818968857637375440, 13722755860101057871, 7447888855543394914, 11546251567136013168}, + }, + { + {2457098738888001184, 13436425175767521555, 2765094396909275573, 13944016834209830039, 11092919542763411502, 1754742216756443900}, + {3000476756681394440, 9364034762555019549, 6876992788712194394, 3585709061747683458, 14106253519316541506, 5279212076903345269}, + }, + { + {10813235272482429086, 731216775886127646, 15234319760355729449, 9466303362664776229, 13159285075818128580, 5734182119311122400}, + {5552097949831952705, 8072700375309437721, 16694077426905656662, 6836436096351296392, 11231592576240564431, 18047071890971042931}, + }, + { + {1022254770374886277, 9469459507582571128, 2689087779341478977, 10040558278837523393, 83202215085697759, 11389135963216852624}, + {43806665444650760, 10286022177325133470, 12773072940237016578, 10992425690329167747, 4947183945666379415, 13675981203969163591}, + }, + { + {13477598317485536079, 10040066752150433290, 7405123541490280851, 9274383932346246150, 14309192723531202554, 2524700381746668787}, + {3616389453203314756, 13581678150808337225, 14540726193639627397, 3234008850825878308, 15341468248221057383, 3830563877031748372}, + }, + { + {10853619680499782048, 17362724233771660267, 10116273108750733202, 8385992189881504730, 17855585710140315498, 8470682662587365724}, + {8287837611861659551, 10994242426397343384, 7964721658577081933, 4070529224299771220, 9413822451565658120, 12865616140969909319}, + }, + { + {4909175585319342946, 10921727442298570876, 10167667568640009770, 6338375152080033018, 3059470611612240919, 5445884441031512847}, + {2080017510988083324, 994134584813785821, 11859009130969323612, 4838588735676167501, 7193860141357257635, 14012081064531795045}, + }, + }, + { + { + {18027264009080180273, 2475688335442217172, 11495630589568554783, 2044610447313340819, 16211574958831636691, 18082923260238685029}, + {15706469362280984389, 10175042474371958564, 1978937508224725826, 8517309419909857419, 14117179981307010083, 16117021543255946075}, + }, + { + {1511347881429709117, 14331553269818546726, 3174494305719383998, 11632902270807950107, 173546718771105251, 8459530881951500056}, + {9768245664684322698, 16561286001450401034, 8971518231697912000, 10976747460480974856, 5720643303151017754, 10819571526556570257}, + }, + { + {9576152676005768185, 10006989422531598194, 16187127654089665852, 10942929199410456340, 12406093935974963980, 9789646989960898506}, + {1787070800558790010, 15321395745534743079, 10957766159164936872, 8270293817925324519, 6611548955360388519, 811894490473141865}, + }, + { + {1177812967446514471, 1517957963298502615, 11830891177576473426, 13778978023558357649, 5108224327305754122, 14001515739949397207}, + {8456370711154495527, 9224707985240991577, 11975300863666543456, 11628484027954011676, 4106175737255204293, 141089986476922703}, + }, + { + {9131678980253850574, 4479975833350928208, 10129015129452566706, 14596103361459462005, 6870275426489406730, 9740372621433972730}, + {14372377876881420680, 5948925994235262952, 14844830411071630096, 5061939034624460495, 13713851364090957723, 15171884222064254954}, + }, + { + {11883295856694360955, 10292514093729377837, 1018241106247366045, 5734998220934568611, 604293790623280200, 6610275829270273887}, + {12366129529412267868, 18331188876567635410, 5216829119638902498, 8912427667935396786, 9501870605862624528, 12344298042089151792}, + }, + { + {8163932230030769123, 9636016199609023759, 9161423603597683840, 6654511074475296823, 17793619545653824539, 4124609248372213291}, + {11230396913985033299, 16604770927162297627, 15127151935380606658, 17824607882620004762, 10373865240573715539, 16654854491247214292}, + }, + { + {14818683899450679836, 14357841858587947614, 5205003223993289617, 9070636802111036582, 5470773669151086737, 16750045699953367638}, + {14277479053033448070, 16287996706847536112, 15752386157739826785, 17892417758463210493, 15541841791609187377, 4029170486772069449}, + }, + { + {590558285614616488, 10384571122104306912, 5382287961959199743, 1207676815187815333, 13011773384862224953, 532436966815548636}, + {3019650690602626765, 7314252074457497416, 1838949562628498144, 10537471043392597480, 3070353104978729913, 15624376645604971077}, + }, + { + {17115127186232346178, 10621035233663393896, 18371958430819337089, 1193295512905013155, 16614017806526374903, 10388183900788590144}, + {12609314943764198670, 11179941239127206128, 12182679129557646733, 8965475646212860502, 13633585572850681632, 3426380476575326349}, + }, + { + {8276623546443212404, 9482903315384710760, 15538896085254227434, 15790143076571948507, 13143573532148067747, 3184541945442546624}, + {4972549455963732427, 18394646794778833511, 9055568163078599201, 11111002929065765438, 17363710725009368186, 15039897105379313802}, + }, + { + {1298806571453657723, 1042114212262366662, 5680532184394488579, 8926718412388834594, 17803123059561224046, 8663230263216788351}, + {1629533050023872010, 16027578301664521945, 10229699200823727147, 7773663415615911623, 14047718958480228325, 9551563011362116236}, + }, + { + {5989309147210387183, 17849299546447616600, 13296929709722338577, 12659773706196250035, 9857145876253632711, 11836080982965367426}, + {13554494825619368750, 17266926296470690286, 18031413991494048783, 16082997100696095698, 7954101307530025972, 17805255183453764631}, + }, + { + {11764175621326135951, 1791939567018465213, 13029241477144523291, 10840557939557580560, 8381031918646881664, 15423611692748071864}, + {867816783445809673, 6030296688691172286, 5561502310603617073, 15534923164629599800, 1208665840373127315, 12554641657645359528}, + }, + { + {3209670898909179942, 3098303062665745356, 14606274486451097890, 5959844521554290710, 2464075942028132860, 4072466165408271129}, + {4803469398150112461, 13680850164034057508, 11856265931978933824, 13240671495015013351, 15372029486600936548, 16702375458830177711}, + }, + }, + { + { + {18354847664660713402, 9400129736098519180, 1693064830516242847, 8562602303494815916, 13461534639537583386, 12859295804198471696}, + {17914958195244970799, 14970948874889495984, 16335291403269479707, 10631004823344361203, 17176847807154743365, 7714732495833925335}, + }, + { + {14957716628768963046, 17714101461064775895, 14988284950839047625, 16071167094351699344, 13890128763447277457, 4634560608180312269}, + {15209983968927413233, 13604763079237964821, 10947506257796639042, 16898823699351743161, 13294221703899555280, 15072745049022926507}, + }, + { + {3852056161889022327, 2473180673803482388, 3734174223964831443, 18372076238287597117, 12199161160370991577, 5666481007872478146}, + {14306064415346698520, 10330919921159881314, 8823577501055193872, 1854546884403147535, 8350718724062793691, 6987169359640195828}, + }, + { + {6350728622830713728, 5701874018092832478, 1307420847228487387, 12162151629784986353, 9986023597556720981, 7652258640582743122}, + {2186001021201828888, 3639063210548593758, 17939576646917089186, 7727612437620888084, 7790541002958463900, 16125720901743858869}, + }, + { + {7987758804483759886, 15261177063236862551, 14141837944496855895, 12436175571389993349, 8274042047049891014, 17152451709054820788}, + {8637518459734046525, 14044145421979578672, 7087188747750571441, 6313728565256547988, 11986656046293683375, 4860648976415357838}, + }, + { + {9009539789648791006, 17968770175863968085, 7552239675047114070, 2857176040809917182, 17447219567921940196, 7265407823518294105}, + {17146273377976250579, 6793545786177262831, 14702522055640190270, 4115098237661381737, 2503118300874563585, 1557013629291304762}, + }, + { + {11378438312695848589, 6538246237007438137, 17401630259167972224, 3718158584776484875, 4653786582172050367, 8204345231064757942}, + {14333075355191893658, 17490753073467497501, 882454733741447284, 13137676416912827511, 12367922995099391170, 11659416979788208350}, + }, + { + {6506114746421938896, 15057654379054626074, 15301323392829790768, 4198974549026211659, 17765210741443108016, 7132509492152477030}, + {13814681355173788286, 18227429366563277742, 5706529263838269680, 3305860129954779061, 6258038612413033234, 5553019991310521590}, + }, + { + {2740541731000766119, 8596175174200043370, 15268406586850192141, 4422842783758936070, 16124815896970518429, 16832763608196271685}, + {15434766743141189819, 7524954445211264826, 10235492655871568031, 8982274848184708554, 61280556653488570, 2365856772460075321}, + }, + { + {13157569055430348176, 15120480921106359700, 8907221703681745856, 9744220876937878792, 12735259395540542647, 9934004250126983654}, + {16718615067756416460, 410404144349530529, 6127062667806307811, 13658502470838162746, 14801118008320529094, 16148996127797465924}, + }, + { + {15802530345131809115, 17755831194964343760, 17769515049688374693, 7857718956073628784, 210191518703714850, 1746393941813293182}, + {9588189846482137991, 16335835178827943095, 13379307055600165683, 13189771146869278015, 15165452058189091322, 16119082358562095187}, + }, + { + {14291300888450540580, 12179403608989848787, 1574081386467411267, 17634301459964659121, 8878112303286796059, 17677799131162737575}, + {15596184219007084082, 6187497693225343219, 3798717948418717856, 4726638163830739524, 5752064164618039868, 12151699975292370996}, + }, + { + {2566281592983211586, 7556513094797110610, 2450166108042699822, 5117635899811819452, 9378838926483608725, 6536766093196310265}, + {7844966478885204208, 17742733133746826278, 14738531168438873782, 12821429720867364479, 17548355350637387437, 10379676596614787905}, + }, + { + {9312968557225948243, 12012357331777111837, 15378903016229100083, 12000905387706281859, 17061047818694588137, 9595998526695275691}, + {11468745480135275611, 15336669098149774847, 1341152435528764937, 15838536921908481248, 11418408147933255250, 5931142050180490224}, + }, + { + {4126355864148604636, 13615307424696038095, 610122995599041643, 7310843591875371159, 9562945189555198546, 5139192984197086614}, + {16434764370823678107, 8879626425844710867, 10870500519197212704, 10351639341497698657, 2684669702506554173, 12776278319330754082}, + }, + }, + { + { + {2976080374040978112, 15463477607266400944, 18021857121116180535, 12769842468896246932, 3127871016491855528, 16064631537662018368}, + {14779669176601385973, 3776668856093058683, 14901222703045028630, 3232341387704264788, 11524644522032323784, 2840977857469413331}, + }, + { + {5288000162182207268, 6882039810247587375, 8670725030786145343, 5145183205378561959, 5837273482862705559, 12796134768505888809}, + {4538314407891574892, 9060622484855928248, 10762409677748173572, 3978391277049014537, 17437084673881602774, 9597445123068848506}, + }, + { + {9647243303471030171, 14403945224496984264, 13886934807685357620, 17412670052512822239, 5167671672373181761, 11309623208884894891}, + {16223393003006029431, 1419420326439656825, 2369169453814801856, 13061716774043471194, 14634525798681795534, 4751674434384485255}, + }, + { + {4551832817507521552, 2313908657037532903, 5993995178973949921, 12447883782437853955, 2555223230220912865, 15167076377045730267}, + {2005335384595372774, 8714558357337187482, 14553513576888660757, 9344637821077197511, 11470542328000845120, 8444785364767260640}, + }, + { + {4138889373221767098, 12141056423117115293, 14874649331180645388, 1705049756225833969, 7848874201060248948, 5156845906941397672}, + {4861831505262375336, 4347196895421922491, 13681671418165655661, 10985831839263041306, 12731646375130791986, 13097670606652769270}, + }, + { + {13662345490304024129, 2974839373795112820, 12056507699680569779, 11760177245091509243, 1304067584530226034, 5993077591223164847}, + {2387375708577719238, 9626459487654222268, 1955587799597889262, 13097747078399605477, 17202959331606801221, 2329556196948809962}, + }, + { + {17812987452373376709, 93922986227836615, 6326230905711504623, 16126249753219785660, 2455759288569847701, 5953549367496130585}, + {330019371493755212, 3787738706597361027, 6252621554557272655, 725518130284881658, 976894057381550612, 3762034607037675717}, + }, + { + {15030213828999353996, 7537307216693595568, 10906817211901741334, 12978201161486570836, 13688879460912198344, 16875104360403708899}, + {2236812266517027774, 8283440131031015303, 2503310362171705003, 14140140152955857646, 9324835099807979519, 14222655865872085142}, + }, + { + {3744645064193324992, 11767671095853168147, 1146189435518138409, 5628986181810339417, 918940426876816812, 15936037265796453016}, + {6613161822954084270, 11628888581784661943, 10812400261220740733, 18166624472577344261, 5876006248392439801, 16310306694834328246}, + }, + { + {14125633931334589394, 14751339378917740218, 5150510528739010610, 14276625313476908582, 428670252922191956, 2631125662043419149}, + {1617981761951911336, 11583305636829657910, 5101252848640834978, 16667317030245715710, 15236201878077258476, 10871787548070323489}, + }, + { + {7447893961295274471, 232689431551823296, 13869806697620401084, 5330160866804784025, 14865575443350752261, 1679832461395111529}, + {13432840916023326626, 5655812378144376418, 17569608518110186458, 12501129428357124126, 12870492098064776642, 2977413908822477380}, + }, + { + {16051075988752124526, 387294815279188176, 3113985811668805632, 1973998868188061597, 3007935075189940834, 1096206135454331889}, + {5718521169091374159, 14981024399127745789, 12740192428843246945, 16002483798782724245, 646320423819307823, 3798677800777828461}, + }, + { + {3175319352668641931, 16660628462131386552, 6009313219444175330, 7678412375003613097, 9306411708347736279, 9935327299823143180}, + {11559141188091897348, 16810520437389758501, 17490645749839025712, 17259327961568124278, 15274735373631914960, 8983416743854404564}, + }, + { + {11963348162499020986, 5141506614889163229, 17433303046800477704, 8199586499645960554, 11047244048987602943, 6043499675044562520}, + {3566164965696214407, 7496224733250850598, 18368140720280229179, 1567369354656910484, 5448980629729479630, 7863641419129732206}, + }, + { + {2725337558589481703, 2497570082780513054, 8145569365382441623, 16909216290827518100, 2055218062540628228, 2415304909498436767}, + {9493217182909039176, 16224541192418752121, 7654146956830687353, 15910281318968056771, 7566577530597601060, 392195615790859862}, + }, + }, + { + { + {16389181503826270360, 12110241482308603158, 18288412366208628916, 6215500050936591061, 6014488852457703712, 15271085167906108065}, + {14292078858945118972, 14481422217835125511, 7781324865065249448, 1680769593324888263, 10152646427558791174, 11660961480686650731}, + }, + { + {12596615897631832150, 8821755551627965643, 9377179163931081776, 39054669779258365, 16376149550862611797, 14563278930531491140}, + {16172472663040388770, 5190287148139844803, 9110064025691300865, 15647288432646291523, 11591045834006760644, 844689883380316992}, + }, + { + {13548776749212678702, 17662168188358040525, 12032615038574171326, 6080133567086225201, 16938431180779549179, 3443895457286094158}, + {6436317213424755334, 9475881081120747064, 8925950328230980837, 1431876965977827621, 2014835158760914736, 12987015014298314305}, + }, + { + {6414994335254419743, 13126391477045983044, 7334301732865328995, 17814900833709399507, 4626754175182728225, 15638724462213933799}, + {4525732141028097375, 8291242304314061980, 7906228613924545091, 15172916208217647131, 12973611124608613858, 14415032784796747468}, + }, + { + {2941763674782308367, 8542334074892503502, 6518009639926774875, 8175768187727642229, 6810163642801138717, 13000888070357934506}, + {6742587576626772316, 6185408768536176876, 6199936764943605186, 14449234849358571084, 15099106384716206744, 424689763956421079}, + }, + { + {11352046731905647368, 13199556803131515747, 5716134925316732088, 5648788594959551026, 3705999902843684565, 560536953153999361}, + {11871652593424132117, 9835410362049088550, 1151003289591121644, 6319035178000560268, 14320824175339506736, 9395144506212799342}, + }, + { + {15455730684964191688, 10234835525295487673, 13182207266101117103, 6524185547415883508, 3326725631592873861, 15008535546194382452}, + {14902727792883529480, 15934241170433009830, 9499368143445027089, 7932650776206057878, 7397463728482754856, 15064673712954012572}, + }, + { + {10466244619397673266, 15399629207270328335, 17269983148989232532, 11915757566815614941, 10527914924508876394, 14191866475212875708}, + {1195709843044148654, 13844920180243298721, 1913057717019589478, 2076654993296600487, 5771535096432721647, 5276006344600556560}, + }, + { + {11597571737530846199, 15087369689361537037, 1943002093062010773, 14166422307764789509, 9566693410200051474, 5715847907279017779}, + {10365566668051221446, 15849087890611260377, 17862304002596752565, 13346541298411131391, 17741431867034125269, 5459305016755278252}, + }, + { + {11716528930963372212, 5531007692335820969, 16480109661368747208, 4989131671065416736, 1321744169687329693, 14777911526361771830}, + {16382233147918448360, 8261406114108376025, 14558557421269437229, 14834971601402563213, 15317501415447267445, 6664947553397092024}, + }, + { + {5785339725163835826, 6971210823493195704, 16124144681939339987, 3475104212436227942, 6049658499241715622, 16458315540661701699}, + {13323859344989042773, 6912561797063467249, 16800874344261680852, 8282162771440569212, 16369106286531876819, 1170526359132776853}, + }, + { + {9782081741251904701, 157951607661604103, 16926146768919338915, 7973413355284153573, 8362125879537081326, 9862990051212466177}, + {5184297884162915665, 10244746657009000097, 17343337497982107750, 10499903102065327375, 4012731889022182801, 7003219507037376215}, + }, + { + {12814653486444031879, 695131493401594940, 5677983402953066279, 12084690974215027335, 10420441289745630608, 14692497896969958685}, + {10769477264375836410, 17164147105428372995, 2619906011157181849, 1415661898003451303, 9866791318849538593, 11584829697149423292}, + }, + { + {14473501522542709727, 10749304489595316230, 2934355198146439368, 11017927560935119595, 5915324032076206144, 6354575443760924114}, + {8112720200285039304, 3582240290765355039, 4273023256712648103, 18427552816472655644, 12422787084653101783, 1105225281604355429}, + }, + { + {17128222588782702290, 13487368180342466954, 18017424846076363710, 8988322008818510817, 4708906557988367239, 7838727005553267159}, + {9398500148632613444, 2222389518787551320, 9441001728156177075, 11730541176540093429, 2854531586000055239, 9731840308469777308}, + }, + }, + { + { + {12818200022021032544, 18304962199648570900, 13782454312217074924, 15136749185545329918, 6562515245419546737, 15005045681562431971}, + {698694633971573994, 4013566334015448244, 14911595848732456117, 18305955879156015222, 6117212666624617460, 18143980466289027383}, + }, + { + {3502426890414957587, 12060773399876551675, 9782583782804195660, 2856421043271709331, 9172760811796379412, 287598491992287381}, + {3574882806715667454, 1471467928527282465, 18213296168373130112, 14471573043027880442, 9733220931679498558, 18238876809557846346}, + }, + { + {1186541863308497492, 9046950340101487212, 2745706024936898790, 4989009340224862161, 12823642979701239217, 17942139398687727132}, + {285479679301825536, 15862959466038586171, 9521459034208492274, 5591094499772746735, 11556872820220759870, 859478641511045607}, + }, + { + {15238342970318237289, 12057224731033370287, 3456414471220945721, 10398678431367169082, 16329262524936091613, 9810430130271885572}, + {507823287632145607, 13852199732643342659, 6599758124440658421, 6281020241660422787, 7196547321920663751, 10793248012346291609}, + }, + { + {16383444525677044377, 2278315169443859734, 10660119552937534602, 11864735405260308934, 8495438467432993830, 17346877704286895877}, + {3849319409996272322, 15807271853256513609, 1281702280418940250, 2373472013096372228, 13886255586271670807, 9001471337887209400}, + }, + { + {126909537204579598, 9749804666000980109, 16255800152061704810, 16609135318627234518, 17961723534307687333, 11140782709978313514}, + {4136643585846766549, 13601295896682468661, 13257346841610635045, 13497111085366129373, 4536183896151771989, 2489943574182543991}, + }, + { + {17280995436445609182, 7102456830521880903, 11461813376456526486, 9119286224190937602, 1677507200155630395, 6530478943017087729}, + {14611227007048719177, 251469378654353230, 4648274799629731126, 18315451912783545607, 16748007467838496641, 8627030552960679348}, + }, + { + {3196164040344762946, 13715698755805511585, 12458229346805024551, 3656509940452321691, 14877033093641476326, 11337317622750049895}, + {13942131585783347058, 18149827011545790191, 14895656048349000943, 16669534928350175969, 12531447672595399983, 13192103245474624236}, + }, + { + {14145917324940179268, 1801646073880966091, 15389460022241189228, 12374720625988164902, 12743858920585304074, 17607177891983515301}, + {15207272938242753632, 10413323271560975478, 12343096097117660807, 8269383012599149690, 15406849301603489917, 5134788699979908779}, + }, + { + {15888200229957314506, 14831411534621040361, 17970009204612188323, 2343767984014726431, 17841302528539551395, 17397648858980735628}, + {5368978612132943636, 4213367444878083717, 2033768727106228984, 14322131493744692794, 1236700335920101663, 9898949435294220253}, + }, + { + {24758834352404155, 5091013253272577242, 2028941475205281304, 15518967929666839380, 18004005068930730609, 1086684650652446553}, + {3503524165121762927, 16631444510755073447, 11468393061269997145, 11182831309911774750, 14403549322101529071, 13276637040909393512}, + }, + { + {16631857123721916775, 12096833102612622585, 17555483922966042784, 6723532965693736694, 5206953889265807064, 5257296707684647125}, + {9873856732725887735, 2019034753037317738, 12416543296251547862, 11111904680478030156, 7089558964960452193, 18166289056279109058}, + }, + { + {10481925795166053003, 6733183822951411784, 2336616077761967501, 16214291345655367389, 1553615587408951311, 17704541651779617310}, + {15809632617388566423, 7040680416264460118, 13227773672965345020, 5249395959455852855, 3700955432488167579, 5695246660982315902}, + }, + { + {1322177735500321843, 9036238380817454036, 7985514519046855063, 12745778131660207555, 7517032570151312640, 9543215009508727185}, + {15511746435670372720, 1582199859560802198, 16232964063663491032, 18413513284071022892, 878561573889774723, 17999994568313632469}, + }, + { + {51610547936916636, 449080743773055520, 11895942441668539651, 11528163466753867928, 5327778117936222113, 8054693531038673087}, + {2883116022051785418, 10880071210182937273, 16424612420341096868, 12563975202447499768, 17898191392637488032, 4341166004500306028}, + }, + }, + { + { + {13532417727291518966, 15621487234118278211, 11434135490251796442, 12174621814582402377, 11920309846702883069, 2376809786088257319}, + {13790218081512629675, 11886070728329073138, 14026033143551470492, 1787100914236464953, 304006454051884466, 2756779920933373985}, + }, + { + {14557765107140528328, 12355977617261039918, 4747772470536185104, 18066963986056971247, 2652951795222371597, 10786073208769016103}, + {11296024438266601030, 10656113304080611004, 8026365448356501999, 2223277656070704256, 11257682407574091370, 7238909102714165030}, + }, + { + {2791395962931366632, 1203894038483281930, 15578449492227701100, 2119859552714176601, 5772832886191005383, 2752141942254219689}, + {10053647313488524348, 5086479179724027856, 17277990771954143064, 15685827892771379266, 7735502714666745260, 9034852030753288603}, + }, + { + {9516343685613462106, 5255139143590615572, 12557738960870331208, 6702052925707924899, 9793008294868108308, 1711520204119625593}, + {13236841202015067107, 11129785963068370784, 1317992927785313925, 17479451244447802402, 13036816126933313535, 12502011338757112622}, + }, + { + {5480168288956527943, 11042549818448342343, 5915412500172865058, 12999251329017129768, 5808021534739634680, 15104939226808360257}, + {16234634328969043664, 3758395717098249756, 1015491288991804400, 5068251056783778816, 16324558660491861300, 1738698513676655878}, + }, + { + {15946881038575547502, 11116762950959791543, 1297081076272427975, 18245256277091707800, 15100977783223461884, 6017885634508292069}, + {16886823282698854680, 2072463130596047656, 6569088142237167338, 1681498520362575025, 5901004614588673498, 17871763470160973506}, + }, + { + {5104558086478114328, 8971286270876655577, 16470947836284805745, 9037729831080471007, 1965555872583588977, 15433240281955214704}, + {15775227419098203047, 9665258145206729468, 6253192577851256595, 14270940816171443030, 16612589103033695708, 15637879580008007829}, + }, + { + {17904034783907348399, 2626038317331972399, 1873258435072511230, 10005975240297222027, 7533652174638142552, 8419273188570922972}, + {1990391844410141613, 7373216149717011445, 12388874252879150470, 16614842721902772761, 2061105669992609107, 9570836984475646549}, + }, + { + {8491665721135698298, 1799890999791860692, 2389734471340627870, 6270039658247138318, 2463312350149470933, 2217609086834055191}, + {2540364179975154870, 13284898623265362260, 15339373729732261072, 4514279700129226946, 9114575154956391114, 2305724692490304627}, + }, + { + {16530141398463115553, 14748291394528377795, 12303798781899702708, 12438876515281985755, 3858890397627964933, 13323517596969431732}, + {9818536194104432590, 16122491291064677498, 484427543635671756, 14180970696306090632, 9883282120273913918, 1968662552094340067}, + }, + { + {10479341768131470504, 2190791104965238551, 2211152119507925575, 2517772887931981229, 4163883984830586116, 7101754214377757388}, + {1318955625560086134, 10530268190194110, 15248667065937080538, 7939869955605316809, 14313273335008385545, 13762768542953544187}, + }, + { + {690011461657587646, 10912073132311140135, 3674573373985417129, 1597723780107325694, 3549368082234927465, 5785289767244769610}, + {10814725183340498172, 1844706750982331307, 3626691260264165038, 5983040194600768762, 14282060651990538968, 3649897431950147558}, + }, + { + {2301048926250107017, 14317366235953485757, 11632712123230515281, 15595916662388747577, 15711429699151908381, 1305749118231488029}, + {10723669266169674926, 5797826425608678920, 17405218711301982393, 21871232298874801, 15013562554137035037, 9701498342635018022}, + }, + { + {8248839050962163686, 188360563145520954, 16729953975463785867, 3169981816175024043, 7187517706576344210, 9124675384823574083}, + {10262932309387547064, 2404363551953852313, 13372721599356368606, 2531242226775172773, 14257983105055729397, 2642170875421515959}, + }, + { + {13319873663433996292, 13089646428714940315, 10556137876882685421, 11656950941183630010, 12276319669931009991, 9463441716524353939}, + {3370727689367607500, 16018376472071193381, 3301478033055661161, 13190011310690675390, 3229558123256164376, 1583255490085522802}, + }, + }, + { + { + {11928390292426988518, 12638952790538679939, 2608009033823001125, 1242834957664439029, 17797992506731473096, 10340201033905982118}, + {10278753530600088172, 14116327152473508099, 5415842384660027374, 8566401179276240818, 4672386168367646978, 7541801451638385534}, + }, + { + {8566538196049418515, 3197654215985957962, 6355192582145549922, 2489061264757130927, 10197194261710918732, 3715293456694744633}, + {1991945499394841082, 3380660455057193206, 9083458464137174418, 3254176369798763840, 9684490403170591220, 10473571146597457026}, + }, + { + {6457826063520179285, 16268949646546946980, 3097451422505225454, 16453171385247691361, 17481519375542182315, 8112355562842761847}, + {18025352535213545210, 3750835203252893359, 10768297909412467901, 17629461198543052222, 10843179524144693103, 5226721924620138404}, + }, + { + {11631805870497408523, 18340134794831315912, 13311913312275168872, 2845528461275777300, 13173530356238926504, 14929218971024971026}, + {2411139026399661115, 17215217074808016346, 18228531498431262439, 6710245408258710904, 10307545091592698852, 15144971226257950491}, + }, + { + {11109750770824264074, 1088007372340209252, 10263956230079210784, 13896899727089451859, 4559138529870539846, 7777534303712666029}, + {15041017330059266135, 14622601734133247399, 7108706896655204385, 7934590922797237644, 7575713521896250968, 3332437975700014380}, + }, + { + {13801266825487496316, 15263809516575468264, 15419536487874300835, 9072780772100611698, 5969380434932396755, 11198543363610134500}, + {4171408162113015715, 10202388527823988708, 4311928890627114703, 11816249602018388228, 16313146221834083742, 16629955175557153355}, + }, + { + {11660286662603189685, 1207956299008625786, 11363359882526736892, 12477550434520668425, 17179867938403281938, 5655901105940295926}, + {136910678421418920, 2416064355587887290, 4502724777522615718, 17912124462718346700, 1361328791937120561, 12111897685488154046}, + }, + { + {8096344270340363443, 2517756701774451654, 9304005451085866903, 5715847369594509871, 9745892404944266254, 6051292773703160279}, + {15884195349114695334, 9517199133306271549, 1066058705882005165, 8365496980814928779, 7686746440596632791, 13176504626066527022}, + }, + { + {5447100387998907411, 15776278570078464376, 15224157255965180681, 16441839948680600381, 8813248177057271462, 10796641304027905046}, + {15358728422211379791, 6653135625270840458, 18255855576461478753, 9625920573335344034, 6295553526678577130, 12814858875321523185}, + }, + { + {17422403916567477760, 6238259464169695174, 11407009829093777631, 14718862258997290816, 14501697263370095522, 18221436165995139407}, + {6055444735226512775, 6768775017420314875, 7196971579967975624, 16790550980878240131, 16309548149795408433, 13384461631727488380}, + }, + { + {14079161021446380314, 7955905127227850069, 6465999511395878315, 7788108352019910331, 6222197449376487017, 4871252710770322572}, + {16673373722646856051, 13544022498694656238, 7378084945975549635, 6707761833586330039, 12377553912462035692, 17347971251371560420}, + }, + { + {14395815921984889730, 16242663560670555551, 10933265444645517596, 5914394225264036695, 16421696853010989602, 5685552142879689368}, + {12020206507361369768, 11602855627342652015, 5200080540337794980, 15877202861979761300, 16623062677785575198, 4399280632997370270}, + }, + { + {1019528443634077636, 6201939062294227465, 2193674349270074093, 17838059521213356953, 17494214752031608293, 1870623058299198966}, + {11485380789709140498, 6901145761334773250, 9249667932906723287, 9945518497873500003, 2287783742604500536, 15642905768346824183}, + }, + { + {6482332546440863608, 7760091220023803488, 3238194504321395476, 11017818554400598448, 15989612191997623737, 17176177776749389800}, + {9233800304624853063, 15940633772893955963, 1055365280899111788, 17832351193102257533, 3728875607894595859, 11458906737664282937}, + }, + { + {8155436981174747409, 4245212880996209373, 7397768860981266872, 12376011921970823763, 6727814153288120097, 4925255243200109984}, + {12956382084478097801, 7578047214327095169, 14028361267843039054, 12893429039763352989, 15016902170609700113, 3952485452273593863}, + }, + }, + { + { + {10212113970351356092, 7523429041914331341, 7486406457607204412, 3324890123572559980, 3609678540132843360, 2779647883674003080}, + {10785490009290216694, 5512178091962365081, 15405389773555373879, 17119053545814414444, 4550915783680335364, 5243325139730264225}, + }, + { + {15514067016142951342, 6798704670058921365, 15788722941232068928, 11593726264526847078, 2286988197169413876, 14828646074338136439}, + {2215588591344044651, 11994073923064762522, 3627301481345142037, 17167985271749886895, 14022445437114653662, 7923678237890136587}, + }, + { + {6611156704115509785, 18035620512627347750, 12381083171658118986, 270239073191874966, 1473931467604861674, 16752630206679926972}, + {13564215097326132206, 4074525343054815713, 177585984812302656, 10624670211816340622, 10109313618255604651, 14687069652115498251}, + }, + { + {16146132531590710538, 12624070149355925261, 3371340830834921143, 3637666900208692421, 12578993021430103850, 8399914141968916590}, + {701294690134606357, 18348654154222046066, 16080787544185533713, 13729499035821774112, 101002779873624994, 6415359183199533087}, + }, + { + {893065980645567055, 9780512522735000137, 14013587606638438320, 2042146894211661930, 4926876227730145005, 17705997753590203223}, + {403180381605128100, 2168255912491056834, 2400870712237917082, 7361183795795049574, 9566809726615509364, 6303637469757763886}, + }, + { + {17460362964014562908, 15586968786742110252, 8494757460457574325, 15624700433298528101, 17318575918908746254, 12652072085873395255}, + {9835587478950302112, 15548301433729187970, 4835168265500394400, 4967939877357046781, 12172794064315424711, 13503969662963117963}, + }, + { + {10829288067385404126, 18368582702063329154, 7495898914356102398, 6638691277000448994, 12421305448095328104, 12913821326734578178}, + {8084574956986873667, 5701547954903136324, 9827732902307175096, 9844605815961285215, 12681790933515557867, 11120448073083314536}, + }, + { + {16068344822778820192, 8689936877594040165, 8315547524451662260, 3879243152723994807, 4538257327824274009, 14758576181122195171}, + {8434922169634574674, 5728614983829345478, 1650023042553620956, 11308715920844572662, 12984057269003477315, 3325170259493507497}, + }, + { + {2598915533513585113, 14183744977018914294, 181474781586722719, 14637209114370560238, 18213257975009888133, 16601151640440493077}, + {11667415477497099667, 14085199965267867494, 16721473494118951513, 14499309470908758904, 12850701150110062639, 2986900412652523759}, + }, + { + {3221589256444770394, 11214409482440895328, 2728454368684972041, 11241800590680666601, 4667060631816223587, 4054750084181257934}, + {16826694011900430102, 11268855356189298229, 17144797540779468702, 8125742309270210655, 3796632567822982708, 8322624158258003342}, + }, + { + {17852794608451085917, 15586644236280880670, 2638796224141730299, 6571369537216725099, 17238484134695994919, 6584002309074770367}, + {332176389297000027, 13368981597643817994, 9475905376702633, 887026676346074182, 2659944342595076192, 9716495411301164463}, + }, + { + {8760436800248748645, 16559589424441408742, 17728067511446087541, 15979039360791931099, 1186131304518732359, 544669493272271576}, + {11512458030364033194, 4234660342823911330, 13269362908985131848, 6620254276755952341, 2472637252854054812, 2804760878774068057}, + }, + { + {15928091392978072069, 1045418146814199706, 7425379098630386963, 16455708007612906306, 5515953762090790798, 4146738699702553135}, + {5126640753769911542, 15649236295646849030, 8100061362821164710, 5931546784464607243, 10980236595948879217, 6825063281664784010}, + }, + { + {8543951044930873896, 6542715458284226112, 2761529550697027755, 10608334059217377785, 5013963483795824785, 12907134297467450098}, + {980382309389436255, 7808952507916033869, 15275563855873621709, 5310054094388396360, 8349155105071860026, 11043771142323384823}, + }, + { + {10152873500779880984, 8921920392860909449, 14073008766417442634, 7574006587459435649, 8742698680973393947, 3634151658166442700}, + {16215510897853847342, 6313231586526240160, 15374028344552157486, 16025015223144590637, 4962437968942642052, 2389997079243177935}, + }, + }, + { + { + {14281041519735018975, 12922311381137007214, 10232502343768314657, 1134871332686858449, 2406027671397524741, 8211135280367851709}, + {17686015482034995045, 13964987788145667419, 7719837707443653733, 11241849337066564058, 6107424228088781549, 6557866097251668304}, + }, + { + {44745771075211169, 12978700281287734965, 12341083357048397205, 1797820217645587144, 16645470871308398952, 5574272877734914713}, + {17391736056610728361, 16032339083920183657, 3446991150741449782, 10033643099742979783, 14851902199569135753, 1830235897561763723}, + }, + { + {8645411699894411605, 1426585791906124213, 3579550076805920171, 9083173147160007694, 11631776499533913846, 8510913582608227570}, + {1541698565399230466, 17192733751495667997, 1610633544366852348, 14882834591025699164, 3805773893383467941, 18227555101610282617}, + }, + { + {7654469169679738716, 17884541881059058957, 1658182501566786879, 2647862499567454261, 3575230054065121063, 5196577140526681418}, + {12604411569045121957, 13620316591036967083, 18197402841216136733, 16577144861751835196, 1856064252812727669, 18261694871001689672}, + }, + { + {4917344388382226976, 6330884756405843776, 17908872738552769229, 5244919991308831166, 8697595492991011433, 4947226470683672404}, + {8425523832699364501, 7754795213298783206, 8063207615592653394, 3563540304379150938, 15696361418241150720, 6209953025795422024}, + }, + { + {10542961880027073714, 14819776903900712189, 10788823732453390406, 3505823457495732649, 7370161041256253297, 7602319824210592069}, + {15683925906988243629, 4273670365516442517, 3693480665904390884, 16506632164939082014, 15344251801076915117, 9664860330838560631}, + }, + { + {13453231080122146905, 6512465127883837379, 7629388504183246683, 4217401442467660418, 13133301451058498685, 10166079809976017824}, + {7398318211270177803, 8363389463704327290, 10324465568426256419, 4965710503345352609, 2089060017802990689, 13427246861509147536}, + }, + { + {3328996401163396997, 14795923992923049777, 2850129498190588037, 2818567789790091571, 2452485851215886435, 10898789027092665189}, + {14647661412525870291, 3599306402736479964, 3756515659636605976, 12815169094441383661, 15786213320252390618, 6231903730571064302}, + }, + { + {10711642105210749960, 3964832036350312570, 2594869633154010768, 7504273439683990593, 6171834057422616095, 12806635729425016087}, + {6242042828168471440, 11746641890873718074, 16615154546579032279, 95454097875132020, 6393615725707696241, 7618061211687978664}, + }, + { + {9930957720367733639, 1077368814711136367, 2417053219800485985, 10848530230418354055, 7260326287853856173, 14141227535390115151}, + {7830749040726146784, 9016206039825747868, 11290344305602325972, 14750454853595294291, 14714683920601490123, 1432121990527736048}, + }, + { + {17441977106390458994, 8730805915901635226, 5819567079469848168, 6321912429222256985, 837082610639548473, 15410302798534400718}, + {16852273756502231397, 8917666851023000894, 14301029351076598242, 15350040486231497808, 1621413004527249197, 13889481477114808738}, + }, + { + {8916394881822438043, 1646293865051273262, 16633458954488857984, 1971089263341201042, 14055873993496913092, 13954758750729316517}, + {12992583064239709509, 1952701756447682135, 5933085826608622333, 3590325588620993260, 18107021064040771922, 5262440036415899013}, + }, + { + {8672666323143994986, 3432698976158862459, 7932092920769909604, 9350507304052696520, 9950195840741471235, 3384863162662803302}, + {11269793069739340493, 6207863446301189912, 12329276380474262269, 10965144619249951761, 97704029241884757, 10457642244982072945}, + }, + { + {12371754360290866894, 1591074855650384155, 8325409655366518323, 11442314427085611305, 10875405650221560131, 7491900189345980515}, + {17244250783259713081, 9507080483851292003, 9417267023896977595, 4243988893984453349, 11064476576986125131, 17158304321030000154}, + }, + { + {5517940657612757396, 4123868648127756780, 943948557181189068, 6078511197957700447, 13220388742767098964, 3184112381859294304}, + {12392153938824408522, 3168610752876052364, 350018255493345977, 2813965382812065687, 11093319528930675311, 6598131031733576701}, + }, + }, + { + { + {17846260309109160862, 1306797101136445625, 11647460062050134126, 4280254741069645613, 13550506007057592994, 18283679445420746708}, + {14822459580299409390, 16348337099471471523, 14343139876287082865, 16111294748648165111, 6270862100768665567, 5789912213367358682}, + }, + { + {200047379930668220, 3107506412723209866, 12635605344473049868, 6454603385777743125, 3634997813341433192, 7438775972421422847}, + {13638641130311201683, 11030479200470016288, 4711568272785668705, 3373744634232082099, 12735396517885935812, 1666767200715548592}, + }, + { + {1661699022230626915, 7732150026917057818, 6874108361236320794, 1159587009959479866, 7007379701174607195, 9952444100833302939}, + {5965322983127194050, 4366859071433931272, 3231323670368819730, 18362879607830583246, 5646154626466164812, 16999943723339328275}, + }, + { + {18089243736135451887, 15837467602480156595, 4979955351269012725, 12695524654989516016, 15309527870169710145, 9923199650873375699}, + {477633266795650405, 6218407297793375468, 13972928132308654086, 6804584457444043116, 11304504344726657230, 16511473903383869711}, + }, + { + {18035621934283433559, 17683775718600141872, 1200977174684534015, 5313684562476274913, 16332322452774063686, 2145323195208686943}, + {1572586157017613665, 6541397378767315724, 4667619245659807579, 6374201727420350952, 18032000221066592915, 2059105043707958084}, + }, + { + {12166351370380034203, 7102163135877977227, 13332299513090850017, 16122777051352557935, 1102940088487877845, 5212887364114727166}, + {6687171729958891220, 1664933694283032903, 14897359728576714580, 5549891844111603232, 4137590082941305255, 10264069531127198424}, + }, + { + {272620083016298055, 17189778207291663400, 15639379971966818574, 3447379160890980726, 10696794611439970864, 16890999064760725295}, + {9003356812390325490, 166360430953008789, 6721503120622592701, 16752071907266696152, 10459887288559544412, 16460372927471671270}, + }, + { + {15720666782902086695, 2243636647767906075, 14348999864993654614, 16530847832477493511, 13572226349455897926, 10485166353342867630}, + {1701375111884628062, 2188828106789127558, 12645689658478144853, 8016727425888546008, 12431997919751623083, 7136689765653286632}, + }, + { + {3054654888507663517, 3901732615579060999, 11618712726777764967, 10400033150633623763, 11673620844004038101, 5065261890057318586}, + {14496601939391821092, 11531645523028139605, 14474922880926708005, 7706650634046982502, 6570274599504352046, 7642596377689896565}, + }, + { + {7699868198387215867, 13465612880023018168, 6802825825452629152, 17947085319706590740, 399098071367693766, 2227253631387109201}, + {7913744672279207864, 5711722633374904101, 16654422138819448366, 1591238867781947932, 13785062295639206639, 5681650681074277757}, + }, + { + {14302942159889415158, 2510726813191413600, 13501150440879192520, 14000061751928804479, 6039954540724187037, 7505529269867033702}, + {18250665573771576073, 5127325503233443708, 14065731457493758594, 11160674673771208971, 15693171419798520829, 17233795126257791284}, + }, + { + {15622130931527103601, 16901855276484525272, 18102024747919573302, 7726517490109845107, 14147913176577212424, 12842015409583521397}, + {8781643538636513691, 12123988514306098157, 16318265076922410388, 17085813739519115894, 11427890478685706148, 13711950220864410601}, + }, + { + {6680912247635161790, 17580838069043296523, 16777963020027530302, 5469775206057287185, 16990549936692332421, 16432218618617031088}, + {16382011306148463125, 16249390935258095721, 789229423855427321, 5584503286135036603, 14761218594144073940, 14540866621986964431}, + }, + { + {9496858985145256777, 6425875918734527060, 12207380394759736422, 7438079918113743538, 696640929848616795, 4155405326832419357}, + {10690817436861400384, 1479037799171245484, 13853435209996737946, 772955156615502406, 16556804502651134724, 13405497439711762710}, + }, + { + {12180390271623191338, 2554198210777409989, 15828648806466804950, 13386302369804389308, 17877328148870959009, 17063001337418714450}, + {14566511491060416421, 5205063642854029012, 15266492670006985909, 10920630473589926436, 6854610609610056970, 4823212255031433832}, + }, + }, + { + { + {11555239510565564423, 102493428844323960, 11265440475505070062, 6954957201906837447, 11578828270036850246, 5363571767815413948}, + {10687688618938071305, 17560569863417444168, 1763490681657096693, 10285148253700502778, 228169834671249043, 3817223026964299801}, + }, + { + {11869614854023374983, 12616170826516189176, 1249571328192797152, 1152755290640443365, 17679907775602849695, 11345355428207169384}, + {92124442948271692, 15136392605896368971, 7174298541623418149, 3977850961259601135, 15260799075573749863, 419190360224954337}, + }, + { + {12941138664806365009, 78537568941164918, 4499564597238696841, 9259817189360690299, 3875404300171494106, 18031393974005709390}, + {14230220635083072083, 8633088687256087821, 9439675871539484936, 10592074684996303446, 5207584782270069594, 16579180203133498559}, + }, + { + {15911051168603653765, 12912915675404184524, 16445705037168890851, 16740563878098656388, 5961314645410792024, 7476305351043019972}, + {11904755216174892471, 4508187020781349730, 1122261304753504973, 6085882050766589531, 8389757320097382309, 13048473480684052162}, + }, + { + {17680809686224888166, 2880007448785334434, 17671705111659901281, 5357941687184787676, 6416428659886206805, 2539295694241036705}, + {15493556906347117063, 15184359621150444926, 15623522089297218213, 11422112823115234443, 10761632026600704373, 10659378440527931495}, + }, + { + {3820135739709169880, 7261377824800497120, 7489769782834815216, 13165627835187312122, 13110045944249714025, 1304982596015592431}, + {10409327089880860262, 8119523470638259517, 3634401951306540946, 1979100535727127060, 7288813164350284510, 8247925357758448450}, + }, + { + {12278090077201324890, 16864061172993697783, 5587071207462858732, 14536122420710742668, 13859058519726422179, 10645667192932212843}, + {15670105262718068703, 15430134228548786966, 1251089591865195285, 2149683357007094264, 1836398382617121265, 16062290149085488761}, + }, + { + {6401472755905860665, 18251568613645282796, 4758943616732471246, 6655672671851225203, 102549765979647744, 6901551898032346073}, + {10154259747808913943, 13030720662056447919, 2754179948730913899, 214967400224523605, 9208467612937514595, 16909326990814546062}, + }, + { + {6054271246698272853, 14544060829566630707, 8136820029398201235, 953136503654279040, 84568208454785546, 14305961879546400571}, + {1732011551860061479, 11399625830128770326, 10400513758237997842, 3165162339732221581, 9416667999137637971, 17092345029934304618}, + }, + { + {9400098298185420887, 5556041148968335564, 6912036430365340369, 2944702321639771461, 13167226429156120766, 18187144612223747373}, + {7959639088001081413, 4236408582243967575, 14543785681099574184, 11098877575745565163, 14302577285379639548, 10484088530600671912}, + }, + { + {9373483053259607268, 3543313042332813439, 17074705243236711793, 7450654168557338084, 16833050907477987107, 16070783762419210385}, + {540551482092433485, 896422619371514104, 138542949191418634, 18265302404419375371, 16792245401695248275, 12353390887345526565}, + }, + { + {3539472665850408941, 9973857813280052924, 12971804241703503646, 7407990072499301360, 9559955945280406647, 14424568234166047002}, + {11096806861225971603, 6816003284380469282, 1147913720130733539, 13720120058704725060, 1399756058361164073, 983212633898190589}, + }, + { + {10664997543956449171, 454517167775805631, 15856261682659737800, 4154393874169146738, 12268872310704088235, 11262767255104080967}, + {1686376439172079011, 12012369940855624242, 6114883187951156869, 778196593644747678, 2384399524034132671, 15059515630710187014}, + }, + { + {16693905404142293085, 4325377301783117143, 2580347499530969883, 1407527347166788600, 17454091049478095854, 17446410903937548513}, + {12048478360023053515, 756323182854419638, 18183393958679661690, 2276830709283047969, 15484089378884863933, 11532985185158241406}, + }, + { + {962670163839534853, 8108389445709454545, 10885345009931744728, 1709075883125195127, 12639892596513679369, 7994345234505196064}, + {3957358292438775986, 15177501453635460453, 5749874344089288877, 13980629880591955685, 11290207695256566671, 6266738518930986595}, + }, + }, + { + { + {2112471176772812653, 5992610445858141042, 3359824065683384802, 14910744199028914975, 3540279332055051816, 7481318687562895300}, + {3778660497841133917, 7665160960416784403, 18344176739282807989, 6652353946044311969, 10335050395834175287, 829161198718552289}, + }, + { + {987187890721916756, 1180893057043299417, 7997694989088471290, 13943477209509617880, 5789135275803442933, 15003053876978578152}, + {11491981179365890542, 9783628750553484845, 78941951872642943, 413130106196007898, 5965786292528401894, 962843809509488765}, + }, + { + {8077344451961036015, 12071091132773222174, 3465673301214104928, 16928369631937685883, 5355222520769513898, 13361191077839573619}, + {10372078388188800788, 16137701973564428727, 16378364657125535444, 14147781750402923873, 16760187636270495320, 7550201579272756957}, + }, + { + {14084923669266627263, 7553568273380849735, 15691370880642541716, 1999581770825966126, 4575194939013031822, 12495949140700950136}, + {7538580687408334777, 17053011349491117810, 1716759308796398676, 16611187257146498231, 8469759805465235212, 12974300428352030494}, + }, + { + {859955691188282569, 13352606119576189973, 3180693414073792430, 5959867301005659300, 13835947303818547540, 162851927886880075}, + {16769940376654738256, 9939117735531953429, 13149699086290415664, 3305357061162836785, 9009939707511121271, 13981210403713247609}, + }, + { + {15280492422823355766, 15236897741281284068, 16375251899685919662, 2375999612321238009, 6002020302005330277, 4867913810970375080}, + {11372869170822493237, 14166186567360268594, 4761141133604528346, 10183261926525426109, 9349125973207534361, 8199961450165628412}, + }, + { + {11291117276267195299, 14973998728699422778, 16425655270225982283, 15329324944689574083, 7979576976920559153, 14994530807417641960}, + {16703738914238983421, 2834957708878859809, 10020001258433278091, 3066018529077593047, 7903800555273951661, 13033393171964190854}, + }, + { + {1653789232981578275, 952371650849832179, 10927445400776044968, 12157933816885775189, 9290507541884583865, 12826421106361126902}, + {551558165798937217, 1729101615745031644, 4791663141996814522, 16904640700879459114, 12874781959897756061, 3513760684524485070}, + }, + { + {8207357056686195321, 11137222442007015668, 15645132451218915478, 3105709674939731826, 10607257435983024941, 16912916807528355764}, + {6323399773421218599, 2748551999608353527, 8626149829332963214, 3316199943098194703, 6716681752170794378, 2936787212120932946}, + }, + { + {15440834838198080689, 931869522652835594, 7592851540253747298, 5478596926880972349, 6652810167530776258, 4577181343372966932}, + {13801964408907248297, 13739037151947376992, 8697064982745685286, 12401883107738713638, 2448777686813372733, 4016677910779410184}, + }, + { + {930435436459751529, 7291335211208166106, 8662147097774800941, 1754832412907874485, 11716049188393912454, 6088054938180223267}, + {14767636360685531193, 16761369108402789416, 3774240452651006015, 8812730740575156268, 2441588704916651547, 6532572576667981720}, + }, + { + {14520642821078702231, 9152978367661523282, 6377069713671652085, 12296007202473970904, 17767917081512566521, 9137555524675129570}, + {339729066832634027, 13577486648345315707, 8784435346186982538, 11788746341130221385, 17389275735918464762, 1499091028328348784}, + }, + { + {6895056287740805821, 15551414767986485684, 18245567068949911079, 11780461279934853858, 17514165768801962395, 4604945067503181622}, + {17970049594076464754, 5131328972180637912, 14013492191391630748, 13860986326135334440, 17262237096531626622, 15447317764876697344}, + }, + { + {9241932972904406753, 10136261935647290984, 2240671992235812692, 17354651007012787836, 3225243242586300908, 3556466132564431774}, + {15035753318658290895, 17220643029876180698, 5318335111039228183, 4424502322878902841, 2675895669690622325, 1884586557676234029}, + }, + { + {5250110106303814488, 1975207799636297674, 13532036578394208591, 3969043079520697544, 5728723625100363223, 7158702673653973988}, + {16195684125677252996, 4149751094169622529, 11846551373222263809, 13787057146822598191, 16962390587607642862, 7670754904406853980}, + }, + }, + { + { + {158721254439694626, 14016472328785146057, 3215742685919437659, 4283116501421190228, 14416945229571419453, 3260361759779720928}, + {11569905182149055942, 13365945824267994176, 9560316005976549600, 8014152880174667326, 8983248355930398915, 6003107822914970018}, + }, + { + {11769244887375954354, 16734798255146218250, 7450660885486578621, 13241415025693890385, 7585701487764431710, 7068349087572048763}, + {11673574025706412973, 12054573315442038381, 3465595090934871151, 14116150045410515995, 16747453732925727391, 2053788472539252039}, + }, + { + {8254128435175778191, 17961721281775180333, 3465171206067904370, 17786859311178538748, 5750765123994852536, 5373889982583891369}, + {5947994461711601875, 4264969794290341217, 5733140740964071824, 566813084550213227, 3008438020483790267, 9393523034553376074}, + }, + { + {3488992165971683960, 5408858964234561845, 3943860838659448298, 10606370049279338924, 1497444843416374478, 5655792335049791924}, + {991809778400186594, 15331432498205269189, 14409135173658903226, 4844024566576229783, 8437358490135848140, 15238255612948837438}, + }, + { + {3981945260589053255, 5238428271891653292, 17666609270668276737, 5136761226420502964, 8998438003563725182, 2026122825528004680}, + {14800276493572942057, 12172612348684122426, 8309771000688236057, 1565694914599287285, 14726316506042877882, 9150853180590412510}, + }, + { + {17340721586269964714, 217529583853973911, 8591243800256753437, 13887006532271166813, 16938831598502428118, 5372377227102637491}, + {451250041397357076, 4989306166373412675, 13630414847684491708, 3996969106514180362, 2275313485002180685, 2301296218808044149}, + }, + { + {4291242465719312676, 10844339224270608311, 2121832093979610215, 16773046612047697523, 10995952484439012381, 12237539089984856911}, + {11585863874855568916, 13849634900022210805, 12285224492680055214, 5525310790718599719, 4273270766854007820, 14699310461571394996}, + }, + { + {13339800343403240396, 7709432974418657015, 5301385839232292107, 2969538953397180786, 3800860603349698317, 2508772359731689564}, + {14378517458066378354, 8882708296441449226, 8558667663066577082, 17076224488360060086, 16842404219922924015, 17095860696531681717}, + }, + { + {6709186302039351677, 8451434297354584619, 4758927276311396271, 12322849161987713036, 3702550498120081225, 16306272953980522166}, + {1037682183893893480, 14663627147661191968, 11571949542375472706, 5714568058845181963, 15981901038671696988, 11976708367028629004}, + }, + { + {11207839561296012338, 4875894249269467127, 5107711364762712689, 8192718242078932005, 5352423725257079410, 3571810293108102994}, + {5515509758059991725, 7457615682786317799, 4860181546702428200, 8930731253012747041, 5659928076906420302, 7496101079865843064}, + }, + { + {12022229726853822462, 14706436872065443302, 3389725333074082852, 1604903701561777472, 8950817588405763739, 13190244158376540107}, + {14016236309633488294, 8475371081917274175, 9944826967483171109, 18053549564499967546, 7930723406558155263, 4626913441465521473}, + }, + { + {2715165459263721907, 9674001561320555387, 12396221282651500645, 3973238506618524626, 7278954243806937758, 9176131567068265043}, + {2372457887719386534, 5022496686095517029, 16913411979107538659, 11089957791594060315, 3232871551299762533, 10181928965032453240}, + }, + { + {13077103522673276166, 13953006147353067459, 13937321564029460312, 11775289180731898757, 9005718366158380378, 13645760323002406046}, + {10332481686150199318, 5314709245555453273, 14740068464959386027, 39846363329861329, 6936258174745205094, 15346255345000921785}, + }, + { + {11902235556304614325, 9716523013532558935, 6408642420452662970, 10910145013733353424, 10487750635963941672, 3263923993556113887}, + {3979263897601764948, 11489365827974628507, 5295637109315505928, 6972999611880974771, 1108442977000346725, 669149380592427324}, + }, + { + {1157132430713125844, 9939423443740928614, 7186655438202963643, 14372268141018236868, 12646427359638789024, 7392025192496396479}, + {11172990535174193001, 1182082134585836558, 2511299207918210769, 2172910944443379020, 9484470871043901670, 1230325285277248870}, + }, + }, + { + { + {9665579348258363865, 2087918080557695122, 135537599087992531, 15215723868160805464, 278908927488187941, 17503720082240216915}, + {5744927809331053213, 13798298316314029615, 9696283778270547989, 4870358740201919966, 3439882118475813321, 4143783440792496951}, + }, + { + {7769489242957847290, 16684864626270304081, 2879249682816493383, 6265076094334458119, 6886499504502814482, 14195770023097875547}, + {2631387143433279288, 16031347118135873637, 2311344129842860939, 12572114332759228948, 7732595900970909006, 14311355333002206999}, + }, + { + {11228237540890978828, 1079293124827979304, 7487220471408651681, 13548174215752533194, 13320332840506137434, 14014587572505105518}, + {10308451336179922295, 1971803029831470018, 3369232812295268792, 4471651358093175556, 12478347644279240383, 16248645353907765158}, + }, + { + {881896658963638416, 2026615415208131225, 1975014851600144074, 6268313587596276173, 15189049743474081851, 14141869123482614039}, + {4695467916519996154, 12465708679157180870, 11422608049605393187, 16598608052494558909, 3756011221236491774, 8063000249101262382}, + }, + { + {5494197245461486331, 15364625217797987691, 1134233848906038918, 7726911346031918100, 15503554540833122104, 9953446955839429175}, + {719175439330210354, 11993546280891538825, 12098356945782186267, 14761662828882868605, 4054521887535828822, 568836477239613961}, + }, + { + {4895604554173507232, 12377758172579626987, 15401866685509290286, 9150363264406780287, 6123727635885171426, 2013086363637951538}, + {1499537875756117851, 10260341551071830418, 15012297749974575104, 11295782034836939405, 14699384490428880947, 4058564242175274162}, + }, + { + {5697099271842625185, 11897498065292086007, 165253007275908673, 8683995743377403005, 12085865296553972670, 5953667974147175744}, + {824129719356249097, 17390674672020315024, 14600835594781296921, 14157907740151210460, 14620516163389564217, 6402637035301660148}, + }, + { + {6814805391879506821, 13733360575773203028, 14964423068624665929, 2845857522246553444, 4737277078061891938, 14974979150537406091}, + {10199845472834911755, 12457032282300718325, 12509382395143476419, 12723831063072297351, 9804751755261218393, 9738618498716380065}, + }, + { + {12971320806846916743, 6373340119401674163, 14940450957165318789, 6054294310918381610, 16262716106286726308, 11738163287805791020}, + {6651936162381007336, 272251828638977954, 16782812253935098255, 157477203834421822, 9758166039167226447, 3757098019902685001}, + }, + { + {2797914620292272718, 6824445594276636543, 7612944636508242479, 12310914090409404192, 5900414063625470828, 1578574444575760813}, + {1746963247281383230, 8358183515669196030, 114807234762833252, 3434169954702426697, 10754906727586255973, 13248437026834498974}, + }, + { + {10367883878888843605, 13209011820972196415, 4546179109832588353, 10048885285637082041, 13740390940277885181, 3897350217203120410}, + {4420913340021562814, 4575173797445180389, 9128196763097374162, 1507217548372129726, 11871635706539357657, 731457449257913541}, + }, + { + {12327596966828336878, 12044047960030865903, 12590450765463213560, 10493254635328920048, 8651077485178084369, 6371936575607168909}, + {5090312744055455793, 17685482889085467956, 9393295431338315435, 15080146787113774018, 8385657726957576620, 3383348226554775383}, + }, + { + {14588590004163196212, 18274572275841358391, 7651897004994035620, 7427055507937608536, 7778320234184341217, 16916348689537901989}, + {2419944192928809758, 8857445667038434995, 11459028014322971295, 8519876766524924471, 8951414995530421895, 11510037251020037555}, + }, + { + {15790971709064914690, 17551616639212949181, 17685426066530430956, 8470300602731078412, 7440168085597529492, 7627174044502506272}, + {1710862283221741969, 13964871482694027643, 617332758617265162, 3711135961102404485, 4655924078995340065, 2113569679148694735}, + }, + { + {2154983266339619301, 11861362304971063147, 4258182409238841621, 6253453232321750157, 15909672604786711366, 1482606699963487564}, + {10258975978079697240, 4952492506950453020, 5749995703462780308, 9651071132904525497, 14977376759992362124, 14011541847161628118}, + }, + }, + { + { + {11998317121553500299, 2582325766599936510, 10226444194055732720, 6578918458494290458, 16856344663543484552, 8023206593552703223}, + {10896969734623517030, 8965286626042649860, 15869898932136510986, 188758287853374907, 3043553330642597875, 4825743274601412340}, + }, + { + {14811264716270138923, 9172209925012047033, 16222958531492700587, 11130963356286229429, 12646613143129669873, 15325043128670486670}, + {11347507763721459405, 12900058314528881450, 5171017319841793302, 4651322121729076016, 10307557446743606869, 6055886709749279778}, + }, + { + {8183782069332642864, 4400608719297868437, 9887680839598123793, 16997602958862657609, 6307175890874383417, 14450424872255242386}, + {6872546037892456974, 8399143418250687787, 9134623456632335969, 13760709404346799708, 12989741448870036879, 2909960824443156805}, + }, + { + {5430907109181030283, 16527229751480129461, 4626559521361924187, 9923786072582407723, 3599523730508604347, 7403949125284615057}, + {4562148631066323166, 5805336986933520185, 8257255431523708381, 4507203543461357226, 5619824380968497684, 11986819821861980903}, + }, + { + {5319261111797206279, 4857131879138244426, 10148248807556188825, 11267161186123495115, 1870130028222872285, 2706665384656124928}, + {17899120971855949667, 3796430035357845496, 12931652797283355998, 8202504218162242839, 4247443200870022359, 11773865795553695256}, + }, + { + {6197233327569567984, 11863568501944321119, 10309410692812279373, 18064151364176098605, 651644022956656301, 10015612095276572238}, + {3712079372837513925, 12629021524719225747, 14243639867450874095, 17310848059794411658, 5934269651842912614, 7281399930842709350}, + }, + { + {2511581009523899341, 15219471439294737719, 7319331989694981973, 5501409405436918279, 16976076438864148161, 6162909726068177573}, + {16008540889386100268, 4274652746244818627, 12394070200068488667, 263293445411113815, 16742410837666591362, 13337130885835734358}, + }, + { + {3564999479898740369, 187214543496040556, 5760327611422130945, 15928347702080842921, 5118946570680674960, 13188149096923612709}, + {18076374160986186344, 1142074025295083811, 300437958095382782, 16478562199461788278, 15937231598514871133, 6966938597435454129}, + }, + { + {13530583958756622194, 16230919531879218650, 7960208013515434222, 8928487179767185338, 4297154246225352437, 18083693613832338785}, + {9858555096056225549, 10553430097471230871, 12398865197153772201, 2169073753193400460, 15971418942371450367, 1091129085077207635}, + }, + { + {9681282287508526911, 4228346943866017698, 10211475224895899114, 1698892461040930260, 17803383979093774988, 10310416508095123236}, + {14111993390309359036, 2601950955716363720, 6730639879397050736, 916578826304680783, 3894845782969558019, 14122184451458658420}, + }, + { + {311655445282733128, 2366794277731754693, 8447159453573507161, 12862724207019311852, 10879028081424972165, 3930832077575481179}, + {14584836693230155370, 3726981236135324025, 817259866591722463, 134655665446114637, 16268648157415006878, 355268316254117109}, + }, + { + {4860532288606162276, 11004314106081710488, 13906897172384614977, 17082455640344885157, 9775380650399905532, 4859705013148787294}, + {4027669077440695384, 4484628209953599288, 13138896518548468962, 18071971245715712413, 11010957284943999098, 3796309351538330539}, + }, + { + {13949338558872623983, 13999822274187176958, 4733168546809278902, 1627926466897635936, 17007149557493659471, 13788534126928728612}, + {6675844921694720089, 9637011121617213286, 15573984252403764668, 2898513089190539810, 10606052222462092213, 18300597426015463926}, + }, + { + {9020738854941186688, 1697516889381119272, 10894637951430404070, 15457129124942948177, 16383433189144661467, 18047431570429355124}, + {6107850723361208829, 17243425140244995421, 13395554308381924491, 1364807545420052892, 16213716354723238556, 17690236310907832398}, + }, + { + {2522091960819005086, 3742779915092319093, 16499486839317582864, 12740630314665543268, 1980734899856062565, 12849686842043469074}, + {12935833425771077826, 83225990269841200, 15699446177561037505, 11225486016581978415, 2649847060493723129, 911854890207243944}, + }, + }, + { + { + {12424795815234096738, 11929854285805518958, 1614907582435615152, 3243608722624509713, 11618089050999655243, 16450991037761706190}, + {14791827265740380694, 16253295635917069809, 12967661044055669288, 8950779205008902591, 8504639429942410457, 17167078365929060886}, + }, + { + {1313046233449071650, 12998265777408570719, 4977133893460974672, 2561165906571264315, 2564935401972071022, 10644027015828213948}, + {10686048288050006911, 9039002669587247392, 7778186232262317846, 15418338195770720773, 12395635872224741505, 11648627441950590376}, + }, + { + {14681037105441419090, 11154412906553738939, 16558423151175496356, 6285030627926492227, 10290832285247957235, 16522750161805300815}, + {4436228920200714418, 2409858423294994518, 617155725363325676, 14011524653303053004, 5177797359236803245, 8290899194960599185}, + }, + { + {12435263296022000489, 14513062589041133148, 3001590359688622693, 1093106399238867375, 8390630854825882223, 5298071266967498440}, + {9716703994510762833, 139163142171401861, 10954439330188883947, 3997722728391005309, 15245271690519046411, 2686187644733347867}, + }, + { + {11528745980014882011, 6182430424023761381, 3475082923360625607, 3076073459063455076, 10378442361972777951, 1928653322025847242}, + {11275859159200702717, 17732962924665430019, 18439987823449214394, 7064944630179873720, 3304719418024411692, 2153772832250412099}, + }, + { + {243789443148875657, 14348824346423476228, 9830514620004209466, 15033617551094748322, 13287145353793822594, 5879970292069402674}, + {12214538079058326601, 16847679853452995547, 18169365757890727021, 16879879400199284117, 7800932071917017135, 12460054258572695815}, + }, + { + {10090114058748492201, 7363290374561050715, 7843838338279350344, 7920870311130336096, 10170914017871367100, 9865561470166537637}, + {9334256772527683640, 8581897812539458667, 8599471352803027994, 8796183458658268985, 12659201731590700622, 4970311472744086260}, + }, + { + {11601996913454808056, 2966774980339442523, 8806491719792949791, 10028525763203412255, 17850477211982122081, 13173986239201796652}, + {4294659508144450490, 274180317020745003, 4247201611788433227, 5939975532167416714, 7655114550003254785, 18074517862019706540}, + }, + { + {11681890644329677881, 2335615570183618708, 12700694827537854982, 6177201878022338797, 10745204280522885060, 5447698501831385650}, + {13944548355133223332, 13427954271655744372, 1758846050835724655, 4081176162908411954, 143138826110337136, 1333853703322284874}, + }, + { + {2393802334236414897, 13598149804179976864, 3558363201881498809, 10555101826553612932, 4227704841951906537, 100142050362332829}, + {12474424570957807697, 1991825797392445989, 17078870348149694209, 1571893036435136749, 11842302574300496814, 17791109433102614838}, + }, + { + {8550811044062711868, 13733211819722662864, 17711131098892634177, 1540706468250987542, 3800475869236690840, 16871019571035580709}, + {6156757348293294843, 16929121828562583242, 18390632985111796241, 11618787844989532555, 10141372211456532826, 10522160836096579564}, + }, + { + {8165081209334278958, 4318582065069784775, 8081574069194739336, 8837613972613683181, 8266196792698516362, 3864857654878740737}, + {6803499104632318962, 10355487208936010141, 8739779104813710437, 12797187628326760113, 12836259478886858533, 7668861972296903573}, + }, + { + {8680747440971223366, 9209090258749385791, 982535240747476893, 4968038987235564059, 16403151423719561525, 11948841256741010288}, + {12550112619626029423, 12104110998874624802, 7496321954500925035, 17315621249735120555, 15846515502273544800, 12285193498005904194}, + }, + { + {4458184136234141447, 13912288647211446586, 7117356884920961264, 5467268310638154588, 15245220777673729712, 1674280713480622742}, + {11266978702654960956, 8634408824232294194, 14563437357018599132, 12842855704844405513, 1838111782288095759, 6169326332823577777}, + }, + { + {15630121427809305107, 1264840490697624404, 701327106091044566, 4687859862481244801, 4265389202393581678, 5961642557976590205}, + {6203324135029419236, 7455513180678088141, 6200001572379546985, 13701878844691679107, 177549874223488145, 685737752624899694}, + }, + }, + { + { + {17917652049280870568, 15058137289936578634, 13285085763522663208, 9845541049437644680, 11548676527161727192, 1593118089521595216}, + {10864003938379607147, 6682934333876753207, 8053350681795059753, 551995444074003321, 3834039616241196288, 13845962738460690774}, + }, + { + {17541102291453342324, 16435134367897898459, 3939250297619897100, 12831289266484462644, 2672302121940744249, 7983602741649631751}, + {9523831687169710855, 17856472103343426230, 10843947846323217757, 14788689810244029330, 16504581624723904320, 11424882804767220488}, + }, + { + {2900014861634585510, 11023132652887767105, 2781680546817585197, 2476750077618814416, 319701938011681702, 16893912712850804803}, + {17902073833702688977, 7222956556801351179, 17573562467147835250, 12198424156050387872, 7580627929306217147, 13998202371779366768}, + }, + { + {1943983450904780125, 7408346268399740105, 575213954926041679, 1462915584543848271, 2793007152100116392, 14469842559338475936}, + {3871734769136634846, 6700443490968311306, 6647535974540130541, 16864861301170855711, 10601116194391087412, 3578030254148841428}, + }, + { + {17076168913451726474, 12485001555750504145, 14937987845634560457, 16395528327395759722, 5249566901251131187, 14663685647372164951}, + {10098944853248455296, 13972698641100795994, 1737447218715933176, 2714092024085619006, 11856165348735870270, 6799485136302256186}, + }, + { + {5871871142109447713, 3293520181912634558, 7939325551904631466, 10798118573813278311, 13730791012248413123, 10321504720930821065}, + {17809680245543286190, 6650716579366069822, 10928266693125200322, 1399611361785322991, 5452474480776063976, 11884595003144475719}, + }, + { + {1276101160526991692, 1768819204291469464, 6678258399213622671, 10371513950625536782, 13597732847202290270, 16825083293383279230}, + {14168055895026590584, 2774764008800741021, 2309957760746875777, 6610907305570878050, 9706314202777059385, 16449252911102591674}, + }, + { + {14813060919741573474, 7098612088410986625, 966349190955014421, 5030549973018435870, 16698536462268084234, 604473235996320648}, + {10311165654586245785, 6873675636522594928, 14584273072844681489, 14316320659212458696, 1005079606220503069, 15954821355200367890}, + }, + { + {11183652692239073486, 8884116362394548598, 16492077002226140882, 16441016482531564528, 7470807081036429707, 9739141751658800808}, + {10370008242233770052, 680077688048593942, 7591564246708190689, 3645206790017203395, 2343053669027771998, 12572086616810161300}, + }, + { + {7519219331676774985, 3636740765491217067, 5116697285820822168, 13451090039382057704, 1896663396212964754, 5095592986735787153}, + {8207963783074146802, 6043379100202585906, 7652091558617243287, 7757654959377578673, 6081998859385971492, 2348786168616402284}, + }, + { + {7133122685181885176, 18155906669418812507, 8358116164721036434, 1130164626051647366, 2252530757558141869, 53649050676747504}, + {6768458751052378608, 10192709252783071229, 12663625005887863612, 9834336599446253001, 2038072719748979950, 13671585969003086743}, + }, + { + {4173851761541023368, 11613248765669161044, 12438237453144940177, 14553457703654741901, 12124876439154757010, 12300911432501569717}, + {9801691717672785463, 15951088982856589802, 13753872259817625075, 8949450803632947356, 12300776088138489008, 840080730448769108}, + }, + { + {5858476980082527952, 3415994521904095408, 16728629317865207261, 7095110407248715536, 9601602711454432831, 13502772203209999571}, + {8615007365984796321, 6504095591339955518, 5137600816385143072, 13062434456967887391, 4631991737746920809, 14058443721136417450}, + }, + { + {1656883461929285686, 17999602600826473063, 1799632323068877945, 7732508045647761265, 10873882997372651873, 3506525810685866503}, + {15989411289191292639, 16479471154067566511, 2001393974257662209, 843909327062680514, 3242569658964181728, 8478074943121574788}, + }, + { + {8836486505210648494, 10426577898344062793, 15007011756836364324, 313253543022452733, 11238239898276565663, 9629338715516113114}, + {993560883855492779, 15607551791478573230, 15193357750834803730, 13987812869592549277, 8887672059344069418, 5889521823488896936}, + }, + }, + { + { + {3145983761589624622, 17611056211316241576, 7512834765800752414, 18184573603751780835, 242382926403786594, 4397520716964975958}, + {4247119304022133294, 8685419354613982051, 9278503793637334290, 16772431670903233717, 16405977360280723789, 18340424413449720973}, + }, + { + {7278488351594086657, 13741799650370721053, 7077234897085578231, 18054749312950890784, 18263305810183755751, 17993843681498715672}, + {931117702416785030, 5163042803543400584, 7302612788872058407, 3506972565756252769, 13474801549451642960, 12996402258486911171}, + }, + { + {12722582186246792962, 8320877050791714570, 8335877567392598374, 13905858286751392828, 9736409409986876840, 11481277047355207753}, + {10562168749192737373, 14796357906073824644, 5143880557235132223, 1571641856571928949, 2271316785876440591, 3660167720441454348}, + }, + { + {18049602908503252792, 11214422395908641790, 11430824735860140075, 2019476279635404969, 6289777936286416617, 13753051460215424762}, + {11815459366199608802, 12257585796234971843, 8445139535123038318, 18054472803182783544, 7741484337923311202, 8173824012406015686}, + }, + { + {12256197267402510387, 13981324545434438090, 8854870249521577116, 1322567737371616078, 206839117288725323, 7997975760757403170}, + {10936017633135714664, 7366988068807007130, 8063896872358704385, 2137626719657327928, 3857424773492212377, 2719356304578840102}, + }, + { + {301934102174571642, 17806324394288773834, 16260123717658024207, 2047056936294915604, 7772436465589087916, 10948745767775306521}, + {9748882939263142737, 15303318171412953528, 951366600399039153, 11773285376383557606, 973693395285409021, 17741704800677625463}, + }, + { + {17924453454819492958, 11063986742596412626, 3141255180896459304, 6613007634173851965, 8230425337359415489, 9592328879812768331}, + {2074105989750243852, 8292968072994968539, 1989007282115330477, 9773026020534605403, 575143206156426338, 15794135741551054909}, + }, + { + {8693419915948057531, 1857557492170437980, 3828328131632721806, 16028252623001538746, 18359326643571678076, 6797739150028305116}, + {5767011240779324391, 1596344978223521735, 17443341853132737437, 10141092192444507922, 2880787045172334942, 2732830950861490359}, + }, + { + {3720564070329831762, 1116290302908559499, 8937540830788665972, 9131941124777117589, 17948366512937030527, 14685135061941669573}, + {18087232427084058704, 16817803762356804259, 1008977742792474413, 9381957960616185727, 11019890287218060046, 3802083666870379154}, + }, + { + {4862605723300674513, 9575672576917996640, 7558492797250409763, 105451604303370500, 16038157294412882498, 8761291945534568660}, + {3569807536094118073, 12152660506168626366, 15524077973685866450, 12984443099952829222, 14525324946986225232, 846797246005295625}, + }, + { + {16118471591100195500, 15075676621793721135, 16827468519303942764, 15179554880581807399, 17607860075908872130, 4006056291125828527}, + {13532541668080502449, 6554388530128575875, 11492311210085820804, 17407862345050568276, 3079559812598152049, 1961041605272859295}, + }, + { + {11643823884368608148, 13692078871457260347, 12760667246660146798, 14632954658001918449, 8493526038677331601, 11799308386431974644}, + {14675672791238509138, 1711971116872200846, 14683263505637045451, 9945937059533842597, 2533449755114148002, 182889653926968389}, + }, + { + {12117719403043995995, 2911986408429249777, 1810092692597231347, 18376367531841849458, 6595121441567685408, 12086792012295038031}, + {18169524376531427837, 7290300957931658086, 1193279940028308124, 133756179824057793, 3153937764794889756, 949814549860399421}, + }, + { + {484820520924399903, 4326328160527123330, 960211674708882727, 8917024768858500619, 6654526459358471452, 13449950526572072120}, + {9962763721058274024, 15699755065403197794, 16510141891401774591, 4621297269285137763, 9994000521116731271, 18052048126792112397}, + }, + { + {13533215919022444391, 9410324278985615744, 9852634656100194208, 1155971444710515203, 2911320463483837737, 231084108675667411}, + {5261097282088390531, 14003855699351521178, 17744595804999607148, 12877326770237543851, 2381016402869931196, 9246060959671779703}, + }, + }, + { + { + {1480509573599822036, 5087695994006556261, 17552775024242623509, 4908461990210297503, 7162610856648884601, 4093820247209466993}, + {2797950306474546244, 5001803039722689495, 6874955169311742070, 16748306778408052918, 4663084007893308007, 14696281298177607450}, + }, + { + {11992083281415385424, 15003924313644360188, 16060749513147241488, 15017414158265602339, 592682985276747063, 10327384700468822392}, + {12963019048030648384, 9853215583316433375, 5853002447766629843, 3573502149365840495, 7038518580360953609, 6673767391281747746}, + }, + { + {9298643174512728477, 13990767093997540279, 4393323960646334288, 4483648226430512282, 8076224304421767616, 6102759767515536930}, + {3652706241006741637, 3186805786206752554, 13272394214313265857, 8224305150459867349, 741190616027468712, 63238693198034713}, + }, + { + {2449597540862217259, 12351778639332774926, 262991594157788783, 2680188811965411501, 615952274938618918, 11101057916879795178}, + {15843704445146482504, 15768003479919439006, 16910795055422658817, 8210619241519359236, 13238407118245991998, 16212017713818083131}, + }, + { + {14806494457242751533, 3449804849483160156, 16962452567092059192, 9141394773020099337, 8870354660703521024, 3891566159386999852}, + {6146187894824960028, 11953410583785840196, 4404488807426703410, 6773066909874546524, 13716047320419439079, 4345501551123937401}, + }, + { + {11770160881016297977, 912473005790610286, 2745675273862880545, 15571792568792967285, 10677789776282348899, 295569599270057816}, + {6996654843946379963, 3996640705568842675, 12385530671849869858, 7412246026156424081, 8603296241680544804, 642377289008783440}, + }, + { + {11971881963673402517, 5439855382586921512, 16727103775229765963, 919596519199508651, 17937823088055377422, 17176167766106996798}, + {3663817202726401586, 5233288534404927566, 12262379145132434982, 12524678428958655570, 15158879251407581617, 18113402803324294467}, + }, + { + {5911831825147712996, 11728153653307965512, 9638203731413711221, 7948268717672672186, 7633819740372611413, 7035796435141898619}, + {6174193923587781027, 5408370123448680957, 4626366961562317252, 2309742647852990490, 16455916524028211003, 4504573468719265476}, + }, + { + {9058031745280178311, 690568667783443719, 5828783220548918226, 16050974080522553564, 13601922218850425804, 8808996512886455105}, + {5092307204676037523, 2947766400331304188, 7168571072799599807, 18029292030846640494, 15149715177238445188, 7857041415140644235}, + }, + { + {11743616397824348491, 11497771481919230308, 7158569983910845263, 13603604323915554008, 3337542887194115557, 14157633378937758586}, + {370281458279622519, 17762634864406198956, 11337855845757706931, 2929878283715844237, 13865396000587203957, 7059037007931834351}, + }, + { + {6973772658311339209, 791613060143613947, 207740421140774752, 15112398720810035573, 9603899779905889177, 5467205843920466750}, + {14380982275701503993, 12490114314596206995, 6782837922057127896, 8380489751197838412, 8510299632595261617, 4701772950345167165}, + }, + { + {17694086330481919631, 11636328947060876015, 1995706737774084856, 1925297315118813321, 3075862652270344957, 6399044835008845126}, + {3179065217616615921, 1550261549062697917, 6277396572721355536, 17738387466266963038, 8634038426968132537, 10728928687683354197}, + }, + { + {13587993255682028939, 3093746275081235678, 18152806066111947732, 14870862873010104695, 6947641398927171301, 6167792530140134466}, + {15651443704630473260, 6642812576181662272, 17064834710938919444, 7375543199807976966, 14845457653197598647, 11635197020740053176}, + }, + { + {4049527531120095178, 4601134559076758743, 9749942598880804868, 3990727773964515788, 7976713942185951445, 3046031092694896893}, + {15903097778987665452, 9044411259806049413, 1100762861888218692, 9340935249673778045, 13483058690067148645, 1545265903606923858}, + }, + { + {2035047113284776118, 14270860440293482779, 8925762303886288983, 14305197949489621718, 10202635115093639414, 10612436012257691297}, + {4441413877178186113, 5982857664255490920, 2491752418622962596, 9740828623410492538, 16822026648654939159, 13367270937584463190}, + }, + }, + { + { + {753467293193578188, 14319628483702379607, 9902332266754012588, 10961250711959848420, 14561592831116999990, 5289034957582773903}, + {16878255390347501753, 6614600699964682579, 15224133068199077460, 8845898800353928686, 13501508557386903079, 12790515894544276936}, + }, + { + {11011452278678065531, 11497839782101232733, 7285443384376562651, 3269734604421310040, 13431092833461803889, 3947360924216217744}, + {3251034893487035800, 12202372175578593549, 1928365734042402305, 13907315815562159932, 4942146767537177575, 9208365212678422011}, + }, + { + {12195725836685438469, 858993920875325442, 13838230858435487279, 3353504415316812969, 7929957941866392419, 14225218649971283983}, + {18163292212490608521, 5208475779203961411, 18277468513758427896, 5137327622216988361, 14819617095799940577, 16354307604702819275}, + }, + { + {16781294408245827650, 10125764934688471810, 17386045350799928761, 7875599535676923213, 11646654052414081972, 13301057675984901743}, + {12871815118558604397, 730917248827024292, 9514315608146867033, 513190696593073824, 15098974280120040377, 16196294686650511719}, + }, + { + {16909596444779110671, 10723968674526571591, 10996553782910854129, 16341969708695486761, 8635318916065362596, 6184764740785536711}, + {4510923062913139004, 2099379644008359301, 12406019366618763142, 11660159720716101851, 9002817464305502564, 15689479522617312827}, + }, + { + {9012015558077211452, 12527300838564203164, 5537302239069624297, 4367370042010266898, 15289441745247695580, 4593879093246181819}, + {7147970286091237416, 7287559954909509597, 4624960348890895434, 4403301422292173682, 7585442950983589875, 7325469891518486313}, + }, + { + {11624314814028789299, 4829320234443117094, 10699140943317911265, 14108042008131265164, 14865288068464758045, 10370004463666457157}, + {5805719613941872131, 5896198105631611038, 1844096097102433842, 1338882622497873479, 2882306796959123998, 15679394935542538300}, + }, + { + {11839803958974077427, 12283042318798607896, 14631718929239598705, 3167303738550719650, 8387688327413311466, 16263982689936295493}, + {4641171021165489505, 15063549369667052490, 4114993861532264470, 17514729201584918440, 11567986488283330737, 11751214862996904663}, + }, + { + {7533651708740465644, 3241255842488644864, 6743080020393835585, 9662587303565932915, 14065041846648071011, 12865213763613806318}, + {3077902115599738788, 3561402121178551657, 14611443992052777610, 8057658460840092305, 3326179385599463412, 10159717164443540788}, + }, + { + {700570683660150445, 16431145398710913934, 14168612051358907826, 13260960614387819370, 12988684119093007748, 1867024934246155048}, + {6311188673107170040, 3547825519151270185, 7128858853100723527, 4250551126633259556, 32233820825017096, 544635653753539727}, + }, + { + {8186226847711890094, 120861651635567506, 15214391831057401822, 9554237535615944181, 10075996254396042981, 14008290848782906398}, + {16525833259001997344, 10952578407797544068, 9567631957420742761, 4694819969357735839, 7767798136118541848, 18127622189992993176}, + }, + { + {7372375356062107488, 14109154833185040894, 4602775210887940742, 13468454637087016746, 5719482738764538175, 4919648522641500969}, + {14001774924525738221, 1330372407151555180, 3428768277669749657, 2816692670087351763, 9277450502900005529, 13715847643179616093}, + }, + { + {6794725365200966305, 9338913627946190988, 6477518264556505079, 5413655651412570539, 3966748832123982834, 17431753968516942256}, + {2369756878476639122, 3529105775992784064, 8846093841954577079, 16453616771411600591, 4485347503114816232, 6730810021701621332}, + }, + { + {1450226730593401111, 2904272681147253326, 11091003663793942841, 12036368148456428561, 11936601964184969530, 16312603396316459043}, + {4136271589497610048, 14294570804106047765, 15555359403853426727, 10264827714357589573, 9810665706497301464, 1311018743132753054}, + }, + { + {18271820402515351558, 8762537564155822450, 6068223146661937849, 5461403608011964107, 4988573958931158097, 10363771067980560783}, + {1663617762306194365, 15095271556849436192, 3047795323021630415, 15887201493595197850, 7868923572436975277, 14683359131088610248}, + }, + }, + { + { + {3584219355111975656, 16371250505380188607, 1783498323461654093, 994193781588257676, 9344084148092131914, 15250514640734155003}, + {5059260913356645611, 15865386190442670448, 17548757651739284710, 8085895309926420946, 4682964998668660167, 5020215203959826643}, + }, + { + {14253762630740826994, 3822111194856117434, 9311588183436895562, 14738024658650371287, 10441316960341346644, 14194770708525922705}, + {10501198799087781964, 6776195770649012397, 2069471581290353759, 16296715215024806431, 4534980656861543696, 6047881007434832794}, + }, + { + {2576612335437377594, 1899682712651141430, 11887300270792449021, 11804472993069758206, 10830999119719313280, 1741753179884488861}, + {16286699122731099873, 3643516247376722163, 3682273255591068565, 6392728837720629214, 11901348706175159921, 16143485051395996208}, + }, + { + {16501275346405437273, 14761564517561445391, 4638515002973003639, 17077550066034272812, 3698823236196638906, 124739081757270004}, + {15651979540537047037, 4985552038876265035, 13897675410836153797, 6701001687129639509, 16001679255576062512, 15935676633572097252}, + }, + { + {6152665130156855097, 9705469503204567708, 13951924545067113356, 2434138635056070528, 16591230788773292318, 4426260001178290949}, + {6390121195308333473, 8700572060668754242, 4812036275221797020, 13956720073248299438, 1902555843966298265, 5202141163826482301}, + }, + { + {2205395724283622824, 14105060019721358203, 15333631923716583964, 15403277868996709611, 16053651221022177038, 4784915253302323097}, + {971368063439244399, 827094312859966805, 1289222939864657176, 6606646522754926560, 17884747739152229998, 2668818780560918135}, + }, + { + {8525645166886970196, 3134143460247871741, 15116115167560752933, 3078800960701409856, 13059504075862532550, 9108153517754978547}, + {8250610785324912755, 9363672325956190127, 1495074847941437905, 10404043508726832050, 3904454763323616406, 12813791572599100929}, + }, + { + {16231508947971999600, 13363198726931461200, 5108997208952476742, 313182511761731319, 13219320773345255384, 17738895122530321495}, + {13811613026355251284, 8104379475524665186, 11192626091005940452, 12269372147510686296, 14390816163307043004, 12548485382177679293}, + }, + { + {8324780214689809449, 12924270761990727384, 15667753985117360698, 2943366707006427041, 10732039278085105434, 187369508428043393}, + {13244759855456178980, 13648213682810990274, 2660837912365849198, 11976770768362504658, 9693934687975961239, 13497908482787476774}, + }, + { + {14274386677405027725, 5124210746189478907, 13406608799629323494, 6405757996539000551, 14833312365952984384, 17785392529319073280}, + {7012330673098190805, 4918207845691492471, 14569574826272718621, 14168881522510616264, 14543438332068119070, 4326878510849999806}, + }, + { + {3341517100128815958, 2243420303688401610, 7153321666640309374, 10525543547452580816, 15776339624494341946, 7695076598671462598}, + {17732536140683547636, 3592810100391824473, 8413963613597435501, 6287395742336969309, 17465824153452860115, 6235174426722257030}, + }, + { + {5115445260875459050, 16200730294025276633, 6547940770886449207, 14513875339087588525, 2198135911102420364, 5169696006198573197}, + {11212158904251814892, 12437547968034770636, 11358243474088174481, 15452137528587726940, 4669136461455404974, 16320538143089060251}, + }, + { + {535242441654234443, 17036092933883802967, 11600759291125000719, 8050420965161709260, 17428526452419188659, 16458791281477337579}, + {6849931777343444339, 8512792140518036559, 7343733992893241199, 600235943839786928, 12840987592523793156, 9723169304965060621}, + }, + { + {16910417058622635394, 13917679375324377616, 17959562963138340920, 13359247597962361445, 636821169073744083, 11256621821635909669}, + {7096901051607551014, 2253054364079345329, 10215298864674526475, 8119225351234426800, 6541463265042612592, 12031138687814031665}, + }, + { + {5533765953345363299, 3666831701473191637, 14428123488067625678, 10208783684904868326, 4235254303243099550, 1152270923153823119}, + {7789988973198825144, 6281293996379084253, 11378132145663703106, 3044105183226657672, 15306186828154649523, 15118610766364934343}, + }, + }, + { + { + {16935319226801225402, 17479248115784925404, 11638874181787898404, 10204689344548103047, 5117503946912602321, 12798676317624404688}, + {9505799912502843544, 8138377038334669868, 12720954262725413506, 15335292261188744188, 15038060543229285980, 8787225712640151227}, + }, + { + {15287318513745980942, 15744943637312052287, 7712210611206194812, 2217808902952441036, 2880866790953980192, 7667233076242231085}, + {13340980843800511721, 1457443910895561494, 5659029865434015148, 9961325920271003974, 15801510722608035636, 12796727676398023612}, + }, + { + {15122689851130277466, 2795800145719527903, 13568032512724822791, 11462146579021072831, 4492622156197866593, 2389375563422758140}, + {12865430000561425758, 6876703980342191229, 6462758017056646394, 8138171318212409116, 4936990990444974691, 5220248005727829595}, + }, + { + {8222368087744136131, 12347516717036849679, 11297745347969103984, 8698144848560622671, 15235738417459308488, 11458307232141527973}, + {3156981165764697119, 3057909217286827485, 12707579681957851551, 14845444651771540740, 80043930456510931, 1427289826580350896}, + }, + { + {7271145335703081483, 8550379746366065405, 13222245170616935372, 1540183103607345547, 2206602728696862159, 2058073362893523092}, + {5459388607478785206, 13539611642074024292, 14402323904633266753, 11367015657725980988, 17537636140146252991, 14350125041234662967}, + }, + { + {15616429048255216098, 9646593367959435050, 10000076172445964456, 6887507833360734784, 9214691284865468772, 13407989755707318537}, + {23319057005728778, 5445755128474749921, 13782721823710291190, 4306629918002434911, 15715349716986824199, 6251943698106742954}, + }, + { + {198559125451872098, 8385427235747237692, 4233027135118542510, 12503554726860108589, 11105115177544924331, 10775185446004113820}, + {18212911447748408345, 13178565926755254085, 11114640510577499, 13843735599818615925, 18381258674287597192, 4756672869046810150}, + }, + { + {17538496477622964185, 1433183888673756786, 9984974491682898090, 4517808169349623741, 11986465564270089848, 8951472393424828879}, + {18196670723256299192, 535472157380722178, 693981884244746078, 15216522065428143733, 17726679260273203578, 9642969849409448024}, + }, + { + {5160114191168942061, 16463297770925271772, 10584792713261988719, 171850540846180989, 11579918515133959672, 10396694913224588816}, + {1922695067497914227, 3714397082557422085, 14915689713324864917, 3021901216294169148, 8451082446819513089, 2760044106111795702}, + }, + { + {2097173236089378814, 1814647054859784608, 10170299954366323333, 15955393059406664485, 4430370743633462938, 14617134597845327698}, + {6936197719765052068, 2035967928833128806, 10470936468275213989, 4552370931749195957, 7631626755294792165, 6995299789974072943}, + }, + { + {12192685447194213477, 16243788027426389138, 3307221830229366704, 4572373691827105584, 1147991015406820584, 7590972120066359889}, + {734169818930149130, 13046977851131733697, 18326449449602619156, 6629039284529698715, 7271937928914886253, 6619823517983792967}, + }, + { + {3491881131560177144, 7135322509001495847, 7718439954155088601, 939390052225540969, 10510098057025374009, 1036897112091468594}, + {16801210479572678348, 15364620159660153125, 9689801136876260321, 8466379544537007598, 4580285922100315708, 14754066353072462775}, + }, + { + {14236937969687093384, 11875131250768543855, 9199326778448473576, 17010296519672747261, 1432191715295448820, 7240396672478525409}, + {9282856696818793150, 8929298554101654038, 11691758527810395698, 13529214720842330904, 11364130274429289404, 16330417304431446315}, + }, + { + {15048936394544601723, 9976495942367902744, 5091911528724055948, 11917276080086885230, 18264141168509742890, 8988005100166523392}, + {13433041019916296924, 81537940451447058, 7905632599843138323, 7403634956612254316, 9471327080643618410, 14680725036927871901}, + }, + { + {2480592968060069230, 10676679272536823217, 15243200241275199686, 4240286848559333728, 12603956967014393016, 7473015364599570554}, + {2693765916823593525, 17572693658548274653, 13118888526718862906, 7144820876393735119, 17370196132870621301, 15051190136387242039}, + }, + }, + { + { + {15739670027855719825, 11036910205333787352, 4021544392863474986, 3565553387347367423, 3964961332364428282, 11603690097938709153}, + {11178322814781082150, 16935748921430175757, 10468742523886846223, 12912873445700591944, 5891559088297154919, 7322207037498008851}, + }, + { + {12503447801634120868, 970610322114574805, 1771807998727008733, 13441366741769313415, 4222236502986444720, 6760646999389453689}, + {1245452496533201083, 11777722003914828797, 8588751099069529352, 5461466601148872630, 8337331853046009840, 14200040474835462559}, + }, + { + {4381862158218819279, 3257946724717759531, 5715153718741221113, 4670267951691935548, 7126319499291794377, 7414184252515644416}, + {4409132192672707346, 5008109015870660081, 6646364227378002309, 2739818052318307018, 5254205492507002412, 2818763676677612931}, + }, + { + {17099575116390052440, 10771651599651215927, 16162078968288139277, 11747949268467955645, 18198632468383550806, 5718826843079118428}, + {12831818154622136923, 1139908981801729025, 18325634788038344414, 7897003381227512409, 4530946171065941992, 9839081555707087441}, + }, + { + {1822027882663919965, 2586692059104727545, 5262003340562216457, 15937894742226805212, 2377491755233029350, 2199279221179036230}, + {54627843603070570, 11018477725217416055, 13581326215347987485, 2599428256427468431, 13357876536889150180, 5983800947159377657}, + }, + { + {15875913836362316711, 10364504788586479828, 17159094454348286198, 2800760017120758514, 14648701318118632258, 10084646760313097110}, + {7413441597539522638, 5800112976104553529, 9603144930153129200, 18001343598967203147, 14907060105560621240, 12851016504514458788}, + }, + { + {3323767885881860783, 945816439403988314, 3122694203407892777, 18097120801908111115, 9507940132379519570, 13017216324377796046}, + {12112635426215062124, 1632305052635647076, 4503287615961131543, 5133655488959366792, 13376146870575309121, 17882590448286769229}, + }, + { + {16466564999101809423, 1103282883706681354, 13897339472612964740, 17515405571613479317, 231560140111353554, 11990302689318760970}, + {7461824051127758032, 2488635053784032130, 6738969321229436836, 12690895278364961387, 2762939532146449635, 2566430231249792091}, + }, + { + {7209658814720595696, 6910205524542965175, 16895432611633764341, 1110904616599822555, 768894652460082360, 5179276470661463666}, + {15046305975780485616, 12488826026249142249, 8883750914202815334, 7813886526674522093, 17626611286752587237, 14173740877250861014}, + }, + { + {9184078983275066527, 171829382296912269, 1767211109057348846, 3838810139883956938, 2892177352325525577, 587540104068323612}, + {16438018710111896232, 13071494062615911086, 9382254240153787479, 17837390153984245022, 9337352294335969384, 18306549772652293379}, + }, + { + {14206472070300656666, 15149876885322007535, 3058976565256742606, 7554155984973508676, 848860206737153803, 17384966138802851783}, + {6071585659381516479, 14599727484496636530, 14181631841630691241, 13597791031715947870, 787248750081521448, 8147947928967221166}, + }, + { + {7004817083098459682, 16726689782184453232, 3213280543725383668, 14046342544758604883, 16080740219683260927, 6076899979239474997}, + {14309002016238865418, 10488447184497156801, 10347316099979186191, 11941243369619909359, 11458632538231428835, 16102685462015086321}, + }, + { + {5487055055828671823, 4943171312842343470, 2928579838198416229, 11795723672039180426, 15618595864800120544, 11464055884874039484}, + {13454571326567663312, 12358687232096370990, 7938409714147002954, 8608381810067054636, 372913087078823561, 864501330934225576}, + }, + { + {635797081607123489, 1104369599182677226, 12483036179234706450, 17056128228042647500, 10009312675611681732, 12059669643105161762}, + {11477626132980303816, 5618063553013787498, 166943516871328425, 14701206874730673486, 9058640949987144681, 14563869860860339278}, + }, + { + {5395965497092106349, 3612539035634205771, 17681237127506582399, 3439193647142441652, 13780614753565633276, 235023041725887347}, + {3033179449351627440, 2044311760483059251, 2065568607574809846, 17974731450209330886, 14177489327434055447, 3961147821444060613}, + }, + }, + } + + @(private,rodata) + Gen_Multiply_Table_p384r1_lo := [48][15]Affine_Point_p384r1 { + { + { + {16703670340392818579, 1286760518886852636, 11248394403413918835, 4151901610420793306, 7970266049123896154, 17445779790134370107}, + {4329645970348976719, 16042142634338562513, 4537215703931505808, 6697447871083152280, 5793772036565999466, 5422118019001268159}, + }, + { + {14433915249620809430, 14971215887698628099, 14827104772163660010, 11634958463871186927, 828474226872480842, 5684743366783276110}, + {1331356080952535699, 5841511589364898644, 16990208903097464526, 13569226881169318218, 14248664498875166094, 17077506676755919754}, + }, + { + {5595676609776115867, 14618789080398559922, 2201134414120099102, 470895016097834742, 4102274241195483625, 2844568561456831518}, + {9494102924637200590, 7204580187252836546, 7742575358791209801, 5793245187166312694, 7454323588778133219, 7806095107071672157}, + }, + { + {18441227226710925557, 4630553211990364563, 3567153708366150805, 3858385788220258018, 2078907395053339838, 13453284031779612583}, + {16169419783227686582, 17856966316888004876, 9896590068038479498, 14513417153433374062, 5670844902446917335, 9309033883650068756}, + }, + { + {8174394611136832104, 13491946505368383532, 12716018224795668623, 15943834453938385647, 3311092385060995418, 10887239960276233526}, + {15318725704412058702, 13116557402644158788, 14528201448082359539, 9228826301082322952, 17581754887086264468, 4047041475027063331}, + }, + { + {18438599215442843313, 4015537097131987576, 1561321091994153296, 9662659929380603540, 5578281112816876342, 3480911564464745823}, + {858348351556501620, 17689640268312640141, 6959330516163154977, 6424518012595766799, 9187284181582831648, 6293794091600054382}, + }, + { + {13045229387657188208, 13690085938659083295, 9600974199166858024, 526884655886879619, 9290237641803195661, 7044646765166233376}, + {16602070129307025076, 15849288967186609035, 9092091796131291387, 10381155581334810487, 4911799803962481643, 914336345096302600}, + }, + { + {13490991706206957717, 8927032385078017633, 7775090801253487746, 17974570142754513596, 464854089971106110, 13646019468240342346}, + {13801477758808282478, 13267721605400745615, 8832595569781960770, 9823421671556846000, 11348861522513112089, 6704673626616438154}, + }, + { + {8798162395637210450, 2683284686000899615, 4296198105208970139, 7947505075124182900, 13030877569967081055, 7202635434125543310}, + {13802611418940267507, 17744356624256633959, 8515974827567262278, 16069780865789899366, 10235134369297564617, 15382730249140051729}, + }, + { + {10693928681786088231, 1868325427202955038, 2891972363284809610, 6677373020746038340, 14105047344690585066, 17441979056936361876}, + {2686563440401097160, 8335702271416969845, 3158278451667439105, 5195564280130047356, 13312870524821286691, 15037483265391344728}, + }, + { + {3961559481920028500, 898644078007715818, 14752617534552494351, 10654851227350209338, 6258212134755923496, 17327451745924835018}, + {5507497779295982340, 843987163524714857, 14881898850445300947, 16441634412065732426, 11312619178008978797, 3479463508901782856}, + }, + { + {17561502496821949095, 17726839616498802252, 13796139019518438084, 17300206272420033420, 10454206928587256948, 15885557324996538691}, + {16041928347765771195, 2239441821804334412, 6135738566013018613, 4043665170586576566, 10115109045930619727, 6594457533842211310}, + }, + { + {14756924596072248000, 4565075227644918341, 9793935188935462586, 9388712027596954480, 8006957541468583297, 8242831277630235578}, + {15798273981155867752, 6668583424992018829, 16434344268720351774, 3606110602406722084, 15561842144076827952, 2349656254358783019}, + }, + { + {3253443540806261442, 12555698908805436602, 6007490220897601617, 5307008481266272767, 13393830130502009899, 8899654776078387782}, + {4245028374464324749, 15297078807106399119, 16491046288077512347, 4048243407351607495, 13370129289324274804, 9876476920885673812}, + }, + { + {5390721684048918729, 16937659987125372309, 7680342595364868670, 12142253496635306986, 14233066834308424598, 671988498495879468}, + {2704194713182753691, 8912885238785332267, 15078054313953845804, 4795992794995133067, 11649755685481317418, 11930012365952944103}, + }, + }, + { + { + {8103759701478546490, 6028420157132162257, 3067900158853996905, 11583772150650265, 13094984669461418774, 6924985893407600465}, + {54958071128185219, 5021622351003191237, 11654157968548247126, 16247401174679100696, 16385802195540251172, 1031107974518303989}, + }, + { + {6428454722497658491, 10574271313549116822, 6743635881957160769, 16913635330376244749, 9681507818909145851, 4876529861171491293}, + {1814394652136903734, 4968086053144023329, 8920542953983370742, 210240699625540355, 8955586987380900266, 2164268895419701767}, + }, + { + {5608034336248364138, 5067877992472687888, 1933286244725713046, 13242405536880737213, 17263293185510756261, 1983344179233384988}, + {4237886563426459300, 9362799971325551733, 6786753397135169332, 5328115443562703638, 13654670013742588183, 3496580653988254115}, + }, + { + {16071914267185072355, 1315031918944783309, 16012293156990256785, 873056734499530638, 182560274640457158, 7405766622048342074}, + {16511661555914077662, 16795211140914816975, 1916902833101131312, 1130623122713241497, 3989275369171052712, 8501563225308840504}, + }, + { + {13149817102019880631, 10613889292284716178, 14010209428095701112, 1069882031932704860, 2775529095131230131, 9347998569909840066}, + {4409541671614199253, 17197365123077983458, 15652322139676023536, 7678148401641840335, 6034482384901310542, 9413989696720117446}, + }, + { + {11107110071047359159, 16288145590887699966, 2478598181863120847, 15571111403485190543, 10919164510183037186, 14098221725957317118}, + {3061511168275528853, 11371457453448805883, 8189313039485832750, 6940285322230600293, 14956213158219260245, 10799498050375169041}, + }, + { + {5031907698608444539, 18023991803445814565, 8556321431341137752, 8726888316311726846, 15478462387049033552, 10223636290028566398}, + {1905780687053743980, 6821165281886008665, 7646114077486165623, 3026148831014052877, 5536359622022292613, 18100746543211803131}, + }, + { + {11288497443759020267, 4363091778301392226, 8219453406085589946, 10369445991132585411, 5649747494026709400, 18114667371941410725}, + {5194421950530684100, 4023001639787678110, 13257830134828579022, 11041975949961923389, 15908375997592753284, 6836247357428864861}, + }, + { + {8547337202213930412, 6990159258245634878, 17883445208299166982, 4330231136088960102, 6472431629071074290, 8131668855043775727}, + {1615633974804093366, 17702421785830517013, 9040817873428455213, 7253431082049880663, 2580856565062595255, 957305604392189103}, + }, + { + {12550147352209098659, 16706353701874781568, 700985739649075400, 4991698549871850585, 14639605956467764796, 3990548737524847695}, + {2159031565346056390, 14297287012776021245, 4068789221096394891, 11837860404566828450, 1306127140860623184, 8582603028558393539}, + }, + { + {8572221175486824716, 7382610452565148879, 3798240777531515882, 7720424940498032163, 7955672733623916913, 10400992857478606514}, + {12536704118238452711, 1197472667002221920, 7958112946414946287, 7516882332626933011, 6786534214144691859, 10528818884598336300}, + }, + { + {4533011924393772581, 16478214876471299994, 2870575348476289509, 8319688882646555414, 7938557478377595810, 17061203640304685056}, + {6044136899841184844, 17176981934203875292, 14440091607628557291, 9556569541816694726, 12283955757179373500, 1728837458486823533}, + }, + { + {5856710237476933835, 18180055770541353170, 13666756016638015302, 9964122442248888293, 10568196656880286198, 10795529097021501365}, + {10291893071934944227, 1707329095509852784, 10774246437350578760, 8243808578767563702, 9842723530450682815, 10188532762574071159}, + }, + { + {12927366458992235142, 12160026958988547745, 16049652135447450561, 11154205822470049879, 2553582547365345640, 1479077593723189613}, + {6276822011775852642, 1807019718136820449, 5338003307650859330, 13548512004292529114, 274283195318475252, 4262254754558484551}, + }, + { + {2472529054687466938, 17137589090954053016, 13215293749622035568, 14627962367947576303, 10928297195163569905, 7813265877078949706}, + {13456308939723513800, 13108147281933977161, 5072676724153339749, 13630316084050530379, 10412807778936469738, 15061325193703102493}, + }, + }, + { + { + {14062262138187338878, 14826409911427014159, 3147169237468764230, 5040482455529903325, 15961102847332276086, 13076348733721508834}, + {15710048825425827881, 4711284320020833684, 5495111936001513123, 3975264090403135121, 18277552338555821101, 4982873089438865894}, + }, + { + {5881757900577935727, 3082203099603789340, 10587626589676775022, 9790887005834760478, 9753637089164583050, 17530540992010733452}, + {5906674355300253726, 14153899797650168477, 3203393482568874434, 7159946211415711208, 7770493192583170243, 6644035929201092924}, + }, + { + {7565543376250635378, 4894026024316289281, 1064629363627018549, 2229266393711567405, 13431836127556156122, 12345166870816475249}, + {5683094813130145113, 14460568816529669593, 16208596146346015783, 2251060002020925256, 6312100574995421868, 14142863082990548960}, + }, + { + {1701333505386754372, 18113825521491950532, 15971836848310645636, 10666804696553863930, 13339073901359549963, 9016082484725164613}, + {524595420371030344, 15193894147408008715, 11249116561046537456, 1416362693818654170, 8646200124849404878, 14789125286420214299}, + }, + { + {4448219040529062825, 16518108651741681163, 3867577730929059843, 12855944907169975887, 16383070643186103984, 3819970029429236068}, + {12270348593365308353, 3228624969622433424, 17746128033189004516, 15514466691444838563, 16922017859272304090, 10873928830553796343}, + }, + { + {6961979079470599534, 16442399973939705101, 5377070573932785756, 17366295333623521118, 1494760113702996405, 429566900985508037}, + {14596353036230607150, 18306968147291386069, 1956159373957339528, 13362661793127394768, 11047915751588023609, 15562772745602654490}, + }, + { + {12121783799905148744, 3210361347813891304, 15601117831098401384, 11374300947166969030, 14495343294857431451, 16887049363902653749}, + {2806824323484143617, 5891762208520246921, 10519788632722533851, 12406881532231465105, 12476596345610166775, 2929326634009750346}, + }, + { + {11619033824779825453, 6336011282085668010, 66441947656791796, 12634397924162340700, 16056962418493926156, 11181515142520561407}, + {228191213136585541, 10830330953744400264, 2487877016763970308, 943175580952184167, 46830635233029711, 6767691008612241467}, + }, + { + {10533215390069074161, 4240175145555423422, 927926585809726275, 5478507036975461437, 7372848586643865635, 9188187990850719132}, + {8456896957742765, 13507092707706845733, 4249106212594536568, 9711299350266342220, 13631286176123080117, 4243238077447546989}, + }, + { + {18238242856411579816, 7012871932937161633, 5224050476172253536, 12408721251948601788, 10429115795365006677, 3477371341824366834}, + {15692232122888670788, 7069484297055312625, 1511660220915668033, 13645274720004713009, 11371041276648404641, 3227460690876065865}, + }, + { + {9499451334789564187, 9807725712319466421, 17195273970347031491, 6512007407498606377, 825966736514514068, 7114432455006537628}, + {10929611578313393309, 3516227960140039809, 12431877805751955166, 4016269285378947058, 8308345904367589503, 479384259777781962}, + }, + { + {14823174488388431791, 10564122197066740052, 6359884666645689361, 3305490714663935161, 6956926106723106036, 1757044025346810681}, + {9218490684456903330, 17894538754746428292, 3686852509050441380, 11911436761000976094, 11281044983406290132, 4794870267149123419}, + }, + { + {6169315169310965043, 5050462902740654046, 4420119860349968507, 5900509286663583281, 6291948542666637974, 3502179279509591327}, + {13414573911064604645, 8561174987712176835, 15147203171479718083, 8916929729860280634, 465692852423696059, 3241796192189938737}, + }, + { + {4805037083483896463, 15749560291366181979, 3006668833558996338, 12746633991383561533, 2093748724448476449, 9143995667421057397}, + {862280791886494713, 158031676650943923, 9973152260325767561, 5540147634920097817, 18166813436129848595, 8728770860976175253}, + }, + { + {4780823618183778549, 14061468507515826456, 7924000550603741539, 16510436260807392542, 17111673152849580261, 1234594638075874309}, + {16418687934646105232, 3635175728906499987, 17864341637460241578, 49761007765188774, 5595562975249122128, 5917189370132161288}, + }, + }, + { + { + {2891150813386726224, 13575952774970790164, 16329951209698470872, 18208247565458407151, 795211506291706468, 3446245218498235605}, + {14887832502310695652, 7581320984927408991, 15304466638902159963, 12725650577835381689, 2109861799774686052, 14818469767057813718}, + }, + { + {8520307348850101682, 7147166939641194797, 7109795853315555561, 442556286123685640, 16703274587824683126, 11297170023439632439}, + {10777125051934595230, 8742602774458406457, 4568334189916483142, 9580614388736516768, 2144947800046381092, 11233838117038064428}, + }, + { + {14724535093102438262, 1097342397055114606, 9684252469138587855, 10770495648038995593, 4782115196813486405, 13108894563021474936}, + {6186407145212796523, 13044986185014550590, 14287812581901877630, 2228056593434999714, 2377539634072584064, 11484070981184438199}, + }, + { + {2372261882030647536, 17006732445240006818, 102465582613597482, 2306438222867094987, 7030387201499219717, 5620507683182655462}, + {7426675944447602092, 17517494666366669692, 1813907813072832665, 1664846168154029277, 8169354358603845783, 1009146886505697517}, + }, + { + {5359889361557595171, 18332881320680903217, 12992372967564983467, 3235336283246928496, 1918122366598530872, 9672910778717714037}, + {10998109349782570051, 13802180944593323119, 9243457800738211841, 14095366958484090980, 16875322389911718389, 11796767024296942452}, + }, + { + {4154159147515201722, 1273058311504047038, 14930295376923149691, 3541538910606543693, 14677828445112984159, 5652606725362693691}, + {12587781688969918075, 5762437720521018878, 8791631222951065564, 18036051705319852103, 6505939774259762064, 7898749725936014100}, + }, + { + {6073232427180312380, 2682532781858699359, 12899347092203445153, 3460025242522313749, 4187053964557337310, 14007867821755778993}, + {18308269875959593333, 17332777355331823582, 7827095597708416078, 17863450250717363140, 18143218844291088501, 10900355318411639865}, + }, + { + {15193822661262360443, 5913328606143520006, 4932960895618406335, 15675963329264670252, 786659723967404702, 15232212664900441010}, + {15668180363894430003, 10607216776267006109, 5301637052223037456, 6083790571087095778, 10053342033687645838, 11423643886760792179}, + }, + { + {13508339220661185864, 7911953729259324588, 18173014631200309538, 270516748480480779, 674907878659291397, 3314126255600287460}, + {11240909876624153823, 14246305828355338213, 16826984562886383731, 13091972868382905056, 16310998494569268055, 13182051848225269981}, + }, + { + {14790615268961369640, 10646825950331407644, 10001662541750174959, 4485562084633894157, 4694132461615297692, 12672440127863843193}, + {14852450733356045921, 12752269371731614662, 1290625671287973161, 2039070529850743039, 8986721707197477570, 7630558459824216971}, + }, + { + {3913192058752964309, 374802346376725418, 7620720531723602129, 7342095966104858310, 10538685091773236584, 16209362234668385483}, + {12484799568540253613, 12923921033391389174, 5685298310721897238, 8993584320789077055, 6359972113055748935, 3898751772482394271}, + }, + { + {1075126414131149860, 16702551730100501572, 16055620698555862254, 12278885216348953795, 3548642758697723931, 15071720148450568818}, + {12280024271646974211, 4447996993562488799, 14555333424853785642, 1510116618615803509, 3964481213568291913, 4155814256055970508}, + }, + { + {10647300335660095520, 18204591302040110305, 16964359131090101117, 11243541948462109820, 8583754773070458282, 5855117432513754745}, + {12473603800066854136, 10368688750745799978, 6023393792530123639, 12684166823166670856, 5507715439369687446, 1938961554823093885}, + }, + { + {13853144112993896041, 13666138769156330420, 3081504300584253886, 10998940258778477483, 2715364081362496022, 5105801355297802600}, + {10251345083070754091, 5637878810016321791, 2328631003481310687, 8881649909555714117, 16947069603315339244, 7416533920645212782}, + }, + { + {8283704072516909927, 12371773270912112344, 3092081269786213287, 16680017677990020370, 689642403329869517, 1983474266047873258}, + {3309976929403283249, 12532343087642554741, 13903549971839166752, 10358144884777122985, 5685607956768455269, 15212858975393784996}, + }, + }, + { + { + {1974541103187663850, 14419503307385213572, 1910357063271577544, 9405849388295731825, 8846714195441265126, 1825348137739350109}, + {8946791593625047664, 7707902765438605609, 16743886742959612839, 10498180759536919434, 17561637045610857774, 6591991118449510560}, + }, + { + {5396387893935102068, 9492930398296567082, 13435301371127725418, 15386190233236435468, 7248487611273180305, 10016334808351425905}, + {11988208056926197509, 10137338921708783421, 2716545254572709847, 14606914623397840325, 2555748042271077974, 4613981232528869724}, + }, + { + {1157528445712671795, 7268820473896949348, 1310099106886122503, 4262348507724938662, 8917553728509651151, 17005257183552454953}, + {10059173412034340597, 577994398230440258, 7002708654309095293, 10286301441424331105, 16384815498995719862, 112791320905797865}, + }, + { + {12313672925235387459, 625188478309360787, 3630661012849554290, 6134464256048521087, 17936871466010965416, 17564699109077082040}, + {6761309657688544628, 17284240846518446876, 3570047841144108922, 15668537842491950089, 17083391336599335387, 9282566732138308423}, + }, + { + {14888961160828833873, 1864596543262469754, 17784154409948684103, 3052077954154793867, 7607056789868369456, 3894203281376040408}, + {17710090260347574598, 2210004113826562961, 5671161332907863757, 6625158587348516953, 577771095520713590, 16394908675016020276}, + }, + { + {6603729010820482722, 310501835036252193, 13954871388003056741, 14251448811909808675, 5233636024407453469, 12245878228209898903}, + {11486231149562966694, 2835585577048418114, 6551484302395633982, 1147669539433231355, 16475838258018071696, 12247646139693000214}, + }, + { + {8095718986263574912, 10516714254110691975, 10870802407417590732, 12874599804285329736, 16364633263585191132, 8865300776110950252}, + {3563236263281283648, 6644962740435178657, 13092866580083075501, 16578846863092146456, 10069414745327895789, 9434194139304387489}, + }, + { + {3556391957256886772, 2045016845106055936, 16226354733380887667, 17466044866167164875, 5174514841894426254, 1878394346602870901}, + {6716526457444196714, 7250663133803025807, 6718545916437832659, 13969599547915135008, 9325220973174112271, 1581163301870356679}, + }, + { + {17874459379059293830, 17502662865497015769, 1413180880150211940, 15088446747480281041, 8470145037392166085, 15096281883892228601}, + {16563437908222832225, 440803266862528997, 17031080291135092609, 11406614303171495232, 3723108198050621166, 4347405779711045020}, + }, + { + {14923234998584905456, 10067479898750534001, 16939842266743060751, 17700070519960195683, 5683478503944407120, 11025361952743521652}, + {4209605377271021882, 1469922120365400988, 11514012988142017467, 7856087734177419136, 4097954809069446909, 12489390616599495992}, + }, + { + {17122478311949624172, 2606406176820258447, 10067594371237100910, 15451154690481864146, 12038146827921735864, 15614369208187755152}, + {6824524079696297568, 2015807129229573570, 8194028607199100376, 6009223747668470820, 7772398281249621704, 762894964403298890}, + }, + { + {7815360071000367774, 17901565192138878313, 10434394026011307506, 17374730254587070753, 520674668586498531, 9514841979847171014}, + {8950553127025783937, 14895127801975478381, 12425287594242504013, 4645132844100203397, 5976766478892526023, 7370660544571859011}, + }, + { + {17533325387355455402, 12119607747199535982, 9073368446213478432, 2599055833895753629, 2355979442709556838, 16659690147892928501}, + {6238157733277724851, 1384135036242951943, 2192811311355019409, 10465103238457430542, 13159060180143520417, 10257462144135243277}, + }, + { + {15864053898474748885, 3221238804944627, 6003608638035281159, 13653735634664806453, 8230891808319557046, 6613649981851363837}, + {5893628415615729604, 9710922278586234190, 10395125337377360528, 3931451882481143085, 15979557321922502583, 16029662329812025753}, + }, + { + {2992392235075872590, 6059858128867517556, 15617366226623071384, 4111806970940100258, 2815759757037139466, 11575444833660170455}, + {12346698926973835666, 7263128764813325306, 15235588485234058492, 7572978345825547287, 4333826640601921394, 1322529269991380909}, + }, + }, + { + { + {9784032244755280441, 10040637167065316270, 13599824657669619733, 10375431024260591386, 11026488569773701752, 148008158803836909}, + {14567290934774912661, 16110515707287744352, 7491732171320356409, 940936830894493669, 14287255966622464286, 5426456074085300916}, + }, + { + {14969046289595378522, 2961608585839402462, 8313047147741327249, 15157159053809069603, 7193489948575262630, 14433197008239894898}, + {14199648694191979725, 3269958096730932465, 7497592897262475128, 2728526358559655944, 4744743661876038842, 2743084008632367240}, + }, + { + {12708234784965893093, 3307842163098541971, 17303873939057534192, 13260319540233926124, 9019484163029605371, 9900024564598332822}, + {9160913700210863226, 14428342536017851587, 603459719728403776, 18236218541634735507, 4474730692000472054, 13244873297017787236}, + }, + { + {1470084386249125812, 13287518884856486050, 2962960042040907088, 2151437856455287500, 2905195302281113959, 16356195231949614105}, + {10979007359054784823, 17866133863009475011, 4170501321215960549, 4594340427813823261, 16023065223081480373, 12495390124432989208}, + }, + { + {3972369974785239897, 2263460443502958971, 271463035813818108, 4070768510424378794, 18183758750525376366, 9693239897287717465}, + {1475136609401905372, 5379591160737925092, 8153537820525801184, 1865515692994364877, 11166184186139353884, 7175559837327764278}, + }, + { + {15851820172704931949, 12655143336395232851, 14730294842561239904, 12459362250042251879, 8382688064372334901, 5889068791548184842}, + {8985568054046695170, 3001288673081076633, 749616385212969715, 2646834045811835619, 4782194008578140982, 10854034154938442923}, + }, + { + {3566983516939841616, 16390187007609797937, 8741971305711964717, 10988398606335852160, 7867588372988852672, 14538400485602331946}, + {8104114227557982732, 14039413126798418158, 5102330106089863488, 5619388808486733299, 2378045731360365970, 7775897872465058879}, + }, + { + {8285639907960685452, 6907081304694029245, 3932091882248482870, 7739498675000172490, 10103249503689721665, 15185105419572705287}, + {6218795015578490321, 6781880938546434941, 5905078566070212755, 299457794212684954, 2165089807353723840, 8480540247598037310}, + }, + { + {14784673784599919989, 2082260535205922993, 8168045341288037020, 11903543474273736259, 11981001928254322331, 9522037239934847936}, + {14472653912826320219, 11309503817936052299, 13738425228648904701, 8042010790362339419, 14117271511958285496, 790309299276090992}, + }, + { + {1732476059839006505, 17018699420444452651, 12153180531366356108, 11316536740921479323, 10078354046704171747, 10800231856927927233}, + {9504117955400644407, 12280517700591263912, 1062093141564177828, 7578015021890571031, 11569246388902651024, 17406496106428159878}, + }, + { + {2347276268330916160, 3811437762946151257, 13719307347921295013, 3930073025002065810, 6454531622431144143, 7482466867004373254}, + {4716770925419565679, 5110702795209658366, 15071426966139561730, 12738769369895983368, 9464508449545437568, 14677026754609888388}, + }, + { + {15527739528861052501, 8795354980099030148, 17061268663297745190, 13090961285447854468, 15698285934641221614, 12271672067594065876}, + {12952447277463416183, 17845959850709540103, 15366734867247877735, 13405705559578435369, 13317381544359441361, 9727437258673830028}, + }, + { + {11430653818134040708, 13972160408058655396, 7084064239516383189, 5779466131231952465, 13956916356587340454, 15097328365167500151}, + {11851587197086244848, 5814948700376813477, 12470797735177958521, 289525451793692048, 15282352302269881904, 15273112883324865707}, + }, + { + {2162599553469592657, 4663793700503951742, 16049802300031157625, 14926606091765253431, 8356290077455847249, 4143079345240852597}, + {13247139040866943853, 14022573155642926251, 207855347034742811, 4720924427150657828, 15071740430405402718, 6051774750243840661}, + }, + { + {7719115525766766580, 15211733959779219234, 9890856375298480641, 2106523170188804656, 11116661084796200293, 7362312025325548799}, + {3717785929351377088, 13315020865788643418, 18113403510273317893, 14815931788618774540, 14634966516940592950, 2034948857717155805}, + }, + }, + { + { + {14244174369224556546, 5342392209233508928, 7438713248457968580, 10614297495547921248, 9202135001584851596, 3342234996026879127}, + {13691335804923598208, 15140348432227922719, 8428540434060562744, 12043754816218808261, 10858831840083451813, 4598155351159579828}, + }, + { + {4498695262421386143, 9265193209482259657, 17498675555682479110, 24163428822819825, 16737629178311549749, 11187404778246278772}, + {10767729479345778777, 17391117902918412174, 6880253873200674120, 15284410651868444657, 12792198194450228219, 2395904758303124696}, + }, + { + {8158446918957702678, 7546107368870022629, 11717312886106537153, 6923216345857736395, 11003539876942772744, 1153070042831623474}, + {633963820936975157, 11353131760056430258, 7976658868901878513, 8020939041587681581, 8591633705762983526, 1696346219311964099}, + }, + { + {16508671692567979884, 7478096400789445774, 14273613261641667275, 16142155569890490590, 17190642547002219793, 1935098112081588531}, + {4595462997311059955, 15750249483900207872, 5924388750545229489, 5293390377249847029, 4749762219313386172, 13693994083245523550}, + }, + { + {16380431445715687892, 106230990604580903, 18014344013591313889, 1033379254497495760, 12516742637402838545, 13779274142940005848}, + {9785610002952463038, 9797590851340545635, 2035999898130400225, 7132629806216558751, 9169445448696845522, 12182932187779129821}, + }, + { + {501907073775093791, 17308901417650437752, 14252322144012009433, 14212853038379844496, 9157666821207522685, 14098967321770430754}, + {693358881197934327, 14629222976781047974, 2813134959990207271, 11343356266664072637, 6987651623587825922, 10281965377549280543}, + }, + { + {2764452604422336440, 300997096301046019, 14094398322842717733, 8058134187047147246, 15215625261188908838, 4382907902287523761}, + {8492851920809087726, 5937579395094221111, 7477845800356457342, 10689515189034436722, 12617667903878138436, 3774778193535313798}, + }, + { + {9960007214821980729, 4069548394854294195, 8627747251011093233, 8210112892681901809, 7088798910112129600, 2053428079297196270}, + {3702967442659062216, 2310906403335544760, 7567753294056516949, 1948580970688562476, 13536454877958536205, 6639944374963599628}, + }, + { + {15295696372734148976, 3579596265901281843, 9574081162895456810, 4923374886486176154, 3219363399904390571, 5015637093415491888}, + {4593899936599160002, 3908598443341109958, 957285171332479030, 15321912334716832124, 7810866701395908986, 1221281858922781688}, + }, + { + {13874958592881679723, 6638033067173937719, 12963324999336699337, 14597466910971525853, 5238085686240872501, 18280593805011112769}, + {1903676504579977735, 6574951020929533498, 13950840705690778416, 1696682485827935789, 8423274085423453740, 14078931046981905240}, + }, + { + {3517518319454019911, 10814049823525725669, 18276808946264820784, 13619936204927961226, 229197000889315492, 16087612506648744856}, + {13359110821899203348, 18273672153546569067, 15448342392556280774, 12827254463788206440, 16731815387033480424, 14776988595871001826}, + }, + { + {15270415391437565596, 2028683490070884787, 11702183509282950225, 8688196922408363831, 9849893844753628582, 9968552033497457092}, + {8940282168698946885, 11937029660413868974, 11118271464781804264, 11568483938414775956, 5728644286601384752, 3703969168279877107}, + }, + { + {11652044326376748259, 17908439335707899388, 17421220331644622730, 9490161168331495839, 12156528627204515202, 7912628748081518108}, + {12398934214500264906, 15275646021381992403, 4419692862258023354, 16421180417058441595, 2454832921933908163, 17393752904451977236}, + }, + { + {17844918621715720543, 3502040829859328267, 12871353770728226564, 3472339707328644724, 12451097532318425848, 71861369639778964}, + {17295347875481859563, 3690461964037187899, 18360181465850037021, 3712583869172705797, 12197237321535716543, 4729929162220746067}, + }, + { + {8731053926361454382, 7287398925224999230, 18086826009699036346, 8335574098738039638, 7591410546978300407, 8794647666674147762}, + {3125018303771223725, 4278864892990223517, 16568066644140435565, 4494257938435512782, 12764272586590492568, 15409898743615904621}, + }, + }, + { + { + {13983598851114853863, 529849755045537891, 1350161153312991881, 5942999622371373086, 13586823003297946505, 12570856107373756476}, + {11045595872248151877, 13409716803560067967, 7556599145425958335, 12242191131006857685, 13579932482365250112, 18381666009358571885}, + }, + { + {17762884470933745605, 13091628412956520, 11848002318246680260, 11007732397942638623, 6536960302098188074, 815221834698284970}, + {9236334332791328041, 1308454297106192382, 13073132817539534118, 10187597698470053764, 1224340772341594193, 17492375944897582958}, + }, + { + {8342214479854782437, 12753724076994494301, 15158115729208345118, 10675749973467471208, 13779951729398402660, 9124105394386876597}, + {16701027235021659665, 17012019762848269150, 9335333600380004220, 4905542903515934494, 4679911467761810541, 18087992689526637879}, + }, + { + {15671008364960232950, 7860658171410702100, 14227259085597804568, 5601891579416133188, 13347153814200955463, 16322888887317605171}, + {6781550399618311953, 3002152930532217896, 16651539803074113759, 12688880914945537327, 8458859171342351565, 6912445599896725323}, + }, + { + {5223854540563296107, 6918357952454360661, 9207094772512963084, 14426924911853158195, 5755518699259636294, 9387283789461380977}, + {3503930759476121643, 9159964934165741367, 15206356441822401499, 1480953354201474586, 16143427034936870480, 14366839330630373342}, + }, + { + {15025229139882835362, 6569314276317895034, 2647355676900663405, 15940408348923221874, 9319872831842193999, 2441065085739546990}, + {10915383241419292088, 9125679006919517116, 16537773929817775472, 16520361616767483661, 177268947296049279, 5845623806684850619}, + }, + { + {1715144640521397840, 9713182207991148222, 9099904704212771890, 18362082653791274277, 5942292809119944225, 9769586133554284694}, + {11519768289953656760, 11743868714787315094, 6721165095180661980, 10279267157246395337, 15375558993376490987, 14492867532550448130}, + }, + { + {12103512047683613691, 4278073385410902126, 14292291658628531517, 9854045601464761923, 16032579696315420438, 7195268416745968767}, + {612006809983855445, 11060333399844039545, 10009253468204157639, 12689475911984215777, 4543371362129747434, 16168227213690204032}, + }, + { + {11770921065158854893, 107067300718291927, 6216709271265794600, 6933524040251286410, 1452606278006972167, 6352326468906969436}, + {14670895904694727522, 3137275022800628766, 14281654070417022408, 17577495604202186311, 16841827195439601162, 422964381244324663}, + }, + { + {2173637395644840283, 9666438537552030781, 2621516439523045149, 16194421987699911464, 1151524228457474221, 2401703450418989544}, + {17462142435831844356, 15163851247483784831, 1841486106108653340, 7822858850019771468, 4249485329140599845, 1821072017377180323}, + }, + { + {15298268041084334151, 1531237843026640514, 15841013071716322151, 9410793877088000637, 5108136920376770765, 14198994672804406233}, + {12867076639631558569, 17777512969934768577, 4278122367966949505, 1107145346780540130, 15722269527707226912, 966176458294482319}, + }, + { + {3539257888383275199, 17944547213827679412, 9759251359067155556, 7261158630405432972, 15290149052332111161, 4170309286957220483}, + {7708910151755850904, 3634500268466769566, 5837736360460882054, 18200381407287071659, 3169144765352868301, 203115232477137729}, + }, + { + {6840468866856259700, 7758204996514135607, 17976257971060442776, 14304394653760424496, 8378305391704268529, 15501414806030165669}, + {11373547512176927055, 7169306605754795400, 4819206690827867025, 938930549801608666, 15550126629632404977, 16998450850862106862}, + }, + { + {15700328879061755831, 3194744149035659602, 12913379952862607162, 10843238782556582006, 10727228193111430396, 1268507586473183326}, + {13242157096784103517, 9764148610613513484, 13432136698405924597, 17207758635006490092, 5669195169308257419, 9700784012686509553}, + }, + { + {13323401950222069126, 7143389192525342566, 2753977793903748710, 14752970139128156351, 11560905576527598704, 7772265590772671469}, + {15339277736310777779, 11892168454138922804, 17815983037800870820, 15149987747549949858, 11149095484837869946, 3146330589620022603}, + }, + }, + { + { + {2176496575786881341, 11137175552988470328, 18165371128924571066, 14493665018797210129, 9027832134416315155, 17831122727374654343}, + {13941117776210453432, 3262628315315934865, 6955607093154218866, 9315601893566251415, 5081138766383608342, 9449507684235557713}, + }, + { + {3015183280845351853, 8567302742230480780, 12270847108839625213, 11246873507912728870, 1058839101090450289, 15063533146116054837}, + {15816951661145602122, 17835613250576961263, 377336345548517249, 16952055578532303378, 10643126612569896087, 15589909904400117121}, + }, + { + {5917530861159333215, 16376811621868701260, 12468667157041084287, 6060910297573454847, 5999643954660792761, 10374199955429433218}, + {15354447643953389125, 17866869079904367209, 8929885267107625215, 9764565262519350782, 12345751593966204455, 9590062130519338399}, + }, + { + {5932736646654537524, 11111625974290371458, 15669816313412657243, 18348488897895796471, 17719589740702908170, 13074575404328778262}, + {13337220567014765893, 3183217332202609863, 13737875422290924678, 5053183954635209364, 7253181521673343044, 16432970095551512913}, + }, + { + {14090926673589572542, 17530443530454432055, 12384368526139233597, 13369819312395505251, 7198182961160804423, 794076975275841051}, + {2760884514203992257, 14661425019208431637, 13933494052308237687, 13461782301434087101, 15552200892959134758, 17074320298955503096}, + }, + { + {6895102306183172231, 17913949034057542002, 8793858421550093100, 16831072178043970751, 13776552101358985318, 1188816091752039796}, + {17433095774009548776, 1361051895268056816, 1584454468837935219, 9000587494960507617, 9150046460469003449, 6677236369751497162}, + }, + { + {10073416357027898043, 11049353932450326412, 5686074628312392124, 8667039569779248174, 7027692055059522005, 7268282275319392236}, + {8629306706584271868, 4544414308773698323, 15825173458798511659, 3783245463927499985, 3277602994961352368, 16594668318001131253}, + }, + { + {17194222042243013514, 9755907999220542865, 15203045510993220352, 16670494240308716815, 5468356552637101934, 2209927657220556130}, + {4080551261822064698, 9410102261896788927, 1729749535853106305, 12865714430736655885, 16788188297672046823, 4739114570896754270}, + }, + { + {14031233216260426655, 13894451532350910002, 14721305842339563831, 2571399673735228739, 17136925918547685412, 12486318545760378351}, + {14945904247785918924, 4332191017784273191, 3577416897748122497, 10770672964471969794, 13859172261775533936, 1323080729872112496}, + }, + { + {4806132367170729030, 3012780210920457375, 3465902493839868696, 8367717133643917430, 7541627860300058604, 15166837387405701033}, + {8755188577678123832, 15440550960246952705, 6821177912455354424, 13580899156034649200, 13889507678691571539, 8622094254907884271}, + }, + { + {8944073100303306076, 6542151642656830118, 4104527697818383341, 956456087501600204, 1355338812157776915, 1576264571133590433}, + {14576384464935893161, 12976993851388633360, 8882463173850021133, 6146594088987122341, 4213885861865358420, 5730501125228024803}, + }, + { + {7734895557992270496, 13773292779533050725, 11791360189416713892, 3844762521853578365, 1284645752772663495, 9812572158308316394}, + {7423486593749131086, 9063179868650496218, 15664453574296549152, 12189904173100887627, 15565268483602424319, 3276085766266736963}, + }, + { + {13663977661665765595, 12869596706690969469, 11622894659269832036, 8626701230474747130, 10051999084490524702, 1254507355148706860}, + {3738417688632628979, 10128963025153309524, 10379579774762834621, 16085982828578912188, 999630916899084620, 5890496890318826833}, + }, + { + {5464691878810358086, 16779490499259550831, 16167618561212471093, 1500388924177938877, 12758820778786031069, 8726936634855616738}, + {17023037108698278190, 3926165730727012559, 2857709494954513428, 3375996756516865105, 7319015008396427730, 5981183379963579669}, + }, + { + {9453101235061934254, 8471689648697407064, 6756160836097095590, 4538217394377244150, 3501535205004454648, 11902347949869551885}, + {698830528006196076, 8321354741552964610, 2475663594321703580, 13966220326496163916, 1495087475066029926, 9248489243263297804}, + }, + }, + { + { + {340762250586370878, 15885853259854490950, 14170016703992127752, 13413185133968590757, 9132295233250564044, 9955913638095083109}, + {11442204168742219584, 18030844452885851851, 4172771706246866818, 8415318956258968622, 10025498907972372942, 9168803391366195663}, + }, + { + {8511258912015600714, 16401285336019435955, 11567231709606604746, 10909146042530314890, 5175867930620067690, 1758264796269950390}, + {1311893356838490889, 2075003657340819455, 4150679767398135680, 9944985572047220304, 11726442185374948983, 9515564709417907692}, + }, + { + {947814274602777664, 16977093960389365711, 17182772961477092323, 7950550504137754878, 12164286910738269376, 2396865457216588451}, + {7712672988612544289, 2256404627520187318, 8042169559407463337, 4322215616044918854, 7896874306873269018, 8861341680456564805}, + }, + { + {1573021064477563490, 12385142738510496803, 5846352022563838737, 7179392922412551607, 16770926861117259109, 4748524474277694353}, + {627992288971210988, 5079973027627716026, 12148275790420566931, 2974507608681532690, 4977283032988448426, 12122543170457868729}, + }, + { + {14982315046876125397, 10694656698025592471, 69978513957895432, 10720522802782817933, 674072974690397016, 18202488981264823240}, + {2763268093414423208, 16627509676996448791, 7905391784431874217, 15969282761758331738, 4087266599186541195, 6705534661083402155}, + }, + { + {4260928749573083864, 14414653187745491590, 17669562882664725861, 5539725367798503840, 9892464532031311709, 8646224288734922726}, + {14636838328767388157, 272416839100440696, 9027818199363669781, 13152959597440376914, 9885545384154705441, 4531971612013043371}, + }, + { + {3054144515900924393, 12231678983485064511, 5344887254723067065, 16260784250181309348, 13554495123766829763, 16541428532159722510}, + {16971418268239157688, 6561565182987963636, 11849488276654035036, 5626075694176069835, 5950685614385695889, 659455020499241038}, + }, + { + {4016750444584361935, 10934103594664060658, 1610640179181480423, 2687152927501620139, 4356423113034416292, 1508042570353658648}, + {12444493154493623021, 7858990549536828280, 2620376282128316119, 3094221996681006634, 2197436117225946497, 13627448762660605994}, + }, + { + {11319267592865004792, 5771783128259971891, 18183444021717726622, 14584551296093059489, 8197314068068346944, 1496665335270628278}, + {7533930075545786161, 17913476997028566696, 10110826559280511221, 12595790705256942207, 8383527098300125989, 10468103262027643123}, + }, + { + {1297397412658178639, 17891290189040928260, 11494441724074567854, 4008680981284786655, 3752678751199473490, 2327749996539228182}, + {14427514318988472029, 3553111765024203036, 9339018535932944476, 5033337384514825308, 4461712737595757481, 1042763231946705190}, + }, + { + {5282595958571557801, 213593101601136936, 5851288338443284810, 7230384975686448098, 5076726665241242579, 15657565414881533309}, + {2806053347798036217, 13325810292191155888, 11207865985035518040, 16753610899485159157, 11780444340160414775, 117213508700926531}, + }, + { + {12301002695840234190, 5825957247323734322, 7540088495914446527, 16042651929295067210, 10094620945045619814, 10110065362760208923}, + {13445281647852023130, 14273322378142608479, 3078794690211711993, 3432436226120118989, 5328806020363596991, 6994513974763316732}, + }, + { + {12003038273625258094, 10383425068383640359, 15520194992621832802, 377777956418164695, 14943016921304093418, 11013649826256127439}, + {7230967483902155369, 10825313619847326325, 7037825115392195402, 8972357023328446193, 1253857384837096935, 6266649133505623519}, + }, + { + {10589482155172539950, 12297389734324327538, 4069221173445026474, 16016744041800779341, 18417752858659154550, 5634264208757126073}, + {15473968400152854338, 2809792092226097652, 7273042078361794560, 2614557813052600661, 11360021509152649943, 16733025469392257248}, + }, + { + {14029153203244842151, 8283401980696181560, 11095661564207243200, 17088874757598325946, 17546567502506221871, 5640913915552816107}, + {7075972272517500150, 2257279655826038849, 5696746906369339622, 2316175253051029175, 17712158778401896374, 364112814656520215}, + }, + }, + { + { + {14679924527974280886, 15947635289512277104, 15351404070450195459, 4727979236151915703, 16350474002987521743, 3821044743014808256}, + {9479595861519884974, 8516666617350278746, 11503226012034686940, 3623032435206572941, 13809630545510991358, 15014347175818555977}, + }, + { + {11057592299455225148, 11418500207601195379, 10015659838321279434, 3277591360102749557, 13870089373464432053, 11899764543560815680}, + {10598708899627490235, 5204860756179583225, 5704026074815499757, 3961740021052616841, 8083325146143482469, 9703502648801234299}, + }, + { + {5296723995152596286, 12702366508473375573, 3560342141598167052, 1229852828708405148, 987112422309132678, 9050289325451932333}, + {8377778558476358877, 18299004077752380767, 8205821641610714688, 415872980483417712, 9637058392436615799, 16488239169772178994}, + }, + { + {14131815066626142041, 11540556304194578314, 17720164231008490194, 8647469527673297080, 13717080072986283066, 16364407850305375121}, + {9812923705693309894, 15252855277120316678, 4251079378183712824, 16287850228852183968, 16981432229628540775, 7288137070535318945}, + }, + { + {8134759848840978213, 133995483652992421, 12594363638483218087, 9394943745697767530, 3292684192987421047, 5641109531274744017}, + {18340625042234832363, 11659678257409646710, 7834895451987153240, 15013848757483954741, 6923004623931848431, 10731117231772923396}, + }, + { + {710182862970832652, 7186938586352280975, 843940566536207033, 18222882275783810673, 9033108566167385693, 5062146455700166349}, + {8983560327851192528, 9593314042056721839, 13080593353438570596, 8499297145526220981, 12018300556898041742, 5590813964218970674}, + }, + { + {560148900890697500, 3872724270688497231, 12155226431747164567, 12069399862495208716, 7800323474020451504, 17842129873781067995}, + {10386941694229256988, 12627593178570682056, 13595572751629997365, 8796981607722448553, 16749808188347360672, 7845278385143284636}, + }, + { + {5771329137650242669, 14398580224071912888, 2684433028961805130, 5472793673559551896, 4139791942141311772, 10242427010920223149}, + {3435557043383543647, 16439074182964580066, 1897097733009851383, 7790954287877138337, 4094797857151328545, 17636387648829877391}, + }, + { + {11084338203592089978, 7046536437278056828, 15270162581532936685, 14872594521711089230, 1065044340676136516, 12215363914120183972}, + {8807558094930205455, 6192530442586873261, 7580836915562456588, 14608662449758709959, 15699254439480728117, 7514868894683313347}, + }, + { + {6725908589474685098, 17990909432805680896, 10064707122671181170, 16351089498679067398, 6987057004328973058, 1476297822394021518}, + {16905817105678067782, 15956790087223100464, 11919441400720484520, 6472307250416206582, 8105558973519980497, 6060069727850515408}, + }, + { + {4394995949664289457, 6428291279342645254, 14868971543072031986, 7469984888154793685, 4535882282594416153, 14087727563932343498}, + {13764853652994987377, 3726460811537607063, 9231152303364152091, 7795121740553029976, 3567427738439652965, 828395371245164136}, + }, + { + {3588112622259521330, 14318995036651536017, 15152996261895537910, 13117193981606719833, 10869520400973032500, 1535537291014629366}, + {3953371315021198156, 386530500873665491, 3508849322379756897, 4055089442250030357, 12628113724743989767, 4186397566457919545}, + }, + { + {3443066389826097469, 5916450488257370663, 14335878619740602917, 10811180552560485498, 10078378655405541627, 10331041864412397191}, + {7918530238023081306, 10187646187565606947, 10643817701072622350, 14671988813510778565, 17264570610690688746, 5035607629406476407}, + }, + { + {3532200476336731719, 5678111310353191224, 11922638866398303913, 7540915859698370345, 7422783730002635298, 12884745215638918079}, + {11258694614182796345, 589030835645795838, 2262193094720294286, 13773904298325886739, 13573020426752625101, 1682880838844955766}, + }, + { + {3667751664279524715, 11424246261326489986, 11184700745029985834, 6642084736925658394, 16833380705883602850, 7641656710490994742}, + {3519566587420847235, 12380249650455369211, 14234084881378137812, 11403307110698732867, 10605766497849541425, 10861452779244197005}, + }, + }, + { + { + {508120474314030324, 2355066544885544183, 2781810294408129833, 15987954833749728730, 11640488433383588320, 273718689405132586}, + {2640929119024127447, 6627781401094026707, 8341197168509731890, 3918225740211580144, 12693567636985320532, 12010813241293331917}, + }, + { + {1067643586933482569, 15789537218210505592, 11772390798352937810, 8551678486344942630, 18134749517345567483, 8018480309623112915}, + {13721763421328053376, 3248048408533182382, 14403298468089883307, 18344377936005924503, 8145236551628572080, 18246715613208739706}, + }, + { + {7517918011338920649, 10924417706771677823, 17726681281676783216, 18231267965570514089, 9942149863736880790, 2495324098584754616}, + {7703134802415701672, 6763631388551517046, 4129117670208724623, 15972974109259347702, 7281041685266079849, 4033286739838961760}, + }, + { + {18167431682574255272, 16875991970663412008, 17295095002088005373, 8493357273501291495, 15937618870319643038, 11833224465563102215}, + {5034304464808785416, 4940901108264101769, 4572127150938139448, 4375798149940068108, 15502449895994354606, 11063825957880913338}, + }, + { + {12106998444454782089, 478129254096369622, 3583445821883510974, 3783525850583222929, 12700800678744232856, 8398918095020677450}, + {10572000908134195556, 2591572375203033135, 7440424324108251337, 5098405712381411786, 16645670879854917662, 1340903336183382664}, + }, + { + {7662402429691938227, 12301560877341388372, 854014491934252472, 13252962285002044539, 14950007384282365768, 9322453517274020995}, + {3037202449373284699, 10134277839370356135, 7874405825451119639, 6074763175687974962, 12425801537362983169, 18441996758138525244}, + }, + { + {6377198952519496340, 10452019513637841848, 17999702029925940943, 7474985002644580736, 16710285089220886173, 8795286825426459720}, + {9274877579709547055, 11658383846072744560, 15190956902413353547, 5248750851994650598, 2300395682072506542, 2755645297874985482}, + }, + { + {17741788053056918633, 14066143977624056531, 9188940017443802353, 8808532662781054683, 3364478519071964886, 3169335378890645771}, + {17112675492175952719, 14236192466751475311, 5603662455233963823, 12286659362580784043, 491873052068930659, 15049849551374735889}, + }, + { + {2576424316119212598, 12775551962911576966, 15259699755977921424, 11651942542046543115, 1402783857204478837, 18324652864132536670}, + {1707338149370542188, 3298420157097588817, 7521797060095862577, 11460596774399479099, 2575910799608490644, 12312525139228130635}, + }, + { + {392896831764612871, 17176033439239962097, 4721807216245185554, 16182155038868684552, 5761252087564225471, 15052621263295120129}, + {12346920066003727294, 6129012491021115289, 9977552588222578097, 6652331187558815009, 14909718540327055008, 968144566139233934}, + }, + { + {13293883802715635807, 2653176068873560866, 709377591048241427, 8121623725564414915, 16119489273759831559, 17342448566209464262}, + {1211174416757974427, 14015417764234041664, 14462722521216925477, 14082661984659007681, 1695477692957516417, 10365750554717767074}, + }, + { + {4884022083833567724, 7559598399602191657, 198426261319140977, 12353123114206461318, 7871074382107198052, 15544439452501146366}, + {10764302824973303475, 18236640700905160595, 4118397287860275206, 8469775327273188212, 6943100138927210185, 7678646557360620170}, + }, + { + {9047129816186912754, 686205745533008290, 17091874804035707852, 13829610192011685605, 8445841882472685584, 12683587236818333381}, + {15248187852218806490, 9143067576807462149, 13130422498538192412, 1987394184930393469, 17234091013976042376, 5309021133366567407}, + }, + { + {11153014502206421469, 15119688811090307722, 11900512007334729116, 12033534775335022157, 14206136005718288725, 11758356920610289524}, + {1170674544739813802, 1735805534869368410, 14265461327530260009, 454122264224446315, 1196955246858854577, 13496891451537487585}, + }, + { + {1963635747876520766, 8037994677047475948, 9778925841589003509, 18373179051584417655, 17774160058627740027, 11457632676580645202}, + {10746767866979893471, 6679657251517714598, 11924693891957720076, 15059776164765359320, 17106029443182107067, 2977050945907214605}, + }, + }, + { + { + {11428714276400700816, 9684363906879720073, 2326880593732199571, 8761076367298171397, 896913682478838017, 17538745710015774502}, + {16011943008419601378, 5975733755904344526, 18015284849904033774, 12671514003052240271, 17740261525233420473, 8887483872226550753}, + }, + { + {4149943974880712918, 10350790058854190497, 8196369947058715735, 4949794127529191723, 14693007776575755250, 799869184787085670}, + {13583602297228816985, 9731922590252326563, 11783888221311533059, 11272596661461028723, 10650424498639591856, 6814307635900293619}, + }, + { + {5187662544727433604, 6610818388649597184, 13217214483925463411, 11225358343307261041, 3979262110455362044, 17023319482473508776}, + {13540734409372034129, 10873366545113221391, 6574497676007990697, 16695089176775352098, 1800106753424785549, 10409365476253724591}, + }, + { + {7201953056257784053, 7550552970976446148, 6715285792546737720, 1597813460246962944, 5934044807465023074, 5362427500790106824}, + {10951441180547054651, 18111344793262344961, 11925095468088301604, 9885237597177799430, 17378911605611802956, 6344832877661407429}, + }, + { + {2193141511878184296, 8475396127202322472, 3917381969650598296, 16265248388470690809, 6186852221346093846, 11846013739636446977}, + {5487357187469375202, 13711750528133438663, 1849109594291933227, 15949224025529501096, 15221000652947043364, 2391723465441720967}, + }, + { + {7536562994359807923, 8905565631504805860, 16506171098935768123, 4130408208541979441, 9322288628868118772, 3079300424148444967}, + {16936259574260547615, 18438783821712938661, 10324525933994673862, 8397550184634189831, 17434676747885185144, 13637497700498785239}, + }, + { + {8483145192795413196, 3847913378476383052, 4337984637797992463, 7010629707438332975, 11953181174909111039, 12014680632165513786}, + {12276869096120751141, 12577833746497947189, 11723523233456261682, 14093651901317012131, 12375742220834231759, 12908141375852234811}, + }, + { + {3461865703771860361, 797298537903379949, 1718621620291046004, 9179319574938112016, 15506643513481237125, 17129849380198117652}, + {7110323273563692976, 2203663670190111617, 9853530541246034651, 12592752863363999293, 5433719754579498668, 224022543784731840}, + }, + { + {326532432663732788, 4070991663847076038, 1470607885232799605, 6211408722804468886, 15716355503743027945, 5590361253785299677}, + {7812181315317979243, 11828059863468531398, 12778009786378056601, 7800732687373876279, 4224156601900994011, 16057020107391082099}, + }, + { + {7782487925572685932, 1724391588041133300, 17972041778362775708, 11333825676811621865, 4537746153362835585, 4171052629714822431}, + {12770750867191330688, 634694503287104037, 10540092664171311636, 1350757360469465298, 16229194085829187695, 11033889142205249636}, + }, + { + {1500626805655044948, 1474262357314620997, 11484027637627776587, 8585564162226987518, 4361776374583212023, 14496468422187250418}, + {17741545623455229310, 12747090277885336885, 18323745182075670270, 2038556268554236114, 7015814683852162475, 2248939812176116415}, + }, + { + {4335040403419509309, 4616570637565163389, 17011251234033239541, 879860923453038495, 6819883123403800219, 1722220926773986334}, + {4709656270455345524, 16636162851412473237, 7348864482366322076, 14270025125795014424, 6328218483059680686, 13214052880713025067}, + }, + { + {11977022734060949713, 5628060629783977587, 103670064741031623, 8484869049261498542, 4939759321638626982, 16432117890868549963}, + {7629267303968775517, 16619962589721111422, 17463764779224102539, 10685322297759502900, 8807902043402042351, 17462711850802416480}, + }, + { + {15295264908526444823, 13335307760080513805, 4604414283483994449, 5316311055438475989, 9106484611277661419, 13606509782370139031}, + {4442177947438604155, 5803819775434638136, 4655697769853187972, 9432210737074556266, 1181431965380933231, 17230321351582564170}, + }, + { + {16450007145062463968, 4085694834533625610, 10068111071916006395, 7262607959861442044, 16002455059452793805, 14195715414553647245}, + {11695905535525197488, 17972632274451872946, 1579756808173779650, 9867832289808138729, 7742524395848721653, 2581276165337478448}, + }, + }, + { + { + {12418897939030198809, 15206661827925660880, 3670234668273509673, 629739459084205561, 12432881678413324698, 14794818295399912598}, + {8304013048279127199, 8979239574719663301, 7898287937622516136, 18064217129523036783, 15422375485556825691, 3491105078158712969}, + }, + { + {12712561841049401285, 13926510503703002969, 2612279756031831730, 9493430901786542794, 13291879522996024106, 5809241029170276658}, + {13691694507969220766, 18143668557798275313, 9138492995891623951, 688189100127541854, 15640560704872541163, 715816703484468594}, + }, + { + {9922254315993542377, 3698353835142433482, 2152397153019100388, 12317485668320147862, 7630803741744990206, 14043844136716370060}, + {8779442871712769558, 9907756658115628584, 14458334256944611273, 16860549487530785456, 6324109159626157948, 4731255892134100106}, + }, + { + {8002922251516613060, 978443873609457407, 3195553158279317543, 5854976976295928246, 10958159112329303460, 3970083282599810189}, + {5557639662225343558, 15971994949723322072, 11989908821085930999, 8821364574039081706, 16665145761534571014, 4658625544288657356}, + }, + { + {6340510664543185199, 17018415579031156332, 5848132202484941289, 1936333141268823482, 12812324366507433640, 6731572340563570418}, + {16857078034411292476, 15068277976532276123, 11722116475437972189, 1964509865396978581, 18238872631873981400, 7991345170212629670}, + }, + { + {4399729739127562657, 11272928375680253530, 11946741552547688174, 14049301799414882766, 15181782087994325146, 10089988859449254233}, + {6518268185564876927, 6536487350448659481, 9828361032623653320, 1339336992832075931, 500012115828942236, 14824212847841613777}, + }, + { + {171920790242842166, 5492071276632784703, 7283720254645560138, 5078044100187809965, 10385647514177990351, 4643536432707194364}, + {14989909821879706494, 8756233713883588748, 12449984475333613170, 12585959722117915734, 1005739684596759274, 11155909844346489416}, + }, + { + {11688324725241825062, 15138461392078796204, 12325266391227455113, 1340485671902994619, 282500164578345499, 7467882813685092227}, + {74331176722111354, 8867394635845954934, 10408699117489665536, 15725442571211452985, 2590111940561580876, 122458286127547889}, + }, + { + {15892645628302923294, 5856468311490081970, 6874561504197875933, 18019303355409739795, 6082937058931523996, 215426188952156771}, + {1268422509930086836, 14213194550854690836, 11126293425133380142, 9865185168089540488, 11632286407552253140, 15174468604920668601}, + }, + { + {10936413110689795487, 15010995742767473191, 4568817801913429420, 4205444133627513879, 6395122355763512349, 8918743386740702009}, + {16692774758406989332, 17955372475145034386, 15048470334846953021, 3736761708891032300, 2111259224340263959, 15614397697732925529}, + }, + { + {8738432084134066654, 3426263179552640084, 719712812862575782, 10981970426674636690, 9230912351159198043, 10854126184000364805}, + {1961455377595115519, 11451312678111642174, 7688356239558056833, 5143561757570891633, 9215608498872789998, 7917478891815725904}, + }, + { + {13905441237538948064, 12480816058500448930, 9351950531208974987, 17868240518152709336, 16456831118221743401, 14827343335622163069}, + {5502543494126784481, 389131188595713234, 13066540568193379266, 13328625471332746991, 5244571811269709341, 6606962250802166084}, + }, + { + {8488561190820155258, 5704568936155861609, 14891109450025140507, 14985917965027582458, 8150697647605526155, 13242121807143276147}, + {3762467964945321810, 6385131138942825064, 11791602379712639353, 8213332910240399371, 995112454035913025, 8530416099523440086}, + }, + { + {13640325735363574879, 9838259707028418406, 13090326969619576773, 13639005985461657607, 2136356356058124836, 13990780887246135133}, + {5609755522352639162, 17659567235866466759, 16259320408797139425, 5409555833771708415, 9408620568269064004, 6504340943038131334}, + }, + { + {5831978049482033791, 13004433680416851426, 13573449569471990176, 7730273069509750576, 11703396887458680397, 13713882189606773514}, + {15136688631097887611, 6655871600738369661, 10582530699775137958, 2242461969176695317, 607007649724149634, 12963349946916344106}, + }, + }, + { + { + {1245849788995478406, 15927065038482738007, 14167031681717622750, 6558184416262903003, 12026552713606964001, 13141157765235910782}, + {13953548913050124814, 10512136906136752951, 17603704039609623324, 145717304147461215, 325471403460036622, 13128236733581623507}, + }, + { + {16674741188506215062, 9760284329368026164, 6227912018538320358, 6062313431245706681, 11530767050864043247, 4050743335749600291}, + {5438096629683113243, 4619575833741800840, 3125333116803012851, 3488990215372938922, 10001296793595923533, 10533821010269665140}, + }, + { + {16525932200239811820, 11277725255119639967, 13380457983594150580, 11345091161981432621, 16404711622698975165, 2413157060343610687}, + {6861888264192898716, 4349048715057257879, 17588098592479288977, 17308040295861018844, 10945075256382032297, 6591571232106737441}, + }, + { + {3312100944805375360, 17751669833244855959, 11421167323527761031, 2790564601954208965, 2677089945270728547, 14912524259578856947}, + {5283996146017069939, 10959370318137784011, 9095576254518931495, 1311273597919359627, 14918615616693191386, 926115797902848153}, + }, + { + {13690563848743893725, 12308308054894561959, 15395087439588112783, 2472586724818805576, 8533710141094669405, 7942802424878184185}, + {5420945215657024810, 16122859608174405004, 3053741733492700862, 12221133467396472029, 15851472746153652052, 1947565546705152863}, + }, + { + {15897054605211154249, 15279739731289823093, 2336561653796295997, 12705889529297020171, 5961825895197974169, 2720481772301941412}, + {18443277954611435845, 594427728188203259, 12303839396678154633, 5358688406862385350, 13000467893527182939, 14952128333381655033}, + }, + { + {6619004200098886597, 3521645713977761698, 12344376102408265251, 12402516760501056887, 16667318326769571309, 12874140072685141335}, + {9621314969493341823, 5207967593480486550, 2826521035705699793, 16265445537996266956, 5066340697704330848, 14633460704255879322}, + }, + { + {4697083591690261853, 16801765456421135763, 18151421584540787936, 16835495532227054337, 7795860894099083043, 1328764521238600097}, + {8297620491750460337, 11793447721298138387, 10295382270817397671, 12786024121368826653, 7279518368534718792, 318434652860893917}, + }, + { + {17026077028448645577, 565529336479994071, 9535502575346171761, 6007100762400155323, 5678897757750626782, 9959925017754425050}, + {16242528163060496516, 4576911095161823236, 4403607854299656167, 12912517930864843821, 4739470393271194311, 1151478280656415262}, + }, + { + {16048476540489898494, 6783117499823714007, 6415336927764029960, 15673195924318961740, 6247136051556578121, 13084657697232162709}, + {13162992357344402018, 16464326350960129807, 839616770160173579, 4740726662754602535, 3152479265198829295, 6404513982945014328}, + }, + { + {3092232113376296196, 15331813846360575326, 18290474234869335723, 8231838642205234980, 7400082193016179605, 8410763375241570875}, + {9128762227989687509, 3794598237625234172, 4286873165056892559, 15334567321376368149, 14794216692099838599, 6895373348463126576}, + }, + { + {2724979383179813062, 14777475620842655294, 8495183486057249617, 13049191530970000171, 1463143549362168712, 7716595605180919892}, + {4514675039144392038, 3975933817505069894, 12970184659307405583, 4177319338659410908, 6165857585915235970, 17620162379352558438}, + }, + { + {1745353185162679063, 3792943368267263896, 5392169106673425858, 12818767881496565683, 12092569230529535449, 2578847804476911357}, + {2780126809449397009, 5405540052572325879, 15285827524500880746, 2941675021271411795, 9447355824276841918, 4559807377485007719}, + }, + { + {7610007746883416737, 10147509530120995196, 10888385397255137878, 14772040059195211280, 10560108669991599276, 2620459706274870386}, + {4887132538582860164, 2596493858310366442, 13580111877897930049, 13035579030058060026, 10732634358057493593, 13596263836781091773}, + }, + { + {16502308326832314698, 6813655593085792854, 865540522694200977, 18406777409114169497, 70237201416715116, 5540630135583650201}, + {11043265419464844764, 75803127346564744, 3544127781510566665, 8608672751361961179, 5292089330226488152, 1998221520759237189}, + }, + }, + { + { + {15843747259285912280, 11051757736519314133, 15850618202671354967, 11414438518663550807, 8901822655665788460, 4938308746649520510}, + {777341510519627412, 11562816405392154916, 767515422569196951, 16316638273329970696, 8108021482044013490, 11530472289475307950}, + }, + { + {17325850825538431065, 37125221006850315, 9538255856396155842, 1677341822293077462, 8890165136267025298, 15244650613952369517}, + {4845598674027029924, 276084057002262337, 16096273565408425115, 5476011667390370895, 13774404766368645238, 1693789135306442102}, + }, + { + {14853893681504474636, 7246777094738611755, 14348468490599768069, 1584676862820702751, 4055902816558872583, 14691624686566000273}, + {8463792358840766097, 3916260300604218254, 7138823842751636444, 12063405069309472256, 9666094494441286118, 227223526050825967}, + }, + { + {11439448267446980509, 10876971879546473859, 12463594188698329361, 4867143769403125573, 12497774131673245064, 3293027647115301082}, + {17269845420219875716, 7999343694417279981, 11042866033136034598, 15364989427615166682, 10865140228718307051, 15023792553833632785}, + }, + { + {3313587089867634043, 12345206552722066323, 2085484537482749047, 8672528099921546193, 13019543378492473719, 16014000899261448682}, + {8688247996955695393, 13880086369349074733, 13685898059232129585, 9745238149905695566, 12860398562206147371, 17318310740773319426}, + }, + { + {4831067862161961952, 1700016751300913085, 120879261664102718, 10126392277187226937, 12334968545166906646, 2424236269343093373}, + {5064451542294364369, 18179376425888307033, 18011599774285802620, 5403509623689485964, 6314622790688034216, 11605915467730303384}, + }, + { + {2247133619710642624, 14577616964025781087, 2368018907158808843, 16498726243986409168, 1407790037339558890, 1268560497020660735}, + {9801656500494901417, 2349861632952537447, 9517882931966374505, 17010759715257218806, 15435798766523589684, 17726795183758368944}, + }, + { + {18311374045587866554, 14447020620922821410, 11083360170030115832, 9113415708727437834, 14541956290558262142, 13961285592123282152}, + {828114605405992045, 12150002910767606346, 7206389356124187542, 17860503209876058312, 11798129788760460490, 17127855426259911149}, + }, + { + {6199176795763629395, 7044922086316649293, 13997864205295119697, 276986585995515541, 18048058974579713616, 16490720274644998299}, + {8536596227155890833, 3914547013952713733, 16510694033833622662, 3939667794619888075, 3178595810875111442, 12482691560580240458}, + }, + { + {6817856411751563437, 5442319161374364825, 2600227314552885688, 885644663444831557, 11700451742910873418, 12995396601628275569}, + {12803389344446349365, 17830292246277698677, 9309532553762179652, 6680640295615786576, 16662072345574199545, 5503555633912973406}, + }, + { + {9023109435328558547, 15291865436110219430, 13383262037362169985, 17595017389171456916, 9112975926620102374, 6959372004949197556}, + {5079998641977253062, 6532421761731762580, 3807095942977659963, 8160554533119900022, 6829392063047646882, 9484387938580835773}, + }, + { + {10226973915924968410, 8694011647938489632, 4300203054946897035, 12117316368104547695, 13852935341469006648, 16325279905079591603}, + {3279907632975731352, 17658867899191622273, 6430488073563164502, 11102370118583390470, 1351653460592165074, 1155328654798844033}, + }, + { + {17696616168038539128, 14705634818800389635, 13086381626647796878, 8160829291664474794, 12380871402708163904, 86292804711961768}, + {18387045944833009681, 366768093235351805, 6342784007092933055, 10213820317755221687, 2637460351332260222, 14273547543620959978}, + }, + { + {17055410858120919085, 5117864209362229433, 7752728474235998778, 5718238531312883549, 11379901830549393718, 6167331998180922513}, + {2139807429787460156, 15318820080504273410, 4676863271077360086, 11038500994511396240, 10091980097419465773, 14332586624137472063}, + }, + { + {10283737372978878771, 12574954996091932368, 15672686541053306208, 12565297310940420187, 16116977738821195704, 13549410483910339391}, + {7927005432441035757, 13175590081759395358, 1211258742602602684, 15884670892710680064, 3650720270567732720, 12671425442920594205}, + }, + }, + { + { + {16945326091077782209, 16464694010613758543, 15031894690983835272, 4230984078465338834, 15876751555985865416, 13853851790773712608}, + {10629669182284449427, 7123507341691517943, 1604779450978617269, 12335442368004615918, 15831231179039969998, 5721219491336463048}, + }, + { + {8779923605369004874, 11015027029723172570, 13053683587822215278, 14371924836322803667, 6175910444240484015, 7444596092153062599}, + {16538104473324970868, 17940085998297689696, 8904671253507597276, 10735167732778346892, 10719411100540081001, 11825864791636217846}, + }, + { + {10513874959070541808, 141726534094196367, 8961670049397339577, 17110620828714912466, 9276156314861939407, 5283989756429336401}, + {10830576007717201253, 10019682216548180288, 14732709404946097825, 11154000097553876933, 7279438743640661651, 11741828296965158287}, + }, + { + {13710602247235634585, 5794283881286256131, 7189333897035442825, 11474888458737436516, 9536387759009059378, 37447282054824480}, + {13831688592995763204, 15514310505960816464, 5617377358519582781, 5382874924721720664, 12826347177360954774, 16487830138240466133}, + }, + { + {10136021926566126263, 11928523244042660673, 620080950963362813, 8625626899007622861, 13450521127313958418, 12173913767817931256}, + {12782398870117899816, 18284930545209739688, 8340732005841122414, 7667253783573485052, 1170918830797979709, 2726644985398233748}, + }, + { + {5868319710548462775, 4614538984539777268, 3606513902357509689, 5842687629722217460, 655661300379058806, 5750034184391579904}, + {6706948898263875391, 1861998499115841763, 17416124038131320471, 3088573942691514912, 10862822225918958565, 10723788336215927712}, + }, + { + {3469954697000879474, 9886078825125536983, 16639512902206423417, 949458984263591079, 4713065388685405969, 6485681870763151394}, + {17550597369256616144, 8492358132474734258, 1973243959933916082, 11845479291839734419, 10373742178422412864, 12917185093797127077}, + }, + { + {10148520876393042933, 17008996819208361065, 11244838413238054187, 7578025140351179165, 11819693939772377780, 11922206691683897452}, + {5193678850892441703, 11269576636085412111, 14586018532679524926, 2160103807216749946, 2883270595579022419, 8933957426785365011}, + }, + { + {7701278840381406043, 813864330332921165, 15346578798485581339, 4630804650809464614, 16185031359787444003, 17826776112141610425}, + {8401323936341934197, 9592171776430509912, 7758005530392712135, 14454554148729439336, 7956273653179990376, 7839320390573561917}, + }, + { + {9250363391170832193, 11006035015261134401, 14458550514807354785, 9325016894298710330, 4144596754841442017, 15054746156170374381}, + {11456640279410058145, 16275606744085683852, 17831878718437221277, 1528529578606146868, 10275813860685205403, 15479223083860040951}, + }, + { + {14596302840734253179, 14900690077811267578, 16140097010885461623, 12772352415462534488, 8614394783748304718, 6766902863888446020}, + {3301138793577892410, 172863568565472035, 5251004015700101269, 3165424378709792613, 4958340403792084944, 12619148531858668210}, + }, + { + {3284553122109620274, 5270759104970263988, 8347616712857016748, 10393685591838506061, 7030247929091757107, 11570651577508724004}, + {303593432212184598, 10870347165523269046, 5858810139852537379, 1529168183268214217, 15332143584615473398, 15102908354736105773}, + }, + { + {9574340152153043928, 1662915623607662881, 1811398080012362182, 14878205415613515919, 13936394534036516069, 2337960597242570130}, + {4877776368265943702, 405103566243555934, 14225276821637443863, 15556532615883469807, 13552306515137288805, 13115529663394516774}, + }, + { + {8161989794903954412, 11660052284711833602, 181947658370696753, 12989304799327482750, 4066413204451462606, 1942221685308503206}, + {12484888137941485851, 4649383641303460090, 8371451456723263654, 18441597518505156777, 2352723388962482606, 13975888702704352920}, + }, + { + {3847700141255053024, 16406472982872848520, 12468984591385771739, 14942334423186830995, 9933763195617481489, 1409101159701707313}, + {3573772803237348824, 11730844867315771254, 7243658460515938367, 2166169203511142802, 6248287935705475203, 8265081108739245827}, + }, + }, + { + { + {13853753564171363451, 13820378722717422408, 3590234094500056381, 6866298275188000567, 9895869565406539361, 14927210698587219451}, + {18236367046121661763, 4730509858602802480, 16337561945026136271, 14109799857833288312, 11587799424253933816, 18285301586729898647}, + }, + { + {5697628194755082385, 10473326214136017445, 14513883747346413480, 15341298111275585222, 17117376470859521237, 11176286297628034124}, + {13634599286238815170, 17382552533170299294, 9094266669583253997, 239734418257835070, 3591794414849763173, 3133034763403569336}, + }, + { + {479206554903518820, 14658665690734737994, 17152906210790105810, 5958667172720220276, 18361725589118886101, 6185981515380453548}, + {3944672359066359091, 13732151285655721173, 13939827029587789643, 4302296200033682886, 10240802189705837857, 17865142655928189798}, + }, + { + {8306168305072060501, 14751131852602843064, 8096080752206544475, 4680206077732390021, 4419645889416275973, 1519820218356079506}, + {5861554578628119723, 17661801171279693964, 13496831092349512650, 3841281188034367706, 9158790543647317313, 10612203699190989969}, + }, + { + {17037898389052207682, 17860849396131636095, 4349951673886175152, 16094377250964498544, 8476986837295463150, 13680887785001025305}, + {9336507099265066829, 5947089043768571535, 16585602400938566700, 12581267016799867259, 5245484406207830441, 15258801158753041634}, + }, + { + {17548721630682880044, 2012629971546646455, 800602602193080743, 17396222438338198463, 15386698858603827900, 4460480856545157616}, + {8525314085294734845, 6802480695964082562, 3816316223911984005, 2464494579218714722, 16070919992014947059, 12434854377052757812}, + }, + { + {10772836789272530628, 17088691547289098969, 6718631187086570471, 420298886229605471, 14226789851958972081, 17291643744773087097}, + {12356365831670845340, 13630822714405907791, 16223114371865091666, 15934941425414639409, 17030594846596638635, 8894066301960174157}, + }, + { + {4310605480085901679, 5471288425725661823, 6576140643955467936, 3714340113776184365, 15078838872712774233, 18067422699917639715}, + {12245168645156565325, 15389216374359086860, 18243910314816324743, 13468377185671333723, 11841166299472831071, 11909676588719569514}, + }, + { + {3039346662401409366, 11575031947853028231, 14291487837746157982, 282111250317099825, 4887181073166372566, 14047452768090024474}, + {2283232607704977993, 4156222868336602759, 2441521584735661714, 13573229353517305526, 9684005436985156440, 16922485212222584386}, + }, + { + {1553039617197624241, 16514547904183858426, 17367571479943820700, 6825408557936662849, 2149227651964819356, 12858662242348855034}, + {16445523343296776096, 15421752631325482241, 9264183421788584112, 10262669298529989004, 3891304426791575665, 7854962043530510807}, + }, + { + {7161328094115041425, 14768718294470741983, 1078847568267874018, 6322480815278149199, 18188544274188331587, 16963805236223110899}, + {6569325721741554692, 3602100460502266263, 6206643867130260259, 3995469255074245935, 4504503583988431466, 13467328567518375341}, + }, + { + {63226333202683911, 14671906635501883344, 4335660486805420293, 11275217723178135465, 6969760830613945548, 5475843160816775058}, + {5191859885839573328, 11668101171119622286, 9518940388019884438, 14714241947617194877, 632307311715190469, 10690578858328770477}, + }, + { + {14884997433355015941, 156621939301515107, 2445891763674288403, 6687931105529654257, 8038932454300528136, 17697513852216155615}, + {10697408303393919012, 1270195498851099805, 8775588255042571995, 1242116603145454630, 9905730533240215250, 11108714318383369270}, + }, + { + {11500726014983094694, 4893160514903146014, 6828604209587544129, 6694479643978756339, 10165551838331433795, 8922014005219839474}, + {3229903124718463251, 14809704320533033299, 16708685770407035451, 5156200782696113140, 8700282174866114406, 7662703141074882120}, + }, + { + {5701014331899997770, 4977516111362250117, 10386130146580034690, 5907362069264702911, 5301877636154186197, 397392370575027293}, + {1263487057932284919, 11711479762453857997, 16042267091696606042, 15652910858049110642, 10197526967041956937, 9889216320967166622}, + }, + }, + { + { + {2278932254609762845, 3068437509226158452, 15744868666981586003, 8677007854964299754, 14625754507006402628, 7482852446653641224}, + {15206963697756253732, 7484355521899064206, 6303098706947551318, 2787820459819783710, 10505036182664953766, 16812578278348872057}, + }, + { + {5328402213024840932, 2831229329708260259, 9906671250991291328, 7195378896450113384, 8137962574541487106, 15483420743942942895}, + {10185763153215621718, 14520317539607894634, 16021622969265412233, 249210915963234415, 17409430098951304156, 3459897863682731842}, + }, + { + {4578309973503497569, 5447834563002642123, 15020655062803172906, 9784029918330815189, 2259183585428823851, 16276654784273178554}, + {16974315692938443293, 10322189489795986428, 18095043949242233690, 15529824169672291114, 1043280182503641486, 14396190389419318386}, + }, + { + {13791916129725914380, 13541507063515942618, 9276345046434203244, 6943275844315018043, 16854690413809965818, 2726487241024832361}, + {3900450032896335120, 5969156219373170750, 17268291021193518751, 11250600592358444059, 7565688406177070545, 15380048155812318403}, + }, + { + {2159715218114046205, 301696308536518990, 11911287610460594499, 11610729258797804364, 1589214470697930255, 1570320627315083551}, + {9260920251773296769, 7918633900008866828, 7386692371354490728, 7126854243096368735, 15222007907649556112, 11290458721857786222}, + }, + { + {17312369275830596578, 5182973081822417591, 5758577204554952034, 295579627010058982, 2247918074145955246, 8367663961370585320}, + {3503412556908913188, 5007246298285139323, 8914116616437113026, 1817837618482256490, 3888281808755203703, 3596198455140072332}, + }, + { + {4204733050884801398, 1015148026108767645, 4474014702901614014, 7893591904251967078, 4629334549496872963, 15544715130284192268}, + {11515169364144564012, 11336358832640243779, 10261616753173485797, 10330995131826947610, 12790048324162427726, 3954964425838098297}, + }, + { + {15466718315096778468, 8207059140145815039, 10673629467808554944, 886708118721286191, 10960160354467637448, 9642682828370620599}, + {17438921783439498819, 14206610474459128199, 11283947246870324451, 12050660127565107275, 13394619346776634282, 17491132232695062376}, + }, + { + {10457517951627566681, 7814805982659785572, 4650803108692583382, 4440130354090651090, 7336812384548660642, 13822285076682517424}, + {11611474337378208231, 10509443664430110860, 10916114862115943164, 12170669850354153477, 1352553062166066021, 11347589626152349860}, + }, + { + {7366949076040585274, 9972276751640303927, 16423512277534811183, 7530907908504052262, 14015798648185098200, 8802667423497257421}, + {228792414850368243, 10508703706507014037, 15514995919049710800, 9118562110950567762, 10221889965935090890, 16185466175233862997}, + }, + { + {16803723690699933675, 8487548998297552291, 5803011050307689648, 8460712827018550942, 16456152075823939447, 156300814418469424}, + {17276908626721299576, 10528203526298520812, 16491173177262003297, 11906011972808274164, 6723396315092456133, 15740670211031988239}, + }, + { + {15373669199500708772, 1418986186617967125, 14646929309039869466, 10499548009936132679, 5225957845760868950, 4939303423191000552}, + {2490287739273437898, 16292383701614685255, 1045010937850952943, 12708627850998017142, 10150876621237058060, 3374704772596624527}, + }, + { + {6486481503809124917, 11162331521576557500, 10016688945665150046, 10440833383589084422, 14434962491136116288, 13795058186240622619}, + {7202909919242169987, 7084906191002088475, 2670999100224514475, 11205165509896785683, 9153315609780748370, 5520519463950164065}, + }, + { + {351071170739877570, 13322560781273060052, 1701785565365847432, 9955777089526659386, 7009753490594385600, 829657910123534028}, + {9606276748652074643, 4015732708367370031, 11721876633733031363, 1595979662340466299, 3599656218219669185, 6412814251963052600}, + }, + { + {322868295872168097, 10779671223207907160, 17146021042584030369, 7744919563204743978, 18009926370684955932, 44255721611034122}, + {7075518626826263580, 12948066299893087092, 7907043165345290748, 13326944701483639264, 4900286334119935957, 4216867816480695349}, + }, + }, + { + { + {11422675888913080491, 5395798484379963549, 17893801226572621158, 3834831668463767880, 18370393837527875887, 17800133101197187390}, + {7029247643873698097, 17334943497121462468, 2660202885167189413, 329065954663218375, 6698129215665562567, 13717605916501910272}, + }, + { + {8639178386474167317, 866299449001193597, 3615027842912577064, 3248451241352944854, 15229370169242039655, 14022996697023959990}, + {18261603954599110401, 277984183194636545, 7122474136492127151, 17268552229454245560, 8360275028065354990, 12658058275321946659}, + }, + { + {7568749213445711158, 11322886283898751316, 1514838974790282409, 16480451187055352472, 3521826310939475982, 13331538149045598985}, + {16615732436977239999, 2388796933096443142, 12226612954948297380, 10822339804892299866, 11505338527635209905, 13965903403607753974}, + }, + { + {17992684961837313681, 6896408298290524868, 8544072807657571566, 6748791036415412590, 14025071172791740982, 9009141746159193034}, + {13586218153614538887, 7799628080484457452, 10266486360990114058, 10957603090701342492, 17913488373740611379, 3678764260563976289}, + }, + { + {7850028067287088329, 12999005266298055869, 177742117066576348, 4187563636181037744, 18227464305249346823, 3944943827343100145}, + {693604820039552598, 11582121744559616851, 8219537047451291189, 12011868187157813437, 4720619866818053644, 4330189064262098264}, + }, + { + {5651722935351245741, 16211924818358123384, 11885056608369234243, 4201983212017634359, 544526908348909642, 18119044215050860139}, + {1629340396439724022, 4959173500186337859, 4507705775156637972, 8833696014848286450, 779478998504818906, 7902380186120673057}, + }, + { + {18293852260825634987, 11802124232706822019, 1644849027510672867, 2812476574328933804, 15557250672802932860, 16508981297686648154}, + {3465734358950613242, 526649456539607490, 1919417099895547055, 17331494709758577824, 5162227762764949865, 6242065099954684976}, + }, + { + {14405288903984360898, 3180009282630369461, 7764333772077120386, 14416489610146878273, 6877362386602494384, 8785041971848387380}, + {16205552197332611855, 1946014005873611974, 7425906351428289382, 14466564319882318102, 17948246265185418576, 2220383241683179866}, + }, + { + {14872241004765885673, 3636107144878936670, 11410176190546783355, 12181463760260857326, 10438330742190191570, 8102662675316985666}, + {6176126135590814635, 15938212979141106430, 6930351408968184663, 8991851982195757076, 5444235666245388183, 9160086367185317170}, + }, + { + {15340964667452830754, 14317488092981700975, 510238063968897076, 6837249889367286466, 525386960344698653, 13363589982130767126}, + {17072735759253073196, 3498833952641874877, 18362568207671943201, 8995020072357799227, 7719631523143820724, 1085622312019426779}, + }, + { + {13037971076711969658, 7591102587937139905, 16112103964232511295, 6658071900440103886, 3506958499519852800, 11206278262730072649}, + {874512935619455066, 14023431168230615564, 7818120766602709739, 8832031439666609419, 5585964366092107082, 11504555017740100069}, + }, + { + {15350102097560218059, 17960930933998802379, 5819537312713605133, 16574725790066529972, 5613973488460835436, 1634532828922318920}, + {6054735558644874316, 6779535286618214798, 12125632371272029575, 14822061593509407829, 9915577628769350648, 3262340591497022728}, + }, + { + {8571949731132956833, 17851489671172976600, 16122671592171467294, 17953595451749771955, 7101774572418004893, 444927268485192911}, + {12898124468306022144, 4543591108002290851, 16651517581025086108, 16702288951395475761, 9009172261902505944, 17794186523942672480}, + }, + { + {15874281727524415422, 6572132168538751333, 2488717046038925837, 7528462563702651155, 15177291123321120421, 14276075288284279593}, + {7287442030153170731, 8621411913466239822, 2230532822823360290, 17882655262254713908, 10820729357094734590, 17116812739217748569}, + }, + { + {3521891825683807648, 1428294732738224966, 4467541612632144795, 10743380230531306175, 11596549629085266496, 12996854075027646298}, + {7286872326554604613, 4747621740227512796, 5892707014992033323, 4322214473714022904, 15745271974603396672, 7332629562375692095}, + }, + }, + { + { + {11178967054056195663, 5059057946657071041, 15846370838494899705, 4058997021862163911, 2593984691649122230, 6254605580411388786}, + {4176062086390468245, 16189011794825339160, 3064989397845883132, 13286588576296135872, 535125068036700463, 10408854172492123217}, + }, + { + {13415824456928728537, 9031989784978508164, 17964218247364329886, 10744745034242750397, 11043008786756317850, 7568533431395324401}, + {7507011205371347198, 2388282443864154121, 13696995679089020165, 12583409078815059304, 13898075392069488590, 3664734608506976906}, + }, + { + {16544958402351236901, 14337484652764170641, 9770866337239118974, 17810777202725060237, 2097808205286057289, 10362289157561627722}, + {2685761484429320421, 2462399891877992298, 6512262486201450596, 10981880327208688077, 6617301996979402163, 2835239075992528291}, + }, + { + {7991173582500478757, 8893625338111976660, 14169111919230117155, 12356393203568432042, 6624804336968870156, 4373502195159979453}, + {5525831087690451674, 11667968375332638977, 11672899591207027148, 16453647862989440606, 11804399513913845371, 7628460269199181450}, + }, + { + {14630566089474246013, 12500213971114656059, 830106031407073402, 6911967831791350423, 5540576114989833332, 5622942981234358149}, + {9345206395676904366, 629433153585557678, 12592664746177863352, 7117895689488311014, 6126264353083621009, 8672251668710377501}, + }, + { + {15343270797031359599, 11669913580639087574, 5479735138674518875, 8134395341091815991, 3472212905841111046, 1943386847444310169}, + {4802323257275851562, 13041393404614837895, 300696023871229709, 8124939534882080453, 7037259695740405607, 15666477288369374120}, + }, + { + {16929655147930952127, 8700678224807582342, 6899508338063907541, 14124820011808216974, 6685131911353931949, 11392136278714910024}, + {16320977876025241931, 1873285772151321892, 3864985292509805330, 9209816330063069102, 14360660501914452161, 13765026774665638630}, + }, + { + {892554047301358165, 8208545275404753447, 8552497586050955747, 5886745868526813090, 11422451069439740114, 14454702771432318255}, + {13473748178404916790, 15675215165690108087, 5664345539094868232, 987897124768858568, 15329698597492189645, 13301936956751718708}, + }, + { + {11819868530282842855, 6710224194746120191, 748201410135027328, 11307022666945855023, 17212649811821554251, 13423110040809399786}, + {9934050328022487645, 12074357593722511625, 6630946082142899698, 17056161405408381398, 8571006633367538659, 3796784189746526746}, + }, + { + {2305785560014348207, 9531795736757421484, 9618934670188570881, 14780074586441306089, 6200104801707088881, 5386351446699164262}, + {3002942961830406638, 148274483233190080, 12735679168321756134, 14693507680316309726, 14232858087052761737, 13985992269476016693}, + }, + { + {13842387890174377681, 15419080605999723375, 16681571383346636493, 9653218004391250805, 1748476375644147649, 16081919636049288692}, + {16200057164189696404, 16659975838973439415, 16148363345960831424, 1128253701358674568, 11627719509137069576, 4062100673790478823}, + }, + { + {9445528033084918138, 3236780574278685899, 9682773997054520194, 3980365165990825614, 10958694477307693178, 10839810148743664524}, + {6650282121724231548, 7894922159420004756, 5624389477223934865, 18151956206730252126, 3735677846659494424, 7111781989342355242}, + }, + { + {10926693111959793122, 3929513560799028061, 13083700370081498912, 7606788298622011804, 1499929199041655117, 2537708677997890346}, + {16163615921094614869, 12490168710448316035, 4173408469387936546, 9680453490885130745, 6897387665823483412, 1803882466154055696}, + }, + { + {12928382421675599167, 8246098434142042032, 7828289919035992593, 12704490623615851803, 11049427248294980078, 13839977807550225944}, + {8790158444480790055, 14691519147850982325, 3571740556626361440, 2025494493460599521, 3901915857099204524, 9232848549491285301}, + }, + { + {17205250580750313739, 15838972152830244406, 5212027996849957464, 16696646218907655391, 13718292263491425643, 17806855155656742837}, + {11988041571551593283, 12853752025657189673, 13524920127388710455, 10671352188986408025, 17279385799981015698, 4758202966923836309}, + }, + }, + { + { + {3974313353418109687, 5720345224825286858, 6801835843798312295, 6372634484952764872, 3310006789326513240, 2726055308497026029}, + {3843770043613727251, 7900599654720541372, 632972795419277904, 5983319127366592262, 3077785537568329842, 11218370678822489750}, + }, + { + {8928421106978139244, 16345148895360341144, 13492011400134727288, 1731289337634521374, 12525842512649542947, 4207120388067304407}, + {2345046098001310699, 330997644936357897, 13635040363459393506, 15230878178212376507, 13652277951430850918, 7237296141945425478}, + }, + { + {4557723407539085034, 14471756909246230823, 12448850285779367089, 7851797223627122363, 5151430975338428030, 2954895927776921398}, + {5279712016090746131, 10809813162354586237, 9242053890074456174, 9668653512111950665, 10135306740731568651, 3351464240228973156}, + }, + { + {1627053608069570695, 11376938021692164730, 9622466798286684763, 5827728193917331600, 975693545877321955, 17470494739932363034}, + {2436171715026125366, 7848361070155121218, 14061221750869732481, 4888283785453330436, 5036741489113467755, 18084794423259936778}, + }, + { + {3552955380513038861, 6493678664778873794, 649357577150179579, 10545862185632419419, 16350124503975893898, 17724367842084936677}, + {8896453178391269512, 4710703558251776246, 8492419126400496150, 12768468520236451572, 9192761450614257478, 7438647446930613021}, + }, + { + {12369531841339403158, 12996664064774054476, 16155473999921375261, 6644207479370307599, 15208474964382806744, 633958492471874768}, + {15790482482394397377, 11673958026072739923, 2075775971265990014, 1102830502989644674, 14328138387706433231, 13602359449553119289}, + }, + { + {12143092119248055873, 14188915263690936719, 7408425876028150433, 3779414505485695820, 1780029671596030155, 12865710926564478965}, + {11680590440944425259, 6090714137241796515, 17343249885314900203, 16644769067866316590, 7256952446206185353, 12961945084971064727}, + }, + { + {11134447122165152593, 12122722588466177555, 13031738851579131777, 775360620960643964, 14535630049172421527, 15517365877497081698}, + {6749416834835986329, 111798195283805063, 9427922671178152846, 5583634039175768131, 18026394909638384188, 9381210933213377107}, + }, + { + {10334265748604755240, 14313974363914896934, 906523409788490776, 18014259526343590726, 2489497295341492694, 15497769074229220560}, + {16667753502962144886, 13343473574324449479, 10922772232061902038, 17638948975896960836, 6206546855196209053, 701379544767660020}, + }, + { + {7323167804561066698, 11606373977379537829, 7740797211952786009, 6774632772002662447, 4137066669379889537, 16448062068535134384}, + {2263388950950990004, 13986419062957738814, 12736780551361126087, 2151837813422636155, 1478109418633068180, 13196418687650255350}, + }, + { + {4763801360917190189, 8413965106647468101, 4459652012857109043, 9905026392952537025, 7732441075598956516, 5321607056947218327}, + {18121980170092748441, 3481588764335216251, 10446782825632997719, 7693360199940913038, 17104571571510845330, 9855412900039516293}, + }, + { + {9385835129240491860, 4824589714590984336, 2196446888524873714, 14983326779959559720, 3813990482140930799, 7930070026494865435}, + {10845320348409053590, 11702362686639252435, 15805206625312010834, 8614879420112692657, 9694429543708544128, 10989853026030014509}, + }, + { + {4594816827257062041, 2562345560258457605, 15050193570974712932, 17246403151526033694, 16146699389908107161, 3086841042515638998}, + {1177843674463060692, 12536747725401551571, 13206715304133223188, 8671490102358535635, 12212794350549092683, 20556749311088582}, + }, + { + {10565304604241425748, 5627103307724972881, 2705248188066943448, 11105071139145988281, 16803969759084451954, 14319542282813740942}, + {9198217579227787191, 10953486347952736044, 4560368619486330585, 757042920267352831, 9594548960853813804, 16693022163678979226}, + }, + { + {16489742344230153188, 6539412415140498039, 5165832543217723569, 13003478072329918265, 10047084890632029191, 4694331753623574371}, + {10703728784580237099, 15556245530594099306, 17588951018132280983, 3935002524499547861, 17702492742125323184, 8520257892664878061}, + }, + }, + { + { + {6560439988460907757, 5477297489685795935, 8263272205317190744, 2155221279069076320, 11867925124460267529, 8571196738200600952}, + {6380793266523402469, 15145030817477249320, 17647327914659401104, 13319573822063298508, 5205094261198279328, 9191043393335719432}, + }, + { + {12034745616655220445, 1806587157936901864, 7601847606478345239, 4533004298191165610, 3124085236761665559, 17389156053407331651}, + {2864989624008200953, 5136009810031599899, 10582433036693217288, 14931735150274274801, 10439401220326631886, 12677134576293396474}, + }, + { + {14650755191841474854, 16300166795758970811, 10649037273588294054, 7104270209860104788, 7967261075606297822, 7279561497784730946}, + {11697616288471532112, 1052366164901768766, 2912238129374155198, 9701834771332452417, 5442175782826775844, 2299045115469613839}, + }, + { + {1287332463662400432, 3513212364154390112, 15346209202263562543, 10855689071781783808, 1452088722357536954, 18071443086358423492}, + {868440689883949449, 1816852863222370485, 5199615657293991859, 9449935448458274470, 177207136542962287, 18245562675978917823}, + }, + { + {17651410429892341588, 2994246517539724152, 17728394019247321391, 15386586165465459648, 3241419904742758835, 8030267348237056794}, + {8435074151094093690, 524712275897055450, 6804195566995782773, 7679712373149113143, 7995287808064276131, 8927279975652841496}, + }, + { + {10778050409776497212, 9536627676531662024, 7658414011223352564, 12327599912454605669, 10735492819935528307, 2807151273987894916}, + {16239030609792653613, 10332717478474239620, 17257364018983708944, 3381279635307716914, 6577585621142376520, 13802487288606991045}, + }, + { + {17954497611593459666, 3664315036641118415, 16509024076253684643, 17283250569741859362, 14982375386085505669, 7689080851173975344}, + {6539602342283003922, 14623322619256010467, 2886392582253254823, 11318353402632029623, 1048960849463114154, 6823726223520193527}, + }, + { + {4530098428200707620, 12839096969967251554, 6198816293838808699, 14497410916805455082, 5464738801928006246, 2590420136286143409}, + {11539859348742386287, 6448283683032046535, 5190841120404297714, 12682630274691496068, 3502978196473226835, 12528396777891929349}, + }, + { + {3746596285568179795, 4244746780559722754, 14192133631604917518, 7971972442736154200, 12850431088842970183, 12924848893782277960}, + {6210043026683817121, 16093936346760077654, 12896762480304091787, 37796835925086671, 3297320202618582783, 16993735692589610973}, + }, + { + {16449417965222475184, 7693932127514324007, 365506606826317804, 11357852591741708092, 13089599889026601450, 16903400737548641302}, + {16984170724371326225, 10391779522684702015, 3067870164038615636, 14252841648119381798, 16218707853229586386, 7836241961586971830}, + }, + { + {15192483994066769425, 4516676767104334066, 3298548929696008355, 14149842818379505147, 7754159985358226567, 18074898548922930513}, + {6787600702315314002, 17427509000681768725, 454039934719798915, 6687725764533626315, 650049015881932447, 8174481017589685550}, + }, + { + {1190766049258248701, 16712766508257076609, 16011267443004798709, 4304976661940244179, 17401735122754430323, 17805491770899188624}, + {12819712409221279306, 6012470734633531883, 13202842728516275075, 6714649673431658519, 14766728086190011567, 12025005326013128366}, + }, + { + {2550442130803597746, 4388182498378820973, 11877916159578114240, 2491232568553766269, 3061633366263606868, 8930196601588700949}, + {8351158090909235917, 17643196865264803997, 15136059012100053669, 10435163437422615040, 14669662828147957267, 1927075496220718405}, + }, + { + {8522264882073051051, 1620578049778200332, 8273686191210510914, 15161466784984992681, 8880636972606501019, 5137083413106892985}, + {7453074636338505180, 12738938384123169905, 14134926144460829976, 13289026532736437285, 9961457855205231232, 16868281080316857896}, + }, + { + {7869220388851879053, 9243594331185701304, 4578820859414588545, 6726500389404417900, 17828060266225175185, 2805995484906762914}, + {8127865232957840490, 1119209698667346666, 1543121112626802223, 11635665147697604228, 8700384215304758069, 15110956032330707009}, + }, + }, + { + { + {3999765870898298471, 14172770317997608516, 15838808511345459441, 17483331932540195875, 11537545446428919358, 18161106008778308362}, + {10832208579815022485, 11144226171709861172, 17832358814667390783, 8104027490956075374, 7738001035752373711, 9976303985994712521}, + }, + { + {3053316092196908301, 14599294197004415859, 11376968891216184065, 2166021074759834008, 15176324388121041813, 1177183645238737592}, + {8872756236922047177, 12695199395087628448, 43719476960233138, 9968538827589652609, 18292294231863534866, 15247938318298852535}, + }, + { + {12542532240058205361, 7268582068935965299, 13539169522639613195, 6415306438194106780, 752732255800848126, 6467156824109874302}, + {8919765688158995394, 10376805730213749427, 3560797874989249371, 13765505640431451465, 5413502209131873679, 5479930898819906026}, + }, + { + {1620953412301746638, 1834494332682380488, 1221287231603861044, 7143200653970910387, 2142887614724373742, 515369627860172237}, + {668312192947122200, 14495573370059274601, 19053408511875346, 11573007294798838371, 5996919291690021344, 10963600343891369281}, + }, + { + {3772056564995867704, 8936213084537725440, 14741295503761475310, 10169482512429303117, 7395158688725827440, 10625709550842394718}, + {14145698620161177178, 2138174424797012712, 6382911437211835009, 9621628449746421183, 15318114188233644891, 9127092351657370481}, + }, + { + {7569439361788924386, 5358743744068588919, 2472617216924555430, 14446025836401453832, 15206339952764265454, 7985026553542652918}, + {2885368393308729366, 7662239829932173449, 16902869606779080248, 173909372728520956, 4745825384290840252, 18238389235634593837}, + }, + { + {17278763089415978011, 14648999284612290464, 14549644405624342751, 5242220935080712551, 1281695041546515602, 15620247700383069753}, + {6061717613096359788, 16094895295267398297, 10954605165474093325, 17036094738837097294, 17315827424817840310, 4006783343088127765}, + }, + { + {3347760495316022590, 18353910874341978035, 6043778301036432970, 13355724919784404041, 13015796096139756391, 12036177583658955420}, + {6518471179080804014, 17158842633921763658, 14405522311746951243, 6973400651137011042, 4746890325642485958, 6736547103097705136}, + }, + { + {10669366973839367672, 2385569531879845310, 5688157778456360570, 5432194657022107321, 12671178471488614588, 7761060866335594839}, + {8978451158519567422, 8492352982229672202, 16643425269116819050, 14671179713658552694, 4363789067899164540, 9370620302779212621}, + }, + { + {13310909055019013380, 9596076897475568893, 6086247547890141325, 6615089564251394108, 7111916614455620574, 11675908774987320387}, + {15925711704010954904, 1550153309190557596, 18423416479089687440, 2237807451710845475, 18354395799746145454, 5438928742395904784}, + }, + { + {4608572069409268399, 15073585230746724421, 5850493471469990136, 17178910933214514567, 9197442918599759710, 1507943865355025659}, + {10368207473957700231, 2360337372791198513, 5963074125901124077, 4250878605574616141, 16077767359709901643, 4855088307376525666}, + }, + { + {2203675397636717516, 10128211604548624427, 4835587188573085370, 7287969591049025649, 18068255218779265239, 17327995020974268765}, + {5719882824311508910, 6709568563671378548, 5291703009398100222, 10788191138630994747, 10408053012947876069, 17443305409665545835}, + }, + { + {3342016462643355321, 16679489257601825281, 12043384844586211843, 2115834496701139743, 7212063995634259653, 9441913556375417406}, + {7879272060659630672, 1322154690117373473, 1520558149537399921, 10259915503278516179, 3368650106971654575, 4144693617269779944}, + }, + { + {123661428923518452, 17329242377861899194, 2113549760254636588, 847106394960135909, 9954070461361301937, 15563438708607816744}, + {1040702637047883211, 10189161753028718742, 4009789976573376701, 1936488692781097326, 8873733742849194027, 12009079112311092681}, + }, + { + {17741068926415815996, 2460265563474934139, 1072480528377351648, 11885568366174373122, 275536108394716793, 4505994571681041972}, + {4997815718062610307, 7966342590073259297, 12194728418927987790, 7653673951695752977, 14783821829300070265, 12992716489185017892}, + }, + }, + { + { + {11640101960998639313, 15953805101075159736, 3493841973394909037, 12961869929990749200, 13933610253398336212, 12682152790147939130}, + {11399471237860797020, 9683858492545796215, 1548460573545589546, 7173998343795107028, 11677696610449743857, 8398835533776273489}, + }, + { + {18347627398589476579, 10477209504919905991, 11985004040168566638, 14212280469459055980, 17155809208164808508, 232842756626748023}, + {17663176896634111834, 11266862009271054832, 2801433370426448852, 5656158823188135309, 12410354059238919535, 2244879375847000921}, + }, + { + {3190520016779022051, 13246407962418081856, 6668351451725762413, 7768576717338627844, 2262028295584292801, 14381567562481981200}, + {15520621358714576108, 15362331656590194956, 13091576850573016550, 5790621552805149408, 11085966456081752022, 7995145398979072602}, + }, + { + {13623592007492989552, 5695669685400021686, 11103834195452561281, 3924874736262277070, 14749945062025337942, 4117578579179786869}, + {4942010861531575831, 1697597687729901180, 8378286745350822869, 1042755497644966445, 4609634700670610222, 1595371322671204226}, + }, + { + {7356907816961926000, 1600282058170066082, 10425052022355846482, 13802483414078059083, 6527010123231557260, 17014236698247006256}, + {18079966107052649494, 18199473573195697305, 12045755339859992655, 9377227322475274712, 4707316309742615490, 9453719605925386277}, + }, + { + {18077338856333540591, 10940855750925578638, 14676427357499773843, 7077022433649111811, 16481763083992802494, 7834705448306735746}, + {10145419701640226394, 16562141330625721365, 16626213781430570449, 17015973614586109901, 12442022173385031947, 9087600251713065715}, + }, + { + {14206474989889371590, 15241997516043179936, 10046960511573015546, 4012668500672179053, 6302607210097986007, 14073285009414845523}, + {10393845740118669710, 9303896053454113349, 318938169015454180, 16356683611313694376, 4951073049233679376, 8961912152048041842}, + }, + { + {8028335957857989427, 10757251699849982309, 4827184158706600421, 1972803202369040744, 10894855692237667943, 4915699847075993000}, + {2764904044867252832, 3759515232559764976, 16791991319742688688, 15982469402311953688, 4451160053970330710, 10836878114068503963}, + }, + { + {1898218734300846462, 1890052160621754096, 17802491502548108823, 6190373917215274157, 803001649590263174, 3115437408056727221}, + {17784493560265139286, 4722713594994619444, 7211558284311348923, 12566601502228621014, 13213147693274689277, 6593798376447442065}, + }, + { + {14162633535901746112, 13888434174969429930, 3406707891053136625, 14343716935895842484, 624836619325620495, 16396608622030250358}, + {11243183545197281900, 13435578064685298093, 8553550930687221160, 11901710173536269070, 11201351899495201574, 6707939517125993234}, + }, + { + {9276193773801045700, 5450558417706905067, 9450904291105895205, 9833917887246857818, 7285500844025425965, 14754203014686269594}, + {810778446780024575, 2913316233752324212, 5099291060376680008, 5738827727953191083, 9464181523940859483, 5936468513591129863}, + }, + { + {4878961831520826954, 14509215665191898446, 6708977457709037859, 12634291587039233323, 14051107097299387218, 1257131711299495146}, + {2944921399309621693, 930008782908430501, 1144887774944683814, 12070375620973983173, 8562905952672576547, 6655131226711101957}, + }, + { + {2899574573379169897, 1484714325759426788, 13026584324463930570, 7354422735718365143, 15271320868736293087, 16264371063992305811}, + {16407322345111310891, 8408499977463544416, 15290440212843619800, 17056597194115740595, 1666861996182883636, 13197583661824364865}, + }, + { + {6358774672677922630, 821442820597003176, 3813988636387892061, 6549290188660731594, 3924164508423783399, 10897312938877431610}, + {10853174774402828944, 11140723571860242940, 13060695462912345962, 14956978874467708930, 3205778154938349955, 4857627122623530951}, + }, + { + {11135246107897067582, 12930931433283727075, 16046715789896369411, 15407716337362202421, 13785191090068112, 14267330907406142872}, + {9630464474491738918, 15849686165796549334, 6769531647489555179, 14133844287397398953, 14941312803089108859, 2539509877677478606}, + }, + }, + { + { + {4519426578252664019, 12498635300136211504, 6321021405218202857, 726318959046945666, 13882007167200891438, 2395319726326567532}, + {14574068852065085528, 10190204462571587840, 3147469108386280925, 10820985172387594951, 6286320751972150388, 11262911446209261547}, + }, + { + {14681940503030753559, 845444804754325384, 17738750192032703554, 16488507045196756482, 11910847346995920258, 8626355026937911802}, + {18017945832199185475, 11050392025640445707, 10242360224530664755, 1617332161128003926, 14748788017604482554, 10938197837639769317}, + }, + { + {16523024021068053599, 14153734702399414874, 8975814599494295874, 13479798347939192877, 11858323547050135962, 16835135870848796279}, + {18442770255404680133, 6432227429946434052, 14626833122688941937, 15380321854072410541, 8513682513482878540, 17341688292014129030}, + }, + { + {9982750773031032188, 8982169985591678537, 5249265836220267338, 745482432716420646, 15780419841302462097, 15584095070673766359}, + {7735573468252400802, 3795411598689442193, 10306326103347347341, 14546148414040805838, 12297870683806673875, 10180646444691724781}, + }, + { + {12710315976002578004, 18013486904999737909, 15071959480643480686, 11232436041458243738, 11242505152758575624, 8836015187488468465}, + {7163797004587484021, 6976175793895240071, 17645939623644273967, 15778152496214427324, 11329126604565270312, 13110466004937401027}, + }, + { + {7062286409431630812, 2728146973991795543, 9706360251287090173, 17163823676653858159, 10108371106182915478, 15145658691257940197}, + {10397214263743326838, 16577575568682665639, 12639970963217473417, 17440990594269730118, 14950277950848187668, 17431952877316305268}, + }, + { + {6480066766050317343, 3568668077668658088, 13783844110647363350, 3962057444946379264, 10510088723077169182, 7170700020292960967}, + {18344863488775695783, 8824084188613580257, 6513472792662119798, 8283498389636157255, 2472052284746094828, 4520476222306731358}, + }, + { + {4812653469852902630, 7740257893595917350, 933590915187574091, 5367604661371230699, 11524926856934229507, 1547803982974742036}, + {7173249707714144699, 3782455439068354757, 3436775349109564743, 2186512130420632639, 13544740200729805403, 16975429410143506788}, + }, + { + {15877732835883777356, 5756653960126645671, 2937501458743429054, 3189115871611189466, 1436979939858552352, 14064609826654033973}, + {6211184029252028368, 14949803431947181926, 13070266838064658248, 12061247352423941993, 10971542374730440659, 3480209766469344160}, + }, + { + {14525709786341885047, 8039674455841380225, 12237612161305828783, 3099183041004087991, 6867967360204688651, 4823608220141329719}, + {2084876862441787600, 12090014665548950766, 3746144123408878153, 3923168966734460049, 9736629444481310223, 2220438547349139262}, + }, + { + {12036615988734629195, 16475002855996060653, 4484972141187264922, 5765002039288394851, 17063350421202862246, 13141299915467681366}, + {18175008310626520279, 16161757370162131471, 10768451552383046438, 17776643199179949221, 10598298165332627044, 15321920779815178261}, + }, + { + {11362509937560115945, 10576153459965418079, 1262608791982484244, 8810089598173523841, 12316042044260285948, 2268907115684739741}, + {11678522433578723279, 13370587091821540471, 9764685266488488043, 16120963353852178901, 6374843544537806852, 9069656632944802220}, + }, + { + {2566151116175682705, 18419852245029475374, 8482627328365732076, 85390825415125292, 15919801360472688229, 5270660089582520119}, + {9546653662379271343, 15939549011572950268, 14048762686232196880, 16243975286260758268, 11298686963723559385, 16417368127514338489}, + }, + { + {17555499161685523827, 4589562335151500279, 4172801013578954247, 4538649193559819086, 14507716041867679317, 15478474910313981001}, + {6017839036160861908, 4246101108460983771, 13629753094704860997, 5513007954781513788, 3904348220984245516, 9061778934720872085}, + }, + { + {15748938882069408756, 14277135008861981773, 18217921952747007161, 13344713176347262386, 17886228199837380528, 1540401873780123937}, + {3324086529084340824, 16272343370371044813, 742477341260013957, 3350915636385358992, 6792514656381585078, 8878152636708404891}, + }, + }, + { + { + {606092015174216516, 5918356105766628823, 3171854402026042629, 5083410488709721579, 3403581311288428367, 17676510467286289614}, + {2967008223055154986, 4440513410884574177, 16523045544893119274, 3217655037837401371, 13054487720522321142, 10034418456224208190}, + }, + { + {7347573045686808521, 8524339315025279874, 16314398830774990578, 7148576901562720613, 17397796952544351613, 12574968465368627587}, + {17127750532495035623, 7031729130299604572, 8389747942949500517, 6996080963912626814, 13495784988274569257, 1168514218006331799}, + }, + { + {3096433627791070893, 1860156442548924013, 15384249936468274478, 6818491582204214579, 16342638307737468887, 4369943414960054850}, + {17533478036417612037, 15025947594061943030, 18236676236976149572, 7039406316466350694, 15869565193009626370, 3852675700088288543}, + }, + { + {18309824205914080602, 6894088905116897314, 10591623158526430812, 2528539630082230699, 12042495883122935729, 5844044239001656400}, + {17005697103726708846, 7925252746001041067, 10999152033548088863, 9154176622465162277, 15084949920970423534, 5578598380515797128}, + }, + { + {6917179209198910574, 3886697537844862434, 18150496386873591051, 4972646778348909437, 4969661664166180669, 2872836128490559084}, + {2704398887171405709, 13639654495080115785, 11425684371658593338, 232369335821630324, 218748759902514707, 6158205593118649580}, + }, + { + {16496178860935794046, 15119575313167393886, 15571136778187380808, 15718174980588554218, 8407222631419874046, 3994751679816363176}, + {16137943000116730838, 649686844284716838, 8196756005862490544, 6988085908898901263, 8051931904212610802, 996284375053598207}, + }, + { + {11202012828915629624, 16434906580972492259, 5073784107975608951, 4555011077667954368, 15056393774484220435, 7153650342547995309}, + {17034230510077633808, 9529331632480295071, 17805365034946979115, 1306070794871122132, 11283252790245181700, 14195024093610616158}, + }, + { + {17062804313340314021, 12487559988166578822, 15223533012653521266, 4215428489484541930, 16150265079986093045, 5813481978377140106}, + {16065565784667247990, 11555499440070100600, 12227692665725509655, 174038838204068309, 6944904892485822829, 8209387774354117162}, + }, + { + {7097764295443365680, 7845963410214653920, 5797125233317311504, 17926005715153747711, 4229684472586339799, 17705398018071993192}, + {11024978540019744970, 7926106855153668317, 3165689713040846858, 1324462571872837789, 4092065205041218276, 4114073167420719940}, + }, + { + {14832234719124735027, 17720736763724642037, 7569347324614805545, 2422203898133075744, 8407080162538697312, 4638392288322278865}, + {14250957996942719144, 1268388636046597839, 5742106579831765479, 7403762642777718888, 10608168393433486378, 5148201736835738471}, + }, + { + {12017738182708598078, 15496109165938912856, 16276087896775269508, 14348251368567035394, 15495719802443424398, 2886769213483924492}, + {13088574881807814182, 6175259348987407998, 10240343649650858024, 2445547966947917305, 4412093101877027279, 11575806026599033878}, + }, + { + {1978949153914018361, 9333756199061121765, 2483677446328516905, 4947844288118935595, 8796341380385369544, 13376588153739423951}, + {15189671345805877067, 7857386656423263866, 12087267128677715980, 3124246805898824272, 8155860863800786429, 10855265042165217616}, + }, + { + {10968540393441817286, 4229948088947631485, 8845677625419290462, 3176865215857370108, 7460329129753473479, 16979518947567294508}, + {2509227000662036147, 6062006495041137172, 10067170914885555116, 17887270821175830326, 11296565130650766701, 7373311159946922401}, + }, + { + {8850120526955796736, 11314469582193677783, 1068054995241090552, 7318394094178466418, 7619360585150493559, 1453572552029566577}, + {17996868603041808639, 17518159987665308986, 12081491143590269787, 16972562088952683938, 9389093909820463685, 4548563124413215604}, + }, + { + {17046249548250582064, 7914728399210345507, 4240928990714296695, 14486835470503581294, 372290144157579880, 16839406978927405392}, + {1016866348257954267, 15113309936348826018, 6432209476523479319, 10269747907106890252, 941691948152294603, 14287414307327182997}, + }, + }, + { + { + {1272546058761547252, 13578575248362383071, 7500958990496300674, 3099202960982751824, 6362531162831059087, 2019233083206809658}, + {2754115770602762476, 17265393813973046355, 1460109499264827148, 8566701200794847730, 7001275408840316981, 8133565635966870191}, + }, + { + {4530800567522751634, 172100420111867893, 10423105592359647894, 5854403877381514842, 8749270627115121145, 3573817859696661904}, + {10641876612315799701, 13310097519809820175, 2575058335739178127, 1763270043880050, 13175676291469077040, 16171136871688122050}, + }, + { + {18354147526894604667, 13484255054412392853, 2800700506464137914, 11110366580313920102, 5646064147441879882, 2795616433118016579}, + {2129899893763421818, 4807666508003926776, 16472812490021449281, 7681490117554722919, 3438671827454179974, 13557284264475208066}, + }, + { + {5975319400755341093, 1124738826642685970, 16753728698306033686, 16494353205423996145, 18061430851006650946, 12807029835851374145}, + {14925084576890361984, 2612771955533652816, 8242017343741157450, 7403436780273402474, 14211525852367133182, 18439046101355433515}, + }, + { + {12522140250931309228, 2650365165363684707, 17266707117780681001, 17646854366183132476, 8242359948852550575, 4320679156333325465}, + {15229476123325427164, 422299931396282295, 12793864739684453285, 14299923645240128941, 9978405170065329096, 832960934203122298}, + }, + { + {518871060412814841, 15562218878203565824, 8980911201550345823, 11524613147177454714, 8894386144833336880, 8282385053468266803}, + {11036310375799843604, 11631323855952279243, 9204542676358250227, 9017637584223443028, 3369721496038149573, 15595900417339550003}, + }, + { + {4591440636846949512, 6036488867281859201, 16533349215338691556, 3133742230803728901, 2571899330106231363, 1631909183838142939}, + {8989734436763331330, 5978410296483257172, 2006955146568177692, 7522769147634649601, 10220842932346919807, 15597809501020248076}, + }, + { + {13439894621213745503, 9146006640549707854, 5648702331867490349, 11405536749919113563, 12230345710914827865, 10071652654740622079}, + {12555953518900584840, 14800100043573333557, 9904134836732167291, 7181207832363950334, 12514588099534090508, 15307927244603231548}, + }, + { + {13605621509983689364, 10781859117898335879, 13538880269705946725, 8371044748813843478, 3462400909078782886, 890871523695605067}, + {16499951906767373988, 10661436183202627477, 10666398637960730939, 12471664467090838807, 1750972772377056241, 7518131157858325250}, + }, + { + {10247949599901648714, 14190196306159090329, 11216722499720804306, 3590282982469992444, 4633227070625809035, 9190116695797697665}, + {15939242820763354667, 16077413183961690083, 6355653157022204783, 8580010924979501748, 7153725479094108372, 1357680516578643501}, + }, + { + {66627260421700178, 981976094061062611, 14088629719356601159, 18087879346236428983, 2519331146402108878, 14689662575392662258}, + {12195986880010891308, 68431921015150749, 3127083875017010141, 3161714979740429833, 12839293036406001550, 7341433216159877049}, + }, + { + {1065953584516863039, 15096288182389718648, 4172454286491200670, 18026295242507833531, 5078063585310882257, 7268157657978060289}, + {7875776889204835546, 10627478238674063372, 8099037147030128002, 3027823377924903270, 14915487051934001991, 15228458635498084487}, + }, + { + {18435525997497788188, 2784122541135616216, 9899619044143187449, 10187065183348144288, 14659596985883743461, 15442370538955392962}, + {17895314255123528958, 5201907198851189607, 3321003244006213256, 12358309570578006578, 16348924419530434982, 11908899161823776291}, + }, + { + {2996337363285490304, 5920778534715228229, 6118912118872553172, 15730295041050666050, 4957216697404822003, 5536648704019369663}, + {17046266803691791611, 2824215581505967575, 8261255744418562057, 9146405379237138408, 14347950681302095310, 16755353354313831572}, + }, + { + {2023775850404636364, 10364798591267796992, 16581829103891111877, 4554451792573593634, 725404179839321971, 11768827269800328280}, + {3438461944423664753, 5207909560991353292, 4151502141621601136, 9129240992387993021, 10289852383205392490, 4419823091950629536}, + }, + }, + { + { + {12192276596816111129, 11439584366963014783, 2713946508948792470, 12156092371372338197, 5082916671545533837, 9910663863905945351}, + {2895173316336063022, 8340424674337499647, 11728516556339912814, 7593958655663885127, 14349406256224440438, 10167298094102276396}, + }, + { + {9604776696424199962, 3890505023889250408, 17042346157821590641, 9813252657656690957, 3258804089827867072, 9204267042383472101}, + {7747649746653076093, 14320851129876639286, 3963186726043119688, 8387428722722708424, 10944959183156131923, 12376934458606855405}, + }, + { + {6374660930662569399, 12346634963964714147, 9701085914647913938, 10287390907227015944, 13392157278046428293, 12147807827670963406}, + {7192397644093650214, 11565761799483254133, 8650181311221997306, 17210098121268283770, 13830241999240110878, 5113645900809384231}, + }, + { + {15158945955863226945, 8229963785033500122, 807836554855297163, 1605387028888366737, 7953194974476541404, 9367206363171169167}, + {189311819502508835, 8213700212546178990, 6170317059714889580, 2177468661830227636, 15110619070491538357, 5283152492368065731}, + }, + { + {16607045468719296517, 2927802433169566022, 8424681719366218084, 17419326047422606150, 5999905625970770911, 6190744183228192436}, + {12634495609470650905, 7990399520412760153, 351497963881822847, 9308418808757913317, 15411526673945299267, 12287423269457077297}, + }, + { + {13180158784974106865, 9942520119447471544, 5134405864152878608, 4720032172529013059, 15879568571954680415, 12977824023383269741}, + {13377925830416234380, 6393639184729793137, 5830766798694674856, 18039280938728751023, 12060628440735138632, 7991124073272328857}, + }, + { + {2644049280934582490, 10000276111558865661, 304722485028140043, 11735908257972102216, 2166515612050129815, 13377192353750901582}, + {14726585142314469382, 16602322022612937022, 4257344852211444460, 18080317473257477535, 2135517644863233373, 17513835768414110554}, + }, + { + {8724634927100459054, 8808563927836495504, 7987949369395724856, 16530109834509215943, 3846892622369353218, 5202324697033273279}, + {6850156471545519811, 15616657543406258924, 5319309874170900032, 16821994765034133697, 11207249294481864848, 9072369915476840210}, + }, + { + {4789875659742294869, 2967870937886378114, 5039716748733970466, 13024655282622758546, 13532935784717493836, 9347203783138386205}, + {8437277641527033147, 7455819464204777750, 3981495148880689532, 17282508695124259106, 13046846599571196113, 911227421359412761}, + }, + { + {14260224171888129031, 18038330451640326075, 15187295489695980501, 6762914031777041371, 6164418084043959767, 2811459417788208737}, + {17735002493861412727, 14516376847997846647, 9469431640063725785, 13958475411167704800, 14313946757521744683, 820863393193999746}, + }, + { + {4594187992219349224, 10516014328076789329, 9634144629372521799, 12811929681753256189, 1612050195000098012, 10578937287722203100}, + {10753937463348294286, 3603138206444261394, 9977000596369528886, 12918098041632842426, 7822977537561576313, 9364821144993035825}, + }, + { + {18090855139103467087, 5666769360330456887, 11220391310171813836, 5925748024381680440, 4640306010653470273, 18420049688662192498}, + {1059075524163100205, 9669195064815845119, 15313725541560391108, 5852840239013352895, 13002771717222269682, 4779511585836627626}, + }, + { + {241470604732582689, 8576671504524153099, 225652023678227074, 12435872718858072551, 13214352155330021296, 13114666440706969044}, + {16229486748212187548, 17546920563101641584, 2680822621869368005, 9315236640170012245, 14213661658286924384, 16853567802071195844}, + }, + { + {9323859950832044295, 15243140817228794442, 16338128914658363502, 12809819155289324786, 11997169044878679089, 9354840640666247977}, + {8822752410054480907, 1693710795906789185, 3728007655785421863, 5709205642332505842, 12656439228195873274, 12902472130882922605}, + }, + { + {14607278468875625959, 7672085385893969446, 11489053104399436980, 9874730896233758251, 8525538217421482215, 13557027426716988643}, + {11011646714046465719, 5278340269600204139, 1189175061902172835, 15246577042271755274, 5610476507823471218, 643296281309723962}, + }, + }, + { + { + {6162274162111650349, 9370977122090552413, 4694677321413743677, 15950549144746715137, 9635784431169384220, 6961808095841628377}, + {2163304554817059286, 8135281500465815472, 15429903319242318055, 11931312695286905498, 8894858811936530766, 995355997076750921}, + }, + { + {12678890939214435529, 17417003843916143348, 13742839322904008361, 10152726179915321290, 734923888530823747, 1110609374259636082}, + {13691542854487986519, 14664730400527454719, 8718834560598843193, 7133813452251675747, 16781599914305742325, 8788103601345715167}, + }, + { + {17797423961269151165, 15688097913738577129, 7587009064470741374, 9652300434517855281, 10128814085960764645, 13054349291137249827}, + {13667863971566990101, 10673432944181115990, 5827094206620143396, 6099167371319575207, 14812954584184361536, 9860618325640310042}, + }, + { + {589591245000469796, 8979433141915604381, 9021800314668643791, 3750105644114233003, 15670991254808140563, 9806671408565926028}, + {2465691143012527725, 4510267491638521072, 7232653231694705753, 14855984652990117558, 12634578316903510172, 1228039410348310529}, + }, + { + {9068020286559576826, 12618713895631873814, 11722393205397692351, 1086070536693193852, 17324321200170762004, 611028187223175838}, + {11651577700459617322, 11901409630642456359, 2085390425394188987, 490403321567849835, 14654293622476130790, 1298964209197946604}, + }, + { + {11322550018095596102, 3527572794553440421, 6339011792028948225, 5151642471735201045, 2959990528935484190, 9272589623358955444}, + {1016320821529073770, 16888052482282045242, 17688112620024597894, 3719928857894020285, 10396159054756858238, 3233119903385274118}, + }, + { + {15749902098907230753, 17763545669244090771, 9755900373517498480, 4320948179558902844, 10566924725356292516, 6116336473010794202}, + {15545737137436862310, 17240371706149670924, 11955643308605230982, 5932841340555536241, 15279500761826801442, 4179996491012197595}, + }, + { + {1552613943182547753, 10840747323421940067, 17328467336775183521, 6802521766845552195, 8626607143686909840, 540795511127208201}, + {15256703109378673438, 5812944466862532241, 6124501523506740441, 513175402986879460, 17434632082742815254, 16069187481501759225}, + }, + { + {8244487053073823419, 3868641351473260462, 2153712666785000554, 6957836165836180397, 500618765615109373, 1238832243704171799}, + {9603490361093858122, 246830756783484378, 2787086006655910133, 3907320948968255488, 14281263422468298103, 939723834433893649}, + }, + { + {6284765599251061063, 16534676857694838737, 3061690289969396130, 9626162384711348108, 1365881874432943624, 14727198041537453743}, + {8889264123676562961, 9777083175236297205, 13215028356698003407, 6986347484245421817, 11678122634649892302, 2435055587926500790}, + }, + { + {10396608653122814276, 17008484250005639146, 6318409447149262851, 7802099541170520164, 5574615603329953919, 16385780123891961969}, + {11134920568042011673, 12640687912091679512, 1146490453403655245, 3102249330058753539, 4095988337115400384, 17335158718433609549}, + }, + { + {12864499821393802475, 11788119049228790088, 977799416909835541, 15499421488379367188, 163390536177699522, 6804786504683418696}, + {3095872826752058595, 7223570057465222827, 1387121623948247335, 15122489364022134171, 10885423363329551545, 6434450333953245952}, + }, + { + {6653769292986613967, 9168736013794357965, 2104630911670700434, 8244457909216763431, 13703714178493743166, 8218306853052367309}, + {7189028979195471657, 5692750993768367394, 6844269123871604359, 17538650433906843042, 2579405218304322009, 2297663885759252861}, + }, + { + {12692054479125812992, 4320705081611888724, 14008964009638233826, 5334393314224233638, 2696459947028270454, 8328775412419649518}, + {5889525878366957250, 11336536538831724301, 12024875252935715642, 3494686190602179160, 9253138142565030267, 3528435954014636439}, + }, + { + {12648684265556130294, 2074783917548245950, 8308495191421783004, 15790318216073206594, 387051048726917672, 10990928722025444053}, + {15969688555016198304, 13762652978883154272, 12850841387412245400, 4825302074606748639, 2432583894467418376, 9326934178392716656}, + }, + }, + { + { + {18031089708973353209, 2245200960251079511, 480259352579296652, 5296730028561240923, 13672097544022918942, 12074013283516969918}, + {695570325720907777, 12417118176840300328, 11125216762475259777, 7694756262905475485, 6389856663806076935, 2023651462558938155}, + }, + { + {3716913865293623832, 9519939044782302522, 1190311626040433621, 4122386088785812252, 9998628051763276281, 6762269968937642429}, + {9861199249890354064, 1243120329240608977, 12074892082479307233, 11448174216179350137, 16878357486848010894, 14263124486707469927}, + }, + { + {4032144724607143660, 17323710612966320098, 4113668299203613008, 17685219225377287708, 13802533048264874636, 2291580023602316722}, + {5991918412653581128, 9413531453038680232, 12039010584036849554, 12779724028748234268, 9334132880061582927, 854018423284649885}, + }, + { + {4279036817315949205, 10908936013777057682, 5459140224800461056, 5336329855941119274, 13817174543987505002, 5803329503585048266}, + {3098013773573646382, 794466548882446711, 10937734087173941890, 10649767122328016589, 672512432710857443, 4439506334562330966}, + }, + { + {6150189972540442038, 17499024099306121191, 973920649937779980, 10819201450198182582, 14435306386254208142, 15898445937302462823}, + {17016479119212840445, 1987134867235671218, 3749994341137487979, 15521454315121012289, 12198185585065236535, 11161746347726704041}, + }, + { + {4108277248035082323, 4763145889189955538, 4083190563033592079, 13055163363599987027, 5746298306966204683, 895046093136418450}, + {4049236010637090060, 13099192881343834296, 8562023198967118756, 13994928855290033576, 12876191625337022672, 15993047528545202523}, + }, + { + {9330745605186235732, 4222579288142143178, 15252637539981899624, 7567380934463081549, 12741264148440889833, 15828019440897091920}, + {12723327006361657486, 4018078838231227180, 2560766106207278510, 13929068044020554063, 4759749660422617144, 1918410964088436476}, + }, + { + {1401229371513852474, 3725211280317699620, 15262967864528722679, 8998318469575212442, 14884830350906617811, 1500695608507126549}, + {629292347007891015, 4795086203008477332, 14482270326941440934, 17180742059572498031, 14991047340345822048, 7320414524005582285}, + }, + { + {3761423041074020566, 9183947159053999516, 17327960252130032123, 17936746435648093112, 4957874135698491906, 18381419405600408140}, + {2021552462092061162, 18293561973713757720, 807095291604235614, 10694367035762253443, 12210621028072312159, 14157551998029009312}, + }, + { + {8253770234288769934, 1748567047436239326, 15113806840556405352, 9849305728745472726, 9352106351313265444, 12676746928135649012}, + {15910355313240486455, 18316120463051771221, 15406553262270712153, 14120304384949032181, 10235649054584170863, 9663403668634321464}, + }, + { + {17566890036357409279, 8153035355283482148, 13497394635071743235, 9324980713264281675, 1855752933438317130, 17353271655839803714}, + {16210618120406652642, 1994646251130732955, 5626798068584404507, 5598549692563786678, 13865783001414878683, 14643387061407936303}, + }, + { + {6501357512501439891, 12176708815869008686, 11994352389570659317, 16086293893515238232, 6781571500932791296, 7749985836495590529}, + {7267769773480576098, 10519122498445425561, 12426530300337493483, 16904464207183051533, 9655317422890141240, 9006359300493534956}, + }, + { + {2379896081555791674, 7529087855981939465, 17515505484370387645, 11992060160533269066, 9874426908749159085, 9612679919749306188}, + {8727002423244992491, 11651910302226593854, 14317531382092040616, 7148921073820945054, 11509981879876620492, 241425876025527115}, + }, + { + {3957931629992459039, 14626193761179440029, 8968065435170182499, 18306857838363825356, 15388760608247994094, 7556220454574081940}, + {2830354800601290284, 6007093254955226710, 5776847166084925815, 17411399255750975735, 12948871637122999099, 10619688187202777033}, + }, + { + {18019620613881262245, 8668018235864297559, 5360445581416845868, 541567173296101055, 17792105755090691444, 11386151880811930327}, + {14234180784132089596, 11582267640018556498, 13014702559444465145, 3629111073015327967, 14739462952187775393, 10310644470035819364}, + }, + }, + { + { + {17403833916326762122, 9740094979480827357, 14548670989847645635, 15707508983563938391, 17654070414772907819, 7410646283891180823}, + {12088151802847404486, 13751887120986972745, 7133572866312957805, 6984144881486426141, 11478362218013196569, 397100930473218000}, + }, + { + {3572843614659695767, 13917566193783723224, 10106991008395751890, 14776064316406512486, 3973284575540205963, 1393548331195253411}, + {17728418700244338613, 3569943135321046585, 15310934114440659327, 7534966422523126315, 6695235484066733707, 10654160843179249647}, + }, + { + {3916524477947621683, 11443354393618774115, 11759119305556384367, 5213174624675660124, 7949463549546931828, 12092151641941435863}, + {62263562580411942, 12003780754220372116, 17593048334196024065, 1486928429974104945, 2382231722092886579, 2435498065565847060}, + }, + { + {12823154059116108213, 7988070353263431872, 5238951896699939370, 8132043978344570215, 9775088878106588256, 1118856390259997431}, + {18065172735230934036, 16325872707906562424, 13000039721574339202, 4312637592102231069, 4902470028754124204, 4272784360331042739}, + }, + { + {6433126302697049134, 14546898608004289942, 5143458349243895500, 2287546739351655153, 15996486027454642710, 8035174736863426329}, + {18381568106804023303, 503934132851985517, 5955511571426124170, 11588909349656865672, 2539783010592793715, 2517368635804605002}, + }, + { + {9688220347159635445, 3779168584047736134, 3386170765747188013, 10056695776861610791, 4230378171552673912, 13380959223891516403}, + {6821607274732022337, 8369692960524296435, 17556137452703259897, 9913246146396765840, 18385056826905781741, 595789229862790596}, + }, + { + {3376198520685928255, 11401697177155390480, 3837907196036866447, 7783605697094735953, 6911185458281008352, 16661582556490022446}, + {8898449499666876128, 12720029146151254358, 9180900453839682688, 16904557421585200609, 3231736335575648393, 13582984509377915948}, + }, + { + {6335991962752687896, 13799946527490837369, 12932853903574384992, 15301891419692833364, 7117580415677557079, 1638243357400401907}, + {12691541233696549250, 13069535028987414972, 1561175855442316177, 15953947983175737946, 17433282081462277288, 17805588449174971002}, + }, + { + {14830787803333713689, 11568262452331360318, 15414418121287856547, 291893575140657361, 8537715289723658891, 895041535012667546}, + {8735575073330490257, 7904711333758081192, 7705478766063086839, 14966128571780877610, 510498342305674002, 5375842717792934507}, + }, + { + {14017553865950425970, 3203585385790093320, 5960504993013900991, 14499792127339543400, 1042520134310564369, 9007730864681746336}, + {8155955287049316865, 1168268403444813838, 8223462980864298646, 7046058388874344827, 3806799754540117714, 14310126916845550569}, + }, + { + {18101015319769141333, 10981175585883985115, 11076843211911188635, 1865376526114106685, 7691555534771124483, 12825758162850881889}, + {12705759021631065468, 13425295730593551151, 2454066834990145158, 7398456861539482216, 17965437387228755239, 4549246519638273011}, + }, + { + {3564216727206350471, 11502367821276581491, 10888792934596534614, 3218935969765398418, 12592775041500777408, 11647588572015935744}, + {2922640897322707689, 8613211193560218045, 2230968453901036138, 14376635144218060540, 16773708514752577950, 17553690068355938998}, + }, + { + {12898296153065645455, 16720692735856066113, 327172655540413761, 13227218237345565511, 8519416956666328535, 9006180558080542517}, + {1264713729050345984, 9103896317460059276, 10413898570640954633, 3676401446977680326, 2935706012419574846, 9423939538748482172}, + }, + { + {2350781039643192469, 1693506343823609927, 11077706501162430667, 16417164483905858926, 13333764386693653370, 12097153330368571478}, + {10940849199388401790, 10597622934633620124, 4717517384091986088, 2104650762579463668, 9840374844871408095, 3483317510992532499}, + }, + { + {4767861261398259198, 15300499894768898507, 8688456959068450491, 16604170046623753993, 38066602101631568, 8293371963850926780}, + {17963446985501477796, 18444654321008564037, 11760177315245860872, 1435879756649854235, 12050871655191687758, 17344630493039043282}, + }, + }, + { + { + {3096485884016777148, 12376984002139145052, 5480443619638874966, 10095208486451434692, 3492940022953765146, 15299835252568625902}, + {6007593829256808804, 9692621867284256874, 13254638193058937432, 11707277530365540634, 16923342671634580125, 10732664863951753047}, + }, + { + {13872582197972895881, 17193014938795396512, 15971767134700759136, 131681455406226309, 15729877667343662624, 15250608391374424092}, + {6602138623471383700, 7643740135412054049, 17664951607321499035, 14599694205978771523, 8340737952520919285, 10584728957567182276}, + }, + { + {4029925504600209836, 9230486924650579139, 12709630435517017856, 16752856913747515048, 16091176512252055807, 5654615991864890349}, + {16213912518103095615, 17398694063688948608, 6470301373189861265, 12049558432878948403, 15731102283993311220, 1974808235304593120}, + }, + { + {4216082854210318654, 13783625863031842952, 14228148352427104722, 798223135284158372, 17371302655925227458, 3868945640945033607}, + {14496156719528803963, 835017877332649412, 15738356549194558199, 11268806386543436865, 1609600006680937174, 15189642421218057250}, + }, + { + {2100911419510810891, 11709730967811792326, 11070968852465741080, 15167667469791505342, 6990446430502772064, 2979739266982579384}, + {9729924531656485522, 14538459181363709770, 8953107760739874488, 15399265283602391297, 2640851218253403446, 397493120169971392}, + }, + { + {15302726863134446614, 13492823216891695902, 1527459733416593466, 3780183339959616960, 646805679119326182, 3572065085993834296}, + {2086050242579936958, 16097128196674610398, 11110917184928300297, 15215051174675736281, 8638996858467536364, 17498051884481561986}, + }, + { + {7442054194398722761, 5899037616301380264, 3602141627092495462, 12455087214158437405, 3316146807961356474, 1301937084617765443}, + {10089073892535620144, 14190065028184329721, 1808236899842351791, 4533062878686621914, 9993862131126637828, 2297009856133766352}, + }, + { + {16801618217516611581, 12059439895460656350, 8598727314831164546, 9586649536512297470, 10941296402181826520, 18191582771052788270}, + {500755738669776861, 12757213489859603192, 5140871938904556861, 9617812594256568652, 14076395917678039824, 9994140370794675736}, + }, + { + {5850038450443732235, 6375066279442420119, 15818683872880571739, 723472722199022174, 9333015052679795537, 16719493839402031559}, + {10024247267249865137, 5868800923297915890, 8041157937570474814, 7928686841256858707, 3370105934450681139, 17883122805284898817}, + }, + { + {5382144947237128088, 1043006451545558226, 1681467077957939654, 9517495454378300520, 7036177533948513894, 13161967355521737889}, + {12219093509482945494, 7442193295382785217, 277712888488640722, 13947546222291113300, 12611485840092686485, 9710833655025677113}, + }, + { + {12502549552167234190, 8232125533311903390, 839854118279680892, 9485775732822833984, 17663390734822952749, 9394764657882708830}, + {9000572432647298775, 6908017511163909222, 6513180860770299323, 1139498172110369417, 14568474154258358741, 5050171222169492187}, + }, + { + {3993332219625203427, 16865359864205374644, 18194512585980505134, 9613014347311695262, 16860790576951889934, 15221161996871384983}, + {15637827171909035878, 12174768900796615919, 10654832940369855667, 2582700277462133737, 6776356767890276075, 15022166989559684534}, + }, + { + {10674226674222713381, 6640126227278302401, 5685415511245921812, 18111307322717025760, 17086035813631913574, 15847356748945327676}, + {15174476977121907079, 17856987969624827110, 16167616169413150302, 1944283930257068430, 2453038170129818707, 1469204933482392249}, + }, + { + {18275102898719666599, 12983079761412852970, 8388106129782060896, 10209355387576245223, 14538158393256278017, 7560687135426084382}, + {10553905131472339745, 11398173317153206213, 13617408055623208259, 11532011743299529667, 11538247191420015587, 5623160693645531170}, + }, + { + {8940662681574827513, 18164959107927468123, 18046552638532109884, 14155453048592004567, 5584625548584318353, 4723581324777545689}, + {11184722677308218083, 3999406699031629777, 4988145712425592916, 12203913929517294737, 9784288473101397226, 128198380995960707}, + }, + }, + { + { + {3863173275874957588, 7607368433346418538, 3446917342117543093, 3102805528911016504, 5796298790620582886, 4845029410873700374}, + {3364570708230969314, 4211843997911050357, 955735840518088540, 4382952718350579495, 11151776336025623039, 3248067064518007812}, + }, + { + {10979154959051140455, 17057489977844809380, 4636877136932368853, 13173423356700842378, 6427295314745268682, 16166484199425823600}, + {13947498680098198587, 9565058221523432140, 6724059640029046123, 2606510272316346451, 14817173045790080526, 17921662463284944192}, + }, + { + {8834547168849238776, 12415387183251468175, 1535769784386765604, 1355498814697642747, 11825072756645717040, 10331067826681906891}, + {8890584623925299707, 550918406340532812, 7338316217644779781, 17543638401057055929, 4365113997542215090, 2411169740153090294}, + }, + { + {10112129279069371496, 11405549101446425766, 12461696963021780427, 1134289511017689360, 9417819820453596293, 7597522379563535727}, + {2074398209324320962, 961715655667925180, 5962000230359126827, 8547804373478236252, 13432658671807283680, 9718385789307084154}, + }, + { + {16080785183875764467, 4017135721666879597, 8974124072605099690, 6665445735103434589, 14756638402029436542, 4331542523722303717}, + {1702503223444440164, 14189603650236390274, 971810312712682183, 8049986845378060800, 7330150922533173899, 16296166314284869572}, + }, + { + {9526769721404560092, 11775998161420767448, 16356632323651128085, 8008696501724706815, 6341629823262057063, 8523528728189280635}, + {18166074208498206728, 2229400479403638901, 5403004557542136690, 8487804674759640484, 3159160659687043477, 5700251865341103945}, + }, + { + {16822522037639219170, 3266418131057286997, 16472577174486956897, 15819423733871391528, 17594326634646650876, 4931927040440301796}, + {999336285551238701, 3401843156036868997, 11496979962939320412, 15550337525570953734, 15845745790852081340, 3342897350949791243}, + }, + { + {5808162251213383712, 18156856773531164983, 1937517322940695286, 11625411969327328360, 9824825636580723903, 12658592751635829899}, + {10492457110340784150, 15080267389153378243, 2728353556631119200, 14320292562386508753, 13490107143925758180, 6274827431709058227}, + }, + { + {14860895913867154489, 10080650032026459432, 12807414385133112117, 847324989654678215, 13613905648479118356, 12400016944146011293}, + {8776013302541032016, 9925887754260000908, 10894174981766535805, 15297900474855663929, 7442689517452234839, 171834335047382038}, + }, + { + {9117588627465418641, 11168331531349603535, 6924358652074850811, 10618700262994212668, 4103627941911888613, 15694811739383802290}, + {9844066545684783246, 18166608448724723735, 15930623463970128522, 16725459693529035690, 2783599048829322892, 441632469097465516}, + }, + { + {499123733301815599, 16274441320546608446, 8669188578438459973, 14214738178860124031, 12485272536092776327, 6746102886227516887}, + {3968023548712012438, 9154853401879925537, 13974983377028591333, 10516947431089663290, 933442150807932151, 1500788281533481018}, + }, + { + {4586047615512747332, 2505846476262500922, 3826876063100299053, 15762019359435942125, 11799323381173767446, 3568265576213353380}, + {12738065238480311575, 4804303397040398585, 6942032723664133680, 14301007503455957988, 184861059208060790, 2126913780868224063}, + }, + { + {1985910238562893230, 14542760065878644523, 16833470122497892859, 6947656477689970299, 16592512648364063018, 6357361689814456051}, + {13200391207691971905, 2310116023035377028, 5508896705935951006, 10187259410896817897, 3059013399060322780, 5209073312162680293}, + }, + { + {2550642766496181772, 11278535109027313473, 3879516477095166631, 5651059749761693924, 6360530625026542850, 8678055154702639383}, + {9895197927639380575, 10283962157020530930, 15939637088764924497, 8554801996782490495, 7371475446643610469, 3583344374097517208}, + }, + { + {17371412619585132655, 4718601666750293258, 15975408209741840969, 7108377055663708997, 17338928230506045982, 14627100588346057122}, + {13528723931279394499, 12515391311856549312, 14781282577544396450, 7264023353215685261, 3375932768360087636, 13881393850792083407}, + }, + }, + { + { + {1721448973177947457, 17542277325179447353, 17937558459976980552, 11205040461324106686, 51740205411633326, 17489989809778293662}, + {15829483165674242202, 2621026715167601087, 12151982072969161717, 14118259735069082779, 16359059099859035748, 2645875010407964904}, + }, + { + {13044315376543176345, 3791987176391770853, 7257315148468660254, 7615181808332653921, 34885173241256032, 13076418563936506107}, + {2024041865836120065, 343217496537691538, 6758070881563975561, 12527712552092021226, 9130227670558521871, 15869156873791479522}, + }, + { + {16624820076559004073, 3290961180687832086, 1505111348777534793, 15451932960818385994, 4885700112405367154, 502473235663078197}, + {9023344755595914819, 1119495374695090045, 13125353132125365621, 4582328460786968359, 13153243053399805058, 7243196921351431637}, + }, + { + {16660609005075089706, 11456541224374281812, 13813535856291553219, 14877518040804369021, 15861475260704681751, 3089740386917625556}, + {5892458763715639755, 15267181778302530854, 3988849050539397794, 10518710330883699493, 17431760984824214042, 12598607198625858948}, + }, + { + {7886366245642682083, 10962884476823348220, 6709711326774074595, 4572918043062220701, 12755952895112236674, 4061495514143300363}, + {7306556391215449886, 9599795224615892204, 459890930081394149, 13715832153540946078, 14440301411429777271, 16495857007705672763}, + }, + { + {265852797146271341, 11386341344328950606, 2823304281998980676, 3128543525090347743, 9711211560804927151, 11699179803002767366}, + {913811348561539832, 4079387039854771378, 5786553996132212662, 4783085098376699354, 11850032584026193104, 2507234732008509693}, + }, + { + {1681054977850769931, 14671156085086914970, 16232677545813708023, 10037013912612964578, 12655886518994362601, 17930493853619313277}, + {4261930640340402336, 16291971428751843912, 14124714297167598319, 7116061430830749554, 5140259185669271312, 9521500824814628533}, + }, + { + {2133204265371102168, 7738424860559779443, 9132973083464203079, 3624293757540177213, 16855385106148764582, 2981904660819867362}, + {2221031423918751149, 12840489442672309770, 12668245131095936710, 2439831201753391314, 19103421409345804, 5682831538477921588}, + }, + { + {2740210992007145962, 10621702461750253547, 10508827636006320761, 8248704461968714321, 6168928611394207164, 14048196011297482761}, + {11562029679319191839, 10199382699007278950, 3360092486992146320, 1463128897560010163, 6976632107921480266, 2129873557666907110}, + }, + { + {1100325675403567262, 673625074442631877, 8514591637299607269, 2345202943752109744, 7167639158345336267, 17342690971659777406}, + {4862595967217912581, 156590070960043410, 1115171684358334313, 6101500075575877531, 4062560666972498140, 5927929705820198011}, + }, + { + {364176692174332883, 7738711573998977497, 3727117924922648734, 17488404453005608305, 8507877372628529188, 7821485339424482447}, + {3407079555113142839, 2821844621824294453, 7117735201903766861, 2746395978318799182, 16096929564195692367, 443983083263483317}, + }, + { + {9618959095759532752, 5009109919584887941, 13273663751866897132, 10020142088235002186, 8463814795688208512, 5854890718933975039}, + {549447413377699602, 13361664826453471360, 4381643613995465702, 11048937580044016933, 356464625333949552, 10426821157046820998}, + }, + { + {18186037674911124153, 9266904366881705693, 1746212978216662911, 16297025199546965112, 12372897714118201342, 8586503557066603618}, + {10659723169179230020, 8331742669536916843, 17458121139259655844, 3918785045029490546, 10947551116738566182, 9999088208920405141}, + }, + { + {8354650412119672244, 17175305374472306433, 2829972105586097490, 10426050169628830453, 17159563166759848715, 58591768570097984}, + {18406299714417692335, 12546352398212878156, 2495694500244923448, 12073608360379166377, 6610894508561660367, 11682997196017168294}, + }, + { + {3210207744299112648, 13875413666800710915, 11640078075030694173, 10454397255148356013, 17880871075693128223, 7359039635726487892}, + {4853115095464004720, 7976333879782734047, 7694722857965415540, 6036769361724001263, 14076311434771587877, 7283323370969754879}, + }, + }, + { + { + {2614353155557682937, 14058591604861440576, 8309144349698829255, 10106897547146685772, 183429285024450792, 7660674933291714098}, + {17722010084076500734, 2099112471522046187, 3527281458003781480, 14209273751181102104, 17230024122478409574, 10483334506136982748}, + }, + { + {6047132184189720819, 4426654828692160218, 4329633098905519796, 14236543825083707690, 14077477151979085718, 1291177900283865316}, + {12977722282683448473, 17497194838527230928, 5763750732808676924, 9844068727688186332, 650882686296875205, 16353023628194028517}, + }, + { + {3571331741751811067, 18233407145253967397, 2182689380490249825, 9862956875499357585, 4101378667203447553, 2434938326871008100}, + {4975383754309760613, 3934729624717234976, 18322513804399478400, 4995364561535811634, 4754224073033422626, 18130942841051642409}, + }, + { + {13897652105647445247, 15549865991927044469, 17587166399757083359, 645157568514571702, 756205085560500677, 14733833165754071077}, + {913239358738001609, 2071269782500914614, 17073597609159000389, 944355324501816969, 4767516640133819639, 7180502768526971577}, + }, + { + {11871454882320947778, 4076335602405372571, 4747500308730376335, 18397169244778911221, 7987453080975894942, 6950688158372586713}, + {17368720469534992117, 11740301568583332137, 15177273953729130117, 18421847781159349697, 505562344182069757, 3704550989049269178}, + }, + { + {11672240582589566888, 1108540908548515402, 3338717371374145046, 10460877846984614452, 9211584971186313940, 11952076760337213457}, + {7672641505116403277, 13764930264603220483, 3744578737514393421, 15724456999421097869, 13506821640767565708, 13538891648668593334}, + }, + { + {1050281222231361612, 8994982763868301024, 12355411974171252835, 11306931529620801092, 5865750322856587361, 15613850005955819172}, + {14398943333497272142, 15112832726445460775, 9983052759258731406, 16935356055040242837, 14203640081769534446, 9130644307291338833}, + }, + { + {4953908352693126534, 5062976277743240918, 16505639315575105155, 14534500310766348303, 17944736498552318640, 4792459954642443738}, + {18252334781095086320, 13063263503472794652, 13198172387261578292, 1616650596611064703, 15181924039569157445, 5150232158682339336}, + }, + { + {5624679813550782251, 2451770210293674414, 13240746159856752674, 903265396767255440, 11078214582152861563, 7261508578820008638}, + {9752563467317727618, 7386516386070528758, 14793037822648488271, 5090452706673272192, 15308894744012067286, 8130767753744452857}, + }, + { + {6918549675326654825, 8356548187098615599, 18110842889094676823, 3963339850475613373, 6987554242330845710, 2982471659740542895}, + {12669841747723635164, 12626688679931160789, 9018528450701894905, 9726597985776847011, 11318736602457760788, 14025138192598645150}, + }, + { + {17505324765173267460, 7096407019104498095, 15924951709972151945, 16257204011042132345, 4971672139719859625, 2321621670487320814}, + {17594404375116307560, 4647612677109579503, 3901300263702871151, 16326292626815115333, 6831256398102532757, 627750677080250535}, + }, + { + {18076088553817290385, 17349449293663683793, 11642446393364288036, 10122513438385611555, 16537537641493131433, 14156371894700831240}, + {10743408581678488725, 8483948758453680699, 12243160245743380209, 1500764398487579885, 13614004849488464930, 5994785415308094372}, + }, + { + {6122565183919808230, 1008209506550806598, 15249625726527344206, 5096898832984665512, 10958457055229538950, 14428643543814058899}, + {17024506398778167044, 1989641393139458938, 3538068469415906392, 7351031458262333307, 18232141335489091166, 101299571031811981}, + }, + { + {12540548462618170712, 208754347981855850, 5755714353878203428, 13810850252670464562, 2144696743162115760, 15602160948740024567}, + {18186995987441524090, 17284490982574717647, 6768470157308652643, 9315159601737265015, 15486248506383436092, 4135862452814063276}, + }, + { + {7062558030802288283, 4151046583133123194, 17296845417413488570, 2939642080257680057, 10681059010204949305, 5154176607283576645}, + {4961584994822815984, 6524971500046141586, 9968235534650293072, 14236553626523573525, 11581675440714217403, 10779043421926068031}, + }, + }, + { + { + {5704148093399535513, 1982201820910068915, 2015300701102890863, 4938678016782651685, 4225735698935095441, 380627551509963002}, + {12290756922107972790, 14689334170111259003, 17081591129898655804, 12725711463684644427, 14355859294197921899, 4833292303349912353}, + }, + { + {1199430367393420777, 7844876978855113240, 8362429417006246806, 18405301817567609597, 2010437614964189103, 15790163337826190044}, + {13172944002680008407, 7545247538771827356, 8799495964430321755, 1636508240176095806, 3688223623562214043, 5001180399862075810}, + }, + { + {9236682024243624347, 1097419180975135931, 16930071776861614326, 9425037863420681425, 1897777030645415141, 14923573308348753100}, + {9048832771935393542, 16495423457575818894, 14651297528469675829, 14681410364817210043, 6270262408162655998, 3202527036040014714}, + }, + { + {12148128553462546338, 14272886082678845161, 1998189262058231244, 3290638835546848685, 10974691513020291898, 11300741189288469923}, + {12102666221723151731, 15168969616238080084, 7571411875816772674, 6708095321534436923, 13842254475238776074, 11645310689961969980}, + }, + { + {15206355933923800488, 1526822957768928677, 18444342976893277734, 18290836660807940588, 14597401039689350006, 2191517853826363150}, + {6631276040465224272, 9608830307927194622, 13173894809175192722, 3447459865798044953, 7473450899969070648, 17538173612935114726}, + }, + { + {2545753328201935179, 1541411216554356934, 12430899315303981226, 16873953755863768968, 16122659417628515478, 11719197339014743998}, + {15840812009819945279, 5620933673682798071, 11726809338101868835, 10020394952939578101, 6417033277605415646, 1193962146484927818}, + }, + { + {12699385012539356648, 1074729856826138284, 11360834127412011973, 11614291784573969284, 4629063743007127923, 6826004983002907114}, + {5533842397602974776, 5380622214800401295, 8077909061924689270, 9153034190848608609, 6198536077171060590, 10840145921066532009}, + }, + { + {16250603474235152690, 753654051241256788, 2265085864511952533, 7827038858733068367, 4327850715387046187, 11399515242612634708}, + {10497059724291403883, 4688252136426618327, 18024770225850104963, 15437873549837467773, 8363336228498661948, 7727493073571533637}, + }, + { + {12358979317647022406, 2405166324543341567, 1131516171615394739, 5450907798304034460, 6666818116269349649, 5855256214551082397}, + {10663129043987590669, 4887396919880469663, 2298289197437656441, 5676069638451158212, 11906248580355770142, 9562940725527931031}, + }, + { + {14844739915543480162, 13246961953132764518, 15443922107017863339, 17591911221252177558, 14809121152752475646, 14938006221572424065}, + {18293125953571441775, 3365272595752907779, 17552372285854513998, 17235054008682833997, 8690722712832570147, 13050282119073535772}, + }, + { + {15776540266747032014, 14852977882697304855, 12442551787887075800, 16222199462276877546, 1348770173344153190, 18330160582494566789}, + {4685257266073614758, 17629760902250811736, 1099686978395867610, 5720148750089389598, 8752939799218942652, 12653117413452417188}, + }, + { + {1928524914772854786, 8132034417591551586, 7951059682269625334, 2812108933072612507, 1596610641421367938, 3496321797212562056}, + {9864359450003079695, 13827098275898780935, 7851275574239236550, 148489084772098078, 14414610826237061088, 6221005392878728474}, + }, + { + {10231841021413400882, 6416526412762119350, 428961125681723016, 5443671154306564465, 6515481304725718135, 7472109697629360236}, + {4053824519380499109, 9856627631912166862, 8808287978132340097, 3494734447997642012, 13122490218403354627, 1586718502175528539}, + }, + { + {6260407175309061893, 14850337727743664854, 15585408845772003227, 7077264422349275731, 8392418541009408758, 443622451095627013}, + {11824794477049100598, 12322457178558060770, 7174368023614892223, 18169994008863893305, 1353822949072228703, 10638226122523854578}, + }, + { + {4765938320248439052, 8363686885434148155, 11304264598901869535, 14452099896297485497, 14813989444275511579, 11997113422384802221}, + {6448271325447843219, 636006309719920128, 9686816723717740028, 9631232081121088634, 8102244673875044160, 3189426959171768223}, + }, + }, + { + { + {2463818565041698203, 8022820688029070207, 4888356879458026368, 11629790905165524278, 16555714206595898330, 13627886481857856688}, + {16335710071193906987, 6321854959216334024, 13113326664056241925, 11554351464078489040, 794805091959363175, 12545188758454015719}, + }, + { + {156113733862257116, 12812294601068672576, 3563267346091688314, 3001452181277921772, 15607483360571672694, 17299258115284201469}, + {981410215374975479, 10842895849914354733, 4019626280262303535, 3964525883133678208, 11449335357635141837, 7447803780571143247}, + }, + { + {3449274165036362414, 4918853138124055081, 1547983020534099669, 8313761980678241388, 12236549001847065606, 8919544181940646346}, + {7959615711717924349, 1998441664630865730, 15662251542753222396, 878616613737147225, 10921558209848383451, 14643587960617282503}, + }, + { + {10030195466513813736, 7264007409425871486, 13572379319575545436, 5989173427119562900, 9714898089014614002, 16719526588489259967}, + {14134732214629887880, 12965589590960717029, 12056814709100630613, 13827802528787563910, 2927559054475015091, 12475732844535894680}, + }, + { + {14808325747134274433, 8057826914079617564, 5525954727355605916, 5290214223388727378, 1085748056393626543, 12252253028550111114}, + {5922977969674250041, 2448526450681685329, 2926522479362225384, 13034339434060413522, 14285788618705740240, 14224616444852968120}, + }, + { + {14468289541178842512, 12201944999920129159, 12698876919717580942, 6936204399773360929, 8336457280891506998, 14054191262205054108}, + {7985103068695070111, 11634744794544986495, 3492551865016082791, 12866518520735982455, 12992402881058061256, 5203085761453373334}, + }, + { + {2744232347627720169, 13383652591074198984, 11038998560267305871, 13459807200627641401, 4723235801697844775, 6052210961441690931}, + {8015232138170246714, 12079252961549472414, 13192819517464270060, 14584389580251977550, 17833236661373150481, 3761490117360962633}, + }, + { + {10639242284018919836, 15769134811853365977, 2764713995390457156, 2939983068560561484, 7744415034623844491, 9862924824634167441}, + {5812124348561302205, 16914325820321413839, 4446235265737737774, 5136338484784530512, 467458589733891477, 2630304324972701607}, + }, + { + {6832719395023449163, 2033508612951663629, 3511592613860178255, 981472589675863291, 12626082291731102761, 966591436305020179}, + {13733382109710953302, 1434291421752039220, 17971214388752092375, 7561304859414785821, 17294534194238094519, 6834714320288858574}, + }, + { + {2420226340788279821, 12053022832331502898, 15086319486305540754, 14384436305396163060, 7162949585624069622, 2339283057144054658}, + {16555809395586932014, 16575909670975005732, 12006449181862665382, 10896691971361895576, 3873458976101713782, 4179351799128456450}, + }, + { + {4772589731323745937, 17591537228186096278, 7733169684400774683, 7943142157971243776, 2600580496982037708, 12240688438179106242}, + {1682995002150080423, 8105112813163255258, 14679869015350748762, 10615354182892733709, 1101044368915518409, 5335546289827620815}, + }, + { + {2820596099556415173, 2594358308517525622, 3833328115443141899, 1838617013547370473, 10703662474010707679, 6132526521387027976}, + {2504146752328209083, 10365161708998346132, 18378027908391206958, 5944023165464852345, 17106626712229962048, 8325422024401372832}, + }, + { + {11789842430665850017, 6421202279499314143, 11573596254910462066, 4537895385523862063, 4377931158374724860, 12552031527611086863}, + {15504318552571625652, 3707368681645487345, 15001785752614913702, 11705782900778611709, 11949053603484681481, 18195922704834165941}, + }, + { + {15421742936087622130, 10159987354101918308, 5370406297439414101, 18048469588184356347, 15077974257262174351, 4171587624627671421}, + {14084050992809485269, 6539059918771085671, 1374789379818515594, 3838078018577862594, 17679614135822761449, 15474878493731691411}, + }, + { + {12693451959622797980, 13290565128275588854, 7361758586005248557, 16075093967835316398, 7087112768596951545, 11543822053453504948}, + {5902482308820286139, 7353185101342606440, 4571190498315407690, 7730145317036018296, 3643250411451134315, 10481041494035321174}, + }, + }, + { + { + {11379922315523310195, 6620262071143097557, 10733110307157784360, 2455420994718286142, 4941160012966559203, 12036389373766931776}, + {2004451758092625142, 4014199760272071819, 15292911034143935666, 17687179513796035433, 1569516718335592017, 12444236748783362218}, + }, + { + {1200397030012372876, 6457491138111915023, 11531993623745349026, 17899861472742612738, 14124733664835562044, 10645792077218180283}, + {13099261645024141037, 10440696952297433984, 1918236772154249849, 9506923430535157418, 17499444799293611002, 1509670397443280998}, + }, + { + {4465757364835631722, 10965936787556583155, 14540946401148103030, 4584421538084028348, 13594362137297692686, 8844279558284617491}, + {5111359204171112465, 12790060720198863411, 4014742787506192452, 6614930013636115085, 11730197034873324635, 8776100629808369100}, + }, + { + {3790258798970833100, 15996801276739271696, 3464398440425134039, 15326814870706418920, 14448492169636125498, 3231159483392005876}, + {3705423779579747953, 11372348237300277088, 8069222225331107027, 2700528497189769719, 13555552327194442702, 410730686168183967}, + }, + { + {6826832086550914049, 17351671830508265713, 10661972945889099645, 12894337943034505815, 9813078142757356629, 782908000516993322}, + {12769245099971286736, 4882620828121265763, 9488137564983431475, 12539028776281802034, 14846786398874564444, 9073776363026222135}, + }, + { + {11362886301924370650, 6443575479653887522, 351000858570459150, 915347620832419895, 12517886863027987115, 12886465789602176705}, + {13102667374276139057, 6893636638757694468, 4158135635197259073, 17014006099419646155, 2886247550772729453, 14342905125501493077}, + }, + { + {3750785743865695174, 16184496891679274640, 4508484768462328620, 12569830003082072446, 4338678566828661049, 15769546354414324906}, + {3809488443136531987, 3433818606509958865, 2864343169319087118, 3035827594190654155, 4283767959137064887, 1597329211670760111}, + }, + { + {6735976130349257678, 16303412525749538849, 16400428130291037330, 3771855351047356253, 8461011934077951901, 9862709568546362072}, + {6948691434839126085, 15094238067058818238, 11970945255041716883, 8357516122660935053, 11312726144884161679, 13888868066934144152}, + }, + { + {8552971979382238094, 14893844762756755755, 15247853217772454969, 7990879378400788049, 1337495408598927433, 4927592820371154426}, + {11318355400818989979, 14034508604918932131, 850449205422148972, 8707631597140933770, 9005290700503315458, 11206135773816655778}, + }, + { + {11717560420962665146, 16036488489927426530, 1073385780093662141, 5605091585524991500, 11567805488139392367, 6960929895827554242}, + {3185029102977538829, 2880896879639691851, 3758583862703327606, 2607528607094689740, 6140415866307855875, 12833322601936456641}, + }, + { + {2487173712779352607, 4163293746622453413, 15225064953453124837, 4745691426593935280, 15916414889134198240, 1934042257062059048}, + {6574682739913942887, 13440408571236322143, 18076013925783648472, 6693474681185919321, 6987178681680099301, 8824321410010451056}, + }, + { + {663297042995494661, 14801753841371941556, 8727539546491979133, 232708169718659428, 1190547424093432076, 10001731533557757135}, + {10564965587834524294, 10882077754824824235, 18044231443793420173, 16047844267187742404, 15237359807179541598, 12335098732141186268}, + }, + { + {4522044229514984187, 12692311112090809521, 5174544620399081630, 15624956610993361290, 17499804740829372070, 14159780115181988400}, + {6980473429664507297, 16919669078262269987, 2419328464610134620, 7279187746594254030, 12270975978407595756, 12652404087215952443}, + }, + { + {3097250801852684058, 7529383389734329429, 8943150468940937789, 8684872219957364714, 1510282680805138697, 1736664582387906156}, + {8559488977052206069, 5218002957160199868, 16129363866527754916, 3419381639187625321, 7406388656339306496, 733912006552345760}, + }, + { + {5051832488018112348, 2845773093799720531, 4269756063941307164, 11932175332287301151, 15864531947553285757, 6880993309378786007}, + {17221326993540037993, 7339003944245759506, 1709954257215636952, 3058564762936670215, 1381289108584710274, 10818101921467782182}, + }, + }, + { + { + {11909603028098105071, 1433304974993906210, 8596793362628962403, 17840341647275356595, 17335910880809706217, 14496938254816120063}, + {9718444168237729680, 97136308719864699, 385208539784578137, 3982687391919868715, 16704940770194925306, 549720452261507487}, + }, + { + {2694843761758977903, 18124804948268586954, 3810124062407334761, 815390255307793990, 14032033031902943311, 4699208123402406172}, + {12100023268807134280, 12092656330344745210, 13856900984407365162, 10791000625265461807, 10537408988523295901, 1213148431505044944}, + }, + { + {5564129609030186650, 661399315027471445, 6227812982018710887, 12211259814675657270, 12640363533246661095, 4250662369482871640}, + {13995602364293455479, 12559572490607005689, 4555992709769317618, 10656755099067169486, 5466266601354190684, 18303706146826818496}, + }, + { + {15368142834518355591, 387732588739217687, 17906815839192787578, 2458368923948318521, 1213186515140052771, 18119735955342268000}, + {1464255699774805313, 15706302797823747047, 11515240128938376809, 3345743489851301863, 4182988989553146063, 5822101833208111449}, + }, + { + {16987042022725647034, 319232815210787283, 4458381292742179195, 17988503646508966180, 11158143875082860346, 11504863432259964894}, + {1973834314893704871, 17030914264131630067, 4911299812763134293, 5430690367398180217, 2557726880455581905, 12434521041073812213}, + }, + { + {545462916220339990, 3584698686781184519, 5328421879230100723, 366775970831948805, 4024338021516994343, 1533516434617926006}, + {15759296396039088968, 1165424695035321437, 4856582709870659258, 12896943835426779442, 14754955776815298193, 410556923033083573}, + }, + { + {4186087526910663586, 6165136419336713660, 12136818299454961122, 3405693470185967536, 3648773103438697505, 6515981208652058927}, + {3752988438485155801, 16815658448321902855, 2796662867929732032, 5824574038203643621, 9332750850995495618, 14417469253846871647}, + }, + { + {5370314366938532279, 9877969370138171231, 13966511470431609240, 15877758322148217369, 773982613756465354, 2790333076733361805}, + {15260338585394597865, 6297024182872652719, 12048909513493364581, 12444492358042311467, 4022686688297847278, 17410241858326791474}, + }, + { + {3482292231700676468, 8908690623157180028, 16288460904525269506, 5959395600638297217, 360588989624002344, 4420646335976102398}, + {15326491091968545497, 9102573345895719113, 11981331366781021439, 11438298421566869030, 11986315544156148772, 9586987921414184090}, + }, + { + {12658775917959337138, 7321726641436322889, 8904085691599899669, 6181173455344381785, 16990799257112339793, 6589370949402051563}, + {152076730697639797, 6292489939246750855, 2631558763335345129, 2400788177969090289, 3082489011322585694, 5460755211051411481}, + }, + { + {16026468164120587616, 3890624441511373656, 13608676030619425331, 10074131329717815957, 10336173319596529425, 15010101088827254127}, + {16066548767291218138, 346765727064293714, 3034008750782532770, 10634970483280908770, 11696186401772501910, 992070167768548909}, + }, + { + {16700357690267037996, 2280486417700678036, 12292705505251502979, 17433319339816222360, 3180311752818744080, 12556842763675232270}, + {7431081179990995973, 11626745676061745617, 925792030195302151, 7573296302591880847, 7111534405851948348, 7418370979279348359}, + }, + { + {16126038235581718523, 4590472232521394945, 15667737325175661395, 3234185470951996453, 6433453928669282028, 15899702540931522631}, + {4961512606010997533, 7075023696164954837, 1926349877304076748, 15847449820251106944, 12103289522218620655, 11755646081940303532}, + }, + { + {2815793807577222685, 3974873120030374430, 14070231706868366483, 14914212937861260775, 11217571411566683403, 13488284407258074738}, + {2447044301855977709, 1991486381221843561, 10306272153518153979, 13012982641746076783, 7500759912363127296, 9368569895638129462}, + }, + { + {16633917127904484128, 766128895880122918, 12296015683476921956, 12780904198992336027, 1747119835730230715, 11648694124739687510}, + {6931300612490207931, 11673373686239852450, 18176687859595005370, 16590940298368519075, 10350216104129322491, 4313019598947936772}, + }, + }, + { + { + {18436559208253217538, 10052692439679361295, 13914661242043605922, 5303216763167780904, 10320619132458662262, 764916138455538204}, + {9742933872987685981, 10626539639975944361, 8938199719602528282, 3118400879731019025, 17486614403295685962, 8194019942137487488}, + }, + { + {16848715567479381646, 3965484758491433728, 17553116401134175918, 266130778949555493, 15612913147808127901, 2452271039599659592}, + {12112647027603191858, 9836632132933298138, 7150220004740389636, 6080952109208447401, 12794151692277391601, 11339774216918951773}, + }, + { + {15370271492241639789, 13865842581349159076, 14645993961035890521, 8096824553138062253, 17815019169532343171, 12197261930135611113}, + {13843017114364404011, 5010421400581829489, 17814230270064460774, 687861654752340118, 17009006702144007774, 10314843449915140883}, + }, + { + {2744318910620647716, 5603184151316605771, 11257624090959454283, 13185449267405233716, 13751271304022947910, 357227629545275976}, + {6629711137100856610, 2708216448052728946, 13226058796854087226, 1788986271084080906, 9168817775042008469, 11922427675226424552}, + }, + { + {14454843566511544351, 12858454059009483825, 6952579439068010126, 7733931976949613017, 2531905974818570751, 2340234299628817285}, + {4064406969820346920, 11776091497743820272, 8329625521872996607, 17793038299121088064, 8268289814329664881, 6179727598715947755}, + }, + { + {13248035145811273019, 7752115389537037710, 3783507151237115160, 7998022990884122769, 16933952266389620556, 9525578126304597588}, + {17660710021706978693, 7887275263336665238, 1823257268190340929, 16929028893372651088, 5606633925842000055, 17725594627635071001}, + }, + { + {10717942541841401668, 5062492223707666521, 2874099965260778327, 2111658619166071126, 11668640869427564697, 129797271043653095}, + {9692221446048485432, 1712242857382255473, 4838248139231811400, 4970058966083233108, 16360347161442205136, 3339445137046433520}, + }, + { + {11766141551615199913, 8685320933099257575, 12025130600585049936, 11062435310323182587, 10065203967214956664, 17179026247686360724}, + {973705476571001605, 12336450041607754348, 874536885921370264, 3620964755713794319, 3600247557571996978, 3539695373337548386}, + }, + { + {6671466056512719629, 16184392602500878537, 13956944166874842510, 3115630032774258951, 1843095648852176408, 8229461234479287588}, + {9459156799383170558, 575562900712226104, 1461784124210182226, 9743344326188849649, 8264467109834156287, 14855166366987863706}, + }, + { + {14443662408692449290, 7664862287740722890, 17649339370312940977, 2156776012545551339, 15768456150480100232, 14346672920916515716}, + {8113778989714113681, 15635297215600657635, 3026622243462570848, 9983527114455639519, 495493109210132335, 1825135321586189570}, + }, + { + {3948205964039691358, 9147407127214526584, 7561468478346924639, 10897363606469824992, 703934561704031911, 11244219452628483166}, + {9517458047229537628, 17195327556556691064, 15691063270835772767, 9438705527839014294, 9695368154409603795, 3649704513354366568}, + }, + { + {8298214822826346584, 16160788589831391317, 17819994725843440833, 1024306577659159521, 1852010738280183503, 16583513376689890736}, + {3373755007779392878, 15683692594403040997, 13166508057783939533, 11523709082285599828, 5437988652322971796, 18109256413139496795}, + }, + { + {12923777389997376805, 9977718769355025596, 13018161749708349740, 14360291996204235159, 9575337711644144758, 9974219793575670651}, + {10424562739975667006, 3563632038522075692, 3672552713411869989, 13884443527418224724, 6155373509257036382, 3207888628018922232}, + }, + { + {11930174348010923271, 1348949055337526798, 726415247102229584, 5055400198081198789, 11015209320490555612, 9833582750989675305}, + {9700597556714543589, 2992217892752165914, 13783701793319444227, 11374474240057387342, 10199414602968931098, 17127353744132587534}, + }, + { + {9563065141641954290, 14665066342222635705, 9884992491626869089, 5974715562776845322, 573036282426832215, 11499375779477883827}, + {3206285674430939161, 12354004793799927731, 5478655966737394286, 7263281183196607046, 8288729282303345591, 18029234498520921275}, + }, + }, + { + { + {2992157424964359003, 10438615318402196118, 255815347996375468, 4465802505310361450, 1438013292054608859, 2462444921683526793}, + {6885574398590377060, 1301114469257389079, 2687344453450416312, 14090513069242834662, 17764663004285116999, 8889109452874431564}, + }, + { + {3947928161712886286, 6283937438203374232, 1924037281168554481, 16154924465225066172, 1172742291383405274, 4266561696255722724}, + {7000612604942850536, 7659188878730526073, 17637356804126820843, 16975720578569227612, 4896458553166174167, 2686308470754372836}, + }, + { + {9432182594949608034, 7182179915820505304, 7710800442508848674, 13288492478214648407, 12461818323948657464, 5572387091938177662}, + {277315655080978560, 8486149812061624297, 17273407137514060442, 15942854874670749371, 11686164309797544370, 5909985884404360345}, + }, + { + {16367186110059925561, 346226761199691539, 11243569651429838414, 15633495530019237469, 16343973985917329298, 10134611081598971563}, + {15093301170509003037, 1008194724710082237, 3218608412640277159, 7159496834485052730, 10712235151472906025, 4198145441405858657}, + }, + { + {5131609251652718207, 86776758092331267, 11360734888319180911, 3469913385423048534, 18100684383471212679, 325475210458359248}, + {3689757001346201628, 1730954327037278569, 3788507424874318707, 10512008196941777061, 11932764492105480931, 8036637367681551485}, + }, + { + {16591185232690243721, 6455242289394723746, 6695217017042848759, 4941824958829892109, 10112600357660465319, 18308711553066796539}, + {8438656634392593423, 4958573399768303703, 11140056576272524422, 1895853887747460679, 7283324369187624339, 16195252249773926894}, + }, + { + {823375075601828122, 17327350242456001950, 1349893857168950396, 8412958507213802615, 948019923217166776, 7456308766971274642}, + {17370437399496312157, 8520389823586348238, 15411367408205754799, 13174837180834440525, 9274060964565734577, 14571182742247634669}, + }, + { + {1082395577808637743, 8147865335545732038, 1404461702912200930, 4993236329065838796, 17484910947541357459, 6852232223602019945}, + {8965634425630211893, 4255349305144782529, 5448760775922504263, 708413774782466570, 11280134104493101923, 6100170211777061175}, + }, + { + {625515264652475732, 3039989026588849470, 417945613321369841, 17093374707175198551, 13237189962567875668, 2311750606403861433}, + {8005856008273673581, 6479389764331986131, 14555228340786648758, 7247893743936400741, 1374541774474051599, 11227441366009495338}, + }, + { + {4181002734489236543, 470999966911862785, 15476804201865281857, 9087684620614573993, 18304567027803637491, 15731747090499402793}, + {2010012731370719240, 2998664217104214076, 1961508652389190300, 6950362691421142338, 15681741907839112240, 17447712985298987779}, + }, + { + {11768357416958608825, 7645918167071842001, 16228882427244007654, 1745696721312212486, 11721695430734972091, 7273899982161219731}, + {8266026594340198219, 15717218685429720821, 14112476118090358572, 17888013578946462203, 13290175546249368751, 17734414485500127553}, + }, + { + {5326868799317243470, 16458483939729073751, 14887970960607081992, 5039987544340497966, 14821797247198942090, 3950630707728288537}, + {17597412384190391301, 5520789045820740828, 8226360244407437775, 16657311355689665307, 5224094771449505848, 16756747441122548551}, + }, + { + {598869525170933512, 6677154916771020677, 12401580674393252457, 9920987208485925499, 13800670572914405529, 9707555292166940171}, + {3223483868032463832, 3631710847850758369, 11358667894316546298, 3754511562356210854, 1701568866431315786, 5919933616663414779}, + }, + { + {11490856134015076232, 5025125213251421660, 17087480468251353943, 3675626333374651640, 15669324372624095816, 5288578761594490376}, + {13849647572526881715, 390378562422129603, 5286372605531545224, 634678992498468192, 16814060184007219837, 16839035721991946110}, + }, + { + {5403383155926395805, 125221686724158846, 16200173587003585891, 1190332142773424609, 15217396669374393068, 2578745759049575066}, + {13475383798014306998, 6424876294380300114, 14191098580567931628, 5890095616593589345, 2936173359172605332, 17487060099266163274}, + }, + }, + { + { + {12719214741013613290, 5114617959251923035, 10751915446782581763, 2484828566956964312, 14343803650946049216, 14801299356022205455}, + {3016813884715770290, 17891349667893557724, 15777676062783188811, 1712819799097224132, 12168613974393954998, 13986990585905126288}, + }, + { + {8023010081509653349, 5335670617918622683, 1846902627262622829, 11994486113849390341, 6538926236372175318, 4814731736716894207}, + {16304448710578682702, 9349072176363267816, 9186691613158664419, 17103823355609391752, 3916770392270698134, 9012943127536839823}, + }, + { + {5275622406326687551, 6112584237967786501, 265405289314185926, 1412958831727264346, 7651126186628822932, 5834995389479500713}, + {13122792515707256985, 2550947875326289463, 7066444771311187962, 4421293422025492021, 10767771791627962866, 14226728638256751184}, + }, + { + {11448691464520706664, 15675985285202273608, 3655079521218996928, 15936388576359819252, 13208918369662918590, 9516984219307854927}, + {11597611792829772123, 7713221738127008948, 7961786708858212519, 16353817233799898756, 14783345852732475068, 10250761950603958774}, + }, + { + {2625594970679028763, 2169078556432423136, 13021097165593667190, 10791106227007710714, 2690189788129576822, 5484825642511489488}, + {16273557857984121953, 12145090445512587769, 16101739928864380638, 2643908061410998004, 12729107251027632439, 7695556167491532786}, + }, + { + {11157440928684545360, 3046840632242460591, 11426877095892198900, 8918480588279063509, 8787952932779849223, 9027816580501160769}, + {9128814207932650961, 7203341616721124638, 8182325905700299211, 13427506527593902897, 18140725933956453022, 5063665298842103866}, + }, + { + {13658301013561762689, 2849842635737133681, 9794505509330850697, 4574981021203185846, 8209746334820554465, 5056236831081348743}, + {16624206083233762319, 2806783205419280334, 4722899220782250386, 6951333432373876775, 16586996273337609315, 4087561966128175843}, + }, + { + {3878852889783645167, 5400481924475044908, 13648745681887805278, 16385969341835471642, 8474668593315413480, 17072114360268111657}, + {15909524935314055264, 12962656664337915873, 16045825205726727428, 17668445836324789204, 9582515111403822925, 8311229418367164498}, + }, + { + {16750713536855692337, 12158883093332386860, 869753891367085490, 15605303972493341694, 12313210121941258747, 13916691409490803616}, + {11444860648717627512, 2835105424184438282, 10913132759099776850, 1412948777401255586, 769776732776506316, 1165176872145242057}, + }, + { + {3136155720816959363, 176782515877232633, 15898658221137319414, 5945945464575269676, 9144428244947354059, 15406556014273518710}, + {9716246750324542500, 1672303908580126879, 11063634686713475813, 5077145573933036029, 9745467858439955753, 6968865545502175550}, + }, + { + {2495713660630230645, 1185980555358051965, 14406641941666869071, 13418195026575315332, 5357639127530659925, 1493186117020140399}, + {15828121188984359229, 8349485267934650396, 7613912943850760152, 18030871967540857146, 8018837622665199635, 15135626352960024679}, + }, + { + {17168709744073976774, 17815617756406029920, 7562176203824291435, 12623565445431123456, 18154939934834134345, 7536657795057385488}, + {1403539525163296919, 18383425392072061037, 3301314769729806667, 6468401011400515937, 17613786701601511597, 14867910979962040781}, + }, + { + {5676915880842387064, 10055846762720957031, 11806698128040651823, 5264306477430907541, 8384892015115220698, 78358395066300931}, + {1150314427301408206, 5063901896663115767, 638613414256407118, 8689364962315350092, 16590905670553712162, 18128165591184340257}, + }, + { + {7752905958520447175, 14603722115727539325, 9781506285327318406, 13087529078766636510, 14023569057475503528, 6019746498716519160}, + {1031759345651315039, 13964338843948005473, 6689558506286989216, 14220086196735492654, 8688284060108936168, 11830821814034764828}, + }, + { + {13480780456478148129, 17091116390541906595, 5942938816814828424, 476503073112423896, 17958436423709724523, 12898659138199048553}, + {2131038254379659612, 12525642025600402532, 3081067260990044234, 2822022238840761302, 7062264661943515613, 5905091641833394361}, + }, + }, + { + { + {13440622283766006421, 9484751676577363406, 9905947788244365184, 9616606862630155221, 9253691280381130230, 310805699197692105}, + {15857119177216089006, 10322980288919041083, 18373416554700920525, 6657775287925290320, 3666256939083168698, 439429372311506210}, + }, + { + {1597897383029505429, 10525228828887910120, 4933923276776716663, 10152243689983019623, 15301370315971850890, 4214213542732825860}, + {897349283246619198, 5660938796941340389, 3717921090959741165, 5280841632073610594, 17979019565907796206, 11519275321457511404}, + }, + { + {3291527771490538711, 12694342940653469057, 13203683462309390985, 1193899784465090270, 659621542292721066, 1071462121865719293}, + {9590655863442234173, 337930243762610616, 6432199645357122456, 10260314756660590323, 14326008875664555298, 3522995246882448014}, + }, + { + {4644598969538718139, 12193860868892577984, 12250306904140467019, 5407962404963080644, 4485091644169226191, 16089382217006835007}, + {920589308924763406, 7142202226709964624, 11524080200370440713, 8450954286780755403, 4635718750704941162, 1486085287263603581}, + }, + { + {14187921230404535350, 11346105716295753707, 18142765952006405051, 4300086759963317261, 1825347314279603037, 4246997353784727565}, + {10550338330776677777, 11915257613511762166, 465865811699731787, 14525465801670139106, 4190035864475007181, 15697268699718129928}, + }, + { + {16520532307875617691, 6478110846501161864, 12009144890567102539, 6639996996037161221, 10346745057146969014, 545026149668689158}, + {12347224953633676077, 13721884389953920858, 16613557823182647213, 8719051450883594518, 1657296232801227258, 9195723469582730377}, + }, + { + {10672379303837372508, 1178915066578644658, 7318232521602719432, 4586807728983065460, 9645130800550409989, 10469349993209561384}, + {6164577485020507700, 14774782349604625747, 1175325949885081731, 7503981034527378970, 6665905526100319746, 14115807008378187235}, + }, + { + {10537591092984195751, 14902777188358201211, 1609682826674157693, 1415112203205414973, 2121292735488271251, 9730644628099641048}, + {1561907835543757283, 17295199465882003505, 6244864773422006269, 14104758566372328508, 5172569374976915040, 10911149041876998445}, + }, + { + {4142743472397546820, 3389473658987681872, 10678200230732012359, 11202709549973179279, 9306523242271834336, 12282962716364438596}, + {9003120795952620535, 14330038165744890298, 10145599770735328847, 16631175899061725823, 6362275304129962702, 314787489785924267}, + }, + { + {11721097912057176600, 465843171488534090, 3822319191955558577, 15208224590212643113, 11095623855521247100, 6466436977520978591}, + {10032477427078550098, 14389677632018329866, 7463855252587484514, 9538679795516955542, 2432362658144624282, 3283104727441149351}, + }, + { + {12785913170846555661, 16504696481298824206, 18387430512449781784, 11501522553203007302, 17453226662032435648, 72841124322579339}, + {10340092917595603421, 18425536899827803529, 3390279596984649469, 104139025934621284, 14389540744379448736, 13185495434887927728}, + }, + { + {13047319551312062583, 13069113474868968778, 14400534570791996729, 2940176026787857058, 3476131159454733686, 4052732675176402643}, + {3639915650884140037, 3373696894468266675, 5954677702497869028, 12219029297141994717, 14767012055233408577, 4804879819244591749}, + }, + { + {5743319169894187724, 3403171851694334648, 4433580132084214877, 13890862639937427160, 10419362266230633172, 2859349082979398226}, + {8742566305870816529, 13813314196081988405, 13904410987635691727, 16614452833957126689, 13707357634780610178, 1642839273094370920}, + }, + { + {14027248214112167925, 1719835930921678207, 18418332983139545900, 3720933284960441366, 602535342330473807, 561868717519919310}, + {12719483106586196278, 10935152826803494465, 1856788292694114055, 11401362997997198554, 16655766755327767076, 16749664986736295564}, + }, + { + {4746163886620296056, 16195921656868907520, 8331686623103669412, 560576196003183117, 12094183225971951844, 16935771085543970093}, + {9464520802091612215, 10072288040788029476, 13937774116306076245, 4650247287489763753, 7901567587026209939, 5944125224832984247}, + }, + }, + { + { + {9018413310491937545, 7479211580165592007, 4723343534675309263, 13895454120971208439, 13937115985645404601, 11554040025799661497}, + {5480952972697767947, 2914963179369015982, 10162636262303291625, 11296982831055708826, 17035403260442020132, 11311386309034106855}, + }, + { + {10287403934820058638, 140061018296065973, 4609836502448609974, 12833794578281306273, 7013376274017941064, 3171002103636180619}, + {17411865245980625367, 17830137832122912415, 9926615308142487378, 10170594699632265376, 9289903336520035955, 295986264357752633}, + }, + { + {2353717779065485542, 7849736054356737745, 16353139566092721807, 12477191479637934527, 611225681162111976, 2348028862004420825}, + {9785747690717484735, 17418090343401958851, 12038755953887168101, 16958893033340106984, 13647755196440313762, 12405018904475572776}, + }, + { + {5298494778929819598, 3924508621232171971, 8749972845037533540, 1931716910689763937, 11971817937790329025, 8597404460835479112}, + {14699754936537593409, 3124307020702767627, 15973366477384098168, 12480586491719897520, 7671564839409689125, 13926805082785871387}, + }, + { + {15204999194234914607, 8349634193664955592, 6009098602331648241, 6924706367035510132, 11252627761006599356, 18041169172716666620}, + {17789359299204781079, 5727817029324871017, 8859671792757355400, 522069605866675301, 11189207261261388877, 11232767462102509610}, + }, + { + {16139497738710238126, 4157146187414349131, 5487114022641721563, 1063383115530797038, 2906599717299719710, 5276015474524600486}, + {9269825514681515477, 16775312150546041513, 14582957882487299154, 15170954478995084883, 2499812420501884408, 10945713424572036595}, + }, + { + {5089807051541807662, 7157200325468149470, 2937849588731584444, 9354845172055266578, 5631696405995964524, 2214323534299283665}, + {9722628493150662989, 17918792662316048829, 3417043373414897775, 17679083211095336242, 16808346554886232447, 13289844996223351707}, + }, + { + {11269874526592562906, 16500978216603335212, 10118738127249413871, 3659452648579232998, 5141018253691260035, 16117724868471222014}, + {11347815034616287201, 7709514744105498479, 14118984237650181458, 12026134955404838277, 9335436582353087685, 369430838816330654}, + }, + { + {1585139051234805814, 404691396436142113, 11444293817557480245, 5830770104023383537, 12277306276048209251, 10642326551634509497}, + {13792665542662432081, 6208000577113784638, 15717378408394080413, 7820469524198781038, 14389089922028942421, 8582404818280480446}, + }, + { + {70981166460121239, 5563408652468244620, 614683176526977757, 2781152952815547101, 12029155884278293318, 17760250353211832620}, + {3187755494407378069, 17888395113661363276, 13412285944510495080, 11584741820870126887, 15965393589757423852, 18040989847530826793}, + }, + { + {5405473909442890818, 14666994240588619109, 12458304673324386647, 11008174367296119903, 14582036957337795851, 17282661739787817063}, + {14222078674054535548, 11008919174943325660, 11819167351245959209, 18134905895138035484, 13162976610859867356, 7513570547713034700}, + }, + { + {14503898932310678540, 10872534209513960811, 10769539085938900258, 950968100788102293, 2593957957211394429, 9325054429337127538}, + {8794306083750832982, 1021791833181379560, 9826075936615091843, 3550496685357100718, 10181274077023686988, 1708403758287646690}, + }, + { + {2114324794753920008, 9126128083829835556, 16280212870402563277, 13283686190256525376, 3251349600931694719, 14483424206972436627}, + {10572754008401154275, 8633764455629405737, 6588424944597437957, 1571954989152470825, 8516883611989669014, 11640306975729561230}, + }, + { + {4109007533450828692, 2356386509806748446, 9041152461761446992, 16218546554098405589, 14154709222330366952, 9392453621407519648}, + {17770577554690365656, 10932372374411174377, 12600690631485435764, 7948622706571305677, 8660221260057720358, 4747684946643246411}, + }, + { + {8540558873947276350, 3622540825228765451, 16650849354810540513, 11226397583292742086, 4705379347219803579, 12325233166887290731}, + {15619140333232072725, 8608337299420394261, 2163342765639233276, 15744964703433685214, 5280747802181153134, 17233894809548258880}, + }, + }, + { + { + {13115213709675436794, 10299123692547567131, 9429245948262081969, 13047795122467758935, 13812575189117105527, 2948332115489926339}, + {2744672569127744094, 4815622797427999112, 859178603639156086, 11576446289001159839, 9958253466657519480, 16703064241036892748}, + }, + { + {9659930467403989932, 17321718087937017122, 3615409075768522018, 6398728174042229488, 8382474392298007936, 16868018560156882295}, + {15394153985344325633, 18233056749369336201, 2786261003208561400, 14117307321540249886, 9686181390715937042, 8956691786907318249}, + }, + { + {12469663383430832235, 13312156986621640537, 11912360761178303017, 11804219970133303678, 18138791436343161493, 2154714404896772973}, + {8464860256859883443, 14324425897255227015, 11075246616197014103, 11084846688464899884, 14026644252332359919, 6402389694082745611}, + }, + { + {1664247920632234678, 10050469124529404545, 13550912777105883578, 5684389909240961711, 18262622312373628010, 5992040147885225610}, + {3886052343944693110, 7794548519566311969, 5328743476861022198, 3557155954099235264, 3684795529791949842, 17691405542438413688}, + }, + { + {9667044915797468497, 5187341894386544411, 9007932748072503962, 8968805127439822005, 4693907985120651307, 1280923431871955632}, + {6721231714391543602, 12198545097663757759, 4397005010009650381, 1422329781944115833, 125099025124551420, 12942840780107155582}, + }, + { + {9559600762660458657, 2654878193132084429, 6142683421157333426, 8600628541895281085, 2720194395607941256, 11800628992463553487}, + {4425191657353376240, 6088099402960722641, 115029919295524541, 12646988404583673832, 13384863624367861501, 18364682859012250550}, + }, + { + {4532078693830769620, 718394906501818236, 3877201007259789143, 760257150764070663, 16650468445415199734, 14938394407466859533}, + {13647198668172065265, 8150502240122876834, 14693081828320862132, 7303871211541846858, 9083743247615337146, 14627695013907233453}, + }, + { + {15736758467123642408, 9706701086221383807, 2559832927730153795, 7692171838583389170, 10835849209926253466, 2290935724211630501}, + {7110948153091501836, 12491488884744421116, 17194507769433100343, 12871741772449719665, 13293932181017940663, 15615371283128275924}, + }, + { + {10561525560550219871, 8873205184226519024, 7699063686607517061, 13635014797737384505, 14667176363819822811, 3925937510121565786}, + {10228456892890207582, 14846438160606646653, 5315480697106497650, 5122456725957472423, 6204140834106767339, 673047575978292150}, + }, + { + {13827793037997042902, 2372112433190900987, 4942678787760432958, 17946455618542608613, 15396054321262292130, 11511518053778317681}, + {11160017347470886464, 13664803594602056362, 8669936965482088617, 17765994223101087455, 14455539200673473573, 7079780915049059206}, + }, + { + {8033984515178450060, 16378670770570801979, 1548095437408110789, 11401360828210390234, 8750170757194679057, 4561487363432466918}, + {9995552829545286346, 4476962116767664929, 5764765679815373569, 15487395691041270870, 2323841776203994300, 2856618876814473844}, + }, + { + {11531868239432263786, 5277805717080096397, 11682853637330501925, 5733978770749385591, 17364192273085890197, 7500286843970580511}, + {86794299821863973, 4596156132784169023, 4785356555999800565, 10872734824615120105, 3047769721102166199, 10829425068529251522}, + }, + { + {16664987869819734811, 12973908345922045971, 4703076108718901177, 14075270048770461650, 104815219486926864, 892782843371503265}, + {10458459649338308428, 10668999312407153052, 13704561636334771166, 4635417240676718572, 5106553366947462575, 3703456388087747221}, + }, + { + {2751721731474885326, 16084898094744997319, 12429196417254737907, 6088459822127419367, 6900842023460552142, 12211266007254795824}, + {7744071277950462535, 2084549072065931478, 9120649345176753774, 4812104275201077076, 657496594162312754, 3182353075430185403}, + }, + { + {8755422501308001479, 10142307435936727265, 11064770721673029308, 18425843187034865157, 13347285302222173760, 3708437028689637787}, + {14876728210989151093, 7705511398925586068, 14248821016296346136, 17806364092565886021, 5124212170718863197, 16198455889993493512}, + }, + }, + { + { + {11131309769818983841, 14973020341004185634, 8446856854308327009, 89059453523509986, 9172267203688134801, 11760494578717306152}, + {5073673248942080292, 1012148470051943223, 11336947344365930468, 9256490203060408704, 15345366488712852356, 4777703526474964085}, + }, + { + {6785992801663327967, 18012758086365480538, 11715768358595862309, 15278468386670997865, 7557494802091764967, 3226512940013553265}, + {10651059331535692113, 11605693566797492518, 7683257465728908366, 1028223626866438466, 16313431221531990341, 6758261315736790700}, + }, + { + {11449545682029299204, 6596199629139963480, 963551988680601724, 698978766831128675, 17425132333529601498, 13413146748170623416}, + {1714656874981820009, 4296884965902036208, 2990962557113972989, 10577651126385226151, 14576461165238503913, 6650017187571610816}, + }, + { + {6245777462138705770, 602174165006002688, 9651995753732157494, 6180859913470161771, 12820839311740267213, 10236566947582409415}, + {11884174684151318817, 15241119462662846032, 6907037784685500586, 8001533132847243248, 3670287336361099984, 3392433665095714529}, + }, + { + {13912308898779395548, 3788232904773170505, 13510110594291767173, 8520990689262136399, 5635271140287576080, 7032476081565599191}, + {3050147342057890882, 5226316271430966932, 11412499390577871486, 11913706106456146646, 4829447444602840419, 14235552292854028654}, + }, + { + {17312195306081130163, 12680842068822272296, 11528293990644984223, 14726421452780975383, 11447257867816650567, 762807127447733227}, + {11172211697797188525, 8517884001168098535, 18342273006866963779, 17586041278289316668, 4779448404822225420, 9813346493235742371}, + }, + { + {9286929404285814938, 8816346852883562511, 7466996584964541958, 5933279471984750642, 1644469041072153982, 11834454051429614839}, + {11689018037377144292, 9302324005187580531, 5409758949060136366, 4109111569593553253, 16829865226968878273, 6434426298631595957}, + }, + { + {16596404332021807148, 11395037243930999642, 6230660960102828038, 14208272099018002212, 8705581668959309002, 7133705014266607355}, + {14252633600291674542, 17382067068187300207, 18138192466898743511, 6530204006214324897, 18284169711456293177, 4900989821334366705}, + }, + { + {5965502925766151340, 3801830478050084251, 6152884788276000974, 10584299273681935132, 2524731521663531672, 15776417203522871638}, + {6285082299497166915, 15290822150488384424, 5578747051433926469, 5845296506012538407, 4823217512374723890, 7213090796321328136}, + }, + { + {1838054042722947491, 18012783215465657741, 1258715365050436512, 7913577973454740911, 7384511648712781941, 4158912753329944154}, + {14299503727251690236, 8238664371507527991, 5075150254794639881, 11556112057563955850, 9196908777829742547, 1421651284198415569}, + }, + { + {7653294651845234281, 297639109833143896, 4336984993054011825, 16447737956972905656, 1714050270655945931, 15452230596345454363}, + {15076547011376710685, 7524806307535928719, 7795256374139730227, 10089448010239318836, 7023465550055784134, 6968423688937605957}, + }, + { + {13092365251897461865, 18278882827386367428, 14555338542207092484, 6910907828139278038, 4543230946116571027, 5044543664197618202}, + {6650151637454194021, 6834808965400326944, 16365723935359292167, 14827804062568090126, 13707520293209424632, 6325303435642990801}, + }, + { + {343357558658755796, 6940253811840342433, 12914150358606642695, 17231336963809853008, 11079943205463705734, 12473223889867436019}, + {15215091930162368566, 11521732813165590119, 4432843582148093137, 2750024527657999932, 9405241261008362249, 10288224084277755975}, + }, + { + {10358507458667546506, 4836195114970556281, 4009596827146315911, 11256224974885245252, 5176303767964952564, 111134394063583597}, + {6393513946378868409, 17037805604945819779, 10171688558016965768, 7858522891516850377, 1914205856134346186, 16973629294504183772}, + }, + { + {10256813334907479264, 17555541259591449755, 10506400127843286281, 3802242808788493442, 16997535067306771110, 8902379766095587425}, + {1036044043924340639, 17424237503082033211, 12387965860513794582, 2930816639468217614, 10629728210657646483, 15009855708899356359}, + }, + }, + { + { + {4454189113653900584, 2369870743683386936, 9771750146904378734, 7229551204834152191, 9308930686126579243, 5564951339003155731}, + {2523209505731486974, 11655219901025790380, 10064955099576512592, 14322381509056856025, 15960759442596276288, 3132442392059561449}, + }, + { + {14421263046720478865, 10262735078638179312, 3820432306672060577, 15745169881456738128, 11281698473866736902, 15822191634431631555}, + {4821811912616493018, 16782915424867765464, 1577651352486052440, 716633372221422297, 508136038908094084, 16377700646398062786}, + }, + { + {424706049021067379, 14217487990368728988, 7719227939353578736, 4199843265846733886, 16388456301404529776, 15169247696432251820}, + {9090595157644861783, 10581077201944372077, 1379900013445280838, 7494321123029536948, 17787926264007537465, 5067787616258265775}, + }, + { + {769698236917518124, 3483900225503109603, 3336909192235363398, 541374049706836141, 18104741290431601017, 14983166848044339752}, + {6121492399965995954, 16666617093809949054, 10249737155929975505, 1473067211573216915, 16575421339110736253, 5806380672117240601}, + }, + { + {13499925512737386719, 13944763802764915814, 9159954083757191227, 6979221481184822758, 14300821660040225990, 16265637021317828603}, + {3128114568639019553, 2504404013570803046, 9274630379913042841, 5414311569178493969, 16628860202352780141, 5598477736550720675}, + }, + { + {9130425033956973272, 14637917817606979898, 17028834835152328690, 3041045091819937813, 5696889246846210875, 14160128160963955776}, + {4567408060924985859, 8330188839918063054, 10075889358467904432, 10649295639077482245, 6371906135676507546, 14525834287139954362}, + }, + { + {16074395804418777643, 5541188270073279665, 8295310521928755861, 6864072771162821613, 17911901316631945045, 10605026599429014107}, + {690935445353571870, 1392537891789610105, 7325904616956299332, 1149398686564874112, 17689896955892401926, 15639337629880458046}, + }, + { + {2591269655907388346, 11399575915049212026, 2043559396265943823, 2133276679198333751, 2052339475550725155, 6752287291455887793}, + {949413463927904836, 9470431435117911687, 8077017638133728996, 16830570160974576546, 8072941217145343758, 4326954112402321249}, + }, + { + {3412919337711024431, 16383399630678254841, 2740801234954712157, 15867621577894919999, 2797972073741634922, 6677462884297174122}, + {17474301298337562800, 3996912168590289455, 2877907669270439874, 12028178698733277400, 9048903683242829652, 16676938495979746758}, + }, + { + {9535591367797480450, 3032516458384811911, 16858722241492443043, 6099583463893158590, 14048493063580960236, 12185142455189643566}, + {13517307410699214798, 262669939477440604, 6425159725529082877, 9337681168995712285, 4468475772573169834, 7978572861495407848}, + }, + { + {14371139353492294781, 4986055967754386106, 994283350302316111, 124059366184412674, 17931249617405877625, 11248278814950278199}, + {8524946062048541221, 6940016701900868483, 4388778906010249088, 3316636379456104494, 4720367297793042554, 11143646688813775128}, + }, + { + {4447383188862483936, 15286779289485640736, 264847228943597281, 17761832039421017475, 5925682522537768028, 7096337516750811757}, + {18071896252632882904, 9283619734214567194, 10122267390711497388, 4667499764407784879, 227971306242715406, 895727107492327229}, + }, + { + {11203525951412289019, 12852755217270479509, 9978444356559295662, 15803698066139233622, 15160649502708391831, 13050401346945170580}, + {17641607277129335085, 15629899850899448002, 8690304923168739299, 13258223666573053280, 9366850728951877315, 5050696512039385569}, + }, + { + {6369749042849981516, 14997591469096472735, 14585781473609538602, 4957906834847789414, 9248310387962593481, 5103185051386294714}, + {13712135472859015397, 6056087516321847761, 2219295526440778687, 8233797578211440273, 7240984299223714420, 4911601582698376693}, + }, + { + {4929990821929415849, 3130583257788034008, 9497231337826843444, 6435653863924772981, 1134942105434085779, 18114272026645693035}, + {2524774042677381563, 7016780555346498950, 5414403864902656268, 15986697199444096112, 9742407776110139287, 6514675658717406998}, + }, + }, + } +} diff --git a/core/crypto/_weierstrass/tools/ecc_gen_tables.odin b/core/crypto/_weierstrass/tools/ecc_gen_tables.odin new file mode 100644 index 000000000..3211c65f3 --- /dev/null +++ b/core/crypto/_weierstrass/tools/ecc_gen_tables.odin @@ -0,0 +1,134 @@ +package weierstrass_tools + +import secec "core:crypto/_weierstrass" +import "core:fmt" +import path "core:path/filepath" +import "core:os" +import "core:strings" + +// Yes this leaks memory, fite me IRL. + +GENERATED :: `/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/` + +main :: proc() { + gen_tables("p256r1") + gen_tables("p384r1") +} + +gen_tables :: proc($CURVE: string) { + when CURVE == "p256r1" { + Affine_Point_p256r1 :: struct { + x: secec.Field_Element_p256r1, + y: secec.Field_Element_p256r1, + } + + Multiply_Table_hi: [32][15]Affine_Point_p256r1 + Multiply_Table_lo: [32][15]Affine_Point_p256r1 + + SC_LEN :: 32 + + g, p: secec.Point_p256r1 + } else when CURVE == "p384r1" { + Affine_Point_p384r1 :: struct { + x: secec.Field_Element_p384r1, + y: secec.Field_Element_p384r1, + } + Multiply_Table_hi: [48][15]Affine_Point_p384r1 + Multiply_Table_lo: [48][15]Affine_Point_p384r1 + + SC_LEN :: 48 + + g, p: secec.Point_p384r1 + } else { + #panic("weistrass/tools: invalid curve") + } + + secec.pt_generator(&g) + + // Precompute ([1,15] << n) * G multiples of G, MSB->LSB + for i in 0.. bool { } if crypto.compare_constant_time(tag, derived_tag) != 1 { - mem.zero_explicit(raw_data(derived_tag), len(derived_tag)) - mem.zero_explicit(raw_data(dst), ct_len) + crypto.zero_explicit(raw_data(derived_tag), len(derived_tag)) + crypto.zero_explicit(raw_data(dst), ct_len) return false } @@ -207,7 +207,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { // reset sanitizes the Context. The Context must be // re-initialized to be used again. reset :: proc "contextless" (ctx: ^Context) { - mem.zero_explicit(&ctx._key, len(ctx._key)) + crypto.zero_explicit(&ctx._key, len(ctx._key)) ctx._key_len = 0 ctx._is_initialized = false -} +} \ No newline at end of file diff --git a/core/crypto/aegis/aegis_impl_ct64.odin b/core/crypto/aegis/aegis_impl_ct64.odin index 4813b37ec..15a9b4b3d 100644 --- a/core/crypto/aegis/aegis_impl_ct64.odin +++ b/core/crypto/aegis/aegis_impl_ct64.odin @@ -1,8 +1,8 @@ package aegis +import "core:crypto" import aes "core:crypto/_aes/ct64" import "core:encoding/endian" -import "core:mem" // This uses the bitlsiced 64-bit general purpose register SWAR AES // round function. The intermediate state is stored in interleaved @@ -324,7 +324,7 @@ dec_sw_256 :: #force_inline proc "contextless" (st: ^State_SW, xi, ci: []byte) # @(private = "file") dec_partial_sw_128l :: proc "contextless" (st: ^State_SW, xn, cn: []byte) #no_bounds_check { tmp: [_RATE_128L]byte - defer mem.zero_explicit(&tmp, size_of(tmp)) + defer crypto.zero_explicit(&tmp, size_of(tmp)) z0_0, z0_1, z1_0, z1_1 := z_sw_128l(st) copy(tmp[:], cn) @@ -349,7 +349,7 @@ dec_partial_sw_128l :: proc "contextless" (st: ^State_SW, xn, cn: []byte) #no_bo @(private = "file") dec_partial_sw_256 :: proc "contextless" (st: ^State_SW, xn, cn: []byte) #no_bounds_check { tmp: [_RATE_256]byte - defer mem.zero_explicit(&tmp, size_of(tmp)) + defer crypto.zero_explicit(&tmp, size_of(tmp)) z_0, z_1 := z_sw_256(st) copy(tmp[:], cn) @@ -448,5 +448,5 @@ finalize_sw :: proc "contextless" (st: ^State_SW, tag: []byte, ad_len, msg_len: @(private) reset_state_sw :: proc "contextless" (st: ^State_SW) { - mem.zero_explicit(st, size_of(st^)) + crypto.zero_explicit(st, size_of(st^)) } diff --git a/core/crypto/aegis/aegis_impl_hw.odin b/core/crypto/aegis/aegis_impl_hw.odin new file mode 100644 index 000000000..4a39b341c --- /dev/null +++ b/core/crypto/aegis/aegis_impl_hw.odin @@ -0,0 +1,397 @@ +#+build amd64,arm64,arm32 +package aegis + +import "base:intrinsics" +import "core:crypto" +import aes_hw "core:crypto/_aes/hw" +import "core:encoding/endian" +import "core:simd" + +@(private) +State_HW :: struct { + s0: simd.u8x16, + s1: simd.u8x16, + s2: simd.u8x16, + s3: simd.u8x16, + s4: simd.u8x16, + s5: simd.u8x16, + s6: simd.u8x16, + s7: simd.u8x16, + rate: int, +} + +when ODIN_ARCH == .amd64 { + @(private="file") + TARGET_FEATURES :: "sse2,aes" +} else when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { + @(private="file") + TARGET_FEATURES :: "neon,aes" +} + +// is_hardware_accelerated returns true if and only if (⟺) hardware +// accelerated AEGIS is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return aes_hw.is_supported() +} + +@(private, enable_target_feature = TARGET_FEATURES) +init_hw :: proc "contextless" (ctx: ^Context, st: ^State_HW, iv: []byte) { + switch ctx._key_len { + case KEY_SIZE_128L: + key := intrinsics.unaligned_load((^simd.u8x16)(&ctx._key[0])) + iv := intrinsics.unaligned_load((^simd.u8x16)(raw_data(iv))) + + st.s0 = simd.bit_xor(key, iv) + st.s1 = intrinsics.unaligned_load((^simd.u8x16)(&_C1[0])) + st.s2 = intrinsics.unaligned_load((^simd.u8x16)(&_C0[0])) + st.s3 = st.s1 + st.s4 = st.s0 + st.s5 = simd.bit_xor(key, st.s2) // key ^ C0 + st.s6 = simd.bit_xor(key, st.s1) // key ^ C1 + st.s7 = st.s5 + st.rate = _RATE_128L + + for _ in 0 ..< 10 { + update_hw_128l(st, iv, key) + } + case KEY_SIZE_256: + k0 := intrinsics.unaligned_load((^simd.u8x16)(&ctx._key[0])) + k1 := intrinsics.unaligned_load((^simd.u8x16)(&ctx._key[16])) + n0 := intrinsics.unaligned_load((^simd.u8x16)(&iv[0])) + n1 := intrinsics.unaligned_load((^simd.u8x16)(&iv[16])) + + st.s0 = simd.bit_xor(k0, n0) + st.s1 = simd.bit_xor(k1, n1) + st.s2 = intrinsics.unaligned_load((^simd.u8x16)(&_C1[0])) + st.s3 = intrinsics.unaligned_load((^simd.u8x16)(&_C0[0])) + st.s4 = simd.bit_xor(k0, st.s3) // k0 ^ C0 + st.s5 = simd.bit_xor(k1, st.s2) // k1 ^ C1 + st.rate = _RATE_256 + + u0, u1 := st.s0, st.s1 + for _ in 0 ..< 4 { + update_hw_256(st, k0) + update_hw_256(st, k1) + update_hw_256(st, u0) + update_hw_256(st, u1) + } + } +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +update_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, m0, m1: simd.u8x16) { + s0_ := aes_hw.aesenc(st.s7, simd.bit_xor(st.s0, m0)) + s1_ := aes_hw.aesenc(st.s0, st.s1) + s2_ := aes_hw.aesenc(st.s1, st.s2) + s3_ := aes_hw.aesenc(st.s2, st.s3) + s4_ := aes_hw.aesenc(st.s3, simd.bit_xor(st.s4, m1)) + s5_ := aes_hw.aesenc(st.s4, st.s5) + s6_ := aes_hw.aesenc(st.s5, st.s6) + s7_ := aes_hw.aesenc(st.s6, st.s7) + st.s0, st.s1, st.s2, st.s3, st.s4, st.s5, st.s6, st.s7 = s0_, s1_, s2_, s3_, s4_, s5_, s6_, s7_ +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +update_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, m: simd.u8x16) { + s0_ := aes_hw.aesenc(st.s5, simd.bit_xor(st.s0, m)) + s1_ := aes_hw.aesenc(st.s0, st.s1) + s2_ := aes_hw.aesenc(st.s1, st.s2) + s3_ := aes_hw.aesenc(st.s2, st.s3) + s4_ := aes_hw.aesenc(st.s3, st.s4) + s5_ := aes_hw.aesenc(st.s4, st.s5) + st.s0, st.s1, st.s2, st.s3, st.s4, st.s5 = s0_, s1_, s2_, s3_, s4_, s5_ +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +absorb_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { + t0 := intrinsics.unaligned_load((^simd.u8x16)(&ai[0])) + t1 := intrinsics.unaligned_load((^simd.u8x16)(&ai[16])) + update_hw_128l(st, t0, t1) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +absorb_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { + m := intrinsics.unaligned_load((^simd.u8x16)(&ai[0])) + update_hw_256(st, m) +} + +@(private, enable_target_feature = TARGET_FEATURES) +absorb_hw :: proc "contextless" (st: ^State_HW, aad: []byte) #no_bounds_check { + ai, l := aad, len(aad) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + absorb_hw_128l(st, ai) + ai = ai[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + absorb_hw_256(st, ai) + + ai = ai[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // AAD is not confidential. + copy(tmp[:], ai) + switch st.rate { + case _RATE_128L: + absorb_hw_128l(st, tmp[:]) + case _RATE_256: + absorb_hw_256(st, tmp[:]) + } + } +} + +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) +z_hw_128l :: #force_inline proc "contextless" (st: ^State_HW) -> (simd.u8x16, simd.u8x16) { + z0 := simd.bit_xor( + st.s6, + simd.bit_xor( + st.s1, + simd.bit_and(st.s2, st.s3), + ), + ) + z1 := simd.bit_xor( + st.s2, + simd.bit_xor( + st.s5, + simd.bit_and(st.s6, st.s7), + ), + ) + return z0, z1 +} + +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) +z_hw_256 :: #force_inline proc "contextless" (st: ^State_HW) -> simd.u8x16 { + return simd.bit_xor( + st.s1, + simd.bit_xor( + st.s4, + simd.bit_xor( + st.s5, + simd.bit_and(st.s2, st.s3), + ), + ), + ) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +enc_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { + z0, z1 := z_hw_128l(st) + + t0 := intrinsics.unaligned_load((^simd.u8x16)(&xi[0])) + t1 := intrinsics.unaligned_load((^simd.u8x16)(&xi[16])) + update_hw_128l(st, t0, t1) + + out0 := simd.bit_xor(t0, z0) + out1 := simd.bit_xor(t1, z1) + intrinsics.unaligned_store((^simd.u8x16)(&ci[0]), out0) + intrinsics.unaligned_store((^simd.u8x16)(&ci[16]), out1) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +enc_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { + z := z_hw_256(st) + + xi_ := intrinsics.unaligned_load((^simd.u8x16)(raw_data(xi))) + update_hw_256(st, xi_) + + ci_ := simd.bit_xor(xi_, z) + intrinsics.unaligned_store((^simd.u8x16)(raw_data(ci)), ci_) +} + +@(private, enable_target_feature = TARGET_FEATURES) +enc_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { + ci, xi, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + enc_hw_128l(st, ci, xi) + ci = ci[_RATE_128L:] + xi = xi[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + enc_hw_256(st, ci, xi) + ci = ci[_RATE_256:] + xi = xi[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // Ciphertext is not confidential. + copy(tmp[:], xi) + switch st.rate { + case _RATE_128L: + enc_hw_128l(st, tmp[:], tmp[:]) + case _RATE_256: + enc_hw_256(st, tmp[:], tmp[:]) + } + copy(ci, tmp[:l]) + } +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +dec_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { + z0, z1 := z_hw_128l(st) + + t0 := intrinsics.unaligned_load((^simd.u8x16)(&ci[0])) + t1 := intrinsics.unaligned_load((^simd.u8x16)(&ci[16])) + out0 := simd.bit_xor(t0, z0) + out1 := simd.bit_xor(t1, z1) + + update_hw_128l(st, out0, out1) + intrinsics.unaligned_store((^simd.u8x16)(&xi[0]), out0) + intrinsics.unaligned_store((^simd.u8x16)(&xi[16]), out1) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +dec_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { + z := z_hw_256(st) + + ci_ := intrinsics.unaligned_load((^simd.u8x16)(raw_data(ci))) + xi_ := simd.bit_xor(ci_, z) + + update_hw_256(st, xi_) + intrinsics.unaligned_store((^simd.u8x16)(raw_data(xi)), xi_) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +dec_partial_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_128L]byte + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + z0, z1 := z_hw_128l(st) + copy(tmp[:], cn) + + t0 := intrinsics.unaligned_load((^simd.u8x16)(&tmp[0])) + t1 := intrinsics.unaligned_load((^simd.u8x16)(&tmp[16])) + out0 := simd.bit_xor(t0, z0) + out1 := simd.bit_xor(t1, z1) + + intrinsics.unaligned_store((^simd.u8x16)(&tmp[0]), out0) + intrinsics.unaligned_store((^simd.u8x16)(&tmp[16]), out1) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_128L; off += 1 { + tmp[off] = 0 + } + out0 = intrinsics.unaligned_load((^simd.u8x16)(&tmp[0])) // v0 + out1 = intrinsics.unaligned_load((^simd.u8x16)(&tmp[16])) // v1 + update_hw_128l(st, out0, out1) +} + +@(private = "file", enable_target_feature = TARGET_FEATURES) +dec_partial_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_256]byte + defer crypto.zero_explicit(&tmp, size_of(tmp)) + + z := z_hw_256(st) + copy(tmp[:], cn) + + cn_ := intrinsics.unaligned_load((^simd.u8x16)(&tmp[0])) + xn_ := simd.bit_xor(cn_, z) + + intrinsics.unaligned_store((^simd.u8x16)(&tmp[0]), xn_) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_256; off += 1 { + tmp[off] = 0 + } + xn_ = intrinsics.unaligned_load((^simd.u8x16)(&tmp[0])) + update_hw_256(st, xn_) +} + +@(private, enable_target_feature = TARGET_FEATURES) +dec_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { + xi, ci, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + dec_hw_128l(st, xi, ci) + xi = xi[_RATE_128L:] + ci = ci[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + dec_hw_256(st, xi, ci) + xi = xi[_RATE_256:] + ci = ci[_RATE_256:] + l -= _RATE_256 + } + } + + // Process the remainder. + if l > 0 { + switch st.rate { + case _RATE_128L: + dec_partial_hw_128l(st, xi, ci) + case _RATE_256: + dec_partial_hw_256(st, xi, ci) + } + } +} + +@(private, enable_target_feature = TARGET_FEATURES) +finalize_hw :: proc "contextless" (st: ^State_HW, tag: []byte, ad_len, msg_len: int) { + tmp: [16]byte + endian.unchecked_put_u64le(tmp[0:], u64(ad_len) * 8) + endian.unchecked_put_u64le(tmp[8:], u64(msg_len) * 8) + + t := intrinsics.unaligned_load((^simd.u8x16)(&tmp[0])) + + t0, t1: simd.u8x16 = ---, --- + switch st.rate { + case _RATE_128L: + t = simd.bit_xor(st.s2, t) + for _ in 0 ..< 7 { + update_hw_128l(st, t, t) + } + + t0 = simd.bit_xor(st.s0, st.s1) + t0 = simd.bit_xor(t0, st.s2) + t0 = simd.bit_xor(t0, st.s3) + + t1 = simd.bit_xor(st.s4, st.s5) + t1 = simd.bit_xor(t1, st.s6) + if len(tag) == TAG_SIZE_256 { + t1 = simd.bit_xor(t1, st.s7) + } + case _RATE_256: + t = simd.bit_xor(st.s3, t) + for _ in 0 ..< 7 { + update_hw_256(st, t) + } + + t0 = simd.bit_xor(st.s0, st.s1) + t0 = simd.bit_xor(t0, st.s2) + + t1 = simd.bit_xor(st.s3, st.s4) + t1 = simd.bit_xor(t1, st.s5) + } + switch len(tag) { + case TAG_SIZE_128: + t0 = simd.bit_xor(t0, t1) + intrinsics.unaligned_store((^simd.u8x16)(&tag[0]), t0) + case TAG_SIZE_256: + intrinsics.unaligned_store((^simd.u8x16)(&tag[0]), t0) + intrinsics.unaligned_store((^simd.u8x16)(&tag[16]), t1) + } +} + +@(private) +reset_state_hw :: proc "contextless" (st: ^State_HW) { + crypto.zero_explicit(st, size_of(st^)) +} diff --git a/core/crypto/aegis/aegis_impl_hw_gen.odin b/core/crypto/aegis/aegis_impl_hw_gen.odin index 5ec2f3d6e..8f8b4c5da 100644 --- a/core/crypto/aegis/aegis_impl_hw_gen.odin +++ b/core/crypto/aegis/aegis_impl_hw_gen.odin @@ -1,4 +1,6 @@ #+build !amd64 +#+build !arm64 +#+build !arm32 package aegis @(private = "file") @@ -7,7 +9,7 @@ ERR_HW_NOT_SUPPORTED :: "crypto/aegis: hardware implementation unsupported" @(private) State_HW :: struct {} -// is_hardware_accelerated returns true iff hardware accelerated AEGIS +// is_hardware_accelerated returns true if and only if (⟺) hardware accelerated AEGIS // is supported. is_hardware_accelerated :: proc "contextless" () -> bool { return false diff --git a/core/crypto/aegis/aegis_impl_hw_intel.odin b/core/crypto/aegis/aegis_impl_hw_intel.odin deleted file mode 100644 index 5334f3258..000000000 --- a/core/crypto/aegis/aegis_impl_hw_intel.odin +++ /dev/null @@ -1,389 +0,0 @@ -#+build amd64 -package aegis - -import "base:intrinsics" -import "core:crypto/aes" -import "core:encoding/endian" -import "core:mem" -import "core:simd/x86" - -@(private) -State_HW :: struct { - s0: x86.__m128i, - s1: x86.__m128i, - s2: x86.__m128i, - s3: x86.__m128i, - s4: x86.__m128i, - s5: x86.__m128i, - s6: x86.__m128i, - s7: x86.__m128i, - rate: int, -} - -// is_hardware_accelerated returns true iff hardware accelerated AEGIS -// is supported. -is_hardware_accelerated :: proc "contextless" () -> bool { - return aes.is_hardware_accelerated() -} - -@(private, enable_target_feature = "sse2,aes") -init_hw :: proc "contextless" (ctx: ^Context, st: ^State_HW, iv: []byte) { - switch ctx._key_len { - case KEY_SIZE_128L: - key := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[0])) - iv := intrinsics.unaligned_load((^x86.__m128i)(raw_data(iv))) - - st.s0 = x86._mm_xor_si128(key, iv) - st.s1 = intrinsics.unaligned_load((^x86.__m128i)(&_C1[0])) - st.s2 = intrinsics.unaligned_load((^x86.__m128i)(&_C0[0])) - st.s3 = st.s1 - st.s4 = st.s0 - st.s5 = x86._mm_xor_si128(key, st.s2) // key ^ C0 - st.s6 = x86._mm_xor_si128(key, st.s1) // key ^ C1 - st.s7 = st.s5 - st.rate = _RATE_128L - - for _ in 0 ..< 10 { - update_hw_128l(st, iv, key) - } - case KEY_SIZE_256: - k0 := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[0])) - k1 := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[16])) - n0 := intrinsics.unaligned_load((^x86.__m128i)(&iv[0])) - n1 := intrinsics.unaligned_load((^x86.__m128i)(&iv[16])) - - st.s0 = x86._mm_xor_si128(k0, n0) - st.s1 = x86._mm_xor_si128(k1, n1) - st.s2 = intrinsics.unaligned_load((^x86.__m128i)(&_C1[0])) - st.s3 = intrinsics.unaligned_load((^x86.__m128i)(&_C0[0])) - st.s4 = x86._mm_xor_si128(k0, st.s3) // k0 ^ C0 - st.s5 = x86._mm_xor_si128(k1, st.s2) // k1 ^ C1 - st.rate = _RATE_256 - - u0, u1 := st.s0, st.s1 - for _ in 0 ..< 4 { - update_hw_256(st, k0) - update_hw_256(st, k1) - update_hw_256(st, u0) - update_hw_256(st, u1) - } - } -} - -@(private = "file", enable_target_feature = "sse2,aes") -update_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, m0, m1: x86.__m128i) { - s0_ := x86._mm_aesenc_si128(st.s7, x86._mm_xor_si128(st.s0, m0)) - s1_ := x86._mm_aesenc_si128(st.s0, st.s1) - s2_ := x86._mm_aesenc_si128(st.s1, st.s2) - s3_ := x86._mm_aesenc_si128(st.s2, st.s3) - s4_ := x86._mm_aesenc_si128(st.s3, x86._mm_xor_si128(st.s4, m1)) - s5_ := x86._mm_aesenc_si128(st.s4, st.s5) - s6_ := x86._mm_aesenc_si128(st.s5, st.s6) - s7_ := x86._mm_aesenc_si128(st.s6, st.s7) - st.s0, st.s1, st.s2, st.s3, st.s4, st.s5, st.s6, st.s7 = s0_, s1_, s2_, s3_, s4_, s5_, s6_, s7_ -} - -@(private = "file", enable_target_feature = "sse2,aes") -update_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, m: x86.__m128i) { - s0_ := x86._mm_aesenc_si128(st.s5, x86._mm_xor_si128(st.s0, m)) - s1_ := x86._mm_aesenc_si128(st.s0, st.s1) - s2_ := x86._mm_aesenc_si128(st.s1, st.s2) - s3_ := x86._mm_aesenc_si128(st.s2, st.s3) - s4_ := x86._mm_aesenc_si128(st.s3, st.s4) - s5_ := x86._mm_aesenc_si128(st.s4, st.s5) - st.s0, st.s1, st.s2, st.s3, st.s4, st.s5 = s0_, s1_, s2_, s3_, s4_, s5_ -} - -@(private = "file", enable_target_feature = "sse2,aes") -absorb_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { - t0 := intrinsics.unaligned_load((^x86.__m128i)(&ai[0])) - t1 := intrinsics.unaligned_load((^x86.__m128i)(&ai[16])) - update_hw_128l(st, t0, t1) -} - -@(private = "file", enable_target_feature = "sse2,aes") -absorb_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { - m := intrinsics.unaligned_load((^x86.__m128i)(&ai[0])) - update_hw_256(st, m) -} - -@(private, enable_target_feature = "sse2,aes") -absorb_hw :: proc "contextless" (st: ^State_HW, aad: []byte) #no_bounds_check { - ai, l := aad, len(aad) - - switch st.rate { - case _RATE_128L: - for l >= _RATE_128L { - absorb_hw_128l(st, ai) - ai = ai[_RATE_128L:] - l -= _RATE_128L - } - case _RATE_256: - for l >= _RATE_256 { - absorb_hw_256(st, ai) - - ai = ai[_RATE_256:] - l -= _RATE_256 - } - } - - // Pad out the remainder with `0`s till it is rate sized. - if l > 0 { - tmp: [_RATE_MAX]byte // AAD is not confidential. - copy(tmp[:], ai) - switch st.rate { - case _RATE_128L: - absorb_hw_128l(st, tmp[:]) - case _RATE_256: - absorb_hw_256(st, tmp[:]) - } - } -} - -@(private = "file", enable_target_feature = "sse2", require_results) -z_hw_128l :: #force_inline proc "contextless" (st: ^State_HW) -> (x86.__m128i, x86.__m128i) { - z0 := x86._mm_xor_si128( - st.s6, - x86._mm_xor_si128( - st.s1, - x86._mm_and_si128(st.s2, st.s3), - ), - ) - z1 := x86._mm_xor_si128( - st.s2, - x86._mm_xor_si128( - st.s5, - x86._mm_and_si128(st.s6, st.s7), - ), - ) - return z0, z1 -} - -@(private = "file", enable_target_feature = "sse2", require_results) -z_hw_256 :: #force_inline proc "contextless" (st: ^State_HW) -> x86.__m128i { - return x86._mm_xor_si128( - st.s1, - x86._mm_xor_si128( - st.s4, - x86._mm_xor_si128( - st.s5, - x86._mm_and_si128(st.s2, st.s3), - ), - ), - ) -} - -@(private = "file", enable_target_feature = "sse2,aes") -enc_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { - z0, z1 := z_hw_128l(st) - - t0 := intrinsics.unaligned_load((^x86.__m128i)(&xi[0])) - t1 := intrinsics.unaligned_load((^x86.__m128i)(&xi[16])) - update_hw_128l(st, t0, t1) - - out0 := x86._mm_xor_si128(t0, z0) - out1 := x86._mm_xor_si128(t1, z1) - intrinsics.unaligned_store((^x86.__m128i)(&ci[0]), out0) - intrinsics.unaligned_store((^x86.__m128i)(&ci[16]), out1) -} - -@(private = "file", enable_target_feature = "sse2,aes") -enc_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { - z := z_hw_256(st) - - xi_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(xi))) - update_hw_256(st, xi_) - - ci_ := x86._mm_xor_si128(xi_, z) - intrinsics.unaligned_store((^x86.__m128i)(raw_data(ci)), ci_) -} - -@(private, enable_target_feature = "sse2,aes") -enc_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { - ci, xi, l := dst, src, len(src) - - switch st.rate { - case _RATE_128L: - for l >= _RATE_128L { - enc_hw_128l(st, ci, xi) - ci = ci[_RATE_128L:] - xi = xi[_RATE_128L:] - l -= _RATE_128L - } - case _RATE_256: - for l >= _RATE_256 { - enc_hw_256(st, ci, xi) - ci = ci[_RATE_256:] - xi = xi[_RATE_256:] - l -= _RATE_256 - } - } - - // Pad out the remainder with `0`s till it is rate sized. - if l > 0 { - tmp: [_RATE_MAX]byte // Ciphertext is not confidential. - copy(tmp[:], xi) - switch st.rate { - case _RATE_128L: - enc_hw_128l(st, tmp[:], tmp[:]) - case _RATE_256: - enc_hw_256(st, tmp[:], tmp[:]) - } - copy(ci, tmp[:l]) - } -} - -@(private = "file", enable_target_feature = "sse2,aes") -dec_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { - z0, z1 := z_hw_128l(st) - - t0 := intrinsics.unaligned_load((^x86.__m128i)(&ci[0])) - t1 := intrinsics.unaligned_load((^x86.__m128i)(&ci[16])) - out0 := x86._mm_xor_si128(t0, z0) - out1 := x86._mm_xor_si128(t1, z1) - - update_hw_128l(st, out0, out1) - intrinsics.unaligned_store((^x86.__m128i)(&xi[0]), out0) - intrinsics.unaligned_store((^x86.__m128i)(&xi[16]), out1) -} - -@(private = "file", enable_target_feature = "sse2,aes") -dec_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { - z := z_hw_256(st) - - ci_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(ci))) - xi_ := x86._mm_xor_si128(ci_, z) - - update_hw_256(st, xi_) - intrinsics.unaligned_store((^x86.__m128i)(raw_data(xi)), xi_) -} - -@(private = "file", enable_target_feature = "sse2,aes") -dec_partial_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { - tmp: [_RATE_128L]byte - defer mem.zero_explicit(&tmp, size_of(tmp)) - - z0, z1 := z_hw_128l(st) - copy(tmp[:], cn) - - t0 := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) - t1 := intrinsics.unaligned_load((^x86.__m128i)(&tmp[16])) - out0 := x86._mm_xor_si128(t0, z0) - out1 := x86._mm_xor_si128(t1, z1) - - intrinsics.unaligned_store((^x86.__m128i)(&tmp[0]), out0) - intrinsics.unaligned_store((^x86.__m128i)(&tmp[16]), out1) - copy(xn, tmp[:]) - - for off := len(xn); off < _RATE_128L; off += 1 { - tmp[off] = 0 - } - out0 = intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) // v0 - out1 = intrinsics.unaligned_load((^x86.__m128i)(&tmp[16])) // v1 - update_hw_128l(st, out0, out1) -} - -@(private = "file", enable_target_feature = "sse2,aes") -dec_partial_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { - tmp: [_RATE_256]byte - defer mem.zero_explicit(&tmp, size_of(tmp)) - - z := z_hw_256(st) - copy(tmp[:], cn) - - cn_ := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) - xn_ := x86._mm_xor_si128(cn_, z) - - intrinsics.unaligned_store((^x86.__m128i)(&tmp[0]), xn_) - copy(xn, tmp[:]) - - for off := len(xn); off < _RATE_256; off += 1 { - tmp[off] = 0 - } - xn_ = intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) - update_hw_256(st, xn_) -} - -@(private, enable_target_feature = "sse2,aes") -dec_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { - xi, ci, l := dst, src, len(src) - - switch st.rate { - case _RATE_128L: - for l >= _RATE_128L { - dec_hw_128l(st, xi, ci) - xi = xi[_RATE_128L:] - ci = ci[_RATE_128L:] - l -= _RATE_128L - } - case _RATE_256: - for l >= _RATE_256 { - dec_hw_256(st, xi, ci) - xi = xi[_RATE_256:] - ci = ci[_RATE_256:] - l -= _RATE_256 - } - } - - // Process the remainder. - if l > 0 { - switch st.rate { - case _RATE_128L: - dec_partial_hw_128l(st, xi, ci) - case _RATE_256: - dec_partial_hw_256(st, xi, ci) - } - } -} - -@(private, enable_target_feature = "sse2,aes") -finalize_hw :: proc "contextless" (st: ^State_HW, tag: []byte, ad_len, msg_len: int) { - tmp: [16]byte - endian.unchecked_put_u64le(tmp[0:], u64(ad_len) * 8) - endian.unchecked_put_u64le(tmp[8:], u64(msg_len) * 8) - - t := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) - - t0, t1: x86.__m128i = ---, --- - switch st.rate { - case _RATE_128L: - t = x86._mm_xor_si128(st.s2, t) - for _ in 0 ..< 7 { - update_hw_128l(st, t, t) - } - - t0 = x86._mm_xor_si128(st.s0, st.s1) - t0 = x86._mm_xor_si128(t0, st.s2) - t0 = x86._mm_xor_si128(t0, st.s3) - - t1 = x86._mm_xor_si128(st.s4, st.s5) - t1 = x86._mm_xor_si128(t1, st.s6) - if len(tag) == TAG_SIZE_256 { - t1 = x86._mm_xor_si128(t1, st.s7) - } - case _RATE_256: - t = x86._mm_xor_si128(st.s3, t) - for _ in 0 ..< 7 { - update_hw_256(st, t) - } - - t0 = x86._mm_xor_si128(st.s0, st.s1) - t0 = x86._mm_xor_si128(t0, st.s2) - - t1 = x86._mm_xor_si128(st.s3, st.s4) - t1 = x86._mm_xor_si128(t1, st.s5) - } - switch len(tag) { - case TAG_SIZE_128: - t0 = x86._mm_xor_si128(t0, t1) - intrinsics.unaligned_store((^x86.__m128i)(&tag[0]), t0) - case TAG_SIZE_256: - intrinsics.unaligned_store((^x86.__m128i)(&tag[0]), t0) - intrinsics.unaligned_store((^x86.__m128i)(&tag[16]), t1) - } -} - -@(private) -reset_state_hw :: proc "contextless" (st: ^State_HW) { - mem.zero_explicit(st, size_of(st^)) -} diff --git a/core/crypto/aes/aes.odin b/core/crypto/aes/aes.odin index 57f49acf4..661acd88f 100644 --- a/core/crypto/aes/aes.odin +++ b/core/crypto/aes/aes.odin @@ -1,5 +1,5 @@ /* -package aes implements the AES block cipher and some common modes. +The `AES` block cipher and some common modes. See: - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]] diff --git a/core/crypto/aes/aes_ctr.odin b/core/crypto/aes/aes_ctr.odin index a74133235..9d7a0b80b 100644 --- a/core/crypto/aes/aes_ctr.odin +++ b/core/crypto/aes/aes_ctr.odin @@ -4,7 +4,6 @@ import "core:bytes" import "core:crypto/_aes/ct64" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // CTR_IV_SIZE is the size of the CTR mode IV in bytes. CTR_IV_SIZE :: 16 @@ -117,7 +116,7 @@ reset_ctr :: proc "contextless" (ctx: ^Context_CTR) { ctx._off = 0 ctx._ctr_hi = 0 ctx._ctr_lo = 0 - mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer)) + zero_explicit(&ctx._buffer, size_of(ctx._buffer)) ctx._is_initialized = false } @@ -172,7 +171,7 @@ ctr_blocks :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_boun // Write back the counter. ctx._ctr_hi, ctx._ctr_lo = ctr_hi, ctr_lo - mem.zero_explicit(&tmp, size_of(tmp)) + zero_explicit(&tmp, size_of(tmp)) } @(private) diff --git a/core/crypto/aes/aes_ctr_hw_intel.odin b/core/crypto/aes/aes_ctr_hw.odin similarity index 60% rename from core/crypto/aes/aes_ctr_hw_intel.odin rename to core/crypto/aes/aes_ctr_hw.odin index 415758b24..859b63a40 100644 --- a/core/crypto/aes/aes_ctr_hw_intel.odin +++ b/core/crypto/aes/aes_ctr_hw.odin @@ -1,31 +1,32 @@ -#+build amd64 +#+build amd64,arm64,arm32 package aes import "base:intrinsics" import "core:crypto/_aes" +import aes_hw "core:crypto/_aes/hw" +import "core:encoding/endian" import "core:math/bits" -import "core:mem" -import "core:simd/x86" +import "core:simd" @(private) CTR_STRIDE_HW :: 4 @(private) CTR_STRIDE_BYTES_HW :: CTR_STRIDE_HW * BLOCK_SIZE -@(private, enable_target_feature = "sse2,aes") +@(private, enable_target_feature = aes_hw.TARGET_FEATURES) ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_bounds_check { hw_ctx := ctx._impl.(Context_Impl_Hardware) - sks: [15]x86.__m128i = --- + sks: [15]simd.u8x16 = --- for i in 0 ..= hw_ctx._num_rounds { - sks[i] = intrinsics.unaligned_load((^x86.__m128i)(&hw_ctx._sk_exp_enc[i])) + sks[i] = intrinsics.unaligned_load((^simd.u8x16)(&hw_ctx._sk_exp_enc[i])) } - hw_inc_ctr := #force_inline proc "contextless" (hi, lo: u64) -> (x86.__m128i, u64, u64) { - ret := x86.__m128i{ - i64(intrinsics.byte_swap(hi)), - i64(intrinsics.byte_swap(lo)), - } + hw_inc_ctr := #force_inline proc "contextless" (hi, lo: u64) -> (simd.u8x16, u64, u64) { + buf: [BLOCK_SIZE]byte = --- + endian.unchecked_put_u64be(buf[0:], hi) + endian.unchecked_put_u64be(buf[8:], lo) + ret := intrinsics.unaligned_load((^simd.u8x16)(&buf)) hi, lo := hi, lo carry: u64 @@ -47,42 +48,42 @@ ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_b nr_blocks := nr_blocks ctr_hi, ctr_lo := ctx._ctr_hi, ctx._ctr_lo - blks: [CTR_STRIDE_HW]x86.__m128i = --- + blks: [CTR_STRIDE_HW]simd.u8x16 = --- for nr_blocks >= CTR_STRIDE_HW { #unroll for i in 0..< CTR_STRIDE_HW { blks[i], ctr_hi, ctr_lo = hw_inc_ctr(ctr_hi, ctr_lo) } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_xor_si128(blks[i], sks[0]) + blks[i] = simd.bit_xor(blks[i], sks[0]) } #unroll for i in 1 ..= 9 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } switch hw_ctx._num_rounds { case _aes.ROUNDS_128: #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[10]) + blks[i] = aes_hw.aesenclast(blks[i], sks[10]) } case _aes.ROUNDS_192: #unroll for i in 10 ..= 11 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[12]) + blks[i] = aes_hw.aesenclast(blks[i], sks[12]) } case _aes.ROUNDS_256: #unroll for i in 10 ..= 13 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[14]) + blks[i] = aes_hw.aesenclast(blks[i], sks[14]) } } @@ -99,23 +100,23 @@ ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_b for nr_blocks > 0 { blks[0], ctr_hi, ctr_lo = hw_inc_ctr(ctr_hi, ctr_lo) - blks[0] = x86._mm_xor_si128(blks[0], sks[0]) + blks[0] = simd.bit_xor(blks[0], sks[0]) #unroll for i in 1 ..= 9 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } switch hw_ctx._num_rounds { case _aes.ROUNDS_128: - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[10]) + blks[0] = aes_hw.aesenclast(blks[0], sks[10]) case _aes.ROUNDS_192: #unroll for i in 10 ..= 11 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[12]) + blks[0] = aes_hw.aesenclast(blks[0], sks[12]) case _aes.ROUNDS_256: #unroll for i in 10 ..= 13 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[14]) + blks[0] = aes_hw.aesenclast(blks[0], sks[14]) } xor_blocks_hw(dst, src, blks[:1]) @@ -130,22 +131,22 @@ ctr_blocks_hw :: proc(ctx: ^Context_CTR, dst, src: []byte, nr_blocks: int) #no_b // Write back the counter. ctx._ctr_hi, ctx._ctr_lo = ctr_hi, ctr_lo - mem.zero_explicit(&blks, size_of(blks)) - mem.zero_explicit(&sks, size_of(sks)) + zero_explicit(&blks, size_of(blks)) + zero_explicit(&sks, size_of(sks)) } -@(private, enable_target_feature = "sse2") -xor_blocks_hw :: proc(dst, src: []byte, blocks: []x86.__m128i) { +@(private, enable_target_feature = aes_hw.TARGET_FEATURES) +xor_blocks_hw :: proc(dst, src: []byte, blocks: []simd.u8x16) { #no_bounds_check { if src != nil { for i in 0 ..< len(blocks) { off := i * BLOCK_SIZE - tmp := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[off:]))) - blocks[i] = x86._mm_xor_si128(blocks[i], tmp) + tmp := intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[off:]))) + blocks[i] = simd.bit_xor(blocks[i], tmp) } } for i in 0 ..< len(blocks) { - intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst[i * BLOCK_SIZE:])), blocks[i]) + intrinsics.unaligned_store((^simd.u8x16)(raw_data(dst[i * BLOCK_SIZE:])), blocks[i]) } } } diff --git a/core/crypto/aes/aes_ecb.odin b/core/crypto/aes/aes_ecb.odin index cac62de5d..9ec1a9a37 100644 --- a/core/crypto/aes/aes_ecb.odin +++ b/core/crypto/aes/aes_ecb.odin @@ -21,7 +21,7 @@ init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := DEFAULT_IMPLEMENTATION) encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { ensure(ctx._is_initialized) ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size") - ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size") + ensure(len(src) == BLOCK_SIZE, "crypto/aes: invalid src size") switch &impl in ctx._impl { case ct64.Context: @@ -35,7 +35,7 @@ encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { decrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { ensure(ctx._is_initialized) ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size") - ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size") + ensure(len(src) == BLOCK_SIZE, "crypto/aes: invalid src size") switch &impl in ctx._impl { case ct64.Context: diff --git a/core/crypto/aes/aes_ecb_hw.odin b/core/crypto/aes/aes_ecb_hw.odin new file mode 100644 index 000000000..87a006d9b --- /dev/null +++ b/core/crypto/aes/aes_ecb_hw.odin @@ -0,0 +1,59 @@ +#+build amd64,arm64,arm32 +package aes + +import "base:intrinsics" +import "core:crypto/_aes" +import aes_hw "core:crypto/_aes/hw" +import "core:simd" + +@(private, enable_target_feature = aes_hw.TARGET_FEATURES) +encrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) { + blk := intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))) + + blk = simd.bit_xor(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[0]))) + #unroll for i in 1 ..= 9 { + blk = aes_hw.aesenc(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[i]))) + } + switch ctx._num_rounds { + case _aes.ROUNDS_128: + blk = aes_hw.aesenclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[10]))) + case _aes.ROUNDS_192: + #unroll for i in 10 ..= 11 { + blk = aes_hw.aesenc(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[i]))) + } + blk = aes_hw.aesenclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[12]))) + case _aes.ROUNDS_256: + #unroll for i in 10 ..= 13 { + blk = aes_hw.aesenc(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[i]))) + } + blk = aes_hw.aesenclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[14]))) + } + + intrinsics.unaligned_store((^simd.u8x16)(raw_data(dst)), blk) +} + +@(private, enable_target_feature = aes_hw.TARGET_FEATURES) +decrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) { + blk := intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))) + + blk = simd.bit_xor(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[0]))) + #unroll for i in 1 ..= 9 { + blk = aes_hw.aesdec(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[i]))) + } + switch ctx._num_rounds { + case _aes.ROUNDS_128: + blk = aes_hw.aesdeclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[10]))) + case _aes.ROUNDS_192: + #unroll for i in 10 ..= 11 { + blk = aes_hw.aesdec(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[i]))) + } + blk = aes_hw.aesdeclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[12]))) + case _aes.ROUNDS_256: + #unroll for i in 10 ..= 13 { + blk = aes_hw.aesdec(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[i]))) + } + blk = aes_hw.aesdeclast(blk, intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_dec[14]))) + } + + intrinsics.unaligned_store((^simd.u8x16)(raw_data(dst)), blk) +} diff --git a/core/crypto/aes/aes_ecb_hw_intel.odin b/core/crypto/aes/aes_ecb_hw_intel.odin deleted file mode 100644 index f1d44a25f..000000000 --- a/core/crypto/aes/aes_ecb_hw_intel.odin +++ /dev/null @@ -1,58 +0,0 @@ -#+build amd64 -package aes - -import "base:intrinsics" -import "core:crypto/_aes" -import "core:simd/x86" - -@(private, enable_target_feature = "sse2,aes") -encrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) { - blk := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))) - - blk = x86._mm_xor_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[0]))) - #unroll for i in 1 ..= 9 { - blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i]))) - } - switch ctx._num_rounds { - case _aes.ROUNDS_128: - blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[10]))) - case _aes.ROUNDS_192: - #unroll for i in 10 ..= 11 { - blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i]))) - } - blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[12]))) - case _aes.ROUNDS_256: - #unroll for i in 10 ..= 13 { - blk = x86._mm_aesenc_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i]))) - } - blk = x86._mm_aesenclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[14]))) - } - - intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst)), blk) -} - -@(private, enable_target_feature = "sse2,aes") -decrypt_block_hw :: proc(ctx: ^Context_Impl_Hardware, dst, src: []byte) { - blk := intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))) - - blk = x86._mm_xor_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[0]))) - #unroll for i in 1 ..= 9 { - blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i]))) - } - switch ctx._num_rounds { - case _aes.ROUNDS_128: - blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[10]))) - case _aes.ROUNDS_192: - #unroll for i in 10 ..= 11 { - blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i]))) - } - blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[12]))) - case _aes.ROUNDS_256: - #unroll for i in 10 ..= 13 { - blk = x86._mm_aesdec_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[i]))) - } - blk = x86._mm_aesdeclast_si128(blk, intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_dec[14]))) - } - - intrinsics.unaligned_store((^x86.__m128i)(raw_data(dst)), blk) -} diff --git a/core/crypto/aes/aes_gcm.odin b/core/crypto/aes/aes_gcm.odin index d349aa353..531844a32 100644 --- a/core/crypto/aes/aes_gcm.odin +++ b/core/crypto/aes/aes_gcm.odin @@ -4,8 +4,8 @@ import "core:bytes" import "core:crypto" import "core:crypto/_aes" import "core:crypto/_aes/ct64" +import aes_hw "core:crypto/_aes/hw" import "core:encoding/endian" -import "core:mem" // GCM_IV_SIZE is the default size of the GCM IV in bytes. GCM_IV_SIZE :: 12 @@ -27,6 +27,10 @@ Context_GCM :: struct { // init_gcm initializes a Context_GCM with the provided key. init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := DEFAULT_IMPLEMENTATION) { + when aes_hw.HAS_GHASH { + impl := aes_hw.is_ghash_supported() ? impl : .Portable + + } init_impl(&ctx._impl, key, impl) ctx._is_initialized = true } @@ -59,14 +63,14 @@ seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) { final_ghash_ct64(&s, &h, &j0_enc, len(aad), len(plaintext)) copy(tag, s[:]) - mem.zero_explicit(&h, len(h)) - mem.zero_explicit(&j0, len(j0)) - mem.zero_explicit(&j0_enc, len(j0_enc)) + zero_explicit(&h, len(h)) + zero_explicit(&j0, len(j0)) + zero_explicit(&j0_enc, len(j0_enc)) } // open_gcm authenticates the aad and ciphertext, and decrypts the ciphertext, // with the provided Context_GCM, iv, and tag, and stores the output in dst, -// returning true iff the authentication was successful. If authentication +// returning true if and only if (⟺) the authentication was successful. If authentication // fails, the destination buffer will be zeroed. // // dst and plaintext MUST alias exactly or not at all. @@ -94,13 +98,13 @@ open_gcm :: proc(ctx: ^Context_GCM, dst, iv, aad, ciphertext, tag: []byte) -> bo ok := crypto.compare_constant_time(s[:], tag) == 1 if !ok { - mem.zero_explicit(raw_data(dst), len(dst)) + zero_explicit(raw_data(dst), len(dst)) } - mem.zero_explicit(&h, len(h)) - mem.zero_explicit(&j0, len(j0)) - mem.zero_explicit(&j0_enc, len(j0_enc)) - mem.zero_explicit(&s, len(s)) + zero_explicit(&h, len(h)) + zero_explicit(&j0, len(j0)) + zero_explicit(&j0_enc, len(j0_enc)) + zero_explicit(&s, len(s)) return ok } @@ -249,6 +253,6 @@ gctr_ct64 :: proc( } } - mem.zero_explicit(&tmp, size_of(tmp)) - mem.zero_explicit(&tmp2, size_of(tmp2)) + zero_explicit(&tmp, size_of(tmp)) + zero_explicit(&tmp2, size_of(tmp2)) } diff --git a/core/crypto/aes/aes_gcm_hw_intel.odin b/core/crypto/aes/aes_gcm_hw.odin similarity index 59% rename from core/crypto/aes/aes_gcm_hw_intel.odin rename to core/crypto/aes/aes_gcm_hw.odin index 3982d1452..13c035a20 100644 --- a/core/crypto/aes/aes_gcm_hw_intel.odin +++ b/core/crypto/aes/aes_gcm_hw.odin @@ -1,13 +1,13 @@ -#+build amd64 +#+build amd64,arm64,arm32 package aes import "base:intrinsics" import "core:crypto" import "core:crypto/_aes" -import "core:crypto/_aes/hw_intel" +@(require) import "core:crypto/_aes/ct64" +import aes_hw "core:crypto/_aes/hw" import "core:encoding/endian" -import "core:mem" -import "core:simd/x86" +import "core:simd" @(private) gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, iv, aad, plaintext: []byte) { @@ -18,14 +18,18 @@ gcm_seal_hw :: proc(ctx: ^Context_Impl_Hardware, dst, tag, iv, aad, plaintext: [ init_ghash_hw(ctx, &h, &j0, &j0_enc, iv) // Note: Our GHASH implementation handles appending padding. - hw_intel.ghash(s[:], h[:], aad) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], aad) + } else { + ct64.ghash(s[:], h[:], aad) + } gctr_hw(ctx, dst, &s, plaintext, &h, &j0, true) final_ghash_hw(&s, &h, &j0_enc, len(aad), len(plaintext)) copy(tag, s[:]) - mem.zero_explicit(&h, len(h)) - mem.zero_explicit(&j0, len(j0)) - mem.zero_explicit(&j0_enc, len(j0_enc)) + zero_explicit(&h, len(h)) + zero_explicit(&j0, len(j0)) + zero_explicit(&j0_enc, len(j0_enc)) } @(private) @@ -36,19 +40,23 @@ gcm_open_hw :: proc(ctx: ^Context_Impl_Hardware, dst, iv, aad, ciphertext, tag: s: [_aes.GHASH_TAG_SIZE]byte init_ghash_hw(ctx, &h, &j0, &j0_enc, iv) - hw_intel.ghash(s[:], h[:], aad) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], aad) + } else { + ct64.ghash(s[:], h[:], aad) + } gctr_hw(ctx, dst, &s, ciphertext, &h, &j0, false) final_ghash_hw(&s, &h, &j0_enc, len(aad), len(ciphertext)) ok := crypto.compare_constant_time(s[:], tag) == 1 if !ok { - mem.zero_explicit(raw_data(dst), len(dst)) + zero_explicit(raw_data(dst), len(dst)) } - mem.zero_explicit(&h, len(h)) - mem.zero_explicit(&j0, len(j0)) - mem.zero_explicit(&j0_enc, len(j0_enc)) - mem.zero_explicit(&s, len(s)) + zero_explicit(&h, len(h)) + zero_explicit(&j0, len(j0)) + zero_explicit(&j0_enc, len(j0_enc)) + zero_explicit(&s, len(s)) return ok } @@ -72,18 +80,26 @@ init_ghash_hw :: proc( } else { // If len(IV) != 96, then let s = 128 ceil(len(IV)/128) - len(IV), // and let J0 = GHASHH(IV || 0^(s+64) || ceil(len(IV))^64). - hw_intel.ghash(j0[:], h[:], iv) + when aes_hw.HAS_GHASH { + aes_hw.ghash(j0[:], h[:], iv) + } else { + ct64.ghash(j0[:], h[:], iv) + } tmp: [_aes.GHASH_BLOCK_SIZE]byte endian.unchecked_put_u64be(tmp[8:], u64(l) * 8) - hw_intel.ghash(j0[:], h[:], tmp[:]) + when aes_hw.HAS_GHASH { + aes_hw.ghash(j0[:], h[:], tmp[:]) + } else { + ct64.ghash(j0[:], h[:], tmp[:]) + } } // ECB encrypt j0, so that we can just XOR with the tag. encrypt_block_hw(ctx, j0_enc[:], j0[:]) } -@(private = "file", enable_target_feature = "sse2") +@(private = "file", enable_target_feature = aes_hw.TARGET_FEATURES) final_ghash_hw :: proc( s: ^[_aes.GHASH_BLOCK_SIZE]byte, h: ^[_aes.GHASH_KEY_SIZE]byte, @@ -95,14 +111,18 @@ final_ghash_hw :: proc( endian.unchecked_put_u64be(blk[0:], u64(a_len) * 8) endian.unchecked_put_u64be(blk[8:], u64(t_len) * 8) - hw_intel.ghash(s[:], h[:], blk[:]) - j0_vec := intrinsics.unaligned_load((^x86.__m128i)(j0)) - s_vec := intrinsics.unaligned_load((^x86.__m128i)(s)) - s_vec = x86._mm_xor_si128(s_vec, j0_vec) - intrinsics.unaligned_store((^x86.__m128i)(s), s_vec) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], blk[:]) + } else { + ct64.ghash(s[:], h[:], blk[:]) + } + j0_vec := intrinsics.unaligned_load((^simd.u8x16)(j0)) + s_vec := intrinsics.unaligned_load((^simd.u8x16)(s)) + s_vec = simd.bit_xor(s_vec, j0_vec) + intrinsics.unaligned_store((^simd.u8x16)(s), s_vec) } -@(private = "file", enable_target_feature = "sse2,sse4.1,aes") +@(private = "file", enable_target_feature = aes_hw.TARGET_FEATURES) gctr_hw :: proc( ctx: ^Context_Impl_Hardware, dst: []byte, @@ -112,13 +132,13 @@ gctr_hw :: proc( iv: ^[_aes.GHASH_BLOCK_SIZE]byte, is_seal: bool, ) #no_bounds_check { - sks: [15]x86.__m128i = --- + sks: [15]simd.u8x16 = --- for i in 0 ..= ctx._num_rounds { - sks[i] = intrinsics.unaligned_load((^x86.__m128i)(&ctx._sk_exp_enc[i])) + sks[i] = intrinsics.unaligned_load((^simd.u8x16)(&ctx._sk_exp_enc[i])) } // Setup the counter block - ctr_blk := intrinsics.unaligned_load((^x86.__m128i)(iv)) + ctr_blk := intrinsics.unaligned_load((^simd.u8x16)(iv)) ctr := endian.unchecked_get_u32be(iv[GCM_IV_SIZE:]) + 1 src, dst := src, dst @@ -128,11 +148,15 @@ gctr_hw :: proc( // This results in an unreadable mess, so we opt for simplicity // as performance is adequate. - blks: [CTR_STRIDE_HW]x86.__m128i = --- + blks: [CTR_STRIDE_HW]simd.u8x16 = --- nr_blocks := len(src) / BLOCK_SIZE for nr_blocks >= CTR_STRIDE_HW { if !is_seal { - hw_intel.ghash(s[:], h[:], src[:CTR_STRIDE_BYTES_HW]) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], src[:CTR_STRIDE_BYTES_HW]) + } else { + ct64.ghash(s[:], h[:], src[:CTR_STRIDE_BYTES_HW]) + } } #unroll for i in 0 ..< CTR_STRIDE_HW { @@ -140,42 +164,46 @@ gctr_hw :: proc( } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_xor_si128(blks[i], sks[0]) + blks[i] = simd.bit_xor(blks[i], sks[0]) } #unroll for i in 1 ..= 9 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } switch ctx._num_rounds { case _aes.ROUNDS_128: #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[10]) + blks[i] = aes_hw.aesenclast(blks[i], sks[10]) } case _aes.ROUNDS_192: #unroll for i in 10 ..= 11 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[12]) + blks[i] = aes_hw.aesenclast(blks[i], sks[12]) } case _aes.ROUNDS_256: #unroll for i in 10 ..= 13 { #unroll for j in 0 ..< CTR_STRIDE_HW { - blks[j] = x86._mm_aesenc_si128(blks[j], sks[i]) + blks[j] = aes_hw.aesenc(blks[j], sks[i]) } } #unroll for i in 0 ..< CTR_STRIDE_HW { - blks[i] = x86._mm_aesenclast_si128(blks[i], sks[14]) + blks[i] = aes_hw.aesenclast(blks[i], sks[14]) } } xor_blocks_hw(dst, src, blks[:]) if is_seal { - hw_intel.ghash(s[:], h[:], dst[:CTR_STRIDE_BYTES_HW]) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], dst[:CTR_STRIDE_BYTES_HW]) + } else { + ct64.ghash(s[:], h[:], dst[:CTR_STRIDE_BYTES_HW]) + } } src = src[CTR_STRIDE_BYTES_HW:] @@ -187,28 +215,32 @@ gctr_hw :: proc( for n := len(src); n > 0; { l := min(n, BLOCK_SIZE) if !is_seal { - hw_intel.ghash(s[:], h[:], src[:l]) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], src[:l]) + } else { + ct64.ghash(s[:], h[:], src[:l]) + } } blks[0], ctr = hw_inc_ctr32(&ctr_blk, ctr) - blks[0] = x86._mm_xor_si128(blks[0], sks[0]) + blks[0] = simd.bit_xor(blks[0], sks[0]) #unroll for i in 1 ..= 9 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } switch ctx._num_rounds { case _aes.ROUNDS_128: - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[10]) + blks[0] = aes_hw.aesenclast(blks[0], sks[10]) case _aes.ROUNDS_192: #unroll for i in 10 ..= 11 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[12]) + blks[0] = aes_hw.aesenclast(blks[0], sks[12]) case _aes.ROUNDS_256: #unroll for i in 10 ..= 13 { - blks[0] = x86._mm_aesenc_si128(blks[0], sks[i]) + blks[0] = aes_hw.aesenc(blks[0], sks[i]) } - blks[0] = x86._mm_aesenclast_si128(blks[0], sks[14]) + blks[0] = aes_hw.aesenclast(blks[0], sks[14]) } if l == BLOCK_SIZE { @@ -220,7 +252,11 @@ gctr_hw :: proc( copy(dst, blk[:l]) } if is_seal { - hw_intel.ghash(s[:], h[:], dst[:l]) + when aes_hw.HAS_GHASH { + aes_hw.ghash(s[:], h[:], dst[:l]) + } else { + ct64.ghash(s[:], h[:], dst[:l]) + } } dst = dst[l:] @@ -228,16 +264,25 @@ gctr_hw :: proc( n -= l } - mem.zero_explicit(&blks, size_of(blks)) - mem.zero_explicit(&sks, size_of(sks)) + zero_explicit(&blks, size_of(blks)) + zero_explicit(&sks, size_of(sks)) } // BUG: Sticking this in gctr_hw (like the other implementations) crashes // the compiler. // // src/check_expr.cpp(8104): Assertion Failure: `c->curr_proc_decl->entity` -@(private = "file", enable_target_feature = "sse4.1") -hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^x86.__m128i, ctr: u32) -> (x86.__m128i, u32) { - ret := x86._mm_insert_epi32(src^, i32(intrinsics.byte_swap(ctr)), 3) +@(private = "file", enable_target_feature = aes_hw.TARGET_FEATURES) +hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^simd.u8x16, ctr: u32) -> (simd.u8x16, u32) { + when ODIN_ENDIAN == .Little { + ctr_be := intrinsics.byte_swap(ctr) + } else { + ctr_be := ctr + } + + ret := transmute(simd.u8x16)( + simd.replace(transmute(simd.u32x4)(src^), 3, ctr_be) + ) + return ret, ctr + 1 } diff --git a/core/crypto/aes/aes_impl.odin b/core/crypto/aes/aes_impl.odin index f26874809..b95abfaf0 100644 --- a/core/crypto/aes/aes_impl.odin +++ b/core/crypto/aes/aes_impl.odin @@ -1,9 +1,11 @@ package aes +import "core:crypto" import "core:crypto/_aes/ct64" -import "core:mem" import "core:reflect" +zero_explicit :: crypto.zero_explicit + @(private) Context_Impl :: union { ct64.Context, @@ -41,5 +43,5 @@ init_impl :: proc(ctx: ^Context_Impl, key: []byte, impl: Implementation) { @(private) reset_impl :: proc "contextless" (ctx: ^Context_Impl) { - mem.zero_explicit(ctx, size_of(Context_Impl)) -} + zero_explicit(ctx, size_of(Context_Impl)) +} \ No newline at end of file diff --git a/core/crypto/aes/aes_impl_hw.odin b/core/crypto/aes/aes_impl_hw.odin new file mode 100644 index 000000000..fe93966f8 --- /dev/null +++ b/core/crypto/aes/aes_impl_hw.odin @@ -0,0 +1,18 @@ +#+build amd64,arm64,arm32 +package aes + +import aes_hw "core:crypto/_aes/hw" + +// is_hardware_accelerated returns true if and only if (⟺) hardware accelerated AES +// is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return aes_hw.is_supported() +} + +@(private) +Context_Impl_Hardware :: aes_hw.Context + +@(private, enable_target_feature = aes_hw.TARGET_FEATURES) +init_impl_hw :: proc(ctx: ^Context_Impl_Hardware, key: []byte) { + aes_hw.init(ctx, key) +} diff --git a/core/crypto/aes/aes_impl_hw_gen.odin b/core/crypto/aes/aes_impl_hw_gen.odin index 0c9ec6edc..10b08b7b5 100644 --- a/core/crypto/aes/aes_impl_hw_gen.odin +++ b/core/crypto/aes/aes_impl_hw_gen.odin @@ -1,10 +1,12 @@ #+build !amd64 +#+build !arm64 +#+build !arm32 package aes @(private = "file") ERR_HW_NOT_SUPPORTED :: "crypto/aes: hardware implementation unsupported" -// is_hardware_accelerated returns true iff hardware accelerated AES +// is_hardware_accelerated returns true if and only if (⟺) hardware accelerated AES // is supported. is_hardware_accelerated :: proc "contextless" () -> bool { return false diff --git a/core/crypto/aes/aes_impl_hw_intel.odin b/core/crypto/aes/aes_impl_hw_intel.odin deleted file mode 100644 index 0f1fa6143..000000000 --- a/core/crypto/aes/aes_impl_hw_intel.odin +++ /dev/null @@ -1,18 +0,0 @@ -#+build amd64 -package aes - -import "core:crypto/_aes/hw_intel" - -// is_hardware_accelerated returns true iff hardware accelerated AES -// is supported. -is_hardware_accelerated :: proc "contextless" () -> bool { - return hw_intel.is_supported() -} - -@(private) -Context_Impl_Hardware :: hw_intel.Context - -@(private, enable_target_feature = "sse2,aes") -init_impl_hw :: proc(ctx: ^Context_Impl_Hardware, key: []byte) { - hw_intel.init(ctx, key) -} diff --git a/core/crypto/argon2id/argon2id.odin b/core/crypto/argon2id/argon2id.odin new file mode 100644 index 000000000..e2f5e487b --- /dev/null +++ b/core/crypto/argon2id/argon2id.odin @@ -0,0 +1,622 @@ +/* +package argon2id implements the Argon2id password hashing algorithm. + +See: [[ https://datatracker.ietf.org/doc/rfc9106/ ]] +*/ +package argon2id + +import "core:crypto/blake2b" +import "core:encoding/endian" +import "core:math/bits" +import "core:mem" + +// Implementation based on the RFC, Monocypher (CC0-1.0), and the reference +// code (CC0-1.0). + +// MAX_INPUT_SIZE is the mamximum size of the various inputs (password, +// salt, secret, ad) in bytes. +MAX_INPUT_SIZE :: (1 << 32) - 1 + +// MIN_PARALLELISM is the minimum allowed parallelism. +MIN_PARALLELISM :: 1 +// MAX_PARALLELISM is the maximum allowed parallelism. +MAX_PARALLELISM :: (1 << 24) - 1 + +// MIN_TAG_SIZE is the minimum digest size in bytes. +MIN_TAG_SIZE :: 4 +// MAX_TAG_SIZE is the maximum digest size in bytes. +MAX_TAG_SIZE :: (1 << 32) - 1 + +// RECOMMENDED_TAG_SIZE is the recommended tag size in bytes. +RECOMMENTED_TAG_SIZE :: 32 // 256-bits +// RECOMMENDNED_SALT_SIZE is the recommended salt size in bytes. +RECOMMENDED_SALT_SIZE :: 16 // 128-bits + +@(private) +V_RFC9106 :: 0x13 +@(private) +Y_ID :: 0x02 +@(private) +BLOCK_SIZE_BYTES :: 1024 +@(private) +BLOCK_SIZE_U64 :: 128 + +// PARAMS_RFC9106 is the first recommended "uniformly safe" parameter set +// per RFC 9106. +@(rodata) +PARAMS_RFC9106 := Parameters{ + memory_size = 2 * 1024 * 1024, // 2 GiB + passes = 1, + parallelism = 4, +} + +// PARAMS_RFC9106_SMALL is the second recommended "uniformly safe" parameter +// set per RFC 9106 tailored for memory constrained environments. +@(rodata) +PARAMS_RFC9106_SMALL := Parameters{ + memory_size = 64 * 1024, // 64 MiB + passes = 3, + parallelism = 4, +} + +// PARAMS_OWASP is one of the recommended parameter set from the OWASP +// Password Storage Cheat Sheet (as of 2026/02). The cheat sheet contains +// additional variations to this parameter set with various trade-offs +// between `memory_size` and `passes` that are intended to provide +// equivalent security. +// +// See: [[ https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html ]] +@(rodata) +PARAMS_OWASP := Parameters{ + memory_size = 19 * 1024, // 19 MiB + passes = 2, + parallelism = 1, +} + +// PARAMS_OWASP_SMALL is equivalent in strength to PARAMS_OWASP, but +// trades off less memory use for more CPU usage. +@(rodata) +PARAMS_OWASP_SMALL := Parameters{ + memory_size = 7 * 1024, // 7 MiB + passes = 5, + parallelism = 1, +} + +// Parameters is an Argon2id parameter set. +Parameters :: struct { + memory_size: u32, // m (KiB) + passes: u32, // t + parallelism: u32, // p +} + +@(private) +Block :: [BLOCK_SIZE_U64]u64 + +// derive invokes Argon2id with the specified parameter set and inputs, +// and outputs the derived key to dst. +@(require_results) +derive :: proc( + parameters: ^Parameters, + password: []byte, // P + salt: []byte, // S + dst: []byte, + secret: []byte = nil, // K (aka `pepper`) + ad: []byte = nil, // X + sanitize := true, + allocator := context.allocator, // Not temp as this can be large. +) -> mem.Allocator_Error #no_bounds_check { + if u64(len(password)) > MAX_INPUT_SIZE { + panic("crypto/argon2id: invalid password size") + } + if u64(len(salt)) > MAX_INPUT_SIZE { + panic("crypto/argon2id: invalid salt size") + } + if u64(len(secret)) > MAX_INPUT_SIZE { + panic("crypto/argon2id: invalid secret size") + } + if u64(len(ad)) > MAX_INPUT_SIZE { + panic("crypto/argon2id: invalid ad size") + } + if l := u64(len(dst)); l > MAX_TAG_SIZE || l < MIN_TAG_SIZE { + panic("crypto/argon2id: invalid dst size") + } + + p, t, m := parameters.parallelism, parameters.passes, u64(parameters.memory_size) + if p < MIN_PARALLELISM || p > MAX_PARALLELISM { + panic("crypto/argon2id: invalid parallelism") + } + if t < 1 { + panic("crypto/argon2id: invalid passes") + } + if m < 8 * u64(p) { + panic("crypto/argon2id: insufficient memory size") + } + if m * BLOCK_SIZE_BYTES > u64(max(int)) { + panic("crypto/argon2id: excessive memory size") + } + + // Allocate the memory as m' 1024-byte blocks, where m' is derived as: + // m' = 4 * p * floor (m / 4p) + // + // For p lanes, the memory is organized in a matrix B[i][j] of + // blocks with p rows (lanes) and q = m' / p columns. + m_ := 4 * u64(p) * (m / u64(4 * p)) + b := mem.alloc_bytes_non_zeroed( + int(m_) * BLOCK_SIZE_BYTES, + alignment = mem.PAGE_SIZE, + allocator = allocator, + ) or_return + defer delete(b, allocator) + + block_buf: [BLOCK_SIZE_BYTES]byte = --- + + blocks := ([^]Block)(raw_data(b))[:m_] + segment_size := u32(m_ / u64(p) / 4) + lane_size := segment_size * 4 + + // Establish H_0 as the 64-byte value as shown below. If K, X, or S + // has zero length, it is just absent, but its length field remains. + // + // H_0 = H^(64)(LE32(p) || LE32(T) || LE32(m) || LE32(t) || + // LE32(v) || LE32(y) || LE32(length(P)) || P || + // LE32(length(S)) || S || LE32(length(K)) || K || + // LE32(length(X)) || X) + { + ctx: blake2b.Context + blake2b.init(&ctx) + + blake2b_update_u32le(&ctx, u32(p)) + blake2b_update_u32le(&ctx, u32(len(dst))) + blake2b_update_u32le(&ctx, parameters.memory_size) + blake2b_update_u32le(&ctx, t) + blake2b_update_u32le(&ctx, V_RFC9106) + blake2b_update_u32le(&ctx, Y_ID) + blake2b_update_u32le(&ctx, u32(len(password))) + blake2b.update(&ctx, password) + blake2b_update_u32le(&ctx, u32(len(salt))) + blake2b.update(&ctx, salt) + blake2b_update_u32le(&ctx, u32(len(secret))) + blake2b.update(&ctx, secret) + blake2b_update_u32le(&ctx, u32(len(ad))) + blake2b.update(&ctx, ad) + + h_0: [blake2b.DIGEST_SIZE+8]byte + blake2b.final(&ctx, h_0[:blake2b.DIGEST_SIZE]) + + // Compute B[i][0] for all i ranging from (and including) 0 to (not + // including) p. + // + // B[i][0] = H'^(1024)(H_0 || LE32(0) || LE32(i)) + // + // Compute B[i][1] for all i ranging from (and including) 0 to (not + // including) p. + // + // B[i][1] = H'^(1024)(H_0 || LE32(1) || LE32(i)) + for l in u32(0) ..< p { + for i in u32(0) ..< 2 { + endian.unchecked_put_u32le(h_0[blake2b.DIGEST_SIZE:], i) // LE32({0,1}) + endian.unchecked_put_u32le(h_0[blake2b.DIGEST_SIZE+4:], l) // LE32(i) + h_prime(block_buf[:], h_0[:]) + blk := &blocks[l * lane_size + i] + for j in 0 ..< BLOCK_SIZE_U64 { + blk[j] = endian.unchecked_get_u64le(block_buf[j*8:]) + } + } + } + + mem.zero_explicit(&h_0, size_of(h_0)) // No longer needed. + } + + // Compute B[i][j] for all i ranging from (and including) 0 to (not + // including) p and for all j ranging from (and including) 2 to (not + // including) q. The computation MUST proceed slicewise + // (Section 3.4): first, blocks from slice 0 are computed for all + // lanes (in an arbitrary order of lanes), then blocks from slice 1 + // are computed, etc. The block indices l and z are determined for + // each i, j differently for Argon2d, Argon2i, and Argon2id. + // + // B[i][j] = G(B[i][j-1], B[l][z]) + // + // If the number of passes t is larger than 1, we repeat step 5. We + // compute B[i][0] and B[i][j] for all i raging from (and including) + // 0 to (not including) p and for all j ranging from (and including) + // 1 to (not including) q. However, blocks are computed differently + // as the old value is XORed with the new one: + // + // B[i][0] = G(B[i][q-1], B[l][z]) XOR B[i][0]; + // B[i][j] = G(B[i][j-1], B[l][z]) XOR B[i][j]. + constant_time := true // Start with constant time indexing. + tmp, index_block: Block = ---, --- + for pass in u32(0) ..< t { + for slice in u32(0) ..< 4 { + // The first slice of the first pass has blocks 0 and 1 + // pre-filled. + pass_offset: u32 = pass == 0 && slice == 0 ? 2 : 0 + slice_offset := slice * segment_size + + // 3.4.1.3. Argon2id + // + // If the pass number is 0 and the slice number is 0 or 1, then compute + // J_1 and J_2 as for Argon2i, else compute J_1 and J_2 as for Argon2d. + if slice == 2 { + constant_time = false + } + + // Each segment can be processed in parallel, as long as + // each iteration of the loop completes before proceeding + // to the next. For simplicity we do this in serial + // instead of using threads. + for segment in u32(0) ..< u32(p) { + index_ctr: u64 = 1 + for block in pass_offset ..< segment_size { + // Current and previous blocks (indexes, not pointers) + lane_offset := segment * lane_size + segment_start := lane_offset + slice_offset + current := segment_start + block + previous := segment_start - 1 + switch { + case block == 0 && slice_offset == 0: + previous += lane_size + case: + previous += block + } + + index_seed: u64 + if constant_time { + // 3.4.1.2. Argon2i + // + // For each segment, we do the following. First, we compute the value Z + // as: + // + // Z= ( LE64(r) || LE64(l) || LE64(sl) || LE64(m') || + // LE64(t) || LE64(y) ) + // + // Figure 11: Input to Compute J1,J2 in Argon2i + // + // where + // + // r: the pass number + // l: the lane number + // sl: the slice number + // m': the total number of memory blocks + // t: the total number of passes + // y: the Argon2 type (0 for Argon2d, 1 for Argon2i, 2 for Argon2id) + // + // Then we compute: + // + // q/(128*SL) 1024-byte values + // G(ZERO(1024),G(ZERO(1024), + // Z || LE64(1) || ZERO(968) )), + // G(ZERO(1024),G(ZERO(1024), + // Z || LE64(2) || ZERO(968) )),... , + // G(ZERO(1024),G(ZERO(1024), + // Z || LE64(q/(128*SL)) || ZERO(968) )), + // + // which are partitioned into q/(SL) 8-byte values X, which are viewed + // as X1||X2 and converted to J_1=int32(X1) and J_2=int32(X2). + // + // The values r, l, sl, m', t, y, and i are represented as 8 bytes in + // little endian. + if block == pass_offset || (block % 128) == 0 { + mem.zero(&index_block, size_of(index_block)) + index_block[0] = u64(pass) + index_block[1] = u64(segment) + index_block[2] = u64(slice) + index_block[3] = u64(lane_size * p) + index_block[4] = u64(t) // passes + index_block[5] = Y_ID + index_block[6] = index_ctr + index_ctr += 1 + + copy(tmp[:], index_block[:]) + g_rounds(&index_block) + xor_block(&index_block, &tmp) + copy(tmp[:], index_block[:]) + g_rounds(&index_block) + xor_block(&index_block, &tmp) + } + index_seed = index_block[block % 128] + } else { + // 3.4.1.1. Argon2d + // + // J_1 is given by the first 32 bits of block B[i][j-1], while J_2 is + // given by the next 32 bits of block B[i][j-1]: + // + // J_1 = int32(extract(B[i][j-1], 0)) + // J_2 = int32(extract(B[i][j-1], 1)) + // + // Figure 10: Deriving J1,J2 in Argon2d + index_seed = blocks[previous][0] + } + + // 3.4.2. Mapping J_1 and J_2 to Reference Block Index [l][z] + // + // The value of l = J_2 mod p gives the index of the lane from which the + // block will be taken. For the first pass (r=0) and the first slice + // (sl=0), the block is taken from the current lane. + // + // The set W contains the indices that are referenced according to the + // following rules: + // + // 1. If l is the current lane, then W includes the indices of all + // blocks in the last SL - 1 = 3 segments computed and finished, as + // well as the blocks computed in the current segment in the current + // pass excluding B[i][j-1]. + // + // 2. If l is not the current lane, then W includes the indices of all + // blocks in the last SL - 1 = 3 segments computed and finished in + // lane l. If B[i][j] is the first block of a segment, then the + // very last index from W is excluded. + // + // Then take a block from W with a nonuniform distribution over [0, |W|) + // using the following mapping: + // + // J_1 -> |W|(1 - J_1^2 / 2^(64)) + // + // Figure 12: Computing J1 + // + // To avoid floating point computation, the following approximation is + // used: + // + // x = J_1^2 / 2^(32) + // y = (|W| * x) / 2^(32) + // zz = |W| - 1 - y + // + // Figure 13: Computing J1, Part 2 + // + // Then take the zz-th index from W; it will be the z value for the + // reference block index [l][z]. + next_slice: u32 = ((slice + 1) % 4) * segment_size + window_start, nb_segments: u32 + lane := u32(index_seed >> 32) % p + switch { + case pass == 0: + nb_segments = slice + if slice == 0 { + lane = segment + } + case: + window_start = next_slice + nb_segments = 3 + } + window_size := nb_segments * segment_size + if lane == segment { + window_size += block - 1 + } else if block == 0 { + window_size += ~u32(0) + } + + j1 := index_seed & 0xffffffff + x := (j1 * j1) >> 32 + y := (u64(window_size) * x) >> 32 + z := (u64(window_size) - 1) - y + ref := u32((u64(window_start) + z) % u64(lane_size)) + reference: u32 = lane * lane_size + ref + + copy(tmp[:], blocks[previous][:]) + xor_block(&tmp, &blocks[reference]) + if pass == 0 { + copy(blocks[current][:], tmp[:]) + } else { + xor_block(&blocks[current], &tmp) + } + g_rounds(&tmp) + xor_block(&blocks[current], &tmp) + } + } + } + } + mem.zero_explicit(&tmp, size_of(tmp)) + mem.zero_explicit(&index_block, size_of(index_block)) + + // After t steps have been iterated, the final block C is computed + // as the XOR of the last column: + // + // C = B[0][q-1] XOR B[1][q-1] XOR ... XOR B[p-1][q-1] + idx := lane_size - 1 + last_block := &blocks[idx] + for _ in 1 ..< p { + idx += lane_size + next_block := &blocks[idx] + xor_block(next_block, last_block) + last_block = next_block + } + + for v, i in last_block { + endian.unchecked_put_u64le(block_buf[i*8:], v) + } + + // The output tag is computed as H'^T(C). + h_prime(dst, block_buf[:]) + mem.zero_explicit(&block_buf, size_of(block_buf)) + + // Sanitize the working memory. While the RFC implies that this is + // optional ("enable the memory-wiping option in the library call"), + // the reference code defaults to enabling it. + // + // An opt-out is provided, as this can get somewhat expensive when + // m gets large. + if sanitize { + mem.zero_explicit(raw_data(b), len(b)) + } + + return nil +} + +@(private) +xor_block :: #force_inline proc(dst, src: ^Block) { + for v, i in src { + dst[i] ~= v + } +} + +@(private) +blake2b_update_u32le :: #force_inline proc(ctx: ^blake2b.Context, i: u32) { + tmp: [4]byte = --- + endian.unchecked_put_u32le(tmp[:], i) + blake2b.update(ctx, tmp[:]) + mem.zero_explicit(&tmp, size_of(tmp)) // Probably overkill. +} + +// 3.3. Variable-Length Hash Function H' +// +// Let V_i be a 64-byte block and W_i be its first 32 bytes. Then we +// define function H' as follows: +// +// if T <= 64 +// H'^T(A) = H^T(LE32(T)||A) +// else +// r = ceil(T/32)-2 +// V_1 = H^(64)(LE32(T)||A) +// V_2 = H^(64)(V_1) +// ... +// V_r = H^(64)(V_{r-1}) +// V_{r+1} = H^(T-32*r)(V_{r}) +// H'^T(X) = W_1 || W_2 || ... || W_r || V_{r+1} +// +// Figure 8: Function H' for Tag and Initial Block Computations +@(private) +h_prime :: proc(dst, src: []byte) { + t := len(dst) + ctx: blake2b.Context + blake2b.init(&ctx, min(t, blake2b.DIGEST_SIZE)) + blake2b_update_u32le(&ctx, u32(t)) + blake2b.update(&ctx, src) + blake2b.final(&ctx, dst) + + if t > 64 { + r := u32((u64(t) + 31) >> 5) - 2 + i: u32 = 1 + off_in := 0 + off_out := 32 + for i < r { + blake2b.init(&ctx, blake2b.DIGEST_SIZE) + blake2b.update(&ctx, dst[off_in:off_in+64]) + blake2b.final(&ctx, dst[off_out:]) + i += 1 + off_in += 32 + off_out += 32 + } + blake2b.init(&ctx, t - int(32 * r)) + blake2b.update(&ctx, dst[off_in:off_in+64]) + blake2b.final(&ctx, dst[off_out:]) + } +} + +// GB(a, b, c, d) is defined as follows: +// +// a = (a + b + 2 * trunc(a) * trunc(b)) mod 2^(64) +// d = (d XOR a) >>> 32 +// c = (c + d + 2 * trunc(c) * trunc(d)) mod 2^(64) +// b = (b XOR c) >>> 24 +// +// a = (a + b + 2 * trunc(a) * trunc(b)) mod 2^(64) +// d = (d XOR a) >>> 16 +// c = (c + d + 2 * trunc(c) * trunc(d)) mod 2^(64) +// b = (b XOR c) >>> 63 +// +// Figure 19: Details of GB +// +// The modular additions in GB are combined with 64-bit multiplications. +// Multiplications are the only difference from the original BLAKE2b +// design. This choice is done to increase the circuit depth and thus +// the running time of ASIC implementations, while having roughly the +// same running time on CPUs thanks to parallelism and pipelining. +@(private,require_results) +gb :: #force_inline proc(a, b, c, d: u64) -> (u64, u64, u64, u64) { + a, b, c, d := a, b, c, d + + trunc := #force_inline proc(v: u64) -> u64 { + return u64(u32(v)) + } + + a += b + ((trunc(a) * trunc(b)) << 1) + d = bits.rotate_left64(d ~ a, 32) // >>> 32 + c += d + ((trunc(c) * trunc(d)) << 1) + b = bits.rotate_left64((b ~ c), 40) // >>> 24 + + a += b + ((trunc(a) * trunc(b)) << 1) + d = bits.rotate_left64(d ~ a, 48) // >>> 16 + c += d + ((trunc(c) * trunc(d)) << 1) + b = bits.rotate_left64((b ~ c), 1) // >>> 63 + + return a, b, c, d +} + +// 3.6. Permutation P +// +// Permutation P is based on the round function of BLAKE2b. The eight +// 16-byte inputs S_0, S_1, ... , S_7 are viewed as a 4x4 matrix of +// 64-bit words, where S_i = (v_{2*i+1} || v_{2*i}): +// +// v_0 v_1 v_2 v_3 +// v_4 v_5 v_6 v_7 +// v_8 v_9 v_10 v_11 +// v_12 v_13 v_14 v_15 +// +// Figure 17: Matrix Element Labeling +// +// It works as follows: +// +// GB(v_0, v_4, v_8, v_12) +// GB(v_1, v_5, v_9, v_13) +// GB(v_2, v_6, v_10, v_14) +// GB(v_3, v_7, v_11, v_15) +// +// GB(v_0, v_5, v_10, v_15) +// GB(v_1, v_6, v_11, v_12) +// GB(v_2, v_7, v_8, v_13) +// GB(v_3, v_4, v_9, v_14) +// +// Figure 18: Feeding Matrix Elements to GB +@(private,require_results) +perm_p :: #force_inline proc(v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9, v_10, v_11, v_12, v_13, v_14, v_15: u64) -> (u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64) { + v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9, v_10, v_11, v_12, v_13, v_14, v_15 := v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9, v_10, v_11, v_12, v_13, v_14, v_15 + + v_0, v_4, v_8, v_12 = gb(v_0, v_4, v_8, v_12) + v_1, v_5, v_9, v_13 = gb(v_1, v_5, v_9, v_13) + v_2, v_6, v_10, v_14 = gb(v_2, v_6, v_10, v_14) + v_3, v_7, v_11, v_15 = gb(v_3, v_7, v_11, v_15) + + v_0, v_5, v_10, v_15 = gb(v_0, v_5, v_10, v_15) + v_1, v_6, v_11, v_12 = gb(v_1, v_6, v_11, v_12) + v_2, v_7, v_8, v_13 = gb(v_2, v_7, v_8, v_13) + v_3, v_4, v_9, v_14 = gb(v_3, v_4, v_9, v_14) + + return v_0, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9, v_10, v_11, v_12, v_13, v_14, v_15 +} + +// 3.5. Compression Function G +// +// The compression function G is built upon the BLAKE2b-based +// transformation P. P operates on the 128-byte input, which can be +// viewed as eight 16-byte registers: +// +// P(A_0, A_1, ... ,A_7) = (B_0, B_1, ... ,B_7) +// +// Figure 14: Blake Round Function P +// +// The compression function G(X, Y) operates on two 1024-byte blocks X +// and Y. It first computes R = X XOR Y. Then R is viewed as an 8x8 +// matrix of 16-byte registers R_0, R_1, ... , R_63. Then P is first +// applied to each row, and then to each column to get Z: +// +// ( Q_0, Q_1, Q_2, ... , Q_7) <- P( R_0, R_1, R_2, ... , R_7) +// ( Q_8, Q_9, Q_10, ... , Q_15) <- P( R_8, R_9, R_10, ... , R_15) +// ... +// (Q_56, Q_57, Q_58, ... , Q_63) <- P(R_56, R_57, R_58, ... , R_63) +// ( Z_0, Z_8, Z_16, ... , Z_56) <- P( Q_0, Q_8, Q_16, ... , Q_56) +// ( Z_1, Z_9, Z_17, ... , Z_57) <- P( Q_1, Q_9, Q_17, ... , Q_57) +// ... +// ( Z_7, Z_15, Z 23, ... , Z_63) <- P( Q_7, Q_15, Q_23, ... , Q_63) +// +// Figure 15: Core of Compression Function G +@(private) +g_rounds :: proc(b: ^Block) { + for i := 0; i < 128; i += 16 { + b[i], b[i+1], b[i+2], b[i+3], b[i+4], b[i+5], b[i+6], b[i+7], b[i+8], b[i+9], b[i+10], b[i+11], b[i+12], b[i+13], b[i+14], b[i+15] = perm_p(b[i], b[i+1], b[i+2], b[i+3], b[i+4], b[i+5], b[i+6], b[i+7], b[i+8], b[i+9], b[i+10], b[i+11], b[i+12], b[i+13], b[i+14], b[i+15]) + } + for i := 0; i < 16; i += 2 { + b[i], b[i+1], b[i+16], b[i+17], b[i+32], b[i+33], b[i+48], b[i+49], b[i+64], b[i+65], b[i+80], b[i+81], b[i+96], b[i+97], b[i+112], b[i+113] = perm_p(b[i], b[i+1], b[i+16], b[i+17], b[i+32], b[i+33], b[i+48], b[i+49], b[i+64], b[i+65], b[i+80], b[i+81], b[i+96], b[i+97], b[i+112], b[i+113]) + } +} diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin index 3b3fc6649..8cce6dac8 100644 --- a/core/crypto/blake2b/blake2b.odin +++ b/core/crypto/blake2b/blake2b.odin @@ -1,5 +1,5 @@ /* -package blake2b implements the BLAKE2b hash algorithm. +`BLAKE2b` hash algorithm. See: - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]] @@ -9,7 +9,7 @@ package blake2b /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -28,13 +28,24 @@ Context :: _blake2.Blake2b_Context // init initializes a Context with the default BLAKE2b config. init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { - ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2b: invalid digest size") + ensure(digest_size <= DIGEST_SIZE, "crypto/blake2b: invalid digest size") cfg: _blake2.Blake2_Config cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) } +// init_mac initializes a Context with a user provided key. +init_mac :: proc(ctx: ^Context, key: []byte, digest_size := DIGEST_SIZE) { + ensure(digest_size <= DIGEST_SIZE, "crypto/blake2b: invalid digest size") + ensure(len(key) <= DIGEST_SIZE, "crypto/blake2b: invalid key size") + + cfg: _blake2.Blake2_Config + cfg.size = u8(digest_size) + cfg.key = key + _blake2.init(ctx, &cfg) +} + // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { _blake2.update(ctx, data) @@ -43,7 +54,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _blake2.final(ctx, hash, finalize_clone) diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin index 9bbd44541..35e278f72 100644 --- a/core/crypto/blake2s/blake2s.odin +++ b/core/crypto/blake2s/blake2s.odin @@ -1,5 +1,5 @@ /* -package blake2s implements the BLAKE2s hash algorithm. +`BLAKE2s` hash algorithm. See: - [[ https://datatracker.ietf.org/doc/html/rfc7693 ]] @@ -9,7 +9,7 @@ package blake2s /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -28,13 +28,24 @@ Context :: _blake2.Blake2s_Context // init initializes a Context with the default BLAKE2s config. init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { - ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2s: invalid digest size") + ensure(digest_size <= DIGEST_SIZE, "crypto/blake2s: invalid digest size") cfg: _blake2.Blake2_Config cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) } +// init_mac initializes a Context with a user provided key. +init_mac :: proc(ctx: ^Context, key: []byte, digest_size := DIGEST_SIZE) { + ensure(digest_size <= DIGEST_SIZE, "crypto/blake2s: invalid digest size") + ensure(len(key) <= DIGEST_SIZE, "crypto/blake2s: invalid key size") + + cfg: _blake2.Blake2_Config + cfg.size = u8(digest_size) + cfg.key = key + _blake2.init(ctx, &cfg) +} + // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { _blake2.update(ctx, data) @@ -43,7 +54,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _blake2.final(ctx, hash, finalize_clone) diff --git a/core/crypto/chacha20/chacha20.odin b/core/crypto/chacha20/chacha20.odin index e8d67eb3e..91f22f744 100644 --- a/core/crypto/chacha20/chacha20.odin +++ b/core/crypto/chacha20/chacha20.odin @@ -1,5 +1,5 @@ /* -package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers. +`ChaCha20` and `XChaCha20` stream ciphers. See: - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]] @@ -8,8 +8,8 @@ See: package chacha20 import "core:bytes" +import "core:crypto" import "core:crypto/_chacha20" -import "core:mem" // KEY_SIZE is the (X)ChaCha20 key size in bytes. KEY_SIZE :: _chacha20.KEY_SIZE @@ -50,7 +50,7 @@ init :: proc(ctx: ^Context, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) { // The sub-key is stored in the keystream buffer. While // this will be overwritten in most circumstances, explicitly // clear it out early. - mem.zero_explicit(&ctx._state._buffer, KEY_SIZE) + crypto.zero_explicit(&ctx._state._buffer, KEY_SIZE) } } diff --git a/core/crypto/chacha20poly1305/chacha20poly1305.odin b/core/crypto/chacha20poly1305/chacha20poly1305.odin index 6706b3820..c405a2736 100644 --- a/core/crypto/chacha20poly1305/chacha20poly1305.odin +++ b/core/crypto/chacha20poly1305/chacha20poly1305.odin @@ -1,7 +1,7 @@ /* -package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 and -AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data -algorithms. +`AEAD_CHACHA20_POLY1305` and `AEAD_XChaCha20_Poly1305` algorithms. + +Where AEAD stands for Authenticated Encryption with Additional Data. See: - [[ https://www.rfc-editor.org/rfc/rfc8439 ]] @@ -13,7 +13,6 @@ import "core:crypto" import "core:crypto/chacha20" import "core:crypto/poly1305" import "core:encoding/endian" -import "core:mem" // KEY_SIZE is the chacha20poly1305 key size in bytes. KEY_SIZE :: chacha20.KEY_SIZE @@ -103,7 +102,7 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { chacha20.keystream_bytes(&stream_ctx, otk[:]) mac_ctx: poly1305.Context = --- poly1305.init(&mac_ctx, otk[:]) - mem.zero_explicit(&otk, size_of(otk)) + crypto.zero_explicit(&otk, size_of(otk)) aad_len, ciphertext_len := len(aad), len(ciphertext) @@ -137,7 +136,7 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // open authenticates the aad and ciphertext, and decrypts the ciphertext, // with the provided Context, iv, and tag, and stores the output in dst, -// returning true iff the authentication was successful. If authentication +// returning true if and only if (⟺) the authentication was successful. If authentication // fails, the destination buffer will be zeroed. // // dst and plaintext MUST alias exactly or not at all. @@ -164,7 +163,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { mac_ctx: poly1305.Context = --- poly1305.init(&mac_ctx, otk[:]) - defer mem.zero_explicit(&otk, size_of(otk)) + defer crypto.zero_explicit(&otk, size_of(otk)) aad_len, ciphertext_len := len(aad), len(ciphertext) @@ -188,7 +187,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { // Validate the tag in constant time. if crypto.compare_constant_time(tag, derived_tag) != 1 { // Zero out the plaintext, as a defense in depth measure. - mem.zero_explicit(raw_data(plaintext), ciphertext_len) + crypto.zero_explicit(raw_data(plaintext), ciphertext_len) return false } @@ -202,7 +201,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { // reset sanitizes the Context. The Context must be // re-initialized to be used again. reset :: proc "contextless" (ctx: ^Context) { - mem.zero_explicit(&ctx._key, len(ctx._key)) + crypto.zero_explicit(&ctx._key, len(ctx._key)) ctx._is_xchacha = false ctx._is_initialized = false } diff --git a/core/crypto/crypto.odin b/core/crypto/crypto.odin index 323cc45d6..3218b8670 100644 --- a/core/crypto/crypto.odin +++ b/core/crypto/crypto.odin @@ -1,17 +1,23 @@ -/* -package crypto implements a selection of cryptography algorithms and useful -helper routines. -*/ +// A selection of cryptography algorithms and useful helper routines. package crypto +import "base:intrinsics" import "base:runtime" -import "core:mem" +import subtle "core:crypto/_subtle" -// compare_constant_time returns 1 iff a and b are equal, 0 otherwise. +// Omit large precomputed tables, trading off performance for size. +COMPACT_IMPLS: bool : #config(ODIN_CRYPTO_COMPACT, false) + +// HAS_RAND_BYTES is true if and only if (⟺) the runtime provides a cryptographic +// entropy source. +HAS_RAND_BYTES :: runtime.HAS_RAND_BYTES + +// compare_constant_time returns 1 if and only if (⟺) a and b are equal, 0 otherwise. // // The execution time of this routine is constant regardless of the contents // of the slices being compared, as long as the length of the slices is equal. -// If the length of the two slices is different, it will early-return 0. +// If and only if (⟺) the length of the two slices is diferent, it will +// early-return 0. compare_constant_time :: proc "contextless" (a, b: []byte) -> int { // If the length of the slices is different, early return. // @@ -26,24 +32,57 @@ compare_constant_time :: proc "contextless" (a, b: []byte) -> int { return compare_byte_ptrs_constant_time(raw_data(a), raw_data(b), n) } -// compare_byte_ptrs_constant_time returns 1 iff the bytes pointed to by +// compare_byte_ptrs_constant_time returns 1 if and only if (⟺) the bytes pointed to by // a and b are equal, 0 otherwise. // // The execution time of this routine is constant regardless of the // contents of the memory being compared. @(optimization_mode="none") compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> int { - x := mem.slice_ptr(a, n) - y := mem.slice_ptr(b, n) + x := ([^]byte)(a)[:n] + y := ([^]byte)(b)[:n] v: byte for i in 0..> 31) + // After the loop, v == 0 if and only if (⟺) a == b. The subtraction will underflow + // if and only if (⟺) v == 0, setting the sign-bit, which gets returned. + return subtle.eq(0, v) +} + +// is_zero_constant_time returns 1 if and only if (⟺) b is all 0s, 0 otherwise. +is_zero_constant_time :: proc "contextless" (b: []byte) -> int { + v: byte + for b_ in b { + v |= b_ + } + + return subtle.byte_eq(0, v) +} + +/* +Set each byte of a memory range to zero. + +This procedure copies the value `0` into the `len` bytes of a memory range, +starting at address `data`. + +This procedure returns the pointer to `data`. + +Unlike the `zero()` procedure, which can be optimized away or reordered by the +compiler under certain circumstances, `zero_explicit()` procedure can not be +optimized away or reordered with other memory access operations, and the +compiler assumes volatile semantics of the memory. +*/ +zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr { + // This routine tries to avoid the compiler optimizing away the call, + // so that it is always executed. It is intended to provide + // equivalent semantics to those provided by the C11 Annex K 3.7.4.1 + // memset_s call. + intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero + intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering + return data } // rand_bytes fills the dst buffer with cryptographic entropy taken from @@ -55,9 +94,9 @@ compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> i // `HAS_RAND_BYTES` boolean constant. rand_bytes :: proc (dst: []byte) { // zero-fill the buffer first - mem.zero_explicit(raw_data(dst), len(dst)) + zero_explicit(raw_data(dst), len(dst)) - _rand_bytes(dst) + runtime.rand_bytes(dst) } // random_generator returns a `runtime.Random_Generator` backed by the diff --git a/core/crypto/deoxysii/deoxysii.odin b/core/crypto/deoxysii/deoxysii.odin index cead770e2..ffe9b4b32 100644 --- a/core/crypto/deoxysii/deoxysii.odin +++ b/core/crypto/deoxysii/deoxysii.odin @@ -1,6 +1,5 @@ /* -package deoxysii implements the Deoxys-II-256 Authenticated Encryption -with Additional Data algorithm. +`Deoxys-II-256` Authenticated Encryption with Additional Data (`AEAD`) algorithm. - [[ https://sites.google.com/view/deoxyscipher ]] - [[ https://thomaspeyrin.github.io/web/assets/docs/papers/Jean-etal-JoC2021.pdf ]] @@ -9,8 +8,8 @@ package deoxysii import "base:intrinsics" import "core:bytes" +import "core:crypto" import "core:crypto/aes" -import "core:mem" import "core:simd" // KEY_SIZE is the Deoxys-II-256 key size in bytes. @@ -123,7 +122,7 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // open authenticates the aad and ciphertext, and decrypts the ciphertext, // with the provided Context, iv, and tag, and stores the output in dst, -// returning true iff the authentication was successful. If authentication +// returning true if and only if (⟺) the authentication was successful. If authentication // fails, the destination buffer will be zeroed. // // dst and plaintext MUST alias exactly or not at all. @@ -143,7 +142,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { ok = d_ref(ctx, dst, iv, aad, ciphertext, tag) } if !ok { - mem.zero_explicit(raw_data(dst), len(ciphertext)) + crypto.zero_explicit(raw_data(dst), len(ciphertext)) } return ok @@ -152,7 +151,7 @@ open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { // reset sanitizes the Context. The Context must be // re-initialized to be used again. reset :: proc "contextless" (ctx: ^Context) { - mem.zero_explicit(&ctx._subkeys, len(ctx._subkeys)) + crypto.zero_explicit(&ctx._subkeys, len(ctx._subkeys)) ctx._is_initialized = false } diff --git a/core/crypto/deoxysii/deoxysii_impl_ct64.odin b/core/crypto/deoxysii/deoxysii_impl_ct64.odin index c4d0edb03..e95eaa678 100644 --- a/core/crypto/deoxysii/deoxysii_impl_ct64.odin +++ b/core/crypto/deoxysii/deoxysii_impl_ct64.odin @@ -4,7 +4,6 @@ import "base:intrinsics" import "core:crypto" import aes "core:crypto/_aes/ct64" import "core:encoding/endian" -import "core:mem" import "core:simd" // This uses the bitlsiced 64-bit general purpose register SWAR AES @@ -149,8 +148,8 @@ bc_absorb :: proc "contextless" ( intrinsics.unaligned_store((^simd.u8x16)(raw_data(dst)), dst_) - mem.zero_explicit(&tweaks, size_of(tweaks)) - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tweaks, size_of(tweaks)) + crypto.zero_explicit(&tmp, size_of(tmp)) return stk_block_nr } @@ -214,8 +213,8 @@ bc_encrypt :: proc "contextless" ( nr_blocks -= n } - mem.zero_explicit(&tweaks, size_of(tweaks)) - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tweaks, size_of(tweaks)) + crypto.zero_explicit(&tmp, size_of(tmp)) return stk_block_nr } @@ -295,13 +294,13 @@ e_ref :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte copy(dst[n*BLOCK_SIZE:], m_star[:]) - mem.zero_explicit(&m_star, size_of(m_star)) + crypto.zero_explicit(&m_star, size_of(m_star)) } copy(tag, auth[:]) - mem.zero_explicit(&st.q_stk, size_of(st.q_stk)) - mem.zero_explicit(&st.q_b, size_of(st.q_b)) + crypto.zero_explicit(&st.q_stk, size_of(st.q_stk)) + crypto.zero_explicit(&st.q_b, size_of(st.q_b)) } @(private, require_results) @@ -336,7 +335,7 @@ d_ref :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byt copy(dst[n*BLOCK_SIZE:], m_star[:]) - mem.zero_explicit(&m_star, size_of(m_star)) + crypto.zero_explicit(&m_star, size_of(m_star)) } // Associated data @@ -382,7 +381,7 @@ d_ref :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byt _ = bc_absorb(&st, auth[:], m_star[:], PREFIX_MSG_FINAL, n) - mem.zero_explicit(&m_star, size_of(m_star)) + crypto.zero_explicit(&m_star, size_of(m_star)) } bc_final(&st, auth[:], iv) @@ -391,9 +390,9 @@ d_ref :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byt // else return false ok := crypto.compare_constant_time(auth[:], tag) == 1 - mem.zero_explicit(&auth, size_of(auth)) - mem.zero_explicit(&st.q_stk, size_of(st.q_stk)) - mem.zero_explicit(&st.q_b, size_of(st.q_b)) + crypto.zero_explicit(&auth, size_of(auth)) + crypto.zero_explicit(&st.q_stk, size_of(st.q_stk)) + crypto.zero_explicit(&st.q_b, size_of(st.q_b)) return ok -} +} \ No newline at end of file diff --git a/core/crypto/deoxysii/deoxysii_impl_hw_intel.odin b/core/crypto/deoxysii/deoxysii_impl_hw.odin similarity index 57% rename from core/crypto/deoxysii/deoxysii_impl_hw_intel.odin rename to core/crypto/deoxysii/deoxysii_impl_hw.odin index d268009a2..47f9ab55f 100644 --- a/core/crypto/deoxysii/deoxysii_impl_hw_intel.odin +++ b/core/crypto/deoxysii/deoxysii_impl_hw.odin @@ -1,153 +1,183 @@ -#+build amd64 +#+build amd64,arm64,arm32 package deoxysii import "base:intrinsics" import "core:crypto" -import "core:crypto/aes" -import "core:mem" +import aes_hw "core:crypto/_aes/hw" import "core:simd" -import "core:simd/x86" // This processes a maximum of 4 blocks at a time, as that is suitable // for most current hardware that doesn't say "Xeon". +// +// TODO/perf: ARM should be able to do 8 at a time. + +when ODIN_ARCH == .amd64 { + @(private="file") + TARGET_FEATURES :: "sse2,ssse3,aes" +} else when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { + @(private="file") + TARGET_FEATURES :: "neon,aes" +} @(private = "file") -_BIT_ENC :: x86.__m128i{0x80, 0} +_BIT_ENC :: simd.u8x16{0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @(private = "file") -_PREFIX_AD_BLOCK :: x86.__m128i{PREFIX_AD_BLOCK << PREFIX_SHIFT, 0} +_PREFIX_AD_BLOCK :: simd.u8x16{ + PREFIX_AD_BLOCK << PREFIX_SHIFT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} @(private = "file") -_PREFIX_AD_FINAL :: x86.__m128i{PREFIX_AD_FINAL << PREFIX_SHIFT, 0} +_PREFIX_AD_FINAL :: simd.u8x16{ + PREFIX_AD_FINAL << PREFIX_SHIFT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} @(private = "file") -_PREFIX_MSG_BLOCK :: x86.__m128i{PREFIX_MSG_BLOCK << PREFIX_SHIFT, 0} +_PREFIX_MSG_BLOCK :: simd.u8x16{ + PREFIX_MSG_BLOCK << PREFIX_SHIFT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} @(private = "file") -_PREFIX_MSG_FINAL :: x86.__m128i{PREFIX_MSG_FINAL << PREFIX_SHIFT, 0} +_PREFIX_MSG_FINAL :: simd.u8x16{ + PREFIX_MSG_FINAL << PREFIX_SHIFT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} -// is_hardware_accelerated returns true iff hardware accelerated Deoxys-II +// is_hardware_accelerated returns true if and only if (⟺) hardware accelerated Deoxys-II // is supported. is_hardware_accelerated :: proc "contextless" () -> bool { - return aes.is_hardware_accelerated() + return aes_hw.is_supported() } -@(private = "file", enable_target_feature = "sse4.1", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) auth_tweak :: #force_inline proc "contextless" ( - prefix: x86.__m128i, + prefix: simd.u8x16, block_nr: int, -) -> x86.__m128i { - return x86._mm_insert_epi64(prefix, i64(intrinsics.byte_swap(u64(block_nr))), 1) -} +) -> simd.u8x16 { + when ODIN_ENDIAN == .Little { + block_nr_u64 := intrinsics.byte_swap(u64(block_nr)) + } else { + block_nr_u64 := u64(block_nr) + } -@(private = "file", enable_target_feature = "sse2", require_results) -enc_tweak :: #force_inline proc "contextless" ( - tag: x86.__m128i, - block_nr: int, -) -> x86.__m128i { - return x86._mm_xor_si128( - x86._mm_or_si128(tag, _BIT_ENC), - x86.__m128i{0, i64(intrinsics.byte_swap(u64(block_nr)))}, + return simd.bit_or( + prefix, + transmute(simd.u8x16)(simd.u64x2{0, block_nr_u64}), ) } -@(private = "file", enable_target_feature = "ssse3", require_results) -h_ :: #force_inline proc "contextless" (tk1: x86.__m128i) -> x86.__m128i { - return transmute(x86.__m128i)h(transmute(simd.u8x16)tk1) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) +enc_tweak :: #force_inline proc "contextless" ( + tag: simd.u8x16, + block_nr: int, +) -> simd.u8x16 { + when ODIN_ENDIAN == .Little { + block_nr_u64 := intrinsics.byte_swap(u64(block_nr)) + } else { + block_nr_u64 := u64(block_nr) + } + + return simd.bit_xor( + simd.bit_or(tag, _BIT_ENC), + transmute(simd.u8x16)(simd.u64x2{0, block_nr_u64}), + ) } -@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) bc_x4 :: #force_inline proc "contextless" ( ctx: ^Context, - s_0, s_1, s_2, s_3: x86.__m128i, - tweak_0, tweak_1, tweak_2, tweak_3: x86.__m128i, -) -> (x86.__m128i, x86.__m128i, x86.__m128i, x86.__m128i) #no_bounds_check { + s_0, s_1, s_2, s_3: simd.u8x16, + tweak_0, tweak_1, tweak_2, tweak_3: simd.u8x16, +) -> (simd.u8x16, simd.u8x16, simd.u8x16, simd.u8x16) #no_bounds_check { s_0, s_1, s_2, s_3 := s_0, s_1, s_2, s_3 tk1_0, tk1_1, tk1_2, tk1_3 := tweak_0, tweak_1, tweak_2, tweak_3 - sk := intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[0])) - stk_0 := x86._mm_xor_si128(tk1_0, sk) - stk_1 := x86._mm_xor_si128(tk1_1, sk) - stk_2 := x86._mm_xor_si128(tk1_2, sk) - stk_3 := x86._mm_xor_si128(tk1_3, sk) + sk := intrinsics.unaligned_load((^simd.u8x16)(&ctx._subkeys[0])) + stk_0 := simd.bit_xor(tk1_0, sk) + stk_1 := simd.bit_xor(tk1_1, sk) + stk_2 := simd.bit_xor(tk1_2, sk) + stk_3 := simd.bit_xor(tk1_3, sk) - s_0 = x86._mm_xor_si128(s_0, stk_0) - s_1 = x86._mm_xor_si128(s_1, stk_1) - s_2 = x86._mm_xor_si128(s_2, stk_2) - s_3 = x86._mm_xor_si128(s_3, stk_3) + s_0 = simd.bit_xor(s_0, stk_0) + s_1 = simd.bit_xor(s_1, stk_1) + s_2 = simd.bit_xor(s_2, stk_2) + s_3 = simd.bit_xor(s_3, stk_3) for i in 1 ..= BC_ROUNDS { - sk = intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[i])) + sk = intrinsics.unaligned_load((^simd.u8x16)(&ctx._subkeys[i])) - tk1_0 = h_(tk1_0) - tk1_1 = h_(tk1_1) - tk1_2 = h_(tk1_2) - tk1_3 = h_(tk1_3) + tk1_0 = h(tk1_0) + tk1_1 = h(tk1_1) + tk1_2 = h(tk1_2) + tk1_3 = h(tk1_3) - stk_0 = x86._mm_xor_si128(tk1_0, sk) - stk_1 = x86._mm_xor_si128(tk1_1, sk) - stk_2 = x86._mm_xor_si128(tk1_2, sk) - stk_3 = x86._mm_xor_si128(tk1_3, sk) + stk_0 = simd.bit_xor(tk1_0, sk) + stk_1 = simd.bit_xor(tk1_1, sk) + stk_2 = simd.bit_xor(tk1_2, sk) + stk_3 = simd.bit_xor(tk1_3, sk) - s_0 = x86._mm_aesenc_si128(s_0, stk_0) - s_1 = x86._mm_aesenc_si128(s_1, stk_1) - s_2 = x86._mm_aesenc_si128(s_2, stk_2) - s_3 = x86._mm_aesenc_si128(s_3, stk_3) + s_0 = aes_hw.aesenc(s_0, stk_0) + s_1 = aes_hw.aesenc(s_1, stk_1) + s_2 = aes_hw.aesenc(s_2, stk_2) + s_3 = aes_hw.aesenc(s_3, stk_3) } return s_0, s_1, s_2, s_3 } -@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) bc_x1 :: #force_inline proc "contextless" ( ctx: ^Context, - s: x86.__m128i, - tweak: x86.__m128i, -) -> x86.__m128i #no_bounds_check { + s: simd.u8x16, + tweak: simd.u8x16, +) -> simd.u8x16 #no_bounds_check { s, tk1 := s, tweak - sk := intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[0])) - stk := x86._mm_xor_si128(tk1, sk) + sk := intrinsics.unaligned_load((^simd.u8x16)(&ctx._subkeys[0])) + stk := simd.bit_xor(tk1, sk) - s = x86._mm_xor_si128(s, stk) + s = simd.bit_xor(s, stk) for i in 1 ..= BC_ROUNDS { - sk = intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[i])) + sk = intrinsics.unaligned_load((^simd.u8x16)(&ctx._subkeys[i])) - tk1 = h_(tk1) + tk1 = h(tk1) - stk = x86._mm_xor_si128(tk1, sk) + stk = simd.bit_xor(tk1, sk) - s = x86._mm_aesenc_si128(s, stk) + s = aes_hw.aesenc(s, stk) } return s } -@(private = "file", enable_target_feature = "sse2,ssse3,sse4.1,aes", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) bc_absorb :: proc "contextless" ( ctx: ^Context, - tag: x86.__m128i, + tag: simd.u8x16, src: []byte, - tweak_prefix: x86.__m128i, + tweak_prefix: simd.u8x16, stk_block_nr: int, -) -> (x86.__m128i, int) #no_bounds_check { +) -> (simd.u8x16, int) #no_bounds_check { src, stk_block_nr, tag := src, stk_block_nr, tag nr_blocks := len(src) / BLOCK_SIZE for nr_blocks >= 4 { d_0, d_1, d_2, d_3 := bc_x4( ctx, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[BLOCK_SIZE:]))), - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[2*BLOCK_SIZE:]))), - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[3*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[2*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[3*BLOCK_SIZE:]))), auth_tweak(tweak_prefix, stk_block_nr), auth_tweak(tweak_prefix, stk_block_nr + 1), auth_tweak(tweak_prefix, stk_block_nr + 2), auth_tweak(tweak_prefix, stk_block_nr + 3), ) - tag = x86._mm_xor_si128(tag, d_0) - tag = x86._mm_xor_si128(tag, d_1) - tag = x86._mm_xor_si128(tag, d_2) - tag = x86._mm_xor_si128(tag, d_3) + tag = simd.bit_xor(tag, d_0) + tag = simd.bit_xor(tag, d_1) + tag = simd.bit_xor(tag, d_2) + tag = simd.bit_xor(tag, d_3) src = src[4*BLOCK_SIZE:] stk_block_nr += 4 @@ -157,11 +187,11 @@ bc_absorb :: proc "contextless" ( for nr_blocks > 0 { d := bc_x1( ctx, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))), auth_tweak(tweak_prefix, stk_block_nr), ) - tag = x86._mm_xor_si128(tag, d) + tag = simd.bit_xor(tag, d) src = src[BLOCK_SIZE:] stk_block_nr += 1 @@ -171,29 +201,29 @@ bc_absorb :: proc "contextless" ( return tag, stk_block_nr } -@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) bc_final :: proc "contextless" ( ctx: ^Context, - tag: x86.__m128i, + tag: simd.u8x16, iv: []byte, -) -> x86.__m128i { +) -> simd.u8x16 { tmp: [BLOCK_SIZE]byte tmp[0] = PREFIX_TAG << PREFIX_SHIFT copy(tmp[1:], iv) - tweak := intrinsics.unaligned_load((^x86.__m128i)(&tmp)) + tweak := intrinsics.unaligned_load((^simd.u8x16)(&tmp)) return bc_x1(ctx, tag, tweak) } -@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +@(private = "file", enable_target_feature = TARGET_FEATURES, require_results) bc_encrypt :: proc "contextless" ( ctx: ^Context, dst: []byte, src: []byte, - iv: x86.__m128i, - tweak_tag: x86.__m128i, + iv: simd.u8x16, + tweak_tag: simd.u8x16, stk_block_nr: int, ) -> int { dst, src, stk_block_nr := dst, src, stk_block_nr @@ -210,31 +240,31 @@ bc_encrypt :: proc "contextless" ( ) intrinsics.unaligned_store( - (^x86.__m128i)(raw_data(dst)), - x86._mm_xor_si128( + (^simd.u8x16)(raw_data(dst)), + simd.bit_xor( d_0, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))), ), ) intrinsics.unaligned_store( - (^x86.__m128i)(raw_data(dst[BLOCK_SIZE:])), - x86._mm_xor_si128( + (^simd.u8x16)(raw_data(dst[BLOCK_SIZE:])), + simd.bit_xor( d_1, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[BLOCK_SIZE:]))), ), ) intrinsics.unaligned_store( - (^x86.__m128i)(raw_data(dst[2*BLOCK_SIZE:])), - x86._mm_xor_si128( + (^simd.u8x16)(raw_data(dst[2*BLOCK_SIZE:])), + simd.bit_xor( d_2, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[2*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[2*BLOCK_SIZE:]))), ), ) intrinsics.unaligned_store( - (^x86.__m128i)(raw_data(dst[3*BLOCK_SIZE:])), - x86._mm_xor_si128( + (^simd.u8x16)(raw_data(dst[3*BLOCK_SIZE:])), + simd.bit_xor( d_3, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[3*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[3*BLOCK_SIZE:]))), ), ) @@ -251,10 +281,10 @@ bc_encrypt :: proc "contextless" ( ) intrinsics.unaligned_store( - (^x86.__m128i)(raw_data(dst)), - x86._mm_xor_si128( + (^simd.u8x16)(raw_data(dst)), + simd.bit_xor( d, - intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src))), ), ) @@ -270,7 +300,7 @@ bc_encrypt :: proc "contextless" ( e_hw :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) #no_bounds_check { tmp: [BLOCK_SIZE]byte copy(tmp[1:], iv) - iv_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(&tmp))) + iv_ := intrinsics.unaligned_load((^simd.u8x16)(raw_data(&tmp))) // Algorithm 3 // @@ -283,7 +313,7 @@ e_hw :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) // if A_∗ != nil then // Auth <- Auth ^ EK(0110 || la, pad10∗(A_∗)) // end - auth: x86.__m128i + auth: simd.u8x16 n: int aad := aad @@ -342,14 +372,14 @@ e_hw :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) copy(dst[n*BLOCK_SIZE:], m_star[:]) } - intrinsics.unaligned_store((^x86.__m128i)(raw_data(tag)), auth) + intrinsics.unaligned_store((^simd.u8x16)(raw_data(tag)), auth) } @(private, require_results) d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { tmp: [BLOCK_SIZE]byte copy(tmp[1:], iv) - iv_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(&tmp))) + iv_ := intrinsics.unaligned_load((^simd.u8x16)(raw_data(&tmp))) // Algorithm 4 // @@ -361,7 +391,7 @@ d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte // if C_∗ != nil then // M_∗ <- C_∗ ^ EK(1 || tag ^ l, 0^8 || N) // end - auth := intrinsics.unaligned_load((^x86.__m128i)(raw_data(tag))) + auth := intrinsics.unaligned_load((^simd.u8x16)(raw_data(tag))) m := ciphertext n := bc_encrypt(ctx, dst, m, iv_, auth, 0) @@ -374,7 +404,7 @@ d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte copy(dst[n*BLOCK_SIZE:], m_star[:]) - mem.zero_explicit(&m_star, size_of(m_star)) + crypto.zero_explicit(&m_star, size_of(m_star)) } // Associated data @@ -386,7 +416,7 @@ d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte // if A∗ != nil then // Auth <- Auth ^ EK(0110| | l_a, pad10∗(A_∗)) // end - auth = x86.__m128i{0, 0} + auth = simd.u8x16{} aad := aad auth, n = bc_absorb(ctx, auth, aad, _PREFIX_AD_BLOCK, 0) aad = aad[BLOCK_SIZE*n:] @@ -425,10 +455,10 @@ d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte // Tag verification // if tag0 = tag then return (M_1 || ... || M_l || M_∗) // else return false - intrinsics.unaligned_store((^x86.__m128i)(raw_data(&tmp)), auth) + intrinsics.unaligned_store((^simd.u8x16)(raw_data(&tmp)), auth) ok := crypto.compare_constant_time(tmp[:], tag) == 1 - mem.zero_explicit(&tmp, size_of(tmp)) + crypto.zero_explicit(&tmp, size_of(tmp)) return ok } diff --git a/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin b/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin index b0705ca62..7f5444535 100644 --- a/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin +++ b/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin @@ -1,10 +1,12 @@ #+build !amd64 +#+build !arm64 +#+build !arm32 package deoxysii @(private = "file") ERR_HW_NOT_SUPPORTED :: "crypto/deoxysii: hardware implementation unsupported" -// is_hardware_accelerated returns true iff hardware accelerated Deoxys-II +// is_hardware_accelerated returns true if and only if (⟺) hardware accelerated Deoxys-II // is supported. is_hardware_accelerated :: proc "contextless" () -> bool { return false diff --git a/core/crypto/ecdh/doc.odin b/core/crypto/ecdh/doc.odin new file mode 100644 index 000000000..e34f255f2 --- /dev/null +++ b/core/crypto/ecdh/doc.odin @@ -0,0 +1,4 @@ +/* +A generic interface to Elliptic Curve Diffie-Hellman key exchange. +*/ +package ecdh diff --git a/core/crypto/ecdh/ecdh.odin b/core/crypto/ecdh/ecdh.odin new file mode 100644 index 000000000..3da3e0e41 --- /dev/null +++ b/core/crypto/ecdh/ecdh.odin @@ -0,0 +1,513 @@ +package ecdh + +import "core:crypto" +import secec "core:crypto/_weierstrass" +import "core:crypto/x25519" +import "core:crypto/x448" +import "core:reflect" + +// Note: For these primitives scalar size = point size +@(private="file") +X25519_Buf :: [x25519.SCALAR_SIZE]byte +@(private="file") +X448_Buf :: [x448.SCALAR_SIZE]byte + +// Curve the curve identifier associated with a given Private_Key +// or Public_Key +Curve :: enum { + Invalid, + SECP256R1, + SECP384R1, + X25519, + X448, +} + +// CURVE_NAMES is the Curve to curve name string. +CURVE_NAMES := [Curve]string { + .Invalid = "Invalid", + .SECP256R1 = "secp256r1", + .SECP384R1 = "secp384r1", + .X25519 = "X25519", + .X448 = "X448", +} + +// PRIVATE_KEY_SIZES is the Curve to private key size in bytes. +PRIVATE_KEY_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = secec.SC_SIZE_P256R1, + .SECP384R1 = secec.SC_SIZE_P384R1, + .X25519 = x25519.SCALAR_SIZE, + .X448 = x448.SCALAR_SIZE, +} + +// PUBLIC_KEY_SIZES is the Curve to public key size in bytes. +PUBLIC_KEY_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = 1 + 2 * secec.FE_SIZE_P256R1, + .SECP384R1 = 1 + 2 * secec.FE_SIZE_P384R1, + .X25519 = x25519.POINT_SIZE, + .X448 = x448.POINT_SIZE, +} + +// SHARED_SECRET_SIZES is the Curve to shared secret size in bytes. +SHARED_SECRET_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = secec.FE_SIZE_P256R1, + .SECP384R1 = secec.FE_SIZE_P384R1, + .X25519 = x25519.POINT_SIZE, + .X448 = x448.POINT_SIZE, +} + +@(private="file") +_PRIV_IMPL_IDS := [Curve]typeid { + .Invalid = nil, + .SECP256R1 = typeid_of(secec.Scalar_p256r1), + .SECP384R1 = typeid_of(secec.Scalar_p384r1), + .X25519 = typeid_of(X25519_Buf), + .X448 = typeid_of(X448_Buf), +} + +@(private="file") +_PUB_IMPL_IDS := [Curve]typeid { + .Invalid = nil, + .SECP256R1 = typeid_of(secec.Point_p256r1), + .SECP384R1 = typeid_of(secec.Point_p384r1), + .X25519 = typeid_of(X25519_Buf), + .X448 = typeid_of(X448_Buf), +} + +// Private_Key is an ECDH private key. +Private_Key :: struct { + // WARNING: All of the members are to be treated as internal (ie: + // the Private_Key structure is intended to be opaque). + _curve: Curve, + _impl: union { + secec.Scalar_p256r1, + secec.Scalar_p384r1, + X25519_Buf, + X448_Buf, + }, + _pub_key: Public_Key, +} + +// Public_Key is an ECDH public key. +Public_Key :: struct { + // WARNING: All of the members are to be treated as internal (ie: + // the Public_Key structure is intended to be opaque). + _curve: Curve, + _impl: union { + secec.Point_p256r1, + secec.Point_p384r1, + X25519_Buf, + X448_Buf, + }, +} + +// private_key_generate uses the system entropy source to generate a new +// Private_Key. This will only fail if and only if (⟺) the system entropy source is +// missing or broken. +@(require_results) +private_key_generate :: proc(priv_key: ^Private_Key, curve: Curve) -> bool { + private_key_clear(priv_key) + + if !crypto.HAS_RAND_BYTES { + return false + } + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + secec.sc_set_random(sc) + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + secec.sc_set_random(sc) + case .X25519: + sc := &priv_key._impl.(X25519_Buf) + crypto.rand_bytes(sc[:]) + case .X448: + sc := &priv_key._impl.(X448_Buf) + crypto.rand_bytes(sc[:]) + case: + panic("crypto/ecdh: invalid curve") + } + + priv_key._curve = curve + private_key_generate_public(priv_key) + + return true +} + +// private_key_set_bytes decodes a byte-encoded private key, and returns +// true if and only if (⟺) the operation was successful. +@(require_results) +private_key_set_bytes :: proc(priv_key: ^Private_Key, curve: Curve, b: []byte) -> bool { + private_key_clear(priv_key) + + if len(b) != PRIVATE_KEY_SIZES[curve] { + return false + } + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + did_reduce := secec.sc_set_bytes(sc, b) + is_zero := secec.sc_is_zero(sc) == 1 + + // Reject `0` and scalars that are not less than the + // curve order. + if did_reduce || is_zero { + private_key_clear(priv_key) + return false + } + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + did_reduce := secec.sc_set_bytes(sc, b) + is_zero := secec.sc_is_zero(sc) == 1 + + // Reject `0` and scalars that are not less than the + // curve order. + if did_reduce || is_zero { + private_key_clear(priv_key) + return false + } + case .X25519: + sc := &priv_key._impl.(X25519_Buf) + copy(sc[:], b) + case .X448: + sc := &priv_key._impl.(X448_Buf) + copy(sc[:], b) + case: + panic("crypto/ecdh: invalid curve") + } + + priv_key._curve = curve + private_key_generate_public(priv_key) + + return true +} + +@(private="file") +private_key_generate_public :: proc(priv_key: ^Private_Key) { + switch &sc in priv_key._impl { + case secec.Scalar_p256r1: + pub_key: secec.Point_p256r1 = --- + secec.pt_scalar_mul_generator(&pub_key, &sc) + secec.pt_rescale(&pub_key, &pub_key) + priv_key._pub_key._impl = pub_key + case secec.Scalar_p384r1: + pub_key: secec.Point_p384r1 = --- + secec.pt_scalar_mul_generator(&pub_key, &sc) + secec.pt_rescale(&pub_key, &pub_key) + priv_key._pub_key._impl = pub_key + case X25519_Buf: + pub_key: X25519_Buf = --- + x25519.scalarmult_basepoint(pub_key[:], sc[:]) + priv_key._pub_key._impl = pub_key + case X448_Buf: + pub_key: X448_Buf = --- + x448.scalarmult_basepoint(pub_key[:], sc[:]) + priv_key._pub_key._impl = pub_key + case: + panic("crypto/ecdh: invalid curve") + } + + priv_key._pub_key._curve = priv_key._curve +} + +// private_key_set sets priv_key to src. +private_key_set :: proc(priv_key, src: ^Private_Key) { + if src == nil || src._curve == .Invalid { + private_key_clear(priv_key) + return + } + + priv_key._curve = src._curve + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[priv_key._curve], + ) + + #partial switch priv_key._curve { + case .SECP256R1: + secec.sc_set(&priv_key._impl.(secec.Scalar_p256r1), &src._impl.(secec.Scalar_p256r1)) + case .SECP384R1: + secec.sc_set(&priv_key._impl.(secec.Scalar_p384r1), &src._impl.(secec.Scalar_p384r1)) + case .X25519: + priv_buf := &(priv_key._impl.(X25519_Buf)) + src_buf := &(src._impl.(X25519_Buf)) + copy(priv_buf[:], src_buf[:]) + case .X448: + priv_buf := &(priv_key._impl.(X448_Buf)) + src_buf := &(src._impl.(X448_Buf)) + copy(priv_buf[:], src_buf[:]) + case: + panic("crypto/ecdh: invalid curve") + } + + public_key_set(&priv_key._pub_key, &src._pub_key) +} + +// private_key_bytes sets dst to byte-encoding of priv_key. +private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + ensure(priv_key._curve != .Invalid, "crypto/ecdh: uninitialized private key") + ensure(len(dst) == PRIVATE_KEY_SIZES[priv_key._curve], "crypto/ecdh: invalid destination size") + + #partial switch priv_key._curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + secec.sc_bytes(dst, sc) + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + secec.sc_bytes(dst, sc) + case .X25519: + sc := &priv_key._impl.(X25519_Buf) + copy(dst, sc[:]) + case .X448: + sc := &priv_key._impl.(X448_Buf) + copy(dst, sc[:]) + case: + panic("crypto/ecdh: invalid curve") + } +} + +// private_key_public_bytes sets dst to the byte-encoding of the public +// key corresponding to priv_key. +private_key_public_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + public_key_bytes(&priv_key._pub_key, dst) +} + +// private_key_equal returns true if and only if (⟺) the private keys are equal, +// in constant time. +@(require_results) +private_key_equal :: proc(p, q: ^Private_Key) -> bool { + if p._curve != q._curve { + return false + } + + #partial switch p._curve { + case .SECP256R1: + sc_p, sc_q := &p._impl.(secec.Scalar_p256r1), &q._impl.(secec.Scalar_p256r1) + return secec.sc_equal(sc_p, sc_q) == 1 + case .SECP384R1: + sc_p, sc_q := &p._impl.(secec.Scalar_p384r1), &q._impl.(secec.Scalar_p384r1) + return secec.sc_equal(sc_p, sc_q) == 1 + case .X25519: + b_p, b_q := &p._impl.(X25519_Buf), &q._impl.(X25519_Buf) + return crypto.compare_constant_time(b_p[:], b_q[:]) == 1 + case .X448: + b_p, b_q := &p._impl.(X448_Buf), &q._impl.(X448_Buf) + return crypto.compare_constant_time(b_p[:], b_q[:]) == 1 + case: + return false + } +} + +// private_key_clear clears priv_key to the uninitialized state. +private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { + crypto.zero_explicit(priv_key, size_of(Private_Key)) +} + +// public_key_set_bytes decodes a byte-encoded public key, and returns +// true if and only if (⟺) the operation was successful. +@(require_results) +public_key_set_bytes :: proc(pub_key: ^Public_Key, curve: Curve, b: []byte) -> bool { + public_key_clear(pub_key) + + if len(b) != PUBLIC_KEY_SIZES[curve] { + return false + } + + reflect.set_union_variant_typeid( + pub_key._impl, + _PUB_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + if b[0] != secec.SEC_PREFIX_UNCOMPRESSED { + return false + } + + pt := &pub_key._impl.(secec.Point_p256r1) + ok := secec.pt_set_sec_bytes(pt, b) + if !ok || secec.pt_is_identity(pt) == 1 { + return false + } + case .SECP384R1: + if b[0] != secec.SEC_PREFIX_UNCOMPRESSED { + return false + } + + pt := &pub_key._impl.(secec.Point_p384r1) + ok := secec.pt_set_sec_bytes(pt, b) + if !ok || secec.pt_is_identity(pt) == 1 { + return false + } + case .X25519: + pt := &pub_key._impl.(X25519_Buf) + copy(pt[:], b) + case .X448: + pt := &pub_key._impl.(X448_Buf) + copy(pt[:], b) + case: + panic("crypto/ecdh: invalid curve") + } + + pub_key._curve = curve + + return true +} + +// public_key_set sets pub_key to src. +public_key_set :: proc(pub_key, src: ^Public_Key) { + if src == nil || src._curve == .Invalid { + public_key_clear(pub_key) + return + } + + pub_key^ = src^ +} + +// public_key_set_priv sets pub_key to the public component of priv_key. +public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { + ensure(priv_key._curve != .Invalid, "crypto/ecdh: uninitialized private key") + public_key_clear(pub_key) + pub_key^ = priv_key._pub_key +} + +// public_key_bytes sets dst to byte-encoding of pub_key. +public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { + ensure(pub_key._curve != .Invalid, "crypto/ecdh: uninitialized public key") + ensure(len(dst) == PUBLIC_KEY_SIZES[pub_key._curve], "crypto/ecdh: invalid destination size") + + #partial switch pub_key._curve { + case .SECP256R1: + // Invariant: Unless the caller is manually building pub_key + // `Z = 1`, so we can skip the rescale. + pt := &pub_key._impl.(secec.Point_p256r1) + + dst[0] = secec.SEC_PREFIX_UNCOMPRESSED + secec.fe_bytes(dst[1:1+secec.FE_SIZE_P256R1], &pt.x) + secec.fe_bytes(dst[1+secec.FE_SIZE_P256R1:], &pt.y) + case .SECP384R1: + // Invariant: Unless the caller is manually building pub_key + // `Z = 1`, so we can skip the rescale. + pt := &pub_key._impl.(secec.Point_p384r1) + + dst[0] = secec.SEC_PREFIX_UNCOMPRESSED + secec.fe_bytes(dst[1:1+secec.FE_SIZE_P384R1], &pt.x) + secec.fe_bytes(dst[1+secec.FE_SIZE_P384R1:], &pt.y) + case .X25519: + pt := &pub_key._impl.(X25519_Buf) + copy(dst, pt[:]) + case .X448: + pt := &pub_key._impl.(X448_Buf) + copy(dst, pt[:]) + case: + panic("crypto/ecdh: invalid curve") + } +} + +// public_key_equal returns true if and only if (⟺) the public keys are equal, +// in constant time. +@(require_results) +public_key_equal :: proc(p, q: ^Public_Key) -> bool { + if p._curve != q._curve { + return false + } + + #partial switch p._curve { + case .SECP256R1: + pt_p, pt_q := &p._impl.(secec.Point_p256r1), &q._impl.(secec.Point_p256r1) + return secec.pt_equal(pt_p, pt_q) == 1 + case .SECP384R1: + pt_p, pt_q := &p._impl.(secec.Point_p384r1), &q._impl.(secec.Point_p384r1) + return secec.pt_equal(pt_p, pt_q) == 1 + case .X25519: + b_p, b_q := &p._impl.(X25519_Buf), &q._impl.(X25519_Buf) + return crypto.compare_constant_time(b_p[:], b_q[:]) == 1 + case .X448: + b_p, b_q := &p._impl.(X448_Buf), &q._impl.(X448_Buf) + return crypto.compare_constant_time(b_p[:], b_q[:]) == 1 + case: + panic("crypto/ecdh: invalid curve") + } +} + +// public_key_clear clears pub_key to the uninitialized state. +public_key_clear :: proc "contextless" (pub_key: ^Public_Key) { + crypto.zero_explicit(pub_key, size_of(Public_Key)) +} + +// ecdh performs an Elliptic Curve Diffie-Hellman key exchange betwween +// the Private_Key and Public_Key, writing the shared secret to dst. +// +// The neutral element is rejected as an error. +@(require_results) +ecdh :: proc(priv_key: ^Private_Key, pub_key: ^Public_Key, dst: []byte) -> bool { + ensure(priv_key._curve == pub_key._curve, "crypto/ecdh: curve mismatch") + ensure(pub_key._curve != .Invalid, "crypto/ecdh: uninitialized public key") + ensure(len(dst) == SHARED_SECRET_SIZES[priv_key._curve], "crypto/ecdh: invalid shared secret size") + + #partial switch priv_key._curve { + case .SECP256R1: + sc, pt := &priv_key._impl.(secec.Scalar_p256r1), &pub_key._impl.(secec.Point_p256r1) + ss: secec.Point_p256r1 + defer secec.pt_clear(&ss) + + secec.pt_scalar_mul(&ss, pt, sc) + return secec.pt_bytes(dst, nil, &ss) + case .SECP384R1: + sc, pt := &priv_key._impl.(secec.Scalar_p384r1), &pub_key._impl.(secec.Point_p384r1) + ss: secec.Point_p384r1 + defer secec.pt_clear(&ss) + + secec.pt_scalar_mul(&ss, pt, sc) + return secec.pt_bytes(dst, nil, &ss) + case .X25519: + sc, pt := &priv_key._impl.(X25519_Buf), &pub_key._impl.(X25519_Buf) + x25519.scalarmult(dst, sc[:], pt[:]) + case .X448: + sc, pt := &priv_key._impl.(X448_Buf), &pub_key._impl.(X448_Buf) + x448.scalarmult(dst, sc[:], pt[:]) + case: + panic("crypto/ecdh: invalid curve") + } + + // X25519/X448 check for all zero digest. + return crypto.is_zero_constant_time(dst) == 0 +} + +// curve returns the Curve used by a Private_Key or Public_Key instance. +@(require_results) +curve :: proc(k: ^$T) -> Curve where (T == Private_Key || T == Public_Key) { + return k._curve +} + +// key_size returns the key size of a Private_Key or Public_Key in bytes. +@(require_results) +key_size :: proc(k: ^$T) -> int where (T == Private_Key || T == Public_Key) { + when T == Private_Key { + return PRIVATE_KEY_SIZES[k._curve] + } else { + return PUBLIC_KEY_SIZES[k._curve] + } +} + +// shared_secret_size returns the shared secret size of a key exchange +// in bytes. +@(require_results) +shared_secret_size :: proc(k: ^$T) -> int where (T == Private_Key || T == Public_Key) { + return SHARED_SECRET_SIZES[k._curve] +} diff --git a/core/crypto/ecdsa/doc.odin b/core/crypto/ecdsa/doc.odin new file mode 100644 index 000000000..8d60f3c52 --- /dev/null +++ b/core/crypto/ecdsa/doc.odin @@ -0,0 +1,7 @@ +/* +Elliptic Curve Digital Signature Algorithm per SEC 2.0 section 4.1. + +See: +- [[ https://secg.org/sec1-v2.pdf ]] +*/ +package ecdsa diff --git a/core/crypto/ecdsa/ecdsa.odin b/core/crypto/ecdsa/ecdsa.odin new file mode 100644 index 000000000..e63539fb1 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa.odin @@ -0,0 +1,383 @@ +package ecdsa + +import "core:crypto" +import secec "core:crypto/_weierstrass" +import "core:reflect" + +// Curve the curve identifier associated with a given Private_Key +// or Public_Key +Curve :: enum { + Invalid, + SECP256R1, + SECP384R1, +} + +// CURVE_NAMES is the Curve to curve name string. +CURVE_NAMES := [Curve]string { + .Invalid = "Invalid", + .SECP256R1 = "secp256r1", + .SECP384R1 = "secp384r1", +} + +// PRIVATE_KEY_SIZES is the Curve to private key size in bytes. +PRIVATE_KEY_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = secec.SC_SIZE_P256R1, + .SECP384R1 = secec.SC_SIZE_P384R1, +} + +// PUBLIC_KEY_SIZES is the Curve to public key size in bytes. +PUBLIC_KEY_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = 1 + 2 * secec.FE_SIZE_P256R1, + .SECP384R1 = 1 + 2 * secec.FE_SIZE_P384R1, +} + +// RAW_SIGNATURE_SIZES is the Curve to "raw" signature size in bytes. +RAW_SIGNATURE_SIZES := [Curve]int { + .Invalid = 0, + .SECP256R1 = 2 * secec.SC_SIZE_P256R1, + .SECP384R1 = 2 * secec.SC_SIZE_P384R1, +} + +@(private="file") +_PRIV_IMPL_IDS := [Curve]typeid { + .Invalid = nil, + .SECP256R1 = typeid_of(secec.Scalar_p256r1), + .SECP384R1 = typeid_of(secec.Scalar_p384r1), +} + +@(private="file") +_PUB_IMPL_IDS := [Curve]typeid { + .Invalid = nil, + .SECP256R1 = typeid_of(secec.Point_p256r1), + .SECP384R1 = typeid_of(secec.Point_p384r1), +} + +// Private_Key is an ECDSA private key. +Private_Key :: struct { + // WARNING: All of the members are to be treated as internal (ie: + // the Private_Key structure is intended to be opaque). + _curve: Curve, + _impl: union { + secec.Scalar_p256r1, + secec.Scalar_p384r1, + }, + _pub_key: Public_Key, +} + +// Public_Key is an ECDSA public key. +Public_Key :: struct { + // WARNING: All of the members are to be treated as internal (ie: + // the Public_Key structure is intended to be opaque). + _curve: Curve, + _impl: union { + secec.Point_p256r1, + secec.Point_p384r1, + }, +} + +// private_key_generate uses the system entropy source to generate a new +// Private_Key. This will only fail if and only if (⟺) the system entropy source is +// missing or broken. +@(require_results) +private_key_generate :: proc(priv_key: ^Private_Key, curve: Curve) -> bool { + private_key_clear(priv_key) + + if !crypto.HAS_RAND_BYTES { + return false + } + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + secec.sc_set_random(sc) + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + secec.sc_set_random(sc) + case: + panic("crypto/ecdsa: invalid curve") + } + + priv_key._curve = curve + private_key_generate_public(priv_key) + + return true +} + +// private_key_set_bytes decodes a byte-encoded private key, and returns +// true if and only if (⟺) the operation was successful. +@(require_results) +private_key_set_bytes :: proc(priv_key: ^Private_Key, curve: Curve, b: []byte) -> bool { + private_key_clear(priv_key) + + if len(b) != PRIVATE_KEY_SIZES[curve] { + return false + } + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + did_reduce := secec.sc_set_bytes(sc, b) + is_zero := secec.sc_is_zero(sc) == 1 + + // Reject `0` and scalars that are not less than the + // curve order. + if did_reduce || is_zero { + private_key_clear(priv_key) + return false + } + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + did_reduce := secec.sc_set_bytes(sc, b) + is_zero := secec.sc_is_zero(sc) == 1 + + // Reject `0` and scalars that are not less than the + // curve order. + if did_reduce || is_zero { + private_key_clear(priv_key) + return false + } + case: + panic("crypto/esa: invalid curve") + } + + priv_key._curve = curve + private_key_generate_public(priv_key) + + return true +} + +@(private="file") +private_key_generate_public :: proc(priv_key: ^Private_Key) { + switch &sc in priv_key._impl { + case secec.Scalar_p256r1: + pub_key: secec.Point_p256r1 = --- + secec.pt_scalar_mul_generator(&pub_key, &sc) + secec.pt_rescale(&pub_key, &pub_key) + priv_key._pub_key._impl = pub_key + case secec.Scalar_p384r1: + pub_key: secec.Point_p384r1 = --- + secec.pt_scalar_mul_generator(&pub_key, &sc) + secec.pt_rescale(&pub_key, &pub_key) + priv_key._pub_key._impl = pub_key + case: + panic("crypto/ecdsa: invalid curve") + } + + priv_key._pub_key._curve = priv_key._curve +} + +// private_key_bytes sets dst to byte-encoding of priv_key. +private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + ensure(priv_key._curve != .Invalid, "crypto/ecdsa: uninitialized private key") + ensure(len(dst) == PRIVATE_KEY_SIZES[priv_key._curve], "crypto/ecdsa: invalid destination size") + + #partial switch priv_key._curve { + case .SECP256R1: + sc := &priv_key._impl.(secec.Scalar_p256r1) + secec.sc_bytes(dst, sc) + case .SECP384R1: + sc := &priv_key._impl.(secec.Scalar_p384r1) + secec.sc_bytes(dst, sc) + case: + panic("crypto/ecdsa: invalid curve") + } +} + +// private_key_public_bytes sets dst to the byte-encoding of the public +// key corresponding to priv_key. +private_key_public_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + public_key_bytes(&priv_key._pub_key, dst) +} + +// private_key_set sets priv_key to src. +private_key_set :: proc(priv_key, src: ^Private_Key) { + if src == nil || src._curve == .Invalid { + private_key_clear(priv_key) + return + } + + priv_key._curve = src._curve + + reflect.set_union_variant_typeid( + priv_key._impl, + _PRIV_IMPL_IDS[priv_key._curve], + ) + + #partial switch priv_key._curve { + case .SECP256R1: + secec.sc_set(&priv_key._impl.(secec.Scalar_p256r1), &src._impl.(secec.Scalar_p256r1)) + case .SECP384R1: + secec.sc_set(&priv_key._impl.(secec.Scalar_p384r1), &src._impl.(secec.Scalar_p384r1)) + case: + panic("crypto/ecdh: invalid curve") + } + + public_key_set(&priv_key._pub_key, &src._pub_key) +} + +// private_key_equal returns true if and only if (⟺) the private keys are equal, +// in constant time. +@(require_results) +private_key_equal :: proc(p, q: ^Private_Key) -> bool { + if p._curve != q._curve { + return false + } + + #partial switch p._curve { + case .SECP256R1: + sc_p, sc_q := &p._impl.(secec.Scalar_p256r1), &q._impl.(secec.Scalar_p256r1) + return secec.sc_equal(sc_p, sc_q) == 1 + case .SECP384R1: + sc_p, sc_q := &p._impl.(secec.Scalar_p384r1), &q._impl.(secec.Scalar_p384r1) + return secec.sc_equal(sc_p, sc_q) == 1 + case: + return false + } +} + +// private_key_clear clears priv_key to the uninitialized state. +private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { + crypto.zero_explicit(priv_key, size_of(Private_Key)) +} + +// public_key_set_bytes decodes a byte-encoded public key, and returns +// true if and only if (⟺) the operation was successful. +@(require_results) +public_key_set_bytes :: proc(pub_key: ^Public_Key, curve: Curve, b: []byte) -> bool { + public_key_clear(pub_key) + + if len(b) != PUBLIC_KEY_SIZES[curve] { + return false + } + + reflect.set_union_variant_typeid( + pub_key._impl, + _PUB_IMPL_IDS[curve], + ) + + #partial switch curve { + case .SECP256R1: + if b[0] != secec.SEC_PREFIX_UNCOMPRESSED { + return false + } + + pt := &pub_key._impl.(secec.Point_p256r1) + ok := secec.pt_set_sec_bytes(pt, b) + if !ok || secec.pt_is_identity(pt) == 1 { + return false + } + case .SECP384R1: + if b[0] != secec.SEC_PREFIX_UNCOMPRESSED { + return false + } + + pt := &pub_key._impl.(secec.Point_p384r1) + ok := secec.pt_set_sec_bytes(pt, b) + if !ok || secec.pt_is_identity(pt) == 1 { + return false + } + case: + panic("crypto/ecdsa: invalid curve") + } + + pub_key._curve = curve + + return true +} + +// public_key_set sets pub_key to src. +public_key_set :: proc(pub_key, src: ^Public_Key) { + if src == nil || src._curve == .Invalid { + public_key_clear(pub_key) + return + } + + pub_key^ = src^ +} + +// public_key_set_priv sets pub_key to the public component of priv_key. +public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { + ensure(priv_key._curve != .Invalid, "crypto/ecdsa: uninitialized private key") + public_key_clear(pub_key) + pub_key^ = priv_key._pub_key +} + +// public_key_bytes sets dst to byte-encoding of pub_key. +public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { + ensure(pub_key._curve != .Invalid, "crypto/ecdsa: uninitialized public key") + ensure(len(dst) == PUBLIC_KEY_SIZES[pub_key._curve], "crypto/ecdsa: invalid destination size") + + #partial switch pub_key._curve { + case .SECP256R1: + // Invariant: Unless the caller is manually building pub_key + // `Z = 1`, so we can skip the rescale. + pt := &pub_key._impl.(secec.Point_p256r1) + + dst[0] = secec.SEC_PREFIX_UNCOMPRESSED + secec.fe_bytes(dst[1:1+secec.FE_SIZE_P256R1], &pt.x) + secec.fe_bytes(dst[1+secec.FE_SIZE_P256R1:], &pt.y) + case .SECP384R1: + // Invariant: Unless the caller is manually building pub_key + // `Z = 1`, so we can skip the rescale. + pt := &pub_key._impl.(secec.Point_p384r1) + + dst[0] = secec.SEC_PREFIX_UNCOMPRESSED + secec.fe_bytes(dst[1:1+secec.FE_SIZE_P384R1], &pt.x) + secec.fe_bytes(dst[1+secec.FE_SIZE_P384R1:], &pt.y) + case: + panic("crypto/ecdsa: invalid curve") + } +} + +// public_key_equal returns true if and only if (⟺) the public keys are equal, +// in constant time. +@(require_results) +public_key_equal :: proc(p, q: ^Public_Key) -> bool { + if p._curve != q._curve { + return false + } + + #partial switch p._curve { + case .SECP256R1: + pt_p, pt_q := &p._impl.(secec.Point_p256r1), &q._impl.(secec.Point_p256r1) + return secec.pt_equal(pt_p, pt_q) == 1 + case .SECP384R1: + pt_p, pt_q := &p._impl.(secec.Point_p384r1), &q._impl.(secec.Point_p384r1) + return secec.pt_equal(pt_p, pt_q) == 1 + case: + panic("crypto/ecdsa: invalid curve") + } +} + +// public_key_clear clears pub_key to the uninitialized state. +public_key_clear :: proc "contextless" (pub_key: ^Public_Key) { + crypto.zero_explicit(pub_key, size_of(Public_Key)) +} + +// curve returns the Curve used by a Private_Key or Public_Key instance. +@(require_results) +curve :: proc(k: ^$T) -> Curve where (T == Private_Key || T == Public_Key) { + return k._curve +} + +// key_size returns the key size of a Private_Key or Public_Key in bytes. +@(require_results) +key_size :: proc(k: ^$T) -> int where (T == Private_Key || T == Public_Key) { + when T == Private_Key { + return PRIVATE_KEY_SIZES[k._curve] + } else { + return PUBLIC_KEY_SIZES[k._curve] + } +} diff --git a/core/crypto/ecdsa/ecdsa_asn1.odin b/core/crypto/ecdsa/ecdsa_asn1.odin new file mode 100644 index 000000000..74c9d65e6 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa_asn1.odin @@ -0,0 +1,183 @@ +package ecdsa + +import secec "core:crypto/_weierstrass" + +// ASN.1 format ECDSA signatures are`SEQUENCE { r INTEGER, s INTEGER }` +// this implements enough to generate/parse signatures. Eventually when +// we have a full ASN.1 DER library, these routines will be removed. + +@(private="file") +TAG_SEQUENCE :: 0x30 +@(private="file") +TAG_INTEGER :: 0x02 + +@(private,require_results) +generate_asn1_sig :: proc(r, s: ^$T, allocator := context.allocator) -> []byte { + when T == secec.Scalar_p256r1 { + SC_SZ :: secec.SC_SIZE_P256R1 + } else when T == secec.Scalar_p384r1 { + SC_SZ :: secec.SC_SIZE_P384R1 + } else { + #panic("crypto/ecdsa: invalid curve") + } + + INT_TLP :: 3 // tag, tength, (optional) leading zero-byte + encode_uint :: proc(b: []byte) -> []byte { + b := b + + // DER requires minimal encoding. + off := INT_TLP + for v in b[off:] { + if v != 0 { + break + } + off += 1 + } + // If the sign big is set, add a leading zero. + if b[off] & 0x80 == 0x80 { + off -= 1 + b[off] = 0 + } + + // Encode the length (up to 127 octets, adequate for ECDSA). + l := len(b[off:]) + off -= 1 + b[off] = byte(l) + + // Encode the tag + off -= 1 + b[off] = TAG_INTEGER + + return b[off:] + } + + r_buf, s_buf: [INT_TLP+SC_SZ]byte = ---, --- + secec.sc_bytes(r_buf[INT_TLP:], r) + secec.sc_bytes(s_buf[INT_TLP:], s) + + r_bytes, s_bytes := encode_uint(r_buf[:]), encode_uint(s_buf[:]) + seq_len := len(r_bytes) + len(s_bytes) + + // WARNING: If secp521r1 support is added, this needs to support + // long-form length encoding. + ensure(seq_len <= 127, "BUG: crypto/ecdsa: signature length too large") + b := make([]byte, seq_len + 2, allocator) + b[0] = TAG_SEQUENCE + b[1] = byte(seq_len) + copy(b[2:], r_bytes) + copy(b[2+len(r_bytes):], s_bytes) + + return b +} + +@(private,require_results) +parse_asn1_sig :: proc(sig: []byte) -> (r, s: []byte, ok: bool) { + read_seq :: proc(b: []byte) -> (v: []byte, rest: []byte, ok: bool) { + b_len := len(b) + if b_len < 3 { + return nil, nil, false + } + if b[0] != TAG_SEQUENCE { + return nil, nil, false + } + seq_len, off: int + if b[1] & 0x80 == 0x80 { + if b[1] != 0x81 || b_len < 4 { // 2-length octets is sufficient for ecdsa. + return nil, nil, false + } + if b[2] & 0x80 == 0x80 || b[3] & 0x80 == 80 { + return nil, nil, false + } + seq_len = int(b[2]) * 127 + int(b[3]) + off = 4 + } else { + seq_len = int(b[1]) + off = 2 + } + if b_len - off < seq_len { + return nil, nil, false + } + return b[off:off+seq_len], b[off+seq_len:], true + } + + read_int :: proc(b: []byte) -> (v: []byte, rest: []byte, ok: bool) { + b_len := len(b) + if b_len < 3 { + return nil, nil, false + } + if b[0] != TAG_INTEGER { + return nil, nil, false + } + v_len := int(b[1]) + if v_len > 0x80 || b_len - 2 < v_len { // 127-bytes max. + return nil, nil, false + } + + return b[2:2+v_len], b[2+v_len:], true + } + + // SEQUENCE + seq_bytes, rest: []byte + seq_bytes, rest, ok = read_seq(sig) + if !ok { + return nil, nil, false + } + if len(rest) != 0 { + return nil, nil, false + } + + // INTEGER (r) + r, rest, ok = read_int(seq_bytes) + if !ok { + return nil, nil, false + } + + // INTEGER (s) + s, rest, ok = read_int(rest) + if !ok { + return nil, nil, false + } + if len(rest) != 0 { + return nil, nil, false + } + + // DER requires a leading 0 if and only if (⟺) the sign bit of the leading byte + // is set to distinguish between positive and negative integers, + // and the minimal length representation. `r` and `s` are always + // going to be unsigned, so we validate malformed DER and strip + // the leading 0 as needed. + fixup_der_uint :: proc(b: []byte) -> ([]byte, bool) { + switch len(b) { + case 0: + // 0 length is invalid + return nil, false + case 1: + // Missing leading zero + if b[0] & 0x80 == 0x80 { + return nil, false + } + case: + if b[0] == 0 { + // Sign bit not set + if b[1] & 0x80 != 0x80 { + return nil, false + } + return b[1:], true + } else if b[0] & 0x80 == 0x80 { + // Missing leading zero + return nil, false + } + } + + return b, true + } + + if r, ok = fixup_der_uint(r); !ok { + return nil, nil, false + } + if s, ok = fixup_der_uint(s); !ok { + return nil, nil, false + } + + return r, s, true +} diff --git a/core/crypto/ecdsa/ecdsa_k_rfc6979.odin b/core/crypto/ecdsa/ecdsa_k_rfc6979.odin new file mode 100644 index 000000000..01d2bb911 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa_k_rfc6979.odin @@ -0,0 +1,98 @@ +package ecdsa + +import "core:crypto" +import "core:crypto/hash" +import "core:crypto/hmac" +import secec "core:crypto/_weierstrass" + +@(private) +Drbg_RFC6979 :: struct { + v: [hash.MAX_DIGEST_SIZE]byte, + k: [hash.MAX_DIGEST_SIZE]byte, + + algorithm: hash.Algorithm, + sz: int, + need_update: bool, +} + +@(private) +init_drbg_rfc6979 :: proc(rng: ^Drbg_RFC6979, algorithm: hash.Algorithm, x_bytes, e_bytes: []byte, deterministic: bool) { + rng.algorithm = algorithm + rng.sz = hash.DIGEST_SIZES[algorithm] + rng.need_update = false + for i in 0.. bool { + // Extremely unlikely, so avoid unless the rejection + // sampling triggers. + if rng.need_update { + drbg_update_k(rng) + drbg_update_v(rng) + } + + drbg_update_v(rng) + rng.need_update = true + + return secec.sc_set_bytes(sc, rng.v[:secec.sc_size(sc)]) +} + +@(private) +drbg_clear_rfc6979 :: proc(rng: ^Drbg_RFC6979) { + crypto.zero_explicit(rng, size_of(Drbg_RFC6979)) +} + +@(private="file") +drbg_update_v :: proc(rng: ^Drbg_RFC6979) { + // V = HMAC_K(V) + k, v := rng.k[:rng.sz], rng.v[:rng.sz] + hmac.sum(rng.algorithm, v, v, k) +} + +@(private="file") +drbg_update_k :: proc(rng: ^Drbg_RFC6979) { + // K = HMAC_K(V || 0x00) + k, v := rng.k[:rng.sz], rng.v[:rng.sz] + + ctx: hmac.Context + hmac.init(&ctx, rng.algorithm, k) + hmac.update(&ctx, v) + hmac.update(&ctx, []byte{0x00}) + hmac.final(&ctx, k) +} + +@(private="file") +drbg_init_update_k :: proc(rng: ^Drbg_RFC6979, i2o_b, b2o_h1: []byte, internal_octet: byte, additional_input: []byte) { + k, v := rng.k[:rng.sz], rng.v[:rng.sz] + + ctx: hmac.Context + hmac.init(&ctx, rng.algorithm, k) + hmac.update(&ctx, v) + hmac.update(&ctx, []byte{internal_octet}) + hmac.update(&ctx, i2o_b) + hmac.update(&ctx, b2o_h1) + if additional_input != nil { + hmac.update(&ctx, additional_input) + } + hmac.final(&ctx, k) +} diff --git a/core/crypto/ecdsa/ecdsa_sign.odin b/core/crypto/ecdsa/ecdsa_sign.odin new file mode 100644 index 000000000..a594bc601 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa_sign.odin @@ -0,0 +1,201 @@ +package ecdsa + +import "base:runtime" +import "core:crypto" +import "core:crypto/hash" +import secec "core:crypto/_weierstrass" + +// sign_asn1 returns the signature by priv_key over msg hased using hash_algo +// using the signing procedure as specified in SEC 1, Version 2.0, Section +// 4.1.3. ASN.1 DER requires minimal encoding, and the format is clunky +// and variable-length so for simplicity we allocate the signature. +// +// The signature format is ASN1. `SEQUECE `{ r INTEGER, s INTEGER }`. +@(require_results) +sign_asn1 :: proc(priv_key: ^Private_Key, hash_algo: hash.Algorithm, msg: []byte, allocator: runtime.Allocator, deterministic := !crypto.HAS_RAND_BYTES) -> ([]byte, bool) { + ensure(hash_algo != .Invalid, "crypto/ecdsa: invalid hash algorithm") + ensure(priv_key._curve != .Invalid, "crypto/ecdsa: invalid curve") + + if !deterministic && !crypto.HAS_RAND_BYTES { + return nil, false + } + + #partial switch priv_key._curve { + case .SECP256R1: + SC_SZ :: secec.SC_SIZE_P256R1 + RAW_SIG_SZ :: 2 * SC_SZ + r, s: secec.Scalar_p256r1 = ---, --- + sk := &priv_key._impl.(secec.Scalar_p256r1) + sign_internal(sk, &r, &s, hash_algo, msg, deterministic) + + return generate_asn1_sig(&r, &s, allocator), true + case .SECP384R1: + SC_SZ :: secec.SC_SIZE_P384R1 + RAW_SIG_SZ :: 2 * SC_SZ + r, s: secec.Scalar_p384r1 = ---, --- + sk := &priv_key._impl.(secec.Scalar_p384r1) + sign_internal(sk, &r, &s, hash_algo, msg, deterministic) + + return generate_asn1_sig(&r, &s, allocator), true + } + + return nil, false +} + +// sign_raw writes the signature by priv_key over msg hased using hash_algo +// to sig, using the signing procedure as specified in SEC 1, Version 2.0, +// Section 4.1.3. +// +// The signature format is `r | s`. +@(require_results) +sign_raw :: proc(priv_key: ^Private_Key, hash_algo: hash.Algorithm, msg, sig: []byte, deterministic := !crypto.HAS_RAND_BYTES) -> bool { + ensure(hash_algo != .Invalid, "crypto/ecdsa: invalid hash algorithm") + ensure(priv_key._curve != .Invalid, "crypto/ecdsa: invalid curve") + ensure(len(sig) == RAW_SIGNATURE_SIZES[priv_key._curve], "crypto/ecdsa: invalid destination size") + + if !deterministic && !crypto.HAS_RAND_BYTES { + return false + } + + #partial switch priv_key._curve { + case .SECP256R1: + SC_SZ :: secec.SC_SIZE_P256R1 + r, s: secec.Scalar_p256r1 = ---, --- + sk := &priv_key._impl.(secec.Scalar_p256r1) + sign_internal(sk, &r, &s, hash_algo, msg, deterministic) + + r_bytes, s_bytes := sig[:SC_SZ], sig[SC_SZ:] + secec.sc_bytes(r_bytes, &r) + secec.sc_bytes(s_bytes, &s) + case .SECP384R1: + SC_SZ :: secec.SC_SIZE_P384R1 + r, s: secec.Scalar_p384r1 = ---, --- + sk := &priv_key._impl.(secec.Scalar_p384r1) + sign_internal(sk, &r, &s, hash_algo, msg, deterministic) + + r_bytes, s_bytes := sig[:SC_SZ], sig[SC_SZ:] + secec.sc_bytes(r_bytes, &r) + secec.sc_bytes(s_bytes, &s) + case: + panic("crypto/ecdsa: invalid curve") + } + + return true +} + +@(private) +sign_internal :: proc(priv_key, sig_r, sig_s: ^$T, hash_algo: hash.Algorithm, msg: []byte, deterministic: bool) { + when T == secec.Scalar_p256r1 { + SC_SZ :: secec.SC_SIZE_P256R1 + FE_SZ :: secec.FE_SIZE_P256R1 + MIN_DRBG_HASH :: hash.Algorithm.SHA256 + r_pt: secec.Point_p256r1 = --- + } else when T == secec.Scalar_p384r1 { + SC_SZ :: secec.SC_SIZE_P384R1 + FE_SZ :: secec.FE_SIZE_P384R1 + MIN_DRBG_HASH :: hash.Algorithm.SHA384 + r_pt: secec.Point_p384r1 = --- + } else { + #panic("crypto/ecdsa: invalid curve") + } + + // Note: `e` (derived from `hash`) in steps 4 and 5, is + // unchanged throughout the process even if a different `k` + // needs to be selected, thus, the value is derived first + // before the rejection sampling loop. + + // 4. Use the hash function selected during the setup procedure + // to compute the hash value: + // H = Hash(M) + // of length hashlen octets as specified in Section 3.5. If the + // hash function outputs “invalid”, output “invalid” and stop. + + // 5. Derive an integer e from H as follows: + // 5.1. Convert the octet string H to a bit string H using the + // conversion routine specified in Section 2.3.2. + // 5.2. Set E = H if ceil(log2(n)) >= 8(hashlen), and set E equal + // to the leftmost ceil(log2(n)) bits of H if ceil(log2(n)) < + // 8(hashlen). + // 5.3. Convert the bit string E to an octet string E using the + // conversion routine specified in Section 2.3.1. + // 5.4. Convert the octet string E to an integer e using the + // conversion routine specified in Section 2.3.8. + + e: T = --- + h_bytes: [hash.MAX_DIGEST_SIZE]byte = --- + e_bytes := hash.hash_bytes_to_buffer(hash_algo, msg, h_bytes[:]) + if len(e_bytes) > SC_SZ { + e_bytes = e_bytes[:SC_SZ] + } + if did_reduce := secec.sc_set_bytes(&e, e_bytes); did_reduce { + // RFC 6979 wants the reduced value + secec.sc_bytes(e_bytes, &e) + } + + x_bytes: [SC_SZ]byte = --- + defer crypto.zero_explicit(&x_bytes, size_of(x_bytes)) + secec.sc_bytes(x_bytes[:], priv_key) + + // While I normally will be content to let idiots compromise + // their signing keys, past precident (eg: Sony Computer + // Entertainment America, Inc v. Hotz) shows that "idiots" + // are also litigatious asshats. By default we use the hedged + // ("with additional input") variant of RFC 6979, with the option + // to disable the added entropy for RFC 6979 compatible deterministic + // signatures. + // + // For implementation simplicity, we will use a hash function that + // has a digest size that is greater than or equal to that of the + // curve order. Using a separate hash is allowed per section 3.6 + // of the RFC, and we only ever use a more secure hash. + + rng: Drbg_RFC6979 = --- + drbg_hash := hash_algo + if hash.DIGEST_SIZES[hash_algo] < SC_SZ { + drbg_hash = MIN_DRBG_HASH + } + init_drbg_rfc6979(&rng, drbg_hash, x_bytes[:], e_bytes, deterministic) + + k: T = --- + defer secec.sc_clear(&k) + for { + // 1. Select an ephemeral elliptic curve key pair (k, R) with + // R = (xR, yR) associated with the elliptic curve domain parameters + // T established during the setup procedure using the key pair + // generation primitive specified in Section 3.2.1. + + if did_reduce := drbg_read_rfc6979(&rng, &k); did_reduce || secec.sc_is_zero(&k) == 1 { + continue + } + secec.pt_scalar_mul_generator(&r_pt, &k) + + // 2. Convert the field element xR to an integer xR using the + // conversion routine specified in Section 2.3.9. + + rx_bytes: [FE_SZ]byte = --- + _ = secec.pt_bytes(rx_bytes[:], nil, &r_pt) + + // 3. Set r = xR mod n. If r = 0, or optionally r fails to meet + // other publicly verifiable criteria (see below), return to Step 1. + + _ = secec.sc_set_bytes(sig_r, rx_bytes[:]) + if secec.sc_is_zero(sig_r) == 1 { + // This is essentially totally untestable since the odds + // of generating `r = 0` is astronomically unlikely. + continue + } + + // (Steps 4/5 done prior to loop.) + + // 6. Compute: s = k^−1 (e + r * dU) mod n. + // If s = 0, return to Step 1. + + secec.sc_inv(&k, &k) + secec.sc_mul(sig_s, sig_r, priv_key) + secec.sc_add(sig_s, sig_s, &e) + secec.sc_mul(sig_s, sig_s, &k) + if secec.sc_is_zero(sig_s) == 0 { + return + } + } +} diff --git a/core/crypto/ecdsa/ecdsa_verify.odin b/core/crypto/ecdsa/ecdsa_verify.odin new file mode 100644 index 000000000..ddc1df9e6 --- /dev/null +++ b/core/crypto/ecdsa/ecdsa_verify.odin @@ -0,0 +1,148 @@ +package ecdsa + +import "core:crypto/hash" +import secec "core:crypto/_weierstrass" + +// verify_raw returns true if and only if (⟺) sig is a valid signature by pub_key over +// msg, hased using hash_algo, per the verification procedure specifed +// in SEC 1, Version 2.0, Section 4.1.4. +// +// The signature format is `r | s`. +@(require_results) +verify_raw :: proc(pub_key: ^Public_Key, hash_algo: hash.Algorithm, msg, sig: []byte) -> bool { + ensure(hash_algo != .Invalid, "crypto/ecdsa: invalid hash algorithm") + ensure(pub_key._curve != .Invalid, "crypto/ecdsa: invalid curve") + + if len(sig) != RAW_SIGNATURE_SIZES[pub_key._curve] { + return false + } + + #partial switch pub_key._curve { + case .SECP256R1: + SC_SZ :: secec.SC_SIZE_P256R1 + r_bytes, s_bytes := sig[:SC_SZ], sig[SC_SZ:] + pk := &pub_key._impl.(secec.Point_p256r1) + return verify_internal(pk, hash_algo, r_bytes, s_bytes, msg) + case .SECP384R1: + SC_SZ :: secec.SC_SIZE_P384R1 + r_bytes, s_bytes := sig[:SC_SZ], sig[SC_SZ:] + pk := &pub_key._impl.(secec.Point_p384r1) + return verify_internal(pk, hash_algo, r_bytes, s_bytes, msg) + } + + panic("crypto/ecdsa: invalid curve") +} + +// verify_asn1 returns true if and only if (⟺) sig is a valid signature by pub_key over +// msg, hased using hash_algo, per the verification procedure specifed +// in SEC 1, Version 2.0, Section 4.1.4. +// +// The signature format is ASN.1 `SEQUENCE { r INTEGER, s INTEGER }`. +@(require_results) +verify_asn1 :: proc(pub_key: ^Public_Key, hash_algo: hash.Algorithm, msg, sig: []byte) -> bool { + ensure(hash_algo != .Invalid, "crypto/ecdsa: invalid hash algorithm") + ensure(pub_key._curve != .Invalid, "crypto/ecdsa: invalid curve") + + r_bytes, s_bytes, ok := parse_asn1_sig(sig) + if !ok { + return false + } + + #partial switch pub_key._curve { + case .SECP256R1: + pk := &pub_key._impl.(secec.Point_p256r1) + return verify_internal(pk, hash_algo, r_bytes, s_bytes, msg) + case .SECP384R1: + pk := &pub_key._impl.(secec.Point_p384r1) + return verify_internal(pk, hash_algo, r_bytes, s_bytes, msg) + } + + panic("crypto/ecdsa: invalid curve") +} + +@(private,require_results) +verify_internal :: proc(pub_key: ^$T, hash_algo: hash.Algorithm, sig_r, sig_s, msg: []byte) -> bool { + when T == secec.Point_p256r1 { + r, s, e, v: secec.Scalar_p256r1 = ---, ---, ---, --- + u1, u2, s_inv: secec.Scalar_p256r1 = ---, ---, --- + SC_SZ :: secec.SC_SIZE_P256R1 + } else when T == secec.Point_p384r1 { + r, s, e, v: secec.Scalar_p384r1 = ---, ---, ---, --- + u1, u2, s_inv: secec.Scalar_p384r1 = ---, ---, --- + SC_SZ :: secec.SC_SIZE_P384R1 + } else { + #panic("crypto/ecdsa: invalid curve") + } + + if len(sig_r) > SC_SZ || len(sig_s) > SC_SZ { + return false + } + + // 1. If r and s are not both integers in the interval [1, n − 1], + // output “invalid” and stop. + + if did_reduce := secec.sc_set_bytes(&r, sig_r); did_reduce { + return false + } + if did_reduce := secec.sc_set_bytes(&s, sig_s); did_reduce { + return false + } + if secec.sc_is_zero(&r) == 1 || secec.sc_is_zero(&s) == 1 { + return false + } + + // 2. Use the hash function established during the setup procedure + // to compute the hash value: + // H = Hash(M) + // of length hashlen octets as specified in Section 3.5. If the + // hash function outputs “invalid”, output “invalid” and stop. + + // 3. Derive an integer e from H as follows: + // 3.1. Convert the octet string H to a bit string H using the + // conversion routine specified in Section 2.3.2. + // 3.2. Set E = H if ceil(log2(n)) >= 8(hashlen), and set E equal + // to the leftmost ceil(log2(n)) bits of H if ceil(log2(n)) < + // 8(hashlen). + // 3.3. Convert the bit string E to an octet string E using the + // conversion routine specified in Section 2.3.1. + // 3.4. Convert the octet string E to an integer e using the + // conversion routine specified in Section 2.3.8. + + h_bytes: [hash.MAX_DIGEST_SIZE]byte = --- + e_bytes := hash.hash_bytes_to_buffer(hash_algo, msg, h_bytes[:]) + if len(e_bytes) > SC_SZ { + e_bytes = e_bytes[:SC_SZ] + } + _ = secec.sc_set_bytes(&e, e_bytes) + + // 4. Compute: u1 = e(s^−1) mod n and u2 = r(s^-1) mod n. + + secec.sc_inv(&s_inv, &s) + secec.sc_mul(&u1, &e, &s_inv) + secec.sc_mul(&u2, &r, &s_inv) + + // 5. Compute: R = (xR, yR) = u1 * G + u2 * QU. + + r_pt: T = --- + secec.pt_double_scalar_mul_generator_vartime(&r_pt, pub_key, &u1, &u2) + + // If R = O, output “invalid” and stop. + + if secec.pt_is_identity(&r_pt) == 1 { + return false + } + + // 6. Convert the field element xR to an integer xR using the + // conversion routine specified in Section 2.3.9. + // + // 7. Set v = xR mod n. + + r_x: [SC_SZ]byte = --- + _ = secec.pt_bytes(r_x[:], nil, &r_pt) + _ = secec.sc_set_bytes(&v, r_x[:]) + + // 8. Compare v and r — if v = r, output “valid”, and if + // v != r, output “invalid”. + + return secec.sc_equal(&r, &v) == 1 +} diff --git a/core/crypto/ed25519/ed25519.odin b/core/crypto/ed25519/ed25519.odin index deeb80685..9f2d2b330 100644 --- a/core/crypto/ed25519/ed25519.odin +++ b/core/crypto/ed25519/ed25519.odin @@ -1,5 +1,5 @@ /* -package ed25519 implements the Ed25519 EdDSA signature algorithm. +`Ed25519` EdDSA signature algorithm. See: - [[ https://datatracker.ietf.org/doc/html/rfc8032 ]] @@ -11,7 +11,6 @@ package ed25519 import "core:crypto" import grp "core:crypto/_edwards25519" import "core:crypto/sha2" -import "core:mem" // PRIVATE_KEY_SIZE is the byte-encoded private key size. PRIVATE_KEY_SIZE :: 32 @@ -48,8 +47,27 @@ Public_Key :: struct { _is_initialized: bool, } +// private_key_generate uses the system entropy source to generate a new +// Private_Key. This will only fail if and only if (⟺) the system entropy source is +// missing or broken. +private_key_generate :: proc(priv_key: ^Private_Key) -> bool { + private_key_clear(priv_key) + + if !crypto.HAS_RAND_BYTES { + return false + } + + b: [PRIVATE_KEY_SIZE]byte + defer crypto.zero_explicit(&b, size_of(b)) + + crypto.rand_bytes(b[:]) + private_key_set_bytes(priv_key, b[:]) + + return true +} + // private_key_set_bytes decodes a byte-encoded private key, and returns -// true iff the operation was successful. +// true if and only if (⟺) the operation was successful. private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool { if len(b) != PRIVATE_KEY_SIZE { return false @@ -79,6 +97,21 @@ private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool { return true } +// private_key_set sets priv_key to src. +private_key_set :: proc(priv_key, src: ^Private_Key) { + if src == nil || !src._is_initialized { + private_key_clear(priv_key) + return + } + + copy(priv_key._b[:], src._b[:]) + grp.sc_set(&priv_key._s, &src._s) + copy(priv_key._hdigest2[:], src._hdigest2[:]) + public_key_set(&priv_key._pub_key, &src._pub_key) + + priv_key._is_initialized = true +} + // private_key_bytes sets dst to byte-encoding of priv_key. private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key") @@ -87,9 +120,15 @@ private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { copy(dst, priv_key._b[:]) } +// private_key_public_bytes sets dst to the byte-encoding of the public +// key corresponding to priv_key. +private_key_public_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + public_key_bytes(&priv_key._pub_key, dst) +} + // private_key_clear clears priv_key to the uninitialized state. private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { - mem.zero_explicit(priv_key, size_of(Private_Key)) + crypto.zero_explicit(priv_key, size_of(Private_Key)) } // sign writes the signature by priv_key over msg to sig. @@ -149,7 +188,7 @@ sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) { } // public_key_set_bytes decodes a byte-encoded public key, and returns -// true iff the operation was successful. +// true if and only if (⟺) the operation was successful. public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) -> bool { if len(b) != PUBLIC_KEY_SIZE { return false @@ -168,9 +207,19 @@ public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) -> return true } +// public_key_set sets pub_key to src. +public_key_set :: proc(pub_key, src: ^Public_Key) { + if src == nil || !src._is_initialized { + public_key_clear(pub_key) + return + } + + pub_key^ = src^ +} + // public_key_set_priv sets pub_key to the public component of priv_key. public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { - ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized public key") + ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key") src := &priv_key._pub_key copy(pub_key._b[:], src._b[:]) @@ -187,14 +236,19 @@ public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { copy(dst, pub_key._b[:]) } -// public_key_equal returns true iff pub_key is equal to other. +// public_key_equal returns true if and only if (⟺) pub_key is equal to other. public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool { ensure(pub_key._is_initialized && other._is_initialized, "crypto/ed25519: uninitialized public key") return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1 } -// verify returns true iff sig is a valid signature by pub_key over msg. +// public_key_clear clears pub_key to the uninitialized state. +public_key_clear :: proc "contextless" (pub_key: ^Public_Key) { + crypto.zero_explicit(pub_key, size_of(Public_Key)) +} + +// verify returns true if and only if (⟺) sig is a valid signature by pub_key over msg. // // The optional `allow_small_order_A` parameter will make this // implementation strictly compatible with FIPS 186-5, at the expense of diff --git a/core/crypto/hash/doc.odin b/core/crypto/hash/doc.odin index 1dfd97de2..992e47e86 100644 --- a/core/crypto/hash/doc.odin +++ b/core/crypto/hash/doc.odin @@ -1,5 +1,5 @@ /* -package hash provides a generic interface to the supported hash algorithms. +A generic interface to the supported hash algorithms. A high-level convenience procedure group `hash` is provided to easily accomplish common tasks. diff --git a/core/crypto/hash/hash.odin b/core/crypto/hash/hash.odin index d47f0ab46..31f07ac72 100644 --- a/core/crypto/hash/hash.odin +++ b/core/crypto/hash/hash.odin @@ -2,14 +2,14 @@ package crypto_hash /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. */ +import "core:crypto" import "core:io" -import "core:mem" // hash_bytes will hash the given input and return the computed digest // in a newly allocated slice. @@ -21,8 +21,7 @@ hash_string :: proc(algorithm: Algorithm, data: string, allocator := context.all // in a newly allocated slice. hash_bytes :: proc(algorithm: Algorithm, data: []byte, allocator := context.allocator) -> []byte { dst := make([]byte, DIGEST_SIZES[algorithm], allocator) - hash_bytes_to_buffer(algorithm, data, dst) - return dst + return hash_bytes_to_buffer(algorithm, data, dst) } // hash_string_to_buffer will hash the given input and assign the @@ -46,7 +45,7 @@ hash_bytes_to_buffer :: proc(algorithm: Algorithm, data, hash: []byte) -> []byte update(&ctx, data) final(&ctx, hash) - return hash + return hash[:DIGEST_SIZES[algorithm]] } // hash_stream will incrementally fully consume a stream, and return the @@ -62,7 +61,7 @@ hash_stream :: proc( ctx: Context buf: [MAX_BLOCK_SIZE * 4]byte - defer mem.zero_explicit(&buf, size_of(buf)) + defer crypto.zero_explicit(&buf, size_of(buf)) init(&ctx, algorithm) diff --git a/core/crypto/hash/hash_js.odin b/core/crypto/hash/hash_js.odin new file mode 100644 index 000000000..99309b944 --- /dev/null +++ b/core/crypto/hash/hash_js.odin @@ -0,0 +1,10 @@ +#+build js +package crypto_hash + +hash :: proc { + hash_stream, + hash_bytes, + hash_string, + hash_bytes_to_buffer, + hash_string_to_buffer, +} diff --git a/core/crypto/hash/hash_os.odin b/core/crypto/hash/hash_os.odin index d54e657ad..49c1a0ff8 100644 --- a/core/crypto/hash/hash_os.odin +++ b/core/crypto/hash/hash_os.odin @@ -1,26 +1,27 @@ #+build !freestanding +#+build !js package crypto_hash import "core:io" import "core:os" -// hash_file will read the file provided by the given handle and return the +// `hash_file` will read the file provided by the given handle and return the // computed digest in a newly allocated slice. -hash_file :: proc( - algorithm: Algorithm, - hd: os.Handle, +hash_file_by_handle :: proc( + algorithm: Algorithm, + handle: ^os.File, load_at_once := false, - allocator := context.allocator, + allocator := context.allocator, ) -> ( []byte, io.Error, ) { if !load_at_once { - return hash_stream(algorithm, os.stream_from_handle(hd), allocator) + return hash_stream(algorithm, os.to_stream(handle), allocator) } - buf, ok := os.read_entire_file(hd, allocator) - if !ok { + buf, err := os.read_entire_file(handle, allocator) + if err != nil { return nil, io.Error.Unknown } defer delete(buf, allocator) @@ -28,11 +29,30 @@ hash_file :: proc( return hash_bytes(algorithm, buf, allocator), io.Error.None } +hash_file_by_name :: proc( + algorithm: Algorithm, + filename: string, + load_at_once := false, + allocator := context.allocator, +) -> ( + []byte, + io.Error, +) { + handle, err := os.open(filename) + defer os.close(handle) + + if err != nil { + return {}, io.Error.Unknown + } + return hash_file_by_handle(algorithm, handle, load_at_once, allocator) +} + + hash :: proc { hash_stream, - hash_file, + hash_file_by_handle, hash_bytes, hash_string, hash_bytes_to_buffer, hash_string_to_buffer, -} +} \ No newline at end of file diff --git a/core/crypto/hash/low_level.odin b/core/crypto/hash/low_level.odin index 242eadd5f..44b2a8100 100644 --- a/core/crypto/hash/low_level.odin +++ b/core/crypto/hash/low_level.odin @@ -235,7 +235,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { switch &impl in ctx._impl { diff --git a/core/crypto/hkdf/hkdf.odin b/core/crypto/hkdf/hkdf.odin index bffe09eff..b2b515676 100644 --- a/core/crypto/hkdf/hkdf.odin +++ b/core/crypto/hkdf/hkdf.odin @@ -1,14 +1,13 @@ /* -package hkdf implements the HKDF HMAC-based Extract-and-Expand Key -Derivation Function. +`HKDF` HMAC-based Extract-and-Expand Key Derivation Function. See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]] */ package hkdf +import "core:crypto" import "core:crypto/hash" import "core:crypto/hmac" -import "core:mem" // extract_and_expand derives output keying material (OKM) via the // HKDF-Extract and HKDF-Expand algorithms, with the specified has @@ -19,7 +18,7 @@ extract_and_expand :: proc(algorithm: hash.Algorithm, salt, ikm, info, dst: []by tmp: [hash.MAX_DIGEST_SIZE]byte prk := tmp[:h_len] - defer mem.zero_explicit(raw_data(prk), h_len) + defer crypto.zero_explicit(raw_data(prk), h_len) extract(algorithm, salt, ikm, prk) expand(algorithm, prk, info, dst) @@ -84,7 +83,7 @@ expand :: proc(algorithm: hash.Algorithm, prk, info, dst: []byte) { if r > 0 { tmp: [hash.MAX_DIGEST_SIZE]byte blk := tmp[:h_len] - defer mem.zero_explicit(raw_data(blk), h_len) + defer crypto.zero_explicit(raw_data(blk), h_len) _F(&base, prev, info, n + 1, blk) copy(dst_blk, blk) diff --git a/core/crypto/hmac/hmac.odin b/core/crypto/hmac/hmac.odin index f74d6492f..56decc0ef 100644 --- a/core/crypto/hmac/hmac.odin +++ b/core/crypto/hmac/hmac.odin @@ -1,5 +1,5 @@ /* -package hmac implements the HMAC MAC algorithm. +`HMAC` message authentication code (`MAC`) algorithm. See: - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]] @@ -8,7 +8,6 @@ package hmac import "core:crypto" import "core:crypto/hash" -import "core:mem" // sum will compute the HMAC with the specified algorithm and key // over msg, and write the computed tag to dst. It requires that @@ -22,7 +21,7 @@ sum :: proc(algorithm: hash.Algorithm, dst, msg, key: []byte) { } // verify will verify the HMAC tag computed with the specified algorithm -// and key over msg and return true iff the tag is valid. It requires +// and key over msg and return true if and only if (⟺) the tag is valid. It requires // that the tag is correctly sized. verify :: proc(algorithm: hash.Algorithm, tag, msg, key: []byte) -> bool { tag_buf: [hash.MAX_DIGEST_SIZE]byte @@ -126,7 +125,7 @@ _init_hashes :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) { kLen := len(key) B := hash.BLOCK_SIZES[algorithm] K0 := K0_buf[:B] - defer mem.zero_explicit(raw_data(K0), B) + defer crypto.zero_explicit(raw_data(K0), B) switch { case kLen == B, kLen < B: @@ -157,7 +156,7 @@ _init_hashes :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) { hash.init(&ctx._i_hash, algorithm) kPad := kPad_buf[:B] - defer mem.zero_explicit(raw_data(kPad), B) + defer crypto.zero_explicit(raw_data(kPad), B) for v, i in K0 { kPad[i] = v ~ _I_PAD diff --git a/core/crypto/kmac/kmac.odin b/core/crypto/kmac/kmac.odin index 6f58e20a7..f0c27739a 100644 --- a/core/crypto/kmac/kmac.odin +++ b/core/crypto/kmac/kmac.odin @@ -1,5 +1,5 @@ /* -package kmac implements the KMAC MAC algorithm. +`KMAC` message authentication code (`MAC`) algorithm. See: - [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]] @@ -32,7 +32,7 @@ sum :: proc(sec_strength: int, dst, msg, key, domain_sep: []byte) { } // verify will verify the KMAC tag computed with the specified security -// strength, key and domain separator over msg and return true iff the +// strength, key and domain separator over msg and return true if and only if (⟺) the // tag is valid. verify :: proc(sec_strength: int, tag, msg, key, domain_sep: []byte, allocator := context.temp_allocator) -> bool { derived_tag := make([]byte, len(tag), allocator) diff --git a/core/crypto/legacy/keccak/keccak.odin b/core/crypto/legacy/keccak/keccak.odin index 40fc2729f..ffca1c95c 100644 --- a/core/crypto/legacy/keccak/keccak.odin +++ b/core/crypto/legacy/keccak/keccak.odin @@ -1,5 +1,5 @@ /* -package keccak implements the Keccak hash algorithm family. +`Keccak` hash algorithm family. During the SHA-3 standardization process, the padding scheme was changed thus Keccac and SHA-3 produce different outputs. Most users should use @@ -10,7 +10,7 @@ package keccak /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -77,7 +77,7 @@ update :: proc "contextless" (ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc "contextless" (ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _sha3.final((^_sha3.Context)(ctx), hash, finalize_clone) diff --git a/core/crypto/legacy/md5/md5.odin b/core/crypto/legacy/md5/md5.odin index 050501d98..ddc795b7d 100644 --- a/core/crypto/legacy/md5/md5.odin +++ b/core/crypto/legacy/md5/md5.odin @@ -1,5 +1,5 @@ /* -package md5 implements the MD5 hash algorithm. +`MD5` hash algorithm. WARNING: The MD5 algorithm is known to be insecure and should only be used for interoperating with legacy applications. @@ -12,15 +12,16 @@ package md5 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. */ +import "base:intrinsics" +import "core:crypto" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // DIGEST_SIZE is the MD5 digest size in bytes. DIGEST_SIZE :: 16 @@ -69,7 +70,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { ensure(ctx.is_initialized) @@ -100,7 +101,7 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { i += 1 } transform(ctx, ctx.data[:]) - mem.set(&ctx.data, 0, 56) + intrinsics.mem_zero(&ctx.data, 56) } ctx.bitlen += u64(ctx.datalen * 8) @@ -124,7 +125,7 @@ reset :: proc(ctx: ^$T) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } /* diff --git a/core/crypto/legacy/sha1/sha1.odin b/core/crypto/legacy/sha1/sha1.odin index 5a2b57005..bf3ad9602 100644 --- a/core/crypto/legacy/sha1/sha1.odin +++ b/core/crypto/legacy/sha1/sha1.odin @@ -1,5 +1,5 @@ /* -package sha1 implements the SHA1 hash algorithm. +`SHA1` hash algorithm. WARNING: The SHA1 algorithm is known to be insecure and should only be used for interoperating with legacy applications. @@ -13,15 +13,16 @@ package sha1 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. */ +import "base:intrinsics" +import "core:crypto" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // DIGEST_SIZE is the SHA1 digest size in bytes. DIGEST_SIZE :: 20 @@ -76,7 +77,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { ensure(ctx.is_initialized) @@ -107,7 +108,7 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { i += 1 } transform(ctx, ctx.data[:]) - mem.set(&ctx.data, 0, 56) + intrinsics.mem_zero(&ctx.data, 56) } ctx.bitlen += u64(ctx.datalen * 8) @@ -131,7 +132,7 @@ reset :: proc(ctx: ^$T) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } /* diff --git a/core/crypto/mldsa/api.odin b/core/crypto/mldsa/api.odin new file mode 100644 index 000000000..ce4f9cffd --- /dev/null +++ b/core/crypto/mldsa/api.odin @@ -0,0 +1,290 @@ +package mldsa + +import "core:crypto" +import "core:crypto/_mldsa" + +// Parameters are the supported ML-DSA parameter sets. +Parameters :: enum { + Invalid, + ML_DSA_44, + ML_DSA_65, + ML_DSA_87, +} + +// PRIVATE_KEY_SEED_SIZE is the size of a private key in bytes. +PRIVATE_KEY_SEED_SIZE :: _mldsa.SEEDBYTES // 32-bytes + +// MAX_CTX_SIZE is the maximum size of the signature context +// (domain separation tag) in bytes. +MAX_CTX_SIZE :: _mldsa.CTXBYTES_MAX // 255-bytes + +// PUBLIC_KEY_SIZES are the per-parameter sizes of a public +// key in bytes. +PUBLIC_KEY_SIZES := [Parameters]int { + .Invalid = 0, + .ML_DSA_44 = 1312, + .ML_DSA_65 = 1952, + .ML_DSA_87 = 2592, +} + +// SIGNATURE_SIZES are the per-parameter sizes of a signature +// in byte. +SIGNATURE_SIZES := [Parameters]int { + .Invalid = 0, + .ML_DSA_44 = 2420, + .ML_DSA_65 = 3309, + .ML_DSA_87 = 4627, +} + +@(private="file") +_PARAMS_TO_INTERNAL := [Parameters]^_mldsa.Params { + .Invalid = nil, + .ML_DSA_44 = &_mldsa.Params_44, + .ML_DSA_65 = &_mldsa.Params_65, + .ML_DSA_87 = &_mldsa.Params_87, +} + +// Private_Key is a ML-DSA private key. +Private_Key :: _mldsa.Private_Key + +// Public_Key is a ML-DSA public key. +Public_Key :: _mldsa.Public_Key + +// private_key_generate uses the system entropy source to generate a new +// Private_Key. This will only fail if and only if (⟺) the system entropy +// source is missing or broken. +@(require_results) +private_key_generate :: proc(priv_key: ^Private_Key, params: Parameters) -> bool { + private_key_clear(priv_key) + + if !crypto.HAS_RAND_BYTES { + return false + } + + params_ := _PARAMS_TO_INTERNAL[params] + if params_ == nil { + return false + } + + seed: [PRIVATE_KEY_SEED_SIZE]byte = --- + defer crypto.zero_explicit(&seed, size_of(seed)) + + crypto.rand_bytes(seed[:]) + + _mldsa.dsa_keygen_internal(priv_key, seed[:], params_) + + return true +} + +// private_key_set_bytes decodes a byte-encoded private key in "seed" format, +// and returns true if and only if (⟺) the operation was successful. +@(require_results) +private_key_set_bytes :: proc(priv_key: ^Private_Key, params: Parameters, b: []byte) -> bool { + private_key_clear(priv_key) + + params_ := _PARAMS_TO_INTERNAL[params] + if params_ == nil { + return false + } + if len(b) != PRIVATE_KEY_SEED_SIZE { + return false + } + + _mldsa.dsa_keygen_internal(priv_key, b, params_) + + return true +} + +// private_key_bytes sets dst to byte-encoding of priv_key in the "seed" +// format. +private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + ensure(priv_key.params != nil, "crypto/mldsa: uninitialized private key") + ensure(len(dst) == PRIVATE_KEY_SEED_SIZE, "crypto/mldsa: invalid destination size") + + copy(dst, priv_key.seed[:]) +} + +// private_key_public_bytes sets dst to the byte-encoding of the public +// key corresponding to priv_key. +private_key_public_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { + public_key_bytes(&priv_key.pub_key, dst) +} + +// private_key_set sets priv_key to src. +private_key_set :: proc(priv_key, src: ^Private_Key) { + if src == nil || internal_to_params(src.params) == .Invalid { + private_key_clear(priv_key) + return + } + + _mldsa.set_sk(priv_key, src) +} + +// private_key_equal returns true if and only if (⟺) the private keys are +// equal, in constant time. +@(require_results) +private_key_equal :: proc(p, q: ^Private_Key) -> bool { + if p.params != q.params { + return false + } + if p.params == nil { + return true + } + + // Just compare the seed that was passed to dsa_keygen_internal, + // since the process is completely deterministic. + return crypto.compare_constant_time(p.seed[:], q.seed[:]) == 1 +} + +// private_key_clear clears priv_key to the uninitialized state. +private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { + _mldsa.clear_sk(priv_key) +} + +// public_key_set_bytes decodes a byte-encoded public key, and returns +// true if and only if (⟺) the operation was successful. +@(require_results) +public_key_set_bytes :: proc(pub_key: ^Public_Key, params: Parameters, b: []byte) -> bool { + params_ := _PARAMS_TO_INTERNAL[params] + if params_ == nil { + return false + } + + return _mldsa.unpack_pk(pub_key, b, params_) +} + +// public_key_set sets pub_key to src. +public_key_set :: proc(pub_key, src: ^Public_Key) { + if src == nil || internal_to_params(src.params) == .Invalid { + public_key_clear(pub_key) + return + } + + _mldsa.set_pk(pub_key, src) +} + +// public_key_set_priv sets pub_key to the public component of priv_key. +public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { + ensure(priv_key.params != nil, "crypto/mldsa: uninitialized private key") + public_key_set(pub_key, &priv_key.pub_key) +} + +// public_key_bytes sets dst to byte-encoding of pub_key. +public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { + ensure(pub_key.params != nil, "crypto/mldsa: uninitialized public key") + params := internal_to_params(pub_key.params) + ensure(len(dst) == PUBLIC_KEY_SIZES[params], "crypto/mldsa: invalid destination size") + + _ = _mldsa.pack_pk(dst, pub_key) +} + +// public_key_equal returns true if and only if (⟺) the public keys are equal, +// in constant time. +@(require_results) +public_key_equal :: proc(p, q: ^Public_Key) -> bool { + if p.params != q.params { + return false + } + if p.params == nil { + return true + } + + // Comparing the pre-computed hash should be enough, but pack + // both public keys and do the comparisons. + PUBLIC_KEY_SIZE_MAX :: 2592 + + l := PUBLIC_KEY_SIZES[internal_to_params(p.params)] + p_buf_, q_buf_: [PUBLIC_KEY_SIZE_MAX]byte = ---, --- + p_buf, q_buf := p_buf_[:l], q_buf_[:l] + + _ = _mldsa.pack_pk(p_buf, p) + _ = _mldsa.pack_pk(q_buf, q) + + return crypto.compare_constant_time(p_buf, q_buf) == 1 +} + +// public_key_clear clears pub_key to the uninitialized state. +public_key_clear :: proc "contextless" (pub_key: ^Public_Key) { + _mldsa.clear_pk(pub_key) +} + +// sign writes the signature by priv_key over (ctx, msg) to sig and +// returns true if and only if (⟺) the signing succeeded. +// +// ctx is an optional domain separation tag and may be omitted (nil). +@(require_results) +sign :: proc(priv_key: ^Private_Key, ctx, msg, sig: []byte, deterministic := !crypto.HAS_RAND_BYTES) -> bool { + params := internal_to_params(priv_key.params) + ensure(params != .Invalid, "crypto/mldsa: invalid private key") + ensure(len(sig) == SIGNATURE_SIZES[params], "crypto/mldsa: invalid destination size") + + if !deterministic && !crypto.HAS_RAND_BYTES { + return false + } + if len(ctx) > MAX_CTX_SIZE { + return false + } + + rnd: [_mldsa.RNDBYTES]byte + defer crypto.zero_explicit(&rnd, size_of(rnd)) + + if !deterministic { + crypto.rand_bytes(rnd[:]) + } + + return _mldsa.dsa_sign_internal(sig, msg, ctx, rnd[:], priv_key) +} + +// verify returns true if and only if (⟺) sig is a valid signature by pub_key +// over (ctx, msg). +@(require_results) +verify :: proc(pub_key: ^Public_Key, ctx, msg, sig: []byte) -> bool { + params := internal_to_params(pub_key.params) + ensure(params != .Invalid, "crypto/mldsa: invalid public key") + + if len(sig) != SIGNATURE_SIZES[params] { + return false + } + if len(ctx) > MAX_CTX_SIZE { + return false + } + + return _mldsa.dsa_verify_internal(sig, msg, ctx, pub_key) +} + +// params returns the Parameters used by a Private_Key or Public_Key +// instance. +@(require_results) +params :: proc(k: ^$T) -> Parameters where (T == Private_Key || T == Public_Key) { + return internal_to_params(k.params) +} + +// key_size returns the key size of a Private_Key or Public_Key in bytes. +@(require_results) +key_size :: proc(k: ^$T) -> int where (T == Private_Key || T == Public_Key) { + when T == Private_Key { + return PRIVATE_KEY_SEED_SIZE + } else { + return PUBLIC_KEY_SIZES[internal_to_params(k.params)] + } +} + +// signature_size returns the key size of a signature in bytes. +@(require_results) +signature_size :: proc(k: ^$T) -> int where (T == Private_Key || T == Public_Key) { + return SIGNATURE_SIZES[internal_to_params(k.params)] +} + +@(private="file",require_results) +internal_to_params :: proc "contextless" (params: ^_mldsa.Params) -> Parameters { + switch params { + case &_mldsa.Params_44: + return .ML_DSA_44 + case &_mldsa.Params_65: + return .ML_DSA_65 + case &_mldsa.Params_87: + return .ML_DSA_87 + case: + return .Invalid + } +} diff --git a/core/crypto/mldsa/doc.odin b/core/crypto/mldsa/doc.odin new file mode 100644 index 000000000..4801c070e --- /dev/null +++ b/core/crypto/mldsa/doc.odin @@ -0,0 +1,7 @@ +/* +Module-Lattice-Based Digital Signature Algorithm. + +See: +- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf ]] +*/ +package mldsa diff --git a/core/crypto/mlkem/api.odin b/core/crypto/mlkem/api.odin new file mode 100644 index 000000000..3e3956ba8 --- /dev/null +++ b/core/crypto/mlkem/api.odin @@ -0,0 +1,304 @@ +package mlkem + +import "core:crypto" +import "core:crypto/_mlkem" + +// Parameters are the supported ML-KEM parameter sets. +Parameters :: enum { + Invalid, + ML_KEM_512, + ML_KEM_768, + ML_KEM_1024, +} + +// DECAPSULATION_KEY_SEED_SIZE is the size of a Decapsulation key in bytes. +DECAPSULATION_KEY_SEED_SIZE :: 64 // (d, z) in NIST terms. + +// DECAPSULATION_KEY_EXPANDED_SIZES are the per-parameter sizes of the +// decapsulation key in bytes. +DECAPSULATION_KEY_EXPANDED_SIZES := [Parameters]int { + .Invalid = 0, + .ML_KEM_512 = _mlkem.DECAPSKEYBYTES_512, // 1632-bytes + .ML_KEM_768 = _mlkem.DECAPSKEYBYTES_768, // 2400-bytes + .ML_KEM_1024 = _mlkem.DECAPSKEYBYTES_1024, // 3168-bytes +} + +// ENCAPSULATION_KEY_SIZES are the per-parameter sizes of the encapsulation +// key in bytes. +ENCAPSULATION_KEY_SIZES := [Parameters]int { + .Invalid = 0, + .ML_KEM_512 = _mlkem.ENCAPSKEYBYTES_512, // 800-bytes + .ML_KEM_768 = _mlkem.ENCAPSKEYBYTES_768, // 1184-bytes + .ML_KEM_1024 = _mlkem.ENCAPSKEYBYTES_1024, // 1568-bytes +} + +// CIPHERTEXT_SIZES are the per-parameter set sizes of the ciphertext +// in bytes. +CIPHERTEXT_SIZES := [Parameters]int { + .Invalid = 0, + .ML_KEM_512 = _mlkem.CIPHERTEXTBYTES_512, // 768-bytes + .ML_KEM_768 = _mlkem.CIPHERTEXTBYTES_768, // 1088-bytes + .ML_KEM_1024 = _mlkem.CIPHERTEXTBYTES_1024, // 1568-bytes +} + +// SHARED_SECRET_SIZE is the size of the final shared secret in bytes. +SHARED_SECRET_SIZE :: 32 + +// Decapsulation_Key is a ML-KEM decapsulation (aka "private") key. +// This implementation opts to include the encapsulation (aka "public") +// key as well for cases where the decapsulation key is reused (eg: HPKE +// with X-Wing). +Decapsulation_Key :: _mlkem.Decapsulation_Key + +// Encapsulation_Key is a ML-KEM encapsulation (aka "public") key. +Encapsulation_Key :: _mlkem.Encapsulation_Key + +// decapsulation_key_generate uses the system entropy source to generate +// a decapsulation key. This will only fail if and only if (⟺) the system +// entropy source is missing or broken. +@(require_results) +decapsulation_key_generate :: proc(dk: ^Decapsulation_Key, params: Parameters) -> bool { + decapsulation_key_clear(dk) + + if !crypto.HAS_RAND_BYTES { + return false + } + + k := params_to_k(params) + if k == 0 { + panic("crypto/mlkem: invalid parameter set") + } + + seed: [DECAPSULATION_KEY_SEED_SIZE]byte = --- + defer crypto.zero_explicit(&seed, size_of(seed)) + + crypto.rand_bytes(seed[:]) + _mlkem.kem_keygen_internal(dk, seed[:], k) + + return true +} + +// decapsulation_key_set_bytes decodes a byte-encoded decapsulation key +// in (d, z) "seed" format, and returns true if and only if (⟺) the +// operation was successful. +@(require_results) +decapsulation_key_set_bytes :: proc(dk: ^Decapsulation_Key, params: Parameters, seed: []byte) -> bool { + k := params_to_k(params) + if k == 0 { + return false + } + if len(seed) != DECAPSULATION_KEY_SEED_SIZE { + return false + } + + _mlkem.kem_keygen_internal(dk, seed, k) + + return true +} + +// decapsulation_key_bytes sets dst to byte-encoding of dk in the (d, z) +// "seed" format. +decapsulation_key_bytes :: proc(dk: ^Decapsulation_Key, dst: []byte) { + ensure(dk.pke_dk.k != 0, "crypto/mlkem: uninitialized Decapsulation_Key") + ensure(len(dst) == DECAPSULATION_KEY_SEED_SIZE, "crypto/mlkem: invalid destination size") + + copy(dst, dk.seed[:]) +} + +// decapsulation_key_expanded_bytes sets dst to the byte-encoding of dk. +// in the expanded FIPS 203 format. This primarily exists for export +// purposes. +decapsulation_key_expanded_bytes :: proc(dk: ^Decapsulation_Key, dst: []byte) { + dk_len: int + switch dk.pke_dk.k { + case _mlkem.K_512: + dk_len = DECAPSULATION_KEY_EXPANDED_SIZES[.ML_KEM_512] + case _mlkem.K_768: + dk_len = DECAPSULATION_KEY_EXPANDED_SIZES[.ML_KEM_768] + case _mlkem.K_1024: + dk_len = DECAPSULATION_KEY_EXPANDED_SIZES[.ML_KEM_1024] + case: + panic("crypto/mlkem: uninitialized Decapsulation_Key") + } + ensure(len(dst) == dk_len, "crypto/mlkem: invalid destination size") + + _mlkem.decapsulation_key_expanded_bytes(dk, dst) +} + +// decapsulation_key_encaps_bytes sets dst to the byte-encoding of the +// encasulation key corresponding to dk. +decapsulation_key_encaps_bytes :: proc(dk: ^Decapsulation_Key, dst: []byte) { + encapsulation_key_bytes(&dk.ek, dst) +} + +// decapsulation_key_clear clears dk to the uninitialized state. +decapsulation_key_clear :: proc(dk: ^Decapsulation_Key) { + crypto.zero_explicit(dk, size_of(Decapsulation_Key)) +} + +// encapsulation_key_set_bytes decodes a byte-encoded encapsulation key, +// and returns true if and only if (⟺) the operation was successful. +@(require_results) +encapsulation_key_set_bytes :: proc(ek: ^Encapsulation_Key, params: Parameters, b: []byte) -> bool { + k := params_to_k(params) + if k == 0 { + return false + } + if len(b) != ENCAPSULATION_KEY_SIZES[params] { + return false + } + + return _mlkem.encapsulation_key_set_bytes(ek, k, b) +} + +// encapsulation_key_set_decaps sets ek to the encapsulation key corresponding +// to dk. +encapsulation_key_set_decaps :: proc(ek: ^Encapsulation_Key, dk: ^Decapsulation_Key) { + ensure(dk.pke_dk.k != 0, "crypto/mlkem: uninitialized Decapsulation_Key") + _mlkem.encapsulation_key_set_decaps(ek, dk) +} + +// encapsulation_key_encaps_bytes sets dst to the byte-encoding of ek. +encapsulation_key_bytes :: proc(ek: ^Encapsulation_Key, dst: []byte) { + ensure(ek.pke_ek.k != 0, "crypto/mlkem: uninitialized Encapsulation_Key") + + k_len: int + switch ek.pke_ek.k { + case _mlkem.K_512: + k_len = ENCAPSULATION_KEY_SIZES[.ML_KEM_512] + case _mlkem.K_768: + k_len = ENCAPSULATION_KEY_SIZES[.ML_KEM_768] + case _mlkem.K_1024: + k_len = ENCAPSULATION_KEY_SIZES[.ML_KEM_1024] + case: + panic("crypto/mlkem: invalid destination size") + } + + copy(dst, ek.raw_bytes[:k_len]) +} + +// encapsulation_key_clear clears ek to the uninitialized state. +encapsulation_key_clear :: proc(ek: ^Encapsulation_Key) { + crypto.zero_explicit(ek, size_of(Encapsulation_Key)) +} + +// encaps_raw_ek_bytes uses the byte encoded encapsulation key to generate +// a shared secret and an associated ciphertext. This routine will fail +// if the system entropy source is unavailable, or of the encapsulation key +// is invalid. +@(require_results) +encaps_ek_raw_bytes :: proc(params: Parameters, raw_ek, shared_secret, ciphertext: []byte) -> bool { + ek: Encapsulation_Key = --- + if !encapsulation_key_set_bytes(&ek, params, raw_ek) { + return false + } + defer encapsulation_key_clear(&ek) + + return encaps_ek(&ek, shared_secret, ciphertext) +} + +// encaps_ek uses the encapsulation key to generate a shared secret and an +// associated ciphertext. This routine will fail if the system entropy source +// is unavailable. +@(require_results) +encaps_ek :: proc(ek: ^Encapsulation_Key, shared_secret, ciphertext: []byte) -> bool { + ensure(len(shared_secret) == SHARED_SECRET_SIZE, "crypto/mlkem: invalid shared_seret size") + + if !crypto.HAS_RAND_BYTES { + return false + } + + m: [_mlkem.SYMBYTES]byte = --- + defer crypto.zero_explicit(&m, size_of(m)) + + crypto.rand_bytes(m[:]) + _mlkem.kem_encaps_internal(shared_secret, ciphertext, ek, m[:]) + + return true +} + +encaps :: proc { + encaps_ek, + encaps_ek_raw_bytes, +} + +// decaps uses the decapsulation key to generate a shared secret from a +// ciphertext. Due to ML-KEM's implicit rejection mechanism, this function +// will only return false if and only if (⟺) the lengths of the inputs +// are invalid or the decapsulation key is uninitialized. +// +// This routine returning true does not guarantee that the shared secret +// matches that generated by the peer. +@(require_results) +decaps :: proc(dk: ^Decapsulation_Key, ciphertext, shared_secret: []byte) -> bool { + ensure(len(shared_secret) == SHARED_SECRET_SIZE, "crypto/mlkem: invalid shared_seret size") + + ct_len: int + switch dk.pke_dk.k { + case _mlkem.K_512: + ct_len = CIPHERTEXT_SIZES[.ML_KEM_512] + case _mlkem.K_768: + ct_len = CIPHERTEXT_SIZES[.ML_KEM_768] + case _mlkem.K_1024: + ct_len = CIPHERTEXT_SIZES[.ML_KEM_1024] + case: + return false + } + if len(ciphertext) != ct_len { + return false + } + + _mlkem.kem_decaps_internal(shared_secret, dk, ciphertext) + + return true +} + +// params returns the Parameters used by a Decapsulation_Key or +// Encapsulation_Key instance. +@(require_results) +params :: proc(k: ^$T) -> Parameters where (T == Encapsulation_Key || T == Decapsulation_Key) { + when T == Encapsulation_Key { + return k_to_params(k.pke_ek.k) + } else { + return k_to_params(k.pke_dk.k) + } +} + +// key_size returns the key size of a Decapsulation_Key or Encapsulation_Key +// in bytes. +@(require_results) +key_size :: proc(k: ^$T) -> int where (T == Encapsulation_Key || T == Decapsulation_Key) { + when T == Encapsulation_Key { + return ENCAPSULATION_KEY_SIZES[k.pke_ek.k] + } else { + return DECAPSULATION_KEY_SEED_SIZE + } +} + +@(private="file") +params_to_k :: #force_inline proc "contextless" (params: Parameters) -> int { + #partial switch params { + case .ML_KEM_512: + return _mlkem.K_512 + case .ML_KEM_768: + return _mlkem.K_768 + case .ML_KEM_1024: + return _mlkem.K_1024 + } + + return 0 +} + +@(private="file") +k_to_params :: #force_inline proc "contextless" (k: int) -> Parameters { + switch k { + case _mlkem.K_512: + return .ML_KEM_512 + case _mlkem.K_768: + return .ML_KEM_768 + case _mlkem.K_1024: + return .ML_KEM_1024 + } + + return .Invalid +} diff --git a/core/crypto/mlkem/doc.odin b/core/crypto/mlkem/doc.odin new file mode 100644 index 000000000..ec32def25 --- /dev/null +++ b/core/crypto/mlkem/doc.odin @@ -0,0 +1,7 @@ +/* +ML-KEM Module-Lattice-Based Key-Encapsulation Mechanism. + +See: +- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf ]] +*/ +package mlkem diff --git a/core/crypto/noise/api.odin b/core/crypto/noise/api.odin new file mode 100644 index 000000000..bae58a399 --- /dev/null +++ b/core/crypto/noise/api.odin @@ -0,0 +1,590 @@ +package noise + +import "base:runtime" +import "core:crypto/aead" +import "core:crypto/ecdh" +import "core:crypto/hash" +import "core:strings" + +// MAX_PACKET_SIZE is the maximum Noise message size, including TAG_SIZE +// if relevant (`seal_message`, `open_message`). +MAX_PACKET_SIZE :: 65535 + +// PSK_SIZE is the size of an optional handshake pre-shared symmetric key. +PSK_SIZE :: 32 +// TAG_SIZE is the size of the AEAD authentication tag. +TAG_SIZE :: 16 +// MAX_STEP_MSG_SIZE is the maximum per-handshake step message size, +// excluding the optional payload. +// +// `e` is DH_LEN, `s` is either DH_LEN or DH_LEN + TAG_SIZE, and there +// is a maximum of one per each message, and a possible mandatory tag. +MAX_STEP_MSG_SIZE :: (MAX_DH_SIZE*2)+TAG_SIZE+TAG_SIZE + +// Status is the status of Noise protocol operation. +Status :: enum { + Ok, + + // States + Handshake_Pending, + Handshake_Complete, + Handshake_Split, + Handshake_Failed, + + // Errors + Invalid_Protocol_String, + Invalid_Pre_Shared_Key, + Invalid_DH_Key, + No_Self_Identity, + No_Peer_Identity, + Unexpected_Peer_Identity, + Unexpected_Pre_Shared_Key, + + DH_Failure, + Invalid_Handshake_Message, + + Decryption_Failure, + IV_Exhausted, + Invalid_Cipher_State, + Invalid_Destination_Buffer, + Invalid_Payload_Message, + Max_Packet_Size, + + Out_Of_Memory, +} + +// Handshake_State is the per-handshake state. +Handshake_State :: struct { + s: ecdh.Private_Key, + e: ecdh.Private_Key, + rs: ecdh.Public_Key, + re: ecdh.Public_Key, + psk: [PSK_SIZE]byte, + + symmetric_state: Symmetric_State, + message_pattern: ^Message_Pattern, + current_message: int, + + status: Status, + + initiator: bool, + pre_set_e: bool, +} + +// Cipher_States are the keyed AEAD instances and associated state, +// derived from a successful handshake. +Cipher_States :: struct { + c1_i_to_r: Cipher_State, + c2_r_to_i: Cipher_State, + + initiator: bool, +} + +// handshake_init initializes a Handshake_State with the provided parameters. +// The relevant values are copied into the Handshake_State instance, and +// can be discarded/sanitized right after handshake_init returns (eg: psk). +// +// Note: While this implementation supports setting `e`, this is primarily +// intended for testing, or cases where the runtime cryptographic entropy +// source is unavailable. Use of this functionality is STRONGLY +// discouraged. +@(require_results) +handshake_init :: proc( + self: ^Handshake_State, + initiator: bool, + prologue: []byte, + s: ^ecdh.Private_Key, // Our static key + rs: ^ecdh.Public_Key, // Peer static key + protocol_name: string, + psk: []byte = nil, + _e: ^ecdh.Private_Key = nil, // Our ephemeral key (for testing/RNG-less systems) +) -> Status { + return handshakestate_initialize( + self, + initiator, + prologue, + s, + _e, + rs, + nil, + protocol_name, + psk, + ) +} + +// handshake_initiator_step takes an input_message received from the responder +// if any and an optional payload to be sent to the responder, and performs +// one step of the Noise handshake process, returning the message to be sent +// to the responder if any, the payload received from the responder if any, +// and the status of the handshake. +// +// The output message MUST be sent to the responder even if the status code +// returned is .Handshake_Complete. +// +// If the dst parameter is provided, the message and payload will be written +// to dst, otherwise new buffers will be allocated. +@(require_results) +handshake_initiator_step :: proc( + self: ^Handshake_State, + input_message: []byte, + payload: []byte = nil, + dst: []byte = nil, + allocator := context.allocator, +) -> ([]byte, []byte, Status) { + output_message: []byte + payload_buffer: []byte + status: Status + + dst := dst + if input_message == nil { + output_message, status = handshakestate_write_message(self, payload, dst, allocator) + } else { + payload_buffer, status = handshakestate_read_message(self, input_message, dst, allocator) + if status == .Handshake_Pending { + if dst != nil { + dst = dst[len(payload_buffer):] + } + output_message, status = handshakestate_write_message(self, payload, dst, allocator) + } + } + + return output_message, payload_buffer, status +} + +// handshake_responder_step takes a input_message received from the initiator, +// and and an optional payload to be sent to the initiator, and performs +// one step of the Noise handshake process, returning the message to be sent +// to the initiator if any, the payload received from the initiator if any, +// and the status of the handshake. +// +// The output message MUST be sent to the initiator even if the status code +// returned is .Handshake_Complete. +// +// If the dst parameter is provided, the message and payload will be written +// to dst, otherwise new buffers will be allocated. +@(require_results) +handshake_responder_step :: proc( + self: ^Handshake_State, + input_message: []byte, + payload: []byte = nil, + dst: []byte = nil, + allocator := context.allocator, +) -> ([]byte, []byte, Status) { + output_message: []byte + + if input_message == nil { + return nil, nil, .Invalid_Handshake_Message + } + + dst := dst + payload_buffer, status := handshakestate_read_message(self, input_message, dst, allocator) + if status == .Handshake_Pending { + if dst != nil { + dst = dst[len(payload_buffer):] + } + output_message, status = handshakestate_write_message(self, payload, dst, allocator) + } + + return output_message, payload_buffer, status +} + +// handshake_write_message calls the Noise HandshakeState's WriteMessage +// function directly. In most cases you are better off using +// handshake_initiator_step or handshake_responder_step. +// +// If the dst parameter is provided, the message and payload will be written +// to dst, otherwise new buffers will be allocated. +@(require_results) +handshake_write_message :: proc( + self: ^Handshake_State, + payload: []byte, + dst: []byte = nil, + allocator := context.allocator, +) -> ([]byte, Status) { + return handshakestate_write_message(self, payload, dst, allocator) +} + +// handshake_read_message calls the Noise HandshakeState's ReadMessage +// function directly. In most cases you are better off using +// handshake_initiator_step or handshake_responder_step. +// +// If the dst parameter is provided, the message and payload will be written +// to dst, otherwise new buffers will be allocated. +@(require_results) +handshake_read_message :: proc( + self: ^Handshake_State, + message: []byte, + dst: []byte = nil, + allocator := context.allocator, +) -> ([]byte, Status) { + return handshakestate_read_message(self, message, dst, allocator) +} + +// handshake_split initializes a Cipher_States instance from a completed +// handshake. This can be called once and only once per Handshake_State +// instance. +@(require_results) +handshake_split :: proc(self: ^Handshake_State, cipher_states: ^Cipher_States) -> Status { + if self.status != .Handshake_Complete { + return self.status + } + + symmetricstate_split(&self.symmetric_state, cipher_states) + if self.message_pattern.is_one_way { + cipherstate_reset(&cipher_states.c2_r_to_i) + cipher_states.c2_r_to_i.is_invalid = true + } + cipher_states.initiator = self.initiator + self.status = .Handshake_Split + + return .Ok +} + +// handshake_peer_identity returns the peer's static DH key used by +// a completed handshake. +// +// This returns a pointer to the Handshake_State's copy of the peer's +// public key, that will get wiped by handshake_reset. If the key is +// needed after a call to handshake_reset, it must be copied. +@(require_results) +handshake_peer_identity :: proc(self: ^Handshake_State) -> (^ecdh.Public_Key, Status) { + #partial switch self.status { + case .Handshake_Complete, .Handshake_Split: + case: + return nil, self.status + } + + if ecdh.curve(&self.rs) == .Invalid { + return nil, .No_Peer_Identity + } + + return &self.rs, .Ok +} + +// handshake_hash returns the handshake transcript hash of a completed +// handshake, for the purposes of channel binding. See 11.2 of the +// specification for details on usage. +// +// This returns a slice to an internal buffer that will get wiped by +// handshake_reset. If the hash is needed after a call to handshake_reset, +// the slice must be copied. +@(require_results) +handshake_hash :: proc(self: ^Handshake_State) -> ([]byte, Status) { + #partial switch self.status { + case .Handshake_Complete, .Handshake_Split: + case: + return nil, self.status + } + + return symmetricstate_get_handshake_hash(&self.symmetric_state), .Ok +} + +// handshake_reset sanitizes the Handshake_State. It is both safe and +// recommended to call this as soon as practical (after any calls to +// handshake_peer_identity, handshake_hash, and handshake_split are +// complete). +handshake_reset :: proc(self: ^Handshake_State) { + handshakestate_reset(self) +} + +// seal_message encrypts the provided data, authenticates the aad and +// ciphertext, and returns the resulting ciphertext. The ciphertext +// will ALWAYS be `len(plaintext) + TAG_SIZE` bytes in length. +// +// If the dst parameter is provided, the ciphertext will be written +// to dst, otherwise a new buffer will be allocated. +@(require_results) +seal_message :: proc(self: ^Cipher_States, aad, plaintext: []byte, dst: []byte = nil, allocator := context.allocator) -> ([]byte, Status) { + data_len := len(plaintext) + + dst := dst + did_alloc: bool + switch { + case dst == nil: + err: runtime.Allocator_Error + dst, err = make([]byte, data_len + TAG_SIZE, allocator) + if err != nil { + return nil, .Out_Of_Memory + } + did_alloc = true + case: + if len(dst) != data_len + TAG_SIZE { + return nil, .Invalid_Destination_Buffer + } + } + + status: Status + switch self.initiator { + case true: + dst, status = cipherstate_encrypt_with_ad(&self.c1_i_to_r, aad, plaintext, dst) + case false: + dst, status = cipherstate_encrypt_with_ad(&self.c2_r_to_i, aad, plaintext, dst) + } + if status != .Ok && did_alloc { + delete(dst, allocator) + dst = nil + } + + return dst, status +} + +// open_message authenticates the aad and ciphertext, decrypts the +// ciphertext and returns the resulting plaintext. The plaintext will +// ALWAYS be `len(ciphertext) - TAG_SIZE` bytes in length. +// +// If the dst parameter is provided, the plaintext will be written to +// dst, otherwise a new buffer will be allocated. +@(require_results) +open_message :: proc(self: ^Cipher_States, aad, ciphertext: []byte, dst: []byte = nil, allocator := context.allocator) -> ([]byte, Status) { + if len(ciphertext) < TAG_SIZE { + return nil, .Invalid_Payload_Message + } + + data_len := len(ciphertext) - TAG_SIZE + + dst := dst + did_alloc: bool + switch { + case dst == nil: + if data_len > 0 { + err: runtime.Allocator_Error + dst, err = make([]byte, data_len, allocator) + if err != nil { + return nil, .Out_Of_Memory + } + did_alloc = true + } + case: + if len(dst) != data_len { + return nil, .Invalid_Destination_Buffer + } + } + + status: Status + switch self.initiator { + case true: + dst, status = cipherstate_decrypt_with_ad(&self.c2_r_to_i, aad, ciphertext, dst) + case false: + dst, status = cipherstate_decrypt_with_ad(&self.c1_i_to_r, aad, ciphertext, dst) + } + if status != .Ok && did_alloc { + delete(dst, allocator) + dst = nil + } + + return dst, status +} + +// cipherstates_rekey updates the selected AEAD key, using a one way function. +// See 11.3 of the specification for examples of usage. +// +// Note: If one side updates the seal_key, the other side must update +// the non-seal_key and vice versa. +@(require_results) +cipherstates_rekey :: proc(self: ^Cipher_States, seal_key: bool) -> Status { + cs := cipherstates_cs(self, seal_key) + if cs.is_invalid { + return .Invalid_Cipher_State + } + if !cipherstate_has_key(cs) { + return .Handshake_Pending + } + + cipherstate_rekey(cs) + + return .Ok +} + +// cipherstates_set_n sets the interal counter used to generate the AEAD +// IV to an explicit value. This can be used to deal with out-of-order +// transport messages. See 11.4 of the specification. +// +// WARNING: Reusing n across different aad/messages with the same Cipher_States +// will result in catastrophic loss of security. +@(require_results) +cipherstates_set_n :: proc(self: ^Cipher_States, seal_key: bool, n: u64) -> Status { + cs := cipherstates_cs(self, seal_key) + if cs.is_invalid { + return .Invalid_Cipher_State + } + if !cipherstate_has_key(cs) { + return .Handshake_Pending + } + + cs.n = n + + return .Ok +} + +// cipherstates_n returns the interal counter used to generate the AEAD +// IV. This can be used to deal with out-of-order transport messages. +// See 11.4 of the specification. +// +// WARNING: Reusing n across different aad/messages with the same Cipher_States +// will result in catastrophic loss of security. +@(require_results) +cipherstates_n :: proc(self: ^Cipher_States, seal_key: bool, n: u64) -> (u64, Status) { + cs := cipherstates_cs(self, seal_key) + if cs.is_invalid { + return 0, .Invalid_Cipher_State + } + if !cipherstate_has_key(cs) { + return 0, .Handshake_Pending + } + + return cs.n, .Ok +} + +// cipherstates_reset sanitizes the Cipher_States. +cipherstates_reset :: proc(self: ^Cipher_States) { + self.initiator = false + cipherstate_reset(&self.c1_i_to_r) + cipherstate_reset(&self.c2_r_to_i) +} + +@(private = "file") +cipherstates_cs :: proc(self: ^Cipher_States, seal_key: bool) -> ^Cipher_State { + switch self.initiator { + case true: + switch seal_key { + case true: + return &self.c1_i_to_r + case false: + return &self.c2_r_to_i + } + case false: + switch seal_key { + case true: + return &self.c2_r_to_i + case false: + return &self.c1_i_to_r + } + } + unreachable() +} + +// split_protocol_string splits a protocol string into individual components. +@(require_results) +split_protocol_string :: proc(protocol_name: string) -> (Handshake_Pattern, ecdh.Curve, aead.Algorithm, hash.Algorithm, Status) { + str := protocol_name + + if len(str) > 255 { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + + s, ok := strings.split_by_byte_iterator(&str, '_') + if !ok || s != "Noise" { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + + if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + + pattern: Handshake_Pattern + switch s { + case "N" : pattern = .N + case "K" : pattern = .K + case "X" : pattern = .X + case "XX": pattern = .XX + case "NK": pattern = .NK + case "NN": pattern = .NN + case "KN": pattern = .KN + case "KK": pattern = .KK + case "NX": pattern = .NX + case "KX": pattern = .KX + case "XN": pattern = .XN + case "IN": pattern = .IN + case "XK": pattern = .XK + case "IK": pattern = .IK + case "IX": pattern = .IX + case "NK1": pattern = .NK1 + case "NX1": pattern = .NX1 + case "X1N": pattern = .X1N + case "X1K": pattern = .X1K + case "XK1": pattern = .XK1 + case "X1K1": pattern = .X1K1 + case "X1X": pattern = .X1X + case "XX1": pattern = .XX1 + case "X1X1": pattern = .X1X1 + case "K1N": pattern = .K1N + case "K1K": pattern = .K1K + case "KK1": pattern = .KK1 + case "K1K1": pattern = .K1K1 + case "K1X": pattern = .K1X + case "KX1": pattern = .KX1 + case "K1X1": pattern = .K1X1 + case "I1N": pattern = .I1N + case "I1K": pattern = .I1K + case "IK1": pattern = .IK1 + case "I1K1": pattern = .I1K1 + case "I1X": pattern = .I1X + case "IX1": pattern = .IX1 + case "I1X1": pattern = .I1X1 + case "Npsk0": pattern = .Npsk0 + case "Kpsk0": pattern = .Kpsk0 + case "Xpsk1": pattern = .Xpsk1 + case "NNpsk0": pattern = .NNpsk0 + case "NNpsk2": pattern = .NNpsk2 + case "NKpsk0": pattern = .NKpsk0 + case "NKpsk2": pattern = .NKpsk2 + case "NXpsk2": pattern = .NXpsk2 + case "XNpsk3": pattern = .XNpsk3 + case "XKpsk3": pattern = .XKpsk3 + case "XXpsk3": pattern = .XXpsk3 + case "KNpsk0": pattern = .KNpsk0 + case "KNpsk2": pattern = .KNpsk2 + case "KKpsk0": pattern = .KKpsk0 + case "KKpsk2": pattern = .KKpsk2 + case "KXpsk2": pattern = .KXpsk2 + case "INpsk1": pattern = .INpsk1 + case "INpsk2": pattern = .INpsk2 + case "IKpsk1": pattern = .IKpsk1 + case "IKpsk2": pattern = .IKpsk2 + case "IXpsk2": pattern = .IXpsk2 + case: pattern = .Invalid + } + + if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + dh: ecdh.Curve + switch s { + case "25519": dh = .X25519 + case "448": dh = .X448 + case: dh = .Invalid + } + + if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + cipher: aead.Algorithm + switch s { + case "AESGCM": cipher = .AES_GCM_256 + case "ChaChaPoly": cipher = .CHACHA20POLY1305 + case: cipher = .Invalid + } + + if s, ok = strings.split_by_byte_iterator(&str, '_'); !ok { + return .Invalid, .Invalid, .Invalid, .Invalid, .Invalid_Protocol_String + } + hash: hash.Algorithm + switch s { + case "SHA512": hash = .SHA512 + case "SHA256": hash = .SHA256 + case "BLAKE2s": hash = .BLAKE2S + case "BLAKE2b": hash = .BLAKE2B + case: hash = .Invalid + } + + status: Status + + if len(str) != 0 { + status = .Invalid_Protocol_String + } + if pattern == .Invalid || dh == .Invalid || cipher == .Invalid || hash == .Invalid { + status = .Invalid_Protocol_String + } + + return pattern, dh, cipher, hash, status +} diff --git a/core/crypto/noise/doc.odin b/core/crypto/noise/doc.odin new file mode 100644 index 000000000..734a1dc6e --- /dev/null +++ b/core/crypto/noise/doc.odin @@ -0,0 +1,35 @@ +/* +An implementation of the Noise Protocol Framework (Revision 34). + +The `fallback` modifier and multi-PSK patterns are not supported +for the sake of simplicity. + +See: +- [[ https://noiseprotocol.org/ ]] +*/ +package noise + +// In general, to complete a noise handshake you must: +// +// - If you are initiating the connection, call `handshake_initiator_step` +// passing `nil` as the `input_message` parameter. +// +// - Send the resulting `[]byte` to the responder (generally a server) via +// the method of your choice. This MUST be done even if the status code +// returned is `.Handshake_Complete`. +// +// - If the status code returned by `handshake_initiator_step` was +// `.Handshake_Complete`, the handshake completed successfully, +// and it is now possible to validate the peer identity, obtain the +// handshake transcript hash, and most usefully call `handshake_split` +// to populate the `Cipher_States` struct that will be used to +// encrypt/decrypt data. +// +// Otherwise, read the response from the responder and feed the response +// data as the `input_message` to the next `handshake_initiator_step` +// until it returns `.Handshake_Complete`. +// +// - If you are the responder, the method is much the same, except you +// must pass a valid `input_message` received from an initiator to the +// first call to `handshake_responder_step`. Repeat until the returned +// status is `.Handshake_Complete`. diff --git a/core/crypto/noise/patterns.odin b/core/crypto/noise/patterns.odin new file mode 100644 index 000000000..14e5b6498 --- /dev/null +++ b/core/crypto/noise/patterns.odin @@ -0,0 +1,1098 @@ +package noise + +import "core:slice" + +@(private) +Pre_Token :: enum { + res_s, + ini_s, +} + +@(private) +Token :: enum { + e, + s, + ee, + es, + se, + ss, + psk, +} + +@(private) +Message_Pattern :: struct { + pre_messages: []Pre_Token, + messages: [][]Token, + is_psk: bool, + is_one_way: bool, +} + +// Handshake_Pattern is the list of currently supported Noise Handshake +// Patterns. +Handshake_Pattern :: enum { + Invalid, + + // One way patterns + N, + K, + X, + + // Fundamental patterns + XX, + NK, + NN, + KN, + KK, + NX, + KX, + XN, + IN, + XK, + IK, + IX, + + // Deferred patterns + NK1, + NX1, + X1N, + X1K, + XK1, + X1K1, + X1X, + XX1, + X1X1, + K1N, + K1K, + KK1, + K1K1, + K1X, + KX1, + K1X1, + I1N, + I1K, + IK1, + I1K1, + I1X, + IX1, + I1X1, + + // Recommended PSK patterns + Npsk0, + Kpsk0, + Xpsk1, + NNpsk0, + NNpsk2, + NKpsk0, + NKpsk2, + NXpsk2, + XNpsk3, + XKpsk3, + XXpsk3, + KNpsk0, + KNpsk2, + KKpsk0, + KKpsk2, + KXpsk2, + INpsk1, + INpsk2, + IKpsk1, + IKpsk2, + IXpsk2, +} + +@(require_results) +pattern_requires_initiator_s :: proc(pattern: Handshake_Pattern) -> (pre: bool, hs: bool) { + p := HANDSHAKE_PATTERNS[pattern] + if slice.contains(p.pre_messages, Pre_Token.ini_s) { + pre = true + } + for msg, i in p.messages { + if i & 1 != 0 { + continue + } + if slice.contains(msg, Token.s) { + hs = true + break + } + } + return pre, hs +} + +@(require_results) +pattern_requires_responder_s :: proc(pattern: Handshake_Pattern) -> (pre: bool, hs: bool) { + p := HANDSHAKE_PATTERNS[pattern] + if slice.contains(p.pre_messages, Pre_Token.res_s) { + pre = true + } + for msg, i in p.messages { + if i & 1 == 0 { + continue + } + if slice.contains(msg, Token.s) { + hs = true + break + } + } + return pre, hs +} + +@(require_results) +pattern_is_psk :: proc(pattern: Handshake_Pattern) -> bool { + return HANDSHAKE_PATTERNS[pattern].is_psk +} + +@(require_results) +pattern_is_one_way :: proc(pattern: Handshake_Pattern) -> bool { + return HANDSHAKE_PATTERNS[pattern].is_one_way +} + +@(require_results) +pattern_num_messages :: proc(pattern: Handshake_Pattern) -> int { + return len(HANDSHAKE_PATTERNS[pattern].messages) +} + +@(private) +HANDSHAKE_PATTERNS := [Handshake_Pattern]^Message_Pattern { + .Invalid = nil, + .N = &PATTERN_N, + .K = &PATTERN_K, + .X = &PATTERN_X, + + .XX = &PATTERN_XX, + .NK = &PATTERN_NK, + .NN = &PATTERN_NN, + .KN = &PATTERN_KN, + .KK = &PATTERN_KK, + .NX = &PATTERN_NX, + .KX = &PATTERN_KX, + .XN = &PATTERN_XN, + .IN = &PATTERN_IN, + .XK = &PATTERN_XK, + .IK = &PATTERN_IK, + .IX = &PATTERN_IX, + + .NK1 = &PATTERN_NK1, + .NX1 = &PATTERN_NX1, + .X1N = &PATTERN_X1N, + .X1K = &PATTERN_X1K, + .XK1 = &PATTERN_XK1, + .X1K1 = &PATTERN_X1K1, + .X1X = &PATTERN_X1X, + .XX1 = &PATTERN_XX1, + .X1X1 = &PATTERN_X1X1, + .K1N = &PATTERN_K1N, + .K1K = & PATTERN_K1K, + .KK1 = &PATTERN_KK1, + .K1K1 = &PATTERN_K1K1, + .K1X = &PATTERN_K1X, + .KX1 = &PATTERN_KX1, + .K1X1 = &PATTERN_K1X1, + .I1N = &PATTERN_I1N, + .I1K = &PATTERN_I1K, + .IK1 = &PATTERN_IK1, + .I1K1 = &PATTERN_I1K1, + .I1X = &PATTERN_I1X, + .IX1 = &PATTERN_IX1, + .I1X1 = &PATTERN_I1X1, + + .Npsk0 = &PATTERN_Npsk0, + .Kpsk0 = &PATTERN_Kpsk0, + .Xpsk1 = &PATTERN_Xpsk1, + .NNpsk0 = &PATTERN_NNpsk0, + .NNpsk2 = &PATTERN_NNpsk2, + .NKpsk0 = &PATTERN_NKpsk0, + .NKpsk2 = &PATTERN_NKpsk2, + .NXpsk2 = &PATTERN_NXpsk2, + .XNpsk3 = &PATTERN_XNpsk3, + .XKpsk3 = &PATTERN_XKpsk3, + .XXpsk3 = &PATTERN_XXpsk3, + .KNpsk0 = &PATTERN_KNpsk0, + .KNpsk2 = &PATTERN_KNpsk2, + .KKpsk0 = &PATTERN_KKpsk0, + .KKpsk2 = &PATTERN_KKpsk2, + .KXpsk2 = &PATTERN_KXpsk2, + .INpsk1 = &PATTERN_INpsk1, + .INpsk2 = &PATTERN_INpsk2, + .IKpsk1 = &PATTERN_IKpsk1, + .IKpsk2 = &PATTERN_IKpsk2, + .IXpsk2 = &PATTERN_IXpsk2, +} + +// ------------- ONE WAY PATTERNS --------------------------------------------------------- + +// N: +// <- s +// ... +// -> e, es +@(private,rodata) +PATTERN_N : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + }, + is_one_way = true, +} + +// K: +// -> s +// <- s +// ... +// -> e, es, ss +@(private,rodata) +PATTERN_K : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e, .es, .ss}, + }, + is_one_way = true, +} + +// X: +// <- s +// ... +// -> e, es, s, ss +@(private,rodata) +PATTERN_X : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s, .ss}, + }, + is_one_way = true, +} + +// ---------------------------------------------------------------------------------------- + +// ------------- FUNDAMENTAL PATTERNS ----------------------------------------------------- + +// XX: +// -> e +// <- e, ee, s, es +// -> s, se +@(private,rodata) +PATTERN_XX : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s, .es}, + {.s, .se}, + }, +} + +// NK: +// <- s +// ... +// -> e, es +// <- e, ee +@(private,rodata) +PATTERN_NK : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + {.e, .ee}, + }, +} + +// NN: +// -> e +// <- e, ee +@(private,rodata) +PATTERN_NN : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee}, + }, +} + +// KN: +// -> s +// ... +// -> e +// <- e, ee, se +@(private,rodata) +PATTERN_KN : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e,}, + {.e, .ee, .se}, + }, +} + +// KK: +// -> s +// <- s +// ... +// -> e, es, ss +// <- e, ee, se +@(private,rodata) +PATTERN_KK : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e, .es, .ss}, + {.e, .ee, .se}, + }, +} + +// NX: +// -> e +// <- e, ee, s, es +@(private,rodata) +PATTERN_NX : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s, .es}, + }, +} + +// KX: +// -> s +// ... +// -> e +// <- e, ee, se, s, es +@(private,rodata) +PATTERN_KX : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .se, .s, .es}, + }, +} + +// XN: +// -> e +// <- e, ee +// -> s, se +@(private,rodata) +PATTERN_XN : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee}, + {.s, .se}, + }, +} + +// IN: +// -> e, s +// <- e, ee, se +@(private,rodata) +PATTERN_IN : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .se}, + }, +} + +// XK: +// <- s +// ... +// -> e, es +// <- e, ee +// -> s, se +@(private,rodata) +PATTERN_XK : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + {.e, .ee}, + {.s, .se}, + }, +} + +// IK: +// <- s +// ... +// -> e, es, s, ss +// <- e, ee, se +@(private,rodata) +PATTERN_IK : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s, .ss}, + {.e, .ee, .se}, + }, +} + +// IX: +// -> e, s +// <- e, ee, se, s, es +@(private,rodata) +PATTERN_IX : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .se, .s, .es}, + }, +} + +// ---------------------------------------------------------------------------------------- + +// ------------- DEFERRED PATTERNS -------------------------------------------------------- + +// NK1: +// <- s +// ... +// -> e +// <- e, ee, es +@(private,rodata) +PATTERN_NK1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e}, + {.e, .ee, .es}, + }, +} + +// NX1: +// -> e +// <- e, ee, s +// -> es +@(private,rodata) +PATTERN_NX1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s}, + {.es}, + }, +} + +// X1N: +// -> e +// <- e, ee +// -> s +// <- se +@(private,rodata) +PATTERN_X1N : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee}, + {.s}, + {.se}, + }, +} + +// X1K: +// <- s +// ... +// -> e, es +// <- e, ee +// -> s +// <- se +@(private,rodata) +PATTERN_X1K : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + {.e, .ee}, + {.s}, + {.se}, + }, +} + +// XK1: +// <- s +// ... +// -> e +// <- e, ee, es +// -> s, se +@(private,rodata) +PATTERN_XK1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e}, + {.e, .ee, .es}, + {.s, .se}, + }, +} + +// X1K1: +// <- s +// ... +// -> e +// <- e, ee, es +// -> s +// <- se +@(private,rodata) +PATTERN_X1K1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e}, + {.e, .ee, .es}, + {.s}, + {.se}, + }, +} + +// X1X: +// -> e +// <- e, ee, s, es +// -> s +// <- se +@(private,rodata) +PATTERN_X1X : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s, .es}, + {.s}, + {.se}, + }, +} + +// XX1: +// -> e +// <- e, ee, s +// -> es, s, se +@(private,rodata) +PATTERN_XX1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s}, + {.es, .s, .se}, + }, +} + +// X1X1: +// -> e +// <- e, ee, s +// -> es, s +// <- se +@(private,rodata) +PATTERN_X1X1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s}, + {.es, .s}, + {.se}, + }, +} + +// K1N: +// -> s +// ... +// -> e +// <- e, ee +// -> se +@(private,rodata) +PATTERN_K1N : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e,}, + {.e, .ee}, + {.se}, + }, +} + +// K1K: +// -> s +// <- s +// ... +// -> e, es +// <- e, ee +// -> se +@(private,rodata) +PATTERN_K1K : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e, .es}, + {.e, .ee}, + {.se}, + }, +} + +// KK1: +// -> s +// <- s +// ... +// -> e +// <- e, ee, se, es +@(private,rodata) +PATTERN_KK1 : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e}, + {.e, .ee, .se, .es}, + }, +} + +// K1K1: +// -> s +// <- s +// ... +// -> e +// <- e, ee, es +// -> se +@(private,rodata) +PATTERN_K1K1 : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e}, + {.e, .ee, .es}, + {.se}, + }, +} + +// K1X: +// -> s +// ... +// -> e +// <- e, ee, s, es +// -> se +@(private,rodata) +PATTERN_K1X : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .s, .es}, + {.se}, + }, +} + +// KX1: +// -> s +// ... +// -> e +// <- e, ee, se, s +// -> es +@(private,rodata) +PATTERN_KX1 : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .se, .s}, + {.es}, + }, +} + +// K1X1: +// -> s +// ... +// -> e +// <- e, ee, s +// -> se, es +@(private,rodata) +PATTERN_K1X1 : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .s}, + {.se, .es}, + }, +} + +// I1N: +// -> e, s +// <- e, ee +// -> se +@(private,rodata) +PATTERN_I1N : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee}, + {.se}, + }, +} + +// I1K: +// <- s +// ... +// -> e, es, s +// <- e, ee +// -> se +@(private,rodata) +PATTERN_I1K : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s}, + {.e, .ee}, + {.se}, + }, +} + +// IK1: +// <- s +// ... +// -> e, s +// <- e, ee, se, es +@(private,rodata) +PATTERN_IK1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .s}, + {.e, .ee, .se, .es}, + }, +} + +// I1K1: +// <- s +// ... +// -> e, s +// <- e, ee, es +// -> se +@(private,rodata) +PATTERN_I1K1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .s}, + {.e, .ee, .es}, + {.se}, + }, +} + +// I1X: +// -> e, s +// <- e, ee, s, es +// -> se +@(private,rodata) +PATTERN_I1X : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .s, .es}, + {.se}, + }, +} + +// IX1: +// -> e, s +// <- e, ee, se, s +// -> es +@(private,rodata) +PATTERN_IX1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .se, .s}, + {.es}, + }, +} + +// I1X1: +// -> e, s +// <- e, ee, s +// -> se, es +@(private,rodata) +PATTERN_I1X1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .s}, + {.se, .es}, + }, +} + +// ---------------------------------------------------------------------------------------- + +// ------------- PSK PATTERNS ------------------------------------------------------------- + +// Npsk0: +// <- s +// ... +// -> psk, e, es +@(private,rodata) +PATTERN_Npsk0 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.psk, .e, .es}, + }, + is_psk = true, + is_one_way = true, +} + +// K: +// -> s +// <- s +// ... +// -> psk, e, es, ss +@(private,rodata) +PATTERN_Kpsk0 : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.psk, .e, .es, .ss}, + }, + is_psk = true, + is_one_way = true, +} + +// X: +// <- s +// ... +// -> e, es, s, ss, psk +@(private,rodata) +PATTERN_Xpsk1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s, .ss, .psk}, + }, + is_psk = true, + is_one_way = true, +} + +// NNpsk0: +// -> psk, e +// <- e, ee +@(private,rodata) +PATTERN_NNpsk0 : Message_Pattern = { + pre_messages = nil, + messages = { + {.psk, .e}, + {.e, .ee}, + }, + is_psk = true, +} + +// NNpsk2: +// -> e +// <- e, ee, psk +@(private,rodata) +PATTERN_NNpsk2 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .psk}, + }, + is_psk = true, +} + +// NKpsk0: +// <- s +// ... +// -> psk, e, es +// <- e, ee +@(private,rodata) +PATTERN_NKpsk0 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.psk, .e, .es}, + {.e, .ee}, + }, + is_psk = true, +} + +// NKpsk2: +// <- s +// ... +// -> e, es +// <- e, ee, psk +@(private,rodata) +PATTERN_NKpsk2 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + {.e, .ee, .psk}, + }, + is_psk = true, +} + +// NXpsk2: +// -> e +// <- e, ee, s, es, psk +@(private,rodata) +PATTERN_NXpsk2 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s, .es, .psk}, + }, + is_psk = true, +} + +// XNpsk3: +// -> e +// <- e, ee +// -> s, se, psk +@(private,rodata) +PATTERN_XNpsk3 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee}, + {.s, .se, .psk}, + }, + is_psk = true, +} + +// XKpsk3: +// <- s +// ... +// -> e, es +// <- e, ee +// -> s, se, psk +@(private,rodata) +PATTERN_XKpsk3 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es}, + {.e, .ee}, + {.s, .se, .psk}, + }, + is_psk = true, +} + +// XXpsk3: +// -> e +// <- e, ee, s, es +// -> s, se, psk +@(private,rodata) +PATTERN_XXpsk3 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e}, + {.e, .ee, .s, .es}, + {.s, .se, .psk}, + }, + is_psk = true, +} + +// KNpsk0: +// -> s +// ... +// -> psk, e +// <- e, ee, se +@(private,rodata) +PATTERN_KNpsk0 : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.psk, .e}, + {.e, .ee, .se}, + }, + is_psk = true, +} + +// KNpsk2: +// -> s +// ... +// -> e +// <- e, ee, se, psk +@(private,rodata) +PATTERN_KNpsk2 : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .se, .psk}, + }, + is_psk = true, +} + +// KKpsk0: +// -> s +// <- s +// ... +// -> psk, e, es, ss +// <- e, ee, se +@(private,rodata) +PATTERN_KKpsk0 : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.psk, .e, .es, .ss}, + {.e, .ee, .se}, + }, + is_psk = true, +} + +// KKpsk2: +// -> s +// <- s +// ... +// -> e, es, ss +// <- e, ee, se, psk +@(private,rodata) +PATTERN_KKpsk2 : Message_Pattern = { + pre_messages = {.ini_s, .res_s}, + messages = { + {.e, .es, .ss}, + {.e, .ee, .se, .psk}, + }, + is_psk = true, +} + +// KXpsk2: +// -> s +// ... +// -> e +// <- e, ee, se, s, es, psk +@(private,rodata) +PATTERN_KXpsk2 : Message_Pattern = { + pre_messages = {.ini_s}, + messages = { + {.e}, + {.e, .ee, .se, .s, .es, .psk}, + }, + is_psk = true, +} + +// INpsk1: +// -> e, s, psk +// <- e, ee, se +@(private,rodata) +PATTERN_INpsk1 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s, .psk}, + {.e, .ee, .se}, + }, + is_psk = true, +} + +// INpsk2: +// -> e, s +// <- e, ee, se, psk +@(private,rodata) +PATTERN_INpsk2 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .se, .psk}, + }, + is_psk = true, +} + +// IKpsk1: +// <- s +// ... +// -> e, es, s, ss, psk +// <- e, ee, se +@(private,rodata) +PATTERN_IKpsk1 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s, .ss, .psk}, + {.e, .ee, .se}, + }, + is_psk = true, +} + +// IKpsk2: +// <- s +// ... +// -> e, es, s, ss +// <- e, ee, se, psk +@(private,rodata) +PATTERN_IKpsk2 : Message_Pattern = { + pre_messages = {.res_s}, + messages = { + {.e, .es, .s, .ss}, + {.e, .ee, .se, .psk}, + }, + is_psk = true, +} + +// IXpsk2: +// -> e, s +// <- e, ee, se, s, es, psk +@(private,rodata) +PATTERN_IXpsk2 : Message_Pattern = { + pre_messages = nil, + messages = { + {.e, .s}, + {.e, .ee, .se, .s, .es, .psk}, + }, + is_psk = true, +} diff --git a/core/crypto/noise/protocol.odin b/core/crypto/noise/protocol.odin new file mode 100644 index 000000000..7327e638b --- /dev/null +++ b/core/crypto/noise/protocol.odin @@ -0,0 +1,989 @@ +#+private +package noise + +import "base:runtime" +import "core:crypto" +import "core:crypto/aead" +import "core:crypto/ecdh" +import "core:crypto/hash" +import "core:crypto/hkdf" +import "core:encoding/endian" +import "core:slice" + +AEAD_KEY_SIZE :: 32 + +MIN_DH_SIZE :: 32 +MAX_DH_SIZE :: 56 +MAX_HASH_SIZE :: 64 + +Protocol :: struct { + handshake_pattern: Handshake_Pattern, + dh: ecdh.Curve, + cipher: aead.Algorithm, + hash: hash.Algorithm, +} + +Symmetric_State :: struct { + protocol: Protocol, + cipher_state: Cipher_State, + + _ck: [MAX_HASH_SIZE]byte, + _h: [MAX_HASH_SIZE]byte, +} + +Cipher_State :: struct { + ctx: aead.Context, + n: u64, + n_exhausted: bool, + is_invalid: bool, +} + +@(require_results) +dh_len :: proc(protocol: ^Protocol) -> int { + return ecdh.PUBLIC_KEY_SIZES[protocol.dh] +} + +@(require_results) +hash_len :: proc(protocol: ^Protocol) -> int { + return hash.DIGEST_SIZES[protocol.hash] +} + +// Generates a new Diffie-Hellman key pair. A DH key pair consists of +// public_key and private_key elements. public_key represents an encoding +// of a DH public key into a byte sequence of length DHLEN. The public_key +// encoding details are specific to each set of DH functions. +generate_keypair :: proc(protocol: ^Protocol, private_key: ^ecdh.Private_Key) { + #partial switch protocol.dh { + case .X25519, .X448: + case: panic("crypto/noise: unsupported DH curve in protocol") + } + + if !ecdh.private_key_generate(private_key, protocol.dh) { + panic("crypto/noise: entropy source unavailable") + } +} + +// Performs a Diffie-Hellman calculation between the private key in key_pair +// and the public_key and returns an output sequence of bytes of length DHLEN. +// For security, the Gap-DH problem based on this function must be unsolvable +// by any practical cryptanalytic adversary [2]. +// +// The public_key either encodes some value which is a generator in a +// large prime-order group (which value may have multiple equivalent +// encodings), or is an invalid value. Implementations must handle invalid +// public keys either by returning some output which is purely a function +// of the public key and does not depend on the private key, or by signaling +// an error to the caller. +// +// The DH function may define more specific rules for handling invalid values. +@(require_results) +_dh :: proc(our_private_key: ^ecdh.Private_Key, their_public_key: ^ecdh.Public_Key, dst: []byte) -> Status { + if ok := ecdh.ecdh(our_private_key, their_public_key, dst); !ok { + return .DH_Failure + } + return .Ok +} + +// Encrypts plaintext using the cipher key k of 32 bytes and an 8-byte +// unsigned integer nonce n which must be unique for the key k. +// Returns the ciphertext. Encryption must be done with an "AEAD" +// encryption mode with the associated data(AD) (using the terminology +// from [1]) and returns a ciphertext that is the same size as the plaintext +// plus 16 bytes for authentication data. The entire ciphertext must be +// indistinguishable from random if the key is secret (note that this is +// an additional requirement that isn't necessarily met by all AEAD schemes). +_encrypt :: proc(ctx: ^aead.Context, n: u64, ad, plaintext, dst: []byte) { + pt_len := len(plaintext) + ensure(len(dst) == pt_len + TAG_SIZE, "crypto/noise: invalid AEAD encrypt destination") + + iv: [12]byte + #partial switch aead.algorithm(ctx) { + case .AES_GCM_256: endian.unchecked_put_u64be(iv[4:], n) + case .CHACHA20POLY1305: endian.unchecked_put_u64le(iv[4:], n) + } + + ciphertext, tag := dst[:pt_len], dst[pt_len:] + aead.seal_ctx(ctx, ciphertext, tag, iv[:], ad, plaintext) +} + +// Decrypts ciphertext using a cipher key k of 32 bytes, an 8-byte unsigned +// integer nonce n, and associated data ad. Returns the plaintext, unless +// authentication fails, in which case an error is signaled to the caller. +@(require_results) +_decrypt :: proc(ctx: ^aead.Context, n: u64, ad, ciphertext, dst: []byte) -> Status { + if len(ciphertext) < TAG_SIZE { + return .Decryption_Failure + } + + iv: [12]byte + #partial switch aead.algorithm(ctx) { + case .AES_GCM_256: endian.unchecked_put_u64be(iv[4:], n) + case .CHACHA20POLY1305: endian.unchecked_put_u64le(iv[4:], n) + } + + ct_len := len(ciphertext) - TAG_SIZE + ct, tag := ciphertext[:ct_len], ciphertext[ct_len:] + if ok := aead.open_ctx(ctx, dst, iv[:], ad, ct, tag); !ok { + return .Decryption_Failure + } + + return .Ok +} + +// Hashes some arbitrary-length data with a collision-resistant cryptographic +// hash function and returns an output of HASHLEN bytes. +_hash :: proc(dst: []byte, protocol: ^Protocol, data: ..[]byte) { + ctx: hash.Context + hash.init(&ctx, protocol.hash) + + for datum in data { + hash.update(&ctx, datum) + } + + hash.final(&ctx, dst) +} + +// Takes a chaining_key byte sequence of length HASHLEN, and an +// input_key_material byte sequence with length either zero bytes, +// 32 bytes, or DHLEN bytes. Returns a pair or triple of byte sequences +// each of length HASHLEN, depending on whether num_outputs is two or three: +// - Sets temp_key = HMAC-HASH(chaining_key, input_key_material). +// - Sets output1 = HMAC-HASH(temp_key, byte(0x01)). +// - Sets output2 = HMAC-HASH(temp_key, output1 || byte(0x02)). +// - If num_outputs == 2 then returns the pair (output1, output2). +// - Sets output3 = HMAC-HASH(temp_key, output2 || byte(0x03)). +// - Returns the triple (output1, output2, output3). +// +// Note that temp_key, output1, output2, and output3 are all HASHLEN +// bytes in length. Also note that the HKDF() function is simply HKDF +// from [4] with the chaining_key as HKDF salt, and zero-length HKDF info. +@(require_results) +_hkdf :: proc(dst, chaining_key, input_key_material: []byte, protocol: ^Protocol) -> ([]byte, []byte, []byte) { + assert(len(input_key_material) == 0 || len(input_key_material) == 32 || len(input_key_material) == dh_len(protocol)) + + hkdf.extract_and_expand(protocol.hash, chaining_key, input_key_material, nil, dst) + + h_len := hash_len(protocol) + assert(len(dst) == h_len * 2 || len(dst) == h_len * 3) + + r1, r2 := dst[:h_len], dst[h_len:h_len*2] + if len(dst) == h_len * 2 { + return r1, r2, nil + } + return r1, r2, dst[h_len*2:] +} + +// Sets k = key. Sets n = 0. +cipherstate_initialize_key :: proc(self: ^Cipher_State, key: []byte, protocol: ^Protocol) { + k_len := len(key) + switch { + case k_len == 0: + // k = empty + aead.reset(&self.ctx) + self.n = 0 + case k_len < AEAD_KEY_SIZE: + panic("crypto/noise: invalid AEAD key size") + case: + aead.init(&self.ctx, protocol.cipher, key[:AEAD_KEY_SIZE]) + self.n = 0 + } +} + +// Returns true if k is non-empty, false otherwise. +@(require_results) +cipherstate_has_key :: proc(self: ^Cipher_State) -> bool { + return aead.algorithm(&self.ctx) != .Invalid +} + +// If k is non-empty returns ENCRYPT(k, n++, ad, plaintext). Otherwise +// returns plaintext. +@(require_results) +cipherstate_encrypt_with_ad :: proc(self: ^Cipher_State, ad, plaintext, dst: []byte) -> ([]byte, Status) { + if self.is_invalid { + return nil, .Invalid_Cipher_State + } + if self.n_exhausted { + return nil, .IV_Exhausted + } + + pt_len := len(plaintext) + if pt_len > MAX_PACKET_SIZE - 16 { + return nil, .Max_Packet_Size + } + + if cipherstate_has_key(self) { + if len(dst) != pt_len + TAG_SIZE { + return nil, .Invalid_Destination_Buffer + } + _encrypt(&self.ctx, self.n, ad, plaintext, dst) + self.n += 1 + if self.n == 0 { + self.n_exhausted = true + } + } else { + if len(dst) != pt_len { + return nil, .Invalid_Destination_Buffer + } + if raw_data(dst) != raw_data(plaintext) { + copy(dst, plaintext) + } + } + + return dst, .Ok +} + +// If k is non-empty returns DECRYPT(k, n++, ad, ciphertext). Otherwise +// returns ciphertext. If an authentication failure occurs in DECRYPT() +// then n is not incremented and an error is signaled to the caller. +@(require_results) +cipherstate_decrypt_with_ad :: proc(self: ^Cipher_State, ad, ciphertext, dst: []byte) -> ([]byte, Status) { + if self.is_invalid { + return nil, .Invalid_Cipher_State + } + if self.n_exhausted { + return nil, .IV_Exhausted + } + + if cipherstate_has_key(self) { + if status := _decrypt(&self.ctx, self.n, ad, ciphertext, dst); status != .Ok { + return nil, status + } + self.n += 1 + if self.n == 0 { + self.n_exhausted = true + } + } else { + if len(dst) != len(ciphertext) { + return nil, .Invalid_Destination_Buffer + } + if raw_data(dst) != raw_data(ciphertext) { + copy(dst, ciphertext) + } + } + + return dst, .Ok +} + +// Sets k = REKEY(k). +cipherstate_rekey :: proc(self: ^Cipher_State) { + if cipherstate_has_key(self) { + algorithm := aead.algorithm(&self.ctx) + + // The "sensible" way to implement this is to inlike REKEY(k), + // so we do. + // + // Returns a new 32-byte cipher key as a pseudorandom function + // of k. If this function is not specifically defined for some + // set of cipher functions, then it defaults to returning the + // first 32 bytes from `ENCRYPT(k, maxnonce, zerolen, zeros)`, + // where maxnonce equals (2^64)-1, zerolen is a zero-length + // byte sequence, and zeros is a sequence of 32 bytes filled + // with zeros. + + zeroes: [AEAD_KEY_SIZE + TAG_SIZE]byte + defer crypto.zero_explicit(&zeroes, size_of(zeroes)) + + // 1 2 3 4 5 6 7 8 + n: u64 = 0xFF_FF_FF_FF_FF_FF_FF_FF + _encrypt(&self.ctx, n, nil, zeroes[:AEAD_KEY_SIZE], zeroes[:]) + aead.init(&self.ctx, algorithm, zeroes[:AEAD_KEY_SIZE]) + } +} + +cipherstate_reset :: proc(self: ^Cipher_State) { + aead.reset(&self.ctx) + crypto.zero_explicit(self, size_of(Cipher_State)) +} + +// Takes an arbitrary-length protocol_name byte sequence (see Section 8). +// Executes the following steps: +// - If protocol_name is less than or equal to HASHLEN bytes in length, +// sets h equal to protocol_name with zero bytes appended to make +// HASHLEN bytes. +// - Otherwise sets h = HASH(protocol_name). +// - Sets ck = h. +// - Calls InitializeKey(empty). +@(require_results) +symmetricstate_initialize :: proc(ss: ^Symmetric_State, protocol_name: string) -> Status { + if status := protocol_from_string(&ss.protocol, protocol_name); status != .Ok { + return status + } + + cipherstate_initialize_key(&ss.cipher_state, nil, &ss.protocol) + + h_len := hash_len(&ss.protocol) + h := ss._h[:h_len] + if len(protocol_name) <= h_len { + copy(h, protocol_name) + } else { + _hash(h, &ss.protocol, transmute([]byte)protocol_name) + } + + copy(ss._ck[:h_len], h) + + return .Ok +} + +// Sets h = HASH(h || data). +symmetricstate_mix_hash :: proc(self: ^Symmetric_State, data: ..[]byte) { + h := self._h[:hash_len(&self.protocol)] + if len(data) == 1 { + _hash(h, &self.protocol, h, data[0]) + } else if len(data) == 2 { + _hash(h, &self.protocol, h, data[0], data[1]) + } else if len(data) == 3 { + _hash(h, &self.protocol, h, data[0], data[1], data[2]) + } else { + panic("crypto/noise: invalid MixHash inputs") + } +} + +// Executes the following steps: +// - Sets ck, temp_k = HKDF(ck, input_key_material, 2). +// - If HASHLEN is 64, then truncates temp_k to 32 bytes. +// - Calls InitializeKey(temp_k). +symmetricstate_mix_key :: proc(self: ^Symmetric_State, input_key_material: []byte) { + h_len := hash_len(&self.protocol) + + dst_len := h_len * 2 + dst: [2*MAX_HASH_SIZE]byte = --- + defer crypto.zero_explicit(&dst, dst_len) + + ck, temp_k, _ := _hkdf(dst[:dst_len], self._ck[:h_len], input_key_material, &self.protocol) + copy(self._ck[:], ck) + cipherstate_initialize_key(&self.cipher_state, temp_k, &self.protocol) +} + +// This function is used for handling pre-shared symmetric keys, as described +// in Section 9. It executes the following steps: +// - Sets ck, temp_h, temp_k = HKDF(ck, input_key_material, 3). +// - Calls MixHash(temp_h). +// - If HASHLEN is 64, then truncates temp_k to 32 bytes. +// - Calls InitializeKey(temp_k). +symmetricstate_mix_key_and_hash :: proc(self: ^Symmetric_State, input_key_material: []byte) { + h_len := hash_len(&self.protocol) + + dst_len := h_len * 3 + dst: [3*MAX_HASH_SIZE]byte = --- + defer crypto.zero_explicit(&dst, dst_len) + + ck, temp_h, temp_k := _hkdf(dst[:dst_len], self._ck[:h_len], input_key_material, &self.protocol) + copy(self._ck[:], ck) + symmetricstate_mix_hash(self, temp_h) + cipherstate_initialize_key(&self.cipher_state, temp_k, &self.protocol) +} + +// Returns h. This function should only be called at the end of a handshake, +// i.e. after the Split() function has been called. +// +// This function is used for channel binding, as described in Section 11.2 +@(require_results) +symmetricstate_get_handshake_hash :: proc(self: ^Symmetric_State) -> []byte { + return self._h[:hash_len(&self.protocol)] +} + +// Sets ciphertext = EncryptWithAd(h, plaintext), calls MixHash(ciphertext), +// and returns ciphertext. +// +// Note that if k is empty, the EncryptWithAd() call will set ciphertext +// equal to plaintext. +@(require_results) +symmetricstate_encrypt_and_hash :: proc(self: ^Symmetric_State, plaintext, dst: []byte) -> ([]byte, Status) { + ciphertext, status := cipherstate_encrypt_with_ad(&self.cipher_state, self._h[:hash_len(&self.protocol)], plaintext, dst) + if status != .Ok { + return nil, status + } + symmetricstate_mix_hash(self, ciphertext) + return ciphertext, status +} + +// Sets plaintext = DecryptWithAd(h, ciphertext), calls MixHash(ciphertext), +// and returns plaintext. +// +// Note that if k is empty, the DecryptWithAd() call will set plaintext +// equal to ciphertext. +@(require_results) +symmetricstate_decrypt_and_hash :: proc(self: ^Symmetric_State, ciphertext, dst: []byte) -> ([]byte, Status) { + h_len := hash_len(&self.protocol) + + h: [MAX_HASH_SIZE]byte = --- + copy(h[:], self._h[:h_len]) + defer crypto.zero_explicit(&h, size_of(h)) + + // We reverse the order to save having to copy the ciphertext, in + // the case that ciphertext and dst alias. + symmetricstate_mix_hash(self, ciphertext) + return cipherstate_decrypt_with_ad(&self.cipher_state, h[:h_len], ciphertext, dst) +} + +// Returns a pair of CipherState objects for encrypting transport messages. +// Executes the following steps, where zerolen is a zero-length byte sequence: +// - Sets temp_k1, temp_k2 = HKDF(ck, zerolen, 2). +// - If HASHLEN is 64, then truncates temp_k1 and temp_k2 to 32 bytes. +// - Creates two new CipherState objects c1 and c2. +// - Calls c1.InitializeKey(temp_k1) and c2.InitializeKey(temp_k2). +// - Returns the pair (c1, c2). +symmetricstate_split :: proc(self: ^Symmetric_State, cipher_states: ^Cipher_States) { + h_len := hash_len(&self.protocol) + + dst_len := h_len * 2 + dst: [2*MAX_HASH_SIZE]byte = --- + defer crypto.zero_explicit(&dst, dst_len) + + temp_k1, temp_k2, _ := _hkdf(dst[:dst_len], self._ck[:h_len], nil, &self.protocol) + cipherstate_initialize_key(&cipher_states.c1_i_to_r, temp_k1, &self.protocol) + cipherstate_initialize_key(&cipher_states.c2_r_to_i, temp_k2, &self.protocol) +} + +symmetricstate_reset :: proc(self: ^Symmetric_State) { + cipherstate_reset(&self.cipher_state) + + crypto.zero_explicit(self, size_of(Symmetric_State)) +} + +// Takes a valid handshake_pattern (see Section 7) and an initiator boolean +// specifying this party's role as either initiator or responder. +// Takes a prologue byte sequence which may be zero-length, or which may +// contain context information that both parties want to confirm is identical +// (see Section 6). +// +// Takes a set of DH key pairs (s, e) and public keys (rs, re) for +// initializing local variables, any of which may be empty. Public keys +// are only passed in if the handshake_pattern uses pre-messages +// (see Section 7). The ephemeral values (e, re) are typically left empty, +// since they are created and exchanged during the handshake; but there +// are exceptions (see Section 10). +// +// Performs the following steps: +// - Derives a protocol_name byte sequence by combining the names for +// the handshake pattern and crypto functions, as specified in Section 8. +// - Calls InitializeSymmetric(protocol_name). +// - Calls MixHash(prologue). +// - Sets the initiator, s, e, rs, and re variables to the corresponding +// arguments. +// - Calls MixHash() once for each public key listed in the pre-messages +// from handshake_pattern, with the specified public key as input +// (see Section 7 for an explanation of pre-messages). +// - If both initiator and responder have pre-messages, the initiator's +// public keys are hashed first. +// - If multiple public keys are listed in either party's pre-message, +// the public keys are hashed in the order that they are listed. +// - Sets message_pattern to the message patterns from handshake_pattern. +@(require_results) +handshakestate_initialize :: proc( + handshake_state: ^Handshake_State, + initiator: bool, + prologue: []byte, + s: ^ecdh.Private_Key, + e: ^ecdh.Private_Key, // Only set for testing. + rs: ^ecdh.Public_Key, + re: ^ecdh.Public_Key, // Only set for testing. + protocol_name: string, + psk: []byte = nil, +) -> Status { + crypto.zero_explicit(handshake_state, size_of(Handshake_State)) + + symmetric_state := &handshake_state.symmetric_state + status: Status + do_init: { + if status = symmetricstate_initialize(symmetric_state, protocol_name); status != .Ok { + break do_init + } + + curve := symmetric_state.protocol.dh + if s != nil && ecdh.curve(s) != curve { + status = .Invalid_DH_Key + break do_init + } + if e != nil && ecdh.curve(e) != curve { + status = .Invalid_DH_Key + break do_init + } + if rs != nil && ecdh.curve(rs) != curve { + status = .Invalid_DH_Key + break do_init + } + if re != nil && ecdh.curve(re) != curve { + status = .Invalid_DH_Key + break do_init + } + + // Check if we will require s later down the line. + s_pre, s_hs: bool + if initiator { + s_pre, s_hs = pattern_requires_initiator_s(symmetric_state.protocol.handshake_pattern) + } else { + s_pre, s_hs = pattern_requires_responder_s(symmetric_state.protocol.handshake_pattern) + } + if (s_pre || s_hs) && s == nil { + status = .No_Self_Identity + break do_init + } + + message_pattern := HANDSHAKE_PATTERNS[symmetric_state.protocol.handshake_pattern] + if message_pattern.pre_messages != nil { + if initiator { + if slice.contains(message_pattern.pre_messages, Pre_Token.res_s) { + if rs == nil { + status = .No_Peer_Identity + break do_init + } + } + } else { + if slice.contains(message_pattern.pre_messages, Pre_Token.ini_s) { + if rs == nil { + status = .No_Peer_Identity + break do_init + } + } + } + } else { + if rs != nil { + status = .Unexpected_Peer_Identity + break do_init + } + } + + symmetricstate_mix_hash(symmetric_state, prologue) + + // In all supported patterns, `ini_s` will always precede `res_s`. + if message_pattern.pre_messages != nil { + tmp: [MAX_DH_SIZE]byte = --- + d_len := dh_len(&symmetric_state.protocol) + dst := tmp[:d_len] + + if initiator { + if slice.contains(message_pattern.pre_messages, Pre_Token.ini_s) { + ecdh.private_key_public_bytes(s, dst) + symmetricstate_mix_hash(symmetric_state, dst) + } + if slice.contains(message_pattern.pre_messages, Pre_Token.res_s) { + ecdh.public_key_bytes(rs, dst) + symmetricstate_mix_hash(symmetric_state, dst) + } + } else { + if slice.contains(message_pattern.pre_messages, Pre_Token.ini_s) { + ecdh.public_key_bytes(rs, dst) + symmetricstate_mix_hash(symmetric_state, dst) + } + if slice.contains(message_pattern.pre_messages, Pre_Token.res_s) { + ecdh.private_key_public_bytes(s, dst) + symmetricstate_mix_hash(symmetric_state, dst) + } + } + } + if message_pattern.is_psk { + if len(psk) != PSK_SIZE { + status = .Invalid_Pre_Shared_Key + break do_init + } + } else if len(psk) != 0 { + status = .Unexpected_Pre_Shared_Key + break do_init + } + } + if status != .Ok { + symmetricstate_reset(symmetric_state) + return status + } + + if s != nil { + ecdh.private_key_set(&handshake_state.s, s) + } + if e != nil { + ecdh.private_key_set(&handshake_state.e, e) + handshake_state.pre_set_e = true + } + if rs != nil { + ecdh.public_key_set(&handshake_state.rs, rs) + } + if re != nil { + ecdh.public_key_set(&handshake_state.re, re) + } + copy(handshake_state.psk[:], psk) + handshake_state.message_pattern = HANDSHAKE_PATTERNS[symmetric_state.protocol.handshake_pattern] + handshake_state.current_message = 0 + handshake_state.status = .Handshake_Pending + handshake_state.initiator = initiator + + return .Ok +} + +handshakestate_reset :: proc(self: ^Handshake_State) { + symmetricstate_reset(&self.symmetric_state) + ecdh.private_key_clear(&self.s) + ecdh.private_key_clear(&self.e) + + crypto.zero_explicit(self, size_of(Handshake_State)) +} + +// Takes a payload byte sequence which may be zero-length, and a +// message_buffer to write the output into. +// Performs the following steps, aborting if any EncryptAndHash() call +// returns an error: +// - Fetches and deletes the next message pattern from message_pattern, +// then sequentially processes each token from the message pattern: +// - For "e": Sets e (which must be empty) to GENERATE_KEYPAIR(). +// Appends e.public_key to the buffer. Calls MixHash(e.public_key). +// - For "s": Appends EncryptAndHash(s.public_key) to the buffer. +// - For "ee": Calls MixKey(DH(e, re)). +// - For "es": Calls MixKey(DH(e, rs)) if initiator, MixKey(DH(s, re)) +// if responder. +// - For "se": Calls MixKey(DH(s, re)) if initiator, MixKey(DH(e, rs)) +// if responder. +// - For "ss": Calls MixKey(DH(s, rs)). +// - Appends EncryptAndHash(payload) to the buffer. +// – (SKIPPED) If there are no more message patterns returns two new +// CipherState objects by calling Split(). +// +// Calling Split() is left to a separate function, although it is technically +// part of the specification. +@(require_results) +handshakestate_write_message :: proc(self: ^Handshake_State, payload, dst: []byte, allocator := context.allocator) -> ([]byte, Status) { + ensure(self.status == .Handshake_Pending, "crypto/noise: invalid state for WriteMessage") + + protocol := &self.symmetric_state.protocol + d_len := dh_len(protocol) + + pattern_buf: [dynamic; MAX_STEP_MSG_SIZE]byte + dh_buf: [MAX_DH_SIZE]byte = --- + defer crypto.zero_explicit(&dh_buf, size_of(dh_buf)) + + pattern := self.message_pattern.messages[self.current_message] + for token in pattern { + switch token { + case .e: + switch self.pre_set_e { + case true: + // Note: "which must be empty", but we allow pre-generated `e` + // for testing/rng-less systems. + self.pre_set_e = false + case false: + if ecdh.curve(&self.e) != .Invalid { + panic("crypto/noise: e was not empty when processing token 'e' during WriteMessage") + } + generate_keypair(protocol, &self.e) + } + e_public := dh_buf[:d_len] + ecdh.private_key_public_bytes(&self.e, e_public) + n := append(&pattern_buf, ..e_public) + ensure(n == d_len, "crypto/noise: truncated append `e`") + + symmetricstate_mix_hash(&self.symmetric_state, e_public) + if self.message_pattern.is_psk { + symmetricstate_mix_key(&self.symmetric_state, e_public) + } + + case .s: + s_public := dh_buf[:d_len] + ecdh.private_key_public_bytes(&self.s, s_public) + + tmp: [MAX_DH_SIZE+TAG_SIZE]byte = --- + dh_buf := tmp[:d_len+TAG_SIZE] + if !cipherstate_has_key(&self.symmetric_state.cipher_state) { + dh_buf = tmp[:d_len] + } + ct, status := symmetricstate_encrypt_and_hash(&self.symmetric_state, s_public, dh_buf) + if status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + n := append(&pattern_buf, ..ct) + ensure(n == len(ct), "crypto/noise: truncated append `s`") + + case .ee: + dh := dh_buf[:d_len] + if status := _dh(&self.e, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + + case .es: + dh := dh_buf[:d_len] + if self.initiator { + if status := _dh(&self.e, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } else { + if status := _dh(&self.s, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } + + case .se: + dh := dh_buf[:d_len] + if self.initiator { + if status := _dh(&self.s, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } else { + if status := _dh(&self.e, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } + + case .ss: + dh := dh_buf[:d_len] + if status := _dh(&self.s, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + + case .psk: + symmetricstate_mix_key_and_hash(&self.symmetric_state, self.psk[:]) + } + } + self.current_message += 1 // Advance after the current message is successful. + + pattern_len := len(pattern_buf) + payload_len := len(payload) + msg_len := pattern_len + payload_len + if cipherstate_has_key(&self.symmetric_state.cipher_state) { + msg_len += TAG_SIZE + } + + msg: []byte + if msg_len != 0 { + did_alloc: bool + if dst != nil { + if len(dst) < msg_len { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + msg = dst[:msg_len] + } else { + err: runtime.Allocator_Error + msg, err = make([]byte, msg_len, allocator) + if err != nil { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + did_alloc = true + } + + copy(msg, pattern_buf[:]) + ciphertext := msg[pattern_len:] + if _, status := symmetricstate_encrypt_and_hash(&self.symmetric_state, payload, ciphertext); status != .Ok { + if did_alloc { + delete(msg) + } + self.status = .Handshake_Failed + return nil, status + } + } + + if self.current_message == len(self.message_pattern.messages) { + self.current_message = -1 + self.status = .Handshake_Complete + } + + return msg, self.status +} + +// Takes a byte sequence containing a Noise handshake message, and a +// payload_buffer to write the message's plaintext payload into. +// Performs the following steps, aborting if any DecryptAndHash() +// call returns an error: +// - Fetches and deletes the next message pattern from message_pattern, +// then sequentially processes each token from the message pattern: +// - For "e": Sets re (which must be empty) to the next DHLEN bytes +// from the message. Calls MixHash(re.public_key). +// - For "s": Sets temp to the next DHLEN + 16 bytes of the message +// if HasKey() == True, or to the next DHLEN bytes otherwise. +// Sets rs (which must be empty) to DecryptAndHash(temp). +// - For "ee": Calls MixKey(DH(e, re)). +// - For "es": Calls MixKey(DH(e, rs)) if initiator, MixKey(DH(s, re)) +// if responder. +// - For "se": Calls MixKey(DH(s, re)) if initiator, MixKey(DH(e, rs)) +// if responder. +// -For "ss": Calls MixKey(DH(s, rs)). +// - Calls DecryptAndHash() on the remaining bytes of the message and stores +// the output into payload_buffer. +// – (SKIPPED) If there are no more message patterns returns two new +// CipherState objects by calling Split(). +// +// Calling Split() is left to a separate function, although it is technically +// part of the specification. +@(require_results) +handshakestate_read_message :: proc(self: ^Handshake_State, message, dst: []byte, allocator := context.allocator) -> ([]byte, Status) { + ensure(self.status == .Handshake_Pending, "crypto/noise: invalid state for ReadMessage") + + protocol := &self.symmetric_state.protocol + d_len := dh_len(&self.symmetric_state.protocol) + + dh_buf: [MAX_DH_SIZE]byte = --- + defer crypto.zero_explicit(&dh_buf, size_of(dh_buf)) + + msg := message + + pattern := self.message_pattern.messages[self.current_message] + for token in pattern { + switch token { + case .e: + if len(msg) < d_len { + return nil, .Invalid_Handshake_Message + } + re := msg[:d_len] + + if ecdh.curve(&self.re) != .Invalid { + panic("crypto/noise: re was not empty when processing token 'e' during ReadMessage") + } + + if !ecdh.public_key_set_bytes(&self.re, protocol.dh, re) { + return nil, .Invalid_Handshake_Message + } + symmetricstate_mix_hash(&self.symmetric_state, re) + if self.message_pattern.is_psk { + symmetricstate_mix_key(&self.symmetric_state, re) + } + msg = msg[d_len:] + + case .s: + rs_len := d_len + if cipherstate_has_key(&self.symmetric_state.cipher_state) { + rs_len += TAG_SIZE + } + if len(msg) < rs_len { + self.status = .Handshake_Failed + return nil, .Invalid_Handshake_Message + } + + rs := dh_buf[:d_len] + if _, status := symmetricstate_decrypt_and_hash(&self.symmetric_state, msg[:rs_len], rs); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + + if ecdh.curve(&self.rs) != .Invalid { + panic("crypto/noise: rs was not empty when processing token 's' during ReadMessage") + } + + if !ecdh.public_key_set_bytes(&self.rs, protocol.dh, rs) { + self.status = .Handshake_Failed + return nil, .Invalid_Handshake_Message + } + msg = msg[rs_len:] + + case .ee: + dh := dh_buf[:d_len] + if status := _dh(&self.e, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + + case .es: + dh := dh_buf[:d_len] + if self.initiator { + if status := _dh(&self.e, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } else { + if status := _dh(&self.s, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } + + case .se: + dh := dh_buf[:d_len] + if self.initiator { + if status := _dh(&self.s, &self.re, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } else { + if status := _dh(&self.e, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + } + + case .ss: + dh := dh_buf[:d_len] + if status := _dh(&self.s, &self.rs, dh); status != .Ok { + self.status = .Handshake_Failed + return nil, status + } + symmetricstate_mix_key(&self.symmetric_state, dh) + + case .psk: + symmetricstate_mix_key_and_hash(&self.symmetric_state, self.psk[:]) + } + } + self.current_message += 1 // Advance after the current message is successful. + + payload: []byte + payload_len := len(msg) + if cipherstate_has_key(&self.symmetric_state.cipher_state) { + if payload_len < TAG_SIZE { + self.status = .Handshake_Failed + return nil, self.status + } + payload_len -= TAG_SIZE + } + + did_alloc: bool + if dst != nil { + if len(dst) < payload_len { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + payload = dst[:payload_len] + } else if payload_len > 0 { + err: runtime.Allocator_Error + payload, err = make([]byte, payload_len, allocator) + if err != nil { + self.status = .Handshake_Failed + return nil, .Out_Of_Memory + } + did_alloc = true + } + + if _, status := symmetricstate_decrypt_and_hash(&self.symmetric_state, msg, payload); status != .Ok { + if did_alloc { + delete(payload) + } + self.status = .Handshake_Failed + return nil, self.status + } + + if self.current_message == len(self.message_pattern.messages) { + self.current_message = -1 + self.status = .Handshake_Complete + } + + return payload, self.status +} + +@(require_results) +protocol_from_string :: proc(self: ^Protocol, protocol_name: string) -> Status { + self^ = Protocol{} + + pattern, dh, cipher, hash, status := split_protocol_string(protocol_name) + if status != .Ok { + return status + } + + self.handshake_pattern = pattern + self.dh = dh + self.cipher = cipher + self.hash = hash + + return .Ok +} diff --git a/core/crypto/pbkdf2/pbkdf2.odin b/core/crypto/pbkdf2/pbkdf2.odin index 8bb5cb73e..c27ec4aa2 100644 --- a/core/crypto/pbkdf2/pbkdf2.odin +++ b/core/crypto/pbkdf2/pbkdf2.odin @@ -1,14 +1,14 @@ /* -package pbkdf2 implements the PBKDF2 password-based key derivation function. +`PBKDF2` password-based key derivation function. See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]] */ package pbkdf2 +import "core:crypto" import "core:crypto/hash" import "core:crypto/hmac" import "core:encoding/endian" -import "core:mem" // derive invokes PBKDF2-HMAC with the specified hash algorithm, password, // salt, iteration count, and outputs the derived key to dst. @@ -66,12 +66,12 @@ derive :: proc( dst_blk = dst_blk[h_len:] } - // Instead of rounding l up, just proceass the one extra block iff + // Instead of rounding l up, just proceass the one extra block if and only if (⟺) // r != 0. if r > 0 { tmp: [hash.MAX_DIGEST_SIZE]byte blk := tmp[:h_len] - defer mem.zero_explicit(raw_data(blk), h_len) + defer crypto.zero_explicit(raw_data(blk), h_len) _F(&base, salt, iterations, u32(l + 1), blk) copy(dst_blk, blk) @@ -84,7 +84,7 @@ _F :: proc(base: ^hmac.Context, salt: []byte, c: u32, i: u32, dst_blk: []byte) { tmp: [hash.MAX_DIGEST_SIZE]byte u := tmp[:h_len] - defer mem.zero_explicit(raw_data(u), h_len) + defer crypto.zero_explicit(raw_data(u), h_len) // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c // diff --git a/core/crypto/poly1305/poly1305.odin b/core/crypto/poly1305/poly1305.odin index 3dd915da7..ed2bec82d 100644 --- a/core/crypto/poly1305/poly1305.odin +++ b/core/crypto/poly1305/poly1305.odin @@ -1,5 +1,5 @@ /* -package poly1305 implements the Poly1305 one-time MAC algorithm. +`Poly1305` one-time MAC algorithm. See: - [[ https://datatracker.ietf.org/doc/html/rfc8439 ]] @@ -10,7 +10,6 @@ import "core:crypto" import field "core:crypto/_fiat/field_poly1305" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // KEY_SIZE is the Poly1305 key size in bytes. KEY_SIZE :: 32 @@ -34,7 +33,7 @@ sum :: proc(dst, msg, key: []byte) { } // verify will verify the Poly1305 tag computed with the key over msg and -// return true iff the tag is valid. It requires that the tag is correctly +// return true if and only if (⟺) the tag is valid. It requires that the tag is correctly // sized. verify :: proc(tag, msg, key: []byte) -> bool { ctx: Context = --- @@ -155,10 +154,10 @@ final :: proc(ctx: ^Context, dst: []byte) { // reset sanitizes the Context. The Context must be re-initialized to // be used again. reset :: proc(ctx: ^Context) { - mem.zero_explicit(&ctx._r, size_of(ctx._r)) - mem.zero_explicit(&ctx._a, size_of(ctx._a)) - mem.zero_explicit(&ctx._s, size_of(ctx._s)) - mem.zero_explicit(&ctx._buffer, size_of(ctx._buffer)) + crypto.zero_explicit(&ctx._r, size_of(ctx._r)) + crypto.zero_explicit(&ctx._a, size_of(ctx._a)) + crypto.zero_explicit(&ctx._s, size_of(ctx._s)) + crypto.zero_explicit(&ctx._buffer, size_of(ctx._buffer)) ctx._is_initialized = false } diff --git a/core/crypto/rand_bsd.odin b/core/crypto/rand_bsd.odin deleted file mode 100644 index 78a6fcaaf..000000000 --- a/core/crypto/rand_bsd.odin +++ /dev/null @@ -1,15 +0,0 @@ -#+build freebsd, openbsd, netbsd -package crypto - -foreign import libc "system:c" - -HAS_RAND_BYTES :: true - -foreign libc { - arc4random_buf :: proc(buf: [^]byte, nbytes: uint) --- -} - -@(private) -_rand_bytes :: proc(dst: []byte) { - arc4random_buf(raw_data(dst), len(dst)) -} diff --git a/core/crypto/rand_darwin.odin b/core/crypto/rand_darwin.odin deleted file mode 100644 index df474bc4c..000000000 --- a/core/crypto/rand_darwin.odin +++ /dev/null @@ -1,17 +0,0 @@ -package crypto - -import "core:fmt" - -import CF "core:sys/darwin/CoreFoundation" -import Sec "core:sys/darwin/Security" - -HAS_RAND_BYTES :: true - -@(private) -_rand_bytes :: proc(dst: []byte) { - err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst)) - if err != .Success { - msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err)) - fmt.panicf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg) - } -} diff --git a/core/crypto/rand_generic.odin b/core/crypto/rand_generic.odin deleted file mode 100644 index 8266f8ffc..000000000 --- a/core/crypto/rand_generic.odin +++ /dev/null @@ -1,16 +0,0 @@ -#+build !linux -#+build !windows -#+build !openbsd -#+build !freebsd -#+build !netbsd -#+build !darwin -#+build !js -#+build !wasi -package crypto - -HAS_RAND_BYTES :: false - -@(private) -_rand_bytes :: proc(dst: []byte) { - unimplemented("crypto: rand_bytes not supported on this OS") -} diff --git a/core/crypto/rand_js.odin b/core/crypto/rand_js.odin deleted file mode 100644 index 72093810e..000000000 --- a/core/crypto/rand_js.odin +++ /dev/null @@ -1,24 +0,0 @@ -package crypto - -foreign import "odin_env" -foreign odin_env { - @(link_name = "rand_bytes") - env_rand_bytes :: proc "contextless" (buf: []byte) --- -} - -HAS_RAND_BYTES :: true - -@(private) -_MAX_PER_CALL_BYTES :: 65536 // 64kiB - -@(private) -_rand_bytes :: proc(dst: []byte) { - dst := dst - - for len(dst) > 0 { - to_read := min(len(dst), _MAX_PER_CALL_BYTES) - env_rand_bytes(dst[:to_read]) - - dst = dst[to_read:] - } -} diff --git a/core/crypto/rand_linux.odin b/core/crypto/rand_linux.odin deleted file mode 100644 index 7e0edbb7e..000000000 --- a/core/crypto/rand_linux.odin +++ /dev/null @@ -1,40 +0,0 @@ -package crypto - -import "core:fmt" - -import "core:sys/linux" - -HAS_RAND_BYTES :: true - -@(private) -_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1 - -@(private) -_rand_bytes :: proc (dst: []byte) { - dst := dst - l := len(dst) - - for l > 0 { - to_read := min(l, _MAX_PER_CALL_BYTES) - n_read, errno := linux.getrandom(dst[:to_read], {}) - #partial switch errno { - case .NONE: - // Do nothing - case .EINTR: - // Call interupted by a signal handler, just retry the - // request. - continue - case .ENOSYS: - // The kernel is apparently prehistoric (< 3.17 circa 2014) - // and does not support getrandom. - panic("crypto: getrandom not available in kernel") - case: - // All other failures are things that should NEVER happen - // unless the kernel interface changes (ie: the Linux - // developers break userland). - fmt.panicf("crypto: getrandom failed: %v", errno) - } - l -= n_read - dst = dst[n_read:] - } -} diff --git a/core/crypto/rand_wasi.odin b/core/crypto/rand_wasi.odin deleted file mode 100644 index 9653fb985..000000000 --- a/core/crypto/rand_wasi.odin +++ /dev/null @@ -1,13 +0,0 @@ -package crypto - -import "core:fmt" -import "core:sys/wasm/wasi" - -HAS_RAND_BYTES :: true - -@(private) -_rand_bytes :: proc(dst: []byte) { - if err := wasi.random_get(dst); err != nil { - fmt.panicf("crypto: wasi.random_get failed: %v", err) - } -} diff --git a/core/crypto/rand_windows.odin b/core/crypto/rand_windows.odin deleted file mode 100644 index 83a976e38..000000000 --- a/core/crypto/rand_windows.odin +++ /dev/null @@ -1,26 +0,0 @@ -package crypto - -import win32 "core:sys/windows" -import "core:os" -import "core:fmt" - -HAS_RAND_BYTES :: true - -@(private) -_rand_bytes :: proc(dst: []byte) { - ret := os.Platform_Error(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)) - if ret != nil { - #partial switch ret { - case os.ERROR_INVALID_HANDLE: - // The handle to the first parameter is invalid. - // This should not happen here, since we explicitly pass nil to it - panic("crypto: BCryptGenRandom Invalid handle for hAlgorithm") - case os.ERROR_INVALID_PARAMETER: - // One of the parameters was invalid - panic("crypto: BCryptGenRandom Invalid parameter") - case: - // Unknown error - fmt.panicf("crypto: BCryptGenRandom failed: %d\n", ret) - } - } -} diff --git a/core/crypto/ristretto255/ristretto255.odin b/core/crypto/ristretto255/ristretto255.odin index 20a002900..ef899d1da 100644 --- a/core/crypto/ristretto255/ristretto255.odin +++ b/core/crypto/ristretto255/ristretto255.odin @@ -1,14 +1,14 @@ /* -package ristretto255 implement the ristretto255 prime-order group. +Ristretto255 prime-order group. See: - [[ https://www.rfc-editor.org/rfc/rfc9496 ]] */ package ristretto255 +import "core:crypto" import grp "core:crypto/_edwards25519" import field "core:crypto/_fiat/field_curve25519" -import "core:mem" // ELEMENT_SIZE is the size of a byte-encoded ristretto255 group element. ELEMENT_SIZE :: 32 @@ -71,7 +71,7 @@ Group_Element :: struct { // ge_clear clears ge to the uninitialized state. ge_clear :: proc "contextless" (ge: ^Group_Element) { - mem.zero_explicit(ge, size_of(Group_Element)) + crypto.zero_explicit(ge, size_of(Group_Element)) } // ge_set sets `ge = a`. @@ -360,7 +360,7 @@ ge_double_scalarmult_generator_vartime :: proc( ge._is_initialized = true } -// ge_cond_negate sets `ge = a` iff `ctrl == 0` and `ge = -a` iff `ctrl == 1`. +// ge_cond_negate sets `ge = a` if and only if (⟺) `ctrl == 0` and `ge = -a` if and only if (⟺) `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) { _ge_ensure_initialized([]^Group_Element{a}) @@ -369,7 +369,7 @@ ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) { ge._is_initialized = true } -// ge_cond_assign sets `ge = ge` iff `ctrl == 0` and `ge = a` iff `ctrl == 1`. +// ge_cond_assign sets `ge = ge` if and only if (⟺) `ctrl == 0` and `ge = a` if and only if (⟺) `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) { _ge_ensure_initialized([]^Group_Element{ge, a}) @@ -377,7 +377,7 @@ ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) { grp.ge_cond_assign(&ge._p, &a._p, ctrl) } -// ge_cond_select sets `ge = a` iff `ctrl == 0` and `ge = b` iff `ctrl == 1`. +// ge_cond_select sets `ge = a` if and only if (⟺) `ctrl == 0` and `ge = b` if and only if (⟺) `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) { _ge_ensure_initialized([]^Group_Element{a, b}) @@ -386,7 +386,7 @@ ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) { ge._is_initialized = true } -// ge_equal returns 1 iff `a == b`, and 0 otherwise. +// ge_equal returns 1 if and only if (⟺) `a == b`, and 0 otherwise. @(require_results) ge_equal :: proc(a, b: ^Group_Element) -> int { _ge_ensure_initialized([]^Group_Element{a, b}) @@ -405,7 +405,7 @@ ge_equal :: proc(a, b: ^Group_Element) -> int { return ret } -// ge_is_identity returns 1 iff `ge` is the identity element, and 0 otherwise. +// ge_is_identity returns 1 if and only if (⟺) `ge` is the identity element, and 0 otherwise. @(require_results) ge_is_identity :: proc(ge: ^Group_Element) -> int { return ge_equal(ge, &GE_IDENTITY) diff --git a/core/crypto/ristretto255/ristretto255_scalar.odin b/core/crypto/ristretto255/ristretto255_scalar.odin index 75844b3f4..743e02ef3 100644 --- a/core/crypto/ristretto255/ristretto255_scalar.odin +++ b/core/crypto/ristretto255/ristretto255_scalar.odin @@ -80,13 +80,13 @@ sc_square :: proc "contextless" (sc, a: ^Scalar) { grp.sc_square(sc, a) } -// sc_cond_assign sets `sc = sc` iff `ctrl == 0` and `sc = a` iff `ctrl == 1`. +// sc_cond_assign sets `sc = sc` if and only if (⟺) `ctrl == 0` and `sc = a` if and only if (⟺) `ctrl == 1`. // Behavior for all other values of ctrl are undefined, sc_cond_assign :: proc(sc, a: ^Scalar, ctrl: int) { grp.sc_cond_assign(sc, a, ctrl) } -// sc_equal returns 1 iff `a == b`, and 0 otherwise. +// sc_equal returns 1 if and only if (⟺) `a == b`, and 0 otherwise. @(require_results) sc_equal :: proc(a, b: ^Scalar) -> int { return grp.sc_equal(a, b) diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index bf9b81601..2eac9240b 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -1,5 +1,5 @@ /* -package sha2 implements the SHA2 hash algorithm family. +`SHA2` hash algorithm family. See: - [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]] @@ -9,15 +9,15 @@ package sha2 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. */ +@(require) import "core:crypto" @(require) import "core:encoding/endian" import "core:math/bits" -@(require) import "core:mem" // DIGEST_SIZE_224 is the SHA-224 digest size in bytes. DIGEST_SIZE_224 :: 28 @@ -44,7 +44,8 @@ Context_256 :: struct { length: u64, md_bits: int, - is_initialized: bool, + is_hw_accelerated: bool, + is_initialized: bool, } // Context_512 is a SHA-384, SHA-512 or SHA-512/256 instance. @@ -55,7 +56,8 @@ Context_512 :: struct { length: u64, md_bits: int, - is_initialized: bool, + is_hw_accelerated: bool, + is_initialized: bool, } // init_224 initializes a Context_256 for SHA-224. @@ -88,6 +90,9 @@ init_512_256 :: proc(ctx: ^Context_512) { _init(ctx) } +@(private) +ERR_HW_NOT_SUPPORTED :: "crypto/sha2: hardware implementation unsupported" + @(private) _init :: proc(ctx: ^$T) { when T == Context_256 { @@ -113,6 +118,8 @@ _init :: proc(ctx: ^$T) { case: panic("crypto/sha2: invalid digest output length") } + + ctx.is_hw_accelerated = is_hardware_accelerated_256() } else when T == Context_512 { switch ctx.md_bits { case 256: @@ -148,6 +155,8 @@ _init :: proc(ctx: ^$T) { case: panic("crypto/sha2: invalid digest output length") } + + ctx.is_hw_accelerated = is_hardware_accelerated_512() } ctx.length = 0 @@ -191,7 +200,7 @@ update :: proc(ctx: ^$T, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { ensure(ctx.is_initialized) @@ -260,14 +269,14 @@ reset :: proc(ctx: ^$T) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } /* SHA2 implementation */ -@(private, rodata) +@(private = "file", rodata) SHA256_K := [64]u32 { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -287,7 +296,7 @@ SHA256_K := [64]u32 { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, } -@(private, rodata) +@(private = "file", rodata) SHA512_K := [80]u64 { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, @@ -336,70 +345,70 @@ SHA256_ROUNDS :: 64 @(private) SHA512_ROUNDS :: 80 -@(private) +@(private = "file") SHA256_CH :: #force_inline proc "contextless" (x, y, z: u32) -> u32 { return (x & y) ~ (~x & z) } -@(private) +@(private = "file") SHA256_MAJ :: #force_inline proc "contextless" (x, y, z: u32) -> u32 { return (x & y) ~ (x & z) ~ (y & z) } -@(private) +@(private = "file") SHA512_CH :: #force_inline proc "contextless" (x, y, z: u64) -> u64 { return (x & y) ~ (~x & z) } -@(private) +@(private = "file") SHA512_MAJ :: #force_inline proc "contextless" (x, y, z: u64) -> u64 { return (x & y) ~ (x & z) ~ (y & z) } -@(private) +@(private = "file") SHA256_F1 :: #force_inline proc "contextless" (x: u32) -> u32 { return bits.rotate_left32(x, 30) ~ bits.rotate_left32(x, 19) ~ bits.rotate_left32(x, 10) } -@(private) +@(private = "file") SHA256_F2 :: #force_inline proc "contextless" (x: u32) -> u32 { return bits.rotate_left32(x, 26) ~ bits.rotate_left32(x, 21) ~ bits.rotate_left32(x, 7) } -@(private) +@(private = "file") SHA256_F3 :: #force_inline proc "contextless" (x: u32) -> u32 { return bits.rotate_left32(x, 25) ~ bits.rotate_left32(x, 14) ~ (x >> 3) } -@(private) +@(private = "file") SHA256_F4 :: #force_inline proc "contextless" (x: u32) -> u32 { return bits.rotate_left32(x, 15) ~ bits.rotate_left32(x, 13) ~ (x >> 10) } -@(private) +@(private = "file") SHA512_F1 :: #force_inline proc "contextless" (x: u64) -> u64 { return bits.rotate_left64(x, 36) ~ bits.rotate_left64(x, 30) ~ bits.rotate_left64(x, 25) } -@(private) +@(private = "file") SHA512_F2 :: #force_inline proc "contextless" (x: u64) -> u64 { return bits.rotate_left64(x, 50) ~ bits.rotate_left64(x, 46) ~ bits.rotate_left64(x, 23) } -@(private) +@(private = "file") SHA512_F3 :: #force_inline proc "contextless" (x: u64) -> u64 { return bits.rotate_left64(x, 63) ~ bits.rotate_left64(x, 56) ~ (x >> 7) } -@(private) +@(private = "file") SHA512_F4 :: #force_inline proc "contextless" (x: u64) -> u64 { return bits.rotate_left64(x, 45) ~ bits.rotate_left64(x, 3) ~ (x >> 6) } -@(private) +@(private = "file") sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) #no_bounds_check { when T == Context_256 { - if is_hardware_accelerated_256() { + if ctx.is_hw_accelerated { sha256_transf_hw(ctx, data) return } @@ -410,6 +419,11 @@ sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) #no_bounds_check { CURR_BLOCK_SIZE :: BLOCK_SIZE_256 } else when T == Context_512 { + if ctx.is_hw_accelerated { + sha512_transf_hw(ctx, data) + return + } + w: [SHA512_ROUNDS]u64 wv: [8]u64 t1, t2: u64 diff --git a/core/crypto/sha2/sha256_impl_hw_arm.odin b/core/crypto/sha2/sha256_impl_hw_arm.odin new file mode 100644 index 000000000..618cc6fff --- /dev/null +++ b/core/crypto/sha2/sha256_impl_hw_arm.odin @@ -0,0 +1,224 @@ +#+build arm64,arm32 +package sha2 + +// Based on the public domain code by Jeffrey Walton, though +// realistically, there only is one sensible way to write this. +// +// See: https://github.com/noloader/SHA-Intrinsics + +import "base:intrinsics" +import "core:simd" +import "core:simd/arm" +import "core:sys/info" + +// is_hardware_accelerated_256 returns true if and only if (⟺) hardware +// accelerated SHA-224/SHA-256 is supported. +is_hardware_accelerated_256 :: proc "contextless" () -> bool { + req_features :: info.CPU_Features{ + .asimd, + .sha256, + } + return info.cpu_features() >= req_features +} + +@(private = "file") +K_0 :: simd.u32x4{0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5} +@(private = "file") +K_1 :: simd.u32x4{0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5} +@(private = "file") +K_2 :: simd.u32x4{0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3} +@(private = "file") +K_3 :: simd.u32x4{0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174} +@(private = "file") +K_4 :: simd.u32x4{0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC} +@(private = "file") +K_5 :: simd.u32x4{0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA} +@(private = "file") +K_6 :: simd.u32x4{0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7} +@(private = "file") +K_7 :: simd.u32x4{0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967} +@(private = "file") +K_8 :: simd.u32x4{0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13} +@(private = "file") +K_9 :: simd.u32x4{0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85} +@(private = "file") +K_10 :: simd.u32x4{0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3} +@(private = "file") +K_11 :: simd.u32x4{0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070} +@(private = "file") +K_12 :: simd.u32x4{0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5} +@(private = "file") +K_13 :: simd.u32x4{0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3} +@(private = "file") +K_14 :: simd.u32x4{0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208} +@(private = "file") +K_15 :: simd.u32x4{0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2} + +@(private, enable_target_feature = "neon,sha2") +sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) #no_bounds_check { + state_0 := intrinsics.unaligned_load((^simd.u32x4)(&ctx.h[0])) + state_1 := intrinsics.unaligned_load((^simd.u32x4)(&ctx.h[4])) + + data := data + for len(data) >= BLOCK_SIZE_256 { + // Save state + abef_save, cdgh_save := state_0, state_1 + + // Load message + msg_0 := intrinsics.unaligned_load((^simd.u32x4)(raw_data(data))) + msg_1 := intrinsics.unaligned_load((^simd.u32x4)(raw_data(data[16:]))) + msg_2 := intrinsics.unaligned_load((^simd.u32x4)(raw_data(data[32:]))) + msg_3 := intrinsics.unaligned_load((^simd.u32x4)(raw_data(data[48:]))) + + // Reverse for little endian + when ODIN_ENDIAN == .Little { + msg_0 = byteswap_u32x4(msg_0) + msg_1 = byteswap_u32x4(msg_1) + msg_2 = byteswap_u32x4(msg_2) + msg_3 = byteswap_u32x4(msg_3) + } + + tmp_0 := simd.add(msg_0, K_0) + + // Rounds 0-3 + msg_0 = arm.vsha256su0q_u32(msg_0, msg_1) + tmp_2 := state_0 + tmp_1 := simd.add(msg_1, K_1) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_0 = arm.vsha256su1q_u32(msg_0, msg_2, msg_3) + + // Rounds 4-7 + msg_1 = arm.vsha256su0q_u32(msg_1, msg_2) + tmp_2 = state_0 + tmp_0 = simd.add(msg_2, K_2) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_1 = arm.vsha256su1q_u32(msg_1, msg_3, msg_0) + + // Rounds 8-11 + msg_2 = arm.vsha256su0q_u32(msg_2, msg_3) + tmp_2 = state_0 + tmp_1 = simd.add(msg_3, K_3) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_2 = arm.vsha256su1q_u32(msg_2, msg_0, msg_1) + + // Rounds 12-15 + msg_3 = arm.vsha256su0q_u32(msg_3, msg_0) + tmp_2 = state_0 + tmp_0 = simd.add(msg_0, K_4) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_3 = arm.vsha256su1q_u32(msg_3, msg_1, msg_2) + + // Rounds 16-19 + msg_0 = arm.vsha256su0q_u32(msg_0, msg_1) + tmp_2 = state_0 + tmp_1 = simd.add(msg_1, K_5) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_0 = arm.vsha256su1q_u32(msg_0, msg_2, msg_3) + + // Rounds 20-23 + msg_1 = arm.vsha256su0q_u32(msg_1, msg_2) + tmp_2 = state_0 + tmp_0 = simd.add(msg_2, K_6) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_1 = arm.vsha256su1q_u32(msg_1, msg_3, msg_0) + + // Rounds 24-27 + msg_2 = arm.vsha256su0q_u32(msg_2, msg_3) + tmp_2 = state_0 + tmp_1 = simd.add(msg_3, K_7) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_2 = arm.vsha256su1q_u32(msg_2, msg_0, msg_1) + + // Rounds 28-31 + msg_3 = arm.vsha256su0q_u32(msg_3, msg_0) + tmp_2 = state_0 + tmp_0 = simd.add(msg_0, K_8) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_3 = arm.vsha256su1q_u32(msg_3, msg_1, msg_2) + + // Rounds 32-35 + msg_0 = arm.vsha256su0q_u32(msg_0, msg_1) + tmp_2 = state_0 + tmp_1 = simd.add(msg_1, K_9) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_0 = arm.vsha256su1q_u32(msg_0, msg_2, msg_3) + + // Rounds 36-39 + msg_1 = arm.vsha256su0q_u32(msg_1, msg_2) + tmp_2 = state_0 + tmp_0 = simd.add(msg_2, K_10) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_1 = arm.vsha256su1q_u32(msg_1, msg_3, msg_0) + + // Rounds 40-43 + msg_2 = arm.vsha256su0q_u32(msg_2, msg_3) + tmp_2 = state_0 + tmp_1 = simd.add(msg_3, K_11) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + msg_2 = arm.vsha256su1q_u32(msg_2, msg_0, msg_1) + + // Rounds 44-47 + msg_3 = arm.vsha256su0q_u32(msg_3, msg_0) + tmp_2 = state_0 + tmp_0 = simd.add(msg_0, K_12) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + msg_3 = arm.vsha256su1q_u32(msg_3, msg_1, msg_2) + + // Rounds 48-51 + tmp_2 = state_0 + tmp_1 = simd.add(msg_1, K_13) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + + // Rounds 52-55 + tmp_2 = state_0 + tmp_0 = simd.add(msg_2, K_14) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + + // Rounds 56-59 + tmp_2 = state_0 + tmp_1 = simd.add(msg_3, K_15) + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_0) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_0) + + // Rounds 60-63 + tmp_2 = state_0 + state_0 = arm.vsha256hq_u32(state_0, state_1, tmp_1) + state_1 = arm.vsha256h2q_u32(state_1, tmp_2, tmp_1) + + // Combine state + state_0 = simd.add(state_0, abef_save) + state_1 = simd.add(state_1, cdgh_save) + + data = data[BLOCK_SIZE_256:] + } + + intrinsics.unaligned_store((^simd.u32x4)(&ctx.h[0]), state_0) + intrinsics.unaligned_store((^simd.u32x4)(&ctx.h[4]), state_1) +} + +when ODIN_ENDIAN == .Little { + @(private = "file", enable_target_feature = "neon") + byteswap_u32x4 :: #force_inline proc "contextless" (a: simd.u32x4) -> simd.u32x4 { + return transmute(simd.u32x4)( + simd.shuffle( + transmute(simd.u8x16)(a), + transmute(simd.u8x16)(a), + 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, + ) + ) + } +} \ No newline at end of file diff --git a/core/crypto/sha2/sha2_impl_hw_gen.odin b/core/crypto/sha2/sha256_impl_hw_gen.odin similarity index 53% rename from core/crypto/sha2/sha2_impl_hw_gen.odin rename to core/crypto/sha2/sha256_impl_hw_gen.odin index 85c7f8b28..ad384caaa 100644 --- a/core/crypto/sha2/sha2_impl_hw_gen.odin +++ b/core/crypto/sha2/sha256_impl_hw_gen.odin @@ -1,15 +1,15 @@ #+build !amd64 +#+build !arm64 +#+build !arm32 package sha2 -@(private = "file") -ERR_HW_NOT_SUPPORTED :: "crypto/sha2: hardware implementation unsupported" - -// is_hardware_accelerated_256 returns true iff hardware accelerated -// SHA-224/SHA-256 is supported. +// is_hardware_accelerated_256 returns true if and only if (⟺) hardware +// accelerated SHA-224/SHA-256 is supported. is_hardware_accelerated_256 :: proc "contextless" () -> bool { return false } +@(private) sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) { panic_contextless(ERR_HW_NOT_SUPPORTED) } diff --git a/core/crypto/sha2/sha2_impl_hw_intel.odin b/core/crypto/sha2/sha256_impl_hw_intel.odin similarity index 93% rename from core/crypto/sha2/sha2_impl_hw_intel.odin rename to core/crypto/sha2/sha256_impl_hw_intel.odin index f16f353df..fcec80a3c 100644 --- a/core/crypto/sha2/sha2_impl_hw_intel.odin +++ b/core/crypto/sha2/sha256_impl_hw_intel.odin @@ -49,21 +49,16 @@ K_14 :: simd.u64x2{0x78a5636f748f82ee, 0x8cc7020884c87814} K_15 :: simd.u64x2{0xa4506ceb90befffa, 0xc67178f2bef9a3f7} -// is_hardware_accelerated_256 returns true iff hardware accelerated +// is_hardware_accelerated_256 returns true if and only if (⟺) hardware accelerated // SHA-224/SHA-256 is supported. is_hardware_accelerated_256 :: proc "contextless" () -> bool { - features, ok := info.cpu_features.? - if !ok { - return false - } - req_features :: info.CPU_Features{ .sse2, .ssse3, .sse41, .sha, } - return features >= req_features + return info.cpu_features() >= req_features } @(private, enable_target_feature="sse2,ssse3,sse4.1,sha") @@ -75,8 +70,7 @@ sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) #no_bou tmp = x86._mm_shuffle_epi32(tmp, 0xb1) // CDAB state_1 = x86._mm_shuffle_epi32(state_1, 0x1b) // EFGH state_0 := x86._mm_alignr_epi8(tmp, state_1, 8) // ABEF - // state_1 = x86._mm_blend_epi16(state_1, tmp, 0xf0) // CDGH - state_1 = kludge_mm_blend_epi16_0xf0(state_1, tmp) + state_1 = x86._mm_blend_epi16(state_1, tmp, 0xf0) // CDGH data := data for len(data) >= BLOCK_SIZE_256 { @@ -243,18 +237,9 @@ sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) #no_bou // Write back the updated state tmp = x86._mm_shuffle_epi32(state_0, 0x1b) // FEBA state_1 = x86._mm_shuffle_epi32(state_1, 0xb1) // DCHG - // state_0 = x86._mm_blend_epi16(tmp, state_1, 0xf0) // DCBA - state_0 = kludge_mm_blend_epi16_0xf0(tmp, state_1) + state_0 = x86._mm_blend_epi16(tmp, state_1, 0xf0) // DCBA state_1 = x86._mm_alignr_epi8(state_1, tmp, 8) // ABEF intrinsics.unaligned_store((^x86.__m128i)(&ctx.h[0]), state_0) intrinsics.unaligned_store((^x86.__m128i)(&ctx.h[4]), state_1) } - -@(private = "file") -kludge_mm_blend_epi16_0xf0 :: #force_inline proc "contextless"(a, b: x86.__m128i) -> x86.__m128i { - // HACK HACK HACK: LLVM got rid of `llvm.x86.sse41.pblendw`. - a_ := simd.to_array(a) - b_ := simd.to_array(b) - return x86.__m128i{a_[0], b_[1]} -} diff --git a/core/crypto/sha2/sha512_impl_hw_arm.odin b/core/crypto/sha2/sha512_impl_hw_arm.odin new file mode 100644 index 000000000..27ef83f5a --- /dev/null +++ b/core/crypto/sha2/sha512_impl_hw_arm.odin @@ -0,0 +1,498 @@ +// The round function's intrinsic calls are based on: +// https://github.com/LostInCompilation/HashMe/blob/main/src/SHA512_Hardware.cpp +// +// The zlib License +// +// Copyright (C) 2024 Marc Schöndorf +// +// This software is provided 'as-is', without any express or implied warranty. In +// no event will the authors be held liable for any damages arising from the use of +// this software. +// +// Permission is granted to anyone to use this software for any purpose, including +// commercial applications, and to alter it and redistribute it freely, subject to +// the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not claim +// that you wrote the original software. If you use this software in a product, +// an acknowledgment in the product documentation would be appreciated but is +// not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. + +#+build arm64 +package sha2 + +import "base:intrinsics" +import "core:simd" +import "core:simd/arm" +import "core:sys/info" + +// is_hardware_accelerated_512 returns true if and only if (⟺) hardware +// accelerated SHA-384, SHA-512, and SHA-512/256 are supported. +is_hardware_accelerated_512 :: proc "contextless" () -> bool { + req_features :: info.CPU_Features{ + .asimd, + .sha512, + .sha3, // XXX: LLVM groups these under `sha3`. + } + return info.cpu_features() >= req_features +} + +@(private = "file") +K_0 :: simd.u64x2{0x428a2f98d728ae22, 0x7137449123ef65cd} +@(private = "file") +K_1 :: simd.u64x2{0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc} +@(private = "file") +K_2 :: simd.u64x2{0x3956c25bf348b538, 0x59f111f1b605d019} +@(private = "file") +K_3 :: simd.u64x2{0x923f82a4af194f9b, 0xab1c5ed5da6d8118} +@(private = "file") +K_4 :: simd.u64x2{0xd807aa98a3030242, 0x12835b0145706fbe} +@(private = "file") +K_5 :: simd.u64x2{0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2} +@(private = "file") +K_6 :: simd.u64x2{0x72be5d74f27b896f, 0x80deb1fe3b1696b1} +@(private = "file") +K_7 :: simd.u64x2{0x9bdc06a725c71235, 0xc19bf174cf692694} +@(private = "file") +K_8 :: simd.u64x2{0xe49b69c19ef14ad2, 0xefbe4786384f25e3} +@(private = "file") +K_9 :: simd.u64x2{0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65} +@(private = "file") +K_10 :: simd.u64x2{0x2de92c6f592b0275, 0x4a7484aa6ea6e483} +@(private = "file") +K_11 :: simd.u64x2{0x5cb0a9dcbd41fbd4, 0x76f988da831153b5} +@(private = "file") +K_12 :: simd.u64x2{0x983e5152ee66dfab, 0xa831c66d2db43210} +@(private = "file") +K_13 :: simd.u64x2{0xb00327c898fb213f, 0xbf597fc7beef0ee4} +@(private = "file") +K_14 :: simd.u64x2{0xc6e00bf33da88fc2, 0xd5a79147930aa725} +@(private = "file") +K_15 :: simd.u64x2{0x06ca6351e003826f, 0x142929670a0e6e70} +@(private = "file") +K_16 :: simd.u64x2{0x27b70a8546d22ffc, 0x2e1b21385c26c926} +@(private = "file") +K_17 :: simd.u64x2{0x4d2c6dfc5ac42aed, 0x53380d139d95b3df} +@(private = "file") +K_18 :: simd.u64x2{0x650a73548baf63de, 0x766a0abb3c77b2a8} +@(private = "file") +K_19 :: simd.u64x2{0x81c2c92e47edaee6, 0x92722c851482353b} +@(private = "file") +K_20 :: simd.u64x2{0xa2bfe8a14cf10364, 0xa81a664bbc423001} +@(private = "file") +K_21 :: simd.u64x2{0xc24b8b70d0f89791, 0xc76c51a30654be30} +@(private = "file") +K_22 :: simd.u64x2{0xd192e819d6ef5218, 0xd69906245565a910} +@(private = "file") +K_23 :: simd.u64x2{0xf40e35855771202a, 0x106aa07032bbd1b8} +@(private = "file") +K_24 :: simd.u64x2{0x19a4c116b8d2d0c8, 0x1e376c085141ab53} +@(private = "file") +K_25 :: simd.u64x2{0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8} +@(private = "file") +K_26 :: simd.u64x2{0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb} +@(private = "file") +K_27 :: simd.u64x2{0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3} +@(private = "file") +K_28 :: simd.u64x2{0x748f82ee5defb2fc, 0x78a5636f43172f60} +@(private = "file") +K_29 :: simd.u64x2{0x84c87814a1f0ab72, 0x8cc702081a6439ec} +@(private = "file") +K_30 :: simd.u64x2{0x90befffa23631e28, 0xa4506cebde82bde9} +@(private = "file") +K_31 :: simd.u64x2{0xbef9a3f7b2c67915, 0xc67178f2e372532b} +@(private = "file") +K_32 :: simd.u64x2{0xca273eceea26619c, 0xd186b8c721c0c207} +@(private = "file") +K_33 :: simd.u64x2{0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178} +@(private = "file") +K_34 :: simd.u64x2{0x06f067aa72176fba, 0x0a637dc5a2c898a6} +@(private = "file") +K_35 :: simd.u64x2{0x113f9804bef90dae, 0x1b710b35131c471b} +@(private = "file") +K_36 :: simd.u64x2{0x28db77f523047d84, 0x32caab7b40c72493} +@(private = "file") +K_37 :: simd.u64x2{0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c} +@(private = "file") +K_38 :: simd.u64x2{0x4cc5d4becb3e42b6, 0x597f299cfc657e2a} +@(private = "file") +K_39 :: simd.u64x2{0x5fcb6fab3ad6faec, 0x6c44198c4a475817} + +@(private, enable_target_feature = "neon,sha3") +sha512_transf_hw :: proc "contextless" (ctx: ^Context_512, data: []byte) #no_bounds_check { + state_0 := intrinsics.unaligned_load((^simd.u64x2)(&ctx.h[0])) + state_1 := intrinsics.unaligned_load((^simd.u64x2)(&ctx.h[2])) + state_2 := intrinsics.unaligned_load((^simd.u64x2)(&ctx.h[4])) + state_3 := intrinsics.unaligned_load((^simd.u64x2)(&ctx.h[6])) + + data := data + for len(data) >= BLOCK_SIZE_512 { + ab_save, cd_save, ef_save, gh_save := state_0, state_1, state_2, state_3 + + // Load message + msg_0 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data))) + msg_1 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[16:]))) + msg_2 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[32:]))) + msg_3 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[48:]))) + msg_4 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[64:]))) + msg_5 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[80:]))) + msg_6 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[96:]))) + msg_7 := intrinsics.unaligned_load((^simd.u64x2)(raw_data(data[112:]))) + + // Reverse for little endian + when ODIN_ENDIAN == .Little { + msg_0 = byteswap_u64x2(msg_0) + msg_1 = byteswap_u64x2(msg_1) + msg_2 = byteswap_u64x2(msg_2) + msg_3 = byteswap_u64x2(msg_3) + msg_4 = byteswap_u64x2(msg_4) + msg_5 = byteswap_u64x2(msg_5) + msg_6 = byteswap_u64x2(msg_6) + msg_7 = byteswap_u64x2(msg_7) + } + + // Rounds 0-1 + msg_k := simd.add(msg_0, K_0) + tmp_0 := simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 := arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_0 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_0, msg_1), msg_7, simd.shuffle(msg_4, msg_5, 1, 2)) + + // Rounds 2-3 + msg_k = simd.add(msg_1, K_1) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_1 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_1, msg_2), msg_0, simd.shuffle(msg_5, msg_6, 1, 2)) + + // Rounds 4-5 + msg_k = simd.add(msg_2, K_2) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_2 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_2, msg_3), msg_1, simd.shuffle(msg_6, msg_7, 1, 2)) + + // Rounds 6-7 + msg_k = simd.add(msg_3, K_3) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_3 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_3, msg_4), msg_2, simd.shuffle(msg_7, msg_0, 1, 2)) + + // Rounds 8-9 + msg_k = simd.add(msg_4, K_4) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_4 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_4, msg_5), msg_3, simd.shuffle(msg_0, msg_1, 1, 2)) + + // Rounds 10-11 + msg_k = simd.add(msg_5, K_5) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_5 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_5, msg_6), msg_4, simd.shuffle(msg_1, msg_2, 1, 2)) + + // Rounds 12-13 + msg_k = simd.add(msg_6, K_6) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_6 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_6, msg_7), msg_5, simd.shuffle(msg_2, msg_3, 1, 2)) + + // Rounds 14-15 + msg_k = simd.add(msg_7, K_7) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_7 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_7, msg_0), msg_6, simd.shuffle(msg_3, msg_4, 1, 2)) + + // Rounds 16-17 + msg_k = simd.add(msg_0, K_8) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_0 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_0, msg_1), msg_7, simd.shuffle(msg_4, msg_5, 1, 2)) + + // Rounds 18-19 + msg_k = simd.add(msg_1, K_9) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_1 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_1, msg_2), msg_0, simd.shuffle(msg_5, msg_6, 1, 2)) + + // Rounds 20-21 + msg_k = simd.add(msg_2, K_10) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_2 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_2, msg_3), msg_1, simd.shuffle(msg_6, msg_7, 1, 2)) + + // Rounds 22-23 + msg_k = simd.add(msg_3, K_11) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_3 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_3, msg_4), msg_2, simd.shuffle(msg_7, msg_0, 1, 2)) + + // Rounds 24-25 + msg_k = simd.add(msg_4, K_12) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_4 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_4, msg_5), msg_3, simd.shuffle(msg_0, msg_1, 1, 2)) + + // Rounds 26-27 + msg_k = simd.add(msg_5, K_13) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_5 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_5, msg_6), msg_4, simd.shuffle(msg_1, msg_2, 1, 2)) + + // Rounds 28-29 + msg_k = simd.add(msg_6, K_14) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_6 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_6, msg_7), msg_5, simd.shuffle(msg_2, msg_3, 1, 2)) + + // Rounds 30-31 + msg_k = simd.add(msg_7, K_15) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_7 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_7, msg_0), msg_6, simd.shuffle(msg_3, msg_4, 1, 2)) + + // Rounds 32-33 + msg_k = simd.add(msg_0, K_16) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_0 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_0, msg_1), msg_7, simd.shuffle(msg_4, msg_5, 1, 2)) + + // Rounds 34-35 + msg_k = simd.add(msg_1, K_17) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_1 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_1, msg_2), msg_0, simd.shuffle(msg_5, msg_6, 1, 2)) + + // Rounds 36-37 + msg_k = simd.add(msg_2, K_18) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_2 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_2, msg_3), msg_1, simd.shuffle(msg_6, msg_7, 1, 2)) + + // Rounds 38-39 + msg_k = simd.add(msg_3, K_19) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_3 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_3, msg_4), msg_2, simd.shuffle(msg_7, msg_0, 1, 2)) + + // Rounds 40-41 + msg_k = simd.add(msg_4, K_20) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_4 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_4, msg_5), msg_3, simd.shuffle(msg_0, msg_1, 1, 2)) + + // Rounds 42-43 + msg_k = simd.add(msg_5, K_21) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_5 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_5, msg_6), msg_4, simd.shuffle(msg_1, msg_2, 1, 2)) + + // Rounds 44-45 + msg_k = simd.add(msg_6, K_22) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_6 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_6, msg_7), msg_5, simd.shuffle(msg_2, msg_3, 1, 2)) + + // Rounds 46-47 + msg_k = simd.add(msg_7, K_23) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_7 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_7, msg_0), msg_6, simd.shuffle(msg_3, msg_4, 1, 2)) + + // Rounds 48-49 + msg_k = simd.add(msg_0, K_24) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_0 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_0, msg_1), msg_7, simd.shuffle(msg_4, msg_5, 1, 2)) + + // Rounds 50-51 + msg_k = simd.add(msg_1, K_25) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_1 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_1, msg_2), msg_0, simd.shuffle(msg_5, msg_6, 1, 2)) + + // Rounds 52-53 + msg_k = simd.add(msg_2, K_26) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_2 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_2, msg_3), msg_1, simd.shuffle(msg_6, msg_7, 1, 2)) + + // Rounds 54-55 + msg_k = simd.add(msg_3, K_27) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_3 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_3, msg_4), msg_2, simd.shuffle(msg_7, msg_0, 1, 2)) + + // Rounds 56-57 + msg_k = simd.add(msg_4, K_28) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + msg_4 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_4, msg_5), msg_3, simd.shuffle(msg_0, msg_1, 1, 2)) + + // Rounds 58-59 + msg_k = simd.add(msg_5, K_29) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + msg_5 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_5, msg_6), msg_4, simd.shuffle(msg_1, msg_2, 1, 2)) + + // Rounds 60-61 + msg_k = simd.add(msg_6, K_30) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + msg_6 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_6, msg_7), msg_5, simd.shuffle(msg_2, msg_3, 1, 2)) + + // Rounds 62-63 + msg_k = simd.add(msg_7, K_31) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + msg_7 = arm.vsha512su1q_u64(arm.vsha512su0q_u64(msg_7, msg_0), msg_6, simd.shuffle(msg_3, msg_4, 1, 2)) + + // Rounds 64-65 + msg_k = simd.add(msg_0, K_32) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + + // Rounds 66-67 + msg_k = simd.add(msg_1, K_33) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + + // Rounds 68-69 + msg_k = simd.add(msg_2, K_34) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + + // Rounds 70-71 + msg_k = simd.add(msg_3, K_35) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + + // Rounds 72-73 + msg_k = simd.add(msg_4, K_36) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_3) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_2, state_3, 1, 2), simd.shuffle(state_1, state_2, 1, 2)) + state_3 = arm.vsha512h2q_u64(tmp_1, state_1, state_0) + state_1 = simd.add(state_1, tmp_1) + + // Rounds 74-75 + msg_k = simd.add(msg_5, K_37) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_2) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_1, state_2, 1, 2), simd.shuffle(state_0, state_1, 1, 2)) + state_2 = arm.vsha512h2q_u64(tmp_1, state_0, state_3) + state_0 = simd.add(state_0, tmp_1) + + // Rounds 76-77 + msg_k = simd.add(msg_6, K_38) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_1) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_0, state_1, 1, 2), simd.shuffle(state_3, state_0, 1, 2)) + state_1 = arm.vsha512h2q_u64(tmp_1, state_3, state_2) + state_3 = simd.add(state_3, tmp_1) + + // Rounds 78-79 + msg_k = simd.add(msg_7, K_39) + tmp_0 = simd.add(simd.shuffle(msg_k, msg_k, 1, 2), state_0) + tmp_1 = arm.vsha512hq_u64(tmp_0, simd.shuffle(state_3, state_0, 1, 2), simd.shuffle(state_2, state_3, 1, 2)) + state_0 = arm.vsha512h2q_u64(tmp_1, state_2, state_1) + state_2 = simd.add(state_2, tmp_1) + + // Combine state + state_0 = simd.add(state_0, ab_save) + state_1 = simd.add(state_1, cd_save) + state_2 = simd.add(state_2, ef_save) + state_3 = simd.add(state_3, gh_save) + + data = data[BLOCK_SIZE_512:] + } + + intrinsics.unaligned_store((^simd.u64x2)(&ctx.h[0]), state_0) + intrinsics.unaligned_store((^simd.u64x2)(&ctx.h[2]), state_1) + intrinsics.unaligned_store((^simd.u64x2)(&ctx.h[4]), state_2) + intrinsics.unaligned_store((^simd.u64x2)(&ctx.h[6]), state_3) +} + +when ODIN_ENDIAN == .Little { + @(private = "file", enable_target_feature = "neon") + byteswap_u64x2 :: #force_inline proc "contextless" (a: simd.u64x2) -> simd.u64x2 { + return transmute(simd.u64x2)( + simd.shuffle( + transmute(simd.u8x16)(a), + transmute(simd.u8x16)(a), + 7, 6, 5, 4, 3, 2, 1, 0, + 15, 14, 13, 12, 11, 10, 9, 8, + ) + ) + } +} diff --git a/core/crypto/sha2/sha512_impl_hw_gen.odin b/core/crypto/sha2/sha512_impl_hw_gen.odin new file mode 100644 index 000000000..701f82709 --- /dev/null +++ b/core/crypto/sha2/sha512_impl_hw_gen.odin @@ -0,0 +1,13 @@ +#+build !arm64 +package sha2 + +// is_hardware_accelerated_512 returns true if and only if (⟺) hardware +// accelerated SHA-384, SHA-512, and SHA-512/256 are supported. +is_hardware_accelerated_512 :: proc "contextless" () -> bool { + return false +} + +@(private) +sha512_transf_hw :: proc "contextless" (ctx: ^Context_512, data: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} diff --git a/core/crypto/sha3/sha3.odin b/core/crypto/sha3/sha3.odin index 3b7bdedd7..2f8d95092 100644 --- a/core/crypto/sha3/sha3.odin +++ b/core/crypto/sha3/sha3.odin @@ -1,5 +1,5 @@ /* -package sha3 implements the SHA3 hash algorithm family. +`SHA3` hash algorithm family. The SHAKE XOF can be found in crypto/shake. While discouraged if the pre-standardization Keccak algorithm is required, it can be found in @@ -12,7 +12,7 @@ package sha3 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. @@ -79,7 +79,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _sha3.final((^_sha3.Context)(ctx), hash, finalize_clone) diff --git a/core/crypto/shake/shake.odin b/core/crypto/shake/shake.odin index e20795b43..f959aaf5f 100644 --- a/core/crypto/shake/shake.odin +++ b/core/crypto/shake/shake.odin @@ -1,5 +1,5 @@ /* -package shake implements the SHAKE and cSHAKE XOF algorithm families. +`SHAKE` and `cSHAKE` XOF algorithm families. The SHA3 hash algorithm can be found in the crypto/sha3. @@ -11,7 +11,7 @@ package shake /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. diff --git a/core/crypto/siphash/siphash.odin b/core/crypto/siphash/siphash.odin index f9fe50cb0..fb1d42d49 100644 --- a/core/crypto/siphash/siphash.odin +++ b/core/crypto/siphash/siphash.odin @@ -1,5 +1,5 @@ /* -package siphash Implements the SipHash hashing algorithm. +`SipHash` hashing algorithm. Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4. @@ -10,11 +10,11 @@ See: package siphash /* - Copyright 2022 zhibog - Made available under the BSD-3 license. + Copyright 2022 zhibog + Made available under Odin's license. - List of contributors: - zhibog: Initial implementation. + List of contributors: + zhibog: Initial implementation. */ import "core:crypto" @@ -22,7 +22,7 @@ import "core:encoding/endian" import "core:math/bits" /* - High level API + High level API */ KEY_SIZE :: 16 @@ -215,7 +215,7 @@ verify_4_8 :: proc { } /* - Low level API + Low level API */ init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin index 6487c5e8c..6f1d788e0 100644 --- a/core/crypto/sm3/sm3.odin +++ b/core/crypto/sm3/sm3.odin @@ -1,5 +1,5 @@ /* -package sm3 implements the SM3 hash algorithm. +`SM3` hash algorithm. See: - [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]] @@ -8,15 +8,15 @@ package sm3 /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. */ +import "core:crypto" import "core:encoding/endian" import "core:math/bits" -import "core:mem" // DIGEST_SIZE is the SM3 digest size in bytes. DIGEST_SIZE :: 32 @@ -80,7 +80,7 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { ensure(ctx.is_initialized) @@ -126,7 +126,7 @@ reset :: proc(ctx: ^Context) { return } - mem.zero_explicit(ctx, size_of(ctx^)) + crypto.zero_explicit(ctx, size_of(ctx^)) } /* diff --git a/core/crypto/tuplehash/tuplehash.odin b/core/crypto/tuplehash/tuplehash.odin index e5caaa9c9..a45c1b120 100644 --- a/core/crypto/tuplehash/tuplehash.odin +++ b/core/crypto/tuplehash/tuplehash.odin @@ -1,5 +1,5 @@ /* -package tuplehash implements the TupleHash and TupleHashXOF algorithms. +`TupleHash` and `TupleHashXOF` algorithms. See: - [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]] @@ -31,7 +31,7 @@ write_element :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the digest to hash, and calls // reset on the Context. // -// Iff finalize_clone is set, final will work on a copy of the Context, +// If and only if (⟺) finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _sha3.final_cshake((^_sha3.Context)(ctx), hash, finalize_clone) diff --git a/core/crypto/x25519/x25519.odin b/core/crypto/x25519/x25519.odin index 6805c3ff8..6268a882d 100644 --- a/core/crypto/x25519/x25519.odin +++ b/core/crypto/x25519/x25519.odin @@ -1,22 +1,24 @@ /* -package x25519 implements the X25519 (aka curve25519) Elliptic-Curve -Diffie-Hellman key exchange protocol. +`X25519` (aka `curve25519`) Elliptic-Curve Diffie-Hellman key exchange protocol. See: - [[ https://www.rfc-editor.org/rfc/rfc7748 ]] */ package x25519 +import "core:crypto" +import ed "core:crypto/_edwards25519" import field "core:crypto/_fiat/field_curve25519" -import "core:mem" // SCALAR_SIZE is the size of a X25519 scalar (private key) in bytes. SCALAR_SIZE :: 32 // POINT_SIZE is the size of a X25519 point (public key/shared secret) in bytes. POINT_SIZE :: 32 -@(private, rodata) -_BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +when crypto.COMPACT_IMPLS == true { + @(private,rodata) + _BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +} @(private) _scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 { @@ -112,19 +114,44 @@ scalarmult :: proc(dst, scalar, point: []byte) { e[31] &= 127 e[31] |= 64 - p: [32]byte = --- - copy_slice(p[:], point) + p := (^[32]byte)(raw_data(point)) + d := (^[32]byte)(raw_data(dst)) + _scalarmult(d, &e, p) - d: [32]byte = --- - _scalarmult(&d, &e, &p) - copy_slice(dst, d[:]) - - mem.zero_explicit(&e, size_of(e)) - mem.zero_explicit(&d, size_of(d)) + crypto.zero_explicit(&e, size_of(e)) } // scalarmult_basepoint "multiplies" the provided scalar with the X25519 // base point and writes the resulting point to dst. scalarmult_basepoint :: proc(dst, scalar: []byte) { - scalarmult(dst, scalar, _BASE_POINT[:]) + when crypto.COMPACT_IMPLS == true { + scalarmult(dst, scalar, _BASE_POINT[:]) + } else { + ensure(len(scalar) == SCALAR_SIZE, "crypto/x25519: invalid scalar size") + ensure(len(dst) == POINT_SIZE, "crypto/x25519: invalid destination point size") + + sc: ed.Scalar = --- + ed.sc_set_bytes_rfc8032(&sc, scalar) + + ge: ed.Group_Element = --- + ed.ge_scalarmult_basepoint(&ge, &sc) + + // u = (y + z)/(z - y) + y_plus_z: field.Loose_Field_Element = --- + z_minus_y: field.Loose_Field_Element = --- + u: field.Tight_Field_Element = --- + + field.fe_add(&y_plus_z, &ge.y, &ge.z) + field.fe_sub(&z_minus_y, &ge.z, &ge.y) + field.fe_carry_inv(&u, &z_minus_y) + field.fe_carry_mul(&u, &y_plus_z, field.fe_relax_cast(&u)) + + dst_ := (^[32]byte)(raw_data(dst)) + field.fe_to_bytes(dst_, &u) + + field.fe_clear_vec([]^field.Loose_Field_Element{&y_plus_z, &z_minus_y}) + field.fe_clear(&u) + ed.sc_clear(&sc) + ed.ge_clear(&ge) + } } diff --git a/core/crypto/x448/x448.odin b/core/crypto/x448/x448.odin index 43c5d25e0..f2cbaadec 100644 --- a/core/crypto/x448/x448.odin +++ b/core/crypto/x448/x448.odin @@ -1,14 +1,13 @@ /* -package x448 implements the X448 (aka curve448) Elliptic-Curve -Diffie-Hellman key exchange protocol. +`X448` (aka `curve448`) Elliptic-Curve Diffie-Hellman key exchange protocol. See: - [[ https://www.rfc-editor.org/rfc/rfc7748 ]] */ package x448 +import "core:crypto" import field "core:crypto/_fiat/field_curve448" -import "core:mem" // SCALAR_SIZE is the size of a X448 scalar (private key) in bytes. SCALAR_SIZE :: 56 @@ -144,8 +143,8 @@ scalarmult :: proc(dst, scalar, point: []byte) { _scalarmult(&d, &e, &p) copy_slice(dst, d[:]) - mem.zero_explicit(&e, size_of(e)) - mem.zero_explicit(&d, size_of(d)) + crypto.zero_explicit(&e, size_of(e)) + crypto.zero_explicit(&d, size_of(d)) } // scalarmult_basepoint "multiplies" the provided scalar with the X448 diff --git a/core/debug/pe/pe.odin b/core/debug/pe/pe.odin index 587c01e8e..d04ed5098 100644 --- a/core/debug/pe/pe.odin +++ b/core/debug/pe/pe.odin @@ -1,3 +1,4 @@ +// A reader for the Windows `PE` executable format for debug purposes. package debug_pe PE_SIGNATURE_OFFSET_INDEX_POS :: 0x3c diff --git a/core/debug/trace/doc.odin b/core/debug/trace/doc.odin index e65548769..f9bb82fb5 100644 --- a/core/debug/trace/doc.odin +++ b/core/debug/trace/doc.odin @@ -1,5 +1,5 @@ /* -A debug stack trace library. Only works when debug symbols are enabled `-debug`. +Stack trace library. Only works when debug symbols are enabled using `-debug`. Example: import "base:runtime" @@ -19,7 +19,7 @@ Example: } runtime.print_byte('\n') - ctx := &trace_ctx + ctx := &global_trace_ctx if !trace.in_resolve(ctx) { buf: [64]trace.Frame runtime.print_string("Debug Trace:\n") @@ -48,4 +48,4 @@ Example: } */ -package debug_trace \ No newline at end of file +package debug_trace diff --git a/core/debug/trace/trace.odin b/core/debug/trace/trace.odin index 134609b05..6a9ba9dab 100644 --- a/core/debug/trace/trace.odin +++ b/core/debug/trace/trace.odin @@ -44,4 +44,34 @@ resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> (r @(require_results) in_resolve :: proc "contextless" (ctx: ^Context) -> bool { return intrinsics.atomic_load(&ctx.in_resolve) -} \ No newline at end of file +} + +_format_hex :: proc(buf: []byte, val: uintptr, allocator: runtime.Allocator) -> int { + _digits := "0123456789abcdef" + + shift := (size_of(uintptr) * 8) - 4 + offs := 0 + + for shift >= 0 { + d := (val >> uint(shift)) & 0xf + buf[offs] = _digits[d] + shift -= 4 + offs += 1 + } + + return offs +} + +_format_missing_proc :: proc(addr: uintptr, allocator: runtime.Allocator) -> string { + PREFIX :: "proc:0x" + buf, buf_err := make([]byte, len(PREFIX) + 16, allocator) + copy(buf, PREFIX) + + if buf_err != nil { + return "OUT_OF_MEMORY" + } + + offs := len(PREFIX) + offs += _format_hex(buf[offs:], uintptr(addr), allocator) + return string(buf[:offs]) +} diff --git a/core/debug/trace/trace_cpp.odin b/core/debug/trace/trace_cpp.odin index 8ef377cef..4828b207e 100644 --- a/core/debug/trace/trace_cpp.odin +++ b/core/debug/trace/trace_cpp.odin @@ -5,11 +5,10 @@ package debug_trace import "base:intrinsics" import "base:runtime" import "core:strings" -import "core:fmt" import "core:c" // NOTE: Relies on C++23 which adds and becomes ABI and that can be used -foreign import stdcpplibbacktrace "system:stdc++_libbacktrace" +foreign import stdcpplibbacktrace "system:stdc++exp" foreign import libdl "system:dl" @@ -164,7 +163,7 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> F } else if info: Dl_info; dladdr(rawptr(address), &info) != 0 && info.dli_sname != "" { frame.procedure = strings.clone_from_cstring(info.dli_sname, btc.allocator) } else { - frame.procedure = fmt.aprintf("(procedure: 0x%x)", allocator=btc.allocator) + frame.procedure = _format_missing_proc(address, btc.allocator) } frame.line = i32(line) return 0 @@ -192,4 +191,4 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> F ) return btc.frame -} \ No newline at end of file +} diff --git a/core/debug/trace/trace_windows.odin b/core/debug/trace/trace_windows.odin index 96507714c..b27b0ee29 100644 --- a/core/debug/trace/trace_windows.odin +++ b/core/debug/trace/trace_windows.odin @@ -6,7 +6,6 @@ import "base:intrinsics" import "base:runtime" import win32 "core:sys/windows" -import "core:fmt" _Context :: struct { hProcess: win32.HANDLE, @@ -54,9 +53,9 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> ( symbol.SizeOfStruct = size_of(symbol^) symbol.MaxNameLen = 255 if win32.SymFromAddrW(ctx.impl.hProcess, win32.DWORD64(frame), &{}, symbol) { - fl.procedure, _ = win32.wstring_to_utf8(&symbol.Name[0], -1, allocator) + fl.procedure, _ = win32.wstring_to_utf8(cstring16(&symbol.Name[0]), -1, allocator) } else { - fl.procedure = fmt.aprintf("(procedure: 0x%x)", frame, allocator=allocator) + fl.procedure = _format_missing_proc(uintptr(frame), allocator) } line: win32.IMAGEHLP_LINE64 diff --git a/core/dynlib/doc.odin b/core/dynlib/doc.odin index 487fcb715..f727a299c 100644 --- a/core/dynlib/doc.odin +++ b/core/dynlib/doc.odin @@ -1,5 +1,5 @@ /* -Package `core:dynlib` implements loading of shared libraries/DLLs and their symbols. +Cross-platform loading of shared libraries/DLLs and their symbols. The behaviour of dynamically loaded libraries is specific to the target platform of the program. For in depth detail on the underlying behaviour please refer to your target platform's documentation. diff --git a/core/dynlib/example/example.odin b/core/dynlib/example/example.odin index 78fb5a98c..84ee103e3 100644 --- a/core/dynlib/example/example.odin +++ b/core/dynlib/example/example.odin @@ -44,4 +44,4 @@ main :: proc() { fmt.println("84 - 13 =", sym.sub(84, 13)) fmt.println("hellope =", sym.hellope^) } -} +} \ No newline at end of file diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin index 05cd2cb3c..95372dac6 100644 --- a/core/dynlib/lib_windows.odin +++ b/core/dynlib/lib_windows.odin @@ -13,7 +13,7 @@ _LIBRARY_FILE_EXTENSION :: "dll" _load_library :: proc(path: string, global_symbols: bool, allocator: runtime.Allocator) -> (Library, bool) { // NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL wide_path := win32.utf8_to_wstring(path, allocator) - defer free(wide_path, allocator) + defer free(rawptr(wide_path), allocator) handle := cast(Library)win32.LoadLibraryW(wide_path) return handle, handle != nil } diff --git a/core/encoding/base32/base32.odin b/core/encoding/base32/base32.odin index 2267a872b..d272b32b8 100644 --- a/core/encoding/base32/base32.odin +++ b/core/encoding/base32/base32.odin @@ -1,19 +1,20 @@ -// Base32 encoding/decoding implementation as specified in RFC 4648. -// [[ More; https://www.rfc-editor.org/rfc/rfc4648.html ]] +/* +`Base32` encoding and decoding, as specified in [[ RFC 4648; https://www.rfc-editor.org/rfc/rfc4648.html ]]. + +A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`. + +If none is supplied it just uses the standard Base32 alphabet. +In case your specific version does not use padding, you may +truncate it from the encoded output. + +Error represents errors that can occur during base32 decoding operations. +As per RFC 4648: +- Section 3.3: Invalid character handling +- Section 3.2: Padding requirements +- Section 6: Base32 encoding specifics (including block size requirements) +*/ package encoding_base32 -// @note(zh): Encoding utility for Base32 -// A secondary param can be used to supply a custom alphabet to -// @link(encode) and a matching decoding table to @link(decode). -// If none is supplied it just uses the standard Base32 alphabet. -// In case your specific version does not use padding, you may -// truncate it from the encoded output. - -// Error represents errors that can occur during base32 decoding operations. -// As per RFC 4648: -// - Section 3.3: Invalid character handling -// - Section 3.2: Padding requirements -// - Section 6: Base32 encoding specifics (including block size requirements) Error :: enum { None, Invalid_Character, // Input contains characters outside the specified alphabet @@ -152,15 +153,15 @@ decode :: proc( padding_count += 1 } + // Verify no padding in the middle + for i := 0; i < data_len - padding_count; i += 1 { + if data[i] == byte(PADDING) { + return nil, .Malformed_Input + } + } + // Check for proper padding and length combinations if padding_count > 0 { - // Verify no padding in the middle - for i := 0; i < data_len - padding_count; i += 1 { - if data[i] == byte(PADDING) { - return nil, .Malformed_Input - } - } - content_len := data_len - padding_count mod8 := content_len % 8 required_padding: int diff --git a/core/encoding/base64/base64.odin b/core/encoding/base64/base64.odin index 1013a7d0b..e97652cd4 100644 --- a/core/encoding/base64/base64.odin +++ b/core/encoding/base64/base64.odin @@ -1,16 +1,19 @@ +/* +`Base64` encoding and decoding. + +A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`. + +If none is supplied it just uses the standard Base64 alphabet. +In case your specific version does not use padding, you may +truncate it from the encoded output. +*/ package encoding_base64 +import "base:intrinsics" +import "base:runtime" import "core:io" -import "core:mem" -import "core:strings" - -// @note(zh): Encoding utility for Base64 -// A secondary param can be used to supply a custom alphabet to -// @link(encode) and a matching decoding table to @link(decode). -// If none is supplied it just uses the standard Base64 alphabet. -// Incase your specific version does not use padding, you may -// truncate it from the encoded output. +@(rodata) ENC_TABLE := [64]byte { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -22,9 +25,23 @@ ENC_TABLE := [64]byte { '4', '5', '6', '7', '8', '9', '+', '/', } +// Encoding table for Base64url variant +@(rodata) +ENC_URL_TABLE := [64]byte { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '_', +} + PADDING :: '=' -DEC_TABLE := [128]int { +@(rodata) +DEC_TABLE := [256]i8 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -41,31 +58,119 @@ DEC_TABLE := [128]int { 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, } -encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> (encoded: string, err: mem.Allocator_Error) #optional_allocator_error { +// Decoding table for Base64url variant +@(rodata) +DEC_URL_TABLE := [256]i8 { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +} + +Error :: union #shared_nil { + runtime.Allocator_Error, + io.Error, + Decode_Error, +} + +Decode_Error :: enum { + None, + Invalid_Character, +} + +encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> (encoded: string, err: runtime.Allocator_Error) #optional_allocator_error { out_length := encoded_len(data) if out_length == 0 { return } - out := strings.builder_make(0, out_length, allocator) or_return - ioerr := encode_into(strings.to_stream(&out), data, ENC_TBL) + out := make([]byte, out_length, allocator) or_return + _, ioerr := encode_impl(out, data, ENC_TBL) + assert(ioerr == nil, "encode should not IO error") + assert(len(out) == out_length, "buffer resized, `encoded_len` was wrong") - assert(ioerr == nil, "string builder should not IO error") - assert(strings.builder_cap(out) == out_length, "buffer resized, `encoded_len` was wrong") + encoded = transmute(string)(out) - return strings.to_string(out), nil + return +} + +encode_into_buf :: proc(dst, data: []byte, ENC_TBL := ENC_TABLE) -> (encoded: []byte, err: Error) { + out_length := encoded_len(data) + if out_length == 0 { + return + } + + return encode_impl(dst, data, ENC_TBL) } encode_into :: proc(w: io.Writer, data: []byte, ENC_TBL := ENC_TABLE) -> io.Error { + _, err := encode_impl(w, data, ENC_TBL) + return err +} + +@(private) +encode_impl :: proc(dst: $T, data: []byte, ENC_TBL := ENC_TABLE) -> ([]byte, io.Error) where T == io.Writer || T == []byte { length := len(data) - if length == 0 { - return nil + when T == []byte { + out_length := encoded_len(data) + if len(dst) < out_length { + return nil, io.Error.Short_Buffer + } + buf := dst + } else { + if length == 0 { + return nil, nil + } + buf: [4]byte } c0, c1, c2, block: int - out: [4]byte for i := 0; i < length; i += 3 { #no_bounds_check { c0, c1, c2 = int(data[i]), -1, -1 @@ -74,15 +179,27 @@ encode_into :: proc(w: io.Writer, data: []byte, ENC_TBL := ENC_TABLE) -> io.Erro if i + 2 < length { c2 = int(data[i + 2]) } block = (c0 << 16) | (max(c1, 0) << 8) | max(c2, 0) - - out[0] = ENC_TBL[block >> 18 & 63] - out[1] = ENC_TBL[block >> 12 & 63] - out[2] = c1 == -1 ? PADDING : ENC_TBL[block >> 6 & 63] - out[3] = c2 == -1 ? PADDING : ENC_TBL[block & 63] + + buf[0] = ENC_TBL[block >> 18 & 63] + buf[1] = ENC_TBL[block >> 12 & 63] + buf[2] = c1 == -1 ? PADDING : ENC_TBL[block >> 6 & 63] + buf[3] = c2 == -1 ? PADDING : ENC_TBL[block & 63] + when T == []byte { + buf = buf[4:] + } + } + when T == io.Writer { + if _, err := io.write_full(dst, buf[:]); err != nil { + return nil, err + } } - io.write_full(w, out[:]) or_return } - return nil + + when T == io.Writer { + return nil, nil + } else { + return dst[:out_length], nil + } } encoded_len :: proc(data: []byte) -> int { @@ -94,65 +211,140 @@ encoded_len :: proc(data: []byte) -> int { return ((4 * length / 3) + 3) &~ 3 } -decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> (decoded: []byte, err: mem.Allocator_Error) #optional_allocator_error { +decode :: proc(data: string, DEC_TBL := DEC_TABLE, dst: []byte = nil, allocator := context.allocator) -> (decoded: []byte, err: Error) { out_length := decoded_len(data) + if out_length == 0 { + return nil, nil + } - out := strings.builder_make(0, out_length, allocator) or_return - ioerr := decode_into(strings.to_stream(&out), data, DEC_TBL) + buf: []byte + if buf, err = make([]byte, out_length, allocator); err != nil { + return + } - assert(ioerr == nil, "string builder should not IO error") - assert(strings.builder_cap(out) == out_length, "buffer resized, `decoded_len` was wrong") + decoded, err = decode_impl(buf, data, DEC_TBL) + if err != nil { + delete(buf, allocator) + } + assert(err != nil || len(decoded) == out_length, "buffer unexpectedly resized, `decoded_len` was wrong") - return out.buf[:], nil + return } -decode_into :: proc(w: io.Writer, data: string, DEC_TBL := DEC_TABLE) -> io.Error { +decode_into_buf :: proc(dst: []byte, data: string, DEC_TBL := DEC_TABLE) -> (decoded: []byte, err: Error) { + out_length := decoded_len(data) + if out_length == 0 { + return + } + + return decode_impl(dst, data, DEC_TBL) +} + +decode_into :: proc(w: io.Writer, data: string, DEC_TBL := DEC_TABLE) -> Error { + _, err := decode_impl(w, data, DEC_TBL) + return err +} + +@(private) +decode_impl :: proc(dst: $T, data: string, DEC_TBL := DEC_TABLE) -> ([]byte, Error) where T == io.Writer || T == []byte { length := decoded_len(data) - if length == 0 { - return nil + when T == []byte { + if len(dst) < length { + return nil, io.Error.Short_Buffer + } + off: int + } else { + if length == 0 { + return nil, nil + } + buf: [3]byte } c0, c1, c2, c3: int + d0, d1, d2, d3: i8 b0, b1, b2: int - buf: [3]byte i, j: int for ; j + 3 <= length; i, j = i + 4, j + 3 { #no_bounds_check { - c0 = DEC_TBL[data[i]] - c1 = DEC_TBL[data[i + 1]] - c2 = DEC_TBL[data[i + 2]] - c3 = DEC_TBL[data[i + 3]] + d0 = DEC_TBL[data[i]] + d1 = DEC_TBL[data[i + 1]] + d2 = DEC_TBL[data[i + 2]] + d3 = DEC_TBL[data[i + 3]] + + if intrinsics.unlikely((d0 | d1 | d2 | d3) & ~i8(0x3f) != 0) { + return nil, Decode_Error.Invalid_Character + } + + c0, c1, c2, c3 = int(d0), int(d1), int(d2), int(d3) b0 = (c0 << 2) | (c1 >> 4) b1 = (c1 << 4) | (c2 >> 2) b2 = (c2 << 6) | c3 - buf[0] = byte(b0) - buf[1] = byte(b1) - buf[2] = byte(b2) + when T == []byte { + dst[off+0] = byte(b0) + dst[off+1] = byte(b1) + dst[off+2] = byte(b2) + off += 3 + } else { + buf[0] = byte(b0) + buf[1] = byte(b1) + buf[2] = byte(b2) + } } - io.write_full(w, buf[:]) or_return + when T == io.Writer { + if _, err := io.write_full(dst, buf[:]); err != .None { + return nil, err + } + } } rest := length - j if rest > 0 { #no_bounds_check { - c0 = DEC_TBL[data[i]] - c1 = DEC_TBL[data[i + 1]] - c2 = DEC_TBL[data[i + 2]] + // Note: decoded_len handles removing padding. + d0 = DEC_TBL[data[i]] + d1 = DEC_TBL[data[i + 1]] + if d2 = 0; rest == 2 { + d2 = DEC_TBL[data[i + 2]] + } + + if intrinsics.unlikely((d0 | d1 | d2) & ~i8(0x3f) != 0) { + return nil, Decode_Error.Invalid_Character + } + + c0, c1, c2 = int(d0), int(d1), int(d2) b0 = (c0 << 2) | (c1 >> 4) b1 = (c1 << 4) | (c2 >> 2) + + when T == []byte { + switch rest { + case 2: + dst[off+1] = byte(b1) + fallthrough + case 1: + dst[off] = byte(b0) + } + } else { + buf[0] = byte(b0) + buf[1] = byte(b1) + } } - switch rest { - case 1: io.write_byte(w, byte(b0)) or_return - case 2: io.write_full(w, {byte(b0), byte(b1)}) or_return + when T == io.Writer { + if _, err := io.write_full(dst, buf[:rest]); err != .None { + return nil, err + } } } - return nil + when T == io.Writer { + return nil, nil + } else { + return dst[:length], nil + } } decoded_len :: proc(data: string) -> int { diff --git a/core/encoding/cbor/cbor.odin b/core/encoding/cbor/cbor.odin index 8eb829ed3..1fb7c34ab 100644 --- a/core/encoding/cbor/cbor.odin +++ b/core/encoding/cbor/cbor.odin @@ -385,17 +385,17 @@ to_diagnostic_format_writer :: proc(w: io.Writer, val: Value, padding := 0) -> i // which we want for the diagnostic format. case f16: buf: [64]byte - str := strconv.append_float(buf[:], f64(v), 'f', 2*size_of(f16), 8*size_of(f16)) + str := strconv.write_float(buf[:], f64(v), 'f', 2*size_of(f16), 8*size_of(f16)) if str[0] == '+' && str != "+Inf" { str = str[1:] } io.write_string(w, str) or_return case f32: buf: [128]byte - str := strconv.append_float(buf[:], f64(v), 'f', 2*size_of(f32), 8*size_of(f32)) + str := strconv.write_float(buf[:], f64(v), 'f', 2*size_of(f32), 8*size_of(f32)) if str[0] == '+' && str != "+Inf" { str = str[1:] } io.write_string(w, str) or_return case f64: buf: [256]byte - str := strconv.append_float(buf[:], f64(v), 'f', 2*size_of(f64), 8*size_of(f64)) + str := strconv.write_float(buf[:], f64(v), 'f', 2*size_of(f64), 8*size_of(f64)) if str[0] == '+' && str != "+Inf" { str = str[1:] } io.write_string(w, str) or_return diff --git a/core/encoding/cbor/doc.odin b/core/encoding/cbor/doc.odin index b3fa36130..370c5aaa9 100644 --- a/core/encoding/cbor/doc.odin +++ b/core/encoding/cbor/doc.odin @@ -1,5 +1,6 @@ /* -Package cbor encodes, decodes, marshals and unmarshals types from/into RCF 8949 compatible CBOR binary. +Encodes and decodes types from/into [[ RCF 8949; https://www.rfc-editor.org/rfc/rfc8949.html ]] compatible `CBOR` binary. + Also provided are conversion to and from JSON and the CBOR diagnostic format. **Allocations:** @@ -165,5 +166,4 @@ Output: "str": "Hello, World!" } */ -package encoding_cbor - +package encoding_cbor \ No newline at end of file diff --git a/core/encoding/cbor/marshal.odin b/core/encoding/cbor/marshal.odin index aca71deb2..b9333bf2b 100644 --- a/core/encoding/cbor/marshal.odin +++ b/core/encoding/cbor/marshal.odin @@ -285,6 +285,32 @@ _marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (er } return + + case runtime.Type_Info_Fixed_Capacity_Dynamic_Array: + array_data := uintptr(v.data) + array_len := (^int)(array_data + info.len_offset)^ + if info.elem.id == byte { + raw := runtime.Raw_Slice{v.data, array_len} + return err_conv(_encode_bytes(e, transmute([]byte)raw)) + } + + err_conv(_encode_u64(e, u64(array_len), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) + for i in 0.. (er case: panic("unknown bit_size size") } + case runtime.Type_Info_Matrix: + count := info.column_count * info.elem_stride + err_conv(_encode_u64(e, u64(count), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) + for i in 0..marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) + for i in 0.. t.count { return _unsupported(v, hdr) } - + slice := ([^]byte)(v.data)[:len(bytes)] - copy(slice, base64.decode(bytes) or_return) + copy(slice, b64_decode(bytes) or_return) return } @@ -378,3 +384,33 @@ tag_base64_marshal :: proc(_: ^Tag_Implementation, e: Encoder, v: any) -> Marsha err_conv(_encode_u64(e, u64(out_len), .Text)) or_return return base64.encode_into(e.writer, bytes) } + +@(private="file") +err_from_b64 :: proc(err: base64.Error) -> Unmarshal_Error { + switch e in err { + case runtime.Allocator_Error: + return e + case io.Error: + return e + case base64.Decode_Error: + return Decode_Data_Error.Bad_Tag_Value + } + + // Should NEVER happen, but fail gracefully. + return io.Error.Unknown +} + +@(private="file") +b64_decode :: proc(data: string) -> ([]byte, Unmarshal_Error) { + decoded, err := base64.decode(data) + if err == nil { + return decoded, nil + } + + return nil, err_from_b64(err) +} + +@(private="file") +b64_decode_into :: proc(w: io.Writer, data: string) -> Unmarshal_Error { + return err_from_b64(base64.decode_into(w, data)) +} diff --git a/core/encoding/cbor/unmarshal.odin b/core/encoding/cbor/unmarshal.odin index 24bbd8137..6925ce1db 100644 --- a/core/encoding/cbor/unmarshal.odin +++ b/core/encoding/cbor/unmarshal.odin @@ -335,6 +335,8 @@ _unmarshal_value :: proc(d: Decoder, v: any, hdr: Header, allocator := context.a _unmarshal_bytes :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, add: Add, allocator := context.allocator, loc := #caller_location) -> (err: Unmarshal_Error) { #partial switch t in ti.variant { case reflect.Type_Info_String: + assert(t.encoding == .UTF_8) + bytes := err_conv(_decode_bytes(d, add, allocator=allocator, loc=loc)) or_return if t.is_cstring { @@ -387,6 +389,23 @@ _unmarshal_bytes :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header n := copy(slice, bytes) assert(n == len(bytes)) return + + case reflect.Type_Info_Fixed_Capacity_Dynamic_Array: + elem_base := reflect.type_info_base(t.elem) + + if elem_base.id != byte { return _unsupported(v, hdr) } + + bytes := err_conv(_decode_bytes(d, add, allocator=context.temp_allocator)) or_return + defer delete(bytes, context.temp_allocator) + + if len(bytes) > t.capacity { return _unsupported(v, hdr) } + + // Copy into array type, delete original. + slice := ([^]byte)(v.data)[:len(bytes)] + n := copy(slice, bytes) + assert(n == len(bytes)) + (^int)(uintptr(v.data) + t.len_offset)^ = n + return } return _unsupported(v, hdr) @@ -551,6 +570,21 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header if out_of_space { return _unsupported(v, hdr) } return + case reflect.Type_Info_Fixed_Capacity_Dynamic_Array: + length, _ := err_conv(_decode_len_container(d, add)) or_return + if length > t.capacity { + return _unsupported(v, hdr) + } + + da := mem.Raw_Dynamic_Array{rawptr(v.data), 0, length, allocator } + + out_of_space := assign_array(d, &da, t.elem, length, growable=false) or_return + if out_of_space { return _unsupported(v, hdr) } + + (^int)(uintptr(v.data) + t.len_offset)^ = length + + return + case reflect.Type_Info_Complex: length, _ := err_conv(_decode_len_container(d, add)) or_return if length > 2 { @@ -591,6 +625,31 @@ _unmarshal_array :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header if out_of_space { return _unsupported(v, hdr) } return + case reflect.Type_Info_Matrix: + count := t.column_count * t.elem_stride + length, _ := err_conv(_decode_len_container(d, add)) or_return + if length > count { + return _unsupported(v, hdr) + } + + da := mem.Raw_Dynamic_Array{rawptr(v.data), 0, length, allocator } + + out_of_space := assign_array(d, &da, t.elem, length, growable=false) or_return + if out_of_space { return _unsupported(v, hdr) } + return + + case reflect.Type_Info_Simd_Vector: + length, _ := err_conv(_decode_len_container(d, add)) or_return + if length > t.count { + return _unsupported(v, hdr) + } + + da := mem.Raw_Dynamic_Array{rawptr(v.data), 0, length, allocator } + + out_of_space := assign_array(d, &da, t.elem, length, growable=false) or_return + if out_of_space { return _unsupported(v, hdr) } + return + case: return _unsupported(v, hdr) } } @@ -634,8 +693,7 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, unknown := length == -1 fields := reflect.struct_fields_zipped(ti.id) - idx := 0 - for ; idx < len(fields) && (unknown || idx < length); idx += 1 { + for idx := 0; unknown || idx < length; idx += 1 { // Decode key, keys can only be strings. key: string if keyv, kerr := decode_key(d, v, context.temp_allocator); unknown && kerr == .Break { @@ -683,16 +741,6 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, _unmarshal_value(d, fany, _decode_header(r) or_return) or_return } - // If there are fields left in the map that did not get decoded into the struct, decode and discard them. - if !unknown { - for _ in idx.. (record: []string, idx: int, err: Error, more: bool) { diff --git a/core/encoding/endian/doc.odin b/core/encoding/endian/doc.odin index 0b43e3097..7cc9da1b7 100644 --- a/core/encoding/endian/doc.odin +++ b/core/encoding/endian/doc.odin @@ -1,6 +1,5 @@ /* - Package endian implements a simple translation between bytes and numbers with - specific endian encodings. + A simple translation between bytes and numbers with specific endian encodings. Example: buf: [100]u8 diff --git a/core/encoding/entity/entity.odin b/core/encoding/entity/entity.odin index cb8fa8611..a756bdf39 100644 --- a/core/encoding/entity/entity.odin +++ b/core/encoding/entity/entity.odin @@ -1,13 +1,5 @@ /* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. - - List of contributors: - Jeroen van Rijn: Initial implementation. -*/ - -/* - A unicode entity encoder/decoder. + Encode and decode `rune`s to/from a Unicode `&entity;`. This code has several procedures to map unicode runes to/from different textual encodings. - SGML/XML/HTML entity @@ -21,6 +13,15 @@ */ package encoding_unicode_entity +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. +*/ + +import "base:runtime" import "core:unicode/utf8" import "core:unicode" import "core:strings" @@ -141,8 +142,10 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator := write_string(&builder, entity) } else { if .No_Entity_Decode not_in options { - if decoded, ok := xml_decode_entity(entity); ok { - write_rune(&builder, decoded) + if decoded, count, ok := xml_decode_entity(entity); ok { + for i in 0.. (err: Error) { } } -xml_decode_entity :: proc(entity: string) -> (decoded: rune, ok: bool) { +xml_decode_entity :: proc(entity: string) -> (decoded: [2]rune, rune_count: int, ok: bool) { entity := entity - if len(entity) == 0 { return -1, false } + if len(entity) == 0 { return } - switch entity[0] { - case '#': + if entity[0] == '#' { base := 10 val := 0 entity = entity[1:] - if len(entity) == 0 { return -1, false } + if len(entity) == 0 { return } if entity[0] == 'x' || entity[0] == 'X' { base = 16 @@ -237,30 +239,275 @@ xml_decode_entity :: proc(entity: string) -> (decoded: rune, ok: bool) { val += int(r - '0') case 'a'..='f': - if base == 10 { return -1, false } + if base == 10 { return } val *= base val += int(r - 'a' + 10) case 'A'..='F': - if base == 10 { return -1, false } + if base == 10 { return } val *= base val += int(r - 'A' + 10) case: - return -1, false + return } - if val > MAX_RUNE_CODEPOINT { return -1, false } + if val > MAX_RUNE_CODEPOINT { return } entity = entity[1:] } - return rune(val), true - - case: - // Named entity. - return named_xml_entity_to_rune(entity) + return rune(val), 1, true } + // Named entity. + return named_xml_entity_to_rune(entity) } + +// escape_html escapes special characters like '&' to become '&'. +// It escapes only 5 different characters: & ' < > and " +@(require_results) +escape_html :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool) { + /* + & -> & + ' -> ' // ' is shorter than ' (NOTE: ' was not available until HTML 5) + < -> < + > -> > + " -> " // " is shorter than " + */ + + b := transmute([]byte)s + + extra_bytes_needed := 0 + + for c in b { + switch c { + case '&': extra_bytes_needed += 4 + case '\'': extra_bytes_needed += 4 + case '<': extra_bytes_needed += 3 + case '>': extra_bytes_needed += 3 + case '"': extra_bytes_needed += 4 + } + } + + if extra_bytes_needed == 0 { + return s, false + } + + t, err := make([]byte, len(s) + extra_bytes_needed, allocator, loc) + if err != nil { + return + } + was_allocation = true + + w := 0 + for c in b { + x := "" + switch c { + case '&': x = "&" + case '\'': x = "'" + case '<': x = "<" + case '>': x = ">" + case '"': x = """ + } + if x != "" { + copy(t[w:], x) + w += len(x) + } else { + t[w] = c + w += 1 + } + } + output = string(t[0:w]) + return +} + + +@(require_results) +unescape_html :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool, err: runtime.Allocator_Error) { + @(require_results) + do_append :: proc(s: string, amp_idx: int, buf: ^[dynamic]byte) -> (n: int) { + s, amp_idx := s, amp_idx + + n += len(s[:amp_idx]) + if buf != nil { append(buf, s[:amp_idx]) } + s = s[amp_idx:] + for len(s) > 0 { + b, w, j := unescape_entity(s) + n += w + if buf != nil { append(buf, ..b[:w]) } + + s = s[j:] + + amp_idx = strings.index_byte(s, '&') + if amp_idx < 0 { + n += len(s) + if buf != nil { append(buf, s) } + break + } + n += amp_idx + if buf != nil { append(buf, s[:amp_idx]) } + s = s[amp_idx:] + } + + return + } + + s := s + amp_idx := strings.index_byte(s, '&') + if amp_idx < 0 { + return s, false, nil + } + + // NOTE(bill): this does a two pass in order to minimize the allocations required + bytes_required := do_append(s, amp_idx, nil) + + buf := make([dynamic]byte, 0, bytes_required, allocator, loc) or_return + was_allocation = true + + _ = do_append(s, amp_idx, &buf) + + assert(len(buf) == cap(buf)) + output = string(buf[:]) + + return +} + +// Returns an unescaped string of an encoded XML/HTML entity. +@(require_results) +unescape_entity :: proc(s: string) -> (b: [8]byte, w: int, j: int) { + s := s + if len(s) < 2 { + return + } + if s[0] != '&' { + return + } + j = 1 + + if s[j] == '#' { // scan numbers + j += 1 + if len(s) <= 3 { // remove `&#.` + return + } + c := s[j] + hex := false + if c == 'x' || c == 'X' { + hex = true + j += 1 + } + + x := rune(0) + scan_number: for j < len(s) { + c = s[j] + j += 1 + if hex { + switch c { + case '0'..='9': x = 16*x + rune(c) - '0'; continue scan_number + case 'a'..='f': x = 16*x + rune(c) - 'a' + 10; continue scan_number + case 'A'..='F': x = 16*x + rune(c) - 'A' + 10; continue scan_number + } + } else { + switch c { + case '0'..='9': x = 10*x + rune(c) - '0'; continue scan_number + } + } + + // Keep the ';' to check for cases which require it and cases which might not + if c != ';' { + j -= 1 + } + break scan_number + } + + + if j <= 3 { // no replacement characters found + return + } + + @(static, rodata) + windows_1252_replacement_table := [0xa0 - 0x80]rune{ // Windows-1252 -> UTF-8 + '\u20ac', '\u0081', '\u201a', '\u0192', + '\u201e', '\u2026', '\u2020', '\u2021', + '\u02c6', '\u2030', '\u0160', '\u2039', + '\u0152', '\u008d', '\u017d', '\u008f', + '\u0090', '\u2018', '\u2019', '\u201c', + '\u201d', '\u2022', '\u2013', '\u2014', + '\u02dc', '\u2122', '\u0161', '\u203a', + '\u0153', '\u009d', '\u017e', '\u0178', + } + + switch x { + case 0x80..<0xa0: + x = windows_1252_replacement_table[x-0x80] + case 0, 0xd800..=0xdfff: + x = utf8.RUNE_ERROR + case: + if x > 0x10ffff { + x = utf8.RUNE_ERROR + } + + } + + b1, w1 := utf8.encode_rune(x) + w += copy(b[:], b1[:w1]) + return + } + + // Lookup by entity names + + scan_ident: for j < len(s) { // scan over letters and digits + c := s[j] + j += 1 + + switch c { + case 'a'..='z', 'A'..='Z', '0'..='9': + continue scan_ident + } + // Keep the ';' to check for cases which require it and cases which might not + if c != ';' { + j -= 1 + } + break scan_ident + } + + entity_name := s[1:j] + if len(entity_name) == 0 { + return + } + + if entity_name[len(entity_name)-1] == ';' { + entity_name = entity_name[:len(entity_name)-1] + } + + if r2, _, ok := named_xml_entity_to_rune(entity_name); ok { + b1, w1 := utf8.encode_rune(r2[0]) + w += copy(b[w:], b1[:w1]) + if r2[1] != 0 { + b2, w2 := utf8.encode_rune(r2[1]) + w += copy(b[w:], b2[:w2]) + } + return + } + + // The longest entities that do not end with a semicolon are <=6 bytes long + LONGEST_ENTITY_WITHOUT_SEMICOLON :: 6 + + n := min(len(entity_name)-1, LONGEST_ENTITY_WITHOUT_SEMICOLON) + for i := n; i > 1; i -= 1 { + if r2, _, ok := named_xml_entity_to_rune(entity_name[:i]); ok { + b1, w1 := utf8.encode_rune(r2[0]) + w += copy(b[w:], b1[:w1]) + if r2[1] != 0 { + b2, w2 := utf8.encode_rune(r2[1]) + w += copy(b[w:], b2[:w2]) + } + return + } + } + + return +} + + // Private XML helper to extract `&;` entity. @(private="file") _extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) { diff --git a/core/encoding/entity/generated.odin b/core/encoding/entity/generated.odin index 52027ae03..fda8e5c2a 100644 --- a/core/encoding/entity/generated.odin +++ b/core/encoding/entity/generated.odin @@ -6,14 +6,14 @@ package encoding_unicode_entity /* This file is generated from "https://github.com/w3c/xml-entities/blob/gh-pages/unicode.xml". - + UPDATE: - - Ensure the XML file was downloaded using "tests\core\download_assets.py". + - Ensure the XML file was downloaded using "tests\core\download_assets.py", given the path to the "tests\assets" directory. - Run "core/unicode/tools/generate_entity_table.odin" Odin unicode generated tables: https://github.com/odin-lang/Odin/tree/master/core/encoding/entity - Copyright David Carlisle 1999-2023 + Copyright David Carlisle 1999-2025 Use and distribution of this code are permitted under the terms of the W3C Software Notice and License. @@ -43,5047 +43,5047 @@ XML_NAME_TO_RUNE_MAX_LENGTH :: 31 entity_name - a string, like "copy" that describes a user-encoded Unicode entity as used in XML. Returns: - "decoded" - The decoded rune if found by name, or -1 otherwise. - "ok" - true if found, false if not. + "decoded" - The decoded runes if found by name, or all zero otherwise. + "rune_count" - The number of decoded runes + "ok" - true if found, false if not. IMPORTANT: XML processors (including browsers) treat these names as case-sensitive. So do we. */ -named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) { +named_xml_entity_to_rune :: proc(name: string) -> (decoded: [2]rune, rune_count: int, ok: bool) { /* Early out if the name is too short or too long. min as a precaution in case the generated table has a bogus value. */ if len(name) < min(1, XML_NAME_TO_RUNE_MIN_LENGTH) || len(name) > XML_NAME_TO_RUNE_MAX_LENGTH { - return -1, false + return } switch rune(name[0]) { - case 'A': switch name { case "AElig": // LATIN CAPITAL LETTER AE - return rune(0xc6), true + return {'Æ', 0}, 1, true case "AMP": // AMPERSAND - return rune(0x26), true + return {'&', 0}, 1, true case "Aacgr": // GREEK CAPITAL LETTER ALPHA WITH TONOS - return rune(0x0386), true + return {'\u0386', 0}, 1, true case "Aacute": // LATIN CAPITAL LETTER A WITH ACUTE - return rune(0xc1), true + return {'Á', 0}, 1, true case "Abreve": // LATIN CAPITAL LETTER A WITH BREVE - return rune(0x0102), true + return {'\u0102', 0}, 1, true case "Acirc": // LATIN CAPITAL LETTER A WITH CIRCUMFLEX - return rune(0xc2), true + return {'Â', 0}, 1, true case "Acy": // CYRILLIC CAPITAL LETTER A - return rune(0x0410), true + return {'\u0410', 0}, 1, true case "Afr": // MATHEMATICAL FRAKTUR CAPITAL A - return rune(0x01d504), true + return {'\U0001d504', 0}, 1, true case "Agr": // GREEK CAPITAL LETTER ALPHA - return rune(0x0391), true + return {'\u0391', 0}, 1, true case "Agrave": // LATIN CAPITAL LETTER A WITH GRAVE - return rune(0xc0), true + return {'À', 0}, 1, true case "Alpha": // GREEK CAPITAL LETTER ALPHA - return rune(0x0391), true + return {'\u0391', 0}, 1, true case "Amacr": // LATIN CAPITAL LETTER A WITH MACRON - return rune(0x0100), true + return {'\u0100', 0}, 1, true case "And": // DOUBLE LOGICAL AND - return rune(0x2a53), true + return {'\u2a53', 0}, 1, true case "Aogon": // LATIN CAPITAL LETTER A WITH OGONEK - return rune(0x0104), true + return {'\u0104', 0}, 1, true case "Aopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL A - return rune(0x01d538), true + return {'\U0001d538', 0}, 1, true case "ApplyFunction": // FUNCTION APPLICATION - return rune(0x2061), true + return {'\u2061', 0}, 1, true case "Aring": // LATIN CAPITAL LETTER A WITH RING ABOVE - return rune(0xc5), true + return {'Å', 0}, 1, true case "Ascr": // MATHEMATICAL SCRIPT CAPITAL A - return rune(0x01d49c), true + return {'\U0001d49c', 0}, 1, true case "Assign": // COLON EQUALS - return rune(0x2254), true + return {'\u2254', 0}, 1, true case "Ast": // TWO ASTERISKS ALIGNED VERTICALLY - return rune(0x2051), true + return {'\u2051', 0}, 1, true case "Atilde": // LATIN CAPITAL LETTER A WITH TILDE - return rune(0xc3), true + return {'Ã', 0}, 1, true case "Auml": // LATIN CAPITAL LETTER A WITH DIAERESIS - return rune(0xc4), true + return {'Ä', 0}, 1, true } case 'B': switch name { case "Backslash": // SET MINUS - return rune(0x2216), true + return {'\u2216', 0}, 1, true case "Barint": // INTEGRAL WITH DOUBLE STROKE - return rune(0x2a0e), true + return {'\u2a0e', 0}, 1, true case "Barv": // SHORT DOWN TACK WITH OVERBAR - return rune(0x2ae7), true + return {'\u2ae7', 0}, 1, true case "Barwed": // PERSPECTIVE - return rune(0x2306), true + return {'\u2306', 0}, 1, true case "Barwedl": // LOGICAL AND WITH DOUBLE OVERBAR - return rune(0x2a5e), true + return {'\u2a5e', 0}, 1, true case "Bcy": // CYRILLIC CAPITAL LETTER BE - return rune(0x0411), true + return {'\u0411', 0}, 1, true case "Because": // BECAUSE - return rune(0x2235), true + return {'\u2235', 0}, 1, true case "Bernoullis": // SCRIPT CAPITAL B - return rune(0x212c), true + return {'\u212c', 0}, 1, true case "Beta": // GREEK CAPITAL LETTER BETA - return rune(0x0392), true + return {'\u0392', 0}, 1, true case "Bfr": // MATHEMATICAL FRAKTUR CAPITAL B - return rune(0x01d505), true + return {'\U0001d505', 0}, 1, true case "Bgr": // GREEK CAPITAL LETTER BETA - return rune(0x0392), true + return {'\u0392', 0}, 1, true case "Bopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL B - return rune(0x01d539), true + return {'\U0001d539', 0}, 1, true case "Breve": // BREVE - return rune(0x02d8), true + return {'\u02d8', 0}, 1, true case "Bscr": // SCRIPT CAPITAL B - return rune(0x212c), true + return {'\u212c', 0}, 1, true case "Bumpeq": // GEOMETRICALLY EQUIVALENT TO - return rune(0x224e), true + return {'\u224e', 0}, 1, true case "Bvert": // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL - return rune(0x2506), true + return {'\u2506', 0}, 1, true } case 'C': switch name { case "CHcy": // CYRILLIC CAPITAL LETTER CHE - return rune(0x0427), true + return {'\u0427', 0}, 1, true case "COPY": // COPYRIGHT SIGN - return rune(0xa9), true + return {'©', 0}, 1, true case "Cacute": // LATIN CAPITAL LETTER C WITH ACUTE - return rune(0x0106), true + return {'\u0106', 0}, 1, true case "Cap": // DOUBLE INTERSECTION - return rune(0x22d2), true + return {'\u22d2', 0}, 1, true case "CapitalDifferentialD": // DOUBLE-STRUCK ITALIC CAPITAL D - return rune(0x2145), true + return {'\u2145', 0}, 1, true case "Cayleys": // BLACK-LETTER CAPITAL C - return rune(0x212d), true + return {'\u212d', 0}, 1, true case "Ccaron": // LATIN CAPITAL LETTER C WITH CARON - return rune(0x010c), true + return {'\u010c', 0}, 1, true case "Ccedil": // LATIN CAPITAL LETTER C WITH CEDILLA - return rune(0xc7), true + return {'Ç', 0}, 1, true case "Ccirc": // LATIN CAPITAL LETTER C WITH CIRCUMFLEX - return rune(0x0108), true + return {'\u0108', 0}, 1, true case "Cconint": // VOLUME INTEGRAL - return rune(0x2230), true + return {'\u2230', 0}, 1, true case "Cdot": // LATIN CAPITAL LETTER C WITH DOT ABOVE - return rune(0x010a), true + return {'\u010a', 0}, 1, true case "Cedilla": // CEDILLA - return rune(0xb8), true + return {'¸', 0}, 1, true case "CenterDot": // MIDDLE DOT - return rune(0xb7), true + return {'·', 0}, 1, true case "Cfr": // BLACK-LETTER CAPITAL C - return rune(0x212d), true + return {'\u212d', 0}, 1, true case "Chi": // GREEK CAPITAL LETTER CHI - return rune(0x03a7), true + return {'\u03a7', 0}, 1, true case "CircleDot": // CIRCLED DOT OPERATOR - return rune(0x2299), true + return {'\u2299', 0}, 1, true case "CircleMinus": // CIRCLED MINUS - return rune(0x2296), true + return {'\u2296', 0}, 1, true case "CirclePlus": // CIRCLED PLUS - return rune(0x2295), true + return {'\u2295', 0}, 1, true case "CircleTimes": // CIRCLED TIMES - return rune(0x2297), true + return {'\u2297', 0}, 1, true case "ClockwiseContourIntegral": // CLOCKWISE CONTOUR INTEGRAL - return rune(0x2232), true + return {'\u2232', 0}, 1, true case "CloseCurlyDoubleQuote": // RIGHT DOUBLE QUOTATION MARK - return rune(0x201d), true + return {'\u201d', 0}, 1, true case "CloseCurlyQuote": // RIGHT SINGLE QUOTATION MARK - return rune(0x2019), true + return {'\u2019', 0}, 1, true case "Colon": // PROPORTION - return rune(0x2237), true + return {'\u2237', 0}, 1, true case "Colone": // DOUBLE COLON EQUAL - return rune(0x2a74), true + return {'\u2a74', 0}, 1, true case "Congruent": // IDENTICAL TO - return rune(0x2261), true + return {'\u2261', 0}, 1, true case "Conint": // SURFACE INTEGRAL - return rune(0x222f), true + return {'\u222f', 0}, 1, true case "ContourIntegral": // CONTOUR INTEGRAL - return rune(0x222e), true + return {'\u222e', 0}, 1, true case "Copf": // DOUBLE-STRUCK CAPITAL C - return rune(0x2102), true + return {'\u2102', 0}, 1, true case "Coproduct": // N-ARY COPRODUCT - return rune(0x2210), true + return {'\u2210', 0}, 1, true case "CounterClockwiseContourIntegral": // ANTICLOCKWISE CONTOUR INTEGRAL - return rune(0x2233), true + return {'\u2233', 0}, 1, true case "Cross": // VECTOR OR CROSS PRODUCT - return rune(0x2a2f), true + return {'\u2a2f', 0}, 1, true case "Cscr": // MATHEMATICAL SCRIPT CAPITAL C - return rune(0x01d49e), true + return {'\U0001d49e', 0}, 1, true case "Cup": // DOUBLE UNION - return rune(0x22d3), true + return {'\u22d3', 0}, 1, true case "CupCap": // EQUIVALENT TO - return rune(0x224d), true + return {'\u224d', 0}, 1, true } case 'D': switch name { case "DD": // DOUBLE-STRUCK ITALIC CAPITAL D - return rune(0x2145), true + return {'\u2145', 0}, 1, true case "DDotrahd": // RIGHTWARDS ARROW WITH DOTTED STEM - return rune(0x2911), true + return {'\u2911', 0}, 1, true case "DJcy": // CYRILLIC CAPITAL LETTER DJE - return rune(0x0402), true + return {'\u0402', 0}, 1, true case "DScy": // CYRILLIC CAPITAL LETTER DZE - return rune(0x0405), true + return {'\u0405', 0}, 1, true case "DZcy": // CYRILLIC CAPITAL LETTER DZHE - return rune(0x040f), true + return {'\u040f', 0}, 1, true case "Dagger": // DOUBLE DAGGER - return rune(0x2021), true + return {'\u2021', 0}, 1, true case "Darr": // DOWNWARDS TWO HEADED ARROW - return rune(0x21a1), true + return {'\u21a1', 0}, 1, true case "Dashv": // VERTICAL BAR DOUBLE LEFT TURNSTILE - return rune(0x2ae4), true + return {'\u2ae4', 0}, 1, true case "Dcaron": // LATIN CAPITAL LETTER D WITH CARON - return rune(0x010e), true + return {'\u010e', 0}, 1, true case "Dcy": // CYRILLIC CAPITAL LETTER DE - return rune(0x0414), true + return {'\u0414', 0}, 1, true case "Del": // NABLA - return rune(0x2207), true + return {'\u2207', 0}, 1, true case "Delta": // GREEK CAPITAL LETTER DELTA - return rune(0x0394), true + return {'\u0394', 0}, 1, true case "Dfr": // MATHEMATICAL FRAKTUR CAPITAL D - return rune(0x01d507), true + return {'\U0001d507', 0}, 1, true case "Dgr": // GREEK CAPITAL LETTER DELTA - return rune(0x0394), true + return {'\u0394', 0}, 1, true case "DiacriticalAcute": // ACUTE ACCENT - return rune(0xb4), true + return {'´', 0}, 1, true case "DiacriticalDot": // DOT ABOVE - return rune(0x02d9), true + return {'\u02d9', 0}, 1, true case "DiacriticalDoubleAcute": // DOUBLE ACUTE ACCENT - return rune(0x02dd), true + return {'\u02dd', 0}, 1, true case "DiacriticalGrave": // GRAVE ACCENT - return rune(0x60), true + return {'`', 0}, 1, true case "DiacriticalTilde": // SMALL TILDE - return rune(0x02dc), true + return {'\u02dc', 0}, 1, true case "Diamond": // DIAMOND OPERATOR - return rune(0x22c4), true + return {'\u22c4', 0}, 1, true case "DifferentialD": // DOUBLE-STRUCK ITALIC SMALL D - return rune(0x2146), true + return {'\u2146', 0}, 1, true case "Dopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL D - return rune(0x01d53b), true + return {'\U0001d53b', 0}, 1, true case "Dot": // DIAERESIS - return rune(0xa8), true + return {'¨', 0}, 1, true case "DotDot": // COMBINING FOUR DOTS ABOVE - return rune(0x20dc), true + return {'\u20dc', 0}, 1, true case "DotEqual": // APPROACHES THE LIMIT - return rune(0x2250), true + return {'\u2250', 0}, 1, true case "DoubleContourIntegral": // SURFACE INTEGRAL - return rune(0x222f), true + return {'\u222f', 0}, 1, true case "DoubleDot": // DIAERESIS - return rune(0xa8), true + return {'¨', 0}, 1, true case "DoubleDownArrow": // DOWNWARDS DOUBLE ARROW - return rune(0x21d3), true + return {'\u21d3', 0}, 1, true case "DoubleLeftArrow": // LEFTWARDS DOUBLE ARROW - return rune(0x21d0), true + return {'\u21d0', 0}, 1, true case "DoubleLeftRightArrow": // LEFT RIGHT DOUBLE ARROW - return rune(0x21d4), true + return {'\u21d4', 0}, 1, true case "DoubleLeftTee": // VERTICAL BAR DOUBLE LEFT TURNSTILE - return rune(0x2ae4), true + return {'\u2ae4', 0}, 1, true case "DoubleLongLeftArrow": // LONG LEFTWARDS DOUBLE ARROW - return rune(0x27f8), true + return {'\u27f8', 0}, 1, true case "DoubleLongLeftRightArrow": // LONG LEFT RIGHT DOUBLE ARROW - return rune(0x27fa), true + return {'\u27fa', 0}, 1, true case "DoubleLongRightArrow": // LONG RIGHTWARDS DOUBLE ARROW - return rune(0x27f9), true + return {'\u27f9', 0}, 1, true case "DoubleRightArrow": // RIGHTWARDS DOUBLE ARROW - return rune(0x21d2), true + return {'\u21d2', 0}, 1, true case "DoubleRightTee": // TRUE - return rune(0x22a8), true + return {'\u22a8', 0}, 1, true case "DoubleUpArrow": // UPWARDS DOUBLE ARROW - return rune(0x21d1), true + return {'\u21d1', 0}, 1, true case "DoubleUpDownArrow": // UP DOWN DOUBLE ARROW - return rune(0x21d5), true + return {'\u21d5', 0}, 1, true case "DoubleVerticalBar": // PARALLEL TO - return rune(0x2225), true + return {'\u2225', 0}, 1, true case "DownArrow": // DOWNWARDS ARROW - return rune(0x2193), true + return {'\u2193', 0}, 1, true case "DownArrowBar": // DOWNWARDS ARROW TO BAR - return rune(0x2913), true + return {'\u2913', 0}, 1, true case "DownArrowUpArrow": // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW - return rune(0x21f5), true + return {'\u21f5', 0}, 1, true case "DownBreve": // COMBINING INVERTED BREVE - return rune(0x0311), true + return {'\u0311', 0}, 1, true case "DownLeftRightVector": // LEFT BARB DOWN RIGHT BARB DOWN HARPOON - return rune(0x2950), true + return {'\u2950', 0}, 1, true case "DownLeftTeeVector": // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR - return rune(0x295e), true + return {'\u295e', 0}, 1, true case "DownLeftVector": // LEFTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21bd), true + return {'\u21bd', 0}, 1, true case "DownLeftVectorBar": // LEFTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2956), true + return {'\u2956', 0}, 1, true case "DownRightTeeVector": // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR - return rune(0x295f), true + return {'\u295f', 0}, 1, true case "DownRightVector": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21c1), true + return {'\u21c1', 0}, 1, true case "DownRightVectorBar": // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2957), true + return {'\u2957', 0}, 1, true case "DownTee": // DOWN TACK - return rune(0x22a4), true + return {'\u22a4', 0}, 1, true case "DownTeeArrow": // DOWNWARDS ARROW FROM BAR - return rune(0x21a7), true + return {'\u21a7', 0}, 1, true case "Downarrow": // DOWNWARDS DOUBLE ARROW - return rune(0x21d3), true + return {'\u21d3', 0}, 1, true case "Dscr": // MATHEMATICAL SCRIPT CAPITAL D - return rune(0x01d49f), true + return {'\U0001d49f', 0}, 1, true case "Dstrok": // LATIN CAPITAL LETTER D WITH STROKE - return rune(0x0110), true + return {'\u0110', 0}, 1, true } case 'E': switch name { case "EEacgr": // GREEK CAPITAL LETTER ETA WITH TONOS - return rune(0x0389), true + return {'\u0389', 0}, 1, true case "EEgr": // GREEK CAPITAL LETTER ETA - return rune(0x0397), true + return {'\u0397', 0}, 1, true case "ENG": // LATIN CAPITAL LETTER ENG - return rune(0x014a), true + return {'\u014a', 0}, 1, true case "ETH": // LATIN CAPITAL LETTER ETH - return rune(0xd0), true + return {'Ð', 0}, 1, true case "Eacgr": // GREEK CAPITAL LETTER EPSILON WITH TONOS - return rune(0x0388), true + return {'\u0388', 0}, 1, true case "Eacute": // LATIN CAPITAL LETTER E WITH ACUTE - return rune(0xc9), true + return {'É', 0}, 1, true case "Ecaron": // LATIN CAPITAL LETTER E WITH CARON - return rune(0x011a), true + return {'\u011a', 0}, 1, true case "Ecirc": // LATIN CAPITAL LETTER E WITH CIRCUMFLEX - return rune(0xca), true + return {'Ê', 0}, 1, true case "Ecy": // CYRILLIC CAPITAL LETTER E - return rune(0x042d), true + return {'\u042d', 0}, 1, true case "Edot": // LATIN CAPITAL LETTER E WITH DOT ABOVE - return rune(0x0116), true + return {'\u0116', 0}, 1, true case "Efr": // MATHEMATICAL FRAKTUR CAPITAL E - return rune(0x01d508), true + return {'\U0001d508', 0}, 1, true case "Egr": // GREEK CAPITAL LETTER EPSILON - return rune(0x0395), true + return {'\u0395', 0}, 1, true case "Egrave": // LATIN CAPITAL LETTER E WITH GRAVE - return rune(0xc8), true + return {'È', 0}, 1, true case "Element": // ELEMENT OF - return rune(0x2208), true + return {'\u2208', 0}, 1, true case "Emacr": // LATIN CAPITAL LETTER E WITH MACRON - return rune(0x0112), true + return {'\u0112', 0}, 1, true case "EmptySmallSquare": // WHITE MEDIUM SQUARE - return rune(0x25fb), true + return {'\u25fb', 0}, 1, true case "EmptyVerySmallSquare": // WHITE SMALL SQUARE - return rune(0x25ab), true + return {'\u25ab', 0}, 1, true case "Eogon": // LATIN CAPITAL LETTER E WITH OGONEK - return rune(0x0118), true + return {'\u0118', 0}, 1, true case "Eopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL E - return rune(0x01d53c), true + return {'\U0001d53c', 0}, 1, true case "Epsilon": // GREEK CAPITAL LETTER EPSILON - return rune(0x0395), true + return {'\u0395', 0}, 1, true case "Equal": // TWO CONSECUTIVE EQUALS SIGNS - return rune(0x2a75), true + return {'\u2a75', 0}, 1, true case "EqualTilde": // MINUS TILDE - return rune(0x2242), true + return {'\u2242', 0}, 1, true case "Equilibrium": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true + return {'\u21cc', 0}, 1, true case "Escr": // SCRIPT CAPITAL E - return rune(0x2130), true + return {'\u2130', 0}, 1, true case "Esim": // EQUALS SIGN ABOVE TILDE OPERATOR - return rune(0x2a73), true + return {'\u2a73', 0}, 1, true case "Eta": // GREEK CAPITAL LETTER ETA - return rune(0x0397), true + return {'\u0397', 0}, 1, true case "Euml": // LATIN CAPITAL LETTER E WITH DIAERESIS - return rune(0xcb), true + return {'Ë', 0}, 1, true case "Exists": // THERE EXISTS - return rune(0x2203), true + return {'\u2203', 0}, 1, true case "ExponentialE": // DOUBLE-STRUCK ITALIC SMALL E - return rune(0x2147), true + return {'\u2147', 0}, 1, true } case 'F': switch name { case "Fcy": // CYRILLIC CAPITAL LETTER EF - return rune(0x0424), true + return {'\u0424', 0}, 1, true case "Ffr": // MATHEMATICAL FRAKTUR CAPITAL F - return rune(0x01d509), true + return {'\U0001d509', 0}, 1, true case "FilledSmallSquare": // BLACK MEDIUM SQUARE - return rune(0x25fc), true + return {'\u25fc', 0}, 1, true case "FilledVerySmallSquare": // BLACK SMALL SQUARE - return rune(0x25aa), true + return {'\u25aa', 0}, 1, true case "Fopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL F - return rune(0x01d53d), true + return {'\U0001d53d', 0}, 1, true case "ForAll": // FOR ALL - return rune(0x2200), true + return {'\u2200', 0}, 1, true case "Fouriertrf": // SCRIPT CAPITAL F - return rune(0x2131), true + return {'\u2131', 0}, 1, true case "Fscr": // SCRIPT CAPITAL F - return rune(0x2131), true + return {'\u2131', 0}, 1, true } case 'G': switch name { case "GJcy": // CYRILLIC CAPITAL LETTER GJE - return rune(0x0403), true + return {'\u0403', 0}, 1, true case "GT": // GREATER-THAN SIGN - return rune(0x3e), true + return {'>', 0}, 1, true case "Game": // TURNED SANS-SERIF CAPITAL G - return rune(0x2141), true + return {'\u2141', 0}, 1, true case "Gamma": // GREEK CAPITAL LETTER GAMMA - return rune(0x0393), true + return {'\u0393', 0}, 1, true case "Gammad": // GREEK LETTER DIGAMMA - return rune(0x03dc), true + return {'\u03dc', 0}, 1, true case "Gbreve": // LATIN CAPITAL LETTER G WITH BREVE - return rune(0x011e), true + return {'\u011e', 0}, 1, true case "Gcedil": // LATIN CAPITAL LETTER G WITH CEDILLA - return rune(0x0122), true + return {'\u0122', 0}, 1, true case "Gcirc": // LATIN CAPITAL LETTER G WITH CIRCUMFLEX - return rune(0x011c), true + return {'\u011c', 0}, 1, true case "Gcy": // CYRILLIC CAPITAL LETTER GHE - return rune(0x0413), true + return {'\u0413', 0}, 1, true case "Gdot": // LATIN CAPITAL LETTER G WITH DOT ABOVE - return rune(0x0120), true + return {'\u0120', 0}, 1, true case "Gfr": // MATHEMATICAL FRAKTUR CAPITAL G - return rune(0x01d50a), true + return {'\U0001d50a', 0}, 1, true case "Gg": // VERY MUCH GREATER-THAN - return rune(0x22d9), true + return {'\u22d9', 0}, 1, true case "Ggr": // GREEK CAPITAL LETTER GAMMA - return rune(0x0393), true + return {'\u0393', 0}, 1, true case "Gopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL G - return rune(0x01d53e), true + return {'\U0001d53e', 0}, 1, true case "GreaterEqual": // GREATER-THAN OR EQUAL TO - return rune(0x2265), true + return {'\u2265', 0}, 1, true case "GreaterEqualLess": // GREATER-THAN EQUAL TO OR LESS-THAN - return rune(0x22db), true + return {'\u22db', 0}, 1, true case "GreaterFullEqual": // GREATER-THAN OVER EQUAL TO - return rune(0x2267), true + return {'\u2267', 0}, 1, true case "GreaterGreater": // DOUBLE NESTED GREATER-THAN - return rune(0x2aa2), true + return {'\u2aa2', 0}, 1, true case "GreaterLess": // GREATER-THAN OR LESS-THAN - return rune(0x2277), true + return {'\u2277', 0}, 1, true case "GreaterSlantEqual": // GREATER-THAN OR SLANTED EQUAL TO - return rune(0x2a7e), true + return {'\u2a7e', 0}, 1, true case "GreaterTilde": // GREATER-THAN OR EQUIVALENT TO - return rune(0x2273), true + return {'\u2273', 0}, 1, true case "Gscr": // MATHEMATICAL SCRIPT CAPITAL G - return rune(0x01d4a2), true + return {'\U0001d4a2', 0}, 1, true case "Gt": // MUCH GREATER-THAN - return rune(0x226b), true + return {'\u226b', 0}, 1, true } case 'H': switch name { case "HARDcy": // CYRILLIC CAPITAL LETTER HARD SIGN - return rune(0x042a), true + return {'\u042a', 0}, 1, true case "Hacek": // CARON - return rune(0x02c7), true + return {'\u02c7', 0}, 1, true case "Hat": // CIRCUMFLEX ACCENT - return rune(0x5e), true + return {'^', 0}, 1, true case "Hcirc": // LATIN CAPITAL LETTER H WITH CIRCUMFLEX - return rune(0x0124), true + return {'\u0124', 0}, 1, true case "Hfr": // BLACK-LETTER CAPITAL H - return rune(0x210c), true + return {'\u210c', 0}, 1, true case "HilbertSpace": // SCRIPT CAPITAL H - return rune(0x210b), true + return {'\u210b', 0}, 1, true case "Hopf": // DOUBLE-STRUCK CAPITAL H - return rune(0x210d), true + return {'\u210d', 0}, 1, true case "HorizontalLine": // BOX DRAWINGS LIGHT HORIZONTAL - return rune(0x2500), true + return {'\u2500', 0}, 1, true case "Hscr": // SCRIPT CAPITAL H - return rune(0x210b), true + return {'\u210b', 0}, 1, true case "Hstrok": // LATIN CAPITAL LETTER H WITH STROKE - return rune(0x0126), true + return {'\u0126', 0}, 1, true case "HumpDownHump": // GEOMETRICALLY EQUIVALENT TO - return rune(0x224e), true + return {'\u224e', 0}, 1, true case "HumpEqual": // DIFFERENCE BETWEEN - return rune(0x224f), true + return {'\u224f', 0}, 1, true } case 'I': switch name { case "IEcy": // CYRILLIC CAPITAL LETTER IE - return rune(0x0415), true + return {'\u0415', 0}, 1, true case "IJlig": // LATIN CAPITAL LIGATURE IJ - return rune(0x0132), true + return {'\u0132', 0}, 1, true case "IOcy": // CYRILLIC CAPITAL LETTER IO - return rune(0x0401), true + return {'\u0401', 0}, 1, true case "Iacgr": // GREEK CAPITAL LETTER IOTA WITH TONOS - return rune(0x038a), true + return {'\u038a', 0}, 1, true case "Iacute": // LATIN CAPITAL LETTER I WITH ACUTE - return rune(0xcd), true + return {'Í', 0}, 1, true case "Icirc": // LATIN CAPITAL LETTER I WITH CIRCUMFLEX - return rune(0xce), true + return {'Î', 0}, 1, true case "Icy": // CYRILLIC CAPITAL LETTER I - return rune(0x0418), true + return {'\u0418', 0}, 1, true case "Idigr": // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA - return rune(0x03aa), true + return {'\u03aa', 0}, 1, true case "Idot": // LATIN CAPITAL LETTER I WITH DOT ABOVE - return rune(0x0130), true + return {'\u0130', 0}, 1, true case "Ifr": // BLACK-LETTER CAPITAL I - return rune(0x2111), true + return {'\u2111', 0}, 1, true case "Igr": // GREEK CAPITAL LETTER IOTA - return rune(0x0399), true + return {'\u0399', 0}, 1, true case "Igrave": // LATIN CAPITAL LETTER I WITH GRAVE - return rune(0xcc), true + return {'Ì', 0}, 1, true case "Im": // BLACK-LETTER CAPITAL I - return rune(0x2111), true + return {'\u2111', 0}, 1, true case "Imacr": // LATIN CAPITAL LETTER I WITH MACRON - return rune(0x012a), true + return {'\u012a', 0}, 1, true case "ImaginaryI": // DOUBLE-STRUCK ITALIC SMALL I - return rune(0x2148), true + return {'\u2148', 0}, 1, true case "Implies": // RIGHTWARDS DOUBLE ARROW - return rune(0x21d2), true + return {'\u21d2', 0}, 1, true case "Int": // DOUBLE INTEGRAL - return rune(0x222c), true + return {'\u222c', 0}, 1, true case "Integral": // INTEGRAL - return rune(0x222b), true + return {'\u222b', 0}, 1, true case "Intersection": // N-ARY INTERSECTION - return rune(0x22c2), true + return {'\u22c2', 0}, 1, true case "InvisibleComma": // INVISIBLE SEPARATOR - return rune(0x2063), true + return {'\u2063', 0}, 1, true case "InvisibleTimes": // INVISIBLE TIMES - return rune(0x2062), true + return {'\u2062', 0}, 1, true case "Iogon": // LATIN CAPITAL LETTER I WITH OGONEK - return rune(0x012e), true + return {'\u012e', 0}, 1, true case "Iopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL I - return rune(0x01d540), true + return {'\U0001d540', 0}, 1, true case "Iota": // GREEK CAPITAL LETTER IOTA - return rune(0x0399), true + return {'\u0399', 0}, 1, true case "Iscr": // SCRIPT CAPITAL I - return rune(0x2110), true + return {'\u2110', 0}, 1, true case "Itilde": // LATIN CAPITAL LETTER I WITH TILDE - return rune(0x0128), true + return {'\u0128', 0}, 1, true case "Iukcy": // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I - return rune(0x0406), true + return {'\u0406', 0}, 1, true case "Iuml": // LATIN CAPITAL LETTER I WITH DIAERESIS - return rune(0xcf), true + return {'Ï', 0}, 1, true } case 'J': switch name { case "Jcirc": // LATIN CAPITAL LETTER J WITH CIRCUMFLEX - return rune(0x0134), true + return {'\u0134', 0}, 1, true case "Jcy": // CYRILLIC CAPITAL LETTER SHORT I - return rune(0x0419), true + return {'\u0419', 0}, 1, true case "Jfr": // MATHEMATICAL FRAKTUR CAPITAL J - return rune(0x01d50d), true + return {'\U0001d50d', 0}, 1, true case "Jopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL J - return rune(0x01d541), true + return {'\U0001d541', 0}, 1, true case "Jscr": // MATHEMATICAL SCRIPT CAPITAL J - return rune(0x01d4a5), true + return {'\U0001d4a5', 0}, 1, true case "Jsercy": // CYRILLIC CAPITAL LETTER JE - return rune(0x0408), true + return {'\u0408', 0}, 1, true case "Jukcy": // CYRILLIC CAPITAL LETTER UKRAINIAN IE - return rune(0x0404), true + return {'\u0404', 0}, 1, true } case 'K': switch name { case "KHcy": // CYRILLIC CAPITAL LETTER HA - return rune(0x0425), true + return {'\u0425', 0}, 1, true case "KHgr": // GREEK CAPITAL LETTER CHI - return rune(0x03a7), true + return {'\u03a7', 0}, 1, true case "KJcy": // CYRILLIC CAPITAL LETTER KJE - return rune(0x040c), true + return {'\u040c', 0}, 1, true case "Kappa": // GREEK CAPITAL LETTER KAPPA - return rune(0x039a), true + return {'\u039a', 0}, 1, true case "Kcedil": // LATIN CAPITAL LETTER K WITH CEDILLA - return rune(0x0136), true + return {'\u0136', 0}, 1, true case "Kcy": // CYRILLIC CAPITAL LETTER KA - return rune(0x041a), true + return {'\u041a', 0}, 1, true case "Kfr": // MATHEMATICAL FRAKTUR CAPITAL K - return rune(0x01d50e), true + return {'\U0001d50e', 0}, 1, true case "Kgr": // GREEK CAPITAL LETTER KAPPA - return rune(0x039a), true + return {'\u039a', 0}, 1, true case "Kopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL K - return rune(0x01d542), true + return {'\U0001d542', 0}, 1, true case "Kscr": // MATHEMATICAL SCRIPT CAPITAL K - return rune(0x01d4a6), true + return {'\U0001d4a6', 0}, 1, true } case 'L': switch name { case "LJcy": // CYRILLIC CAPITAL LETTER LJE - return rune(0x0409), true + return {'\u0409', 0}, 1, true case "LT": // LESS-THAN SIGN - return rune(0x3c), true + return {'<', 0}, 1, true case "Lacute": // LATIN CAPITAL LETTER L WITH ACUTE - return rune(0x0139), true + return {'\u0139', 0}, 1, true case "Lambda": // GREEK CAPITAL LETTER LAMDA - return rune(0x039b), true + return {'\u039b', 0}, 1, true case "Lang": // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET - return rune(0x27ea), true + return {'\u27ea', 0}, 1, true case "Laplacetrf": // SCRIPT CAPITAL L - return rune(0x2112), true + return {'\u2112', 0}, 1, true case "Larr": // LEFTWARDS TWO HEADED ARROW - return rune(0x219e), true + return {'\u219e', 0}, 1, true case "Lcaron": // LATIN CAPITAL LETTER L WITH CARON - return rune(0x013d), true + return {'\u013d', 0}, 1, true case "Lcedil": // LATIN CAPITAL LETTER L WITH CEDILLA - return rune(0x013b), true + return {'\u013b', 0}, 1, true case "Lcy": // CYRILLIC CAPITAL LETTER EL - return rune(0x041b), true + return {'\u041b', 0}, 1, true case "LeftAngleBracket": // MATHEMATICAL LEFT ANGLE BRACKET - return rune(0x27e8), true + return {'\u27e8', 0}, 1, true case "LeftArrow": // LEFTWARDS ARROW - return rune(0x2190), true + return {'\u2190', 0}, 1, true case "LeftArrowBar": // LEFTWARDS ARROW TO BAR - return rune(0x21e4), true + return {'\u21e4', 0}, 1, true case "LeftArrowRightArrow": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true + return {'\u21c6', 0}, 1, true case "LeftCeiling": // LEFT CEILING - return rune(0x2308), true + return {'\u2308', 0}, 1, true case "LeftDoubleBracket": // MATHEMATICAL LEFT WHITE SQUARE BRACKET - return rune(0x27e6), true + return {'\u27e6', 0}, 1, true case "LeftDownTeeVector": // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR - return rune(0x2961), true + return {'\u2961', 0}, 1, true case "LeftDownVector": // DOWNWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21c3), true + return {'\u21c3', 0}, 1, true case "LeftDownVectorBar": // DOWNWARDS HARPOON WITH BARB LEFT TO BAR - return rune(0x2959), true + return {'\u2959', 0}, 1, true case "LeftFloor": // LEFT FLOOR - return rune(0x230a), true + return {'\u230a', 0}, 1, true case "LeftRightArrow": // LEFT RIGHT ARROW - return rune(0x2194), true + return {'\u2194', 0}, 1, true case "LeftRightVector": // LEFT BARB UP RIGHT BARB UP HARPOON - return rune(0x294e), true + return {'\u294e', 0}, 1, true case "LeftTee": // LEFT TACK - return rune(0x22a3), true + return {'\u22a3', 0}, 1, true case "LeftTeeArrow": // LEFTWARDS ARROW FROM BAR - return rune(0x21a4), true + return {'\u21a4', 0}, 1, true case "LeftTeeVector": // LEFTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295a), true + return {'\u295a', 0}, 1, true case "LeftTriangle": // NORMAL SUBGROUP OF - return rune(0x22b2), true + return {'\u22b2', 0}, 1, true case "LeftTriangleBar": // LEFT TRIANGLE BESIDE VERTICAL BAR - return rune(0x29cf), true + return {'\u29cf', 0}, 1, true case "LeftTriangleEqual": // NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22b4), true + return {'\u22b4', 0}, 1, true case "LeftUpDownVector": // UP BARB LEFT DOWN BARB LEFT HARPOON - return rune(0x2951), true + return {'\u2951', 0}, 1, true case "LeftUpTeeVector": // UPWARDS HARPOON WITH BARB LEFT FROM BAR - return rune(0x2960), true + return {'\u2960', 0}, 1, true case "LeftUpVector": // UPWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21bf), true + return {'\u21bf', 0}, 1, true case "LeftUpVectorBar": // UPWARDS HARPOON WITH BARB LEFT TO BAR - return rune(0x2958), true + return {'\u2958', 0}, 1, true case "LeftVector": // LEFTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21bc), true + return {'\u21bc', 0}, 1, true case "LeftVectorBar": // LEFTWARDS HARPOON WITH BARB UP TO BAR - return rune(0x2952), true + return {'\u2952', 0}, 1, true case "Leftarrow": // LEFTWARDS DOUBLE ARROW - return rune(0x21d0), true + return {'\u21d0', 0}, 1, true case "Leftrightarrow": // LEFT RIGHT DOUBLE ARROW - return rune(0x21d4), true + return {'\u21d4', 0}, 1, true case "LessEqualGreater": // LESS-THAN EQUAL TO OR GREATER-THAN - return rune(0x22da), true + return {'\u22da', 0}, 1, true case "LessFullEqual": // LESS-THAN OVER EQUAL TO - return rune(0x2266), true + return {'\u2266', 0}, 1, true case "LessGreater": // LESS-THAN OR GREATER-THAN - return rune(0x2276), true + return {'\u2276', 0}, 1, true case "LessLess": // DOUBLE NESTED LESS-THAN - return rune(0x2aa1), true + return {'\u2aa1', 0}, 1, true case "LessSlantEqual": // LESS-THAN OR SLANTED EQUAL TO - return rune(0x2a7d), true + return {'\u2a7d', 0}, 1, true case "LessTilde": // LESS-THAN OR EQUIVALENT TO - return rune(0x2272), true + return {'\u2272', 0}, 1, true case "Lfr": // MATHEMATICAL FRAKTUR CAPITAL L - return rune(0x01d50f), true + return {'\U0001d50f', 0}, 1, true case "Lgr": // GREEK CAPITAL LETTER LAMDA - return rune(0x039b), true + return {'\u039b', 0}, 1, true case "Ll": // VERY MUCH LESS-THAN - return rune(0x22d8), true + return {'\u22d8', 0}, 1, true case "Lleftarrow": // LEFTWARDS TRIPLE ARROW - return rune(0x21da), true + return {'\u21da', 0}, 1, true case "Lmidot": // LATIN CAPITAL LETTER L WITH MIDDLE DOT - return rune(0x013f), true + return {'\u013f', 0}, 1, true case "LongLeftArrow": // LONG LEFTWARDS ARROW - return rune(0x27f5), true + return {'\u27f5', 0}, 1, true case "LongLeftRightArrow": // LONG LEFT RIGHT ARROW - return rune(0x27f7), true + return {'\u27f7', 0}, 1, true case "LongRightArrow": // LONG RIGHTWARDS ARROW - return rune(0x27f6), true + return {'\u27f6', 0}, 1, true case "Longleftarrow": // LONG LEFTWARDS DOUBLE ARROW - return rune(0x27f8), true + return {'\u27f8', 0}, 1, true case "Longleftrightarrow": // LONG LEFT RIGHT DOUBLE ARROW - return rune(0x27fa), true + return {'\u27fa', 0}, 1, true case "Longrightarrow": // LONG RIGHTWARDS DOUBLE ARROW - return rune(0x27f9), true + return {'\u27f9', 0}, 1, true case "Lopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL L - return rune(0x01d543), true + return {'\U0001d543', 0}, 1, true case "LowerLeftArrow": // SOUTH WEST ARROW - return rune(0x2199), true + return {'\u2199', 0}, 1, true case "LowerRightArrow": // SOUTH EAST ARROW - return rune(0x2198), true + return {'\u2198', 0}, 1, true case "Lscr": // SCRIPT CAPITAL L - return rune(0x2112), true + return {'\u2112', 0}, 1, true case "Lsh": // UPWARDS ARROW WITH TIP LEFTWARDS - return rune(0x21b0), true + return {'\u21b0', 0}, 1, true case "Lstrok": // LATIN CAPITAL LETTER L WITH STROKE - return rune(0x0141), true + return {'\u0141', 0}, 1, true case "Lt": // MUCH LESS-THAN - return rune(0x226a), true + return {'\u226a', 0}, 1, true case "Ltbar": // DOUBLE NESTED LESS-THAN WITH UNDERBAR - return rune(0x2aa3), true + return {'\u2aa3', 0}, 1, true } case 'M': switch name { case "Map": // RIGHTWARDS TWO-HEADED ARROW FROM BAR - return rune(0x2905), true + return {'\u2905', 0}, 1, true case "Mapfrom": // LEFTWARDS DOUBLE ARROW FROM BAR - return rune(0x2906), true + return {'\u2906', 0}, 1, true case "Mapto": // RIGHTWARDS DOUBLE ARROW FROM BAR - return rune(0x2907), true + return {'\u2907', 0}, 1, true case "Mcy": // CYRILLIC CAPITAL LETTER EM - return rune(0x041c), true + return {'\u041c', 0}, 1, true case "MediumSpace": // MEDIUM MATHEMATICAL SPACE - return rune(0x205f), true + return {'\u205f', 0}, 1, true case "Mellintrf": // SCRIPT CAPITAL M - return rune(0x2133), true + return {'\u2133', 0}, 1, true case "Mfr": // MATHEMATICAL FRAKTUR CAPITAL M - return rune(0x01d510), true + return {'\U0001d510', 0}, 1, true case "Mgr": // GREEK CAPITAL LETTER MU - return rune(0x039c), true + return {'\u039c', 0}, 1, true case "MinusPlus": // MINUS-OR-PLUS SIGN - return rune(0x2213), true + return {'\u2213', 0}, 1, true case "Mopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL M - return rune(0x01d544), true + return {'\U0001d544', 0}, 1, true case "Mscr": // SCRIPT CAPITAL M - return rune(0x2133), true + return {'\u2133', 0}, 1, true case "Mu": // GREEK CAPITAL LETTER MU - return rune(0x039c), true + return {'\u039c', 0}, 1, true } case 'N': switch name { case "NJcy": // CYRILLIC CAPITAL LETTER NJE - return rune(0x040a), true + return {'\u040a', 0}, 1, true case "Nacute": // LATIN CAPITAL LETTER N WITH ACUTE - return rune(0x0143), true + return {'\u0143', 0}, 1, true case "Ncaron": // LATIN CAPITAL LETTER N WITH CARON - return rune(0x0147), true + return {'\u0147', 0}, 1, true case "Ncedil": // LATIN CAPITAL LETTER N WITH CEDILLA - return rune(0x0145), true + return {'\u0145', 0}, 1, true case "Ncy": // CYRILLIC CAPITAL LETTER EN - return rune(0x041d), true + return {'\u041d', 0}, 1, true case "NegativeMediumSpace": // ZERO WIDTH SPACE - return rune(0x200b), true + return {'\u200b', 0}, 1, true case "NegativeThickSpace": // ZERO WIDTH SPACE - return rune(0x200b), true + return {'\u200b', 0}, 1, true case "NegativeThinSpace": // ZERO WIDTH SPACE - return rune(0x200b), true + return {'\u200b', 0}, 1, true case "NegativeVeryThinSpace": // ZERO WIDTH SPACE - return rune(0x200b), true + return {'\u200b', 0}, 1, true case "NestedGreaterGreater": // MUCH GREATER-THAN - return rune(0x226b), true + return {'\u226b', 0}, 1, true case "NestedLessLess": // MUCH LESS-THAN - return rune(0x226a), true + return {'\u226a', 0}, 1, true case "NewLine": // LINE FEED (LF) - return rune(0x0a), true + return {'\n', 0}, 1, true case "Nfr": // MATHEMATICAL FRAKTUR CAPITAL N - return rune(0x01d511), true + return {'\U0001d511', 0}, 1, true case "Ngr": // GREEK CAPITAL LETTER NU - return rune(0x039d), true + return {'\u039d', 0}, 1, true case "NoBreak": // WORD JOINER - return rune(0x2060), true + return {'\u2060', 0}, 1, true case "NonBreakingSpace": // NO-BREAK SPACE - return rune(0xa0), true + return {'\u00a0', 0}, 1, true case "Nopf": // DOUBLE-STRUCK CAPITAL N - return rune(0x2115), true + return {'\u2115', 0}, 1, true case "Not": // DOUBLE STROKE NOT SIGN - return rune(0x2aec), true + return {'\u2aec', 0}, 1, true case "NotCongruent": // NOT IDENTICAL TO - return rune(0x2262), true + return {'\u2262', 0}, 1, true case "NotCupCap": // NOT EQUIVALENT TO - return rune(0x226d), true + return {'\u226d', 0}, 1, true case "NotDoubleVerticalBar": // NOT PARALLEL TO - return rune(0x2226), true + return {'\u2226', 0}, 1, true case "NotElement": // NOT AN ELEMENT OF - return rune(0x2209), true + return {'\u2209', 0}, 1, true case "NotEqual": // NOT EQUAL TO - return rune(0x2260), true + return {'\u2260', 0}, 1, true case "NotEqualTilde": // MINUS TILDE with slash - return rune(0x2242), true + return {'\u2242', '\u0338'}, 2, true case "NotExists": // THERE DOES NOT EXIST - return rune(0x2204), true + return {'\u2204', 0}, 1, true case "NotGreater": // NOT GREATER-THAN - return rune(0x226f), true + return {'\u226f', 0}, 1, true case "NotGreaterEqual": // NEITHER GREATER-THAN NOR EQUAL TO - return rune(0x2271), true + return {'\u2271', 0}, 1, true case "NotGreaterFullEqual": // GREATER-THAN OVER EQUAL TO with slash - return rune(0x2267), true + return {'\u2267', '\u0338'}, 2, true case "NotGreaterGreater": // MUCH GREATER THAN with slash - return rune(0x226b), true + return {'\u226b', '\u0338'}, 2, true case "NotGreaterLess": // NEITHER GREATER-THAN NOR LESS-THAN - return rune(0x2279), true + return {'\u2279', 0}, 1, true case "NotGreaterSlantEqual": // GREATER-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7e), true + return {'\u2a7e', '\u0338'}, 2, true case "NotGreaterTilde": // NEITHER GREATER-THAN NOR EQUIVALENT TO - return rune(0x2275), true + return {'\u2275', 0}, 1, true case "NotHumpDownHump": // GEOMETRICALLY EQUIVALENT TO with slash - return rune(0x224e), true + return {'\u224e', '\u0338'}, 2, true case "NotHumpEqual": // DIFFERENCE BETWEEN with slash - return rune(0x224f), true + return {'\u224f', '\u0338'}, 2, true case "NotLeftTriangle": // NOT NORMAL SUBGROUP OF - return rune(0x22ea), true + return {'\u22ea', 0}, 1, true case "NotLeftTriangleBar": // LEFT TRIANGLE BESIDE VERTICAL BAR with slash - return rune(0x29cf), true + return {'\u29cf', '\u0338'}, 2, true case "NotLeftTriangleEqual": // NOT NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22ec), true + return {'\u22ec', 0}, 1, true case "NotLess": // NOT LESS-THAN - return rune(0x226e), true + return {'\u226e', 0}, 1, true case "NotLessEqual": // NEITHER LESS-THAN NOR EQUAL TO - return rune(0x2270), true + return {'\u2270', 0}, 1, true case "NotLessGreater": // NEITHER LESS-THAN NOR GREATER-THAN - return rune(0x2278), true + return {'\u2278', 0}, 1, true case "NotLessLess": // MUCH LESS THAN with slash - return rune(0x226a), true + return {'\u226a', '\u0338'}, 2, true case "NotLessSlantEqual": // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true + return {'\u2a7d', '\u0338'}, 2, true case "NotLessTilde": // NEITHER LESS-THAN NOR EQUIVALENT TO - return rune(0x2274), true + return {'\u2274', 0}, 1, true case "NotNestedGreaterGreater": // DOUBLE NESTED GREATER-THAN with slash - return rune(0x2aa2), true + return {'\u2aa2', '\u0338'}, 2, true case "NotNestedLessLess": // DOUBLE NESTED LESS-THAN with slash - return rune(0x2aa1), true + return {'\u2aa1', '\u0338'}, 2, true case "NotPrecedes": // DOES NOT PRECEDE - return rune(0x2280), true + return {'\u2280', 0}, 1, true case "NotPrecedesEqual": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2aaf), true + return {'\u2aaf', '\u0338'}, 2, true case "NotPrecedesSlantEqual": // DOES NOT PRECEDE OR EQUAL - return rune(0x22e0), true + return {'\u22e0', 0}, 1, true case "NotReverseElement": // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true + return {'\u220c', 0}, 1, true case "NotRightTriangle": // DOES NOT CONTAIN AS NORMAL SUBGROUP - return rune(0x22eb), true + return {'\u22eb', 0}, 1, true case "NotRightTriangleBar": // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash - return rune(0x29d0), true + return {'\u29d0', '\u0338'}, 2, true case "NotRightTriangleEqual": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL - return rune(0x22ed), true + return {'\u22ed', 0}, 1, true case "NotSquareSubset": // SQUARE IMAGE OF with slash - return rune(0x228f), true + return {'\u228f', '\u0338'}, 2, true case "NotSquareSubsetEqual": // NOT SQUARE IMAGE OF OR EQUAL TO - return rune(0x22e2), true + return {'\u22e2', 0}, 1, true case "NotSquareSuperset": // SQUARE ORIGINAL OF with slash - return rune(0x2290), true + return {'\u2290', '\u0338'}, 2, true case "NotSquareSupersetEqual": // NOT SQUARE ORIGINAL OF OR EQUAL TO - return rune(0x22e3), true + return {'\u22e3', 0}, 1, true case "NotSubset": // SUBSET OF with vertical line - return rune(0x2282), true + return {'\u2282', '\u20d2'}, 2, true case "NotSubsetEqual": // NEITHER A SUBSET OF NOR EQUAL TO - return rune(0x2288), true + return {'\u2288', 0}, 1, true case "NotSucceeds": // DOES NOT SUCCEED - return rune(0x2281), true + return {'\u2281', 0}, 1, true case "NotSucceedsEqual": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2ab0), true + return {'\u2ab0', '\u0338'}, 2, true case "NotSucceedsSlantEqual": // DOES NOT SUCCEED OR EQUAL - return rune(0x22e1), true + return {'\u22e1', 0}, 1, true case "NotSucceedsTilde": // SUCCEEDS OR EQUIVALENT TO with slash - return rune(0x227f), true + return {'\u227f', '\u0338'}, 2, true case "NotSuperset": // SUPERSET OF with vertical line - return rune(0x2283), true + return {'\u2283', '\u20d2'}, 2, true case "NotSupersetEqual": // NEITHER A SUPERSET OF NOR EQUAL TO - return rune(0x2289), true + return {'\u2289', 0}, 1, true case "NotTilde": // NOT TILDE - return rune(0x2241), true + return {'\u2241', 0}, 1, true case "NotTildeEqual": // NOT ASYMPTOTICALLY EQUAL TO - return rune(0x2244), true + return {'\u2244', 0}, 1, true case "NotTildeFullEqual": // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO - return rune(0x2247), true + return {'\u2247', 0}, 1, true case "NotTildeTilde": // NOT ALMOST EQUAL TO - return rune(0x2249), true + return {'\u2249', 0}, 1, true case "NotVerticalBar": // DOES NOT DIVIDE - return rune(0x2224), true + return {'\u2224', 0}, 1, true case "Nscr": // MATHEMATICAL SCRIPT CAPITAL N - return rune(0x01d4a9), true + return {'\U0001d4a9', 0}, 1, true case "Ntilde": // LATIN CAPITAL LETTER N WITH TILDE - return rune(0xd1), true + return {'Ñ', 0}, 1, true case "Nu": // GREEK CAPITAL LETTER NU - return rune(0x039d), true + return {'\u039d', 0}, 1, true } case 'O': switch name { case "OElig": // LATIN CAPITAL LIGATURE OE - return rune(0x0152), true + return {'\u0152', 0}, 1, true case "OHacgr": // GREEK CAPITAL LETTER OMEGA WITH TONOS - return rune(0x038f), true + return {'\u038f', 0}, 1, true case "OHgr": // GREEK CAPITAL LETTER OMEGA - return rune(0x03a9), true + return {'\u03a9', 0}, 1, true case "Oacgr": // GREEK CAPITAL LETTER OMICRON WITH TONOS - return rune(0x038c), true + return {'\u038c', 0}, 1, true case "Oacute": // LATIN CAPITAL LETTER O WITH ACUTE - return rune(0xd3), true + return {'Ó', 0}, 1, true case "Ocirc": // LATIN CAPITAL LETTER O WITH CIRCUMFLEX - return rune(0xd4), true + return {'Ô', 0}, 1, true case "Ocy": // CYRILLIC CAPITAL LETTER O - return rune(0x041e), true + return {'\u041e', 0}, 1, true case "Odblac": // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE - return rune(0x0150), true + return {'\u0150', 0}, 1, true case "Ofr": // MATHEMATICAL FRAKTUR CAPITAL O - return rune(0x01d512), true + return {'\U0001d512', 0}, 1, true case "Ogr": // GREEK CAPITAL LETTER OMICRON - return rune(0x039f), true + return {'\u039f', 0}, 1, true case "Ograve": // LATIN CAPITAL LETTER O WITH GRAVE - return rune(0xd2), true + return {'Ò', 0}, 1, true case "Omacr": // LATIN CAPITAL LETTER O WITH MACRON - return rune(0x014c), true + return {'\u014c', 0}, 1, true case "Omega": // GREEK CAPITAL LETTER OMEGA - return rune(0x03a9), true + return {'\u03a9', 0}, 1, true case "Omicron": // GREEK CAPITAL LETTER OMICRON - return rune(0x039f), true + return {'\u039f', 0}, 1, true case "Oopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL O - return rune(0x01d546), true + return {'\U0001d546', 0}, 1, true case "OpenCurlyDoubleQuote": // LEFT DOUBLE QUOTATION MARK - return rune(0x201c), true + return {'\u201c', 0}, 1, true case "OpenCurlyQuote": // LEFT SINGLE QUOTATION MARK - return rune(0x2018), true + return {'\u2018', 0}, 1, true case "Or": // DOUBLE LOGICAL OR - return rune(0x2a54), true + return {'\u2a54', 0}, 1, true case "Oscr": // MATHEMATICAL SCRIPT CAPITAL O - return rune(0x01d4aa), true + return {'\U0001d4aa', 0}, 1, true case "Oslash": // LATIN CAPITAL LETTER O WITH STROKE - return rune(0xd8), true + return {'Ø', 0}, 1, true case "Otilde": // LATIN CAPITAL LETTER O WITH TILDE - return rune(0xd5), true + return {'Õ', 0}, 1, true case "Otimes": // MULTIPLICATION SIGN IN DOUBLE CIRCLE - return rune(0x2a37), true + return {'\u2a37', 0}, 1, true case "Ouml": // LATIN CAPITAL LETTER O WITH DIAERESIS - return rune(0xd6), true + return {'Ö', 0}, 1, true case "OverBar": // OVERLINE - return rune(0x203e), true + return {'\u203e', 0}, 1, true case "OverBrace": // TOP CURLY BRACKET - return rune(0x23de), true + return {'\u23de', 0}, 1, true case "OverBracket": // TOP SQUARE BRACKET - return rune(0x23b4), true + return {'\u23b4', 0}, 1, true case "OverParenthesis": // TOP PARENTHESIS - return rune(0x23dc), true + return {'\u23dc', 0}, 1, true } case 'P': switch name { case "PHgr": // GREEK CAPITAL LETTER PHI - return rune(0x03a6), true + return {'\u03a6', 0}, 1, true case "PSgr": // GREEK CAPITAL LETTER PSI - return rune(0x03a8), true + return {'\u03a8', 0}, 1, true case "PartialD": // PARTIAL DIFFERENTIAL - return rune(0x2202), true + return {'\u2202', 0}, 1, true case "Pcy": // CYRILLIC CAPITAL LETTER PE - return rune(0x041f), true + return {'\u041f', 0}, 1, true case "Pfr": // MATHEMATICAL FRAKTUR CAPITAL P - return rune(0x01d513), true + return {'\U0001d513', 0}, 1, true case "Pgr": // GREEK CAPITAL LETTER PI - return rune(0x03a0), true + return {'\u03a0', 0}, 1, true case "Phi": // GREEK CAPITAL LETTER PHI - return rune(0x03a6), true + return {'\u03a6', 0}, 1, true case "Pi": // GREEK CAPITAL LETTER PI - return rune(0x03a0), true + return {'\u03a0', 0}, 1, true case "PlusMinus": // PLUS-MINUS SIGN - return rune(0xb1), true + return {'±', 0}, 1, true case "Poincareplane": // BLACK-LETTER CAPITAL H - return rune(0x210c), true + return {'\u210c', 0}, 1, true case "Popf": // DOUBLE-STRUCK CAPITAL P - return rune(0x2119), true + return {'\u2119', 0}, 1, true case "Pr": // DOUBLE PRECEDES - return rune(0x2abb), true + return {'\u2abb', 0}, 1, true case "Precedes": // PRECEDES - return rune(0x227a), true + return {'\u227a', 0}, 1, true case "PrecedesEqual": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2aaf), true + return {'\u2aaf', 0}, 1, true case "PrecedesSlantEqual": // PRECEDES OR EQUAL TO - return rune(0x227c), true + return {'\u227c', 0}, 1, true case "PrecedesTilde": // PRECEDES OR EQUIVALENT TO - return rune(0x227e), true + return {'\u227e', 0}, 1, true case "Prime": // DOUBLE PRIME - return rune(0x2033), true + return {'\u2033', 0}, 1, true case "Product": // N-ARY PRODUCT - return rune(0x220f), true + return {'\u220f', 0}, 1, true case "Proportion": // PROPORTION - return rune(0x2237), true + return {'\u2237', 0}, 1, true case "Proportional": // PROPORTIONAL TO - return rune(0x221d), true + return {'\u221d', 0}, 1, true case "Pscr": // MATHEMATICAL SCRIPT CAPITAL P - return rune(0x01d4ab), true + return {'\U0001d4ab', 0}, 1, true case "Psi": // GREEK CAPITAL LETTER PSI - return rune(0x03a8), true + return {'\u03a8', 0}, 1, true } case 'Q': switch name { case "QUOT": // QUOTATION MARK - return rune(0x22), true + return {'"', 0}, 1, true case "Qfr": // MATHEMATICAL FRAKTUR CAPITAL Q - return rune(0x01d514), true + return {'\U0001d514', 0}, 1, true case "Qopf": // DOUBLE-STRUCK CAPITAL Q - return rune(0x211a), true + return {'\u211a', 0}, 1, true case "Qscr": // MATHEMATICAL SCRIPT CAPITAL Q - return rune(0x01d4ac), true + return {'\U0001d4ac', 0}, 1, true } case 'R': switch name { case "RBarr": // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW - return rune(0x2910), true + return {'\u2910', 0}, 1, true case "REG": // REGISTERED SIGN - return rune(0xae), true + return {'®', 0}, 1, true case "Racute": // LATIN CAPITAL LETTER R WITH ACUTE - return rune(0x0154), true + return {'\u0154', 0}, 1, true case "Rang": // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET - return rune(0x27eb), true + return {'\u27eb', 0}, 1, true case "Rarr": // RIGHTWARDS TWO HEADED ARROW - return rune(0x21a0), true + return {'\u21a0', 0}, 1, true case "Rarrtl": // RIGHTWARDS TWO-HEADED ARROW WITH TAIL - return rune(0x2916), true + return {'\u2916', 0}, 1, true case "Rcaron": // LATIN CAPITAL LETTER R WITH CARON - return rune(0x0158), true + return {'\u0158', 0}, 1, true case "Rcedil": // LATIN CAPITAL LETTER R WITH CEDILLA - return rune(0x0156), true + return {'\u0156', 0}, 1, true case "Rcy": // CYRILLIC CAPITAL LETTER ER - return rune(0x0420), true + return {'\u0420', 0}, 1, true case "Re": // BLACK-LETTER CAPITAL R - return rune(0x211c), true + return {'\u211c', 0}, 1, true case "ReverseElement": // CONTAINS AS MEMBER - return rune(0x220b), true + return {'\u220b', 0}, 1, true case "ReverseEquilibrium": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true + return {'\u21cb', 0}, 1, true case "ReverseUpEquilibrium": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - return rune(0x296f), true + return {'\u296f', 0}, 1, true case "Rfr": // BLACK-LETTER CAPITAL R - return rune(0x211c), true + return {'\u211c', 0}, 1, true case "Rgr": // GREEK CAPITAL LETTER RHO - return rune(0x03a1), true + return {'\u03a1', 0}, 1, true case "Rho": // GREEK CAPITAL LETTER RHO - return rune(0x03a1), true + return {'\u03a1', 0}, 1, true case "RightAngleBracket": // MATHEMATICAL RIGHT ANGLE BRACKET - return rune(0x27e9), true + return {'\u27e9', 0}, 1, true case "RightArrow": // RIGHTWARDS ARROW - return rune(0x2192), true + return {'\u2192', 0}, 1, true case "RightArrowBar": // RIGHTWARDS ARROW TO BAR - return rune(0x21e5), true + return {'\u21e5', 0}, 1, true case "RightArrowLeftArrow": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true + return {'\u21c4', 0}, 1, true case "RightCeiling": // RIGHT CEILING - return rune(0x2309), true + return {'\u2309', 0}, 1, true case "RightDoubleBracket": // MATHEMATICAL RIGHT WHITE SQUARE BRACKET - return rune(0x27e7), true + return {'\u27e7', 0}, 1, true case "RightDownTeeVector": // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR - return rune(0x295d), true + return {'\u295d', 0}, 1, true case "RightDownVector": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21c2), true + return {'\u21c2', 0}, 1, true case "RightDownVectorBar": // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR - return rune(0x2955), true + return {'\u2955', 0}, 1, true case "RightFloor": // RIGHT FLOOR - return rune(0x230b), true + return {'\u230b', 0}, 1, true case "RightTee": // RIGHT TACK - return rune(0x22a2), true + return {'\u22a2', 0}, 1, true case "RightTeeArrow": // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true + return {'\u21a6', 0}, 1, true case "RightTeeVector": // RIGHTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295b), true + return {'\u295b', 0}, 1, true case "RightTriangle": // CONTAINS AS NORMAL SUBGROUP - return rune(0x22b3), true + return {'\u22b3', 0}, 1, true case "RightTriangleBar": // VERTICAL BAR BESIDE RIGHT TRIANGLE - return rune(0x29d0), true + return {'\u29d0', 0}, 1, true case "RightTriangleEqual": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - return rune(0x22b5), true + return {'\u22b5', 0}, 1, true case "RightUpDownVector": // UP BARB RIGHT DOWN BARB RIGHT HARPOON - return rune(0x294f), true + return {'\u294f', 0}, 1, true case "RightUpTeeVector": // UPWARDS HARPOON WITH BARB RIGHT FROM BAR - return rune(0x295c), true + return {'\u295c', 0}, 1, true case "RightUpVector": // UPWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21be), true + return {'\u21be', 0}, 1, true case "RightUpVectorBar": // UPWARDS HARPOON WITH BARB RIGHT TO BAR - return rune(0x2954), true + return {'\u2954', 0}, 1, true case "RightVector": // RIGHTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21c0), true + return {'\u21c0', 0}, 1, true case "RightVectorBar": // RIGHTWARDS HARPOON WITH BARB UP TO BAR - return rune(0x2953), true + return {'\u2953', 0}, 1, true case "Rightarrow": // RIGHTWARDS DOUBLE ARROW - return rune(0x21d2), true + return {'\u21d2', 0}, 1, true case "Ropf": // DOUBLE-STRUCK CAPITAL R - return rune(0x211d), true + return {'\u211d', 0}, 1, true case "RoundImplies": // RIGHT DOUBLE ARROW WITH ROUNDED HEAD - return rune(0x2970), true + return {'\u2970', 0}, 1, true case "Rrightarrow": // RIGHTWARDS TRIPLE ARROW - return rune(0x21db), true + return {'\u21db', 0}, 1, true case "Rscr": // SCRIPT CAPITAL R - return rune(0x211b), true + return {'\u211b', 0}, 1, true case "Rsh": // UPWARDS ARROW WITH TIP RIGHTWARDS - return rune(0x21b1), true + return {'\u21b1', 0}, 1, true case "RuleDelayed": // RULE-DELAYED - return rune(0x29f4), true + return {'\u29f4', 0}, 1, true } case 'S': switch name { case "SHCHcy": // CYRILLIC CAPITAL LETTER SHCHA - return rune(0x0429), true + return {'\u0429', 0}, 1, true case "SHcy": // CYRILLIC CAPITAL LETTER SHA - return rune(0x0428), true + return {'\u0428', 0}, 1, true case "SOFTcy": // CYRILLIC CAPITAL LETTER SOFT SIGN - return rune(0x042c), true + return {'\u042c', 0}, 1, true case "Sacute": // LATIN CAPITAL LETTER S WITH ACUTE - return rune(0x015a), true + return {'\u015a', 0}, 1, true case "Sc": // DOUBLE SUCCEEDS - return rune(0x2abc), true + return {'\u2abc', 0}, 1, true case "Scaron": // LATIN CAPITAL LETTER S WITH CARON - return rune(0x0160), true + return {'\u0160', 0}, 1, true case "Scedil": // LATIN CAPITAL LETTER S WITH CEDILLA - return rune(0x015e), true + return {'\u015e', 0}, 1, true case "Scirc": // LATIN CAPITAL LETTER S WITH CIRCUMFLEX - return rune(0x015c), true + return {'\u015c', 0}, 1, true case "Scy": // CYRILLIC CAPITAL LETTER ES - return rune(0x0421), true + return {'\u0421', 0}, 1, true case "Sfr": // MATHEMATICAL FRAKTUR CAPITAL S - return rune(0x01d516), true + return {'\U0001d516', 0}, 1, true case "Sgr": // GREEK CAPITAL LETTER SIGMA - return rune(0x03a3), true + return {'\u03a3', 0}, 1, true case "ShortDownArrow": // DOWNWARDS ARROW - return rune(0x2193), true + return {'\u2193', 0}, 1, true case "ShortLeftArrow": // LEFTWARDS ARROW - return rune(0x2190), true + return {'\u2190', 0}, 1, true case "ShortRightArrow": // RIGHTWARDS ARROW - return rune(0x2192), true + return {'\u2192', 0}, 1, true case "ShortUpArrow": // UPWARDS ARROW - return rune(0x2191), true + return {'\u2191', 0}, 1, true case "Sigma": // GREEK CAPITAL LETTER SIGMA - return rune(0x03a3), true + return {'\u03a3', 0}, 1, true case "SmallCircle": // RING OPERATOR - return rune(0x2218), true + return {'\u2218', 0}, 1, true case "Sopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL S - return rune(0x01d54a), true + return {'\U0001d54a', 0}, 1, true case "Sqrt": // SQUARE ROOT - return rune(0x221a), true + return {'\u221a', 0}, 1, true case "Square": // WHITE SQUARE - return rune(0x25a1), true + return {'\u25a1', 0}, 1, true case "SquareIntersection": // SQUARE CAP - return rune(0x2293), true + return {'\u2293', 0}, 1, true case "SquareSubset": // SQUARE IMAGE OF - return rune(0x228f), true + return {'\u228f', 0}, 1, true case "SquareSubsetEqual": // SQUARE IMAGE OF OR EQUAL TO - return rune(0x2291), true + return {'\u2291', 0}, 1, true case "SquareSuperset": // SQUARE ORIGINAL OF - return rune(0x2290), true + return {'\u2290', 0}, 1, true case "SquareSupersetEqual": // SQUARE ORIGINAL OF OR EQUAL TO - return rune(0x2292), true + return {'\u2292', 0}, 1, true case "SquareUnion": // SQUARE CUP - return rune(0x2294), true + return {'\u2294', 0}, 1, true case "Sscr": // MATHEMATICAL SCRIPT CAPITAL S - return rune(0x01d4ae), true + return {'\U0001d4ae', 0}, 1, true case "Star": // STAR OPERATOR - return rune(0x22c6), true + return {'\u22c6', 0}, 1, true case "Sub": // DOUBLE SUBSET - return rune(0x22d0), true + return {'\u22d0', 0}, 1, true case "Subset": // DOUBLE SUBSET - return rune(0x22d0), true + return {'\u22d0', 0}, 1, true case "SubsetEqual": // SUBSET OF OR EQUAL TO - return rune(0x2286), true + return {'\u2286', 0}, 1, true case "Succeeds": // SUCCEEDS - return rune(0x227b), true + return {'\u227b', 0}, 1, true case "SucceedsEqual": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2ab0), true + return {'\u2ab0', 0}, 1, true case "SucceedsSlantEqual": // SUCCEEDS OR EQUAL TO - return rune(0x227d), true + return {'\u227d', 0}, 1, true case "SucceedsTilde": // SUCCEEDS OR EQUIVALENT TO - return rune(0x227f), true + return {'\u227f', 0}, 1, true case "SuchThat": // CONTAINS AS MEMBER - return rune(0x220b), true + return {'\u220b', 0}, 1, true case "Sum": // N-ARY SUMMATION - return rune(0x2211), true + return {'\u2211', 0}, 1, true case "Sup": // DOUBLE SUPERSET - return rune(0x22d1), true + return {'\u22d1', 0}, 1, true case "Superset": // SUPERSET OF - return rune(0x2283), true + return {'\u2283', 0}, 1, true case "SupersetEqual": // SUPERSET OF OR EQUAL TO - return rune(0x2287), true + return {'\u2287', 0}, 1, true case "Supset": // DOUBLE SUPERSET - return rune(0x22d1), true + return {'\u22d1', 0}, 1, true } case 'T': switch name { case "THORN": // LATIN CAPITAL LETTER THORN - return rune(0xde), true + return {'Þ', 0}, 1, true case "THgr": // GREEK CAPITAL LETTER THETA - return rune(0x0398), true + return {'\u0398', 0}, 1, true case "TRADE": // TRADE MARK SIGN - return rune(0x2122), true + return {'\u2122', 0}, 1, true case "TSHcy": // CYRILLIC CAPITAL LETTER TSHE - return rune(0x040b), true + return {'\u040b', 0}, 1, true case "TScy": // CYRILLIC CAPITAL LETTER TSE - return rune(0x0426), true + return {'\u0426', 0}, 1, true case "Tab": // CHARACTER TABULATION - return rune(0x09), true + return {'\t', 0}, 1, true case "Tau": // GREEK CAPITAL LETTER TAU - return rune(0x03a4), true + return {'\u03a4', 0}, 1, true case "Tcaron": // LATIN CAPITAL LETTER T WITH CARON - return rune(0x0164), true + return {'\u0164', 0}, 1, true case "Tcedil": // LATIN CAPITAL LETTER T WITH CEDILLA - return rune(0x0162), true + return {'\u0162', 0}, 1, true case "Tcy": // CYRILLIC CAPITAL LETTER TE - return rune(0x0422), true + return {'\u0422', 0}, 1, true case "Tfr": // MATHEMATICAL FRAKTUR CAPITAL T - return rune(0x01d517), true + return {'\U0001d517', 0}, 1, true case "Tgr": // GREEK CAPITAL LETTER TAU - return rune(0x03a4), true + return {'\u03a4', 0}, 1, true case "Therefore": // THEREFORE - return rune(0x2234), true + return {'\u2234', 0}, 1, true case "Theta": // GREEK CAPITAL LETTER THETA - return rune(0x0398), true + return {'\u0398', 0}, 1, true case "Thetav": // GREEK CAPITAL THETA SYMBOL - return rune(0x03f4), true + return {'\u03f4', 0}, 1, true case "ThickSpace": // space of width 5/18 em - return rune(0x205f), true + return {'\u205f', '\u200a'}, 2, true case "ThinSpace": // THIN SPACE - return rune(0x2009), true + return {'\u2009', 0}, 1, true case "Tilde": // TILDE OPERATOR - return rune(0x223c), true + return {'\u223c', 0}, 1, true case "TildeEqual": // ASYMPTOTICALLY EQUAL TO - return rune(0x2243), true + return {'\u2243', 0}, 1, true case "TildeFullEqual": // APPROXIMATELY EQUAL TO - return rune(0x2245), true + return {'\u2245', 0}, 1, true case "TildeTilde": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "Topf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL T - return rune(0x01d54b), true + return {'\U0001d54b', 0}, 1, true case "TripleDot": // COMBINING THREE DOTS ABOVE - return rune(0x20db), true + return {'\u20db', 0}, 1, true case "Tscr": // MATHEMATICAL SCRIPT CAPITAL T - return rune(0x01d4af), true + return {'\U0001d4af', 0}, 1, true case "Tstrok": // LATIN CAPITAL LETTER T WITH STROKE - return rune(0x0166), true + return {'\u0166', 0}, 1, true } case 'U': switch name { case "Uacgr": // GREEK CAPITAL LETTER UPSILON WITH TONOS - return rune(0x038e), true + return {'\u038e', 0}, 1, true case "Uacute": // LATIN CAPITAL LETTER U WITH ACUTE - return rune(0xda), true + return {'Ú', 0}, 1, true case "Uarr": // UPWARDS TWO HEADED ARROW - return rune(0x219f), true + return {'\u219f', 0}, 1, true case "Uarrocir": // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE - return rune(0x2949), true + return {'\u2949', 0}, 1, true case "Ubrcy": // CYRILLIC CAPITAL LETTER SHORT U - return rune(0x040e), true + return {'\u040e', 0}, 1, true case "Ubreve": // LATIN CAPITAL LETTER U WITH BREVE - return rune(0x016c), true + return {'\u016c', 0}, 1, true case "Ucirc": // LATIN CAPITAL LETTER U WITH CIRCUMFLEX - return rune(0xdb), true + return {'Û', 0}, 1, true case "Ucy": // CYRILLIC CAPITAL LETTER U - return rune(0x0423), true + return {'\u0423', 0}, 1, true case "Udblac": // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE - return rune(0x0170), true + return {'\u0170', 0}, 1, true case "Udigr": // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA - return rune(0x03ab), true + return {'\u03ab', 0}, 1, true case "Ufr": // MATHEMATICAL FRAKTUR CAPITAL U - return rune(0x01d518), true + return {'\U0001d518', 0}, 1, true case "Ugr": // GREEK CAPITAL LETTER UPSILON - return rune(0x03a5), true + return {'\u03a5', 0}, 1, true case "Ugrave": // LATIN CAPITAL LETTER U WITH GRAVE - return rune(0xd9), true + return {'Ù', 0}, 1, true case "Umacr": // LATIN CAPITAL LETTER U WITH MACRON - return rune(0x016a), true + return {'\u016a', 0}, 1, true case "UnderBar": // LOW LINE - return rune(0x5f), true + return {'_', 0}, 1, true case "UnderBrace": // BOTTOM CURLY BRACKET - return rune(0x23df), true + return {'\u23df', 0}, 1, true case "UnderBracket": // BOTTOM SQUARE BRACKET - return rune(0x23b5), true + return {'\u23b5', 0}, 1, true case "UnderParenthesis": // BOTTOM PARENTHESIS - return rune(0x23dd), true + return {'\u23dd', 0}, 1, true case "Union": // N-ARY UNION - return rune(0x22c3), true + return {'\u22c3', 0}, 1, true case "UnionPlus": // MULTISET UNION - return rune(0x228e), true + return {'\u228e', 0}, 1, true case "Uogon": // LATIN CAPITAL LETTER U WITH OGONEK - return rune(0x0172), true + return {'\u0172', 0}, 1, true case "Uopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL U - return rune(0x01d54c), true + return {'\U0001d54c', 0}, 1, true case "UpArrow": // UPWARDS ARROW - return rune(0x2191), true + return {'\u2191', 0}, 1, true case "UpArrowBar": // UPWARDS ARROW TO BAR - return rune(0x2912), true + return {'\u2912', 0}, 1, true case "UpArrowDownArrow": // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW - return rune(0x21c5), true + return {'\u21c5', 0}, 1, true case "UpDownArrow": // UP DOWN ARROW - return rune(0x2195), true + return {'\u2195', 0}, 1, true case "UpEquilibrium": // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - return rune(0x296e), true + return {'\u296e', 0}, 1, true case "UpTee": // UP TACK - return rune(0x22a5), true + return {'\u22a5', 0}, 1, true case "UpTeeArrow": // UPWARDS ARROW FROM BAR - return rune(0x21a5), true + return {'\u21a5', 0}, 1, true case "Uparrow": // UPWARDS DOUBLE ARROW - return rune(0x21d1), true + return {'\u21d1', 0}, 1, true case "Updownarrow": // UP DOWN DOUBLE ARROW - return rune(0x21d5), true + return {'\u21d5', 0}, 1, true case "UpperLeftArrow": // NORTH WEST ARROW - return rune(0x2196), true + return {'\u2196', 0}, 1, true case "UpperRightArrow": // NORTH EAST ARROW - return rune(0x2197), true + return {'\u2197', 0}, 1, true case "Upsi": // GREEK UPSILON WITH HOOK SYMBOL - return rune(0x03d2), true + return {'\u03d2', 0}, 1, true case "Upsilon": // GREEK CAPITAL LETTER UPSILON - return rune(0x03a5), true + return {'\u03a5', 0}, 1, true case "Uring": // LATIN CAPITAL LETTER U WITH RING ABOVE - return rune(0x016e), true + return {'\u016e', 0}, 1, true case "Uscr": // MATHEMATICAL SCRIPT CAPITAL U - return rune(0x01d4b0), true + return {'\U0001d4b0', 0}, 1, true case "Utilde": // LATIN CAPITAL LETTER U WITH TILDE - return rune(0x0168), true + return {'\u0168', 0}, 1, true case "Uuml": // LATIN CAPITAL LETTER U WITH DIAERESIS - return rune(0xdc), true + return {'Ü', 0}, 1, true } case 'V': switch name { case "VDash": // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE - return rune(0x22ab), true + return {'\u22ab', 0}, 1, true case "Vbar": // DOUBLE UP TACK - return rune(0x2aeb), true + return {'\u2aeb', 0}, 1, true case "Vcy": // CYRILLIC CAPITAL LETTER VE - return rune(0x0412), true + return {'\u0412', 0}, 1, true case "Vdash": // FORCES - return rune(0x22a9), true + return {'\u22a9', 0}, 1, true case "Vdashl": // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL - return rune(0x2ae6), true + return {'\u2ae6', 0}, 1, true case "Vee": // N-ARY LOGICAL OR - return rune(0x22c1), true + return {'\u22c1', 0}, 1, true case "Verbar": // DOUBLE VERTICAL LINE - return rune(0x2016), true + return {'\u2016', 0}, 1, true case "Vert": // DOUBLE VERTICAL LINE - return rune(0x2016), true + return {'\u2016', 0}, 1, true case "VerticalBar": // DIVIDES - return rune(0x2223), true + return {'\u2223', 0}, 1, true case "VerticalLine": // VERTICAL LINE - return rune(0x7c), true + return {'|', 0}, 1, true case "VerticalSeparator": // LIGHT VERTICAL BAR - return rune(0x2758), true + return {'\u2758', 0}, 1, true case "VerticalTilde": // WREATH PRODUCT - return rune(0x2240), true + return {'\u2240', 0}, 1, true case "VeryThinSpace": // HAIR SPACE - return rune(0x200a), true + return {'\u200a', 0}, 1, true case "Vfr": // MATHEMATICAL FRAKTUR CAPITAL V - return rune(0x01d519), true + return {'\U0001d519', 0}, 1, true case "Vopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL V - return rune(0x01d54d), true + return {'\U0001d54d', 0}, 1, true case "Vscr": // MATHEMATICAL SCRIPT CAPITAL V - return rune(0x01d4b1), true + return {'\U0001d4b1', 0}, 1, true case "Vvdash": // TRIPLE VERTICAL BAR RIGHT TURNSTILE - return rune(0x22aa), true + return {'\u22aa', 0}, 1, true } case 'W': switch name { case "Wcirc": // LATIN CAPITAL LETTER W WITH CIRCUMFLEX - return rune(0x0174), true + return {'\u0174', 0}, 1, true case "Wedge": // N-ARY LOGICAL AND - return rune(0x22c0), true + return {'\u22c0', 0}, 1, true case "Wfr": // MATHEMATICAL FRAKTUR CAPITAL W - return rune(0x01d51a), true + return {'\U0001d51a', 0}, 1, true case "Wopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL W - return rune(0x01d54e), true + return {'\U0001d54e', 0}, 1, true case "Wscr": // MATHEMATICAL SCRIPT CAPITAL W - return rune(0x01d4b2), true + return {'\U0001d4b2', 0}, 1, true } case 'X': switch name { case "Xfr": // MATHEMATICAL FRAKTUR CAPITAL X - return rune(0x01d51b), true + return {'\U0001d51b', 0}, 1, true case "Xgr": // GREEK CAPITAL LETTER XI - return rune(0x039e), true + return {'\u039e', 0}, 1, true case "Xi": // GREEK CAPITAL LETTER XI - return rune(0x039e), true + return {'\u039e', 0}, 1, true case "Xopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL X - return rune(0x01d54f), true + return {'\U0001d54f', 0}, 1, true case "Xscr": // MATHEMATICAL SCRIPT CAPITAL X - return rune(0x01d4b3), true + return {'\U0001d4b3', 0}, 1, true } case 'Y': switch name { case "YAcy": // CYRILLIC CAPITAL LETTER YA - return rune(0x042f), true + return {'\u042f', 0}, 1, true case "YIcy": // CYRILLIC CAPITAL LETTER YI - return rune(0x0407), true + return {'\u0407', 0}, 1, true case "YUcy": // CYRILLIC CAPITAL LETTER YU - return rune(0x042e), true + return {'\u042e', 0}, 1, true case "Yacute": // LATIN CAPITAL LETTER Y WITH ACUTE - return rune(0xdd), true + return {'Ý', 0}, 1, true case "Ycirc": // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX - return rune(0x0176), true + return {'\u0176', 0}, 1, true case "Ycy": // CYRILLIC CAPITAL LETTER YERU - return rune(0x042b), true + return {'\u042b', 0}, 1, true case "Yfr": // MATHEMATICAL FRAKTUR CAPITAL Y - return rune(0x01d51c), true + return {'\U0001d51c', 0}, 1, true case "Yopf": // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y - return rune(0x01d550), true + return {'\U0001d550', 0}, 1, true case "Yscr": // MATHEMATICAL SCRIPT CAPITAL Y - return rune(0x01d4b4), true + return {'\U0001d4b4', 0}, 1, true case "Yuml": // LATIN CAPITAL LETTER Y WITH DIAERESIS - return rune(0x0178), true + return {'\u0178', 0}, 1, true } case 'Z': switch name { case "ZHcy": // CYRILLIC CAPITAL LETTER ZHE - return rune(0x0416), true + return {'\u0416', 0}, 1, true case "Zacute": // LATIN CAPITAL LETTER Z WITH ACUTE - return rune(0x0179), true + return {'\u0179', 0}, 1, true case "Zcaron": // LATIN CAPITAL LETTER Z WITH CARON - return rune(0x017d), true + return {'\u017d', 0}, 1, true case "Zcy": // CYRILLIC CAPITAL LETTER ZE - return rune(0x0417), true + return {'\u0417', 0}, 1, true case "Zdot": // LATIN CAPITAL LETTER Z WITH DOT ABOVE - return rune(0x017b), true + return {'\u017b', 0}, 1, true case "ZeroWidthSpace": // ZERO WIDTH SPACE - return rune(0x200b), true + return {'\u200b', 0}, 1, true case "Zeta": // GREEK CAPITAL LETTER ZETA - return rune(0x0396), true + return {'\u0396', 0}, 1, true case "Zfr": // BLACK-LETTER CAPITAL Z - return rune(0x2128), true + return {'\u2128', 0}, 1, true case "Zgr": // GREEK CAPITAL LETTER ZETA - return rune(0x0396), true + return {'\u0396', 0}, 1, true case "Zopf": // DOUBLE-STRUCK CAPITAL Z - return rune(0x2124), true + return {'\u2124', 0}, 1, true case "Zscr": // MATHEMATICAL SCRIPT CAPITAL Z - return rune(0x01d4b5), true + return {'\U0001d4b5', 0}, 1, true } case 'a': switch name { case "aacgr": // GREEK SMALL LETTER ALPHA WITH TONOS - return rune(0x03ac), true + return {'\u03ac', 0}, 1, true case "aacute": // LATIN SMALL LETTER A WITH ACUTE - return rune(0xe1), true + return {'á', 0}, 1, true case "abreve": // LATIN SMALL LETTER A WITH BREVE - return rune(0x0103), true + return {'\u0103', 0}, 1, true case "ac": // INVERTED LAZY S - return rune(0x223e), true + return {'\u223e', 0}, 1, true case "acE": // INVERTED LAZY S with double underline - return rune(0x223e), true + return {'\u223e', '\u0333'}, 2, true case "acd": // SINE WAVE - return rune(0x223f), true + return {'\u223f', 0}, 1, true case "acirc": // LATIN SMALL LETTER A WITH CIRCUMFLEX - return rune(0xe2), true + return {'â', 0}, 1, true case "actuary": // COMBINING ANNUITY SYMBOL - return rune(0x20e7), true + return {'\u20e7', 0}, 1, true case "acute": // ACUTE ACCENT - return rune(0xb4), true + return {'´', 0}, 1, true case "acy": // CYRILLIC SMALL LETTER A - return rune(0x0430), true + return {'\u0430', 0}, 1, true case "aelig": // LATIN SMALL LETTER AE - return rune(0xe6), true + return {'æ', 0}, 1, true case "af": // FUNCTION APPLICATION - return rune(0x2061), true + return {'\u2061', 0}, 1, true case "afr": // MATHEMATICAL FRAKTUR SMALL A - return rune(0x01d51e), true + return {'\U0001d51e', 0}, 1, true case "agr": // GREEK SMALL LETTER ALPHA - return rune(0x03b1), true + return {'\u03b1', 0}, 1, true case "agrave": // LATIN SMALL LETTER A WITH GRAVE - return rune(0xe0), true + return {'à', 0}, 1, true case "alefsym": // ALEF SYMBOL - return rune(0x2135), true + return {'\u2135', 0}, 1, true case "aleph": // ALEF SYMBOL - return rune(0x2135), true + return {'\u2135', 0}, 1, true case "alpha": // GREEK SMALL LETTER ALPHA - return rune(0x03b1), true + return {'\u03b1', 0}, 1, true case "amacr": // LATIN SMALL LETTER A WITH MACRON - return rune(0x0101), true + return {'\u0101', 0}, 1, true case "amalg": // AMALGAMATION OR COPRODUCT - return rune(0x2a3f), true + return {'\u2a3f', 0}, 1, true case "amp": // AMPERSAND - return rune(0x26), true + return {'&', 0}, 1, true case "and": // LOGICAL AND - return rune(0x2227), true + return {'\u2227', 0}, 1, true case "andand": // TWO INTERSECTING LOGICAL AND - return rune(0x2a55), true + return {'\u2a55', 0}, 1, true case "andd": // LOGICAL AND WITH HORIZONTAL DASH - return rune(0x2a5c), true + return {'\u2a5c', 0}, 1, true case "andslope": // SLOPING LARGE AND - return rune(0x2a58), true + return {'\u2a58', 0}, 1, true case "andv": // LOGICAL AND WITH MIDDLE STEM - return rune(0x2a5a), true + return {'\u2a5a', 0}, 1, true case "ang": // ANGLE - return rune(0x2220), true + return {'\u2220', 0}, 1, true case "ang90": // RIGHT ANGLE - return rune(0x221f), true + return {'\u221f', 0}, 1, true case "angdnl": // TURNED ANGLE - return rune(0x29a2), true + return {'\u29a2', 0}, 1, true case "angdnr": // ACUTE ANGLE - return rune(0x299f), true + return {'\u299f', 0}, 1, true case "ange": // ANGLE WITH UNDERBAR - return rune(0x29a4), true + return {'\u29a4', 0}, 1, true case "angle": // ANGLE - return rune(0x2220), true + return {'\u2220', 0}, 1, true case "angles": // ANGLE WITH S INSIDE - return rune(0x299e), true + return {'\u299e', 0}, 1, true case "angmsd": // MEASURED ANGLE - return rune(0x2221), true + return {'\u2221', 0}, 1, true case "angmsdaa": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT - return rune(0x29a8), true + return {'\u29a8', 0}, 1, true case "angmsdab": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT - return rune(0x29a9), true + return {'\u29a9', 0}, 1, true case "angmsdac": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT - return rune(0x29aa), true + return {'\u29aa', 0}, 1, true case "angmsdad": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT - return rune(0x29ab), true + return {'\u29ab', 0}, 1, true case "angmsdae": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP - return rune(0x29ac), true + return {'\u29ac', 0}, 1, true case "angmsdaf": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP - return rune(0x29ad), true + return {'\u29ad', 0}, 1, true case "angmsdag": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN - return rune(0x29ae), true + return {'\u29ae', 0}, 1, true case "angmsdah": // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN - return rune(0x29af), true + return {'\u29af', 0}, 1, true case "angrt": // RIGHT ANGLE - return rune(0x221f), true + return {'\u221f', 0}, 1, true case "angrtvb": // RIGHT ANGLE WITH ARC - return rune(0x22be), true + return {'\u22be', 0}, 1, true case "angrtvbd": // MEASURED RIGHT ANGLE WITH DOT - return rune(0x299d), true + return {'\u299d', 0}, 1, true case "angsph": // SPHERICAL ANGLE - return rune(0x2222), true + return {'\u2222', 0}, 1, true case "angst": // LATIN CAPITAL LETTER A WITH RING ABOVE - return rune(0xc5), true + return {'Å', 0}, 1, true case "angupl": // REVERSED ANGLE - return rune(0x29a3), true + return {'\u29a3', 0}, 1, true case "angzarr": // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW - return rune(0x237c), true + return {'\u237c', 0}, 1, true case "aogon": // LATIN SMALL LETTER A WITH OGONEK - return rune(0x0105), true + return {'\u0105', 0}, 1, true case "aopf": // MATHEMATICAL DOUBLE-STRUCK SMALL A - return rune(0x01d552), true + return {'\U0001d552', 0}, 1, true case "ap": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "apE": // APPROXIMATELY EQUAL OR EQUAL TO - return rune(0x2a70), true + return {'\u2a70', 0}, 1, true case "apacir": // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT - return rune(0x2a6f), true + return {'\u2a6f', 0}, 1, true case "ape": // ALMOST EQUAL OR EQUAL TO - return rune(0x224a), true + return {'\u224a', 0}, 1, true case "apid": // TRIPLE TILDE - return rune(0x224b), true + return {'\u224b', 0}, 1, true case "apos": // APOSTROPHE - return rune(0x27), true + return {'\'', 0}, 1, true case "approx": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "approxeq": // ALMOST EQUAL OR EQUAL TO - return rune(0x224a), true + return {'\u224a', 0}, 1, true case "aring": // LATIN SMALL LETTER A WITH RING ABOVE - return rune(0xe5), true + return {'å', 0}, 1, true case "arrllsr": // LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW - return rune(0x2943), true + return {'\u2943', 0}, 1, true case "arrlrsl": // RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW - return rune(0x2942), true + return {'\u2942', 0}, 1, true case "arrsrll": // SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW - return rune(0x2944), true + return {'\u2944', 0}, 1, true case "ascr": // MATHEMATICAL SCRIPT SMALL A - return rune(0x01d4b6), true + return {'\U0001d4b6', 0}, 1, true case "ast": // ASTERISK - return rune(0x2a), true + return {'*', 0}, 1, true case "astb": // SQUARED ASTERISK - return rune(0x29c6), true + return {'\u29c6', 0}, 1, true case "asymp": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "asympeq": // EQUIVALENT TO - return rune(0x224d), true + return {'\u224d', 0}, 1, true case "atilde": // LATIN SMALL LETTER A WITH TILDE - return rune(0xe3), true + return {'ã', 0}, 1, true case "auml": // LATIN SMALL LETTER A WITH DIAERESIS - return rune(0xe4), true + return {'ä', 0}, 1, true case "awconint": // ANTICLOCKWISE CONTOUR INTEGRAL - return rune(0x2233), true + return {'\u2233', 0}, 1, true case "awint": // ANTICLOCKWISE INTEGRATION - return rune(0x2a11), true + return {'\u2a11', 0}, 1, true } case 'b': switch name { case "b.Delta": // MATHEMATICAL BOLD CAPITAL DELTA - return rune(0x01d6ab), true + return {'\U0001d6ab', 0}, 1, true case "b.Gamma": // MATHEMATICAL BOLD CAPITAL GAMMA - return rune(0x01d6aa), true + return {'\U0001d6aa', 0}, 1, true case "b.Gammad": // MATHEMATICAL BOLD CAPITAL DIGAMMA - return rune(0x01d7ca), true + return {'\U0001d7ca', 0}, 1, true case "b.Lambda": // MATHEMATICAL BOLD CAPITAL LAMDA - return rune(0x01d6b2), true + return {'\U0001d6b2', 0}, 1, true case "b.Omega": // MATHEMATICAL BOLD CAPITAL OMEGA - return rune(0x01d6c0), true + return {'\U0001d6c0', 0}, 1, true case "b.Phi": // MATHEMATICAL BOLD CAPITAL PHI - return rune(0x01d6bd), true + return {'\U0001d6bd', 0}, 1, true case "b.Pi": // MATHEMATICAL BOLD CAPITAL PI - return rune(0x01d6b7), true + return {'\U0001d6b7', 0}, 1, true case "b.Psi": // MATHEMATICAL BOLD CAPITAL PSI - return rune(0x01d6bf), true + return {'\U0001d6bf', 0}, 1, true case "b.Sigma": // MATHEMATICAL BOLD CAPITAL SIGMA - return rune(0x01d6ba), true + return {'\U0001d6ba', 0}, 1, true case "b.Theta": // MATHEMATICAL BOLD CAPITAL THETA - return rune(0x01d6af), true + return {'\U0001d6af', 0}, 1, true case "b.Upsi": // MATHEMATICAL BOLD CAPITAL UPSILON - return rune(0x01d6bc), true + return {'\U0001d6bc', 0}, 1, true case "b.Xi": // MATHEMATICAL BOLD CAPITAL XI - return rune(0x01d6b5), true + return {'\U0001d6b5', 0}, 1, true case "b.alpha": // MATHEMATICAL BOLD SMALL ALPHA - return rune(0x01d6c2), true + return {'\U0001d6c2', 0}, 1, true case "b.beta": // MATHEMATICAL BOLD SMALL BETA - return rune(0x01d6c3), true + return {'\U0001d6c3', 0}, 1, true case "b.chi": // MATHEMATICAL BOLD SMALL CHI - return rune(0x01d6d8), true + return {'\U0001d6d8', 0}, 1, true case "b.delta": // MATHEMATICAL BOLD SMALL DELTA - return rune(0x01d6c5), true + return {'\U0001d6c5', 0}, 1, true case "b.epsi": // MATHEMATICAL BOLD SMALL EPSILON - return rune(0x01d6c6), true + return {'\U0001d6c6', 0}, 1, true case "b.epsiv": // MATHEMATICAL BOLD EPSILON SYMBOL - return rune(0x01d6dc), true + return {'\U0001d6dc', 0}, 1, true case "b.eta": // MATHEMATICAL BOLD SMALL ETA - return rune(0x01d6c8), true + return {'\U0001d6c8', 0}, 1, true case "b.gamma": // MATHEMATICAL BOLD SMALL GAMMA - return rune(0x01d6c4), true + return {'\U0001d6c4', 0}, 1, true case "b.gammad": // MATHEMATICAL BOLD SMALL DIGAMMA - return rune(0x01d7cb), true + return {'\U0001d7cb', 0}, 1, true case "b.iota": // MATHEMATICAL BOLD SMALL IOTA - return rune(0x01d6ca), true + return {'\U0001d6ca', 0}, 1, true case "b.kappa": // MATHEMATICAL BOLD SMALL KAPPA - return rune(0x01d6cb), true + return {'\U0001d6cb', 0}, 1, true case "b.kappav": // MATHEMATICAL BOLD KAPPA SYMBOL - return rune(0x01d6de), true + return {'\U0001d6de', 0}, 1, true case "b.lambda": // MATHEMATICAL BOLD SMALL LAMDA - return rune(0x01d6cc), true + return {'\U0001d6cc', 0}, 1, true case "b.mu": // MATHEMATICAL BOLD SMALL MU - return rune(0x01d6cd), true + return {'\U0001d6cd', 0}, 1, true case "b.nu": // MATHEMATICAL BOLD SMALL NU - return rune(0x01d6ce), true + return {'\U0001d6ce', 0}, 1, true case "b.omega": // MATHEMATICAL BOLD SMALL OMEGA - return rune(0x01d6da), true + return {'\U0001d6da', 0}, 1, true case "b.phi": // MATHEMATICAL BOLD SMALL PHI - return rune(0x01d6d7), true + return {'\U0001d6d7', 0}, 1, true case "b.phiv": // MATHEMATICAL BOLD PHI SYMBOL - return rune(0x01d6df), true + return {'\U0001d6df', 0}, 1, true case "b.pi": // MATHEMATICAL BOLD SMALL PI - return rune(0x01d6d1), true + return {'\U0001d6d1', 0}, 1, true case "b.piv": // MATHEMATICAL BOLD PI SYMBOL - return rune(0x01d6e1), true + return {'\U0001d6e1', 0}, 1, true case "b.psi": // MATHEMATICAL BOLD SMALL PSI - return rune(0x01d6d9), true + return {'\U0001d6d9', 0}, 1, true case "b.rho": // MATHEMATICAL BOLD SMALL RHO - return rune(0x01d6d2), true + return {'\U0001d6d2', 0}, 1, true case "b.rhov": // MATHEMATICAL BOLD RHO SYMBOL - return rune(0x01d6e0), true + return {'\U0001d6e0', 0}, 1, true case "b.sigma": // MATHEMATICAL BOLD SMALL SIGMA - return rune(0x01d6d4), true + return {'\U0001d6d4', 0}, 1, true case "b.sigmav": // MATHEMATICAL BOLD SMALL FINAL SIGMA - return rune(0x01d6d3), true + return {'\U0001d6d3', 0}, 1, true case "b.tau": // MATHEMATICAL BOLD SMALL TAU - return rune(0x01d6d5), true + return {'\U0001d6d5', 0}, 1, true case "b.thetas": // MATHEMATICAL BOLD SMALL THETA - return rune(0x01d6c9), true + return {'\U0001d6c9', 0}, 1, true case "b.thetav": // MATHEMATICAL BOLD THETA SYMBOL - return rune(0x01d6dd), true + return {'\U0001d6dd', 0}, 1, true case "b.upsi": // MATHEMATICAL BOLD SMALL UPSILON - return rune(0x01d6d6), true + return {'\U0001d6d6', 0}, 1, true case "b.xi": // MATHEMATICAL BOLD SMALL XI - return rune(0x01d6cf), true + return {'\U0001d6cf', 0}, 1, true case "b.zeta": // MATHEMATICAL BOLD SMALL ZETA - return rune(0x01d6c7), true + return {'\U0001d6c7', 0}, 1, true case "bNot": // REVERSED DOUBLE STROKE NOT SIGN - return rune(0x2aed), true + return {'\u2aed', 0}, 1, true case "backcong": // ALL EQUAL TO - return rune(0x224c), true + return {'\u224c', 0}, 1, true case "backepsilon": // GREEK REVERSED LUNATE EPSILON SYMBOL - return rune(0x03f6), true + return {'\u03f6', 0}, 1, true case "backprime": // REVERSED PRIME - return rune(0x2035), true + return {'\u2035', 0}, 1, true case "backsim": // REVERSED TILDE - return rune(0x223d), true + return {'\u223d', 0}, 1, true case "backsimeq": // REVERSED TILDE EQUALS - return rune(0x22cd), true + return {'\u22cd', 0}, 1, true case "barV": // DOUBLE DOWN TACK - return rune(0x2aea), true + return {'\u2aea', 0}, 1, true case "barvee": // NOR - return rune(0x22bd), true + return {'\u22bd', 0}, 1, true case "barwed": // PROJECTIVE - return rune(0x2305), true + return {'\u2305', 0}, 1, true case "barwedge": // PROJECTIVE - return rune(0x2305), true + return {'\u2305', 0}, 1, true case "bbrk": // BOTTOM SQUARE BRACKET - return rune(0x23b5), true + return {'\u23b5', 0}, 1, true case "bbrktbrk": // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET - return rune(0x23b6), true + return {'\u23b6', 0}, 1, true case "bcong": // ALL EQUAL TO - return rune(0x224c), true + return {'\u224c', 0}, 1, true case "bcy": // CYRILLIC SMALL LETTER BE - return rune(0x0431), true + return {'\u0431', 0}, 1, true case "bdlhar": // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR - return rune(0x2961), true + return {'\u2961', 0}, 1, true case "bdquo": // DOUBLE LOW-9 QUOTATION MARK - return rune(0x201e), true + return {'\u201e', 0}, 1, true case "bdrhar": // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR - return rune(0x295d), true + return {'\u295d', 0}, 1, true case "becaus": // BECAUSE - return rune(0x2235), true + return {'\u2235', 0}, 1, true case "because": // BECAUSE - return rune(0x2235), true + return {'\u2235', 0}, 1, true case "bemptyv": // REVERSED EMPTY SET - return rune(0x29b0), true + return {'\u29b0', 0}, 1, true case "bepsi": // GREEK REVERSED LUNATE EPSILON SYMBOL - return rune(0x03f6), true + return {'\u03f6', 0}, 1, true case "bernou": // SCRIPT CAPITAL B - return rune(0x212c), true + return {'\u212c', 0}, 1, true case "beta": // GREEK SMALL LETTER BETA - return rune(0x03b2), true + return {'\u03b2', 0}, 1, true case "beth": // BET SYMBOL - return rune(0x2136), true + return {'\u2136', 0}, 1, true case "between": // BETWEEN - return rune(0x226c), true + return {'\u226c', 0}, 1, true case "bfr": // MATHEMATICAL FRAKTUR SMALL B - return rune(0x01d51f), true + return {'\U0001d51f', 0}, 1, true case "bgr": // GREEK SMALL LETTER BETA - return rune(0x03b2), true + return {'\u03b2', 0}, 1, true case "bigcap": // N-ARY INTERSECTION - return rune(0x22c2), true + return {'\u22c2', 0}, 1, true case "bigcirc": // LARGE CIRCLE - return rune(0x25ef), true + return {'\u25ef', 0}, 1, true case "bigcup": // N-ARY UNION - return rune(0x22c3), true + return {'\u22c3', 0}, 1, true case "bigodot": // N-ARY CIRCLED DOT OPERATOR - return rune(0x2a00), true + return {'\u2a00', 0}, 1, true case "bigoplus": // N-ARY CIRCLED PLUS OPERATOR - return rune(0x2a01), true + return {'\u2a01', 0}, 1, true case "bigotimes": // N-ARY CIRCLED TIMES OPERATOR - return rune(0x2a02), true + return {'\u2a02', 0}, 1, true case "bigsqcup": // N-ARY SQUARE UNION OPERATOR - return rune(0x2a06), true + return {'\u2a06', 0}, 1, true case "bigstar": // BLACK STAR - return rune(0x2605), true + return {'\u2605', 0}, 1, true case "bigtriangledown": // WHITE DOWN-POINTING TRIANGLE - return rune(0x25bd), true + return {'\u25bd', 0}, 1, true case "bigtriangleup": // WHITE UP-POINTING TRIANGLE - return rune(0x25b3), true + return {'\u25b3', 0}, 1, true case "biguplus": // N-ARY UNION OPERATOR WITH PLUS - return rune(0x2a04), true + return {'\u2a04', 0}, 1, true case "bigvee": // N-ARY LOGICAL OR - return rune(0x22c1), true + return {'\u22c1', 0}, 1, true case "bigwedge": // N-ARY LOGICAL AND - return rune(0x22c0), true + return {'\u22c0', 0}, 1, true case "bkarow": // RIGHTWARDS DOUBLE DASH ARROW - return rune(0x290d), true + return {'\u290d', 0}, 1, true case "blacklozenge": // BLACK LOZENGE - return rune(0x29eb), true + return {'\u29eb', 0}, 1, true case "blacksquare": // BLACK SMALL SQUARE - return rune(0x25aa), true + return {'\u25aa', 0}, 1, true case "blacktriangle": // BLACK UP-POINTING SMALL TRIANGLE - return rune(0x25b4), true + return {'\u25b4', 0}, 1, true case "blacktriangledown": // BLACK DOWN-POINTING SMALL TRIANGLE - return rune(0x25be), true + return {'\u25be', 0}, 1, true case "blacktriangleleft": // BLACK LEFT-POINTING SMALL TRIANGLE - return rune(0x25c2), true + return {'\u25c2', 0}, 1, true case "blacktriangleright": // BLACK RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b8), true + return {'\u25b8', 0}, 1, true case "blank": // BLANK SYMBOL - return rune(0x2422), true + return {'\u2422', 0}, 1, true case "bldhar": // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR - return rune(0x295e), true + return {'\u295e', 0}, 1, true case "blk12": // MEDIUM SHADE - return rune(0x2592), true + return {'\u2592', 0}, 1, true case "blk14": // LIGHT SHADE - return rune(0x2591), true + return {'\u2591', 0}, 1, true case "blk34": // DARK SHADE - return rune(0x2593), true + return {'\u2593', 0}, 1, true case "block": // FULL BLOCK - return rune(0x2588), true + return {'\u2588', 0}, 1, true case "bluhar": // LEFTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295a), true + return {'\u295a', 0}, 1, true case "bne": // EQUALS SIGN with reverse slash - return rune(0x3d), true + return {'=', '\u20e5'}, 2, true case "bnequiv": // IDENTICAL TO with reverse slash - return rune(0x2261), true + return {'\u2261', '\u20e5'}, 2, true case "bnot": // REVERSED NOT SIGN - return rune(0x2310), true + return {'\u2310', 0}, 1, true case "bopf": // MATHEMATICAL DOUBLE-STRUCK SMALL B - return rune(0x01d553), true + return {'\U0001d553', 0}, 1, true case "bot": // UP TACK - return rune(0x22a5), true + return {'\u22a5', 0}, 1, true case "bottom": // UP TACK - return rune(0x22a5), true + return {'\u22a5', 0}, 1, true case "bowtie": // BOWTIE - return rune(0x22c8), true + return {'\u22c8', 0}, 1, true case "boxDL": // BOX DRAWINGS DOUBLE DOWN AND LEFT - return rune(0x2557), true + return {'\u2557', 0}, 1, true case "boxDR": // BOX DRAWINGS DOUBLE DOWN AND RIGHT - return rune(0x2554), true + return {'\u2554', 0}, 1, true case "boxDl": // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - return rune(0x2556), true + return {'\u2556', 0}, 1, true case "boxDr": // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - return rune(0x2553), true + return {'\u2553', 0}, 1, true case "boxH": // BOX DRAWINGS DOUBLE HORIZONTAL - return rune(0x2550), true + return {'\u2550', 0}, 1, true case "boxHD": // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - return rune(0x2566), true + return {'\u2566', 0}, 1, true case "boxHU": // BOX DRAWINGS DOUBLE UP AND HORIZONTAL - return rune(0x2569), true + return {'\u2569', 0}, 1, true case "boxHd": // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - return rune(0x2564), true + return {'\u2564', 0}, 1, true case "boxHu": // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - return rune(0x2567), true + return {'\u2567', 0}, 1, true case "boxUL": // BOX DRAWINGS DOUBLE UP AND LEFT - return rune(0x255d), true + return {'\u255d', 0}, 1, true case "boxUR": // BOX DRAWINGS DOUBLE UP AND RIGHT - return rune(0x255a), true + return {'\u255a', 0}, 1, true case "boxUl": // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - return rune(0x255c), true + return {'\u255c', 0}, 1, true case "boxUr": // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - return rune(0x2559), true + return {'\u2559', 0}, 1, true case "boxV": // BOX DRAWINGS DOUBLE VERTICAL - return rune(0x2551), true + return {'\u2551', 0}, 1, true case "boxVH": // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - return rune(0x256c), true + return {'\u256c', 0}, 1, true case "boxVL": // BOX DRAWINGS DOUBLE VERTICAL AND LEFT - return rune(0x2563), true + return {'\u2563', 0}, 1, true case "boxVR": // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - return rune(0x2560), true + return {'\u2560', 0}, 1, true case "boxVh": // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - return rune(0x256b), true + return {'\u256b', 0}, 1, true case "boxVl": // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - return rune(0x2562), true + return {'\u2562', 0}, 1, true case "boxVr": // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - return rune(0x255f), true + return {'\u255f', 0}, 1, true case "boxbox": // TWO JOINED SQUARES - return rune(0x29c9), true + return {'\u29c9', 0}, 1, true case "boxdL": // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - return rune(0x2555), true + return {'\u2555', 0}, 1, true case "boxdR": // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE - return rune(0x2552), true + return {'\u2552', 0}, 1, true case "boxdl": // BOX DRAWINGS LIGHT DOWN AND LEFT - return rune(0x2510), true + return {'\u2510', 0}, 1, true case "boxdr": // BOX DRAWINGS LIGHT DOWN AND RIGHT - return rune(0x250c), true + return {'\u250c', 0}, 1, true case "boxh": // BOX DRAWINGS LIGHT HORIZONTAL - return rune(0x2500), true + return {'\u2500', 0}, 1, true case "boxhD": // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - return rune(0x2565), true + return {'\u2565', 0}, 1, true case "boxhU": // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - return rune(0x2568), true + return {'\u2568', 0}, 1, true case "boxhd": // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - return rune(0x252c), true + return {'\u252c', 0}, 1, true case "boxhu": // BOX DRAWINGS LIGHT UP AND HORIZONTAL - return rune(0x2534), true + return {'\u2534', 0}, 1, true case "boxminus": // SQUARED MINUS - return rune(0x229f), true + return {'\u229f', 0}, 1, true case "boxplus": // SQUARED PLUS - return rune(0x229e), true + return {'\u229e', 0}, 1, true case "boxtimes": // SQUARED TIMES - return rune(0x22a0), true + return {'\u22a0', 0}, 1, true case "boxuL": // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - return rune(0x255b), true + return {'\u255b', 0}, 1, true case "boxuR": // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - return rune(0x2558), true + return {'\u2558', 0}, 1, true case "boxul": // BOX DRAWINGS LIGHT UP AND LEFT - return rune(0x2518), true + return {'\u2518', 0}, 1, true case "boxur": // BOX DRAWINGS LIGHT UP AND RIGHT - return rune(0x2514), true + return {'\u2514', 0}, 1, true case "boxv": // BOX DRAWINGS LIGHT VERTICAL - return rune(0x2502), true + return {'\u2502', 0}, 1, true case "boxvH": // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - return rune(0x256a), true + return {'\u256a', 0}, 1, true case "boxvL": // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - return rune(0x2561), true + return {'\u2561', 0}, 1, true case "boxvR": // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - return rune(0x255e), true + return {'\u255e', 0}, 1, true case "boxvh": // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - return rune(0x253c), true + return {'\u253c', 0}, 1, true case "boxvl": // BOX DRAWINGS LIGHT VERTICAL AND LEFT - return rune(0x2524), true + return {'\u2524', 0}, 1, true case "boxvr": // BOX DRAWINGS LIGHT VERTICAL AND RIGHT - return rune(0x251c), true + return {'\u251c', 0}, 1, true case "bprime": // REVERSED PRIME - return rune(0x2035), true + return {'\u2035', 0}, 1, true case "brdhar": // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR - return rune(0x295f), true + return {'\u295f', 0}, 1, true case "breve": // BREVE - return rune(0x02d8), true + return {'\u02d8', 0}, 1, true case "bruhar": // RIGHTWARDS HARPOON WITH BARB UP FROM BAR - return rune(0x295b), true + return {'\u295b', 0}, 1, true case "brvbar": // BROKEN BAR - return rune(0xa6), true + return {'¦', 0}, 1, true case "bscr": // MATHEMATICAL SCRIPT SMALL B - return rune(0x01d4b7), true + return {'\U0001d4b7', 0}, 1, true case "bsemi": // REVERSED SEMICOLON - return rune(0x204f), true + return {'\u204f', 0}, 1, true case "bsim": // REVERSED TILDE - return rune(0x223d), true + return {'\u223d', 0}, 1, true case "bsime": // REVERSED TILDE EQUALS - return rune(0x22cd), true + return {'\u22cd', 0}, 1, true case "bsol": // REVERSE SOLIDUS - return rune(0x5c), true + return {'\\', 0}, 1, true case "bsolb": // SQUARED FALLING DIAGONAL SLASH - return rune(0x29c5), true + return {'\u29c5', 0}, 1, true case "bsolhsub": // REVERSE SOLIDUS PRECEDING SUBSET - return rune(0x27c8), true + return {'\u27c8', 0}, 1, true case "btimes": // SEMIDIRECT PRODUCT WITH BOTTOM CLOSED - return rune(0x2a32), true + return {'\u2a32', 0}, 1, true case "bulhar": // UPWARDS HARPOON WITH BARB LEFT FROM BAR - return rune(0x2960), true + return {'\u2960', 0}, 1, true case "bull": // BULLET - return rune(0x2022), true + return {'\u2022', 0}, 1, true case "bullet": // BULLET - return rune(0x2022), true + return {'\u2022', 0}, 1, true case "bump": // GEOMETRICALLY EQUIVALENT TO - return rune(0x224e), true + return {'\u224e', 0}, 1, true case "bumpE": // EQUALS SIGN WITH BUMPY ABOVE - return rune(0x2aae), true + return {'\u2aae', 0}, 1, true case "bumpe": // DIFFERENCE BETWEEN - return rune(0x224f), true + return {'\u224f', 0}, 1, true case "bumpeq": // DIFFERENCE BETWEEN - return rune(0x224f), true + return {'\u224f', 0}, 1, true case "burhar": // UPWARDS HARPOON WITH BARB RIGHT FROM BAR - return rune(0x295c), true + return {'\u295c', 0}, 1, true } case 'c': switch name { case "cacute": // LATIN SMALL LETTER C WITH ACUTE - return rune(0x0107), true + return {'\u0107', 0}, 1, true case "cap": // INTERSECTION - return rune(0x2229), true + return {'\u2229', 0}, 1, true case "capand": // INTERSECTION WITH LOGICAL AND - return rune(0x2a44), true + return {'\u2a44', 0}, 1, true case "capbrcup": // INTERSECTION ABOVE BAR ABOVE UNION - return rune(0x2a49), true + return {'\u2a49', 0}, 1, true case "capcap": // INTERSECTION BESIDE AND JOINED WITH INTERSECTION - return rune(0x2a4b), true + return {'\u2a4b', 0}, 1, true case "capcup": // INTERSECTION ABOVE UNION - return rune(0x2a47), true + return {'\u2a47', 0}, 1, true case "capdot": // INTERSECTION WITH DOT - return rune(0x2a40), true + return {'\u2a40', 0}, 1, true case "capint": // INTEGRAL WITH INTERSECTION - return rune(0x2a19), true + return {'\u2a19', 0}, 1, true case "caps": // INTERSECTION with serifs - return rune(0x2229), true + return {'\u2229', '\ufe00'}, 2, true case "caret": // CARET INSERTION POINT - return rune(0x2041), true + return {'\u2041', 0}, 1, true case "caron": // CARON - return rune(0x02c7), true + return {'\u02c7', 0}, 1, true case "ccaps": // CLOSED INTERSECTION WITH SERIFS - return rune(0x2a4d), true + return {'\u2a4d', 0}, 1, true case "ccaron": // LATIN SMALL LETTER C WITH CARON - return rune(0x010d), true + return {'\u010d', 0}, 1, true case "ccedil": // LATIN SMALL LETTER C WITH CEDILLA - return rune(0xe7), true + return {'ç', 0}, 1, true case "ccirc": // LATIN SMALL LETTER C WITH CIRCUMFLEX - return rune(0x0109), true + return {'\u0109', 0}, 1, true case "ccups": // CLOSED UNION WITH SERIFS - return rune(0x2a4c), true + return {'\u2a4c', 0}, 1, true case "ccupssm": // CLOSED UNION WITH SERIFS AND SMASH PRODUCT - return rune(0x2a50), true + return {'\u2a50', 0}, 1, true case "cdot": // LATIN SMALL LETTER C WITH DOT ABOVE - return rune(0x010b), true + return {'\u010b', 0}, 1, true case "cedil": // CEDILLA - return rune(0xb8), true + return {'¸', 0}, 1, true case "cemptyv": // EMPTY SET WITH SMALL CIRCLE ABOVE - return rune(0x29b2), true + return {'\u29b2', 0}, 1, true case "cent": // CENT SIGN - return rune(0xa2), true + return {'¢', 0}, 1, true case "centerdot": // MIDDLE DOT - return rune(0xb7), true + return {'·', 0}, 1, true case "cfr": // MATHEMATICAL FRAKTUR SMALL C - return rune(0x01d520), true + return {'\U0001d520', 0}, 1, true case "chcy": // CYRILLIC SMALL LETTER CHE - return rune(0x0447), true + return {'\u0447', 0}, 1, true case "check": // CHECK MARK - return rune(0x2713), true + return {'\u2713', 0}, 1, true case "checkmark": // CHECK MARK - return rune(0x2713), true + return {'\u2713', 0}, 1, true case "chi": // GREEK SMALL LETTER CHI - return rune(0x03c7), true + return {'\u03c7', 0}, 1, true case "cir": // WHITE CIRCLE - return rune(0x25cb), true + return {'\u25cb', 0}, 1, true case "cirE": // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT - return rune(0x29c3), true + return {'\u29c3', 0}, 1, true case "cirb": // SQUARED SMALL CIRCLE - return rune(0x29c7), true + return {'\u29c7', 0}, 1, true case "circ": // MODIFIER LETTER CIRCUMFLEX ACCENT - return rune(0x02c6), true + return {'\u02c6', 0}, 1, true case "circeq": // RING EQUAL TO - return rune(0x2257), true + return {'\u2257', 0}, 1, true case "circlearrowleft": // ANTICLOCKWISE OPEN CIRCLE ARROW - return rune(0x21ba), true + return {'\u21ba', 0}, 1, true case "circlearrowright": // CLOCKWISE OPEN CIRCLE ARROW - return rune(0x21bb), true + return {'\u21bb', 0}, 1, true case "circledR": // REGISTERED SIGN - return rune(0xae), true + return {'®', 0}, 1, true case "circledS": // CIRCLED LATIN CAPITAL LETTER S - return rune(0x24c8), true + return {'\u24c8', 0}, 1, true case "circledast": // CIRCLED ASTERISK OPERATOR - return rune(0x229b), true + return {'\u229b', 0}, 1, true case "circledcirc": // CIRCLED RING OPERATOR - return rune(0x229a), true + return {'\u229a', 0}, 1, true case "circleddash": // CIRCLED DASH - return rune(0x229d), true + return {'\u229d', 0}, 1, true case "cirdarr": // WHITE CIRCLE WITH DOWN ARROW - return rune(0x29ec), true + return {'\u29ec', 0}, 1, true case "cire": // RING EQUAL TO - return rune(0x2257), true + return {'\u2257', 0}, 1, true case "cirerr": // ERROR-BARRED WHITE CIRCLE - return rune(0x29f2), true + return {'\u29f2', 0}, 1, true case "cirfdarr": // BLACK CIRCLE WITH DOWN ARROW - return rune(0x29ed), true + return {'\u29ed', 0}, 1, true case "cirferr": // ERROR-BARRED BLACK CIRCLE - return rune(0x29f3), true + return {'\u29f3', 0}, 1, true case "cirfnint": // CIRCULATION FUNCTION - return rune(0x2a10), true + return {'\u2a10', 0}, 1, true case "cirmid": // VERTICAL LINE WITH CIRCLE ABOVE - return rune(0x2aef), true + return {'\u2aef', 0}, 1, true case "cirscir": // CIRCLE WITH SMALL CIRCLE TO THE RIGHT - return rune(0x29c2), true + return {'\u29c2', 0}, 1, true case "closur": // CLOSE UP - return rune(0x2050), true + return {'\u2050', 0}, 1, true case "clubs": // BLACK CLUB SUIT - return rune(0x2663), true + return {'\u2663', 0}, 1, true case "clubsuit": // BLACK CLUB SUIT - return rune(0x2663), true + return {'\u2663', 0}, 1, true case "colon": // COLON - return rune(0x3a), true + return {':', 0}, 1, true case "colone": // COLON EQUALS - return rune(0x2254), true + return {'\u2254', 0}, 1, true case "coloneq": // COLON EQUALS - return rune(0x2254), true + return {'\u2254', 0}, 1, true case "comma": // COMMA - return rune(0x2c), true + return {',', 0}, 1, true case "commat": // COMMERCIAL AT - return rune(0x40), true + return {'@', 0}, 1, true case "comp": // COMPLEMENT - return rune(0x2201), true + return {'\u2201', 0}, 1, true case "compfn": // RING OPERATOR - return rune(0x2218), true + return {'\u2218', 0}, 1, true case "complement": // COMPLEMENT - return rune(0x2201), true + return {'\u2201', 0}, 1, true case "complexes": // DOUBLE-STRUCK CAPITAL C - return rune(0x2102), true + return {'\u2102', 0}, 1, true case "cong": // APPROXIMATELY EQUAL TO - return rune(0x2245), true + return {'\u2245', 0}, 1, true case "congdot": // CONGRUENT WITH DOT ABOVE - return rune(0x2a6d), true + return {'\u2a6d', 0}, 1, true case "conint": // CONTOUR INTEGRAL - return rune(0x222e), true + return {'\u222e', 0}, 1, true case "copf": // MATHEMATICAL DOUBLE-STRUCK SMALL C - return rune(0x01d554), true + return {'\U0001d554', 0}, 1, true case "coprod": // N-ARY COPRODUCT - return rune(0x2210), true + return {'\u2210', 0}, 1, true case "copy": // COPYRIGHT SIGN - return rune(0xa9), true + return {'©', 0}, 1, true case "copysr": // SOUND RECORDING COPYRIGHT - return rune(0x2117), true + return {'\u2117', 0}, 1, true case "crarr": // DOWNWARDS ARROW WITH CORNER LEFTWARDS - return rune(0x21b5), true + return {'\u21b5', 0}, 1, true case "cross": // BALLOT X - return rune(0x2717), true + return {'\u2717', 0}, 1, true case "cscr": // MATHEMATICAL SCRIPT SMALL C - return rune(0x01d4b8), true + return {'\U0001d4b8', 0}, 1, true case "csub": // CLOSED SUBSET - return rune(0x2acf), true + return {'\u2acf', 0}, 1, true case "csube": // CLOSED SUBSET OR EQUAL TO - return rune(0x2ad1), true + return {'\u2ad1', 0}, 1, true case "csup": // CLOSED SUPERSET - return rune(0x2ad0), true + return {'\u2ad0', 0}, 1, true case "csupe": // CLOSED SUPERSET OR EQUAL TO - return rune(0x2ad2), true + return {'\u2ad2', 0}, 1, true case "ctdot": // MIDLINE HORIZONTAL ELLIPSIS - return rune(0x22ef), true + return {'\u22ef', 0}, 1, true case "cudarrl": // RIGHT-SIDE ARC CLOCKWISE ARROW - return rune(0x2938), true + return {'\u2938', 0}, 1, true case "cudarrr": // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS - return rune(0x2935), true + return {'\u2935', 0}, 1, true case "cuepr": // EQUAL TO OR PRECEDES - return rune(0x22de), true + return {'\u22de', 0}, 1, true case "cuesc": // EQUAL TO OR SUCCEEDS - return rune(0x22df), true + return {'\u22df', 0}, 1, true case "cularr": // ANTICLOCKWISE TOP SEMICIRCLE ARROW - return rune(0x21b6), true + return {'\u21b6', 0}, 1, true case "cularrp": // TOP ARC ANTICLOCKWISE ARROW WITH PLUS - return rune(0x293d), true + return {'\u293d', 0}, 1, true case "cup": // UNION - return rune(0x222a), true + return {'\u222a', 0}, 1, true case "cupbrcap": // UNION ABOVE BAR ABOVE INTERSECTION - return rune(0x2a48), true + return {'\u2a48', 0}, 1, true case "cupcap": // UNION ABOVE INTERSECTION - return rune(0x2a46), true + return {'\u2a46', 0}, 1, true case "cupcup": // UNION BESIDE AND JOINED WITH UNION - return rune(0x2a4a), true + return {'\u2a4a', 0}, 1, true case "cupdot": // MULTISET MULTIPLICATION - return rune(0x228d), true + return {'\u228d', 0}, 1, true case "cupint": // INTEGRAL WITH UNION - return rune(0x2a1a), true + return {'\u2a1a', 0}, 1, true case "cupor": // UNION WITH LOGICAL OR - return rune(0x2a45), true + return {'\u2a45', 0}, 1, true case "cupre": // PRECEDES OR EQUAL TO - return rune(0x227c), true + return {'\u227c', 0}, 1, true case "cups": // UNION with serifs - return rune(0x222a), true + return {'\u222a', '\ufe00'}, 2, true case "curarr": // CLOCKWISE TOP SEMICIRCLE ARROW - return rune(0x21b7), true + return {'\u21b7', 0}, 1, true case "curarrm": // TOP ARC CLOCKWISE ARROW WITH MINUS - return rune(0x293c), true + return {'\u293c', 0}, 1, true case "curlyeqprec": // EQUAL TO OR PRECEDES - return rune(0x22de), true + return {'\u22de', 0}, 1, true case "curlyeqsucc": // EQUAL TO OR SUCCEEDS - return rune(0x22df), true + return {'\u22df', 0}, 1, true case "curlyvee": // CURLY LOGICAL OR - return rune(0x22ce), true + return {'\u22ce', 0}, 1, true case "curlywedge": // CURLY LOGICAL AND - return rune(0x22cf), true + return {'\u22cf', 0}, 1, true case "curren": // CURRENCY SIGN - return rune(0xa4), true + return {'¤', 0}, 1, true case "curvearrowleft": // ANTICLOCKWISE TOP SEMICIRCLE ARROW - return rune(0x21b6), true + return {'\u21b6', 0}, 1, true case "curvearrowright": // CLOCKWISE TOP SEMICIRCLE ARROW - return rune(0x21b7), true + return {'\u21b7', 0}, 1, true case "cuvee": // CURLY LOGICAL OR - return rune(0x22ce), true + return {'\u22ce', 0}, 1, true case "cuwed": // CURLY LOGICAL AND - return rune(0x22cf), true + return {'\u22cf', 0}, 1, true case "cwconint": // CLOCKWISE CONTOUR INTEGRAL - return rune(0x2232), true + return {'\u2232', 0}, 1, true case "cwint": // CLOCKWISE INTEGRAL - return rune(0x2231), true + return {'\u2231', 0}, 1, true case "cylcty": // CYLINDRICITY - return rune(0x232d), true + return {'\u232d', 0}, 1, true } case 'd': switch name { case "dAarr": // DOWNWARDS TRIPLE ARROW - return rune(0x290b), true + return {'\u290b', 0}, 1, true case "dArr": // DOWNWARDS DOUBLE ARROW - return rune(0x21d3), true + return {'\u21d3', 0}, 1, true case "dHar": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - return rune(0x2965), true + return {'\u2965', 0}, 1, true case "dagger": // DAGGER - return rune(0x2020), true + return {'\u2020', 0}, 1, true case "dalembrt": // SQUARE WITH CONTOURED OUTLINE - return rune(0x29e0), true + return {'\u29e0', 0}, 1, true case "daleth": // DALET SYMBOL - return rune(0x2138), true + return {'\u2138', 0}, 1, true case "darr": // DOWNWARDS ARROW - return rune(0x2193), true + return {'\u2193', 0}, 1, true case "darr2": // DOWNWARDS PAIRED ARROWS - return rune(0x21ca), true + return {'\u21ca', 0}, 1, true case "darrb": // DOWNWARDS ARROW TO BAR - return rune(0x2913), true + return {'\u2913', 0}, 1, true case "darrln": // DOWNWARDS ARROW WITH HORIZONTAL STROKE - return rune(0x2908), true + return {'\u2908', 0}, 1, true case "dash": // HYPHEN - return rune(0x2010), true + return {'\u2010', 0}, 1, true case "dashV": // DOUBLE VERTICAL BAR LEFT TURNSTILE - return rune(0x2ae3), true + return {'\u2ae3', 0}, 1, true case "dashv": // LEFT TACK - return rune(0x22a3), true + return {'\u22a3', 0}, 1, true case "dbkarow": // RIGHTWARDS TRIPLE DASH ARROW - return rune(0x290f), true + return {'\u290f', 0}, 1, true case "dblac": // DOUBLE ACUTE ACCENT - return rune(0x02dd), true + return {'\u02dd', 0}, 1, true case "dcaron": // LATIN SMALL LETTER D WITH CARON - return rune(0x010f), true + return {'\u010f', 0}, 1, true case "dcy": // CYRILLIC SMALL LETTER DE - return rune(0x0434), true + return {'\u0434', 0}, 1, true case "dd": // DOUBLE-STRUCK ITALIC SMALL D - return rune(0x2146), true + return {'\u2146', 0}, 1, true case "ddagger": // DOUBLE DAGGER - return rune(0x2021), true + return {'\u2021', 0}, 1, true case "ddarr": // DOWNWARDS PAIRED ARROWS - return rune(0x21ca), true + return {'\u21ca', 0}, 1, true case "ddotseq": // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW - return rune(0x2a77), true + return {'\u2a77', 0}, 1, true case "deg": // DEGREE SIGN - return rune(0xb0), true + return {'°', 0}, 1, true case "delta": // GREEK SMALL LETTER DELTA - return rune(0x03b4), true + return {'\u03b4', 0}, 1, true case "demptyv": // EMPTY SET WITH OVERBAR - return rune(0x29b1), true + return {'\u29b1', 0}, 1, true case "dfisht": // DOWN FISH TAIL - return rune(0x297f), true + return {'\u297f', 0}, 1, true case "dfr": // MATHEMATICAL FRAKTUR SMALL D - return rune(0x01d521), true + return {'\U0001d521', 0}, 1, true case "dgr": // GREEK SMALL LETTER DELTA - return rune(0x03b4), true + return {'\u03b4', 0}, 1, true case "dharl": // DOWNWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21c3), true + return {'\u21c3', 0}, 1, true case "dharr": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21c2), true + return {'\u21c2', 0}, 1, true case "diam": // DIAMOND OPERATOR - return rune(0x22c4), true + return {'\u22c4', 0}, 1, true case "diamdarr": // BLACK DIAMOND WITH DOWN ARROW - return rune(0x29ea), true + return {'\u29ea', 0}, 1, true case "diamerr": // ERROR-BARRED WHITE DIAMOND - return rune(0x29f0), true + return {'\u29f0', 0}, 1, true case "diamerrf": // ERROR-BARRED BLACK DIAMOND - return rune(0x29f1), true + return {'\u29f1', 0}, 1, true case "diamond": // DIAMOND OPERATOR - return rune(0x22c4), true + return {'\u22c4', 0}, 1, true case "diamondsuit": // BLACK DIAMOND SUIT - return rune(0x2666), true + return {'\u2666', 0}, 1, true case "diams": // BLACK DIAMOND SUIT - return rune(0x2666), true + return {'\u2666', 0}, 1, true case "die": // DIAERESIS - return rune(0xa8), true + return {'¨', 0}, 1, true case "digamma": // GREEK SMALL LETTER DIGAMMA - return rune(0x03dd), true + return {'\u03dd', 0}, 1, true case "disin": // ELEMENT OF WITH LONG HORIZONTAL STROKE - return rune(0x22f2), true + return {'\u22f2', 0}, 1, true case "div": // DIVISION SIGN - return rune(0xf7), true + return {'÷', 0}, 1, true case "divide": // DIVISION SIGN - return rune(0xf7), true + return {'÷', 0}, 1, true case "divideontimes": // DIVISION TIMES - return rune(0x22c7), true + return {'\u22c7', 0}, 1, true case "divonx": // DIVISION TIMES - return rune(0x22c7), true + return {'\u22c7', 0}, 1, true case "djcy": // CYRILLIC SMALL LETTER DJE - return rune(0x0452), true + return {'\u0452', 0}, 1, true case "dlarr": // SOUTH WEST ARROW - return rune(0x2199), true + return {'\u2199', 0}, 1, true case "dlcorn": // BOTTOM LEFT CORNER - return rune(0x231e), true + return {'\u231e', 0}, 1, true case "dlcrop": // BOTTOM LEFT CROP - return rune(0x230d), true + return {'\u230d', 0}, 1, true case "dlharb": // DOWNWARDS HARPOON WITH BARB LEFT TO BAR - return rune(0x2959), true + return {'\u2959', 0}, 1, true case "dollar": // DOLLAR SIGN - return rune(0x24), true + return {'$', 0}, 1, true case "dopf": // MATHEMATICAL DOUBLE-STRUCK SMALL D - return rune(0x01d555), true + return {'\U0001d555', 0}, 1, true case "dot": // DOT ABOVE - return rune(0x02d9), true + return {'\u02d9', 0}, 1, true case "doteq": // APPROACHES THE LIMIT - return rune(0x2250), true + return {'\u2250', 0}, 1, true case "doteqdot": // GEOMETRICALLY EQUAL TO - return rune(0x2251), true + return {'\u2251', 0}, 1, true case "dotminus": // DOT MINUS - return rune(0x2238), true + return {'\u2238', 0}, 1, true case "dotplus": // DOT PLUS - return rune(0x2214), true + return {'\u2214', 0}, 1, true case "dotsquare": // SQUARED DOT OPERATOR - return rune(0x22a1), true + return {'\u22a1', 0}, 1, true case "doublebarwedge": // PERSPECTIVE - return rune(0x2306), true + return {'\u2306', 0}, 1, true case "downarrow": // DOWNWARDS ARROW - return rune(0x2193), true + return {'\u2193', 0}, 1, true case "downdownarrows": // DOWNWARDS PAIRED ARROWS - return rune(0x21ca), true + return {'\u21ca', 0}, 1, true case "downharpoonleft": // DOWNWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21c3), true + return {'\u21c3', 0}, 1, true case "downharpoonright": // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21c2), true + return {'\u21c2', 0}, 1, true case "drarr": // SOUTH EAST ARROW - return rune(0x2198), true + return {'\u2198', 0}, 1, true case "drbkarow": // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW - return rune(0x2910), true + return {'\u2910', 0}, 1, true case "drcorn": // BOTTOM RIGHT CORNER - return rune(0x231f), true + return {'\u231f', 0}, 1, true case "drcrop": // BOTTOM RIGHT CROP - return rune(0x230c), true + return {'\u230c', 0}, 1, true case "drharb": // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR - return rune(0x2955), true + return {'\u2955', 0}, 1, true case "dscr": // MATHEMATICAL SCRIPT SMALL D - return rune(0x01d4b9), true + return {'\U0001d4b9', 0}, 1, true case "dscy": // CYRILLIC SMALL LETTER DZE - return rune(0x0455), true + return {'\u0455', 0}, 1, true case "dsol": // SOLIDUS WITH OVERBAR - return rune(0x29f6), true + return {'\u29f6', 0}, 1, true case "dstrok": // LATIN SMALL LETTER D WITH STROKE - return rune(0x0111), true + return {'\u0111', 0}, 1, true case "dtdot": // DOWN RIGHT DIAGONAL ELLIPSIS - return rune(0x22f1), true + return {'\u22f1', 0}, 1, true case "dtri": // WHITE DOWN-POINTING SMALL TRIANGLE - return rune(0x25bf), true + return {'\u25bf', 0}, 1, true case "dtrif": // BLACK DOWN-POINTING SMALL TRIANGLE - return rune(0x25be), true + return {'\u25be', 0}, 1, true case "dtrilf": // DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK - return rune(0x29e8), true + return {'\u29e8', 0}, 1, true case "dtrirf": // DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK - return rune(0x29e9), true + return {'\u29e9', 0}, 1, true case "duarr": // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW - return rune(0x21f5), true + return {'\u21f5', 0}, 1, true case "duhar": // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - return rune(0x296f), true + return {'\u296f', 0}, 1, true case "dumap": // DOUBLE-ENDED MULTIMAP - return rune(0x29df), true + return {'\u29df', 0}, 1, true case "dwangle": // OBLIQUE ANGLE OPENING UP - return rune(0x29a6), true + return {'\u29a6', 0}, 1, true case "dzcy": // CYRILLIC SMALL LETTER DZHE - return rune(0x045f), true + return {'\u045f', 0}, 1, true case "dzigrarr": // LONG RIGHTWARDS SQUIGGLE ARROW - return rune(0x27ff), true + return {'\u27ff', 0}, 1, true } case 'e': switch name { case "eDDot": // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW - return rune(0x2a77), true + return {'\u2a77', 0}, 1, true case "eDot": // GEOMETRICALLY EQUAL TO - return rune(0x2251), true + return {'\u2251', 0}, 1, true case "eacgr": // GREEK SMALL LETTER EPSILON WITH TONOS - return rune(0x03ad), true + return {'\u03ad', 0}, 1, true case "eacute": // LATIN SMALL LETTER E WITH ACUTE - return rune(0xe9), true + return {'é', 0}, 1, true case "easter": // EQUALS WITH ASTERISK - return rune(0x2a6e), true + return {'\u2a6e', 0}, 1, true case "ecaron": // LATIN SMALL LETTER E WITH CARON - return rune(0x011b), true + return {'\u011b', 0}, 1, true case "ecir": // RING IN EQUAL TO - return rune(0x2256), true + return {'\u2256', 0}, 1, true case "ecirc": // LATIN SMALL LETTER E WITH CIRCUMFLEX - return rune(0xea), true + return {'ê', 0}, 1, true case "ecolon": // EQUALS COLON - return rune(0x2255), true + return {'\u2255', 0}, 1, true case "ecy": // CYRILLIC SMALL LETTER E - return rune(0x044d), true + return {'\u044d', 0}, 1, true case "edot": // LATIN SMALL LETTER E WITH DOT ABOVE - return rune(0x0117), true + return {'\u0117', 0}, 1, true case "ee": // DOUBLE-STRUCK ITALIC SMALL E - return rune(0x2147), true + return {'\u2147', 0}, 1, true case "eeacgr": // GREEK SMALL LETTER ETA WITH TONOS - return rune(0x03ae), true + return {'\u03ae', 0}, 1, true case "eegr": // GREEK SMALL LETTER ETA - return rune(0x03b7), true + return {'\u03b7', 0}, 1, true case "efDot": // APPROXIMATELY EQUAL TO OR THE IMAGE OF - return rune(0x2252), true + return {'\u2252', 0}, 1, true case "efr": // MATHEMATICAL FRAKTUR SMALL E - return rune(0x01d522), true + return {'\U0001d522', 0}, 1, true case "eg": // DOUBLE-LINE EQUAL TO OR GREATER-THAN - return rune(0x2a9a), true + return {'\u2a9a', 0}, 1, true case "egr": // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true + return {'\u03b5', 0}, 1, true case "egrave": // LATIN SMALL LETTER E WITH GRAVE - return rune(0xe8), true + return {'è', 0}, 1, true case "egs": // SLANTED EQUAL TO OR GREATER-THAN - return rune(0x2a96), true + return {'\u2a96', 0}, 1, true case "egsdot": // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE - return rune(0x2a98), true + return {'\u2a98', 0}, 1, true case "el": // DOUBLE-LINE EQUAL TO OR LESS-THAN - return rune(0x2a99), true + return {'\u2a99', 0}, 1, true case "elinters": // ELECTRICAL INTERSECTION - return rune(0x23e7), true + return {'\u23e7', 0}, 1, true case "ell": // SCRIPT SMALL L - return rune(0x2113), true + return {'\u2113', 0}, 1, true case "els": // SLANTED EQUAL TO OR LESS-THAN - return rune(0x2a95), true + return {'\u2a95', 0}, 1, true case "elsdot": // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE - return rune(0x2a97), true + return {'\u2a97', 0}, 1, true case "emacr": // LATIN SMALL LETTER E WITH MACRON - return rune(0x0113), true + return {'\u0113', 0}, 1, true case "empty": // EMPTY SET - return rune(0x2205), true + return {'\u2205', 0}, 1, true case "emptyset": // EMPTY SET - return rune(0x2205), true + return {'\u2205', 0}, 1, true case "emptyv": // EMPTY SET - return rune(0x2205), true + return {'\u2205', 0}, 1, true case "emsp": // EM SPACE - return rune(0x2003), true + return {'\u2003', 0}, 1, true case "emsp13": // THREE-PER-EM SPACE - return rune(0x2004), true + return {'\u2004', 0}, 1, true case "emsp14": // FOUR-PER-EM SPACE - return rune(0x2005), true + return {'\u2005', 0}, 1, true case "eng": // LATIN SMALL LETTER ENG - return rune(0x014b), true + return {'\u014b', 0}, 1, true case "ensp": // EN SPACE - return rune(0x2002), true + return {'\u2002', 0}, 1, true case "eogon": // LATIN SMALL LETTER E WITH OGONEK - return rune(0x0119), true + return {'\u0119', 0}, 1, true case "eopf": // MATHEMATICAL DOUBLE-STRUCK SMALL E - return rune(0x01d556), true + return {'\U0001d556', 0}, 1, true case "epar": // EQUAL AND PARALLEL TO - return rune(0x22d5), true + return {'\u22d5', 0}, 1, true case "eparsl": // EQUALS SIGN AND SLANTED PARALLEL - return rune(0x29e3), true + return {'\u29e3', 0}, 1, true case "eplus": // EQUALS SIGN ABOVE PLUS SIGN - return rune(0x2a71), true + return {'\u2a71', 0}, 1, true case "epsi": // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true + return {'\u03b5', 0}, 1, true case "epsilon": // GREEK SMALL LETTER EPSILON - return rune(0x03b5), true + return {'\u03b5', 0}, 1, true case "epsis": // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true + return {'\u03f5', 0}, 1, true case "epsiv": // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true + return {'\u03f5', 0}, 1, true case "eqcirc": // RING IN EQUAL TO - return rune(0x2256), true + return {'\u2256', 0}, 1, true case "eqcolon": // EQUALS COLON - return rune(0x2255), true + return {'\u2255', 0}, 1, true case "eqeq": // TWO CONSECUTIVE EQUALS SIGNS - return rune(0x2a75), true + return {'\u2a75', 0}, 1, true case "eqsim": // MINUS TILDE - return rune(0x2242), true + return {'\u2242', 0}, 1, true case "eqslantgtr": // SLANTED EQUAL TO OR GREATER-THAN - return rune(0x2a96), true + return {'\u2a96', 0}, 1, true case "eqslantless": // SLANTED EQUAL TO OR LESS-THAN - return rune(0x2a95), true + return {'\u2a95', 0}, 1, true case "equals": // EQUALS SIGN - return rune(0x3d), true + return {'=', 0}, 1, true case "equest": // QUESTIONED EQUAL TO - return rune(0x225f), true + return {'\u225f', 0}, 1, true case "equiv": // IDENTICAL TO - return rune(0x2261), true + return {'\u2261', 0}, 1, true case "equivDD": // EQUIVALENT WITH FOUR DOTS ABOVE - return rune(0x2a78), true + return {'\u2a78', 0}, 1, true case "eqvparsl": // IDENTICAL TO AND SLANTED PARALLEL - return rune(0x29e5), true + return {'\u29e5', 0}, 1, true case "erDot": // IMAGE OF OR APPROXIMATELY EQUAL TO - return rune(0x2253), true + return {'\u2253', 0}, 1, true case "erarr": // EQUALS SIGN ABOVE RIGHTWARDS ARROW - return rune(0x2971), true + return {'\u2971', 0}, 1, true case "escr": // SCRIPT SMALL E - return rune(0x212f), true + return {'\u212f', 0}, 1, true case "esdot": // APPROACHES THE LIMIT - return rune(0x2250), true + return {'\u2250', 0}, 1, true case "esim": // MINUS TILDE - return rune(0x2242), true + return {'\u2242', 0}, 1, true case "eta": // GREEK SMALL LETTER ETA - return rune(0x03b7), true + return {'\u03b7', 0}, 1, true case "eth": // LATIN SMALL LETTER ETH - return rune(0xf0), true + return {'ð', 0}, 1, true case "euml": // LATIN SMALL LETTER E WITH DIAERESIS - return rune(0xeb), true + return {'ë', 0}, 1, true case "euro": // EURO SIGN - return rune(0x20ac), true + return {'\u20ac', 0}, 1, true case "excl": // EXCLAMATION MARK - return rune(0x21), true + return {'!', 0}, 1, true case "exist": // THERE EXISTS - return rune(0x2203), true + return {'\u2203', 0}, 1, true case "expectation": // SCRIPT CAPITAL E - return rune(0x2130), true + return {'\u2130', 0}, 1, true case "exponentiale": // DOUBLE-STRUCK ITALIC SMALL E - return rune(0x2147), true + return {'\u2147', 0}, 1, true } case 'f': switch name { case "fallingdotseq": // APPROXIMATELY EQUAL TO OR THE IMAGE OF - return rune(0x2252), true + return {'\u2252', 0}, 1, true case "fbowtie": // BLACK BOWTIE - return rune(0x29d3), true + return {'\u29d3', 0}, 1, true case "fcy": // CYRILLIC SMALL LETTER EF - return rune(0x0444), true + return {'\u0444', 0}, 1, true case "fdiag": // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT - return rune(0x2572), true + return {'\u2572', 0}, 1, true case "fdiordi": // FALLING DIAGONAL CROSSING RISING DIAGONAL - return rune(0x292c), true + return {'\u292c', 0}, 1, true case "fdonearr": // FALLING DIAGONAL CROSSING NORTH EAST ARROW - return rune(0x292f), true + return {'\u292f', 0}, 1, true case "female": // FEMALE SIGN - return rune(0x2640), true + return {'\u2640', 0}, 1, true case "ffilig": // LATIN SMALL LIGATURE FFI - return rune(0xfb03), true + return {'\ufb03', 0}, 1, true case "fflig": // LATIN SMALL LIGATURE FF - return rune(0xfb00), true + return {'\ufb00', 0}, 1, true case "ffllig": // LATIN SMALL LIGATURE FFL - return rune(0xfb04), true + return {'\ufb04', 0}, 1, true case "ffr": // MATHEMATICAL FRAKTUR SMALL F - return rune(0x01d523), true + return {'\U0001d523', 0}, 1, true case "fhrglass": // BLACK HOURGLASS - return rune(0x29d7), true + return {'\u29d7', 0}, 1, true case "filig": // LATIN SMALL LIGATURE FI - return rune(0xfb01), true + return {'\ufb01', 0}, 1, true case "fjlig": // fj ligature - return rune(0x66), true + return {'f', 'j'}, 2, true case "flat": // MUSIC FLAT SIGN - return rune(0x266d), true + return {'\u266d', 0}, 1, true case "fllig": // LATIN SMALL LIGATURE FL - return rune(0xfb02), true + return {'\ufb02', 0}, 1, true case "fltns": // WHITE PARALLELOGRAM - return rune(0x25b1), true + return {'\u25b1', 0}, 1, true case "fnof": // LATIN SMALL LETTER F WITH HOOK - return rune(0x0192), true + return {'\u0192', 0}, 1, true case "fopf": // MATHEMATICAL DOUBLE-STRUCK SMALL F - return rune(0x01d557), true + return {'\U0001d557', 0}, 1, true case "forall": // FOR ALL - return rune(0x2200), true + return {'\u2200', 0}, 1, true case "fork": // PITCHFORK - return rune(0x22d4), true + return {'\u22d4', 0}, 1, true case "forkv": // ELEMENT OF OPENING DOWNWARDS - return rune(0x2ad9), true + return {'\u2ad9', 0}, 1, true case "fpartint": // FINITE PART INTEGRAL - return rune(0x2a0d), true + return {'\u2a0d', 0}, 1, true case "frac12": // VULGAR FRACTION ONE HALF - return rune(0xbd), true + return {'½', 0}, 1, true case "frac13": // VULGAR FRACTION ONE THIRD - return rune(0x2153), true + return {'\u2153', 0}, 1, true case "frac14": // VULGAR FRACTION ONE QUARTER - return rune(0xbc), true + return {'¼', 0}, 1, true case "frac15": // VULGAR FRACTION ONE FIFTH - return rune(0x2155), true + return {'\u2155', 0}, 1, true case "frac16": // VULGAR FRACTION ONE SIXTH - return rune(0x2159), true + return {'\u2159', 0}, 1, true case "frac18": // VULGAR FRACTION ONE EIGHTH - return rune(0x215b), true + return {'\u215b', 0}, 1, true case "frac23": // VULGAR FRACTION TWO THIRDS - return rune(0x2154), true + return {'\u2154', 0}, 1, true case "frac25": // VULGAR FRACTION TWO FIFTHS - return rune(0x2156), true + return {'\u2156', 0}, 1, true case "frac34": // VULGAR FRACTION THREE QUARTERS - return rune(0xbe), true + return {'¾', 0}, 1, true case "frac35": // VULGAR FRACTION THREE FIFTHS - return rune(0x2157), true + return {'\u2157', 0}, 1, true case "frac38": // VULGAR FRACTION THREE EIGHTHS - return rune(0x215c), true + return {'\u215c', 0}, 1, true case "frac45": // VULGAR FRACTION FOUR FIFTHS - return rune(0x2158), true + return {'\u2158', 0}, 1, true case "frac56": // VULGAR FRACTION FIVE SIXTHS - return rune(0x215a), true + return {'\u215a', 0}, 1, true case "frac58": // VULGAR FRACTION FIVE EIGHTHS - return rune(0x215d), true + return {'\u215d', 0}, 1, true case "frac78": // VULGAR FRACTION SEVEN EIGHTHS - return rune(0x215e), true + return {'\u215e', 0}, 1, true case "frasl": // FRACTION SLASH - return rune(0x2044), true + return {'\u2044', 0}, 1, true case "frown": // FROWN - return rune(0x2322), true + return {'\u2322', 0}, 1, true case "fscr": // MATHEMATICAL SCRIPT SMALL F - return rune(0x01d4bb), true + return {'\U0001d4bb', 0}, 1, true } case 'g': switch name { case "gE": // GREATER-THAN OVER EQUAL TO - return rune(0x2267), true + return {'\u2267', 0}, 1, true case "gEl": // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN - return rune(0x2a8c), true + return {'\u2a8c', 0}, 1, true case "gacute": // LATIN SMALL LETTER G WITH ACUTE - return rune(0x01f5), true + return {'\u01f5', 0}, 1, true case "gamma": // GREEK SMALL LETTER GAMMA - return rune(0x03b3), true + return {'\u03b3', 0}, 1, true case "gammad": // GREEK SMALL LETTER DIGAMMA - return rune(0x03dd), true + return {'\u03dd', 0}, 1, true case "gap": // GREATER-THAN OR APPROXIMATE - return rune(0x2a86), true + return {'\u2a86', 0}, 1, true case "gbreve": // LATIN SMALL LETTER G WITH BREVE - return rune(0x011f), true + return {'\u011f', 0}, 1, true case "gcedil": // LATIN SMALL LETTER G WITH CEDILLA - return rune(0x0123), true + return {'\u0123', 0}, 1, true case "gcirc": // LATIN SMALL LETTER G WITH CIRCUMFLEX - return rune(0x011d), true + return {'\u011d', 0}, 1, true case "gcy": // CYRILLIC SMALL LETTER GHE - return rune(0x0433), true + return {'\u0433', 0}, 1, true case "gdot": // LATIN SMALL LETTER G WITH DOT ABOVE - return rune(0x0121), true + return {'\u0121', 0}, 1, true case "ge": // GREATER-THAN OR EQUAL TO - return rune(0x2265), true + return {'\u2265', 0}, 1, true case "gel": // GREATER-THAN EQUAL TO OR LESS-THAN - return rune(0x22db), true + return {'\u22db', 0}, 1, true case "geq": // GREATER-THAN OR EQUAL TO - return rune(0x2265), true + return {'\u2265', 0}, 1, true case "geqq": // GREATER-THAN OVER EQUAL TO - return rune(0x2267), true + return {'\u2267', 0}, 1, true case "geqslant": // GREATER-THAN OR SLANTED EQUAL TO - return rune(0x2a7e), true + return {'\u2a7e', 0}, 1, true case "ges": // GREATER-THAN OR SLANTED EQUAL TO - return rune(0x2a7e), true + return {'\u2a7e', 0}, 1, true case "gescc": // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL - return rune(0x2aa9), true + return {'\u2aa9', 0}, 1, true case "gesdot": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE - return rune(0x2a80), true + return {'\u2a80', 0}, 1, true case "gesdoto": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE - return rune(0x2a82), true + return {'\u2a82', 0}, 1, true case "gesdotol": // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT - return rune(0x2a84), true + return {'\u2a84', 0}, 1, true case "gesl": // GREATER-THAN slanted EQUAL TO OR LESS-THAN - return rune(0x22db), true + return {'\u22db', '\ufe00'}, 2, true case "gesles": // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL - return rune(0x2a94), true + return {'\u2a94', 0}, 1, true case "gfr": // MATHEMATICAL FRAKTUR SMALL G - return rune(0x01d524), true + return {'\U0001d524', 0}, 1, true case "gg": // MUCH GREATER-THAN - return rune(0x226b), true + return {'\u226b', 0}, 1, true case "ggg": // VERY MUCH GREATER-THAN - return rune(0x22d9), true + return {'\u22d9', 0}, 1, true case "ggr": // GREEK SMALL LETTER GAMMA - return rune(0x03b3), true + return {'\u03b3', 0}, 1, true case "gimel": // GIMEL SYMBOL - return rune(0x2137), true + return {'\u2137', 0}, 1, true case "gjcy": // CYRILLIC SMALL LETTER GJE - return rune(0x0453), true + return {'\u0453', 0}, 1, true case "gl": // GREATER-THAN OR LESS-THAN - return rune(0x2277), true + return {'\u2277', 0}, 1, true case "glE": // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL - return rune(0x2a92), true + return {'\u2a92', 0}, 1, true case "gla": // GREATER-THAN BESIDE LESS-THAN - return rune(0x2aa5), true + return {'\u2aa5', 0}, 1, true case "glj": // GREATER-THAN OVERLAPPING LESS-THAN - return rune(0x2aa4), true + return {'\u2aa4', 0}, 1, true case "gnE": // GREATER-THAN BUT NOT EQUAL TO - return rune(0x2269), true + return {'\u2269', 0}, 1, true case "gnap": // GREATER-THAN AND NOT APPROXIMATE - return rune(0x2a8a), true + return {'\u2a8a', 0}, 1, true case "gnapprox": // GREATER-THAN AND NOT APPROXIMATE - return rune(0x2a8a), true + return {'\u2a8a', 0}, 1, true case "gne": // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a88), true + return {'\u2a88', 0}, 1, true case "gneq": // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a88), true + return {'\u2a88', 0}, 1, true case "gneqq": // GREATER-THAN BUT NOT EQUAL TO - return rune(0x2269), true + return {'\u2269', 0}, 1, true case "gnsim": // GREATER-THAN BUT NOT EQUIVALENT TO - return rune(0x22e7), true + return {'\u22e7', 0}, 1, true case "gopf": // MATHEMATICAL DOUBLE-STRUCK SMALL G - return rune(0x01d558), true + return {'\U0001d558', 0}, 1, true case "grave": // GRAVE ACCENT - return rune(0x60), true + return {'`', 0}, 1, true case "gscr": // SCRIPT SMALL G - return rune(0x210a), true + return {'\u210a', 0}, 1, true case "gsdot": // GREATER-THAN WITH DOT - return rune(0x22d7), true + return {'\u22d7', 0}, 1, true case "gsim": // GREATER-THAN OR EQUIVALENT TO - return rune(0x2273), true + return {'\u2273', 0}, 1, true case "gsime": // GREATER-THAN ABOVE SIMILAR OR EQUAL - return rune(0x2a8e), true + return {'\u2a8e', 0}, 1, true case "gsiml": // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN - return rune(0x2a90), true + return {'\u2a90', 0}, 1, true case "gt": // GREATER-THAN SIGN - return rune(0x3e), true + return {'>', 0}, 1, true case "gtcc": // GREATER-THAN CLOSED BY CURVE - return rune(0x2aa7), true + return {'\u2aa7', 0}, 1, true case "gtcir": // GREATER-THAN WITH CIRCLE INSIDE - return rune(0x2a7a), true + return {'\u2a7a', 0}, 1, true case "gtdot": // GREATER-THAN WITH DOT - return rune(0x22d7), true + return {'\u22d7', 0}, 1, true case "gtlPar": // DOUBLE LEFT ARC GREATER-THAN BRACKET - return rune(0x2995), true + return {'\u2995', 0}, 1, true case "gtquest": // GREATER-THAN WITH QUESTION MARK ABOVE - return rune(0x2a7c), true + return {'\u2a7c', 0}, 1, true case "gtrapprox": // GREATER-THAN OR APPROXIMATE - return rune(0x2a86), true + return {'\u2a86', 0}, 1, true case "gtrarr": // GREATER-THAN ABOVE RIGHTWARDS ARROW - return rune(0x2978), true + return {'\u2978', 0}, 1, true case "gtrdot": // GREATER-THAN WITH DOT - return rune(0x22d7), true + return {'\u22d7', 0}, 1, true case "gtreqless": // GREATER-THAN EQUAL TO OR LESS-THAN - return rune(0x22db), true + return {'\u22db', 0}, 1, true case "gtreqqless": // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN - return rune(0x2a8c), true + return {'\u2a8c', 0}, 1, true case "gtrless": // GREATER-THAN OR LESS-THAN - return rune(0x2277), true + return {'\u2277', 0}, 1, true case "gtrpar": // SPHERICAL ANGLE OPENING LEFT - return rune(0x29a0), true + return {'\u29a0', 0}, 1, true case "gtrsim": // GREATER-THAN OR EQUIVALENT TO - return rune(0x2273), true + return {'\u2273', 0}, 1, true case "gvertneqq": // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke - return rune(0x2269), true + return {'\u2269', '\ufe00'}, 2, true case "gvnE": // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke - return rune(0x2269), true + return {'\u2269', '\ufe00'}, 2, true } case 'h': switch name { case "hArr": // LEFT RIGHT DOUBLE ARROW - return rune(0x21d4), true + return {'\u21d4', 0}, 1, true case "hairsp": // HAIR SPACE - return rune(0x200a), true + return {'\u200a', 0}, 1, true case "half": // VULGAR FRACTION ONE HALF - return rune(0xbd), true + return {'½', 0}, 1, true case "hamilt": // SCRIPT CAPITAL H - return rune(0x210b), true + return {'\u210b', 0}, 1, true case "hardcy": // CYRILLIC SMALL LETTER HARD SIGN - return rune(0x044a), true + return {'\u044a', 0}, 1, true case "harr": // LEFT RIGHT ARROW - return rune(0x2194), true + return {'\u2194', 0}, 1, true case "harrcir": // LEFT RIGHT ARROW THROUGH SMALL CIRCLE - return rune(0x2948), true + return {'\u2948', 0}, 1, true case "harrw": // LEFT RIGHT WAVE ARROW - return rune(0x21ad), true + return {'\u21ad', 0}, 1, true case "hbar": // PLANCK CONSTANT OVER TWO PI - return rune(0x210f), true + return {'\u210f', 0}, 1, true case "hcirc": // LATIN SMALL LETTER H WITH CIRCUMFLEX - return rune(0x0125), true + return {'\u0125', 0}, 1, true case "hearts": // BLACK HEART SUIT - return rune(0x2665), true + return {'\u2665', 0}, 1, true case "heartsuit": // BLACK HEART SUIT - return rune(0x2665), true + return {'\u2665', 0}, 1, true case "hellip": // HORIZONTAL ELLIPSIS - return rune(0x2026), true + return {'\u2026', 0}, 1, true case "hercon": // HERMITIAN CONJUGATE MATRIX - return rune(0x22b9), true + return {'\u22b9', 0}, 1, true case "hfr": // MATHEMATICAL FRAKTUR SMALL H - return rune(0x01d525), true + return {'\U0001d525', 0}, 1, true case "hksearow": // SOUTH EAST ARROW WITH HOOK - return rune(0x2925), true + return {'\u2925', 0}, 1, true case "hkswarow": // SOUTH WEST ARROW WITH HOOK - return rune(0x2926), true + return {'\u2926', 0}, 1, true case "hoarr": // LEFT RIGHT OPEN-HEADED ARROW - return rune(0x21ff), true + return {'\u21ff', 0}, 1, true case "homtht": // HOMOTHETIC - return rune(0x223b), true + return {'\u223b', 0}, 1, true case "hookleftarrow": // LEFTWARDS ARROW WITH HOOK - return rune(0x21a9), true + return {'\u21a9', 0}, 1, true case "hookrightarrow": // RIGHTWARDS ARROW WITH HOOK - return rune(0x21aa), true + return {'\u21aa', 0}, 1, true case "hopf": // MATHEMATICAL DOUBLE-STRUCK SMALL H - return rune(0x01d559), true + return {'\U0001d559', 0}, 1, true case "horbar": // HORIZONTAL BAR - return rune(0x2015), true + return {'\u2015', 0}, 1, true case "hrglass": // WHITE HOURGLASS - return rune(0x29d6), true + return {'\u29d6', 0}, 1, true case "hscr": // MATHEMATICAL SCRIPT SMALL H - return rune(0x01d4bd), true + return {'\U0001d4bd', 0}, 1, true case "hslash": // PLANCK CONSTANT OVER TWO PI - return rune(0x210f), true + return {'\u210f', 0}, 1, true case "hstrok": // LATIN SMALL LETTER H WITH STROKE - return rune(0x0127), true + return {'\u0127', 0}, 1, true case "htimes": // VECTOR OR CROSS PRODUCT - return rune(0x2a2f), true + return {'\u2a2f', 0}, 1, true case "hybull": // HYPHEN BULLET - return rune(0x2043), true + return {'\u2043', 0}, 1, true case "hyphen": // HYPHEN - return rune(0x2010), true + return {'\u2010', 0}, 1, true } case 'i': switch name { case "iacgr": // GREEK SMALL LETTER IOTA WITH TONOS - return rune(0x03af), true + return {'\u03af', 0}, 1, true case "iacute": // LATIN SMALL LETTER I WITH ACUTE - return rune(0xed), true + return {'í', 0}, 1, true case "ic": // INVISIBLE SEPARATOR - return rune(0x2063), true + return {'\u2063', 0}, 1, true case "icirc": // LATIN SMALL LETTER I WITH CIRCUMFLEX - return rune(0xee), true + return {'î', 0}, 1, true case "icy": // CYRILLIC SMALL LETTER I - return rune(0x0438), true + return {'\u0438', 0}, 1, true case "idiagr": // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS - return rune(0x0390), true + return {'\u0390', 0}, 1, true case "idigr": // GREEK SMALL LETTER IOTA WITH DIALYTIKA - return rune(0x03ca), true + return {'\u03ca', 0}, 1, true case "iecy": // CYRILLIC SMALL LETTER IE - return rune(0x0435), true + return {'\u0435', 0}, 1, true case "iexcl": // INVERTED EXCLAMATION MARK - return rune(0xa1), true + return {'¡', 0}, 1, true case "iff": // LEFT RIGHT DOUBLE ARROW - return rune(0x21d4), true + return {'\u21d4', 0}, 1, true case "ifr": // MATHEMATICAL FRAKTUR SMALL I - return rune(0x01d526), true + return {'\U0001d526', 0}, 1, true case "igr": // GREEK SMALL LETTER IOTA - return rune(0x03b9), true + return {'\u03b9', 0}, 1, true case "igrave": // LATIN SMALL LETTER I WITH GRAVE - return rune(0xec), true + return {'ì', 0}, 1, true case "ii": // DOUBLE-STRUCK ITALIC SMALL I - return rune(0x2148), true + return {'\u2148', 0}, 1, true case "iiiint": // QUADRUPLE INTEGRAL OPERATOR - return rune(0x2a0c), true + return {'\u2a0c', 0}, 1, true case "iiint": // TRIPLE INTEGRAL - return rune(0x222d), true + return {'\u222d', 0}, 1, true case "iinfin": // INCOMPLETE INFINITY - return rune(0x29dc), true + return {'\u29dc', 0}, 1, true case "iiota": // TURNED GREEK SMALL LETTER IOTA - return rune(0x2129), true + return {'\u2129', 0}, 1, true case "ijlig": // LATIN SMALL LIGATURE IJ - return rune(0x0133), true + return {'\u0133', 0}, 1, true case "imacr": // LATIN SMALL LETTER I WITH MACRON - return rune(0x012b), true + return {'\u012b', 0}, 1, true case "image": // BLACK-LETTER CAPITAL I - return rune(0x2111), true + return {'\u2111', 0}, 1, true case "imagline": // SCRIPT CAPITAL I - return rune(0x2110), true + return {'\u2110', 0}, 1, true case "imagpart": // BLACK-LETTER CAPITAL I - return rune(0x2111), true + return {'\u2111', 0}, 1, true case "imath": // LATIN SMALL LETTER DOTLESS I - return rune(0x0131), true + return {'\u0131', 0}, 1, true case "imof": // IMAGE OF - return rune(0x22b7), true + return {'\u22b7', 0}, 1, true case "imped": // LATIN CAPITAL LETTER Z WITH STROKE - return rune(0x01b5), true + return {'\u01b5', 0}, 1, true case "in": // ELEMENT OF - return rune(0x2208), true + return {'\u2208', 0}, 1, true case "incare": // CARE OF - return rune(0x2105), true + return {'\u2105', 0}, 1, true case "infin": // INFINITY - return rune(0x221e), true + return {'\u221e', 0}, 1, true case "infintie": // TIE OVER INFINITY - return rune(0x29dd), true + return {'\u29dd', 0}, 1, true case "inodot": // LATIN SMALL LETTER DOTLESS I - return rune(0x0131), true + return {'\u0131', 0}, 1, true case "int": // INTEGRAL - return rune(0x222b), true + return {'\u222b', 0}, 1, true case "intcal": // INTERCALATE - return rune(0x22ba), true + return {'\u22ba', 0}, 1, true case "integers": // DOUBLE-STRUCK CAPITAL Z - return rune(0x2124), true + return {'\u2124', 0}, 1, true case "intercal": // INTERCALATE - return rune(0x22ba), true + return {'\u22ba', 0}, 1, true case "intlarhk": // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK - return rune(0x2a17), true + return {'\u2a17', 0}, 1, true case "intprod": // INTERIOR PRODUCT - return rune(0x2a3c), true + return {'\u2a3c', 0}, 1, true case "iocy": // CYRILLIC SMALL LETTER IO - return rune(0x0451), true + return {'\u0451', 0}, 1, true case "iogon": // LATIN SMALL LETTER I WITH OGONEK - return rune(0x012f), true + return {'\u012f', 0}, 1, true case "iopf": // MATHEMATICAL DOUBLE-STRUCK SMALL I - return rune(0x01d55a), true + return {'\U0001d55a', 0}, 1, true case "iota": // GREEK SMALL LETTER IOTA - return rune(0x03b9), true + return {'\u03b9', 0}, 1, true case "iprod": // INTERIOR PRODUCT - return rune(0x2a3c), true + return {'\u2a3c', 0}, 1, true case "iprodr": // RIGHTHAND INTERIOR PRODUCT - return rune(0x2a3d), true + return {'\u2a3d', 0}, 1, true case "iquest": // INVERTED QUESTION MARK - return rune(0xbf), true + return {'¿', 0}, 1, true case "iscr": // MATHEMATICAL SCRIPT SMALL I - return rune(0x01d4be), true + return {'\U0001d4be', 0}, 1, true case "isin": // ELEMENT OF - return rune(0x2208), true + return {'\u2208', 0}, 1, true case "isinE": // ELEMENT OF WITH TWO HORIZONTAL STROKES - return rune(0x22f9), true + return {'\u22f9', 0}, 1, true case "isindot": // ELEMENT OF WITH DOT ABOVE - return rune(0x22f5), true + return {'\u22f5', 0}, 1, true case "isins": // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - return rune(0x22f4), true + return {'\u22f4', 0}, 1, true case "isinsv": // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - return rune(0x22f3), true + return {'\u22f3', 0}, 1, true case "isinv": // ELEMENT OF - return rune(0x2208), true + return {'\u2208', 0}, 1, true case "isinvb": // ELEMENT OF WITH UNDERBAR - return rune(0x22f8), true + return {'\u22f8', 0}, 1, true case "it": // INVISIBLE TIMES - return rune(0x2062), true + return {'\u2062', 0}, 1, true case "itilde": // LATIN SMALL LETTER I WITH TILDE - return rune(0x0129), true + return {'\u0129', 0}, 1, true case "iukcy": // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I - return rune(0x0456), true + return {'\u0456', 0}, 1, true case "iuml": // LATIN SMALL LETTER I WITH DIAERESIS - return rune(0xef), true + return {'ï', 0}, 1, true } case 'j': switch name { case "jcirc": // LATIN SMALL LETTER J WITH CIRCUMFLEX - return rune(0x0135), true + return {'\u0135', 0}, 1, true case "jcy": // CYRILLIC SMALL LETTER SHORT I - return rune(0x0439), true + return {'\u0439', 0}, 1, true case "jfr": // MATHEMATICAL FRAKTUR SMALL J - return rune(0x01d527), true + return {'\U0001d527', 0}, 1, true case "jmath": // LATIN SMALL LETTER DOTLESS J - return rune(0x0237), true + return {'\u0237', 0}, 1, true case "jnodot": // LATIN SMALL LETTER DOTLESS J - return rune(0x0237), true + return {'\u0237', 0}, 1, true case "jopf": // MATHEMATICAL DOUBLE-STRUCK SMALL J - return rune(0x01d55b), true + return {'\U0001d55b', 0}, 1, true case "jscr": // MATHEMATICAL SCRIPT SMALL J - return rune(0x01d4bf), true + return {'\U0001d4bf', 0}, 1, true case "jsercy": // CYRILLIC SMALL LETTER JE - return rune(0x0458), true + return {'\u0458', 0}, 1, true case "jukcy": // CYRILLIC SMALL LETTER UKRAINIAN IE - return rune(0x0454), true + return {'\u0454', 0}, 1, true } case 'k': switch name { case "kappa": // GREEK SMALL LETTER KAPPA - return rune(0x03ba), true + return {'\u03ba', 0}, 1, true case "kappav": // GREEK KAPPA SYMBOL - return rune(0x03f0), true + return {'\u03f0', 0}, 1, true case "kcedil": // LATIN SMALL LETTER K WITH CEDILLA - return rune(0x0137), true + return {'\u0137', 0}, 1, true case "kcy": // CYRILLIC SMALL LETTER KA - return rune(0x043a), true + return {'\u043a', 0}, 1, true case "kfr": // MATHEMATICAL FRAKTUR SMALL K - return rune(0x01d528), true + return {'\U0001d528', 0}, 1, true case "kgr": // GREEK SMALL LETTER KAPPA - return rune(0x03ba), true + return {'\u03ba', 0}, 1, true case "kgreen": // LATIN SMALL LETTER KRA - return rune(0x0138), true + return {'\u0138', 0}, 1, true case "khcy": // CYRILLIC SMALL LETTER HA - return rune(0x0445), true + return {'\u0445', 0}, 1, true case "khgr": // GREEK SMALL LETTER CHI - return rune(0x03c7), true + return {'\u03c7', 0}, 1, true case "kjcy": // CYRILLIC SMALL LETTER KJE - return rune(0x045c), true + return {'\u045c', 0}, 1, true case "kopf": // MATHEMATICAL DOUBLE-STRUCK SMALL K - return rune(0x01d55c), true + return {'\U0001d55c', 0}, 1, true case "koppa": // GREEK LETTER KOPPA - return rune(0x03de), true + return {'\u03de', 0}, 1, true case "kscr": // MATHEMATICAL SCRIPT SMALL K - return rune(0x01d4c0), true + return {'\U0001d4c0', 0}, 1, true } case 'l': switch name { case "lAarr": // LEFTWARDS TRIPLE ARROW - return rune(0x21da), true + return {'\u21da', 0}, 1, true case "lArr": // LEFTWARDS DOUBLE ARROW - return rune(0x21d0), true + return {'\u21d0', 0}, 1, true case "lAtail": // LEFTWARDS DOUBLE ARROW-TAIL - return rune(0x291b), true + return {'\u291b', 0}, 1, true case "lBarr": // LEFTWARDS TRIPLE DASH ARROW - return rune(0x290e), true + return {'\u290e', 0}, 1, true case "lE": // LESS-THAN OVER EQUAL TO - return rune(0x2266), true + return {'\u2266', 0}, 1, true case "lEg": // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN - return rune(0x2a8b), true + return {'\u2a8b', 0}, 1, true case "lHar": // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN - return rune(0x2962), true + return {'\u2962', 0}, 1, true case "lacute": // LATIN SMALL LETTER L WITH ACUTE - return rune(0x013a), true + return {'\u013a', 0}, 1, true case "laemptyv": // EMPTY SET WITH LEFT ARROW ABOVE - return rune(0x29b4), true + return {'\u29b4', 0}, 1, true case "lagran": // SCRIPT CAPITAL L - return rune(0x2112), true + return {'\u2112', 0}, 1, true case "lambda": // GREEK SMALL LETTER LAMDA - return rune(0x03bb), true + return {'\u03bb', 0}, 1, true case "lang": // MATHEMATICAL LEFT ANGLE BRACKET - return rune(0x27e8), true + return {'\u27e8', 0}, 1, true case "langd": // LEFT ANGLE BRACKET WITH DOT - return rune(0x2991), true + return {'\u2991', 0}, 1, true case "langle": // MATHEMATICAL LEFT ANGLE BRACKET - return rune(0x27e8), true + return {'\u27e8', 0}, 1, true case "lap": // LESS-THAN OR APPROXIMATE - return rune(0x2a85), true + return {'\u2a85', 0}, 1, true case "laquo": // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - return rune(0xab), true + return {'«', 0}, 1, true case "larr": // LEFTWARDS ARROW - return rune(0x2190), true + return {'\u2190', 0}, 1, true case "larr2": // LEFTWARDS PAIRED ARROWS - return rune(0x21c7), true + return {'\u21c7', 0}, 1, true case "larrb": // LEFTWARDS ARROW TO BAR - return rune(0x21e4), true + return {'\u21e4', 0}, 1, true case "larrbfs": // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND - return rune(0x291f), true + return {'\u291f', 0}, 1, true case "larrfs": // LEFTWARDS ARROW TO BLACK DIAMOND - return rune(0x291d), true + return {'\u291d', 0}, 1, true case "larrhk": // LEFTWARDS ARROW WITH HOOK - return rune(0x21a9), true + return {'\u21a9', 0}, 1, true case "larrlp": // LEFTWARDS ARROW WITH LOOP - return rune(0x21ab), true + return {'\u21ab', 0}, 1, true case "larrpl": // LEFT-SIDE ARC ANTICLOCKWISE ARROW - return rune(0x2939), true + return {'\u2939', 0}, 1, true case "larrsim": // LEFTWARDS ARROW ABOVE TILDE OPERATOR - return rune(0x2973), true + return {'\u2973', 0}, 1, true case "larrtl": // LEFTWARDS ARROW WITH TAIL - return rune(0x21a2), true + return {'\u21a2', 0}, 1, true case "lat": // LARGER THAN - return rune(0x2aab), true + return {'\u2aab', 0}, 1, true case "latail": // LEFTWARDS ARROW-TAIL - return rune(0x2919), true + return {'\u2919', 0}, 1, true case "late": // LARGER THAN OR EQUAL TO - return rune(0x2aad), true + return {'\u2aad', 0}, 1, true case "lates": // LARGER THAN OR slanted EQUAL - return rune(0x2aad), true + return {'\u2aad', '\ufe00'}, 2, true case "lbarr": // LEFTWARDS DOUBLE DASH ARROW - return rune(0x290c), true + return {'\u290c', 0}, 1, true case "lbbrk": // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT - return rune(0x2772), true + return {'\u2772', 0}, 1, true case "lbrace": // LEFT CURLY BRACKET - return rune(0x7b), true + return {'{', 0}, 1, true case "lbrack": // LEFT SQUARE BRACKET - return rune(0x5b), true + return {'[', 0}, 1, true case "lbrke": // LEFT SQUARE BRACKET WITH UNDERBAR - return rune(0x298b), true + return {'\u298b', 0}, 1, true case "lbrksld": // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - return rune(0x298f), true + return {'\u298f', 0}, 1, true case "lbrkslu": // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER - return rune(0x298d), true + return {'\u298d', 0}, 1, true case "lcaron": // LATIN SMALL LETTER L WITH CARON - return rune(0x013e), true + return {'\u013e', 0}, 1, true case "lcedil": // LATIN SMALL LETTER L WITH CEDILLA - return rune(0x013c), true + return {'\u013c', 0}, 1, true case "lceil": // LEFT CEILING - return rune(0x2308), true + return {'\u2308', 0}, 1, true case "lcub": // LEFT CURLY BRACKET - return rune(0x7b), true + return {'{', 0}, 1, true case "lcy": // CYRILLIC SMALL LETTER EL - return rune(0x043b), true + return {'\u043b', 0}, 1, true case "ldca": // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS - return rune(0x2936), true + return {'\u2936', 0}, 1, true case "ldharb": // LEFTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2956), true + return {'\u2956', 0}, 1, true case "ldot": // LESS-THAN WITH DOT - return rune(0x22d6), true + return {'\u22d6', 0}, 1, true case "ldquo": // LEFT DOUBLE QUOTATION MARK - return rune(0x201c), true + return {'\u201c', 0}, 1, true case "ldquor": // DOUBLE LOW-9 QUOTATION MARK - return rune(0x201e), true + return {'\u201e', 0}, 1, true case "ldrdhar": // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN - return rune(0x2967), true + return {'\u2967', 0}, 1, true case "ldrdshar": // LEFT BARB DOWN RIGHT BARB DOWN HARPOON - return rune(0x2950), true + return {'\u2950', 0}, 1, true case "ldrushar": // LEFT BARB DOWN RIGHT BARB UP HARPOON - return rune(0x294b), true + return {'\u294b', 0}, 1, true case "ldsh": // DOWNWARDS ARROW WITH TIP LEFTWARDS - return rune(0x21b2), true + return {'\u21b2', 0}, 1, true case "le": // LESS-THAN OR EQUAL TO - return rune(0x2264), true + return {'\u2264', 0}, 1, true case "leftarrow": // LEFTWARDS ARROW - return rune(0x2190), true + return {'\u2190', 0}, 1, true case "leftarrowtail": // LEFTWARDS ARROW WITH TAIL - return rune(0x21a2), true + return {'\u21a2', 0}, 1, true case "leftharpoondown": // LEFTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21bd), true + return {'\u21bd', 0}, 1, true case "leftharpoonup": // LEFTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21bc), true + return {'\u21bc', 0}, 1, true case "leftleftarrows": // LEFTWARDS PAIRED ARROWS - return rune(0x21c7), true + return {'\u21c7', 0}, 1, true case "leftrightarrow": // LEFT RIGHT ARROW - return rune(0x2194), true + return {'\u2194', 0}, 1, true case "leftrightarrows": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true + return {'\u21c6', 0}, 1, true case "leftrightharpoons": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true + return {'\u21cb', 0}, 1, true case "leftrightsquigarrow": // LEFT RIGHT WAVE ARROW - return rune(0x21ad), true + return {'\u21ad', 0}, 1, true case "leftthreetimes": // LEFT SEMIDIRECT PRODUCT - return rune(0x22cb), true + return {'\u22cb', 0}, 1, true case "leg": // LESS-THAN EQUAL TO OR GREATER-THAN - return rune(0x22da), true + return {'\u22da', 0}, 1, true case "leq": // LESS-THAN OR EQUAL TO - return rune(0x2264), true + return {'\u2264', 0}, 1, true case "leqq": // LESS-THAN OVER EQUAL TO - return rune(0x2266), true + return {'\u2266', 0}, 1, true case "leqslant": // LESS-THAN OR SLANTED EQUAL TO - return rune(0x2a7d), true + return {'\u2a7d', 0}, 1, true case "les": // LESS-THAN OR SLANTED EQUAL TO - return rune(0x2a7d), true + return {'\u2a7d', 0}, 1, true case "lescc": // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL - return rune(0x2aa8), true + return {'\u2aa8', 0}, 1, true case "lesdot": // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE - return rune(0x2a7f), true + return {'\u2a7f', 0}, 1, true case "lesdoto": // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE - return rune(0x2a81), true + return {'\u2a81', 0}, 1, true case "lesdotor": // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT - return rune(0x2a83), true + return {'\u2a83', 0}, 1, true case "lesg": // LESS-THAN slanted EQUAL TO OR GREATER-THAN - return rune(0x22da), true + return {'\u22da', '\ufe00'}, 2, true case "lesges": // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL - return rune(0x2a93), true + return {'\u2a93', 0}, 1, true case "lessapprox": // LESS-THAN OR APPROXIMATE - return rune(0x2a85), true + return {'\u2a85', 0}, 1, true case "lessdot": // LESS-THAN WITH DOT - return rune(0x22d6), true + return {'\u22d6', 0}, 1, true case "lesseqgtr": // LESS-THAN EQUAL TO OR GREATER-THAN - return rune(0x22da), true + return {'\u22da', 0}, 1, true case "lesseqqgtr": // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN - return rune(0x2a8b), true + return {'\u2a8b', 0}, 1, true case "lessgtr": // LESS-THAN OR GREATER-THAN - return rune(0x2276), true + return {'\u2276', 0}, 1, true case "lesssim": // LESS-THAN OR EQUIVALENT TO - return rune(0x2272), true + return {'\u2272', 0}, 1, true case "lfbowtie": // BOWTIE WITH LEFT HALF BLACK - return rune(0x29d1), true + return {'\u29d1', 0}, 1, true case "lfisht": // LEFT FISH TAIL - return rune(0x297c), true + return {'\u297c', 0}, 1, true case "lfloor": // LEFT FLOOR - return rune(0x230a), true + return {'\u230a', 0}, 1, true case "lfr": // MATHEMATICAL FRAKTUR SMALL L - return rune(0x01d529), true + return {'\U0001d529', 0}, 1, true case "lftimes": // TIMES WITH LEFT HALF BLACK - return rune(0x29d4), true + return {'\u29d4', 0}, 1, true case "lg": // LESS-THAN OR GREATER-THAN - return rune(0x2276), true + return {'\u2276', 0}, 1, true case "lgE": // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL - return rune(0x2a91), true + return {'\u2a91', 0}, 1, true case "lgr": // GREEK SMALL LETTER LAMDA - return rune(0x03bb), true + return {'\u03bb', 0}, 1, true case "lhard": // LEFTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21bd), true + return {'\u21bd', 0}, 1, true case "lharu": // LEFTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21bc), true + return {'\u21bc', 0}, 1, true case "lharul": // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - return rune(0x296a), true + return {'\u296a', 0}, 1, true case "lhblk": // LOWER HALF BLOCK - return rune(0x2584), true + return {'\u2584', 0}, 1, true case "ljcy": // CYRILLIC SMALL LETTER LJE - return rune(0x0459), true + return {'\u0459', 0}, 1, true case "ll": // MUCH LESS-THAN - return rune(0x226a), true + return {'\u226a', 0}, 1, true case "llarr": // LEFTWARDS PAIRED ARROWS - return rune(0x21c7), true + return {'\u21c7', 0}, 1, true case "llcorner": // BOTTOM LEFT CORNER - return rune(0x231e), true + return {'\u231e', 0}, 1, true case "llhard": // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - return rune(0x296b), true + return {'\u296b', 0}, 1, true case "lltri": // LOWER LEFT TRIANGLE - return rune(0x25fa), true + return {'\u25fa', 0}, 1, true case "lltrif": // BLACK LOWER LEFT TRIANGLE - return rune(0x25e3), true + return {'\u25e3', 0}, 1, true case "lmidot": // LATIN SMALL LETTER L WITH MIDDLE DOT - return rune(0x0140), true + return {'\u0140', 0}, 1, true case "lmoust": // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - return rune(0x23b0), true + return {'\u23b0', 0}, 1, true case "lmoustache": // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - return rune(0x23b0), true + return {'\u23b0', 0}, 1, true case "lnE": // LESS-THAN BUT NOT EQUAL TO - return rune(0x2268), true + return {'\u2268', 0}, 1, true case "lnap": // LESS-THAN AND NOT APPROXIMATE - return rune(0x2a89), true + return {'\u2a89', 0}, 1, true case "lnapprox": // LESS-THAN AND NOT APPROXIMATE - return rune(0x2a89), true + return {'\u2a89', 0}, 1, true case "lne": // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a87), true + return {'\u2a87', 0}, 1, true case "lneq": // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - return rune(0x2a87), true + return {'\u2a87', 0}, 1, true case "lneqq": // LESS-THAN BUT NOT EQUAL TO - return rune(0x2268), true + return {'\u2268', 0}, 1, true case "lnsim": // LESS-THAN BUT NOT EQUIVALENT TO - return rune(0x22e6), true + return {'\u22e6', 0}, 1, true case "loang": // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET - return rune(0x27ec), true + return {'\u27ec', 0}, 1, true case "loarr": // LEFTWARDS OPEN-HEADED ARROW - return rune(0x21fd), true + return {'\u21fd', 0}, 1, true case "lobrk": // MATHEMATICAL LEFT WHITE SQUARE BRACKET - return rune(0x27e6), true + return {'\u27e6', 0}, 1, true case "locub": // LEFT WHITE CURLY BRACKET - return rune(0x2983), true + return {'\u2983', 0}, 1, true case "longleftarrow": // LONG LEFTWARDS ARROW - return rune(0x27f5), true + return {'\u27f5', 0}, 1, true case "longleftrightarrow": // LONG LEFT RIGHT ARROW - return rune(0x27f7), true + return {'\u27f7', 0}, 1, true case "longmapsto": // LONG RIGHTWARDS ARROW FROM BAR - return rune(0x27fc), true + return {'\u27fc', 0}, 1, true case "longrightarrow": // LONG RIGHTWARDS ARROW - return rune(0x27f6), true + return {'\u27f6', 0}, 1, true case "looparrowleft": // LEFTWARDS ARROW WITH LOOP - return rune(0x21ab), true + return {'\u21ab', 0}, 1, true case "looparrowright": // RIGHTWARDS ARROW WITH LOOP - return rune(0x21ac), true + return {'\u21ac', 0}, 1, true case "lopar": // LEFT WHITE PARENTHESIS - return rune(0x2985), true + return {'\u2985', 0}, 1, true case "lopf": // MATHEMATICAL DOUBLE-STRUCK SMALL L - return rune(0x01d55d), true + return {'\U0001d55d', 0}, 1, true case "loplus": // PLUS SIGN IN LEFT HALF CIRCLE - return rune(0x2a2d), true + return {'\u2a2d', 0}, 1, true case "lotimes": // MULTIPLICATION SIGN IN LEFT HALF CIRCLE - return rune(0x2a34), true + return {'\u2a34', 0}, 1, true case "lowast": // LOW ASTERISK - return rune(0x204e), true + return {'\u204e', 0}, 1, true case "lowbar": // LOW LINE - return rune(0x5f), true + return {'_', 0}, 1, true case "lowint": // INTEGRAL WITH UNDERBAR - return rune(0x2a1c), true + return {'\u2a1c', 0}, 1, true case "loz": // LOZENGE - return rune(0x25ca), true + return {'\u25ca', 0}, 1, true case "lozenge": // LOZENGE - return rune(0x25ca), true + return {'\u25ca', 0}, 1, true case "lozf": // BLACK LOZENGE - return rune(0x29eb), true + return {'\u29eb', 0}, 1, true case "lpar": // LEFT PARENTHESIS - return rune(0x28), true + return {'(', 0}, 1, true case "lpargt": // SPHERICAL ANGLE OPENING LEFT - return rune(0x29a0), true + return {'\u29a0', 0}, 1, true case "lparlt": // LEFT ARC LESS-THAN BRACKET - return rune(0x2993), true + return {'\u2993', 0}, 1, true case "lrarr": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true + return {'\u21c6', 0}, 1, true case "lrarr2": // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - return rune(0x21c6), true + return {'\u21c6', 0}, 1, true case "lrcorner": // BOTTOM RIGHT CORNER - return rune(0x231f), true + return {'\u231f', 0}, 1, true case "lrhar": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true + return {'\u21cb', 0}, 1, true case "lrhar2": // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - return rune(0x21cb), true + return {'\u21cb', 0}, 1, true case "lrhard": // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - return rune(0x296d), true + return {'\u296d', 0}, 1, true case "lrm": // LEFT-TO-RIGHT MARK - return rune(0x200e), true + return {'\u200e', 0}, 1, true case "lrtri": // RIGHT TRIANGLE - return rune(0x22bf), true + return {'\u22bf', 0}, 1, true case "lsaquo": // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - return rune(0x2039), true + return {'\u2039', 0}, 1, true case "lscr": // MATHEMATICAL SCRIPT SMALL L - return rune(0x01d4c1), true + return {'\U0001d4c1', 0}, 1, true case "lsh": // UPWARDS ARROW WITH TIP LEFTWARDS - return rune(0x21b0), true + return {'\u21b0', 0}, 1, true case "lsim": // LESS-THAN OR EQUIVALENT TO - return rune(0x2272), true + return {'\u2272', 0}, 1, true case "lsime": // LESS-THAN ABOVE SIMILAR OR EQUAL - return rune(0x2a8d), true + return {'\u2a8d', 0}, 1, true case "lsimg": // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN - return rune(0x2a8f), true + return {'\u2a8f', 0}, 1, true case "lsqb": // LEFT SQUARE BRACKET - return rune(0x5b), true + return {'[', 0}, 1, true case "lsquo": // LEFT SINGLE QUOTATION MARK - return rune(0x2018), true + return {'\u2018', 0}, 1, true case "lsquor": // SINGLE LOW-9 QUOTATION MARK - return rune(0x201a), true + return {'\u201a', 0}, 1, true case "lstrok": // LATIN SMALL LETTER L WITH STROKE - return rune(0x0142), true + return {'\u0142', 0}, 1, true case "lt": // LESS-THAN SIGN - return rune(0x3c), true + return {'<', 0}, 1, true case "ltcc": // LESS-THAN CLOSED BY CURVE - return rune(0x2aa6), true + return {'\u2aa6', 0}, 1, true case "ltcir": // LESS-THAN WITH CIRCLE INSIDE - return rune(0x2a79), true + return {'\u2a79', 0}, 1, true case "ltdot": // LESS-THAN WITH DOT - return rune(0x22d6), true + return {'\u22d6', 0}, 1, true case "lthree": // LEFT SEMIDIRECT PRODUCT - return rune(0x22cb), true + return {'\u22cb', 0}, 1, true case "ltimes": // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT - return rune(0x22c9), true + return {'\u22c9', 0}, 1, true case "ltlarr": // LESS-THAN ABOVE LEFTWARDS ARROW - return rune(0x2976), true + return {'\u2976', 0}, 1, true case "ltquest": // LESS-THAN WITH QUESTION MARK ABOVE - return rune(0x2a7b), true + return {'\u2a7b', 0}, 1, true case "ltrPar": // DOUBLE RIGHT ARC LESS-THAN BRACKET - return rune(0x2996), true + return {'\u2996', 0}, 1, true case "ltri": // WHITE LEFT-POINTING SMALL TRIANGLE - return rune(0x25c3), true + return {'\u25c3', 0}, 1, true case "ltrie": // NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22b4), true + return {'\u22b4', 0}, 1, true case "ltrif": // BLACK LEFT-POINTING SMALL TRIANGLE - return rune(0x25c2), true + return {'\u25c2', 0}, 1, true case "ltrivb": // LEFT TRIANGLE BESIDE VERTICAL BAR - return rune(0x29cf), true + return {'\u29cf', 0}, 1, true case "luharb": // LEFTWARDS HARPOON WITH BARB UP TO BAR - return rune(0x2952), true + return {'\u2952', 0}, 1, true case "lurdshar": // LEFT BARB UP RIGHT BARB DOWN HARPOON - return rune(0x294a), true + return {'\u294a', 0}, 1, true case "luruhar": // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP - return rune(0x2966), true + return {'\u2966', 0}, 1, true case "lurushar": // LEFT BARB UP RIGHT BARB UP HARPOON - return rune(0x294e), true + return {'\u294e', 0}, 1, true case "lvertneqq": // LESS-THAN BUT NOT EQUAL TO - with vertical stroke - return rune(0x2268), true + return {'\u2268', '\ufe00'}, 2, true case "lvnE": // LESS-THAN BUT NOT EQUAL TO - with vertical stroke - return rune(0x2268), true + return {'\u2268', '\ufe00'}, 2, true } case 'm': switch name { case "mDDot": // GEOMETRIC PROPORTION - return rune(0x223a), true + return {'\u223a', 0}, 1, true case "macr": // MACRON - return rune(0xaf), true + return {'¯', 0}, 1, true case "male": // MALE SIGN - return rune(0x2642), true + return {'\u2642', 0}, 1, true case "malt": // MALTESE CROSS - return rune(0x2720), true + return {'\u2720', 0}, 1, true case "maltese": // MALTESE CROSS - return rune(0x2720), true + return {'\u2720', 0}, 1, true case "map": // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true + return {'\u21a6', 0}, 1, true case "mapsto": // RIGHTWARDS ARROW FROM BAR - return rune(0x21a6), true + return {'\u21a6', 0}, 1, true case "mapstodown": // DOWNWARDS ARROW FROM BAR - return rune(0x21a7), true + return {'\u21a7', 0}, 1, true case "mapstoleft": // LEFTWARDS ARROW FROM BAR - return rune(0x21a4), true + return {'\u21a4', 0}, 1, true case "mapstoup": // UPWARDS ARROW FROM BAR - return rune(0x21a5), true + return {'\u21a5', 0}, 1, true case "marker": // BLACK VERTICAL RECTANGLE - return rune(0x25ae), true + return {'\u25ae', 0}, 1, true case "mcomma": // MINUS SIGN WITH COMMA ABOVE - return rune(0x2a29), true + return {'\u2a29', 0}, 1, true case "mcy": // CYRILLIC SMALL LETTER EM - return rune(0x043c), true + return {'\u043c', 0}, 1, true case "mdash": // EM DASH - return rune(0x2014), true + return {'\u2014', 0}, 1, true case "measuredangle": // MEASURED ANGLE - return rune(0x2221), true + return {'\u2221', 0}, 1, true case "mfr": // MATHEMATICAL FRAKTUR SMALL M - return rune(0x01d52a), true + return {'\U0001d52a', 0}, 1, true case "mgr": // GREEK SMALL LETTER MU - return rune(0x03bc), true + return {'\u03bc', 0}, 1, true case "mho": // INVERTED OHM SIGN - return rune(0x2127), true + return {'\u2127', 0}, 1, true case "micro": // MICRO SIGN - return rune(0xb5), true + return {'µ', 0}, 1, true case "mid": // DIVIDES - return rune(0x2223), true + return {'\u2223', 0}, 1, true case "midast": // ASTERISK - return rune(0x2a), true + return {'*', 0}, 1, true case "midcir": // VERTICAL LINE WITH CIRCLE BELOW - return rune(0x2af0), true + return {'\u2af0', 0}, 1, true case "middot": // MIDDLE DOT - return rune(0xb7), true + return {'·', 0}, 1, true case "minus": // MINUS SIGN - return rune(0x2212), true + return {'\u2212', 0}, 1, true case "minusb": // SQUARED MINUS - return rune(0x229f), true + return {'\u229f', 0}, 1, true case "minusd": // DOT MINUS - return rune(0x2238), true + return {'\u2238', 0}, 1, true case "minusdu": // MINUS SIGN WITH DOT BELOW - return rune(0x2a2a), true + return {'\u2a2a', 0}, 1, true case "mlcp": // TRANSVERSAL INTERSECTION - return rune(0x2adb), true + return {'\u2adb', 0}, 1, true case "mldr": // HORIZONTAL ELLIPSIS - return rune(0x2026), true + return {'\u2026', 0}, 1, true case "mnplus": // MINUS-OR-PLUS SIGN - return rune(0x2213), true + return {'\u2213', 0}, 1, true case "models": // MODELS - return rune(0x22a7), true + return {'\u22a7', 0}, 1, true case "mopf": // MATHEMATICAL DOUBLE-STRUCK SMALL M - return rune(0x01d55e), true + return {'\U0001d55e', 0}, 1, true case "mp": // MINUS-OR-PLUS SIGN - return rune(0x2213), true + return {'\u2213', 0}, 1, true case "mscr": // MATHEMATICAL SCRIPT SMALL M - return rune(0x01d4c2), true + return {'\U0001d4c2', 0}, 1, true case "mstpos": // INVERTED LAZY S - return rune(0x223e), true + return {'\u223e', 0}, 1, true case "mu": // GREEK SMALL LETTER MU - return rune(0x03bc), true + return {'\u03bc', 0}, 1, true case "multimap": // MULTIMAP - return rune(0x22b8), true + return {'\u22b8', 0}, 1, true case "mumap": // MULTIMAP - return rune(0x22b8), true + return {'\u22b8', 0}, 1, true } case 'n': switch name { case "nGg": // VERY MUCH GREATER-THAN with slash - return rune(0x22d9), true + return {'\u22d9', '\u0338'}, 2, true case "nGt": // MUCH GREATER THAN with vertical line - return rune(0x226b), true + return {'\u226b', '\u20d2'}, 2, true case "nGtv": // MUCH GREATER THAN with slash - return rune(0x226b), true + return {'\u226b', '\u0338'}, 2, true case "nLeftarrow": // LEFTWARDS DOUBLE ARROW WITH STROKE - return rune(0x21cd), true + return {'\u21cd', 0}, 1, true case "nLeftrightarrow": // LEFT RIGHT DOUBLE ARROW WITH STROKE - return rune(0x21ce), true + return {'\u21ce', 0}, 1, true case "nLl": // VERY MUCH LESS-THAN with slash - return rune(0x22d8), true + return {'\u22d8', '\u0338'}, 2, true case "nLt": // MUCH LESS THAN with vertical line - return rune(0x226a), true + return {'\u226a', '\u20d2'}, 2, true case "nLtv": // MUCH LESS THAN with slash - return rune(0x226a), true + return {'\u226a', '\u0338'}, 2, true case "nRightarrow": // RIGHTWARDS DOUBLE ARROW WITH STROKE - return rune(0x21cf), true + return {'\u21cf', 0}, 1, true case "nVDash": // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE - return rune(0x22af), true + return {'\u22af', 0}, 1, true case "nVdash": // DOES NOT FORCE - return rune(0x22ae), true + return {'\u22ae', 0}, 1, true case "nabla": // NABLA - return rune(0x2207), true + return {'\u2207', 0}, 1, true case "nacute": // LATIN SMALL LETTER N WITH ACUTE - return rune(0x0144), true + return {'\u0144', 0}, 1, true case "nang": // ANGLE with vertical line - return rune(0x2220), true + return {'\u2220', '\u20d2'}, 2, true case "nap": // NOT ALMOST EQUAL TO - return rune(0x2249), true + return {'\u2249', 0}, 1, true case "napE": // APPROXIMATELY EQUAL OR EQUAL TO with slash - return rune(0x2a70), true + return {'\u2a70', '\u0338'}, 2, true case "napid": // TRIPLE TILDE with slash - return rune(0x224b), true + return {'\u224b', '\u0338'}, 2, true case "napos": // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE - return rune(0x0149), true + return {'\u0149', 0}, 1, true case "napprox": // NOT ALMOST EQUAL TO - return rune(0x2249), true + return {'\u2249', 0}, 1, true case "natur": // MUSIC NATURAL SIGN - return rune(0x266e), true + return {'\u266e', 0}, 1, true case "natural": // MUSIC NATURAL SIGN - return rune(0x266e), true + return {'\u266e', 0}, 1, true case "naturals": // DOUBLE-STRUCK CAPITAL N - return rune(0x2115), true + return {'\u2115', 0}, 1, true case "nbsp": // NO-BREAK SPACE - return rune(0xa0), true + return {'\u00a0', 0}, 1, true case "nbump": // GEOMETRICALLY EQUIVALENT TO with slash - return rune(0x224e), true + return {'\u224e', '\u0338'}, 2, true case "nbumpe": // DIFFERENCE BETWEEN with slash - return rune(0x224f), true + return {'\u224f', '\u0338'}, 2, true case "ncap": // INTERSECTION WITH OVERBAR - return rune(0x2a43), true + return {'\u2a43', 0}, 1, true case "ncaron": // LATIN SMALL LETTER N WITH CARON - return rune(0x0148), true + return {'\u0148', 0}, 1, true case "ncedil": // LATIN SMALL LETTER N WITH CEDILLA - return rune(0x0146), true + return {'\u0146', 0}, 1, true case "ncong": // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO - return rune(0x2247), true + return {'\u2247', 0}, 1, true case "ncongdot": // CONGRUENT WITH DOT ABOVE with slash - return rune(0x2a6d), true + return {'\u2a6d', '\u0338'}, 2, true case "ncup": // UNION WITH OVERBAR - return rune(0x2a42), true + return {'\u2a42', 0}, 1, true case "ncy": // CYRILLIC SMALL LETTER EN - return rune(0x043d), true + return {'\u043d', 0}, 1, true case "ndash": // EN DASH - return rune(0x2013), true + return {'\u2013', 0}, 1, true case "ne": // NOT EQUAL TO - return rune(0x2260), true + return {'\u2260', 0}, 1, true case "neArr": // NORTH EAST DOUBLE ARROW - return rune(0x21d7), true + return {'\u21d7', 0}, 1, true case "nearhk": // NORTH EAST ARROW WITH HOOK - return rune(0x2924), true + return {'\u2924', 0}, 1, true case "nearr": // NORTH EAST ARROW - return rune(0x2197), true + return {'\u2197', 0}, 1, true case "nearrow": // NORTH EAST ARROW - return rune(0x2197), true + return {'\u2197', 0}, 1, true case "nedot": // APPROACHES THE LIMIT with slash - return rune(0x2250), true + return {'\u2250', '\u0338'}, 2, true case "neonwarr": // NORTH EAST ARROW CROSSING NORTH WEST ARROW - return rune(0x2931), true + return {'\u2931', 0}, 1, true case "neosearr": // NORTH EAST ARROW CROSSING SOUTH EAST ARROW - return rune(0x292e), true + return {'\u292e', 0}, 1, true case "nequiv": // NOT IDENTICAL TO - return rune(0x2262), true + return {'\u2262', 0}, 1, true case "nesear": // NORTH EAST ARROW AND SOUTH EAST ARROW - return rune(0x2928), true + return {'\u2928', 0}, 1, true case "nesim": // MINUS TILDE with slash - return rune(0x2242), true + return {'\u2242', '\u0338'}, 2, true case "neswsarr": // NORTH EAST AND SOUTH WEST ARROW - return rune(0x2922), true + return {'\u2922', 0}, 1, true case "nexist": // THERE DOES NOT EXIST - return rune(0x2204), true + return {'\u2204', 0}, 1, true case "nexists": // THERE DOES NOT EXIST - return rune(0x2204), true + return {'\u2204', 0}, 1, true case "nfr": // MATHEMATICAL FRAKTUR SMALL N - return rune(0x01d52b), true + return {'\U0001d52b', 0}, 1, true case "ngE": // GREATER-THAN OVER EQUAL TO with slash - return rune(0x2267), true + return {'\u2267', '\u0338'}, 2, true case "nge": // NEITHER GREATER-THAN NOR EQUAL TO - return rune(0x2271), true + return {'\u2271', 0}, 1, true case "ngeq": // NEITHER GREATER-THAN NOR EQUAL TO - return rune(0x2271), true + return {'\u2271', 0}, 1, true case "ngeqq": // GREATER-THAN OVER EQUAL TO with slash - return rune(0x2267), true + return {'\u2267', '\u0338'}, 2, true case "ngeqslant": // GREATER-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7e), true + return {'\u2a7e', '\u0338'}, 2, true case "nges": // GREATER-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7e), true + return {'\u2a7e', '\u0338'}, 2, true case "ngr": // GREEK SMALL LETTER NU - return rune(0x03bd), true + return {'\u03bd', 0}, 1, true case "ngsim": // NEITHER GREATER-THAN NOR EQUIVALENT TO - return rune(0x2275), true + return {'\u2275', 0}, 1, true case "ngt": // NOT GREATER-THAN - return rune(0x226f), true + return {'\u226f', 0}, 1, true case "ngtr": // NOT GREATER-THAN - return rune(0x226f), true + return {'\u226f', 0}, 1, true case "nhArr": // LEFT RIGHT DOUBLE ARROW WITH STROKE - return rune(0x21ce), true + return {'\u21ce', 0}, 1, true case "nharr": // LEFT RIGHT ARROW WITH STROKE - return rune(0x21ae), true + return {'\u21ae', 0}, 1, true case "nhpar": // PARALLEL WITH HORIZONTAL STROKE - return rune(0x2af2), true + return {'\u2af2', 0}, 1, true case "ni": // CONTAINS AS MEMBER - return rune(0x220b), true + return {'\u220b', 0}, 1, true case "nis": // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - return rune(0x22fc), true + return {'\u22fc', 0}, 1, true case "nisd": // CONTAINS WITH LONG HORIZONTAL STROKE - return rune(0x22fa), true + return {'\u22fa', 0}, 1, true case "niv": // CONTAINS AS MEMBER - return rune(0x220b), true + return {'\u220b', 0}, 1, true case "njcy": // CYRILLIC SMALL LETTER NJE - return rune(0x045a), true + return {'\u045a', 0}, 1, true case "nlArr": // LEFTWARDS DOUBLE ARROW WITH STROKE - return rune(0x21cd), true + return {'\u21cd', 0}, 1, true case "nlE": // LESS-THAN OVER EQUAL TO with slash - return rune(0x2266), true + return {'\u2266', '\u0338'}, 2, true case "nlarr": // LEFTWARDS ARROW WITH STROKE - return rune(0x219a), true + return {'\u219a', 0}, 1, true case "nldr": // TWO DOT LEADER - return rune(0x2025), true + return {'\u2025', 0}, 1, true case "nle": // NEITHER LESS-THAN NOR EQUAL TO - return rune(0x2270), true + return {'\u2270', 0}, 1, true case "nleftarrow": // LEFTWARDS ARROW WITH STROKE - return rune(0x219a), true + return {'\u219a', 0}, 1, true case "nleftrightarrow": // LEFT RIGHT ARROW WITH STROKE - return rune(0x21ae), true + return {'\u21ae', 0}, 1, true case "nleq": // NEITHER LESS-THAN NOR EQUAL TO - return rune(0x2270), true + return {'\u2270', 0}, 1, true case "nleqq": // LESS-THAN OVER EQUAL TO with slash - return rune(0x2266), true + return {'\u2266', '\u0338'}, 2, true case "nleqslant": // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true + return {'\u2a7d', '\u0338'}, 2, true case "nles": // LESS-THAN OR SLANTED EQUAL TO with slash - return rune(0x2a7d), true + return {'\u2a7d', '\u0338'}, 2, true case "nless": // NOT LESS-THAN - return rune(0x226e), true + return {'\u226e', 0}, 1, true case "nlsim": // NEITHER LESS-THAN NOR EQUIVALENT TO - return rune(0x2274), true + return {'\u2274', 0}, 1, true case "nlt": // NOT LESS-THAN - return rune(0x226e), true + return {'\u226e', 0}, 1, true case "nltri": // NOT NORMAL SUBGROUP OF - return rune(0x22ea), true + return {'\u22ea', 0}, 1, true case "nltrie": // NOT NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22ec), true + return {'\u22ec', 0}, 1, true case "nltrivb": // LEFT TRIANGLE BESIDE VERTICAL BAR with slash - return rune(0x29cf), true + return {'\u29cf', '\u0338'}, 2, true case "nmid": // DOES NOT DIVIDE - return rune(0x2224), true + return {'\u2224', 0}, 1, true case "nopf": // MATHEMATICAL DOUBLE-STRUCK SMALL N - return rune(0x01d55f), true + return {'\U0001d55f', 0}, 1, true case "not": // NOT SIGN - return rune(0xac), true + return {'¬', 0}, 1, true case "notin": // NOT AN ELEMENT OF - return rune(0x2209), true + return {'\u2209', 0}, 1, true case "notinE": // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash - return rune(0x22f9), true + return {'\u22f9', '\u0338'}, 2, true case "notindot": // ELEMENT OF WITH DOT ABOVE with slash - return rune(0x22f5), true + return {'\u22f5', '\u0338'}, 2, true case "notinva": // NOT AN ELEMENT OF - return rune(0x2209), true + return {'\u2209', 0}, 1, true case "notinvb": // SMALL ELEMENT OF WITH OVERBAR - return rune(0x22f7), true + return {'\u22f7', 0}, 1, true case "notinvc": // ELEMENT OF WITH OVERBAR - return rune(0x22f6), true + return {'\u22f6', 0}, 1, true case "notni": // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true + return {'\u220c', 0}, 1, true case "notniva": // DOES NOT CONTAIN AS MEMBER - return rune(0x220c), true + return {'\u220c', 0}, 1, true case "notnivb": // SMALL CONTAINS WITH OVERBAR - return rune(0x22fe), true + return {'\u22fe', 0}, 1, true case "notnivc": // CONTAINS WITH OVERBAR - return rune(0x22fd), true + return {'\u22fd', 0}, 1, true case "npar": // NOT PARALLEL TO - return rune(0x2226), true + return {'\u2226', 0}, 1, true case "nparallel": // NOT PARALLEL TO - return rune(0x2226), true + return {'\u2226', 0}, 1, true case "nparsl": // DOUBLE SOLIDUS OPERATOR with reverse slash - return rune(0x2afd), true + return {'\u2afd', '\u20e5'}, 2, true case "npart": // PARTIAL DIFFERENTIAL with slash - return rune(0x2202), true + return {'\u2202', '\u0338'}, 2, true case "npolint": // LINE INTEGRATION NOT INCLUDING THE POLE - return rune(0x2a14), true + return {'\u2a14', 0}, 1, true case "npr": // DOES NOT PRECEDE - return rune(0x2280), true + return {'\u2280', 0}, 1, true case "nprcue": // DOES NOT PRECEDE OR EQUAL - return rune(0x22e0), true + return {'\u22e0', 0}, 1, true case "npre": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2aaf), true + return {'\u2aaf', '\u0338'}, 2, true case "nprec": // DOES NOT PRECEDE - return rune(0x2280), true + return {'\u2280', 0}, 1, true case "npreceq": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2aaf), true + return {'\u2aaf', '\u0338'}, 2, true case "nprsim": // PRECEDES OR EQUIVALENT TO with slash - return rune(0x227e), true + return {'\u227e', '\u0338'}, 2, true case "nrArr": // RIGHTWARDS DOUBLE ARROW WITH STROKE - return rune(0x21cf), true + return {'\u21cf', 0}, 1, true case "nrarr": // RIGHTWARDS ARROW WITH STROKE - return rune(0x219b), true + return {'\u219b', 0}, 1, true case "nrarrc": // WAVE ARROW POINTING DIRECTLY RIGHT with slash - return rune(0x2933), true + return {'\u2933', '\u0338'}, 2, true case "nrarrw": // RIGHTWARDS WAVE ARROW with slash - return rune(0x219d), true + return {'\u219d', '\u0338'}, 2, true case "nrightarrow": // RIGHTWARDS ARROW WITH STROKE - return rune(0x219b), true + return {'\u219b', 0}, 1, true case "nrtri": // DOES NOT CONTAIN AS NORMAL SUBGROUP - return rune(0x22eb), true + return {'\u22eb', 0}, 1, true case "nrtrie": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL - return rune(0x22ed), true + return {'\u22ed', 0}, 1, true case "nsGt": // DOUBLE NESTED GREATER-THAN with slash - return rune(0x2aa2), true + return {'\u2aa2', '\u0338'}, 2, true case "nsLt": // DOUBLE NESTED LESS-THAN with slash - return rune(0x2aa1), true + return {'\u2aa1', '\u0338'}, 2, true case "nsc": // DOES NOT SUCCEED - return rune(0x2281), true + return {'\u2281', 0}, 1, true case "nsccue": // DOES NOT SUCCEED OR EQUAL - return rune(0x22e1), true + return {'\u22e1', 0}, 1, true case "nsce": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2ab0), true + return {'\u2ab0', '\u0338'}, 2, true case "nscr": // MATHEMATICAL SCRIPT SMALL N - return rune(0x01d4c3), true + return {'\U0001d4c3', 0}, 1, true case "nscsim": // SUCCEEDS OR EQUIVALENT TO with slash - return rune(0x227f), true + return {'\u227f', '\u0338'}, 2, true case "nshortmid": // DOES NOT DIVIDE - return rune(0x2224), true + return {'\u2224', 0}, 1, true case "nshortparallel": // NOT PARALLEL TO - return rune(0x2226), true + return {'\u2226', 0}, 1, true case "nsim": // NOT TILDE - return rune(0x2241), true + return {'\u2241', 0}, 1, true case "nsime": // NOT ASYMPTOTICALLY EQUAL TO - return rune(0x2244), true + return {'\u2244', 0}, 1, true case "nsimeq": // NOT ASYMPTOTICALLY EQUAL TO - return rune(0x2244), true + return {'\u2244', 0}, 1, true case "nsmid": // DOES NOT DIVIDE - return rune(0x2224), true + return {'\u2224', 0}, 1, true case "nspar": // NOT PARALLEL TO - return rune(0x2226), true + return {'\u2226', 0}, 1, true case "nsqsub": // SQUARE IMAGE OF with slash - return rune(0x228f), true + return {'\u228f', '\u0338'}, 2, true case "nsqsube": // NOT SQUARE IMAGE OF OR EQUAL TO - return rune(0x22e2), true + return {'\u22e2', 0}, 1, true case "nsqsup": // SQUARE ORIGINAL OF with slash - return rune(0x2290), true + return {'\u2290', '\u0338'}, 2, true case "nsqsupe": // NOT SQUARE ORIGINAL OF OR EQUAL TO - return rune(0x22e3), true + return {'\u22e3', 0}, 1, true case "nsub": // NOT A SUBSET OF - return rune(0x2284), true + return {'\u2284', 0}, 1, true case "nsubE": // SUBSET OF ABOVE EQUALS SIGN with slash - return rune(0x2ac5), true + return {'\u2ac5', '\u0338'}, 2, true case "nsube": // NEITHER A SUBSET OF NOR EQUAL TO - return rune(0x2288), true + return {'\u2288', 0}, 1, true case "nsubset": // SUBSET OF with vertical line - return rune(0x2282), true + return {'\u2282', '\u20d2'}, 2, true case "nsubseteq": // NEITHER A SUBSET OF NOR EQUAL TO - return rune(0x2288), true + return {'\u2288', 0}, 1, true case "nsubseteqq": // SUBSET OF ABOVE EQUALS SIGN with slash - return rune(0x2ac5), true + return {'\u2ac5', '\u0338'}, 2, true case "nsucc": // DOES NOT SUCCEED - return rune(0x2281), true + return {'\u2281', 0}, 1, true case "nsucceq": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - return rune(0x2ab0), true + return {'\u2ab0', '\u0338'}, 2, true case "nsup": // NOT A SUPERSET OF - return rune(0x2285), true + return {'\u2285', 0}, 1, true case "nsupE": // SUPERSET OF ABOVE EQUALS SIGN with slash - return rune(0x2ac6), true + return {'\u2ac6', '\u0338'}, 2, true case "nsupe": // NEITHER A SUPERSET OF NOR EQUAL TO - return rune(0x2289), true + return {'\u2289', 0}, 1, true case "nsupset": // SUPERSET OF with vertical line - return rune(0x2283), true + return {'\u2283', '\u20d2'}, 2, true case "nsupseteq": // NEITHER A SUPERSET OF NOR EQUAL TO - return rune(0x2289), true + return {'\u2289', 0}, 1, true case "nsupseteqq": // SUPERSET OF ABOVE EQUALS SIGN with slash - return rune(0x2ac6), true + return {'\u2ac6', '\u0338'}, 2, true case "ntgl": // NEITHER GREATER-THAN NOR LESS-THAN - return rune(0x2279), true + return {'\u2279', 0}, 1, true case "ntilde": // LATIN SMALL LETTER N WITH TILDE - return rune(0xf1), true + return {'ñ', 0}, 1, true case "ntlg": // NEITHER LESS-THAN NOR GREATER-THAN - return rune(0x2278), true + return {'\u2278', 0}, 1, true case "ntriangleleft": // NOT NORMAL SUBGROUP OF - return rune(0x22ea), true + return {'\u22ea', 0}, 1, true case "ntrianglelefteq": // NOT NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22ec), true + return {'\u22ec', 0}, 1, true case "ntriangleright": // DOES NOT CONTAIN AS NORMAL SUBGROUP - return rune(0x22eb), true + return {'\u22eb', 0}, 1, true case "ntrianglerighteq": // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL - return rune(0x22ed), true + return {'\u22ed', 0}, 1, true case "nu": // GREEK SMALL LETTER NU - return rune(0x03bd), true + return {'\u03bd', 0}, 1, true case "num": // NUMBER SIGN - return rune(0x23), true + return {'#', 0}, 1, true case "numero": // NUMERO SIGN - return rune(0x2116), true + return {'\u2116', 0}, 1, true case "numsp": // FIGURE SPACE - return rune(0x2007), true + return {'\u2007', 0}, 1, true case "nvDash": // NOT TRUE - return rune(0x22ad), true + return {'\u22ad', 0}, 1, true case "nvHarr": // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE - return rune(0x2904), true + return {'\u2904', 0}, 1, true case "nvap": // EQUIVALENT TO with vertical line - return rune(0x224d), true + return {'\u224d', '\u20d2'}, 2, true case "nvbrtri": // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash - return rune(0x29d0), true + return {'\u29d0', '\u0338'}, 2, true case "nvdash": // DOES NOT PROVE - return rune(0x22ac), true + return {'\u22ac', 0}, 1, true case "nvge": // GREATER-THAN OR EQUAL TO with vertical line - return rune(0x2265), true + return {'\u2265', '\u20d2'}, 2, true case "nvgt": // GREATER-THAN SIGN with vertical line - return rune(0x3e), true + return {'>', '\u20d2'}, 2, true case "nvinfin": // INFINITY NEGATED WITH VERTICAL BAR - return rune(0x29de), true + return {'\u29de', 0}, 1, true case "nvlArr": // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE - return rune(0x2902), true + return {'\u2902', 0}, 1, true case "nvle": // LESS-THAN OR EQUAL TO with vertical line - return rune(0x2264), true + return {'\u2264', '\u20d2'}, 2, true case "nvlt": // LESS-THAN SIGN with vertical line - return rune(0x3c), true + return {'<', '\u20d2'}, 2, true case "nvltrie": // NORMAL SUBGROUP OF OR EQUAL TO with vertical line - return rune(0x22b4), true + return {'\u22b4', '\u20d2'}, 2, true case "nvrArr": // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE - return rune(0x2903), true + return {'\u2903', 0}, 1, true case "nvrtrie": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line - return rune(0x22b5), true + return {'\u22b5', '\u20d2'}, 2, true case "nvsim": // TILDE OPERATOR with vertical line - return rune(0x223c), true + return {'\u223c', '\u20d2'}, 2, true case "nwArr": // NORTH WEST DOUBLE ARROW - return rune(0x21d6), true + return {'\u21d6', 0}, 1, true case "nwarhk": // NORTH WEST ARROW WITH HOOK - return rune(0x2923), true + return {'\u2923', 0}, 1, true case "nwarr": // NORTH WEST ARROW - return rune(0x2196), true + return {'\u2196', 0}, 1, true case "nwarrow": // NORTH WEST ARROW - return rune(0x2196), true + return {'\u2196', 0}, 1, true case "nwnear": // NORTH WEST ARROW AND NORTH EAST ARROW - return rune(0x2927), true + return {'\u2927', 0}, 1, true case "nwonearr": // NORTH WEST ARROW CROSSING NORTH EAST ARROW - return rune(0x2932), true + return {'\u2932', 0}, 1, true case "nwsesarr": // NORTH WEST AND SOUTH EAST ARROW - return rune(0x2921), true + return {'\u2921', 0}, 1, true } case 'o': switch name { case "oS": // CIRCLED LATIN CAPITAL LETTER S - return rune(0x24c8), true + return {'\u24c8', 0}, 1, true case "oacgr": // GREEK SMALL LETTER OMICRON WITH TONOS - return rune(0x03cc), true + return {'\u03cc', 0}, 1, true case "oacute": // LATIN SMALL LETTER O WITH ACUTE - return rune(0xf3), true + return {'ó', 0}, 1, true case "oast": // CIRCLED ASTERISK OPERATOR - return rune(0x229b), true + return {'\u229b', 0}, 1, true case "obsol": // CIRCLED REVERSE SOLIDUS - return rune(0x29b8), true + return {'\u29b8', 0}, 1, true case "ocir": // CIRCLED RING OPERATOR - return rune(0x229a), true + return {'\u229a', 0}, 1, true case "ocirc": // LATIN SMALL LETTER O WITH CIRCUMFLEX - return rune(0xf4), true + return {'ô', 0}, 1, true case "ocy": // CYRILLIC SMALL LETTER O - return rune(0x043e), true + return {'\u043e', 0}, 1, true case "odash": // CIRCLED DASH - return rune(0x229d), true + return {'\u229d', 0}, 1, true case "odblac": // LATIN SMALL LETTER O WITH DOUBLE ACUTE - return rune(0x0151), true + return {'\u0151', 0}, 1, true case "odiv": // CIRCLED DIVISION SIGN - return rune(0x2a38), true + return {'\u2a38', 0}, 1, true case "odot": // CIRCLED DOT OPERATOR - return rune(0x2299), true + return {'\u2299', 0}, 1, true case "odsold": // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN - return rune(0x29bc), true + return {'\u29bc', 0}, 1, true case "oelig": // LATIN SMALL LIGATURE OE - return rune(0x0153), true + return {'\u0153', 0}, 1, true case "ofcir": // CIRCLED BULLET - return rune(0x29bf), true + return {'\u29bf', 0}, 1, true case "ofr": // MATHEMATICAL FRAKTUR SMALL O - return rune(0x01d52c), true + return {'\U0001d52c', 0}, 1, true case "ogon": // OGONEK - return rune(0x02db), true + return {'\u02db', 0}, 1, true case "ogr": // GREEK SMALL LETTER OMICRON - return rune(0x03bf), true + return {'\u03bf', 0}, 1, true case "ograve": // LATIN SMALL LETTER O WITH GRAVE - return rune(0xf2), true + return {'ò', 0}, 1, true case "ogt": // CIRCLED GREATER-THAN - return rune(0x29c1), true + return {'\u29c1', 0}, 1, true case "ohacgr": // GREEK SMALL LETTER OMEGA WITH TONOS - return rune(0x03ce), true + return {'\u03ce', 0}, 1, true case "ohbar": // CIRCLE WITH HORIZONTAL BAR - return rune(0x29b5), true + return {'\u29b5', 0}, 1, true case "ohgr": // GREEK SMALL LETTER OMEGA - return rune(0x03c9), true + return {'\u03c9', 0}, 1, true case "ohm": // GREEK CAPITAL LETTER OMEGA - return rune(0x03a9), true + return {'\u03a9', 0}, 1, true case "oint": // CONTOUR INTEGRAL - return rune(0x222e), true + return {'\u222e', 0}, 1, true case "olarr": // ANTICLOCKWISE OPEN CIRCLE ARROW - return rune(0x21ba), true + return {'\u21ba', 0}, 1, true case "olcir": // CIRCLED WHITE BULLET - return rune(0x29be), true + return {'\u29be', 0}, 1, true case "olcross": // CIRCLE WITH SUPERIMPOSED X - return rune(0x29bb), true + return {'\u29bb', 0}, 1, true case "oline": // OVERLINE - return rune(0x203e), true + return {'\u203e', 0}, 1, true case "olt": // CIRCLED LESS-THAN - return rune(0x29c0), true + return {'\u29c0', 0}, 1, true case "omacr": // LATIN SMALL LETTER O WITH MACRON - return rune(0x014d), true + return {'\u014d', 0}, 1, true case "omega": // GREEK SMALL LETTER OMEGA - return rune(0x03c9), true + return {'\u03c9', 0}, 1, true case "omicron": // GREEK SMALL LETTER OMICRON - return rune(0x03bf), true + return {'\u03bf', 0}, 1, true case "omid": // CIRCLED VERTICAL BAR - return rune(0x29b6), true + return {'\u29b6', 0}, 1, true case "ominus": // CIRCLED MINUS - return rune(0x2296), true + return {'\u2296', 0}, 1, true case "oopf": // MATHEMATICAL DOUBLE-STRUCK SMALL O - return rune(0x01d560), true + return {'\U0001d560', 0}, 1, true case "opar": // CIRCLED PARALLEL - return rune(0x29b7), true + return {'\u29b7', 0}, 1, true case "operp": // CIRCLED PERPENDICULAR - return rune(0x29b9), true + return {'\u29b9', 0}, 1, true case "opfgamma": // DOUBLE-STRUCK SMALL GAMMA - return rune(0x213d), true + return {'\u213d', 0}, 1, true case "opfpi": // DOUBLE-STRUCK CAPITAL PI - return rune(0x213f), true + return {'\u213f', 0}, 1, true case "opfsum": // DOUBLE-STRUCK N-ARY SUMMATION - return rune(0x2140), true + return {'\u2140', 0}, 1, true case "oplus": // CIRCLED PLUS - return rune(0x2295), true + return {'\u2295', 0}, 1, true case "or": // LOGICAL OR - return rune(0x2228), true + return {'\u2228', 0}, 1, true case "orarr": // CLOCKWISE OPEN CIRCLE ARROW - return rune(0x21bb), true + return {'\u21bb', 0}, 1, true case "ord": // LOGICAL OR WITH HORIZONTAL DASH - return rune(0x2a5d), true + return {'\u2a5d', 0}, 1, true case "order": // SCRIPT SMALL O - return rune(0x2134), true + return {'\u2134', 0}, 1, true case "orderof": // SCRIPT SMALL O - return rune(0x2134), true + return {'\u2134', 0}, 1, true case "ordf": // FEMININE ORDINAL INDICATOR - return rune(0xaa), true + return {'ª', 0}, 1, true case "ordm": // MASCULINE ORDINAL INDICATOR - return rune(0xba), true + return {'º', 0}, 1, true case "origof": // ORIGINAL OF - return rune(0x22b6), true + return {'\u22b6', 0}, 1, true case "oror": // TWO INTERSECTING LOGICAL OR - return rune(0x2a56), true + return {'\u2a56', 0}, 1, true case "orslope": // SLOPING LARGE OR - return rune(0x2a57), true + return {'\u2a57', 0}, 1, true case "orv": // LOGICAL OR WITH MIDDLE STEM - return rune(0x2a5b), true + return {'\u2a5b', 0}, 1, true case "oscr": // SCRIPT SMALL O - return rune(0x2134), true + return {'\u2134', 0}, 1, true case "oslash": // LATIN SMALL LETTER O WITH STROKE - return rune(0xf8), true + return {'ø', 0}, 1, true case "osol": // CIRCLED DIVISION SLASH - return rune(0x2298), true + return {'\u2298', 0}, 1, true case "otilde": // LATIN SMALL LETTER O WITH TILDE - return rune(0xf5), true + return {'õ', 0}, 1, true case "otimes": // CIRCLED TIMES - return rune(0x2297), true + return {'\u2297', 0}, 1, true case "otimesas": // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT - return rune(0x2a36), true + return {'\u2a36', 0}, 1, true case "ouml": // LATIN SMALL LETTER O WITH DIAERESIS - return rune(0xf6), true + return {'ö', 0}, 1, true case "ovbar": // APL FUNCTIONAL SYMBOL CIRCLE STILE - return rune(0x233d), true + return {'\u233d', 0}, 1, true case "ovrbrk": // TOP SQUARE BRACKET - return rune(0x23b4), true + return {'\u23b4', 0}, 1, true case "ovrcub": // TOP CURLY BRACKET - return rune(0x23de), true + return {'\u23de', 0}, 1, true case "ovrpar": // TOP PARENTHESIS - return rune(0x23dc), true + return {'\u23dc', 0}, 1, true case "oxuarr": // UP ARROW THROUGH CIRCLE - return rune(0x29bd), true + return {'\u29bd', 0}, 1, true } case 'p': switch name { case "par": // PARALLEL TO - return rune(0x2225), true + return {'\u2225', 0}, 1, true case "para": // PILCROW SIGN - return rune(0xb6), true + return {'¶', 0}, 1, true case "parallel": // PARALLEL TO - return rune(0x2225), true + return {'\u2225', 0}, 1, true case "parsim": // PARALLEL WITH TILDE OPERATOR - return rune(0x2af3), true + return {'\u2af3', 0}, 1, true case "parsl": // DOUBLE SOLIDUS OPERATOR - return rune(0x2afd), true + return {'\u2afd', 0}, 1, true case "part": // PARTIAL DIFFERENTIAL - return rune(0x2202), true + return {'\u2202', 0}, 1, true case "pcy": // CYRILLIC SMALL LETTER PE - return rune(0x043f), true + return {'\u043f', 0}, 1, true case "percnt": // PERCENT SIGN - return rune(0x25), true + return {'%', 0}, 1, true case "period": // FULL STOP - return rune(0x2e), true + return {'.', 0}, 1, true case "permil": // PER MILLE SIGN - return rune(0x2030), true + return {'\u2030', 0}, 1, true case "perp": // UP TACK - return rune(0x22a5), true + return {'\u22a5', 0}, 1, true case "pertenk": // PER TEN THOUSAND SIGN - return rune(0x2031), true + return {'\u2031', 0}, 1, true case "pfr": // MATHEMATICAL FRAKTUR SMALL P - return rune(0x01d52d), true + return {'\U0001d52d', 0}, 1, true case "pgr": // GREEK SMALL LETTER PI - return rune(0x03c0), true + return {'\u03c0', 0}, 1, true case "phgr": // GREEK SMALL LETTER PHI - return rune(0x03c6), true + return {'\u03c6', 0}, 1, true case "phi": // GREEK SMALL LETTER PHI - return rune(0x03c6), true + return {'\u03c6', 0}, 1, true case "phis": // GREEK PHI SYMBOL - return rune(0x03d5), true + return {'\u03d5', 0}, 1, true case "phiv": // GREEK PHI SYMBOL - return rune(0x03d5), true + return {'\u03d5', 0}, 1, true case "phmmat": // SCRIPT CAPITAL M - return rune(0x2133), true + return {'\u2133', 0}, 1, true case "phone": // BLACK TELEPHONE - return rune(0x260e), true + return {'\u260e', 0}, 1, true case "pi": // GREEK SMALL LETTER PI - return rune(0x03c0), true + return {'\u03c0', 0}, 1, true case "pitchfork": // PITCHFORK - return rune(0x22d4), true + return {'\u22d4', 0}, 1, true case "piv": // GREEK PI SYMBOL - return rune(0x03d6), true + return {'\u03d6', 0}, 1, true case "planck": // PLANCK CONSTANT OVER TWO PI - return rune(0x210f), true + return {'\u210f', 0}, 1, true case "planckh": // PLANCK CONSTANT - return rune(0x210e), true + return {'\u210e', 0}, 1, true case "plankv": // PLANCK CONSTANT OVER TWO PI - return rune(0x210f), true + return {'\u210f', 0}, 1, true case "plus": // PLUS SIGN - return rune(0x2b), true + return {'+', 0}, 1, true case "plusacir": // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE - return rune(0x2a23), true + return {'\u2a23', 0}, 1, true case "plusb": // SQUARED PLUS - return rune(0x229e), true + return {'\u229e', 0}, 1, true case "pluscir": // PLUS SIGN WITH SMALL CIRCLE ABOVE - return rune(0x2a22), true + return {'\u2a22', 0}, 1, true case "plusdo": // DOT PLUS - return rune(0x2214), true + return {'\u2214', 0}, 1, true case "plusdu": // PLUS SIGN WITH DOT BELOW - return rune(0x2a25), true + return {'\u2a25', 0}, 1, true case "pluse": // PLUS SIGN ABOVE EQUALS SIGN - return rune(0x2a72), true + return {'\u2a72', 0}, 1, true case "plusmn": // PLUS-MINUS SIGN - return rune(0xb1), true + return {'±', 0}, 1, true case "plussim": // PLUS SIGN WITH TILDE BELOW - return rune(0x2a26), true + return {'\u2a26', 0}, 1, true case "plustrif": // PLUS SIGN WITH BLACK TRIANGLE - return rune(0x2a28), true + return {'\u2a28', 0}, 1, true case "plustwo": // PLUS SIGN WITH SUBSCRIPT TWO - return rune(0x2a27), true + return {'\u2a27', 0}, 1, true case "pm": // PLUS-MINUS SIGN - return rune(0xb1), true + return {'±', 0}, 1, true case "pointint": // INTEGRAL AROUND A POINT OPERATOR - return rune(0x2a15), true + return {'\u2a15', 0}, 1, true case "popf": // MATHEMATICAL DOUBLE-STRUCK SMALL P - return rune(0x01d561), true + return {'\U0001d561', 0}, 1, true case "pound": // POUND SIGN - return rune(0xa3), true + return {'£', 0}, 1, true case "pr": // PRECEDES - return rune(0x227a), true + return {'\u227a', 0}, 1, true case "prE": // PRECEDES ABOVE EQUALS SIGN - return rune(0x2ab3), true + return {'\u2ab3', 0}, 1, true case "prap": // PRECEDES ABOVE ALMOST EQUAL TO - return rune(0x2ab7), true + return {'\u2ab7', 0}, 1, true case "prcue": // PRECEDES OR EQUAL TO - return rune(0x227c), true + return {'\u227c', 0}, 1, true case "pre": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2aaf), true + return {'\u2aaf', 0}, 1, true case "prec": // PRECEDES - return rune(0x227a), true + return {'\u227a', 0}, 1, true case "precapprox": // PRECEDES ABOVE ALMOST EQUAL TO - return rune(0x2ab7), true + return {'\u2ab7', 0}, 1, true case "preccurlyeq": // PRECEDES OR EQUAL TO - return rune(0x227c), true + return {'\u227c', 0}, 1, true case "preceq": // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2aaf), true + return {'\u2aaf', 0}, 1, true case "precnapprox": // PRECEDES ABOVE NOT ALMOST EQUAL TO - return rune(0x2ab9), true + return {'\u2ab9', 0}, 1, true case "precneqq": // PRECEDES ABOVE NOT EQUAL TO - return rune(0x2ab5), true + return {'\u2ab5', 0}, 1, true case "precnsim": // PRECEDES BUT NOT EQUIVALENT TO - return rune(0x22e8), true + return {'\u22e8', 0}, 1, true case "precsim": // PRECEDES OR EQUIVALENT TO - return rune(0x227e), true + return {'\u227e', 0}, 1, true case "prime": // PRIME - return rune(0x2032), true + return {'\u2032', 0}, 1, true case "primes": // DOUBLE-STRUCK CAPITAL P - return rune(0x2119), true + return {'\u2119', 0}, 1, true case "prnE": // PRECEDES ABOVE NOT EQUAL TO - return rune(0x2ab5), true + return {'\u2ab5', 0}, 1, true case "prnap": // PRECEDES ABOVE NOT ALMOST EQUAL TO - return rune(0x2ab9), true + return {'\u2ab9', 0}, 1, true case "prnsim": // PRECEDES BUT NOT EQUIVALENT TO - return rune(0x22e8), true + return {'\u22e8', 0}, 1, true case "prod": // N-ARY PRODUCT - return rune(0x220f), true + return {'\u220f', 0}, 1, true case "profalar": // ALL AROUND-PROFILE - return rune(0x232e), true + return {'\u232e', 0}, 1, true case "profline": // ARC - return rune(0x2312), true + return {'\u2312', 0}, 1, true case "profsurf": // SEGMENT - return rune(0x2313), true + return {'\u2313', 0}, 1, true case "prop": // PROPORTIONAL TO - return rune(0x221d), true + return {'\u221d', 0}, 1, true case "propto": // PROPORTIONAL TO - return rune(0x221d), true + return {'\u221d', 0}, 1, true case "prsim": // PRECEDES OR EQUIVALENT TO - return rune(0x227e), true + return {'\u227e', 0}, 1, true case "prurel": // PRECEDES UNDER RELATION - return rune(0x22b0), true + return {'\u22b0', 0}, 1, true case "pscr": // MATHEMATICAL SCRIPT SMALL P - return rune(0x01d4c5), true + return {'\U0001d4c5', 0}, 1, true case "psgr": // GREEK SMALL LETTER PSI - return rune(0x03c8), true + return {'\u03c8', 0}, 1, true case "psi": // GREEK SMALL LETTER PSI - return rune(0x03c8), true + return {'\u03c8', 0}, 1, true case "puncsp": // PUNCTUATION SPACE - return rune(0x2008), true + return {'\u2008', 0}, 1, true } case 'q': switch name { case "qfr": // MATHEMATICAL FRAKTUR SMALL Q - return rune(0x01d52e), true + return {'\U0001d52e', 0}, 1, true case "qint": // QUADRUPLE INTEGRAL OPERATOR - return rune(0x2a0c), true + return {'\u2a0c', 0}, 1, true case "qopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Q - return rune(0x01d562), true + return {'\U0001d562', 0}, 1, true case "qprime": // QUADRUPLE PRIME - return rune(0x2057), true + return {'\u2057', 0}, 1, true case "qscr": // MATHEMATICAL SCRIPT SMALL Q - return rune(0x01d4c6), true + return {'\U0001d4c6', 0}, 1, true case "quaternions": // DOUBLE-STRUCK CAPITAL H - return rune(0x210d), true + return {'\u210d', 0}, 1, true case "quatint": // QUATERNION INTEGRAL OPERATOR - return rune(0x2a16), true + return {'\u2a16', 0}, 1, true case "quest": // QUESTION MARK - return rune(0x3f), true + return {'?', 0}, 1, true case "questeq": // QUESTIONED EQUAL TO - return rune(0x225f), true + return {'\u225f', 0}, 1, true case "quot": // QUOTATION MARK - return rune(0x22), true + return {'"', 0}, 1, true } case 'r': switch name { case "rAarr": // RIGHTWARDS TRIPLE ARROW - return rune(0x21db), true + return {'\u21db', 0}, 1, true case "rArr": // RIGHTWARDS DOUBLE ARROW - return rune(0x21d2), true + return {'\u21d2', 0}, 1, true case "rAtail": // RIGHTWARDS DOUBLE ARROW-TAIL - return rune(0x291c), true + return {'\u291c', 0}, 1, true case "rBarr": // RIGHTWARDS TRIPLE DASH ARROW - return rune(0x290f), true + return {'\u290f', 0}, 1, true case "rHar": // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN - return rune(0x2964), true + return {'\u2964', 0}, 1, true case "race": // REVERSED TILDE with underline - return rune(0x223d), true + return {'\u223d', '\u0331'}, 2, true case "racute": // LATIN SMALL LETTER R WITH ACUTE - return rune(0x0155), true + return {'\u0155', 0}, 1, true case "radic": // SQUARE ROOT - return rune(0x221a), true + return {'\u221a', 0}, 1, true case "raemptyv": // EMPTY SET WITH RIGHT ARROW ABOVE - return rune(0x29b3), true + return {'\u29b3', 0}, 1, true case "rang": // MATHEMATICAL RIGHT ANGLE BRACKET - return rune(0x27e9), true + return {'\u27e9', 0}, 1, true case "rangd": // RIGHT ANGLE BRACKET WITH DOT - return rune(0x2992), true + return {'\u2992', 0}, 1, true case "range": // REVERSED ANGLE WITH UNDERBAR - return rune(0x29a5), true + return {'\u29a5', 0}, 1, true case "rangle": // MATHEMATICAL RIGHT ANGLE BRACKET - return rune(0x27e9), true + return {'\u27e9', 0}, 1, true case "raquo": // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - return rune(0xbb), true + return {'»', 0}, 1, true case "rarr": // RIGHTWARDS ARROW - return rune(0x2192), true + return {'\u2192', 0}, 1, true case "rarr2": // RIGHTWARDS PAIRED ARROWS - return rune(0x21c9), true + return {'\u21c9', 0}, 1, true case "rarr3": // THREE RIGHTWARDS ARROWS - return rune(0x21f6), true + return {'\u21f6', 0}, 1, true case "rarrap": // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO - return rune(0x2975), true + return {'\u2975', 0}, 1, true case "rarrb": // RIGHTWARDS ARROW TO BAR - return rune(0x21e5), true + return {'\u21e5', 0}, 1, true case "rarrbfs": // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND - return rune(0x2920), true + return {'\u2920', 0}, 1, true case "rarrc": // WAVE ARROW POINTING DIRECTLY RIGHT - return rune(0x2933), true + return {'\u2933', 0}, 1, true case "rarrfs": // RIGHTWARDS ARROW TO BLACK DIAMOND - return rune(0x291e), true + return {'\u291e', 0}, 1, true case "rarrhk": // RIGHTWARDS ARROW WITH HOOK - return rune(0x21aa), true + return {'\u21aa', 0}, 1, true case "rarrlp": // RIGHTWARDS ARROW WITH LOOP - return rune(0x21ac), true + return {'\u21ac', 0}, 1, true case "rarrpl": // RIGHTWARDS ARROW WITH PLUS BELOW - return rune(0x2945), true + return {'\u2945', 0}, 1, true case "rarrsim": // RIGHTWARDS ARROW ABOVE TILDE OPERATOR - return rune(0x2974), true + return {'\u2974', 0}, 1, true case "rarrtl": // RIGHTWARDS ARROW WITH TAIL - return rune(0x21a3), true + return {'\u21a3', 0}, 1, true case "rarrw": // RIGHTWARDS WAVE ARROW - return rune(0x219d), true + return {'\u219d', 0}, 1, true case "rarrx": // RIGHTWARDS ARROW THROUGH X - return rune(0x2947), true + return {'\u2947', 0}, 1, true case "ratail": // RIGHTWARDS ARROW-TAIL - return rune(0x291a), true + return {'\u291a', 0}, 1, true case "ratio": // RATIO - return rune(0x2236), true + return {'\u2236', 0}, 1, true case "rationals": // DOUBLE-STRUCK CAPITAL Q - return rune(0x211a), true + return {'\u211a', 0}, 1, true case "rbarr": // RIGHTWARDS DOUBLE DASH ARROW - return rune(0x290d), true + return {'\u290d', 0}, 1, true case "rbbrk": // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT - return rune(0x2773), true + return {'\u2773', 0}, 1, true case "rbrace": // RIGHT CURLY BRACKET - return rune(0x7d), true + return {'}', 0}, 1, true case "rbrack": // RIGHT SQUARE BRACKET - return rune(0x5d), true + return {']', 0}, 1, true case "rbrke": // RIGHT SQUARE BRACKET WITH UNDERBAR - return rune(0x298c), true + return {'\u298c', 0}, 1, true case "rbrksld": // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - return rune(0x298e), true + return {'\u298e', 0}, 1, true case "rbrkslu": // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER - return rune(0x2990), true + return {'\u2990', 0}, 1, true case "rcaron": // LATIN SMALL LETTER R WITH CARON - return rune(0x0159), true + return {'\u0159', 0}, 1, true case "rcedil": // LATIN SMALL LETTER R WITH CEDILLA - return rune(0x0157), true + return {'\u0157', 0}, 1, true case "rceil": // RIGHT CEILING - return rune(0x2309), true + return {'\u2309', 0}, 1, true case "rcub": // RIGHT CURLY BRACKET - return rune(0x7d), true + return {'}', 0}, 1, true case "rcy": // CYRILLIC SMALL LETTER ER - return rune(0x0440), true + return {'\u0440', 0}, 1, true case "rdca": // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS - return rune(0x2937), true + return {'\u2937', 0}, 1, true case "rdharb": // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR - return rune(0x2957), true + return {'\u2957', 0}, 1, true case "rdiag": // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT - return rune(0x2571), true + return {'\u2571', 0}, 1, true case "rdiofdi": // RISING DIAGONAL CROSSING FALLING DIAGONAL - return rune(0x292b), true + return {'\u292b', 0}, 1, true case "rdldhar": // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN - return rune(0x2969), true + return {'\u2969', 0}, 1, true case "rdosearr": // RISING DIAGONAL CROSSING SOUTH EAST ARROW - return rune(0x2930), true + return {'\u2930', 0}, 1, true case "rdquo": // RIGHT DOUBLE QUOTATION MARK - return rune(0x201d), true + return {'\u201d', 0}, 1, true case "rdquor": // RIGHT DOUBLE QUOTATION MARK - return rune(0x201d), true + return {'\u201d', 0}, 1, true case "rdsh": // DOWNWARDS ARROW WITH TIP RIGHTWARDS - return rune(0x21b3), true + return {'\u21b3', 0}, 1, true case "real": // BLACK-LETTER CAPITAL R - return rune(0x211c), true + return {'\u211c', 0}, 1, true case "realine": // SCRIPT CAPITAL R - return rune(0x211b), true + return {'\u211b', 0}, 1, true case "realpart": // BLACK-LETTER CAPITAL R - return rune(0x211c), true + return {'\u211c', 0}, 1, true case "reals": // DOUBLE-STRUCK CAPITAL R - return rune(0x211d), true + return {'\u211d', 0}, 1, true case "rect": // WHITE RECTANGLE - return rune(0x25ad), true + return {'\u25ad', 0}, 1, true case "reg": // REGISTERED SIGN - return rune(0xae), true + return {'®', 0}, 1, true case "rfbowtie": // BOWTIE WITH RIGHT HALF BLACK - return rune(0x29d2), true + return {'\u29d2', 0}, 1, true case "rfisht": // RIGHT FISH TAIL - return rune(0x297d), true + return {'\u297d', 0}, 1, true case "rfloor": // RIGHT FLOOR - return rune(0x230b), true + return {'\u230b', 0}, 1, true case "rfr": // MATHEMATICAL FRAKTUR SMALL R - return rune(0x01d52f), true + return {'\U0001d52f', 0}, 1, true case "rftimes": // TIMES WITH RIGHT HALF BLACK - return rune(0x29d5), true + return {'\u29d5', 0}, 1, true case "rgr": // GREEK SMALL LETTER RHO - return rune(0x03c1), true + return {'\u03c1', 0}, 1, true case "rhard": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21c1), true + return {'\u21c1', 0}, 1, true case "rharu": // RIGHTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21c0), true + return {'\u21c0', 0}, 1, true case "rharul": // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - return rune(0x296c), true + return {'\u296c', 0}, 1, true case "rho": // GREEK SMALL LETTER RHO - return rune(0x03c1), true + return {'\u03c1', 0}, 1, true case "rhov": // GREEK RHO SYMBOL - return rune(0x03f1), true + return {'\u03f1', 0}, 1, true case "rightarrow": // RIGHTWARDS ARROW - return rune(0x2192), true + return {'\u2192', 0}, 1, true case "rightarrowtail": // RIGHTWARDS ARROW WITH TAIL - return rune(0x21a3), true + return {'\u21a3', 0}, 1, true case "rightharpoondown": // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - return rune(0x21c1), true + return {'\u21c1', 0}, 1, true case "rightharpoonup": // RIGHTWARDS HARPOON WITH BARB UPWARDS - return rune(0x21c0), true + return {'\u21c0', 0}, 1, true case "rightleftarrows": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true + return {'\u21c4', 0}, 1, true case "rightleftharpoons": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true + return {'\u21cc', 0}, 1, true case "rightrightarrows": // RIGHTWARDS PAIRED ARROWS - return rune(0x21c9), true + return {'\u21c9', 0}, 1, true case "rightsquigarrow": // RIGHTWARDS WAVE ARROW - return rune(0x219d), true + return {'\u219d', 0}, 1, true case "rightthreetimes": // RIGHT SEMIDIRECT PRODUCT - return rune(0x22cc), true + return {'\u22cc', 0}, 1, true case "rimply": // RIGHT DOUBLE ARROW WITH ROUNDED HEAD - return rune(0x2970), true + return {'\u2970', 0}, 1, true case "ring": // RING ABOVE - return rune(0x02da), true + return {'\u02da', 0}, 1, true case "risingdotseq": // IMAGE OF OR APPROXIMATELY EQUAL TO - return rune(0x2253), true + return {'\u2253', 0}, 1, true case "rlarr": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true + return {'\u21c4', 0}, 1, true case "rlarr2": // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - return rune(0x21c4), true + return {'\u21c4', 0}, 1, true case "rlhar": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true + return {'\u21cc', 0}, 1, true case "rlhar2": // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - return rune(0x21cc), true + return {'\u21cc', 0}, 1, true case "rlm": // RIGHT-TO-LEFT MARK - return rune(0x200f), true + return {'\u200f', 0}, 1, true case "rmoust": // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - return rune(0x23b1), true + return {'\u23b1', 0}, 1, true case "rmoustache": // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - return rune(0x23b1), true + return {'\u23b1', 0}, 1, true case "rnmid": // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH - return rune(0x2aee), true + return {'\u2aee', 0}, 1, true case "roang": // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET - return rune(0x27ed), true + return {'\u27ed', 0}, 1, true case "roarr": // RIGHTWARDS OPEN-HEADED ARROW - return rune(0x21fe), true + return {'\u21fe', 0}, 1, true case "robrk": // MATHEMATICAL RIGHT WHITE SQUARE BRACKET - return rune(0x27e7), true + return {'\u27e7', 0}, 1, true case "rocub": // RIGHT WHITE CURLY BRACKET - return rune(0x2984), true + return {'\u2984', 0}, 1, true case "ropar": // RIGHT WHITE PARENTHESIS - return rune(0x2986), true + return {'\u2986', 0}, 1, true case "ropf": // MATHEMATICAL DOUBLE-STRUCK SMALL R - return rune(0x01d563), true + return {'\U0001d563', 0}, 1, true case "roplus": // PLUS SIGN IN RIGHT HALF CIRCLE - return rune(0x2a2e), true + return {'\u2a2e', 0}, 1, true case "rotimes": // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE - return rune(0x2a35), true + return {'\u2a35', 0}, 1, true case "rpar": // RIGHT PARENTHESIS - return rune(0x29), true + return {')', 0}, 1, true case "rpargt": // RIGHT ARC GREATER-THAN BRACKET - return rune(0x2994), true + return {'\u2994', 0}, 1, true case "rppolint": // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE - return rune(0x2a12), true + return {'\u2a12', 0}, 1, true case "rrarr": // RIGHTWARDS PAIRED ARROWS - return rune(0x21c9), true + return {'\u21c9', 0}, 1, true case "rsaquo": // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - return rune(0x203a), true + return {'\u203a', 0}, 1, true case "rscr": // MATHEMATICAL SCRIPT SMALL R - return rune(0x01d4c7), true + return {'\U0001d4c7', 0}, 1, true case "rsh": // UPWARDS ARROW WITH TIP RIGHTWARDS - return rune(0x21b1), true + return {'\u21b1', 0}, 1, true case "rsolbar": // REVERSE SOLIDUS WITH HORIZONTAL STROKE - return rune(0x29f7), true + return {'\u29f7', 0}, 1, true case "rsqb": // RIGHT SQUARE BRACKET - return rune(0x5d), true + return {']', 0}, 1, true case "rsquo": // RIGHT SINGLE QUOTATION MARK - return rune(0x2019), true + return {'\u2019', 0}, 1, true case "rsquor": // RIGHT SINGLE QUOTATION MARK - return rune(0x2019), true + return {'\u2019', 0}, 1, true case "rthree": // RIGHT SEMIDIRECT PRODUCT - return rune(0x22cc), true + return {'\u22cc', 0}, 1, true case "rtimes": // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT - return rune(0x22ca), true + return {'\u22ca', 0}, 1, true case "rtri": // WHITE RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b9), true + return {'\u25b9', 0}, 1, true case "rtrie": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - return rune(0x22b5), true + return {'\u22b5', 0}, 1, true case "rtrif": // BLACK RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b8), true + return {'\u25b8', 0}, 1, true case "rtriltri": // RIGHT TRIANGLE ABOVE LEFT TRIANGLE - return rune(0x29ce), true + return {'\u29ce', 0}, 1, true case "ruharb": // RIGHTWARDS HARPOON WITH BARB UP TO BAR - return rune(0x2953), true + return {'\u2953', 0}, 1, true case "ruluhar": // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP - return rune(0x2968), true + return {'\u2968', 0}, 1, true case "rx": // PRESCRIPTION TAKE - return rune(0x211e), true + return {'\u211e', 0}, 1, true } case 's': switch name { case "sacute": // LATIN SMALL LETTER S WITH ACUTE - return rune(0x015b), true + return {'\u015b', 0}, 1, true case "samalg": // N-ARY COPRODUCT - return rune(0x2210), true + return {'\u2210', 0}, 1, true case "sampi": // GREEK LETTER SAMPI - return rune(0x03e0), true + return {'\u03e0', 0}, 1, true case "sbquo": // SINGLE LOW-9 QUOTATION MARK - return rune(0x201a), true + return {'\u201a', 0}, 1, true case "sbsol": // SMALL REVERSE SOLIDUS - return rune(0xfe68), true + return {'\ufe68', 0}, 1, true case "sc": // SUCCEEDS - return rune(0x227b), true + return {'\u227b', 0}, 1, true case "scE": // SUCCEEDS ABOVE EQUALS SIGN - return rune(0x2ab4), true + return {'\u2ab4', 0}, 1, true case "scap": // SUCCEEDS ABOVE ALMOST EQUAL TO - return rune(0x2ab8), true + return {'\u2ab8', 0}, 1, true case "scaron": // LATIN SMALL LETTER S WITH CARON - return rune(0x0161), true + return {'\u0161', 0}, 1, true case "sccue": // SUCCEEDS OR EQUAL TO - return rune(0x227d), true + return {'\u227d', 0}, 1, true case "sce": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2ab0), true + return {'\u2ab0', 0}, 1, true case "scedil": // LATIN SMALL LETTER S WITH CEDILLA - return rune(0x015f), true + return {'\u015f', 0}, 1, true case "scirc": // LATIN SMALL LETTER S WITH CIRCUMFLEX - return rune(0x015d), true + return {'\u015d', 0}, 1, true case "scnE": // SUCCEEDS ABOVE NOT EQUAL TO - return rune(0x2ab6), true + return {'\u2ab6', 0}, 1, true case "scnap": // SUCCEEDS ABOVE NOT ALMOST EQUAL TO - return rune(0x2aba), true + return {'\u2aba', 0}, 1, true case "scnsim": // SUCCEEDS BUT NOT EQUIVALENT TO - return rune(0x22e9), true + return {'\u22e9', 0}, 1, true case "scpolint": // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE - return rune(0x2a13), true + return {'\u2a13', 0}, 1, true case "scsim": // SUCCEEDS OR EQUIVALENT TO - return rune(0x227f), true + return {'\u227f', 0}, 1, true case "scy": // CYRILLIC SMALL LETTER ES - return rune(0x0441), true + return {'\u0441', 0}, 1, true case "sdot": // DOT OPERATOR - return rune(0x22c5), true + return {'\u22c5', 0}, 1, true case "sdotb": // SQUARED DOT OPERATOR - return rune(0x22a1), true + return {'\u22a1', 0}, 1, true case "sdote": // EQUALS SIGN WITH DOT BELOW - return rune(0x2a66), true + return {'\u2a66', 0}, 1, true case "seArr": // SOUTH EAST DOUBLE ARROW - return rune(0x21d8), true + return {'\u21d8', 0}, 1, true case "searhk": // SOUTH EAST ARROW WITH HOOK - return rune(0x2925), true + return {'\u2925', 0}, 1, true case "searr": // SOUTH EAST ARROW - return rune(0x2198), true + return {'\u2198', 0}, 1, true case "searrow": // SOUTH EAST ARROW - return rune(0x2198), true + return {'\u2198', 0}, 1, true case "sect": // SECTION SIGN - return rune(0xa7), true + return {'§', 0}, 1, true case "semi": // SEMICOLON - return rune(0x3b), true + return {';', 0}, 1, true case "seonearr": // SOUTH EAST ARROW CROSSING NORTH EAST ARROW - return rune(0x292d), true + return {'\u292d', 0}, 1, true case "seswar": // SOUTH EAST ARROW AND SOUTH WEST ARROW - return rune(0x2929), true + return {'\u2929', 0}, 1, true case "setminus": // SET MINUS - return rune(0x2216), true + return {'\u2216', 0}, 1, true case "setmn": // SET MINUS - return rune(0x2216), true + return {'\u2216', 0}, 1, true case "sext": // SIX POINTED BLACK STAR - return rune(0x2736), true + return {'\u2736', 0}, 1, true case "sfgr": // GREEK SMALL LETTER FINAL SIGMA - return rune(0x03c2), true + return {'\u03c2', 0}, 1, true case "sfr": // MATHEMATICAL FRAKTUR SMALL S - return rune(0x01d530), true + return {'\U0001d530', 0}, 1, true case "sfrown": // FROWN - return rune(0x2322), true + return {'\u2322', 0}, 1, true case "sgr": // GREEK SMALL LETTER SIGMA - return rune(0x03c3), true + return {'\u03c3', 0}, 1, true case "sharp": // MUSIC SHARP SIGN - return rune(0x266f), true + return {'\u266f', 0}, 1, true case "shchcy": // CYRILLIC SMALL LETTER SHCHA - return rune(0x0449), true + return {'\u0449', 0}, 1, true case "shcy": // CYRILLIC SMALL LETTER SHA - return rune(0x0448), true + return {'\u0448', 0}, 1, true case "shortmid": // DIVIDES - return rune(0x2223), true + return {'\u2223', 0}, 1, true case "shortparallel": // PARALLEL TO - return rune(0x2225), true + return {'\u2225', 0}, 1, true case "shuffle": // SHUFFLE PRODUCT - return rune(0x29e2), true + return {'\u29e2', 0}, 1, true case "shy": // SOFT HYPHEN - return rune(0xad), true + return {'\u00ad', 0}, 1, true case "sigma": // GREEK SMALL LETTER SIGMA - return rune(0x03c3), true + return {'\u03c3', 0}, 1, true case "sigmaf": // GREEK SMALL LETTER FINAL SIGMA - return rune(0x03c2), true + return {'\u03c2', 0}, 1, true case "sigmav": // GREEK SMALL LETTER FINAL SIGMA - return rune(0x03c2), true + return {'\u03c2', 0}, 1, true case "sim": // TILDE OPERATOR - return rune(0x223c), true + return {'\u223c', 0}, 1, true case "simdot": // TILDE OPERATOR WITH DOT ABOVE - return rune(0x2a6a), true + return {'\u2a6a', 0}, 1, true case "sime": // ASYMPTOTICALLY EQUAL TO - return rune(0x2243), true + return {'\u2243', 0}, 1, true case "simeq": // ASYMPTOTICALLY EQUAL TO - return rune(0x2243), true + return {'\u2243', 0}, 1, true case "simg": // SIMILAR OR GREATER-THAN - return rune(0x2a9e), true + return {'\u2a9e', 0}, 1, true case "simgE": // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN - return rune(0x2aa0), true + return {'\u2aa0', 0}, 1, true case "siml": // SIMILAR OR LESS-THAN - return rune(0x2a9d), true + return {'\u2a9d', 0}, 1, true case "simlE": // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN - return rune(0x2a9f), true + return {'\u2a9f', 0}, 1, true case "simne": // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO - return rune(0x2246), true + return {'\u2246', 0}, 1, true case "simplus": // PLUS SIGN WITH TILDE ABOVE - return rune(0x2a24), true + return {'\u2a24', 0}, 1, true case "simrarr": // TILDE OPERATOR ABOVE RIGHTWARDS ARROW - return rune(0x2972), true + return {'\u2972', 0}, 1, true case "slarr": // LEFTWARDS ARROW - return rune(0x2190), true + return {'\u2190', 0}, 1, true case "slint": // INTEGRAL AVERAGE WITH SLASH - return rune(0x2a0f), true + return {'\u2a0f', 0}, 1, true case "smallsetminus": // SET MINUS - return rune(0x2216), true + return {'\u2216', 0}, 1, true case "smashp": // SMASH PRODUCT - return rune(0x2a33), true + return {'\u2a33', 0}, 1, true case "smeparsl": // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE - return rune(0x29e4), true + return {'\u29e4', 0}, 1, true case "smid": // DIVIDES - return rune(0x2223), true + return {'\u2223', 0}, 1, true case "smile": // SMILE - return rune(0x2323), true + return {'\u2323', 0}, 1, true case "smt": // SMALLER THAN - return rune(0x2aaa), true + return {'\u2aaa', 0}, 1, true case "smte": // SMALLER THAN OR EQUAL TO - return rune(0x2aac), true + return {'\u2aac', 0}, 1, true case "smtes": // SMALLER THAN OR slanted EQUAL - return rune(0x2aac), true + return {'\u2aac', '\ufe00'}, 2, true case "softcy": // CYRILLIC SMALL LETTER SOFT SIGN - return rune(0x044c), true + return {'\u044c', 0}, 1, true case "sol": // SOLIDUS - return rune(0x2f), true + return {'/', 0}, 1, true case "solb": // SQUARED RISING DIAGONAL SLASH - return rune(0x29c4), true + return {'\u29c4', 0}, 1, true case "solbar": // APL FUNCTIONAL SYMBOL SLASH BAR - return rune(0x233f), true + return {'\u233f', 0}, 1, true case "sopf": // MATHEMATICAL DOUBLE-STRUCK SMALL S - return rune(0x01d564), true + return {'\U0001d564', 0}, 1, true case "spades": // BLACK SPADE SUIT - return rune(0x2660), true + return {'\u2660', 0}, 1, true case "spadesuit": // BLACK SPADE SUIT - return rune(0x2660), true + return {'\u2660', 0}, 1, true case "spar": // PARALLEL TO - return rune(0x2225), true + return {'\u2225', 0}, 1, true case "sqcap": // SQUARE CAP - return rune(0x2293), true + return {'\u2293', 0}, 1, true case "sqcaps": // SQUARE CAP with serifs - return rune(0x2293), true + return {'\u2293', '\ufe00'}, 2, true case "sqcup": // SQUARE CUP - return rune(0x2294), true + return {'\u2294', 0}, 1, true case "sqcups": // SQUARE CUP with serifs - return rune(0x2294), true + return {'\u2294', '\ufe00'}, 2, true case "sqsub": // SQUARE IMAGE OF - return rune(0x228f), true + return {'\u228f', 0}, 1, true case "sqsube": // SQUARE IMAGE OF OR EQUAL TO - return rune(0x2291), true + return {'\u2291', 0}, 1, true case "sqsubset": // SQUARE IMAGE OF - return rune(0x228f), true + return {'\u228f', 0}, 1, true case "sqsubseteq": // SQUARE IMAGE OF OR EQUAL TO - return rune(0x2291), true + return {'\u2291', 0}, 1, true case "sqsup": // SQUARE ORIGINAL OF - return rune(0x2290), true + return {'\u2290', 0}, 1, true case "sqsupe": // SQUARE ORIGINAL OF OR EQUAL TO - return rune(0x2292), true + return {'\u2292', 0}, 1, true case "sqsupset": // SQUARE ORIGINAL OF - return rune(0x2290), true + return {'\u2290', 0}, 1, true case "sqsupseteq": // SQUARE ORIGINAL OF OR EQUAL TO - return rune(0x2292), true + return {'\u2292', 0}, 1, true case "squ": // WHITE SQUARE - return rune(0x25a1), true + return {'\u25a1', 0}, 1, true case "square": // WHITE SQUARE - return rune(0x25a1), true + return {'\u25a1', 0}, 1, true case "squarf": // BLACK SMALL SQUARE - return rune(0x25aa), true + return {'\u25aa', 0}, 1, true case "squb": // SQUARED SQUARE - return rune(0x29c8), true + return {'\u29c8', 0}, 1, true case "squerr": // ERROR-BARRED WHITE SQUARE - return rune(0x29ee), true + return {'\u29ee', 0}, 1, true case "squf": // BLACK SMALL SQUARE - return rune(0x25aa), true + return {'\u25aa', 0}, 1, true case "squferr": // ERROR-BARRED BLACK SQUARE - return rune(0x29ef), true + return {'\u29ef', 0}, 1, true case "srarr": // RIGHTWARDS ARROW - return rune(0x2192), true + return {'\u2192', 0}, 1, true case "sscr": // MATHEMATICAL SCRIPT SMALL S - return rune(0x01d4c8), true + return {'\U0001d4c8', 0}, 1, true case "ssetmn": // SET MINUS - return rune(0x2216), true + return {'\u2216', 0}, 1, true case "ssmile": // SMILE - return rune(0x2323), true + return {'\u2323', 0}, 1, true case "sstarf": // STAR OPERATOR - return rune(0x22c6), true + return {'\u22c6', 0}, 1, true case "star": // WHITE STAR - return rune(0x2606), true + return {'\u2606', 0}, 1, true case "starf": // BLACK STAR - return rune(0x2605), true + return {'\u2605', 0}, 1, true case "stigma": // GREEK LETTER STIGMA - return rune(0x03da), true + return {'\u03da', 0}, 1, true case "straightepsilon": // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true + return {'\u03f5', 0}, 1, true case "straightphi": // GREEK PHI SYMBOL - return rune(0x03d5), true + return {'\u03d5', 0}, 1, true case "strns": // MACRON - return rune(0xaf), true + return {'¯', 0}, 1, true case "sub": // SUBSET OF - return rune(0x2282), true + return {'\u2282', 0}, 1, true case "subE": // SUBSET OF ABOVE EQUALS SIGN - return rune(0x2ac5), true + return {'\u2ac5', 0}, 1, true case "subdot": // SUBSET WITH DOT - return rune(0x2abd), true + return {'\u2abd', 0}, 1, true case "sube": // SUBSET OF OR EQUAL TO - return rune(0x2286), true + return {'\u2286', 0}, 1, true case "subedot": // SUBSET OF OR EQUAL TO WITH DOT ABOVE - return rune(0x2ac3), true + return {'\u2ac3', 0}, 1, true case "submult": // SUBSET WITH MULTIPLICATION SIGN BELOW - return rune(0x2ac1), true + return {'\u2ac1', 0}, 1, true case "subnE": // SUBSET OF ABOVE NOT EQUAL TO - return rune(0x2acb), true + return {'\u2acb', 0}, 1, true case "subne": // SUBSET OF WITH NOT EQUAL TO - return rune(0x228a), true + return {'\u228a', 0}, 1, true case "subplus": // SUBSET WITH PLUS SIGN BELOW - return rune(0x2abf), true + return {'\u2abf', 0}, 1, true case "subrarr": // SUBSET ABOVE RIGHTWARDS ARROW - return rune(0x2979), true + return {'\u2979', 0}, 1, true case "subset": // SUBSET OF - return rune(0x2282), true + return {'\u2282', 0}, 1, true case "subseteq": // SUBSET OF OR EQUAL TO - return rune(0x2286), true + return {'\u2286', 0}, 1, true case "subseteqq": // SUBSET OF ABOVE EQUALS SIGN - return rune(0x2ac5), true + return {'\u2ac5', 0}, 1, true case "subsetneq": // SUBSET OF WITH NOT EQUAL TO - return rune(0x228a), true + return {'\u228a', 0}, 1, true case "subsetneqq": // SUBSET OF ABOVE NOT EQUAL TO - return rune(0x2acb), true + return {'\u2acb', 0}, 1, true case "subsim": // SUBSET OF ABOVE TILDE OPERATOR - return rune(0x2ac7), true + return {'\u2ac7', 0}, 1, true case "subsub": // SUBSET ABOVE SUBSET - return rune(0x2ad5), true + return {'\u2ad5', 0}, 1, true case "subsup": // SUBSET ABOVE SUPERSET - return rune(0x2ad3), true + return {'\u2ad3', 0}, 1, true case "succ": // SUCCEEDS - return rune(0x227b), true + return {'\u227b', 0}, 1, true case "succapprox": // SUCCEEDS ABOVE ALMOST EQUAL TO - return rune(0x2ab8), true + return {'\u2ab8', 0}, 1, true case "succcurlyeq": // SUCCEEDS OR EQUAL TO - return rune(0x227d), true + return {'\u227d', 0}, 1, true case "succeq": // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - return rune(0x2ab0), true + return {'\u2ab0', 0}, 1, true case "succnapprox": // SUCCEEDS ABOVE NOT ALMOST EQUAL TO - return rune(0x2aba), true + return {'\u2aba', 0}, 1, true case "succneqq": // SUCCEEDS ABOVE NOT EQUAL TO - return rune(0x2ab6), true + return {'\u2ab6', 0}, 1, true case "succnsim": // SUCCEEDS BUT NOT EQUIVALENT TO - return rune(0x22e9), true + return {'\u22e9', 0}, 1, true case "succsim": // SUCCEEDS OR EQUIVALENT TO - return rune(0x227f), true + return {'\u227f', 0}, 1, true case "sum": // N-ARY SUMMATION - return rune(0x2211), true + return {'\u2211', 0}, 1, true case "sumint": // SUMMATION WITH INTEGRAL - return rune(0x2a0b), true + return {'\u2a0b', 0}, 1, true case "sung": // EIGHTH NOTE - return rune(0x266a), true + return {'\u266a', 0}, 1, true case "sup": // SUPERSET OF - return rune(0x2283), true + return {'\u2283', 0}, 1, true case "sup1": // SUPERSCRIPT ONE - return rune(0xb9), true + return {'¹', 0}, 1, true case "sup2": // SUPERSCRIPT TWO - return rune(0xb2), true + return {'²', 0}, 1, true case "sup3": // SUPERSCRIPT THREE - return rune(0xb3), true + return {'³', 0}, 1, true case "supE": // SUPERSET OF ABOVE EQUALS SIGN - return rune(0x2ac6), true + return {'\u2ac6', 0}, 1, true case "supdot": // SUPERSET WITH DOT - return rune(0x2abe), true + return {'\u2abe', 0}, 1, true case "supdsub": // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET - return rune(0x2ad8), true + return {'\u2ad8', 0}, 1, true case "supe": // SUPERSET OF OR EQUAL TO - return rune(0x2287), true + return {'\u2287', 0}, 1, true case "supedot": // SUPERSET OF OR EQUAL TO WITH DOT ABOVE - return rune(0x2ac4), true + return {'\u2ac4', 0}, 1, true case "suphsol": // SUPERSET PRECEDING SOLIDUS - return rune(0x27c9), true + return {'\u27c9', 0}, 1, true case "suphsub": // SUPERSET BESIDE SUBSET - return rune(0x2ad7), true + return {'\u2ad7', 0}, 1, true case "suplarr": // SUPERSET ABOVE LEFTWARDS ARROW - return rune(0x297b), true + return {'\u297b', 0}, 1, true case "supmult": // SUPERSET WITH MULTIPLICATION SIGN BELOW - return rune(0x2ac2), true + return {'\u2ac2', 0}, 1, true case "supnE": // SUPERSET OF ABOVE NOT EQUAL TO - return rune(0x2acc), true + return {'\u2acc', 0}, 1, true case "supne": // SUPERSET OF WITH NOT EQUAL TO - return rune(0x228b), true + return {'\u228b', 0}, 1, true case "supplus": // SUPERSET WITH PLUS SIGN BELOW - return rune(0x2ac0), true + return {'\u2ac0', 0}, 1, true case "supset": // SUPERSET OF - return rune(0x2283), true + return {'\u2283', 0}, 1, true case "supseteq": // SUPERSET OF OR EQUAL TO - return rune(0x2287), true + return {'\u2287', 0}, 1, true case "supseteqq": // SUPERSET OF ABOVE EQUALS SIGN - return rune(0x2ac6), true + return {'\u2ac6', 0}, 1, true case "supsetneq": // SUPERSET OF WITH NOT EQUAL TO - return rune(0x228b), true + return {'\u228b', 0}, 1, true case "supsetneqq": // SUPERSET OF ABOVE NOT EQUAL TO - return rune(0x2acc), true + return {'\u2acc', 0}, 1, true case "supsim": // SUPERSET OF ABOVE TILDE OPERATOR - return rune(0x2ac8), true + return {'\u2ac8', 0}, 1, true case "supsub": // SUPERSET ABOVE SUBSET - return rune(0x2ad4), true + return {'\u2ad4', 0}, 1, true case "supsup": // SUPERSET ABOVE SUPERSET - return rune(0x2ad6), true + return {'\u2ad6', 0}, 1, true case "swArr": // SOUTH WEST DOUBLE ARROW - return rune(0x21d9), true + return {'\u21d9', 0}, 1, true case "swarhk": // SOUTH WEST ARROW WITH HOOK - return rune(0x2926), true + return {'\u2926', 0}, 1, true case "swarr": // SOUTH WEST ARROW - return rune(0x2199), true + return {'\u2199', 0}, 1, true case "swarrow": // SOUTH WEST ARROW - return rune(0x2199), true + return {'\u2199', 0}, 1, true case "swnwar": // SOUTH WEST ARROW AND NORTH WEST ARROW - return rune(0x292a), true + return {'\u292a', 0}, 1, true case "szlig": // LATIN SMALL LETTER SHARP S - return rune(0xdf), true + return {'ß', 0}, 1, true } case 't': switch name { case "target": // POSITION INDICATOR - return rune(0x2316), true + return {'\u2316', 0}, 1, true case "tau": // GREEK SMALL LETTER TAU - return rune(0x03c4), true + return {'\u03c4', 0}, 1, true case "tbrk": // TOP SQUARE BRACKET - return rune(0x23b4), true + return {'\u23b4', 0}, 1, true case "tcaron": // LATIN SMALL LETTER T WITH CARON - return rune(0x0165), true + return {'\u0165', 0}, 1, true case "tcedil": // LATIN SMALL LETTER T WITH CEDILLA - return rune(0x0163), true + return {'\u0163', 0}, 1, true case "tcy": // CYRILLIC SMALL LETTER TE - return rune(0x0442), true + return {'\u0442', 0}, 1, true case "tdot": // COMBINING THREE DOTS ABOVE - return rune(0x20db), true + return {'\u20db', 0}, 1, true case "telrec": // TELEPHONE RECORDER - return rune(0x2315), true + return {'\u2315', 0}, 1, true case "tfr": // MATHEMATICAL FRAKTUR SMALL T - return rune(0x01d531), true + return {'\U0001d531', 0}, 1, true case "tgr": // GREEK SMALL LETTER TAU - return rune(0x03c4), true + return {'\u03c4', 0}, 1, true case "there4": // THEREFORE - return rune(0x2234), true + return {'\u2234', 0}, 1, true case "therefore": // THEREFORE - return rune(0x2234), true + return {'\u2234', 0}, 1, true case "thermod": // THERMODYNAMIC - return rune(0x29e7), true + return {'\u29e7', 0}, 1, true case "theta": // GREEK SMALL LETTER THETA - return rune(0x03b8), true + return {'\u03b8', 0}, 1, true case "thetas": // GREEK SMALL LETTER THETA - return rune(0x03b8), true + return {'\u03b8', 0}, 1, true case "thetasym": // GREEK THETA SYMBOL - return rune(0x03d1), true + return {'\u03d1', 0}, 1, true case "thetav": // GREEK THETA SYMBOL - return rune(0x03d1), true + return {'\u03d1', 0}, 1, true case "thgr": // GREEK SMALL LETTER THETA - return rune(0x03b8), true + return {'\u03b8', 0}, 1, true case "thickapprox": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "thicksim": // TILDE OPERATOR - return rune(0x223c), true + return {'\u223c', 0}, 1, true case "thinsp": // THIN SPACE - return rune(0x2009), true + return {'\u2009', 0}, 1, true case "thkap": // ALMOST EQUAL TO - return rune(0x2248), true + return {'\u2248', 0}, 1, true case "thksim": // TILDE OPERATOR - return rune(0x223c), true + return {'\u223c', 0}, 1, true case "thorn": // LATIN SMALL LETTER THORN - return rune(0xfe), true + return {'þ', 0}, 1, true case "tilde": // SMALL TILDE - return rune(0x02dc), true + return {'\u02dc', 0}, 1, true case "timeint": // INTEGRAL WITH TIMES SIGN - return rune(0x2a18), true + return {'\u2a18', 0}, 1, true case "times": // MULTIPLICATION SIGN - return rune(0xd7), true + return {'×', 0}, 1, true case "timesb": // SQUARED TIMES - return rune(0x22a0), true + return {'\u22a0', 0}, 1, true case "timesbar": // MULTIPLICATION SIGN WITH UNDERBAR - return rune(0x2a31), true + return {'\u2a31', 0}, 1, true case "timesd": // MULTIPLICATION SIGN WITH DOT ABOVE - return rune(0x2a30), true + return {'\u2a30', 0}, 1, true case "tint": // TRIPLE INTEGRAL - return rune(0x222d), true + return {'\u222d', 0}, 1, true case "toea": // NORTH EAST ARROW AND SOUTH EAST ARROW - return rune(0x2928), true + return {'\u2928', 0}, 1, true case "top": // DOWN TACK - return rune(0x22a4), true + return {'\u22a4', 0}, 1, true case "topbot": // APL FUNCTIONAL SYMBOL I-BEAM - return rune(0x2336), true + return {'\u2336', 0}, 1, true case "topcir": // DOWN TACK WITH CIRCLE BELOW - return rune(0x2af1), true + return {'\u2af1', 0}, 1, true case "topf": // MATHEMATICAL DOUBLE-STRUCK SMALL T - return rune(0x01d565), true + return {'\U0001d565', 0}, 1, true case "topfork": // PITCHFORK WITH TEE TOP - return rune(0x2ada), true + return {'\u2ada', 0}, 1, true case "tosa": // SOUTH EAST ARROW AND SOUTH WEST ARROW - return rune(0x2929), true + return {'\u2929', 0}, 1, true case "tprime": // TRIPLE PRIME - return rune(0x2034), true + return {'\u2034', 0}, 1, true case "trade": // TRADE MARK SIGN - return rune(0x2122), true + return {'\u2122', 0}, 1, true case "triS": // S IN TRIANGLE - return rune(0x29cc), true + return {'\u29cc', 0}, 1, true case "triangle": // WHITE UP-POINTING SMALL TRIANGLE - return rune(0x25b5), true + return {'\u25b5', 0}, 1, true case "triangledown": // WHITE DOWN-POINTING SMALL TRIANGLE - return rune(0x25bf), true + return {'\u25bf', 0}, 1, true case "triangleleft": // WHITE LEFT-POINTING SMALL TRIANGLE - return rune(0x25c3), true + return {'\u25c3', 0}, 1, true case "trianglelefteq": // NORMAL SUBGROUP OF OR EQUAL TO - return rune(0x22b4), true + return {'\u22b4', 0}, 1, true case "triangleq": // DELTA EQUAL TO - return rune(0x225c), true + return {'\u225c', 0}, 1, true case "triangleright": // WHITE RIGHT-POINTING SMALL TRIANGLE - return rune(0x25b9), true + return {'\u25b9', 0}, 1, true case "trianglerighteq": // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - return rune(0x22b5), true + return {'\u22b5', 0}, 1, true case "tribar": // TRIANGLE WITH UNDERBAR - return rune(0x29cb), true + return {'\u29cb', 0}, 1, true case "tridot": // WHITE UP-POINTING TRIANGLE WITH DOT - return rune(0x25ec), true + return {'\u25ec', 0}, 1, true case "tridoto": // TRIANGLE WITH DOT ABOVE - return rune(0x29ca), true + return {'\u29ca', 0}, 1, true case "trie": // DELTA EQUAL TO - return rune(0x225c), true + return {'\u225c', 0}, 1, true case "triminus": // MINUS SIGN IN TRIANGLE - return rune(0x2a3a), true + return {'\u2a3a', 0}, 1, true case "triplus": // PLUS SIGN IN TRIANGLE - return rune(0x2a39), true + return {'\u2a39', 0}, 1, true case "trisb": // TRIANGLE WITH SERIFS AT BOTTOM - return rune(0x29cd), true + return {'\u29cd', 0}, 1, true case "tritime": // MULTIPLICATION SIGN IN TRIANGLE - return rune(0x2a3b), true + return {'\u2a3b', 0}, 1, true case "trpezium": // WHITE TRAPEZIUM - return rune(0x23e2), true + return {'\u23e2', 0}, 1, true case "tscr": // MATHEMATICAL SCRIPT SMALL T - return rune(0x01d4c9), true + return {'\U0001d4c9', 0}, 1, true case "tscy": // CYRILLIC SMALL LETTER TSE - return rune(0x0446), true + return {'\u0446', 0}, 1, true case "tshcy": // CYRILLIC SMALL LETTER TSHE - return rune(0x045b), true + return {'\u045b', 0}, 1, true case "tstrok": // LATIN SMALL LETTER T WITH STROKE - return rune(0x0167), true + return {'\u0167', 0}, 1, true case "tverbar": // TRIPLE VERTICAL BAR DELIMITER - return rune(0x2980), true + return {'\u2980', 0}, 1, true case "twixt": // BETWEEN - return rune(0x226c), true + return {'\u226c', 0}, 1, true case "twoheadleftarrow": // LEFTWARDS TWO HEADED ARROW - return rune(0x219e), true + return {'\u219e', 0}, 1, true case "twoheadrightarrow": // RIGHTWARDS TWO HEADED ARROW - return rune(0x21a0), true + return {'\u21a0', 0}, 1, true } case 'u': switch name { case "uAarr": // UPWARDS TRIPLE ARROW - return rune(0x290a), true + return {'\u290a', 0}, 1, true case "uArr": // UPWARDS DOUBLE ARROW - return rune(0x21d1), true + return {'\u21d1', 0}, 1, true case "uHar": // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - return rune(0x2963), true + return {'\u2963', 0}, 1, true case "uacgr": // GREEK SMALL LETTER UPSILON WITH TONOS - return rune(0x03cd), true + return {'\u03cd', 0}, 1, true case "uacute": // LATIN SMALL LETTER U WITH ACUTE - return rune(0xfa), true + return {'ú', 0}, 1, true case "uarr": // UPWARDS ARROW - return rune(0x2191), true + return {'\u2191', 0}, 1, true case "uarr2": // UPWARDS PAIRED ARROWS - return rune(0x21c8), true + return {'\u21c8', 0}, 1, true case "uarrb": // UPWARDS ARROW TO BAR - return rune(0x2912), true + return {'\u2912', 0}, 1, true case "uarrln": // UPWARDS ARROW WITH HORIZONTAL STROKE - return rune(0x2909), true + return {'\u2909', 0}, 1, true case "ubrcy": // CYRILLIC SMALL LETTER SHORT U - return rune(0x045e), true + return {'\u045e', 0}, 1, true case "ubreve": // LATIN SMALL LETTER U WITH BREVE - return rune(0x016d), true + return {'\u016d', 0}, 1, true case "ucirc": // LATIN SMALL LETTER U WITH CIRCUMFLEX - return rune(0xfb), true + return {'û', 0}, 1, true case "ucy": // CYRILLIC SMALL LETTER U - return rune(0x0443), true + return {'\u0443', 0}, 1, true case "udarr": // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW - return rune(0x21c5), true + return {'\u21c5', 0}, 1, true case "udblac": // LATIN SMALL LETTER U WITH DOUBLE ACUTE - return rune(0x0171), true + return {'\u0171', 0}, 1, true case "udhar": // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - return rune(0x296e), true + return {'\u296e', 0}, 1, true case "udiagr": // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS - return rune(0x03b0), true + return {'\u03b0', 0}, 1, true case "udigr": // GREEK SMALL LETTER UPSILON WITH DIALYTIKA - return rune(0x03cb), true + return {'\u03cb', 0}, 1, true case "udrbrk": // BOTTOM SQUARE BRACKET - return rune(0x23b5), true + return {'\u23b5', 0}, 1, true case "udrcub": // BOTTOM CURLY BRACKET - return rune(0x23df), true + return {'\u23df', 0}, 1, true case "udrpar": // BOTTOM PARENTHESIS - return rune(0x23dd), true + return {'\u23dd', 0}, 1, true case "ufisht": // UP FISH TAIL - return rune(0x297e), true + return {'\u297e', 0}, 1, true case "ufr": // MATHEMATICAL FRAKTUR SMALL U - return rune(0x01d532), true + return {'\U0001d532', 0}, 1, true case "ugr": // GREEK SMALL LETTER UPSILON - return rune(0x03c5), true + return {'\u03c5', 0}, 1, true case "ugrave": // LATIN SMALL LETTER U WITH GRAVE - return rune(0xf9), true + return {'ù', 0}, 1, true case "uharl": // UPWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21bf), true + return {'\u21bf', 0}, 1, true case "uharr": // UPWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21be), true + return {'\u21be', 0}, 1, true case "uhblk": // UPPER HALF BLOCK - return rune(0x2580), true + return {'\u2580', 0}, 1, true case "ulcorn": // TOP LEFT CORNER - return rune(0x231c), true + return {'\u231c', 0}, 1, true case "ulcorner": // TOP LEFT CORNER - return rune(0x231c), true + return {'\u231c', 0}, 1, true case "ulcrop": // TOP LEFT CROP - return rune(0x230f), true + return {'\u230f', 0}, 1, true case "uldlshar": // UP BARB LEFT DOWN BARB LEFT HARPOON - return rune(0x2951), true + return {'\u2951', 0}, 1, true case "ulharb": // UPWARDS HARPOON WITH BARB LEFT TO BAR - return rune(0x2958), true + return {'\u2958', 0}, 1, true case "ultri": // UPPER LEFT TRIANGLE - return rune(0x25f8), true + return {'\u25f8', 0}, 1, true case "umacr": // LATIN SMALL LETTER U WITH MACRON - return rune(0x016b), true + return {'\u016b', 0}, 1, true case "uml": // DIAERESIS - return rune(0xa8), true + return {'¨', 0}, 1, true case "uogon": // LATIN SMALL LETTER U WITH OGONEK - return rune(0x0173), true + return {'\u0173', 0}, 1, true case "uopf": // MATHEMATICAL DOUBLE-STRUCK SMALL U - return rune(0x01d566), true + return {'\U0001d566', 0}, 1, true case "uparrow": // UPWARDS ARROW - return rune(0x2191), true + return {'\u2191', 0}, 1, true case "updownarrow": // UP DOWN ARROW - return rune(0x2195), true + return {'\u2195', 0}, 1, true case "upharpoonleft": // UPWARDS HARPOON WITH BARB LEFTWARDS - return rune(0x21bf), true + return {'\u21bf', 0}, 1, true case "upharpoonright": // UPWARDS HARPOON WITH BARB RIGHTWARDS - return rune(0x21be), true + return {'\u21be', 0}, 1, true case "upint": // INTEGRAL WITH OVERBAR - return rune(0x2a1b), true + return {'\u2a1b', 0}, 1, true case "uplus": // MULTISET UNION - return rune(0x228e), true + return {'\u228e', 0}, 1, true case "upsi": // GREEK SMALL LETTER UPSILON - return rune(0x03c5), true + return {'\u03c5', 0}, 1, true case "upsih": // GREEK UPSILON WITH HOOK SYMBOL - return rune(0x03d2), true + return {'\u03d2', 0}, 1, true case "upsilon": // GREEK SMALL LETTER UPSILON - return rune(0x03c5), true + return {'\u03c5', 0}, 1, true case "upuparrows": // UPWARDS PAIRED ARROWS - return rune(0x21c8), true + return {'\u21c8', 0}, 1, true case "urcorn": // TOP RIGHT CORNER - return rune(0x231d), true + return {'\u231d', 0}, 1, true case "urcorner": // TOP RIGHT CORNER - return rune(0x231d), true + return {'\u231d', 0}, 1, true case "urcrop": // TOP RIGHT CROP - return rune(0x230e), true + return {'\u230e', 0}, 1, true case "urdrshar": // UP BARB RIGHT DOWN BARB RIGHT HARPOON - return rune(0x294f), true + return {'\u294f', 0}, 1, true case "urharb": // UPWARDS HARPOON WITH BARB RIGHT TO BAR - return rune(0x2954), true + return {'\u2954', 0}, 1, true case "uring": // LATIN SMALL LETTER U WITH RING ABOVE - return rune(0x016f), true + return {'\u016f', 0}, 1, true case "urtri": // UPPER RIGHT TRIANGLE - return rune(0x25f9), true + return {'\u25f9', 0}, 1, true case "urtrif": // BLACK UPPER RIGHT TRIANGLE - return rune(0x25e5), true + return {'\u25e5', 0}, 1, true case "uscr": // MATHEMATICAL SCRIPT SMALL U - return rune(0x01d4ca), true + return {'\U0001d4ca', 0}, 1, true case "utdot": // UP RIGHT DIAGONAL ELLIPSIS - return rune(0x22f0), true + return {'\u22f0', 0}, 1, true case "utilde": // LATIN SMALL LETTER U WITH TILDE - return rune(0x0169), true + return {'\u0169', 0}, 1, true case "utri": // WHITE UP-POINTING SMALL TRIANGLE - return rune(0x25b5), true + return {'\u25b5', 0}, 1, true case "utrif": // BLACK UP-POINTING SMALL TRIANGLE - return rune(0x25b4), true + return {'\u25b4', 0}, 1, true case "uuarr": // UPWARDS PAIRED ARROWS - return rune(0x21c8), true + return {'\u21c8', 0}, 1, true case "uuml": // LATIN SMALL LETTER U WITH DIAERESIS - return rune(0xfc), true + return {'ü', 0}, 1, true case "uwangle": // OBLIQUE ANGLE OPENING DOWN - return rune(0x29a7), true + return {'\u29a7', 0}, 1, true } case 'v': switch name { case "vArr": // UP DOWN DOUBLE ARROW - return rune(0x21d5), true + return {'\u21d5', 0}, 1, true case "vBar": // SHORT UP TACK WITH UNDERBAR - return rune(0x2ae8), true + return {'\u2ae8', 0}, 1, true case "vBarv": // SHORT UP TACK ABOVE SHORT DOWN TACK - return rune(0x2ae9), true + return {'\u2ae9', 0}, 1, true case "vDash": // TRUE - return rune(0x22a8), true + return {'\u22a8', 0}, 1, true case "vDdash": // VERTICAL BAR TRIPLE RIGHT TURNSTILE - return rune(0x2ae2), true + return {'\u2ae2', 0}, 1, true case "vangrt": // RIGHT ANGLE VARIANT WITH SQUARE - return rune(0x299c), true + return {'\u299c', 0}, 1, true case "varepsilon": // GREEK LUNATE EPSILON SYMBOL - return rune(0x03f5), true + return {'\u03f5', 0}, 1, true case "varkappa": // GREEK KAPPA SYMBOL - return rune(0x03f0), true + return {'\u03f0', 0}, 1, true case "varnothing": // EMPTY SET - return rune(0x2205), true + return {'\u2205', 0}, 1, true case "varphi": // GREEK PHI SYMBOL - return rune(0x03d5), true + return {'\u03d5', 0}, 1, true case "varpi": // GREEK PI SYMBOL - return rune(0x03d6), true + return {'\u03d6', 0}, 1, true case "varpropto": // PROPORTIONAL TO - return rune(0x221d), true + return {'\u221d', 0}, 1, true case "varr": // UP DOWN ARROW - return rune(0x2195), true + return {'\u2195', 0}, 1, true case "varrho": // GREEK RHO SYMBOL - return rune(0x03f1), true + return {'\u03f1', 0}, 1, true case "varsigma": // GREEK SMALL LETTER FINAL SIGMA - return rune(0x03c2), true + return {'\u03c2', 0}, 1, true case "varsubsetneq": // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members - return rune(0x228a), true + return {'\u228a', '\ufe00'}, 2, true case "varsubsetneqq": // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - return rune(0x2acb), true + return {'\u2acb', '\ufe00'}, 2, true case "varsupsetneq": // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members - return rune(0x228b), true + return {'\u228b', '\ufe00'}, 2, true case "varsupsetneqq": // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - return rune(0x2acc), true + return {'\u2acc', '\ufe00'}, 2, true case "vartheta": // GREEK THETA SYMBOL - return rune(0x03d1), true + return {'\u03d1', 0}, 1, true case "vartriangleleft": // NORMAL SUBGROUP OF - return rune(0x22b2), true + return {'\u22b2', 0}, 1, true case "vartriangleright": // CONTAINS AS NORMAL SUBGROUP - return rune(0x22b3), true + return {'\u22b3', 0}, 1, true case "vbrtri": // VERTICAL BAR BESIDE RIGHT TRIANGLE - return rune(0x29d0), true + return {'\u29d0', 0}, 1, true case "vcy": // CYRILLIC SMALL LETTER VE - return rune(0x0432), true + return {'\u0432', 0}, 1, true case "vdash": // RIGHT TACK - return rune(0x22a2), true + return {'\u22a2', 0}, 1, true case "vee": // LOGICAL OR - return rune(0x2228), true + return {'\u2228', 0}, 1, true case "veeBar": // LOGICAL OR WITH DOUBLE UNDERBAR - return rune(0x2a63), true + return {'\u2a63', 0}, 1, true case "veebar": // XOR - return rune(0x22bb), true + return {'\u22bb', 0}, 1, true case "veeeq": // EQUIANGULAR TO - return rune(0x225a), true + return {'\u225a', 0}, 1, true case "vellip": // VERTICAL ELLIPSIS - return rune(0x22ee), true + return {'\u22ee', 0}, 1, true case "vellip4": // DOTTED FENCE - return rune(0x2999), true + return {'\u2999', 0}, 1, true case "vellipv": // TRIPLE COLON OPERATOR - return rune(0x2af6), true + return {'\u2af6', 0}, 1, true case "verbar": // VERTICAL LINE - return rune(0x7c), true + return {'|', 0}, 1, true case "vert": // VERTICAL LINE - return rune(0x7c), true + return {'|', 0}, 1, true case "vert3": // TRIPLE VERTICAL BAR BINARY RELATION - return rune(0x2af4), true + return {'\u2af4', 0}, 1, true case "vfr": // MATHEMATICAL FRAKTUR SMALL V - return rune(0x01d533), true + return {'\U0001d533', 0}, 1, true case "vldash": // LEFT SQUARE BRACKET LOWER CORNER - return rune(0x23a3), true + return {'\u23a3', 0}, 1, true case "vltri": // NORMAL SUBGROUP OF - return rune(0x22b2), true + return {'\u22b2', 0}, 1, true case "vnsub": // SUBSET OF with vertical line - return rune(0x2282), true + return {'\u2282', '\u20d2'}, 2, true case "vnsup": // SUPERSET OF with vertical line - return rune(0x2283), true + return {'\u2283', '\u20d2'}, 2, true case "vopf": // MATHEMATICAL DOUBLE-STRUCK SMALL V - return rune(0x01d567), true + return {'\U0001d567', 0}, 1, true case "vprime": // PRIME - return rune(0x2032), true + return {'\u2032', 0}, 1, true case "vprop": // PROPORTIONAL TO - return rune(0x221d), true + return {'\u221d', 0}, 1, true case "vrtri": // CONTAINS AS NORMAL SUBGROUP - return rune(0x22b3), true + return {'\u22b3', 0}, 1, true case "vscr": // MATHEMATICAL SCRIPT SMALL V - return rune(0x01d4cb), true + return {'\U0001d4cb', 0}, 1, true case "vsubnE": // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - return rune(0x2acb), true + return {'\u2acb', '\ufe00'}, 2, true case "vsubne": // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members - return rune(0x228a), true + return {'\u228a', '\ufe00'}, 2, true case "vsupnE": // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - return rune(0x2acc), true + return {'\u2acc', '\ufe00'}, 2, true case "vsupne": // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members - return rune(0x228b), true + return {'\u228b', '\ufe00'}, 2, true case "vzigzag": // VERTICAL ZIGZAG LINE - return rune(0x299a), true + return {'\u299a', 0}, 1, true } case 'w': switch name { case "wcirc": // LATIN SMALL LETTER W WITH CIRCUMFLEX - return rune(0x0175), true + return {'\u0175', 0}, 1, true case "wedbar": // LOGICAL AND WITH UNDERBAR - return rune(0x2a5f), true + return {'\u2a5f', 0}, 1, true case "wedge": // LOGICAL AND - return rune(0x2227), true + return {'\u2227', 0}, 1, true case "wedgeq": // ESTIMATES - return rune(0x2259), true + return {'\u2259', 0}, 1, true case "weierp": // SCRIPT CAPITAL P - return rune(0x2118), true + return {'\u2118', 0}, 1, true case "wfr": // MATHEMATICAL FRAKTUR SMALL W - return rune(0x01d534), true + return {'\U0001d534', 0}, 1, true case "wopf": // MATHEMATICAL DOUBLE-STRUCK SMALL W - return rune(0x01d568), true + return {'\U0001d568', 0}, 1, true case "wp": // SCRIPT CAPITAL P - return rune(0x2118), true + return {'\u2118', 0}, 1, true case "wr": // WREATH PRODUCT - return rune(0x2240), true + return {'\u2240', 0}, 1, true case "wreath": // WREATH PRODUCT - return rune(0x2240), true + return {'\u2240', 0}, 1, true case "wscr": // MATHEMATICAL SCRIPT SMALL W - return rune(0x01d4cc), true + return {'\U0001d4cc', 0}, 1, true } case 'x': switch name { case "xandand": // TWO LOGICAL AND OPERATOR - return rune(0x2a07), true + return {'\u2a07', 0}, 1, true case "xbsol": // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT - return rune(0x2571), true + return {'\u2571', 0}, 1, true case "xcap": // N-ARY INTERSECTION - return rune(0x22c2), true + return {'\u22c2', 0}, 1, true case "xcirc": // LARGE CIRCLE - return rune(0x25ef), true + return {'\u25ef', 0}, 1, true case "xcup": // N-ARY UNION - return rune(0x22c3), true + return {'\u22c3', 0}, 1, true case "xcupdot": // N-ARY UNION OPERATOR WITH DOT - return rune(0x2a03), true + return {'\u2a03', 0}, 1, true case "xdtri": // WHITE DOWN-POINTING TRIANGLE - return rune(0x25bd), true + return {'\u25bd', 0}, 1, true case "xfr": // MATHEMATICAL FRAKTUR SMALL X - return rune(0x01d535), true + return {'\U0001d535', 0}, 1, true case "xgr": // GREEK SMALL LETTER XI - return rune(0x03be), true + return {'\u03be', 0}, 1, true case "xhArr": // LONG LEFT RIGHT DOUBLE ARROW - return rune(0x27fa), true + return {'\u27fa', 0}, 1, true case "xharr": // LONG LEFT RIGHT ARROW - return rune(0x27f7), true + return {'\u27f7', 0}, 1, true case "xi": // GREEK SMALL LETTER XI - return rune(0x03be), true + return {'\u03be', 0}, 1, true case "xlArr": // LONG LEFTWARDS DOUBLE ARROW - return rune(0x27f8), true + return {'\u27f8', 0}, 1, true case "xlarr": // LONG LEFTWARDS ARROW - return rune(0x27f5), true + return {'\u27f5', 0}, 1, true case "xmap": // LONG RIGHTWARDS ARROW FROM BAR - return rune(0x27fc), true + return {'\u27fc', 0}, 1, true case "xnis": // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - return rune(0x22fb), true + return {'\u22fb', 0}, 1, true case "xodot": // N-ARY CIRCLED DOT OPERATOR - return rune(0x2a00), true + return {'\u2a00', 0}, 1, true case "xopf": // MATHEMATICAL DOUBLE-STRUCK SMALL X - return rune(0x01d569), true + return {'\U0001d569', 0}, 1, true case "xoplus": // N-ARY CIRCLED PLUS OPERATOR - return rune(0x2a01), true + return {'\u2a01', 0}, 1, true case "xoror": // TWO LOGICAL OR OPERATOR - return rune(0x2a08), true + return {'\u2a08', 0}, 1, true case "xotime": // N-ARY CIRCLED TIMES OPERATOR - return rune(0x2a02), true + return {'\u2a02', 0}, 1, true case "xrArr": // LONG RIGHTWARDS DOUBLE ARROW - return rune(0x27f9), true + return {'\u27f9', 0}, 1, true case "xrarr": // LONG RIGHTWARDS ARROW - return rune(0x27f6), true + return {'\u27f6', 0}, 1, true case "xscr": // MATHEMATICAL SCRIPT SMALL X - return rune(0x01d4cd), true + return {'\U0001d4cd', 0}, 1, true case "xsol": // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT - return rune(0x2572), true + return {'\u2572', 0}, 1, true case "xsqcap": // N-ARY SQUARE INTERSECTION OPERATOR - return rune(0x2a05), true + return {'\u2a05', 0}, 1, true case "xsqcup": // N-ARY SQUARE UNION OPERATOR - return rune(0x2a06), true + return {'\u2a06', 0}, 1, true case "xsqu": // WHITE MEDIUM SQUARE - return rune(0x25fb), true + return {'\u25fb', 0}, 1, true case "xsquf": // BLACK MEDIUM SQUARE - return rune(0x25fc), true + return {'\u25fc', 0}, 1, true case "xtimes": // N-ARY TIMES OPERATOR - return rune(0x2a09), true + return {'\u2a09', 0}, 1, true case "xuplus": // N-ARY UNION OPERATOR WITH PLUS - return rune(0x2a04), true + return {'\u2a04', 0}, 1, true case "xutri": // WHITE UP-POINTING TRIANGLE - return rune(0x25b3), true + return {'\u25b3', 0}, 1, true case "xvee": // N-ARY LOGICAL OR - return rune(0x22c1), true + return {'\u22c1', 0}, 1, true case "xwedge": // N-ARY LOGICAL AND - return rune(0x22c0), true + return {'\u22c0', 0}, 1, true } case 'y': switch name { case "yacute": // LATIN SMALL LETTER Y WITH ACUTE - return rune(0xfd), true + return {'ý', 0}, 1, true case "yacy": // CYRILLIC SMALL LETTER YA - return rune(0x044f), true + return {'\u044f', 0}, 1, true case "ycirc": // LATIN SMALL LETTER Y WITH CIRCUMFLEX - return rune(0x0177), true + return {'\u0177', 0}, 1, true case "ycy": // CYRILLIC SMALL LETTER YERU - return rune(0x044b), true + return {'\u044b', 0}, 1, true case "yen": // YEN SIGN - return rune(0xa5), true + return {'¥', 0}, 1, true case "yfr": // MATHEMATICAL FRAKTUR SMALL Y - return rune(0x01d536), true + return {'\U0001d536', 0}, 1, true case "yicy": // CYRILLIC SMALL LETTER YI - return rune(0x0457), true + return {'\u0457', 0}, 1, true case "yopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Y - return rune(0x01d56a), true + return {'\U0001d56a', 0}, 1, true case "yscr": // MATHEMATICAL SCRIPT SMALL Y - return rune(0x01d4ce), true + return {'\U0001d4ce', 0}, 1, true case "yucy": // CYRILLIC SMALL LETTER YU - return rune(0x044e), true + return {'\u044e', 0}, 1, true case "yuml": // LATIN SMALL LETTER Y WITH DIAERESIS - return rune(0xff), true + return {'ÿ', 0}, 1, true } case 'z': switch name { case "zacute": // LATIN SMALL LETTER Z WITH ACUTE - return rune(0x017a), true + return {'\u017a', 0}, 1, true case "zcaron": // LATIN SMALL LETTER Z WITH CARON - return rune(0x017e), true + return {'\u017e', 0}, 1, true case "zcy": // CYRILLIC SMALL LETTER ZE - return rune(0x0437), true + return {'\u0437', 0}, 1, true case "zdot": // LATIN SMALL LETTER Z WITH DOT ABOVE - return rune(0x017c), true + return {'\u017c', 0}, 1, true case "zeetrf": // BLACK-LETTER CAPITAL Z - return rune(0x2128), true + return {'\u2128', 0}, 1, true case "zeta": // GREEK SMALL LETTER ZETA - return rune(0x03b6), true + return {'\u03b6', 0}, 1, true case "zfr": // MATHEMATICAL FRAKTUR SMALL Z - return rune(0x01d537), true + return {'\U0001d537', 0}, 1, true case "zgr": // GREEK SMALL LETTER ZETA - return rune(0x03b6), true + return {'\u03b6', 0}, 1, true case "zhcy": // CYRILLIC SMALL LETTER ZHE - return rune(0x0436), true + return {'\u0436', 0}, 1, true case "zigrarr": // RIGHTWARDS SQUIGGLE ARROW - return rune(0x21dd), true + return {'\u21dd', 0}, 1, true case "zopf": // MATHEMATICAL DOUBLE-STRUCK SMALL Z - return rune(0x01d56b), true + return {'\U0001d56b', 0}, 1, true case "zscr": // MATHEMATICAL SCRIPT SMALL Z - return rune(0x01d4cf), true + return {'\U0001d4cf', 0}, 1, true case "zwj": // ZERO WIDTH JOINER - return rune(0x200d), true + return {'\u200d', 0}, 1, true case "zwnj": // ZERO WIDTH NON-JOINER - return rune(0x200c), true + return {'\u200c', 0}, 1, true } } - return -1, false + return } /* diff --git a/core/encoding/hex/hex.odin b/core/encoding/hex/hex.odin index c1753003e..c4726d9e9 100644 --- a/core/encoding/hex/hex.odin +++ b/core/encoding/hex/hex.odin @@ -1,34 +1,115 @@ +// Encoding and decoding of hex-encoded binary, e.g. `0x23` -> `#`. package encoding_hex +import "base:runtime" import "core:io" import "core:strings" -encode :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> []byte #no_bounds_check { - dst := make([]byte, len(src) * 2, allocator, loc) - for i, j := 0, 0; i < len(src); i += 1 { +/* +Encodes a byte slice into a lowercase hex sequence + +*Allocates Using Provided Allocator* + +Inputs: +- src: The `[]byte` to be hex-encoded +- allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: #caller_location) + +Returns: +- res: The hex-encoded result +- err: An optional allocator error if one occured, `.None` otherwise +*/ +encode :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> (res: []byte, err: runtime.Allocator_Error) #optional_allocator_error { + res, err = make([]byte, len(src) * 2, allocator, loc) + #no_bounds_check for i, j := 0, 0; i < len(src); i += 1 { v := src[i] - dst[j] = HEXTABLE[v>>4] - dst[j+1] = HEXTABLE[v&0x0f] + res[j] = LOWER[v>>4] + res[j+1] = LOWER[v&0x0f] j += 2 } - - return dst + return } -encode_into_writer :: proc(dst: io.Writer, src: []byte) -> io.Error { +/* +Encodes a byte slice as a lowercase hex sequence into an `io.Writer` + +Inputs: +- dst: The `io.Writer` to encode into +- src: The `[]byte` to be hex-encoded + +Returns: +- err: An `io.Error` if one occured, `.None` otherwise +*/ +encode_into_writer :: proc(dst: io.Writer, src: []byte) -> (err: io.Error) { for v in src { - io.write(dst, {HEXTABLE[v>>4], HEXTABLE[v&0x0f]}) or_return + io.write(dst, {LOWER[v>>4], LOWER[v&0x0f]}) or_return } - return nil + return } -decode :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> (dst: []byte, ok: bool) #no_bounds_check { +/* +Encodes a byte slice into an uppercase hex sequence + +*Allocates Using Provided Allocator* + +Inputs: +- src: The `[]byte` to be hex-encoded +- allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: #caller_location) + +Returns: +- res: The hex-encoded result +- err: An optional allocator error if one occured, `.None` otherwise +*/ +encode_upper :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> (res: []byte, err: runtime.Allocator_Error) #optional_allocator_error { + res, err = make([]byte, len(src) * 2, allocator, loc) + #no_bounds_check for i, j := 0, 0; i < len(src); i += 1 { + v := src[i] + res[j] = UPPER[v>>4] + res[j+1] = UPPER[v&0x0f] + j += 2 + } + return +} + +/* +Encodes a byte slice as an uppercase hex sequence into an `io.Writer` + +Inputs: +- dst: The `io.Writer` to encode into +- src: The `[]byte` to be hex-encoded + +Returns: +- err: An `io.Error` if one occured, `.None` otherwise +*/ +encode_upper_into_writer :: proc(dst: io.Writer, src: []byte) -> (err: io.Error) { + for v in src { + io.write(dst, {UPPER[v>>4], UPPER[v&0x0f]}) or_return + } + return +} + +/* +Decodes a hex sequence into a byte slice + +*Allocates Using Provided Allocator* + +Inputs: +- dst: The hex sequence decoded into bytes +- src: The `[]byte` to be hex-decoded +- allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: #caller_location) + +Returns: +- ok: A bool, `true` if decoding succeeded, `false` otherwise +*/ +decode :: proc(src: []byte, allocator := context.allocator, loc := #caller_location) -> (dst: []byte, ok: bool) { if len(src) % 2 == 1 { return } dst = make([]byte, len(src) / 2, allocator, loc) - for i, j := 0, 1; j < len(src); j += 2 { + #no_bounds_check for i, j := 0, 1; j < len(src); j += 2 { p := src[j-1] q := src[j] @@ -42,8 +123,16 @@ decode :: proc(src: []byte, allocator := context.allocator, loc := #caller_locat return dst, true } -// Decodes the given sequence into one byte. -// Should be called with one byte worth of the source, eg: 0x23 -> '#'. +/* +Decodes the first byte in a hex sequence to a byte + +Inputs: +- str: A hex-encoded `string`, e.g. `"0x23"` + +Returns: +- res: The decoded byte, e.g. `'#'` +- ok: A bool, `true` if decoding succeeded, `false` otherwise +*/ decode_sequence :: proc(str: string) -> (res: byte, ok: bool) { str := str if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") { @@ -61,13 +150,21 @@ decode_sequence :: proc(str: string) -> (res: byte, ok: bool) { } @(private) -HEXTABLE := [16]byte { +LOWER := [16]byte { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', } +@(private) +UPPER := [16]byte { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F', +} + @(private) hex_digit :: proc(char: byte) -> (u8, bool) { switch char { diff --git a/core/encoding/hxa/doc.odin b/core/encoding/hxa/doc.odin index b696bef7e..902428668 100644 --- a/core/encoding/hxa/doc.odin +++ b/core/encoding/hxa/doc.odin @@ -1,5 +1,6 @@ /* -Implementation of the HxA 3D asset format +Eskil Steenberg's `HxA` 3D asset interchange format. + HxA is a interchangeable graphics asset format. Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com diff --git a/core/encoding/hxa/hxa.odin b/core/encoding/hxa/hxa.odin index 9d0c58196..4ed2001d9 100644 --- a/core/encoding/hxa/hxa.odin +++ b/core/encoding/hxa/hxa.odin @@ -1,6 +1,6 @@ package encoding_hxa -import "core:mem" +import "base:runtime" LATEST_VERSION :: 3 VERSION_API :: "0.3" @@ -16,7 +16,7 @@ Header :: struct #packed { File :: struct { using header: Header, backing: []byte, - allocator: mem.Allocator, + allocator: runtime.Allocator, nodes: []Node, } diff --git a/core/encoding/hxa/hxa_os.odin b/core/encoding/hxa/hxa_os.odin new file mode 100644 index 000000000..17ad94819 --- /dev/null +++ b/core/encoding/hxa/hxa_os.odin @@ -0,0 +1,34 @@ +#+build !freestanding +#+build !js +package encoding_hxa + +import "core:os" + +read_from_file :: proc(filename: string, print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { + context.allocator = allocator + + data, data_err := os.read_entire_file(filename, allocator, loc) + if data_err != nil { + err = .Unable_To_Read_File + delete(data, allocator) + return + } + file, err = read(data, filename, print_error, allocator) + file.backing = data + return +} + +write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) { + required := required_write_size(file) + buf, alloc_err := make([]byte, required) + if alloc_err == .Out_Of_Memory { + return .Failed_File_Write + } + defer delete(buf) + + write_internal(&Writer{data = buf}, file) + if os.write_entire_file(filepath, buf) != nil { + err =.Failed_File_Write + } + return +} diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin index 6dde16848..29d57838c 100644 --- a/core/encoding/hxa/read.odin +++ b/core/encoding/hxa/read.odin @@ -1,8 +1,6 @@ package encoding_hxa import "core:fmt" -import "core:os" -import "core:mem" Read_Error :: enum { None, @@ -11,20 +9,6 @@ Read_Error :: enum { Unable_To_Read_File, } -read_from_file :: proc(filename: string, print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { - context.allocator = allocator - - data, ok := os.read_entire_file(filename, allocator, loc) - if !ok { - err = .Unable_To_Read_File - delete(data, allocator, loc) - return - } - file, err = read(data, filename, print_error, allocator, loc) - file.backing = data - return -} - read :: proc(data: []byte, filename := "", print_error := false, allocator := context.allocator, loc := #caller_location) -> (file: File, err: Read_Error) { Reader :: struct { filename: string, @@ -60,7 +44,7 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato } ptr := raw_data(r.data[r.offset:]) - value = mem.slice_ptr((^T)(ptr), count) + value = ([^]T)(ptr)[:count] r.offset += size_of(T)*count return } diff --git a/core/encoding/hxa/write.odin b/core/encoding/hxa/write.odin index 5bb950e81..0716131f5 100644 --- a/core/encoding/hxa/write.odin +++ b/core/encoding/hxa/write.odin @@ -1,29 +1,11 @@ package encoding_hxa -import "core:os" -import "core:mem" - Write_Error :: enum { None, Buffer_Too_Small, Failed_File_Write, } -write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) { - required := required_write_size(file) - buf, alloc_err := make([]byte, required) - if alloc_err == .Out_Of_Memory { - return .Failed_File_Write - } - defer delete(buf) - - write_internal(&Writer{data = buf}, file) - if !os.write_entire_file(filepath, buf) { - err =.Failed_File_Write - } - return -} - write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) { required := required_write_size(file) if len(buf) < required { @@ -66,7 +48,7 @@ write_internal :: proc(w: ^Writer, file: File) { remaining := len(w.data) - w.offset assert(size_of(T)*len(array) <= remaining) ptr := raw_data(w.data[w.offset:]) - dst := mem.slice_ptr((^T)(ptr), len(array)) + dst := ([^]T)(ptr)[:len(array)] copy(dst, array) } w.offset += size_of(T)*len(array) @@ -76,7 +58,7 @@ write_internal :: proc(w: ^Writer, file: File) { remaining := len(w.data) - w.offset assert(size_of(byte)*len(str) <= remaining) ptr := raw_data(w.data[w.offset:]) - dst := mem.slice_ptr((^byte)(ptr), len(str)) + dst := ([^]byte)(ptr)[:len(str)] copy(dst, str) } w.offset += size_of(byte)*len(str) diff --git a/core/encoding/ini/ini.odin b/core/encoding/ini/ini.odin index c32b1deb5..8bf6c6c9a 100644 --- a/core/encoding/ini/ini.odin +++ b/core/encoding/ini/ini.odin @@ -1,12 +1,12 @@ +// Reader and writer for a variant of the `.ini` file format with `key = value` entries in `[sections]`. package encoding_ini -import "base:runtime" -import "base:intrinsics" -import "core:strings" -import "core:strconv" -import "core:io" -import "core:os" -import "core:fmt" +import "base:runtime" +import "base:intrinsics" +import "core:strings" +import "core:strconv" +import "core:io" +import "core:fmt" _ :: fmt Options :: struct { @@ -119,17 +119,6 @@ load_map_from_string :: proc(src: string, allocator: runtime.Allocator, options return } -load_map_from_path :: proc(path: string, allocator: runtime.Allocator, options := DEFAULT_OPTIONS) -> (m: Map, err: runtime.Allocator_Error, ok: bool) { - data := os.read_entire_file(path, allocator) or_return - defer delete(data, allocator) - m, err = load_map_from_string(string(data), allocator, options) - ok = err == nil - defer if !ok { - delete_map(m) - } - return -} - save_map_to_string :: proc(m: Map, allocator: runtime.Allocator) -> (data: string) { b := strings.builder_make(allocator) _, _ = write_map(strings.to_writer(&b), m) @@ -190,4 +179,4 @@ write_map :: proc(w: io.Writer, m: Map) -> (n: int, err: io.Error) { section_index += 1 } return -} +} \ No newline at end of file diff --git a/core/encoding/ini/ini_os.odin b/core/encoding/ini/ini_os.odin new file mode 100644 index 000000000..22c6bf7b3 --- /dev/null +++ b/core/encoding/ini/ini_os.odin @@ -0,0 +1,20 @@ +#+build !freestanding +#+build !js +package encoding_ini + +import "base:runtime" +import "core:os" + +load_map_from_path :: proc(path: string, allocator: runtime.Allocator, options := DEFAULT_OPTIONS) -> (m: Map, err: runtime.Allocator_Error, ok: bool) { + data, data_err := os.read_entire_file(path, allocator) + defer delete(data, allocator) + if data_err != nil { + return + } + m, err = load_map_from_string(string(data), allocator, options) + ok = err == nil + defer if !ok { + delete_map(m) + } + return +} diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index 020facd14..e6c8fba38 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -62,6 +62,79 @@ Marshal_Options :: struct { mjson_skipped_first_braces_end: bool, } +User_Marshaler :: #type proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> Marshal_Error + +Register_User_Marshaler_Error :: enum { + None, + No_User_Marshaler, + Marshaler_Previously_Found, +} + +// Example User Marshaler: +// Custom Marshaler for `int` +// Some_Marshaler :: proc(w: io.Writer, v: any, opt: ^json.Marshal_Options) -> json.Marshal_Error { +// io.write_string(w, fmt.tprintf("%b", v)) +// return json.Marshal_Data_Error.None +// } +// +// main :: proc() { +// // Ensure the json._user_marshaler map is initialized +// json.set_user_marshalers(new(map[typeid]json.User_Marshaler)) +// reg_err := json.register_user_marshaler(type_info_of(int).id, Some_Marshaler) +// assert(reg_err == .None) +// +// +// // Use the custom marshaler +// SomeType :: struct { +// value: int, +// } +// +// x := SomeType{42} +// data, marshal_err := json.marshal(x) +// assert(marshal_err == nil) +// defer delete(data) +// +// fmt.println("Custom output:", string(data)) // Custom output: {"value":101010} +// } + +// NOTE(Jeroen): This is a pointer to prevent accidental additions +// it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary +_user_marshalers: ^map[typeid]User_Marshaler + +// Sets user-defined marshalers for custom json marshaling of specific types +// +// Inputs: +// - m: A pointer to a map of typeids to User_Marshaler procs. +// +// NOTE: Must be called before using register_user_marshaler. +// +set_user_marshalers :: proc(m: ^map[typeid]User_Marshaler) { + assert(_user_marshalers == nil, "set_user_marshalers must not be called more than once.") + _user_marshalers = m +} + +// Registers a user-defined marshaler for a specific typeid +// +// Inputs: +// - id: The typeid of the custom type. +// - formatter: The User_Marshaler function for the custom type. +// +// Returns: A Register_User_Marshaler_Error value indicating the success or failure of the operation. +// +// WARNING: set_user_marshalers must be called before using this procedure. +// +register_user_marshaler :: proc(id: typeid, marshaler: User_Marshaler) -> Register_User_Marshaler_Error { + if _user_marshalers == nil { + return .No_User_Marshaler + } + if prev, found := _user_marshalers[id]; found && prev != nil { + return .Marshaler_Previously_Found + } + _user_marshalers[id] = marshaler + return .None +} + +@(require_results) marshal :: proc(v: any, opt: Marshal_Options = {}, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Marshal_Error) { b := strings.builder_make(allocator, loc) defer if err != nil { @@ -91,6 +164,13 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: return } + if _user_marshalers != nil { + marshaler := _user_marshalers[v.id] + if marshaler != nil { + return marshaler(w, v, opt) + } + } + ti := runtime.type_info_base(type_info_of(v.id)) a := any{v.data, ti.id} @@ -108,13 +188,13 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: if opt.write_uint_as_hex && (opt.spec == .JSON5 || opt.spec == .MJSON) { switch i in a { case u8, u16, u32, u64, u128: - s = strconv.append_bits_128(buf[:], u, 16, info.signed, 8*ti.size, "0123456789abcdef", { .Prefix }) + s = strconv.write_bits_128(buf[:], u, 16, info.signed, 8*ti.size, "0123456789abcdef", { .Prefix }) case: - s = strconv.append_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil) + s = strconv.write_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil) } } else { - s = strconv.append_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil) + s = strconv.write_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil) } io.write_string(w, s) or_return @@ -122,9 +202,9 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: case runtime.Type_Info_Rune: r := a.(rune) - io.write_byte(w, '"') or_return - io.write_escaped_rune(w, r, '"', true) or_return - io.write_byte(w, '"') or_return + io.write_byte(w, '"') or_return + io.write_escaped_rune(w, r, '"', for_json = true) or_return + io.write_byte(w, '"') or_return case runtime.Type_Info_Float: switch f in a { @@ -176,7 +256,11 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: return .Unsupported_Type case runtime.Type_Info_Pointer: - return .Unsupported_Type + if v.id == typeid_of(Null) { + io.write_string(w, "null") or_return + } else { + return .Unsupported_Type + } case runtime.Type_Info_Multi_Pointer: return .Unsupported_Type @@ -237,6 +321,16 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: } opt_write_end(w, opt, ']') or_return + case runtime.Type_Info_Fixed_Capacity_Dynamic_Array: + opt_write_start(w, opt, '[') or_return + len := (^int)(uintptr(v.data) + info.len_offset)^ + for i in 0.. (err: case runtime.Type_Info_Integer: buf: [40]byte u := cast_any_int_to_u128(ka) - name = strconv.append_bits_128(buf[:], u, 10, info.signed, 8*kti.size, "0123456789", nil) + name = strconv.write_bits_128(buf[:], u, 10, info.signed, 8*kti.size, "0123456789", nil) opt_write_key(w, opt, name) or_return case: return .Unsupported_Type @@ -353,10 +447,10 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: #partial switch info in ti.variant { case runtime.Type_Info_String: switch x in v { - case string: - return x == "" - case cstring: - return x == nil || x == "" + case string: return x == "" + case cstring: return x == nil || x == "" + case string16: return x == "" + case cstring16: return x == nil || x == "" } case runtime.Type_Info_Any: return v.(any) == nil @@ -410,6 +504,12 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: opt_write_iteration(w, opt, first_iteration) or_return first_iteration = false + + if opt.pretty { + comment := reflect.struct_tag_get(reflect.Struct_Tag(info.tags[i]), "jsoncomment") + opt_write_comment(w, opt, &comment) or_return + } + if json_name != "" { opt_write_key(w, opt, json_name) or_return } else { @@ -529,6 +629,26 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: return } +// Newlines are split into multiple comment lines +opt_write_comment :: proc(w: io.Writer, opt: ^Marshal_Options, comment: ^string) -> (err: io.Error) { + if comment^ == "" { + return nil + } + + switch opt.spec { + case .JSON5, .MJSON: + for line in strings.split_iterator(comment, "\n") { + io.write_string(w, "// ") or_return + io.write_string(w, line) or_return + io.write_rune(w, '\n') or_return + opt_write_indentation(w, opt) or_return + } + case .JSON: return nil + } + + return nil +} + // write key as quoted string or with optional quotes in mjson opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err: io.Error) { switch opt.spec { diff --git a/core/encoding/json/match.odin b/core/encoding/json/match.odin new file mode 100644 index 000000000..d9598c626 --- /dev/null +++ b/core/encoding/json/match.odin @@ -0,0 +1,68 @@ +package encoding_json + +Match_Key_Variant :: union #no_nil { + int, // Index + string, // Key +} + +Match_Error :: enum { + None, + Invalid_Argument, + Invalid_Type_For_Index, + Invalid_Type_For_Key, + Key_Not_Found, + Out_Of_Bounds_Index, +} + +Match_Flags :: distinct bit_set[Match_Flag] +Match_Flag :: enum { + Ignore_Key_Not_Found, + Allow_String_Indexing_By_Byte, +} + +@(require_results) +match :: proc(value: Value, args: ..Match_Key_Variant, flags: Match_Flags = nil) -> (found: Value, err: Match_Error) { + found = value + arg_loop: for arg in args { + switch k in arg { + case int: + #partial switch v in found { + case Array: + if 0 <= k && k < len(v) { + found = v[k] + continue arg_loop + } + err = .Out_Of_Bounds_Index + return + case String: + if .Allow_String_Indexing_By_Byte in flags { + if 0 <= k && k < len(v) { + found = Integer(v[k]) + continue arg_loop + } + err = .Out_Of_Bounds_Index + return + } + } + err = .Invalid_Type_For_Index + return + case string: + v, ok := found.(Object) + if !ok { + err = .Invalid_Type_For_Key + return + } + vfound, vok := v[k] + if vok || (.Ignore_Key_Not_Found in flags) { + found = vfound + continue arg_loop + } + err = .Key_Not_Found + return + case: + err = .Invalid_Argument + return + } + } + return +} \ No newline at end of file diff --git a/core/encoding/json/parser.odin b/core/encoding/json/parser.odin index 38f71edf6..91bc42e4c 100644 --- a/core/encoding/json/parser.odin +++ b/core/encoding/json/parser.odin @@ -14,9 +14,16 @@ Parser :: struct { parse_integers: bool, } -make_parser :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator) -> Parser { +make_parser :: proc{ + make_parser_from_bytes, + make_parser_from_string, +} + +@(require_results) +make_parser_from_bytes :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator) -> Parser { return make_parser_from_string(string(data), spec, parse_integers, allocator) } +@(require_results) make_parser_from_string :: proc(data: string, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator) -> Parser { p: Parser p.tok = make_tokenizer(data, spec, parse_integers) @@ -27,18 +34,25 @@ make_parser_from_string :: proc(data: string, spec := DEFAULT_SPECIFICATION, par return p } +parse :: proc{ + parse_bytes, + parse_string, +} -parse :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator, loc := #caller_location) -> (Value, Error) { + +@(require_results) +parse_bytes :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator, loc := #caller_location) -> (Value, Error) { return parse_string(string(data), spec, parse_integers, allocator, loc) } +@(require_results) parse_string :: proc(data: string, spec := DEFAULT_SPECIFICATION, parse_integers := false, allocator := context.allocator, loc := #caller_location) -> (Value, Error) { context.allocator = allocator p := make_parser_from_string(data, spec, parse_integers, allocator) switch p.spec { case .JSON: - return parse_object(&p, loc) + return parse_value(&p, loc) case .JSON5: return parse_value(&p, loc) case .SJSON: @@ -51,6 +65,7 @@ parse_string :: proc(data: string, spec := DEFAULT_SPECIFICATION, parse_integers return parse_object(&p, loc) } +@(require_results) token_end_pos :: proc(tok: Token) -> Pos { end := tok.pos end.offset += len(tok.text) @@ -65,6 +80,7 @@ advance_token :: proc(p: ^Parser) -> (Token, Error) { } +@(require_results) allow_token :: proc(p: ^Parser, kind: Token_Kind) -> bool { if p.curr_token.kind == kind { advance_token(p) @@ -73,6 +89,7 @@ allow_token :: proc(p: ^Parser, kind: Token_Kind) -> bool { return false } +@(require_results) expect_token :: proc(p: ^Parser, kind: Token_Kind) -> Error { prev := p.curr_token advance_token(p) @@ -83,14 +100,16 @@ expect_token :: proc(p: ^Parser, kind: Token_Kind) -> Error { } +@(require_results) parse_colon :: proc(p: ^Parser) -> (err: Error) { - colon_err := expect_token(p, .Colon) + colon_err := expect_token(p, .Colon) if colon_err == nil { return nil } return .Expected_Colon_After_Key } +@(require_results) parse_comma :: proc(p: ^Parser) -> (do_break: bool) { switch p.spec { case .JSON5, .MJSON: @@ -106,6 +125,7 @@ parse_comma :: proc(p: ^Parser) -> (do_break: bool) { return false } +@(require_results) parse_value :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: Error) { err = .None token := p.curr_token @@ -133,13 +153,13 @@ parse_value :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: f, _ := strconv.parse_f64(token.text) value = Float(f) return - + case .Ident: if p.spec == .MJSON { advance_token(p) - return string(token.text), nil + return clone_string(token.text, p.allocator, loc) } - + case .String: advance_token(p) return unquote_string(token, p.spec, p.allocator, loc) @@ -176,6 +196,7 @@ parse_value :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: return } +@(require_results) parse_array :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: Error) { err = .None expect_token(p, .Open_Bracket) or_return @@ -192,7 +213,7 @@ parse_array :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: for p.curr_token.kind != .Close_Bracket { elem := parse_value(p, loc) or_return append(&array, elem, loc) - + if parse_comma(p) { break } @@ -203,7 +224,7 @@ parse_array :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: return } -@(private) +@(private, require_results) bytes_make :: proc(size, alignment: int, allocator: mem.Allocator, loc := #caller_location) -> (bytes: []byte, err: Error) { b, berr := mem.alloc_bytes(size, alignment, allocator, loc) if berr != nil { @@ -217,6 +238,7 @@ bytes_make :: proc(size, alignment: int, allocator: mem.Allocator, loc := #calle return } +@(require_results) clone_string :: proc(s: string, allocator: mem.Allocator, loc := #caller_location) -> (str: string, err: Error) { n := len(s) b := bytes_make(n+1, 1, allocator, loc) or_return @@ -228,6 +250,7 @@ clone_string :: proc(s: string, allocator: mem.Allocator, loc := #caller_locatio return } +@(require_results) parse_object_key :: proc(p: ^Parser, key_allocator: mem.Allocator, loc := #caller_location) -> (key: string, err: Error) { tok := p.curr_token if p.spec != .JSON { @@ -242,6 +265,7 @@ parse_object_key :: proc(p: ^Parser, key_allocator: mem.Allocator, loc := #calle return unquote_string(tok, p.spec, key_allocator, loc) } +@(require_results) parse_object_body :: proc(p: ^Parser, end_token: Token_Kind, loc := #caller_location) -> (obj: Object, err: Error) { obj = make(Object, allocator=p.allocator, loc=loc) @@ -278,10 +302,11 @@ parse_object_body :: proc(p: ^Parser, end_token: Token_Kind, loc := #caller_loca if parse_comma(p) { break } - } + } return obj, .None } +@(require_results) parse_object :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: Error) { expect_token(p, .Open_Brace) or_return obj := parse_object_body(p, .Close_Brace, loc) or_return @@ -291,6 +316,7 @@ parse_object :: proc(p: ^Parser, loc := #caller_location) -> (value: Value, err: // IMPORTANT NOTE(bill): unquote_string assumes a mostly valid string +@(require_results) unquote_string :: proc(token: Token, spec: Specification, allocator := context.allocator, loc := #caller_location) -> (value: string, err: Error) { get_u2_rune :: proc(s: string) -> rune { if len(s) < 4 || s[0] != '\\' || s[1] != 'x' { @@ -474,11 +500,14 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a i += width buf, buf_width := utf8.encode_rune(r) - assert(buf_width <= width) + // If we have an invalid utf8 character, width can be smaller than the width of RUNE_ERROR + if r != utf8.RUNE_ERROR { + assert(buf_width <= width) + } copy(b[w:], buf[:buf_width]) w += buf_width } } return string(b[:w]), nil -} \ No newline at end of file +} diff --git a/core/encoding/json/tokenizer.odin b/core/encoding/json/tokenizer.odin index ad928b7d9..153c41b29 100644 --- a/core/encoding/json/tokenizer.odin +++ b/core/encoding/json/tokenizer.odin @@ -49,11 +49,12 @@ Tokenizer :: struct { curr_line_offset: int, spec: Specification, parse_integers: bool, - insert_comma: bool, + insert_comma: bool, } +@(require_results) make_tokenizer :: proc(data: string, spec := DEFAULT_SPECIFICATION, parse_integers := false) -> Tokenizer { t := Tokenizer{pos = {line=1}, data = data, spec = spec, parse_integers = parse_integers} next_rune(&t) @@ -78,6 +79,7 @@ next_rune :: proc(t: ^Tokenizer) -> rune #no_bounds_check { } +@(require_results) get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { skip_digits :: proc(t: ^Tokenizer) { for t.offset < len(t.data) { @@ -101,6 +103,7 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { } } + @(require_results) scan_escape :: proc(t: ^Tokenizer) -> bool { switch t.r { case '"', '\'', '\\', '/', 'b', 'n', 'r', 't', 'f': @@ -125,7 +128,7 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { return false } - skip_whitespace :: proc(t: ^Tokenizer, on_newline: bool) -> rune { + skip_whitespace :: proc(t: ^Tokenizer, on_newline: bool) { loop: for t.offset < len(t.data) { switch t.r { case ' ', '\t', '\v', '\f', '\r': @@ -149,7 +152,7 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { break loop } } - return t.r + return } skip_to_next_line :: proc(t: ^Tokenizer) { @@ -310,7 +313,7 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { break } if r == '\\' { - scan_escape(t) + _ = scan_escape(t) } } @@ -347,10 +350,8 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { case '*': // None-nested multi-line comments for t.offset < len(t.data) { - next_rune(t) - if t.r == '*' { - next_rune(t) - if t.r == '/' { + if next_rune(t) == '*' { + if next_rune(t) == '/' { next_rune(t) return get_token(t) } @@ -385,6 +386,7 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) { +@(require_results) is_valid_number :: proc(str: string, spec: Specification) -> bool { s := str if s == "" { @@ -473,6 +475,7 @@ is_valid_number :: proc(str: string, spec: Specification) -> bool { return s == "" } +@(require_results) is_valid_string_literal :: proc(str: string, spec: Specification) -> bool { s := str if len(s) < 2 { diff --git a/core/encoding/json/types.odin b/core/encoding/json/types.odin index 41eb21377..66ff5c700 100644 --- a/core/encoding/json/types.odin +++ b/core/encoding/json/types.odin @@ -1,14 +1,13 @@ -package encoding_json - -import "core:strings" - /* - JSON +Encoding and decoding JSON in strict `JSON`, [[ JSON5 ; https://json5.org/ ]] and [[ BitSquid ; https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html ]] variants. + +Using one of these `Specification`s. + JSON strict JSON - JSON5 + JSON5 pure superset of JSON and valid JavaScript https://json5.org/ - + * Object keys may be an ECMAScript 5.1 IdentifierName. * Objects may have a single trailing comma. * Arrays may have a single trailing comma. @@ -21,17 +20,21 @@ import "core:strings" * Numbers may begin with an explicit plus sign. * Single and multi-line comments are allowed. * Additional white space characters are allowed. - + MJSON pure superset of JSON5, may not be valid JavaScript https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html - + * All the same features as JSON5 plus extras. * Assume an object definition at the root level (no need to surround entire file with { } ). * Commas are optional, using comma insertion rules with newlines. * Quotes around object keys are optional if the keys are valid identifiers. * : can be replaced with = */ +package encoding_json + +import "core:strings" + Specification :: enum { JSON, JSON5, // https://json5.org/ @@ -73,6 +76,7 @@ Error :: enum { Invalid_Number, String_Not_Terminated, Invalid_String, + Invalid_Rune, // Parsing Errors @@ -108,7 +112,9 @@ destroy_value :: proc(value: Value, allocator := context.allocator, loc := #call } } +@(require_results) clone_value :: proc(value: Value, allocator := context.allocator) -> Value { + value := value context.allocator = allocator #partial switch &v in value { diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index 151bd69c3..0f8c19b5d 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -26,6 +26,88 @@ Unmarshal_Error :: union { Unsupported_Type_Error, } +User_Unmarshaler :: #type proc(p: ^Parser, v: any) -> Unmarshal_Error + +Register_User_Unmarshaler_Error :: enum { + None, + No_User_Unmarshaler, + Unmarshaler_Previously_Found, +} + +// NOTE(Jeroen): This is a pointer to prevent accidental additions +// it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary +_user_unmarshalers: ^map[typeid]User_Unmarshaler + +// Sets user-defined unmarshalers for custom json unmarshaling of specific types +// +// Inputs: +// - m: A pointer to a map of typeids to User_Unmarshaler procs. +// +// NOTE: Must be called before using `register_user_unmarshaler`. +// +set_user_unmarshalers :: proc(m: ^map[typeid]User_Unmarshaler) { + assert(_user_unmarshalers == nil, "set_user_unmarshalers must not be called more than once.") + _user_unmarshalers = m +} + +/* +Registers a user-defined unmarshaler for a specific `typeid`. + +WARNING: set_user_unmarshalers must be called before using this procedure. + +Inputs: +- id: The `typeid` of the custom type. +- unmarshaler: The `User_Unmarshaler` function for the custom type. + +Example: + import "core:fmt" + import "core:encoding/json" + import "core:strconv" + + // Custom Unmarshaler for `int` + some_unmarshaler :: proc(p: ^json.Parser, v: any) -> json.Unmarshal_Error { + token := p.curr_token.text + i, ok := strconv.parse_i64_of_base(token, 2) + if !ok { + return .Invalid_Data + } + + (^int)(v.data)^ = int(i) + + json.advance_token(p) + return nil + } + + register_user_unmarshaler_example :: proc() { + // Ensure the `json._user_unmarshalers` map is initialized. + json.set_user_unmarshalers(new(map[typeid]json.User_Unmarshaler)) + reg_err := json.register_user_unmarshaler(typeid_of(int), some_unmarshaler) + assert(reg_err == .None) + + data := `{"value":101010}` + SomeType :: struct { + value: int, + } + y: SomeType + + unmarshal_err := json.unmarshal(transmute([]byte)data, &y) + fmt.println(y, unmarshal_err) + } + +Output: + SomeType{value = 42} nil +*/ +register_user_unmarshaler :: proc(id: typeid, unmarshaler: User_Unmarshaler) -> Register_User_Unmarshaler_Error { + if _user_unmarshalers == nil { + return .No_User_Unmarshaler + } + if prev, found := _user_unmarshalers[id]; found && prev != nil { + return .Unmarshaler_Previously_Found + } + _user_unmarshalers[id] = unmarshaler + return .None +} + unmarshal_any :: proc(data: []byte, v: any, spec := DEFAULT_SPECIFICATION, allocator := context.allocator) -> Unmarshal_Error { v := v if v == nil || v.id == nil { @@ -37,8 +119,10 @@ unmarshal_any :: proc(data: []byte, v: any, spec := DEFAULT_SPECIFICATION, alloc return .Non_Pointer_Parameter } PARSE_INTEGERS :: true - - if !is_valid(data, spec, PARSE_INTEGERS) { + + // If we have custom unmarshalers, we skip validation in case the custom data is not quite up to spec. + have_custom := _user_unmarshalers != nil && len(_user_unmarshalers) > 0 + if !have_custom && !is_valid(data, spec, PARSE_INTEGERS) { return .Invalid_Data } p := make_parser(data, spec, PARSE_INTEGERS, allocator) @@ -188,8 +272,18 @@ assign_float :: proc(val: any, f: $T) -> bool { @(private) -unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> (ok: bool, err: Error) { - val := val +unmarshal_string_token :: proc(p: ^Parser, val: any, token: Token, ti: ^reflect.Type_Info) -> (ok: bool, err: Error) { + str: string + switch { + case token.kind == .String: + str = unquote_string(token, p.spec, p.allocator) or_return + case: + str = clone_string(token.text, p.allocator) or_return + } + defer if !ok || (val.id != string && val.id != cstring) { + delete(str, p.allocator) + } + switch &dst in val { case string: dst = str @@ -215,6 +309,15 @@ unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.T } ok = true return + case rune: + for rne, i in str { + if i > 0 { + dst = {} + return false, .Invalid_Rune + } + dst = rne + } + return true, nil } #partial switch variant in ti.variant { @@ -255,12 +358,18 @@ unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.T return false, nil } - @(private) unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { UNSUPPORTED_TYPE := Unsupported_Type_Error{v.id, p.curr_token} token := p.curr_token + if _user_unmarshalers != nil { + unmarshaler := _user_unmarshalers[v.id] + if unmarshaler != nil { + return unmarshaler(p, v) + } + } + v := v ti := reflect.type_info_base(type_info_of(v.id)) if u, ok := ti.variant.(reflect.Type_Info_Union); ok && token.kind != .Null { @@ -339,7 +448,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { case .Ident: advance_token(p) if p.spec == .MJSON { - if unmarshal_string_token(p, any{v.data, ti.id}, token.text, ti) or_return { + if unmarshal_string_token(p, any{v.data, ti.id}, token, ti) or_return { return nil } } @@ -347,18 +456,10 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { case .String: advance_token(p) - str := unquote_string(token, p.spec, p.allocator) or_return - dest := any{v.data, ti.id} - if !(unmarshal_string_token(p, dest, str, ti) or_return) { - delete(str, p.allocator) - return UNSUPPORTED_TYPE + if unmarshal_string_token(p, any{v.data, ti.id}, token, ti) or_return { + return nil } - - switch destv in dest { - case string, cstring: - case: delete(str, p.allocator) - } - return nil + return UNSUPPORTED_TYPE case .Open_Brace: return unmarshal_object(p, v, .Close_Brace) @@ -406,6 +507,9 @@ unmarshal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_loca return prev } +// Struct tags can include not only the name of the JSON key, but also a tag such as `omitempty`. +// Example: `json:"key_name,omitempty"` +// This returns the first field as `json_name`, and the rest are returned as `extra`. @(private) json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) { json_name = value @@ -441,12 +545,6 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm defer delete(key, p.allocator) unmarshal_expect_token(p, .Colon) - - field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool { - prev_set := field_used[offset/8] & byte(offset&7) != 0 - field_used[offset/8] |= byte(offset&7) - return prev_set - } field_used_bytes := (reflect.size_of_typeid(ti.id)+7)/8 field_used := intrinsics.alloca(field_used_bytes + 1, 1) // + 1 to not overflow on size_of 0 types. @@ -465,7 +563,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm if use_field_idx < 0 { for field, field_idx in fields { - if key == field.name { + tag_value := reflect.struct_tag_get(field.tag, "json") + json_name, _ := json_name_from_tag_value(tag_value) + if json_name == "" && key == field.name { use_field_idx = field_idx break } @@ -486,7 +586,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm } } - if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) { + tag_value := reflect.struct_tag_get(field.tag, "json") + json_name, _ := json_name_from_tag_value(tag_value) + if (json_name == "" && field.name == key) || json_name == key { offset = field.offset type = field.type found = true @@ -508,6 +610,11 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm } if field_found { + field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool { + prev_set := field_used[offset/8] & byte(offset&7) != 0 + field_used[offset/8] |= byte(offset&7) + return prev_set + } if field_test(field_used, offset) { return .Multiple_Use_Field } @@ -528,7 +635,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm defer p.allocator = allocator p.allocator = mem.nil_allocator() - parse_value(p) or_return + _ = parse_value(p) or_return if parse_comma(p) { break struct_loop } @@ -564,7 +671,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm key_ptr: rawptr #partial switch tk in t.key.variant { - case runtime.Type_Info_String: + case runtime.Type_Info_String: + assert(tk.encoding == .UTF_8) + key_ptr = rawptr(&key) key_cstr: cstring if reflect.is_cstring(t.key) { @@ -699,6 +808,16 @@ unmarshal_array :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) { raw.allocator = p.allocator return assign_array(p, raw.data, t.elem, length) + + case reflect.Type_Info_Fixed_Capacity_Dynamic_Array: + if int(length) > t.capacity { + return UNSUPPORTED_TYPE + } + base_ptr := cast(uintptr)v.data + len_ptr := base_ptr + t.len_offset + len_val := cast(^int)len_ptr + len_val^ = int(length) + return assign_array(p, rawptr(base_ptr), t.elem, length) case reflect.Type_Info_Array: // NOTE(bill): Allow lengths which are less than the dst array diff --git a/core/encoding/json/unparse.odin b/core/encoding/json/unparse.odin new file mode 100644 index 000000000..1b00f1b0e --- /dev/null +++ b/core/encoding/json/unparse.odin @@ -0,0 +1,89 @@ +package encoding_json + +import "base:runtime" +import "core:strings" +import "core:io" +import "core:slice" + +Unparse_Error :: union #shared_nil { + io.Error, + runtime.Allocator_Error, +} + +@(require_results) +unparse :: proc(v: Value, opt: Marshal_Options = {}, allocator := context.allocator, loc := #caller_location) -> (data: string, err: Unparse_Error) { + b := strings.builder_make(allocator, loc) + defer if err != nil { + strings.builder_destroy(&b) + } + + // temp guard in case we are sorting map keys, which will use temp allocations + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = allocator == context.temp_allocator) + + opt := opt + unparse_to_builder(&b, v, &opt) or_return + data = string(b.buf[:]) + return +} + +@(require_results) +unparse_to_builder :: proc(b: ^strings.Builder, v: Value, opt: ^Marshal_Options) -> Unparse_Error { + return unparse_to_writer(strings.to_writer(b), v, opt) +} + +@(require_results) +unparse_to_writer :: proc(w: io.Writer, value: Value, opt: ^Marshal_Options) -> Unparse_Error { + switch v in value { + case nil, Null: + io.write_string(w, "null") or_return + case Integer: + base := 16 if opt.write_uint_as_hex && (opt.spec == .JSON5 || opt.spec == .MJSON) else 10 + io.write_i64(w, v, base) or_return + case Float: + io.write_f64(w, v) or_return + case Boolean: + io.write_string(w, "true" if v else "false") or_return + case String: + io.write_quoted_string(w, v, '"', nil, true) or_return + case Array: + opt_write_start(w, opt, '[') or_return + for e, i in v { + opt_write_iteration(w, opt, i == 0) or_return + unparse_to_writer (w, e, opt) or_return + } + opt_write_end(w, opt, ']') or_return + case Object: + if !opt.sort_maps_by_key { + opt_write_start(w, opt, '{') or_return + for first_iteration := true; key, val in v { + opt_write_iteration(w, opt, first_iteration) or_return + opt_write_key (w, opt, key) or_return + unparse_to_writer (w, val, opt) or_return + first_iteration = false + } + opt_write_end(w, opt, '}') or_return + } else { + Map_Entry :: struct { + key: string, + value: Value, + } + + entries := make([dynamic]Map_Entry, 0, len(v), context.temp_allocator) or_return + for key, val in v { + _, _ = append(&entries, Map_Entry{key, val}) + } + + slice.sort_by(entries[:], proc(i, j: Map_Entry) -> bool { return i.key < j.key }) + + opt_write_start(w, opt, '{') or_return + for e, i in entries { + opt_write_iteration(w, opt, i == 0) or_return + opt_write_key (w, opt, e.key) or_return + unparse_to_writer (w, e.value, opt) or_return + } + opt_write_end(w, opt, '}') or_return + } + return nil + } + return nil +} diff --git a/core/encoding/json/validator.odin b/core/encoding/json/validator.odin index a6873319d..e8b5cc49d 100644 --- a/core/encoding/json/validator.odin +++ b/core/encoding/json/validator.odin @@ -3,12 +3,13 @@ package encoding_json import "core:mem" // NOTE(bill): is_valid will not check for duplicate keys +@(require_results) is_valid :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false) -> bool { p := make_parser(data, spec, parse_integers, mem.nil_allocator()) - + switch p.spec { case .JSON: - return validate_object(&p) + return validate_value(&p) case .JSON5: return validate_value(&p) case .MJSON: @@ -21,6 +22,7 @@ is_valid :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := return validate_object(&p) } +@(require_results) validate_object_key :: proc(p: ^Parser) -> bool { if p.spec != .JSON { if allow_token(p, .Ident) { @@ -31,6 +33,7 @@ validate_object_key :: proc(p: ^Parser) -> bool { return err == .None } +@(require_results) validate_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> bool { for p.curr_token.kind != end_token { if !validate_object_key(p) { @@ -48,11 +51,12 @@ validate_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> bool { return true } +@(require_results) validate_object :: proc(p: ^Parser) -> bool { if err := expect_token(p, .Open_Brace); err != .None { return false } - + validate_object_body(p, .Close_Brace) or_return if err := expect_token(p, .Close_Brace); err != .None { @@ -61,6 +65,7 @@ validate_object :: proc(p: ^Parser) -> bool { return true } +@(require_results) validate_array :: proc(p: ^Parser) -> bool { if err := expect_token(p, .Open_Bracket); err != .None { return false @@ -83,6 +88,7 @@ validate_array :: proc(p: ^Parser) -> bool { return true } +@(require_results) validate_value :: proc(p: ^Parser) -> bool { token := p.curr_token @@ -102,7 +108,7 @@ validate_value :: proc(p: ^Parser) -> bool { case .Open_Bracket: return validate_array(p) - + case .Ident: if p.spec == .MJSON { advance_token(p) diff --git a/core/encoding/pem/doc.odin b/core/encoding/pem/doc.odin new file mode 100644 index 000000000..cf5fb20a5 --- /dev/null +++ b/core/encoding/pem/doc.odin @@ -0,0 +1,7 @@ +/* +Encodes and decodes PEM formatted data. + +See: +- [[ https://www.rfc-editor.org/rfc/rfc7468.html ]] +*/ +package pem diff --git a/core/encoding/pem/pem.odin b/core/encoding/pem/pem.odin new file mode 100644 index 000000000..88ba6e2db --- /dev/null +++ b/core/encoding/pem/pem.odin @@ -0,0 +1,299 @@ +package pem + +import "base:runtime" +import "core:bufio" +import "core:bytes" +import "core:crypto" +import "core:encoding/base64" +import "core:strings" + +@(private) +BASE64_FULL_LINE_LENGTH :: 64 +@(private) +BASE64_FULL_LINE_BYTES :: (BASE64_FULL_LINE_LENGTH / 4) * 3 +@(private) +PREFIX_BEGIN : string : "-----BEGIN " +@(private) +PREFIX_END : string : "-----END " +@(private) +SUFFIX : string : "-----" +@(private) +LF :: "\n" +@(private) +PREEB_OVERHEAD :: len(PREFIX_BEGIN) + len(SUFFIX) + len(LF) +@(private) +POSTEB_OVERHEAD :: len(PREFIX_END) + len(SUFFIX) + +// Block is a block of PEM encoded data. +Block :: struct { + label: string, + data: [dynamic]byte, +} + +LABEL_CERTIFICATE :: "CERTIFICATE" // RFC 5280 +LABEL_X509_CRL :: "X509_CRL" // RFC 5280 +LABEL_CERTIFICATE_REQUEST :: "CERTIFICATE REQUEST" // RFC 2986 +LABEL_PKCS7 :: "PKCS7" // RFC 2315 +LABEL_CMS :: "CMS" // RFC 5652 +LABEL_PRIVATE_KEY :: "PRIVATE KEY" // RFC 5208/ RFC 5958 +LABEL_ENCRYPTED_PRIVATE_KEY :: "ENCRYPTED PRIVATE KEY" // RFC 5958 +LABEL_ATTRIBUTE_CERTIFICATE :: "ATTRIBUTE CERTIFICATE" // RFC 5755 +LABEL_PUBLIC_KEY :: "PUBLIC KEY" // RFC 5280 + +Decode_Error :: enum { + None, + Bad_Boundary, // Invalid boundary line. + Bad_Label, // Invalid label in BEGIN/END boundary line. + Bad_Data, // Invalid base64 data. + Label_Mismatch, // Label in END boundary line does not match. + Missing_End_Boundary, // End of data without END boundary. +} + +Error :: union #shared_nil { + runtime.Allocator_Error, + Decode_Error, +} + +// decode decodes the first encountered PEM block, returning the resulting +// block, remaining data, and nil if and only if (⟺) the process was +// successful. +// +// Note: No PEM blocks will result in this procedure returning all nils, +// and is not considered an error. +@(require_results) +decode :: proc(data: []byte, allocator := context.allocator) -> (blk: ^Block, remaining: []byte, err: Error) { + line: []byte + remaining = data + + // Search for the first `preeb`. + label: string + found := false // Label is allowed to be empty. + for len(remaining) > 0 { + line, remaining = get_line(remaining) + + label, found, err = parse_eb(line, true) + if err != nil { + return nil, nil, err + } + if found { + break + } + } + if !found { + return nil, nil, nil + } + + // RFC 1421: Parse header block. + // RFC 7468 (lax): Skip whitespace. + + // Initialize the block. + blk = new(Block, allocator) or_return + if blk.data, err = make([dynamic]byte, 0, 32, allocator); err != nil { + free(blk, allocator) + return nil, nil, err + } + if blk.label, err = strings.clone(label, allocator); err != nil { + block_delete(blk) + return nil, nil, err + } + + // Parse the `strictbase64text`. + l_buf: [BASE64_FULL_LINE_BYTES]byte + defer crypto.zero_explicit(&l_buf, size_of(l_buf)) + base64text_loop: for len(remaining) > 0 { + line, remaining = get_line(remaining) + l := len(line) + switch { + case l == 0: + block_delete(blk) + return nil, nil, .Bad_Data + case line[0] == '-': + // Looks like we hit the `posteb`, break. + break base64text_loop + case l > BASE64_FULL_LINE_LENGTH || l & 3 != 0: + // Padding is mandatory, so the line length will always + // be a multiple of 4. + block_delete(blk) + return nil, nil, .Bad_Data + } + + decoded, dec_err := base64.decode_into_buf(l_buf[:], transmute(string)(line)) + if dec_err != nil { + block_delete(blk) + return nil, nil, .Bad_Data + } + + if _, err = append(&blk.data, ..decoded); err != nil { + block_delete(blk) + return nil, nil, err + } + + // As `strictbase64text = *base64fullline strictbase64finl`, + // if we did not have a full line, we must have reached + // `strictbase64finl`. Grab what should be the `posteb` + // and break. + if l < BASE64_FULL_LINE_LENGTH { + line, remaining = get_line(remaining) + break + } + } + + // Validate the `posteb`. + post_label: string + post_label, found, err = parse_eb(line, false) + if err == nil { + switch { + case !found: + err = .Missing_End_Boundary + case label != post_label: + err = .Label_Mismatch + } + } + if err != nil { + block_delete(blk) + blk, remaining = nil, nil + } + + return +} + +// encode encodes the specified label and data into PEM format. +@(require_results) +encode :: proc(label: string, data: []byte, newline := false, allocator := context.allocator) -> (res: []byte, err: runtime.Allocator_Error) #optional_allocator_error { + sanitize_sb := proc(sb: ^strings.Builder) { + buf := sb.buf[:] + b, l := raw_data(buf), len(buf) + crypto.zero_explicit(b, l) + strings.builder_destroy(sb) + } + + sb := strings.builder_make_none(allocator) or_return + defer sanitize_sb(&sb) + + label_len := len(label) + + // Write `preeb`. + n := strings.write_string(&sb, PREFIX_BEGIN) + n += strings.write_string(&sb, label) + n += strings.write_string(&sb, SUFFIX) + n += strings.write_string(&sb, LF) + if n != PREEB_OVERHEAD + label_len { + return nil, .Out_Of_Memory + } + + // RFC 1421: Write header block. + + // Write `base64text`. + l: [BASE64_FULL_LINE_LENGTH]byte + defer crypto.zero_explicit(&l, size_of(l)) + + d := data + for len(d) > 0 { + n = min(len(d), BASE64_FULL_LINE_BYTES) + encoded, _ := base64.encode_into_buf(l[:], d[:n]) + d = d[n:] + + expected_len := len(encoded) + len(LF) + n = strings.write_bytes(&sb, encoded) + n += strings.write_string(&sb, LF) + if n != expected_len { + return nil, .Out_Of_Memory + } + } + + // Write `posteb`. + expected_len := POSTEB_OVERHEAD + label_len + (len(LF) if newline else 0) + n = strings.write_string(&sb, PREFIX_END) + n += strings.write_string(&sb, label) + n += strings.write_string(&sb, SUFFIX) + if newline { + n += strings.write_string(&sb, LF) + } + if n != expected_len { + return nil, .Out_Of_Memory + } + + res = transmute([]byte)(strings.clone(strings.to_string(sb), allocator) or_return) + + return +} + +// block_bytes returns a slice to the Block's data. +block_bytes :: proc(blk: ^Block) -> []byte { + return blk.data[:] +} + +// block_delete frees a Block returned from decode. +// +// Note: No allocator is specified as decode uses the same allocator +// for everything. +block_delete :: proc(blk: ^Block) { + allocator := ((^runtime.Raw_Dynamic_Array)(&blk.data)).allocator + + delete(blk.label, allocator) + sanitize_and_delete(blk.data) + free(blk, allocator) +} + +@(private) +get_line :: proc(data: []byte) -> (line, rest: []byte) { + adv: int + adv, line, _, _ = bufio.scan_lines(data, true) + rest = data[adv:] + + return +} + +@(private) +parse_eb :: proc(line: []byte, is_pre: bool) -> (label: string, found: bool, err: Error) { + line := line + + prefix: string + switch is_pre { + case true: + prefix = PREFIX_BEGIN + case false: + prefix = PREFIX_END + } + + l := len(line) + line = bytes.trim_prefix(line, transmute([]byte)(prefix)) + if len(line) == l { + return "", false, nil + } + + l = len(line) + line = bytes.trim_suffix(line, transmute([]byte)(SUFFIX)) + if len(line) == l { + return "", false, .Bad_Boundary + } + + // labelchar = %x21-2C / %x2E-7E ; any printable character, + // ; except hyphen-minus + // label = [ labelchar *( ["-" / SP] labelchar ) ] ; empty ok + l = len(line) + line = bytes.trim(line, []byte{'-', ' '}) + if len(line) != l { + return "", false, .Bad_Label + } + for b in line { + // We already ruled out non-labelchar start/end, so this + // allows ' '/'-'. + if b < 0x20 || b > 0x7e { + return "", false, .Bad_Label + } + } + + found = true + label = transmute(string)(line) + + return +} + +@(private) +sanitize_and_delete :: proc(data: [dynamic]byte) { + b, l := raw_data(data), len(data) + crypto.zero_explicit(b, l) + + delete(data) +} diff --git a/core/encoding/uuid/LICENSE b/core/encoding/uuid/LICENSE index e4e21e62d..c7f46ddf6 100644 --- a/core/encoding/uuid/LICENSE +++ b/core/encoding/uuid/LICENSE @@ -1,28 +1,17 @@ -BSD 3-Clause License +Copyright (c) 2024-2025 Feoramund, Ginger Bill. All rights reserved. -Copyright (c) 2024, Feoramund +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/core/encoding/uuid/doc.odin b/core/encoding/uuid/doc.odin index f910c33d8..a5f01ca7c 100644 --- a/core/encoding/uuid/doc.odin +++ b/core/encoding/uuid/doc.odin @@ -1,6 +1,5 @@ /* -package uuid implements Universally Unique Identifiers according to the -standard originally outlined in RFC 4122 with additions from RFC 9562. +Universally Unique Identifiers (`UUID`) according to [[ RFC 4122 ; https://tools.ietf.org/html/rfc4122.html ]], with additions from [[ RFC 9562 ; https://tools.ietf.org/html/rfc9562.html ]]. The UUIDs are textually represented and read in the following string format: `00000000-0000-v000-V000-000000000000` diff --git a/core/encoding/uuid/legacy/legacy.odin b/core/encoding/uuid/legacy/legacy.odin index d5f3df617..fe5c88e23 100644 --- a/core/encoding/uuid/legacy/legacy.odin +++ b/core/encoding/uuid/legacy/legacy.odin @@ -1,7 +1,6 @@ /* -package uuid/legacy implements versions 3 and 5 of UUID generation, both of -which are using hashing algorithms (MD5 and SHA1, respectively) that are known -these days to no longer be secure. +Versions 3 and 5 of `UUID` generation, both of which use legacy (`MD5` + `SHA1`) hashes. +Those are known these days to no longer be secure. */ package uuid_legacy diff --git a/core/encoding/varint/doc.odin b/core/encoding/varint/doc.odin index a00cfed15..e17faec49 100644 --- a/core/encoding/varint/doc.odin +++ b/core/encoding/varint/doc.odin @@ -1,7 +1,5 @@ /* -Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others. - -Author of this Odin package: Jeroen van Rijn +`LEB128` variable integer encoding and decoding, as used by `DWARF` & `DEX` files. Example: package main @@ -24,4 +22,4 @@ Example: fmt.printf("Decoded as %v, using %v byte%v\n", decoded_val, decode_size, "" if decode_size == 1 else "s") } */ -package encoding_varint +package encoding_varint \ No newline at end of file diff --git a/core/encoding/varint/leb128.odin b/core/encoding/varint/leb128.odin index 606c57ba7..86a72f121 100644 --- a/core/encoding/varint/leb128.odin +++ b/core/encoding/varint/leb128.odin @@ -1,13 +1,13 @@ +package encoding_varint + /* Copyright 2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. */ -package encoding_varint - // In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file. // Instead we'll set limits on the values we'll encode/decode // 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`. diff --git a/core/encoding/xml/debug_print.odin b/core/encoding/xml/debug_print.odin index acced262a..9c47e79e8 100644 --- a/core/encoding/xml/debug_print.odin +++ b/core/encoding/xml/debug_print.odin @@ -4,7 +4,7 @@ package encoding_xml An XML 1.0 / 1.1 parser Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. A from-scratch XML implementation, loosely modeled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816). diff --git a/core/encoding/xml/doc.odin b/core/encoding/xml/doc.odin index 10d9f78be..9030cd400 100644 --- a/core/encoding/xml/doc.odin +++ b/core/encoding/xml/doc.odin @@ -1,7 +1,7 @@ /* -XML 1.0 / 1.1 parser +A parser for a useful subset of the `XML` specification. -A from-scratch XML implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]]. +A from-scratch `XML` implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]]. Features: - Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage. @@ -11,8 +11,8 @@ Caveats: - We do NOT support HTML in this package, as that may or may not be valid XML. If it works, great. If it doesn't, that's not considered a bug. -- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences. -- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options. +- We do NOT support `UTF-16`. If you have a `UTF-16` XML file, please convert it to `UTF-8` first. Also, our condolences. +- `<[!ELEMENT` and `<[!ATTLIST` are not supported, and will be either ignored or return an error depending on the parser options. MAYBE: - XML writer? diff --git a/core/encoding/xml/example/xml_example.odin b/core/encoding/xml/example/xml_example.odin index 9648143db..5ea689069 100644 --- a/core/encoding/xml/example/xml_example.odin +++ b/core/encoding/xml/example/xml_example.odin @@ -10,8 +10,6 @@ import "core:hash" N :: 1 example :: proc() { - using fmt - docs: [N]^xml.Document errs: [N]xml.Error times: [N]time.Duration @@ -59,23 +57,23 @@ example :: proc() { fmt.printf("[Average]: %v bytes in %.2f ms (%.2f MiB/s).\n", len(input), average_ms, average_speed) if errs[0] != .None { - printf("Load/Parse error: %v\n", errs[0]) + fmt.eprintf("Load/Parse error: %v\n", errs[0]) if errs[0] == .File_Error { - println("\"unicode.xml\" not found. Did you run \"tests\\download_assets.py\"?") + fmt.eprintln("\"unicode.xml\" not found. Did you run \"tests\\download_assets.py\"?") } return } charlist, charlist_ok := xml.find_child_by_ident(docs[0], 0, "charlist") if !charlist_ok { - eprintln("Could not locate top-level `` tag.") - return + fmt.eprintln("Could not locate top-level `` tag.") + return } - printf("Found `` with %v children, %v elements total\n", len(docs[0].elements[charlist].value), docs[0].element_count) + fmt.printf("Found `` with %v children, %v elements total\n", len(docs[0].elements[charlist].value), docs[0].element_count) crc32 := doc_hash(docs[0], false) - printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0x420dbac5 else "🤬", crc32) + fmt.printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0x420dbac5 else "🤬", crc32) for round in 0.. (crc32: u32) { } main :: proc() { - using fmt - track: mem.Tracking_Allocator mem.tracking_allocator_init(&track, context.allocator) context.allocator = mem.tracking_allocator(&track) @@ -103,10 +99,10 @@ main :: proc() { example() if len(track.allocation_map) > 0 { - println() + fmt.println() for _, v in track.allocation_map { - printf("%v Leaked %v bytes.\n", v.location, v.size) + fmt.printf("%v Leaked %v bytes.\n", v.location, v.size) } } - println("Done and cleaned up!") + fmt.println("Done and cleaned up!") } diff --git a/core/encoding/xml/helpers.odin b/core/encoding/xml/helpers.odin index a9d4ad493..79f2d72c7 100644 --- a/core/encoding/xml/helpers.odin +++ b/core/encoding/xml/helpers.odin @@ -4,7 +4,7 @@ package encoding_xml An XML 1.0 / 1.1 parser Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. This file contains helper functions. */ diff --git a/core/encoding/xml/tokenizer.odin b/core/encoding/xml/tokenizer.odin index 3ef9a6388..d07f41580 100644 --- a/core/encoding/xml/tokenizer.odin +++ b/core/encoding/xml/tokenizer.odin @@ -4,7 +4,7 @@ package encoding_xml An XML 1.0 / 1.1 parser Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. A from-scratch XML implementation, loosely modeled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816). @@ -264,7 +264,7 @@ scan_comment :: proc(t: ^Tokenizer) -> (comment: string, err: Error) { expect(t, .Dash) expect(t, .Gt) - return string(t.src[offset : t.offset - 1]), .None + return string(t.src[offset : t.offset - 3]), .None } // Skip CDATA diff --git a/core/encoding/xml/xml_os.odin b/core/encoding/xml/xml_os.odin new file mode 100644 index 000000000..1e94572c6 --- /dev/null +++ b/core/encoding/xml/xml_os.odin @@ -0,0 +1,18 @@ +#+build !freestanding +#+build !js +package encoding_xml + +import "core:os" + +// Load an XML file +load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) { + context.allocator = allocator + options := options + + data, data_err := os.read_entire_file(filename, allocator) + if data_err != nil { return {}, .File_Error } + + options.flags += { .Input_May_Be_Modified } + + return parse_bytes(data, options, filename, error_handler, allocator) +} diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin index d616be9dc..6d068466b 100644 --- a/core/encoding/xml/xml_reader.odin +++ b/core/encoding/xml/xml_reader.odin @@ -1,21 +1,20 @@ +package encoding_xml /* + An XML 1.0 / 1.1 parser + 2021-2022 Jeroen van Rijn . - available under Odin's BSD-3 license. + available under Odin's license. List of contributors: - Jeroen van Rijn: Initial implementation. */ -package encoding_xml -// An XML 1.0 / 1.1 parser - -import "core:bytes" -import "core:encoding/entity" -import "base:intrinsics" -import "core:mem" -import "core:os" -import "core:strings" -import "base:runtime" +import "base:runtime" +import "core:bytes" +import "core:encoding/entity" +import "base:intrinsics" +import "core:mem" +import "core:strings" likely :: intrinsics.expect @@ -175,7 +174,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha data = bytes.clone(data) } - t := &Tokenizer{} + t := new(Tokenizer) init(t, string(data), path, error_handler) doc = new(Document) @@ -294,7 +293,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha comment := scan_comment(t) or_return if .Intern_Comments in opts.flags { - if len(doc.elements) == 0 { + if doc.element_count == 0 { append(&doc.comments, comment) } else { el := new_element(doc) @@ -308,6 +307,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha case .Open_Bracket: // This could be a CDATA tag part of a tag's body. Unread the ` (doc: ^Document, err: Error) { +destroy :: proc(doc: ^Document, allocator := context.allocator) { context.allocator = allocator - options := options - - data, data_ok := os.read_entire_file(filename) - if !data_ok { return {}, .File_Error } - - options.flags += { .Input_May_Be_Modified } - - return parse_bytes(data, options, filename, error_handler, allocator) -} - -destroy :: proc(doc: ^Document) { if doc == nil { return } for el in doc.elements { @@ -403,6 +391,7 @@ destroy :: proc(doc: ^Document) { } delete(doc.strings_to_free) + free(doc.tokenizer) free(doc) } @@ -624,4 +613,4 @@ new_element :: proc(doc: ^Document) -> (id: Element_ID) { cur := doc.element_count doc.element_count += 1 return cur -} \ No newline at end of file +} diff --git a/core/flags/LICENSE b/core/flags/LICENSE index e4e21e62d..c7f46ddf6 100644 --- a/core/flags/LICENSE +++ b/core/flags/LICENSE @@ -1,28 +1,17 @@ -BSD 3-Clause License +Copyright (c) 2024-2025 Feoramund, Ginger Bill. All rights reserved. -Copyright (c) 2024, Feoramund +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/core/flags/constants.odin b/core/flags/constants.odin index 6f5281928..154ed3cec 100644 --- a/core/flags/constants.odin +++ b/core/flags/constants.odin @@ -11,15 +11,14 @@ NO_CORE_NAMED_TYPES :: #config(ODIN_CORE_FLAGS_NO_CORE_NAMED_TYPES, false) IMPORTING_TIME :: #config(ODIN_CORE_FLAGS_USE_TIME, time.IS_SUPPORTED) // Override support for parsing `net` types. -// TODO: Update this when the BSDs are supported. -IMPORTING_NET :: #config(ODIN_CORE_FLAGS_USE_NET, ODIN_OS == .Windows || ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD) +IMPORTING_NET :: #config(ODIN_CORE_FLAGS_USE_NET, ODIN_OS == .Windows || ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD) TAG_ARGS :: "args" SUBTAG_NAME :: "name" SUBTAG_POS :: "pos" SUBTAG_REQUIRED :: "required" SUBTAG_HIDDEN :: "hidden" -SUBTAG_VARIADIC :: "variadic" +SUBTAG_MANIFOLD :: "manifold" SUBTAG_FILE :: "file" SUBTAG_PERMS :: "perms" SUBTAG_INDISTINCT :: "indistinct" @@ -28,7 +27,7 @@ TAG_USAGE :: "usage" UNDOCUMENTED_FLAG :: "" -INTERNAL_VARIADIC_FLAG :: "varg" +INTERNAL_OVERFLOW_FLAG :: #config(ODIN_CORE_FLAGS_OVERFLOW_FLAG, "overflow") RESERVED_HELP_FLAG :: "help" RESERVED_HELP_FLAG_SHORT :: "h" diff --git a/core/flags/doc.odin b/core/flags/doc.odin index b97547806..e17cff21b 100644 --- a/core/flags/doc.odin +++ b/core/flags/doc.odin @@ -1,5 +1,5 @@ /* -package flags implements a command-line argument parser. +Command-line argument parser. It works by using Odin's run-time type information to determine where and how to store data on a struct provided by the program. Type conversion is handled @@ -11,13 +11,32 @@ Command-Line Syntax: Arguments are treated differently depending on how they're formatted. The format is similar to the Odin binary's way of handling compiler flags. - type handling - ------------ ------------------------ - depends on struct layout - - set a bool true - - set flag to option - - set flag to option, alternative syntax - -:= set map[key] to value + type handling + ------------ ------------------------ + depends on struct layout + - set a bool true + - set flag to option + - set flag to option, alternative syntax + - set bit_set flag to one or more options + - set bit_set flag to one or more options, alternative syntax + -:= set map[key] to value + +Underscores (`_`) in a flag will be replaced with dashes (`-`). + +Bit sets may be set with a strictly comma-separated list of options. + +Bit sets may also be set with a binary string of 0s and 1s, and will be parsed from left to right, from least significant bit to most significant bit. Underscores are allowed and will be ignored. However, starting with an underscore is disallowed. + + +Unhandled Arguments: + +All unhandled positional arguments are placed into the `overflow` field on a +struct, if it exists. In UNIX-style parsing, the existence of a `--` on the +command line will also pass all arguments afterwards into this field. + +If desired, the name of the field may be changed from `overflow` to any string +by setting the `ODIN_CORE_FLAGS_OVERFLOW_FLAG` compile-time config option with +`-define:ODIN_CORE_FLAGS_OVERFLOW_FLAG=`. Struct Tags: @@ -32,7 +51,7 @@ Under the `args` tag, there are the following subtags: - `pos=N`: place positional argument `N` into this flag. - `hidden`: hide this flag from the usage documentation. - `required`: cause verification to fail if this argument is not set. -- `variadic`: take all remaining arguments when set, UNIX-style only. +- `manifold=N`: take several arguments at once, UNIX-style only. - `file`: for `os.Handle` types, file open mode. - `perms`: for `os.Handle` types, file open permissions. - `indistinct`: allow the setting of distinct types by their base type. @@ -47,8 +66,9 @@ you want to require 3 and only 3 arguments in a dynamic array, you would specify `required=3<4`. -`variadic` may be given a number (`variadic=N`) above 1 to limit how many extra -arguments it consumes. +`manifold` may be given a number (`manifold=N`) above 1 to limit how many extra +arguments it consumes at once. If this number is not specified, it will take as +many arguments as can be converted to the underlying element type. `file` determines the file open mode for an `os.Handle`. @@ -160,7 +180,7 @@ at parse time. --flag --flag=argument --flag argument - --flag argument repeating-argument + --flag argument (manifold-argument) `-flag` may also be substituted for `--flag`. diff --git a/core/flags/errors.odin b/core/flags/errors.odin index 6e48f6ccf..efe4cb6c4 100644 --- a/core/flags/errors.odin +++ b/core/flags/errors.odin @@ -1,10 +1,12 @@ package flags +import "base:runtime" +import "core:net" import "core:os" Parse_Error_Reason :: enum { None, - // An extra positional argument was given, and there is no `varg` field. + // An extra positional argument was given, and there is no `overflow` field. Extra_Positional, // The underlying type does not support the string value it is being set to. Bad_Value, @@ -24,13 +26,19 @@ Parse_Error :: struct { message: string, } +Unified_Parse_Error_Reason :: union #shared_nil { + Parse_Error_Reason, + runtime.Allocator_Error, + net.Parse_Endpoint_Error, +} + // Raised during parsing. // Provides more granular information than what just a string could hold. Open_File_Error :: struct { filename: string, errno: os.Error, - mode: int, - perms: int, + flags: os.File_Flags, + perms: os.Permissions, } // Raised during parsing. diff --git a/core/flags/errors_bsd.odin b/core/flags/errors_bsd.odin deleted file mode 100644 index 4d98d2ee4..000000000 --- a/core/flags/errors_bsd.odin +++ /dev/null @@ -1,9 +0,0 @@ -#+build netbsd, openbsd -package flags - -import "base:runtime" - -Unified_Parse_Error_Reason :: union #shared_nil { - Parse_Error_Reason, - runtime.Allocator_Error, -} diff --git a/core/flags/errors_nonbsd.odin b/core/flags/errors_nonbsd.odin deleted file mode 100644 index 28912b57f..000000000 --- a/core/flags/errors_nonbsd.odin +++ /dev/null @@ -1,12 +0,0 @@ -#+build !netbsd -#+build !openbsd -package flags - -import "base:runtime" -import "core:net" - -Unified_Parse_Error_Reason :: union #shared_nil { - Parse_Error_Reason, - runtime.Allocator_Error, - net.Parse_Endpoint_Error, -} diff --git a/core/flags/example/example.odin b/core/flags/example/example.odin index b1d7b58d6..204fca8e9 100644 --- a/core/flags/example/example.odin +++ b/core/flags/example/example.odin @@ -20,6 +20,14 @@ Optimization_Level :: enum { Ludicrous_Speed, } +Vet_Flag :: enum { + Unused, + Unused_Variables, + Unused_Imports, + Shadowing, + Using_Stmt, +} + // It's simple but powerful. my_custom_type_setter :: proc( data: rawptr, @@ -76,13 +84,15 @@ Distinct_Int :: distinct int main :: proc() { Options :: struct { - file: os.Handle `args:"pos=0,required,file=r" usage:"Input file."`, - output: os.Handle `args:"pos=1,file=cw" usage:"Output file."`, + file: ^os.File `args:"pos=0,required,file=r" usage:"Input file."`, + output: ^os.File `args:"pos=1,file=cw" usage:"Output file."`, hub: net.Host_Or_Endpoint `usage:"Internet address to contact for updates."`, schedule: datetime.DateTime `usage:"Launch tasks at this time."`, opt: Optimization_Level `usage:"Optimization level."`, + vet_flags: bit_set[Vet_Flag] `usage:"Vet flags. Example usage: + -vet-flags:Unused,Shadowing"`, todo: [dynamic]string `usage:"Todo items."`, accuracy: Fixed_Point1_1 `args:"required" usage:"Lenience in FLOP calculations."`, @@ -107,14 +117,14 @@ main :: proc() { // assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`, - // (Variadic) Only available in UNIX style: + // (Manifold) Only available in UNIX style: - // bots: [dynamic]string `args:"variadic=2,required"`, + // bots: [dynamic]string `args:"manifold=2,required"`, verbose: bool `usage:"Show verbose output."`, debug: bool `args:"hidden" usage:"print debug info"`, - varg: [dynamic]string `usage:"Any extra arguments go here."`, + overflow: [dynamic]string `usage:"Any extra arguments go here."`, } opt: Options @@ -126,7 +136,7 @@ main :: proc() { fmt.printfln("%#v", opt) - if opt.output != 0 { + if opt.output != nil { os.write_string(opt.output, "Hellope!\n") } } diff --git a/core/flags/internal_assignment.odin b/core/flags/internal_assignment.odin index 12ddb876f..5999dbf2d 100644 --- a/core/flags/internal_assignment.odin +++ b/core/flags/internal_assignment.odin @@ -33,9 +33,9 @@ push_positional :: #force_no_inline proc (model: ^$T, parser: ^Parser, arg: stri field, index, has_pos_assigned := get_field_by_pos(model, pos) if !has_pos_assigned { - when intrinsics.type_has_field(T, INTERNAL_VARIADIC_FLAG) { + when intrinsics.type_has_field(T, INTERNAL_OVERFLOW_FLAG) { // Add it to the fallback array. - field = reflect.struct_field_by_name(T, INTERNAL_VARIADIC_FLAG) + field = reflect.struct_field_by_name(T, INTERNAL_OVERFLOW_FLAG) } else { return Parse_Error { .Extra_Positional, @@ -117,8 +117,8 @@ set_unix_flag :: proc(model: ^$T, parser: ^Parser, name: string) -> (future_args case runtime.Type_Info_Dynamic_Array: future_args = 1 if tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok { - if length, is_variadic := get_struct_subtag(tag, SUBTAG_VARIADIC); is_variadic { - // Variadic arrays may specify how many arguments they consume at once. + if length, is_manifold := get_struct_subtag(tag, SUBTAG_MANIFOLD); is_manifold { + // Manifold arrays may specify how many arguments they consume at once. // Otherwise, they take everything that's left. if value, value_ok := strconv.parse_u64_of_base(length, 10); value_ok { future_args = cast(int)value diff --git a/core/flags/internal_parsing.odin b/core/flags/internal_parsing.odin index 4e49f45b0..6d544e5af 100644 --- a/core/flags/internal_parsing.odin +++ b/core/flags/internal_parsing.odin @@ -95,7 +95,7 @@ parse_one_unix_arg :: proc(model: ^$T, parser: ^Parser, arg: string) -> ( // `--`, and only `--`. // Everything from now on will be treated as an argument. future_args = max(int) - current_flag = INTERNAL_VARIADIC_FLAG + current_flag = INTERNAL_OVERFLOW_FLAG return } } diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin index 1c559ca55..8a79f75a8 100644 --- a/core/flags/internal_rtti.odin +++ b/core/flags/internal_rtti.odin @@ -1,17 +1,18 @@ #+private package flags -import "base:intrinsics" -import "base:runtime" -import "core:fmt" -import "core:mem" -import "core:os" -import "core:reflect" -import "core:strconv" -import "core:strings" -@require import "core:time" -@require import "core:time/datetime" -import "core:unicode/utf8" +import "base:intrinsics" +import "base:runtime" +import "core:fmt" +import "core:mem" +import "core:net" +@(require) import "core:os" +import "core:reflect" +import "core:strconv" +import "core:strings" +@(require) import "core:time" +@(require) import "core:time/datetime" +import "core:unicode/utf8" @(optimization_mode="favor_size") parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: ^runtime.Type_Info) -> bool { @@ -109,7 +110,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: case f32be: (^f32be)(ptr)^ = cast(f32be) value case f64be: (^f64be)(ptr)^ = cast(f64be) value } - + case runtime.Type_Info_Complex: value := strconv.parse_complex128(str) or_return switch type_info.id { @@ -117,7 +118,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: case complex64: (^complex64) (ptr)^ = (complex64)(value) case complex128: (^complex128)(ptr)^ = value } - + case runtime.Type_Info_Quaternion: value := strconv.parse_quaternion256(str) or_return switch type_info.id { @@ -127,6 +128,8 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: } case runtime.Type_Info_String: + assert(specific_type_info.encoding == .UTF_8) + if specific_type_info.is_cstring { cstr_ptr := (^cstring)(ptr) if cstr_ptr != nil { @@ -149,15 +152,16 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: } case runtime.Type_Info_Bit_Set: - // Parse a string of 1's and 0's, from left to right, + // Parse a string of 1s and 0s, from left to right, // least significant bit to most significant bit. value: u128 // NOTE: `upper` is inclusive, i.e: `0..=31` - max_bit_index := u128(1 + specific_type_info.upper - specific_type_info.lower) + underscores := u128(strings.count(str, "_")) + bit_index_limit := u128(1 + specific_type_info.upper - specific_type_info.lower) + underscores bit_index := u128(0) #no_bounds_check for string_index in 0..= {.Read, .Write} { + octal_perms |= 0o200 + } else if .Write in flags { + octal_perms |= 0o200 } else { - mode |= os.O_RDONLY + flags |= {.Read} } if permstr, ok := get_struct_subtag(arg_tag, SUBTAG_PERMS); ok { if value, parse_ok := strconv.parse_u64_of_base(permstr, 8); parse_ok { - perms = int(value) + octal_perms = int(value) } } - handle, errno := os.open(str, mode, perms) - if errno != nil { + perms := os.perm(octal_perms) + + f, error := os.open(str, flags, perms) + if error != nil { // NOTE(Feoramund): os.Error is system-dependent, and there's // currently no good way to translate them all into strings. // - // The upcoming `os2` package will hopefully solve this. + // The upcoming `core:os` package will hopefully solve this. // // We can at least provide the number for now, so the user can look // it up. out_error^ = Open_File_Error { str, - errno, - mode, + error, + flags, perms, } return } - (^os.Handle)(ptr)^ = handle + (^^os.File)(ptr)^ = f return } @@ -308,7 +309,18 @@ parse_and_set_pointer_by_named_type :: proc(ptr: rawptr, str: string, data_type: } when IMPORTING_NET { - if try_net_parse_workaround(data_type, str, ptr, out_error) { + if data_type == net.Host_Or_Endpoint { + addr, net_error := net.parse_hostname_or_endpoint(str) + if net_error != nil { + // We pass along `net.Error` here. + out_error^ = Parse_Error { + net_error, + "Invalid Host/Endpoint.", + } + return + } + + (cast(^net.Host_Or_Endpoint)ptr)^ = addr return } } @@ -410,7 +422,7 @@ parse_and_set_pointer_by_type :: proc(ptr: rawptr, str: string, type_info: ^runt } } else { parse_and_set_pointer_by_named_type(ptr, str, type_info.id, arg_tag, &error) - + if error != nil { // So far, it's none of the types that we recognize. // Check to see if we can set it by base type, if allowed. @@ -460,7 +472,76 @@ parse_and_set_pointer_by_type :: proc(ptr: rawptr, str: string, type_info: ^runt } } + case runtime.Type_Info_Bit_Set: + if str[0] == '0' || str[0] == '1' { + if !parse_and_set_pointer_by_base_type(ptr, str, type_info) { + return Parse_Error { + // The caller will add more details. + .Bad_Value, + "", + } + } else { + error = nil + return + } + } + + value: u128 + + et := runtime.type_info_base(specific_type_info.elem) + if enum_type_info, is_enum := et.variant.(runtime.Type_Info_Enum); is_enum { + names, _ := strings.split(str, ",", context.temp_allocator) + valid_names := enum_type_info.names + underlying_values := enum_type_info.values + + #no_bounds_check outer_loop: for name in names { + found: bool + #no_bounds_check for valid_name, index in valid_names { + if name == valid_name { + shift := u128(underlying_values[index]) - u128(specific_type_info.lower) + value |= u128(1 << shift) + found = true + continue outer_loop + } + } + if !found { + return Parse_Error { + .Bad_Value, + fmt.tprintf( + "Invalid value name: `%s`. Valid names are: %s", + name, + valid_names, + ), + } + } + } + } else { + return Parse_Error { + // The caller will add more details. + .Bad_Value, + "", + } + } + + if specific_type_info.underlying != nil { + set_unbounded_integer_by_type(ptr, value, specific_type_info.underlying.id) + } else { + switch 8*type_info.size { + case 8: (^u8) (ptr)^ = cast(u8) value + case 16: (^u16) (ptr)^ = cast(u16) value + case 32: (^u32) (ptr)^ = cast(u32) value + case 64: (^u64) (ptr)^ = cast(u64) value + case 128: (^u128)(ptr)^ = value + } + } + error = nil + case: + if type_info.id == ^os.File { + parse_and_set_pointer_by_named_type(ptr, str, type_info.id, arg_tag, &error) + return + } + if !parse_and_set_pointer_by_base_type(ptr, str, type_info) { return Parse_Error { // The caller will add more details. diff --git a/core/flags/internal_rtti_nonbsd.odin b/core/flags/internal_rtti_nonbsd.odin deleted file mode 100644 index e1286186b..000000000 --- a/core/flags/internal_rtti_nonbsd.odin +++ /dev/null @@ -1,32 +0,0 @@ -#+private -#+build !netbsd -#+build !openbsd -package flags - -import "core:net" - -// This proc exists purely as a workaround for import restrictions. -// Returns true if caller should return early. -try_net_parse_workaround :: #force_inline proc ( - data_type: typeid, - str: string, - ptr: rawptr, - out_error: ^Error, -) -> bool { - if data_type == net.Host_Or_Endpoint { - addr, net_error := net.parse_hostname_or_endpoint(str) - if net_error != nil { - // We pass along `net.Error` here. - out_error^ = Parse_Error { - net_error, - "Invalid Host/Endpoint.", - } - return true - } - - (cast(^net.Host_Or_Endpoint)ptr)^ = addr - return true - } - - return false -} diff --git a/core/flags/internal_validation.odin b/core/flags/internal_validation.odin index afd05331c..6f9016a21 100644 --- a/core/flags/internal_validation.odin +++ b/core/flags/internal_validation.odin @@ -59,7 +59,8 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ } } - if pos_str, has_pos := get_struct_subtag(args_tag, SUBTAG_POS); has_pos { + pos_str, has_pos := get_struct_subtag(args_tag, SUBTAG_POS) + if has_pos { #partial switch specific_type_info in field.type.variant { case runtime.Type_Info_Map: fmt.panicf("%T.%s has `%s` defined, and this does not make sense on a map type.", @@ -79,7 +80,7 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ fmt.assertf(!reflect.is_boolean(field.type), "%T.%s is a required boolean. This is disallowed.", model_type, field.name, loc = loc) - fmt.assertf(field.name != INTERNAL_VARIADIC_FLAG, "%T.%s is defined as required. This is disallowed.", + fmt.assertf(field.name != INTERNAL_OVERFLOW_FLAG, "%T.%s is defined as required. This is disallowed.", model_type, field.name, loc = loc) if len(requirement) > 0 { @@ -109,44 +110,48 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ } } - if length, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic { + if length, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold { + fmt.assertf(!has_pos, + "%T.%s has both `%s` and `%s` defined. This is disallowed.\n\tSuggestion: Use a dynamic array field named `%s` to accept unspecified positional arguments.", + model_type, field.name, SUBTAG_POS, SUBTAG_MANIFOLD, INTERNAL_OVERFLOW_FLAG, loc = loc) + if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok { fmt.assertf(value > 0, "%T.%s has `%s` set to %i. It must be greater than zero.", - model_type, field.name, value, SUBTAG_VARIADIC, loc = loc) + model_type, field.name, value, SUBTAG_MANIFOLD, loc = loc) fmt.assertf(value != 1, - "%T.%s has `%s` set to 1. This has no effect.", - model_type, field.name, SUBTAG_VARIADIC, loc = loc) + "%T.%s has `%s` set to 1. This is equivalent to not defining `%s`.", + model_type, field.name, SUBTAG_MANIFOLD, SUBTAG_MANIFOLD, loc = loc) } #partial switch specific_type_info in field.type.variant { case runtime.Type_Info_Dynamic_Array: fmt.assertf(style != .Odin, "%T.%s has `%s` defined, but this only makes sense in UNIX-style parsing mode.", - model_type, field.name, SUBTAG_VARIADIC, loc = loc) + model_type, field.name, SUBTAG_MANIFOLD, loc = loc) case: fmt.panicf("%T.%s has `%s` defined, but this only makes sense on dynamic arrays.", - model_type, field.name, SUBTAG_VARIADIC, loc = loc) + model_type, field.name, SUBTAG_MANIFOLD, loc = loc) } } allowed_to_define_file_perms: bool = --- #partial switch specific_type_info in field.type.variant { case runtime.Type_Info_Map: - allowed_to_define_file_perms = specific_type_info.value.id == os.Handle + allowed_to_define_file_perms = specific_type_info.value.id == ^os.File case runtime.Type_Info_Dynamic_Array: - allowed_to_define_file_perms = specific_type_info.elem.id == os.Handle + allowed_to_define_file_perms = specific_type_info.elem.id == ^os.File case: - allowed_to_define_file_perms = field.type.id == os.Handle + allowed_to_define_file_perms = field.type.id == ^os.File } if _, has_file := get_struct_subtag(args_tag, SUBTAG_FILE); has_file { - fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `os.Handle` type.", + fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `^os.File` type.", model_type, field.name, SUBTAG_FILE, loc = loc) } if _, has_perms := get_struct_subtag(args_tag, SUBTAG_PERMS); has_perms { - fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `os.Handle` type.", + fmt.assertf(allowed_to_define_file_perms, "%T.%s has `%s` defined, but it is not nor does it contain an `^os.File` type.", model_type, field.name, SUBTAG_PERMS, loc = loc) } diff --git a/core/flags/parsing.odin b/core/flags/parsing.odin index 2d8ce34eb..989a9a1a6 100644 --- a/core/flags/parsing.odin +++ b/core/flags/parsing.odin @@ -6,7 +6,7 @@ package flags Parsing_Style :: enum { // Odin-style: `-flag`, `-flag:option`, `-map:key=value` Odin, - // UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument repeating-argument` + // UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument (manifold-argument)` Unix, } @@ -61,7 +61,7 @@ parse :: proc( } case .Unix: - // Support for `-flag argument (repeating-argument ...)` + // Support for `-flag argument (manifold-argument ...)` future_args: int current_flag: string diff --git a/core/flags/rtti.odin b/core/flags/rtti.odin index ce7a23773..058292698 100644 --- a/core/flags/rtti.odin +++ b/core/flags/rtti.odin @@ -38,6 +38,6 @@ Note that only one can be active at a time. Inputs: - setter: The type setter. Pass `nil` to disable any previously set setter. */ -register_type_setter :: proc(setter: Custom_Type_Setter) { +register_type_setter :: proc "contextless" (setter: Custom_Type_Setter) { global_custom_type_setter = setter } diff --git a/core/flags/usage.odin b/core/flags/usage.odin index c42df7576..a44baec81 100644 --- a/core/flags/usage.odin +++ b/core/flags/usage.odin @@ -30,18 +30,18 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty is_positional: bool, is_required: bool, is_boolean: bool, - is_variadic: bool, - variadic_length: int, + is_manifold: bool, + manifold_length: int, } // // POSITIONAL+REQUIRED, POSITIONAL, REQUIRED, NON_REQUIRED+NON_POSITIONAL, ... // sort_flags :: proc(i, j: Flag) -> slice.Ordering { - // `varg` goes to the end. - if i.name == INTERNAL_VARIADIC_FLAG { + // `overflow` goes to the end. + if i.name == INTERNAL_OVERFLOW_FLAG { return .Greater - } else if j.name == INTERNAL_VARIADIC_FLAG { + } else if j.name == INTERNAL_OVERFLOW_FLAG { return .Less } @@ -120,10 +120,10 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty flag.is_required = true flag.required_min, flag.required_max, _ = parse_requirements(requirement) } - if length_str, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic { - flag.is_variadic = true + if length_str, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold { + flag.is_manifold = true if length, parse_ok := strconv.parse_u64_of_base(length_str, 10); parse_ok { - flag.variadic_length = cast(int)length + flag.manifold_length = cast(int)length } } } @@ -147,15 +147,15 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty case runtime.Type_Info_Dynamic_Array: requirement_spec := describe_array_requirements(flag) - if flag.is_variadic || flag.name == INTERNAL_VARIADIC_FLAG { - if flag.variadic_length == 0 { + if flag.is_manifold || flag.name == INTERNAL_OVERFLOW_FLAG { + if flag.manifold_length == 0 { flag.type_description = fmt.tprintf("<%v, ...>%s", specific_type_info.elem.id, requirement_spec) } else { flag.type_description = fmt.tprintf("<%v, %i at once>%s", specific_type_info.elem.id, - flag.variadic_length, + flag.manifold_length, requirement_spec) } } else { @@ -177,7 +177,7 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty } } - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { flag.full_length = len(flag.type_description) } else if flag.is_boolean { flag.full_length = len(flag_prefix) + len(flag.name) + len(flag.type_description) @@ -201,13 +201,13 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty strings.write_string(&builder, program) for flag in visible_flags { - if keep_it_short && !(flag.is_required || flag.is_positional || flag.name == INTERNAL_VARIADIC_FLAG) { + if keep_it_short && !(flag.is_required || flag.is_positional || flag.name == INTERNAL_OVERFLOW_FLAG) { continue } strings.write_byte(&builder, ' ') - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { strings.write_string(&builder, "...") continue } @@ -252,7 +252,7 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty strings.write_byte(&builder, '\t') - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { strings.write_string(&builder, flag.type_description) } else { strings.write_string(&builder, flag_prefix) diff --git a/core/flags/util.odin b/core/flags/util.odin index ce7e2e36c..b5e557cf6 100644 --- a/core/flags/util.odin +++ b/core/flags/util.odin @@ -1,9 +1,9 @@ package flags -import "core:fmt" +import "core:fmt" @require import "core:os" @require import "core:path/filepath" -import "core:strings" +import "core:strings" /* Parse any arguments into an annotated struct or exit if there was an error. @@ -38,7 +38,7 @@ parse_or_exit :: proc( error := parse(model, args, style, true, true, allocator, loc) if error != nil { - stderr := os.stream_from_handle(os.stderr) + stderr := os.to_stream(os.stderr) if len(args) == 0 { // No arguments entered, and there was an error; show the usage, @@ -65,19 +65,44 @@ Inputs: */ @(optimization_mode="favor_size") print_errors :: proc(data_type: typeid, error: Error, program: string, style: Parsing_Style = .Odin) { - stderr := os.stream_from_handle(os.stderr) - stdout := os.stream_from_handle(os.stdout) + stderr := os.to_stream(os.stderr) + stdout := os.to_stream(os.stdout) switch specific_error in error { case Parse_Error: fmt.wprintfln(stderr, "[%T.%v] %s", specific_error, specific_error.reason, specific_error.message) case Open_File_Error: - fmt.wprintfln(stderr, "[%T#%i] Unable to open file with perms 0o%o in mode 0x%x: %s", - specific_error, - specific_error.errno, - specific_error.perms, - specific_error.mode, - specific_error.filename) + if os.exists(specific_error.filename) { + flags: string + if specific_error.flags == {.Read} { + flags = "read-only" + } else if specific_error.flags == {.Write} { + flags = "write-only" + } else if specific_error.flags == {.Read, .Write} { + flags = "read/write" + } + + if flags != "" { + fmt.wprintfln(stderr, "[%T#%i] Unable to open %q with perms 0o%o as %s", + specific_error, + specific_error.errno, + specific_error.filename, + u16(transmute(u32)specific_error.perms), + flags) + } else { + fmt.wprintfln(stderr, "[%T#%i] Unable to open %q with perms 0o%o and flags %v", + specific_error, + specific_error.errno, + specific_error.filename, + u16(transmute(u32)specific_error.perms), + specific_error.flags) + } + } else { + fmt.wprintfln(stderr, "[%T#%i] Unable to open %q. File not found", + specific_error, + specific_error.errno, + specific_error.filename) + } case Validation_Error: fmt.wprintfln(stderr, "[%T] %s", specific_error, specific_error.message) case Help_Request: diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin index d45e6c796..c0d6d5289 100644 --- a/core/fmt/doc.odin +++ b/core/fmt/doc.odin @@ -1,5 +1,5 @@ /* -package fmt implements formatted I/O with procedures similar to C's printf and Python's format. +Formatted `I/O` with procedures similar to `C`'s printf and `Python`'s format. The format 'verbs' are derived from C's but simpler. Printing @@ -29,6 +29,8 @@ Integer: %x base 16, with lower-case letters for a-f %X base 16, with upper-case letters for A-F %U Unicode format: U+1234; same as "U+%04X" + %m number of bytes in the best unit of measurement, e.g. 123.45mib + %M number of bytes in the best unit of measurement, e.g. 123.45MiB Floating-point, complex numbers, and quaternions: %e scientific notation, e.g. -1.23456e+78 %E scientific notation, e.g. -1.23456E+78 @@ -38,8 +40,6 @@ Floating-point, complex numbers, and quaternions: %G synonym for %g %h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd) %H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD) - %m number of bytes in the best unit of measurement, e.g. 123.45mib - %M number of bytes in the best unit of measurement, e.g. 123.45MiB String and slice of bytes %s the uninterpreted bytes of the string or slice %q a double-quoted string safely escaped with Odin syntax diff --git a/core/fmt/example.odin b/core/fmt/example.odin index 6929e9be7..a700b238e 100644 --- a/core/fmt/example.odin +++ b/core/fmt/example.odin @@ -10,14 +10,14 @@ SomeType :: struct { My_Custom_Base_Type :: distinct u32 main :: proc() { - // Ensure the fmt._user_formatters map is initialized + // Ensure the fmt._user_formatters map is initialized fmt.set_user_formatters(new(map[typeid]fmt.User_Formatter)) // Register custom formatters for my favorite types err := fmt.register_user_formatter(type_info_of(SomeType).id, SomeType_Formatter) - assert(err == .None) + assert(err == .None) err = fmt.register_user_formatter(type_info_of(My_Custom_Base_Type).id, My_Custom_Base_Formatter) - assert(err == .None) + assert(err == .None) // Use the custom formatters. fmt.printfln("SomeType{{42}}: '%v'", SomeType{42}) @@ -53,5 +53,4 @@ My_Custom_Base_Formatter :: proc(fi: ^fmt.Info, arg: any, verb: rune) -> bool { return false } return true -} - +} \ No newline at end of file diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 9c07847dd..3ef5a13e6 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -42,6 +42,8 @@ Info_State :: struct { width: int, prec: int, indent: int, + + parent_struct: any, } @@ -693,7 +695,7 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : fi: Info end := len(fmt) unused_args: bit_set[0 ..< MAX_CHECKED_ARGS] - for i in 0 ..< len(args) { + for _, i in args { unused_args += {i} } @@ -816,7 +818,7 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any, flush := true, newline : } } - if unused_args != {} { + if unused_args != nil { // Use default options when formatting extra arguments. extra_fi := Info { writer = fi.writer, n = fi.n } @@ -1067,7 +1069,7 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d } } - buf: [256]byte + buf: [BUF_SIZE]byte start := 0 if fi.hash && !is_signed { @@ -1084,7 +1086,7 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d case 12: io.write_byte(fi.writer, '0', &fi.n) - io.write_byte(fi.writer, 'o', &fi.n) + io.write_byte(fi.writer, 'z', &fi.n) start = 2 case 16: @@ -1098,10 +1100,7 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d if fi.prec_set { prec = fi.prec if prec == 0 && u == 0 { - prev_zero := fi.zero - fi.zero = false fmt_write_padding(fi, fi.width) - fi.zero = prev_zero return } } else if fi.zero && fi.width_set { @@ -1122,7 +1121,7 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d flags: strconv.Int_Flags if fi.hash && !fi.zero && start == 0 { flags += {.Prefix} } if fi.plus { flags += {.Plus} } - s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags) + s := strconv.write_bits(buf[start:], u, base, is_signed, bit_size, digits, flags) prev_zero := fi.zero defer fi.zero = prev_zero fi.zero = false @@ -1169,7 +1168,7 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i case 12: io.write_byte(fi.writer, '0', &fi.n) - io.write_byte(fi.writer, 'o', &fi.n) + io.write_byte(fi.writer, 'z', &fi.n) start = 2 case 16: @@ -1183,10 +1182,7 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i if fi.prec_set { prec = fi.prec if prec == 0 && u == 0 { - prev_zero := fi.zero - fi.zero = false fmt_write_padding(fi, fi.width) - fi.zero = prev_zero return } } else if fi.zero && fi.width_set { @@ -1207,7 +1203,7 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i flags: strconv.Int_Flags if fi.hash && !fi.zero && start == 0 { flags += {.Prefix} } if fi.plus { flags += {.Plus} } - s := strconv.append_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags) + s := strconv.write_bits_128(buf[start:], u, base, is_signed, bit_size, digits, flags) if fi.hash && fi.zero && fi.indent == 0 { c: byte = 0 @@ -1229,8 +1225,8 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i _pad(fi, s) } // Units of measurements: -__MEMORY_LOWER := " b kib mib gib tib pib eib" -__MEMORY_UPPER := " B KiB MiB GiB TiB PiB EiB" +@(rodata) __MEMORY_LOWER := " b kib mib gib tib pib eib" +@(rodata) __MEMORY_UPPER := " B KiB MiB GiB TiB PiB EiB" // Formats an integer value as bytes with the best representation. // // Inputs: @@ -1272,7 +1268,7 @@ _fmt_memory :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, units: st } buf: [256]byte - str := strconv.append_float(buf[:], amt, 'f', prec, 64) + str := strconv.write_float(buf[:], amt, 'f', prec, 64) // Add the unit at the end. copy(buf[len(str):], units[off:off+unit_len]) @@ -1281,15 +1277,15 @@ _fmt_memory :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, units: st if !fi.plus { // Strip sign from "+" but not "+Inf". if str[0] == '+' && str[1] != 'I' { - str = str[1:] + str = str[1:] } } _pad(fi, str) } // Hex Values: -__DIGITS_LOWER := "0123456789abcdefx" -__DIGITS_UPPER := "0123456789ABCDEFX" +@(rodata) __DIGITS_LOWER := "0123456789abcdefx" +@(rodata) __DIGITS_UPPER := "0123456789ABCDEFX" // Formats a rune value according to the specified formatting verb. // // Inputs: @@ -1424,7 +1420,7 @@ _fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: b buf: [386]byte // Can return "NaN", "+Inf", "-Inf", "+", "-". - str := strconv.append_float(buf[:], v, float_fmt, prec, bit_size) + str := strconv.write_float(buf[:], v, float_fmt, prec, bit_size) if !fi.plus { // Strip sign from "+" but not "+Inf". @@ -1460,9 +1456,11 @@ fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) { prev_fi := fi^ defer fi^ = prev_fi fi.hash = false - fi.width = bit_size fi.zero = true fi.plus = false + // force the width to always be bit_size/4 to accurately represent the number + fi.width = bit_size/4 + fi.width_set = true u: u64 switch bit_size { @@ -1551,6 +1549,79 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) { fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) { fmt_string(fi, string(s), verb) } + +// Formats a string UTF-16 with a specific format. +// +// Inputs: +// - fi: Pointer to the Info struct containing format settings. +// - s: The string to format. +// - verb: The format specifier character (e.g. 's', 'v', 'q', 'x', 'X'). +// +fmt_string16 :: proc(fi: ^Info, s: string16, verb: rune) { + s, verb := s, verb + if ol, ok := fi.optional_len.?; ok { + s = s[:clamp(ol, 0, len(s))] + } + if !fi.in_bad && fi.record_level > 0 && verb == 'v' { + verb = 'q' + } + + switch verb { + case 's', 'v': + if fi.width_set { + if fi.width > len(s) { + if fi.minus { + io.write_string16(fi.writer, s, &fi.n) + } + + for _ in 0.. 0 && space { + io.write_byte(fi.writer, ' ', &fi.n) + } + char_set := __DIGITS_UPPER + if verb == 'x' { + char_set = __DIGITS_LOWER + } + _fmt_int(fi, u64(s[i]), 16, false, bit_size=16, digits=char_set) + } + + case: + fmt_bad_verb(fi, verb) + } +} +// Formats a C-style UTF-16 string with a specific format. +// +// Inputs: +// - fi: Pointer to the Info struct containing format settings. +// - s: The C-style string to format. +// - verb: The format specifier character (Ref fmt_string). +// +fmt_cstring16 :: proc(fi: ^Info, s: cstring16, verb: rune) { + fmt_string16(fi, string16(s), verb) +} + // Formats a raw pointer with a specific format. // // Inputs: @@ -1638,7 +1709,7 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { } type_info := type_info_of(v.id) - #partial switch e in type_info.variant { + #partial switch &e in type_info.variant { case: fmt_bad_verb(fi, verb) case runtime.Type_Info_Enum: switch verb { @@ -1678,7 +1749,7 @@ stored_enum_value_to_string :: proc(enum_type: ^runtime.Type_Info, ev: runtime.T et := runtime.type_info_base(enum_type) ev := ev ev += runtime.Type_Info_Enum_Value(offset) - #partial switch e in et.variant { + #partial switch &e in et.variant { case: return "", false case runtime.Type_Info_Enum: if reflect.is_string(e.base) { @@ -1715,7 +1786,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') { return false } t := runtime.type_info_base(ti) - #partial switch info in t.variant { + #partial switch &info in t.variant { case runtime.Type_Info_Integer: switch info.endianness { case .Platform: return false @@ -1729,7 +1800,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') { byte_swap :: bits.byte_swap type_info := type_info_of(v.id) - #partial switch info in type_info.variant { + #partial switch &info in type_info.variant { case runtime.Type_Info_Named: val := v val.id = info.base.id @@ -1864,7 +1935,7 @@ fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: in } fi.record_level += 1 defer fi.record_level -= 1 - + if fi.hash { io.write_byte(fi.writer, '\n', &fi.n) defer fmt_write_indent(fi) @@ -1998,6 +2069,235 @@ handle_tag :: proc(state: ^Info_State, data: rawptr, info: reflect.Type_Info_Str } return } + + +__handle_raw_union_tag :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) -> (ok: bool) { + ut := type_info_of(v.id) + + if !reflect.is_raw_union(ut) { + return false + } + + tag_name: string + for tag in info.tags[:info.field_count] { + rut := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "raw_union_tag") or_continue + head_tag, match, _ := strings.partition(string(rut), "=") + if match != "=" { + continue + } + if tag_name == "" { + tag_name = head_tag + } else if tag_name != head_tag { + return false + } + } + if tag_name == "" { + return false + } + + tag := reflect.struct_field_value_by_name(fi.state.parent_struct, tag_name, true) + if tag == nil { + // try the current type just in case the tag is also stored here + tag = reflect.struct_field_value_by_name(v, tag_name, false) + } + if tag == nil { + return false + } + + + tag_info := reflect.type_info_base(type_info_of(tag.id)) + #partial switch ti in tag_info.variant { + case reflect.Type_Info_Enum: + tag_string := reflect.enum_string(tag) + + for tag, index in info.tags[:info.field_count] { + rut_list := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "raw_union_tag") or_continue + + for rut in strings.split_iterator(&rut_list, ",") { + head_tag, match, tail_name := strings.partition(string(rut), "=") + if head_tag != tag_name || match != "=" { + continue + } + + // just ignore the `A.` prefix for `A.B` stuff entirely + if _, _, try_tail_name := strings.partition(string(rut), "."); try_tail_name != "" { + tail_name = try_tail_name + } + + if tail_name == tag_string { + io.write_string(fi.writer, "#raw_union(.", &fi.n) + io.write_string(fi.writer, tag_string, &fi.n) + io.write_string(fi.writer, ") ", &fi.n) + fmt_arg(fi, any{v.data, info.types[index].id}, the_verb) + return true + } + } + } + case reflect.Type_Info_Integer: + tag_value := reflect.as_i64(tag) or_break + + for tag, index in info.tags[:info.field_count] { + rut_list := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "raw_union_tag") or_continue + + for rut in strings.split_iterator(&rut_list, ",") { + head_tag, match, tail_name := strings.partition(string(rut), "=") + if head_tag != tag_name || match != "=" { + continue + } + + // just ignore the `A.` prefix for `A.B` stuff entirely + if _, _, try_tail_name := strings.partition(string(rut), "."); try_tail_name != "" { + tail_name = try_tail_name + } + + tail_value := strconv.parse_i64(tail_name) or_continue + + if tail_value == tag_value { + io.write_string(fi.writer, "#raw_union(.", &fi.n) + io.write_i64(fi.writer, tag_value, 10, &fi.n) + io.write_string(fi.writer, ") ", &fi.n) + fmt_arg(fi, any{v.data, info.types[index].id}, the_verb) + return true + } + } + } + + case reflect.Type_Info_Boolean: + tag_value := reflect.as_bool(tag) or_break + + for tag, index in info.tags[:info.field_count] { + rut_list := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "raw_union_tag") or_continue + + for rut in strings.split_iterator(&rut_list, ",") { + head_tag, match, tail_name := strings.partition(string(rut), "=") + if head_tag != tag_name || match != "=" { + continue + } + + // just ignore the `A.` prefix for `A.B` stuff entirely + if _, _, try_tail_name := strings.partition(string(rut), "."); try_tail_name != "" { + tail_name = try_tail_name + } + + tail_value := strconv.parse_bool(tail_name) or_continue + + if tail_value == tag_value { + io.write_string(fi.writer, "#raw_union(.", &fi.n) + io.write_string(fi.writer, "true" if tag_value else "false", &fi.n) + io.write_string(fi.writer, ") ", &fi.n) + fmt_arg(fi, any{v.data, info.types[index].id}, the_verb) + return true + } + } + } + } + + return false +} + +@(private) +fmt_soa_struct_internal :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string, hash: bool, indent: int) { + is_empty := info.field_count == 0 + + fi.indent += 1 + defer fi.indent -= 1 + + base_type_name: string + if v, ok := info.soa_base_type.variant.(runtime.Type_Info_Named); ok { + base_type_name = v.name + } + + actual_field_count := info.field_count + + n := uintptr(info.soa_len) + + if info.soa_kind == .Slice { + actual_field_count = info.field_count-1 // len + + n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^) + + } else if info.soa_kind == .Dynamic { + actual_field_count = info.field_count-3 // len, cap, allocator + + n = uintptr((^int)(uintptr(v.data) + info.offsets[actual_field_count])^) + } + + if hash && n > 0 { + io.write_byte(fi.writer, '\n', &fi.n) + } + + for index in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } + + field_count := -1 + + if !hash && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) } + + if hash { + fi.indent -= 1 + fmt_write_indent(fi) + fi.indent += 1 + } + io.write_string(fi.writer, base_type_name, &fi.n) + io.write_byte(fi.writer, '{', &fi.n) + if hash && !is_empty { io.write_byte(fi.writer, '\n', &fi.n) } + defer { + if hash && !is_empty { + fi.indent -= 1 + fmt_write_indent(fi) + fi.indent += 1 + } + io.write_byte(fi.writer, '}', &fi.n) + if hash { io.write_string(fi.writer, ",\n", &fi.n) } + } + fi.record_level += 1 + defer fi.record_level -= 1 + + for i in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } + if hash { + fmt_write_indent(fi) + } + + io.write_string(fi.writer, name, &fi.n) + io.write_string(fi.writer, " = ", &fi.n) + + if info.soa_kind == .Fixed { + t := info.types[i].variant.(runtime.Type_Info_Array).elem + t_size := uintptr(t.size) + if reflect.is_any(t) { + io.write_string(fi.writer, "any{}", &fi.n) + } else { + data := rawptr(uintptr(v.data) + info.offsets[i] + index*t_size) + fmt_arg(fi, any{data, t.id}, verb) + } + } else { + t := info.types[i].variant.(runtime.Type_Info_Multi_Pointer).elem + t_size := uintptr(t.size) + if reflect.is_any(t) { + io.write_string(fi.writer, "any{}", &fi.n) + } else { + field_ptr := (^^byte)(uintptr(v.data) + info.offsets[i])^ + data := rawptr(uintptr(field_ptr) + index*t_size) + fmt_arg(fi, any{data, t.id}, verb) + } + } + + if hash { io.write_string(fi.writer, ",\n", &fi.n) } + } + } + + if hash && n > 0 { + for _ in 0.. 0 { - io.write_byte(fi.writer, '\n', &fi.n) - } - - for index in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } - - field_count := -1 - - if !hash && field_count > 0 { io.write_string(fi.writer, ", ", &fi.n) } - - if hash { - fi.indent -= 1 - fmt_write_indent(fi) - fi.indent += 1 - } - io.write_string(fi.writer, base_type_name, &fi.n) - io.write_byte(fi.writer, '{', &fi.n) - if hash && !is_empty { io.write_byte(fi.writer, '\n', &fi.n) } - defer { - if hash && !is_empty { - fi.indent -= 1 - fmt_write_indent(fi) - fi.indent += 1 - } - io.write_byte(fi.writer, '}', &fi.n) - if hash { io.write_string(fi.writer, ",\n", &fi.n) } - } - fi.record_level += 1 - defer fi.record_level -= 1 - - for i in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } - if hash { - fmt_write_indent(fi) - } - - io.write_string(fi.writer, name, &fi.n) - io.write_string(fi.writer, " = ", &fi.n) - - if info.soa_kind == .Fixed { - t := info.types[i].variant.(runtime.Type_Info_Array).elem - t_size := uintptr(t.size) - if reflect.is_any(t) { - io.write_string(fi.writer, "any{}", &fi.n) - } else { - data := rawptr(uintptr(v.data) + info.offsets[i] + index*t_size) - fmt_arg(fi, any{data, t.id}, verb) - } - } else { - t := info.types[i].variant.(runtime.Type_Info_Multi_Pointer).elem - t_size := uintptr(t.size) - if reflect.is_any(t) { - io.write_string(fi.writer, "any{}", &fi.n) - } else { - field_ptr := (^^byte)(uintptr(v.data) + info.offsets[i])^ - data := rawptr(uintptr(field_ptr) + index*t_size) - fmt_arg(fi, any{data, t.id}, verb) - } - } - - if hash { io.write_string(fi.writer, ",\n", &fi.n) } - } - } - - if hash && n > 0 { - for _ in 0.. bool { + switch a in v { + case runtime.Source_Code_Location: + io.write_string(fi.writer, a.file_path, &fi.n) + + when ODIN_ERROR_POS_STYLE == .Default { + io.write_byte(fi.writer, '(', &fi.n) + io.write_int(fi.writer, int(a.line), 10, &fi.n) + if a.column != 0 { + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.column), 10, &fi.n) + } + io.write_byte(fi.writer, ')', &fi.n) + } else when ODIN_ERROR_POS_STYLE == .Unix { + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.line), 10, &fi.n) + if a.column != 0 { + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.column), 10, &fi.n) + } + io.write_byte(fi.writer, ':', &fi.n) + } else { + #panic("Unhandled ODIN_ERROR_POS_STYLE") + } + return true + + case time.Duration: + ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) { + v := v + w := len(buf) + print := false + for _ in 0.. int { + v := v + w := len(buf) + if v == 0 { + w -= 1 + buf[w] = '0' + } else { + for v > 0 { + w -= 1 + buf[w] = byte(v%10) + '0' + v /= 10 + } + } + return w + } + + buf: [32]byte + w := len(buf) + u := u64(a) + neg := a < 0 + if neg { + u = -u + } + + if u < u64(time.Second) { + prec: int + w -= 1 + buf[w] = 's' + w -= 1 + switch { + case u == 0: + io.write_string(fi.writer, "0s", &fi.n) + return true + case u < u64(time.Microsecond): + prec = 0 + buf[w] = 'n' + case u < u64(time.Millisecond): + prec = 3 + // U+00B5 'µ' micro sign == 0xC2 0xB5 + w -= 1 // Need room for two bytes + copy(buf[w:], "µ") + case: + prec = 6 + buf[w] = 'm' + } + if fi.space { + w -= 1 + buf[w] = ' ' + } + w, u = ffrac(buf[:w], u, prec) + w = fint(buf[:w], u) + } else { + w -= 1 + buf[w] = 's' + if fi.space { + w -= 1 + buf[w] = ' ' + } + w, u = ffrac(buf[:w], u, 9) + w = fint(buf[:w], u%60) + u /= 60 + if u > 0 { + w -= 1 + buf[w] = 'm' + w = fint(buf[:w], u%60) + u /= 60 + if u > 0 { + w -= 1 + buf[w] = 'h' + w = fint(buf[:w], u) + } + } + } + + if neg { + w -= 1 + buf[w] = '-' + } + io.write_string(fi.writer, string(buf[w:]), &fi.n) + return true + + case time.Time: + write_padded_number :: proc(fi: ^Info, i: i64, width: int) { + n := width-1 + for x := i; x >= 10; x /= 10 { + n -= 1 + } + for _ in 0..= 10; x /= 10 { - n -= 1 - } - for _ in 0.. (nw: int, nv: u64) { - v := v - w := len(buf) - print := false - for _ in 0.. int { - v := v - w := len(buf) - if v == 0 { - w -= 1 - buf[w] = '0' - } else { - for v > 0 { - w -= 1 - buf[w] = byte(v%10) + '0' - v /= 10 - } - } - return w - } - - buf: [32]byte - w := len(buf) - u := u64(a) - neg := a < 0 - if neg { - u = -u - } - - if u < u64(time.Second) { - prec: int - w -= 1 - buf[w] = 's' - w -= 1 - switch { - case u == 0: - io.write_string(fi.writer, "0s", &fi.n) - return - case u < u64(time.Microsecond): - prec = 0 - buf[w] = 'n' - case u < u64(time.Millisecond): - prec = 3 - // U+00B5 'µ' micro sign == 0xC2 0xB5 - w -= 1 // Need room for two bytes - copy(buf[w:], "µ") - case: - prec = 6 - buf[w] = 'm' - } - w, u = ffrac(buf[:w], u, prec) - w = fint(buf[:w], u) - } else { - w -= 1 - buf[w] = 's' - w, u = ffrac(buf[:w], u, 9) - w = fint(buf[:w], u%60) - u /= 60 - if u > 0 { - w -= 1 - buf[w] = 'm' - w = fint(buf[:w], u%60) - u /= 60 - if u > 0 { - w -= 1 - buf[w] = 'h' - w = fint(buf[:w], u) - } - } - } - - if neg { - w -= 1 - buf[w] = '-' - } - io.write_string(fi.writer, string(buf[w:]), &fi.n) - return - - case time.Time: - t := a - y, mon, d := time.date(t) - h, min, s := time.clock(t) - ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9 - write_padded_number(fi, i64(y), 4) - io.write_byte(fi.writer, '-', &fi.n) - write_padded_number(fi, i64(mon), 2) - io.write_byte(fi.writer, '-', &fi.n) - write_padded_number(fi, i64(d), 2) - io.write_byte(fi.writer, ' ', &fi.n) - - write_padded_number(fi, i64(h), 2) - io.write_byte(fi.writer, ':', &fi.n) - write_padded_number(fi, i64(min), 2) - io.write_byte(fi.writer, ':', &fi.n) - write_padded_number(fi, i64(s), 2) - io.write_byte(fi.writer, '.', &fi.n) - write_padded_number(fi, (ns), 9) - io.write_string(fi.writer, " +0000 UTC", &fi.n) - return - } + if verb != 'w' && fmt_named_buitlin_custom_formatters(fi, v, verb, info) { + return } - #partial switch b in info.base.variant { + #partial switch &b in info.base.variant { case runtime.Type_Info_Struct: fmt_struct(fi, v, verb, b, info.name) case runtime.Type_Info_Bit_Field: @@ -2692,6 +2921,234 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit } +@(private) +fmt_pointer_from_value :: proc(fi: ^Info, v: any, info: runtime.Type_Info_Pointer, verb: rune) { + if v.id == typeid_of(^runtime.Type_Info) { + reflect.write_type(fi.writer, (^^runtime.Type_Info)(v.data)^, &fi.n) + } else { + ptr := (^rawptr)(v.data)^ + if verb != 'p' && info.elem != nil { + a := any{ptr, info.elem.id} + + elem := runtime.type_info_base(info.elem) + if elem != nil { + #partial switch &e in elem.variant { + case runtime.Type_Info_Array, + runtime.Type_Info_Slice, + runtime.Type_Info_Dynamic_Array, + runtime.Type_Info_Map: + if ptr == nil { + io.write_string(fi.writer, "", &fi.n) + return + } + if fi.indirection_level < 1 { + fi.indirection_level += 1 + defer fi.indirection_level -= 1 + io.write_byte(fi.writer, '&') + fmt_value(fi, a, verb) + return + } + + case runtime.Type_Info_Struct, + runtime.Type_Info_Union, + runtime.Type_Info_Bit_Field: + if ptr == nil { + io.write_string(fi.writer, "", &fi.n) + return + } + if fi.indirection_level < 1 { + fi.indirection_level += 1 + defer fi.indirection_level -= 1 + io.write_byte(fi.writer, '&', &fi.n) + fmt_value(fi, a, verb) + return + } + } + } + } + fmt_pointer(fi, ptr, verb) + } +} + +@(private) +fmt_multi_pointer :: proc(fi: ^Info, v: any, info: runtime.Type_Info_Multi_Pointer, verb: rune) { + ptr := (^rawptr)(v.data)^ + if ptr == nil { + io.write_string(fi.writer, "", &fi.n) + return + } + if verb != 'p' && info.elem != nil { + a := any{ptr, info.elem.id} + + elem := runtime.type_info_base(info.elem) + if elem != nil { + if n, ok := fi.optional_len.?; ok { + fi.optional_len = nil + fmt_array(fi, ptr, n, elem.size, elem, verb) + return + } else if fi.use_nul_termination { + fi.use_nul_termination = false + fmt_array_nul_terminated(fi, ptr, -1, elem.size, elem, verb) + return + } + + #partial switch &e in elem.variant { + case runtime.Type_Info_Integer: + switch verb { + case 's', 'q': + switch elem.id { + case u8: + fmt_cstring(fi, cstring(ptr), verb) + return + case u16, u32, rune: + n := search_nul_termination(ptr, elem.size, -1) + fmt_array(fi, ptr, n, elem.size, elem, verb) + return + } + } + + case runtime.Type_Info_Array, + runtime.Type_Info_Slice, + runtime.Type_Info_Dynamic_Array, + runtime.Type_Info_Map: + if fi.indirection_level < 1 { + fi.indirection_level += 1 + defer fi.indirection_level -= 1 + io.write_byte(fi.writer, '&', &fi.n) + fmt_value(fi, a, verb) + return + } + + case runtime.Type_Info_Struct, + runtime.Type_Info_Union: + if fi.indirection_level < 1 { + fi.indirection_level += 1 + defer fi.indirection_level -= 1 + io.write_byte(fi.writer, '&', &fi.n) + fmt_value(fi, a, verb) + return + } + } + } + } + fmt_pointer(fi, ptr, verb) +} + +fmt_enumerated_array :: proc(fi: ^Info, v: any, info: runtime.Type_Info_Enumerated_Array, verb: rune) { + fi.record_level += 1 + defer fi.record_level -= 1 + + if fi.hash { + io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) + io.write_byte(fi.writer, '\n', &fi.n) + defer { + fmt_write_indent(fi) + io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) + } + indent := fi.indent + fi.indent += 1 + defer fi.indent = indent + + for i in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } + + idx, ok := stored_enum_value_to_string(info.index, info.min_value, i) + if ok { + io.write_byte(fi.writer, '.', &fi.n) + io.write_string(fi.writer, idx, &fi.n) + } else { + io.write_i64(fi.writer, i64(info.min_value)+i64(i), 10, &fi.n) + } + io.write_string(fi.writer, " = ", &fi.n) + + data := uintptr(v.data) + uintptr(i*info.elem_size) + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) + } + } +} + +fmt_map :: proc(fi: ^Info, v: any, info: runtime.Type_Info_Map, verb: rune) { + switch verb { + case: + fmt_bad_verb(fi, verb) + case 'v', 'w': + if verb == 'v' { + io.write_string(fi.writer, "map", &fi.n) + } + io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) + defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) + + + hash := fi.hash; defer fi.hash = hash + indent := fi.indent; defer fi.indent -= 1 + do_trailing_comma := hash + + fi.indent += 1 + if hash { + io.write_byte(fi.writer, '\n', &fi.n) + } + defer { + if hash { + for _ in 0.. 0 { io.write_string(fi.writer, ", ") } + if hash { + fmt_write_indent(fi) + } + j += 1 + + key := runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index) + value := runtime.map_cell_index_dynamic(vs, info.map_info.vs, bucket_index) + + fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, verb) + if info.value.size > 0 { + if hash { + io.write_string(fi.writer, " = ", &fi.n) + } else { + io.write_string(fi.writer, "=", &fi.n) + } + fmt_arg(fi, any{rawptr(value), info.value.id}, verb) + } + + if do_trailing_comma { io.write_string(fi.writer, ",\n", &fi.n) } + } + } + } + +} // Formats a value based on its type and formatting verb // @@ -2721,185 +3178,36 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fi.ignore_user_formatters = false type_info := type_info_of(v.id) - switch info in type_info.variant { - case runtime.Type_Info_Any: // Ignore - case runtime.Type_Info_Parameters: // Ignore + switch &info in type_info.variant { + case runtime.Type_Info_Any: + // Ignore + case runtime.Type_Info_Parameters: + // Ignore case runtime.Type_Info_Named: fmt_named(fi, v, verb, info) - case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb) - case runtime.Type_Info_Integer: fmt_arg(fi, v, verb) - case runtime.Type_Info_Rune: fmt_arg(fi, v, verb) - case runtime.Type_Info_Float: fmt_arg(fi, v, verb) - case runtime.Type_Info_Complex: fmt_arg(fi, v, verb) - case runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb) - case runtime.Type_Info_String: fmt_arg(fi, v, verb) + case runtime.Type_Info_Boolean, + runtime.Type_Info_Integer, + runtime.Type_Info_Rune, + runtime.Type_Info_Float, + runtime.Type_Info_Complex, + runtime.Type_Info_Quaternion, + runtime.Type_Info_String: + fmt_arg(fi, v, verb) case runtime.Type_Info_Pointer: - if v.id == typeid_of(^runtime.Type_Info) { - reflect.write_type(fi.writer, (^^runtime.Type_Info)(v.data)^, &fi.n) - } else { - ptr := (^rawptr)(v.data)^ - if verb != 'p' && info.elem != nil { - a := any{ptr, info.elem.id} - - elem := runtime.type_info_base(info.elem) - if elem != nil { - #partial switch e in elem.variant { - case runtime.Type_Info_Array, - runtime.Type_Info_Slice, - runtime.Type_Info_Dynamic_Array, - runtime.Type_Info_Map: - if ptr == nil { - io.write_string(fi.writer, "", &fi.n) - return - } - if fi.indirection_level < 1 { - fi.indirection_level += 1 - defer fi.indirection_level -= 1 - io.write_byte(fi.writer, '&') - fmt_value(fi, a, verb) - return - } - - case runtime.Type_Info_Struct, - runtime.Type_Info_Union, - runtime.Type_Info_Bit_Field: - if ptr == nil { - io.write_string(fi.writer, "", &fi.n) - return - } - if fi.indirection_level < 1 { - fi.indirection_level += 1 - defer fi.indirection_level -= 1 - io.write_byte(fi.writer, '&', &fi.n) - fmt_value(fi, a, verb) - return - } - } - } - } - fmt_pointer(fi, ptr, verb) - } + fmt_pointer_from_value(fi, v, info, verb) case runtime.Type_Info_Soa_Pointer: ptr := (^runtime.Raw_Soa_Pointer)(v.data)^ fmt_soa_pointer(fi, ptr, verb) case runtime.Type_Info_Multi_Pointer: - ptr := (^rawptr)(v.data)^ - if ptr == nil { - io.write_string(fi.writer, "", &fi.n) - return - } - if verb != 'p' && info.elem != nil { - a := any{ptr, info.elem.id} - - elem := runtime.type_info_base(info.elem) - if elem != nil { - if n, ok := fi.optional_len.?; ok { - fi.optional_len = nil - fmt_array(fi, ptr, n, elem.size, elem, verb) - return - } else if fi.use_nul_termination { - fi.use_nul_termination = false - fmt_array_nul_terminated(fi, ptr, -1, elem.size, elem, verb) - return - } - - #partial switch e in elem.variant { - case runtime.Type_Info_Integer: - switch verb { - case 's', 'q': - switch elem.id { - case u8: - fmt_cstring(fi, cstring(ptr), verb) - return - case u16, u32, rune: - n := search_nul_termination(ptr, elem.size, -1) - fmt_array(fi, ptr, n, elem.size, elem, verb) - return - } - } - - case runtime.Type_Info_Array, - runtime.Type_Info_Slice, - runtime.Type_Info_Dynamic_Array, - runtime.Type_Info_Map: - if fi.indirection_level < 1 { - fi.indirection_level += 1 - defer fi.indirection_level -= 1 - io.write_byte(fi.writer, '&', &fi.n) - fmt_value(fi, a, verb) - return - } - - case runtime.Type_Info_Struct, - runtime.Type_Info_Union: - if fi.indirection_level < 1 { - fi.indirection_level += 1 - defer fi.indirection_level -= 1 - io.write_byte(fi.writer, '&', &fi.n) - fmt_value(fi, a, verb) - return - } - } - } - } - fmt_pointer(fi, ptr, verb) + fmt_multi_pointer(fi, v, info, verb) case runtime.Type_Info_Enumerated_Array: - fi.record_level += 1 - defer fi.record_level -= 1 - - if fi.hash { - io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) - io.write_byte(fi.writer, '\n', &fi.n) - defer { - fmt_write_indent(fi) - io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) - } - indent := fi.indent - fi.indent += 1 - defer fi.indent = indent - - for i in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } - - idx, ok := stored_enum_value_to_string(info.index, info.min_value, i) - if ok { - io.write_byte(fi.writer, '.', &fi.n) - io.write_string(fi.writer, idx, &fi.n) - } else { - io.write_i64(fi.writer, i64(info.min_value)+i64(i), 10, &fi.n) - } - io.write_string(fi.writer, " = ", &fi.n) - - data := uintptr(v.data) + uintptr(i*info.elem_size) - fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) - } - } + fmt_enumerated_array(fi, v, info, verb) case runtime.Type_Info_Array: n := info.count @@ -2942,6 +3250,21 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } fmt_array(fi, ptr, n, info.elem_size, info.elem, verb) + + case runtime.Type_Info_Fixed_Capacity_Dynamic_Array: + n := (^int)(uintptr(v.data) + info.len_offset)^ + + ptr := v.data // data is stored at the start + if ol, ok := fi.optional_len.?; ok { + fi.optional_len = nil + n = min(n, ol) + } else if fi.use_nul_termination { + fi.use_nul_termination = false + fmt_array_nul_terminated(fi, ptr, n, info.elem_size, info.elem, verb) + return + } + fmt_array(fi, ptr, n, info.elem_size, info.elem, verb) + case runtime.Type_Info_Simd_Vector: io.write_byte(fi.writer, '<', &fi.n) defer io.write_byte(fi.writer, '>', &fi.n) @@ -2954,63 +3277,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { case runtime.Type_Info_Map: - switch verb { - case: - fmt_bad_verb(fi, verb) - case 'v', 'w': - if verb == 'v' { - io.write_string(fi.writer, "map", &fi.n) - } - io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) - defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) - - - hash := fi.hash; defer fi.hash = hash - indent := fi.indent; defer fi.indent -= 1 - do_trailing_comma := hash - - fi.indent += 1 - if hash { - io.write_byte(fi.writer, '\n', &fi.n) - } - defer { - if hash { - for _ in 0.. 0 { io.write_string(fi.writer, ", ") } - if hash { - fmt_write_indent(fi) - } - j += 1 - - key := runtime.map_cell_index_dynamic(ks, info.map_info.ks, bucket_index) - value := runtime.map_cell_index_dynamic(vs, info.map_info.vs, bucket_index) - - fmt_arg(&Info{writer = fi.writer}, any{rawptr(key), info.key.id}, verb) - if hash { - io.write_string(fi.writer, " = ", &fi.n) - } else { - io.write_string(fi.writer, "=", &fi.n) - } - fmt_arg(fi, any{rawptr(value), info.value.id}, verb) - - if do_trailing_comma { io.write_string(fi.writer, ",\n", &fi.n) } - } - } - } + fmt_map(fi, v, info, verb) case runtime.Type_Info_Struct: fmt_struct(fi, v, verb, info, "") @@ -3165,7 +3432,7 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) { base_arg := arg base_arg.id = runtime.typeid_base(base_arg.id) - switch a in base_arg { + switch &a in base_arg { case bool: fmt_bool(fi, a, verb) case b8: fmt_bool(fi, bool(a), verb) case b16: fmt_bool(fi, bool(a), verb) @@ -3210,6 +3477,9 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) { case string: fmt_string(fi, a, verb) case cstring: fmt_cstring(fi, a, verb) + case string16: fmt_string16(fi, a, verb) + case cstring16: fmt_cstring16(fi, a, verb) + case typeid: reflect.write_typeid(fi.writer, a, &fi.n) case i16le: fmt_int(fi, u64(a), true, 16, verb) diff --git a/core/fmt/fmt_js.odin b/core/fmt/fmt_js.odin index ce90fbfe7..ccab15220 100644 --- a/core/fmt/fmt_js.odin +++ b/core/fmt/fmt_js.odin @@ -1,10 +1,6 @@ #+build js package fmt -import "core:bufio" -import "core:io" -import "core:os" - foreign import "odin_env" @(private="file") @@ -12,90 +8,77 @@ foreign odin_env { write :: proc "contextless" (fd: u32, p: []byte) --- } -@(private="file") -write_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { - if mode == .Write { - fd := u32(uintptr(stream_data)) - write(fd, p) - return i64(len(p)), nil - } - return 0, .Empty -} +stdout :: u32(1) +stderr :: u32(2) @(private="file") -stdout := io.Writer{ - procedure = write_stream_proc, - data = rawptr(uintptr(1)), -} -@(private="file") -stderr := io.Writer{ - procedure = write_stream_proc, - data = rawptr(uintptr(2)), -} +BUF_SIZE :: 1024 @(private="file") -fd_to_writer :: proc(fd: os.Handle, loc := #caller_location) -> io.Writer { - switch fd { - case 1: return stdout - case 2: return stderr - case: panic("`fmt.fprint` variant called with invalid file descriptor for JS, only 1 (stdout) and 2 (stderr) are supported", loc) +// TODO: Find a way to grow this if necessary +buf: [BUF_SIZE]byte + +@(private="file") +get_fd :: proc(f: any, loc := #caller_location) -> (fd: u32) { + if _fd, _ok := f.(u32); _ok { + fd = _fd } + if fd != 1 && fd != 2 { + panic("`fmt.fprint` variant called with invalid file descriptor for JS, only 1 (stdout) and 2 (stderr) are supported", loc) + } + return fd } // fprint formats using the default print settings and writes to fd -fprint :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true, loc := #caller_location) -> int { - buf: [1024]byte - b: bufio.Writer - defer bufio.writer_flush(&b) - - bufio.writer_init_with_buf(&b, fd_to_writer(fd, loc), buf[:]) - w := bufio.writer_to_writer(&b) - return wprint(w, ..args, sep=sep, flush=flush) +// flush is ignored +fprint :: proc(f: any, args: ..any, sep := " ", flush := true, loc := #caller_location) -> (n: int) { + fd := get_fd(f) + s := bprint(buf[:], ..args, sep=sep) + n = len(s) + write(fd, transmute([]byte)s) + return n } -// fprintln formats using the default print settings and writes to fd -fprintln :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true, loc := #caller_location) -> int { - buf: [1024]byte - b: bufio.Writer - defer bufio.writer_flush(&b) - - bufio.writer_init_with_buf(&b, fd_to_writer(fd, loc), buf[:]) - - w := bufio.writer_to_writer(&b) - return wprintln(w, ..args, sep=sep, flush=flush) +// fprintln formats using the default print settings and writes to fd, followed by a newline +// flush is ignored +fprintln :: proc(f: any, args: ..any, sep := " ", flush := true, loc := #caller_location) -> (n: int) { + fd := get_fd(f) + s := bprintln(buf[:], ..args, sep=sep) + n = len(s) + write(fd, transmute([]byte)s) + return n } // fprintf formats according to the specified format string and writes to fd -fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true, newline := false, loc := #caller_location) -> int { - buf: [1024]byte - b: bufio.Writer - defer bufio.writer_flush(&b) - - bufio.writer_init_with_buf(&b, fd_to_writer(fd, loc), buf[:]) - - w := bufio.writer_to_writer(&b) - return wprintf(w, fmt, ..args, flush=flush, newline=newline) +// flush is ignored +fprintf :: proc(f: any, fmt: string, args: ..any, flush := true, newline := false, loc := #caller_location) -> (n: int) { + fd := get_fd(f) + s := bprintf(buf[:], fmt, ..args, newline=newline) + n = len(s) + write(fd, transmute([]byte)s) + return n } // fprintfln formats according to the specified format string and writes to fd, followed by a newline. -fprintfln :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true, loc := #caller_location) -> int { - return fprintf(fd, fmt, ..args, flush=flush, newline=true, loc=loc) +// flush is ignored +fprintfln :: proc(f: any, fmt: string, args: ..any, flush := true, loc := #caller_location) -> int { + return fprintf(f, fmt, ..args, flush=flush, newline=true, loc=loc) } // print formats using the default print settings and writes to stdout -print :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stdout, args=args, sep=sep, flush=flush) } +print :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(stdout, ..args, sep=sep, flush=flush) } // println formats using the default print settings and writes to stdout -println :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stdout, args=args, sep=sep, flush=flush) } +println :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(stdout, ..args, sep=sep, flush=flush) } // printf formats according to the specififed format string and writes to stdout -printf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush) } +printf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(stdout, fmt, ..args, flush=flush) } // printfln formats according to the specified format string and writes to stdout, followed by a newline. -printfln :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush, newline=true) } +printfln :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(stdout, fmt, ..args, flush=flush, newline=true) } // eprint formats using the default print settings and writes to stderr -eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stderr, args=args, sep=sep, flush=flush) } +eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(stderr, ..args, sep=sep, flush=flush) } // eprintln formats using the default print settings and writes to stderr -eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stderr, args=args, sep=sep, flush=flush) } +eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(stderr, ..args, sep=sep, flush=flush) } // eprintf formats according to the specififed format string and writes to stderr -eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stderr, fmt, ..args, flush=flush) } +eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(stderr, fmt, ..args, flush=flush) } // eprintfln formats according to the specified format string and writes to stderr, followed by a newline. -eprintfln :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush, newline=true) } +eprintfln :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(stderr, fmt, ..args, flush=flush, newline=true) } \ No newline at end of file diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index a481061f1..0fd97f143 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -8,59 +8,56 @@ import "core:os" import "core:io" import "core:bufio" +// NOTE(Jeroen): The other option is to deprecate `fprint*` and make it an alias for `wprint*`, using File.stream directly. + // fprint formats using the default print settings and writes to fd -fprint :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int { +fprint :: proc(f: ^os.File, args: ..any, sep := " ", flush := true) -> int { buf: [1024]byte b: bufio.Writer - defer bufio.writer_flush(&b) - bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) + bufio.writer_init_with_buf(&b, os.to_stream(f), buf[:]) w := bufio.writer_to_writer(&b) return wprint(w, ..args, sep=sep, flush=flush) } // fprintln formats using the default print settings and writes to fd -fprintln :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int { +fprintln :: proc(f: ^os.File, args: ..any, sep := " ", flush := true) -> int { buf: [1024]byte b: bufio.Writer - defer bufio.writer_flush(&b) - bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) + bufio.writer_init_with_buf(&b, os.to_stream(f), buf[:]) w := bufio.writer_to_writer(&b) return wprintln(w, ..args, sep=sep, flush=flush) } // fprintf formats according to the specified format string and writes to fd -fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true, newline := false) -> int { +fprintf :: proc(f: ^os.File, fmt: string, args: ..any, flush := true, newline := false) -> int { buf: [1024]byte b: bufio.Writer - defer bufio.writer_flush(&b) - bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) + bufio.writer_init_with_buf(&b, os.to_stream(f), buf[:]) w := bufio.writer_to_writer(&b) return wprintf(w, fmt, ..args, flush=flush, newline=newline) } // fprintfln formats according to the specified format string and writes to fd, followed by a newline. -fprintfln :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int { - return fprintf(fd, fmt, ..args, flush=flush, newline=true) +fprintfln :: proc(f: ^os.File, fmt: string, args: ..any, flush := true) -> int { + return fprintf(f, fmt, ..args, flush=flush, newline=true) } -fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info, flush := true) -> (n: int, err: io.Error) { +fprint_type :: proc(f: ^os.File, info: ^runtime.Type_Info, flush := true) -> (n: int, err: io.Error) { buf: [1024]byte b: bufio.Writer - defer bufio.writer_flush(&b) - bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) + bufio.writer_init_with_buf(&b, os.to_stream(f), buf[:]) w := bufio.writer_to_writer(&b) return wprint_type(w, info, flush=flush) } -fprint_typeid :: proc(fd: os.Handle, id: typeid, flush := true) -> (n: int, err: io.Error) { +fprint_typeid :: proc(f: ^os.File, id: typeid, flush := true) -> (n: int, err: io.Error) { buf: [1024]byte b: bufio.Writer - defer bufio.writer_flush(&b) - bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:]) + bufio.writer_init_with_buf(&b, os.to_stream(f), buf[:]) w := bufio.writer_to_writer(&b) return wprint_typeid(w, id, flush=flush) diff --git a/core/hash/crc.odin b/core/hash/crc.odin index 68b8f5369..1182ba92e 100644 --- a/core/hash/crc.odin +++ b/core/hash/crc.odin @@ -1,10 +1,27 @@ package hash +/* + Compute CRC-16 in the manner of CCITT (ITU-T V.41), using the 0x1021 polynomial. + Generator polynomial: x^16 + x^12 + x^5 + 1 + + Used in the UDF (DVD *.iso) disk format's Volume Descriptor Tag, + and was more historically the ITU-T V.41 CRC-16 used in the XModem protocol, + which uses 0xffff as the initial value. +*/ +@(optimization_mode="favor_size") +crc16_ccitt_0x1021 :: proc "contextless" (data: []u8, seed := u16(0)) -> (result: u16) #no_bounds_check { + result = seed + #no_bounds_check for b in data { + result = result << 8 ~ _ccitt_0x1021_table[(result >> 8) ~ u16(b)] + } + return result +} + @(optimization_mode="favor_size") crc64_ecma_182 :: proc "contextless" (data: []byte, seed := u64(0)) -> (result: u64) #no_bounds_check { result = seed #no_bounds_check for b in data { - result = result<<8 ~ _crc64_table_ecma_182[((result>>56) ~ u64(b)) & 0xff] + result = result << 8 ~ _crc64_table_ecma_182[((result>>56) ~ u64(b)) & 0xff] } return result } @@ -49,9 +66,7 @@ crc64_xz :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_ return u64(~result) } -/* - Generator polynomial: x^64 + x^4 + x^3 + x + 1 -*/ +// Generator polynomial: x^64 + x^4 + x^3 + x + 1 @(optimization_mode="favor_size") crc64_iso_3306 :: proc "contextless" (data: []byte, seed := u64(0)) -> u64 #no_bounds_check { @@ -75,7 +90,8 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u return ~result } -@private _crc64_table_ecma_182 := [256]u64{ +@(private, rodata) +_crc64_table_ecma_182 := [256]u64{ 0x0000000000000000, 0x42f0e1eba9ea3693, 0x85e1c3d753d46d26, 0xc711223cfa3e5bb5, 0x493366450e42ecdf, 0x0bc387aea7a8da4c, 0xccd2a5925d9681f9, 0x8e224479f47cb76a, 0x9266cc8a1c85d9be, 0xd0962d61b56fef2d, 0x17870f5d4f51b498, 0x5577eeb6e6bb820b, @@ -142,7 +158,8 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u 0x5dedc41a34bbeeb2, 0x1f1d25f19d51d821, 0xd80c07cd676f8394, 0x9afce626ce85b507, } -@private _crc64_table_xz := [8][256]u64le{ +@(private, rodata) +_crc64_table_xz := [8][256]u64le{ { 0x0000000000000000, 0xb32e4cbe03a75f6f, 0xf4843657a840a05b, 0x47aa7ae9abe7ff34, 0x7bd0c384ff8f5e33, 0xc8fe8f3afc28015c, 0x8f54f5d357cffe68, 0x3c7ab96d5468a107, @@ -673,7 +690,8 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u }, } -@private _crc64_table_iso_3306 := [256]u16{ +@(private, rodata) +_crc64_table_iso_3306 := [256]u16{ 0x0000, 0x01b0, 0x0360, 0x02d0, 0x06c0, 0x0770, 0x05a0, 0x0410, 0x0d80, 0x0c30, 0x0ee0, 0x0f50, @@ -739,3 +757,39 @@ crc64_iso_3306_inverse :: proc "contextless" (data: []byte, seed := u64(0)) -> u 0x9480, 0x9530, 0x97e0, 0x9650, 0x9240, 0x93f0, 0x9120, 0x9090, } + +@(private, rodata) +_ccitt_0x1021_table := [256]u16{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +} diff --git a/core/hash/crc32.odin b/core/hash/crc32.odin index a7f68207e..777209bed 100644 --- a/core/hash/crc32.odin +++ b/core/hash/crc32.odin @@ -1,7 +1,5 @@ package hash -import "base:intrinsics" - @(optimization_mode="favor_size") crc32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 #no_bounds_check { crc := ~seed @@ -317,85 +315,4 @@ crc32_table := [8][256]u32{ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6, }, -} - - - -/* -@(optimization_mode="speed") -crc32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { - result := ~u32(seed); - #no_bounds_check for b in data { - result = result>>8 ~ _crc32_table[(result ~ u32(b)) & 0xff]; - } - return ~result; -} - - -@private _crc32_table := [256]u32{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, -}; -*/ +} \ No newline at end of file diff --git a/core/hash/doc.odin b/core/hash/doc.odin new file mode 100644 index 000000000..d7531a4c2 --- /dev/null +++ b/core/hash/doc.odin @@ -0,0 +1,2 @@ +// `crc32`, `crc64`, `adler32`, `djb`, `fnv`, `jenkins`, `murmur` and other hashes. +package hash \ No newline at end of file diff --git a/core/hash/hash.odin b/core/hash/hash.odin index 45f524d8a..b495fd30d 100644 --- a/core/hash/hash.odin +++ b/core/hash/hash.odin @@ -1,7 +1,6 @@ package hash import "core:mem" -import "base:intrinsics" @(optimization_mode="favor_size") adler32 :: proc "contextless" (data: []byte, seed := u32(1)) -> u32 #no_bounds_check { @@ -57,14 +56,14 @@ djb2 :: proc "contextless" (data: []byte, seed := u32(5381)) -> u32 { djbx33a :: proc "contextless" (data: []byte, seed := u32(5381)) -> (result: [16]byte) #no_bounds_check { state := [4]u32{seed, seed, seed, seed} - + s: u32 = 0 for p in data { state[s] = (state[s] << 5) + state[s] + u32(p) // hash * 33 + u32(b) s = (s + 1) & 3 } - - + + (^u32le)(&result[0])^ = u32le(state[0]) (^u32le)(&result[4])^ = u32le(state[1]) (^u32le)(&result[8])^ = u32le(state[2]) @@ -127,7 +126,7 @@ jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { } @(optimization_mode="favor_size") -murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { +murmur32 :: proc "contextless" (data: []byte, seed := u32(0x9747b28c)) -> u32 { c1_32: u32 : 0xcc9e2d51 c2_32: u32 : 0x1b873593 @@ -160,7 +159,7 @@ murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { case 1: k1 ~= u32(tail[0]) k1 *= c1_32 - k1 = (k1 << 15) | (k1 >> 17) + k1 = (k1 << 15) | (k1 >> 17) k1 *= c2_32 h1 ~= k1 } diff --git a/core/hash/xxhash/common.odin b/core/hash/xxhash/common.odin index adfc1bac2..e0f00a3db 100644 --- a/core/hash/xxhash/common.odin +++ b/core/hash/xxhash/common.odin @@ -1,15 +1,17 @@ +// Yann Collet's `xxhash`. +// +// [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]] +package xxhash + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license, based on the original C code. + Made available under Odin's license, based on the original C code. List of contributors: Jeroen van Rijn: Initial implementation. */ -// An implementation of Yann Collet's [[ xxhash Fast Hash Algorithm; https://cyan4973.github.io/xxHash/ ]]. -package xxhash - import "base:intrinsics" import "base:runtime" @@ -101,3 +103,35 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned) return u64(b) } } + +XXH64_read64_simd :: #force_inline proc(buf: []$E, $W: uint, alignment := Alignment.Unaligned) -> (res: #simd[W]u64) { + if alignment == .Aligned { + res = (^#simd[W]u64)(raw_data(buf))^ + } else { + res = intrinsics.unaligned_load((^#simd[W]u64)(raw_data(buf))) + } + + when ODIN_ENDIAN == .Big { + bytes := transmute(#simd[W*8]u8)res + bytes = intrinsics.simd_lanes_reverse(bytes) + res = transmute(#simd[W]u64)bytes + res = intrinsics.simd_lanes_reverse(res) + } + return +} + +XXH64_write64_simd :: #force_inline proc(buf: []$E, value: $V/#simd[$W]u64, alignment := Alignment.Unaligned) { + value := value + when ODIN_ENDIAN == .Big { + bytes := transmute(#simd[W*8]u8)value + bytes = intrinsics.simd_lanes_reverse(bytes) + value = transmute(#simd[W]u64)bytes + value = intrinsics.simd_lanes_reverse(value) + } + + if alignment == .Aligned { + (^V)(raw_data(buf))^ = value + } else { + intrinsics.unaligned_store((^V)(raw_data(buf)), value) + } +} diff --git a/core/hash/xxhash/streaming.odin b/core/hash/xxhash/streaming.odin index f77edf3e9..22d99be1d 100644 --- a/core/hash/xxhash/streaming.odin +++ b/core/hash/xxhash/streaming.odin @@ -1,16 +1,16 @@ +package xxhash + /* An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/). Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license, based on the original C code. + Made available under Odin's license, based on the original C code. List of contributors: Jeroen van Rijn: Initial implementation. */ -package xxhash - -import "core:mem" +import "base:runtime" import "base:intrinsics" /* @@ -121,7 +121,7 @@ XXH3_init_state :: proc(state: ^XXH3_state) { } XXH3_create_state :: proc(allocator := context.allocator) -> (res: ^XXH3_state, err: Error) { - state, mem_error := mem.new_aligned(XXH3_state, 64, allocator) + state, mem_error := runtime.new_aligned(XXH3_state, 64, allocator) err = nil if mem_error == nil else .Error XXH3_init_state(state) diff --git a/core/hash/xxhash/xxhash_3.odin b/core/hash/xxhash/xxhash_3.odin index 293e98528..810b98f1a 100644 --- a/core/hash/xxhash/xxhash_3.odin +++ b/core/hash/xxhash/xxhash_3.odin @@ -1,15 +1,15 @@ +package xxhash + /* An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/). Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license, based on the original C code. + Made available under Odin's license, based on the original C code. List of contributors: Jeroen van Rijn: Initial implementation. */ -package xxhash - import "base:intrinsics" /* @@ -52,6 +52,7 @@ XXH3_SECRET_SIZE_MIN :: 136 #assert(len(XXH3_kSecret) == 192 && len(XXH3_kSecret) > XXH3_SECRET_SIZE_MIN) XXH_ACC_ALIGN :: 8 /* scalar */ +XXH_MAX_WIDTH :: #config(XXH_MAX_WIDTH, 512) / 64 /* This is the optimal update size for incremental hashing. @@ -62,10 +63,11 @@ XXH3_INTERNAL_BUFFER_SIZE :: 256 Streaming state. IMPORTANT: This structure has a strict alignment requirement of 64 bytes!! ** - Do not allocate this with `make()` or `new`, it will not be sufficiently aligned. - Use`XXH3_create_state` and `XXH3_destroy_state, or stack allocation. + Default allocators will align it correctly if created via `new`, as will + placing this struct on the stack, but if using a custom allocator make sure + that it handles the alignment correctly! */ -XXH3_state :: struct { +XXH3_state :: struct #align(64) { acc: [8]u64, custom_secret: [XXH_SECRET_DEFAULT_SIZE]u8, buffer: [XXH3_INTERNAL_BUFFER_SIZE]u8, @@ -380,7 +382,6 @@ XXH3_INIT_ACC :: [XXH_ACC_NB]xxh_u64{ XXH_SECRET_MERGEACCS_START :: 11 -@(optimization_mode="favor_size") XXH3_hashLong_128b_internal :: #force_inline proc( input: []u8, secret: []u8, @@ -408,7 +409,6 @@ XXH3_hashLong_128b_internal :: #force_inline proc( /* * It's important for performance that XXH3_hashLong is not inlined. */ -@(optimization_mode="favor_size") XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator) } @@ -416,12 +416,10 @@ XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, /* * It's important for performance that XXH3_hashLong is not inlined. */ -@(optimization_mode="favor_size") XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator) } -@(optimization_mode="favor_size") XXH3_hashLong_128b_withSeed_internal :: #force_inline proc( input: []u8, seed: xxh_u64, secret: []u8, f_acc512: XXH3_accumulate_512_f, @@ -442,7 +440,6 @@ XXH3_hashLong_128b_withSeed_internal :: #force_inline proc( /* * It's important for performance that XXH3_hashLong is not inlined. */ - @(optimization_mode="favor_size") XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret) } @@ -477,7 +474,7 @@ XXH3_128bits_internal :: #force_inline proc( /* === Public XXH128 API === */ @(optimization_mode="favor_size") XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) { - return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed) + return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_default) } @(optimization_mode="favor_size") @@ -733,10 +730,6 @@ XXH3_accumulate_512_f :: #type proc(acc: []xxh_u64, input: []u8, secret: XXH3_scramble_accumulator_f :: #type proc(acc: []xxh_u64, secret: []u8) XXH3_init_custom_secret_f :: #type proc(custom_secret: []u8, seed64: xxh_u64) -XXH3_accumulate_512 : XXH3_accumulate_512_f = XXH3_accumulate_512_scalar -XXH3_scramble_accumulator : XXH3_scramble_accumulator_f = XXH3_scramble_accumulator_scalar -XXH3_init_custom_secret : XXH3_init_custom_secret_f = XXH3_init_custom_secret_scalar - /* scalar variants - universal */ @(optimization_mode="favor_size") XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) { @@ -751,7 +744,7 @@ XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, se sec := XXH64_read64(xsecret[8 * i:]) data_key := data_val ~ sec xacc[i ~ 1] += data_val /* swap adjacent lanes */ - xacc[i ] += u64(u128(u32(data_key)) * u128(u64(data_key >> 32))) + xacc[i ] += u64(u32(data_key)) * u64(data_key >> 32) } } @@ -785,6 +778,87 @@ XXH3_init_custom_secret_scalar :: #force_inline proc(custom_secret: []u8, seed64 } } +/* generalized SIMD variants */ +XXH3_accumulate_512_simd_generic :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8, $W: uint) { + u32xW :: #simd[W]u32 + u64xW :: #simd[W]u64 + + #no_bounds_check for i in uint(0).. 1 { + XXH3_accumulate_512_simd_generic(acc, input, secret, XXH_NATIVE_WIDTH) + } else { + XXH3_accumulate_512_scalar(acc, input, secret) + } +} + +XXH3_scramble_accumulator :: #force_inline proc(acc: []xxh_u64, secret: []u8) { + when XXH_NATIVE_WIDTH > 1 { + XXH3_scramble_accumulator_simd_generic(acc, secret, XXH_NATIVE_WIDTH) + } else { + XXH3_scramble_accumulator_scalar(acc, secret) + } +} + +XXH3_init_custom_secret :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64) { + when XXH_NATIVE_WIDTH > 1 { + XXH3_init_custom_secret_simd_generic(custom_secret, seed64, XXH_NATIVE_WIDTH) + } else { + XXH3_init_custom_secret_scalar(custom_secret, seed64) + } +} + XXH_PREFETCH_DIST :: 320 /* @@ -796,7 +870,7 @@ XXH_PREFETCH_DIST :: 320 XXH3_accumulate :: #force_inline proc( acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) { - for n := uint(0); n < nbStripes; n += 1 { + #no_bounds_check for n := uint(0); n < nbStripes; n += 1 { when !XXH_DISABLE_PREFETCH { in_ptr := &input[n * XXH_STRIPE_LEN] prefetch(in_ptr, XXH_PREFETCH_DIST) @@ -869,7 +943,6 @@ XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8, /* It's important for performance that XXH3_hashLong is not inlined. */ -@(optimization_mode="favor_size") XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) { return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator) } @@ -881,24 +954,11 @@ XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u This variant enforces that the compiler can detect that, and uses this opportunity to streamline the generated code for better performance. */ -@(optimization_mode="favor_size") XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) { return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator) } -/* - XXH3_hashLong_64b_withSeed(): - Generate a custom key based on alteration of default XXH3_kSecret with the seed, - and then use this key for long mode hashing. - - This operation is decently fast but nonetheless costs a little bit of time. - Try to avoid it whenever possible (typically when seed==0). - - It's important for performance that XXH3_hashLong is not inlined. Not sure - why (uop cache maybe?), but the difference is large and easily measurable. -*/ -@(optimization_mode="favor_size") -XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc( +XXH3_hashLong_64b_withSeed_internal :: #force_inline proc( input: []u8, seed: xxh_u64, f_acc512: XXH3_accumulate_512_f, @@ -915,9 +975,16 @@ XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc( } /* - It's important for performance that XXH3_hashLong is not inlined. + XXH3_hashLong_64b_withSeed(): + Generate a custom key based on alteration of default XXH3_kSecret with the seed, + and then use this key for long mode hashing. + + This operation is decently fast but nonetheless costs a little bit of time. + Try to avoid it whenever possible (typically when seed==0). + + It's important for performance that XXH3_hashLong is not inlined. Not sure + why (uop cache maybe?), but the difference is large and easily measurable. */ -@(optimization_mode="favor_size") XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) { return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret) } @@ -926,7 +993,7 @@ XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: xxh_u64) @(optimization_mode="favor_size") -XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) { +XXH3_64bits_internal :: #force_inline proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) { assert(len(secret) >= XXH3_SECRET_SIZE_MIN) /* If an action is to be taken if len(secret) condition is not respected, it should be done here. diff --git a/core/hash/xxhash/xxhash_32.odin b/core/hash/xxhash/xxhash_32.odin index 28cd4e177..7c03c232e 100644 --- a/core/hash/xxhash/xxhash_32.odin +++ b/core/hash/xxhash/xxhash_32.odin @@ -1,15 +1,15 @@ +package xxhash + /* An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/). Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license, based on the original C code. + Made available under Odin's license, based on the original C code. List of contributors: Jeroen van Rijn: Initial implementation. */ -package xxhash - import "base:intrinsics" /* diff --git a/core/hash/xxhash/xxhash_3_intel.odin b/core/hash/xxhash/xxhash_3_intel.odin new file mode 100644 index 000000000..3397fcef5 --- /dev/null +++ b/core/hash/xxhash/xxhash_3_intel.odin @@ -0,0 +1,13 @@ +#+build amd64, i386 +package xxhash + +import "base:intrinsics" + +@(private="file") SSE2_FEATURES :: "sse2" +@(private="file") AVX2_FEATURES :: "avx2" +@(private="file") AVX512_FEATURES :: "avx512dq,evex512" + +XXH_NATIVE_WIDTH :: min(XXH_MAX_WIDTH, + 8 when intrinsics.has_target_feature(AVX512_FEATURES) else + 4 when intrinsics.has_target_feature(AVX2_FEATURES) else + 2 when intrinsics.has_target_feature(SSE2_FEATURES) else 1) diff --git a/core/hash/xxhash/xxhash_3_other.odin b/core/hash/xxhash/xxhash_3_other.odin new file mode 100644 index 000000000..e1a5d0474 --- /dev/null +++ b/core/hash/xxhash/xxhash_3_other.odin @@ -0,0 +1,8 @@ +#+build !amd64 +#+build !i386 +package xxhash + +import "base:runtime" + +XXH_NATIVE_WIDTH :: min(XXH_MAX_WIDTH, + 2 when runtime.HAS_HARDWARE_SIMD else 1) diff --git a/core/hash/xxhash/xxhash_64.odin b/core/hash/xxhash/xxhash_64.odin index 87e8916d6..80818db67 100644 --- a/core/hash/xxhash/xxhash_64.odin +++ b/core/hash/xxhash/xxhash_64.odin @@ -1,15 +1,15 @@ +package xxhash + /* An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/). Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license, based on the original C code. + Made available under Odin's license, based on the original C code. List of contributors: Jeroen van Rijn: Initial implementation. */ -package xxhash - import "base:intrinsics" /* diff --git a/core/image/bmp/bmp.odin b/core/image/bmp/bmp.odin index 057c2ffa0..efb0dd7d9 100644 --- a/core/image/bmp/bmp.odin +++ b/core/image/bmp/bmp.odin @@ -1,4 +1,4 @@ -// package bmp implements a Microsoft BMP image reader +// Reader and writer for Microsoft `BMP` images. package core_image_bmp import "core:image" @@ -741,6 +741,6 @@ destroy :: proc(img: ^Image) { } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.BMP, load_from_bytes, destroy) } diff --git a/core/image/bmp/bmp_js.odin b/core/image/bmp/bmp_js.odin index fa5d59095..255c8aec7 100644 --- a/core/image/bmp/bmp_js.odin +++ b/core/image/bmp/bmp_js.odin @@ -1,4 +1,3 @@ -#+build js package core_image_bmp load :: proc{load_from_bytes, load_from_context} diff --git a/core/image/bmp/bmp_os.odin b/core/image/bmp/bmp_os.odin index 70a85a784..1aa1d63de 100644 --- a/core/image/bmp/bmp_os.odin +++ b/core/image/bmp/bmp_os.odin @@ -9,10 +9,10 @@ load :: proc{load_from_file, load_from_bytes, load_from_context} load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { context.allocator = allocator - data, ok := os.read_entire_file(filename) - defer delete(data) + data, data_err := os.read_entire_file(filename, allocator) + defer delete(data, allocator) - if ok { + if data_err == nil { return load_from_bytes(data, options) } else { return nil, .Unable_To_Read_File @@ -28,7 +28,7 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato defer bytes.buffer_destroy(out) save_to_buffer(out, img, options) or_return - write_ok := os.write_entire_file(output, out.buf[:]) + write_err := os.write_entire_file(output, out.buf[:]) - return nil if write_ok else .Unable_To_Write_File + return nil if write_err == nil else .Unable_To_Write_File } \ No newline at end of file diff --git a/core/image/common.odin b/core/image/common.odin index 690ebc045..1d51afb1c 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -1,15 +1,14 @@ +package image + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation, optimization. Ginger Bill: Cosmetic changes. */ -// package image implements a general 2D image library to be used with other image related packages -package image - import "core:bytes" import "core:mem" import "core:io" @@ -64,8 +63,16 @@ Image_Metadata :: union #shared_nil { ^QOI_Info, ^TGA_Info, ^BMP_Info, + ^JPEG_Info, } +Exif :: struct { + byte_order: enum { + little_endian, + big_endian, + }, + data: []u8 `fmt:"-"`, +} /* @@ -112,8 +119,7 @@ Image_Option: `.alpha_drop_if_present` If the image has an alpha channel, drop it. - You may want to use `.alpha_ - tiply` in this case. + You may want to use `.alpha_premultiply` in this case. NOTE: For PNG, this also skips handling of the tRNS chunk, if present, unless you select `alpha_premultiply`. @@ -163,6 +169,7 @@ Error :: union #shared_nil { PNG_Error, QOI_Error, BMP_Error, + JPEG_Error, compress.Error, compress.General_Error, @@ -575,6 +582,140 @@ TGA_Info :: struct { extension: Maybe(TGA_Extension), } + +/* + JPEG-specific +*/ +JFIF_Magic := [?]byte{0x4A, 0x46, 0x49, 0x46} // "JFIF" +JFXX_Magic := [?]byte{0x4A, 0x46, 0x58, 0x58} // "JFXX" +Exif_Magic := [?]byte{0x45, 0x78, 0x69, 0x66} // "Exif" + +JPEG_Error :: enum { + None = 0, + Duplicate_SOI_Marker, + Invalid_JFXX_Extension_Code, + Encountered_SOS_Before_SOF, + Invalid_Quantization_Table_Precision, + Invalid_Quantization_Table_Index, + Invalid_Huffman_Coefficient_Type, + Invalid_Huffman_Table_Index, + Unsupported_Frame_Type, + Invalid_Frame_Bit_Depth_Combo, + Invalid_Sampling_Factor, + Unsupported_12_Bit_Depth, + Multiple_SOS_Markers, + Encountered_RST_Marker_Outside_ECS, + Extra_Data_After_SOS, // Image seemed to have decoded okay, but there's more data after SOS + Invalid_Thumbnail_Size, + Huffman_Symbols_Exceeds_Max, +} + +JFIF_Unit :: enum byte { + None = 0, + Dots_Per_Inch = 1, + Dots_Per_Centimeter = 2, +} + +JFIF_APP0 :: struct { + version: u16be, + x_density: u16be, + y_density: u16be, + units: JFIF_Unit, + x_thumbnail: u8, + y_thumbnail: u8, + greyscale_thumbnail: bool, + thumbnail: []RGB_Pixel `fmt:"-"`, +} + +JFXX_APP0 :: struct { + extension_code: JFXX_Extension_Code, + x_thumbnail: u8, + y_thumbnail: u8, + thumbnail: []byte `fmt:"-"`, +} + +JFXX_Extension_Code :: enum u8 { + Thumbnail_JPEG = 0x10, + Thumbnail_1_Byte_Palette = 0x11, + Thumbnail_3_Byte_RGB = 0x13, +} + +JPEG_Marker :: enum u8 { + SOF0 = 0xC0, // Baseline sequential DCT + SOF1 = 0xC1, // Extended sequential DCT + SOF2 = 0xC2, // Progressive DCT + SOF3 = 0xC3, // Lossless (sequential) + SOF5 = 0xC5, // Differential sequential DCT + SOF6 = 0xC6, // Differential progressive DCT + SOF7 = 0xC7, // Differential lossless (sequential) + SOF9 = 0xC9, // Extended sequential DCT, Arithmetic coding + SOF10 = 0xCA, // Progressive DCT, Arithmetic coding + SOF11 = 0xCB, // Lossless (sequential), Arithmetic coding + SOF13 = 0xCD, // Differential sequential DCT, Arithmetic coding + SOF14 = 0xCE, // Differential progressive DCT, Arithmetic coding + SOF15 = 0xCF, // Differential lossless (sequential), Arithmetic coding + + DHT = 0xC4, + JPG = 0xC8, + DAC = 0xCC, + RST0 = 0xD0, + RST1 = 0xD1, + RST2 = 0xD2, + RST3 = 0xD3, + RST4 = 0xD4, + RST5 = 0xD5, + RST6 = 0xD6, + RST7 = 0xD7, + SOI = 0xD8, + EOI = 0xD9, + SOS = 0xDA, + DQT = 0xDB, + DNL = 0xDC, + DRI = 0xDD, + DHP = 0xDE, + EXP = 0xDF, + APP0 = 0xE0, + APP1 = 0xE1, + APP2 = 0xE2, + APP3 = 0xE3, + APP4 = 0xE4, + APP5 = 0xE5, + APP6 = 0xE6, + APP7 = 0xE7, + APP8 = 0xE8, + APP9 = 0xE9, + APP10 = 0xEA, + APP11 = 0xEB, + APP12 = 0xEC, + APP13 = 0xED, + APP14 = 0xEE, + APP15 = 0xEF, + JPG0 = 0xF0, + JPG1 = 0xF1, + JPG2 = 0xF2, + JPG3 = 0xF3, + JPG4 = 0xF4, + JPG5 = 0xF5, + JPG6 = 0xF6, + JPG7 = 0xF7, + JPG8 = 0xF8, + JPG9 = 0xF9, + JPG10 = 0xFA, + JPG11 = 0xFB, + JPG12 = 0xFC, + JPG13 = 0xFD, + COM = 0xFE, + TEM = 0x01, +} + +JPEG_Info :: struct { + jfif_app0: Maybe(JFIF_APP0), + jfxx_app0: Maybe(JFXX_APP0), + comments: [dynamic]string, + exif: [dynamic]Exif, + frame_type: JPEG_Marker, +} + // Function to help with image buffer calculations compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes := int(0)) -> (size: int) { size = ((((channels * width * depth) + 7) >> 3) + extra_row_bytes) * height diff --git a/core/image/doc.odin b/core/image/doc.odin new file mode 100644 index 000000000..1e44cca59 --- /dev/null +++ b/core/image/doc.odin @@ -0,0 +1,2 @@ +// General 2D image types and procedures to be used with other image related packages. +package image \ No newline at end of file diff --git a/core/image/general.odin b/core/image/general.odin index e92b54f18..779f5d0b1 100644 --- a/core/image/general.odin +++ b/core/image/general.odin @@ -10,13 +10,13 @@ Destroy_Proc :: #type proc(img: ^Image) _internal_loaders: [Which_File_Type]Loader_Proc _internal_destroyers: [Which_File_Type]Destroy_Proc -register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) { - assert(loader != nil) - assert(destroyer != nil) - assert(_internal_loaders[kind] == nil) +register :: proc "contextless" (kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) { + assert_contextless(loader != nil) + assert_contextless(destroyer != nil) + assert_contextless(_internal_loaders[kind] == nil) _internal_loaders[kind] = loader - assert(_internal_destroyers[kind] == nil) + assert_contextless(_internal_destroyers[kind] == nil) _internal_destroyers[kind] = destroyer } @@ -86,7 +86,7 @@ which_bytes :: proc(data: []byte) -> Which_File_Type { return v } get16le :: #force_inline proc(s: ^string) -> u16 { - v := u16(s[0]) | u16(s[1])<<16 + v := u16(s[0]) | u16(s[1])<<8 s^ = s[2:] return v } @@ -147,7 +147,7 @@ which_bytes :: proc(data: []byte) -> Which_File_Type { return .JPEG case s[:3] == "\xff\xd8\xff": switch s[3] { - case 0xdb, 0xee, 0xe1, 0xe0: + case 0xdb, 0xee, 0xe1, 0xe0, 0xfe, 0xed: return .JPEG } switch { diff --git a/core/image/general_js.odin b/core/image/general_js.odin index abf9812c0..6e6a95501 100644 --- a/core/image/general_js.odin +++ b/core/image/general_js.odin @@ -1,4 +1,3 @@ -#+build js package image load :: proc{ diff --git a/core/image/general_os.odin b/core/image/general_os.odin index 98eb5bdbe..63d7c8d43 100644 --- a/core/image/general_os.odin +++ b/core/image/general_os.odin @@ -8,18 +8,16 @@ load :: proc{ load_from_file, } - load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { - data, ok := os.read_entire_file(filename, allocator) + data, data_err := os.read_entire_file(filename, allocator) defer delete(data, allocator) - if ok { + if data_err == nil { return load_from_bytes(data, options, allocator) } else { return nil, .Unable_To_Read_File } } - which :: proc{ which_bytes, which_file, diff --git a/core/image/jpeg/jpeg.odin b/core/image/jpeg/jpeg.odin new file mode 100644 index 000000000..7261e5dd5 --- /dev/null +++ b/core/image/jpeg/jpeg.odin @@ -0,0 +1,1097 @@ +// Reader for baseline `JPEG` images. +package jpeg + +import "core:bytes" +import "core:compress" +import "core:math" +import "core:mem" +import "core:image" +import "core:slice" +import "core:strings" + +Image :: image.Image +Error :: image.Error +Options :: image.Options + +HUFFMAN_MAX_SYMBOLS :: 176 +HUFFMAN_MAX_BITS :: 16 +// 768 bytes of 24-bit RGB values. +THUMBNAIL_PALETTE_SIZE :: 768 +BLOCK_SIZE :: 8 +COEFFICIENT_COUNT :: BLOCK_SIZE * BLOCK_SIZE +SEGMENT_MAX_SIZE :: 65533 + +Coefficient :: enum u8 { + DC, + AC, +} + +Component :: enum u8 { + Y = 1, + Cb = 2, + Cr = 3, +} + +Huffman_Table :: struct { + symbols: [HUFFMAN_MAX_SYMBOLS]byte, + codes: [HUFFMAN_MAX_SYMBOLS]u32, + offsets: [HUFFMAN_MAX_BITS + 1]byte, +} + +Quantization_Table :: [COEFFICIENT_COUNT]u16be + +Color_Component :: struct { + dc_table_idx: u8, + ac_table_idx: u8, + quantization_table_idx: u8, + v_sampling_factor: int, + h_sampling_factor: int, +} + +// 8x8 block of pixels +Block :: [Component][COEFFICIENT_COUNT]i16 + +@(private="file") +zigzag := [?]byte{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, +} + +@(optimization_mode="favor_size", private="file") +refill_msb :: #force_inline proc(z: ^compress.Context_Memory_Input, width := i8(48)) { + refill := u64(width) + b := u64(0) + + if z.num_bits > refill { + return + } + + for { + if len(z.input_data) != 0 { + b = u64(z.input_data[0]) + + if len(z.input_data) > 1 && b == 0xFF { + next := u64(z.input_data[1]) + + if next == 0x00 { + // 0x00 is used as a stuffing to indicate that the 0xFF is part of the data and not + // the beginning of a marker + z.input_data = z.input_data[2:] + } else if next >= cast(u64)image.JPEG_Marker.RST0 && next <= cast(u64)image.JPEG_Marker.RST7 { + // Skip any RSTn markers if we encounter them + if len(z.input_data) > 2 { + b = u64(z.input_data[2]) + z.input_data = z.input_data[3:] + } else { + b = 0 + } + } + } else { + z.input_data = z.input_data[1:] + } + } else { + b = 0 + } + + z.code_buffer |= ((b << 56) >> u8(z.num_bits)) + z.num_bits += 8 + if z.num_bits > refill { + break + } + } +} + +@(optimization_mode="favor_size", private="file") +consume_bits_msb :: #force_inline proc(z: ^compress.Context_Memory_Input, width: u8) { + z.code_buffer <<= width + z.num_bits -= u64(width) +} + +@(private="file") +byte_align :: #force_inline proc(z: ^compress.Context_Memory_Input) { + skip := z.num_bits % 8 + consume_bits_msb(z, cast(u8)skip) +} + +@(optimization_mode="favor_size", private="file") +peek_bits_msb :: #force_inline proc(z: ^compress.Context_Memory_Input, width: u8) -> u32 { + if z.num_bits < u64(width) { + refill_msb(z) + } + return u32((z.code_buffer &~ (max(u64) >> width)) >> (64 - width)) +} + +@(optimization_mode="favor_size", private="file") +read_bits_msb :: #force_inline proc(z: ^compress.Context_Memory_Input, width: u8) -> u32 { + k := #force_inline peek_bits_msb(z, width) + #force_inline consume_bits_msb(z, width) + return k +} + +load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { + ctx := &compress.Context_Memory_Input{ + input_data = data, + } + + img, err = load_from_context(ctx, options, allocator) + return img, err +} + +@(private="file") +get_symbol :: proc(ctx: ^$C, huffman_table: Huffman_Table) -> byte { + possible_code: u32 = 0 + + for i in 0.. (img: ^Image, err: Error) { + context.allocator = allocator + options := options + + // Precalculate IDCT scaling factors + m0 := 2.0 * math.cos_f32(1.0 / 16.0 * 2.0 * math.PI) + m1 := 2.0 * math.cos_f32(2.0 / 16.0 * 2.0 * math.PI) + m3 := 2.0 * math.cos_f32(2.0 / 16.0 * 2.0 * math.PI) + m5 := 2.0 * math.cos_f32(3.0 / 16.0 * 2.0 * math.PI) + m2 := m0 - m5 + m4 := m0 + m5 + + s0 := math.cos_f32(0.0 / 16.0 * math.PI) / math.sqrt_f32(8.0) + s1 := math.cos_f32(1.0 / 16.0 * math.PI) / 2.0 + s2 := math.cos_f32(2.0 / 16.0 * math.PI) / 2.0 + s3 := math.cos_f32(3.0 / 16.0 * math.PI) / 2.0 + s4 := math.cos_f32(4.0 / 16.0 * math.PI) / 2.0 + s5 := math.cos_f32(5.0 / 16.0 * math.PI) / 2.0 + s6 := math.cos_f32(6.0 / 16.0 * math.PI) / 2.0 + s7 := math.cos_f32(7.0 / 16.0 * math.PI) / 2.0 + + if .info in options { + options += {.return_metadata, .do_not_decompress_image} + options -= {.info} + } + + if .return_header in options && .return_metadata in options { + options -= {.return_header} + } + + if .do_not_expand_channels in options || .do_not_expand_grayscale in options { + return img, .Unsupported_Option + } + + first := compress.read_u8(ctx) or_return + soi := cast(image.JPEG_Marker)compress.read_u8(ctx) or_return + if first != 0xFF && soi != .SOI { + return img, .Invalid_Signature + } + + img = new(Image) or_return + img.which = .JPEG + + expect_EOI := false + zero_based_components := false + huffman: [Coefficient][4]Huffman_Table + quantization: [4]Quantization_Table + color_components: [Component]Color_Component + restart_interval: int + // Image width and height in MCUs + mcu_width: int + mcu_height: int + // Image width and height in blocks + block_width: int + block_height: int + blocks: []Block + defer delete(blocks) + + loop: for { + // Loop until we find 0xFF. + first = compress.read_u8(ctx) or_return + (first == 0xFF) or_continue + + marker := cast(image.JPEG_Marker)compress.read_u8(ctx) or_return + if expect_EOI && marker != .EOI { + return img, .Extra_Data_After_SOS + } + #partial switch marker { + case cast(image.JPEG_Marker)0xFF: + // If we encounter multiple FF bytes then just skip them + continue + case .SOI: + return img, .Duplicate_SOI_Marker + case .APP0: + ident := make([dynamic]byte, 0, 16, context.temp_allocator) or_return + length := cast(int)((compress.read_data(ctx, u16be) or_return) - 2) + for { + b := compress.read_u8(ctx) or_return + if b == 0x00 { + break + } + append(&ident, b) or_return + } + if slice.equal(ident[:], image.JFIF_Magic[:]) { + if length != 14 { + // Malformed APP0. Skip it + compress.read_slice(ctx, length - len(ident) - 1) or_return + continue + } + + version := compress.read_data(ctx, u16be) or_return + units := cast(image.JFIF_Unit)(compress.read_u8(ctx) or_return) + x_density := compress.read_data(ctx, u16be) or_return + y_density := compress.read_data(ctx, u16be) or_return + x_thumbnail := cast(int)compress.read_u8(ctx) or_return + y_thumbnail := cast(int)compress.read_u8(ctx) or_return + thumbnail: []image.RGB_Pixel + + if x_thumbnail * y_thumbnail != 0 { + greyscale_thumbnail := false + thumbnail_size := x_thumbnail * y_thumbnail * 3 + // According to the JFIF spec, the thumbnail should always be made of RGB pixels. + // But some jpegs encode single-channel thumbnails. + if thumbnail_size != length - 14 && thumbnail_size / 3 == length - 14 { + thumbnail_size = x_thumbnail * y_thumbnail + greyscale_thumbnail = true + } else { + return img, .Invalid_Thumbnail_Size + } + thumb_pixels := slice.reinterpret([]image.RGB_Pixel, compress.read_slice_from_memory(ctx, x_thumbnail * y_thumbnail) or_return) + + if .return_metadata in options { + thumbnail = make([]image.RGB_Pixel, x_thumbnail * y_thumbnail) or_return + copy(thumbnail, thumb_pixels) + + info: ^image.JPEG_Info + if img.metadata == nil { + info = new(image.JPEG_Info) or_return + } else { + info = img.metadata.(^image.JPEG_Info) + } + info.jfif_app0 = image.JFIF_APP0{ + version, + x_density, + y_density, + units, + cast(u8)x_thumbnail, + cast(u8)y_thumbnail, + greyscale_thumbnail, + thumbnail, + } + img.metadata = info + } + } + } else if slice.equal(ident[:], image.JFXX_Magic[:]) { + extension_code := cast(image.JFXX_Extension_Code)compress.read_u8(ctx) or_return + thumbnail: []byte + + switch extension_code { + // We return the JPEG-compressed bytes for this type of thumbnail. + // It's up to the user if they want to decode it by checking the extension code + // and calling image.load() on the thumbnail. + // Not sure where to document that though, maybe it's better if the thumbnail is always raw pixel data. + case .Thumbnail_JPEG: + // +1 for the NUL byte + thumbnail_len := length - (size_of(image.JFXX_Magic) + 1 + size_of(image.JFXX_Extension_Code)) + thumbnail_jpeg := compress.read_slice(ctx, thumbnail_len) or_return + + if .return_metadata in options { + thumbnail = make([]byte, thumbnail_len) or_return + copy(thumbnail, thumbnail_jpeg) + + info: ^image.JPEG_Info + if img.metadata == nil { + info = new(image.JPEG_Info) or_return + } else { + info = img.metadata.(^image.JPEG_Info) + } + info.jfxx_app0 = image.JFXX_APP0{ + extension_code, + 0, + 0, + thumbnail, + } + img.metadata = info + } + case .Thumbnail_3_Byte_RGB: + x_thumbnail := cast(int)compress.read_u8(ctx) or_return + y_thumbnail := cast(int)compress.read_u8(ctx) or_return + pixels := compress.read_slice(ctx, x_thumbnail * y_thumbnail * 3) or_return + + if .return_metadata in options { + thumbnail = make([]byte, x_thumbnail * y_thumbnail * 3) or_return + copy(thumbnail, pixels) + + info: ^image.JPEG_Info + if img.metadata == nil { + info = new(image.JPEG_Info) or_return + } else { + info = img.metadata.(^image.JPEG_Info) + } + info.jfxx_app0 = image.JFXX_APP0{ + extension_code, + cast(u8)x_thumbnail, + cast(u8)y_thumbnail, + thumbnail, + } + img.metadata = info + } + case .Thumbnail_1_Byte_Palette: // NOTE(illusionman1212): NOT TESTED. Couldn't find a jpeg to test this with. + x_thumbnail := cast(int)compress.read_u8(ctx) or_return + y_thumbnail := cast(int)compress.read_u8(ctx) or_return + palette := slice.reinterpret([]image.RGB_Pixel, compress.read_slice(ctx, THUMBNAIL_PALETTE_SIZE / 3) or_return) + old_pixels := compress.read_slice(ctx, x_thumbnail * y_thumbnail) or_return + + if .return_metadata in options { + pixels := make([]byte, x_thumbnail * y_thumbnail * 3) or_return + for i in 0.. 0 && len(info.exif[len(info.exif) - 1].data) == SEGMENT_MAX_SIZE - len(ident) - 2 { + exif.byte_order = info.exif[len(info.exif) - 1].byte_order + } else { + compress.read_slice(ctx, length - len(ident) - 2) or_return + continue + } + } + + // - 2 for the NUL byte and padding byte + data := compress.read_slice(ctx, length - len(ident) - 2) or_return + exif.data = make([]byte, len(data)) or_return + copy(exif.data, data) + + append(&info.exif, exif) or_return + img.metadata = info + } else { + // - 1 for the NUL byte + compress.read_slice(ctx, length - len(ident) - 1) or_return + continue + } + case .COM: + length := (compress.read_data(ctx, u16be) or_return) - 2 + comment := string(compress.read_slice(ctx, cast(int)length) or_return) + if .return_metadata in options { + if info, ok := img.metadata.(^image.JPEG_Info); ok { + append(&info.comments, strings.clone(comment)) or_return + } + } + case .DQT: + length := cast(int)(compress.read_data(ctx, u16be) or_return) - 2 + + for length > 0 { + precision_and_index := compress.read_u8(ctx) or_return + precision := precision_and_index >> 4 + index := precision_and_index & 0xF + + if precision != 0 && precision != 1 { + return img, .Invalid_Quantization_Table_Precision + } + + if index < 0 || index > 3 { + return img, .Invalid_Quantization_Table_Index + } + + // When precision is 0, we read 64 u8s. + // when it's 1, we read 64 u16s. + table_bytes := 64 + if precision == 1 { + table_bytes = 128 + table := compress.read_slice(ctx, table_bytes) or_return + for v, i in slice.reinterpret([]u16be, table) { + quantization[index][i] = v + } + } else { + table := compress.read_slice(ctx, table_bytes) or_return + for v, i in table { + quantization[index][i] = cast(u16be)v + } + } + + length -= table_bytes + 1 + } + case .DHT: + length := (compress.read_data(ctx, u16be) or_return) - 2 + + for length > 0 { + type_index := compress.read_u8(ctx) or_return + type := cast(Coefficient)((type_index >> 4) & 0xF) + index := type_index & 0xF + + if type != .DC && type != .AC { + return img, .Invalid_Huffman_Coefficient_Type + } + + if index < 0 || index > 3 { + return img, .Invalid_Huffman_Table_Index + } + + lengths := compress.read_slice(ctx, HUFFMAN_MAX_BITS) or_return + num_symbols: u8 = 0 + for length, i in lengths { + num_symbols += length + huffman[type][index].offsets[i + 1] = num_symbols + } + + if num_symbols > HUFFMAN_MAX_SYMBOLS { + return img, .Huffman_Symbols_Exceeds_Max + } + + symbols := compress.read_slice(ctx, cast(int)num_symbols) or_return + copy(huffman[type][index].symbols[:], symbols) + + length -= cast(u16be)(1 + HUFFMAN_MAX_BITS + num_symbols) + + code: u32 = 0 + for i in 0.. image.MAX_DIMENSIONS { + return img, .Image_Dimensions_Too_Large + } + + // TODO: Some JPEGs use CMYK as the color model which means there will be 4 components + if components != 1 && components != 3 { + return img, .Invalid_Number_Of_Channels + } + + if img.metadata != nil { + info := img.metadata.(^image.JPEG_Info) + info.frame_type = marker + } + + mcu_width = (img.width + 7) / BLOCK_SIZE + mcu_height = (img.height + 7) / BLOCK_SIZE + block_width = mcu_width + block_height = mcu_height + + for _ in 0.. .Cr { + return img, .Image_Does_Not_Adhere_to_Spec + } + + h_v_factors := compress.read_u8(ctx) or_return + horizontal_sampling := h_v_factors >> 4 + vertical_sampling := h_v_factors & 0xF + + // TODO: spec says the range for the sampling factors is 1-4 + // We only support 1,2 for now. + if horizontal_sampling < 1 || horizontal_sampling > 2 { + return img, .Invalid_Sampling_Factor + } + if vertical_sampling < 1 || vertical_sampling > 2 { + return img, .Invalid_Sampling_Factor + } + + if id == .Y { + if horizontal_sampling == 2 && mcu_width % 2 == 1 { + block_width += 1 + } + if vertical_sampling == 2 && mcu_height % 2 == 1 { + block_height += 1 + } + } else { + if horizontal_sampling != 1 && vertical_sampling != 1 { + return img, .Invalid_Sampling_Factor + } + } + + quantization_table_idx := compress.read_u8(ctx) or_return + + if quantization_table_idx < 0 || quantization_table_idx > 3 { + return img, .Invalid_Quantization_Table_Index + } + + color_components[id].quantization_table_idx = quantization_table_idx + color_components[id].v_sampling_factor = cast(int)vertical_sampling + color_components[id].h_sampling_factor = cast(int)horizontal_sampling + } + case .SOF2, // Progressive DCT + .SOF3, // Lossless (sequential) + .SOF5, // Differential sequential DCT + .SOF6, // Differential progressive DCT + .SOF7, // Differential lossless (sequential) + .SOF9, // Extended sequential DCT, Arithmetic coding + .SOF10, // Progressive DCT, Arithmetic coding + .SOF11, // Lossless (sequential), Arithmetic coding + .SOF13, // Differential sequential DCT, Arithmetic coding + .SOF14, // Differential progressive DCT, Arithmetic coding + .SOF15: // Differential lossless (sequential), Arithmetic coding + if img.metadata != nil { + info := img.metadata.(^image.JPEG_Info) + info.frame_type = marker + } + return img, .Unsupported_Frame_Type + case .SOS: + if img.channels == 0 && img.depth == 0 && img.width == 0 && img.height == 0 { + return img, .Encountered_SOS_Before_SOF + } + + if .do_not_decompress_image in options { + return img, nil + } + + // Length + compress.read_data(ctx, u16be) or_return + num_components := compress.read_u8(ctx) or_return + if num_components != 1 && num_components != 3 { + return img, .Invalid_Number_Of_Channels + } + + for _ in 0.. .Cr { + return img, .Image_Does_Not_Adhere_to_Spec + } + + // high 4 is DC, low 4 is AC + coefficient_indices := compress.read_u8(ctx) or_return + dc_table_idx := coefficient_indices >> 4 + ac_table_idx := coefficient_indices & 0xF + + if (dc_table_idx < 0 || dc_table_idx > 3) || (ac_table_idx < 0 || ac_table_idx > 3) { + return img, .Invalid_Huffman_Table_Index + } + + color_components[component_id].dc_table_idx = dc_table_idx + color_components[component_id].ac_table_idx = ac_table_idx + } + // TODO: These aren't used for sequential DCT, only progressive and lossless. + Ss := compress.read_u8(ctx) or_return + _ = Ss + Se := compress.read_u8(ctx) or_return + _ = Se + Ah_Al := compress.read_u8(ctx) or_return + _ = Ah_Al + + blocks = make([]Block, block_height * block_width) or_return + + previous_dc: [Component]i16 + + luma_v_sampling_factor := color_components[.Y].v_sampling_factor + luma_h_sampling_factor := color_components[.Y].h_sampling_factor + + restart_interval *= luma_v_sampling_factor * luma_h_sampling_factor + #no_bounds_check for y := 0; y < mcu_height; y += luma_v_sampling_factor { + for x := 0; x < mcu_width; x += luma_h_sampling_factor { + blk := y * block_width + x + + if restart_interval != 0 && blk % restart_interval == 0 { + previous_dc[.Y] = 0 + previous_dc[.Cb] = 0 + previous_dc[.Cr] = 0 + byte_align(ctx) + } + for c in 1..=img.channels { + c := cast(Component)c + for v in 0.. 11 { + return img, .Corrupt + } + + dc_coeff := cast(i16)read_bits_msb(ctx, length) + + if length != 0 && dc_coeff < (1 << (length - 1)) { + dc_coeff -= (1 << length) - 1 + } + mcu[0] = (dc_coeff + previous_dc[c]) * cast(i16)quantization_table[0] + previous_dc[c] = dc_coeff + previous_dc[c] + + for i := 1; i < COEFFICIENT_COUNT; i += 1 { + // High nibble is amount of 0s to skip. + // Low nibble is length of coeff. + symbol := get_symbol(ctx, ac_table) + + // Special symbol used to indicate + // that the rest of the MCU is filled with 0s + if symbol == 0x00 { + continue h_loop + } + + amnt_zeros := int(symbol >> 4) + ac_coeff_len := symbol & 0xF + ac_coeff: i16 = 0 + + if i + amnt_zeros >= COEFFICIENT_COUNT || ac_coeff_len > 10 { + return img, .Corrupt + } + + i += amnt_zeros + + ac_coeff = cast(i16)read_bits_msb(ctx, ac_coeff_len) + if ac_coeff < (1 << (ac_coeff_len - 1)) { + ac_coeff -= (1 << ac_coeff_len) - 1 + } + + mcu[zigzag[i]] = ac_coeff * cast(i16)quantization_table[i] + } + } + } + } + + for c in 1..=img.channels { + c := cast(Component)c + + for v in 0..= 0; v -= 1 { + for h := luma_h_sampling_factor - 1; h >= 0; h -= 1 { + y_blk := &blocks[(y + v) * block_width + (x + h)] + + for j := BLOCK_SIZE - 1; j >= 0; j -= 1 { + for k := BLOCK_SIZE - 1; k >= 0; k -= 1 { + i := j * BLOCK_SIZE + k + cbcr_pixel_row := j / luma_v_sampling_factor + 4 * v + cbcr_pixel_column := k / luma_h_sampling_factor + 4 * h + cbcr_pixel := cbcr_pixel_row * BLOCK_SIZE + cbcr_pixel_column + + r := cast(i16)clamp(cast(f32)y_blk[.Y][i] + 1.402 * cast(f32)cbcr_blk[.Cr][cbcr_pixel] + 128, 0, 255) + g := cast(i16)clamp(cast(f32)y_blk[.Y][i] - 0.344 * cast(f32)cbcr_blk[.Cb][cbcr_pixel] - 0.714 * cast(f32)cbcr_blk[.Cr][cbcr_pixel] + 128, 0, 255) + b := cast(i16)clamp(cast(f32)y_blk[.Y][i] + 1.772 * cast(f32)cbcr_blk[.Cb][cbcr_pixel] + 128, 0, 255) + + y_blk[.Y][i] = r + y_blk[.Cb][i] = g + y_blk[.Cr][i] = b + } + } + } + } + } + } + + orig_channels := img.channels + + // We automatically expand grayscale images to RGB + if img.channels == 1 { + img.channels += 2 + } + + if .alpha_add_if_missing in options { + img.channels += 1 + orig_channels += 1 + } + + if resize(&img.pixels.buf, img.width * img.height * img.channels) != nil { + return img, .Unable_To_Allocate_Or_Resize + } + + switch orig_channels { + case 1: // Grayscale JPEG expanded to RGB + out := mem.slice_data_cast([]image.RGB_Pixel, img.pixels.buf[:]) + out_idx := 0 + for y in 0.. (img: ^Image, err: Error) { + context.allocator = allocator + + data, data_err := os.read_entire_file(filename, allocator) + defer delete(data, allocator) + + if data_err == nil { + return load_from_bytes(data, options) + } else { + return nil, .Unable_To_Read_File + } +} diff --git a/core/image/netpbm/doc.odin b/core/image/netpbm/doc.odin index 7106e023e..bac893b0f 100644 --- a/core/image/netpbm/doc.odin +++ b/core/image/netpbm/doc.odin @@ -1,4 +1,6 @@ /* +Readers and writers for `PBM`, `PGM`, `PPM`, `PAM` and `PFM` images. + Formats: PBM (P1, P4): Portable Bit Map, stores black and white images (1 channel) diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index a9dc6599a..6a30d135a 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -1,4 +1,3 @@ -#+vet !using-stmt package netpbm import "core:bytes" @@ -73,8 +72,7 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context } } - // using info so we can just talk about the header - using info + header := &info.header // validation if header.format in (PBM + PGM + Formats{.Pf}) && img.channels != 1 \ @@ -664,14 +662,14 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for ASCII :: Formats{.P1, .P2, .P3} */ - using res.header + h := &res.header - width = img.width - height = img.height - channels = img.channels - depth = img.depth - maxval = 255 if img.depth == 8 else 65535 - little_endian = true if ODIN_ENDIAN == .Little else false + h.width = img.width + h.height = img.height + h.channels = img.channels + h.depth = img.depth + h.maxval = 255 if img.depth == 8 else 65535 + h.little_endian = ODIN_ENDIAN == .Little // Assume we'll find a suitable format ok = true @@ -680,37 +678,37 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for case 1: // Must be Portable Float Map if img.depth == 32 { - format = .Pf + h.format = .Pf return } if force_black_and_white { // Portable Bit Map - format = .P4 if prefer_binary else .P1 - maxval = 1 + h.format = .P4 if prefer_binary else .P1 + h.maxval = 1 return } else { // Portable Gray Map - format = .P5 if prefer_binary else .P2 + h.format = .P5 if prefer_binary else .P2 return } case 3: // Must be Portable Float Map if img.depth == 32 { - format = .PF + h.format = .PF return } // Portable Pixel Map - format = .P6 if prefer_binary else .P3 + h.format = .P6 if prefer_binary else .P3 return case: // Portable Arbitrary Map if img.depth == 8 || img.depth == 16 { - format = .P7 - scale = pfm_scale + h.format = .P7 + h.scale = pfm_scale return } } @@ -720,7 +718,7 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { return load_from_bytes(data, allocator) } diff --git a/core/image/netpbm/netpbm_js.odin b/core/image/netpbm/netpbm_js.odin index 7d475cf62..cc2e5615c 100644 --- a/core/image/netpbm/netpbm_js.odin +++ b/core/image/netpbm/netpbm_js.odin @@ -1,4 +1,3 @@ -#+build js package netpbm load :: proc { diff --git a/core/image/netpbm/netpbm_os.odin b/core/image/netpbm/netpbm_os.odin index 2cf2439ac..ae9029b54 100644 --- a/core/image/netpbm/netpbm_os.odin +++ b/core/image/netpbm/netpbm_os.odin @@ -8,20 +8,18 @@ load :: proc { load_from_bytes, } - load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: ^Image, err: Error) { context.allocator = allocator - data, ok := os.read_entire_file(filename); defer delete(data) - if !ok { + data, data_err := os.read_entire_file(filename, allocator); defer delete(data) + if data_err == nil { + return load_from_bytes(data) + } else { err = .Unable_To_Read_File return } - - return load_from_bytes(data) } - save :: proc { save_to_file, save_to_buffer, @@ -33,7 +31,7 @@ save_to_file :: proc(filename: string, img: ^Image, custom_info: Info = {}, allo data: []byte; defer delete(data) data = save_to_buffer(img, custom_info) or_return - if ok := os.write_entire_file(filename, data); !ok { + if save_err := os.write_entire_file(filename, data); save_err != nil { return .Unable_To_Write_File } diff --git a/core/image/png/doc.odin b/core/image/png/doc.odin deleted file mode 100644 index 623c13077..000000000 --- a/core/image/png/doc.odin +++ /dev/null @@ -1,348 +0,0 @@ -/* -package png implements a PNG image reader - -The PNG specification is at [[ https://www.w3.org/TR/PNG/ ]]. - -Example: - package main - - import "core:image" - // import "core:image/png" - import "core:bytes" - import "core:fmt" - - // For PPM writer - import "core:mem" - import "core:os" - - main :: proc() { - track := mem.Tracking_Allocator{} - mem.tracking_allocator_init(&track, context.allocator) - - context.allocator = mem.tracking_allocator(&track) - - demo() - - if len(track.allocation_map) > 0 { - fmt.println("Leaks:") - for _, v in track.allocation_map { - fmt.printf("\t%v\n\n", v) - } - } - } - - demo :: proc() { - file: string - - options := image.Options{.return_metadata} - err: image.Error - img: ^image.Image - - file = "../../../misc/logo-slim.png" - - img, err = load(file, options) - defer destroy(img) - - if err != nil { - fmt.printf("Trying to read PNG file %v returned %v\n", file, err) - } else { - fmt.printf("Image: %vx%vx%v, %v-bit.\n", img.width, img.height, img.channels, img.depth) - - if v, ok := img.metadata.(^image.PNG_Info); ok { - // Handle ancillary chunks as you wish. - // We provide helper functions for a few types. - for c in v.chunks { - #partial switch c.header.type { - case .tIME: - if t, t_ok := core_time(c); t_ok { - fmt.printf("[tIME]: %v\n", t) - } - case .gAMA: - if gama, gama_ok := gamma(c); gama_ok { - fmt.printf("[gAMA]: %v\n", gama) - } - case .pHYs: - if phys, phys_ok := phys(c); phys_ok { - if phys.unit == .Meter { - xm := f32(img.width) / f32(phys.ppu_x) - ym := f32(img.height) / f32(phys.ppu_y) - dpi_x, dpi_y := phys_to_dpi(phys) - fmt.printf("[pHYs] Image resolution is %v x %v pixels per meter.\n", phys.ppu_x, phys.ppu_y) - fmt.printf("[pHYs] Image resolution is %v x %v DPI.\n", dpi_x, dpi_y) - fmt.printf("[pHYs] Image dimensions are %v x %v meters.\n", xm, ym) - } else { - fmt.printf("[pHYs] x: %v, y: %v pixels per unknown unit.\n", phys.ppu_x, phys.ppu_y) - } - } - case .iTXt, .zTXt, .tEXt: - res, ok_text := text(c) - if ok_text { - if c.header.type == .iTXt { - fmt.printf("[iTXt] %v (%v:%v): %v\n", res.keyword, res.language, res.keyword_localized, res.text) - } else { - fmt.printf("[tEXt/zTXt] %v: %v\n", res.keyword, res.text) - } - } - defer text_destroy(res) - case .bKGD: - fmt.printf("[bKGD] %v\n", img.background) - case .eXIf: - if res, ok_exif := exif(c); ok_exif { - /* - Other than checking the signature and byte order, we don't handle Exif data. - If you wish to interpret it, pass it to an Exif parser. - */ - fmt.printf("[eXIf] %v\n", res) - } - case .PLTE: - if plte, plte_ok := plte(c); plte_ok { - fmt.printf("[PLTE] %v\n", plte) - } else { - fmt.printf("[PLTE] Error\n") - } - case .hIST: - if res, ok_hist := hist(c); ok_hist { - fmt.printf("[hIST] %v\n", res) - } - case .cHRM: - if res, ok_chrm := chrm(c); ok_chrm { - fmt.printf("[cHRM] %v\n", res) - } - case .sPLT: - res, ok_splt := splt(c) - if ok_splt { - fmt.printf("[sPLT] %v\n", res) - } - splt_destroy(res) - case .sBIT: - if res, ok_sbit := sbit(c); ok_sbit { - fmt.printf("[sBIT] %v\n", res) - } - case .iCCP: - res, ok_iccp := iccp(c) - if ok_iccp { - fmt.printf("[iCCP] %v\n", res) - } - iccp_destroy(res) - case .sRGB: - if res, ok_srgb := srgb(c); ok_srgb { - fmt.printf("[sRGB] Rendering intent: %v\n", res) - } - case: - type := c.header.type - name := chunk_type_to_name(&type) - fmt.printf("[%v]: %v\n", name, c.data) - } - } - } - } - - fmt.printf("Done parsing metadata.\n") - - if err == nil && .do_not_decompress_image not_in options && .info not_in options { - if ok := write_image_as_ppm("out.ppm", img); ok { - fmt.println("Saved decoded image.") - } else { - fmt.println("Error saving out.ppm.") - fmt.println(img) - } - } - } - - // Crappy PPM writer used during testing. Don't use in production. - write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: bool) { - - _bg :: proc(bg: Maybe([3]u16), x, y: int, high := true) -> (res: [3]u16) { - if v, ok := bg.?; ok { - res = v - } else { - if high { - l := u16(30 * 256 + 30) - - if (x & 4 == 0) ~ (y & 4 == 0) { - res = [3]u16{l, 0, l} - } else { - res = [3]u16{l >> 1, 0, l >> 1} - } - } else { - if (x & 4 == 0) ~ (y & 4 == 0) { - res = [3]u16{30, 30, 30} - } else { - res = [3]u16{15, 15, 15} - } - } - } - return - } - - // profiler.timed_proc(); - using image - using os - - flags: int = O_WRONLY|O_CREATE|O_TRUNC - - img := image - - // PBM 16-bit images are big endian - when ODIN_ENDIAN == .Little { - if img.depth == 16 { - // The pixel components are in Big Endian. Let's byteswap back. - input := mem.slice_data_cast([]u16, img.pixels.buf[:]) - output := mem.slice_data_cast([]u16be, img.pixels.buf[:]) - #no_bounds_check for v, i in input { - output[i] = u16be(v) - } - } - } - - pix := bytes.buffer_to_bytes(&img.pixels) - - if len(pix) == 0 || len(pix) < image.width * image.height * int(image.channels) { - return false - } - - mode: int = 0 - when ODIN_OS == .Linux || ODIN_OS == .Darwin { - // NOTE(justasd): 644 (owner read, write; group read; others read) - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH - } - - fd, err := open(filename, flags, mode) - if err != nil { - return false - } - defer close(fd) - - write_string(fd, - fmt.tprintf("P6\n%v %v\n%v\n", width, height, uint(1 << uint(depth) - 1)), - ) - - if channels == 3 { - // We don't handle transparency here... - write_ptr(fd, raw_data(pix), len(pix)) - } else { - bpp := depth == 16 ? 2 : 1 - bytes_needed := width * height * 3 * bpp - - op := bytes.Buffer{} - bytes.buffer_init_allocator(&op, bytes_needed, bytes_needed) - defer bytes.buffer_destroy(&op) - - if channels == 1 { - if depth == 16 { - assert(len(pix) == width * height * 2) - p16 := mem.slice_data_cast([]u16, pix) - o16 := mem.slice_data_cast([]u16, op.buf[:]) - #no_bounds_check for len(p16) != 0 { - r := u16(p16[0]) - o16[0] = r - o16[1] = r - o16[2] = r - p16 = p16[1:] - o16 = o16[3:] - } - } else { - o := 0 - for i := 0; i < len(pix); i += 1 { - r := pix[i] - op.buf[o ] = r - op.buf[o+1] = r - op.buf[o+2] = r - o += 3 - } - } - write_ptr(fd, raw_data(op.buf), len(op.buf)) - } else if channels == 2 { - if depth == 16 { - p16 := mem.slice_data_cast([]u16, pix) - o16 := mem.slice_data_cast([]u16, op.buf[:]) - - bgcol := img.background - - #no_bounds_check for len(p16) != 0 { - r := f64(u16(p16[0])) - bg: f64 - if bgcol != nil { - v := bgcol.([3]u16)[0] - bg = f64(v) - } - a := f64(u16(p16[1])) / 65535.0 - l := (a * r) + (1 - a) * bg - - o16[0] = u16(l) - o16[1] = u16(l) - o16[2] = u16(l) - - p16 = p16[2:] - o16 = o16[3:] - } - } else { - o := 0 - for i := 0; i < len(pix); i += 2 { - r := pix[i]; a := pix[i+1]; a1 := f32(a) / 255.0 - c := u8(f32(r) * a1) - op.buf[o ] = c - op.buf[o+1] = c - op.buf[o+2] = c - o += 3 - } - } - write_ptr(fd, raw_data(op.buf), len(op.buf)) - } else if channels == 4 { - if depth == 16 { - p16 := mem.slice_data_cast([]u16be, pix) - o16 := mem.slice_data_cast([]u16be, op.buf[:]) - - #no_bounds_check for len(p16) != 0 { - - bg := _bg(img.background, 0, 0) - r := f32(p16[0]) - g := f32(p16[1]) - b := f32(p16[2]) - a := f32(p16[3]) / 65535.0 - - lr := (a * r) + (1 - a) * f32(bg[0]) - lg := (a * g) + (1 - a) * f32(bg[1]) - lb := (a * b) + (1 - a) * f32(bg[2]) - - o16[0] = u16be(lr) - o16[1] = u16be(lg) - o16[2] = u16be(lb) - - p16 = p16[4:] - o16 = o16[3:] - } - } else { - o := 0 - - for i := 0; i < len(pix); i += 4 { - - x := (i / 4) % width - y := i / width / 4 - - _b := _bg(img.background, x, y, false) - bgcol := [3]u8{u8(_b[0]), u8(_b[1]), u8(_b[2])} - - r := f32(pix[i]) - g := f32(pix[i+1]) - b := f32(pix[i+2]) - a := f32(pix[i+3]) / 255.0 - - lr := u8(f32(r) * a + (1 - a) * f32(bgcol[0])) - lg := u8(f32(g) * a + (1 - a) * f32(bgcol[1])) - lb := u8(f32(b) * a + (1 - a) * f32(bgcol[2])) - op.buf[o ] = lr - op.buf[o+1] = lg - op.buf[o+2] = lb - o += 3 - } - } - write_ptr(fd, raw_data(op.buf), len(op.buf)) - } else { - return false - } - } - return true - } -*/ -package png diff --git a/core/image/png/example.odin b/core/image/png/example.odin new file mode 100644 index 000000000..cab6e4de1 --- /dev/null +++ b/core/image/png/example.odin @@ -0,0 +1,136 @@ +#+build ignore +package png_example + +import "core:image" +import "core:image/png" +import "core:image/tga" +import "core:fmt" +import "core:mem" + +demo :: proc() { + options := image.Options{.return_metadata} + err: image.Error + img: ^image.Image + + PNG_FILE :: ODIN_ROOT + "misc/logo-slim.png" + + img, err = png.load(PNG_FILE, options) + defer png.destroy(img) + + if err != nil { + fmt.eprintfln("Trying to read PNG file %v returned %v.", PNG_FILE, err) + } else { + fmt.printfln("Image: %vx%vx%v, %v-bit.", img.width, img.height, img.channels, img.depth) + + if v, ok := img.metadata.(^image.PNG_Info); ok { + // Handle ancillary chunks as you wish. + // We provide helper functions for a few types. + for c in v.chunks { + #partial switch c.header.type { + case .tIME: + if t, t_ok := png.core_time(c); t_ok { + fmt.printfln("[tIME]: %v", t) + } + case .gAMA: + if gama, gama_ok := png.gamma(c); gama_ok { + fmt.printfln("[gAMA]: %v", gama) + } + case .pHYs: + if phys, phys_ok := png.phys(c); phys_ok { + if phys.unit == .Meter { + xm := f32(img.width) / f32(phys.ppu_x) + ym := f32(img.height) / f32(phys.ppu_y) + dpi_x, dpi_y := png.phys_to_dpi(phys) + fmt.printfln("[pHYs] Image resolution is %v x %v pixels per meter.", phys.ppu_x, phys.ppu_y) + fmt.printfln("[pHYs] Image resolution is %v x %v DPI.", dpi_x, dpi_y) + fmt.printfln("[pHYs] Image dimensions are %v x %v meters.", xm, ym) + } else { + fmt.printfln("[pHYs] x: %v, y: %v pixels per unknown unit.", phys.ppu_x, phys.ppu_y) + } + } + case .iTXt, .zTXt, .tEXt: + res, ok_text := png.text(c) + if ok_text { + if c.header.type == .iTXt { + fmt.printfln("[iTXt] %v (%v:%v): %v", res.keyword, res.language, res.keyword_localized, res.text) + } else { + fmt.printfln("[tEXt/zTXt] %v: %v", res.keyword, res.text) + } + } + defer png.text_destroy(res) + case .bKGD: + fmt.printfln("[bKGD] %v", img.background) + case .eXIf: + if res, ok_exif := png.exif(c); ok_exif { + /* + Other than checking the signature and byte order, we don't handle Exif data. + If you wish to interpret it, pass it to an Exif parser. + */ + fmt.printfln("[eXIf] %v", res) + } + case .PLTE: + if plte, plte_ok := png.plte(c); plte_ok { + fmt.printfln("[PLTE] %v", plte) + } else { + fmt.printfln("[PLTE] Error") + } + case .hIST: + if res, ok_hist := png.hist(c); ok_hist { + fmt.printfln("[hIST] %v", res) + } + case .cHRM: + if res, ok_chrm := png.chrm(c); ok_chrm { + fmt.printfln("[cHRM] %v", res) + } + case .sPLT: + res, ok_splt := png.splt(c) + if ok_splt { + fmt.printfln("[sPLT] %v", res) + } + png.splt_destroy(res) + case .sBIT: + if res, ok_sbit := png.sbit(c); ok_sbit { + fmt.printfln("[sBIT] %v", res) + } + case .iCCP: + res, ok_iccp := png.iccp(c) + if ok_iccp { + fmt.printfln("[iCCP] %v", res) + } + png.iccp_destroy(res) + case .sRGB: + if res, ok_srgb := png.srgb(c); ok_srgb { + fmt.printfln("[sRGB] Rendering intent: %v", res) + } + case: + type := c.header.type + name := png.chunk_type_to_name(&type) + fmt.printfln("[%v]: %v", name, c.data) + } + } + } + } + + fmt.printfln("Done parsing metadata.") + + if err == nil && .do_not_decompress_image not_in options && .info not_in options { + if err = tga.save("out.tga", img); err == nil { + fmt.println("Saved decoded image.") + } else { + fmt.eprintfln("Error %v saving out.ppm.", err) + } + } +} + +main :: proc() { + track: mem.Tracking_Allocator + mem.tracking_allocator_init(&track, context.allocator) + defer mem.tracking_allocator_destroy(&track) + context.allocator = mem.tracking_allocator(&track) + + demo() + + for _, leak in track.allocation_map { + fmt.printf("%v leaked %m", leak.location, leak.size) + } +} \ No newline at end of file diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin index a9495ed4d..527ac486c 100644 --- a/core/image/png/helpers.odin +++ b/core/image/png/helpers.odin @@ -1,3 +1,5 @@ +package png + /* Copyright 2021 Jeroen van Rijn . Made available under Odin's BSD-2 license. @@ -9,8 +11,6 @@ These are a few useful utility functions to work with PNG images. */ -package png - import "core:image" import "core:compress/zlib" import coretime "core:time" @@ -366,7 +366,7 @@ chrm :: proc(c: image.PNG_Chunk) -> (res: cHRM, ok: bool) { return } -exif :: proc(c: image.PNG_Chunk) -> (res: Exif, ok: bool) { +exif :: proc(c: image.PNG_Chunk) -> (res: image.Exif, ok: bool) { ok = true @@ -396,4 +396,4 @@ exif :: proc(c: image.PNG_Chunk) -> (res: Exif, ok: bool) { General helper functions */ -compute_buffer_size :: image.compute_buffer_size \ No newline at end of file +compute_buffer_size :: image.compute_buffer_size diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 2d3665e94..5a0913cff 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -1,16 +1,17 @@ +#+feature using-stmt +// Reader for `PNG` images. +// The PNG specification is at [[ https://www.w3.org/TR/PNG/ ]]. +package png + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. Ginger Bill: Cosmetic changes. */ - -#+vet !using-stmt -package png - import "core:compress" import "core:compress/zlib" import "core:image" @@ -138,14 +139,6 @@ Text :: struct { text: string, } -Exif :: struct { - byte_order: enum { - little_endian, - big_endian, - }, - data: []u8, -} - iCCP :: struct { name: string, profile: []u8, @@ -250,10 +243,14 @@ read_header :: proc(ctx: ^$C) -> (image.PNG_IHDR, Error) { header := (^image.PNG_IHDR)(raw_data(c.data))^ // Validate IHDR using header - if width == 0 || height == 0 || u128(width) * u128(height) > image.MAX_DIMENSIONS { + if width == 0 || height == 0 { return {}, .Invalid_Image_Dimensions } + if u128(width) * u128(height) > image.MAX_DIMENSIONS { + return {}, .Image_Dimensions_Too_Large + } + if compression_method != 0 { return {}, compress.General_Error.Unknown_Compression_Method } @@ -1212,7 +1209,6 @@ Filter_Params :: struct #packed { depth_scale_table :: []u8{0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01} -// @(optimization_mode="speed") defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) { using params @@ -1273,7 +1269,6 @@ defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) { return } -// @(optimization_mode="speed") defilter_less_than_8 :: proc(params: ^Filter_Params) -> bool #no_bounds_check { using params @@ -1436,7 +1431,6 @@ defilter_less_than_8 :: proc(params: ^Filter_Params) -> bool #no_bounds_check { return true } -// @(optimization_mode="speed") defilter_16 :: proc(params: ^Filter_Params) -> bool { using params @@ -1614,6 +1608,6 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.PNG, load_from_bytes, destroy) } diff --git a/core/image/png/png_js.odin b/core/image/png/png_js.odin index dd9e74526..25e5c4071 100644 --- a/core/image/png/png_js.odin +++ b/core/image/png/png_js.odin @@ -1,4 +1,3 @@ -#+build js package png load :: proc{load_from_bytes, load_from_context} diff --git a/core/image/png/png_os.odin b/core/image/png/png_os.odin index 8e0706206..5fc10cec4 100644 --- a/core/image/png/png_os.odin +++ b/core/image/png/png_os.odin @@ -8,12 +8,12 @@ load :: proc{load_from_file, load_from_bytes, load_from_context} load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { context.allocator = allocator - data, ok := os.read_entire_file(filename) - defer delete(data) + data, data_err := os.read_entire_file(filename, allocator) + defer delete(data, allocator) - if ok { + if data_err == nil { return load_from_bytes(data, options) } else { return nil, .Unable_To_Read_File } -} +} \ No newline at end of file diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index 6b6149e60..f633fe9b6 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -1,17 +1,16 @@ +// Reader and writer for `QOI` images. +// +// The QOI specification is at [[ https://qoiformat.org ]]. +package qoi + /* Copyright 2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. */ - -// package qoi implements a QOI image reader -// -// The QOI specification is at [[ https://qoiformat.org ]]. -package qoi - import "core:image" import "core:compress" import "core:bytes" @@ -371,6 +370,6 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) { } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.QOI, load_from_bytes, destroy) } diff --git a/core/image/qoi/qoi_js.odin b/core/image/qoi/qoi_js.odin index 4a69e98a0..19ee2e04d 100644 --- a/core/image/qoi/qoi_js.odin +++ b/core/image/qoi/qoi_js.odin @@ -1,4 +1,3 @@ -#+build js package qoi save :: proc{save_to_buffer} diff --git a/core/image/qoi/qoi_os.odin b/core/image/qoi/qoi_os.odin index c85fdd839..f2bf83cfc 100644 --- a/core/image/qoi/qoi_os.odin +++ b/core/image/qoi/qoi_os.odin @@ -4,8 +4,22 @@ package qoi import "core:os" import "core:bytes" -save :: proc{save_to_buffer, save_to_file} +load :: proc{load_from_file, load_from_bytes, load_from_context} +load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { + context.allocator = allocator + + data, data_err := os.read_entire_file(filename, allocator) + defer delete(data, allocator) + + if data_err == nil { + return load_from_bytes(data, options) + } else { + return nil, .Unable_To_Read_File + } +} + +save :: proc{save_to_buffer, save_to_file} save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) { context.allocator = allocator @@ -14,24 +28,7 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato defer bytes.buffer_destroy(out) save_to_buffer(out, img, options) or_return - write_ok := os.write_entire_file(output, out.buf[:]) + write_err := os.write_entire_file(output, out.buf[:]) - return nil if write_ok else .Unable_To_Write_File -} - - -load :: proc{load_from_file, load_from_bytes, load_from_context} - - -load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { - context.allocator = allocator - - data, ok := os.read_entire_file(filename) - defer delete(data) - - if ok { - return load_from_bytes(data, options) - } else { - return nil, .Unable_To_Read_File - } + return nil if write_err == nil else .Unable_To_Write_File } \ No newline at end of file diff --git a/core/image/tga/tga.odin b/core/image/tga/tga.odin index 46e37a0cf..1941b53f9 100644 --- a/core/image/tga/tga.odin +++ b/core/image/tga/tga.odin @@ -1,16 +1,15 @@ +// Reader and writer for 8-bit RGB and RGBA `TGA` images. +package tga + /* Copyright 2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. Benoit Jacquier: tga loader */ - -// package tga implements a TGA image writer for 8-bit RGB and RGBA images. -package tga - import "core:mem" import "core:image" import "core:bytes" @@ -153,7 +152,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a // Intentionally blank case .Uncompressed_Black_White: black_white = true - dest_depth = 24 + dest_depth = 8 if .do_not_expand_grayscale in options else 24 case .Uncompressed_Color_Mapped: color_mapped = true case .Compressed_Color_Mapped: @@ -162,7 +161,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a case .Compressed_Black_White: black_white = true rle_encoding = true - dest_depth = 24 + dest_depth = 8 if .do_not_expand_grayscale in options else 24 case: return nil, .Unsupported_Format @@ -181,6 +180,9 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a } switch dest_depth { + case 8: // R8 + src_channels = 1 + dest_channels = 1 case 15: // B5G5R5 src_channels = 2 dest_channels = 3 @@ -406,6 +408,6 @@ IMAGE_DESCRIPTOR_RIGHT_MASK :: 1<<4 IMAGE_DESCRIPTOR_TOP_MASK :: 1<<5 @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.TGA, load_from_bytes, destroy) } \ No newline at end of file diff --git a/core/image/tga/tga_js.odin b/core/image/tga/tga_js.odin index 9261be8c6..2ab95eaa8 100644 --- a/core/image/tga/tga_js.odin +++ b/core/image/tga/tga_js.odin @@ -1,4 +1,3 @@ -#+build js package tga save :: proc{save_to_buffer} diff --git a/core/image/tga/tga_os.odin b/core/image/tga/tga_os.odin index a78998105..ba50439de 100644 --- a/core/image/tga/tga_os.odin +++ b/core/image/tga/tga_os.odin @@ -4,6 +4,21 @@ package tga import "core:os" import "core:bytes" +load :: proc{load_from_file, load_from_bytes, load_from_context} + +load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { + context.allocator = allocator + + data, data_err := os.read_entire_file(filename, allocator) + defer delete(data) + + if data_err == nil { + return load_from_bytes(data, options) + } else { + return nil, .Unable_To_Read_File + } +} + save :: proc{save_to_buffer, save_to_file} save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) { @@ -13,22 +28,7 @@ save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocato defer bytes.buffer_destroy(out) save_to_buffer(out, img, options) or_return - write_ok := os.write_entire_file(output, out.buf[:]) + write_err := os.write_entire_file(output, out.buf[:]) - return nil if write_ok else .Unable_To_Write_File -} - -load :: proc{load_from_file, load_from_bytes, load_from_context} - -load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) { - context.allocator = allocator - - data, ok := os.read_entire_file(filename) - defer delete(data) - - if ok { - return load_from_bytes(data, options) - } else { - return nil, .Unable_To_Read_File - } + return nil if write_err == nil else .Unable_To_Write_File } \ No newline at end of file diff --git a/core/io/io.odin b/core/io/io.odin index c2b44cbdb..631a232aa 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -1,10 +1,11 @@ -// package io provides basic interfaces for generic data stream primitives. +// Basic interfaces for generic data stream primitives. // The purpose of this package is wrap existing data structures and their // operations into an abstracted stream interface. package io import "base:intrinsics" import "core:unicode/utf8" +import "core:unicode/utf16" // Seek whence values Seek_From :: enum { @@ -37,8 +38,11 @@ Error :: enum i32 { // This is usually a sign of a broken `io.Reader` implementation No_Progress, + // Invalid whence argument Invalid_Whence, + // Invalid offset Invalid_Offset, + // Invalid "unread" operation Invalid_Unread, Negative_Read, @@ -49,8 +53,19 @@ Error :: enum i32 { // Unknown means that an error has occurred but cannot be categorized Unknown, - // Empty is returned when a procedure has not been implemented for an io.Stream - Empty = -1, + // Indicates that an attempt to retrieve a Stream's size was made, but the + // stream doesn't have a size. + No_Size, + + Permission_Denied, + + // Stream cannot be used since it has been Closed + Closed, + + // Unsupported is returned when a procedure has not been implemented for an io.Stream + Unsupported = -1, + + Empty = Unsupported, } Stream_Mode :: enum { @@ -101,7 +116,7 @@ destroy :: proc(s: Stream) -> (err: Error) { if s.procedure != nil { _, err = s.procedure(s.data, .Destroy, nil, 0, nil) } else { - err = .Empty + err = .Unsupported } return } @@ -137,7 +152,7 @@ read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) { n = int(n64) if n_read != nil { n_read^ += n } } else { - err = .Empty + err = .Unsupported } return } @@ -150,7 +165,7 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro n = int(n64) if n_written != nil { n_written^ += n } } else { - err = .Empty + err = .Unsupported } return } @@ -166,7 +181,7 @@ seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) if s.procedure != nil { n, err = s.procedure(s.data, .Seek, nil, offset, whence) } else { - err = .Empty + err = .Unsupported } return } @@ -191,7 +206,7 @@ flush :: proc(s: Flusher) -> (err: Error) { size :: proc(s: Stream) -> (n: i64, err: Error) { if s.procedure != nil { n, err = s.procedure(s.data, .Size, nil, 0, nil) - if err == .Empty { + if err == .Unsupported { n = 0 curr := seek(s, 0, .Current) or_return end := seek(s, 0, .End) or_return @@ -199,7 +214,7 @@ size :: proc(s: Stream) -> (n: i64, err: Error) { n = end } } else { - err = .Empty + err = .Unsupported } return } @@ -216,7 +231,7 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: if r.procedure != nil { n64: i64 n64, err = r.procedure(r.data, .Read_At, p, offset, nil) - if err != .Empty { + if err != .Unsupported { n = int(n64) } else { curr := seek(r, offset, .Current) or_return @@ -228,7 +243,7 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: } if n_read != nil { n_read^ += n } } else { - err = .Empty + err = .Unsupported } return } @@ -242,7 +257,7 @@ write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> if w.procedure != nil { n64: i64 n64, err = w.procedure(w.data, .Write_At, p, offset, nil) - if err != .Empty { + if err != .Unsupported { n = int(n64) } else { curr := seek(w, offset, .Current) or_return @@ -254,7 +269,7 @@ write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> } if n_written != nil { n_written^ += n } } else { - err = .Empty + err = .Unsupported } return } @@ -314,6 +329,29 @@ write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, return write(s, transmute([]byte)str, n_written) } +// write_string16 writes the contents of the string16 s to w reencoded as utf-8 +write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: int, err: Error) { + for i := 0; i < len(str); i += 1 { + r := rune(utf16.REPLACEMENT_CHAR) + switch c := str[i]; { + case c < utf16._surr1, utf16._surr3 <= c: + r = rune(c) + case utf16._surr1 <= c && c < utf16._surr2 && i+1 < len(str) && + utf16._surr2 <= str[i+1] && str[i+1] < utf16._surr3: + r = utf16.decode_surrogate_pair(rune(c), rune(str[i+1])) + i += 1 + } + + w: int + w, err = write_rune(s, r, n_written) + n += w + if err != nil { + return + } + } + return +} + // write_rune writes a UTF-8 encoded rune to w. write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) { defer if err == nil && n_written != nil { @@ -398,7 +436,7 @@ copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err // copy_n copies n bytes (or till an error) from src to dst. // It returns the number of bytes copied and the first error that occurred whilst copying, if any. -// On return, written == n IFF err == nil +// On return, written == n if and only if (⟺) err == nil copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) { nsrc := limited_reader_init(&Limited_Reader{}, src, n) written, err = copy(dst, nsrc) @@ -416,7 +454,7 @@ copy_n :: proc(dst: Writer, src: Reader, n: i64) -> (written: i64, err: Error) { @(private) _copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, err: Error) { if dst.procedure == nil || src.procedure == nil { - return 0, .Empty + return 0, .Unsupported } buf := buf if buf == nil { diff --git a/core/io/multi.odin b/core/io/multi.odin index e25e8133e..abd9b9c5e 100644 --- a/core/io/multi.odin +++ b/core/io/multi.odin @@ -8,7 +8,7 @@ _multi_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, of if mode == .Query { return query_utility({.Read, .Query}) } else if mode != .Read { - return 0, .Empty + return 0, .Unsupported } mr := (^Multi_Reader)(stream_data) for len(mr.readers) > 0 { @@ -61,7 +61,7 @@ _multi_writer_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, of if mode == .Query { return query_utility({.Write, .Query}) } else if mode != .Write { - return 0, .Empty + return 0, .Unsupported } mw := (^Multi_Writer)(stream_data) for w in mw.writers { diff --git a/core/io/util.odin b/core/io/util.odin index fdbbd5b9f..35297c121 100644 --- a/core/io/util.odin +++ b/core/io/util.odin @@ -8,6 +8,11 @@ read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n return read(r, ([^]byte)(p)[:byte_size], n_read) } +read_slice :: proc(r: Reader, slice: $S/[]$T, n_read: ^int = nil) -> (n: int, err: Error) { + size := len(slice)*size_of(T) + return read_ptr(r, raw_data(slice), size, n_read) +} + write_ptr :: proc(w: Writer, p: rawptr, byte_size: int, n_written: ^int = nil) -> (n: int, err: Error) { return write(w, ([^]byte)(p)[:byte_size], n_written) } @@ -20,14 +25,20 @@ write_ptr_at :: proc(w: Writer_At, p: rawptr, byte_size: int, offset: i64, n_wri return write_at(w, ([^]byte)(p)[:byte_size], offset, n_written) } +write_slice :: proc(w: Writer, slice: $S/[]$T, n_written: ^int = nil) -> (n: int, err: Error) { + size := len(slice)*size_of(T) + return write_ptr(w, raw_data(slice), size, n_written) +} + + write_u64 :: proc(w: Writer, i: u64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) { - buf: [32]byte - s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil) + buf: [64]byte + s := strconv.write_bits(buf[:], i, base, false, 64, strconv.digits, nil) return write_string(w, s, n_written) } write_i64 :: proc(w: Writer, i: i64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) { - buf: [32]byte - s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) + buf: [65]byte + s := strconv.write_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) return write_string(w, s, n_written) } @@ -39,19 +50,19 @@ write_int :: proc(w: Writer, i: int, base: int = 10, n_written: ^int = nil) -> ( } write_u128 :: proc(w: Writer, i: u128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) { - buf: [39]byte - s := strconv.append_bits_128(buf[:], i, base, false, 128, strconv.digits, nil) + buf: [128]byte + s := strconv.write_bits_128(buf[:], i, base, false, 128, strconv.digits, nil) return write_string(w, s, n_written) } write_i128 :: proc(w: Writer, i: i128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) { - buf: [40]byte - s := strconv.append_bits_128(buf[:], u128(i), base, true, 128, strconv.digits, nil) + buf: [129]byte + s := strconv.write_bits_128(buf[:], u128(i), base, true, 128, strconv.digits, nil) return write_string(w, s, n_written) } write_f16 :: proc(w: Writer, val: f16, n_written: ^int = nil) -> (n: int, err: Error) { buf: [386]byte - str := strconv.append_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val)) + str := strconv.write_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val)) s := buf[:len(str)+1] if s[1] == '+' || s[1] == '-' { s = s[1:] @@ -67,7 +78,7 @@ write_f16 :: proc(w: Writer, val: f16, n_written: ^int = nil) -> (n: int, err: E write_f32 :: proc(w: Writer, val: f32, n_written: ^int = nil) -> (n: int, err: Error) { buf: [386]byte - str := strconv.append_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val)) + str := strconv.write_float(buf[1:], f64(val), 'f', 2*size_of(val), 8*size_of(val)) s := buf[:len(str)+1] if s[1] == '+' || s[1] == '-' { s = s[1:] @@ -83,7 +94,7 @@ write_f32 :: proc(w: Writer, val: f32, n_written: ^int = nil) -> (n: int, err: E write_f64 :: proc(w: Writer, val: f64, n_written: ^int = nil) -> (n: int, err: Error) { buf: [386]byte - str := strconv.append_float(buf[1:], val, 'f', 2*size_of(val), 8*size_of(val)) + str := strconv.write_float(buf[1:], val, 'f', 2*size_of(val), 8*size_of(val)) s := buf[:len(str)+1] if s[1] == '+' || s[1] == '-' { s = s[1:] @@ -130,7 +141,7 @@ write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^ write_string(w, `\x`, &n) or_return buf: [2]byte - s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil) + s := strconv.write_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil) switch len(s) { case 0: write_string(w, "00", &n) or_return @@ -189,6 +200,23 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, write_encoded_rune(w, r, false, &n) or_return return } + if r < 32 && for_json { + switch r { + case '\b': write_string(w, `\b`, &n) or_return + case '\f': write_string(w, `\f`, &n) or_return + case '\n': write_string(w, `\n`, &n) or_return + case '\r': write_string(w, `\r`, &n) or_return + case '\t': write_string(w, `\t`, &n) or_return + case: + write_byte(w, '\\', &n) or_return + write_byte(w, 'u', &n) or_return + write_byte(w, '0', &n) or_return + write_byte(w, '0', &n) or_return + write_byte(w, DIGITS_LOWER[r>>4 & 0xf], &n) or_return + write_byte(w, DIGITS_LOWER[r & 0xf], &n) or_return + } + return + } switch r { case '\a': write_string(w, `\a`, &n) or_return case '\b': write_string(w, `\b`, &n) or_return @@ -264,6 +292,33 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written return } +write_quoted_string16 :: proc(w: Writer, str: string16, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) { + defer if n_written != nil { + n_written^ += n + } + write_byte(w, quote, &n) or_return + for width, s := 0, str; len(s) > 0; s = s[width:] { + r := rune(s[0]) + width = 1 + if r >= utf8.RUNE_SELF { + r, width = utf16.decode_rune_in_string(s) + } + if width == 1 && r == utf8.RUNE_ERROR { + write_byte(w, '\\', &n) or_return + write_byte(w, 'x', &n) or_return + write_byte(w, DIGITS_LOWER[s[0]>>4], &n) or_return + write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return + continue + } + + n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return + + } + write_byte(w, quote, &n) or_return + return +} + + // writer append a quoted rune into the byte buffer, return the written size write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) { _write_byte :: #force_inline proc(w: Writer, c: byte) -> int { @@ -310,7 +365,7 @@ _tee_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, offs case .Query: return query_utility({.Read, .Query}) } - return 0, .Empty + return 0, .Unsupported } // tee_reader_init returns a Reader that writes to 'w' what it reads from 'r' @@ -360,7 +415,7 @@ _limited_reader_proc :: proc(stream_data: rawptr, mode: Stream_Mode, p: []byte, case .Query: return query_utility({.Read, .Query}) } - return 0, .Empty + return 0, .Unsupported } limited_reader_init :: proc(l: ^Limited_Reader, r: Reader, n: i64) -> Reader { diff --git a/core/log/console_logger_js.odin b/core/log/console_logger_js.odin new file mode 100644 index 000000000..1e07b6cdc --- /dev/null +++ b/core/log/console_logger_js.odin @@ -0,0 +1,119 @@ +#+build js +package log + +import "core:fmt" +import "core:strings" +import "core:time" + +Level_Headers := [?]string{ + 0..<10 = "[DEBUG] --- ", + 10..<20 = "[INFO ] --- ", + 20..<30 = "[WARN ] --- ", + 30..<40 = "[ERROR] --- ", + 40..<50 = "[FATAL] --- ", +} + +Default_Console_Logger_Opts :: Options{ + .Level, + .Short_File_Path, + .Line, + .Procedure, +} | Full_Timestamp_Opts + +Console_Logger_Data :: struct { + ident: string, +} + +create_console_logger :: proc(lowest := Level.Debug, opt := Default_Console_Logger_Opts, ident := "", allocator := context.allocator) -> Logger { + data := new(Console_Logger_Data, allocator) + data.ident = strings.clone(ident) + return Logger{console_logger_proc, data, lowest, opt} +} + +destroy_console_logger :: proc(log: Logger, allocator := context.allocator) { + data := cast(^Console_Logger_Data)log.data + delete(data.ident) + free(log.data, allocator) +} + +console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { + options := options + data := cast(^Console_Logger_Data)logger_data + + backing: [1024]byte //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths. + buf := strings.builder_from_bytes(backing[:]) + + if .Level in options { + fmt.sbprint(&buf, Level_Headers[level]) + } + + when time.IS_SUPPORTED { + do_time_header(options, &buf, time.now()) + } + + do_location_header(options, &buf, location) + + if data.ident != "" { + fmt.sbprintf(&buf, "[%s] ", data.ident) + } + + h := fmt.stderr if level >= .Error else fmt.stdout + + //TODO(Hoej): When we have better atomics and such, make this thread-safe + fmt.fprintf(h, "%s%s\n", strings.to_string(buf), text) +} + +do_time_header :: proc(opts: Options, buf: ^strings.Builder, t: time.Time) { + when time.IS_SUPPORTED { + if Full_Timestamp_Opts & opts != nil { + fmt.sbprint(buf, "[") + y, m, d := time.date(t) + h, min, s := time.clock(t) + if .Date in opts { + fmt.sbprintf(buf, "%d-%02d-%02d", y, m, d) + if .Time in opts { + fmt.sbprint(buf, " ") + } + } + if .Time in opts { fmt.sbprintf(buf, "%02d:%02d:%02d", h, min, s) } + fmt.sbprint(buf, "] ") + } + } +} + +do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #caller_location) { + if Location_Header_Opts & opts == nil { + return + } + fmt.sbprint(buf, "[") + + file := location.file_path + if .Short_File_Path in opts { + last := 0 + for r, i in location.file_path { + if r == '/' { + last = i+1 + } + } + file = location.file_path[last:] + } + + if Location_File_Opts & opts != nil { + fmt.sbprint(buf, file) + } + if .Line in opts { + if Location_File_Opts & opts != nil { + fmt.sbprint(buf, ":") + } + fmt.sbprint(buf, location.line) + } + + if .Procedure in opts { + if (Location_File_Opts | {.Line}) & opts != nil { + fmt.sbprint(buf, ":") + } + fmt.sbprintf(buf, "%s()", location.procedure) + } + + fmt.sbprint(buf, "] ") +} \ No newline at end of file diff --git a/core/log/doc.odin b/core/log/doc.odin new file mode 100644 index 000000000..d0e45bd93 --- /dev/null +++ b/core/log/doc.odin @@ -0,0 +1,68 @@ +/* +Implementation of logging facilities. + +Odin has builtin support for logging using procedure `context`. After a logger is created it can then be assigned to +`context.logger` and used implicitly in future log calls. + +While it is ok for simple apps to use the `core:fmt` package, libraries and complex apps should prefer the `core:log` +package. By using the implicit logger library and application authors allow the caller to decide how to process log +messages. + +When starting out you can easily just init the logger with a single line. +Example: + + package main + + import "core:log" + + main :: proc() { + context.logger = log.create_console_logger() + log.info("Hello World!") + } + +However when the application gets more involved you might want to try a more complex setup. +Example: + + package main + + import "core:log" + import "core:os" + + main :: proc() { + handle, err := os.open("logs.txt", os.O_RDWR | os.O_APPEND | os.O_CREATE, 0o666) + assert(err == nil, "Cannot open log file") + + file_logger := log.create_file_logger(handle) + // This closes the file handle + defer log.destroy_file_logger(file_logger) + + console_logger := log.create_console_logger() + defer log.destroy_console_logger(console_logger) + + multi_logger := log.create_multi_logger(console_logger, file_logger) + defer log.destroy_multi_logger(multi_logger) + + context.logger = multi_logger + + log.info("Application started!") + } + +It is also possible to create an allocator that logs all allocations. +Example: + + package main + + import "core:log" + + main :: proc() { + context.logger = log.create_console_logger() + + alloc: log.Log_Allocator + log.log_allocator_init(&alloc, .Debug) + context.allocator = log.log_allocator(&alloc) + + a := new(i32) + free(a) + } +*/ +package log \ No newline at end of file diff --git a/core/log/file_console_logger.odin b/core/log/file_console_logger.odin index 6d93fb879..b7220ad30 100644 --- a/core/log/file_console_logger.odin +++ b/core/log/file_console_logger.odin @@ -1,13 +1,17 @@ #+build !freestanding #+build !orca +#+build !js package log -import "core:encoding/ansi" +import "base:runtime" import "core:fmt" import "core:strings" import "core:os" +import "core:terminal" +import "core:terminal/ansi" import "core:time" +// Strings to output when `.Level` is included in the logger options. Level_Headers := [?]string{ 0..<10 = "[DEBUG] --- ", 10..<20 = "[INFO ] --- ", @@ -16,59 +20,151 @@ Level_Headers := [?]string{ 40..<50 = "[FATAL] --- ", } +/* +The default option set for a console logger. + +It is similar to the file logger default option set, but the output includes colors. + +When you use this set of options you can expect the following output: + + [LEVEL] --- [YYYY-MM-DD HH:MM:SS] [file.odin:L:proc()] Message + +For example: + + [INFO ] --- [2025-01-02 12:34:56] [main.odin:8:main()] Hello World! +*/ Default_Console_Logger_Opts :: Options{ .Level, .Terminal_Color, .Short_File_Path, .Line, .Procedure, -} | Full_Timestamp_Opts +} + Full_Timestamp_Opts +/* +The default option set for a file logger. + +It is similar to the console logger default option set, but the output is not colored. + +When you use this set of options you can expect the following output: + + [LEVEL] --- [YYYY-MM-DD HH:MM:SS] [file.odin:L:proc()] Message + +For example: + + [INFO ] --- [2025-01-02 12:34:56] [main.odin:8:main()] Hello World! +*/ Default_File_Logger_Opts :: Options{ .Level, .Short_File_Path, .Line, .Procedure, -} | Full_Timestamp_Opts +} + Full_Timestamp_Opts +//Data backing a file or console logger. File_Console_Logger_Data :: struct { - file_handle: os.Handle, + file_handle: ^os.File, ident: string, } -create_file_logger :: proc(h: os.Handle, lowest := Level.Debug, opt := Default_File_Logger_Opts, ident := "", allocator := context.allocator) -> Logger { - data := new(File_Console_Logger_Data, allocator) - data.file_handle = h - data.ident = ident - return Logger{file_console_logger_proc, data, lowest, opt} +@(private) global_subtract_stdout_options: Options +@(private) global_subtract_stderr_options: Options + +@(init, private) +init_standard_stream_status :: proc "contextless" () { + // NOTE(Feoramund): While it is technically possible for these streams to + // be redirected during the runtime of the program, the cost of checking on + // every single log message is not worth it to support such an + // uncommonly-used feature. + if terminal.color_enabled { + context = runtime.default_context() + + // This is done this way because it's possible that only one of these + // streams could be redirected to a file. + if !terminal.is_terminal(os.stdout) { + global_subtract_stdout_options = {.Terminal_Color} + } + if !terminal.is_terminal(os.stderr) { + global_subtract_stderr_options = {.Terminal_Color} + } + } else { + // Override any terminal coloring. + global_subtract_stdout_options = {.Terminal_Color} + global_subtract_stderr_options = {.Terminal_Color} + } } + +/* +Create a logger that outputs to a file. + +*Allocates Using Provided Allocator* + +When no longer needed can be destroyed with `destroy_file_logger`. + +Inputs: +- `h`: A handle to the output file +- `lowest`: Log level to use (default is `.Debug`) +- `opt`: Specifies additional data present in the log output (default is `log.Default_File_Logger_Opts`) +- `ident`: Identifier to include in the output (default is `""`) +- `allocator`: Allocator to use for data backing the logger (default is `context.allocator`) +*/ +create_file_logger :: proc(f: ^os.File, lowest := Level.Debug, opt := Default_File_Logger_Opts, ident := "", allocator := context.allocator) -> Logger { + data := new(File_Console_Logger_Data, allocator) + data.file_handle = f + data.ident = ident + return Logger{file_logger_proc, data, lowest, opt} +} + +/* +Free the state allocated with `create_file_logger` and close the file handle. + +Inputs: +- `log`: Logger created with `create_file_logger` +- `allocator`: Allocator passed to `create_file_logger` (default is `context.allocator`) +*/ destroy_file_logger :: proc(log: Logger, allocator := context.allocator) { data := cast(^File_Console_Logger_Data)log.data - if data.file_handle != os.INVALID_HANDLE { + if data.file_handle != nil { os.close(data.file_handle) } free(data, allocator) } +/* +Create a logger that outputs to the terminal. + +*Allocates Using Provided Allocator* + +When no longer needed can be destroyed with `destroy_console_logger`. + +Inputs: +- `lowest`: Log level to use (default is `.Debug`) +- `opt`: Specifies additional data present in the log output (default is `log.Default_Console_Logger_Opts`) +- `ident`: Identifier to include in the output (default is `""`) +- `allocator`: Allocator to use for data backing the logger (default is `context.allocator`) +*/ create_console_logger :: proc(lowest := Level.Debug, opt := Default_Console_Logger_Opts, ident := "", allocator := context.allocator) -> Logger { data := new(File_Console_Logger_Data, allocator) - data.file_handle = os.INVALID_HANDLE + data.file_handle = nil data.ident = ident - return Logger{file_console_logger_proc, data, lowest, opt} + return Logger{console_logger_proc, data, lowest, opt} } +/* +Free the state allocated with `create_console_logger`. + +Inputs: +- `log`: Logger created with `create_console_logger` +- `allocator`: Allocator passed to `create_console_logger` (default is `context.allocator`) +*/ destroy_console_logger :: proc(log: Logger, allocator := context.allocator) { free(log.data, allocator) } -file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { - data := cast(^File_Console_Logger_Data)logger_data - h: os.Handle = os.stdout if level <= Level.Error else os.stderr - if data.file_handle != os.INVALID_HANDLE { - h = data.file_handle - } +@(private) +_file_console_logger_proc :: proc(h: ^os.File, ident: string, level: Level, text: string, options: Options, location: runtime.Source_Code_Location) { backing: [1024]byte //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths. buf := strings.builder_from_bytes(backing[:]) @@ -81,18 +177,37 @@ file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string do_location_header(options, &buf, location) if .Thread_Id in options { - // NOTE(Oskar): not using context.thread_id here since that could be - // incorrect when replacing context for a thread. - fmt.sbprintf(&buf, "[{}] ", os.current_thread_id()) + fmt.sbprintf(&buf, "[{}] ", os.get_current_thread_id()) } - if data.ident != "" { - fmt.sbprintf(&buf, "[%s] ", data.ident) + if ident != "" { + fmt.sbprintf(&buf, "[%s] ", ident) } //TODO(Hoej): When we have better atomics and such, make this thread-safe fmt.fprintf(h, "%s%s\n", strings.to_string(buf), text) } + +file_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { + data := cast(^File_Console_Logger_Data)logger_data + _file_console_logger_proc(data.file_handle, data.ident, level, text, options, location) +} + +console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { + options := options + data := cast(^File_Console_Logger_Data)logger_data + h: ^os.File = nil + if level < Level.Error { + h = os.stdout + options -= global_subtract_stdout_options + } else { + h = os.stderr + options -= global_subtract_stderr_options + } + _file_console_logger_proc(h, data.ident, level, text, options, location) +} + +// Helper used to build the part of the message including the log level. do_level_header :: proc(opts: Options, str: ^strings.Builder, level: Level) { RESET :: ansi.CSI + ansi.RESET + ansi.SGR @@ -119,6 +234,7 @@ do_level_header :: proc(opts: Options, str: ^strings.Builder, level: Level) { } } +// Helper used to build the part of the message including the data and time. do_time_header :: proc(opts: Options, buf: ^strings.Builder, t: time.Time) { when time.IS_SUPPORTED { if Full_Timestamp_Opts & opts != nil { @@ -137,6 +253,7 @@ do_time_header :: proc(opts: Options, buf: ^strings.Builder, t: time.Time) { } } +// Helper used to build the part of the message including the file location. do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #caller_location) { if Location_Header_Opts & opts == nil { return @@ -172,4 +289,4 @@ do_location_header :: proc(opts: Options, buf: ^strings.Builder, location := #ca } fmt.sbprint(buf, "] ") -} +} \ No newline at end of file diff --git a/core/log/log.odin b/core/log/log.odin index 2b6317060..ce0f49124 100644 --- a/core/log/log.odin +++ b/core/log/log.odin @@ -4,48 +4,99 @@ import "base:runtime" import "core:fmt" -// NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle. +//These are defined in package `base:runtime` as they are used in the `context`. This is to prevent an import definition cycle. /* -Logger_Level :: enum { - Debug = 0, - Info = 10, - Warning = 20, - Error = 30, - Fatal = 40, -} + Logger_Level :: enum { + Debug = 0, + Info = 10, + Warning = 20, + Error = 30, + Fatal = 40, + } */ Level :: runtime.Logger_Level /* -Option :: enum { - Level, - Date, - Time, - Short_File_Path, - Long_File_Path, - Line, - Procedure, - Terminal_Color -} +Specifies additional data present in the log output. + +Defined in `package runtime` as it is used in the `context`. This is to prevent an import definition cycle. + + Option :: enum { + // The log level, e.g. "[DEBUG] ---" + Level, + // The date, e.g. [2025-01-02] + Date, + // The time, e.g. [12:34:56] + Time, + // Just the filename, e.g. [main.odin] + Short_File_Path, + // Full file path, e.g. [/tmp/project/main.odin] + Long_File_Path, + // File line of the log statement, e.g. [8] + Line, + // Calling procedure, e.g. [main()] + Procedure, + // Enables colored output + Terminal_Color + } */ Option :: runtime.Logger_Option /* -Options :: bit_set[Option]; +Specifies additional data present in the log output. + +Defined in `package runtime` as it is used in the `context`. This is to prevent an import definition cycle. + + Options :: bit_set[Option]; */ Options :: runtime.Logger_Options +/* +A preset option set for a logger. + +When you use this set of options you can expect the following output: + + [YYYY-MM-DD HH:MM:SS] Message + +For example: + + [2025-01-02 12:34:56] Hello World! +*/ Full_Timestamp_Opts :: Options{ .Date, .Time, } + +/* +A preset option set for a logger. + +When you use this set of options you can expect the following output: + + [file.odin:L:proc()] Message + +For example: + + [main.odin:8:main()] Hello World! +*/ Location_Header_Opts :: Options{ .Short_File_Path, .Long_File_Path, .Line, .Procedure, } + +/* +A preset option set for a logger. + +When you use this set of options you can expect the following output: + + [file.odin] Message + +For example: + + [main.odin] Hello World! +*/ Location_File_Opts :: Options{ .Short_File_Path, .Long_File_Path, @@ -53,67 +104,206 @@ Location_File_Opts :: Options{ /* -Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location); +Implementation of the logger. + +Defined in `package runtime` as it is used in the `context`. This is to prevent an import definition cycle. + + Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location); + */ Logger_Proc :: runtime.Logger_Proc /* -Logger :: struct { - procedure: Logger_Proc, - data: rawptr, - lowest_level: Level, - options: Logger_Options, -} +Data backing the logger. + +Defined in `package runtime` as it is used in the `context`. This is to prevent an import definition cycle. + + Logger :: struct { + // Implementation + procedure: Logger_Proc, + // Configuration data passed to the implementation + data: rawptr, + // Minimum level for messages passed to the implementation + lowest_level: Level, + // Additional data present in the log output + options: Logger_Options, + } */ Logger :: runtime.Logger +/* +Do nothing. + +Defined in `package runtime` as it is used in the `context`. This is to prevent an import definition cycle. +*/ nil_logger_proc :: runtime.default_logger_proc +/* +Create a logger that does nothing. + +Returns: +- A logger that does nothing +*/ nil_logger :: proc() -> Logger { return Logger{nil_logger_proc, nil, Level.Debug, nil} } + +/* +Log a formatted message at the `Debug` level. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) { logf(.Debug, fmt_str, ..args, location=location) } + +/* +Log a formatted message at the `Info` level. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ infof :: proc(fmt_str: string, args: ..any, location := #caller_location) { logf(.Info, fmt_str, ..args, location=location) } + +/* +Log a formatted message at the `Warn` level. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) { logf(.Warning, fmt_str, ..args, location=location) } + +/* +Log a formatted message at the `Error` level. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) { logf(.Error, fmt_str, ..args, location=location) } + +/* +Log a formatted message at the `Fatal` level. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) { logf(.Fatal, fmt_str, ..args, location=location) } +/* +Log a message at the `Debug` level. + +Inputs: +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ debug :: proc(args: ..any, sep := " ", location := #caller_location) { log(.Debug, ..args, sep=sep, location=location) } + +/* +Log a message at the `Info` level. + +Inputs: +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ info :: proc(args: ..any, sep := " ", location := #caller_location) { log(.Info, ..args, sep=sep, location=location) } + +/* +Log a message at the `Warn` level. + +Inputs: +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ warn :: proc(args: ..any, sep := " ", location := #caller_location) { log(.Warning, ..args, sep=sep, location=location) } + +/* +Log a message at the `Error` level. + +Inputs: +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ error :: proc(args: ..any, sep := " ", location := #caller_location) { log(.Error, ..args, sep=sep, location=location) } + +/* +Log a message at the `Fatal` level. + +Inputs: +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ fatal :: proc(args: ..any, sep := " ", location := #caller_location) { log(.Fatal, ..args, sep=sep, location=location) } +/* +Log a message at the `Fatal` level and abort the program. + +Inputs: +- `args`: values to be concatenated into the output +- `location`: Location of the caller (default is #caller_location) +*/ panic :: proc(args: ..any, location := #caller_location) -> ! { log(.Fatal, ..args, location=location) runtime.panic("log.panic", location) } + +/* +Log a formatted message at the `Fatal` level and abort the program. + +Inputs: +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! { logf(.Fatal, fmt_str, ..args, location=location) runtime.panic("log.panicf", location) } +/* +When condition is `false` log a message at the `Fatal` level and abort the program. + +Can be disabled using `ODIN_DISABLE_ASSERT`. + +Inputs: +- `condition`: A boolean to check +- `message`: Message to log when condition is false (a default is provided) +- `loc`: Location of the caller (default is #caller_location) +*/ @(disabled=ODIN_DISABLE_ASSERT) assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) { if !condition { @@ -130,6 +320,17 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc := } } +/* +When condition is `false` log a formatted message at the `Fatal` level and abort the program. + +Can be disabled using `ODIN_DISABLE_ASSERT`. + +Inputs: +- `condition`: A boolean to check +- `fmt_str`: A format string to use when condition is false, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `loc`: Location of the caller (default is #caller_location) +*/ @(disabled=ODIN_DISABLE_ASSERT) assertf :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_location) { if !condition { @@ -151,6 +352,16 @@ assertf :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_lo } } +/* +When condition is `false` log a message at the `Fatal` level and abort the program. + +Unlike `assert` this procedure cannot be disabled with `ODIN_DISABLE_ASSERT` and will always execute. + +Inputs: +- `condition`: A boolean to check +- `message`: Message to log when condition is false (a default is provided) +- `loc`: Location of the caller (default is #caller_location) +*/ ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) { if !condition { @(cold) @@ -166,6 +377,17 @@ ensure :: proc(condition: bool, message := #caller_expression(condition), loc := } } +/* +When condition is `false` log a formatted message at the `Fatal` level and abort the program. + +Unlike `assertf` this procedure cannot be disabled with `ODIN_DISABLE_ASSERT` and will always execute. + +Inputs: +- `condition`: A boolean to check +- `fmt_str`: A format string to use when condition is false, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `loc`: Location of the caller (default is #caller_location) +*/ ensuref :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_location) { if !condition { @(cold) @@ -183,7 +405,15 @@ ensuref :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_lo } +/* +Log a message at the desired level. +Inputs: +- `level`: The level of the message +- `args`: values to be concatenated into the output +- `sep`: separator to use when concatenating (default is `" "`) +- `location`: Location of the caller (default is #caller_location) +*/ log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location) { logger := context.logger if logger.procedure == nil || logger.procedure == nil_logger_proc { @@ -193,10 +423,19 @@ log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location) return } runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - str := fmt.tprint(..args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is. + str := fmt.tprint(..args, sep=sep) logger.procedure(logger.data, level, str, logger.options, location) } +/* +Log a formatted message at the desired level. + +Inputs: +- `level`: The level of the message +- `fmt_str`: A format string, e.g. `"a: %v, b: %v" +- `args`: Arguments for the format string +- `location`: Location of the caller (default is #caller_location) +*/ logf :: proc(level: Level, fmt_str: string, args: ..any, location := #caller_location) { logger := context.logger if logger.procedure == nil || logger.procedure == nil_logger_proc { diff --git a/core/log/log_allocator.odin b/core/log/log_allocator.odin index 16f1abe31..a6784133b 100644 --- a/core/log/log_allocator.odin +++ b/core/log/log_allocator.odin @@ -1,31 +1,56 @@ +#+build !freestanding + package log import "base:runtime" import "core:fmt" +import "core:sync" +// Format to use when logging allocations. Log_Allocator_Format :: enum { Bytes, // Actual number of bytes. Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate. } + +// Log_Allocator is an allocator which calls `context.logger` on each of its allocations operations. +// The format can be changed by setting the `size_fmt: Log_Allocator_Format` field to either `Bytes` or `Human`. Log_Allocator :: struct { - allocator: runtime.Allocator, - level: Level, - prefix: string, - locked: bool, - size_fmt: Log_Allocator_Format, + allocator: runtime.Allocator, // Wrapped allocator + level: Level, // Log Level used for allocations + prefix: string, // Prefix to use in log messages + lock: sync.Mutex, + size_fmt: Log_Allocator_Format, // Format to use when logging allocations } +/* +Initialize the backing data for the allocator that logs all allocations. + +Inputs: +- `la`: Pointer to the data structure to initialize +- `level`: Log level to use for allocations +- `size_fmt`: Format to use when logging allocations (default is `.Bytes`) +- `allocator`: Wrapped allocator (default is `context.allocator`) +- `prefix`: Prefix to use in log messages (default is `""`) +*/ log_allocator_init :: proc(la: ^Log_Allocator, level: Level, size_fmt := Log_Allocator_Format.Bytes, allocator := context.allocator, prefix := "") { la.allocator = allocator - la.level = level - la.prefix = prefix - la.locked = false + la.level = level + la.prefix = prefix + la.lock = {} la.size_fmt = size_fmt } +/* +Create an allocator that logs all allocations. +Inputs: +- `la`: Pointer to the data structure backing the allocator + +Returns: +- An allocator that logs all allocations +*/ log_allocator :: proc(la: ^Log_Allocator) -> runtime.Allocator { return runtime.Allocator{ procedure = log_allocator_proc, @@ -33,6 +58,7 @@ log_allocator :: proc(la: ^Log_Allocator) -> runtime.Allocator { } } +// Backing procedure for allocator that logs all allocations. log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, runtime.Allocator_Error) { @@ -46,83 +72,78 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, buf: [256]byte = --- - if !la.locked { - la.locked = true - defer la.locked = false + sync.lock(&la.lock) + switch mode { + case .Alloc: + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - switch mode { - case .Alloc: + case .Alloc_Non_Zeroed: + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Free: + if old_size != 0 { format: string switch la.size_fmt { - case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)" - case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)" + case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)" + case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)" } - str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size) context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Alloc_Non_Zeroed: - format: string - switch la.size_fmt { - case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)" - case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)" - } - str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Free: - if old_size != 0 { - format: string - switch la.size_fmt { - case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)" - case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)" - } - str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - } else { - str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - } - - case .Free_All: - str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Resize: - format: string - switch la.size_fmt { - case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)" - case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)" - } - str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Resize_Non_Zeroed: - format: string - switch la.size_fmt { - case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)" - case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)" - } - str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Query_Features: - str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - - case .Query_Info: - str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding) + } else { + str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory) context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } + + case .Free_All: + str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Resize: + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Resize_Non_Zeroed: + format: string + switch la.size_fmt { + case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)" + case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)" + } + str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Query_Features: + str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + + case .Query_Info: + str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) } + sync.unlock(&la.lock) data, err := la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location) - if !la.locked { - la.locked = true - defer la.locked = false - if err != nil { - str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err) - context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) - } + if err != nil { + sync.lock(&la.lock) + str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err) + context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location) + sync.unlock(&la.lock) } return data, err } diff --git a/core/log/multi_logger.odin b/core/log/multi_logger.odin index 6122554bb..99d7377db 100644 --- a/core/log/multi_logger.odin +++ b/core/log/multi_logger.odin @@ -1,10 +1,27 @@ package log +// A container backing for multiple loggers. Multi_Logger_Data :: struct { loggers: []Logger, } +/* +Create a logger that logs to all backing loggers. + +*Allocates Using Provided Allocator* + +When no longer needed can be destroyed with `destroy_multi_logger`. + +Note: Logs using a multi logger take both the multi logger and the backing loggers' log levels into account. + +Inputs: +- `logs` - Backing loggers passed as multiple arguments +- `allocator` - An allocator used to allocate data to store backing loggers (default is `context.allocator`) + +Returns: +- A multi logger +*/ create_multi_logger :: proc(logs: ..Logger, allocator := context.allocator) -> Logger { data := new(Multi_Logger_Data, allocator) data.loggers = make([]Logger, len(logs), allocator) @@ -12,12 +29,20 @@ create_multi_logger :: proc(logs: ..Logger, allocator := context.allocator) -> L return Logger{multi_logger_proc, data, Level.Debug, nil} } +/* +Free the state allocated with `create_multi_logger`. + +Inputs: +- `log`: Logger created with `create_multi_logger` +- `allocator`: Allocator passed to `create_multi_logger` (default is `context.allocator`) +*/ destroy_multi_logger :: proc(log: Logger, allocator := context.allocator) { data := (^Multi_Logger_Data)(log.data) delete(data.loggers, allocator) free(data, allocator) } +// Backing procedure for the multi logger. multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string, options: Options, location := #caller_location) { data := cast(^Multi_Logger_Data)logger_data diff --git a/core/math/big/api.odin b/core/math/big/api.odin index bf19e83b6..e18a40b30 100644 --- a/core/math/big/api.odin +++ b/core/math/big/api.odin @@ -1,12 +1,12 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. This file collects public proc maps and their aliases. */ - -package math_big /* === === === === === === === === === === === === === === === === === === === === === === === === @@ -160,6 +160,5 @@ destroy :: proc { int_destroy :: proc(integers: ..^Int) */ int_destroy, -} - - + internal_rat_destroy, +} \ No newline at end of file diff --git a/core/math/big/common.odin b/core/math/big/common.odin index 5428b00ee..acf32749e 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -1,12 +1,12 @@ -/* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. -*/ - - package math_big +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. +*/ + import "base:intrinsics" +import "base:runtime" /* TODO: Make the tunables runtime adjustable where practical. @@ -14,32 +14,10 @@ import "base:intrinsics" This allows to benchmark and/or setting optimized values for a certain CPU without recompiling. */ -/* - ========================== TUNABLES ========================== - - `initialize_constants` returns `#config(MUL_KARATSUBA_CUTOFF, _DEFAULT_MUL_KARATSUBA_CUTOFF)` - and we initialize this cutoff that way so that the procedure is used and called, - because it handles initializing the constants ONE, ZERO, MINUS_ONE, NAN and INF. - - `initialize_constants` also replaces the other `_DEFAULT_*` cutoffs with custom compile-time values if so `#config`ured. - -*/ - -/* - There is a bug with DLL globals. They don't get set. - To allow tests to run we add `-define:MATH_BIG_EXE=false` to hardcode the cutoffs for now. -*/ -when #config(MATH_BIG_EXE, true) { - MUL_KARATSUBA_CUTOFF := initialize_constants() - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF -} else { - MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF -} +MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF +SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF +MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF +SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF /* These defaults were tuned on an AMD A8-6600K (64-bit) using libTomMath's `make tune`. @@ -49,9 +27,6 @@ when #config(MATH_BIG_EXE, true) { It would also be cool if we collected some data across various processor families. This would let uss set reasonable defaults at runtime as this library initializes itself by using `cpuid` or the ARM equivalent. - - IMPORTANT: The 32_BIT path has largely gone untested. It needs to be tested and - debugged where necessary. */ _DEFAULT_MUL_KARATSUBA_CUTOFF :: #config(MATH_BIG_MUL_KARATSUBA_CUTOFF, 80) @@ -65,7 +40,7 @@ MAX_ITERATIONS_ROOT_N := 500 /* Largest `N` for which we'll compute `N!` */ -FACTORIAL_MAX_N := 1_000_000 +FACTORIAL_MAX_N := 1_000_000 /* Cutoff to switch to int_factorial_binary_split, and its max recursion level. @@ -97,22 +72,10 @@ MAX_ITERATIONS_RANDOM_PRIME := 1_000_000 */ @thread_local RANDOM_PRIME_ITERATIONS_USED: int -/* - We don't allow these to be switched at runtime for two reasons: - - 1) 32-bit and 64-bit versions of procedures use different types for their storage, - so we'd have to double the number of procedures, and they couldn't interact. - - 2) Optimizations thanks to precomputed masks wouldn't work. -*/ -MATH_BIG_FORCE_64_BIT :: #config(MATH_BIG_FORCE_64_BIT, false) -MATH_BIG_FORCE_32_BIT :: #config(MATH_BIG_FORCE_32_BIT, false) -when (MATH_BIG_FORCE_32_BIT && MATH_BIG_FORCE_64_BIT) { #panic("Cannot force 32-bit and 64-bit big backend simultaneously.") } - /* Trade a smaller memory footprint for more processing overhead? */ -_LOW_MEMORY :: #config(MATH_BIG_SMALL_MEMORY, false) +_LOW_MEMORY :: #config(MATH_BIG_SMALL_MEMORY, false) when _LOW_MEMORY { _DEFAULT_DIGIT_COUNT :: 8 _TAB_SIZE :: 32 @@ -150,11 +113,12 @@ Flags :: bit_set[Flag; u8] /* Errors are a strict superset of runtime.Allocation_Error. */ -Error :: enum int { - Okay = 0, +Error :: enum byte { + None = 0, Out_Of_Memory = 1, Invalid_Pointer = 2, Invalid_Argument = 3, + Mode_Not_Implemented = 4, // Allocation Assignment_To_Immutable = 10, Max_Iterations_Reached = 11, @@ -170,13 +134,19 @@ Error :: enum int { Cannot_Write_File = 52, Unimplemented = 127, + + Okay = None, } +#assert(intrinsics.type_is_superset_of(Error, runtime.Allocator_Error)) + + Error_String :: #sparse[Error]string{ - .Okay = "Okay", + .None = "None", .Out_Of_Memory = "Out of memory", .Invalid_Pointer = "Invalid pointer", .Invalid_Argument = "Invalid argument", + .Mode_Not_Implemented = "Allocation mode not implemented", .Assignment_To_Immutable = "Assignment to immutable", .Max_Iterations_Reached = "Max iterations reached", @@ -221,22 +191,19 @@ _MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS) _MAX_BIT_COUNT :: (max(int) - 2) _MAX_DIGIT_COUNT :: _MAX_BIT_COUNT / _DIGIT_BITS -when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { - /* - We can use u128 as an intermediary. - */ - DIGIT :: distinct u64 - _WORD :: distinct u128 -} else { - DIGIT :: distinct u32 - _WORD :: distinct u64 -} +// We use u128 as an intermediary. +DIGIT :: distinct u64 +_WORD :: distinct u128 + +// Base 10 extraction constants +ITOA_DIVISOR :: DIGIT(1_000_000_000_000_000_000) +ITOA_COUNT :: 18 #assert(size_of(_WORD) == 2 * size_of(DIGIT)) _DIGIT_TYPE_BITS :: 8 * size_of(DIGIT) _WORD_TYPE_BITS :: 8 * size_of(_WORD) -_DIGIT_NAILS :: 4 +_DIGIT_NAILS :: 1 _DIGIT_BITS :: _DIGIT_TYPE_BITS - _DIGIT_NAILS _WORD_BITS :: 2 * _DIGIT_BITS diff --git a/core/math/big/doc.odin b/core/math/big/doc.odin deleted file mode 100644 index 0f9b88d01..000000000 --- a/core/math/big/doc.odin +++ /dev/null @@ -1,6 +0,0 @@ -/* -A BigInt implementation in Odin. -For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. -The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. -*/ -package math_big diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index ee09bb2c7..21a5bdc35 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -1,13 +1,12 @@ -/* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. -*/ - - package math_big +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. +*/ + import "base:intrinsics" -import rnd "core:math/rand" +import "base:runtime" /* TODO: Int.flags and Constants like ONE, NAN, etc, are not yet properly handled everywhere. @@ -362,17 +361,7 @@ platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) count_lsb :: proc { int_count_lsb, platform_count_lsb, } -int_random_digit :: proc() -> (res: DIGIT) { - when _DIGIT_BITS == 60 { // DIGIT = u64 - return DIGIT(rnd.uint64()) & _MASK - } else when _DIGIT_BITS == 28 { // DIGIT = u32 - return DIGIT(rnd.uint32()) & _MASK - } else { - panic("Unsupported DIGIT size.") - } - - return 0 // We shouldn't get here. -} +int_random_digit :: internal_int_random_digit int_random :: proc(dest: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { /* @@ -777,32 +766,36 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca */ INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} -@(init, private) -_init_constants :: proc() { - initialize_constants() -} +@(private) +constant_allocator: runtime.Allocator -initialize_constants :: proc() -> (res: int) { - internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} - internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable} - internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} +@(init, private) +initialize_constants :: proc "contextless" () { + context = runtime.default_context() + constant_allocator = context.allocator + + internal_int_set_from_integer( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} + internal_int_set_from_integer( INT_ONE, 1); INT_ONE.flags = {.Immutable} + internal_int_set_from_integer(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} /* We set these special values to -1 or 1 so they don't get mistake for zero accidentally. This allows for shortcut tests of is_zero as .used == 0. */ - internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} - internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} - internal_set(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} - - return _DEFAULT_MUL_KARATSUBA_CUTOFF + internal_int_set_from_integer( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} + internal_int_set_from_integer( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} + internal_int_set_from_integer(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} } /* Destroy constants. Optional for an EXE, as this would be called at the very end of a process. */ -destroy_constants :: proc() { +@(fini, private) +destroy_constants :: proc "contextless" () { + context = runtime.default_context() + context.allocator = constant_allocator + internal_destroy(INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN) } diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index c9b331e55..e2bfa8f50 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -1,6 +1,8 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. ========================== Low-level routines ========================== @@ -25,12 +27,10 @@ TODO: Handle +/- Infinity and NaN. */ -package math_big - -import "core:mem" -import "base:intrinsics" -import rnd "core:math/rand" import "base:builtin" +import "base:intrinsics" +import "base:runtime" +@(require) import rnd "core:math/rand" /* Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7. @@ -746,19 +746,15 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used / 3) * 2) { assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set.") - err = _private_int_div_recursive(quotient, remainder, numerator, denominator) + return _private_int_div_recursive(quotient, remainder, numerator, denominator) } else { - when true { - err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) - } else { - /* - NOTE(Jeroen): We no longer need or use `_private_int_div_small`. - We'll keep it around for a bit until we're reasonably certain div_school is bug free. - */ - err = _private_int_div_small(quotient, remainder, numerator, denominator) - } + return #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) + /* + NOTE(Jeroen): We no longer need or use `_private_int_div_small`. + We'll keep it around for a bit until we're reasonably certain div_school is bug free. + */ + // err = _private_int_div_small(quotient, remainder, numerator, denominator) } - return } /* @@ -993,7 +989,8 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : Zero remainder. Special case, can't use `internal_zero_unused`. */ if zero_count > 0 { - mem.zero_slice(remainder.digit[zero_count:]) + data := remainder.digit[zero_count:] + _zero(data) } /* @@ -1019,7 +1016,7 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : Assumes `a` not to be `nil`. */ internal_int_allocated_cap :: #force_inline proc(a: ^Int) -> (cap: int) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit + raw := transmute(runtime.Raw_Dynamic_Array)a.digit return raw.cap } @@ -1181,6 +1178,8 @@ internal_cmp_digit :: internal_compare_digit */ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: int) { assert_if_nil(a, b) + internal_clamp(a) + internal_clamp(b) // Compare based on used digits. if a.used != b.used { @@ -1203,14 +1202,14 @@ internal_cmp_mag :: internal_compare_magnitude bool := a < b */ internal_int_less_than :: #force_inline proc(a, b: ^Int) -> (less_than: bool) { - return internal_cmp(a, b) == -1 + return internal_cmp(a, b) < 0 } /* bool := a < b */ internal_int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (less_than: bool) { - return internal_cmp_digit(a, b) == -1 + return internal_cmp_digit(a, b) < 0 } /* @@ -1218,7 +1217,7 @@ internal_int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (less_t Compares the magnitudes only, ignores the sign. */ internal_int_less_than_abs :: #force_inline proc(a, b: ^Int) -> (less_than: bool) { - return internal_cmp_mag(a, b) == -1 + return internal_cmp_mag(a, b) < 0 } internal_less_than :: proc { @@ -1453,6 +1452,7 @@ internal_int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) { /* Fast path for `Int`s that fit within a single `DIGIT`. */ + internal_clamp(a) if a.used == 1 { return internal_log(a.digit[0], DIGIT(base)) } return _private_int_log(a, base) @@ -1660,13 +1660,13 @@ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (e if internal_gte(y, x) { internal_swap(dest, x) - return nil + return internal_clamp(dest) } internal_swap(x, y) } internal_swap(dest, x) - return err + return internal_clamp(dest) } internal_sqrt :: proc { internal_int_sqrt, } @@ -1688,7 +1688,7 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca */ if n == 2 { return #force_inline internal_sqrt(dest, src) } - if n < 0 || n > int(_DIGIT_MAX) { return .Invalid_Argument } + if n < 0 || _WORD(n) > _WORD(_DIGIT_MAX) { return .Invalid_Argument } if n & 1 == 0 && #force_inline internal_is_negative(src) { return .Invalid_Argument } @@ -1849,7 +1849,7 @@ internal_int_destroy :: proc(integers: ..^Int) { for &a in integers { if internal_int_allocated_cap(a) > 0 { - mem.zero_slice(a.digit[:]) + _zero(a.digit[:]) free(&a.digit[0]) } a = &Int{} @@ -2181,7 +2181,11 @@ internal_int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator If not yet initialized, initialize the `digit` backing with the allocator we were passed. */ if cap == 0 { - a.digit = make([dynamic]DIGIT, needed, allocator) + mem_err: runtime.Allocator_Error + a.digit, mem_err = make([dynamic]DIGIT, needed, allocator) + if mem_err != nil { + return cast(Error)mem_err + } } else if cap < needed { /* `[dynamic]DIGIT` already knows what allocator was used for it, so resize will do the right thing. @@ -2208,9 +2212,9 @@ internal_grow :: proc { internal_int_grow, } Assumes `a` not to be `nil`. */ internal_int_clear :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit + raw := transmute(runtime.Raw_Dynamic_Array)a.digit if raw.cap != 0 { - mem.zero_slice(a.digit[:a.used]) + _zero(a.digit[:a.used]) } a.sign = .Zero_or_Positive a.used = 0 @@ -2273,7 +2277,7 @@ internal_int_power_of_two :: proc(a: ^Int, power: int, allocator := context.allo /* Zero the entirety. */ - mem.zero_slice(a.digit[:]) + _zero(a.digit[:]) /* Set the bit. @@ -2791,7 +2795,8 @@ internal_int_count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { x *= _DIGIT_BITS x += internal_count_lsb(q) } else { - lnz := []int{ + @(static, rodata) + lnz := [?]int{ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, } @@ -2818,9 +2823,9 @@ internal_platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) internal_count_lsb :: proc { internal_int_count_lsb, internal_platform_count_lsb, } internal_int_random_digit :: proc() -> (res: DIGIT) { - when _DIGIT_BITS == 60 { // DIGIT = u64 + when _DIGIT_TYPE_BITS == 64 { // DIGIT = u64 return DIGIT(rnd.uint64()) & _MASK - } else when _DIGIT_BITS == 28 { // DIGIT = u32 + } else when _DIGIT_TYPE_BITS == 32 { // DIGIT = u32 return DIGIT(rnd.uint32()) & _MASK } else { panic("Unsupported DIGIT size.") @@ -2885,12 +2890,12 @@ internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context } internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, } -internal_error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { +internal_error_if_immutable_single :: proc "contextless" (arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable } return nil } -internal_error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { +internal_error_if_immutable_multi :: proc "contextless" (args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable } } @@ -2933,7 +2938,7 @@ internal_int_zero_unused :: #force_inline proc(dest: ^Int, old_used := -1) { If we don't pass the number of previously used DIGITs, we zero all remaining ones. */ zero_count: int - if old_used == -1 { + if old_used < 0 { zero_count = len(dest.digit) - dest.used } else { zero_count = old_used - dest.used @@ -2943,11 +2948,15 @@ internal_int_zero_unused :: #force_inline proc(dest: ^Int, old_used := -1) { Zero remainder. */ if zero_count > 0 && dest.used < len(dest.digit) { - mem.zero_slice(dest.digit[dest.used:][:zero_count]) + _zero(dest.digit[dest.used:][:zero_count]) } } internal_zero_unused :: proc { internal_int_zero_unused, } +_zero :: proc(data: []DIGIT) { + intrinsics.mem_zero(raw_data(data), size_of(DIGIT)*len(data)) +} + /* ========================== End of low-level routines ========================== */ diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin index 00134228b..a600ef823 100644 --- a/core/math/big/logical.odin +++ b/core/math/big/logical.odin @@ -1,6 +1,8 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. An arbitrary precision mathematics implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. @@ -9,9 +11,6 @@ This file contains logical operations like `and`, `or` and `xor`. */ - -package math_big - /* The `and`, `or` and `xor` binops differ in two lines only. We could handle those with a switch, but that adds overhead. diff --git a/core/math/big/prime.odin b/core/math/big/prime.odin index 832c75119..7fa6d8e4a 100644 --- a/core/math/big/prime.odin +++ b/core/math/big/prime.odin @@ -1,6 +1,8 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. An arbitrary precision mathematics implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. @@ -9,9 +11,6 @@ This file contains prime finding operations. */ - -package math_big - /* Determines if an Integer is divisible by one of the _PRIME_TABLE primes. Returns true if it is, false if not. @@ -102,7 +101,7 @@ internal_int_power_modulo :: proc(res, G, X, P: ^Int, allocator := context.alloc If the modulus is odd or dr != 0 use the montgomery method. */ if internal_int_is_odd(P) || dr != 0 { - return _private_int_exponent_mod(res, G, X, P, dr) + return _private_int_exponent_mod_fast(res, G, X, P, dr) } /* @@ -135,7 +134,8 @@ internal_int_kronecker :: proc(a, p: ^Int, allocator := context.allocator) -> (k a1, p1, r := &Int{}, &Int{}, &Int{} defer internal_destroy(a1, p1, r) - table := []int{0, 1, 0, -1, 0, -1, 0, 1} + @(static, rodata) + table := [?]int{0, 1, 0, -1, 0, -1, 0, 1} if internal_int_is_zero(p) { if a.used == 1 && a.digit[0] == 1 { @@ -1208,7 +1208,7 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags := /* Automatically choose the number of Rabin-Miller trials? */ - if trials == -1 { + if trials < 0 { trials = number_of_rabin_miller_trials(size_in_bits) } diff --git a/core/math/big/private.odin b/core/math/big/private.odin index bb6b9497c..1ca706c6d 100644 --- a/core/math/big/private.odin +++ b/core/math/big/private.odin @@ -1,6 +1,8 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. An arbitrary precision mathematics implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. @@ -16,11 +18,7 @@ These aren't exported for the same reasons. */ - -package math_big - import "base:intrinsics" -import "core:mem" /* Multiplies |a| * |b| and only computes upto digs digits of result. @@ -441,8 +439,14 @@ _private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := contex return _private_int_mul_high_comba(dest, a, b, digits) } - internal_grow(dest, a.used + b.used + 1) or_return - dest.used = a.used + b.used + 1 + /* + Set up temporary output `Int`, which we'll swap for `dest` when done. + */ + + t := &Int{} + + internal_grow(t, a.used + b.used + 1) or_return + t.used = a.used + b.used + 1 pa := a.used pb := b.used @@ -453,20 +457,23 @@ _private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := contex /* Calculate the double precision result. */ - r := _WORD(dest.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry) + r := _WORD(t.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry) /* Get the lower part. */ - dest.digit[ix + iy] = DIGIT(r & _WORD(_MASK)) + t.digit[ix + iy] = DIGIT(r & _WORD(_MASK)) /* Carry the carry. */ carry = DIGIT(r >> _WORD(_DIGIT_BITS)) } - dest.digit[ix + pb] = carry + t.digit[ix + pb] = carry } + + internal_swap(dest, t) + internal_destroy(t) return internal_clamp(dest) } @@ -818,7 +825,7 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat x1.used = src.used - B #force_inline internal_copy_digits(x0, src, x0.used) - #force_inline mem.copy_non_overlapping(&x1.digit[0], &src.digit[B], size_of(DIGIT) * x1.used) + intrinsics.mem_copy_non_overlapping(&x1.digit[0], &src.digit[B], size_of(DIGIT) * x1.used) #force_inline internal_clamp(x0) /* @@ -883,9 +890,9 @@ _private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) - a1.used = B a2.used = src.used - 2 * B - #force_inline mem.copy_non_overlapping(&a0.digit[0], &src.digit[ 0], size_of(DIGIT) * a0.used) - #force_inline mem.copy_non_overlapping(&a1.digit[0], &src.digit[ B], size_of(DIGIT) * a1.used) - #force_inline mem.copy_non_overlapping(&a2.digit[0], &src.digit[2 * B], size_of(DIGIT) * a2.used) + intrinsics.mem_copy_non_overlapping(&a0.digit[0], &src.digit[ 0], size_of(DIGIT) * a0.used) + intrinsics.mem_copy_non_overlapping(&a1.digit[0], &src.digit[ B], size_of(DIGIT) * a1.used) + intrinsics.mem_copy_non_overlapping(&a2.digit[0], &src.digit[2 * B], size_of(DIGIT) * a2.used) internal_clamp(a0) internal_clamp(a1) @@ -1051,7 +1058,6 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In Normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */ norm := internal_count_bits(y) % _DIGIT_BITS - if norm < _DIGIT_BITS - 1 { norm = (_DIGIT_BITS - 1) - norm internal_shl(x, x, norm) or_return @@ -1071,33 +1077,29 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In y = y*b**{n-t} */ + _private_int_shl_leg(y, n - t) or_return - gte := internal_gte(x, y) - for gte { + for internal_gte(x, y) { q.digit[n - t] += 1 internal_sub(x, x, y) or_return - gte = internal_gte(x, y) } /* Reset y by shifting it back down. */ _private_int_shr_leg(y, n - t) - /* Step 3. for i from n down to (t + 1). */ #no_bounds_check for i := n; i >= (t + 1); i -= 1 { if i > x.used { continue } - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if x.digit[i] == y.digit[t] { - q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1) + q.digit[(i - t) - 1] = 1 << _DIGIT_BITS - 1 } else { - tmp := _WORD(x.digit[i]) << _DIGIT_BITS tmp |= _WORD(x.digit[i - 1]) tmp /= _WORD(y.digit[t]) @@ -1370,8 +1372,8 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := /* Slower bit-bang division... also smaller. + Prefer `_int_div_school` for speed. */ -@(deprecated="Use `_int_div_school`, it's 3.5x faster.") _private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Error) { ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{} @@ -1668,7 +1670,7 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) - defer internal_destroy(bracket_low, bracket_high, bracket_mid, t, bi_base) ic := #force_inline internal_cmp(a, base) - if ic == -1 || ic == 0 { + if ic <= 0 { return 1 if ic == 0 else 0, nil } defer if err != nil { @@ -2346,7 +2348,7 @@ _private_int_dr_reduce :: proc(x, n: ^Int, k: DIGIT, allocator := context.alloca /* Zero words above m. */ - mem.zero_slice(x.digit[m + 1:][:x.used - m]) + _zero(x.digit[m + 1:][:x.used - m]) /* Clamp, sub and return. @@ -2498,9 +2500,9 @@ _private_int_exponent_mod :: proc(res, G, X, P: ^Int, redmode: int, allocator := bitcnt -= 1 if bitcnt == 0 { /* - If digidx == -1 we are out of digits. + If digidx < 0 we are out of digits. */ - if digidx == -1 { break } + if digidx < 0 { break } /* Read next digit and reset the bitcnt. @@ -2754,9 +2756,9 @@ _private_int_exponent_mod_fast :: proc(res, G, X, P: ^Int, redmode: int, allocat bitcnt -= 1 if bitcnt == 0 { /* - If digidx == -1 we are out of digits so break. + If digidx < 0 we are out of digits so break. */ - if digidx == -1 { break } + if digidx < 0 { break } /* Read next digit and reset the bitcnt. @@ -3143,7 +3145,7 @@ _private_copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0)) -> } digits = min(digits, len(src.digit), len(dest.digit)) - mem.copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits) + intrinsics.mem_copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits) return nil } @@ -3181,7 +3183,7 @@ _private_int_shl_leg :: proc(quotient: ^Int, digits: int, allocator := context.a } quotient.used += digits - mem.zero_slice(quotient.digit[:digits]) + _zero(quotient.digit[:digits]) return nil } @@ -3223,6 +3225,7 @@ _private_int_shr_leg :: proc(quotient: ^Int, digits: int, allocator := context.a Tables used by `internal_*` and `_*`. */ +@(rodata) _private_int_rem_128 := [?]DIGIT{ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, @@ -3235,6 +3238,7 @@ _private_int_rem_128 := [?]DIGIT{ } #assert(128 * size_of(DIGIT) == size_of(_private_int_rem_128)) +@(rodata) _private_int_rem_105 := [?]DIGIT{ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, @@ -3247,6 +3251,7 @@ _private_int_rem_105 := [?]DIGIT{ #assert(105 * size_of(DIGIT) == size_of(_private_int_rem_105)) _PRIME_TAB_SIZE :: 256 +@(rodata) _private_prime_table := [_PRIME_TAB_SIZE]DIGIT{ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, @@ -3286,8 +3291,8 @@ _private_prime_table := [_PRIME_TAB_SIZE]DIGIT{ } #assert(_PRIME_TAB_SIZE * size_of(DIGIT) == size_of(_private_prime_table)) -when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { - _factorial_table := [35]_WORD{ +@(rodata) +_factorial_table := [35]_WORD{ /* f(00): */ 1, /* f(01): */ 1, /* f(02): */ 2, @@ -3323,33 +3328,9 @@ when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* f(32): */ 263_130_836_933_693_530_167_218_012_160_000_000, /* f(33): */ 8_683_317_618_811_886_495_518_194_401_280_000_000, /* f(34): */ 295_232_799_039_604_140_847_618_609_643_520_000_000, - } -} else { - _factorial_table := [21]_WORD{ -/* f(00): */ 1, -/* f(01): */ 1, -/* f(02): */ 2, -/* f(03): */ 6, -/* f(04): */ 24, -/* f(05): */ 120, -/* f(06): */ 720, -/* f(07): */ 5_040, -/* f(08): */ 40_320, -/* f(09): */ 362_880, -/* f(10): */ 3_628_800, -/* f(11): */ 39_916_800, -/* f(12): */ 479_001_600, -/* f(13): */ 6_227_020_800, -/* f(14): */ 87_178_291_200, -/* f(15): */ 1_307_674_368_000, -/* f(16): */ 20_922_789_888_000, -/* f(17): */ 355_687_428_096_000, -/* f(18): */ 6_402_373_705_728_000, -/* f(19): */ 121_645_100_408_832_000, -/* f(20): */ 2_432_902_008_176_640_000, - } } + /* ========================= End of private tables ======================== */ \ No newline at end of file diff --git a/core/math/big/public.odin b/core/math/big/public.odin index 070c45283..07d2a7f21 100644 --- a/core/math/big/public.odin +++ b/core/math/big/public.odin @@ -1,6 +1,9 @@ +// Arbitrary precision integers and rationals. +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. An arbitrary precision mathematics implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. @@ -9,9 +12,6 @@ This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ... */ - -package math_big - import "base:intrinsics" /* @@ -593,7 +593,7 @@ int_less_than :: #force_inline proc(a, b: ^Int, allocator := context.allocator) c: int c, err = cmp(a, b) - return c == -1, err + return c < 0, err } /* @@ -608,7 +608,7 @@ int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := contex c: int c, err = cmp(a, b) - return c == -1, err + return c < 0, err } /* @@ -624,7 +624,7 @@ int_less_than_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocat c: int c, err = cmp_mag(a, b) - return c == -1, err + return c < 0, err } less_than :: proc { diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index a5100e478..1a80fdf88 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -1,6 +1,8 @@ +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. An arbitrary precision mathematics implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. @@ -13,12 +15,7 @@ - Also look at extracting and splatting several digits at once. */ - -package math_big - import "base:intrinsics" -import "core:mem" -import "core:os" /* This version of `itoa` allocates on behalf of the caller. The caller must free the string. @@ -45,7 +42,11 @@ int_itoa_string :: proc(a: ^Int, radix := i8(10), zero_terminate := false, alloc /* Allocate the buffer we need. */ - buffer := make([]u8, size) + buffer, mem_err := make([]u8, size) + if mem_err != nil { + err = cast(Error)mem_err + return + } /* Write the digits out into the buffer. @@ -107,7 +108,7 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter /* We weren't given a size. Let's compute it. */ - if size == -1 { + if size < 0 { size = radix_size(a, radix, zero_terminate) or_return } @@ -141,7 +142,7 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter written = len(buffer) - available if written < size { diff := size - written - mem.copy(&buffer[0], &buffer[diff], written) + intrinsics.mem_copy(&buffer[0], &buffer[diff], written) } return written, nil } @@ -174,7 +175,7 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter written = len(buffer) - available if written < size { diff := size - written - mem.copy(&buffer[0], &buffer[diff], written) + intrinsics.mem_copy(&buffer[0], &buffer[diff], written) } return written, nil } @@ -182,16 +183,15 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter /* Fast path for radixes that are a power of two. */ + count := count_bits(a) or_return + if is_power_of_two(int(radix)) { if zero_terminate { available -= 1 buffer[available] = 0 } - shift, count: int - // mask := _WORD(radix - 1); - shift, err = log(DIGIT(radix), 2) - count, err = count_bits(a) + shift := log(DIGIT(radix), 2) or_return digit: _WORD for offset := 0; offset < count; offset += shift { @@ -216,12 +216,22 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter written = len(buffer) - available if written < size { diff := size - written - mem.copy(&buffer[0], &buffer[diff], written) + intrinsics.mem_copy(&buffer[0], &buffer[diff], written) } return written, nil } - return _itoa_raw_full(a, radix, buffer, zero_terminate) + // NOTE(Jeroen): The new method is faster for an `Int` up to ~32768 bits in size with optimizations. + // At `.None` or `.Minimal`, it appears to always be faster. + // If we optimize `itoa` further, this needs to be evaluated. + itoa_method := _itoa_raw_full + + when ODIN_OPTIMIZATION_MODE >= .Size { + if count >= 32768 { + itoa_method = _itoa_raw_old + } + } + return itoa_method(a, radix, buffer, zero_terminate) } itoa :: proc{int_itoa_string, int_itoa_raw} @@ -280,7 +290,7 @@ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context } pos := ch - '+' - if RADIX_TABLE_REVERSE_SIZE <= pos { + if RADIX_TABLE_REVERSE_SIZE <= u32(pos) { break } y := RADIX_TABLE_REVERSE[pos] @@ -310,7 +320,7 @@ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context res.sign = sign } - return nil + return internal_clamp(res) } @@ -354,8 +364,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con internal_set(la, bit_count) or_return /* k = floor(2^29/log_2(radix)) + 1 */ - lb := _log_bases - internal_set(k, lb[radix]) or_return + internal_set(k, _log_bases[radix]) or_return /* n = floor((la * k) / 2^29) + 1 */ internal_mul(k, la, k) or_return @@ -375,64 +384,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con return size, nil } -/* - We might add functions to read and write byte-encoded Ints from/to files, using `int_to_bytes_*` functions. - LibTomMath allows exporting/importing to/from a file in ASCII, but it doesn't support a much more compact representation in binary, even though it has several pack functions int_to_bytes_* (which I expanded upon and wrote Python interoperable versions of as well), and (un)pack, which is GMP compatible. - Someone could implement their own read/write binary int procedures, of course. - - Could be worthwhile to add a canonical binary file representation with an optional small header that says it's an Odin big.Int, big.Rat or Big.Float, byte count for each component that follows, flag for big/little endian and a flag that says a checksum exists at the end of the file. - For big.Rat and big.Float the header couldn't be optional, because we'd have no way to distinguish where the components end. -*/ - -/* - Read an Int from an ASCII file. -*/ -internal_int_read_from_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - /* - We can either read the entire file at once, or read a bunch at a time and keep multiplying by the radix. - For now, we'll read the entire file. Eventually we'll replace this with a copy that duplicates the logic - of `atoi` so we don't need to read the entire file. - */ - - res, ok := os.read_entire_file(filename, allocator) - defer delete(res, allocator) - - if !ok { - return .Cannot_Read_File - } - - as := string(res) - return atoi(a, as, radix) -} - -/* - Write an Int to an ASCII file. -*/ -internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - /* - For now we'll convert the Int using itoa and writing the result in one go. - If we want to preserve memory we could duplicate the itoa logic and write backwards. - */ - - as := itoa(a, radix) or_return - defer delete(as) - - l := len(as) - assert(l > 0) - - data := transmute([]u8)mem.Raw_Slice{ - data = raw_data(as), - len = l, - } - - ok := os.write_entire_file(filename, data, truncate=true) - return nil if ok else .Cannot_Write_File -} /* Calculate the size needed for `internal_int_pack`. @@ -561,8 +513,9 @@ internal_int_unpack :: proc(a: ^Int, buf: []$T, nails := 0, order := Order.LSB_F */ _RADIX_SIZE_SCALE :: 29 -_log_bases :: [65]u32{ - 0, 0, 0x20000001, 0x14309399, 0x10000001, +@(rodata) +_log_bases := [65]u32{ + 0, 0, 0x20000001, 0x14309399, 0x10000001, 0xdc81a35, 0xc611924, 0xb660c9e, 0xaaaaaab, 0xa1849cd, 0x9a209a9, 0x94004e1, 0x8ed19c2, 0x8a5ca7d, 0x867a000, 0x830cee3, 0x8000001, 0x7d42d60, 0x7ac8b32, 0x7887847, @@ -581,6 +534,7 @@ _log_bases :: [65]u32{ Characters used in radix conversions. */ RADIX_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" +@(rodata) RADIX_TABLE_REVERSE := [RADIX_TABLE_REVERSE_SIZE]u8{ 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x01, 0x02, 0x03, 0x04, /* +,-./01234 */ 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56789:;<=> */ @@ -597,14 +551,108 @@ RADIX_TABLE_REVERSE_SIZE :: 80 Stores a bignum as a ASCII string in a given radix (2..64) The buffer must be appropriately sized. This routine doesn't check. */ + _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false, allocator := context.allocator) -> (written: int, err: Error) { assert_if_nil(a) context.allocator = allocator - temp, denominator := &Int{}, &Int{} + // Calculate largest radix^n that fits within _DIGIT_BITS + divisor := _WORD(ITOA_DIVISOR) + digit_count := ITOA_COUNT + _radix := DIGIT(radix) - internal_copy(temp, a) or_return - internal_set(denominator, radix) or_return + if radix != 10 { + i := _WORD(1) + digit_count = -1 + for i < _WORD(1 << _DIGIT_BITS) { + divisor = _WORD(i) + i *= _WORD(radix) + digit_count += 1 + } + } + + temp := &Int{} + internal_copy(temp, a) or_return + defer internal_destroy(temp) + + available := len(buffer) + if zero_terminate { + available -= 1 + buffer[available] = 0 + } + + if a.sign == .Negative { + temp.sign = .Zero_or_Positive + } + + q := &Int{} + defer internal_destroy(q) + + remainder: DIGIT + for { + internal_grow(q, temp.used) or_return + q.used = temp.used + q.sign = temp.sign + + w := _WORD(0) + + for ix := temp.used - 1; ix >= 0; ix -= 1 { + t := DIGIT(0) + w = (w << _WORD(_DIGIT_BITS) | _WORD(temp.digit[ix])) + if w >= divisor { + t = DIGIT(w / divisor) + w -= _WORD(t) * divisor + } + q.digit[ix] = t + } + remainder = DIGIT(w) + + internal_clamp(q) + q, temp = temp, q + + count := digit_count + for available > 0 && count > 0 { + available -= 1 + buffer[available] = RADIX_TABLE[remainder % _radix] + remainder /= _radix + count -= 1 + } + + if temp.used == 0 { + break + } + } + + // Remove leading zero if we ended up with one. + if buffer[available] == '0' { + available += 1 + } + + if a.sign == .Negative { + available -= 1 + buffer[available] = '-' + } + + /* + If we overestimated the size, we need to move the buffer left. + */ + written = len(buffer) - available + if written < len(buffer) { + diff := len(buffer) - written + intrinsics.mem_copy(&buffer[0], &buffer[diff], written) + } + return written, nil +} + +// Old internal digit extraction procedure. +// We're keeping this around as ground truth for the tests. +_itoa_raw_old :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false, allocator := context.allocator) -> (written: int, err: Error) { + assert_if_nil(a) + context.allocator = allocator + + temp := &Int{} + internal_copy(temp, a) or_return + defer internal_destroy(temp) available := len(buffer) if zero_terminate { @@ -619,7 +667,6 @@ _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false remainder: DIGIT for { if remainder, err = #force_inline internal_divmod(temp, temp, DIGIT(radix)); err != nil { - internal_destroy(temp, denominator) return len(buffer) - available, err } available -= 1 @@ -634,15 +681,13 @@ _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false buffer[available] = '-' } - internal_destroy(temp, denominator) - /* If we overestimated the size, we need to move the buffer left. */ written = len(buffer) - available if written < len(buffer) { diff := len(buffer) - written - mem.copy(&buffer[0], &buffer[diff], written) + intrinsics.mem_copy(&buffer[0], &buffer[diff], written) } return written, nil } \ No newline at end of file diff --git a/core/math/big/radix_os.odin b/core/math/big/radix_os.odin new file mode 100644 index 000000000..793a6c88a --- /dev/null +++ b/core/math/big/radix_os.odin @@ -0,0 +1,79 @@ +#+build !freestanding +#+build !js +package math_big + +/* + Copyright 2021 Jeroen van Rijn . + Made available under Odin's license. + + An arbitrary precision mathematics implementation in Odin. + For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. + The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. + + This file contains radix conversions, `string_to_int` (atoi) and `int_to_string` (itoa). + + TODO: + - Use Barrett reduction for non-powers-of-two. + - Also look at extracting and splatting several digits at once. +*/ + +import "base:runtime" +import "core:os" + +/* + We might add functions to read and write byte-encoded Ints from/to files, using `int_to_bytes_*` functions. + + LibTomMath allows exporting/importing to/from a file in ASCII, but it doesn't support a much more compact representation in binary, even though it has several pack functions int_to_bytes_* (which I expanded upon and wrote Python interoperable versions of as well), and (un)pack, which is GMP compatible. + Someone could implement their own read/write binary int procedures, of course. + + Could be worthwhile to add a canonical binary file representation with an optional small header that says it's an Odin big.Int, big.Rat or Big.Float, byte count for each component that follows, flag for big/little endian and a flag that says a checksum exists at the end of the file. + For big.Rat and big.Float the header couldn't be optional, because we'd have no way to distinguish where the components end. +*/ + +/* + Read an Int from an ASCII file. +*/ +internal_int_read_from_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + /* + We can either read the entire file at once, or read a bunch at a time and keep multiplying by the radix. + For now, we'll read the entire file. Eventually we'll replace this with a copy that duplicates the logic + of `atoi` so we don't need to read the entire file. + */ + res, res_err := os.read_entire_file(filename, allocator) + defer delete(res, allocator) + + if res_err != nil { + return .Cannot_Read_File + } + + as := string(res) + return atoi(a, as, radix) +} + +/* + Write an Int to an ASCII file. +*/ +internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + /* + For now we'll convert the Int using itoa and writing the result in one go. + If we want to preserve memory we could duplicate the itoa logic and write backwards. + */ + + as := itoa(a, radix) or_return + defer delete(as) + + l := len(as) + assert(l > 0) + + data := transmute([]u8)runtime.Raw_Slice{ + data = raw_data(as), + len = l, + } + + write_err := os.write_entire_file(filename, data, truncate=true) + return nil if write_err == nil else .Cannot_Write_File +} \ No newline at end of file diff --git a/core/math/big/rat.odin b/core/math/big/rat.odin index e0e58b80f..3c32d45cb 100644 --- a/core/math/big/rat.odin +++ b/core/math/big/rat.odin @@ -157,6 +157,8 @@ internal_rat_norm :: proc(z: ^Rat, allocator := context.allocator) -> (err: Erro z.b.sign = .Zero_or_Positive f := &Int{} + defer internal_int_destroy(f) + internal_int_gcd(f, &z.a, &z.b) or_return if !internal_int_equals_digit(f, 1) { f.sign = .Zero_or_Positive @@ -378,9 +380,6 @@ internal_rat_to_float :: proc($T: typeid, z: ^Rat, allocator := context.allocato } has_sign := a.sign != b.sign - defer if has_sign { - f = -builtin.abs(f) - } exp := alen - blen a2, b2 := &Int{}, &Int{} @@ -440,6 +439,9 @@ internal_rat_to_float :: proc($T: typeid, z: ^Rat, allocator := context.allocato if math.is_inf(f, 0) { exact = false } + if has_sign { + f = -builtin.abs(f) + } return } diff --git a/core/math/big/tune.odin b/core/math/big/tune.odin index eab36b951..b2dc9829c 100644 --- a/core/math/big/tune.odin +++ b/core/math/big/tune.odin @@ -1,15 +1,15 @@ +#+build ignore +package math_big + /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. A BigInt implementation in Odin. For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. */ -#+build ignore -package math_big - import "core:time" import "base:runtime" diff --git a/core/math/bits/bits.odin b/core/math/bits/bits.odin index 154b5a142..1e8d765dd 100644 --- a/core/math/bits/bits.odin +++ b/core/math/bits/bits.odin @@ -1,27 +1,51 @@ +// Bit-level operations, including the ability to set or toggle individual bits in an integer. package math_bits import "base:intrinsics" +// The minimum value held by a `u8`. The same value as `min(u8)`, except untyped. U8_MIN :: 0 +// The minimum value held by a `u16`. The same value as `min(u16)`, except untyped. U16_MIN :: 0 +// The minimum value held by a `u32`. The same value as `min(u32)`, except untyped. U32_MIN :: 0 +// The minimum value held by a `u64`. The same value as `min(u64)`, except untyped. U64_MIN :: 0 +// The minimum value held by a `uint`. The same value as `min(uint)`, except untyped. +UINT_MIN :: 0 +// The maximum value held by a `u8`. The same value as `max(u8)`, except untyped. U8_MAX :: 1 << 8 - 1 +// The maximum value held by a `u16`. The same value as `max(u16)`, except untyped. U16_MAX :: 1 << 16 - 1 +// The maximum value held by a `u32`. The same value as `max(u32)`, except untyped. U32_MAX :: 1 << 32 - 1 +// The maximum value held by a `u64`. The same value as `max(u64)`, except untyped. U64_MAX :: 1 << 64 - 1 +// The maximum value held by a `uint`. The same value as `max(uint)`, except untyped. +UINT_MAX :: U64_MAX when size_of(uint) == 8 else U32_MAX +// The minimum value held by an `i8`. The same value as `min(i8)`, except untyped. I8_MIN :: - 1 << 7 +// The minimum value held by an `i16`. The same value as `min(i16)`, except untyped. I16_MIN :: - 1 << 15 +// The minimum value held by an `i32`. The same value as `min(i32)`, except untyped. I32_MIN :: - 1 << 31 +// The minimum value held by an `i64`. The same value as `min(i64)`, except untyped. I64_MIN :: - 1 << 63 +// The minimum value held by an `int`. The same value as `min(int)`, except untyped. +INT_MIN :: I64_MIN when size_of(int) == 8 else I32_MIN +// The maximum value held by an `i8`. The same value as `max(i8)`, except untyped. I8_MAX :: 1 << 7 - 1 +// The maximum value held by an `i16`. The same value as `max(i16)`, except untyped. I16_MAX :: 1 << 15 - 1 +// The maximum value held by an `i32`. The same value as `max(i32)`, except untyped. I32_MAX :: 1 << 31 - 1 +// The maximum value held by an `i64`. The same value as `max(i64)`, except untyped. I64_MAX :: 1 << 63 - 1 - +// The maximum value held by an `int`. The same value as `max(int)`, except untyped. +INT_MAX :: I64_MAX when size_of(int) == 8 else I32_MAX count_ones :: intrinsics.count_ones count_zeros :: intrinsics.count_zeros @@ -31,100 +55,440 @@ count_trailing_zeros :: intrinsics.count_trailing_zeros count_leading_zeros :: intrinsics.count_leading_zeros reverse_bits :: intrinsics.reverse_bits byte_swap :: intrinsics.byte_swap +overflowing_add :: intrinsics.overflow_add +overflowing_sub :: intrinsics.overflow_sub +overflowing_mul :: intrinsics.overflow_mul -overflowing_add :: intrinsics.overflow_add -overflowing_sub :: intrinsics.overflow_sub -overflowing_mul :: intrinsics.overflow_mul +/* +Returns the base-2 logarithm of an unsigned integer `x` +Another way to say this is that `log2(x)` is the position of its leading `1` bit. +NOTE: This is ill-defined for `0` as it has no `1` bits, and `log2(0)` will return `max(T)`. + +Inputs: +- x: The unsigned integer + +Returns: +- res: The base-2 logarithm of `x` + +Example: + + import "core:fmt" + import "core:math/bits" + + log2_example :: proc() { + for i in u8(1)..=8 { + fmt.printfln("{0} ({0:4b}): {1}", i, bits.log2(i)) + } + assert(bits.log2( u8(0)) == max(u8)) + assert(bits.log2( u16(0)) == max(u16)) + assert(bits.log2( u32(0)) == max(u32)) + assert(bits.log2( u64(0)) == max(u64)) + assert(bits.log2(u128(0)) == max(u128)) + } + +Output: + + 1 (0001): 0 + 2 (0010): 1 + 3 (0011): 1 + 4 (0100): 2 + 5 (0101): 2 + 6 (0110): 2 + 7 (0111): 2 + 8 (1000): 3 + +*/ @(require_results) -log2 :: proc "contextless" (x: $T) -> T where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) { +log2 :: proc "contextless" (x: $T) -> (res: T) where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) { return (8*size_of(T)-1) - count_leading_zeros(x) } +/* +Returns unsigned integer `x` rotated left by `k` bits + +Can be thought of as a bit shift in which the leading bits are shifted back in on the bottom, rather than dropped. + +This is equivalent to the [[ROL ; https://www.felixcloutier.com/x86/rcl:rcr:rol:ror]] CPU instruction. + +Inputs: +- x: The unsigned integer +- k: Number of bits to rotate left by + +Returns: +- res: `x` rotated left by `k` bits + +Example: + + import "core:fmt" + import "core:math/bits" + + rotate_left8_example :: proc() { + x := u8(13) + for k in 0..<8 { + fmt.printfln("{0:8b}: {1}", bits.rotate_left8(x, k), k) + } + } + +Output: + + 00001101: 0 + 00011010: 1 + 00110100: 2 + 01101000: 3 + 11010000: 4 + 10100001: 5 + 01000011: 6 + 10000110: 7 + +*/ @(require_results) rotate_left8 :: proc "contextless" (x: u8, k: int) -> u8 { n :: 8 s := uint(k) & (n-1) - return x <>(n-s) + return x << s | x >> (n-s) } + +/* +Returns unsigned integer `x` rotated left by `k` bits + +Can be thought of as a bit shift in which the leading bits are shifted back in on the bottom, rather than dropped. + +This is equivalent to the [[ROL ; https://www.felixcloutier.com/x86/rcl:rcr:rol:ror]] CPU instruction. + +Inputs: +- x: The unsigned integer +- k: Number of bits to rotate left by + +Returns: +- res: `x` rotated left by `k` bits +*/ @(require_results) rotate_left16 :: proc "contextless" (x: u16, k: int) -> u16 { n :: 16 s := uint(k) & (n-1) - return x <>(n-s) + return x << s | x >>(n-s) } + +/* +Returns unsigned integer `x` rotated left by `k` bits + +Can be thought of as a bit shift in which the leading bits are shifted back in on the bottom, rather than dropped. + +This is equivalent to the [[ROL ; https://www.felixcloutier.com/x86/rcl:rcr:rol:ror]] CPU instruction. + +Inputs: +- x: The unsigned integer +- k: Number of bits to rotate left by + +Returns: +- res: `x` rotated left by `k` bits +*/ @(require_results) rotate_left32 :: proc "contextless" (x: u32, k: int) -> u32 { n :: 32 s := uint(k) & (n-1) - return x <>(n-s) + return x << s | x >> (n-s) } + +/* +Returns unsigned integer `x` rotated left by `k` bits + +Can be thought of as a bit shift in which the leading bits are shifted back in on the bottom, rather than dropped. + +This is equivalent to the [[ROL ; https://www.felixcloutier.com/x86/rcl:rcr:rol:ror]] CPU instruction. + +Inputs: +- x: The unsigned integer +- k: Number of bits to rotate left by + +Returns: +- res: `x` rotated left by `k` bits +*/ @(require_results) rotate_left64 :: proc "contextless" (x: u64, k: int) -> u64 { n :: 64 s := uint(k) & (n-1) - return x <>(n-s) + return x << s | x >> (n-s) } +/* +Returns unsigned integer `x` rotated left by `k` bits + +Can be thought of as a bit shift in which the leading bits are shifted back in on the bottom, rather than dropped. + +This is equivalent to the [[ROL ; https://www.felixcloutier.com/x86/rcl:rcr:rol:ror]] CPU instruction. + +Inputs: +- x: The unsigned integer +- k: Number of bits to rotate left by + +Returns: +- res: `x` rotated left by `k` bits +*/ @(require_results) rotate_left :: proc "contextless" (x: uint, k: int) -> uint { n :: 8*size_of(uint) s := uint(k) & (n-1) - return x <>(n-s) + return x << s | x >> (n-s) } +/* +Returns unsigned integer `i` + +NOTE: A byte has no endianness, so `from_be_u8` exists to be complementary to `from_be_*`. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i` +*/ @(require_results) from_be_u8 :: proc "contextless" (i: u8) -> u8 { return i } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } +/* +Returns unsigned integer `i` + +NOTE: A byte has no endianness, so `from_le_u8` exists to be complementary to `from_le_*`. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i` +*/ @(require_results) from_le_u8 :: proc "contextless" (i: u8) -> u8 { return i } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) from_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } +/* +Returns unsigned integer `i` + +NOTE: A byte has no endianness, so `to_be_u8` exists to be complementary to `to_be_*`. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i` +*/ @(require_results) to_be_u8 :: proc "contextless" (i: u8) -> u8 { return i } @(require_results) + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ to_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a little endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_be_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } } +/* +Returns unsigned integer `i` +NOTE: A byte has no endianness, so `to_le_u8` exists to be complementary to `to_le_*`. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i` +*/ @(require_results) to_le_u8 :: proc "contextless" (i: u8) -> u8 { return i } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } + +/* +Returns unsigned integer `i`, byte-swapped if we're on a big endian target. + +Inputs: +- i: The unsigned integer + +Returns: +- res: `i`, optionally byte-swapped +*/ @(require_results) to_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } } - - +// returns the minimum number of bits required to represent x @(require_results) len_u8 :: proc "contextless" (x: u8) -> int { return int(len_u8_table[x]) } + +// returns the minimum number of bits required to represent x @(require_results) len_u16 :: proc "contextless" (x: u16) -> (n: int) { x := x @@ -134,6 +498,8 @@ len_u16 :: proc "contextless" (x: u16) -> (n: int) { } return n + int(len_u8_table[x]) } + +// returns the minimum number of bits required to represent x @(require_results) len_u32 :: proc "contextless" (x: u32) -> (n: int) { x := x @@ -147,6 +513,8 @@ len_u32 :: proc "contextless" (x: u32) -> (n: int) { } return n + int(len_u8_table[x]) } + +// returns the minimum number of bits required to represent x @(require_results) len_u64 :: proc "contextless" (x: u64) -> (n: int) { x := x @@ -164,6 +532,8 @@ len_u64 :: proc "contextless" (x: u64) -> (n: int) { } return n + int(len_u8_table[x]) } + +// returns the minimum number of bits required to represent x @(require_results) len_uint :: proc "contextless" (x: uint) -> (n: int) { when size_of(uint) == size_of(u64) { @@ -176,23 +546,60 @@ len_uint :: proc "contextless" (x: uint) -> (n: int) { // returns the minimum number of bits required to represent x len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint} +/* +Add with carry +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- carry: Carry in + +Returns: +- sum: The sum +- carry_out: Carry out +*/ @(require_results) add_u32 :: proc "contextless" (x, y, carry: u32) -> (sum, carry_out: u32) { tmp_carry, tmp_carry2: bool - sum, tmp_carry = intrinsics.overflow_add(x, y) + sum, tmp_carry = intrinsics.overflow_add(x, y) sum, tmp_carry2 = intrinsics.overflow_add(sum, carry) carry_out = u32(tmp_carry | tmp_carry2) return } + +/* +Add with carry + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- carry: Carry in + +Returns: +- sum: The sum +- carry_out: Carry out +*/ @(require_results) add_u64 :: proc "contextless" (x, y, carry: u64) -> (sum, carry_out: u64) { tmp_carry, tmp_carry2: bool - sum, tmp_carry = intrinsics.overflow_add(x, y) + sum, tmp_carry = intrinsics.overflow_add(x, y) sum, tmp_carry2 = intrinsics.overflow_add(sum, carry) carry_out = u64(tmp_carry | tmp_carry2) return } + +/* +Add with carry + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- carry: Carry in + +Returns: +- sum: The sum +- carry_out: Carry out +*/ @(require_results) add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) { when size_of(uint) == size_of(u64) { @@ -203,17 +610,54 @@ add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) { } return uint(a), uint(b) } + +/* +Add with carry + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- carry: Carry in + +Returns: +- sum: The sum +- carry_out: Carry out +*/ add :: proc{add_u32, add_u64, add_uint} +/* +Subtract with borrow +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- borrow: Borrow in + +Returns: +- diff: The difference +- borrow_out: Borrow out +*/ @(require_results) sub_u32 :: proc "contextless" (x, y, borrow: u32) -> (diff, borrow_out: u32) { tmp_borrow, tmp_borrow2: bool - diff, tmp_borrow = intrinsics.overflow_sub(x, y) + diff, tmp_borrow = intrinsics.overflow_sub(x, y) diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow) borrow_out = u32(tmp_borrow | tmp_borrow2) return } + +/* +Subtract with borrow + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- borrow: Borrow in + +Returns: +- diff: The difference +- borrow_out: Borrow out +*/ @(require_results) sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) { tmp_borrow, tmp_borrow2: bool @@ -222,6 +666,19 @@ sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) { borrow_out = u64(tmp_borrow | tmp_borrow2) return } + +/* +Subtract with borrow + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- borrow: Borrow in + +Returns: +- diff: The difference +- borrow_out: Borrow out +*/ @(require_results) sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint) { when size_of(uint) == size_of(u64) { @@ -232,15 +689,50 @@ sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint) } return uint(a), uint(b) } + +/* +Subtract with borrow + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer +- borrow: Borrow in + +Returns: +- diff: The difference +- borrow_out: Borrow out +*/ sub :: proc{sub_u32, sub_u64, sub_uint} +/* +Multiply two words and return the result in high and low word +Inputs: +- x: The unsigned integer +- y: Another unsigned integer + +Returns: +- hi: The result's high word +- lo: The result's low word +*/ @(require_results) mul_u32 :: proc "contextless" (x, y: u32) -> (hi, lo: u32) { z := u64(x) * u64(y) hi, lo = u32(z>>32), u32(z) return } + +/* +Multiply two words and return the result in high and low word + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer + +Returns: +- hi: The result's high word +- lo: The result's low word +*/ @(require_results) mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) { prod_wide := u128(x) * u128(y) @@ -248,6 +740,17 @@ mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) { return } +/* +Multiply two words and return the result in high and low word + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer + +Returns: +- hi: The result's high word +- lo: The result's low word +*/ @(require_results) mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) { when size_of(uint) == size_of(u32) { @@ -259,9 +762,31 @@ mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) { return uint(a), uint(b) } +/* +Multiply two words and return the result in high and low word + +Inputs: +- x: The unsigned integer +- y: Another unsigned integer + +Returns: +- hi: The result's high word +- lo: The result's low word +*/ mul :: proc{mul_u32, mul_u64, mul_uint} +/* +Divide a 64-bit unsigned integer (in two 32-bit words) by a 32-bit divisor +Inputs: +- hi: High word of 64-bit integer +- lo: Low word of 64-bit integer +- y: Divisor + +Returns: +- quo: 32-bit quotient +- rem: 32-bit remainder +*/ @(require_results) div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) { assert(y != 0 && y <= hi) @@ -269,6 +794,19 @@ div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) { quo, rem = u32(z/u64(y)), u32(z%u64(y)) return } + +/* +Divide a 128-bit unsigned integer (in two 64-bit words) by a 64-bit divisor + +Inputs: +- hi: High word of 128-bit integer +- lo: Low word of 128-bit integer +- y: Divisor + +Returns: +- quo: 64-bit quotient +- rem: 64-bit Remainder +*/ @(require_results) div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) { y := y @@ -315,6 +853,19 @@ div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) { return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s } + +/* +Divide an unsigned integer (in two words) by a divisor + +Inputs: +- hi: High word of input +- lo: Low word of input +- y: Divisor + +Returns: +- quo: Quotient +- rem: Remainder +*/ @(require_results) div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) { when size_of(uint) == size_of(u32) { @@ -325,31 +876,150 @@ div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) { } return uint(a), uint(b) } + +/* +Divide an unsigned integer (in two words) by a divisor + +Inputs: +- hi: High word of input +- lo: Low word of input +- y: Divisor + +Returns: +- quo: Quotient +- rem: Remainder +*/ div :: proc{div_u32, div_u64, div_uint} +/* +Checks whether an unsigned number is a power of two +Inputs: +- i: Unsigned number +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ @(require_results) -is_power_of_two_u8 :: proc "contextless" (i: u8) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_i8 :: proc "contextless" (i: i8) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_u16 :: proc "contextless" (i: u16) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_i16 :: proc "contextless" (i: i16) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_u32 :: proc "contextless" (i: u32) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_i32 :: proc "contextless" (i: i32) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_u64 :: proc "contextless" (i: u64) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_i64 :: proc "contextless" (i: i64) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_uint :: proc "contextless" (i: uint) -> bool { return i > 0 && (i & (i-1)) == 0 } -@(require_results) -is_power_of_two_int :: proc "contextless" (i: int) -> bool { return i > 0 && (i & (i-1)) == 0 } +is_power_of_two_u8 :: proc "contextless" (i: u8) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_i8 :: proc "contextless" (i: i8) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_u16 :: proc "contextless" (i: u16) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_i16 :: proc "contextless" (i: i16) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_u32 :: proc "contextless" (i: u32) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_i32 :: proc "contextless" (i: i32) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_u64 :: proc "contextless" (i: u64) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_i64 :: proc "contextless" (i: i64) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_uint :: proc "contextless" (i: uint) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ +@(require_results) +is_power_of_two_int :: proc "contextless" (i: int) -> (is_pot: bool) { return i > 0 && (i & (i-1)) == 0 } + +/* +Checks whether an unsigned number is a power of two + +Inputs: +- i: Unsigned number + +Returns: +- is_pot: `true` if `i` is a power of two, `false` otherwise +*/ is_power_of_two :: proc{ is_power_of_two_u8, is_power_of_two_i8, is_power_of_two_u16, is_power_of_two_i16, @@ -372,20 +1042,101 @@ len_u8_table := [256]u8{ 128..<256 = 8, } +/* +Extracts bits from an unsigned integer -@(require_results) -bitfield_extract_u8 :: proc "contextless" (value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1< u16 { return (value >> offset) & u16(1< u32 { return (value >> offset) & u32(1< u64 { return (value >> offset) & u64(1< u128 { return (value >> offset) & u128(1< uint { return (value >> offset) & uint(1< (res: u8) { return (value >> offset) & u8(1< (res: u16) { return (value >> offset) & u16(1< (res: u32) { return (value >> offset) & u32(1< (res: u64) { return (value >> offset) & u64(1< (res: u128) { return (value >> offset) & u128(1< (res: uint) { return (value >> offset) & uint(1< i8 { v := (u8(value) >> offset) & u8(1< i8 r := (v~m) - m return i8(r) } + +/* +Extracts bits from a signed integer + +Inputs: +- value: Signed integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ @(require_results) bitfield_extract_i16 :: proc "contextless" (value: i16, offset, bits: uint) -> i16 { v := (u16(value) >> offset) & u16(1< i r := (v~m) - m return i16(r) } + +/* +Extracts bits from a signed integer + +Inputs: +- value: Signed integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ @(require_results) bitfield_extract_i32 :: proc "contextless" (value: i32, offset, bits: uint) -> i32 { v := (u32(value) >> offset) & u32(1< i r := (v~m) - m return i32(r) } + +/* +Extracts bits from a signed integer + +Inputs: +- value: Signed integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ @(require_results) bitfield_extract_i64 :: proc "contextless" (value: i64, offset, bits: uint) -> i64 { v := (u64(value) >> offset) & u64(1< i r := (v~m) - m return i64(r) } + +/* +Extracts bits from a signed integer + +Inputs: +- value: Signed integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ @(require_results) bitfield_extract_i128 :: proc "contextless" (value: i128, offset, bits: uint) -> i128 { v := (u128(value) >> offset) & u128(1< r := (v~m) - m return i128(r) } + +/* +Extracts bits from a signed integer + +Inputs: +- value: Signed integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ @(require_results) bitfield_extract_int :: proc "contextless" (value: int, offset, bits: uint) -> int { v := (uint(value) >> offset) & uint(1< i return int(r) } +/* +Extracts bits from an integer +Inputs: +- value: Integer +- offset: Offset (counting from LSB) at which to extract +- bits: Number of bits to extract + +Returns: +- res: `bits` bits starting at offset `offset` +*/ bitfield_extract :: proc{ bitfield_extract_u8, bitfield_extract_u16, @@ -445,69 +1266,260 @@ bitfield_extract :: proc{ bitfield_extract_int, } +/* +Insert a subset of bits from one integer into another integer +Copies `bits` number of `insert`'s lower bits to `base` at `offset`. + +Inputs: +- base: Original integer to insert bits into +- insert: Integer to copy bits from +- offset: Bit offset in `base` at which to place `insert`'s bits +- bits: Number of bits to copy + +Returns: +- res: `base` with `bits` bits at `offset` replaced with `insert`'s +*/ @(require_results) -bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> u8 { +bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> (res: u8) { mask := u8(1< u16 { +bitfield_insert_u16 :: proc "contextless" (base, insert: u16, offset, bits: uint) -> (res: u16) { mask := u16(1< u32 { +bitfield_insert_u32 :: proc "contextless" (base, insert: u32, offset, bits: uint) -> (res: u32) { mask := u32(1< u64 { +bitfield_insert_u64 :: proc "contextless" (base, insert: u64, offset, bits: uint) -> (res: u64) { mask := u64(1< u128 { +bitfield_insert_u128 :: proc "contextless" (base, insert: u128, offset, bits: uint) -> (res: u128) { mask := u128(1< uint { +bitfield_insert_uint :: proc "contextless" (base, insert: uint, offset, bits: uint) -> (res: uint) { mask := uint(1< i8 { +bitfield_insert_i8 :: proc "contextless" (base, insert: i8, offset, bits: uint) -> (res: i8) { mask := i8(1< i16 { +bitfield_insert_i16 :: proc "contextless" (base, insert: i16, offset, bits: uint) -> (res: i16) { mask := i16(1< i32 { +bitfield_insert_i32 :: proc "contextless" (base, insert: i32, offset, bits: uint) -> (res: i32) { mask := i32(1< i64 { +bitfield_insert_i64 :: proc "contextless" (base, insert: i64, offset, bits: uint) -> (res: i64) { mask := i64(1< i128 { +bitfield_insert_i128 :: proc "contextless" (base, insert: i128, offset, bits: uint) -> (res: i128) { mask := i128(1< int { +bitfield_insert_int :: proc "contextless" (base, insert: int, offset, bits: uint) -> (res: int) { mask := int(1< T where intrinsics.type_is_f if p == 0.0 || p == 1.0 { return p } - + if p < 0.5 { return 0.5 * math.pow(2, (20 * p) - 10) } else { @@ -307,224 +306,51 @@ Ease :: enum { } @(require_results) -ease :: proc "contextless" (type: Ease, p: $T) -> T - where intrinsics.type_is_float(T) { +ease :: proc "contextless" (type: Ease, p: $T) -> T where intrinsics.type_is_float(T) { switch type { - case .Linear: return p + case .Linear: return p - case .Quadratic_In: return quadratic_in(p) - case .Quadratic_Out: return quadratic_out(p) - case .Quadratic_In_Out: return quadratic_in_out(p) + case .Quadratic_In: return quadratic_in(p) + case .Quadratic_Out: return quadratic_out(p) + case .Quadratic_In_Out: return quadratic_in_out(p) - case .Cubic_In: return cubic_in(p) - case .Cubic_Out: return cubic_out(p) - case .Cubic_In_Out: return cubic_in_out(p) + case .Cubic_In: return cubic_in(p) + case .Cubic_Out: return cubic_out(p) + case .Cubic_In_Out: return cubic_in_out(p) - case .Quartic_In: return quartic_in(p) - case .Quartic_Out: return quartic_out(p) - case .Quartic_In_Out: return quartic_in_out(p) + case .Quartic_In: return quartic_in(p) + case .Quartic_Out: return quartic_out(p) + case .Quartic_In_Out: return quartic_in_out(p) - case .Quintic_In: return quintic_in(p) - case .Quintic_Out: return quintic_out(p) - case .Quintic_In_Out: return quintic_in_out(p) + case .Quintic_In: return quintic_in(p) + case .Quintic_Out: return quintic_out(p) + case .Quintic_In_Out: return quintic_in_out(p) - case .Sine_In: return sine_in(p) - case .Sine_Out: return sine_out(p) - case .Sine_In_Out: return sine_in_out(p) + case .Sine_In: return sine_in(p) + case .Sine_Out: return sine_out(p) + case .Sine_In_Out: return sine_in_out(p) - case .Circular_In: return circular_in(p) - case .Circular_Out: return circular_out(p) - case .Circular_In_Out: return circular_in_out(p) + case .Circular_In: return circular_in(p) + case .Circular_Out: return circular_out(p) + case .Circular_In_Out: return circular_in_out(p) - case .Exponential_In: return exponential_in(p) - case .Exponential_Out: return exponential_out(p) + case .Exponential_In: return exponential_in(p) + case .Exponential_Out: return exponential_out(p) case .Exponential_In_Out: return exponential_in_out(p) - case .Elastic_In: return elastic_in(p) - case .Elastic_Out: return elastic_out(p) - case .Elastic_In_Out: return elastic_in_out(p) + case .Elastic_In: return elastic_in(p) + case .Elastic_Out: return elastic_out(p) + case .Elastic_In_Out: return elastic_in_out(p) - case .Back_In: return back_in(p) - case .Back_Out: return back_out(p) - case .Back_In_Out: return back_in_out(p) + case .Back_In: return back_in(p) + case .Back_Out: return back_out(p) + case .Back_In_Out: return back_in_out(p) - case .Bounce_In: return bounce_in(p) - case .Bounce_Out: return bounce_out(p) - case .Bounce_In_Out: return bounce_in_out(p) + case .Bounce_In: return bounce_in(p) + case .Bounce_Out: return bounce_out(p) + case .Bounce_In_Out: return bounce_in_out(p) } // in case type was invalid return 0 } -Flux_Map :: struct($T: typeid) { - values: map[^T]Flux_Tween(T), - keys_to_be_deleted: [dynamic]^T, -} - -Flux_Tween :: struct($T: typeid) { - value: ^T, - start: T, - diff: T, - goal: T, - - delay: f64, // in seconds - duration: time.Duration, - - progress: f64, - rate: f64, - type: Ease, - - inited: bool, - - // callbacks, data can be set, will be pushed to callback - data: rawptr, // by default gets set to value input - on_start: proc(flux: ^Flux_Map(T), data: rawptr), - on_update: proc(flux: ^Flux_Map(T), data: rawptr), - on_complete: proc(flux: ^Flux_Map(T), data: rawptr), -} - -// init flux map to a float type and a wanted cap -@(require_results) -flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) { - return { - values = make(map[^T]Flux_Tween(T), value_capacity), - keys_to_be_deleted = make([dynamic]^T, 0, value_capacity), - } -} - -// delete map content -flux_destroy :: proc(flux: Flux_Map($T)) where intrinsics.type_is_float(T) { - delete(flux.values) - delete(flux.keys_to_be_deleted) -} - -// clear map content, stops all animations -flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) { - clear(&flux.values) -} - -// append / overwrite existing tween value to parameters -// rest is initialized in flux_tween_init, inside update -// return value can be used to set callbacks -@(require_results) -flux_to :: proc( - flux: ^Flux_Map($T), - value: ^T, - goal: T, - type: Ease = .Quadratic_Out, - duration: time.Duration = time.Second, - delay: f64 = 0, -) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) { - if res, ok := &flux.values[value]; ok { - tween = res - } else { - flux.values[value] = {} - tween = &flux.values[value] - } - - tween^ = { - value = value, - goal = goal, - duration = duration, - delay = delay, - type = type, - data = value, - } - - return -} - -// init internal properties -flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) { - tween.inited = true - tween.start = tween.value^ - tween.diff = tween.goal - tween.value^ - s := time.duration_seconds(duration) - tween.rate = duration > 0 ? 1.0 / s : 0 - tween.progress = duration > 0 ? 0 : 1 -} - -// update all tweens, wait for their delay if one exists -// calls callbacks in all stages, when they're filled -// deletes tween from the map after completion -flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) { - clear(&flux.keys_to_be_deleted) - - for key, &tween in flux.values { - delay_remainder := f64(0) - - // Update delay if necessary. - if tween.delay > 0 { - tween.delay -= dt - - if tween.delay < 0 { - // We finished the delay, but in doing so consumed part of this frame's `dt` budget. - // Keep track of it so we can apply it to this tween without affecting others. - delay_remainder = tween.delay - // We're done with this delay. - tween.delay = 0 - } - } - - // We either had no delay, or the delay has been consumed. - if tween.delay <= 0 { - if !tween.inited { - flux_tween_init(&tween, tween.duration) - - if tween.on_start != nil { - tween.on_start(flux, tween.data) - } - } - - // If part of the `dt` budget was consumed this frame, then `delay_remainder` will be - // that remainder, a negative value. Adding it to `dt` applies what's left of the `dt` - // to the tween so it advances properly, instead of too much or little. - tween.progress += tween.rate * (dt + delay_remainder) - x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress) - tween.value^ = tween.start + tween.diff * T(x) - - if tween.on_update != nil { - tween.on_update(flux, tween.data) - } - - if tween.progress >= 1 { - // append keys to array that will be deleted after the loop - append(&flux.keys_to_be_deleted, key) - - if tween.on_complete != nil { - tween.on_complete(flux, tween.data) - } - } - } - } - - // loop through keys that should be deleted from the map - if len(flux.keys_to_be_deleted) != 0 { - for key in flux.keys_to_be_deleted { - delete_key(&flux.values, key) - } - } -} - -// stop a specific key inside the map -// returns true when it successfully removed the key -@(require_results) -flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) { - if key in flux.values { - delete_key(&flux.values, key) - return true - } - - return false -} - -// returns the amount of time left for the tween animation, if the key exists in the map -// returns 0 if the tween doesnt exist on the map -@(require_results) -flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 { - if tween, ok := flux.values[key]; ok { - return ((1 - tween.progress) * tween.rate) + tween.delay - } else { - return 0 - } -} diff --git a/core/math/ease/ease_inverse.odin b/core/math/ease/ease_inverse.odin new file mode 100644 index 000000000..12d6394eb --- /dev/null +++ b/core/math/ease/ease_inverse.odin @@ -0,0 +1,250 @@ +// Inverse easing procedures +// These are the mathematical inverses of the corresponding easing functions, +// allowing you to reverse the transformation: +// if y = ease_fn(x), then x = ease_fn_inverse(y) + some_imprecision +package ease + +@require import "core:math" +import "base:intrinsics" + +// Helper for handling negative bases with fractional exponents +// since math.pow(negative, fraction) returns NaN +@(private) +_signed_pow :: proc "contextless" (x, exp: $T) -> T where intrinsics.type_is_float(T) { + if x >= 0 { + return math.pow(x, exp) + } else { + return -math.pow(-x, exp) + } +} + +@(private) PI_2_INV :: 2 / math.PI + +// Inverse of quadratic_in +// x = sqrt(y) +@(require_results) +quadratic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.sqrt(p) +} + +// Inverse of quadratic_out +// x = 1 - sqrt(1 - y) +@(require_results) +quadratic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return 1 - math.sqrt(1 - p) +} + +// Inverse of quadratic_in_out +// x = sqrt(y/2) ; [0, 0.5) +// x = 1 - sqrt((1-y)/2) ; [0.5, 1] +@(require_results) +quadratic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p < 0.5 { + return math.sqrt(p * 0.5) + } else { + return 1 - math.sqrt((1 - p) * 0.5) + } +} + +// Inverse of cubic_in +// x = y^(1/3) +@(require_results) +cubic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.pow(p, 1.0/3.0) +} + +// Inverse of cubic_out +// x = (y - 1)^(1/3) + 1 +@(require_results) +cubic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return _signed_pow(p - 1, 1.0/3.0) + 1 +} + +// Inverse of cubic_in_out +// x = (y/4)^(1/3) ; [0, 0.5) +// x = ((y-1)*2)^(1/3)/2 + 1 ; [0.5, 1] +@(require_results) +cubic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p < 0.5 { + return math.pow(p * 0.25, 1.0/3.0) + } else { + return _signed_pow((p - 1) * 2, 1.0/3.0) * 0.5 + 1 + } +} + +// Inverse of quartic_in +// x = y^(1/4) +@(require_results) +quartic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.pow(p, 0.25) +} + +// Inverse of quartic_out +// x = 1 - (1 - y)^(1/4) +@(require_results) +quartic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return 1 - math.pow(1 - p, 0.25) +} + +// Inverse of quartic_in_out +// x = (y/8)^(1/4) ; [0, 0.5) +// x = 1 - ((1-y)/8)^(1/4) ; [0.5, 1] +@(require_results) +quartic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p < 0.5 { + return math.pow(p * 0.125, 0.25) + } else { + return 1 - math.pow((1 - p) * 0.125, 0.25) + } +} + +// Inverse of quintic_in +// x = y^(1/5) +@(require_results) +quintic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.pow(p, 0.2) +} + +// Inverse of quintic_out +// x = (y - 1)^(1/5) + 1 +@(require_results) +quintic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return _signed_pow(p - 1, 0.2) + 1 +} + +// Inverse of quintic_in_out +// x = (y/16)^(1/5) ; [0, 0.5) +// x = ((y-1)*2)^(1/5)/2 + 1 ; [0.5, 1] +@(require_results) +quintic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p < 0.5 { + return math.pow(0.0625 * p, 0.2) + } else { + return _signed_pow((p - 1) * 2, 0.2) * 0.5 + 1 + } +} + +// Inverse of sine_in +// x = asin(y - 1) * 2/π + 1 +@(require_results) +sine_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.asin(p - 1) * PI_2_INV + 1 +} + +// Inverse of sine_out +// x = asin(y) * 2/π +@(require_results) +sine_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.asin(p) * PI_2_INV +} + +// Inverse of sine_in_out +// x = acos(1 - 2y) / π +@(require_results) +sine_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.acos(1 - 2*p) / math.PI +} + +// Inverse of circular_in +// x = sqrt(2y - y²) +@(require_results) +circular_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return math.sqrt(2*p - p*p) +} + +// Inverse of circular_out +// x = 1 - sqrt(1 - y²) +@(require_results) +circular_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return 1 - math.sqrt(1 - p*p) +} + +// Inverse of circular_in_out +// x = sqrt(1 - (1-2y)²) / 2 ; [0, 0.5) +// x = 1 - sqrt(1 - (2y-1)²) / 2 ; [0.5, 1] +@(require_results) +circular_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p < 0.5 { + q := 1 - 2*p + return 0.5 * math.sqrt(1 - q*q) + } else { + q := 2*p - 1 + return 1 - 0.5 * math.sqrt(1 - q*q) + } +} + +// Inverse of exponential_in +// x = log₂(y) / 10 + 1 +@(require_results) +exponential_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return p == 0.0 ? 0.0 : 0.1 * math.log2(p) + 1 +} + +// Inverse of exponential_out +// x = -log₂(1 - y) / 10 +@(require_results) +exponential_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + return p == 1.0 ? 1.0 : 0.1 * -math.log2(1 - p) +} + +// Inverse of exponential_in_out +// x = (log₂(2y) + 10) / 20 ; [0, 0.5) +// x = (10 - log₂(2(1-y))) / 20 ; [0.5, 1] +@(require_results) +exponential_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) { + if p == 0.0 || p == 1.0 { + return p + } + + if p < 0.5 { + return 0.05 * (math.log2(2*p) + 10) + } else { + return 0.05 * (10 - math.log2(2*(1-p))) + } +} + +// Additional enum variant + +@(require_results) +ease_inverse :: proc "contextless" (type: Ease, p: $T) -> T where intrinsics.type_is_float(T) { + switch type { + case .Linear: return p + + case .Quadratic_In: return quadratic_in_inverse(p) + case .Quadratic_Out: return quadratic_out_inverse(p) + case .Quadratic_In_Out: return quadratic_in_out_inverse(p) + + case .Cubic_In: return cubic_in_inverse(p) + case .Cubic_Out: return cubic_out_inverse(p) + case .Cubic_In_Out: return cubic_in_out_inverse(p) + + case .Quartic_In: return quartic_in_inverse(p) + case .Quartic_Out: return quartic_out_inverse(p) + case .Quartic_In_Out: return quartic_in_out_inverse(p) + + case .Quintic_In: return quintic_in_inverse(p) + case .Quintic_Out: return quintic_out_inverse(p) + case .Quintic_In_Out: return quintic_in_out_inverse(p) + + case .Sine_In: return sine_in_inverse(p) + case .Sine_Out: return sine_out_inverse(p) + case .Sine_In_Out: return sine_in_out_inverse(p) + + case .Circular_In: return circular_in_inverse(p) + case .Circular_Out: return circular_out_inverse(p) + case .Circular_In_Out: return circular_in_out_inverse(p) + + case .Exponential_In: return exponential_in_inverse(p) + case .Exponential_Out: return exponential_out_inverse(p) + case .Exponential_In_Out: return exponential_in_out_inverse(p) + + case .Elastic_In, .Elastic_Out, .Elastic_In_Out, + .Back_In, .Back_Out, .Back_In_Out, + .Bounce_In, .Bounce_Out, .Bounce_In_Out: + // These do not have simple closed-form inverses + return 0 + } + + // In case type was invalid + return 0 +} diff --git a/core/math/ease/flux.odin b/core/math/ease/flux.odin new file mode 100644 index 000000000..8a9de9636 --- /dev/null +++ b/core/math/ease/flux.odin @@ -0,0 +1,178 @@ +// Flux easing used for animations +package ease + +import "base:intrinsics" +import "core:time" + +Flux_Map :: struct($T: typeid) { + values: map[^T]Flux_Tween(T), + keys_to_be_deleted: [dynamic]^T, +} + +Flux_Tween :: struct($T: typeid) { + value: ^T, + start: T, + diff: T, + goal: T, + + delay: f64, // in seconds + duration: time.Duration, + + progress: f64, + rate: f64, + type: Ease, + + inited: bool, + + // callbacks, data can be set, will be pushed to callback + data: rawptr, // by default gets set to value input + on_start: proc(flux: ^Flux_Map(T), data: rawptr), + on_update: proc(flux: ^Flux_Map(T), data: rawptr), + on_complete: proc(flux: ^Flux_Map(T), data: rawptr), +} + +// init flux map to a float type and a wanted cap +@(require_results) +flux_init :: proc($T: typeid, value_capacity := 8, allocator := context.allocator, loc := #caller_location) -> Flux_Map(T) where intrinsics.type_is_float(T) { + return { + values = make(map[^T]Flux_Tween(T), value_capacity, allocator, loc), + keys_to_be_deleted = make([dynamic]^T, 0, value_capacity, allocator, loc), + } +} + +// delete map content +flux_destroy :: proc(flux: Flux_Map($T), allocator := context.allocator, loc := #caller_location) where intrinsics.type_is_float(T) { + delete(flux.values, loc) + delete(flux.keys_to_be_deleted, loc) +} + +// clear map content, stops all animations +flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) { + clear(&flux.values) +} + +// append / overwrite existing tween value to parameters +// rest is initialized in flux_tween_init, inside update +// return value can be used to set callbacks +@(require_results) +flux_to :: proc( + flux: ^Flux_Map($T), + value: ^T, + goal: T, + type: Ease = .Quadratic_Out, + duration: time.Duration = time.Second, + delay: f64 = 0, +) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) { + if res, ok := &flux.values[value]; ok { + tween = res + } else { + flux.values[value] = {} + tween = &flux.values[value] + } + + tween^ = { + value = value, + goal = goal, + duration = duration, + delay = delay, + type = type, + data = value, + } + + return +} + +// init internal properties +flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) { + tween.inited = true + tween.start = tween.value^ + tween.diff = tween.goal - tween.value^ + s := time.duration_seconds(duration) + tween.rate = duration > 0 ? 1.0 / s : 0 + tween.progress = duration > 0 ? 0 : 1 +} + +// update all tweens, wait for their delay if one exists +// calls callbacks in all stages, when they're filled +// deletes tween from the map after completion +flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) { + clear(&flux.keys_to_be_deleted) + + for key, &tween in flux.values { + delay_remainder := f64(0) + + // Update delay if necessary. + if tween.delay > 0 { + tween.delay -= dt + + if tween.delay < 0 { + // We finished the delay, but in doing so consumed part of this frame's `dt` budget. + // Keep track of it so we can apply it to this tween without affecting others. + delay_remainder = tween.delay + // We're done with this delay. + tween.delay = 0 + } + } + + // We either had no delay, or the delay has been consumed. + if tween.delay <= 0 { + if !tween.inited { + flux_tween_init(&tween, tween.duration) + + if tween.on_start != nil { + tween.on_start(flux, tween.data) + } + } + + // If part of the `dt` budget was consumed this frame, then `delay_remainder` will be + // that remainder, a negative value. Adding it to `dt` applies what's left of the `dt` + // to the tween so it advances properly, instead of too much or little. + tween.progress += tween.rate * (dt + delay_remainder) + x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress) + tween.value^ = tween.start + tween.diff * T(x) + + if tween.on_update != nil { + tween.on_update(flux, tween.data) + } + + if tween.progress >= 1 { + // append keys to array that will be deleted after the loop + append(&flux.keys_to_be_deleted, key) + + if tween.on_complete != nil { + tween.on_complete(flux, tween.data) + } + } + } + } + + // loop through keys that should be deleted from the map + if len(flux.keys_to_be_deleted) != 0 { + for key in flux.keys_to_be_deleted { + delete_key(&flux.values, key) + } + } +} + +// stop a specific key inside the map +// returns true when it successfully removed the key +@(require_results) +flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) { + if key in flux.values { + delete_key(&flux.values, key) + return true + } + + return false +} + +// returns the amount of time left for the tween animation, if the key exists in the map +// returns 0 if the tween doesn't exist on the map +@(require_results) +flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 { + if tween, ok := flux.values[key]; ok { + return ((1 - tween.progress) * tween.rate) + tween.delay + } else { + return 0 + } +} diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin index b23090307..6b9ef364b 100644 --- a/core/math/fixed/fixed.odin +++ b/core/math/fixed/fixed.odin @@ -1,3 +1,4 @@ +// Fixed-point rational numbers and conversion to/from `f64`. package math_fixed import "core:math" @@ -28,7 +29,7 @@ Fixed32_32 :: distinct Fixed(i64, 32) Fixed52_12 :: distinct Fixed(i64, 12) -init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { +init_from_f64 :: proc "contextless" (x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { i, f := math.modf(math.abs(val)) x.i = Backing(f * (1< f64 { +to_f64 :: proc "contextless" (x: $T/Fixed($Backing, $Fraction_Width)) -> f64 { sign := -1.0 if x.i < 0 else 1.0 num := math.abs(x.i) res := f64(num >> Fraction_Width) @@ -54,39 +55,39 @@ to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 { @(require_results) -add :: proc(x, y: $T/Fixed) -> T { +add :: proc "contextless" (x, y: $T/Fixed) -> T { return {x.i + y.i} } @(require_results) -sub :: proc(x, y: $T/Fixed) -> T { +sub :: proc "contextless" (x, y: $T/Fixed) -> T { return {x.i - y.i} } @(require_results) -mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { +mul :: proc "contextless" (x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width) return } @(require_results) -mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { +mul_sat :: proc "contextless" (x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width) return } @(require_results) -div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { +div :: proc "contextless" (x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width) return } @(require_results) -div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { +div_sat :: proc "contextless" (x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width) return } @(require_results) -floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { +floor :: proc "contextless" (x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { if x.i >= 0 { return x.i >> Fraction_Width } else { @@ -94,16 +95,16 @@ floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { } } @(require_results) -ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { +ceil :: proc "contextless" (x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { return (x.i + (1 << Fraction_Width - 1)) >> Fraction_Width } @(require_results) -round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { +round :: proc "contextless" (x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { return (x.i + (1 << (Fraction_Width - 1))) >> Fraction_Width } @(require_results) -append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { +write :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { Integer_Width :: 8*size_of(Backing) - Fraction_Width x := x @@ -124,16 +125,16 @@ append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { when size_of(Backing) < 16 { T :: u64 - append_uint :: strconv.append_uint + write_uint :: strconv.write_uint } else { T :: u128 - append_uint :: strconv.append_u128 + write_uint :: strconv.write_u128 } integer := T(x.i) >> Fraction_Width fraction := T(x.i) & (1< string { @(require_results) to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string { buf: [48]byte - s := append(buf[:], x) + s := write(buf[:], x) str := make([]byte, len(s), allocator) copy(str, s) return string(str) } -@(private) +@(rodata, private) _power_of_two_table := [129]string{ "0.5", "1", diff --git a/core/math/linalg/doc.odin b/core/math/linalg/doc.odin index 4bc9b674d..38a894148 100644 --- a/core/math/linalg/doc.odin +++ b/core/math/linalg/doc.odin @@ -1,2 +1,2 @@ -// core:math/linalg implements linear algebra procedures useful for 3D spatial transformations +// Linear algebra procedures useful for 3D spatial transformations. package linalg diff --git a/core/math/linalg/extended.odin b/core/math/linalg/extended.odin index 22c37dd0e..9e00a76d2 100644 --- a/core/math/linalg/extended.odin +++ b/core/math/linalg/extended.odin @@ -1,12 +1,13 @@ package linalg import "base:builtin" +import "base:intrinsics" import "core:math" @(require_results) to_radians :: proc "contextless" (degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_NUMERIC(ELEM @(require_results) to_degrees :: proc "contextless" (radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_NUMERIC(ELEM @(require_results) min_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: ELEM_TYPE(T)) where IS_NUMERIC out = builtin.min(a[0], a[1]) } else { out = builtin.min(a[0], a[1]) - for i in 2.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: ELEM_TYPE(T)) where IS_NUMERIC out = builtin.max(a[0], a[1], a[2]) }else { out = builtin.max(a[0], a[1]) - for i in 2.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results) sign :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { @(require_results) clamp :: proc "contextless" (x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) lerp :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T) @(require_results) mix :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) step :: proc "contextless" (e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. T where IS_FLOAT(ELEM_TYPE @(require_results) sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) inverse_sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE( @(require_results) cos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) sin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) tan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) acos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) asin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) atan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) atan2 :: proc "contextless" (y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) @(require_results) ln :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { log2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { INVLN2 :: 1.4426950408889634073599246810018921374266459541529859341354494069 when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { log10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { INVLN10 :: 0.4342944819032518276511289189166050822943970058036665661144537831 when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) log :: proc "contextless" (x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) exp :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) exp2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) exp10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) pow :: proc "contextless" (x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { @(require_results) ceil :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { - when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { - when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { - for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { return } +@(require_results) +trunc :: proc "contextless" (x: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { + return _from_simd4(T, intrinsics.simd_trunc(_to_simd4(x))) +} + @(require_results) fract :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { f := #force_inline floor(x) @@ -494,7 +486,7 @@ is_nan_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) { @(require_results) is_nan_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { - for i in 0.. bool where IS_FLOAT(T) { @(require_results) is_inf_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { - for i in 0.. math.Float_Class where IS_FLOAT @(require_results) classify_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) { - for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0.. y[i] } return } @(require_results) greater_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0..= y[i] } return } @(require_results) equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { - for i in 0.. (out: bool) { @(require_results) not :: proc "contextless" (x: $A/[$N]bool) -> (out: A) { for e, i in x { - out[i] = !e + #no_bounds_check out[i] = !e } return } + + +@(require_results) +_to_simd4 :: #force_inline proc "contextless" (a: $T) -> (out: #simd[4]ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) #no_bounds_check { + when IS_ARRAY(T) { + when len(T) == 1 { + _a: [4]ELEM_TYPE(T) + _a.x = a.x + return transmute(#simd[4]ELEM_TYPE(T))_a + } else when len(T) == 2 { + _a: [4]ELEM_TYPE(T) + _a.xy = a + return transmute(#simd[4]ELEM_TYPE(T))_a + } else when len(T) == 3 { + _a: [4]ELEM_TYPE(T) + _a.xyz = a + return transmute(#simd[4]ELEM_TYPE(T))_a + } else { + return transmute(#simd[4]ELEM_TYPE(T))a + } + } else { + _a: [4]ELEM_TYPE(T) + _a.x = a + return transmute(#simd[4]ELEM_TYPE(T))_a + } +} + +@(require_results) +_from_simd4 :: #force_inline proc "contextless" ($T: typeid, a: $V/#simd[4]$E) -> T where IS_NUMERIC(ELEM_TYPE(T)) #no_bounds_check { + when IS_ARRAY(T) { + when len(T) == 1 { + return (transmute([4]ELEM_TYPE(T))a).x + } else when len(T) == 2 { + return (transmute([4]ELEM_TYPE(T))a).xy + } else when len(T) == 3 { + return (transmute([4]ELEM_TYPE(T))a).xyz + } else { + return transmute([4]ELEM_TYPE(T))a + } + } else { + return (transmute([4]ELEM_TYPE(T))a).x + } +} diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin index 4a0150972..7013de244 100644 --- a/core/math/linalg/general.odin +++ b/core/math/linalg/general.odin @@ -46,11 +46,22 @@ scalar_dot :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) @(require_results) vector_dot :: proc "contextless" (a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check { - for i in 0.. (c: f16) { return a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z @@ -86,11 +97,8 @@ vector_cross2 :: proc "contextless" (a, b: $T/[2]$E) -> E where IS_NUMERIC(E) { } @(require_results) -vector_cross3 :: proc "contextless" (a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) { - c[0] = a[1]*b[2] - b[1]*a[2] - c[1] = a[2]*b[0] - b[2]*a[0] - c[2] = a[0]*b[1] - b[0]*a[1] - return +vector_cross3 :: proc "contextless" (a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) #no_bounds_check { + return a.yzx*b.zxy - b.yzx*a.zxy } @(require_results) @@ -130,12 +138,12 @@ normalize0 :: proc{vector_normalize0, quaternion_normalize0} @(require_results) vector_length :: proc "contextless" (v: $T/[$N]$E) -> E where IS_FLOAT(E) { - return math.sqrt(dot(v, v)) + return #force_inline math.sqrt(#force_inline dot(v, v)) } @(require_results) vector_length2 :: proc "contextless" (v: $T/[$N]$E) -> E where IS_NUMERIC(E) { - return dot(v, v) + return #force_inline dot(v, v) } @(require_results) @@ -359,11 +367,8 @@ cubic :: proc "contextless" (v1, v2, v3, v4: $T/[$N]$E, s: E) -> T #no_bounds_ch @(require_results) -array_cast :: proc "contextless" (v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check { - for i in 0.. [N]Elem_Type #no_bounds_check { + return ([N]Elem_Type)(v) } @(require_results) @@ -376,27 +381,28 @@ matrix_cast :: proc "contextless" (v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) - return } -@(require_results) to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32) } -@(require_results) to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64) } +@(require_results) to_f16 :: #force_inline proc(v: $A/[$N]$T) -> [N]f16 { return ([N]f16) (v) } +@(require_results) to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return ([N]f32) (v) } +@(require_results) to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return ([N]f64) (v) } -@(require_results) to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8) } -@(require_results) to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16) } -@(require_results) to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32) } -@(require_results) to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64) } -@(require_results) to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int) } +@(require_results) to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return ([N]i8) (v) } +@(require_results) to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return ([N]i16) (v) } +@(require_results) to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return ([N]i32) (v) } +@(require_results) to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return ([N]i64) (v) } +@(require_results) to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return ([N]int) (v) } -@(require_results) to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8) } -@(require_results) to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16) } -@(require_results) to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32) } -@(require_results) to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64) } -@(require_results) to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint) } +@(require_results) to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return ([N]u8) (v) } +@(require_results) to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return ([N]u16) (v) } +@(require_results) to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return ([N]u32) (v) } +@(require_results) to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return ([N]u64) (v) } +@(require_results) to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return ([N]uint)(v) } -@(require_results) to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) } -@(require_results) to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) } -@(require_results) to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) } -@(require_results) to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) } -@(require_results) to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) } -@(require_results) to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) } +@(require_results) to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return ([N]complex32) (v) } +@(require_results) to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return ([N]complex64) (v) } +@(require_results) to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return ([N]complex128) (v) } +@(require_results) to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return ([N]quaternion64) (v) } +@(require_results) to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return ([N]quaternion128)(v) } +@(require_results) to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return ([N]quaternion256)(v) } hadamard_product :: intrinsics.hadamard_product @@ -408,6 +414,10 @@ determinant :: proc{ matrix2x2_determinant, matrix3x3_determinant, matrix4x4_determinant, + matrix5x5_determinant, + matrix6x6_determinant, + matrix7x7_determinant, + matrix8x8_determinant, } adjugate :: proc{ @@ -415,6 +425,10 @@ adjugate :: proc{ matrix2x2_adjugate, matrix3x3_adjugate, matrix4x4_adjugate, + matrix5x5_adjugate, + matrix6x6_adjugate, + matrix7x7_adjugate, + matrix8x8_adjugate, } cofactor :: proc{ @@ -422,6 +436,10 @@ cofactor :: proc{ matrix2x2_cofactor, matrix3x3_cofactor, matrix4x4_cofactor, + matrix5x5_cofactor, + matrix6x6_cofactor, + matrix7x7_cofactor, + matrix8x8_cofactor, } inverse_transpose :: proc{ @@ -429,14 +447,21 @@ inverse_transpose :: proc{ matrix2x2_inverse_transpose, matrix3x3_inverse_transpose, matrix4x4_inverse_transpose, + matrix5x5_inverse_transpose, + matrix6x6_inverse_transpose, + matrix7x7_inverse_transpose, + matrix8x8_inverse_transpose, } - inverse :: proc{ matrix1x1_inverse, matrix2x2_inverse, matrix3x3_inverse, matrix4x4_inverse, + matrix5x5_inverse, + matrix6x6_inverse, + matrix7x7_inverse, + matrix8x8_inverse, } @(require_results) @@ -486,15 +511,96 @@ matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) # } @(require_results) matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) #no_bounds_check { - c := cofactor(m) - for i in 0..<4 { - det += m[0, i] * c[0, i] - } + s0 := m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1] + s1 := m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2] + s2 := m[0, 0] * m[1, 3] - m[1, 0] * m[0, 3] + s3 := m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2] + s4 := m[0, 1] * m[1, 3] - m[1, 1] * m[0, 3] + s5 := m[0, 2] * m[1, 3] - m[1, 2] * m[0, 3] + + c5 := m[2, 2] * m[3, 3] - m[3, 2] * m[2, 3] + c4 := m[2, 1] * m[3, 3] - m[3, 1] * m[2, 3] + c3 := m[2, 1] * m[3, 2] - m[3, 1] * m[2, 2] + c2 := m[2, 0] * m[3, 3] - m[3, 0] * m[2, 3] + c1 := m[2, 0] * m[3, 2] - m[3, 0] * m[2, 2] + c0 := m[2, 0] * m[3, 1] - m[3, 0] * m[2, 1] + + det = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0 return } +@(require_results) +matrix5x5_determinant :: proc "contextless" (m: $M/matrix[5, 5]$T) -> (det: T) #no_bounds_check { + return matrix_determinant_generic(m) +} +@(require_results) +matrix6x6_determinant :: proc "contextless" (m: $M/matrix[6, 6]$T) -> (det: T) #no_bounds_check { + return matrix_determinant_generic(m) +} +@(require_results) +matrix7x7_determinant :: proc "contextless" (m: $M/matrix[7, 7]$T) -> (det: T) #no_bounds_check { + return matrix_determinant_generic(m) +} + +@(require_results) +matrix8x8_determinant :: proc "contextless" (m: $M/matrix[8, 8]$T) -> (det: T) #no_bounds_check { + return matrix_determinant_generic(m) +} + +@(require_results) +matrix_determinant_generic :: proc "contextless" (a: $M/matrix[$N, N]$T) -> T #no_bounds_check { + when N == 1 { + return matrix1x1_determinant(a) + } else when N == 2 { + return matrix2x2_determinant(a) + } else when N == 3 { + return matrix3x3_determinant(a) + } else when N == 4 { + return matrix4x4_determinant(a) + } else { + a := a + det: T = 1 + + for col in 0.. pivot_val { + pivot_val = val + pivot_row = row + } + } + + if pivot_val == 0 { + return 0 + } + + if pivot_row != col { + for k in 0.. (y: M) #no_bounds_check { @@ -527,12 +633,92 @@ matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bo @(require_results) matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { - for i in 0..<4 { - for j in 0..<4 { - sign: T = 1 if (i + j) % 2 == 0 else -1 - y[i, j] = sign * matrix_minor(x, j, i) + s0 := x[0, 0] * x[1, 1] - x[1, 0] * x[0, 1] + s1 := x[0, 0] * x[1, 2] - x[1, 0] * x[0, 2] + s2 := x[0, 0] * x[1, 3] - x[1, 0] * x[0, 3] + s3 := x[0, 1] * x[1, 2] - x[1, 1] * x[0, 2] + s4 := x[0, 1] * x[1, 3] - x[1, 1] * x[0, 3] + s5 := x[0, 2] * x[1, 3] - x[1, 2] * x[0, 3] + + c5 := x[2, 2] * x[3, 3] - x[3, 2] * x[2, 3] + c4 := x[2, 1] * x[3, 3] - x[3, 1] * x[2, 3] + c3 := x[2, 1] * x[3, 2] - x[3, 1] * x[2, 2] + c2 := x[2, 0] * x[3, 3] - x[3, 0] * x[2, 3] + c1 := x[2, 0] * x[3, 2] - x[3, 0] * x[2, 2] + c0 := x[2, 0] * x[3, 1] - x[3, 0] * x[2, 1] + + y[0, 0] = x[1, 1] * c5 - x[1, 2] * c4 + x[1, 3] * c3 + y[0, 1] = -x[0, 1] * c5 + x[0, 2] * c4 - x[0, 3] * c3 + y[0, 2] = x[3, 1] * s5 - x[3, 2] * s4 + x[3, 3] * s3 + y[0, 3] = -x[2, 1] * s5 + x[2, 2] * s4 - x[2, 3] * s3 + + y[1, 0] = -x[1, 0] * c5 + x[1, 2] * c2 - x[1, 3] * c1 + y[1, 1] = x[0, 0] * c5 - x[0, 2] * c2 + x[0, 3] * c1 + y[1, 2] = -x[3, 0] * s5 + x[3, 2] * s2 - x[3, 3] * s1 + y[1, 3] = x[2, 0] * s5 - x[2, 2] * s2 + x[2, 3] * s1 + + y[2, 0] = x[1, 0] * c4 - x[1, 1] * c2 + x[1, 3] * c0 + y[2, 1] = -x[0, 0] * c4 + x[0, 1] * c2 - x[0, 3] * c0 + y[2, 2] = x[3, 0] * s4 - x[3, 1] * s2 + x[3, 3] * s0 + y[2, 3] = -x[2, 0] * s4 + x[2, 1] * s2 - x[2, 3] * s0 + + y[3, 0] = -x[1, 0] * c3 + x[1, 1] * c1 - x[1, 2] * c0 + y[3, 1] = x[0, 0] * c3 - x[0, 1] * c1 + x[0, 2] * c0 + y[3, 2] = -x[3, 0] * s3 + x[3, 1] * s1 - x[3, 2] * s0 + y[3, 3] = x[2, 0] * s3 - x[2, 1] * s1 + x[2, 2] * s0 + + return +} + +@(require_results) +matrix5x5_adjugate :: proc "contextless" (x: $M/matrix[5, 5]$T) -> (y: M) #no_bounds_check { + return matrix_adjugate_general(x) +} + +@(require_results) +matrix6x6_adjugate :: proc "contextless" (x: $M/matrix[6, 6]$T) -> (y: M) #no_bounds_check { + return matrix_adjugate_general(x) +} + +@(require_results) +matrix7x7_adjugate :: proc "contextless" (x: $M/matrix[7, 7]$T) -> (y: M) #no_bounds_check { + return matrix_adjugate_general(x) +} + +@(require_results) +matrix8x8_adjugate :: proc "contextless" (x: $M/matrix[8, 8]$T) -> (y: M) #no_bounds_check { + return matrix_adjugate_general(x) +} + +@(require_results) +matrix_adjugate_general :: proc "contextless" (x: $M/matrix[$N, N]$T) -> (y: M) where N >= 2 #no_bounds_check { + for row in 0.. (y: M) #no_bo @(require_results) matrix4x4_cofactor :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { - for i in 0..<4 { - for j in 0..<4 { - sign: T = 1 if (i + j) % 2 == 0 else -1 - y[i, j] = sign * matrix_minor(x, i, j) - } - } + s0 := x[0, 0] * x[1, 1] - x[1, 0] * x[0, 1] + s1 := x[0, 0] * x[1, 2] - x[1, 0] * x[0, 2] + s2 := x[0, 0] * x[1, 3] - x[1, 0] * x[0, 3] + s3 := x[0, 1] * x[1, 2] - x[1, 1] * x[0, 2] + s4 := x[0, 1] * x[1, 3] - x[1, 1] * x[0, 3] + s5 := x[0, 2] * x[1, 3] - x[1, 2] * x[0, 3] + + c5 := x[2, 2] * x[3, 3] - x[3, 2] * x[2, 3] + c4 := x[2, 1] * x[3, 3] - x[3, 1] * x[2, 3] + c3 := x[2, 1] * x[3, 2] - x[3, 1] * x[2, 2] + c2 := x[2, 0] * x[3, 3] - x[3, 0] * x[2, 3] + c1 := x[2, 0] * x[3, 2] - x[3, 0] * x[2, 2] + c0 := x[2, 0] * x[3, 1] - x[3, 0] * x[2, 1] + + // Cofactor = transpose of adjugate + y[0, 0] = x[1, 1] * c5 - x[1, 2] * c4 + x[1, 3] * c3 + y[1, 0] = -x[0, 1] * c5 + x[0, 2] * c4 - x[0, 3] * c3 + y[2, 0] = x[3, 1] * s5 - x[3, 2] * s4 + x[3, 3] * s3 + y[3, 0] = -x[2, 1] * s5 + x[2, 2] * s4 - x[2, 3] * s3 + + y[0, 1] = -x[1, 0] * c5 + x[1, 2] * c2 - x[1, 3] * c1 + y[1, 1] = x[0, 0] * c5 - x[0, 2] * c2 + x[0, 3] * c1 + y[2, 1] = -x[3, 0] * s5 + x[3, 2] * s2 - x[3, 3] * s1 + y[3, 1] = x[2, 0] * s5 - x[2, 2] * s2 + x[2, 3] * s1 + + y[0, 2] = x[1, 0] * c4 - x[1, 1] * c2 + x[1, 3] * c0 + y[1, 2] = -x[0, 0] * c4 + x[0, 1] * c2 - x[0, 3] * c0 + y[2, 2] = x[3, 0] * s4 - x[3, 1] * s2 + x[3, 3] * s0 + y[3, 2] = -x[2, 0] * s4 + x[2, 1] * s2 - x[2, 3] * s0 + + y[0, 3] = -x[1, 0] * c3 + x[1, 1] * c1 - x[1, 2] * c0 + y[1, 3] = x[0, 0] * c3 - x[0, 1] * c1 + x[0, 2] * c0 + y[2, 3] = -x[3, 0] * s3 + x[3, 1] * s1 - x[3, 2] * s0 + y[3, 3] = x[2, 0] * s3 - x[2, 1] * s1 + x[2, 2] * s0 + return } +@(require_results) +matrix5x5_cofactor :: proc "contextless" (x: $M/matrix[5, 5]$T) -> (y: M) #no_bounds_check { + return matrix_cofactor_general(x) +} + +@(require_results) +matrix6x6_cofactor :: proc "contextless" (x: $M/matrix[6, 6]$T) -> (y: M) #no_bounds_check { + return matrix_cofactor_general(x) +} + +@(require_results) +matrix7x7_cofactor :: proc "contextless" (x: $M/matrix[7, 7]$T) -> (y: M) #no_bounds_check { + return matrix_cofactor_general(x) +} + +@(require_results) +matrix8x8_cofactor :: proc "contextless" (x: $M/matrix[8, 8]$T) -> (y: M) #no_bounds_check { + return matrix_cofactor_general(x) +} + +@(require_results) +matrix_cofactor_general :: proc "contextless" (x: $M/matrix[$N, N]$T) -> (y: M) where N >= 2 #no_bounds_check { + for row in 0.. (y: M) #no_bounds_check { y[0, 0] = 1/x[0, 0] @@ -647,10 +914,34 @@ matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: return } +@(require_results) +matrix5x5_inverse_transpose :: proc "contextless" (x: $M/matrix[5, 5]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return transpose(y) +} + +@(require_results) +matrix6x6_inverse_transpose :: proc "contextless" (x: $M/matrix[6, 6]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return transpose(y) +} + +@(require_results) +matrix7x7_inverse_transpose :: proc "contextless" (x: $M/matrix[7, 7]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return transpose(y) +} + +@(require_results) +matrix8x8_inverse_transpose :: proc "contextless" (x: $M/matrix[8, 8]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return transpose(y) +} + @(require_results) matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) #no_bounds_check { y[0, 0] = 1/x[0, 0] - return + return transpose(y) } @(require_results) @@ -715,3 +1006,210 @@ matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bou } return } + +@(require_results) +matrix5x5_inverse :: proc "contextless" (x: $M/matrix[5, 5]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return +} + +@(require_results) +matrix6x6_inverse :: proc "contextless" (x: $M/matrix[6, 6]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return +} + +@(require_results) +matrix7x7_inverse :: proc "contextless" (x: $M/matrix[7, 7]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return +} + +@(require_results) +matrix8x8_inverse :: proc "contextless" (x: $M/matrix[8, 8]$T) -> (y: M) #no_bounds_check { + y, _ = matrix_inverse_lu_decomposition(x) + return +} + +@(private="file") +swap :: #force_inline proc "contextless" (a, b: ^$T) { + t := a^ + a^ = b^ + b^ = t +} + +@(require_results) +matrix_inverse_gauss_jordan :: proc "contextless" (A: $M/matrix[$N, N]$T) -> (b: M, non_singular: bool) #no_bounds_check { + a := A + b = 1 + + for col in 0.. pivot_val { + pivot_val = val + pivot_row = row + } + } + + if pivot_val == 0 { + return + } + + if pivot_row != col { + for k in 0.. (b: M, non_singular: bool) #no_bounds_check { + // LU decomposition with partial pivoting + a := A + pivot: [N]int = --- + for i in 0.. pivot_val { + pivot_val = val + pivot_row = row + } + } + + if pivot_val == 0 { + return + } + + // Swap pivot indices + if pivot_row != col { + t := pivot[col] + pivot[col] = pivot[pivot_row] + pivot[pivot_row] = t + + for k in 0.. (B: matrix[C, R]T, not_singular: bool) #no_bounds_check { + At := transpose(A) + + when R >= C { + // Overdetermined (tall): + // pseudo_inverse(A) = inverse(transpose(A)*A)*transpose(A) + AtA := At * A // [C, C] + AtA_inv := matrix_inverse_generic(AtA) or_return + B = AtA_inv * At + not_singular = true + } else { + // Underdetermined (wide): + // pseudo_inverse(A) = transpose(A)*inverse(A*transpose(A)) + AAt := A * At // [R, R] + AAt_inv := matrix_inverse_generic(AAt) or_return + B = At * AAt_inv + not_singular = true + } + + return +} \ No newline at end of file diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index bd2cf416a..46ee7a6f7 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -1,4 +1,4 @@ -// core:math/linalg/glsl implements a GLSL-like mathematics library plus numerous other utility procedures +// `GLSL`-like mathematics library plus numerous other utility procedures. package math_linalg_glsl import "base:builtin" diff --git a/core/math/linalg/hlsl/linalg_hlsl.odin b/core/math/linalg/hlsl/linalg_hlsl.odin index cca70f9c8..8666f6f60 100644 --- a/core/math/linalg/hlsl/linalg_hlsl.odin +++ b/core/math/linalg/hlsl/linalg_hlsl.odin @@ -1,4 +1,4 @@ -// core:math/linalg/hlsl implements a HLSL-like mathematics library plus numerous other utility procedures +// `HLSL`-like mathematics library plus numerous other utility procedures. package math_linalg_hlsl import "base:builtin" @@ -22,6 +22,7 @@ FLOAT_EPSILON :: 1e-7 DOUBLE_EPSILON :: 1e-15 // Aliases (not distict) of types +half :: f16 float :: f32 double :: f64 int :: builtin.i32 @@ -46,6 +47,30 @@ float4x1 :: matrix[4, 1]float float4x2 :: matrix[4, 2]float float4x3 :: matrix[4, 3]float +// Half Precision (half) Floating Point Types + +half2 :: [2]half +half3 :: [3]half +half4 :: [4]half + +half1x1 :: matrix[1, 1]half +half2x2 :: matrix[2, 2]half +half3x3 :: matrix[3, 3]half +half4x4 :: matrix[4, 4]half + +half1x2 :: matrix[1, 2]half +half1x3 :: matrix[1, 3]half +half1x4 :: matrix[1, 4]half +half2x1 :: matrix[2, 1]half +half2x3 :: matrix[2, 3]half +half2x4 :: matrix[2, 4]half +half3x1 :: matrix[3, 1]half +half3x2 :: matrix[3, 2]half +half3x4 :: matrix[3, 4]half +half4x1 :: matrix[4, 1]half +half4x2 :: matrix[4, 2]half +half4x3 :: matrix[4, 3]half + float2 :: [2]float float3 :: [3]float float4 :: [4]float @@ -106,8 +131,12 @@ int4x2 :: matrix[4, 2]int int4x3 :: matrix[4, 3]int cos :: proc{ + cos_half, cos_float, cos_double, + cos_half2, + cos_half3, + cos_half4, cos_float2, cos_float3, cos_float4, @@ -115,6 +144,9 @@ cos :: proc{ cos_double3, cos_double4, } +@(require_results) cos_half2 :: proc "c" (x: half2) -> half2 { return {cos(x.x), cos(x.y)} } +@(require_results) cos_half3 :: proc "c" (x: half3) -> half3 { return {cos(x.x), cos(x.y), cos(x.z)} } +@(require_results) cos_half4 :: proc "c" (x: half4) -> half4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } @(require_results) cos_float2 :: proc "c" (x: float2) -> float2 { return {cos(x.x), cos(x.y)} } @(require_results) cos_float3 :: proc "c" (x: float3) -> float3 { return {cos(x.x), cos(x.y), cos(x.z)} } @(require_results) cos_float4 :: proc "c" (x: float4) -> float4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } @@ -123,8 +155,12 @@ cos :: proc{ @(require_results) cos_double4 :: proc "c" (x: double4) -> double4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } sin :: proc{ + sin_half, sin_float, sin_double, + sin_half2, + sin_half3, + sin_half4, sin_float2, sin_float3, sin_float4, @@ -132,6 +168,9 @@ sin :: proc{ sin_double3, sin_double4, } +@(require_results) sin_half2 :: proc "c" (x: half2) -> half2 { return {sin(x.x), sin(x.y)} } +@(require_results) sin_half3 :: proc "c" (x: half3) -> half3 { return {sin(x.x), sin(x.y), sin(x.z)} } +@(require_results) sin_half4 :: proc "c" (x: half4) -> half4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } @(require_results) sin_float2 :: proc "c" (x: float2) -> float2 { return {sin(x.x), sin(x.y)} } @(require_results) sin_float3 :: proc "c" (x: float3) -> float3 { return {sin(x.x), sin(x.y), sin(x.z)} } @(require_results) sin_float4 :: proc "c" (x: float4) -> float4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } @@ -140,8 +179,12 @@ sin :: proc{ @(require_results) sin_double4 :: proc "c" (x: double4) -> double4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } tan :: proc{ + tan_half, tan_float, tan_double, + tan_half2, + tan_half3, + tan_half4, tan_float2, tan_float3, tan_float4, @@ -149,6 +192,9 @@ tan :: proc{ tan_double3, tan_double4, } +@(require_results) tan_half2 :: proc "c" (x: half2) -> half2 { return {tan(x.x), tan(x.y)} } +@(require_results) tan_half3 :: proc "c" (x: half3) -> half3 { return {tan(x.x), tan(x.y), tan(x.z)} } +@(require_results) tan_half4 :: proc "c" (x: half4) -> half4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } @(require_results) tan_float2 :: proc "c" (x: float2) -> float2 { return {tan(x.x), tan(x.y)} } @(require_results) tan_float3 :: proc "c" (x: float3) -> float3 { return {tan(x.x), tan(x.y), tan(x.z)} } @(require_results) tan_float4 :: proc "c" (x: float4) -> float4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } @@ -157,8 +203,12 @@ tan :: proc{ @(require_results) tan_double4 :: proc "c" (x: double4) -> double4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } acos :: proc{ + acos_half, acos_float, acos_double, + acos_half2, + acos_half3, + acos_half4, acos_float2, acos_float3, acos_float4, @@ -166,6 +216,9 @@ acos :: proc{ acos_double3, acos_double4, } +@(require_results) acos_half2 :: proc "c" (x: half2) -> half2 { return {acos(x.x), acos(x.y)} } +@(require_results) acos_half3 :: proc "c" (x: half3) -> half3 { return {acos(x.x), acos(x.y), acos(x.z)} } +@(require_results) acos_half4 :: proc "c" (x: half4) -> half4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } @(require_results) acos_float2 :: proc "c" (x: float2) -> float2 { return {acos(x.x), acos(x.y)} } @(require_results) acos_float3 :: proc "c" (x: float3) -> float3 { return {acos(x.x), acos(x.y), acos(x.z)} } @(require_results) acos_float4 :: proc "c" (x: float4) -> float4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } @@ -174,8 +227,12 @@ acos :: proc{ @(require_results) acos_double4 :: proc "c" (x: double4) -> double4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } asin :: proc{ + asin_half, asin_float, asin_double, + asin_half2, + asin_half3, + asin_half4, asin_float2, asin_float3, asin_float4, @@ -183,6 +240,9 @@ asin :: proc{ asin_double3, asin_double4, } +@(require_results) asin_half2 :: proc "c" (x: half2) -> half2 { return {asin(x.x), asin(x.y)} } +@(require_results) asin_half3 :: proc "c" (x: half3) -> half3 { return {asin(x.x), asin(x.y), asin(x.z)} } +@(require_results) asin_half4 :: proc "c" (x: half4) -> half4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } @(require_results) asin_float2 :: proc "c" (x: float2) -> float2 { return {asin(x.x), asin(x.y)} } @(require_results) asin_float3 :: proc "c" (x: float3) -> float3 { return {asin(x.x), asin(x.y), asin(x.z)} } @(require_results) asin_float4 :: proc "c" (x: float4) -> float4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } @@ -191,8 +251,12 @@ asin :: proc{ @(require_results) asin_double4 :: proc "c" (x: double4) -> double4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } atan :: proc{ + atan_half, atan_float, atan_double, + atan_half2, + atan_half3, + atan_half4, atan_float2, atan_float3, atan_float4, @@ -208,6 +272,9 @@ atan :: proc{ atan2_double3, atan2_double4, } +@(require_results) atan_half2 :: proc "c" (x: half2) -> half2 { return {atan(x.x), atan(x.y)} } +@(require_results) atan_half3 :: proc "c" (x: half3) -> half3 { return {atan(x.x), atan(x.y), atan(x.z)} } +@(require_results) atan_half4 :: proc "c" (x: half4) -> half4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } @(require_results) atan_float2 :: proc "c" (x: float2) -> float2 { return {atan(x.x), atan(x.y)} } @(require_results) atan_float3 :: proc "c" (x: float3) -> float3 { return {atan(x.x), atan(x.y), atan(x.z)} } @(require_results) atan_float4 :: proc "c" (x: float4) -> float4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } @@ -216,8 +283,12 @@ atan :: proc{ @(require_results) atan_double4 :: proc "c" (x: double4) -> double4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } atan2 :: proc{ + atan2_half, atan2_float, atan2_double, + atan2_half2, + atan2_half3, + atan2_half4, atan2_float2, atan2_float3, atan2_float4, @@ -225,6 +296,9 @@ atan2 :: proc{ atan2_double3, atan2_double4, } +@(require_results) atan2_half2 :: proc "c" (y, x: half2) -> half2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } +@(require_results) atan2_half3 :: proc "c" (y, x: half3) -> half3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } +@(require_results) atan2_half4 :: proc "c" (y, x: half4) -> half4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } @(require_results) atan2_float2 :: proc "c" (y, x: float2) -> float2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } @(require_results) atan2_float3 :: proc "c" (y, x: float3) -> float3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } @(require_results) atan2_float4 :: proc "c" (y, x: float4) -> float4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } @@ -235,8 +309,12 @@ atan2 :: proc{ cosh :: proc{ + cosh_half, cosh_float, cosh_double, + cosh_half2, + cosh_half3, + cosh_half4, cosh_float2, cosh_float3, cosh_float4, @@ -244,6 +322,9 @@ cosh :: proc{ cosh_double3, cosh_double4, } +@(require_results) cosh_half2 :: proc "c" (x: half2) -> half2 { return {cosh(x.x), cosh(x.y)} } +@(require_results) cosh_half3 :: proc "c" (x: half3) -> half3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } +@(require_results) cosh_half4 :: proc "c" (x: half4) -> half4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } @(require_results) cosh_float2 :: proc "c" (x: float2) -> float2 { return {cosh(x.x), cosh(x.y)} } @(require_results) cosh_float3 :: proc "c" (x: float3) -> float3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } @(require_results) cosh_float4 :: proc "c" (x: float4) -> float4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } @@ -253,8 +334,12 @@ cosh :: proc{ sinh :: proc{ + sinh_half, sinh_float, sinh_double, + sinh_half2, + sinh_half3, + sinh_half4, sinh_float2, sinh_float3, sinh_float4, @@ -262,6 +347,9 @@ sinh :: proc{ sinh_double3, sinh_double4, } +@(require_results) sinh_half2 :: proc "c" (x: half2) -> half2 { return {sinh(x.x), sinh(x.y)} } +@(require_results) sinh_half3 :: proc "c" (x: half3) -> half3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } +@(require_results) sinh_half4 :: proc "c" (x: half4) -> half4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } @(require_results) sinh_float2 :: proc "c" (x: float2) -> float2 { return {sinh(x.x), sinh(x.y)} } @(require_results) sinh_float3 :: proc "c" (x: float3) -> float3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } @(require_results) sinh_float4 :: proc "c" (x: float4) -> float4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } @@ -270,8 +358,12 @@ sinh :: proc{ @(require_results) sinh_double4 :: proc "c" (x: double4) -> double4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } tanh :: proc{ + tanh_half, tanh_float, tanh_double, + tanh_half2, + tanh_half3, + tanh_half4, tanh_float2, tanh_float3, tanh_float4, @@ -279,6 +371,9 @@ tanh :: proc{ tanh_double3, tanh_double4, } +@(require_results) tanh_half2 :: proc "c" (x: half2) -> half2 { return {tanh(x.x), tanh(x.y)} } +@(require_results) tanh_half3 :: proc "c" (x: half3) -> half3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } +@(require_results) tanh_half4 :: proc "c" (x: half4) -> half4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } @(require_results) tanh_float2 :: proc "c" (x: float2) -> float2 { return {tanh(x.x), tanh(x.y)} } @(require_results) tanh_float3 :: proc "c" (x: float3) -> float3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } @(require_results) tanh_float4 :: proc "c" (x: float4) -> float4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } @@ -287,8 +382,12 @@ tanh :: proc{ @(require_results) tanh_double4 :: proc "c" (x: double4) -> double4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } acosh :: proc{ + acosh_half, acosh_float, acosh_double, + acosh_half2, + acosh_half3, + acosh_half4, acosh_float2, acosh_float3, acosh_float4, @@ -296,6 +395,9 @@ acosh :: proc{ acosh_double3, acosh_double4, } +@(require_results) acosh_half2 :: proc "c" (x: half2) -> half2 { return {acosh(x.x), acosh(x.y)} } +@(require_results) acosh_half3 :: proc "c" (x: half3) -> half3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } +@(require_results) acosh_half4 :: proc "c" (x: half4) -> half4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } @(require_results) acosh_float2 :: proc "c" (x: float2) -> float2 { return {acosh(x.x), acosh(x.y)} } @(require_results) acosh_float3 :: proc "c" (x: float3) -> float3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } @(require_results) acosh_float4 :: proc "c" (x: float4) -> float4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } @@ -304,8 +406,12 @@ acosh :: proc{ @(require_results) acosh_double4 :: proc "c" (x: double4) -> double4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } asinh :: proc{ + asinh_half, asinh_float, asinh_double, + asinh_half2, + asinh_half3, + asinh_half4, asinh_float2, asinh_float3, asinh_float4, @@ -313,6 +419,9 @@ asinh :: proc{ asinh_double3, asinh_double4, } +@(require_results) asinh_half2 :: proc "c" (x: half2) -> half2 { return {asinh(x.x), asinh(x.y)} } +@(require_results) asinh_half3 :: proc "c" (x: half3) -> half3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } +@(require_results) asinh_half4 :: proc "c" (x: half4) -> half4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } @(require_results) asinh_float2 :: proc "c" (x: float2) -> float2 { return {asinh(x.x), asinh(x.y)} } @(require_results) asinh_float3 :: proc "c" (x: float3) -> float3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } @(require_results) asinh_float4 :: proc "c" (x: float4) -> float4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } @@ -321,8 +430,12 @@ asinh :: proc{ @(require_results) asinh_double4 :: proc "c" (x: double4) -> double4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } atanh :: proc{ + atanh_half, atanh_float, atanh_double, + atanh_half2, + atanh_half3, + atanh_half4, atanh_float2, atanh_float3, atanh_float4, @@ -330,6 +443,9 @@ atanh :: proc{ atanh_double3, atanh_double4, } +@(require_results) atanh_half2 :: proc "c" (x: half2) -> half2 { return {atanh(x.x), atanh(x.y)} } +@(require_results) atanh_half3 :: proc "c" (x: half3) -> half3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } +@(require_results) atanh_half4 :: proc "c" (x: half4) -> half4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } @(require_results) atanh_float2 :: proc "c" (x: float2) -> float2 { return {atanh(x.x), atanh(x.y)} } @(require_results) atanh_float3 :: proc "c" (x: float3) -> float3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } @(require_results) atanh_float4 :: proc "c" (x: float4) -> float4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } @@ -338,8 +454,12 @@ atanh :: proc{ @(require_results) atanh_double4 :: proc "c" (x: double4) -> double4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } sqrt :: proc{ + sqrt_half, sqrt_float, sqrt_double, + sqrt_half2, + sqrt_half3, + sqrt_half4, sqrt_float2, sqrt_float3, sqrt_float4, @@ -347,6 +467,9 @@ sqrt :: proc{ sqrt_double3, sqrt_double4, } +@(require_results) sqrt_half2 :: proc "c" (x: half2) -> half2 { return {sqrt(x.x), sqrt(x.y)} } +@(require_results) sqrt_half3 :: proc "c" (x: half3) -> half3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } +@(require_results) sqrt_half4 :: proc "c" (x: half4) -> half4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } @(require_results) sqrt_float2 :: proc "c" (x: float2) -> float2 { return {sqrt(x.x), sqrt(x.y)} } @(require_results) sqrt_float3 :: proc "c" (x: float3) -> float3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } @(require_results) sqrt_float4 :: proc "c" (x: float4) -> float4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } @@ -355,8 +478,12 @@ sqrt :: proc{ @(require_results) sqrt_double4 :: proc "c" (x: double4) -> double4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } rsqrt :: proc{ + rsqrt_half, rsqrt_float, rsqrt_double, + rsqrt_half2, + rsqrt_half3, + rsqrt_half4, rsqrt_float2, rsqrt_float3, rsqrt_float4, @@ -364,6 +491,9 @@ rsqrt :: proc{ rsqrt_double3, rsqrt_double4, } +@(require_results) rsqrt_half2 :: proc "c" (x: half2) -> half2 { return {rsqrt(x.x), rsqrt(x.y)} } +@(require_results) rsqrt_half3 :: proc "c" (x: half3) -> half3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} } +@(require_results) rsqrt_half4 :: proc "c" (x: half4) -> half4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} } @(require_results) rsqrt_float2 :: proc "c" (x: float2) -> float2 { return {rsqrt(x.x), rsqrt(x.y)} } @(require_results) rsqrt_float3 :: proc "c" (x: float3) -> float3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} } @(require_results) rsqrt_float4 :: proc "c" (x: float4) -> float4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} } @@ -372,8 +502,12 @@ rsqrt :: proc{ @(require_results) rsqrt_double4 :: proc "c" (x: double4) -> double4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} } rcp :: proc{ + rcp_half, rcp_float, rcp_double, + rcp_half2, + rcp_half3, + rcp_half4, rcp_float2, rcp_float3, rcp_float4, @@ -381,6 +515,9 @@ rcp :: proc{ rcp_double3, rcp_double4, } +@(require_results) rcp_half2 :: proc "c" (x: half2) -> half2 { return {rcp(x.x), rcp(x.y)} } +@(require_results) rcp_half3 :: proc "c" (x: half3) -> half3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} } +@(require_results) rcp_half4 :: proc "c" (x: half4) -> half4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} } @(require_results) rcp_float2 :: proc "c" (x: float2) -> float2 { return {rcp(x.x), rcp(x.y)} } @(require_results) rcp_float3 :: proc "c" (x: float3) -> float3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} } @(require_results) rcp_float4 :: proc "c" (x: float4) -> float4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} } @@ -390,8 +527,12 @@ rcp :: proc{ pow :: proc{ + pow_half, pow_float, pow_double, + pow_half2, + pow_half3, + pow_half4, pow_float2, pow_float3, pow_float4, @@ -399,6 +540,9 @@ pow :: proc{ pow_double3, pow_double4, } +@(require_results) pow_half2 :: proc "c" (x, y: half2) -> half2 { return {pow(x.x, y.x), pow(x.y, y.y)} } +@(require_results) pow_half3 :: proc "c" (x, y: half3) -> half3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } +@(require_results) pow_half4 :: proc "c" (x, y: half4) -> half4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } @(require_results) pow_float2 :: proc "c" (x, y: float2) -> float2 { return {pow(x.x, y.x), pow(x.y, y.y)} } @(require_results) pow_float3 :: proc "c" (x, y: float3) -> float3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } @(require_results) pow_float4 :: proc "c" (x, y: float4) -> float4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } @@ -409,8 +553,12 @@ pow :: proc{ exp :: proc{ + exp_half, exp_float, exp_double, + exp_half2, + exp_half3, + exp_half4, exp_float2, exp_float3, exp_float4, @@ -418,6 +566,9 @@ exp :: proc{ exp_double3, exp_double4, } +@(require_results) exp_half2 :: proc "c" (x: half2) -> half2 { return {exp(x.x), exp(x.y)} } +@(require_results) exp_half3 :: proc "c" (x: half3) -> half3 { return {exp(x.x), exp(x.y), exp(x.z)} } +@(require_results) exp_half4 :: proc "c" (x: half4) -> half4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } @(require_results) exp_float2 :: proc "c" (x: float2) -> float2 { return {exp(x.x), exp(x.y)} } @(require_results) exp_float3 :: proc "c" (x: float3) -> float3 { return {exp(x.x), exp(x.y), exp(x.z)} } @(require_results) exp_float4 :: proc "c" (x: float4) -> float4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } @@ -428,8 +579,12 @@ exp :: proc{ log :: proc{ + log_half, log_float, log_double, + log_half2, + log_half3, + log_half4, log_float2, log_float3, log_float4, @@ -437,6 +592,9 @@ log :: proc{ log_double3, log_double4, } +@(require_results) log_half2 :: proc "c" (x: half2) -> half2 { return {log(x.x), log(x.y)} } +@(require_results) log_half3 :: proc "c" (x: half3) -> half3 { return {log(x.x), log(x.y), log(x.z)} } +@(require_results) log_half4 :: proc "c" (x: half4) -> half4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } @(require_results) log_float2 :: proc "c" (x: float2) -> float2 { return {log(x.x), log(x.y)} } @(require_results) log_float3 :: proc "c" (x: float3) -> float3 { return {log(x.x), log(x.y), log(x.z)} } @(require_results) log_float4 :: proc "c" (x: float4) -> float4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } @@ -446,8 +604,12 @@ log :: proc{ log2 :: proc{ + log2_half, log2_float, log2_double, + log2_half2, + log2_half3, + log2_half4, log2_float2, log2_float3, log2_float4, @@ -455,6 +617,9 @@ log2 :: proc{ log2_double3, log2_double4, } +@(require_results) log2_half2 :: proc "c" (x: half2) -> half2 { return {log2(x.x), log2(x.y)} } +@(require_results) log2_half3 :: proc "c" (x: half3) -> half3 { return {log2(x.x), log2(x.y), log2(x.z)} } +@(require_results) log2_half4 :: proc "c" (x: half4) -> half4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} } @(require_results) log2_float2 :: proc "c" (x: float2) -> float2 { return {log2(x.x), log2(x.y)} } @(require_results) log2_float3 :: proc "c" (x: float3) -> float3 { return {log2(x.x), log2(x.y), log2(x.z)} } @(require_results) log2_float4 :: proc "c" (x: float4) -> float4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} } @@ -465,8 +630,12 @@ log2 :: proc{ log10 :: proc{ + log10_half, log10_float, log10_double, + log10_half2, + log10_half3, + log10_half4, log10_float2, log10_float3, log10_float4, @@ -474,6 +643,9 @@ log10 :: proc{ log10_double3, log10_double4, } +@(require_results) log10_half2 :: proc "c" (x: half2) -> half2 { return {log10(x.x), log10(x.y)} } +@(require_results) log10_half3 :: proc "c" (x: half3) -> half3 { return {log10(x.x), log10(x.y), log10(x.z)} } +@(require_results) log10_half4 :: proc "c" (x: half4) -> half4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} } @(require_results) log10_float2 :: proc "c" (x: float2) -> float2 { return {log10(x.x), log10(x.y)} } @(require_results) log10_float3 :: proc "c" (x: float3) -> float3 { return {log10(x.x), log10(x.y), log10(x.z)} } @(require_results) log10_float4 :: proc "c" (x: float4) -> float4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} } @@ -485,8 +657,12 @@ log10 :: proc{ exp2 :: proc{ + exp2_half, exp2_float, exp2_double, + exp2_half2, + exp2_half3, + exp2_half4, exp2_float2, exp2_float3, exp2_float4, @@ -494,6 +670,9 @@ exp2 :: proc{ exp2_double3, exp2_double4, } +@(require_results) exp2_half2 :: proc "c" (x: half2) -> half2 { return {exp2(x.x), exp2(x.y)} } +@(require_results) exp2_half3 :: proc "c" (x: half3) -> half3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } +@(require_results) exp2_half4 :: proc "c" (x: half4) -> half4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } @(require_results) exp2_float2 :: proc "c" (x: float2) -> float2 { return {exp2(x.x), exp2(x.y)} } @(require_results) exp2_float3 :: proc "c" (x: float3) -> float3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } @(require_results) exp2_float4 :: proc "c" (x: float4) -> float4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } @@ -503,10 +682,14 @@ exp2 :: proc{ sign :: proc{ + sign_half, sign_int, sign_uint, sign_float, sign_double, + sign_half2, + sign_half3, + sign_half4, sign_float2, sign_float3, sign_float4, @@ -522,6 +705,9 @@ sign :: proc{ } @(require_results) sign_int :: proc "c" (x: int) -> int { return -1 if x < 0 else +1 if x > 0 else 0 } @(require_results) sign_uint :: proc "c" (x: uint) -> uint { return +1 if x > 0 else 0 } +@(require_results) sign_half2 :: proc "c" (x: half2) -> half2 { return {sign(x.x), sign(x.y)} } +@(require_results) sign_half3 :: proc "c" (x: half3) -> half3 { return {sign(x.x), sign(x.y), sign(x.z)} } +@(require_results) sign_half4 :: proc "c" (x: half4) -> half4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } @(require_results) sign_float2 :: proc "c" (x: float2) -> float2 { return {sign(x.x), sign(x.y)} } @(require_results) sign_float3 :: proc "c" (x: float3) -> float3 { return {sign(x.x), sign(x.y), sign(x.z)} } @(require_results) sign_float4 :: proc "c" (x: float4) -> float4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } @@ -536,8 +722,12 @@ sign :: proc{ @(require_results) sign_uint4 :: proc "c" (x: uint4) -> uint4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } floor :: proc{ + floor_half, floor_float, floor_double, + floor_half2, + floor_half3, + floor_half4, floor_float2, floor_float3, floor_float4, @@ -545,6 +735,9 @@ floor :: proc{ floor_double3, floor_double4, } +@(require_results) floor_half2 :: proc "c" (x: half2) -> half2 { return {floor(x.x), floor(x.y)} } +@(require_results) floor_half3 :: proc "c" (x: half3) -> half3 { return {floor(x.x), floor(x.y), floor(x.z)} } +@(require_results) floor_half4 :: proc "c" (x: half4) -> half4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } @(require_results) floor_float2 :: proc "c" (x: float2) -> float2 { return {floor(x.x), floor(x.y)} } @(require_results) floor_float3 :: proc "c" (x: float3) -> float3 { return {floor(x.x), floor(x.y), floor(x.z)} } @(require_results) floor_float4 :: proc "c" (x: float4) -> float4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } @@ -553,8 +746,12 @@ floor :: proc{ @(require_results) floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } round :: proc{ + round_half, round_float, round_double, + round_half2, + round_half3, + round_half4, round_float2, round_float3, round_float4, @@ -562,6 +759,9 @@ round :: proc{ round_double3, round_double4, } +@(require_results) round_half2 :: proc "c" (x: half2) -> half2 { return {round(x.x), round(x.y)} } +@(require_results) round_half3 :: proc "c" (x: half3) -> half3 { return {round(x.x), round(x.y), round(x.z)} } +@(require_results) round_half4 :: proc "c" (x: half4) -> half4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} } @(require_results) round_float2 :: proc "c" (x: float2) -> float2 { return {round(x.x), round(x.y)} } @(require_results) round_float3 :: proc "c" (x: float3) -> float3 { return {round(x.x), round(x.y), round(x.z)} } @(require_results) round_float4 :: proc "c" (x: float4) -> float4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} } @@ -571,8 +771,12 @@ round :: proc{ ceil :: proc{ + ceil_half, ceil_float, ceil_double, + ceil_half2, + ceil_half3, + ceil_half4, ceil_float2, ceil_float3, ceil_float4, @@ -580,6 +784,9 @@ ceil :: proc{ ceil_double3, ceil_double4, } +@(require_results) ceil_half2 :: proc "c" (x: half2) -> half2 { return {ceil(x.x), ceil(x.y)} } +@(require_results) ceil_half3 :: proc "c" (x: half3) -> half3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } +@(require_results) ceil_half4 :: proc "c" (x: half4) -> half4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } @(require_results) ceil_float2 :: proc "c" (x: float2) -> float2 { return {ceil(x.x), ceil(x.y)} } @(require_results) ceil_float3 :: proc "c" (x: float3) -> float3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } @(require_results) ceil_float4 :: proc "c" (x: float4) -> float4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } @@ -588,6 +795,10 @@ ceil :: proc{ @(require_results) ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } +@(require_results) isfinite_half :: proc "c" (x: half) -> bool { return !isinf_half(x) } +@(require_results) isfinite_half2 :: proc "c" (x: half2) -> bool2 { return {isfinite_half(x.x), isfinite_half(x.y)} } +@(require_results) isfinite_half3 :: proc "c" (x: half3) -> bool3 { return {isfinite_half(x.x), isfinite_half(x.y), isfinite_half(x.z)} } +@(require_results) isfinite_half4 :: proc "c" (x: half4) -> bool4 { return {isfinite_half(x.x), isfinite_half(x.y), isfinite_half(x.z), isfinite_half(x.w)} } @(require_results) isfinite_float :: proc "c" (x: float) -> bool { return !isinf_float(x) } @(require_results) isfinite_float2 :: proc "c" (x: float2) -> bool2 { return {isfinite_float(x.x), isfinite_float(x.y)} } @(require_results) isfinite_float3 :: proc "c" (x: float3) -> bool3 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z)} } @@ -599,6 +810,10 @@ ceil :: proc{ // isfinite is the opposite of isinf and returns true if the number is neither positive-infinite or negative-infinite isfinite :: proc{ + isfinite_half, + isfinite_half2, + isfinite_half3, + isfinite_half4, isfinite_float, isfinite_float2, isfinite_float3, @@ -610,6 +825,10 @@ isfinite :: proc{ } +@(require_results) isinf_half :: proc "c" (x: half) -> bool { return x * 0.5 == x } +@(require_results) isinf_half2 :: proc "c" (x: half2) -> bool2 { return {isinf_half(x.x), isinf_half(x.y)} } +@(require_results) isinf_half3 :: proc "c" (x: half3) -> bool3 { return {isinf_half(x.x), isinf_half(x.y), isinf_half(x.z)} } +@(require_results) isinf_half4 :: proc "c" (x: half4) -> bool4 { return {isinf_half(x.x), isinf_half(x.y), isinf_half(x.z), isinf_half(x.w)} } @(require_results) isinf_float :: proc "c" (x: float) -> bool { return x * 0.5 == x } @(require_results) isinf_float2 :: proc "c" (x: float2) -> bool2 { return {isinf_float(x.x), isinf_float(x.y)} } @(require_results) isinf_float3 :: proc "c" (x: float3) -> bool3 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z)} } @@ -621,6 +840,10 @@ isfinite :: proc{ // isinf is the opposite of isfinite and returns true if the number is either positive-infinite or negative-infinite isinf :: proc{ + isinf_half, + isinf_half2, + isinf_half3, + isinf_half4, isinf_float, isinf_float2, isinf_float3, @@ -632,6 +855,9 @@ isinf :: proc{ } +@(require_results) isnan_half2 :: proc "c" (x: half2) -> bool2 { return {isnan_half(x.x), isnan_half(x.y)} } +@(require_results) isnan_half3 :: proc "c" (x: half3) -> bool3 { return {isnan_half(x.x), isnan_half(x.y), isnan_half(x.z)} } +@(require_results) isnan_half4 :: proc "c" (x: half4) -> bool4 { return {isnan_half(x.x), isnan_half(x.y), isnan_half(x.z), isnan_half(x.w)} } @(require_results) isnan_float2 :: proc "c" (x: float2) -> bool2 { return {isnan_float(x.x), isnan_float(x.y)} } @(require_results) isnan_float3 :: proc "c" (x: float3) -> bool3 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z)} } @(require_results) isnan_float4 :: proc "c" (x: float4) -> bool4 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z), isnan_float(x.w)} } @@ -641,6 +867,10 @@ isinf :: proc{ // isnan returns true if the input value is the special case of Not-A-Number isnan :: proc{ + isnan_half, + isnan_half2, + isnan_half3, + isnan_half4, isnan_float, isnan_float2, isnan_float3, @@ -652,8 +882,12 @@ isnan :: proc{ } fmod :: proc{ + fmod_half, fmod_float, fmod_double, + fmod_half2, + fmod_half3, + fmod_half4, fmod_float2, fmod_float3, fmod_float4, @@ -661,6 +895,9 @@ fmod :: proc{ fmod_double3, fmod_double4, } +@(require_results) fmod_half2 :: proc "c" (x, y: half2) -> half2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} } +@(require_results) fmod_half3 :: proc "c" (x, y: half3) -> half3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} } +@(require_results) fmod_half4 :: proc "c" (x, y: half4) -> half4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} } @(require_results) fmod_float2 :: proc "c" (x, y: float2) -> float2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} } @(require_results) fmod_float3 :: proc "c" (x, y: float3) -> float3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} } @(require_results) fmod_float4 :: proc "c" (x, y: float4) -> float4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} } @@ -670,8 +907,12 @@ fmod :: proc{ frac :: proc{ + frac_half, frac_float, frac_double, + frac_half2, + frac_half3, + frac_half4, frac_float2, frac_float3, frac_float4, @@ -679,6 +920,9 @@ frac :: proc{ frac_double3, frac_double4, } +@(require_results) frac_half2 :: proc "c" (x: half2) -> half2 { return {frac(x.x), frac(x.y)} } +@(require_results) frac_half3 :: proc "c" (x: half3) -> half3 { return {frac(x.x), frac(x.y), frac(x.z)} } +@(require_results) frac_half4 :: proc "c" (x: half4) -> half4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} } @(require_results) frac_float2 :: proc "c" (x: float2) -> float2 { return {frac(x.x), frac(x.y)} } @(require_results) frac_float3 :: proc "c" (x: float3) -> float3 { return {frac(x.x), frac(x.y), frac(x.z)} } @(require_results) frac_float4 :: proc "c" (x: float4) -> float4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} } @@ -689,8 +933,12 @@ frac :: proc{ radians :: proc{ + radians_half, radians_float, radians_double, + radians_half2, + radians_half3, + radians_half4, radians_float2, radians_float3, radians_float4, @@ -698,8 +946,12 @@ radians :: proc{ radians_double3, radians_double4, } +@(require_results) radians_half :: proc "c" (degrees: half) -> half { return degrees * TAU / 360.0 } @(require_results) radians_float :: proc "c" (degrees: float) -> float { return degrees * TAU / 360.0 } @(require_results) radians_double :: proc "c" (degrees: double) -> double { return degrees * TAU / 360.0 } +@(require_results) radians_half2 :: proc "c" (degrees: half2) -> half2 { return degrees * TAU / 360.0 } +@(require_results) radians_half3 :: proc "c" (degrees: half3) -> half3 { return degrees * TAU / 360.0 } +@(require_results) radians_half4 :: proc "c" (degrees: half4) -> half4 { return degrees * TAU / 360.0 } @(require_results) radians_float2 :: proc "c" (degrees: float2) -> float2 { return degrees * TAU / 360.0 } @(require_results) radians_float3 :: proc "c" (degrees: float3) -> float3 { return degrees * TAU / 360.0 } @(require_results) radians_float4 :: proc "c" (degrees: float4) -> float4 { return degrees * TAU / 360.0 } @@ -709,8 +961,12 @@ radians :: proc{ degrees :: proc{ + degrees_half, degrees_float, degrees_double, + degrees_half2, + degrees_half3, + degrees_half4, degrees_float2, degrees_float3, degrees_float4, @@ -718,8 +974,12 @@ degrees :: proc{ degrees_double3, degrees_double4, } +@(require_results) degrees_half :: proc "c" (radians: half) -> half { return radians * 360.0 / TAU } @(require_results) degrees_float :: proc "c" (radians: float) -> float { return radians * 360.0 / TAU } @(require_results) degrees_double :: proc "c" (radians: double) -> double { return radians * 360.0 / TAU } +@(require_results) degrees_half2 :: proc "c" (radians: half2) -> half2 { return radians * 360.0 / TAU } +@(require_results) degrees_half3 :: proc "c" (radians: half3) -> half3 { return radians * 360.0 / TAU } +@(require_results) degrees_half4 :: proc "c" (radians: half4) -> half4 { return radians * 360.0 / TAU } @(require_results) degrees_float2 :: proc "c" (radians: float2) -> float2 { return radians * 360.0 / TAU } @(require_results) degrees_float3 :: proc "c" (radians: float3) -> float3 { return radians * 360.0 / TAU } @(require_results) degrees_float4 :: proc "c" (radians: float4) -> float4 { return radians * 360.0 / TAU } @@ -728,10 +988,14 @@ degrees :: proc{ @(require_results) degrees_double4 :: proc "c" (radians: double4) -> double4 { return radians * 360.0 / TAU } min :: proc{ + min_half, min_int, min_uint, min_float, min_double, + min_half2, + min_half3, + min_half4, min_float2, min_float3, min_float4, @@ -747,8 +1011,12 @@ min :: proc{ } @(require_results) min_int :: proc "c" (x, y: int) -> int { return builtin.min(x, y) } @(require_results) min_uint :: proc "c" (x, y: uint) -> uint { return builtin.min(x, y) } +@(require_results) min_half :: proc "c" (x, y: half) -> half { return builtin.min(x, y) } @(require_results) min_float :: proc "c" (x, y: float) -> float { return builtin.min(x, y) } @(require_results) min_double :: proc "c" (x, y: double) -> double { return builtin.min(x, y) } +@(require_results) min_half2 :: proc "c" (x, y: half2) -> half2 { return {min(x.x, y.x), min(x.y, y.y)} } +@(require_results) min_half3 :: proc "c" (x, y: half3) -> half3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +@(require_results) min_half4 :: proc "c" (x, y: half4) -> half4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } @(require_results) min_float2 :: proc "c" (x, y: float2) -> float2 { return {min(x.x, y.x), min(x.y, y.y)} } @(require_results) min_float3 :: proc "c" (x, y: float3) -> float3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } @(require_results) min_float4 :: proc "c" (x, y: float4) -> float4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } @@ -765,9 +1033,13 @@ min :: proc{ max :: proc{ max_int, - max_uint, + max_uint, + max_half, max_float, max_double, + max_half2, + max_half3, + max_half4, max_float2, max_float3, max_float4, @@ -784,7 +1056,11 @@ max :: proc{ @(require_results) max_int :: proc "c" (x, y: int) -> int { return builtin.max(x, y) } @(require_results) max_uint :: proc "c" (x, y: uint) -> uint { return builtin.max(x, y) } @(require_results) max_float :: proc "c" (x, y: float) -> float { return builtin.max(x, y) } +@(require_results) max_half :: proc "c" (x, y: half) -> half { return builtin.max(x, y) } @(require_results) max_double :: proc "c" (x, y: double) -> double { return builtin.max(x, y) } +@(require_results) max_half2 :: proc "c" (x, y: half2) -> half2 { return {max(x.x, y.x), max(x.y, y.y)} } +@(require_results) max_half3 :: proc "c" (x, y: half3) -> half3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +@(require_results) max_half4 :: proc "c" (x, y: half4) -> half4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } @(require_results) max_float2 :: proc "c" (x, y: float2) -> float2 { return {max(x.x, y.x), max(x.y, y.y)} } @(require_results) max_float3 :: proc "c" (x, y: float3) -> float3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } @(require_results) max_float4 :: proc "c" (x, y: float4) -> float4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } @@ -803,8 +1079,12 @@ max :: proc{ clamp :: proc{ clamp_int, clamp_uint, - clamp_float, + clamp_half, + clamp_float, clamp_double, + clamp_half2, + clamp_half3, + clamp_half4, clamp_float2, clamp_float3, clamp_float4, @@ -820,8 +1100,12 @@ clamp :: proc{ } @(require_results) clamp_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, y, z) } @(require_results) clamp_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, y, z) } +@(require_results) clamp_half :: proc "c" (x, y, z: half) -> half { return builtin.clamp(x, y, z) } @(require_results) clamp_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, y, z) } @(require_results) clamp_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, y, z) } +@(require_results) clamp_half2 :: proc "c" (x, y, z: half2) -> half2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +@(require_results) clamp_half3 :: proc "c" (x, y, z: half3) -> half3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +@(require_results) clamp_half4 :: proc "c" (x, y, z: half4) -> half4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } @(require_results) clamp_float2 :: proc "c" (x, y, z: float2) -> float2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } @(require_results) clamp_float3 :: proc "c" (x, y, z: float3) -> float3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } @(require_results) clamp_float4 :: proc "c" (x, y, z: float4) -> float4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } @@ -838,8 +1122,12 @@ clamp :: proc{ saturate :: proc{ saturate_int, saturate_uint, + saturate_half, saturate_float, saturate_double, + saturate_half2, + saturate_half3, + saturate_half4, saturate_float2, saturate_float3, saturate_float4, @@ -855,8 +1143,12 @@ saturate :: proc{ } @(require_results) saturate_int :: proc "c" (v: int) -> int { return builtin.clamp(v, 0, 1) } @(require_results) saturate_uint :: proc "c" (v: uint) -> uint { return builtin.clamp(v, 0, 1) } +@(require_results) saturate_half :: proc "c" (v: half) -> half { return builtin.clamp(v, 0, 1) } @(require_results) saturate_float :: proc "c" (v: float) -> float { return builtin.clamp(v, 0, 1) } @(require_results) saturate_double :: proc "c" (v: double) -> double { return builtin.clamp(v, 0, 1) } +@(require_results) saturate_half2 :: proc "c" (v: half2) -> half2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} } +@(require_results) saturate_half3 :: proc "c" (v: half3) -> half3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} } +@(require_results) saturate_half4 :: proc "c" (v: half4) -> half4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} } @(require_results) saturate_float2 :: proc "c" (v: float2) -> float2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} } @(require_results) saturate_float3 :: proc "c" (v: float3) -> float3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} } @(require_results) saturate_float4 :: proc "c" (v: float4) -> float4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} } @@ -872,8 +1164,12 @@ saturate :: proc{ lerp :: proc{ + lerp_half, lerp_float, lerp_double, + lerp_half2, + lerp_half3, + lerp_half4, lerp_float2, lerp_float3, lerp_float4, @@ -881,8 +1177,12 @@ lerp :: proc{ lerp_double3, lerp_double4, } +@(require_results) lerp_half :: proc "c" (x, y, t: half) -> half { return x*(1-t) + y*t } @(require_results) lerp_float :: proc "c" (x, y, t: float) -> float { return x*(1-t) + y*t } @(require_results) lerp_double :: proc "c" (x, y, t: double) -> double { return x*(1-t) + y*t } +@(require_results) lerp_half2 :: proc "c" (x, y, t: half2) -> half2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } +@(require_results) lerp_half3 :: proc "c" (x, y, t: half3) -> half3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } +@(require_results) lerp_half4 :: proc "c" (x, y, t: half4) -> half4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } @(require_results) lerp_float2 :: proc "c" (x, y, t: float2) -> float2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } @(require_results) lerp_float3 :: proc "c" (x, y, t: float3) -> float3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } @(require_results) lerp_float4 :: proc "c" (x, y, t: float4) -> float4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } @@ -892,8 +1192,12 @@ lerp :: proc{ step :: proc{ + step_half, step_float, step_double, + step_half2, + step_half3, + step_half4, step_float2, step_float3, step_float4, @@ -901,8 +1205,12 @@ step :: proc{ step_double3, step_double4, } +@(require_results) step_half :: proc "c" (edge, x: half) -> half { return 0 if x < edge else 1 } @(require_results) step_float :: proc "c" (edge, x: float) -> float { return 0 if x < edge else 1 } @(require_results) step_double :: proc "c" (edge, x: double) -> double { return 0 if x < edge else 1 } +@(require_results) step_half2 :: proc "c" (edge, x: half2) -> half2 { return {step(edge.x, x.x), step(edge.y, x.y)} } +@(require_results) step_half3 :: proc "c" (edge, x: half3) -> half3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } +@(require_results) step_half4 :: proc "c" (edge, x: half4) -> half4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } @(require_results) step_float2 :: proc "c" (edge, x: float2) -> float2 { return {step(edge.x, x.x), step(edge.y, x.y)} } @(require_results) step_float3 :: proc "c" (edge, x: float3) -> float3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } @(require_results) step_float4 :: proc "c" (edge, x: float4) -> float4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } @@ -911,8 +1219,12 @@ step :: proc{ @(require_results) step_double4 :: proc "c" (edge, x: double4) -> double4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } smoothstep :: proc{ + smoothstep_half, smoothstep_float, smoothstep_double, + smoothstep_half2, + smoothstep_half3, + smoothstep_half4, smoothstep_float2, smoothstep_float3, smoothstep_float4, @@ -920,6 +1232,10 @@ smoothstep :: proc{ smoothstep_double3, smoothstep_double4, } +@(require_results) smoothstep_half :: proc "c" (edge0, edge1, x: half) -> half { + y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) + return y * y * (3 - 2*y) +} @(require_results) smoothstep_float :: proc "c" (edge0, edge1, x: float) -> float { y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) return y * y * (3 - 2*y) @@ -928,6 +1244,9 @@ smoothstep :: proc{ y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) return y * y * (3 - 2*y) } +@(require_results) smoothstep_half2 :: proc "c" (edge0, edge1, x: half2) -> half2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } +@(require_results) smoothstep_half3 :: proc "c" (edge0, edge1, x: half3) -> half3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } +@(require_results) smoothstep_half4 :: proc "c" (edge0, edge1, x: half4) -> half4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } @(require_results) smoothstep_float2 :: proc "c" (edge0, edge1, x: float2) -> float2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } @(require_results) smoothstep_float3 :: proc "c" (edge0, edge1, x: float3) -> float3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } @(require_results) smoothstep_float4 :: proc "c" (edge0, edge1, x: float4) -> float4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } @@ -939,8 +1258,12 @@ smoothstep :: proc{ abs :: proc{ abs_int, abs_uint, + abs_half, abs_float, abs_double, + abs_half2, + abs_half3, + abs_half4, abs_float2, abs_float3, abs_float4, @@ -956,8 +1279,12 @@ abs :: proc{ } @(require_results) abs_int :: proc "c" (x: int) -> int { return builtin.abs(x) } @(require_results) abs_uint :: proc "c" (x: uint) -> uint { return x } +@(require_results) abs_half :: proc "c" (x: half) -> half { return builtin.abs(x) } @(require_results) abs_float :: proc "c" (x: float) -> float { return builtin.abs(x) } @(require_results) abs_double :: proc "c" (x: double) -> double { return builtin.abs(x) } +@(require_results) abs_half2 :: proc "c" (x: half2) -> half2 { return {abs(x.x), abs(x.y)} } +@(require_results) abs_half3 :: proc "c" (x: half3) -> half3 { return {abs(x.x), abs(x.y), abs(x.z)} } +@(require_results) abs_half4 :: proc "c" (x: half4) -> half4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } @(require_results) abs_float2 :: proc "c" (x: float2) -> float2 { return {abs(x.x), abs(x.y)} } @(require_results) abs_float3 :: proc "c" (x: float3) -> float3 { return {abs(x.x), abs(x.y), abs(x.z)} } @(require_results) abs_float4 :: proc "c" (x: float4) -> float4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } @@ -974,8 +1301,12 @@ abs :: proc{ dot :: proc{ dot_int, dot_uint, + dot_half, dot_float, dot_double, + dot_half2, + dot_half3, + dot_half4, dot_float2, dot_float3, dot_float4, @@ -991,8 +1322,12 @@ dot :: proc{ } @(require_results) dot_int :: proc "c" (a, b: int) -> int { return a*b } @(require_results) dot_uint :: proc "c" (a, b: uint) -> uint { return a*b } +@(require_results) dot_half :: proc "c" (a, b: half) -> half { return a*b } @(require_results) dot_float :: proc "c" (a, b: float) -> float { return a*b } @(require_results) dot_double :: proc "c" (a, b: double) -> double { return a*b } +@(require_results) dot_half2 :: proc "c" (a, b: half2) -> half { return a.x*b.x + a.y*b.y } +@(require_results) dot_half3 :: proc "c" (a, b: half3) -> half { return a.x*b.x + a.y*b.y + a.z*b.z } +@(require_results) dot_half4 :: proc "c" (a, b: half4) -> half { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } @(require_results) dot_float2 :: proc "c" (a, b: float2) -> float { return a.x*b.x + a.y*b.y } @(require_results) dot_float3 :: proc "c" (a, b: float3) -> float { return a.x*b.x + a.y*b.y + a.z*b.z } @(require_results) dot_float4 :: proc "c" (a, b: float4) -> float { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } @@ -1007,8 +1342,12 @@ dot :: proc{ @(require_results) dot_uint4 :: proc "c" (a, b: uint4) -> uint { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } length :: proc{ + length_half, length_float, length_double, + length_half2, + length_half3, + length_half4, length_float2, length_float3, length_float4, @@ -1016,8 +1355,12 @@ length :: proc{ length_double3, length_double4, } +@(require_results) length_half :: proc "c" (x: half) -> half { return builtin.abs(x) } @(require_results) length_float :: proc "c" (x: float) -> float { return builtin.abs(x) } @(require_results) length_double :: proc "c" (x: double) -> double { return builtin.abs(x) } +@(require_results) length_half2 :: proc "c" (x: half2) -> half { return sqrt(x.x*x.x + x.y*x.y) } +@(require_results) length_half3 :: proc "c" (x: half3) -> half { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } +@(require_results) length_half4 :: proc "c" (x: half4) -> half { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } @(require_results) length_float2 :: proc "c" (x: float2) -> float { return sqrt(x.x*x.x + x.y*x.y) } @(require_results) length_float3 :: proc "c" (x: float3) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } @(require_results) length_float4 :: proc "c" (x: float4) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } @@ -1027,8 +1370,12 @@ length :: proc{ distance :: proc{ + distance_half, distance_float, distance_double, + distance_half2, + distance_half3, + distance_half4, distance_float2, distance_float3, distance_float4, @@ -1036,8 +1383,12 @@ distance :: proc{ distance_double3, distance_double4, } +@(require_results) distance_half :: proc "c" (x, y: half) -> half { return length(y-x) } @(require_results) distance_float :: proc "c" (x, y: float) -> float { return length(y-x) } @(require_results) distance_double :: proc "c" (x, y: double) -> double { return length(y-x) } +@(require_results) distance_half2 :: proc "c" (x, y: half2) -> half { return length(y-x) } +@(require_results) distance_half3 :: proc "c" (x, y: half3) -> half { return length(y-x) } +@(require_results) distance_half4 :: proc "c" (x, y: half4) -> half { return length(y-x) } @(require_results) distance_float2 :: proc "c" (x, y: float2) -> float { return length(y-x) } @(require_results) distance_float3 :: proc "c" (x, y: float3) -> float { return length(y-x) } @(require_results) distance_float4 :: proc "c" (x, y: float4) -> float { return length(y-x) } @@ -1047,11 +1398,18 @@ distance :: proc{ cross :: proc{ + cross_half3, cross_float3, cross_double3, cross_int3, } +@(require_results) cross_half3 :: proc "c" (a, b: half3) -> (c: half3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} @(require_results) cross_float3 :: proc "c" (a, b: float3) -> (c: float3) { c.x = a.y*b.z - b.y*a.z c.y = a.z*b.x - b.z*a.x @@ -1072,8 +1430,12 @@ cross :: proc{ } normalize :: proc{ + normalize_half, normalize_float, normalize_double, + normalize_half2, + normalize_half3, + normalize_half4, normalize_float2, normalize_float3, normalize_float4, @@ -1081,8 +1443,12 @@ normalize :: proc{ normalize_double3, normalize_double4, } +@(require_results) normalize_half :: proc "c" (x: half) -> half { return 1.0 } @(require_results) normalize_float :: proc "c" (x: float) -> float { return 1.0 } @(require_results) normalize_double :: proc "c" (x: double) -> double { return 1.0 } +@(require_results) normalize_half2 :: proc "c" (x: half2) -> half2 { return x / length(x) } +@(require_results) normalize_half3 :: proc "c" (x: half3) -> half3 { return x / length(x) } +@(require_results) normalize_half4 :: proc "c" (x: half4) -> half4 { return x / length(x) } @(require_results) normalize_float2 :: proc "c" (x: float2) -> float2 { return x / length(x) } @(require_results) normalize_float3 :: proc "c" (x: float3) -> float3 { return x / length(x) } @(require_results) normalize_float4 :: proc "c" (x: float4) -> float4 { return x / length(x) } @@ -1092,8 +1458,12 @@ normalize :: proc{ faceforward :: proc{ + faceforward_half, faceforward_float, faceforward_double, + faceforward_half2, + faceforward_half3, + faceforward_half4, faceforward_float2, faceforward_float3, faceforward_float4, @@ -1101,8 +1471,12 @@ faceforward :: proc{ faceforward_double3, faceforward_double4, } +@(require_results) faceforward_half :: proc "c" (N, I, Nref: half) -> half { return N if dot(I, Nref) < 0 else -N } @(require_results) faceforward_float :: proc "c" (N, I, Nref: float) -> float { return N if dot(I, Nref) < 0 else -N } @(require_results) faceforward_double :: proc "c" (N, I, Nref: double) -> double { return N if dot(I, Nref) < 0 else -N } +@(require_results) faceforward_half2 :: proc "c" (N, I, Nref: half2) -> half2 { return N if dot(I, Nref) < 0 else -N } +@(require_results) faceforward_half3 :: proc "c" (N, I, Nref: half3) -> half3 { return N if dot(I, Nref) < 0 else -N } +@(require_results) faceforward_half4 :: proc "c" (N, I, Nref: half4) -> half4 { return N if dot(I, Nref) < 0 else -N } @(require_results) faceforward_float2 :: proc "c" (N, I, Nref: float2) -> float2 { return N if dot(I, Nref) < 0 else -N } @(require_results) faceforward_float3 :: proc "c" (N, I, Nref: float3) -> float3 { return N if dot(I, Nref) < 0 else -N } @(require_results) faceforward_float4 :: proc "c" (N, I, Nref: float4) -> float4 { return N if dot(I, Nref) < 0 else -N } @@ -1112,8 +1486,12 @@ faceforward :: proc{ reflect :: proc{ + reflect_half, reflect_float, reflect_double, + reflect_half2, + reflect_half3, + reflect_half4, reflect_float2, reflect_float3, reflect_float4, @@ -1121,8 +1499,12 @@ reflect :: proc{ reflect_double3, reflect_double4, } +@(require_results) reflect_half :: proc "c" (I, N: half) -> half { return I - 2*N*dot(N, I) } @(require_results) reflect_float :: proc "c" (I, N: float) -> float { return I - 2*N*dot(N, I) } @(require_results) reflect_double :: proc "c" (I, N: double) -> double { return I - 2*N*dot(N, I) } +@(require_results) reflect_half2 :: proc "c" (I, N: half2) -> half2 { return I - 2*N*dot(N, I) } +@(require_results) reflect_half3 :: proc "c" (I, N: half3) -> half3 { return I - 2*N*dot(N, I) } +@(require_results) reflect_half4 :: proc "c" (I, N: half4) -> half4 { return I - 2*N*dot(N, I) } @(require_results) reflect_float2 :: proc "c" (I, N: float2) -> float2 { return I - 2*N*dot(N, I) } @(require_results) reflect_float3 :: proc "c" (I, N: float3) -> float3 { return I - 2*N*dot(N, I) } @(require_results) reflect_float4 :: proc "c" (I, N: float4) -> float4 { return I - 2*N*dot(N, I) } @@ -1134,8 +1516,12 @@ reflect :: proc{ refract :: proc{ + refract_half, refract_float, refract_double, + refract_half2, + refract_half3, + refract_half4, refract_float2, refract_float3, refract_float4, @@ -1144,6 +1530,13 @@ refract :: proc{ refract_double4, } @(require_results) +refract_half :: proc "c" (i, n, eta: half) -> half { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * half(int(cost2 > 0)) +} +@(require_results) refract_float :: proc "c" (i, n, eta: float) -> float { cosi := dot(-i, n) cost2 := 1 - eta*eta*(1 - cosi*cosi) @@ -1158,6 +1551,27 @@ refract_double :: proc "c" (i, n, eta: double) -> double { return t * double(int(cost2 > 0)) } @(require_results) +refract_half2 :: proc "c" (i, n, eta: half2) -> half2 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * half2{half(int(cost2.x > 0)), half(int(cost2.y > 0))} +} +@(require_results) +refract_half3 :: proc "c" (i, n, eta: half3) -> half3 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * half3{half(int(cost2.x > 0)), half(int(cost2.y > 0)), half(int(cost2.z > 0))} +} +@(require_results) +refract_half4 :: proc "c" (i, n, eta: half4) -> half4 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * half4{half(int(cost2.x > 0)), half(int(cost2.y > 0)), half(int(cost2.z > 0)), half(int(cost2.w > 0))} +} +@(require_results) refract_float2 :: proc "c" (i, n, eta: float2) -> float2 { cosi := dot(-i, n) cost2 := 1 - eta*eta*(1 - cosi*cosi) @@ -1201,19 +1615,23 @@ refract_double4 :: proc "c" (i, n, eta: double4) -> double4 { } scalarTripleProduct :: proc{ + scalarTripleProduct_half3, scalarTripleProduct_float3, scalarTripleProduct_double3, scalarTripleProduct_int3, } +@(require_results) scalarTripleProduct_half3 :: proc "c" (a, b, c: half3) -> half { return dot(a, cross(b, c)) } @(require_results) scalarTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float { return dot(a, cross(b, c)) } @(require_results) scalarTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double { return dot(a, cross(b, c)) } @(require_results) scalarTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int { return dot(a, cross(b, c)) } vectorTripleProduct :: proc { + vectorTripleProduct_half3, vectorTripleProduct_float3, vectorTripleProduct_double3, vectorTripleProduct_int3, } +@(require_results) vectorTripleProduct_half3 :: proc "c" (a, b, c: half3) -> half3 { return cross(a, cross(b, c)) } @(require_results) vectorTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float3 { return cross(a, cross(b, c)) } @(require_results) vectorTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double3 { return cross(a, cross(b, c)) } @(require_results) vectorTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int3 { return cross(a, cross(b, c)) } @@ -1222,35 +1640,43 @@ vectorTripleProduct :: proc { // Vector Relational Procedures lessThan :: proc{ + lessThan_half, lessThan_float, lessThan_double, lessThan_int, lessThan_uint, + lessThan_half2, lessThan_float2, lessThan_double2, lessThan_int2, lessThan_uint2, + lessThan_half3, lessThan_float3, lessThan_double3, lessThan_int3, lessThan_uint3, + lessThan_half4, lessThan_float4, lessThan_double4, lessThan_int4, lessThan_uint4, } +@(require_results) lessThan_half :: proc "c" (a, b: half) -> bool { return a < b } @(require_results) lessThan_float :: proc "c" (a, b: float) -> bool { return a < b } @(require_results) lessThan_double :: proc "c" (a, b: double) -> bool { return a < b } @(require_results) lessThan_int :: proc "c" (a, b: int) -> bool { return a < b } @(require_results) lessThan_uint :: proc "c" (a, b: uint) -> bool { return a < b } +@(require_results) lessThan_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x < b.x, a.y < b.y} } @(require_results) lessThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x < b.x, a.y < b.y} } @(require_results) lessThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x < b.x, a.y < b.y} } @(require_results) lessThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x < b.x, a.y < b.y} } @(require_results) lessThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x < b.x, a.y < b.y} } +@(require_results) lessThan_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } @(require_results) lessThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } @(require_results) lessThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } @(require_results) lessThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } @(require_results) lessThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +@(require_results) lessThan_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } @(require_results) lessThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } @(require_results) lessThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } @(require_results) lessThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } @@ -1258,35 +1684,43 @@ lessThan :: proc{ lessThanEqual :: proc{ + lessThanEqual_half, lessThanEqual_float, lessThanEqual_double, lessThanEqual_int, lessThanEqual_uint, + lessThanEqual_half2, lessThanEqual_float2, lessThanEqual_double2, lessThanEqual_int2, lessThanEqual_uint2, + lessThanEqual_half3, lessThanEqual_float3, lessThanEqual_double3, lessThanEqual_int3, lessThanEqual_uint3, + lessThanEqual_half4, lessThanEqual_float4, lessThanEqual_double4, lessThanEqual_int4, lessThanEqual_uint4, } +@(require_results) lessThanEqual_half :: proc "c" (a, b: half) -> bool { return a <= b } @(require_results) lessThanEqual_float :: proc "c" (a, b: float) -> bool { return a <= b } @(require_results) lessThanEqual_double :: proc "c" (a, b: double) -> bool { return a <= b } @(require_results) lessThanEqual_int :: proc "c" (a, b: int) -> bool { return a <= b } @(require_results) lessThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a <= b } +@(require_results) lessThanEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } @(require_results) lessThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } @(require_results) lessThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } @(require_results) lessThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } @(require_results) lessThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } +@(require_results) lessThanEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } @(require_results) lessThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } @(require_results) lessThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } @(require_results) lessThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } @(require_results) lessThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +@(require_results) lessThanEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } @(require_results) lessThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } @(require_results) lessThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } @(require_results) lessThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } @@ -1294,35 +1728,43 @@ lessThanEqual :: proc{ greaterThan :: proc{ + greaterThan_half, greaterThan_float, greaterThan_double, greaterThan_int, greaterThan_uint, + greaterThan_half2, greaterThan_float2, greaterThan_double2, greaterThan_int2, greaterThan_uint2, + greaterThan_half3, greaterThan_float3, greaterThan_double3, greaterThan_int3, greaterThan_uint3, + greaterThan_half4, greaterThan_float4, greaterThan_double4, greaterThan_int4, greaterThan_uint4, } +@(require_results) greaterThan_half :: proc "c" (a, b: half) -> bool { return a > b } @(require_results) greaterThan_float :: proc "c" (a, b: float) -> bool { return a > b } @(require_results) greaterThan_double :: proc "c" (a, b: double) -> bool { return a > b } @(require_results) greaterThan_int :: proc "c" (a, b: int) -> bool { return a > b } @(require_results) greaterThan_uint :: proc "c" (a, b: uint) -> bool { return a > b } +@(require_results) greaterThan_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x > b.x, a.y > b.y} } @(require_results) greaterThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x > b.x, a.y > b.y} } @(require_results) greaterThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x > b.x, a.y > b.y} } @(require_results) greaterThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x > b.x, a.y > b.y} } @(require_results) greaterThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x > b.x, a.y > b.y} } +@(require_results) greaterThan_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } @(require_results) greaterThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } @(require_results) greaterThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } @(require_results) greaterThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } @(require_results) greaterThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +@(require_results) greaterThan_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } @(require_results) greaterThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } @(require_results) greaterThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } @(require_results) greaterThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } @@ -1330,35 +1772,43 @@ greaterThan :: proc{ greaterThanEqual :: proc{ + greaterThanEqual_half, greaterThanEqual_float, greaterThanEqual_double, greaterThanEqual_int, greaterThanEqual_uint, + greaterThanEqual_half2, greaterThanEqual_float2, greaterThanEqual_double2, greaterThanEqual_int2, greaterThanEqual_uint2, + greaterThanEqual_half3, greaterThanEqual_float3, greaterThanEqual_double3, greaterThanEqual_int3, greaterThanEqual_uint3, + greaterThanEqual_half4, greaterThanEqual_float4, greaterThanEqual_double4, greaterThanEqual_int4, greaterThanEqual_uint4, } +@(require_results) greaterThanEqual_half :: proc "c" (a, b: half) -> bool { return a >= b } @(require_results) greaterThanEqual_float :: proc "c" (a, b: float) -> bool { return a >= b } @(require_results) greaterThanEqual_double :: proc "c" (a, b: double) -> bool { return a >= b } @(require_results) greaterThanEqual_int :: proc "c" (a, b: int) -> bool { return a >= b } @(require_results) greaterThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a >= b } +@(require_results) greaterThanEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } @(require_results) greaterThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } @(require_results) greaterThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } @(require_results) greaterThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } @(require_results) greaterThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } +@(require_results) greaterThanEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } @(require_results) greaterThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } @(require_results) greaterThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } @(require_results) greaterThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } @(require_results) greaterThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +@(require_results) greaterThanEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } @(require_results) greaterThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } @(require_results) greaterThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } @(require_results) greaterThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } @@ -1366,70 +1816,86 @@ greaterThanEqual :: proc{ equal :: proc{ + equal_half, equal_float, equal_double, equal_int, equal_uint, + equal_half2, equal_float2, equal_double2, equal_int2, equal_uint2, + equal_half3, equal_float3, equal_double3, equal_int3, equal_uint3, + equal_half4, equal_float4, equal_double4, equal_int4, equal_uint4, } +@(require_results) equal_half :: proc "c" (a, b: half) -> bool { return a == b } @(require_results) equal_float :: proc "c" (a, b: float) -> bool { return a == b } @(require_results) equal_double :: proc "c" (a, b: double) -> bool { return a == b } @(require_results) equal_int :: proc "c" (a, b: int) -> bool { return a == b } @(require_results) equal_uint :: proc "c" (a, b: uint) -> bool { return a == b } +@(require_results) equal_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x == b.x, a.y == b.y} } @(require_results) equal_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x == b.x, a.y == b.y} } @(require_results) equal_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x == b.x, a.y == b.y} } @(require_results) equal_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x == b.x, a.y == b.y} } @(require_results) equal_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x == b.x, a.y == b.y} } +@(require_results) equal_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } @(require_results) equal_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } @(require_results) equal_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } @(require_results) equal_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } @(require_results) equal_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +@(require_results) equal_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } @(require_results) equal_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } @(require_results) equal_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } @(require_results) equal_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } @(require_results) equal_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } notEqual :: proc{ + notEqual_half, notEqual_float, notEqual_double, notEqual_int, notEqual_uint, + notEqual_half2, notEqual_float2, notEqual_double2, notEqual_int2, notEqual_uint2, + notEqual_half3, notEqual_float3, notEqual_double3, notEqual_int3, notEqual_uint3, + notEqual_half4, notEqual_float4, notEqual_double4, notEqual_int4, notEqual_uint4, } +@(require_results) notEqual_half :: proc "c" (a, b: half) -> bool { return a != b } @(require_results) notEqual_float :: proc "c" (a, b: float) -> bool { return a != b } @(require_results) notEqual_double :: proc "c" (a, b: double) -> bool { return a != b } @(require_results) notEqual_int :: proc "c" (a, b: int) -> bool { return a != b } @(require_results) notEqual_uint :: proc "c" (a, b: uint) -> bool { return a != b } +@(require_results) notEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x != b.x, a.y != b.y} } @(require_results) notEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x != b.x, a.y != b.y} } @(require_results) notEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x != b.x, a.y != b.y} } @(require_results) notEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x != b.x, a.y != b.y} } @(require_results) notEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x != b.x, a.y != b.y} } +@(require_results) notEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } @(require_results) notEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } @(require_results) notEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } @(require_results) notEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } @(require_results) notEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +@(require_results) notEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } @(require_results) notEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } @(require_results) notEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } @(require_results) notEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } @@ -1472,6 +1938,10 @@ not :: proc{ +@(require_results) inverse_half1x1 :: proc "c" (m: half1x1) -> half1x1 { return inverse_matrix1x1(m) } +@(require_results) inverse_half2x2 :: proc "c" (m: half2x2) -> half2x2 { return inverse_matrix2x2(m) } +@(require_results) inverse_half3x3 :: proc "c" (m: half3x3) -> half3x3 { return inverse_matrix3x3(m) } +@(require_results) inverse_half4x4 :: proc "c" (m: half4x4) -> half4x4 { return inverse_matrix4x4(m) } @(require_results) inverse_float1x1 :: proc "c" (m: float1x1) -> float1x1 { return inverse_matrix1x1(m) } @(require_results) inverse_float2x2 :: proc "c" (m: float2x2) -> float2x2 { return inverse_matrix2x2(m) } @(require_results) inverse_float3x3 :: proc "c" (m: float3x3) -> float3x3 { return inverse_matrix3x3(m) } @@ -1482,6 +1952,10 @@ not :: proc{ @(require_results) inverse_double4x4 :: proc "c" (m: double4x4) -> double4x4 { return inverse_matrix4x4(m) } inverse :: proc{ + inverse_half1x1, + inverse_half2x2, + inverse_half3x3, + inverse_half4x4, inverse_float1x1, inverse_float2x2, inverse_float3x3, @@ -1807,12 +2281,176 @@ inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bou +ashalf :: proc{ + ashalf_half, + ashalf_float, + ashalf_double, + ashalf_int, + ashalf_uint, + ashalf_half1x1, + ashalf_half2x2, + ashalf_half3x3, + ashalf_half4x4, + ashalf_half1x2, + ashalf_half1x3, + ashalf_half1x4, + ashalf_half2x1, + ashalf_half2x3, + ashalf_half2x4, + ashalf_half3x1, + ashalf_half3x2, + ashalf_half3x4, + ashalf_half4x1, + ashalf_half4x2, + ashalf_half4x3, + ashalf_half2, + ashalf_half3, + ashalf_half4, + ashalf_float1x1, + ashalf_float2x2, + ashalf_float3x3, + ashalf_float4x4, + ashalf_float1x2, + ashalf_float1x3, + ashalf_float1x4, + ashalf_float2x1, + ashalf_float2x3, + ashalf_float2x4, + ashalf_float3x1, + ashalf_float3x2, + ashalf_float3x4, + ashalf_float4x1, + ashalf_float4x2, + ashalf_float4x3, + ashalf_float2, + ashalf_float3, + ashalf_float4, + ashalf_int2, + ashalf_int3, + ashalf_int4, + ashalf_uint2, + ashalf_uint3, + ashalf_uint4, + ashalf_bool2, + ashalf_bool3, + ashalf_bool4, + ashalf_double1x1, + ashalf_double2x2, + ashalf_double3x3, + ashalf_double4x4, + ashalf_double1x2, + ashalf_double1x3, + ashalf_double1x4, + ashalf_double2x1, + ashalf_double2x3, + ashalf_double2x4, + ashalf_double3x1, + ashalf_double3x2, + ashalf_double3x4, + ashalf_double4x1, + ashalf_double4x2, + ashalf_double4x3, + ashalf_double2, + ashalf_double3, + ashalf_double4, +} +@(require_results) ashalf_half :: proc "c" (v: half) -> half { return half(v) } +@(require_results) ashalf_float :: proc "c" (v: float) -> half { return half(v) } +@(require_results) ashalf_double :: proc "c" (v: double) -> half { return half(v) } +@(require_results) ashalf_int :: proc "c" (v: int) -> half { return half(v) } +@(require_results) ashalf_uint :: proc "c" (v: uint) -> half { return half(v) } +@(require_results) ashalf_half1x1 :: proc "c" (v: half1x1) -> half1x1 { return half1x1(v) } +@(require_results) ashalf_half2x2 :: proc "c" (v: half2x2) -> half2x2 { return half2x2(v) } +@(require_results) ashalf_half3x3 :: proc "c" (v: half3x3) -> half3x3 { return half3x3(v) } +@(require_results) ashalf_half4x4 :: proc "c" (v: half4x4) -> half4x4 { return half4x4(v) } +@(require_results) ashalf_half1x2 :: proc "c" (v: half1x2) -> half1x2 { return half1x2(v) } +@(require_results) ashalf_half1x3 :: proc "c" (v: half1x3) -> half1x3 { return half1x3(v) } +@(require_results) ashalf_half1x4 :: proc "c" (v: half1x4) -> half1x4 { return half1x4(v) } +@(require_results) ashalf_half2x1 :: proc "c" (v: half2x1) -> half2x1 { return half2x1(v) } +@(require_results) ashalf_half2x3 :: proc "c" (v: half2x3) -> half2x3 { return half2x3(v) } +@(require_results) ashalf_half2x4 :: proc "c" (v: half2x4) -> half2x4 { return half2x4(v) } +@(require_results) ashalf_half3x1 :: proc "c" (v: half3x1) -> half3x1 { return half3x1(v) } +@(require_results) ashalf_half3x2 :: proc "c" (v: half3x2) -> half3x2 { return half3x2(v) } +@(require_results) ashalf_half3x4 :: proc "c" (v: half3x4) -> half3x4 { return half3x4(v) } +@(require_results) ashalf_half4x1 :: proc "c" (v: half4x1) -> half4x1 { return half4x1(v) } +@(require_results) ashalf_half4x2 :: proc "c" (v: half4x2) -> half4x2 { return half4x2(v) } +@(require_results) ashalf_half4x3 :: proc "c" (v: half4x3) -> half4x3 { return half4x3(v) } +@(require_results) ashalf_half2 :: proc "c" (v: half2) -> half2 { return half2(v) } +@(require_results) ashalf_half3 :: proc "c" (v: half3) -> half3 { return half3(v) } +@(require_results) ashalf_half4 :: proc "c" (v: half4) -> half4 { return half4(v) } +@(require_results) ashalf_float1x1 :: proc "c" (v: float1x1) -> half1x1 { return half1x1(v) } +@(require_results) ashalf_float2x2 :: proc "c" (v: float2x2) -> half2x2 { return half2x2(v) } +@(require_results) ashalf_float3x3 :: proc "c" (v: float3x3) -> half3x3 { return half3x3(v) } +@(require_results) ashalf_float4x4 :: proc "c" (v: float4x4) -> half4x4 { return half4x4(v) } +@(require_results) ashalf_float1x2 :: proc "c" (v: float1x2) -> half1x2 { return half1x2(v) } +@(require_results) ashalf_float1x3 :: proc "c" (v: float1x3) -> half1x3 { return half1x3(v) } +@(require_results) ashalf_float1x4 :: proc "c" (v: float1x4) -> half1x4 { return half1x4(v) } +@(require_results) ashalf_float2x1 :: proc "c" (v: float2x1) -> half2x1 { return half2x1(v) } +@(require_results) ashalf_float2x3 :: proc "c" (v: float2x3) -> half2x3 { return half2x3(v) } +@(require_results) ashalf_float2x4 :: proc "c" (v: float2x4) -> half2x4 { return half2x4(v) } +@(require_results) ashalf_float3x1 :: proc "c" (v: float3x1) -> half3x1 { return half3x1(v) } +@(require_results) ashalf_float3x2 :: proc "c" (v: float3x2) -> half3x2 { return half3x2(v) } +@(require_results) ashalf_float3x4 :: proc "c" (v: float3x4) -> half3x4 { return half3x4(v) } +@(require_results) ashalf_float4x1 :: proc "c" (v: float4x1) -> half4x1 { return half4x1(v) } +@(require_results) ashalf_float4x2 :: proc "c" (v: float4x2) -> half4x2 { return half4x2(v) } +@(require_results) ashalf_float4x3 :: proc "c" (v: float4x3) -> half4x3 { return half4x3(v) } +@(require_results) ashalf_float2 :: proc "c" (v: float2) -> half2 { return half2{half(v.x), half(v.y)} } +@(require_results) ashalf_float3 :: proc "c" (v: float3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} } +@(require_results) ashalf_float4 :: proc "c" (v: float4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} } +@(require_results) ashalf_int2 :: proc "c" (v: int2) -> half2 { return half2{half(v.x), half(v.y)} } +@(require_results) ashalf_int3 :: proc "c" (v: int3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} } +@(require_results) ashalf_int4 :: proc "c" (v: int4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} } +@(require_results) ashalf_uint2 :: proc "c" (v: uint2) -> half2 { return half2{half(v.x), half(v.y)} } +@(require_results) ashalf_uint3 :: proc "c" (v: uint3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} } +@(require_results) ashalf_uint4 :: proc "c" (v: uint4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} } +@(require_results) ashalf_bool2 :: proc "c" (v: bool2) -> half2 { return half2{half(int(v.x)), half(int(v.y))} } +@(require_results) ashalf_bool3 :: proc "c" (v: bool3) -> half3 { return half3{half(int(v.x)), half(int(v.y)), half(int(v.z))} } +@(require_results) ashalf_bool4 :: proc "c" (v: bool4) -> half4 { return half4{half(int(v.x)), half(int(v.y)), half(int(v.z)), half(int(v.w))} } +@(require_results) ashalf_double1x1 :: proc "c" (v: double1x1) -> half1x1 { return half1x1(v) } +@(require_results) ashalf_double2x2 :: proc "c" (v: double2x2) -> half2x2 { return half2x2(v) } +@(require_results) ashalf_double3x3 :: proc "c" (v: double3x3) -> half3x3 { return half3x3(v) } +@(require_results) ashalf_double4x4 :: proc "c" (v: double4x4) -> half4x4 { return half4x4(v) } +@(require_results) ashalf_double1x2 :: proc "c" (v: double1x2) -> half1x2 { return half1x2(v) } +@(require_results) ashalf_double1x3 :: proc "c" (v: double1x3) -> half1x3 { return half1x3(v) } +@(require_results) ashalf_double1x4 :: proc "c" (v: double1x4) -> half1x4 { return half1x4(v) } +@(require_results) ashalf_double2x1 :: proc "c" (v: double2x1) -> half2x1 { return half2x1(v) } +@(require_results) ashalf_double2x3 :: proc "c" (v: double2x3) -> half2x3 { return half2x3(v) } +@(require_results) ashalf_double2x4 :: proc "c" (v: double2x4) -> half2x4 { return half2x4(v) } +@(require_results) ashalf_double3x1 :: proc "c" (v: double3x1) -> half3x1 { return half3x1(v) } +@(require_results) ashalf_double3x2 :: proc "c" (v: double3x2) -> half3x2 { return half3x2(v) } +@(require_results) ashalf_double3x4 :: proc "c" (v: double3x4) -> half3x4 { return half3x4(v) } +@(require_results) ashalf_double4x1 :: proc "c" (v: double4x1) -> half4x1 { return half4x1(v) } +@(require_results) ashalf_double4x2 :: proc "c" (v: double4x2) -> half4x2 { return half4x2(v) } +@(require_results) ashalf_double4x3 :: proc "c" (v: double4x3) -> half4x3 { return half4x3(v) } +@(require_results) ashalf_double2 :: proc "c" (v: double2) -> half2 { return half2{half(v.x), half(v.y)} } +@(require_results) ashalf_double3 :: proc "c" (v: double3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} } +@(require_results) ashalf_double4 :: proc "c" (v: double4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} } asfloat :: proc{ + asfloat_half, asfloat_float, asfloat_double, asfloat_int, asfloat_uint, + asfloat_half1x1, + asfloat_half2x2, + asfloat_half3x3, + asfloat_half4x4, + asfloat_half1x2, + asfloat_half1x3, + asfloat_half1x4, + asfloat_half2x1, + asfloat_half2x3, + asfloat_half2x4, + asfloat_half3x1, + asfloat_half3x2, + asfloat_half3x4, + asfloat_half4x1, + asfloat_half4x2, + asfloat_half4x3, + asfloat_half2, + asfloat_half3, + asfloat_half4, asfloat_float1x1, asfloat_float2x2, asfloat_float3x3, @@ -1861,10 +2499,30 @@ asfloat :: proc{ asfloat_double3, asfloat_double4, } +@(require_results) asfloat_half :: proc "c" (v: half) -> float { return float(v) } @(require_results) asfloat_float :: proc "c" (v: float) -> float { return float(v) } @(require_results) asfloat_double :: proc "c" (v: double) -> float { return float(v) } @(require_results) asfloat_int :: proc "c" (v: int) -> float { return float(v) } @(require_results) asfloat_uint :: proc "c" (v: uint) -> float { return float(v) } +@(require_results) asfloat_half1x1 :: proc "c" (v: half1x1) -> float1x1 { return float1x1(v) } +@(require_results) asfloat_half2x2 :: proc "c" (v: half2x2) -> float2x2 { return float2x2(v) } +@(require_results) asfloat_half3x3 :: proc "c" (v: half3x3) -> float3x3 { return float3x3(v) } +@(require_results) asfloat_half4x4 :: proc "c" (v: half4x4) -> float4x4 { return float4x4(v) } +@(require_results) asfloat_half1x2 :: proc "c" (v: half1x2) -> float1x2 { return float1x2(v) } +@(require_results) asfloat_half1x3 :: proc "c" (v: half1x3) -> float1x3 { return float1x3(v) } +@(require_results) asfloat_half1x4 :: proc "c" (v: half1x4) -> float1x4 { return float1x4(v) } +@(require_results) asfloat_half2x1 :: proc "c" (v: half2x1) -> float2x1 { return float2x1(v) } +@(require_results) asfloat_half2x3 :: proc "c" (v: half2x3) -> float2x3 { return float2x3(v) } +@(require_results) asfloat_half2x4 :: proc "c" (v: half2x4) -> float2x4 { return float2x4(v) } +@(require_results) asfloat_half3x1 :: proc "c" (v: half3x1) -> float3x1 { return float3x1(v) } +@(require_results) asfloat_half3x2 :: proc "c" (v: half3x2) -> float3x2 { return float3x2(v) } +@(require_results) asfloat_half3x4 :: proc "c" (v: half3x4) -> float3x4 { return float3x4(v) } +@(require_results) asfloat_half4x1 :: proc "c" (v: half4x1) -> float4x1 { return float4x1(v) } +@(require_results) asfloat_half4x2 :: proc "c" (v: half4x2) -> float4x2 { return float4x2(v) } +@(require_results) asfloat_half4x3 :: proc "c" (v: half4x3) -> float4x3 { return float4x3(v) } +@(require_results) asfloat_half2 :: proc "c" (v: half2) -> float2 { return float2{float(v.x), float(v.y)} } +@(require_results) asfloat_half3 :: proc "c" (v: half3) -> float3 { return float3{float(v.x), float(v.y), float(v.z)} } +@(require_results) asfloat_half4 :: proc "c" (v: half4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} } @(require_results) asfloat_float1x1 :: proc "c" (v: float1x1) -> float1x1 { return float1x1(v) } @(require_results) asfloat_float2x2 :: proc "c" (v: float2x2) -> float2x2 { return float2x2(v) } @(require_results) asfloat_float3x3 :: proc "c" (v: float3x3) -> float3x3 { return float3x3(v) } @@ -1914,10 +2572,30 @@ asfloat :: proc{ @(require_results) asfloat_double4 :: proc "c" (v: double4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} } asdouble :: proc{ + asdouble_half, asdouble_float, asdouble_double, asdouble_int, asdouble_uint, + asdouble_half1x1, + asdouble_half2x2, + asdouble_half3x3, + asdouble_half4x4, + asdouble_half1x2, + asdouble_half1x3, + asdouble_half1x4, + asdouble_half2x1, + asdouble_half2x3, + asdouble_half2x4, + asdouble_half3x1, + asdouble_half3x2, + asdouble_half3x4, + asdouble_half4x1, + asdouble_half4x2, + asdouble_half4x3, + asdouble_half2, + asdouble_half3, + asdouble_half4, asdouble_float1x1, asdouble_float2x2, asdouble_float3x3, @@ -1966,10 +2644,30 @@ asdouble :: proc{ asdouble_double3, asdouble_double4, } +@(require_results) asdouble_half :: proc "c" (v: half) -> double { return double(v) } @(require_results) asdouble_float :: proc "c" (v: float) -> double { return double(v) } @(require_results) asdouble_double :: proc "c" (v: double) -> double { return double(v) } @(require_results) asdouble_int :: proc "c" (v: int) -> double { return double(v) } @(require_results) asdouble_uint :: proc "c" (v: uint) -> double { return double(v) } +@(require_results) asdouble_half1x1 :: proc "c" (v: half1x1) -> double1x1 { return double1x1(v) } +@(require_results) asdouble_half2x2 :: proc "c" (v: half2x2) -> double2x2 { return double2x2(v) } +@(require_results) asdouble_half3x3 :: proc "c" (v: half3x3) -> double3x3 { return double3x3(v) } +@(require_results) asdouble_half4x4 :: proc "c" (v: half4x4) -> double4x4 { return double4x4(v) } +@(require_results) asdouble_half1x2 :: proc "c" (v: half1x2) -> double1x2 { return double1x2(v) } +@(require_results) asdouble_half1x3 :: proc "c" (v: half1x3) -> double1x3 { return double1x3(v) } +@(require_results) asdouble_half1x4 :: proc "c" (v: half1x4) -> double1x4 { return double1x4(v) } +@(require_results) asdouble_half2x1 :: proc "c" (v: half2x1) -> double2x1 { return double2x1(v) } +@(require_results) asdouble_half2x3 :: proc "c" (v: half2x3) -> double2x3 { return double2x3(v) } +@(require_results) asdouble_half2x4 :: proc "c" (v: half2x4) -> double2x4 { return double2x4(v) } +@(require_results) asdouble_half3x1 :: proc "c" (v: half3x1) -> double3x1 { return double3x1(v) } +@(require_results) asdouble_half3x2 :: proc "c" (v: half3x2) -> double3x2 { return double3x2(v) } +@(require_results) asdouble_half3x4 :: proc "c" (v: half3x4) -> double3x4 { return double3x4(v) } +@(require_results) asdouble_half4x1 :: proc "c" (v: half4x1) -> double4x1 { return double4x1(v) } +@(require_results) asdouble_half4x2 :: proc "c" (v: half4x2) -> double4x2 { return double4x2(v) } +@(require_results) asdouble_half4x3 :: proc "c" (v: half4x3) -> double4x3 { return double4x3(v) } +@(require_results) asdouble_half2 :: proc "c" (v: half2) -> double2 { return double2{double(v.x), double(v.y)} } +@(require_results) asdouble_half3 :: proc "c" (v: half3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} } +@(require_results) asdouble_half4 :: proc "c" (v: half4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } @(require_results) asdouble_float1x1 :: proc "c" (v: float1x1) -> double1x1 { return double1x1(v) } @(require_results) asdouble_float2x2 :: proc "c" (v: float2x2) -> double2x2 { return double2x2(v) } @(require_results) asdouble_float3x3 :: proc "c" (v: float3x3) -> double3x3 { return double3x3(v) } @@ -2019,10 +2717,30 @@ asdouble :: proc{ @(require_results) asdouble_double4 :: proc "c" (v: double4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } asint :: proc{ + asint_half, asint_float, asint_double, asint_int, asint_uint, + asint_half1x1, + asint_half2x2, + asint_half3x3, + asint_half4x4, + asint_half1x2, + asint_half1x3, + asint_half1x4, + asint_half2x1, + asint_half2x3, + asint_half2x4, + asint_half3x1, + asint_half3x2, + asint_half3x4, + asint_half4x1, + asint_half4x2, + asint_half4x3, + asint_half2, + asint_half3, + asint_half4, asint_float1x1, asint_float2x2, asint_float3x3, @@ -2071,10 +2789,30 @@ asint :: proc{ asint_double3, asint_double4, } +@(require_results) asint_half :: proc "c" (v: half) -> int { return int(v) } @(require_results) asint_float :: proc "c" (v: float) -> int { return int(v) } @(require_results) asint_double :: proc "c" (v: double) -> int { return int(v) } @(require_results) asint_int :: proc "c" (v: int) -> int { return int(v) } @(require_results) asint_uint :: proc "c" (v: uint) -> int { return int(v) } +@(require_results) asint_half1x1 :: proc "c" (v: half1x1) -> int1x1 { return int1x1(v) } +@(require_results) asint_half2x2 :: proc "c" (v: half2x2) -> int2x2 { return int2x2(v) } +@(require_results) asint_half3x3 :: proc "c" (v: half3x3) -> int3x3 { return int3x3(v) } +@(require_results) asint_half4x4 :: proc "c" (v: half4x4) -> int4x4 { return int4x4(v) } +@(require_results) asint_half1x2 :: proc "c" (v: half1x2) -> int1x2 { return int1x2(v) } +@(require_results) asint_half1x3 :: proc "c" (v: half1x3) -> int1x3 { return int1x3(v) } +@(require_results) asint_half1x4 :: proc "c" (v: half1x4) -> int1x4 { return int1x4(v) } +@(require_results) asint_half2x1 :: proc "c" (v: half2x1) -> int2x1 { return int2x1(v) } +@(require_results) asint_half2x3 :: proc "c" (v: half2x3) -> int2x3 { return int2x3(v) } +@(require_results) asint_half2x4 :: proc "c" (v: half2x4) -> int2x4 { return int2x4(v) } +@(require_results) asint_half3x1 :: proc "c" (v: half3x1) -> int3x1 { return int3x1(v) } +@(require_results) asint_half3x2 :: proc "c" (v: half3x2) -> int3x2 { return int3x2(v) } +@(require_results) asint_half3x4 :: proc "c" (v: half3x4) -> int3x4 { return int3x4(v) } +@(require_results) asint_half4x1 :: proc "c" (v: half4x1) -> int4x1 { return int4x1(v) } +@(require_results) asint_half4x2 :: proc "c" (v: half4x2) -> int4x2 { return int4x2(v) } +@(require_results) asint_half4x3 :: proc "c" (v: half4x3) -> int4x3 { return int4x3(v) } +@(require_results) asint_half2 :: proc "c" (v: half2) -> int2 { return int2{int(v.x), int(v.y)} } +@(require_results) asint_half3 :: proc "c" (v: half3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} } +@(require_results) asint_half4 :: proc "c" (v: half4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} } @(require_results) asint_float1x1 :: proc "c" (v: float1x1) -> int1x1 { return int1x1(v) } @(require_results) asint_float2x2 :: proc "c" (v: float2x2) -> int2x2 { return int2x2(v) } @(require_results) asint_float3x3 :: proc "c" (v: float3x3) -> int3x3 { return int3x3(v) } @@ -2125,10 +2863,14 @@ asint :: proc{ asuint :: proc{ + asuint_half, asuint_float, asuint_double, asuint_int, asuint_uint, + asuint_half2, + asuint_half3, + asuint_half4, asuint_float2, asuint_float3, asuint_float4, @@ -2145,10 +2887,14 @@ asuint :: proc{ asuint_double3, asuint_double4, } +@(require_results) asuint_half :: proc "c" (v: half) -> uint { return uint(v) } @(require_results) asuint_float :: proc "c" (v: float) -> uint { return uint(v) } @(require_results) asuint_double :: proc "c" (v: double) -> uint { return uint(v) } @(require_results) asuint_int :: proc "c" (v: int) -> uint { return uint(v) } @(require_results) asuint_uint :: proc "c" (v: uint) -> uint { return uint(v) } +@(require_results) asuint_half2 :: proc "c" (v: half2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } +@(require_results) asuint_half3 :: proc "c" (v: half3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } +@(require_results) asuint_half4 :: proc "c" (v: half4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } @(require_results) asuint_float2 :: proc "c" (v: float2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } @(require_results) asuint_float3 :: proc "c" (v: float3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } @(require_results) asuint_float4 :: proc "c" (v: float4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } diff --git a/core/math/linalg/hlsl/linalg_hlsl_math.odin b/core/math/linalg/hlsl/linalg_hlsl_math.odin index 5b8004342..92c741f03 100644 --- a/core/math/linalg/hlsl/linalg_hlsl_math.odin +++ b/core/math/linalg/hlsl/linalg_hlsl_math.odin @@ -2,6 +2,42 @@ package math_linalg_hlsl import "core:math" +@(require_results) cos_half :: proc "c" (x: half) -> half { return math.cos(x) } +@(require_results) sin_half :: proc "c" (x: half) -> half { return math.sin(x) } +@(require_results) tan_half :: proc "c" (x: half) -> half { return math.tan(x) } +@(require_results) acos_half :: proc "c" (x: half) -> half { return math.acos(x) } +@(require_results) asin_half :: proc "c" (x: half) -> half { return math.asin(x) } +@(require_results) atan_half :: proc "c" (x: half) -> half { return math.atan(x) } +@(require_results) atan2_half :: proc "c" (y, x: half) -> half { return math.atan2(y, x) } +@(require_results) cosh_half :: proc "c" (x: half) -> half { return math.cosh(x) } +@(require_results) sinh_half :: proc "c" (x: half) -> half { return math.sinh(x) } +@(require_results) tanh_half :: proc "c" (x: half) -> half { return math.tanh(x) } +@(require_results) acosh_half :: proc "c" (x: half) -> half { return math.acosh(x) } +@(require_results) asinh_half :: proc "c" (x: half) -> half { return math.asinh(x) } +@(require_results) atanh_half :: proc "c" (x: half) -> half { return math.atanh(x) } +@(require_results) sqrt_half :: proc "c" (x: half) -> half { return math.sqrt(x) } +@(require_results) rsqrt_half :: proc "c" (x: half) -> half { return 1.0/math.sqrt(x) } +@(require_results) rcp_half :: proc "c" (x: half) -> half { return 1.0/x } +@(require_results) pow_half :: proc "c" (x, y: half) -> half { return math.pow(x, y) } +@(require_results) exp_half :: proc "c" (x: half) -> half { return math.exp(x) } +@(require_results) log_half :: proc "c" (x: half) -> half { return math.ln(x) } +@(require_results) log2_half :: proc "c" (x: half) -> half { return math.log(x, 2) } +@(require_results) log10_half :: proc "c" (x: half) -> half { return math.log(x, 10) } +@(require_results) exp2_half :: proc "c" (x: half) -> half { return math.pow(half(2), x) } +@(require_results) sign_half :: proc "c" (x: half) -> half { return math.sign(x) } +@(require_results) floor_half :: proc "c" (x: half) -> half { return math.floor(x) } +@(require_results) round_half :: proc "c" (x: half) -> half { return math.round(x) } +@(require_results) ceil_half :: proc "c" (x: half) -> half { return math.ceil(x) } +@(require_results) isnan_half :: proc "c" (x: half) -> bool { return math.classify(x) == .NaN} +@(require_results) fmod_half :: proc "c" (x, y: half) -> half { return math.mod(x, y) } +@(require_results) +frac_half :: proc "c" (x: half) -> half { + if x >= 0 { + return x - math.trunc(x) + } + return math.trunc(-x) + x +} + @(require_results) cos_float :: proc "c" (x: float) -> float { return math.cos(x) } @(require_results) sin_float :: proc "c" (x: float) -> float { return math.sin(x) } @(require_results) tan_float :: proc "c" (x: float) -> float { return math.tan(x) } diff --git a/core/math/linalg/specific.odin b/core/math/linalg/specific.odin index c23feddce..eea4155ca 100644 --- a/core/math/linalg/specific.odin +++ b/core/math/linalg/specific.odin @@ -164,25 +164,25 @@ orthogonal :: proc{vector2_orthogonal, vector3_orthogonal} @(require_results) vector4_srgb_to_linear_f16 :: proc "contextless" (col: Vector4f16) -> Vector4f16 { - r := math.pow(col.x, 2.2) - g := math.pow(col.y, 2.2) - b := math.pow(col.z, 2.2) + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 a := col.w return {r, g, b, a} } @(require_results) vector4_srgb_to_linear_f32 :: proc "contextless" (col: Vector4f32) -> Vector4f32 { - r := math.pow(col.x, 2.2) - g := math.pow(col.y, 2.2) - b := math.pow(col.z, 2.2) + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 a := col.w return {r, g, b, a} } @(require_results) vector4_srgb_to_linear_f64 :: proc "contextless" (col: Vector4f64) -> Vector4f64 { - r := math.pow(col.x, 2.2) - g := math.pow(col.y, 2.2) - b := math.pow(col.z, 2.2) + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 a := col.w return {r, g, b, a} } @@ -192,70 +192,55 @@ vector4_srgb_to_linear :: proc{ vector4_srgb_to_linear_f64, } +@(require_results) +vector3_srgb_to_linear_f16 :: proc "contextless" (col: Vector3f16) -> Vector3f16 { + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 + return {r, g, b} +} +@(require_results) +vector3_srgb_to_linear_f32 :: proc "contextless" (col: Vector3f32) -> Vector3f32 { + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 + return {r, g, b} +} +@(require_results) +vector3_srgb_to_linear_f64 :: proc "contextless" (col: Vector3f64) -> Vector3f64 { + r := math.pow((col.x + 0.055) / 1.055, 2.4) if col.x > 0.04045 else col.x / 12.92 + g := math.pow((col.y + 0.055) / 1.055, 2.4) if col.y > 0.04045 else col.y / 12.92 + b := math.pow((col.z + 0.055) / 1.055, 2.4) if col.z > 0.04045 else col.z / 12.92 + return {r, g, b} +} +vector3_srgb_to_linear :: proc{ + vector3_srgb_to_linear_f16, + vector3_srgb_to_linear_f32, + vector3_srgb_to_linear_f64, +} + @(require_results) vector4_linear_to_srgb_f16 :: proc "contextless" (col: Vector4f16) -> Vector4f16 { - a :: 2.51 - b :: 0.03 - c :: 2.43 - d :: 0.59 - e :: 0.14 - - x := col.x - y := col.y - z := col.z - - x = (x * (a * x + b)) / (x * (c * x + d) + e) - y = (y * (a * y + b)) / (y * (c * y + d) + e) - z = (z * (a * z + b)) / (z * (c * z + d) + e) - - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z return {x, y, z, col.w} } @(require_results) vector4_linear_to_srgb_f32 :: proc "contextless" (col: Vector4f32) -> Vector4f32 { - a :: 2.51 - b :: 0.03 - c :: 2.43 - d :: 0.59 - e :: 0.14 - - x := col.x - y := col.y - z := col.z - - x = (x * (a * x + b)) / (x * (c * x + d) + e) - y = (y * (a * y + b)) / (y * (c * y + d) + e) - z = (z * (a * z + b)) / (z * (c * z + d) + e) - - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z return {x, y, z, col.w} } @(require_results) vector4_linear_to_srgb_f64 :: proc "contextless" (col: Vector4f64) -> Vector4f64 { - a :: 2.51 - b :: 0.03 - c :: 2.43 - d :: 0.59 - e :: 0.14 - - x := col.x - y := col.y - z := col.z - - x = (x * (a * x + b)) / (x * (c * x + d) + e) - y = (y * (a * y + b)) / (y * (c * y + d) + e) - z = (z * (a * z + b)) / (z * (c * z + d) + e) - - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z return {x, y, z, col.w} } @@ -265,6 +250,36 @@ vector4_linear_to_srgb :: proc{ vector4_linear_to_srgb_f64, } +@(require_results) +vector3_linear_to_srgb_f16 :: proc "contextless" (col: Vector3f16) -> Vector3f16 { + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z + + return {x, y, z} +} +@(require_results) +vector3_linear_to_srgb_f32 :: proc "contextless" (col: Vector3f32) -> Vector3f32 { + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z + + return {x, y, z} +} +@(require_results) +vector3_linear_to_srgb_f64 :: proc "contextless" (col: Vector3f64) -> Vector3f64 { + x := 1.055 * math.pow(col.x, 1.0 / 2.4) - 0.055 if col.x > 0.0031308 else 12.92 * col.x + y := 1.055 * math.pow(col.y, 1.0 / 2.4) - 0.055 if col.y > 0.0031308 else 12.92 * col.y + z := 1.055 * math.pow(col.z, 1.0 / 2.4) - 0.055 if col.z > 0.0031308 else 12.92 * col.z + + return {x, y, z} +} +vector3_linear_to_srgb :: proc{ + vector3_linear_to_srgb_f16, + vector3_linear_to_srgb_f32, + vector3_linear_to_srgb_f64, +} + @(require_results) vector4_hsl_to_rgb_f16 :: proc "contextless" (h, s, l: f16, a: f16 = 1) -> Vector4f16 { @@ -497,7 +512,8 @@ quaternion_angle_axis :: proc{ @(require_results) angle_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + angle := math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + return q.w < 0 ? math.TAU - angle : angle } return math.acos(q.w) * 2 @@ -505,7 +521,8 @@ angle_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 { @(require_results) angle_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + angle := math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + return q.w < 0 ? math.TAU - angle : angle } return math.acos(q.w) * 2 @@ -513,7 +530,8 @@ angle_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 { @(require_results) angle_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + angle := math.asin(math.sqrt(q.x*q.x + q.y*q.y + q.z*q.z)) * 2 + return q.w < 0 ? math.TAU - angle : angle } return math.acos(q.w) * 2 @@ -620,7 +638,7 @@ quaternion_from_forward_and_up_f16 :: proc "contextless" (forward, up: Vector3f1 case: S := 2 * math.sqrt(1 + m[2, 2] - m[0, 0] - m[1, 1]) q.w = (m[0, 1] - m[1, 0]) / S - q.x = (m[2, 0] - m[0, 2]) / S + q.x = (m[2, 0] + m[0, 2]) / S q.y = (m[2, 1] + m[1, 2]) / S q.z = 0.25 * S } @@ -664,7 +682,7 @@ quaternion_from_forward_and_up_f32 :: proc "contextless" (forward, up: Vector3f3 case: S := 2 * math.sqrt(1 + m[2, 2] - m[0, 0] - m[1, 1]) q.w = (m[0, 1] - m[1, 0]) / S - q.x = (m[2, 0] - m[0, 2]) / S + q.x = (m[2, 0] + m[0, 2]) / S q.y = (m[2, 1] + m[1, 2]) / S q.z = 0.25 * S } @@ -708,7 +726,7 @@ quaternion_from_forward_and_up_f64 :: proc "contextless" (forward, up: Vector3f6 case: S := 2 * math.sqrt(1 + m[2, 2] - m[0, 0] - m[1, 1]) q.w = (m[0, 1] - m[1, 0]) / S - q.x = (m[2, 0] - m[0, 2]) / S + q.x = (m[2, 0] + m[0, 2]) / S q.y = (m[2, 1] + m[1, 2]) / S q.z = 0.25 * S } @@ -2750,52 +2768,16 @@ matrix2_orthonormalize :: proc{ @(require_results) -matrix3_orthonormalize_f16 :: proc "contextless" (m: Matrix3f16) -> (r: Matrix3f16) #no_bounds_check { - r = m - r[0] = normalize(m[0]) - - d0 := dot(r[0], r[1]) - r[1] -= r[0] * d0 - r[1] = normalize(r[1]) - - d1 := dot(r[1], r[2]) - d0 = dot(r[0], r[2]) - r[2] -= r[0]*d0 + r[1]*d1 - r[2] = normalize(r[2]) - - return +matrix3_orthonormalize_f16 :: proc "contextless" (m: Matrix3f16) -> Matrix3f16 #no_bounds_check { + return matrix3_gram_schmidt(m, 0, 1, 2) } @(require_results) -matrix3_orthonormalize_f32 :: proc "contextless" (m: Matrix3f32) -> (r: Matrix3f32) #no_bounds_check { - r = m - r[0] = normalize(m[0]) - - d0 := dot(r[0], r[1]) - r[1] -= r[0] * d0 - r[1] = normalize(r[1]) - - d1 := dot(r[1], r[2]) - d0 = dot(r[0], r[2]) - r[2] -= r[0]*d0 + r[1]*d1 - r[2] = normalize(r[2]) - - return +matrix3_orthonormalize_f32 :: proc "contextless" (m: Matrix3f32) -> Matrix3f32 #no_bounds_check { + return matrix3_gram_schmidt(m, 0, 1, 2) } @(require_results) -matrix3_orthonormalize_f64 :: proc "contextless" (m: Matrix3f64) -> (r: Matrix3f64) #no_bounds_check { - r = m - r[0] = normalize(m[0]) - - d0 := dot(r[0], r[1]) - r[1] -= r[0] * d0 - r[1] = normalize(r[1]) - - d1 := dot(r[1], r[2]) - d0 = dot(r[0], r[2]) - r[2] -= r[0]*d0 + r[1]*d1 - r[2] = normalize(r[2]) - - return +matrix3_orthonormalize_f64 :: proc "contextless" (m: Matrix3f64) -> Matrix3f64 #no_bounds_check { + return matrix3_gram_schmidt(m, 0, 1, 2) } matrix3_orthonormalize :: proc{ matrix3_orthonormalize_f16, @@ -2804,6 +2786,27 @@ matrix3_orthonormalize :: proc{ } +@(require_results) +matrix3_gram_schmidt :: proc "contextless" (m: matrix[3, 3]$E, $A, $B, $C: int) -> (r: matrix[3, 3]E) + where A != B, A != C, B != C #no_bounds_check +{ + r = m + r[A] = normalize(m[A]) + + d0 := dot(r[A], r[B]) + r[B] -= r[A] * d0 + r[B] = normalize(r[B]) + + d1 := dot(r[B], r[C]) + d0 = dot(r[A], r[C]) + r[C] -= r[A]*d0 + r[B]*d1 + r[C] = normalize(r[C]) + + return +} + + + @(require_results) vector3_orthonormalize_f16 :: proc "contextless" (x, y: Vector3f16) -> (z: Vector3f16) { return normalize(x - y * dot(y, x)) diff --git a/core/math/math.odin b/core/math/math.odin index b99a97bc1..6fe872907 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -1,3 +1,4 @@ +// Typical trignometric and other basic math routines. package math import "base:intrinsics" @@ -402,7 +403,12 @@ remap :: proc "contextless" (old_value, old_min, old_max, new_min, new_max: $T) if old_range == 0 { return new_range / 2 } - return ((old_value - old_min) / old_range) * new_range + new_min + + when intrinsics.type_is_integer(T) { + return (((old_value - old_min)) * new_range) / old_range + new_min + } else { + return ((old_value - old_min) / old_range) * new_range + new_min + } } @(require_results) @@ -412,7 +418,7 @@ remap_clamped :: proc "contextless" (old_value, old_min, old_max, new_min, new_m } @(require_results) -wrap :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { +wrap :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_numeric(T), intrinsics.type_is_float(T), !intrinsics.type_is_array(T) { tmp := mod(x, y) return y + tmp if tmp < 0 else tmp } @@ -451,7 +457,6 @@ gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_float(T) { return bias(t*2 - 1, 1 - g) * 0.5 + 0.5 } - @(require_results) sign_f16 :: proc "contextless" (x: f16) -> f16 { return f16(int(0 < x) - int(x < 0)) } @(require_results) sign_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(int(0 < x) - int(x < 0)) } @(require_results) sign_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(int(0 < x) - int(x < 0)) } @@ -461,10 +466,24 @@ gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_float(T) { @(require_results) sign_f64 :: proc "contextless" (x: f64) -> f64 { return f64(int(0 < x) - int(x < 0)) } @(require_results) sign_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(int(0 < x) - int(x < 0)) } @(require_results) sign_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(int(0 < x) - int(x < 0)) } +@(require_results) sign_int :: proc "contextless" (x: int) -> int { return int(0 < x) - int(x < 0) } +@(require_results) sign_i16 :: proc "contextless" (x: i16) -> i16 { return i16(int(0 < x) - int(x < 0)) } +@(require_results) sign_i16le :: proc "contextless" (x: i16le) -> i16le { return i16le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i16be :: proc "contextless" (x: i16be) -> i16be { return i16be(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32 :: proc "contextless" (x: i32) -> i32 { return i32(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32le :: proc "contextless" (x: i32le) -> i32le { return i32le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32be :: proc "contextless" (x: i32be) -> i32be { return i32be(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64 :: proc "contextless" (x: i64) -> i64 { return i64(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64le :: proc "contextless" (x: i64le) -> i64le { return i64le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64be :: proc "contextless" (x: i64be) -> i64be { return i64be(int(0 < x) - int(x < 0)) } sign :: proc{ sign_f16, sign_f16le, sign_f16be, sign_f32, sign_f32le, sign_f32be, sign_f64, sign_f64le, sign_f64be, + sign_int, + sign_i16, sign_i16le, sign_i16be, + sign_i32, sign_i32le, sign_i32be, + sign_i64, sign_i64le, sign_i64be, } @(require_results) sign_bit_f16 :: proc "contextless" (x: f16) -> bool { return (transmute(u16)x) & (1<<15) != 0 } @@ -476,10 +495,24 @@ sign :: proc{ @(require_results) sign_bit_f64 :: proc "contextless" (x: f64) -> bool { return (transmute(u64)x) & (1<<63) != 0 } @(require_results) sign_bit_f64le :: proc "contextless" (x: f64le) -> bool { return #force_inline sign_bit_f64(f64(x)) } @(require_results) sign_bit_f64be :: proc "contextless" (x: f64be) -> bool { return #force_inline sign_bit_f64(f64(x)) } +@(require_results) sign_bit_int :: proc "contextless" (x: int) -> bool { return uint(x) & (1<<(size_of(int)*8 - 1)) != 0 } +@(require_results) sign_bit_i16 :: proc "contextless" (x: i16) -> bool { return u16(x) & (1<<15) != 0 } +@(require_results) sign_bit_i16le :: proc "contextless" (x: i16le) -> bool { return #force_inline sign_bit_i16(i16(x)) } +@(require_results) sign_bit_i16be :: proc "contextless" (x: i16be) -> bool { return #force_inline sign_bit_i16(i16(x)) } +@(require_results) sign_bit_i32 :: proc "contextless" (x: i32) -> bool { return u32(x) & (1<<31) != 0 } +@(require_results) sign_bit_i32le :: proc "contextless" (x: i32le) -> bool { return #force_inline sign_bit_i32(i32(x)) } +@(require_results) sign_bit_i32be :: proc "contextless" (x: i32be) -> bool { return #force_inline sign_bit_i32(i32(x)) } +@(require_results) sign_bit_i64 :: proc "contextless" (x: i64) -> bool { return u64(x) & (1<<63) != 0 } +@(require_results) sign_bit_i64le :: proc "contextless" (x: i64le) -> bool { return #force_inline sign_bit_i64(i64(x)) } +@(require_results) sign_bit_i64be :: proc "contextless" (x: i64be) -> bool { return #force_inline sign_bit_i64(i64(x)) } sign_bit :: proc{ sign_bit_f16, sign_bit_f16le, sign_bit_f16be, sign_bit_f32, sign_bit_f32le, sign_bit_f32be, sign_bit_f64, sign_bit_f64le, sign_bit_f64be, + sign_bit_int, + sign_bit_i16, sign_bit_i16le, sign_bit_i16be, + sign_bit_i32, sign_bit_i32le, sign_bit_i32be, + sign_bit_i64, sign_bit_i64le, sign_bit_i64be, } @(require_results) @@ -1580,17 +1613,11 @@ is_power_of_two :: proc "contextless" (x: int) -> bool { @(require_results) next_power_of_two :: proc "contextless" (x: int) -> int { - k := x -1 - when size_of(int) == 8 { - k = k | (k >> 32) + if x <= 1 { + return 1 } - k = k | (k >> 16) - k = k | (k >> 8) - k = k | (k >> 4) - k = k | (k >> 2) - k = k | (k >> 1) - k += 1 + int(x <= 0) - return k + n := uint(size_of(x) * 8) - uint(intrinsics.count_leading_zeros(uint(x) - 1)) + return int(1) << n } @(require_results) diff --git a/core/math/math_cbrt.odin b/core/math/math_cbrt.odin new file mode 100644 index 000000000..98c0281aa --- /dev/null +++ b/core/math/math_cbrt.odin @@ -0,0 +1,103 @@ +package math + +import "base:intrinsics" + +@(require_results) cbrt_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(cbrt_f16(f16(x))) } +@(require_results) cbrt_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(cbrt_f16(f16(x))) } +@(require_results) cbrt_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(cbrt_f32(f32(x))) } +@(require_results) cbrt_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(cbrt_f32(f32(x))) } +@(require_results) cbrt_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(cbrt_f64(f64(x))) } +@(require_results) cbrt_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(cbrt_f64(f64(x))) } + +// cbrt returns the cube root of x. +// +// Special cases are: +// +// cbrt(±0) = ±0 +// cbrt(±Inf) = ±Inf +// cbrt(NaN) = NaN +cbrt :: proc{ + cbrt_f16, cbrt_f16le, cbrt_f16be, + cbrt_f32, cbrt_f32le, cbrt_f32be, + cbrt_f64, cbrt_f64le, cbrt_f64be, +} + + + +@(require_results) +cbrt_f16 :: proc "contextless" (x: f16) -> f16 { return #force_inline f16(cbrt_f64(f64(x))) } +@(require_results) +cbrt_f32 :: proc "contextless" (x: f32) -> f32 { return #force_inline f32(cbrt_f64(f64(x))) } + +// cbrt returns the cube root of x. +// +// Special cases are: +// +// cbrt(±0) = ±0 +// cbrt(±Inf) = ±Inf +// cbrt(NaN) = NaN +@(require_results) +cbrt_f64 :: proc "contextless" (x: f64) -> f64 { + // http://www.netlib.org/fdlibm/s_cbrt.c and came with this notice. + // + // ==================================================== + // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + // + // Developed at SunSoft, a Sun Microsystems, Inc. business. + // Permission to use, copy, modify, and distribute this + // software is freely granted, provided that this notice + // is preserved. + // ==================================================== + + B1 :: 715094163 // (682-0.03306235651)*2**20 + B2 :: 696219795 // (664-0.03306235651)*2**20 + SMALLEST_NORMAL :: 0h0010000000000000 // 2.22507385850720138309e-308 == 2**-1022 + + C :: 0h3FE15F15F15F15F1 // 5.42857142857142815906e-01 == 19/35 + D :: 0hBFE691DE2532C834 // -7.05306122448979611050e-01 == -864/1225 + E :: 0h3FF6A0EA0EA0EA0F // 1.41428571428571436819e+00 == 99/70 + F :: 0h3FF9B6DB6DB6DB6E // 1.60714285714285720630e+00 == 45/28 + G :: 0h3FD6DB6DB6DB6DB7 // 3.57142857142857150787e-01 == 5/14 + + x := x + + switch { + case x == 0 || is_nan(x) || is_inf(x, 0): + return x + } + + sign := false + if x < 0 { + x = -x + sign = true + } + + // Approximate cbrt (5-bits) + t := transmute(f64)((transmute(u64)x)/3 + B1<<32) + if x < SMALLEST_NORMAL { + t = f64(1 << 54) + t *= x + t = transmute(f64)((transmute(u64)x)/3 + B2<<32) + } + + // Approximate cbrt (23-bits) + r := t * t / x + s := C + r*t + t *= G + F/(s+E + D/s) + + // Truncate to 22 bits, make larger than cbrt(x) + t = transmute(f64)((transmute(u64)t)&(0xffffffffc<<28) + 1<<30) + + // Single step of Newton-Raphson iteration to 53 bits with error less than 0.667ulps + s = t * t // t*t is exact + r = x / s + w := t + t + r = (r - t) / (w + r) // r-s is exact + t = t + t*r + + // Restore sign + if sign { + t = -t + } + return t +} diff --git a/core/math/math_sincos.odin b/core/math/math_sincos.odin index 9b4d3de40..a17f39fe5 100644 --- a/core/math/math_sincos.odin +++ b/core/math/math_sincos.odin @@ -1,6 +1,6 @@ package math -import "core:math/bits" +import "base:intrinsics" // The original C code, the long comment, and the constants // below were from http://netlib.sandia.gov/cephes/cmath/sin.c, @@ -280,16 +280,16 @@ _trig_reduce_f64 :: proc "contextless" (x: f64) -> (j: u64, z: f64) #no_bounds_c z1 := (bd_pi4[digit+1] << bitshift) | (bd_pi4[digit+2] >> (64 - bitshift)) z2 := (bd_pi4[digit+2] << bitshift) | (bd_pi4[digit+3] >> (64 - bitshift)) // Multiply mantissa by the digits and extract the upper two digits (hi, lo). - z2hi, _ := bits.mul(z2, ix) - z1hi, z1lo := bits.mul(z1, ix) + z2hi, _ := mul_u64(z2, ix) + z1hi, z1lo := mul_u64(z1, ix) z0lo := z0 * ix - lo, c := bits.add(z1lo, z2hi, 0) - hi, _ := bits.add(z0lo, z1hi, c) + lo, c := add_u64(z1lo, z2hi, 0) + hi, _ := add_u64(z0lo, z1hi, c) // The top 3 bits are j. j = hi >> 61 // Extract the fraction and find its magnitude. hi = hi<<3 | lo>>61 - lz := uint(bits.leading_zeros(hi)) + lz := uint(intrinsics.count_leading_zeros(hi)) e := u64(BIAS - (lz + 1)) // Clear implicit mantissa bit and shift into place. hi = (hi << (lz + 1)) | (lo >> (64 - (lz + 1))) @@ -305,4 +305,20 @@ _trig_reduce_f64 :: proc "contextless" (x: f64) -> (j: u64, z: f64) #no_bounds_c } // Multiply the fractional part by pi/4. return j, z * PI4 + + @(require_results) + add_u64 :: proc "contextless" (x, y, carry: u64) -> (sum, carry_out: u64) { + tmp_carry, tmp_carry2: bool + sum, tmp_carry = intrinsics.overflow_add(x, y) + sum, tmp_carry2 = intrinsics.overflow_add(sum, carry) + carry_out = u64(tmp_carry | tmp_carry2) + return + } + + @(require_results) + mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) { + prod_wide := u128(x) * u128(y) + hi, lo = u64(prod_wide>>64), u64(prod_wide) + return + } } diff --git a/core/math/noise/internal.odin b/core/math/noise/internal.odin index f75c0ee87..af3e16ad8 100644 --- a/core/math/noise/internal.odin +++ b/core/math/noise/internal.odin @@ -1,11 +1,12 @@ +#+private +package math_noise + /* OpenSimplex2 noise implementation. Ported from https://github.com/KdotJPG/OpenSimplex2. Copyright 2022 Yuki2 (https://github.com/NoahR02) */ -#+private -package math_noise /* Private implementation details follow. diff --git a/core/math/noise/opensimplex2.odin b/core/math/noise/opensimplex2.odin index 634c32948..0fabdf3cf 100644 --- a/core/math/noise/opensimplex2.odin +++ b/core/math/noise/opensimplex2.odin @@ -1,7 +1,7 @@ /* - OpenSimplex2 noise implementation. + [[ OpenSimplex2 ; https://github.com/KdotJPG/OpenSimplex2 ]] noise algorithm. - Ported from [[ https://github.com/KdotJPG/OpenSimplex2 }]. + Ported from [[ https://github.com/KdotJPG/OpenSimplex2 ]]. Copyright 2022 Yuki2 [[ https://github.com/NoahR02 ]] */ package math_noise diff --git a/core/math/rand/distributions.odin b/core/math/rand/distributions.odin index 755e6f86f..7718bef9a 100644 --- a/core/math/rand/distributions.odin +++ b/core/math/rand/distributions.odin @@ -1,5 +1,6 @@ package rand +import "base:runtime" import "core:math" float64_uniform :: float64_range @@ -336,3 +337,76 @@ float64_gompertz :: proc(eta, b: f64, gen := context.random_generator) -> f64 { float32_gompertz :: proc(eta, b: f32, gen := context.random_generator) -> f32 { return f32(float64_gompertz(f64(eta), f64(b), gen)) } + + + +// A contextual structure for generating Zipf distributed variates. +Zipf :: struct { + gen: runtime.Random_Generator, + imax: f64, + v: f64, + q: f64, + s: f64, + oneminus_Q: f64, + oneminus_Qinv: f64, + hxm: f64, + hx0_minus_hxm: f64, +} + + +// Creates a Zipf variate generator. +// The generator produces values k ∈ [0, imax] such that P(k) is proportional to (v + k) ** (-s). +// The parameters must be: s > 1 and v >= 1 +// +// W.Hormann, G.Derflinger: +// "Rejection-Inversion to Generate Variates from Monotone Discrete Distributions" +// [[ http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz ]] +@(require_results) +zipf_create :: proc(s, v: f64, imax: u64, gen := context.random_generator) -> (z: Zipf, ok: bool) { + if s <= 1 || v < 1 { + return + } + z.gen = gen + z.imax = f64(imax) + z.v = v + z.q = s + z.oneminus_Q = 1.0 - z.q + z.oneminus_Qinv = 1.0 / z.oneminus_Q + z.hxm = zipf_h(z, z.imax + 0.5) + z.hx0_minus_hxm = zipf_h(z, 0.5) - math.exp(math.ln(z.v)*(-z.q)) - z.hxm + z.s = 1 - zipf_hinv(z, zipf_h(z, 1.5)-math.exp(-z.q * math.ln(z.v+1.0))) + return z, true +} + + +@(require_results) +zipf_h :: proc(z: Zipf, x: f64) -> f64 { + return math.exp(z.oneminus_Q * math.ln(z.v + x) * z.oneminus_Qinv) +} +@(require_results) +zipf_hinv :: proc(z: Zipf, x: f64) -> f64 { + return math.exp(z.oneminus_Qinv * math.ln(z.oneminus_Q * x)) - z.v +} + + +// Returns a value drawn from the zipf distribution described by the `Zipf` contextual structure. +@(require_results) +zipf_uint64 :: proc(z: Zipf) -> u64 { + assert(z.gen.procedure != nil) + k := f64(0.0) + + for { + r := float64(z.gen) // [0, 1) + ur := r * z.hx0_minus_hxm + z.hxm + x := zipf_hinv(z, ur) + k = math.floor(x + 0.5) + if k-x <= z.s { + break + } + if ur >= zipf_h(z, k+0.5) - math.exp(-math.ln(k + z.v)*z.q) { + break + } + } + + return u64(k) +} \ No newline at end of file diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 56208931f..738de07e5 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -1,28 +1,59 @@ - -/* -Package core:math/rand implements various random number generators -*/ +// Random number generators. package rand import "base:intrinsics" import "base:runtime" import "core:math" -import "core:mem" Generator :: runtime.Random_Generator Generator_Query_Info :: runtime.Random_Generator_Query_Info Default_Random_State :: runtime.Default_Random_State + +/* +Returns an instance of the runtime pseudorandom generator. If no +initial state is provided, the PRNG will be lazily initialized with +entropy from the system entropy source on first-use. + +The cryptographic security of the returned random number generator +is directly dependent on the quality of the initialization entropy. +Calling `reset`/`create` SHOULD be done with no seed/state, or +32-bytes of high-quality entropy. + +WARNING: +- The lazy initialization will panic if there is no system entropy + source available. +- While the generator is cryptographically secure, developers SHOULD + prefer `crypto.random_generator()` for cryptographic use cases such + as key generation. + +Inputs: +- state: Optional initial PRNG state. + +Returns: +- A `Generator` instance. +*/ default_random_generator :: runtime.default_random_generator @(require_results) -create :: proc(seed: u64) -> (state: Default_Random_State) { +create_u64 :: proc(seed: u64) -> (state: Default_Random_State) { seed := seed runtime.default_random_generator_proc(&state, .Reset, ([^]byte)(&seed)[:size_of(seed)]) return } +@(require_results) +create_bytes :: proc(seed: []byte) -> (state: Default_Random_State) { + runtime.default_random_generator_proc(&state, .Reset, seed) + return +} + +create :: proc { + create_u64, + create_bytes, +} + /* Reset the seed used by the context.random_generator. @@ -42,10 +73,14 @@ Possible Output: 10 */ -reset :: proc(seed: u64, gen := context.random_generator) { - runtime.random_generator_reset_u64(gen, seed) +reset :: proc { + reset_u64, + reset_bytes, } +reset_u64 :: proc(seed: u64, gen := context.random_generator) { + runtime.random_generator_reset_u64(gen, seed) +} reset_bytes :: proc(bytes: []byte, gen := context.random_generator) { runtime.random_generator_reset_bytes(gen, bytes) @@ -56,13 +91,6 @@ query_info :: proc(gen := context.random_generator) -> Generator_Query_Info { } -@(private) -_random_u64 :: proc(gen := context.random_generator) -> (res: u64) { - ok := runtime.random_generator_read_ptr(gen, &res, size_of(res)) - assert(ok, "uninitialized gen/context.random_generator") - return -} - /* Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -84,7 +112,7 @@ Possible Output: */ @(require_results) -uint32 :: proc(gen := context.random_generator) -> (val: u32) { return u32(_random_u64(gen)) } +uint32 :: proc(gen := context.random_generator) -> (val: u32) {return u32(uint64(gen))} /* Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -107,7 +135,11 @@ Possible Output: */ @(require_results) -uint64 :: proc(gen := context.random_generator) -> (val: u64) { return _random_u64(gen) } +uint64 :: proc(gen := context.random_generator) -> (val: u64) { + ok := runtime.random_generator_read_ptr(gen, &val, size_of(val)) + assert(ok, "uninitialized gen/context.random_generator") + return +} /* Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -131,13 +163,13 @@ Possible Output: */ @(require_results) uint128 :: proc(gen := context.random_generator) -> (val: u128) { - a := u128(_random_u64(gen)) - b := u128(_random_u64(gen)) + a := u128(uint64(gen)) + b := u128(uint64(gen)) return (a<<64) | b } /* -Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -160,7 +192,7 @@ Possible Output: @(require_results) int31 :: proc(gen := context.random_generator) -> (val: i32) { return i32(uint32(gen) << 1 >> 1) } /* -Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -183,7 +215,7 @@ Possible Output: @(require_results) int63 :: proc(gen := context.random_generator) -> (val: i64) { return i64(uint64(gen) << 1 >> 1) } /* -Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -214,7 +246,7 @@ Inputs: Returns: - val: A random 31 bit value in the range `[0, n)` -WARNING: Panics if n is less than 0 +WARNING: Panics if n is less than or equal to 0 Example: import "core:math/rand" @@ -227,7 +259,7 @@ Example: Possible Output: 6 - 500 + 13 */ @(require_results) @@ -255,7 +287,7 @@ Inputs: Returns: - val: A random 63 bit value in the range `[0, n)` -WARNING: Panics if n is less than 0 +WARNING: Panics if n is less than or equal to 0 Example: import "core:math/rand" @@ -268,7 +300,7 @@ Example: Possible Output: 6 - 500 + 13 */ @(require_results) @@ -296,7 +328,7 @@ Inputs: Returns: - val: A random 127 bit value in the range `[0, n)` -WARNING: Panics if n is less than 0 +WARNING: Panics if n is less than or equal to 0 Example: import "core:math/rand" @@ -309,7 +341,7 @@ Example: Possible Output: 6 - 500 + 13 */ @(require_results) @@ -337,7 +369,7 @@ Inputs: Returns: - val: A random integer value in the range `[0, n)` -WARNING: Panics if n is less than 0 +WARNING: Panics if n is less than or equal to 0 Example: import "core:math/rand" @@ -350,7 +382,7 @@ Example: Possible Output: 6 - 500 + 13 */ @(require_results) @@ -365,6 +397,478 @@ int_max :: proc(n: int, gen := context.random_generator) -> (val: int) { } } +/* +Generates a random 32 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- n: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 32 bit value in the range `[0, n)` + +WARNING: Panics if n is equal to 0 + +Example: + import "core:math/rand" + import "core:fmt" + + uint32_max_example :: proc() { + fmt.println(rand.uint32_max(16)) + } + +Possible Output: + + 6 + 13 + +*/ +@(require_results) +uint32_max :: proc(n: u32, gen := context.random_generator) -> (val: u32) { + if n == 0 { + panic("Invalid argument to uint32_max") + } + if n & (n - 1) == 0 { + return uint32(gen) & (n - 1) + } + min := (-n) % n + v := uint32(gen) + for v < min { + v = uint32(gen) + } + return v % n +} + +/* +Generates a random 64 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- n: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 64 bit value in the range `[0, n)` + +WARNING: Panics if n is equal to 0 + +Example: + import "core:math/rand" + import "core:fmt" + + uint64_max_example :: proc() { + fmt.println(rand.uint64_max(16)) + } + +Possible Output: + + 6 + 13 + +*/ +@(require_results) +uint64_max :: proc(n: u64, gen := context.random_generator) -> (val: u64) { + if n == 0 { + panic("Invalid argument to uint64_max") + } + if n & (n - 1) == 0 { + return uint64(gen) & (n - 1) + } + min := (-n) % n + v := uint64(gen) + for v < min { + v = uint64(gen) + } + return v % n +} + +/* +Generates a random 128 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- n: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 128 bit value in the range `[0, n)` + +WARNING: Panics if n is equal to 0 + +Example: + import "core:math/rand" + import "core:fmt" + + uint128_max_example :: proc() { + fmt.println(rand.uint128_max(16)) + } + +Possible Output: + + 6 + 13 + +*/ +@(require_results) +uint128_max :: proc(n: u128, gen := context.random_generator) -> (val: u128) { + if n == 0 { + panic("Invalid argument to uint128_max") + } + if n & (n - 1) == 0 { + return uint128(gen) & (n - 1) + } + min := (-n) % n + v := uint128(gen) + for v < min { + v = uint128(gen) + } + return v % n +} + +/* +Generates a random integer value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- n: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random integer value in the range `[0, n)` + +WARNING: Panics if n is equal to 0 + +Example: + import "core:math/rand" + import "core:fmt" + + uint_max_example :: proc() { + fmt.println(rand.uint_max(16)) + } + +Possible Output: + + 6 + 13 + +*/ +@(require_results) +uint_max :: proc(n: uint, gen := context.random_generator) -> (val: uint) { + if n <= 0 { + panic("Invalid argument to uint_max") + } + when size_of(int) == 4 { + return uint(uint32_max(u32(n), gen)) + } else { + return uint(uint64_max(u64(n), gen)) + } +} + +/* +Generates a random unsigned 32 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 32 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + uint32_range_example :: proc() { + fmt.println(rand.uint32_range(5,15)) + } + +Possible Output: + + 6 + 13 + +*/ +uint32_range :: proc(lo, hi: u32, gen := context.random_generator) -> (val: u32) { + assert(lo < hi, "Invalid arguments to uint32_range: lo must be less than hi") + range := hi - lo + if (range & (range - 1)) == 0 { + return lo + (uint32(gen) & (range - 1)) + } + threshold := -range % range + v := uint32(gen) + for v < threshold { + v = uint32(gen) + } + return lo + (v % range) +} + +/* +Generates a random unsigned 64 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 64 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + uint64_range_example :: proc() { + fmt.println(rand.uint64_range(5,15)) + } + +Possible Output: + + 6 + 13 + +*/ +uint64_range :: proc(lo, hi: u64, gen := context.random_generator) -> (val: u64) { + assert(lo < hi, "Invalid arguments to uint64_range: lo must be less than hi") + range := hi - lo + if (range & (range - 1)) == 0 { + return lo + (uint64(gen) & (range - 1)) + } + threshold := -range % range + v := uint64(gen) + for v < threshold { + v = uint64(gen) + } + return lo + (v % range) +} + +/* +Generates a random unsigned 128 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 128 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + uint128_range_example :: proc() { + fmt.println(rand.uint128_range(5,15)) + } + +Possible Output: + + 6 + 13 + +*/ +uint128_range :: proc(lo, hi: u128, gen := context.random_generator) -> (val: u128) { + assert(lo < hi, "Invalid arguments to uint128_range: lo must be less than hi") + range := hi - lo + if (range & (range - 1)) == 0 { + return lo + (uint128(gen) & (range - 1)) + } + threshold := -range % range + v := uint128(gen) + for v < threshold { + v = uint128(gen) + } + return lo + (v % range) +} + +/* +Generates a random unsigned integer value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random integer value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + uint_range_example :: proc() { + fmt.println(rand.uint_range(5,15)) + } + +Possible Output: + + 6 + 13 + +*/ +@(require_results) +uint_range :: proc(lo, hi: uint, gen := context.random_generator) -> (val: uint) { + assert(lo < hi, "Invalid arguments to uint_range: lo must be less than hi") + when size_of(int) == 4 { + return uint(uint32_range(u32(lo), u32(hi), gen)) + } else { + return uint(uint64_range(u64(lo), u64(hi), gen)) + } +} + +/* +Generates a random signed 32 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 32 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + int32_range_example :: proc() { + fmt.println(rand.int32_range(-10,10)) + } + +Possible Output: + + 6 + -9 + +*/ +int32_range :: proc(lo, hi: i32, gen := context.random_generator) -> (val: i32) { + assert(lo < hi, "Invalid arguments to int32_range: lo must be less than hi") + range := u32(hi) - u32(lo) + if (range & (range - 1)) == 0 { + return lo + i32(uint32(gen) & (range - 1)) + } + threshold := -range % range + v := uint32(gen) + for v < threshold { + v = uint32(gen) + } + return lo + i32(v % range) +} + +/* +Generates a random signed 64 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 64 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + int64_range_example :: proc() { + fmt.println(rand.int64_range(-10,10)) + } + +Possible Output: + + 6 + -9 + +*/ +int64_range :: proc(lo, hi: i64, gen := context.random_generator) -> (val: i64) { + assert(lo < hi, "Invalid arguments to int64_range: lo must be less than hi") + range := u64(hi) - u64(lo) + if (range & (range - 1)) == 0 { + return lo + i64(uint64(gen) & (range - 1)) + } + threshold := -range % range + v := uint64(gen) + for v < threshold { + v = uint64(gen) + } + return lo + i64(v % range) +} + +/* +Generates a random signed 128 bit value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random 128 bit value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + int128_range_example :: proc() { + fmt.println(rand.int128_range(-10,10)) + } + +Possible Output: + + 6 + -9 + +*/ +int128_range :: proc(lo, hi: i128, gen := context.random_generator) -> (val: i128) { + assert(lo < hi, "Invalid arguments to int128_range: lo must be less than hi") + range := u128(hi) - u128(lo) + if (range & (range - 1)) == 0 { + return lo + i128(uint128(gen) & (range - 1)) + } + threshold := -range % range + v := uint128(gen) + for v < threshold { + v = uint128(gen) + } + return lo + i128(v % range) +} + +/* +Generates a random signed integer value in the range `[lo, hi)` using the provided random number generator. If no generator is provided the global random number generator will be used. + +Inputs: +- lo: The lower bound of the generated number, this value is inclusice +- hi: The upper bound of the generated number, this value is exclusive + +Returns: +- val: A random integer value in the range `[lo, hi)` + +WARNING: Panics if `lo` is greater or equal to `hi` + +Example: + import "core:math/rand" + import "core:fmt" + + int_range_example :: proc() { + fmt.println(rand.int_range(-10,10)) + } + +Possible Output: + + 6 + -9 + +*/ +@(require_results) +int_range :: proc(lo, hi: int, gen := context.random_generator) -> (val: int) { + assert(lo < hi, "Invalid arguments to int_range: lo must be less than hi") + when size_of(int) == 4 { + return int(int32_range(i32(lo), i32(hi), gen)) + } else { + return int(int64_range(i64(lo), i64(hi), gen)) + } +} + /* Generates a random double floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -480,8 +984,8 @@ Possible Output: } /* -Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - p: The byte slice to fill @@ -508,22 +1012,12 @@ Possible Output: */ @(require_results) read :: proc(p: []byte, gen := context.random_generator) -> (n: int) { - pos := i8(0) - val := i64(0) - for n = 0; n < len(p); n += 1 { - if pos == 0 { - val = int63(gen) - pos = 7 - } - p[n] = byte(val) - val >>= 8 - pos -= 1 - } - return + if !runtime.random_generator_read_bytes(gen, p) {return 0} + return len(p) } /* -Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used. +Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used. *Allocates Using Provided Allocator* @@ -536,11 +1030,11 @@ Returns: - err: An allocator error if one occured, `nil` otherwise Example: + import "base:runtime" import "core:math/rand" - import "core:mem" import "core:fmt" - perm_example :: proc() -> (err: mem.Allocator_Error) { + perm_example :: proc() -> (err: runtime.Allocator_Error) { data := rand.perm(4) or_return fmt.println(data) defer delete(data, context.allocator) @@ -555,7 +1049,7 @@ Possible Output: */ @(require_results) -perm :: proc(n: int, allocator := context.allocator, gen := context.random_generator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error { +perm :: proc(n: int, allocator := context.allocator, gen := context.random_generator) -> (res: []int, err: runtime.Allocator_Error) #optional_allocator_error { m := make([]int, n, allocator) or_return for i := 0; i < n; i += 1 { j := int_max(i+1, gen) @@ -566,7 +1060,7 @@ perm :: proc(n: int, allocator := context.allocator, gen := context.random_gener } /* -Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used. +Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used. Inputs: - array: The slice to randomize @@ -607,7 +1101,7 @@ shuffle :: proc(array: $T/[]$E, gen := context.random_generator) { } /* -Returns a random element from the provided slice. If no generator is provided the global random number generator will be used. +Returns a random element from the provided slice. If no generator is provided the global random number generator will be used. Inputs: - array: The slice to choose an element from @@ -704,11 +1198,14 @@ choice_bit_set :: proc(set: $T/bit_set[$E], gen := context.random_generator) -> return {}, false } - core_set := transmute(intrinsics.type_bit_set_underlying_type(T))set + target := int_max(total_set, gen) - for target := int_max(total_set, gen); target > 0; target -= 1 { - core_set &= core_set - 1 + for value in set { + if target == 0 { + return value, true + } + target -= 1 } - return E(intrinsics.count_trailing_zeros(core_set)), true + return {}, false } diff --git a/core/math/rand/rand_pcg.odin b/core/math/rand/rand_pcg.odin new file mode 100644 index 000000000..79c18acbb --- /dev/null +++ b/core/math/rand/rand_pcg.odin @@ -0,0 +1,111 @@ +package rand + +import "base:intrinsics" +import "base:runtime" + +/* +The state for a PCG64 RXS-M-XS pseudorandom generator. +*/ +PCG_Random_State :: struct { + state: u64, + inc: u64, +} + +pcg_random_generator_proc :: proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) { + @(require_results) + read_u64 :: proc "contextless" (r: ^PCG_Random_State) -> u64 { + old_state := r.state + r.state = old_state * 6364136223846793005 + (r.inc|1) + xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081 + rot := (old_state >> 59) + return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63)) + } + + @(thread_local) + global_rand_seed: PCG_Random_State + + init :: proc "contextless" (r: ^PCG_Random_State, seed: u64) { + seed := seed + if seed == 0 { + seed = u64(intrinsics.read_cycle_counter()) + } + r.state = 0 + r.inc = (seed << 1) | 1 + _ = read_u64(r) + r.state += seed + _ = read_u64(r) + } + + r: ^PCG_Random_State = --- + if data == nil { + r = &global_rand_seed + } else { + r = cast(^PCG_Random_State)data + } + + switch mode { + case .Read: + if r.state == 0 && r.inc == 0 { + init(r, 0) + } + + switch len(p) { + case size_of(u64): + // Fast path for a 64-bit destination. + intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r)) + case: + // All other cases. + n := len(p) / size_of(u64) + buff := ([^]u64)(raw_data(p))[:n] + for &e in buff { + intrinsics.unaligned_store(&e, read_u64(r)) + } + // Handle remaining bytes + rem := len(p) % size_of(u64) + if rem > 0 { + val := read_u64(r) + tail := p[len(p) - rem:] + for &b in tail { + b = byte(val) + val >>= 8 + } + } + } + + case .Reset: + seed: u64 + runtime.mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p))) + init(r, seed) + + case .Query_Info: + if len(p) != size_of(Generator_Query_Info) { + return + } + info := (^Generator_Query_Info)(raw_data(p)) + info^ += {.Uniform, .Resettable} + } +} + +/* +Returns an instance of the PGC64 RXS-M-XS pseudorandom generator. If no +initial state is provided, the PRNG will be lazily initialized with the +system timestamp counter on first-use. + +WARNING: This random number generator is NOT cryptographically secure, +and is additionally known to be flawed. It is only included for +backward compatibility with historical releases of Odin. +See: https://github.com/odin-lang/Odin/issues/5881 + +Inputs: +- state: Optional initial PRNG state. + +Returns: +- A `Generator` instance. +*/ +@(require_results) +pcg_random_generator :: proc "contextless" (state: ^PCG_Random_State = nil) -> Generator { + return { + procedure = pcg_random_generator_proc, + data = state, + } +} diff --git a/core/math/rand/rand_xoshiro256.odin b/core/math/rand/rand_xoshiro256.odin new file mode 100644 index 000000000..3771d2beb --- /dev/null +++ b/core/math/rand/rand_xoshiro256.odin @@ -0,0 +1,144 @@ +package rand + +import "base:intrinsics" +import "base:runtime" + +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + // LLVM thinks that using SIMD for read_u64 is good, + // when it causes a ~3x performance regression. As + // far as I can tell, this behavior is limited to + // Intel. + @(private = "file") + TARGET_FEATURES :: "-sse,-avx,-avx2" +} else { + @(private = "file") + TARGET_FEATURES :: "" +} + +/* +The state for a xoshiro256** pseudorandom generator. +*/ +Xoshiro256_Random_State :: struct { + s: [4]u64, +} + +@(enable_target_feature = TARGET_FEATURES) +xoshiro256_random_generator_proc :: proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) { + @(require_results, enable_target_feature = TARGET_FEATURES) + read_u64 :: proc "contextless" (r: ^Xoshiro256_Random_State) -> u64 { + // xoshiro256** output function and state transition + + result := rotate_left64(r.s[1] * 5, 7) * 9 + t := r.s[1] << 17 + + r.s[2] = r.s[2] ~ r.s[0] + r.s[3] = r.s[3] ~ r.s[1] + r.s[1] = r.s[1] ~ r.s[2] + r.s[0] = r.s[0] ~ r.s[3] + r.s[2] = r.s[2] ~ t + r.s[3] = rotate_left64(r.s[3], 45) + + return result + + rotate_left64 :: #force_inline proc "contextless" (x: u64, k: int) -> u64 { + n :: 64 + s := uint(k) & (n-1) + return x << s | x >> (n-s) + } + } + + @(thread_local) + global_rand_seed: Xoshiro256_Random_State + + init :: proc "contextless" (r: ^Xoshiro256_Random_State, seed: u64) { + // splitmix64 to expand a 64-bit seed into 256 bits of state + sm64_next :: proc "contextless" (s: ^u64) -> u64 { + s^ += 0x9E3779B97F4A7C15 + z := s^ + z = (z ~ (z >> 30)) * 0xBF58476D1CE4E5B9 + z = (z ~ (z >> 27)) * 0x94D049BB133111EB + return z ~ (z >> 31) + } + + local_seed := seed + r.s[0] = sm64_next(&local_seed) + r.s[1] = sm64_next(&local_seed) + r.s[2] = sm64_next(&local_seed) + r.s[3] = sm64_next(&local_seed) + // Extremely unlikely all zero; ensure non-zero state + if (r.s[0] | r.s[1] | r.s[2] | r.s[3]) == 0 { + // force a minimal non-zero tweak + r.s[0] = 1 + } + } + + r: ^Xoshiro256_Random_State = --- + if data == nil { + r = &global_rand_seed + } else { + r = cast(^Xoshiro256_Random_State)data + } + + switch mode { + case .Read: + if (r.s[0] | r.s[1] | r.s[2] | r.s[3]) == 0 { + init(r, u64(intrinsics.read_cycle_counter())) + } + + switch len(p) { + case size_of(u64): + // Fast path for a 64-bit destination. + intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r)) + case: + // All other cases. + n := len(p) / size_of(u64) + buff := ([^]u64)(raw_data(p))[:n] + for &e in buff { + intrinsics.unaligned_store(&e, read_u64(r)) + } + // Handle remaining bytes + rem := len(p) % size_of(u64) + if rem > 0 { + val := read_u64(r) + tail := p[len(p) - rem:] + for &b in tail { + b = byte(val) + val >>= 8 + } + } + } + + case .Reset: + seed: u64 = 0 + runtime.mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p))) + init(r, seed) + + case .Query_Info: + if len(p) != size_of(Generator_Query_Info) { + return + } + info := (^Generator_Query_Info)(raw_data(p)) + info^ += {.Uniform, .Resettable} + } +} + +/* +Returns an instance of the xoshiro256** pseudorandom generator. If no +initial state is provided, the PRNG will be lazily initialized with the +system timestamp counter on first-use. + +WARNING: This random number generator is NOT cryptographically secure. + +Inputs: +- state: Optional initial PRNG state. + +Returns: +- A `Generator` instance. +*/ +@(require_results) +xoshiro256_random_generator :: proc "contextless" (state: ^Xoshiro256_Random_State = nil) -> Generator { + return { + procedure = xoshiro256_random_generator_proc, + data = state, + } +} diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 48cc39245..282c8d0b4 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -255,11 +255,10 @@ alignment is not specified explicitly. DEFAULT_ALIGNMENT :: 2*align_of(rawptr) /* -Default page size. - -This value is the default page size for the current platform. +On platforms where we were able to query a configurable size, we use that value instead. +See `query_page_size_init()` */ -DEFAULT_PAGE_SIZE :: +PAGE_SIZE: int = 64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else 16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else 4 * 1024 diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 1bb887212..dcd126230 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -2,7 +2,57 @@ package mem import "base:intrinsics" import "base:runtime" -import "base:sanitizer" + +// NOTE(Feoramund): Sanitizer usage in this package has been temporarily +// disabled pending a thorough review per allocator, as ASan is particular +// about the addresses and ranges it receives. +// +// In short, it keeps track only of 8-byte blocks. This can cause issues if an +// allocator poisons an entire range but an allocation for less than 8 bytes is +// desired or if the next allocation address would not be 8-byte aligned. +// +// This must be handled carefully on a per-allocator basis and some allocators +// may not be able to participate. +// +// Please see the following link for more information: +// +// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping +// +// import "base:sanitizer" + + +/* +This procedure checks if a byte slice `range` is poisoned and makes sure the +root address of the poison range is the base pointer of `range`. + +This can help guard against buggy allocators returning memory that they already returned. + +This has no effect if `-sanitize:address` is not enabled. +*/ +// @(disabled=.Address not_in ODIN_SANITIZER_FLAGS, private) +// ensure_poisoned :: proc(range: []u8, loc := #caller_location) { +// cond := sanitizer.address_region_is_poisoned(range) == raw_data(range) +// // If this fails, we've overlapped an allocation and it's our fault. +// ensure(cond, `This allocator has sliced a block of memory of which some part is not poisoned before returning. +// This is a bug in the core library and should be reported to the Odin developers with a stack trace and minimal example code if possible.`, loc) +// } + +/* +This procedure checks if a byte slice `range` is not poisoned. + +This can help guard against buggy allocators resizing memory that they should not. + +This has no effect if `-sanitize:address` is not enabled. +*/ +// @(disabled=.Address not_in ODIN_SANITIZER_FLAGS, private) +// ensure_not_poisoned :: proc(range: []u8, loc := #caller_location) { +// cond := sanitizer.address_region_is_poisoned(range) == nil +// // If this fails, we've tried to resize memory that is poisoned, which +// // could be user error caused by an incorrect `old_memory` pointer. +// ensure(cond, `This allocator has sliced a block of memory of which some part is poisoned before returning. +// This may be a bug in the core library, or it could be user error due to an invalid pointer passed to a resize operation. +// If after ensuring your own code is not responsible, report the problem to the Odin developers with a stack trace and minimal example code if possible.`, loc) +// } /* Nil allocator. @@ -49,8 +99,8 @@ panic_allocator :: proc() -> Allocator { panic_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, - size, alignment: int, - old_memory: rawptr, + size, alignment: int, + old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]byte, Allocator_Error) { @@ -108,11 +158,10 @@ The arena allocator (also known as a linear allocator, bump allocator, region allocator) is an allocator that uses a single backing buffer for allocations. -The buffer is being used contiguously, from start by end. Each subsequent -allocation occupies the next adjacent region of memory in the buffer. Since -arena allocator does not keep track of any metadata associated with the -allocations and their locations, it is impossible to free individual -allocations. +The buffer is used contiguously, from start to end. Each subsequent allocation +occupies the next adjacent region of memory in the buffer. Since the arena +allocator does not keep track of any metadata associated with the allocations +and their locations, it is impossible to free individual allocations. The arena allocator can be used for temporary allocations in frame-based memory management. Games are one example of such applications. A global arena can be @@ -131,7 +180,7 @@ arena_allocator :: proc(arena: ^Arena) -> Allocator { /* Initialize an arena. -This procedure initializes the arena `a` with memory region `data` as it's +This procedure initializes the arena `a` with memory region `data` as its backing buffer. */ arena_init :: proc(a: ^Arena, data: []byte) { @@ -139,7 +188,7 @@ arena_init :: proc(a: ^Arena, data: []byte) { a.offset = 0 a.peak_used = 0 a.temp_count = 0 - sanitizer.address_poison(a.data) + // sanitizer.address_poison(a.data) } /* @@ -216,7 +265,7 @@ arena_alloc_bytes_non_zeroed :: proc( loc := #caller_location ) -> ([]byte, Allocator_Error) { if a.data == nil { - panic("Arena is not initialized", loc) + panic("Allocation on uninitialized Arena allocator.", loc) } #no_bounds_check end := &a.data[a.offset] ptr := align_forward(end, uintptr(alignment)) @@ -227,16 +276,17 @@ arena_alloc_bytes_non_zeroed :: proc( a.offset += total_size a.peak_used = max(a.peak_used, a.offset) result := byte_slice(ptr, size) - sanitizer.address_unpoison(result) + // ensure_poisoned(result) + // sanitizer.address_unpoison(result) return result, nil } /* -Free all memory to an arena. +Free all memory back to the arena allocator. */ arena_free_all :: proc(a: ^Arena) { a.offset = 0 - sanitizer.address_poison(a.data) + // sanitizer.address_poison(a.data) } arena_allocator_proc :: proc( @@ -275,12 +325,12 @@ arena_allocator_proc :: proc( } /* -Temporary memory region of arena. +Temporary memory region of an `Arena` allocator. -Temporary memory regions of arena act as "savepoints" for arena. When one is -created, the subsequent allocations are done inside the temporary memory -region. When `end_arena_temp_memory` is called, the arena is rolled back, and -all of the memory that was allocated from the arena will be freed. +Temporary memory regions of an arena act as "save-points" for the allocator. +When one is created, the subsequent allocations are done inside the temporary +memory region. When `end_arena_temp_memory` is called, the arena is rolled +back, and all of the memory that was allocated from the arena will be freed. Multiple temporary memory regions can exist at the same time for an arena. */ @@ -314,7 +364,7 @@ allocations *inside* the temporary memory region will be freed to the arena. end_arena_temp_memory :: proc(tmp: Arena_Temp_Memory) { assert(tmp.arena.offset >= tmp.prev_offset) assert(tmp.arena.temp_count > 0) - sanitizer.address_poison(tmp.arena.data[tmp.prev_offset:tmp.arena.offset]) + // sanitizer.address_poison(tmp.arena.data[tmp.prev_offset:tmp.arena.offset]) tmp.arena.offset = tmp.prev_offset tmp.arena.temp_count -= 1 } @@ -328,29 +378,37 @@ scratch_allocator_destroy :: scratch_destroy Scratch allocator data. */ Scratch :: struct { - data: []byte, - curr_offset: int, - prev_allocation: rawptr, - backup_allocator: Allocator, - leaked_allocations: [dynamic][]byte, + data: []byte, + curr_offset: int, + prev_allocation: rawptr, + prev_allocation_root: rawptr, + backup_allocator: Allocator, + leaked_allocations: [dynamic][]byte, } /* Scratch allocator. The scratch allocator works in a similar way to the `Arena` allocator. The -scratch allocator has a backing buffer, that is being allocated in -contiguous regions, from start to end. +scratch allocator has a backing buffer that is allocated in contiguous regions, +from start to end. Each subsequent allocation will be the next adjacent region of memory in the backing buffer. If the allocation doesn't fit into the remaining space of the backing buffer, this allocation is put at the start of the buffer, and all -previous allocations will become invalidated. If the allocation doesn't fit -into the backing buffer as a whole, it will be allocated using a backing -allocator, and pointer to the allocated memory region will be put into the -`leaked_allocations` array. +previous allocations will become invalidated. -The `leaked_allocations` array is managed by the `context` allocator. +If the allocation doesn't fit into the backing buffer as a whole, it will be +allocated using a backing allocator, and the pointer to the allocated memory +region will be put into the `leaked_allocations` array. A `Warning`-level log +message will be sent as well. + +Allocations which are resized will be resized in-place if they were the last +allocation. Otherwise, they are re-allocated to avoid overwriting previous +allocations. + +The `leaked_allocations` array is managed by the `context` allocator if no +`backup_allocator` is specified in `scratch_init`. */ @(require_results) scratch_allocator :: proc(allocator: ^Scratch) -> Allocator { @@ -361,20 +419,24 @@ scratch_allocator :: proc(allocator: ^Scratch) -> Allocator { } /* -Initialize scratch allocator. +Initialize a scratch allocator. */ scratch_init :: proc(s: ^Scratch, size: int, backup_allocator := context.allocator) -> Allocator_Error { s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) or_return s.curr_offset = 0 s.prev_allocation = nil + s.prev_allocation_root = nil s.backup_allocator = backup_allocator s.leaked_allocations.allocator = backup_allocator - sanitizer.address_poison(s.data) + // sanitizer.address_poison(s.data) return nil } /* Free all data associated with a scratch allocator. + +This is distinct from `scratch_free_all` in that it deallocates all memory used +to setup the allocator, as opposed to all allocations made from that space. */ scratch_destroy :: proc(s: ^Scratch) { if s == nil { @@ -384,13 +446,13 @@ scratch_destroy :: proc(s: ^Scratch) { free_bytes(ptr, s.backup_allocator) } delete(s.leaked_allocations) - sanitizer.address_unpoison(s.data) + // sanitizer.address_unpoison(s.data) delete(s.data, s.backup_allocator) s^ = {} } /* -Allocate memory from scratch allocator. +Allocate memory from a scratch allocator. This procedure allocates `size` bytes of memory aligned on a boundary specified by `alignment`. The allocated memory region is zero-initialized. This procedure @@ -408,7 +470,7 @@ scratch_alloc :: proc( } /* -Allocate memory from scratch allocator. +Allocate memory from a scratch allocator. This procedure allocates `size` bytes of memory aligned on a boundary specified by `alignment`. The allocated memory region is zero-initialized. This procedure @@ -429,7 +491,7 @@ scratch_alloc_bytes :: proc( } /* -Allocate non-initialized memory from scratch allocator. +Allocate non-initialized memory from a scratch allocator. This procedure allocates `size` bytes of memory aligned on a boundary specified by `alignment`. The allocated memory region is not explicitly zero-initialized. @@ -447,7 +509,7 @@ scratch_alloc_non_zeroed :: proc( } /* -Allocate non-initialized memory from scratch allocator. +Allocate non-initialized memory from a scratch allocator. This procedure allocates `size` bytes of memory aligned on a boundary specified by `alignment`. The allocated memory region is not explicitly zero-initialized. @@ -463,39 +525,40 @@ scratch_alloc_bytes_non_zeroed :: proc( if s.data == nil { DEFAULT_BACKING_SIZE :: 4 * Megabyte if !(context.allocator.procedure != scratch_allocator_proc && context.allocator.data != s) { - panic("cyclic initialization of the scratch allocator with itself", loc) + panic("Cyclic initialization of the scratch allocator with itself.", loc) } scratch_init(s, DEFAULT_BACKING_SIZE) } - size := size - size = align_forward_int(size, alignment) - if size <= len(s.data) { - offset := uintptr(0) - if s.curr_offset+size <= len(s.data) { - offset = uintptr(s.curr_offset) - } else { - offset = 0 - } + aligned_size := size + if alignment > 1 { + // It is possible to do this with less bytes, but this is the + // mathematically simpler solution, and this being a Scratch allocator, + // we don't need to be so strict about every byte. + aligned_size += alignment - 1 + } + if s.curr_offset+aligned_size <= len(s.data) { + offset := uintptr(s.curr_offset) start := uintptr(raw_data(s.data)) - ptr := align_forward_uintptr(offset+start, uintptr(alignment)) - s.prev_allocation = rawptr(ptr) - s.curr_offset = int(offset) + size - result := byte_slice(rawptr(ptr), size) - sanitizer.address_unpoison(result) + ptr := rawptr(offset+start) + // We keep track of the original base pointer without extra alignment + // in order to later allow the free operation to work from that point. + s.prev_allocation_root = ptr + if !is_aligned(ptr, alignment) { + ptr = align_forward(ptr, uintptr(alignment)) + } + s.prev_allocation = ptr + s.curr_offset = int(offset) + aligned_size + result := byte_slice(ptr, size) + // ensure_poisoned(result) + // sanitizer.address_unpoison(result) return result, nil } else { + // NOTE: No need to use `aligned_size` here, as the backup allocator will handle alignment for us. a := s.backup_allocator - if a.procedure == nil { - a = context.allocator - s.backup_allocator = a - } ptr, err := alloc_bytes_non_zeroed(size, alignment, a, loc) if err != nil { return ptr, err } - if s.leaked_allocations == nil { - s.leaked_allocations, err = make([dynamic][]byte, a) - } append(&s.leaked_allocations, ptr) if logger := context.logger; logger.lowest_level <= .Warning { if logger.procedure != nil { @@ -507,7 +570,7 @@ scratch_alloc_bytes_non_zeroed :: proc( } /* -Free memory to the scratch allocator. +Free memory back to the scratch allocator. This procedure frees the memory region allocated at pointer `ptr`. @@ -516,7 +579,7 @@ operation is a no-op. */ scratch_free :: proc(s: ^Scratch, ptr: rawptr, loc := #caller_location) -> Allocator_Error { if s.data == nil { - panic("Free on an uninitialized scratch allocator", loc) + panic("Free on an uninitialized Scratch allocator.", loc) } if ptr == nil { return nil @@ -525,9 +588,10 @@ scratch_free :: proc(s: ^Scratch, ptr: rawptr, loc := #caller_location) -> Alloc end := start + uintptr(len(s.data)) old_ptr := uintptr(ptr) if s.prev_allocation == ptr { - s.curr_offset = int(uintptr(s.prev_allocation) - start) - sanitizer.address_poison(s.data[s.curr_offset:]) + s.curr_offset = int(uintptr(s.prev_allocation_root) - start) + // sanitizer.address_poison(s.data[s.curr_offset:]) s.prev_allocation = nil + s.prev_allocation_root = nil return nil } if start <= old_ptr && old_ptr < end { @@ -548,7 +612,7 @@ scratch_free :: proc(s: ^Scratch, ptr: rawptr, loc := #caller_location) -> Alloc } /* -Free all memory to the scratch allocator. +Free all memory back to the scratch allocator. */ scratch_free_all :: proc(s: ^Scratch, loc := #caller_location) { s.curr_offset = 0 @@ -557,15 +621,15 @@ scratch_free_all :: proc(s: ^Scratch, loc := #caller_location) { free_bytes(ptr, s.backup_allocator, loc) } clear(&s.leaked_allocations) - sanitizer.address_poison(s.data) + // sanitizer.address_poison(s.data) } /* -Resize an allocation. +Resize an allocation owned by a scratch allocator. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `scratch_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -590,10 +654,10 @@ scratch_resize :: proc( } /* -Resize an allocation. +Resize an allocation owned by a scratch allocator. -This procedure resizes a memory region, specified by `old_data`, to have a size -`size` and alignment `alignment`. The newly allocated memory, if any is +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `scratch_alloc()`, @@ -621,11 +685,11 @@ scratch_resize_bytes :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a scratch allocator, without zero-initialization. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is not explicitly zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `scratch_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -650,10 +714,10 @@ scratch_resize_non_zeroed :: proc( } /* -Resize an allocation. +Resize an allocation owned by a scratch allocator. -This procedure resizes a memory region, specified by `old_data`, to have a size -`size` and alignment `alignment`. The newly allocated memory, if any is not +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `scratch_alloc()`, @@ -678,17 +742,24 @@ scratch_resize_bytes_non_zeroed :: proc( if s.data == nil { DEFAULT_BACKING_SIZE :: 4 * Megabyte if !(context.allocator.procedure != scratch_allocator_proc && context.allocator.data != s) { - panic("cyclic initialization of the scratch allocator with itself", loc) + panic("Cyclic initialization of the scratch allocator with itself.", loc) } scratch_init(s, DEFAULT_BACKING_SIZE) } begin := uintptr(raw_data(s.data)) end := begin + uintptr(len(s.data)) old_ptr := uintptr(old_memory) - if begin <= old_ptr && old_ptr < end && old_ptr+uintptr(size) < end { + // We can only sanely resize the last allocation; to do otherwise may + // overwrite memory that could very well just have been allocated. + // + // Also, the alignments must match, otherwise we must re-allocate to + // guarantee the user's request. + if s.prev_allocation == old_memory && is_aligned(old_memory, alignment) && old_ptr+uintptr(size) < end { + // ensure_not_poisoned(old_data) + // sanitizer.address_poison(old_memory) s.curr_offset = int(old_ptr-begin)+size result := byte_slice(old_memory, size) - sanitizer.address_unpoison(result) + // sanitizer.address_unpoison(result) return result, nil } data, err := scratch_alloc_bytes_non_zeroed(s, size, alignment, loc) @@ -780,7 +851,7 @@ stack_allocator :: proc(stack: ^Stack) -> Allocator { } /* -Initialize the stack allocator. +Initialize a stack allocator. This procedure initializes the stack allocator with a backing buffer specified by `data` parameter. @@ -790,11 +861,11 @@ stack_init :: proc(s: ^Stack, data: []byte) { s.prev_offset = 0 s.curr_offset = 0 s.peak_used = 0 - sanitizer.address_poison(data) + // sanitizer.address_poison(data) } /* -Allocate memory from stack. +Allocate memory from a stack allocator. This procedure allocates `size` bytes of memory, aligned to the boundary specified by `alignment`. The allocated memory is zero-initialized. This @@ -812,7 +883,7 @@ stack_alloc :: proc( } /* -Allocate memory from stack. +Allocate memory from a stack allocator. This procedure allocates `size` bytes of memory, aligned to the boundary specified by `alignment`. The allocated memory is zero-initialized. This @@ -833,7 +904,7 @@ stack_alloc_bytes :: proc( } /* -Allocate memory from stack. +Allocate memory from a stack allocator. This procedure allocates `size` bytes of memory, aligned to the boundary specified by `alignment`. The allocated memory is not explicitly @@ -851,13 +922,13 @@ stack_alloc_non_zeroed :: proc( } /* -Allocate memory from stack. +Allocate memory from a stack allocator. This procedure allocates `size` bytes of memory, aligned to the boundary specified by `alignment`. The allocated memory is not explicitly zero-initialized. This procedure returns the slice of the allocated memory. */ -@(require_results) +@(require_results, no_sanitize_address) stack_alloc_bytes_non_zeroed :: proc( s: ^Stack, size: int, @@ -865,7 +936,7 @@ stack_alloc_bytes_non_zeroed :: proc( loc := #caller_location ) -> ([]byte, Allocator_Error) { if s.data == nil { - panic("Stack allocation on an uninitialized stack allocator", loc) + panic("Allocation on an uninitialized Stack allocator.", loc) } curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset) padding := calc_padding_with_header( @@ -881,21 +952,21 @@ stack_alloc_bytes_non_zeroed :: proc( s.curr_offset += padding next_addr := curr_addr + uintptr(padding) header := (^Stack_Allocation_Header)(next_addr - size_of(Stack_Allocation_Header)) - sanitizer.address_unpoison(header) header.padding = padding header.prev_offset = old_offset s.curr_offset += size s.peak_used = max(s.peak_used, s.curr_offset) result := byte_slice(rawptr(next_addr), size) - sanitizer.address_unpoison(result) + // ensure_poisoned(result) + // sanitizer.address_unpoison(result) return result, nil } /* -Free memory to the stack. +Free memory back to the stack allocator. This procedure frees the memory region starting at `old_memory` to the stack. -If the freeing does is an out of order freeing, the `.Invalid_Pointer` error +If the freeing is an out of order freeing, the `.Invalid_Pointer` error is returned. */ stack_free :: proc( @@ -904,7 +975,7 @@ stack_free :: proc( loc := #caller_location, ) -> (Allocator_Error) { if s.data == nil { - panic("Stack free on an uninitialized stack allocator", loc) + panic("Free on an uninitialized Stack allocator.", loc) } if old_memory == nil { return nil @@ -913,7 +984,7 @@ stack_free :: proc( end := start + uintptr(len(s.data)) curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - panic("Out of bounds memory address passed to stack allocator (free)", loc) + panic("Out of bounds memory address passed to Stack allocator. (free)", loc) } if curr_addr >= start+uintptr(s.curr_offset) { // NOTE(bill): Allow double frees @@ -922,32 +993,31 @@ stack_free :: proc( header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)) old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) if old_offset != s.prev_offset { - // panic("Out of order stack allocator free"); return .Invalid_Pointer } s.prev_offset = header.prev_offset - sanitizer.address_poison(s.data[old_offset:s.curr_offset]) + // sanitizer.address_poison(s.data[old_offset:s.curr_offset]) s.curr_offset = old_offset return nil } /* -Free all allocations to the stack. +Free all memory back to the stack allocator. */ stack_free_all :: proc(s: ^Stack, loc := #caller_location) { s.prev_offset = 0 s.curr_offset = 0 - sanitizer.address_poison(s.data) + // sanitizer.address_poison(s.data) } /* -Resize an allocation. +Resize an allocation owned by a stack allocator. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -972,11 +1042,11 @@ stack_resize :: proc( } /* -Resize an allocation. +Resize an allocation owned by a stack allocator. -This procedure resizes a memory region, specified by the `old_data` parameter -to have a size `size` and alignment `alignment`. The newly allocated memory, -if any is zero-initialized. +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is +zero-initialized. If `old_memory` is `nil`, this procedure acts just like `stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -995,8 +1065,8 @@ stack_resize_bytes :: proc( alignment := DEFAULT_ALIGNMENT, loc := #caller_location, ) -> ([]byte, Allocator_Error) { - bytes, err := stack_alloc_bytes_non_zeroed(s, size, alignment, loc) - if bytes != nil { + bytes, err := stack_resize_bytes_non_zeroed(s, old_data, size, alignment, loc) + if err == nil { if old_data == nil { zero_slice(bytes) } else if size > len(old_data) { @@ -1007,11 +1077,11 @@ stack_resize_bytes :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a stack allocator, without zero-initialization. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is not explicitly zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1036,11 +1106,11 @@ stack_resize_non_zeroed :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a stack allocator, without zero-initialization. -This procedure resizes a memory region, specified by the `old_data` parameter -to have a size `size` and alignment `alignment`. The newly allocated memory, -if any is not explicitly zero-initialized. +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is not +explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1062,24 +1132,34 @@ stack_resize_bytes_non_zeroed :: proc( old_memory := raw_data(old_data) old_size := len(old_data) if s.data == nil { - panic("Stack free all on an uninitialized stack allocator", loc) + panic("Resize on an uninitialized Stack allocator.", loc) } if old_memory == nil { return stack_alloc_bytes_non_zeroed(s, size, alignment, loc) } if size == 0 { - return nil, nil + return nil, stack_free(s, old_memory, loc) } start := uintptr(raw_data(s.data)) end := start + uintptr(len(s.data)) curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - panic("Out of bounds memory address passed to stack allocator (resize)") + panic("Out of bounds memory address passed to Stack allocator. (resize)") } if curr_addr >= start+uintptr(s.curr_offset) { // NOTE(bill): Allow double frees return nil, nil } + if uintptr(old_memory) & uintptr(alignment-1) != 0 { + // A different alignment has been requested and the current address + // does not satisfy it. + data, err := stack_alloc_bytes_non_zeroed(s, size, alignment, loc) + if err == nil { + runtime.copy(data, byte_slice(old_memory, old_size)) + // sanitizer.address_poison(old_memory) + } + return data, err + } if old_size == size { return byte_slice(old_memory, size), nil } @@ -1089,6 +1169,7 @@ stack_resize_bytes_non_zeroed :: proc( data, err := stack_alloc_bytes_non_zeroed(s, size, alignment, loc) if err == nil { runtime.copy(data, byte_slice(old_memory, old_size)) + // sanitizer.address_poison(old_memory) } return data, err } @@ -1098,9 +1179,12 @@ stack_resize_bytes_non_zeroed :: proc( s.curr_offset += diff // works for smaller sizes too if diff > 0 { zero(rawptr(curr_addr + uintptr(diff)), diff) + } else { + // sanitizer.address_poison(old_data[size:]) } result := byte_slice(old_memory, size) - sanitizer.address_unpoison(result) + // ensure_poisoned(result) + // sanitizer.address_unpoison(result) return result, nil } @@ -1160,7 +1244,7 @@ Small_Stack :: struct { } /* -Initialize small stack. +Initialize a small stack allocator. This procedure initializes the small stack allocator with `data` as its backing buffer. @@ -1169,15 +1253,18 @@ small_stack_init :: proc(s: ^Small_Stack, data: []byte) { s.data = data s.offset = 0 s.peak_used = 0 - sanitizer.address_poison(data) + // sanitizer.address_poison(data) } /* Small stack allocator. -The small stack allocator is just like a stack allocator, with the only +The small stack allocator is just like a `Stack` allocator, with the only difference being an extremely small header size. Unlike the stack allocator, -small stack allows out-of order freeing of memory. +the small stack allows out-of order freeing of memory, with the stipulation +that all allocations made after the freed allocation will become invalidated +upon following allocations as they will begin to overwrite the memory formerly +used by the freed allocation. The memory is allocated in the backing buffer linearly, from start to end. Each subsequent allocation will get the next adjacent memory region. @@ -1195,7 +1282,7 @@ small_stack_allocator :: proc(stack: ^Small_Stack) -> Allocator { } /* -Allocate memory from small stack. +Allocate memory from a small stack allocator. This procedure allocates `size` bytes of memory aligned to a boundary specified by `alignment`. The allocated memory is zero-initialized. This procedure @@ -1213,7 +1300,7 @@ small_stack_alloc :: proc( } /* -Allocate memory from small stack. +Allocate memory from a small stack allocator. This procedure allocates `size` bytes of memory aligned to a boundary specified by `alignment`. The allocated memory is zero-initialized. This procedure @@ -1234,7 +1321,7 @@ small_stack_alloc_bytes :: proc( } /* -Allocate memory from small stack. +Allocate memory from a small stack allocator. This procedure allocates `size` bytes of memory aligned to a boundary specified by `alignment`. The allocated memory is not explicitly zero-initialized. This @@ -1252,13 +1339,13 @@ small_stack_alloc_non_zeroed :: proc( } /* -Allocate memory from small stack. +Allocate memory from a small stack allocator. This procedure allocates `size` bytes of memory aligned to a boundary specified by `alignment`. The allocated memory is not explicitly zero-initialized. This procedure returns a slice of the allocated memory region. */ -@(require_results) +@(require_results, no_sanitize_address) small_stack_alloc_bytes_non_zeroed :: proc( s: ^Small_Stack, size: int, @@ -1266,7 +1353,7 @@ small_stack_alloc_bytes_non_zeroed :: proc( loc := #caller_location, ) -> ([]byte, Allocator_Error) { if s.data == nil { - panic("Small stack is not initialized", loc) + panic("Allocation on an uninitialized Small Stack allocator.", loc) } alignment := alignment alignment = clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2) @@ -1278,17 +1365,21 @@ small_stack_alloc_bytes_non_zeroed :: proc( s.offset += padding next_addr := curr_addr + uintptr(padding) header := (^Small_Stack_Allocation_Header)(next_addr - size_of(Small_Stack_Allocation_Header)) - sanitizer.address_unpoison(header) - header.padding = auto_cast padding + header.padding = cast(u8)padding + // We must poison the header, no matter what its state is, because there + // may have been an out-of-order free before this point. + // sanitizer.address_poison(header) s.offset += size s.peak_used = max(s.peak_used, s.offset) result := byte_slice(rawptr(next_addr), size) - sanitizer.address_unpoison(result) + // NOTE: We cannot ensure the poison state of this allocation, because this + // allocator allows out-of-order frees with overwriting. + // sanitizer.address_unpoison(result) return result, nil } /* -Allocate memory from small stack. +Allocate memory from a small stack allocator. This procedure allocates `size` bytes of memory aligned to a boundary specified by `alignment`. The allocated memory is not explicitly zero-initialized. This @@ -1300,7 +1391,7 @@ small_stack_free :: proc( loc := #caller_location, ) -> Allocator_Error { if s.data == nil { - panic("Small stack is not initialized", loc) + panic("Free on an uninitialized Small Stack allocator.", loc) } if old_memory == nil { return nil @@ -1309,8 +1400,7 @@ small_stack_free :: proc( end := start + uintptr(len(s.data)) curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - // panic("Out of bounds memory address passed to stack allocator (free)"); - return .Invalid_Pointer + panic("Out of bounds memory address passed to Small Stack allocator. (free)", loc) } if curr_addr >= start+uintptr(s.offset) { // NOTE(bill): Allow double frees @@ -1318,25 +1408,25 @@ small_stack_free :: proc( } header := (^Small_Stack_Allocation_Header)(curr_addr - size_of(Small_Stack_Allocation_Header)) old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))) - sanitizer.address_poison(s.data[old_offset:s.offset]) + // sanitizer.address_poison(s.data[old_offset:s.offset]) s.offset = old_offset return nil } /* -Free all memory to small stack. +Free all memory back to the small stack allocator. */ small_stack_free_all :: proc(s: ^Small_Stack) { s.offset = 0 - sanitizer.address_poison(s.data) + // sanitizer.address_poison(s.data) } /* -Resize an allocation. +Resize an allocation owned by a small stack allocator. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `small_stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1361,11 +1451,11 @@ small_stack_resize :: proc( } /* -Resize an allocation. +Resize an allocation owned by a small stack allocator. -This procedure resizes a memory region, specified by the `old_data` parameter -to have a size `size` and alignment `alignment`. The newly allocated memory, -if any is zero-initialized. +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is +zero-initialized. If `old_memory` is `nil`, this procedure acts just like `small_stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1396,11 +1486,11 @@ small_stack_resize_bytes :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a small stack allocator, without zero-initialization. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is not explicitly zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `small_stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1425,11 +1515,11 @@ small_stack_resize_non_zeroed :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a small stack allocator, without zero-initialization. -This procedure resizes a memory region, specified by the `old_data` parameter -to have a size `size` and alignment `alignment`. The newly allocated memory, -if any is not explicitly zero-initialized. +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is not +explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `small_stack_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified @@ -1449,7 +1539,7 @@ small_stack_resize_bytes_non_zeroed :: proc( loc := #caller_location, ) -> ([]byte, Allocator_Error) { if s.data == nil { - panic("Small stack is not initialized", loc) + panic("Resize on an uninitialized Small Stack allocator.", loc) } old_memory := raw_data(old_data) old_size := len(old_data) @@ -1459,22 +1549,31 @@ small_stack_resize_bytes_non_zeroed :: proc( return small_stack_alloc_bytes_non_zeroed(s, size, alignment, loc) } if size == 0 { - return nil, nil + return nil, small_stack_free(s, old_memory, loc) } start := uintptr(raw_data(s.data)) end := start + uintptr(len(s.data)) curr_addr := uintptr(old_memory) if !(start <= curr_addr && curr_addr < end) { - // panic("Out of bounds memory address passed to stack allocator (resize)"); - return nil, .Invalid_Pointer + panic("Out of bounds memory address passed to Small Stack allocator. (resize)", loc) } if curr_addr >= start+uintptr(s.offset) { // NOTE(bill): Treat as a double free return nil, nil } + if uintptr(old_memory) & uintptr(alignment-1) != 0 { + // A different alignment has been requested and the current address + // does not satisfy it. + data, err := small_stack_alloc_bytes_non_zeroed(s, size, alignment, loc) + if err == nil { + runtime.copy(data, byte_slice(old_memory, old_size)) + // sanitizer.address_poison(old_memory) + } + return data, err + } if old_size == size { result := byte_slice(old_memory, size) - sanitizer.address_unpoison(result) + // sanitizer.address_unpoison(result) return result, nil } data, err := small_stack_alloc_bytes_non_zeroed(s, size, alignment, loc) @@ -1522,20 +1621,6 @@ small_stack_allocator_proc :: proc( return nil, nil } - -/* Preserved for compatibility */ -Dynamic_Pool :: Dynamic_Arena -DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT -DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT -dynamic_pool_allocator_proc :: dynamic_arena_allocator_proc -dynamic_pool_free_all :: dynamic_arena_free_all -dynamic_pool_reset :: dynamic_arena_reset -dynamic_pool_alloc_bytes :: dynamic_arena_alloc_bytes -dynamic_pool_alloc :: dynamic_arena_alloc -dynamic_pool_init :: dynamic_arena_init -dynamic_pool_allocator :: dynamic_arena_allocator -dynamic_pool_destroy :: dynamic_arena_destroy - /* Default block size for dynamic arena. */ @@ -1552,7 +1637,7 @@ Dynamic arena allocator data. Dynamic_Arena :: struct { block_size: int, out_band_size: int, - alignment: int, + minimum_alignment: int, unused_blocks: [dynamic]rawptr, used_blocks: [dynamic]rawptr, out_band_allocations: [dynamic]rawptr, @@ -1569,41 +1654,41 @@ This procedure initializes a dynamic arena. The specified `block_allocator` will be used to allocate arena blocks, and `array_allocator` to allocate arrays of blocks and out-band blocks. The blocks have the default size of `block_size` and out-band threshold will be `out_band_size`. All allocations -will be aligned to a boundary specified by `alignment`. +will be aligned at a minimum to a boundary specified by `minimum_alignment`. */ dynamic_arena_init :: proc( - pool: ^Dynamic_Arena, - block_allocator := context.allocator, - array_allocator := context.allocator, - block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT, - out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT, - alignment := DEFAULT_ALIGNMENT, + arena: ^Dynamic_Arena, + block_allocator := context.allocator, + array_allocator := context.allocator, + block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT, + out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT, + minimum_alignment := DEFAULT_ALIGNMENT, ) { - pool.block_size = block_size - pool.out_band_size = out_band_size - pool.alignment = alignment - pool.block_allocator = block_allocator - pool.out_band_allocations.allocator = array_allocator - pool.unused_blocks.allocator = array_allocator - pool.used_blocks.allocator = array_allocator + arena.block_size = block_size + arena.out_band_size = out_band_size + arena.minimum_alignment = minimum_alignment + arena.block_allocator = block_allocator + arena.out_band_allocations.allocator = array_allocator + arena.unused_blocks.allocator = array_allocator + arena.used_blocks.allocator = array_allocator } /* Dynamic arena allocator. The dynamic arena allocator uses blocks of a specific size, allocated on-demand -using the block allocator. This allocator acts similarly to arena. All +using the block allocator. This allocator acts similarly to `Arena`. All allocations in a block happen contiguously, from start to end. If an allocation -does not fit into the remaining space of the block, and its size is smaller +does not fit into the remaining space of the block and its size is smaller than the specified out-band size, a new block is allocated using the `block_allocator` and the allocation is performed from a newly-allocated block. -If an allocation has bigger size than the specified out-band size, a new block +If an allocation is larger than the specified out-band size, a new block is allocated such that the allocation fits into this new block. This is referred to as an *out-band allocation*. The out-band blocks are kept separately from normal blocks. -Just like arena, the dynamic arena does not support freeing of individual +Just like `Arena`, the dynamic arena does not support freeing of individual objects. */ @(require_results) @@ -1617,7 +1702,7 @@ dynamic_arena_allocator :: proc(a: ^Dynamic_Arena) -> Allocator { /* Destroy a dynamic arena. -This procedure frees all allocations, made on a dynamic arena, including the +This procedure frees all allocations made on a dynamic arena, including the unused blocks, as well as the arrays for storing blocks. */ dynamic_arena_destroy :: proc(a: ^Dynamic_Arena) { @@ -1629,9 +1714,9 @@ dynamic_arena_destroy :: proc(a: ^Dynamic_Arena) { } @(private="file") -_dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, loc := #caller_location) -> (err: Allocator_Error) { +_dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, alignment: int, loc := #caller_location) -> (err: Allocator_Error) { if a.block_allocator.procedure == nil { - panic("You must call arena_init on a Pool before using it", loc) + panic("You must call `dynamic_arena_init` on a Dynamic Arena before using it.", loc) } if a.current_block != nil { append(&a.used_blocks, a.current_block, loc=loc) @@ -1645,10 +1730,11 @@ _dynamic_arena_cycle_new_block :: proc(a: ^Dynamic_Arena, loc := #caller_locatio a.block_allocator.data, Allocator_Mode.Alloc, a.block_size, - a.alignment, + max(a.minimum_alignment, alignment), nil, 0, ) + // sanitizer.address_poison(data) new_block = raw_data(data) } a.bytes_left = a.block_size @@ -1665,9 +1751,9 @@ by `alignment` from a dynamic arena `a`. The allocated memory is zero-initialized. This procedure returns a pointer to the newly allocated memory region. */ -@(private, require_results) -dynamic_arena_alloc :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> (rawptr, Allocator_Error) { - data, err := dynamic_arena_alloc_bytes(a, size, loc) +@(require_results) +dynamic_arena_alloc :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> (rawptr, Allocator_Error) { + data, err := dynamic_arena_alloc_bytes(a, size, alignment, loc) return raw_data(data), err } @@ -1680,8 +1766,8 @@ zero-initialized. This procedure returns a slice of the newly allocated memory region. */ @(require_results) -dynamic_arena_alloc_bytes :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - bytes, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc) +dynamic_arena_alloc_bytes :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> ([]byte, Allocator_Error) { + bytes, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc) if bytes != nil { zero_slice(bytes) } @@ -1697,8 +1783,8 @@ zero-initialized. This procedure returns a pointer to the newly allocated memory region. */ @(require_results) -dynamic_arena_alloc_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> (rawptr, Allocator_Error) { - data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc) +dynamic_arena_alloc_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> (rawptr, Allocator_Error) { + data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc) return raw_data(data), err } @@ -1711,84 +1797,91 @@ zero-initialized. This procedure returns a slice of the newly allocated memory region. */ @(require_results) -dynamic_arena_alloc_bytes_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - n := align_formula(size, a.alignment) - if n > a.block_size { - return nil, .Invalid_Argument - } - if n >= a.out_band_size { - assert(a.block_allocator.procedure != nil, "Backing block allocator must be initialized", loc=loc) - memory, err := alloc_bytes_non_zeroed(a.block_size, a.alignment, a.block_allocator, loc) +dynamic_arena_alloc_bytes_non_zeroed :: proc(a: ^Dynamic_Arena, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> ([]byte, Allocator_Error) { + if size >= a.out_band_size { + assert(a.out_band_allocations.allocator.procedure != nil, "Backing array allocator must be initialized", loc=loc) + memory, err := alloc_bytes_non_zeroed(size, alignment, a.out_band_allocations.allocator, loc) if memory != nil { append(&a.out_band_allocations, raw_data(memory), loc = loc) } return memory, err } - if a.bytes_left < n { - err := _dynamic_arena_cycle_new_block(a, loc) + actual_alignment := max(a.minimum_alignment, alignment) + n := align_formula(size, actual_alignment) + if n > a.block_size { + return nil, .Invalid_Argument + } + memory := align_forward(a.current_pos, uintptr(actual_alignment)) + margin := int(uintptr(memory) - uintptr(a.current_pos)) + if a.bytes_left < margin + n { + err := _dynamic_arena_cycle_new_block(a, alignment, loc) if err != nil { return nil, err } if a.current_block == nil { return nil, .Out_Of_Memory } + margin = 0 + memory = a.current_pos } - memory := a.current_pos - a.current_pos = ([^]byte)(a.current_pos)[n:] - a.bytes_left -= n - return ([^]byte)(memory)[:size], nil + a.current_pos = ([^]byte)(memory)[n:] + a.bytes_left -= margin + n + result := ([^]byte)(memory)[:size] + // ensure_poisoned(result) + // sanitizer.address_unpoison(result) + return result, nil } /* -Reset the dynamic arena. +Reset a dynamic arena allocator. -This procedure frees all the allocations, owned by the dynamic arena, excluding +This procedure frees all the allocations owned by the dynamic arena, excluding the unused blocks. */ dynamic_arena_reset :: proc(a: ^Dynamic_Arena, loc := #caller_location) { if a.current_block != nil { + // sanitizer.address_poison(a.current_block, a.block_size) append(&a.unused_blocks, a.current_block, loc=loc) a.current_block = nil } for block in a.used_blocks { + // sanitizer.address_poison(block, a.block_size) append(&a.unused_blocks, block, loc=loc) } clear(&a.used_blocks) for allocation in a.out_band_allocations { - free(allocation, a.block_allocator, loc=loc) + free(allocation, a.out_band_allocations.allocator, loc=loc) } clear(&a.out_band_allocations) a.bytes_left = 0 // Make new allocations call `_dynamic_arena_cycle_new_block` again. } /* -Free all memory from a dynamic arena. +Free all memory back to the dynamic arena allocator. -This procedure frees all the allocations, owned by the dynamic arena, including +This procedure frees all the allocations owned by the dynamic arena, including the unused blocks. */ dynamic_arena_free_all :: proc(a: ^Dynamic_Arena, loc := #caller_location) { dynamic_arena_reset(a) for block in a.unused_blocks { + // sanitizer.address_unpoison(block, a.block_size) free(block, a.block_allocator, loc) } clear(&a.unused_blocks) } /* -Resize an allocation. +Resize an allocation owned by a dynamic arena allocator. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `dynamic_arena_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified by `alignment`. -If `size` is 0, this procedure acts just like `dynamic_arena_free()`, freeing -the memory region located at an address specified by `old_memory`. - This procedure returns the pointer to the resized memory region. */ @(require_results) @@ -1797,36 +1890,39 @@ dynamic_arena_resize :: proc( old_memory: rawptr, old_size: int, size: int, + alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location, ) -> (rawptr, Allocator_Error) { - bytes, err := dynamic_arena_resize_bytes(a, byte_slice(old_memory, old_size), size, loc) + bytes, err := dynamic_arena_resize_bytes(a, byte_slice(old_memory, old_size), size, alignment, loc) return raw_data(bytes), err } /* -Resize an allocation. +Resize an allocation owned by a dynamic arena allocator. -This procedure resizes a memory region, specified by `old_data`, to have a size -`size` and alignment `alignment`. The newly allocated memory, if any is +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is zero-initialized. If `old_memory` is `nil`, this procedure acts just like `dynamic_arena_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified by `alignment`. -If `size` is 0, this procedure acts just like `dynamic_arena_free()`, freeing the -memory region located at an address specified by `old_memory`. - This procedure returns the slice of the resized memory region. */ @(require_results) dynamic_arena_resize_bytes :: proc( - a: ^Dynamic_Arena, - old_data: []byte, - size: int, + a: ^Dynamic_Arena, + old_data: []byte, + size: int, + alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location, ) -> ([]byte, Allocator_Error) { - bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, old_data, size, loc) + if size == 0 { + // NOTE: This allocator has no Free mode. + return nil, nil + } + bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, old_data, size, alignment, loc) if bytes != nil { if old_data == nil { zero_slice(bytes) @@ -1838,19 +1934,16 @@ dynamic_arena_resize_bytes :: proc( } /* -Resize an allocation without zero-initialization. +Resize an allocation owned by a dynamic arena allocator, without zero-initialization. -This procedure resizes a memory region, defined by its location, `old_memory`, -and its size, `old_size` to have a size `size` and alignment `alignment`. The -newly allocated memory, if any is not explicitly zero-initialized. +This procedure resizes a memory region defined by its location `old_memory` +and its size `old_size` to have a size `size` and alignment `alignment`. The +newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `dynamic_arena_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified by `alignment`. -If `size` is 0, this procedure acts just like `dynamic_arena_free()`, freeing the -memory region located at an address specified by `old_memory`. - This procedure returns the pointer to the resized memory region. */ @(require_results) @@ -1859,41 +1952,47 @@ dynamic_arena_resize_non_zeroed :: proc( old_memory: rawptr, old_size: int, size: int, + alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location, ) -> (rawptr, Allocator_Error) { - bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, byte_slice(old_memory, old_size), size, loc) + bytes, err := dynamic_arena_resize_bytes_non_zeroed(a, byte_slice(old_memory, old_size), size, alignment, loc) return raw_data(bytes), err } /* -Resize an allocation. +Resize an allocation owned by a dynamic arena allocator, without zero-initialization. -This procedure resizes a memory region, specified by `old_data`, to have a size -`size` and alignment `alignment`. The newly allocated memory, if any is not +This procedure resizes a memory region specified by `old_data` to have a size +`size` and alignment `alignment`. The newly allocated memory, if any, is not explicitly zero-initialized. If `old_memory` is `nil`, this procedure acts just like `dynamic_arena_alloc()`, allocating a memory region `size` bytes in size, aligned on a boundary specified by `alignment`. -If `size` is 0, this procedure acts just like `dynamic_arena_free()`, freeing -the memory region located at an address specified by `old_memory`. - This procedure returns the slice of the resized memory region. */ @(require_results) dynamic_arena_resize_bytes_non_zeroed :: proc( - a: ^Dynamic_Arena, - old_data: []byte, - size: int, + a: ^Dynamic_Arena, + old_data: []byte, + size: int, + alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location, ) -> ([]byte, Allocator_Error) { + if size == 0 { + // NOTE: This allocator has no Free mode. + return nil, nil + } old_memory := raw_data(old_data) old_size := len(old_data) if old_size >= size { + // sanitizer.address_poison(old_data[size:]) return byte_slice(old_memory, size), nil } - data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, loc) + // No information is kept about allocations in this allocator, thus we + // cannot truly resize anything and must reallocate. + data, err := dynamic_arena_alloc_bytes_non_zeroed(a, size, alignment, loc) if err == nil { runtime.copy(data, byte_slice(old_memory, old_size)) } @@ -1912,17 +2011,17 @@ dynamic_arena_allocator_proc :: proc( arena := (^Dynamic_Arena)(allocator_data) switch mode { case .Alloc: - return dynamic_arena_alloc_bytes(arena, size, loc) + return dynamic_arena_alloc_bytes(arena, size, alignment, loc) case .Alloc_Non_Zeroed: - return dynamic_arena_alloc_bytes_non_zeroed(arena, size, loc) + return dynamic_arena_alloc_bytes_non_zeroed(arena, size, alignment, loc) case .Free: return nil, .Mode_Not_Implemented case .Free_All: dynamic_arena_free_all(arena, loc) case .Resize: - return dynamic_arena_resize_bytes(arena, byte_slice(old_memory, old_size), size, loc) + return dynamic_arena_resize_bytes(arena, byte_slice(old_memory, old_size), size, alignment, loc) case .Resize_Non_Zeroed: - return dynamic_arena_resize_bytes_non_zeroed(arena, byte_slice(old_memory, old_size), size, loc) + return dynamic_arena_resize_bytes_non_zeroed(arena, byte_slice(old_memory, old_size), size, alignment, loc) case .Query_Features: set := (^Allocator_Mode_Set)(old_memory) if set != nil { @@ -1933,7 +2032,7 @@ dynamic_arena_allocator_proc :: proc( info := (^Allocator_Query_Info)(old_memory) if info != nil && info.pointer != nil { info.size = arena.block_size - info.alignment = arena.alignment + info.alignment = arena.minimum_alignment return byte_slice(info, size_of(info^)), nil } return nil, nil @@ -1953,7 +2052,7 @@ Buddy_Block :: struct #align(align_of(uint)) { /* Obtain the next buddy block. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_block_next :: proc(block: ^Buddy_Block) -> ^Buddy_Block { return (^Buddy_Block)(([^]byte)(block)[block.size:]) } @@ -1961,7 +2060,7 @@ buddy_block_next :: proc(block: ^Buddy_Block) -> ^Buddy_Block { /* Split the block into two, by truncating the given block to a given size. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_block_split :: proc(block: ^Buddy_Block, size: uint) -> ^Buddy_Block { block := block if block != nil && size != 0 { @@ -1984,6 +2083,7 @@ buddy_block_split :: proc(block: ^Buddy_Block, size: uint) -> ^Buddy_Block { /* Coalesce contiguous blocks in a range of blocks into one. */ +@(no_sanitize_address) buddy_block_coalescence :: proc(head, tail: ^Buddy_Block) { for { // Keep looping until there are no more buddies to coalesce @@ -2020,7 +2120,7 @@ buddy_block_coalescence :: proc(head, tail: ^Buddy_Block) { /* Find the best block for storing a given size in a range of blocks. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_block_find_best :: proc(head, tail: ^Buddy_Block, size: uint) -> ^Buddy_Block { assert(size != 0) best_block: ^Buddy_Block @@ -2083,7 +2183,7 @@ The buddy allocator data. */ Buddy_Allocator :: struct { head: ^Buddy_Block, - tail: ^Buddy_Block, + tail: ^Buddy_Block `fmt:"-"`, alignment: uint, } @@ -2106,10 +2206,13 @@ buddy_allocator :: proc(b: ^Buddy_Allocator) -> Allocator { } /* -Initialize the buddy allocator. +Initialize a buddy allocator. This procedure initializes the buddy allocator `b` with a backing buffer `data` and block alignment specified by `alignment`. + +`alignment` may be any power of two, but the backing buffer must be aligned to +at least `size_of(Buddy_Block)`. */ buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint, loc := #caller_location) { assert(data != nil) @@ -2120,12 +2223,14 @@ buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint, alignment = size_of(Buddy_Block) } ptr := raw_data(data) - assert(uintptr(ptr) % uintptr(alignment) == 0, "data is not aligned to minimum alignment", loc) + assert(uintptr(ptr) % uintptr(alignment) == 0, "The data is not aligned to the minimum alignment, which must be at least `size_of(Buddy_Block)`.", loc) b.head = (^Buddy_Block)(ptr) b.head.size = len(data) b.head.is_free = true b.tail = buddy_block_next(b.head) b.alignment = alignment + assert(uint(len(data)) >= 2 * buddy_block_size_required(b, 1), "The size of the backing buffer must be large enough to hold at least two 1-byte allocations given the alignment requirements, otherwise it cannot split.", loc) + // sanitizer.address_poison(data) } /* @@ -2133,12 +2238,14 @@ Get required block size to fit in the allocation as well as the alignment paddin */ @(require_results) buddy_block_size_required :: proc(b: ^Buddy_Allocator, size: uint) -> uint { - size := size - actual_size := b.alignment - size += size_of(Buddy_Block) - size = align_forward_uint(size, b.alignment) - for size > actual_size { - actual_size <<= 1 + assert(size > 0) + // NOTE: `size_of(Buddy_Block)` will be accounted for in `b.alignment`. + // This calculation is also previously guarded against being given a `size` + // 0 by `buddy_allocator_alloc_bytes_non_zeroed` checking for that. + actual_size := b.alignment + size + if intrinsics.count_ones(actual_size) != 1 { + // We're not a power of two. Let's fix that. + actual_size = 1 << (size_of(uint) * 8 - intrinsics.count_leading_zeros(actual_size)) } return actual_size } @@ -2146,11 +2253,12 @@ buddy_block_size_required :: proc(b: ^Buddy_Allocator, size: uint) -> uint { /* Allocate memory from a buddy allocator. -This procedure allocates `size` bytes of memory aligned on a boundary specified -by `alignment`. The allocated memory region is zero-initialized. This procedure -returns a pointer to the allocated memory region. +This procedure allocates `size` bytes of memory. The allocation's alignment is +fixed to the `alignment` specified at initialization. The allocated memory +region is zero-initialized. This procedure returns a pointer to the allocated +memory region. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_allocator_alloc :: proc(b: ^Buddy_Allocator, size: uint) -> (rawptr, Allocator_Error) { bytes, err := buddy_allocator_alloc_bytes(b, size) return raw_data(bytes), err @@ -2159,11 +2267,12 @@ buddy_allocator_alloc :: proc(b: ^Buddy_Allocator, size: uint) -> (rawptr, Alloc /* Allocate memory from a buddy allocator. -This procedure allocates `size` bytes of memory aligned on a boundary specified -by `alignment`. The allocated memory region is zero-initialized. This procedure -returns a slice of the allocated memory region. +This procedure allocates `size` bytes of memory. The allocation's alignment is +fixed to the `alignment` specified at initialization. The allocated memory +region is zero-initialized. This procedure returns a slice of the allocated +memory region. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_allocator_alloc_bytes :: proc(b: ^Buddy_Allocator, size: uint) -> ([]byte, Allocator_Error) { bytes, err := buddy_allocator_alloc_bytes_non_zeroed(b, size) if bytes != nil { @@ -2175,11 +2284,12 @@ buddy_allocator_alloc_bytes :: proc(b: ^Buddy_Allocator, size: uint) -> ([]byte, /* Allocate non-initialized memory from a buddy allocator. -This procedure allocates `size` bytes of memory aligned on a boundary specified -by `alignment`. The allocated memory region is not explicitly zero-initialized. -This procedure returns a pointer to the allocated memory region. +This procedure allocates `size` bytes of memory. The allocation's alignment is +fixed to the `alignment` specified at initialization. The allocated memory +region is not explicitly zero-initialized. This procedure returns a pointer to +the allocated memory region. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_allocator_alloc_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint) -> (rawptr, Allocator_Error) { bytes, err := buddy_allocator_alloc_bytes_non_zeroed(b, size) return raw_data(bytes), err @@ -2188,16 +2298,17 @@ buddy_allocator_alloc_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint) -> (ra /* Allocate non-initialized memory from a buddy allocator. -This procedure allocates `size` bytes of memory aligned on a boundary specified -by `alignment`. The allocated memory region is not explicitly zero-initialized. -This procedure returns a slice of the allocated memory region. +This procedure allocates `size` bytes of memory. The allocation's alignment is +fixed to the `alignment` specified at initialization. The allocated memory +region is not explicitly zero-initialized. This procedure returns a slice of +the allocated memory region. */ -@(require_results) +@(require_results, no_sanitize_address) buddy_allocator_alloc_bytes_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint) -> ([]byte, Allocator_Error) { if size != 0 { actual_size := buddy_block_size_required(b, size) found := buddy_block_find_best(b.head, b.tail, actual_size) - if found != nil { + if found == nil { // Try to coalesce all the free buddy blocks and then search again buddy_block_coalescence(b.head, b.tail) found = buddy_block_find_best(b.head, b.tail, actual_size) @@ -2207,25 +2318,30 @@ buddy_allocator_alloc_bytes_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint) } found.is_free = false data := ([^]byte)(found)[b.alignment:][:size] + assert(cast(uintptr)raw_data(data)+cast(uintptr)(size-1) < cast(uintptr)buddy_block_next(found), "Buddy_Allocator has made an allocation which overlaps a block header.") + // ensure_poisoned(data) + // sanitizer.address_unpoison(data) return data, nil } return nil, nil } /* -Free memory to the buddy allocator. +Free memory back to the buddy allocator. This procedure frees the memory region allocated at pointer `ptr`. If `ptr` is not the latest allocation and is not a leaked allocation, this operation is a no-op. */ +@(no_sanitize_address) buddy_allocator_free :: proc(b: ^Buddy_Allocator, ptr: rawptr) -> Allocator_Error { if ptr != nil { if !(b.head <= ptr && ptr <= b.tail) { return .Invalid_Pointer } block := (^Buddy_Block)(([^]byte)(ptr)[-b.alignment:]) + // sanitizer.address_poison(ptr, block.size) block.is_free = true buddy_block_coalescence(b.head, b.tail) } @@ -2233,16 +2349,18 @@ buddy_allocator_free :: proc(b: ^Buddy_Allocator, ptr: rawptr) -> Allocator_Erro } /* -Free all memory to the buddy allocator. +Free all memory back to the buddy allocator. */ +@(no_sanitize_address) buddy_allocator_free_all :: proc(b: ^Buddy_Allocator) { alignment := b.alignment head := ([^]byte)(b.head) tail := ([^]byte)(b.tail) data := head[:ptr_sub(tail, head)] - buddy_allocator_init(b, data, alignment) + buddy_allocator_init(b, data, alignment) } +@(no_sanitize_address) buddy_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, @@ -2296,7 +2414,7 @@ buddy_allocator_proc :: proc( // on the old size to work. // // The overhead of this allocator is an extra max(alignment, size_of(Header)) bytes allocated for each allocation, these bytes are -// used to store the size and original pointer. +// used to store the size and alignment. Compat_Allocator :: struct { parent: Allocator, } @@ -2305,6 +2423,7 @@ compat_allocator_init :: proc(rra: ^Compat_Allocator, allocator := context.alloc rra.parent = allocator } +@(require_results) compat_allocator :: proc(rra: ^Compat_Allocator) -> Allocator { return Allocator{ data = rra, @@ -2316,51 +2435,87 @@ compat_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> (data: []byte, err: Allocator_Error) { - size, old_size := size, old_size - Header :: struct { - size: int, - ptr: rawptr, + size: int, + alignment: int, + } + + @(no_sanitize_address) + get_unpoisoned_header :: #force_inline proc(ptr: rawptr) -> Header { + header := ([^]Header)(ptr)[-1] + // a := max(header.alignment, size_of(Header)) + // sanitizer.address_unpoison(rawptr(uintptr(ptr)-uintptr(a)), a) + return header } rra := (^Compat_Allocator)(allocator_data) switch mode { case .Alloc, .Alloc_Non_Zeroed: - a := max(alignment, size_of(Header)) - size += a - assert(size >= 0, "overflow") + a := max(alignment, size_of(Header)) + req_size := size + a + assert(req_size >= 0, "overflow") - allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) or_return + allocation := rra.parent.procedure(rra.parent.data, mode, req_size, alignment, old_memory, old_size, location) or_return #no_bounds_check data = allocation[a:] ([^]Header)(raw_data(data))[-1] = { - size = size, - ptr = raw_data(allocation), + size = size, + alignment = alignment, } + + // sanitizer.address_poison(raw_data(allocation), a) return case .Free: - header := ([^]Header)(old_memory)[-1] - return rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location) + header := get_unpoisoned_header(old_memory) + a := max(header.alignment, size_of(Header)) + orig_ptr := rawptr(uintptr(old_memory)-uintptr(a)) + orig_size := header.size + a + + return rra.parent.procedure(rra.parent.data, mode, orig_size, header.alignment, orig_ptr, orig_size, location) case .Resize, .Resize_Non_Zeroed: - header := ([^]Header)(old_memory)[-1] + header := get_unpoisoned_header(old_memory) + orig_a := max(header.alignment, size_of(Header)) + orig_ptr := rawptr(uintptr(old_memory)-uintptr(orig_a)) + orig_size := header.size + orig_a - a := max(alignment, size_of(header)) - size += a + new_alignment := max(header.alignment, alignment) + + a := max(new_alignment, size_of(header)) + req_size := size + a assert(size >= 0, "overflow") - allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location) or_return + allocation := rra.parent.procedure(rra.parent.data, mode, req_size, new_alignment, orig_ptr, orig_size, location) or_return #no_bounds_check data = allocation[a:] ([^]Header)(raw_data(data))[-1] = { - size = size, - ptr = raw_data(allocation), + size = size, + alignment = new_alignment, + } + + // sanitizer.address_poison(raw_data(allocation), a) + return + + case .Free_All: + return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) + + case .Query_Info: + info := (^Allocator_Query_Info)(old_memory) + if info != nil && info.pointer != nil { + header := get_unpoisoned_header(info.pointer) + info.size = header.size + info.alignment = header.alignment } return - case .Free_All, .Query_Info, .Query_Features: - return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) + case .Query_Features: + data, err = rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) + if err != nil { + set := (^Allocator_Mode_Set)(old_memory) + set^ += {.Query_Info} + } + return case: unreachable() } diff --git a/core/mem/doc.odin b/core/mem/doc.odin index 580b08c96..657251902 100644 --- a/core/mem/doc.odin +++ b/core/mem/doc.odin @@ -1,6 +1,5 @@ /* -The `mem` package implements various allocators and provides utility procedures -for dealing with memory, pointers and slices. +Various allocators and provides helpers for dealing with memory, pointers and slices. The documentation below describes basic concepts, applicable to the `mem` package. diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 5789309f7..66da0f2d9 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -315,18 +315,38 @@ check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool { Offset a given pointer by a given amount. This procedure offsets the pointer `ptr` to an object of type `T`, by the amount -of bytes specified by `offset*size_of(T)`, and returns the pointer `ptr`. +of bytes specified by `offset * size_of(T)`, and returns the pointer `ptr`. **Note**: Prefer to use multipointer types, if possible. */ ptr_offset :: intrinsics.ptr_offset /* -Offset a given pointer by a given amount backwards. +Subtract two pointers of the same type, and return the number of `T` between them. -This procedure offsets the pointer `ptr` to an object of type `T`, by the amount -of bytes specified by `offset*size_of(T)` in the negative direction, and -returns the pointer `ptr`. +This procedure subtracts pointer `b` from pointer `a`, both of type `^T`, +and returns an integer count of the `T` between them. + +**Inputs** +- `a`: A pointer to a type T +- `b`: A pointer to a type T + +**Returns** +- `a` - `b` in items of T as an `int`. + +Example: + + import "core:mem" + import "core:fmt" + + ptr_sub_example :: proc() { + arr: [2]int + fmt.println(mem.ptr_sub(&arr[1], &arr[0])) + } + +Output: + + 1 */ ptr_sub :: intrinsics.ptr_sub @@ -447,13 +467,7 @@ Check whether a number is a power of two. This procedure checks whether a given pointer-sized unsigned integer contains a power-of-two value. */ -@(require_results) -is_power_of_two :: proc "contextless" (x: uintptr) -> bool { - if x <= 0 { - return false - } - return (x & (x-1)) == 0 -} +is_power_of_two :: runtime.is_power_of_two_uintptr /* Check if a pointer is aligned. @@ -477,11 +491,7 @@ bytes, `ptr` is returned. The specified alignment must be a power of 2. */ -@(require_results) -align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr { - assert(is_power_of_two(align)) - return (ptr + align-1) & ~(align-1) -} +align_forward_uintptr :: runtime.align_forward_uintptr /* Align pointer forward. @@ -506,10 +516,7 @@ bytes, `ptr` is returned. The specified alignment must be a power of 2. */ -@(require_results) -align_forward_int :: proc(ptr, align: int) -> int { - return int(align_forward_uintptr(uintptr(ptr), uintptr(align))) -} +align_forward_int :: runtime.align_forward_int /* Align uint forward. @@ -520,10 +527,7 @@ bytes, `ptr` is returned. The specified alignment must be a power of 2. */ -@(require_results) -align_forward_uint :: proc(ptr, align: uint) -> uint { - return uint(align_forward_uintptr(uintptr(ptr), uintptr(align))) -} +align_forward_uint :: runtime.align_forward_uint /* Align uintptr backwards. @@ -606,32 +610,6 @@ reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: T) { return } -/* -Dynamic array with a fixed capacity buffer. - -This type represents dynamic arrays with a fixed-size backing buffer. Upon -allocating memory beyond reaching the maximum capacity, allocations from fixed -byte buffers return `nil` and no error. -*/ -Fixed_Byte_Buffer :: distinct [dynamic]byte - -/* -Create a fixed byte buffer from a slice. -*/ -@(require_results) -make_fixed_byte_buffer :: proc "contextless" (backing: []byte) -> Fixed_Byte_Buffer { - s := transmute(Raw_Slice)backing - d: Raw_Dynamic_Array - d.data = s.data - d.len = 0 - d.cap = s.len - d.allocator = Allocator{ - procedure = nil_allocator_proc, - data = nil, - } - return transmute(Fixed_Byte_Buffer)d -} - /* General-purpose align formula. @@ -684,4 +662,4 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he } } return int(padding) -} \ No newline at end of file +} diff --git a/core/mem/mem_posix.odin b/core/mem/mem_posix.odin new file mode 100644 index 000000000..f652e6a25 --- /dev/null +++ b/core/mem/mem_posix.odin @@ -0,0 +1,13 @@ +#+build linux, darwin, netbsd, freebsd, openbsd +package mem + +import "core:sys/posix" + +@(init, private, no_sanitize_address) +query_page_size_init :: proc "contextless" () { + size := posix.sysconf(._PAGESIZE) + PAGE_SIZE = max(PAGE_SIZE, int(size)) + + // is power of two + assert_contextless(PAGE_SIZE != 0 && (PAGE_SIZE & (PAGE_SIZE-1)) == 0) +} \ No newline at end of file diff --git a/core/mem/mem_windows.odin b/core/mem/mem_windows.odin new file mode 100644 index 000000000..09f14d5d0 --- /dev/null +++ b/core/mem/mem_windows.odin @@ -0,0 +1,16 @@ +#+build windows +package mem + +import "core:sys/windows" + +@(init, private, no_sanitize_address) +query_page_size_init :: proc "contextless" () { + info: windows.SYSTEM_INFO + windows.GetSystemInfo(&info) + + size := info.dwPageSize + PAGE_SIZE = max(PAGE_SIZE, int(size)) + + // is power of two + assert_contextless(PAGE_SIZE != 0 && (PAGE_SIZE & (PAGE_SIZE-1)) == 0) +} \ No newline at end of file diff --git a/core/mem/raw.odin b/core/mem/raw.odin index 41c91555e..0a608db31 100644 --- a/core/mem/raw.odin +++ b/core/mem/raw.odin @@ -18,6 +18,17 @@ Memory layout of the `cstring` type. */ Raw_Cstring :: runtime.Raw_Cstring + +/* +Memory layout of the `string16` type. +*/ +Raw_String16 :: runtime.Raw_String16 + +/* +Memory layout of the `cstring16` type. +*/ +Raw_Cstring16 :: runtime.Raw_Cstring16 + /* Memory layout of `[]T` types. */ diff --git a/core/mem/rollback_stack_allocator.odin b/core/mem/rollback_stack_allocator.odin index a00131b7f..3c98135de 100644 --- a/core/mem/rollback_stack_allocator.odin +++ b/core/mem/rollback_stack_allocator.odin @@ -1,7 +1,7 @@ package mem import "base:runtime" -import "base:sanitizer" +// import "base:sanitizer" /* Rollback stack default block size. @@ -134,7 +134,7 @@ rb_free_all :: proc(stack: ^Rollback_Stack) { stack.head.next_block = nil stack.head.last_alloc = nil stack.head.offset = 0 - sanitizer.address_poison(stack.head.buffer) + // sanitizer.address_poison(stack.head.buffer) } /* @@ -241,7 +241,7 @@ rb_alloc_bytes_non_zeroed :: proc( block.offset = cast(uintptr)len(block.buffer) } res := ptr[:size] - sanitizer.address_unpoison(res) + // sanitizer.address_unpoison(res) return res, nil } return nil, .Out_Of_Memory @@ -338,13 +338,13 @@ rb_resize_bytes_non_zeroed :: proc( block.offset += cast(uintptr)size - cast(uintptr)old_size } res := (ptr)[:size] - sanitizer.address_unpoison(res) + // sanitizer.address_unpoison(res) #no_bounds_check return res, nil } } } result = rb_alloc_bytes_non_zeroed(stack, size, alignment) or_return - runtime.mem_copy_non_overlapping(raw_data(result), ptr, old_size) + runtime.mem_copy_non_overlapping(raw_data(result), ptr, min(old_size, size)) err = rb_free(stack, ptr) return } diff --git a/core/mem/tlsf/tlsf.odin b/core/mem/tlsf/tlsf.odin index 0ae8c28e0..b1ef4406a 100644 --- a/core/mem/tlsf/tlsf.odin +++ b/core/mem/tlsf/tlsf.odin @@ -1,15 +1,15 @@ +// Two Level Segregated Fit memory allocator. +package mem_tlsf + /* Copyright 2024 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under tlsf's LICENSE (BSD 3-clause). List of contributors: Matt Conte: Original C implementation, see LICENSE file in this package Jeroen van Rijn: Source port */ -// package mem_tlsf implements a Two Level Segregated Fit memory allocator. -package mem_tlsf - import "base:intrinsics" import "base:runtime" diff --git a/core/mem/tlsf/tlsf_internal.odin b/core/mem/tlsf/tlsf_internal.odin index 89b875679..802c4a3fd 100644 --- a/core/mem/tlsf/tlsf_internal.odin +++ b/core/mem/tlsf/tlsf_internal.odin @@ -1,6 +1,6 @@ /* Copyright 2024 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under tlsf's LICENSE (BSD 3-clause). List of contributors: Matt Conte: Original C implementation, see LICENSE file in this package @@ -10,7 +10,7 @@ package mem_tlsf import "base:intrinsics" -import "base:sanitizer" +// import "base:sanitizer" import "base:runtime" // log2 of number of linear subdivisions of block sizes. @@ -210,7 +210,7 @@ alloc_bytes_non_zeroed :: proc(control: ^Allocator, size: uint, align: uint) -> return nil, .Out_Of_Memory } - sanitizer.address_poison(new_pool_buf) + // sanitizer.address_poison(new_pool_buf) // Allocate a new link in the `control.pool` tracking structure. new_pool := new_clone(Pool{ @@ -257,7 +257,7 @@ alloc_bytes_non_zeroed :: proc(control: ^Allocator, size: uint, align: uint) -> return block_prepare_used(control, block, adjust) } -@(private, require_results, no_sanitize_address) +@(private, require_results) alloc_bytes :: proc(control: ^Allocator, size: uint, align: uint) -> (res: []byte, err: runtime.Allocator_Error) { res, err = alloc_bytes_non_zeroed(control, size, align) if err == nil { @@ -267,6 +267,7 @@ alloc_bytes :: proc(control: ^Allocator, size: uint, align: uint) -> (res: []byt } +@(no_sanitize_address) free_with_size :: proc(control: ^Allocator, ptr: rawptr, size: uint) { assert(control != nil) // `size` is currently ignored @@ -276,7 +277,7 @@ free_with_size :: proc(control: ^Allocator, ptr: rawptr, size: uint) { block := block_from_ptr(ptr) assert(!block_is_free(block), "block already marked as free") // double free - sanitizer.address_poison(ptr, block.size) + // sanitizer.address_poison(ptr, block.size) block_mark_as_free(block) block = block_merge_prev(control, block) block = block_merge_next(control, block) @@ -320,7 +321,7 @@ resize :: proc(control: ^Allocator, ptr: rawptr, old_size, new_size: uint, align block_trim_used(control, block, adjust) res = ([^]byte)(ptr)[:new_size] - sanitizer.address_unpoison(res) + // sanitizer.address_unpoison(res) if min_size < new_size { to_zero := ([^]byte)(ptr)[min_size:new_size] @@ -477,25 +478,25 @@ block_mark_as_free :: proc(block: ^Block_Header) { } @(private, no_sanitize_address) -block_mark_as_used :: proc(block: ^Block_Header, ) { +block_mark_as_used :: proc(block: ^Block_Header) { next := block_next(block) block_set_prev_used(next) block_set_used(block) } -@(private, require_results, no_sanitize_address) +@(private, require_results) align_up :: proc(x, align: uint) -> (aligned: uint) { assert(0 == (align & (align - 1)), "must align to a power of two") return (x + (align - 1)) &~ (align - 1) } -@(private, require_results, no_sanitize_address) +@(private, require_results) align_down :: proc(x, align: uint) -> (aligned: uint) { assert(0 == (align & (align - 1)), "must align to a power of two") return x - (x & (align - 1)) } -@(private, require_results, no_sanitize_address) +@(private, require_results) align_ptr :: proc(ptr: rawptr, align: uint) -> (aligned: rawptr) { assert(0 == (align & (align - 1)), "must align to a power of two") align_mask := uintptr(align) - 1 @@ -505,7 +506,7 @@ align_ptr :: proc(ptr: rawptr, align: uint) -> (aligned: rawptr) { } // Adjust an allocation size to be aligned to word size, and no smaller than internal minimum. -@(private, require_results, no_sanitize_address) +@(private, require_results) adjust_request_size :: proc(size, align: uint) -> (adjusted: uint) { if size == 0 { return 0 @@ -519,7 +520,7 @@ adjust_request_size :: proc(size, align: uint) -> (adjusted: uint) { } // Adjust an allocation size to be aligned to word size, and no smaller than internal minimum. -@(private, require_results, no_sanitize_address) +@(private, require_results) adjust_request_size_with_err :: proc(size, align: uint) -> (adjusted: uint, err: runtime.Allocator_Error) { if size == 0 { return 0, nil @@ -537,7 +538,7 @@ adjust_request_size_with_err :: proc(size, align: uint) -> (adjusted: uint, err: // TLSF utility functions. In most cases these are direct translations of // the documentation in the research paper. -@(optimization_mode="favor_size", private, require_results, no_sanitize_address) +@(optimization_mode="favor_size", private, require_results) mapping_insert :: proc(size: uint) -> (fl, sl: i32) { if size < SMALL_BLOCK_SIZE { // Store small blocks in first list. @@ -550,7 +551,7 @@ mapping_insert :: proc(size: uint) -> (fl, sl: i32) { return } -@(optimization_mode="favor_size", private, require_results, no_sanitize_address) +@(optimization_mode="favor_size", private, require_results) mapping_round :: #force_inline proc(size: uint) -> (rounded: uint) { rounded = size if size >= SMALL_BLOCK_SIZE { @@ -561,7 +562,7 @@ mapping_round :: #force_inline proc(size: uint) -> (rounded: uint) { } // This version rounds up to the next block size (for allocations) -@(optimization_mode="favor_size", private, require_results, no_sanitize_address) +@(optimization_mode="favor_size", private, require_results) mapping_search :: proc(size: uint) -> (fl, sl: i32) { return mapping_insert(mapping_round(size)) } @@ -788,7 +789,7 @@ block_prepare_used :: proc(control: ^Allocator, block: ^Block_Header, size: uint block_trim_free(control, block, size) block_mark_as_used(block) res = ([^]byte)(block_to_ptr(block))[:size] - sanitizer.address_unpoison(res) + // sanitizer.address_unpoison(res) } return } diff --git a/core/mem/tracking_allocator.odin b/core/mem/tracking_allocator.odin index 01080075e..d6462faf1 100644 --- a/core/mem/tracking_allocator.odin +++ b/core/mem/tracking_allocator.odin @@ -130,11 +130,11 @@ the tracking allocator to the old behavior, where the bad_free_array was used. */ @(no_sanitize_address) tracking_allocator_bad_free_callback_panic :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) { - runtime.print_caller_location(location) - runtime.print_string(" Tracking allocator error: Bad free of pointer ") - runtime.print_uintptr(uintptr(memory)) - runtime.print_string("\n") - runtime.trap() + buf: [256]byte + offset := 0 + _ = runtime.write_string(&offset, buf[:], "Tracking allocator error: Bad free of pointer ") + _ = runtime.write_u64(&offset, buf[:], u64(uintptr(memory))) + panic(string(buf[:offset]), loc = location) } /* diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 4e1cc2466..3d3827885 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -3,7 +3,7 @@ package mem_virtual import "core:mem" import "core:sync" -import "base:sanitizer" +// import "base:sanitizer" Arena_Kind :: enum uint { Growing = 0, // Chained memory blocks (singly linked list). @@ -55,7 +55,7 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING if arena.minimum_block_size == 0 { arena.minimum_block_size = reserved } - sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) + // sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) return } @@ -68,7 +68,7 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_STATIC_R arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return arena.total_used = 0 arena.total_reserved = arena.curr_block.reserved - sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) + // sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) return } @@ -82,7 +82,7 @@ arena_init_buffer :: proc(arena: ^Arena, buffer: []byte) -> (err: Allocator_Erro arena.kind = .Buffer - sanitizer.address_poison(buffer[:]) + // sanitizer.address_poison(buffer[:]) block_base := raw_data(buffer) block := (^Memory_Block)(block_base) @@ -108,6 +108,16 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l } sync.mutex_guard(&arena.mutex) + return arena_alloc_unguarded(arena, size, alignment, loc) +} + +// Allocates memory from the provided arena. +@(require_results, no_sanitize_address, private) +arena_alloc_unguarded :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { + size := size + if size == 0 { + return nil, nil + } switch arena.kind { case .Growing: @@ -116,11 +126,11 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l if err == .Out_Of_Memory { if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE - arena.minimum_block_size = mem.align_forward_uint(arena.minimum_block_size, DEFAULT_PAGE_SIZE) + arena.minimum_block_size = mem.align_forward_uint(arena.minimum_block_size, uint(mem.PAGE_SIZE)) } if arena.default_commit_size == 0 { arena.default_commit_size = min(DEFAULT_ARENA_GROWING_COMMIT_SIZE, arena.minimum_block_size) - arena.default_commit_size = mem.align_forward_uint(arena.default_commit_size, DEFAULT_PAGE_SIZE) + arena.default_commit_size = mem.align_forward_uint(arena.default_commit_size, uint(mem.PAGE_SIZE)) } if arena.default_commit_size != 0 { @@ -133,7 +143,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l needed = max(needed, arena.default_commit_size) block_size := max(needed, arena.minimum_block_size) - new_block := memory_block_alloc(needed, block_size, alignment, {}) or_return + new_block := memory_block_alloc(needed, block_size, alignment) or_return new_block.prev = arena.curr_block arena.curr_block = new_block arena.total_reserved += new_block.reserved @@ -163,7 +173,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l arena.total_used = arena.curr_block.used } - sanitizer.address_unpoison(data) + // sanitizer.address_unpoison(data) return } @@ -182,7 +192,7 @@ arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) mem.zero_slice(arena.curr_block.base[arena.curr_block.used:][:prev_pos-pos]) } arena.total_used = arena.curr_block.used - sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) + // sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) return true } else if pos == 0 { arena.total_used = 0 @@ -200,7 +210,7 @@ arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_locat arena.total_reserved -= free_block.reserved arena.curr_block = free_block.prev - sanitizer.address_poison(free_block.base[:free_block.committed]) + // sanitizer.address_poison(free_block.base[:free_block.committed]) memory_block_dealloc(free_block) } } @@ -219,9 +229,9 @@ arena_free_all :: proc(arena: ^Arena, loc := #caller_location) { if arena.curr_block != nil { curr_block_used := int(arena.curr_block.used) arena.curr_block.used = 0 - sanitizer.address_unpoison(arena.curr_block.base[:curr_block_used]) + // sanitizer.address_unpoison(arena.curr_block.base[:curr_block_used]) mem.zero(arena.curr_block.base, curr_block_used) - sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) + // sanitizer.address_poison(arena.curr_block.base[:arena.curr_block.committed]) } arena.total_used = 0 case .Static, .Buffer: @@ -345,11 +355,15 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case size == 0: err = .Mode_Not_Implemented return - case uintptr(old_data) & uintptr(alignment-1) == 0: + } + + sync.mutex_guard(&arena.mutex) + + if uintptr(old_data) & uintptr(alignment-1) == 0 { if size < old_size { // shrink data in-place data = old_data[:size] - sanitizer.address_poison(old_data[size:old_size]) + // sanitizer.address_poison(old_data[size:old_size]) return } @@ -363,18 +377,18 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, _ = alloc_from_memory_block(block, new_end - old_end, 1, default_commit_size=arena.default_commit_size) or_return arena.total_used += block.used - prev_used data = block.base[start:new_end] - sanitizer.address_unpoison(data) + // sanitizer.address_unpoison(data) return } } } - new_memory := arena_alloc(arena, size, alignment, location) or_return + new_memory := arena_alloc_unguarded(arena, size, alignment, location) or_return if new_memory == nil { return } copy(new_memory, old_data[:old_size]) - sanitizer.address_poison(old_data[:old_size]) + // sanitizer.address_poison(old_data[:old_size]) return new_memory, nil case .Query_Features: set := (^mem.Allocator_Mode_Set)(old_memory) diff --git a/core/mem/virtual/arena_util.odin b/core/mem/virtual/arena_util.odin index 4e28c17d6..fb778687b 100644 --- a/core/mem/virtual/arena_util.odin +++ b/core/mem/virtual/arena_util.odin @@ -20,6 +20,17 @@ new_aligned :: proc(arena: ^Arena, $T: typeid, alignment: uint, loc := #caller_l return } +// The `new_clone` procedure allocates memory for a type `T` from a `virtual.Arena`. The second argument is a value that +// is to be copied to the allocated data. The value returned is a pointer to a newly allocated value of that type using the specified allocator. +@(require_results) +new_clone :: proc(arena: ^Arena, data: $T, loc := #caller_location) -> (ptr: ^T, err: Allocator_Error) { + ptr, err = new_aligned(arena, T, align_of(T), loc) + if ptr != nil && err == nil { + ptr^ = data + } + return +} + // `make_slice` allocates and initializes a slice. Like `new`, the second argument is a type, not a value. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. // diff --git a/core/mem/virtual/common.odin b/core/mem/virtual/common.odin new file mode 100644 index 000000000..ad8505c89 --- /dev/null +++ b/core/mem/virtual/common.odin @@ -0,0 +1,16 @@ +package mem_virtual + +Map_File_Error :: enum { + None, + Open_Failure, + Stat_Failure, + Negative_Size, + Too_Large_Size, + Map_Failure, +} + +Map_File_Flag :: enum u32 { + Read, + Write, +} +Map_File_Flags :: distinct bit_set[Map_File_Flag; u32] \ No newline at end of file diff --git a/core/mem/virtual/doc.odin b/core/mem/virtual/doc.odin new file mode 100644 index 000000000..2c7e046ea --- /dev/null +++ b/core/mem/virtual/doc.odin @@ -0,0 +1,75 @@ +/* +A platform agnostic way to reserve/commit/decommit virtual memory. + +virtual.Arena usage + +Example: + // Source: https://github.com/odin-lang/examples/blob/master/arena_allocator/arena_allocator.odin + import "core:fmt" + import "core:os" + + // virtual package implements a multi-purpose arena allocator. If you are on a + // platform that does not support virtual memory, then there is also a similar + // arena in `core:mem`. + import vmem "core:mem/virtual" + + load_files :: proc() -> ([]string, vmem.Arena) { + // This creates a growing virtual memory arena. It uses virtual memory and + // can grow as things are added to it. + arena: vmem.Arena + arena_err := vmem.arena_init_growing(&arena) + ensure(arena_err == nil) + arena_alloc := vmem.arena_allocator(&arena) + + // See arena_init_static for an arena that uses virtual memory, but cannot grow. + + // See arena_init_buffer for an arena that does not use virtual memory, + // instead it relies on you feeding it a buffer. + + f1, f1_err := os.read_entire_file("file1.txt", arena_alloc) + ensure(f1_err == nil) + + f2, f2_err := os.read_entire_file("file2.txt", arena_alloc) + ensure(f2_err == nil) + + f3, f3_err := os.read_entire_file("file3.txt", arena_alloc) + ensure(f3_err == nil) + + res := make([]string, 3, arena_alloc) + res[0] = string(f1) + res[1] = string(f2) + res[2] = string(f3) + + return res, arena + } + + main :: proc() { + files, arena := load_files() + + for f in files { + fmt.println(f) + } + + // This deallocates everything that was allocated on the arena: + // The loaded content of the files as well as the `files` slice. + vmem.arena_destroy(&arena) + } + +virtual.map_file usage + +Example: + // Source: https://github.com/odin-lang/examples/blob/master/arena_allocator/arena_allocator.odin + import "core:fmt" + + // virtual package implements cross-platform file memory mapping + import vmem "core:mem/virtual" + + main :: proc() { + data, err := vmem.map_file_from_path(#file, {.Read}) + defer vmem.unmap_file(data) + fmt.printfln("Error: %v", err) + fmt.printfln("Data: %s", data) + } +*/ +package mem_virtual + diff --git a/core/mem/virtual/file.odin b/core/mem/virtual/file.odin index 2f852b40c..af0449e66 100644 --- a/core/mem/virtual/file.odin +++ b/core/mem/virtual/file.odin @@ -1,39 +1,32 @@ +#+build !freestanding +#+build !js package mem_virtual import "core:os" -Map_File_Error :: enum { - None, - Open_Failure, - Stat_Failure, - Negative_Size, - Too_Large_Size, - Map_Failure, -} - -Map_File_Flag :: enum u32 { - Read, - Write, -} -Map_File_Flags :: distinct bit_set[Map_File_Flag; u32] - map_file :: proc{ map_file_from_path, - map_file_from_file_descriptor, + map_file_from_file, } map_file_from_path :: proc(filename: string, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { - fd, err := os.open(filename, os.O_RDWR) + open_flags : os.File_Flags + if .Read in flags { + open_flags += {.Read} + } + if .Write in flags { + open_flags += {.Write} + } + f, err := os.open(filename, open_flags) if err != nil { return nil, .Open_Failure } - defer os.close(fd) - - return map_file_from_file_descriptor(uintptr(fd), flags) + defer os.close(f) + return map_file_from_file(f, flags) } -map_file_from_file_descriptor :: proc(fd: uintptr, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { - size, os_err := os.file_size(os.Handle(fd)) +map_file_from_file :: proc(f: ^os.File, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { + size, os_err := os.file_size(f) if os_err != nil { return nil, .Stat_Failure } @@ -43,5 +36,12 @@ map_file_from_file_descriptor :: proc(fd: uintptr, flags: Map_File_Flags) -> (da if size != i64(int(size)) { return nil, .Too_Large_Size } + fd := os.fd(f) return _map_file(fd, size, flags) } + +unmap_file :: proc(data: []byte) { + if raw_data(data) != nil { + _unmap_file(data) + } +} diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 031fb721a..ae6206de7 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -2,27 +2,20 @@ package mem_virtual import "core:mem" import "base:intrinsics" -import "base:sanitizer" +// import "base:sanitizer" import "base:runtime" _ :: runtime -DEFAULT_PAGE_SIZE := uint(4096) - -@(init, private) -platform_memory_init :: proc() { - _platform_memory_init() -} - Allocator_Error :: mem.Allocator_Error @(require_results, no_sanitize_address) -reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { - return _reserve(size) +reserve :: proc "contextless" (size: uint, address_hint := uintptr(0)) -> (data: []byte, err: Allocator_Error) { + return _reserve(size, address_hint) } @(no_sanitize_address) commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error { - sanitizer.address_unpoison(data, size) + // sanitizer.address_unpoison(data, size) return _commit(data, size) } @@ -35,13 +28,13 @@ reserve_and_commit :: proc "contextless" (size: uint) -> (data: []byte, err: All @(no_sanitize_address) decommit :: proc "contextless" (data: rawptr, size: uint) { - sanitizer.address_poison(data, size) + // sanitizer.address_poison(data, size) _decommit(data, size) } @(no_sanitize_address) release :: proc "contextless" (data: rawptr, size: uint) { - sanitizer.address_unpoison(data, size) + // sanitizer.address_unpoison(data, size) _release(data, size) } @@ -79,7 +72,7 @@ align_formula :: #force_inline proc "contextless" (size, align: uint) -> uint { @(require_results, no_sanitize_address) memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags: Memory_Block_Flags = {}) -> (block: ^Memory_Block, err: Allocator_Error) { - page_size := DEFAULT_PAGE_SIZE + page_size := uint(mem.PAGE_SIZE) assert(mem.is_power_of_two(uintptr(page_size))) committed := committed @@ -89,8 +82,8 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags reserved = align_formula(reserved, page_size) committed = clamp(committed, 0, reserved) - total_size := uint(reserved + max(alignment, size_of(Platform_Memory_Block))) - base_offset := uintptr(max(alignment, size_of(Platform_Memory_Block))) + total_size := reserved + alignment + size_of(Platform_Memory_Block) + base_offset := mem.align_forward_uintptr(size_of(Platform_Memory_Block), max(uintptr(alignment), align_of(Platform_Memory_Block))) protect_offset := uintptr(0) do_protection := false @@ -115,7 +108,7 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags } pmblock.block.committed = committed - pmblock.block.reserved = reserved + pmblock.block.reserved = total_size - uint(base_offset) return &pmblock.block, nil @@ -144,7 +137,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint, // TODO(bill): determine a better heuristic for this behaviour extra_size := max(size, block.committed>>1) platform_total_commit := base_offset + block.used + extra_size - platform_total_commit = align_formula(platform_total_commit, DEFAULT_PAGE_SIZE) + platform_total_commit = align_formula(platform_total_commit, uint(mem.PAGE_SIZE)) platform_total_commit = min(max(platform_total_commit, default_commit_size), pmblock.reserved) assert(pmblock.committed <= pmblock.reserved) @@ -154,7 +147,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint, pmblock.committed = platform_total_commit block.committed = pmblock.committed - base_offset - + assert(block.committed <= block.reserved) } return } @@ -174,12 +167,12 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint, err = .Out_Of_Memory return } - assert(block.committed <= block.reserved) + do_commit_if_necessary(block, size, default_commit_size) or_return data = block.base[block.used+alignment_offset:][:min_size] block.used += size - sanitizer.address_unpoison(data) + // sanitizer.address_unpoison(data) return } diff --git a/core/mem/virtual/virtual_darwin.odin b/core/mem/virtual/virtual_darwin.odin index 0635c83d4..63f7f0771 100644 --- a/core/mem/virtual/virtual_darwin.odin +++ b/core/mem/virtual/virtual_darwin.odin @@ -2,8 +2,8 @@ package mem_virtual import "core:sys/posix" -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { - result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE}) +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { + result := posix.mmap(rawptr(address_hint), size, {}, {.ANONYMOUS, .PRIVATE}) if result == posix.MAP_FAILED { assert_contextless(posix.errno() == .ENOMEM) return nil, .Out_Of_Memory diff --git a/core/mem/virtual/virtual_freebsd.odin b/core/mem/virtual/virtual_freebsd.odin index af0f31733..d055d6052 100644 --- a/core/mem/virtual/virtual_freebsd.odin +++ b/core/mem/virtual/virtual_freebsd.odin @@ -2,14 +2,14 @@ package mem_virtual import "core:sys/posix" -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { PROT_MAX :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags { _PROT_MAX_SHIFT :: 16 return transmute(posix.Prot_Flags)(transmute(i32)flags << _PROT_MAX_SHIFT) } - result := posix.mmap(nil, size, PROT_MAX({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE}) + result := posix.mmap(rawptr(address_hint), size, PROT_MAX({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE}) if result == posix.MAP_FAILED { assert_contextless(posix.errno() == .ENOMEM) return nil, .Out_Of_Memory diff --git a/core/mem/virtual/virtual_linux.odin b/core/mem/virtual/virtual_linux.odin index 3e0d7668b..665749489 100644 --- a/core/mem/virtual/virtual_linux.odin +++ b/core/mem/virtual/virtual_linux.odin @@ -4,8 +4,8 @@ package mem_virtual import "core:sys/linux" -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { - addr, errno := linux.mmap(0, size, {}, {.PRIVATE, .ANONYMOUS}) +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { + addr, errno := linux.mmap(address_hint, size, {}, {.PRIVATE, .ANONYMOUS}) if errno == .ENOMEM { return nil, .Out_Of_Memory } else if errno == .EINVAL { @@ -43,13 +43,6 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return errno == .NONE } -_platform_memory_init :: proc() { - DEFAULT_PAGE_SIZE = 4096 - // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) -} - - _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { prot: linux.Mem_Protection if .Read in flags { @@ -66,3 +59,7 @@ _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) } return ([^]byte)(addr)[:size], nil } + +_unmap_file :: proc "contextless" (data: []byte) { + _release(raw_data(data), uint(len(data))) +} diff --git a/core/mem/virtual/virtual_netbsd.odin b/core/mem/virtual/virtual_netbsd.odin index 588625cc7..afd2e27f4 100644 --- a/core/mem/virtual/virtual_netbsd.odin +++ b/core/mem/virtual/virtual_netbsd.odin @@ -2,13 +2,13 @@ package mem_virtual import "core:sys/posix" -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { PROT_MPROTECT :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags { return transmute(posix.Prot_Flags)(transmute(i32)flags << 3) } - result := posix.mmap(nil, size, PROT_MPROTECT({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE}) + result := posix.mmap(rawptr(address_hint), size, PROT_MPROTECT({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE}) if result == posix.MAP_FAILED { assert_contextless(posix.errno() == .ENOMEM) return nil, .Out_Of_Memory diff --git a/core/mem/virtual/virtual_openbsd.odin b/core/mem/virtual/virtual_openbsd.odin index 83f7ca9ca..41adf359c 100644 --- a/core/mem/virtual/virtual_openbsd.odin +++ b/core/mem/virtual/virtual_openbsd.odin @@ -2,8 +2,8 @@ package mem_virtual import "core:sys/posix" -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { - result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE}) +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { + result := posix.mmap(rawptr(address_hint), size, {}, {.ANONYMOUS, .PRIVATE}) if result == posix.MAP_FAILED { assert_contextless(posix.errno() == .ENOMEM) return nil, .Out_Of_Memory diff --git a/core/mem/virtual/virtual_other.odin b/core/mem/virtual/virtual_other.odin index a57856975..a8ba29d14 100644 --- a/core/mem/virtual/virtual_other.odin +++ b/core/mem/virtual/virtual_other.odin @@ -7,7 +7,7 @@ #+build !windows package mem_virtual -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { return nil, nil } @@ -25,9 +25,10 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return false } -_platform_memory_init :: proc() { -} - -_map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { +_map_file :: proc "contextless" (f: any, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { return nil, .Map_Failure } + +_unmap_file :: proc "contextless" (data: []byte) { + +} diff --git a/core/mem/virtual/virtual_posix.odin b/core/mem/virtual/virtual_posix.odin index 0b304a5e7..623a2b911 100644 --- a/core/mem/virtual/virtual_posix.odin +++ b/core/mem/virtual/virtual_posix.odin @@ -28,15 +28,6 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return posix.mprotect(data, size, transmute(posix.Prot_Flags)flags) == .OK } -_platform_memory_init :: proc() { - // NOTE: `posix.PAGESIZE` due to legacy reasons could be wrong so we use `sysconf`. - size := posix.sysconf(._PAGESIZE) - DEFAULT_PAGE_SIZE = uint(max(size, posix.PAGESIZE)) - - // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) -} - _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { #assert(i32(posix.Prot_Flag_Bits.READ) == i32(Map_File_Flag.Read)) #assert(i32(posix.Prot_Flag_Bits.WRITE) == i32(Map_File_Flag.Write)) @@ -47,3 +38,7 @@ _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) } return ([^]byte)(addr)[:size], nil } + +_unmap_file :: proc "contextless" (data: []byte) { + _release(raw_data(data), uint(len(data))) +} \ No newline at end of file diff --git a/core/mem/virtual/virtual_windows.odin b/core/mem/virtual/virtual_windows.odin index 0da8498d5..768eae711 100644 --- a/core/mem/virtual/virtual_windows.odin +++ b/core/mem/virtual/virtual_windows.odin @@ -72,7 +72,7 @@ foreign Kernel32 { flProtect: u32, dwMaximumSizeHigh: u32, dwMaximumSizeLow: u32, - lpName: [^]u16, + lpName: cstring16, ) -> rawptr --- MapViewOfFile :: proc( @@ -82,11 +82,13 @@ foreign Kernel32 { dwFileOffsetLow: u32, dwNumberOfBytesToMap: uint, ) -> rawptr --- + + UnmapViewOfFile :: proc(lpBaseAddress: rawptr) -> b32 --- } @(no_sanitize_address) -_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) { - result := VirtualAlloc(nil, size, MEM_RESERVE, PAGE_READWRITE) +_reserve :: proc "contextless" (size: uint, address_hint: uintptr) -> (data: []byte, err: Allocator_Error) { + result := VirtualAlloc(rawptr(address_hint), size, MEM_RESERVE, PAGE_READWRITE) if result == nil { err = .Out_Of_Memory return @@ -144,18 +146,6 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return bool(ok) } - -@(no_sanitize_address) -_platform_memory_init :: proc() { - sys_info: SYSTEM_INFO - GetSystemInfo(&sys_info) - DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, uint(sys_info.dwPageSize)) - - // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) -} - - @(no_sanitize_address) _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { page_flags: u32 @@ -185,3 +175,8 @@ _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) file_data := MapViewOfFile(handle, desired_access, 0, 0, uint(size)) return ([^]byte)(file_data)[:size], nil } + +@(no_sanitize_address) +_unmap_file :: proc "contextless" (data: []byte) { + UnmapViewOfFile(raw_data(data)) +} diff --git a/core/nbio/doc.odin b/core/nbio/doc.odin new file mode 100644 index 000000000..706d9d42f --- /dev/null +++ b/core/nbio/doc.odin @@ -0,0 +1,213 @@ +/* +package nbio implements a non-blocking I/O and event loop abstraction layer +over several platform-specific asynchronous I/O APIs. + +More examples can be found in Odin's examples repository +at [[ examples/nbio ; https://github.com/odin-lang/examples/tree/master/nbio ]]. + +**Event Loop**: + +Each thread may have at most one event loop associated with it. +This is enforced by the package, as running multiple event loops on a single +thread does not make sense. + +Event loops are reference counted and managed by the package. + +`acquire_thread_event_loop` and `release_thread_event_loop` can be used +to acquire and release a reference. Acquiring must be done before any operation +is done. + +The event loop progresses in ticks. A tick checks if any work is to be done, +and based on the given timeout may block waiting for work. + +Ticks are typically done using the `tick`, `run`, and `run_until` procedures. + +Example: + package main + + import "core:nbio" + import "core:time" + import "core:fmt" + + main :: proc() { + err := nbio.acquire_thread_event_loop() + assert(err == nil) + defer nbio.release_thread_event_loop() + + nbio.timeout(time.Second, proc(_: ^nbio.Operation) { + fmt.println("Hellope after 1 second!") + }) + + err = nbio.run() + assert(err == nil) + } + + +**Time and timeouts**: + +Timeouts are intentionally *slightly inaccurate* by design. + +A timeout is not checked continuously, instead, it is evaluated only when +a tick occurs. This means if a tick took a long time, your timeout may be ready +for a bit of time already before the callback is called. + +The function `now` returns the current time as perceived by the event +loop. This value is cached at least once per tick so it is fast to retrieve. + +Most operations also take an optional timeout when executed. +If the timeout completes before the operation, the operation is cancelled and +called back with a `.Timeout` error. + + +**Threading**: + +The package has a concept of I/O threads (threads that are ticking) and worker +threads (any other thread). + +An I/O thread is mostly self contained, operations are executed on it, and +callbacks run on it. + +If you try to execute an operation on a thread that has no running event loop +a panic will be executed. Instead a worker thread can execute operations onto +a running event loop by taking it's reference and executing operations with +that reference. + +In this case: +- The operation is enqueued from the worker thread +- The I/O thread is optionally woken up from blocking for work with `wake_up` +- The next tick, the operation is executed by the I/O thread +- The callback is invoked on the I/O thread + +Example: + package main + + import "core:nbio" + import "core:net" + import "core:thread" + import "core:time" + + Connection :: struct { + loop: ^nbio.Event_Loop, + socket: net.TCP_Socket, + } + + main :: proc() { + workers: thread.Pool + thread.pool_init(&workers, context.allocator, 2) + thread.pool_start(&workers) + + err := nbio.acquire_thread_event_loop() + defer nbio.release_thread_event_loop() + assert(err == nil) + + server, listen_err := nbio.listen_tcp({nbio.IP4_Any, 1234}) + assert(listen_err == nil) + nbio.accept_poly(server, &workers, on_accept) + + err = nbio.run() + assert(err == nil) + + on_accept :: proc(op: ^nbio.Operation, workers: ^thread.Pool) { + assert(op.accept.err == nil) + + nbio.accept_poly(op.accept.socket, workers, on_accept) + + thread.pool_add_task(workers, context.allocator, do_work, new_clone(Connection{ + loop = op.l, + socket = op.accept.client, + })) + } + + do_work :: proc(t: thread.Task) { + connection := (^Connection)(t.data) + + // Imagine CPU intensive work that's been ofloaded to a worker thread. + time.sleep(time.Second * 1) + + nbio.send_poly(connection.socket, {transmute([]byte)string("Hellope!\n")}, connection, on_sent, l=connection.loop) + } + + on_sent :: proc(op: ^nbio.Operation, connection: ^Connection) { + assert(op.send.err == nil) + // Client got our message, clean up. + nbio.close(connection.socket) + free(connection) + } + } + + +**Handle and socket association**: + +Most platforms require handles (files, sockets, etc.) to be explicitly +associated with an event loop or configured for non-blocking/asynchronous +operation. + +On some platforms (notably Windows), this requires a specific flag at open +time (`.Non_Blocking` for `core:os`) and association may fail if the handle was +not created correctly. + +For this reason, prefer `open` and `create_socket` from this package instead. + +`associate_handle`, `associate_file`, and `associate_socket` can be used for +externally opened files/sockets. + + +**Offsets and positional I/O**: + +Operations do not implicitly use or modify a handle’s internal file +offset. + +Instead, operations such as `read` and `write` are *positional* and require +an explicit offset. + +This avoids ambiguity and subtle bugs when multiple asynchronous operations +are issued concurrently against the same handle. + + +**Contexts and callbacks**: + +The `context` inside a callback is *not* the context that submitted the +operation. + +Instead, the callback receives the context that was active when the event +loop function (`tick`, `run`, etc.) was called. + +This is because otherwise the context would have to be copied and held onto for +each operation. + +If the submitting context is required inside the callback, it must be copied +into the operation’s user data explicitly. + +Example: + nbio.timeout_poly(time.Second, new_clone(context), proc(_: ^Operation, ctx: ^runtime.Context) { + context = ctx^ + free(ctx) + }) + + +**Callback scheduling guarantees**: + +Callbacks are guaranteed to be invoked in a later tick, never synchronously. +This means that the operation returned from a procedure is at least valid till +the end of the current tick, because an operation is freed after it's callback +is called. Thus you can set user data after an execution is queued, or call +`remove`, removing subtle "race" conditions and simplifying control flow. + +**Why does the design of this package use callbacks?** + +Callbacks are the simplest interface an event loop can reasonably expose: "Run +this when the operation completes". This means the loop itself doesn’t need to +know how the result is consumed (You could give control of the entire loop to +the user, but that comes with all the problems in that). + +Other mechanisms can be built on top of this, such as coroutines or even a queue +you comsume at your own time. + +The choice of one `Operation` type and one callback type for all the operations +is partly so it is easy to bind into Lua-like or native coroutines. + +Callbacks also allow multiple independent users to share the same event loop. +A package can register its own operations, and application code can register +others, without either seeing or handling the other’s completions. +*/ +package nbio diff --git a/core/nbio/errors.odin b/core/nbio/errors.odin new file mode 100644 index 000000000..f3bd381d5 --- /dev/null +++ b/core/nbio/errors.odin @@ -0,0 +1,84 @@ +package nbio + +import "base:intrinsics" + +import "core:reflect" + +Error :: intrinsics.type_merge( + Network_Error, + union #shared_nil { + General_Error, + FS_Error, + }, +) +#assert(size_of(Error) == 8) + +// Errors regarding general usage of the event loop. +General_Error :: enum i32 { + None, + + Allocation_Failed = i32(PLATFORM_ERR_ALLOCATION_FAILED), + Unsupported = i32(PLATFORM_ERR_UNSUPPORTED), +} + +// Errors gotten from file system operations. +FS_Error :: enum i32 { + None, + Unsupported = i32(PLATFORM_ERR_UNSUPPORTED), + Allocation_Failed = i32(PLATFORM_ERR_ALLOCATION_FAILED), + Timeout = i32(PLATFORM_ERR_TIMEOUT), + Invalid_Argument = i32(PLATFORM_ERR_INVALID_ARGUMENT), + Permission_Denied = i32(PLATFORM_ERR_PERMISSION_DENIED), + EOF = i32(PLATFORM_ERR_EOF), + Exists = i32(PLATFORM_ERR_EXISTS), + Not_Found = i32(PLATFORM_ERR_NOT_FOUND), +} + +Platform_Error :: _Platform_Error + +error_string :: proc(err: Error) -> string { + err := err + variant := any{ + id = reflect.union_variant_typeid(err), + data = &err, + } + str := reflect.enum_string(variant) + + if str == "" { + #partial switch uerr in err { + case FS_Error: + str, _ = reflect.enum_name_from_value(Platform_Error(uerr)) + case General_Error: + str, _ = reflect.enum_name_from_value(Platform_Error(uerr)) + } + } + if str == "" { + str = "Unknown" + } + + return str +} + +error_string_recv :: proc(recv_err: Recv_Error) -> string { + switch err in recv_err { + case TCP_Recv_Error: return error_string(err) + case UDP_Recv_Error: return error_string(err) + case: return "Unknown" + } +} + +error_string_send :: proc(send_err: Send_Error) -> string { + switch err in send_err { + case TCP_Send_Error: return error_string(err) + case UDP_Send_Error: return error_string(err) + case: return "Unknown" + } +} + +error_string_sendfile :: proc(send_err: Send_File_Error) -> string { + switch err in send_err { + case TCP_Send_Error: return error_string(err) + case FS_Error: return error_string(err) + case: return "Unknown" + } +} diff --git a/core/nbio/errors_linux.odin b/core/nbio/errors_linux.odin new file mode 100644 index 000000000..5c3472500 --- /dev/null +++ b/core/nbio/errors_linux.odin @@ -0,0 +1,16 @@ +#+private +package nbio + +import "core:sys/linux" + +PLATFORM_ERR_UNSUPPORTED :: linux.Errno.ENOSYS +PLATFORM_ERR_ALLOCATION_FAILED :: linux.Errno.ENOMEM +PLATFORM_ERR_TIMEOUT :: linux.Errno.ECANCELED +PLATFORM_ERR_INVALID_ARGUMENT :: linux.Errno.EINVAL +PLATFORM_ERR_OVERFLOW :: linux.Errno.E2BIG +PLATFORM_ERR_NOT_FOUND :: linux.Errno.ENOENT +PLATFORM_ERR_EXISTS :: linux.Errno.EEXIST +PLATFORM_ERR_PERMISSION_DENIED :: linux.Errno.EPERM +PLATFORM_ERR_EOF :: -100 // There is no EOF errno, we use negative for our own error codes. + +_Platform_Error :: linux.Errno diff --git a/core/nbio/errors_others.odin b/core/nbio/errors_others.odin new file mode 100644 index 000000000..f27c91178 --- /dev/null +++ b/core/nbio/errors_others.odin @@ -0,0 +1,20 @@ +#+build !darwin +#+build !freebsd +#+build !openbsd +#+build !netbsd +#+build !linux +#+build !windows +#+private +package nbio + +PLATFORM_ERR_UNSUPPORTED :: 1 +PLATFORM_ERR_ALLOCATION_FAILED :: 2 +PLATFORM_ERR_TIMEOUT :: 3 +PLATFORM_ERR_INVALID_ARGUMENT :: 4 +PLATFORM_ERR_OVERFLOW :: 5 +PLATFORM_ERR_NOT_FOUND :: 6 +PLATFORM_ERR_EXISTS :: 7 +PLATFORM_ERR_PERMISSION_DENIED :: 8 +PLATFORM_ERR_EOF :: 9 + +_Platform_Error :: enum i32 {} diff --git a/core/nbio/errors_posix.odin b/core/nbio/errors_posix.odin new file mode 100644 index 000000000..3dd8f781d --- /dev/null +++ b/core/nbio/errors_posix.odin @@ -0,0 +1,17 @@ +#+build darwin, freebsd, netbsd, openbsd +#+private +package nbio + +import "core:sys/posix" + +PLATFORM_ERR_UNSUPPORTED :: posix.Errno.ENOSYS +PLATFORM_ERR_ALLOCATION_FAILED :: posix.Errno.ENOMEM +PLATFORM_ERR_TIMEOUT :: posix.Errno.ECANCELED +PLATFORM_ERR_INVALID_ARGUMENT :: posix.Errno.EINVAL +PLATFORM_ERR_OVERFLOW :: posix.Errno.E2BIG +PLATFORM_ERR_NOT_FOUND :: posix.Errno.ENOENT +PLATFORM_ERR_EXISTS :: posix.Errno.EEXIST +PLATFORM_ERR_PERMISSION_DENIED :: posix.Errno.EPERM +PLATFORM_ERR_EOF :: -100 // There is no EOF errno, we use negative for our own error codes. + +_Platform_Error :: posix.Errno diff --git a/core/nbio/errors_windows.odin b/core/nbio/errors_windows.odin new file mode 100644 index 000000000..d9b3b7e4d --- /dev/null +++ b/core/nbio/errors_windows.odin @@ -0,0 +1,17 @@ +#+private +package nbio + +import win "core:sys/windows" + +PLATFORM_ERR_UNSUPPORTED :: win.System_Error.NOT_SUPPORTED + +PLATFORM_ERR_ALLOCATION_FAILED :: win.System_Error.OUTOFMEMORY +PLATFORM_ERR_TIMEOUT :: win.System_Error.WAIT_TIMEOUT +PLATFORM_ERR_INVALID_ARGUMENT :: win.System_Error.BAD_ARGUMENTS +PLATFORM_ERR_OVERFLOW :: win.System_Error.BUFFER_OVERFLOW +PLATFORM_ERR_NOT_FOUND :: win.System_Error.FILE_NOT_FOUND +PLATFORM_ERR_EXISTS :: win.System_Error.FILE_EXISTS +PLATFORM_ERR_PERMISSION_DENIED :: win.System_Error.ACCESS_DENIED +PLATFORM_ERR_EOF :: win.System_Error.HANDLE_EOF + +_Platform_Error :: win.System_Error diff --git a/core/nbio/impl.odin b/core/nbio/impl.odin new file mode 100644 index 000000000..18bb7cfa9 --- /dev/null +++ b/core/nbio/impl.odin @@ -0,0 +1,318 @@ +#+private +package nbio + +import "base:runtime" +import "base:intrinsics" + +import "core:container/pool" +import "core:net" +import "core:reflect" +import "core:slice" +import "core:strings" +import "core:time" + +@(init, private) +init_thread_local_cleaner :: proc "contextless" () { + runtime.add_thread_local_cleaner(proc() { + l := &_tls_event_loop + if l.refs > 0 { + l.refs = 1 + _release_thread_event_loop() + } + }) +} + +@(thread_local) +_tls_event_loop: Event_Loop + +_acquire_thread_event_loop :: proc() -> General_Error { + l := &_tls_event_loop + if l.err == nil && l.refs == 0 { + when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 && ODIN_OS != .Orca { + allocator := runtime.default_wasm_allocator() + } else { + allocator := runtime.heap_allocator() + } + + l.allocator = allocator + + if alloc_err := mpsc_init(&l.queue, 128, l.allocator); alloc_err != nil { + l.err = .Allocation_Failed + return l.err + } + defer if l.err != nil { mpsc_destroy(&l.queue, l.allocator) } + + if pool_err := pool.init(&l.operation_pool, "_pool_link"); pool_err != nil { + l.err = .Allocation_Failed + return l.err + } + defer if l.err != nil { pool.destroy(&l.operation_pool) } + + l.err = _init(l, allocator) + l.now = time.now() + } + + if l.err != nil { + return l.err + } + + l.refs += 1 + return nil +} + +_release_thread_event_loop :: proc() { + l := &_tls_event_loop + if l.err != nil { + assert(l.refs == 0) + return + } + + if l.refs > 0 { + l.refs -= 1 + if l.refs == 0 { + mpsc_destroy(&l.queue, l.allocator) + pool.destroy(&l.operation_pool) + _destroy(l) + l^ = {} + } + } +} + +_current_thread_event_loop :: #force_inline proc(loc := #caller_location) -> (^Event_Loop) { + l := &_tls_event_loop + + if intrinsics.expect(l.refs == 0, false) { + return nil + } + + return l +} + +_tick :: proc(l: ^Event_Loop, timeout: time.Duration) -> (err: General_Error) { + // Receive operations queued from other threads first. + for { + op := (^Operation)(mpsc_dequeue(&l.queue)) + if op == nil { break } + _exec(op) + } + + return __tick(l, timeout) +} + +_listen_tcp :: proc( + l: ^Event_Loop, + endpoint: Endpoint, + backlog := 1000, + loc := #caller_location, +) -> ( + socket: TCP_Socket, + err: Network_Error, +) { + family := family_from_endpoint(endpoint) + socket = create_tcp_socket(family, l, loc) or_return + defer if err != nil { close(socket, l=l) } + + net.set_option(socket, .Reuse_Address, true) + + bind(socket, endpoint) or_return + + _listen(socket, backlog) or_return + return +} + +_read_entire_file :: proc(l: ^Event_Loop, path: string, user_data: rawptr, cb: Read_Entire_File_Callback, allocator := context.allocator, dir := CWD) { + open_poly3(path, user_data, cb, allocator, on_open, dir=dir, l=l) + + on_open :: proc(op: ^Operation, user_data: rawptr, cb: Read_Entire_File_Callback, allocator: runtime.Allocator) { + if op.open.err != nil { + cb(user_data, nil, {.Open, op.open.err}) + return + } + + stat_poly3(op.open.handle, user_data, cb, allocator, on_stat) + } + + on_stat :: proc(op: ^Operation, user_data: rawptr, cb: Read_Entire_File_Callback, allocator: runtime.Allocator) { + if op.stat.err != nil { + close(op.stat.handle) + cb(user_data, nil, {.Stat, op.stat.err}) + return + } + + if op.stat.type != .Regular { + close(op.stat.handle) + cb(user_data, nil, {.Stat, .Unsupported}) + return + } + + buf, err := make([]byte, op.stat.size, allocator) + if err != nil { + close(op.stat.handle) + cb(user_data, nil, {.Read, .Allocation_Failed}) + return + } + + read_poly3(op.stat.handle, 0, buf, user_data, cb, allocator, on_read, all=true) + } + + on_read :: proc(op: ^Operation, user_data: rawptr, cb: Read_Entire_File_Callback, allocator: runtime.Allocator) { + close(op.read.handle) + + if op.read.err != nil { + delete(op.read.buf, allocator) + cb(user_data, nil, {.Read, op.read.err}) + return + } + + assert(op.read.read == len(op.read.buf)) + cb(user_data, op.read.buf, {}) + } +} + +NBIO_DEBUG :: #config(NBIO_DEBUG, false) + +Debuggable :: union { + Operation_Type, + string, + int, + time.Time, + time.Duration, +} + +@(disabled=!NBIO_DEBUG) +debug :: proc(contents: ..Debuggable, location := #caller_location) { + if context.logger.procedure == nil || .Debug < context.logger.lowest_level { + return + } + + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + b: strings.Builder + b.buf.allocator = context.temp_allocator + + strings.write_string(&b, "[nbio] ") + + for content, i in contents { + switch val in content { + case Operation_Type: + name, _ := reflect.enum_name_from_value(val) + strings.write_string(&b, name) + case string: + strings.write_string(&b, val) + case int: + strings.write_int(&b, val) + case time.Duration: + ms := time.duration_milliseconds(val) + strings.write_f64(&b, ms, 'f') + strings.write_string(&b, "ms") + + case time.Time: + buf: [time.MIN_HMS_LEN+1]byte + h, m, s, ns := time.precise_clock_from_time(val) + buf[8] = '.' + buf[7] = '0' + u8(s % 10); s /= 10 + buf[6] = '0' + u8(s) + buf[5] = ':' + buf[4] = '0' + u8(m % 10); m /= 10 + buf[3] = '0' + u8(m) + buf[2] = ':' + buf[1] = '0' + u8(h % 10); h /= 10 + buf[0] = '0' + u8(h) + + strings.write_string(&b, string(buf[:])) + strings.write_int(&b, ns) + } + + if i < len(contents)-1 { + strings.write_byte(&b, ' ') + } + } + + context.logger.procedure(context.logger.data, .Debug, strings.to_string(b), context.logger.options, location) +} + +warn :: proc(text: string, location := #caller_location) { + if context.logger.procedure == nil || .Warning < context.logger.lowest_level { + return + } + + context.logger.procedure(context.logger.data, .Warning, text, context.logger.options, location) +} + +/* +In order to: +1. Not require the caller to allocate their buffers (`op.send.bufs` and `op.recv.bufs` can be stack allocated) +2. Have `op.send.bufs` and `op.recv.bufs` be valid and the same content in the callback as when called +3. Be able to facilitate the `all` option, which requires mutating the slices (advancing them) +4. Constraint single send/recv syscalls to MAX_RW bytes + +We need to copy the input buffers twice, once for a stable copy returned to the user, +and one for the working copy that we mutate with `all` set. +*/ + +Bufs :: struct { + backing: [1][]byte, + working: struct #raw_union { + small: [1][]byte, + big: [][]byte, + }, +} + +bufs_init :: proc(bufs: ^Bufs, orig: ^[][]byte, allocator: runtime.Allocator) -> runtime.Allocator_Error { + if len(orig) > 1 { + backing := make([][]byte, len(orig)*2, allocator) or_return + bufs.working.big = backing[len(orig):] + copy(bufs.working.big, orig^) + copy(backing, orig^) + orig^ = backing[:len(orig)] + return nil + } + + bufs.backing = {orig[0]} + orig^ = bufs.backing[:] + return nil +} + +bufs_delete :: proc(bufs: ^Bufs, orig: [][]byte, allocator: runtime.Allocator) { + if len(orig) > 1 { + backing := raw_data(orig)[:len(orig)*2] + delete(backing, allocator) + } +} + +@(require_results) +bufs_to_process :: proc(bufs: ^Bufs, orig: [][]byte, processed: int) -> (working: [][]byte, total: int) { + if len(orig) > 1 { + // Reset to length and contents of backing, so a previous modification is removed. + (^runtime.Raw_Slice)(&bufs.working.big).len = len(orig) + copy(bufs.working.big, orig) + working = bufs.working.big + } else { + bufs.working.small = {orig[0]} + working = bufs.working.small[:] + } + + working = slice.advance_slices(working, processed) + working, total = constraint_bufs_to_max_rw(working) + return +} + +@(require_results) +constraint_bufs_to_max_rw :: proc(bufs: [][]byte) -> (constrained: [][]byte, total: int) { + for buf in bufs { + total += len(buf) + } + + constrained = bufs + for n := total; n > MAX_RW; { + last := &constrained[len(constrained)-1] + take := min(len(last), n-MAX_RW) + last^ = last[:take] + if len(last) == 0 { + constrained = constrained[:len(constrained)-1] + } + n -= take + } + + return +} diff --git a/core/nbio/impl_linux.odin b/core/nbio/impl_linux.odin new file mode 100644 index 000000000..f4b200830 --- /dev/null +++ b/core/nbio/impl_linux.odin @@ -0,0 +1,1465 @@ +#+private file +package nbio + +import "base:intrinsics" + +import "core:container/pool" +import "core:container/queue" +import "core:mem" +import "core:net" +import "core:strings" +import "core:sys/linux" +import "core:sys/linux/uring" +import "core:time" + +@(private="package") +_FULLY_SUPPORTED :: true + +@(private="package") +_Event_Loop :: struct { + ring: uring.Ring, + // Ready to be submitted to kernel, if kernel is full. + unqueued: queue.Queue(^Operation), + // Ready to run callbacks, mainly next tick, some other ops that error outside the kernel. + completed: queue.Queue(^Operation), + wake: ^Operation, +} + +@(private="package") +_Handle :: linux.Fd + +@(private="package") +_CWD :: linux.AT_FDCWD + +@(private="package") +MAX_RW :: mem.Gigabyte + +@(private="package") +_Operation :: struct { + removal: ^Operation, + sqe: ^linux.IO_Uring_SQE, + expires: linux.Time_Spec, +} + +@(private="package") +_Accept :: struct { + sockaddr: linux.Sock_Addr_Any, + sockaddr_len: i32, +} + +@(private="package") +_Close :: struct {} + +@(private="package") +_Dial :: struct { + sockaddr: linux.Sock_Addr_Any, +} + +@(private="package") +_Read :: struct {} + +@(private="package") +_Write :: struct {} + +Sock_Addr_Ip :: struct #raw_union { + using _: struct { + family: linux.Address_Family, + port: u16be, + }, + using ipv4: linux.Sock_Addr_In, + using ipv6: linux.Sock_Addr_In6, +} + +@(private="package") +_Send :: struct { + endpoint: Sock_Addr_Ip, + msghdr: linux.Msg_Hdr, + bufs: Bufs, +} + +@(private="package") +_Recv :: struct { + addr_out: Sock_Addr_Ip, + msghdr: linux.Msg_Hdr, + bufs: Bufs, +} + +@(private="package") +_Timeout :: struct { + expires: linux.Time_Spec, +} + +@(private="package") +_Poll :: struct {} + +@(private="package") +_Remove :: struct { + target: ^Operation, +} + +@(private="package") +_Link_Timeout :: struct { + target: ^Operation, + expires: linux.Time_Spec, +} + +@(private="package") +_Send_File :: struct { + len: int, + pipe: Handle, + + splice: ^Operation, +} + +@(private="package") +_Splice :: struct { + off: int, + len: int, + file: Handle, + pipe: Handle, + + written: int, + + sendfile: ^Operation, +} + +@(private="package") +_Open :: struct { + cpath: cstring, +} + +@(private="package") +_Stat :: struct { + buf: linux.Statx, +} + +@(private="package") +_init :: proc(l: ^Event_Loop, alloc: mem.Allocator) -> (err: General_Error) { + params := uring.DEFAULT_PARAMS + params.flags += {.SUBMIT_ALL, .COOP_TASKRUN, .SINGLE_ISSUER} + + uerr := uring.init(&l.ring, ¶ms, QUEUE_SIZE) + if uerr != nil { + err = General_Error(uerr) + return + } + defer if err != nil { uring.destroy(&l.ring) } + + if perr := queue.init(&l.unqueued, allocator = alloc); perr != nil { + err = .Allocation_Failed + return + } + defer if err != nil { queue.destroy(&l.unqueued) } + + if perr := queue.init(&l.completed, allocator = alloc); perr != nil { + err = .Allocation_Failed + return + } + defer if err != nil { queue.destroy(&l.completed) } + + set_up_wake_up(l) or_return + + return + + set_up_wake_up :: proc(l: ^Event_Loop) -> General_Error { + wakefd, wakefd_err := linux.eventfd(0, {.SEMAPHORE, .CLOEXEC, .NONBLOCK}) + if wakefd_err != nil { + return General_Error(wakefd_err) + } + + op, alloc_err := new(Operation, l.allocator) + if alloc_err != nil { + linux.close(wakefd) + return .Allocation_Failed + } + + l.wake = op + l.wake.detached = true + l.wake.l = l + l.wake.type = .Read + l.wake.cb = wake_up_callback + l.wake.read.handle = wakefd + l.wake.read.buf = ([^]byte)(&l.wake.user_data)[:8] + _exec(l.wake) + + return nil + } + + wake_up_callback :: proc(op: ^Operation) { + assert(op.type == .Read) + assert(op == op.l.wake) + assert(op.read.err == nil) + assert(op.read.read == 8) + value := intrinsics.unaligned_load((^u64)(&op.user_data)) + assert(value > 0) + debug(int(value), "wake_up calls handled") + + op.read.read = 0 + op.user_data = {} + _exec(op) + } +} + +@(private="package") +_destroy :: proc(l: ^Event_Loop) { + linux.close(l.wake.read.handle) + free(l.wake, l.allocator) + + queue.destroy(&l.unqueued) + queue.destroy(&l.completed) + uring.destroy(&l.ring) +} + +@(private="package") +__tick :: proc(l: ^Event_Loop, timeout: time.Duration) -> General_Error { + debug("tick") + + // Execute completed operations, mostly next tick ops, also some other ops that may error before + // adding it to the Uring. + n := queue.len(l.completed) + if n > 0 { + l.now = time.now() + for _ in 0 ..< n { + completed := queue.pop_front(&l.completed) + if completed._impl.removal == nil { + completed.cb(completed) + } else if completed._impl.removal != (^Operation)(REMOVED) { + completed._impl.removal._remove.target = nil + } + if !completed.detached { + pool.put(&l.operation_pool, completed) + } + } + } + + err := _flush_submissions(l, timeout) + if err != nil { return General_Error(err) } + + l.now = time.now() + + err = _flush_completions(l, false) + if err != nil { return General_Error(err) } + + return nil + + _flush_completions :: proc(l: ^Event_Loop, wait: bool) -> linux.Errno { + wait := wait + cqes: [128]linux.IO_Uring_CQE = --- + for { + completed, err := uring.copy_cqes(&l.ring, cqes[:], 1 if wait else 0) + if err == .EINTR { + continue + } else if err != nil { + return err + } + + _flush_unqueued(l) + + if completed > 0 { + debug(int(completed), "operations returned from uring") + } + + for cqe in cqes[:completed] { + assert(cqe.user_data != 0) + op, is_timeout := unpack_operation(cqe.user_data) + if is_timeout { + link_timeout_callback(op, cqe.res) + } else { + handle_completed(op, cqe.res) + } + } + + if completed < len(cqes) { break } + + debug("more events ready than our results buffer handles, getting more") + wait = false + } + + return nil + } + + _flush_submissions :: proc(l: ^Event_Loop, timeout: time.Duration) -> linux.Errno { + for { + ts: linux.Time_Spec + ts.time_nsec = uint(timeout) + _, err := uring.submit(&l.ring, 0 if timeout == 0 else 1, nil if timeout < 0 else &ts) + #partial switch err { + case .NONE, .ETIME: + case .EINTR: + warn("uring interrupted") + continue + case .ENOMEM: + // It's full, wait for at least one operation to complete and try again. + warn("could not flush submissions, ENOMEM, waiting for operations to complete before continuing") + ferr := _flush_completions(l, true) + if ferr != nil { return ferr } + continue + case: + return err + } + + break + } + + return nil + } + + _flush_unqueued :: proc(l: ^Event_Loop) { + n := queue.len(l.unqueued) + for _ in 0.. (handle: Handle, err: FS_Error) { + if path == "" { + err = .Invalid_Argument + return + } + + cpath, cerr := strings.clone_to_cstring(path, l.allocator) + if cerr != nil { + err = .Allocation_Failed + return + } + defer delete(cpath, l.allocator) + + sys_flags := linux.Open_Flags{.NOCTTY, .CLOEXEC, .NONBLOCK} + + if .Write in mode { + if .Read in mode { + sys_flags += {.RDWR} + } else { + sys_flags += {.WRONLY} + } + } + + if .Append in mode { sys_flags += {.APPEND} } + if .Create in mode { sys_flags += {.CREAT} } + if .Excl in mode { sys_flags += {.EXCL} } + if .Sync in mode { sys_flags += {.DSYNC} } + if .Trunc in mode { sys_flags += {.TRUNC} } + // if .Inheritable in mode { sys_flags -= {.CLOEXEC} } + + errno: linux.Errno + handle, errno = linux.openat(dir, cpath, sys_flags, transmute(linux.Mode)perm) + if errno != nil { + err = FS_Error(errno) + } + + return +} + +@(private="package") +_create_socket :: proc( + _: ^Event_Loop, + family: Address_Family, + protocol: Socket_Protocol, +) -> ( + socket: Any_Socket, + err: Create_Socket_Error, +) { + socket = net.create_socket(family, protocol) or_return + // NOTE: this doesn't seem needed with io uring. + // defer if err != nil { net.close(socket) } + // net.set_blocking(socket, false) or_return + return +} + +@(private="package") +_listen :: proc(socket: TCP_Socket, backlog := 1000) -> Listen_Error { + err := linux.listen(linux.Fd(socket), i32(backlog)) + if err != nil { + return net._listen_error(err) + } + return nil +} + +@(private="package") +_remove :: proc(target: ^Operation) { + target := target + assert(target != nil) + + if target._impl.removal != nil { + return + } + + op := _prep(target.l, proc(_: ^Operation) {}, ._Remove) + op._remove.target = target + + target._impl.removal = op + + enqueue(op, uring.async_cancel( + &op.l.ring, + u64(uintptr(target)), + u64(uintptr(op)), + )) +} + +@(private="package") +_associate_handle :: proc(handle: uintptr, l: ^Event_Loop) -> (Handle, Association_Error) { + // Works by default. + return Handle(handle), nil +} + +@(private="package") +_associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop) -> Association_Error { + // Works by default. + return nil +} + +@(private="package") +_wake_up :: proc(l: ^Event_Loop) { + assert(l != &_tls_event_loop) + one: u64 = 1 + // Called from another thread, in which we can't use the uring. + n, err := linux.write(l.wake.read.handle, ([^]byte)(&one)[:size_of(one)]) + // Shouldn't fail. + assert(err == nil) + assert(n == 8) +} + +@(private="package") +_yield :: proc() { + linux.sched_yield() +} + +// Start file private. + +// The size of the IO Uring queues. +QUEUE_SIZE :: #config(ODIN_NBIO_QUEUE_SIZE, 2048) +#assert(QUEUE_SIZE <= uring.MAX_ENTRIES) + +#assert(size_of(Operation) <= 384) // Just so we see when we make it bigger. +#assert(size_of(Specifics) <= 288) // Just so we see when we make it bigger. + +REMOVED :: rawptr(max(uintptr)-1) + +handle_completed :: proc(op: ^Operation, res: i32) { + debug("handling", op.type, "result", int(res)) + + switch op.type { + case .Accept: + accept_callback(op, res) + case .Dial: + dial_callback(op, res) + case .Timeout: + timeout_callback(op, res) + case .Write: + if !write_callback(op, res) { return } + case .Read: + if !read_callback(op, res) { return } + case .Close: + close_callback(op, res) + case .Poll: + poll_callback(op, res) + case .Send: + if !send_callback(op, res) { return } + maybe_callback(op) + bufs_delete(&op.send._impl.bufs, op.send.bufs, op.l.allocator) + cleanup(op) + return + case .Recv: + if !recv_callback(op, res) { return } + maybe_callback(op) + bufs_delete(&op.recv._impl.bufs, op.recv.bufs, op.l.allocator) + cleanup(op) + return + case .Open: + open_callback(op, res) + case .Stat: + stat_callback(op, res) + case .Send_File: + if !sendfile_callback(op, res) { return } + case ._Splice: + if !splice_callback(op, res) { return } + case ._Remove: + if !remove_callback(op, res) { return } + case ._Link_Timeout: + unreachable() + case .None: + fallthrough + case: + panic("corrupted operation") + } + + maybe_callback(op) + cleanup(op) + + maybe_callback :: proc(op: ^Operation) { + if op._impl.removal == nil { + debug("done, calling back", op.type) + op.cb(op) + } else if op._impl.removal == (^Operation)(REMOVED) { + debug("done but was cancelled by remove", op.type) + } else { + debug("done but has removal pending", op.type) + // If the remove callback sees their target is nil, they know it is done already. + op._impl.removal._remove.target = nil + } + } + + cleanup :: proc(op: ^Operation) { + if !op.detached { + pool.put(&op.l.operation_pool, op) + } + } +} + +enqueue :: proc(op: ^Operation, sqe: ^linux.IO_Uring_SQE, ok: bool) { + assert(uintptr(op) & LINK_TIMEOUT_MASK == 0) + debug("enqueue", op.type) + if !ok { + warn("queueing for next tick because the ring is full, queue size may need increasing") + pok, _ := queue.push_back(&op.l.unqueued, op) + ensure(pok, "unqueued queue allocation failure") + return + } + + op._impl.sqe = sqe +} + +LINK_TIMEOUT_MASK :: 1 + +link_timeout :: proc(target: ^Operation, expires: time.Time) { + if expires == {} { + return + } + + // If the last op was queued because kernel is full, return. + if target._impl.sqe == nil { + assert(queue.len(target.l.unqueued) > 0 && queue.back_ptr(&target.l.unqueued)^ == target) + return + } + + target._impl.sqe.flags += {.IO_LINK} + target._impl.expires = ns_to_time_spec(expires._nsec) + + // Tag the pointer as a timeout. + p := uintptr(target) + assert(p & LINK_TIMEOUT_MASK == 0) + p |= LINK_TIMEOUT_MASK + + _, ok := uring.link_timeout( + &target.l.ring, + u64(p), + &target._impl.expires, + {.ABS, .REALTIME}, + ) + // If the target wasn't queued, the link timeout should not need to be queued, because uring + // leaves one spot specifically for a link. + assert(ok) +} + +link_timeout_callback :: proc(op: ^Operation, res: i32) { + err := linux.Errno(-res) + if err != nil && err != .ETIME && err != .ECANCELED { + panic("unexpected nbio.link_timeout() error") + } +} + +unpack_operation :: #force_inline proc(user_data: u64) -> (op: ^Operation, timed_out: bool) { + p := uintptr(user_data) + return (^Operation)(p &~ LINK_TIMEOUT_MASK), bool(p & LINK_TIMEOUT_MASK) +} + +@(require_results) +remove_callback :: proc(op: ^Operation, res: i32) -> bool { + assert(op.type == ._Remove) + err := linux.Errno(-res) + + target := op._remove.target + if target == nil { + debug("remove target nil, already handled") + return true + } + + assert(target.type != .None) + assert(target._impl.removal == op) + + if err == .ENOENT { + debug("remove ENOENT, trying again") + + enqueue(op, uring.async_cancel( + &op.l.ring, + u64(uintptr(target)), + u64(uintptr(op)), + )) + + return false + } else if err == .EALREADY { + debug("remove is accepted and will be tried") + } else if err != nil { + assert(false, "unexpected nbio.remove() error") + } + + // Set to sentinel so nothing references the operation that will be reused. + target._impl.removal = (^Operation)(REMOVED) + return true +} + +accept_exec :: proc(op: ^Operation) { + assert(op.type == .Accept) + op.accept._impl.sockaddr_len = size_of(op.accept._impl.sockaddr) + enqueue(op, uring.accept( + &op.l.ring, + u64(uintptr(op)), + linux.Fd(op.accept.socket), + &op.accept._impl.sockaddr, + &op.accept._impl.sockaddr_len, + {}, + )) + link_timeout(op, op.accept.expires) +} + +accept_callback :: proc(op: ^Operation, res: i32) { + assert(op.type == .Accept) + if res < 0 { + errno := linux.Errno(-res) + #partial switch errno { + case .ECANCELED: + op.accept.err = .Timeout + case: + op.accept.err = net._accept_error(errno) + } + + return + } + + op.accept.client = TCP_Socket(res) + // net.set_blocking(net.TCP_Socket(op.accept.client), false) + op.accept.client_endpoint = sockaddr_storage_to_endpoint_any(&op.accept._impl.sockaddr) +} + +dial_exec :: proc(op: ^Operation) { + assert(op.type == .Dial) + if op.dial.socket == {} { + if op.dial.endpoint.port == 0 { + op.dial.err = .Port_Required + queue.push_back(&op.l.completed, op) + return + } + + sock, err := create_socket(net.family_from_endpoint(op.dial.endpoint), .TCP) + if err != nil { + op.dial.err = err + queue.push_back(&op.l.completed, op) + return + } + + op.dial.socket = sock.(TCP_Socket) + op.dial._impl.sockaddr = endpoint_to_sockaddr_any(op.dial.endpoint) + } + + enqueue(op, uring.connect( + &op.l.ring, + u64(uintptr(op)), + linux.Fd(op.dial.socket), + &op.dial._impl.sockaddr, + )) + link_timeout(op, op.dial.expires) +} + +dial_callback :: proc(op: ^Operation, res: i32) { + assert(op.type == .Dial) + errno := linux.Errno(-res) + if errno != nil { + #partial switch errno { + case .ECANCELED: + op.dial.err = Dial_Error.Timeout + case: + op.dial.err = net._dial_error(errno) + } + close(op.dial.socket) + } +} + +timeout_exec :: proc(op: ^Operation) { + assert(op.type == .Timeout) + if op.timeout.duration <= 0 { + queue.push_back(&op.l.completed, op) + return + } + + expires := time.time_add(op.l.now, op.timeout.duration) + op.timeout._impl.expires = ns_to_time_spec(expires._nsec) + + enqueue(op, uring.timeout( + &op.l.ring, + u64(uintptr(op)), + &op.timeout._impl.expires, + 0, + {.ABS, .REALTIME}, + )) +} + +timeout_callback :: proc(op: ^Operation, res: i32) { + if res < 0 { + errno := linux.Errno(-res) + #partial switch errno { + case .ETIME, .ECANCELED: // OK. + case: + debug("unexpected timeout error:", int(errno)) + panic("unexpected timeout error") + } + } +} + +close_exec :: proc(op: ^Operation) { + assert(op.type == .Close) + + fd: linux.Fd + switch closable in op.close.subject { + case Handle: fd = linux.Fd(closable) + case TCP_Socket: fd = linux.Fd(closable) + case UDP_Socket: fd = linux.Fd(closable) + case: op.close.err = .Invalid_Argument; return + } + + enqueue(op, uring.close( + &op.l.ring, + u64(uintptr(op)), + fd, + )) +} + +close_callback :: proc(op: ^Operation, res: i32) { + assert(op.type == .Close) + op.close.err = FS_Error(linux.Errno(-res)) +} + +recv_exec :: proc(op: ^Operation) { + assert(op.type == .Recv) + + if op.recv.err != nil { + queue.push_back(&op.l.completed, op) + return + } + + bufs, _ := bufs_to_process(&op.recv._impl.bufs, op.recv.bufs, op.recv.received) + op.recv._impl.msghdr.iov = transmute([]linux.IO_Vec)bufs + + sock: linux.Fd + switch socket in op.recv.socket { + case TCP_Socket: + sock = linux.Fd(socket) + case UDP_Socket: + sock = linux.Fd(socket) + op.recv._impl.msghdr.name = &op.recv._impl.addr_out + op.recv._impl.msghdr.namelen = size_of(op.recv._impl.addr_out) + } + + enqueue(op, uring.recvmsg( + &op.l.ring, + u64(uintptr(op)), + linux.Fd(sock), + &op.recv._impl.msghdr, + {.NOSIGNAL}, + )) + link_timeout(op, op.recv.expires) +} + +@(require_results) +recv_callback :: proc(op: ^Operation, res: i32) -> bool { + assert(op.type == .Recv) + + if res < 0 { + errno := linux.Errno(-res) + switch sock in op.recv.socket { + case TCP_Socket: + #partial switch errno { + case .ECANCELED: + op.recv.err = TCP_Recv_Error.Timeout + case: + op.recv.err = net._tcp_recv_error(errno) + } + case UDP_Socket: + #partial switch errno { + case .ECANCELED: + op.recv.err = UDP_Recv_Error.Timeout + case: + op.recv.err = net._udp_recv_error(errno) + } + } + + return true + } + + op.recv.received += int(res) + + switch sock in op.recv.socket { + case TCP_Socket: + if res == 0 { + // Connection closed. + return true + } + + if op.recv.all { + total: int + for buf in op.recv.bufs { + total += len(buf) + } + + if op.recv.received < total { + recv_exec(op) + return false + } + } + + case UDP_Socket: + op.recv.source = sockaddr_storage_to_endpoint_ip(&op.recv._impl.addr_out) + } + + return true +} + +send_exec :: proc(op: ^Operation) { + assert(op.type == .Send) + + if op.send.err != nil { + queue.push_back(&op.l.completed, op) + return + } + + bufs, _ := bufs_to_process(&op.send._impl.bufs, op.send.bufs, op.send.sent) + op.send._impl.msghdr.iov = transmute([]linux.IO_Vec)bufs + + sock: linux.Fd + switch socket in op.send.socket { + case TCP_Socket: + sock = linux.Fd(socket) + case UDP_Socket: + sock = linux.Fd(socket) + op.send._impl.endpoint = endpoint_to_sockaddr_ip(op.send.endpoint) + op.send._impl.msghdr.name = &op.send._impl.endpoint + op.send._impl.msghdr.namelen = size_of(op.send._impl.endpoint) + } + + enqueue(op, uring.sendmsg( + &op.l.ring, + u64(uintptr(op)), + sock, + &op.send._impl.msghdr, + {.NOSIGNAL}, + )) + link_timeout(op, op.send.expires) +} + +@(require_results) +send_callback :: proc(op: ^Operation, res: i32) -> bool { + assert(op.type == .Send) + if res < 0 { + errno := linux.Errno(-res) + switch sock in op.send.socket { + case TCP_Socket: + #partial switch errno { + case .ECANCELED: + op.send.err = TCP_Send_Error.Timeout + case: + op.send.err = net._tcp_send_error(errno) + } + case UDP_Socket: + #partial switch errno { + case .ECANCELED: + op.send.err = UDP_Send_Error.Timeout + case: + op.send.err = net._udp_send_error(errno) + } + case: panic("corrupted socket") + } + + return true + } + + op.send.sent += int(res) + + if op.send.all { + total: int + for buf in op.send.bufs { + total += len(buf) + } + + if op.send.sent < total { + assert(res > 0) + send_exec(op) + return false + } + } + + return true +} + +write_exec :: proc(op: ^Operation) { + assert(op.type == .Write) + + buf := op.write.buf[op.write.written:] + buf = buf[:min(MAX_RW, len(buf))] + + enqueue(op, uring.write( + &op.l.ring, + u64(uintptr(op)), + op.write.handle, + buf, + u64(op.write.offset) + u64(op.write.written), + )) + link_timeout(op, op.write.expires) +} + +@(require_results) +write_callback :: proc(op: ^Operation, res: i32) -> bool { + if res < 0 { + errno := linux.Errno(-res) + op.write.err = FS_Error(errno) + return true + } + + op.write.written += int(res) + + if op.write.all && op.write.written < len(op.write.buf) { + write_exec(op) + return false + } + + return true +} + +read_exec :: proc(op: ^Operation) { + assert(op.type == .Read) + + buf := op.read.buf[op.read.read:] + buf = buf[:min(MAX_RW, len(buf))] + + enqueue(op, uring.read( + &op.l.ring, + u64(uintptr(op)), + op.read.handle, + buf, + u64(op.read.offset) + u64(op.read.read), + )) + link_timeout(op, op.read.expires) +} + +@(require_results) +read_callback :: proc(op: ^Operation, res: i32) -> bool { + if res < 0 { + errno := linux.Errno(-res) + op.read.err = FS_Error(errno) + return true + } else if res == 0 { + if op.read.read == 0 { + op.read.err = .EOF + } + return true + } + + op.read.read += int(res) + + if op.read.all && op.read.read < len(op.read.buf) { + read_exec(op) + return false + } + + return true +} + +poll_exec :: proc(op: ^Operation) { + assert(op.type == .Poll) + + events: linux.Fd_Poll_Events + switch op.poll.event { + case .Receive: events = { .IN } + case .Send: events = { .OUT } + } + + fd: linux.Fd + switch sock in op.poll.socket { + case TCP_Socket: fd = linux.Fd(sock) + case UDP_Socket: fd = linux.Fd(sock) + } + + enqueue(op, uring.poll_add( + &op.l.ring, + u64(uintptr(op)), + fd, + events, + {}, + )) + link_timeout(op, op.poll.expires) +} + +poll_callback :: proc(op: ^Operation, res: i32) { + if res < 0 { + errno := linux.Errno(-res) + #partial switch errno { + case .NONE: // no-op + case .ECANCELED: + op.poll.result = .Timeout + case .EINVAL, .EFAULT, .EBADF: + op.poll.result = .Invalid_Argument + case: + op.poll.result = .Error + } + + return + } + + op.poll.result = .Ready +} + +/* +`sendfile` is implemented with 2 splices over a pipe. + +Splice A: from file to pipe +Splice B: from pipe to socket (optionally linked to a timeout) + +The splices are hard-linked which means A completes before B. +B could get an `EWOULDBLOCK`, which is when the remote end has not read enough of the socket data yet. +In that case we enqueue a poll on the socket and continue when that completes. +A shouldn't get `EWOULDBLOCK`, but as a cautionary measure we handle it. + +The timeout is either linked to the splice B op, or the poll op, either of these is also always in progress in the kernel. +*/ +sendfile_exec :: proc(op: ^Operation, splice := true) { + assert(op.type == .Send_File) + + splice_done := !splice + if splice_op := op.sendfile._impl.splice; splice && splice_op != nil { + splice_done = splice_op._splice.written == splice_op._splice.len + } + + debug("sendfile_exec") + + if op.sendfile._impl.splice == nil { + // First stat for the file size. + if op.sendfile.nbytes == SEND_ENTIRE_FILE { + debug("sendfile SEND_ENTIRE_FILE, doing stat") + + stat_poly(op.sendfile.file, op, proc(stat_op: ^Operation, sendfile_op: ^Operation) { + if stat_op.stat.err != nil { + sendfile_op.sendfile.err = stat_op.stat.err + } else if stat_op.stat.type != .Regular { + sendfile_op.sendfile.err = FS_Error.Invalid_Argument + } else { + sendfile_op.sendfile.nbytes = int(i64(stat_op.stat.size) - i64(sendfile_op.sendfile.offset)) + if sendfile_op.sendfile.nbytes <= 0 { + sendfile_op.sendfile.err = FS_Error.Invalid_Argument + } + } + + if sendfile_op.sendfile.err != nil { + handle_completed(sendfile_op, 0) + return + } + + sendfile_exec(sendfile_op) + }) + return + } + + debug("sendfile setting up") + + rw: [2]linux.Fd + err := linux.pipe2(&rw, {.NONBLOCK, .CLOEXEC}) + if err != nil { + op.sendfile.err = FS_Error(err) + queue.push_back(&op.l.completed, op) + return + } + + splice_op := _prep(op.l, proc(_: ^Operation) { debug("sendfile splice helper callback") }, ._Splice) + splice_op._splice.sendfile = op + splice_op._splice.file = op.sendfile.file + splice_op._splice.pipe = rw[1] + splice_op._splice.off = op.sendfile.offset + splice_op._splice.len = op.sendfile.nbytes + + op.sendfile._impl.splice = splice_op + op.sendfile._impl.pipe = rw[0] + op.sendfile._impl.len = op.sendfile.nbytes + } + + splice_op: ^Operation + if !splice_done { + splice_op = op.sendfile._impl.splice + enqueue(splice_op, uring.splice( + &splice_op.l.ring, + u64(uintptr(splice_op)), + splice_op._splice.file, + i64(splice_op._splice.off) + i64(splice_op._splice.written), + splice_op._splice.pipe, + -1, + u32(min(splice_op._splice.len - splice_op._splice.written, MAX_RW)), + {.NONBLOCK}, + )) + } + + b, b_added := uring.splice( + &op.l.ring, + u64(uintptr(op)), + op.sendfile._impl.pipe, + -1, + linux.Fd(op.sendfile.socket), + -1, + u32(min(op.sendfile._impl.len - op.sendfile.sent, MAX_RW)), + {.NONBLOCK}, + ) + if !splice_done && b_added { + assert(splice_op._impl.sqe != nil) // if b was added successfully, a should've been too. + // Makes sure splice A (file to pipe) completes before splice B (pipe to socket). + splice_op._impl.sqe.flags += {.IO_HARDLINK} + } + enqueue(op, b, b_added) + + link_timeout(op, op.sendfile.expires) +} + +@(require_results) +splice_callback :: proc(op: ^Operation, res: i32) -> bool { + assert(op.type == ._Splice) + + if res < 0 { + errno := linux.Errno(-res) + #partial switch errno { + case .EAGAIN: + // Splice A (from file to pipe) would block, this means the buffer is full and it first needs + // to be sent over the socket by splice B (from pipe to socket). + // So we don't do anything here, once a splice B completes a new splice A will be created. + + case: + // Splice A (from file to pipe) error, we need to close the pipes, cancel the pending splice B, + // and call the callback with the error. + + debug("sendfile helper splice error, closing pipe") + + close(op._splice.pipe) + + // This is nil if this is a cancel originating from the sendfile. + // This is not nil if it is an actual error that happened on this splice. + sendfile_op := op._splice.sendfile + if sendfile_op != nil { + debug("sendfile helper splice error, cancelling main sendfile") + assert(sendfile_op.type == .Send_File) + + sendfile_op.sendfile._impl.splice = nil + sendfile_op.sendfile.err = FS_Error(errno) + } + } + + return true + } + + op._splice.written += int(res) + + sendfile_op := op._splice.sendfile + if sendfile_op != nil { + if op._splice.written < sendfile_op.sendfile.nbytes { + return false + } + + sendfile_op.sendfile._impl.splice = nil + } + + assert(op._splice.pipe > 0) + close(op._splice.pipe) + + debug("sendfile helper splice completely done") + return true +} + +@(require_results) +sendfile_callback :: proc(op: ^Operation, res: i32) -> bool { + assert(op.type == .Send_File) + + if op.sendfile.err == nil && res < 0 { + errno := linux.Errno(-res) + #partial switch errno { + case .EAGAIN: + // Splice B (from pipe to socket) would block. We are waiting on the remote to read more + // of our buffer before we can send more to it. + // We use a poll to find out when this is. + + debug("sendfile needs to poll") + + poll_op := poll_poly(op.sendfile.socket, .Send, op, proc(poll_op: ^Operation, sendfile_op: ^Operation) { + #partial switch poll_op.poll.result { + case .Ready: + // Do not enqueue a splice right away, we know there is at least one splice call worth of data in the kernel buffer. + sendfile_exec(sendfile_op, splice=false) + return + + case .Timeout: + sendfile_op.sendfile.err = TCP_Send_Error.Timeout + case: + sendfile_op.sendfile.err = TCP_Send_Error.Unknown + } + + debug("sendfile poll error") + handle_completed(sendfile_op, 0) + }) + + link_timeout(poll_op, op.sendfile.expires) + return false + + case .ECANCELED: + op.sendfile.err = TCP_Send_Error.Timeout + case: + op.sendfile.err = net._tcp_send_error(errno) + } + } + + if op.sendfile.err != nil { + debug("sendfile error") + + if op.sendfile._impl.pipe > 0 { + close(op.sendfile._impl.pipe) + } + + splice_op := op.sendfile._impl.splice + if splice_op != nil { + assert(splice_op.type == ._Splice) + splice_op._splice.sendfile = nil + _remove(splice_op) + } + + return true + } + + op.sendfile.sent += int(res) + if op.sendfile.sent < op.sendfile._impl.len { + debug("sendfile not completely done yet") + sendfile_exec(op) + if op.sendfile.progress_updates { op.cb(op) } + return false + } + + debug("sendfile completely done") + return true +} + +open_exec :: proc(op: ^Operation) { + assert(op.type == .Open) + + sys_flags := linux.Open_Flags{.NOCTTY, .CLOEXEC, .NONBLOCK} + + if .Write in op.open.mode { + if .Read in op.open.mode { + sys_flags += {.RDWR} + } else { + sys_flags += {.WRONLY} + } + } + + if .Append in op.open.mode { sys_flags += {.APPEND} } + if .Create in op.open.mode { sys_flags += {.CREAT} } + if .Excl in op.open.mode { sys_flags += {.EXCL} } + if .Sync in op.open.mode { sys_flags += {.DSYNC} } + if .Trunc in op.open.mode { sys_flags += {.TRUNC} } + // if .Inheritable in op.open.mode { sys_flags -= {.CLOEXEC} } + + cpath, err := strings.clone_to_cstring(op.open.path, op.l.allocator) + if err != nil { + op.open.err = .Allocation_Failed + queue.push_back(&op.l.completed, op) + return + } + op.open._impl.cpath = cpath + + enqueue(op, uring.openat( + &op.l.ring, + u64(uintptr(op)), + linux.Fd(op.open.dir), + op.open._impl.cpath, + transmute(linux.Mode)op.open.perm, + sys_flags, + )) +} + +open_callback :: proc(op: ^Operation, res: i32) { + assert(op.type == .Open) + + delete(op.open._impl.cpath, op.l.allocator) + + if res < 0 { + errno := linux.Errno(-res) + op.open.err = FS_Error(errno) + return + } + + op.open.handle = Handle(res) +} + +stat_exec :: proc(op: ^Operation) { + assert(op.type == .Stat) + + enqueue(op, uring.statx( + &op.l.ring, + u64(uintptr(op)), + op.stat.handle, + "", + {.EMPTY_PATH}, + {.TYPE, .SIZE}, + &op.stat._impl.buf, + )) +} + +stat_callback :: proc(op: ^Operation, res: i32) { + assert(op.type == .Stat) + + if res < 0 { + errno := linux.Errno(-res) + op.stat.err = FS_Error(errno) + return + } + + type := File_Type.Regular + switch op.stat._impl.buf.mode & linux.S_IFMT { + case linux.S_IFBLK, linux.S_IFCHR: type = .Device + case linux.S_IFDIR: type = .Directory + case linux.S_IFIFO: type = .Pipe_Or_Socket + case linux.S_IFLNK: type = .Symlink + case linux.S_IFREG: type = .Regular + case linux.S_IFSOCK: type = .Pipe_Or_Socket + } + + op.stat.type = type + op.stat.size = i64(op.stat._impl.buf.size) +} + +@(require_results) +sockaddr_storage_to_endpoint_ip :: proc(addr: ^Sock_Addr_Ip) -> (ep: Endpoint) { + #partial switch addr.family { + case .INET: + return Endpoint { + address = IP4_Address(addr.sin_addr), + port = int(addr.sin_port), + } + case .INET6: + return Endpoint { + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = int(addr.sin6_port), + } + case: + return {} + } +} + +@(require_results) +sockaddr_storage_to_endpoint_any :: proc(addr: ^linux.Sock_Addr_Any) -> (ep: Endpoint) { + #partial switch addr.family { + case .INET: + return Endpoint { + address = IP4_Address(addr.sin_addr), + port = int(addr.sin_port), + } + case .INET6: + return Endpoint { + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = int(addr.sin6_port), + } + case: + return {} + } +} + +@(require_results) +endpoint_to_sockaddr_ip :: proc(ep: Endpoint) -> (sockaddr: Sock_Addr_Ip) { + switch a in ep.address { + case IP4_Address: + sockaddr.sin_family = .INET + sockaddr.sin_port = u16be(ep.port) + sockaddr.sin_addr = cast([4]u8)a + return + case IP6_Address: + sockaddr.sin6_family = .INET6 + sockaddr.sin6_port = u16be(ep.port) + sockaddr.sin6_addr = transmute([16]u8)a + return + } + + unreachable() +} + +@(require_results) +endpoint_to_sockaddr_any :: proc(ep: Endpoint) -> (sockaddr: linux.Sock_Addr_Any) { + switch a in ep.address { + case IP4_Address: + sockaddr.sin_family = .INET + sockaddr.sin_port = u16be(ep.port) + sockaddr.sin_addr = cast([4]u8)a + return + case IP6_Address: + sockaddr.sin6_family = .INET6 + sockaddr.sin6_port = u16be(ep.port) + sockaddr.sin6_addr = transmute([16]u8)a + return + } + + unreachable() +} + +@(require_results) +ns_to_time_spec :: proc(nsec: i64) -> linux.Time_Spec { + NANOSECONDS_PER_SECOND :: 1e9 + return { + time_sec = uint(nsec / NANOSECONDS_PER_SECOND), + time_nsec = uint(nsec % NANOSECONDS_PER_SECOND), + } +} diff --git a/core/nbio/impl_others.odin b/core/nbio/impl_others.odin new file mode 100644 index 000000000..0a4564454 --- /dev/null +++ b/core/nbio/impl_others.odin @@ -0,0 +1,218 @@ +#+build !darwin +#+build !freebsd +#+build !openbsd +#+build !netbsd +#+build !linux +#+build !windows +#+private +package nbio + +import "core:container/avl" +import "core:container/pool" +import "core:container/queue" +import "core:mem" +import "core:slice" +import "core:time" + +_FULLY_SUPPORTED :: false + +_Event_Loop :: struct { + completed: queue.Queue(^Operation), + timeouts: avl.Tree(^Operation), +} + +_Handle :: uintptr + +_CWD :: Handle(-100) + +MAX_RW :: mem.Gigabyte + +_Operation :: struct { + removed: bool, +} + +_Accept :: struct {} + +_Close :: struct {} + +_Dial :: struct {} + +_Recv :: struct { + small_bufs: [1][]byte, +} + +_Send :: struct { + small_bufs: [1][]byte, +} + +_Read :: struct {} + +_Write :: struct {} + +_Timeout :: struct { + expires: time.Time, +} + +_Poll :: struct {} + +_Send_File :: struct {} + +_Open :: struct {} + +_Stat :: struct {} + +_Splice :: struct {} + +_Remove :: struct {} + +_Link_Timeout :: struct {} + +_init :: proc(l: ^Event_Loop, allocator: mem.Allocator) -> (rerr: General_Error) { + l.completed.data.allocator = allocator + + avl.init_cmp(&l.timeouts, timeouts_cmp, allocator) + + return nil + + timeouts_cmp :: #force_inline proc(a, b: ^Operation) -> slice.Ordering { + switch { + case a.timeout._impl.expires._nsec < b.timeout._impl.expires._nsec: + return .Less + case a.timeout._impl.expires._nsec > b.timeout._impl.expires._nsec: + return .Greater + case uintptr(a) < uintptr(b): + return .Less + case uintptr(a) > uintptr(b): + return .Greater + case: + assert(a == b) + return .Equal + } + } +} + +_destroy :: proc(l: ^Event_Loop) { + queue.destroy(&l.completed) + avl.destroy(&l.timeouts, false) +} + +__tick :: proc(l: ^Event_Loop, timeout: time.Duration) -> General_Error { + l.now = time.now() + + for op in queue.pop_front_safe(&l.completed) { + if !op._impl.removed { + op.cb(op) + } + if !op.detached { + pool.put(&l.operation_pool, op) + } + } + + iter := avl.iterator(&l.timeouts, .Forward) + for node in avl.iterator_next(&iter) { + op := node.value + cexpires := time.diff(l.now, op.timeout._impl.expires) + + done := cexpires <= 0 + if done { + op.cb(op) + avl.remove_node(&l.timeouts, node) + if !op.detached { + pool.put(&l.operation_pool, op) + } + continue + } + + break + } + + return nil +} + +_create_socket :: proc(l: ^Event_Loop, family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Create_Socket_Error) { + return nil, .Network_Unreachable +} + +_listen :: proc(socket: TCP_Socket, backlog := 1000) -> Listen_Error { + return .Network_Unreachable +} + +_exec :: proc(op: ^Operation) { + switch op.type { + case .Timeout: + _, _, err := avl.find_or_insert(&op.l.timeouts, op) + if err != nil { + panic("nbio: allocation failure") + } + return + case .Accept: + op.accept.err = .Network_Unreachable + case .Close: + op.close.err = .Unsupported + case .Dial: + op.dial.err = Dial_Error.Network_Unreachable + case .Recv: + switch _ in op.recv.socket { + case TCP_Socket: op.recv.err = TCP_Recv_Error.Network_Unreachable + case UDP_Socket: op.recv.err = UDP_Recv_Error.Network_Unreachable + case: op.recv.err = TCP_Recv_Error.Network_Unreachable + } + case .Send: + switch _ in op.send.socket { + case TCP_Socket: op.send.err = TCP_Send_Error.Network_Unreachable + case UDP_Socket: op.send.err = UDP_Send_Error.Network_Unreachable + case: op.send.err = TCP_Send_Error.Network_Unreachable + } + case .Send_File: + op.sendfile.err = .Network_Unreachable + case .Read: + op.read.err = .Unsupported + case .Write: + op.write.err = .Unsupported + case .Poll: + op.poll.result = .Error + case .Open: + op.open.err = .Unsupported + case .Stat: + op.stat.err = .Unsupported + case .None, ._Link_Timeout, ._Remove, ._Splice: + fallthrough + case: + unreachable() + } + + _, err := queue.push_back(&op.l.completed, op) + if err != nil { + panic("nbio: allocation failure") + } +} + +_remove :: proc(target: ^Operation) { + #partial switch target.type { + case .Timeout: + avl.remove_value(&target.l.timeouts, target) + if !target.detached { + pool.put(&target.l.operation_pool, target) + } + case: + target._impl.removed = true + } +} + +_open_sync :: proc(l: ^Event_Loop, path: string, dir: Handle, mode: File_Flags, perm: Permissions) -> (handle: Handle, err: FS_Error) { + return 0, FS_Error.Unsupported +} + +_associate_handle :: proc(handle: uintptr, l: ^Event_Loop) -> (Handle, Association_Error) { + return Handle(handle), nil +} + +_associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop) -> Association_Error { + return nil +} + +_wake_up :: proc(l: ^Event_Loop) { +} + +_yield :: proc() { +} diff --git a/core/nbio/impl_posix.odin b/core/nbio/impl_posix.odin new file mode 100644 index 000000000..05fe584ba --- /dev/null +++ b/core/nbio/impl_posix.odin @@ -0,0 +1,1413 @@ +#+build darwin, freebsd, openbsd, netbsd +#+private file +package nbio + +import "core:c" +import "core:container/pool" +import "core:container/queue" +import "core:mem" +import "core:net" +import "core:strings" +import "core:sys/posix" +import "core:time" +import kq "core:sys/kqueue" + +@(private="package") +_FULLY_SUPPORTED :: true + +@(private="package") +_Event_Loop :: struct { + // kqueue does not permit multiple {ident, filter} pairs in the kqueue. + // We have to keep record of what we currently have in the kqueue, and if we get an operation + // that would be the same (ident, filter) pair we need to bundle the operations under one kevent. + submitted: map[Queue_Identifier]^Operation, + // Holds all events we want to flush. Flushing is done each tick at which point this is emptied. + pending: [dynamic; QUEUE_SIZE]kq.KEvent, + // Holds what should be in `pending` but didn't fit. + // When `pending`is flushed these are moved to `pending`. + overflow: queue.Queue(kq.KEvent), + // Contains all operations that were immediately completed in `exec`. + // These ops did not block so can call back next tick. + completed: queue.Queue(^Operation), + kqueue: kq.KQ, +} + +@(private="package") +_Handle :: posix.FD + +@(private="package") +_CWD :: posix.AT_FDCWD + +@(private="package") +MAX_RW :: mem.Gigabyte + +@(private="package") +_Operation :: struct { + // Linked list of operations that are bundled (same {ident, filter} pair) with this one. + next: ^Operation, + prev: ^Operation, + + flags: Operation_Flags, + result: i64, +} + +@(private="package") +_Accept :: struct {} + +@(private="package") +_Close :: struct {} + +@(private="package") +_Dial :: struct {} + +@(private="package") +_Recv :: struct { + bufs: Bufs, +} + +@(private="package") +_Send :: struct { + bufs: Bufs, +} + +@(private="package") +_Read :: struct {} + +@(private="package") +_Write :: struct {} + +@(private="package") +_Timeout :: struct {} + +@(private="package") +_Poll :: struct {} + +@(private="package") +_Send_File :: struct { + mapping: []byte, // `mmap`'d buffer (if native `sendfile` is not supported). +} + +@(private="package") +_Open :: struct {} + +@(private="package") +_Stat :: struct {} + +@(private="package") +_Splice :: struct {} + +@(private="package") +_Remove :: struct {} + +@(private="package") +_Link_Timeout :: struct {} + +@(private="package") +_init :: proc(l: ^Event_Loop, allocator: mem.Allocator) -> (rerr: General_Error) { + l.submitted.allocator = allocator + l.overflow.data.allocator = allocator + l.completed.data.allocator = allocator + + kqueue, err := kq.kqueue() + if err != nil { + return General_Error(posix.errno()) + } + + l.kqueue = kqueue + + append(&l.pending, kq.KEvent{ + ident = IDENT_WAKE_UP, + filter = .User, + flags = {.Add, .Enable, .Clear}, + }) + __tick(l, 0) // Tick to enqueue wake up, allowing wake ups before the user's first tick. + + return nil +} + +@(private="package") +_destroy :: proc(l: ^Event_Loop) { + delete(l.submitted) + queue.destroy(&l.overflow) + queue.destroy(&l.completed) + posix.close(l.kqueue) +} + +@(private="package") +__tick :: proc(l: ^Event_Loop, timeout: time.Duration) -> General_Error { + debug("tick") + + if n := queue.len(l.completed); n > 0 { + l.now = time.now() + debug("processing", n, "already completed") + + for _ in 0 ..< n { + op := queue.pop_front(&l.completed) + handle_completed(op) + } + + if pool.num_outstanding(&l.operation_pool) == 0 { return nil } + } + + if NBIO_DEBUG { + npending := len(l.pending) + if npending > 0 { + debug("queueing", npending, "new events, there are", int(len(l.submitted)), "events pending") + } else { + debug("there are", int(len(l.submitted)), "events pending") + } + } + + ts_backing: posix.timespec + ts_pointer: ^posix.timespec // nil means forever. + if queue.len(l.completed) == 0 && len(l.submitted) > 0 { + if timeout >= 0 { + debug("timeout", timeout) + ts_backing = {tv_sec=posix.time_t(timeout/time.Second), tv_nsec=c.long(timeout%time.Second)} + ts_pointer = &ts_backing + } else { + debug("timeout forever") + } + } else { + debug("timeout 0, there is completed work pending") + ts_pointer = &ts_backing + } + + for { + results_buf: [128]kq.KEvent + results := kevent(l, results_buf[:], ts_pointer) or_return + + clear(&l.pending) + for overflow in queue.pop_front_safe(&l.overflow) { + (append(&l.pending, overflow) != 0) or_break + } + + l.now = time.now() + + handle_results(l, results) + + if len(results) < len(results_buf) { + break + } + + debug("more events ready than our results buffer handles, getting more") + + // No timeout for the next call. + ts_backing = {} + ts_pointer = &ts_backing + } + + + return nil + + kevent :: proc(l: ^Event_Loop, buf: []kq.KEvent, ts: ^posix.timespec) -> ([]kq.KEvent, General_Error) { + for { + new_events, err := kq.kevent(l.kqueue, l.pending[:], buf, ts) + #partial switch err { + case nil: + assert(new_events >= 0) + return buf[:new_events], nil + case .EINTR: + warn("kevent interrupted") + case: + warn("kevent error") + warn(string(posix.strerror(err))) + return nil, General_Error(err) + } + } + } + + is_internal_timeout :: proc(filter: kq.Filter, op: ^Operation) -> bool { + // A `.Timeout` that `.Has_Timeout` is a `remove()`'d timeout. + return filter == .Timer && (op.type != .Timeout || .Has_Timeout in op._impl.flags) + } + + handle_results :: proc(l: ^Event_Loop, results: []kq.KEvent) { + if len(results) > 0 { + debug(len(results), "events completed") + } + + // Mark all operations that have an event returned as not `.For_Kernel`. + // We have to do this right away, or we may process an operation as if we think the kernel is responsible. + for &event in results { + if ODIN_OS != .Darwin { + // On the BSDs, a `.Delete` that results in an `.Error` does not keep the `.Delete` flag in the result. + // We only have `udata == nil` when we do a delete, so we can add it back here to keep consistent. + if .Error in event.flags && event.udata == nil { + event.flags += {.Delete} + } + } + + if .Delete in event.flags { + continue + } + + if event.filter == .User && event.ident == IDENT_WAKE_UP { + continue + } + + op := cast(^Operation)event.udata + assert(op != nil) + assert(op.type != .None) + + if is_internal_timeout(event.filter, op) { + continue + } + + _, del := delete_key(&l.submitted, Queue_Identifier{ ident = event.ident, filter = event.filter }) + assert(del != nil) + + for next := op; next != nil; next = next._impl.next { + assert(.For_Kernel in next._impl.flags) + next._impl.flags -= {.For_Kernel} + } + } + + // If we get a timeout and an actual result, ignore the timeout. + // We have to do this after the previous loop so we know if the target op of a timeout was also completed. + // We have to do this before the next loop so we handle timeouts before their target ops. Otherwise the target could already be done. + for &event in results { + if .Delete in event.flags { + continue + } + + if event.filter == .User && event.ident == IDENT_WAKE_UP { + continue + } + + op := cast(^Operation)event.udata + if is_internal_timeout(event.filter, op) { + // If the actual event has also been returned this tick, we need to ignore the timeout to not get a uaf. + if .For_Kernel not_in op._impl.flags { + assert(.Has_Timeout in op._impl.flags) + op._impl.flags -= {.Has_Timeout} + + event.filter = kq.Filter(FILTER_IGNORE) + debug(op.type, "timed out but was also completed this tick, ignoring timeout") + } + + } + } + + for event in results { + if event.filter == kq.Filter(FILTER_IGNORE) { + // Previous loop told us to ignore. + continue + } + + if event.filter == .User && event.ident == IDENT_WAKE_UP { + debug("woken up") + continue + } + + if .Delete in event.flags { + assert(.Error in event.flags) + // Seems to happen when you delete at the same time or just after a close. + debug("delete error", int(event.data)) + if err := posix.Errno(event.data); err != .ENOENT && err != .EBADF { + warn("unexpected delete error") + warn(string(posix.strerror(err))) + } + continue + } + + op := cast(^Operation)event.udata + assert(op != nil) + assert(op.type != .None) + + // Timeout result that is a non-timeout op, meaning the operation timed out. + // Because of the previous loop we are sure that the target op is not also in this tick's results. + if is_internal_timeout(event.filter, op) { + debug("got timeout for", op.type) + + assert(.Error not_in event.flags) + + assert(.Has_Timeout in op._impl.flags) + op._impl.flags -= {.Has_Timeout} + + // Remove the actual operation. + timeout_and_delete(op) + handle_completed(op) + continue + } + + // Weird loop, but we need to get the next ptr before handle_completed(curr), curr is freed in handle_completed. + for curr, next := op, op._impl.next; curr != nil; curr, next = next, next == nil ? nil : next._impl.next { + if .Error in event.flags { curr._impl.flags += {.Error} } + if .EOF in event.flags { curr._impl.flags += {.EOF} } + curr._impl.result = event.data + + // Remove refs to the list in case the operation would still block and `add_pending` + // is executed on it again. + curr._impl.prev = nil + curr._impl.next = nil + + handle_completed(curr) + } + } + } +} + +@(private="package") +_create_socket :: proc(l: ^Event_Loop, family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Create_Socket_Error) { + socket = net.create_socket(family, protocol) or_return + + berr := net.set_blocking(socket, false) + // This shouldn't be able to fail. + assert(berr == nil) + + return +} + +@(private="package") +_listen :: proc(socket: TCP_Socket, backlog := 1000) -> Listen_Error { + if res := posix.listen(posix.FD(socket), i32(backlog)); res != .OK { + return posix_listen_error() + } + return nil +} + +@(private="package") +_exec :: proc(op: ^Operation) { + assert(op.l == &_tls_event_loop) + + debug("exec", op.type) + + result: Op_Result + switch op.type { + case .Accept: + result = accept_exec(op) + case .Close: + // no-op + case .Timeout: + result = timeout_exec(op) + case .Dial: + result = dial_exec(op) + case .Recv: + result = recv_exec(op) + case .Send: + result = send_exec(op) + case .Send_File: + result = sendfile_exec(op) + case .Read: + result = read_exec(op) + case .Write: + result = write_exec(op) + case .Poll: + result = poll_exec(op) + assert(result == .Pending) + case .Open: + open_exec(op) + case .Stat: + stat_exec(op) + case .None, ._Link_Timeout, ._Remove, ._Splice: + fallthrough + case: + unreachable() + } + + switch result { + case .Pending: + // no-op, in kernel. + debug(op.type, "pending") + case .Done: + debug(op.type, "done immediately") + op._impl.flags += {.Done} + _, err := queue.push_back(&op.l.completed, op) // Got result, handle it next tick. + ensure(err == nil, "allocation failure") + } +} + +@(private="package") +_remove :: proc(target: ^Operation) { + assert(target != nil) + + debug("remove", target.type) + + if .Removed in target._impl.flags { + debug("already removed") + return + } + + target._impl.flags += {.Removed, .Has_Timeout} + link_timeout(target, target.l.now) +} + +@(private="package") +_open_sync :: proc(l: ^Event_Loop, path: string, dir: Handle, mode: File_Flags, perm: Permissions) -> (handle: Handle, err: FS_Error) { + if path == "" { + err = .Invalid_Argument + return + } + + cpath, cerr := strings.clone_to_cstring(path, l.allocator) + if cerr != nil { + err = .Allocation_Failed + return + } + defer delete(cpath, l.allocator) + + sys_flags := posix.O_Flags{.NOCTTY, .CLOEXEC, .NONBLOCK} + + if .Write in mode { + if .Read in mode { + sys_flags += {.RDWR} + } else { + sys_flags += {.WRONLY} + } + } + + if .Append in mode { sys_flags += {.APPEND} } + if .Create in mode { sys_flags += {.CREAT} } + if .Excl in mode { sys_flags += {.EXCL} } + if .Sync in mode { sys_flags += {.DSYNC} } + if .Trunc in mode { sys_flags += {.TRUNC} } + + handle = posix.openat(dir, cpath, sys_flags, transmute(posix.mode_t)posix._mode_t(transmute(u32)perm)) + if handle < 0 { + err = FS_Error(posix.errno()) + } + + return +} + +@(private="package") +_associate_handle :: proc(handle: uintptr, l: ^Event_Loop) -> (Handle, Association_Error) { + flags_ := posix.fcntl(posix.FD(handle), .GETFL) + if flags_ < 0 { + #partial switch errno := posix.errno(); errno { + case .EBADF: return -1, .Invalid_Handle + case: return -1, Association_Error(errno) + } + } + flags := transmute(posix.O_Flags)(flags_) + + if .NONBLOCK in flags { + return Handle(handle), nil + } + + if posix.fcntl(posix.FD(handle), .SETFL, flags) < 0 { + #partial switch errno := posix.errno(); errno { + case .EBADF: return -1, .Invalid_Handle + case: return -1, Association_Error(errno) + } + } + + return Handle(handle), nil +} + +@(private="package") +_associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop) -> Association_Error { + if err := net.set_blocking(socket, false); err != nil { + switch err { + case .None: unreachable() + case .Network_Unreachable: return .Network_Unreachable + case .Invalid_Argument: return .Invalid_Handle + case .Unknown: fallthrough + case: return Association_Error(net.last_platform_error()) + } + } + + return nil +} + +@(private="package") +_wake_up :: proc(l: ^Event_Loop) { + // TODO: only if we are sleeping (like Windows). + ev := [1]kq.KEvent{ + { + ident = IDENT_WAKE_UP, + filter = .User, + flags = {}, + fflags = { + user = {.Trigger}, + }, + }, + } + t: posix.timespec + n, err := kq.kevent(l.kqueue, ev[:], nil, &t) + assert(err == nil) + assert(n == 0) +} + +@(private="package") +_yield :: proc() { + posix.sched_yield() +} + +// Start file private. + +// Max operations that can be enqueued per tick. +QUEUE_SIZE :: #config(ODIN_NBIO_QUEUE_SIZE, 256) + +FILTER_IGNORE :: kq.Filter(max(kq._Filter_Backing)) + +IDENT_WAKE_UP :: 69 + +Op_Result :: enum { + Done, + Pending, +} + +Operation_Flag :: enum { + Done, + Removed, + Has_Timeout, + For_Kernel, + EOF, + Error, +} +Operation_Flags :: bit_set[Operation_Flag] + +// Operations in the kqueue are uniquely identified using these 2 fields. You may not have more +// than one operation with the same identity submitted. +// So we need to keep track of the operations we have submitted, and if we add another, link it to a previously +// added operation. +Queue_Identifier :: struct { + filter: kq.Filter, + ident: uintptr, +} + +handle_completed :: proc(op: ^Operation) { + debug("handling", op.type) + + result: Op_Result + #partial switch op.type { + case .Accept: + result = accept_exec(op) + case .Dial: + result = dial_exec(op) + case .Send: + if send_exec(op) == .Done { + maybe_callback(op) + bufs_delete(&op.send._impl.bufs, op.send.bufs, op.l.allocator) + cleanup(op) + } + return + case .Recv: + if recv_exec(op) == .Done { + maybe_callback(op) + bufs_delete(&op.recv._impl.bufs, op.recv.bufs, op.l.allocator) + cleanup(op) + } + return + case .Send_File: + result = sendfile_exec(op) + case .Read: + result = read_exec(op) + case .Write: + result = write_exec(op) + case .Poll: + result = poll_exec(op) + case .Open: + open_exec(op) + case .Close: + close_exec(op) + case .Timeout, .Stat: + // no-op + case: + unimplemented() + } + + if result == .Done { + maybe_callback(op) + cleanup(op) + } + + maybe_callback :: proc(op: ^Operation) { + if .Removed not_in op._impl.flags { + debug("done", op.type, "calling back") + op.cb(op) + } else { + debug("done but removed", op.type) + } + } + + bufs_destroy :: proc(bufs: [][]byte, allocator: mem.Allocator) { + if len(bufs) > 1 { + delete(bufs, allocator) + } + } + + cleanup :: proc(op: ^Operation) { + if .Has_Timeout in op._impl.flags { + remove_link_timeout(op) + } + if !op.detached { + pool.put(&op.l.operation_pool, op) + } + } +} + +@(require_results) +accept_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Accept) + + defer if op.accept.err != nil && op.accept.client > 0 { + posix.close(posix.FD(op.accept.client)) + } + + if op.accept.err != nil || .Done in op._impl.flags { + return .Done + } + + op.accept.client, op.accept.client_endpoint, op.accept.err = net.accept_tcp(op.accept.socket) + if op.accept.err != nil { + if op.accept.err == .Would_Block { + op.accept.err = nil + add_pending(op, .Read, uintptr(op.accept.socket)) + link_timeout(op, op.accept.expires) + return .Pending + } + + return .Done + } + + if err := net.set_blocking(op.accept.client, false); err != nil { + op.accept.err = posix_accept_error() + } + + return .Done +} + +@(require_results) +dial_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Dial) + + defer if op.dial.err != nil && op.dial.socket > 0 { + posix.close(posix.FD(op.dial.socket)) + } + + if op.dial.err != nil || .Done in op._impl.flags { + return .Done + } + + if op.dial.socket > 0 { + // We have already called connect, retrieve potential error number only. + err: posix.Errno + size := posix.socklen_t(size_of(err)) + posix.getsockopt(posix.FD(op.dial.socket), posix.SOL_SOCKET, .ERROR, &err, &size) + if err != nil { + posix.errno(err) + op.dial.err = posix_dial_error() + } + return .Done + } + + if op.dial.endpoint.port == 0 { + op.dial.err = .Port_Required + return .Done + } + + family := family_from_endpoint(op.dial.endpoint) + osocket, socket_err := _create_socket(op.l, family, .TCP) + if socket_err != nil { + op.dial.err = socket_err + return .Done + } + + op.dial.socket = osocket.(TCP_Socket) + + sockaddr := endpoint_to_sockaddr(op.dial.endpoint) + if posix.connect(posix.FD(op.dial.socket), (^posix.sockaddr)(&sockaddr), posix.socklen_t(sockaddr.ss_len)) != .OK { + if posix.errno() == .EINPROGRESS { + add_pending(op, .Write, uintptr(op.dial.socket)) + link_timeout(op, op.dial.expires) + return .Pending + } + + op.dial.err = posix_dial_error() + return .Done + } + + return .Done +} + +@(require_results) +poll_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Poll) + + if .Error in op._impl.flags { + #partial switch posix.Errno(op._impl.result) { + case .EBADF: op.poll.result = .Invalid_Argument + case: op.poll.result = .Error + } + return .Done + } + + if op._impl.result != 0 { + op.poll.result = .Ready + return .Done + } + + if op.poll.result != .Ready { + return .Done + } + + if .EOF in op._impl.flags { + op.poll.result = .Ready + return .Done + } + + filter: kq.Filter + switch op.poll.event { + case .Receive: filter = .Read + case .Send: filter = .Write + } + + add_pending(op, filter, uintptr(net.any_socket_to_socket(op.poll.socket))) + link_timeout(op, op.poll.expires) + return .Pending +} + +close_exec :: proc(op: ^Operation) { + assert(op.type == .Close) + + if op.close.err != nil || op.close.subject == nil { + return + } + + fd: posix.FD + switch subject in op.close.subject { + case TCP_Socket: fd = posix.FD(subject) + case UDP_Socket: fd = posix.FD(subject) + case Handle: fd = posix.FD(subject) + case: op.close.err = .Invalid_Argument; return + } + + if posix.close(fd) != .OK { + op.close.err = FS_Error(posix.errno()) + } +} + +@(require_results) +send_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Send) + + if op.send.err != nil || .Done in op._impl.flags { + return .Done + } + + bufs, total := bufs_to_process(&op.send._impl.bufs, op.send.bufs, op.send.sent) + sock, n := sendv(op.send.socket, bufs, op.send.endpoint) + if n < 0 { + if posix.errno() == .EWOULDBLOCK { + if !op.send.all && op.send.sent > 0 { + return .Done + } + + add_pending(op, .Write, uintptr(sock)) + link_timeout(op, op.send.expires) + return .Pending + } + + switch _ in op.send.socket { + case TCP_Socket: op.send.err = posix_tcp_send_error() + case UDP_Socket: op.send.err = posix_udp_send_error() + } + return .Done + } + + op.send.sent += n + + if n < total { + return send_exec(op) + } + + return .Done + + sendv :: proc(socket: Any_Socket, bufs: [][]byte, to: net.Endpoint) -> (posix.FD, int) { + assert(len(bufs) < int(max(i32))) + + msg: posix.msghdr + msg.msg_iov = cast([^]posix.iovec)raw_data(bufs) + msg.msg_iovlen = i32(len(bufs)) + + toaddr: posix.sockaddr_storage + fd: posix.FD + switch sock in socket { + case TCP_Socket: + fd = posix.FD(sock) + case UDP_Socket: + fd = posix.FD(sock) + toaddr = endpoint_to_sockaddr(to) + msg.msg_name = &toaddr + msg.msg_namelen = posix.socklen_t(toaddr.ss_len) + } + + return fd, posix.sendmsg(fd, &msg, {.NOSIGNAL}) + } +} + +@(require_results) +recv_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Recv) + + if op.recv.err != nil || .Done in op._impl.flags { + return .Done + } + + bufs, total := bufs_to_process(&op.recv._impl.bufs, op.recv.bufs, op.recv.received) + _, is_tcp := op.recv.socket.(net.TCP_Socket) + + sock, n := recvv(op.recv.socket, bufs, &op.recv.source) + if n < 0 { + if posix.errno() == .EWOULDBLOCK { + if is_tcp && !op.recv.all && op.recv.received > 0 { + return .Done + } + + add_pending(op, .Read, uintptr(sock)) + link_timeout(op, op.recv.expires) + return .Pending + } + + if is_tcp { + op.recv.err = posix_tcp_recv_error() + } else { + op.recv.err = posix_udp_recv_error() + } + + return .Done + } + + assert(is_tcp || op.recv.received == 0) + op.recv.received += n + + if is_tcp && n != 0 && n < total { + return recv_exec(op) + } + + return .Done + + recvv :: proc(socket: Any_Socket, bufs: [][]byte, from: ^Endpoint) -> (fd: posix.FD, n: int) { + assert(len(bufs) < int(max(i32))) + + msg: posix.msghdr + msg.msg_iov = cast([^]posix.iovec)raw_data(bufs) + msg.msg_iovlen = i32(len(bufs)) + + udp: bool + fromaddr: posix.sockaddr_storage + switch sock in socket { + case TCP_Socket: + fd = posix.FD(sock) + case UDP_Socket: + fd = posix.FD(sock) + udp = true + msg.msg_name = &fromaddr + msg.msg_namelen = posix.socklen_t(size_of(fromaddr)) + } + + n = posix.recvmsg(fd, &msg, {.NOSIGNAL}) + if n >= 0 && udp { + from^ = sockaddr_to_endpoint(&fromaddr) + } + + return + } +} + +@(require_results) +sendfile_exec :: proc(op: ^Operation) -> (result: Op_Result) { + assert(op.type == .Send_File) + + defer if result == .Done && op.sendfile._impl.mapping != nil { + posix.munmap(raw_data(op.sendfile._impl.mapping), len(op.sendfile._impl.mapping)) + } + + if op.sendfile.err != nil || .Done in op._impl.flags { + return .Done + } + + when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { + // Doesn't have `sendfile`, emulate it with `mmap` + normal `send`. + return sendfile_exec_emulated(op) + } else { + return sendfile_exec_native(op) + + @(require_results) + sendfile_exec_native :: proc(op: ^Operation) -> Op_Result { + nbytes := op.sendfile.nbytes + assert(nbytes != 0) + if nbytes == SEND_ENTIRE_FILE { + nbytes = 0 // special value for entire file. + + // If we want progress updates we need nbytes to be the actual size, or the user + // won't be able to check `sent < nbytes` to know if it's the final callback. + if op.sendfile.progress_updates { + stat: posix.stat_t + if posix.fstat(op.sendfile.file, &stat) != .OK { + op.sendfile.err = FS_Error(posix.errno()) + return .Done + } + op.sendfile.nbytes = int(stat.st_size - posix.off_t(op.sendfile.offset)) + } + } else { + nbytes -= op.sendfile.sent + } + + n, ok := posix_sendfile(op.sendfile.file, op.sendfile.socket, op.sendfile.offset + op.sendfile.sent, nbytes) + + assert(n >= 0) + op.sendfile.sent += n + + if !ok { + op.sendfile.err = posix_tcp_send_error() + if op.sendfile.err == .Would_Block { + op.sendfile.err = nil + if op.sendfile.progress_updates { op.cb(op) } + add_pending(op, .Write, uintptr(op.sendfile.socket)) + link_timeout(op, op.sendfile.expires) + return .Pending + } + + return .Done + } + + assert(op.sendfile.nbytes == SEND_ENTIRE_FILE || op.sendfile.sent == op.sendfile.nbytes) + return .Done + } + } + + @(require_results) + sendfile_exec_emulated :: proc(op: ^Operation) -> Op_Result { + if op.sendfile.nbytes == SEND_ENTIRE_FILE { + stat: posix.stat_t + if posix.fstat(op.sendfile.file, &stat) != .OK { + op.sendfile.err = FS_Error(posix.errno()) + return .Done + } + op.sendfile.nbytes = int(stat.st_size - posix.off_t(op.sendfile.offset)) + } + + if op.sendfile._impl.mapping == nil { + addr := posix.mmap(nil, uint(op.sendfile.nbytes), {.READ}, {}, op.sendfile.file, posix.off_t(op.sendfile.offset)) + if addr == posix.MAP_FAILED { + op.sendfile.err = FS_Error(posix.errno()) + return .Done + } + op.sendfile._impl.mapping = ([^]byte)(addr)[:op.sendfile.nbytes] + } + + n := posix.send( + posix.FD(op.sendfile.socket), + raw_data(op.sendfile._impl.mapping)[op.sendfile.sent:], + uint(min(MAX_RW, op.sendfile.nbytes - op.sendfile.sent)), + {.NOSIGNAL}, + ) + if n < 0 { + op.sendfile.err = posix_tcp_send_error() + if op.sendfile.err == .Would_Block { + op.sendfile.err = nil + add_pending(op, .Write, uintptr(op.sendfile.socket)) + link_timeout(op, op.sendfile.expires) + return .Pending + } + + return .Done + } + + op.sendfile.sent += n + + if op.sendfile.sent < op.sendfile.nbytes { + if op.sendfile.progress_updates { op.cb(op) } + return sendfile_exec_emulated(op) + } + + return .Done + } +} + +@(require_results) +read_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Read) + + if op.read.err != nil || .Done in op._impl.flags { + return .Done + } + + to_read := op.read.buf[op.read.read:] + to_read = to_read[:min(MAX_RW, len(to_read))] + + res := posix.pread(op.read.handle, raw_data(to_read), len(to_read), posix.off_t(op.read.offset) + posix.off_t(op.read.read)) + if res < 0 { + errno := posix.errno() + if errno == .EWOULDBLOCK { + if !op.read.all && op.read.read > 0 { + return .Done + } + + add_pending(op, .Read, uintptr(op.read.handle)) + link_timeout(op, op.read.expires) + return .Pending + } + + op.read.err = FS_Error(errno) + return .Done + } else if res == 0 { + if op.read.read == 0 { + op.read.err = .EOF + } + return .Done + } + + op.read.read += res + + if op.read.read < len(op.read.buf) { + return read_exec(op) + } + + return .Done +} + +@(require_results) +write_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Write) + + if op.write.err != nil || .Done in op._impl.flags { + return .Done + } + + to_write := op.write.buf[op.write.written:] + to_write = to_write[:min(MAX_RW, len(to_write))] + + res := posix.pwrite(op.write.handle, raw_data(to_write), len(to_write), posix.off_t(op.write.offset) + posix.off_t(op.write.written)) + if res < 0 { + errno := posix.errno() + if errno == .EWOULDBLOCK { + if !op.write.all && op.write.written > 0 { + return .Done + } + + add_pending(op, .Write, uintptr(op.write.handle)) + link_timeout(op, op.write.expires) + return .Pending + } + + op.write.err = FS_Error(errno) + return .Done + } + + op.write.written += res + + if op.write.written < len(op.write.buf) { + return write_exec(op) + } + + return .Done +} + +timeout_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Timeout) + + if op.timeout.duration <= 0 { + return .Done + } + + op.l.submitted[Queue_Identifier{ ident = uintptr(op), filter = .Timer }] = op + + op._impl.flags += {.For_Kernel} + + append_pending(op.l, kq.KEvent { + ident = uintptr(op), + filter = .Timer, + flags = {.Add, .Enable, .One_Shot}, + fflags = { + timer = kq.TIMER_FLAGS_NSECONDS + {.Absolute}, + }, + data = op.l.now._nsec + i64(op.timeout.duration), + udata = op, + }) + return .Pending +} + +open_exec :: proc(op: ^Operation) { + assert(op.type == .Open) + + if op.open.err != nil && op.open.handle > 0 { + posix.close(op.open.handle) + return + } + + if .Done in op._impl.flags { + return + } + + op.open.handle, op.open.err = _open_sync(op.l, op.open.path, op.open.dir, op.open.mode, op.open.perm) +} + +stat_exec :: proc(op: ^Operation) { + assert(op.type == .Stat) + + stat: posix.stat_t + if posix.fstat(op.stat.handle, &stat) != .OK { + op.stat.err = FS_Error(posix.errno()) + return + } + + op.stat.type = .Undetermined + switch { + case posix.S_ISBLK(stat.st_mode) || posix.S_ISCHR(stat.st_mode): + op.stat.type = .Device + case posix.S_ISDIR(stat.st_mode): + op.stat.type = .Directory + case posix.S_ISFIFO(stat.st_mode) || posix.S_ISSOCK(stat.st_mode): + op.stat.type = .Pipe_Or_Socket + case posix.S_ISLNK(stat.st_mode): + op.stat.type = .Symlink + case posix.S_ISREG(stat.st_mode): + op.stat.type = .Regular + } + + op.stat.size = i64(stat.st_size) +} + +add_pending :: proc(op: ^Operation, filter: kq.Filter, ident: uintptr) { + debug("adding pending", op.type) + assert(op._impl.next == nil) + assert(op._impl.prev == nil) + op._impl.flags += {.For_Kernel} + + _, val, just_inserted, err := map_entry(&op.l.submitted, Queue_Identifier{ ident = ident, filter = filter }) + ensure(err == nil, "allocation failure") + if just_inserted { + val^ = op + + append_pending(op.l, kq.KEvent { + filter = filter, + ident = ident, + flags = {.Add, .Enable, .One_Shot}, + udata = op, + }) + } else { + debug("already have this operation on the kqueue, bundling it") + + last := val^ + for last._impl.next != nil { + last = last._impl.next + } + last._impl.next = op + op._impl.prev = last + } +} + +append_pending :: #force_inline proc(l: ^Event_Loop, ev: kq.KEvent) { + if append(&l.pending, ev) == 0 { + warn("queue is full, adding to overflow, should QUEUE_SIZE be increased?") + _, err := queue.append(&l.overflow, ev) + ensure(err == nil, "allocation failure") + } +} + +link_timeout :: proc(op: ^Operation, expires: time.Time) { + if expires == {} { + return + } + + debug(op.type, "times out at", expires) + + op._impl.flags += {.Has_Timeout} + + append_pending(op.l, kq.KEvent { + ident = uintptr(op), + filter = .Timer, + flags = {.Add, .Enable, .One_Shot}, + fflags = { + timer = kq.TIMER_FLAGS_NSECONDS + {.Absolute}, + }, + data = expires._nsec, + udata = op, + }) +} + +remove_link_timeout :: proc(op: ^Operation) { + debug("removing timeout of", op.type) + assert(.Has_Timeout in op._impl.flags) + + append_pending(op.l, kq.KEvent { + ident = uintptr(op), + filter = .Timer, + flags = {.Delete, .Disable, .One_Shot}, + }) +} + +timeout_and_delete :: proc(target: ^Operation) { + filter: kq.Filter + ident: uintptr + switch target.type { + case .Accept: + target.accept.err = .Timeout + filter = .Read + ident = uintptr(target.accept.socket) + case .Dial: + target.dial.err = Dial_Error.Timeout + filter = .Write + ident = uintptr(target.dial.socket) + case .Read: + target.read.err = .Timeout + filter = .Read + ident = uintptr(target.read.handle) + case .Write: + target.write.err = .Timeout + filter = .Write + ident = uintptr(target.write.handle) + case .Recv: + switch sock in target.recv.socket { + case TCP_Socket: + target.recv.err = TCP_Recv_Error.Timeout + ident = uintptr(sock) + case UDP_Socket: + target.recv.err = UDP_Recv_Error.Timeout + ident = uintptr(sock) + } + filter = .Read + case .Send: + switch sock in target.send.socket { + case TCP_Socket: + target.send.err = TCP_Send_Error.Timeout + ident = uintptr(sock) + case UDP_Socket: + target.send.err = UDP_Send_Error.Timeout + ident = uintptr(sock) + } + filter = .Write + case .Send_File: + target.send.err = TCP_Send_Error.Timeout + filter = .Write + ident = uintptr(target.sendfile.socket) + case .Poll: + target.poll.result = .Timeout + ident = uintptr(net.any_socket_to_socket(target.poll.socket)) + + switch target.poll.event { + case .Receive: filter = .Read + case .Send: filter = .Write + } + + case .Timeout: + ident = uintptr(target) + filter = .Timer + + case .Close: + target.close.err = .Timeout + return + + case .Open: + target.open.err = .Timeout + return + + case .Stat: + target.stat.err = .Timeout + return + + case .None, ._Link_Timeout, ._Remove, ._Splice: + return + } + + // If there are other ops linked to this kevent, don't remove it. + if target._impl.next != nil || target._impl.prev != nil { + debug("removing target by pulling it out of the linked list, other ops depend on the kevent") + assert(filter != .Timer) + + if target._impl.next != nil { + target._impl.next._impl.prev = target._impl.prev + } + + if target._impl.prev != nil { + target._impl.prev._impl.next = target._impl.next + } else { + debug("target was the head of the list, updating map to point at new head") + + _, vp, _, err := map_entry(&target.l.submitted, Queue_Identifier{ ident = ident, filter = filter }) + ensure(err == nil, "allocation failure") + assert(vp^ == target) + vp^ = target._impl.next + + ev := kq.KEvent{ + filter = filter, + ident = ident, + flags = {.Add, .Enable, .One_Shot}, + udata = target._impl.next, + } + if append(&target.l.pending, ev) == 0 { + warn("just removed the head operation of a list of multiple, and the queue is full, have to force this update through inefficiently") + // This has to happen the next time we submit or we could have udata pointing wrong. + // Very inefficient but probably never hit. + + // Makes kevent return a receipt for our addition, so we don't take any new events from it. + // This forces .Error to be added and data being 0 means it's added. + ev.flags += {.Receipt} + + timeout: posix.timespec + n, err := kq.kevent(target.l.kqueue, ([^]kq.KEvent)(&ev)[:1], ([^]kq.KEvent)(&ev)[:1], &timeout) + assert(n == 1) + assert(err == nil) + + // The receipt flag makes this occur on the event. + assert(.Error in ev.flags) + assert(ev.data == 0) + } + } + + } else if .For_Kernel in target._impl.flags { + debug("adding delete event") + + _, dval := delete_key(&target.l.submitted, Queue_Identifier{ ident = ident, filter = filter }) + assert(dval != nil) + + append_pending(target.l, kq.KEvent{ + ident = ident, + filter = filter, + flags = {.Delete, .Disable, .One_Shot}, + }) + } else { + debug("remove without delete event, because target is not in kernel") + } +} + +@(require_results) +endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: posix.sockaddr_storage) { + switch a in ep.address { + case IP4_Address: + (^posix.sockaddr_in)(&sockaddr)^ = posix.sockaddr_in { + sin_port = u16be(ep.port), + sin_addr = transmute(posix.in_addr)a, + sin_family = .INET, + sin_len = size_of(posix.sockaddr_in), + } + return + case IP6_Address: + (^posix.sockaddr_in6)(&sockaddr)^ = posix.sockaddr_in6 { + sin6_port = u16be(ep.port), + sin6_addr = transmute(posix.in6_addr)a, + sin6_family = .INET6, + sin6_len = size_of(posix.sockaddr_in6), + } + return + } + unreachable() +} + +@(require_results) +sockaddr_to_endpoint :: proc(native_addr: ^posix.sockaddr_storage) -> (ep: Endpoint) { + #partial switch native_addr.ss_family { + case .INET: + addr := cast(^posix.sockaddr_in)native_addr + port := int(addr.sin_port) + ep = Endpoint { + address = IP4_Address(transmute([4]byte)addr.sin_addr), + port = port, + } + case .INET6: + addr := cast(^posix.sockaddr_in6)native_addr + port := int(addr.sin6_port) + ep = Endpoint { + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = port, + } + case: + panic("native_addr is neither IP4 or IP6 address") + } + return +} diff --git a/core/nbio/impl_posix_darwin.odin b/core/nbio/impl_posix_darwin.odin new file mode 100644 index 000000000..7ec64c2df --- /dev/null +++ b/core/nbio/impl_posix_darwin.odin @@ -0,0 +1,29 @@ +#+private +package nbio + +import "core:net" +import "core:sys/posix" + +foreign import lib "system:System" + +posix_sendfile :: proc(fd: Handle, s: TCP_Socket, offset, nbytes: int) -> (sent: int, ok := true) { + foreign lib { + @(link_name="sendfile") + _posix_sendfile :: proc (fd, s: posix.FD, offset: posix.off_t, len: ^posix.off_t, hdtr: rawptr, flags: i32) -> posix.result --- + } + + len := posix.off_t(nbytes) + if _posix_sendfile(posix.FD(fd), posix.FD(s), posix.off_t(offset), &len, nil, 0) != .OK { + ok = false + } + sent = int(len) + return +} + +posix_listen_error :: net._listen_error +posix_accept_error :: net._accept_error +posix_dial_error :: net._dial_error +posix_tcp_send_error :: net._tcp_send_error +posix_udp_send_error :: net._udp_send_error +posix_tcp_recv_error :: net._tcp_recv_error +posix_udp_recv_error :: net._udp_recv_error diff --git a/core/nbio/impl_posix_freebsd.odin b/core/nbio/impl_posix_freebsd.odin new file mode 100644 index 000000000..50089510b --- /dev/null +++ b/core/nbio/impl_posix_freebsd.odin @@ -0,0 +1,52 @@ +#+private +package nbio + +import "core:net" +import "core:sys/posix" +import "core:sys/freebsd" + +foreign import lib "system:c" + +// TODO: rewrite freebsd implementation to use `sys/freebsd` instead of `sys/posix`. + +posix_sendfile :: proc(fd: Handle, s: TCP_Socket, offset, nbytes: int) -> (sent: int, ok := true) { + foreign lib { + @(link_name="sendfile") + _posix_sendfile :: proc (fd, s: posix.FD, offset: posix.off_t, nbytes: uint, hdtr: rawptr, sbytes: ^posix.off_t, flags: i32) -> posix.result --- + } + + len: posix.off_t + if _posix_sendfile(posix.FD(fd), posix.FD(s), posix.off_t(offset), uint(nbytes), nil, &len, 0) != .OK { + ok = false + } + sent = int(len) + return +} + +posix_listen_error :: proc() -> Listen_Error { + return net._listen_error(freebsd.Errno(posix.errno())) +} + +posix_accept_error :: proc() -> Accept_Error { + return net._accept_error(freebsd.Errno(posix.errno())) +} + +posix_dial_error :: proc() -> Dial_Error { + return net._dial_error(freebsd.Errno(posix.errno())) +} + +posix_tcp_send_error :: proc() -> TCP_Send_Error { + return net._tcp_send_error(freebsd.Errno(posix.errno())) +} + +posix_udp_send_error :: proc() -> UDP_Send_Error { + return net._udp_send_error(freebsd.Errno(posix.errno())) +} + +posix_tcp_recv_error :: proc() -> TCP_Recv_Error { + return net._tcp_recv_error(freebsd.Errno(posix.errno())) +} + +posix_udp_recv_error :: proc() -> UDP_Recv_Error { + return net._udp_recv_error(freebsd.Errno(posix.errno())) +} diff --git a/core/nbio/impl_posix_netbsd.odin b/core/nbio/impl_posix_netbsd.odin new file mode 100644 index 000000000..a0e2652f4 --- /dev/null +++ b/core/nbio/impl_posix_netbsd.odin @@ -0,0 +1,12 @@ +#+private +package nbio + +import "core:net" + +posix_listen_error :: net._listen_error +posix_accept_error :: net._accept_error +posix_dial_error :: net._dial_error +posix_tcp_send_error :: net._tcp_send_error +posix_udp_send_error :: net._udp_send_error +posix_tcp_recv_error :: net._tcp_recv_error +posix_udp_recv_error :: net._udp_recv_error diff --git a/core/nbio/impl_posix_openbsd.odin b/core/nbio/impl_posix_openbsd.odin new file mode 100644 index 000000000..a0e2652f4 --- /dev/null +++ b/core/nbio/impl_posix_openbsd.odin @@ -0,0 +1,12 @@ +#+private +package nbio + +import "core:net" + +posix_listen_error :: net._listen_error +posix_accept_error :: net._accept_error +posix_dial_error :: net._dial_error +posix_tcp_send_error :: net._tcp_send_error +posix_udp_send_error :: net._udp_send_error +posix_tcp_recv_error :: net._tcp_recv_error +posix_udp_recv_error :: net._udp_recv_error diff --git a/core/nbio/impl_windows.odin b/core/nbio/impl_windows.odin new file mode 100644 index 000000000..adf2d5351 --- /dev/null +++ b/core/nbio/impl_windows.odin @@ -0,0 +1,1848 @@ +#+private file +package nbio + +import "base:intrinsics" + +import "core:container/avl" +import "core:container/pool" +import "core:container/queue" +import "core:mem" +import "core:net" +import "core:path/filepath" +import "core:slice" +import "core:strings" +import "core:sync" +import "core:time" + +import win "core:sys/windows" + +@(private="package") +_FULLY_SUPPORTED :: true + +@(private="package") +_Event_Loop :: struct { + timeouts: avl.Tree(^Operation), + thread: win.HANDLE, + completed: queue.Queue(^Operation), + completed_oob: Multi_Producer_Single_Consumer, + state: enum { + Working, + Waking, + Sleeping, + }, +} + +@(private="package") +_Handle :: distinct uintptr + +@(private="package") +_CWD :: ~_Handle(99) + +@(private="package") +MAX_RW :: mem.Gigabyte + +@(private="package") +_Operation :: struct { + over: win.OVERLAPPED, + timeout: ^Operation, +} + +@(private="package") +_Accept :: struct { + // Space that gets the local and remote address written into it. + addrs: [(size_of(win.sockaddr_in6)+16)*2]byte, +} + +@(private="package") +_Close :: struct {} + +@(private="package") +_Dial :: struct { + addr: win.SOCKADDR_STORAGE_LH, +} + +@(private="package") +_Read :: struct {} + +@(private="package") +_Write :: struct {} + +@(private="package") +_Send :: struct { + bufs: Bufs, +} + +@(private="package") +_Recv :: struct { + source: win.SOCKADDR_STORAGE_LH, + source_len: win.INT, + flags: win.DWORD, + bufs: Bufs, +} + +@(private="package") +_Timeout :: struct { + expires: time.Time, + target: ^Operation, +} + +@(private="package") +_Poll :: struct { + wait_handle: win.HANDLE, +} + +@(private="package") +_Send_File :: struct {} + +@(private="package") +_Remove :: struct {} + +@(private="package") +_Link_Timeout :: struct {} + +@(private="package") +_Splice :: struct {} + +@(private="package") +_Open :: struct {} + +@(private="package") +_Stat :: struct {} + +@(private="package") +_init :: proc(l: ^Event_Loop, alloc: mem.Allocator) -> (err: General_Error) { + l.allocator = alloc + + l.completed.data.allocator = l.allocator + + avl.init(&l.timeouts, timeouts_cmp, alloc) + + mpsc_init(&l.completed_oob, QUEUE_SIZE, l.allocator) + defer if err != nil { mpsc_destroy(&l.completed_oob, l.allocator) } + + dup_ok := win.DuplicateHandle( + win.GetCurrentProcess(), win.GetCurrentThread(), + win.GetCurrentProcess(), &l.thread, + 0, false, win.DUPLICATE_SAME_ACCESS, + ) + ensure(dup_ok == true) + defer if err != nil { win.CloseHandle(l.thread) } + + err = g_ref() + return +} + +@(private="package") +_destroy :: proc(l: ^Event_Loop) { + avl.destroy(&l.timeouts) + queue.destroy(&l.completed) + mpsc_destroy(&l.completed_oob, l.allocator) + win.CloseHandle(l.thread) + g_unref() +} + +@(private="package") +__tick :: proc(l: ^Event_Loop, timeout: time.Duration) -> (err: General_Error) { + debug("tick") + + l.now = time.now() + next_timeout := check_timeouts(l) + + // Prevent infinite loop when callback adds to completed by storing length. + n := queue.len(l.completed) + if n > 0 { + for _ in 0 ..< n { + op := queue.pop_front(&l.completed) + handle_completed(op) + } + } + + for { + op := (^Operation)(mpsc_dequeue(&l.completed_oob)) + if op == nil { break } + handle_completed(op) + } + + if pool.num_outstanding(&l.operation_pool) == 0 { return nil } + + actual_timeout := win.INFINITE + if queue.len(l.completed) > 0 || mpsc_count(&l.completed_oob) > 0 { + actual_timeout = 0 + } else if timeout >= 0 { + actual_timeout = win.DWORD(timeout / time.Millisecond) + } + if nt, ok := next_timeout.?; ok { + actual_timeout = min(actual_timeout, win.DWORD(nt / time.Millisecond)) + } + + if actual_timeout > 0 { + sync.atomic_store_explicit(&l.state, .Sleeping, .Release) + + // There could be a race condition where we go sleeping at the same time as things get queued + // and a wakeup isn't done because the state is not .Sleeping yet. + // So after sleeping we first check our queues. + + for { + op := (^Operation)(mpsc_dequeue(&l.queue)) + if op == nil { break } + _exec(op) + } + + for { + op := (^Operation)(mpsc_dequeue(&l.completed_oob)) + if op == nil { break } + handle_completed(op) + } + } + + for { + events: [256]win.OVERLAPPED_ENTRY + entries_removed: win.ULONG + if !win.GetQueuedCompletionStatusEx(g.iocp, &events[0], len(events), &entries_removed, actual_timeout, true) { + winerr := win.GetLastError() + switch winerr { + case win.WAIT_TIMEOUT, win.WAIT_IO_COMPLETION: + entries_removed = 0 + case: + err = General_Error(winerr) + return + } + } + + sync.atomic_store_explicit(&l.state, .Working, .Relaxed) + + if actual_timeout > 0 { + // We may have just waited some time, lets update the current time. + l.now = time.now() + } + + if entries_removed > 0 { + debug(int(entries_removed), "operations were completed") + } + + for event in events[:entries_removed] { + assert(event.lpOverlapped != nil) + op := container_of(container_of(event.lpOverlapped, _Operation, "over"), Operation, "_impl") + + if op.l == l { + handle_completed(op) + } else { + op_l := op.l + for !mpsc_enqueue(&op.l.completed_oob, op) { + warn("oob queue filled up, QUEUE_SIZE may need increasing") + _wake_up(op_l) + win.SwitchToThread() + } + _wake_up(op_l) + } + } + + if entries_removed < len(events) { + break + } + + // `events` was filled up, get more. + debug("GetQueuedCompletionStatusEx filled entire events buffer, getting more") + actual_timeout = 0 + } + + return nil + + check_timeouts :: proc(l: ^Event_Loop) -> (expires: Maybe(time.Duration)) { + curr := l.now + + if avl.len(&l.timeouts) == 0 { + return + } + + debug(avl.len(&l.timeouts), "timeouts", "threshold", curr) + + iter := avl.iterator(&l.timeouts, .Forward) + for node in avl.iterator_next(&iter) { + op := node.value + cexpires := time.diff(curr, op.timeout._impl.expires) + + debug("expires after", cexpires) + + removed := op._impl.timeout == (^Operation)(REMOVED) + done := cexpires <= 0 + if removed { + debug("timeout removed!") + } else if done { + debug("timeout done!") + handle_completed(op) + } + if removed || done { + avl.remove_node(&l.timeouts, node) + continue + } + + break + } + + // Don't merge this with the previous iteration because the `handle_completed` in that one might queue + // more timeouts which we want to detect here. + // For example: `timeout(time.Second, proc(_: ^Operation) { timeout(time.Second, ...) })` + + first := avl.first(&l.timeouts) + if first != nil { + op := first.value + cexpires := time.diff(curr, op.timeout._impl.expires) + debug("first timeout in the future is at", op.timeout._impl.expires, "after", cexpires) + expires = cexpires + } + return + } + + handle_completed :: proc(op: ^Operation) { + debug("handling", op.type) + + if op._impl.timeout == (^Operation)(REMOVED) { + debug(op.type, "was removed") + + // Set an error, and call the internal callback. + // This way resources are cleaned up properly, for example the result socket for dial. + // If we just do nothing it will be leaked. + + if op._impl.over.Internal == nil { + // There is no error from the kernel, set one ourselves. + // This needs to be an NTSTATUS code, not a win32 error number. + STATUS_REQUEST_ABORTED :: 0xC023000C + op._impl.over.Internal = (^win.c_ulong)(uintptr(STATUS_REQUEST_ABORTED)) + } + } + + result := Op_Result.Done + switch op.type { + case .Read: + result = read_callback(op) + case .Recv: + result = recv_callback(op) + if result == .Done { + maybe_callback(op) + bufs_delete(&op.recv._impl.bufs, op.recv.bufs, op.l.allocator) + cleanup(op) + return + } + case .Write: + result = write_callback(op) + case .Send: + result = send_callback(op) + if result == .Done { + maybe_callback(op) + bufs_delete(&op.send._impl.bufs, op.send.bufs, op.l.allocator) + cleanup(op) + return + } + case .Send_File: + result = sendfile_callback(op) + case .Accept: + accept_callback(op) + case .Dial: + dial_callback(op) + case .Poll: + poll_callback(op) + case .Timeout, .Open, .Stat, .Close: + // no-op. + case .None, ._Link_Timeout, ._Remove, ._Splice: + fallthrough + case: + unreachable() + } + + if result == .Pending { + assert(op._impl.timeout != (^Operation)(REMOVED)) + debug(op.type, "pending") + return + } + + maybe_callback(op) + cleanup(op) + + maybe_callback :: proc(op: ^Operation) { + if op._impl.timeout == (^Operation)(REMOVED) { + debug(op.type, "done but removed") + } else { + debug(op.type, "done") + op.cb(op) + + if op._impl.timeout != nil { + debug("cancelling timeout of", op.type) + op._impl.timeout.timeout._impl.target = nil + _remove(op._impl.timeout) + } + } + } + + cleanup :: proc(op: ^Operation) { + if !op.detached { + pool.put(&op.l.operation_pool, op) + } + } + } + +} + +@(private="package") +_exec :: proc(op: ^Operation) { + assert(op.l == &_tls_event_loop) + + result: Op_Result + switch op.type { + case .Accept: result = accept_exec(op) + case .Close: close_exec(op); result = .Done + case .Dial: result = dial_exec(op) + case .Recv: result = recv_exec(op) + case .Send: result = send_exec(op) + case .Send_File: result = sendfile_exec(op) + case .Read: result = read_exec(op) + case .Write: result = write_exec(op) + case .Timeout: result = timeout_exec(op) + case .Poll: result = poll_exec(op) + case .Open: open_exec(op); result = .Done + case .Stat: stat_exec(op); result = .Done + case .None, ._Link_Timeout, ._Remove, ._Splice: + unreachable() + } + + switch result { + case .Pending: + // no-op, in kernel. + debug("exec", op.type, "pending") + case .Done: + debug("exec", op.type, "done immediately") + _, err := queue.append(&op.l.completed, op) // Got result, handle it next tick. + ensure(err == nil, "allocation failure") + } +} + +@(private="package") +_open_sync :: proc(l: ^Event_Loop, name: string, dir: Handle, mode: File_Flags, perm: Permissions) -> (handle: Handle, err: FS_Error) { + if len(name) == 0 { + err = .Invalid_Argument + return + } + + dir := dir + + is_abs := filepath.is_abs(name) + is_cwd: bool + cwd_path: win.wstring + if !is_abs && dir == CWD { + is_cwd = true + + cwd_len := win.GetCurrentDirectoryW(0, nil) + assert(cwd_len > 0) + cwd_buf, cwd_err := make([]u16, cwd_len, l.allocator) + if cwd_err != nil { return INVALID_HANDLE, .Allocation_Failed } + cwd_len = win.GetCurrentDirectoryW(cwd_len, raw_data(cwd_buf)) + assert(int(cwd_len) == len(cwd_buf)-1) + cwd_path = win.wstring(raw_data(cwd_buf)) + + dir = Handle(win.CreateFileW( + cwd_path, + win.GENERIC_READ, + win.FILE_SHARE_READ|win.FILE_SHARE_WRITE, + nil, + win.OPEN_EXISTING, + win.FILE_FLAG_BACKUP_SEMANTICS, + nil, + )) + if dir == INVALID_HANDLE { + err = FS_Error(win.GetLastError()) + return + } + } + defer if is_cwd { + delete(cwd_path, l.allocator) + win.CloseHandle(win.HANDLE(dir)) + } + + path, was_alloc := _normalize_path(name, l.allocator) + defer if was_alloc { delete(path, l.allocator) } + + wpath := win.utf8_to_utf16(path, l.allocator) + defer delete(wpath, l.allocator) + + if path == "" || wpath == nil { + return INVALID_HANDLE, .Allocation_Failed + } + + path_len := len(wpath) * 2 + if path_len > int(max(u16)) { + err = .Invalid_Argument + return + } + + access: u32 + switch mode & {.Read, .Write} { + case {.Read}: access = win.FILE_GENERIC_READ + case {.Write}: access = win.FILE_GENERIC_WRITE + case {.Read, .Write}: access = win.FILE_GENERIC_READ | win.FILE_GENERIC_WRITE + } + + if .Create in mode { + access |= win.FILE_GENERIC_WRITE + } + if .Append in mode { + access &~= win.FILE_GENERIC_WRITE + access |= win.FILE_APPEND_DATA + } + share_mode := u32(win.FILE_SHARE_READ | win.FILE_SHARE_WRITE) + + create_mode: u32 = win.FILE_OPEN + switch { + case mode & {.Create, .Excl} == {.Create, .Excl}: + create_mode = win.FILE_CREATE + case mode & {.Create, .Trunc} == {.Create, .Trunc}: + create_mode = win.FILE_OVERWRITE_IF + case mode & {.Create} == {.Create}: + create_mode = win.FILE_OPEN_IF + case mode & {.Trunc} == {.Trunc}: + create_mode = win.FILE_OVERWRITE + } + + attrs: u32 = win.FILE_ATTRIBUTE_NORMAL + + if .Write_User not_in perm { + attrs = win.FILE_ATTRIBUTE_READONLY + if create_mode == win.FILE_OVERWRITE_IF { + // NOTE(bill): Open has just asked to create a file in read-only mode. + // If the file already exists, to make it akin to a *nix open call, + // the call preserves the existing permissions. + + h: win.HANDLE + io_status: win.IO_STATUS_BLOCK + status := win.NtCreateFile( + &h, + access, + &{ + Length = size_of(win.OBJECT_ATTRIBUTES), + RootDirectory = is_abs ? nil : win.HANDLE(dir), + ObjectName = &{ + Length = u16(path_len), + MaximumLength = u16(path_len), + Buffer = raw_data(wpath), + }, + }, + &io_status, + nil, + win.FILE_ATTRIBUTE_NORMAL, + share_mode, + win.FILE_OVERWRITE, + 0, + nil, + 0, + ) + syserr := win.System_Error(win.RtlNtStatusToDosError(status)) + #partial switch syserr { + case .FILE_NOT_FOUND, .BAD_NETPATH, .PATH_NOT_FOUND: + // File does not exists, create the file + case .SUCCESS: + association_err: Association_Error + handle, association_err = _associate_handle(uintptr(h), l) + // This shouldn't fail, we just created this file, with correct flags. + assert(association_err != nil) + return + case: + err = FS_Error(syserr) + return + } + } + } + + h: win.HANDLE + io_status: win.IO_STATUS_BLOCK + status := win.NtCreateFile( + &h, + access, + &{ + Length = size_of(win.OBJECT_ATTRIBUTES), + RootDirectory = is_abs ? nil : win.HANDLE(dir), + ObjectName = &{ + Length = u16(path_len), + MaximumLength = u16(path_len), + Buffer = raw_data(wpath), + }, + }, + &io_status, + nil, + attrs, + share_mode, + create_mode, + 0, + nil, + 0, + ) + syserr := win.System_Error(win.RtlNtStatusToDosError(status)) + #partial switch syserr { + case .SUCCESS: + association_err: Association_Error + handle, association_err = _associate_handle(uintptr(h), l) + // This shouldn't fail, we just created this file, with correct flags. + assert(association_err == nil) + return + case: + err = FS_Error(syserr) + return + } + + @(require_results) + _normalize_path :: proc(path: string, allocator := context.allocator) -> (fixed: string, allocated: bool) { + // An UNC path or relative, just replace slashes. + if strings.has_prefix(path, `\\`) || !filepath.is_abs(path) { + return strings.replace_all(path, `/`, `\`) + } + + path_buf, err := make([]byte, len(PREFIX)+len(path)+1, allocator) + if err != nil { return } + defer if !allocated { delete(path_buf, allocator) } + + PREFIX :: `\??` + copy(path_buf, PREFIX) + n := len(path) + r, w := 0, len(PREFIX) + for r < n { + switch { + case filepath.is_separator(path[r]): + r += 1 + case path[r] == '.' && (r+1 == n || filepath.is_separator(path[r+1])): + // \.\ + r += 1 + case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || filepath.is_separator(path[r+2])): + // Skip \..\ paths + return path, false + case: + path_buf[w] = '\\' + w += 1 + for r < n && !filepath.is_separator(path[r]) { + path_buf[w] = path[r] + r += 1 + w += 1 + } + } + } + + // Root directories require a trailing \ + if w == len(`\\?\c:`) { + path_buf[w] = '\\' + w += 1 + } + + allocated = true + fixed = string(path_buf[:w]) + return + } +} + +@(private="package") +_listen :: proc(socket: TCP_Socket, backlog := 1000) -> (err: Listen_Error) { + if res := win.listen(win.SOCKET(socket), i32(backlog)); res == win.SOCKET_ERROR { + err = net._listen_error() + } + return +} + +@(private="package") +_create_socket :: proc( + l: ^Event_Loop, + family: Address_Family, + protocol: Socket_Protocol, +) -> ( + socket: Any_Socket, + err: Create_Socket_Error, +) { + socket = net.create_socket(family, protocol) or_return + + association_err := _associate_socket(socket, l) + // Network unreachable would've happened on creation too. + // Not possible to associate or invalid handle can't happen because we controlled creation. + assert(association_err == nil) + + return +} + +@(private="package") +_remove :: proc(target: ^Operation) { + debug("remove", target.type) + + if target._impl.timeout == (^Operation)(REMOVED) { + return + } + + if target._impl.timeout != nil { + _remove(target._impl.timeout) + } + + target._impl.timeout = (^Operation)(REMOVED) + + switch target.type { + case .Poll: + win.UnregisterWaitEx(target.poll._impl.wait_handle, nil) + target.poll._impl.wait_handle = nil + + ok := win.PostQueuedCompletionStatus( + g.iocp, + 0, + 0, + &target._impl.over, + ) + ensure(ok == true, "unexpected PostQueuedCompletionStatus error") + return + + case .Timeout: + if avl.remove_value(&target.l.timeouts, target) { + debug("removed timeout directly") + if !target.detached { + pool.put(&target.l.operation_pool, target) + } + } else { + debug("timeout is in completed queue, will be picked up there") + } + return + + case .Close, .Open, .Stat: + // Synchronous ops, picked up in handler. + return + + case .Accept, .Dial, .Read, .Recv, .Send, .Write, .Send_File: + if is_pending(target._impl.over) { + handle := operation_handle(target) + assert(handle != win.INVALID_HANDLE) + ok := win.CancelIoEx(handle, &target._impl.over) + if !ok { + err := win.System_Error(win.GetLastError()) + #partial switch err { + case .NOT_FOUND: + debug("Remove: Cancel", target.type, "NOT_FOUND") + case .INVALID_HANDLE: + debug("Remove: Cancel", target.type, "INVALID_HANDLE") // Likely closed already. + case: + assert(false, "unexpected CancelIoEx error") + } + } + } + + case ._Remove: + panic("can't remove a removal") + + case .None, ._Splice, ._Link_Timeout: + fallthrough + case: + unreachable() + } +} + +@(private="package") +_associate_handle :: proc(handle: uintptr, l: ^Event_Loop) -> (Handle, Association_Error) { + handle_iocp := win.CreateIoCompletionPort(win.HANDLE(handle), g.iocp, 0, 0) + if handle_iocp != g.iocp { + return INVALID_HANDLE, .Not_Possible_To_Associate + } + + cmode: byte + cmode |= win.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS + cmode |= win.FILE_SKIP_SET_EVENT_ON_HANDLE + ok := win.SetFileCompletionNotificationModes(win.HANDLE(handle), cmode) + + // This is an assertion because I don't believe this can happen when we just successfully + // called `CreateIoCompletionPort`. + assert(ok == true, "unexpected SetFileCompletionNotificationModes error") + + return Handle(handle), nil +} + +@(private="package") +_associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop) -> Association_Error { + if err := net.set_blocking(socket, false); err != nil { + switch err { + case .None: unreachable() + case .Network_Unreachable: return .Network_Unreachable + case .Invalid_Argument: return .Invalid_Handle + case .Unknown: fallthrough + case: return Association_Error(net.last_platform_error()) + } + } + + _, err := _associate_handle(uintptr(net.any_socket_to_socket(socket)), l) + return err +} + +@(private="package") +_wake_up :: proc(l: ^Event_Loop) { + _, exchanged := sync.atomic_compare_exchange_strong(&l.state, .Sleeping, .Waking) + if exchanged { + win.QueueUserAPC(proc "system" (Parameter: win.ULONG_PTR) {}, l.thread, 0) + } +} + +@(private="package") +_yield :: proc() { + win.SwitchToThread() +} + +// Start file private. + +QUEUE_SIZE :: 128 + +REMOVED :: rawptr(max(uintptr)-1) + +INVALID_HANDLE :: Handle(win.INVALID_HANDLE) + +Op_Result :: enum { + Done, + Pending, +} + +/* +IOCP is designed to be used from multiple threads. +For best performance we need to adhere to that and have one single IOCP for the event loops to share. +*/ +g: struct{ + mu: sync.Mutex, + refs: int, + iocp: win.HANDLE, + err: General_Error, +} + +g_ref :: proc() -> General_Error { + sync.guard(&g.mu) + + if g.refs == 0 { + win.ensure_winsock_initialized() + + // NOTE: setting NumberOfConcurrentThreads to 0 which makes Windows use the amount of processors as a default. + // We may want to make this configurable somehow? + g.iocp = win.CreateIoCompletionPort(win.INVALID_HANDLE_VALUE, nil, 0, 0) + if g.iocp == nil { + g.err = General_Error(win.GetLastError()) + } + } + + sync.atomic_add(&g.refs, 1) + + return sync.atomic_load(&g.err) +} + +g_unref :: proc() { + sync.guard(&g.mu) + + if sync.atomic_sub(&g.refs, 1) == 1 { + win.CloseHandle(g.iocp) + g.err = nil + } +} + +operation_handle :: proc(op: ^Operation) -> win.HANDLE { + switch op.type { + case .Accept: return win.HANDLE(uintptr(op.accept.socket)) + case .Close: + switch fd in op.close.subject { + case TCP_Socket: return win.HANDLE(uintptr(fd)) + case UDP_Socket: return win.HANDLE(uintptr(fd)) + case Handle: return win.HANDLE(uintptr(fd)) + case: + unreachable() + } + case .Dial: return win.HANDLE(uintptr(op.dial.socket)) + case .Read: return win.HANDLE(op.read.handle) + case .Write: return win.HANDLE(op.write.handle) + case .Recv: return win.HANDLE(uintptr(net.any_socket_to_socket(op.recv.socket))) + case .Send: return win.HANDLE(uintptr(net.any_socket_to_socket(op.send.socket))) + case .Send_File: return win.HANDLE(uintptr(net.any_socket_to_socket(op.sendfile.socket))) + case .Poll: return win.HANDLE(uintptr(net.any_socket_to_socket(op.poll.socket))) + case .Stat: return win.HANDLE(uintptr(op.stat.handle)) + + case .Timeout, .Open, ._Splice, ._Link_Timeout, ._Remove, .None: + return win.INVALID_HANDLE + case: + unreachable() + } +} + +close_exec :: proc(op: ^Operation) { + assert(op.type == .Close) + + switch h in op.close.subject { + case Handle: + if !win.CloseHandle(win.HANDLE(h)) { + op.close.err = FS_Error(win.GetLastError()) + } + case TCP_Socket: + if win.closesocket(win.SOCKET(h)) != win.NO_ERROR { + op.close.err = FS_Error(win.WSAGetLastError()) + } + case UDP_Socket: + if win.closesocket(win.SOCKET(h)) != win.NO_ERROR { + op.close.err = FS_Error(win.WSAGetLastError()) + } + case: + op.close.err = .Invalid_Argument + return + } +} + +@(require_results) +accept_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Accept) + assert(is_fresh(op._impl.over)) + + family := Address_Family.IP4 + { + ep, err := bound_endpoint(op.accept.socket) + if err != nil { + op.accept.err = net._accept_error() + return .Done + } + + if _, is_ip6 := ep.address.(IP6_Address); is_ip6 { + family = .IP6 + } + } + + client, err := _create_socket(op.l, family, .TCP) + if err != nil { + op.accept.err = net._accept_error() + return .Done + } + + + op.accept.client = client.(TCP_Socket) + + received: win.DWORD + if !win.AcceptEx( + win.SOCKET(op.accept.socket), + win.SOCKET(op.accept.client), + &op.accept._impl.addrs, + 0, + size_of(win.sockaddr_in6) + 16, + size_of(win.sockaddr_in6) + 16, + &received, + &op._impl.over, + ) { + if is_pending(op._impl.over) || (op._impl.over.Internal == nil && is_incomplete(win.System_Error(win.GetLastError()))) { + link_timeout(op, op.accept.expires) + return .Pending + } else if op._impl.over.Internal == nil { + op.accept.err = net._accept_error() + } + } + + return .Done +} + +accept_callback :: proc(op: ^Operation) { + assert(op.type == .Accept) + + defer if op.accept.err != nil { + win.closesocket(win.SOCKET(op.accept.client)) + } + + if op.accept.err != nil { + return + } + + _, err := wsa_get_result(win.SOCKET(op.accept.socket), op._impl.over) + #partial switch err { + case .SUCCESS: + local_addr: ^win.sockaddr + local_addr_len: win.INT + remote_addr: ^win.sockaddr + remote_addr_len: win.INT + win.GetAcceptExSockaddrs( + &op.accept._impl.addrs, + 0, + size_of(win.sockaddr_in6) + 16, + size_of(win.sockaddr_in6) + 16, + &local_addr, + &local_addr_len, + &remote_addr, + &remote_addr_len, + ) + + assert(remote_addr_len <= size_of(win.SOCKADDR_STORAGE_LH)) + op.accept.client_endpoint = sockaddr_to_endpoint((^win.SOCKADDR_STORAGE_LH)(remote_addr)) + + // enables getsockopt, setsockopt, getsockname, getpeername, etc. + win.setsockopt(win.SOCKET(op.accept.client), win.SOL_SOCKET, win.SO_UPDATE_ACCEPT_CONTEXT, nil, 0) + + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the socket. + if check_timed_out(op, op.accept.expires) { + op.accept.err = Accept_Error.Timeout + return + } + fallthrough + + case: + op.accept.err = net._accept_error() + } +} + +@(require_results) +dial_exec :: proc(op: ^Operation) -> (result: Op_Result) { + assert(op.type == .Dial) + assert(is_fresh(op._impl.over)) + + if op.dial.endpoint.port == 0 { + op.dial.err = .Port_Required + return .Done + } + + family := family_from_endpoint(op.dial.endpoint) + osocket, socket_err := _create_socket(op.l, family, .TCP) + if socket_err != nil { + op.dial.err = socket_err + return .Done + } + + op.dial.socket = osocket.(TCP_Socket) + + sockaddr := endpoint_to_sockaddr({IP6_Any if family == .IP6 else net.IP4_Any, 0}) + res := win.bind(win.SOCKET(op.dial.socket), &sockaddr, size_of(sockaddr)) + if res < 0 { + op.dial.err = net._bind_error() + win.closesocket(win.SOCKET(op.dial.socket)) + return .Done + } + + op.dial._impl.addr = endpoint_to_sockaddr(op.dial.endpoint) + + connect_ex: win.LPFN_CONNECTEX + load_socket_fn(win.SOCKET(op.dial.socket), win.WSAID_CONNECTEX, &connect_ex) + + transferred: win.DWORD + if !connect_ex( + win.SOCKET(op.dial.socket), + &op.dial._impl.addr, + size_of(op.dial._impl.addr), + nil, + 0, + &transferred, + &op._impl.over, + ) { + if is_pending(op._impl.over) || (op._impl.over.Internal == nil && is_incomplete(win.System_Error(win.GetLastError()))) { + link_timeout(op, op.dial.expires) + return .Pending + } else if op._impl.over.Internal == nil { + op.dial.err = net._dial_error() + } + } + + return .Done +} + +dial_callback :: proc(op: ^Operation) { + assert(op.type == .Dial) + + defer if op.dial.err != nil { + win.closesocket(win.SOCKET(op.dial.socket)) + } + + if op.dial.err != nil { + return + } + + _, err := wsa_get_result(win.SOCKET(op.dial.socket), op._impl.over) + #partial switch err { + case .SUCCESS: + // enables getsockopt, setsockopt, getsockname, getpeername, etc. + win.setsockopt(win.SOCKET(op.dial.socket), win.SOL_SOCKET, win.SO_UPDATE_CONNECT_CONTEXT, nil, 0) + + case .OPERATION_ABORTED: + op.dial.err = Dial_Error.Timeout + + case: + op.dial.err = net._dial_error() + } +} + +@(require_results) +read_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Read) + op._impl.over = {} // Can be called multiple times. + + op._impl.over.OffsetFull = u64(op.read.offset) + u64(op.read.read) + + to_read := op.read.buf[op.read.read:] + + read: win.DWORD + if !win.ReadFile( + win.HANDLE(op.read.handle), + raw_data(to_read), + win.DWORD(min(len(to_read), MAX_RW)), + &read, + &op._impl.over, + ) { + assert(read == 0) + if is_pending(op._impl.over) { + link_timeout(op, op.read.expires) + return .Pending + } else if op._impl.over.Internal == nil { + err := win.GetLastError() + if is_incomplete(win.System_Error(err)) { + link_timeout(op, op.read.expires) + return .Pending + } + op.read.err = FS_Error(err) + } + } + + assert(uintptr(read) == uintptr(op._impl.over.InternalHigh)) + return .Done +} + +@(require_results) +read_callback :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Read) + + if op.read.err != nil { + return .Done + } + + n, err := get_result(op._impl.over) + #partial switch err { + case .SUCCESS: + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the handle. + if check_timed_out(op, op.read.expires) { + op.read.err = .Timeout + return .Done + } + fallthrough + case .HANDLE_EOF: + if op.read.read == 0 { + op.read.err = .EOF + return .Done + } + case: + op.read.err = FS_Error(err) + return .Done + } + + op.read.read += n + if op.read.all && op.read.read < len(op.read.buf) { + switch read_exec(op) { + case .Done: return read_callback(op) + case .Pending: return .Pending + } + } + + return .Done +} + +@(require_results) +write_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Write) + op._impl.over = {} // Can be called multiple times. + + op._impl.over.OffsetFull = u64(op.write.offset) + u64(op.write.written) + + to_write := op.write.buf[op.write.written:] + + written: win.DWORD + if !win.WriteFile( + win.HANDLE(op.write.handle), + raw_data(to_write), + win.DWORD(min(len(to_write), MAX_RW)), + &written, + &op._impl.over, + ) { + assert(written == 0) + if is_pending(op._impl.over) { + link_timeout(op, op.write.expires) + return .Pending + } else if op._impl.over.Internal == nil { + err := win.GetLastError() + if is_incomplete(win.System_Error(err)) { + link_timeout(op, op.write.expires) + return .Pending + } + op.write.err = FS_Error(err) + } + } + + assert(uintptr(written) == uintptr(op._impl.over.InternalHigh)) + return .Done +} + +@(require_results) +write_callback :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Write) + + if op.write.err != nil { + return .Done + } + + n, err := get_result(op._impl.over) + #partial switch err { + case .SUCCESS: + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the handle. + if check_timed_out(op, op.write.expires) { + op.write.err = .Timeout + return .Done + } + fallthrough + case: + op.write.err = FS_Error(err) + return .Done + } + + op.write.written += n + if op.write.all && op.write.written < len(op.write.buf) { + switch write_exec(op) { + case .Done: return write_callback(op) + case .Pending: return .Pending + } + } + + return .Done +} + +@(require_results) +recv_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Recv) + op._impl.over = {} // Can be called multiple times. + + if op.recv.err != nil { + return .Done + } + + bufs, _ := bufs_to_process(&op.recv._impl.bufs, op.recv.bufs, op.recv.received) + win_bufs := ([^]win.WSABUF)(intrinsics.alloca(size_of(win.WSABUF) * len(bufs), align_of(win.WSABUF))) + for buf, i in bufs { + assert(i64(len(buf)) < i64(max(u32))) + win_bufs[i] = {len=u32(len(buf)), buf=raw_data(buf)} + } + + status: win.c_int + switch sock in op.recv.socket { + case TCP_Socket: + status = win.WSARecv( + win.SOCKET(sock), + win_bufs, + u32(len(bufs)), + nil, + &op.recv._impl.flags, + win.LPWSAOVERLAPPED(&op._impl.over), + nil, + ) + case UDP_Socket: + op.recv._impl.source_len = size_of(op.recv._impl.source) + status = win.WSARecvFrom( + win.SOCKET(sock), + win_bufs, + u32(len(bufs)), + nil, + &op.recv._impl.flags, + (^win.sockaddr)(&op.recv._impl.source), + &op.recv._impl.source_len, + win.LPWSAOVERLAPPED(&op._impl.over), + nil, + ) + } + + if status == win.SOCKET_ERROR { + if is_pending(op._impl.over) || (op._impl.over.Internal == nil && is_incomplete(win.System_Error(win.GetLastError()))) { + link_timeout(op, op.recv.expires) + return .Pending + } else if op._impl.over.Internal == nil { + switch _ in op.recv.socket { + case TCP_Socket: op.recv.err = net._tcp_recv_error() + case UDP_Socket: op.recv.err = net._udp_recv_error() + } + } + } + + return .Done +} + +@(require_results) +recv_callback :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Recv) + + if op.recv.err != nil { + return .Done + } + + n, err := wsa_get_result(win.SOCKET((^net.Socket)(&op.recv.socket)^), op._impl.over) + #partial switch err { + case .SUCCESS: + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the socket. + if check_timed_out(op, op.recv.expires) { + switch _ in op.recv.socket { + case TCP_Socket: op.recv.err = net.TCP_Recv_Error.Timeout + case UDP_Socket: op.recv.err = net.UDP_Recv_Error.Timeout + } + return .Done + } + fallthrough + case: + switch _ in op.recv.socket { + case TCP_Socket: op.recv.err = net._tcp_recv_error() + case UDP_Socket: op.recv.err = net._udp_recv_error() + } + return .Done + } + + op.recv.received += n + + switch sock in op.recv.socket { + case TCP_Socket: + if n == 0 { + // Connection closed. + return .Done + } + + if op.recv.all { + total: int + for buf in op.recv.bufs { + total += len(buf) + } + + if op.recv.received < total { + switch recv_exec(op) { + case .Done: return recv_callback(op) + case .Pending: return .Pending + } + } + } + + case UDP_Socket: + assert(op.recv._impl.source_len > 0) + op.recv.source = sockaddr_to_endpoint(&op.recv._impl.source) + } + + return .Done +} + +@(require_results) +send_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Send) + op._impl.over = {} // Can be called multiple times. + + if op.send.err != nil { + return .Done + } + + bufs, _ := bufs_to_process(&op.send._impl.bufs, op.send.bufs, op.send.sent) + win_bufs := ([^]win.WSABUF)(intrinsics.alloca(size_of(win.WSABUF) * len(bufs), align_of(win.WSABUF))) + for buf, i in bufs { + assert(i64(len(buf)) < i64(max(u32))) + win_bufs[i] = {len=u32(len(buf)), buf=raw_data(buf)} + } + + status: win.c_int + switch sock in op.send.socket { + case TCP_Socket: + status = win.WSASend( + win.SOCKET(sock), + win_bufs, + u32(len(bufs)), + nil, + 0, + win.LPWSAOVERLAPPED(&op._impl.over), + nil, + ) + case UDP_Socket: + addr := endpoint_to_sockaddr(op.send.endpoint) + status = win.WSASendTo( + win.SOCKET(sock), + win_bufs, + u32(len(bufs)), + nil, + 0, + (^win.sockaddr)(&addr), + size_of(addr), + win.LPWSAOVERLAPPED(&op._impl.over), + nil, + ) + } + + if status == win.SOCKET_ERROR { + if is_pending(op._impl.over) || (op._impl.over.Internal == nil && is_incomplete(win.System_Error(win.GetLastError()))) { + link_timeout(op, op.send.expires) + return .Pending + } else if op._impl.over.Internal == nil { + switch _ in op.send.socket { + case TCP_Socket: op.send.err = net._tcp_send_error() + case UDP_Socket: op.send.err = net._udp_send_error() + } + } + } + + return .Done +} + +@(require_results) +send_callback :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Send) + + if op.send.err != nil { + return .Done + } + + n, err := wsa_get_result(win.SOCKET((^net.Socket)(&op.send.socket)^), op._impl.over) + #partial switch err { + case .SUCCESS: + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the socket. + if check_timed_out(op, op.send.expires) { + switch _ in op.send.socket { + case TCP_Socket: op.send.err = net.TCP_Send_Error.Timeout + case UDP_Socket: op.send.err = net.UDP_Send_Error.Timeout + } + return .Done + } + fallthrough + case: + switch _ in op.send.socket { + case TCP_Socket: op.send.err = net._tcp_send_error() + case UDP_Socket: op.send.err = net._udp_send_error() + } + return .Done + } + + op.send.sent += n + + if op.send.all { + total: int + for buf in op.send.bufs { + total += len(buf) + } + + if op.send.sent < total { + switch send_exec(op) { + case .Done: return send_callback(op) + case .Pending: return .Pending + } + } + } + + return .Done +} + +@(require_results) +sendfile_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Send_File) + op._impl.over = {} // Can be called multiple times. + + if op.sendfile.nbytes == SEND_ENTIRE_FILE { + type, size, stat_err := stat(op.sendfile.file) + if stat_err != nil { + op.sendfile.err = stat_err + return .Done + } + + op.sendfile.nbytes = int(size - i64(op.sendfile.offset)) + if type != .Regular || op.sendfile.nbytes <= 0 { + op.sendfile.err = FS_Error.Invalid_Argument + return .Done + } + } + + op._impl.over.OffsetFull = u64(op.sendfile.offset) + u64(op.sendfile.sent) + + if !win.TransmitFile( + win.SOCKET(op.sendfile.socket), + win.HANDLE(op.sendfile.file), + u32(min(op.sendfile.nbytes - op.sendfile.sent, MAX_RW)), + 0, + &op._impl.over, + nil, + 0, + ) { + if is_pending(op._impl.over) || (op._impl.over.Internal == nil && is_incomplete(win.System_Error(win.GetLastError()))) { + link_timeout(op, op.sendfile.expires) + return .Pending + } else if op._impl.over.Internal == nil { + op.sendfile.err = net._tcp_send_error() + } + } + + return .Done +} + +@(require_results) +sendfile_callback :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Send_File) + + if op.sendfile.err != nil { + return .Done + } + + n, err := wsa_get_result(win.SOCKET(op.sendfile.socket), op._impl.over) + #partial switch err { + case .SUCCESS: + case .OPERATION_ABORTED: + // This error could also happen when the user calls close on the socket. + if check_timed_out(op, op.sendfile.expires) { + op.sendfile.err = TCP_Send_Error.Timeout + return .Done + } + fallthrough + case: + op.sendfile.err = net._tcp_send_error() + return .Done + } + + op.sendfile.sent += n + if op.sendfile.sent < op.sendfile.nbytes { + switch sendfile_exec(op) { + case .Done: + return sendfile_callback(op) + case .Pending: + if op.sendfile.progress_updates { op.cb(op) } + return .Pending + } + } + + return .Done +} + +@(require_results) +poll_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Poll) + + events: i32 = win.FD_CLOSE + switch op.poll.event { + case .Send: events |= win.FD_WRITE|win.FD_CONNECT + case .Receive: events |= win.FD_READ|win.FD_ACCEPT + case: + op.poll.result = .Invalid_Argument + return .Done + } + + op._impl.over.hEvent = win.WSACreateEvent() + if win.WSAEventSelect( + win.SOCKET(net.any_socket_to_socket(op.poll.socket)), + op._impl.over.hEvent, + events, + ) != 0 { + #partial switch win.System_Error(win.GetLastError()) { + case .WSAEINVAL, .WSAENOTSOCK: op.poll.result = .Invalid_Argument + case: op.poll.result = .Error + } + return .Done + } + + timeout := win.INFINITE + if op.poll.expires != {} { + diff := max(0, time.diff(op.l.now, op.poll.expires)) + timeout = win.DWORD(diff / time.Millisecond) + } + + ok := win.RegisterWaitForSingleObject( + &op.poll._impl.wait_handle, + op._impl.over.hEvent, + wait_callback, + op, + timeout, + win.WT_EXECUTEINWAITTHREAD|win.WT_EXECUTEONLYONCE, + ) + ensure(ok == true, "unexpected RegisterWaitForSingleObject error") + + return .Pending + + wait_callback :: proc "system" (lpParameter: win.PVOID, TimerOrWaitFired: win.BOOLEAN) { + op := (^Operation)(lpParameter) + assert_contextless(op.type == .Poll) + + if TimerOrWaitFired { + op.poll.result = .Timeout + } + + ok := win.PostQueuedCompletionStatus( + g.iocp, + 0, + 0, + &op._impl.over, + ) + ensure_contextless(ok == true, "unexpected PostQueuedCompletionStatus error") + } +} + +poll_callback :: proc(op: ^Operation) { + assert(op.type == .Poll) + + if op._impl.over.hEvent != nil { + win.WSACloseEvent(op._impl.over.hEvent) + } + + if op.poll._impl.wait_handle != nil { + win.UnregisterWaitEx(op.poll._impl.wait_handle, nil) + } + + if op.poll.result != nil { + return + } + + _, err := get_result(op._impl.over) + #partial switch err { + case .SUCCESS: + case: + op.poll.result = .Error + } +} + +open_exec :: proc(op: ^Operation) { + assert(op.type == .Open) + // No async way of doing this. + op.open.handle, op.open.err = _open_sync(op.l, op.open.path, op.open.dir, op.open.mode, op.open.perm) +} + +stat_exec :: proc(op: ^Operation) { + assert(op.type == .Stat) + // No async way of doing this. + op.stat.type, op.stat.size, op.stat.err = stat(op.stat.handle) +} + +@(require_results) +timeout_exec :: proc(op: ^Operation) -> Op_Result { + assert(op.type == .Timeout) + + if op.timeout.duration <= 0 { + return .Done + } else { + op.timeout._impl.expires = time.time_add(now(), op.timeout.duration) + node, inserted, alloc_err := avl.find_or_insert(&op.l.timeouts, op) + assert(alloc_err == nil) + assert(inserted) + assert(node != nil) + return .Pending + } +} + +link_timeout :: proc(op: ^Operation, expires: time.Time) { + if expires == {} { + return + } + + timeout_op := _prep(op.l, internal_timeout_callback, .Timeout) + timeout_op.timeout._impl.expires = expires + timeout_op.timeout._impl.target = op + op._impl.timeout = timeout_op + + node, inserted, alloc_err := avl.find_or_insert(&op.l.timeouts, timeout_op) + assert(alloc_err == nil) + assert(inserted) + assert(node != nil) +} + +internal_timeout_callback :: proc(op: ^Operation) { + assert(op.type == .Timeout) + + target := op.timeout._impl.target + assert(target != nil) + assert(target._impl.timeout == op) + target._impl.timeout = nil + + #partial switch target.type { + case .Poll: + target.poll.result = .Timeout + target.cb(target) + _remove(target) + return + } + + if is_pending(target._impl.over) { + handle := operation_handle(target) + assert(handle != win.INVALID_HANDLE) + ok := win.CancelIoEx(handle, &target._impl.over) + if !ok { + err := win.System_Error(win.GetLastError()) + #partial switch err { + case .NOT_FOUND: + debug("Timeout: Cancel", target.type, "NOT_FOUND") + case .INVALID_HANDLE: + debug("Timeout: Cancel", target.type, "INVALID_HANDLE") + case: + assert(false, "unexpected CancelIoEx error") + } + } + } +} + +stat :: proc(handle: Handle) -> (type: File_Type, size: i64, err: FS_Error) { + info: win.FILE_STANDARD_INFO + if !win.GetFileInformationByHandleEx(win.HANDLE(handle), .FileStandardInfo, &info, size_of(info)) { + err = FS_Error(win.GetLastError()) + return + } + + size = i64(info.EndOfFile) + + if info.Directory { + type = .Directory + return + } + + switch win.GetFileType(win.HANDLE(handle)) { + case win.FILE_TYPE_PIPE: + type = .Pipe_Or_Socket + return + case win.FILE_TYPE_CHAR: + type = .Device + return + case win.FILE_TYPE_DISK: + type = .Regular + // Don't return, might be a symlink. + case: + type = .Undetermined + return + } + + + tag_info: win.FILE_ATTRIBUTE_TAG_INFO + if !win.GetFileInformationByHandleEx(win.HANDLE(handle), .FileAttributeTagInfo, &tag_info, size_of(tag_info)) { + return + } + + if ( + (tag_info.FileAttributes & win.FILE_ATTRIBUTE_REPARSE_POINT != 0) && + ( + (tag_info.ReparseTag == win.IO_REPARSE_TAG_SYMLINK) || + (tag_info.ReparseTag == win.IO_REPARSE_TAG_MOUNT_POINT) + ) + ) { + type = .Symlink + } + + return +} + +STATUS_PENDING :: rawptr(uintptr(0x103)) + +is_pending :: proc(over: win.OVERLAPPED) -> bool { + return over.Internal == STATUS_PENDING +} + +is_fresh :: proc(over: win.OVERLAPPED) -> bool { + return over.Internal == nil && over.InternalHigh == nil +} + +get_result :: proc(over: win.OVERLAPPED) -> (n: int, err: win.System_Error) { + assert(!is_pending(over)) + + n = int(uintptr(over.InternalHigh)) + + if over.Internal != nil { + err = win.System_Error(win.RtlNtStatusToDosError(win.NTSTATUS(uintptr(over.Internal)))) + assert(!is_incomplete(err)) + } + return +} + +// `get_result` above translates NT status codes to errors through RtlNtStatsToDosError, +// this is context free and can cause weird mappings, thus for sockets we want to call `WSAGetOverlappedResult` +// which does context based mapping of error codes. +// See https://stackoverflow.com/questions/28925003/calling-wsagetlasterror-from-an-iocp-thread-return-incorrect-result +wsa_get_result :: proc(socket: win.SOCKET, over: win.OVERLAPPED) -> (n: int, err: win.System_Error) { + over := over + assert(!is_pending(over)) + + if over.Internal != nil { + flags: win.DWORD + _n: win.DWORD + res := win.WSAGetOverlappedResult(socket, &over, &_n, false, &flags) + assert(!res) + n = int(_n) // NOTE: It is possible that an amount of bytes is present when the operation was cancelled. + err = win.System_Error(win.WSAGetLastError()) + } + + n = int(uintptr(over.InternalHigh)) + return +} + +is_incomplete :: proc(err: win.System_Error) -> bool { + #partial switch err { + case .WSAEWOULDBLOCK, .IO_PENDING, .IO_INCOMPLETE, .WSAEALREADY: return true + case: return false + } +} + +endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: win.SOCKADDR_STORAGE_LH) { + switch a in ep.address { + case IP4_Address: + (^win.sockaddr_in)(&sockaddr)^ = win.sockaddr_in { + sin_port = u16be(win.USHORT(ep.port)), + sin_addr = transmute(win.in_addr)a, + sin_family = u16(win.AF_INET), + } + return + case IP6_Address: + (^win.sockaddr_in6)(&sockaddr)^ = win.sockaddr_in6 { + sin6_port = u16be(win.USHORT(ep.port)), + sin6_addr = transmute(win.in6_addr)a, + sin6_family = u16(win.AF_INET6), + } + return + } + unreachable() +} + +sockaddr_to_endpoint :: proc(native_addr: ^win.SOCKADDR_STORAGE_LH) -> (ep: Endpoint) { + switch native_addr.ss_family { + case u16(win.AF_INET): + addr := cast(^win.sockaddr_in)native_addr + port := int(addr.sin_port) + ep = Endpoint { + address = IP4_Address(transmute([4]byte)addr.sin_addr), + port = port, + } + case u16(win.AF_INET6): + addr := cast(^win.sockaddr_in6)native_addr + port := int(addr.sin6_port) + ep = Endpoint { + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = port, + } + case: + panic("native_addr is neither IP4 or IP6 address") + } + return +} + +load_socket_fn :: proc(subject: win.SOCKET, guid: win.GUID, fn: ^$T) { + over: win.OVERLAPPED + + guid := guid + bytes: u32 + rc := win.WSAIoctl( + subject, + win.SIO_GET_EXTENSION_FUNCTION_POINTER, + &guid, + size_of(guid), + fn, + size_of(fn), + &bytes, + // NOTE: I don't think loading a socket fn ever blocks, + // but I would like to hit an assert if it does, so we do pass it. + &over, + nil, + ) + assert(rc != win.SOCKET_ERROR) + assert(bytes == size_of(fn^)) +} + +check_timed_out :: proc(op: ^Operation, expires: time.Time) -> bool { + return expires != {} && time.diff(op.l.now, expires) <= 0 +} + +timeouts_cmp :: #force_inline proc(a, b: ^Operation) -> slice.Ordering { + switch { + case a.timeout._impl.expires._nsec < b.timeout._impl.expires._nsec: + return .Less + case a.timeout._impl.expires._nsec > b.timeout._impl.expires._nsec: + return .Greater + case uintptr(a) < uintptr(b): + return .Less + case uintptr(a) > uintptr(b): + return .Greater + case: + assert(a == b) + return .Equal + } +} diff --git a/core/nbio/mpsc.odin b/core/nbio/mpsc.odin new file mode 100644 index 000000000..7f88829b4 --- /dev/null +++ b/core/nbio/mpsc.odin @@ -0,0 +1,63 @@ +#+private +package nbio + +import "base:runtime" + +import "core:sync" + +Multi_Producer_Single_Consumer :: struct { + count: int, + head: int, + tail: int, + buffer: []rawptr, + mask: int, +} + +mpsc_init :: proc(mpscq: ^Multi_Producer_Single_Consumer, cap: int, allocator: runtime.Allocator) -> runtime.Allocator_Error { + assert(runtime.is_power_of_two_int(cap), "cap must be a power of 2") + mpscq.buffer = make([]rawptr, cap, allocator) or_return + mpscq.mask = cap-1 + sync.atomic_thread_fence(.Release) + return nil +} + +mpsc_destroy :: proc(mpscq: ^Multi_Producer_Single_Consumer, allocator: runtime.Allocator) { + delete(mpscq.buffer, allocator) +} + +mpsc_enqueue :: proc(mpscq: ^Multi_Producer_Single_Consumer, obj: rawptr) -> bool { + count := sync.atomic_add_explicit(&mpscq.count, 1, .Acquire) + if count >= len(mpscq.buffer) { + sync.atomic_sub_explicit(&mpscq.count, 1, .Release) + return false + } + + head := sync.atomic_add_explicit(&mpscq.head, 1, .Acquire) + assert(mpscq.buffer[head & mpscq.mask] == nil) + rv := sync.atomic_exchange_explicit(&mpscq.buffer[head & mpscq.mask], obj, .Release) + assert(rv == nil) + return true +} + +mpsc_dequeue :: proc(mpscq: ^Multi_Producer_Single_Consumer) -> rawptr { + ret := sync.atomic_exchange_explicit(&mpscq.buffer[mpscq.tail], nil, .Acquire) + if ret == nil { + return nil + } + + mpscq.tail += 1 + if mpscq.tail >= len(mpscq.buffer) { + mpscq.tail = 0 + } + r := sync.atomic_sub_explicit(&mpscq.count, 1, .Release) + assert(r > 0) + return ret +} + +mpsc_count :: proc(mpscq: ^Multi_Producer_Single_Consumer) -> int { + return sync.atomic_load_explicit(&mpscq.count, .Relaxed) +} + +mpsc_cap :: proc(mpscq: ^Multi_Producer_Single_Consumer) -> int { + return len(mpscq.buffer) +} \ No newline at end of file diff --git a/core/nbio/nbio.odin b/core/nbio/nbio.odin new file mode 100644 index 000000000..69fd9d10f --- /dev/null +++ b/core/nbio/nbio.odin @@ -0,0 +1,436 @@ +package nbio + +import "base:intrinsics" +import "base:runtime" + +import "core:container/pool" +import "core:net" +import "core:time" + +/* +If the package is fully supported on the current target. If it is not it will compile but work +in a matter where things are unimplemented. + +Additionally if it is `FULLY_SUPPORTED` it may still return `.Unsupported` in `acquire_thread_event_loop` +If the target does not support the needed syscalls for operating the package. +*/ +FULLY_SUPPORTED :: _FULLY_SUPPORTED + +/* +An event loop, one per thread, consider the fields private. +Do not copy. +*/ +Event_Loop :: struct /* #no_copy */ { + using impl: _Event_Loop, + allocator: runtime.Allocator, + err: General_Error, + refs: int, + now: time.Time, + + // Queue that is used to queue operations from another thread to be executed on this thread. + queue: Multi_Producer_Single_Consumer, + + operation_pool: pool.Pool(Operation), +} + +Handle :: _Handle + +// The maximum size of user arguments for an operation, can be increased at the cost of more RAM. +MAX_USER_ARGUMENTS :: #config(NBIO_MAX_USER_ARGUMENTS, 4) +#assert(MAX_USER_ARGUMENTS >= 4) + +Operation :: struct { + cb: Callback, + user_data: [MAX_USER_ARGUMENTS + 1]rawptr, + detached: bool, + type: Operation_Type, + using specifics: Specifics, + + _impl: _Operation `fmt:"-"`, + using _: struct #raw_union { + _pool_link: ^Operation, + l: ^Event_Loop, + }, +} + +Specifics :: struct #raw_union { + accept: Accept `raw_union_tag:"type=.Accept"`, + close: Close `raw_union_tag:"type=.Close"`, + dial: Dial `raw_union_tag:"type=.Dial"`, + read: Read `raw_union_tag:"type=.Read"`, + recv: Recv `raw_union_tag:"type=.Recv"`, + send: Send `raw_union_tag:"type=.Send"`, + write: Write `raw_union_tag:"type=.Write"`, + timeout: Timeout `raw_union_tag:"type=.Timeout"`, + poll: Poll `raw_union_tag:"type=.Poll"`, + sendfile: Send_File `raw_union_tag:"type=.Send_File"`, + open: Open `raw_union_tag:"type=.Open"`, + stat: Stat `raw_union_tag:"type=.Stat"`, + + _remove: _Remove `raw_union_tag:"type=._Remove"`, + _link_timeout: _Link_Timeout `raw_union_tag:"type=._Link_Timeout"`, + _splice: _Splice `raw_union_tag:"type=._Splice"`, +} + +Operation_Type :: enum i32 { + None, + Accept, + Close, + Dial, + Read, + Recv, + Send, + Write, + Timeout, + Poll, + Send_File, + Open, + Stat, + + _Link_Timeout, + _Remove, + _Splice, +} + +Callback :: #type proc(op: ^Operation) + +/* +Initialize or increment the reference counted event loop for the current thread. +*/ +acquire_thread_event_loop :: proc() -> General_Error { + return _acquire_thread_event_loop() +} + +/* +Destroy or decrease the reference counted event loop for the current thread. +*/ +release_thread_event_loop :: proc() { + _release_thread_event_loop() +} + +current_thread_event_loop :: proc(loc := #caller_location) -> ^Event_Loop { + return _current_thread_event_loop(loc) +} + +/* +Each time you call this the implementation checks its state +and calls any callbacks which are ready. You would typically call this in a loop. + +Blocks for up-to timeout waiting for events if there is nothing to do. +*/ +tick :: proc(timeout: time.Duration = NO_TIMEOUT) -> General_Error { + l := &_tls_event_loop + if l.refs == 0 { return nil } + return _tick(l, timeout) +} + +/* +Runs the event loop by ticking in a loop until there is no more work to be done. +*/ +run :: proc() -> General_Error { + l := &_tls_event_loop + if l.refs == 0 { return nil } + + acquire_thread_event_loop() + defer release_thread_event_loop() + + for num_waiting() > 0 { + if errno := _tick(l, NO_TIMEOUT); errno != nil { + return errno + } + } + return nil +} + +/* +Runs the event loop by ticking in a loop until there is no more work to be done, or the flag `done` is `true`. +*/ +run_until :: proc(done: ^bool) -> General_Error { + l := &_tls_event_loop + if l.refs == 0 { return nil } + + acquire_thread_event_loop() + defer release_thread_event_loop() + + for num_waiting() > 0 && !intrinsics.volatile_load(done) { + if errno := _tick(l, NO_TIMEOUT); errno != nil { + return errno + } + } + return nil +} + +/* +Returns the number of in-progress operations to be completed on the event loop. +*/ +num_waiting :: proc(l: Maybe(^Event_Loop) = nil) -> int { + l_ := l.? or_else &_tls_event_loop + if l_.refs == 0 { return 0 } + return pool.num_outstanding(&l_.operation_pool) +} + +/* +Returns the current time (cached at most at the beginning of the current tick). +*/ +now :: proc() -> time.Time { + if _tls_event_loop.now == {} { + return time.now() + } + return _tls_event_loop.now +} + +/* +Remove the given operation from the event loop. The callback of it won't be called and resources are freed. + +Calling `remove`: +- Cancels the operation if it has not yet completed +- Prevents the callback from being called + +Cancellation via `remove` is *final* and silent: +- The callback will never be invoked +- No error is delivered +- The operation must be considered dead after removal + +WARN: the operation could have already been (partially or completely) completed. + A send with `all` set to true could have sent a portion already. + But also, a send that could be completed without blocking could have been completed. + You just won't get a callback. + +WARN: once an operation's callback is called it can not be removed anymore (use after free). + +WARN: needs to be called from the thread of the event loop the target belongs to. + +Common use would be to cancel a timeout, remove a polling, or remove an `accept` before calling `close` on it's socket. +*/ +remove :: proc(target: ^Operation) { + if target == nil { + return + } + + assert(target.type != .None) + + if target.l != &_tls_event_loop { + panic("nbio.remove called on different thread") + } + + _remove(target) +} + +/* +Creates a socket for use in `nbio` and relates it to the given event loop. + +Inputs: +- family: Should this be an IP4 or IP6 socket +- protocol: The type of socket (TCP or UDP) +- l: The event loop to associate it with, defaults to the current thread's loop + +Returns: +- socket: The created socket, consider `create_{udp|tcp}_socket` for a typed socket instead of the union +- err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening +*/ +create_socket :: proc( + family: Address_Family, + protocol: Socket_Protocol, + l: ^Event_Loop = nil, + loc := #caller_location, +) -> ( + socket: Any_Socket, + err: Create_Socket_Error, +) { + return _create_socket(l if l != nil else _current_thread_event_loop(loc), family, protocol) +} + +/* +Creates a UDP socket for use in `nbio` and relates it to the given event loop. + +Inputs: +- family: Should this be an IP4 or IP6 socket +- l: The event loop to associate it with, defaults to the current thread's loop + +Returns: +- socket: The created UDP socket +- err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening +*/ +create_udp_socket :: proc(family: Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (net.UDP_Socket, Create_Socket_Error) { + socket, err := create_socket(family, .UDP, l, loc) + if err != nil { + return -1, err + } + + return socket.(UDP_Socket), nil +} + +/* +Creates a TCP socket for use in `nbio` and relates it to the given event loop. + +Inputs: +- family: Should this be an IP4 or IP6 socket +- l: The event loop to associate it with, defaults to the current thread's loop + +Returns: +- socket: The created TCP socket +- err: A network error (`Create_Socket_Error`, or `Set_Blocking_Error`) which happened while opening +*/ +create_tcp_socket :: proc(family: Address_Family, l: ^Event_Loop = nil, loc := #caller_location) -> (net.TCP_Socket, Create_Socket_Error) { + socket, err := create_socket(family, .TCP, l, loc) + if err != nil { + return -1, err + } + + return socket.(TCP_Socket), nil +} + +/* +Creates a socket, sets non blocking mode, relates it to the given IO, binds the socket to the given endpoint and starts listening. + +Inputs: +- endpoint: Where to bind the socket to +- backlog: The maximum length to which the queue of pending connections may grow, before refusing connections +- l: The event loop to associate the socket with, defaults to the current thread's loop + +Returns: +- socket: The opened, bound and listening socket +- err: A network error (`Create_Socket_Error`, `Bind_Error`, or `Listen_Error`) that has happened +*/ +listen_tcp :: proc(endpoint: Endpoint, backlog := 1000, l: ^Event_Loop = nil, loc := #caller_location) -> (socket: TCP_Socket, err: net.Network_Error) { + assert(backlog > 0 && backlog < int(max(i32))) + return _listen_tcp(l if l != nil else _current_thread_event_loop(loc), endpoint, backlog) +} + +/* +Opens a file and associates it with the event loop. + +Inputs: +- path: path to the file, if not absolute: relative from `dir` +- dir: directory that `path` is relative from (if it is relative), defaults to the current working directory +- mode: open mode, defaults to read-only +- perm: permissions to use when creating a file, defaults to read+write for everybody +- l: event loop to associate the file with, defaults to the current thread's + +Returns: +- handle: The file handle +- err: An error if it occurred +*/ +open_sync :: proc(path: string, dir: Handle = CWD, mode: File_Flags = {.Read}, perm := Permissions_Default_File, l: ^Event_Loop = nil, loc := #caller_location) -> (handle: Handle, err: FS_Error) { + return _open_sync(l if l != nil else _current_thread_event_loop(loc), path, dir, mode, perm) +} + +Association_Error :: enum { + None, + // The given file/handle/socket was not opened in a mode that it can be made non-blocking afterwards. + // + // On Windows, this can happen when a file is not opened with the `FILE_FLAG_OVERLAPPED` flag. + // If using `core:os`, that is set when you specify the `O_NONBLOCK` flag. + // There is no way to add that after the fact. + Not_Possible_To_Associate, + // The given handle is not a valid handle. + Invalid_Handle, + // No network connection, or the network stack is not initialized. + Network_Unreachable, +} + +/* +Associate the given OS handle, not opened through this package, with the event loop. + +Consider using this package's `open` or `open_sync` directly instead. + +The handle returned is for convenience, it is actually still the same handle as given. +Thus you should not close the given handle. + +On Windows, this can error when a file is not opened with the `FILE_FLAG_OVERLAPPED` flag. +If using `core:os`, that is set when you specify the `O_NONBLOCK` flag. +There is no way to add that after the fact. +*/ +associate_handle :: proc(handle: uintptr, l: ^Event_Loop = nil, loc := #caller_location) -> (Handle, Association_Error) { + return _associate_handle(handle, l if l != nil else _current_thread_event_loop(loc)) +} + +/* +Associate the given socket, not created through this package, with the event loop. + +Consider using this package's `create_socket` directly instead. +*/ +associate_socket :: proc(socket: Any_Socket, l: ^Event_Loop = nil, loc := #caller_location) -> Association_Error { + return _associate_socket(socket, l if l != nil else _current_thread_event_loop(loc)) +} + +Read_Entire_File_Error :: struct { + operation: Operation_Type, + value: FS_Error, +} + +Read_Entire_File_Callback :: #type proc(user_data: rawptr, data: []byte, err: Read_Entire_File_Error) + +/* +Combines multiple operations (open, stat, read, close) into one that reads an entire regular file. + +The error contains the `operation` that the error happened on. + +Inputs: +- path: path to the file, if not absolute: relative from `dir` +- user_data: a pointer passed through into the callback +- cb: the callback to call once completed, called with the user data, file data, and an optional error +- allocator: the allocator to allocate the file's contents onto +- dir: directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: event loop to execute the operation on +*/ +read_entire_file :: proc(path: string, user_data: rawptr, cb: Read_Entire_File_Callback, allocator := context.allocator, dir := CWD, l: ^Event_Loop = nil, loc := #caller_location) { + _read_entire_file(l if l != nil else _current_thread_event_loop(loc), path, user_data, cb, allocator, dir) +} + +/* +Detach an operation from the package's lifetime management. + +By default the operation's lifetime is managed by the package and freed after a callback is called. +Calling this function detaches the operation from this lifetime. +You are expected to call `reattach` to give the package back this operation. +*/ +detach :: proc(op: ^Operation) { + op.detached = true +} + +/* +Reattach an operation to the package's lifetime management. +*/ +reattach :: proc(op: ^Operation) { + pool.put(&op.l.operation_pool, op) +} + +/* +Execute an operation. + +If the operation is attached to another thread's event loop, it is queued to be executed on that event loop, +optionally waking that loop up (from a blocking `tick`) with `trigger_wake_up`. +*/ +exec :: proc(op: ^Operation, trigger_wake_up := true) { + if op.l == &_tls_event_loop { + _exec(op) + } else { + // Capture the loop pointer before the enqueue publishes `op`: the + // target loop can complete the operation and return it to the + // operation pool before `op.l` is re-read below, and `l` is in a + // raw union with the pool's free-list link. + l := op.l + for !mpsc_enqueue(&l.queue, op) { + warn("operation queue on event loop filled up") + wake_up(l) + _yield() + } + if trigger_wake_up { + wake_up(l) + } + } +} + +/* +Wake up an event loop on another thread which may be blocking for completed operations. + +Commonly used with `exec` from a worker thread to have the event loop pick up that work. +Note that by default `exec` already calls this procedure. +*/ +wake_up :: proc(l: ^Event_Loop) { + if l == &_tls_event_loop { + return + } + _wake_up(l) +} diff --git a/core/nbio/net.odin b/core/nbio/net.odin new file mode 100644 index 000000000..d584639a7 --- /dev/null +++ b/core/nbio/net.odin @@ -0,0 +1,39 @@ +package nbio + +import "core:net" + +Network_Error :: net.Network_Error +Accept_Error :: net.Accept_Error +Dial_Error :: net.Dial_Error +Send_Error :: net.Send_Error +TCP_Send_Error :: net.TCP_Send_Error +UDP_Send_Error :: net.UDP_Send_Error +Recv_Error :: net.Recv_Error +TCP_Recv_Error :: net.TCP_Recv_Error +UDP_Recv_Error :: net.UDP_Recv_Error +Listen_Error :: net.Listen_Error +Create_Socket_Error :: net.Create_Socket_Error + +Address_Family :: net.Address_Family +Socket_Protocol :: net.Socket_Protocol + +Address :: net.Address +IP4_Address :: net.IP4_Address +IP6_Address :: net.IP6_Address + +Endpoint :: net.Endpoint + +TCP_Socket :: net.TCP_Socket +UDP_Socket :: net.UDP_Socket +Any_Socket :: net.Any_Socket + +IP4_Any :: net.IP4_Any +IP6_Any :: net.IP6_Any +IP4_Loopback :: net.IP4_Loopback +IP6_Loopback :: net.IP6_Loopback + +family_from_endpoint :: net.family_from_endpoint +bind :: net.bind +bound_endpoint :: net.bound_endpoint +parse_endpoint :: net.parse_endpoint +endpoint_to_string :: net.endpoint_to_string diff --git a/core/nbio/ops.odin b/core/nbio/ops.odin new file mode 100644 index 000000000..382dca747 --- /dev/null +++ b/core/nbio/ops.odin @@ -0,0 +1,2461 @@ +package nbio + +import "base:intrinsics" + +import "core:container/pool" +import "core:time" +import "core:slice" + +NO_TIMEOUT: time.Duration: -1 + +Accept :: struct { + // Socket to accept an incoming connection on. + socket: TCP_Socket, + // When this operation expires and should be timed out. + expires: time.Time, + + // The connection that was accepted. + client: TCP_Socket, + // The connection's remote origin. + client_endpoint: Endpoint, + // An error, if it occurred. + err: Accept_Error, + + // Implementation specifics, private. + _impl: _Accept `fmt:"-"`, +} + +/* +Retrieves and preps an operation to do an accept without executing it. + +Executing can then be done with the `exec` procedure. + +The timeout is calculated from the time when this procedure was called, not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- socket: A bound and listening socket *associated with the event loop* +- cb: The callback to be called when the operation finishes, `Operation.accept` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_accept :: #force_inline proc( + socket: TCP_Socket, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Accept) + op.accept.socket = socket + if timeout > 0 { + op.accept.expires = time.time_add(now(), timeout) + } + return op +} + +/* +Using the given socket, accepts the next incoming connection, calling the callback when that happens. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `accept_poly`, `accept_poly2`, and `accept_poly3`. + +Inputs: +- socket: A bound and listening socket *associated with the event loop* +- cb: The callback to be called when the operation finishes, `Operation.accept` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +accept :: #force_inline proc( + socket: TCP_Socket, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + res := prep_accept(socket, cb, timeout, l) + exec(res) + return res +} + +/* +Using the given socket, accepts the next incoming connection, calling the callback when that happens. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: A bound and listening socket *associated with the event loop* +- p: User data, the callback will receive this as it's second argument +- cb: The callback to be called when the operation finishes, `Operation.accept` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +accept_poly :: #force_inline proc( + socket: TCP_Socket, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_accept(socket, _poly_cb(C, T), timeout, l) + _put_user_data(op, cb, p) + exec(op) + return op +} + +/* +Using the given socket, accepts the next incoming connection, calling the callback when that happens. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: A bound and listening socket *associated with the event loop* +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The callback to be called when the operation finishes, `Operation.accept` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +accept_poly2 :: #force_inline proc( + socket: TCP_Socket, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_accept(socket, _poly_cb2(C, T, T2), timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + return op +} + +/* +Using the given socket, accepts the next incoming connection, calling the callback when that happens. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: A bound and listening socket *associated with the event loop* +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The callback to be called when the operation finishes, `Operation.accept` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +accept_poly3 :: #force_inline proc( + socket: TCP_Socket, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_accept(socket, _poly_cb3(C, T, T2, T3), timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + return op +} + +/* +A union of closable types that can be passed to `close`. +*/ +Closable :: union { + TCP_Socket, + UDP_Socket, + Handle, +} + +Close :: struct { + // The subject to close. + subject: Closable, + + // An error, if it occurred. + err: FS_Error, + + // Implementation specifics, private. + _impl: _Close `fmt:"-"`, +} + +@(private) +empty_callback :: proc(_: ^Operation) {} + +/* +Retrieves and preps an operation to do a close without executing it. + +Executing can then be done with the `exec` procedure. + +Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. +For consistent behavior first call `remove` on in progress IO. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- subject: The subject (socket or file) to close +- cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_close :: #force_inline proc(subject: Closable, cb: Callback = empty_callback, l: ^Event_Loop = nil) -> ^Operation { + op := _prep(l, cb, .Close) + op.close.subject = subject + return op +} + +/* +Closes the given subject (file or socket). + +Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. +For consistent behavior first call `remove` on in progress IO. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `close_poly`, `close_poly2`, and `close_poly3`. + +Inputs: +- subject: The subject (socket or file) to close +- cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +close :: #force_inline proc(subject: Closable, cb: Callback = empty_callback, l: ^Event_Loop = nil) -> ^Operation { + op := prep_close(subject, cb, l) + exec(op) + return op +} + +/* +Closes the given subject (file or socket). + +Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. +For consistent behavior first call `remove` on in progress IO. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- subject: The subject (socket or file) to close +- p: User data, the callback will receive this as it's second argument +- cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +close_poly :: #force_inline proc(subject: Closable, p: $T, cb: $C/proc(op: ^Operation, p: T), l: ^Event_Loop = nil) -> ^Operation +where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_close(subject, _poly_cb(C, T), l) + _put_user_data(op, cb, p) + exec(op) + return op +} + +/* +Closes the given subject (file or socket). + +Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. +For consistent behavior first call `remove` on in progress IO. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- subject: The subject (socket or file) to close +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +close_poly2 :: #force_inline proc(subject: Closable, p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: T, p2: T2), l: ^Event_Loop = nil) -> ^Operation +where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_close(subject, _poly_cb2(C, T, T2), l) + _put_user_data2(op, cb, p, p2) + exec(op) + return op +} + +/* +Closes the given subject (file or socket). + +Closing something that has IO in progress may or may not cancel it, and may or may not call the callback. +For consistent behavior first call `remove` on in progress IO. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- subject: The subject (socket or file) to close +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The optional callback to be called when the operation finishes, `Operation.close` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +close_poly3 :: #force_inline proc(subject: Closable, p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), l: ^Event_Loop = nil) -> ^Operation +where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_close(subject, _poly_cb3(C, T, T2, T3), l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + return op +} + +Dial :: struct { + // The endpoint to connect to. + endpoint: Endpoint, + // When this operation expires and should be timed out. + expires: time.Time, + + // Errors that can be returned: `Create_Socket_Error`, or `Dial_Error`. + err: Network_Error, + // The socket to communicate with the connected server. + socket: TCP_Socket, + + // Implementation specifics, private. + _impl: _Dial `fmt:"-"`, +} + +/* +Retrieves and preps an operation to do a dial operation without executing it. + +Executing can then be done with the `exec` procedure. + +The timeout is calculated from the time when this procedure was called, not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- endpoint: The endpoint to connect to +- cb: The callback to be called when the operation finishes, `Operation.dial` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_dial :: #force_inline proc( + endpoint: Endpoint, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Dial) + if timeout > 0 { + op.dial.expires = time.time_add(now(), timeout) + } + op.dial.endpoint = endpoint + return op +} + +/* +Dials the given endpoint. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `dial_poly`, `dial_poly2`, and `dial_poly3`. + +Inputs: +- endpoint: The endpoint to connect to +- cb: The callback to be called when the operation finishes, `Operation.dial` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +dial :: #force_inline proc( + endpoint: Endpoint, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + res := prep_dial(endpoint, cb, timeout, l) + exec(res) + return res +} + +/* +Dials the given endpoint. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- endpoint: The endpoint to connect to +- p: User data, the callback will receive this as it's second argument +- cb: The callback to be called when the operation finishes, `Operation.dial` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +dial_poly :: #force_inline proc( + endpoint: Endpoint, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_dial(endpoint, _poly_cb(C, T), timeout, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Dials the given endpoint. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- endpoint: The endpoint to connect to +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The callback to be called when the operation finishes, `Operation.dial` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +dial_poly2 :: #force_inline proc( + endpoint: Endpoint, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_dial(endpoint, _poly_cb2(C, T, T2), timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Dials the given endpoint. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- endpoint: The endpoint to connect to +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The callback to be called when the operation finishes, `Operation.dial` will contain results +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +dial_poly3 :: #force_inline proc( + endpoint: Endpoint, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_dial(endpoint, _poly_cb3(C, T, T2, T3), timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +Recv :: struct { + // The socket to receive from. + socket: Any_Socket, + // The buffers to receive data into. + // The outer slice is copied internally, but the backing data must remain alive. + // It is safe to access `bufs` during the callback. + bufs: [][]byte, + // If true, the operation waits until all buffers are filled (TCP only). + all: bool, + // When this operation expires and should be timed out. + expires: time.Time, + + // The source endpoint data was received from (UDP only). + source: Endpoint, + + // An error, if it occurred. + // If `received == 0` and `err == nil`, the connection was closed by the peer. + err: Recv_Error, + // The number of bytes received. + received: int, + + // Implementation specifics, private. + _impl: _Recv `fmt:"-"`, +} + +/* +Retrieves and preps an operation to do a receive without executing it. + +Executing can then be done with the `exec` procedure. + +To avoid ambiguity between a closed connection and a 0-byte read, the provided buffers must have a total capacity greater than 0. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +The timeout is calculated from the time when this procedure was called, not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- socket: The socket to receive from +- bufs: Buffers to fill with received data +- cb: The callback to be called when the operation finishes, `Operation.recv` will contain results +- all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_recv :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + cb: Callback, + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + assert(socket != nil) + + // If we accepted `bufs` that total 0 it would be ambiguous if the result of `received == 0 && err == nil` means connection closed or received 0 bytes. + assert(len(bufs) > 0) + assert(slice.any_of_proc(bufs, proc(buf: []byte) -> bool { return len(buf) > 0 })) + + op := _prep(l, cb, .Recv) + op.recv.socket = socket + op.recv.bufs = bufs + op.recv.all = all + if timeout > 0 { + op.recv.expires = time.time_add(now(), timeout) + } + + if err := bufs_init(&op.recv._impl.bufs, &op.recv.bufs, op.l.allocator); err != nil { + switch _ in op.recv.socket { + case TCP_Socket: op.recv.err = TCP_Recv_Error.Insufficient_Resources + case UDP_Socket: op.recv.err = UDP_Recv_Error.Insufficient_Resources + case: unreachable() + } + } + + return op +} + +/* +Receives data from the socket. + +If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `recv_poly`, `recv_poly2`, and `recv_poly3`. + +Inputs: +- socket: The socket to receive from +- bufs: Buffers to fill with received data +- cb: The callback to be called when the operation finishes, `Operation.recv` will contain results +- all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +recv :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + cb: Callback, + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation { + op := prep_recv(socket, bufs, cb, all, timeout, l) + exec(op) + return op +} + +/* +Receives data from the socket. + +If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to receive from +- bufs: Buffers to fill with received data +- p: User data, the callback will receive this as it's second argument +- cb: The callback to be called when the operation finishes, `Operation.recv` will contain results +- all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +recv_poly :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_recv(socket, bufs, _poly_cb(C, T), all, timeout, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Receives data from the socket. + +If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to receive from +- bufs: Buffers to fill with received data +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The callback to be called when the operation finishes, `Operation.recv` will contain results +- all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +recv_poly2 :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_recv(socket, bufs, _poly_cb2(C, T, T2), all, timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Receives data from the socket. + +If the operation completes with 0 bytes received and no error, it indicates the connection was closed by the peer. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to receive from +- bufs: Buffers to fill with received data +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The callback to be called when the operation finishes, `Operation.recv` will contain results +- all: If true, waits until all buffers are full before completing (TCP only, ignored for UDP) +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +recv_poly3 :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_recv(socket, bufs, _poly_cb3(C, T, T2, T3), all, timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +Send :: struct { + // The socket to send to. + socket: Any_Socket, + // The buffers to send. + // The outer slice is copied internally, but the backing data must remain alive. + // It is safe to access `bufs` during the callback. + bufs: [][]byte `fmt:"-"`, + // The destination endpoint to send to (UDP only). + endpoint: Endpoint, + // If true, the operation ensures all data is sent before completing. + all: bool, + // When this operation expires and should be timed out. + expires: time.Time, + + // An error, if it occurred. + err: Send_Error, + // The number of bytes sent. + sent: int, + + // Implementation specifics, private. + _impl: _Send `fmt:"-"`, +} + +/* +Retrieves and preps an operation to do a send without executing it. + +Executing can then be done with the `exec` procedure. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +The timeout is calculated from the time when this procedure was called, not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- socket: The socket to send to +- bufs: Buffers containing the data to send +- cb: The callback to be called when the operation finishes, `Operation.send` will contain results +- endpoint: The destination endpoint (UDP only, ignored for TCP) +- all: If true, the operation ensures all data is sent before completing +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_send :: proc( + socket: Any_Socket, + bufs: [][]byte, + cb: Callback, + endpoint: Endpoint = {}, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + assert(socket != nil) + op := _prep(l, cb, .Send) + op.send.socket = socket + op.send.bufs = bufs + op.send.endpoint = endpoint + op.send.all = all + if timeout > 0 { + op.send.expires = time.time_add(now(), timeout) + } + + if err := bufs_init(&op.send._impl.bufs, &op.send.bufs, op.l.allocator); err != nil { + switch _ in op.send.socket { + case TCP_Socket: op.send.err = TCP_Send_Error.Insufficient_Resources + case UDP_Socket: op.send.err = UDP_Send_Error.Insufficient_Resources + case: unreachable() + } + } + + return op +} + +/* +Sends data to the socket. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `send_poly`, `send_poly2`, and `send_poly3`. + +Inputs: +- socket: The socket to send to +- bufs: Buffers containing the data to send +- cb: The callback to be called when the operation finishes, `Operation.send` will contain results +- endpoint: The destination endpoint (UDP only, ignored for TCP) +- all: If true, the operation ensures all data is sent before completing +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +send :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + cb: Callback, + endpoint: Endpoint = {}, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_send(socket, bufs, cb, endpoint, all, timeout, l) + exec(op) + return op +} + +/* +Sends data to the socket. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to send to +- bufs: Buffers containing the data to send +- p: User data, the callback will receive this as it's second argument +- cb: The callback to be called when the operation finishes, `Operation.send` will contain results +- endpoint: The destination endpoint (UDP only, ignored for TCP) +- all: If true, the operation ensures all data is sent before completing +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +send_poly :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + endpoint: Endpoint = {}, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_send(socket, bufs, _poly_cb(C, T), endpoint, all, timeout, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Sends data to the socket. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to send to +- bufs: Buffers containing the data to send +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The callback to be called when the operation finishes, `Operation.send` will contain results +- endpoint: The destination endpoint (UDP only, ignored for TCP) +- all: If true, the operation ensures all data is sent before completing +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +send_poly2 :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + endpoint: Endpoint = {}, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_send(socket, bufs, _poly_cb2(C, T, T2), endpoint, all, timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Sends data to the socket. + +The `bufs` slice itself is copied into the operation, so it can be temporary (e.g. on the stack), but the underlying memory of the buffers must remain valid until the callback is fired. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The socket to send to +- bufs: Buffers containing the data to send +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The callback to be called when the operation finishes, `Operation.send` will contain results +- endpoint: The destination endpoint (UDP only, ignored for TCP) +- all: If true, the operation ensures all data is sent before completing +- timeout: Optional timeout for the operation, the callback will get a `.Timeout` error after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +send_poly3 :: #force_inline proc( + socket: Any_Socket, + bufs: [][]byte, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + endpoint: Endpoint = {}, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_send(socket, bufs, _poly_cb3(C, T, T2, T3), endpoint, all, timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +Read :: struct { + // Handle to read from. + handle: Handle, + // Buffer to read data into. + buf: []byte `fmt:"v,read"`, + // Offset to read from. + offset: int, + // Whether to read until the buffer is full or an error occurs. + all: bool, + // When this operation expires and should be timed out. + expires: time.Time, + + // Error, if it occurred. + err: FS_Error, + // Number of bytes read. + read: int, + + // Implementation specifics, private. + _impl: _Read `fmt:"-"`, +} + +/* +Retrieves and preps a positional read operation without executing it. + +This is a pread-style operation: the read starts at the given offset and does +not modify the handle's current file position. + +Executing can then be done with the `exec` procedure. + +The timeout is calculated from the time when this procedure was called, +not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- handle: Handle to read from +- offset: Offset to read from +- buf: Buffer to read data into (must not be empty) +- cb: The callback to be called when the operation finishes, `Operation.read` will contain results +- all: Whether to read until the buffer is full or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_read :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + cb: Callback, + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + assert(len(buf) > 0) + op := _prep(l, cb, .Read) + op.read.handle = handle + op.read.buf = buf + op.read.offset = offset + op.read.all = all + if timeout > 0 { + op.read.expires = time.time_add(now(), timeout) + } + return op +} + +/* +Reads data from a handle at a specific offset. + +This is a pread-style operation: the read starts at the given offset and does +not modify the handle's current file position. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `read_poly`, `read_poly2`, and `read_poly3`. + +Inputs: +- handle: Handle to read from +- offset: Offset to read from +- buf: Buffer to read data into (must not be empty) +- cb: The callback to be called when the operation finishes, `Operation.read` will contain results +- all: Whether to read until the buffer is full or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +read :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + cb: Callback, + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_read(handle, offset, buf, cb, all, timeout, l) + exec(op) + return op +} + +/* +Reads data from a handle at a specific offset. + +This is a pread-style operation: the read starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to read from +- offset: Offset to read from +- buf: Buffer to read data into (must not be empty) +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes, `Operation.read` will contain results +- all: Whether to read until the buffer is full or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +read_poly :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_read(handle, offset, buf, _poly_cb(C, T), all=all, timeout=timeout, l=l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Reads data from a handle at a specific offset. + +This is a pread-style operation: the read starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to read from +- offset: Offset to read from +- buf: Buffer to read data into (must not be empty) +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes, `Operation.read` will contain results +- all: Whether to read until the buffer is full or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +read_poly2 :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_read(handle, offset, buf, _poly_cb2(C, T, T2), all, timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Reads data from a handle at a specific offset. + +This is a pread-style operation: the read starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to read from +- offset: Offset to read from +- buf: Buffer to read data into (must not be empty) +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes, `Operation.read` will contain results +- all: Whether to read until the buffer is full or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +read_poly3 :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + all := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_read(handle, offset, buf, _poly_cb3(C, T, T2, T3), all, timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +Write :: struct { + // Handle to write to. + handle: Handle, + // Buffer containing data to write. + buf: []byte, + // Offset to write to. + offset: int, + // Whether to write until the buffer is fully written or an error occurs. + all: bool, + // When this operation expires and should be timed out. + expires: time.Time, + + // Error, if it occurred. + err: FS_Error, + // Number of bytes written. + written: int, + + // Implementation specifics, private. + _impl: _Write `fmt:"-"`, +} + +/* +Retrieves and preps a positional write operation without executing it. + +This is a pwrite-style operation: the write starts at the given offset and does +not modify the handle's current file position. + +Executing can then be done with the `exec` procedure. + +The timeout is calculated from the time when this procedure was called, +not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- handle: Handle to write to +- offset: Offset to write to +- buf: Buffer containing data to write (must not be empty) +- cb: The callback to be called when the operation finishes, `Operation.write` will contain results +- all: Whether to write until the entire buffer is written or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_write :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + cb: Callback, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + assert(len(buf) > 0) + op := _prep(l, cb, .Write) + op.write.handle = handle + op.write.buf = buf + op.write.offset = offset + op.write.all = all + if timeout > 0 { + op.write.expires = time.time_add(now(), timeout) + } + return op +} + +/* +Writes data to a handle at a specific offset. + +This is a pwrite-style operation: the write starts at the given offset and does +not modify the handle's current file position. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `write_poly`, `write_poly2`, and `write_poly3`. + +Inputs: +- handle: Handle to write to +- offset: Offset to write to +- buf: Buffer containing data to write (must not be empty) +- cb: The callback to be called when the operation finishes, `Operation.write` will contain results +- all: Whether to write until the entire buffer is written or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +write :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + cb: Callback, + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_write(handle, offset, buf, cb, all, timeout, l) + exec(op) + return op +} + +/* +Writes data to a handle at a specific offset. + +This is a pwrite-style operation: the write starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to write to +- offset: Offset to write to +- buf: Buffer containing data to write (must not be empty) +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes, `Operation.write` will contain results +- all: Whether to write until the entire buffer is written or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +write_poly :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_write(handle, offset, buf, _poly_cb(C, T), all=all, timeout=timeout, l=l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Writes data to a handle at a specific offset. + +This is a pwrite-style operation: the write starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to write to +- offset: Offset to write to +- buf: Buffer containing data to write (must not be empty) +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes, `Operation.write` will contain results +- all: Whether to write until the entire buffer is written or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +write_poly2 :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_write(handle, offset, buf, _poly_cb2(C, T, T2), all, timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Writes data to a handle at a specific offset. + +This is a pwrite-style operation: the write starts at the given offset and does +not modify the handle's current file position. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to write to +- offset: Offset to write to +- buf: Buffer containing data to write (must not be empty) +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes, `Operation.write` will contain results +- all: Whether to write until the entire buffer is written or an error occurs +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +write_poly3 :: #force_inline proc( + handle: Handle, + offset: int, + buf: []byte, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + all := true, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_write(handle, offset, buf, _poly_cb3(C, T, T2, T3), all, timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +Timeout :: struct { + // Duration after which the timeout expires. + duration: time.Duration, + + // Implementation specifics, private. + _impl: _Timeout `fmt:"-"`, +} + +/* +Retrieves and preps a timeout operation without executing it. + +Executing can then be done with the `exec` procedure. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- duration: Duration to wait before the operation completes +- cb: The callback to be called when the operation finishes +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_timeout :: #force_inline proc( + duration: time.Duration, + cb: Callback, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Timeout) + op.timeout.duration = duration + return op +} + +/* +Schedules a timeout that completes after the given duration. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `timeout_poly`, `timeout_poly2`, and `timeout_poly3`. + +Inputs: +- duration: Duration to wait before the operation completes +- cb: The callback to be called when the operation finishes +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +timeout :: #force_inline proc( + duration: time.Duration, + cb: Callback, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_timeout(duration, cb, l) + exec(op) + return op +} + +/* +Schedules a timeout that completes after the given duration. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- dur: Duration to wait before the operation completes +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +timeout_poly :: #force_inline proc( + dur: time.Duration, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + l: ^Event_Loop = nil, +) -> ^Operation + where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_timeout(dur, _poly_cb(C, T), l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Schedules a timeout that completes after the given duration. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- dur: Duration to wait before the operation completes +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +timeout_poly2 :: #force_inline proc( + dur: time.Duration, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + l: ^Event_Loop = nil, +) -> ^Operation + where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_timeout(dur, _poly_cb2(C, T, T2), l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Schedules a timeout that completes after the given duration. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- dur: Duration to wait before the operation completes +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +timeout_poly3 :: #force_inline proc( + dur: time.Duration, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + l: ^Event_Loop = nil, +) -> ^Operation + where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_timeout(dur, _poly_cb3(C, T, T2, T3), l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +/* +Retrieves and preps an operation that completes on the next event loop tick. + +This is equivalent to `prep_timeout(0, ...)`. +*/ +prep_next_tick :: #force_inline proc(cb: Callback, l: ^Event_Loop = nil) -> ^Operation { + return prep_timeout(0, cb, l) +} + +/* +Schedules an operation that completes on the next event loop tick. + +This is equivalent to `timeout(0, ...)`. +*/ +next_tick :: #force_inline proc(cb: Callback, l: ^Event_Loop = nil) -> ^Operation { + return timeout(0, cb, l) +} + +/* +Schedules an operation that completes on the next event loop tick. + +This is equivalent to `timeout_poly(0, ...)`. +*/ +next_tick_poly :: #force_inline proc(p: $T, cb: $C/proc(op: ^Operation, p: T), l: ^Event_Loop = nil) -> ^Operation + where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + return timeout_poly(0, p, cb, l) +} + +/* +Schedules an operation that completes on the next event loop tick. + +This is equivalent to `timeout_poly2(0, ...)`. +*/ +next_tick_poly2 :: #force_inline proc(p: $T, p2: $T2, cb: $C/proc(op: ^Operation, p: T, p2: T2), l: ^Event_Loop = nil) -> ^Operation + where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + return timeout_poly2(0, p, p2, cb, l) +} + +/* +Schedules an operation that completes on the next event loop tick. + +This is equivalent to `timeout_poly3(0, ...)`. +*/ +next_tick_poly3 :: #force_inline proc(p: $T, p2: $T2, p3: $T3, cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), l: ^Event_Loop = nil) -> ^Operation + where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + return timeout_poly3(0, p, p2, p3, cb, l) +} + +Poll_Result :: enum i32 { + // The requested event is ready. + Ready, + // The operation timed out before the event became ready. + Timeout, + // The socket was invalid. + Invalid_Argument, + // An unspecified error occurred. + Error, +} + +Poll_Event :: enum { + // The subject is ready to be received from. + Receive, + // The subject is ready to be sent to. + Send, +} + +Poll :: struct { + // Socket to poll. + socket: Any_Socket, + // Event to poll for. + event: Poll_Event, + // When this operation expires and should be timed out. + expires: time.Time, + + // Result of the poll. + result: Poll_Result, + + // Implementation specifics, private. + _impl: _Poll `fmt:"-"`, +} + +/* +Retrieves and preps an operation to poll a socket without executing it. + +Executing can then be done with the `exec` procedure. + +The timeout is calculated from the time when this procedure was called, +not from when it's executed. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- socket: Socket to poll that is *associated with the event loop* +- event: Event to poll for +- cb: The callback to be called when the operation finishes, `Operation.poll` will contain results +- timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_poll :: #force_inline proc( + socket: Any_Socket, + event: Poll_Event, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Poll) + op.poll.socket = socket + op.poll.event = event + if timeout > 0 { + op.poll.expires = time.time_add(now(), timeout) + } + return op +} + +/* +Poll a socket for readiness. + +NOTE: this is provided to help with "legacy" APIs that require polling behavior. +If you can avoid it and use the other procs in this package, do so. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `poll_poly`, `poll_poly2`, and `poll_poly3`. + +Inputs: +- socket: Socket to poll that is *associated with the event loop* +- event: Event to poll for +- cb: The callback to be called when the operation finishes, `Operation.poll` will contain results +- timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +poll :: #force_inline proc( + socket: Any_Socket, + event: Poll_Event, + cb: Callback, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_poll(socket, event, cb, timeout, l) + exec(op) + return op +} + +/* +Poll a socket for readiness. + +NOTE: this is provided to help with "legacy" APIs that require polling behavior. +If you can avoid it and use the other procs in this package, do so. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: Socket to poll that is *associated with the event loop* +- event: Event to poll for +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes, `Operation.poll` will contain results +- timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +poll_poly :: #force_inline proc( + socket: Any_Socket, + event: Poll_Event, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_poll(socket, event, _poly_cb(C, T), timeout, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Poll a socket for readiness. + +NOTE: this is provided to help with "legacy" APIs that require polling behavior. +If you can avoid it and use the other procs in this package, do so. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: Socket to poll that is *associated with the event loop* +- event: Event to poll for +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes, `Operation.poll` will contain results +- timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +poll_poly2 :: #force_inline proc( + socket: Any_Socket, + event: Poll_Event, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_poll(socket, event, _poly_cb2(C, T, T2), timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Poll a socket for readiness. + +NOTE: this is provided to help with "legacy" APIs that require polling behavior. +If you can avoid it and use the other procs in this package, do so. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: Socket to poll that is *associated with the event loop* +- event: Event to poll for +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes, `Operation.poll` will contain results +- timeout: Optional timeout for the operation, the callback will receive a `.Timeout` result after that duration +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +poll_poly3 :: #force_inline proc( + socket: Any_Socket, + event: Poll_Event, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_poll(socket, event, _poly_cb3(C, T, T2, T3), timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +SEND_ENTIRE_FILE :: -1 + +Send_File_Error :: union #shared_nil { + FS_Error, + TCP_Send_Error, +} + +Send_File :: struct { + // The TCP socket to send the file over. + socket: TCP_Socket, + // The handle of the regular file to send. + file: Handle, + // When this operation expires and should be timed out. + expires: time.Time, + // The starting offset within the file. + offset: int, + // Number of bytes to send. If set to SEND_ENTIRE_FILE, the file size is retrieved + // automatically and this field is updated to reflect the full size. + nbytes: int, + // If true, the callback is triggered periodically as data is sent. + // The callback will continue to be called until `sent == nbytes` or an error occurs. + progress_updates: bool, + + // Total number of bytes (so far if `progress_updates` is true). + sent: int, + // An error, if it occurred. Can be a filesystem or networking error. + err: Send_File_Error, + + // Implementation specifics, private. + _impl: _Send_File `fmt:"-"`, +} + +/* +Retrieves and preps an operation to send a file over a socket without executing it. + +Executing can then be done with the `exec` procedure. + +This uses high-performance zero-copy system calls where available. +Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- socket: The destination TCP socket +- file: The source file handle +- cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes +- offset: Byte offset to start reading from the file +- nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) +- progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the final callback is called +*/ +prep_sendfile :: #force_inline proc( + socket: TCP_Socket, + file: Handle, + cb: Callback, + offset: int = 0, + nbytes: int = SEND_ENTIRE_FILE, + progress_updates := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + assert(offset >= 0) + assert(nbytes == SEND_ENTIRE_FILE || nbytes > 0) + op := _prep(l, cb, .Send_File) + op.sendfile.socket = socket + op.sendfile.file = file + if timeout > 0 { + op.sendfile.expires = time.time_add(now(), timeout) + } + op.sendfile.offset = offset + op.sendfile.nbytes = nbytes + op.sendfile.progress_updates = progress_updates + return op +} + +/* +Sends a file over a TCP socket. + +This uses high-performance zero-copy system calls where available. +Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `sendfile_poly`, `sendfile_poly2`, and `sendfile_poly3`. + +Inputs: +- socket: The destination TCP socket +- file: The source file handle +- cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes +- offset: Byte offset to start reading from the file +- nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) +- progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the final callback is called +*/ +sendfile :: #force_inline proc( + socket: TCP_Socket, + file: Handle, + cb: Callback, + offset: int = 0, + nbytes: int = SEND_ENTIRE_FILE, + progress_updates := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_sendfile(socket, file, cb, offset, nbytes, progress_updates, timeout, l) + exec(op) + return op +} + +/* +Sends a file over a TCP socket. + +This uses high-performance zero-copy system calls where available. +Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The destination TCP socket +- file: The source file handle +- p: User data, the callback will receive this as it's second argument +- cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes +- offset: Byte offset to start reading from the file +- nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) +- progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the final callback is called +*/ +sendfile_poly :: #force_inline proc( + socket: TCP_Socket, + file: Handle, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + offset: int = 0, + nbytes: int = SEND_ENTIRE_FILE, + progress_updates := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_sendfile(socket, file, _poly_cb(C, T), offset, nbytes, progress_updates, timeout, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Sends a file over a TCP socket. + +This uses high-performance zero-copy system calls where available. +Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The destination TCP socket +- file: The source file handle +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes +- offset: Byte offset to start reading from the file +- nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) +- progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the final callback is called +*/ +sendfile_poly2 :: #force_inline proc( + socket: TCP_Socket, + file: Handle, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + offset: int = 0, + nbytes: int = SEND_ENTIRE_FILE, + progress_updates := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_sendfile(socket, file, _poly_cb2(C, T, T2), offset, nbytes, progress_updates, timeout, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Sends a file over a TCP socket. + +This uses high-performance zero-copy system calls where available. +Note: This is emulated on NetBSD and OpenBSD (stat -> mmap -> send) as they lack a native sendfile implementation. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- socket: The destination TCP socket +- file: The source file handle +- p: User data, the callback will receive this as it's second argument +- p2: User data, the callback will receive this as it's third argument +- p3: User data, the callback will receive this as it's fourth argument +- cb: The callback to be called when data is sent (if `progress_updates` is true) or the operation completes +- offset: Byte offset to start reading from the file +- nbytes: Total bytes to send (use SEND_ENTIRE_FILE for the whole file) +- progress_updates: If true, the callback fires multiple times to report progress, `sent == nbytes` means te operation completed +- timeout: Optional timeout for the operation +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the final callback is called +*/ +sendfile_poly3 :: #force_inline proc( + socket: TCP_Socket, + file: Handle, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + offset: int = 0, + nbytes: int = SEND_ENTIRE_FILE, + progress_updates := false, + timeout: time.Duration = NO_TIMEOUT, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_sendfile(socket, file, _poly_cb3(C, T, T2, T3), offset, nbytes, progress_updates, timeout, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +/* +File permission bit-set. + +This type represents POSIX-style file permissions, split into user, group, +and other categories, each with read, write, and execute flags. +*/ +Permissions :: distinct bit_set[Permission_Flag; u32] + +Permission_Flag :: enum u32 { + Execute_Other = 0, + Write_Other = 1, + Read_Other = 2, + + Execute_Group = 3, + Write_Group = 4, + Read_Group = 5, + + Execute_User = 6, + Write_User = 7, + Read_User = 8, +} + +// Convenience permission sets. +Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other} +Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other} +Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other} + +// Read and write permissions for user, group, and others. +Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All + +// Read, write, and execute permissions for user, group, and others. +Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All + +// Default permissions used when creating a file (read and write for everyone). +Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All + +// Default permissions used when creating a directory (read, write, and execute for everyone). +Permissions_Default_Directory :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All + +File_Flags :: bit_set[File_Flag; int] + +File_Flag :: enum { + // Open for reading. + Read, + // Open for writing. + Write, + // Append writes to the end of the file. + Append, + // Create the file if it does not exist. + Create, + // Fail if the file already exists (used with Create). + Excl, + Sync, + // Truncate the file on open. + Trunc, +} + +Open :: struct { + // Base directory the path is relative to. + dir: Handle, + // Path to the file. + path: string, + // File open mode flags. + mode: File_Flags, + // Permissions used if the file is created. + perm: Permissions, + + // The opened file handle. + handle: Handle, + // An error, if it occurred. + err: FS_Error, + + // Implementation specifics, private. + _impl: _Open `fmt:"-"`, +} + +// Sentinel handle representing the current/present working directory. +CWD :: _CWD + +/* +Retrieves and preps an operation to open a file without executing it. + +Executing can then be done with the `exec` procedure. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- path: Path to the file, if not absolute: relative from `dir` +- cb: The callback to be called when the operation finishes, `Operation.open` will contain results +- mode: File open mode flags, defaults to read-only +- perm: Permissions to use when creating a file, defaults to read+write for everybody +- dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_open :: #force_inline proc( + path: string, + cb: Callback, + mode: File_Flags = {.Read}, + perm: Permissions = Permissions_Default_File, + dir: Handle = CWD, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Open) + op.open.path = path + op.open.mode = mode + op.open.perm = perm + op.open.dir = dir + return op +} + +/* +Opens a file and associates it with the event loop. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `open_poly`, `open_poly2`, and `open_poly3`. + +Inputs: +- path: Path to the file, if not absolute: relative from `dir` +- cb: The callback to be called when the operation finishes, `Operation.open` will contain results +- mode: File open mode flags, defaults to read-only +- perm: Permissions to use when creating a file, defaults to read+write for everybody +- dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +open :: #force_inline proc( + path: string, + cb: Callback, + mode: File_Flags = {.Read}, + perm: Permissions = Permissions_Default_File, + dir: Handle = CWD, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_open(path, cb, mode, perm, dir, l) + exec(op) + return op +} + +/* +Opens a file and associates it with the event loop. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- path: Path to the file, if not absolute: relative from `dir` +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes, `Operation.open` will contain results +- mode: File open mode flags, defaults to read-only +- perm: Permissions to use when creating a file, defaults to read+write for everybody +- dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +open_poly :: #force_inline proc( + path: string, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + mode: File_Flags = {.Read}, + perm: Permissions = Permissions_Default_File, + dir: Handle = CWD, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_open(path, _poly_cb(C, T), mode, perm, dir, l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Opens a file and associates it with the event loop. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- path: Path to the file, if not absolute: relative from `dir` +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes, `Operation.open` will contain results +- mode: File open mode flags, defaults to read-only +- perm: Permissions to use when creating a file, defaults to read+write for everybody +- dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +open_poly2 :: #force_inline proc( + path: string, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + mode: File_Flags = {.Read}, + perm: Permissions = Permissions_Default_File, + dir: Handle = CWD, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_open(path, _poly_cb2(C, T, T2), mode, perm, dir, l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Asynchronously opens a file and associates it with the event loop. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- path: Path to the file, if not absolute: relative from `dir` +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes, `Operation.open` will contain results +- mode: File open mode flags, defaults to read-only +- perm: Permissions to use when creating a file, defaults to read+write for everybody +- dir: Directory that `path` is relative from (if it is relative), defaults to the current working directory +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +open_poly3 :: #force_inline proc( + path: string, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + mode: File_Flags = {.Read}, + perm: Permissions = Permissions_Default_File, + dir: Handle = CWD, + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_open(path, _poly_cb3(C, T, T2, T3), mode, perm, dir, l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +File_Type :: enum { + // File type could not be determined. + Undetermined, + // Regular file. + Regular, + // Directory. + Directory, + // Symbolic link. + Symlink, + // Pipe or socket. + Pipe_Or_Socket, + // Character or block device. + Device, +} + +Stat :: struct { + // Handle to stat. + handle: Handle, + + // The type of the file. + type: File_Type, + // Size of the file in bytes. + size: i64 `fmt:"M"`, + + // An error, if it occurred. + err: FS_Error, + + // Implementation specifics, private. + _impl: _Stat `fmt:"-"`, +} + +/* +Retrieves and preps an operation to stat a handle without executing it. + +Executing can then be done with the `exec` procedure. + +Any user data can be set on the returned operation's `user_data` field. + +Inputs: +- handle: Handle to retrieve stat +- cb: The callback to be called when the operation finishes, `Operation.stat` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +prep_stat :: #force_inline proc( + handle: Handle, + cb: Callback, + l: ^Event_Loop = nil, +) -> ^Operation { + op := _prep(l, cb, .Stat) + op.stat.handle = handle + return op +} + +/* +Stats a handle. + +Any user data can be set on the returned operation's `user_data` field. +Polymorphic variants for type safe user data are available under `stat_poly`, `stat_poly2`, and `stat_poly3`. + +Inputs: +- handle: Handle to retrieve status information for +- cb: The callback to be called when the operation finishes, `Operation.stat` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +stat :: #force_inline proc( + handle: Handle, + cb: Callback, + l: ^Event_Loop = nil, +) -> ^Operation { + op := prep_stat(handle, cb, l) + exec(op) + return op +} + +/* +Stats a handle. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to retrieve status information for +- p: User data, the callback will receive this as its second argument +- cb: The callback to be called when the operation finishes, `Operation.stat` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +stat_poly :: #force_inline proc( + handle: Handle, + p: $T, + cb: $C/proc(op: ^Operation, p: T), + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_stat(handle, _poly_cb(C, T), l) + _put_user_data(op, cb, p) + exec(op) + + return op +} + +/* +Stats a handle. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to retrieve status information for +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- cb: The callback to be called when the operation finishes, `Operation.stat` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +stat_poly2 :: #force_inline proc( + handle: Handle, + p: $T, p2: $T2, + cb: $C/proc(op: ^Operation, p: T, p2: T2), + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_stat(handle, _poly_cb2(C, T, T2), l) + _put_user_data2(op, cb, p, p2) + exec(op) + + return op +} + +/* +Stats a handle. + +This procedure uses polymorphism for type safe user data up to a certain size. + +Inputs: +- handle: Handle to retrieve status information for +- p: User data, the callback will receive this as its second argument +- p2: User data, the callback will receive this as its third argument +- p3: User data, the callback will receive this as its fourth argument +- cb: The callback to be called when the operation finishes, `Operation.stat` will contain results +- l: Event loop to associate the operation with, defaults to the current thread's loop + +Returns: A non-nil pointer to the operation, alive until the callback is called +*/ +stat_poly3 :: #force_inline proc( + handle: Handle, + p: $T, p2: $T2, p3: $T3, + cb: $C/proc(op: ^Operation, p: T, p2: T2, p3: T3), + l: ^Event_Loop = nil, +) -> ^Operation where size_of(T) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS { + + op := prep_stat(handle, _poly_cb3(C, T, T2, T3), l) + _put_user_data3(op, cb, p, p2, p3) + exec(op) + + return op +} + +_prep :: proc(l: ^Event_Loop, cb: Callback, type: Operation_Type) -> ^Operation { + assert(cb != nil) + assert(type != .None) + l := l + if l == nil { l = _current_thread_event_loop() } + operation := pool.get(&l.operation_pool) + operation.l = l + operation.type = type + operation.cb = cb + return operation +} + +_poly_cb :: #force_inline proc($C: typeid, $T: typeid) -> proc(^Operation) { + return proc(op: ^Operation) { + ptr := uintptr(&op.user_data) + cb := intrinsics.unaligned_load((^C)(rawptr(ptr))) + p := intrinsics.unaligned_load((^T)(rawptr(ptr + size_of(C)))) + cb(op, p) + } +} + +_poly_cb2 :: #force_inline proc($C: typeid, $T: typeid, $T2: typeid) -> proc(^Operation) { + return proc(op: ^Operation) { + ptr := uintptr(&op.user_data) + cb := intrinsics.unaligned_load((^C) (rawptr(ptr))) + p := intrinsics.unaligned_load((^T) (rawptr(ptr + size_of(C)))) + p2 := intrinsics.unaligned_load((^T2)(rawptr(ptr + size_of(C) + size_of(T)))) + cb(op, p, p2) + } +} + +_poly_cb3 :: #force_inline proc($C: typeid, $T: typeid, $T2: typeid, $T3: typeid) -> proc(^Operation) { + return proc(op: ^Operation) { + ptr := uintptr(&op.user_data) + cb := intrinsics.unaligned_load((^C) (rawptr(ptr))) + p := intrinsics.unaligned_load((^T) (rawptr(ptr + size_of(C)))) + p2 := intrinsics.unaligned_load((^T2)(rawptr(ptr + size_of(C) + size_of(T)))) + p3 := intrinsics.unaligned_load((^T3)(rawptr(ptr + size_of(C) + size_of(T) + size_of(T2)))) + cb(op, p, p2, p3) + } +} + +_put_user_data :: #force_inline proc(op: ^Operation, cb: $C, p: $T) { + ptr := uintptr(&op.user_data) + intrinsics.unaligned_store((^C)(rawptr(ptr)), cb) + intrinsics.unaligned_store((^T)(rawptr(ptr + size_of(cb))), p) +} + +_put_user_data2 :: #force_inline proc(op: ^Operation, cb: $C, p: $T, p2: $T2) { + ptr := uintptr(&op.user_data) + intrinsics.unaligned_store((^C) (rawptr(ptr)), cb) + intrinsics.unaligned_store((^T) (rawptr(ptr + size_of(cb))), p) + intrinsics.unaligned_store((^T2)(rawptr(ptr + size_of(cb) + size_of(p))), p2) +} + +_put_user_data3 :: #force_inline proc(op: ^Operation, cb: $C, p: $T, p2: $T2, p3: $T3) { + ptr := uintptr(&op.user_data) + intrinsics.unaligned_store((^C) (rawptr(ptr)), cb) + intrinsics.unaligned_store((^T) (rawptr(ptr + size_of(cb))), p) + intrinsics.unaligned_store((^T2)(rawptr(ptr + size_of(cb) + size_of(p))), p2) + intrinsics.unaligned_store((^T3)(rawptr(ptr + size_of(cb) + size_of(p) + size_of(p2))), p3) +} diff --git a/core/net/addr.odin b/core/net/addr.odin index c47c6f55e..888744841 100644 --- a/core/net/addr.odin +++ b/core/net/addr.odin @@ -1,4 +1,3 @@ -#+build windows, linux, darwin, freebsd package net /* @@ -11,7 +10,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -22,7 +21,6 @@ package net import "core:strconv" import "core:strings" -import "core:fmt" /* Expects an IPv4 address with no leading or trailing whitespace: @@ -461,31 +459,63 @@ split_port :: proc(endpoint_str: string) -> (addr_or_host: string, port: int, ok return } -// Joins an address or hostname with a port. -join_port :: proc(address_or_host: string, port: int, allocator := context.allocator) -> string { +// Joins an address or hostname with a port, allocated using an Allocator. +join_port_allocator :: proc(address_or_host: string, port: int, allocator := context.allocator) -> string { addr_or_host, _, ok := split_port(address_or_host) if !ok { return addr_or_host } b := strings.builder_make(allocator) + addr := parse_address(addr_or_host) + if addr == nil { + // hostname + strings.write_string(&b, addr_or_host) + strings.write_string(&b, ":") + strings.write_int(&b, port) + return strings.to_string(b) + } else { + return _join_port_internal(addr, port, &b) + } +} + +// Joins an address or hostname with a port, allocated using a `strings.Builder`. +join_port_builder :: proc(address_or_host: string, port: int, b: ^strings.Builder) -> string { + addr_or_host, _, ok := split_port(address_or_host) + if !ok { + return addr_or_host + } addr := parse_address(addr_or_host) if addr == nil { // hostname - fmt.sbprintf(&b, "%v:%v", addr_or_host, port) + strings.write_string(b, addr_or_host) + strings.write_string(b, ":") + strings.write_int(b, port) + return strings.to_string(b^) } else { - switch _ in addr { - case IP4_Address: - fmt.sbprintf(&b, "%v:%v", address_to_string(addr), port) - case IP6_Address: - fmt.sbprintf(&b, "[%v]:%v", address_to_string(addr), port) - } + return _join_port_internal(addr, port, b) } - return strings.to_string(b) } +join_port :: proc{join_port_allocator, join_port_builder} +// Also used in `endpoint_to_string_builder`. +@(private) +_join_port_internal :: proc(addr: Address, port: int, b: ^strings.Builder) -> string { + switch a in addr { + case IP4_Address: + address_to_string_builder(addr, b) + strings.write_string(b, ":") + strings.write_int(b, port) + case IP6_Address: + strings.write_string(b, "[") + address_to_string_builder(addr, b) + strings.write_string(b, "]:") + strings.write_int(b, port) + } + return strings.to_string(b^) +} // TODO(tetra): Do we need this? map_to_ip6 :: proc(addr: Address) -> Address { @@ -495,8 +525,8 @@ map_to_ip6 :: proc(addr: Address) -> Address { addr4 := addr.(IP4_Address) addr4_u16 := transmute([2]u16be) addr4 addr6: IP6_Address - addr6[4] = 0xffff - copy(addr6[5:], addr4_u16[:]) + addr6[5] = 0xffff + copy(addr6[6:], addr4_u16[:]) return addr6 } @@ -505,11 +535,26 @@ map_to_ip6 :: proc(addr: Address) -> Address { See RFC 5952 section 4 for IPv6 representation recommendations. */ -address_to_string :: proc(addr: Address, allocator := context.temp_allocator) -> string { +address_to_string_allocator :: proc(addr: Address, allocator := context.temp_allocator) -> string { b := strings.builder_make(allocator) + return address_to_string_builder(addr, &b) +} + +/* + Returns a string representation of the address using a `strings.Builder`. + + See RFC 5952 section 4 for IPv6 representation recommendations. +*/ +address_to_string_builder :: proc(addr: Address, b: ^strings.Builder) -> string { switch v in addr { case IP4_Address: - fmt.sbprintf(&b, "%v.%v.%v.%v", v[0], v[1], v[2], v[3]) + strings.write_uint(b, uint(v[0])) + strings.write_byte(b, '.') + strings.write_uint(b, uint(v[1])) + strings.write_byte(b, '.') + strings.write_uint(b, uint(v[2])) + strings.write_byte(b, '.') + strings.write_uint(b, uint(v[3])) case IP6_Address: // First find the longest run of zeroes. Zero_Run :: struct { @@ -563,50 +608,61 @@ address_to_string :: proc(addr: Address, allocator := context.temp_allocator) -> for val, i in v { if best.start == i || best.end == i { // For the left and right side of the best zero run, print a `:`. - fmt.sbprint(&b, ":") + strings.write_string(b, ":") } else if i < best.start { /* If we haven't made it to the best run yet, print the digit. Make sure we only print a `:` after the digit if it's not immediately followed by the run's own leftmost `:`. */ - fmt.sbprintf(&b, "%x", val) + + buf: [32]byte + str := strconv.write_bits(buf[:], u64(val), 16, false, size_of(val), strconv.digits, {}) + strings.write_string(b, str) + if i < best.start - 1 { - fmt.sbprintf(&b, ":") + strings.write_string(b, ":") } } else if i > best.end { /* If there are any digits after the zero run, print them. But don't print the `:` at the end of the IP number. */ - fmt.sbprintf(&b, "%x", val) + + buf: [32]byte + str := strconv.write_bits(buf[:], u64(val), 16, false, size_of(val), strconv.digits, {}) + strings.write_string(b, str) + if i != 7 { - fmt.sbprintf(&b, ":") + strings.write_string(b, ":") } } } } - return strings.to_string(b) + return strings.to_string(b^) } +address_to_string :: proc{address_to_string_allocator, address_to_string_builder} // Returns a temporarily-allocated string representation of the endpoint. // If there's a port, uses the `ip4address:port` or `[ip6address]:port` format, respectively. -endpoint_to_string :: proc(ep: Endpoint, allocator := context.temp_allocator) -> string { +endpoint_to_string_allocator :: proc(ep: Endpoint, allocator := context.temp_allocator) -> string { + b := strings.builder_make(allocator) + return endpoint_to_string_builder(ep, &b) +} + +// Returns a string representation of the endpoint using a `strings.Builder`. +// If there's a port, uses the `ip4address:port` or `[ip6address]:port` format, respectively. +endpoint_to_string_builder :: proc(ep: Endpoint, b: ^strings.Builder) -> string { if ep.port == 0 { - return address_to_string(ep.address, allocator) + return address_to_string(ep.address, b) } else { - s := address_to_string(ep.address, context.temp_allocator) - b := strings.builder_make(allocator) - switch a in ep.address { - case IP4_Address: fmt.sbprintf(&b, "%v:%v", s, ep.port) - case IP6_Address: fmt.sbprintf(&b, "[%v]:%v", s, ep.port) - } - return strings.to_string(b) + return _join_port_internal(ep.address, ep.port, b) } } -to_string :: proc{address_to_string, endpoint_to_string} +endpoint_to_string :: proc{endpoint_to_string_allocator, endpoint_to_string_builder} +to_string :: proc{address_to_string_allocator, address_to_string_builder, endpoint_to_string_allocator, endpoint_to_string_builder} family_from_address :: proc(addr: Address) -> Address_Family { switch _ in addr { diff --git a/core/net/common.odin b/core/net/common.odin index fb6b17511..2758a7359 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -1,4 +1,3 @@ -#+build windows, linux, darwin, freebsd package net /* @@ -14,7 +13,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -64,6 +63,7 @@ Network_Error :: union #shared_nil { UDP_Recv_Error, Shutdown_Error, Interfaces_Error, + Socket_Info_Error, Socket_Option_Error, Set_Blocking_Error, Parse_Endpoint_Error, @@ -90,6 +90,7 @@ Parse_Endpoint_Error :: enum u32 { Resolve_Error :: enum u32 { None = 0, Unable_To_Resolve = 1, + Allocation_Failure, } DNS_Error :: enum u32 { @@ -143,11 +144,11 @@ Address :: union {IP4_Address, IP6_Address} IP4_Loopback :: IP4_Address{127, 0, 0, 1} IP6_Loopback :: IP6_Address{0, 0, 0, 0, 0, 0, 0, 1} -IP4_Any := IP4_Address{} -IP6_Any := IP6_Address{} +IP4_Any :: IP4_Address{} +IP6_Any :: IP6_Address{} -IP4_mDNS_Broadcast := Endpoint{address=IP4_Address{224, 0, 0, 251}, port=5353} -IP6_mDNS_Broadcast := Endpoint{address=IP6_Address{65282, 0, 0, 0, 0, 0, 0, 251}, port = 5353} +IP4_mDNS_Broadcast :: Endpoint{address=IP4_Address{224, 0, 0, 251}, port=5353} +IP6_mDNS_Broadcast :: Endpoint{address=IP6_Address{65282, 0, 0, 0, 0, 0, 0, 251}, port = 5353} Endpoint :: struct { address: Address, @@ -260,6 +261,9 @@ DNS_Configuration :: struct { resolv_conf: string, hosts_file: string, + resolv_conf_buf: [128]u8, + hosts_file_buf: [128]u8, + // TODO: Allow loading these up with `reload_configuration()` call or the like, // so we don't have to do it each call. name_servers: []Endpoint, diff --git a/core/net/dns.odin b/core/net/dns.odin index 7eb543db3..54cc57c38 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -1,4 +1,3 @@ -#+build windows, linux, darwin, freebsd package net /* @@ -12,7 +11,7 @@ package net Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . Copyright 2025 Christiano Haesbaert . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -22,69 +21,38 @@ package net Haesbaert: Security fixes */ +@(require) +import "base:runtime" +import "core:bufio" +import "core:io" import "core:mem" import "core:strings" import "core:time" -import "core:os" -import "core:math/rand" -/* - Default configuration for DNS resolution. -*/ + +@(require) +import "core:sync" + +dns_config_initialized: sync.Once when ODIN_OS == .Windows { - DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{ - resolv_conf = "", - hosts_file = "%WINDIR%\\system32\\drivers\\etc\\hosts", + dns_configuration := DNS_Configuration{ + resolv_conf = "", + hosts_file = "%WINDIR%\\system32\\drivers\\etc\\hosts", } } else when ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD { - DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{ - resolv_conf = "/etc/resolv.conf", - hosts_file = "/etc/hosts", + dns_configuration := DNS_Configuration{ + resolv_conf = "/etc/resolv.conf", + hosts_file = "/etc/hosts", } } else { - #panic("Please add a configuration for this OS.") + DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{} } -@(init) init_dns_configuration :: proc() { - /* - Resolve %ENVIRONMENT% placeholders in their paths. - */ - dns_configuration.resolv_conf, _ = replace_environment_path(dns_configuration.resolv_conf) - dns_configuration.hosts_file, _ = replace_environment_path(dns_configuration.hosts_file) -} - -@(fini, private) -destroy_dns_configuration :: proc() { - delete(dns_configuration.resolv_conf) - dns_configuration.resolv_conf = "" - delete(dns_configuration.hosts_file) - dns_configuration.hosts_file = "" -} - -dns_configuration := DEFAULT_DNS_CONFIGURATION - -// Always allocates for consistency. -replace_environment_path :: proc(path: string, allocator := context.allocator) -> (res: string, ok: bool) { - // Nothing to replace. Return a clone of the original. - if strings.count(path, "%") != 2 { - return strings.clone(path, allocator), true + when ODIN_OS == .Windows { + _init_dns_configuration() } - - left := strings.index(path, "%") + 1 - assert(left > 0 && left <= len(path)) // should be covered by there being two % - - right := strings.index(path[left:], "%") + 1 - assert(right > 0 && right <= len(path)) // should be covered by there being two % - - env_key := path[left: right] - env_val := os.get_env(env_key, allocator) - defer delete(env_val) - - res, _ = strings.replace(path, path[left - 1: right + 1], env_val, 1, allocator) - return res, true } - /* Resolves a hostname to exactly one IP4 and IP6 endpoint. It's then up to you which one you use. @@ -204,6 +172,7 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net See `destroy_records`. */ get_dns_records_from_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { + init_dns_configuration() return _get_dns_records_os(hostname, type, allocator) } @@ -219,48 +188,17 @@ get_dns_records_from_os :: proc(hostname: string, type: DNS_Record_Type, allocat See `destroy_records`. */ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type, name_servers: []Endpoint, host_overrides: []DNS_Record, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { + init_dns_configuration() context.allocator = allocator - if type != .SRV { - // NOTE(tetra): 'hostname' can contain underscores when querying SRV records - ok := validate_hostname(hostname) - if !ok { - return nil, .Invalid_Hostname_Error - } - } + id: u16be + rand_ok := runtime.random_generator_read_ptr(context.random_generator, &id, size_of(id)) + assert(rand_ok, "uninitialized gen/context.random_generator") - hdr := DNS_Header{ - id = u16be(rand.uint32()), - is_response = false, - opcode = 0, - is_authoritative = false, - is_truncated = false, - is_recursion_desired = true, - is_recursion_available = false, - response_code = DNS_Response_Code.No_Error, - } + dns_packet_buf: [DNS_PACKET_MIN_LEN]byte = --- + dns_packet := make_dns_packet(dns_packet_buf[:], id, hostname, type) or_return - id, bits := pack_dns_header(hdr) - dns_hdr := [6]u16be{} - dns_hdr[0] = id - dns_hdr[1] = bits - dns_hdr[2] = 1 - - dns_query := [2]u16be{ u16be(type), 1 } - - output := [(size_of(u16be) * 6) + NAME_MAX + (size_of(u16be) * 2)]u8{} - b := strings.builder_from_slice(output[:]) - - strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_hdr[:])) - ok := encode_hostname(&b, hostname) - if !ok { - return nil, .Invalid_Hostname_Error - } - strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_query[:])) - - dns_packet := output[:strings.builder_len(b)] - - dns_response_buf := [4096]u8{} + dns_response_buf: [4096]u8 = --- dns_response: []u8 for name_server in name_servers { conn, sock_err := make_unbound_udp_socket(family_from_endpoint(name_server)) @@ -303,6 +241,42 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return } +DNS_PACKET_MIN_LEN :: (size_of(u16be) * 6) + NAME_MAX + (size_of(u16be) * 2) + +make_dns_packet :: proc(buf: []byte, id: u16be, hostname: string, type: DNS_Record_Type) -> (packet: []byte, err: DNS_Error) { + assert(len(buf) >= DNS_PACKET_MIN_LEN) + + hdr := DNS_Header{ + id = id, + is_response = false, + opcode = 0, + is_authoritative = false, + is_truncated = false, + is_recursion_desired = true, + is_recursion_available = false, + response_code = DNS_Response_Code.No_Error, + } + + _, bits := pack_dns_header(hdr) + dns_hdr := [6]u16be{} + dns_hdr[0] = id + dns_hdr[1] = bits + dns_hdr[2] = 1 + + dns_query := [2]u16be{ u16be(type), 1 } + + b := strings.builder_from_slice(buf[:]) + + strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_hdr[:])) + ok := encode_hostname(&b, hostname) + if !ok { + return nil, .Invalid_Hostname_Error + } + strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_query[:])) + + return buf[:strings.builder_len(b)], nil +} + // `records` slice is also destroyed. destroy_dns_records :: proc(records: []DNS_Record, allocator := context.allocator) { context.allocator = allocator @@ -384,13 +358,8 @@ unpack_dns_header :: proc(id: u16be, bits: u16be) -> (hdr: DNS_Header) { return hdr } -load_resolv_conf :: proc(resolv_conf_path: string, allocator := context.allocator) -> (name_servers: []Endpoint, ok: bool) { - context.allocator = allocator - - res := os.read_entire_file_from_filename(resolv_conf_path) or_return - defer delete(res) - resolv_str := string(res) - +parse_resolv_conf :: proc(resolv_str: string, allocator := context.allocator) -> (name_servers: []Endpoint) { + resolv_str := resolv_str id_str := "nameserver" id_len := len(id_str) @@ -421,39 +390,51 @@ load_resolv_conf :: proc(resolv_conf_path: string, allocator := context.allocato append(&_name_servers, endpoint) } - return _name_servers[:], true + return _name_servers[:] } -load_hosts :: proc(hosts_file_path: string, allocator := context.allocator) -> (hosts: []DNS_Host_Entry, ok: bool) { - context.allocator = allocator +parse_hosts :: proc(stream: io.Stream, allocator := context.allocator) -> (hosts: []DNS_Host_Entry, ok: bool) { + s := bufio.scanner_init(&{}, stream, allocator) + defer bufio.scanner_destroy(s) - res := os.read_entire_file_from_filename(hosts_file_path, allocator) or_return - defer delete(res) + resize(&s.buf, 256) - _hosts := make([dynamic]DNS_Host_Entry, 0, allocator) - hosts_str := string(res) - for line in strings.split_lines_iterator(&hosts_str) { - if len(line) == 0 || line[0] == '#' { - continue + _hosts: [dynamic]DNS_Host_Entry + _hosts.allocator = allocator + defer if !ok { + for host in _hosts { + delete(host.name, allocator) } + delete(_hosts) + } - splits := strings.fields(line) - defer delete(splits) + for bufio.scanner_scan(s) { + line := bufio.scanner_text(s) + + line, _, _ = strings.partition(line, "#") + (len(line) > 0) or_continue + + ip_str := strings.fields_iterator(&line) or_continue - ip_str := splits[0] addr := parse_address(ip_str) - if addr == nil { - continue - } + (addr != nil) or_continue - for hostname in splits[1:] { - if len(hostname) != 0 { - append(&_hosts, DNS_Host_Entry{hostname, addr}) - } + for hostname in strings.fields_iterator(&line) { + (len(hostname) > 0) or_continue + + clone, alloc_err := strings.clone(hostname, allocator) + if alloc_err != nil { return } + + _, alloc_err = append(&_hosts, DNS_Host_Entry{clone, addr}) + if alloc_err != nil { return } } } - return _hosts[:], true + if bufio.scanner_error(s) != nil { return } + + hosts = _hosts[:] + ok = true + return } // www.google.com -> 3www6google3com0 @@ -612,7 +593,7 @@ decode_hostname :: proc(packet: []u8, start_idx: int, allocator := context.alloc // Uses RFC 952 & RFC 1123 validate_hostname :: proc(hostname: string) -> (ok: bool) { - if len(hostname) > 255 || len(hostname) == 0 { + if len(hostname) > NAME_MAX || len(hostname) == 0 { return } @@ -622,7 +603,7 @@ validate_hostname :: proc(hostname: string) -> (ok: bool) { _hostname := hostname for label in strings.split_iterator(&_hostname, ".") { - if len(label) > 63 || len(label) == 0 { + if len(label) > LABEL_MAX || len(label) == 0 { return } diff --git a/core/net/dns_os.odin b/core/net/dns_os.odin new file mode 100644 index 000000000..ad9724d37 --- /dev/null +++ b/core/net/dns_os.odin @@ -0,0 +1,24 @@ +#+build darwin, freebsd, openbsd, netbsd, linux, windows, wasi +#+private +package net + +import "core:os" + +load_resolv_conf :: proc(resolv_conf_path: string, allocator := context.allocator) -> (name_servers: []Endpoint, ok: bool) { + context.allocator = allocator + + res, err := os.read_entire_file(resolv_conf_path, allocator) + if err != nil { return } + defer delete(res) + resolv_str := string(res) + + return parse_resolv_conf(resolv_str), true +} + +load_hosts :: proc(hosts_file_path: string, allocator := context.allocator) -> (hosts: []DNS_Host_Entry, ok: bool) { + handle, err := os.open(hosts_file_path) + if err != nil { return } + defer os.close(handle) + + return parse_hosts(os.to_stream(handle), allocator) +} \ No newline at end of file diff --git a/core/net/dns_others.odin b/core/net/dns_others.odin new file mode 100644 index 000000000..842e833aa --- /dev/null +++ b/core/net/dns_others.odin @@ -0,0 +1,12 @@ +#+build !windows +#+build !linux +#+build !darwin +#+build !freebsd +#+build !netbsd +#+build !openbsd +package net + +@(private) +_get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { + return +} diff --git a/core/net/dns_unix.odin b/core/net/dns_unix.odin index e4336e410..be95b8341 100644 --- a/core/net/dns_unix.odin +++ b/core/net/dns_unix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd +#+build linux, darwin, freebsd, openbsd, netbsd package net /* Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures. @@ -10,7 +10,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -42,14 +42,19 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator : } hosts, hosts_ok := load_hosts(dns_configuration.hosts_file) - defer delete(hosts) if !hosts_ok { return nil, .Invalid_Hosts_Config_Error } + defer { + for h in hosts { + delete(h.name) + } + delete(hosts) + } host_overrides := make([dynamic]DNS_Record) for host in hosts { - if strings.compare(host.name, hostname) != 0 { + if host.name != hostname { continue } diff --git a/core/net/dns_windows.odin b/core/net/dns_windows.odin index 7736851b8..393df5fa7 100644 --- a/core/net/dns_windows.odin +++ b/core/net/dns_windows.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -20,11 +20,29 @@ package net Feoramund: FreeBSD platform code */ -import "core:strings" +import "base:runtime" + import "core:mem" +import "core:os" +import "core:strings" +import "core:sync" import win "core:sys/windows" +/* + Replaces environment placeholders in `dns_configuration`. Only necessary on Windows. + Is automatically called, once, by `get_dns_records_*`. +*/ +@(private) +_init_dns_configuration :: proc() { + sync.once_do(&dns_config_initialized, proc() { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + val := os.replace_environment_placeholders(dns_configuration.hosts_file, context.temp_allocator) + copy(dns_configuration.hosts_file_buf[:], val) + dns_configuration.hosts_file = string(dns_configuration.hosts_file_buf[:len(val)]) + }) +} + @(private) _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { context.allocator = allocator @@ -171,4 +189,4 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator : records = recs[:] return -} \ No newline at end of file +} diff --git a/core/net/doc.odin b/core/net/doc.odin index ed720c0ae..8fd88904c 100644 --- a/core/net/doc.odin +++ b/core/net/doc.odin @@ -1,20 +1,5 @@ /* - Copyright 2022 Tetralux - Copyright 2022 Colin Davidson - Copyright 2022 Jeroen van Rijn . - Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. - - List of contributors: - Tetralux: Initial implementation - Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver - Jeroen van Rijn: Cross platform unification, code style, documentation - Feoramund: FreeBSD platform code -*/ - -/* -Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures. -For other protocols and their features, see subdirectories of this package. +Cross-platform Berkeley Sockets, `DNS` resolution and associated procedures. Features: - Supports Windows, Linux and OSX. @@ -44,3 +29,17 @@ or worse. This means that should you replace the temp allocator with an insuffic we'll do our best to loudly complain the first time you try it. */ package net + +/* + Copyright 2022 Tetralux + Copyright 2022 Colin Davidson + Copyright 2022 Jeroen van Rijn . + Copyright 2024 Feoramund . + Made available under Odin's license. + + List of contributors: + Tetralux: Initial implementation + Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver + Jeroen van Rijn: Cross platform unification, code style, documentation + Feoramund: FreeBSD platform code +*/ \ No newline at end of file diff --git a/core/net/errors.odin b/core/net/errors.odin index 53c936a66..28153375c 100644 --- a/core/net/errors.odin +++ b/core/net/errors.odin @@ -139,6 +139,11 @@ Accept_Error :: enum i32 { Unknown, } +Recv_Error :: union #shared_nil { + TCP_Recv_Error, + UDP_Recv_Error, +} + TCP_Recv_Error :: enum i32 { None, // No network connection, or the network stack is not initialized. @@ -149,7 +154,8 @@ TCP_Recv_Error :: enum i32 { Invalid_Argument, // The socket is not connected. Not_Connected, - // Connection was closed/broken/shutdown while receiving data. + // Connection was closed due to an error or shutdown. + // NOTE: a graceful close is indicated by a `0, nil` (0 bytes received and no error) return. Connection_Closed, // Timed out before being able to receive any data. Timeout, @@ -170,7 +176,8 @@ UDP_Recv_Error :: enum i32 { Insufficient_Resources, // Invalid socket or buffer given. Invalid_Argument, - // "Connection" was refused by remote, or closed/broken/shutdown while receiving data. + // "Connection" was refused, or closed due to an error. + // NOTE: a graceful close is indicated by a `0, nil` (0 bytes received and no error) return. Connection_Refused, // Timed out before being able to receive any data. Timeout, @@ -185,6 +192,11 @@ UDP_Recv_Error :: enum i32 { Unknown, } +Send_Error :: union #shared_nil { + TCP_Send_Error, + UDP_Send_Error, +} + TCP_Send_Error :: enum i32 { None, // No network connection, or the network stack is not initialized. @@ -193,7 +205,7 @@ TCP_Send_Error :: enum i32 { Insufficient_Resources, // Invalid socket or buffer given. Invalid_Argument, - // Connection was closed/broken/shutdown while receiving data. + // Connection was closed/broken/shutdown while sending data. Connection_Closed, // The socket is not connected. Not_Connected, @@ -246,6 +258,23 @@ Shutdown_Error :: enum i32 { Unknown, } +Socket_Info_Error :: enum i32 { + None, + // No network connection, or the network stack is not initialized. + Network_Unreachable, + // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. + Insufficient_Resources, + // Socket is invalid or not connected, or the manner given is invalid. + Invalid_Argument, + // The socket is valid, but unsupported by this opperation. + Unsupported_Socket, + // Connection was closed/aborted/shutdown. + Connection_Closed, + + // An error unable to be categorized in above categories, `last_platform_error` may have more info. + Unknown, +} + Socket_Option_Error :: enum i32 { None, // No network connection, or the network stack is not initialized. diff --git a/core/net/errors_freebsd.odin b/core/net/errors_freebsd.odin index 707ffd0dd..29bdd3ff8 100644 --- a/core/net/errors_freebsd.odin +++ b/core/net/errors_freebsd.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -255,6 +255,24 @@ _shutdown_error :: proc(errno: freebsd.Errno) -> Shutdown_Error { } } +_socket_info_error :: proc(errno: freebsd.Errno) -> Socket_Info_Error { + assert(errno != nil) + _last_error = errno + + #partial switch errno { + case .EBADF, .ENOTSOCK, .EINVAL, .EFAULT: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .ECONNRESET: + return .Connection_Closed + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc(errno: freebsd.Errno) -> Socket_Option_Error { assert(errno != nil) _last_error = errno diff --git a/core/net/errors_linux.odin b/core/net/errors_linux.odin index 237579f28..636ebb6f9 100644 --- a/core/net/errors_linux.odin +++ b/core/net/errors_linux.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -258,6 +258,22 @@ _shutdown_error :: proc(errno: linux.Errno) -> Shutdown_Error { } } +_socket_info_error :: proc(errno: linux.Errno) -> Socket_Info_Error { + assert(errno != nil) + _last_error = errno + + #partial switch errno { + case .EBADF, .ENOTSOCK, .EFAULT, .EINVAL: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc(errno: linux.Errno) -> Socket_Option_Error { assert(errno != nil) _last_error = errno diff --git a/core/net/errors_others.odin b/core/net/errors_others.odin index bda0fd28f..3a752d58e 100644 --- a/core/net/errors_others.odin +++ b/core/net/errors_others.odin @@ -2,6 +2,8 @@ #+build !linux #+build !freebsd #+build !windows +#+build !netbsd +#+build !openbsd package net @(private="file", thread_local) diff --git a/core/net/errors_darwin.odin b/core/net/errors_posix.odin similarity index 93% rename from core/net/errors_darwin.odin rename to core/net/errors_posix.odin index 7aaa220e9..b59cbc30b 100644 --- a/core/net/errors_darwin.odin +++ b/core/net/errors_posix.odin @@ -1,4 +1,4 @@ -#+build darwin +#+build darwin, netbsd, openbsd package net /* @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -226,6 +226,23 @@ _shutdown_error :: proc() -> Shutdown_Error { } } +_socket_info_error :: proc() -> Socket_Info_Error { + #partial switch posix.errno() { + case .EBADF, .ENOTSOCK: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .EOPNOTSUPP: + return .Unsupported_Socket + case .EINVAL: + return .Connection_Closed + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc() -> Socket_Option_Error { #partial switch posix.errno() { case .ENOBUFS: diff --git a/core/net/errors_windows.odin b/core/net/errors_windows.odin index b30046a17..6d3724c82 100644 --- a/core/net/errors_windows.odin +++ b/core/net/errors_windows.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -63,7 +63,7 @@ _dial_error :: proc() -> Dial_Error { return .Already_Connecting case .WSAEADDRNOTAVAIL, .WSAEAFNOSUPPORT, .WSAEFAULT, .WSAENOTSOCK, .WSAEINPROGRESS, .WSAEINVAL: return .Invalid_Argument - case .WSAECONNREFUSED: + case .WSAECONNREFUSED, .CONNECTION_REFUSED: return .Refused case .WSAEISCONN: return .Already_Connected @@ -122,7 +122,7 @@ _accept_error :: proc() -> Accept_Error { return .Aborted case .WSAEFAULT, .WSAEINPROGRESS, .WSAENOTSOCK: return .Invalid_Argument - case .WSAEINTR: + case .WSAEINTR, .OPERATION_ABORTED: return .Interrupted case .WSAEINVAL: return .Not_Listening @@ -234,6 +234,17 @@ _shutdown_error :: proc() -> Shutdown_Error { } } +_socket_info_error :: proc() -> Socket_Info_Error { + #partial switch win.System_Error(win.WSAGetLastError()) { + case .WSAEFAULT, .WSAEINPROGRESS, .WSAENOTSOCK, .WSAEINVAL: + return .Invalid_Argument + case .WSANOTINITIALISED, .WSAENETDOWN, .WSAENOTCONN: + return .Network_Unreachable + case: + return .Unknown + } +} + _socket_option_error :: proc() -> Socket_Option_Error { #partial switch win.System_Error(win.WSAGetLastError()) { case .WSAENETDOWN, .WSANOTINITIALISED: diff --git a/core/net/interface.odin b/core/net/interface.odin index 4d499a008..182ef3584 100644 --- a/core/net/interface.odin +++ b/core/net/interface.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation diff --git a/core/net/interface_freebsd.odin b/core/net/interface_freebsd.odin index 90a538a04..056ad3ac6 100644 --- a/core/net/interface_freebsd.odin +++ b/core/net/interface_freebsd.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation diff --git a/core/net/interface_linux.odin b/core/net/interface_linux.odin index e329803c5..8680c39d8 100644 --- a/core/net/interface_linux.odin +++ b/core/net/interface_linux.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation diff --git a/core/net/interface_others.odin b/core/net/interface_others.odin new file mode 100644 index 000000000..9a8a141df --- /dev/null +++ b/core/net/interface_others.odin @@ -0,0 +1,11 @@ +#+build !darwin +#+build !linux +#+build !freebsd +#+build !windows +#+build !netbsd +#+build !openbsd +package net + +_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) { + return +} diff --git a/core/net/interface_darwin.odin b/core/net/interface_posix.odin similarity index 77% rename from core/net/interface_darwin.odin rename to core/net/interface_posix.odin index f189e5844..202951b29 100644 --- a/core/net/interface_darwin.odin +++ b/core/net/interface_posix.odin @@ -1,4 +1,4 @@ -#+build darwin +#+build darwin, openbsd, netbsd package net /* @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -23,7 +23,7 @@ package net import "core:strings" import "core:sys/posix" -foreign import lib "system:System.framework" +foreign import lib "system:System" @(private) _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) { @@ -117,32 +117,47 @@ IF_Flag :: enum u32 { BROADCAST, DEBUG, LOOPBACK, - POINTTOPOINT, - NOTRAILERS, - RUNNING, - NOARP, - PROMISC, - ALLMULTI, - OACTIVE, - SIMPLEX, - LINK0, - LINK1, - LINK2, - MULTICAST, + // NOTE: different order on other BSDs but we don't even need these. + // POINTTOPOINT, + // NOTRAILERS, + // RUNNING, + // NOARP, + // PROMISC, + // ALLMULTI, + // OACTIVE, + // SIMPLEX, + // LINK0, + // LINK1, + // LINK2, + // MULTICAST, } @(private) IF_Flags :: bit_set[IF_Flag; u32] -@(private) -ifaddrs :: struct { - next: ^ifaddrs, - name: cstring, - flags: IF_Flags, - addr: ^posix.sockaddr, - netmask: ^posix.sockaddr, - dstaddr: ^posix.sockaddr, - data: rawptr, +when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { + @(private) + ifaddrs :: struct { + next: ^ifaddrs, + name: cstring, + flags: IF_Flags, + addr: ^posix.sockaddr, + netmask: ^posix.sockaddr, + dstaddr: ^posix.sockaddr, + data: rawptr, + } +} else when ODIN_OS == .NetBSD { + @(private) + ifaddrs :: struct { + next: ^ifaddrs, + name: cstring, + flags: IF_Flags, + addr: ^posix.sockaddr, + netmask: ^posix.sockaddr, + dstaddr: ^posix.sockaddr, + data: rawptr, + addrflags: u32, + } } @(private) diff --git a/core/net/interface_windows.odin b/core/net/interface_windows.odin index 571fb322f..c4e3c22eb 100644 --- a/core/net/interface_windows.odin +++ b/core/net/interface_windows.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation diff --git a/core/net/socket.odin b/core/net/socket.odin index 801693962..e2f96e2f3 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -1,4 +1,3 @@ -#+build windows, linux, darwin, freebsd package net /* @@ -11,7 +10,7 @@ package net Copyright 2022-2023 Colin Davidson Copyright 2022-2023 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -20,6 +19,35 @@ package net Feoramund: FreeBSD platform code */ +Socket_Option :: enum i32 { + Broadcast = i32(_SOCKET_OPTION_BROADCAST), + Reuse_Address = i32(_SOCKET_OPTION_REUSE_ADDRESS), + Keep_Alive = i32(_SOCKET_OPTION_KEEP_ALIVE), + Out_Of_Bounds_Data_Inline = i32(_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE), + Linger = i32(_SOCKET_OPTION_LINGER), + Receive_Buffer_Size = i32(_SOCKET_OPTION_RECEIVE_BUFFER_SIZE), + Send_Buffer_Size = i32(_SOCKET_OPTION_SEND_BUFFER_SIZE), + Receive_Timeout = i32(_SOCKET_OPTION_RECEIVE_TIMEOUT), + Send_Timeout = i32(_SOCKET_OPTION_SEND_TIMEOUT), + + TCP_Nodelay = i32(_SOCKET_OPTION_TCP_NODELAY), + + Use_Loopback = i32(_SOCKET_OPTION_USE_LOOPBACK), + Reuse_Port = i32(_SOCKET_OPTION_REUSE_PORT), + No_SIGPIPE_From_EPIPE = i32(_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE), + Reuse_Port_Load_Balancing = i32(_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING), + + Exclusive_Addr_Use = i32(_SOCKET_OPTION_EXCLUSIVE_ADDR_USE), + Conditional_Accept = i32(_SOCKET_OPTION_CONDITIONAL_ACCEPT), + Dont_Linger = i32(_SOCKET_OPTION_DONT_LINGER), +} + +Shutdown_Manner :: enum i32 { + Receive = i32(_SHUTDOWN_MANNER_RECEIVE), + Send = i32(_SHUTDOWN_MANNER_SEND), + Both = i32(_SHUTDOWN_MANNER_BOTH), +} + any_socket_to_socket :: proc "contextless" (socket: Any_Socket) -> Socket { switch s in socket { case TCP_Socket: return Socket(s) @@ -174,10 +202,17 @@ listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: TC /* Returns the endpoint that the given socket is listening / bound on. */ -bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Listen_Error) { +bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Socket_Info_Error) { return _bound_endpoint(socket) } +/* + Returns the endpoint that the given socket is connected to. (Peer's endpoint) +*/ +peer_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Socket_Info_Error) { + return _peer_endpoint(socket) +} + accept_tcp :: proc(socket: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { return _accept_tcp(socket, options) } @@ -186,21 +221,36 @@ close :: proc(socket: Any_Socket) { _close(socket) } +/* + Receive data into a buffer from a TCP socket. + + If no error occurs, `recv_tcp` returns the number of bytes received and `buf` will contain this data received. + If the connection has been gracefully closed, the return value is `0, nil` (0 bytes read and no error). +*/ recv_tcp :: proc(socket: TCP_Socket, buf: []byte) -> (bytes_read: int, err: TCP_Recv_Error) { return _recv_tcp(socket, buf) } +/* + Receive data into a buffer from a UDP socket. + + If no error occurs, `recv_udp` returns the number of bytes received and `buf` will contain this data received. + If the "connection" has been gracefully closed, the return value is `0, nil` (0 bytes read and no error). +*/ recv_udp :: proc(socket: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endpoint: Endpoint, err: UDP_Recv_Error) { return _recv_udp(socket, buf) } /* - Receive data from into a buffer from any socket. + Receive data into a buffer from any socket. Note: `remote_endpoint` parameter is non-nil only if the socket type is UDP. On TCP sockets it will always return `nil`. - Errors that can be returned: `TCP_Recv_Error`, or `UDP_Recv_Error` + Errors that can be returned: `TCP_Recv_Error`, or `UDP_Recv_Error`. + + If no error occurs, `recv_any` returns the number of bytes received and `buf` will contain this data received. + If the connection has been gracefully closed, the return value is `0, nil, nil` (0 bytes read and no error). */ recv_any :: proc(socket: Any_Socket, buf: []byte) -> ( bytes_read: int, diff --git a/core/net/socket_freebsd.odin b/core/net/socket_freebsd.odin index b510346ba..bd600fd99 100644 --- a/core/net/socket_freebsd.odin +++ b/core/net/socket_freebsd.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -20,45 +20,35 @@ package net Feoramund: FreeBSD platform code */ -import "core:c" import "core:sys/freebsd" import "core:time" Fd :: freebsd.Fd -Socket_Option :: enum c.int { - // TODO: Test and implement more socket options. - // DEBUG - Reuse_Address = cast(c.int)freebsd.Socket_Option.REUSEADDR, - Keep_Alive = cast(c.int)freebsd.Socket_Option.KEEPALIVE, - // DONTROUTE - Broadcast = cast(c.int)freebsd.Socket_Option.BROADCAST, - Use_Loopback = cast(c.int)freebsd.Socket_Option.USELOOPBACK, - Linger = cast(c.int)freebsd.Socket_Option.LINGER, - Out_Of_Bounds_Data_Inline = cast(c.int)freebsd.Socket_Option.OOBINLINE, - Reuse_Port = cast(c.int)freebsd.Socket_Option.REUSEPORT, - // TIMESTAMP - No_SIGPIPE_From_EPIPE = cast(c.int)freebsd.Socket_Option.NOSIGPIPE, - // ACCEPTFILTER - // BINTIME - // NO_OFFLOAD - // NO_DDP - Reuse_Port_Load_Balancing = cast(c.int)freebsd.Socket_Option.REUSEPORT_LB, - // RERROR +_SOCKET_OPTION_BROADCAST :: freebsd.Socket_Option.BROADCAST +_SOCKET_OPTION_REUSE_ADDRESS :: freebsd.Socket_Option.REUSEADDR +_SOCKET_OPTION_KEEP_ALIVE :: freebsd.Socket_Option.KEEPALIVE +_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE :: freebsd.Socket_Option.OOBINLINE +_SOCKET_OPTION_LINGER :: freebsd.Socket_Option.LINGER +_SOCKET_OPTION_RECEIVE_BUFFER_SIZE :: freebsd.Socket_Option.RCVBUF +_SOCKET_OPTION_SEND_BUFFER_SIZE :: freebsd.Socket_Option.SNDBUF +_SOCKET_OPTION_RECEIVE_TIMEOUT :: freebsd.Socket_Option.RCVTIMEO +_SOCKET_OPTION_SEND_TIMEOUT :: freebsd.Socket_Option.SNDTIMEO - Send_Buffer_Size = cast(c.int)freebsd.Socket_Option.SNDBUF, - Receive_Buffer_Size = cast(c.int)freebsd.Socket_Option.RCVBUF, - // SNDLOWAT - // RCVLOWAT - Send_Timeout = cast(c.int)freebsd.Socket_Option.SNDTIMEO, - Receive_Timeout = cast(c.int)freebsd.Socket_Option.RCVTIMEO, -} +_SOCKET_OPTION_TCP_NODELAY :: -1 -Shutdown_Manner :: enum c.int { - Receive = cast(c.int)freebsd.Shutdown_Method.RD, - Send = cast(c.int)freebsd.Shutdown_Method.WR, - Both = cast(c.int)freebsd.Shutdown_Method.RDWR, -} +_SOCKET_OPTION_USE_LOOPBACK :: freebsd.Socket_Option.USELOOPBACK +_SOCKET_OPTION_REUSE_PORT :: freebsd.Socket_Option.REUSEPORT +_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE :: freebsd.Socket_Option.NOSIGPIPE +_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING :: freebsd.Socket_Option.REUSEPORT_LB + +_SOCKET_OPTION_EXCLUSIVE_ADDR_USE :: -1 +_SOCKET_OPTION_CONDITIONAL_ACCEPT :: -1 +_SOCKET_OPTION_DONT_LINGER :: -1 + +_SHUTDOWN_MANNER_RECEIVE :: freebsd.Shutdown_Method.RD +_SHUTDOWN_MANNER_SEND :: freebsd.Shutdown_Method.WR +_SHUTDOWN_MANNER_BOTH :: freebsd.Shutdown_Method.RDWR @(private) _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Create_Socket_Error) { @@ -140,12 +130,26 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: T } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: freebsd.Socket_Address_Storage errno := freebsd.getsockname(cast(Fd)any_socket_to_socket(sock), &sockaddr) if errno != nil { - err = _listen_error(errno) + err = _socket_info_error(errno) + return + } + + ep = _sockaddr_to_endpoint(&sockaddr) + return +} + +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + sockaddr: freebsd.Socket_Address_Storage + + errno := freebsd.getpeername(cast(Fd)any_socket_to_socket(sock), &sockaddr) + if errno != nil { + err = _socket_info_error(errno) return } @@ -258,7 +262,7 @@ _set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc : ptr: rawptr len: freebsd.socklen_t - switch option { + #partial switch option { case .Reuse_Address, .Keep_Alive, @@ -330,7 +334,7 @@ _set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc : ptr = &int_value len = size_of(int_value) case: - unimplemented("set_option() option not yet implemented", loc) + return .Invalid_Option } real_socket := any_socket_to_socket(socket) @@ -377,7 +381,7 @@ _endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: freebsd.Socket_Address } case IP6_Address: (cast(^freebsd.Socket_Address_Internet6)(&sockaddr))^ = { - len = size_of(freebsd.Socket_Address_Internet), + len = size_of(freebsd.Socket_Address_Internet6), family = .INET6, port = cast(freebsd.in_port_t)ep.port, addr = transmute(freebsd.IP6_Address)addr, diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index 3ec3521f0..8348ce114 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -21,28 +21,33 @@ package net Feoramund: FreeBSD platform code */ -import "core:c" import "core:time" import "core:sys/linux" -Socket_Option :: enum c.int { - Reuse_Address = c.int(linux.Socket_Option.REUSEADDR), - Keep_Alive = c.int(linux.Socket_Option.KEEPALIVE), - Out_Of_Bounds_Data_Inline = c.int(linux.Socket_Option.OOBINLINE), - TCP_Nodelay = c.int(linux.Socket_TCP_Option.NODELAY), - Linger = c.int(linux.Socket_Option.LINGER), - Receive_Buffer_Size = c.int(linux.Socket_Option.RCVBUF), - Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF), - Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO), - Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO), - Broadcast = c.int(linux.Socket_Option.BROADCAST), -} +_SOCKET_OPTION_BROADCAST :: linux.Socket_Option.BROADCAST +_SOCKET_OPTION_REUSE_ADDRESS :: linux.Socket_Option.REUSEADDR +_SOCKET_OPTION_KEEP_ALIVE :: linux.Socket_Option.KEEPALIVE +_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE :: linux.Socket_Option.OOBINLINE +_SOCKET_OPTION_LINGER :: linux.Socket_Option.LINGER +_SOCKET_OPTION_RECEIVE_BUFFER_SIZE :: linux.Socket_Option.RCVBUF +_SOCKET_OPTION_SEND_BUFFER_SIZE :: linux.Socket_Option.SNDBUF +_SOCKET_OPTION_RECEIVE_TIMEOUT :: linux.Socket_Option.RCVTIMEO +_SOCKET_OPTION_SEND_TIMEOUT :: linux.Socket_Option.SNDTIMEO -Shutdown_Manner :: enum c.int { - Receive = c.int(linux.Shutdown_How.RD), - Send = c.int(linux.Shutdown_How.WR), - Both = c.int(linux.Shutdown_How.RDWR), -} +_SOCKET_OPTION_TCP_NODELAY :: linux.Socket_TCP_Option.NODELAY + +_SOCKET_OPTION_USE_LOOPBACK :: -1 +_SOCKET_OPTION_REUSE_PORT :: -1 +_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE :: -1 +_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING :: -1 + +_SOCKET_OPTION_EXCLUSIVE_ADDR_USE :: -1 +_SOCKET_OPTION_CONDITIONAL_ACCEPT :: -1 +_SOCKET_OPTION_DONT_LINGER :: -1 + +_SHUTDOWN_MANNER_RECEIVE :: linux.Shutdown_How.RD +_SHUTDOWN_MANNER_SEND :: linux.Shutdown_How.WR +_SHUTDOWN_MANNER_BOTH :: linux.Shutdown_How.RDWR // Wrappers and unwrappers for system-native types @@ -218,11 +223,24 @@ _listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (socket: TCP_Socket, } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: linux.Sock_Addr_Any errno := linux.getsockname(_unwrap_os_socket(sock), &addr) if errno != .NONE { - err = _listen_error(errno) + err = _socket_info_error(errno) + return + } + + ep = _wrap_os_addr(addr) + return +} + +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + addr: linux.Sock_Addr_Any + errno := linux.getpeername(_unwrap_os_socket(sock), &addr) + if errno != .NONE { + err = _socket_info_error(errno) return } @@ -334,7 +352,7 @@ _set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := int_value: i32 timeval_value: linux.Time_Val errno: linux.Errno - switch option { + #partial switch option { case .Reuse_Address, .Keep_Alive, @@ -387,10 +405,14 @@ _set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := panic("set_option() value must be an integer here", loc) } errno = linux.setsockopt(os_sock, level, int(option), &int_value) + case: + return .Invalid_Socket } + if errno != .NONE { return _socket_option_error(errno) } + return nil } diff --git a/core/net/socket_others.odin b/core/net/socket_others.odin new file mode 100644 index 000000000..61cf7240e --- /dev/null +++ b/core/net/socket_others.odin @@ -0,0 +1,105 @@ +#+build !darwin +#+build !linux +#+build !freebsd +#+build !windows +#+build !netbsd +#+build !openbsd +#+private +package net + +_SOCKET_OPTION_BROADCAST :: -1 +_SOCKET_OPTION_REUSE_ADDRESS :: -1 +_SOCKET_OPTION_KEEP_ALIVE :: -1 +_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE :: -1 +_SOCKET_OPTION_LINGER :: -1 +_SOCKET_OPTION_RECEIVE_BUFFER_SIZE :: -1 +_SOCKET_OPTION_SEND_BUFFER_SIZE :: -1 +_SOCKET_OPTION_RECEIVE_TIMEOUT :: -1 +_SOCKET_OPTION_SEND_TIMEOUT :: -1 + +_SOCKET_OPTION_TCP_NODELAY :: -1 + +_SOCKET_OPTION_USE_LOOPBACK :: -1 +_SOCKET_OPTION_REUSE_PORT :: -1 +_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE :: -1 +_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING :: -1 + +_SOCKET_OPTION_EXCLUSIVE_ADDR_USE :: -1 +_SOCKET_OPTION_CONDITIONAL_ACCEPT :: -1 +_SOCKET_OPTION_DONT_LINGER :: -1 + +_SHUTDOWN_MANNER_RECEIVE :: -1 +_SHUTDOWN_MANNER_SEND :: -1 +_SHUTDOWN_MANNER_BOTH :: -1 + +_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := DEFAULT_TCP_OPTIONS) -> (sock: TCP_Socket, err: Network_Error) { + err = Create_Socket_Error.Network_Unreachable + return +} + +_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (sock: Any_Socket, err: Create_Socket_Error) { + err = .Network_Unreachable + return +} + +_bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Bind_Error) { + err = .Network_Unreachable + return +} + +_listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_Socket, err: Network_Error) { + err = Create_Socket_Error.Network_Unreachable + return +} + +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + err = .Network_Unreachable + return +} + +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + err = .Network_Unreachable + return +} + +_accept_tcp :: proc(sock: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { + err = .Network_Unreachable + return +} + +_close :: proc(skt: Any_Socket) { +} + +_recv_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_read: int, err: TCP_Recv_Error) { + err = .Network_Unreachable + return +} + +_recv_udp :: proc(skt: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endpoint: Endpoint, err: UDP_Recv_Error) { + err = .Network_Unreachable + return +} + +_send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: TCP_Send_Error) { + err = .Network_Unreachable + return +} + +_send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: int, err: UDP_Send_Error) { + err = .Network_Unreachable + return +} + +_shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Shutdown_Error) { + err = .Network_Unreachable + return +} + +_set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Socket_Option_Error { + return .Network_Unreachable +} + +_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Set_Blocking_Error) { + err = .Network_Unreachable + return +} diff --git a/core/net/socket_darwin.odin b/core/net/socket_posix.odin similarity index 86% rename from core/net/socket_darwin.odin rename to core/net/socket_posix.odin index e63f1844a..243b2e06f 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_posix.odin @@ -1,4 +1,4 @@ -#+build darwin +#+build darwin, netbsd, openbsd package net /* @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -20,28 +20,33 @@ package net Feoramund: FreeBSD platform code */ -import "core:c" import "core:sys/posix" import "core:time" -Socket_Option :: enum c.int { - Broadcast = c.int(posix.Sock_Option.BROADCAST), - Reuse_Address = c.int(posix.Sock_Option.REUSEADDR), - Keep_Alive = c.int(posix.Sock_Option.KEEPALIVE), - Out_Of_Bounds_Data_Inline = c.int(posix.Sock_Option.OOBINLINE), - TCP_Nodelay = c.int(posix.TCP_NODELAY), - Linger = c.int(posix.Sock_Option.LINGER), - Receive_Buffer_Size = c.int(posix.Sock_Option.RCVBUF), - Send_Buffer_Size = c.int(posix.Sock_Option.SNDBUF), - Receive_Timeout = c.int(posix.Sock_Option.RCVTIMEO), - Send_Timeout = c.int(posix.Sock_Option.SNDTIMEO), -} +_SOCKET_OPTION_BROADCAST :: posix.Sock_Option.BROADCAST +_SOCKET_OPTION_REUSE_ADDRESS :: posix.Sock_Option.REUSEADDR +_SOCKET_OPTION_KEEP_ALIVE :: posix.Sock_Option.KEEPALIVE +_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE :: posix.Sock_Option.OOBINLINE +_SOCKET_OPTION_LINGER :: posix.Sock_Option.LINGER +_SOCKET_OPTION_RECEIVE_BUFFER_SIZE :: posix.Sock_Option.RCVBUF +_SOCKET_OPTION_SEND_BUFFER_SIZE :: posix.Sock_Option.SNDBUF +_SOCKET_OPTION_RECEIVE_TIMEOUT :: posix.Sock_Option.RCVTIMEO +_SOCKET_OPTION_SEND_TIMEOUT :: posix.Sock_Option.SNDTIMEO -Shutdown_Manner :: enum c.int { - Receive = c.int(posix.SHUT_RD), - Send = c.int(posix.SHUT_WR), - Both = c.int(posix.SHUT_RDWR), -} +_SOCKET_OPTION_TCP_NODELAY :: posix.TCP_NODELAY + +_SOCKET_OPTION_USE_LOOPBACK :: -1 +_SOCKET_OPTION_REUSE_PORT :: -1 +_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE :: -1 +_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING :: -1 + +_SOCKET_OPTION_EXCLUSIVE_ADDR_USE :: -1 +_SOCKET_OPTION_CONDITIONAL_ACCEPT :: -1 +_SOCKET_OPTION_DONT_LINGER :: -1 + +_SHUTDOWN_MANNER_RECEIVE :: posix.SHUT_RD +_SHUTDOWN_MANNER_SEND :: posix.SHUT_WR +_SHUTDOWN_MANNER_BOTH :: posix.SHUT_RDWR @(private) _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Create_Socket_Error) { @@ -137,11 +142,24 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_ } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: posix.sockaddr_storage addr_len := posix.socklen_t(size_of(addr)) if posix.getsockname(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { - err = _listen_error() + err = _socket_info_error() + return + } + + ep = _sockaddr_to_endpoint(&addr) + return +} + +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + addr: posix.sockaddr_storage + addr_len := posix.socklen_t(size_of(addr)) + if posix.getpeername(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { + err = _socket_info_error() return } @@ -260,7 +278,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca ptr: rawptr len: posix.socklen_t - switch option { + #partial switch option { case .Broadcast, .Reuse_Address, @@ -314,6 +332,8 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca } ptr = &int_value len = size_of(int_value) + case: + return .Invalid_Option } skt := any_socket_to_socket(s) diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index 4576149de..4eea0ea65 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -11,7 +11,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -24,62 +24,33 @@ import "core:c" import win "core:sys/windows" import "core:time" -Socket_Option :: enum c.int { - // bool: Whether the address that this socket is bound to can be reused by other sockets. - // This allows you to bypass the cooldown period if a program dies while the socket is bound. - Reuse_Address = win.SO_REUSEADDR, +_SOCKET_OPTION_BROADCAST :: win.SO_BROADCAST +_SOCKET_OPTION_REUSE_ADDRESS :: win.SO_REUSEADDR +_SOCKET_OPTION_KEEP_ALIVE :: win.SO_KEEPALIVE +_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE :: win.SO_OOBINLINE +_SOCKET_OPTION_LINGER :: win.SO_LINGER +_SOCKET_OPTION_RECEIVE_BUFFER_SIZE :: win.SO_RCVBUF +_SOCKET_OPTION_SEND_BUFFER_SIZE :: win.SO_SNDBUF +_SOCKET_OPTION_RECEIVE_TIMEOUT :: win.SO_RCVTIMEO +_SOCKET_OPTION_SEND_TIMEOUT :: win.SO_SNDTIMEO - // bool: Whether other programs will be inhibited from binding the same endpoint as this socket. - Exclusive_Addr_Use = win.SO_EXCLUSIVEADDRUSE, +_SOCKET_OPTION_TCP_NODELAY :: win.TCP_NODELAY - // bool: When true, keepalive packets will be automatically be sent for this connection. TODO: verify this understanding - Keep_Alive = win.SO_KEEPALIVE, +_SOCKET_OPTION_USE_LOOPBACK :: -1 +_SOCKET_OPTION_REUSE_PORT :: -1 +_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE :: -1 +_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING :: -1 - // bool: When true, client connections will immediately be sent a TCP/IP RST response, rather than being accepted. - Conditional_Accept = win.SO_CONDITIONAL_ACCEPT, +_SOCKET_OPTION_EXCLUSIVE_ADDR_USE :: win.SO_EXCLUSIVEADDRUSE +_SOCKET_OPTION_CONDITIONAL_ACCEPT :: win.SO_CONDITIONAL_ACCEPT +_SOCKET_OPTION_DONT_LINGER :: win.SO_DONTLINGER - // bool: If true, when the socket is closed, but data is still waiting to be sent, discard that data. - Dont_Linger = win.SO_DONTLINGER, - - // bool: When true, 'out-of-band' data sent over the socket will be read by a normal net.recv() call, the same as normal 'in-band' data. - Out_Of_Bounds_Data_Inline = win.SO_OOBINLINE, - - // bool: When true, disables send-coalescing, therefore reducing latency. - TCP_Nodelay = win.TCP_NODELAY, - - // win.LINGER: Customizes how long (if at all) the socket will remain open when there - // is some remaining data waiting to be sent, and net.close() is called. - Linger = win.SO_LINGER, - - // win.DWORD: The size, in bytes, of the OS-managed receive-buffer for this socket. - Receive_Buffer_Size = win.SO_RCVBUF, - - // win.DWORD: The size, in bytes, of the OS-managed send-buffer for this socket. - Send_Buffer_Size = win.SO_SNDBUF, - - // win.DWORD: For blocking sockets, the time in milliseconds to wait for incoming data to be received, before giving up and returning .Timeout. - // For non-blocking sockets, ignored. - // Use a value of zero to potentially wait forever. - Receive_Timeout = win.SO_RCVTIMEO, - - // win.DWORD: For blocking sockets, the time in milliseconds to wait for outgoing data to be sent, before giving up and returning .Timeout. - // For non-blocking sockets, ignored. - // Use a value of zero to potentially wait forever. - Send_Timeout = win.SO_SNDTIMEO, - - // bool: Allow sending to, receiving from, and binding to, a broadcast address. - Broadcast = win.SO_BROADCAST, -} - - -Shutdown_Manner :: enum c.int { - Receive = win.SD_RECEIVE, - Send = win.SD_SEND, - Both = win.SD_BOTH, -} +_SHUTDOWN_MANNER_RECEIVE :: win.SD_RECEIVE +_SHUTDOWN_MANNER_SEND :: win.SD_SEND +_SHUTDOWN_MANNER_BOTH :: win.SD_BOTH @(init, private) -ensure_winsock_initialized :: proc() { +ensure_winsock_initialized :: proc "contextless" () { win.ensure_winsock_initialized() } @@ -177,11 +148,25 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: T } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: win.SOCKADDR_STORAGE_LH sockaddrlen := c.int(size_of(sockaddr)) if win.getsockname(win.SOCKET(any_socket_to_socket(sock)), &sockaddr, &sockaddrlen) == win.SOCKET_ERROR { - err = _listen_error() + err = _socket_info_error() + return + } + + ep = _sockaddr_to_endpoint(&sockaddr) + return +} + +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { + sockaddr: win.SOCKADDR_STORAGE_LH + sockaddrlen := c.int(size_of(sockaddr)) + res := win.getpeername(win.SOCKET(any_socket_to_socket(sock)), &sockaddr, &sockaddrlen) + if res < 0 { + err = _socket_info_error() return } @@ -308,7 +293,7 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca ptr: rawptr len: c.int - switch option { + #partial switch option { case .Reuse_Address, .Exclusive_Addr_Use, @@ -369,6 +354,8 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca } ptr = &int_value len = size_of(int_value) + case: + return .Invalid_Option } socket := any_socket_to_socket(s) diff --git a/core/net/url.odin b/core/net/url.odin index aadcf5e48..29028b16c 100644 --- a/core/net/url.odin +++ b/core/net/url.odin @@ -9,7 +9,7 @@ package net Copyright 2022 Colin Davidson Copyright 2022 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Tetralux: Initial implementation @@ -125,7 +125,7 @@ percent_encode :: proc(s: string, allocator := context.allocator) -> string { bytes, n := utf8.encode_rune(ch) for byte in bytes[:n] { buf: [2]u8 = --- - t := strconv.append_int(buf[:], i64(byte), 16) + t := strconv.write_int(buf[:], i64(byte), 16) strings.write_rune(&b, '%') strings.write_string(&b, t) } @@ -154,7 +154,7 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) - strings.write_string(&b, s[:i]) s = s[i:] - if len(s) == 0 { + if len(s) <= 1 { return // percent without anything after it } s = s[1:] diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 3b8998b31..22139d7f9 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -1,3 +1,4 @@ +// Abstract Syntax Tree for the `Odin` parser packages. package odin_ast import "core:odin/tokenizer" @@ -16,6 +17,11 @@ Proc_Inlining :: enum u32 { No_Inline = 2, } +Proc_Tailing :: enum u32 { + None = 0, + Must_Tail = 1, +} + Proc_Calling_Convention_Extra :: enum i32 { Foreign_Block_Default, } @@ -70,7 +76,7 @@ File :: struct { src: string, tags: [dynamic]tokenizer.Token, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil pkg_decl: ^Package_Decl, pkg_token: tokenizer.Token, @@ -137,26 +143,27 @@ Basic_Directive :: struct { Ellipsis :: struct { using node: Expr, tok: tokenizer.Token_Kind, - expr: ^Expr, + expr: ^Expr, // possibly nil } Proc_Lit :: struct { using node: Expr, - type: ^Proc_Type, - body: ^Stmt, - tags: Proc_Tags, - inlining: Proc_Inlining, - where_token: tokenizer.Token, + type: ^Proc_Type, + body: ^Stmt, // nil when it represents a foreign procedure + tags: Proc_Tags, + inlining: Proc_Inlining, + tailing: Proc_Tailing, + where_token: tokenizer.Token, where_clauses: []^Expr, } Comp_Lit :: struct { using node: Expr, - type: ^Expr, - open: tokenizer.Pos, + type: ^Expr, // nil when type is inferred + open: tokenizer.Pos, elems: []^Expr, close: tokenizer.Pos, - tag: ^Expr, + tag: ^Expr, // possibly nil } @@ -170,7 +177,7 @@ Tag_Expr :: struct { Unary_Expr :: struct { using node: Expr, op: tokenizer.Token, - expr: ^Expr, + expr: ^Expr, // nil in the case of `[?]T` or `x.?` } Binary_Expr :: struct { @@ -224,9 +231,9 @@ Slice_Expr :: struct { using node: Expr, expr: ^Expr, open: tokenizer.Pos, - low: ^Expr, + low: ^Expr, // possibly nil interval: tokenizer.Token, - high: ^Expr, + high: ^Expr, // possibly nil close: tokenizer.Pos, } @@ -242,6 +249,7 @@ Matrix_Index_Expr :: struct { Call_Expr :: struct { using node: Expr, inlining: Proc_Inlining, + tailing: Proc_Tailing, expr: ^Expr, open: tokenizer.Pos, args: []^Expr, @@ -291,7 +299,7 @@ Or_Branch_Expr :: struct { using node: Expr, expr: ^Expr, token: tokenizer.Token, - label: ^Expr, + label: ^Expr, // possibly nil when not used } Type_Assertion :: struct { @@ -384,13 +392,13 @@ Block_Stmt :: struct { If_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil if_pos: tokenizer.Pos, - init: ^Stmt, + init: ^Stmt, // possibly nil cond: ^Expr, body: ^Stmt, else_pos: tokenizer.Pos, - else_stmt: ^Stmt, + else_stmt: ^Stmt, // possibly nil } When_Stmt :: struct { @@ -398,7 +406,7 @@ When_Stmt :: struct { when_pos: tokenizer.Pos, cond: ^Expr, body: ^Stmt, - else_stmt: ^Stmt, + else_stmt: ^Stmt, // possibly nil } Return_Stmt :: struct { @@ -413,17 +421,18 @@ Defer_Stmt :: struct { For_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil for_pos: tokenizer.Pos, - init: ^Stmt, - cond: ^Expr, - post: ^Stmt, + init: ^Stmt, // possibly nil + cond: ^Expr, // possibly nil + post: ^Stmt, // possibly nil body: ^Stmt, } Range_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil + init: ^Stmt, for_pos: tokenizer.Pos, vals: []^Expr, in_pos: tokenizer.Pos, @@ -436,12 +445,12 @@ Inline_Range_Stmt :: Unroll_Range_Stmt Unroll_Range_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil unroll_pos: tokenizer.Pos, args: []^Expr, for_pos: tokenizer.Pos, val0: ^Expr, - val1: ^Expr, + val1: ^Expr, // possibly nil in_pos: tokenizer.Pos, expr: ^Expr, body: ^Stmt, @@ -460,9 +469,9 @@ Case_Clause :: struct { Switch_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil switch_pos: tokenizer.Pos, - init: ^Stmt, + init: ^Stmt, // possibly nil cond: ^Expr, body: ^Stmt, partial: bool, @@ -470,7 +479,7 @@ Switch_Stmt :: struct { Type_Switch_Stmt :: struct { using node: Stmt, - label: ^Expr, + label: ^Expr, // possibly nil switch_pos: tokenizer.Pos, tag: ^Stmt, expr: ^Expr, @@ -481,7 +490,7 @@ Type_Switch_Stmt :: struct { Branch_Stmt :: struct { using node: Stmt, tok: tokenizer.Token, - label: ^Ident, + label: ^Ident, // possibly nil } Using_Stmt :: struct { @@ -498,55 +507,55 @@ Bad_Decl :: struct { Value_Decl :: struct { using node: Decl, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily names: []^Expr, - type: ^Expr, + type: ^Expr, // possibly nil values: []^Expr, - comment: ^Comment_Group, + comment: ^Comment_Group, // possibly nil is_using: bool, is_mutable: bool, } Package_Decl :: struct { using node: Decl, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil token: tokenizer.Token, name: string, - comment: ^Comment_Group, + comment: ^Comment_Group, // possibly nil } Import_Decl :: struct { using node: Decl, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily is_using: bool, import_tok: tokenizer.Token, name: tokenizer.Token, relpath: tokenizer.Token, fullpath: string, - comment: ^Comment_Group, + comment: ^Comment_Group, // possibly nil } Foreign_Block_Decl :: struct { using node: Decl, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily tok: tokenizer.Token, - foreign_library: ^Expr, - body: ^Stmt, + foreign_library: ^Expr, // possibly nil + body: ^Stmt, // possibly nil } Foreign_Import_Decl :: struct { using node: Decl, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily foreign_tok: tokenizer.Token, import_tok: tokenizer.Token, - name: ^Ident, + name: ^Ident, // possibly nil collection_name: string, fullpaths: []^Expr, - comment: ^Comment_Group, + comment: ^Comment_Group, // possibly nil } @@ -689,13 +698,13 @@ Attribute :: struct { Field :: struct { using node: Node, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil names: []^Expr, // Could be polymorphic type: ^Expr, - default_value: ^Expr, + default_value: ^Expr, // possibly nil tag: tokenizer.Token, flags: Field_Flags, - comment: ^Comment_Group, + comment: ^Comment_Group, // possibly nil } Field_List :: struct { @@ -710,7 +719,7 @@ Field_List :: struct { Typeid_Type :: struct { using node: Expr, tok: tokenizer.Token_Kind, - specialization: ^Expr, + specialization: ^Expr, // possibly nil } Helper_Type :: struct { @@ -729,7 +738,7 @@ Poly_Type :: struct { using node: Expr, dollar: tokenizer.Pos, type: ^Ident, - specialization: ^Expr, + specialization: ^Expr, // possibly nil } Proc_Type :: struct { @@ -746,7 +755,7 @@ Proc_Type :: struct { Pointer_Type :: struct { using node: Expr, - tag: ^Expr, + tag: ^Expr, // possibly nil pointer: tokenizer.Pos, elem: ^Expr, } @@ -762,7 +771,7 @@ Multi_Pointer_Type :: struct { Array_Type :: struct { using node: Expr, open: tokenizer.Pos, - tag: ^Expr, + tag: ^Expr, // possibly nil len: ^Expr, // Unary_Expr node for [?]T array types, nil for slice types close: tokenizer.Pos, elem: ^Expr, @@ -770,25 +779,37 @@ Array_Type :: struct { Dynamic_Array_Type :: struct { using node: Expr, - tag: ^Expr, + tag: ^Expr, // possibly nil open: tokenizer.Pos, dynamic_pos: tokenizer.Pos, close: tokenizer.Pos, elem: ^Expr, } +Fixed_Capacity_Dynamic_Array_Type :: struct { + using node: Expr, + tag: ^Expr, // possibly nil + open: tokenizer.Pos, + dynamic_pos: tokenizer.Pos, + capacity: ^Expr, + close: tokenizer.Pos, + elem: ^Expr, +} + Struct_Type :: struct { using node: Expr, tok_pos: tokenizer.Pos, - poly_params: ^Field_List, - align: ^Expr, - min_field_align: ^Expr, - max_field_align: ^Expr, + poly_params: ^Field_List, // possibly nil + align: ^Expr, // possibly nil + min_field_align: ^Expr, // possibly nil + max_field_align: ^Expr, // possibly nil where_token: tokenizer.Token, where_clauses: []^Expr, is_packed: bool, is_raw_union: bool, is_no_copy: bool, + is_all_or_none: bool, + is_simple: bool, fields: ^Field_List, name_count: int, } @@ -803,8 +824,8 @@ Union_Type_Kind :: enum u8 { Union_Type :: struct { using node: Expr, tok_pos: tokenizer.Pos, - poly_params: ^Field_List, - align: ^Expr, + poly_params: ^Field_List, // possibly nil + align: ^Expr, // possibly nil kind: Union_Type_Kind, where_token: tokenizer.Token, where_clauses: []^Expr, @@ -814,7 +835,7 @@ Union_Type :: struct { Enum_Type :: struct { using node: Expr, tok_pos: tokenizer.Pos, - base_type: ^Expr, + base_type: ^Expr, // possibly nil open: tokenizer.Pos, fields: []^Expr, close: tokenizer.Pos, @@ -827,7 +848,7 @@ Bit_Set_Type :: struct { tok_pos: tokenizer.Pos, open: tokenizer.Pos, elem: ^Expr, - underlying: ^Expr, + underlying: ^Expr, // possibly nil close: tokenizer.Pos, } @@ -864,12 +885,12 @@ Bit_Field_Type :: struct { Bit_Field_Field :: struct { using node: Node, - docs: ^Comment_Group, + docs: ^Comment_Group, // possibly nil name: ^Expr, type: ^Expr, bit_size: ^Expr, tag: tokenizer.Token, - comments: ^Comment_Group, + comments: ^Comment_Group, // possibly nil } Any_Node :: union { @@ -920,6 +941,7 @@ Any_Node :: union { ^Multi_Pointer_Type, ^Array_Type, ^Dynamic_Array_Type, + ^Fixed_Capacity_Dynamic_Array_Type, ^Struct_Type, ^Union_Type, ^Enum_Type, @@ -1006,6 +1028,7 @@ Any_Expr :: union { ^Multi_Pointer_Type, ^Array_Type, ^Dynamic_Array_Type, + ^Fixed_Capacity_Dynamic_Array_Type, ^Struct_Type, ^Union_Type, ^Enum_Type, diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index b7501e6ca..163485840 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -239,6 +239,7 @@ clone_node :: proc(node: ^Node) -> ^Node { r.body = clone(r.body) case ^Range_Stmt: r.label = clone(r.label) + r.init = clone(r.init) r.vals = clone(r.vals) r.expr = clone(r.expr) r.body = clone(r.body) @@ -310,10 +311,16 @@ clone_node :: proc(node: ^Node) -> ^Node { case ^Multi_Pointer_Type: r.elem = clone(r.elem) case ^Array_Type: + r.tag = clone(r.tag) r.len = clone(r.len) r.elem = clone(r.elem) case ^Dynamic_Array_Type: + r.tag = clone(r.tag) r.elem = clone(r.elem) + case ^Fixed_Capacity_Dynamic_Array_Type: + r.tag = clone(r.tag) + r.capacity = clone(r.capacity) + r.elem = clone(r.elem) case ^Struct_Type: r.poly_params = auto_cast clone(r.poly_params) r.align = clone(r.align) diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin index cba040875..d3824c213 100644 --- a/core/odin/ast/walk.odin +++ b/core/odin/ast/walk.odin @@ -222,6 +222,9 @@ walk :: proc(v: ^Visitor, node: ^Node) { if n.label != nil { walk(v, n.label) } + if n.init != nil { + walk(v, n.init) + } for val in n.vals { if val != nil { walk(v, val) @@ -377,6 +380,12 @@ walk :: proc(v: ^Visitor, node: ^Node) { walk(v, n.tag) } walk(v, n.elem) + case ^Fixed_Capacity_Dynamic_Array_Type: + if n.tag != nil { + walk(v, n.tag) + } + walk(v, n.capacity) + walk(v, n.elem) case ^Struct_Type: if n.poly_params != nil { walk(v, n.poly_params) @@ -402,9 +411,7 @@ walk :: proc(v: ^Visitor, node: ^Node) { walk_expr_list(v, n.fields) case ^Bit_Set_Type: walk(v, n.elem) - if n.underlying != nil { - walk(v, n.underlying) - } + walk(v, n.underlying) case ^Map_Type: walk(v, n.key) walk(v, n.value) diff --git a/core/odin/doc-format/doc_format.odin b/core/odin/doc-format/doc_format.odin index e6804c981..28552b346 100644 --- a/core/odin/doc-format/doc_format.odin +++ b/core/odin/doc-format/doc_format.odin @@ -1,3 +1,4 @@ +// The `.odin-doc` file format, as used by these package docs at `pkg.odin-lang.org`. package odin_doc_format import "core:mem" @@ -11,7 +12,7 @@ String :: distinct Array(byte) Version_Type_Major :: 0 Version_Type_Minor :: 3 -Version_Type_Patch :: 1 +Version_Type_Patch :: 2 Version_Type :: struct { major, minor, patch: u8, @@ -167,32 +168,33 @@ Attribute :: struct { } Type_Kind :: enum u32le { - Invalid = 0, - Basic = 1, - Named = 2, - Generic = 3, - Pointer = 4, - Array = 5, - Enumerated_Array = 6, - Slice = 7, - Dynamic_Array = 8, - Map = 9, - Struct = 10, - Union = 11, - Enum = 12, - Parameters = 13, - Proc = 14, - Bit_Set = 15, - Simd_Vector = 16, - SOA_Struct_Fixed = 17, - SOA_Struct_Slice = 18, - SOA_Struct_Dynamic = 19, - Relative_Pointer = 20, - Relative_Multi_Pointer = 21, - Multi_Pointer = 22, - Matrix = 23, - Soa_Pointer = 24, - Bit_Field = 25, + Invalid = 0, + Basic = 1, + Named = 2, + Generic = 3, + Pointer = 4, + Array = 5, + Enumerated_Array = 6, + Slice = 7, + Dynamic_Array = 8, + Map = 9, + Struct = 10, + Union = 11, + Enum = 12, + Parameters = 13, + Proc = 14, + Bit_Set = 15, + Simd_Vector = 16, + SOA_Struct_Fixed = 17, + SOA_Struct_Slice = 18, + SOA_Struct_Dynamic = 19, + Relative_Pointer = 20, + Relative_Multi_Pointer = 21, + Multi_Pointer = 22, + Matrix = 23, + Soa_Pointer = 24, + Bit_Field = 25, + Fixed_Capacity_Dynamic_Array = 26, } Type_Elems_Cap :: 4 @@ -218,12 +220,14 @@ Type :: struct { custom_align: String, // Used by: - // .Array - 1 count: 0=len - // .Enumerated_Array - 1 count: 0=len - // .SOA_Struct_Fixed - 1 count: 0=len - // .Bit_Set - 2 count: 0=lower, 1=upper - // .Simd_Vector - 1 count: 0=len - // .Matrix - 2 count: 0=row_count, 1=column_count + // .Array - 1 count: 0=len + // .Enumerated_Array - 1 count: 0=len + // .SOA_Struct_Fixed - 1 count: 0=len + // .Bit_Set - 2 count: 0=lower, 1=upper + // .Simd_Vector - 1 count: 0=len + // .Matrix - 2 count: 0=row_count, 1=column_count + // .Struct - <=2 count: 0=min_field_align, 1=max_field_align + // .Fixed_Capacity_Dynamic_Array - 1 count: 0=cap elem_count_len: u32le, elem_counts: [Type_Elems_Cap]i64le, @@ -232,27 +236,28 @@ Type :: struct { calling_convention: String, // Used by: - // .Named - 1 type: 0=base type - // .Generic - <1 type: 0=specialization - // .Pointer - 1 type: 0=element - // .Array - 1 type: 0=element - // .Enumerated_Array - 2 types: 0=index and 1=element - // .Slice - 1 type: 0=element - // .Dynamic_Array - 1 type: 0=element - // .Map - 2 types: 0=key, 1=value - // .SOA_Struct_Fixed - 1 type: underlying SOA struct element - // .SOA_Struct_Slice - 1 type: underlying SOA struct element - // .SOA_Struct_Dynamic - 1 type: underlying SOA struct element - // .Union - 0+ types: variants - // .Enum - <1 type: 0=base type - // .Proc - 2 types: 0=parameters, 1=results - // .Bit_Set - <=2 types: 0=element type, 1=underlying type (Underlying_Type flag will be set) - // .Simd_Vector - 1 type: 0=element - // .Relative_Pointer - 2 types: 0=pointer type, 1=base integer - // .Multi_Pointer - 1 type: 0=element - // .Matrix - 1 type: 0=element - // .Soa_Pointer - 1 type: 0=element - // .Bit_Field - 1 type: 0=backing type + // .Named - 1 type: 0=base type + // .Generic - <1 type: 0=specialization + // .Pointer - 1 type: 0=element + // .Array - 1 type: 0=element (and 1=generic index (if exists)) + // .Enumerated_Array - 2 types: 0=index and 1=element + // .Slice - 1 type: 0=element + // .Dynamic_Array - 1 type: 0=element + // .Map - 2 types: 0=key, 1=value + // .SOA_Struct_Fixed - 1 type: underlying SOA struct element + // .SOA_Struct_Slice - 1 type: underlying SOA struct element + // .SOA_Struct_Dynamic - 1 type: underlying SOA struct element + // .Union - 0+ types: variants + // .Enum - <1 type: 0=base type + // .Proc - 2 types: 0=parameters, 1=results + // .Bit_Set - <=2 types: 0=element type, 1=underlying type (Underlying_Type flag will be set) + // .Simd_Vector - 1 type: 0=element + // .Relative_Pointer - 2 types: 0=pointer type, 1=base integer + // .Multi_Pointer - 1 type: 0=element + // .Matrix - 1 type: 0=element + // .Soa_Pointer - 1 type: 0=element + // .Bit_Field - 1 type: 0=backing type + // .Fixed_Capacity_Dynamic_Array - 1 type: 0=element (and 1=generic index (if exists)) types: Array(Type_Index), // Used by: @@ -280,6 +285,7 @@ Type_Flag_Struct :: enum u32le { Polymorphic = 0, Packed = 1, Raw_Union = 2, + All_Or_None = 3, } Type_Flags_Union :: distinct bit_set[Type_Flag_Union; u32le] diff --git a/core/odin/doc.odin b/core/odin/doc.odin new file mode 100644 index 000000000..40aeaea7f --- /dev/null +++ b/core/odin/doc.odin @@ -0,0 +1,2 @@ +// A lexer and parser for the `Odin` language for the purposes of writing tooling. +package odin \ No newline at end of file diff --git a/core/odin/parser/file_tags.odin b/core/odin/parser/file_tags.odin index 24aea3b9e..669fa5263 100644 --- a/core/odin/parser/file_tags.odin +++ b/core/odin/parser/file_tags.odin @@ -65,12 +65,6 @@ get_build_arch_from_string :: proc(str: string) -> runtime.Odin_Arch_Type { @require_results parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags: File_Tags) { - context.allocator = allocator - - if file.docs == nil && file.tags == nil { - return - } - next_char :: proc(src: string, i: ^int) -> (ch: u8) { if i^ < len(src) { ch = src[i^] @@ -102,15 +96,6 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags } } - build_kinds: [dynamic]Build_Kind - defer shrink(&build_kinds) - - build_project_name_strings: [dynamic]string - defer shrink(&build_project_name_strings) - - build_project_names: [dynamic][]string - defer shrink(&build_project_names) - parse_tag :: proc(text: string, tags: ^File_Tags, build_kinds: ^[dynamic]Build_Kind, build_project_name_strings: ^[dynamic]string, build_project_names: ^[dynamic][]string) { @@ -143,7 +128,7 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags for { skip_whitespace(text, &i) name_start := i - + switch next_char(text, &i) { case 0, '\r', '\n': i -= 1 @@ -155,7 +140,7 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags case: i -= 1 } - + scan_value(text, &i) append(build_project_name_strings, text[name_start:i]) } @@ -220,6 +205,18 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags } } + context.allocator = allocator + + if file.docs == nil && file.tags == nil { + return + } + + build_kinds: [dynamic]Build_Kind + build_project_names: [dynamic][]string + + build_project_name_strings: [dynamic]string + + if file.docs != nil { for comment in file.docs.list { if len(comment.text) < 3 || comment.text[:2] != "//" { @@ -241,6 +238,10 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags parse_tag(text, &tags, &build_kinds, &build_project_name_strings, &build_project_names) } + shrink(&build_kinds) + shrink(&build_project_names) + delete(build_project_name_strings) + tags.build = build_kinds[:] tags.build_project_name = build_project_names[:] diff --git a/core/odin/parser/parse_files.odin b/core/odin/parser/parse_files.odin index d4e532ec7..2ea47ca89 100644 --- a/core/odin/parser/parse_files.odin +++ b/core/odin/parser/parse_files.odin @@ -11,8 +11,8 @@ import "core:strings" collect_package :: proc(path: string) -> (pkg: ^ast.Package, success: bool) { NO_POS :: tokenizer.Pos{} - pkg_path, pkg_path_ok := filepath.abs(path) - if !pkg_path_ok { + pkg_path, pkg_path_err := os.get_absolute_path(path, context.allocator) + if pkg_path_err != nil { return } @@ -28,14 +28,13 @@ collect_package :: proc(path: string) -> (pkg: ^ast.Package, success: bool) { pkg.fullpath = pkg_path for match in matches { - src: []byte - fullpath, ok := filepath.abs(match) - if !ok { + fullpath, fullpath_err := os.get_absolute_path(match, context.allocator) + if fullpath_err != nil { return } - src, ok = os.read_entire_file(fullpath) - if !ok { + src, src_err := os.read_entire_file(fullpath, context.allocator) + if src_err != nil { delete(fullpath) return } diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 7f1f4ca87..5e681728d 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1,3 +1,4 @@ +// The `Odin` file parser to be used in tooling. package odin_parser import "core:odin/ast" @@ -98,18 +99,14 @@ end_pos :: proc(tok: tokenizer.Token) -> tokenizer.Pos { pos := tok.pos pos.offset += len(tok.text) - if tok.kind == .Comment { - if tok.text[:2] != "/*" { - pos.column += len(tok.text) - } else { - for i := 0; i < len(tok.text); i += 1 { - c := tok.text[i] - if c == '\n' { - pos.line += 1 - pos.column = 1 - } else { - pos.column += 1 - } + if (tok.kind == .Comment && tok.text[:2] == "/*") || (tok.kind == .String && tok.text[:1] == "`") { + for i := 0; i < len(tok.text); i += 1 { + c := tok.text[i] + if c == '\n' { + pos.line += 1 + pos.column = 1 + } else { + pos.column += 1 } } } else { @@ -348,27 +345,30 @@ consume_comment_group :: proc(p: ^Parser, n: int) -> (comments: ^ast.Comment_Gro } consume_comment_groups :: proc(p: ^Parser, prev: tokenizer.Token) { - if p.curr_tok.kind == .Comment { - comment: ^ast.Comment_Group - end_line := 0 - - if p.curr_tok.pos.line == prev.pos.line { - comment, end_line = consume_comment_group(p, 0) - if p.curr_tok.pos.line != end_line || p.curr_tok.kind == .EOF { - p.line_comment = comment - } - } - - end_line = -1 - for p.curr_tok.kind == .Comment { - comment, end_line = consume_comment_group(p, 1) - } - if end_line+1 >= p.curr_tok.pos.line || end_line < 0 { - p.lead_comment = comment - } - - assert(p.curr_tok.kind != .Comment) + if p.curr_tok.kind != .Comment { + return } + comment: ^ast.Comment_Group + end_line := 0 + + if p.curr_tok.pos.line == prev.pos.line { + comment, end_line = consume_comment_group(p, 0) + if p.curr_tok.pos.line != end_line || + p.curr_tok.pos.line == prev.pos.line+1 || + p.curr_tok.kind == .EOF { + p.line_comment = comment + } + } + + end_line = -1 + for p.curr_tok.kind == .Comment { + comment, end_line = consume_comment_group(p, 1) + } + if end_line+1 >= p.curr_tok.pos.line || end_line < 0 { + p.lead_comment = comment + } + + assert(p.curr_tok.kind != .Comment) } advance_token :: proc(p: ^Parser) -> tokenizer.Token { @@ -378,7 +378,14 @@ advance_token :: proc(p: ^Parser) -> tokenizer.Token { prev := p.prev_tok if next_token0(p) { - consume_comment_groups(p, prev) + #partial switch p.curr_tok.kind { + case .Comment: + consume_comment_groups(p, prev) + case .Semicolon: + if p.expr_level > 0 && p.curr_tok.text == "\n" { + advance_token(p) + } + } } return prev } @@ -881,7 +888,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { body: ^ast.Stmt is_range := false - if p.curr_tok.kind != .Open_Brace && p.curr_tok.kind != .Do { + general_conds: if p.curr_tok.kind != .Open_Brace && p.curr_tok.kind != .Do { prev_level := p.expr_level defer p.expr_level = prev_level p.expr_level = -1 @@ -898,7 +905,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { if allow_token(p, .Do) { body = convert_stmt_to_body(p, parse_stmt(p)) if tok.pos.line != body.pos.line { - error(p, body.pos, "the body of a 'do' must be on the same line as 'else'") + error(p, body.pos, "the body of a 'do' must be on the same line as 'for'") } } else { @@ -929,6 +936,18 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { error(p, p.curr_tok.pos, "Expected ';', followed by a condition expression and post statement, got %s", tokenizer.tokens[p.curr_tok.kind]) } else { if p.curr_tok.kind != .Semicolon { + if p.curr_tok.kind == .Ident { + next_token := peek_token(p) + if next_token.kind == .In || next_token.kind == .Comma { + cond = parse_simple_stmt(p, {.In}) + if as, ok := cond.derived_stmt.(^ast.Assign_Stmt); ok { + assert(as.op.kind == .In) + is_range = true + } + break general_conds + } + } + cond = parse_simple_stmt(p, nil) } @@ -967,6 +986,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt { range_stmt := ast.new(ast.Range_Stmt, tok.pos, body) range_stmt.for_pos = tok.pos + range_stmt.init = init range_stmt.vals = vals range_stmt.in_pos = assign_stmt.op.pos range_stmt.expr = rhs @@ -1377,7 +1397,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { .Pointer, .Asm, // Inline assembly // Unary Expressions - .Add, .Sub, .Xor, .Not, .And: + .Add, .Sub, .Xor, .Not, .And, .Increment, .Decrement: s := parse_simple_stmt(p, {Stmt_Allow_Flag.Label}) expect_semicolon(p, s) @@ -1528,8 +1548,8 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { es.expr = ce return es - case "force_inline", "force_no_inline": - expr := parse_inlining_operand(p, true, tag) + case "force_inline", "force_no_inline", "must_tail": + expr := parse_inlining_or_tailing_operand(p, true, tag) es := ast.new(ast.Expr_Stmt, expr.pos, expr) es.expr = expr return es @@ -1772,6 +1792,13 @@ is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag { advance_token(p) return .Using case .Hash: + if tok := peek_token(p); tok.kind == .Ident { + switch tok.text { + case "simd", "type", "row_major", "column_major", "sparse", "soa": + return .Invalid + } + } + tok: tokenizer.Token advance_token(p) tok = p.curr_tok @@ -2186,6 +2213,57 @@ parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) { return } +is_expr_generic :: proc(expr : ^ast.Expr) -> bool { + is_generic := false + if expr != nil { + #partial switch e in expr.derived_expr { + case ^ast.Typeid_Type: + is_generic = e.specialization != nil + case ^ast.Poly_Type: + is_generic = true + case ^ast.Proc_Type: + is_generic = e.generic + case ^ast.Pointer_Type: + is_generic = is_expr_generic(e.elem) + case ^ast.Multi_Pointer_Type: + is_generic = is_expr_generic(e.elem) + case ^ast.Array_Type: + is_generic = is_expr_generic(e.len) || is_expr_generic(e.elem) + case ^ast.Dynamic_Array_Type: + is_generic = is_expr_generic(e.elem) + case ^ast.Fixed_Capacity_Dynamic_Array_Type: + is_generic = is_expr_generic(e.capacity) || is_expr_generic(e.elem) + case ^ast.Bit_Set_Type: + is_generic = is_expr_generic(e.elem) + case ^ast.Map_Type: + is_generic = is_expr_generic(e.key) || is_expr_generic(e.value) + case ^ast.Matrix_Type: + is_generic = is_expr_generic(e.row_count) || is_expr_generic(e.column_count) || is_expr_generic(e.elem) + } + } + return is_generic +} + +is_field_list_generic :: proc(field_list : ^ast.Field_List, check_names : bool) -> bool { + is_generic := false + loop: for param in field_list.list { + if is_expr_generic(param.type) { + is_generic = true + break loop + } + if !check_names || param.type == nil { + continue + } + for name in param.names { + if _, ok := name.derived.(^ast.Poly_Type); ok { + is_generic = true + break loop + } + } + } + return is_generic +} + parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type { cc: ast.Proc_Calling_Convention if p.curr_tok.kind == .String { @@ -2207,21 +2285,9 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type { expect_closing_parentheses_of_field_list(p) results, diverging := parse_results(p) - is_generic := false - - loop: for param in params.list { - if param.type != nil { - if _, ok := param.type.derived.(^ast.Poly_Type); ok { - is_generic = true - break loop - } - for name in param.names { - if _, ok := name.derived.(^ast.Poly_Type); ok { - is_generic = true - break loop - } - } - } + is_generic := is_field_list_generic(params, true) + if !is_generic && results != nil { + is_generic = is_field_list_generic(results, false) } end := end_pos(p.prev_tok) @@ -2235,10 +2301,11 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type { return pt } -parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ast.Expr { +parse_inlining_or_tailing_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ast.Expr { expr := parse_unary_expr(p, lhs) pi := ast.Proc_Inlining.None + pt := ast.Proc_Tailing.None #partial switch tok.kind { case .Inline: pi = .Inline @@ -2250,6 +2317,8 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ pi = .Inline case "force_no_inline": pi = .No_Inline + case "must_tail": + pt = .Must_Tail } } @@ -2259,13 +2328,19 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^ if e.inlining != .None && e.inlining != pi { error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal") } + if pt != .None { + error(p, expr.pos, "'#must_tail' can only be applied to a procedure call, not the procedure literal") + } + e.inlining = pi + e.tailing = pt return expr case ^ast.Call_Expr: if e.inlining != .None && e.inlining != pi { error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure call") } e.inlining = pi + e.tailing = pt return expr } } @@ -2305,9 +2380,10 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Open_Paren: open := expect_token(p, .Open_Paren) - p.expr_level += 1 + prev_expr_level := p.expr_level + p.expr_level = max(p.expr_level, 0) + 1 expr := parse_expr(p, false) - p.expr_level -= 1 + p.expr_level = prev_expr_level close := expect_token(p, .Close_Paren) pe := ast.new(ast.Paren_Expr, open.pos, end_pos(close)) @@ -2367,6 +2443,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case ^ast.Array_Type: t.tag = bd case ^ast.Dynamic_Array_Type: t.tag = bd case ^ast.Pointer_Type: t.tag = bd + case ^ast.Fixed_Capacity_Dynamic_Array_Type: t.tag = bd case: error(p, original_type.pos, "expected an array or pointer type after #%s", name.text) } @@ -2450,7 +2527,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { return rt case "force_inline", "force_no_inline": - return parse_inlining_operand(p, lhs, name) + return parse_inlining_or_tailing_operand(p, lhs, name) case: expr := parse_expr(p, lhs) end := expr.pos if expr != nil else end_pos(tok) @@ -2463,7 +2540,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Inline, .No_Inline: tok := advance_token(p) - return parse_inlining_operand(p, lhs, tok) + return parse_inlining_or_tailing_operand(p, lhs, tok) case .Proc: tok := expect_token(p, .Proc) @@ -2476,12 +2553,23 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { elem := parse_expr(p, false) + + if p.curr_tok.kind == .Where { + tok_where := expect_token(p, .Where) + cond := parse_expr(p, false) + + be := ast.new(ast.Binary_Expr, elem.pos, end_pos(p.prev_tok)) + be.left = elem + be.op = tok_where + be.right = cond + elem = be + } append(&args, elem) allow_token(p, .Comma) or_break } - close := expect_token(p, .Close_Brace) + close := expect_closing_brace_of_field_list(p) if len(args) == 0 { error(p, tok.pos, "expected at least 1 argument in procedure group") @@ -2604,6 +2692,20 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { return t case .Dynamic: tok := expect_token(p, .Dynamic) + if allow_token(p, .Semicolon) { + capacity := parse_expr(p, false) + close := expect_token(p, .Close_Bracket) + elem := parse_type(p) + + da := ast.new(ast.Fixed_Capacity_Dynamic_Array_Type, open.pos, elem) + da.open = open.pos + da.dynamic_pos = tok.pos + da.capacity = capacity + da.close = close.pos + da.elem = elem + return da + } + close := expect_token(p, .Close_Bracket) elem := parse_type(p) da := ast.new(ast.Dynamic_Array_Type, open.pos, elem) @@ -2653,11 +2755,13 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { align: ^ast.Expr min_field_align: ^ast.Expr max_field_align: ^ast.Expr - is_packed: bool - is_raw_union: bool - is_no_copy: bool - fields: ^ast.Field_List - name_count: int + is_packed: bool + is_raw_union: bool + is_no_copy: bool + is_all_or_none: bool + is_simple: bool + fields: ^ast.Field_List + name_count: int if allow_token(p, .Open_Paren) { param_count: int @@ -2679,6 +2783,16 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) } is_packed = true + case "all_or_none": + if is_all_or_none { + error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) + } + is_all_or_none = true + case "simple": + if is_simple { + error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) + } + is_simple = true case "align": if align != nil { error(p, tag.pos, "duplicate struct tag '#%s'", tag.text) @@ -2716,9 +2830,9 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { } p.expr_level = prev_level - if is_raw_union && is_packed { - is_packed = false - error(p, tok.pos, "'#raw_union' cannot also be '#packed") + if is_raw_union && is_all_or_none { + is_all_or_none = false + error(p, tok.pos, "'#raw_union' cannot also be '#all_or_none") } where_token: tokenizer.Token @@ -2740,17 +2854,19 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { close := expect_closing_brace_of_field_list(p) st := ast.new(ast.Struct_Type, tok.pos, end_pos(close)) - st.poly_params = poly_params - st.align = align - st.min_field_align = min_field_align - st.max_field_align = max_field_align - st.is_packed = is_packed - st.is_raw_union = is_raw_union - st.is_no_copy = is_no_copy - st.fields = fields - st.name_count = name_count - st.where_token = where_token - st.where_clauses = where_clauses + st.poly_params = poly_params + st.align = align + st.min_field_align = min_field_align + st.max_field_align = max_field_align + st.is_packed = is_packed + st.is_raw_union = is_raw_union + st.is_no_copy = is_no_copy + st.is_all_or_none = is_all_or_none + st.is_simple = is_simple + st.fields = fields + st.name_count = name_count + st.where_token = where_token + st.where_clauses = where_clauses return st case .Union: @@ -2922,6 +3038,8 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { fields: [dynamic]^ast.Bit_Field_Field for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF { + docs := p.lead_comment + name := parse_ident(p) expect_token(p, .Colon) type := parse_type(p) @@ -2932,6 +3050,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { if p.curr_tok.kind == .String { tag = expect_token(p, .String) } + ok := allow_token(p, .Comma) field := ast.new(ast.Bit_Field_Field, name.pos, bit_size) @@ -2939,10 +3058,14 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { field.type = type field.bit_size = bit_size field.tag = tag + field.docs = docs + field.comments = p.line_comment append(&fields, field) - allow_token(p, .Comma) or_break + if !ok { + break + } } close := expect_closing_brace_of_field_list(p) @@ -3059,6 +3182,7 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool { ^ast.Union_Type, ^ast.Enum_Type, ^ast.Dynamic_Array_Type, + ^ast.Fixed_Capacity_Dynamic_Array_Type, ^ast.Map_Type, ^ast.Bit_Set_Type, ^ast.Matrix_Type, @@ -3070,9 +3194,6 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool { } parse_value :: proc(p: ^Parser) -> ^ast.Expr { - if p.curr_tok.kind == .Open_Brace { - return parse_literal_value(p, nil) - } prev_allow_range := p.allow_range defer p.allow_range = prev_allow_range p.allow_range = true @@ -3107,11 +3228,12 @@ parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr { parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit { elems: []^ast.Expr open := expect_token(p, .Open_Brace) - p.expr_level += 1 + prev_expr_level := p.expr_level + p.expr_level = 0 if p.curr_tok.kind != .Close_Brace { elems = parse_elem_list(p) } - p.expr_level -= 1 + p.expr_level = prev_expr_level skip_possible_newline(p) close := expect_closing_brace_of_field_list(p) @@ -3130,7 +3252,8 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { ellipsis: tokenizer.Token - p.expr_level += 1 + prev_expr_level := p.expr_level + p.expr_level = 0 open := expect_token(p, .Open_Paren) seen_ellipsis := false @@ -3177,8 +3300,8 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { allow_token(p, .Comma) or_break } + p.expr_level = prev_expr_level close := expect_closing_token_of_field_list(p, .Close_Paren, "argument list") - p.expr_level -= 1 ce := ast.new(ast.Call_Expr, operand.pos, end_pos(close)) ce.expr = operand @@ -3198,6 +3321,17 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr { return ce } +empty_selector_expr :: proc(tok: tokenizer.Token, operand: ^ast.Expr) -> ^ast.Selector_Expr { + field := ast.new(ast.Ident, tok.pos, end_pos(tok)) + field.name = "" + + sel := ast.new(ast.Selector_Expr, operand.pos, field) + sel.expr = operand + sel.op = tok + sel.field = field + + return sel +} parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^ast.Expr) { operand = value @@ -3253,8 +3387,8 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a } } - close := expect_token(p, .Close_Bracket) p.expr_level -= 1 + close := expect_token(p, .Close_Bracket) if is_slice_op { if interval.kind == .Comma { @@ -3331,8 +3465,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a case: error(p, p.curr_tok.pos, "expected a selector") - advance_token(p) - operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)) + operand = empty_selector_expr(tok, operand) } case .Arrow_Right: @@ -3349,8 +3482,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a operand = sel case: error(p, p.curr_tok.pos, "expected a selector") - advance_token(p) - operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok)) + operand = empty_selector_expr(tok, operand) } case .Pointer: @@ -3440,7 +3572,8 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { case .Add, .Sub, .Not, .Xor, - .And: + .And, + .Mul_Mul: op := advance_token(p) expr := parse_unary_expr(p, lhs) @@ -3526,6 +3659,7 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr { case .When: x := expr cond := parse_expr(p, lhs) + skip_possible_newline(p) else_tok := expect_token(p, .Else) y := parse_expr(p, lhs) te := ast.new(ast.Ternary_When_Expr, expr.pos, end_pos(p.prev_tok)) @@ -3780,10 +3914,6 @@ parse_import_decl :: proc(p: ^Parser, kind := Import_Decl_Kind.Standard) -> ^ast import_name.pos = p.curr_tok.pos } - if !is_using && is_blank_ident(import_name) { - error(p, import_name.pos, "illegal import name: '_'") - } - path := expect_token_after(p, .String, "import") decl := ast.new(ast.Import_Decl, tok.pos, end_pos(path)) diff --git a/core/odin/tokenizer/token.odin b/core/odin/tokenizer/token.odin index 48d08f127..8c84ca69b 100644 --- a/core/odin/tokenizer/token.odin +++ b/core/odin/tokenizer/token.odin @@ -67,6 +67,8 @@ Token_Kind :: enum u32 { Cmp_And, // && Cmp_Or, // || + Mul_Mul, // ** + B_Assign_Op_Begin, Add_Eq, // += Sub_Eq, // -= @@ -202,6 +204,8 @@ tokens := [Token_Kind.COUNT]string { "&&", "||", + "**", + "", "+=", "-=", diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin index d4da82c56..df9d5b01d 100644 --- a/core/odin/tokenizer/tokenizer.odin +++ b/core/odin/tokenizer/tokenizer.odin @@ -1,5 +1,7 @@ +// The tokenizer (lexer) for `Odin` files, used to create tooling. package odin_tokenizer +import "base:intrinsics" import "core:fmt" import "core:unicode" import "core:unicode/utf8" @@ -31,6 +33,68 @@ Tokenizer :: struct { error_count: int, } + +Keyword_Hash_Entry :: struct { + hash: u32, + kind: Token_Kind, + name: string, +} + +KEYWORD_LUT_LEN :: 1<<9 +KEYWORD_LUT_MASK :: KEYWORD_LUT_LEN-1 +Keyword_LUT :: [KEYWORD_LUT_LEN]Keyword_Hash_Entry + +global_keyword_lut: Keyword_LUT // protected by `_global_keyword_lut_spinlock` +_global_keyword_lut_initialized: bool // atomic +_global_keyword_lut_spinlock: bool // atomic + +_global_keyword_spin_lock :: proc() { + for intrinsics.atomic_exchange_explicit(&_global_keyword_lut_spinlock, true, .Acquire) { + intrinsics.cpu_relax() + } +} + +_global_keyword_spin_unlock :: proc() { + intrinsics.atomic_store_explicit(&_global_keyword_lut_spinlock, false, .Release) +} + +@(require_results) +keyword_hash :: proc(text: string) -> u32 #no_bounds_check { + h := u32(0x811c9dc5) + for i in 0.. bool { + if lut == nil { + return false + } + + max_keyword_size := 0 + + for kind in (Token_Kind.B_Keyword_Begin+Token_Kind(1)).. 1) + assert(max_keyword_size < 16) + + return true +} + + init :: proc(t: ^Tokenizer, src: string, path: string, err: Error_Handler = default_error_handler) { t.src = src t.err = err @@ -43,6 +107,13 @@ init :: proc(t: ^Tokenizer, src: string, path: string, err: Error_Handler = defa t.error_count = 0 t.path = path + if !intrinsics.atomic_load(&_global_keyword_lut_initialized) { + _global_keyword_spin_lock() + ok := keyword_lut_init(&global_keyword_lut) + intrinsics.atomic_store(&_global_keyword_lut_initialized, ok) + _global_keyword_spin_unlock() + } + advance_rune(t) if t.ch == utf8.RUNE_BOM { advance_rune(t) @@ -209,14 +280,14 @@ scan_comment :: proc(t: ^Tokenizer) -> string { scan_file_tag :: proc(t: ^Tokenizer) -> string { offset := t.offset - 1 - for t.ch != '\n' { + for t.ch != '\n' && t.ch != utf8.RUNE_EOF { if t.ch == '/' { next := peek_byte(t, 0) if next == '/' || next == '*' { break } - } + } advance_rune(t) } @@ -501,13 +572,20 @@ scan :: proc(t: ^Tokenizer) -> Token { case is_letter(ch): lit = scan_identifier(t) kind = .Ident - check_keyword: if len(lit) > 1 { - // TODO(bill): Maybe have a hash table lookup rather than this linear search - for i in Token_Kind.B_Keyword_Begin ..= Token_Kind.B_Keyword_End { - if lit == tokens[i] { - kind = Token_Kind(i) + check_keyword: if 1 < len(lit) && len(lit) < 16 { + if intrinsics.atomic_load(&_global_keyword_lut_initialized) { + entry := &global_keyword_lut[keyword_hash(lit) & KEYWORD_LUT_MASK] + if entry.kind != .Invalid && entry.name == lit { + kind = entry.kind break check_keyword } + } else { + for i in Token_Kind.B_Keyword_Begin ..= Token_Kind.B_Keyword_End { + if lit == tokens[i] { + kind = Token_Kind(i) + break check_keyword + } + } } for keyword, i in custom_keyword_tokens { if lit == keyword { @@ -515,7 +593,6 @@ scan :: proc(t: ^Tokenizer) -> Token { break check_keyword } } - break check_keyword } case '0' <= ch && ch <= '9': kind, lit = scan_number(t, false) @@ -602,6 +679,9 @@ scan :: proc(t: ^Tokenizer) -> Token { if t.ch == '=' { advance_rune(t) kind = .Mul_Eq + } else if t.ch == '*' { + advance_rune(t) + kind = .Mul_Mul } case '=': kind = .Eq diff --git a/core/os/os2/allocators.odin b/core/os/allocators.odin similarity index 94% rename from core/os/os2/allocators.odin rename to core/os/allocators.odin index cedfbdee1..e49d416e1 100644 --- a/core/os/os2/allocators.odin +++ b/core/os/allocators.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -16,7 +16,7 @@ MAX_TEMP_ARENA_COLLISIONS :: MAX_TEMP_ARENA_COUNT - 1 global_default_temp_allocator_arenas: [MAX_TEMP_ARENA_COUNT]runtime.Arena @(fini, private) -temp_allocator_fini :: proc() { +temp_allocator_fini :: proc "contextless" () { for &arena in global_default_temp_allocator_arenas { runtime.arena_destroy(&arena) } @@ -69,6 +69,6 @@ _temp_allocator_end :: proc(tmp: runtime.Arena_Temp) { } @(init, private) -init_thread_local_cleaner :: proc() { +init_thread_local_cleaner :: proc "contextless" () { runtime.add_thread_local_cleaner(temp_allocator_fini) } diff --git a/core/os/os2/dir.odin b/core/os/dir.odin similarity index 70% rename from core/os/os2/dir.odin rename to core/os/dir.odin index a33e8a8d9..ee7cbfb09 100644 --- a/core/os/os2/dir.odin +++ b/core/os/dir.odin @@ -1,10 +1,15 @@ -package os2 +package os import "base:runtime" import "core:slice" +import "core:strings" read_dir :: read_directory +/* + Reads the file `f` (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ @(require_results) read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) { if f == nil { @@ -46,11 +51,18 @@ read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files } +/* + Reads the file `f` (assuming it is a directory) and returns all of the unsorted directory entries. +*/ @(require_results) read_all_directory :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { return read_directory(f, -1, allocator) } +/* + Reads the named directory by path (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ @(require_results) read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { f := open(path) or_return @@ -58,6 +70,9 @@ read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocato return read_directory(f, n, allocator) } +/* + Reads the named directory by path (assuming it is a directory) and returns all of the unsorted directory entries. +*/ @(require_results) read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) { return read_directory_by_path(path, -1, allocator) @@ -145,8 +160,8 @@ extend its lifetime. Example: package main - import "core:fmt" - import os "core:os/os2" + import "core:fmt" + import "core:os" main :: proc() { f, oerr := os.open("core") @@ -180,7 +195,6 @@ Example: } } */ -@(require_results) read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { if it.f == nil { return @@ -194,28 +208,54 @@ read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, } // Recursively copies a directory to `dst` from `src` -copy_directory :: proc(dst, src: string, dst_perm := 0o755) -> Error { - switch err := make_directory_all(dst, dst_perm); err { - case nil, .Exist: - // okay - case: +copy_directory_all :: proc(dst, src: string, dst_perm := Permissions_Default) -> Error { + when #defined(_copy_directory_all_native) { + return _copy_directory_all_native(dst, src, dst_perm) + } else { + return _copy_directory_all(dst, src, dst_perm) + } +} + +@(private) +_copy_directory_all :: proc(dst, src: string, dst_perm := Permissions_Default) -> Error { + err := make_directory_all(dst, dst_perm) + if err != nil && err != .Exist { return err } temp_allocator := TEMP_ALLOCATOR_GUARD({}) - file_infos := read_all_directory_by_path(src, temp_allocator) or_return - for fi in file_infos { - temp_allocator_scope(temp_allocator) + abs_src := get_absolute_path(src, temp_allocator) or_return + abs_dst := get_absolute_path(dst, temp_allocator) or_return - dst_path := join_path({dst, fi.name}, temp_allocator) or_return - src_path := fi.fullpath + dst_buf := make([dynamic]byte, 0, len(abs_dst) + 256, temp_allocator) or_return - if fi.type == .Directory { - copy_directory(dst_path, src_path) or_return + w: Walker + walker_init_path(&w, src) + defer walker_destroy(&w) + + for info in walker_walk(&w) { + _ = walker_error(&w) or_break + + rel := strings.trim_prefix(info.fullpath, abs_src) + + non_zero_resize(&dst_buf, 0) + reserve(&dst_buf, len(abs_dst) + len(Path_Separator_String) + len(rel)) or_return + append(&dst_buf, abs_dst) + append(&dst_buf, Path_Separator_String) + append(&dst_buf, rel) + + if info.type == .Directory { + err = make_directory(string(dst_buf[:]), dst_perm) + if err != nil && err != .Exist { + return err + } } else { - copy_file(dst_path, src_path) or_return + copy_file(string(dst_buf[:]), info.fullpath) or_return } } + + _ = walker_error(&w) or_return + return nil } diff --git a/core/os/dir_js.odin b/core/os/dir_js.odin new file mode 100644 index 000000000..cd6227507 --- /dev/null +++ b/core/os/dir_js.odin @@ -0,0 +1,28 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:intrinsics" + +Read_Directory_Iterator_Impl :: struct { + fullpath: [dynamic]byte, + buf: []byte, + off: int, +} + +@(require_results) +_read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { + return {}, -1, false +} + +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + +} + +_read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { + +} \ No newline at end of file diff --git a/core/os/os2/dir_linux.odin b/core/os/dir_linux.odin similarity index 96% rename from core/os/os2/dir_linux.odin rename to core/os/dir_linux.odin index 34346c02f..e0e658c26 100644 --- a/core/os/os2/dir_linux.odin +++ b/core/os/dir_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "core:sys/linux" @@ -97,8 +97,8 @@ _read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { return } - stat: linux.Stat - errno := linux.fstat(linux.Fd(fd(f)), &stat) + stat: linux.Statx + errno := linux.statx(linux.Fd(fd(f)), "", {.EMPTY_PATH}, {.TYPE}, &stat) if errno != .NONE { read_directory_iterator_set_error(it, name(f), _get_platform_error(errno)) return diff --git a/core/os/os2/dir_posix.odin b/core/os/dir_posix.odin similarity index 99% rename from core/os/os2/dir_posix.odin rename to core/os/dir_posix.odin index d9fa16f8d..c67a37430 100644 --- a/core/os/os2/dir_posix.odin +++ b/core/os/dir_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "core:sys/posix" diff --git a/core/os/dir_posix_darwin.odin b/core/os/dir_posix_darwin.odin new file mode 100644 index 000000000..ddd25c1fc --- /dev/null +++ b/core/os/dir_posix_darwin.odin @@ -0,0 +1,17 @@ +#+private +package os + +import "core:sys/darwin" + +_copy_directory_all_native :: proc(dst, src: string, dst_perm := Permissions_Default) -> (err: Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + + csrc := clone_to_cstring(src, temp_allocator) or_return + cdst := clone_to_cstring(dst, temp_allocator) or_return + + if darwin.copyfile(csrc, cdst, nil, darwin.COPYFILE_ALL + {.RECURSIVE}) < 0 { + err = _get_platform_error() + } + + return +} diff --git a/core/os/os2/dir_walker.odin b/core/os/dir_walker.odin similarity index 98% rename from core/os/os2/dir_walker.odin rename to core/os/dir_walker.odin index 0af751f31..b510b7a2a 100644 --- a/core/os/os2/dir_walker.odin +++ b/core/os/dir_walker.odin @@ -1,4 +1,4 @@ -package os2 +package os import "core:container/queue" @@ -136,9 +136,9 @@ If an error occurred opening a directory, you may get zero'd info struct and Example: package main - import "core:fmt" - import "core:strings" - import os "core:os/os2" + import "core:fmt" + import "core:strings" + import "core:os" main :: proc() { w := os.walker_create("core") @@ -227,4 +227,4 @@ walker_walk :: proc(w: ^Walker) -> (fi: File_Info, ok: bool) { } return info, iter_ok -} +} \ No newline at end of file diff --git a/core/os/os2/dir_wasi.odin b/core/os/dir_wasi.odin similarity index 98% rename from core/os/os2/dir_wasi.odin rename to core/os/dir_wasi.odin index 61c005674..05d74be31 100644 --- a/core/os/os2/dir_wasi.odin +++ b/core/os/dir_wasi.odin @@ -1,7 +1,6 @@ #+private -package os2 +package os -import "base:runtime" import "core:slice" import "base:intrinsics" import "core:sys/wasm/wasi" diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index ae3e6922c..3fd045560 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -1,114 +1,144 @@ +#+private package os -import win32 "core:sys/windows" -import "core:strings" import "base:runtime" +import "core:time" +import win32 "core:sys/windows" + +@(private="file") +find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { + // Ignore "." and ".." + if d.cFileName[0] == '.' && d.cFileName[1] == 0 { + return + } + if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 { + return + } + + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + path := concatenate({base_path, `\`, win32_wstring_to_utf8(cstring16(raw_data(d.cFileName[:])), temp_allocator) or_else ""}, allocator) or_return + + handle := win32.HANDLE(_open_internal(path, {.Read}, Permissions_Read_Write_All) or_else 0) + defer win32.CloseHandle(handle) + + fi.fullpath = path + fi.name = basename(path) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + + fi.type, fi.mode = _file_type_mode_from_file_attributes(d.dwFileAttributes, handle, d.dwReserved0) + + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + + if file_id_info: win32.FILE_ID_INFO; handle != nil && win32.GetFileInformationByHandleEx(handle, .FileIdInfo, &file_id_info, size_of(file_id_info)) { + #assert(size_of(fi.inode) == size_of(file_id_info.FileId)) + #assert(size_of(fi.inode) == 16) + runtime.mem_copy_non_overlapping(&fi.inode, &file_id_info.FileId, 16) + } + + return +} + +Read_Directory_Iterator_Impl :: struct { + find_data: win32.WIN32_FIND_DATAW, + find_handle: win32.HANDLE, + path: string, + prev_fi: File_Info, + no_more_files: bool, +} + @(require_results) -read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) { - @(require_results) - find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { - // Ignore "." and ".." - if d.cFileName[0] == '.' && d.cFileName[1] == 0 { +_read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { + for !it.impl.no_more_files { + err: Error + file_info_delete(it.impl.prev_fi, file_allocator()) + it.impl.prev_fi = {} + + fi, err = find_data_to_file_info(it.impl.path, &it.impl.find_data, file_allocator()) + if err != nil { + read_directory_iterator_set_error(it, it.impl.path, err) return } - if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 { - return - } - path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:]) or_else ""}) - fi.fullpath = path - fi.name = basename(path) - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { - fi.mode |= 0o444 - } else { - fi.mode |= 0o666 + if fi.name != "" { + it.impl.prev_fi = fi + ok = true + index = it.index + it.index += 1 } - is_sym := false - if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 { - is_sym = false - } else { - is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT - } - - if is_sym { - fi.mode |= File_Mode_Sym_Link - } else { - if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - fi.mode |= 0o111 | File_Mode_Dir + if !win32.FindNextFileW(it.impl.find_handle, &it.impl.find_data) { + e := _get_platform_error() + if pe, _ := is_platform_error(e); pe != i32(win32.ERROR_NO_MORE_FILES) { + read_directory_iterator_set_error(it, it.impl.path, e) } - - // fi.mode |= file_type_mode(h); + it.impl.no_more_files = true } + if ok { + return + } + } + return +} - windows_set_file_info_times(&fi, d) +_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { + it.impl.no_more_files = false - fi.is_dir = fi.mode & File_Mode_Dir != 0 + if f == nil || f.impl == nil { + read_directory_iterator_set_error(it, "", .Invalid_File) return } - if fd == 0 { - return nil, ERROR_INVALID_HANDLE + it.f = f + impl := (^File_Impl)(f.impl) + + // NOTE: Allow calling `init` to target a new directory with the same iterator - reset idx. + if it.impl.find_handle != nil { + win32.FindClose(it.impl.find_handle) + } + if it.impl.path != "" { + delete(it.impl.path, file_allocator()) } - context.allocator = allocator - - h := win32.HANDLE(fd) - - dir_fi, _ := file_info_from_get_file_information_by_handle("", h) - if !dir_fi.is_dir { - return nil, .Not_Dir - } - - n := n - size := n - if n <= 0 { - n = -1 - size = 100 - } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - - wpath := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return - if len(wpath) == 0 { + if !is_directory(impl.name) { + read_directory_iterator_set_error(it, impl.name, .Invalid_Dir) return } - dfi := make([dynamic]File_Info, 0, size) or_return + wpath := string16(impl.wname) + temp_allocator := TEMP_ALLOCATOR_GUARD({}) - wpath_search := make([]u16, len(wpath)+3, context.temp_allocator) or_return + wpath_search := make([]u16, len(wpath)+3, temp_allocator) copy(wpath_search, wpath) wpath_search[len(wpath)+0] = '\\' wpath_search[len(wpath)+1] = '*' wpath_search[len(wpath)+2] = 0 - path := cleanpath_from_buf(wpath) - defer delete(path) - - find_data := &win32.WIN32_FIND_DATAW{} - find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data) - if find_handle == win32.INVALID_HANDLE_VALUE { - err = get_last_error() - return dfi[:], err + it.impl.find_handle = win32.FindFirstFileW(cstring16(raw_data(wpath_search)), &it.impl.find_data) + if it.impl.find_handle == win32.INVALID_HANDLE_VALUE { + read_directory_iterator_set_error(it, impl.name, _get_platform_error()) + return } - defer win32.FindClose(find_handle) - for n != 0 { - fi: File_Info - fi = find_data_to_file_info(path, find_data) - if fi.name != "" { - append(&dfi, fi) - n -= 1 - } - - if !win32.FindNextFileW(find_handle, find_data) { - e := get_last_error() - if e == ERROR_NO_MORE_FILES { - break - } - return dfi[:], e - } + defer if it.err.err != nil { + win32.FindClose(it.impl.find_handle) } - return dfi[:], nil + err: Error + it.impl.path, err = get_absolute_path(impl.name, file_allocator()) + if err != nil { + read_directory_iterator_set_error(it, impl.name, err) + } + + return +} + +_read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { + if it.f == nil { + return + } + file_info_delete(it.impl.prev_fi, file_allocator()) + delete(it.impl.path, file_allocator()) + win32.FindClose(it.impl.find_handle) } diff --git a/core/os/doc.odin b/core/os/doc.odin new file mode 100644 index 000000000..10087a5e1 --- /dev/null +++ b/core/os/doc.odin @@ -0,0 +1,3 @@ +// A cross-platform API for things like `I/O`, intended to be uniform across all operating systems. +// Features not generally available appear in the system-specific packages under `core:sys`. +package os diff --git a/core/os/env.odin b/core/os/env.odin new file mode 100644 index 000000000..0b8138e6b --- /dev/null +++ b/core/os/env.odin @@ -0,0 +1,122 @@ +package os + +import "base:runtime" +import "core:strings" + +// `get_env` retrieves the value of the environment variable named by the key +// It returns the value, which will be empty if the variable is not present +// To distinguish between an empty value and an unset value, use lookup_env +// NOTE: the value will be allocated with the supplied allocator +@(require_results) +get_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> string { + value, _ := lookup_env(key, allocator) + return value +} + +// `get_env` retrieves the value of the environment variable named by the key +// It returns the value, which will be empty if the variable is not present +// To distinguish between an empty value and an unset value, use lookup_env +// NOTE: this version takes a backing buffer for the string value +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> string { + value, _ := lookup_env(buf, key) + return value +} + +get_env :: proc{get_env_alloc, get_env_buf} + +// `lookup_env` gets the value of the environment variable named by the key +// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true +// Otherwise the returned value will be empty and the boolean will be false +// NOTE: the value will be allocated with the supplied allocator +@(require_results) +lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { + return _lookup_env_alloc(key, allocator) +} + +// This version of `lookup_env` doesn't allocate and instead requires the user to provide a buffer. +// Note that it is limited to environment names and values of 512 utf-16 values each +// due to the necessary utf-8 <> utf-16 conversion. +@(require_results) +lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + return _lookup_env_buf(buf, key) +} + +lookup_env :: proc{lookup_env_alloc, lookup_env_buf} + +// set_env sets the value of the environment variable named by the key +// Returns Error on failure +set_env :: proc(key, value: string) -> Error { + return _set_env(key, value) +} + +// unset_env unsets a single environment variable +// Returns true on success, false on failure +unset_env :: proc(key: string) -> bool { + return _unset_env(key) +} + +clear_env :: proc() { + _clear_env() +} + + +// environ returns a copy of strings representing the environment, in the form "key=value" +// NOTE: the slice of strings and the strings with be allocated using the supplied allocator +@(require_results) +environ :: proc(allocator: runtime.Allocator) -> ([]string, Error) { + return _environ(allocator) +} + +// Always allocates for consistency. +replace_environment_placeholders :: proc(path: string, allocator: runtime.Allocator) -> (res: string) { + path := path + + sb: strings.Builder + strings.builder_init_none(&sb, allocator) + + for len(path) > 0 { + switch path[0] { + case '%': // Windows + when ODIN_OS == .Windows { + for r, i in path[1:] { + if r == '%' { + env_key := path[1:i+1] + env_val := get_env(env_key, context.temp_allocator) + strings.write_string(&sb, env_val) + path = path[i+1:] // % is part of key, so skip 1 character extra + } + } + } else { + strings.write_rune(&sb, rune(path[0])) + } + + case '$': // Posix + when ODIN_OS != .Windows { + env_key := "" + dollar_loop: for r, i in path[1:] { + switch r { + case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident + case: + env_key = path[1:i+1] + break dollar_loop + } + } + if len(env_key) > 0 { + env_val := get_env(env_key, context.temp_allocator) + strings.write_string(&sb, env_val) + path = path[len(env_key):] + } + + } else { + strings.write_rune(&sb, rune(path[0])) + } + + case: + strings.write_rune(&sb, rune(path[0])) + } + + path = path[1:] + } + return strings.to_string(sb) +} \ No newline at end of file diff --git a/core/os/env_js.odin b/core/os/env_js.odin new file mode 100644 index 000000000..55ffce593 --- /dev/null +++ b/core/os/env_js.odin @@ -0,0 +1,42 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" + +build_env :: proc() -> (err: Error) { + return +} + +@(require_results) +_lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { + return +} + +_lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) { + return "", .Unsupported +} +_lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + +@(require_results) +_set_env :: proc(key, value: string) -> (err: Error) { + return .Unsupported +} + +@(require_results) +_unset_env :: proc(key: string) -> bool { + return true +} + +_clear_env :: proc() { + +} + +@(require_results) +_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + return {}, .Unsupported +} \ No newline at end of file diff --git a/core/os/env_linux.odin b/core/os/env_linux.odin new file mode 100644 index 000000000..e55c59293 --- /dev/null +++ b/core/os/env_linux.odin @@ -0,0 +1,369 @@ +#+private +package os + +import "base:runtime" +import "base:intrinsics" + +import "core:sync" +import "core:slice" +import "core:strings" +import "core:sys/linux" +import "core:sys/posix" + +_ :: sync +_ :: slice +_ :: linux +_ :: posix + +when ODIN_NO_CRT { + // TODO: Override the libc environment functions' weak linkage to + // allow us to interact with 3rd party code that DOES link + // to libc. Otherwise, our environment can be out of sync. + + NOT_FOUND :: -1 + + // the environment is a 0 delimited list of = strings + _env: [dynamic]string + + _env_mutex: sync.Recursive_Mutex + + // We need to be able to figure out if the environment variable + // is contained in the original environment or not. This also + // serves as a flag to determine if we have built _env. + _org_env_begin: uintptr // atomic + _org_env_end: uintptr // guarded by _env_mutex + + // Returns value + index location into _env + // or -1 if not found + _lookup :: proc(key: string) -> (value: string, idx: int) { + sync.guard(&_env_mutex) + + for entry, i in _env { + if k, v := _kv_from_entry(entry); k == key { + return v, i + } + } + return "", -1 + } + + _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + _build_env() + } + + if v, idx := _lookup(key); idx != -1 { + found = true + value, _ = clone_string(v, allocator) + } + return + } + + _lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + _build_env() + } + + if v, idx := _lookup(key); idx != -1 { + if len(buf) >= len(v) { + copy(buf, v) + return string(buf[:len(v)]), nil + } + return "", .Buffer_Full + } + return "", .Env_Var_Not_Found + } + + _lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + + _set_env :: proc(key, v_new: string) -> Error { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + _build_env() + } + sync.guard(&_env_mutex) + + // all key values are stored as "key=value\x00" + kv_size := len(key) + len(v_new) + 2 + if v_curr, idx := _lookup(key); idx != NOT_FOUND { + if v_curr == v_new { + return nil + } + + unordered_remove(&_env, idx) + + if !_is_in_org_env(v_curr) { + // We allocated this key-value. Possibly resize and + // overwrite the value only. Otherwise, treat as if it + // wasn't in the environment in the first place. + k_addr, v_addr := _kv_addr_from_val(v_curr, key) + if len(v_new) > len(v_curr) { + k_addr = ([^]u8)(runtime.heap_resize(k_addr, kv_size)) + if k_addr == nil { + return .Out_Of_Memory + } + v_addr = &k_addr[len(key) + 1] + } + intrinsics.mem_copy_non_overlapping(v_addr, raw_data(v_new), len(v_new)) + v_addr[len(v_new)] = 0 + + append(&_env, string(k_addr[:kv_size])) + return nil + } + } + + k_addr := ([^]u8)(runtime.heap_alloc(kv_size)) + if k_addr == nil { + return .Out_Of_Memory + } + intrinsics.mem_copy_non_overlapping(k_addr, raw_data(key), len(key)) + k_addr[len(key)] = '=' + + val_slice := k_addr[len(key) + 1:] + intrinsics.mem_copy_non_overlapping(&val_slice[0], raw_data(v_new), len(v_new)) + val_slice[len(v_new)] = 0 + + append(&_env, string(k_addr[:kv_size - 1])) + return nil + } + + _unset_env :: proc(key: string) -> bool { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + _build_env() + } + sync.guard(&_env_mutex) + + v: string + i: int + if v, i = _lookup(key); i == -1 { + return true + } + + unordered_remove(&_env, i) + + if _is_in_org_env(v) { + return true + } + + // if we got this far, the environment variable + // existed AND was allocated by us. + k_addr, _ := _kv_addr_from_val(v, key) + runtime.heap_free(k_addr) + return true + } + + _clear_env :: proc() { + sync.guard(&_env_mutex) + + for kv in _env { + if !_is_in_org_env(kv) { + runtime.heap_free(raw_data(kv)) + } + } + clear(&_env) + + // nothing resides in the original environment either + intrinsics.atomic_store_explicit(&_org_env_begin, ~uintptr(0), .Release) + _org_env_end = ~uintptr(0) + } + + _environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + _build_env() + } + sync.guard(&_env_mutex) + + env := make([dynamic]string, 0, len(_env), allocator) or_return + defer if err != nil { + for e in env { + delete(e, allocator) + } + delete(env) + } + + for entry in _env { + s := clone_string(entry, allocator) or_return + append(&env, s) + } + environ = env[:] + return + } + + // The entire environment is stored as 0 terminated strings, + // so there is no need to clone/free individual variables + export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { + // The environment has not been modified, so we can just + // send the original environment + org_env := _get_original_env() + n: int + for ; org_env[n] != nil; n += 1 {} + return slice.clone(org_env[:n + 1], allocator) + } + sync.guard(&_env_mutex) + + // NOTE: already terminated by nil pointer via + 1 + env := make([]cstring, len(_env) + 1, allocator) + + for entry, i in _env { + env[i] = cstring(raw_data(entry)) + } + return env + } + + _build_env :: proc() { + sync.guard(&_env_mutex) + if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) != 0 { + return + } + + _env = make(type_of(_env), runtime.heap_allocator()) + cstring_env := _get_original_env() + intrinsics.atomic_store_explicit(&_org_env_begin, uintptr(rawptr(cstring_env[0])), .Release) + for i := 0; cstring_env[i] != nil; i += 1 { + bytes := ([^]u8)(cstring_env[i]) + n := len(cstring_env[i]) + _org_env_end = uintptr(&bytes[n]) + append(&_env, string(bytes[:n])) + } + } + + _get_original_env :: #force_inline proc() -> [^]cstring { + // essentially &argv[argc] which should be a nil pointer! + #no_bounds_check env: [^]cstring = &runtime.args__[len(runtime.args__)] + assert(env[0] == nil) + return &env[1] + } + + _kv_from_entry :: #force_inline proc(entry: string) -> (k, v: string) { + eq_idx := strings.index_byte(entry, '=') + if eq_idx == -1 { + return entry, "" + } + return entry[:eq_idx], entry[eq_idx + 1:] + } + + _kv_addr_from_val :: #force_inline proc(val: string, key: string) -> ([^]u8, [^]u8) { + v_addr := raw_data(val) + k_addr := ([^]u8)(&v_addr[-(len(key) + 1)]) + return k_addr, v_addr + } + + _is_in_org_env :: #force_inline proc(env_data: string) -> bool { + addr := uintptr(raw_data(env_data)) + return addr >= intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) && addr < _org_env_end + } + +} else { + + _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { + if key == "" { + return + } + + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + ckey := strings.clone_to_cstring(key, temp_allocator) + cval := posix.getenv(ckey) + if cval == nil { + return + } + + found = true + value = strings.clone(string(cval), allocator) // NOTE(laytan): what if allocation fails? + + return + } + + _lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) { + if key == "" { + return + } + + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + cval := posix.getenv(cstring(raw_data(buf))) + if cval == nil { + return + } + + if value = string(cval); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } + } + + _lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + + _set_env :: proc(key, value: string) -> (err: Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + + ckey := strings.clone_to_cstring(key, temp_allocator) or_return + cval := strings.clone_to_cstring(value, temp_allocator) or_return + + if posix.setenv(ckey, cval, true) != nil { + posix_errno := posix.errno() + linux_errno := cast(linux.Errno)(cast(int)posix_errno) + err = _get_platform_error(linux_errno) + } + return + } + + _unset_env :: proc(key: string) -> (ok: bool) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + + ckey := strings.clone_to_cstring(key, temp_allocator) + + ok = posix.unsetenv(ckey) == .OK + return + } + + // NOTE(laytan): clearing the env is weird, why would you ever do that? + + _clear_env :: proc() { + for entry := posix.environ[0]; entry != nil; entry = posix.environ[0] { + key := strings.truncate_to_byte(string(entry), '=') + _unset_env(key) + } + } + + _environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { + n := 0 + for entry := posix.environ[0]; entry != nil; n, entry = n+1, posix.environ[n] {} + + r := make([dynamic]string, 0, n, allocator) or_return + defer if err != nil { + for e in r { + delete(e, allocator) + } + delete(r) + } + + for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] { + append(&r, strings.clone(string(entry), allocator) or_return) + } + + environ = r[:] + return + } + + + + export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { + env := make([dynamic]cstring, allocator) + for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] { + append(&env, entry) + } + append(&env, nil) + return env[:] + } +} diff --git a/core/os/os2/env_posix.odin b/core/os/env_posix.odin similarity index 68% rename from core/os/os2/env_posix.odin rename to core/os/env_posix.odin index 13682f76b..5d46cf7fc 100644 --- a/core/os/os2/env_posix.odin +++ b/core/os/env_posix.odin @@ -1,13 +1,13 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" import "core:strings" import "core:sys/posix" -_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { +_lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { if key == "" { return } @@ -26,6 +26,37 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string return } +_lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) { + if key == "" { + return + } + + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + cval := posix.getenv(cstring(raw_data(buf))) + if cval == nil { + return + } + + if value = string(cval); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} + +_lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + _set_env :: proc(key, value: string) -> (err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) @@ -50,7 +81,7 @@ _unset_env :: proc(key: string) -> (ok: bool) { // NOTE(laytan): clearing the env is weird, why would you ever do that? _clear_env :: proc() { - for i, entry := 0, posix.environ[0]; entry != nil; i, entry = i+1, posix.environ[i] { + for entry := posix.environ[0]; entry != nil; entry = posix.environ[0] { key := strings.truncate_to_byte(string(entry), '=') _unset_env(key) } diff --git a/core/os/os2/env_wasi.odin b/core/os/env_wasi.odin similarity index 83% rename from core/os/os2/env_wasi.odin rename to core/os/env_wasi.odin index faa54e36b..03a56421d 100644 --- a/core/os/os2/env_wasi.odin +++ b/core/os/env_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -67,7 +67,7 @@ delete_string_if_not_original :: proc(str: string) { } @(require_results) -_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { +_lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { if err := build_env(); err != nil { return } @@ -79,6 +79,35 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string return } +_lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, error: Error) { + if key == "" { + return + } + + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + sync.shared_guard(&g_env_mutex) + + val, ok := g_env[key] + + if !ok { + return "", .Env_Var_Not_Found + } else { + if len(val) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, val) + return string(buf[:len(val)]), nil + } + } +} +_lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + @(require_results) _set_env :: proc(key, value: string) -> (err: Error) { build_env() or_return diff --git a/core/os/env_windows.odin b/core/os/env_windows.odin index efd002342..dfbc5c454 100644 --- a/core/os/env_windows.odin +++ b/core/os/env_windows.odin @@ -1,97 +1,91 @@ +#+private package os import win32 "core:sys/windows" import "base:runtime" -// lookup_env gets the value of the environment variable named by the key -// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true -// Otherwise the returned value will be empty and the boolean will be false -// NOTE: the value will be allocated with the supplied allocator -@(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +_lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { if key == "" { return } - wkey := win32.utf8_to_wstring(key) - n := win32.GetEnvironmentVariableW(wkey, nil, 0) - if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND { - return "", false - } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + wkey, _ := win32_utf8_to_wstring(key, temp_allocator) + + n := win32.GetEnvironmentVariableW(wkey, nil, 0) + if n == 0 { + err := win32.GetLastError() + if err == win32.ERROR_ENVVAR_NOT_FOUND { + return "", false + } + return "", true + } + + b := make([]u16, n+1, temp_allocator) - b, _ := make([dynamic]u16, n, context.temp_allocator) n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))) - if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND { + if n == 0 { + err := win32.GetLastError() + if err == win32.ERROR_ENVVAR_NOT_FOUND { + return "", false + } return "", false } - value, _ = win32.utf16_to_utf8(b[:n], allocator) + + value = win32_utf16_to_utf8(string16(b[:n]), allocator) or_else "" found = true return } - -// get_env retrieves the value of the environment variable named by the key -// It returns the value, which will be empty if the variable is not present -// To distinguish between an empty value and an unset value, use lookup_env -// NOTE: the value will be allocated with the supplied allocator +// This version of `lookup_env` doesn't allocate and instead requires the user to provide a buffer. +// Note that it is limited to environment names and values of 512 utf-16 values each +// due to the necessary utf-8 <> utf-16 conversion. @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { - value, _ = lookup_env(key, allocator) - return -} +_lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + key_buf: [513]u16 + wkey := win32.utf8_to_wstring(key_buf[:], key) + if wkey == nil { + return "", .Buffer_Full + } -// set_env sets the value of the environment variable named by the key -set_env :: proc(key, value: string) -> Error { - k := win32.utf8_to_wstring(key) - v := win32.utf8_to_wstring(value) + n2 := win32.GetEnvironmentVariableW(wkey, nil, 0) + if n2 == 0 { + return "", .Env_Var_Not_Found + } + + val_buf: [513]u16 + n2 = win32.GetEnvironmentVariableW(wkey, raw_data(val_buf[:]), u32(len(val_buf[:]))) + if n2 == 0 { + return "", .Env_Var_Not_Found + } else if int(n2) > len(buf) { + return "", .Buffer_Full + } + + value = win32.utf16_to_utf8(buf, val_buf[:n2]) + + return value, nil +} +_lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf} + +_set_env :: proc(key, value: string) -> Error { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + k := win32_utf8_to_wstring(key, temp_allocator) or_return + v := win32_utf8_to_wstring(value, temp_allocator) or_return if !win32.SetEnvironmentVariableW(k, v) { - return get_last_error() + return _get_platform_error() } return nil } -// unset_env unsets a single environment variable -unset_env :: proc(key: string) -> Error { - k := win32.utf8_to_wstring(key) - if !win32.SetEnvironmentVariableW(k, nil) { - return get_last_error() - } - return nil +_unset_env :: proc(key: string) -> bool { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + k, _ := win32_utf8_to_wstring(key, temp_allocator) + return bool(win32.SetEnvironmentVariableW(k, nil)) } -// environ returns a copy of strings representing the environment, in the form "key=value" -// NOTE: the slice of strings and the strings with be allocated using the supplied allocator -@(require_results) -environ :: proc(allocator := context.allocator) -> []string { - envs := ([^]win32.WCHAR)(win32.GetEnvironmentStringsW()) - if envs == nil { - return nil - } - defer win32.FreeEnvironmentStringsW(envs) - - r, err := make([dynamic]string, 0, 50, allocator) - if err != nil { - return nil - } - for from, i := 0, 0; true; i += 1 { - if c := envs[i]; c == 0 { - if i <= from { - break - } - append(&r, win32.utf16_to_utf8(envs[from:i], allocator) or_else "") - from = i + 1 - } - } - - return r[:] -} - - -// clear_env deletes all environment variables -clear_env :: proc() { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - envs := environ(context.temp_allocator) +_clear_env :: proc() { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + envs, _ := environ(temp_allocator) for env in envs { for j in 1.. (err: i32, ok: bool) { +is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) { v := ferr.(Platform_Error) or_else {} return i32(v), i32(v) != 0 } + +// Attempts to return the error `ferr` as a string without any allocation @(require_results) -error_string :: proc "contextless" (ferr: Error) -> string { +error_string :: proc(ferr: Error) -> string { if ferr == nil { return "" } @@ -67,21 +65,19 @@ error_string :: proc "contextless" (ferr: Error) -> string { case General_Error: switch e { case .None: return "" - case .Permission_Denied: return "permission denied" - case .Exist: return "file already exists" - case .Not_Exist: return "file does not exist" - case .Closed: return "file already closed" - case .Timeout: return "i/o timeout" - case .Broken_Pipe: return "Broken pipe" - case .No_Size: return "file has no definite size" - case .Invalid_File: return "invalid file" - case .Invalid_Dir: return "invalid directory" - case .Invalid_Path: return "invalid path" - case .Invalid_Callback: return "invalid callback" - case .Unsupported: return "unsupported" - case .Pattern_Has_Separator: return "pattern has separator" - case .File_Is_Pipe: return "file is pipe" - case .Not_Dir: return "file is not directory" + case .Exist: return "file already exists" + case .Not_Exist: return "file does not exist" + case .Timeout: return "i/o timeout" + case .Broken_Pipe: return "Broken pipe" + case .Invalid_File: return "invalid file" + case .Invalid_Dir: return "invalid directory" + case .Invalid_Path: return "invalid path" + case .Invalid_Callback: return "invalid callback" + case .Invalid_Command: return "invalid command" + case .Pattern_Has_Separator: return "pattern has separator" + case .Pattern_Syntax_Error: return "glob pattern syntax error" + case .No_HOME_Variable: return "no $HOME variable" + case .Env_Var_Not_Found: return "environment variable not found" } case io.Error: switch e { @@ -99,7 +95,11 @@ error_string :: proc "contextless" (ferr: Error) -> string { case .Negative_Write: return "negative write" case .Negative_Count: return "negative count" case .Buffer_Full: return "buffer full" - case .Unknown, .Empty: // + case .Permission_Denied: return "permission denied" + case .Closed: return "file already closed" + case .No_Size: return "file has no definite size" + case .Unsupported: return "unsupported" + case .Unknown: // } case runtime.Allocator_Error: switch e { @@ -110,210 +110,35 @@ error_string :: proc "contextless" (ferr: Error) -> string { case .Mode_Not_Implemented: return "allocator mode not implemented" } case Platform_Error: - return _error_string(e) + return _error_string(i32(e)) } return "unknown error" } -print_error :: proc(f: Handle, ferr: Error, msg: string) -> (n: int, err: Error) { +/* + `print_error` is a utility procedure which will print an error `ferr` to a specified file `f`. +*/ +print_error :: proc(f: ^File, ferr: Error, msg: string) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) err_str := error_string(ferr) // msg + ": " + err_str + '\n' length := len(msg) + 2 + len(err_str) + 1 - buf_ := intrinsics.alloca(length, 1) - buf := buf_[:length] + buf := make([]u8, length, temp_allocator) copy(buf, msg) buf[len(msg)] = ':' buf[len(msg) + 1] = ' ' copy(buf[len(msg) + 2:], err_str) buf[length - 1] = '\n' - return write(f, buf) + write(f, buf) } -@(require_results, private) -_error_string :: proc "contextless" (e: Platform_Error) -> string where intrinsics.type_is_enum(Platform_Error) { - if e == nil { - return "" - } - when ODIN_OS == .Darwin { - if s := string(_darwin_string_error(i32(e))); s != "" { - return s - } - } - - when ODIN_OS != .Linux { - @(require_results) - binary_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) #no_bounds_check { - n := len(array) - left, right := 0, n - for left < right { - mid := int(uint(left+right) >> 1) - if array[mid] < key { - left = mid+1 - } else { - // equal or greater - right = mid - } - } - return left, left < n && array[left] == key - } - - err := runtime.Type_Info_Enum_Value(e) - - ti := &runtime.type_info_base(type_info_of(Platform_Error)).variant.(runtime.Type_Info_Enum) - if idx, ok := binary_search(ti.values, err); ok { - return ti.names[idx] - } - } else { - @(rodata, static) - pe_strings := [Platform_Error]string{ - .NONE = "", - .EPERM = "Operation not permitted", - .ENOENT = "No such file or directory", - .ESRCH = "No such process", - .EINTR = "Interrupted system call", - .EIO = "Input/output error", - .ENXIO = "No such device or address", - .E2BIG = "Argument list too long", - .ENOEXEC = "Exec format error", - .EBADF = "Bad file descriptor", - .ECHILD = "No child processes", - .EAGAIN = "Resource temporarily unavailable", - .ENOMEM = "Cannot allocate memory", - .EACCES = "Permission denied", - .EFAULT = "Bad address", - .ENOTBLK = "Block device required", - .EBUSY = "Device or resource busy", - .EEXIST = "File exists", - .EXDEV = "Invalid cross-device link", - .ENODEV = "No such device", - .ENOTDIR = "Not a directory", - .EISDIR = "Is a directory", - .EINVAL = "Invalid argument", - .ENFILE = "Too many open files in system", - .EMFILE = "Too many open files", - .ENOTTY = "Inappropriate ioctl for device", - .ETXTBSY = "Text file busy", - .EFBIG = "File too large", - .ENOSPC = "No space left on device", - .ESPIPE = "Illegal seek", - .EROFS = "Read-only file system", - .EMLINK = "Too many links", - .EPIPE = "Broken pipe", - .EDOM = "Numerical argument out of domain", - .ERANGE = "Numerical result out of range", - .EDEADLK = "Resource deadlock avoided", - .ENAMETOOLONG = "File name too long", - .ENOLCK = "No locks available", - .ENOSYS = "Function not implemented", - .ENOTEMPTY = "Directory not empty", - .ELOOP = "Too many levels of symbolic links", - .EUNKNOWN_41 = "Unknown Error (41)", - .ENOMSG = "No message of desired type", - .EIDRM = "Identifier removed", - .ECHRNG = "Channel number out of range", - .EL2NSYNC = "Level 2 not synchronized", - .EL3HLT = "Level 3 halted", - .EL3RST = "Level 3 reset", - .ELNRNG = "Link number out of range", - .EUNATCH = "Protocol driver not attached", - .ENOCSI = "No CSI structure available", - .EL2HLT = "Level 2 halted", - .EBADE = "Invalid exchange", - .EBADR = "Invalid request descriptor", - .EXFULL = "Exchange full", - .ENOANO = "No anode", - .EBADRQC = "Invalid request code", - .EBADSLT = "Invalid slot", - .EUNKNOWN_58 = "Unknown Error (58)", - .EBFONT = "Bad font file format", - .ENOSTR = "Device not a stream", - .ENODATA = "No data available", - .ETIME = "Timer expired", - .ENOSR = "Out of streams resources", - .ENONET = "Machine is not on the network", - .ENOPKG = "Package not installed", - .EREMOTE = "Object is remote", - .ENOLINK = "Link has been severed", - .EADV = "Advertise error", - .ESRMNT = "Srmount error", - .ECOMM = "Communication error on send", - .EPROTO = "Protocol error", - .EMULTIHOP = "Multihop attempted", - .EDOTDOT = "RFS specific error", - .EBADMSG = "Bad message", - .EOVERFLOW = "Value too large for defined data type", - .ENOTUNIQ = "Name not unique on network", - .EBADFD = "File descriptor in bad state", - .EREMCHG = "Remote address changed", - .ELIBACC = "Can not access a needed shared library", - .ELIBBAD = "Accessing a corrupted shared library", - .ELIBSCN = ".lib section in a.out corrupted", - .ELIBMAX = "Attempting to link in too many shared libraries", - .ELIBEXEC = "Cannot exec a shared library directly", - .EILSEQ = "Invalid or incomplete multibyte or wide character", - .ERESTART = "Interrupted system call should be restarted", - .ESTRPIPE = "Streams pipe error", - .EUSERS = "Too many users", - .ENOTSOCK = "Socket operation on non-socket", - .EDESTADDRREQ = "Destination address required", - .EMSGSIZE = "Message too long", - .EPROTOTYPE = "Protocol wrong type for socket", - .ENOPROTOOPT = "Protocol not available", - .EPROTONOSUPPORT = "Protocol not supported", - .ESOCKTNOSUPPORT = "Socket type not supported", - .EOPNOTSUPP = "Operation not supported", - .EPFNOSUPPORT = "Protocol family not supported", - .EAFNOSUPPORT = "Address family not supported by protocol", - .EADDRINUSE = "Address already in use", - .EADDRNOTAVAIL = "Cannot assign requested address", - .ENETDOWN = "Network is down", - .ENETUNREACH = "Network is unreachable", - .ENETRESET = "Network dropped connection on reset", - .ECONNABORTED = "Software caused connection abort", - .ECONNRESET = "Connection reset by peer", - .ENOBUFS = "No buffer space available", - .EISCONN = "Transport endpoint is already connected", - .ENOTCONN = "Transport endpoint is not connected", - .ESHUTDOWN = "Cannot send after transport endpoint shutdown", - .ETOOMANYREFS = "Too many references: cannot splice", - .ETIMEDOUT = "Connection timed out", - .ECONNREFUSED = "Connection refused", - .EHOSTDOWN = "Host is down", - .EHOSTUNREACH = "No route to host", - .EALREADY = "Operation already in progress", - .EINPROGRESS = "Operation now in progress", - .ESTALE = "Stale file handle", - .EUCLEAN = "Structure needs cleaning", - .ENOTNAM = "Not a XENIX named type file", - .ENAVAIL = "No XENIX semaphores available", - .EISNAM = "Is a named type file", - .EREMOTEIO = "Remote I/O error", - .EDQUOT = "Disk quota exceeded", - .ENOMEDIUM = "No medium found", - .EMEDIUMTYPE = "Wrong medium type", - .ECANCELED = "Operation canceled", - .ENOKEY = "Required key not available", - .EKEYEXPIRED = "Key has expired", - .EKEYREVOKED = "Key has been revoked", - .EKEYREJECTED = "Key was rejected by service", - .EOWNERDEAD = "Owner died", - .ENOTRECOVERABLE = "State not recoverable", - .ERFKILL = "Operation not possible due to RF-kill", - .EHWPOISON = "Memory page has hardware error", - } - if Platform_Error.NONE <= e && e <= max(Platform_Error) { - return pe_strings[e] - } - } - return "" -} - -@(private, require_results) +// Attempts to convert an `Error` `ferr` into an `io.Error` +@(private) error_to_io_error :: proc(ferr: Error) -> io.Error { if ferr == nil { return .None diff --git a/core/os/errors_js.odin b/core/os/errors_js.odin new file mode 100644 index 000000000..368b94d68 --- /dev/null +++ b/core/os/errors_js.odin @@ -0,0 +1,17 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +_Platform_Error :: enum i32 {} + +_error_string :: proc(errno: i32) -> string { + return "" +} + +_get_platform_error :: proc(errno: _Platform_Error) -> Error { + return Platform_Error(errno) +} \ No newline at end of file diff --git a/core/os/os2/errors_linux.odin b/core/os/errors_linux.odin similarity index 99% rename from core/os/os2/errors_linux.odin rename to core/os/errors_linux.odin index a7556c306..713c03359 100644 --- a/core/os/os2/errors_linux.odin +++ b/core/os/errors_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "core:sys/linux" @@ -148,7 +148,7 @@ _get_platform_error :: proc(errno: linux.Errno) -> Error { #partial switch errno { case .NONE: return nil - case .EPERM: + case .EPERM, .EACCES: return .Permission_Denied case .EEXIST: return .Exist diff --git a/core/os/os2/errors_posix.odin b/core/os/errors_posix.odin similarity index 96% rename from core/os/os2/errors_posix.odin rename to core/os/errors_posix.odin index 8a9ca07df..45bac931f 100644 --- a/core/os/os2/errors_posix.odin +++ b/core/os/errors_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "core:sys/posix" @@ -16,7 +16,7 @@ _get_platform_error_from_errno :: proc() -> Error { _get_platform_error_existing :: proc(errno: posix.Errno) -> Error { #partial switch errno { - case .EPERM: + case .EPERM, .EACCES: return .Permission_Denied case .EEXIST: return .Exist diff --git a/core/os/os2/errors_wasi.odin b/core/os/errors_wasi.odin similarity index 98% rename from core/os/os2/errors_wasi.odin rename to core/os/errors_wasi.odin index b88e5b81e..a0377ce96 100644 --- a/core/os/os2/errors_wasi.odin +++ b/core/os/errors_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/errors_windows.odin b/core/os/errors_windows.odin similarity index 99% rename from core/os/os2/errors_windows.odin rename to core/os/errors_windows.odin index 404560f98..639780337 100644 --- a/core/os/os2/errors_windows.odin +++ b/core/os/errors_windows.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" import "core:slice" diff --git a/core/os/file.odin b/core/os/file.odin new file mode 100644 index 000000000..61582c528 --- /dev/null +++ b/core/os/file.odin @@ -0,0 +1,570 @@ +package os + +import "core:io" +import "core:time" +import "base:runtime" + +/* + Type representing a file handle. + + This struct represents an OS-specific file-handle, which can be one of + the following: + - File + - Directory + - Pipe + - Named pipe + - Block Device + - Character device + - Symlink + - Socket + + See `File_Type` enum for more information on file types. +*/ +File :: struct { + impl: rawptr, + stream: File_Stream, +} + +/* + Type representing the type of a file handle. + + **Note(windows)**: Socket handles can not be distinguished from + files, as they are just a normal file handle that is being treated by + a special driver. Windows also makes no distinction between block and + character devices. +*/ +File_Type :: enum { + // The type of a file could not be determined for the current platform. + Undetermined, + // Represents a regular file. + Regular, + // Represents a directory. + Directory, + // Represents a symbolic link. + Symlink, + // Represents a named pipe (FIFO). + Named_Pipe, + // Represents a socket. + // **Note(windows)**: Not returned on windows + Socket, + // Represents a block device. + // **Note(windows)**: On windows represents all devices. + Block_Device, + // Represents a character device. + // **Note(windows)**: Not returned on windows + Character_Device, +} + +// Represents the file flags for a file handle +File_Flags :: distinct bit_set[File_Flag; uint] +File_Flag :: enum { + Read, + Write, + Append, + Create, + Excl, + Sync, + Trunc, + Sparse, + Inheritable, + Non_Blocking, + Unbuffered_IO, +} + +O_RDONLY :: File_Flags{.Read} +O_WRONLY :: File_Flags{.Write} +O_RDWR :: File_Flags{.Read, .Write} +O_APPEND :: File_Flags{.Append} +O_CREATE :: File_Flags{.Create} +O_EXCL :: File_Flags{.Excl} +O_SYNC :: File_Flags{.Sync} +O_TRUNC :: File_Flags{.Trunc} +O_SPARSE :: File_Flags{.Sparse} + +/* + If specified, the file handle is inherited upon the creation of a child + process. By default all handles are created non-inheritable. + + **Note**: The standard file handles (stderr, stdout and stdin) are always + initialized as inheritable. +*/ +O_INHERITABLE :: File_Flags{.Inheritable} + +Permissions :: distinct bit_set[Permission_Flag; u32] +Permission_Flag :: enum u32 { + Execute_Other = 0, + Write_Other = 1, + Read_Other = 2, + + Execute_Group = 3, + Write_Group = 4, + Read_Group = 5, + + Execute_User = 6, + Write_User = 7, + Read_User = 8, +} + +Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other} +Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other} +Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other} + +Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All + +Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All + +Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All +Permissions_Default_Directory :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All +Permissions_Default :: Permissions_Default_Directory + +perm :: proc{ + perm_number, +} + +/* + `perm_number` converts an integer value `perm` to the bit set `Permissions` +*/ +@(require_results) +perm_number :: proc "contextless" (perm: int) -> Permissions { + return transmute(Permissions)u32(perm & 0o777) +} + + + +// `stdin` is an open file pointing to the standard input file stream +stdin: ^File = nil // OS-Specific + +// `stdout` is an open file pointing to the standard output file stream +stdout: ^File = nil // OS-Specific + +// `stderr` is an open file pointing to the standard error file stream +stderr: ^File = nil // OS-Specific + +/* + `create` creates or truncates a named file `name`. + If the file already exists, it is truncated. + If the file does not exist, it is created with the `Permissions_Default_File` permissions. + If successful, a `^File` is return which can be used for I/O. + And error is returned if any is encountered. +*/ +@(require_results) +create :: proc(name: string) -> (^File, Error) { + return open(name, {.Read, .Write, .Create, .Trunc}, Permissions_Default_File) +} + +/* + `open` is a generalized open call, which defaults to opening for reading. + If the file does not exist, and the `{.Create}` flag is passed, it is created with the permissions `perm`, + and please note that the containing directory must exist otherwise and an error will be returned. + If successful, a `^File` is return which can be used for I/O. + And error is returned if any is encountered. +*/ +@(require_results) +open :: proc(name: string, flags := File_Flags{.Read}, perm := Permissions_Default) -> (^File, Error) { + return _open(name, flags, perm) +} + +// @(require_results) +// open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) { +// if buffer_size == 0 { +// return _open(name, flags, perm) +// } +// return _open_buffered(name, buffer_size, flags, perm) +// } + +/* + `new_file` returns a new `^File` with the given file descriptor `handle` and `name`. + The return value will only be `nil` IF the `handle` is not a valid file descriptor. +*/ +@(require_results) +new_file :: proc(handle: uintptr, name: string) -> ^File { + file, err := _new_file(handle, name, file_allocator()) + if err != nil { + panic(error_string(err)) + } + return file +} + +/* + `clone` returns a new `^File` based on the passed file `f` with the same underlying file descriptor. +*/ +@(require_results) +clone :: proc(f: ^File) -> (^File, Error) { + return _clone(f) +} + +/* + `fd` returns the file descriptor of the file `f` passed. If the file is not valid, an invalid handle will be returned. +*/ +@(require_results) +fd :: proc(f: ^File) -> uintptr { + return _fd(f) +} + +/* + `name` returns the name of the file. The lifetime of this string lasts as long as the file handle itself. +*/ +@(require_results) +name :: proc(f: ^File) -> string { + return _name(f) +} + +/* + Close a file and its stream. + + Any further use of the file or its stream should be considered to be in the + same class of bugs as a use-after-free. +*/ +close :: proc(f: ^File) -> Error { + if f != nil { + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Close, nil, 0, nil, runtime.nil_allocator()) + return err + } + return nil +} + +/* + seek sets the offsets for the next read or write on a file to a specified `offset`, + according to what `whence` is set. + `.Start` is relative to the origin of the file. + `.Current` is relative to the current offset. + `.End` is relative to the end. + It returns the new offset and an error, if any is encountered. + Prefer `read_at` or `write_at` if the offset does not want to be changed. + +*/ +seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + return f.stream.procedure(f, .Seek, nil, offset, whence, runtime.nil_allocator()) + } + return 0, .Invalid_File +} + +/* + `read` reads up to len(p) bytes from the file `f`, and then stores them in `p`. + It returns the number of bytes read and an error, if any is encountered. + At the end of a file, it returns `0, io.EOF`. +*/ +read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read, p, 0, nil, runtime.nil_allocator()) + return int(n64), err + } + return 0, .Invalid_File +} + +/* + `read_at` reads up to len(p) bytes from the file `f` at the byte offset `offset`, and then stores them in `p`. + It returns the number of bytes read and an error, if any is encountered. + `read_at` always returns a non-nil error when `n < len(p)`. + At the end of a file, the error is `io.EOF`. +*/ +read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err + } + return 0, .Invalid_File +} + +/* + `write` writes `len(p)` bytes from `p` to the file `f`. It returns the number of bytes written to + and an error, if any is encountered. + `write` returns a non-nil error when `n != len(p)`. +*/ +write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write, p, 0, nil, runtime.nil_allocator()) + return int(n64), err + } + return 0, .Invalid_File +} + +/* + `write_at` writes `len(p)` bytes from `p` to the file `f` starting at byte offset `offset`. + It returns the number of bytes written to and an error, if any is encountered. + `write_at` returns a non-nil error when `n != len(p)`. +*/ +write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err + } + return 0, .Invalid_File +} + +/* + `file_size` returns the length of the file `f` in bytes and an error, if any is encountered. +*/ +file_size :: proc(f: ^File) -> (n: i64, err: Error) { + if f != nil { + if f.stream.procedure == nil { + return 0, .Unsupported + } + n, err = f.stream.procedure(f, .Size, nil, 0, nil, runtime.nil_allocator()) + if err == .Unsupported { + n = 0 + curr := seek(f, 0, .Current) or_return + end := seek(f, 0, .End) or_return + seek(f, curr, .Start) or_return + n = end + } + return + } + return 0, .Invalid_File +} + +/* + `flush` flushes a file `f` +*/ +flush :: proc(f: ^File) -> Error { + if f != nil { + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Flush, nil, 0, nil, runtime.nil_allocator()) + return err + } + return nil +} + +/* + `sync` commits the current contents of the file `f` to stable storage. + This usually means flushing the file system's in-memory copy to disk. +*/ +sync :: proc(f: ^File) -> Error { + return _sync(f) +} + +/* + `truncate` changes the size of the file `f` to `size` in bytes. + This can be used to shorten or lengthen a file. + It does not change the "offset" of the file. +*/ +truncate :: proc(f: ^File, size: i64) -> Error { + return _truncate(f, size) +} + +/* + `remove` removes a named file or (empty) directory. +*/ +remove :: proc(name: string) -> Error { + return _remove(name) +} + +/* + `rename` renames (moves) `old_path` to `new_path`. +*/ +rename :: proc(old_path, new_path: string) -> Error { + return _rename(old_path, new_path) +} + +/* + `link` creates a `new_name` as a hard link to the `old_name` file. +*/ +link :: proc(old_name, new_name: string) -> Error { + return _link(old_name, new_name) +} + +/* + `symlink` creates a `new_name` as a symbolic link to the `old_name` file. +*/ +symlink :: proc(old_name, new_name: string) -> Error { + return _symlink(old_name, new_name) +} + +/* + `read_link` returns the destinction of the named symbolic link `name`. +*/ +read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) { + return _read_link(name,allocator) +} + + +chdir :: change_directory + +/* + Changes the current working directory to the named directory. +*/ +change_directory :: proc(name: string) -> Error { + return _chdir(name) +} + +chmod :: change_mode + +/* + Changes the mode/permissions of the named file to `mode`. + If the file is a symbolic link, it changes the mode of the link's target. + + On Windows, only `{.Write_User}` of `mode` is used, and controls whether or not + the file has a read-only attribute. Use `{.Read_User}` for a read-only file and + `{.Read_User, .Write_User}` for a readable & writable file. +*/ +change_mode :: proc(name: string, mode: Permissions) -> Error { + return _chmod(name, mode) +} + +chown :: change_owner + +/* + Changes the numeric `uid` and `gid` of a named file. If the file is a symbolic link, + it changes the `uid` and `gid` of the link's target. + + On Windows, it always returns an error. +*/ +change_owner :: proc(name: string, uid, gid: int) -> Error { + return _chown(name, uid, gid) +} + +fchdir :: fchange_directory + +/* + Changes the current working directory to the file, which must be a directory. +*/ +fchange_directory :: proc(f: ^File) -> Error { + return _fchdir(f) +} + +fchmod :: fchange_mode + +/* + Changes the current `mode` permissions of the file `f`. +*/ +fchange_mode :: proc(f: ^File, mode: Permissions) -> Error { + return _fchmod(f, mode) +} + +fchown :: fchange_owner + +/* + Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link, + it changes the `uid` and `gid` of the link's target. + + On Windows, it always returns an error. +*/ +fchange_owner :: proc(f: ^File, uid, gid: int) -> Error { + return _fchown(f, uid, gid) +} + + +lchown :: change_owner_do_not_follow_links + +/* + Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link, + it changes the `uid` and `gid` of the lin itself. + + On Windows, it always returns an error. +*/ +change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error { + return _lchown(name, uid, gid) +} + +chtimes :: change_times + +/* + Changes the access `atime` and modification `mtime` times of a named file. +*/ +change_times :: proc(name: string, atime, mtime: time.Time) -> Error { + return _chtimes(name, atime, mtime) +} + +fchtimes :: fchange_times + +/* + Changes the access `atime` and modification `mtime` times of the file `f`. +*/ +fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error { + return _fchtimes(f, atime, mtime) +} + +/* + `exists` returns whether or not a named file exists. +*/ +@(require_results) +exists :: proc(path: string) -> bool { + return _exists(path) +} + +/* + `is_file` returns whether or not the type of a named file is a `File_Type.Regular` file. +*/ +@(require_results) +is_file :: proc(path: string) -> bool { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + fi, err := stat(path, temp_allocator) + if err != nil { + return false + } + return fi.type == .Regular +} + +is_dir :: is_directory + +/* + Returns whether or not the type of a named file is a `File_Type.Directory` file. +*/ +@(require_results) +is_directory :: proc(path: string) -> bool { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + fi, err := stat(path, temp_allocator) + if err != nil { + return false + } + return fi.type == .Directory +} + +/* + `copy_file` copies a file from `src_path` to `dst_path` and returns an error if any was encountered. +*/ +@(require_results) +is_tty :: proc "contextless" (f: ^File) -> bool { + return _is_tty(f) +} + +copy_file :: proc(dst_path, src_path: string) -> Error { + when #defined(_copy_file_native) { + return _copy_file_native(dst_path, src_path) + } else { + return _copy_file(dst_path, src_path) + } +} + +@(private) +_copy_file :: proc(dst_path, src_path: string) -> Error { + src := open(src_path) or_return + defer close(src) + + info := fstat(src, file_allocator()) or_return + defer file_info_delete(info, file_allocator()) + if info.type == .Directory { + return .Invalid_File + } + + dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & Permissions_All) or_return + defer close(dst) + + _, err := io.copy(to_writer(dst), to_reader(src)) + return err +} \ No newline at end of file diff --git a/core/os/file_js.odin b/core/os/file_js.odin new file mode 100644 index 000000000..aef811c11 --- /dev/null +++ b/core/os/file_js.odin @@ -0,0 +1,115 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" +import "core:io" +import "core:time" + +File_Impl :: struct { + file: File, +} + +_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) { + return nil, .Unsupported +} + +_new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) { + return nil, .Unsupported +} + +_clone :: proc(f: ^File) -> (clone: ^File, err: Error) { + return nil, .Unsupported +} + +_close :: proc(f: ^File_Impl) -> (err: Error) { + return .Unsupported +} + +_fd :: proc(f: ^File) -> uintptr { + return 0 +} + +_is_tty :: proc "contextless" (f: ^File) -> bool { + return true +} + +_name :: proc(f: ^File) -> string { + return "" +} + +_sync :: proc(f: ^File) -> Error { + return .Unsupported +} + +_truncate :: proc(f: ^File, size: i64) -> Error { + return .Unsupported +} + +_remove :: proc(name: string) -> Error { + return .Unsupported +} + +_rename :: proc(old_path, new_path: string) -> Error { + return .Unsupported +} + +_link :: proc(old_name, new_name: string) -> Error { + return .Unsupported +} + +_symlink :: proc(old_name, new_name: string) -> Error { + return .Unsupported +} + +_read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, err: Error) { + return "", .Unsupported +} + +_chdir :: proc(name: string) -> Error { + return .Unsupported +} + +_fchdir :: proc(f: ^File) -> Error { + return .Unsupported +} + +_fchmod :: proc(f: ^File, mode: Permissions) -> Error { + return .Unsupported +} + +_chmod :: proc(name: string, mode: Permissions) -> Error { + return .Unsupported +} + +_fchown :: proc(f: ^File, uid, gid: int) -> Error { + return .Unsupported +} + +_chown :: proc(name: string, uid, gid: int) -> Error { + return .Unsupported +} + +_lchown :: proc(name: string, uid, gid: int) -> Error { + return .Unsupported +} + +_chtimes :: proc(name: string, atime, mtime: time.Time) -> Error { + return .Unsupported +} + +_fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error { + return .Unsupported +} + +_exists :: proc(path: string) -> bool { + return false +} + +_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { + return 0, .Empty +} \ No newline at end of file diff --git a/core/os/os2/file_linux.odin b/core/os/file_linux.odin similarity index 85% rename from core/os/os2/file_linux.odin rename to core/os/file_linux.odin index a1ead7f9f..6b9540235 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/file_linux.odin @@ -1,11 +1,12 @@ #+private -package os2 +package os import "base:runtime" import "core:io" import "core:time" import "core:sync" import "core:sys/linux" +import "core:sys/posix" // Most implementations will EINVAL at some point when doing big writes. // In practice a read/write call would probably never read/write these big buffers all at once, @@ -29,24 +30,21 @@ _stdin := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stdout := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stderr := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } @init -_standard_stream_init :: proc() { - new_std :: proc(impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File { +_standard_stream_init :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File { impl.file.impl = impl impl.fd = linux.Fd(fd) impl.allocator = runtime.nil_allocator() @@ -55,7 +53,6 @@ _standard_stream_init :: proc() { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -65,7 +62,7 @@ _standard_stream_init :: proc() { stderr = new_std(&files[2], 2, "/proc/self/fd/2") } -_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) { +_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) name_cstr := clone_to_cstring(name, temp_allocator) or_return @@ -86,9 +83,10 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err if .Excl in flags { sys_flags += {.EXCL} } if .Sync in flags { sys_flags += {.DSYNC} } if .Trunc in flags { sys_flags += {.TRUNC} } + if .Non_Blocking in flags { sys_flags += {.NONBLOCK} } if .Inheritable in flags { sys_flags -= {.CLOEXEC} } - fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)u32(perm)) + fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)transmute(u32)perm) if errno != .NONE { return nil, _get_platform_error(errno) } @@ -109,7 +107,6 @@ _new_file :: proc(fd: uintptr, _: string, allocator: runtime.Allocator) -> (f: ^ data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -132,7 +129,7 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) { @(require_results) -_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) { +_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) { assert(buffer_size > 0) f, err = _open(name, flags, perm) if f != nil && err == nil { @@ -178,6 +175,17 @@ _fd :: proc(f: ^File) -> uintptr { return uintptr(impl.fd) } +_is_tty :: proc "contextless" (f: ^File) -> bool { + if f == nil || f.impl == nil { + return false + } + impl := (^File_Impl)(f.impl) + + // TODO: Replace `posix.isatty` with `tcgetattr(fd, &termios) == 0` + is_tty := posix.isatty(posix.FD(impl.fd)) + return bool(is_tty) +} + _name :: proc(f: ^File) -> string { return (^File_Impl)(f.impl).name if f != nil && f.impl != nil else "" } @@ -198,7 +206,7 @@ _seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, er case .NONE: return n, nil case: - return -1, _get_platform_error(errno) + return 0, _get_platform_error(errno) } } @@ -209,7 +217,7 @@ _read :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { n, errno := linux.read(f.fd, p[:min(len(p), MAX_RW)]) if errno != .NONE { - return -1, _get_platform_error(errno) + return 0, _get_platform_error(errno) } return i64(n), io.Error.EOF if n == 0 else nil } @@ -223,7 +231,7 @@ _read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { } n, errno := linux.pread(f.fd, p[:min(len(p), MAX_RW)], offset) if errno != .NONE { - return -1, _get_platform_error(errno) + return 0, _get_platform_error(errno) } if n == 0 { return 0, .EOF @@ -269,13 +277,12 @@ _write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (nt: i64, err: Error return } +@(no_sanitize_memory) _file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) { - // TODO: Identify 0-sized "pseudo" files and return No_Size. This would - // eliminate the need for the _read_entire_pseudo_file procs. - s: linux.Stat = --- - errno := linux.fstat(f.fd, &s) + s: linux.Statx = --- + errno := linux.statx(f.fd, "", {.EMPTY_PATH}, {.SIZE, .TYPE}, &s) if errno != .NONE { - return -1, _get_platform_error(errno) + return 0, _get_platform_error(errno) } if s.mode & linux.S_IFMT == linux.S_IFREG { @@ -368,15 +375,15 @@ _fchdir :: proc(f: ^File) -> Error { return _get_platform_error(linux.fchdir(impl.fd)) } -_chmod :: proc(name: string, mode: int) -> Error { +_chmod :: proc(name: string, mode: Permissions) -> Error { temp_allocator := TEMP_ALLOCATOR_GUARD({}) name_cstr := clone_to_cstring(name, temp_allocator) or_return - return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)(u32(mode)))) + return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)transmute(u32)mode)) } -_fchmod :: proc(f: ^File, mode: int) -> Error { +_fchmod :: proc(f: ^File, mode: Permissions) -> Error { impl := (^File_Impl)(f.impl) - return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode)))) + return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)transmute(u32)mode)) } // NOTE: will throw error without super user priviledges @@ -475,89 +482,77 @@ _read_entire_pseudo_file_cstring :: proc(name: cstring, allocator: runtime.Alloc } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } - return 0, .Empty + return 0, .Unsupported } @(private="package") -_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } - return 0, .Empty + return 0, .Unsupported } diff --git a/core/os/os2/file_posix.odin b/core/os/file_posix.odin similarity index 85% rename from core/os/os2/file_posix.odin rename to core/os/file_posix.odin index 2d74618ee..006f25e11 100644 --- a/core/os/os2/file_posix.odin +++ b/core/os/file_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" @@ -25,8 +25,8 @@ File_Impl :: struct { } @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File { impl.file.impl = impl impl.fd = fd impl.allocator = runtime.nil_allocator() @@ -36,7 +36,6 @@ init_std_files :: proc() { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -46,7 +45,7 @@ init_std_files :: proc() { stderr = new_std(&files[2], posix.STDERR_FILENO, "/dev/stderr") } -_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) { +_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) { if name == "" { err = .Invalid_Path return @@ -62,17 +61,18 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err } } - if .Append in flags { sys_flags += {.APPEND} } - if .Create in flags { sys_flags += {.CREAT} } - if .Excl in flags { sys_flags += {.EXCL} } - if .Sync in flags { sys_flags += {.DSYNC} } - if .Trunc in flags { sys_flags += {.TRUNC} } - if .Inheritable in flags { sys_flags -= {.CLOEXEC} } + if .Append in flags { sys_flags += {.APPEND} } + if .Create in flags { sys_flags += {.CREAT} } + if .Excl in flags { sys_flags += {.EXCL} } + if .Sync in flags { sys_flags += {.DSYNC} } + if .Trunc in flags { sys_flags += {.TRUNC} } + if .Non_Blocking in flags { sys_flags += {.NONBLOCK} } + if .Inheritable in flags { sys_flags -= {.CLOEXEC} } temp_allocator := TEMP_ALLOCATOR_GUARD({}) cname := clone_to_cstring(name, temp_allocator) or_return - fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(perm)) + fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(transmute(u32)perm)) if fd < 0 { err = _get_platform_error() return @@ -110,7 +110,6 @@ __new_file :: proc(handle: posix.FD, allocator: runtime.Allocator) -> ^File { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -162,6 +161,13 @@ __fd :: proc(f: ^File) -> posix.FD { return -1 } +_is_tty :: proc "contextless" (f: ^File) -> bool { + context = runtime.default_context() + fd := _fd(f) + is_tty := posix.isatty(posix.FD(fd)) + return bool(is_tty) +} + _name :: proc(f: ^File) -> string { if f != nil && f.impl != nil { return (^File_Impl)(f.impl).name @@ -284,17 +290,17 @@ _fchdir :: proc(f: ^File) -> Error { return nil } -_fchmod :: proc(f: ^File, mode: int) -> Error { - if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(mode)) != .OK { +_fchmod :: proc(f: ^File, mode: Permissions) -> Error { + if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK { return _get_platform_error() } return nil } -_chmod :: proc(name: string, mode: int) -> (err: Error) { +_chmod :: proc(name: string, mode: Permissions) -> (err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) cname := clone_to_cstring(name, temp_allocator) or_return - if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(mode)) != .OK { + if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK { return _get_platform_error() } return nil @@ -371,7 +377,7 @@ _exists :: proc(path: string) -> bool { return posix.access(cpath) == .OK } -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) fd := f.fd @@ -382,12 +388,14 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, } to_read := uint(min(len(p), MAX_RW)) - n = i64(posix.read(fd, raw_data(p), to_read)) + _n := i64(posix.read(fd, raw_data(p), to_read)) switch { - case n == 0: + case _n == 0: err = .EOF - case n < 0: + case _n < 0: err = .Unknown + case: + n = _n } return @@ -402,12 +410,14 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, } to_read := uint(min(len(p), MAX_RW)) - n = i64(posix.pread(fd, raw_data(p), to_read, posix.off_t(offset))) + _n := i64(posix.pread(fd, raw_data(p), to_read, posix.off_t(offset))) switch { - case n == 0: + case _n == 0: err = .EOF - case n < 0: + case _n < 0: err = .Unknown + case: + n = _n } return @@ -460,15 +470,18 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, return } - n = i64(posix.lseek(fd, posix.off_t(offset), posix.Whence(whence))) - if n < 0 { + _n := i64(posix.lseek(fd, posix.off_t(offset), posix.Whence(whence))) + if _n < 0 { #partial switch posix.get_errno() { case .EINVAL: err = .Invalid_Offset case: err = .Unknown } + return } + + n = _n return case .Size: @@ -482,19 +495,20 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, return case .Flush: - ferr := _sync(&f.file) - err = error_to_io_error(ferr) + err = _sync(&f.file) return case .Close, .Destroy: - ferr := _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return case: - return 0, .Empty + return 0, .Unsupported } } diff --git a/core/os/file_posix_darwin.odin b/core/os/file_posix_darwin.odin new file mode 100644 index 000000000..5522124ae --- /dev/null +++ b/core/os/file_posix_darwin.odin @@ -0,0 +1,46 @@ +#+private +package os + +import "base:runtime" + +import "core:sys/darwin" +import "core:sys/posix" + +_posix_absolute_path :: proc(fd: posix.FD, name: string, allocator: runtime.Allocator) -> (path: cstring, err: Error) { + F_GETPATH :: 50 + + buf: [posix.PATH_MAX]byte + if posix.fcntl(fd, posix.FCNTL_Cmd(F_GETPATH), &buf) != 0 { + err = _get_platform_error() + return + } + + return clone_to_cstring(string(cstring(&buf[0])), allocator) +} + +_copy_file_native :: proc(dst_path, src_path: string) -> (err: Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + + csrc := clone_to_cstring(src_path, temp_allocator) or_return + cdst := clone_to_cstring(dst_path, temp_allocator) or_return + + // Disallow directories, as specified by the generic implementation. + + stat: posix.stat_t + if posix.stat(csrc, &stat) != .OK { + err = _get_platform_error() + return + } + + if posix.S_ISDIR(stat.st_mode) { + err = .Invalid_File + return + } + + ret := darwin.copyfile(csrc, cdst, nil, darwin.COPYFILE_ALL) + if ret < 0 { + err = _get_platform_error() + } + + return +} \ No newline at end of file diff --git a/core/os/os2/file_posix_freebsd.odin b/core/os/file_posix_freebsd.odin similarity index 99% rename from core/os/os2/file_posix_freebsd.odin rename to core/os/file_posix_freebsd.odin index 05d031930..4ed9ecc1e 100644 --- a/core/os/os2/file_posix_freebsd.odin +++ b/core/os/file_posix_freebsd.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/file_posix_netbsd.odin b/core/os/file_posix_netbsd.odin similarity index 97% rename from core/os/os2/file_posix_netbsd.odin rename to core/os/file_posix_netbsd.odin index f96c227ba..791836c00 100644 --- a/core/os/os2/file_posix_netbsd.odin +++ b/core/os/file_posix_netbsd.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/file_posix_other.odin b/core/os/file_posix_other.odin similarity index 86% rename from core/os/os2/file_posix_other.odin rename to core/os/file_posix_other.odin index d2946098b..6430c9fb6 100644 --- a/core/os/os2/file_posix_other.odin +++ b/core/os/file_posix_other.odin @@ -1,6 +1,6 @@ #+private #+build openbsd -package os2 +package os import "base:runtime" @@ -8,7 +8,7 @@ import "core:sys/posix" _posix_absolute_path :: proc(fd: posix.FD, name: string, allocator: runtime.Allocator) -> (path: cstring, err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - cname := clone_to_cstring(name, temp_allocator) + cname := clone_to_cstring(name, temp_allocator) or_return buf: [posix.PATH_MAX]byte path = posix.realpath(cname, raw_data(buf[:])) diff --git a/core/os/file_stream.odin b/core/os/file_stream.odin new file mode 100644 index 000000000..cee1bef47 --- /dev/null +++ b/core/os/file_stream.odin @@ -0,0 +1,89 @@ +package os + +import "base:intrinsics" +import "base:runtime" +import "core:io" + +// A subset of the io.Stream_Mode with added File specific modes +File_Stream_Mode :: enum { + Close, + Flush, + Read, + Read_At, + Write, + Write_At, + Seek, + Size, + Destroy, + Query, // query what modes are available on `io.Stream` + + Fstat, // File specific (not available on io.Stream) +} +#assert(intrinsics.type_is_superset_of(File_Stream_Mode, io.Stream_Mode)) + +// Superset interface of io.Stream_Proc with the added `runtime.Allocator` parameter needed for the Fstat mode +File_Stream_Proc :: #type proc( + stream_data: rawptr, + mode: File_Stream_Mode, + p: []byte, + offset: i64, + whence: io.Seek_From, + allocator: runtime.Allocator, +) -> (n: i64, err: Error) + +File_Stream :: struct { + procedure: File_Stream_Proc, + data: rawptr, +} + + +// Converts a file `f` into an `io.Stream` +to_stream :: proc(f: ^File) -> (s: io.Stream) { + if f != nil { + assert(f.stream.procedure != nil) + s = { + file_io_stream_proc, + f, + } + } + return +} + +/* + This is an alias of `to_stream` which converts a file `f` to an `io.Stream`. + It can be useful to indicate what the stream is meant to be used for as a writer, + even if it has no logical difference. +*/ +to_writer :: to_stream + +/* + This is an alias of `to_stream` which converts a file `f` to an `io.Stream`. + It can be useful to indicate what the stream is meant to be used for as a reader, + even if it has no logical difference. +*/ +to_reader :: to_stream + + +@(private="package") +file_io_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { + f := (^File)(stream_data) + + file_stream_mode := transmute(File_Stream_Mode)mode + + ferr: Error + n, ferr = f.stream.procedure(f, file_stream_mode, p, offset, whence, runtime.nil_allocator()) + err = error_to_io_error(ferr) + return +} + +@(private="package") +file_stream_fstat_utility :: proc(f: ^File_Impl, p: []byte, allocator: runtime.Allocator) -> (err: Error) { + fi: File_Info + if len(p) >= size_of(fi) { + fi, err = _fstat(&f.file, allocator) + runtime.mem_copy_non_overlapping(raw_data(p), &fi, size_of(fi)) + } else { + err = .Short_Buffer + } + return +} \ No newline at end of file diff --git a/core/os/file_util.odin b/core/os/file_util.odin new file mode 100644 index 000000000..94e1a5841 --- /dev/null +++ b/core/os/file_util.odin @@ -0,0 +1,276 @@ +package os + +import "base:runtime" +import "core:strconv" +import "core:unicode/utf8" + +/* + `write_string` writes a string `s` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ +write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) { + return write(f, transmute([]byte)s) +} + +/* + `write_strings` writes a variadic list of strings `strings` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ +write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) { + for s in strings { + m: int + m, err = write_string(f, s) + n += m + if err != nil { + return + } + } + return +} +/* + `write_byte` writes a byte `b` to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ +write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) { + return write(f, []byte{b}) +} + +/* + `write_rune` writes a rune `r` as an UTF-8 encoded string to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ +write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { + if r < utf8.RUNE_SELF { + return write_byte(f, byte(r)) + } + + b: [4]byte + b, n = utf8.encode_rune(r) + return write(f, b[:n]) +} + +/* + `write_encoded_rune` writes a rune `r` as an UTF-8 encoded string which with escaped control codes to file `f`. + Returns the number of bytes written and an error, if any is encountered. +*/ +write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { + wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool { + n^ += m + if merr != nil { + err^ = merr + return true + } + return false + } + + if wrap(write_byte(f, '\''), &n, &err) { return } + + switch r { + case '\a': if wrap(write_string(f, "\\a"), &n, &err) { return } + case '\b': if wrap(write_string(f, "\\b"), &n, &err) { return } + case '\e': if wrap(write_string(f, "\\e"), &n, &err) { return } + case '\f': if wrap(write_string(f, "\\f"), &n, &err) { return } + case '\n': if wrap(write_string(f, "\\n"), &n, &err) { return } + case '\r': if wrap(write_string(f, "\\r"), &n, &err) { return } + case '\t': if wrap(write_string(f, "\\t"), &n, &err) { return } + case '\v': if wrap(write_string(f, "\\v"), &n, &err) { return } + case: + if r < 32 { + if wrap(write_string(f, "\\x"), &n, &err) { return } + b: [2]byte + s := strconv.write_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil) + switch len(s) { + case 0: if wrap(write_string(f, "00"), &n, &err) { return } + case 1: if wrap(write_rune(f, '0'), &n, &err) { return } + case 2: if wrap(write_string(f, s), &n, &err) { return } + } + } else { + if wrap(write_rune(f, r), &n, &err) { return } + } + } + _ = wrap(write_byte(f, '\''), &n, &err) + return +} + +/* + `write_ptr` is a utility procedure that writes the bytes points at `data` with length `len`. + + It is equivalent to: `write(f, ([^]byte)(data)[:len])` +*/ +write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { + return write(f, ([^]byte)(data)[:len]) +} + +/* + `read_ptr` is a utility procedure that reads the bytes points at `data` with length `len`. + + It is equivalent to: `read(f, ([^]byte)(data)[:len])` +*/ +read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { + return read(f, ([^]byte)(data)[:len]) +} + + +/* + `write_slice` is a utility procedure that writes the bytes points at `slice`. + + It is equivalent to: `write(f, ([^]byte)(raw_data(slice))[:len(slice)*size_of(slice[0])])` +*/ +write_slice :: proc(f: ^File, slice: $S/[]$T) -> (n: int, err: Error) { + return write(f, ([^]byte)(raw_data(slice))[:len(slice)*size_of(slice[0])]) +} + +/* + `read_slice` is a utility procedure that writes the bytes points at `slice`. + + It is equivalent to: `read(f, ([^]byte)(raw_data(slice))[:len(slice)*size_of(slice[0])])` +*/ +read_slice :: proc(f: ^File, slice: $S/[]$T) -> (n: int, err: Error) { + return read(f, ([^]byte)(raw_data(slice))[:len(slice)*size_of(slice[0])]) +} + + + +/* + `read_at_least` reads from `f` into `buf` until it has read at least `min` bytes. + It returns the number of bytes copied and an error if fewer bytes were read. + The error is only an `io.EOF` if no bytes were read. +*/ +read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) { + if len(buf) < min { + return 0, .Short_Buffer + } + nn := max(int) + for nn > 0 && n < min && err == nil { + nn, err = read(f, buf[n:]) + n += nn + } + if n >= min { + err = nil + } + return +} + +/* + `read_full` reads exactly `len(buf)` bytes from `f` into `buf`. + It returns the number of bytes copied and an error if fewer bytes were read. + The error is only an `io.EOF` if no bytes were read. + + It is equivalent to `read_at_least(f, buf, len(buf))`. +*/ +read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) { + return read_at_least(f, buf, len(buf)) +} + + + +read_entire_file :: proc{ + read_entire_file_from_path, + read_entire_file_from_file, +} + +/* + `read_entire_file_from_path` reads the entire named file `name` into memory allocated with `allocator`. + A slice of bytes and an error is returned, if any error is encountered. +*/ +@(require_results) +read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) { + f, ferr := open(name) + if ferr != nil { + return nil, ferr + } + defer close(f) + return read_entire_file_from_file(f=f, allocator=allocator, loc=loc) +} + +/* + `read_entire_file_from_file` reads the entire file `f` into memory allocated with `allocator`. + A slice of bytes and an error is returned, if any error is encountered. +*/ +@(require_results) +read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) { + size: int + has_size := false + if size64, serr := file_size(f); serr == nil { + if i64(int(size64)) == size64 { + has_size = true + size = int(size64) + } + } + + if has_size && size > 0 { + total: int + data = make([]byte, size, allocator, loc) or_return + for total < len(data) { + n: int + n, err = read(f, data[total:]) + total += n + if err != nil { + if err == .EOF { + err = nil + } + data = data[:total] + break + } + } + return + } else { + buffer: [1024]u8 + out_buffer := make([dynamic]u8, 0, 0, allocator, loc) or_return + for { + n: int + n, err = read(f, buffer[:]) + if _, aerr := append_elems(&out_buffer, ..buffer[:n], loc=loc); aerr != nil { + return out_buffer[:], aerr + } + if err != nil { + if err == .EOF || err == .Broken_Pipe { + err = nil + } + data = out_buffer[:] + return + } + } + } +} + +/* + `write_entire_file` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ +write_entire_file :: proc{ + write_entire_file_from_bytes, + write_entire_file_from_string, +} + +/* + `write_entire_file_from_bytes` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ +@(require_results) +write_entire_file_from_bytes :: proc(name: string, data: []byte, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error { + flags := O_WRONLY|O_CREATE + if truncate { + flags |= O_TRUNC + } + f := open(name, flags, perm) or_return + _, err := write(f, data) + if cerr := close(f); cerr != nil && err == nil { + err = cerr + } + return err +} + + + +/* + `write_entire_file_from_string` writes the contents of `data` into named file `name`. + It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default. + An error is returned if any is encountered. +*/ +@(require_results) +write_entire_file_from_string :: proc(name: string, data: string, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error { + return write_entire_file(name, transmute([]byte)data, perm, truncate) +} diff --git a/core/os/os2/file_wasi.odin b/core/os/file_wasi.odin similarity index 91% rename from core/os/os2/file_wasi.odin rename to core/os/file_wasi.odin index 0245841e3..116c237d6 100644 --- a/core/os/os2/file_wasi.odin +++ b/core/os/file_wasi.odin @@ -1,5 +1,6 @@ +#+feature global-context #+private -package os2 +package os import "base:runtime" @@ -30,8 +31,8 @@ Preopen :: struct { preopens: []Preopen @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File { impl.file.impl = impl impl.allocator = runtime.nil_allocator() impl.fd = fd @@ -40,7 +41,6 @@ init_std_files :: proc() { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -51,8 +51,8 @@ init_std_files :: proc() { } @(init) -init_preopens :: proc() { - strip_prefixes :: proc(path: string) -> string { +init_preopens :: proc "contextless" () { + strip_prefixes :: proc "contextless" (path: string) -> string { path := path loop: for len(path) > 0 { switch { @@ -69,6 +69,8 @@ init_preopens :: proc() { return path } + context = runtime.default_context() + n: int n_loop: for fd := wasi.fd_t(3); ; fd += 1 { _, err := wasi.fd_prestat_get(fd) @@ -171,7 +173,7 @@ match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) { return match.fd, relative, true } -_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) { +_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) { dir_fd, relative, ok := match_preopen(name) if !ok { return nil, .Invalid_Path @@ -183,8 +185,9 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err if .Trunc in flags { oflags += {.TRUNC} } fdflags: wasi.fdflags_t - if .Append in flags { fdflags += {.APPEND} } - if .Sync in flags { fdflags += {.SYNC} } + if .Append in flags { fdflags += {.APPEND} } + if .Sync in flags { fdflags += {.SYNC} } + if .Non_Blocking in flags { fdflags += {.NONBLOCK} } // NOTE: rights are adjusted to what this package's functions might want to call. rights: wasi.rights_t @@ -218,7 +221,6 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) - data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -270,6 +272,10 @@ __fd :: proc(f: ^File) -> wasi.fd_t { return -1 } +_is_tty :: proc "contextless" (f: ^File) -> bool { + return false +} + _name :: proc(f: ^File) -> string { if f != nil && f.impl != nil { return (^File_Impl)(f.impl).name @@ -373,11 +379,11 @@ _fchdir :: proc(f: ^File) -> Error { return .Unsupported } -_fchmod :: proc(f: ^File, mode: int) -> Error { +_fchmod :: proc(f: ^File, mode: Permissions) -> Error { return .Unsupported } -_chmod :: proc(name: string, mode: int) -> Error { +_chmod :: proc(name: string, mode: Permissions) -> Error { return .Unsupported } @@ -426,7 +432,7 @@ _exists :: proc(path: string) -> bool { return true } -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) fd := f.fd @@ -554,7 +560,11 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return + case: - return 0, .Empty + return 0, .Unsupported } } diff --git a/core/os/os2/file_windows.odin b/core/os/file_windows.odin similarity index 79% rename from core/os/os2/file_windows.odin rename to core/os/file_windows.odin index 16803f1ac..3a9e90fed 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/file_windows.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -12,30 +12,6 @@ import win32 "core:sys/windows" INVALID_HANDLE :: ~uintptr(0) -// NOTE(Jeroen): We don't translate mode flags for Linux when given to `chmod`. -// Let's not do so for Windows for `chmod` or `read_directory_iterator` either. -// They're *not* portable between Windows and non-Windows platforms. -// -// It also leads to information loss as flags like Archive, Hidden and System have no equivalent there. -// We can of course parse them so we can set the `.Symlink` and `.Directory` type, but we shouldn't pretend -// that 0o644 is meaningful when returned as a mode. -// `C:\bootmgr` as an example has attributes read only, hidden, system, archive. In no way is it sensible to replace that with 0o444. -FILE_ATTRIBUTE_READONLY :: win32.FILE_ATTRIBUTE_READONLY // 0x00000001 -FILE_ATTRIBUTE_HIDDEN :: win32.FILE_ATTRIBUTE_HIDDEN // 0x00000002 -FILE_ATTRIBUTE_SYSTEM :: win32.FILE_ATTRIBUTE_SYSTEM // 0x00000004 -FILE_ATTRIBUTE_DIRECTORY :: win32.FILE_ATTRIBUTE_DIRECTORY // 0x00000010 -FILE_ATTRIBUTE_ARCHIVE :: win32.FILE_ATTRIBUTE_ARCHIVE // 0x00000020 -FILE_ATTRIBUTE_DEVICE :: win32.FILE_ATTRIBUTE_DEVICE // 0x00000040 -FILE_ATTRIBUTE_NORMAL :: win32.FILE_ATTRIBUTE_NORMAL // 0x00000080 -FILE_ATTRIBUTE_TEMPORARY :: win32.FILE_ATTRIBUTE_TEMPORARY // 0x00000100 -FILE_ATTRIBUTE_SPARSE_FILE :: win32.FILE_ATTRIBUTE_SPARSE_FILE // 0x00000200 -FILE_ATTRIBUTE_REPARSE_Point :: win32.FILE_ATTRIBUTE_REPARSE_Point // 0x00000400 -FILE_ATTRIBUTE_REPARSE_POINT :: win32.FILE_ATTRIBUTE_REPARSE_POINT // 0x00000400 -FILE_ATTRIBUTE_COMPRESSED :: win32.FILE_ATTRIBUTE_COMPRESSED // 0x00000800 -FILE_ATTRIBUTE_OFFLINE :: win32.FILE_ATTRIBUTE_OFFLINE // 0x00001000 -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :: win32.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED // 0x00002000 -FILE_ATTRIBUTE_ENCRYPTED :: win32.FILE_ATTRIBUTE_ENCRYPTED // 0x00004000 - _ERROR_BAD_NETPATH :: 53 MAX_RW :: 1<<30 @@ -66,8 +42,8 @@ File_Impl :: struct { } @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, code: u32, name: string) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, code: u32, name: string) -> ^File { impl.file.impl = impl impl.allocator = runtime.nil_allocator() @@ -89,7 +65,6 @@ init_std_files :: proc() { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -100,11 +75,11 @@ init_std_files :: proc() { stderr = new_std(&files[2], win32.STD_ERROR_HANDLE, "") } -_handle :: proc(f: ^File) -> win32.HANDLE { +_handle :: proc "contextless" (f: ^File) -> win32.HANDLE { return win32.HANDLE(_fd(f)) } -_open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: uintptr, err: Error) { +_open_internal :: proc(name: string, flags: File_Flags, perm: Permissions) -> (handle: uintptr, err: Error) { if len(name) == 0 { err = .Not_Exist return @@ -145,13 +120,17 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u } attrs: u32 = win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS - if u32(perm) & FILE_ATTRIBUTE_NORMAL == 0 { + if .Write_User not_in perm { attrs = win32.FILE_ATTRIBUTE_READONLY if create_mode == win32.CREATE_ALWAYS { // NOTE(bill): Open has just asked to create a file in read-only mode. // If the file already exists, to make it akin to a *nix open call, // the call preserves the existing permissions. - h := win32.CreateFileW(path, access, share_mode, &sa, win32.TRUNCATE_EXISTING, win32.FILE_ATTRIBUTE_NORMAL, nil) + nix_attrs := win32.FILE_ATTRIBUTE_NORMAL + if .Non_Blocking in flags { + nix_attrs |= win32.FILE_FLAG_OVERLAPPED + } + h := win32.CreateFileW(path, access, share_mode, &sa, win32.TRUNCATE_EXISTING, nix_attrs, nil) if h == win32.INVALID_HANDLE { switch e := win32.GetLastError(); e { case win32.ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, win32.ERROR_PATH_NOT_FOUND: @@ -165,6 +144,10 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u } } + if .Non_Blocking in flags { + attrs |= win32.FILE_FLAG_OVERLAPPED + } + h := win32.CreateFileW(path, access, share_mode, &sa, create_mode, attrs, nil) if h == win32.INVALID_HANDLE { return 0, _get_platform_error() @@ -173,7 +156,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u } -_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) { +_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) { flags := flags if flags != nil else {.Read} handle := _open_internal(name, flags, perm) or_return return _new_file(handle, name, file_allocator()) @@ -209,14 +192,13 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) - data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @(require_results) -_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) { +_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) { assert(buffer_size > 0) flags := flags if flags != nil else {.Read} handle := _open_internal(name, flags, perm) or_return @@ -257,24 +239,29 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) { return _new_file(uintptr(clonefd), name(f), file_allocator()) } -_fd :: proc(f: ^File) -> uintptr { +_fd :: proc "contextless" (f: ^File) -> uintptr { if f == nil || f.impl == nil { return INVALID_HANDLE } return uintptr((^File_Impl)(f.impl).fd) } +_is_tty :: proc "contextless" (f: ^File) -> bool { + fd := _fd(f) + return win32.GetFileType(win32.HANDLE(fd)) == win32.FILE_TYPE_CHAR +} + _destroy :: proc(f: ^File_Impl) -> Error { if f == nil { return nil } a := f.allocator - err0 := free(f.wname, a) + err0 := free(rawptr(f.wname), a) err1 := delete(f.name, a) - err2 := free(f, a) - err3 := delete(f.r_buf, a) - err4 := delete(f.w_buf, a) + err2 := delete(f.r_buf, a) + err3 := delete(f.w_buf, a) + err4 := free(f, a) err0 or_return err1 or_return err2 or_return @@ -390,33 +377,33 @@ _read_internal :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) { handle := _handle(&f.file) - single_read_length: win32.DWORD total_read: int sync.shared_guard(&f.rw_mutex) // multiple readers if sync.guard(&f.p_mutex) { - to_read := min(win32.DWORD(length), MAX_RW) - ok: win32.BOOL - if f.kind == .Console { - n, cerr := read_console(handle, p[total_read:][:to_read]) - total_read += n - if cerr != nil { - return i64(total_read), cerr + to_read := win32.DWORD(min(length, MAX_RW)) + switch f.kind { + case .Console: + // NOTE(laytan): at least for now, just use ReadFile, it seems to work fine, + // but, there may be issues with certain situations that we need to get reproductions for. + // total_read, err = read_console(handle, p[total_read:][:to_read]) + fallthrough + case .Pipe, .File: + single_read_length: win32.DWORD + ok := win32.ReadFile(handle, &p[total_read], to_read, &single_read_length, nil) + if ok { + total_read += int(single_read_length) + } else { + err = _get_platform_error() } - } else { - ok = win32.ReadFile(handle, &p[total_read], to_read, &single_read_length, nil) } + } - if single_read_length > 0 && ok { - total_read += int(single_read_length) - } else if single_read_length == 0 && ok { - // ok and 0 bytes means EOF: - // https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file - err = .EOF - } else { - err = _get_platform_error() - } + if total_read == 0 && err == nil { + // ok and 0 bytes means EOF: + // https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file + err = .EOF } return i64(total_read), err @@ -642,7 +629,7 @@ _symlink :: proc(old_name, new_name: string) -> Error { return .Unsupported } -_open_sym_link :: proc(p: [^]u16) -> (handle: win32.HANDLE, err: Error) { +_open_sym_link :: proc(p: cstring16) -> (handle: win32.HANDLE, err: Error) { attrs := u32(win32.FILE_FLAG_BACKUP_SEMANTICS) attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT handle = win32.CreateFileW(p, 0, 0, nil, win32.OPEN_EXISTING, attrs, nil) @@ -684,7 +671,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st } - handle := _open_sym_link(raw_data(p)) or_return + handle := _open_sym_link(cstring16(raw_data(p))) or_return defer win32.CloseHandle(handle) n := win32.GetFinalPathNameByHandleW(handle, nil, 0, win32.VOLUME_NAME_DOS) @@ -695,7 +682,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) buf := make([]u16, n+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(handle, raw_data(buf), u32(len(buf)), win32.VOLUME_NAME_DOS) + n = win32.GetFinalPathNameByHandleW(handle, cstring16(raw_data(buf)), u32(len(buf)), win32.VOLUME_NAME_DOS) if n == 0 { return "", _get_platform_error() } @@ -736,7 +723,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er switch rdb.ReparseTag { case win32.IO_REPARSE_TAG_SYMLINK: rb := (^win32.SYMBOLIC_LINK_REPARSE_BUFFER)(&rdb.rest) - pb := win32.wstring(&rb.PathBuffer) + pb := ([^]u16)(&rb.PathBuffer) pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0 p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength] if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 { @@ -746,7 +733,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er case win32.IO_REPARSE_TAG_MOUNT_POINT: rb := (^win32.MOUNT_POINT_REPARSE_BUFFER)(&rdb.rest) - pb := win32.wstring(&rb.PathBuffer) + pb := ([^]u16)(&rb.PathBuffer) pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0 p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength] return _normalize_link_path(p, allocator) @@ -767,14 +754,24 @@ _fchdir :: proc(f: ^File) -> Error { return nil } -_fchmod :: proc(f: ^File, mode: int) -> Error { +_fchmod :: proc(f: ^File, mode: Permissions) -> Error { if f == nil || f.impl == nil { return nil } + d: win32.BY_HANDLE_FILE_INFORMATION + if !win32.GetFileInformationByHandle(_handle(f), &d) { + return _get_platform_error() + } + attrs := d.dwFileAttributes + if .Write_User in mode { + attrs &~= win32.FILE_ATTRIBUTE_READONLY + } else { + attrs |= win32.FILE_ATTRIBUTE_READONLY + } info: win32.FILE_BASIC_INFO - info.FileAttributes = win32.DWORD(mode) - if !win32.SetFileInformationByHandle(_handle(f), .FileBasicInfo, &info, size_of(info)) { + info.FileAttributes = attrs + if !win32.SetFileInformationByHandle(_handle(f), .FileBasicInfo, &info, size_of(d)) { return _get_platform_error() } return nil @@ -793,7 +790,7 @@ _chdir :: proc(name: string) -> Error { return nil } -_chmod :: proc(name: string, mode: int) -> Error { +_chmod :: proc(name: string, mode: Permissions) -> Error { f := open(name, {.Write}) or_return defer close(f) return _fchmod(f, mode) @@ -841,54 +838,48 @@ _exists :: proc(path: string) -> bool { } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } - return 0, .Empty + return 0, .Unsupported } @(private="package", require_results) -win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) { - ws = raw_data(win32_utf8_to_utf16(s, allocator) or_return) +win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: cstring16, err: runtime.Allocator_Error) { + ws = cstring16(raw_data(win32_utf8_to_utf16(s, allocator) or_return)) return } @@ -922,24 +913,26 @@ win32_utf8_to_utf16 :: proc(s: string, allocator: runtime.Allocator) -> (ws: []u } @(private="package", require_results) -win32_wstring_to_utf8 :: proc(s: [^]u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { - if s == nil || s[0] == 0 { +win32_wstring_to_utf8 :: proc(s: cstring16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { + if s == nil || s == "" { return "", nil } - n := 0 - for s[n] != 0 { - n += 1 - } - return win32_utf16_to_utf8(s[:n], allocator) + return win32_utf16_to_utf8(string16(s), allocator) +} + +@(private="package") +win32_utf16_to_utf8 :: proc{ + win32_utf16_string16_to_utf8, + win32_utf16_u16_to_utf8, } @(private="package", require_results) -win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { +win32_utf16_string16_to_utf8 :: proc(s: string16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { if len(s) == 0 { return } - n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), nil, 0, nil, nil) + n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil) if n == 0 { return } @@ -951,7 +944,41 @@ win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: str // will not be null terminated. text := make([]byte, n, allocator) or_return - n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), raw_data(text), n, nil, nil) + n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil) + if n1 == 0 { + delete(text, allocator) + return + } + + for i in 0.. (res: string, err: runtime.Allocator_Error) { + if len(s) == 0 { + return + } + + n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil) + if n == 0 { + return + } + + // If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated + // and will scan it to find the first null terminated character. The resulting string will + // also be null terminated. + // If N > 0 it assumes the wide string is not null terminated and the resulting string + // will not be null terminated. + text := make([]byte, n, allocator) or_return + + n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil) if n1 == 0 { delete(text, allocator) return diff --git a/core/os/os2/heap.odin b/core/os/heap.odin similarity index 86% rename from core/os/os2/heap.odin rename to core/os/heap.odin index 8f9c7680a..356e60b4d 100644 --- a/core/os/os2/heap.odin +++ b/core/os/heap.odin @@ -1,7 +1,10 @@ -package os2 +package os import "base:runtime" +/* + Returns the default `heap_allocator` for this specific platform. +*/ @(require_results) heap_allocator :: proc() -> runtime.Allocator { return runtime.Allocator{ diff --git a/core/os/heap_js.odin b/core/os/heap_js.odin new file mode 100644 index 000000000..ebc8f902d --- /dev/null +++ b/core/os/heap_js.odin @@ -0,0 +1,11 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" + +_heap_allocator_proc :: runtime.wasm_allocator_proc \ No newline at end of file diff --git a/core/os/os2/heap_linux.odin b/core/os/heap_linux.odin similarity index 87% rename from core/os/os2/heap_linux.odin rename to core/os/heap_linux.odin index 1d1f12726..69c2b6edf 100644 --- a/core/os/os2/heap_linux.odin +++ b/core/os/heap_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/heap_posix.odin b/core/os/heap_posix.odin similarity index 91% rename from core/os/os2/heap_posix.odin rename to core/os/heap_posix.odin index 1b52aed75..5bff96de6 100644 --- a/core/os/os2/heap_posix.odin +++ b/core/os/heap_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" diff --git a/core/os/os2/heap_wasi.odin b/core/os/heap_wasi.odin similarity index 87% rename from core/os/os2/heap_wasi.odin rename to core/os/heap_wasi.odin index 7da3c4845..066a43f85 100644 --- a/core/os/os2/heap_wasi.odin +++ b/core/os/heap_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/heap_windows.odin b/core/os/heap_windows.odin similarity index 99% rename from core/os/os2/heap_windows.odin rename to core/os/heap_windows.odin index 7fd4529a0..e0e62a91f 100644 --- a/core/os/os2/heap_windows.odin +++ b/core/os/heap_windows.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "core:mem" import win32 "core:sys/windows" diff --git a/core/os/os2/internal_util.odin b/core/os/internal_util.odin similarity index 99% rename from core/os/os2/internal_util.odin rename to core/os/internal_util.odin index 9616af8b0..a279e9bee 100644 --- a/core/os/os2/internal_util.odin +++ b/core/os/internal_util.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:intrinsics" import "base:runtime" diff --git a/core/os/dir_unix.odin b/core/os/old/dir_unix.odin similarity index 94% rename from core/os/dir_unix.odin rename to core/os/old/dir_unix.odin index c3dd844ef..78115cbb9 100644 --- a/core/os/dir_unix.odin +++ b/core/os/old/dir_unix.odin @@ -1,5 +1,5 @@ -#+build darwin, linux, netbsd, freebsd, openbsd, haiku -package os +#+build darwin, linux, netbsd, freebsd, openbsd +package os_old import "core:strings" diff --git a/core/os/old/dir_windows.odin b/core/os/old/dir_windows.odin new file mode 100644 index 000000000..b81787872 --- /dev/null +++ b/core/os/old/dir_windows.odin @@ -0,0 +1,114 @@ +package os_old + +import win32 "core:sys/windows" +import "core:strings" +import "base:runtime" + +@(require_results) +read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) { + @(require_results) + find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { + // Ignore "." and ".." + if d.cFileName[0] == '.' && d.cFileName[1] == 0 { + return + } + if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 { + return + } + path := strings.concatenate({base_path, `\`, win32.utf16_to_utf8(d.cFileName[:]) or_else ""}) + fi.fullpath = path + fi.name = basename(path) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + + if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { + fi.mode |= 0o444 + } else { + fi.mode |= 0o666 + } + + is_sym := false + if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 { + is_sym = false + } else { + is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT + } + + if is_sym { + fi.mode |= File_Mode_Sym_Link + } else { + if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { + fi.mode |= 0o111 | File_Mode_Dir + } + + // fi.mode |= file_type_mode(h); + } + + windows_set_file_info_times(&fi, d) + + fi.is_dir = fi.mode & File_Mode_Dir != 0 + return + } + + if fd == 0 { + return nil, ERROR_INVALID_HANDLE + } + + context.allocator = allocator + + h := win32.HANDLE(fd) + + dir_fi, _ := file_info_from_get_file_information_by_handle("", h) + if !dir_fi.is_dir { + return nil, .Not_Dir + } + + n := n + size := n + if n <= 0 { + n = -1 + size = 100 + } + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) + + wpath := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return + if len(wpath) == 0 { + return + } + + dfi := make([dynamic]File_Info, 0, size) or_return + + wpath_search := make([]u16, len(wpath)+3, context.temp_allocator) or_return + copy(wpath_search, wpath) + wpath_search[len(wpath)+0] = '\\' + wpath_search[len(wpath)+1] = '*' + wpath_search[len(wpath)+2] = 0 + + path := cleanpath_from_buf(wpath) + defer delete(path) + + find_data := &win32.WIN32_FIND_DATAW{} + find_handle := win32.FindFirstFileW(cstring16(raw_data(wpath_search)), find_data) + if find_handle == win32.INVALID_HANDLE_VALUE { + err = get_last_error() + return dfi[:], err + } + defer win32.FindClose(find_handle) + for n != 0 { + fi: File_Info + fi = find_data_to_file_info(path, find_data) + if fi.name != "" { + append(&dfi, fi) + n -= 1 + } + + if !win32.FindNextFileW(find_handle, find_data) { + e := get_last_error() + if e == ERROR_NO_MORE_FILES { + break + } + return dfi[:], e + } + } + + return dfi[:], nil +} diff --git a/core/os/old/doc.odin b/core/os/old/doc.odin new file mode 100644 index 000000000..525c0b96d --- /dev/null +++ b/core/os/old/doc.odin @@ -0,0 +1,2 @@ +// The original implementation of `core:os`, to be removed in Q2 2026. +package os_old \ No newline at end of file diff --git a/core/os/old/env_windows.odin b/core/os/old/env_windows.odin new file mode 100644 index 000000000..f9480340c --- /dev/null +++ b/core/os/old/env_windows.odin @@ -0,0 +1,140 @@ +package os_old + +import win32 "core:sys/windows" +import "base:runtime" + +// lookup_env gets the value of the environment variable named by the key +// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true +// Otherwise the returned value will be empty and the boolean will be false +// NOTE: the value will be allocated with the supplied allocator +@(require_results) +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { + if key == "" { + return + } + wkey := win32.utf8_to_wstring(key) + n := win32.GetEnvironmentVariableW(wkey, nil, 0) + if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND { + return "", false + } + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) + + b, _ := make([dynamic]u16, n, context.temp_allocator) + n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))) + if n == 0 && get_last_error() == ERROR_ENVVAR_NOT_FOUND { + return "", false + } + value, _ = win32.utf16_to_utf8(b[:n], allocator) + found = true + return +} + +// This version of `lookup_env` doesn't allocate and instead requires the user to provide a buffer. +// Note that it is limited to environment names and values of 512 utf-16 values each +// due to the necessary utf-8 <> utf-16 conversion. +@(require_results) +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + key_buf: [513]u16 + wkey := win32.utf8_to_wstring(key_buf[:], key) + if wkey == nil { + return "", .Buffer_Full + } + + n2 := win32.GetEnvironmentVariableW(wkey, nil, 0) + if n2 == 0 { + return "", .Env_Var_Not_Found + } + + val_buf: [513]u16 + n2 = win32.GetEnvironmentVariableW(wkey, raw_data(val_buf[:]), u32(len(val_buf[:]))) + if n2 == 0 { + return "", .Env_Var_Not_Found + } else if int(n2) > len(buf) { + return "", .Buffer_Full + } + + value = win32.utf16_to_utf8(buf, val_buf[:n2]) + + return value, nil +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +// get_env retrieves the value of the environment variable named by the key +// It returns the value, which will be empty if the variable is not present +// To distinguish between an empty value and an unset value, use lookup_env +// NOTE: the value will be allocated with the supplied allocator +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { + value, _ = lookup_env(key, allocator) + return +} + +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + + +// set_env sets the value of the environment variable named by the key +set_env :: proc(key, value: string) -> Error { + k := win32.utf8_to_wstring(key) + v := win32.utf8_to_wstring(value) + + if !win32.SetEnvironmentVariableW(k, v) { + return get_last_error() + } + return nil +} + +// unset_env unsets a single environment variable +unset_env :: proc(key: string) -> Error { + k := win32.utf8_to_wstring(key) + if !win32.SetEnvironmentVariableW(k, nil) { + return get_last_error() + } + return nil +} + +// environ returns a copy of strings representing the environment, in the form "key=value" +// NOTE: the slice of strings and the strings with be allocated using the supplied allocator +@(require_results) +environ :: proc(allocator := context.allocator) -> []string { + envs := ([^]win32.WCHAR)(win32.GetEnvironmentStringsW()) + if envs == nil { + return nil + } + defer win32.FreeEnvironmentStringsW(envs) + + r, err := make([dynamic]string, 0, 50, allocator) + if err != nil { + return nil + } + for from, i := 0, 0; true; i += 1 { + if c := envs[i]; c == 0 { + if i <= from { + break + } + append(&r, win32.utf16_to_utf8(envs[from:i], allocator) or_else "") + from = i + 1 + } + } + + return r[:] +} + + +// clear_env deletes all environment variables +clear_env :: proc() { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + envs := environ(context.temp_allocator) + for env in envs { + for j in 1.. string where intrinsics.type_is_enum(Platform_Error) { + if e == nil { + return "" + } + + when ODIN_OS == .Darwin { + if s := string(_darwin_string_error(i32(e))); s != "" { + return s + } + } + + when ODIN_OS != .Linux { + @(require_results) + binary_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) #no_bounds_check { + n := len(array) + left, right := 0, n + for left < right { + mid := int(uint(left+right) >> 1) + if array[mid] < key { + left = mid+1 + } else { + // equal or greater + right = mid + } + } + return left, left < n && array[left] == key + } + + err := runtime.Type_Info_Enum_Value(e) + + ti := &runtime.type_info_base(type_info_of(Platform_Error)).variant.(runtime.Type_Info_Enum) + if idx, ok := binary_search(ti.values, err); ok { + return ti.names[idx] + } + } else { + @(rodata, static) + pe_strings := [Platform_Error]string{ + .NONE = "", + .EPERM = "Operation not permitted", + .ENOENT = "No such file or directory", + .ESRCH = "No such process", + .EINTR = "Interrupted system call", + .EIO = "Input/output error", + .ENXIO = "No such device or address", + .E2BIG = "Argument list too long", + .ENOEXEC = "Exec format error", + .EBADF = "Bad file descriptor", + .ECHILD = "No child processes", + .EAGAIN = "Resource temporarily unavailable", + .ENOMEM = "Cannot allocate memory", + .EACCES = "Permission denied", + .EFAULT = "Bad address", + .ENOTBLK = "Block device required", + .EBUSY = "Device or resource busy", + .EEXIST = "File exists", + .EXDEV = "Invalid cross-device link", + .ENODEV = "No such device", + .ENOTDIR = "Not a directory", + .EISDIR = "Is a directory", + .EINVAL = "Invalid argument", + .ENFILE = "Too many open files in system", + .EMFILE = "Too many open files", + .ENOTTY = "Inappropriate ioctl for device", + .ETXTBSY = "Text file busy", + .EFBIG = "File too large", + .ENOSPC = "No space left on device", + .ESPIPE = "Illegal seek", + .EROFS = "Read-only file system", + .EMLINK = "Too many links", + .EPIPE = "Broken pipe", + .EDOM = "Numerical argument out of domain", + .ERANGE = "Numerical result out of range", + .EDEADLK = "Resource deadlock avoided", + .ENAMETOOLONG = "File name too long", + .ENOLCK = "No locks available", + .ENOSYS = "Function not implemented", + .ENOTEMPTY = "Directory not empty", + .ELOOP = "Too many levels of symbolic links", + .EUNKNOWN_41 = "Unknown Error (41)", + .ENOMSG = "No message of desired type", + .EIDRM = "Identifier removed", + .ECHRNG = "Channel number out of range", + .EL2NSYNC = "Level 2 not synchronized", + .EL3HLT = "Level 3 halted", + .EL3RST = "Level 3 reset", + .ELNRNG = "Link number out of range", + .EUNATCH = "Protocol driver not attached", + .ENOCSI = "No CSI structure available", + .EL2HLT = "Level 2 halted", + .EBADE = "Invalid exchange", + .EBADR = "Invalid request descriptor", + .EXFULL = "Exchange full", + .ENOANO = "No anode", + .EBADRQC = "Invalid request code", + .EBADSLT = "Invalid slot", + .EUNKNOWN_58 = "Unknown Error (58)", + .EBFONT = "Bad font file format", + .ENOSTR = "Device not a stream", + .ENODATA = "No data available", + .ETIME = "Timer expired", + .ENOSR = "Out of streams resources", + .ENONET = "Machine is not on the network", + .ENOPKG = "Package not installed", + .EREMOTE = "Object is remote", + .ENOLINK = "Link has been severed", + .EADV = "Advertise error", + .ESRMNT = "Srmount error", + .ECOMM = "Communication error on send", + .EPROTO = "Protocol error", + .EMULTIHOP = "Multihop attempted", + .EDOTDOT = "RFS specific error", + .EBADMSG = "Bad message", + .EOVERFLOW = "Value too large for defined data type", + .ENOTUNIQ = "Name not unique on network", + .EBADFD = "File descriptor in bad state", + .EREMCHG = "Remote address changed", + .ELIBACC = "Can not access a needed shared library", + .ELIBBAD = "Accessing a corrupted shared library", + .ELIBSCN = ".lib section in a.out corrupted", + .ELIBMAX = "Attempting to link in too many shared libraries", + .ELIBEXEC = "Cannot exec a shared library directly", + .EILSEQ = "Invalid or incomplete multibyte or wide character", + .ERESTART = "Interrupted system call should be restarted", + .ESTRPIPE = "Streams pipe error", + .EUSERS = "Too many users", + .ENOTSOCK = "Socket operation on non-socket", + .EDESTADDRREQ = "Destination address required", + .EMSGSIZE = "Message too long", + .EPROTOTYPE = "Protocol wrong type for socket", + .ENOPROTOOPT = "Protocol not available", + .EPROTONOSUPPORT = "Protocol not supported", + .ESOCKTNOSUPPORT = "Socket type not supported", + .EOPNOTSUPP = "Operation not supported", + .EPFNOSUPPORT = "Protocol family not supported", + .EAFNOSUPPORT = "Address family not supported by protocol", + .EADDRINUSE = "Address already in use", + .EADDRNOTAVAIL = "Cannot assign requested address", + .ENETDOWN = "Network is down", + .ENETUNREACH = "Network is unreachable", + .ENETRESET = "Network dropped connection on reset", + .ECONNABORTED = "Software caused connection abort", + .ECONNRESET = "Connection reset by peer", + .ENOBUFS = "No buffer space available", + .EISCONN = "Transport endpoint is already connected", + .ENOTCONN = "Transport endpoint is not connected", + .ESHUTDOWN = "Cannot send after transport endpoint shutdown", + .ETOOMANYREFS = "Too many references: cannot splice", + .ETIMEDOUT = "Connection timed out", + .ECONNREFUSED = "Connection refused", + .EHOSTDOWN = "Host is down", + .EHOSTUNREACH = "No route to host", + .EALREADY = "Operation already in progress", + .EINPROGRESS = "Operation now in progress", + .ESTALE = "Stale file handle", + .EUCLEAN = "Structure needs cleaning", + .ENOTNAM = "Not a XENIX named type file", + .ENAVAIL = "No XENIX semaphores available", + .EISNAM = "Is a named type file", + .EREMOTEIO = "Remote I/O error", + .EDQUOT = "Disk quota exceeded", + .ENOMEDIUM = "No medium found", + .EMEDIUMTYPE = "Wrong medium type", + .ECANCELED = "Operation canceled", + .ENOKEY = "Required key not available", + .EKEYEXPIRED = "Key has expired", + .EKEYREVOKED = "Key has been revoked", + .EKEYREJECTED = "Key was rejected by service", + .EOWNERDEAD = "Owner died", + .ENOTRECOVERABLE = "State not recoverable", + .ERFKILL = "Operation not possible due to RF-kill", + .EHWPOISON = "Memory page has hardware error", + } + if Platform_Error.NONE <= e && e <= max(Platform_Error) { + return pe_strings[e] + } + } + return "" +} + +@(private, require_results) +error_to_io_error :: proc(ferr: Error) -> io.Error { + if ferr == nil { + return .None + } + return ferr.(io.Error) or_else .Unknown +} diff --git a/core/os/os.odin b/core/os/old/os.odin similarity index 78% rename from core/os/os.odin rename to core/os/old/os.odin index 30b86d4cd..01e93126d 100644 --- a/core/os/os.odin +++ b/core/os/old/os.odin @@ -1,9 +1,11 @@ -package os +// Cross-platform `OS` interactions like file `I/O`. +package os_old import "base:intrinsics" import "base:runtime" import "core:io" import "core:strconv" +import "core:strings" import "core:unicode/utf8" @@ -57,7 +59,7 @@ write_encoded_rune :: proc(f: Handle, r: rune) -> (n: int, err: Error) { if r < 32 { if wrap(write_string(f, "\\x"), &n, &err) { return } b: [2]byte - s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil) + s := strconv.write_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil) switch len(s) { case 0: if wrap(write_string(f, "00"), &n, &err) { return } case 1: if wrap(write_rune(f, '0'), &n, &err) { return } @@ -210,3 +212,55 @@ heap_free :: runtime.heap_free processor_core_count :: proc() -> int { return _processor_core_count() } + +// Always allocates for consistency. +replace_environment_placeholders :: proc(path: string, allocator := context.allocator) -> (res: string) { + path := path + + sb: strings.Builder + strings.builder_init_none(&sb, allocator) + for len(path) > 0 { + switch path[0] { + case '%': // Windows + when ODIN_OS == .Windows { + for r, i in path[1:] { + if r == '%' { + env_key := path[1:i+1] + env_val := get_env(env_key, context.temp_allocator) + strings.write_string(&sb, env_val) + path = path[i+1:] // % is part of key, so skip 1 character extra + } + } + } else { + strings.write_rune(&sb, rune(path[0])) + } + + case '$': // Posix + when ODIN_OS != .Windows { + env_key := "" + dollar_loop: for r, i in path[1:] { + switch r { + case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident + case: + env_key = path[1:i+1] + break dollar_loop + } + } + if len(env_key) > 0 { + env_val := get_env(env_key, context.temp_allocator) + strings.write_string(&sb, env_val) + path = path[len(env_key):] + } + + } else { + strings.write_rune(&sb, rune(path[0])) + } + + case: + strings.write_rune(&sb, rune(path[0])) + } + + path = path[1:] + } + return strings.to_string(sb) +} \ No newline at end of file diff --git a/core/os/os_darwin.odin b/core/os/old/os_darwin.odin similarity index 96% rename from core/os/os_darwin.odin rename to core/os/old/os_darwin.odin index bbffc46d7..6a6efe4e2 100644 --- a/core/os/os_darwin.odin +++ b/core/os/old/os_darwin.odin @@ -1,8 +1,8 @@ -package os +package os_old foreign import dl "system:dl" -foreign import libc "system:System.framework" -foreign import pthread "system:System.framework" +foreign import libc "system:System" +foreign import pthread "system:System" import "base:runtime" import "core:strings" @@ -598,7 +598,7 @@ foreign libc { @(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int --- @(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t --- @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int --- - @(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int --- + @(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int --- @(link_name="dup") _unix_dup :: proc(handle: Handle) -> Handle --- @(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir --- @@ -1055,9 +1055,10 @@ flush :: proc(fd: Handle) -> Error { } @(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) + // NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults. cstr := _unix_getenv(path_str) if cstr == nil { return "", false @@ -1066,11 +1067,40 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin } @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + if value = string(_unix_getenv(cstring(raw_data(buf)))); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + set_env :: proc(key, value: string) -> Error { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() key_cstring := strings.clone_to_cstring(key, context.temp_allocator) @@ -1196,8 +1226,9 @@ _processor_core_count :: proc() -> int { return 1 } -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -1205,6 +1236,12 @@ _alloc_command_line_arguments :: proc() -> []string { return res } +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) +} + socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { result := _unix_socket(c.int(domain), c.int(type), c.int(protocol)) if result < 0 { diff --git a/core/os/os_freebsd.odin b/core/os/old/os_freebsd.odin similarity index 95% rename from core/os/os_freebsd.odin rename to core/os/old/os_freebsd.odin index 87a56b057..a1ecf2aff 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/old/os_freebsd.odin @@ -1,4 +1,4 @@ -package os +package os_old foreign import dl "system:dl" foreign import libc "system:c" @@ -662,7 +662,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Error) { return File_Time(modified), nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -674,7 +674,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -688,7 +688,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { s: OS_Stat = --- result := _unix_fstat(fd, &s) @@ -827,10 +827,10 @@ access :: proc(path: string, mask: int) -> (bool, Error) { } @(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - path_str := strings.clone_to_cstring(key, context.temp_allocator) + // NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults. cstr := _unix_getenv(path_str) if cstr == nil { return "", false @@ -839,11 +839,40 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin } @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + if value = string(_unix_getenv(cstring(raw_data(buf)))); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + @(require_results) get_current_directory :: proc(allocator := context.allocator) -> string { context.allocator = allocator @@ -936,11 +965,18 @@ _processor_core_count :: proc() -> int { } -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) - for arg, i in runtime.args__ { - res[i] = string(arg) + for _, i in res { + res[i] = string(runtime.args__[i]) } return res } + +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) +} diff --git a/core/os/old/os_freestanding.odin b/core/os/old/os_freestanding.odin new file mode 100644 index 000000000..def000aae --- /dev/null +++ b/core/os/old/os_freestanding.odin @@ -0,0 +1,4 @@ +#+build freestanding +package os_old + +#panic("package os_old does not support a freestanding target") diff --git a/core/os/os_js.odin b/core/os/old/os_js.odin similarity index 91% rename from core/os/os_js.odin rename to core/os/old/os_js.odin index 348554728..cefabbf4d 100644 --- a/core/os/os_js.odin +++ b/core/os/old/os_js.odin @@ -1,5 +1,5 @@ #+build js -package os +package os_old foreign import "odin_env" @@ -249,3 +249,27 @@ exit :: proc "contextless" (code: int) -> ! { current_thread_id :: proc "contextless" () -> int { return 0 } + +@(require_results) +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { + return "", false +} + +@(require_results) +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + return "", .Env_Var_Not_Found +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { + value, _ = lookup_env(key, allocator) + return +} + +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} \ No newline at end of file diff --git a/core/os/os_linux.odin b/core/os/old/os_linux.odin similarity index 96% rename from core/os/os_linux.odin rename to core/os/old/os_linux.odin index 2281e6a82..504f6f5b3 100644 --- a/core/os/os_linux.odin +++ b/core/os/old/os_linux.odin @@ -1,4 +1,4 @@ -package os +package os_old foreign import dl "system:dl" foreign import libc "system:c" @@ -7,19 +7,8 @@ import "base:runtime" import "core:strings" import "core:c" import "core:strconv" - -// NOTE(flysand): For compatibility we'll make core:os package -// depend on the old (scheduled for removal) linux package. -// Seeing that there are plans for os2, I'm imagining that *that* -// package should inherit the new sys functionality. -// The reasons for these are as follows: -// 1. It's very hard to update this package without breaking *a lot* of code. -// 2. os2 is not stable anyways, so we can break compatibility all we want -// It might be weird to bring up compatibility when Odin in it's nature isn't -// all that about compatibility. But we don't want to push experimental changes -// and have people's code break while it's still work in progress. -import unix "core:sys/unix" -import linux "core:sys/linux" +import "core:sys/unix" +import "core:sys/linux" Handle :: distinct i32 Pid :: distinct i32 @@ -674,7 +663,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return i64(res), nil } -@(require_results) +@(require_results, no_sanitize_memory) file_size :: proc(fd: Handle) -> (i64, Error) { // deliberately uninitialized; the syscall fills this buffer for us s: OS_Stat = --- @@ -794,7 +783,7 @@ last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { return File_Time(modified), nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -808,7 +797,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -822,7 +811,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { // deliberately uninitialized; the syscall fills this buffer for us s: OS_Stat = --- @@ -908,7 +897,7 @@ _dup :: proc(fd: Handle) -> (Handle, Error) { @(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { buf : [256]byte - fd_str := strconv.itoa( buf[:], cast(int)fd ) + fd_str := strconv.write_int( buf[:], cast(i64)fd, 10 ) procfs_path := strings.concatenate( []string{ "/proc/self/fd/", fd_str } ) defer delete(procfs_path) @@ -946,7 +935,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { } @(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) // NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults. @@ -958,11 +947,40 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin } @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + if value = string(_unix_getenv(cstring(raw_data(buf)))); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + set_env :: proc(key, value: string) -> Error { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() key_cstring := strings.clone_to_cstring(key, context.temp_allocator) @@ -1069,15 +1087,22 @@ _processor_core_count :: proc() -> int { return int(_unix_get_nprocs()) } -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) - for arg, i in runtime.args__ { - res[i] = string(arg) + for _, i in res { + res[i] = string(runtime.args__[i]) } return res } +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) +} + @(require_results) socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { result := unix.sys_socket(domain, type, protocol) diff --git a/core/os/os_netbsd.odin b/core/os/old/os_netbsd.odin similarity index 96% rename from core/os/os_netbsd.odin rename to core/os/old/os_netbsd.odin index e3ba760a4..601e42199 100644 --- a/core/os/os_netbsd.odin +++ b/core/os/old/os_netbsd.odin @@ -1,4 +1,4 @@ -package os +package os_old foreign import dl "system:dl" foreign import libc "system:c" @@ -724,7 +724,7 @@ last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { return File_Time(modified), nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -736,7 +736,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -750,7 +750,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { s: OS_Stat = --- result := _unix_fstat(fd, &s) @@ -874,10 +874,10 @@ access :: proc(path: string, mask: int) -> (bool, Error) { } @(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - path_str := strings.clone_to_cstring(key, context.temp_allocator) + // NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults. cstr := _unix_getenv(path_str) if cstr == nil { return "", false @@ -886,11 +886,40 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin } @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + if value = string(_unix_getenv(cstring(raw_data(buf)))); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + @(require_results) get_current_directory :: proc(allocator := context.allocator) -> string { context.allocator = allocator @@ -986,11 +1015,18 @@ _processor_core_count :: proc() -> int { return 1 } -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) - for arg, i in runtime.args__ { - res[i] = string(arg) + for _, i in res { + res[i] = string(runtime.args__[i]) } return res } + +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) +} diff --git a/core/os/os_openbsd.odin b/core/os/old/os_openbsd.odin similarity index 94% rename from core/os/os_openbsd.odin rename to core/os/old/os_openbsd.odin index 6548a57dc..95d431134 100644 --- a/core/os/os_openbsd.odin +++ b/core/os/old/os_openbsd.odin @@ -1,4 +1,4 @@ -package os +package os_old foreign import libc "system:c" @@ -639,7 +639,7 @@ last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { return File_Time(modified), nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -653,7 +653,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -667,7 +667,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@(private, require_results) +@(private, require_results, no_sanitize_memory) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { // deliberately uninitialized s: OS_Stat = --- @@ -787,9 +787,10 @@ access :: proc(path: string, mask: int) -> (bool, Error) { } @(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) + // NOTE(tetra): Lifetime of 'cstr' is unclear, but _unix_free(cstr) segfaults. cstr := _unix_getenv(path_str) if cstr == nil { return "", false @@ -798,11 +799,40 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin } @(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + if len(key) + 1 > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, key) + buf[len(key)] = 0 + } + + if value = string(_unix_getenv(cstring(raw_data(buf)))); value == "" { + return "", .Env_Var_Not_Found + } else { + if len(value) > len(buf) { + return "", .Buffer_Full + } else { + copy(buf, value) + return string(buf[:len(value)]), nil + } + } +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} + @(require_results) get_current_directory :: proc(allocator := context.allocator) -> string { context.allocator = allocator @@ -885,11 +915,18 @@ _processor_core_count :: proc() -> int { return int(_sysconf(_SC_NPROCESSORS_ONLN)) } -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) - for arg, i in runtime.args__ { - res[i] = string(arg) + for _, i in res { + res[i] = string(runtime.args__[i]) } return res } + +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) +} diff --git a/core/os/os_wasi.odin b/core/os/old/os_wasi.odin similarity index 82% rename from core/os/os_wasi.odin rename to core/os/old/os_wasi.odin index 28f470357..287034957 100644 --- a/core/os/os_wasi.odin +++ b/core/os/old/os_wasi.odin @@ -1,4 +1,4 @@ -package os +package os_old import "core:sys/wasm/wasi" import "base:runtime" @@ -27,13 +27,20 @@ stderr: Handle = 2 args := _alloc_command_line_arguments() -@(require_results) -_alloc_command_line_arguments :: proc() -> (args: []string) { - args = make([]string, len(runtime.args__)) - for &arg, i in args { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() + cmd_args := make([]string, len(runtime.args__)) + for &arg, i in cmd_args { arg = string(runtime.args__[i]) } - return + return cmd_args +} + +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + delete(args) } // WASI works with "preopened" directories, the environment retrieves directories @@ -52,9 +59,8 @@ Preopen :: struct { preopens: []Preopen @(init, private) -init_preopens :: proc() { - - strip_prefixes :: proc(path: string) -> string { +init_preopens :: proc "contextless" () { + strip_prefixes :: proc "contextless"(path: string) -> string { path := path loop: for len(path) > 0 { switch { @@ -71,6 +77,8 @@ init_preopens :: proc() { return path } + context = runtime.default_context() + dyn_preopens: [dynamic]Preopen loop: for fd := wasi.fd_t(3); ; fd += 1 { desc, err := wasi.fd_prestat_get(fd) @@ -239,3 +247,27 @@ exit :: proc "contextless" (code: int) -> ! { runtime._cleanup_runtime_contextless() wasi.proc_exit(wasi.exitcode_t(code)) } + +@(require_results) +lookup_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { + return "", false +} + +@(require_results) +lookup_env_buffer :: proc(buf: []u8, key: string) -> (value: string, err: Error) { + return "", .Env_Var_Not_Found +} +lookup_env :: proc{lookup_env_alloc, lookup_env_buffer} + +@(require_results) +get_env_alloc :: proc(key: string, allocator := context.allocator) -> (value: string) { + value, _ = lookup_env(key, allocator) + return +} + +@(require_results) +get_env_buf :: proc(buf: []u8, key: string) -> (value: string) { + value, _ = lookup_env(buf, key) + return +} +get_env :: proc{get_env_alloc, get_env_buf} \ No newline at end of file diff --git a/core/os/os_windows.odin b/core/os/old/os_windows.odin similarity index 97% rename from core/os/os_windows.odin rename to core/os/old/os_windows.odin index 0c532bf14..8081d9726 100644 --- a/core/os/os_windows.odin +++ b/core/os/old/os_windows.odin @@ -1,5 +1,5 @@ #+build windows -package os +package os_old import win32 "core:sys/windows" import "base:runtime" @@ -193,8 +193,9 @@ current_thread_id :: proc "contextless" () -> int { -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { +@(private, require_results) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() arg_count: i32 arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count) arg_list := make([]string, int(arg_count)) @@ -215,6 +216,15 @@ _alloc_command_line_arguments :: proc() -> []string { return arg_list } +@(private, fini) +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() + for s in args { + delete(s) + } + delete(args) +} + /* Windows 11 (preview) has the same major and minor version numbers as Windows 10: 10 and 0 respectively. @@ -323,8 +333,14 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Erro case: create_mode = win32.OPEN_EXISTING } + + attrs := win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS + if mode & (O_NONBLOCK) == O_NONBLOCK { + attrs |= win32.FILE_FLAG_OVERLAPPED + } + wide_path := win32.utf8_to_wstring(path) - handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS, nil)) + handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, attrs, nil)) if handle != INVALID_HANDLE { return handle, nil } @@ -852,4 +868,4 @@ pipe :: proc() -> (r, w: Handle, err: Error) { err = get_last_error() } return -} \ No newline at end of file +} diff --git a/core/os/old/stat.odin b/core/os/old/stat.odin new file mode 100644 index 000000000..fad8ff755 --- /dev/null +++ b/core/os/old/stat.odin @@ -0,0 +1,33 @@ +package os_old + +import "core:time" + +File_Info :: struct { + fullpath: string, // allocated + name: string, // uses `fullpath` as underlying data + size: i64, + mode: File_Mode, + is_dir: bool, + creation_time: time.Time, + modification_time: time.Time, + access_time: time.Time, +} + +file_info_slice_delete :: proc(infos: []File_Info, allocator := context.allocator) { + for i := len(infos)-1; i >= 0; i -= 1 { + file_info_delete(infos[i], allocator) + } + delete(infos, allocator) +} + +file_info_delete :: proc(fi: File_Info, allocator := context.allocator) { + delete(fi.fullpath, allocator) +} + +File_Mode :: distinct u32 + +File_Mode_Dir :: File_Mode(1<<16) +File_Mode_Named_Pipe :: File_Mode(1<<17) +File_Mode_Device :: File_Mode(1<<18) +File_Mode_Char_Device :: File_Mode(1<<19) +File_Mode_Sym_Link :: File_Mode(1<<20) diff --git a/core/os/stat_unix.odin b/core/os/old/stat_unix.odin similarity index 97% rename from core/os/stat_unix.odin rename to core/os/old/stat_unix.odin index 648987a07..d7f49e12b 100644 --- a/core/os/stat_unix.odin +++ b/core/os/old/stat_unix.odin @@ -1,5 +1,5 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku -package os +#+build linux, darwin, freebsd, openbsd, netbsd +package os_old import "core:time" diff --git a/core/os/old/stat_windows.odin b/core/os/old/stat_windows.odin new file mode 100644 index 000000000..34e5e1695 --- /dev/null +++ b/core/os/old/stat_windows.odin @@ -0,0 +1,303 @@ +package os_old + +import "core:time" +import "base:runtime" +import win32 "core:sys/windows" + +@(private, require_results) +full_path_from_name :: proc(name: string, allocator := context.allocator) -> (path: string, err: Errno) { + context.allocator = allocator + + name := name + if name == "" { + name = "." + } + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) + p := win32.utf8_to_utf16(name, context.temp_allocator) + buf := make([dynamic]u16, 100) + defer delete(buf) + for { + n := win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil) + if n == 0 { + return "", get_last_error() + } + if n <= u32(len(buf)) { + return win32.utf16_to_utf8(buf[:n], allocator) or_else "", nil + } + resize(&buf, len(buf)*2) + } + + return +} + +@(private, require_results) +_stat :: proc(name: string, create_file_attributes: u32, allocator := context.allocator) -> (fi: File_Info, e: Errno) { + if len(name) == 0 { + return {}, ERROR_PATH_NOT_FOUND + } + + context.allocator = allocator + + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) + + wname := win32.utf8_to_wstring(fix_long_path(name), context.temp_allocator) + fa: win32.WIN32_FILE_ATTRIBUTE_DATA + ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa) + if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { + // Not a symlink + return file_info_from_win32_file_attribute_data(&fa, name) + } + + err := 0 if ok else win32.GetLastError() + + if err == win32.ERROR_SHARING_VIOLATION { + fd: win32.WIN32_FIND_DATAW + sh := win32.FindFirstFileW(wname, &fd) + if sh == win32.INVALID_HANDLE_VALUE { + e = get_last_error() + return + } + win32.FindClose(sh) + + return file_info_from_win32_find_data(&fd, name) + } + + h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) + if h == win32.INVALID_HANDLE_VALUE { + e = get_last_error() + return + } + defer win32.CloseHandle(h) + return file_info_from_get_file_information_by_handle(name, h) +} + + +@(require_results) +lstat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { + attrs := win32.FILE_FLAG_BACKUP_SEMANTICS + attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT + return _stat(name, attrs, allocator) +} + +@(require_results) +stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { + attrs := win32.FILE_FLAG_BACKUP_SEMANTICS + return _stat(name, attrs, allocator) +} + +@(require_results) +fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) { + if fd == 0 { + err = ERROR_INVALID_HANDLE + } + context.allocator = allocator + + path := cleanpath_from_handle(fd) or_return + defer if err != nil { + delete(path) + } + + h := win32.HANDLE(fd) + switch win32.GetFileType(h) { + case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR: + fi.name = basename(path) + fi.mode |= file_type_mode(h) + err = nil + case: + fi = file_info_from_get_file_information_by_handle(path, h) or_return + } + fi.fullpath = path + return +} + + +@(private, require_results) +cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { + buf := buf + N := 0 + for c, i in buf { + if c == 0 { break } + N = i+1 + } + buf = buf[:N] + + if len(buf) >= 4 && buf[0] == '\\' && buf[1] == '\\' && buf[2] == '?' && buf[3] == '\\' { + buf = buf[4:] + + /* + NOTE(Jeroen): Properly handle UNC paths. + We need to turn `\\?\UNC\synology.local` into `\\synology.local`. + */ + if len(buf) >= 3 && buf[0] == 'U' && buf[1] == 'N' && buf[2] == 'C' { + buf = buf[2:] + buf[0] = '\\' + } + } + return buf +} + +@(private, require_results) +cleanpath_from_handle :: proc(fd: Handle) -> (s: string, err: Errno) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) + buf := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return + return win32.utf16_to_utf8(buf, context.allocator) +} +@(private, require_results) +cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ([]u16, Errno) { + if fd == 0 { + return nil, ERROR_INVALID_HANDLE + } + h := win32.HANDLE(fd) + + n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0) + if n == 0 { + return nil, get_last_error() + } + buf := make([]u16, max(n, win32.DWORD(260))+1, allocator) + buf_len := win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), n, 0) + return buf[:buf_len], nil +} +@(private, require_results) +cleanpath_from_buf :: proc(buf: []u16) -> string { + buf := buf + buf = cleanpath_strip_prefix(buf) + return win32.utf16_to_utf8(buf, context.allocator) or_else "" +} + +@(private, require_results) +basename :: proc(name: string) -> (base: string) { + name := name + if len(name) > 3 && name[:3] == `\\?` { + name = name[3:] + } + + if len(name) == 2 && name[1] == ':' { + return "." + } else if len(name) > 2 && name[1] == ':' { + name = name[2:] + } + i := len(name)-1 + + for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i -= 1 { + name = name[:i] + } + for i -= 1; i >= 0; i -= 1 { + if name[i] == '/' || name[i] == '\\' { + name = name[i+1:] + break + } + } + return name +} + +@(private, require_results) +file_type_mode :: proc(h: win32.HANDLE) -> File_Mode { + switch win32.GetFileType(h) { + case win32.FILE_TYPE_PIPE: + return File_Mode_Named_Pipe + case win32.FILE_TYPE_CHAR: + return File_Mode_Device | File_Mode_Char_Device + } + return 0 +} + + +@(private, require_results) +file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) { + if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { + mode |= 0o444 + } else { + mode |= 0o666 + } + + is_sym := false + if FileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { + is_sym = false + } else { + is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT + } + + if is_sym { + mode |= File_Mode_Sym_Link + } else { + if FileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { + mode |= 0o111 | File_Mode_Dir + } + + if h != nil { + mode |= file_type_mode(h) + } + } + + return +} + +@(private) +windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) +} + +@(private, require_results) +file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + + fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.is_dir = fi.mode & File_Mode_Dir != 0 + + windows_set_file_info_times(&fi, d) + + fi.fullpath, e = full_path_from_name(name) + fi.name = basename(fi.fullpath) + + return +} + +@(private, require_results) +file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) -> (fi: File_Info, e: Errno) { + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + + fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.is_dir = fi.mode & File_Mode_Dir != 0 + + windows_set_file_info_times(&fi, d) + + fi.fullpath, e = full_path_from_name(name) + fi.name = basename(fi.fullpath) + + return +} + +@(private, require_results) +file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) { + d: win32.BY_HANDLE_FILE_INFORMATION + if !win32.GetFileInformationByHandle(h, &d) { + err := get_last_error() + return {}, err + + } + + ti: win32.FILE_ATTRIBUTE_TAG_INFO + if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) { + err := get_last_error() + if err != ERROR_INVALID_PARAMETER { + return {}, err + } + // Indicate this is a symlink on FAT file systems + ti.ReparseTag = 0 + } + + fi: File_Info + + fi.fullpath = path + fi.name = basename(path) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + + fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag) + fi.is_dir = fi.mode & File_Mode_Dir != 0 + + windows_set_file_info_times(&fi, &d) + + return fi, nil +} diff --git a/core/os/stream.odin b/core/os/old/stream.odin similarity index 97% rename from core/os/stream.odin rename to core/os/old/stream.odin index 39edc9cd5..d94505505 100644 --- a/core/os/stream.odin +++ b/core/os/old/stream.odin @@ -1,4 +1,4 @@ -package os +package os_old import "core:io" @@ -62,7 +62,7 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, case .Size: n, os_err = file_size(fd) case .Destroy: - err = .Empty + err = .Unsupported case .Query: return io.query_utility({.Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query}) } diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin deleted file mode 100644 index 4cf1f8396..000000000 --- a/core/os/os2/dir_windows.odin +++ /dev/null @@ -1,152 +0,0 @@ -#+private -package os2 - -import "base:runtime" -import "core:time" -import win32 "core:sys/windows" - -@(private="file") -find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { - // Ignore "." and ".." - if d.cFileName[0] == '.' && d.cFileName[1] == 0 { - return - } - if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 { - return - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - path := concatenate({base_path, `\`, win32_wstring_to_utf8(raw_data(d.cFileName[:]), temp_allocator) or_else ""}, allocator) or_return - - handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0) - defer win32.CloseHandle(handle) - - fi.fullpath = path - fi.name = basename(path) - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - - fi.type, fi.mode = _file_type_mode_from_file_attributes(d.dwFileAttributes, handle, d.dwReserved0) - - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - - if file_id_info: win32.FILE_ID_INFO; handle != nil && win32.GetFileInformationByHandleEx(handle, .FileIdInfo, &file_id_info, size_of(file_id_info)) { - #assert(size_of(fi.inode) == size_of(file_id_info.FileId)) - #assert(size_of(fi.inode) == 16) - runtime.mem_copy_non_overlapping(&fi.inode, &file_id_info.FileId, 16) - } - - return -} - -Read_Directory_Iterator_Impl :: struct { - find_data: win32.WIN32_FIND_DATAW, - find_handle: win32.HANDLE, - path: string, - prev_fi: File_Info, - no_more_files: bool, -} - - -@(require_results) -_read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) { - for !it.impl.no_more_files { - err: Error - file_info_delete(it.impl.prev_fi, file_allocator()) - it.impl.prev_fi = {} - - fi, err = find_data_to_file_info(it.impl.path, &it.impl.find_data, file_allocator()) - if err != nil { - read_directory_iterator_set_error(it, it.impl.path, err) - return - } - - if fi.name != "" { - it.impl.prev_fi = fi - ok = true - index = it.index - it.index += 1 - } - - if !win32.FindNextFileW(it.impl.find_handle, &it.impl.find_data) { - e := _get_platform_error() - if pe, _ := is_platform_error(e); pe != i32(win32.ERROR_NO_MORE_FILES) { - read_directory_iterator_set_error(it, it.impl.path, e) - } - it.impl.no_more_files = true - } - if ok { - return - } - } - return -} - -_read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { - it.impl.no_more_files = false - - if f == nil || f.impl == nil { - read_directory_iterator_set_error(it, "", .Invalid_File) - return - } - - it.f = f - impl := (^File_Impl)(f.impl) - - // NOTE: Allow calling `init` to target a new directory with the same iterator - reset idx. - if it.impl.find_handle != nil { - win32.FindClose(it.impl.find_handle) - } - if it.impl.path != "" { - delete(it.impl.path, file_allocator()) - } - - if !is_directory(impl.name) { - read_directory_iterator_set_error(it, impl.name, .Invalid_Dir) - return - } - - wpath: []u16 - { - i := 0 - for impl.wname[i] != 0 { - i += 1 - } - wpath = impl.wname[:i] - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - - wpath_search := make([]u16, len(wpath)+3, temp_allocator) - copy(wpath_search, wpath) - wpath_search[len(wpath)+0] = '\\' - wpath_search[len(wpath)+1] = '*' - wpath_search[len(wpath)+2] = 0 - - it.impl.find_handle = win32.FindFirstFileW(raw_data(wpath_search), &it.impl.find_data) - if it.impl.find_handle == win32.INVALID_HANDLE_VALUE { - read_directory_iterator_set_error(it, impl.name, _get_platform_error()) - return - } - defer if it.err.err != nil { - win32.FindClose(it.impl.find_handle) - } - - err: Error - it.impl.path, err = _cleanpath_from_buf(wpath, file_allocator()) - if err != nil { - read_directory_iterator_set_error(it, impl.name, err) - } - - return -} - -_read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { - if it.f == nil { - return - } - file_info_delete(it.impl.prev_fi, file_allocator()) - delete(it.impl.path, file_allocator()) - win32.FindClose(it.impl.find_handle) -} diff --git a/core/os/os2/doc.odin b/core/os/os2/doc.odin deleted file mode 100644 index e413ef186..000000000 --- a/core/os/os2/doc.odin +++ /dev/null @@ -1,11 +0,0 @@ -// Package os provides a platform-independent interface to operating system functionality. -// The design is UNIX-like but with Odin-like error handling. Failing calls return values with a specific error type rather than error number. -// -// The package os interface is intended to be uniform across all operating systems. -// Features not generally available appear in the system-specific packages under core:sys/*. -// -// -// IMPORTANT NOTE from Bill: this is purely a mockup of what I want the new package os to be, and NON-FUNCTIONING. -// It is not complete but should give designers a better idea of the general interface and how to write things. -// This entire interface is subject to change. -package os2 diff --git a/core/os/os2/env.odin b/core/os/os2/env.odin deleted file mode 100644 index 13c107f3c..000000000 --- a/core/os/os2/env.odin +++ /dev/null @@ -1,48 +0,0 @@ -package os2 - -import "base:runtime" - -// get_env retrieves the value of the environment variable named by the key -// It returns the value, which will be empty if the variable is not present -// To distinguish between an empty value and an unset value, use lookup_env -// NOTE: the value will be allocated with the supplied allocator -@(require_results) -get_env :: proc(key: string, allocator: runtime.Allocator) -> string { - value, _ := lookup_env(key, allocator) - return value -} - -// lookup_env gets the value of the environment variable named by the key -// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true -// Otherwise the returned value will be empty and the boolean will be false -// NOTE: the value will be allocated with the supplied allocator -@(require_results) -lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { - return _lookup_env(key, allocator) -} - -// set_env sets the value of the environment variable named by the key -// Returns Error on failure -set_env :: proc(key, value: string) -> Error { - return _set_env(key, value) -} - -// unset_env unsets a single environment variable -// Returns true on success, false on failure -unset_env :: proc(key: string) -> bool { - return _unset_env(key) -} - -clear_env :: proc() { - _clear_env() -} - - -// environ returns a copy of strings representing the environment, in the form "key=value" -// NOTE: the slice of strings and the strings with be allocated using the supplied allocator -@(require_results) -environ :: proc(allocator: runtime.Allocator) -> ([]string, Error) { - return _environ(allocator) -} - - diff --git a/core/os/os2/env_linux.odin b/core/os/os2/env_linux.odin deleted file mode 100644 index 59b772328..000000000 --- a/core/os/os2/env_linux.odin +++ /dev/null @@ -1,231 +0,0 @@ -#+private -package os2 - -import "base:runtime" -import "base:intrinsics" - -import "core:sync" -import "core:slice" -import "core:strings" - -// TODO: IF NO_CRT: -// Override the libc environment functions' weak linkage to -// allow us to interact with 3rd party code that DOES link -// to libc. Otherwise, our environment can be out of sync. -// ELSE: -// Just use the libc. - -NOT_FOUND :: -1 - -// the environment is a 0 delimited list of = strings -_env: [dynamic]string - -_env_mutex: sync.Recursive_Mutex - -// We need to be able to figure out if the environment variable -// is contained in the original environment or not. This also -// serves as a flag to determine if we have built _env. -_org_env_begin: uintptr // atomic -_org_env_end: uintptr // guarded by _env_mutex - -// Returns value + index location into _env -// or -1 if not found -_lookup :: proc(key: string) -> (value: string, idx: int) { - sync.guard(&_env_mutex) - - for entry, i in _env { - if k, v := _kv_from_entry(entry); k == key { - return v, i - } - } - return "", -1 -} - -_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { - _build_env() - } - - if v, idx := _lookup(key); idx != -1 { - found = true - value, _ = clone_string(v, allocator) - } - return -} - -_set_env :: proc(key, v_new: string) -> Error { - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { - _build_env() - } - sync.guard(&_env_mutex) - - // all key values are stored as "key=value\x00" - kv_size := len(key) + len(v_new) + 2 - if v_curr, idx := _lookup(key); idx != NOT_FOUND { - if v_curr == v_new { - return nil - } - - unordered_remove(&_env, idx) - - if !_is_in_org_env(v_curr) { - // We allocated this key-value. Possibly resize and - // overwrite the value only. Otherwise, treat as if it - // wasn't in the environment in the first place. - k_addr, v_addr := _kv_addr_from_val(v_curr, key) - if len(v_new) > len(v_curr) { - k_addr = ([^]u8)(runtime.heap_resize(k_addr, len(v_curr), kv_size)) - if k_addr == nil { - return .Out_Of_Memory - } - v_addr = &k_addr[len(key) + 1] - } - intrinsics.mem_copy_non_overlapping(v_addr, raw_data(v_new), len(v_new)) - v_addr[len(v_new)] = 0 - - append(&_env, string(k_addr[:kv_size])) - return nil - } - } - - k_addr := ([^]u8)(runtime.heap_alloc(kv_size)) - if k_addr == nil { - return .Out_Of_Memory - } - intrinsics.mem_copy_non_overlapping(k_addr, raw_data(key), len(key)) - k_addr[len(key)] = '=' - - val_slice := k_addr[len(key) + 1:] - intrinsics.mem_copy_non_overlapping(&val_slice[0], raw_data(v_new), len(v_new)) - val_slice[len(v_new)] = 0 - - append(&_env, string(k_addr[:kv_size - 1])) - return nil -} - -_unset_env :: proc(key: string) -> bool { - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { - _build_env() - } - sync.guard(&_env_mutex) - - v: string - i: int - if v, i = _lookup(key); i == -1 { - return false - } - - unordered_remove(&_env, i) - - if _is_in_org_env(v) { - return true - } - - // if we got this far, the environment variable - // existed AND was allocated by us. - k_addr, _ := _kv_addr_from_val(v, key) - runtime.heap_free(k_addr) - return true -} - -_clear_env :: proc() { - sync.guard(&_env_mutex) - - for kv in _env { - if !_is_in_org_env(kv) { - runtime.heap_free(raw_data(kv)) - } - } - clear(&_env) - - // nothing resides in the original environment either - intrinsics.atomic_store_explicit(&_org_env_begin, ~uintptr(0), .Release) - _org_env_end = ~uintptr(0) -} - -_environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) { - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { - _build_env() - } - sync.guard(&_env_mutex) - - env := make([dynamic]string, 0, len(_env), allocator) or_return - defer if err != nil { - for e in env { - delete(e, allocator) - } - delete(env) - } - - for entry in _env { - s := clone_string(entry, allocator) or_return - append(&env, s) - } - environ = env[:] - return -} - -// The entire environment is stored as 0 terminated strings, -// so there is no need to clone/free individual variables -export_cstring_environment :: proc(allocator: runtime.Allocator) -> []cstring { - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) == 0 { - // The environment has not been modified, so we can just - // send the original environment - org_env := _get_original_env() - n: int - for ; org_env[n] != nil; n += 1 {} - return slice.clone(org_env[:n + 1], allocator) - } - sync.guard(&_env_mutex) - - // NOTE: already terminated by nil pointer via + 1 - env := make([]cstring, len(_env) + 1, allocator) - - for entry, i in _env { - env[i] = cstring(raw_data(entry)) - } - return env -} - -_build_env :: proc() { - sync.guard(&_env_mutex) - if intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) != 0 { - return - } - - _env = make(type_of(_env), runtime.heap_allocator()) - cstring_env := _get_original_env() - intrinsics.atomic_store_explicit(&_org_env_begin, uintptr(rawptr(cstring_env[0])), .Release) - for i := 0; cstring_env[i] != nil; i += 1 { - bytes := ([^]u8)(cstring_env[i]) - n := len(cstring_env[i]) - _org_env_end = uintptr(&bytes[n]) - append(&_env, string(bytes[:n])) - } -} - -_get_original_env :: #force_inline proc() -> [^]cstring { - // essentially &argv[argc] which should be a nil pointer! - #no_bounds_check env: [^]cstring = &runtime.args__[len(runtime.args__)] - assert(env[0] == nil) - return &env[1] -} - -_kv_from_entry :: #force_inline proc(entry: string) -> (k, v: string) { - eq_idx := strings.index_byte(entry, '=') - if eq_idx == -1 { - return entry, "" - } - return entry[:eq_idx], entry[eq_idx + 1:] -} - -_kv_addr_from_val :: #force_inline proc(val: string, key: string) -> ([^]u8, [^]u8) { - v_addr := raw_data(val) - k_addr := ([^]u8)(&v_addr[-(len(key) + 1)]) - return k_addr, v_addr -} - -_is_in_org_env :: #force_inline proc(env_data: string) -> bool { - addr := uintptr(raw_data(env_data)) - return addr >= intrinsics.atomic_load_explicit(&_org_env_begin, .Acquire) && addr < _org_env_end -} diff --git a/core/os/os2/env_windows.odin b/core/os/os2/env_windows.odin deleted file mode 100644 index 6bfde34bb..000000000 --- a/core/os/os2/env_windows.odin +++ /dev/null @@ -1,112 +0,0 @@ -#+private -package os2 - -import win32 "core:sys/windows" -import "base:runtime" - -_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) { - if key == "" { - return - } - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - wkey, _ := win32_utf8_to_wstring(key, temp_allocator) - - n := win32.GetEnvironmentVariableW(wkey, nil, 0) - if n == 0 { - err := win32.GetLastError() - if err == win32.ERROR_ENVVAR_NOT_FOUND { - return "", false - } - return "", true - } - - b := make([]u16, n+1, temp_allocator) - - n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b))) - if n == 0 { - err := win32.GetLastError() - if err == win32.ERROR_ENVVAR_NOT_FOUND { - return "", false - } - return "", false - } - - value = win32_utf16_to_utf8(b[:n], allocator) or_else "" - found = true - return -} - -_set_env :: proc(key, value: string) -> Error { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - k := win32_utf8_to_wstring(key, temp_allocator) or_return - v := win32_utf8_to_wstring(value, temp_allocator) or_return - - if !win32.SetEnvironmentVariableW(k, v) { - return _get_platform_error() - } - return nil -} - -_unset_env :: proc(key: string) -> bool { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - k, _ := win32_utf8_to_wstring(key, temp_allocator) - return bool(win32.SetEnvironmentVariableW(k, nil)) -} - -_clear_env :: proc() { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - envs, _ := environ(temp_allocator) - for env in envs { - for j in 1.. (err: i32, ok: bool) { - v := ferr.(Platform_Error) or_else {} - return i32(v), i32(v) != 0 -} - - -@(require_results) -error_string :: proc(ferr: Error) -> string { - if ferr == nil { - return "" - } - switch e in ferr { - case General_Error: - switch e { - case .None: return "" - case .Permission_Denied: return "permission denied" - case .Exist: return "file already exists" - case .Not_Exist: return "file does not exist" - case .Closed: return "file already closed" - case .Timeout: return "i/o timeout" - case .Broken_Pipe: return "Broken pipe" - case .No_Size: return "file has no definite size" - case .Invalid_File: return "invalid file" - case .Invalid_Dir: return "invalid directory" - case .Invalid_Path: return "invalid path" - case .Invalid_Callback: return "invalid callback" - case .Invalid_Command: return "invalid command" - case .Unsupported: return "unsupported" - case .Pattern_Has_Separator: return "pattern has separator" - } - case io.Error: - switch e { - case .None: return "" - case .EOF: return "eof" - case .Unexpected_EOF: return "unexpected eof" - case .Short_Write: return "short write" - case .Invalid_Write: return "invalid write result" - case .Short_Buffer: return "short buffer" - case .No_Progress: return "multiple read calls return no data or error" - case .Invalid_Whence: return "invalid whence" - case .Invalid_Offset: return "invalid offset" - case .Invalid_Unread: return "invalid unread" - case .Negative_Read: return "negative read" - case .Negative_Write: return "negative write" - case .Negative_Count: return "negative count" - case .Buffer_Full: return "buffer full" - case .Unknown, .Empty: // - } - case runtime.Allocator_Error: - switch e { - case .None: return "" - case .Out_Of_Memory: return "out of memory" - case .Invalid_Pointer: return "invalid allocator pointer" - case .Invalid_Argument: return "invalid allocator argument" - case .Mode_Not_Implemented: return "allocator mode not implemented" - } - case Platform_Error: - return _error_string(i32(e)) - } - - return "unknown error" -} - -print_error :: proc(f: ^File, ferr: Error, msg: string) { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - err_str := error_string(ferr) - - // msg + ": " + err_str + '\n' - length := len(msg) + 2 + len(err_str) + 1 - buf := make([]u8, length, temp_allocator) - - copy(buf, msg) - buf[len(msg)] = ':' - buf[len(msg) + 1] = ' ' - copy(buf[len(msg) + 2:], err_str) - buf[length - 1] = '\n' - write(f, buf) -} diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin deleted file mode 100644 index ff214182e..000000000 --- a/core/os/os2/file.odin +++ /dev/null @@ -1,330 +0,0 @@ -package os2 - -import "core:io" -import "core:time" -import "base:runtime" - -/* - Type representing a file handle. - - This struct represents an OS-specific file-handle, which can be one of - the following: - - File - - Directory - - Pipe - - Named pipe - - Block Device - - Character device - - Symlink - - Socket - - See `File_Type` enum for more information on file types. -*/ -File :: struct { - impl: rawptr, - stream: io.Stream, - fstat: Fstat_Callback, -} - -/* - Type representing the type of a file handle. - - **Note(windows)**: Socket handles can not be distinguished from - files, as they are just a normal file handle that is being treated by - a special driver. Windows also makes no distinction between block and - character devices. -*/ -File_Type :: enum { - // The type of a file could not be determined for the current platform. - Undetermined, - // Represents a regular file. - Regular, - // Represents a directory. - Directory, - // Represents a symbolic link. - Symlink, - // Represents a named pipe (FIFO). - Named_Pipe, - // Represents a socket. - // **Note(windows)**: Not returned on windows - Socket, - // Represents a block device. - // **Note(windows)**: On windows represents all devices. - Block_Device, - // Represents a character device. - // **Note(windows)**: Not returned on windows - Character_Device, -} - -File_Flags :: distinct bit_set[File_Flag; uint] -File_Flag :: enum { - Read, - Write, - Append, - Create, - Excl, - Sync, - Trunc, - Sparse, - Inheritable, - - Unbuffered_IO, -} - -O_RDONLY :: File_Flags{.Read} -O_WRONLY :: File_Flags{.Write} -O_RDWR :: File_Flags{.Read, .Write} -O_APPEND :: File_Flags{.Append} -O_CREATE :: File_Flags{.Create} -O_EXCL :: File_Flags{.Excl} -O_SYNC :: File_Flags{.Sync} -O_TRUNC :: File_Flags{.Trunc} -O_SPARSE :: File_Flags{.Sparse} - -/* - If specified, the file handle is inherited upon the creation of a child - process. By default all handles are created non-inheritable. - - **Note**: The standard file handles (stderr, stdout and stdin) are always - initialized as inheritable. -*/ -O_INHERITABLE :: File_Flags{.Inheritable} - -stdin: ^File = nil // OS-Specific -stdout: ^File = nil // OS-Specific -stderr: ^File = nil // OS-Specific - -@(require_results) -create :: proc(name: string) -> (^File, Error) { - return open(name, {.Read, .Write, .Create}, 0o777) -} - -@(require_results) -open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) { - return _open(name, flags, perm) -} - -// @(require_results) -// open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) { -// if buffer_size == 0 { -// return _open(name, flags, perm) -// } -// return _open_buffered(name, buffer_size, flags, perm) -// } - - -@(require_results) -new_file :: proc(handle: uintptr, name: string) -> ^File { - file, err := _new_file(handle, name, file_allocator()) - if err != nil { - panic(error_string(err)) - } - return file -} - -@(require_results) -clone :: proc(f: ^File) -> (^File, Error) { - return _clone(f) -} - -@(require_results) -fd :: proc(f: ^File) -> uintptr { - return _fd(f) -} - -@(require_results) -name :: proc(f: ^File) -> string { - return _name(f) -} - -/* - Close a file and its stream. - - Any further use of the file or its stream should be considered to be in the - same class of bugs as a use-after-free. -*/ -close :: proc(f: ^File) -> Error { - if f != nil { - return io.close(f.stream) - } - return nil -} - -seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { - if f != nil { - return io.seek(f.stream, offset, whence) - } - return 0, .Invalid_File -} - -read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { - if f != nil { - return io.read(f.stream, p) - } - return 0, .Invalid_File -} - -read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { - if f != nil { - return io.read_at(f.stream, p, offset) - } - return 0, .Invalid_File -} - -write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { - if f != nil { - return io.write(f.stream, p) - } - return 0, .Invalid_File -} - -write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { - if f != nil { - return io.write_at(f.stream, p, offset) - } - return 0, .Invalid_File -} - -file_size :: proc(f: ^File) -> (n: i64, err: Error) { - if f != nil { - return io.size(f.stream) - } - return 0, .Invalid_File -} - -flush :: proc(f: ^File) -> Error { - if f != nil { - return io.flush(f.stream) - } - return nil -} - -sync :: proc(f: ^File) -> Error { - return _sync(f) -} - -truncate :: proc(f: ^File, size: i64) -> Error { - return _truncate(f, size) -} - -remove :: proc(name: string) -> Error { - return _remove(name) -} - -rename :: proc(old_path, new_path: string) -> Error { - return _rename(old_path, new_path) -} - - -link :: proc(old_name, new_name: string) -> Error { - return _link(old_name, new_name) -} - -symlink :: proc(old_name, new_name: string) -> Error { - return _symlink(old_name, new_name) -} - -read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) { - return _read_link(name,allocator) -} - - -chdir :: change_directory - -change_directory :: proc(name: string) -> Error { - return _chdir(name) -} - -chmod :: change_mode - -change_mode :: proc(name: string, mode: int) -> Error { - return _chmod(name, mode) -} - -chown :: change_owner - -change_owner :: proc(name: string, uid, gid: int) -> Error { - return _chown(name, uid, gid) -} - -fchdir :: fchange_directory - -fchange_directory :: proc(f: ^File) -> Error { - return _fchdir(f) -} - -fchmod :: fchange_mode - -fchange_mode :: proc(f: ^File, mode: int) -> Error { - return _fchmod(f, mode) -} - -fchown :: fchange_owner - -fchange_owner :: proc(f: ^File, uid, gid: int) -> Error { - return _fchown(f, uid, gid) -} - - -lchown :: change_owner_do_not_follow_links - -change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error { - return _lchown(name, uid, gid) -} - -chtimes :: change_times - -change_times :: proc(name: string, atime, mtime: time.Time) -> Error { - return _chtimes(name, atime, mtime) -} - -fchtimes :: fchange_times - -fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error { - return _fchtimes(f, atime, mtime) -} - -@(require_results) -exists :: proc(path: string) -> bool { - return _exists(path) -} - -@(require_results) -is_file :: proc(path: string) -> bool { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - fi, err := stat(path, temp_allocator) - if err != nil { - return false - } - return fi.type == .Regular -} - -is_dir :: is_directory - -@(require_results) -is_directory :: proc(path: string) -> bool { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - fi, err := stat(path, temp_allocator) - if err != nil { - return false - } - return fi.type == .Directory -} - - -copy_file :: proc(dst_path, src_path: string) -> Error { - src := open(src_path) or_return - defer close(src) - - info := fstat(src, file_allocator()) or_return - defer file_info_delete(info, file_allocator()) - if info.type == .Directory { - return .Invalid_File - } - - dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & 0o777) or_return - defer close(dst) - - _, err := io.copy(to_writer(dst), to_reader(src)) - return err -} diff --git a/core/os/os2/file_posix_darwin.odin b/core/os/os2/file_posix_darwin.odin deleted file mode 100644 index 920a63a71..000000000 --- a/core/os/os2/file_posix_darwin.odin +++ /dev/null @@ -1,18 +0,0 @@ -#+private -package os2 - -import "base:runtime" - -import "core:sys/posix" - -_posix_absolute_path :: proc(fd: posix.FD, name: string, allocator: runtime.Allocator) -> (path: cstring, err: Error) { - F_GETPATH :: 50 - - buf: [posix.PATH_MAX]byte - if posix.fcntl(fd, posix.FCNTL_Cmd(F_GETPATH), &buf) != 0 { - err = _get_platform_error() - return - } - - return clone_to_cstring(string(cstring(&buf[0])), allocator) -} diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin deleted file mode 100644 index 84176928d..000000000 --- a/core/os/os2/file_stream.odin +++ /dev/null @@ -1,23 +0,0 @@ -package os2 - -import "core:io" - -to_stream :: proc(f: ^File) -> (s: io.Stream) { - if f != nil { - assert(f.stream.procedure != nil) - s = f.stream - } - return -} - -to_writer :: to_stream -to_reader :: to_stream - - -@(private) -error_to_io_error :: proc(ferr: Error) -> io.Error { - if ferr == nil { - return .None - } - return ferr.(io.Error) or_else .Unknown -} diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin deleted file mode 100644 index 8af46fab3..000000000 --- a/core/os/os2/file_util.odin +++ /dev/null @@ -1,179 +0,0 @@ -package os2 - -import "base:runtime" -import "core:strconv" -import "core:unicode/utf8" - -write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) { - return write(f, transmute([]byte)s) -} - -write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) { - for s in strings { - m: int - m, err = write_string(f, s) - n += m - if err != nil { - return - } - } - return -} - -write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) { - return write(f, []byte{b}) -} - -write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { - if r < utf8.RUNE_SELF { - return write_byte(f, byte(r)) - } - - b: [4]byte - b, n = utf8.encode_rune(r) - return write(f, b[:n]) -} - -write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) { - wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool { - n^ += m - if merr != nil { - err^ = merr - return true - } - return false - } - - if wrap(write_byte(f, '\''), &n, &err) { return } - - switch r { - case '\a': if wrap(write_string(f, "\\a"), &n, &err) { return } - case '\b': if wrap(write_string(f, "\\b"), &n, &err) { return } - case '\e': if wrap(write_string(f, "\\e"), &n, &err) { return } - case '\f': if wrap(write_string(f, "\\f"), &n, &err) { return } - case '\n': if wrap(write_string(f, "\\n"), &n, &err) { return } - case '\r': if wrap(write_string(f, "\\r"), &n, &err) { return } - case '\t': if wrap(write_string(f, "\\t"), &n, &err) { return } - case '\v': if wrap(write_string(f, "\\v"), &n, &err) { return } - case: - if r < 32 { - if wrap(write_string(f, "\\x"), &n, &err) { return } - b: [2]byte - s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil) - switch len(s) { - case 0: if wrap(write_string(f, "00"), &n, &err) { return } - case 1: if wrap(write_rune(f, '0'), &n, &err) { return } - case 2: if wrap(write_string(f, s), &n, &err) { return } - } - } else { - if wrap(write_rune(f, r), &n, &err) { return } - } - } - _ = wrap(write_byte(f, '\''), &n, &err) - return -} - -read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) { - if len(buf) < min { - return 0, .Short_Buffer - } - nn := max(int) - for nn > 0 && n < min && err == nil { - nn, err = read(f, buf[n:]) - n += nn - } - if n >= min { - err = nil - } - return -} - -read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) { - return read_at_least(f, buf, len(buf)) -} - -write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { - return write(f, ([^]byte)(data)[:len]) -} - -read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) { - return read(f, ([^]byte)(data)[:len]) -} - - -read_entire_file :: proc{ - read_entire_file_from_path, - read_entire_file_from_file, -} - -@(require_results) -read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator) -> (data: []byte, err: Error) { - f, ferr := open(name) - if ferr != nil { - return nil, ferr - } - defer close(f) - return read_entire_file_from_file(f, allocator) -} - -@(require_results) -read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (data: []byte, err: Error) { - size: int - has_size := false - if size64, serr := file_size(f); serr == nil { - if i64(int(size64)) == size64 { - has_size = true - size = int(size64) - } - } - - if has_size && size > 0 { - total: int - data = make([]byte, size, allocator) or_return - for total < len(data) { - n: int - n, err = read(f, data[total:]) - total += n - if err != nil { - if err == .EOF { - err = nil - } - data = data[:total] - break - } - } - return - } else { - buffer: [1024]u8 - out_buffer := make([dynamic]u8, 0, 0, allocator) - total := 0 - for { - n: int - n, err = read(f, buffer[:]) - total += n - append_elems(&out_buffer, ..buffer[:n]) - if err != nil { - if err == .EOF || err == .Broken_Pipe { - err = nil - } - data = out_buffer[:total] - return - } - } - } -} - -@(require_results) -write_entire_file :: proc(name: string, data: []byte, perm: int = 0o644, truncate := true) -> Error { - flags := O_WRONLY|O_CREATE - if truncate { - flags |= O_TRUNC - } - f := open(name, flags, perm) or_return - _, err := write(f, data) - if cerr := close(f); cerr != nil && err == nil { - err = cerr - } - return err -} - diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin deleted file mode 100644 index e12aa3c9c..000000000 --- a/core/os/os2/path.odin +++ /dev/null @@ -1,462 +0,0 @@ -package os2 - -import "base:runtime" - -import "core:strings" - -Path_Separator :: _Path_Separator // OS-Specific -Path_Separator_String :: _Path_Separator_String // OS-Specific -Path_List_Separator :: _Path_List_Separator // OS-Specific - -#assert(_Path_Separator <= rune(0x7F), "The system-specific path separator rune is expected to be within the 7-bit ASCII character set.") - -/* -Return true if `c` is a character used to separate paths into directory and -file hierarchies on the current system. -*/ -@(require_results) -is_path_separator :: proc(c: byte) -> bool { - return _is_path_separator(c) -} - -mkdir :: make_directory - -/* -Make a new directory. - -If `path` is relative, it will be relative to the process's current working directory. -*/ -make_directory :: proc(name: string, perm: int = 0o755) -> Error { - return _mkdir(name, perm) -} - -mkdir_all :: make_directory_all - -/* -Make a new directory, creating new intervening directories when needed. - -If `path` is relative, it will be relative to the process's current working directory. -*/ -make_directory_all :: proc(path: string, perm: int = 0o755) -> Error { - return _mkdir_all(path, perm) -} - -/* -Delete `path` and all files and directories inside of `path` if it is a directory. - -If `path` is relative, it will be relative to the process's current working directory. -*/ -remove_all :: proc(path: string) -> Error { - return _remove_all(path) -} - -getwd :: get_working_directory - -/* -Get the working directory of the current process. - -*Allocates Using Provided Allocator* -*/ -@(require_results) -get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { - return _get_working_directory(allocator) -} - -setwd :: set_working_directory - -/* -Change the working directory of the current process. - -*Allocates Using Provided Allocator* -*/ -set_working_directory :: proc(dir: string) -> (err: Error) { - return _set_working_directory(dir) -} - -/* -Get the path for the currently running executable. - -*Allocates Using Provided Allocator* -*/ -@(require_results) -get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { - return _get_executable_path(allocator) -} - -/* -Get the directory for the currently running executable. - -*Allocates Using Provided Allocator* -*/ -@(require_results) -get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { - path = _get_executable_path(allocator) or_return - path, _ = split_path(path) - return -} - -/* -Compare two paths for exactness without normalization. - -This procedure takes into account case-sensitivity on differing systems. -*/ -@(require_results) -are_paths_identical :: proc(a, b: string) -> (identical: bool) { - return _are_paths_identical(a, b) -} - -/* -Normalize a path. - -*Allocates Using Provided Allocator* - -This will remove duplicate separators and unneeded references to the current or -parent directory. -*/ -@(require_results) -clean_path :: proc(path: string, allocator: runtime.Allocator) -> (cleaned: string, err: Error) { - if path == "" || path == "." { - return strings.clone(".", allocator) - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - // The extra byte is to simplify appending path elements by letting the - // loop to end each with a separator. We'll trim the last one when we're done. - buffer := make([]u8, len(path) + 1, temp_allocator) or_return - - // This is the only point where Windows and POSIX differ, as Windows has - // alphabet-based volumes for root paths. - rooted, start := _clean_path_handle_start(path, buffer) - - head, buffer_i := start, start - for i, j := start, start; i <= len(path); i += 1 { - if i == len(path) || _is_path_separator(path[i]) { - elem := path[j:i] - j = i + 1 - - switch elem { - case "", ".": - // Skip duplicate path separators and current directory references. - case "..": - if !rooted && buffer_i == head { - // Only allow accessing further parent directories when the path is relative. - buffer[buffer_i] = '.' - buffer[buffer_i+1] = '.' - buffer[buffer_i+2] = _Path_Separator - buffer_i += 3 - head = buffer_i - } else { - // Roll back to the last separator or the head of the buffer. - back_to := head - // `buffer_i` will be equal to 1 + the last set byte, so - // skipping two bytes avoids the final separator we just - // added. - for k := buffer_i-2; k >= head; k -= 1 { - if _is_path_separator(buffer[k]) { - back_to = k + 1 - break - } - } - buffer_i = back_to - } - case: - // Copy the path element verbatim and add a separator. - copy(buffer[buffer_i:], elem) - buffer_i += len(elem) - buffer[buffer_i] = _Path_Separator - buffer_i += 1 - } - } - } - - // Trim the final separator. - // NOTE: No need to check if the last byte is a separator, as we always add it. - if buffer_i > start { - buffer_i -= 1 - } - - if buffer_i == 0 { - return strings.clone(".", allocator) - } - - compact := make([]u8, buffer_i, allocator) or_return - copy(compact, buffer) // NOTE(bill): buffer[:buffer_i] is redundant here - return string(compact), nil -} - -/* -Return true if `path` is an absolute path as opposed to a relative one. -*/ -@(require_results) -is_absolute_path :: proc(path: string) -> bool { - return _is_absolute_path(path) -} - -/* -Get the absolute path to `path` with respect to the process's current directory. - -*Allocates Using Provided Allocator* -*/ -@(require_results) -get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { - return _get_absolute_path(path, allocator) -} - -/* -Get the relative path needed to change directories from `base` to `target`. - -*Allocates Using Provided Allocator* - -The result is such that `join_path(base, get_relative_path(base, target))` is equivalent to `target`. - -NOTE: This procedure expects both `base` and `target` to be normalized first, -which can be done by calling `clean_path` on them if needed. - -This procedure will return an `Invalid_Path` error if `base` begins with a -reference to the parent directory (`".."`). Use `get_working_directory` with -`join_path` to construct absolute paths for both arguments instead. -*/ -@(require_results) -get_relative_path :: proc(base, target: string, allocator: runtime.Allocator) -> (path: string, err: Error) { - if _are_paths_identical(base, target) { - return strings.clone(".", allocator) - } - if base == "." { - return strings.clone(target, allocator) - } - - // This is the first point where Windows and POSIX differ, as Windows has - // alphabet-based volumes for root paths. - if !_get_relative_path_handle_start(base, target) { - return "", .Invalid_Path - } - if strings.has_prefix(base, "..") && (len(base) == 2 || _is_path_separator(base[2])) { - // We could do the work for the user of getting absolute paths for both - // arguments, but that could make something costly (repeatedly - // normalizing paths) convenient, when it would be better for the user - // to store already-finalized paths and operate on those instead. - return "", .Invalid_Path - } - - // This is the other point where Windows and POSIX differ, as Windows is - // case-insensitive. - common := _get_common_path_len(base, target) - - // Get the result of splitting `base` and `target` on _Path_Separator, - // comparing them up to their most common elements, then count how many - // unshared parts are in the split `base`. - seps := 0 - size := 0 - if len(base)-common > 0 { - seps = 1 - size = 2 - } - // This range skips separators on the ends of the string. - for i in common+1.. 0 { - // Account for leading separators on the target after cutting the common part. - // (i.e. base == `/home`, target == `/home/a`) - if _is_path_separator(trailing[0]) { - trailing = trailing[1:] - } - size += len(trailing) - if seps > 0 { - size += 1 - } - } - if trailing == "." { - trailing = "" - size -= 2 - } - - // Build the string. - buf := make([]u8, size, allocator) or_return - n := 0 - if seps > 0 { - buf[0] = '.' - buf[1] = '.' - n = 2 - } - for _ in 1.. 0 { - if seps > 0 { - buf[n] = _Path_Separator - n += 1 - } - copy(buf[n:], trailing) - } - - path = string(buf) - - return -} - -/* -Split a path into a directory hierarchy and a filename. - -For example, `split_path("/home/foo/bar.tar.gz")` will return `"/home/foo"` and `"bar.tar.gz"`. -*/ -@(require_results) -split_path :: proc(path: string) -> (dir, filename: string) { - return _split_path(path) -} - -/* -Join all `elems` with the system's path separator and normalize the result. - -*Allocates Using Provided Allocator* - -For example, `join_path({"/home", "foo", "bar.txt"})` will result in `"/home/foo/bar.txt"`. -*/ -@(require_results) -join_path :: proc(elems: []string, allocator: runtime.Allocator) -> (joined: string, err: Error) { - for e, i in elems { - if e != "" { - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - p := strings.join(elems[i:], Path_Separator_String, temp_allocator) or_return - return clean_path(p, allocator) - } - } - return "", nil -} - -/* -Split a filename from its extension. - -This procedure splits on the last separator. - -If the filename begins with a separator, such as `".readme.txt"`, the separator -will be included in the filename, resulting in `".readme"` and `"txt"`. - -For example, `split_filename("foo.tar.gz")` will return `"foo.tar"` and `"gz"`. -*/ -@(require_results) -split_filename :: proc(filename: string) -> (base, ext: string) { - i := strings.last_index_byte(filename, '.') - if i <= 0 { - return filename, "" - } - return filename[:i], filename[i+1:] -} - -/* -Split a filename from its extension. - -This procedure splits on the first separator. - -If the filename begins with a separator, such as `".readme.txt.gz"`, the separator -will be included in the filename, resulting in `".readme"` and `"txt.gz"`. - -For example, `split_filename_all("foo.tar.gz")` will return `"foo"` and `"tar.gz"`. -*/ -@(require_results) -split_filename_all :: proc(filename: string) -> (base, ext: string) { - i := strings.index_byte(filename, '.') - if i == 0 { - j := strings.index_byte(filename[1:], '.') - if j != -1 { - j += 1 - } - i = j - } - if i == -1 { - return filename, "" - } - return filename[:i], filename[i+1:] -} - -/* -Join `base` and `ext` with the system's filename extension separator. - -*Allocates Using Provided Allocator* - -For example, `join_filename("foo", "tar.gz")` will result in `"foo.tar.gz"`. -*/ -@(require_results) -join_filename :: proc(base: string, ext: string, allocator: runtime.Allocator) -> (joined: string, err: Error) { - if len(base) == 0 { - return strings.clone(ext, allocator) - } else if len(ext) == 0 { - return strings.clone(base, allocator) - } - - buf := make([]u8, len(base) + 1 + len(ext), allocator) or_return - copy(buf, base) - buf[len(base)] = '.' - copy(buf[1+len(base):], ext) - - return string(buf), nil -} - -/* -Split a string that is separated by a system-specific separator, typically used -for environment variables specifying multiple directories. - -*Allocates Using Provided Allocator* - -For example, there is the "PATH" environment variable on POSIX systems which -this procedure can split into separate entries. -*/ -@(require_results) -split_path_list :: proc(path: string, allocator: runtime.Allocator) -> (list: []string, err: Error) { - if path == "" { - return nil, nil - } - - start: int - quote: bool - - start, quote = 0, false - count := 0 - - for i := 0; i < len(path); i += 1 { - c := path[i] - switch { - case c == '"': - quote = !quote - case c == Path_List_Separator && !quote: - count += 1 - } - } - - start, quote = 0, false - list = make([]string, count + 1, allocator) or_return - index := 0 - for i := 0; i < len(path); i += 1 { - c := path[i] - switch { - case c == '"': - quote = !quote - case c == Path_List_Separator && !quote: - list[index] = path[start:i] - index += 1 - start = i + 1 - } - } - assert(index == count) - list[index] = path[start:] - - for s0, i in list { - s, new := strings.replace_all(s0, `"`, ``, allocator) - if !new { - s = strings.clone(s, allocator) or_return - } - list[i] = s - } - - return list, nil -} diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin deleted file mode 100644 index d6b524684..000000000 --- a/core/os/os2/stat.odin +++ /dev/null @@ -1,86 +0,0 @@ -package os2 - -import "base:runtime" -import "core:strings" -import "core:time" - -Fstat_Callback :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) - -File_Info :: struct { - fullpath: string, - name: string, - - inode: u128, // might be zero if cannot be determined - size: i64 `fmt:"M"`, - mode: int `fmt:"o"`, - type: File_Type, - - creation_time: time.Time, - modification_time: time.Time, - access_time: time.Time, -} - -@(require_results) -file_info_clone :: proc(fi: File_Info, allocator: runtime.Allocator) -> (cloned: File_Info, err: runtime.Allocator_Error) { - cloned = fi - cloned.fullpath = strings.clone(fi.fullpath, allocator) or_return - _, cloned.name = split_path(cloned.fullpath) - return -} - -file_info_slice_delete :: proc(infos: []File_Info, allocator: runtime.Allocator) { - #reverse for info in infos { - file_info_delete(info, allocator) - } - delete(infos, allocator) -} - -file_info_delete :: proc(fi: File_Info, allocator: runtime.Allocator) { - delete(fi.fullpath, allocator) -} - -@(require_results) -fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { - if f == nil { - return {}, nil - } else if f.fstat != nil { - return f->fstat(allocator) - } - return {}, .Invalid_Callback -} - -@(require_results) -stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { - return _stat(name, allocator) -} - -lstat :: stat_do_not_follow_links - -@(require_results) -stat_do_not_follow_links :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { - return _lstat(name, allocator) -} - - -@(require_results) -same_file :: proc(fi1, fi2: File_Info) -> bool { - return _same_file(fi1, fi2) -} - - -last_write_time :: modification_time -last_write_time_by_name :: modification_time_by_path - -@(require_results) -modification_time :: proc(f: ^File) -> (time.Time, Error) { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - fi, err := fstat(f, temp_allocator) - return fi.modification_time, err -} - -@(require_results) -modification_time_by_path :: proc(path: string) -> (time.Time, Error) { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - fi, err := stat(path, temp_allocator) - return fi.modification_time, err -} diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin deleted file mode 100644 index 918c86f76..000000000 --- a/core/os/os2/stat_windows.odin +++ /dev/null @@ -1,370 +0,0 @@ -#+private -package os2 - -import "base:runtime" -import "core:time" -import "core:strings" -import win32 "core:sys/windows" - -_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { - if f == nil || (^File_Impl)(f.impl).fd == nil { - return - } - - path := _cleanpath_from_handle(f, allocator) or_return - - h := _handle(f) - switch win32.GetFileType(h) { - case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR: - fi = File_Info { - fullpath = path, - name = basename(path), - type = file_type(h), - } - return - } - - return _file_info_from_get_file_information_by_handle(path, h, allocator) -} - -_stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { - return internal_stat(name, win32.FILE_FLAG_BACKUP_SEMANTICS, allocator) -} - -_lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { - return internal_stat(name, win32.FILE_FLAG_BACKUP_SEMANTICS|win32.FILE_FLAG_OPEN_REPARSE_POINT, allocator) -} - -_same_file :: proc(fi1, fi2: File_Info) -> bool { - return fi1.fullpath == fi2.fullpath -} - -full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path: string, err: Error) { - name := name - if name == "" { - name = "." - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - p := win32_utf8_to_utf16(name, temp_allocator) or_return - - n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil) - if n == 0 { - return "", _get_platform_error() - } - buf := make([]u16, n+1, temp_allocator) - n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) - if n == 0 { - return "", _get_platform_error() - } - return win32_utf16_to_utf8(buf[:n], allocator) -} - -internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { - if len(name) == 0 { - return {}, .Not_Exist - } - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - wname := _fix_long_path(name, temp_allocator) or_return - fa: win32.WIN32_FILE_ATTRIBUTE_DATA - ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa) - if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - // Not a symlink - fi = _file_info_from_win32_file_attribute_data(&fa, name, allocator) or_return - if fi.type == .Undetermined { - fi.type = _file_type_from_create_file(wname, create_file_attributes) - } - return - } - - err := 0 if ok else win32.GetLastError() - - if err == win32.ERROR_SHARING_VIOLATION { - fd: win32.WIN32_FIND_DATAW - sh := win32.FindFirstFileW(wname, &fd) - if sh == win32.INVALID_HANDLE_VALUE { - e = _get_platform_error() - return - } - win32.FindClose(sh) - - fi = _file_info_from_win32_find_data(&fd, name, allocator) or_return - if fi.type == .Undetermined { - fi.type = _file_type_from_create_file(wname, create_file_attributes) - } - return - } - - h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) - if h == win32.INVALID_HANDLE_VALUE { - e = _get_platform_error() - return - } - defer win32.CloseHandle(h) - return _file_info_from_get_file_information_by_handle(name, h, allocator) -} - -_cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { - buf := buf - N := 0 - for c, i in buf { - if c == 0 { break } - N = i+1 - } - buf = buf[:N] - - if len(buf) >= 4 { - if buf[0] == '\\' && - buf[1] == '\\' && - buf[2] == '?' && - buf[3] == '\\' { - buf = buf[4:] - } - } - return buf -} - -_cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (string, Error) { - if f == nil { - return "", nil - } - h := _handle(f) - - n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0) - if n == 0 { - return "", _get_platform_error() - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - buf := make([]u16, max(n, 260)+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0) - return _cleanpath_from_buf(buf[:n], allocator) -} - -_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) { - if f == nil { - return nil, nil - } - h := _handle(f) - - n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0) - if n == 0 { - return nil, _get_platform_error() - } - - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - - buf := make([]u16, max(n, 260)+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0) - return _cleanpath_strip_prefix(buf[:n]), nil -} - -_cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { - buf := buf - buf = _cleanpath_strip_prefix(buf) - return win32_utf16_to_utf8(buf, allocator) -} - -basename :: proc(name: string) -> (base: string) { - name := name - if len(name) > 3 && name[:3] == `\\?` { - name = name[3:] - } - - if len(name) == 2 && name[1] == ':' { - return "." - } else if len(name) > 2 && name[1] == ':' { - name = name[2:] - } - i := len(name)-1 - - for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i -= 1 { - name = name[:i] - } - for i -= 1; i >= 0; i -= 1 { - if name[i] == '/' || name[i] == '\\' { - name = name[i+1:] - break - } - } - return name -} - -file_type :: proc(h: win32.HANDLE) -> File_Type { - switch win32.GetFileType(h) { - case win32.FILE_TYPE_PIPE: return .Named_Pipe - case win32.FILE_TYPE_CHAR: return .Character_Device - case win32.FILE_TYPE_DISK: return .Regular - } - return .Undetermined -} - -_file_type_from_create_file :: proc(wname: win32.wstring, create_file_attributes: u32) -> File_Type { - h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) - if h == win32.INVALID_HANDLE_VALUE { - return .Undetermined - } - defer win32.CloseHandle(h) - return file_type(h) -} - -_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: int) { - // NOTE(Jeroen): We don't translate mode flags for Linux when given to `chmod`. - // Let's not do so for Windows for `chmod` or `read_directory_iterator` either. - // They're *not* portable between Windows and non-Windows platforms. - // - // It also leads to information loss as flags like Archive, Hidden and System have no equivalent there. - // We can of course parse them so we can set the `.Symlink` and `.Directory` type, but we shouldn't pretend - // that 0o644 is meaningful when returned as a mode. - // `C:\bootmgr` as an example has attributes read only, hidden, system, archive. In no way is it sensible to replace that with 0o444. - mode = int(file_attributes) - - is_sym := false - if file_attributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { - is_sym = false - } else { - is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT - } - - if is_sym { - type = .Symlink - } else if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - type = .Directory - } else if h != nil { - type = file_type(h) - } - return -} - -// a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC) -time_as_filetime :: #force_inline proc(t: time.Time) -> (ft: win32.LARGE_INTEGER) { - win := u64(t._nsec / 100) + 116444736000000000 - return win32.LARGE_INTEGER(win) -} - -filetime_as_time_li :: #force_inline proc(ft: win32.LARGE_INTEGER) -> (t: time.Time) { - return {_nsec=(i64(ft) - 116444736000000000) * 100} -} - -filetime_as_time_ft :: #force_inline proc(ft: win32.FILETIME) -> (t: time.Time) { - return filetime_as_time_li(win32.LARGE_INTEGER(ft.dwLowDateTime) + win32.LARGE_INTEGER(ft.dwHighDateTime) << 32) -} - -filetime_as_time :: proc{filetime_as_time_ft, filetime_as_time_li} - -_file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) - fi.type = type - fi.mode |= mode - fi.creation_time = filetime_as_time(d.ftCreationTime) - fi.modification_time = filetime_as_time(d.ftLastWriteTime) - fi.access_time = filetime_as_time(d.ftLastAccessTime) - fi.fullpath, e = full_path_from_name(name, allocator) - fi.name = basename(fi.fullpath) - return -} - -_file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) - fi.type = type - fi.mode |= mode - fi.creation_time = filetime_as_time(d.ftCreationTime) - fi.modification_time = filetime_as_time(d.ftLastWriteTime) - fi.access_time = filetime_as_time(d.ftLastAccessTime) - fi.fullpath, e = full_path_from_name(name, allocator) - fi.name = basename(fi.fullpath) - return -} - -_file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE, allocator: runtime.Allocator) -> (File_Info, Error) { - d: win32.BY_HANDLE_FILE_INFORMATION - if !win32.GetFileInformationByHandle(h, &d) { - return {}, _get_platform_error() - - } - - ti: win32.FILE_ATTRIBUTE_TAG_INFO - if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) { - err := win32.GetLastError() - if err != win32.ERROR_INVALID_PARAMETER { - return {}, Platform_Error(err) - } - // Indicate this is a symlink on FAT file systems - ti.ReparseTag = 0 - } - fi: File_Info - fi.fullpath = path - fi.name = basename(path) - fi.inode = u128(u64(d.nFileIndexHigh)<<32 + u64(d.nFileIndexLow)) - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, h, 0) - fi.type = type - fi.mode |= mode - fi.creation_time = filetime_as_time(d.ftCreationTime) - fi.modification_time = filetime_as_time(d.ftLastWriteTime) - fi.access_time = filetime_as_time(d.ftLastAccessTime) - return fi, nil -} - -reserved_names := [?]string{ - "CON", "PRN", "AUX", "NUL", - "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", - "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", -} - -_is_reserved_name :: proc(path: string) -> bool { - if len(path) == 0 { - return false - } - for reserved in reserved_names { - if strings.equal_fold(path, reserved) { - return true - } - } - return false -} - -_is_UNC :: proc(path: string) -> bool { - return _volume_name_len(path) > 2 -} - -_volume_name_len :: proc(path: string) -> int { - if len(path) < 2 { - return 0 - } - c := path[0] - if path[1] == ':' { - switch c { - case 'a'..='z', 'A'..='Z': - return 2 - } - } - - // URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx - if l := len(path); l >= 5 && _is_path_separator(path[0]) && _is_path_separator(path[1]) && - !_is_path_separator(path[2]) && path[2] != '.' { - for n := 3; n < l-1; n += 1 { - if _is_path_separator(path[n]) { - n += 1 - if !_is_path_separator(path[n]) { - if path[n] == '.' { - break - } - } - for ; n < l; n += 1 { - if _is_path_separator(path[n]) { - break - } - } - return n - } - break - } - } - return 0 -} diff --git a/core/os/os2/user.odin b/core/os/os2/user.odin deleted file mode 100644 index b2856a319..000000000 --- a/core/os/os2/user.odin +++ /dev/null @@ -1,79 +0,0 @@ -package os2 - -import "base:runtime" - -@(require_results) -user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - #partial switch ODIN_OS { - case .Windows: - dir = get_env("LocalAppData", temp_allocator) - if dir != "" { - dir = clone_string(dir, temp_allocator) or_return - } - case .Darwin: - dir = get_env("HOME", temp_allocator) - if dir != "" { - dir = concatenate({dir, "/Library/Caches"}, temp_allocator) or_return - } - case: // All other UNIX systems - dir = get_env("XDG_CACHE_HOME", allocator) - if dir == "" { - dir = get_env("HOME", temp_allocator) - if dir == "" { - return - } - dir = concatenate({dir, "/.cache"}, temp_allocator) or_return - } - } - if dir == "" { - err = .Invalid_Path - } - return -} - -@(require_results) -user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - - #partial switch ODIN_OS { - case .Windows: - dir = get_env("AppData", temp_allocator) - if dir != "" { - dir = clone_string(dir, allocator) or_return - } - case .Darwin: - dir = get_env("HOME", temp_allocator) - if dir != "" { - dir = concatenate({dir, "/.config"}, allocator) or_return - } - case: // All other UNIX systems - dir = get_env("XDG_CONFIG_HOME", allocator) - if dir == "" { - dir = get_env("HOME", temp_allocator) - if dir == "" { - return - } - dir = concatenate({dir, "/.config"}, allocator) or_return - } - } - if dir == "" { - err = .Invalid_Path - } - return -} - -@(require_results) -user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { - env := "HOME" - #partial switch ODIN_OS { - case .Windows: - env = "USERPROFILE" - } - if v := get_env(env, allocator); v != "" { - return v, nil - } - return "", .Invalid_Path -} - diff --git a/core/os/os_essence.odin b/core/os/os_essence.odin deleted file mode 100644 index 75c4c1156..000000000 --- a/core/os/os_essence.odin +++ /dev/null @@ -1,60 +0,0 @@ -package os - -import "core:sys/es" - -Handle :: distinct int -_Platform_Error :: enum i32 {NONE} - -// ERROR_NONE :: Error(es.SUCCESS) - -O_RDONLY :: 0x1 -O_WRONLY :: 0x2 -O_CREATE :: 0x4 -O_TRUNC :: 0x8 - -stderr : Handle = 0 - -current_thread_id :: proc "contextless" () -> int { - return (int) (es.ThreadGetID(es.CURRENT_THREAD)) -} - -heap_alloc :: proc(size: int, zero_memory := true) -> rawptr { - return es.HeapAllocate(size, zero_memory) -} - -heap_free :: proc(ptr: rawptr) { - es.HeapFree(ptr) -} - -heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { - return es.HeapReallocate(ptr, new_size, false) -} - -open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { - return (Handle) (0), (Error) (1) -} - -close :: proc(fd: Handle) -> Error { - return (Error) (1) -} - -file_size :: proc(fd: Handle) -> (i64, Error) { - return (i64) (0), (Error) (1) -} - -read :: proc(fd: Handle, data: []byte) -> (int, Error) { - return (int) (0), (Error) (1) -} - -write :: proc(fd: Handle, data: []u8) -> (int, Error) { - return (int) (0), (Error) (1) -} - -seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { - return (i64) (0), (Error) (1) -} - -flush :: proc(fd: Handle) -> Error { - // do nothing - return nil -} \ No newline at end of file diff --git a/core/os/os_freestanding.odin b/core/os/os_freestanding.odin deleted file mode 100644 index c22a6d7d5..000000000 --- a/core/os/os_freestanding.odin +++ /dev/null @@ -1,4 +0,0 @@ -#+build freestanding -package os - -#panic("package os does not support a freestanding target") diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin deleted file mode 100644 index 4a57afb87..000000000 --- a/core/os/os_haiku.odin +++ /dev/null @@ -1,506 +0,0 @@ -package os - -foreign import lib "system:c" - -import "base:runtime" -import "core:c" -import "core:c/libc" -import "core:strings" -import "core:sys/haiku" -import "core:sys/posix" - -Handle :: i32 -Pid :: i32 -File_Time :: i64 -_Platform_Error :: haiku.Errno - -MAX_PATH :: haiku.PATH_MAX - -ENOSYS :: _Platform_Error(haiku.Errno.ENOSYS) - -INVALID_HANDLE :: ~Handle(0) - -stdin: Handle = 0 -stdout: Handle = 1 -stderr: Handle = 2 - -pid_t :: haiku.pid_t -off_t :: haiku.off_t -dev_t :: haiku.dev_t -ino_t :: haiku.ino_t -mode_t :: haiku.mode_t -nlink_t :: haiku.nlink_t -uid_t :: haiku.uid_t -gid_t :: haiku.gid_t -blksize_t :: haiku.blksize_t -blkcnt_t :: haiku.blkcnt_t -time_t :: haiku.time_t - - -Unix_File_Time :: struct { - seconds: time_t, - nanoseconds: c.long, -} - -OS_Stat :: struct { - device_id: dev_t, // device ID that this file resides on - serial: ino_t, // this file's serial inode ID - mode: mode_t, // file mode (rwx for user, group, etc) - nlink: nlink_t, // number of hard links to this file - uid: uid_t, // user ID of the file's owner - gid: gid_t, // group ID of the file's group - size: off_t, // file size, in bytes - rdev: dev_t, // device type (not used) - block_size: blksize_t, // optimal blocksize for I/O - - last_access: Unix_File_Time, // time of last access - modified: Unix_File_Time, // time of last data modification - status_change: Unix_File_Time, // time of last file status change - birthtime: Unix_File_Time, // time of file creation - - type: u32, // attribute/index type - - blocks: blkcnt_t, // blocks allocated for file -} - -/* file access modes for open() */ -O_RDONLY :: 0x0000 /* read only */ -O_WRONLY :: 0x0001 /* write only */ -O_RDWR :: 0x0002 /* read and write */ -O_ACCMODE :: 0x0003 /* mask to get the access modes above */ -O_RWMASK :: O_ACCMODE - -/* flags for open() */ -O_EXCL :: 0x0100 /* exclusive creat */ -O_CREATE :: 0x0200 /* create and open file */ -O_TRUNC :: 0x0400 /* open with truncation */ -O_NOCTTY :: 0x1000 /* don't make tty the controlling tty */ -O_NOTRAVERSE :: 0x2000 /* do not traverse leaf link */ - -// File type -S_IFMT :: 0o170000 // Type of file mask -S_IFIFO :: 0o010000 // Named pipe (fifo) -S_IFCHR :: 0o020000 // Character special -S_IFDIR :: 0o040000 // Directory -S_IFBLK :: 0o060000 // Block special -S_IFREG :: 0o100000 // Regular -S_IFLNK :: 0o120000 // Symbolic link -S_IFSOCK :: 0o140000 // Socket -S_ISVTX :: 0o001000 // Save swapped text even after use - -// File mode - // Read, write, execute/search by owner -S_IRWXU :: 0o0700 // RWX mask for owner -S_IRUSR :: 0o0400 // R for owner -S_IWUSR :: 0o0200 // W for owner -S_IXUSR :: 0o0100 // X for owner - - // Read, write, execute/search by group -S_IRWXG :: 0o0070 // RWX mask for group -S_IRGRP :: 0o0040 // R for group -S_IWGRP :: 0o0020 // W for group -S_IXGRP :: 0o0010 // X for group - - // Read, write, execute/search by others -S_IRWXO :: 0o0007 // RWX mask for other -S_IROTH :: 0o0004 // R for other -S_IWOTH :: 0o0002 // W for other -S_IXOTH :: 0o0001 // X for other - -S_ISUID :: 0o4000 // Set user id on execution -S_ISGID :: 0o2000 // Set group id on execution -S_ISTXT :: 0o1000 // Sticky bit - -S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } - -__error :: libc.errno -_unix_open :: posix.open - -foreign lib { - @(link_name="fork") _unix_fork :: proc() -> pid_t --- - @(link_name="getthrid") _unix_getthrid :: proc() -> int --- - - @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int --- - @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- - @(link_name="pread") _unix_pread :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t --- - @(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- - @(link_name="pwrite") _unix_pwrite :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t --- - @(link_name="lseek") _unix_seek :: proc(fd: Handle, offset: off_t, whence: c.int) -> off_t --- - @(link_name="stat") _unix_stat :: proc(path: cstring, sb: ^OS_Stat) -> c.int --- - @(link_name="fstat") _unix_fstat :: proc(fd: Handle, sb: ^OS_Stat) -> c.int --- - @(link_name="lstat") _unix_lstat :: proc(path: cstring, sb: ^OS_Stat) -> c.int --- - @(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t --- - @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int --- - @(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring --- - @(link_name="chdir") _unix_chdir :: proc(path: cstring) -> c.int --- - @(link_name="rename") _unix_rename :: proc(old, new: cstring) -> c.int --- - @(link_name="unlink") _unix_unlink :: proc(path: cstring) -> c.int --- - @(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int --- - @(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int --- - @(link_name="fsync") _unix_fsync :: proc(fd: Handle) -> c.int --- - - @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int --- - @(link_name="sysconf") _sysconf :: proc(name: c.int) -> c.long --- - @(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir --- - @(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int --- - @(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) --- - @(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int --- - @(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle --- - - @(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr --- - @(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr --- - @(link_name="free") _unix_free :: proc(ptr: rawptr) --- - @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr --- - - @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- - @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: [^]byte = nil) -> cstring --- - - @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! --- - - @(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: c.int) -> rawptr --- - @(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr --- - @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int --- - @(link_name="dlerror") _unix_dlerror :: proc() -> cstring --- -} - -MAXNAMLEN :: haiku.NAME_MAX - -Dirent :: struct { - dev: dev_t, - pdef: dev_t, - ino: ino_t, - pino: ino_t, - reclen: u16, - name: [MAXNAMLEN + 1]byte, // name -} - -Dir :: distinct rawptr // DIR* - -@(require_results) -is_path_separator :: proc(r: rune) -> bool { - return r == '/' -} - -@(require_results, no_instrumentation) -get_last_error :: proc "contextless" () -> Error { - return Platform_Error(__error()^) -} - -@(require_results) -fork :: proc() -> (Pid, Error) { - pid := _unix_fork() - if pid == -1 { - return Pid(-1), get_last_error() - } - return Pid(pid), nil -} - -@(require_results) -open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - cstr := strings.clone_to_cstring(path, context.temp_allocator) - handle := cast(Handle)_unix_open(cstr, transmute(posix.O_Flags)i32(flags), transmute(posix.mode_t)i32(mode)) - if handle == -1 { - return INVALID_HANDLE, get_last_error() - } - return handle, nil -} - -close :: proc(fd: Handle) -> Error { - result := _unix_close(fd) - if result == -1 { - return get_last_error() - } - return nil -} - -flush :: proc(fd: Handle) -> Error { - result := _unix_fsync(fd) - if result == -1 { - return get_last_error() - } - return nil -} - -// In practice a read/write call would probably never read/write these big buffers all at once, -// which is why the number of bytes is returned and why there are procs that will call this in a -// loop for you. -// We set a max of 1GB to keep alignment and to be safe. -@(private) -MAX_RW :: 1 << 30 - -read :: proc(fd: Handle, data: []byte) -> (int, Error) { - to_read := min(c.size_t(len(data)), MAX_RW) - bytes_read := _unix_read(fd, &data[0], to_read) - if bytes_read == -1 { - return -1, get_last_error() - } - return int(bytes_read), nil -} - -write :: proc(fd: Handle, data: []byte) -> (int, Error) { - if len(data) == 0 { - return 0, nil - } - - to_write := min(c.size_t(len(data)), MAX_RW) - bytes_written := _unix_write(fd, &data[0], to_write) - if bytes_written == -1 { - return -1, get_last_error() - } - return int(bytes_written), nil -} - -read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) { - if len(data) == 0 { - return 0, nil - } - - to_read := min(uint(len(data)), MAX_RW) - - bytes_read := _unix_pread(fd, raw_data(data), to_read, offset) - if bytes_read < 0 { - return -1, get_last_error() - } - return bytes_read, nil -} - -write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) { - if len(data) == 0 { - return 0, nil - } - - to_write := min(uint(len(data)), MAX_RW) - - bytes_written := _unix_pwrite(fd, raw_data(data), to_write, offset) - if bytes_written < 0 { - return -1, get_last_error() - } - return bytes_written, nil -} - -seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { - switch whence { - case SEEK_SET, SEEK_CUR, SEEK_END: - break - case: - return 0, .Invalid_Whence - } - res := _unix_seek(fd, offset, c.int(whence)) - if res == -1 { - errno := get_last_error() - switch errno { - case .BAD_VALUE: - return 0, .Invalid_Offset - } - return 0, errno - } - return res, nil -} - -@(require_results) -file_size :: proc(fd: Handle) -> (i64, Error) { - s, err := _fstat(fd) - if err != nil { - return -1, err - } - return s.size, nil -} - -// "Argv" arguments converted to Odin strings -args := _alloc_command_line_arguments() - -@(require_results) -_alloc_command_line_arguments :: proc() -> []string { - res := make([]string, len(runtime.args__)) - for arg, i in runtime.args__ { - res[i] = string(arg) - } - return res -} - -@(private, require_results) -_stat :: proc(path: string) -> (OS_Stat, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - cstr := strings.clone_to_cstring(path, context.temp_allocator) - - // deliberately uninitialized - s: OS_Stat = --- - res := _unix_stat(cstr, &s) - if res == -1 { - return s, get_last_error() - } - return s, nil -} - -@(private, require_results) -_lstat :: proc(path: string) -> (OS_Stat, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - cstr := strings.clone_to_cstring(path, context.temp_allocator) - - // deliberately uninitialized - s: OS_Stat = --- - res := _unix_lstat(cstr, &s) - if res == -1 { - return s, get_last_error() - } - return s, nil -} - -@(private, require_results) -_fstat :: proc(fd: Handle) -> (OS_Stat, Error) { - // deliberately uninitialized - s: OS_Stat = --- - res := _unix_fstat(fd, &s) - if res == -1 { - return s, get_last_error() - } - return s, nil -} - -@(private) -_fdopendir :: proc(fd: Handle) -> (Dir, Error) { - dirp := _unix_fdopendir(fd) - if dirp == cast(Dir)nil { - return nil, get_last_error() - } - return dirp, nil -} - -@(private) -_closedir :: proc(dirp: Dir) -> Error { - rc := _unix_closedir(dirp) - if rc != 0 { - return get_last_error() - } - return nil -} - -@(private) -_rewinddir :: proc(dirp: Dir) { - _unix_rewinddir(dirp) -} - -@(private, require_results) -_readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { - result: ^Dirent - rc := _unix_readdir_r(dirp, &entry, &result) - - if rc != 0 { - err = get_last_error() - return - } - - if result == nil { - end_of_stream = true - return - } - - return -} - -@(private, require_results) -_readlink :: proc(path: string) -> (string, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) - path_cstr := strings.clone_to_cstring(path, context.temp_allocator) - - bufsz : uint = MAX_PATH - buf := make([]byte, MAX_PATH) - for { - rc := _unix_readlink(path_cstr, &(buf[0]), bufsz) - if rc == -1 { - delete(buf) - return "", get_last_error() - } else if rc == int(bufsz) { - bufsz += MAX_PATH - delete(buf) - buf = make([]byte, bufsz) - } else { - return strings.string_from_ptr(&buf[0], rc), nil - } - } -} - -@(require_results) -absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { - return "", Error(ENOSYS) -} - -@(require_results) -absolute_path_from_relative :: proc(rel: string, allocator := context.allocator) -> (path: string, err: Error) { - rel := rel - if rel == "" { - rel = "." - } - - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) - rel_cstr := strings.clone_to_cstring(rel, context.temp_allocator) - - path_ptr := _unix_realpath(rel_cstr, nil) - if path_ptr == nil { - return "", get_last_error() - } - defer _unix_free(rawptr(path_ptr)) - - path_cstr := cstring(path_ptr) - return strings.clone(string(path_cstr), allocator) -} - -access :: proc(path: string, mask: int) -> (bool, Error) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - cstr := strings.clone_to_cstring(path, context.temp_allocator) - res := _unix_access(cstr, c.int(mask)) - if res == -1 { - return false, get_last_error() - } - return true, nil -} - -@(require_results) -lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - path_str := strings.clone_to_cstring(key, context.temp_allocator) - cstr := _unix_getenv(path_str) - if cstr == nil { - return "", false - } - return strings.clone(string(cstr), allocator), true -} - -@(require_results) -get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { - value, _ = lookup_env(key, allocator) - return -} - -@(private, require_results) -_processor_core_count :: proc() -> int { - info: haiku.system_info - haiku.get_system_info(&info) - return int(info.cpu_count) -} - -exit :: proc "contextless" (code: int) -> ! { - runtime._cleanup_runtime_contextless() - _unix_exit(i32(code)) -} - -@(require_results) -current_thread_id :: proc "contextless" () -> int { - return int(haiku.find_thread(nil)) -} - -@(private, require_results) -_dup :: proc(fd: Handle) -> (Handle, Error) { - dup := _unix_dup(fd) - if dup == -1 { - return INVALID_HANDLE, get_last_error() - } - return dup, nil -} diff --git a/core/os/path.odin b/core/os/path.odin new file mode 100644 index 000000000..22ec2d3f7 --- /dev/null +++ b/core/os/path.odin @@ -0,0 +1,1016 @@ +package os + +import "base:runtime" +import "core:slice" +import "core:strings" +import "core:unicode/utf8" + + +Path_Separator :: _Path_Separator // OS-Specific +Path_Separator_String :: _Path_Separator_String // OS-Specific +Path_Separator_Chars :: `/\` +Path_List_Separator :: _Path_List_Separator // OS-Specific + +#assert(_Path_Separator <= rune(0x7F), "The system-specific path separator rune is expected to be within the 7-bit ASCII character set.") + +/* +Return true if `c` is a character used to separate paths into directory and +file hierarchies on the current system. +*/ +@(require_results) +is_path_separator :: proc(c: byte) -> bool { + return _is_path_separator(c) +} + +/* +Returns the result of replacing each path separator character in the path +with the `new_sep` rune. + +*Allocates Using Provided Allocator* +*/ +replace_path_separators :: proc(path: string, new_sep: rune, allocator: runtime.Allocator) -> (new_path: string, err: Error) { + length := len(path) + rep_b, rep_w := utf8.encode_rune(new_sep) + + byte_oriented := rep_w == 1 + + for r in path { + if r == '/' || r == '\\' { + length += rep_w - 1 + } + if r > rune(0x7f) { + byte_oriented = false + } + } + + buf := make([]u8, length, allocator) or_return + + if byte_oriented { + // Neither replacement rune or any other rune in the path takes up more than 1 byte + str := transmute([]byte)path + #no_bounds_check for b, i in str { + buf[i] = u8(new_sep) if b == '/' || b == '\\' else b + } + } else { + i: int + for r in path { + if r == '/' || r == '\\' { + copy(buf[i:], rep_b[:rep_w]) + i += rep_w + } else { + r_b, r_w := utf8.encode_rune(r) + copy(buf[i:], r_b[:r_w]) + i += r_w + } + } + } + return string(buf), nil +} + +mkdir :: make_directory + +/* +Make a new directory. + +If `path` is relative, it will be relative to the process's current working directory. +*/ +make_directory :: proc(name: string, perm := Permissions_Default_Directory) -> Error { + return _mkdir(name, perm) +} + +mkdir_all :: make_directory_all + +/* +Make a new directory, creating new intervening directories when needed. + +If `path` is relative, it will be relative to the process's current working directory. +*/ +make_directory_all :: proc(path: string, perm := Permissions_Default_Directory) -> Error { + return _mkdir_all(path, perm) +} + +/* +Delete `path` and all files and directories inside of `path` if it is a directory. + +If `path` is relative, it will be relative to the process's current working directory. +*/ +remove_all :: proc(path: string) -> Error { + return _remove_all(path) +} + +getwd :: get_working_directory + +/* +Get the working directory of the current process. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _get_working_directory(allocator) +} + +setwd :: set_working_directory + +/* +Change the working directory of the current process. + +*Allocates Using Provided Allocator* +*/ +set_working_directory :: proc(dir: string) -> (err: Error) { + return _set_working_directory(dir) +} + +/* +Get the path for the currently running executable. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + return _get_executable_path(allocator) +} + +/* +Get the directory for the currently running executable. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + path = _get_executable_path(allocator) or_return + path, _ = split_path(path) + return +} + +/* +Compare two paths for exactness without normalization. + +This procedure takes into account case-sensitivity on differing systems. +*/ +@(require_results) +are_paths_identical :: proc(a, b: string) -> (identical: bool) { + return _are_paths_identical(a, b) +} + +/* +Normalize a path. + +*Allocates Using Provided Allocator* + +This will remove duplicate separators and unneeded references to the current or +parent directory. +*/ +@(require_results) +clean_path :: proc(path: string, allocator: runtime.Allocator) -> (cleaned: string, err: runtime.Allocator_Error) { + if path == "" || path == "." { + return strings.clone(".", allocator) + } + + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + // The extra byte is to simplify appending path elements by letting the + // loop to end each with a separator. We'll trim the last one when we're done. + buffer := make([]u8, len(path) + 1, temp_allocator) or_return + + // This is the only point where Windows and POSIX differ, as Windows has + // alphabet-based volumes for root paths. + rooted, start := _clean_path_handle_start(path, buffer) + + head, buffer_i := start, start + for i, j := start, start; i <= len(path); i += 1 { + if i == len(path) || _is_path_separator(path[i]) { + elem := path[j:i] + j = i + 1 + + switch elem { + case "", ".": + // Skip duplicate path separators and current directory references. + case "..": + if !rooted && buffer_i == head { + // Only allow accessing further parent directories when the path is relative. + buffer[buffer_i] = '.' + buffer[buffer_i+1] = '.' + buffer[buffer_i+2] = _Path_Separator + buffer_i += 3 + head = buffer_i + } else { + // Roll back to the last separator or the head of the buffer. + back_to := head + // `buffer_i` will be equal to 1 + the last set byte, so + // skipping two bytes avoids the final separator we just + // added. + for k := buffer_i-2; k >= head; k -= 1 { + if _is_path_separator(buffer[k]) { + back_to = k + 1 + break + } + } + buffer_i = back_to + } + case: + // Copy the path element verbatim and add a separator. + copy(buffer[buffer_i:], elem) + buffer_i += len(elem) + buffer[buffer_i] = _Path_Separator + buffer_i += 1 + } + } + } + + // Trim the final separator. + // NOTE: No need to check if the last byte is a separator, as we always add it. + if buffer_i > start { + buffer_i -= 1 + } + + if buffer_i == 0 { + return strings.clone(".", allocator) + } + + compact := make([]u8, buffer_i, allocator) or_return + copy(compact, buffer) // NOTE(bill): buffer[:buffer_i] is redundant here + return string(compact), nil +} + +/* +Return true if `path` is an absolute path as opposed to a relative one. +*/ +@(require_results) +is_absolute_path :: proc(path: string) -> bool { + return _is_absolute_path(path) +} + +/* +Get the absolute path to `path` with respect to the process's current directory. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + return _get_absolute_path(path, allocator) +} + +/* +Get the relative path needed to change directories from `base` to `target`. + +*Allocates Using Provided Allocator* + +The result is such that `join_path(base, get_relative_path(base, target))` is equivalent to `target`. + +NOTE: This procedure expects both `base` and `target` to be normalized first, +which can be done by calling `clean_path` on them if needed. + +This procedure will return an `Invalid_Path` error if `base` begins with a +reference to the parent directory (`".."`). Use `get_working_directory` with +`join_path` to construct absolute paths for both arguments instead. +*/ +@(require_results) +get_relative_path :: proc(base, target: string, allocator: runtime.Allocator) -> (path: string, err: Error) { + if _are_paths_identical(base, target) { + return strings.clone(".", allocator) + } + if base == "." { + return strings.clone(target, allocator) + } + + // This is the first point where Windows and POSIX differ, as Windows has + // alphabet-based volumes for root paths. + if !_get_relative_path_handle_start(base, target) { + return "", .Invalid_Path + } + if strings.has_prefix(base, "..") && (len(base) == 2 || _is_path_separator(base[2])) { + // We could do the work for the user of getting absolute paths for both + // arguments, but that could make something costly (repeatedly + // normalizing paths) convenient, when it would be better for the user + // to store already-finalized paths and operate on those instead. + return "", .Invalid_Path + } + + // This is the other point where Windows and POSIX differ, as Windows is + // case-insensitive. + common := _get_common_path_len(base, target) + + // Get the result of splitting `base` and `target` on _Path_Separator, + // comparing them up to their most common elements, then count how many + // unshared parts are in the split `base`. + seps := 0 + size := 0 + if len(base)-common > 0 { + seps = 1 + size = 2 + } + // This range skips separators on the ends of the string. + for i in common+1.. 0 { + // Account for leading separators on the target after cutting the common part. + // (i.e. base == `/home`, target == `/home/a`) + if _is_path_separator(trailing[0]) { + trailing = trailing[1:] + } + size += len(trailing) + if seps > 0 { + size += 1 + } + } + if trailing == "." { + trailing = "" + size -= 2 + } + + // Build the string. + buf := make([]u8, size, allocator) or_return + n := 0 + if seps > 0 { + buf[0] = '.' + buf[1] = '.' + n = 2 + } + for _ in 1.. 0 { + if seps > 0 { + buf[n] = _Path_Separator + n += 1 + } + copy(buf[n:], trailing) + } + + path = string(buf) + + return +} + +/* +Split a path into a directory hierarchy and a filename. + +For example, `split_path("/home/foo/bar.tar.gz")` will return `"/home/foo"` and `"bar.tar.gz"`. +*/ +@(require_results) +split_path :: proc(path: string) -> (dir, filename: string) { + return _split_path(path) +} + + +/* +Gets the file name and extension from a path. + +e.g. + 'path/to/name.tar.gz' -> 'name.tar.gz' + 'path/to/name.txt' -> 'name.txt' + 'path/to/name' -> 'name' + +Returns "." if the path is an empty string. +*/ +base :: proc(path: string) -> string { + if path == "" { + return "." + } + + _, file := split_path(path) + return file +} + +/* +Gets the parent directory path from a path. + +e.g. + '/home/foo/bar.tar.gz' -> '/home/foo' + 'path/to/name.tar.gz' -> 'path/to' + +Returns "." if the path is an empty string. +*/ +dir :: proc(path: string) -> string { + if path == "" { + return "." + } + + d, _ := split_path(path) + return d +} + +/* +Gets the name of a file from a path. + +The stem of a file is such that `stem(path)` + `ext(path)` = `base(path)`. + +Only the last dot is considered when splitting the file extension. +See `short_stem`. + +e.g. + 'name.tar.gz' -> 'name.tar' + 'name.txt' -> 'name' + +Returns an empty string if the path is empty +Returns an empty string if there is no stem. e.g: '.gitignore'. +Returns an empty string if there's a trailing path separator. +*/ +stem :: proc(path: string) -> string { + if path == "" { + return "" + } + + // If the last character is a path separator, there is no file. + if is_path_separator(path[len(path) - 1]) { + return "" + } + + // Get the base path. + p := base(path) + if i := strings.last_index_any(p, Path_Separator_Chars); i != -1 { + p = p[i+1:] + } + + if i := strings.last_index_byte(p, '.'); i != -1 { + return p[:i] + } + return p +} + +/* +Gets the name of a file from a path. + +The short stem is such that `short_stem(path)` + `long_ext(path)` = `base(path)`, +where `long_ext` is the extension returned by `split_filename_all`. + +The first dot is used to split off the file extension, unlike `stem` which uses the last dot. + +e.g. + 'name.tar.gz' -> 'name' + 'name.txt' -> 'name' + +Returns an empty string if there is no stem. e.g: '.gitignore'. +Returns an empty string if there's a trailing path separator. +*/ +short_stem :: proc(path: string) -> string { + s := stem(path) + if i := strings.index_byte(s, '.'); i != -1 { + return s[:i] + } + return s +} + +/* +Gets the file extension from a path, including the dot. + +The file extension is such that `stem_path(path)` + `ext(path)` = `base(path)`. + +Only the last dot is considered when splitting the file extension. +See `long_ext`. + +e.g. + 'name.tar.gz' -> '.gz' + 'name.txt' -> '.txt' + +Returns an empty string if there is no dot. +Returns an empty string if there is a trailing path separator. +*/ +ext :: proc(path: string) -> string { + for i := len(path)-1; i >= 0 && !is_path_separator(path[i]); i -= 1 { + if path[i] == '.' { + return path[i:] + } + } + return "" +} + +/* +Gets the file extension from a path, including the dot. + +The long file extension is such that `short_stem(path)` + `long_ext(path)` = `base(path)`. + +The first dot is used to split off the file extension, unlike `ext` which uses the last dot. + +e.g. + 'name.tar.gz' -> '.tar.gz' + 'name.txt' -> '.txt' + +Returns an empty string if there is no dot. +Returns an empty string if there is a trailing path separator. +*/ +long_ext :: proc(path: string) -> string { + if len(path) > 0 && is_path_separator(path[len(path) - 1]) { + // NOTE(tetra): Trailing separator + return "" + } + + // NOTE(tetra): Get the basename + path := path + if i := strings.last_index_any(path, Path_Separator_Chars); i != -1 { + path = path[i+1:] + } + + if i := strings.index_byte(path, '.'); i != -1 { + return path[i:] + } + + return "" +} + +/* +Join all `elems` with the system's path separator and normalize the result. + +*Allocates Using Provided Allocator* + +For example, `join_path({"/home", "foo", "bar.txt"})` will result in `"/home/foo/bar.txt"`. +*/ +@(require_results) +join_path :: proc(elems: []string, allocator: runtime.Allocator) -> (joined: string, err: runtime.Allocator_Error) { + for e, i in elems { + if e != "" { + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + p := strings.join(elems[i:], Path_Separator_String, temp_allocator) or_return + return clean_path(p, allocator) + } + } + return "", nil +} + +/* +Split a filename from its extension. + +This procedure splits on the last separator. + +If the filename begins with a separator, such as `".readme.txt"`, the separator +will be included in the filename, resulting in `".readme"` and `"txt"`. + +For example, `split_filename("foo.tar.gz")` will return `"foo.tar"` and `"gz"`. +*/ +@(require_results) +split_filename :: proc(filename: string) -> (base, ext: string) { + i := strings.last_index_byte(filename, '.') + if i <= 0 { + return filename, "" + } + return filename[:i], filename[i+1:] +} + +/* +Split a filename from its extension. + +This procedure splits on the first separator. + +If the filename begins with a separator, such as `".readme.txt.gz"`, the separator +will be included in the filename, resulting in `".readme"` and `"txt.gz"`. + +For example, `split_filename_all("foo.tar.gz")` will return `"foo"` and `"tar.gz"`. +*/ +@(require_results) +split_filename_all :: proc(filename: string) -> (base, ext: string) { + i := strings.index_byte(filename, '.') + if i == 0 { + j := strings.index_byte(filename[1:], '.') + if j != -1 { + j += 1 + } + i = j + } + if i == -1 { + return filename, "" + } + return filename[:i], filename[i+1:] +} + +/* +Join `base` and `ext` with the system's filename extension separator. + +*Allocates Using Provided Allocator* + +For example, `join_filename("foo", "tar.gz")` will result in `"foo.tar.gz"`. +*/ +@(require_results) +join_filename :: proc(base: string, ext: string, allocator: runtime.Allocator) -> (joined: string, err: Error) { + if len(base) == 0 { + return strings.clone(ext, allocator) + } else if len(ext) == 0 { + return strings.clone(base, allocator) + } + + buf := make([]u8, len(base) + 1 + len(ext), allocator) or_return + copy(buf, base) + buf[len(base)] = '.' + copy(buf[1+len(base):], ext) + + return string(buf), nil +} + +/* +Split a string that is separated by a system-specific separator, typically used +for environment variables specifying multiple directories. + +*Allocates Using Provided Allocator* + +For example, there is the "PATH" environment variable on POSIX systems which +this procedure can split into separate entries. +*/ +@(require_results) +split_path_list :: proc(path: string, allocator: runtime.Allocator) -> (list: []string, err: Error) { + if path == "" { + return nil, nil + } + + start: int + quote: bool + + start, quote = 0, false + count := 0 + + for i := 0; i < len(path); i += 1 { + c := path[i] + switch { + case c == '"': + quote = !quote + case c == Path_List_Separator && !quote: + count += 1 + } + } + + start, quote = 0, false + list = make([]string, count + 1, allocator) or_return + index := 0 + for i := 0; i < len(path); i += 1 { + c := path[i] + switch { + case c == '"': + quote = !quote + case c == Path_List_Separator && !quote: + list[index] = path[start:i] + index += 1 + start = i + 1 + } + } + assert(index == count) + list[index] = path[start:] + + for s0, i in list { + s, new := strings.replace_all(s0, `"`, ``, allocator) + if !new { + s = strings.clone(s, allocator) or_return + } + list[i] = s + } + + return list, nil +} + +/* +`match` states whether "name" matches the shell pattern + +Pattern syntax is: + pattern: + {term} + term: + '*' matches any sequence of non-/ characters + '?' matches any single non-/ character + '[' ['^'] { character-range } ']' + character classification (cannot be empty) + c matches character c (c != '*', '?', '\\', '[') + '\\' c matches character c + + character-range + c matches character c (c != '\\', '-', ']') + '\\' c matches character c + lo '-' hi matches character c for lo <= c <= hi + +`match` requires that the pattern matches the entirety of the name, not just a substring. +The only possible error returned is `.Syntax_Error` or an allocation error. + +NOTE(bill): This is effectively the shell pattern matching system found +*/ +match :: proc(pattern, name: string) -> (matched: bool, err: Error) { + pattern, name := pattern, name + pattern_loop: for len(pattern) > 0 { + star: bool + chunk: string + star, chunk, pattern = scan_chunk(pattern) + if star && chunk == "" { + return !strings.contains(name, _Path_Separator_String), nil + } + + t, ok := match_chunk(chunk, name) or_return + + if ok && (len(t) == 0 || len(pattern) > 0) { + name = t + continue + } + + if star { + for i := 0; i < len(name) && name[i] != _Path_Separator; i += 1 { + t, ok = match_chunk(chunk, name[i+1:]) or_return + if ok { + if len(pattern) == 0 && len(t) > 0 { + continue + } + name = t + continue pattern_loop + } + } + } + + return false, nil + } + + return len(name) == 0, nil +} + +// glob returns the names of all files matching pattern or nil if there are no matching files +// The syntax of patterns is the same as "match". +// The pattern may describe hierarchical names such as /usr/*/bin (assuming '/' is a separator) +// +// glob ignores file system errors +// +glob :: proc(pattern: string, allocator := context.allocator) -> (matches: []string, err: Error) { + _split :: proc(path: string) -> (dir, file: string) { + vol := volume_name(path) + i := len(path) - 1 + for i >= len(vol) && !is_path_separator(path[i]) { + i -= 1 + } + return path[:i+1], path[i+1:] + } + + context.allocator = allocator + + if !has_meta(pattern) { + // TODO(bill): os.lstat on here to check for error + m := make([]string, 1) + m[0] = pattern + return m[:], nil + } + + // NOTE(Jeroen): For `glob`, we need this version of `split`, which leaves the trailing `/` on `dir`. + dir, file := _split(pattern) + + temp_buf: [8]byte + vol_len: int + vol_len, dir = clean_glob_path(dir, temp_buf[:]) + + if !has_meta(dir[vol_len:]) { + m, e := _glob(dir, file, nil) + return m[:], e + } + + m := glob(dir) or_return + defer { + for s in m { + delete(s) + } + delete(m) + } + + dmatches := make([dynamic]string, 0, 0) + for d in m { + dmatches, err = _glob(d, file, &dmatches) + if err != nil { + break + } + } + if len(dmatches) > 0 { + matches = dmatches[:] + } + return +} + +/* + Returns leading volume name. + + e.g. + "C:\foo\bar\baz" will return "C:" on Windows. + Everything else will be "". +*/ +volume_name :: proc(path: string) -> string { + when ODIN_OS == .Windows { + return path[:_volume_name_len(path)] + } else { + return "" + } +} + +@(private="file") +scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) { + pattern := pattern + for len(pattern) > 0 && pattern[0] == '*' { + pattern = pattern[1:] + star = true + } + + in_range, i := false, 0 + + scan_loop: for i = 0; i < len(pattern); i += 1 { + switch pattern[i] { + case '\\': + when ODIN_OS != .Windows { + if i+1 < len(pattern) { + i += 1 + } + } + case '[': + in_range = true + case ']': + in_range = false + case '*': + in_range or_break scan_loop + + } + } + return star, pattern[:i], pattern[i:] +} + +@(private="file") +match_chunk :: proc(chunk, s: string) -> (rest: string, ok: bool, err: Error) { + slash_equal :: proc(a, b: u8) -> bool { + switch a { + case '/': return b == '/' || b == '\\' + case '\\': return b == '/' || b == '\\' + case: return a == b + } + } + + chunk, s := chunk, s + for len(chunk) > 0 { + if len(s) == 0 { + return + } + switch chunk[0] { + case '[': + r, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] + is_negated := false + if len(chunk) > 0 && chunk[0] == '^' { + is_negated = true + chunk = chunk[1:] + } + match := false + range_count := 0 + for { + if len(chunk) > 0 && chunk[0] == ']' && range_count > 0 { + chunk = chunk[1:] + break + } + lo, hi: rune + if lo, chunk, err = get_escape(chunk); err != nil { + return + } + hi = lo + if chunk[0] == '-' { + if hi, chunk, err = get_escape(chunk[1:]); err != nil { + return + } + } + + if lo <= r && r <= hi { + match = true + } + range_count += 1 + } + if match == is_negated { + return + } + + case '?': + if s[0] == _Path_Separator { + return + } + _, w := utf8.decode_rune_in_string(s) + s = s[w:] + chunk = chunk[1:] + + case '\\': + when ODIN_OS != .Windows { + chunk = chunk[1:] + if len(chunk) == 0 { + err = .Pattern_Syntax_Error + return + } + } + fallthrough + case: + if !slash_equal(chunk[0], s[0]) { + return + } + s = s[1:] + chunk = chunk[1:] + + } + } + return s, true, nil +} + +@(private="file") +get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Error) { + if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { + err = .Pattern_Syntax_Error + return + } + chunk := chunk + if chunk[0] == '\\' && ODIN_OS != .Windows { + chunk = chunk[1:] + if len(chunk) == 0 { + err = .Pattern_Syntax_Error + return + } + } + + w: int + r, w = utf8.decode_rune_in_string(chunk) + if r == utf8.RUNE_ERROR && w == 1 { + err = .Pattern_Syntax_Error + } + + next_chunk = chunk[w:] + if len(next_chunk) == 0 { + err = .Pattern_Syntax_Error + } + + return +} + +// Internal implementation of `glob`, not meant to be used by the user. Prefer `glob`. +_glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := context.allocator) -> (m: [dynamic]string, e: Error) { + context.allocator = allocator + + if matches != nil { + m = matches^ + } else { + m = make([dynamic]string, 0, 0) + } + + + d := open(dir, O_RDONLY) or_return + defer close(d) + + file_info := fstat(d, allocator) or_return + defer file_info_delete(file_info, allocator) + + if file_info.type != .Directory { + return + } + + fis, _ := read_dir(d, -1, allocator) + slice.sort_by(fis, proc(a, b: File_Info) -> bool { + return a.name < b.name + }) + defer file_info_slice_delete(fis, allocator) + + for fi in fis { + matched := match(pattern, fi.name) or_return + if matched { + matched_path := join_path({dir, fi.name}, allocator) or_return + append(&m, matched_path) + } + } + return +} + +@(private) +has_meta :: proc(path: string) -> bool { + when ODIN_OS == .Windows { + CHARS :: `*?[` + } else { + CHARS :: `*?[\` + } + return strings.contains_any(path, CHARS) +} + +@(private) +clean_glob_path :: proc(path: string, temp_buf: []byte) -> (int, string) { + when ODIN_OS == .Windows { + vol_len := _volume_name_len(path) + switch { + case path == "": + return 0, "." + case vol_len+1 == len(path) && is_path_separator(path[len(path)-1]): // /, \, C:\, C:/ + return vol_len+1, path + case vol_len == len(path) && len(path) == 2: // C: + copy(temp_buf[:], path) + temp_buf[2] = '.' + return vol_len, string(temp_buf[:3]) + } + + if vol_len >= len(path) { + vol_len = len(path) -1 + } + return vol_len, path[:len(path)-1] + } else { + switch path { + case "": + return 0, "." + case Path_Separator_String: + return 0, path + } + return 0, path[:len(path)-1] + } +} \ No newline at end of file diff --git a/core/os/os2/path_darwin.odin b/core/os/path_darwin.odin similarity index 97% rename from core/os/os2/path_darwin.odin rename to core/os/path_darwin.odin index 65aaf1e95..dbfdb584b 100644 --- a/core/os/os2/path_darwin.odin +++ b/core/os/path_darwin.odin @@ -1,4 +1,4 @@ -package os2 +package os import "base:runtime" diff --git a/core/os/os2/path_freebsd.odin b/core/os/path_freebsd.odin similarity index 98% rename from core/os/os2/path_freebsd.odin rename to core/os/path_freebsd.odin index e7e4f63c9..5ec43466e 100644 --- a/core/os/os2/path_freebsd.odin +++ b/core/os/path_freebsd.odin @@ -1,4 +1,4 @@ -package os2 +package os import "base:runtime" diff --git a/core/os/path_js.odin b/core/os/path_js.odin new file mode 100644 index 000000000..556d93b16 --- /dev/null +++ b/core/os/path_js.odin @@ -0,0 +1,89 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" + +_Path_Separator :: '/' +_Path_Separator_String :: "/" +_Path_List_Separator :: ':' + +_is_path_separator :: proc(c: byte) -> (ok: bool) { + return c == _Path_Separator +} + +_mkdir :: proc(name: string, perm: Permissions) -> (err: Error) { + return .Unsupported +} + +_mkdir_all :: proc(path: string, perm: Permissions) -> (err: Error) { + return .Unsupported +} + +_remove_all :: proc(path: string) -> (err: Error) { + return .Unsupported +} + +_get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return "", .Unsupported +} + +_set_working_directory :: proc(dir: string) -> (err: Error) { + return .Unsupported +} + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + return "", .Unsupported +} + +_are_paths_identical :: proc(a, b: string) -> bool { + return false +} + +_clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, start: int) { + return +} + +_is_absolute_path :: proc(path: string) -> bool { + return false +} + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + return "", .Unsupported +} + +_get_relative_path_handle_start :: proc(base, target: string) -> bool { + return false +} + +_get_common_path_len :: proc(base, target: string) -> int { + i := 0 + end := min(len(base), len(target)) + for j in 0..=end { + if j == end || _is_path_separator(base[j]) { + if base[i:j] == target[i:j] { + i = j + } else { + break + } + } + } + return i +} + +_split_path :: proc(path: string) -> (dir, file: string) { + i := len(path) - 1 + for i >= 0 && !_is_path_separator(path[i]) { + i -= 1 + } + if i == 0 { + return path[:i+1], path[i+1:] + } else if i > 0 { + return path[:i], path[i+1:] + } + return "", path +} \ No newline at end of file diff --git a/core/os/os2/path_linux.odin b/core/os/path_linux.odin similarity index 85% rename from core/os/os2/path_linux.odin rename to core/os/path_linux.odin index 64f415187..8911e6986 100644 --- a/core/os/os2/path_linux.odin +++ b/core/os/path_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -17,14 +17,14 @@ _is_path_separator :: proc(c: byte) -> bool { return c == _Path_Separator } -_mkdir :: proc(path: string, perm: int) -> Error { +_mkdir :: proc(path: string, perm: Permissions) -> Error { temp_allocator := TEMP_ALLOCATOR_GUARD({}) path_cstr := clone_to_cstring(path, temp_allocator) or_return - return _get_platform_error(linux.mkdir(path_cstr, transmute(linux.Mode)u32(perm))) + return _get_platform_error(linux.mkdir(path_cstr, transmute(linux.Mode)transmute(u32)perm)) } -_mkdir_all :: proc(path: string, perm: int) -> Error { - mkdirat :: proc(dfd: linux.Fd, path: []u8, perm: int, has_created: ^bool) -> Error { +_mkdir_all :: proc(path: string, perm: Permissions) -> Error { + mkdirat :: proc(dfd: linux.Fd, path: []u8, perm: Permissions, has_created: ^bool) -> Error { i: int for ; i < len(path) - 1 && path[i] != '/'; i += 1 {} if i == 0 { @@ -34,7 +34,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { new_dfd, errno := linux.openat(dfd, cstring(&path[0]), _OPENDIR_FLAGS) #partial switch errno { case .ENOENT: - if errno = linux.mkdirat(dfd, cstring(&path[0]), transmute(linux.Mode)u32(perm)); errno != .NONE { + if errno = linux.mkdirat(dfd, cstring(&path[0]), transmute(linux.Mode)transmute(u32)perm); errno != .NONE { return _get_platform_error(errno) } has_created^ = true @@ -71,7 +71,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { if errno != .NONE { return _get_platform_error(errno) } - + has_created: bool mkdirat(dfd, path_bytes, perm, &has_created) or_return return nil if has_created else .Exist @@ -147,13 +147,13 @@ _remove_all :: proc(path: string) -> Error { return _get_platform_error(linux.rmdir(path_cstr)) } -_get_working_directory :: proc(allocator: runtime.Allocator) -> (string, Error) { +_get_working_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { // NOTE(tetra): I would use PATH_MAX here, but I was not able to find // an authoritative value for it across all systems. // The largest value I could find was 4096, so might as well use the page size. // NOTE(jason): Avoiding libc, so just use 4096 directly PATH_MAX :: 4096 - buf := make([dynamic]u8, PATH_MAX, allocator) + buf := make([dynamic]u8, PATH_MAX, allocator) or_return for { #no_bounds_check n, errno := linux.getcwd(buf[:]) if errno == .NONE { @@ -162,7 +162,7 @@ _get_working_directory :: proc(allocator: runtime.Allocator) -> (string, Error) if errno != .ERANGE { return "", _get_platform_error(errno) } - resize(&buf, len(buf)+PATH_MAX) + resize(&buf, len(buf)+PATH_MAX) or_return } unreachable() } @@ -199,7 +199,7 @@ _get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fullpath: buf: [32]u8 copy(buf[:], PROC_FD_PATH) - strconv.itoa(buf[len(PROC_FD_PATH):], int(fd)) + strconv.write_int(buf[len(PROC_FD_PATH):], i64(fd), 10) if fullpath, err = _read_link_cstr(cstring(&buf[0]), allocator); err != nil || fullpath[0] != '/' { delete(fullpath, allocator) @@ -207,3 +207,21 @@ _get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fullpath: } return } + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + rel := path + if rel == "" { + rel = "." + } + + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + fd, errno := linux.open(clone_to_cstring(path, temp_allocator) or_return, {}) + if errno != nil { + err = _get_platform_error(errno) + return + } + defer linux.close(fd) + + return _get_full_path(fd, allocator) +} diff --git a/core/os/os2/path_netbsd.odin b/core/os/path_netbsd.odin similarity index 97% rename from core/os/os2/path_netbsd.odin rename to core/os/path_netbsd.odin index 815102dea..a9ceb13df 100644 --- a/core/os/os2/path_netbsd.odin +++ b/core/os/path_netbsd.odin @@ -1,4 +1,4 @@ -package os2 +package os import "base:runtime" diff --git a/core/os/os2/path_openbsd.odin b/core/os/path_openbsd.odin similarity index 99% rename from core/os/os2/path_openbsd.odin rename to core/os/path_openbsd.odin index cbc0346d4..55b6b7d1f 100644 --- a/core/os/os2/path_openbsd.odin +++ b/core/os/path_openbsd.odin @@ -1,4 +1,4 @@ -package os2 +package os import "base:runtime" diff --git a/core/os/os2/path_posix.odin b/core/os/path_posix.odin similarity index 76% rename from core/os/os2/path_posix.odin rename to core/os/path_posix.odin index e59567240..6f383903a 100644 --- a/core/os/os2/path_posix.odin +++ b/core/os/path_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" @@ -14,16 +14,16 @@ _is_path_separator :: proc(c: byte) -> bool { return c == _Path_Separator } -_mkdir :: proc(name: string, perm: int) -> (err: Error) { +_mkdir :: proc(name: string, perm: Permissions) -> (err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) cname := clone_to_cstring(name, temp_allocator) or_return - if posix.mkdir(cname, transmute(posix.mode_t)posix._mode_t(perm)) != .OK { + if posix.mkdir(cname, transmute(posix.mode_t)posix._mode_t(transmute(u32)perm)) != .OK { return _get_platform_error() } return nil } -_mkdir_all :: proc(path: string, perm: int) -> Error { +_mkdir_all :: proc(path: string, perm: Permissions) -> Error { if path == "" { return .Invalid_Path } @@ -37,7 +37,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { clean_path := clean_path(path, temp_allocator) or_return return internal_mkdir_all(clean_path, perm) - internal_mkdir_all :: proc(path: string, perm: int) -> Error { + internal_mkdir_all :: proc(path: string, perm: Permissions) -> Error { dir, file := split_path(path) if file != path && dir != "/" { if len(dir) > 1 && dir[len(dir) - 1] == '/' { @@ -123,3 +123,20 @@ _set_working_directory :: proc(dir: string) -> (err: Error) { } return } + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + rel := path + if rel == "" { + rel = "." + } + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + rel_cstr := clone_to_cstring(rel, temp_allocator) or_return + path_ptr := posix.realpath(rel_cstr, nil) + if path_ptr == nil { + return "", _get_platform_error() + } + defer posix.free(path_ptr) + + path_str := clone_string(string(path_ptr), allocator) or_return + return path_str, nil +} diff --git a/core/os/os2/path_posixfs.odin b/core/os/path_posixfs.odin similarity index 69% rename from core/os/os2/path_posixfs.odin rename to core/os/path_posixfs.odin index 4102d71c1..aea89c60a 100644 --- a/core/os/os2/path_posixfs.odin +++ b/core/os/path_posixfs.odin @@ -1,13 +1,9 @@ #+private #+build linux, darwin, netbsd, freebsd, openbsd, wasi -package os2 +package os // This implementation is for all systems that have POSIX-compliant filesystem paths. -import "base:runtime" -import "core:strings" -import "core:sys/posix" - _are_paths_identical :: proc(a, b: string) -> (identical: bool) { return a == b } @@ -26,23 +22,6 @@ _is_absolute_path :: proc(path: string) -> bool { return len(path) > 0 && _is_path_separator(path[0]) } -_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { - rel := path - if rel == "" { - rel = "." - } - temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - rel_cstr := strings.clone_to_cstring(rel, temp_allocator) - path_ptr := posix.realpath(rel_cstr, nil) - if path_ptr == nil { - return "", Platform_Error(posix.errno()) - } - defer posix.free(path_ptr) - - path_str := strings.clone(string(path_ptr), allocator) - return path_str, nil -} - _get_relative_path_handle_start :: proc(base, target: string) -> bool { base_rooted := len(base) > 0 && _is_path_separator(base[0]) target_rooted := len(target) > 0 && _is_path_separator(target[0]) diff --git a/core/os/os2/path_wasi.odin b/core/os/path_wasi.odin similarity index 85% rename from core/os/os2/path_wasi.odin rename to core/os/path_wasi.odin index b8240e188..e7c003001 100644 --- a/core/os/os2/path_wasi.odin +++ b/core/os/path_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -14,7 +14,7 @@ _is_path_separator :: proc(c: byte) -> bool { return c == _Path_Separator } -_mkdir :: proc(name: string, perm: int) -> Error { +_mkdir :: proc(name: string, perm: Permissions) -> Error { dir_fd, relative, ok := match_preopen(name) if !ok { return .Invalid_Path @@ -23,7 +23,7 @@ _mkdir :: proc(name: string, perm: int) -> Error { return _get_platform_error(wasi.path_create_directory(dir_fd, relative)) } -_mkdir_all :: proc(path: string, perm: int) -> Error { +_mkdir_all :: proc(path: string, perm: Permissions) -> Error { if path == "" { return .Invalid_Path } @@ -34,7 +34,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { return .Exist } - clean_path := clean_path(path, temp_allocator) + clean_path := clean_path(path, temp_allocator) or_return return internal_mkdir_all(clean_path) internal_mkdir_all :: proc(path: string) -> Error { @@ -46,7 +46,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { internal_mkdir_all(dir) or_return } - err := _mkdir(path, 0) + err := _mkdir(path, Permissions_Default) if err == .Exist { err = nil } return err } @@ -114,3 +114,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err return concatenate({"/", arg}, allocator) } + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + return "", .Unsupported +} diff --git a/core/os/os2/path_windows.odin b/core/os/path_windows.odin similarity index 84% rename from core/os/os2/path_windows.odin rename to core/os/path_windows.odin index 9c0fec9b9..83100ad69 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/path_windows.odin @@ -1,6 +1,7 @@ #+private -package os2 +package os +import "base:intrinsics" import "base:runtime" import "core:strings" import win32 "core:sys/windows" @@ -13,7 +14,7 @@ _is_path_separator :: proc(c: byte) -> bool { return c == '\\' || c == '/' } -_mkdir :: proc(name: string, perm: int) -> Error { +_mkdir :: proc(name: string, perm: Permissions) -> Error { temp_allocator := TEMP_ALLOCATOR_GUARD({}) if !win32.CreateDirectoryW(_fix_long_path(name, temp_allocator) or_return, nil) { return _get_platform_error() @@ -21,7 +22,7 @@ _mkdir :: proc(name: string, perm: int) -> Error { return nil } -_mkdir_all :: proc(path: string, perm: int) -> Error { +_mkdir_all :: proc(path: string, perm: Permissions) -> Error { fix_root_directory :: proc(p: string) -> (s: string, allocated: bool, err: runtime.Allocator_Error) { if len(p) == len(`\\?\c:`) { if is_path_separator(p[0]) && is_path_separator(p[1]) && p[2] == '?' && is_path_separator(p[3]) && p[5] == ':' { @@ -91,11 +92,11 @@ _remove_all :: proc(path: string) -> Error { nil, win32.FO_DELETE, dir, - &empty[0], + cstring16(&empty[0]), win32.FOF_NOCONFIRMATION | win32.FOF_NOERRORUI | win32.FOF_SILENT, false, nil, - &empty[0], + cstring16(&empty[0]), } res := win32.SHFileOperationW(&file_op) if res != 0 { @@ -157,17 +158,30 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err } } -can_use_long_paths: bool -@(init) -init_long_path_support :: proc() { +@(require_results) +has_long_path_support :: proc "contextless" () -> bool { + @(static) + can_use_long_paths_lock: win32.SRWLOCK + @(static) + can_use_long_paths_checked: bool // atomic + @(static) + can_use_long_paths: bool + + if intrinsics.atomic_load_explicit(&can_use_long_paths_checked, .Acquire) == true { + return can_use_long_paths + } + win32.AcquireSRWLockExclusive(&can_use_long_paths_lock) + defer win32.ReleaseSRWLockExclusive(&can_use_long_paths_lock) + defer intrinsics.atomic_store_explicit(&can_use_long_paths_checked, true, .Release) + can_use_long_paths = false key: win32.HKEY res := win32.RegOpenKeyExW(win32.HKEY_LOCAL_MACHINE, win32.L(`SYSTEM\CurrentControlSet\Control\FileSystem`), 0, win32.KEY_READ, &key) defer win32.RegCloseKey(key) if res != 0 { - return + return can_use_long_paths } value: u32 @@ -182,12 +196,13 @@ init_long_path_support :: proc() { &size, ) if res != 0 { - return + return can_use_long_paths } if value == 1 { can_use_long_paths = true } + return can_use_long_paths } @(require_results) @@ -202,10 +217,11 @@ _fix_long_path :: proc(path: string, allocator: runtime.Allocator) -> (win32.wst @(require_results) _fix_long_path_internal :: proc(path: string) -> string { - if can_use_long_paths { + if has_long_path_support() { return path } + // When using win32 to create a directory, the path // cannot be too long that you cannot append an 8.3 // file name, because MAX_PATH is 260, 260-12 = 248 @@ -271,6 +287,11 @@ _clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, s start += 1 } copy(buffer, path[:start]) + for n in 0.. bool { if _is_reserved_name(path) { return true } + if len(path) > 0 && _is_path_separator(path[0]) { + return true + } + l := _volume_name_len(path) if l == 0 { return false @@ -299,15 +324,15 @@ _get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absol } temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) rel_utf16 := win32.utf8_to_utf16(rel, temp_allocator) - n := win32.GetFullPathNameW(raw_data(rel_utf16), 0, nil, nil) + n := win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), 0, nil, nil) if n == 0 { - return "", Platform_Error(win32.GetLastError()) + return "", _get_platform_error() } buf := make([]u16, n, temp_allocator) or_return - n = win32.GetFullPathNameW(raw_data(rel_utf16), u32(n), raw_data(buf), nil) + n = win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), u32(n), cstring16(raw_data(buf)), nil) if n == 0 { - return "", Platform_Error(win32.GetLastError()) + return "", _get_platform_error() } return win32.utf16_to_utf8(buf, allocator) @@ -324,6 +349,9 @@ _get_common_path_len :: proc(base, target: string) -> int { end := min(len(base), len(target)) for j in 0..=end { if j == end || _is_path_separator(base[j]) { + if i < end && _is_path_separator(base[i]) && _is_path_separator(target[i]) { + i += 1 + } if strings.equal_fold(base[i:j], target[i:j]) { i = j } else { @@ -347,4 +375,4 @@ _split_path :: proc(path: string) -> (dir, file: string) { return path[:i], path[i+1:] } return "", path -} +} \ No newline at end of file diff --git a/core/os/os2/pipe.odin b/core/os/pipe.odin similarity index 94% rename from core/os/os2/pipe.odin rename to core/os/pipe.odin index 5d3e8368e..5254f9469 100644 --- a/core/os/os2/pipe.odin +++ b/core/os/pipe.odin @@ -1,4 +1,4 @@ -package os2 +package os /* Create an anonymous pipe. @@ -15,7 +15,7 @@ process, that end of the pipe needs to be closed by the parent, before any data is attempted to be read. Although pipes look like files and is compatible with most file APIs in package -os2, the way it's meant to be read is different. Due to asynchronous nature of +os, the way it's meant to be read is different. Due to asynchronous nature of the communication channel, the data may not be present at the time of a read request. The other scenario is when a pipe has no data because the other end of the pipe was closed by the child process. diff --git a/core/os/pipe_js.odin b/core/os/pipe_js.odin new file mode 100644 index 000000000..5e724ea00 --- /dev/null +++ b/core/os/pipe_js.odin @@ -0,0 +1,18 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +_pipe :: proc() -> (r, w: ^File, err: Error) { + err = .Unsupported + return +} + +@(require_results) +_pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) { + err = .Unsupported + return +} \ No newline at end of file diff --git a/core/os/os2/pipe_linux.odin b/core/os/pipe_linux.odin similarity index 98% rename from core/os/os2/pipe_linux.odin rename to core/os/pipe_linux.odin index bb4456e1c..561f82f80 100644 --- a/core/os/os2/pipe_linux.odin +++ b/core/os/pipe_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "core:sys/linux" diff --git a/core/os/os2/pipe_posix.odin b/core/os/pipe_posix.odin similarity index 99% rename from core/os/os2/pipe_posix.odin rename to core/os/pipe_posix.odin index 7c07bc068..e811e306f 100644 --- a/core/os/os2/pipe_posix.odin +++ b/core/os/pipe_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "core:sys/posix" import "core:strings" diff --git a/core/os/os2/pipe_wasi.odin b/core/os/pipe_wasi.odin similarity index 94% rename from core/os/os2/pipe_wasi.odin rename to core/os/pipe_wasi.odin index 19c11b51d..e27c9419e 100644 --- a/core/os/os2/pipe_wasi.odin +++ b/core/os/pipe_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os _pipe :: proc() -> (r, w: ^File, err: Error) { err = .Unsupported diff --git a/core/os/os2/pipe_windows.odin b/core/os/pipe_windows.odin similarity index 98% rename from core/os/os2/pipe_windows.odin rename to core/os/pipe_windows.odin index d6dc47c9c..4e627e26a 100644 --- a/core/os/os2/pipe_windows.odin +++ b/core/os/pipe_windows.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import win32 "core:sys/windows" diff --git a/core/os/os2/process.odin b/core/os/process.odin similarity index 90% rename from core/os/os2/process.odin rename to core/os/process.odin index 3c84f3539..ef3b09fdd 100644 --- a/core/os/os2/process.odin +++ b/core/os/process.odin @@ -1,4 +1,4 @@ -package os2 +package os import "base:runtime" @@ -16,19 +16,36 @@ Arguments to the current process. args := get_args() @(private="file") -get_args :: proc() -> []string { +internal_args_to_free: []string + +@(private="file") +get_args :: proc "contextless" () -> []string { + context = runtime.default_context() result := make([]string, len(runtime.args__), heap_allocator()) for rt_arg, i in runtime.args__ { result[i] = string(rt_arg) } + internal_args_to_free = result return result } +@(fini, private="file") +delete_args :: proc "contextless" () { + if internal_args_to_free != nil { + context = runtime.default_context() + delete(internal_args_to_free, heap_allocator()) + } +} + /* -Exit the current process. +Tells the OS to exit the current process directly. + +IMPORTANT: `@(fini)` blocks won't be executed. + +If you want `@(fini)` cleanup to happen, call `runtime._cleanup_runtime` first. */ exit :: proc "contextless" (code: int) -> ! { - _exit(code) + runtime.exit(code) } /* @@ -107,6 +124,21 @@ get_ppid :: proc() -> int { return _get_ppid() } +/* +Obtain the current thread id +*/ +@(require_results) +get_current_thread_id :: proc "contextless" () -> int { + return _get_current_thread_id() +} + +/* +Return the number of cores +*/ +get_processor_core_count :: proc() -> int { + return _get_processor_core_count() +} + /* Obtain ID's of all processes running in the system. */ @@ -283,7 +315,8 @@ This procedure obtains a process handle of a process specified by `pid`. This procedure can be subject to race conditions. See the description of `Process`. -Use `process_close()` function to close the process handle. +Use the `process_wait()` procedure (optionally prefaced with a `process_kill()`) +to close and free the process handle. */ @(require_results) process_open :: proc(pid: int, flags := Process_Open_Flags {}) -> (Process, Error) { @@ -332,10 +365,8 @@ be created. It contains information such as the command line, the environment of the process, the starting directory and many other options. Most of the fields in the struct can be set to `nil` or an empty value. -Use `process_close` to close the handle to the process. Note, that this -is not the same as terminating the process. One can terminate the process -and not close the handle, in which case the handle would be leaked. In case -the function returns an error, an invalid handle is returned. +Use the `process_wait()` procedure (optionally prefaced with a `process_kill()`) +to close and free the process handle. This procedure is not thread-safe. It may alter the inheritance properties of file handles in an unpredictable manner. In case multiple threads change @@ -467,7 +498,7 @@ Process_State :: struct { // Will also store the number of the exception or signal that has crashed the // process. exit_code: int, - // Specifies whether the termination of the process was successfull or not, + // Specifies whether the termination of the process was successful or not, // i.e. whether it has crashed or not. // **Note(windows)**: On windows `true` is always returned, as there is no // reliable way to obtain information about whether the process has crashed. @@ -483,7 +514,9 @@ Wait for a process event. This procedure blocks the execution until the process has exited or the timeout (if specified) has reached zero. If the timeout is `TIMEOUT_INFINITE`, -no timeout restriction is imposed and the procedure can block indefinately. +no timeout restriction is imposed and the procedure can block indefinitely. + +If the timeout is 0, no blocking will be done and the current state is returned. If the timeout has expired, the `General_Error.Timeout` is returned as the error. @@ -497,24 +530,25 @@ process_wait :: proc(process: Process, timeout := TIMEOUT_INFINITE) -> (Process_ } /* -Close the handle to a process. +Kill a process. -This procedure closes the handle associated with a process. It **does not** -terminate a process, in case it was running. In case a termination is -desired, kill the process first, wait for the process to finish, -then close the handle. +This procedure kills a process, specified by it's handle, `process`. + +The process is forced to exit and can't ignore the request. */ @(require_results) -process_close :: proc(process: Process) -> (Error) { - return _process_close(process) +process_kill :: proc(process: Process) -> (Error) { + return _process_kill(process) } /* Terminate a process. This procedure terminates a process, specified by it's handle, `process`. + +The process is requested to exit and can ignore the request. */ @(require_results) -process_kill :: proc(process: Process) -> (Error) { - return _process_kill(process) +process_terminate :: proc(process: Process) -> (Error) { + return _process_terminate(process) } diff --git a/core/os/process_freebsd.odin b/core/os/process_freebsd.odin new file mode 100644 index 000000000..794991ae5 --- /dev/null +++ b/core/os/process_freebsd.odin @@ -0,0 +1,34 @@ +#+private +#+build freebsd +package os + +foreign import libc "system:c" +foreign import dl "system:dl" + +foreign libc { + @(link_name="sysctlbyname") + _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> i32 --- +} + +foreign dl { + @(link_name="pthread_getthreadid_np") + pthread_getthreadid_np :: proc() -> i32 --- +} + +@(require_results) +_get_current_thread_id :: proc "contextless" () -> int { + return int(pthread_getthreadid_np()) +} + +@(require_results) +_get_processor_core_count :: proc() -> int { + count : int = 0 + count_size := size_of(count) + if _sysctlbyname("hw.ncpu", &count, &count_size, nil, 0) == 0 { + if count > 0 { + return count + } + } + + return 1 +} diff --git a/core/os/process_js.odin b/core/os/process_js.odin new file mode 100644 index 000000000..7aa6bb1b8 --- /dev/null +++ b/core/os/process_js.odin @@ -0,0 +1,99 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" +import "core:time" + + +_exit :: proc "contextless" (code: int) -> ! { + runtime.panic_contextless("exit") +} + +_get_uid :: proc() -> int { + return 0 +} + +_get_euid :: proc() -> int { + return 0 +} + +_get_gid :: proc() -> int { + return 0 +} + +_get_egid :: proc() -> int { + return 0 +} + +_get_pid :: proc() -> int { + return 0 +} + +_get_ppid :: proc() -> int { + return 0 +} + +_get_current_thread_id :: proc "contextless" () -> int { + return 0 +} + +_get_processor_core_count :: proc() -> int { + return 1 +} + +_process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) { + err = .Unsupported + return +} + +_current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) { + err = .Unsupported + return +} + +_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { + err = .Unsupported + return +} + +_process_wait :: proc(process: Process, timeout: time.Duration) -> (process_state: Process_State, err: Error) { + err = .Unsupported + return +} + +_process_kill :: proc(process: Process) -> (err: Error) { + return .Unsupported +} + +_process_terminate :: proc(process: Process) -> (err: Error) { + return .Unsupported +} + +_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) { + err = .Unsupported + return +} + +_process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error) { + err = .Unsupported + return +} + +_process_open :: proc(pid: int, flags: Process_Open_Flags) -> (process: Process, err: Error) { + process.pid = pid + err = .Unsupported + return +} + +_process_handle_still_valid :: proc(p: Process) -> Error { + return nil +} + +_process_state_update_times :: proc(p: Process, state: ^Process_State) { + return +} diff --git a/core/os/os2/process_linux.odin b/core/os/process_linux.odin similarity index 95% rename from core/os/os2/process_linux.odin rename to core/os/process_linux.odin index 170f0ea1a..2224222e1 100644 --- a/core/os/os2/process_linux.odin +++ b/core/os/process_linux.odin @@ -1,6 +1,6 @@ #+build linux #+private file -package os2 +package os import "base:runtime" import "base:intrinsics" @@ -13,11 +13,6 @@ import "core:sys/linux" PIDFD_UNASSIGNED :: ~uintptr(0) -@(private="package") -_exit :: proc "contextless" (code: int) -> ! { - linux.exit_group(i32(code)) -} - @(private="package") _get_uid :: proc() -> int { return int(linux.getuid()) @@ -48,6 +43,22 @@ _get_ppid :: proc() -> int { return int(linux.getppid()) } +@(private="package") +_get_current_thread_id :: proc "contextless" () -> int { + return int(linux.gettid()) +} + +@(private="package") +_get_processor_core_count :: proc() -> (core_count: int) { + cpu_set: [128]u64 + if n, err := linux.sched_getaffinity(0, size_of(cpu_set), &cpu_set); err == nil { + for set in cpu_set[:n / 8] { + core_count += int(intrinsics.count_ones(set)) + } + } + return +} + @(private="package") _process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) @@ -118,8 +129,8 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator defer linux.close(proc_fd) username_if: if .Username in selection { - s: linux.Stat - if errno = linux.fstat(proc_fd, &s); errno != .NONE { + s: linux.Statx + if errno = linux.statx(proc_fd, "", {.EMPTY_PATH}, {.UID}, &s); errno != .NONE { err = _get_platform_error(errno) break username_if } @@ -427,7 +438,8 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { strings.write_string(&exe_builder, executable_name) exe_path = strings.to_cstring(&exe_builder) or_return - if linux.access(exe_path, linux.X_OK) == .NONE { + stat: linux.Statx + if linux.statx(linux.AT_FDCWD, exe_path, {}, {.TYPE, .MODE}, &stat) == .NONE && .IFREG in stat.mode && .IXUSR in stat.mode { found = true break } @@ -662,6 +674,8 @@ _reap_terminated :: proc(process: Process) -> (state: Process_State, err: Error) state.exit_code = int(info.status) state.success = false } + + _process_close(process) return } @@ -703,6 +717,8 @@ _timed_wait_on_handle :: proc(process: Process, timeout: time.Duration) -> (proc start_tick = time.tick_now() continue } + + _process_close(process) return process_state, _get_platform_error(errno) } @@ -713,6 +729,7 @@ _timed_wait_on_handle :: proc(process: Process, timeout: time.Duration) -> (proc } if errno = linux.waitid(.PIDFD, linux.Id(process.handle), &info, {.WEXITED, .WNOHANG, .WNOWAIT}, nil); errno != .NONE { + _process_close(process) return process_state, _get_platform_error(errno) } @@ -747,6 +764,8 @@ _timed_wait_on_handle :: proc(process: Process, timeout: time.Duration) -> (proc process_state.success = false } } + + _process_close(process) return } @@ -763,6 +782,7 @@ _timed_wait_on_pid :: proc(process: Process, timeout: time.Duration) -> (process org_sigset: linux.Sig_Set errno := linux.rt_sigprocmask(.SIG_BLOCK, &sigchld_set, &org_sigset) if errno != .NONE { + _process_close(process) return process_state, _get_platform_error(errno) } defer linux.rt_sigprocmask(.SIG_SETMASK, &org_sigset, nil) @@ -794,6 +814,7 @@ _timed_wait_on_pid :: proc(process: Process, timeout: time.Duration) -> (process timeout -= time.tick_since(start_tick) start_tick = time.tick_now() case .EINVAL: + _process_close(process) return process_state, _get_platform_error(errno) } } @@ -832,13 +853,13 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (Process_Stat return process_state, .Timeout } if errno != .NONE { + _process_close(process) return process_state, _get_platform_error(errno) } return _reap_terminated(process) } -@(private="package") _process_close :: proc(process: Process) -> Error { if process.handle == 0 || process.handle == PIDFD_UNASSIGNED { return nil @@ -852,3 +873,7 @@ _process_kill :: proc(process: Process) -> Error { return _get_platform_error(linux.kill(linux.Pid(process.pid), .SIGKILL)) } +@(private="package") +_process_terminate :: proc(process: Process) -> Error { + return _get_platform_error(linux.kill(linux.Pid(process.pid), .SIGTERM)) +} diff --git a/core/os/process_netbsd.odin b/core/os/process_netbsd.odin new file mode 100644 index 000000000..af65e1371 --- /dev/null +++ b/core/os/process_netbsd.odin @@ -0,0 +1,30 @@ +#+private +#+build netbsd +package os + +foreign import libc "system:c" + +@(private) +foreign libc { + _lwp_self :: proc() -> i32 --- + + @(link_name="sysctlbyname") + _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> i32 --- +} + +@(require_results) +_get_current_thread_id :: proc "contextless" () -> int { + return int(_lwp_self()) +} + +_get_processor_core_count :: proc() -> int { + count : int = 0 + count_size := size_of(count) + if _sysctlbyname("hw.ncpu", &count, &count_size, nil, 0) == 0 { + if count > 0 { + return count + } + } + + return 1 +} diff --git a/core/os/process_openbsd.odin b/core/os/process_openbsd.odin new file mode 100644 index 000000000..cab562aaf --- /dev/null +++ b/core/os/process_openbsd.odin @@ -0,0 +1,25 @@ +#+private +#+build openbsd +package os + +import "core:c" + +foreign import libc "system:c" + +@(default_calling_convention="c") +foreign libc { + @(link_name="getthrid") _unix_getthrid :: proc() -> int --- + @(link_name="sysconf") _sysconf :: proc(name: c.int) -> c.long --- +} + +@(require_results) +_get_current_thread_id :: proc "contextless" () -> int { + return _unix_getthrid() +} + +_SC_NPROCESSORS_ONLN :: 503 + +@(private, require_results) +_get_processor_core_count :: proc() -> int { + return int(_sysconf(_SC_NPROCESSORS_ONLN)) +} diff --git a/core/os/os2/process_posix.odin b/core/os/process_posix.odin similarity index 97% rename from core/os/os2/process_posix.odin rename to core/os/process_posix.odin index fcacdf654..f41779290 100644 --- a/core/os/os2/process_posix.odin +++ b/core/os/process_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" @@ -10,10 +10,6 @@ import "core:strings" import kq "core:sys/kqueue" import "core:sys/posix" -_exit :: proc "contextless" (code: int) -> ! { - posix.exit(i32(code)) -} - _get_uid :: proc() -> int { return int(posix.getuid()) } @@ -333,10 +329,6 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (process_stat return } -_process_close :: proc(process: Process) -> Error { - return nil -} - _process_kill :: proc(process: Process) -> (err: Error) { _process_handle_still_valid(process) or_return @@ -346,3 +338,13 @@ _process_kill :: proc(process: Process) -> (err: Error) { return } + +_process_terminate :: proc(process: Process) -> (err: Error) { + _process_handle_still_valid(process) or_return + + if posix.kill(posix.pid_t(process.pid), .SIGTERM) != .OK { + err = _get_platform_error() + } + + return +} diff --git a/core/os/os2/process_posix_darwin.odin b/core/os/process_posix_darwin.odin similarity index 90% rename from core/os/os2/process_posix_darwin.odin rename to core/os/process_posix_darwin.odin index ac2d4b78c..ea621eea8 100644 --- a/core/os/os2/process_posix_darwin.odin +++ b/core/os/process_posix_darwin.odin @@ -1,8 +1,7 @@ #+private -package os2 +package os import "base:runtime" -import "base:intrinsics" import "core:bytes" import "core:sys/darwin" @@ -10,14 +9,40 @@ import "core:sys/posix" import "core:sys/unix" import "core:time" -foreign import lib "system:System.framework" +foreign import libsystem "system:System" -foreign lib { - sysctl :: proc( +foreign libsystem { + sysctl :: proc "c" ( name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^uint, newp: rawptr, newlen: uint, ) -> posix.result --- + + @(link_name="sysctlbyname") + _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> posix.result --- + + // NOTE(Oskar): available from OSX 10.6 and iOS 3.2. + // For older versions there is `syscall(SYS_thread_selfid)`, but not really + // the same thing apparently. + pthread_threadid_np :: proc "c" (rawptr, ^u64) -> i32 --- +} + +_get_current_thread_id :: proc "contextless" () -> int { + tid: u64 + pthread_threadid_np(nil, &tid) + return int(tid) +} + +_get_processor_core_count :: proc() -> int { + count: int = 0 + count_size := size_of(count) + if _sysctlbyname("hw.logicalcpu", &count, &count_size, nil, 0) == .OK { + if count > 0 { + return count + } + } + + return 1 } _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) { diff --git a/core/os/os2/process_posix_other.odin b/core/os/process_posix_other.odin similarity index 98% rename from core/os/os2/process_posix_other.odin rename to core/os/process_posix_other.odin index 65da3e9e2..85ed6cdd8 100644 --- a/core/os/os2/process_posix_other.odin +++ b/core/os/process_posix_other.odin @@ -1,6 +1,6 @@ #+private #+build netbsd, openbsd, freebsd -package os2 +package os import "base:runtime" diff --git a/core/os/os2/process_wasi.odin b/core/os/process_wasi.odin similarity index 87% rename from core/os/os2/process_wasi.odin rename to core/os/process_wasi.odin index 9f4d61649..09c12a600 100644 --- a/core/os/os2/process_wasi.odin +++ b/core/os/process_wasi.odin @@ -1,14 +1,10 @@ #+private -package os2 +package os import "base:runtime" import "core:time" -import "core:sys/wasm/wasi" - -_exit :: proc "contextless" (code: int) -> ! { - wasi.proc_exit(wasi.exitcode_t(code)) -} +// import "core:sys/wasm/wasi" _get_uid :: proc() -> int { return 0 @@ -34,6 +30,14 @@ _get_ppid :: proc() -> int { return 0 } +_get_current_thread_id :: proc "contextless" () -> int { + return 0 +} + +_get_processor_core_count :: proc() -> int { + return 1 +} + _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) { err = .Unsupported return @@ -54,11 +58,11 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (process_stat return } -_process_close :: proc(process: Process) -> Error { +_process_kill :: proc(process: Process) -> (err: Error) { return .Unsupported } -_process_kill :: proc(process: Process) -> (err: Error) { +_process_terminate :: proc(process: Process) -> (err: Error) { return .Unsupported } diff --git a/core/os/os2/process_windows.odin b/core/os/process_windows.odin similarity index 90% rename from core/os/os2/process_windows.odin rename to core/os/process_windows.odin index 199e5ad74..e1ed4f3c0 100644 --- a/core/os/os2/process_windows.odin +++ b/core/os/process_windows.odin @@ -1,17 +1,13 @@ #+private file -package os2 +package os +import "base:intrinsics" import "base:runtime" import "core:strings" import win32 "core:sys/windows" import "core:time" -@(private="package") -_exit :: proc "contextless" (code: int) -> ! { - win32.ExitProcess(u32(code)) -} - @(private="package") _get_uid :: proc() -> int { return -1 @@ -55,6 +51,35 @@ _get_ppid :: proc() -> int { return -1 } +@(private="package") +_get_current_thread_id :: proc "contextless" () -> int { + return int(win32.GetCurrentThreadId()) +} + +@(private="package") +_get_processor_core_count :: proc() -> int { + length : win32.DWORD = 0 + result := win32.GetLogicalProcessorInformation(nil, &length) + + thread_count := 0 + if !result && win32.GetLastError() == 122 && length > 0 { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + processors := make([]win32.SYSTEM_LOGICAL_PROCESSOR_INFORMATION, length, context.temp_allocator) + + result = win32.GetLogicalProcessorInformation(&processors[0], &length) + if result { + for processor in processors { + if processor.Relationship == .RelationProcessorCore { + thread := intrinsics.count_ones(processor.ProcessorMask) + thread_count += int(thread) + } + } + } + } + + return thread_count +} + @(private="package") _process_list :: proc(allocator: runtime.Allocator) -> (list: []int, err: Error) { snap := win32.CreateToolhelp32Snapshot(win32.TH32CS_SNAPPROCESS, 0) @@ -175,7 +200,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator info.fields += {.Command_Line} } if .Command_Args in selection { - info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return + info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return info.fields += {.Command_Args} } } @@ -286,7 +311,7 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields info.fields += {.Command_Line} } if .Command_Args in selection { - info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return + info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return info.fields += {.Command_Args} } } @@ -514,6 +539,7 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (process_stat exit_code: u32 if !win32.GetExitCodeProcess(handle, &exit_code) { err =_get_platform_error() + _process_close(process) return } time_created: win32.FILETIME @@ -522,6 +548,7 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (process_stat time_user: win32.FILETIME if !win32.GetProcessTimes(handle, &time_created, &time_exited, &time_kernel, &time_user) { err = _get_platform_error() + _process_close(process) return } process_state = { @@ -532,17 +559,18 @@ _process_wait :: proc(process: Process, timeout: time.Duration) -> (process_stat system_time = _filetime_to_duration(time_kernel), user_time = _filetime_to_duration(time_user), } + _process_close(process) return case win32.WAIT_TIMEOUT: err = General_Error.Timeout return case: err = _get_platform_error() + _process_close(process) return } } -@(private="package") _process_close :: proc(process: Process) -> Error { if !win32.CloseHandle(win32.HANDLE(process.handle)) { return _get_platform_error() @@ -562,6 +590,49 @@ _process_kill :: proc(process: Process) -> Error { return nil } +@(private="package") +_process_terminate :: proc(process: Process) -> Error { + Enum_Windows_State :: struct { + has_windows: bool, + pid: int, + } + state: Enum_Windows_State + state.pid = process.pid + ok := win32.EnumWindows( + proc "system" (hwnd: win32.HWND, lParam: win32.LPARAM) -> win32.BOOL { + #assert(size_of(win32.LPARAM) == size_of(^Enum_Windows_State)) + state := (^Enum_Windows_State)(rawptr(uintptr(lParam))) + + dwPid: win32.DWORD + win32.GetWindowThreadProcessId(hwnd, &dwPid) + if (dwPid == win32.DWORD(state.pid)) { + state.has_windows = true + win32.PostMessageW(hwnd, win32.WM_CLOSE, 0, 0) + } + + return true + }, + win32.LPARAM(uintptr(&state)), + ) + if state.has_windows { + if ok { + return nil + } + + err := _get_platform_error() + kill_err := _process_kill(process) + return kill_err == nil ? nil : err + } + + if !win32.GenerateConsoleCtrlEvent(win32.CTRL_C_EVENT, win32.DWORD(process.pid)) { + err := _get_platform_error() + kill_err := _process_kill(process) + return kill_err == nil ? nil : err + } + + return nil +} + _filetime_to_duration :: proc(filetime: win32.FILETIME) -> time.Duration { ticks := u64(filetime.dwHighDateTime)<<32 | u64(filetime.dwLowDateTime) return time.Duration(ticks * 100) @@ -610,7 +681,7 @@ _process_exe_by_pid :: proc(pid: int, allocator: runtime.Allocator) -> (exe_path err =_get_platform_error() return } - return win32_wstring_to_utf8(raw_data(entry.szExePath[:]), allocator) + return win32_wstring_to_utf8(cstring16(raw_data(entry.szExePath[:])), allocator) } _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Allocator) -> (full_username: string, err: Error) { @@ -650,7 +721,7 @@ _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Alloc return strings.concatenate({domain, "\\", username}, allocator) } -_parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) -> (argv: []string, err: Error) { +_parse_command_line :: proc(cmd_line_w: cstring16, allocator: runtime.Allocator) -> (argv: []string, err: Error) { argc: i32 argv_w := win32.CommandLineToArgvW(cmd_line_w, &argc) if argv_w == nil { diff --git a/core/os/stat.odin b/core/os/stat.odin index 21a4961d1..fa92e8a8e 100644 --- a/core/os/stat.odin +++ b/core/os/stat.odin @@ -1,33 +1,117 @@ package os +import "base:runtime" +import "core:strings" import "core:time" +Fstat_Callback :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) + +/* + `File_Info` describes a file and is returned from `stat`, `fstat`, and `lstat`. +*/ File_Info :: struct { - fullpath: string, // allocated - name: string, // uses `fullpath` as underlying data - size: i64, - mode: File_Mode, - is_dir: bool, + fullpath: string, // fullpath of the file + name: string, // base name of the file + + inode: u128, // might be zero if cannot be determined + size: i64 `fmt:"M"`, // length in bytes for regular files; system-dependent for other file types + mode: Permissions, // file permission flags + type: File_Type, + creation_time: time.Time, modification_time: time.Time, access_time: time.Time, } -file_info_slice_delete :: proc(infos: []File_Info, allocator := context.allocator) { - for i := len(infos)-1; i >= 0; i -= 1 { - file_info_delete(infos[i], allocator) +@(require_results) +file_info_clone :: proc(fi: File_Info, allocator: runtime.Allocator) -> (cloned: File_Info, err: runtime.Allocator_Error) { + cloned = fi + cloned.fullpath = strings.clone(fi.fullpath, allocator) or_return + _, cloned.name = split_path(cloned.fullpath) + return +} + +file_info_slice_delete :: proc(infos: []File_Info, allocator: runtime.Allocator) { + #reverse for info in infos { + file_info_delete(info, allocator) } delete(infos, allocator) } -file_info_delete :: proc(fi: File_Info, allocator := context.allocator) { +file_info_delete :: proc(fi: File_Info, allocator: runtime.Allocator) { delete(fi.fullpath, allocator) } -File_Mode :: distinct u32 +@(require_results) +fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { + if f == nil { + return {}, nil + } else if f.stream.procedure != nil { + fi: File_Info + data := ([^]byte)(&fi)[:size_of(fi)] + _, err := f.stream.procedure(f, .Fstat, data, 0, nil, allocator) + return fi, err + } + return {}, .Invalid_Callback +} -File_Mode_Dir :: File_Mode(1<<16) -File_Mode_Named_Pipe :: File_Mode(1<<17) -File_Mode_Device :: File_Mode(1<<18) -File_Mode_Char_Device :: File_Mode(1<<19) -File_Mode_Sym_Link :: File_Mode(1<<20) +/* + `stat` returns a `File_Info` describing the named file from the file system. + The resulting `File_Info` must be deleted with `file_info_delete`. +*/ +@(require_results) +stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { + return _stat(name, allocator) +} + +lstat :: stat_do_not_follow_links + +/* + Returns a `File_Info` describing the named file from the file system. + If the file is a symbolic link, the `File_Info` returns describes the symbolic link, + rather than following the link. + The resulting `File_Info` must be deleted with `file_info_delete`. +*/ +@(require_results) +stat_do_not_follow_links :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { + return _lstat(name, allocator) +} + + +/* + Returns true if two `File_Info`s are equivalent. +*/ +@(require_results) +same_file :: proc(fi1, fi2: File_Info) -> bool { + return _same_file(fi1, fi2) +} + + +last_write_time :: modification_time +last_write_time_by_name :: modification_time_by_path + +/* + Returns the modification time of the file `f`. + The resolution of the timestamp is system-dependent. +*/ +@(require_results) +modification_time :: proc(f: ^File) -> (time.Time, Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + fi, err := fstat(f, temp_allocator) + return fi.modification_time, err +} + +/* + Returns the modification time of the named file `path`. + The resolution of the timestamp is system-dependent. +*/ +@(require_results) +modification_time_by_path :: proc(path: string) -> (time.Time, Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + fi, err := stat(path, temp_allocator) + return fi.modification_time, err +} + +is_reserved_name :: proc(path: string) -> bool { + return _is_reserved_name(path) +} \ No newline at end of file diff --git a/core/os/stat_js.odin b/core/os/stat_js.odin new file mode 100644 index 000000000..a304435d9 --- /dev/null +++ b/core/os/stat_js.odin @@ -0,0 +1,29 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" + +_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { + return {}, .Unsupported +} + +_stat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { + return {}, .Unsupported +} + +_lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { + return {}, .Unsupported +} + +_same_file :: proc(fi1, fi2: File_Info) -> bool { + return fi1.fullpath == fi2.fullpath +} + +_is_reserved_name :: proc(path: string) -> bool { + return false +} \ No newline at end of file diff --git a/core/os/os2/stat_linux.odin b/core/os/stat_linux.odin similarity index 79% rename from core/os/os2/stat_linux.odin rename to core/os/stat_linux.odin index 373765be5..3abddc275 100644 --- a/core/os/os2/stat_linux.odin +++ b/core/os/stat_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "core:time" import "base:runtime" @@ -11,8 +11,8 @@ _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { } _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { - s: linux.Stat - errno := linux.fstat(fd, &s) + s: linux.Statx + errno := linux.statx(fd, "", {.EMPTY_PATH}, {.TYPE, .MODE, .ATIME, .MTIME, .CTIME, .INO, .SIZE}, &s) if errno != .NONE { return {}, _get_platform_error(errno) } @@ -26,9 +26,8 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File case linux.S_IFREG: type = .Regular case linux.S_IFSOCK: type = .Socket } - mode := int(0o7777 & transmute(u32)s.mode) + mode := transmute(Permissions)(0o7777 & transmute(u32)s.mode) - // TODO: As of Linux 4.11, the new statx syscall can retrieve creation_time fi = File_Info { fullpath = _get_full_path(fd, allocator) or_return, name = "", @@ -36,9 +35,9 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File size = i64(s.size), mode = mode, type = type, - modification_time = time.Time {i64(s.mtime.time_sec) * i64(time.Second) + i64(s.mtime.time_nsec)}, - access_time = time.Time {i64(s.atime.time_sec) * i64(time.Second) + i64(s.atime.time_nsec)}, - creation_time = time.Time{i64(s.ctime.time_sec) * i64(time.Second) + i64(s.ctime.time_nsec)}, // regular stat does not provide this + modification_time = time.Time {i64(s.mtime.sec) * i64(time.Second) + i64(s.mtime.nsec)}, + access_time = time.Time {i64(s.atime.sec) * i64(time.Second) + i64(s.atime.nsec)}, + creation_time = time.Time {i64(s.btime.sec) * i64(time.Second) + i64(s.btime.nsec)}, } fi.creation_time = fi.modification_time _, fi.name = split_path(fi.fullpath) @@ -73,3 +72,7 @@ _lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, er _same_file :: proc(fi1, fi2: File_Info) -> bool { return fi1.fullpath == fi2.fullpath } + +_is_reserved_name :: proc(path: string) -> bool { + return false +} diff --git a/core/os/os2/stat_posix.odin b/core/os/stat_posix.odin similarity index 95% rename from core/os/os2/stat_posix.odin rename to core/os/stat_posix.odin index 6ffbdf1da..924860744 100644 --- a/core/os/os2/stat_posix.odin +++ b/core/os/stat_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" @@ -14,7 +14,7 @@ internal_stat :: proc(stat: posix.stat_t, fullpath: string) -> (fi: File_Info) { fi.inode = u128(stat.st_ino) fi.size = i64(stat.st_size) - fi.mode = int(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT)) + fi.mode = transmute(Permissions)u32(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT)) fi.type = .Undetermined switch { @@ -135,3 +135,7 @@ _lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, er _same_file :: proc(fi1, fi2: File_Info) -> bool { return fi1.fullpath == fi2.fullpath } + +_is_reserved_name :: proc(path: string) -> bool { + return false +} \ No newline at end of file diff --git a/core/os/os2/stat_wasi.odin b/core/os/stat_wasi.odin similarity index 96% rename from core/os/os2/stat_wasi.odin rename to core/os/stat_wasi.odin index bf18d8273..5f5e6fe45 100644 --- a/core/os/os2/stat_wasi.odin +++ b/core/os/stat_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" @@ -98,3 +98,7 @@ _lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, er _same_file :: proc(fi1, fi2: File_Info) -> bool { return fi1.fullpath == fi2.fullpath } + +_is_reserved_name :: proc(path: string) -> bool { + return false +} \ No newline at end of file diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index ca4f87668..35f2ae86b 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -1,51 +1,82 @@ +#+private package os -import "core:time" import "base:runtime" +import "core:time" +import "core:strings" import win32 "core:sys/windows" -@(private, require_results) -full_path_from_name :: proc(name: string, allocator := context.allocator) -> (path: string, err: Errno) { - context.allocator = allocator - +_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) { + if f == nil || (^File_Impl)(f.impl).fd == nil { + return + } + + path := _cleanpath_from_handle(f, allocator) or_return + + h := _handle(f) + switch win32.GetFileType(h) { + case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR: + fi = File_Info { + fullpath = path, + name = basename(path), + type = file_type(h), + } + return + } + + return _file_info_from_get_file_information_by_handle(path, h, allocator) +} + +_stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { + return internal_stat(name, win32.FILE_FLAG_BACKUP_SEMANTICS, allocator) +} + +_lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) { + return internal_stat(name, win32.FILE_FLAG_BACKUP_SEMANTICS|win32.FILE_FLAG_OPEN_REPARSE_POINT, allocator) +} + +_same_file :: proc(fi1, fi2: File_Info) -> bool { + return fi1.fullpath == fi2.fullpath +} + +full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path: string, err: Error) { name := name if name == "" { name = "." } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - p := win32.utf8_to_utf16(name, context.temp_allocator) - buf := make([dynamic]u16, 100) - defer delete(buf) - for { - n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) - if n == 0 { - return "", get_last_error() - } - if n <= u32(len(buf)) { - return win32.utf16_to_utf8(buf[:n], allocator) or_else "", nil - } - resize(&buf, len(buf)*2) - } - return + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + p := win32_utf8_to_utf16(name, temp_allocator) or_return + + n := win32.GetFullPathNameW(cstring16(raw_data(p)), 0, nil, nil) + if n == 0 { + return "", _get_platform_error() + } + buf := make([]u16, n+1, temp_allocator) + n = win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil) + if n == 0 { + return "", _get_platform_error() + } + return win32_utf16_to_utf8(buf[:n], allocator) } -@(private, require_results) -_stat :: proc(name: string, create_file_attributes: u32, allocator := context.allocator) -> (fi: File_Info, e: Errno) { +internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { if len(name) == 0 { - return {}, ERROR_PATH_NOT_FOUND + return {}, .Not_Exist } + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - context.allocator = allocator - - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - - wname := win32.utf8_to_wstring(fix_long_path(name), context.temp_allocator) + wname := _fix_long_path(name, temp_allocator) or_return fa: win32.WIN32_FILE_ATTRIBUTE_DATA ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa) if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { // Not a symlink - return file_info_from_win32_file_attribute_data(&fa, name) + fi = _file_info_from_win32_file_attribute_data(&fa, name, allocator) or_return + if fi.type == .Undetermined { + fi.type = _file_type_from_create_file(wname, create_file_attributes) + } + return } err := 0 if ok else win32.GetLastError() @@ -54,65 +85,28 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al fd: win32.WIN32_FIND_DATAW sh := win32.FindFirstFileW(wname, &fd) if sh == win32.INVALID_HANDLE_VALUE { - e = get_last_error() + e = _get_platform_error() return } win32.FindClose(sh) - return file_info_from_win32_find_data(&fd, name) + fi = _file_info_from_win32_find_data(&fd, name, allocator) or_return + if fi.type == .Undetermined { + fi.type = _file_type_from_create_file(wname, create_file_attributes) + } + return } h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) if h == win32.INVALID_HANDLE_VALUE { - e = get_last_error() + e = _get_platform_error() return } defer win32.CloseHandle(h) - return file_info_from_get_file_information_by_handle(name, h) + return _file_info_from_get_file_information_by_handle(name, h, allocator) } - -@(require_results) -lstat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { - attrs := win32.FILE_FLAG_BACKUP_SEMANTICS - attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT - return _stat(name, attrs, allocator) -} - -@(require_results) -stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { - attrs := win32.FILE_FLAG_BACKUP_SEMANTICS - return _stat(name, attrs, allocator) -} - -@(require_results) -fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) { - if fd == 0 { - err = ERROR_INVALID_HANDLE - } - context.allocator = allocator - - path := cleanpath_from_handle(fd) or_return - defer if err != nil { - delete(path) - } - - h := win32.HANDLE(fd) - switch win32.GetFileType(h) { - case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR: - fi.name = basename(path) - fi.mode |= file_type_mode(h) - err = nil - case: - fi = file_info_from_get_file_information_by_handle(path, h) or_return - } - fi.fullpath = path - return -} - - -@(private, require_results) -cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { +_cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { buf := buf N := 0 for c, i in buf { @@ -121,50 +115,59 @@ cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { } buf = buf[:N] - if len(buf) >= 4 && buf[0] == '\\' && buf[1] == '\\' && buf[2] == '?' && buf[3] == '\\' { - buf = buf[4:] - - /* - NOTE(Jeroen): Properly handle UNC paths. - We need to turn `\\?\UNC\synology.local` into `\\synology.local`. - */ - if len(buf) >= 3 && buf[0] == 'U' && buf[1] == 'N' && buf[2] == 'C' { - buf = buf[2:] - buf[0] = '\\' + if len(buf) >= 4 { + if buf[0] == '\\' && + buf[1] == '\\' && + buf[2] == '?' && + buf[3] == '\\' { + buf = buf[4:] } } return buf } -@(private, require_results) -cleanpath_from_handle :: proc(fd: Handle) -> (s: string, err: Errno) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) - buf := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return - return win32.utf16_to_utf8(buf, context.allocator) -} -@(private, require_results) -cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ([]u16, Errno) { - if fd == 0 { - return nil, ERROR_INVALID_HANDLE +_cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (string, Error) { + if f == nil { + return "", nil } - h := win32.HANDLE(fd) + h := _handle(f) n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0) if n == 0 { - return nil, get_last_error() + return "", _get_platform_error() } - buf := make([]u16, max(n, win32.DWORD(260))+1, allocator) - buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0) - return buf[:buf_len], nil -} -@(private, require_results) -cleanpath_from_buf :: proc(buf: []u16) -> string { - buf := buf - buf = cleanpath_strip_prefix(buf) - return win32.utf16_to_utf8(buf, context.allocator) or_else "" + + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + buf := make([]u16, max(n, 260)+1, temp_allocator) + n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0) + return _cleanpath_from_buf(string16(buf[:n]), allocator) +} + +_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) { + if f == nil { + return nil, nil + } + h := _handle(f) + + n := win32.GetFinalPathNameByHandleW(h, nil, 0, 0) + if n == 0 { + return nil, _get_platform_error() + } + + temp_allocator := TEMP_ALLOCATOR_GUARD({}) + + buf := make([]u16, max(n, 260)+1, temp_allocator) + n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0) + return _cleanpath_strip_prefix(buf[:n]), nil +} + +_cleanpath_from_buf :: proc(buf: string16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { + buf := transmute([]u16)buf + buf = _cleanpath_strip_prefix(buf) + return win32_utf16_to_utf8(buf, allocator) } -@(private, require_results) basename :: proc(name: string) -> (base: string) { name := name if len(name) > 3 && name[:3] == `\\?` { @@ -190,114 +193,209 @@ basename :: proc(name: string) -> (base: string) { return name } -@(private, require_results) -file_type_mode :: proc(h: win32.HANDLE) -> File_Mode { +file_type :: proc(h: win32.HANDLE) -> File_Type { switch win32.GetFileType(h) { - case win32.FILE_TYPE_PIPE: - return File_Mode_Named_Pipe - case win32.FILE_TYPE_CHAR: - return File_Mode_Device | File_Mode_Char_Device + case win32.FILE_TYPE_PIPE: return .Named_Pipe + case win32.FILE_TYPE_CHAR: return .Character_Device + case win32.FILE_TYPE_DISK: return .Regular } - return 0 + return .Undetermined } +_file_type_from_create_file :: proc(wname: win32.wstring, create_file_attributes: u32) -> File_Type { + h := win32.CreateFileW(wname, 0, 0, nil, win32.OPEN_EXISTING, create_file_attributes, nil) + if h == win32.INVALID_HANDLE_VALUE { + return .Undetermined + } + defer win32.CloseHandle(h) + return file_type(h) +} -@(private, require_results) -file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) { - if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { - mode |= 0o444 +_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: Permissions) { + if file_attributes & win32.FILE_ATTRIBUTE_READONLY != 0 { + mode += Permissions_Write_All } else { - mode |= 0o666 + mode += Permissions_Read_Write_All } is_sym := false - if FileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { + if file_attributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { is_sym = false } else { is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT } if is_sym { - mode |= File_Mode_Sym_Link - } else { - if FileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - mode |= 0o111 | File_Mode_Dir - } - - if h != nil { - mode |= file_type_mode(h) - } + type = .Symlink + } else if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { + type = .Directory + mode += Permissions_Execute_All + } else if h != nil { + type = file_type(h) } - return } -@(private) -windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) +// a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC) +time_as_filetime :: #force_inline proc(t: time.Time) -> (ft: win32.LARGE_INTEGER) { + win := u64(t._nsec / 100) + 116444736000000000 + return win32.LARGE_INTEGER(win) } -@(private, require_results) -file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { +filetime_as_time_li :: #force_inline proc(ft: win32.LARGE_INTEGER) -> (t: time.Time) { + return {_nsec=(i64(ft) - 116444736000000000) * 100} +} + +filetime_as_time_ft :: #force_inline proc(ft: win32.FILETIME) -> (t: time.Time) { + return filetime_as_time_li(win32.LARGE_INTEGER(ft.dwLowDateTime) + win32.LARGE_INTEGER(ft.dwHighDateTime) << 32) +} + +filetime_as_time :: proc{filetime_as_time_ft, filetime_as_time_li} + +_file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - - fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) - fi.is_dir = fi.mode & File_Mode_Dir != 0 - - windows_set_file_info_times(&fi, d) - - fi.fullpath, e = full_path_from_name(name) + type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.type = type + fi.mode |= mode + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) + fi.fullpath, e = full_path_from_name(name, allocator) fi.name = basename(fi.fullpath) - return } -@(private, require_results) -file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) -> (fi: File_Info, e: Errno) { +_file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - - fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) - fi.is_dir = fi.mode & File_Mode_Dir != 0 - - windows_set_file_info_times(&fi, d) - - fi.fullpath, e = full_path_from_name(name) + type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, 0) + fi.type = type + fi.mode |= mode + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) + fi.fullpath, e = full_path_from_name(name, allocator) fi.name = basename(fi.fullpath) - return } -@(private, require_results) -file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) { +_file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE, allocator: runtime.Allocator) -> (File_Info, Error) { d: win32.BY_HANDLE_FILE_INFORMATION if !win32.GetFileInformationByHandle(h, &d) { - err := get_last_error() - return {}, err + return {}, _get_platform_error() } ti: win32.FILE_ATTRIBUTE_TAG_INFO if !win32.GetFileInformationByHandleEx(h, .FileAttributeTagInfo, &ti, size_of(ti)) { - err := get_last_error() - if err != ERROR_INVALID_PARAMETER { + err := _get_platform_error() + if perr, ok := is_platform_error(err); ok && perr != i32(win32.ERROR_INVALID_PARAMETER) { return {}, err } // Indicate this is a symlink on FAT file systems ti.ReparseTag = 0 } - fi: File_Info - fi.fullpath = path fi.name = basename(path) - fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - - fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag) - fi.is_dir = fi.mode & File_Mode_Dir != 0 - - windows_set_file_info_times(&fi, &d) - + fi.inode = u128(u64(d.nFileIndexHigh)<<32 + u64(d.nFileIndexLow)) + fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) + type, mode := _file_type_mode_from_file_attributes(d.dwFileAttributes, h, 0) + fi.type = type + fi.mode |= mode + fi.creation_time = filetime_as_time(d.ftCreationTime) + fi.modification_time = filetime_as_time(d.ftLastWriteTime) + fi.access_time = filetime_as_time(d.ftLastAccessTime) return fi, nil } + +reserved_names := [?]string{ + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", +} + +_is_reserved_name :: proc(path: string) -> bool { + if len(path) == 0 { + return false + } + for reserved in reserved_names { + if strings.equal_fold(path, reserved) { + return true + } + } + return false +} + +_volume_name_len :: proc(path: string) -> (length: int) { + if len(path) < 2 { + return 0 + } + + if path[1] == ':' { + switch path[0] { + case 'a'..='z', 'A'..='Z': + return 2 + } + } + + /* + See: URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + Further allowed paths can be of the form of: + - \\server\share or \\server\share\more\path + - \\?\C:\... + - \\.\PhysicalDriveX + */ + // Any remaining kind of path has to start with two slashes. + if !_is_path_separator(path[0]) || !_is_path_separator(path[1]) { + return 0 + } + + // Device path. The volume name is the whole string + if len(path) >= 5 && path[2] == '.' && _is_path_separator(path[3]) { + return len(path) + } + + // We're a UNC share `\\host\share`, file namespace `\\?\C:` or UNC in file namespace `\\?\\host\share` + prefix := 2 + + // File namespace. + if len(path) >= 5 && path[2] == '?' && _is_path_separator(path[3]) { + if _is_path_separator(path[4]) { + // `\\?\\` UNC path in file namespace + prefix = 5 + } + + if len(path) >= 6 && path[5] == ':' { + switch path[4] { + case 'a'..='z', 'A'..='Z': + return 6 + case: + return 0 + } + } + } + + // UNC path, minimum version of the volume is `\\h\s` for host, share. + // Can also contain an IP address in the host position. + // (path might be purely path separators) + slash_count := 0 + found_host: bool + for i in prefix.. (f: ^File, err: Error) { +create_temp_file :: proc(dir, pattern: string, additional_flags: File_Flags = {}) -> (f: ^File, err: Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) dir := dir if dir != "" else temp_directory(temp_allocator) or_return prefix, suffix := _prefix_and_suffix(pattern) or_return - prefix = temp_join_path(dir, prefix) or_return + prefix = temp_join_path(dir, prefix, temp_allocator) or_return rand_buf: [10]byte name_buf := make([]byte, len(prefix)+len(rand_buf)+len(suffix), temp_allocator) @@ -26,7 +26,7 @@ create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) { attempts := 0 for { name := concatenate_strings_from_buffer(name_buf[:], prefix, random_string(rand_buf[:]), suffix) - f, err = open(name, {.Read, .Write, .Create, .Excl}, 0o666) + f, err = open(name, {.Read, .Write, .Create, .Excl} + additional_flags, Permissions_Read_Write_All) if err == .Exist { close(f) attempts += 1 @@ -50,7 +50,7 @@ make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) dir := dir if dir != "" else temp_directory(temp_allocator) or_return prefix, suffix := _prefix_and_suffix(pattern) or_return - prefix = temp_join_path(dir, prefix) or_return + prefix = temp_join_path(dir, prefix, temp_allocator) or_return rand_buf: [10]byte name_buf := make([]byte, len(prefix)+len(rand_buf)+len(suffix), temp_allocator) @@ -58,7 +58,7 @@ make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) attempts := 0 for { name := concatenate_strings_from_buffer(name_buf[:], prefix, random_string(rand_buf[:]), suffix) - err = make_directory(name, 0o700) + err = make_directory(name) if err == nil { return clone_string(name, allocator) } @@ -80,6 +80,19 @@ make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) } temp_dir :: temp_directory + +/* + Returns the default directory to use for temporary files. + + On Unix systems, it typically returns $TMPDIR if non-empty, otherwlse `/tmp`. + On Windows, it uses `GetTempPathW`, returning the first non-empty value from one of the following: + * `%TMP%` + * `%TEMP%` + * `%USERPROFILE %` + * or the Windows directory + See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppathw for more information. + On wasi, it returns `/tmp`. +*/ @(require_results) temp_directory :: proc(allocator: runtime.Allocator) -> (string, Error) { return _temp_dir(allocator) @@ -88,12 +101,10 @@ temp_directory :: proc(allocator: runtime.Allocator) -> (string, Error) { @(private="file") -temp_join_path :: proc(dir, name: string) -> (string, runtime.Allocator_Error) { - temp_allocator := TEMP_ALLOCATOR_GUARD({}) - +temp_join_path :: proc(dir, name: string, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { if len(dir) > 0 && is_path_separator(dir[len(dir)-1]) { - return concatenate({dir, name}, temp_allocator,) + return concatenate({dir, name}, allocator) } - return concatenate({dir, Path_Separator_String, name}, temp_allocator) + return concatenate({dir, Path_Separator_String, name}, allocator) } diff --git a/core/os/temp_file_js.odin b/core/os/temp_file_js.odin new file mode 100644 index 000000000..53158d843 --- /dev/null +++ b/core/os/temp_file_js.odin @@ -0,0 +1,13 @@ +#+build js wasm32, js wasm64p32 +#+private +package os + +// None of this does anything on js/wasm. +// It's only here so importing `core:os` on wasm panics cleanly, +// without spamming about all sorts of missing procs and types. + +import "base:runtime" + +_temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { + return "", .Mode_Not_Implemented +} \ No newline at end of file diff --git a/core/os/os2/temp_file_linux.odin b/core/os/temp_file_linux.odin similarity index 96% rename from core/os/os2/temp_file_linux.odin rename to core/os/temp_file_linux.odin index 310720cbe..30f2169ad 100644 --- a/core/os/os2/temp_file_linux.odin +++ b/core/os/temp_file_linux.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/temp_file_posix.odin b/core/os/temp_file_posix.odin similarity index 97% rename from core/os/os2/temp_file_posix.odin rename to core/os/temp_file_posix.odin index b44ea13a7..a72dc2fab 100644 --- a/core/os/os2/temp_file_posix.odin +++ b/core/os/temp_file_posix.odin @@ -1,6 +1,6 @@ #+private #+build darwin, netbsd, freebsd, openbsd -package os2 +package os import "base:runtime" diff --git a/core/os/os2/temp_file_wasi.odin b/core/os/temp_file_wasi.odin similarity index 95% rename from core/os/os2/temp_file_wasi.odin rename to core/os/temp_file_wasi.odin index d5628d300..d3fa941f7 100644 --- a/core/os/os2/temp_file_wasi.odin +++ b/core/os/temp_file_wasi.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" diff --git a/core/os/os2/temp_file_windows.odin b/core/os/temp_file_windows.odin similarity index 77% rename from core/os/os2/temp_file_windows.odin rename to core/os/temp_file_windows.odin index 9d75ef99d..4c927134d 100644 --- a/core/os/os2/temp_file_windows.odin +++ b/core/os/temp_file_windows.odin @@ -1,5 +1,5 @@ #+private -package os2 +package os import "base:runtime" import win32 "core:sys/windows" @@ -12,12 +12,12 @@ _temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Er temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) b := make([]u16, max(win32.MAX_PATH, n), temp_allocator) - n = win32.GetTempPathW(u32(len(b)), raw_data(b)) + n = win32.GetTempPathW(u32(len(b)), cstring16(raw_data(b))) if n == 3 && b[1] == ':' && b[2] == '\\' { } else if n > 0 && b[n-1] == '\\' { n -= 1 } - return win32_utf16_to_utf8(b[:n], allocator) + return win32_utf16_to_utf8(string16(b[:n]), allocator) } diff --git a/core/os/user.odin b/core/os/user.odin new file mode 100644 index 000000000..8e952477d --- /dev/null +++ b/core/os/user.odin @@ -0,0 +1,149 @@ +package os + +import "base:runtime" + +// ``` +// Windows: C:\Users\Alice +// macOS: /Users/Alice +// Linux: /home/alice +// ``` +@(require_results) +user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_home_dir(allocator) +} + +// Files that applications can regenerate/refetch at a loss of speed, e.g. shader caches +// +// Sometimes deleted for system maintenance +// +// ``` +// Windows: C:\Users\Alice\AppData\Local +// macOS: /Users/Alice/Library/Caches +// Linux: /home/alice/.cache +// ``` +@(require_results) +user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_cache_dir(allocator) +} + +// User-hidden application data +// +// ``` +// Windows: C:\Users\Alice\AppData\Local ("C:\Users\Alice\AppData\Roaming" if `roaming`) +// macOS: /Users/Alice/Library/Application Support +// Linux: /home/alice/.local/share +// ``` +// +// NOTE: (Windows only) `roaming` is for syncing across multiple devices within a *domain network* +@(require_results) +user_data_dir :: proc(allocator: runtime.Allocator, roaming := false) -> (dir: string, err: Error) { + return _user_data_dir(allocator, roaming) +} + +// Non-essential application data, e.g. history, ui layout state +// +// ``` +// Windows: C:\Users\Alice\AppData\Local +// macOS: /Users/Alice/Library/Application Support +// Linux: /home/alice/.local/state +// ``` +@(require_results) +user_state_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_state_dir(allocator) +} + +// Application log files +// +// ``` +// Windows: C:\Users\Alice\AppData\Local +// macOS: /Users/Alice/Library/Logs +// Linux: /home/alice/.local/state +// ``` +@(require_results) +user_log_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_log_dir(allocator) +} + +// Application settings/preferences +// +// ``` +// Windows: C:\Users\Alice\AppData\Local ("C:\Users\Alice\AppData\Roaming" if `roaming`) +// macOS: /Users/Alice/Library/Application Support +// Linux: /home/alice/.config +// ``` +// +// NOTE: (Windows only) `roaming` is for syncing across multiple devices within a *domain network* +@(require_results) +user_config_dir :: proc(allocator: runtime.Allocator, roaming := false) -> (dir: string, err: Error) { + return _user_config_dir(allocator, roaming) +} + +// ``` +// Windows: C:\Users\Alice\Music +// macOS: /Users/Alice/Music +// Linux: /home/alice/Music +// ``` +@(require_results) +user_music_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_music_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Desktop +// macOS: /Users/Alice/Desktop +// Linux: /home/alice/Desktop +// ``` +@(require_results) +user_desktop_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_desktop_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Documents +// macOS: /Users/Alice/Documents +// Linux: /home/alice/Documents +// ``` +@(require_results) +user_documents_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_documents_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Downloads +// macOS: /Users/Alice/Downloads +// Linux: /home/alice/Downloads +// ``` +@(require_results) +user_downloads_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_downloads_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Pictures +// macOS: /Users/Alice/Pictures +// Linux: /home/alice/Pictures +// ``` +@(require_results) +user_pictures_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_pictures_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Public +// macOS: /Users/Alice/Public +// Linux: /home/alice/Public +// ``` +@(require_results) +user_public_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_public_dir(allocator) +} + +// ``` +// Windows: C:\Users\Alice\Videos +// macOS: /Users/Alice/Movies +// Linux: /home/alice/Videos +// ``` +@(require_results) +user_videos_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + return _user_videos_dir(allocator) +} \ No newline at end of file diff --git a/core/os/user_posix.odin b/core/os/user_posix.odin new file mode 100644 index 000000000..355a2e3cd --- /dev/null +++ b/core/os/user_posix.odin @@ -0,0 +1,176 @@ +#+build !windows +package os + +import "base:intrinsics" +import "base:runtime" +import "core:strings" + +_user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Library/Caches", allocator) + case: // Unix + return _xdg_lookup("XDG_CACHE_HOME", "/.cache", allocator) + } +} + +_user_config_dir :: proc(allocator: runtime.Allocator, _roaming: bool) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Library/Application Support", allocator) + case: // Unix + return _xdg_lookup("XDG_CONFIG_HOME", "/.config", allocator) + } +} + +_user_state_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Library/Application Support", allocator) + case: // Unix + return _xdg_lookup("XDG_STATE_HOME", "/.local/state", allocator) + } +} + +_user_log_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Library/Logs", allocator) + case: // Unix + return _xdg_lookup("XDG_STATE_HOME", "/.local/state", allocator) + } +} + +_user_data_dir :: proc(allocator: runtime.Allocator, _roaming: bool) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Library/Application Support", allocator) + case: // Unix + return _xdg_lookup("XDG_DATA_HOME", "/.local/share", allocator) + } +} + +_user_music_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Music", allocator) + case: // Unix + return _xdg_lookup("XDG_MUSIC_DIR", "/Music", allocator) + } +} + +_user_desktop_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Desktop", allocator) + case: // Unix + return _xdg_lookup("XDG_DESKTOP_DIR", "/Desktop", allocator) + } +} + +_user_documents_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Documents", allocator) + case: // Unix + return _xdg_lookup("XDG_DOCUMENTS_DIR", "/Documents", allocator) + } +} + +_user_downloads_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Downloads", allocator) + case: // Unix + return _xdg_lookup("XDG_DOWNLOAD_DIR", "/Downloads", allocator) + } +} + +_user_pictures_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Pictures", allocator) + case: // Unix + return _xdg_lookup("XDG_PICTURES_DIR", "/Pictures", allocator) + } +} + +_user_public_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Public", allocator) + case: // Unix + return _xdg_lookup("XDG_PUBLICSHARE_DIR", "/Public", allocator) + } +} + +_user_videos_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + #partial switch ODIN_OS { + case .Darwin: + return _xdg_lookup("", "/Movies", allocator) + case: // Unix + return _xdg_lookup("XDG_VIDEOS_DIR", "/Videos", allocator) + } +} + +_user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + if v := get_env("HOME", allocator); v != "" { + return v, nil + } + err = .No_HOME_Variable + return +} + +_xdg_lookup :: proc(xdg_key: string, fallback_suffix: string, allocator: runtime.Allocator) -> (dir: string, err: Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + + if xdg_key == "" { // Darwin doesn't have XDG paths. + dir = get_env("HOME", temp_allocator) + if dir == "" { + err = .No_HOME_Variable + return + } + return concatenate({dir, fallback_suffix}, allocator) + } else { + if strings.ends_with(xdg_key, "_DIR") { + dir = _xdg_user_dirs_lookup(xdg_key, allocator) or_return + } else { + dir = get_env(xdg_key, allocator) + } + + if dir == "" { + dir = get_env("HOME", temp_allocator) + if dir == "" { + err = .No_HOME_Variable + return + } + dir = concatenate({dir, fallback_suffix}, allocator) or_return + } + return + } +} + +// If `/user-dirs.dirs` doesn't exist, or `xdg_key` can't be found there: returns `""` +_xdg_user_dirs_lookup :: proc(xdg_key: string, allocator: runtime.Allocator) -> (dir: string, err: Error) { + temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) + config_dir := user_config_dir(temp_allocator) or_return + user_dirs_path := concatenate({config_dir, "/user-dirs.dirs"}, temp_allocator) or_return + content := read_entire_file(user_dirs_path, temp_allocator) or_return + + xdg_dirs := string(content) + for line in strings.split_lines_iterator(&xdg_dirs) { + if len(line) > 0 && line[0] == '#' { + continue + } + + equals := strings.index(line, "=") + if equals > -1 { + if line[:equals] == xdg_key { + // Unquote to return a bare path string as we do on Windows + val := strings.trim(line[equals+1:], "\"") + return replace_environment_placeholders(val, allocator), nil + } + } + } + return +} \ No newline at end of file diff --git a/core/os/user_windows.odin b/core/os/user_windows.odin new file mode 100644 index 000000000..6f7b74d6d --- /dev/null +++ b/core/os/user_windows.odin @@ -0,0 +1,78 @@ +package os + +import "base:runtime" +@(require) import win32 "core:sys/windows" + +_local_appdata :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_LocalAppData + return _get_known_folder_path(&guid, allocator) +} + +_local_appdata_or_roaming :: proc(allocator: runtime.Allocator, roaming: bool) -> (dir: string, err: Error) { + guid := win32.FOLDERID_LocalAppData + if roaming { + guid = win32.FOLDERID_RoamingAppData + } + return _get_known_folder_path(&guid, allocator) +} + +_user_config_dir :: _local_appdata_or_roaming +_user_data_dir :: _local_appdata_or_roaming + +_user_state_dir :: _local_appdata +_user_log_dir :: _local_appdata +_user_cache_dir :: _local_appdata + +_user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Profile + return _get_known_folder_path(&guid, allocator) +} + +_user_music_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Music + return _get_known_folder_path(&guid, allocator) +} + +_user_desktop_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Desktop + return _get_known_folder_path(&guid, allocator) +} + +_user_documents_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Documents + return _get_known_folder_path(&guid, allocator) +} + +_user_downloads_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Downloads + return _get_known_folder_path(&guid, allocator) +} + +_user_pictures_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Pictures + return _get_known_folder_path(&guid, allocator) +} + +_user_public_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Public + return _get_known_folder_path(&guid, allocator) +} + +_user_videos_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { + guid := win32.FOLDERID_Videos + return _get_known_folder_path(&guid, allocator) +} + +_get_known_folder_path :: proc(rfid: win32.REFKNOWNFOLDERID, allocator: runtime.Allocator) -> (dir: string, err: Error) { + // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath + // See also `known_folders.odin` in `core:sys/windows` for the GUIDs. + path_w: win32.LPWSTR + res := win32.SHGetKnownFolderPath(rfid, 0, nil, &path_w) + defer win32.CoTaskMemFree(path_w) + + if res != 0 { + return "", .Invalid_Path + } + + return win32_wstring_to_utf8(cstring16(path_w), allocator) +} \ No newline at end of file diff --git a/core/os/wasm.odin b/core/os/wasm.odin new file mode 100644 index 000000000..79c00f694 --- /dev/null +++ b/core/os/wasm.odin @@ -0,0 +1,4 @@ +#+build js wasm32, js wasm64p32 +package os + +#panic("core:os is unsupported on js/wasm") \ No newline at end of file diff --git a/core/path/filepath/match.odin b/core/path/filepath/match.odin index 1f0ac9287..178d5f986 100644 --- a/core/path/filepath/match.odin +++ b/core/path/filepath/match.odin @@ -1,15 +1,8 @@ #+build !wasi +#+build !js package filepath import "core:os" -import "core:slice" -import "core:strings" -import "core:unicode/utf8" - -Match_Error :: enum { - None, - Syntax_Error, -} // match states whether "name" matches the shell pattern // Pattern syntax is: @@ -33,183 +26,7 @@ Match_Error :: enum { // // NOTE(bill): This is effectively the shell pattern matching system found // -match :: proc(pattern, name: string) -> (matched: bool, err: Match_Error) { - pattern, name := pattern, name - pattern_loop: for len(pattern) > 0 { - star: bool - chunk: string - star, chunk, pattern = scan_chunk(pattern) - if star && chunk == "" { - return !strings.contains(name, SEPARATOR_STRING), .None - } - - t: string - ok: bool - t, ok, err = match_chunk(chunk, name) - - if ok && (len(t) == 0 || len(pattern) > 0) { - name = t - continue - } - if err != .None { - return - } - if star { - for i := 0; i < len(name) && name[i] != SEPARATOR; i += 1 { - t, ok, err = match_chunk(chunk, name[i+1:]) - if ok { - if len(pattern) == 0 && len(t) > 0 { - continue - } - name = t - continue pattern_loop - } - if err != .None { - return - } - } - } - - return false, .None - } - - return len(name) == 0, .None -} - - -@(private="file") -scan_chunk :: proc(pattern: string) -> (star: bool, chunk, rest: string) { - pattern := pattern - for len(pattern) > 0 && pattern[0] == '*' { - pattern = pattern[1:] - star = true - } - - in_range, i := false, 0 - - scan_loop: for i = 0; i < len(pattern); i += 1 { - switch pattern[i] { - case '\\': - when ODIN_OS != .Windows { - if i+1 < len(pattern) { - i += 1 - } - } - case '[': - in_range = true - case ']': - in_range = false - case '*': - in_range or_break scan_loop - - } - } - return star, pattern[:i], pattern[i:] -} - -@(private="file") -match_chunk :: proc(chunk, s: string) -> (rest: string, ok: bool, err: Match_Error) { - chunk, s := chunk, s - for len(chunk) > 0 { - if len(s) == 0 { - return - } - switch chunk[0] { - case '[': - r, w := utf8.decode_rune_in_string(s) - s = s[w:] - chunk = chunk[1:] - is_negated := false - if len(chunk) > 0 && chunk[0] == '^' { - is_negated = true - chunk = chunk[1:] - } - match := false - range_count := 0 - for { - if len(chunk) > 0 && chunk[0] == ']' && range_count > 0 { - chunk = chunk[1:] - break - } - lo, hi: rune - if lo, chunk, err = get_escape(chunk); err != .None { - return - } - hi = lo - if chunk[0] == '-' { - if hi, chunk, err = get_escape(chunk[1:]); err != .None { - return - } - } - - if lo <= r && r <= hi { - match = true - } - range_count += 1 - } - if match == is_negated { - return - } - - case '?': - if s[0] == SEPARATOR { - return - } - _, w := utf8.decode_rune_in_string(s) - s = s[w:] - chunk = chunk[1:] - - case '\\': - when ODIN_OS != .Windows { - chunk = chunk[1:] - if len(chunk) == 0 { - err = .Syntax_Error - return - } - } - fallthrough - case: - if chunk[0] != s[0] { - return - } - s = s[1:] - chunk = chunk[1:] - - } - } - return s, true, .None -} - -@(private="file") -get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Match_Error) { - if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { - err = .Syntax_Error - return - } - chunk := chunk - if chunk[0] == '\\' && ODIN_OS != .Windows { - chunk = chunk[1:] - if len(chunk) == 0 { - err = .Syntax_Error - return - } - } - - w: int - r, w = utf8.decode_rune_in_string(chunk) - if r == utf8.RUNE_ERROR && w == 1 { - err = .Syntax_Error - } - - next_chunk = chunk[w:] - if len(next_chunk) == 0 { - err = .Syntax_Error - } - - return -} - - +match :: os.match // glob returns the names of all files matching pattern or nil if there are no matching files // The syntax of patterns is the same as "match". @@ -217,145 +34,4 @@ get_escape :: proc(chunk: string) -> (r: rune, next_chunk: string, err: Match_Er // // glob ignores file system errors // -glob :: proc(pattern: string, allocator := context.allocator) -> (matches: []string, err: Match_Error) { - context.allocator = allocator - - if !has_meta(pattern) { - // TODO(bill): os.lstat on here to check for error - m := make([]string, 1) - m[0] = pattern - return m[:], .None - } - - dir, file := split(pattern) - volume_len := 0 - when ODIN_OS == .Windows { - temp_buf: [8]byte - volume_len, dir = clean_glob_path_windows(dir, temp_buf[:]) - - } else { - dir = clean_glob_path(dir) - } - - if !has_meta(dir[volume_len:]) { - m, e := _glob(dir, file, nil) - return m[:], e - } - - m: []string - m, err = glob(dir) - if err != .None { - return - } - defer { - for s in m { - delete(s) - } - delete(m) - } - - dmatches := make([dynamic]string, 0, 0) - for d in m { - dmatches, err = _glob(d, file, &dmatches) - if err != .None { - break - } - } - if len(dmatches) > 0 { - matches = dmatches[:] - } - return -} - -// Internal implementation of `glob`, not meant to be used by the user. Prefer `glob`. -_glob :: proc(dir, pattern: string, matches: ^[dynamic]string, allocator := context.allocator) -> (m: [dynamic]string, e: Match_Error) { - context.allocator = allocator - - if matches != nil { - m = matches^ - } else { - m = make([dynamic]string, 0, 0) - } - - - d, derr := os.open(dir, os.O_RDONLY) - if derr != nil { - return - } - defer os.close(d) - - { - file_info, ferr := os.fstat(d) - defer os.file_info_delete(file_info) - - if ferr != nil { - return - } - if !file_info.is_dir { - return - } - } - - - fis, _ := os.read_dir(d, -1) - slice.sort_by(fis, proc(a, b: os.File_Info) -> bool { - return a.name < b.name - }) - defer { - for fi in fis { - os.file_info_delete(fi) - } - delete(fis) - } - - for fi in fis { - n := fi.name - matched := match(pattern, n) or_return - if matched { - append(&m, join({dir, n})) - } - } - return -} - -@(private) -has_meta :: proc(path: string) -> bool { - when ODIN_OS == .Windows { - CHARS :: `*?[` - } else { - CHARS :: `*?[\` - } - return strings.contains_any(path, CHARS) -} - -@(private) -clean_glob_path :: proc(path: string) -> string { - switch path { - case "": - return "." - case SEPARATOR_STRING: - return path - } - return path[:len(path)-1] -} - - -@(private) -clean_glob_path_windows :: proc(path: string, temp_buf: []byte) -> (prefix_len: int, cleaned: string) { - vol_len := volume_name_len(path) - switch { - case path == "": - return 0, "." - case vol_len+1 == len(path) && is_separator(path[len(path)-1]): // /, \, C:\, C:/ - return vol_len+1, path - case vol_len == len(path) && len(path) == 2: // C: - copy(temp_buf[:], path) - temp_buf[2] = '.' - return vol_len, string(temp_buf[:3]) - } - - if vol_len >= len(path) { - vol_len = len(path) -1 - } - return vol_len, path[:len(path)-1] -} +glob :: os.glob \ No newline at end of file diff --git a/core/path/filepath/path.odin b/core/path/filepath/path.odin index e23183b02..09c0187bc 100644 --- a/core/path/filepath/path.odin +++ b/core/path/filepath/path.odin @@ -1,35 +1,46 @@ -// The path/filepath package uses either forward slashes or backslashes depending on the operating system -// To process paths such as URLs that depend on forward slashes regardless of the OS, use the path package +// Process paths using either forward slashes or backslashes depending on the operating system. +// To process paths such as URLs that depend on forward slashes regardless of the OS, use the slashpath package. package filepath import "base:runtime" +import "core:os" import "core:strings" SEPARATOR_CHARS :: `/\` // is_separator checks whether the byte is a valid separator character -is_separator :: proc(c: byte) -> bool { - switch c { - case '/': return true - case '\\': return ODIN_OS == .Windows - } - return false -} +is_separator :: os.is_path_separator -@(private) -is_slash :: proc(c: byte) -> bool { - return c == '\\' || c == '/' -} +/* + In Windows, returns `true` if `path` is one of the following: + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", + + On other platforms, returns `false`. +*/ +is_reserved_name :: os.is_reserved_name // Splits path immediate following the last separator; separating the path into a directory and file. // If no separator is found, `dir` will be empty and `path` set to `path`. -split :: proc(path: string) -> (dir, file: string) { - vol := volume_name(path) - i := len(path) - 1 - for i >= len(vol) && !is_separator(path[i]) { - i -= 1 - } - return path[:i+1], path[i+1:] +split :: os.split_path + + +/* +Join all `elems` with the system's path separator and normalize the result. + +*Allocates Using Provided Allocator* + +For example, `join_path({"/home", "foo", "bar.txt"})` will result in `"/home/foo/bar.txt"`. +*/ +join :: proc( + elems: []string, + allocator := context.allocator, +) -> ( + joined: string, + err: runtime.Allocator_Error, +) { + return os.join_path(elems, allocator) } /* @@ -39,48 +50,7 @@ split :: proc(path: string) -> (dir, file: string) { "C:\foo\bar\baz" will return "C:" on Windows. Everything else will be "". */ -volume_name :: proc(path: string) -> string { - return path[:volume_name_len(path)] -} - -// Returns the length of the volume name in bytes. -volume_name_len :: proc(path: string) -> int { - if ODIN_OS == .Windows { - if len(path) < 2 { - return 0 - } - c := path[0] - if path[1] == ':' { - switch c { - case 'a'..='z', 'A'..='Z': - return 2 - } - } - - // URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx - if l := len(path); l >= 5 && is_slash(path[0]) && is_slash(path[1]) && - !is_slash(path[2]) && path[2] != '.' { - for n := 3; n < l-1; n += 1 { - if is_slash(path[n]) { - n += 1 - if !is_slash(path[n]) { - if path[n] == '.' { - break - } - } - for ; n < l; n += 1 { - if is_slash(path[n]) { - break - } - } - return n - } - break - } - } - } - return 0 -} +volume_name :: os.volume_name /* Gets the file name and extension from a path. @@ -92,30 +62,7 @@ volume_name_len :: proc(path: string) -> int { Returns "." if the path is an empty string. */ -base :: proc(path: string) -> string { - if path == "" { - return "." - } - - path := path - for len(path) > 0 && is_separator(path[len(path)-1]) { - path = path[:len(path)-1] - } - - path = path[volume_name_len(path):] - - i := len(path)-1 - for i >= 0 && !is_separator(path[i]) { - i -= 1 - } - if i >= 0 { - path = path[i+1:] - } - if path == "" { - return SEPARATOR_STRING - } - return path -} +base :: os.base /* Gets the name of a file from a path. @@ -132,24 +79,7 @@ base :: proc(path: string) -> string { Returns an empty string if there is no stem. e.g: '.gitignore'. Returns an empty string if there's a trailing path separator. */ -stem :: proc(path: string) -> string { - if len(path) > 0 && is_separator(path[len(path) - 1]) { - // NOTE(tetra): Trailing separator - return "" - } - - // NOTE(tetra): Get the basename - path := path - if i := strings.last_index_any(path, SEPARATOR_CHARS); i != -1 { - path = path[i+1:] - } - - if i := strings.last_index_byte(path, '.'); i != -1 { - return path[:i] - } - - return path -} +stem :: os.stem /* Gets the name of a file from a path. @@ -165,13 +95,7 @@ stem :: proc(path: string) -> string { Returns an empty string if there is no stem. e.g: '.gitignore'. Returns an empty string if there's a trailing path separator. */ -short_stem :: proc(path: string) -> string { - s := stem(path) - if i := strings.index_byte(s, '.'); i != -1 { - return s[:i] - } - return s -} +short_stem :: os.short_stem /* Gets the file extension from a path, including the dot. @@ -188,14 +112,7 @@ short_stem :: proc(path: string) -> string { Returns an empty string if there is no dot. Returns an empty string if there is a trailing path separator. */ -ext :: proc(path: string) -> string { - for i := len(path)-1; i >= 0 && !is_separator(path[i]); i -= 1 { - if path[i] == '.' { - return path[i:] - } - } - return "" -} +ext :: os.ext /* Gets the file extension from a path, including the dot. @@ -211,24 +128,7 @@ ext :: proc(path: string) -> string { Returns an empty string if there is no dot. Returns an empty string if there is a trailing path separator. */ -long_ext :: proc(path: string) -> string { - if len(path) > 0 && is_separator(path[len(path) - 1]) { - // NOTE(tetra): Trailing separator - return "" - } - - // NOTE(tetra): Get the basename - path := path - if i := strings.last_index_any(path, SEPARATOR_CHARS); i != -1 { - path = path[i+1:] - } - - if i := strings.index_byte(path, '.'); i != -1 { - return path[i:] - } - - return "" -} +long_ext :: os.long_ext /* Returns the shortest path name equivalent to `path` through solely lexical processing. @@ -245,108 +145,56 @@ long_ext :: proc(path: string) -> string { If the result of the path is an empty string, the returned path with be `"."`. */ -clean :: proc(path: string, allocator := context.allocator) -> (cleaned: string, err: runtime.Allocator_Error) #optional_allocator_error { - context.allocator = allocator - - path := path - original_path := path - vol_len := volume_name_len(path) - path = path[vol_len:] - - if path == "" { - if vol_len > 1 && original_path[1] != ':' { - s, ok := from_slash(original_path) - if !ok { - s = strings.clone(s) or_return - } - return s, nil - } - return strings.concatenate({original_path, "."}) - } - - rooted := is_separator(path[0]) - - n := len(path) - out := &Lazy_Buffer{ - s = path, - vol_and_path = original_path, - vol_len = vol_len, - } - defer lazy_buffer_destroy(out) - - r, dot_dot := 0, 0 - if rooted { - lazy_buffer_append(out, SEPARATOR) or_return - r, dot_dot = 1, 1 - } - - for r < n { - switch { - case is_separator(path[r]): - r += 1 - case path[r] == '.' && (r+1 == n || is_separator(path[r+1])): - r += 1 - case path[r] == '.' && path[r+1] == '.' && (r+2 == n || is_separator(path[r+2])): - r += 2 - switch { - case out.w > dot_dot: - out.w -= 1 - for out.w > dot_dot && !is_separator(lazy_buffer_index(out, out.w)) { - out.w -= 1 - } - case !rooted: - if out.w > 0 { - lazy_buffer_append(out, SEPARATOR) or_return - } - lazy_buffer_append(out, '.') or_return - lazy_buffer_append(out, '.') or_return - dot_dot = out.w - } - case: - if rooted && out.w != 1 || !rooted && out.w != 0 { - lazy_buffer_append(out, SEPARATOR) or_return - } - for ; r < n && !is_separator(path[r]); r += 1 { - lazy_buffer_append(out, path[r]) or_return - } - - } - } - - if out.w == 0 { - lazy_buffer_append(out, '.') or_return - } - - s := lazy_buffer_string(out) or_return - - new_allocation: bool - cleaned, new_allocation = from_slash(s) - if new_allocation { - delete(s) - } - return +clean :: proc( + path: string, + allocator := context.allocator, +) -> ( + cleaned: string, + err: runtime.Allocator_Error, +) { + return os.clean_path(path, allocator) } -// Returns the result of replacing each forward slash `/` character in the path with the separate OS specific character. -from_slash :: proc(path: string, allocator := context.allocator) -> (new_path: string, new_allocation: bool) { - if SEPARATOR == '/' { - return path, false - } - return strings.replace_all(path, "/", SEPARATOR_STRING, allocator) +/* +Returns the result of replacing each path separator character in the path +with the specific character `new_sep`. + +*Allocates Using Provided Allocator* +*/ +replace_separators :: proc( + path: string, + new_sep: rune, + allocator := context.allocator, +) -> ( + new_path: string, + err: os.Error, +) { + return os.replace_path_separators(path, new_sep, allocator) } -// Returns the result of replacing each OS specific separator with a forward slash `/` character. -to_slash :: proc(path: string, allocator := context.allocator) -> (new_path: string, new_allocation: bool) { - if SEPARATOR == '/' { - return path, false - } - return strings.replace_all(path, SEPARATOR_STRING, "/", allocator) -} +/* +Return true if `path` is an absolute path as opposed to a relative one. +*/ +is_abs :: os.is_absolute_path +/* +Get the absolute path to `path` with respect to the process's current directory. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +abs :: proc( + path: string, + allocator := context.allocator, +) -> ( + absolute_path: string, + error: os.Error, +) { + return os.get_absolute_path(path, allocator) +} Relative_Error :: enum { None, - Cannot_Relate, } @@ -359,8 +207,10 @@ Relative_Error :: enum { */ rel :: proc(base_path, target_path: string, allocator := context.allocator) -> (string, Relative_Error) { context.allocator = allocator - base_clean := clean(base_path, allocator) - target_clean := clean(target_path, allocator) + base_clean, base_err := clean(base_path, allocator) + if base_err != nil { return "", .Cannot_Relate} + target_clean, target_err := clean(target_path, allocator) + if target_err != nil { return "", .Cannot_Relate} defer delete(base_clean, allocator) defer delete(target_clean, allocator) @@ -368,8 +218,8 @@ rel :: proc(base_path, target_path: string, allocator := context.allocator) -> ( return strings.clone(".", allocator), .None } - base_vol := volume_name(base_path) - target_vol := volume_name(target_path) + base_vol := volume_name(base_clean) + target_vol := volume_name(target_clean) base := base_clean [len(base_vol):] target := target_clean[len(target_vol):] if base == "." { @@ -430,25 +280,11 @@ rel :: proc(base_path, target_path: string, allocator := context.allocator) -> ( } /* - Returns all but the last element path, usually the path's directory. Once the final element has been removed, - `dir` calls `clean` on the path and trailing separators are removed. If the path consists purely of separators, - then `"."` is returned. + Returns all but the last path element, usually the path's directory. Once the final element has been removed, + `dir` calls `clean` on the path and trailing separators are removed. If the path is empty or consists purely + of separators, then `"."` is returned. */ -dir :: proc(path: string, allocator := context.allocator) -> string { - context.allocator = allocator - vol := volume_name(path) - i := len(path) - 1 - for i >= len(vol) && !is_separator(path[i]) { - i -= 1 - } - dir := clean(path[len(vol) : i+1]) - defer delete(dir) - if dir == "." && len(vol) > 2 { - return strings.clone(vol) - } - return strings.concatenate({vol, dir}) -} - +dir :: os.dir // Splits the PATH-like `path` string, returning an array of its separated components (delete after use). @@ -456,108 +292,4 @@ dir :: proc(path: string, allocator := context.allocator) -> string { // An empty string returns nil. A non-empty string with no separators returns a 1-element array. // Any empty components will be included, e.g. `a::b` will return a 3-element array, as will `::`. // Separators within pairs of double-quotes will be ignored and stripped, e.g. `"a:b"c:d` will return []{`a:bc`, `d`}. -split_list :: proc(path: string, allocator := context.allocator) -> (list: []string, err: runtime.Allocator_Error) #optional_allocator_error { - if path == "" { - return nil, nil - } - - start: int - quote: bool - - start, quote = 0, false - count := 0 - - for i := 0; i < len(path); i += 1 { - c := path[i] - switch { - case c == '"': - quote = !quote - case c == LIST_SEPARATOR && !quote: - count += 1 - } - } - - start, quote = 0, false - list = make([]string, count + 1, allocator) or_return - index := 0 - for i := 0; i < len(path); i += 1 { - c := path[i] - switch { - case c == '"': - quote = !quote - case c == LIST_SEPARATOR && !quote: - list[index] = path[start:i] - index += 1 - start = i + 1 - } - } - assert(index == count) - list[index] = path[start:] - - for s0, i in list { - s, new := strings.replace_all(s0, `"`, ``, allocator) - if !new { - s = strings.clone(s, allocator) or_return - } - list[i] = s - } - - return list, nil -} - - - - -/* - Lazy_Buffer is a lazily made path buffer - When it does allocate, it uses the context.allocator - */ -@(private) -Lazy_Buffer :: struct { - s: string, - b: []byte, - w: int, // write index - vol_and_path: string, - vol_len: int, -} - -@(private) -lazy_buffer_index :: proc(lb: ^Lazy_Buffer, i: int) -> byte { - if lb.b != nil { - return lb.b[i] - } - return lb.s[i] -} -@(private) -lazy_buffer_append :: proc(lb: ^Lazy_Buffer, c: byte) -> (err: runtime.Allocator_Error) { - if lb.b == nil { - if lb.w < len(lb.s) && lb.s[lb.w] == c { - lb.w += 1 - return - } - lb.b = make([]byte, len(lb.s)) or_return - copy(lb.b, lb.s[:lb.w]) - } - lb.b[lb.w] = c - lb.w += 1 - return -} -@(private) -lazy_buffer_string :: proc(lb: ^Lazy_Buffer) -> (s: string, err: runtime.Allocator_Error) { - if lb.b == nil { - return strings.clone(lb.vol_and_path[:lb.vol_len+lb.w]) - } - - x := lb.vol_and_path[:lb.vol_len] - y := string(lb.b[:lb.w]) - z := make([]byte, len(x)+len(y)) or_return - copy(z, x) - copy(z[len(x):], y) - return string(z), nil -} -@(private) -lazy_buffer_destroy :: proc(lb: ^Lazy_Buffer) -> runtime.Allocator_Error { - err := delete(lb.b) - lb^ = {} - return err -} +split_list :: os.split_path_list \ No newline at end of file diff --git a/core/path/filepath/path_js.odin b/core/path/filepath/path_js.odin new file mode 100644 index 000000000..e2657cb3e --- /dev/null +++ b/core/path/filepath/path_js.odin @@ -0,0 +1,5 @@ +package filepath + +SEPARATOR :: '/' +SEPARATOR_STRING :: `/` +LIST_SEPARATOR :: ':' \ No newline at end of file diff --git a/core/path/filepath/path_unix.odin b/core/path/filepath/path_unix.odin index 8bf412599..3079c31f9 100644 --- a/core/path/filepath/path_unix.odin +++ b/core/path/filepath/path_unix.odin @@ -1,46 +1,6 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd package filepath -import "base:runtime" - -import "core:strings" -import "core:sys/posix" - SEPARATOR :: '/' SEPARATOR_STRING :: `/` LIST_SEPARATOR :: ':' - -is_reserved_name :: proc(path: string) -> bool { - return false -} - -is_abs :: proc(path: string) -> bool { - return strings.has_prefix(path, "/") -} - -abs :: proc(path: string, allocator := context.allocator) -> (string, bool) { - rel := path - if rel == "" { - rel = "." - } - rel_cstr := strings.clone_to_cstring(rel, context.temp_allocator) - path_ptr := posix.realpath(rel_cstr, nil) - if path_ptr == nil { - return "", posix.errno() == nil - } - defer posix.free(path_ptr) - - path_str := strings.clone(string(path_ptr), allocator) - return path_str, true -} - -join :: proc(elems: []string, allocator := context.allocator) -> (joined: string, err: runtime.Allocator_Error) #optional_allocator_error { - for e, i in elems { - if e != "" { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - p := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator) or_return - return clean(p, allocator) - } - } - return "", nil -} diff --git a/core/path/filepath/path_wasi.odin b/core/path/filepath/path_wasi.odin index 74cc6ca1e..e2657cb3e 100644 --- a/core/path/filepath/path_wasi.odin +++ b/core/path/filepath/path_wasi.odin @@ -1,36 +1,5 @@ package filepath -import "base:runtime" - -import "core:strings" - SEPARATOR :: '/' SEPARATOR_STRING :: `/` -LIST_SEPARATOR :: ':' - -is_reserved_name :: proc(path: string) -> bool { - return false -} - -is_abs :: proc(path: string) -> bool { - return strings.has_prefix(path, "/") -} - -abs :: proc(path: string, allocator := context.allocator) -> (string, bool) { - if is_abs(path) { - return strings.clone(string(path), allocator), true - } - - return path, false -} - -join :: proc(elems: []string, allocator := context.allocator) -> (joined: string, err: runtime.Allocator_Error) #optional_allocator_error { - for e, i in elems { - if e != "" { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) - p := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator) or_return - return clean(p, allocator) - } - } - return "", nil -} +LIST_SEPARATOR :: ':' \ No newline at end of file diff --git a/core/path/filepath/path_windows.odin b/core/path/filepath/path_windows.odin index 0dcb28cf8..9b8e92bbd 100644 --- a/core/path/filepath/path_windows.odin +++ b/core/path/filepath/path_windows.odin @@ -1,135 +1,9 @@ package filepath -import "core:strings" -import "base:runtime" -import "core:os" -import win32 "core:sys/windows" - SEPARATOR :: '\\' SEPARATOR_STRING :: `\` LIST_SEPARATOR :: ';' -@(private) -reserved_names := [?]string{ - "CON", "PRN", "AUX", "NUL", - "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", - "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", -} - -is_reserved_name :: proc(path: string) -> bool { - if len(path) == 0 { - return false - } - for reserved in reserved_names { - if strings.equal_fold(path, reserved) { - return true - } - } - return false -} - is_UNC :: proc(path: string) -> bool { - return volume_name_len(path) > 2 -} - - -is_abs :: proc(path: string) -> bool { - if is_reserved_name(path) { - return true - } - l := volume_name_len(path) - if l == 0 { - return false - } - - path := path - path = path[l:] - if path == "" { - return false - } - return is_slash(path[0]) -} - - -@(private) -temp_full_path :: proc(name: string) -> (path: string, err: os.Error) { - ta := context.temp_allocator - - name := name - if name == "" { - name = "." - } - - p := win32.utf8_to_utf16(name, ta) - n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil) - if n == 0 { - return "", os.get_last_error() - } - - buf := make([]u16, n, ta) - n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) - if n == 0 { - delete(buf) - return "", os.get_last_error() - } - - return win32.utf16_to_utf8(buf[:n], ta) -} - - - -abs :: proc(path: string, allocator := context.allocator) -> (string, bool) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = allocator == context.temp_allocator) - full_path, err := temp_full_path(path) - if err != nil { - return "", false - } - p := clean(full_path, allocator) - return p, true -} - - -join :: proc(elems: []string, allocator := context.allocator) -> string { - for e, i in elems { - if e != "" { - return join_non_empty(elems[i:], allocator) - } - } - return "" -} - -join_non_empty :: proc(elems: []string, allocator := context.allocator) -> string { - context.allocator = allocator - - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = allocator == context.temp_allocator) - - if len(elems[0]) == 2 && elems[0][1] == ':' { - i := 1 - for ; i < len(elems); i += 1 { - if elems[i] != "" { - break - } - } - s := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator) - s = strings.concatenate({elems[0], s}, context.temp_allocator) - return clean(s) - } - - p := clean(strings.join(elems, SEPARATOR_STRING, context.temp_allocator)) - if !is_UNC(p) { - return p - } - - head := clean(elems[0], context.temp_allocator) - if is_UNC(head) { - return p - } - delete(p) // It is not needed now - - tail := clean(strings.join(elems[1:], SEPARATOR_STRING, context.temp_allocator), context.temp_allocator) - if head[len(head)-1] == SEPARATOR { - return strings.concatenate({head, tail}) - } - - return strings.concatenate({head, SEPARATOR_STRING, tail}) -} + return len(volume_name(path)) > 2 +} \ No newline at end of file diff --git a/core/path/filepath/walk.odin b/core/path/filepath/walk.odin index 53b10eed7..2e2a4ff54 100644 --- a/core/path/filepath/walk.odin +++ b/core/path/filepath/walk.odin @@ -1,82 +1,105 @@ #+build !wasi +#+build !js package filepath import "core:os" -import "core:slice" -// Walk_Proc is the type of the procedure called for each file or directory visited by 'walk' -// The 'path' parameter contains the parameter to walk as a prefix (this is the same as info.fullpath except on 'root') -// The 'info' parameter is the os.File_Info for the named path -// -// If there was a problem walking to the file or directory named by path, the incoming error will describe the problem -// and the procedure can decide how to handle that error (and walk will not descend into that directory) -// In the case of an error, the info argument will be 0 -// If an error is returned, processing stops -// The sole exception is if 'skip_dir' is returned as true: -// when 'skip_dir' is invoked on a directory. 'walk' skips directory contents -// when 'skip_dir' is invoked on a non-directory. 'walk' skips the remaining files in the containing directory -Walk_Proc :: #type proc(info: os.File_Info, in_err: os.Error, user_data: rawptr) -> (err: os.Error, skip_dir: bool) +Walker :: os.Walker -// walk walks the file tree rooted at 'root', calling 'walk_proc' for each file or directory in the tree, including 'root' -// All errors that happen visiting files and directories are filtered by walk_proc -// The files are walked in lexical order to make the output deterministic -// NOTE: Walking large directories can be inefficient due to the lexical sort -// NOTE: walk does not follow symbolic links -// NOTE: os.File_Info uses the 'context.temp_allocator' to allocate, and will delete when it is done -walk :: proc(root: string, walk_proc: Walk_Proc, user_data: rawptr) -> os.Error { - info, err := os.lstat(root, context.temp_allocator) - defer os.file_info_delete(info, context.temp_allocator) +/* +Initializes a walker, either using a path or a file pointer to a directory the walker will start at. - skip_dir: bool - if err != nil { - err, skip_dir = walk_proc(info, err, user_data) - } else { - err, skip_dir = _walk(info, walk_proc, user_data) - } - return nil if skip_dir else err -} +You are allowed to repeatedly call this to reuse it for later walks. +For an example on how to use the walker, see `walker_walk`. +*/ +walker_init :: os.walker_init -@(private) -_walk :: proc(info: os.File_Info, walk_proc: Walk_Proc, user_data: rawptr) -> (err: os.Error, skip_dir: bool) { - if !info.is_dir { - if info.fullpath == "" && info.name == "" { - // ignore empty things - return - } - return walk_proc(info, nil, user_data) - } +/* +Creates a walker, either using a path or a file pointer to a directory the walker will start at. - fis: []os.File_Info - err1: os.Error - fis, err = read_dir(info.fullpath, context.temp_allocator) - defer os.file_info_slice_delete(fis, context.temp_allocator) +For an example on how to use the walker, see `walker_walk`. +*/ +walker_create :: os.walker_create - err1, skip_dir = walk_proc(info, err, user_data) - if err != nil || err1 != nil || skip_dir { - err = err1 - return - } +/* +Returns the last error that occurred during the walker's operations. - for fi in fis { - err, skip_dir = _walk(fi, walk_proc, user_data) - if err != nil || skip_dir { - if !fi.is_dir || !skip_dir { - return +Can be called while iterating, or only at the end to check if anything failed. +*/ +walker_error :: os.walker_error + +walker_destroy :: os.walker_destroy + +// Marks the current directory to be skipped (not entered into). +walker_skip_dir :: os.walker_skip_dir + +/* +Returns the next file info in the iterator, files are iterated in breadth-first order. + +If an error occurred opening a directory, you may get zero'd info struct and +`walker_error` will return the error. + +Example: + package main + + import "core:fmt" + import "core:strings" + import "core:os" + + main :: proc() { + w := os.walker_create("core") + defer os.walker_destroy(&w) + + for info in os.walker_walk(&w) { + // Optionally break on the first error: + // _ = walker_error(&w) or_break + + // Or, handle error as we go: + if path, err := os.walker_error(&w); err != nil { + fmt.eprintfln("failed walking %s: %s", path, err) + continue } + + // Or, do not handle errors during iteration, and just check the error at the end. + + + + // Skip a directory: + if strings.has_suffix(info.fullpath, ".git") { + os.walker_skip_dir(&w) + continue + } + + fmt.printfln("%#v", info) + } + + // Handle error if one happened during iteration at the end: + if path, err := os.walker_error(&w); err != nil { + fmt.eprintfln("failed walking %s: %v", path, err) } } +*/ +walker_walk :: os.walker_walk - return -} +/* + Reads the file `f` (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ +read_directory :: os.read_directory -@(private) -read_dir :: proc(dir_name: string, allocator := context.temp_allocator) -> (fis: []os.File_Info, err: os.Error) { - f := os.open(dir_name, os.O_RDONLY) or_return - defer os.close(f) - fis = os.read_dir(f, -1, allocator) or_return - slice.sort_by(fis, proc(a, b: os.File_Info) -> bool { - return a.name < b.name - }) - return -} +/* + Reads the file `f` (assuming it is a directory) and returns all of the unsorted directory entries. +*/ +read_all_directory :: os.read_all_directory + +/* + Reads the named directory by path (assuming it is a directory) and returns the unsorted directory entries. + This returns up to `n` entries OR all of them if `n <= 0`. +*/ +read_directory_by_path :: os.read_directory_by_path + +/* + Reads the named directory by path (assuming it is a directory) and returns all of the unsorted directory entries. +*/ +read_all_directory_by_path :: os.read_all_directory_by_path \ No newline at end of file diff --git a/core/path/slashpath/path.odin b/core/path/slashpath/path.odin index 52b4878bc..1d2a24453 100644 --- a/core/path/slashpath/path.odin +++ b/core/path/slashpath/path.odin @@ -1,5 +1,4 @@ -// The slashpath package is only to be used for paths separated by forward slashes, -// e.g. paths in URLs +// Process paths separated by forward slashes only, e.g. paths in `URL`s. // // This package does not deal with Windows/NT paths with volume letters or backslashes // To manipulate operating system specific paths, use the path/filepath package diff --git a/core/prof/spall/doc.odin b/core/prof/spall/doc.odin index b007ad4cb..e07a00a26 100644 --- a/core/prof/spall/doc.odin +++ b/core/prof/spall/doc.odin @@ -1,4 +1,8 @@ /* +Profiling using the "`spall`" format. + +See: [[ https://gravitymoth.com/spall/ ]] + Example: package main diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index 12f082b2c..281eaa82d 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -1,36 +1,44 @@ package spall +import "base:intrinsics" + import "core:os" import "core:time" -import "base:intrinsics" // File Format MANUAL_MAGIC :: u64le(0x0BADF00D) -Manual_Header :: struct #packed { +Manual_Stream_Header :: struct #packed { magic: u64le, version: u64le, timestamp_scale: f64le, reserved: u64le, } +Manual_Buffer_Header :: struct #packed { + size: u32le, + tid: u32le, + pid: u32le, + first_ts: u64le, +} + Manual_Event_Type :: enum u8 { - Invalid = 0, + Invalid = 0, - Begin = 3, - End = 4, - Instant = 5, + Begin = 3, + End = 4, + Instant = 5, - Pad_Skip = 7, + Pad_Skip = 7, + + Name_Process = 8, + Name_Thread = 9, } Begin_Event :: struct #packed { type: Manual_Event_Type, - category: u8, - pid: u32le, - tid: u32le, - ts: f64le, + ts: u64le, name_len: u8, args_len: u8, } @@ -38,9 +46,7 @@ BEGIN_EVENT_MAX :: size_of(Begin_Event) + 255 + 255 End_Event :: struct #packed { type: Manual_Event_Type, - pid: u32le, - tid: u32le, - ts: f64le, + ts: u64le, } Pad_Skip :: struct #packed { @@ -48,12 +54,20 @@ Pad_Skip :: struct #packed { size: u32le, } +Name_Event :: struct #packed { + type: Manual_Event_Type, + name_len: u8, +} +NAME_EVENT_MAX :: size_of(Name_Event) + 255 + // User Interface Context :: struct { precise_time: bool, timestamp_scale: f64, - fd: os.Handle, + + file: ^os.File, + fd: uintptr, } Buffer :: struct { @@ -61,66 +75,84 @@ Buffer :: struct { head: int, tid: u32, pid: u32, + first_ts: u64, } BUFFER_DEFAULT_SIZE :: 0x10_0000 context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok { - fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600) + file, err := os.open(filename, {.Write, .Append, .Create, .Trunc}, {.Read_User, .Write_User}) if err != nil { return } - ctx.fd = fd + ctx.file = file + ctx.fd = os.fd(file) + ctx.precise_time = precise_time ctx.timestamp_scale = timestamp_scale - temp := [size_of(Manual_Header)]u8{} - _build_header(temp[:], ctx.timestamp_scale) - os.write(ctx.fd, temp[:]) + temp := [size_of(Manual_Stream_Header)]u8{} + _build_stream_header(temp[:], ctx.timestamp_scale) + write(ctx.fd, temp[:]) ok = true return } context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok { freq, freq_ok := time.tsc_frequency(sleep) - timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1 + timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000_000) if freq_ok else 1 return context_create_with_scale(filename, freq_ok, timestamp_scale) } context_create :: proc{context_create_with_scale, context_create_with_sleep} +@(no_instrumentation) context_destroy :: proc(ctx: ^Context) { if ctx == nil { return } - os.close(ctx.fd) + os.close(ctx.file) ctx^ = Context{} } buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok { assert(len(data) >= 1024) - buffer.data = data - buffer.tid = tid - buffer.pid = pid - buffer.head = 0 + buffer.data = data + buffer.tid = tid + buffer.pid = pid + buffer.first_ts = 0 + buffer.head = size_of(Manual_Buffer_Header) ok = true return } @(no_instrumentation) buffer_flush :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_check /* bounds check would segfault instrumentation */ { + if len(buffer.data) == 0 { + return + } + + buffer_size := buffer.head - size_of(Manual_Buffer_Header) + hdr := (^Manual_Buffer_Header)(raw_data(buffer.data)) + hdr.size = u32le(buffer_size) + hdr.pid = u32le(buffer.pid) + hdr.tid = u32le(buffer.tid) + hdr.first_ts = u64le(buffer.first_ts) + start := _trace_now(ctx) write(ctx.fd, buffer.data[:buffer.head]) - buffer.head = 0 + buffer.head = size_of(Manual_Buffer_Header) end := _trace_now(ctx) - buffer.head += _build_begin(buffer.data[buffer.head:], "Spall Trace Buffer Flush", "", start, buffer.tid, buffer.pid) - buffer.head += _build_end(buffer.data[buffer.head:], end, buffer.tid, buffer.pid) + buffer.head += _build_begin(buffer.data[buffer.head:], "Spall Trace Buffer Flush", "", start) + buffer.head += _build_end(buffer.data[buffer.head:], end) + buffer.first_ts = end } +@(no_instrumentation) buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { buffer_flush(ctx, buffer) @@ -130,35 +162,37 @@ buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { @(deferred_in=_scoped_buffer_end) +@(no_instrumentation) SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool { _buffer_begin(ctx, buffer, name, args, location) return true } @(private) +@(no_instrumentation) _scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) { _buffer_end(ctx, buffer) } @(no_instrumentation) -_trace_now :: proc "contextless" (ctx: ^Context) -> f64 { +_trace_now :: proc "contextless" (ctx: ^Context) -> u64 { if !ctx.precise_time { - return f64(tick_now()) / 1_000 + return u64(tick_now()) } - return f64(intrinsics.read_cycle_counter()) + return u64(intrinsics.read_cycle_counter()) } @(no_instrumentation) -_build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok { - header_size = size_of(Manual_Header) +_build_stream_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok { + header_size = size_of(Manual_Stream_Header) if header_size > len(buffer) { return 0, false } - hdr := (^Manual_Header)(raw_data(buffer)) + hdr := (^Manual_Stream_Header)(raw_data(buffer)) hdr.magic = MANUAL_MAGIC - hdr.version = 1 + hdr.version = 3 hdr.timestamp_scale = f64le(timestamp_scale) hdr.reserved = 0 ok = true @@ -166,7 +200,7 @@ _build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (hea } @(no_instrumentation) -_build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, args: string, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ { +_build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, args: string, ts: u64) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ { ev := (^Begin_Event)(raw_data(buffer)) name_len := min(len(name), 255) args_len := min(len(args), 255) @@ -177,9 +211,7 @@ _build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, ar } ev.type = .Begin - ev.pid = u32le(pid) - ev.tid = u32le(tid) - ev.ts = f64le(ts) + ev.ts = u64le(ts) ev.name_len = u8(name_len) ev.args_len = u8(args_len) intrinsics.mem_copy_non_overlapping(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len) @@ -190,7 +222,7 @@ _build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, ar } @(no_instrumentation) -_build_end :: proc "contextless" (buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok { +_build_end :: proc "contextless" (buffer: []u8, ts: u64) -> (event_size: int, ok: bool) #optional_ok { ev := (^End_Event)(raw_data(buffer)) event_size = size_of(End_Event) if event_size > len(buffer) { @@ -198,9 +230,28 @@ _build_end :: proc "contextless" (buffer: []u8, ts: f64, tid: u32, pid: u32) -> } ev.type = .End - ev.pid = u32le(pid) - ev.tid = u32le(tid) - ev.ts = f64le(ts) + ev.ts = u64le(ts) + ok = true + + return +} + +@(no_instrumentation) +_build_name_event :: #force_inline proc "contextless" (buffer: []u8, name: string, type: Manual_Event_Type) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ { + ev := (^Name_Event)(raw_data(buffer)) + name_len := min(len(name), 255) + + event_size = size_of(Name_Event) + name_len + if event_size > len(buffer) { + return 0, false + } + if type != .Name_Process && type != .Name_Thread { + return 0, false + } + + ev.type = type + ev.name_len = u8(name_len) + intrinsics.mem_copy_non_overlapping(raw_data(buffer[size_of(Name_Event):]), raw_data(name), name_len) ok = true return @@ -212,7 +263,7 @@ _buffer_begin :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: strin buffer_flush(ctx, buffer) } name := location.procedure if name == "" else name - buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx), buffer.tid, buffer.pid) + buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx)) } @(no_instrumentation) @@ -223,15 +274,31 @@ _buffer_end :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_ch buffer_flush(ctx, buffer) } - buffer.head += _build_end(buffer.data[buffer.head:], ts, buffer.tid, buffer.pid) + buffer.head += _build_end(buffer.data[buffer.head:], ts) } @(no_instrumentation) -write :: proc "contextless" (fd: os.Handle, buf: []byte) -> (n: int, err: os.Error) { - return _write(fd, buf) +_buffer_name_thread :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: string, location := #caller_location) #no_bounds_check /* bounds check would segfault instrumentation */ { + if buffer.head + NAME_EVENT_MAX > len(buffer.data) { + buffer_flush(ctx, buffer) + } + buffer.head += _build_name_event(buffer.data[buffer.head:], name, .Name_Thread) } @(no_instrumentation) +_buffer_name_process :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: string, location := #caller_location) #no_bounds_check /* bounds check would segfault instrumentation */ { + if buffer.head + NAME_EVENT_MAX > len(buffer.data) { + buffer_flush(ctx, buffer) + } + buffer.head += _build_name_event(buffer.data[buffer.head:], name, .Name_Process) +} + +@(no_instrumentation, private="package") +write :: proc "contextless" (fd: uintptr, buf: []byte) { + _write(fd, buf) +} + +@(no_instrumentation, private="package") tick_now :: proc "contextless" () -> (ns: i64) { return _tick_now() } diff --git a/core/prof/spall/spall_linux.odin b/core/prof/spall/spall_linux.odin index 8060af448..207bd8471 100644 --- a/core/prof/spall/spall_linux.odin +++ b/core/prof/spall/spall_linux.odin @@ -1,19 +1,17 @@ #+private package spall -// Only for types and constants. -import "core:os" - // Package is `#+no-instrumentation`, safe to use. import "core:sys/linux" MAX_RW :: 0x7fffffff @(no_instrumentation) -_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ { +_write :: proc "contextless" (fd: uintptr, data: []byte) #no_bounds_check /* bounds check would segfault instrumentation */ { + n: int for n < len(data) { chunk := data[:min(len(data), MAX_RW)] - n += linux.write(linux.Fd(fd), chunk) or_return + n += linux.write(linux.Fd(fd), chunk) or_break } return } diff --git a/core/prof/spall/spall_unix.odin b/core/prof/spall/spall_unix.odin index 455245aad..2f1e356ee 100644 --- a/core/prof/spall/spall_unix.odin +++ b/core/prof/spall/spall_unix.odin @@ -2,29 +2,23 @@ #+build darwin, freebsd, openbsd, netbsd package spall -// Only for types. -import "core:os" - import "core:sys/posix" MAX_RW :: 0x7fffffff @(no_instrumentation) -_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (n: int, err: os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ { - if len(data) == 0 { - return 0, nil - } - +_write :: proc "contextless" (fd: uintptr, data: []byte) #no_bounds_check /* bounds check would segfault instrumentation */ { + n: int for n < len(data) { chunk := data[:min(len(data), MAX_RW)] written := posix.write(posix.FD(fd), raw_data(chunk), len(chunk)) if written < 0 { - return n, os.get_last_error() + return } n += written } - return n, nil + return } // NOTE(tetra): "RAW" means: Not adjusted by NTP. diff --git a/core/prof/spall/spall_windows.odin b/core/prof/spall/spall_windows.odin index 11e216b63..2d059dc4d 100644 --- a/core/prof/spall/spall_windows.odin +++ b/core/prof/spall/spall_windows.odin @@ -1,20 +1,13 @@ #+private package spall -// Only for types. -import "core:os" - // Package is `#+no-instrumentation`, safe to use. import win32 "core:sys/windows" MAX_RW :: 1<<30 @(no_instrumentation) -_write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Error) #no_bounds_check /* bounds check would segfault instrumentation */ { - if len(data) == 0 { - return 0, nil - } - +_write :: proc "contextless" (fd: uintptr, data: []byte) #no_bounds_check /* bounds check would segfault instrumentation */ { single_write_length: win32.DWORD total_write: i64 length := i64(len(data)) @@ -25,11 +18,12 @@ _write :: proc "contextless" (fd: os.Handle, data: []byte) -> (int, os.Error) #n e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil) if single_write_length <= 0 || !e { - return int(total_write), os.get_last_error() + return } total_write += i64(single_write_length) } - return int(total_write), nil + + return } @(no_instrumentation) diff --git a/core/reflect/doc.odin b/core/reflect/doc.odin new file mode 100644 index 000000000..5ec5e7070 --- /dev/null +++ b/core/reflect/doc.odin @@ -0,0 +1,51 @@ +// Utility procedures and types to perform runtime type introspection/reflection (`RTTI`). +// +// WARNING! THIS IS ADVANCED BEHAVIOUR FOR ODIN! THIS SHOULD NOT BE USED BY BEGINNERS TO ODIN! +// +// This package is only to be used by individuals who know exactly how the RTTI works as well as EXACTLY how `any` works. +// Especially since `any` can be unintuitive in its use to many, it can be dangerous to use. It is highly recommend that you **do not** +// use `any` unless you know exactly what you are doing. +// +// RTTI is an extremely powerful tool which should only be used when absolutely necessary (such runtime-type-safe formatted printing). +// +// ## The Type System of Odin +// +// It is important to understand how the type systems works in Odin before using any RTTI. A good example of this is Odin's `distinct` type system. +// In Odin, `distinct` types are represented by `Type_Info_Named`. A named struct is a `Type_Info_Named` which then points to a `Type_Info_Struct`. +// This means you must use something like `type_info_base` to restrict the `Type_Info_Named` aspect and get the base-type directly. Doing a type-assertion +// on the variant will not work as (incorrectly) expected without doing this. +// +// ## Advanced Information of How `any` Works +// +// An overview of how `any` works: +// +// An `any` type can reference any data type. It is functionally equivalent to `struct {data: rawptr, id: typeid}` with extra semantics on +// how assignment and type assertion works. +// +// This is commonly used to construct runtime-type-safe printing, such as in `core:fmt`. +// The use of `any` outside of this is heavily discourage and should be only used by people who FULLY understand its semantics. +// +// The `any` value is only valid as long as the underlying data is still valid. Passing a literal to an `any` will allocate the literal in +// the current stack frame. +// +// Example: +// x: int = 123 +// a: any = x +// // equivalent to +// a: any +// a.data = &x +// a.id = typeid_of(type_of(x)) +// // With literals +// v: any = 123 +// // equivalent to +// v: any +// _tmp: int = 123 +// v.data = &_tmp +// v.id = typeid_of(type_of(_tmp)) +// +// +// `any` is a topologically-dual to a `union` in terms of its usage. Both support assignments of differing types +// (`any` being open to any type, `union` being closed to a specific set of types), type assertions (`x.(T)`), and `switch in`. +// The main internal difference is how the memory is stored. `any` being open is a pointer+typeid, a `union` +// is a blob+tag. A `union` does not need to store a `typeid` because it is a closed ABI-consistent set of variant types. +package reflect \ No newline at end of file diff --git a/core/reflect/iterator.odin b/core/reflect/iterator.odin index 090fe04cc..d283f190f 100644 --- a/core/reflect/iterator.odin +++ b/core/reflect/iterator.odin @@ -2,6 +2,10 @@ package reflect import "base:runtime" +// An iterator to dynamically iterate across something that is array-like (or pointer-to-array-like) +// Example: +// it: int // used as a tracking value +// for elem, idx in iterate_array(any_array_val, &it) { ... } @(require_results) iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { if val == nil || it == nil { @@ -40,11 +44,24 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { index = it^ it^ += 1 } + case Type_Info_Fixed_Capacity_Dynamic_Array: + count := (^int)(uintptr(val.data) + info.len_offset)^ + if it^ < count { + elem.data = rawptr(uintptr(val.data) + uintptr(it^ * info.elem_size)) + elem.id = info.elem.id + ok = true + index = it^ + it^ += 1 + } } return } +// An iterator to dynamically iterate across map (or pointer-to-map) +// Example: +// it: int // used as a tracking value +// for key, val in iterate_map(any_map_val, &it) { ... } @(require_results) iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) { if val == nil || it == nil { diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index b3315a0c3..e7115fc96 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -6,33 +6,34 @@ _ :: intrinsics Type_Info :: runtime.Type_Info -Type_Info_Named :: runtime.Type_Info_Named -Type_Info_Integer :: runtime.Type_Info_Integer -Type_Info_Rune :: runtime.Type_Info_Rune -Type_Info_Float :: runtime.Type_Info_Float -Type_Info_Complex :: runtime.Type_Info_Complex -Type_Info_Quaternion :: runtime.Type_Info_Quaternion -Type_Info_String :: runtime.Type_Info_String -Type_Info_Boolean :: runtime.Type_Info_Boolean -Type_Info_Any :: runtime.Type_Info_Any -Type_Info_Type_Id :: runtime.Type_Info_Type_Id -Type_Info_Pointer :: runtime.Type_Info_Pointer -Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer -Type_Info_Procedure :: runtime.Type_Info_Procedure -Type_Info_Array :: runtime.Type_Info_Array -Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array -Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array -Type_Info_Slice :: runtime.Type_Info_Slice -Type_Info_Parameters :: runtime.Type_Info_Parameters -Type_Info_Struct :: runtime.Type_Info_Struct -Type_Info_Union :: runtime.Type_Info_Union -Type_Info_Enum :: runtime.Type_Info_Enum -Type_Info_Map :: runtime.Type_Info_Map -Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set -Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector -Type_Info_Matrix :: runtime.Type_Info_Matrix -Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer -Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field +Type_Info_Named :: runtime.Type_Info_Named +Type_Info_Integer :: runtime.Type_Info_Integer +Type_Info_Rune :: runtime.Type_Info_Rune +Type_Info_Float :: runtime.Type_Info_Float +Type_Info_Complex :: runtime.Type_Info_Complex +Type_Info_Quaternion :: runtime.Type_Info_Quaternion +Type_Info_String :: runtime.Type_Info_String +Type_Info_Boolean :: runtime.Type_Info_Boolean +Type_Info_Any :: runtime.Type_Info_Any +Type_Info_Type_Id :: runtime.Type_Info_Type_Id +Type_Info_Pointer :: runtime.Type_Info_Pointer +Type_Info_Multi_Pointer :: runtime.Type_Info_Multi_Pointer +Type_Info_Procedure :: runtime.Type_Info_Procedure +Type_Info_Array :: runtime.Type_Info_Array +Type_Info_Enumerated_Array :: runtime.Type_Info_Enumerated_Array +Type_Info_Dynamic_Array :: runtime.Type_Info_Dynamic_Array +Type_Info_Slice :: runtime.Type_Info_Slice +Type_Info_Parameters :: runtime.Type_Info_Parameters +Type_Info_Struct :: runtime.Type_Info_Struct +Type_Info_Union :: runtime.Type_Info_Union +Type_Info_Enum :: runtime.Type_Info_Enum +Type_Info_Map :: runtime.Type_Info_Map +Type_Info_Bit_Set :: runtime.Type_Info_Bit_Set +Type_Info_Simd_Vector :: runtime.Type_Info_Simd_Vector +Type_Info_Matrix :: runtime.Type_Info_Matrix +Type_Info_Soa_Pointer :: runtime.Type_Info_Soa_Pointer +Type_Info_Bit_Field :: runtime.Type_Info_Bit_Field +Type_Info_Fixed_Capacity_Dynamic_Array :: runtime.Type_Info_Fixed_Capacity_Dynamic_Array Type_Info_Enum_Value :: runtime.Type_Info_Enum_Value @@ -67,72 +68,95 @@ Type_Kind :: enum { Matrix, Soa_Pointer, Bit_Field, + Fixed_Capacity_Dynamic_Array, } +// type_kind returns a enum `Type_Kind` to state what kind of type a typeid is @(require_results) type_kind :: proc(T: typeid) -> Type_Kind { ti := type_info_of(T) if ti != nil { switch _ in ti.variant { - case Type_Info_Named: return .Named - case Type_Info_Integer: return .Integer - case Type_Info_Rune: return .Rune - case Type_Info_Float: return .Float - case Type_Info_Complex: return .Complex - case Type_Info_Quaternion: return .Quaternion - case Type_Info_String: return .String - case Type_Info_Boolean: return .Boolean - case Type_Info_Any: return .Any - case Type_Info_Type_Id: return .Type_Id - case Type_Info_Pointer: return .Pointer - case Type_Info_Multi_Pointer: return .Multi_Pointer - case Type_Info_Procedure: return .Procedure - case Type_Info_Array: return .Array - case Type_Info_Enumerated_Array: return .Enumerated_Array - case Type_Info_Dynamic_Array: return .Dynamic_Array - case Type_Info_Slice: return .Slice - case Type_Info_Parameters: return .Parameters - case Type_Info_Struct: return .Struct - case Type_Info_Union: return .Union - case Type_Info_Enum: return .Enum - case Type_Info_Map: return .Map - case Type_Info_Bit_Set: return .Bit_Set - case Type_Info_Simd_Vector: return .Simd_Vector - case Type_Info_Matrix: return .Matrix - case Type_Info_Soa_Pointer: return .Soa_Pointer - case Type_Info_Bit_Field: return .Bit_Field + case Type_Info_Named: return .Named + case Type_Info_Integer: return .Integer + case Type_Info_Rune: return .Rune + case Type_Info_Float: return .Float + case Type_Info_Complex: return .Complex + case Type_Info_Quaternion: return .Quaternion + case Type_Info_String: return .String + case Type_Info_Boolean: return .Boolean + case Type_Info_Any: return .Any + case Type_Info_Type_Id: return .Type_Id + case Type_Info_Pointer: return .Pointer + case Type_Info_Multi_Pointer: return .Multi_Pointer + case Type_Info_Procedure: return .Procedure + case Type_Info_Array: return .Array + case Type_Info_Enumerated_Array: return .Enumerated_Array + case Type_Info_Dynamic_Array: return .Dynamic_Array + case Type_Info_Slice: return .Slice + case Type_Info_Parameters: return .Parameters + case Type_Info_Struct: return .Struct + case Type_Info_Union: return .Union + case Type_Info_Enum: return .Enum + case Type_Info_Map: return .Map + case Type_Info_Bit_Set: return .Bit_Set + case Type_Info_Simd_Vector: return .Simd_Vector + case Type_Info_Matrix: return .Matrix + case Type_Info_Soa_Pointer: return .Soa_Pointer + case Type_Info_Bit_Field: return .Bit_Field + case Type_Info_Fixed_Capacity_Dynamic_Array: return .Fixed_Capacity_Dynamic_Array } } return .Invalid } -// TODO(bill): Better name +// Returns the `Type_Kind` of the base-type of a typeid. @(require_results) underlying_type_kind :: proc(T: typeid) -> Type_Kind { return type_kind(runtime.typeid_base(T)) } -// TODO(bill): Better name +// Returns the `Type_Kind` of the core-type of a typeid. See @(require_results) backing_type_kind :: proc(T: typeid) -> Type_Kind { return type_kind(runtime.typeid_core(T)) } +// type_info_base returns the base-type of a `^Type_Info` stripping the `distinct`ness from the first level type_info_base :: runtime.type_info_base + +// type_info_core returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR +// returns the backing integer type of an enum or bit_set `^Type_Info`. +// This is also aliased as `type_info_base_without_enum` type_info_core :: runtime.type_info_core + + +// type_info_base_without_enum returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR +// returns the backing integer type of an enum or bit_set `^Type_Info`. +// This is also aliased as `type_info_core` type_info_base_without_enum :: type_info_core when !ODIN_NO_RTTI { + // typeid_base returns the base-type of a `typeid` stripping the `distinct`ness from the first level typeid_base :: runtime.typeid_base + + // typeid_core returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR + // returns the backing integer type of an enum or bit_set `typeid`. + // This is also aliased as `typeid_base_without_enum` typeid_core :: runtime.typeid_core + + // typeid_base_without_enum returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR + // returns the backing integer type of an enum or bit_set `typeid`. + // This is also aliased as `typeid_core` typeid_base_without_enum :: typeid_core } +// any_base returns an `any` where the `typeid` has been replaced with the `base-type` equivalent @(require_results) any_base :: proc(v: any) -> any { v := v @@ -141,6 +165,8 @@ any_base :: proc(v: any) -> any { } return v } + +// any_core returns an `any` where the `typeid` has been replaced with the `core-type` equivalent @(require_results) any_core :: proc(v: any) -> any { v := v @@ -150,6 +176,20 @@ any_core :: proc(v: any) -> any { return v } +// typeid_elem returns a `typeid` of the element-type of a type if possible, otherwise it returns itself +// complex32 -> f16 +// complex64 -> f32 +// complex128 -> f64 +// quaternion64 -> f16 +// quaternion128 -> f32 +// quaternion256 -> f64 +// ^T -> T +// [^]T -> T +// #soa^T -> T +// [N]T -> T +// []T -> T +// [dynamic]T -> T +// #simd[N]T -> T @(require_results) typeid_elem :: proc(id: typeid) -> typeid { ti := type_info_of(id) @@ -160,11 +200,13 @@ typeid_elem :: proc(id: typeid) -> typeid { #partial switch v in ti.variant { case Type_Info_Complex: switch bits { + case 32: return f16 case 64: return f32 case 128: return f64 } case Type_Info_Quaternion: switch bits { + case 64: return f16 case 128: return f32 case 256: return f64 } @@ -176,11 +218,13 @@ typeid_elem :: proc(id: typeid) -> typeid { case Type_Info_Slice: return v.elem.id case Type_Info_Dynamic_Array: return v.elem.id case Type_Info_Simd_Vector: return v.elem.id + case Type_Info_Fixed_Capacity_Dynamic_Array: return v.elem.id } return id } +// returns the size of the type that the passed typeid represents @(require_results) size_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { @@ -189,6 +233,7 @@ size_of_typeid :: proc(T: typeid) -> int { return 0 } +// returns the alignment of the type that the passed typeid represents @(require_results) align_of_typeid :: proc(T: typeid) -> int { if ti := type_info_of(T); ti != nil { @@ -197,6 +242,7 @@ align_of_typeid :: proc(T: typeid) -> int { return 1 } +// Reinterprets the data stored at `v` as a slice of bytes @(require_results) as_bytes :: proc(v: any) -> []byte { if v != nil { @@ -206,11 +252,13 @@ as_bytes :: proc(v: any) -> []byte { return nil } +// Splits the data stored in `any` into its two components: `data` and `id` @(require_results) any_data :: #force_inline proc(v: any) -> (data: rawptr, id: typeid) { return v.data, v.id } +// Returns true if the `any` value is either `nil` or the data stored at the address is all zeroed @(require_results) is_nil :: proc(v: any) -> bool { if v == nil { @@ -228,6 +276,16 @@ is_nil :: proc(v: any) -> bool { return true } + +// Returns the length of the type that represents the `any` value, or returns 0 if not possible +// len(^T) -> len(T) +// len([N]T) -> N +// len(#simd[N]T) -> N +// len([]T) +// len([dynamic]T) +// len(map[K]V) +// len(string) or len(cstring) +// len(string16) or len(cstring16) @(require_results) length :: proc(val: any) -> int { if val == nil { return 0 } @@ -251,14 +309,26 @@ length :: proc(val: any) -> int { case Type_Info_Dynamic_Array: return (^runtime.Raw_Dynamic_Array)(val.data).len + case Type_Info_Fixed_Capacity_Dynamic_Array: + return (^int)(uintptr(val.data) + a.len_offset)^ + case Type_Info_Map: return runtime.map_len((^runtime.Raw_Map)(val.data)^) case Type_Info_String: - if a.is_cstring { - return len((^cstring)(val.data)^) - } else { - return (^runtime.Raw_String)(val.data).len + switch a.encoding { + case .UTF_8: + if a.is_cstring { + return len((^cstring)(val.data)^) + } else { + return (^runtime.Raw_String)(val.data).len + } + case .UTF_16: + if a.is_cstring { + return len((^cstring16)(val.data)^) + } else { + return (^runtime.Raw_String16)(val.data).len + } } case Type_Info_Simd_Vector: @@ -268,6 +338,12 @@ length :: proc(val: any) -> int { return 0 } +// Returns the capacity of the type that represents the `any` value, or returns 0 if not possible +// cap(^T) -> cap(T) +// cap([N]T) -> N +// cap(#simd[N]T) -> N +// cap([dynamic]T) +// cap(map[K]V) @(require_results) capacity :: proc(val: any) -> int { if val == nil { return 0 } @@ -288,6 +364,9 @@ capacity :: proc(val: any) -> int { case Type_Info_Dynamic_Array: return (^runtime.Raw_Dynamic_Array)(val.data).cap + case Type_Info_Fixed_Capacity_Dynamic_Array: + return a.capacity + case Type_Info_Map: return runtime.map_cap((^runtime.Raw_Map)(val.data)^) @@ -299,6 +378,7 @@ capacity :: proc(val: any) -> int { } +// Dynamically indexes `any` as an indexable-type if possible. Returns `nil` if not possible @(require_results) index :: proc(val: any, i: int, loc := #caller_location) -> any { if val == nil { return nil } @@ -347,18 +427,35 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { data := rawptr(uintptr(raw.data) + offset) return any{data, a.elem.id} + case Type_Info_Fixed_Capacity_Dynamic_Array: + count := (^int)(uintptr(val.data) + a.len_offset)^ + runtime.bounds_check_error_loc(loc, i, count) + offset := uintptr(a.elem.size * i) + data := rawptr(uintptr(val.data) + offset) + return any{data, a.elem.id} + case Type_Info_String: if a.is_cstring { return nil } - raw := (^runtime.Raw_String)(val.data) - runtime.bounds_check_error_loc(loc, i, raw.len) - offset := uintptr(size_of(u8) * i) - data := rawptr(uintptr(raw.data) + offset) - return any{data, typeid_of(u8)} + switch a.encoding { + case .UTF_8: + raw := (^runtime.Raw_String)(val.data) + runtime.bounds_check_error_loc(loc, i, raw.len) + offset := uintptr(size_of(u8) * i) + data := rawptr(uintptr(raw.data) + offset) + return any{data, typeid_of(u8)} + case .UTF_16: + raw := (^runtime.Raw_String16)(val.data) + runtime.bounds_check_error_loc(loc, i, raw.len) + offset := uintptr(size_of(u16) * i) + data := rawptr(uintptr(raw.data) + offset) + return any{data, typeid_of(u16)} + } } return nil } +// Dereferences `any` if it represents a pointer-based value (`^T -> T`) @(require_results) deref :: proc(val: any) -> any { if val != nil { @@ -375,20 +472,22 @@ deref :: proc(val: any) -> any { -// Struct_Tag represents the type of the string of a struct field +// `Struct_Tag` represents the type of the `string` of a struct field // -// Through convention, tags are the concatenation of optionally space separationed key:"value" pairs. +// Through convention, tags are the concatenation of optionally space-separated key:"value" pairs. // Each key is a non-empty string which contains no control characters other than space, quotes, and colon. Struct_Tag :: distinct string +// `Struct_Field` represents a information of a field of a struct Struct_Field :: struct { name: string, type: ^Type_Info, tag: Struct_Tag, - offset: uintptr, + offset: uintptr, // in bytes is_using: bool, } +// Returns a `Struct_Field` containing the information for a struct field of a typeid `T` at index `i` @(require_results) struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) @@ -404,6 +503,7 @@ struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { return } +// Returns a `Struct_Field` containing the information for a struct field by `name` of a typeid `T` @(require_results) struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) @@ -422,6 +522,10 @@ struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { return } +// Returns an `any` of a struct field specified by name +// Example: +// v := struct_field_value_by_name(the_struct, "field_name") +// nested_value_through_using := struct_field_value_by_name(the_struct, "field_name", allow_using=true) @(require_results) struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) -> any { if a == nil { return nil } @@ -452,6 +556,10 @@ struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) return nil } +// Returns an `any` of a struct field specified by a `Struct_Field` +// Example: +// field := struct_field_value_by_name(the_struct, "field_name") +// value_by_field := struct_field_value(the_struct, field) @(require_results) struct_field_value :: proc(a: any, field: Struct_Field) -> any { if a == nil { return nil } @@ -461,6 +569,7 @@ struct_field_value :: proc(a: any, field: Struct_Field) -> any { } } +// Returns a `[]string` of the names of the struct fields of type `T` @(require_results) struct_field_names :: proc(T: typeid) -> []string { ti := runtime.type_info_base(type_info_of(T)) @@ -470,6 +579,7 @@ struct_field_names :: proc(T: typeid) -> []string { return nil } +// Returns a `[]^Type_Info` of the types of the struct fields of type `T` @(require_results) struct_field_types :: proc(T: typeid) -> []^Type_Info { ti := runtime.type_info_base(type_info_of(T)) @@ -480,6 +590,7 @@ struct_field_types :: proc(T: typeid) -> []^Type_Info { } +// Returns a `[]Struct_Tag` of the tags of the struct fields of type `T` @(require_results) struct_field_tags :: proc(T: typeid) -> []Struct_Tag { ti := runtime.type_info_base(type_info_of(T)) @@ -489,6 +600,7 @@ struct_field_tags :: proc(T: typeid) -> []Struct_Tag { return nil } +// Returns a `[]uintptr` of the offsets in bytes of the struct fields of type `T` @(require_results) struct_field_offsets :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) @@ -498,6 +610,7 @@ struct_field_offsets :: proc(T: typeid) -> []uintptr { return nil } +// Struct_Field_Count_Method is the count method used by `struct_field_count` in order to find the number of fields Struct_Field_Count_Method :: enum { Top_Level, Using, @@ -556,6 +669,10 @@ struct_field_count :: proc(T: typeid, method := Struct_Field_Count_Method.Top_Le return } +// Returns the fields of a struct type `T` as an `#soa` slice. +// This is useful to iterate over. +// Example: +// for field, i in reflect.struct_fields_zipped(Foo) { ... } @(require_results) struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) @@ -572,13 +689,26 @@ struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { } - +// struct_tag_get returns the value associated with a key in the tag string. +// If the key is present in the tag, the value (which might be empty) is returned. Otherwise an empty string is returned. +// This is just a wrapper around `struct_tag_lookup` with the `ok` value being ignored. +// +// The convention for struct tags is usually of the form: +// +// `key:"value" another:"set" and:"whatever"` @(require_results) struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: string) { v, _ := struct_tag_lookup(tag, key) - return string(v) + return v } +// struct_tag_lookup returns the value associated with a key in the tag string. +// If the key is present in the tag, the value (which might be empty) is return. Otherwise an empty string is returned. +// The `ok` value returns whether the value was explicit set in the tag string. +// +// The convention for struct tags is usually of the form: +// +// `key:"value" another:"set" and:"whatever"` @(require_results) struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: bool) { for t := tag; t != ""; /**/ { @@ -638,6 +768,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: b } +// Returns the string representation of an enum value. It will panic if the value passed is not an enum. @(require_results) enum_string :: proc(a: any) -> string { if a == nil { return "" } @@ -656,7 +787,7 @@ enum_string :: proc(a: any) -> string { return "" } -// Given a enum type and a value name, get the enum value. +// Given an enum type and a value name, get the enum value. @(require_results) enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) { ti := type_info_base(type_info_of(Enum_Type)) @@ -674,6 +805,7 @@ enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, o return } +// enum_from_name_any returns the value of an enum field's name if found, returns `0, false` otherwise. @(require_results) enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info_Enum_Value, ok: bool) { ti := runtime.type_info_base(type_info_of(Enum_Type)) @@ -690,6 +822,7 @@ enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info return } +// enum_name_from_value returns the name of enum field if a valid name using parametric polymorphism, otherwise returns `"", false` @(require_results) enum_name_from_value :: proc(value: $Enum_Type) -> (name: string, ok: bool) where intrinsics.type_is_enum(Enum_Type) { ti := type_info_base(type_info_of(Enum_Type)) @@ -706,6 +839,7 @@ enum_name_from_value :: proc(value: $Enum_Type) -> (name: string, ok: bool) wher return } +// enum_name_from_value_any returns the name of enum field if a valid name using reflection, otherwise returns `"", false` @(require_results) enum_name_from_value_any :: proc(value: any) -> (name: string, ok: bool) { if value.id == nil { @@ -725,9 +859,7 @@ enum_name_from_value_any :: proc(value: any) -> (name: string, ok: bool) { return } -/* -Returns whether the value given has a defined name in the enum type. -*/ +// Returns whether the value given has a defined name in the enum type. @(require_results) enum_value_has_name :: proc(value: $T) -> bool where intrinsics.type_is_enum(T) { when len(T) == cap(T) { @@ -749,6 +881,7 @@ enum_value_has_name :: proc(value: $T) -> bool where intrinsics.type_is_enum(T) +// enum_field_names returns `[]string` of the names of the fields of type `Enum_Type` @(require_results) enum_field_names :: proc(Enum_Type: typeid) -> []string { ti := runtime.type_info_base(type_info_of(Enum_Type)) @@ -757,6 +890,7 @@ enum_field_names :: proc(Enum_Type: typeid) -> []string { } return nil } +// enum_field_values returns `[]Type_Info_Enum_Value` of the values of the fields of type `Enum_Type` @(require_results) enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value { ti := runtime.type_info_base(type_info_of(Enum_Type)) @@ -766,11 +900,16 @@ enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value { return nil } +// Represents an `Enum_Field` storing the `name` and `value` Enum_Field :: struct { name: string, value: Type_Info_Enum_Value, } +// Returns a #soa slice of the enum field information of type `Enum_Type` +// This is useful to iterate over. +// Example: +// for field, i in reflect.enum_fields_zipped(Foo) { ... } @(require_results) enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { ti := runtime.type_info_base(type_info_of(Enum_Type)) @@ -782,17 +921,20 @@ enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { +// Returns `^Type_Info` of a any-encoded union type. Panics if a union was not passed. @(require_results) union_variant_type_info :: proc(a: any) -> ^Type_Info { id := union_variant_typeid(a) return type_info_of(id) } +// Returns whether the `Type_Info_Union` store no tag (called a "pure maybe"). @(require_results) type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool { return len(info.variants) == 1 && is_pointer_internally(info.variants[0]) } +// UNSAFE: Returns `typeid` of a any-encoded union type. Panics if a union was not passed. @(require_results) union_variant_typeid :: proc(a: any) -> typeid { if a == nil { return nil } @@ -833,6 +975,7 @@ union_variant_typeid :: proc(a: any) -> typeid { panic("expected a union to reflect.union_variant_typeid") } +// UNSAFE: Returns the underlying tag value of a union. Panics if a union was not passed. @(require_results) get_union_variant_raw_tag :: proc(a: any) -> i64 { if a == nil { return -1 } @@ -864,6 +1007,7 @@ get_union_variant_raw_tag :: proc(a: any) -> i64 { panic("expected a union to reflect.get_union_variant_raw_tag") } +// Returns the underlying variant value of a union. Panics if a union was not passed. @(require_results) get_union_variant :: proc(a: any) -> any { if a == nil { @@ -876,6 +1020,14 @@ get_union_variant :: proc(a: any) -> any { return any{a.data, id} } +// Converts a pointer to a union, to a union containing the pointers to the variant types, and stores a pointer of the variant value in the new union +// +// Example: +// val: union{i32, f32, string} +// val = "123" +// ptr: union{^i32, ^f32, ^string} = get_union_as_ptr_variants(&val) +// sp := ptr.(^string) +// assert(sp^ == "123") @(require_results) get_union_as_ptr_variants :: proc(val: ^$T) -> (res: intrinsics.type_convert_variants_to_pointers(T)) where intrinsics.type_is_union(T) { ptr := rawptr(val) @@ -886,7 +1038,7 @@ get_union_as_ptr_variants :: proc(val: ^$T) -> (res: intrinsics.type_convert_var } - +// UNSAFE: Manually set the tag value of a union using an integer. Panics if a union was not passed. set_union_variant_raw_tag :: proc(a: any, tag: i64) { if a == nil { return } @@ -917,6 +1069,7 @@ set_union_variant_raw_tag :: proc(a: any, tag: i64) { panic("expected a union to reflect.set_union_variant_raw_tag") } +// UNSAFE: Manually set the tag value of a union using a `typeid`. Panics if a union was not passed. set_union_variant_typeid :: proc(a: any, id: typeid) { if a == nil { return } @@ -947,6 +1100,7 @@ set_union_variant_typeid :: proc(a: any, id: typeid) { panic("expected a union to reflect.set_union_variant_typeid") } +// UNSAFE: Manually set the tag value of a union using a `^Type_Info`. Panics if a union was not passed. set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { if a == nil { return } @@ -977,6 +1131,7 @@ set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { panic("expected a union to reflect.set_union_variant_type_info") } +// UNSAFE: Manually set the variant value of a union using an `any`. Panics if a union was not passed. set_union_value :: proc(dst: any, value: any) -> bool { if dst == nil { return false } @@ -1015,6 +1170,7 @@ set_union_value :: proc(dst: any, value: any) -> bool { panic("expected a union to reflect.set_union_variant_typeid") } +// UNSAFE: Checks to see if the data stored is a `bit_set` and is big endian. Panics if a `bit_set` was not passed. @(require_results) bit_set_is_big_endian :: proc(value: any, loc := #caller_location) -> bool { if value == nil { return ODIN_ENDIAN == .Big } @@ -1046,6 +1202,10 @@ Bit_Field :: struct { tag: Struct_Tag, } +// Returns the fields of a `bit_field` type `T` as an `#soa` slice. +// This is useful to iterate over. +// Example: +// for field, i in reflect.bit_fields_zipped(Foo_Bit_Field) { ... } @(require_results) bit_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Bit_Field) { ti := runtime.type_info_base(type_info_of(T)) @@ -1061,6 +1221,7 @@ bit_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Bit_Field) { return nil } +// bit_field_names returns a `[]string` of the field names of a `bit_field` type `T` @(require_results) bit_field_names :: proc(T: typeid) -> []string { ti := runtime.type_info_base(type_info_of(T)) @@ -1070,6 +1231,7 @@ bit_field_names :: proc(T: typeid) -> []string { return nil } +// bit_field_types returns a `[]^Type_Info` of the field representation types of a `bit_field` type `T`, not the backing integer-bit-width types @(require_results) bit_field_types :: proc(T: typeid) -> []^Type_Info { ti := runtime.type_info_base(type_info_of(T)) @@ -1079,6 +1241,7 @@ bit_field_types :: proc(T: typeid) -> []^Type_Info { return nil } +// bit_field_types returns a `[]uintptr` of the field bit-width-sizes of a `bit_field` type `T` @(require_results) bit_field_sizes :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) @@ -1088,6 +1251,7 @@ bit_field_sizes :: proc(T: typeid) -> []uintptr { return nil } +// bit_field_types returns a `[]uintptr` of the field offsets in bits of a `bit_field` type `T` @(require_results) bit_field_offsets :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) @@ -1097,6 +1261,7 @@ bit_field_offsets :: proc(T: typeid) -> []uintptr { return nil } +// bit_field_types returns a `[]Struct_Tag` of the field tags of a `bit_field` type `T` @(require_results) bit_field_tags :: proc(T: typeid) -> []Struct_Tag { ti := runtime.type_info_base(type_info_of(T)) @@ -1106,6 +1271,7 @@ bit_field_tags :: proc(T: typeid) -> []Struct_Tag { return nil } +// as_bool attempts to convert an `any` to a `bool`. @(require_results) as_bool :: proc(a: any) -> (value: bool, valid: bool) { if a == nil { return } @@ -1129,6 +1295,7 @@ as_bool :: proc(a: any) -> (value: bool, valid: bool) { return } +// as_int attempts to convert an `any` to a `int`. @(require_results) as_int :: proc(a: any) -> (value: int, valid: bool) { v: i64 @@ -1137,6 +1304,7 @@ as_int :: proc(a: any) -> (value: int, valid: bool) { return } +// as_uint attempts to convert an `any` to a `uint`. @(require_results) as_uint :: proc(a: any) -> (value: uint, valid: bool) { v: u64 @@ -1145,6 +1313,7 @@ as_uint :: proc(a: any) -> (value: uint, valid: bool) { return } +// as_i64 attempts to convert an `any` to a `i64`. @(require_results) as_i64 :: proc(a: any) -> (value: i64, valid: bool) { if a == nil { return } @@ -1253,6 +1422,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { return } +// as_u64 attempts to convert an `any` to a `u64`. @(require_results) as_u64 :: proc(a: any) -> (value: u64, valid: bool) { if a == nil { return } @@ -1363,6 +1533,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { } +// as_f64 attempts to convert an `any` to a `f64`. @(require_results) as_f64 :: proc(a: any) -> (value: f64, valid: bool) { if a == nil { return } @@ -1480,6 +1651,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { } +// as_string attempts to convert an `any` to a `string`. @(require_results) as_string :: proc(a: any) -> (value: string, valid: bool) { if a == nil { return } @@ -1500,6 +1672,27 @@ as_string :: proc(a: any) -> (value: string, valid: bool) { return } +// as_string16 attempts to convert an `any` to a `string16`. +@(require_results) +as_string16 :: proc(a: any) -> (value: string16, valid: bool) { + if a == nil { return } + a := a + ti := runtime.type_info_core(type_info_of(a.id)) + a.id = ti.id + + #partial switch info in ti.variant { + case Type_Info_String: + valid = true + switch v in a { + case string16: value = v + case cstring16: value = string16(v) + case: valid = false + } + } + + return +} + @(require_results) relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) -> rawptr { _handle :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) { @@ -1543,6 +1736,8 @@ relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) +// as_pointer attempts to convert an `any` to a `rawptr`. +// This only works for `^T`, `[^]T`, `cstring`, `cstring16` based types @(require_results) as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return } @@ -1551,14 +1746,15 @@ as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Pointer: + case Type_Info_Pointer, Type_Info_Multi_Pointer: valid = true value = (^rawptr)(a.data)^ case Type_Info_String: valid = true switch v in a { - case cstring: value = rawptr(v) + case cstring: value = rawptr(v) + case cstring16: value = rawptr(v) case: valid = false } } @@ -1567,6 +1763,7 @@ as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { } +// Returns the equivalent of doing `raw_data(v)` where `v` is a non-any value @(require_results) as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { if a == nil { return } @@ -1578,8 +1775,10 @@ as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { case Type_Info_String: valid = true switch v in a { - case string: value = raw_data(v) - case cstring: value = rawptr(v) // just in case + case string: value = raw_data(v) + case cstring: value = rawptr(v) // just in case + case string16: value = raw_data(v) + case cstring16: value = rawptr(v) // just in case case: valid = false } @@ -1591,6 +1790,10 @@ as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { valid = true value = (^runtime.Raw_Slice)(a.data).data + case Type_Info_Fixed_Capacity_Dynamic_Array: + valid = true + value = a.data + case Type_Info_Dynamic_Array: valid = true value = (^runtime.Raw_Dynamic_Array)(a.data).data @@ -1604,10 +1807,13 @@ ne :: not_equal DEFAULT_EQUAL_MAX_RECURSION_LEVEL :: 32 +// Checks to see if two `any` values are not semantically equivalent @(require_results) not_equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool { return !equal(a, b, including_indirect_array_recursion, recursion_level) } + +// Checks to see if two `any` values are semantically equivalent @(require_results) equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool { if a == nil && b == nil { @@ -1702,14 +1908,27 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_ return runtime.memory_compare(a.data, b.data, t.size) == 0 case Type_Info_String: - if v.is_cstring { - x := string((^cstring)(a.data)^) - y := string((^cstring)(b.data)^) - return x == y - } else { - x := (^string)(a.data)^ - y := (^string)(b.data)^ - return x == y + switch v.encoding { + case .UTF_8: + if v.is_cstring { + x := string((^cstring)(a.data)^) + y := string((^cstring)(b.data)^) + return x == y + } else { + x := (^string)(a.data)^ + y := (^string)(b.data)^ + return x == y + } + case .UTF_16: + if v.is_cstring { + x := string16((^cstring16)(a.data)^) + y := string16((^cstring16)(b.data)^) + return x == y + } else { + x := (^string16)(a.data)^ + y := (^string16)(b.data)^ + return x == y + } } return true case Type_Info_Array: @@ -1721,6 +1940,23 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_ } } return true + case Type_Info_Fixed_Capacity_Dynamic_Array: + a_count := (^int)(uintptr(a.data) + v.len_offset)^ + b_count := (^int)(uintptr(b.data) + v.len_offset)^ + if a_count != b_count { + return false + } + + for i in 0.. uintptr where intrinsics.type_is_comparable(T) { + assert(ptr != nil) + info := intrinsics.type_map_info(map[T]struct{}) + + h := u64(seed) + runtime.INITIAL_HASH_SEED + actual_seed := uintptr(h) | uintptr(uintptr(h) == 0) + + return info.key_hasher(ptr, actual_seed) } \ No newline at end of file diff --git a/core/reflect/types.odin b/core/reflect/types.odin index ba47fee4d..fa40c1d1b 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -3,6 +3,10 @@ package reflect import "core:io" import "core:strings" + +// Returns true when the `^Type_Info`s are semantically equivalent types +// Note: The pointers being identical should be enough to check but this is done to make sure in certain cases where it is non-trivial +// and each value wants to be checked directly. @(require_results) are_types_identical :: proc(a, b: ^Type_Info) -> bool { if a == b { @@ -28,36 +32,36 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { return x.signed == y.signed && x.endianness == y.endianness case Type_Info_Rune: - _, ok := b.variant.(Type_Info_Rune) - return ok + _ = b.variant.(Type_Info_Rune) or_return + return true case Type_Info_Float: - _, ok := b.variant.(Type_Info_Float) - return ok + y := b.variant.(Type_Info_Float) or_return + return x.endianness == y.endianness case Type_Info_Complex: - _, ok := b.variant.(Type_Info_Complex) - return ok + _ = b.variant.(Type_Info_Complex) or_return + return true case Type_Info_Quaternion: - _, ok := b.variant.(Type_Info_Quaternion) - return ok + _ = b.variant.(Type_Info_Quaternion) or_return + return true case Type_Info_Type_Id: - _, ok := b.variant.(Type_Info_Type_Id) - return ok + _ = b.variant.(Type_Info_Type_Id) or_return + return true case Type_Info_String: - _, ok := b.variant.(Type_Info_String) - return ok + y := b.variant.(Type_Info_String) or_return + return x.is_cstring == y.is_cstring && x.encoding == y.encoding case Type_Info_Boolean: - _, ok := b.variant.(Type_Info_Boolean) - return ok + _ = b.variant.(Type_Info_Boolean) or_return + return true case Type_Info_Any: - _, ok := b.variant.(Type_Info_Any) - return ok + _ = b.variant.(Type_Info_Any) or_return + return true case Type_Info_Pointer: y := b.variant.(Type_Info_Pointer) or_return @@ -74,22 +78,19 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { case Type_Info_Procedure: y := b.variant.(Type_Info_Procedure) or_return - switch { - case x.variadic != y.variadic, - x.convention != y.convention: - return false - } + (x.variadic == y.variadic) or_return + (x.convention == y.convention) or_return return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results) case Type_Info_Array: y := b.variant.(Type_Info_Array) or_return - if x.count != y.count { return false } + (x.count == y.count) or_return return are_types_identical(x.elem, y.elem) case Type_Info_Enumerated_Array: y := b.variant.(Type_Info_Enumerated_Array) or_return - if x.count != y.count { return false } + (x.count == y.count) or_return return are_types_identical(x.index, y.index) && are_types_identical(x.elem, y.elem) @@ -101,14 +102,17 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { y := b.variant.(Type_Info_Slice) or_return return are_types_identical(x.elem, y.elem) + case Type_Info_Fixed_Capacity_Dynamic_Array: + y := b.variant.(Type_Info_Fixed_Capacity_Dynamic_Array) or_return + (x.capacity == y.capacity) or_return + return are_types_identical(x.elem, y.elem) + case Type_Info_Parameters: y := b.variant.(Type_Info_Parameters) or_return - if len(x.types) != len(y.types) { return false } + (len(x.types) == len(y.types)) or_return for _, i in x.types { xt, yt := x.types[i], y.types[i] - if !are_types_identical(xt, yt) { - return false - } + are_types_identical(xt, yt) or_return } return true @@ -127,59 +131,64 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { xt, yt := x.types[i], y.types[i] xl, yl := x.tags[i], y.tags[i] - if xn != yn { return false } - if !are_types_identical(xt, yt) { return false } - if xl != yl { return false } + (xn == yn) or_return + are_types_identical(xt, yt) or_return + (xl == yl) or_return } return true case Type_Info_Union: - y := b.variant.(Type_Info_Union) or_return - if len(x.variants) != len(y.variants) { return false } + y := b.variant.(Type_Info_Union) or_return + (len(x.variants) == len(y.variants)) or_return for _, i in x.variants { xv, yv := x.variants[i], y.variants[i] - if !are_types_identical(xv, yv) { return false } + are_types_identical(xv, yv) or_return } return true case Type_Info_Enum: - // NOTE(bill): Should be handled above - return false + y := b.variant.(Type_Info_Enum) or_return + are_types_identical(x.base, y.base) or_return + (len(x.names) == len(y.names)) or_return + + for _, i in x.names { + (x.names[i] == y.names[i]) or_return + (x.values[i] == y.values[i]) or_return + } + return true case Type_Info_Map: y := b.variant.(Type_Info_Map) or_return return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value) case Type_Info_Bit_Set: - y := b.variant.(Type_Info_Bit_Set) or_return - return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper + y := b.variant.(Type_Info_Bit_Set) or_return + are_types_identical(x.underlying, y.underlying) or_return + are_types_identical(x.elem, y.elem) or_return + + return x.lower == y.lower && x.upper == y.upper case Type_Info_Simd_Vector: y := b.variant.(Type_Info_Simd_Vector) or_return return x.count == y.count && x.elem == y.elem case Type_Info_Matrix: - y := b.variant.(Type_Info_Matrix) or_return - if x.row_count != y.row_count { return false } - if x.column_count != y.column_count { return false } - if x.layout != y.layout { return false } + y := b.variant.(Type_Info_Matrix) or_return + (x.row_count == y.row_count) or_return + (x.column_count == y.column_count) or_return + (x.layout == y.layout) or_return return are_types_identical(x.elem, y.elem) case Type_Info_Bit_Field: - y := b.variant.(Type_Info_Bit_Field) or_return - if !are_types_identical(x.backing_type, y.backing_type) { return false } - if x.field_count != y.field_count { return false } + y := b.variant.(Type_Info_Bit_Field) or_return + are_types_identical(x.backing_type, y.backing_type) or_return + (x.field_count == y.field_count) or_return + for _, i in x.names[:x.field_count] { - if x.names[i] != y.names[i] { - return false - } - if !are_types_identical(x.types[i], y.types[i]) { - return false - } - if x.bit_sizes[i] != y.bit_sizes[i] { - return false - } + (x.names[i] == y.names[i]) or_return + are_types_identical(x.types[i], y.types[i]) or_return + (x.bit_sizes[i] == y.bit_sizes[i]) or_return } return true } @@ -187,6 +196,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { return false } +// Returns true if the base-type is a signed integer or just a float, false otherwise. @(require_results) is_signed :: proc(info: ^Type_Info) -> bool { if info == nil { return false } @@ -196,6 +206,7 @@ is_signed :: proc(info: ^Type_Info) -> bool { } return false } +// Returns true if the base-type is an usigned integer, false otherwise. @(require_results) is_unsigned :: proc(info: ^Type_Info) -> bool { if info == nil { return false } @@ -206,6 +217,7 @@ is_unsigned :: proc(info: ^Type_Info) -> bool { return false } +// Returns true when it is a 1-byte wide integer type, false otherwise. @(require_results) is_byte :: proc(info: ^Type_Info) -> bool { if info == nil { return false } @@ -216,83 +228,114 @@ is_byte :: proc(info: ^Type_Info) -> bool { } +// Returns true the base-type is an integer of any kind, false otherwise. @(require_results) is_integer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Integer) return ok } +// Returns true the base-type is a rune, false otherwise. @(require_results) is_rune :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Rune) return ok } +// Returns true the base-type is a float of any kind, false otherwise. @(require_results) is_float :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Float) return ok } +// Returns true the base-type is a complex-type of any kind, false otherwise. @(require_results) is_complex :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Complex) return ok } +// Returns true the base-type is a quaternions any kind, false otherwise. @(require_results) is_quaternion :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Quaternion) return ok } +// Returns true the base-type is an `any`, false otherwise. @(require_results) is_any :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Any) return ok } + +// Returns true the base-type is a string of any kind (string, cstring, string16, cstring16), false otherwise. @(require_results) is_string :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_String) return ok } +// Returns true the base-type is a cstring of any kind (cstring, cstring16), false otherwise. @(require_results) is_cstring :: proc(info: ^Type_Info) -> bool { if info == nil { return false } v, ok := type_info_base(info).variant.(Type_Info_String) return ok && v.is_cstring } + +// Returns true the base-type is a string of any kind (string16, cstring16), false otherwise. +@(require_results) +is_string16 :: proc(info: ^Type_Info) -> bool { + if info == nil { return false } + v, ok := type_info_base(info).variant.(Type_Info_String) + return ok && v.encoding == .UTF_16 +} +// Returns true the base-type is a cstring of any kind (cstring16), false otherwise. +@(require_results) +is_cstring16 :: proc(info: ^Type_Info) -> bool { + if info == nil { return false } + v, ok := type_info_base(info).variant.(Type_Info_String) + return ok && v.is_cstring && v.encoding == .UTF_16 +} + +// Returns true the base-type is a boolean of any kind, false otherwise. @(require_results) is_boolean :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Boolean) return ok } +// Returns true the base-type is a pointer-type of any kind (^T or rawptr), false otherwise. @(require_results) is_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Pointer) return ok } +// Returns true the base-type is a pointer-type of any kind ([^]T), false otherwise. @(require_results) is_multi_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer) return ok } +// Returns true the base-type is a pointer-type of any kind (#soa^T), false otherwise. @(require_results) is_soa_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Soa_Pointer) return ok } +// Returns true when the type is a pointer-like type, false otherwise. @(require_results) is_pointer_internally :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - #partial switch v in info.variant { - case Type_Info_Pointer, Type_Info_Multi_Pointer, + #partial switch v in type_info_base(info).variant { + case Type_Info_Pointer, + Type_Info_Multi_Pointer, Type_Info_Procedure: return true case Type_Info_String: @@ -300,86 +343,109 @@ is_pointer_internally :: proc(info: ^Type_Info) -> bool { } return false } +// Returns true when the type is a procedure type, false otherwise. @(require_results) is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Procedure) return ok } +// Returns true when the type is a fixed-array type ([N]T), false otherwise. @(require_results) is_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Array) return ok } +// Returns true when the type is an enumerated-array type ([Enum]T), false otherwise. @(require_results) is_enumerated_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array) return ok } +// Returns true when the type is a dynamic-array type ([dynamic]T), false otherwise. @(require_results) is_dynamic_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array) return ok } +// Returns true when the type is a map type (map[K]V), false otherwise. @(require_results) is_dynamic_map :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Map) return ok } +// Returns true when the type is a bit_set type, false otherwise. @(require_results) is_bit_set :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Bit_Set) return ok } +// Returns true when the type is a slice type ([]T), false otherwise. @(require_results) is_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Slice) return ok } +// Returns true when the type represents a set of parameters for a procedure (inputs or outputs), false otherwise. @(require_results) is_parameters :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Parameters) return ok } +// Returns true when the type is a struct type, `#raw_union` will be false. All other types will be false otherwise. @(require_results) is_struct :: proc(info: ^Type_Info) -> bool { if info == nil { return false } s, ok := type_info_base(info).variant.(Type_Info_Struct) return ok && .raw_union not_in s.flags } +// Returns true when the type is a struct type with `#raw_union` applied, when `#raw_union` is not applied, the value will be false. All other types will be false otherwise. @(require_results) is_raw_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } s, ok := type_info_base(info).variant.(Type_Info_Struct) return ok && .raw_union in s.flags } +// Returns true when the type is a union type (not `#raw_union`), false otherwise. @(require_results) is_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Union) return ok } +// Returns true when the type is an enum type, false otherwise. @(require_results) is_enum :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Enum) return ok } +// Returns true when the type is a #simd-array type (#simd[N]T), false otherwise. @(require_results) is_simd_vector :: proc(info: ^Type_Info) -> bool { if info == nil { return false } _, ok := type_info_base(info).variant.(Type_Info_Simd_Vector) return ok } +// Returns true when the type is a fixed-capacity dynamic-array type ([dynamic; N]T), false otherwise. +@(require_results) +is_fixed_capacity_dynamic_array :: proc(info: ^Type_Info) -> bool { + if info == nil { return false } + _, ok := type_info_base(info).variant.(Type_Info_Fixed_Capacity_Dynamic_Array) + return ok +} +// Returns true when the core-type is represented with a platform-native endian type, and returns false otherwise. +// This will also return false when the type is not an integer, pointer, or bit_set. +// If the type is the same as the platform-native endian type (e.g. `u32le` on a little-endian system), this will return false. @(require_results) is_endian_platform :: proc(info: ^Type_Info) -> bool { if info == nil { return false} @@ -388,17 +454,19 @@ is_endian_platform :: proc(info: ^Type_Info) -> bool { #partial switch v in info.variant { case Type_Info_Integer: return v.endianness == .Platform + case Type_Info_Float: + return v.endianness == .Platform case Type_Info_Bit_Set: - if v.underlying != nil { - return is_endian_platform(v.underlying) - } - return true + return is_endian_platform(v.underlying) case Type_Info_Pointer: return true } return false } +// Returns true when the core-type is represented with a platform-native endian type or the same endianness as the system. +// This will also return false when the type is not an integer, pointer, or bit_set. +// If the type is the same as the platform-native endian type (e.g. `u32le` on a little-endian system), this will return true. @(require_results) is_endian_little :: proc(info: ^Type_Info) -> bool { if info == nil { return false} @@ -410,17 +478,22 @@ is_endian_little :: proc(info: ^Type_Info) -> bool { return ODIN_ENDIAN == .Little } return v.endianness == .Little - case Type_Info_Bit_Set: - if v.underlying != nil { - return is_endian_platform(v.underlying) + case Type_Info_Float: + if v.endianness == .Platform { + return ODIN_ENDIAN == .Little } - return ODIN_ENDIAN == .Little + return v.endianness == .Little + case Type_Info_Bit_Set: + return is_endian_little(v.underlying) case Type_Info_Pointer: return ODIN_ENDIAN == .Little } return ODIN_ENDIAN == .Little } +// Returns true when the core-type is represented with a platform-native endian type or the same endianness as the system. +// This will also return false when the type is not an integer, pointer, or bit_set. +// If the type is the same as the platform-native endian type (e.g. `u32be` on a big-endian system), this will return true. @(require_results) is_endian_big :: proc(info: ^Type_Info) -> bool { if info == nil { return false} @@ -432,11 +505,13 @@ is_endian_big :: proc(info: ^Type_Info) -> bool { return ODIN_ENDIAN == .Big } return v.endianness == .Big - case Type_Info_Bit_Set: - if v.underlying != nil { - return is_endian_platform(v.underlying) + case Type_Info_Float: + if v.endianness == .Platform { + return ODIN_ENDIAN == .Big } - return ODIN_ENDIAN == .Big + return v.endianness == .Big + case Type_Info_Bit_Set: + return is_endian_big(v.underlying) case Type_Info_Pointer: return ODIN_ENDIAN == .Big } @@ -446,27 +521,33 @@ is_endian_big :: proc(info: ^Type_Info) -> bool { +// Writes a typeid in standard (non-canonical) form to a `strings.Builder` write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) { return write_type_writer(strings.to_writer(buf), type_info_of(id)) } +// Writes a typeid in standard (non-canonical) form to an `io.Writer` write_typeid_writer :: proc(writer: io.Writer, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) { return write_type_writer(writer, type_info_of(id), n_written) } +// Writes a typeid in standard (non-canonical) form write_typeid :: proc{ write_typeid_builder, write_typeid_writer, } +// Writes a `^Type_Info` in standard (non-canonical) form write_type :: proc{ write_type_builder, write_type_writer, } +// Writes a `^Type_Info` in standard (non-canonical) form to a `strings.Builder` write_type_builder :: proc(buf: ^strings.Builder, ti: ^Type_Info) -> int { n, _ := write_type_writer(strings.to_writer(buf), ti) return n } +// Writes a `^Type_Info` in standard (non-canonical) form to an `io.Writer` write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -> (n: int, err: io.Error) { defer if n_written != nil { n_written^ += n @@ -511,9 +592,12 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_i64(w, i64(8*ti.size), 10, &n) or_return case Type_Info_String: if info.is_cstring { - io.write_string(w, "cstring", &n) or_return - } else { - io.write_string(w, "string", &n) or_return + io.write_byte(w, 'c', &n) or_return + } + io.write_string(w, "string", &n) or_return + switch info.encoding { + case .UTF_8: /**/ + case .UTF_16: io.write_string(w, "16", &n) or_return } case Type_Info_Boolean: switch ti.id { @@ -602,6 +686,12 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_string(w, "[]", &n) or_return write_type(w, info.elem, &n) or_return + case Type_Info_Fixed_Capacity_Dynamic_Array: + io.write_string(w, "[dynamic; ", &n) or_return + io.write_i64(w, i64(info.capacity), 10, &n) or_return + io.write_string(w, "]", &n) or_return + write_type(w, info.elem, &n) or_return + case Type_Info_Map: io.write_string(w, "map[", &n) or_return write_type(w, info.key, &n) or_return @@ -628,9 +718,10 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_string(w, "struct ", &n) or_return - if .packed in info.flags { io.write_string(w, "#packed ", &n) or_return } - if .raw_union in info.flags { io.write_string(w, "#raw_union ", &n) or_return } - if .no_copy in info.flags { io.write_string(w, "#no_copy ", &n) or_return } + if .packed in info.flags { io.write_string(w, "#packed ", &n) or_return } + if .raw_union in info.flags { io.write_string(w, "#raw_union ", &n) or_return } + if .all_or_none in info.flags { io.write_string(w, "#all_or_none ", &n) or_return } + if .simple in info.flags { io.write_string(w, "#simple ", &n) or_return } if .align in info.flags { io.write_string(w, "#align(", &n) or_return io.write_i64(w, i64(ti.align), 10, &n) or_return @@ -685,7 +776,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_string(w, "..=", &n) or_return io.write_i64(w, info.upper, 10, &n) or_return } - if info.underlying != nil { + if info.explicit_underlying { io.write_string(w, "; ", &n) or_return write_type(w, info.underlying, &n) or_return } @@ -726,3 +817,72 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt return } + +// The `^Type_Info` type refers to absolutely no internal pointers, meaning it can be trivially copied +has_no_indirections :: proc(ti: ^Type_Info) -> bool { + if ti == nil { + return true + } + + #partial switch &info in ti.variant { + case Type_Info_Named: + return has_no_indirections(info.base) + + case Type_Info_Integer, + Type_Info_Rune, + Type_Info_Boolean, + Type_Info_Float, + Type_Info_Complex, + Type_Info_Quaternion, + Type_Info_Type_Id: + return true + case Type_Info_String, + Type_Info_Any: + return false + + case Type_Info_Enum: + return has_no_indirections(info.base) + + case Type_Info_Pointer, + Type_Info_Multi_Pointer, + Type_Info_Soa_Pointer, + Type_Info_Procedure, + Type_Info_Slice, + Type_Info_Dynamic_Array, + Type_Info_Map: + return false + + case Type_Info_Parameters: + // If you have gotten here, it's a procedure + return false + + case Type_Info_Array: + return has_no_indirections(info.elem) + case Type_Info_Enumerated_Array: + return has_no_indirections(info.elem) + case Type_Info_Fixed_Capacity_Dynamic_Array: + return has_no_indirections(info.elem) + + case Type_Info_Simd_Vector: + return true + case Type_Info_Matrix: + return true + case Type_Info_Bit_Set: + return true + case Type_Info_Bit_Field: + return true + + case Type_Info_Struct: + for i in 0.. uint8x16_t { + return _vaeseq_u8(data, key) +} + +@(require_results, enable_target_feature = "aes") +vaesdq_u8 :: #force_inline proc "c" (data, key: uint8x16_t) -> uint8x16_t { + return _vaesdq_u8(data, key) +} + +@(require_results, enable_target_feature = "aes") +vaesmcq_u8 :: #force_inline proc "c" (data: uint8x16_t) -> uint8x16_t { + return _vaesmcq_u8(data) +} + +@(require_results,enable_target_feature = "aes") +vaesimcq_u8 :: #force_inline proc "c" (data: uint8x16_t) -> uint8x16_t { + return _vaesimcq_u8(data) +} + +@(private, default_calling_convention = "none") +foreign _ { + @(link_name = "llvm.aarch64.crypto.aese" when ODIN_ARCH == .arm64 else "llvm.arm.neon.aese") + _vaeseq_u8 :: proc(data, key: uint8x16_t) -> uint8x16_t --- + @(link_name = "llvm.aarch64.crypto.aesd" when ODIN_ARCH == .arm64 else "llvm.arm.neon.aesd") + _vaesdq_u8 :: proc(data, key: uint8x16_t) -> uint8x16_t --- + @(link_name = "llvm.aarch64.crypto.aesmc" when ODIN_ARCH == .arm64 else "llvm.arm.neon.aesmc") + _vaesmcq_u8 :: proc(data: uint8x16_t) -> uint8x16_t --- + @(link_name = "llvm.aarch64.crypto.aesimc" when ODIN_ARCH == .arm64 else "llvm.arm.neon.aesimc") + _vaesimcq_u8 :: proc(data: uint8x16_t) -> uint8x16_t --- +} diff --git a/core/simd/arm/doc.odin b/core/simd/arm/doc.odin new file mode 100644 index 000000000..ecedc7bac --- /dev/null +++ b/core/simd/arm/doc.odin @@ -0,0 +1,2 @@ +// `SIMD` intrinsics specific to ARMv8 `arm32` and `arm64` architectures. +package simd_arm \ No newline at end of file diff --git a/core/simd/arm/sha.odin b/core/simd/arm/sha.odin new file mode 100644 index 000000000..ca87c9795 --- /dev/null +++ b/core/simd/arm/sha.odin @@ -0,0 +1,108 @@ +#+build arm64,arm32 +package simd_arm + +@(require_results, enable_target_feature = "sha2") +vsha1cq_u32 :: #force_inline proc "c" (hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t { + return _vsha1cq_u32(hash_abcd, e, wk) +} + +@(require_results, enable_target_feature = "sha2") +vsha1pq_u32 :: #force_inline proc "c" (hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t { + return _vsha1pq_u32(hash_abcd, e, wk) +} + +@(require_results, enable_target_feature = "sha2") +vsha1mq_u32 :: #force_inline proc "c" (hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t { + return _vsha1mq_u32(hash_abcd, e, wk) +} + +@(require_results, enable_target_feature = "sha2") +vsha1h_u32 :: #force_inline proc "c" (e: uint32_t) -> uint32_t { + return _vsha1h_u32(e) +} + +@(require_results, enable_target_feature = "sha2") +vsha1su0q_u32 :: #force_inline proc "c" (w0_3, w4_7, w8_11: uint32x4_t) -> uint32x4_t { + return _vsha1su0q_u32(w0_3, w4_7, w8_11) +} + +@(require_results, enable_target_feature = "sha2") +vsha1su1q_u32 :: #force_inline proc "c" (tw0_3, w12_15: uint32x4_t) -> uint32x4_t { + return _vsha1su1q_u32(tw0_3, w12_15) +} + +@(require_results, enable_target_feature = "sha2") +vsha256hq_u32 :: #force_inline proc "c" (hash_abcd, hash_efgh, wk: uint32x4_t) -> uint32x4_t { + return _vsha256hq_u32(hash_abcd, hash_efgh, wk) +} + +@(require_results, enable_target_feature = "sha2") +vsha256h2q_u32 :: #force_inline proc "c" (hash_efgh, hash_abcd, wk: uint32x4_t) -> uint32x4_t { + return _vsha256h2q_u32(hash_efgh, hash_abcd, wk) +} + +@(require_results, enable_target_feature = "sha2") +vsha256su0q_u32 :: #force_inline proc "c" (w0_3, w4_7: uint32x4_t) -> uint32x4_t { + return _vsha256su0q_u32(w0_3, w4_7) +} + +@(require_results, enable_target_feature = "sha2") +vsha256su1q_u32 :: #force_inline proc "c" (tw0_3, w8_11, w12_15: uint32x4_t) -> uint32x4_t { + return _vsha256su1q_u32(tw0_3, w8_11, w12_15) +} + +// Note: The SHA512 instructions are part of the `sha3` feature set. + +@(require_results, enable_target_feature = "sha3") +vsha512hq_u64 :: #force_inline proc "c" (hash_ed, hash_gf, kwh_kwh2: uint64x2_t) -> uint64x2_t { + return _vsha512hq_u64(hash_ed, hash_gf, kwh_kwh2) +} + +@(require_results, enable_target_feature = "sha3") +vsha512h2q_u64 :: #force_inline proc "c" (sum_ab, hash_c_, hash_ab: uint64x2_t) -> uint64x2_t { + return _vsha512h2q_u64(sum_ab, hash_c_, hash_ab) +} + +@(require_results, enable_target_feature = "sha3") +vsha512su0q_u64 :: #force_inline proc "c" (w0_1, w2_: uint64x2_t) -> uint64x2_t { + return _vsha512su0q_u64(w0_1, w2_) +} + +@(require_results, enable_target_feature = "sha3") +vsha512su1q_u64 :: #force_inline proc "c" (s01_s02, w14_15, w9_10: uint64x2_t) -> uint64x2_t { + return _vsha512su1q_u64(s01_s02, w14_15, w9_10) +} + +@(private, default_calling_convention = "none") +foreign _ { + @(link_name = "llvm.aarch64.crypto.sha1c" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1c") + _vsha1cq_u32 :: proc(hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha1p" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1p") + _vsha1pq_u32 :: proc(hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha1m" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1m") + _vsha1mq_u32 :: proc(hash_abcd: uint32x4_t, e: uint32_t, wk: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha1h" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1h") + _vsha1h_u32 :: proc(e: uint32_t) -> uint32_t --- + @(link_name = "llvm.aarch64.crypto.sha1su0" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1su0") + _vsha1su0q_u32 :: proc(w0_3, w4_7, w8_11: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha1su1" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha1su1") + _vsha1su1q_u32 :: proc(tw0_3, w12_15: uint32x4_t) -> uint32x4_t --- + + @(link_name = "llvm.aarch64.crypto.sha256h" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha256h") + _vsha256hq_u32 :: proc(hash_abcd, hash_efgh, wk: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha256h2" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha256h2") + _vsha256h2q_u32 :: proc(hash_efgh, hash_abcd, wk: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha256su0" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha256su0") + _vsha256su0q_u32 :: proc(w0_3, w4_7: uint32x4_t) -> uint32x4_t --- + @(link_name = "llvm.aarch64.crypto.sha256su1" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha256su1") + _vsha256su1q_u32 :: proc(tw0_3, w8_11, w12_15: uint32x4_t) -> uint32x4_t --- + + @(link_name = "llvm.aarch64.crypto.sha512h" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha512h") + _vsha512hq_u64 :: proc(hash_ed, hash_gf, kwh_kwh2: uint64x2_t) -> uint64x2_t --- + @(link_name = "llvm.aarch64.crypto.sha512h2" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha512h2") + _vsha512h2q_u64 :: proc(sum_ab, hash_c_, hash_ab: uint64x2_t) -> uint64x2_t --- + @(link_name = "llvm.aarch64.crypto.sha512su0" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha512su0") + _vsha512su0q_u64 :: proc(w0_1, w2_: uint64x2_t) -> uint64x2_t --- + @(link_name = "llvm.aarch64.crypto.sha512su1" when ODIN_ARCH == .arm64 else "llvm.arm.neon.sha512su1") + _vsha512su1q_u64 :: proc(s01_s02, w14_15, w9_10: uint64x2_t) -> uint64x2_t --- +} diff --git a/core/simd/arm/types.odin b/core/simd/arm/types.odin new file mode 100644 index 000000000..05e3540b6 --- /dev/null +++ b/core/simd/arm/types.odin @@ -0,0 +1,9 @@ +#+build arm64,arm32 +package simd_arm + +// Type aliases to match `arm_neon.h`. +uint32_t :: u32 + +uint8x16_t :: #simd[16]u8 +uint32x4_t :: #simd[4]u32 +uint64x2_t :: #simd[2]u64 diff --git a/core/simd/simd.odin b/core/simd/simd.odin index a97155f58..1631c4d23 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -1,5 +1,5 @@ /* -The SIMD support package. +Cross-platform `SIMD` support types and procedures. SIMD (Single Instruction Multiple Data), is a CPU hardware feature that introduce special registers and instructions which operate on multiple units @@ -21,20 +21,17 @@ package simd import "base:builtin" import "base:intrinsics" +import "base:runtime" /* Check if SIMD is software-emulated on a target platform. -This value is `false`, when the compile-time target has the hardware support for -at 128-bit (or wider) SIMD. If the compile-time target lacks the hardware support -for 128-bit SIMD, this value is `true`, and all SIMD operations will likely be +This value is `true`, when the compile-time target has the hardware support for +at least 128-bit (or wider) SIMD. If the compile-time target lacks the hardware support +for 128-bit SIMD, this value is `false`, and all SIMD operations will likely be emulated. */ -IS_EMULATED :: true when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else - true when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else - true when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else - true when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else - false +HAS_HARDWARE_SIMD :: runtime.HAS_HARDWARE_SIMD /* Vector of 16 `u8` lanes (128 bits). @@ -274,7 +271,7 @@ Inputs: Returns: - A vector that is the sum of two input vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] + b[i] @@ -310,7 +307,7 @@ Inputs: Returns: - A vector that is the difference of two vectors, `a` - `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] - b[i] @@ -345,7 +342,7 @@ Inputs: Returns: - A vector that is the product of two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] * b[i] @@ -383,7 +380,7 @@ Inputs: Returns: - A vector that is the quotient of two vectors, `a` / `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] / b[i] @@ -423,7 +420,7 @@ Result: - A vector, where each lane is the lane from `a` shifted left by the amount specified in the corresponding lane of the vector `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { if b[i] < 8*size_of(a[i]) { @@ -473,7 +470,7 @@ Result: - A vector, where each lane is the lane from `a` shifted right by the amount specified in the corresponding lane of the vector `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { if b[i] < 8*size_of(a[i]) { @@ -496,7 +493,7 @@ Example: +-------+-------+-------+-------+ res: +-------+-------+-------+--------+ - | 0x04 | 0x2a | 0 | 0xff | + | 0x04 | 0x2a | 0 | 0x7f | +-------+-------+-------+--------+ */ shr :: intrinsics.simd_shr @@ -518,7 +515,7 @@ Result: - A vector, where each lane is the lane from `a` shifted left by the amount specified in the corresponding lane of the vector `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { mask := 8*size_of(a[i]) - 1 @@ -564,7 +561,7 @@ Result: - A vector, where each lane is the lane from `a` shifted right by the amount specified in the corresponding lane of the vector `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { mask := 8*size_of(a[i]) - 1 @@ -584,7 +581,7 @@ Example: +-------+-------+-------+-------+ res: +-------+-------+-------+--------+ - | 0x04 | 0x2a | 0x01 | 0xff | + | 0x04 | 0x2a | 0x01 | 0x7f | +-------+-------+-------+--------+ */ shr_masked :: intrinsics.simd_shr_masked @@ -607,7 +604,7 @@ Inputs: Returns: - The saturated sum of the two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { switch { @@ -656,7 +653,7 @@ Inputs: Returns: - The saturated difference of the two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { switch { @@ -700,7 +697,7 @@ Inputs: Returns: - A vector that is the result of the bitwise AND operation between two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] & b[i] @@ -735,7 +732,7 @@ Inputs: Returns: - A vector that is the result of the bitwise OR operation between two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] | b[i] @@ -770,7 +767,7 @@ Inputs: Returns: - A vector that is the result of the bitwise XOR operation between two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] ~ b[i] @@ -805,7 +802,7 @@ Inputs: Returns: - A vector that is the result of the bitwise AND NOT operation between two vectors. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = a[i] &~ b[i] @@ -839,7 +836,7 @@ Inputs: Returns: - The negated version of the vector `a`. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = -a[i] @@ -870,7 +867,7 @@ Inputs: Returns: - The absolute value of a vector. -**Operation**: +Operation: for i in 0 ..< len(res) { switch { @@ -906,7 +903,7 @@ Inputs: Returns: - A vector containing with minimum values from corresponding lanes of `a` and `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] < b[i] { @@ -945,7 +942,7 @@ Inputs: Returns: - A vector containing with maximum values from corresponding lanes of `a` and `b`. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] > b[i] { @@ -986,7 +983,7 @@ Inputs: Returns: - A vector containing clamped values in each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { val := v[i] @@ -1032,7 +1029,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] == b[i] { @@ -1074,7 +1071,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] != b[i] { @@ -1116,7 +1113,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] < b[i] { @@ -1159,7 +1156,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] <= b[i] { @@ -1202,7 +1199,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] > b[i] { @@ -1245,7 +1242,7 @@ Returns: - A vector of unsigned integers of the same size as the input vector's lanes, containing the comparison results for each lane. -**Operation**: +Operation: for i in 0 ..< len(res) { if a[i] >= b[i] { @@ -1304,7 +1301,7 @@ Returns: loaded from the pointer vector `ptr`, and all values from masked indices loaded from the value vector `val`. -**Operation**: +Operation: for i in 0 ..< len(res) { if mask[i]&1 == 1 { @@ -1387,7 +1384,7 @@ Inputs: set), the corresponding lane is written into memory. Otherwise it's not written into memory. -**Operation**: +Operation: for i in 0 ..< len(ptr) { if mask[i]&1 == 1 { @@ -1460,7 +1457,7 @@ Returns: - The loaded vector. The lanes for which the mask was set are loaded from memory, and the other lanes are loaded from the `val` vector. -**Operation**: +Operation: for i in 0 ..< len(res) { if mask[i]&1 == 1 { @@ -1528,7 +1525,7 @@ Inputs: - `val`: The vector to store. - `mask`: The mask, selecting which lanes of the vector to store into memory. -**Operation**: +Operation: for i in 0 ..< len(val) { if mask[i]&1 == 1 { @@ -1597,7 +1594,7 @@ Inputs: Returns: - The result vector, holding masked memory values unmasked default values. -**Operation**: +Operation: mem_idx := 0 for i in 0 ..< len(mask) { @@ -1670,7 +1667,7 @@ Inputs: - `val`: The vector to store into memory. - `mask`: The mask that selects which values to store into memory. -**Operation**: +Operation: mem_idx := 0 for i in 0 ..< len(mask) { @@ -1732,7 +1729,7 @@ Inputs: Returns: - The value of the lane at the specified index. -**Operation**: +Operation: return a[idx] */ @@ -1752,7 +1749,7 @@ Inputs: Returns: - Vector with the specified lane replaced. -**Operation**: +Operation: a[idx] = elem */ @@ -1778,7 +1775,7 @@ Inputs: Result: - Sum of all lanes, as a scalar. -**Operation**: +Operation: for n > 1 { n = n / 2 @@ -1826,7 +1823,7 @@ Inputs: Result: - Product of all lanes, as a scalar. -**Operation**: +Operation: for n > 1 { n = n / 2 @@ -1868,7 +1865,7 @@ Inputs: Result: - Sum of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -1891,7 +1888,7 @@ Inputs: Result: - Product of all lanes, as a scalar. -**Operation**: +Operation: res := 1 for i in 0 ..< len(a) { @@ -1919,7 +1916,7 @@ Inputs: Result: - Sum of all lanes, as a scalar. -**Operation**: +Operation: for n > 1 { n = n / 2 @@ -1967,7 +1964,7 @@ Inputs: Result: - Product of all lanes, as a scalar. -**Operation**: +Operation: for n > 1 { n = n / 2 @@ -2006,7 +2003,7 @@ Inputs: Result: - Minimum value of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2027,7 +2024,7 @@ Inputs: Result: - Maximum value of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2048,7 +2045,7 @@ Inputs: Result: - Bitwise AND of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2069,7 +2066,7 @@ Inputs: Result: - Bitwise OR of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2090,7 +2087,7 @@ Inputs: Result: - Bitwise XOR of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2111,7 +2108,7 @@ Inputs: Result: - Bitwise OR of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2132,7 +2129,7 @@ Inputs: Result: - Bitwise AND of all lanes, as a scalar. -**Operation**: +Operation: res := 0 for i in 0 ..< len(a) { @@ -2157,7 +2154,7 @@ Inputs: Result: - Swizzled input vector. -**Operation**: +Operation: res = {} for i in 0 ..< len(indices) { @@ -2210,7 +2207,7 @@ swizzle :: builtin.swizzle /* Extract the set of most-significant bits of a SIMD vector. -This procedure checks the the most-significant bit (MSB) for each lane of vector +This procedure checks the most-significant bit (MSB) for each lane of vector and returns the numbers of lanes with the most-significant bit set. This procedure can be used in conjuction with `lanes_eq` (and other similar procedures) to count the number of matched lanes by computing the cardinality of the resulting @@ -2223,7 +2220,7 @@ Result: - A bitset of integers, corresponding to the indexes of the lanes, whose MSBs are set. -**Operation**: +Operation: bits_per_lane = 8*size_of(a[0]) res = bit_set {} @@ -2256,7 +2253,7 @@ extract_msbs :: intrinsics.simd_extract_msbs /* Extract the set of least-significant bits of a SIMD vector. -This procedure checks the the least-significant bit (LSB) for each lane of vector +This procedure checks the least-significant bit (LSB) for each lane of vector and returns the numbers of lanes with the least-significant bit set. This procedure can be used in conjuction with `lanes_eq` (and other similar procedures) to count the number of matched lanes by computing the cardinality of the resulting @@ -2269,7 +2266,7 @@ Result: - A bitset of integers, corresponding to the indexes of the lanes, whose LSBs are set. -**Operation**: +Operation: res = bit_set {} for i in 0 ..< len(a) { @@ -2317,7 +2314,7 @@ Inputs: Result: - Input vectors, shuffled according to the indices. -**Operation**: +Operation: res = {} for i in 0 ..< len(indices) { @@ -2389,7 +2386,7 @@ Inputs: Result: - The result of selecting values from the two input vectors. -**Operation**: +Operation: res = {} for i in 0 ..< len(cond) { @@ -2443,6 +2440,71 @@ Graphically, the operation looks as follows. The `t` and `f` represent the */ select :: intrinsics.simd_select +/* +Hardware-level dynamic swizzle / table lookup. + +For each output lane `i`, picks an element from `table` using `indices[i]` +as the source position. Maps directly onto hardware table-lookup instructions +where available (`tbl` on ARM, `pshufb` on x86, `swizzle` on WASM). This is +the runtime counterpart of `simd.shuffle`. + +Inputs: +- `table`: a `#simd[N]T` lookup table, where `T` is an integer type and + `N` is a power of two (enforced by `#simd`). +- `indices`: a `#simd[N]T` of source positions. Must have the exact same + type as `table`. + +Returns: +- A `#simd[N]T`. For `indices[i]` in `[0, N-1]`, `result[i] = table[indices[i]]` + on ARM, on WebAssembly (16-byte), and on the scalar emulation fallback. + On x86 vectors larger than 16 bytes, the operation is lane-local; see Notes. + +Operation (in-range indices, non-lane-local platforms): + + for i in 0 ..< N { + result[i] = table[indices[i]] // indices[i] assumed to be in [0, N-1] + } + +Notes: +- **Out-of-range indices** (`indices[i] >= N`) are platform-defined: + most hardware paths return 0; the scalar fallback wraps via + `indices[i] & (N-1)`. Mask explicitly if you need portable behavior. +- **x86 wide vectors are lane-local.** `vpshufb` treats a 256-bit AVX2 + register as two independent 128-bit lanes; `pshufb.b.512` treats a + 512-bit AVX-512 register as four. An index in lane `k` can only address + table entries in that same lane. AVX2 Example: Lane 0 is [0..15], Lane 1 + is [16..31]. Accessing `indices[20] = 5` yields `table[21]`, not `table[5]`. + ARM `tbl` and the emulation fallback are cross-lane across the full table. +- **Hardware acceleration is conditional.** It requires 8-bit integer + elements, a vector size supported by the target, and the relevant + target features enabled (`ssse3` / `avx2` / `avx512f`+`avx512bw` on x86, + `neon` on ARM). Otherwise this falls back to scalar emulation. Non-byte + element types always use the scalar fallback. + +Implementation: + + | Platform | Hardware path (8-bit elements) | Notes | + |-------------|-------------------------------------------------|-------------------------------| + | x86-64 | pshufb (16B), vpshufb (32B), pshufb.b.512 (64B) | 32 / 64 B are lane-local | + | ARM64 | tbl1 (16B), tbl2 (32B), tbl4 (64B) | >16 B: split into 16-B chunks | + | ARM32 | vtbl1 (8B), vtbl2 (16B), vtbl4 (32B) | >8 B: split into 8-B chunks | + | WebAssembly | i8x16.swizzle (16B) | Other sizes: emulated | + | Other | Scalar emulation | | + +Example: + + import "core:simd" + import "core:fmt" + + runtime_swizzle_example :: proc() { + table := simd.u8x16{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + indices := simd.u8x16{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} + result := simd.runtime_swizzle(table, indices) + fmt.println(result) // {15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} + } +*/ +runtime_swizzle :: intrinsics.simd_runtime_swizzle + /* Compute the square root of each lane in a SIMD vector. */ @@ -2469,10 +2531,16 @@ Compute the nearest integer of each lane in a SIMD vector. nearest :: intrinsics.simd_nearest /* -Transmute a SIMD vector into an integer vector. +Transmute a SIMD vector into an unsigned integer vector. */ to_bits :: intrinsics.simd_to_bits +/* +Transmute a SIMD vector into a signed integer vector. +*/ +to_bits_signed :: intrinsics.simd_to_bits_signed + + /* Reverse the lanes of a SIMD vector. @@ -2531,6 +2599,33 @@ Reverse the bit pattern of a SIMD vector. */ reverse_bits :: intrinsics.reverse_bits +/* +Swap the bytes of the elements of a SIMD vector. +*/ +byte_swap :: intrinsics.byte_swap + + +/* +**Operation** + + #assert(len(a) == len(b)) + res := 0 + N :: len(a) + for i in 0 ..< N/2 { + res[i] = a[2*i + 1] + } + for i in 0 ..< N/2 { + res[i + N/2] = b[2*i] + } + return res +*/ +odd_even :: intrinsics.simd_odd_even + +@(require_results) +add_sub :: #force_inline proc "contextless" (a, b: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { + return odd_even(add(a, b), sub(a, b)) +} + /* Perform a FMA (Fused multiply-add) operation on each lane of SIMD vectors. @@ -2558,6 +2653,41 @@ Returns: */ fused_mul_add :: intrinsics.fused_mul_add + +@(require_results) +fused_neg_mul_add :: #force_inline proc "contextless" (a, b, c: $T/#simd[$LANES]$E) -> T { + return fused_mul_add(neg(a), b, c) +} + +@(require_results) +fused_mul_sub :: #force_inline proc "contextless" (a, b, c: $T/#simd[$LANES]$E) -> T { + return fused_mul_add(a, b, neg(c)) +} + +@(require_results) +fused_neg_mul_sub :: #force_inline proc "contextless" (a, b, c: $T/#simd[$LANES]$E) -> T { + return fused_mul_add(neg(a), b, neg(c)) +} + +@(require_results) +fused_mul_add_sub :: #force_inline proc "contextless" (a, b, c: $T/#simd[$LANES]$E) -> T { + odd := fused_mul_add(a, b, c) + even := fused_mul_sub(a, b, c) + return odd_even(odd, even) +} + +@(require_results) +fused_mul_sub_add :: #force_inline proc "contextless" (a, b, c: $T/#simd[$LANES]$E) -> T { + odd := fused_mul_sub(a, b, c) + even := fused_mul_add(a, b, c) + return odd_even(odd, even) +} + + + + + + /* Perform a FMA (Fused multiply-add) operation on each lane of SIMD vectors. @@ -2588,6 +2718,7 @@ fma :: intrinsics.fused_mul_add /* Convert pointer to SIMD vector to an array pointer. */ +@(require_results) to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E { return (^[LANES]E)(v) } @@ -2595,6 +2726,7 @@ to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANE /* Convert SIMD vector to an array. */ +@(require_results) to_array :: #force_inline proc "contextless" (v: #simd[$LANES]$E) -> [LANES]E { return transmute([LANES]E)(v) } @@ -2602,6 +2734,7 @@ to_array :: #force_inline proc "contextless" (v: #simd[$LANES]$E) -> [LANES]E { /* Convert array to SIMD vector. */ +@(require_results) from_array :: #force_inline proc "contextless" (v: $A/[$LANES]$E) -> #simd[LANES]E { return transmute(#simd[LANES]E)v } @@ -2609,6 +2742,7 @@ from_array :: #force_inline proc "contextless" (v: $A/[$LANES]$E) -> #simd[LANES /* Convert slice to SIMD vector. */ +@(require_results) from_slice :: proc($T: typeid/#simd[$LANES]$E, slice: []E) -> T { assert(len(slice) >= LANES, "slice length must be a least the number of lanes") array: [LANES]E @@ -2624,7 +2758,7 @@ Perform binary not operation on a SIMD vector. This procedure returns a vector where each lane is the result of the binary NOT operation of the corresponding lane in the vector `a`. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = ~a[i] @@ -2641,13 +2775,15 @@ Example: | 0xff | 0xaf | 0x7f | 0x00 | +------+------+------+------+ */ +@(require_results) bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { - return xor(v, T(~E(0))) + return bit_xor(v, T(~E(0))) } /* Copy the signs from lanes of one SIMD vector into another SIMD vector. */ +@(require_results) copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { neg_zero := to_bits(T(-0.0)) sign_bit := to_bits(sign) & neg_zero @@ -2663,11 +2799,21 @@ This procedure returns a vector, each lane of which contains either +1.0 or input vector. If the lane of the input vector has NaN, then the result vector will contain this NaN value as-is. */ +@(require_results) signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { is_nan := lanes_ne(v, v) return select(is_nan, v, copysign(T(1), v)) } +@(require_results) +sign_bit :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> (res: type_of(intrinsics.simd_to_bits(T{}))) { + BITS :: 8*size_of(E) + val := to_bits(v) + mask := type_of(val)(1<<(BITS-1)) + masked := bit_and(val, mask) + return to_bits(shr_masked(to_bits_signed(masked), BITS-1)) +} + /* Calculate reciprocals of SIMD lanes. @@ -2680,7 +2826,7 @@ Inputs: Returns: - Negated vector. -**Operation**: +Operation: for i in 0 ..< len(res) { res[i] = 1.0 / a[i] @@ -2697,20 +2843,63 @@ Example: | 0.5 | 1 | 0.33 | 0.2 | +------+------+------+------+ */ +@(require_results) recip :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) { return T(1) / v } +approx_recip :: intrinsics.simd_approx_recip +approx_recip_sqrt :: intrinsics.simd_approx_recip_sqrt + + /* Create a vector where each lane contains the index of that lane. Inputs: - `V`: The type of the vector to create. Result: - A vector of the given type, where each lane contains the index of that lane. -**Operation**: +Operation: for i in 0 ..< N { res[i] = i } */ -indices :: intrinsics.simd_indices \ No newline at end of file +indices :: intrinsics.simd_indices + +/* +Create a vector where each lane contains the index of that lane. +Inputs: +- `V`: The type of the vector to create. +Result: +- A vector of the given type, where each lane contains the index of that lane. +Operation: + for i in 0 ..< N { + res[i] = i + } +*/ +iota :: intrinsics.simd_indices + + +sums_of_n :: intrinsics.simd_sums_of_n + + +@(require_results) +saturating_neg :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { + return saturating_sub(T(0), v) +} + +@(require_results) +saturating_abs :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { + return max(v, saturating_sub(T(0), v)) +} + +@(require_results) +abs_diff :: #force_inline proc "contextless" (a, b: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) { + return abs(sub(a, b)) +} + +pairwise_add :: intrinsics.simd_pairwise_add +pairwise_sub :: intrinsics.simd_pairwise_add + +interleave :: intrinsics.simd_interleave +deinterleave :: intrinsics.simd_deinterleave \ No newline at end of file diff --git a/core/simd/x86/avx.odin b/core/simd/x86/avx.odin new file mode 100644 index 000000000..5b0383526 --- /dev/null +++ b/core/simd/x86/avx.odin @@ -0,0 +1,1854 @@ +#+build i386, amd64 +package simd_x86 + +import "base:intrinsics" + +// Adds packed double-precision (64-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_add_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_add(a, b) +} + +// Adds packed single-precision (32-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_add_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_add(a, b) +} + +// Computes the bitwise AND of a packed double-precision (64-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_and_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + a := transmute(#simd[4]u64)a + b := transmute(#simd[4]u64)b + return transmute(__m256d)intrinsics.simd_bit_and(a, b) +} + +// Computes the bitwise AND of packed single-precision (32-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_and_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + a := transmute(#simd[8]u32)a + b := transmute(#simd[8]u32)b + return transmute(__m256)intrinsics.simd_bit_and(a, b) +} + +// Computes the bitwise OR packed double-precision (64-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_or_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + a := transmute(#simd[4]u64)a + b := transmute(#simd[4]u64)b + return transmute(__m256d)intrinsics.simd_bit_or(a, b) +} + +// Computes the bitwise OR packed single-precision (32-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_or_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + a := transmute(#simd[8]u32)a + b := transmute(#simd[8]u32)b + return transmute(__m256)intrinsics.simd_bit_or(a, b) +} + +// Shuffles double-precision (64-bit) floating-point elements within 128-bit lanes using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_shuffle_pd :: #force_inline proc "c" (a, b: __m256d, $MASK: u8) -> __m256d { + return intrinsics.simd_shuffle( + a, + b, + MASK & 1, + ((MASK >> 1) & 1) + 4, + ((MASK >> 2) & 1) + 2, + ((MASK >> 3) & 1) + 6, + ) +} + + +// Shuffles single-precision (32-bit) floating-point elements in `a` within 128-bit lanes using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_shuffle_ps :: #force_inline proc "c" (a, b: __m256, $MASK: u8) -> __m256 { + return intrinsics.simd_shuffle( + a, + b, + MASK & 0b11, + (MASK >> 2) & 0b11, + ((MASK >> 4) & 0b11) + 8, + ((MASK >> 6) & 0b11) + 8, + (MASK & 0b11) + 4, + ((MASK >> 2) & 0b11) + 4, + ((MASK >> 4) & 0b11) + 12, + ((MASK >> 6) & 0b11) + 12, + ) +} + + + +// Computes the bitwise NOT of packed double-precision (64-bit) floating-point elements in `a`, and then AND with `b`. +@(require_results, enable_target_feature="avx") +_mm256_andnot_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + a := transmute(#simd[4]u64)a + b := transmute(#simd[4]u64)b + return transmute(__m256d)intrinsics.simd_bit_and(intrinsics.simd_bit_xor((#simd[4]u64)(0), a), b) +} + +// Computes the bitwise NOT of packed single-precision (32-bit) floating-point elements in `a` and then AND with `b`. +@(require_results, enable_target_feature="avx") +_mm256_andnot_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + a := transmute(#simd[8]u32)a + b := transmute(#simd[8]u32)b + return transmute(__m256)intrinsics.simd_bit_and(intrinsics.simd_bit_xor((#simd[8]u32)(0), a), b) +} + + + +// Compares packed double-precision (64-bit) floating-point elements in `a` and `b`, and returns packed maximum values +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_max_pd) +@(require_results, enable_target_feature="avx") +_mm256_max_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return llvm_vmaxpd(a, b) +} + +// Compares packed single-precision (32-bit) floating-point elements in `a` and `b`, and returns packed maximum values +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_max_ps) +@(require_results, enable_target_feature="avx") +_mm256_max_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return llvm_vmaxps(a, b) +} + +// Compares packed double-precision (64-bit) floating-point elements in `a` and `b`, and returns packed minimum values +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_min_pd) +@(require_results, enable_target_feature="avx") +_mm256_min_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return llvm_vminpd(a, b) +} + +// Compares packed single-precision (32-bit) floating-point elements in `a` and `b`, and returns packed minimum values +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_min_ps) +@(require_results, enable_target_feature="avx") +_mm256_min_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return llvm_vminps(a, b) +} + + + +// Multiplies packed double-precision (64-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_mul_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_mul(a, b) +} + +// Multiplies packed single-precision (32-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_mul_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_mul(a, b) +} + +// Alternatively adds and subtracts packed double-precision (64-bit) floating-point elements in `a` to/from packed elements in `b`. +@(require_results, enable_target_feature="avx") +_mm256_addsub_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + add := intrinsics.simd_add(a, b) + sub := intrinsics.simd_sub(a, b) + return intrinsics.simd_shuffle(add, sub, 4, 1, 6, 3) +} + + +// Alternatively adds and subtracts packed single-precision (32-bit) floating-point elements in `a` to/from packed elements in `b`. +@(require_results, enable_target_feature="avx") +_mm256_addsub_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + add := intrinsics.simd_add(a, b) + sub := intrinsics.simd_sub(a, b) + return intrinsics.simd_shuffle(add, sub, 8, 1, 10, 3, 12, 5, 14, 7) +} + + +// Subtracts packed double-precision (64-bit) floating-point elements in `b` +// from packed elements in `a`. +@(require_results, enable_target_feature="avx") +_mm256_sub_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_sub(a, b) +} + +// Subtracts packed single-precision (32-bit) floating-point elements in `b` +// from packed elements in `a`. +@(require_results, enable_target_feature="avx") +_mm256_sub_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_sub(a, b) +} + +// Computes the division of each of the 8 packed 32-bit floating-point elements +// in `a` by the corresponding packed elements in `b`. +@(require_results, enable_target_feature="avx") +_mm256_div_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_div(a, b) +} + +// Computes the division of each of the 4 packed 64-bit floating-point elements +// in `a` by the corresponding packed elements in `b`. +@(require_results, enable_target_feature="avx") +_mm256_div_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_div(a, b) +} + + + +// Rounds packed double-precision (64-bit) floating point elements in `a` +// according to the flag `ROUNDING`. The value of `ROUNDING` may be as follows: +// +// - `0x00`: Round to the nearest whole number. +// - `0x01`: Round down, toward negative infinity. +// - `0x02`: Round up, toward positive infinity. +// - `0x03`: Truncate the values. +// +// For a complete list of options, check [the LLVM docs][llvm_docs]. +// +// [llvm_docs]: https://github.com/llvm-mirror/clang/blob/dcd8d797b20291f1a6b3e0ddda085aa2bbb382a8/lib/Headers/avxintrin.h#L382 +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_round_pd) +@(require_results, enable_target_feature="avx") +_mm256_round_pd :: #force_inline proc "c" (a: __m256d, $ROUNDING: u8) -> __m256d where ROUNDING < 16 { + return llvm_roundpd256(a, ROUNDING) +} + +// Rounds packed double-precision (64-bit) floating point elements in `a` +// toward positive infinity. +@(require_results, enable_target_feature="avx") +_mm256_ceil_pd :: #force_inline proc "c" (a: __m256d) -> __m256d { + return intrinsics.simd_ceil(a) +} + +// Rounds packed double-precision (64-bit) floating point elements in `a` +// toward negative infinity. +@(require_results, enable_target_feature="avx") +_mm256_floor_pd :: #force_inline proc "c" (a: __m256d) -> __m256d { + return intrinsics.simd_floor(a) +} + + + +// Rounds packed single-precision (32-bit) floating point elements in `a` +// according to the flag `ROUNDING`. The value of `ROUNDING` may be as follows: +// +// - `0x00`: Round to the nearest whole number. +// - `0x01`: Round down, toward negative infinity. +// - `0x02`: Round up, toward positive infinity. +// - `0x03`: Truncate the values. +// +// For a complete list of options, check [the LLVM docs][llvm_docs]. +// +// [llvm_docs]: https://github.com/llvm-mirror/clang/blob/dcd8d797b20291f1a6b3e0ddda085aa2bbb382a8/lib/Headers/avxintrin.h#L382 +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_round_ps) +@(require_results, enable_target_feature="avx") +_mm256_round_ps :: #force_inline proc(a: __m256, $ROUNDING: u8) -> __m256 where ROUNDING < 16 { + return llvm_roundps256(a, u32(ROUNDING)) +} + +// Rounds packed single-precision (32-bit) floating point elements in `a` +// toward positive infinity. +@(require_results, enable_target_feature="avx") +_mm256_ceil_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return intrinsics.simd_ceil(a) +} + +// Rounds packed single-precision (32-bit) floating point elements in `a` +// toward negative infinity. +@(require_results, enable_target_feature="avx") +_mm256_floor_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return intrinsics.simd_floor(a) +} + +// Returns the square root of packed single-precision (32-bit) floating point elements in `a`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sqrt_ps) +@(require_results, enable_target_feature="avx") +_mm256_sqrt_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return intrinsics.sqrt(a) +} + +// Returns the square root of packed double-precision (64-bit) floating point elements in `a`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sqrt_pd) +@(require_results, enable_target_feature="avx") +_mm256_sqrt_pd :: #force_inline proc "c" (a: __m256d) -> __m256d { + return intrinsics.sqrt(a) +} + + + +// Blends packed double-precision (64-bit) floating-point elements from +// `a` and `b` using control mask `imm8`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_blend_pd) +@(require_results, enable_target_feature="avx") +_mm256_blend_pd :: #force_inline proc "c" (a, b: __m256d, $IIM4: u32) -> __m256d where IMM4 < 16 { + return intrinsics.simd_shuffle( + a, + b, + ((IMM4 >> 0) & 1) * 4 + 0, + ((IMM4 >> 1) & 1) * 4 + 1, + ((IMM4 >> 2) & 1) * 4 + 2, + ((IMM4 >> 3) & 1) * 4 + 3, + ) +} + +// Blends packed single-precision (32-bit) floating-point elements from +// `a` and `b` using control mask `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_blend_ps :: #force_inline proc "c" (a, b: __m256, $IMM8: u8) -> __m256 { + return intrinsics.simd_shuffle( + a, + b, + ((IMM8 >> 0) & 1) * 8 + 0, + ((IMM8 >> 1) & 1) * 8 + 1, + ((IMM8 >> 2) & 1) * 8 + 2, + ((IMM8 >> 3) & 1) * 8 + 3, + ((IMM8 >> 4) & 1) * 8 + 4, + ((IMM8 >> 5) & 1) * 8 + 5, + ((IMM8 >> 6) & 1) * 8 + 6, + ((IMM8 >> 7) & 1) * 8 + 7, + ) +} + + + +// Blends packed double-precision (64-bit) floating-point elements from +// `a` and `b` using `c` as a mask. +@(require_results, enable_target_feature="avx") +_mm256_blendv_pd :: #force_inline proc "c" (a, b: __m256d, c: __m256d) -> __m256d { + mask := intrinsics.simd_lanes_lt(transmute(#simd[4]i64)c, 0) + return intrinsics.simd_select(mask, b, a) +} + +// Blends packed single-precision (32-bit) floating-point elements from +// `a` and `b` using `c` as a mask. +@(require_results, enable_target_feature="avx") +_mm256_blendv_ps :: #force_inline proc "c" (a, b: __m256, c: __m256) -> __m256 { + mask := intrinsics.simd_lanes_lt(transmute(#simd[8]i32)c, 0) + return intrinsics.simd_select(mask, b, a) +} + + + +// Conditionally multiplies the packed single-precision (32-bit) floating-point elements in `a` and `b` using the high 4 bits in `imm8`, +// sum the four products, and conditionally return the sum +// using the low 4 bits of `imm8`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_dp_ps) +@(require_results, enable_target_feature="avx") +_mm256_dp_ps :: #force_inline proc "c" (a, b: __m256, $IMM8: i8) -> __m256 { + return llvm_vdpps(a, b, IMM8) +} + +// Horizontal addition of adjacent pairs in the two packed vectors +// of 4 64-bit floating points `a` and `b`. +// In the result, sums of elements from `a` are returned in even locations, +// while sums of elements from `b` are returned in odd locations. +@(require_results, enable_target_feature="avx") +_mm256_hadd_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + even := intrinsics.simd_shuffle(a, b, 0, 4, 2, 6) + odd := intrinsics.simd_shuffle(a, b, 1, 5, 3, 7) + return intrinsics.simd_add(even, odd) +} + + + +// Horizontal addition of adjacent pairs in the two packed vectors +// of 8 32-bit floating points `a` and `b`. +// In the result, sums of elements from `a` are returned in locations of +// indices 0, 1, 4, 5; while sums of elements from `b` are locations +// 2, 3, 6, 7. +@(require_results, enable_target_feature="avx") +_mm256_hadd_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + even := intrinsics.simd_shuffle(a, b, 0, 2, 8, 10, 4, 6, 12, 14) + odd := intrinsics.simd_shuffle(a, b, 1, 3, 9, 11, 5, 7, 13, 15) + return intrinsics.simd_add(even, odd) +} + +// Horizontal subtraction of adjacent pairs in the two packed vectors +// of 4 64-bit floating points `a` and `b`. +// In the result, sums of elements from `a` are returned in even locations, +// while sums of elements from `b` are returned in odd locations. +@(require_results, enable_target_feature="avx") +_mm256_hsub_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + even := intrinsics.simd_shuffle(a, b, 0, 4, 2, 6) + odd := intrinsics.simd_shuffle(a, b, 1, 5, 3, 7) + return intrinsics.simd_sub(even, odd) +} + +// Horizontal subtraction of adjacent pairs in the two packed vectors +// of 8 32-bit floating points `a` and `b`. +// In the result, sums of elements from `a` are returned in locations of +// indices 0, 1, 4, 5; while sums of elements from `b` are locations +// 2, 3, 6, 7. +@(require_results, enable_target_feature="avx") +_mm256_hsub_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + even := intrinsics.simd_shuffle(a, b, 0, 2, 8, 10, 4, 6, 12, 14) + odd := intrinsics.simd_shuffle(a, b, 1, 3, 9, 11, 5, 7, 13, 15) + return intrinsics.simd_sub(even, odd) +} + +// Computes the bitwise XOR of packed double-precision (64-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_xor_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + a := transmute(#simd[4]u64)a + b := transmute(#simd[4]u64)b + return transmute(__m256d)intrinsics.simd_bit_xor(a, b) +} + +// Computes the bitwise XOR of packed single-precision (32-bit) floating-point elements in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_xor_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + a := transmute(#simd[8]u32)a + b := transmute(#simd[8]u32)b + return transmute(__m256)intrinsics.simd_bit_xor(a, b) +} + + + +_CMP_EQ_OQ :: 0x00 // Equal (ordered, non-signaling) +_CMP_LT_OS :: 0x01 // Less-than (ordered, signaling) +_CMP_LE_OS :: 0x02 // Less-than-or-equal (ordered, signaling) +_CMP_UNORD_Q :: 0x03 // Unordered (non-signaling) +_CMP_NEQ_UQ :: 0x04 // Not-equal (unordered, non-signaling) +_CMP_NLT_US :: 0x05 // Not-less-than (unordered, signaling) +_CMP_NLE_US :: 0x06 // Not-less-than-or-equal (unordered, signaling) +_CMP_ORD_Q :: 0x07 // Ordered (non-signaling) +_CMP_EQ_UQ :: 0x08 // Equal (unordered, non-signaling) +_CMP_NGE_US :: 0x09 // Not-greater-than-or-equal (unordered, signaling) +_CMP_NGT_US :: 0x0a // Not-greater-than (unordered, signaling) +_CMP_FALSE_OQ :: 0x0b // False (ordered, non-signaling) +_CMP_NEQ_OQ :: 0x0c // Not-equal (ordered, non-signaling) +_CMP_GE_OS :: 0x0d // Greater-than-or-equal (ordered, signaling) +_CMP_GT_OS :: 0x0e // Greater-than (ordered, signaling) +_CMP_TRUE_UQ :: 0x0f // True (unordered, non-signaling) +_CMP_EQ_OS :: 0x10 // Equal (ordered, signaling) +_CMP_LT_OQ :: 0x11 // Less-than (ordered, non-signaling) +_CMP_LE_OQ :: 0x12 // Less-than-or-equal (ordered, non-signaling) +_CMP_UNORD_S :: 0x13 // Unordered (signaling) +_CMP_NEQ_US :: 0x14 // Not-equal (unordered, signaling) +_CMP_NLT_UQ :: 0x15 // Not-less-than (unordered, non-signaling) +_CMP_NLE_UQ :: 0x16 // Not-less-than-or-equal (unordered, non-signaling) +_CMP_ORD_S :: 0x17 // Ordered (signaling) +_CMP_EQ_US :: 0x18 // Equal (unordered, signaling) +_CMP_NGE_UQ :: 0x19 // Not-greater-than-or-equal (unordered, non-signaling) +_CMP_NGT_UQ :: 0x1a // Not-greater-than (unordered, non-signaling) +_CMP_FALSE_OS :: 0x1b // False (ordered, signaling) +_CMP_NEQ_OS :: 0x1c // Not-equal (ordered, signaling) +_CMP_GE_OQ :: 0x1d // Greater-than-or-equal (ordered, non-signaling) +_CMP_GT_OQ :: 0x1e // Greater-than (ordered, non-signaling) +_CMP_TRUE_US :: 0x1f // True (unordered, signaling) + + + +// Compares packed double-precision (64-bit) floating-point elements in `a` and `b` based on the comparison operand specified by `IMM5`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmp_pd) +@(require_results, enable_target_feature="avx") +_mm_cmp_pd :: #force_inline proc "c" (a, b: __m128d, $IMM5: u8) -> __m128d where IMM5 < 32 { + return llvm_vcmppd(a, b, IMM5) +} + +// Compares packed double-precision (64-bit) floating-point elements in `a` and `b` based on the comparison operand specified by `IMM5`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cmp_pd) +@(require_results, enable_target_feature="avx") +_mm256_cmp_pd :: #force_inline proc "c" (a, b: __m256d, $IMM5: u8) -> __m256d where IMM5 < 32 { + return llvm_vcmppd256(a, b, IMM5) +} + +// Compares packed single-precision (32-bit) floating-point elements in `a` and `b` based on the comparison operand specified by `IMM5`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmp_ps) +@(require_results, enable_target_feature="avx") +_mm_cmp_ps :: #force_inline proc "c" (a: __m128, b: __m128, $IMM5: u8) -> __m128 where IMM5 < 32 { + return llvm_vcmpps(a, b, IMM5) +} + +// Compares packed single-precision (32-bit) floating-point elements in `a` and `b` based on the comparison operand specified by `IMM5`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cmp_ps) +@(require_results, enable_target_feature="avx") +_mm256_cmp_ps :: #force_inline proc "c" (a, b: __m256, $IMM5: u8) -> __m256 where IMM5 < 32 { + return llvm_vcmpps256(a, b, IMM5) +} + +// Compares the lower double-precision (64-bit) floating-point element in +// `a` and `b` based on the comparison operand specified by `IMM5`, +// store the result in the lower element of returned vector, +// and copies the upper element from `a` to the upper element of returned +// vector. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmp_sd) +@(require_results, enable_target_feature="avx") +_mm_cmp_sd :: #force_inline proc "c" (a, b: __m128d, $IMM5: u8) -> __m128d where IMM5 < 32 { + return llvm_vcmpsd(a, b, IMM5) +} + +// Compares the lower single-precision (32-bit) floating-point element in +// `a` and `b` based on the comparison operand specified by `IMM5`, +// store the result in the lower element of returned vector, +// and copies the upper 3 packed elements from `a` to the upper elements of +// returned vector. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmp_ss) +@(require_results, enable_target_feature="avx") +_mm_cmp_ss :: #force_inline proc "c" (a: __m128, b: __m128, $IMM5: u8) -> __m128 where IMM5 < 32 { + return llvm_vcmpss(a, b, IMM5) +} + +// Converts packed 32-bit integers in `a` to packed double-precision (64-bit) floating-point elements. +@(require_results, enable_target_feature="avx") +_mm256_cvtepi32_pd :: #force_inline proc "c" (a: __m128i) -> __m256d { + return __m256d(transmute(#simd[4]i32)a) +} + +// Converts packed 32-bit integers in `a` to packed single-precision (32-bit) floating-point elements. +@(require_results, enable_target_feature="avx") +_mm256_cvtepi32_ps :: #force_inline proc "c" (a: __m256i) -> __m256 { + return __m256(transmute(#simd[8]i32)a) +} + +// Converts packed double-precision (64-bit) floating-point elements in `a` to packed single-precision (32-bit) floating-point elements. +@(require_results, enable_target_feature="avx") +_mm256_cvtpd_ps :: #force_inline proc "c" (a: __m256d) -> __m128 { + return __m128(a) +} + +// Converts packed single-precision (32-bit) floating-point elements in `a` to packed 32-bit integers. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cvtps_epi32) +@(require_results, enable_target_feature="avx") +_mm256_cvtps_epi32 :: #force_inline proc "c" (a: __m256) -> __m256i { + return transmute(__m256i)llvm_vcvtps2dq(a) +} + +// Converts packed single-precision (32-bit) floating-point elements in `a` to packed double-precision (64-bit) floating-point elements. +@(require_results, enable_target_feature="avx") +_mm256_cvtps_pd :: #force_inline proc "c" (a: __m128) -> __m256d { + return __m256d(a) +} + +// Returns the first element of the input vector of `[4 x double]`. +@(require_results, enable_target_feature="avx") +_mm256_cvtsd_f64 :: #force_inline proc "c" (a: __m256d) -> f64 { + return intrinsics.simd_extract(a, 0) +} + +// Converts packed double-precision (64-bit) floating-point elements in `a` to packed 32-bit integers with truncation. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cvttpd_epi32) +@(require_results, enable_target_feature="avx") +_mm256_cvttpd_epi32 :: #force_inline proc "c" (a: __m256d) -> __m128i { + return transmute(__m128i)llvm_vcvttpd2dq(a) +} + +// Converts packed double-precision (64-bit) floating-point elements in `a` to packed 32-bit integers. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cvtpd_epi32) +@(require_results, enable_target_feature="avx") +_mm256_cvtpd_epi32 :: #force_inline proc "c" (a: __m256d) -> __m128i { + return transmute(__m128i)llvm_vcvtpd2dq(a) +} + +// Converts packed single-precision (32-bit) floating-point elements in `a` to packed 32-bit integers with truncation. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_cvttps_epi32) +@(require_results, enable_target_feature="avx") +_mm256_cvttps_epi32 :: #force_inline proc "c" (a: __m256) -> __m256i { + return transmute(__m256i)llvm_vcvttps2dq(a) +} + + + +// Extracts 128 bits (composed of 4 packed single-precision (32-bit) floating-point elements) from `a`, selected with `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_extractf128_ps :: #force_inline proc "c" (a: __m256, $IMM1: u8) -> __m128 where IMM1 < 2 { + when IMM1 == 0 { + return intrinsics.simd_shuffle(a, _mm256_undefined_ps(), 0, 1, 2, 3) + } else { + return intrinsics.simd_shuffle(a, _mm256_undefined_ps(), 4, 5, 6, 7) + } +} + +// Extracts 128 bits (composed of 2 packed double-precision (64-bit) floating-point elements) from `a`, selected with `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_extractf128_pd :: #force_inline proc "c" (a: __m256d, $IMM1: u8) -> __m128d where IMM1 < 2 { + when IMM1 == 0 { + return intrinsics.simd_shuffle(a, _mm256_undefined_pd(), 0, 1) + } else { + return intrinsics.simd_shuffle(a, _mm256_undefined_pd(), 2, 3) + } +} + +// Extracts 128 bits (composed of integer data) from `a`, selected with `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_extractf128_si256 :: #force_inline proc "c" (a: __m256i, $IMM1: u8) -> __m128i where IMM1 < 2 { + when IMM1 == 0 { + dst := intrinsics.simd_shuffle(transmute(#simd[4]i64)a, (#simd[4]i64)(0), 0, 1) + return transmute(__m128i)dst + } else { + dst := intrinsics.simd_shuffle(transmute(#simd[4]i64)a, (#simd[4]i64)(0), 2, 3) + return transmute(__m128i)dst + } +} + +// Extracts a 32-bit integer from `a`, selected with `INDEX`. +@(require_results, enable_target_feature="avx") +_mm256_extract_epi32 :: #force_inline proc "c" (a: __m256i, $INDEX: u8) -> i32 where INDEX < 8 { + return intrinsics.simd_extract(transmute(#simd[8]i32)a, INDEX) +} + +@(require_results, enable_target_feature="avx") +_mm256_cvtsi256_si32 :: #force_inline proc "c" (a: __m256i) -> i32 { + return intrinsics.simd_extract(transmute(#simd[8]i32)a, 0) +} + +// Zeroes the contents of all XMM or YMM registers. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_zeroall) +@(enable_target_feature="avx") +_mm256_zeroall :: #force_inline proc "c" () { + llvm_vzeroall() +} + +// Zeroes the upper 128 bits of all YMM registers; the lower 128-bits of the registers are unmodified. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_zeroupper) +@(enable_target_feature="avx") +_mm256_zeroupper :: #force_inline proc "c" () { + llvm_vzeroupper() +} + +// Shuffles single-precision (32-bit) floating-point elements in `a` within 128-bit lanes using the control in `b`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permutevar_ps) +@(require_results, enable_target_feature="avx") +_mm256_permutevar_ps :: #force_inline proc "c" (a: __m256, b: __m256i) -> __m256 { + return llvm_vpermilps256(a, transmute(#simd[8]i32)b) +} + +// Shuffles single-precision (32-bit) floating-point elements in `a` using the control in `b`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_permutevar_ps) +@(require_results, enable_target_feature="avx") +_mm_permutevar_ps :: #force_inline proc "c" (a: __m128, b: __m128i) -> __m128 { + return llvm_vpermilps(a, transmute(#simd[4]i32)b) +} + +// Shuffles single-precision (32-bit) floating-point elements in `a` within 128-bit lanes using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_permute_ps :: #force_inline proc "c" (a: __m256, $IMM8: u8) -> __m256 { + return intrinsics.simd_shuffle( + a, + _mm256_undefined_ps(), + (IMM8 >> 0) & 0b11, + (IMM8 >> 2) & 0b11, + (IMM8 >> 4) & 0b11, + (IMM8 >> 6) & 0b11, + ((IMM8 >> 0) & 0b11) + 4, + ((IMM8 >> 2) & 0b11) + 4, + ((IMM8 >> 4) & 0b11) + 4, + ((IMM8 >> 6) & 0b11) + 4, + ) +} + +// Shuffles single-precision (32-bit) floating-point elements in `a` using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm_permute_ps :: #force_inline proc "c" (a: __m128, $IMM8: u8) -> __m128 { + return intrinsics.simd_shuffle( + a, + _mm_undefined_ps(), + (IMM8 >> 0) & 0b11, + (IMM8 >> 2) & 0b11, + (IMM8 >> 4) & 0b11, + (IMM8 >> 6) & 0b11, + ) +} + +// Shuffles double-precision (64-bit) floating-point elements in `a` within 256-bit lanes using the control in `b`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permutevar_pd) +@(require_results, enable_target_feature="avx") +_mm256_permutevar_pd :: #force_inline proc "c" (a: __m256d, b: __m256i) -> __m256d { + return llvm_vpermilpd256(a, b) +} + +// Shuffles double-precision (64-bit) floating-point elements in `a` using the control in `b`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_permutevar_pd) +@(require_results, enable_target_feature="avx") +_mm_permutevar_pd :: #force_inline proc "c" (a: __m128d, b: __m128i) -> __m128d { + return llvm_vpermilpd(a, b) +} + +// Shuffles double-precision (64-bit) floating-point elements in `a` within 128-bit lanes using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_permute_pd :: #force_inline proc "c" (a: __m256d, $IMM4: u8) -> __m256d where IMM4 < 16 { + return intrinsics.simd_shuffle( + a, + _mm256_undefined_pd(), + ((IMM4 >> 0) & 1), + ((IMM4 >> 1) & 1), + ((IMM4 >> 2) & 1) + 2, + ((IMM4 >> 3) & 1) + 2, + ) +} + +// Shuffles double-precision (64-bit) floating-point elements in `a` using the control in `imm8`. +@(require_results, enable_target_feature="avx") +_mm_permute_pd :: #force_inline proc "c" (a: __m128d, $IMM2: u8) -> __m128d where IMM2 < 4 { + return intrinsics.simd_shuffle( + a, + _mm_undefined_pd(), + (IMM2) & 1, + (IMM2 >> 1) & 1, + ) +} + + + +// Shuffles 256 bits (composed of 8 packed single-precision (32-bit) floating-point elements) selected by `imm8` from `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_permute2f128_ps :: #force_inline proc "c" (a, b: __m256, $IMM8: u8) -> __m256 { + return _mm256_castsi256_ps(_mm256_permute2f128_si256( + _mm256_castps_si256(a), + _mm256_castps_si256(b), + IMM8, + )) +} + +// Shuffles 256 bits (composed of 4 packed double-precision (64-bit) floating-point elements) selected by `imm8` from `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_permute2f128_pd :: #force_inline proc "c" (a, b: __m256d, $IMM8: u8) -> __m256d { + _mm256_castsi256_pd(_mm256_permute2f128_si256( + _mm256_castpd_si256(a), + _mm256_castpd_si256(b), + IMM8, + )) +} + +// Shuffles 128-bits (composed of integer data) selected by `imm8` from `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_permute2f128_si256 :: #force_inline proc "c" (a, b: __m256i, $IMM8: u8) -> __m256i { + r := intrinsics.simd_shuffle( + a, + b, + 2 * ((IMM8 & 0xf) & 0b11) + 0, + 2 * ((IMM8 & 0xf) & 0b11) + 1, + + 2 * (((IMM8 & 0xf0) >> 4) & 0b11) + 0, + 2 * (((IMM8 & 0xf0) >> 4) & 0b11) + 1, + ) + return intrinsics.simd_shuffle( + r, + __m256i(0), + + 4 if ((IMM8 & 0xf) & 0b1000) != 0 else 0, + 4 if ((IMM8 & 0xf) & 0b1000) != 0 else 1, + + 4 if (((IMM8 & 0xf0)>>4) & 0b1000) != 0 else 2, + 4 if (((IMM8 & 0xf0)>>4) & 0b1000) != 0 else 3, + ) +} + +// Broadcasts a single-precision (32-bit) floating-point element from memory to all elements of the returned vector. +@(require_results, enable_target_feature="avx") +_mm256_broadcast_ss :: #force_inline proc "c" (f: ^f32) -> __m256 { + return _mm256_set1_ps(f^) +} + +// Broadcasts a single-precision (32-bit) floating-point element from memory to all elements of the returned vector. +@(require_results, enable_target_feature="sse,avx") +_mm_broadcast_ss :: #force_inline proc "c" (f: ^f32) -> __m128 { + return _mm_set1_ps(f^) +} + +// Broadcasts a double-precision (64-bit) floating-point element from memory to all elements of the returned vector. +@(require_results, enable_target_feature="avx") +_mm256_broadcast_sd :: #force_inline proc "c" (f: ^f64) -> __m256d { + return _mm256_set1_pd(f^) +} + +// Broadcasts 128 bits from memory (composed of 4 packed single-precision (32-bit) floating-point elements) to all elements of the returned vector. +@(require_results, enable_target_feature="sse,avx") +_mm256_broadcast_ps :: #force_inline proc "c" (a: ^__m128) -> __m256 { + return intrinsics.simd_shuffle(a^, _mm_setzero_ps(), 0, 1, 2, 3, 0, 1, 2, 3) +} + +// Broadcasts 128 bits from memory (composed of 2 packed double-precision (64-bit) floating-point elements) to all elements of the returned vector. +@(require_results, enable_target_feature="sse2,avx") +_mm256_broadcast_pd :: #force_inline proc "c" (a: ^__m128d) -> __m256d { + return intrinsics.simd_shuffle(a^, _mm_setzero_pd(), 0, 1, 0, 1) +} + +// Copies `a` to result, then inserts 128 bits (composed of 4 packed +// single-precision (32-bit) floating-point elements) from `b` into result +// at the location specified by `imm8`. +@(require_results, enable_target_feature="sse,avx") +_mm256_insertf128_ps :: #force_inline proc "c" (a: __m256, b: __m128, $IMM1: u8) -> __m256 where IMM1 < 2 { + when IMM1 == 0 { + return intrinsics.simd_shuffle( + a, + _mm256_castps128_ps256(b), + 8, 9, 10, 11, 4, 5, 6, 7, + ) + } else { + return intrinsics.simd_shuffle( + a, + _mm256_castps128_ps256(b), + 0, 1, 2, 3, 8, 9, 10, 11, + ) + } +} + +// Copies `a` to result, then inserts 128 bits (composed of 2 packed +// double-precision (64-bit) floating-point elements) from `b` into result +// at the location specified by `imm8`. +@(require_results, enable_target_feature="sse2,avx") +_mm256_insertf128_pd :: #force_inline proc "c" (a: __m256d, b: __m128d, $IMM1: u8) -> __m256d where IMM1 < 2 { + when IMM1 == 0 { + return intrinsics.simd_shuffle( + a, + _mm256_castpd128_pd256(b), + 4, 5, 2, 3, + ) + } else { + return intrinsics.simd_shuffle( + a, + _mm256_castpd128_pd256(b), + 0, 1, 4, 5, + ) + } +} + +// Copies `a` to result, then inserts 128 bits from `b` into result at the location specified by `imm8`. +@(require_results, enable_target_feature="avx") +_mm256_insertf128_si256 :: #force_inline proc "c" (a: __m256i, b: __m128i, $IMM1: u8) -> __m256i where IMM1 < 2 { + when IMM1 == 0 { + return intrinsics.simd_shuffle( + a, + _mm256_castsi128_si256(b), + 4, 5, 2, 3, + ) + } else { + return intrinsics.simd_shuffle( + a, + _mm256_castsi128_si256(b), + 0, 1, 4, 5, + ) + } +} + +// Copies `a` to result, and inserts the 8-bit integer `i` into result at the location specified by `index`. +@(require_results, enable_target_feature="avx") +_mm256_insert_epi8 :: #force_inline proc "c" (a: __m256i, i: i8, $INDEX: u8) -> __m256i where INDEX < 32 { + return transmute(__m256i)intrinsics.simd_replace(transmute(#simd[32]i8)a, INDEX, i) +} + +// Copies `a` to result, and inserts the 16-bit integer `i` into result at the location specified by `index`. +@(require_results, enable_target_feature="avx") +_mm256_insert_epi16 :: #force_inline proc "c" (a: __m256i, i: i16, $INDEX: u8) -> __m256i where INDEX < 16 { + return transmute(__m256i)intrinsics.simd_replace(transmute(#simd[16]i16)a, INDEX, i) +} + +// Copies `a` to result, and inserts the 32-bit integer `i` into result at the location specified by `index`. +@(require_results, enable_target_feature="avx") +_mm256_insert_epi32 :: #force_inline proc "c" (a: __m256i, i: i32, $INDEX: u8) -> __m256i where INDEX < 8 { + return transmute(__m256i)intrinsics.simd_replace(transmute(#simd[8]i32)a, INDEX, i) +} + + + +// Loads 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from memory into result. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_load_pd) +@(require_results, enable_target_feature="avx") +_mm256_load_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m256d { + return (^__m256d)(mem_addr)^ +} + +// Stores 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from `a` into memory. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_store_pd) +@(enable_target_feature="avx") +_mm256_store_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m256d) { + (^__m256d)(mem_addr)^ = a +} + +// Loads 256-bits (composed of 8 packed single-precision (32-bit) floating-point elements) from memory into result. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_load_ps) +@(require_results, enable_target_feature="avx") +_mm256_load_ps :: #force_inline proc "c" (mem_addr: ^f32) -> __m256 { + return (^__m256)(mem_addr)^ +} + +// Stores 256-bits (composed of 8 packed single-precision (32-bit) floating-point elements) from `a` into memory. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_store_ps) +@(enable_target_feature="avx") +_mm256_store_ps :: #force_inline proc "c" (mem_addr: ^f32, a: __m256) { + (^__m256)(mem_addr)^ = a +} + +// Loads 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from memory into result. +// `mem_addr` does not need to be aligned on any particular boundary. +@(enable_target_feature="avx") +_mm256_loadu_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m256d { + return intrinsics.unaligned_load((^__m256d)(mem_addr)) +} + +// Stores 256-bits (composed of 4 packed double-precision (64-bit) floating-point elements) from `a` into memory. +// `mem_addr` does not need to be aligned on any particular boundary. +@(enable_target_feature="avx") +_mm256_storeu_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m256d) { + intrinsics.unaligned_store((^__m256d)(mem_addr), a) +} + +// Loads 256-bits (composed of 8 packed single-precision (32-bit) floating-point elements) from memory into result. +// `mem_addr` does not need to be aligned on any particular boundary. +@(require_results, enable_target_feature="avx") +_mm256_loadu_ps :: #force_inline proc "c" (mem_addr: ^f32) -> __m256 { + return intrinsics.unaligned_load((^__m256)(mem_addr)) +} + +// Stores 256-bits (composed of 8 packed single-precision (32-bit) floating-point elements) from `a` into memory. +// `mem_addr` does not need to be aligned on any particular boundary. +@(enable_target_feature="avx") +_mm256_storeu_ps :: #force_inline proc "c" (mem_addr: ^f32, a: __m256) { + intrinsics.unaligned_store((^__m256)(mem_addr), a) +} + +// Loads 256-bits of integer data from memory into result. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_load_si256) +@(require_results, enable_target_feature="avx") +_mm256_load_si256 :: #force_inline proc "c" (mem_addr: ^__m256i) -> __m256i { + return mem_addr^ +} + +// Stores 256-bits of integer data from `a` into memory. +// `mem_addr` must be aligned on a 32-byte boundary or a +// general-protection exception may be generated. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_store_si256) +@(enable_target_feature="avx") +_mm256_store_si256 :: #force_inline proc "c" (mem_addr: ^__m256i, a: __m256i) { + mem_addr^ = a +} + +// Loads 256-bits of integer data from memory into result. +// `mem_addr` does not need to be aligned on any particular boundary. +@(require_results, enable_target_feature="avx") +_mm256_loadu_si256 :: #force_inline proc "c" (mem_addr: ^__m256i) -> __m256i { + return intrinsics.unaligned_load(mem_addr) +} + +// Stores 256-bits of integer data from `a` into memory. +// `mem_addr` does not need to be aligned on any particular boundary. +@(enable_target_feature="avx") +_mm256_storeu_si256 :: #force_inline proc "c" (mem_addr: ^__m256i, a: __m256i) { + intrinsics.unaligned_store(mem_addr, a) +} + +// Loads packed double-precision (64-bit) floating-point elements from memory +// into result using `mask` (elements are zeroed out when the high bit of the +// corresponding element is not set). +@(require_results, enable_target_feature="avx") +_mm256_maskload_pd :: #force_inline proc "c" (mem_addr: ^f64, mask: __m256i) -> __m256d { + mask_mask := intrinsics.simd_shr(mask, 63) + return intrinsics.simd_masked_load(mem_addr, _mm256_setzero_pd(), mask_mask) +} + +// Stores packed double-precision (64-bit) floating-point elements from `a` +// into memory using `mask`. +@(enable_target_feature="avx") +_mm256_maskstore_pd :: #force_inline proc "c" (mem_addr: ^f64, mask: __m256i, a: __m256d) { + mask_mask := intrinsics.simd_shr(mask, 63) + intrinsics.simd_masked_store(mem_addr, a, mask_mask) +} + + +// Loads packed double-precision (64-bit) floating-point elements from memory +// into result using `mask` (elements are zeroed out when the high bit of the +// corresponding element is not set). +@(require_results, enable_target_feature="sse2,avx") +_mm_maskload_pd :: #force_inline proc "c" (mem_addr: ^f64, mask: __m128i) -> __m128d { + mask_mask := intrinsics.simd_shr(mask, 63) + return intrinsics.simd_masked_load(mem_addr, _mm_setzero_pd(), mask_mask) +} + +// Stores packed double-precision (64-bit) floating-point elements from `a` +// into memory using `mask`. +@(enable_target_feature="avx") +_mm_maskstore_pd :: #force_inline proc "c" (mem_addr: ^f64, mask: __m128i, a: __m128d) { + mask_mask := intrinsics.simd_shr(mask, 63) + intrinsics.simd_masked_store(mem_addr, a, mask_mask) +} + +// Loads packed single-precision (32-bit) floating-point elements from memory +// into result using `mask` (elements are zeroed out when the high bit of the +// corresponding element is not set). +@(require_results, enable_target_feature="avx") +_mm256_maskload_ps :: #force_inline proc "c" (mem_addr: ^f32, mask: __m256i) -> __m256 { + mask_mask := intrinsics.simd_shr(transmute(#simd[8]i32)mask, 31) + return intrinsics.simd_masked_load(mem_addr, _mm256_setzero_ps(), mask_mask) +} + +// Stores packed single-precision (32-bit) floating-point elements from `a` +// into memory using `mask`. +@(enable_target_feature="avx") +_mm256_maskstore_ps :: #force_inline proc "c" (mem_addr: ^f32, mask: __m256i, a: __m256) { + mask_mask := intrinsics.simd_shr(transmute(#simd[8]i32)mask, 31) + intrinsics.simd_masked_store(mem_addr, a, mask_mask) +} + +// Loads packed single-precision (32-bit) floating-point elements from memory +// into result using `mask` (elements are zeroed out when the high bit of the +// corresponding element is not set). +@(require_results, enable_target_feature="sse,avx") +_mm_maskload_ps :: #force_inline proc "c" (mem_addr: ^f32, mask: __m128i) -> __m128 { + mask_mask := intrinsics.simd_shr(transmute(#simd[4]i32)mask, 31) + return intrinsics.simd_masked_load(mem_addr, _mm_setzero_ps(), mask_mask) +} + +// Stores packed single-precision (32-bit) floating-point elements from `a` +// into memory using `mask`. +@(enable_target_feature="avx") +_mm_maskstore_ps :: #force_inline proc "c" (mem_addr: ^f32, mask: __m128i, a: __m128) { + mask_mask := intrinsics.simd_shr(transmute(#simd[4]i32)mask, 31) + intrinsics.simd_masked_store(mem_addr, a, mask_mask) +} + + + + +// Duplicate odd-indexed single-precision (32-bit) floating-point elements from `a`, and returns the results. +@(require_results, enable_target_feature="avx") +_mm256_movehdup_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return intrinsics.simd_shuffle(a, a, 1, 1, 3, 3, 5, 5, 7, 7) +} + +// Duplicate even-indexed single-precision (32-bit) floating-point elements from `a`, and returns the results. +@(require_results, enable_target_feature="avx") +_mm256_moveldup_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return intrinsics.simd_shuffle(a, a, 0, 0, 2, 2, 4, 4, 6, 6) +} + +// Duplicate even-indexed double-precision (64-bit) floating-point elements from `a`, and returns the results. +@(require_results, enable_target_feature="avx") +_mm256_movedup_pd :: #force_inline proc "c" (a: __m256d) -> __m256d { + return intrinsics.simd_shuffle(a, a, 0, 0, 2, 2) +} + + +// Loads 256-bits of integer data from unaligned memory into result. +// This intrinsic may perform better than `_mm256_loadu_si256` when the +// data crosses a cache line boundary. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_lddqu_si256) +@(require_results, enable_target_feature="avx") +_mm256_lddqu_si256 :: #force_inline proc "c" (mem_addr: ^__m256i) -> __m256i { + return transmute(__m256i)llvm_vlddqu(mem_addr) +} + +/* +// Moves integer data from a 256-bit integer vector to a 32-byte +// aligned memory location. To minimize caching, the data is flagged as +// non-temporal (unlikely to be used again soon) +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_stream_si256) +// +// # Safety of non-temporal stores +// +// After using this intrinsic, but before any other access to the memory that this intrinsic +// mutates, a call to [`_mm_sfence`] must be performed by the thread that used the intrinsic. In +// particular, functions that call this intrinsic should generally call `_mm_sfence` before they +// return. +// +// See [`_mm_sfence`] for details. +@(enable_target_feature="avx") +_mm256_stream_si256 :: #force_inline proc "c" (mem_addr: ^__m256i, a: __m256i) { + panic_contextless("TODO: _mm256_stream_si256") +} + +// Moves double-precision values from a 256-bit vector of `[4 x double]` +// to a 32-byte aligned memory location. To minimize caching, the data is +// flagged as non-temporal (unlikely to be used again soon). +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_stream_pd) +// +// # Safety of non-temporal stores +// +// After using this intrinsic, but before any other access to the memory that this intrinsic +// mutates, a call to [`_mm_sfence`] must be performed by the thread that used the intrinsic. In +// particular, functions that call this intrinsic should generally call `_mm_sfence` before they +// return. +// +// See [`_mm_sfence`] for details. +@(enable_target_feature="avx") +_mm256_stream_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m256d) { + panic_contextless("TODO: _mm256_stream_pd") +} + +// Moves single-precision floating point values from a 256-bit vector +// of `[8 x float]` to a 32-byte aligned memory location. To minimize +// caching, the data is flagged as non-temporal (unlikely to be used again +// soon). +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_stream_ps) +// +// # Safety of non-temporal stores +// +// After using this intrinsic, but before any other access to the memory that this intrinsic +// mutates, a call to [`_mm_sfence`] must be performed by the thread that used the intrinsic. In +// particular, functions that call this intrinsic should generally call `_mm_sfence` before they +// return. +// +// See [`_mm_sfence`] for details. +@(enable_target_feature="avx") +_mm256_stream_ps :: #force_inline proc "c" (mem_addr: ^f32, a: __m256) { + panic_contextless("TODO: _mm256_stream_ps") +} +*/ + +// Computes the approximate reciprocal of packed single-precision (32-bit) floating-point elements in `a`, and returns the results. The maximum +// relative error for this approximation is less than 1.5*2^-12. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_rcp_ps) +@(require_results, enable_target_feature="avx") +_mm256_rcp_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return llvm_vrcpps(a) +} + +// Computes the approximate reciprocal square root of packed single-precision +// (32-bit) floating-point elements in `a`, and returns the results. +// The maximum relative error for this approximation is less than 1.5*2^-12. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_rsqrt_ps) +@(require_results, enable_target_feature="avx") +_mm256_rsqrt_ps :: #force_inline proc "c" (a: __m256) -> __m256 { + return llvm_vrsqrtps(a) +} + + + +// Unpacks and interleave double-precision (64-bit) floating-point elements +// from the high half of each 128-bit lane in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_unpackhi_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_shuffle(a, b, 1, 5, 3, 7) +} + +// Unpacks and interleave single-precision (32-bit) floating-point elements +// from the high half of each 128-bit lane in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_unpackhi_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_shuffle(a, b, 2, 10, 3, 11, 6, 14, 7, 15) +} + +// Unpacks and interleave double-precision (64-bit) floating-point elements +// from the low half of each 128-bit lane in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_unpacklo_pd :: #force_inline proc "c" (a, b: __m256d) -> __m256d { + return intrinsics.simd_shuffle(a, b, 0, 4, 2, 6) +} + +// Unpacks and interleave single-precision (32-bit) floating-point elements +// from the low half of each 128-bit lane in `a` and `b`. +@(require_results, enable_target_feature="avx") +_mm256_unpacklo_ps :: #force_inline proc "c" (a, b: __m256) -> __m256 { + return intrinsics.simd_shuffle(a, b, 0, 8, 1, 9, 4, 12, 5, 13) +} + +// Computes the bitwise AND of 256 bits (representing integer data) in `a` and +// `b`, and set `ZF` to 1 if the result is zero, otherwise set `ZF` to 0. +// Computes the bitwise NOT of `a` and then AND with `b`, and set `CF` to 1 if +// the result is zero, otherwise set `CF` to 0. Return the `ZF` value. +@(require_results, enable_target_feature="avx") +_mm256_testz_si256 :: #force_inline proc "c" (a, b: __m256i) -> i32 { + r := intrinsics.simd_bit_and(a, b) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + +// Computes the bitwise AND of 256 bits (representing integer data) in `a` and +// `b`, and set `ZF` to 1 if the result is zero, otherwise set `ZF` to 0. +// Computes the bitwise NOT of `a` and then AND with `b`, and set `CF` to 1 if +// the result is zero, otherwise set `CF` to 0. Return the `CF` value. +@(require_results, enable_target_feature="avx") +_mm256_testc_si256 :: #force_inline proc "c" (a, b: __m256i) -> i32 { + r := intrinsics.simd_bit_and(intrinsics.simd_bit_xor(a, __m256i(~i64(0))), b) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + + + +// Computes the bitwise AND of 256 bits (representing integer data) in `a` and +// `b`, and set `ZF` to 1 if the result is zero, otherwise set `ZF` to 0. +// Computes the bitwise NOT of `a` and then AND with `b`, and set `CF` to 1 if +// the result is zero, otherwise set `CF` to 0. Return 1 if both the `ZF` and +// `CF` values are zero, otherwise return 0. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testnzc_si256) +@(require_results, enable_target_feature="avx") +_mm256_testnzc_si256 :: #force_inline proc "c" (a, b: __m256i) -> i32 { + return llvm_ptestnzc256(a, b) +} + +// Computes the bitwise AND of 256 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `ZF` value. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testz_pd) +@(require_results, enable_target_feature="avx") +_mm256_testz_pd :: #force_inline proc "c" (a, b: __m256d) -> i32 { + return llvm_vtestzpd256(a, b) +} + +// Computes the bitwise AND of 256 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `CF` value. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testc_pd) +@(require_results, enable_target_feature="avx") +_mm256_testc_pd :: #force_inline proc "c" (a, b: __m256d) -> i32 { + return llvm_vtestcpd256(a, b) +} + +// Computes the bitwise AND of 256 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return 1 if both the `ZF` and `CF` values +// are zero, otherwise return 0. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testnzc_pd) +@(require_results, enable_target_feature="avx") +_mm256_testnzc_pd :: #force_inline proc "c" (a, b: __m256d) -> i32 { + return llvm_vtestnzcpd256(a, b) +} + +// Computes the bitwise AND of 128 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `ZF` value. +@(require_results, enable_target_feature="sse2,avx") +_mm_testz_pd :: #force_inline proc "c" (a, b: __m128d) -> i32 { + r := intrinsics.simd_lanes_lt(transmute(__m128i)_mm_and_pd(a, b), __m128i(0)) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + +// Computes the bitwise AND of 128 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `CF` value. +@(require_results, enable_target_feature="sse2,avx") +_mm_testc_pd :: #force_inline proc "c" (a, b: __m128d) -> i32 { + r := intrinsics.simd_lanes_lt(transmute(__m128i)_mm_andnot_pd(a, b), __m128i(0)) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + +// Computes the bitwise AND of 128 bits (representing double-precision (64-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 64-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 64-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return 1 if both the `ZF` and `CF` values +// are zero, otherwise return 0. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_testnzc_pd) +@(require_results, enable_target_feature="avx") +_mm_testnzc_pd :: #force_inline proc "c" (a, b: __m128d) -> i32 { + return llvm_vtestnzcpd(a, b) +} + +// Computes the bitwise AND of 256 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `ZF` value. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testz_ps) +@(require_results, enable_target_feature="avx") +_mm256_testz_ps :: #force_inline proc "c" (a, b: __m256) -> i32 { + return llvm_vtestzps256(a, b) +} + +// Computes the bitwise AND of 256 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `CF` value. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testc_ps) +@(require_results, enable_target_feature="avx") +_mm256_testc_ps :: #force_inline proc "c" (a, b: __m256) -> i32 { + return llvm_vtestcps256(a, b) +} + +// Computes the bitwise AND of 256 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 256-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return 1 if both the `ZF` and `CF` values +// are zero, otherwise return 0. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testnzc_ps) +@(require_results, enable_target_feature="avx") +_mm256_testnzc_ps :: #force_inline proc "c" (a, b: __m256) -> i32 { + return llvm_vtestnzcps256(a, b) +} + +// Computes the bitwise AND of 128 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `ZF` value. +@(require_results, enable_target_feature="sse,avx") +_mm_testz_ps :: #force_inline proc "c" (a: __m128, b: __m128) -> i32 { + r := intrinsics.simd_lanes_lt(transmute(#simd[4]i32)_mm_and_ps(a, b), (#simd[4]i32)(0)) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + +// Computes the bitwise AND of 128 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return the `CF` value. +@(require_results, enable_target_feature="sse,avx") +_mm_testc_ps :: #force_inline proc "c" (a: __m128, b: __m128) -> i32 { + r := intrinsics.simd_lanes_lt(transmute(#simd[4]i32)_mm_andnot_ps(a, b), (#simd[4]i32)(0)) + return i32(0 == intrinsics.simd_reduce_or(r)) +} + +// Computes the bitwise AND of 128 bits (representing single-precision (32-bit) floating-point elements) in `a` and `b`, producing an intermediate 128-bit +// value, and set `ZF` to 1 if the sign bit of each 32-bit element in the +// intermediate value is zero, otherwise set `ZF` to 0. Compute the bitwise +// NOT of `a` and then AND with `b`, producing an intermediate value, and set +// `CF` to 1 if the sign bit of each 32-bit element in the intermediate value +// is zero, otherwise set `CF` to 0. Return 1 if both the `ZF` and `CF` values +// are zero, otherwise return 0. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_testnzc_ps) +@(require_results, enable_target_feature="avx") +_mm_testnzc_ps :: #force_inline proc "c" (a: __m128, b: __m128) -> i32 { + return llvm_vtestnzcps(a, b) +} + +// Sets each bit of the returned mask based on the most significant bit of the +// corresponding packed double-precision (64-bit) floating-point element in +// `a`. +@(require_results, enable_target_feature="avx") +_mm256_movemask_pd :: #force_inline proc "c" (a: __m256d) -> i32 { + mask := intrinsics.simd_lanes_lt(transmute(#simd[4]i64)a, (#simd[4]i64)(0)) + return i32(transmute(u8)intrinsics.simd_extract_lsbs(mask)) +} + +// Sets each bit of the returned mask based on the most significant bit of the +// corresponding packed single-precision (32-bit) floating-point element in +// `a`. +@(require_results, enable_target_feature="avx") +_mm256_movemask_ps :: #force_inline proc "c" (a: __m256) -> i32 { + // Propagate the highest bit to the rest, because simd_bitmask + // requires all-1 or all-0. + mask := intrinsics.simd_lanes_lt(transmute(#simd[8]i32)a, (#simd[8]i32)(0)) + return i32(transmute(u8)intrinsics.simd_extract_lsbs(mask)) +} + +// Returns vector of type __m256d with all elements set to zero. +@(require_results, enable_target_feature="avx") +_mm256_setzero_pd :: #force_inline proc "c" () -> __m256d { + return 0 +} + +// Returns vector of type __m256 with all elements set to zero. +@(require_results, enable_target_feature="avx") +_mm256_setzero_ps :: #force_inline proc "c" () -> __m256 { + return 0 +} + +// Returns vector of type __m256i with all elements set to zero. +@(require_results, enable_target_feature="avx") +_mm256_setzero_si256 :: #force_inline proc "c" () -> __m256i { + return 0 +} + +// Sets packed double-precision (64-bit) floating-point elements in returned +// vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_pd :: #force_inline proc "c" (a: f64, b: f64, c: f64, d: f64) -> __m256d { + return _mm256_setr_pd(d, c, b, a) +} + +// Sets packed single-precision (32-bit) floating-point elements in returned +// vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_ps :: #force_inline proc "c" ( + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, + g: f32, + h: f32, +) -> __m256 { + return _mm256_setr_ps(h, g, f, e, d, c, b, a) +} + +// Sets packed 8-bit integers in returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_epi8 :: #force_inline proc "c" ( + e00, e01, e02, e03, e04, e05, e06, e07: i8, + e08, e09, e10, e11, e12, e13, e14, e15: i8, + e16, e17, e18, e19, e20, e21, e22, e23: i8, + e24, e25, e26, e27, e28, e29, e30, e31: i8, +) -> __m256i { + return _mm256_setr_epi8( + e31, e30, e29, e28, e27, e26, e25, e24, + e23, e22, e21, e20, e19, e18, e17, e16, + e15, e14, e13, e12, e11, e10, e09, e08, + e07, e06, e05, e04, e03, e02, e01, e00, + ) +} + +// Sets packed 16-bit integers in returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_epi16 :: #force_inline proc "c" ( + e00, e01, e02, e03, e04, e05, e06, e07: i16, + e08, e09, e10, e11, e12, e13, e14, e15: i16, +) -> __m256i { + return _mm256_setr_epi16( + e15, e14, e13, e12, + e11, e10, e09, e08, + e07, e06, e05, e04, + e03, e02, e01, e00, + ) +} + +// Sets packed 32-bit integers in returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_epi32 :: #force_inline proc "c" (e0, e1, e2, e3, e4, e5, e6, e7: i32) -> __m256i { + return _mm256_setr_epi32(e7, e6, e5, e4, e3, e2, e1, e0) +} + +// Sets packed 64-bit integers in returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_epi64x :: #force_inline proc "c" (a: i64, b: i64, c: i64, d: i64) -> __m256i { + return _mm256_setr_epi64x(d, c, b, a) +} + +// Sets packed double-precision (64-bit) floating-point elements in returned +// vector with the supplied values in reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_pd :: #force_inline proc "c" (a: f64, b: f64, c: f64, d: f64) -> __m256d { + return __m256d{a, b, c, d} +} + +// Sets packed single-precision (32-bit) floating-point elements in returned +// vector with the supplied values in reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_ps :: #force_inline proc "c" (a, b, c, d, e, f, g, h: f32) -> __m256 { + return __m256{a, b, c, d, e, f, g, h} +} + +// Sets packed 8-bit integers in returned vector with the supplied values in +// reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_epi8 :: #force_inline proc "c" ( + e00, e01, e02, e03, e04, e05, e06, e07: i8, + e08, e09, e10, e11, e12, e13, e14, e15: i8, + e16, e17, e18, e19, e20, e21, e22, e23: i8, + e24, e25, e26, e27, e28, e29, e30, e31: i8, +) -> __m256i { + return transmute(__m256i)#simd[32]i8{ + e00, e01, e02, e03, e04, e05, e06, e07, + e08, e09, e10, e11, e12, e13, e14, e15, + e16, e17, e18, e19, e20, e21, e22, e23, + e24, e25, e26, e27, e28, e29, e30, e31, + } +} + +// Sets packed 16-bit integers in returned vector with the supplied values in +// reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_epi16 :: #force_inline proc "c" ( + e00, e01, e02, e03, e04, e05, e06, e07: i16, + e08, e09, e10, e11, e12, e13, e14, e15: i16, +) -> __m256i { + return transmute(__m256i)#simd[16]i16{ + e00, e01, e02, e03, + e04, e05, e06, e07, + e08, e09, e10, e11, + e12, e13, e14, e15, + } +} + +// Sets packed 32-bit integers in returned vector with the supplied values in +// reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_epi32 :: #force_inline proc "c" (e0, e1, e2, e3, e4, e5, e6, e7: i32) -> __m256i { + return transmute(__m256i)#simd[8]i32{e0, e1, e2, e3, e4, e5, e6, e7} +} + +// Sets packed 64-bit integers in returned vector with the supplied values in +// reverse order. +@(require_results, enable_target_feature="avx") +_mm256_setr_epi64x :: #force_inline proc "c" (a: i64, b: i64, c: i64, d: i64) -> __m256i { + return {a, b, c, d} +} + +// Broadcasts double-precision (64-bit) floating-point value `a` to all elements of returned vector. +@(require_results, enable_target_feature="avx") +_mm256_set1_pd :: #force_inline proc "c" (a: f64) -> __m256d { + return a +} + +// Broadcasts single-precision (32-bit) floating-point value `a` to all elements of returned vector. +@(require_results, enable_target_feature="avx") +_mm256_set1_ps :: #force_inline proc "c" (a: f32) -> __m256 { + return a +} + +// Broadcasts 8-bit integer `a` to all elements of returned vector. +// This intrinsic may generate the `vpbroadcastb`. +@(require_results, enable_target_feature="avx") +_mm256_set1_epi8 :: #force_inline proc "c" (a: i8) -> __m256i { + return transmute(__m256i)(#simd[32]i8)(a) +} + +// Broadcasts 16-bit integer `a` to all elements of returned vector. +// This intrinsic may generate the `vpbroadcastw`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_set1_epi16) +@(require_results, enable_target_feature="avx") +_mm256_set1_epi16 :: #force_inline proc "c" (a: i16) -> __m256i { + return transmute(__m256i)(#simd[16]i16)(a) +} + +// Broadcasts 32-bit integer `a` to all elements of returned vector. +// This intrinsic may generate the `vpbroadcastd`. +@(require_results, enable_target_feature="avx") +_mm256_set1_epi32 :: #force_inline proc "c" (a: i32) -> __m256i { + return transmute(__m256i)(#simd[8]i32)(a) +} + +// Broadcasts 64-bit integer `a` to all elements of returned vector. +// This intrinsic may generate the `vpbroadcastq`. +// +// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_set1_epi64x) +@(require_results, enable_target_feature="avx") +_mm256_set1_epi64x :: #force_inline proc "c" (a: i64) -> __m256i { + return a +} + +// Cast vector of type __m256d to type __m256. +@(require_results, enable_target_feature="avx") +_mm256_castpd_ps :: #force_inline proc "c" (a: __m256d) -> __m256 { + return transmute(__m256)a +} + +// Cast vector of type __m256 to type __m256d. +@(require_results, enable_target_feature="avx") +_mm256_castps_pd :: #force_inline proc "c" (a: __m256) -> __m256d { + return transmute(__m256d)a +} + +// Casts vector of type __m256 to type __m256i. +@(require_results, enable_target_feature="avx") +_mm256_castps_si256 :: #force_inline proc "c" (a: __m256) -> __m256i { + return transmute(__m256i)a +} + +// Casts vector of type __m256i to type __m256. +@(require_results, enable_target_feature="avx") +_mm256_castsi256_ps :: #force_inline proc "c" (a: __m256i) -> __m256 { + return transmute(__m256)a +} + +// Casts vector of type __m256d to type __m256i. +@(require_results, enable_target_feature="avx") +_mm256_castpd_si256 :: #force_inline proc "c" (a: __m256d) -> __m256i { + return transmute(__m256i)a +} + +// Casts vector of type __m256i to type __m256d. +@(require_results, enable_target_feature="avx") +_mm256_castsi256_pd :: #force_inline proc "c" (a: __m256i) -> __m256d { + return transmute(__m256d)a +} + +// Casts vector of type __m256 to type __m128. +@(require_results, enable_target_feature="avx") +_mm256_castps256_ps128 :: #force_inline proc "c" (a: __m256) -> __m128 { + return intrinsics.simd_shuffle(a, a, 0, 1, 2, 3) +} + +// Casts vector of type __m256d to type __m128d. +@(require_results, enable_target_feature="avx") +_mm256_castpd256_pd128 :: #force_inline proc "c" (a: __m256d) -> __m128d { + return intrinsics.simd_shuffle(a, a, 0, 1) +} + +// Casts vector of type __m256i to type __m128i. +@(require_results, enable_target_feature="avx") +_mm256_castsi256_si128 :: #force_inline proc "c" (a: __m256i) -> __m128i { + return intrinsics.simd_shuffle(a, a, 0, 1) +} + +// Casts vector of type __m128 to type __m256; +// the upper 128 bits of the result are indeterminate. +// +// In the Intel documentation, the upper bits are declared to be "undefined". +@(require_results, enable_target_feature="sse,avx") +_mm256_castps128_ps256 :: #force_inline proc "c" (a: __m128) -> __m256 { + return intrinsics.simd_shuffle(a, _mm_undefined_ps(), 0, 1, 2, 3, 4, 4, 4, 4) +} + +// Casts vector of type __m128d to type __m256d; +// the upper 128 bits of the result are indeterminate. +// +// In the Intel documentation, the upper bits are declared to be "undefined". +@(require_results, enable_target_feature="sse2,avx") +_mm256_castpd128_pd256 :: #force_inline proc "c" (a: __m128d) -> __m256d { + return intrinsics.simd_shuffle(a, _mm_undefined_pd(), 0, 1, 2, 2) +} + +// Casts vector of type __m128i to type __m256i; +// the upper 128 bits of the result are indeterminate. +// +// In the Intel documentation, the upper bits are declared to be "undefined". +@(require_results, enable_target_feature="avx") +_mm256_castsi128_si256 :: #force_inline proc "c" (a: __m128i) -> __m256i { + return intrinsics.simd_shuffle(a, __m128i(0), 0, 1, 2, 2) +} + +// Constructs a 256-bit floating-point vector of `[8 x float]` from a +// 128-bit floating-point vector of `[4 x float]`. The lower 128 bits contain +// the value of the source vector. The upper 128 bits are set to zero. +@(require_results, enable_target_feature="sse,avx") +_mm256_zextps128_ps256 :: #force_inline proc "c" (a: __m128) -> __m256 { + return intrinsics.simd_shuffle(a, _mm_setzero_ps(), 0, 1, 2, 3, 4, 5, 6, 7) +} + +// Constructs a 256-bit integer vector from a 128-bit integer vector. +// The lower 128 bits contain the value of the source vector. The upper +// 128 bits are set to zero. +@(require_results, enable_target_feature="avx") +_mm256_zextsi128_si256 :: #force_inline proc "c" (a: __m128i) -> __m256i { + return intrinsics.simd_shuffle(a, __m128i(0), 0, 1, 2, 3) +} + +// Constructs a 256-bit floating-point vector of `[4 x double]` from a +// 128-bit floating-point vector of `[2 x double]`. The lower 128 bits +// contain the value of the source vector. The upper 128 bits are set +// to zero. +@(require_results, enable_target_feature="sse2,avx") +_mm256_zextpd128_pd256 :: #force_inline proc "c" (a: __m128d) -> __m256d { + return intrinsics.simd_shuffle(a, _mm_setzero_pd(), 0, 1, 2, 3) +} + +// Returns vector of type `__m256` with indeterminate elements. +// Despite using the word "undefined" (following Intel's naming scheme), this non-deterministically +@(require_results, enable_target_feature="avx") +_mm256_undefined_ps :: #force_inline proc "c" () -> __m256 { + return 0 +} + +// Returns vector of type `__m256d` with indeterminate elements. +// Despite using the word "undefined" (following Intel's naming scheme), this non-deterministically +@(require_results, enable_target_feature="avx") +_mm256_undefined_pd :: #force_inline proc "c" () -> __m256d { + return 0 +} + +// Returns vector of type __m256i with with indeterminate elements. +// Despite using the word "undefined" (following Intel's naming scheme), this non-deterministically +@(require_results, enable_target_feature="avx") +_mm256_undefined_si256 :: #force_inline proc "c" () -> __m256i { + return 0 +} + +// Sets packed __m256 returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_m128 :: #force_inline proc "c" (hi: __m128, lo: __m128) -> __m256 { + return intrinsics.simd_shuffle(lo, hi, 0, 1, 2, 3, 4, 5, 6, 7) +} + +// Sets packed __m256d returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_m128d :: #force_inline proc "c" (hi: __m128d, lo: __m128d) -> __m256d { + hi := transmute(__m128)hi + lo := transmute(__m128)lo + return transmute(__m256d)_mm256_set_m128(hi, lo) +} + +// Sets packed __m256i returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_set_m128i :: #force_inline proc "c" (hi: __m128i, lo: __m128i) -> __m256i { + hi := transmute(__m128)hi + lo := transmute(__m128)lo + return transmute(__m256i)_mm256_set_m128(hi, lo) +} + +// Sets packed __m256 returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_setr_m128 :: #force_inline proc "c" (lo: __m128, hi: __m128) -> __m256 { + return _mm256_set_m128(hi, lo) +} + +// Sets packed __m256d returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_setr_m128d :: #force_inline proc "c" (lo: __m128d, hi: __m128d) -> __m256d { + return _mm256_set_m128d(hi, lo) +} + +// Sets packed __m256i returned vector with the supplied values. +@(require_results, enable_target_feature="avx") +_mm256_setr_m128i :: #force_inline proc "c" (lo: __m128i, hi: __m128i) -> __m256i { + return _mm256_set_m128i(hi, lo) +} + +// Loads two 128-bit values (composed of 4 packed single-precision (32-bit) floating-point elements) from memory, and combine them into a 256-bit value. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(require_results, enable_target_feature="sse,avx") +_mm256_loadu2_m128 :: #force_inline proc "c" (hiaddr, loaddr: ^f32) -> __m256 { + a := _mm256_castps128_ps256(_mm_loadu_ps(loaddr)) + return _mm256_insertf128_ps(a, _mm_loadu_ps(hiaddr), 1) +} + +// Loads two 128-bit values (composed of 2 packed double-precision (64-bit) floating-point elements) from memory, and combine them into a 256-bit value. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(require_results, enable_target_feature="sse2,avx") +_mm256_loadu2_m128d :: #force_inline proc "c" (hiaddr, loaddr: ^f64) -> __m256d { + a := _mm256_castpd128_pd256(_mm_loadu_pd(loaddr)) + return _mm256_insertf128_pd(a, _mm_loadu_pd(hiaddr), 1) +} + +// Loads two 128-bit values (composed of integer data) from memory, and combine them into a 256-bit value. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(require_results, enable_target_feature="sse2,avx") +_mm256_loadu2_m128i :: #force_inline proc "c" (hiaddr, loaddr: ^__m128i) -> __m256i { + a := _mm256_castsi128_si256(_mm_loadu_si128(loaddr)) + return _mm256_insertf128_si256(a, _mm_loadu_si128(hiaddr), 1) +} + +// Stores the high and low 128-bit halves (each composed of 4 packed +// single-precision (32-bit) floating-point elements) from `a` into memory two +// different 128-bit locations. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(enable_target_feature="sse,avx") +_mm256_storeu2_m128 :: #force_inline proc "c" (hiaddr, loaddr: ^f32, a: __m256) { + lo := _mm256_castps256_ps128(a) + _mm_storeu_ps(loaddr, lo) + hi := _mm256_extractf128_ps(a, 1) + _mm_storeu_ps(hiaddr, hi) +} + +// Stores the high and low 128-bit halves (each composed of 2 packed +// double-precision (64-bit) floating-point elements) from `a` into memory two +// different 128-bit locations. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(enable_target_feature="sse2,avx") +_mm256_storeu2_m128d :: #force_inline proc "c" (hiaddr, loaddr: ^f64, a: __m256d) { + lo := _mm256_castpd256_pd128(a) + _mm_storeu_pd(loaddr, lo) + hi := _mm256_extractf128_pd(a, 1) + _mm_storeu_pd(hiaddr, hi) +} + +// Stores the high and low 128-bit halves (each composed of integer data) from +// `a` into memory two different 128-bit locations. +// `hiaddr` and `loaddr` do not need to be aligned on any particular boundary. +@(enable_target_feature="sse2,avx") +_mm256_storeu2_m128i :: #force_inline proc "c" (hiaddr, loaddr: ^__m128i, a: __m256i) { + lo := _mm256_castsi256_si128(a) + _mm_storeu_si128(loaddr, lo) + hi := _mm256_extractf128_si256(a, 1) + _mm_storeu_si128(hiaddr, hi) +} + +// Returns the first element of the input vector of `[8 x float]`. +@(require_results, enable_target_feature="avx") +_mm256_cvtss_f32 :: #force_inline proc "c" (a: __m256) -> f32 { + return intrinsics.simd_extract(a, 0) +} + + + +@(require_results, enable_target_feature="avx") +_mm256_insert_epi64 :: #force_inline proc "c" (a: __m256i, i: i64, $idx: u32) -> __m256i { + return intrinsics.simd_replace(transmute(#simd[4]i64)a, idx, i) +} + +@(require_results, enable_target_feature="avx") +_mm256_extract_epi64 :: #force_inline proc "c" (a: __m256i, $idx: u32) -> i64 { + return intrinsics.simd_extract(transmute(#simd[4]i64)a, idx) +} + + +@(private, default_calling_convention="none") +foreign _ { + @(link_name="llvm.x86.avx.round.pd.256") llvm_roundpd256 :: proc(a: __m256d, #const b: u32) -> __m256d --- + @(link_name="llvm.x86.avx.round.ps.256") llvm_roundps256 :: proc(a: __m256, #const b: u32) -> __m256 --- + @(link_name="llvm.x86.avx.dp.ps.256") llvm_vdpps :: proc(a, b: __m256, #const imm8: u8) -> __m256 --- + @(link_name="llvm.x86.sse2.cmp.pd") llvm_vcmppd :: proc(a, b: __m128d, #const imm8: u8) -> __m128d --- + @(link_name="llvm.x86.avx.cmp.pd.256") llvm_vcmppd256 :: proc(a, b: __m256d, imm8: u8) -> __m256d --- + @(link_name="llvm.x86.sse.cmp.ps") llvm_vcmpps :: proc(a: __m128, b: __m128, #const imm8: u8) -> __m128 --- + @(link_name="llvm.x86.avx.cmp.ps.256") llvm_vcmpps256 :: proc(a, b: __m256, imm8: u8) -> __m256 --- + @(link_name="llvm.x86.sse2.cmp.sd") llvm_vcmpsd :: proc(a, b: __m128d, #const imm8: u8) -> __m128d --- + @(link_name="llvm.x86.sse.cmp.ss") llvm_vcmpss :: proc(a: __m128, b: __m128, #const imm8: u8) -> __m128 --- + @(link_name="llvm.x86.avx.cvt.ps2dq.256") llvm_vcvtps2dq :: proc(a: __m256) -> #simd[8]i32 --- + @(link_name="llvm.x86.avx.cvtt.pd2dq.256") llvm_vcvttpd2dq :: proc(a: __m256d) -> #simd[4]i32 --- + @(link_name="llvm.x86.avx.cvt.pd2dq.256") llvm_vcvtpd2dq :: proc(a: __m256d) -> #simd[4]i32 --- + @(link_name="llvm.x86.avx.cvtt.ps2dq.256") llvm_vcvttps2dq :: proc(a: __m256) -> #simd[8]i32 --- + @(link_name="llvm.x86.avx.vzeroall") llvm_vzeroall :: proc() --- + @(link_name="llvm.x86.avx.vzeroupper") llvm_vzeroupper :: proc() --- + @(link_name="llvm.x86.avx.vpermilvar.ps.256") llvm_vpermilps256 :: proc(a: __m256, b: #simd[8]i32) -> __m256 --- + @(link_name="llvm.x86.avx.vpermilvar.ps") llvm_vpermilps :: proc(a: __m128, b: #simd[4]i32) -> __m128 --- + @(link_name="llvm.x86.avx.vpermilvar.pd.256") llvm_vpermilpd256 :: proc(a: __m256d, b: #simd[4]i64) -> __m256d --- + @(link_name="llvm.x86.avx.vpermilvar.pd") llvm_vpermilpd :: proc(a: __m128d, b: #simd[2]i64) -> __m128d --- + @(link_name="llvm.x86.avx.ldu.dq.256") llvm_vlddqu :: proc(mem_addr: rawptr) -> #simd[32]i8 --- + @(link_name="llvm.x86.avx.rcp.ps.256") llvm_vrcpps :: proc(a: __m256) -> __m256 --- + @(link_name="llvm.x86.avx.rsqrt.ps.256") llvm_vrsqrtps :: proc(a: __m256) -> __m256 --- + @(link_name="llvm.x86.avx.ptestnzc.256") llvm_ptestnzc256 :: proc(a: #simd[4]i64, b: #simd[4]i64) -> i32 --- + @(link_name="llvm.x86.avx.vtestz.pd.256") llvm_vtestzpd256 :: proc(a, b: __m256d) -> i32 --- + @(link_name="llvm.x86.avx.vtestc.pd.256") llvm_vtestcpd256 :: proc(a, b: __m256d) -> i32 --- + @(link_name="llvm.x86.avx.vtestnzc.pd.256") llvm_vtestnzcpd256 :: proc(a, b: __m256d) -> i32 --- + @(link_name="llvm.x86.avx.vtestnzc.pd") llvm_vtestnzcpd :: proc(a, b: __m128d) -> i32 --- + @(link_name="llvm.x86.avx.vtestz.ps.256") llvm_vtestzps256 :: proc(a, b: __m256) -> i32 --- + @(link_name="llvm.x86.avx.vtestc.ps.256") llvm_vtestcps256 :: proc(a, b: __m256) -> i32 --- + @(link_name="llvm.x86.avx.vtestnzc.ps.256") llvm_vtestnzcps256 :: proc(a, b: __m256) -> i32 --- + @(link_name="llvm.x86.avx.vtestnzc.ps") llvm_vtestnzcps :: proc(a: __m128, b: __m128) -> i32 --- + @(link_name="llvm.x86.avx.min.ps.256") llvm_vminps :: proc(a, b: __m256) -> __m256 --- + @(link_name="llvm.x86.avx.max.ps.256") llvm_vmaxps :: proc(a, b: __m256) -> __m256 --- + @(link_name="llvm.x86.avx.min.pd.256") llvm_vminpd :: proc(a, b: __m256d) -> __m256d --- + @(link_name="llvm.x86.avx.max.pd.256") llvm_vmaxpd :: proc(a, b: __m256d) -> __m256d --- +} diff --git a/core/simd/x86/doc.odin b/core/simd/x86/doc.odin new file mode 100644 index 000000000..dcdc30abd --- /dev/null +++ b/core/simd/x86/doc.odin @@ -0,0 +1,2 @@ +// `SIMD` intrinsics specific to the Intel `x86` and `AMD64` architectures. +package simd_x86 \ No newline at end of file diff --git a/core/simd/x86/sse41.odin b/core/simd/x86/sse41.odin index 81089ed63..510f5d8e9 100644 --- a/core/simd/x86/sse41.odin +++ b/core/simd/x86/sse41.odin @@ -26,7 +26,18 @@ _mm_blendv_epi8 :: #force_inline proc "c" (a, b, mask: __m128i) -> __m128i { } @(require_results, enable_target_feature="sse4.1") _mm_blend_epi16 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i { - return transmute(__m128i)pblendw(transmute(i16x8)a, transmute(i16x8)b, IMM8) + return transmute(__m128i)simd.shuffle( + transmute(i16x8)b, + transmute(i16x8)a, + 0 when (IMM8 >> 0) & 1 == 1 else 8, + 1 when (IMM8 >> 1) & 1 == 1 else 9, + 2 when (IMM8 >> 2) & 1 == 1 else 10, + 3 when (IMM8 >> 3) & 1 == 1 else 11, + 4 when (IMM8 >> 4) & 1 == 1 else 12, + 5 when (IMM8 >> 5) & 1 == 1 else 13, + 6 when (IMM8 >> 6) & 1 == 1 else 14, + 7 when (IMM8 >> 7) & 1 == 1 else 15, + ) } @(require_results, enable_target_feature="sse4.1") _mm_blendv_pd :: #force_inline proc "c" (a, b, mask: __m128d) -> __m128d { @@ -303,8 +314,6 @@ foreign _ { blendpd :: proc(a, b: __m128d, #const imm2: u8) -> __m128d --- @(link_name = "llvm.x86.sse41.blendps") blendps :: proc(a, b: __m128, #const imm4: u8) -> __m128 --- - @(link_name = "llvm.x86.sse41.pblendw") - pblendw :: proc(a: i16x8, b: i16x8, #const imm8: u8) -> i16x8 --- @(link_name = "llvm.x86.sse41.insertps") insertps :: proc(a, b: __m128, #const imm8: u8) -> __m128 --- @(link_name = "llvm.x86.sse41.pmaxsb") diff --git a/core/simd/x86/types.odin b/core/simd/x86/types.odin index ea0eff534..1b52f22f1 100644 --- a/core/simd/x86/types.odin +++ b/core/simd/x86/types.odin @@ -22,25 +22,25 @@ __m256bh :: #simd[16]bf16 __m512bh :: #simd[32]bf16 -/// The `__mmask64` type used in AVX-512 intrinsics, a 64-bit integer +// The `__mmask64` type used in AVX-512 intrinsics, a 64-bit integer __mmask64 :: u64 -/// The `__mmask32` type used in AVX-512 intrinsics, a 32-bit integer +// The `__mmask32` type used in AVX-512 intrinsics, a 32-bit integer __mmask32 :: u32 -/// The `__mmask16` type used in AVX-512 intrinsics, a 16-bit integer +// The `__mmask16` type used in AVX-512 intrinsics, a 16-bit integer __mmask16 :: u16 -/// The `__mmask8` type used in AVX-512 intrinsics, a 8-bit integer +// The `__mmask8` type used in AVX-512 intrinsics, a 8-bit integer __mmask8 :: u8 -/// The `_MM_CMPINT_ENUM` type used to specify comparison operations in AVX-512 intrinsics. +// The `_MM_CMPINT_ENUM` type used to specify comparison operations in AVX-512 intrinsics. _MM_CMPINT_ENUM :: i32 -/// The `MM_MANTISSA_NORM_ENUM` type used to specify mantissa normalized operations in AVX-512 intrinsics. +// The `MM_MANTISSA_NORM_ENUM` type used to specify mantissa normalized operations in AVX-512 intrinsics. _MM_MANTISSA_NORM_ENUM :: i32 -/// The `MM_MANTISSA_SIGN_ENUM` type used to specify mantissa signed operations in AVX-512 intrinsics. +// The `MM_MANTISSA_SIGN_ENUM` type used to specify mantissa signed operations in AVX-512 intrinsics. _MM_MANTISSA_SIGN_ENUM :: i32 _MM_PERM_ENUM :: i32 diff --git a/core/slice/heap/heap.odin b/core/slice/heap/heap.odin index 7480a1673..de6dfb43b 100644 --- a/core/slice/heap/heap.odin +++ b/core/slice/heap/heap.odin @@ -1,14 +1,14 @@ +// A generic in-place max heap on a slice for any type. +package heap + /* Copyright 2022 Dale Weiler . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Dale Weiler: Initial implementation */ -// Package implements a generic max heap in-place on a slice for any type. -package heap - /* Constructs a max heap in slice given by data with comparator. A max heap is a range of elements which has the following properties: diff --git a/core/slice/map.odin b/core/slice/map.odin index c68488d26..fafbb55ee 100644 --- a/core/slice/map.odin +++ b/core/slice/map.odin @@ -6,8 +6,8 @@ import "base:runtime" _ :: intrinsics _ :: runtime -map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K, err: runtime.Allocator_Error) { - keys = make(type_of(keys), len(m), allocator) or_return +map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator, loc := #caller_location) -> (keys: []K, err: runtime.Allocator_Error) { + keys = make(type_of(keys), len(m), allocator, loc) or_return i := 0 for key in m { keys[i] = key @@ -15,8 +15,8 @@ map_keys :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (keys: []K, } return } -map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (values: []V, err: runtime.Allocator_Error) { - values = make(type_of(values), len(m), allocator) or_return +map_values :: proc(m: $M/map[$K]$V, allocator := context.allocator, loc := #caller_location) -> (values: []V, err: runtime.Allocator_Error) { + values = make(type_of(values), len(m), allocator, loc) or_return i := 0 for _, value in m { values[i] = value @@ -37,8 +37,8 @@ Map_Entry_Info :: struct($Key, $Value: typeid) { } -map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry(K, V), err: runtime.Allocator_Error) { - entries = make(type_of(entries), len(m), allocator) or_return +map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator, loc := #caller_location) -> (entries: []Map_Entry(K, V), err: runtime.Allocator_Error) { + entries = make(type_of(entries), len(m), allocator, loc) or_return i := 0 for key, value in m { entries[i].key = key @@ -48,13 +48,13 @@ map_entries :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries return } -map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator) -> (entries: []Map_Entry_Info(K, V), err: runtime.Allocator_Error) #no_bounds_check { +map_entry_infos :: proc(m: $M/map[$K]$V, allocator := context.allocator, loc := #caller_location) -> (entries: []Map_Entry_Info(K, V), err: runtime.Allocator_Error) #no_bounds_check { m := m rm := (^runtime.Raw_Map)(&m) info := runtime.type_info_base(type_info_of(M)).variant.(runtime.Type_Info_Map) if info.map_info != nil { - entries = make(type_of(entries), len(m), allocator) or_return + entries = make(type_of(entries), len(m), allocator, loc) or_return map_cap := uintptr(cap(m)) ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(rm^, info.map_info) diff --git a/core/slice/permute.odin b/core/slice/permute.odin index 42b6d4129..280989e47 100644 --- a/core/slice/permute.odin +++ b/core/slice/permute.odin @@ -29,12 +29,13 @@ Returns: make_permutation_iterator :: proc( slice: []$T, allocator := context.allocator, + loc := #caller_location, ) -> ( iter: Permutation_Iterator(T), error: runtime.Allocator_Error, ) #optional_allocator_error { iter.slice = slice - iter.counters = make([]int, len(iter.slice), allocator) or_return + iter.counters = make([]int, len(iter.slice), allocator, loc) or_return return } diff --git a/core/slice/ptr.odin b/core/slice/ptr.odin index 99d4157c3..b52853375 100644 --- a/core/slice/ptr.odin +++ b/core/slice/ptr.odin @@ -3,14 +3,14 @@ package slice import "base:builtin" import "base:runtime" -ptr_add :: proc(p: $P/^$T, x: int) -> ^T { +ptr_add :: proc "contextless" (p: $P/^$T, x: int) -> ^T { return ([^]T)(p)[x:] } -ptr_sub :: proc(p: $P/^$T, x: int) -> ^T { +ptr_sub :: proc "contextless" (p: $P/^$T, x: int) -> ^T { return ([^]T)(p)[-x:] } -ptr_swap_non_overlapping :: proc(x, y: rawptr, len: int) { +ptr_swap_non_overlapping :: proc "contextless" (x, y: rawptr, len: int) { if len <= 0 { return } @@ -44,7 +44,7 @@ ptr_swap_non_overlapping :: proc(x, y: rawptr, len: int) { } } -ptr_swap_overlapping :: proc(x, y: rawptr, len: int) { +ptr_swap_overlapping :: proc "contextless" (x, y: rawptr, len: int) { if len <= 0 { return } @@ -68,7 +68,7 @@ ptr_swap_overlapping :: proc(x, y: rawptr, len: int) { } -ptr_rotate :: proc(left: int, mid: ^$T, right: int) { +ptr_rotate :: proc "contextless" (left: int, mid: ^$T, right: int) { when size_of(T) != 0 { left, mid, right := left, mid, right diff --git a/core/slice/slice.odin b/core/slice/slice.odin index c328fd267..8485af145 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -1,13 +1,12 @@ +// Utility procedures for working with slices, including sorting and searching them. package slice import "base:intrinsics" import "base:builtin" -import "core:math/bits" import "base:runtime" _ :: intrinsics _ :: builtin -_ :: bits _ :: runtime /* @@ -40,7 +39,7 @@ to_bytes :: proc "contextless" (s: []$T) -> []byte { Turns a byte slice into a type. */ @(require_results) -to_type :: proc(buf: []u8, $T: typeid) -> (T, bool) #optional_ok { +to_type :: proc "contextless" (buf: []u8, $T: typeid) -> (T, bool) #optional_ok { if len(buf) < size_of(T) { return {}, false } @@ -104,7 +103,7 @@ swap :: proc(array: $T/[]$E, a, b: int) { } } -swap_between :: proc(a, b: $T/[]$E) { +swap_between :: proc "contextless" (a, b: $T/[]$E) #no_bounds_check { n := builtin.min(len(a), len(b)) if n >= 0 { ptr_swap_overlapping(&a[0], &b[0], size_of(E)*n) @@ -121,7 +120,7 @@ reverse :: proc(array: $T/[]$E) { @(require_results) -contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) { +contains :: proc "contextless" (array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) { _, found := linear_search(array, value) return found } @@ -155,7 +154,7 @@ Example: assert(index == 1 && found == true) */ @(require_results) -linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) +linear_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) where intrinsics.type_is_comparable(T) { for x, i in array { if x == key { @@ -218,7 +217,7 @@ Example: assert(index == 1 && found == true) */ @(require_results) -linear_search_reverse :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool) +linear_search_reverse :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) where intrinsics.type_is_comparable(T) { #reverse for x, i in array { if x == key { @@ -326,7 +325,7 @@ binary_search_by :: proc(array: $A/[]$T, key: $K, f: proc(T, K) -> Ordering) -> } @(require_results) -equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) #no_bounds_check { +equal :: proc "contextless" (a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) #no_bounds_check { if len(a) != len(b) { return false } @@ -354,7 +353,7 @@ equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) #no_ } @(require_results) -simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) { +simple_equal :: proc "contextless" (a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) { if len(a) != len(b) { return false } @@ -369,7 +368,7 @@ simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_comp slice.prefix_length([]u8{1, 2, 3, 4}, []u8{2, 3, 4}) -> 0 */ @(require_results) -prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) { +prefix_length :: proc "contextless" (a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) { _len := builtin.min(len(a), len(b)) #no_bounds_check for n < _len && a[n] == b[n] { @@ -379,7 +378,7 @@ prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_compar } @(require_results) -has_prefix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) { +has_prefix :: proc "contextless" (array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) { n := len(needle) if len(array) >= n { return equal(array[:n], needle) @@ -387,9 +386,28 @@ has_prefix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_c return false } +/* + return the suffix length common between slices `a` and `b`. + + slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3, 4}) -> 4 + slice.suffix_length([]u8{1, 2, 3, 4}, []u8{3, 4}) -> 2 + slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 0 + slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 3, 5}) -> 0 + slice.suffix_length([]u8{3, 4, 5}, []u8{3, 5}) -> 1 +*/ +@(require_results) +suffix_length :: proc "contextless" (a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) { + len_a, len_b := len(a), len(b) + _len := builtin.min(len_a, len_b) + + #no_bounds_check for i := 1; i <= _len && a[len_a - i] == b[len_b - i]; i += 1 { + n += 1 + } + return +} @(require_results) -has_suffix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) { +has_suffix :: proc "contextless" (array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_comparable(E) { array := array m, n := len(array), len(needle) if m >= n { @@ -398,13 +416,13 @@ has_suffix :: proc(array: $T/[]$E, needle: T) -> bool where intrinsics.type_is_c return false } -zero :: proc(array: $T/[]$E) #no_bounds_check { +zero :: proc "contextless" (array: $T/[]$E) #no_bounds_check { if len(array) > 0 { intrinsics.mem_zero(raw_data(array), size_of(E)*len(array)) } } -fill :: proc(array: $T/[]$E, value: E) #no_bounds_check { +fill :: proc "contextless" (array: $T/[]$E, value: E) #no_bounds_check { if len(array) <= 0 { return } @@ -414,7 +432,10 @@ fill :: proc(array: $T/[]$E, value: E) #no_bounds_check { } } -rotate_left :: proc(array: $T/[]$E, mid: int) { +rotate_left :: proc "contextless" (array: $T/[]$E, mid: int) { + if len(array) == 0 { + return + } n := len(array) m := mid %% n k := n - m @@ -423,7 +444,7 @@ rotate_left :: proc(array: $T/[]$E, mid: int) { p := cast(^E)raw_data(array) ptr_rotate(m, ptr_add(p, m), k) } -rotate_right :: proc(array: $T/[]$E, k: int) { +rotate_right :: proc "contextless" (array: $T/[]$E, k: int) { rotate_left(array, -k) } @@ -434,7 +455,7 @@ swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) { } @(require_results) -concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, err: runtime.Allocator_Error) #optional_allocator_error { +concatenate :: proc(a: []$T/[]$E, allocator := context.allocator, loc := #caller_location) -> (res: T, err: runtime.Allocator_Error) #optional_allocator_error { if len(a) == 0 { return } @@ -442,7 +463,7 @@ concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, er for s in a { n += len(s) } - res = make(T, n, allocator) or_return + res = make(T, n, allocator, loc) or_return i := 0 for s in a { i += copy(res[i:], s) @@ -460,6 +481,7 @@ clone :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_locatio // copies slice into a new dynamic array +@(require_results) clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> ([dynamic]E, runtime.Allocator_Error) #optional_allocator_error { d, err := make([dynamic]E, len(a), allocator, loc) copy(d[:], a) @@ -482,11 +504,11 @@ into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E { @(require_results) -length :: proc(a: $T/[]$E) -> int { +length :: proc "contextless" (a: $T/[]$E) -> int { return len(a) } @(require_results) -is_empty :: proc(a: $T/[]$E) -> bool { +is_empty :: proc "contextless" (a: $T/[]$E) -> bool { return len(a) == 0 } @@ -540,16 +562,16 @@ last_ptr :: proc(array: $T/[]$E) -> ^E { } @(require_results) -get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) { - if uint(index) < len(array) { +get :: proc "contextless" (array: $T/[]$E, index: int) -> (value: E, ok: bool) { + #bounds_check if uint(index) < len(array) { value = array[index] ok = true } return } @(require_results) -get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) { - if uint(index) < len(array) { +get_ptr :: proc "contextless" (array: $T/[]$E, index: int) -> (value: ^E, ok: bool) { + #no_bounds_check if uint(index) < len(array) { value = &array[index] ok = true } @@ -557,14 +579,14 @@ get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) { } @(require_results) -as_ptr :: proc(array: $T/[]$E) -> [^]E { +as_ptr :: proc "contextless" (array: $T/[]$E) -> [^]E { return raw_data(array) } @(require_results) -mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> (r: []V, err: runtime.Allocator_Error) #optional_allocator_error { - r = make([]V, len(s), allocator) or_return +mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator, loc := #caller_location) -> (r: []V, err: runtime.Allocator_Error) #optional_allocator_error { + r = make([]V, len(s), allocator, loc) or_return for v, i in s { r[i] = f(v) } @@ -590,33 +612,33 @@ reduce_reverse :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V { } @(require_results) -filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { - r := make([dynamic]U, 0, 0, allocator) or_return +filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator, loc := #caller_location) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { + r := make([dynamic]U, 0, 0, allocator, loc) or_return for v in s { if f(v) { - append(&r, v) + append(&r, v, loc) } } return r[:], nil } @(require_results) -filter_reverse :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { - r := make([dynamic]U, 0, 0, allocator) or_return +filter_reverse :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator, loc := #caller_location) -> (res: S, err: runtime.Allocator_Error) #optional_allocator_error { + r := make([dynamic]U, 0, 0, allocator, loc) or_return for i := len(s)-1; i >= 0; i -= 1 { #no_bounds_check v := s[i] if f(v) { - append(&r, v) + append(&r, v, loc) } } return r[:], nil } @(require_results) -scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> (res: []V, err: runtime.Allocator_Error) #optional_allocator_error { +scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator, loc := #caller_location) -> (res: []V, err: runtime.Allocator_Error) #optional_allocator_error { if len(s) == 0 { return } - res = make([]V, len(s), allocator) or_return + res = make([]V, len(s), allocator, loc) or_return p := as_ptr(s) q := as_ptr(res) r := initializer @@ -633,14 +655,14 @@ scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := c @(require_results) -repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator) -> (b: S, err: runtime.Allocator_Error) #optional_allocator_error { +repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator, loc := #caller_location) -> (b: S, err: runtime.Allocator_Error) #optional_allocator_error { if count < 0 { panic("slice: negative repeat count") } else if count > 0 && (len(s)*count)/count != len(s) { panic("slice: repeat count will cause an overflow") } - b = make(S, len(s)*count, allocator) or_return + b = make(S, len(s)*count, allocator, loc) or_return i := copy(b, s) for i < len(b) { // 2^N trick to reduce the need to copy copy(b[i:], b[:i]) @@ -652,7 +674,7 @@ repeat :: proc(s: $S/[]$U, count: int, allocator := context.allocator) -> (b: S, // 'unique' replaces consecutive runs of equal elements with a single copy. // The procedures modifies the slice in-place and returns the modified slice. @(require_results) -unique :: proc(s: $S/[]$T) -> S where intrinsics.type_is_comparable(T) #no_bounds_check { +unique :: proc "contextless" (s: $S/[]$T) -> S where intrinsics.type_is_comparable(T) #no_bounds_check { if len(s) < 2 { return s } @@ -691,7 +713,7 @@ unique_proc :: proc(s: $S/[]$T, eq: proc(T, T) -> bool) -> S #no_bounds_check { @(require_results) -min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { +min :: proc "contextless" (s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) != 0 { res = s[0] ok = true @@ -702,7 +724,7 @@ min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T return } @(require_results) -max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { +max :: proc "contextless" (s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) != 0 { res = s[0] ok = true @@ -714,7 +736,7 @@ max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T } @(require_results) -min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ordered(T) { +min_max :: proc "contextless" (s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ordered(T) { if len(s) != 0 { min, max = s[0], s[0] ok = true @@ -728,7 +750,7 @@ min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ // Find the index of the (first) minimum element in a slice. @(require_results) -min_index :: proc(s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { +min_index :: proc "contextless" (s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) == 0 { return -1, false } @@ -745,7 +767,7 @@ min_index :: proc(s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.typ // Find the index of the (first) maximum element in a slice. @(require_results) -max_index :: proc(s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { +max_index :: proc "contextless" (s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok { if len(s) == 0 { return -1, false } @@ -761,7 +783,7 @@ max_index :: proc(s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.typ } @(require_results) -any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { +any_of :: proc "contextless" (s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { for v in s { if v == value { return true @@ -771,7 +793,7 @@ any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable } @(require_results) -none_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { +none_of :: proc "contextless" (s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { for v in s { if v == value { return false @@ -781,7 +803,7 @@ none_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparabl } @(require_results) -all_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { +all_of :: proc "contextless" (s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) { if len(s) == 0 { return false } @@ -829,7 +851,7 @@ all_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool { @(require_results) -count :: proc(s: $S/[]$T, value: T) -> (n: int) where intrinsics.type_is_comparable(T) { +count :: proc "contextless" (s: $S/[]$T, value: T) -> (n: int) where intrinsics.type_is_comparable(T) { for v in s { if v == value { n += 1 @@ -850,7 +872,7 @@ count_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> (n: int) { @(require_results) -dot_product :: proc(a, b: $S/[]$T) -> (r: T, ok: bool) +dot_product :: proc "contextless" (a, b: $S/[]$T) -> (r: T, ok: bool) where intrinsics.type_is_numeric(T) { if len(a) != len(b) { return @@ -864,7 +886,7 @@ dot_product :: proc(a, b: $S/[]$T) -> (r: T, ok: bool) // Convert a pointer to an enumerated array to a slice of the element type @(require_results) -enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T) +enumerated_array :: proc "contextless" (ptr: ^$T) -> []intrinsics.type_elem_type(T) where intrinsics.type_is_enumerated_array(T) { return ([^]intrinsics.type_elem_type(T))(ptr)[:len(T)] } @@ -873,7 +895,7 @@ enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T) // e.g.: // bs := slice.enum_slice_to_bitset(my_flag_slice, rl.ConfigFlags) @(require_results) -enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { +enum_slice_to_bitset :: proc "contextless" (enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { for v in enums { bits += {v} } @@ -897,9 +919,45 @@ bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) wher // e.g.: // sl := slice.bitset_to_enum_slice(bs) @(require_results) -bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid, allocator := context.allocator) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { - buf := make([]E, card(bs), allocator) +bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid, allocator := context.allocator, loc := #caller_location) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { + buf := make([]E, card(bs), allocator, loc) return bitset_to_enum_slice(buf, bs) } bitset_to_enum_slice :: proc{bitset_to_enum_slice_with_make, bitset_to_enum_slice_with_buffer} + +/* +Removes the first n elements (`elems`) from a slice of slices, spanning inner slices and dropping empty ones. + +If `elems` is out of bounds (more than the total) this will trigger a bounds check. + +Example: + import "core:fmt" + import "core:slice" + + advance_slices_example :: proc() { + slices := [][]byte { + {1, 2, 3, 4}, + {5, 6, 7}, + } + + fmt.println(slice.advance_slices(slices, 4)) + } + +Output: + [[5, 6, 7]] +*/ +advance_slices :: proc(slices: $S/[][]$T, elems: int) -> S { + slices, elems := slices, elems + for elems > 0 { + slice := &slices[0] + take := builtin.min(elems, len(slice)) + slice^ = slice[take:] + if len(slice) == 0 { + slices = slices[1:] + } + elems -= take + } + + return slices +} diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 3b4119afa..ed9d1f315 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -6,6 +6,8 @@ Ordering :: enum { Greater = +1, } +Generic_Cmp :: #type proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering + @(require_results) cmp :: proc(a, b: $E) -> Ordering where ORD(E) { switch { @@ -35,7 +37,16 @@ cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) { sort :: proc(data: $T/[]$E) where ORD(E) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered) + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + x, y := (^E)(lhs)^, (^E)(rhs)^ + if x < y { + return .Less + } else if x > y { + return .Greater + } + return .Equal + }, nil) } } } @@ -43,9 +54,9 @@ sort :: proc(data: $T/[]$E) where ORD(E) { sort_by_indices :: proc{ sort_by_indices_allocate, _sort_by_indices} -sort_by_indices_allocate :: proc(data: $T/[]$E, indices: []int, allocator := context.allocator) -> (sorted: T) { +sort_by_indices_allocate :: proc(data: $T/[]$E, indices: []int, allocator := context.allocator, loc := #caller_location) -> (sorted: T) { assert(len(data) == len(indices)) - sorted = make(T, len(data), allocator) + sorted = make(T, len(data), allocator, loc) for v, i in indices { sorted[i] = data[v] } @@ -70,16 +81,48 @@ sort_by_indices_overwrite :: proc(data: $T/[]$E, indices: []int) { swap_with_slice(data, temp) } +sort_from_permutation_indices :: proc(data: $T/[]$E, indices: []int) { + assert(len(data) == len(indices)) + if len(indices) <= 1 { + return + } + + for i in 0.. (indices: []int) where ORD(E) { - indices = make([]int, len(data), allocator) +sort_with_indices :: proc(data: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (indices: []int) where ORD(E) { + indices = make([]int, len(data), allocator, loc) when size_of(E) != 0 { if n := len(data); n > 1 { for _, idx in indices { indices[idx] = idx } - _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), struct{}{}, .Ordered) + + raw := ([^]byte)(raw_data(indices)) + _smoothsort(raw, uint(len(indices)), size_of(int), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + data := ([^]E)(user_data) + + xi, yi := (^int)(lhs)^, (^int)(rhs)^ + #no_bounds_check x, y := data[xi], data[yi] + if x < y { + return .Less + } else if x > y { + return .Greater + } + return .Equal + }, raw_data(data)) + + sort_from_permutation_indices(data, indices) } return indices } @@ -91,22 +134,105 @@ sort_with_indices :: proc(data: $T/[]$E, allocator := context.allocator) -> (ind sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_general(data, 0, n, _max_depth(n), less, .Less) + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + x, y := (^E)(lhs)^, (^E)(rhs)^ + less := (proc(E, E) -> bool)(user_data) + switch { + case less(x, y): return .Less + case less(y, x): return .Greater + } + return .Equal + }, rawptr(less)) + } + } +} + +sort_by_with_data :: proc(data: $T/[]$E, less: proc(i, j: E, user_data: rawptr) -> bool, user_data: rawptr) { + when size_of(E) != 0 { + if n := len(data); n > 1 { + Context :: struct { + less: proc(i, j: E, user_data: rawptr) -> bool, + user_data: rawptr, + } + ctx := &Context{less, user_data} + + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + x, y := (^E)(lhs)^, (^E)(rhs)^ + ctx := (^Context)(user_data) + switch { + case ctx.less(x, y, ctx.user_data): return .Less + case ctx.less(y, x, ctx.user_data): return .Greater + } + return .Equal + }, ctx) } } } // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" // This sort is not guaranteed to be stable -sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocator := context.allocator) -> (indices : []int) { - indices = make([]int, len(data), allocator) +sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocator := context.allocator, loc := #caller_location) -> (indices : []int) { + indices = make([]int, len(data), allocator, loc) when size_of(E) != 0 { if n := len(data); n > 1 { for _, idx in indices { indices[idx] = idx } - _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), less, .Less) - return indices + + Context :: struct{ + less: proc(i, j: E) -> bool, + data: T, + } + ctx := &Context{less, data} + + raw := ([^]byte)(raw_data(indices)) + _smoothsort(raw, uint(len(indices)), size_of(int), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + ctx := (^Context)(user_data) + xi, yi := (^int)(lhs)^, (^int)(rhs)^ + x, y := ctx.data[xi], ctx.data[yi] + switch { + case ctx.less(x, y): return .Less + case ctx.less(y, x): return .Greater + } + return .Equal + }, ctx) + + sort_from_permutation_indices(data, indices) + } + } + return indices +} + +sort_by_with_indices_with_data :: proc(data: $T/[]$E, less: proc(i, j: E, user_data: rawptr) -> bool, user_data: rawptr, allocator := context.allocator, loc := #caller_location) -> (indices : []int) { + indices = make([]int, len(data), allocator, loc) + when size_of(E) != 0 { + if n := len(data); n > 1 { + for _, idx in indices { + indices[idx] = idx + } + + Context :: struct{ + less: proc(i, j: E, user_data: rawptr) -> bool, + data: T, + user_data: rawptr, + } + ctx := &Context{less, data, user_data} + + raw := ([^]byte)(raw_data(indices)) + _smoothsort(raw, uint(len(indices)), size_of(int), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + ctx := (^Context)(user_data) + xi, yi := (^int)(lhs)^, (^int)(rhs)^ + x, y := ctx.data[xi], ctx.data[yi] + switch { + case ctx.less(x, y, ctx.user_data): return .Less + case ctx.less(y, x, ctx.user_data): return .Greater + } + return .Equal + }, ctx) + + sort_from_permutation_indices(data, indices) } } return indices @@ -115,12 +241,50 @@ sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocat sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { when size_of(E) != 0 { if n := len(data); n > 1 { - _quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp) + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + x, y := (^E)(lhs)^, (^E)(rhs)^ + cmp := cast(proc(E, E) -> Ordering)(user_data) + return cmp(x, y) + }, rawptr(cmp)) } } } -// stable_sort sorts a slice + +sort_by_cmp_with_data :: proc(data: $T/[]$E, cmp: proc(i, j: E, user_data: rawptr) -> Ordering, user_data: rawptr) { + when size_of(E) != 0 { + if n := len(data); n > 1 { + Context :: struct{ + cmp: proc(i, j: E, user_data: rawptr) -> Ordering, + user_data: rawptr, + } + ctx := &Context{cmp, user_data} + + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + x, y := (^E)(lhs)^, (^E)(rhs)^ + ctx := (^Context)(user_data) + return ctx.cmp(x, y, ctx.user_data) + }, ctx) + } + } +} + + +sort_by_generic_cmp :: proc(data: $T/[]$E, cmp: Generic_Cmp, user_data: rawptr) { + when size_of(E) != 0 { + if n := len(data); n > 1 { + raw := ([^]byte)(raw_data(data)) + _smoothsort(raw, uint(len(data)), size_of(E), cmp, user_data) + } + } +} + + +/* +Sorts a slice while maintaining the relative order of elements with the same key. For an example see either `stable_sort_by` or `stable_sort_by_cmp`. +*/ stable_sort :: proc(data: $T/[]$E) where ORD(E) { when size_of(E) != 0 { if n := len(data); n > 1 { @@ -129,7 +293,33 @@ stable_sort :: proc(data: $T/[]$E) where ORD(E) { } } -// stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" +/* +Sorts a slice while maintaining the relative order of elements with the same key. Two items `i` and `j` are ordered if `less(i, j)` returns `true`. + +Example: + import "core:slice" + import "core:fmt" + + stable_sort_by_example :: proc() { + Example :: struct { n: int, s: string } + + arr := []Example { + {2, "name"}, + {3, "Bill"}, + {1, "My"}, + {2, "is"} + } + slice.stable_sort_by(arr, proc(i, j: Example) -> bool { + return i.n < j.n + }) + + for e in arr do fmt.printf("%s ", e.s) + fmt.println() + } + +Output: + My name is Bill +*/ stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { when size_of(E) != 0 { if n := len(data); n > 1 { @@ -138,6 +328,34 @@ stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { } } + +/* +Sorts a slice while maintaining the relative order of elements with the same key. The ordering of the any two items is defined by the user-provided `cmp`. + +Example: + import "core:slice" + import "core:fmt" + + stable_sort_by_cmp_example :: proc() { + Example :: struct { n: int, s: string } + + arr := []Example { + {2, "name"}, + {3, "Bill"}, + {1, "My"}, + {2, "is"} + } + slice.stable_sort_by_cmp(arr, proc(i, j: Example) -> slice.Ordering { + return slice.cmp(i.n, j.n) + }) + + for e in arr do fmt.printf("%s ", e.s) + fmt.println() + } + +Output: + My name is Bill +*/ stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { when size_of(E) != 0 { if n := len(data); n > 1 { @@ -188,37 +406,59 @@ reverse_sort :: proc(data: $T/[]$E) where ORD(E) { reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { - context._internal = rawptr(less) - sort_by(data, proc(i, j: E) -> bool { - k := (proc(i, j: E) -> bool)(context._internal) - return k(j, i) - }) + sort_by_with_data(data, proc(i, j: E, user_data: rawptr) -> bool { + less := (proc(E, E) -> bool)(user_data) + return less(j, i) + }, rawptr(less)) } reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { - context._internal = rawptr(cmp) - sort_by_cmp(data, proc(i, j: E) -> Ordering { - k := (proc(i, j: E) -> Ordering)(context._internal) + sort_by_cmp_with_data(data, proc(i, j: E, user_data: rawptr) -> Ordering { + k := (proc(i, j: E) -> Ordering)(user_data) return k(j, i) - }) + }, rawptr(cmp)) } // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough? sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) { - context._internal = rawptr(key) - sort_by(data, proc(i, j: E) -> bool { - k := (proc(E) -> K)(context._internal) - return k(i) < k(j) - }) + Context :: struct { + key: proc(E) -> K, + } + ctx := &Context{key} + + sort_by_generic_cmp(data, proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + i, j := (^E)(lhs)^, (^E)(rhs)^ + + ctx := (^Context)(user_data) + a := ctx.key(i) + b := ctx.key(j) + switch { + case a < b: return .Less + case a > b: return .Greater + } + return .Equal + }, ctx) } reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) { - context._internal = rawptr(key) - sort_by(data, proc(i, j: E) -> bool { - k := (proc(E) -> K)(context._internal) - return k(j) < k(i) - }) + Context :: struct { + key: proc(E) -> K, + } + ctx := &Context{key} + + sort_by_generic_cmp(data, proc(lhs, rhs: rawptr, user_data: rawptr) -> Ordering { + i, j := (^E)(lhs)^, (^E)(rhs)^ + + ctx := (^Context)(user_data) + a := ctx.key(i) + b := ctx.key(j) + switch { + case a < b: return .Greater + case a > b: return .Less + } + return .Equal + }, ctx) } @(require_results) @@ -230,11 +470,3 @@ is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K } return true } - -@(private, require_results) -_max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1)) - for i := n; i > 0; i >>= 1 { - depth += 1 - } - return depth * 2 -} diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin index 36637c4cd..efa9c596b 100644 --- a/core/slice/sort_private.odin +++ b/core/slice/sort_private.odin @@ -1,6 +1,7 @@ #+private package slice +import "base:builtin" import "base:intrinsics" _ :: intrinsics @@ -12,171 +13,6 @@ Sort_Kind :: enum { Cmp, } -_quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check { - less :: #force_inline proc(a, b: E, call: P) -> bool { - when KIND == .Ordered { - return a < b - } else when KIND == .Less { - return call(a, b) - } else when KIND == .Cmp { - return call(a, b) == .Less - } else { - #panic("unhandled Sort_Kind") - } - } - - insertion_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check { - for i in a+1.. a && less(data[j], data[j-1], call); j -= 1 { - swap(data, j, j-1) - } - } - } - - heap_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check { - sift_down :: proc(data: T, lo, hi, first: int, call: P) #no_bounds_check { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && less(data[first+child], data[first+child+1], call) { - child += 1 - } - if !less(data[first+root], data[first+child], call) { - return - } - swap(data, first+root, first+child) - root = child - } - } - - - first, lo, hi := a, 0, b-a - - for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(data, i, hi, first, call) - } - - for i := hi-1; i >= 0; i -= 1 { - swap(data, first, first+i) - sift_down(data, lo, i, first, call) - } - } - - median3 :: proc(data: T, m1, m0, m2: int, call: P) #no_bounds_check { - if less(data[m1], data[m0], call) { - swap(data, m1, m0) - } - if less(data[m2], data[m1], call) { - swap(data, m2, m1) - if less(data[m1], data[m0], call) { - swap(data, m1, m0) - } - } - } - - do_pivot :: proc(data: T, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check { - m := int(uint(lo+hi)>>1) - if hi-lo > 40 { - s := (hi-lo)/8 - median3(data, lo, lo+s, lo+s*2, call) - median3(data, m, m-s, m+s, call) - median3(data, hi-1, hi-1-s, hi-1-s*2, call) - } - median3(data, lo, m, hi-1, call) - - pivot := lo - a, c := lo+1, hi-1 - - - for ; a < c && less(data[a], data[pivot], call); a += 1 { - } - b := a - - for { - for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot - } - for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot - } - if b >= c { - break - } - - swap(data, b, c-1) - b += 1 - c -= 1 - } - - protect := hi-c < 5 - if !protect && hi-c < (hi-lo)/4 { - dups := 0 - if !less(data[pivot], data[hi-1], call) { - swap(data, c, hi-1) - c += 1 - dups += 1 - } - if !less(data[b-1], data[pivot], call) { - b -= 1 - dups += 1 - } - - if !less(data[m], data[pivot], call) { - swap(data, m, b-1) - b -= 1 - dups += 1 - } - protect = dups > 1 - } - if protect { - for { - for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 { - } - for ; a < b && less(data[a], data[pivot], call); a += 1 { - } - if a >= b { - break - } - swap(data, a, b-1) - a += 1 - b -= 1 - } - } - swap(data, pivot, b-1) - return b-1, c - } - - - a, b, max_depth := a, b, max_depth - - for b-a > 12 { // only use shell sort for lengths <= 12 - if max_depth == 0 { - heap_sort(data, a, b, call) - return - } - max_depth -= 1 - mlo, mhi := do_pivot(data, a, b, call) - if mlo-a < b-mhi { - _quick_sort_general(data, a, mlo, max_depth, call, KIND) - a = mhi - } else { - _quick_sort_general(data, mhi, b, max_depth, call, KIND) - b = mlo - } - } - if b-a > 1 { - // Shell short with gap 6 - for i in a+6.. bool { when KIND == .Ordered { @@ -200,179 +36,181 @@ _stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (O } } -_quick_sort_general_with_indices :: proc(data: $T/[]$E, indices: []int, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check { - less :: #force_inline proc(a, b: E, call: P) -> bool { - when KIND == .Ordered { - return a < b - } else when KIND == .Less { - return call(a, b) - } else when KIND == .Cmp { - return call(a, b) == .Less - } else { - #panic("unhandled Sort_Kind") +@(private) +_smoothsort :: proc(base: [^]byte, nel: uint, width: uint, cmp: Generic_Cmp, arg: rawptr) { + pntz :: proc "contextless" (p: [2]uint) -> int { + r := intrinsics.count_trailing_zeros(p[0] - 1) + if r != 0 { + return int(r) } + r = (8*size_of(uint) + intrinsics.count_trailing_zeros(p[1])) + if r != 8*size_of(uint) { + return int(r) + } + return 0 } - insertion_sort :: proc(data: $T/[]$E, indices: []int, a, b: int, call: P) #no_bounds_check { - for i in a+1.. a && less(data[j], data[j-1], call); j -= 1 { - swap(data, j, j-1) - swap(indices, j, j-1) - } + shl :: proc "contextless" (p: []uint, n: int) { + n := n + if n >= 8*size_of(uint) { + n -= 8*size_of(uint) + p[1] = p[0] + p[0] = 0 } + p[1] <<= uint(n) + p[0] |= p[0] >> uint(8*size_of(uint) - n) + p[0] <<= uint(n) + } + shr :: proc "contextless" (p: []uint, n: int) { + n := n + if n >= 8*size_of(uint) { + n -= 8*size_of(uint) + p[0] = p[1] + p[1] = 0 + } + p[0] >>= uint(n) + p[0] |= p[1] << uint(8*size_of(uint) - n) + p[1] >>= uint(n) } - heap_sort :: proc(data: $T/[]$E, indices: []int, a, b: int, call: P) #no_bounds_check { - sift_down :: proc(data: T, indices: []int, lo, hi, first: int, call: P) #no_bounds_check { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && less(data[first+child], data[first+child+1], call) { - child += 1 - } - if !less(data[first+root], data[first+child], call) { - return - } - swap(data, first+root, first+child) - swap(indices, first+root, first+child) - root = child - } - } - - - first, lo, hi := a, 0, b-a - - for i := (hi-1)/2; i >= 0; i -= 1 { - sift_down(data, indices, i, hi, first, call) - } - - for i := hi-1; i >= 0; i -= 1 { - swap(data, first, first+i) - swap(indices, first, first+i) - sift_down(data, indices, lo, i, first, call) - } - } - - median3 :: proc(data: T, indices: []int, m1, m0, m2: int, call: P) #no_bounds_check { - if less(data[m1], data[m0], call) { - swap(data, m1, m0) - swap(indices, m1, m0) - } - if less(data[m2], data[m1], call) { - swap(data, m2, m1) - swap(indices, m2, m1) - if less(data[m1], data[m0], call) { - swap(data, m1, m0) - swap(indices, m1, m0) - } - } - } - - do_pivot :: proc(data: T, indices: []int, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check { - m := int(uint(lo+hi)>>1) - if hi-lo > 40 { - s := (hi-lo)/8 - median3(data, indices, lo, lo+s, lo+s*2, call) - median3(data, indices, m, m-s, m+s, call) - median3(data, indices, hi-1, hi-1-s, hi-1-s*2, call) - } - median3(data, indices, lo, m, hi-1, call) - - pivot := lo - a, c := lo+1, hi-1 - - - for ; a < c && less(data[a], data[pivot], call); a += 1 { - } - b := a - - for { - for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot - } - for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot - } - if b >= c { - break - } - - swap(data, b, c-1) - swap(indices, b, c-1) - b += 1 - c -= 1 - } - - protect := hi-c < 5 - if !protect && hi-c < (hi-lo)/4 { - dups := 0 - if !less(data[pivot], data[hi-1], call) { - swap(data, c, hi-1) - swap(indices, c, hi-1) - c += 1 - dups += 1 - } - if !less(data[b-1], data[pivot], call) { - b -= 1 - dups += 1 - } - - if !less(data[m], data[pivot], call) { - swap(data, m, b-1) - swap(indices, m, b-1) - b -= 1 - dups += 1 - } - protect = dups > 1 - } - if protect { - for { - for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 { - } - for ; a < b && less(data[a], data[pivot], call); a += 1 { - } - if a >= b { - break - } - swap(data, a, b-1) - swap(indices, a, b-1) - a += 1 - b -= 1 - } - } - swap(data, pivot, b-1) - swap(indices, pivot, b-1) - return b-1, c - } - - assert(len(data) == len(indices)) - - a, b, max_depth := a, b, max_depth - - for b-a > 12 { // only use shell sort for lengths <= 12 - if max_depth == 0 { - heap_sort(data, indices, a, b, call) + cycle :: proc "contextless" (width: uint, data: [][^]byte, n: int) { + if len(data) < 2 { return } - max_depth -= 1 - mlo, mhi := do_pivot(data, indices, a, b, call) - if mlo-a < b-mhi { - _quick_sort_general_with_indices(data, indices, a, mlo, max_depth, call, KIND) - a = mhi - } else { - _quick_sort_general_with_indices(data, indices, mhi, b, max_depth, call, KIND) - b = mlo + buf: [256]u8 = --- + data[n] = raw_data(buf[:]) + width := width + for width != 0 { + l := builtin.min(size_of(buf), int(width)) + copy(data[n][:l], data[0][:l]) + for i in 0.. 1 { - // Shell short with gap 6 - for i in a+6.. 1 { + rt := head[-width:] + lf := head[-width:][-lp[pshift - 2]:] + if cmp(buf[0], lf, arg) >= .Equal && cmp(buf[0], rt, arg) >= .Equal { + break + } + if cmp(lf, rt, arg) >= .Equal { + buf[i], head = lf, lf + pshift -= 1 + } else { + buf[i], head = rt, rt + pshift -= 2 + } + i += 1 + } + cycle(width, buf[:], i) + } + + trinkle :: proc(head: [^]byte, width: uint, cmp: Generic_Cmp, arg: rawptr, pp: []uint, pshift: int, trusty: bool, lp: []uint) { + head := head + + p := [2]uint{pp[0], pp[1]} + + buf: [14*size_of(uint)+1][^]byte = --- + buf[0] = head + + i := 1 + trail := 0 + pshift := pshift + trusty := trusty + for p[0] != 1 || p[1] != 0 { + stepson := head[-lp[pshift]:] + if cmp(stepson, buf[0], arg) <= .Equal { + break + } + if !trusty && pshift > 1 { + rt := head[-width:] + lf := head[-width:][-lp[pshift-2]:] + if cmp(rt, stepson, arg) >= .Equal || cmp(lf, stepson, arg) >= .Equal { + break + } + } + buf[i] = stepson + head = stepson + trail = pntz(p) + shr(p[:], trail) + pshift += trail + trusty = false + i += 1 + } + if trusty { + return + } + cycle(width, buf[:], i) + sift(head, width, cmp, arg, pshift, lp) + } + + size := nel * width + if size == 0 { + return + } + + lp: [12*size_of(uint)]uint = --- + lp[1] = width + lp[0] = lp[1] + for i := 2; true; i += 1 { + lp[i] = lp[i-2] + lp[i-1] + width + if lp[i] >= size { + break + } + } + + head := base + high := head[size - width:] + p := [2]uint{1, 0} + pshift := 1 + for head < high { + if (p[0] & 3) == 3 { + sift(head, width, cmp, arg, pshift, lp[:]) + shr(p[:], 2) + pshift += 2 + } else { + if lp[pshift - 1] >= uint(uintptr(high) - uintptr(head)) { + trinkle(head, width, cmp, arg, p[:], pshift, false, lp[:]) + } else { + sift(head, width, cmp, arg, pshift, lp[:]) + } + if pshift == 1 { + shl(p[:], 1) + pshift = 0 + } else { + shl(p[:], pshift - 1) + pshift = 1 } } - insertion_sort(data, indices, a, b, call) + p[0] |= 1 + head = head[width:] } -} + trinkle(head, width, cmp, arg, p[:], pshift, false, lp[:]) + for pshift != 1 || p[0] != 1 || p[1] != 0 { + if pshift <= 1 { + trail := pntz(p) + shr(p[:], trail) + pshift += trail + } else { + shl(p[:], 2) + pshift -= 2 + p[0] ~= 7 + shr(p[:], 1) + trinkle(head[-width:][-lp[pshift]:], width, cmp, arg, p[:], pshift + 1, true, lp[:]) + shl(p[:], 1) + p[0] |= 1 + trinkle(head[-width:], width, cmp, arg, p[:], pshift, true, lp[:]) + } + head = head[-width:] + } +} \ No newline at end of file diff --git a/core/sort/sort.odin b/core/sort/sort.odin index 322613cc4..30abc5336 100644 --- a/core/sort/sort.odin +++ b/core/sort/sort.odin @@ -1,11 +1,10 @@ +// A sorting interface and algorithms. package sort import "core:mem" -import _slice "core:slice" import "base:intrinsics" _ :: intrinsics -_ :: _slice ORD :: intrinsics.type_is_ordered Interface :: struct { @@ -30,14 +29,6 @@ sort :: proc(it: Interface) { _quick_sort(it, 0, n, max_depth(n)) } - -@(deprecated="use slice.sort") -slice :: proc(array: $T/[]$E) where ORD(E) { - _slice.sort(array) - // s := array; - // sort(slice_interface(&s)); -} - slice_interface :: proc(s: ^$T/[]$E) -> Interface where ORD(E) { return Interface{ collection = rawptr(s), @@ -80,31 +71,6 @@ reverse_sort :: proc(it: Interface) { sort(reverse_interface(&it)) } -@(deprecated="use slice.reverse") -reverse_slice :: proc(array: $T/[]$E) where ORD(E) { - _slice.reverse(array) - /* - s := array; - sort(Interface{ - collection = rawptr(&s), - len = proc(it: Interface) -> int { - s := (^T)(it.collection); - return len(s^); - }, - less = proc(it: Interface, i, j: int) -> bool { - s := (^T)(it.collection); - return s[j] < s[i]; // manual set up - }, - swap = proc(it: Interface, i, j: int) { - s := (^T)(it.collection); - s[i], s[j] = s[j], s[i]; - }, - }); - */ -} - - - is_sorted :: proc(it: Interface) -> bool { n := it->len() for i := n-1; i > 0; i -= 1 { @@ -294,11 +260,6 @@ _insertion_sort :: proc(it: Interface, a, b: int) { } } - - - - -// @(deprecated="use sort.sort or slice.sort_by") bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { assert(f != nil) count := len(array) @@ -327,7 +288,6 @@ bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { } } -// @(deprecated="use sort.sort_slice or slice.sort") bubble_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { count := len(array) @@ -355,7 +315,6 @@ bubble_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { } } -// @(deprecated="use sort.sort or slice.sort_by") quick_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { assert(f != nil) a := array @@ -384,7 +343,6 @@ quick_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { quick_sort_proc(a[i:n], f) } -// @(deprecated="use sort.sort_slice or slice.sort") quick_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { a := array n := len(a) @@ -420,7 +378,6 @@ _log2 :: proc(x: int) -> int { return res } -// @(deprecated="use sort.sort or slice.sort_by") merge_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { merge :: proc(a: A, start, mid, end: int, f: proc(T, T) -> int) { s, m := start, mid @@ -462,7 +419,6 @@ merge_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { internal_sort(array, 0, len(array)-1, f) } -// @(deprecated="use sort.sort_slice or slice.sort") merge_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { merge :: proc(a: A, start, mid, end: int) { s, m := start, mid @@ -504,8 +460,6 @@ merge_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { internal_sort(array, 0, len(array)-1) } - -// @(deprecated="use sort.sort or slice.sort_by") heap_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { sift_proc :: proc(a: A, pi: int, n: int, f: proc(T, T) -> int) #no_bounds_check { p := pi @@ -540,7 +494,6 @@ heap_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { } } -// @(deprecated="use sort.sort_slice or slice.sort") heap_sort :: proc(array: $A/[]$T) where intrinsics.type_is_ordered(T) { sift :: proc(a: A, pi: int, n: int) #no_bounds_check { p := pi @@ -684,7 +637,7 @@ compare_f64s :: proc(a, b: f64) -> int { compare_strings :: proc(a, b: string) -> int { x := transmute(mem.Raw_String)a y := transmute(mem.Raw_String)b - + ret := mem.compare_byte_ptrs(x.data, y.data, min(x.len, y.len)) if ret == 0 && x.len != y.len { return -1 if x.len < y.len else +1 diff --git a/core/strconv/decimal/decimal.odin b/core/strconv/decimal/decimal.odin index cb9285083..98891a548 100644 --- a/core/strconv/decimal/decimal.odin +++ b/core/strconv/decimal/decimal.odin @@ -1,5 +1,6 @@ -// Multiple precision decimal numbers -// NOTE: This is only for floating point printing and nothing else +// Multiple precision decimal numbers for use by the `strconv` package. +// +// NOTE: This is only for floating point printing and nothing else. package strconv_decimal Decimal :: struct { @@ -12,11 +13,11 @@ Decimal :: struct { Sets a Decimal from a given string `s`. The string is expected to represent a float. Stores parsed number in the given Decimal structure. If parsing fails, the Decimal will be left in an undefined state. -**Inputs** +**Inputs** - d: Pointer to a Decimal struct where the parsed result will be stored - s: The input string representing the floating-point number -**Returns** +**Returns** - ok: A boolean indicating whether the parsing was successful */ set :: proc(d: ^Decimal, s: string) -> (ok: bool) { @@ -104,11 +105,11 @@ set :: proc(d: ^Decimal, s: string) -> (ok: bool) { /* Converts a Decimal to a string representation, using the provided buffer as storage. -**Inputs** +**Inputs** - buf: A byte slice buffer to hold the resulting string - a: The struct to be converted to a string -**Returns** +**Returns** - A string representation of the Decimal */ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { @@ -150,7 +151,7 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string { /* Trims trailing zeros in the given Decimal, updating the count and decimal_point values as needed. -**Inputs** +**Inputs** - a: Pointer to the Decimal struct to be trimmed */ trim :: proc(a: ^Decimal) { @@ -166,7 +167,7 @@ Converts a given u64 integer `idx` to its Decimal representation in the provided **Used for internal Decimal Operations.** -**Inputs** +**Inputs** - a: Where the result will be stored - idx: The value to be assigned to the Decimal */ @@ -190,11 +191,11 @@ assign :: proc(a: ^Decimal, idx: u64) { trim(a) } /* -Shifts the Decimal value to the right by k positions. +Shifts the Decimal value to the right by k positions. **Used for internal Decimal Operations.** -**Inputs** +**Inputs** - a: The Decimal struct to be shifted - k: The number of positions to shift right */ @@ -344,7 +345,7 @@ Shifts the decimal of the input value to the left by `k` places WARNING: asserts `k < 61` -**Inputs** +**Inputs** - a: The Decimal to be modified - k: The number of places to shift the decimal to the left */ @@ -405,7 +406,7 @@ shift_left :: proc(a: ^Decimal, k: uint) #no_bounds_check { /* Shifts the decimal of the input value by the specified number of places -**Inputs** +**Inputs** - a: The Decimal to be modified - i: The number of places to shift the decimal (positive for left shift, negative for right shift) */ @@ -435,7 +436,7 @@ shift :: proc(a: ^Decimal, i: int) { /* Determines if the Decimal can be rounded up at the given digit index -**Inputs** +**Inputs** - a: The Decimal to check - nd: The digit index to consider for rounding up @@ -455,7 +456,7 @@ can_round_up :: proc(a: ^Decimal, nd: int) -> bool { /* Rounds the Decimal at the given digit index -**Inputs** +**Inputs** - a: The Decimal to be modified - nd: The digit index to round */ @@ -470,7 +471,7 @@ round :: proc(a: ^Decimal, nd: int) { /* Rounds the Decimal up at the given digit index -**Inputs** +**Inputs** - a: The Decimal to be modified - nd: The digit index to round up */ @@ -493,7 +494,7 @@ round_up :: proc(a: ^Decimal, nd: int) { /* Rounds down the decimal value to the specified number of decimal places -**Inputs** +**Inputs** - a: The Decimal value to be rounded down - nd: The number of decimal places to round down to @@ -522,7 +523,7 @@ round_down :: proc(a: ^Decimal, nd: int) { /* Extracts the rounded integer part of a decimal value -**Inputs** +**Inputs** - a: A pointer to the Decimal value to extract the rounded integer part from WARNING: There are no guarantees about overflow. diff --git a/core/strconv/deprecated.odin b/core/strconv/deprecated.odin new file mode 100644 index 000000000..9f41f1940 --- /dev/null +++ b/core/strconv/deprecated.odin @@ -0,0 +1,25 @@ +package strconv + +// 2025-10-03 Deprecated C short names and implementations + +@(deprecated="Use strconv.write_int() instead") +itoa :: proc(buf: []byte, i: int) -> string { + return write_int(buf, i64(i), 10) +} + +@(deprecated="Use strconv.parse_int() instead") +atoi :: proc(s: string) -> int { + v, _ := parse_int(s) + return v +} + +@(deprecated="Use strconv.parse_f64() instead") +atof :: proc(s: string) -> f64 { + v, _ := parse_f64(s) + return v +} + +@(deprecated="Use strconv.write_float() instead") +ftoa :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { + return string(generic_ftoa(buf, f, fmt, prec, bit_size)) +} \ No newline at end of file diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index b126dc3b6..902a4317c 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -23,7 +23,7 @@ _f64_info := Float_Info{52, 11, -1023} /* Converts a floating-point number to a string with the specified format and precision. -**Inputs** +**Inputs** buf: A byte slice to store the resulting string val: The floating-point value to be converted @@ -40,7 +40,7 @@ Example: bit_size := 64 result := strconv.generic_ftoa(buf[:], val, fmt, precision, bit_size) -> "3.14" -**Returns** +**Returns** - A byte slice containing the formatted string */ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) -> []byte { @@ -122,7 +122,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, precision, bit_size: int) /* Converts a decimal floating-point number into a byte buffer with the given format -**Inputs** +**Inputs** - buf: The byte buffer to store the formatted number - shortest: If true, generates the shortest representation of the number - neg: If true, the number is negative @@ -130,7 +130,7 @@ Converts a decimal floating-point number into a byte buffer with the given forma - precision: The number of digits after the decimal point - fmt: The format specifier (accepted values: 'f', 'F', 'e', 'E', 'g', 'G') -**Returns** +**Returns** - A byte slice containing the formatted decimal floating-point number */ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, precision: int, fmt: byte) -> []byte { @@ -256,7 +256,7 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic /* Rounds the given decimal number to its shortest representation, considering the provided floating-point format -**Inputs** +**Inputs** - d: The decimal number to round - mant: The mantissa of the floating-point number - exp: The exponent of the floating-point number @@ -281,7 +281,7 @@ round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Inf } upper_: decimal.Decimal; upper := &upper_ - decimal.assign(upper, 2*mant - 1) + decimal.assign(upper, 2*mant + 1) decimal.shift(upper, exp - int(flt.mantbits) - 1) mantlo: u64 @@ -331,11 +331,11 @@ round_shortest :: proc(d: ^decimal.Decimal, mant: u64, exp: int, flt: ^Float_Inf /* Converts a decimal number to its floating-point representation with the given format and returns the resulting bits -**Inputs** +**Inputs** - d: Pointer to the decimal number to convert - info: Pointer to the Float_Info structure containing information about the floating-point format -**Returns** +**Returns** - b: The bits representing the floating-point number - overflow: A boolean indicating whether an overflow occurred during conversion */ diff --git a/core/strconv/integers.odin b/core/strconv/integers.odin index 98a432ac5..16c31ac42 100644 --- a/core/strconv/integers.odin +++ b/core/strconv/integers.odin @@ -12,12 +12,12 @@ digits := "0123456789abcdefghijklmnopqrstuvwxyz" /* Determines whether the given unsigned 64-bit integer is a negative value by interpreting it as a signed integer with the specified bit size. -**Inputs** +**Inputs** - x: The unsigned 64-bit integer to check for negativity - is_signed: A boolean indicating if the input should be treated as a signed integer - bit_size: The bit size of the signed integer representation (8, 16, 32, or 64) -**Returns** +**Returns** - u: The absolute value of the input integer - neg: A boolean indicating whether the input integer is negative */ @@ -48,9 +48,9 @@ is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64, return } /* -Appends the string representation of an integer to a buffer with specified base, flags, and digit set. +Writes the string representation of an integer to a buffer with specified base, flags, and digit set. -**Inputs** +**Inputs** - buf: The buffer to append the integer representation to - x: The integer value to convert - base: The base for the integer representation (2 <= base <= MAX_BASE) @@ -59,12 +59,12 @@ Appends the string representation of an integer to a buffer with specified base, - digits: The digit set used for the integer representation - flags: The Int_Flags bit set to control integer formatting -**Returns** +**Returns** - The string containing the integer representation appended to the buffer */ -append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { +write_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits") + panic("strconv: illegal base passed to write_bits") } a: [129]byte @@ -106,12 +106,12 @@ append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: i /* Determines whether the given unsigned 128-bit integer is a negative value by interpreting it as a signed integer with the specified bit size. -**Inputs** +**Inputs** - x: The unsigned 128-bit integer to check for negativity - is_signed: A boolean indicating if the input should be treated as a signed integer - bit_size: The bit size of the signed integer representation (8, 16, 32, 64, or 128) -**Returns** +**Returns** - u: The absolute value of the input integer - neg: A boolean indicating whether the input integer is negative */ @@ -146,9 +146,9 @@ is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u: return } /* -Appends the string representation of a 128-bit integer to a buffer with specified base, flags, and digit set. +Writes the string representation of a 128-bit integer to a buffer with specified base, flags, and digit set. -**Inputs** +**Inputs** - buf: The buffer to append the integer representation to - x: The 128-bit integer value to convert - base: The base for the integer representation (2 <= base <= MAX_BASE) @@ -157,12 +157,12 @@ Appends the string representation of a 128-bit integer to a buffer with specifie - digits: The digit set used for the integer representation - flags: The Int_Flags bit set to control integer formatting -**Returns** -- The string containing the integer representation appended to the buffer +**Returns** +- The string containing the integer representation written to the buffer */ -append_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { +write_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits") + panic("strconv: illegal base passed to write_bits") } a: [140]byte diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 26a737bd1..f52e7d133 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -1,3 +1,4 @@ +// Conversions to and from `string` representations of other data types like integers and booleans. package strconv import "core:unicode/utf8" @@ -5,8 +6,8 @@ import "decimal" /* Parses a boolean value from the input string -**Inputs** -- s: The input string +**Inputs** +- s: The input string - true: "1", "t", "T", "true", "TRUE", "True" - false: "0", "f", "F", "false", "FALSE", "False" - n: An optional pointer to an int to store the length of the parsed substring (default: nil) @@ -341,6 +342,7 @@ Parses a signed integer value from the input string, using the specified base or - base: The base of the number system to use for parsing (default: 0) - If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal) - If base is not 0, it will be used for parsing regardless of any prefix in the input string +- n: An optional pointer to an int to store the length of the parsed substring (default: nil) Example: @@ -384,9 +386,10 @@ Parses an unsigned integer value from the input string, using the specified base - base: The base of the number system to use for parsing (default: 0, inferred) - If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal) - If base is not 0, it will be used for parsing regardless of any prefix in the input string +- n: An optional pointer to an int to store the length of the parsed substring (default: nil) Example: - + import "core:fmt" import "core:strconv" parse_uint_example :: proc() { @@ -399,14 +402,14 @@ Example: n, ok = strconv.parse_uint("0xffff") // with prefix and inferred base fmt.println(n,ok) } - + Output: 1234 true 65535 true 65535 true -**Returns** +**Returns** value: The parsed uint value ok: `false` if no appropriate value could be found; the value was negative; he input string contained more than just the number @@ -423,7 +426,7 @@ parse_uint :: proc(s: string, base := 0, n: ^int = nil) -> (value: uint, ok: boo /* Parses an integer value from a string in the given base, without any prefix -**Inputs** +**Inputs** - str: The input string containing the integer value - base: The base (radix) to use for parsing the integer (1-16) - n: An optional pointer to an int to store the length of the parsed substring (default: nil) @@ -436,12 +439,12 @@ Example: n, ok := strconv.parse_i128_of_base("-1234eeee", 10) fmt.println(n,ok) } - + Output: -1234 false -**Returns** +**Returns** - value: The parsed i128 value - ok: false if no numeric value of the appropriate base could be found, or if the input string contained more than just the number. */ @@ -491,7 +494,7 @@ parse_i128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: i12 /* Parses an integer value from a string in base 10, unless there's a prefix -**Inputs** +**Inputs** - str: The input string containing the integer value - n: An optional pointer to an int to store the length of the parsed substring (default: nil) @@ -506,13 +509,13 @@ Example: n, ok = strconv.parse_i128_maybe_prefixed("0xeeee") fmt.println(n, ok) } - + Output: 1234 true 61166 true - -**Returns** + +**Returns** - value: The parsed i128 value - ok: `false` if a valid integer could not be found, or if the input string contained more than just the number. */ @@ -574,7 +577,7 @@ parse_i128 :: proc{parse_i128_maybe_prefixed, parse_i128_of_base} /* Parses an unsigned integer value from a string in the given base, without any prefix -**Inputs** +**Inputs** - str: The input string containing the integer value - base: The base (radix) to use for parsing the integer (1-16) - n: An optional pointer to an int to store the length of the parsed substring (default: nil) @@ -590,13 +593,13 @@ Example: n, ok = strconv.parse_u128_of_base("5678eeee", 16) fmt.println(n, ok) } - + Output: 1234 false 1450766062 true - -**Returns** + +**Returns** - value: The parsed u128 value - ok: `false` if no numeric value of the appropriate base could be found, or if the input string contained more than just the number. */ @@ -634,7 +637,7 @@ parse_u128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: u12 /* Parses an unsigned integer value from a string in base 10, unless there's a prefix -**Inputs** +**Inputs** - str: The input string containing the integer value - n: An optional pointer to an int to store the length of the parsed substring (default: nil) @@ -649,13 +652,13 @@ Example: n, ok = strconv.parse_u128_maybe_prefixed("5678eeee") fmt.println(n, ok) } - + Output: 1234 true 5678 false - -**Returns** + +**Returns** - value: The parsed u128 value - ok: false if a valid integer could not be found, if the value was negative, or if the input string contained more than just the number. */ @@ -706,10 +709,10 @@ parse_u128 :: proc{parse_u128_maybe_prefixed, parse_u128_of_base} /* Converts a byte to lowercase -**Inputs** +**Inputs** - ch: A byte character to be converted to lowercase. -**Returns** +**Returns** - A lowercase byte character. */ @(private) @@ -717,7 +720,7 @@ lower :: #force_inline proc "contextless" (ch: byte) -> byte { return ('a' - 'A' /* Parses a 32-bit floating point number from a string -**Inputs** +**Inputs** - s: The input string containing a 32-bit floating point number. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -732,13 +735,13 @@ Example: n, ok = strconv.parse_f32("5678e2") fmt.printfln("%.3f %v", n, ok) } - + Output: 0.000 false 567800.000 true - -**Returns** + +**Returns** - value: The parsed 32-bit floating point number. - ok: `false` if a base 10 float could not be found, or if the input string contained more than just the number. */ @@ -750,7 +753,7 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) { /* Parses a 64-bit floating point number from a string -**Inputs** +**Inputs** - str: The input string containing a 64-bit floating point number. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -765,13 +768,13 @@ Example: n, ok = strconv.parse_f64("5678e2") fmt.printfln("%.3f %v", n, ok) } - + Output: 0.000 false 567800.000 true - -**Returns** + +**Returns** - value: The parsed 64-bit floating point number. - ok: `false` if a base 10 float could not be found, or if the input string contained more than just the number. */ @@ -787,7 +790,7 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { /* Parses a 32-bit floating point number from a string and returns the parsed number, the length of the parsed substring, and a boolean indicating whether the parsing was successful -**Inputs** +**Inputs** - str: The input string containing a 32-bit floating point number. Example: @@ -801,14 +804,14 @@ Example: n, _, ok = strconv.parse_f32_prefix("5678e2") fmt.printfln("%.3f %v", n, ok) } - + Output: 0.000 false 567800.000 true - -**Returns** + +**Returns** - value: The parsed 32-bit floating point number. - nr: The length of the parsed substring. - ok: A boolean indicating whether the parsing was successful. @@ -822,7 +825,7 @@ parse_f32_prefix :: proc(str: string) -> (value: f32, nr: int, ok: bool) { /* Parses a 64-bit floating point number from a string and returns the parsed number, the length of the parsed substring, and a boolean indicating whether the parsing was successful -**Inputs** +**Inputs** - str: The input string containing a 64-bit floating point number. Example: @@ -846,7 +849,7 @@ Output: 1234.000 true 13.370 true -**Returns** +**Returns** - value: The parsed 64-bit floating point number. - nr: The length of the parsed substring. - ok: `false` if a base 10 float could not be found @@ -1095,6 +1098,39 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { return transmute(f64)bits, ok } + if len(str) > 2 && str[0] == '0' && str[1] == 'h' { + nr = 2 + + as_int: u64 + digits: int + for r in str[2:] { + if r == '_' { + nr += 1 + continue + } + v := u64(_digit_value(r)) + if v >= 16 { + break + } + as_int *= 16 + as_int += v + digits += 1 + } + nr += digits + ok = len(str) == nr + + switch digits { + case 4: + value = cast(f64)transmute(f16)cast(u16)as_int + case 8: + value = cast(f64)transmute(f32)cast(u32)as_int + case 16: + value = transmute(f64)as_int + case: + ok = false + } + return + } if value, nr, ok = check_special(str); ok { return @@ -1151,7 +1187,7 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { /* Parses a 128-bit complex number from a string -**Inputs** +**Inputs** - str: The input string containing a 128-bit complex number. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1167,13 +1203,13 @@ Example: c, ok = strconv.parse_complex128("5+7i hellope", &n) fmt.printfln("%v %i %t", c, n, ok) } - + Output: 3+1i 4 true 5+7i 4 false - -**Returns** + +**Returns** - value: The parsed 128-bit complex number. - ok: `false` if a complex number could not be found, or if the input string contained more than just the number. */ @@ -1199,12 +1235,12 @@ parse_complex128 :: proc(str: string, n: ^int = nil) -> (value: complex128, ok: } value = complex(real_value, imag_value) - return + return } /* Parses a 64-bit complex number from a string -**Inputs** +**Inputs** - str: The input string containing a 64-bit complex number. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1220,13 +1256,13 @@ Example: c, ok = strconv.parse_complex64("5+7i hellope", &n) fmt.printfln("%v %i %t", c, n, ok) } - + Output: 3+1i 4 true 5+7i 4 false - -**Returns** + +**Returns** - value: The parsed 64-bit complex number. - ok: `false` if a complex number could not be found, or if the input string contained more than just the number. */ @@ -1238,7 +1274,7 @@ parse_complex64 :: proc(str: string, n: ^int = nil) -> (value: complex64, ok: bo /* Parses a 32-bit complex number from a string -**Inputs** +**Inputs** - str: The input string containing a 32-bit complex number. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1254,13 +1290,13 @@ Example: c, ok = strconv.parse_complex32("5+7i hellope", &n) fmt.printfln("%v %i %t", c, n, ok) } - + Output: 3+1i 4 true 5+7i 4 false - -**Returns** + +**Returns** - value: The parsed 32-bit complex number. - ok: `false` if a complex number could not be found, or if the input string contained more than just the number. */ @@ -1272,7 +1308,7 @@ parse_complex32 :: proc(str: string, n: ^int = nil) -> (value: complex32, ok: bo /* Parses a 256-bit quaternion from a string -**Inputs** +**Inputs** - str: The input string containing a 256-bit quaternion. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1288,13 +1324,13 @@ Example: q, ok = strconv.parse_quaternion256("1+2i+3j+4k hellope", &n) fmt.printfln("%v %i %t", q, n, ok) } - + Output: 1+2i+3j+4k 10 true 1+2i+3j+4k 10 false - -**Returns** + +**Returns** - value: The parsed 256-bit quaternion. - ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion. */ @@ -1352,7 +1388,7 @@ parse_quaternion256 :: proc(str: string, n: ^int = nil) -> (value: quaternion256 /* Parses a 128-bit quaternion from a string -**Inputs** +**Inputs** - str: The input string containing a 128-bit quaternion. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1368,13 +1404,13 @@ Example: q, ok = strconv.parse_quaternion128("1+2i+3j+4k hellope", &n) fmt.printfln("%v %i %t", q, n, ok) } - + Output: 1+2i+3j+4k 10 true 1+2i+3j+4k 10 false - -**Returns** + +**Returns** - value: The parsed 128-bit quaternion. - ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion. */ @@ -1386,7 +1422,7 @@ parse_quaternion128 :: proc(str: string, n: ^int = nil) -> (value: quaternion128 /* Parses a 64-bit quaternion from a string -**Inputs** +**Inputs** - str: The input string containing a 64-bit quaternion. - n: An optional pointer to an int to store the length of the parsed substring (default: nil). @@ -1402,13 +1438,13 @@ Example: q, ok = strconv.parse_quaternion64("1+2i+3j+4k hellope", &n) fmt.printfln("%v %i %t", q, n, ok) } - + Output: 1+2i+3j+4k 10 true 1+2i+3j+4k 10 false - -**Returns** + +**Returns** - value: The parsed 64-bit quaternion. - ok: `false` if a quaternion could not be found, or if the input string contained more than just the quaternion. */ @@ -1417,20 +1453,20 @@ parse_quaternion64 :: proc(str: string, n: ^int = nil) -> (value: quaternion64, v, ok = parse_quaternion256(str, n) return cast(quaternion64)v, ok } -/* -Appends a boolean value as a string to the given buffer +/* +Writes a boolean value as a string to the given buffer -**Inputs** -- buf: The buffer to append the boolean value to -- b: The boolean value to be appended +**Inputs** +- buf: The buffer to write the boolean value to +- b: The boolean value to be written Example: import "core:fmt" import "core:strconv" - append_bool_example :: proc() { + write_bool_example :: proc() { buf: [6]byte - result := strconv.append_bool(buf[:], true) + result := strconv.write_bool(buf[:], true) fmt.println(result, buf) } @@ -1438,10 +1474,10 @@ Output: true [116, 114, 117, 101, 0, 0] -**Returns** -- The resulting string after appending the boolean value +**Returns** +- The resulting string after writing the boolean value */ -append_bool :: proc(buf: []byte, b: bool) -> string { +write_bool :: proc(buf: []byte, b: bool) -> string { n := 0 if b { n = copy(buf, "true") @@ -1450,21 +1486,21 @@ append_bool :: proc(buf: []byte, b: bool) -> string { } return string(buf[:n]) } -/* -Appends an unsigned integer value as a string to the given buffer with the specified base +/* +Writes an unsigned integer value as a string to the given buffer with the specified base -**Inputs** -- buf: The buffer to append the unsigned integer value to -- u: The unsigned integer value to be appended +**Inputs** +- buf: The buffer to write the unsigned integer value to +- u: The unsigned integer value to be written - base: The base to use for converting the integer value Example: import "core:fmt" import "core:strconv" - append_uint_example :: proc() { + write_uint_example :: proc() { buf: [4]byte - result := strconv.append_uint(buf[:], 42, 16) + result := strconv.write_uint(buf[:], 42, 16) fmt.println(result, buf) } @@ -1472,27 +1508,27 @@ Output: 2a [50, 97, 0, 0] -**Returns** -- The resulting string after appending the unsigned integer value +**Returns** +- The resulting string after writing the unsigned integer value */ -append_uint :: proc(buf: []byte, u: u64, base: int) -> string { - return append_bits(buf, u, base, false, 8*size_of(uint), digits, nil) +write_uint :: proc(buf: []byte, u: u64, base: int) -> string { + return write_bits(buf, u, base, false, 8*size_of(uint), digits, nil) } -/* -Appends a signed integer value as a string to the given buffer with the specified base +/* +Writes a signed integer value as a string to the given buffer with the specified base -**Inputs** -- buf: The buffer to append the signed integer value to -- i: The signed integer value to be appended +**Inputs** +- buf: The buffer to write the signed integer value to +- i: The signed integer value to be written - base: The base to use for converting the integer value Example: import "core:fmt" import "core:strconv" - append_int_example :: proc() { + write_int_example :: proc() { buf: [4]byte - result := strconv.append_int(buf[:], -42, 10) + result := strconv.write_int(buf[:], -42, 10) fmt.println(result, buf) } @@ -1500,104 +1536,27 @@ Output: -42 [45, 52, 50, 0] -**Returns** -- The resulting string after appending the signed integer value +**Returns** +- The resulting string after writing the signed integer value */ -append_int :: proc(buf: []byte, i: i64, base: int) -> string { - return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, nil) +write_int :: proc(buf: []byte, i: i64, base: int) -> string { + return write_bits(buf, u64(i), base, true, 8*size_of(int), digits, nil) } -append_u128 :: proc(buf: []byte, u: u128, base: int) -> string { - return append_bits_128(buf, u, base, false, 8*size_of(uint), digits, nil) +write_u128 :: proc(buf: []byte, u: u128, base: int) -> string { + return write_bits_128(buf, u, base, false, 8*size_of(uint), digits, nil) } -/* -Converts an integer value to a string and stores it in the given buffer - -**Inputs** -- buf: The buffer to store the resulting string -- i: The integer value to be converted - -Example: - - import "core:fmt" - import "core:strconv" - itoa_example :: proc() { - buf: [4]byte - result := strconv.itoa(buf[:], 42) - fmt.println(result, buf) // "42" - } - -Output: - - 42 [52, 50, 0, 0] - -**Returns** -- The resulting string after converting the integer value -*/ -itoa :: proc(buf: []byte, i: int) -> string { - return append_int(buf, i64(i), 10) -} /* -Converts a string to an integer value +`ftoa` C name deprecated, use `write_float` instead (same procedure) -**Inputs** -- s: The string to be converted +Writes a float64 value as a string to the given buffer with the specified format and precision -Example: - - import "core:fmt" - import "core:strconv" - atoi_example :: proc() { - fmt.println(strconv.atoi("42")) - } - -Output: - - 42 - -**Returns** -- The resulting integer value -*/ -atoi :: proc(s: string) -> int { - v, _ := parse_int(s) - return v -} -/* -Converts a string to a float64 value - -**Inputs** -- s: The string to be converted - -Example: - - import "core:fmt" - import "core:strconv" - atof_example :: proc() { - fmt.printfln("%.3f", strconv.atof("3.14")) - } - -Output: - - 3.140 - -**Returns** -- The resulting float64 value after converting the string -*/ -atof :: proc(s: string) -> f64 { - v, _ := parse_f64(s) - return v -} -// Alias to `append_float` -ftoa :: append_float -/* -Appends a float64 value as a string to the given buffer with the specified format and precision - -**Inputs** -- buf: The buffer to append the float64 value to -- f: The float64 value to be appended +**Inputs** +- buf: The buffer to write the float64 value to +- f: The float64 value to be written - fmt: The byte specifying the format to use for the conversion - prec: The precision to use for the conversion - bit_size: The size of the float in bits (32 or 64) @@ -1606,9 +1565,9 @@ Example: import "core:fmt" import "core:strconv" - append_float_example :: proc() { + write_float_example :: proc() { buf: [8]byte - result := strconv.append_float(buf[:], 3.14159, 'f', 2, 64) + result := strconv.write_float(buf[:], 3.14159, 'f', 2, 64) fmt.println(result, buf) } @@ -1616,20 +1575,27 @@ Output: +3.14 [43, 51, 46, 49, 52, 0, 0, 0] -**Returns** -- The resulting string after appending the float +**Returns** +- The resulting string after writing the float */ -append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { +write_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { return string(generic_ftoa(buf, f, fmt, prec, bit_size)) } +// Accepts '0'..='9', otherwise returns ok = false +digit_to_int :: proc(r: rune) -> (value: int, ok: bool) { + if '0' <= r && r <= '9' { + return int(r - '0'), true + } + return -1, false +} /* -Appends a quoted string representation of the input string to a given byte slice and returns the result as a string +Writes a quoted string representation of the input string to a given byte slice and returns the result as a string -**Inputs** -- buf: The byte slice to which the quoted string will be appended +**Inputs** +- buf: The byte slice to which the quoted string will be written - str: The input string to be quoted -!! ISSUE !! NOT EXPECTED -- "\"hello\"" was expected +!! ISSUE !! NOT EXPECTED -- "\"hello\"" was expected Example: @@ -1645,8 +1611,8 @@ Output: "'h''e''l''l''o'" [34, 39, 104, 39, 39, 101, 39, 39, 108, 39, 39, 108, 39, 39, 111, 39, 34, 0, 0, 0] -**Returns** -- The resulting string after appending the quoted string representation +**Returns** +- The resulting string after writing the quoted string representation */ quote :: proc(buf: []byte, str: string) -> string { write_byte :: proc(buf: []byte, i: ^int, bytes: ..byte) { @@ -1686,10 +1652,10 @@ quote :: proc(buf: []byte, str: string) -> string { return string(buf[:i]) } /* -Appends a quoted rune representation of the input rune to a given byte slice and returns the result as a string +Writes a quoted rune representation of the input rune to a given byte slice and returns the result as a string -**Inputs** -- buf: The byte slice to which the quoted rune will be appended +**Inputs** +- buf: The byte slice to which the quoted rune will be written - r: The input rune to be quoted Example: @@ -1706,8 +1672,8 @@ Output: 'A' [39, 65, 39, 0] -**Returns** -- The resulting string after appending the quoted rune representation +**Returns** +- The resulting string after writing the quoted rune representation */ quote_rune :: proc(buf: []byte, r: rune) -> string { write_byte :: proc(buf: []byte, i: ^int, bytes: ..byte) { @@ -1750,7 +1716,7 @@ quote_rune :: proc(buf: []byte, r: rune) -> string { if r < 32 { write_string(buf, &i, "\\x") b: [2]byte - s := append_bits(b[:], u64(r), 16, true, 64, digits, nil) + s := write_bits(b[:], u64(r), 16, true, 64, digits, nil) switch len(s) { case 0: write_string(buf, &i, "00") case 1: write_rune(buf, &i, '0') @@ -1767,11 +1733,11 @@ quote_rune :: proc(buf: []byte, r: rune) -> string { /* Unquotes a single character from the input string, considering the given quote character -**Inputs** +**Inputs** - str: The input string containing the character to unquote - quote: The quote character to consider (e.g., '"') -Example: +Example: import "core:fmt" import "core:strconv" @@ -1782,12 +1748,12 @@ Example: fmt.printf("r: <%v>, multiple_bytes:%v, tail_string:<%s>, success:%v\n",r, multiple_bytes, tail_string, success) } -Output: +Output: Source: 'The' raven r: <'>, multiple_bytes:false, tail_string:, success:true -**Returns** +**Returns** - r: The unquoted rune - multiple_bytes: A boolean indicating if the rune has multiple bytes - tail_string: The remaining portion of the input string after unquoting the character @@ -1890,13 +1856,13 @@ unquote_char :: proc(str: string, quote: byte) -> (r: rune, multiple_bytes: bool /* Unquotes the input string considering any type of quote character and returns the unquoted string -**Inputs** +**Inputs** - lit: The input string to unquote - allocator: (default: context.allocator) WARNING: This procedure gives unexpected results if the quotes are not the first and last characters. -Example: +Example: import "core:fmt" import "core:strconv" @@ -1914,10 +1880,10 @@ Example: src="The raven \'Huginn\' is black." s, allocated, ok = strconv.unquote_string(src) // Will produce undesireable results fmt.println(src) - fmt.printf("Unquoted: <%s>, alloc:%v, ok:%v\n", s, allocated, ok) + fmt.printf("Unquoted: <%s>, alloc:%v, ok:%v\n", s, allocated, ok) } -Output: +Output: "The raven Huginn is black." Unquoted: , alloc:false, ok:true @@ -1928,7 +1894,7 @@ Output: The raven 'Huginn' is black. Unquoted: , alloc:false, ok:true -**Returns** +**Returns** - res: The resulting unquoted string - allocated: A boolean indicating if the resulting string was allocated using the provided allocator - success: A boolean indicating whether the unquoting was successful @@ -1969,7 +1935,7 @@ unquote_string :: proc(lit: string, allocator := context.allocator) -> (res: str return s, false, true } } - + context.allocator = allocator buf_len := 3*len(s) / 2 diff --git a/core/strings/builder.odin b/core/strings/builder.odin index e5a88527a..79ba6108f 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -3,7 +3,6 @@ package strings import "base:runtime" import "core:unicode/utf8" import "core:strconv" -import "core:mem" import "core:io" /* Type definition for a procedure that flushes a Builder @@ -35,7 +34,7 @@ Returns: - res: The new Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_make_none :: proc(allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_make_none :: proc(allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error { return Builder{buf=make([dynamic]byte, allocator, loc) or_return }, nil } /* @@ -51,7 +50,7 @@ Returns: - res: The new Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_make_len :: proc(len: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_make_len :: proc(len: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error { return Builder{buf=make([dynamic]byte, len, allocator, loc) or_return }, nil } /* @@ -68,7 +67,7 @@ Returns: - res: The new Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_make_len_cap :: proc(len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: Builder, err: runtime.Allocator_Error) #optional_allocator_error { return Builder{buf=make([dynamic]byte, len, cap, allocator, loc) or_return }, nil } /* @@ -116,7 +115,7 @@ Returns: - res: A pointer to the initialized Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_init_none :: proc(b: ^Builder, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_init_none :: proc(b: ^Builder, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error { b.buf = make([dynamic]byte, allocator, loc) or_return return b, nil } @@ -135,7 +134,7 @@ Returns: - res: A pointer to the initialized Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_init_len :: proc(b: ^Builder, len: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error { b.buf = make([dynamic]byte, len, allocator, loc) or_return return b, nil } @@ -153,7 +152,7 @@ Returns: - res: A pointer to the initialized Builder - err: An optional allocator error if one occured, `nil` otherwise */ -builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: mem.Allocator_Error) #optional_allocator_error { +builder_init_len_cap :: proc(b: ^Builder, len, cap: int, allocator := context.allocator, loc := #caller_location) -> (res: ^Builder, err: runtime.Allocator_Error) #optional_allocator_error { b.buf = make([dynamic]byte, len, cap, allocator, loc) or_return return b, nil } @@ -182,7 +181,7 @@ _builder_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byt case .Query: return io.query_utility({.Write, .Size, .Destroy, .Query}) } - return 0, .Empty + return 0, .Unsupported } /* @@ -269,8 +268,19 @@ Output: */ builder_from_bytes :: proc(backing: []byte) -> (res: Builder) { - return Builder{ buf = mem.buffer_from_slice(backing) } + return Builder{ + buf = transmute([dynamic]byte)runtime.Raw_Dynamic_Array{ + data = raw_data(backing), + len = 0, + cap = len(backing), + allocator = runtime.Allocator{ + procedure = runtime.nil_allocator_proc, + data = nil, + }, + }, + } } + // Alias to `builder_from_bytes` builder_from_slice :: builder_from_bytes /* @@ -296,8 +306,8 @@ Inputs: Returns: - res: A cstring of the Builder's buffer */ -unsafe_to_cstring :: proc(b: ^Builder) -> (res: cstring) { - append(&b.buf, 0) +unsafe_to_cstring :: proc(b: ^Builder, loc := #caller_location) -> (res: cstring) { + append(&b.buf, 0, loc) pop(&b.buf) return cstring(raw_data(b.buf)) } @@ -311,8 +321,8 @@ Returns: - res: A cstring of the Builder's buffer upon success - err: An optional allocator error if one occured, `nil` otherwise */ -to_cstring :: proc(b: ^Builder) -> (res: cstring, err: mem.Allocator_Error) { - n := append(&b.buf, 0) or_return +to_cstring :: proc(b: ^Builder, loc := #caller_location) -> (res: cstring, err: runtime.Allocator_Error) #optional_allocator_error { + n := append(&b.buf, 0, loc) or_return if n != 1 { return nil, .Out_Of_Memory } @@ -518,9 +528,9 @@ Output: abc */ -write_string :: proc(b: ^Builder, s: string) -> (n: int) { +write_string :: proc(b: ^Builder, s: string, loc := #caller_location) -> (n: int) { n0 := len(b.buf) - append(&b.buf, s) + append(&b.buf, s, loc) n1 := len(b.buf) return n1-n0 } @@ -675,7 +685,7 @@ Returns: */ write_float :: proc(b: ^Builder, f: f64, fmt: byte, prec, bit_size: int, always_signed := false) -> (n: int) { buf: [384]byte - s := strconv.append_float(buf[:], f, fmt, prec, bit_size) + s := strconv.write_float(buf[:], f, fmt, prec, bit_size) // If the result starts with a `+` then unless we always want signed results, // we skip it unless it's followed by an `I` (because of +Inf). if !always_signed && (buf[0] == '+' && buf[1] != 'I') { @@ -699,7 +709,7 @@ Returns: */ write_f16 :: proc(b: ^Builder, f: f16, fmt: byte, always_signed := false) -> (n: int) { buf: [384]byte - s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) + s := strconv.write_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) if !always_signed && (buf[0] == '+' && buf[1] != 'I') { s = s[1:] } @@ -739,7 +749,7 @@ Output: */ write_f32 :: proc(b: ^Builder, f: f32, fmt: byte, always_signed := false) -> (n: int) { buf: [384]byte - s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) + s := strconv.write_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) if !always_signed && (buf[0] == '+' && buf[1] != 'I') { s = s[1:] } @@ -761,7 +771,7 @@ Returns: */ write_f64 :: proc(b: ^Builder, f: f64, fmt: byte, always_signed := false) -> (n: int) { buf: [384]byte - s := strconv.append_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) + s := strconv.write_float(buf[:], f64(f), fmt, 2*size_of(f), 8*size_of(f)) if !always_signed && (buf[0] == '+' && buf[1] != 'I') { s = s[1:] } @@ -782,7 +792,7 @@ Returns: */ write_u64 :: proc(b: ^Builder, i: u64, base: int = 10) -> (n: int) { buf: [32]byte - s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil) + s := strconv.write_bits(buf[:], i, base, false, 64, strconv.digits, nil) return write_string(b, s) } /* @@ -800,7 +810,7 @@ Returns: */ write_i64 :: proc(b: ^Builder, i: i64, base: int = 10) -> (n: int) { buf: [32]byte - s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) + s := strconv.write_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil) return write_string(b, s) } /* @@ -835,3 +845,125 @@ Returns: write_int :: proc(b: ^Builder, i: int, base: int = 10) -> (n: int) { return write_i64(b, i64(i), base) } + + +/* +Replaces all instances of `old` in the string in a Builder `b` with the `new` string + +*Allocates Using The Allocator On The Builder* + +Inputs: +- b: The input `Builder` +- old: The substring to be replaced +- new: The replacement string + +Returns: +- replaced: The number of replacements +- err: if any allocation errors occurred +*/ +builder_replace_all :: proc(b: ^Builder, old, new: string) -> (replaced: int, err: runtime.Allocator_Error) { + return builder_replace(b, old, new, -1) +} + +/* +Replaces n instances of `old` in the string in a Builder `b` with the `new` string + +*Allocates Using The Allocator On The Builder* + +Inputs: +- b: The input `Builder` +- old: The substring to be replaced +- new: The replacement string +- n: The number of instances to replace (if `n < 0`, no limit on the number of replacements) + +Returns: +- replaced: The number of replacements +- err: if any allocation errors occurred +*/ +builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_location) -> (replaced: int, err: runtime.Allocator_Error) { + if old == new || n == 0 { + return + } + + if m := count(to_string(b^), old); m == 0 { + return + } + + if len(old) == 0 { + // NOTE(bill): reserve the necessary memory + found := 0 + for i := 0; i <= len(b.buf); i += len(new)+1 { + if n > 0 && found == n { + break + } + found += 1 + } + if found == 0 { + return + } + reserve(&b.buf, len(b.buf) + len(new)*found) or_return + + + for i := 0; i <= len(b.buf); i += len(new)+1 { + if n > 0 && replaced == n { + break + } + + resize(&b.buf, len(b.buf)+len(new), loc) or_return + copy(b.buf[i+len(new):], b.buf[i:]) + copy(b.buf[i:], new) + replaced += 1 + } + } else { + if len(new) > len(old) { + // NOTE(bill): reserve the necessary memory + found := 0 + for i := 0; i < len(b.buf); /**/ { + if n > 0 && found == n { + break + } + + j := index(string(b.buf[i:]), old) + if j < 0 { + break + } + i += j+len(old) + found += 1 + } + if found == 0 { + return + } + reserve(&b.buf, len(b.buf) + (len(new)-len(old))*found) or_return + } + + for i := 0; i < len(b.buf); /**/ { + if n > 0 && replaced == n { + break + } + + j := index(string(b.buf[i:]), old) + if j < 0 { + break + } + + if len(new) > len(old) { + resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return + } + + cur := b.buf[i+j:] + src := cur[len(old):] + dst := cur[len(new):] + copy(dst, src) + copy(cur, new) + + i += j+len(new) + + replaced += 1 + + if len(new) < len(old) { + resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return + } + } + } + return +} \ No newline at end of file diff --git a/core/strings/conversion.odin b/core/strings/conversion.odin index 2e82fff58..2e6bee573 100644 --- a/core/strings/conversion.odin +++ b/core/strings/conversion.odin @@ -1,7 +1,7 @@ package strings +import "base:runtime" import "core:io" -import "core:mem" import "core:unicode" import "core:unicode/utf8" @@ -21,7 +21,7 @@ Returns: - res: A valid UTF-8 string with invalid sequences replaced by `replacement`. - err: An optional allocator error if one occured, `nil` otherwise */ -to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { if len(s) == 0 { return "", nil } @@ -101,7 +101,7 @@ Output: test */ -to_lower :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_lower :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { b: Builder builder_init(&b, 0, len(s), allocator) or_return for r in s { @@ -136,7 +136,7 @@ Output: TEST */ -to_upper :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_upper :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { b: Builder builder_init(&b, 0, len(s), allocator) or_return for r in s { @@ -260,7 +260,7 @@ Returns: - res: The converted string - err: An optional allocator error if one occured, `nil` otherwise */ -to_camel_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_camel_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := s s = trim_space(s) b: Builder @@ -296,7 +296,7 @@ Returns: - res: The converted string - err: An optional allocator error if one occured, `nil` otherwise */ -to_pascal_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_pascal_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := s s = trim_space(s) b: Builder @@ -355,7 +355,7 @@ to_delimiter_case :: proc( delimiter: rune, all_upper_case: bool, allocator := context.allocator, -) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := s s = trim_space(s) b: Builder @@ -422,7 +422,7 @@ Output: hello_world */ -to_snake_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_snake_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { return to_delimiter_case(s, '_', false, allocator) } // Alias for `to_upper_snake_case` @@ -454,7 +454,7 @@ Output: HELLO_WORLD */ -to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { return to_delimiter_case(s, '_', true, allocator) } /* @@ -484,7 +484,7 @@ Output: hello-world */ -to_kebab_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_kebab_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { return to_delimiter_case(s, '-', false, allocator) } /* @@ -514,7 +514,7 @@ Output: HELLO-WORLD */ -to_upper_kebab_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_upper_kebab_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { return to_delimiter_case(s, '-', true, allocator) } /* @@ -544,7 +544,7 @@ Output: Hello_World */ -to_ada_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +to_ada_case :: proc(s: string, allocator := context.allocator) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := s s = trim_space(s) b: Builder diff --git a/core/strings/intern.odin b/core/strings/intern.odin index 0b8ed173e..9b816ff8d 100644 --- a/core/strings/intern.odin +++ b/core/strings/intern.odin @@ -1,7 +1,6 @@ package strings import "base:runtime" -import "core:mem" // Custom string entry struct Intern_Entry :: struct { @@ -30,11 +29,12 @@ Inputs: - m: A pointer to the Intern struct to be initialized - allocator: The allocator for the Intern_Entry strings (Default: context.allocator) - map_allocator: The allocator for the map of entries (Default: context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - err: An allocator error if one occured, `nil` otherwise */ -intern_init :: proc(m: ^Intern, allocator := context.allocator, map_allocator := context.allocator, loc := #caller_location) -> (err: mem.Allocator_Error) { +intern_init :: proc(m: ^Intern, allocator := context.allocator, map_allocator := context.allocator, loc := #caller_location) -> (err: runtime.Allocator_Error) { m.allocator = allocator m.entries = make(map[string]^Intern_Entry, 16, map_allocator, loc) or_return return nil @@ -78,6 +78,7 @@ Returns an interned copy of the given text as a cstring, adding it to the map if Inputs: - m: A pointer to the Intern struct - text: The string to be interned +- loc: The caller location for debugging purposes (default: `#caller_location`) NOTE: The returned cstring lives as long as the map entry lives @@ -85,8 +86,8 @@ Returns: - str: The interned cstring - err: An allocator error if one occured, `nil` otherwise */ -intern_get_cstring :: proc(m: ^Intern, text: string) -> (str: cstring, err: runtime.Allocator_Error) { - entry := _intern_get_entry(m, text) or_return +intern_get_cstring :: proc(m: ^Intern, text: string, loc := #caller_location) -> (str: cstring, err: runtime.Allocator_Error) { + entry := _intern_get_entry(m, text, loc) or_return return cstring(&entry.str[0]), nil } @@ -99,12 +100,13 @@ Sets and allocates the entry if it wasn't set yet Inputs: - m: A pointer to the Intern struct - text: The string to be looked up or interned +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - new_entry: The interned cstring - err: An allocator error if one occured, `nil` otherwise */ -_intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check { +_intern_get_entry :: proc(m: ^Intern, text: string, loc := #caller_location) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check { if m.allocator.procedure == nil { m.allocator = context.allocator } @@ -115,7 +117,7 @@ _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry } entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1 - bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return + bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator, loc) or_return new_entry = (^Intern_Entry)(raw_data(bytes)) new_entry.len = len(text) diff --git a/core/strings/reader.odin b/core/strings/reader.odin index bb49bf917..0d467f285 100644 --- a/core/strings/reader.odin +++ b/core/strings/reader.odin @@ -310,5 +310,5 @@ _reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse case .Query: return io.query_utility({.Size, .Read, .Read_At, .Seek, .Query}) } - return 0, .Empty + return 0, .Unsupported } diff --git a/core/strings/strings.odin b/core/strings/strings.odin index e15754dff..40dc11e75 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -1,10 +1,10 @@ -// Procedures to manipulate UTF-8 encoded strings +// A `string` builder, as well as procedures to manipulate `UTF-8` encoded strings. package strings import "base:intrinsics" +import "base:runtime" import "core:bytes" import "core:io" -import "core:mem" import "core:unicode" import "core:unicode/utf8" @@ -22,29 +22,12 @@ Returns: - res: The cloned string - err: An optional allocator error if one occured, `nil` otherwise */ -clone :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +clone :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { c := make([]byte, len(s), allocator, loc) or_return copy(c, s) return string(c), nil } -/* -Clones a string safely (returns early with an allocation error on failure) -*Allocates Using Provided Allocator* - -Inputs: -- s: The string to be cloned -- allocator: (default: context.allocator) -- loc: The caller location for debugging purposes (default: #caller_location) - -Returns: -- res: The cloned string -- err: An allocator error if one occured, `nil` otherwise -*/ -@(deprecated="Prefer clone. It now returns an optional allocator error") -clone_safe :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) { - return clone(s, allocator, loc) -} /* Clones a string and appends a null-byte to make it a cstring @@ -59,12 +42,13 @@ Returns: - res: A cloned cstring with an appended null-byte - err: An optional allocator error if one occured, `nil` otherwise */ -clone_to_cstring :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: cstring, err: mem.Allocator_Error) #optional_allocator_error { +clone_to_cstring :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: cstring, err: runtime.Allocator_Error) #optional_allocator_error { c := make([]byte, len(s)+1, allocator, loc) or_return copy(c, s) c[len(s)] = 0 return cstring(&c[0]), nil } + /* Transmutes a raw pointer into a string. Non-allocating. @@ -78,8 +62,9 @@ Returns: - res: A string created from the byte pointer and length */ string_from_ptr :: proc(ptr: ^byte, len: int) -> (res: string) { - return transmute(string)mem.Raw_String{ptr, len} + return transmute(string)runtime.Raw_String{ptr, len} } + /* Transmutes a raw pointer (null-terminated) into a string. Non-allocating. Searches for a null-byte from `0.. (res: ^byte) { - d := transmute(mem.Raw_String)str - return d.data -} /* Converts a string `str` to a cstring @@ -124,9 +96,10 @@ Returns: - res: The converted cstring */ unsafe_string_to_cstring :: proc(str: string) -> (res: cstring) { - d := transmute(mem.Raw_String)str + d := transmute(runtime.Raw_String)str return cstring(d.data) } + /* Truncates a string `str` at the first occurrence of char/byte `b` @@ -139,13 +112,14 @@ NOTE: Failure to find the byte results in returning the entire string. Returns: - res: The truncated string */ -truncate_to_byte :: proc "contextless" (str: string, b: byte) -> (res: string) { +truncate_to_byte :: proc "contextless" (str: string, b: byte) -> (res: string) #no_bounds_check { n := index_byte(str, b) if n < 0 { n = len(str) } return str[:n] } + /* Truncates a string `str` at the first occurrence of rune `r` as a slice of the original, entire string if not found @@ -156,13 +130,14 @@ Inputs: Returns: - res: The truncated string */ -truncate_to_rune :: proc(str: string, r: rune) -> (res: string) { +truncate_to_rune :: proc(str: string, r: rune) -> (res: string) #no_bounds_check { n := index_rune(str, r) if n < 0 { n = len(str) } return str[:n] } + /* Clones a byte array `s` and appends a null-byte @@ -177,12 +152,13 @@ Returns: - res: The cloned string from the byte array with a null-byte - err: An optional allocator error if one occured, `nil` otherwise */ -clone_from_bytes :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +clone_from_bytes :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { c := make([]byte, len(s)+1, allocator, loc) or_return copy(c, s) c[len(s)] = 0 return string(c[:len(s)]), nil } + /* Clones a cstring `s` as a string @@ -197,9 +173,10 @@ Returns: - res: The cloned string from the cstring - err: An optional allocator error if one occured, `nil` otherwise */ -clone_from_cstring :: proc(s: cstring, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +clone_from_cstring :: proc(s: cstring, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { return clone(string(s), allocator, loc) } + /* Clones a string from a byte pointer `ptr` and a byte length `len` @@ -217,10 +194,11 @@ Returns: - res: The cloned string from the byte pointer and length - err: An optional allocator error if one occured, `nil` otherwise */ -clone_from_ptr :: proc(ptr: ^byte, len: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +clone_from_ptr :: proc(ptr: ^byte, len: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := string_from_ptr(ptr, len) return clone(s, allocator, loc) } + // Overloaded procedure to clone from a string, `[]byte`, `cstring` or a `^byte` + length clone_from :: proc{ clone, @@ -228,6 +206,7 @@ clone_from :: proc{ clone_from_cstring, clone_from_ptr, } + /* Clones a string from a null-terminated cstring `ptr` and a byte length `len` @@ -245,11 +224,12 @@ Returns: - res: The cloned string from the null-terminated cstring and byte length - err: An optional allocator error if one occured, `nil` otherwise */ -clone_from_cstring_bounded :: proc(ptr: cstring, len: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +clone_from_cstring_bounded :: proc(ptr: cstring, len: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { s := string_from_ptr((^u8)(ptr), len) s = truncate_to_byte(s, 0) return clone(s, allocator, loc) } + /* Compares two strings, returning a value representing which one comes first lexicographically. -1 for `lhs`; 1 for `rhs`, or 0 if they are equal. @@ -261,9 +241,8 @@ Inputs: Returns: - result: `-1` if `lhs` comes first, `1` if `rhs` comes first, or `0` if they are equal */ -compare :: proc "contextless" (lhs, rhs: string) -> (result: int) { - return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs) -} +compare :: runtime.string_cmp + /* Checks if rune `r` in the string `s` @@ -282,6 +261,7 @@ contains_rune :: proc(s: string, r: rune) -> (result: bool) { } return false } + /* Returns true when the string `substr` is contained inside the string `s` @@ -313,6 +293,7 @@ Output: contains :: proc(s, substr: string) -> (res: bool) { return index(s, substr) >= 0 } + /* Returns `true` when the string `s` contains any of the characters inside the string `chars` @@ -385,6 +366,7 @@ Output: rune_count :: proc(s: string) -> (res: int) { return utf8.rune_count_in_string(s) } + /* Returns whether the strings `u` and `v` are the same alpha characters, ignoring different casings Works with UTF-8 string content @@ -416,7 +398,7 @@ Output: false */ -equal_fold :: proc(u, v: string) -> (res: bool) { +equal_fold :: proc(u, v: string) -> (res: bool) #no_bounds_check { s, t := u, v loop: for s != "" && t != "" { sr, tr: rune @@ -451,13 +433,19 @@ equal_fold :: proc(u, v: string) -> (res: bool) { return false } - // TODO(bill): Unicode folding - + r := unicode.simple_fold(sr) + for r != sr && r < tr { + r = unicode.simple_fold(r) + } + if r == tr { + continue loop + } return false } return s == t } + /* Returns the prefix length common between strings `a` and `b` @@ -488,29 +476,58 @@ Output: 0 */ -prefix_length :: proc(a, b: string) -> (n: int) { - _len := min(len(a), len(b)) +prefix_length :: proc "contextless" (a, b: string) -> (n: int) { + RUNE_ERROR :: '\ufffd' + RUNE_SELF :: 0x80 + UTF_MAX :: 4 - // Scan for matches including partial codepoints. - #no_bounds_check for n < _len && a[n] == b[n] { - n += 1 - } - - // Now scan to ignore partial codepoints. - if n > 0 { - s := a[:n] - n = 0 - for { - r0, w := utf8.decode_rune(s[n:]) - if r0 != utf8.RUNE_ERROR { - n += w - } else { - break + n = runtime.memory_prefix_length(raw_data(a), raw_data(b), min(len(a), len(b))) + lim := max(n - UTF_MAX + 1, 0) + #no_bounds_check for l := n; l > lim; l -= 1 { + r, _ := runtime.string_decode_rune(a[l - 1:]) + if r != RUNE_ERROR { + if l > 0 && (a[l - 1] & 0xc0 == 0xc0) { + return l - 1 } + return l } } return } + +/* +Returns the common prefix between strings `a` and `b` + +Inputs: +- a: The first input string +- b: The second input string + +Returns: +- n: The string prefix common between strings `a` and `b` + +Example: + + import "core:fmt" + import "core:strings" + + common_prefix_example :: proc() { + fmt.println(strings.common_prefix("testing", "test")) + fmt.println(strings.common_prefix("testing", "te")) + fmt.println(strings.common_prefix("telephone", "te")) + } + +Output: + + test + te + te + + +*/ +common_prefix :: proc(a, b: string) -> string { + return a[:prefix_length(a, b)] +} + /* Determines if a string `s` starts with a given `prefix` @@ -575,7 +592,7 @@ Output: true */ -has_suffix :: proc(s, suffix: string) -> (result: bool) { +has_suffix :: proc(s, suffix: string) -> (result: bool) #no_bounds_check { return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix } @@ -614,7 +631,7 @@ Output: a...b...c */ -join :: proc(a: []string, sep: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +join :: proc(a: []string, sep: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { if len(a) == 0 { return "", nil } @@ -632,24 +649,7 @@ join :: proc(a: []string, sep: string, allocator := context.allocator, loc := #c } return string(b), nil } -/* -Joins a slice of strings `a` with a `sep` string, returns an error on allocation failure -*Allocates Using Provided Allocator* - -Inputs: -- a: A slice of strings to join -- sep: The separator string -- allocator: (default is context.allocator) - -Returns: -- str: A combined string from the slice of strings `a` separated with the `sep` string -- err: An allocator error if one occured, `nil` otherwise -*/ -@(deprecated="Prefer join. It now returns an optional allocator error") -join_safe :: proc(a: []string, sep: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) { - return join(a, sep, allocator) -} /* Returns a combined string from the slice of strings `a` without a separator @@ -678,7 +678,7 @@ Output: abc */ -concatenate :: proc(a: []string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +concatenate :: proc(a: []string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { if len(a) == 0 { return "", nil } @@ -694,22 +694,6 @@ concatenate :: proc(a: []string, allocator := context.allocator, loc := #caller_ } return string(b), nil } -/* -Returns a combined string from the slice of strings `a` without a separator, or an error if allocation fails - -*Allocates Using Provided Allocator* - -Inputs: -- a: A slice of strings to concatenate -- allocator: (default is context.allocator) - -Returns: -The concatenated string, and an error if allocation fails -*/ -@(deprecated="Prefer concatenate. It now returns an optional allocator error") -concatenate_safe :: proc(a: []string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) { - return concatenate(a, allocator) -} /* Returns a substring of the input string `s` with the specified rune offset and length @@ -777,6 +761,7 @@ Inputs: - rune_offset: The starting rune index (default is 0). In runes, not bytes. - rune_length: The number of runes to include in the substring (default is 0, which returns the remainder of the string). In runes, not bytes. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The substring @@ -800,7 +785,7 @@ Output: example */ -cut_clone :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +cut_clone :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { res = cut(s, rune_offset, rune_length) return clone(res, allocator, loc) } @@ -818,6 +803,7 @@ Inputs: - sep_save: A flag determining if the separator should be saved in the resulting substrings - n: The maximum number of substrings to return, returns `nil` without alloc when `n=0` - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) NOTE: Allocation occurs for the array, the splits are all views of the original string. @@ -826,7 +812,7 @@ Returns: - err: An optional allocator error if one occured, `nil` otherwise */ @private -_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) { +_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #no_bounds_check { s, n := s_, n_ if n == 0 { @@ -872,6 +858,7 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato return res[:i+1], nil } + /* Splits a string into parts based on a separator. @@ -881,6 +868,7 @@ Inputs: - s: The string to split. - sep: The separator string used to split the input string. - allocator: (default is context.allocator). +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice of strings, each representing a part of the split string. @@ -904,9 +892,10 @@ Output: ["aaa", "bbb", "ccc", "ddd", "eee"] */ -split :: proc(s, sep: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { - return _split(s, sep, 0, -1, allocator) +split :: proc(s, sep: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { + return _split(s, sep, 0, -1, allocator, loc) } + /* Splits a string into parts based on a separator. If n < count of seperators, the remainder of the string is returned in the last entry. @@ -917,6 +906,7 @@ Inputs: - sep: The separator string used to split the input string. - n: The maximum amount of parts to split the string into. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice of strings, each representing a part of the split string. @@ -940,9 +930,10 @@ Output: ["aaa", "bbb", "ccc.ddd.eee"] */ -split_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { - return _split(s, sep, 0, n, allocator) +split_n :: proc(s, sep: string, n: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { + return _split(s, sep, 0, n, allocator, loc) } + /* Splits a string into parts after the separator, retaining it in the substrings. @@ -952,6 +943,7 @@ Inputs: - s: The string to split. - sep: The separator string used to split the input string. - allocator: (default is context.allocator). +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice of strings, each representing a part of the split string after the separator @@ -975,9 +967,10 @@ Output: ["aaa.", "bbb.", "ccc.", "ddd.", "eee"] */ -split_after :: proc(s, sep: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { - return _split(s, sep, len(sep), -1, allocator) +split_after :: proc(s, sep: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { + return _split(s, sep, len(sep), -1, allocator, loc) } + /* Splits a string into a total of `n` parts after the separator. @@ -988,6 +981,7 @@ Inputs: - sep: The separator string used to split the input string. - n: The maximum number of parts to split the string into. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice of strings with `n` parts or fewer if there weren't @@ -1011,9 +1005,10 @@ Output: ["aaa.", "bbb.", "ccc.ddd.eee"] */ -split_after_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { - return _split(s, sep, len(sep), n, allocator) +split_after_n :: proc(s, sep: string, n: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { + return _split(s, sep, len(sep), n, allocator, loc) } + /* Searches for the first occurrence of `sep` in the given string and returns the substring up to (but not including) the separator, as well as a boolean indicating success. @@ -1042,7 +1037,7 @@ _split_iterator :: proc(s: ^string, sep: string, sep_save: int) -> (res: string, } else { m = index(s^, sep) } - if m < 0 { + #no_bounds_check if m < 0 { // not found res = s[:] ok = res != "" @@ -1054,6 +1049,7 @@ _split_iterator :: proc(s: ^string, sep: string, sep_save: int) -> (res: string, } return } + /* Splits the input string by the byte separator in an iterator fashion. @@ -1088,7 +1084,7 @@ Output: */ split_by_byte_iterator :: proc(s: ^string, sep: u8) -> (res: string, ok: bool) { m := index_byte(s^, sep) - if m < 0 { + #no_bounds_check if m < 0 { // not found res = s[:] ok = res != "" @@ -1100,6 +1096,7 @@ split_by_byte_iterator :: proc(s: ^string, sep: u8) -> (res: string, ok: bool) { } return } + /* Splits the input string by the separator string in an iterator fashion. @@ -1135,6 +1132,7 @@ Output: split_iterator :: proc(s: ^string, sep: string) -> (res: string, ok: bool) { return _split_iterator(s, sep, 0) } + /* Splits the input string after every separator string in an iterator fashion. @@ -1170,6 +1168,7 @@ Output: split_after_iterator :: proc(s: ^string, sep: string) -> (res: string, ok: bool) { return _split_iterator(s, sep, len(sep)) } + /* Trims the carriage return character from the end of the input string. @@ -1182,7 +1181,7 @@ Returns: - res: The trimmed string as a slice of the original. */ @(private) -_trim_cr :: proc(s: string) -> (res: string) { +_trim_cr :: proc(s: string) -> (res: string) #no_bounds_check { n := len(s) if n > 0 { if s[n-1] == '\r' { @@ -1191,6 +1190,7 @@ _trim_cr :: proc(s: string) -> (res: string) { } return s } + /* Splits the input string at every line break `\n`. @@ -1199,6 +1199,7 @@ Splits the input string at every line break `\n`. Inputs: - s: The input string to split. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice (allocated) of the split string (slices into original string) @@ -1220,14 +1221,15 @@ Output: ["a", "b", "c", "d", "e"] */ -split_lines :: proc(s: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { +split_lines :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { sep :: "\n" - lines := _split(s, sep, 0, -1, allocator) or_return + lines := _split(s, sep, 0, -1, allocator, loc) or_return for &line in lines { line = _trim_cr(line) } return lines, nil } + /* Splits the input string at every line break `\n` for `n` parts. @@ -1237,6 +1239,7 @@ Inputs: - s: The input string to split. - n: The number of parts to split into. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice (allocated) of the split string (slices into original string) @@ -1260,14 +1263,15 @@ Output: ["a", "b", "c\nd\ne"] */ -split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { +split_lines_n :: proc(s: string, n: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { sep :: "\n" - lines := _split(s, sep, 0, n, allocator) or_return + lines := _split(s, sep, 0, n, allocator, loc) or_return for &line in lines { line = _trim_cr(line) } return lines, nil } + /* Splits the input string at every line break `\n` leaving the `\n` in the resulting strings. @@ -1276,6 +1280,7 @@ Splits the input string at every line break `\n` leaving the `\n` in the resulti Inputs: - s: The input string to split. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice (allocated) of the split string (slices into original string), with `\n` included @@ -1299,14 +1304,15 @@ Output: ["a\n", "b\n", "c\n", "d\n", "e"] */ -split_lines_after :: proc(s: string, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { +split_lines_after :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { sep :: "\n" - lines := _split(s, sep, len(sep), -1, allocator) or_return + lines := _split(s, sep, len(sep), -1, allocator, loc) or_return for &line in lines { line = _trim_cr(line) } return lines, nil } + /* Splits the input string at every line break `\n` leaving the `\n` in the resulting strings. Only runs for n parts. @@ -1317,6 +1323,7 @@ Inputs: - s: The input string to split. - n: The number of parts to split into. - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The slice (allocated) of the split string (slices into original string), with `\n` included @@ -1340,14 +1347,15 @@ Output: ["a\n", "b\n", "c\nd\ne"] */ -split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error { +split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error { sep :: "\n" - lines := _split(s, sep, len(sep), n, allocator) or_return + lines := _split(s, sep, len(sep), n, allocator, loc) or_return for &line in lines { line = _trim_cr(line) } return lines, nil } + /* Splits the input string at every line break `\n`. Returns the current split string every iteration until the string is consumed. @@ -1382,6 +1390,7 @@ split_lines_iterator :: proc(s: ^string) -> (line: string, ok: bool) { line = _split_iterator(s, sep, 0) or_return return _trim_cr(line), true } + /* Splits the input string at every line break `\n`. Returns the current split string with line breaks included every iteration until the string is consumed. @@ -1419,6 +1428,7 @@ split_lines_after_iterator :: proc(s: ^string) -> (line: string, ok: bool) { line = _split_iterator(s, sep, len(sep)) or_return return _trim_cr(line), true } + /* Returns the byte offset of the first byte `c` in the string s it finds, -1 when not found. NOTE: Can't find UTF-8 based runes. @@ -1453,6 +1463,7 @@ Output: index_byte :: proc "contextless" (s: string, c: byte) -> (res: int) { return #force_inline bytes.index_byte(transmute([]u8)s, c) } + /* Returns the byte offset of the last byte `c` in the string `s`, -1 when not found. @@ -1488,6 +1499,7 @@ Output: last_index_byte :: proc "contextless" (s: string, c: byte) -> (res: int) { return #force_inline bytes.last_index_byte(transmute([]u8)s, c) } + /* Returns the byte offset of the first rune `r` in the string `s` it finds, -1 when not found. Invalid runes return -1 @@ -1579,8 +1591,8 @@ Output: -1 */ -index :: proc "contextless" (s, substr: string) -> (res: int) { - hash_str_rabin_karp :: proc "contextless" (s: string) -> (hash: u32 = 0, pow: u32 = 1) { +index :: proc "contextless" (s, substr: string) -> (res: int) #no_bounds_check { + hash_str_rabin_karp :: proc "contextless" (s: string) -> (hash: u32 = 0, pow: u32 = 1) #no_bounds_check { for i := 0; i < len(s); i += 1 { hash = hash*PRIME_RABIN_KARP + u32(s[i]) } @@ -1628,6 +1640,7 @@ index :: proc "contextless" (s, substr: string) -> (res: int) { } return -1 } + /* Returns the last byte offset of the string `substr` in the string `s`, -1 when not found. @@ -1658,8 +1671,8 @@ Output: -1 */ -last_index :: proc(s, substr: string) -> (res: int) { - hash_str_rabin_karp_reverse :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) { +last_index :: proc(s, substr: string) -> (res: int) #no_bounds_check { + hash_str_rabin_karp_reverse :: proc "contextless" (s: string) -> (hash: u32 = 0, pow: u32 = 1) #no_bounds_check { for i := len(s) - 1; i >= 0; i -= 1 { hash = hash*PRIME_RABIN_KARP + u32(s[i]) } @@ -1705,6 +1718,7 @@ last_index :: proc(s, substr: string) -> (res: int) { } return -1 } + /* Returns the index of any first char of `chars` found in `s`, -1 if not found. @@ -1737,7 +1751,7 @@ Output: -1 */ -index_any :: proc(s, chars: string) -> (res: int) { +index_any :: proc(s, chars: string) -> (res: int) #no_bounds_check { if chars == "" { return -1 } @@ -1768,6 +1782,7 @@ index_any :: proc(s, chars: string) -> (res: int) { } return -1 } + /* Finds the last occurrence of any character in `chars` within `s`. Iterates in reverse. @@ -1800,7 +1815,7 @@ Output: -1 */ -last_index_any :: proc(s, chars: string) -> (res: int) { +last_index_any :: proc(s, chars: string) -> (res: int) #no_bounds_check { if chars == "" { return -1 } @@ -1849,6 +1864,7 @@ last_index_any :: proc(s, chars: string) -> (res: int) { } return -1 } + /* Finds the first occurrence of any substring in `substrs` within `s` @@ -1860,7 +1876,7 @@ Returns: - idx: the index of the first matching substring - width: the length of the found substring */ -index_multi :: proc(s: string, substrs: []string) -> (idx: int, width: int) { +index_multi :: proc(s: string, substrs: []string) -> (idx: int, width: int) #no_bounds_check { idx = -1 if s == "" || len(substrs) <= 0 { return @@ -1890,6 +1906,7 @@ index_multi :: proc(s: string, substrs: []string) -> (idx: int, width: int) { } return } + /* Counts the number of non-overlapping occurrences of `substr` in `s` @@ -1922,7 +1939,7 @@ Output: 0 */ -count :: proc(s, substr: string) -> (res: int) { +count :: proc(s, substr: string) -> (res: int) #no_bounds_check { if len(substr) == 0 { // special case return rune_count(s) + 1 } @@ -1956,6 +1973,7 @@ count :: proc(s, substr: string) -> (res: int) { } return n } + /* Repeats the string `s` `count` times, concatenating the result @@ -1965,6 +1983,7 @@ Inputs: - s: The string to repeat - count: The number of times to repeat `s` - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The concatenated repeated string @@ -1986,7 +2005,7 @@ Output: abcabc */ -repeat :: proc(s: string, count: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +repeat :: proc(s: string, count: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { if count < 0 { panic("strings: negative repeat count") } else if count > 0 && (len(s)*count)/count != len(s) { @@ -1995,12 +2014,13 @@ repeat :: proc(s: string, count: int, allocator := context.allocator, loc := #ca b := make([]byte, len(s)*count, allocator, loc) or_return i := copy(b, s) - for i < len(b) { // 2^N trick to reduce the need to copy + #no_bounds_check for i < len(b) { // 2^N trick to reduce the need to copy copy(b[i:], b[:i]) i *= 2 } return string(b), nil } + /* Replaces all occurrences of `old` in `s` with `new` @@ -2011,6 +2031,7 @@ Inputs: - old: The substring to replace - new: The substring to replace `old` with - allocator: The allocator to use for the new string (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - output: The modified string @@ -2034,9 +2055,11 @@ Output: zzzz true */ -replace_all :: proc(s, old, new: string, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return replace(s, old, new, -1, allocator) + +replace_all :: proc(s, old, new: string, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool) { + return replace(s, old, new, -1, allocator, loc) } + /* Replaces n instances of old in the string s with the new string @@ -2048,6 +2071,7 @@ Inputs: - new: The replacement string - n: The number of instances to replace (if `n < 0`, no limit on the number of replacements) - allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - output: The modified string @@ -2097,7 +2121,7 @@ replace :: proc(s, old, new: string, n: int, allocator := context.allocator, loc w := 0 start := 0 - for i := 0; i < byte_count; i += 1 { + #no_bounds_check for i := 0; i < byte_count; i += 1 { j := start if len(old) == 0 { if i > 0 { @@ -2115,6 +2139,7 @@ replace :: proc(s, old, new: string, n: int, allocator := context.allocator, loc output = string(t[0:w]) return } + /* Removes the key string `n` times from the `s` string @@ -2125,6 +2150,7 @@ Inputs: - key: The substring to be removed - n: The number of instances to remove (if `n < 0`, no limit on the number of removes) - allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - output: The modified string @@ -2150,9 +2176,10 @@ Output: abcabc false */ -remove :: proc(s, key: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return replace(s, key, "", n, allocator) +remove :: proc(s, key: string, n: int, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool) { + return replace(s, key, "", n, allocator, loc) } + /* Removes all the `key` string instances from the `s` string @@ -2162,6 +2189,7 @@ Inputs: - s: The input string - key: The substring to be removed - allocator: (default: context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - output: The modified string @@ -2185,9 +2213,10 @@ Output: abcabc false */ -remove_all :: proc(s, key: string, allocator := context.allocator) -> (output: string, was_allocation: bool) { - return remove(s, key, -1, allocator) +remove_all :: proc(s, key: string, allocator := context.allocator, loc := #caller_location) -> (output: string, was_allocation: bool) { + return remove(s, key, -1, allocator, loc) } + // Returns true if is an ASCII space character ('\t', '\n', '\v', '\f', '\r', ' ') @(private) _ascii_space := [256]bool{'\t' = true, '\n' = true, '\v' = true, '\f' = true, '\r' = true, ' ' = true} @@ -2291,6 +2320,7 @@ index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> (res: int } return -1 } + // Same as `index_proc`, but the procedure p takes a raw pointer for state index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> (res: int) { for r, i in s { @@ -2300,6 +2330,7 @@ index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: r } return -1 } + // Finds the index of the *last* rune in the string s for which the procedure p returns the same value as truth last_index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> (res: int) { // TODO(bill): Probably use Rabin-Karp Search @@ -2312,6 +2343,7 @@ last_index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> (res } return -1 } + // Same as `index_proc_with_state`, runs through the string in reverse last_index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> (res: int) { // TODO(bill): Probably use Rabin-Karp Search @@ -2324,6 +2356,7 @@ last_index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, sta } return -1 } + /* Trims the input string `s` from the left until the procedure `p` returns false @@ -2358,6 +2391,7 @@ trim_left_proc :: proc(s: string, p: proc(rune) -> bool) -> (res: string) { } return s[i:] } + /* Trims the input string `s` from the left until the procedure `p` with state returns false @@ -2376,6 +2410,7 @@ trim_left_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, stat } return s[i:] } + /* Trims the input string `s` from the right until the procedure `p` returns `false` @@ -2403,7 +2438,7 @@ Output: test */ -trim_right_proc :: proc(s: string, p: proc(rune) -> bool) -> (res: string) { +trim_right_proc :: proc(s: string, p: proc(rune) -> bool) -> (res: string) #no_bounds_check { i := last_index_proc(s, p, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { _, w := utf8.decode_rune_in_string(s[i:]) @@ -2413,6 +2448,7 @@ trim_right_proc :: proc(s: string, p: proc(rune) -> bool) -> (res: string) { } return s[0:i] } + /* Trims the input string `s` from the right until the procedure `p` with state returns `false` @@ -2424,7 +2460,7 @@ Inputs: Returns: - res: The trimmed string as a slice of the original, empty when no match */ -trim_right_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> (res: string) { +trim_right_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> (res: string) #no_bounds_check { i := last_index_proc_with_state(s, p, state, false) if i >= 0 && s[i] >= utf8.RUNE_SELF { _, w := utf8.decode_rune_in_string(s[i:]) @@ -2434,6 +2470,7 @@ trim_right_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, sta } return s[0:i] } + // Procedure for `trim_*_proc` variants, which has a string rawptr cast + rune comparison is_in_cutset :: proc(state: rawptr, r: rune) -> (res: bool) { cutset := (^string)(state)^ @@ -2444,6 +2481,7 @@ is_in_cutset :: proc(state: rawptr, r: rune) -> (res: bool) { } return false } + /* Trims the cutset string from the `s` string @@ -2461,6 +2499,7 @@ trim_left :: proc(s: string, cutset: string) -> (res: string) { state := cutset return trim_left_proc_with_state(s, is_in_cutset, &state) } + /* Trims the cutset string from the `s` string from the right @@ -2478,6 +2517,7 @@ trim_right :: proc(s: string, cutset: string) -> (res: string) { state := cutset return trim_right_proc_with_state(s, is_in_cutset, &state) } + /* Trims the cutset string from the `s` string, both from left and right @@ -2491,6 +2531,7 @@ Returns: trim :: proc(s: string, cutset: string) -> (res: string) { return trim_right(trim_left(s, cutset), cutset) } + /* Trims until a valid non-space rune from the left, "\t\txyz\t\t" -> "xyz\t\t" @@ -2503,6 +2544,7 @@ Returns: trim_left_space :: proc(s: string) -> (res: string) { return trim_left_proc(s, is_space) } + /* Trims from the right until a valid non-space rune, "\t\txyz\t\t" -> "\t\txyz" @@ -2515,6 +2557,7 @@ Returns: trim_right_space :: proc(s: string) -> (res: string) { return trim_right_proc(s, is_space) } + /* Trims from both sides until a valid non-space rune, "\t\txyz\t\t" -> "xyz" @@ -2527,6 +2570,7 @@ Returns: trim_space :: proc(s: string) -> (res: string) { return trim_right_space(trim_left_space(s)) } + /* Trims null runes from the left, "\x00\x00testing\x00\x00" -> "testing\x00\x00" @@ -2539,6 +2583,7 @@ Returns: trim_left_null :: proc(s: string) -> (res: string) { return trim_left_proc(s, is_null) } + /* Trims null runes from the right, "\x00\x00testing\x00\x00" -> "\x00\x00testing" @@ -2551,6 +2596,7 @@ Returns: trim_right_null :: proc(s: string) -> (res: string) { return trim_right_proc(s, is_null) } + /* Trims null runes from both sides, "\x00\x00testing\x00\x00" -> "testing" @@ -2562,6 +2608,7 @@ Returns: trim_null :: proc(s: string) -> (res: string) { return trim_right_null(trim_left_null(s)) } + /* Trims a `prefix` string from the start of the `s` string and returns the trimmed string @@ -2588,12 +2635,13 @@ Output: testing */ -trim_prefix :: proc(s, prefix: string) -> (res: string) { +trim_prefix :: proc(s, prefix: string) -> (res: string) #no_bounds_check { if has_prefix(s, prefix) { return s[len(prefix):] } return s } + /* Trims a `suffix` string from the end of the `s` string and returns the trimmed string @@ -2620,12 +2668,13 @@ Output: todo.doc */ -trim_suffix :: proc(s, suffix: string) -> (res: string) { +trim_suffix :: proc(s, suffix: string) -> (res: string) #no_bounds_check { if has_suffix(s, suffix) { return s[:len(s)-len(suffix)] } return s } + /* Splits the input string `s` by all possible `substrs` and returns an allocated array of strings @@ -2635,6 +2684,7 @@ Inputs: - s: The input string - substrs: An array of substrings used for splitting - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: An array of strings, or nil on empty substring or no matches @@ -2658,7 +2708,7 @@ Output: ["testing", "this", "out", "nice", "done", "last"] */ -split_multi :: proc(s: string, substrs: []string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check { +split_multi :: proc(s: string, substrs: []string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { if s == "" || len(substrs) <= 0 { return nil, nil } @@ -2698,6 +2748,7 @@ split_multi :: proc(s: string, substrs: []string, allocator := context.allocator assert(len(results) == n) return results[:], nil } + /* Splits the input string `s` by all possible `substrs` in an iterator fashion. The full string is returned if no match. @@ -2757,6 +2808,7 @@ split_multi_iterate :: proc(it: ^string, substrs: []string) -> (res: string, ok: ok = true return } + /* Replaces invalid UTF-8 characters in the input string with a specified replacement string. Adjacent invalid bytes are only replaced once. @@ -2766,6 +2818,7 @@ Inputs: - s: The input string - replacement: The string used to replace invalid UTF-8 characters - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A new string with invalid UTF-8 characters replaced @@ -2786,16 +2839,16 @@ Output: Hello? */ -scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +scrub :: proc(s: string, replacement: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { str := s b: Builder - builder_init(&b, 0, len(s), allocator) or_return + builder_init(&b, 0, len(s), allocator, loc) or_return has_error := false cursor := 0 origin := str - for len(str) > 0 { + #no_bounds_check for len(str) > 0 { r, w := utf8.decode_rune_in_string(str) if r == utf8.RUNE_ERROR { @@ -2817,6 +2870,7 @@ scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> return to_string(b), nil } + /* Reverses the input string `s` @@ -2825,6 +2879,7 @@ Reverses the input string `s` Inputs: - s: The input string - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A reversed version of the input string @@ -2846,13 +2901,13 @@ Output: abcxyz zyxcba */ -reverse :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +reverse :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { str := s n := len(str) buf := make([]byte, n, allocator, loc) or_return i := n - for len(str) > 0 { + #no_bounds_check for len(str) > 0 { _, w := utf8.decode_rune_in_string(str) i -= w copy(buf[i:], str[:w]) @@ -2860,6 +2915,7 @@ reverse :: proc(s: string, allocator := context.allocator, loc := #caller_locati } return string(buf), nil } + /* Expands the input string by replacing tab characters with spaces to align to a specified tab size @@ -2869,6 +2925,7 @@ Inputs: - s: The input string - tab_size: The number of spaces to use for each tab character - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A new string with tab characters expanded to the specified tab size @@ -2891,7 +2948,7 @@ Output: abc1 abc2 abc3 */ -expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { if tab_size <= 0 { panic("tab size must be positive") } @@ -2901,12 +2958,12 @@ expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) -> } b: Builder - builder_init(&b, allocator) or_return + builder_init(&b, allocator, loc) or_return writer := to_writer(&b) str := s column: int - for len(str) > 0 { + #no_bounds_check for len(str) > 0 { r, w := utf8.decode_rune_in_string(str) if r == '\t' { @@ -2932,6 +2989,7 @@ expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) -> return to_string(b), nil } + /* Splits the input string `str` by the separator `sep` string and returns 3 parts. The values are slices of the original string. @@ -2970,7 +3028,7 @@ Output: true */ -partition :: proc(str, sep: string) -> (head, match, tail: string) { +partition :: proc(str, sep: string) -> (head, match, tail: string) #no_bounds_check { i := index(str, sep) if i == -1 { head = str @@ -2982,8 +3040,10 @@ partition :: proc(str, sep: string) -> (head, match, tail: string) { tail = str[i+len(sep):] return } + // Alias for centre_justify center_justify :: centre_justify // NOTE(bill): Because Americans exist + /* Centers the input string within a field of specified length by adding pad string on both sides, if its length is less than the target length. @@ -2994,22 +3054,23 @@ Inputs: - length: The desired length of the centered string, in runes - pad: The string used for padding on both sides - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A new string centered within a field of the specified length - err: An optional allocator error if one occured, `nil` otherwise */ -centre_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +centre_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-n pad_len := rune_count(pad) b: Builder - builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) or_return + builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) or_return w := to_writer(&b) @@ -3019,6 +3080,7 @@ centre_justify :: proc(str: string, length: int, pad: string, allocator := conte return to_string(b), nil } + /* Left-justifies the input string within a field of specified length by adding pad string on the right side, if its length is less than the target length. @@ -3029,22 +3091,23 @@ Inputs: - length: The desired length of the left-justified string - pad: The string used for padding on the right side - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A new string left-justified within a field of the specified length - err: An optional allocator error if one occured, `nil` otherwise */ -left_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +left_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-n pad_len := rune_count(pad) b: Builder - builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) or_return + builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) or_return w := to_writer(&b) @@ -3053,6 +3116,7 @@ left_justify :: proc(str: string, length: int, pad: string, allocator := context return to_string(b), nil } + /* Right-justifies the input string within a field of specified length by adding pad string on the left side, if its length is less than the target length. @@ -3063,22 +3127,23 @@ Inputs: - length: The desired length of the right-justified string - pad: The string used for padding on the left side - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: A new string right-justified within a field of the specified length - err: An optional allocator error if one occured, `nil` otherwise */ -right_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) #optional_allocator_error { +right_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: runtime.Allocator_Error) #optional_allocator_error { n := rune_count(str) if n >= length || pad == "" { - return clone(str, allocator) + return clone(str, allocator, loc) } remains := length-n pad_len := rune_count(pad) b: Builder - builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator) or_return + builder_init(&b, 0, len(str) + (remains/pad_len + 1)*len(pad), allocator, loc) or_return w := to_writer(&b) @@ -3087,6 +3152,7 @@ right_justify :: proc(str: string, length: int, pad: string, allocator := contex return to_string(b), nil } + /* Writes a given pad string a specified number of times to an `io.Writer` @@ -3100,19 +3166,20 @@ Inputs: write_pad_string :: proc(w: io.Writer, pad: string, pad_len, remains: int) { repeats := remains / pad_len - for i := 0; i < repeats; i += 1 { + for _ in 0.. (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check { +fields :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { n := 0 was_space := 1 set_bits := u8(0) @@ -3174,6 +3242,7 @@ fields :: proc(s: string, allocator := context.allocator, loc := #caller_locatio } return a, nil } + /* Splits a string into a slice of substrings at each run of unicode code points `r` satisfying the predicate `f(r)` @@ -3183,6 +3252,7 @@ Inputs: - s: The input string - f: A predicate function to determine the split points - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) NOTE: fields_proc makes no guarantee about the order in which it calls `f(r)`, it assumes that `f` always returns the same value for a given `r` @@ -3190,7 +3260,7 @@ Returns: - res: A slice of substrings of the input string, or an empty slice if all code points in the input string satisfy the predicate or if the input string is empty - err: An optional allocator error if one occured, `nil` otherwise */ -fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: mem.Allocator_Error) #optional_allocator_error #no_bounds_check { +fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator, loc := #caller_location) -> (res: []string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { substrings := make([dynamic]string, 0, 32, allocator, loc) or_return start, end := -1, -1 @@ -3216,6 +3286,7 @@ fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.alloc return substrings[:], nil } + /* Retrieves the first non-space substring from a mutable string reference and advances the reference. `s` is advanced from any space after the substring, or be an empty string if the substring was the remaining characters @@ -3226,7 +3297,7 @@ Returns: - field: The first non-space substring found - ok: A boolean indicating if a non-space substring was found */ -fields_iterator :: proc(s: ^string) -> (field: string, ok: bool) { +fields_iterator :: proc(s: ^string) -> (field: string, ok: bool) #no_bounds_check { start, end := -1, -1 for r, offset in s { end = offset @@ -3254,6 +3325,7 @@ fields_iterator :: proc(s: ^string) -> (field: string, ok: bool) { s^ = s[len(s):] return } + /* Computes the Levenshtein edit distance between two strings @@ -3264,6 +3336,7 @@ NOTE: Does not perform internal allocation if length of string `b`, in runes, is Inputs: - a, b: The two strings to compare - allocator: (default is context.allocator) +- loc: The caller location for debugging purposes (default: `#caller_location`) Returns: - res: The Levenshtein edit distance between the two strings @@ -3271,7 +3344,7 @@ Returns: NOTE: This implementation is a single-row-version of the Wagner–Fischer algorithm, based on C code by Martin Ettl. */ -levenshtein_distance :: proc(a, b: string, allocator := context.allocator, loc := #caller_location) -> (res: int, err: mem.Allocator_Error) #optional_allocator_error { +levenshtein_distance :: proc(a, b: string, allocator := context.allocator, loc := #caller_location) -> (res: int, err: runtime.Allocator_Error) #optional_allocator_error { LEVENSHTEIN_DEFAULT_COSTS: []int : { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, @@ -3331,7 +3404,7 @@ levenshtein_distance :: proc(a, b: string, allocator := context.allocator, loc : } @(private) -internal_substring :: proc(s: string, rune_start: int, rune_end: int) -> (sub: string, ok: bool) { +internal_substring :: proc(s: string, rune_start: int, rune_end: int) -> (sub: string, ok: bool) #no_bounds_check { sub = s ok = true @@ -3347,7 +3420,9 @@ internal_substring :: proc(s: string, rune_start: int, rune_end: int) -> (sub: s } rune_i += 1 } - if !ok { return } + if !ok { + sub = sub[rune_i:] + } } if rune_end >= rune_start { @@ -3431,4 +3506,4 @@ substring_to :: proc(s: string, rune_end: int) -> (sub: string, ok: bool) { } return internal_substring(s, -1, rune_end) -} +} \ No newline at end of file diff --git a/core/sync/atomic.odin b/core/sync/atomic.odin index 7e514a6b4..f680c7aa3 100644 --- a/core/sync/atomic.odin +++ b/core/sync/atomic.odin @@ -27,7 +27,7 @@ multiple memory locations between two cores. Which is why CPU's allow for stronger memory ordering guarantees if certain instructions or instruction variants are used. -In Odin there are 5 different memory ordering guaranties that can be provided +In Odin there are 5 different memory ordering guarantees that can be provided to an atomic operation: - `Relaxed`: The memory access (load or store) is unordered with respect to @@ -450,4 +450,4 @@ the load operation, if the comparison fails. The memory ordering for these operations is as specified by the `success` and `failure` parameters respectively. */ -atomic_compare_exchange_weak_explicit :: intrinsics.atomic_compare_exchange_weak_explicit \ No newline at end of file +atomic_compare_exchange_weak_explicit :: intrinsics.atomic_compare_exchange_weak_explicit diff --git a/core/sync/chan/chan.odin b/core/sync/chan/chan.odin index eca4c28d7..5daabe2eb 100644 --- a/core/sync/chan/chan.odin +++ b/core/sync/chan/chan.odin @@ -3,10 +3,17 @@ package sync_chan import "base:builtin" import "base:intrinsics" import "base:runtime" -import "core:mem" import "core:sync" import "core:math/rand" +when ODIN_TEST { +/* +Hook for testing _try_select_raw allowing the test harness to manipulate the +channels prior to the select actually operating on them. +*/ +__try_select_raw_pause : proc() = nil +} + /* Determines what operations `Chan` supports. */ @@ -75,6 +82,8 @@ Raw_Chan :: struct { r_waiting: int, // guarded by `mutex` w_waiting: int, // guarded by `mutex` + did_read: bool, // lets a sender know if the value was read + // Buffered queue: ^Raw_Queue, @@ -245,20 +254,20 @@ Example: } */ @(require_results) -create_raw_unbuffered :: proc(#any_int msg_size, msg_alignment: int, allocator: runtime.Allocator) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { +create_raw_unbuffered :: proc(#any_int msg_size, msg_alignment: int, allocator: runtime.Allocator, loc := #caller_location) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { assert(msg_size <= int(max(u16))) align := max(align_of(Raw_Chan), msg_alignment) - size := mem.align_forward_int(size_of(Raw_Chan), align) + size := runtime.align_forward_int(size_of(Raw_Chan), align) offset := size size += msg_size - size = mem.align_forward_int(size, align) + size = runtime.align_forward_int(size, align) - ptr := mem.alloc(size, align, allocator) or_return - c = (^Raw_Chan)(ptr) + data := runtime.mem_alloc(size, align, allocator, loc) or_return + c = (^Raw_Chan)(raw_data(data)) c.allocator = allocator c.allocation_size = size - c.unbuffered_data = ([^]byte)(ptr)[offset:] + c.unbuffered_data = raw_data(data[offset:]) c.msg_size = u16(msg_size) return } @@ -290,7 +299,7 @@ Example: } */ @(require_results) -create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: int, allocator: runtime.Allocator) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { +create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: int, allocator: runtime.Allocator, loc := #caller_location) -> (c: ^Raw_Chan, err: runtime.Allocator_Error) { assert(msg_size <= int(max(u16))) if cap <= 0 { return create_raw_unbuffered(msg_size, msg_alignment, allocator) @@ -298,15 +307,16 @@ create_raw_buffered :: proc(#any_int msg_size, msg_alignment: int, #any_int cap: align := max(align_of(Raw_Chan), msg_alignment, align_of(Raw_Queue)) - size := mem.align_forward_int(size_of(Raw_Chan), align) + size := runtime.align_forward_int(size_of(Raw_Chan), align) q_offset := size - size = mem.align_forward_int(q_offset + size_of(Raw_Queue), msg_alignment) + size = runtime.align_forward_int(q_offset + size_of(Raw_Queue), msg_alignment) offset := size size += msg_size * cap - size = mem.align_forward_int(size, align) + size = runtime.align_forward_int(size, align) - ptr := mem.alloc(size, align, allocator) or_return - c = (^Raw_Chan)(ptr) + data := runtime.mem_alloc(size, align, allocator, loc) or_return + ptr := raw_data(data) + c = (^Raw_Chan)(raw_data(data)) c.allocator = allocator c.allocation_size = size @@ -329,10 +339,10 @@ Destroys the Channel. **Returns**: - An `Allocator_Error` */ -destroy :: proc(c: ^Raw_Chan) -> (err: runtime.Allocator_Error) { +destroy :: proc(c: ^Raw_Chan, loc := #caller_location) -> (err: runtime.Allocator_Error) { if c != nil { allocator := c.allocator - err = mem.free_with_size(c, c.allocation_size, allocator) + err = runtime.mem_free_with_size(c, c.allocation_size, allocator, loc) } return } @@ -412,8 +422,8 @@ as_recv :: #force_inline proc "contextless" (c: $C/Chan($T, $D)) -> (r: Chan(T, Sends the specified message, blocking the current thread if: - the channel is unbuffered - the channel's buffer is full -until the channel is being read from. `send` will return -`false` when attempting to send on an already closed channel. +until the channel is being read from or the channel is closed. `send` will +return `false` when attempting to send on an already closed channel. **Inputs** - `c`: The channel @@ -484,8 +494,9 @@ try_send :: proc "contextless" (c: $C/Chan($T, $D), data: T) -> (ok: bool) where Reads a message from the channel, blocking the current thread if: - the channel is unbuffered - the channel's buffer is empty -until the channel is being written to. `recv` will return -`false` when attempting to receive a message on an already closed channel. +until the channel is being written to or the channel is closed. `recv` will +return `false` when attempting to receive a message on an already closed +channel. **Inputs** - `c`: The channel @@ -558,8 +569,8 @@ try_recv :: proc "contextless" (c: $C/Chan($T)) -> (data: T, ok: bool) where C.D Sends the specified message, blocking the current thread if: - the channel is unbuffered - the channel's buffer is full -until the channel is being read from. `send_raw` will return -`false` when attempting to send on an already closed channel. +until the channel is being read from or the channel is closed. `send_raw` will +return `false` when attempting to send on an already closed channel. Note: The message referenced by `msg_out` must match the size and alignment used when the `Raw_Chan` was created. @@ -619,12 +630,23 @@ send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) { return false } - mem.copy(c.unbuffered_data, msg_in, int(c.msg_size)) + c.did_read = false + defer c.did_read = false + + intrinsics.mem_copy(c.unbuffered_data, msg_in, int(c.msg_size)) + c.w_waiting += 1 + if c.r_waiting > 0 { sync.signal(&c.r_cond) } + sync.wait(&c.w_cond, &c.mutex) + + if c.closed && !c.did_read { + return false + } + ok = true } return @@ -634,8 +656,9 @@ send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) { Reads a message from the channel, blocking the current thread if: - the channel is unbuffered - the channel's buffer is empty -until the channel is being written to. `recv_raw` will return -`false` when attempting to receive a message on an already closed channel. +until the channel is being written to or the channel is closed. `recv_raw` +will return `false` when attempting to receive a message on an already closed +channel. Note: The location pointed to by `msg_out` must match the size and alignment used when the `Raw_Chan` was created. @@ -688,7 +711,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { msg := raw_queue_pop(c.queue) if msg != nil { - mem.copy(msg_out, msg, int(c.msg_size)) + intrinsics.mem_copy(msg_out, msg, int(c.msg_size)) } if c.w_waiting > 0 { @@ -698,8 +721,7 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { } else if c.unbuffered_data != nil { // unbuffered sync.guard(&c.mutex) - for !c.closed && - c.w_waiting == 0 { + for !c.closed && c.w_waiting == 0 { c.r_waiting += 1 sync.wait(&c.r_cond, &c.mutex) c.r_waiting -= 1 @@ -709,9 +731,10 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) { return } - mem.copy(msg_out, c.unbuffered_data, int(c.msg_size)) + intrinsics.mem_copy(msg_out, c.unbuffered_data, int(c.msg_size)) c.w_waiting -= 1 + c.did_read = true sync.signal(&c.w_cond) ok = true } @@ -771,11 +794,11 @@ try_send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) } else if c.unbuffered_data != nil { // unbuffered sync.guard(&c.mutex) - if c.closed { + if c.closed || c.r_waiting - c.w_waiting <= 0 { return false } - mem.copy(c.unbuffered_data, msg_in, int(c.msg_size)) + intrinsics.mem_copy(c.unbuffered_data, msg_in, int(c.msg_size)) c.w_waiting += 1 if c.r_waiting > 0 { sync.signal(&c.r_cond) @@ -825,7 +848,7 @@ try_recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> bool { msg := raw_queue_pop(c.queue) if msg != nil { - mem.copy(msg_out, msg, int(c.msg_size)) + intrinsics.mem_copy(msg_out, msg, int(c.msg_size)) } if c.w_waiting > 0 { @@ -835,11 +858,11 @@ try_recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> bool { } else if c.unbuffered_data != nil { // unbuffered sync.guard(&c.mutex) - if c.closed || c.w_waiting == 0 { + if c.closed || c.w_waiting - c.r_waiting <= 0 { return false } - mem.copy(msg_out, c.unbuffered_data, int(c.msg_size)) + intrinsics.mem_copy(msg_out, c.unbuffered_data, int(c.msg_size)) c.w_waiting -= 1 sync.signal(&c.w_cond) @@ -1038,8 +1061,9 @@ is_closed :: proc "contextless" (c: ^Raw_Chan) -> bool { } /* -Returns whether a message is ready to be read, i.e., -if a call to `recv` or `recv_raw` would block +Returns whether a message can be read without blocking the current +thread. Specifically, it checks if the channel is buffered and not full, +or if there is already a writer attempting to send a message. **Inputs** - `c`: The channel @@ -1067,7 +1091,7 @@ can_recv :: proc "contextless" (c: ^Raw_Chan) -> bool { if is_buffered(c) { return c.queue.len > 0 } - return c.w_waiting > 0 + return c.w_waiting - c.r_waiting > 0 } @@ -1080,7 +1104,7 @@ or if there is already a reader waiting for a message. - `c`: The channel **Returns** -- `true` if a message can be send, `false` otherwise +- `true` if a message can be sent, `false` otherwise Example: @@ -1102,18 +1126,30 @@ can_send :: proc "contextless" (c: ^Raw_Chan) -> bool { if is_buffered(c) { return c.queue.len < c.queue.cap } - return c.w_waiting == 0 + return c.r_waiting - c.w_waiting > 0 +} + +/* +Specifies the direction of the selected channel. +*/ +Select_Status :: enum { + None, + Recv, + Send, } /* -Attempts to either send or receive messages on the specified channels. +Attempts to either send or receive messages on the specified channels without blocking. -`select_raw` first identifies which channels have messages ready to be received +`try_select_raw` first identifies which channels have messages ready to be received and which are available for sending. It then randomly selects one operation (either a send or receive) to perform. +If no channels have messages ready, the procedure is a noop. + Note: Each message in `send_msgs` corresponds to the send channel at the same index in `sends`. +If the message is nil, corresponding send channel will be skipped. **Inputs** - `recv`: A slice of channels to read from @@ -1130,7 +1166,7 @@ Example: import "core:sync/chan" import "core:fmt" - select_raw_example :: proc() { + try_select_raw_example :: proc() { c, err := chan.create(chan.Chan(int), 1, context.allocator) assert(err == .None) defer chan.destroy(c) @@ -1145,32 +1181,32 @@ Example: // where the value from the read should be stored received_value: int - idx, ok := chan.select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) + idx, ok := chan.try_select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) fmt.println("SELECT: ", idx, ok) fmt.println("RECEIVED VALUE ", received_value) - idx, ok = chan.select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) + idx, ok = chan.try_select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) fmt.println("SELECT: ", idx, ok) fmt.println("RECEIVED VALUE ", received_value) // closing of a channel also affects the select operation chan.close(c) - idx, ok = chan.select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) + idx, ok = chan.try_select_raw(receive_chans[:], send_chans[:], msgs[:], &received_value) fmt.println("SELECT: ", idx, ok) } Output: - SELECT: 0 true + SELECT: 0 Send RECEIVED VALUE 0 - SELECT: 0 true + SELECT: 0 Recv RECEIVED VALUE 1 - SELECT: 0 false + SELECT: -1 None */ @(require_results) -select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []rawptr, recv_out: rawptr) -> (select_idx: int, ok: bool) #no_bounds_check { +try_select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []rawptr, recv_out: rawptr) -> (select_idx: int, status: Select_Status) #no_bounds_check { Select_Op :: struct { idx: int, // local to the slice that was given is_recv: bool, @@ -1178,43 +1214,66 @@ select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: [] candidate_count := builtin.len(recvs)+builtin.len(sends) candidates := ([^]Select_Op)(intrinsics.alloca(candidate_count*size_of(Select_Op), align_of(Select_Op))) - count := 0 - for c, i in recvs { - if can_recv(c) { - candidates[count] = { - is_recv = true, - idx = i, + try_loop: for { + count := 0 + + for c, i in recvs { + if !c.closed && can_recv(c) { + candidates[count] = { + is_recv = true, + idx = i, + } + count += 1 } - count += 1 } - } - for c, i in sends { - if can_send(c) { - candidates[count] = { - is_recv = false, - idx = i, + for c, i in sends { + if i > builtin.len(send_msgs)-1 || send_msgs[i] == nil { + continue + } + if !c.closed && can_send(c) { + candidates[count] = { + is_recv = false, + idx = i, + } + count += 1 } - count += 1 } - } - if count == 0 { - return - } + if count == 0 { + return -1, .None + } - select_idx = rand.int_max(count) if count > 0 else 0 + when ODIN_TEST { + if __try_select_raw_pause != nil { + __try_select_raw_pause() + } + } - sel := candidates[select_idx] - if sel.is_recv { - ok = recv_raw(recvs[sel.idx], recv_out) - } else { - ok = send_raw(sends[sel.idx], send_msgs[sel.idx]) + candidate_idx := rand.int_max(count) if count > 0 else 0 + + sel := candidates[candidate_idx] + if sel.is_recv { + status = .Recv + if !try_recv_raw(recvs[sel.idx], recv_out) { + continue try_loop + } + } else { + status = .Send + if !try_send_raw(sends[sel.idx], send_msgs[sel.idx]) { + continue try_loop + } + } + + return sel.idx, status } - return } +@(require_results, deprecated = "use try_select_raw") +select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []rawptr, recv_out: rawptr) -> (select_idx: int, status: Select_Status) #no_bounds_check { + return try_select_raw(recvs, sends, send_msgs, recv_out) +} /* `Raw_Queue` is a non-thread-safe queue implementation designed to store messages @@ -1300,7 +1359,7 @@ raw_queue_push :: proc "contextless" (q: ^Raw_Queue, data: rawptr) -> bool { } val_ptr := q.data[pos*q.size:] - mem.copy(val_ptr, data, q.size) + intrinsics.mem_copy(val_ptr, data, q.size) q.len += 1 return true } diff --git a/core/sync/chan/doc.odin b/core/sync/chan/doc.odin index 5d65d7410..63e633531 100644 --- a/core/sync/chan/doc.odin +++ b/core/sync/chan/doc.odin @@ -1,6 +1,5 @@ /* -This package provides both high-level and low-level channel types -for thread-safe communication. +High-level and low-level channel types for thread-safe communication. While channels are essentially thread-safe queues under the hood, their primary purpose is to facilitate safe communication between diff --git a/core/sync/doc.odin b/core/sync/doc.odin index 320732ea7..faae245c4 100644 --- a/core/sync/doc.odin +++ b/core/sync/doc.odin @@ -1,11 +1,7 @@ /* -Synchronization primitives +Various synchronization primitives useful to mediate threads' access to shared memory. -This package implements various synchronization primitives that can be used to -synchronize threads' access to shared memory. - -To limit or control the threads' access to shared memory typically the -following approaches are used: +To limit or control the threads' access to shared memory typically the following approaches are used: - Locks - Lock-free diff --git a/core/sync/extended.odin b/core/sync/extended.odin index 0cea38d7f..58344b740 100644 --- a/core/sync/extended.odin +++ b/core/sync/extended.odin @@ -26,7 +26,7 @@ is not allowed to become negative. **Note**: Just like any synchronization primitives, a wait group cannot be copied after first use. See documentation for `Mutex` or `Cond`. */ -Wait_Group :: struct #no_copy { +Wait_Group :: struct { counter: int, mutex: Mutex, cond: Cond, @@ -47,12 +47,12 @@ wait_group_add :: proc "contextless" (wg: ^Wait_Group, delta: int) { guard(&wg.mutex) atomic_add(&wg.counter, delta) - if wg.counter < 0 { + switch counter := atomic_load(&wg.counter); { + case counter < 0: panic_contextless("sync.Wait_Group negative counter") - } - if wg.counter == 0 { + case wg.counter == 0: cond_broadcast(&wg.cond) - if wg.counter != 0 { + if atomic_load(&wg.counter) != 0 { panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") } } @@ -78,11 +78,8 @@ wait group's internal counter reaches zero. wait_group_wait :: proc "contextless" (wg: ^Wait_Group) { guard(&wg.mutex) - if wg.counter != 0 { + for atomic_load(&wg.counter) != 0 { cond_wait(&wg.cond, &wg.mutex) - if wg.counter != 0 { - panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") - } } } @@ -100,13 +97,10 @@ wait_group_wait_with_timeout :: proc "contextless" (wg: ^Wait_Group, duration: t } guard(&wg.mutex) - if wg.counter != 0 { + for atomic_load(&wg.counter) != 0 { if !cond_wait_with_timeout(&wg.cond, &wg.mutex, duration) { return false } - if wg.counter != 0 { - panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") - } } return true } @@ -150,7 +144,7 @@ thread procedure. thread.destroy(t) } */ -Barrier :: struct #no_copy { +Barrier :: struct { mutex: Mutex, cond: Cond, index: int, @@ -212,7 +206,7 @@ When a thread calls `auto_reset_event_wait`, its execution will be blocked, until the event is signalled by another thread. The call to `auto_reset_event_signal` wakes up exactly one thread waiting for the event. */ -Auto_Reset_Event :: struct #no_copy { +Auto_Reset_Event :: struct { // status == 0: Event is reset and no threads are waiting // status == 1: Event is signalled // status == -N: Event is reset and N threads are waiting @@ -228,9 +222,10 @@ thread. */ auto_reset_event_signal :: proc "contextless" (e: ^Auto_Reset_Event) { old_status := atomic_load_explicit(&e.status, .Relaxed) - new_status := old_status + 1 if old_status < 1 else 1 for { - if _, ok := atomic_compare_exchange_weak_explicit(&e.status, old_status, new_status, .Release, .Relaxed); ok { + new_status := old_status + 1 if old_status < 1 else 1 + ok: bool + if old_status, ok = atomic_compare_exchange_weak_explicit(&e.status, old_status, new_status, .Release, .Relaxed); ok { break } cpu_relax() @@ -266,7 +261,7 @@ of entries into the critical section. This type of synchronization primitive is applicable for short critical sections in low-contention systems, as it uses a spinlock under the hood. */ -Ticket_Mutex :: struct #no_copy { +Ticket_Mutex :: struct { ticket: uint, serving: uint, } @@ -338,7 +333,7 @@ Once a lock on a benaphore is acquired by a thread, no other thread is allowed into any critical sections, associted with the same benaphore, until the lock is released. */ -Benaphore :: struct #no_copy { +Benaphore :: struct { counter: i32, sema: Sema, } @@ -430,7 +425,7 @@ to acquire another lock on the same benaphore. When a thread has acquired the lock on a benaphore, the benaphore will stay locked until the thread releases the lock as many times as it has been locked by the thread. */ -Recursive_Benaphore :: struct #no_copy { +Recursive_Benaphore :: struct { counter: int, owner: int, recursion: i32, @@ -542,7 +537,7 @@ Once action. `Once` a synchronization primitive, that only allows a single entry into a critical section from a single thread. */ -Once :: struct #no_copy { +Once :: struct { m: Mutex, done: bool, } @@ -642,7 +637,7 @@ A Parker is an associated token which is initially not present: * The `unpark` procedure automatically makes the token available if it was not already. */ -Parker :: struct #no_copy { +Parker :: struct { state: Futex, } @@ -719,7 +714,7 @@ A one-shot event is an associated token which is initially not present: * The `one_shot_event_signal` procedure automatically makes the token available if its was not already. */ -One_Shot_Event :: struct #no_copy { +One_Shot_Event :: struct { state: Futex, } diff --git a/core/sync/futex_darwin.odin b/core/sync/futex_darwin.odin index 10ff7bfbb..2b104fed6 100644 --- a/core/sync/futex_darwin.odin +++ b/core/sync/futex_darwin.odin @@ -6,7 +6,7 @@ import "core:c" import "core:sys/darwin" import "core:time" -foreign import System "system:System.framework" +foreign import System "system:System" foreign System { // __ulock_wait is not available on 10.15 diff --git a/core/sync/futex_haiku.odin b/core/sync/futex_haiku.odin deleted file mode 100644 index 52321644a..000000000 --- a/core/sync/futex_haiku.odin +++ /dev/null @@ -1,164 +0,0 @@ -#+private -package sync - -import "core:sys/haiku" -import "core:sys/posix" -import "core:time" - -@(private="file") -Wait_Node :: struct { - thread: posix.pthread_t, - futex: ^Futex, - prev, next: ^Wait_Node, -} -@(private="file") -atomic_flag :: distinct bool -@(private="file") -Wait_Queue :: struct { - lock: atomic_flag, - list: Wait_Node, -} -@(private="file") -waitq_lock :: proc "contextless" (waitq: ^Wait_Queue) { - for cast(bool)atomic_exchange_explicit(&waitq.lock, atomic_flag(true), .Acquire) { - cpu_relax() // spin... - } -} -@(private="file") -waitq_unlock :: proc "contextless" (waitq: ^Wait_Queue) { - atomic_store_explicit(&waitq.lock, atomic_flag(false), .Release) -} - -// FIXME: This approach may scale badly in the future, -// possible solution - hash map (leads to deadlocks now). -@(private="file") -g_waitq: Wait_Queue - -@(init, private="file") -g_waitq_init :: proc() { - g_waitq = { - list = { - prev = &g_waitq.list, - next = &g_waitq.list, - }, - } -} - -@(private="file") -get_waitq :: #force_inline proc "contextless" (f: ^Futex) -> ^Wait_Queue { - _ = f - return &g_waitq -} - -_futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) { - waitq := get_waitq(f) - waitq_lock(waitq) - defer waitq_unlock(waitq) - - head := &waitq.list - waiter := Wait_Node{ - thread = posix.pthread_self(), - futex = f, - prev = head, - next = head.next, - } - - waiter.prev.next = &waiter - waiter.next.prev = &waiter - - old_mask, mask: posix.sigset_t - posix.sigemptyset(&mask) - posix.sigaddset(&mask, .SIGCONT) - posix.pthread_sigmask(.BLOCK, &mask, &old_mask) - - if u32(atomic_load_explicit(f, .Acquire)) == expect { - waitq_unlock(waitq) - defer waitq_lock(waitq) - - sig: posix.Signal - errno := posix.sigwait(&mask, &sig) - ok = errno == nil - } - - waiter.prev.next = waiter.next - waiter.next.prev = waiter.prev - - _ = posix.pthread_sigmask(.SETMASK, &old_mask, nil) - - // FIXME: Add error handling! - return -} - -_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration: time.Duration) -> (ok: bool) { - if duration <= 0 { - return false - } - waitq := get_waitq(f) - waitq_lock(waitq) - defer waitq_unlock(waitq) - - head := &waitq.list - waiter := Wait_Node{ - thread = posix.pthread_self(), - futex = f, - prev = head, - next = head.next, - } - - waiter.prev.next = &waiter - waiter.next.prev = &waiter - - old_mask, mask: posix.sigset_t - posix.sigemptyset(&mask) - posix.sigaddset(&mask, .SIGCONT) - posix.pthread_sigmask(.BLOCK, &mask, &old_mask) - - if u32(atomic_load_explicit(f, .Acquire)) == expect { - waitq_unlock(waitq) - defer waitq_lock(waitq) - - info: posix.siginfo_t - ts := posix.timespec{ - tv_sec = posix.time_t(i64(duration / 1e9)), - tv_nsec = i64(duration % 1e9), - } - haiku.sigtimedwait(&mask, &info, &ts) - errno := posix.errno() - ok = errno == .EAGAIN || errno == nil - } - - waiter.prev.next = waiter.next - waiter.next.prev = waiter.prev - - posix.pthread_sigmask(.SETMASK, &old_mask, nil) - - // FIXME: Add error handling! - return -} - -_futex_signal :: proc "contextless" (f: ^Futex) { - waitq := get_waitq(f) - waitq_lock(waitq) - defer waitq_unlock(waitq) - - head := &waitq.list - for waiter := head.next; waiter != head; waiter = waiter.next { - if waiter.futex == f { - posix.pthread_kill(waiter.thread, .SIGCONT) - break - } - } -} - -_futex_broadcast :: proc "contextless" (f: ^Futex) { - waitq := get_waitq(f) - waitq_lock(waitq) - defer waitq_unlock(waitq) - - head := &waitq.list - for waiter := head.next; waiter != head; waiter = waiter.next { - if waiter.futex == f { - posix.pthread_kill(waiter.thread, .SIGCONT) - } - } -} diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin index f091de045..276427477 100644 --- a/core/sync/primitives.odin +++ b/core/sync/primitives.odin @@ -36,7 +36,7 @@ holding another lock, that will cause a trivial case of deadlock. Do not use `Mutex` in recursive functions. In case multiple locks by the same thread are desired, use `Recursive_Mutex`. */ -Mutex :: struct #no_copy { +Mutex :: struct { impl: _Mutex, } @@ -147,7 +147,7 @@ result in broken and unsafe behavior. For this reason, mutexes are marked as exclusive lock more than once from the same thread, or an exclusive and shared lock on the same thread. Taking a shared lock multiple times is acceptable. */ -RW_Mutex :: struct #no_copy { +RW_Mutex :: struct { impl: _RW_Mutex, } @@ -313,7 +313,7 @@ released. Trying to use a copy of the lock at a different memory address will result in broken and unsafe behavior. For this reason, mutexes are marked as `#no_copy`. */ -Recursive_Mutex :: struct #no_copy { +Recursive_Mutex :: struct { impl: _Recursive_Mutex, } @@ -414,7 +414,7 @@ lock has been released. Trying to use a copy of the lock at a different memory address will result in broken and unsafe behavior. For this reason, condition variables are marked as `#no_copy`. */ -Cond :: struct #no_copy { +Cond :: struct { impl: _Cond, } @@ -494,7 +494,7 @@ must watch the same memory address to know when the lock has been released. Trying to use a copy of the lock at a different memory address will result in broken and unsafe behavior. For this reason, semaphores are marked as `#no_copy`. */ -Sema :: struct #no_copy { +Sema :: struct { impl: _Sema, } diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin index a8a84b2bc..9d5bdf7ee 100644 --- a/core/sync/primitives_atomic.odin +++ b/core/sync/primitives_atomic.odin @@ -13,7 +13,7 @@ Atomic_Mutex_State :: enum Futex { // The zero value for a Atomic_Mutex is an unlocked mutex // // An Atomic_Mutex must not be copied after first use -Atomic_Mutex :: struct #no_copy { +Atomic_Mutex :: struct { state: Atomic_Mutex_State, } @@ -95,21 +95,17 @@ atomic_mutex_guard :: proc "contextless" (m: ^Atomic_Mutex) -> bool { Atomic_RW_Mutex_State :: distinct uint -Atomic_RW_Mutex_State_Half_Width :: size_of(Atomic_RW_Mutex_State)*8/2 -Atomic_RW_Mutex_State_Is_Writing :: Atomic_RW_Mutex_State(1) -Atomic_RW_Mutex_State_Writer :: Atomic_RW_Mutex_State(1)<<1 -Atomic_RW_Mutex_State_Reader :: Atomic_RW_Mutex_State(1)< bool { if atomic_mutex_try_lock(&rw.mutex) { state := atomic_load(&rw.state) if state & Atomic_RW_Mutex_State_Reader_Mask == 0 { - _ = atomic_or(&rw.state, Atomic_RW_Mutex_State_Is_Writing) - return true + // Compare-and-exchange for absolute certainty that no one has come in to read. + _, ok := atomic_compare_exchange_strong(&rw.state, state, state | Atomic_RW_Mutex_State_Is_Writing) + if ok { + return true + } } + // A reader is active or came in while we have the lock, so we need to + // back out. atomic_mutex_unlock(&rw.mutex) } return false @@ -150,16 +157,22 @@ atomic_rw_mutex_try_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) -> bool { // atomic_rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers) atomic_rw_mutex_shared_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { state := atomic_load(&rw.state) - for state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { + for state & Atomic_RW_Mutex_State_Is_Writing == 0 { ok: bool state, ok = atomic_compare_exchange_weak(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) if ok { + // We succesfully took the shared reader lock without any writers intervening. return } } + // A writer is active or came in while we were trying to get a shared + // reader lock, so now we must take the full lock in order to wait for the + // writer to give it up. atomic_mutex_lock(&rw.mutex) + // At this point, we have the lock, so we can add to the reader count. _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader) + // Then we give up the lock to let other readers (or writers) come through. atomic_mutex_unlock(&rw.mutex) } @@ -169,6 +182,8 @@ atomic_rw_mutex_shared_unlock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { if (state & Atomic_RW_Mutex_State_Reader_Mask == Atomic_RW_Mutex_State_Reader) && (state & Atomic_RW_Mutex_State_Is_Writing != 0) { + // We were the last reader, so post to the writer with the lock who's + // waiting to continue. atomic_sema_post(&rw.sema) } } @@ -176,12 +191,21 @@ atomic_rw_mutex_shared_unlock :: proc "contextless" (rw: ^Atomic_RW_Mutex) { // atomic_rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers) atomic_rw_mutex_try_shared_lock :: proc "contextless" (rw: ^Atomic_RW_Mutex) -> bool { state := atomic_load(&rw.state) - if state & (Atomic_RW_Mutex_State_Is_Writing|Atomic_RW_Mutex_State_Writer_Mask) == 0 { - _, ok := atomic_compare_exchange_strong(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) + // NOTE: We need to check this in a for loop, because it is possible for + // another reader to change the underlying state which would cause our + // compare-and-exchange to fail. + for state & (Atomic_RW_Mutex_State_Is_Writing) == 0 { + ok: bool + state, ok = atomic_compare_exchange_weak(&rw.state, state, state + Atomic_RW_Mutex_State_Reader) if ok { return true } } + // A writer is active or came in during our lock attempt. + + // We try to take the full lock, and if that succeeds (perhaps because the + // writer finished during the time since we failed our CAS), we increment + // the reader count and head on. if atomic_mutex_try_lock(&rw.mutex) { _ = atomic_add(&rw.state, Atomic_RW_Mutex_State_Reader) atomic_mutex_unlock(&rw.mutex) @@ -222,7 +246,7 @@ atomic_rw_mutex_shared_guard :: proc "contextless" (m: ^Atomic_RW_Mutex) -> bool // The zero value for a Recursive_Mutex is an unlocked mutex // // An Atomic_Recursive_Mutex must not be copied after first use -Atomic_Recursive_Mutex :: struct #no_copy { +Atomic_Recursive_Mutex :: struct { owner: int, recursion: int, mutex: Mutex, @@ -285,7 +309,7 @@ atomic_recursive_mutex_guard :: proc "contextless" (m: ^Atomic_Recursive_Mutex) // waiting for signalling the occurence of an event // // An Atomic_Cond must not be copied after first use -Atomic_Cond :: struct #no_copy { +Atomic_Cond :: struct { state: Futex, } @@ -320,7 +344,7 @@ atomic_cond_broadcast :: proc "contextless" (c: ^Atomic_Cond) { // Posting to the semaphore increases the count by one, or the provided amount. // // An Atomic_Sema must not be copied after first use -Atomic_Sema :: struct #no_copy { +Atomic_Sema :: struct { count: Futex, } diff --git a/core/sync/primitives_darwin.odin b/core/sync/primitives_darwin.odin index 141cea744..4ae4b7789 100644 --- a/core/sync/primitives_darwin.odin +++ b/core/sync/primitives_darwin.odin @@ -5,7 +5,7 @@ package sync import "core:c" import "base:intrinsics" -foreign import pthread "system:System.framework" +foreign import pthread "system:System" _current_thread_id :: proc "contextless" () -> int { tid: u64 diff --git a/core/sync/primitives_haiku.odin b/core/sync/primitives_haiku.odin deleted file mode 100644 index 69d005206..000000000 --- a/core/sync/primitives_haiku.odin +++ /dev/null @@ -1,8 +0,0 @@ -#+private -package sync - -import "core:sys/haiku" - -_current_thread_id :: proc "contextless" () -> int { - return int(haiku.find_thread(nil)) -} diff --git a/core/sys/darwin/CoreFoundation/CFCGTypes.odin b/core/sys/darwin/CoreFoundation/CFCGTypes.odin new file mode 100644 index 000000000..ccfdf177a --- /dev/null +++ b/core/sys/darwin/CoreFoundation/CFCGTypes.odin @@ -0,0 +1,18 @@ +package CoreFoundation + +CGFloat :: distinct (f32 when size_of(uint) == 4 else f64) + +CGPoint :: struct { + x: CGFloat, + y: CGFloat, +} + +CGRect :: struct { + using origin: CGPoint, + using size: CGSize, +} + +CGSize :: struct { + width: CGFloat, + height: CGFloat, +} diff --git a/core/sys/darwin/CoreFoundation/CFString.odin b/core/sys/darwin/CoreFoundation/CFString.odin index 24485a494..d245ba793 100644 --- a/core/sys/darwin/CoreFoundation/CFString.odin +++ b/core/sys/darwin/CoreFoundation/CFString.odin @@ -1,10 +1,12 @@ package CoreFoundation +import "core:c" + foreign import CoreFoundation "system:CoreFoundation.framework" String :: distinct TypeRef // same as CFStringRef -StringEncoding :: distinct u32 +StringEncoding :: distinct c.long StringBuiltInEncodings :: enum StringEncoding { MacRoman = 0, @@ -171,7 +173,7 @@ foreign CoreFoundation { // Fetches a range of the characters from a string into a byte buffer after converting the characters to a specified encoding. StringGetBytes :: proc(thestring: String, range: Range, encoding: StringEncoding, lossByte: u8, isExternalRepresentation: b8, buffer: [^]byte, maxBufLen: Index, usedBufLen: ^Index) -> Index --- - StringIsEncodingAvailable :: proc(encoding: StringEncoding) -> bool --- + StringIsEncodingAvailable :: proc(encoding: StringEncoding) -> b8 --- @(link_name = "__CFStringMakeConstantString") StringMakeConstantString :: proc "c" (#const c: cstring) -> String --- diff --git a/core/sys/darwin/CoreGraphics/CoreGraphics.odin b/core/sys/darwin/CoreGraphics/CoreGraphics.odin new file mode 100644 index 000000000..e2ba5fe3c --- /dev/null +++ b/core/sys/darwin/CoreGraphics/CoreGraphics.odin @@ -0,0 +1,57 @@ +package CoreGraphics + +import "core:c" +import CF "core:sys/darwin/CoreFoundation" + +@(require) +foreign import "system:CoreGraphics.framework" + +@(link_prefix="CG", default_calling_convention="c") +foreign CoreGraphics { + AssociateMouseAndMouseCursorPosition :: proc(connected: b32) -> Error --- + DisplayIDToOpenGLDisplayMask :: proc(display: DirectDisplayID) -> OpenGLDisplayMask --- + DisplayMoveCursorToPoint :: proc(display: DirectDisplayID, point: Point) -> Error --- + EventSourceKeyState :: proc(stateID: EventSourceStateID, key: KeyCode) -> bool --- + GetActiveDisplayList :: proc(maxDisplays: c.uint32_t, activeDisplays: [^]DirectDisplayID, displayCount: ^c.uint32_t) -> Error --- + GetDisplaysWithOpenGLDisplayMask :: proc(mask: OpenGLDisplayMask, maxDisplays: c.uint32_t, displays: [^]DirectDisplayID, matchingDisplayCount: ^c.uint32_t) -> Error --- + GetDisplaysWithPoint :: proc(point: Point, maxDisplays: c.uint32_t, displays: [^]DirectDisplayID, matchingDisplayCount: ^c.uint32_t) -> Error --- + GetDisplaysWithRect :: proc(rect: Rect, maxDisplays: c.uint32_t, displays: [^]DirectDisplayID, matchingDisplayCount: ^c.uint32_t) -> Error --- + GetOnlineDisplayList :: proc(maxDisplays: c.uint32_t, onlineDisplays: [^]DirectDisplayID, displayCount: ^c.uint32_t) -> Error --- + MainDisplayID :: proc() -> DirectDisplayID --- + OpenGLDisplayMaskToDisplayID :: proc(mask: OpenGLDisplayMask) -> DirectDisplayID --- + WarpMouseCursorPosition :: proc(newCursorPosition: Point) -> Error --- +} + +DirectDisplayID :: c.uint32_t + +Error :: enum c.int32_t { + Success = 0, + Failure = 1000, + IllegalArgument = 1001, + InvalidConnection = 1002, + InvalidContext = 1003, + CannotComplete = 1004, + NotImplemented = 1006, + RangeCheck = 1007, + TypeCheck = 1008, + InvalidOperation = 1010, + NoneAvailable = 1011, +} + +EventSourceStateID :: enum c.int32_t { + Private = -1, + CombinedSessionState = 0, + HIDSystemState = 1, +} + +Float :: CF.CGFloat + +KeyCode :: c.uint16_t + +OpenGLDisplayMask :: c.uint32_t + +Point :: CF.CGPoint + +Rect :: CF.CGRect + +Size :: CF.CGSize diff --git a/core/sys/darwin/Foundation/NSApplication.odin b/core/sys/darwin/Foundation/NSApplication.odin index 254da75ad..cdda7b3e4 100644 --- a/core/sys/darwin/Foundation/NSApplication.odin +++ b/core/sys/darwin/Foundation/NSApplication.odin @@ -1,21 +1,9 @@ package objc_Foundation -foreign import "system:Foundation.framework" - import "base:intrinsics" import "base:runtime" import "core:strings" -RunLoopMode :: ^String - -@(link_prefix="NS") -foreign Foundation { - RunLoopCommonModes: RunLoopMode - DefaultRunLoopMode: RunLoopMode - EventTrackingRunLoopMode: RunLoopMode - ModalPanelRunLoopMode: RunLoopMode -} - ActivationPolicy :: enum UInteger { Regular = 0, Accessory = 1, @@ -82,7 +70,6 @@ Application_setActivationPolicy :: proc "c" (self: ^Application, activationPolic // NOTE: this is technically deprecated but still actively used (Sokol, glfw, SDL, etc.) // and has no clear alternative although `activate` is what Apple tells you to use, // that does not work the same way. -// @(deprecated="Use NSApplication method activate instead.") @(objc_type=Application, objc_name="activateIgnoringOtherApps") Application_activateIgnoringOtherApps :: proc "c" (self: ^Application, ignoreOtherApps: BOOL) { msgSend(nil, self, "activateIgnoringOtherApps:", ignoreOtherApps) @@ -93,13 +80,18 @@ Application_activate :: proc "c" (self: ^Application) { msgSend(nil, self, "activate") } +@(objc_type=Application, objc_name="active") +Application_active :: proc "c" (self: ^Application) -> BOOL { + return msgSend(BOOL, self, "isActive") +} + @(objc_type=Application, objc_name="setTitle") Application_setTitle :: proc "c" (self: ^Application, title: ^String) { msgSend(nil, self, "setTitle", title) } @(objc_type=Application, objc_name="mainMenu") -Window_mainMenu :: proc "c" (self: ^Application) -> ^Menu { +Application_mainMenu :: proc "c" (self: ^Application) -> ^Menu { return msgSend(^Menu, self, "mainMenu") } @@ -108,6 +100,35 @@ Application_setMainMenu :: proc "c" (self: ^Application, menu: ^Menu) { msgSend(nil, self, "setMainMenu:", menu) } +// This property is actually not exposed in AppKit's public API. +// But there is basically no other way to configure the apple menu without using NIB files. +// Therefore, an Odin binding for this non-public API was created. +// Note: SDL also calls this non-public method. +@(objc_type=Application, objc_name="setAppleMenu") +Application_setAppleMenu :: proc "c" (self: ^Application, menu: ^Menu) { + msgSend(nil, self, "setAppleMenu:", menu) +} + +@(objc_type=Application, objc_name="servicesMenu") +Application_servicesMenu :: proc "c" (self: ^Application) -> ^Menu { + return msgSend(^Menu, self, "servicesMenu") +} + +@(objc_type=Application, objc_name="setServicesMenu") +Application_setServicesMenu :: proc "c" (self: ^Application, menu: ^Menu) { + msgSend(nil, self, "setServicesMenu:", menu) +} + +@(objc_type=Application, objc_name="windowsMenu") +Application_windowsMenu :: proc "c" (self: ^Application) -> ^Menu { + return msgSend(^Menu, self, "windowsMenu") +} + +@(objc_type=Application, objc_name="setWindowsMenu") +Application_setWindowsMenu :: proc "c" (self: ^Application, menu: ^Menu) { + msgSend(nil, self, "setWindowsMenu:", menu) +} + @(objc_type=Application, objc_name="mainWindow") Application_mainWindow :: proc "c" (self: ^Application) -> ^Window { return msgSend(^Window, self, "mainWindow") @@ -133,6 +154,11 @@ Application_finishLaunching :: proc "c" (self: ^Application) { msgSend(nil, self, "finishLaunching") } +@(objc_type=Application, objc_name="stop") +Application_stop :: proc "c" (self: ^Application, sender: ^Object) { + msgSend(nil, self, "stop:", sender) +} + @(objc_type=Application, objc_name="terminate") Application_terminate :: proc "c" (self: ^Application, sender: ^Object) { msgSend(nil, self, "terminate:", sender) @@ -157,11 +183,24 @@ Application_nextEventMatchingMask :: proc "c" (self: ^Application, mask: EventMa Application_sendEvent :: proc "c" (self: ^Application, event: ^Event) { msgSend(nil, self, "sendEvent:", event) } + +@(objc_type=Application, objc_name="postEvent") +Application_postEvent :: proc "c" (self: ^Application, event: ^Event, atStart: BOOL) { + msgSend(nil, self, "postEvent:atStart:", event, atStart) +} + @(objc_type=Application, objc_name="updateWindows") Application_updateWindows :: proc "c" (self: ^Application) { msgSend(nil, self, "updateWindows") } +@(objc_type=Application, objc_name="sendAction") +Application_sendAction :: proc "c" (self: ^Application, action: SEL, to: id, from: id) { + msgSend(nil, self, "sendAction:to:from:", action, to, from) +} + + + @(objc_class="NSRunningApplication") RunningApplication :: struct {using _: Object} @@ -176,6 +215,11 @@ RunningApplication_localizedName :: proc "c" (self: ^RunningApplication) -> ^Str return msgSend(^String, self, "localizedName") } +@(objc_type=RunningApplication, objc_name="finishedLaunching") +RunningApplication_finishedLaunching :: proc "c" (self: ^RunningApplication) -> BOOL { + return msgSend(BOOL, self, "isFinishedLaunching") +} + ApplicationDelegateTemplate :: struct { // Launching Applications applicationWillFinishLaunching: proc(notification: ^Notification), @@ -256,7 +300,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem return nil } if template.applicationWillFinishLaunching != nil { - applicationWillFinishLaunching :: proc "c" (self: id, notification: ^Notification) { + applicationWillFinishLaunching :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillFinishLaunching(notification) @@ -264,7 +308,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillFinishLaunching:"), auto_cast applicationWillFinishLaunching, "v@:@") } if template.applicationDidFinishLaunching != nil { - applicationDidFinishLaunching :: proc "c" (self: id, notification: ^Notification) { + applicationDidFinishLaunching :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFinishLaunching(notification) @@ -272,7 +316,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidFinishLaunching:"), auto_cast applicationDidFinishLaunching, "v@:@") } if template.applicationWillBecomeActive != nil { - applicationWillBecomeActive :: proc "c" (self: id, notification: ^Notification) { + applicationWillBecomeActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillBecomeActive(notification) @@ -280,7 +324,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillBecomeActive:"), auto_cast applicationWillBecomeActive, "v@:@") } if template.applicationDidBecomeActive != nil { - applicationDidBecomeActive :: proc "c" (self: id, notification: ^Notification) { + applicationDidBecomeActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidBecomeActive(notification) @@ -288,7 +332,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidBecomeActive:"), auto_cast applicationDidBecomeActive, "v@:@") } if template.applicationWillResignActive != nil { - applicationWillResignActive :: proc "c" (self: id, notification: ^Notification) { + applicationWillResignActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillResignActive(notification) @@ -296,7 +340,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillResignActive:"), auto_cast applicationWillResignActive, "v@:@") } if template.applicationDidResignActive != nil { - applicationDidResignActive :: proc "c" (self: id, notification: ^Notification) { + applicationDidResignActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidResignActive(notification) @@ -304,7 +348,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidResignActive:"), auto_cast applicationDidResignActive, "v@:@") } if template.applicationShouldTerminate != nil { - applicationShouldTerminate :: proc "c" (self: id, sender: ^Application) -> ApplicationTerminateReply { + applicationShouldTerminate :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> ApplicationTerminateReply { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldTerminate(sender) @@ -312,7 +356,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminate:"), auto_cast applicationShouldTerminate, _UINTEGER_ENCODING+"@:@") } if template.applicationShouldTerminateAfterLastWindowClosed != nil { - applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldTerminateAfterLastWindowClosed(sender) @@ -320,7 +364,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast applicationShouldTerminateAfterLastWindowClosed, "B@:@") } if template.applicationWillTerminate != nil { - applicationWillTerminate :: proc "c" (self: id, notification: ^Notification) { + applicationWillTerminate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillTerminate(notification) @@ -328,7 +372,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillTerminate:"), auto_cast applicationWillTerminate, "v@:@") } if template.applicationWillHide != nil { - applicationWillHide :: proc "c" (self: id, notification: ^Notification) { + applicationWillHide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillHide(notification) @@ -336,7 +380,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillHide:"), auto_cast applicationWillHide, "v@:@") } if template.applicationDidHide != nil { - applicationDidHide :: proc "c" (self: id, notification: ^Notification) { + applicationDidHide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidHide(notification) @@ -344,7 +388,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidHide:"), auto_cast applicationDidHide, "v@:@") } if template.applicationWillUnhide != nil { - applicationWillUnhide :: proc "c" (self: id, notification: ^Notification) { + applicationWillUnhide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillUnhide(notification) @@ -352,7 +396,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillUnhide:"), auto_cast applicationWillUnhide, "v@:@") } if template.applicationDidUnhide != nil { - applicationDidUnhide :: proc "c" (self: id, notification: ^Notification) { + applicationDidUnhide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUnhide(notification) @@ -360,7 +404,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidUnhide:"), auto_cast applicationDidUnhide, "v@:@") } if template.applicationWillUpdate != nil { - applicationWillUpdate :: proc "c" (self: id, notification: ^Notification) { + applicationWillUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillUpdate(notification) @@ -368,7 +412,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillUpdate:"), auto_cast applicationWillUpdate, "v@:@") } if template.applicationDidUpdate != nil { - applicationDidUpdate :: proc "c" (self: id, notification: ^Notification) { + applicationDidUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUpdate(notification) @@ -376,7 +420,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidUpdate:"), auto_cast applicationDidUpdate, "v@:@") } if template.applicationShouldHandleReopenHasVisibleWindows != nil { - applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, sender: ^Application, flag: BOOL) -> BOOL { + applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, cmd: SEL, sender: ^Application, flag: BOOL) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldHandleReopenHasVisibleWindows(sender, flag) @@ -384,7 +428,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldHandleReopen:hasVisibleWindows:"), auto_cast applicationShouldHandleReopenHasVisibleWindows, "B@:@B") } if template.applicationDockMenu != nil { - applicationDockMenu :: proc "c" (self: id, sender: ^Application) -> ^Menu { + applicationDockMenu :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> ^Menu { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationDockMenu(sender) @@ -392,7 +436,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDockMenu:"), auto_cast applicationDockMenu, "@@:@") } if template.applicationShouldAutomaticallyLocalizeKeyEquivalents != nil { - applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, application: ^Application) -> BOOL { + applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, cmd: SEL, application: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldAutomaticallyLocalizeKeyEquivalents(application) @@ -400,7 +444,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldAutomaticallyLocalizeKeyEquivalents:"), auto_cast applicationShouldAutomaticallyLocalizeKeyEquivalents, "B@:@") } if template.applicationWillPresentError != nil { - applicationWillPresentError :: proc "c" (self: id, application: ^Application, error: ^Error) -> ^Error { + applicationWillPresentError :: proc "c" (self: id, cmd: SEL, application: ^Application, error: ^Error) -> ^Error { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationWillPresentError(application, error) @@ -408,7 +452,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willPresentError:"), auto_cast applicationWillPresentError, "@@:@@") } if template.applicationDidChangeScreenParameters != nil { - applicationDidChangeScreenParameters :: proc "c" (self: id, notification: ^Notification) { + applicationDidChangeScreenParameters :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidChangeScreenParameters(notification) @@ -416,7 +460,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeScreenParameters:"), auto_cast applicationDidChangeScreenParameters, "v@:@") } if template.applicationWillContinueUserActivityWithType != nil { - applicationWillContinueUserActivityWithType :: proc "c" (self: id, application: ^Application, userActivityType: ^String) -> BOOL { + applicationWillContinueUserActivityWithType :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivityType: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationWillContinueUserActivityWithType(application, userActivityType) @@ -424,7 +468,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willContinueUserActivityWithType:"), auto_cast applicationWillContinueUserActivityWithType, "B@:@@") } if template.applicationContinueUserActivityRestorationHandler != nil { - applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL { + applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationContinueUserActivityRestorationHandler(application, userActivity, restorationHandler) @@ -432,7 +476,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:continueUserActivity:restorationHandler:"), auto_cast applicationContinueUserActivityRestorationHandler, "B@:@@?") } if template.applicationDidFailToContinueUserActivityWithTypeError != nil { - applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, application: ^Application, userActivityType: ^String, error: ^Error) { + applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivityType: ^String, error: ^Error) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFailToContinueUserActivityWithTypeError(application, userActivityType, error) @@ -440,7 +484,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didFailToContinueUserActivityWithType:error:"), auto_cast applicationDidFailToContinueUserActivityWithTypeError, "v@:@@@") } if template.applicationDidUpdateUserActivity != nil { - applicationDidUpdateUserActivity :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity) { + applicationDidUpdateUserActivity :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivity: ^UserActivity) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUpdateUserActivity(application, userActivity) @@ -448,7 +492,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didUpdateUserActivity:"), auto_cast applicationDidUpdateUserActivity, "v@:@@") } if template.applicationDidRegisterForRemoteNotificationsWithDeviceToken != nil { - applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, application: ^Application, deviceToken: ^Data) { + applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, cmd: SEL, application: ^Application, deviceToken: ^Data) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidRegisterForRemoteNotificationsWithDeviceToken(application, deviceToken) @@ -456,7 +500,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didRegisterForRemoteNotificationsWithDeviceToken:"), auto_cast applicationDidRegisterForRemoteNotificationsWithDeviceToken, "v@:@@") } if template.applicationDidFailToRegisterForRemoteNotificationsWithError != nil { - applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, application: ^Application, error: ^Error) { + applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, cmd: SEL, application: ^Application, error: ^Error) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFailToRegisterForRemoteNotificationsWithError(application, error) @@ -464,7 +508,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didFailToRegisterForRemoteNotificationsWithError:"), auto_cast applicationDidFailToRegisterForRemoteNotificationsWithError, "v@:@@") } if template.applicationDidReceiveRemoteNotification != nil { - applicationDidReceiveRemoteNotification :: proc "c" (self: id, application: ^Application, userInfo: ^Dictionary) { + applicationDidReceiveRemoteNotification :: proc "c" (self: id, cmd: SEL, application: ^Application, userInfo: ^Dictionary) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidReceiveRemoteNotification(application, userInfo) @@ -472,7 +516,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didReceiveRemoteNotification:"), auto_cast applicationDidReceiveRemoteNotification, "v@:@@") } // if template.applicationUserDidAcceptCloudKitShareWithMetadata != nil { - // applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, application: ^Application, metadata: ^CKShareMetadata) { + // applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, cmd: SEL, application: ^Application, metadata: ^CKShareMetadata) { // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) // context = del._context // del.applicationUserDidAcceptCloudKitShareWithMetadata(application, metadata) @@ -480,7 +524,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem // class_addMethod(class, intrinsics.objc_find_selector("application:userDidAcceptCloudKitShareWithMetadata:"), auto_cast applicationUserDidAcceptCloudKitShareWithMetadata, "v@:@@") // } // if template.applicationHandlerForIntent != nil { - // applicationHandlerForIntent :: proc "c" (self: id, application: ^Application, intent: ^INIntent) -> id { + // applicationHandlerForIntent :: proc "c" (self: id, cmd: SEL, application: ^Application, intent: ^INIntent) -> id { // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) // context = del._context // return del.applicationHandlerForIntent(application, intent) @@ -488,7 +532,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem // class_addMethod(class, intrinsics.objc_find_selector("application:handlerForIntent:"), auto_cast applicationHandlerForIntent, "@@:@@") // } if template.applicationOpenURLs != nil { - applicationOpenURLs :: proc "c" (self: id, application: ^Application, urls: ^Array) { + applicationOpenURLs :: proc "c" (self: id, cmd: SEL, application: ^Application, urls: ^Array) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationOpenURLs(application, urls) @@ -496,7 +540,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openURLs:"), auto_cast applicationOpenURLs, "v@:@@") } if template.applicationOpenFile != nil { - applicationOpenFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationOpenFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenFile(sender, filename) @@ -504,7 +548,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFile:"), auto_cast applicationOpenFile, "B@:@@") } if template.applicationOpenFileWithoutUI != nil { - applicationOpenFileWithoutUI :: proc "c" (self: id, sender: id, filename: ^String) -> BOOL { + applicationOpenFileWithoutUI :: proc "c" (self: id, cmd: SEL, sender: id, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenFileWithoutUI(sender, filename) @@ -512,7 +556,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFileWithoutUI:"), auto_cast applicationOpenFileWithoutUI, "B@:@@") } if template.applicationOpenTempFile != nil { - applicationOpenTempFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationOpenTempFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenTempFile(sender, filename) @@ -520,7 +564,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openTempFile:"), auto_cast applicationOpenTempFile, "B@:@@") } if template.applicationOpenFiles != nil { - applicationOpenFiles :: proc "c" (self: id, sender: ^Application, filenames: ^Array) { + applicationOpenFiles :: proc "c" (self: id, cmd: SEL, sender: ^Application, filenames: ^Array) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationOpenFiles(sender, filenames) @@ -528,7 +572,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFiles:"), auto_cast applicationOpenFiles, "v@:@@") } if template.applicationShouldOpenUntitledFile != nil { - applicationShouldOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationShouldOpenUntitledFile :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldOpenUntitledFile(sender) @@ -536,7 +580,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldOpenUntitledFile:"), auto_cast applicationShouldOpenUntitledFile, "B@:@") } if template.applicationOpenUntitledFile != nil { - applicationOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationOpenUntitledFile :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenUntitledFile(sender) @@ -544,7 +588,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationOpenUntitledFile:"), auto_cast applicationOpenUntitledFile, "B@:@") } if template.applicationPrintFile != nil { - applicationPrintFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationPrintFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationPrintFile(sender, filename) @@ -552,7 +596,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:printFile:"), auto_cast applicationPrintFile, "B@:@@") } if template.applicationPrintFilesWithSettingsShowPrintPanels != nil { - applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply { + applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, cmd: SEL, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationPrintFilesWithSettingsShowPrintPanels(application, fileNames, printSettings, showPrintPanels) @@ -560,7 +604,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:printFiles:withSettings:showPrintPanels:"), auto_cast applicationPrintFilesWithSettingsShowPrintPanels, _UINTEGER_ENCODING+"@:@@@B") } if template.applicationSupportsSecureRestorableState != nil { - applicationSupportsSecureRestorableState :: proc "c" (self: id, app: ^Application) -> BOOL { + applicationSupportsSecureRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationSupportsSecureRestorableState(app) @@ -568,7 +612,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationSupportsSecureRestorableState:"), auto_cast applicationSupportsSecureRestorableState, "B@:@") } if template.applicationProtectedDataDidBecomeAvailable != nil { - applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, notification: ^Notification) { + applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationProtectedDataDidBecomeAvailable(notification) @@ -576,7 +620,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataDidBecomeAvailable:"), auto_cast applicationProtectedDataDidBecomeAvailable, "v@:@") } if template.applicationProtectedDataWillBecomeUnavailable != nil { - applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, notification: ^Notification) { + applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationProtectedDataWillBecomeUnavailable(notification) @@ -584,7 +628,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataWillBecomeUnavailable:"), auto_cast applicationProtectedDataWillBecomeUnavailable, "v@:@") } if template.applicationWillEncodeRestorableState != nil { - applicationWillEncodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) { + applicationWillEncodeRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application, coder: ^Coder) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillEncodeRestorableState(app, coder) @@ -592,7 +636,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willEncodeRestorableState:"), auto_cast applicationWillEncodeRestorableState, "v@:@@") } if template.applicationDidDecodeRestorableState != nil { - applicationDidDecodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) { + applicationDidDecodeRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application, coder: ^Coder) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidDecodeRestorableState(app, coder) @@ -600,7 +644,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didDecodeRestorableState:"), auto_cast applicationDidDecodeRestorableState, "v@:@@") } if template.applicationDidChangeOcclusionState != nil { - applicationDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) { + applicationDidChangeOcclusionState :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidChangeOcclusionState(notification) @@ -608,7 +652,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeOcclusionState:"), auto_cast applicationDidChangeOcclusionState, "v@:@") } if template.applicationDelegateHandlesKey != nil { - applicationDelegateHandlesKey :: proc "c" (self: id, sender: ^Application, key: ^String) -> BOOL { + applicationDelegateHandlesKey :: proc "c" (self: id, cmd: SEL, sender: ^Application, key: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationDelegateHandlesKey(sender, key) diff --git a/core/sys/darwin/Foundation/NSArray.odin b/core/sys/darwin/Foundation/NSArray.odin index b238f63f8..0977c6469 100644 --- a/core/sys/darwin/Foundation/NSArray.odin +++ b/core/sys/darwin/Foundation/NSArray.odin @@ -40,3 +40,49 @@ Array_objectAs :: proc "c" (self: ^Array, index: UInteger, $T: typeid) -> T wher Array_count :: proc "c" (self: ^Array) -> UInteger { return msgSend(UInteger, self, "count") } + + +@(objc_class="NSMutableArray") +MutableArray :: struct { + using _: Copying(MutableArray), +} + +@(objc_type=MutableArray, objc_name="alloc", objc_is_class_method=true) +MutableArray_alloc :: proc "c" () -> ^MutableArray { + return msgSend(^MutableArray, MutableArray, "alloc") +} + +@(objc_type=MutableArray, objc_name="init") +MutableArray_init :: proc "c" (self: ^MutableArray) -> ^MutableArray { + return msgSend(^MutableArray, self, "init") +} + +@(objc_type=MutableArray, objc_name="initWithObjects") +MutableArray_initWithObjects :: proc "c" (self: ^MutableArray, objects: [^]^Object, count: UInteger) -> ^MutableArray { + return msgSend(^MutableArray, self, "initWithObjects:count:", objects, count) +} + +@(objc_type=MutableArray, objc_name="initWithCoder") +MutableArray_initWithCoder :: proc "c" (self: ^MutableArray, coder: ^Coder) -> ^MutableArray { + return msgSend(^MutableArray, self, "initWithCoder:", coder) +} + +@(objc_type=MutableArray, objc_name="object") +MutableArray_object :: proc "c" (self: ^MutableArray, index: UInteger) -> ^Object { + return msgSend(^Object, self, "objectAtIndex:", index) +} +@(objc_type=MutableArray, objc_name="objectAs") +MutableArray_objectAs :: proc "c" (self: ^MutableArray, index: UInteger, $T: typeid) -> T where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) { + return (T)(MutableArray_object(self, index)) +} + +@(objc_type=MutableArray, objc_name="count") +MutableArray_count :: proc "c" (self: ^MutableArray) -> UInteger { + return msgSend(UInteger, self, "count") +} + + +@(objc_type=MutableArray, objc_name="exchangeObjectAtIndex") +MutableArray_exchangeObjectAtIndex :: proc "c" (self: ^MutableArray, idx1, idx2: UInteger) { + msgSend(nil, self, "exchangeObjectAtIndex:withObjectAtIndex:", idx1, idx2) +} diff --git a/core/sys/darwin/Foundation/NSBitmapImageRep.odin b/core/sys/darwin/Foundation/NSBitmapImageRep.odin new file mode 100644 index 000000000..d10043d7a --- /dev/null +++ b/core/sys/darwin/Foundation/NSBitmapImageRep.odin @@ -0,0 +1,80 @@ +package objc_Foundation + +@(objc_class="NSBitmapImageRep") +BitmapImageRep :: struct { using _: Object } + +BitmapInteger :: distinct UInteger +BitmapFormatFlag :: enum BitmapInteger { + AlphaFirst = 0, + AlphaNonpremultiplied = 1, + FloatingPointSamples = 2, + SixteenBitLittleEndian = 8, + ThirtyTwoBitLittleEndian = 9, + SixteenBitBigEndian = 10, + ThirtyTwoBitBigEndian = 11, +} +BitmapFormatFlags :: bit_set[BitmapFormatFlag; BitmapInteger] + +@(objc_type=BitmapImageRep, objc_name="alloc", objc_is_class_method=true) +BitmapImageRep_alloc :: proc "c" () -> ^BitmapImageRep { + return msgSend(^BitmapImageRep, BitmapImageRep, "alloc") +} + +BitmapImageRep_initWithBitmapDataPlanes_legacy :: proc "c" ( + self: ^BitmapImageRep, + bitmapDataPlanes: ^^u8, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, + samplesPerPixel: Integer, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bytesPerRow: Integer, + bitsPerPixel: Integer, +) -> ^BitmapImageRep { + return msgSend( + ^BitmapImageRep, self, + "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:", + bitmapDataPlanes, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, + hasAlpha, isPlanar, colorSpaceName, bytesPerRow, bitsPerPixel, + ) +} + +BitmapImageRep_initWithBitmapDataPlanes_bitmapFormat :: proc "c" ( + self: ^BitmapImageRep, + bitmapDataPlanes: ^^u8, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, + samplesPerPixel: Integer, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bitmapFormat: BitmapFormatFlags, + bytesPerRow: Integer, + bitsPerPixel: Integer, +) -> ^BitmapImageRep { + return msgSend( + ^BitmapImageRep, self, + "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:", + bitmapDataPlanes, pixelsWide, pixelsHigh, bitsPerSample, samplesPerPixel, + hasAlpha, isPlanar, colorSpaceName, bitmapFormat, bytesPerRow, bitsPerPixel, + ) +} + +@(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes") +BitmapImageRep_initWithBitmapDataPlanes :: proc{ + BitmapImageRep_initWithBitmapDataPlanes_legacy, + BitmapImageRep_initWithBitmapDataPlanes_bitmapFormat, +} + +@(objc_type=BitmapImageRep, objc_name="bitmapData") +BitmapImageRep_bitmapData :: proc "c" (self: ^BitmapImageRep) -> rawptr { + return msgSend(rawptr, self, "bitmapData") +} + +@(objc_type=BitmapImageRep, objc_name="CGImage") +BitmapImageRep_CGImage :: proc "c" (self: ^BitmapImageRep) -> rawptr { + return msgSend(rawptr, self, "CGImage") +} diff --git a/core/sys/darwin/Foundation/NSBlock.odin b/core/sys/darwin/Foundation/NSBlock.odin index 1ef5e8a9b..a5b99abc5 100644 --- a/core/sys/darwin/Foundation/NSBlock.odin +++ b/core/sys/darwin/Foundation/NSBlock.odin @@ -2,13 +2,13 @@ package objc_Foundation import "base:intrinsics" import "base:builtin" -import "core:mem" +import "base:runtime" @(objc_class="NSBlock") Block :: struct {using _: Object} @(objc_type=Block, objc_name="createGlobal", objc_is_class_method=true) -Block_createGlobal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error { +Block_createGlobal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator := context.allocator) -> (^Block, runtime.Allocator_Error) #optional_allocator_error { return Block_createInternal(true, user_data, user_proc, allocator) } @(objc_type=Block, objc_name="createLocal", objc_is_class_method=true) @@ -17,7 +17,7 @@ Block_createLocal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: ra return b } @(objc_type=Block, objc_name="createGlobalWithParam", objc_is_class_method=true) -Block_createGlobalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error { +Block_createGlobalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator := context.allocator) -> (^Block, runtime.Allocator_Error) #optional_allocator_error { return Block_createInternalWithParam(true, user_data, user_proc, allocator) } @(objc_type=Block, objc_name="createLocalWithParam", objc_is_class_method=true) @@ -62,14 +62,14 @@ global_block_descriptor := Block_Descriptor{ size = size_of(Internal_Block_Literal), } -foreign import libSystem "system:System.framework" +foreign import libSystem "system:System" foreign libSystem { _NSConcreteGlobalBlock: intrinsics.objc_class _NSConcreteStackBlock: intrinsics.objc_class } @(private="file") -internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr, allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) { +internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr, allocator: runtime.Allocator) -> (b: ^Block, err: runtime.Allocator_Error) { _init :: proc(bl: ^Internal_Block_Literal, is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr) { // Set to true on blocks that have captures (and thus are not true // global blocks) but are known not to escape for various other @@ -82,7 +82,7 @@ internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_pr BLOCK_HAS_COPY_DISPOSE :: 1 << 25 BLOCK_HAS_CTOR :: 1 << 26 // helpers have C++ code BLOCK_IS_GLOBAL :: 1 << 28 - BLOCK_HAS_STRET :: 1 << 29 // IFF BLOCK_HAS_SIGNATURE + BLOCK_HAS_STRET :: 1 << 29 // if and only if (⟺) BLOCK_HAS_SIGNATURE BLOCK_HAS_SIGNATURE :: 1 << 30 bl.isa = is_global ? &_NSConcreteGlobalBlock : &_NSConcreteStackBlock @@ -105,7 +105,7 @@ internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_pr } @(private="file") -Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) { +Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator: runtime.Allocator) -> (b: ^Block, err: runtime.Allocator_Error) { invoke :: proc "c" (bl: ^Internal_Block_Literal) { user_proc := (proc "c" (rawptr))(bl.user_proc) user_proc(bl.user_data) @@ -114,7 +114,7 @@ Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: pro } @(private="file") -Block_createInternalWithParam :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) { +Block_createInternalWithParam :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator: runtime.Allocator) -> (b: ^Block, err: runtime.Allocator_Error) { invoke :: proc "c" (bl: ^Internal_Block_Literal, t: T) { user_proc := (proc "c" (rawptr, T))(bl.user_proc) user_proc(bl.user_data, t) diff --git a/core/sys/darwin/Foundation/NSColor.odin b/core/sys/darwin/Foundation/NSColor.odin index 453b33144..b50e08af1 100644 --- a/core/sys/darwin/Foundation/NSColor.odin +++ b/core/sys/darwin/Foundation/NSColor.odin @@ -1,5 +1,7 @@ package objc_Foundation +foreign import "system:Foundation.framework" + @(objc_class="NSColorSpace") ColorSpace :: struct {using _: Object} @@ -146,4 +148,9 @@ Color_numberOfComponents :: proc "c" (self: ^Color) -> Integer { @(objc_type=Color, objc_name="getComponents") Color_getComponents :: proc "c" (self: ^Color, components: [^]Float) { msgSend(nil, self, "getComponents:", components) -} \ No newline at end of file +} + +@(link_prefix="NS", default_calling_convention="c") +foreign Foundation { + DeviceRGBColorSpace: ^String +} diff --git a/core/sys/darwin/Foundation/NSCursor.odin b/core/sys/darwin/Foundation/NSCursor.odin new file mode 100644 index 000000000..5c43e1353 --- /dev/null +++ b/core/sys/darwin/Foundation/NSCursor.odin @@ -0,0 +1,47 @@ +package objc_Foundation + +@(objc_class="NSCursor") +Cursor :: struct {using _: Object} + +@(objc_type=Cursor, objc_name="alloc", objc_is_class_method=true) +Cursor_alloc :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "alloc") +} +@(objc_type=Cursor, objc_name="initWithImage") +Cursor_initWithImage :: proc "c" (self: ^Cursor, image: ^Image, hotSpot: Point) -> ^Cursor { + return msgSend(^Cursor, self, "initWithImage:hotSpot:", image, hotSpot) +} +@(objc_type=Cursor, objc_name="hide", objc_is_class_method=true) +Cursor_hide :: proc() { + msgSend(nil, Cursor, "hide") +} +@(objc_type=Cursor, objc_name="unhide", objc_is_class_method=true) +Cursor_unhide :: proc() { + msgSend(nil, Cursor, "unhide") +} +@(objc_type=Cursor, objc_name="setHiddenUntilMouseMoves", objc_is_class_method=true) +Cursor_setHiddenUntilMouseMoves :: proc(flag: BOOL) { + msgSend(nil, Cursor, "setHiddenUntilMouseMoves:", flag) +} + +@(objc_type=Cursor, objc_name="set") +Cursor_set :: proc(self: ^Cursor) { + msgSend(EventType, self, "set") +} +@(objc_type=Cursor, objc_name="currentCursor", objc_is_class_method=true) +Cursor_currentCursor :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "currentCursor") +} +@(objc_type=Cursor, objc_name="IBeamCursor", objc_is_class_method=true) +Cursor_IBeamCursor :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "IBeamCursor") +} +@(objc_type=Cursor, objc_name="arrowCursor", objc_is_class_method=true) +Cursor_arrowCursor :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "arrowCursor") +} +@(objc_type=Cursor, objc_name="pointingHandCursor", objc_is_class_method=true) +Cursor_pointingHandCursor :: proc "c" () -> ^Cursor { + return msgSend(^Cursor, Cursor, "pointingHandCursor") +} + diff --git a/core/sys/darwin/Foundation/NSEvent.odin b/core/sys/darwin/Foundation/NSEvent.odin index 548c5c172..952a1726c 100644 --- a/core/sys/darwin/Foundation/NSEvent.odin +++ b/core/sys/darwin/Foundation/NSEvent.odin @@ -250,6 +250,35 @@ kVK :: enum { ISO_Section = 0x0A, } +/* class methods for creating events */ + +@(objc_type=Event, objc_name="otherEventWithType", objc_is_class_method=true) +Event_otherEventWithType :: proc "c" ( + type: EventType, + location: Point, + flags: EventModifierFlags, + time: TimeInterval, + window_number: Integer, + ctx: id, + subtype: i16, + data1: Integer, + data2: Integer, +) -> ^Event { + return msgSend( + ^Event, + Event, + "otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:", + type, + location, + flags, + time, + window_number, + ctx, + subtype, + data1, + data2, + ) +} /* these messages are valid for all events */ @@ -305,6 +334,11 @@ Event_locationInWindow :: proc "c" (self: ^Event) -> Point { return msgSend(Point, self, "locationInWindow") } +@(objc_type=Event, objc_name="mouseLocation", objc_is_class_method=true) +Event_mouseLocation :: proc "c" () -> Point { + return msgSend(Point, Event, "mouseLocation") +} + @(objc_type=Event, objc_name="deltaX") Event_deltaX :: proc "c" (self: ^Event) -> Float { diff --git a/core/sys/darwin/Foundation/NSImage.odin b/core/sys/darwin/Foundation/NSImage.odin new file mode 100644 index 000000000..33aae6c50 --- /dev/null +++ b/core/sys/darwin/Foundation/NSImage.odin @@ -0,0 +1,19 @@ +package objc_Foundation + +@(objc_class="NSImage") +Image :: struct { using _: Object } + +@(objc_type=Image, objc_name="alloc", objc_is_class_method=true) +Image_alloc :: proc "c" () -> ^Image { + return msgSend(^Image, Image, "alloc") +} + +@(objc_type=Image, objc_name="initWithSize") +Image_initWithSize :: proc "c" (self: ^Image, size: Size) -> ^Image { + return msgSend(^Image, self, "initWithSize:", size) +} + +@(objc_type=Image, objc_name="addRepresentation") +Image_addRepresentation :: proc(self: ^Image, rep: ^ImageRep) { + msgSend(nil, self, "addRepresentation:", rep) +} diff --git a/core/sys/darwin/Foundation/NSImageRep.odin b/core/sys/darwin/Foundation/NSImageRep.odin new file mode 100644 index 000000000..1e80cb336 --- /dev/null +++ b/core/sys/darwin/Foundation/NSImageRep.odin @@ -0,0 +1,4 @@ +package objc_Foundation + +@(objc_class="NSImageRep") +ImageRep :: struct { using _: Object } diff --git a/core/sys/darwin/Foundation/NSMenu.odin b/core/sys/darwin/Foundation/NSMenu.odin index 9a74151b0..747920ab7 100644 --- a/core/sys/darwin/Foundation/NSMenu.odin +++ b/core/sys/darwin/Foundation/NSMenu.odin @@ -2,127 +2,562 @@ package objc_Foundation import "base:builtin" import "base:intrinsics" - -KeyEquivalentModifierFlag :: enum UInteger { - CapsLock = 16, // Set if Caps Lock key is pressed. - Shift = 17, // Set if Shift key is pressed. - Control = 18, // Set if Control key is pressed. - Option = 19, // Set if Option or Alternate key is pressed. - Command = 20, // Set if Command key is pressed. - NumericPad = 21, // Set if any key in the numeric keypad is pressed. - Help = 22, // Set if the Help key is pressed. - Function = 23, // Set if any function key is pressed. -} -KeyEquivalentModifierMask :: distinct bit_set[KeyEquivalentModifierFlag; UInteger] - -// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information. -KeyEventModifierFlagDeviceIndependentFlagsMask := transmute(KeyEquivalentModifierMask)_KeyEventModifierFlagDeviceIndependentFlagsMask -@(private) _KeyEventModifierFlagDeviceIndependentFlagsMask := UInteger(0xffff0000) +import "core:c" -MenuItemCallback :: proc "c" (unused: rawptr, name: SEL, sender: ^Object) - - -@(objc_class="NSMenuItem") -MenuItem :: struct {using _: Object} - -@(objc_type=MenuItem, objc_name="alloc", objc_is_class_method=true) -MenuItem_alloc :: proc "c" () -> ^MenuItem { - return msgSend(^MenuItem, MenuItem, "alloc") +MenuSelectionMode :: enum c.long { + Automatic = 0, + SelectOne = 1, + SelectAny = 2, } -@(objc_type=MenuItem, objc_name="registerActionCallback", objc_is_class_method=true) -MenuItem_registerActionCallback :: proc "c" (name: cstring, callback: MenuItemCallback) -> SEL { - s := string(name) - n := len(s) - sel: SEL - if n > 0 && s[n-1] != ':' { - col_name := intrinsics.alloca(n+2, 1) - builtin.copy(col_name[:n], s) - col_name[n] = ':' - col_name[n+1] = 0 - sel = sel_registerName(cstring(col_name)) - } else { - sel = sel_registerName(name) - } - if callback != nil { - class_addMethod(intrinsics.objc_find_class("NSObject"), sel, auto_cast callback, "v@:@") - } - return sel +MenuPresentationStyle :: enum c.long { + Regular = 0, + Palette = 1, } -@(objc_type=MenuItem, objc_name="separatorItem", objc_is_class_method=true) -MenuItem_separatorItem :: proc "c" () -> ^MenuItem { - return msgSend(^MenuItem, MenuItem, "separatorItem") +UserInterfaceLayoutDirection :: enum c.long { + LeftToRight = 0, + RightToLeft = 1, } -@(objc_type=MenuItem, objc_name="init") -MenuItem_init :: proc "c" (self: ^MenuItem) -> ^MenuItem { - return msgSend(^MenuItem, self, "init") +MenuPropertyItem :: enum c.ulong { + Title = 0, + AttributedTitle = 1, + KeyEquivalent = 2, + Image = 3, + Enabled = 4, + AccessibilityDescription = 5, } - -@(objc_type=MenuItem, objc_name="initWithTitle") -MenuItem_initWithTitle :: proc "c" (self: ^MenuItem, title: ^String, action: SEL, keyEquivalent: ^String) -> ^MenuItem { - return msgSend(^MenuItem, self, "initWithTitle:action:keyEquivalent:", title, action, keyEquivalent) -} - -@(objc_type=MenuItem, objc_name="setKeyEquivalentModifierMask") -MenuItem_setKeyEquivalentModifierMask :: proc "c" (self: ^MenuItem, modifierMask: KeyEquivalentModifierMask) { - msgSend(nil, self, "setKeyEquivalentModifierMask:", modifierMask) -} - -@(objc_type=MenuItem, objc_name="keyEquivalentModifierMask") -MenuItem_keyEquivalentModifierMask :: proc "c" (self: ^MenuItem) -> KeyEquivalentModifierMask { - return msgSend(KeyEquivalentModifierMask, self, "keyEquivalentModifierMask") -} - -@(objc_type=MenuItem, objc_name="setSubmenu") -MenuItem_setSubmenu :: proc "c" (self: ^MenuItem, submenu: ^Menu) { - msgSend(nil, self, "setSubmenu:", submenu) -} - -@(objc_type=MenuItem, objc_name="title") -MenuItem_title :: proc "c" (self: ^MenuItem) -> ^String { - return msgSend(^String, self, "title") -} - -@(objc_type=MenuItem, objc_name="setTitle") -MenuItem_setTitle :: proc "c" (self: ^MenuItem, title: ^String) -> ^String { - return msgSend(^String, self, "title:", title) -} - +MenuProperties :: distinct bit_set[MenuPropertyItem; c.ulong] @(objc_class="NSMenu") Menu :: struct {using _: Object} -@(objc_type=Menu, objc_name="alloc", objc_is_class_method=true) -Menu_alloc :: proc "c" () -> ^Menu { - return msgSend(^Menu, Menu, "alloc") -} - @(objc_type=Menu, objc_name="init") Menu_init :: proc "c" (self: ^Menu) -> ^Menu { return msgSend(^Menu, self, "init") } + @(objc_type=Menu, objc_name="initWithTitle") -Menu_initWithTitle :: proc "c" (self: ^Menu, title: ^String) -> ^Menu { +Menu_initWithTitle :: #force_inline proc "c" (self: ^Menu, title: ^String) -> ^Menu { return msgSend(^Menu, self, "initWithTitle:", title) } - - +@(objc_type=Menu, objc_name="initWithCoder") +Menu_initWithCoder :: #force_inline proc "c" (self: ^Menu, coder: ^Coder) -> ^Menu { + return msgSend(^Menu, self, "initWithCoder:", coder) +} +@(objc_type=Menu, objc_name="popUpContextMenu_withEvent_forView", objc_is_class_method=true) +Menu_popUpContextMenu_withEvent_forView :: #force_inline proc "c" (menu: ^Menu, event: ^Event, view: ^View) { + msgSend(nil, Menu, "popUpContextMenu:withEvent:forView:", menu, event, view) +} +// @(objc_type=Menu, objc_name="popUpContextMenu_withEvent_forView_withFont", objc_is_class_method=true) +// Menu_popUpContextMenu_withEvent_forView_withFont :: #force_inline proc "c" (menu: ^Menu, event: ^Event, view: ^View, font: ^Font) { +// msgSend(nil, Menu, "popUpContextMenu:withEvent:forView:withFont:", menu, event, view, font) +// } +@(objc_type=Menu, objc_name="popUpMenuPositioningItem") +Menu_popUpMenuPositioningItem :: #force_inline proc "c" (self: ^Menu, item: ^MenuItem, location: Point, view: ^View) -> bool { + return msgSend(bool, self, "popUpMenuPositioningItem:atLocation:inView:", item, location, view) +} +@(objc_type=Menu, objc_name="setMenuBarVisible", objc_is_class_method=true) +Menu_setMenuBarVisible :: #force_inline proc "c" (visible: bool) { + msgSend(nil, Menu, "setMenuBarVisible:", visible) +} +@(objc_type=Menu, objc_name="menuBarVisible", objc_is_class_method=true) +Menu_menuBarVisible :: #force_inline proc "c" () -> bool { + return msgSend(bool, Menu, "menuBarVisible") +} +@(objc_type=Menu, objc_name="insertItem") +Menu_insertItem :: #force_inline proc "c" (self: ^Menu, newItem: ^MenuItem, index: Integer) { + msgSend(nil, self, "insertItem:atIndex:", newItem, index) +} @(objc_type=Menu, objc_name="addItem") -Menu_addItem :: proc "c" (self: ^Menu, item: ^MenuItem) { - msgSend(nil, self, "addItem:", item) +Menu_addItem :: #force_inline proc "c" (self: ^Menu, newItem: ^MenuItem) { + msgSend(nil, self, "addItem:", newItem) +} +@(objc_type=Menu, objc_name="insertItemWithTitle") +Menu_insertItemWithTitle :: #force_inline proc "c" (self: ^Menu, string: ^String, selector: SEL, charCode: ^String, index: Integer) -> ^MenuItem { + return msgSend(^MenuItem, self, "insertItemWithTitle:action:keyEquivalent:atIndex:", string, selector, charCode, index) } - @(objc_type=Menu, objc_name="addItemWithTitle") -Menu_addItemWithTitle :: proc "c" (self: ^Menu, title: ^String, selector: SEL, keyEquivalent: ^String) -> ^MenuItem { - return msgSend(^MenuItem, self, "addItemWithTitle:action:keyEquivalent:", title, selector, keyEquivalent) +Menu_addItemWithTitle :: #force_inline proc "c" (self: ^Menu, string: ^String, selector: SEL, charCode: ^String) -> ^MenuItem { + return msgSend(^MenuItem, self, "addItemWithTitle:action:keyEquivalent:", string, selector, charCode) +} +@(objc_type=Menu, objc_name="removeItemAtIndex") +Menu_removeItemAtIndex :: #force_inline proc "c" (self: ^Menu, index: Integer) { + msgSend(nil, self, "removeItemAtIndex:", index) +} +@(objc_type=Menu, objc_name="removeItem") +Menu_removeItem :: #force_inline proc "c" (self: ^Menu, item: ^MenuItem) { + msgSend(nil, self, "removeItem:", item) +} +@(objc_type=Menu, objc_name="setSubmenu") +Menu_setSubmenu :: #force_inline proc "c" (self: ^Menu, menu: ^Menu, item: ^MenuItem) { + msgSend(nil, self, "setSubmenu:forItem:", menu, item) +} +@(objc_type=Menu, objc_name="removeAllItems") +Menu_removeAllItems :: #force_inline proc "c" (self: ^Menu) { + msgSend(nil, self, "removeAllItems") +} +@(objc_type=Menu, objc_name="itemAtIndex") +Menu_itemAtIndex :: #force_inline proc "c" (self: ^Menu, index: Integer) -> ^MenuItem { + return msgSend(^MenuItem, self, "itemAtIndex:", index) +} +@(objc_type=Menu, objc_name="indexOfItem") +Menu_indexOfItem :: #force_inline proc "c" (self: ^Menu, item: ^MenuItem) -> Integer { + return msgSend(Integer, self, "indexOfItem:", item) +} +@(objc_type=Menu, objc_name="indexOfItemWithTitle") +Menu_indexOfItemWithTitle :: #force_inline proc "c" (self: ^Menu, title: ^String) -> Integer { + return msgSend(Integer, self, "indexOfItemWithTitle:", title) +} +@(objc_type=Menu, objc_name="indexOfItemWithTag") +Menu_indexOfItemWithTag :: #force_inline proc "c" (self: ^Menu, tag: Integer) -> Integer { + return msgSend(Integer, self, "indexOfItemWithTag:", tag) +} +@(objc_type=Menu, objc_name="indexOfItemWithRepresentedObject") +Menu_indexOfItemWithRepresentedObject :: #force_inline proc "c" (self: ^Menu, object: id) -> Integer { + return msgSend(Integer, self, "indexOfItemWithRepresentedObject:", object) +} +@(objc_type=Menu, objc_name="indexOfItemWithSubmenu") +Menu_indexOfItemWithSubmenu :: #force_inline proc "c" (self: ^Menu, submenu: ^Menu) -> Integer { + return msgSend(Integer, self, "indexOfItemWithSubmenu:", submenu) +} +@(objc_type=Menu, objc_name="indexOfItemWithTarget") +Menu_indexOfItemWithTarget :: #force_inline proc "c" (self: ^Menu, target: id, actionSelector: SEL) -> Integer { + return msgSend(Integer, self, "indexOfItemWithTarget:andAction:", target, actionSelector) +} +@(objc_type=Menu, objc_name="itemWithTitle") +Menu_itemWithTitle :: #force_inline proc "c" (self: ^Menu, title: ^String) -> ^MenuItem { + return msgSend(^MenuItem, self, "itemWithTitle:", title) +} +@(objc_type=Menu, objc_name="itemWithTag") +Menu_itemWithTag :: #force_inline proc "c" (self: ^Menu, tag: Integer) -> ^MenuItem { + return msgSend(^MenuItem, self, "itemWithTag:", tag) +} +@(objc_type=Menu, objc_name="update") +Menu_update :: #force_inline proc "c" (self: ^Menu) { + msgSend(nil, self, "update") +} +@(objc_type=Menu, objc_name="performKeyEquivalent") +Menu_performKeyEquivalent :: #force_inline proc "c" (self: ^Menu, event: ^Event) -> bool { + return msgSend(bool, self, "performKeyEquivalent:", event) +} +@(objc_type=Menu, objc_name="itemChanged") +Menu_itemChanged :: #force_inline proc "c" (self: ^Menu, item: ^MenuItem) { + msgSend(nil, self, "itemChanged:", item) +} +@(objc_type=Menu, objc_name="performActionForItemAtIndex") +Menu_performActionForItemAtIndex :: #force_inline proc "c" (self: ^Menu, index: Integer) { + msgSend(nil, self, "performActionForItemAtIndex:", index) +} +@(objc_type=Menu, objc_name="cancelTracking") +Menu_cancelTracking :: #force_inline proc "c" (self: ^Menu) { + msgSend(nil, self, "cancelTracking") +} +@(objc_type=Menu, objc_name="cancelTrackingWithoutAnimation") +Menu_cancelTrackingWithoutAnimation :: #force_inline proc "c" (self: ^Menu) { + msgSend(nil, self, "cancelTrackingWithoutAnimation") +} +@(objc_type=Menu, objc_name="title") +Menu_title :: #force_inline proc "c" (self: ^Menu) -> ^String { + return msgSend(^String, self, "title") +} +@(objc_type=Menu, objc_name="setTitle") +Menu_setTitle :: #force_inline proc "c" (self: ^Menu, title: ^String) { + msgSend(nil, self, "setTitle:", title) +} +@(objc_type=Menu, objc_name="supermenu") +Menu_supermenu :: #force_inline proc "c" (self: ^Menu) -> ^Menu { + return msgSend(^Menu, self, "supermenu") +} +@(objc_type=Menu, objc_name="setSupermenu") +Menu_setSupermenu :: #force_inline proc "c" (self: ^Menu, supermenu: ^Menu) { + msgSend(nil, self, "setSupermenu:", supermenu) +} +@(objc_type=Menu, objc_name="itemArray") +Menu_itemArray :: #force_inline proc "c" (self: ^Menu) -> ^Array { + return msgSend(^Array, self, "itemArray") +} +@(objc_type=Menu, objc_name="setItemArray") +Menu_setItemArray :: #force_inline proc "c" (self: ^Menu, itemArray: ^Array) { + msgSend(nil, self, "setItemArray:", itemArray) +} +@(objc_type=Menu, objc_name="numberOfItems") +Menu_numberOfItems :: #force_inline proc "c" (self: ^Menu) -> Integer { + return msgSend(Integer, self, "numberOfItems") +} +@(objc_type=Menu, objc_name="autoenablesItems") +Menu_autoenablesItems :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "autoenablesItems") +} +@(objc_type=Menu, objc_name="setAutoenablesItems") +Menu_setAutoenablesItems :: #force_inline proc "c" (self: ^Menu, autoenablesItems: bool) { + msgSend(nil, self, "setAutoenablesItems:", autoenablesItems) +} +@(objc_type=Menu, objc_name="delegate") +Menu_delegate :: #force_inline proc "c" (self: ^Menu) -> ^MenuDelegate { + return msgSend(^MenuDelegate, self, "delegate") +} +@(objc_type=Menu, objc_name="setDelegate") +Menu_setDelegate :: #force_inline proc "c" (self: ^Menu, delegate: ^MenuDelegate) { + msgSend(nil, self, "setDelegate:", delegate) +} +@(objc_type=Menu, objc_name="menuBarHeight") +Menu_menuBarHeight :: #force_inline proc "c" (self: ^Menu) -> Float { + return msgSend(Float, self, "menuBarHeight") +} +@(objc_type=Menu, objc_name="highlightedItem") +Menu_highlightedItem :: #force_inline proc "c" (self: ^Menu) -> ^MenuItem { + return msgSend(^MenuItem, self, "highlightedItem") +} +@(objc_type=Menu, objc_name="minimumWidth") +Menu_minimumWidth :: #force_inline proc "c" (self: ^Menu) -> Float { + return msgSend(Float, self, "minimumWidth") +} +@(objc_type=Menu, objc_name="setMinimumWidth") +Menu_setMinimumWidth :: #force_inline proc "c" (self: ^Menu, minimumWidth: Float) { + msgSend(nil, self, "setMinimumWidth:", minimumWidth) +} +@(objc_type=Menu, objc_name="size") +Menu_size :: #force_inline proc "c" (self: ^Menu) -> Size { + return msgSend(Size, self, "size") +} +// @(objc_type=Menu, objc_name="font") +// Menu_font :: #force_inline proc "c" (self: ^Menu) -> ^Font { +// return msgSend(^Font, self, "font") +// } +// @(objc_type=Menu, objc_name="setFont") +// Menu_setFont :: #force_inline proc "c" (self: ^Menu, font: ^Font) { +// msgSend(nil, self, "setFont:", font) +// } +@(objc_type=Menu, objc_name="allowsContextMenuPlugIns") +Menu_allowsContextMenuPlugIns :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "allowsContextMenuPlugIns") +} +@(objc_type=Menu, objc_name="setAllowsContextMenuPlugIns") +Menu_setAllowsContextMenuPlugIns :: #force_inline proc "c" (self: ^Menu, allowsContextMenuPlugIns: bool) { + msgSend(nil, self, "setAllowsContextMenuPlugIns:", allowsContextMenuPlugIns) +} +@(objc_type=Menu, objc_name="showsStateColumn") +Menu_showsStateColumn :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "showsStateColumn") +} +@(objc_type=Menu, objc_name="setShowsStateColumn") +Menu_setShowsStateColumn :: #force_inline proc "c" (self: ^Menu, showsStateColumn: bool) { + msgSend(nil, self, "setShowsStateColumn:", showsStateColumn) +} +@(objc_type=Menu, objc_name="userInterfaceLayoutDirection") +Menu_userInterfaceLayoutDirection :: #force_inline proc "c" (self: ^Menu) -> UserInterfaceLayoutDirection { + return msgSend(UserInterfaceLayoutDirection, self, "userInterfaceLayoutDirection") +} +@(objc_type=Menu, objc_name="setUserInterfaceLayoutDirection") +Menu_setUserInterfaceLayoutDirection :: #force_inline proc "c" (self: ^Menu, userInterfaceLayoutDirection: UserInterfaceLayoutDirection) { + msgSend(nil, self, "setUserInterfaceLayoutDirection:", userInterfaceLayoutDirection) +} +@(objc_type=Menu, objc_name="paletteMenuWithColors_titles_selectionHandler", objc_is_class_method=true) +Menu_paletteMenuWithColors_titles_selectionHandler :: #force_inline proc "c" (colors: ^Array, itemTitles: ^Array, onSelectionChange: proc "c" (_arg_0: ^Menu)) -> ^Menu { + return msgSend(^Menu, Menu, "paletteMenuWithColors:titles:selectionHandler:", colors, itemTitles, onSelectionChange) +} +// @(objc_type=Menu, objc_name="paletteMenuWithColors_titles_templateImage_selectionHandler", objc_is_class_method=true) +// Menu_paletteMenuWithColors_titles_templateImage_selectionHandler :: #force_inline proc "c" (colors: ^Array, itemTitles: ^Array, image: ^Image, onSelectionChange: proc "c" (_arg_0: ^Menu)) -> ^Menu { +// return msgSend(^Menu, Menu, "paletteMenuWithColors:titles:templateImage:selectionHandler:", colors, itemTitles, image, onSelectionChange) +// } +@(objc_type=Menu, objc_name="presentationStyle") +Menu_presentationStyle :: #force_inline proc "c" (self: ^Menu) -> MenuPresentationStyle { + return msgSend(MenuPresentationStyle, self, "presentationStyle") +} +@(objc_type=Menu, objc_name="setPresentationStyle") +Menu_setPresentationStyle :: #force_inline proc "c" (self: ^Menu, presentationStyle: MenuPresentationStyle) { + msgSend(nil, self, "setPresentationStyle:", presentationStyle) +} +@(objc_type=Menu, objc_name="selectionMode") +Menu_selectionMode :: #force_inline proc "c" (self: ^Menu) -> MenuSelectionMode { + return msgSend(MenuSelectionMode, self, "selectionMode") +} +@(objc_type=Menu, objc_name="setSelectionMode") +Menu_setSelectionMode :: #force_inline proc "c" (self: ^Menu, selectionMode: MenuSelectionMode) { + msgSend(nil, self, "setSelectionMode:", selectionMode) +} +@(objc_type=Menu, objc_name="selectedItems") +Menu_selectedItems :: #force_inline proc "c" (self: ^Menu) -> ^Array { + return msgSend(^Array, self, "selectedItems") +} +@(objc_type=Menu, objc_name="setSelectedItems") +Menu_setSelectedItems :: #force_inline proc "c" (self: ^Menu, selectedItems: ^Array) { + msgSend(nil, self, "setSelectedItems:", selectedItems) +} +@(objc_type=Menu, objc_name="submenuAction") +Menu_submenuAction :: #force_inline proc "c" (self: ^Menu, sender: id) { + msgSend(nil, self, "submenuAction:", sender) +} +@(objc_type=Menu, objc_name="propertiesToUpdate") +Menu_propertiesToUpdate :: #force_inline proc "c" (self: ^Menu) -> MenuProperties { + return msgSend(MenuProperties, self, "propertiesToUpdate") +} +@(objc_type=Menu, objc_name="setMenuRepresentation") +Menu_setMenuRepresentation :: #force_inline proc "c" (self: ^Menu, menuRep: id) { + msgSend(nil, self, "setMenuRepresentation:", menuRep) +} +@(objc_type=Menu, objc_name="menuRepresentation") +Menu_menuRepresentation :: #force_inline proc "c" (self: ^Menu) -> id { + return msgSend(id, self, "menuRepresentation") +} +@(objc_type=Menu, objc_name="setContextMenuRepresentation") +Menu_setContextMenuRepresentation :: #force_inline proc "c" (self: ^Menu, menuRep: id) { + msgSend(nil, self, "setContextMenuRepresentation:", menuRep) +} +@(objc_type=Menu, objc_name="contextMenuRepresentation") +Menu_contextMenuRepresentation :: #force_inline proc "c" (self: ^Menu) -> id { + return msgSend(id, self, "contextMenuRepresentation") +} +@(objc_type=Menu, objc_name="setTearOffMenuRepresentation") +Menu_setTearOffMenuRepresentation :: #force_inline proc "c" (self: ^Menu, menuRep: id) { + msgSend(nil, self, "setTearOffMenuRepresentation:", menuRep) +} +@(objc_type=Menu, objc_name="tearOffMenuRepresentation") +Menu_tearOffMenuRepresentation :: #force_inline proc "c" (self: ^Menu) -> id { + return msgSend(id, self, "tearOffMenuRepresentation") +} +@(objc_type=Menu, objc_name="menuZone", objc_is_class_method=true) +Menu_menuZone :: #force_inline proc "c" () -> ^Zone { + return msgSend(^Zone, Menu, "menuZone") +} +@(objc_type=Menu, objc_name="setMenuZone", objc_is_class_method=true) +Menu_setMenuZone :: #force_inline proc "c" (zone: ^Zone) { + msgSend(nil, Menu, "setMenuZone:", zone) +} +@(objc_type=Menu, objc_name="attachedMenu") +Menu_attachedMenu :: #force_inline proc "c" (self: ^Menu) -> ^Menu { + return msgSend(^Menu, self, "attachedMenu") +} +@(objc_type=Menu, objc_name="isAttached") +Menu_isAttached :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "isAttached") +} +@(objc_type=Menu, objc_name="sizeToFit") +Menu_sizeToFit :: #force_inline proc "c" (self: ^Menu) { + msgSend(nil, self, "sizeToFit") +} +@(objc_type=Menu, objc_name="locationForSubmenu") +Menu_locationForSubmenu :: #force_inline proc "c" (self: ^Menu, submenu: ^Menu) -> Point { + return msgSend(Point, self, "locationForSubmenu:", submenu) +} +@(objc_type=Menu, objc_name="helpRequested") +Menu_helpRequested :: #force_inline proc "c" (self: ^Menu, eventPtr: ^Event) { + msgSend(nil, self, "helpRequested:", eventPtr) +} +@(objc_type=Menu, objc_name="menuChangedMessagesEnabled") +Menu_menuChangedMessagesEnabled :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "menuChangedMessagesEnabled") +} +@(objc_type=Menu, objc_name="setMenuChangedMessagesEnabled") +Menu_setMenuChangedMessagesEnabled :: #force_inline proc "c" (self: ^Menu, menuChangedMessagesEnabled: bool) { + msgSend(nil, self, "setMenuChangedMessagesEnabled:", menuChangedMessagesEnabled) +} +@(objc_type=Menu, objc_name="isTornOff") +Menu_isTornOff :: #force_inline proc "c" (self: ^Menu) -> bool { + return msgSend(bool, self, "isTornOff") +} +@(objc_type=Menu, objc_name="load", objc_is_class_method=true) +Menu_load :: #force_inline proc "c" () { + msgSend(nil, Menu, "load") +} +@(objc_type=Menu, objc_name="initialize", objc_is_class_method=true) +Menu_initialize :: #force_inline proc "c" () { + msgSend(nil, Menu, "initialize") +} +@(objc_type=Menu, objc_name="new", objc_is_class_method=true) +Menu_new :: #force_inline proc "c" () -> ^Menu { + return msgSend(^Menu, Menu, "new") +} +@(objc_type=Menu, objc_name="allocWithZone", objc_is_class_method=true) +Menu_allocWithZone :: #force_inline proc "c" (zone: ^Zone) -> ^Menu { + return msgSend(^Menu, Menu, "allocWithZone:", zone) +} +@(objc_type=Menu, objc_name="alloc", objc_is_class_method=true) +Menu_alloc :: #force_inline proc "c" () -> ^Menu { + return msgSend(^Menu, Menu, "alloc") +} +@(objc_type=Menu, objc_name="copyWithZone", objc_is_class_method=true) +Menu_copyWithZone :: #force_inline proc "c" (zone: ^Zone) -> id { + return msgSend(id, Menu, "copyWithZone:", zone) +} +@(objc_type=Menu, objc_name="mutableCopyWithZone", objc_is_class_method=true) +Menu_mutableCopyWithZone :: #force_inline proc "c" (zone: ^Zone) -> id { + return msgSend(id, Menu, "mutableCopyWithZone:", zone) +} +@(objc_type=Menu, objc_name="instancesRespondToSelector", objc_is_class_method=true) +Menu_instancesRespondToSelector :: #force_inline proc "c" (aSelector: SEL) -> bool { + return msgSend(bool, Menu, "instancesRespondToSelector:", aSelector) +} +@(objc_type=Menu, objc_name="conformsToProtocol", objc_is_class_method=true) +Menu_conformsToProtocol :: #force_inline proc "c" (protocol: ^Protocol) -> bool { + return msgSend(bool, Menu, "conformsToProtocol:", protocol) +} +@(objc_type=Menu, objc_name="instanceMethodForSelector", objc_is_class_method=true) +Menu_instanceMethodForSelector :: #force_inline proc "c" (aSelector: SEL) -> IMP { + return msgSend(IMP, Menu, "instanceMethodForSelector:", aSelector) +} +// @(objc_type=Menu, objc_name="instanceMethodSignatureForSelector", objc_is_class_method=true) +// Menu_instanceMethodSignatureForSelector :: #force_inline proc "c" (aSelector: SEL) -> ^MethodSignature { +// return msgSend(^MethodSignature, Menu, "instanceMethodSignatureForSelector:", aSelector) +// } +@(objc_type=Menu, objc_name="isSubclassOfClass", objc_is_class_method=true) +Menu_isSubclassOfClass :: #force_inline proc "c" (aClass: Class) -> bool { + return msgSend(bool, Menu, "isSubclassOfClass:", aClass) +} +@(objc_type=Menu, objc_name="resolveClassMethod", objc_is_class_method=true) +Menu_resolveClassMethod :: #force_inline proc "c" (sel: SEL) -> bool { + return msgSend(bool, Menu, "resolveClassMethod:", sel) +} +@(objc_type=Menu, objc_name="resolveInstanceMethod", objc_is_class_method=true) +Menu_resolveInstanceMethod :: #force_inline proc "c" (sel: SEL) -> bool { + return msgSend(bool, Menu, "resolveInstanceMethod:", sel) +} +@(objc_type=Menu, objc_name="hash", objc_is_class_method=true) +Menu_hash :: #force_inline proc "c" () -> UInteger { + return msgSend(UInteger, Menu, "hash") +} +@(objc_type=Menu, objc_name="superclass", objc_is_class_method=true) +Menu_superclass :: #force_inline proc "c" () -> Class { + return msgSend(Class, Menu, "superclass") +} +@(objc_type=Menu, objc_name="class", objc_is_class_method=true) +Menu_class :: #force_inline proc "c" () -> Class { + return msgSend(Class, Menu, "class") +} +@(objc_type=Menu, objc_name="description", objc_is_class_method=true) +Menu_description :: #force_inline proc "c" () -> ^String { + return msgSend(^String, Menu, "description") +} +@(objc_type=Menu, objc_name="debugDescription", objc_is_class_method=true) +Menu_debugDescription :: #force_inline proc "c" () -> ^String { + return msgSend(^String, Menu, "debugDescription") +} +@(objc_type=Menu, objc_name="version", objc_is_class_method=true) +Menu_version :: #force_inline proc "c" () -> Integer { + return msgSend(Integer, Menu, "version") +} +@(objc_type=Menu, objc_name="setVersion", objc_is_class_method=true) +Menu_setVersion :: #force_inline proc "c" (aVersion: Integer) { + msgSend(nil, Menu, "setVersion:", aVersion) +} +@(objc_type=Menu, objc_name="poseAsClass", objc_is_class_method=true) +Menu_poseAsClass :: #force_inline proc "c" (aClass: Class) { + msgSend(nil, Menu, "poseAsClass:", aClass) +} +@(objc_type=Menu, objc_name="cancelPreviousPerformRequestsWithTarget_selector_object", objc_is_class_method=true) +Menu_cancelPreviousPerformRequestsWithTarget_selector_object :: #force_inline proc "c" (aTarget: id, aSelector: SEL, anArgument: id) { + msgSend(nil, Menu, "cancelPreviousPerformRequestsWithTarget:selector:object:", aTarget, aSelector, anArgument) +} +@(objc_type=Menu, objc_name="cancelPreviousPerformRequestsWithTarget_", objc_is_class_method=true) +Menu_cancelPreviousPerformRequestsWithTarget_ :: #force_inline proc "c" (aTarget: id) { + msgSend(nil, Menu, "cancelPreviousPerformRequestsWithTarget:", aTarget) +} +@(objc_type=Menu, objc_name="accessInstanceVariablesDirectly", objc_is_class_method=true) +Menu_accessInstanceVariablesDirectly :: #force_inline proc "c" () -> bool { + return msgSend(bool, Menu, "accessInstanceVariablesDirectly") +} +@(objc_type=Menu, objc_name="useStoredAccessor", objc_is_class_method=true) +Menu_useStoredAccessor :: #force_inline proc "c" () -> bool { + return msgSend(bool, Menu, "useStoredAccessor") +} +@(objc_type=Menu, objc_name="keyPathsForValuesAffectingValueForKey", objc_is_class_method=true) +Menu_keyPathsForValuesAffectingValueForKey :: #force_inline proc "c" (key: ^String) -> ^Set { + return msgSend(^Set, Menu, "keyPathsForValuesAffectingValueForKey:", key) +} +@(objc_type=Menu, objc_name="automaticallyNotifiesObserversForKey", objc_is_class_method=true) +Menu_automaticallyNotifiesObserversForKey :: #force_inline proc "c" (key: ^String) -> bool { + return msgSend(bool, Menu, "automaticallyNotifiesObserversForKey:", key) +} +@(objc_type=Menu, objc_name="setKeys", objc_is_class_method=true) +Menu_setKeys :: #force_inline proc "c" (keys: ^Array, dependentKey: ^String) { + msgSend(nil, Menu, "setKeys:triggerChangeNotificationsForDependentKey:", keys, dependentKey) +} +@(objc_type=Menu, objc_name="classFallbacksForKeyedArchiver", objc_is_class_method=true) +Menu_classFallbacksForKeyedArchiver :: #force_inline proc "c" () -> ^Array { + return msgSend(^Array, Menu, "classFallbacksForKeyedArchiver") +} +@(objc_type=Menu, objc_name="classForKeyedUnarchiver", objc_is_class_method=true) +Menu_classForKeyedUnarchiver :: #force_inline proc "c" () -> Class { + return msgSend(Class, Menu, "classForKeyedUnarchiver") +} +@(objc_type=Menu, objc_name="exposeBinding", objc_is_class_method=true) +Menu_exposeBinding :: #force_inline proc "c" (binding: ^String) { + msgSend(nil, Menu, "exposeBinding:", binding) +} +@(objc_type=Menu, objc_name="setDefaultPlaceholder", objc_is_class_method=true) +Menu_setDefaultPlaceholder :: #force_inline proc "c" (placeholder: id, marker: id, binding: ^String) { + msgSend(nil, Menu, "setDefaultPlaceholder:forMarker:withBinding:", placeholder, marker, binding) +} +@(objc_type=Menu, objc_name="defaultPlaceholderForMarker", objc_is_class_method=true) +Menu_defaultPlaceholderForMarker :: #force_inline proc "c" (marker: id, binding: ^String) -> id { + return msgSend(id, Menu, "defaultPlaceholderForMarker:withBinding:", marker, binding) +} +@(objc_type=Menu, objc_name="popUpContextMenu") +Menu_popUpContextMenu :: proc { + Menu_popUpContextMenu_withEvent_forView, + // Menu_popUpContextMenu_withEvent_forView_withFont, } -@(objc_type=Menu, objc_name="itemArray") -Menu_itemArray :: proc "c" (self: ^Menu) -> ^Array { - return msgSend(^Array, self, "itemArray") -} \ No newline at end of file +@(objc_type=Menu, objc_name="paletteMenuWithColors") +Menu_paletteMenuWithColors :: proc { + Menu_paletteMenuWithColors_titles_selectionHandler, + // Menu_paletteMenuWithColors_titles_templateImage_selectionHandler, +} + +@(objc_type=Menu, objc_name="cancelPreviousPerformRequestsWithTarget") +Menu_cancelPreviousPerformRequestsWithTarget :: proc { + Menu_cancelPreviousPerformRequestsWithTarget_selector_object, + Menu_cancelPreviousPerformRequestsWithTarget_, +} + + + + + + + +@(objc_class="NSMenuDelegate") +MenuDelegate :: struct {using _: Object, using _: ObjectProtocol} + +@(objc_type=MenuDelegate, objc_name="menuNeedsUpdate") +MenuDelegate_menuNeedsUpdate :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu) { + msgSend(nil, self, "menuNeedsUpdate:", menu) +} +@(objc_type=MenuDelegate, objc_name="numberOfItemsInMenu") +MenuDelegate_numberOfItemsInMenu :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu) -> Integer { + return msgSend(Integer, self, "numberOfItemsInMenu:", menu) +} +@(objc_type=MenuDelegate, objc_name="menu_updateItem_atIndex_shouldCancel") +MenuDelegate_menu_updateItem_atIndex_shouldCancel :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu, item: ^MenuItem, index: Integer, shouldCancel: bool) -> bool { + return msgSend(bool, self, "menu:updateItem:atIndex:shouldCancel:", menu, item, index, shouldCancel) +} +@(objc_type=MenuDelegate, objc_name="menuHasKeyEquivalent") +MenuDelegate_menuHasKeyEquivalent :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu, event: ^Event, target: ^id, action: ^SEL) -> bool { + return msgSend(bool, self, "menuHasKeyEquivalent:forEvent:target:action:", menu, event, target, action) +} +@(objc_type=MenuDelegate, objc_name="menuWillOpen") +MenuDelegate_menuWillOpen :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu) { + msgSend(nil, self, "menuWillOpen:", menu) +} +@(objc_type=MenuDelegate, objc_name="menuDidClose") +MenuDelegate_menuDidClose :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu) { + msgSend(nil, self, "menuDidClose:", menu) +} +@(objc_type=MenuDelegate, objc_name="menu_willHighlightItem") +MenuDelegate_menu_willHighlightItem :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu, item: ^MenuItem) { + msgSend(nil, self, "menu:willHighlightItem:", menu, item) +} +@(objc_type=MenuDelegate, objc_name="confinementRectForMenu") +MenuDelegate_confinementRectForMenu :: #force_inline proc "c" (self: ^MenuDelegate, menu: ^Menu, screen: ^Screen) -> Rect { + return msgSend(Rect, self, "confinementRectForMenu:onScreen:", menu, screen) +} +@(objc_type=MenuDelegate, objc_name="menu") +MenuDelegate_menu :: proc { + MenuDelegate_menu_updateItem_atIndex_shouldCancel, + MenuDelegate_menu_willHighlightItem, +} diff --git a/core/sys/darwin/Foundation/NSMenuItem.odin b/core/sys/darwin/Foundation/NSMenuItem.odin new file mode 100644 index 000000000..248a0cf4f --- /dev/null +++ b/core/sys/darwin/Foundation/NSMenuItem.odin @@ -0,0 +1,460 @@ +package objc_Foundation + +import "base:builtin" +import "base:intrinsics" + +KeyEquivalentModifierFlag :: EventModifierFlag +KeyEquivalentModifierMask :: EventModifierFlags + +// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information. +KeyEventModifierFlagDeviceIndependentFlagsMask := transmute(KeyEquivalentModifierMask)_KeyEventModifierFlagDeviceIndependentFlagsMask +@(private) _KeyEventModifierFlagDeviceIndependentFlagsMask := UInteger(0xffff0000) + +MenuItemCallback :: proc "c" (unused: rawptr, name: SEL, sender: ^Object) + +@(objc_class="NSMenuItem") +MenuItem :: struct {using _: Object} + +@(objc_type=MenuItem, objc_name="registerActionCallback", objc_is_class_method=true) +MenuItem_registerActionCallback :: proc "c" (name: cstring, callback: MenuItemCallback) -> SEL { + s := string(name) + n := len(s) + sel: SEL + if n > 0 && s[n-1] != ':' { + col_name := intrinsics.alloca(n+2, 1) + builtin.copy(col_name[:n], s) + col_name[n] = ':' + col_name[n+1] = 0 + sel = sel_registerName(cstring(col_name)) + } else { + sel = sel_registerName(name) + } + if callback != nil { + class_addMethod(intrinsics.objc_find_class("NSObject"), sel, auto_cast callback, "v@:@") + } + return sel +} + +@(objc_type=MenuItem, objc_name="init") +MenuItem_init :: proc "c" (self: ^MenuItem) -> ^MenuItem { + return msgSend(^MenuItem, self, "init") +} + + +@(objc_type=MenuItem, objc_name="separatorItem", objc_is_class_method=true) +MenuItem_separatorItem :: #force_inline proc "c" () -> ^MenuItem { + return msgSend(^MenuItem, MenuItem, "separatorItem") +} +@(objc_type=MenuItem, objc_name="sectionHeaderWithTitle", objc_is_class_method=true) +MenuItem_sectionHeaderWithTitle :: #force_inline proc "c" (title: ^String) -> ^MenuItem { + return msgSend(^MenuItem, MenuItem, "sectionHeaderWithTitle:", title) +} +@(objc_type=MenuItem, objc_name="initWithTitle") +MenuItem_initWithTitle :: #force_inline proc "c" (self: ^MenuItem, string: ^String, selector: SEL, charCode: ^String) -> ^MenuItem { + return msgSend(^MenuItem, self, "initWithTitle:action:keyEquivalent:", string, selector, charCode) +} +@(objc_type=MenuItem, objc_name="initWithCoder") +MenuItem_initWithCoder :: #force_inline proc "c" (self: ^MenuItem, coder: ^Coder) -> ^MenuItem { + return msgSend(^MenuItem, self, "initWithCoder:", coder) +} +@(objc_type=MenuItem, objc_name="usesUserKeyEquivalents", objc_is_class_method=true) +MenuItem_usesUserKeyEquivalents :: #force_inline proc "c" () -> bool { + return msgSend(bool, MenuItem, "usesUserKeyEquivalents") +} +@(objc_type=MenuItem, objc_name="setUsesUserKeyEquivalents", objc_is_class_method=true) +MenuItem_setUsesUserKeyEquivalents :: #force_inline proc "c" (usesUserKeyEquivalents: bool) { + msgSend(nil, MenuItem, "setUsesUserKeyEquivalents:", usesUserKeyEquivalents) +} +@(objc_type=MenuItem, objc_name="menu") +MenuItem_menu :: #force_inline proc "c" (self: ^MenuItem) -> ^Menu { + return msgSend(^Menu, self, "menu") +} +@(objc_type=MenuItem, objc_name="setMenu") +MenuItem_setMenu :: #force_inline proc "c" (self: ^MenuItem, menu: ^Menu) { + msgSend(nil, self, "setMenu:", menu) +} +@(objc_type=MenuItem, objc_name="hasSubmenu") +MenuItem_hasSubmenu :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "hasSubmenu") +} +@(objc_type=MenuItem, objc_name="submenu") +MenuItem_submenu :: #force_inline proc "c" (self: ^MenuItem) -> ^Menu { + return msgSend(^Menu, self, "submenu") +} +@(objc_type=MenuItem, objc_name="setSubmenu") +MenuItem_setSubmenu :: #force_inline proc "c" (self: ^MenuItem, submenu: ^Menu) { + msgSend(nil, self, "setSubmenu:", submenu) +} +@(objc_type=MenuItem, objc_name="parentItem") +MenuItem_parentItem :: #force_inline proc "c" (self: ^MenuItem) -> ^MenuItem { + return msgSend(^MenuItem, self, "parentItem") +} +@(objc_type=MenuItem, objc_name="title") +MenuItem_title :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "title") +} +@(objc_type=MenuItem, objc_name="setTitle") +MenuItem_setTitle :: #force_inline proc "c" (self: ^MenuItem, title: ^String) { + msgSend(nil, self, "setTitle:", title) +} +// @(objc_type=MenuItem, objc_name="attributedTitle") +// MenuItem_attributedTitle :: #force_inline proc "c" (self: ^MenuItem) -> ^AttributedString { +// return msgSend(^AttributedString, self, "attributedTitle") +// } +// @(objc_type=MenuItem, objc_name="setAttributedTitle") +// MenuItem_setAttributedTitle :: #force_inline proc "c" (self: ^MenuItem, attributedTitle: ^AttributedString) { +// msgSend(nil, self, "setAttributedTitle:", attributedTitle) +// } +@(objc_type=MenuItem, objc_name="subtitle") +MenuItem_subtitle :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "subtitle") +} +@(objc_type=MenuItem, objc_name="setSubtitle") +MenuItem_setSubtitle :: #force_inline proc "c" (self: ^MenuItem, subtitle: ^String) { + msgSend(nil, self, "setSubtitle:", subtitle) +} +@(objc_type=MenuItem, objc_name="isSeparatorItem") +MenuItem_isSeparatorItem :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isSeparatorItem") +} +@(objc_type=MenuItem, objc_name="isSectionHeader") +MenuItem_isSectionHeader :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isSectionHeader") +} +@(objc_type=MenuItem, objc_name="keyEquivalent") +MenuItem_keyEquivalent :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "keyEquivalent") +} +@(objc_type=MenuItem, objc_name="setKeyEquivalent") +MenuItem_setKeyEquivalent :: #force_inline proc "c" (self: ^MenuItem, keyEquivalent: ^String) { + msgSend(nil, self, "setKeyEquivalent:", keyEquivalent) +} +@(objc_type=MenuItem, objc_name="keyEquivalentModifierMask") +MenuItem_keyEquivalentModifierMask :: #force_inline proc "c" (self: ^MenuItem) -> EventModifierFlags { + return msgSend(EventModifierFlags, self, "keyEquivalentModifierMask") +} +@(objc_type=MenuItem, objc_name="setKeyEquivalentModifierMask") +MenuItem_setKeyEquivalentModifierMask :: #force_inline proc "c" (self: ^MenuItem, keyEquivalentModifierMask: EventModifierFlags) { + msgSend(nil, self, "setKeyEquivalentModifierMask:", keyEquivalentModifierMask) +} +@(objc_type=MenuItem, objc_name="userKeyEquivalent") +MenuItem_userKeyEquivalent :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "userKeyEquivalent") +} +@(objc_type=MenuItem, objc_name="allowsKeyEquivalentWhenHidden") +MenuItem_allowsKeyEquivalentWhenHidden :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "allowsKeyEquivalentWhenHidden") +} +@(objc_type=MenuItem, objc_name="setAllowsKeyEquivalentWhenHidden") +MenuItem_setAllowsKeyEquivalentWhenHidden :: #force_inline proc "c" (self: ^MenuItem, allowsKeyEquivalentWhenHidden: bool) { + msgSend(nil, self, "setAllowsKeyEquivalentWhenHidden:", allowsKeyEquivalentWhenHidden) +} +@(objc_type=MenuItem, objc_name="allowsAutomaticKeyEquivalentLocalization") +MenuItem_allowsAutomaticKeyEquivalentLocalization :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "allowsAutomaticKeyEquivalentLocalization") +} +@(objc_type=MenuItem, objc_name="setAllowsAutomaticKeyEquivalentLocalization") +MenuItem_setAllowsAutomaticKeyEquivalentLocalization :: #force_inline proc "c" (self: ^MenuItem, allowsAutomaticKeyEquivalentLocalization: bool) { + msgSend(nil, self, "setAllowsAutomaticKeyEquivalentLocalization:", allowsAutomaticKeyEquivalentLocalization) +} +@(objc_type=MenuItem, objc_name="allowsAutomaticKeyEquivalentMirroring") +MenuItem_allowsAutomaticKeyEquivalentMirroring :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "allowsAutomaticKeyEquivalentMirroring") +} +@(objc_type=MenuItem, objc_name="setAllowsAutomaticKeyEquivalentMirroring") +MenuItem_setAllowsAutomaticKeyEquivalentMirroring :: #force_inline proc "c" (self: ^MenuItem, allowsAutomaticKeyEquivalentMirroring: bool) { + msgSend(nil, self, "setAllowsAutomaticKeyEquivalentMirroring:", allowsAutomaticKeyEquivalentMirroring) +} +// @(objc_type=MenuItem, objc_name="image") +// MenuItem_image :: #force_inline proc "c" (self: ^MenuItem) -> ^Image { +// return msgSend(^Image, self, "image") +// } +// @(objc_type=MenuItem, objc_name="setImage") +// MenuItem_setImage :: #force_inline proc "c" (self: ^MenuItem, image: ^Image) { +// msgSend(nil, self, "setImage:", image) +// } +// @(objc_type=MenuItem, objc_name="state") +// MenuItem_state :: #force_inline proc "c" (self: ^MenuItem) -> ControlStateValue { +// return msgSend(ControlStateValue, self, "state") +// } +// @(objc_type=MenuItem, objc_name="setState") +// MenuItem_setState :: #force_inline proc "c" (self: ^MenuItem, state: ControlStateValue) { +// msgSend(nil, self, "setState:", state) +// } +// @(objc_type=MenuItem, objc_name="onStateImage") +// MenuItem_onStateImage :: #force_inline proc "c" (self: ^MenuItem) -> ^Image { +// return msgSend(^Image, self, "onStateImage") +// } +// @(objc_type=MenuItem, objc_name="setOnStateImage") +// MenuItem_setOnStateImage :: #force_inline proc "c" (self: ^MenuItem, onStateImage: ^Image) { +// msgSend(nil, self, "setOnStateImage:", onStateImage) +// } +// @(objc_type=MenuItem, objc_name="offStateImage") +// MenuItem_offStateImage :: #force_inline proc "c" (self: ^MenuItem) -> ^Image { +// return msgSend(^Image, self, "offStateImage") +// } +// @(objc_type=MenuItem, objc_name="setOffStateImage") +// MenuItem_setOffStateImage :: #force_inline proc "c" (self: ^MenuItem, offStateImage: ^Image) { +// msgSend(nil, self, "setOffStateImage:", offStateImage) +// } +// @(objc_type=MenuItem, objc_name="mixedStateImage") +// MenuItem_mixedStateImage :: #force_inline proc "c" (self: ^MenuItem) -> ^Image { +// return msgSend(^Image, self, "mixedStateImage") +// } +// @(objc_type=MenuItem, objc_name="setMixedStateImage") +// MenuItem_setMixedStateImage :: #force_inline proc "c" (self: ^MenuItem, mixedStateImage: ^Image) { +// msgSend(nil, self, "setMixedStateImage:", mixedStateImage) +// } +@(objc_type=MenuItem, objc_name="isEnabled") +MenuItem_isEnabled :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isEnabled") +} +@(objc_type=MenuItem, objc_name="setEnabled") +MenuItem_setEnabled :: #force_inline proc "c" (self: ^MenuItem, enabled: bool) { + msgSend(nil, self, "setEnabled:", enabled) +} +@(objc_type=MenuItem, objc_name="isAlternate") +MenuItem_isAlternate :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isAlternate") +} +@(objc_type=MenuItem, objc_name="setAlternate") +MenuItem_setAlternate :: #force_inline proc "c" (self: ^MenuItem, alternate: bool) { + msgSend(nil, self, "setAlternate:", alternate) +} +@(objc_type=MenuItem, objc_name="indentationLevel") +MenuItem_indentationLevel :: #force_inline proc "c" (self: ^MenuItem) -> Integer { + return msgSend(Integer, self, "indentationLevel") +} +@(objc_type=MenuItem, objc_name="setIndentationLevel") +MenuItem_setIndentationLevel :: #force_inline proc "c" (self: ^MenuItem, indentationLevel: Integer) { + msgSend(nil, self, "setIndentationLevel:", indentationLevel) +} +@(objc_type=MenuItem, objc_name="target") +MenuItem_target :: #force_inline proc "c" (self: ^MenuItem) -> id { + return msgSend(id, self, "target") +} +@(objc_type=MenuItem, objc_name="setTarget") +MenuItem_setTarget :: #force_inline proc "c" (self: ^MenuItem, target: id) { + msgSend(nil, self, "setTarget:", target) +} +@(objc_type=MenuItem, objc_name="action") +MenuItem_action :: #force_inline proc "c" (self: ^MenuItem) -> SEL { + return msgSend(SEL, self, "action") +} +@(objc_type=MenuItem, objc_name="setAction") +MenuItem_setAction :: #force_inline proc "c" (self: ^MenuItem, action: SEL) { + msgSend(nil, self, "setAction:", action) +} +@(objc_type=MenuItem, objc_name="tag") +MenuItem_tag :: #force_inline proc "c" (self: ^MenuItem) -> Integer { + return msgSend(Integer, self, "tag") +} +@(objc_type=MenuItem, objc_name="setTag") +MenuItem_setTag :: #force_inline proc "c" (self: ^MenuItem, tag: Integer) { + msgSend(nil, self, "setTag:", tag) +} +@(objc_type=MenuItem, objc_name="representedObject") +MenuItem_representedObject :: #force_inline proc "c" (self: ^MenuItem) -> id { + return msgSend(id, self, "representedObject") +} +@(objc_type=MenuItem, objc_name="setRepresentedObject") +MenuItem_setRepresentedObject :: #force_inline proc "c" (self: ^MenuItem, representedObject: id) { + msgSend(nil, self, "setRepresentedObject:", representedObject) +} +@(objc_type=MenuItem, objc_name="view") +MenuItem_view :: #force_inline proc "c" (self: ^MenuItem) -> ^View { + return msgSend(^View, self, "view") +} +@(objc_type=MenuItem, objc_name="setView") +MenuItem_setView :: #force_inline proc "c" (self: ^MenuItem, view: ^View) { + msgSend(nil, self, "setView:", view) +} +@(objc_type=MenuItem, objc_name="isHighlighted") +MenuItem_isHighlighted :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isHighlighted") +} +@(objc_type=MenuItem, objc_name="isHidden") +MenuItem_isHidden :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isHidden") +} +@(objc_type=MenuItem, objc_name="setHidden") +MenuItem_setHidden :: #force_inline proc "c" (self: ^MenuItem, hidden: bool) { + msgSend(nil, self, "setHidden:", hidden) +} +@(objc_type=MenuItem, objc_name="isHiddenOrHasHiddenAncestor") +MenuItem_isHiddenOrHasHiddenAncestor :: #force_inline proc "c" (self: ^MenuItem) -> bool { + return msgSend(bool, self, "isHiddenOrHasHiddenAncestor") +} +@(objc_type=MenuItem, objc_name="toolTip") +MenuItem_toolTip :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "toolTip") +} +@(objc_type=MenuItem, objc_name="setToolTip") +MenuItem_setToolTip :: #force_inline proc "c" (self: ^MenuItem, toolTip: ^String) { + msgSend(nil, self, "setToolTip:", toolTip) +} +// @(objc_type=MenuItem, objc_name="badge") +// MenuItem_badge :: #force_inline proc "c" (self: ^MenuItem) -> ^MenuItemBadge { +// return msgSend(^MenuItemBadge, self, "badge") +// } +// @(objc_type=MenuItem, objc_name="setBadge") +// MenuItem_setBadge :: #force_inline proc "c" (self: ^MenuItem, badge: ^MenuItemBadge) { +// msgSend(nil, self, "setBadge:", badge) +// } +@(objc_type=MenuItem, objc_name="setMnemonicLocation") +MenuItem_setMnemonicLocation :: #force_inline proc "c" (self: ^MenuItem, location: UInteger) { + msgSend(nil, self, "setMnemonicLocation:", location) +} +@(objc_type=MenuItem, objc_name="mnemonicLocation") +MenuItem_mnemonicLocation :: #force_inline proc "c" (self: ^MenuItem) -> UInteger { + return msgSend(UInteger, self, "mnemonicLocation") +} +@(objc_type=MenuItem, objc_name="mnemonic") +MenuItem_mnemonic :: #force_inline proc "c" (self: ^MenuItem) -> ^String { + return msgSend(^String, self, "mnemonic") +} +@(objc_type=MenuItem, objc_name="setTitleWithMnemonic") +MenuItem_setTitleWithMnemonic :: #force_inline proc "c" (self: ^MenuItem, stringWithAmpersand: ^String) { + msgSend(nil, self, "setTitleWithMnemonic:", stringWithAmpersand) +} +@(objc_type=MenuItem, objc_name="load", objc_is_class_method=true) +MenuItem_load :: #force_inline proc "c" () { + msgSend(nil, MenuItem, "load") +} +@(objc_type=MenuItem, objc_name="initialize", objc_is_class_method=true) +MenuItem_initialize :: #force_inline proc "c" () { + msgSend(nil, MenuItem, "initialize") +} +@(objc_type=MenuItem, objc_name="new", objc_is_class_method=true) +MenuItem_new :: #force_inline proc "c" () -> ^MenuItem { + return msgSend(^MenuItem, MenuItem, "new") +} +@(objc_type=MenuItem, objc_name="allocWithZone", objc_is_class_method=true) +MenuItem_allocWithZone :: #force_inline proc "c" (zone: ^Zone) -> ^MenuItem { + return msgSend(^MenuItem, MenuItem, "allocWithZone:", zone) +} +@(objc_type=MenuItem, objc_name="alloc", objc_is_class_method=true) +MenuItem_alloc :: #force_inline proc "c" () -> ^MenuItem { + return msgSend(^MenuItem, MenuItem, "alloc") +} +@(objc_type=MenuItem, objc_name="copyWithZone", objc_is_class_method=true) +MenuItem_copyWithZone :: #force_inline proc "c" (zone: ^Zone) -> id { + return msgSend(id, MenuItem, "copyWithZone:", zone) +} +@(objc_type=MenuItem, objc_name="mutableCopyWithZone", objc_is_class_method=true) +MenuItem_mutableCopyWithZone :: #force_inline proc "c" (zone: ^Zone) -> id { + return msgSend(id, MenuItem, "mutableCopyWithZone:", zone) +} +@(objc_type=MenuItem, objc_name="instancesRespondToSelector", objc_is_class_method=true) +MenuItem_instancesRespondToSelector :: #force_inline proc "c" (aSelector: SEL) -> bool { + return msgSend(bool, MenuItem, "instancesRespondToSelector:", aSelector) +} +@(objc_type=MenuItem, objc_name="conformsToProtocol", objc_is_class_method=true) +MenuItem_conformsToProtocol :: #force_inline proc "c" (protocol: ^Protocol) -> bool { + return msgSend(bool, MenuItem, "conformsToProtocol:", protocol) +} +@(objc_type=MenuItem, objc_name="instanceMethodForSelector", objc_is_class_method=true) +MenuItem_instanceMethodForSelector :: #force_inline proc "c" (aSelector: SEL) -> IMP { + return msgSend(IMP, MenuItem, "instanceMethodForSelector:", aSelector) +} +// @(objc_type=MenuItem, objc_name="instanceMethodSignatureForSelector", objc_is_class_method=true) +// MenuItem_instanceMethodSignatureForSelector :: #force_inline proc "c" (aSelector: SEL) -> ^MethodSignature { +// return msgSend(^MethodSignature, MenuItem, "instanceMethodSignatureForSelector:", aSelector) +// } +@(objc_type=MenuItem, objc_name="isSubclassOfClass", objc_is_class_method=true) +MenuItem_isSubclassOfClass :: #force_inline proc "c" (aClass: Class) -> bool { + return msgSend(bool, MenuItem, "isSubclassOfClass:", aClass) +} +@(objc_type=MenuItem, objc_name="resolveClassMethod", objc_is_class_method=true) +MenuItem_resolveClassMethod :: #force_inline proc "c" (sel: SEL) -> bool { + return msgSend(bool, MenuItem, "resolveClassMethod:", sel) +} +@(objc_type=MenuItem, objc_name="resolveInstanceMethod", objc_is_class_method=true) +MenuItem_resolveInstanceMethod :: #force_inline proc "c" (sel: SEL) -> bool { + return msgSend(bool, MenuItem, "resolveInstanceMethod:", sel) +} +@(objc_type=MenuItem, objc_name="hash", objc_is_class_method=true) +MenuItem_hash :: #force_inline proc "c" () -> UInteger { + return msgSend(UInteger, MenuItem, "hash") +} +@(objc_type=MenuItem, objc_name="superclass", objc_is_class_method=true) +MenuItem_superclass :: #force_inline proc "c" () -> Class { + return msgSend(Class, MenuItem, "superclass") +} +@(objc_type=MenuItem, objc_name="class", objc_is_class_method=true) +MenuItem_class :: #force_inline proc "c" () -> Class { + return msgSend(Class, MenuItem, "class") +} +@(objc_type=MenuItem, objc_name="description", objc_is_class_method=true) +MenuItem_description :: #force_inline proc "c" () -> ^String { + return msgSend(^String, MenuItem, "description") +} +@(objc_type=MenuItem, objc_name="debugDescription", objc_is_class_method=true) +MenuItem_debugDescription :: #force_inline proc "c" () -> ^String { + return msgSend(^String, MenuItem, "debugDescription") +} +@(objc_type=MenuItem, objc_name="version", objc_is_class_method=true) +MenuItem_version :: #force_inline proc "c" () -> Integer { + return msgSend(Integer, MenuItem, "version") +} +@(objc_type=MenuItem, objc_name="setVersion", objc_is_class_method=true) +MenuItem_setVersion :: #force_inline proc "c" (aVersion: Integer) { + msgSend(nil, MenuItem, "setVersion:", aVersion) +} +@(objc_type=MenuItem, objc_name="poseAsClass", objc_is_class_method=true) +MenuItem_poseAsClass :: #force_inline proc "c" (aClass: Class) { + msgSend(nil, MenuItem, "poseAsClass:", aClass) +} +@(objc_type=MenuItem, objc_name="cancelPreviousPerformRequestsWithTarget_selector_object", objc_is_class_method=true) +MenuItem_cancelPreviousPerformRequestsWithTarget_selector_object :: #force_inline proc "c" (aTarget: id, aSelector: SEL, anArgument: id) { + msgSend(nil, MenuItem, "cancelPreviousPerformRequestsWithTarget:selector:object:", aTarget, aSelector, anArgument) +} +@(objc_type=MenuItem, objc_name="cancelPreviousPerformRequestsWithTarget_", objc_is_class_method=true) +MenuItem_cancelPreviousPerformRequestsWithTarget_ :: #force_inline proc "c" (aTarget: id) { + msgSend(nil, MenuItem, "cancelPreviousPerformRequestsWithTarget:", aTarget) +} +@(objc_type=MenuItem, objc_name="accessInstanceVariablesDirectly", objc_is_class_method=true) +MenuItem_accessInstanceVariablesDirectly :: #force_inline proc "c" () -> bool { + return msgSend(bool, MenuItem, "accessInstanceVariablesDirectly") +} +@(objc_type=MenuItem, objc_name="useStoredAccessor", objc_is_class_method=true) +MenuItem_useStoredAccessor :: #force_inline proc "c" () -> bool { + return msgSend(bool, MenuItem, "useStoredAccessor") +} +@(objc_type=MenuItem, objc_name="keyPathsForValuesAffectingValueForKey", objc_is_class_method=true) +MenuItem_keyPathsForValuesAffectingValueForKey :: #force_inline proc "c" (key: ^String) -> ^Set { + return msgSend(^Set, MenuItem, "keyPathsForValuesAffectingValueForKey:", key) +} +@(objc_type=MenuItem, objc_name="automaticallyNotifiesObserversForKey", objc_is_class_method=true) +MenuItem_automaticallyNotifiesObserversForKey :: #force_inline proc "c" (key: ^String) -> bool { + return msgSend(bool, MenuItem, "automaticallyNotifiesObserversForKey:", key) +} +@(objc_type=MenuItem, objc_name="setKeys", objc_is_class_method=true) +MenuItem_setKeys :: #force_inline proc "c" (keys: ^Array, dependentKey: ^String) { + msgSend(nil, MenuItem, "setKeys:triggerChangeNotificationsForDependentKey:", keys, dependentKey) +} +@(objc_type=MenuItem, objc_name="classFallbacksForKeyedArchiver", objc_is_class_method=true) +MenuItem_classFallbacksForKeyedArchiver :: #force_inline proc "c" () -> ^Array { + return msgSend(^Array, MenuItem, "classFallbacksForKeyedArchiver") +} +@(objc_type=MenuItem, objc_name="classForKeyedUnarchiver", objc_is_class_method=true) +MenuItem_classForKeyedUnarchiver :: #force_inline proc "c" () -> Class { + return msgSend(Class, MenuItem, "classForKeyedUnarchiver") +} +@(objc_type=MenuItem, objc_name="exposeBinding", objc_is_class_method=true) +MenuItem_exposeBinding :: #force_inline proc "c" (binding: ^String) { + msgSend(nil, MenuItem, "exposeBinding:", binding) +} +@(objc_type=MenuItem, objc_name="setDefaultPlaceholder", objc_is_class_method=true) +MenuItem_setDefaultPlaceholder :: #force_inline proc "c" (placeholder: id, marker: id, binding: ^String) { + msgSend(nil, MenuItem, "setDefaultPlaceholder:forMarker:withBinding:", placeholder, marker, binding) +} +@(objc_type=MenuItem, objc_name="defaultPlaceholderForMarker", objc_is_class_method=true) +MenuItem_defaultPlaceholderForMarker :: #force_inline proc "c" (marker: id, binding: ^String) -> id { + return msgSend(id, MenuItem, "defaultPlaceholderForMarker:withBinding:", marker, binding) +} +@(objc_type=MenuItem, objc_name="cancelPreviousPerformRequestsWithTarget") +MenuItem_cancelPreviousPerformRequestsWithTarget :: proc { + MenuItem_cancelPreviousPerformRequestsWithTarget_selector_object, + MenuItem_cancelPreviousPerformRequestsWithTarget_, +} \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSNotification.odin b/core/sys/darwin/Foundation/NSNotification.odin index f766d0cab..f2f4e819b 100644 --- a/core/sys/darwin/Foundation/NSNotification.odin +++ b/core/sys/darwin/Foundation/NSNotification.odin @@ -50,10 +50,22 @@ NotificationCenter_defaultCenter :: proc "c" () -> ^NotificationCenter { return msgSend(^NotificationCenter, NotificationCenter, "defaultCenter") } -@(objc_type=NotificationCenter, objc_name="addObserver") -NotificationCenter_addObserverName :: proc "c" (self: ^NotificationCenter, name: NotificationName, pObj: ^Object, pQueue: rawptr, block: ^Block) -> ^Object { - return msgSend(^Object, self, "addObserverName:object:queue:block:", name, pObj, pQueue, block) +@(objc_type=NotificationCenter, objc_name="addObserverForName") +NotificationCenter_addObserverForName :: proc{NotificationCenter_addObserverForName_old, NotificationCenter_addObserverForName_new} + +NotificationCenter_addObserverForName_old :: proc "c" (self: ^NotificationCenter, name: NotificationName, pObj: ^Object, pQueue: rawptr, block: ^Block) -> ^Object { + return msgSend(^Object, self, "addObserverForName:object:queue:usingBlock:", name, pObj, pQueue, block) } + +NotificationCenter_addObserverForName_new :: proc "c" (self: ^NotificationCenter, name: NotificationName, pObj: ^Object, pQueue: rawptr, block: ^Objc_Block) -> ^Object { + return msgSend(^Object, self, "addObserverForName:object:queue:usingBlock:", name, pObj, pQueue, block) +} + +@(objc_type=NotificationCenter, objc_name="addObserver") +NotificationCenter_addObserver :: proc "c" (self: ^NotificationCenter, observer: ^Object, selector: SEL, name: NotificationName, object: ^Object) { + msgSend(nil, self, "addObserver:selector:name:object:", observer, selector, name, object) +} + @(objc_type=NotificationCenter, objc_name="removeObserver") NotificationCenter_removeObserver :: proc "c" (self: ^NotificationCenter, pObserver: ^Object) { msgSend(nil, self, "removeObserver:", pObserver) diff --git a/core/sys/darwin/Foundation/NSObject.odin b/core/sys/darwin/Foundation/NSObject.odin index 31ece47a1..7a423e757 100644 --- a/core/sys/darwin/Foundation/NSObject.odin +++ b/core/sys/darwin/Foundation/NSObject.odin @@ -81,6 +81,12 @@ debugDescription :: proc "c" (self: ^Object) -> ^String { return nil } + +@(objc_type=Object, objc_name="performSelectorOnMainThread") +performSelectorOnMainThread :: proc "c" (self: ^Object, aSelector: SEL, arg: id, wait: BOOL) { + msgSend(^String, self, "performSelectorOnMainThread:withObject:waitUntilDone:", aSelector, arg, wait) +} + bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) { return (T)(obj) } @@ -88,4 +94,4 @@ bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_poi @(objc_class="NSCoder") Coder :: struct {using _: Object} -// TODO(bill): Implement all the methods for this massive type \ No newline at end of file +// TODO(bill): Implement all the methods for this massive type diff --git a/core/sys/darwin/Foundation/NSRunLoop.odin b/core/sys/darwin/Foundation/NSRunLoop.odin new file mode 100644 index 000000000..a9c47bd0e --- /dev/null +++ b/core/sys/darwin/Foundation/NSRunLoop.odin @@ -0,0 +1,27 @@ +package objc_Foundation + +foreign import "system:Foundation.framework" + +RunLoopMode :: ^String + +@(link_prefix="NS") +foreign Foundation { + RunLoopCommonModes: RunLoopMode + DefaultRunLoopMode: RunLoopMode + EventTrackingRunLoopMode: RunLoopMode + ModalPanelRunLoopMode: RunLoopMode +} + +@(objc_class="NSRunLoop") +RunLoop :: struct { using _: Object } + +@(objc_type=RunLoop, objc_name="mainRunLoop", objc_is_class_method=true) +RunLoop_mainRunLoop :: proc() -> ^RunLoop { + return msgSend(^RunLoop, RunLoop, "mainRunLoop") +} + +@(objc_type=RunLoop, objc_name="addTimerForMode") +RunLoop_addTimerForMode :: proc(self: ^RunLoop, timer: ^Timer, forMode: RunLoopMode) { + msgSend(nil, self, "addTimer:forMode:", timer, forMode) +} + diff --git a/core/sys/darwin/Foundation/NSScreen.odin b/core/sys/darwin/Foundation/NSScreen.odin index 79ab00fbe..8d52b9e1c 100644 --- a/core/sys/darwin/Foundation/NSScreen.odin +++ b/core/sys/darwin/Foundation/NSScreen.odin @@ -3,18 +3,22 @@ package objc_Foundation @(objc_class="NSScreen") Screen :: struct {using _: Object} -@(objc_type=Screen, objc_name="mainScreen") +@(objc_type=Screen, objc_name="mainScreen", objc_is_class_method=true) Screen_mainScreen :: proc "c" () -> ^Screen { return msgSend(^Screen, Screen, "mainScreen") } -@(objc_type=Screen, objc_name="deepestScreen") +@(objc_type=Screen, objc_name="deepestScreen", objc_is_class_method=true) Screen_deepestScreen :: proc "c" () -> ^Screen { return msgSend(^Screen, Screen, "deepestScreen") } -@(objc_type=Screen, objc_name="screens") +@(objc_type=Screen, objc_name="screens", objc_is_class_method=true) Screen_screens :: proc "c" () -> ^Array { return msgSend(^Array, Screen, "screens") } +@(objc_type=Screen, objc_name="screensHaveSeparateSpaces", objc_is_class_method=true) +Screen_screensHaveSeparateSpaces :: proc "c" () -> BOOL { + return msgSend(BOOL, Screen, "screensHaveSeparateSpaces") +} @(objc_type=Screen, objc_name="frame") Screen_frame :: proc "c" (self: ^Screen) -> Rect { return msgSend(Rect, self, "frame") diff --git a/core/sys/darwin/Foundation/NSString.odin b/core/sys/darwin/Foundation/NSString.odin index eac855c3b..87e110da1 100644 --- a/core/sys/darwin/Foundation/NSString.odin +++ b/core/sys/darwin/Foundation/NSString.odin @@ -81,7 +81,7 @@ String_initWithString :: proc "c" (self: ^String, other: ^String) -> ^String { @(objc_type=String, objc_name="initWithCString") String_initWithCString :: proc "c" (self: ^String, pString: cstring, encoding: StringEncoding) -> ^String { - return msgSend(^String, self, "initWithCstring:encoding:", pString, encoding) + return msgSend(^String, self, "initWithCString:encoding:", pString, encoding) } @(objc_type=String, objc_name="initWithBytesNoCopy") diff --git a/core/sys/darwin/Foundation/NSTimer.odin b/core/sys/darwin/Foundation/NSTimer.odin new file mode 100644 index 000000000..7e10078ca --- /dev/null +++ b/core/sys/darwin/Foundation/NSTimer.odin @@ -0,0 +1,14 @@ +package objc_Foundation + +@(objc_class="NSTimer") +Timer :: struct { using _: Object } + +@(objc_type=Timer, objc_name="scheduledTimerWithTimeIntervalRepeatsBlock", objc_is_class_method=true) +Timer_scheduledTimerWithTimeIntervalRepeatsBlock :: proc(interval: TimeInterval, repeats: BOOL, block: ^Block) -> ^Timer { + return msgSend(^Timer, Timer, "scheduledTimerWithTimeInterval:repeats:block:", repeats, block) +} + +@(objc_type=Timer, objc_name="scheduledTimerWithTimeIntervalTargetSelectorUserInfoRepeat", objc_is_class_method=true) +Timer_scheduledTimerWithTimeIntervalTargetSelectorUserInfoRepeat :: proc(interval: TimeInterval, aTarget: id, aSelector: SEL, userInfo: id, repeats: BOOL) -> ^Timer { + return msgSend(^Timer, Timer, "scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:", interval, aTarget, aSelector, userInfo, repeats) +} diff --git a/core/sys/darwin/Foundation/NSTypes.odin b/core/sys/darwin/Foundation/NSTypes.odin index 822a07ab1..7c379cf99 100644 --- a/core/sys/darwin/Foundation/NSTypes.odin +++ b/core/sys/darwin/Foundation/NSTypes.odin @@ -1,6 +1,7 @@ package objc_Foundation import "base:intrinsics" +import CF "core:sys/darwin/CoreFoundation" @(private) msgSend :: intrinsics.objc_send @@ -34,17 +35,11 @@ ComparisonResult :: enum Integer { NotFound :: IntegerMax -Float :: distinct (f32 when size_of(uint) == 4 else f64) +Float :: CF.CGFloat -Point :: struct { - x: Float, - y: Float, -} +Point :: CF.CGPoint -Size :: struct { - width: Float, - height: Float, -} +Size :: CF.CGSize when size_of(UInteger) == 8 { _UINTEGER_ENCODING :: "Q" diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin index 57ac2b6f6..fcf35546e 100644 --- a/core/sys/darwin/Foundation/NSWindow.odin +++ b/core/sys/darwin/Foundation/NSWindow.odin @@ -1,12 +1,28 @@ package objc_Foundation import "core:strings" +import CF "core:sys/darwin/CoreFoundation" import "base:runtime" import "base:intrinsics" -Rect :: struct { - using origin: Point, - using size: Size, +Rect :: CF.CGRect +MaxX :: proc(aRect: Rect) -> Float { + return aRect.origin.x + aRect.size.width +} +MaxY :: proc(aRect: Rect) -> Float { + return aRect.origin.y + aRect.size.height +} +MidX :: proc(aRect: Rect) -> Float { + return aRect.origin.x + aRect.size.width*0.5 +} +MidY :: proc(aRect: Rect) -> Float { + return aRect.origin.y + aRect.size.height*0.5 +} +MinX :: proc(aRect: Rect) -> Float { + return aRect.origin.x +} +MinY :: proc(aRect: Rect) -> Float { + return aRect.origin.y } Depth :: enum UInteger { @@ -56,6 +72,60 @@ BackingStoreType :: enum UInteger { Buffered = 2, } +WindowCollectionBehaviorFlag :: enum UInteger { + CanJoinAllSpaces = 0, + MoveToActiveSpace = 1, + Managed = 2, + Transient = 3, + Stationary = 4, + ParticipatesInCycle = 5, + IgnoresCycle = 6, + FullScreenPrimary = 7, + FullScreenAuxiliary = 8, + FullScreenNone = 9, + FullScreenAllowsTiling = 11, + FullScreenDisallowsTiling = 12, + Primary = 16, + Auxiliary = 17, + CanJoinAllApplications = 18, +} +WindowCollectionBehavior :: distinct bit_set[WindowCollectionBehaviorFlag; UInteger] +WindowCollectionBehaviorDefault :: WindowCollectionBehavior{} +WindowCollectionBehaviorPrimary :: WindowCollectionBehavior{.Primary, .FullScreenAuxiliary} +WindowCollectionBehaviorAuxiliary :: WindowCollectionBehavior{.Auxiliary, .FullScreenNone} +WindowCollectionBehaviorCanJoinAllApplications :: WindowCollectionBehavior{.CanJoinAllApplications} +WindowCollectionBehaviorCanJoinAllSpaces :: WindowCollectionBehavior{.CanJoinAllSpaces} +WindowCollectionBehaviorMoveToActiveSpace :: WindowCollectionBehavior{.MoveToActiveSpace} +WindowCollectionBehaviorStationary :: WindowCollectionBehavior{.Stationary} +WindowCollectionBehaviorManaged :: WindowCollectionBehavior{.Managed} +WindowCollectionBehaviorTransient :: WindowCollectionBehavior{.Transient} +WindowCollectionBehaviorFullScreenPrimary :: WindowCollectionBehavior{.FullScreenPrimary} +WindowCollectionBehaviorFullScreenAuxiliary :: WindowCollectionBehavior{.FullScreenAuxiliary} +WindowCollectionBehaviorFullScreenNone :: WindowCollectionBehavior{.FullScreenNone} +WindowCollectionBehaviorFullScreenAllowsTiling :: WindowCollectionBehavior{.FullScreenAllowsTiling} +WindowCollectionBehaviorFullScreenDisallowsTiling :: WindowCollectionBehavior{.FullScreenDisallowsTiling} +WindowCollectionBehaviorParticipatesInCycle :: WindowCollectionBehavior{.ParticipatesInCycle} +WindowCollectionBehaviorIgnoresCycle :: WindowCollectionBehavior{.IgnoresCycle} + +WindowLevel :: enum Integer { + Normal = 0, + Floating = 3, + Submenu = 3, + TornOffMenu = 3, + ModalPanel = 8, + MainMenu = 24, + Status = 25, + PopUpMenu = 101, + ScreenSaver = 1000, +} + +WindowTabbingMode :: enum Integer { + Automatic = 0, + Preferred = 1, + Disallowed = 2, +} + + WindowDelegateTemplate :: struct { // Managing Sheets windowWillPositionSheetUsingRect: proc(window: ^Window, sheet: ^Window, rect: Rect) -> Rect, @@ -146,7 +216,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla return nil } if template.windowWillPositionSheetUsingRect != nil { - windowWillPositionSheetUsingRect :: proc "c" (self: id, window: ^Window, sheet: ^Window, rect: Rect) -> Rect { + windowWillPositionSheetUsingRect :: proc "c" (self: id, cmd: SEL, window: ^Window, sheet: ^Window, rect: Rect) -> Rect { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillPositionSheetUsingRect(window, sheet, rect) @@ -154,7 +224,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willPositionSheet:usingRect:"), auto_cast windowWillPositionSheetUsingRect, _RECT_ENCODING+"@:@@"+_RECT_ENCODING) } if template.windowWillBeginSheet != nil { - windowWillBeginSheet :: proc "c" (self: id, notification: ^Notification) { + windowWillBeginSheet :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillBeginSheet(notification) @@ -162,7 +232,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillBeginSheet:"), auto_cast windowWillBeginSheet, "v@:@") } if template.windowDidEndSheet != nil { - windowDidEndSheet :: proc "c" (self: id, notification: ^Notification) { + windowDidEndSheet :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEndSheet(notification) @@ -170,7 +240,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEndSheet:"), auto_cast windowDidEndSheet, "v@:@") } if template.windowWillResizeToSize != nil { - windowWillResizeToSize :: proc "c" (self: id, sender: ^Window, frameSize: Size) -> Size { + windowWillResizeToSize :: proc "c" (self: id, cmd: SEL, sender: ^Window, frameSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillResizeToSize(sender, frameSize) @@ -178,7 +248,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillResize:toSize:"), auto_cast windowWillResizeToSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING) } if template.windowDidResize != nil { - windowDidResize :: proc "c" (self: id, notification: ^Notification) { + windowDidResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResize(notification) @@ -186,7 +256,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResize:"), auto_cast windowDidResize, "v@:@") } if template.windowWillStartLiveResize != nil { - windowWillStartLiveResize :: proc "c" (self: id, notification: ^Notification) { + windowWillStartLiveResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillStartLiveResize(notification) @@ -194,7 +264,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillStartLiveResize:"), auto_cast windowWillStartLiveResize, "v@:@") } if template.windowDidEndLiveResize != nil { - windowDidEndLiveResize :: proc "c" (self: id, notification: ^Notification) { + windowDidEndLiveResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEndLiveResize(notification) @@ -202,7 +272,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEndLiveResize:"), auto_cast windowDidEndLiveResize, "v@:@") } if template.windowWillMiniaturize != nil { - windowWillMiniaturize :: proc "c" (self: id, notification: ^Notification) { + windowWillMiniaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillMiniaturize(notification) @@ -210,7 +280,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillMiniaturize:"), auto_cast windowWillMiniaturize, "v@:@") } if template.windowDidMiniaturize != nil { - windowDidMiniaturize :: proc "c" (self: id, notification: ^Notification) { + windowDidMiniaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidMiniaturize(notification) @@ -218,7 +288,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidMiniaturize:"), auto_cast windowDidMiniaturize, "v@:@") } if template.windowDidDeminiaturize != nil { - windowDidDeminiaturize :: proc "c" (self: id, notification: ^Notification) { + windowDidDeminiaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidDeminiaturize(notification) @@ -226,7 +296,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidDeminiaturize:"), auto_cast windowDidDeminiaturize, "v@:@") } if template.windowWillUseStandardFrameDefaultFrame != nil { - windowWillUseStandardFrameDefaultFrame :: proc(self: id, window: ^Window, newFrame: Rect) -> Rect { + windowWillUseStandardFrameDefaultFrame :: proc(self: id, cmd: SEL, window: ^Window, newFrame: Rect) -> Rect { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseStandardFrameDefaultFrame(window, newFrame) @@ -234,7 +304,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillUseStandardFrame:defaultFrame:"), auto_cast windowWillUseStandardFrameDefaultFrame, _RECT_ENCODING+"@:@"+_RECT_ENCODING) } if template.windowShouldZoomToFrame != nil { - windowShouldZoomToFrame :: proc "c" (self: id, window: ^Window, newFrame: Rect) -> BOOL { + windowShouldZoomToFrame :: proc "c" (self: id, cmd: SEL, window: ^Window, newFrame: Rect) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldZoomToFrame(window, newFrame) @@ -242,7 +312,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowShouldZoom:toFrame:"), auto_cast windowShouldZoomToFrame, "B@:@"+_RECT_ENCODING) } if template.windowWillUseFullScreenContentSize != nil { - windowWillUseFullScreenContentSize :: proc "c" (self: id, window: ^Window, proposedSize: Size) -> Size { + windowWillUseFullScreenContentSize :: proc "c" (self: id, cmd: SEL, window: ^Window, proposedSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseFullScreenContentSize(window, proposedSize) @@ -250,7 +320,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenContentSize:"), auto_cast windowWillUseFullScreenContentSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING) } if template.windowWillUseFullScreenPresentationOptions != nil { - windowWillUseFullScreenPresentationOptions :: proc(self: id, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions { + windowWillUseFullScreenPresentationOptions :: proc(self: id, cmd: SEL, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseFullScreenPresentationOptions(window, proposedOptions) @@ -258,7 +328,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenPresentationOptions:"), auto_cast windowWillUseFullScreenPresentationOptions, _UINTEGER_ENCODING+"@:@"+_UINTEGER_ENCODING) } if template.windowWillEnterFullScreen != nil { - windowWillEnterFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowWillEnterFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEnterFullScreen(notification) @@ -266,7 +336,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterFullScreen:"), auto_cast windowWillEnterFullScreen, "v@:@") } if template.windowDidEnterFullScreen != nil { - windowDidEnterFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidEnterFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEnterFullScreen(notification) @@ -274,7 +344,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterFullScreen:"), auto_cast windowDidEnterFullScreen, "v@:@") } if template.windowWillExitFullScreen != nil { - windowWillExitFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowWillExitFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillExitFullScreen(notification) @@ -282,7 +352,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillExitFullScreen:"), auto_cast windowWillExitFullScreen, "v@:@") } if template.windowDidExitFullScreen != nil { - windowDidExitFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidExitFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExitFullScreen(notification) @@ -290,7 +360,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidExitFullScreen:"), auto_cast windowDidExitFullScreen, "v@:@") } if template.customWindowsToEnterFullScreenForWindow != nil { - customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array { + customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToEnterFullScreenForWindow(window) @@ -298,7 +368,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:"), auto_cast customWindowsToEnterFullScreenForWindow, "@@:@") } if template.customWindowsToEnterFullScreenForWindowOnScreen != nil { - customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, window: ^Window, screen: ^Screen) -> ^Array { + customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, cmd: SEL, window: ^Window, screen: ^Screen) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToEnterFullScreenForWindowOnScreen(window, screen) @@ -306,7 +376,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:onScreen:"), auto_cast customWindowsToEnterFullScreenForWindowOnScreen, "@@:@@") } if template.windowStartCustomAnimationToEnterFullScreenWithDuration != nil { - windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) { + windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, cmd: SEL, window: ^Window, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToEnterFullScreenWithDuration(window, duration) @@ -314,7 +384,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenWithDuration, "v@:@@") } if template.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration != nil { - windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, window: ^Window, screen: ^Screen, duration: TimeInterval) { + windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, cmd: SEL, window: ^Window, screen: ^Screen, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration(window, screen, duration) @@ -322,7 +392,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenOnScreen:withDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration, "v@:@@d") } if template.windowDidFailToEnterFullScreen != nil { - windowDidFailToEnterFullScreen :: proc "c" (self: id, window: ^Window) { + windowDidFailToEnterFullScreen :: proc "c" (self: id, cmd: SEL, window: ^Window) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidFailToEnterFullScreen(window) @@ -330,7 +400,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToEnterFullScreen:"), auto_cast windowDidFailToEnterFullScreen, "v@:@") } if template.customWindowsToExitFullScreenForWindow != nil { - customWindowsToExitFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array { + customWindowsToExitFullScreenForWindow :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToExitFullScreenForWindow(window) @@ -338,7 +408,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToExitFullScreenForWindow:"), auto_cast customWindowsToExitFullScreenForWindow, "@@:@") } if template.windowStartCustomAnimationToExitFullScreenWithDuration != nil { - windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) { + windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, cmd: SEL, window: ^Window, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToExitFullScreenWithDuration(window, duration) @@ -346,7 +416,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToExitFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToExitFullScreenWithDuration, "v@:@d") } if template.windowDidFailToExitFullScreen != nil { - windowDidFailToExitFullScreen :: proc "c" (self: id, window: ^Window) { + windowDidFailToExitFullScreen :: proc "c" (self: id, cmd: SEL, window: ^Window) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidFailToExitFullScreen(window) @@ -354,7 +424,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToExitFullScreen:"), auto_cast windowDidFailToExitFullScreen, "v@:@") } if template.windowWillMove != nil { - windowWillMove :: proc "c" (self: id, notification: ^Notification) { + windowWillMove :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillMove(notification) @@ -362,7 +432,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillMove:"), auto_cast windowWillMove, "v@:@") } if template.windowDidMove != nil { - windowDidMove :: proc "c" (self: id, notification: ^Notification) { + windowDidMove :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidMove(notification) @@ -370,7 +440,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidMove:"), auto_cast windowDidMove, "v@:@") } if template.windowDidChangeScreen != nil { - windowDidChangeScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeScreen(notification) @@ -378,7 +448,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreen:"), auto_cast windowDidChangeScreen, "v@:@") } if template.windowDidChangeScreenProfile != nil { - windowDidChangeScreenProfile :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeScreenProfile :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeScreenProfile(notification) @@ -386,7 +456,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreenProfile:"), auto_cast windowDidChangeScreenProfile, "v@:@") } if template.windowDidChangeBackingProperties != nil { - windowDidChangeBackingProperties :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeBackingProperties :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeBackingProperties(notification) @@ -394,7 +464,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeBackingProperties:"), auto_cast windowDidChangeBackingProperties, "v@:@") } if template.windowShouldClose != nil { - windowShouldClose :: proc "c" (self:id, sender: ^Window) -> BOOL { + windowShouldClose :: proc "c" (self:id, cmd: SEL, sender: ^Window) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldClose(sender) @@ -402,7 +472,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowShouldClose:"), auto_cast windowShouldClose, "B@:@") } if template.windowWillClose != nil { - windowWillClose :: proc "c" (self:id, notification: ^Notification) { + windowWillClose :: proc "c" (self:id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillClose(notification) @@ -410,7 +480,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillClose:"), auto_cast windowWillClose, "v@:@") } if template.windowDidBecomeKey != nil { - windowDidBecomeKey :: proc "c" (self: id, notification: ^Notification) { + windowDidBecomeKey :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidBecomeKey(notification) @@ -418,7 +488,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeKey:"), auto_cast windowDidBecomeKey, "v@:@") } if template.windowDidResignKey != nil { - windowDidResignKey :: proc "c" (self: id, notification: ^Notification) { + windowDidResignKey :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResignKey(notification) @@ -426,7 +496,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResignKey:"), auto_cast windowDidResignKey, "v@:@") } if template.windowDidBecomeMain != nil { - windowDidBecomeMain :: proc "c" (self: id, notification: ^Notification) { + windowDidBecomeMain :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidBecomeMain(notification) @@ -434,7 +504,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeMain:"), auto_cast windowDidBecomeMain, "v@:@") } if template.windowDidResignMain != nil { - windowDidResignMain :: proc "c" (self: id, notification: ^Notification) { + windowDidResignMain :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResignMain(notification) @@ -442,7 +512,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResignMain:"), auto_cast windowDidResignMain, "v@:@") } if template.windowWillReturnFieldEditorToObject != nil { - windowWillReturnFieldEditorToObject :: proc "c" (self:id, sender: ^Window, client: id) -> id { + windowWillReturnFieldEditorToObject :: proc "c" (self:id, cmd: SEL, sender: ^Window, client: id) -> id { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillReturnFieldEditorToObject(sender, client) @@ -450,7 +520,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnFieldEditor:toObject:"), auto_cast windowWillReturnFieldEditorToObject, "@@:@@") } if template.windowDidUpdate != nil { - windowDidUpdate :: proc "c" (self: id, notification: ^Notification) { + windowDidUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidUpdate(notification) @@ -458,7 +528,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidUpdate:"), auto_cast windowDidUpdate, "v@:@") } if template.windowDidExpose != nil { - windowDidExpose :: proc "c" (self: id, notification: ^Notification) { + windowDidExpose :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExpose(notification) @@ -466,7 +536,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidExpose:"), auto_cast windowDidExpose, "v@:@") } if template.windowDidChangeOcclusionState != nil { - windowDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeOcclusionState :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeOcclusionState(notification) @@ -474,7 +544,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeOcclusionState:"), auto_cast windowDidChangeOcclusionState, "v@:@") } if template.windowShouldDragDocumentWithEventFromWithPasteboard != nil { - windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL { + windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, cmd: SEL, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldDragDocumentWithEventFromWithPasteboard(window, event, dragImageLocation, pasteboard) @@ -482,7 +552,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:shouldDragDocumentWithEvent:from:withPasteboard:"), auto_cast windowShouldDragDocumentWithEventFromWithPasteboard, "B@:@@"+_POINT_ENCODING+"@") } if template.windowWillReturnUndoManager != nil { - windowWillReturnUndoManager :: proc "c" (self: id, window: ^Window) -> ^UndoManager { + windowWillReturnUndoManager :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^UndoManager { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillReturnUndoManager(window) @@ -490,7 +560,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnUndoManager:"), auto_cast windowWillReturnUndoManager, "@@:@") } if template.windowShouldPopUpDocumentPathMenu != nil { - windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, window: ^Window, menu: ^Menu) -> BOOL { + windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, cmd: SEL, window: ^Window, menu: ^Menu) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldPopUpDocumentPathMenu(window, menu) @@ -498,7 +568,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:shouldPopUpDocumentPathMenu:"), auto_cast windowShouldPopUpDocumentPathMenu, "B@:@@") } if template.windowWillEncodeRestorableState != nil { - windowWillEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) { + windowWillEncodeRestorableState :: proc "c" (self: id, cmd: SEL, window: ^Window, state: ^Coder) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEncodeRestorableState(window, state) @@ -506,7 +576,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willEncodeRestorableState:"), auto_cast windowWillEncodeRestorableState, "v@:@@") } if template.windowDidEncodeRestorableState != nil { - windowDidEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) { + windowDidEncodeRestorableState :: proc "c" (self: id, cmd: SEL, window: ^Window, state: ^Coder) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEncodeRestorableState(window, state) @@ -514,7 +584,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:didDecodeRestorableState:"), auto_cast windowDidEncodeRestorableState, "v@:@@") } if template.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize != nil { - windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size { + windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, cmd: SEL, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize(window, maxPreferredFrameSize, maxPreferredFrameSize) @@ -522,7 +592,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willResizeForVersionBrowserWithMaxPreferredSize:maxAllowedSize:"), auto_cast windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING+_SIZE_ENCODING) } if template.windowWillEnterVersionBrowser != nil { - windowWillEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowWillEnterVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEnterVersionBrowser(notification) @@ -530,7 +600,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterVersionBrowser:"), auto_cast windowWillEnterVersionBrowser, "v@:@") } if template.windowDidEnterVersionBrowser != nil { - windowDidEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowDidEnterVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEnterVersionBrowser(notification) @@ -538,7 +608,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterVersionBrowser:"), auto_cast windowDidEnterVersionBrowser, "v@:@") } if template.windowWillExitVersionBrowser != nil { - windowWillExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowWillExitVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillExitVersionBrowser(notification) @@ -546,7 +616,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillExitVersionBrowser:"), auto_cast windowWillExitVersionBrowser, "v@:@") } if template.windowDidExitVersionBrowser != nil { - windowDidExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowDidExitVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExitVersionBrowser(notification) @@ -568,6 +638,15 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla @(objc_class="CALayer") Layer :: struct { using _: Object } + +@(objc_type=Layer, objc_name="contents") +Layer_contents :: proc "c" (self: ^Layer) -> rawptr { + return msgSend(rawptr, self, "contents") +} +@(objc_type=Layer, objc_name="setContents") +Layer_setContents :: proc "c" (self: ^Layer, contents: rawptr) { + msgSend(nil, self, "setContents:", contents) +} @(objc_type=Layer, objc_name="contentsScale") Layer_contentsScale :: proc "c" (self: ^Layer) -> Float { return msgSend(Float, self, "contentsScale") @@ -580,6 +659,14 @@ Layer_setContentsScale :: proc "c" (self: ^Layer, scale: Float) { Layer_frame :: proc "c" (self: ^Layer) -> Rect { return msgSend(Rect, self, "frame") } +@(objc_type=Layer, objc_name="position") +Layer_position :: proc "c" (self: ^Layer) -> Point { + return msgSend(Point, self, "position") +} +@(objc_type=Layer, objc_name="setPosition") +Layer_setPosition :: proc "c" (self: ^Layer, position: Point) { + msgSend(nil, self, "setPosition:", position) +} @(objc_type=Layer, objc_name="addSublayer") Layer_addSublayer :: proc "c" (self: ^Layer, layer: ^Layer) { msgSend(nil, self, "addSublayer:", layer) @@ -591,6 +678,10 @@ Responder :: struct {using _: Object} @(objc_class="NSView") View :: struct {using _: Responder} +@(objc_type=View, objc_name="alloc", objc_is_class_method=true) +View_alloc :: proc "c" () -> ^View { + return msgSend(^View, View, "alloc") +} @(objc_type=View, objc_name="initWithFrame") View_initWithFrame :: proc "c" (self: ^View, frame: Rect) -> ^View { @@ -624,6 +715,14 @@ View_convertPointFromView :: proc "c" (self: ^View, point: Point, view: ^View) - View_addSubview :: proc "c" (self: ^View, view: ^View) { msgSend(nil, self, "addSubview:", view) } +@(objc_type=View, objc_name="isFlipped") +View_isFlipped :: proc "c" (self: ^View) -> BOOL { + return msgSend(BOOL, self, "isFlipped") +} +@(objc_type=View, objc_name="setIsFlipped") +View_setIsFlipped :: proc "c" (self: ^View, flipped: BOOL) { + msgSend(nil, self, "setIsFlipped:", flipped) +} @(objc_class="NSWindow") Window :: struct {using _: Responder} @@ -654,8 +753,16 @@ Window_frame :: proc "c" (self: ^Window) -> Rect { return msgSend(Rect, self, "frame") } @(objc_type=Window, objc_name="setFrame") -Window_setFrame :: proc "c" (self: ^Window, frame: Rect) { - msgSend(nil, self, "setFrame:", frame) +Window_setFrame :: proc "c" (self: ^Window, frame: Rect, display: BOOL) { + msgSend(nil, self, "setFrame:display:", frame, display) +} +@(objc_type=Window, objc_name="setFrameOrigin") +Window_setFrameOrigin :: proc "c" (self: ^Window, origin: Point) { + msgSend(nil, self, "setFrameOrigin:", origin) +} +@(objc_type=Window, objc_name="center") +Window_center :: proc "c" (self: ^Window) { + msgSend(nil, self, "center") } @(objc_type=Window, objc_name="opaque") Window_opaque :: proc "c" (self: ^Window) -> BOOL { @@ -673,6 +780,14 @@ Window_backgroundColor :: proc "c" (self: ^Window) -> ^Color { Window_setBackgroundColor :: proc "c" (self: ^Window, color: ^Color) { msgSend(nil, self, "setBackgroundColor:", color) } +@(objc_type = Window, objc_name = "orderFront") +Window_orderFront :: proc "c" (self: ^Window, sender: id) { + msgSend(nil, self, "orderFront:", sender) +} +@(objc_type = Window, objc_name = "orderOut") +Window_orderOut :: proc "c" (self: ^Window, sender: id) { + msgSend(nil, self, "orderOut:", sender) +} @(objc_type=Window, objc_name="makeKeyAndOrderFront") Window_makeKeyAndOrderFront :: proc "c" (self: ^Window, key: ^Object) { msgSend(nil, self, "makeKeyAndOrderFront:", key) @@ -693,10 +808,18 @@ Window_setMovable :: proc "c" (self: ^Window, ok: BOOL) { Window_setMovableByWindowBackground :: proc "c" (self: ^Window, ok: BOOL) { msgSend(nil, self, "setMovableByWindowBackground:", ok) } +@(objc_type=Window, objc_name="setAcceptsMouseMovedEvents") +Window_setAcceptsMouseMovedEvents :: proc "c" (self: ^Window, ok: BOOL) { + msgSend(nil, self, "setAcceptsMouseMovedEvents:", ok) +} @(objc_type=Window, objc_name="setStyleMask") Window_setStyleMask :: proc "c" (self: ^Window, style_mask: WindowStyleMask) { msgSend(nil, self, "setStyleMask:", style_mask) } +@(objc_type=Window, objc_name="performClose") +Window_performClose :: proc "c" (self: ^Window, sender: id) { + msgSend(nil, self, "performClose:", sender) +} @(objc_type=Window, objc_name="close") Window_close :: proc "c" (self: ^Window) { msgSend(nil, self, "close") @@ -705,10 +828,46 @@ Window_close :: proc "c" (self: ^Window) { Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) { msgSend(nil, self, "setDelegate:", delegate) } +@(objc_type = Window, objc_name = "delegate") +Window_delegate :: proc "c" (self: ^Window) -> ^WindowDelegate { + return msgSend(^WindowDelegate, self, "delegate") +} @(objc_type=Window, objc_name="backingScaleFactor") Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float { return msgSend(Float, self, "backingScaleFactor") } +@(objc_type = Window, objc_name = "convertRectFromBacking") +Window_convertRectFromBacking :: proc "c" (self: ^Window, rect: Rect) -> Rect { + return msgSend(Rect, self, "convertRectFromBacking:", rect) +} +@(objc_type = Window, objc_name = "convertRectFromScreen") +Window_convertRectFromScreen :: proc "c" (self: ^Window, rect: Rect) -> Rect { + return msgSend(Rect, self, "convertRectFromScreen:", rect) +} +@(objc_type = Window, objc_name = "convertPointFromBacking") +Window_convertPointFromBacking :: proc "c" (self: ^Window, point: Point) -> Point { + return msgSend(Point, self, "convertPointFromBacking:", point) +} +@(objc_type = Window, objc_name = "convertPointFromScreen") +Window_convertPointFromScreen :: proc "c" (self: ^Window, point: Point) -> Point { + return msgSend(Point, self, "convertPointFromScreen:", point) +} +@(objc_type = Window, objc_name = "convertRectToBacking") +Window_convertRectToBacking :: proc "c" (self: ^Window, rect: Rect) -> Rect { + return msgSend(Rect, self, "convertRectToBacking:", rect) +} +@(objc_type = Window, objc_name = "convertRectToScreen") +Window_convertRectToScreen :: proc "c" (self: ^Window, rect: Rect) -> Rect { + return msgSend(Rect, self, "convertRectToScreen:", rect) +} +@(objc_type = Window, objc_name = "convertPointToBacking") +Window_convertPointToBacking :: proc "c" (self: ^Window, point: Point) -> Point { + return msgSend(Point, self, "convertPointToBacking:", point) +} +@(objc_type = Window, objc_name = "convertPointToScreen") +Window_convertPointToScreen :: proc "c" (self: ^Window, point: Point) -> Point { + return msgSend(Point, self, "convertPointToScreen:", point) +} @(objc_type=Window, objc_name="setWantsLayer") Window_setWantsLayer :: proc "c" (self: ^Window, ok: BOOL) { msgSend(nil, self, "setWantsLayer:", ok) @@ -780,4 +939,72 @@ Window_performWindowDragWithEvent :: proc "c" (self: ^Window, event: ^Event) { @(objc_type=Window, objc_name="setToolbar") Window_setToolbar :: proc "c" (self: ^Window, toolbar: ^Toolbar) { msgSend(nil, self, "setToolbar:", toolbar) -} \ No newline at end of file +} +@(objc_type = Window, objc_name = "setCollectionBehavior") +Window_setCollectionBehavior :: proc "c" (self: ^Window, behavior: WindowCollectionBehavior) { + msgSend(nil, self, "setCollectionBehavior:", behavior) +} +@(objc_type = Window, objc_name = "collectionBehavior") +Window_collectionBehavior :: proc "c" (self: ^Window) -> WindowCollectionBehavior { + return msgSend(WindowCollectionBehavior, self, "collectionBehavior") +} +@(objc_type = Window, objc_name = "setLevel") +Window_setLevel :: proc "c" (self: ^Window, level: WindowLevel) { + msgSend(nil, self, "setLevel:", level) +} +@(objc_type = Window, objc_name = "keyWindow") +Window_keyWindow :: proc "c" (self: ^Window) -> BOOL { + return msgSend(BOOL, self, "isKeyWindow") +} +@(objc_type = Window, objc_name = "mainWindow") +Window_mainWindow :: proc "c" (self: ^Window) -> BOOL { + return msgSend(BOOL, self, "isMainWindow") +} +@(objc_type = Window, objc_name = "parentWindow") +Window_parentWindow :: proc "c" (self: ^Window) -> ^Window { + return msgSend(^Window, self, "parentWindow") +} +@(objc_type = Window, objc_name = "setReleasedWhenClosed") +Window_setReleasedWhenClosed :: proc "c" (self: ^Window, flag: BOOL) { + msgSend(nil, self, "setReleasedWhenClosed:", flag) +} +@(objc_type = Window, objc_name = "makeFirstResponder") +Window_makeFirstResponder :: proc "c" (self: ^Window, responder: ^Responder) -> BOOL { + return msgSend(BOOL, self, "makeFirstResponder:", responder) +} +@(objc_type = Window, objc_name = "setRestorable") +Window_setRestorable :: proc "c" (self: ^Window, flag: BOOL) { + msgSend(nil, self, "setRestorable:", flag) +} +@(objc_type = Window, objc_name = "setTabbingMode") +Window_setTabbingMode :: proc "c" (self: ^Window, mode: WindowTabbingMode) { + msgSend(nil, self, "setTabbingMode:", mode) +} +@(objc_type = Window, objc_name = "toggleFullScreen") +Window_toggleFullScreen :: proc "c" (self: ^Window, sender: id) { + msgSend(nil, self, "toggleFullScreen:", sender) +} +@(objc_type = Window, objc_name = "contentRectForFrameRect", objc_is_class_method=true) +Window_contentRectForFrameRectType :: proc "c" (frameRect: Rect, styleMask: WindowStyleMask) -> Rect { + return msgSend(Rect, Window, "contentRectForFrameRect:styleMask:", frameRect, styleMask) +} +@(objc_type = Window, objc_name = "frameRectForContentRect", objc_is_class_method=true) +Window_frameRectForContentRectType :: proc "c" (contentRect: Rect, styleMask: WindowStyleMask) -> Rect { + return msgSend(Rect, Window, "frameRectForContentRect:styleMask:", contentRect, styleMask) +} +@(objc_type = Window, objc_name = "minFrameWidthWithTitle", objc_is_class_method=true) +Window_minFrameWidthWithTitle :: proc "c" (title: ^String, styleMask: WindowStyleMask) -> Float { + return msgSend(Float, Window, "minFrameWidthWithTitle:styleMask:", title, styleMask) +} +@(objc_type = Window, objc_name = "contentRectForFrameRect") +Window_contentRectForFrameRectInstance :: proc "c" (self: ^Window, frameRect: Rect) -> Rect { + return msgSend(Rect, self, "contentRectForFrameRect:", frameRect) +} +@(objc_type = Window, objc_name = "frameRectForContentRect") +Window_frameRectForContentRectInstance :: proc "c" (self: ^Window, contentRect: Rect) -> Rect { + return msgSend(Rect, self, "frameRectForContentRect:", contentRect) +} +@(objc_type = Window, objc_name = "screen") +Window_screen :: proc "c" (self: ^Window) -> ^Screen { + return msgSend(^Screen, self, "screen") +} diff --git a/core/sys/darwin/Foundation/objc_helper.odin b/core/sys/darwin/Foundation/objc_helper.odin new file mode 100644 index 000000000..0748d700b --- /dev/null +++ b/core/sys/darwin/Foundation/objc_helper.odin @@ -0,0 +1,136 @@ +package objc_Foundation + +import "base:runtime" +import "base:intrinsics" + +Subclasser_Proc :: proc(cls: Class, vtable: rawptr) + +Object_VTable_Info :: struct { + vtable: rawptr, + size: uint, + impl: Subclasser_Proc, +} + +Class_VTable_Info :: struct { + _context: runtime.Context, + super_vtable: rawptr, + protocol_vtable: rawptr, +} + +@(require_results) +class_get_metaclass :: #force_inline proc "contextless" (cls: Class) -> Class { + return (^Class)(cls)^ +} + +@(require_results) +object_get_vtable_info :: proc "contextless" (obj: id) -> ^Class_VTable_Info { + return (^Class_VTable_Info)(object_getIndexedIvars(obj)) +} + +@(require_results) +make_subclasser :: #force_inline proc(vtable: ^$T, impl: proc(cls: Class, vt: ^T)) -> Object_VTable_Info { + return Object_VTable_Info{ + vtable = vtable, + size = size_of(T), + impl = (Subclasser_Proc)(impl), + } +} + +@(require_results) +register_subclass :: proc( + class_name: cstring, + superclass: Class, + superclass_overrides: Maybe(Object_VTable_Info) = nil, + protocol: Maybe(Object_VTable_Info) = nil, + _context: Maybe(runtime.Context) = nil, +) -> Class { + assert(superclass != nil) + + super_size: uint + proto_size: uint + + if superclass_overrides != nil { + // Align to 8-byte boundary + super_size = (superclass_overrides.?.size + 7)/8 * 8 + } + + if protocol != nil { + // Align to 8-byte boundary + proto_size = (protocol.?.size + 7)/8 * 8 + } + + cls := objc_lookUpClass(class_name) + if cls != nil { + return cls + } + + extra_size := uint(size_of(Class_VTable_Info)) + 8 + super_size + proto_size + + cls = objc_allocateClassPair(superclass, class_name, extra_size) + assert(cls != nil) + + if s, ok := superclass_overrides.?; ok { + s.impl(cls, s.vtable) + } + + if p, ok := protocol.?; ok { + p.impl(cls, p.vtable) + } + + objc_registerClassPair(cls) + meta_cls := class_get_metaclass(cls) + meta_size := uint(class_getInstanceSize(meta_cls)) + + // Offsets are always aligned to 8-byte boundary + info_offset := (meta_size + 7) / 8 * 8 + super_vtable_offset := (info_offset + size_of(Class_VTable_Info) + 7) / 8 * 8 + ptoto_vtable_offset := super_vtable_offset + super_size + + + p_info := (^Class_VTable_Info)(([^]u8)(cls)[info_offset:]) + p_super_vtable := ([^]u8)(cls)[super_vtable_offset:] + p_proto_vtable := ([^]u8)(cls)[ptoto_vtable_offset:] + + intrinsics.mem_zero(p_info, size_of(Class_VTable_Info)) + + // Assign the context + p_info._context = _context.? or_else context + + if s, ok := superclass_overrides.?; ok { + p_info.super_vtable = p_super_vtable + intrinsics.mem_copy(p_super_vtable, s.vtable, super_size) + } + if p, ok := protocol.?; ok { + p_info.protocol_vtable = p_proto_vtable + intrinsics.mem_copy(p_proto_vtable, p.vtable, p.size) + } + + return cls +} + +@(require_results) +class_get_vtable_info :: proc "contextless" (cls: Class) -> ^Class_VTable_Info { + meta_cls := class_get_metaclass(cls) + meta_size := uint(class_getInstanceSize(meta_cls)) + + // Align to 8-byte boundary + info_offset := (meta_size+7) / 8 * 8 + + p_cls := ([^]u8)(cls)[info_offset:] + ctx := (^Class_VTable_Info)(p_cls) + return ctx +} + +@(require_results) +alloc_user_object :: proc "contextless" (cls: Class, _context: Maybe(runtime.Context) = nil) -> id { + info := class_get_vtable_info(cls) + + obj := class_createInstance(cls, size_of(Class_VTable_Info)) + obj_info := (^Class_VTable_Info)(object_getIndexedIvars(obj)) + obj_info^ = info^ + + if _context != nil { + obj_info._context = _context.? + } + return obj +} \ No newline at end of file diff --git a/core/sys/darwin/copyfile.odin b/core/sys/darwin/copyfile.odin new file mode 100644 index 000000000..6c58b8067 --- /dev/null +++ b/core/sys/darwin/copyfile.odin @@ -0,0 +1,67 @@ +package darwin + +import "core:sys/posix" + +copyfile_state_t :: distinct rawptr + +copyfile_flags :: bit_set[enum { + ACL, + STAT, + XATTR, + DATA, + + RECURSIVE = 15, + + CHECK, + EXCL, + NOFOLLOW_SRC, + NOFOLLOW_DST, + MOVE, + UNLINK, + PACK, + UNPACK, + + CLONE, + CLONE_FORCE, + RUN_IN_PLACE, + DATA_SPARSE, + PRESERVE_DST_TRACKED, + VERBOSE = 30, +}; u32] + +COPYFILE_SECURITY :: copyfile_flags{.STAT, .ACL} +COPYFILE_METADATA :: COPYFILE_SECURITY + copyfile_flags{.XATTR} +COPYFILE_ALL :: COPYFILE_METADATA + copyfile_flags{.DATA} + +COPYFILE_NOFOLLOW :: copyfile_flags{.NOFOLLOW_SRC, .NOFOLLOW_DST} + +copyfile_state_flag :: enum u32 { + SRC_FD = 1, + SRC_FILENAME, + DST_FD, + DST_FILENAME, + QUARANTINE, + STATUS_CB, + STATUS_CTX, + COPIED, + XATTRNAME, + WAS_CLONED, + SRC_BSIZE, + DST_BSIZE, + BSIZE, + FORBID_CROSS_MOUNT, + NOCPROTECT, + PRESERVE_SUID, + RECURSIVE_SRC_FTSENT, + FORBID_DST_EXISTING_SYMLINKS, +} + +foreign system { + copyfile :: proc(from, to: cstring, state: copyfile_state_t, flags: copyfile_flags) -> i32 --- + fcopyfile :: proc(from, to: posix.FD, state: copyfile_state_t, flags: copyfile_flags) -> i32 --- + + copyfile_state_alloc :: proc() -> copyfile_state_t --- + copyfile_state_free :: proc(state: copyfile_state_t) -> posix.result --- + copyfile_state_get :: proc(state: copyfile_state_t, flag: copyfile_state_flag, dst: rawptr) -> posix.result --- + copyfile_state_set :: proc(state: copyfile_state_t, flag: copyfile_state_flag, src: rawptr) -> posix.result --- +} diff --git a/core/sys/darwin/darwin.odin b/core/sys/darwin/darwin.odin index d109f5544..52297505a 100644 --- a/core/sys/darwin/darwin.odin +++ b/core/sys/darwin/darwin.odin @@ -3,7 +3,8 @@ package darwin import "core:c" -foreign import system "system:System.framework" +@(export) +foreign import system "system:System" Bool :: b8 diff --git a/core/sys/darwin/mach_darwin.odin b/core/sys/darwin/mach_darwin.odin index 2cc823e69..9520e0e00 100644 --- a/core/sys/darwin/mach_darwin.odin +++ b/core/sys/darwin/mach_darwin.odin @@ -1,19 +1,38 @@ package darwin -foreign import mach "system:System.framework" +foreign import mach "system:System" import "core:c" import "base:intrinsics" -kern_return_t :: distinct c.int - mach_port_t :: distinct c.uint +task_t :: mach_port_t + +semaphore_t :: distinct u64 + +kern_return_t :: distinct c.int +thread_act_t :: distinct u32 +thread_state_t :: distinct ^u32 +thread_list_t :: [^]thread_act_t +vm_region_recurse_info_t :: distinct ^i32 +task_info_t :: distinct ^i32 + +MACH_PORT_NULL :: 0 +MACH_PORT_DEAD :: ~mach_port_t(0) + +MACH_MSG_PORT_DESCRIPTOR :: 0 + +X86_THREAD_STATE32 :: 1 +X86_THREAD_STATE64 :: 4 +ARM_THREAD_STATE64 :: 6 + +mach_msg_option_t :: distinct i32 +name_t :: distinct cstring + vm_map_t :: mach_port_t mem_entry_name_port_t :: mach_port_t ipc_space_t :: mach_port_t thread_t :: mach_port_t -task_t :: mach_port_t -semaphore_t :: mach_port_t vm_size_t :: distinct c.uintptr_t @@ -29,11 +48,279 @@ vm_inherit_t :: distinct c.uint mach_port_name_t :: distinct c.uint +mach_port_right_t :: distinct c.uint + sync_policy_t :: distinct c.int +mach_msg_port_descriptor_t :: struct { + name: mach_port_t, + _: u32, + using _: bit_field u32 { + _: u32 | 16, + disposition: u32 | 8, + type: u32 | 8, + }, +} + +Task_Port_Type :: enum u32 { + Kernel = 1, + Host, + Name, + Bootstrap, + Seatbelt = 7, + Access = 9, +} + +Bootstrap_Error :: enum u32 { + Success, + Not_Privileged = 1100, + Name_In_Use = 1101, + Unknown_Service = 1102, + Service_Active = 1103, + Bad_Count = 1104, + No_Memory = 1105, + No_Children = 1106, +} + +Msg_Type :: enum u32 { + Unstructured = 0, + Bit = 0, + Boolean = 0, + Integer_16 = 1, + Integer_32 = 2, + Char = 8, + Byte = 9, + Integer_8 = 9, + Real = 10, + Integer_64 = 11, + String = 12, + String_C = 12, + + Port_Name = 15, + + Move_Receive = 16, + Port_Receive = 16, + Move_Send = 17, + Port_Send = 17, + Move_Send_Once = 18, + Port_Send_Once = 18, + Copy_Send = 19, + Make_Send = 20, + Make_Send_Once = 21, +} + +Msg_Header_Bits :: enum u32 { + Zero = 0, + Remote_Mask = 0xff, + Local_Mask = 0xff00, + Migrated = 0x08000000, + Unused = 0x07ff0000, + Complex_Data = 0x10000000, + Complex_Ports = 0x20000000, + Circular = 0x40000000, + Complex = 0x80000000, +} + +mach_msg_type_t :: struct { + using _: bit_field u32 { + name: u32 | 8, + size: u32 | 8, + number: u32 | 12, + inline: u32 | 1, + longform: u32 | 1, + deallocate: u32 | 1, + unused: u32 | 1, + }, +} + +mach_msg_header_t :: struct { + msgh_bits: u32, + msgh_size: u32, + msgh_remote_port: mach_port_t, + msgh_local_port: mach_port_t, + msgh_voucher_port: u32, + msgh_id: i32, +} + +mach_msg_body_t :: struct { + msgh_descriptor_count: u32, +} + +mach_msg_trailer_t :: struct { + msgh_trailer_type: u32, + msgh_trailer_size: u32, +} + +x86_thread_state32_t :: struct { + eax: u32, + ebx: u32, + ecx: u32, + edx: u32, + edi: u32, + esi: u32, + ebp: u32, + esp: u32, + ss: u32, + eflags: u32, + eip: u32, + cs: u32, + ds: u32, + es: u32, + fs: u32, + gs: u32, +} +X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32) + +x86_thread_state64_t :: struct #packed { + rax: u64, + rbx: u64, + rcx: u64, + rdx: u64, + rdi: u64, + rsi: u64, + rbp: u64, + rsp: u64, + r8: u64, + r9: u64, + r10: u64, + r11: u64, + r12: u64, + r13: u64, + r14: u64, + r15: u64, + rip: u64, + rflags: u64, + cs: u64, + fs: u64, + gs: u64, +} +X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32) + +arm_thread_state64_t :: struct #packed { + x: [29]u64, + fp: u64, + lr: u64, + sp: u64, + pc: u64, + cpsr: u32, + pad: u32, +} +ARM_THREAD_STATE64_COUNT :: size_of(arm_thread_state64_t) / size_of(u32) + +THREAD_IDENTIFIER_INFO :: 4 +thread_identifier_info :: struct { + thread_id: u64, + thread_handler: u64, + dispatch_qaddr: u64, +} +THREAD_IDENTIFIER_INFO_COUNT :: size_of(thread_identifier_info) / size_of(u32) + +vm_region_submap_info_64 :: struct { + protection: u32, + max_protection: u32, + inheritance: u32, + offset: u64, + user_tag: u32, + pages_residept: u32, + pages_shared_now_private: u32, + pages_swapped_out: u32, + pages_dirtied: u32, + ref_count: u32, + shadow_depth: u16, + external_pager: u8, + share_mode: u8, + is_submap: b32, + behavior: i32, + object_id: u32, + user_wired_count: u16, + pages_reusable: u32, +} +VM_REGION_SUBMAP_INFO_COUNT_64 :: size_of(vm_region_submap_info_64) / size_of(u32) + +TASK_DYLD_INFO :: 17 +task_dyld_info :: struct { + all_image_info_addr: u64, + all_image_info_size: u64, + all_image_info_format: i32, +} +TASK_DYLD_INFO_COUNT :: size_of(task_dyld_info) / size_of(u32) + +dyld_image_info :: struct { + image_load_addr: u64, + image_file_path: cstring, + image_file_mod_date: u64, +} + +dyld_uuid_info :: struct { + image_load_addr: u64, + image_uuid: [16]u8, +} + +dyld_all_image_infos :: struct { + version: u32, + info_array_count: u32, + info_array: rawptr, + notification: rawptr, + process_detached_from_shared_region: b32, + libSystem_initialized: b32, + dyld_image_load_addr: u64, + jit_info: rawptr, + dyld_version: cstring, + error_message: cstring, + termination_flags: u64, + core_symbolication_shm_page: rawptr, + system_order_flag: u64, + uuid_array_count: u64, + uuid_array: rawptr, + dyld_all_image_infos_addr: u64, + initial_image_count: u64, + error_kind: u64, + error_client_of_dylib_path: cstring, + error_target_dylib_path: cstring, + error_symbol: cstring, + shared_cache_slide: u64, + shared_cache_uuid: [16]u8, + shared_cache_base_addr: u64, + info_array_change_timestamp: u64, + dyld_path: cstring, + notify_ports: [8]mach_port_t, + reserved: [7]u64, + shared_cache_fsid: u64, + shared_cache_fsobjid: u64, + compact_dyld_image_info_addr: u64, + compact_dyld_image_info_size: u64, + platform: u32, + aot_info_count: u32, + aot_info_array: rawptr, + aot_info_array_change_timestamp: u64, + aot_shared_cache_base_address: u64, + aot_shared_cache_uuid: [16]u8, +} + + @(default_calling_convention="c") foreign mach { - mach_task_self :: proc() -> mach_port_t --- + mach_task_self :: proc() -> mach_port_t --- + mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> Kern_Return --- + mach_msg_send :: proc(header: rawptr) -> Kern_Return --- + mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> Kern_Return --- + mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> Kern_Return --- + mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> Kern_Return --- + mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> Kern_Return --- + vm_page_size: u64 + vm_page_mask: u64 + vm_page_shift: i32 + + mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> Kern_Return --- + mach_port_deallocate :: proc(task: task_t, name: u32) -> Kern_Return --- + mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> Kern_Return --- + + task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> Kern_Return --- + task_suspend :: proc(task: task_t) -> Kern_Return --- + task_resume :: proc(task: task_t) -> Kern_Return --- + task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> Kern_Return --- + task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> Kern_Return --- + task_terminate :: proc(task: task_t) -> Kern_Return --- semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return --- semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return --- @@ -44,9 +331,11 @@ foreign mach { semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return --- - vm_allocate :: proc (target_task : vm_map_t, address: ^vm_address_t, size: vm_size_t, flags: VM_Flags) -> Kern_Return --- + thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> Kern_Return --- + thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> Kern_Return --- - vm_deallocate :: proc(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) -> Kern_Return --- + bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> Kern_Return --- + bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> Kern_Return --- vm_map :: proc( target_task: vm_map_t, @@ -70,15 +359,10 @@ foreign mach { object_handle: ^mem_entry_name_port_t, parent_entry: mem_entry_name_port_t, ) -> Kern_Return --- - - mach_port_deallocate :: proc( - task: ipc_space_t, - name: mach_port_name_t, - ) -> Kern_Return --- - - vm_page_size: vm_size_t } + + Kern_Return :: enum kern_return_t { Success, @@ -500,6 +784,39 @@ VM_PROT_NONE :: VM_Prot_Flags{} VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write} VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute} +/* + * Mach msg options, defined as bits within the mach_msg_option_t type + */ + +Msg_Option :: enum mach_msg_option_t { + Send_Msg, + Receive_Msg, + + Send_Timeout = LOG2(0x10), + Send_Notify = LOG2(0x20), + Send_Interrupt = LOG2(0x40), + Send_Cancel = LOG2(0x80), + Receive_Timeout = LOG2(0x100), + Receive_Notify = LOG2(0x200), + Receive_Interrupt = LOG2(0x400), + Receive_Large = LOG2(0x800), + Send_Always = LOG2(0x10000), +} + +Msg_Option_Flags :: distinct bit_set[Msg_Option; mach_msg_option_t] + +/* + * Enumeration of valid values for mach_port_right_t + */ + +Port_Right :: enum mach_port_right_t { + Send, + Receive, + Send_Once, + Port_Set, + Dead_Name, +} + /* * Enumeration of valid values for vm_inherit_t. */ @@ -522,3 +839,7 @@ Sync_Policy :: enum sync_policy_t { Lifo = Fifo | Reversed, } + +mach_vm_trunc_page :: proc(v: u64) -> u64 { + return v & ~vm_page_mask +} diff --git a/core/sys/darwin/proc.odin b/core/sys/darwin/proc.odin index fa5391f6f..ccd05f478 100644 --- a/core/sys/darwin/proc.odin +++ b/core/sys/darwin/proc.odin @@ -4,7 +4,7 @@ import "base:intrinsics" import "core:sys/posix" -foreign import lib "system:System.framework" +foreign import lib "system:System" // Incomplete bindings to the proc API on MacOS, add to when needed. diff --git a/core/sys/darwin/sync.odin b/core/sys/darwin/sync.odin index 58fc7c9e4..5f4f16fc3 100644 --- a/core/sys/darwin/sync.odin +++ b/core/sys/darwin/sync.odin @@ -1,27 +1,15 @@ package darwin -foreign import system "system:System.framework" - // #define OS_WAIT_ON_ADDR_AVAILABILITY \ // __API_AVAILABLE(macos(14.4), ios(17.4), tvos(17.4), watchos(10.4)) when ODIN_OS == .Darwin { - - when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 17_04_00 { - WAIT_ON_ADDRESS_AVAILABLE :: true - } else when ODIN_MINIMUM_OS_VERSION >= 14_04_00 { - WAIT_ON_ADDRESS_AVAILABLE :: true + when ODIN_PLATFORM_SUBTARGET_IOS { + WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 17_04_00 + ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_00_00 } else { - WAIT_ON_ADDRESS_AVAILABLE :: false + WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_04_00 + ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 11_00_00 } - - when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 14_00_00 { - ULOCK_WAIT_2_AVAILABLE :: true - } else when ODIN_MINIMUM_OS_VERSION >= 11_00_00 { - ULOCK_WAIT_2_AVAILABLE :: true - } else { - ULOCK_WAIT_2_AVAILABLE :: false - } - } else { WAIT_ON_ADDRESS_AVAILABLE :: false ULOCK_WAIT_2_AVAILABLE :: false diff --git a/core/sys/darwin/xnu_system_call_wrappers.odin b/core/sys/darwin/xnu_system_call_wrappers.odin index 1188091a9..43bcb543b 100644 --- a/core/sys/darwin/xnu_system_call_wrappers.odin +++ b/core/sys/darwin/xnu_system_call_wrappers.odin @@ -19,16 +19,6 @@ X_OK :: c.int((1 << 0)) /* test for execute or search permission */ W_OK :: c.int((1 << 1)) /* test for write permission */ R_OK :: c.int((1 << 2)) /* test for read permission */ -/* copyfile flags */ -COPYFILE_ACL :: (1 << 0) -COPYFILE_STAT :: (1 << 1) -COPYFILE_XATTR :: (1 << 2) -COPYFILE_DATA :: (1 << 3) - -COPYFILE_SECURITY :: (COPYFILE_STAT | COPYFILE_ACL) -COPYFILE_METADATA :: (COPYFILE_SECURITY | COPYFILE_XATTR) -COPYFILE_ALL :: (COPYFILE_METADATA | COPYFILE_DATA) - /* syslimits.h */ PATH_MAX :: 1024 /* max bytes in pathname */ @@ -233,6 +223,11 @@ _Proc_Bsdinfo :: struct { /*--==========================================================================--*/ +/* Get window size */ +TIOCGWINSZ :: 0x40087468 + +/*--==========================================================================--*/ + syscall_fsync :: #force_inline proc "contextless" (fildes: c.int) -> bool { return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.fsync), uintptr(fildes))) } @@ -285,6 +280,10 @@ syscall_lseek :: #force_inline proc "contextless" (fd: c.int, offset: i64, whenc return cast(i64)intrinsics.syscall(unix_offset_syscall(.lseek), uintptr(fd), uintptr(offset), uintptr(whence)) } +syscall_ioctl :: #force_inline proc "contextless" (fd: c.int, request: u32, arg: rawptr) -> c.int { + return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.ioctl), uintptr(fd), uintptr(request), uintptr(arg))) +} + syscall_gettid :: #force_inline proc "contextless" () -> u64 { return cast(u64)intrinsics.syscall(unix_offset_syscall(.gettid)) } diff --git a/core/sys/es/api.odin b/core/sys/es/api.odin deleted file mode 100644 index 4cf64b748..000000000 --- a/core/sys/es/api.odin +++ /dev/null @@ -1,2900 +0,0 @@ -package es -ElementPublic :: struct { - userCallback : UICallbackFunction, - cName : cstring , - userData : Generic, - accessKey : i8 , - window : ^Window, - instance : ^INSTANCE_TYPE, - flags : u64 , -} -Generic :: rawptr; -INSTANCE_TYPE :: Instance; -Element :: ElementPublic; -Panel :: Element; -Window :: Element; -Scrollbar :: Element; -Button :: Element; -TextDisplay :: Element; -IconDisplay :: Element; -Textbox :: Element; -ListView :: Element; -Menu :: Element; -Choice :: Element; -ColorWell :: Element; -Splitter :: Element; -ImageDisplay :: Element; -TextPlan :: rawptr; -Store :: rawptr; -PaintTarget :: rawptr; -DirectoryMonitor :: rawptr; -NodeType :: u8 ; -Error :: int ; -Handle :: uint ; -Response :: i32; -FileOffset :: u64 ; -FileOffsetDifference :: i64 ; -AudioDeviceID :: u64 ; -SCANCODE_A :: (0x04); -SCANCODE_B :: (0x05); -SCANCODE_C :: (0x06); -SCANCODE_D :: (0x07); -SCANCODE_E :: (0x08); -SCANCODE_F :: (0x09); -SCANCODE_G :: (0x0A); -SCANCODE_H :: (0x0B); -SCANCODE_I :: (0x0C); -SCANCODE_J :: (0x0D); -SCANCODE_K :: (0x0E); -SCANCODE_L :: (0x0F); -SCANCODE_M :: (0x10); -SCANCODE_N :: (0x11); -SCANCODE_O :: (0x12); -SCANCODE_P :: (0x13); -SCANCODE_Q :: (0x14); -SCANCODE_R :: (0x15); -SCANCODE_S :: (0x16); -SCANCODE_T :: (0x17); -SCANCODE_U :: (0x18); -SCANCODE_V :: (0x19); -SCANCODE_W :: (0x1A); -SCANCODE_X :: (0x1B); -SCANCODE_Y :: (0x1C); -SCANCODE_Z :: (0x1D); -SCANCODE_1 :: (0x1E); -SCANCODE_2 :: (0x1F); -SCANCODE_3 :: (0x20); -SCANCODE_4 :: (0x21); -SCANCODE_5 :: (0x22); -SCANCODE_6 :: (0x23); -SCANCODE_7 :: (0x24); -SCANCODE_8 :: (0x25); -SCANCODE_9 :: (0x26); -SCANCODE_0 :: (0x27); -SCANCODE_ENTER :: (0x28); -SCANCODE_ESCAPE :: (0x29); -SCANCODE_BACKSPACE :: (0x2A); -SCANCODE_TAB :: (0x2B); -SCANCODE_SPACE :: (0x2C); -SCANCODE_HYPHEN :: (0x2D); -SCANCODE_EQUALS :: (0x2E); -SCANCODE_LEFT_BRACE :: (0x2F); -SCANCODE_RIGHT_BRACE :: (0x30); -SCANCODE_COMMA :: (0x36); -SCANCODE_PERIOD :: (0x37); -SCANCODE_SLASH :: (0x38); -SCANCODE_PUNCTUATION_1 :: (0x31) ; -SCANCODE_PUNCTUATION_2 :: (0x32) ; -SCANCODE_PUNCTUATION_3 :: (0x33) ; -SCANCODE_PUNCTUATION_4 :: (0x34) ; -SCANCODE_PUNCTUATION_5 :: (0x35) ; -SCANCODE_PUNCTUATION_6 :: (0x64) ; -SCANCODE_F1 :: (0x3A); -SCANCODE_F2 :: (0x3B); -SCANCODE_F3 :: (0x3C); -SCANCODE_F4 :: (0x3D); -SCANCODE_F5 :: (0x3E); -SCANCODE_F6 :: (0x3F); -SCANCODE_F7 :: (0x40); -SCANCODE_F8 :: (0x41); -SCANCODE_F9 :: (0x42); -SCANCODE_F10 :: (0x43); -SCANCODE_F11 :: (0x44); -SCANCODE_F12 :: (0x45); -SCANCODE_F13 :: (0x68); -SCANCODE_F14 :: (0x69); -SCANCODE_F15 :: (0x6A); -SCANCODE_F16 :: (0x6B); -SCANCODE_F17 :: (0x6C); -SCANCODE_F18 :: (0x6D); -SCANCODE_F19 :: (0x6E); -SCANCODE_F20 :: (0x6F); -SCANCODE_F21 :: (0x70); -SCANCODE_F22 :: (0x71); -SCANCODE_F23 :: (0x72); -SCANCODE_F24 :: (0x73); -SCANCODE_CAPS_LOCK :: (0x39); -SCANCODE_PRINT_SCREEN :: (0x46); -SCANCODE_SCROLL_LOCK :: (0x47); -SCANCODE_PAUSE :: (0x48); -SCANCODE_INSERT :: (0x49); -SCANCODE_HOME :: (0x4A); -SCANCODE_PAGE_UP :: (0x4B); -SCANCODE_DELETE :: (0x4C); -SCANCODE_END :: (0x4D); -SCANCODE_PAGE_DOWN :: (0x4E); -SCANCODE_RIGHT_ARROW :: (0x4F); -SCANCODE_LEFT_ARROW :: (0x50); -SCANCODE_DOWN_ARROW :: (0x51); -SCANCODE_UP_ARROW :: (0x52); -SCANCODE_NUM_LOCK :: (0x53); -SCANCODE_CONTEXT_MENU :: (0x65); -SCANCODE_SYSTEM_REQUEST :: (0x9A); -SCANCODE_ACTION_EXECUTE :: (0x74); -SCANCODE_ACTION_HELP :: (0x75); -SCANCODE_ACTION_MENU :: (0x76); -SCANCODE_ACTION_SELECT :: (0x77); -SCANCODE_ACTION_STOP :: (0x78); -SCANCODE_ACTION_AGAIN :: (0x79); -SCANCODE_ACTION_UNDO :: (0x7A); -SCANCODE_ACTION_CUT :: (0x7B); -SCANCODE_ACTION_COPY :: (0x7C); -SCANCODE_ACTION_PASTE :: (0x7D); -SCANCODE_ACTION_FIND :: (0x7E); -SCANCODE_ACTION_CANCEL :: (0x9B); -SCANCODE_ACTION_CLEAR :: (0x9C); -SCANCODE_ACTION_PRIOR :: (0x9D); -SCANCODE_ACTION_RETURN :: (0x9E); -SCANCODE_ACTION_SEPARATOR :: (0x9F); -SCANCODE_MM_MUTE :: (0x7F); -SCANCODE_MM_LOUDER :: (0x80); -SCANCODE_MM_QUIETER :: (0x81); -SCANCODE_MM_NEXT :: (0x103); -SCANCODE_MM_PREVIOUS :: (0x104); -SCANCODE_MM_STOP :: (0x105); -SCANCODE_MM_PAUSE :: (0x106); -SCANCODE_MM_SELECT :: (0x107); -SCANCODE_MM_EMAIL :: (0x108); -SCANCODE_MM_CALC :: (0x109); -SCANCODE_MM_FILES :: (0x10A); -SCANCODE_INTERNATIONAL_1 :: (0x87); -SCANCODE_INTERNATIONAL_2 :: (0x88); -SCANCODE_INTERNATIONAL_3 :: (0x89); -SCANCODE_INTERNATIONAL_4 :: (0x8A); -SCANCODE_INTERNATIONAL_5 :: (0x8B); -SCANCODE_INTERNATIONAL_6 :: (0x8C); -SCANCODE_INTERNATIONAL_7 :: (0x8D); -SCANCODE_INTERNATIONAL_8 :: (0x8E); -SCANCODE_INTERNATIONAL_9 :: (0x8F); -SCANCODE_HANGUL_ENGLISH_TOGGLE :: (0x90); -SCANCODE_HANJA_CONVERSION :: (0x91); -SCANCODE_KATAKANA :: (0x92); -SCANCODE_HIRAGANA :: (0x93); -SCANCODE_HANKAKU_ZENKAKU_TOGGLE :: (0x94); -SCANCODE_ALTERNATE_ERASE :: (0x99); -SCANCODE_THOUSANDS_SEPARATOR :: (0xB2); -SCANCODE_DECIMAL_SEPARATOR :: (0xB3); -SCANCODE_CURRENCY_UNIT :: (0xB4); -SCANCODE_CURRENCY_SUBUNIT :: (0xB5); -SCANCODE_NUM_DIVIDE :: (0x54); -SCANCODE_NUM_MULTIPLY :: (0x55); -SCANCODE_NUM_SUBTRACT :: (0x56); -SCANCODE_NUM_ADD :: (0x57); -SCANCODE_NUM_ENTER :: (0x58); -SCANCODE_NUM_1 :: (0x59); -SCANCODE_NUM_2 :: (0x5A); -SCANCODE_NUM_3 :: (0x5B); -SCANCODE_NUM_4 :: (0x5C); -SCANCODE_NUM_5 :: (0x5D); -SCANCODE_NUM_6 :: (0x5E); -SCANCODE_NUM_7 :: (0x5F); -SCANCODE_NUM_8 :: (0x60); -SCANCODE_NUM_9 :: (0x61); -SCANCODE_NUM_0 :: (0x62); -SCANCODE_NUM_POINT :: (0x63); -SCANCODE_NUM_EQUALS :: (0x67); -SCANCODE_NUM_COMMA :: (0x82); -SCANCODE_NUM_00 :: (0xB0); -SCANCODE_NUM_000 :: (0xB1); -SCANCODE_NUM_LEFT_PAREN :: (0xB6); -SCANCODE_NUM_RIGHT_PAREN :: (0xB7); -SCANCODE_NUM_LEFT_BRACE :: (0xB8); -SCANCODE_NUM_RIGHT_BRACE :: (0xB9); -SCANCODE_NUM_TAB :: (0xBA); -SCANCODE_NUM_BACKSPACE :: (0xBB); -SCANCODE_NUM_A :: (0xBC); -SCANCODE_NUM_B :: (0xBD); -SCANCODE_NUM_C :: (0xBE); -SCANCODE_NUM_D :: (0xBF); -SCANCODE_NUM_E :: (0xC0); -SCANCODE_NUM_F :: (0xC1); -SCANCODE_NUM_XOR :: (0xC2); -SCANCODE_NUM_CARET :: (0xC3); -SCANCODE_NUM_PERCENT :: (0xC4); -SCANCODE_NUM_LESS_THAN :: (0xC5); -SCANCODE_NUM_GREATER_THAN :: (0xC6); -SCANCODE_NUM_AMPERSAND :: (0xC7); -SCANCODE_NUM_DOUBLE_AMPERSAND :: (0xC8); -SCANCODE_NUM_BAR :: (0xC9); -SCANCODE_NUM_DOUBLE_BAR :: (0xCA); -SCANCODE_NUM_COLON :: (0xCB); -SCANCODE_NUM_HASH :: (0xCC); -SCANCODE_NUM_SPACE :: (0xCD); -SCANCODE_NUM_AT :: (0xCE); -SCANCODE_NUM_EXCLAMATION_MARK :: (0xCF); -SCANCODE_NUM_MEMORY_STORE :: (0xD0); -SCANCODE_NUM_MEMORY_RECALL :: (0xD1); -SCANCODE_NUM_MEMORY_CLEAR :: (0xD2); -SCANCODE_NUM_MEMORY_ADD :: (0xD3); -SCANCODE_NUM_MEMORY_SUBTRACT :: (0xD4); -SCANCODE_NUM_MEMORY_MULTIPLY :: (0xD5); -SCANCODE_NUM_MEMORY_DIVIDE :: (0xD6); -SCANCODE_NUM_NEGATE :: (0xD7); -SCANCODE_NUM_CLEAR_ALL :: (0xD8); -SCANCODE_NUM_CLEAR :: (0xD9); -SCANCODE_NUM_BINARY :: (0xDA); -SCANCODE_NUM_OCTAL :: (0xDB); -SCANCODE_NUM_DECIMAL :: (0xDC); -SCANCODE_NUM_HEXADECIMAL :: (0xDD); -SCANCODE_LEFT_CTRL :: (0xE0); -SCANCODE_LEFT_SHIFT :: (0xE1); -SCANCODE_LEFT_ALT :: (0xE2); -SCANCODE_LEFT_FLAG :: (0xE3); -SCANCODE_RIGHT_CTRL :: (0xE4); -SCANCODE_RIGHT_SHIFT :: (0xE5); -SCANCODE_RIGHT_ALT :: (0xE6); -SCANCODE_RIGHT_FLAG :: (0xE7); -SCANCODE_ACPI_POWER :: (0x100); -SCANCODE_ACPI_SLEEP :: (0x101); -SCANCODE_ACPI_WAKE :: (0x102); -SCANCODE_WWW_SEARCH :: (0x10B); -SCANCODE_WWW_HOME :: (0x10C); -SCANCODE_WWW_BACK :: (0x10D); -SCANCODE_WWW_FORWARD :: (0x10E); -SCANCODE_WWW_STOP :: (0x10F); -SCANCODE_WWW_REFRESH :: (0x110); -SCANCODE_WWW_STARRED :: (0x111); -PROCESS_STATE_ALL_THREADS_TERMINATED :: (1); -PROCESS_STATE_TERMINATING :: (2); -PROCESS_STATE_CRASHED :: (4); -PROCESS_STATE_PINGED :: (8); -FLAGS_DEFAULT :: (0); -SUCCESS :: (-1); -ERROR_BUFFER_TOO_SMALL :: (-2); -ERROR_UNKNOWN :: (-7); -ERROR_NO_MESSAGES_AVAILABLE :: (-9); -ERROR_MESSAGE_QUEUE_FULL :: (-10); -ERROR_PATH_NOT_WITHIN_MOUNTED_VOLUME :: (-14); -ERROR_PATH_NOT_TRAVERSABLE :: (-15); -ERROR_FILE_ALREADY_EXISTS :: (-19); -ERROR_FILE_DOES_NOT_EXIST :: (-20); -ERROR_DRIVE_ERROR_FILE_DAMAGED :: (-21) ; -ERROR_ACCESS_NOT_WITHIN_FILE_BOUNDS :: (-22) ; -ERROR_FILE_PERMISSION_NOT_GRANTED :: (-23); -ERROR_FILE_IN_EXCLUSIVE_USE :: (-24); -ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE :: (-25); -ERROR_INCORRECT_NODE_TYPE :: (-26); -ERROR_EVENT_NOT_SET :: (-27); -ERROR_FILE_HAS_WRITERS :: (-28); -ERROR_TIMEOUT_REACHED :: (-29); -ERROR_FILE_ON_READ_ONLY_VOLUME :: (-32); -ERROR_INVALID_DIMENSIONS :: (-34); -ERROR_DRIVE_CONTROLLER_REPORTED :: (-35); -ERROR_COULD_NOT_ISSUE_PACKET :: (-36); -ERROR_HANDLE_TABLE_FULL :: (-37); -ERROR_COULD_NOT_RESIZE_FILE :: (-38); -ERROR_DIRECTORY_NOT_EMPTY :: (-39); -ERROR_NODE_DELETED :: (-41); -ERROR_VOLUME_MISMATCH :: (-43); -ERROR_TARGET_WITHIN_SOURCE :: (-44); -ERROR_TARGET_INVALID_TYPE :: (-45); -ERROR_MALFORMED_NODE_PATH :: (-47); -ERROR_OUT_OF_CACHE_RESOURCES :: (-48); -ERROR_TARGET_IS_SOURCE :: (-49); -ERROR_INVALID_NAME :: (-50); -ERROR_CORRUPT_DATA :: (-51); -ERROR_INSUFFICIENT_RESOURCES :: (-52); -ERROR_UNSUPPORTED_FEATURE :: (-53); -ERROR_FILE_TOO_FRAGMENTED :: (-54); -ERROR_DRIVE_FULL :: (-55); -ERROR_COULD_NOT_RESOLVE_SYMBOL :: (-56); -ERROR_ALREADY_EMBEDDED :: (-57); -ERROR_EVENT_SINK_OVERFLOW :: (-58); -ERROR_EVENT_SINK_DUPLICATE :: (-59); -ERROR_UNSUPPORTED_CONVERSION :: (-60); -ERROR_SOURCE_EMPTY :: (-61); -ERROR_UNSUPPORTED_EXECUTABLE :: (-62); -ERROR_NO_ADDRESS_FOR_DOMAIN_NAME :: (-63); -ERROR_NO_CONNECTED_NETWORK_INTERFACES :: (-64); -ERROR_BAD_DOMAIN_NAME :: (-65); -ERROR_LOST_IP_ADDRESS :: (-66); -ERROR_CONNECTION_RESET :: (-67); -ERROR_CONNECTION_REFUSED :: (-68); -SYSTEM_CONSTANT_TIME_STAMP_UNITS_PER_MICROSECOND :: (0); -SYSTEM_CONSTANT_NO_FANCY_GRAPHICS :: (1); -SYSTEM_CONSTANT_REPORTED_PROBLEMS :: (2); -SYSTEM_CONSTANT_RIGHT_TO_LEFT :: (3); -SYSTEM_CONSTANT_WINDOW_INSET :: (4); -SYSTEM_CONSTANT_CONTAINER_TAB_BAND_HEIGHT :: (5); -INVALID_HANDLE :: (( Handle) (0)); -CURRENT_THREAD :: (( Handle) (0x10)); -CURRENT_PROCESS :: (( Handle) (0x11)); -DRAW_ALPHA_OVERWRITE :: (0x100); -DRAW_ALPHA_FULL :: (0x200) ; -WAIT_NO_TIMEOUT :: (-1); -MAX_WAIT_COUNT :: (8); -MAX_EVENT_FORWARD_COUNT :: (4) ; -MAX_EVENT_SINK_BUFFER_SIZE :: (256) ; -MAX_DIRECTORY_CHILD_NAME_LENGTH :: (256); -PROCESS_EXECUTABLE_NOT_LOADED :: (0); -PROCESS_EXECUTABLE_FAILED_TO_LOAD :: (1); -PROCESS_EXECUTABLE_LOADED :: (2); -SNAPSHOT_MAX_PROCESS_NAME_LENGTH :: (80); -SYSTEM_SNAPSHOT_PROCESSES :: (1); -SYSTEM_SNAPSHOT_DRIVES :: (2); -HANDLED :: (0); -NOT_HANDLED :: (-1); -REJECTED :: (-2); -SHARED_MEMORY_NAME_MAX_LENGTH :: (32); -MAP_OBJECT_ALL :: (0); -TEXT_H_LEFT :: (1); -TEXT_H_RIGHT :: (2); -TEXT_H_CENTER :: (3); -TEXT_V_TOP :: (4); -TEXT_V_BOTTOM :: (8); -TEXT_V_CENTER :: (12); -TEXT_WRAP :: (16); -TEXT_ELLIPSIS :: (32); -NODE_ACCESS_READ_SHARED :: (0x1) ; -NODE_ACCESS_READ :: (0x2) ; -NODE_ACCESS_WRITE :: (0x4) ; -NODE_ACCESS_WRITE_EXCLUSIVE :: (0x8) ; -NODE_FILE :: (0); -NODE_DIRECTORY :: (0x10); -NODE_INVALID :: (0x20); -NODE_FAIL_IF_FOUND :: (0x1000); -NODE_FAIL_IF_NOT_FOUND :: (0x2000); -NODE_PREVENT_RESIZE :: (0x4000); -NODE_CREATE_DIRECTORIES :: (0x8000) ; -NODE_POSIX_NAMESPACE :: (0x10000) ; -_ES_NODE_FROM_WRITE_EXCLUSIVE :: (0x20000); -DIRECTORY_CHILDREN_UNKNOWN :: (( FileOffsetDifference) (-1)); -MEMORY_OPEN_FAIL_IF_FOUND :: (0x1000); -MEMORY_OPEN_FAIL_IF_NOT_FOUND :: (0x2000); -MAP_OBJECT_READ_WRITE :: (0); -MAP_OBJECT_READ_ONLY :: (1); -MAP_OBJECT_COPY_ON_WRITE :: (2); -STRING_FORMAT_ENOUGH_SPACE :: ( (-1)); -STRING_FORMAT_SIMPLE :: (1 << 0); -POSIX_SYSCALL_GET_POSIX_FD_PATH :: (0x10000); -PERMISSION_ACCESS_SYSTEM_FILES :: (1 << 0); -PERMISSION_ACCESS_USER_FILES :: (1 << 1); -PERMISSION_PROCESS_CREATE :: (1 << 2); -PERMISSION_PROCESS_OPEN :: (1 << 3); -PERMISSION_SCREEN_MODIFY :: (1 << 4) ; -PERMISSION_SHUTDOWN :: (1 << 5); -PERMISSION_TAKE_SYSTEM_SNAPSHOT :: (1 << 6); -PERMISSION_WINDOW_OPEN :: (1 << 7); -PERMISSION_ALL :: ( (-1)); -PERMISSION_INHERIT :: ( (1) << 63); -PANEL_STYLE_DEFAULT :: "Panel.Default"; -PANEL_STYLE_TRANSPARENT :: "Panel.Transparent"; -PANEL_STYLE_WINDOW_BACKGROUND :: "Panel.WindowBackground"; -PANEL_STYLE_WINDOW_DIVIDER :: "Panel.WindowDivider"; -PANEL_STYLE_SHEET :: "Panel.Sheet"; -PANEL_STYLE_GROUP_BOX :: "Panel.GroupBox"; -PANEL_STYLE_INDENT :: "Panel.Indent"; -PANEL_BAND_SIZE_DEFAULT :: (-1); -ELEMENT_FOCUSABLE :: ( (1) << 32); -ELEMENT_HIDDEN :: ( (1) << 33) ; -ELEMENT_DISABLED :: ( (1) << 34) ; -ELEMENT_DEBUG :: ( (1) << 35) ; -ELEMENT_SCROLL_X :: ( (1) << 36); -ELEMENT_SCROLL_Y :: ( (1) << 37); -ELEMENT_NO_HOVER :: ( (1) << 38) ; -ELEMENT_BLOCK_FOCUS :: ( (1) << 39) ; -ELEMENT_NOT_TAB_TRAVERSABLE :: ( (1) << 40) ; -ELEMENT_NO_INFORM_PARENT :: ( (1) << 41) ; -ELEMENT_CENTER_ACCESS_KEY_HINT :: ( (1) << 42) ; -ELEMENT_LAYOUT_HINT_HORIZONTAL :: ( (1) << 43) ; -ELEMENT_STICKY_ACCESS_KEY :: ( (1) << 44) ; -CELL_NEW_BAND :: ( (1) << 51); -CELL_COLLAPSABLE :: ( (1) << 51); -CELL_H_PUSH :: ( (1) << 54); -CELL_H_EXPAND :: ( (1) << 55); -CELL_H_SHRINK :: ( (1) << 56); -CELL_H_LEFT :: ( (1) << 57); -CELL_H_RIGHT :: ( (1) << 58); -CELL_V_PUSH :: ( (1) << 59); -CELL_V_EXPAND :: ( (1) << 60); -CELL_V_SHRINK :: ( (1) << 61); -CELL_V_TOP :: ( (1) << 62); -CELL_V_BOTTOM :: ( (1) << 63); -PANEL_VERTICAL :: (0x0001); -PANEL_WRAP :: (0x0002); -PANEL_TABLE :: (0x0004); -PANEL_Z_STACK :: (0x0008); -PANEL_H_LEFT :: (0x0010); -PANEL_H_RIGHT :: (0x0020); -PANEL_H_CENTER :: (0x0040); -PANEL_H_JUSTIFY :: (0x0080); -PANEL_V_TOP :: (0x0100); -PANEL_V_BOTTOM :: (0x0200); -PANEL_V_CENTER :: (0x0400); -PANEL_V_JUSTIFY :: (0x0800); -PANEL_H_SCROLL :: (0x1000); -PANEL_V_SCROLL :: (0x2000); -PANEL_SWITCHER :: (0x4000); -TEXTBOX_MULTILINE :: (1 << 0); -TEXTBOX_EDIT_BASED :: (1 << 1); -TEXTBOX_COMPACT :: (1 << 2); -TEXTBOX_NO_SMART_CONTEXT_MENUS :: (1 << 3); -TEXTBOX_FIND_BACKWARDS :: (1 << 0); -BUTTON_DEFAULT :: (1 << 0); -BUTTON_DANGEROUS :: (1 << 1); -BUTTON_MENU_ITEM :: (1 << 2); -BUTTON_NOT_FOCUSABLE :: (1 << 3); -BUTTON_TOOLBAR :: (1 << 4); -BUTTON_DROPDOWN :: (1 << 5); -BUTTON_COMPACT :: (1 << 6); -MENU_ITEM_HEADER :: (1 << 7); -BUTTON_CHECKBOX :: (1 << 8); -BUTTON_RADIOBOX :: (1 << 9); -BUTTON_CANCEL :: (1 << 10); -BUTTON_PUSH :: (1 << 11); -COLOR_WELL_HAS_OPACITY :: (1 << 0); -SCROLLBAR_VERTICAL :: (0 << 0); -SCROLLBAR_HORIZONTAL :: (1 << 0); -SPLITTER_VERTICAL :: (0 << 0); -SPLITTER_HORIZONTAL :: (1 << 0); -IMAGE_DISPLAY_LOAD_ASYNCHRONOUSLY :: (1 << 0); -IMAGE_DISPLAY_UNLOAD_WHEN_HIDDEN :: (1 << 1); -IMAGE_DISPLAY_UPSCALE_NEAREST :: (1 << 2); -IMAGE_DISPLAY_DOWNSCALE_NEAREST :: (1 << 3); -IMAGE_DISPLAY_OPAQUE :: (1 << 4); -LIST_VIEW_HORIZONTAL :: (1 << 0) ; -LIST_VIEW_VARIABLE_SIZE :: (1 << 1) ; -LIST_VIEW_TILED :: (1 << 2) ; -LIST_VIEW_NON_LINEAR :: (1 << 3) ; -LIST_VIEW_SINGLE_SELECT :: (1 << 4) ; -LIST_VIEW_MULTI_SELECT :: (1 << 5) ; -LIST_VIEW_COLUMNS :: (1 << 6) ; -LIST_VIEW_GROUP_HAS_HEADER :: (1 << 0) ; -LIST_VIEW_GROUP_HAS_FOOTER :: (1 << 1) ; -LIST_VIEW_GROUP_INDENT :: (1 << 2) ; -LIST_VIEW_GROUP_COLLAPSABLE :: (1 << 3) ; -LIST_VIEW_COLUMN_RIGHT_ALIGNED :: (1 << 0) ; -LIST_VIEW_COLUMN_ASCENDING :: (1 << 1) ; -LIST_VIEW_COLUMN_DESCENDING :: (1 << 2) ; -LIST_VIEW_COLUMN_HAS_MENU :: (1 << 3) ; -MENU_AT_CURSOR :: (1 << 0); -MENU_MAXIMUM_HEIGHT :: (1 << 1); -FONT_SANS :: (0xFFFF); -FONT_SERIF :: (0xFFFE); -FONT_MONOSPACED :: (0xFFFD); -FONT_REGULAR :: (4); -FONT_BOLD :: (7); -TEXT_FIGURE_DEFAULT :: (0); -TEXT_FIGURE_OLD :: (1); -TEXT_FIGURE_TABULAR :: (2); -TEXT_DISPLAY_CONTENT_MAX_VALUES :: (8); -DIRECTORY_MONITOR_SUBTREE :: (1 << 0) ; -DIRECTORY_MONITOR_CONTENTS :: (1 << 1) ; -DIRECTORY_MONITOR_MODIFY :: (1 << 2) ; -COMMAND_SYSTEM_START :: (0xF0000000); -COMMAND_DELETE :: (0xF0000001); -COMMAND_SELECT_ALL :: (0xF0000002); -COMMAND_CUT :: (0xF0000003); -COMMAND_COPY :: (0xF0000004); -COMMAND_PASTE :: (0xF0000005); -AUDIO_STREAM_OVERRUN :: (1 << 0); -AUDIO_STREAM_UNDERRUN :: (1 << 0); -AUDIO_STREAM_FORMAT_CHANGED :: (1 << 1); -AUDIO_STREAM_TERMINATED :: (1 << 2); -AUDIO_STREAM_RUNNING :: (1 << 0); -AUDIO_STREAM_MUTED :: (1 << 1); -AUDIO_STREAM_ONESHOT :: (1 << 2); -AUDIO_DEFAULT_OUTPUT :: (1); -SAMPLE_FORMAT_U8 :: (1); -SAMPLE_FORMAT_S16LE :: (2); -SAMPLE_FORMAT_S32LE :: (3); -SAMPLE_FORMAT_F32LE :: (4) ; -CELL_FILL :: ( CELL_H_FILL | CELL_V_FILL); -CELL_H_FILL :: ( CELL_H_PUSH | CELL_H_EXPAND | CELL_H_SHRINK); -CELL_V_FILL :: ( CELL_V_PUSH | CELL_V_EXPAND | CELL_V_SHRINK); -CELL_CENTER :: ( CELL_H_CENTER | CELL_V_CENTER); -CELL_PUSH :: ( CELL_H_PUSH | CELL_V_PUSH); -CELL_EXPAND :: ( CELL_H_EXPAND | CELL_V_EXPAND); -CELL_CORNER :: ( CELL_H_LEFT | CELL_V_TOP); -CELL_SHRINK :: ( CELL_H_SHRINK | CELL_V_SHRINK); -CELL_H_CENTER :: ( CELL_H_LEFT | CELL_H_RIGHT); -CELL_V_CENTER :: ( CELL_V_TOP | CELL_V_BOTTOM); -THEME_METRICS_INSETS :: (1 << 0); -THEME_METRICS_CLIP_INSETS :: (1 << 1); -THEME_METRICS_GLOBAL_OFFSET :: (1 << 2) ; -THEME_METRICS_CLIP_ENABLED :: (1 << 3); -THEME_METRICS_CURSOR :: (1 << 4); -THEME_METRICS_ENTRANCE_TRANSITION :: (1 << 5); -THEME_METRICS_EXIT_TRANSITION :: (1 << 6); -THEME_METRICS_ENTRANCE_DURATION :: (1 << 7); -THEME_METRICS_EXIT_DURATION :: (1 << 8); -THEME_METRICS_PREFERRED_WIDTH :: (1 << 9); -THEME_METRICS_PREFERRED_HEIGHT :: (1 << 10); -THEME_METRICS_MINIMUM_WIDTH :: (1 << 11); -THEME_METRICS_MINIMUM_HEIGHT :: (1 << 12); -THEME_METRICS_MAXIMUM_WIDTH :: (1 << 13); -THEME_METRICS_MAXIMUM_HEIGHT :: (1 << 14); -THEME_METRICS_GAP_MAJOR :: (1 << 15); -THEME_METRICS_GAP_MINOR :: (1 << 16); -THEME_METRICS_GAP_WRAP :: (1 << 17); -THEME_METRICS_GAP_ALL :: ( THEME_METRICS_GAP_MAJOR | THEME_METRICS_GAP_MINOR | THEME_METRICS_GAP_WRAP); -THEME_METRICS_TEXT_COLOR :: (1 << 18); -THEME_METRICS_SELECTED_BACKGROUND :: (1 << 19); -THEME_METRICS_SELECTED_TEXT :: (1 << 20); -THEME_METRICS_ICON_COLOR :: (1 << 21); -THEME_METRICS_TEXT_ALIGN :: (1 << 22); -THEME_METRICS_TEXT_SIZE :: (1 << 23); -THEME_METRICS_FONT_FAMILY :: (1 << 24); -THEME_METRICS_FONT_WEIGHT :: (1 << 25); -THEME_METRICS_ICON_SIZE :: (1 << 26); -THEME_METRICS_IS_ITALIC :: (1 << 27); -THEME_METRICS_ELLIPSIS :: (1 << 28); -THEME_METRICS_WRAP_TEXT :: (1 << 29); -MOVE_WINDOW_MAXIMISED :: (1 << 0); -MOVE_WINDOW_ADJUST_TO_FIT_SCREEN :: (1 << 1); -MOVE_WINDOW_HIDDEN :: (1 << 2); -MOVE_WINDOW_ALWAYS_ON_TOP :: (1 << 3); -MOVE_WINDOW_AT_BOTTOM :: (1 << 4); -MOVE_WINDOW_UPDATE_SCREEN :: (1 << 5); -WINDOW_SOLID_TRUE :: (1 << 0); -WINDOW_SOLID_NO_ACTIVATE :: (1 << 1); -THEME_BITMAP_WIDTH :: (400); -THEME_BITMAP_HEIGHT :: (200); -THEME_BITMAP_NAME :: "Desktop.ThemeBitmap"; -TEXTBOX_MOVE_CARET_SINGLE :: (2); -TEXTBOX_MOVE_CARET_WORD :: (3); -TEXTBOX_MOVE_CARET_LINE :: (4); -TEXTBOX_MOVE_CARET_VERTICAL :: (5); -TEXTBOX_MOVE_CARET_ALL :: (6); -TEXTBOX_MOVE_CARET_FIRST_ONLY :: (1 << 8); -TEXTBOX_MOVE_CARET_SECOND_ONLY :: (1 << 9); -TEXTBOX_MOVE_CARET_BACKWARDS :: (1 << 10); -TEXTBOX_MOVE_CARET_STRONG_WHITESPACE :: (1 << 11); -GAME_CONTROLLER_MAX_COUNT :: (16); -DOMAIN_NAME_MAX_LENGTH :: (255); -ECHO_REQUEST_MAX_LENGTH :: (48); -CONNECTION_OPEN_WAIT :: (1 << 0); -FILE_CONTROL_NOTIFY_MONITORS :: (1 << 0); -FILE_CONTROL_FLUSH :: (1 << 1); -using StandardIcon :: enum i32 { - ICON_NONE, - ICON_ACTION_UNAVAILABLE_SYMBOLIC, - ICON_ADDRESS_BOOK_NEW, - ICON_ADDRESS_BOOK_NEW_SYMBOLIC, - ICON_ALIGN_HORIZONTAL_CENTER, - ICON_ALIGN_HORIZONTAL_CENTER_SYMBOLIC, - ICON_ALIGN_HORIZONTAL_LEFT, - ICON_ALIGN_HORIZONTAL_LEFT_SYMBOLIC, - ICON_ALIGN_HORIZONTAL_LEFT_TO_ANCHOR, - ICON_ALIGN_HORIZONTAL_LEFT_TO_ANCHOR_SYMBOLIC, - ICON_ALIGN_HORIZONTAL_RIGHT, - ICON_ALIGN_HORIZONTAL_RIGHT_SYMBOLIC, - ICON_ALIGN_HORIZONTAL_RIGHT_TO_ANCHOR, - ICON_ALIGN_HORIZONTAL_RIGHT_TO_ANCHOR_SYMBOLIC, - ICON_ALIGN_VERTICAL_BOTTOM, - ICON_ALIGN_VERTICAL_BOTTOM_SYMBOLIC, - ICON_ALIGN_VERTICAL_BOTTOM_TO_ANCHOR, - ICON_ALIGN_VERTICAL_BOTTOM_TO_ANCHOR_SYMBOLIC, - ICON_ALIGN_VERTICAL_CENTER, - ICON_ALIGN_VERTICAL_CENTER_SYMBOLIC, - ICON_ALIGN_VERTICAL_TOP, - ICON_ALIGN_VERTICAL_TOP_SYMBOLIC, - ICON_ALIGN_VERTICAL_TOP_TO_ANCHOR, - ICON_ALIGN_VERTICAL_TOP_TO_ANCHOR_SYMBOLIC, - ICON_APPLICATION_ADD_SYMBOLIC, - ICON_APPOINTMENT_NEW, - ICON_APPOINTMENT_NEW_SYMBOLIC, - ICON_APPOINTMENT_SYMBOLIC, - ICON_BOOKMARK_NEW, - ICON_BOOKMARK_NEW_SYMBOLIC, - ICON_BROWSER_DOWNLOAD, - ICON_BROWSER_DOWNLOAD_SYMBOLIC, - ICON_CALL_START, - ICON_CALL_START_SYMBOLIC, - ICON_CALL_STOP, - ICON_CALL_STOP_SYMBOLIC, - ICON_COLOR_FILL, - ICON_COLOR_GRADIENT, - ICON_COLOR_GRADIENT_MESH, - ICON_COLOR_SELECT_SYMBOLIC, - ICON_CONTACT_NEW, - ICON_CONTACT_NEW_SYMBOLIC, - ICON_DISTRIBUTE_HORIZONTAL_CENTER, - ICON_DISTRIBUTE_HORIZONTAL_GAPS, - ICON_DISTRIBUTE_HORIZONTAL_LEFT, - ICON_DISTRIBUTE_HORIZONTAL_RIGHT, - ICON_DISTRIBUTE_VERTICAL_BOTTOM, - ICON_DISTRIBUTE_VERTICAL_CENTER, - ICON_DISTRIBUTE_VERTICAL_GAPS, - ICON_DISTRIBUTE_VERTICAL_TOP, - ICON_DOCUMENT_EDIT, - ICON_DOCUMENT_EDIT_SYMBOLIC, - ICON_DOCUMENT_EXPORT, - ICON_DOCUMENT_EXPORT_SYMBOLIC, - ICON_DOCUMENT_IMPORT, - ICON_DOCUMENT_IMPORT_SYMBOLIC, - ICON_DOCUMENT_NEW, - ICON_DOCUMENT_NEW_SYMBOLIC, - ICON_DOCUMENT_OPEN_RECENT, - ICON_DOCUMENT_OPEN_RECENT_SYMBOLIC, - ICON_DOCUMENT_OPEN_SYMBOLIC, - ICON_DOCUMENT_PAGE_SETUP, - ICON_DOCUMENT_PAGE_SETUP_SYMBOLIC, - ICON_DOCUMENT_PRINT_PREVIEW, - ICON_DOCUMENT_PRINT_PREVIEW_SYMBOLIC, - ICON_DOCUMENT_PRINT_SYMBOLIC, - ICON_DOCUMENT_PROPERTIES, - ICON_DOCUMENT_PROPERTIES_SYMBOLIC, - ICON_DOCUMENT_REVERT, - ICON_DOCUMENT_REVERT_SYMBOLIC, - ICON_DOCUMENT_SAVE_AS, - ICON_DOCUMENT_SAVE_AS_SYMBOLIC, - ICON_DOCUMENT_SAVE_SYMBOLIC, - ICON_DOCUMENT_SEND, - ICON_DOCUMENT_SEND_SYMBOLIC, - ICON_DRAW_CUBOID, - ICON_DRAW_ELLIPSE, - ICON_DRAW_ERASER, - ICON_DRAW_FREEHAND, - ICON_DRAW_PATH, - ICON_DRAW_POLYGON_STAR, - ICON_DRAW_RECTANGLE, - ICON_DRAW_SPIRAL, - ICON_DRAW_TEXT, - ICON_EDIT_CLEAR, - ICON_EDIT_CLEAR_ALL_SYMBOLIC, - ICON_EDIT_CLEAR_SYMBOLIC, - ICON_EDIT_COPY, - ICON_EDIT_COPY_SYMBOLIC, - ICON_EDIT_CUT, - ICON_EDIT_CUT_SYMBOLIC, - ICON_EDIT_DELETE_SYMBOLIC, - ICON_EDIT_FIND, - ICON_EDIT_FIND_REPLACE, - ICON_EDIT_FIND_REPLACE_SYMBOLIC, - ICON_EDIT_FIND_SYMBOLIC, - ICON_EDIT_FLAG, - ICON_EDIT_FLAG_SYMBOLIC, - ICON_EDIT_MARK, - ICON_EDIT_PASTE, - ICON_EDIT_PASTE_SYMBOLIC, - ICON_EDIT_REDO, - ICON_EDIT_REDO_SYMBOLIC, - ICON_EDIT_SELECT_ALL, - ICON_EDIT_SELECT_ALL_SYMBOLIC, - ICON_EDIT_SELECT_SYMBOLIC, - ICON_EDIT_UNDO, - ICON_EDIT_UNDO_ARCHIVE, - ICON_EDIT_UNDO_SYMBOLIC, - ICON_ERROR_CORRECT_SYMBOLIC, - ICON_EVENT_NEW, - ICON_FIND_LOCATION, - ICON_FIND_LOCATION_SYMBOLIC, - ICON_FOLDER_COPY, - ICON_FOLDER_MOVE, - ICON_FOLDER_NEW, - ICON_FOLDER_NEW_SYMBOLIC, - ICON_FONT_SELECT_SYMBOLIC, - ICON_FORMAT_INDENT_LESS, - ICON_FORMAT_INDENT_LESS_SYMBOLIC, - ICON_FORMAT_INDENT_MORE, - ICON_FORMAT_INDENT_MORE_SYMBOLIC, - ICON_FORMAT_JUSTIFY_CENTER, - ICON_FORMAT_JUSTIFY_CENTER_SYMBOLIC, - ICON_FORMAT_JUSTIFY_FILL, - ICON_FORMAT_JUSTIFY_FILL_SYMBOLIC, - ICON_FORMAT_JUSTIFY_LEFT, - ICON_FORMAT_JUSTIFY_LEFT_SYMBOLIC, - ICON_FORMAT_JUSTIFY_RIGHT, - ICON_FORMAT_JUSTIFY_RIGHT_SYMBOLIC, - ICON_FORMAT_TEXT_BOLD, - ICON_FORMAT_TEXT_BOLD_ES_SYMBOLIC, - ICON_FORMAT_TEXT_BOLD_FR_SYMBOLIC, - ICON_FORMAT_TEXT_BOLD_SYMBOLIC, - ICON_FORMAT_TEXT_CLEAR_FORMATTING_SYMBOLIC, - ICON_FORMAT_TEXT_DIRECTION_LTR_SYMBOLIC, - ICON_FORMAT_TEXT_HIGHLIGHT, - ICON_FORMAT_TEXT_ITALIC, - ICON_FORMAT_TEXT_ITALIC_ES_SYMBOLIC, - ICON_FORMAT_TEXT_ITALIC_SYMBOLIC, - ICON_FORMAT_TEXT_LARGER_SYMBOLIC, - ICON_FORMAT_TEXT_NONE, - ICON_FORMAT_TEXT_SMALLER_SYMBOLIC, - ICON_FORMAT_TEXT_STRIKETHROUGH, - ICON_FORMAT_TEXT_STRIKETHROUGH_FR_SYMBOLIC, - ICON_FORMAT_TEXT_STRIKETHROUGH_SYMBOLIC, - ICON_FORMAT_TEXT_UNDERLINE, - ICON_FORMAT_TEXT_UNDERLINE_FR_SYMBOLIC, - ICON_FORMAT_TEXT_UNDERLINE_SYMBOLIC, - ICON_GO_BOTTOM, - ICON_GO_BOTTOM_SYMBOLIC, - ICON_GO_DOWN, - ICON_GO_DOWN_SYMBOLIC, - ICON_GO_FIRST, - ICON_GO_FIRST_SYMBOLIC, - ICON_GO_HOME_SYMBOLIC, - ICON_GO_JUMP, - ICON_GO_JUMP_SYMBOLIC, - ICON_GO_LAST, - ICON_GO_LAST_SYMBOLIC, - ICON_GO_NEXT, - ICON_GO_NEXT_SYMBOLIC, - ICON_GO_PREVIOUS, - ICON_GO_PREVIOUS_SYMBOLIC, - ICON_GO_TOP, - ICON_GO_TOP_SYMBOLIC, - ICON_GO_UP, - ICON_GO_UP_SYMBOLIC, - ICON_HELP_ABOUT, - ICON_HELP_ABOUT_SYMBOLIC, - ICON_HELP_CONTENTS, - ICON_HELP_CONTENTS_SYMBOLIC, - ICON_HELP_INFO_SYMBOLIC, - ICON_IMAGE_ADJUST, - ICON_IMAGE_AUTO_ADJUST, - ICON_IMAGE_CROP, - ICON_IMAGE_CROP_SYMBOLIC, - ICON_IMAGE_RED_EYE, - ICON_IMAGE_RED_EYE_SYMBOLIC, - ICON_INSERT_IMAGE, - ICON_INSERT_IMAGE_SYMBOLIC, - ICON_INSERT_LINK, - ICON_INSERT_LINK_SYMBOLIC, - ICON_INSERT_OBJECT, - ICON_INSERT_OBJECT_SYMBOLIC, - ICON_INSERT_TEXT_SYMBOLIC, - ICON_LIST_ADD, - ICON_LIST_ADD_SYMBOLIC, - ICON_LIST_REMOVE, - ICON_LIST_REMOVE_SYMBOLIC, - ICON_MAIL_ARCHIVE, - ICON_MAIL_FORWARD, - ICON_MAIL_FORWARD_SYMBOLIC, - ICON_MAIL_MARK_IMPORTANT, - ICON_MAIL_MARK_IMPORTANT_SYMBOLIC, - ICON_MAIL_MARK_JUNK, - ICON_MAIL_MARK_JUNK_SYMBOLIC, - ICON_MAIL_MARK_NOTJUNK, - ICON_MAIL_MARK_NOTJUNK_SYMBOLIC, - ICON_MAIL_MESSAGE_NEW, - ICON_MAIL_MESSAGE_NEW_SYMBOLIC, - ICON_MAIL_MOVE, - ICON_MAIL_MOVE_SYMBOLIC, - ICON_MAIL_REPLY_ALL, - ICON_MAIL_REPLY_ALL_SYMBOLIC, - ICON_MAIL_REPLY_SENDER, - ICON_MAIL_REPLY_SENDER_SYMBOLIC, - ICON_MAIL_SEND, - ICON_MAIL_SEND_RECEIVE_SYMBOLIC, - ICON_MAIL_SEND_SYMBOLIC, - ICON_MARK_LOCATION_SYMBOLIC, - ICON_MEDIA_EJECT, - ICON_MEDIA_EJECT_SYMBOLIC, - ICON_MEDIA_EQ_SYMBOLIC, - ICON_MEDIA_PLAYBACK_PAUSE, - ICON_MEDIA_PLAYBACK_PAUSE_SYMBOLIC, - ICON_MEDIA_PLAYBACK_START, - ICON_MEDIA_PLAYBACK_START_SYMBOLIC, - ICON_MEDIA_PLAYBACK_STOP, - ICON_MEDIA_PLAYBACK_STOP_SYMBOLIC, - ICON_MEDIA_RECORD, - ICON_MEDIA_RECORD_SYMBOLIC, - ICON_MEDIA_SEEK_BACKWARD, - ICON_MEDIA_SEEK_BACKWARD_SYMBOLIC, - ICON_MEDIA_SEEK_FORWARD, - ICON_MEDIA_SEEK_FORWARD_SYMBOLIC, - ICON_MEDIA_SKIP_BACKWARD, - ICON_MEDIA_SKIP_FORWARD, - ICON_MEDIA_VIEW_SUBTITLES_SYMBOLIC, - ICON_NODE_ADD, - ICON_NODE_ALIGN_HORIZONTAL, - ICON_NODE_ALIGN_VERTICAL, - ICON_NODE_BREAK, - ICON_NODE_CUSP, - ICON_NODE_DELETE, - ICON_NODE_DELETE_SEGMENT, - ICON_NODE_DISTRIBUTE_HORIZONTAL, - ICON_NODE_DISTRIBUTE_VERTICAL, - ICON_NODE_INSERT, - ICON_NODE_JOIN, - ICON_NODE_JOIN_SEGMENT, - ICON_NODE_SMOOTH, - ICON_NODE_SYMMETRIC, - ICON_OBJECT_FLIP_HORIZONTAL, - ICON_OBJECT_FLIP_HORIZONTAL_SYMBOLIC, - ICON_OBJECT_FLIP_VERTICAL, - ICON_OBJECT_FLIP_VERTICAL_SYMBOLIC, - ICON_OBJECT_GROUP, - ICON_OBJECT_GROUP_SYMBOLIC, - ICON_OBJECT_INVERSE, - ICON_OBJECT_INVERSE_SYMBOLIC, - ICON_OBJECT_MERGE, - ICON_OBJECT_ROTATE_LEFT, - ICON_OBJECT_ROTATE_LEFT_SYMBOLIC, - ICON_OBJECT_ROTATE_RIGHT, - ICON_OBJECT_ROTATE_RIGHT_SYMBOLIC, - ICON_OBJECT_SELECT_SYMBOLIC, - ICON_OBJECT_STRAIGHTEN, - ICON_OBJECT_TO_PATH, - ICON_OBJECT_UNGROUP, - ICON_OBJECT_UNGROUP_SYMBOLIC, - ICON_OPEN_MENU, - ICON_OPEN_MENU_SYMBOLIC, - ICON_PAN_DOWN_SYMBOLIC, - ICON_PANE_HIDE_SYMBOLIC, - ICON_PAN_END_SYMBOLIC, - ICON_PANE_SHOW_SYMBOLIC, - ICON_PAN_START_SYMBOLIC, - ICON_PAN_UP_SYMBOLIC, - ICON_PATH_BREAK_APART, - ICON_PATH_BREAK_APART_SYMBOLIC, - ICON_PATH_COMBINE, - ICON_PATH_COMBINE_SYMBOLIC, - ICON_PATH_DIFFERENCE, - ICON_PATH_DIFFERENCE_SYMBOLIC, - ICON_PATH_DIVISION, - ICON_PATH_DIVISION_SYMBOLIC, - ICON_PATH_EXCLUSION, - ICON_PATH_EXCLUSION_SYMBOLIC, - ICON_PATH_INTERSECTION, - ICON_PATH_INTERSECTION_SYMBOLIC, - ICON_PATH_UNION, - ICON_PATH_UNION_SYMBOLIC, - ICON_PROCESS_STOP, - ICON_PROCESS_STOP_SYMBOLIC, - ICON_SEGMENT_CURVE, - ICON_SEGMENT_LINE, - ICON_SELECTION_ADD, - ICON_SELECTION_BOTTOM, - ICON_SELECTION_BOTTOM_SYMBOLIC, - ICON_SELECTION_CHECKED, - ICON_SELECTION_END_SYMBOLIC, - ICON_SELECTION_LOWER, - ICON_SELECTION_LOWER_SYMBOLIC, - ICON_SELECTION_RAISE, - ICON_SELECTION_RAISE_SYMBOLIC, - ICON_SELECTION_REMOVE, - ICON_SELECTION_START_SYMBOLIC, - ICON_SELECTION_TOP, - ICON_SELECTION_TOP_SYMBOLIC, - ICON_SEND_TO, - ICON_SEND_TO_SYMBOLIC, - ICON_STAR_NEW_SYMBOLIC, - ICON_STROKE_TO_PATH, - ICON_SYSTEM_LOCK_SCREEN, - ICON_SYSTEM_LOCK_SCREEN_SYMBOLIC, - ICON_SYSTEM_LOG_OUT, - ICON_SYSTEM_REBOOT, - ICON_SYSTEM_RUN, - ICON_SYSTEM_RUN_SYMBOLIC, - ICON_SYSTEM_SHUTDOWN, - ICON_SYSTEM_SHUTDOWN_SYMBOLIC, - ICON_SYSTEM_SUSPEND, - ICON_TAB_NEW_SYMBOLIC, - ICON_TAG_NEW, - ICON_TAG_NEW_SYMBOLIC, - ICON_TOOL_MEASURE, - ICON_TOOL_NODE_EDITOR, - ICON_TOOLS_CHECK_SPELLING_SYMBOLIC, - ICON_TOOLS_TIMER_SYMBOLIC, - ICON_VIEW_COLUMN_SYMBOLIC, - ICON_VIEW_CONTINUOUS_SYMBOLIC, - ICON_VIEW_DUAL_SYMBOLIC, - ICON_VIEW_FILTER_SYMBOLIC, - ICON_VIEW_FULLSCREEN_SYMBOLIC, - ICON_VIEW_GRID_SYMBOLIC, - ICON_VIEW_LIST_COMPACT_SYMBOLIC, - ICON_VIEW_LIST_IMAGES_SYMBOLIC, - ICON_VIEW_LIST_SYMBOLIC, - ICON_VIEW_LIST_VIDEO_SYMBOLIC, - ICON_VIEW_MORE_HORIZONTAL_SYMBOLIC, - ICON_VIEW_MORE_SYMBOLIC, - ICON_VIEW_PAGED_SYMBOLIC, - ICON_VIEW_PIN_SYMBOLIC, - ICON_VIEW_READER, - ICON_VIEW_READER_SYMBOLIC, - ICON_VIEW_REFRESH, - ICON_VIEW_REFRESH_SYMBOLIC, - ICON_VIEW_RESTORE_SYMBOLIC, - ICON_VIEW_SORT_ASCENDING_SYMBOLIC, - ICON_VIEW_SORT_DESCENDING_SYMBOLIC, - ICON_WINDOW_CLOSE, - ICON_WINDOW_CLOSE_SYMBOLIC, - ICON_WINDOW_MAXIMIZE_SYMBOLIC, - ICON_WINDOW_MINIMIZE_SYMBOLIC, - ICON_WINDOW_NEW, - ICON_WINDOW_NEW_SYMBOLIC, - ICON_WINDOW_POP_OUT_SYMBOLIC, - ICON_WINDOW_RESTORE_SYMBOLIC, - ICON_ZOOM_FIT_BEST, - ICON_ZOOM_FIT_BEST_SYMBOLIC, - ICON_ZOOM_IN, - ICON_ZOOM_IN_SYMBOLIC, - ICON_ZOOM_ORIGINAL, - ICON_ZOOM_ORIGINAL_SYMBOLIC, - ICON_ZOOM_OUT, - ICON_ZOOM_OUT_SYMBOLIC, - ICON_ACCESSORIES_CALCULATOR, - ICON_ACCESSORIES_CALCULATOR_SYMBOLIC, - ICON_ACCESSORIES_SCREENSHOT, - ICON_ACCESSORIES_TEXT_EDITOR, - ICON_ACCESSORIES_TEXT_EDITOR_SYMBOLIC, - ICON_APPLICATION_DEFAULT_ICON, - ICON_ARCHIVE_MANAGER, - ICON_INTERNET_CHAT, - ICON_INTERNET_CHAT_SYMBOLIC, - ICON_INTERNET_MAIL, - ICON_INTERNET_MAIL_SYMBOLIC, - ICON_INTERNET_NEWS_READER, - ICON_INTERNET_NEWS_READER_SYMBOLIC, - ICON_INTERNET_WEB_BROWSER, - ICON_INTERNET_WEB_BROWSER_SYMBOLIC, - ICON_MULTIMEDIA_AUDIO_PLAYER, - ICON_MULTIMEDIA_PHOTO_MANAGER, - ICON_MULTIMEDIA_VIDEO_PLAYER, - ICON_OFFICE_ADDRESS_BOOK, - ICON_OFFICE_CALENDAR, - ICON_OFFICE_CALENDAR_SYMBOLIC, - ICON_ONBOARD, - ICON_POSTSCRIPT_VIEWER, - ICON_PREFERENCES_DESKTOP, - ICON_PREFERENCES_DESKTOP_FONT, - ICON_SYSTEM_FILE_MANAGER, - ICON_SYSTEM_OS_INSTALLER, - ICON_SYSTEM_SOFTWARE_INSTALL, - ICON_SYSTEM_SOFTWARE_INSTALL_SYMBOLIC, - ICON_SYSTEM_SOFTWARE_UPDATE, - ICON_SYSTEM_SOFTWARE_UPDATE_SYMBOLIC, - ICON_SYSTEM_USERS, - ICON_SYSTEM_USERS_SYMBOLIC, - ICON_UTILITIES_SYSTEM_MONITOR, - ICON_UTILITIES_TERMINAL, - ICON_UTILITIES_TERMINAL_SYMBOLIC, - ICON_APPLICATIONS_ACCESSORIES, - ICON_APPLICATIONS_AUDIO_SYMBOLIC, - ICON_APPLICATIONS_DEVELOPMENT, - ICON_APPLICATIONS_DEVELOPMENT_SYMBOLIC, - ICON_APPLICATIONS_EDUCATION, - ICON_APPLICATIONS_EDUCATION_SYMBOLIC, - ICON_APPLICATIONS_ENGINEERING_SYMBOLIC, - ICON_APPLICATIONS_FONTS, - ICON_APPLICATIONS_GAMES, - ICON_APPLICATIONS_GAMES_SYMBOLIC, - ICON_APPLICATIONS_GRAPHICS, - ICON_APPLICATIONS_GRAPHICS_SYMBOLIC, - ICON_APPLICATIONS_INTERFACEDESIGN, - ICON_APPLICATIONS_INTERNET_SYMBOLIC, - ICON_APPLICATIONS_MULTIMEDIA, - ICON_APPLICATIONS_MULTIMEDIA_SYMBOLIC, - ICON_APPLICATIONS_OFFICE, - ICON_APPLICATIONS_OFFICE_SYMBOLIC, - ICON_APPLICATIONS_OTHER, - ICON_APPLICATIONS_OTHER_SYMBOLIC, - ICON_APPLICATIONS_PHOTOGRAPHY, - ICON_APPLICATIONS_SCIENCE, - ICON_APPLICATIONS_SCIENCE_SYMBOLIC, - ICON_APPLICATIONS_UTILITIES, - ICON_APPLICATIONS_UTILITIES_SYMBOLIC, - ICON_APPLICATIONS_VIDEO_SYMBOLIC, - ICON_BUG, - ICON_BUG_SYMBOLIC, - ICON_EMOJI_ACTIVITY_SYMBOLIC, - ICON_EMOJI_BODY_SYMBOLIC, - ICON_EMOJI_FOOD_SYMBOLIC, - ICON_EMOJI_NATURE_SYMBOLIC, - ICON_EMOJI_OBJECTS_SYMBOLIC, - ICON_EMOJI_TRAVEL_SYMBOLIC, - ICON_EVENT_BIRTHDAY_SYMBOLIC, - ICON_PREFERENCES_BLUETOOTH_SYMBOLIC, - ICON_PREFERENCES_COLOR, - ICON_PREFERENCES_COLOR_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_ACCESSIBILITY, - ICON_PREFERENCES_DESKTOP_ACCESSIBILITY_POINTING, - ICON_PREFERENCES_DESKTOP_ACCESSIBILITY_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_ACCESSIBILITY_ZOOM, - ICON_PREFERENCES_DESKTOP_APPLICATIONS, - ICON_PREFERENCES_DESKTOP_DISPLAY, - ICON_PREFERENCES_DESKTOP_DISPLAY_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_KEYBOARD, - ICON_PREFERENCES_DESKTOP_KEYBOARD_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_LOCALE, - ICON_PREFERENCES_DESKTOP_LOCALE_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_ONLINE_ACCOUNTS, - ICON_PREFERENCES_DESKTOP_ONLINE_ACCOUNTS_SYMBOLIC, - ICON_PREFERENCES_DESKTOP_PERIPHERALS, - ICON_PREFERENCES_DESKTOP_SOUND, - ICON_PREFERENCES_DESKTOP_WALLPAPER, - ICON_PREFERENCES_DESKTOP_WORKSPACES, - ICON_PREFERENCES_OTHER_SYMBOLIC, - ICON_PREFERENCES_SYSTEM, - ICON_PREFERENCES_SYSTEM_NETWORK, - ICON_PREFERENCES_SYSTEM_NETWORK_SYMBOLIC, - ICON_PREFERENCES_SYSTEM_NOTIFICATIONS, - ICON_PREFERENCES_SYSTEM_PARENTAL_CONTROLS, - ICON_PREFERENCES_SYSTEM_PARENTAL_CONTROL_SYMBOLIC, - ICON_PREFERENCES_SYSTEM_POWER, - ICON_PREFERENCES_SYSTEM_POWER_SYMBOLIC, - ICON_PREFERENCES_SYSTEM_PRIVACY_HOUSEKEEPING, - ICON_PREFERENCES_SYSTEM_SHARING, - ICON_PREFERENCES_SYSTEM_SHARING_SYMBOLIC, - ICON_PREFERENCES_SYSTEM_TIME, - ICON_PREFERENCES_SYSTEM_TIME_SYMBOLIC, - ICON_PREFERENCES_SYSTEM_WINDOWS, - ICON_AC_ADAPTER_SYMBOLIC, - ICON_AUDIO_CARD_SYMBOLIC, - ICON_AUDIO_HEADPHONES, - ICON_AUDIO_HEADPHONES_SYMBOLIC, - ICON_AUDIO_HEADSETS, - ICON_AUDIO_HEADSET_SYMBOLIC, - ICON_AUDIO_INPUT_MICROPHONE, - ICON_AUDIO_INPUT_MICROPHONE_SYMBOLIC, - ICON_AUDIO_SPEAKER_CENTER, - ICON_AUDIO_SPEAKER_CENTER_BACK, - ICON_AUDIO_SPEAKER_CENTER_BACK_TESTING, - ICON_AUDIO_SPEAKER_CENTER_TESTING, - ICON_AUDIO_SPEAKER_LEFT, - ICON_AUDIO_SPEAKER_LEFT_BACK, - ICON_AUDIO_SPEAKER_LEFT_BACK_TESTING, - ICON_AUDIO_SPEAKER_LEFT_SIDE, - ICON_AUDIO_SPEAKER_LEFT_SIDE_TESTING, - ICON_AUDIO_SPEAKER_LEFT_TESTING, - ICON_AUDIO_SPEAKER_RIGHT, - ICON_AUDIO_SPEAKER_RIGHT_BACK, - ICON_AUDIO_SPEAKER_RIGHT_BACK_TESTING, - ICON_AUDIO_SPEAKER_RIGHT_SIDE, - ICON_AUDIO_SPEAKER_RIGHT_SIDE_TESTING, - ICON_AUDIO_SPEAKER_RIGHT_TESTING, - ICON_AUDIO_SPEAKERS, - ICON_AUDIO_SPEAKERS_SYMBOLIC, - ICON_AUDIO_SUBWOOFER, - ICON_AUDIO_SUBWOOFER_TESTING, - ICON_BATTERY, - ICON_BATTERY_SYMBOLIC, - ICON_BLUETOOTH, - ICON_BLUETOOTH_SYMBOLIC, - ICON_CAMERA_PHOTO, - ICON_CAMERA_PHOTO_SYMBOLIC, - ICON_CAMERA_VIDEO, - ICON_CAMERA_VIDEO_SYMBOLIC, - ICON_CAMERA_WEB, - ICON_CAMERA_WEB_SYMBOLIC, - ICON_COLORIMETER_COLORHUG_SYMBOLIC, - ICON_COMPUTER_LAPTOP, - ICON_COMPUTER_LAPTOP_SYMBOLIC, - ICON_DISPLAY_PROJECTOR_SYMBOLIC, - ICON_DRIVE_HARDDISK, - ICON_DRIVE_HARDDISK_IEEE1394_SYMBOLIC, - ICON_DRIVE_HARDDISK_SOLIDSTATE, - ICON_DRIVE_HARDDISK_SOLIDSTATE_SYMBOLIC, - ICON_DRIVE_HARDDISK_SYMBOLIC, - ICON_DRIVE_MULTIDISK_SYMBOLIC, - ICON_DRIVE_OPTICAL_SYMBOLIC, - ICON_DRIVE_REMOVABLE_MEDIA, - ICON_DRIVE_REMOVABLE_MEDIA_SYMBOLIC, - ICON_DRIVE_REMOVABLE_MEDIA_USB, - ICON_FINGERPRINT, - ICON_FINGERPRINT_SYMBOLIC, - ICON_GNOME_DEV_PRINTER_NEW, - ICON_INPUT_DIALPAD_SYMBOLIC, - ICON_INPUT_GAMING, - ICON_INPUT_GAMING_SYMBOLIC, - ICON_INPUT_KEYBOARD, - ICON_INPUT_KEYBOARD_SYMBOLIC, - ICON_INPUT_MOUSE, - ICON_INPUT_MOUSE_SYMBOLIC, - ICON_INPUT_TABLET, - ICON_INPUT_TABLET_SYMBOLIC, - ICON_INPUT_TOUCHPAD, - ICON_INPUT_TOUCHPAD_SYMBOLIC, - ICON_MEDIA_FLASH_CF, - ICON_MEDIA_FLASH_MS, - ICON_MEDIA_FLASH_SYMBOLIC, - ICON_MEDIA_FLOPPY_SYMBOLIC, - ICON_MEDIA_MEMORY, - ICON_MEDIA_MEMORY_SD, - ICON_MEDIA_MEMORY_SEMBOLIC, - ICON_MEDIA_MEMORY_SM, - ICON_MEDIA_OPTICAL, - ICON_MEDIA_OPTICAL_SYMBOLIC, - ICON_MEDIA_REMOVABLE_SYMBOLIC, - ICON_MEDIA_TAPE_SYMBOLIC, - ICON_MEDIA_ZIP_SYMBOLIC, - ICON_MODEM, - ICON_MODEM_SYMBOLIC, - ICON_MULTIMEDIA_PLAYER, - ICON_MULTIMEDIA_PLAYER_SYMBOLIC, - ICON_NETWORK_CELLULAR, - ICON_NETWORK_FIREWALL, - ICON_NETWORK_VPN, - ICON_NETWORK_WIRED, - ICON_NETWORK_WIRELESS, - ICON_NETWORK_WIRELESS_HOTSPOT, - ICON_NM_DEVICE_WWAN, - ICON_PDA_SYMBOLIC, - ICON_PHONE, - ICON_PHONE_SYMBOLIC, - ICON_PRINTER, - ICON_PRINTER_NETWORK, - ICON_PRINTER_SYMBOLIC, - ICON_SCANNER, - ICON_SCANNER_SYMBOLIC, - ICON_TABLET, - ICON_TABLET_SYMBOLIC, - ICON_TV_SYMBOLIC, - ICON_UNINTERRUPTIBLE_POWER_SUPPLY, - ICON_UNINTERRUPTIBLE_POWER_SUPPLY_SYMBOLIC, - ICON_VIDEO_DISPLAY, - ICON_VIDEO_DISPLAY_SYMBOLIC, - ICON_EMBLEM_DEFAULT_SYMBOLIC, - ICON_EMBLEM_DOCUMENTS_SYMBOLIC, - ICON_EMBLEM_FAVORITE_SYMBOLIC, - ICON_EMBLEM_IMPORTANT_SYMBOLIC, - ICON_EMBLEM_MUSIC_SYMBOLIC, - ICON_EMBLEM_OK_SYMBOLIC, - ICON_EMBLEM_PHOTOS_SYMBOLIC, - ICON_EMBLEM_READONLY, - ICON_EMBLEM_SHARED_SYMBOLIC, - ICON_EMBLEM_SYMBOLIC_LINK, - ICON_EMBLEM_SYNCHRONIZED, - ICON_EMBLEM_SYNCHRONIZING_SYMBOLIC, - ICON_EMBLEM_UNREADABLE, - ICON_EMBLEM_VIDEOS_SYMBOLIC, - ICON_FACE_ANGEL, - ICON_FACE_ANGEL_SYMBOLIC, - ICON_FACE_ANGRY, - ICON_FACE_ANGRY_SYMBOLIC, - ICON_FACE_COOL, - ICON_FACE_COOL_SYMBOLIC, - ICON_FACE_CRYING, - ICON_FACE_CRYING_SYMBOLIC, - ICON_FACE_DEVILISH, - ICON_FACE_DEVILISH_SYMBOLIC, - ICON_FACE_EMBARRASSED, - ICON_FACE_EMBARRASSED_SYMBOLIC, - ICON_FACE_HEART, - ICON_FACE_HEART_BROKEN, - ICON_FACE_HEART_BROKEN_SYMBOLIC, - ICON_FACE_HEART_SYMBOLIC, - ICON_FACE_KISS, - ICON_FACE_KISS_SYMBOLIC, - ICON_FACE_LAUGH, - ICON_FACE_LAUGH_SYMBOLIC, - ICON_FACE_MONKEY_SYMBOLIC, - ICON_FACE_PLAIN, - ICON_FACE_PLAIN_SYMBOLIC, - ICON_FACE_RASPBERRY, - ICON_FACE_RASPBERRY_SYMBOLIC, - ICON_FACE_SAD, - ICON_FACE_SAD_SYMBOLIC, - ICON_FACE_SICK, - ICON_FACE_SICK_SYMBOLIC, - ICON_FACE_SMILE, - ICON_FACE_SMILE_BIG, - ICON_FACE_SMILE_BIG_SYMBOLIC, - ICON_FACE_SMILE_SYMBOLIC, - ICON_FACE_SMIRK, - ICON_FACE_SMIRK_SYMBOLIC, - ICON_FACE_SURPRISE, - ICON_FACE_SURPRISE_SYMBOLIC, - ICON_FACE_TIRED, - ICON_FACE_TIRED_SYMBOLIC, - ICON_FACE_UNCERTAIN, - ICON_FACE_UNCERTAIN_SYMBOLIC, - ICON_FACE_WINK, - ICON_FACE_WINK_SYMBOLIC, - ICON_FACE_WORRIED, - ICON_FACE_WORRIED_SYMBOLIC, - ICON_APPLICATION_CERTIFICATE_SYMBOLIC, - ICON_APPLICATION_EPUB_ZIP, - ICON_APPLICATION_ILLUSTRATOR, - ICON_APPLICATION_JAVASCRIPT, - ICON_APPLICATION_MSWORD, - ICON_APPLICATION_OCTET_STREAM, - ICON_APPLICATION_PDF, - ICON_APPLICATION_PGP, - ICON_APPLICATION_RSS_XML_SYMBOLIC, - ICON_APPLICATION_VND, - ICON_APPLICATION_X_APPLIANCE_SYMBOLIC, - ICON_APPLICATION_X_BITTORRENT, - ICON_APPLICATION_X_CD_IMAGE, - ICON_APPLICATION_X_DESKTOP, - ICON_APPLICATION_X_EXECUTABLE_SYMBOLIC, - ICON_APPLICATION_X_FICTIONBOOK_XML, - ICON_APPLICATION_X_FIRMWARE, - ICON_APPLICATION_X_FIRMWARE_SYMBOLIC, - ICON_APPLICATION_X_FLASH_VIDEO, - ICON_APPLICATION_X_MS_DOS_EXECUTABLE, - ICON_APPLICATION_X_PARTIAL_DOWNLOAD, - ICON_APPLICATION_X_PHP, - ICON_APPLICATION_X_RUBY, - ICON_AUDIO_X_GENERIC, - ICON_AUDIO_X_GENERIC_SYMBOLIC, - ICON_AUDIO_X_PLAYLIST, - ICON_EXTENSION, - ICON_FONT_X_GENERIC, - ICON_FONT_X_GENERIC_SYMBOLIC, - ICON_IMAGE_VND, - ICON_IMAGE_X_GENERIC, - ICON_IMAGE_X_GENERIC_SYMBOLIC, - ICON_IMAGE_X_XCF, - ICON_INTERNET_FEED, - ICON_MODEL, - ICON_OFFICE_CONTACT, - ICON_OFFICE_DATABASE, - ICON_PACKAGE_X_GENERIC, - ICON_PACKAGE_X_GENERIC_SYMBOLIC, - ICON_PAYMENT_CARD, - ICON_PAYMENT_CARD_AMEX, - ICON_PAYMENT_CARD_DINERS_CLUB, - ICON_PAYMENT_CARD_DISCOVER, - ICON_PAYMENT_CARD_JCB, - ICON_PAYMENT_CARD_MASTERCARD, - ICON_PAYMENT_CARD_SYMBOLIC, - ICON_PAYMENT_CARD_UNIONPAY, - ICON_PAYMENT_CARD_VISA, - ICON_TEXT, - ICON_TEXT_CSS, - ICON_TEXT_HTML, - ICON_TEXT_HTML_SYMBOLIC, - ICON_TEXT_MARKDOWN, - ICON_TEXT_X_BIBTEX, - ICON_TEXT_X_CHANGELOG, - ICON_TEXT_X_CHDR, - ICON_TEXT_X_COPYING, - ICON_TEXT_X_COPYING_SYMBOLIC, - ICON_TEXT_X_CSRC, - ICON_TEXT_X_GENERIC_SYMBOLIC, - ICON_TEXT_X_GENERIC_TEMPLATE, - ICON_TEXT_X_GETTEXT_TRANSLATION, - ICON_TEXT_X_GETTEXT_TRANSLATION_TEMPLATE, - ICON_TEXT_X_GO, - ICON_TEXT_X_INSTALL, - ICON_TEXT_X_MAKEFILE, - ICON_TEXT_X_PREVIEW, - ICON_TEXT_X_PYTHON, - ICON_TEXT_X_README, - ICON_TEXT_X_SASS, - ICON_TEXT_X_SCRIPT, - ICON_TEXT_X_SSA, - ICON_TEXT_X_TEX, - ICON_TEXT_X_VALA, - ICON_UNKNOWN, - ICON_VIDEO_X_GENERIC, - ICON_VIDEO_X_GENERIC_SYMBOLIC, - ICON_X_OFFICE_ADDRESS_BOOK_SYMBOLIC, - ICON_X_OFFICE_DOCUMENT, - ICON_X_OFFICE_DOCUMENT_SYMBOLIC, - ICON_X_OFFICE_DOCUMENT_TEMPLATE, - ICON_X_OFFICE_DRAWING, - ICON_X_OFFICE_DRAWING_SYMBOLIC, - ICON_X_OFFICE_DRAWING_TEMPLATE, - ICON_X_OFFICE_PRESENTATION, - ICON_X_OFFICE_PRESENTATION_SYMBOLIC, - ICON_X_OFFICE_PRESENTATION_TEMPLATE, - ICON_X_OFFICE_SPREADSHEET, - ICON_X_OFFICE_SPREADSHEET_SYMBOLIC, - ICON_X_OFFICE_SPREADSHEET_TEMPLATE, - ICON_BOOKMARK_MISSING, - ICON_DISTRIBUTOR_LOGO, - ICON_DISTRIBUTOR_LOGO_SYMBOLIC, - ICON_FOLDER, - ICON_FOLDER_DOCUMENTS, - ICON_FOLDER_DOCUMENTS_OPEN, - ICON_FOLDER_DOCUMENTS_SYMBOLIC, - ICON_FOLDER_DOWNLOAD, - ICON_FOLDER_DOWNLOAD_OPEN, - ICON_FOLDER_DOWNLOAD_SYMBOLIC, - ICON_FOLDER_MUSIC, - ICON_FOLDER_MUSIC_OPEN, - ICON_FOLDER_MUSIC_SYMBOLIC, - ICON_FOLDER_OPEN, - ICON_FOLDER_PICTURES, - ICON_FOLDER_PICTURES_OPEN, - ICON_FOLDER_PICTURES_SYMBOLIC, - ICON_FOLDER_PUBLICSHARE, - ICON_FOLDER_PUBLICSHARE_OPEN, - ICON_FOLDER_PUBLICSHARE_SYMBOLIC, - ICON_FOLDER_RECENT, - ICON_FOLDER_RECENT_SYMBOLIC, - ICON_FOLDER_REMOTE, - ICON_FOLDER_REMOTE_OPEN, - ICON_FOLDER_SAVED_SEARCH, - ICON_FOLDER_SYMBOLIC, - ICON_FOLDER_TAG, - ICON_FOLDER_TEMPLATES, - ICON_FOLDER_TEMPLATES_OPEN, - ICON_FOLDER_TEMPLATES_SYMBOLIC, - ICON_FOLDER_VIDEOS, - ICON_FOLDER_VIDEOS_OPEN, - ICON_FOLDER_VIDEOS_SYMBOLIC, - ICON_INTERNET_RADIO, - ICON_INTERNET_RADIO_SYMBOLIC, - ICON_LIBRARY_AUDIOBOOK, - ICON_LIBRARY_PLACES, - ICON_LIBRARY_PODCAST, - ICON_MAIL_INBOX, - ICON_MAIL_INBOX_SYMBOLIC, - ICON_MAIL_MAILBOX, - ICON_MAIL_MAILBOX_SYMBOLIC, - ICON_MAIL_OUTBOX, - ICON_MAIL_OUTBOX_SYMBOLIC, - ICON_NETWORK_SERVER_SYMBOLIC, - ICON_PLAYLIST, - ICON_PLAYLIST_AUTOMATIC, - ICON_PLAYLIST_QUEUE, - ICON_PLAYLIST_QUEUE_SYMBOLIC, - ICON_PLAYLIST_SIMILAR, - ICON_PLAYLIST_SYMBOLIC, - ICON_TAG_SYMBOLIC, - ICON_USER_BOOKMARKS_SYMBOLIC, - ICON_USER_HOME, - ICON_USER_HOME_OPEN, - ICON_USER_HOME_SYMBOLIC, - ICON_USER_TRASH, - ICON_USER_TRASH_FULL, - ICON_USER_TRASH_SYMBOLIC, - ICON_AIRPLANE_MODE, - ICON_AIRPLANE_MODE_SYMBOLIC, - ICON_ALARM_SYMBOLIC, - ICON_APPOINTMENT_MISSED, - ICON_APPOINTMENT_MISSED_SYMBOLIC, - ICON_APPOINTMENT_SOON, - ICON_APPOINTMENT_SOON_SYMBOLIC, - ICON_AUDIO_VOLUME_HIGH_SYMBOLIC, - ICON_AUDIO_VOLUME_LOW_SYMBOLIC, - ICON_AUDIO_VOLUME_MEDIUM_SYMBOLIC, - ICON_AUDIO_VOLUME_MUTED_BLOCKING_SYMBOLIC, - ICON_AUDIO_VOLUME_MUTED_SYMBOLIC, - ICON_AVATAR_DEFAULT, - ICON_AVATAR_DEFAULT_SYMBOLIC, - ICON_BATTERY_AC_ADAPTER, - ICON_BATTERY_AC_ADAPTER_SYMBOLIC, - ICON_BATTERY_CAUTION, - ICON_BATTERY_CAUTION_CHARGING, - ICON_BATTERY_CAUTION_CHARGING_SYMBOLIC, - ICON_BATTERY_CAUTION_SYMBOLIC, - ICON_BATTERY_EMPTY, - ICON_BATTERY_EMPTY_CHARGING, - ICON_BATTERY_EMPTY_CHARGING_SYMBOLIC, - ICON_BATTERY_EMPTY_SYMBOLIC, - ICON_BATTERY_FULL, - ICON_BATTERY_FULL_CHARGED, - ICON_BATTERY_FULL_CHARGED_SYMBOLIC, - ICON_BATTERY_FULL_CHARGING, - ICON_BATTERY_FULL_CHARGING_SYMBOLIC, - ICON_BATTERY_FULL_SYMBOLIC, - ICON_BATTERY_GOOD, - ICON_BATTERY_GOOD_CHARGING, - ICON_BATTERY_GOOD_CHARGING_SYMBOLIC, - ICON_BATTERY_GOOD_SYMBOLIC, - ICON_BATTERY_LOW, - ICON_BATTERY_LOW_CHARGING, - ICON_BATTERY_LOW_CHARGING_SYMBOLIC, - ICON_BATTERY_LOW_SYMBOLIC, - ICON_BATTERY_MISSING, - ICON_BATTERY_MISSING_SYMBOLIC, - ICON_BLUETOOTH_ACTIVE_SYMBOLIC, - ICON_BLUETOOTH_DISABLED, - ICON_BLUETOOTH_DISABLED_10_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_20_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_30_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_40_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_50_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_60_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_70_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_80_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_90_SYMBOLIC, - ICON_BLUETOOTH_DISABLED_SYMBOLIC, - ICON_BLUETOOTH_PAIRED_SYMBOLIC, - ICON_CALL_MISSED_SYMBOLIC, - ICON_CHANGES_ALLOW, - ICON_CHANGES_ALLOW_SYMBOLIC, - ICON_CHANGES_PREVENT_SYMBOLIC, - ICON_CHANNEL_INSECURE_SYMBOLIC, - ICON_CHANNEL_SECURE_SYMBOLIC, - ICON_CHECK_ACTIVE_SYMBOLIC, - ICON_CHECKBOX_CHECKED_SYMBOLIC, - ICON_CHECKBOX_MIXED_SYMBOLIC, - ICON_CHECKBOX_SYMBOLIC, - ICON_CHECK_MIXED_SYMBOLIC, - ICON_COMPUTER_FAIL_SYMBOLIC, - ICON_CONTENT_LOADING_SYMBOLIC, - ICON_DAYTIME_SUNRISE_SYMBOLIC, - ICON_DAYTIME_SUNSET_SYMBOLIC, - ICON_DIALOG_ERROR, - ICON_DIALOG_ERROR_SYMBOLIC, - ICON_DIALOG_INFORMATION, - ICON_DIALOG_INFORMATION_SYMBOLIC, - ICON_DIALOG_PASSWORD, - ICON_DIALOG_PASSWORD_SYMBOLIC, - ICON_DIALOG_WARNING, - ICON_DIALOG_WARNING_SYMBOLIC, - ICON_DISPLAY_BRIGHTNESS_SYMBOLIC, - ICON_FOLDER_OPEN_SYMBOLIC, - ICON_FOLDER_VISITING_SYMBOLIC, - ICON_IMAGE_LOADING, - ICON_IMAGE_MISSING, - ICON_INPUT_KEYBOARD_CAPSLOCK_SYMBOLIC, - ICON_INPUT_KEYBOARD_NUMLOCK_SYMBOLIC, - ICON_KEYBOARD_BRIGHTNESS_SYMBOLIC, - ICON_LOCATION_ACTIVE_SYMBOLIC, - ICON_LOCATION_DISABLED_SYMBOLIC, - ICON_LOCATION_INACTIVE_SYMBOLIC, - ICON_LOCKED, - ICON_MAIL_ATTACHMENT_SYMBOLIC, - ICON_MAIL_FORWARDED_SYMBOLIC, - ICON_MAIL_IMPORTANT_SYMBOLIC, - ICON_MAIL_READ_SYMBOLIC, - ICON_MAIL_REPLIED_SYMBOLIC, - ICON_MAIL_UNREAD, - ICON_MAIL_UNREAD_SYMBOLIC, - ICON_MEDIA_PLAYLIST_CONSECUTIVE_SYMBOLIC, - ICON_MEDIA_PLAYLIST_NO_REPEAT_SYMBOLIC, - ICON_MEDIA_PLAYLIST_REPEAT, - ICON_MEDIA_PLAYLIST_REPEAT_SONG_SYMBOLIC, - ICON_MEDIA_PLAYLIST_REPEAT_SYMBOLIC, - ICON_MEDIA_PLAYLIST_SHUFFLE_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_HIGH_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_LOW_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MEDIUM_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_10_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_20_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_30_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_40_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_50_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_60_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_70_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_80_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_90_SYMBOLIC, - ICON_MICROPHONE_SENSITIVITY_MUTED_SYMBOLIC, - ICON_NETWORK_CELLULAR_ACQUIRING_SYMBOLIC, - ICON_NETWORK_CELLULAR_CONNECTED_SYMBOLIC, - ICON_NETWORK_CELLULAR_NO_ROUTE_SYMBOLIC, - ICON_NETWORK_CELLULAR_OFFLINE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_EXCELLENT_SECURE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_EXCELLENT_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_GOOD_SECURE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_GOOD_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_NONE_SECURE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_NONE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_OK_SECURE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_OK_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_WEAK_SECURE_SYMBOLIC, - ICON_NETWORK_CELLULAR_SIGNAL_WEAK_SYMBOLIC, - ICON_NETWORK_ERROR, - ICON_NETWORK_ERROR_SYMBOLIC, - ICON_NETWORK_IDLE, - ICON_NETWORK_OFFLINE_SYMBOLIC, - ICON_NETWORK_VPN_ACQUIRING_SYMBOLIC, - ICON_NETWORK_VPN_LOCK_SYMBOLIC, - ICON_NETWORK_VPN_SYMBOLIC, - ICON_NETWORK_WIRED_ACQUIRING_SYMBOLIC, - ICON_NETWORK_WIRED_DISCONNECTED, - ICON_NETWORK_WIRED_NO_ROUTE_SYMBOLIC, - ICON_NETWORK_WIRED_OFFLINE_SYMBOLIC, - ICON_NETWORK_WIRED_SYMBOLIC, - ICON_NETWORK_WIRELESS_ACQUIRING_SYMBOLIC, - ICON_NETWORK_WIRELESS_CONNECTED_SYMBOLIC, - ICON_NETWORK_WIRELESS_ENCRYPTED_SYMBOLIC, - ICON_NETWORK_WIRELESS_HOTSPOT_SYMBOLIC, - ICON_NETWORK_WIRELESS_NO_ROUTE_SYMBOLIC, - ICON_NETWORK_WIRELESS_OFFLINE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_EXCELLENT, - ICON_NETWORK_WIRELESS_SIGNAL_EXCELLENT_SECURE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_EXCELLENT_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_GOOD, - ICON_NETWORK_WIRELESS_SIGNAL_GOOD_SECURE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_GOOD_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_NONE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_OK, - ICON_NETWORK_WIRELESS_SIGNAL_OK_SECURE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_OK_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_WEAK, - ICON_NETWORK_WIRELESS_SIGNAL_WEAK_SECURE_SYMBOLIC, - ICON_NETWORK_WIRELESS_SIGNAL_WEAK_SYMBOLIC, - ICON_NETWORK_WIRELESS_SYMBOLIC, - ICON_NIGHT_LIGHT, - ICON_NIGHT_LIGHT_DISABLED_10_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_20_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_30_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_40_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_50_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_60_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_70_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_80_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_90_SYMBOLIC, - ICON_NIGHT_LIGHT_DISABLED_SYMBOLIC, - ICON_NIGHT_LIGHT_SYMBOLIC, - ICON_NM_NO_CONNECTION, - ICON_NM_SIGNAL_0, - ICON_NM_SIGNAL_0_SECURE, - ICON_NM_SIGNAL_100, - ICON_NM_SIGNAL_100_SECURE, - ICON_NM_SIGNAL_25, - ICON_NM_SIGNAL_25_SECURE, - ICON_NM_SIGNAL_50, - ICON_NM_SIGNAL_50_SECURE, - ICON_NM_SIGNAL_75, - ICON_NM_SIGNAL_75_SECURE, - ICON_NM_VPN_ACTIVE_LOCK, - ICON_NM_VPN_LOCK, - ICON_NON_STARRED, - ICON_NON_STARRED_SYMBOLIC, - ICON_NOTIFICATION_AUDIO_VOLUME_HIGH, - ICON_NOTIFICATION_AUDIO_VOLUME_LOW, - ICON_NOTIFICATION_AUDIO_VOLUME_MEDIUM, - ICON_NOTIFICATION_AUDIO_VOLUME_MUTED, - ICON_NOTIFICATION_DEVICE_EJECT, - ICON_NOTIFICATION_DISABLED, - ICON_NOTIFICATION_DISABLED_10_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_20_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_30_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_40_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_50_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_60_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_70_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_80_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_90_SYMBOLIC, - ICON_NOTIFICATION_DISABLED_SYMBOLIC, - ICON_NOTIFICATION_DISPLAY_BRIGHTNESS, - ICON_NOTIFICATION_KEYBOARD_BRIGHTNESS, - ICON_NOTIFICATION_NETWORK_ETHERNET_DISCONNECTED, - ICON_NOTIFICATION_NETWORK_WIRED, - ICON_NOTIFICATION_NETWORK_WIRELESS, - ICON_NOTIFICATION_NETWORK_WIRELESS_DISCONNECTED, - ICON_NOTIFICATION_NETWORK_WIRELESS_DISCONNECTED_SYMBOLIC, - ICON_NOTIFICATION_NETWORK_WIRELESS_SYMBOLIC, - ICON_NOTIFICATION_NEW_10_SYMBOLIC, - ICON_NOTIFICATION_NEW_20_SYMBOLIC, - ICON_NOTIFICATION_NEW_30_SYMBOLIC, - ICON_NOTIFICATION_NEW_40_SYMBOLIC, - ICON_NOTIFICATION_NEW_50_SYMBOLIC, - ICON_NOTIFICATION_NEW_60_SYMBOLIC, - ICON_NOTIFICATION_NEW_70_SYMBOLIC, - ICON_NOTIFICATION_NEW_80_SYMBOLIC, - ICON_NOTIFICATION_NEW_90_SYMBOLIC, - ICON_NOTIFICATION_NEW_SYMBOLIC, - ICON_NOTIFICATION_SYMBOLIC, - ICON_PAGER_CHECKED_SYMBOLIC, - ICON_PRINTER_ERROR, - ICON_PRINTER_ERROR_SYMBOLIC, - ICON_PRINTER_PRINTING_SYMBOLIC, - ICON_PRINTER_WARNING_SYMBOLIC, - ICON_PROCESS_COMPLETED, - ICON_PROCESS_COMPLETED_SYMBOLIC, - ICON_PROCESS_ERROR_SYMBOLIC, - ICON_PROCESS_WORKING_SYMBOLIC, - ICON_RADIO_CHECKED_SYMBOLIC, - ICON_RADIO_MIXED_SYMBOLIC, - ICON_RADIO_SYMBOLIC, - ICON_ROTATION_ALLOWED_SYMBOLIC, - ICON_ROTATION_LOCKED_SYMBOLIC, - ICON_SECURITY_HIGH, - ICON_SECURITY_HIGH_SYMBOLIC, - ICON_SECURITY_LOW, - ICON_SECURITY_LOW_SYMBOLIC, - ICON_SECURITY_MEDIUM, - ICON_SECURITY_MEDIUM_SYMBOLIC, - ICON_SEMI_STARRED, - ICON_SEMI_STARRED_SYMBOLIC, - ICON_SOFTWARE_UPDATE_AVAILABLE_SYMBOLIC, - ICON_SOFTWARE_UPDATE_URGENT_SYMBOLIC, - ICON_STARRED, - ICON_STARRED_SYMBOLIC, - ICON_TASK_DUE_SYMBOLIC, - ICON_TASK_PAST_DUE_SYMBOLIC, - ICON_TOUCHPAD_DISABLED_SYMBOLIC, - ICON_USER_AVAILABLE, - ICON_USER_AVAILABLE_SYMBOLIC, - ICON_USER_AWAY, - ICON_USER_AWAY_SYMBOLIC, - ICON_USER_BUSY, - ICON_USER_BUSY_SYMBOLIC, - ICON_USER_IDLE_SYMBOLIC, - ICON_USER_INVISIBLE, - ICON_USER_INVISIBLE_SYMBOLIC, - ICON_USER_OFFLINE, - ICON_USER_OFFLINE_SYMBOLIC, - ICON_USER_STATUS_PENDING_SYMBOLIC, - ICON_USER_TRASH_FULL_SYMBOLIC, - ICON_USER_TYPING, - ICON_VIEW_PRIVATE, - ICON_VIEW_PRIVATE_SYMBOLIC, - ICON_VIEW_WRAPPED_SYMBOLIC, - ICON_WEATHER_CLEAR_NIGHT_SYMBOLIC, - ICON_WEATHER_CLEAR_SYMBOLIC, - ICON_WEATHER_FEW_CLOUDS_NIGHT_SYMBOLIC, - ICON_WEATHER_FEW_CLOUDS_SYMBOLIC, - ICON_WEATHER_FOG_NIGHT_SYMBOLIC, - ICON_WEATHER_FOG_SYMBOLIC, - ICON_WEATHER_OVERCAST_NIGHT_SYMBOLIC, - ICON_WEATHER_OVERCAST_SYMBOLIC, - ICON_WEATHER_SEVERE_ALERT_SYMBOLIC, - ICON_WEATHER_SHOWERS_NIGHT_SYMBOLIC, - ICON_WEATHER_SHOWERS_SCATTERED_NIGHT_SYMBOLIC, - ICON_WEATHER_SHOWERS_SCATTERED_SYMBOLIC, - ICON_WEATHER_SHOWERS_SYMBOLIC, - ICON_WEATHER_SNOW_NIGHT_SYMBOLIC, - ICON_WEATHER_SNOW_SYMBOLIC, - ICON_WEATHER_STORM_NIGHT_SYMBOLIC, - ICON_WEATHER_STORM_SYMBOLIC, - ICON_WEATHER_STORM_TORNADO_NIGHT_SYMBOLIC, - ICON_WEATHER_STORM_TORNADO_SYMBOLIC, - ICON_WEATHER_WINDY_SYMBOLIC, -} -using FatalError :: enum i32 { - FATAL_ERROR_INVALID_BUFFER, - FATAL_ERROR_UNKNOWN_SYSCALL, - FATAL_ERROR_INVALID_MEMORY_REGION, - FATAL_ERROR_MEMORY_REGION_LOCKED_BY_KERNEL, - FATAL_ERROR_PATH_LENGTH_EXCEEDS_LIMIT, - FATAL_ERROR_INVALID_HANDLE, - FATAL_ERROR_MUTEX_NOT_ACQUIRED_BY_THREAD, - FATAL_ERROR_MUTEX_ALREADY_ACQUIRED, - FATAL_ERROR_SHARED_MEMORY_REGION_TOO_LARGE, - FATAL_ERROR_INCORRECT_FILE_ACCESS, - FATAL_ERROR_TOO_MANY_WAIT_OBJECTS, - FATAL_ERROR_INCORRECT_NODE_TYPE, - FATAL_ERROR_PROCESSOR_EXCEPTION, - FATAL_ERROR_UNKNOWN, - FATAL_ERROR_RECURSIVE_BATCH, - FATAL_ERROR_CORRUPT_HEAP, - FATAL_ERROR_CORRUPT_LINKED_LIST, - FATAL_ERROR_SPINLOCK_NOT_ACQUIRED, - FATAL_ERROR_UNKNOWN_SNAPSHOT_TYPE, - FATAL_ERROR_PROCESS_ALREADY_ATTACHED, - FATAL_ERROR_INSUFFICIENT_PERMISSIONS, - FATAL_ERROR_ABORT, - FATAL_ERROR_COUNT, -} -using SyscallType :: enum i32 { - SYSCALL_ALLOCATE, - SYSCALL_FREE, - SYSCALL_SHARE_MEMORY, - SYSCALL_MAP_OBJECT, - SYSCALL_OPEN_SHARED_MEMORY, - SYSCALL_MEMORY_COMMIT, - SYSCALL_CREATE_PROCESS, - SYSCALL_GET_CREATION_ARGUMENT, - SYSCALL_TERMINATE_THREAD, - SYSCALL_CREATE_THREAD, - SYSCALL_WAIT, - SYSCALL_TERMINATE_PROCESS, - SYSCALL_CREATE_EVENT, - SYSCALL_SET_EVENT, - SYSCALL_RESET_EVENT, - SYSCALL_POLL_EVENT, - SYSCALL_PAUSE_PROCESS, - SYSCALL_CRASH_PROCESS, - SYSCALL_GET_THREAD_ID, - SYSCALL_GET_PROCESS_STATE, - SYSCALL_YIELD_SCHEDULER, - SYSCALL_SLEEP, - SYSCALL_OPEN_PROCESS, - SYSCALL_SET_TLS, - SYSCALL_GET_TLS, - SYSCALL_TIMER_SET, - SYSCALL_TIMER_CREATE, - SYSCALL_GET_PROCESS_STATUS, - SYSCALL_EVENT_FORWARD, - SYSCALL_EVENT_SINK_CREATE, - SYSCALL_EVENT_SINK_POP, - SYSCALL_EVENT_SINK_PUSH, - SYSCALL_AUDIO_STREAM_OPEN, - SYSCALL_AUDIO_STREAM_NOTIFY, - SYSCALL_GET_MESSAGE, - SYSCALL_POST_MESSAGE, - SYSCALL_POST_MESSAGE_REMOTE, - SYSCALL_WAIT_MESSAGE, - SYSCALL_GET_CURSOR_POSITION, - SYSCALL_SET_CURSOR_POSITION, - SYSCALL_GAME_CONTROLLER_STATE_POLL, - SYSCALL_COPY, - SYSCALL_GET_CLIPBOARD_HEADER, - SYSCALL_PASTE_TEXT, - SYSCALL_START_EYEDROP, - SYSCALL_SET_SCREEN_WORK_AREA, - SYSCALL_GET_SCREEN_WORK_AREA, - SYSCALL_GET_SCREEN_BOUNDS, - SYSCALL_FORCE_SCREEN_UPDATE, - SYSCALL_SET_WINDOW_FRAME_BITMAP, - SYSCALL_WINDOW_CREATE, - SYSCALL_WINDOW_CLOSE, - SYSCALL_WINDOW_REDRAW, - SYSCALL_WINDOW_MOVE, - SYSCALL_WINDOW_GET_ID, - SYSCALL_WINDOW_GET_BOUNDS, - SYSCALL_WINDOW_SET_SOLID, - SYSCALL_WINDOW_SET_BITS, - SYSCALL_WINDOW_SET_OPAQUE_BOUNDS, - SYSCALL_WINDOW_SET_BLUR_BOUNDS, - SYSCALL_WINDOW_SET_ALPHA, - SYSCALL_WINDOW_SET_FOCUSED, - SYSCALL_WINDOW_SET_METADATA, - SYSCALL_WINDOW_SET_EMBED, - SYSCALL_WINDOW_SET_CURSOR, - SYSCALL_WINDOW_SET_OBJECT, - SYSCALL_WINDOW_SET_EMBED_OWNER, - SYSCALL_WINDOW_SET_RESIZE_CLEAR_COLOR, - SYSCALL_OPEN_NODE, - SYSCALL_OPEN_NODE_RELATIVE, - SYSCALL_READ_FILE_SYNC, - SYSCALL_WRITE_FILE_SYNC, - SYSCALL_RESIZE_FILE, - SYSCALL_REFRESH_NODE_INFORMATION, - SYSCALL_ENUMERATE_DIRECTORY_CHILDREN, - SYSCALL_DELETE_NODE, - SYSCALL_MOVE_NODE, - SYSCALL_DIRECTORY_MONITOR, - SYSCALL_FILE_CONTROL, - SYSCALL_DOMAIN_NAME_RESOLVE, - SYSCALL_ECHO_REQUEST, - SYSCALL_CONNECTION_OPEN, - SYSCALL_CONNECTION_POLL, - SYSCALL_CONNECTION_NOTIFY, - SYSCALL_READ_CONSTANT_BUFFER, - SYSCALL_SHARE_CONSTANT_BUFFER, - SYSCALL_CREATE_CONSTANT_BUFFER, - SYSCALL_MAILSLOT_SEND_DATA, - SYSCALL_MAILSLOT_SEND_MESSAGE, - SYSCALL_MAILSLOT_SHARE, - SYSCALL_PIPE_CREATE, - SYSCALL_PIPE_WRITE, - SYSCALL_PIPE_READ, - SYSCALL_USER_GET_HOME_FOLDER, - SYSCALL_USER_LOGIN, - SYSCALL_GET_SYSTEM_CONSTANTS, - SYSCALL_TAKE_SYSTEM_SNAPSHOT, - SYSCALL_SET_SYSTEM_CONSTANT, - SYSCALL_GET_SYSTEM_INFORMATION, - SYSCALL_SYSTEM_CONFIGURATION_WRITE, - SYSCALL_SYSTEM_CONFIGURATION_READ, - SYSCALL_PRINT, - SYSCALL_CLOSE_HANDLE, - SYSCALL_BATCH, - SYSCALL_SHUTDOWN, - SYSCALL_POSIX, - SYSCALL_START_PROGRAM, - SYSCALL_DEBUG_COMMAND, - SYSCALL_COUNT, -} -using MessageType :: enum i32 { - MSG_WM_START = 0x1000, - MSG_MOUSE_MOVED = 0x1001, - MSG_WINDOW_ACTIVATED = 0x1002, - MSG_WINDOW_DEACTIVATED = 0x1003, - MSG_WINDOW_DESTROYED = 0x1004, - MSG_MOUSE_EXIT = 0x1006 , - MSG_WINDOW_RESIZED = 0x1007, - MSG_MOUSE_LEFT_PRESSED = 0x1008 , - MSG_MOUSE_LEFT_RELEASED = 0x1009, - MSG_MOUSE_RIGHT_PRESSED = 0x100A, - MSG_MOUSE_RIGHT_RELEASED = 0x100B, - MSG_MOUSE_MIDDLE_PRESSED = 0x100C, - MSG_MOUSE_MIDDLE_RELEASED = 0x100D , - MSG_KEY_PRESSED = 0x100E, - MSG_KEY_RELEASED = 0x100F, - MSG_UPDATE_WINDOW = 0x1010, - MSG_WM_END = 0x13FF, - MSG_PAINT = 0x2000 , - MSG_PAINT_BACKGROUND = 0x2001 , - MSG_PAINT_FOREGROUND = 0x2002 , - MSG_GET_CURSOR = 0x2003 , - MSG_ANIMATE = 0x2004 , - MSG_Z_ORDER = 0x2005 , - MSG_DESTROY = 0x2006 , - MSG_MEASURE = 0x2008 , - MSG_LAYOUT = 0x2009 , - MSG_ENSURE_VISIBLE = 0x200A , - MSG_ADD_CHILD = 0x200B , - MSG_REMOVE_CHILD = 0x200C , - MSG_PRE_ADD_CHILD = 0x200D , - MSG_HIT_TEST = 0x200E , - MSG_MOUSE_DRAGGED = 0x200F , - MSG_CLICKED = 0x2010 , - MSG_KEY_TYPED = 0x2011 , - MSG_SCROLL_X = 0x2012 , - MSG_SCROLL_Y = 0x2013 , - MSG_STRONG_FOCUS_END = 0x2014 , - MSG_BEFORE_Z_ORDER = 0x2015 , - MSG_AFTER_Z_ORDER = 0x2016 , - MSG_PAINT_CHILDREN = 0x2017 , - MSG_DESTROY_CONTENTS = 0x2018 , - MSG_STATE_CHANGE_MESSAGE_START = 0x2080, - MSG_HOVERED_START = 0x2081 , - MSG_HOVERED_END = 0x2082 , - MSG_PRESSED_START = 0x2083 , - MSG_PRESSED_END = 0x2084 , - MSG_FOCUSED_START = 0x2085 , - MSG_FOCUSED_END = 0x2086 , - MSG_FOCUS_WITHIN_START = 0x2087 , - MSG_FOCUS_WITHIN_END = 0x2088 , - MSG_STATE_CHANGE_MESSAGE_END = 0x20FF, - MSG_SCROLLBAR_MOVED = 0x3000 , - MSG_CHECK_UPDATED = 0x3001 , - MSG_RADIO_GROUP_UPDATED = 0x3002 , - MSG_COLOR_CHANGED = 0x3003 , - MSG_DESKTOP_START_PROGRAM = 0x4800, - MSG_POWER_BUTTON_PRESSED = 0x4801, - MSG_SET_WINDOW_METADATA = 0x4802, - MSG_EMBEDDED_WINDOW_DESTROYED = 0x4803, - MSG_FS_EVENT_START = 0x4B80, - MSG_FS_CREATE = 0x4B81, - MSG_FS_DELETE = 0x4B82, - MSG_FS_MOVE = 0x4B83, - MSG_FS_MODIFY = 0x4B84, - MSG_FS_EVENT_END = 0x4B85, - MSG_FS_MONITOR_DESTROY = 0x4B86 , - MSG_PROGRAM_CRASH = 0x4C00, - MSG_CLIPBOARD_UPDATED = 0x5001, - MSG_EYEDROP_REPORT = 0x5002, - MSG_SYSTEM_CONSTANT_UPDATED = 0x5004, - MSG_TIMER = 0x5006, - MSG_PING = 0x5007 , - MSG_RECEIVE_DATA = 0x5080, - MSG_MAILSLOT_CLOSED = 0x5081, - MSG_CHOICE_ADD_ITEMS = 0x5180, - MSG_CHOICE_ITEM_TO_STRING = 0x5181, - MSG_CHOICE_UPDATE = 0x5182, - MSG_TEXTBOX_UPDATED = 0x5200, - MSG_TEXTBOX_EDIT_START = 0x5201 , - MSG_TEXTBOX_EDIT_END = 0x5202 , - MSG_TEXTBOX_NUMBER_DRAG_START = 0x5203 , - MSG_TEXTBOX_NUMBER_DRAG_END = 0x5204 , - MSG_TEXTBOX_NUMBER_DRAG_DELTA = 0x5205 , - MSG_TEXTBOX_NUMBER_UPDATED = 0x5206 , - MSG_TEXTBOX_GET_BREADCRUMB = 0x5207 , - MSG_TEXTBOX_ACTIVATE_BREADCRUMB = 0x5208 , - MSG_LIST_VIEW_COMPARE_INDICES = 0x5300, - MSG_LIST_VIEW_NEXT_INDEX = 0x5301, - MSG_LIST_VIEW_PREVIOUS_INDEX = 0x5302, - MSG_LIST_VIEW_FIRST_INDEX = 0x5303, - MSG_LIST_VIEW_LAST_INDEX = 0x5304, - MSG_LIST_VIEW_FIND_INDEX = 0x5305, - MSG_LIST_VIEW_COUNT_ITEMS = 0x5306, - MSG_LIST_VIEW_MEASURE_RANGE = 0x5307, - MSG_LIST_VIEW_MEASURE_ITEM = 0x5308, - MSG_LIST_VIEW_CREATE_ITEM = 0x5309, - MSG_LIST_VIEW_GET_CONTENT = 0x530A, - MSG_LIST_VIEW_GET_INDENT = 0x530B, - MSG_LIST_VIEW_FIND_POSITION = 0x530C, - MSG_LIST_VIEW_IS_SELECTED = 0x530D, - MSG_LIST_VIEW_SELECT = 0x530E, - MSG_LIST_VIEW_SELECT_RANGE = 0x530F, - MSG_LIST_VIEW_CHOOSE_ITEM = 0x5310, - MSG_LIST_VIEW_SEARCH = 0x5311, - MSG_PROGRAM_EXIT = 0x7001, - MSG_INSTANCE_CREATE = 0x7002, - MSG_INSTANCE_OPEN = 0x7003, - MSG_INSTANCE_SAVE = 0x7004, - MSG_USER_START = 0x8000, - MSG_USER_END = 0xBFFF, -} -using DrawMode :: enum i32 { - DRAW_MODE_REPEAT_FIRST = 1 , - DRAW_MODE_STRECH, - DRAW_MODE_REPEAT, - DRAW_MODE_NONE, -} -using ClipboardFormat :: enum i32 { - CLIPBOARD_FORMAT_EMPTY, - CLIPBOARD_FORMAT_TEXT, - CLIPBOARD_FORMAT_FILE_LIST, -} -using CursorStyle :: enum i32 { - CURSOR_NORMAL, - CURSOR_TEXT, - CURSOR_RESIZE_VERTICAL, - CURSOR_RESIZE_HORIZONTAL, - CURSOR_RESIZE_DIAGONAL_1, - CURSOR_RESIZE_DIAGONAL_2, - CURSOR_SPLIT_VERTICAL, - CURSOR_SPLIT_HORIZONTAL, - CURSOR_HAND_HOVER, - CURSOR_HAND_DRAG, - CURSOR_HAND_POINT, - CURSOR_SCROLL_UP_LEFT, - CURSOR_SCROLL_UP, - CURSOR_SCROLL_UP_RIGHT, - CURSOR_SCROLL_LEFT, - CURSOR_SCROLL_CENTER, - CURSOR_SCROLL_RIGHT, - CURSOR_SCROLL_DOWN_LEFT, - CURSOR_SCROLL_DOWN, - CURSOR_SCROLL_DOWN_RIGHT, - CURSOR_SELECT_LINES, - CURSOR_DROP_TEXT, - CURSOR_CROSS_HAIR_PICK, - CURSOR_CROSS_HAIR_RESIZE, - CURSOR_MOVE_HOVER, - CURSOR_MOVE_DRAG, - CURSOR_ROTATE_HOVER, - CURSOR_ROTATE_DRAG, - CURSOR_BLANK, - CURSOR_COUNT, -} -using WindowStyle :: enum i32 { - WINDOW_NORMAL, - WINDOW_CONTAINER, - WINDOW_MENU, - WINDOW_TIP, - WINDOW_PLAIN, -} -using FormatValueType :: enum i32 { - FORMAT_VALUE_INVALID, - FORMAT_VALUE_STRING, - FORMAT_VALUE_NUMBER, - FORMAT_VALUE_TIME, -} -using CheckState :: enum i32 { - CHECK_UNCHECKED = 0, - CHECK_CHECKED = 1, - CHECK_INDETERMINATE = 2, -} -using DocumentState :: enum i32 { - DOCUMENT_STATE_EMPTY, - DOCUMENT_STATE_UNSAVED, - DOCUMENT_STATE_FILE, -} -using TransitionType :: enum i32 { - TRANSITION_NONE, - TRANSITION_SLIDE_UP, - TRANSITION_SLIDE_DOWN, - TRANSITION_COVER_UP, - TRANSITION_COVER_DOWN, - TRANSITION_SQUISH_UP, - TRANSITION_SQUISH_DOWN, - TRANSITION_ZOOM_OUT, - TRANSITION_ZOOM_IN, - TRANSITION_ZOOM_OUT_LIGHT, - TRANSITION_ZOOM_IN_LIGHT, - TRANSITION_REVEAL_UP, - TRANSITION_REVEAL_DOWN, - TRANSITION_FADE_IN, - TRANSITION_FADE_OUT, -} -using MemoryProtection :: enum i32 { - MEMORY_PROTECTION_READ_ONLY, - MEMORY_PROTECTION_READ_WRITE, - MEMORY_PROTECTION_EXECUTABLE, -} -UICallbackFunction :: distinct #type proc "c" ( ^Element, ^Message, ^Response); -BatchCall :: struct { - index : SyscallType, - stopBatchIfError : bool, - using _ : struct #raw_union { - argument0 : uint , - returnValue : uint , - }, - argument1 : uint , - argument2 : uint , - argument3 : uint , -} -ThreadInformation :: struct { - handle : Handle, - tid : uint , -} -ProcessInformation :: struct { - handle : Handle, - pid : uint , - mainThread : ThreadInformation, -} -UniqueIdentifier :: struct { - d : [16]u8 , -} -NodeInformation :: struct { - handle : Handle, - type : NodeType, - fileSize : FileOffset, - directoryChildren : FileOffsetDifference, -} -DirectoryChild :: struct { - name : [MAX_DIRECTORY_CHILD_NAME_LENGTH]i8 , - nameBytes : int , - information : NodeInformation, -} -Point :: struct { - x : i32 , - y : i32 , -} -Rectangle :: struct { - l : i32 , - r : i32 , - t : i32 , - b : i32 , -} -Spinlock :: struct { - state : u8 , -} -Mutex :: struct { - event : Handle, - spinlock : Spinlock, - state : u8 , - queued : u32 , -} -CrashReason :: struct { - errorCode : Error, -} -ProcessState :: struct { - crashReason : CrashReason, - creationArgument : Generic, - id : uint , - executableState : uint , - flags : u8 , -} -ClipboardHeader :: struct { - customBytes : int , - format : ClipboardFormat, - textBytes : int , - unused : uint , -} -Painter :: struct { - clip : Rectangle, - offsetX : i32, - offsetY : i32, - width : i32, - height : i32, - style : rawptr, - target : ^PaintTarget, -} -Message :: struct { - type : MessageType, - using _ : struct #raw_union { - user : struct { - context1 : Generic, - context2 : Generic, - context3 : Generic, - }, - _argument : rawptr, - mouseMoved : struct { - oldPositionX : i32, - newPositionX : i32, - oldPositionY : i32, - newPositionY : i32, - newPositionXScreen : i32, - newPositionYScreen : i32, - }, - mouseDragged : struct { - oldPositionX : i32, - newPositionX : i32, - oldPositionY : i32, - newPositionY : i32, - originalPositionX : i32, - originalPositionY : i32, - }, - mousePressed : struct { - positionX : i32, - positionY : i32, - positionXScreen : i32, - positionYScreen : i32, - clickChainCount : u8 , - alt : u8 , - ctrl : u8 , - shift : u8 , - activationClick : u8 , - }, - keyboard : struct { - scancode : u32 , - alt : u8 , - ctrl : u8 , - shift : u8 , - numpad : u8 , - repeat : u8 , - }, - crash : struct { - reason : CrashReason, - process : Handle, - pid : uint , - }, - clipboard : ClipboardHeader, - receive : struct { - buffer : Handle, - bytes : int , - }, - animate : struct { - deltaUs : i64 , - waitUs : i64 , - complete : bool, - }, - systemConstantUpdated : struct { - index : uint , - newValue : u64 , - }, - desktopExecute : struct { - whatBuffer : Handle, - argumentBuffer : Handle, - mailslot : Handle, - whatBytes : int , - argumentBytes : int , - modalWindowParent : u64 , - }, - windowMetadata : struct { - id : u64 , - buffer : Handle, - bytes : int , - }, - windowResized : struct { - content : Rectangle, - hidden : bool, - }, - painter : ^Painter, - measure : struct { - width : i32, - height : i32, - hideScrollbarX : bool, - hideScrollbarY : bool, - }, - child : rawptr, - hitTest : struct { - x : i32, - y : i32, - inside : bool, - }, - zOrder : struct { - index : uint , - child : ^Element, - }, - scrollbarMoved : struct { - scroll : i32, - previous : i32, - }, - ensureVisible : struct { - child : ^Element, - }, - cursorStyle : CursorStyle, - eyedrop : struct { - color : u32 , - cancelled : bool, - }, - colorChanged : struct { - newColor : u32 , - pickerClosed : bool, - }, - itemToString : struct { - item : Generic, - text : string, - }, - choiceUpdated : struct { - newItem : Generic, - oldItem : Generic, - }, - numberDragDelta : struct { - delta : i32, - hoverCharacter : i32 , - fast : bool, - }, - numberUpdated : struct { - delta : f64 , - newValue : f64 , - }, - getBreadcrumb : struct { - index : uint , - text : string, - }, - activateBreadcrumb : uint , - checkState : CheckState, - fsEvent : struct { - buffer : Handle, - bufferBytes : u16 , - pathOffset : u16 , - oldPathOffset : u16 , - pathBytes : u16 , - oldPathBytes : u16 , - _context : Generic, - }, - createInstance : struct { - window : Handle, - data : Handle, - dataBytes : int , - }, - instanceOpen : struct { - instance : ^INSTANCE_TYPE, - path : string, - }, - instanceSave : struct { - instance : ^INSTANCE_TYPE, - path : string, - }, - compareIndices : struct { - group : i32 , - left : Generic, - right : Generic, - result : i32, - }, - iterateIndex : struct { - group : i32 , - index : Generic, - position : i64 , - }, - itemRange : struct { - group : i32 , - firstIndex : Generic, - lastIndex : Generic, - result : i64 , - }, - measureItem : struct { - group : i32 , - index : Generic, - result : i64 , - }, - createItem : struct { - group : i32 , - index : Generic, - parent : ^Element, - }, - getContent : struct { - index : Generic, - group : i32 , - column : u8 , - icon : u32 , - text : string, - }, - getIndent : struct { - group : i32 , - index : Generic, - indent : u8 , - }, - selectRange : struct { - fromIndex : Generic, - toIndex : Generic, - group : i32 , - select : bool, - toggle : bool, - }, - selectItem : struct { - group : i32 , - index : Generic, - isSelected : bool, - }, - chooseItem : struct { - group : i32 , - index : Generic, - }, - searchItem : struct { - group : i32 , - index : Generic, - query : string, - }, - layout : struct { - sizeChanged : bool, - }, - }, -} -_EsMessageWithObject :: struct { - object : rawptr, - message : Message, -} -DebuggerMessage :: struct { - process : Handle, - reason : CrashReason, -} -DriveInformation :: struct { - name : [64]i8 , - nameBytes : int , - mountpoint : [256]i8 , - mountpointBytes : int , -} -SnapshotProcessesItem :: struct { - pid : i64 , - memoryUsage : i64 , - cpuTimeSlices : i64 , - name : [SNAPSHOT_MAX_PROCESS_NAME_LENGTH]i8 , - nameLength : int , - internal : u64 , -} -SystemInformation :: struct { - processCount : uint , - threadCount : uint , - handleCount : uint , - commitLimit : uint , - commit : uint , - countZeroedPages : uint , - countFreePages : uint , - countStandbyPages : uint , - countActivePages : uint , - coreHeapSize : uint , - coreHeapAllocations : uint , - fixedHeapSize : uint , - fixedHeapAllocations : uint , - coreRegions : uint , - kernelRegions : uint , -} -SnapshotProcesses :: struct { - count : int , - processes : []SnapshotProcessesItem, -} -_EsPOSIXSyscall :: struct { - index : int , - arguments : [7]int , -} -ProcessCreationArguments :: struct { - executablePath : string, - environmentBlock : rawptr, - environmentBlockBytes : int , - creationArgument : Generic, - permissions : u64 , -} -_EsUserLoginArguments :: struct { - name : string, - home : string, -} -Instance :: struct { - _private : rawptr, - window : ^Window, - documentState : DocumentState, -} -PanelBand :: struct { - preferredSize : i32, - minimumSize : i32, - maximumSize : i32, - grow : i32, - shrink : i32, -} -ThemeMetrics :: struct { - mask : u64 , - insets : Rectangle, - clipInsets : Rectangle, - globalOffset : Rectangle, - clipEnabled : i32, - cursor : i32, - entranceTransition : i32, - exitTransition : i32, - entranceDuration : i32, - exitDuration : i32, - preferredWidth : i32, - preferredHeight : i32, - minimumWidth : i32, - minimumHeight : i32, - maximumWidth : i32, - maximumHeight : i32, - gapMajor : i32, - gapMinor : i32, - gapWrap : i32, - textColor : i32, - selectedBackground : i32, - selectedText : i32, - iconColor : i32, - textAlign : i32, - textSize : i32, - fontFamily : i32, - fontWeight : i32, - iconSize : i32, - isItalic : bool, - ellipsis : bool, - wrapText : bool, -} -Font :: struct { - family : u16 , - weight : u8 , - italic : bool, -} -TextStyle :: struct { - font : Font, - size : u16 , - baselineOffset : u16 , - kerning : i8 , - figures : u8 , - alternateDirection : bool, - color : u32 , - blur : u8 , - underlined : bool, -} -TextRun :: struct { - style : TextStyle, - bytes : u32 , -} -TextDisplayProperties :: struct { - cLanguage : cstring , - rtl : bool, - trimTrailingSpaces : bool, - align : u8 , - maxLines : i32, -} -TextSelection :: struct { - caret0 : int , - caret1 : int , - hideCaret : bool, - foreground : u32 , - background : u32 , -} -FormatValue :: struct { - type : FormatValueType, - isCString : bool, - isStringLiteral : bool, - using _ : struct #raw_union { - string : ^i8 , - number : f64 , - time : u64 , - }, -} -FragmentShaderCallbackFunction :: distinct #type proc "c" ( i32, i32, ^StyledBox) -> u32 ; -StyledBox :: struct { - bounds : Rectangle, - clip : Rectangle, - backgroundColor : u32 , - backgroundColor2 : u32 , - fragmentShader : FragmentShaderCallbackFunction, - borderColor : u32 , - borders : Rectangle, - cornerRadiusTopLeft : i32, - cornerRadiusTopRight : i32, - cornerRadiusBottomLeft : i32, - cornerRadiusBottomRight : i32, - blur : bool, - overwriteAlpha : bool, -} -Arena :: struct { - firstEmptySlot : rawptr, - firstBlock : rawptr, - slotsPerBlock : int , - slotSize : int , - blockSize : int , -} -CalculationValue :: struct { - error : bool, - number : f64 , -} -CommandCallbackFunction :: distinct #type proc "c" ( ^INSTANCE_TYPE, ^Element, ^Command); -Command :: struct { - elements : ^^Element, - callback : CommandCallbackFunction, - disabled : bool, - registered : bool, - allocated : bool, - stableID : u32 , - cKeyboardShortcut : cstring , - data : Generic, -} -ListViewColumn :: struct { - title : string, - flags : u64 , - width : i32, -} -AudioFormat :: struct { - sampleRate : u32 , - sampleFormat : u8 , - channels : u8 , - reserved : u16 , -} -AudioStream :: struct { - format : AudioFormat, - handle : Handle, - buffer : ^u8 , - bufferBytes : u32 , - readPointer : u32 , - writePointer : u32 , - status : u16 , - control : u16 , - clock : u64 , -} -ApplicationStartupInformation :: struct { - id : i64 , - filePath : string, - targetWindow : ^Window, - flags : u64 , -} -INIState :: struct { - buffer : ^i8 , - sectionClass : ^i8 , - section : ^i8 , - key : ^i8 , - value : ^i8 , - bytes : int , - sectionClassBytes : int , - sectionBytes : int , - keyBytes : int , - valueBytes : int , -} -SystemConfigurationItem :: struct { - key : ^i8 , - value : ^i8 , - keyBytes : int , - valueBytes : int , -} -SystemConfigurationGroup :: struct { - section : ^i8 , - sectionClass : ^i8 , - sectionBytes : int , - sectionClassBytes : int , - items : ^SystemConfigurationItem, - itemCount : int , -} -AnalogInput :: struct { - x : u8 , - y : u8 , - z : u8 , -} -GameControllerState :: struct { - id : u64 , - buttonCount : u8 , - analogCount : u8 , - directionalPad : u8 , - buttons : u32 , - analog : [8]AnalogInput, -} -SchedulerLogEntry :: struct { - path : [64]i8 , - thread : [16]i8 , - pathBytes : u8 , - threadBytes : u8 , - cpu : u8 , - count : u32 , - timeMs : u64 , -} -PCIDevice :: struct { - deviceID : u32 , - classCode : u8 , - subclassCode : u8 , - progIF : u8 , - bus : u8 , - slot : u8 , - function : u8 , - interruptPin : u8 , - interruptLine : u8 , - baseAddressesSizes : [6]int , - baseAddresses : [6]u32 , - driverName : [64]i8 , - driverNameBytes : int , -} -Address :: struct { - using _ : struct #raw_union { - using _ : struct { - ipv4 : u32 , - port : u16 , - }, - d : [20]u8 , - }, -} -Connection :: struct { - address : Address, - receiveBufferBytes : int , - sendBufferBytes : int , - receiveBuffer : ^u8 , - sendBuffer : ^u8 , - receiveWritePointer : uint , - sendReadPointer : uint , - open : bool, - error : Error, - receiveReadPointer : uint , - sendWritePointer : uint , - handle : Handle, -} -ThreadEntryFunction :: distinct #type proc "c" ( Generic); -ComparisonCallbackFunction :: distinct #type proc "c" ( rawptr, rawptr, Generic) -> i32; -SwapCallbackFunction :: distinct #type proc "c" ( rawptr, rawptr, Generic); -CRTComparisonCallback :: distinct #type proc "c" ( rawptr, rawptr) -> i32; -TimerCallbackFunction :: distinct #type proc "c" ( Generic); -MenuCallbackFunction :: distinct #type proc "c" ( ^Menu, Generic); -StorePullCallbackFunction :: distinct #type proc "c" ( ^Store, ^INSTANCE_TYPE, Generic, i32, Generic, ^FormatValue); -StoreCallbackFunction :: distinct #type proc "c" ( ^Store, ^INSTANCE_TYPE, Generic, Generic); -DirectoryMonitorCallbackFunction :: distinct #type proc "c" ( ^DirectoryMonitor, i32, ^i8 , int , ^i8 , int , Generic); -Batch :: #force_inline proc "c" (calls_ : ^BatchCall, count_ : int ){ addr := 0x1000 + 0 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^BatchCall, int )) (fp))(calls_, count_); } -GetCreationArgument :: #force_inline proc "c" (object_ : Handle) -> Generic{ addr := 0x1000 + 1 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> Generic) (fp))(object_); } -GetSystemInformation :: #force_inline proc "c" (systemInformation_ : ^SystemInformation){ addr := 0x1000 + 2 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^SystemInformation)) (fp))(systemInformation_); } -HandleClose :: #force_inline proc "c" (handle_ : Handle) -> Error{ addr := 0x1000 + 3 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> Error) (fp))(handle_); } -InitialiseCStandardLibrary :: #force_inline proc "c" (argc_ : ^i32, argv_ : ^^^i8 ){ addr := 0x1000 + 4 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^i32, ^^^i8 )) (fp))(argc_, argv_); } -MailslotSendData :: #force_inline proc "c" (mailslot_ : Handle, data_ : rawptr, bytes_ : int ) -> bool{ addr := 0x1000 + 5 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, rawptr, int ) -> bool) (fp))(mailslot_, data_, bytes_); } -MakeLinuxSystemCall2 :: #force_inline proc "c" (n_ : int , a1_ : int , a2_ : int , a3_ : int , a4_ : int , a5_ : int , a6_ : int ) -> int { addr := 0x1000 + 6 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , int , int , int , int , int , int ) -> int ) (fp))(n_, a1_, a2_, a3_, a4_, a5_, a6_); } -SystemGetConstant :: #force_inline proc "c" (index_ : uint ) -> u64 { addr := 0x1000 + 8 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( uint ) -> u64 ) (fp))(index_); } -TakeSystemSnapshot :: #force_inline proc "c" (type_ : i32, bufferSize_ : ^int ) -> Handle{ addr := 0x1000 + 9 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32, ^int ) -> Handle) (fp))(type_, bufferSize_); } -UserGetHomeFolder :: #force_inline proc "c" (buffer_ : ^i8 , bufferBytes_ : int ) -> int { addr := 0x1000 + 10 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int ) -> int ) (fp))(buffer_, bufferBytes_); } -_EsInstanceCreate :: #force_inline proc "c" (bytes_ : int , message_ : ^Message, cName_ : cstring ) -> ^Instance{ addr := 0x1000 + 11 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , ^Message, cstring ) -> ^Instance) (fp))(bytes_, message_, cName_); } -_EsSyscall :: #force_inline proc "c" (a_ : uint , b_ : uint , c_ : uint , d_ : uint , e_ : uint , f_ : uint ) -> uint { addr := 0x1000 + 12 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( uint , uint , uint , uint , uint , uint ) -> uint ) (fp))(a_, b_, c_, d_, e_, f_); } -ApplicationStart :: #force_inline proc "c" (information_ : ^ApplicationStartupInformation){ addr := 0x1000 + 124 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ApplicationStartupInformation)) (fp))(information_); } -SystemConfigurationReadAll :: #force_inline proc "c" (groupCount_ : ^int ) -> ^SystemConfigurationGroup{ addr := 0x1000 + 164 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^int ) -> ^SystemConfigurationGroup) (fp))(groupCount_); } -SystemConfigurationReadInteger :: #force_inline proc "c" (section_ : string, key_ : string, defaultValue_ : i64 = 0) -> i64 { addr := 0x1000 + 295 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^u8, int, i64 ) -> i64 ) (fp))(raw_data(section_), len(section_), raw_data(key_), len(key_), defaultValue_); } -SystemConfigurationGroupReadInteger :: #force_inline proc "c" (group_ : ^SystemConfigurationGroup, key_ : string, defaultValue_ : i64 = 0) -> i64 { addr := 0x1000 + 296 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^SystemConfigurationGroup, ^u8, int, i64 ) -> i64 ) (fp))(group_, raw_data(key_), len(key_), defaultValue_); } -SystemConfigurationReadString :: #force_inline proc "c" (section_ : string, key_ : string, valueBytes_ : ^int = nil) -> ^i8 { addr := 0x1000 + 297 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^u8, int, ^int ) -> ^i8 ) (fp))(raw_data(section_), len(section_), raw_data(key_), len(key_), valueBytes_); } -SystemConfigurationGroupReadString :: #force_inline proc "c" (group_ : ^SystemConfigurationGroup, key_ : string, valueBytes_ : ^int = nil) -> ^i8 { addr := 0x1000 + 298 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^SystemConfigurationGroup, ^u8, int, ^int ) -> ^i8 ) (fp))(group_, raw_data(key_), len(key_), valueBytes_); } -INIParse :: #force_inline proc "c" (s_ : ^INIState) -> bool{ addr := 0x1000 + 7 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^INIState) -> bool) (fp))(s_); } -INIPeek :: #force_inline proc "c" (s_ : ^INIState) -> bool{ addr := 0x1000 + 87 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^INIState) -> bool) (fp))(s_); } -INIFormat :: #force_inline proc "c" (s_ : ^INIState, buffer_ : ^i8 , bytes_ : int ) -> int { addr := 0x1000 + 125 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^INIState, ^i8 , int ) -> int ) (fp))(s_, buffer_, bytes_); } -INIZeroTerminate :: #force_inline proc "c" (s_ : ^INIState){ addr := 0x1000 + 126 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^INIState)) (fp))(s_); } -CommandAddButton :: #force_inline proc "c" (command_ : ^Command, button_ : ^Button){ addr := 0x1000 + 13 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Command, ^Button)) (fp))(command_, button_); } -CommandByID :: #force_inline proc "c" (instance_ : ^Instance, stableID_ : u32 ) -> ^Command{ addr := 0x1000 + 14 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Instance, u32 ) -> ^Command) (fp))(instance_, stableID_); } -CommandRegister :: #force_inline proc "c" (command_ : ^Command, instance_ : ^Instance, callback_ : CommandCallbackFunction, stableID_ : u32 , cDefaultKeyboardShortcut_ : cstring = nil, enabled_ : bool = false) -> ^Command{ addr := 0x1000 + 15 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Command, ^Instance, CommandCallbackFunction, u32 , cstring , bool) -> ^Command) (fp))(command_, instance_, callback_, stableID_, cDefaultKeyboardShortcut_, enabled_); } -CommandSetCallback :: #force_inline proc "c" (command_ : ^Command, callback_ : CommandCallbackFunction){ addr := 0x1000 + 16 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Command, CommandCallbackFunction)) (fp))(command_, callback_); } -CommandSetDisabled :: #force_inline proc "c" (command_ : ^Command, disabled_ : bool){ addr := 0x1000 + 17 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Command, bool)) (fp))(command_, disabled_); } -DialogClose :: #force_inline proc "c" (window_ : ^Window){ addr := 0x1000 + 18 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Window)) (fp))(window_); } -DialogShow :: #force_inline proc "c" (window_ : ^Window) -> ^Element{ addr := 0x1000 + 19 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Window) -> ^Element) (fp))(window_); } -DialogShowAlert :: #force_inline proc "c" (window_ : ^Window, title_ : string, content_ : string, iconID_ : u32 , addOKButton_ : bool = false) -> ^Element{ addr := 0x1000 + 20 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Window, ^u8, int, ^u8, int, u32 , bool) -> ^Element) (fp))(window_, raw_data(title_), len(title_), raw_data(content_), len(content_), iconID_, addOKButton_); } -InstanceDestroy :: #force_inline proc "c" (instance_ : ^INSTANCE_TYPE){ addr := 0x1000 + 300 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^INSTANCE_TYPE)) (fp))(instance_); } -KeyboardIsAltHeld :: #force_inline proc "c" () -> bool{ addr := 0x1000 + 21 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> bool) (fp))(); } -KeyboardIsCtrlHeld :: #force_inline proc "c" () -> bool{ addr := 0x1000 + 22 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> bool) (fp))(); } -KeyboardIsShiftHeld :: #force_inline proc "c" () -> bool{ addr := 0x1000 + 23 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> bool) (fp))(); } -MessageGetInputText :: #force_inline proc "c" (message_ : ^Message, buffer_ : ^i8 ) -> int { addr := 0x1000 + 24 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Message, ^i8 ) -> int ) (fp))(message_, buffer_); } -MessageMutexAcquire :: #force_inline proc "c" (){ addr := 0x1000 + 26 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -MessageMutexCheck :: #force_inline proc "c" (){ addr := 0x1000 + 27 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -MessageMutexRelease :: #force_inline proc "c" (){ addr := 0x1000 + 28 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -MessagePost :: #force_inline proc "c" (target_ : ^Element, message_ : ^Message) -> Error{ addr := 0x1000 + 29 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, ^Message) -> Error) (fp))(target_, message_); } -MessagePostRemote :: #force_inline proc "c" (process_ : Handle, message_ : ^Message) -> Error{ addr := 0x1000 + 30 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, ^Message) -> Error) (fp))(process_, message_); } -MessageSend :: #force_inline proc "c" (object_ : ^Element, message_ : ^Message) -> Response{ addr := 0x1000 + 31 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, ^Message) -> Response) (fp))(object_, message_); } -MessageReceive :: #force_inline proc "c" () -> ^Message{ addr := 0x1000 + 318 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> ^Message) (fp))(); } -MouseGetPosition :: #force_inline proc "c" (relativeElement_ : ^Element = nil) -> Point{ addr := 0x1000 + 32 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> Point) (fp))(relativeElement_); } -MouseSetPosition :: #force_inline proc "c" (relativeWindow_ : ^Window, x_ : i32, y_ : i32){ addr := 0x1000 + 33 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Window, i32, i32)) (fp))(relativeWindow_, x_, y_); } -StyleInheritRegister :: #force_inline proc "c" (cStyle_ : cstring , cParent_ : cstring , customMetrics_ : ^ThemeMetrics){ addr := 0x1000 + 239 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( cstring , cstring , ^ThemeMetrics)) (fp))(cStyle_, cParent_, customMetrics_); } -StyleRefreshAll :: #force_inline proc "c" (window_ : ^Element){ addr := 0x1000 + 37 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element)) (fp))(window_); } -UISetDPI :: #force_inline proc "c" (dpiScale_ : i32){ addr := 0x1000 + 38 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( i32)) (fp))(dpiScale_); } -DirectoryEnumerateChildren :: #force_inline proc "c" (path_ : string, buffer_ : ^^DirectoryChild) -> int { addr := 0x1000 + 39 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^^DirectoryChild) -> int ) (fp))(raw_data(path_), len(path_), buffer_); } -DirectoryEnumerateChildrenFromHandle :: #force_inline proc "c" (directory_ : Handle, buffer_ : ^DirectoryChild, bufferCount_ : int ) -> int { addr := 0x1000 + 40 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, ^DirectoryChild, int ) -> int ) (fp))(directory_, buffer_, bufferCount_); } -DirectoryMonitorCreate :: #force_inline proc "c" (path_ : string, flags_ : u32 , callback_ : DirectoryMonitorCallbackFunction, _context_ : Generic) -> ^DirectoryMonitor{ addr := 0x1000 + 41 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, u32 , DirectoryMonitorCallbackFunction, Generic) -> ^DirectoryMonitor) (fp))(raw_data(path_), len(path_), flags_, callback_, _context_); } -DirectoryMonitorCreateFromHandle :: #force_inline proc "c" (directory_ : Handle, flags_ : u32 , callback_ : DirectoryMonitorCallbackFunction, _context_ : Generic) -> ^DirectoryMonitor{ addr := 0x1000 + 42 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, u32 , DirectoryMonitorCallbackFunction, Generic) -> ^DirectoryMonitor) (fp))(directory_, flags_, callback_, _context_); } -DirectoryMonitorDestroy :: #force_inline proc "c" (monitor_ : ^DirectoryMonitor){ addr := 0x1000 + 43 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^DirectoryMonitor)) (fp))(monitor_); } -FileControl :: #force_inline proc "c" (file_ : Handle, flags_ : u32 ) -> Error{ addr := 0x1000 + 96 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, u32 ) -> Error) (fp))(file_, flags_); } -FileReadAll :: #force_inline proc "c" (filePath_ : string, fileSize_ : ^int ) -> rawptr{ addr := 0x1000 + 44 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^int ) -> rawptr) (fp))(raw_data(filePath_), len(filePath_), fileSize_); } -FileReadSync :: #force_inline proc "c" (file_ : Handle, offset_ : FileOffset, size_ : int , buffer_ : rawptr) -> int { addr := 0x1000 + 45 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, FileOffset, int , rawptr) -> int ) (fp))(file_, offset_, size_, buffer_); } -FileResize :: #force_inline proc "c" (file_ : Handle, newSize_ : FileOffset) -> Error{ addr := 0x1000 + 46 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, FileOffset) -> Error) (fp))(file_, newSize_); } -FileWriteAll :: #force_inline proc "c" (filePath_ : string, data_ : rawptr, fileSize_ : int ) -> Error{ addr := 0x1000 + 47 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, rawptr, int ) -> Error) (fp))(raw_data(filePath_), len(filePath_), data_, fileSize_); } -FileWriteAllGather :: #force_inline proc "c" (filePath_ : string, data_ : ^rawptr, fileSize_ : ^int , gatherCount_ : int ) -> Error{ addr := 0x1000 + 48 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^rawptr, ^int , int ) -> Error) (fp))(raw_data(filePath_), len(filePath_), data_, fileSize_, gatherCount_); } -FileWriteSync :: #force_inline proc "c" (file_ : Handle, offset_ : FileOffset, size_ : int , buffer_ : rawptr) -> int { addr := 0x1000 + 50 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, FileOffset, int , rawptr) -> int ) (fp))(file_, offset_, size_, buffer_); } -NodeDelete :: #force_inline proc "c" (node_ : Handle) -> Error{ addr := 0x1000 + 51 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> Error) (fp))(node_); } -NodeDeleteByPath :: #force_inline proc "c" (filePath_ : string) -> Error{ addr := 0x1000 + 52 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int) -> Error) (fp))(raw_data(filePath_), len(filePath_)); } -NodeFindUniqueName :: #force_inline proc "c" (buffer_ : ^i8 , originalBytes_ : int , bufferBytes_ : int ) -> int { addr := 0x1000 + 53 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int , int ) -> int ) (fp))(buffer_, originalBytes_, bufferBytes_); } -NodeMove :: #force_inline proc "c" (node_ : Handle, newDirectory_ : Handle, newName_ : string) -> Error{ addr := 0x1000 + 54 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, Handle, ^u8, int) -> Error) (fp))(node_, newDirectory_, raw_data(newName_), len(newName_)); } -NodeOpen :: #force_inline proc "c" (path_ : string, flags_ : u32 , information_ : ^NodeInformation) -> Error{ addr := 0x1000 + 55 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, u32 , ^NodeInformation) -> Error) (fp))(raw_data(path_), len(path_), flags_, information_); } -NodeOpenRelative :: #force_inline proc "c" (directory_ : Handle, path_ : string, flags_ : u32 , information_ : ^NodeInformation) -> Error{ addr := 0x1000 + 56 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, ^u8, int, u32 , ^NodeInformation) -> Error) (fp))(directory_, raw_data(path_), len(path_), flags_, information_); } -NodeRefreshInformation :: #force_inline proc "c" (information_ : ^NodeInformation){ addr := 0x1000 + 57 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^NodeInformation)) (fp))(information_); } -ProcessCrash :: #force_inline proc "c" (error_ : Error, message_ : string){ addr := 0x1000 + 58 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Error, ^u8, int)) (fp))(error_, raw_data(message_), len(message_)); } -ProcessCreate :: #force_inline proc "c" (executablePath_ : string, information_ : ^ProcessInformation, argument_ : Generic) -> Error{ addr := 0x1000 + 59 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^ProcessInformation, Generic) -> Error) (fp))(raw_data(executablePath_), len(executablePath_), information_, argument_); } -ProcessCreate2 :: #force_inline proc "c" (arguments_ : ^ProcessCreationArguments, information_ : ^ProcessInformation) -> Error{ addr := 0x1000 + 60 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^ProcessCreationArguments, ^ProcessInformation) -> Error) (fp))(arguments_, information_); } -ProcessGetExitStatus :: #force_inline proc "c" (process_ : Handle) -> i32{ addr := 0x1000 + 61 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> i32) (fp))(process_); } -ProcessGetID :: #force_inline proc "c" (process_ : Handle) -> uint { addr := 0x1000 + 62 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> uint ) (fp))(process_); } -ProcessGetState :: #force_inline proc "c" (process_ : Handle, state_ : ^ProcessState){ addr := 0x1000 + 63 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, ^ProcessState)) (fp))(process_, state_); } -ProcessOpen :: #force_inline proc "c" (pid_ : u64 ) -> Handle{ addr := 0x1000 + 64 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( u64 ) -> Handle) (fp))(pid_); } -ProcessPause :: #force_inline proc "c" (process_ : Handle, resume_ : bool){ addr := 0x1000 + 65 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, bool)) (fp))(process_, resume_); } -ProcessTerminate :: #force_inline proc "c" (process_ : Handle, status_ : i32){ addr := 0x1000 + 66 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, i32)) (fp))(process_, status_); } -ProcessTerminateCurrent :: #force_inline proc "c" (){ addr := 0x1000 + 67 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -ThreadCreate :: #force_inline proc "c" (entryFunction_ : ThreadEntryFunction, information_ : ^ThreadInformation, argument_ : Generic) -> Error{ addr := 0x1000 + 68 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ThreadEntryFunction, ^ThreadInformation, Generic) -> Error) (fp))(entryFunction_, information_, argument_); } -ThreadGetID :: #force_inline proc "c" (thread_ : Handle) -> uint { addr := 0x1000 + 69 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> uint ) (fp))(thread_); } -ThreadTerminate :: #force_inline proc "c" (thread_ : Handle){ addr := 0x1000 + 71 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle)) (fp))(thread_); } -ArenaAllocate :: #force_inline proc "c" (arena_ : ^Arena, zero_ : bool) -> rawptr{ addr := 0x1000 + 72 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Arena, bool) -> rawptr) (fp))(arena_, zero_); } -ArenaFree :: #force_inline proc "c" (arena_ : ^Arena, pointer_ : rawptr){ addr := 0x1000 + 73 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Arena, rawptr)) (fp))(arena_, pointer_); } -ArenaInitialise :: #force_inline proc "c" (arena_ : ^Arena, blockSize_ : int , itemSize_ : int ){ addr := 0x1000 + 74 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Arena, int , int )) (fp))(arena_, blockSize_, itemSize_); } -ConstantBufferCreate :: #force_inline proc "c" (data_ : rawptr, dataBytes_ : int , targetProcess_ : Handle) -> Handle{ addr := 0x1000 + 75 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, int , Handle) -> Handle) (fp))(data_, dataBytes_, targetProcess_); } -ConstantBufferRead :: #force_inline proc "c" (constantBuffer_ : Handle, output_ : rawptr){ addr := 0x1000 + 76 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, rawptr)) (fp))(constantBuffer_, output_); } -ConstantBufferShare :: #force_inline proc "c" (constantBuffer_ : Handle, targetProcess_ : Handle) -> Handle{ addr := 0x1000 + 77 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, Handle) -> Handle) (fp))(constantBuffer_, targetProcess_); } -HeapAllocate :: #force_inline proc "c" (size_ : int , zeroMemory_ : bool) -> rawptr{ addr := 0x1000 + 78 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , bool) -> rawptr) (fp))(size_, zeroMemory_); } -HeapFree :: #force_inline proc "c" (address_ : rawptr){ addr := 0x1000 + 79 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr)) (fp))(address_); } -HeapReallocate :: #force_inline proc "c" (oldAddress_ : rawptr, newAllocationSize_ : int , zeroNewSpace_ : bool) -> rawptr{ addr := 0x1000 + 80 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, int , bool) -> rawptr) (fp))(oldAddress_, newAllocationSize_, zeroNewSpace_); } -HeapValidate :: #force_inline proc "c" (){ addr := 0x1000 + 81 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -MemoryCommit :: #force_inline proc "c" (pointer_ : rawptr, bytes_ : int ) -> bool{ addr := 0x1000 + 82 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, int ) -> bool) (fp))(pointer_, bytes_); } -MemoryCompare :: #force_inline proc "c" (a_ : rawptr, b_ : rawptr, bytes_ : int ) -> i32{ addr := 0x1000 + 83 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, rawptr, int ) -> i32) (fp))(a_, b_, bytes_); } -MemoryCopy :: #force_inline proc "c" (destination_ : rawptr, source_ : rawptr, bytes_ : int ){ addr := 0x1000 + 84 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, rawptr, int )) (fp))(destination_, source_, bytes_); } -MemoryCopyReverse :: #force_inline proc "c" (_destination_ : rawptr, _source_ : rawptr, bytes_ : int ){ addr := 0x1000 + 85 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, rawptr, int )) (fp))(_destination_, _source_, bytes_); } -MemoryDecommit :: #force_inline proc "c" (pointer_ : rawptr, bytes_ : int ) -> bool{ addr := 0x1000 + 320 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, int ) -> bool) (fp))(pointer_, bytes_); } -MemoryFill :: #force_inline proc "c" (from_ : rawptr, to_ : rawptr, byte_ : u8 ){ addr := 0x1000 + 86 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, rawptr, u8 )) (fp))(from_, to_, byte_); } -MemoryMove :: #force_inline proc "c" (_start_ : rawptr, _end_ : rawptr, amount_ : int , zeroEmptySpace_ : bool){ addr := 0x1000 + 88 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, rawptr, int , bool)) (fp))(_start_, _end_, amount_, zeroEmptySpace_); } -MemoryOpen :: #force_inline proc "c" (size_ : int , name_ : string, flags_ : u32 ) -> Handle{ addr := 0x1000 + 89 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , ^u8, int, u32 ) -> Handle) (fp))(size_, raw_data(name_), len(name_), flags_); } -MemoryReserve :: #force_inline proc "c" (size_ : int , protection_ : MemoryProtection = MEMORY_PROTECTION_READ_WRITE, commitAll_ : bool = true) -> rawptr{ addr := 0x1000 + 25 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , MemoryProtection, bool) -> rawptr) (fp))(size_, protection_, commitAll_); } -MemoryShare :: #force_inline proc "c" (sharedMemoryRegion_ : Handle, targetProcess_ : Handle, readOnly_ : bool) -> Handle{ addr := 0x1000 + 90 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, Handle, bool) -> Handle) (fp))(sharedMemoryRegion_, targetProcess_, readOnly_); } -MemorySumBytes :: #force_inline proc "c" (data_ : ^u8 , bytes_ : int ) -> u8 { addr := 0x1000 + 91 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^u8 , int ) -> u8 ) (fp))(data_, bytes_); } -MemoryUnreserve :: #force_inline proc "c" (pointer_ : rawptr, size_ : int = 0){ addr := 0x1000 + 319 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, int )) (fp))(pointer_, size_); } -MemoryZero :: #force_inline proc "c" (destination_ : rawptr, bytes_ : int ){ addr := 0x1000 + 92 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, int )) (fp))(destination_, bytes_); } -ObjectMap :: #force_inline proc "c" (object_ : Handle, offset_ : uint , size_ : int , flags_ : u32 ) -> rawptr{ addr := 0x1000 + 93 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, uint , int , u32 ) -> rawptr) (fp))(object_, offset_, size_, flags_); } -AssertionFailure :: #force_inline proc "c" (cFile_ : cstring , line_ : i32){ addr := 0x1000 + 94 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( cstring , i32)) (fp))(cFile_, line_); } -DoubleParse :: #force_inline proc "c" (string_ : string, endptr_ : ^^i8 ) -> f64 { addr := 0x1000 + 97 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^^i8 ) -> f64 ) (fp))(raw_data(string_), len(string_), endptr_); } -ExtractArguments :: #force_inline proc "c" (string_ : ^i8 , bytes_ : int , delimiterByte_ : u8 , replacementDelimiter_ : u8 , argvAllocated_ : int , argv_ : ^^i8 , argc_ : ^int ) -> bool{ addr := 0x1000 + 98 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int , u8 , u8 , int , ^^i8 , ^int ) -> bool) (fp))(string_, bytes_, delimiterByte_, replacementDelimiter_, argvAllocated_, argv_, argc_); } -RandomU8 :: #force_inline proc "c" () -> u8 { addr := 0x1000 + 301 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> u8 ) (fp))(); } -RandomU64 :: #force_inline proc "c" () -> u64 { addr := 0x1000 + 302 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> u64 ) (fp))(); } -IntegerParse :: #force_inline proc "c" (text_ : string) -> i64 { addr := 0x1000 + 101 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int) -> i64 ) (fp))(raw_data(text_), len(text_)); } -Print :: #force_inline proc "c" (format_ : cstring , _varargs_ : ..any){ addr := 0x1000 + 102 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( cstring , ..any)) (fp))(format_, _varargs_); } -PrintDirect :: #force_inline proc "c" (string_ : string){ addr := 0x1000 + 103 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" (^u8, int)) (fp))(raw_data(string_), len(string_)); } -PrintHelloWorld :: #force_inline proc "c" (){ addr := 0x1000 + 104 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -RandomAddEntropy :: #force_inline proc "c" (x_ : u64 ){ addr := 0x1000 + 106 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( u64 )) (fp))(x_); } -RandomSeed :: #force_inline proc "c" (x_ : u64 ){ addr := 0x1000 + 107 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( u64 )) (fp))(x_); } -RectangleClip :: #force_inline proc "c" (parent_ : Rectangle, rectangle_ : Rectangle, output_ : ^Rectangle) -> bool{ addr := 0x1000 + 108 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Rectangle, Rectangle, ^Rectangle) -> bool) (fp))(parent_, rectangle_, output_); } -Sort :: #force_inline proc "c" (_base_ : rawptr, nmemb_ : int , size_ : int , compar_ : ComparisonCallbackFunction, argument_ : Generic){ addr := 0x1000 + 109 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, int , int , ComparisonCallbackFunction, Generic)) (fp))(_base_, nmemb_, size_, compar_, argument_); } -SortWithSwapCallback :: #force_inline proc "c" (_base_ : rawptr, nmemb_ : int , size_ : int , compar_ : ComparisonCallbackFunction, argument_ : Generic, swap_ : SwapCallbackFunction){ addr := 0x1000 + 110 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, int , int , ComparisonCallbackFunction, Generic, SwapCallbackFunction)) (fp))(_base_, nmemb_, size_, compar_, argument_, swap_); } -TimeStamp :: #force_inline proc "c" () -> u64 { addr := 0x1000 + 252 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> u64 ) (fp))(); } -TimeStampMs :: #force_inline proc "c" () -> f64 { addr := 0x1000 + 261 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> f64 ) (fp))(); } -ColorBlend :: #force_inline proc "c" (under_ : u32 , over_ : u32 , fullAlpha_ : bool) -> u32 { addr := 0x1000 + 111 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( u32 , u32 , bool) -> u32 ) (fp))(under_, over_, fullAlpha_); } -ColorConvertToRGB :: #force_inline proc "c" (h_ : f32 , s_ : f32 , v_ : f32 ) -> u32 { addr := 0x1000 + 112 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 , f32 , f32 ) -> u32 ) (fp))(h_, s_, v_); } -ColorConvertToHSV :: #force_inline proc "c" (color_ : u32 , h_ : ^f32 , s_ : ^f32 , v_ : ^f32 ) -> bool{ addr := 0x1000 + 113 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( u32 , ^f32 , ^f32 , ^f32 ) -> bool) (fp))(color_, h_, s_, v_); } -ColorParse :: #force_inline proc "c" (string_ : string) -> u32 { addr := 0x1000 + 114 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int) -> u32 ) (fp))(raw_data(string_), len(string_)); } -DrawBitmap :: #force_inline proc "c" (painter_ : ^Painter, region_ : Rectangle, bits_ : ^u32 , stride_ : uint ){ addr := 0x1000 + 324 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, Rectangle, ^u32 , uint )) (fp))(painter_, region_, bits_, stride_); } -DrawInvert :: #force_inline proc "c" (painter_ : ^Painter, bounds_ : Rectangle){ addr := 0x1000 + 95 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, Rectangle)) (fp))(painter_, bounds_); } -DrawStandardIcon :: #force_inline proc "c" (painter_ : ^Painter, id_ : u32 , size_ : i32, region_ : Rectangle, color_ : u32 ) -> bool{ addr := 0x1000 + 115 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Painter, u32 , i32, Rectangle, u32 ) -> bool) (fp))(painter_, id_, size_, region_, color_); } -DrawStyledBox :: #force_inline proc "c" (painter_ : ^Painter, box_ : StyledBox){ addr := 0x1000 + 116 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, StyledBox)) (fp))(painter_, box_); } -DrawPaintTarget :: #force_inline proc "c" (painter_ : ^Painter, source_ : ^PaintTarget, destinationRegion_ : Rectangle, sourceRegion_ : Rectangle, borderRegion_ : Rectangle, mode_ : DrawMode, alpha_ : u16 , clipRegion_ : Rectangle){ addr := 0x1000 + 263 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, ^PaintTarget, Rectangle, Rectangle, Rectangle, DrawMode, u16 , Rectangle)) (fp))(painter_, source_, destinationRegion_, sourceRegion_, borderRegion_, mode_, alpha_, clipRegion_); } -DrawText :: #force_inline proc "c" (painter_ : ^Painter, plan_ : ^TextPlan, bounds_ : Rectangle, clip_ : ^Rectangle = nil, selectionProperties_ : ^TextSelection = nil){ addr := 0x1000 + 120 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, ^TextPlan, Rectangle, ^Rectangle, ^TextSelection)) (fp))(painter_, plan_, bounds_, clip_, selectionProperties_); } -FontGetName :: #force_inline proc "c" (family_ : u16 , buffer_ : ^i8 , bufferBytes_ : int ) -> int { addr := 0x1000 + 121 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( u16 , ^i8 , int ) -> int ) (fp))(family_, buffer_, bufferBytes_); } -IconIDFromString :: #force_inline proc "c" (string_ : string = "") -> u32 { addr := 0x1000 + 127 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int) -> u32 ) (fp))(raw_data(string_), len(string_)); } -ImageLoad :: #force_inline proc "c" (file_ : ^u8 , fileSize_ : int , width_ : ^u32 , height_ : ^u32 , imageChannels_ : i32) -> ^u8 { addr := 0x1000 + 165 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^u8 , int , ^u32 , ^u32 , i32) -> ^u8 ) (fp))(file_, fileSize_, width_, height_, imageChannels_); } -PainterBoundsClient :: #force_inline proc "c" (painter_ : ^Painter) -> Rectangle{ addr := 0x1000 + 122 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Painter) -> Rectangle) (fp))(painter_); } -PainterBoundsInset :: #force_inline proc "c" (painter_ : ^Painter) -> Rectangle{ addr := 0x1000 + 123 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Painter) -> Rectangle) (fp))(painter_); } -PainterDrawStandardContent :: #force_inline proc "c" (painter_ : ^Painter, text_ : string, iconID_ : u32 ){ addr := 0x1000 + 117 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Painter, ^u8, int, u32 )) (fp))(painter_, raw_data(text_), len(text_), iconID_); } -PaintTargetClear :: #force_inline proc "c" (target_ : ^PaintTarget){ addr := 0x1000 + 34 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^PaintTarget)) (fp))(target_); } -PaintTargetEndDirectAccess :: #force_inline proc "c" (target_ : ^PaintTarget){ addr := 0x1000 + 264 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^PaintTarget)) (fp))(target_); } -PaintTargetStartDirectAccess :: #force_inline proc "c" (target_ : ^PaintTarget, bits_ : ^^u32 , width_ : ^int , height_ : ^int , stride_ : ^int ){ addr := 0x1000 + 276 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^PaintTarget, ^^u32 , ^int , ^int , ^int )) (fp))(target_, bits_, width_, height_, stride_); } -PaintTargetTake :: #force_inline proc "c" (target_ : ^PaintTarget, width_ : int , height_ : int ) -> bool{ addr := 0x1000 + 35 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^PaintTarget, int , int ) -> bool) (fp))(target_, width_, height_); } -PaintTargetReturn :: #force_inline proc "c" (target_ : ^PaintTarget){ addr := 0x1000 + 36 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^PaintTarget)) (fp))(target_); } -TextGetLineHeight :: #force_inline proc "c" (font_ : Font, size_ : u16 ) -> i32{ addr := 0x1000 + 157 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Font, u16 ) -> i32) (fp))(font_, size_); } -TextGetPartialStringWidth :: #force_inline proc "c" (font_ : Font, size_ : u16 , fullString_ : ^i8 , fullStringBytes_ : int , measureOffset_ : uint , measureBytes_ : int ) -> i32{ addr := 0x1000 + 171 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Font, u16 , ^i8 , int , uint , int ) -> i32) (fp))(font_, size_, fullString_, fullStringBytes_, measureOffset_, measureBytes_); } -TextGetCharacterAtPoint :: #force_inline proc "c" (font_ : Font, size_ : u16 , fullString_ : ^i8 , fullStringBytes_ : int , measureOffset_ : uint , measureBytes_ : int , pointX_ : ^i32, reverse_ : bool, middle_ : bool) -> int { addr := 0x1000 + 237 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Font, u16 , ^i8 , int , uint , int , ^i32, bool, bool) -> int ) (fp))(font_, size_, fullString_, fullStringBytes_, measureOffset_, measureBytes_, pointX_, reverse_, middle_); } -AudioStreamClose :: #force_inline proc "c" (stream_ : ^AudioStream){ addr := 0x1000 + 128 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^AudioStream)) (fp))(stream_); } -AudioStreamOpen :: #force_inline proc "c" (device_ : AudioDeviceID, bufferLengthUs_ : int ) -> ^AudioStream{ addr := 0x1000 + 129 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( AudioDeviceID, int ) -> ^AudioStream) (fp))(device_, bufferLengthUs_); } -AudioStreamNotify :: #force_inline proc "c" (stream_ : ^AudioStream){ addr := 0x1000 + 130 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^AudioStream)) (fp))(stream_); } -AudioStreamSend :: #force_inline proc "c" (destination_ : ^AudioStream, source_ : ^AudioStream, time_ : ^f64 ) -> Error{ addr := 0x1000 + 131 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^AudioStream, ^AudioStream, ^f64 ) -> Error) (fp))(destination_, source_, time_); } -AddressResolve :: #force_inline proc "c" (domain_ : string, flags_ : u32 , address_ : ^Address) -> Error{ addr := 0x1000 + 99 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, u32 , ^Address) -> Error) (fp))(raw_data(domain_), len(domain_), flags_, address_); } -ConnectionClose :: #force_inline proc "c" (connection_ : ^Connection){ addr := 0x1000 + 321 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Connection)) (fp))(connection_); } -ConnectionNotify :: #force_inline proc "c" (connection_ : ^Connection){ addr := 0x1000 + 322 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Connection)) (fp))(connection_); } -ConnectionOpen :: #force_inline proc "c" (connection_ : ^Connection, flags_ : u32 ) -> Error{ addr := 0x1000 + 100 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Connection, u32 ) -> Error) (fp))(connection_, flags_); } -ConnectionPoll :: #force_inline proc "c" (connection_ : ^Connection){ addr := 0x1000 + 303 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Connection)) (fp))(connection_); } -ConnectionRead :: #force_inline proc "c" (connection_ : ^Connection, buffer_ : rawptr, bufferBytes_ : int , bytesRead_ : ^int ) -> Error{ addr := 0x1000 + 325 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Connection, rawptr, int , ^int ) -> Error) (fp))(connection_, buffer_, bufferBytes_, bytesRead_); } -ConnectionWriteSync :: #force_inline proc "c" (connection_ : ^Connection, data_ : rawptr, dataBytes_ : int ) -> Error{ addr := 0x1000 + 323 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Connection, rawptr, int ) -> Error) (fp))(connection_, data_, dataBytes_); } -GameControllerStatePoll :: #force_inline proc "c" (buffer_ : ^GameControllerState) -> int { addr := 0x1000 + 299 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^GameControllerState) -> int ) (fp))(buffer_); } -EventCreate :: #force_inline proc "c" (autoReset_ : bool) -> Handle{ addr := 0x1000 + 132 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( bool) -> Handle) (fp))(autoReset_); } -EventForward :: #force_inline proc "c" (event_ : Handle, eventSink_ : Handle, data_ : Generic){ addr := 0x1000 + 133 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, Handle, Generic)) (fp))(event_, eventSink_, data_); } -EventPoll :: #force_inline proc "c" (event_ : Handle) -> Error{ addr := 0x1000 + 134 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle) -> Error) (fp))(event_); } -EventReset :: #force_inline proc "c" (event_ : Handle){ addr := 0x1000 + 135 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle)) (fp))(event_); } -EventSet :: #force_inline proc "c" (event_ : Handle){ addr := 0x1000 + 136 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle)) (fp))(event_); } -EventSinkCreate :: #force_inline proc "c" (ignoreDuplicates_ : bool) -> Handle{ addr := 0x1000 + 137 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( bool) -> Handle) (fp))(ignoreDuplicates_); } -EventSinkPop :: #force_inline proc "c" (eventSink_ : Handle, data_ : ^Generic) -> Error{ addr := 0x1000 + 138 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, ^Generic) -> Error) (fp))(eventSink_, data_); } -EventSinkPush :: #force_inline proc "c" (eventSink_ : Handle, data_ : Generic) -> Error{ addr := 0x1000 + 139 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( Handle, Generic) -> Error) (fp))(eventSink_, data_); } -MutexAcquire :: #force_inline proc "c" (mutex_ : ^Mutex){ addr := 0x1000 + 140 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Mutex)) (fp))(mutex_); } -MutexDestroy :: #force_inline proc "c" (mutex_ : ^Mutex){ addr := 0x1000 + 141 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Mutex)) (fp))(mutex_); } -MutexRelease :: #force_inline proc "c" (mutex_ : ^Mutex){ addr := 0x1000 + 142 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Mutex)) (fp))(mutex_); } -PerformanceTimerPush :: #force_inline proc "c" (){ addr := 0x1000 + 143 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -PerformanceTimerPop :: #force_inline proc "c" () -> f64 { addr := 0x1000 + 144 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> f64 ) (fp))(); } -SchedulerYield :: #force_inline proc "c" (){ addr := 0x1000 + 145 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ()) (fp))(); } -Sleep :: #force_inline proc "c" (milliseconds_ : u64 ){ addr := 0x1000 + 146 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( u64 )) (fp))(milliseconds_); } -SpinlockAcquire :: #force_inline proc "c" (spinlock_ : ^Spinlock){ addr := 0x1000 + 147 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Spinlock)) (fp))(spinlock_); } -SpinlockRelease :: #force_inline proc "c" (spinlock_ : ^Spinlock){ addr := 0x1000 + 148 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Spinlock)) (fp))(spinlock_); } -TimerCreate :: #force_inline proc "c" () -> Handle{ addr := 0x1000 + 149 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" () -> Handle) (fp))(); } -TimerSet :: #force_inline proc "c" (handle_ : Handle, afterMs_ : u64 , callback_ : TimerCallbackFunction, argument_ : Generic){ addr := 0x1000 + 150 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( Handle, u64 , TimerCallbackFunction, Generic)) (fp))(handle_, afterMs_, callback_, argument_); } -Wait :: #force_inline proc "c" (objects_ : ^Handle, objectCount_ : int , timeoutMs_ : uint ) -> uint { addr := 0x1000 + 151 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Handle, int , uint ) -> uint ) (fp))(objects_, objectCount_, timeoutMs_); } -CStringLength :: #force_inline proc "c" (string_ : cstring ) -> int { addr := 0x1000 + 152 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( cstring ) -> int ) (fp))(string_); } -StringAllocateAndFormat :: #force_inline proc "c" (bytes_ : ^int , format_ : cstring , _varargs_ : ..any) -> ^i8 { addr := 0x1000 + 153 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^int , cstring , ..any) -> ^i8 ) (fp))(bytes_, format_, _varargs_); } -StringCompare :: #force_inline proc "c" (s1_ : string, s2_ : string) -> i32{ addr := 0x1000 + 155 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^u8, int) -> i32) (fp))(raw_data(s1_), len(s1_), raw_data(s2_), len(s2_)); } -StringCompareRaw :: #force_inline proc "c" (s1_ : string, s2_ : string) -> i32{ addr := 0x1000 + 156 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^u8, int) -> i32) (fp))(raw_data(s1_), len(s1_), raw_data(s2_), len(s2_)); } -StringFormat :: #force_inline proc "c" (buffer_ : ^i8 , bufferLength_ : int , format_ : cstring , _varargs_ : ..any) -> int { addr := 0x1000 + 158 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int , cstring , ..any) -> int ) (fp))(buffer_, bufferLength_, format_, _varargs_); } -StringFormatTemporary :: #force_inline proc "c" (format_ : cstring , _varargs_ : ..any) -> ^i8 { addr := 0x1000 + 159 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( cstring , ..any) -> ^i8 ) (fp))(format_, _varargs_); } -StringFormatAppend :: #force_inline proc "c" (buffer_ : ^i8 , bufferLength_ : int , bufferPosition_ : ^int , format_ : cstring , _varargs_ : ..any) -> bool{ addr := 0x1000 + 161 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int , ^int , cstring , ..any) -> bool) (fp))(buffer_, bufferLength_, bufferPosition_, format_, _varargs_); } -StringLength :: #force_inline proc "c" (string_ : ^i8 , end_ : u8 ) -> int { addr := 0x1000 + 163 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , u8 ) -> int ) (fp))(string_, end_); } -StringStartsWith :: #force_inline proc "c" (string_ : string, prefix_ : string, caseInsensitive_ : bool) -> bool{ addr := 0x1000 + 166 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int, ^u8, int, bool) -> bool) (fp))(raw_data(string_), len(string_), raw_data(prefix_), len(prefix_), caseInsensitive_); } -StringZeroTerminate :: #force_inline proc "c" (string_ : string) -> ^i8 { addr := 0x1000 + 167 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" (^u8, int) -> ^i8 ) (fp))(raw_data(string_), len(string_)); } -CRTabs :: #force_inline proc "c" (n_ : i32) -> i32{ addr := 0x1000 + 168 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(n_); } -CRTacosf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 169 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTasinf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 170 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTatan2f :: #force_inline proc "c" (y_ : f32 , x_ : f32 ) -> f32 { addr := 0x1000 + 172 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 , f32 ) -> f32 ) (fp))(y_, x_); } -CRTatanf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 173 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTatoi :: #force_inline proc "c" (string_ : ^i8 ) -> i32{ addr := 0x1000 + 174 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 ) -> i32) (fp))(string_); } -CRTcalloc :: #force_inline proc "c" (num_ : int , size_ : int ) -> rawptr{ addr := 0x1000 + 175 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int , int ) -> rawptr) (fp))(num_, size_); } -CRTceil :: #force_inline proc "c" (x_ : f64 ) -> f64 { addr := 0x1000 + 176 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f64 ) -> f64 ) (fp))(x_); } -CRTceilf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 177 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTcosf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 178 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTexp :: #force_inline proc "c" (x_ : f64 ) -> f64 { addr := 0x1000 + 326 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f64 ) -> f64 ) (fp))(x_); } -CRTexp2f :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 327 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTfabs :: #force_inline proc "c" (x_ : f64 ) -> f64 { addr := 0x1000 + 179 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f64 ) -> f64 ) (fp))(x_); } -CRTfabsf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 344 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTfloor :: #force_inline proc "c" (x_ : f64 ) -> f64 { addr := 0x1000 + 181 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f64 ) -> f64 ) (fp))(x_); } -CRTfloorf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 182 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTfmodf :: #force_inline proc "c" (x_ : f32 , y_ : f32 ) -> f32 { addr := 0x1000 + 183 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 , f32 ) -> f32 ) (fp))(x_, y_); } -CRTfree :: #force_inline proc "c" (ptr_ : rawptr){ addr := 0x1000 + 184 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr)) (fp))(ptr_); } -CRTgetenv :: #force_inline proc "c" (name_ : ^i8 ) -> ^i8 { addr := 0x1000 + 185 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 ) -> ^i8 ) (fp))(name_); } -CRTisalpha :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 186 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -CRTisdigit :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 187 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -CRTisnanf :: #force_inline proc "c" (f_ : f32 ) -> bool{ addr := 0x1000 + 345 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> bool) (fp))(f_); } -CRTisspace :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 188 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -CRTisupper :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 189 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -CRTisxdigit :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 190 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -CRTmalloc :: #force_inline proc "c" (size_ : int ) -> rawptr{ addr := 0x1000 + 191 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( int ) -> rawptr) (fp))(size_); } -CRTmemchr :: #force_inline proc "c" (_s_ : rawptr, _c_ : i32, n_ : int ) -> rawptr{ addr := 0x1000 + 192 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, i32, int ) -> rawptr) (fp))(_s_, _c_, n_); } -CRTmemcmp :: #force_inline proc "c" (s1_ : rawptr, s2_ : rawptr, n_ : int ) -> i32{ addr := 0x1000 + 193 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, rawptr, int ) -> i32) (fp))(s1_, s2_, n_); } -CRTmemcpy :: #force_inline proc "c" (dest_ : rawptr, src_ : rawptr, n_ : int ) -> rawptr{ addr := 0x1000 + 194 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, rawptr, int ) -> rawptr) (fp))(dest_, src_, n_); } -CRTmemmove :: #force_inline proc "c" (dest_ : rawptr, src_ : rawptr, n_ : int ) -> rawptr{ addr := 0x1000 + 195 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, rawptr, int ) -> rawptr) (fp))(dest_, src_, n_); } -CRTmemset :: #force_inline proc "c" (s_ : rawptr, c_ : i32, n_ : int ) -> rawptr{ addr := 0x1000 + 196 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, i32, int ) -> rawptr) (fp))(s_, c_, n_); } -CRTpowf :: #force_inline proc "c" (x_ : f32 , y_ : f32 ) -> f32 { addr := 0x1000 + 328 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 , f32 ) -> f32 ) (fp))(x_, y_); } -CRTqsort :: #force_inline proc "c" (_base_ : rawptr, nmemb_ : int , size_ : int , compar_ : CRTComparisonCallback){ addr := 0x1000 + 197 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( rawptr, int , int , CRTComparisonCallback)) (fp))(_base_, nmemb_, size_, compar_); } -CRTrealloc :: #force_inline proc "c" (ptr_ : rawptr, size_ : int ) -> rawptr{ addr := 0x1000 + 198 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( rawptr, int ) -> rawptr) (fp))(ptr_, size_); } -CRTsinf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 199 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTsnprintf :: #force_inline proc "c" (buffer_ : ^i8 , bufferSize_ : int , format_ : ^i8 , _varargs_ : ..any) -> i32{ addr := 0x1000 + 200 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int , ^i8 , ..any) -> i32) (fp))(buffer_, bufferSize_, format_, _varargs_); } -CRTsprintf :: #force_inline proc "c" (buffer_ : ^i8 , format_ : ^i8 , _varargs_ : ..any) -> i32{ addr := 0x1000 + 201 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 , ..any) -> i32) (fp))(buffer_, format_, _varargs_); } -CRTsqrt :: #force_inline proc "c" (x_ : f64 ) -> f64 { addr := 0x1000 + 202 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f64 ) -> f64 ) (fp))(x_); } -CRTsqrtf :: #force_inline proc "c" (x_ : f32 ) -> f32 { addr := 0x1000 + 203 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( f32 ) -> f32 ) (fp))(x_); } -CRTstrcat :: #force_inline proc "c" (dest_ : ^i8 , src_ : ^i8 ) -> ^i8 { addr := 0x1000 + 205 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 ) -> ^i8 ) (fp))(dest_, src_); } -CRTstrchr :: #force_inline proc "c" (s_ : ^i8 , c_ : i32) -> ^i8 { addr := 0x1000 + 206 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , i32) -> ^i8 ) (fp))(s_, c_); } -CRTstrcmp :: #force_inline proc "c" (s1_ : ^i8 , s2_ : ^i8 ) -> i32{ addr := 0x1000 + 207 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 ) -> i32) (fp))(s1_, s2_); } -CRTstrcpy :: #force_inline proc "c" (dest_ : ^i8 , src_ : ^i8 ) -> ^i8 { addr := 0x1000 + 208 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 ) -> ^i8 ) (fp))(dest_, src_); } -CRTstrdup :: #force_inline proc "c" (string_ : ^i8 ) -> ^i8 { addr := 0x1000 + 70 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 ) -> ^i8 ) (fp))(string_); } -CRTstrerror :: #force_inline proc "c" (errnum_ : i32) -> ^i8 { addr := 0x1000 + 209 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> ^i8 ) (fp))(errnum_); } -CRTstrlen :: #force_inline proc "c" (s_ : ^i8 ) -> int { addr := 0x1000 + 210 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 ) -> int ) (fp))(s_); } -CRTstrncmp :: #force_inline proc "c" (s1_ : ^i8 , s2_ : ^i8 , n_ : int ) -> i32{ addr := 0x1000 + 211 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 , int ) -> i32) (fp))(s1_, s2_, n_); } -CRTstrncpy :: #force_inline proc "c" (dest_ : ^i8 , src_ : ^i8 , n_ : int ) -> ^i8 { addr := 0x1000 + 212 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 , int ) -> ^i8 ) (fp))(dest_, src_, n_); } -CRTstrnlen :: #force_inline proc "c" (s_ : ^i8 , maxlen_ : int ) -> int { addr := 0x1000 + 213 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , int ) -> int ) (fp))(s_, maxlen_); } -CRTstrstr :: #force_inline proc "c" (haystack_ : ^i8 , needle_ : ^i8 ) -> ^i8 { addr := 0x1000 + 214 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^i8 ) -> ^i8 ) (fp))(haystack_, needle_); } -CRTstrtol :: #force_inline proc "c" (nptr_ : ^i8 , endptr_ : ^^i8 , base_ : i32) -> i64 { addr := 0x1000 + 215 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^^i8 , i32) -> i64 ) (fp))(nptr_, endptr_, base_); } -CRTstrtoul :: #force_inline proc "c" (nptr_ : ^i8 , endptr_ : ^^i8 , base_ : i32) -> u64 { addr := 0x1000 + 216 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^i8 , ^^i8 , i32) -> u64 ) (fp))(nptr_, endptr_, base_); } -CRTtolower :: #force_inline proc "c" (c_ : i32) -> i32{ addr := 0x1000 + 217 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( i32) -> i32) (fp))(c_); } -NewPanel :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^Panel{ addr := 0x1000 + 219 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^Panel) (fp))(parent_, flags_, cStyle_); } -NewSplitter :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^Splitter{ addr := 0x1000 + 220 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^Splitter) (fp))(parent_, flags_, cStyle_); } -NewButton :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil, label_ : string = "") -> ^Button{ addr := 0x1000 + 221 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring , ^u8, int) -> ^Button) (fp))(parent_, flags_, cStyle_, raw_data(label_), len(label_)); } -NewChoice :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^Choice{ addr := 0x1000 + 222 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^Choice) (fp))(parent_, flags_, cStyle_); } -NewColorWell :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil, colorRGB_ : u32 = 0) -> ^ColorWell{ addr := 0x1000 + 223 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring , u32 ) -> ^ColorWell) (fp))(parent_, flags_, cStyle_, colorRGB_); } -NewTextDisplay :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil, label_ : string = "") -> ^TextDisplay{ addr := 0x1000 + 224 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring , ^u8, int) -> ^TextDisplay) (fp))(parent_, flags_, cStyle_, raw_data(label_), len(label_)); } -NewIconDisplay :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil, iconID_ : u32 = 0) -> ^IconDisplay{ addr := 0x1000 + 225 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring , u32 ) -> ^IconDisplay) (fp))(parent_, flags_, cStyle_, iconID_); } -NewImageDisplay :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^ImageDisplay{ addr := 0x1000 + 226 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^ImageDisplay) (fp))(parent_, flags_, cStyle_); } -NewListView :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil, cItemStyle_ : cstring = nil, cHeaderItemStyle_ : cstring = nil, cFooterItemStyle_ : cstring = nil) -> ^ListView{ addr := 0x1000 + 227 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring , cstring , cstring , cstring ) -> ^ListView) (fp))(parent_, flags_, cStyle_, cItemStyle_, cHeaderItemStyle_, cFooterItemStyle_); } -NewTextbox :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^Textbox{ addr := 0x1000 + 228 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^Textbox) (fp))(parent_, flags_, cStyle_); } -NewCustomElement :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, cStyle_ : cstring = nil) -> ^Element{ addr := 0x1000 + 229 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , cstring ) -> ^Element) (fp))(parent_, flags_, cStyle_); } -NewWindow :: #force_inline proc "c" (instance_ : ^INSTANCE_TYPE, style_ : WindowStyle) -> ^Window{ addr := 0x1000 + 230 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^INSTANCE_TYPE, WindowStyle) -> ^Window) (fp))(instance_, style_); } -NewMenu :: #force_inline proc "c" (source_ : ^Element, flags_ : u64 = FLAGS_DEFAULT, userCallback_ : MenuCallbackFunction = nil, _context_ : Generic = nil, fixedWidth_ : i32 = 0, fixedHeight_ : i32 = 0) -> ^Menu{ addr := 0x1000 + 231 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 , MenuCallbackFunction, Generic, i32, i32) -> ^Menu) (fp))(source_, flags_, userCallback_, _context_, fixedWidth_, fixedHeight_); } -NewMenuItem :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 , label_ : string = "", callback_ : MenuCallbackFunction = nil, _context_ : Generic = nil){ addr := 0x1000 + 232 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, u64 , ^u8, int, MenuCallbackFunction, Generic)) (fp))(parent_, flags_, raw_data(label_), len(label_), callback_, _context_); } -NewMenuCommand :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 , label_ : string, command_ : ^Command){ addr := 0x1000 + 233 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, u64 , ^u8, int, ^Command)) (fp))(parent_, flags_, raw_data(label_), len(label_), command_); } -NewMenuColumn :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 = FLAGS_DEFAULT) -> ^Element{ addr := 0x1000 + 234 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 ) -> ^Element) (fp))(parent_, flags_); } -NewMenuSeparator :: #force_inline proc "c" (parent_ : ^Element){ addr := 0x1000 + 235 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element)) (fp))(parent_); } -NewSpacer :: #force_inline proc "c" (parent_ : ^Element, flags_ : u64 ) -> ^Element{ addr := 0x1000 + 236 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element, u64 ) -> ^Element) (fp))(parent_, flags_); } -NewTextPlan :: #force_inline proc "c" (properties_ : ^TextDisplayProperties, bounds_ : Rectangle, string_ : ^i8 , textRuns_ : ^TextRun, textRunCount_ : int , singleUse_ : bool) -> ^TextPlan{ addr := 0x1000 + 238 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^TextDisplayProperties, Rectangle, ^i8 , ^TextRun, int , bool) -> ^TextPlan) (fp))(properties_, bounds_, string_, textRuns_, textRunCount_, singleUse_); } -ElementDraw :: #force_inline proc "c" (element_ : ^Element, painter_ : ^Painter){ addr := 0x1000 + 240 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, ^Painter)) (fp))(element_, painter_); } -ElementFocus :: #force_inline proc "c" (element_ : ^Element, ensureVisible_ : bool = false){ addr := 0x1000 + 243 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, bool)) (fp))(element_, ensureVisible_); } -ElementSetDisabled :: #force_inline proc "c" (element_ : ^Element, disabled_ : bool = true){ addr := 0x1000 + 244 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, bool)) (fp))(element_, disabled_); } -ElementSetHidden :: #force_inline proc "c" (element_ : ^Element, hidden_ : bool = true){ addr := 0x1000 + 245 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, bool)) (fp))(element_, hidden_); } -ElementSetCallback :: #force_inline proc "c" (element_ : ^Element, callback_ : UICallbackFunction){ addr := 0x1000 + 246 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, UICallbackFunction)) (fp))(element_, callback_); } -ElementGetSize :: #force_inline proc "c" (element_ : ^Element, width_ : ^i32, height_ : ^i32){ addr := 0x1000 + 247 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, ^i32, ^i32)) (fp))(element_, width_, height_); } -ElementRepaint :: #force_inline proc "c" (element_ : ^Element, all_ : bool, region_ : Rectangle){ addr := 0x1000 + 248 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, bool, Rectangle)) (fp))(element_, all_, region_); } -ElementSetCellRange :: #force_inline proc "c" (element_ : ^Element, xFrom_ : i32, yFrom_ : i32, xTo_ : i32 = -1, yTo_ : i32 = -1){ addr := 0x1000 + 251 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, i32, i32, i32, i32)) (fp))(element_, xFrom_, yFrom_, xTo_, yTo_); } -ElementGetInsets :: #force_inline proc "c" (element_ : ^Element) -> Rectangle{ addr := 0x1000 + 253 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> Rectangle) (fp))(element_); } -ElementGetInsetSize :: #force_inline proc "c" (element_ : ^Element) -> Rectangle{ addr := 0x1000 + 254 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> Rectangle) (fp))(element_); } -ElementGetMetrics :: #force_inline proc "c" (element_ : ^Element) -> ThemeMetrics{ addr := 0x1000 + 105 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> ThemeMetrics) (fp))(element_); } -ElementGetPreferredSize :: #force_inline proc "c" (element_ : ^Element) -> Rectangle{ addr := 0x1000 + 255 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> Rectangle) (fp))(element_); } -ElementMove :: #force_inline proc "c" (element_ : ^Element, x_ : i32, y_ : i32, width_ : i32, height_ : i32){ addr := 0x1000 + 256 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element, i32, i32, i32, i32)) (fp))(element_, x_, y_, width_, height_); } -ElementGetLayoutParent :: #force_inline proc "c" (element_ : ^Element) -> ^Element{ addr := 0x1000 + 257 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> ^Element) (fp))(element_); } -ElementDestroy :: #force_inline proc "c" (element_ : ^Element){ addr := 0x1000 + 258 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element)) (fp))(element_); } -ElementDestroyContents :: #force_inline proc "c" (element_ : ^Element){ addr := 0x1000 + 259 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Element)) (fp))(element_); } -ElementStartAnimating :: #force_inline proc "c" (element_ : ^Element) -> bool{ addr := 0x1000 + 260 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Element) -> bool) (fp))(element_); } -WindowGetBounds :: #force_inline proc "c" (window_ : ^Window) -> Rectangle{ addr := 0x1000 + 265 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Window) -> Rectangle) (fp))(window_); } -WindowGetToolbar :: #force_inline proc "c" (window_ : ^Window) -> ^Element{ addr := 0x1000 + 266 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Window) -> ^Element) (fp))(window_); } -WindowSetIcon :: #force_inline proc "c" (window_ : ^Window, iconID_ : u32 ){ addr := 0x1000 + 267 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Window, u32 )) (fp))(window_, iconID_); } -WindowSetTitle :: #force_inline proc "c" (window_ : ^Window, title_ : string = ""){ addr := 0x1000 + 268 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Window, ^u8, int)) (fp))(window_, raw_data(title_), len(title_)); } -MenuGetSource :: #force_inline proc "c" (menu_ : ^Menu) -> ^Element{ addr := 0x1000 + 269 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Menu) -> ^Element) (fp))(menu_); } -ButtonSetIcon :: #force_inline proc "c" (button_ : ^Button, iconID_ : u32 ){ addr := 0x1000 + 270 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Button, u32 )) (fp))(button_, iconID_); } -ButtonSetCheck :: #force_inline proc "c" (button_ : ^Button, checkState_ : CheckState = CHECK_CHECKED, sendUpdatedMessage_ : bool = true){ addr := 0x1000 + 271 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Button, CheckState, bool)) (fp))(button_, checkState_, sendUpdatedMessage_); } -ButtonGetCheck :: #force_inline proc "c" (button_ : ^Button) -> CheckState{ addr := 0x1000 + 272 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Button) -> CheckState) (fp))(button_); } -ButtonOnCommand :: #force_inline proc "c" (button_ : ^Button, callback_ : CommandCallbackFunction, command_ : ^Command = nil){ addr := 0x1000 + 273 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Button, CommandCallbackFunction, ^Command)) (fp))(button_, callback_, command_); } -ButtonSetCheckBuddy :: #force_inline proc "c" (button_ : ^Button, checkBuddy_ : ^Element){ addr := 0x1000 + 274 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Button, ^Element)) (fp))(button_, checkBuddy_); } -ButtonGetCheckBuddy :: #force_inline proc "c" (button_ : ^Button) -> ^Element{ addr := 0x1000 + 275 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Button) -> ^Element) (fp))(button_); } -TextboxFind :: #force_inline proc "c" (textbox_ : ^Textbox, string_ : string, line_ : ^i32 , byte_ : ^i32 , flags_ : u32 ) -> bool{ addr := 0x1000 + 277 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Textbox, ^u8, int, ^i32 , ^i32 , u32 ) -> bool) (fp))(textbox_, raw_data(string_), len(string_), line_, byte_, flags_); } -TextboxInsert :: #force_inline proc "c" (textbox_ : ^Textbox, string_ : string = "", sendUpdatedMessage_ : bool = true){ addr := 0x1000 + 278 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, ^u8, int, bool)) (fp))(textbox_, raw_data(string_), len(string_), sendUpdatedMessage_); } -TextboxGetContents :: #force_inline proc "c" (textbox_ : ^Textbox, bytes_ : ^int = nil) -> ^i8 { addr := 0x1000 + 279 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Textbox, ^int ) -> ^i8 ) (fp))(textbox_, bytes_); } -TextboxGetLineLength :: #force_inline proc "c" (textbox_ : ^Textbox, line_ : uint = 0) -> int { addr := 0x1000 + 280 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Textbox, uint ) -> int ) (fp))(textbox_, line_); } -TextboxGetSelection :: #force_inline proc "c" (textbox_ : ^Textbox, fromLine_ : ^i32 , fromByte_ : ^i32 , toLine_ : ^i32 , toByte_ : ^i32 ){ addr := 0x1000 + 281 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, ^i32 , ^i32 , ^i32 , ^i32 )) (fp))(textbox_, fromLine_, fromByte_, toLine_, toByte_); } -TextboxMoveCaret :: #force_inline proc "c" (textbox_ : ^Textbox, line_ : i32 , byte_ : i32 ){ addr := 0x1000 + 282 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, i32 , i32 )) (fp))(textbox_, line_, byte_); } -TextboxSetSelection :: #force_inline proc "c" (textbox_ : ^Textbox, fromLine_ : i32 , fromByte_ : i32 , toLine_ : i32 , toByte_ : i32 ){ addr := 0x1000 + 283 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, i32 , i32 , i32 , i32 )) (fp))(textbox_, fromLine_, fromByte_, toLine_, toByte_); } -TextboxSelectAll :: #force_inline proc "c" (textbox_ : ^Textbox){ addr := 0x1000 + 284 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox)) (fp))(textbox_); } -TextboxClear :: #force_inline proc "c" (textbox_ : ^Textbox, sendUpdatedMessage_ : bool){ addr := 0x1000 + 285 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, bool)) (fp))(textbox_, sendUpdatedMessage_); } -TextboxUseNumberOverlay :: #force_inline proc "c" (textbox_ : ^Textbox, defaultBehaviour_ : bool){ addr := 0x1000 + 286 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, bool)) (fp))(textbox_, defaultBehaviour_); } -TextboxUseBreadcrumbOverlay :: #force_inline proc "c" (textbox_ : ^Textbox){ addr := 0x1000 + 287 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox)) (fp))(textbox_); } -TextboxMoveCaretRelative :: #force_inline proc "c" (textbox_ : ^Textbox, flags_ : u32 ){ addr := 0x1000 + 118 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox, u32 )) (fp))(textbox_, flags_); } -TextboxEnsureCaretVisible :: #force_inline proc "c" (textbox_ : ^Textbox){ addr := 0x1000 + 119 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Textbox)) (fp))(textbox_); } -PanelSetBands :: #force_inline proc "c" (panel_ : ^Panel, columnCount_ : int , rowCount_ : int = 0, columns_ : ^PanelBand = nil, rows_ : ^PanelBand = nil){ addr := 0x1000 + 288 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Panel, int , int , ^PanelBand, ^PanelBand)) (fp))(panel_, columnCount_, rowCount_, columns_, rows_); } -PanelSwitchTo :: #force_inline proc "c" (panel_ : ^Panel, targetChild_ : ^Element, transitionType_ : TransitionType, destroyPreviousAfterTransitionCompletes_ : bool = false){ addr := 0x1000 + 289 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Panel, ^Element, TransitionType, bool)) (fp))(panel_, targetChild_, transitionType_, destroyPreviousAfterTransitionCompletes_); } -TextPlanGetWidth :: #force_inline proc "c" (plan_ : ^TextPlan) -> i32{ addr := 0x1000 + 290 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^TextPlan) -> i32) (fp))(plan_); } -TextPlanGetHeight :: #force_inline proc "c" (plan_ : ^TextPlan) -> i32{ addr := 0x1000 + 291 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^TextPlan) -> i32) (fp))(plan_); } -TextPlanGetLineCount :: #force_inline proc "c" (plan_ : ^TextPlan) -> int { addr := 0x1000 + 292 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^TextPlan) -> int ) (fp))(plan_); } -TextPlanDestroy :: #force_inline proc "c" (plan_ : ^TextPlan){ addr := 0x1000 + 293 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^TextPlan)) (fp))(plan_); } -TextDisplaySetContents :: #force_inline proc "c" (display_ : ^TextDisplay, contents_ : string = ""){ addr := 0x1000 + 294 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^TextDisplay, ^u8, int)) (fp))(display_, raw_data(contents_), len(contents_)); } -ColorWellGetRGB :: #force_inline proc "c" (well_ : ^ColorWell) -> u32 { addr := 0x1000 + 304 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^ColorWell) -> u32 ) (fp))(well_); } -ColorWellSetRGB :: #force_inline proc "c" (well_ : ^ColorWell, colorRGB_ : u32 , sendChangedMessage_ : bool){ addr := 0x1000 + 305 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ColorWell, u32 , bool)) (fp))(well_, colorRGB_, sendChangedMessage_); } -ColorWellSetIndeterminate :: #force_inline proc "c" (well_ : ^ColorWell){ addr := 0x1000 + 306 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ColorWell)) (fp))(well_); } -ChoiceAddMenuItem :: #force_inline proc "c" (choice_ : ^Choice, item_ : Generic){ addr := 0x1000 + 307 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Choice, Generic)) (fp))(choice_, item_); } -ChoiceSetItem :: #force_inline proc "c" (choice_ : ^Choice, item_ : Generic, sendUpdatedMessage_ : bool = true){ addr := 0x1000 + 308 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^Choice, Generic, bool)) (fp))(choice_, item_, sendUpdatedMessage_); } -ChoiceGetItem :: #force_inline proc "c" (choice_ : ^Choice) -> Generic{ addr := 0x1000 + 309 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^Choice) -> Generic) (fp))(choice_); } -ListViewInsertGroup :: #force_inline proc "c" (view_ : ^ListView, group_ : i32 , flags_ : u32 = FLAGS_DEFAULT){ addr := 0x1000 + 310 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, i32 , u32 )) (fp))(view_, group_, flags_); } -ListViewInsert :: #force_inline proc "c" (view_ : ^ListView, group_ : i32 , firstIndex_ : Generic, lastIndex_ : Generic, count_ : i64 = -1){ addr := 0x1000 + 311 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, i32 , Generic, Generic, i64 )) (fp))(view_, group_, firstIndex_, lastIndex_, count_); } -ListViewRemove :: #force_inline proc "c" (view_ : ^ListView, group_ : i32 , firstIndex_ : Generic, lastIndex_ : Generic, count_ : i64 = -1){ addr := 0x1000 + 312 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, i32 , Generic, Generic, i64 )) (fp))(view_, group_, firstIndex_, lastIndex_, count_); } -ListViewRemoveAll :: #force_inline proc "c" (view_ : ^ListView, group_ : i32 ){ addr := 0x1000 + 313 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, i32 )) (fp))(view_, group_); } -ListViewGetIndex :: #force_inline proc "c" (view_ : ^ListView, item_ : ^Element) -> Generic{ addr := 0x1000 + 314 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); return ((proc "c" ( ^ListView, ^Element) -> Generic) (fp))(view_, item_); } -ListViewSetColumns :: #force_inline proc "c" (view_ : ^ListView, columns_ : ^ListViewColumn, columnCount_ : int ){ addr := 0x1000 + 315 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, ^ListViewColumn, int )) (fp))(view_, columns_, columnCount_); } -ListViewSetEmptyMessage :: #force_inline proc "c" (view_ : ^ListView, message_ : string = ""){ addr := 0x1000 + 262 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, ^u8, int)) (fp))(view_, raw_data(message_), len(message_)); } -ListViewSelect :: #force_inline proc "c" (view_ : ^ListView, group_ : i32 , index_ : Generic){ addr := 0x1000 + 316 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView, i32 , Generic)) (fp))(view_, group_, index_); } -ListViewResetSearchBuffer :: #force_inline proc "c" (view_ : ^ListView){ addr := 0x1000 + 317 * size_of(int); fp := (rawptr(((^uintptr)(uintptr(addr)))^)); ((proc "c" ( ^ListView)) (fp))(view_); } diff --git a/core/sys/freebsd/constants.odin b/core/sys/freebsd/constants.odin new file mode 100644 index 000000000..692cfc0fe --- /dev/null +++ b/core/sys/freebsd/constants.odin @@ -0,0 +1,19 @@ +package sys_freebsd + +/* Get window size */ +TIOCGWINSZ :: 0x40087468 + +/* + Standard input file descriptor +*/ +STDIN_FILENO :: Fd(0) + +/* + Standard output file descriptor +*/ +STDOUT_FILENO :: Fd(1) + +/* + Standard error file descriptor +*/ +STDERR_FILENO :: Fd(2) diff --git a/core/sys/freebsd/syscalls.odin b/core/sys/freebsd/syscalls.odin index 405d1e47c..ad10a9d62 100644 --- a/core/sys/freebsd/syscalls.odin +++ b/core/sys/freebsd/syscalls.odin @@ -2,7 +2,7 @@ package sys_freebsd /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -23,6 +23,7 @@ SYS_recvfrom : uintptr : 29 SYS_accept : uintptr : 30 SYS_getpeername: uintptr : 31 SYS_getsockname: uintptr : 32 +SYS_ioctl : uintptr : 54 SYS_fcntl : uintptr : 92 SYS_fsync : uintptr : 95 SYS_socket : uintptr : 97 @@ -62,7 +63,7 @@ read :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) { // // The write() function appeared in Version 1 AT&T UNIX. write :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) { - result, ok := intrinsics.syscall_bsd(SYS_pwrite, + result, ok := intrinsics.syscall_bsd(SYS_write, cast(uintptr)fd, cast(uintptr)raw_data(buf), cast(uintptr)len(buf)) @@ -204,21 +205,21 @@ accept_nil :: proc "contextless" (s: Fd) -> (Fd, Errno) { accept :: proc { accept_T, accept_nil } getsockname_or_peername :: proc "contextless" (s: Fd, sockaddr: ^$T, is_peer: bool) -> Errno { - // sockaddr must contain a valid pointer, or this will segfault because - // we're telling the syscall that there's memory available to write to. - addrlen: socklen_t = size_of(T) + // sockaddr must contain a valid pointer, or this will segfault because + // we're telling the syscall that there's memory available to write to. + addrlen: socklen_t = size_of(T) - result, ok := intrinsics.syscall_bsd( - is_peer ? SYS_getpeername : SYS_getsockname, - cast(uintptr)s, - cast(uintptr)sockaddr, - cast(uintptr)&addrlen) + result, ok := intrinsics.syscall_bsd( + is_peer ? SYS_getpeername : SYS_getsockname, + cast(uintptr)s, + cast(uintptr)sockaddr, + cast(uintptr)&addrlen) - if !ok { - return cast(Errno)result - } + if !ok { + return cast(Errno)result + } - return nil + return nil } // Get name of connected peer @@ -634,3 +635,13 @@ accept4_nil :: proc "contextless" (s: Fd, flags: Socket_Flags = {}) -> (Fd, Errn } accept4 :: proc { accept4_nil, accept4_T } + +ioctl :: proc "contextless" (fd: Fd, request: c.ulong, arg: uintptr) -> (int, Errno) { + result, ok := intrinsics.syscall_bsd(SYS_ioctl, cast(uintptr)fd, arg) + + if !ok { + return -1, cast(Errno)result + } + + return cast(int)result, nil +} diff --git a/core/sys/freebsd/types.odin b/core/sys/freebsd/types.odin index 37e8abf68..c6b13ef91 100644 --- a/core/sys/freebsd/types.odin +++ b/core/sys/freebsd/types.odin @@ -2,7 +2,7 @@ package sys_freebsd /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/sys/haiku/errno.odin b/core/sys/haiku/errno.odin deleted file mode 100644 index ef5a360bd..000000000 --- a/core/sys/haiku/errno.odin +++ /dev/null @@ -1,302 +0,0 @@ -#+build haiku -package sys_haiku - -import "core:sys/posix" - -foreign import libroot "system:c" - -USE_POSITIVE_POSIX_ERRORS :: posix._HAIKU_USE_POSITIVE_POSIX_ERRORS -POSIX_ERROR_FACTOR :: posix._POSIX_ERROR_FACTOR - -// Error baselines -GENERAL_ERROR_BASE :: min(i32) -OS_ERROR_BASE :: GENERAL_ERROR_BASE + 0x1000 -APP_ERROR_BASE :: GENERAL_ERROR_BASE + 0x2000 -INTERFACE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x3000 -MEDIA_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4000 -TRANSLATION_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4800 -MIDI_ERROR_BASE :: GENERAL_ERROR_BASE + 0x5000 -STORAGE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x6000 -POSIX_ERROR_BASE :: GENERAL_ERROR_BASE + 0x7000 -MAIL_ERROR_BASE :: GENERAL_ERROR_BASE + 0x8000 -PRINT_ERROR_BASE :: GENERAL_ERROR_BASE + 0x9000 -DEVICE_ERROR_BASE :: GENERAL_ERROR_BASE + 0xA000 - -// Developer-defined errors start at (ERRORS_END+1) -ERRORS_END :: GENERAL_ERROR_BASE + 0xFFFF - -Errno :: enum i32 { - // General Errors - NO_MEMORY = GENERAL_ERROR_BASE + 0, - IO_ERROR = GENERAL_ERROR_BASE + 1, - PERMISSION_DENIED = GENERAL_ERROR_BASE + 2, - BAD_INDEX = GENERAL_ERROR_BASE + 3, - BAD_TYPE = GENERAL_ERROR_BASE + 4, - BAD_VALUE = GENERAL_ERROR_BASE + 5, - MISMATCHED_VALUES = GENERAL_ERROR_BASE + 6, - NAME_NOT_FOUND = GENERAL_ERROR_BASE + 7, - NAME_IN_USE = GENERAL_ERROR_BASE + 8, - TIMED_OUT = GENERAL_ERROR_BASE + 9, - INTERRUPTED = GENERAL_ERROR_BASE + 10, - WOULD_BLOCK = GENERAL_ERROR_BASE + 11, - CANCELED = GENERAL_ERROR_BASE + 12, - NO_INIT = GENERAL_ERROR_BASE + 13, - NOT_INITIALIZED = GENERAL_ERROR_BASE + 13, - BUSY = GENERAL_ERROR_BASE + 14, - NOT_ALLOWED = GENERAL_ERROR_BASE + 15, - BAD_DATA = GENERAL_ERROR_BASE + 16, - DONT_DO_THAT = GENERAL_ERROR_BASE + 17, - - ERROR = -1, - OK = 0, - NO_ERROR = 0, - - // Kernel Kit Errors - BAD_SEM_ID = OS_ERROR_BASE + 0, - NO_MORE_SEMS = OS_ERROR_BASE + 1, - BAD_THREAD_ID = OS_ERROR_BASE + 0x100, - NO_MORE_THREADS = OS_ERROR_BASE + 0x101, - BAD_THREAD_STATE = OS_ERROR_BASE + 0x102, - BAD_TEAM_ID = OS_ERROR_BASE + 0x103, - NO_MORE_TEAMS = OS_ERROR_BASE + 0x104, - BAD_PORT_ID = OS_ERROR_BASE + 0x200, - NO_MORE_PORTS = OS_ERROR_BASE + 0x201, - BAD_IMAGE_ID = OS_ERROR_BASE + 0x300, - BAD_ADDRESS = OS_ERROR_BASE + 0x301, - NOT_AN_EXECUTABLE = OS_ERROR_BASE + 0x302, - MISSING_LIBRARY = OS_ERROR_BASE + 0x303, - MISSING_SYMBOL = OS_ERROR_BASE + 0x304, - UNKNOWN_EXECUTABLE = OS_ERROR_BASE + 0x305, - LEGACY_EXECUTABLE = OS_ERROR_BASE + 0x306, - - DEBUGGER_ALREADY_INSTALLED = OS_ERROR_BASE + 0x400, - - // Application Kit Errors - BAD_REPLY = APP_ERROR_BASE + 0, - DUPLICATE_REPLY = APP_ERROR_BASE + 1, - MESSAGE_TO_SELF = APP_ERROR_BASE + 2, - BAD_HANDLER = APP_ERROR_BASE + 3, - ALREADY_RUNNING = APP_ERROR_BASE + 4, - LAUNCH_FAILED = APP_ERROR_BASE + 5, - AMBIGUOUS_APP_LAUNCH = APP_ERROR_BASE + 6, - UNKNOWN_MIME_TYPE = APP_ERROR_BASE + 7, - BAD_SCRIPT_SYNTAX = APP_ERROR_BASE + 8, - LAUNCH_FAILED_NO_RESOLVE_LINK = APP_ERROR_BASE + 9, - LAUNCH_FAILED_EXECUTABLE = APP_ERROR_BASE + 10, - LAUNCH_FAILED_APP_NOT_FOUND = APP_ERROR_BASE + 11, - LAUNCH_FAILED_APP_IN_TRASH = APP_ERROR_BASE + 12, - LAUNCH_FAILED_NO_PREFERRED_APP = APP_ERROR_BASE + 13, - LAUNCH_FAILED_FILES_APP_NOT_FOUND = APP_ERROR_BASE + 14, - BAD_MIME_SNIFFER_RULE = APP_ERROR_BASE + 15, - NOT_A_MESSAGE = APP_ERROR_BASE + 16, - SHUTDOWN_CANCELLED = APP_ERROR_BASE + 17, - SHUTTING_DOWN = APP_ERROR_BASE + 18, - - // Storage Kit/File System Errors - FILE_ERROR = STORAGE_ERROR_BASE + 0, - // 1 was B_FILE_NOT_FOUND (deprecated) - FILE_EXISTS = STORAGE_ERROR_BASE + 2, - ENTRY_NOT_FOUND = STORAGE_ERROR_BASE + 3, - NAME_TOO_LONG = STORAGE_ERROR_BASE + 4, - NOT_A_DIRECTORY = STORAGE_ERROR_BASE + 5, - DIRECTORY_NOT_EMPTY = STORAGE_ERROR_BASE + 6, - DEVICE_FULL = STORAGE_ERROR_BASE + 7, - READ_ONLY_DEVICE = STORAGE_ERROR_BASE + 8, - IS_A_DIRECTORY = STORAGE_ERROR_BASE + 9, - NO_MORE_FDS = STORAGE_ERROR_BASE + 10, - CROSS_DEVICE_LINK = STORAGE_ERROR_BASE + 11, - LINK_LIMIT = STORAGE_ERROR_BASE + 12, - BUSTED_PIPE = STORAGE_ERROR_BASE + 13, - UNSUPPORTED = STORAGE_ERROR_BASE + 14, - PARTITION_TOO_SMALL = STORAGE_ERROR_BASE + 15, - PARTIAL_READ = STORAGE_ERROR_BASE + 16, - PARTIAL_WRITE = STORAGE_ERROR_BASE + 17, - - EIO = posix.EIO, - EACCES = posix.EACCES, - EINVAL = posix.EINVAL, - ETIMEDOUT = posix.ETIMEDOUT, - EINTR = posix.EINTR, - EAGAIN = posix.EAGAIN, - EWOULDBLOCK = posix.EWOULDBLOCK, - EBUSY = posix.EBUSY, - EPERM = posix.EPERM, - EFAULT = posix.EFAULT, - ENOEXEC = posix.ENOEXEC, - EBADF = posix.EBADF, - EEXIST = posix.EEXIST, - ENOENT = posix.ENOENT, - ENAMETOOLONG = posix.ENAMETOOLONG, - ENOTDIR = posix.ENOTDIR, - ENOTEMPTY = posix.ENOTEMPTY, - ENOSPC = posix.ENOSPC, - EROFS = posix.EROFS, - EISDIR = posix.EISDIR, - EMFILE = posix.EMFILE, - EXDEV = posix.EXDEV, - ELOOP = posix.ELOOP, - EPIPE = posix.EPIPE, - ENOMEM = posix.ENOMEM, - E2BIG = posix.E2BIG, - ECHILD = posix.ECHILD, - EDEADLK = posix.EDEADLK, - EFBIG = posix.EFBIG, - EMLINK = posix.EMLINK, - ENFILE = posix.ENFILE, - ENODEV = posix.ENODEV, - ENOLCK = posix.ENOLCK, - ENOSYS = posix.ENOSYS, - ENOTTY = posix.ENOTTY, - ENXIO = posix.ENXIO, - ESPIPE = posix.ESPIPE, - ESRCH = posix.ESRCH, - EDOM = posix.EDOM, - ERANGE = posix.ERANGE, - EPROTOTYPE = posix.EPROTOTYPE, - EPROTONOSUPPORT = posix.EPROTONOSUPPORT, - EAFNOSUPPORT = posix.EAFNOSUPPORT, - EADDRINUSE = posix.EADDRINUSE, - EADDRNOTAVAIL = posix.EADDRNOTAVAIL, - ENETDOWN = posix.ENETDOWN, - ENETUNREACH = posix.ENETUNREACH, - ENETRESET = posix.ENETRESET, - ECONNABORTED = posix.ECONNABORTED, - ECONNRESET = posix.ECONNRESET, - EISCONN = posix.EISCONN, - ENOTCONN = posix.ENOTCONN, - ECONNREFUSED = posix.ECONNREFUSED, - EHOSTUNREACH = posix.EHOSTUNREACH, - ENOPROTOOPT = posix.ENOPROTOOPT, - ENOBUFS = posix.ENOBUFS, - EINPROGRESS = posix.EINPROGRESS, - EALREADY = posix.EALREADY, - EILSEQ = posix.EILSEQ, - ENOMSG = posix.ENOMSG, - ESTALE = posix.ESTALE, - EOVERFLOW = posix.EOVERFLOW, - EMSGSIZE = posix.EMSGSIZE, - EOPNOTSUPP = posix.EOPNOTSUPP, - ENOTSOCK = posix.ENOTSOCK, - EBADMSG = posix.EBADMSG, - ECANCELED = posix.ECANCELED, - EDESTADDRREQ = posix.EDESTADDRREQ, - EDQUOT = posix.EDQUOT, - EIDRM = posix.EIDRM, - EMULTIHOP = posix.EMULTIHOP, - ENODATA = posix.ENODATA, - ENOLINK = posix.ENOLINK, - ENOSR = posix.ENOSR, - ENOSTR = posix.ENOSTR, - ENOTSUP = posix.ENOTSUP, - EPROTO = posix.EPROTO, - ETIME = posix.ETIME, - ETXTBSY = posix.ETXTBSY, - ENOTRECOVERABLE = posix.ENOTRECOVERABLE, - EOWNERDEAD = posix.EOWNERDEAD, - - // New error codes that can be mapped to POSIX errors - TOO_MANY_ARGS = POSIX_ERROR_FACTOR * E2BIG, - FILE_TOO_LARGE = POSIX_ERROR_FACTOR * EFBIG, - DEVICE_NOT_FOUND = POSIX_ERROR_FACTOR * ENODEV, - RESULT_NOT_REPRESENTABLE = POSIX_ERROR_FACTOR * ERANGE, - BUFFER_OVERFLOW = POSIX_ERROR_FACTOR * EOVERFLOW, - NOT_SUPPORTED = POSIX_ERROR_FACTOR * EOPNOTSUPP, - - // Media Kit Errors - STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0, - SERVER_NOT_FOUND = MEDIA_ERROR_BASE + 1, - RESOURCE_NOT_FOUND = MEDIA_ERROR_BASE + 2, - RESOURCE_UNAVAILABLE = MEDIA_ERROR_BASE + 3, - BAD_SUBSCRIBER = MEDIA_ERROR_BASE + 4, - SUBSCRIBER_NOT_ENTERED = MEDIA_ERROR_BASE + 5, - BUFFER_NOT_AVAILABLE = MEDIA_ERROR_BASE + 6, - LAST_BUFFER_ERROR = MEDIA_ERROR_BASE + 7, - MEDIA_SYSTEM_FAILURE = MEDIA_ERROR_BASE + 100, - MEDIA_BAD_NODE = MEDIA_ERROR_BASE + 101, - MEDIA_NODE_BUSY = MEDIA_ERROR_BASE + 102, - MEDIA_BAD_FORMAT = MEDIA_ERROR_BASE + 103, - MEDIA_BAD_BUFFER = MEDIA_ERROR_BASE + 104, - MEDIA_TOO_MANY_NODES = MEDIA_ERROR_BASE + 105, - MEDIA_TOO_MANY_BUFFERS = MEDIA_ERROR_BASE + 106, - MEDIA_NODE_ALREADY_EXISTS = MEDIA_ERROR_BASE + 107, - MEDIA_BUFFER_ALREADY_EXISTS = MEDIA_ERROR_BASE + 108, - MEDIA_CANNOT_SEEK = MEDIA_ERROR_BASE + 109, - MEDIA_CANNOT_CHANGE_RUN_MODE = MEDIA_ERROR_BASE + 110, - MEDIA_APP_ALREADY_REGISTERED = MEDIA_ERROR_BASE + 111, - MEDIA_APP_NOT_REGISTERED = MEDIA_ERROR_BASE + 112, - MEDIA_CANNOT_RECLAIM_BUFFERS = MEDIA_ERROR_BASE + 113, - MEDIA_BUFFERS_NOT_RECLAIMED = MEDIA_ERROR_BASE + 114, - MEDIA_TIME_SOURCE_STOPPED = MEDIA_ERROR_BASE + 115, - MEDIA_TIME_SOURCE_BUSY = MEDIA_ERROR_BASE + 116, - MEDIA_BAD_SOURCE = MEDIA_ERROR_BASE + 117, - MEDIA_BAD_DESTINATION = MEDIA_ERROR_BASE + 118, - MEDIA_ALREADY_CONNECTED = MEDIA_ERROR_BASE + 119, - MEDIA_NOT_CONNECTED = MEDIA_ERROR_BASE + 120, - MEDIA_BAD_CLIP_FORMAT = MEDIA_ERROR_BASE + 121, - MEDIA_ADDON_FAILED = MEDIA_ERROR_BASE + 122, - MEDIA_ADDON_DISABLED = MEDIA_ERROR_BASE + 123, - MEDIA_CHANGE_IN_PROGRESS = MEDIA_ERROR_BASE + 124, - MEDIA_STALE_CHANGE_COUNT = MEDIA_ERROR_BASE + 125, - MEDIA_ADDON_RESTRICTED = MEDIA_ERROR_BASE + 126, - MEDIA_NO_HANDLER = MEDIA_ERROR_BASE + 127, - MEDIA_DUPLICATE_FORMAT = MEDIA_ERROR_BASE + 128, - MEDIA_REALTIME_DISABLED = MEDIA_ERROR_BASE + 129, - MEDIA_REALTIME_UNAVAILABLE = MEDIA_ERROR_BASE + 130, - - // Mail Kit Errors - MAIL_NO_DAEMON = MAIL_ERROR_BASE + 0, - MAIL_UNKNOWN_USER = MAIL_ERROR_BASE + 1, - MAIL_WRONG_PASSWORD = MAIL_ERROR_BASE + 2, - MAIL_UNKNOWN_HOST = MAIL_ERROR_BASE + 3, - MAIL_ACCESS_ERROR = MAIL_ERROR_BASE + 4, - MAIL_UNKNOWN_FIELD = MAIL_ERROR_BASE + 5, - MAIL_NO_RECIPIENT = MAIL_ERROR_BASE + 6, - MAIL_INVALID_MAIL = MAIL_ERROR_BASE + 7, - - // Printing Errors - NO_PRINT_SERVER = PRINT_ERROR_BASE + 0, - - // Device Kit Errors - DEV_INVALID_IOCTL = DEVICE_ERROR_BASE + 0, - DEV_NO_MEMORY = DEVICE_ERROR_BASE + 1, - DEV_BAD_DRIVE_NUM = DEVICE_ERROR_BASE + 2, - DEV_NO_MEDIA = DEVICE_ERROR_BASE + 3, - DEV_UNREADABLE = DEVICE_ERROR_BASE + 4, - DEV_FORMAT_ERROR = DEVICE_ERROR_BASE + 5, - DEV_TIMEOUT = DEVICE_ERROR_BASE + 6, - DEV_RECALIBRATE_ERROR = DEVICE_ERROR_BASE + 7, - DEV_SEEK_ERROR = DEVICE_ERROR_BASE + 8, - DEV_ID_ERROR = DEVICE_ERROR_BASE + 9, - DEV_READ_ERROR = DEVICE_ERROR_BASE + 10, - DEV_WRITE_ERROR = DEVICE_ERROR_BASE + 11, - DEV_NOT_READY = DEVICE_ERROR_BASE + 12, - DEV_MEDIA_CHANGED = DEVICE_ERROR_BASE + 13, - DEV_MEDIA_CHANGE_REQUESTED = DEVICE_ERROR_BASE + 14, - DEV_RESOURCE_CONFLICT = DEVICE_ERROR_BASE + 15, - DEV_CONFIGURATION_ERROR = DEVICE_ERROR_BASE + 16, - DEV_DISABLED_BY_USER = DEVICE_ERROR_BASE + 17, - DEV_DOOR_OPEN = DEVICE_ERROR_BASE + 18, - DEV_INVALID_PIPE = DEVICE_ERROR_BASE + 19, - DEV_CRC_ERROR = DEVICE_ERROR_BASE + 20, - DEV_STALLED = DEVICE_ERROR_BASE + 21, - DEV_BAD_PID = DEVICE_ERROR_BASE + 22, - DEV_UNEXPECTED_PID = DEVICE_ERROR_BASE + 23, - DEV_DATA_OVERRUN = DEVICE_ERROR_BASE + 24, - DEV_DATA_UNDERRUN = DEVICE_ERROR_BASE + 25, - DEV_FIFO_OVERRUN = DEVICE_ERROR_BASE + 26, - DEV_FIFO_UNDERRUN = DEVICE_ERROR_BASE + 27, - DEV_PENDING = DEVICE_ERROR_BASE + 28, - DEV_MULTIPLE_ERRORS = DEVICE_ERROR_BASE + 29, - DEV_TOO_LATE = DEVICE_ERROR_BASE + 30, - - // Translation Kit Errors - TRANSLATION_BASE_ERROR = TRANSLATION_ERROR_BASE + 0, - NO_TRANSLATOR = TRANSLATION_ERROR_BASE + 1, - ILLEGAL_DATA = TRANSLATION_ERROR_BASE + 2, -} - -@(default_calling_convention="c") -foreign libroot { - _to_positive_error :: proc(error: i32) -> i32 --- - _to_negative_error :: proc(error: i32) -> i32 --- -} diff --git a/core/sys/haiku/find_directory.odin b/core/sys/haiku/find_directory.odin deleted file mode 100644 index c700bd53b..000000000 --- a/core/sys/haiku/find_directory.odin +++ /dev/null @@ -1,171 +0,0 @@ -#+build haiku -package sys_haiku - -import "base:intrinsics" - -foreign import libroot "system:c" - -directory_which :: enum i32 { - // Per volume directories - DESKTOP_DIRECTORY = 0, - TRASH_DIRECTORY, - - // System directories - SYSTEM_DIRECTORY = 1000, - SYSTEM_ADDONS_DIRECTORY = 1002, - SYSTEM_BOOT_DIRECTORY, - SYSTEM_FONTS_DIRECTORY, - SYSTEM_LIB_DIRECTORY, - SYSTEM_SERVERS_DIRECTORY, - SYSTEM_APPS_DIRECTORY, - SYSTEM_BIN_DIRECTORY, - SYSTEM_DOCUMENTATION_DIRECTORY = 1010, - SYSTEM_PREFERENCES_DIRECTORY, - SYSTEM_TRANSLATORS_DIRECTORY, - SYSTEM_MEDIA_NODES_DIRECTORY, - SYSTEM_SOUNDS_DIRECTORY, - SYSTEM_DATA_DIRECTORY, - SYSTEM_DEVELOP_DIRECTORY, - SYSTEM_PACKAGES_DIRECTORY, - SYSTEM_HEADERS_DIRECTORY, - SYSTEM_ETC_DIRECTORY = 2008, - SYSTEM_SETTINGS_DIRECTORY = 2010, - SYSTEM_LOG_DIRECTORY = 2012, - SYSTEM_SPOOL_DIRECTORY, - SYSTEM_TEMP_DIRECTORY, - SYSTEM_VAR_DIRECTORY, - SYSTEM_CACHE_DIRECTORY = 2020, - SYSTEM_NONPACKAGED_DIRECTORY = 2023, - SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, - SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY, - SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY, - SYSTEM_NONPACKAGED_BIN_DIRECTORY, - SYSTEM_NONPACKAGED_DATA_DIRECTORY, - SYSTEM_NONPACKAGED_FONTS_DIRECTORY, - SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY, - SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY, - SYSTEM_NONPACKAGED_LIB_DIRECTORY, - SYSTEM_NONPACKAGED_HEADERS_DIRECTORY, - SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY, - - // User directories. These are interpreted in the context of the user making the find_directory call. - USER_DIRECTORY = 3000, - USER_CONFIG_DIRECTORY, - USER_ADDONS_DIRECTORY, - USER_BOOT_DIRECTORY, - USER_FONTS_DIRECTORY, - USER_LIB_DIRECTORY, - USER_SETTINGS_DIRECTORY, - USER_DESKBAR_DIRECTORY, - USER_PRINTERS_DIRECTORY, - USER_TRANSLATORS_DIRECTORY, - USER_MEDIA_NODES_DIRECTORY, - USER_SOUNDS_DIRECTORY, - USER_DATA_DIRECTORY, - USER_CACHE_DIRECTORY, - USER_PACKAGES_DIRECTORY, - USER_HEADERS_DIRECTORY, - USER_NONPACKAGED_DIRECTORY, - USER_NONPACKAGED_ADDONS_DIRECTORY, - USER_NONPACKAGED_TRANSLATORS_DIRECTORY, - USER_NONPACKAGED_MEDIA_NODES_DIRECTORY, - USER_NONPACKAGED_BIN_DIRECTORY, - USER_NONPACKAGED_DATA_DIRECTORY, - USER_NONPACKAGED_FONTS_DIRECTORY, - USER_NONPACKAGED_SOUNDS_DIRECTORY, - USER_NONPACKAGED_DOCUMENTATION_DIRECTORY, - USER_NONPACKAGED_LIB_DIRECTORY, - USER_NONPACKAGED_HEADERS_DIRECTORY, - USER_NONPACKAGED_DEVELOP_DIRECTORY, - USER_DEVELOP_DIRECTORY, - USER_DOCUMENTATION_DIRECTORY, - USER_SERVERS_DIRECTORY, - USER_APPS_DIRECTORY, - USER_BIN_DIRECTORY, - USER_PREFERENCES_DIRECTORY, - USER_ETC_DIRECTORY, - USER_LOG_DIRECTORY, - USER_SPOOL_DIRECTORY, - USER_VAR_DIRECTORY, - - // Global directories - APPS_DIRECTORY = 4000, - PREFERENCES_DIRECTORY, - UTILITIES_DIRECTORY, - PACKAGE_LINKS_DIRECTORY, - - // Obsolete: Legacy BeOS definition to be phased out - BEOS_DIRECTORY = 1000, - BEOS_SYSTEM_DIRECTORY, - BEOS_ADDONS_DIRECTORY, - BEOS_BOOT_DIRECTORY, - BEOS_FONTS_DIRECTORY, - BEOS_LIB_DIRECTORY, - BEOS_SERVERS_DIRECTORY, - BEOS_APPS_DIRECTORY, - BEOS_BIN_DIRECTORY, - BEOS_ETC_DIRECTORY, - BEOS_DOCUMENTATION_DIRECTORY, - BEOS_PREFERENCES_DIRECTORY, - BEOS_TRANSLATORS_DIRECTORY, - BEOS_MEDIA_NODES_DIRECTORY, - BEOS_SOUNDS_DIRECTORY, -} - -find_path_flag :: enum u32 { - CREATE_DIRECTORY = intrinsics.constant_log2(0x0001), - CREATE_PARENT_DIRECTORY = intrinsics.constant_log2(0x0002), - EXISTING_ONLY = intrinsics.constant_log2(0x0004), - - // find_paths() only - SYSTEM_ONLY = intrinsics.constant_log2(0x0010), - USER_ONLY = intrinsics.constant_log2(0x0020), -} -find_path_flags :: distinct bit_set[find_path_flag; u32] - -path_base_directory :: enum i32 { - INSTALLATION_LOCATION_DIRECTORY, - ADD_ONS_DIRECTORY, - APPS_DIRECTORY, - BIN_DIRECTORY, - BOOT_DIRECTORY, - CACHE_DIRECTORY, - DATA_DIRECTORY, - DEVELOP_DIRECTORY, - DEVELOP_LIB_DIRECTORY, - DOCUMENTATION_DIRECTORY, - ETC_DIRECTORY, - FONTS_DIRECTORY, - HEADERS_DIRECTORY, - LIB_DIRECTORY, - LOG_DIRECTORY, - MEDIA_NODES_DIRECTORY, - PACKAGES_DIRECTORY, - PREFERENCES_DIRECTORY, - SERVERS_DIRECTORY, - SETTINGS_DIRECTORY, - SOUNDS_DIRECTORY, - SPOOL_DIRECTORY, - TRANSLATORS_DIRECTORY, - VAR_DIRECTORY, - - // find_path() only - IMAGE_PATH = 1000, - PACKAGE_PATH, -} - -// value that can be used instead of a pointer to a symbol in the program image -APP_IMAGE_SYMBOL :: rawptr(addr_t(0)) -// pointer to a symbol in the callers image (same as B_CURRENT_IMAGE_SYMBOL) -current_image_symbol :: proc "contextless" () -> rawptr { return rawptr(current_image_symbol) } - -@(default_calling_convention="c") -foreign libroot { - find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]byte, length: i32) -> status_t --- - find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- - find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- - find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- - find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t --- - find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t --- - find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t --- -} diff --git a/core/sys/haiku/os.odin b/core/sys/haiku/os.odin deleted file mode 100644 index 3edee88b5..000000000 --- a/core/sys/haiku/os.odin +++ /dev/null @@ -1,498 +0,0 @@ -#+build haiku -package sys_haiku - -import "base:intrinsics" -import "core:sys/posix" - -foreign import libroot "system:c" - -PATH_MAX :: 1024 -NAME_MAX :: 256 -MAXPATHLEN :: PATH_MAX - -FILE_NAME_LENGTH :: NAME_MAX -PATH_NAME_LENGTH :: MAXPATHLEN -OS_NAME_LENGTH :: 32 - -// Areas - -area_info :: struct { - area: area_id, - name: [OS_NAME_LENGTH]byte, - size: uint, - lock: u32, - protection: u32, - team: team_id, - ram_size: u32, - copy_count: u32, - in_count: u32, - out_count: u32, - address: rawptr, -} - -area_locking :: enum u32 { - NO_LOCK = 0, - LAZY_LOCK = 1, - FULL_LOCK = 2, - CONTIGUOUS = 3, - LOMEM = 4, // CONTIGUOUS, < 16 MB physical address - _32_BIT_FULL_LOCK = 5, // FULL_LOCK, < 4 GB physical addresses - _32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address -} - -// for create_area() and clone_area() -address_spec :: enum u32 { - ANY_ADDRESS = 0, - EXACT_ADDRESS = 1, - BASE_ADDRESS = 2, - CLONE_ADDRESS = 3, - ANY_KERNEL_ADDRESS = 4, - // ANY_KERNEL_BLOCK_ADDRESS = 5, - RANDOMIZED_ANY_ADDRESS = 6, - RANDOMIZED_BASE_ADDRESS = 7, -} - -area_protection_flag :: enum u32 { - READ_AREA = 0, - WRITE_AREA = 1, - EXECUTE_AREA = 2, - // "stack" protection is not available on most platforms - it's used - // to only commit memory as needed, and have guard pages at the - // bottom of the stack. - STACK_AREA = 3, - CLONEABLE_AREA = 8, -} -area_protection_flags :: distinct bit_set[area_protection_flag; u32] - -@(default_calling_convention="c") -foreign libroot { - create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uint, lock: area_locking, protection: area_protection_flags) -> area_id --- - clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id --- - find_area :: proc(name: cstring) -> area_id --- - area_for :: proc(address: rawptr) -> area_id --- - delete_area :: proc(id: area_id) -> status_t --- - resize_area :: proc(id: area_id, newSize: uint) -> status_t --- - set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t --- - _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uint) -> status_t --- - _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uint) -> status_t --- -} - -// Ports - -port_info :: struct { - port: port_id, - team: team_id, - name: [OS_NAME_LENGTH]byte, - capacity: i32, // queue depth - queue_count: i32, // # msgs waiting to be read - total_count: i32, // total # msgs read so far -} - -port_flag :: enum u32 { - USE_USER_MEMCPY = intrinsics.constant_log2(0x80000000), - // read the message, but don't remove it; kernel-only; memory must be locked - PEEK_PORT_MESSAGE = intrinsics.constant_log2(0x100), -} -port_flags :: distinct bit_set[port_flag; u32] - -@(default_calling_convention="c") -foreign libroot { - create_port :: proc(capacity: i32, name: cstring) -> port_id --- - find_port :: proc(name: cstring) -> port_id --- - read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint) -> int --- - read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> int --- - write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t --- - write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> status_t --- - close_port :: proc(port: port_id) -> status_t --- - delete_port :: proc(port: port_id) -> status_t --- - port_buffer_size :: proc(port: port_id) -> int --- - port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int --- - port_count :: proc(port: port_id) -> int --- - set_port_owner :: proc(port: port_id, team: team_id) -> status_t --- - _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uint) -> status_t --- - _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uint) -> status_t --- -} - -// Semaphores - -sem_info :: struct { - sem: sem_id, - team: team_id, - name: [OS_NAME_LENGTH]byte, - count: i32, - latest_holder: thread_id, -} - -semaphore_flag :: enum u32 { - CAN_INTERRUPT = intrinsics.constant_log2(0x01), // acquisition of the semaphore can be interrupted (system use only) - CHECK_PERMISSION = intrinsics.constant_log2(0x04), // ownership will be checked (system use only) - KILL_CAN_INTERRUPT = intrinsics.constant_log2(0x20), // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only) - - // release_sem_etc() only flags - DO_NOT_RESCHEDULE = intrinsics.constant_log2(0x02), // thread is not rescheduled - RELEASE_ALL = intrinsics.constant_log2(0x08), // all waiting threads will be woken up, count will be zeroed - RELEASE_IF_WAITING_ONLY = intrinsics.constant_log2(0x10), // release count only if there are any threads waiting -} -semaphore_flags :: distinct bit_set[semaphore_flag; u32] - -@(default_calling_convention="c") -foreign libroot { - create_sem :: proc(count: i32, name: cstring) -> sem_id --- - delete_sem :: proc(id: sem_id) -> status_t --- - acquire_sem :: proc(id: sem_id) -> status_t --- - acquire_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t --- - release_sem :: proc(id: sem_id) -> status_t --- - release_sem_etc :: proc(id: sem_id, count: i32, flags: semaphore_flags) -> status_t --- - switch_sem :: proc(semToBeReleased: sem_id) -> status_t --- - switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t --- - get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t --- - set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t --- - _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uint) -> status_t --- - _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uint) -> status_t --- -} - -// Teams - -team_info :: struct { - team: team_id, - thread_count: i32, - image_count: i32, - area_count: i32, - debugger_nub_thread: thread_id, - debugger_nub_port: port_id, - argc: i32, - args: [64]byte, - uid: uid_t, - gid: gid_t, - - // Haiku R1 extensions - real_uid: uid_t, - real_gid: gid_t, - group_id: pid_t, - session_id: pid_t, - parent: team_id, - name: [OS_NAME_LENGTH]byte, - start_time: bigtime_t, -} - -CURRENT_TEAM :: 0 -SYSTEM_TEAM :: 1 - -team_usage_info :: struct { - user_time: bigtime_t, - kernel_time: bigtime_t, -} - -team_usage_who :: enum i32 { - // compatible to sys/resource.h RUSAGE_SELF and RUSAGE_CHILDREN - SELF = 0, - CHILDREN = -1, -} - -@(default_calling_convention="c") -foreign libroot { - // see also: send_signal() - kill_team :: proc(team: team_id) -> status_t --- - _get_team_info :: proc(id: team_id, info: ^team_info, size: uint) -> status_t --- - _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uint) -> status_t --- - _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uint) -> status_t --- -} - -// Threads - -thread_state :: enum i32 { - RUNNING = 1, - READY, - RECEIVING, - ASLEEP, - SUSPENDED, - WAITING, -} - -thread_info :: struct { - thread: thread_id, - team: team_id, - name: [OS_NAME_LENGTH]byte, - state: thread_state, - priority: thread_priority, - sem: sem_id, - user_time: bigtime_t, - kernel_time: bigtime_t, - stack_base: rawptr, - stack_end: rawptr, -} - -thread_priority :: enum i32 { - IDLE_PRIORITY = 0, - LOWEST_ACTIVE_PRIORITY = 1, - LOW_PRIORITY = 5, - NORMAL_PRIORITY = 10, - DISPLAY_PRIORITY = 15, - URGENT_DISPLAY_PRIORITY = 20, - REAL_TIME_DISPLAY_PRIORITY = 100, - URGENT_PRIORITY = 110, - REAL_TIME_PRIORITY = 120, -} - -FIRST_REAL_TIME_PRIORITY :: thread_priority.REAL_TIME_PRIORITY - -// time base for snooze_*(), compatible with the clockid_t constants defined in -SYSTEM_TIMEBASE :: 0 - -thread_func :: #type proc "c" (rawptr) -> status_t - -@(default_calling_convention="c") -foreign libroot { - spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id --- - kill_thread :: proc(thread: thread_id) -> status_t --- - resume_thread :: proc(thread: thread_id) -> status_t --- - suspend_thread :: proc(thread: thread_id) -> status_t --- - rename_thread :: proc(thread: thread_id, newName: cstring) -> status_t --- - set_thread_priority :: proc(thread: thread_id, newPriority: thread_priority) -> status_t --- - exit_thread :: proc(status: status_t) --- - wait_for_thread :: proc(thread: thread_id, returnValue: ^status_t) -> status_t --- - // FIXME: Find and define those flags. - wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t --- - on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t --- - find_thread :: proc(name: cstring) -> thread_id --- - send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t --- - receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uint) -> i32 --- - has_data :: proc(thread: thread_id) -> bool --- - snooze :: proc(amount: bigtime_t) -> status_t --- - // FIXME: Find and define those flags. - snooze_etc :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t --- - snooze_until :: proc(time: bigtime_t, timeBase: i32) -> status_t --- - _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uint) -> status_t --- - _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uint) -> status_t --- - // bridge to the pthread API - get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id --- -} - -// Time - -@(default_calling_convention="c") -foreign libroot { - real_time_clock :: proc() -> uint --- - set_real_time_clock :: proc(secsSinceJan1st1970: uint) --- - real_time_clock_usecs :: proc() -> bigtime_t --- - // time since booting in microseconds - system_time :: proc() -> bigtime_t --- - // time since booting in nanoseconds - system_time_nsecs :: proc() -> nanotime_t --- -} - -// Alarm - -alarm_mode :: enum u32 { - ONE_SHOT_ABSOLUTE_ALARM = 1, - ONE_SHOT_RELATIVE_ALARM, - PERIODIC_ALARM, // "when" specifies the period -} - -@(default_calling_convention="c") -foreign libroot { - set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t --- -} - -// Debugger - -@(default_calling_convention="c") -foreign libroot { - debugger :: proc(message: cstring) --- - /* - calling this function with a non-zero value will cause your thread - to receive signals for any exceptional conditions that occur (i.e. - you'll get SIGSEGV for data access exceptions, SIGFPE for floating - point errors, SIGILL for illegal instructions, etc). - - to re-enable the default debugger pass a zero. - */ - disable_debugger :: proc(state: i32) -> i32 --- -} - -// System information - -cpu_info :: struct { - active_time: bigtime_t, - enabled: bool, - current_frequency: u64, -} - -system_info :: struct { - boot_time: bigtime_t, // time of boot (usecs since 1/1/1970) - - cpu_count: u32, // number of cpus - - max_pages: u64, // total # of accessible pages - used_pages: u64, // # of accessible pages in use - cached_pages: u64, - block_cache_pages: u64, - ignored_pages: u64, // # of ignored/inaccessible pages - - needed_memory: u64, - free_memory: u64, - - max_swap_pages: u64, - free_swap_pages: u64, - - page_faults: u32, // # of page faults - - max_sems: u32, - used_sems: u32, - - max_ports: u32, - used_ports: u32, - - max_threads: u32, - used_threads: u32, - - max_teams: u32, - used_teams: u32, - - kernel_name: [FILE_NAME_LENGTH]byte, - kernel_build_date: [OS_NAME_LENGTH]byte, - kernel_build_time: [OS_NAME_LENGTH]byte, - - kernel_version: i64, - abi: u32, // the system API -} - -topology_level_type :: enum i32 { - UNKNOWN, - ROOT, - SMT, - CORE, - PACKAGE, -} - -cpu_platform :: enum i32 { - UNKNOWN, - x86, - x86_64, - PPC, - PPC_64, - M68K, - ARM, - ARM_64, - ALPHA, - MIPS, - SH, - SPARC, - RISC_V, -} - -cpu_vendor :: enum i32 { - UNKNOWN, - AMD, - CYRIX, - IDT, - INTEL, - NATIONAL_SEMICONDUCTOR, - RISE, - TRANSMETA, - VIA, - IBM, - MOTOROLA, - NEC, - HYGON, - SUN, - FUJITSU, -} - -cpu_topology_node_info :: struct { - id: u32, - type: topology_level_type, - level: u32, - - data: struct #raw_union { - _root: struct { - platform: cpu_platform, - }, - _package: struct { - vendor: cpu_vendor, - cache_line_size: u32, - }, - _core: struct { - model: u32, - default_frequency: u64, - }, - }, -} - -when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { - cpuid_info :: struct #raw_union { - eax_0: struct { - max_eax: u32, - vendor_id: [12]byte, - }, - - eax_1: struct { - using _: bit_field u32 { - stepping: u32 | 4, - model: u32 | 4, - family: u32 | 4, - type: u32 | 2, - reserved_0: u32 | 2, - extended_model: u32 | 4, - extended_family: u32 | 8, - reserved_1: u32 | 4, - }, - - using _: bit_field u32 { - brand_index: u32 | 8, - clflush: u32 | 8, - logical_cpus: u32 | 8, - apic_id: u32 | 8, - }, - - features: u32, - extended_features: u32, - }, - - eax_2: struct { - call_num: u8, - cache_descriptors: [15]u8, - }, - - eax_3: struct { - reserved: [2]u32, - serial_number_high: u32, - serial_number_low: u32, - }, - - as_chars: [16]byte, - - regs: struct { - eax: u32, - ebx: u32, - edx: u32, - ecx: u32, - }, - } -} - -@(default_calling_convention="c") -foreign libroot { - get_system_info :: proc(info: ^system_info) -> status_t --- - _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uint) -> status_t --- - get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t --- - - when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { - get_cpuid :: proc(info: ^cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t --- - } - - is_computer_on :: proc() -> i32 --- - is_computer_on_fire :: proc() -> f64 --- -} - -// POSIX signals - -@(default_calling_convention="c") -foreign libroot { - /* - Wait for queued signals. - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]] - */ - sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result --- -} diff --git a/core/sys/haiku/types.odin b/core/sys/haiku/types.odin deleted file mode 100644 index f15ffb00d..000000000 --- a/core/sys/haiku/types.odin +++ /dev/null @@ -1,56 +0,0 @@ -#+build haiku -package sys_haiku - -status_t :: Errno -bigtime_t :: i64 -nanotime_t :: i64 -type_code :: u32 -perform_code :: u32 - -phys_addr_t :: uintptr -phys_size_t :: phys_addr_t -generic_addr_t :: uintptr -generic_size_t :: generic_addr_t - -area_id :: i32 -port_id :: i32 -sem_id :: i32 -team_id :: i32 -thread_id :: i32 - -blkcnt_t :: i64 -blksize_t :: i32 -fsblkcnt_t :: i64 -fsfilcnt_t :: i64 -off_t :: i64 -ino_t :: i64 -cnt_t :: i32 -dev_t :: i32 -pid_t :: i32 -id_t :: i32 - -uid_t :: u32 -gid_t :: u32 -mode_t :: u32 -umode_t :: u32 -nlink_t :: i32 - -caddr_t :: [^]byte - -addr_t :: phys_addr_t -key_t :: i32 - -clockid_t :: i32 - -time_t :: int -timespec :: struct { - tv_sec: time_t, - tv_nsec: int, -} - -sig_atomic_t :: i32 -sigset_t :: u64 - -image_id :: i32 - -pthread_t :: rawptr diff --git a/core/sys/info/cpu_arm.odin b/core/sys/info/cpu_arm.odin index 960e55a56..439007e24 100644 --- a/core/sys/info/cpu_arm.odin +++ b/core/sys/info/cpu_arm.odin @@ -41,30 +41,32 @@ CPU_Feature :: enum u64 { CPU_Features :: distinct bit_set[CPU_Feature; u64] -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +// Retrieving CPU features on ARM is even more expensive than on Intel, so we're doing this lookup only once, before `main()` +@(private) _features: CPU_Features + + +@(private) _name_buf: [256]u8 +@(private) _name: string @(private) -cpu_name_buf: [128]byte +_cpu_name :: proc() -> (name: string) { + return _name +} @(init, private) -init_cpu_name :: proc "contextless" () { - generic := true - +_init_cpu_name :: proc "contextless" () { when ODIN_OS == .Darwin { - if unix.sysctlbyname("machdep.cpu.brand_string", &cpu_name_buf) { - cpu_name = string(cstring(rawptr(&cpu_name_buf))) - generic = false + if unix.sysctlbyname("machdep.cpu.brand_string", &_name_buf) { + _name = string(cstring(rawptr(&_name_buf))) + return } } - if generic { - when ODIN_ARCH == .arm64 { - copy(cpu_name_buf[:], "ARM64") - cpu_name = string(cpu_name_buf[:len("ARM64")]) - } else { - copy(cpu_name_buf[:], "ARM") - cpu_name = string(cpu_name_buf[:len("ARM")]) - } + when ODIN_ARCH == .arm64 { + copy(_name_buf[:], "ARM64") + _name = string(_name_buf[:len("ARM64")]) + } else { + copy(_name_buf[:], "ARM") + _name = string(_name_buf[:len("ARM")]) } -} +} \ No newline at end of file diff --git a/core/sys/info/cpu_darwin.odin b/core/sys/info/cpu_darwin.odin new file mode 100644 index 000000000..06a44227c --- /dev/null +++ b/core/sys/info/cpu_darwin.odin @@ -0,0 +1,12 @@ +package sysinfo + +import "core:sys/unix" + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + _physical, _logical: i64 + unix.sysctlbyname("hw.physicalcpu", &_physical) + unix.sysctlbyname("hw.logicalcpu", &_logical) + + return int(_physical), int(_logical), true +} \ No newline at end of file diff --git a/core/sys/info/cpu_darwin_arm64.odin b/core/sys/info/cpu_darwin_arm64.odin index ffa60d1cb..7f4c7dda2 100644 --- a/core/sys/info/cpu_darwin_arm64.odin +++ b/core/sys/info/cpu_darwin_arm64.odin @@ -2,15 +2,17 @@ package sysinfo import "core:sys/unix" -@(init, private) -init_cpu_features :: proc "contextless" () { - @(static) features: CPU_Features - defer cpu_features = features +@(private) +_cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return _features +} - try_set :: proc "contextless" (name: cstring, feature: CPU_Feature) -> (ok: bool) { +@(init, private) +_init_cpu_features :: proc "contextless" () -> () { + try_set :: proc "contextless" (features: ^CPU_Features, name: cstring, feature: CPU_Feature) -> (ok: bool) { support: b32 if ok = unix.sysctlbyname(name, &support); ok && support { - features += { feature } + features^ += { feature } } return } @@ -20,79 +22,79 @@ init_cpu_features :: proc "contextless" () { // Advanced SIMD & floating-point capabilities: { - if !try_set("hw.optional.AdvSIMD", .asimd) { - try_set("hw.optional.neon", .asimd) + if !try_set(&_features, "hw.optional.AdvSIMD", .asimd) { + try_set(&_features, "hw.optional.neon", .asimd) } - try_set("hw.optional.floatingpoint", .floatingpoint) + try_set(&_features, "hw.optional.floatingpoint", .floatingpoint) - if !try_set("hw.optional.AdvSIMD_HPFPCvt", .asimdhp) { - try_set("hw.optional.neon_hpfp", .asimdhp) + if !try_set(&_features, "hw.optional.AdvSIMD_HPFPCvt", .asimdhp) { + try_set(&_features, "hw.optional.neon_hpfp", .asimdhp) } - try_set("hw.optional.arm.FEAT_BF16", .bf16) - // try_set("hw.optional.arm.FEAT_DotProd", .dotprod) + try_set(&_features, "hw.optional.arm.FEAT_BF16", .bf16) + // try_set(&_features, "hw.optional.arm.FEAT_DotProd", .dotprod) - if !try_set("hw.optional.arm.FEAT_FCMA", .fcma) { - try_set("hw.optional.armv8_3_compnum", .fcma) + if !try_set(&_features, "hw.optional.arm.FEAT_FCMA", .fcma) { + try_set(&_features, "hw.optional.armv8_3_compnum", .fcma) } - if !try_set("hw.optional.arm.FEAT_FHM", .fhm) { - try_set("hw.optional.armv8_2_fhm", .fhm) + if !try_set(&_features, "hw.optional.arm.FEAT_FHM", .fhm) { + try_set(&_features, "hw.optional.armv8_2_fhm", .fhm) } - if !try_set("hw.optional.arm.FEAT_FP16", .fp16) { - try_set("hw.optional.neon_fp16", .fp16) + if !try_set(&_features, "hw.optional.arm.FEAT_FP16", .fp16) { + try_set(&_features, "hw.optional.neon_fp16", .fp16) } - try_set("hw.optional.arm.FEAT_FRINTTS", .frint) - try_set("hw.optional.arm.FEAT_I8MM", .i8mm) - try_set("hw.optional.arm.FEAT_JSCVT", .jscvt) - try_set("hw.optional.arm.FEAT_RDM", .rdm) + try_set(&_features, "hw.optional.arm.FEAT_FRINTTS", .frint) + try_set(&_features, "hw.optional.arm.FEAT_I8MM", .i8mm) + try_set(&_features, "hw.optional.arm.FEAT_JSCVT", .jscvt) + try_set(&_features, "hw.optional.arm.FEAT_RDM", .rdm) } // Integer capabilities: { - try_set("hw.optional.arm.FEAT_FlagM", .flagm) - try_set("hw.optional.arm.FEAT_FlagM2", .flagm2) - try_set("hw.optional.armv8_crc32", .crc32) + try_set(&_features, "hw.optional.arm.FEAT_FlagM", .flagm) + try_set(&_features, "hw.optional.arm.FEAT_FlagM2", .flagm2) + try_set(&_features, "hw.optional.armv8_crc32", .crc32) } // Atomic and memory ordering instruction capabilities: { - try_set("hw.optional.arm.FEAT_LRCPC", .lrcpc) - try_set("hw.optional.arm.FEAT_LRCPC2", .lrcpc2) + try_set(&_features, "hw.optional.arm.FEAT_LRCPC", .lrcpc) + try_set(&_features, "hw.optional.arm.FEAT_LRCPC2", .lrcpc2) - if !try_set("hw.optional.arm.FEAT_LSE", .lse) { - try_set("hw.optional.armv8_1_atomics", .lse) + if !try_set(&_features, "hw.optional.arm.FEAT_LSE", .lse) { + try_set(&_features, "hw.optional.armv8_1_atomics", .lse) } - // try_set("hw.optional.arm.FEAT_LSE2", .lse2) + // try_set(&_features, "hw.optional.arm.FEAT_LSE2", .lse2) } // Encryption capabilities: { - try_set("hw.optional.arm.FEAT_AES", .aes) - try_set("hw.optional.arm.FEAT_PMULL", .pmull) - try_set("hw.optional.arm.FEAT_SHA1", .sha1) - try_set("hw.optional.arm.FEAT_SHA256", .sha256) + try_set(&_features, "hw.optional.arm.FEAT_AES", .aes) + try_set(&_features, "hw.optional.arm.FEAT_PMULL", .pmull) + try_set(&_features, "hw.optional.arm.FEAT_SHA1", .sha1) + try_set(&_features, "hw.optional.arm.FEAT_SHA256", .sha256) - if !try_set("hw.optional.arm.FEAT_SHA512", .sha512) { - try_set("hw.optional.armv8_2_sha512", .sha512) + if !try_set(&_features, "hw.optional.arm.FEAT_SHA512", .sha512) { + try_set(&_features, "hw.optional.armv8_2_sha512", .sha512) } - if !try_set("hw.optional.arm.FEAT_SHA3", .sha3) { - try_set("hw.optional.armv8_2_sha3", .sha3) + if !try_set(&_features, "hw.optional.arm.FEAT_SHA3", .sha3) { + try_set(&_features, "hw.optional.armv8_2_sha3", .sha3) } } // General capabilities: { - // try_set("hw.optional.arm.FEAT_BTI", .bti) - // try_set("hw.optional.arm.FEAT_DPB", .dpb) - // try_set("hw.optional.arm.FEAT_DPB2", .dpb2) - // try_set("hw.optional.arm.FEAT_ECV", .ecv) - try_set("hw.optional.arm.FEAT_SB", .sb) - try_set("hw.optional.arm.FEAT_SSBS", .ssbs) + // try_set(&_features, "hw.optional.arm.FEAT_BTI", .bti) + // try_set(&_features, "hw.optional.arm.FEAT_DPB", .dpb) + // try_set(&_features, "hw.optional.arm.FEAT_DPB2", .dpb2) + // try_set(&_features, "hw.optional.arm.FEAT_ECV", .ecv) + try_set(&_features, "hw.optional.arm.FEAT_SB", .sb) + try_set(&_features, "hw.optional.arm.FEAT_SSBS", .ssbs) } -} +} \ No newline at end of file diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin index c8b8282fe..0a75e2475 100644 --- a/core/sys/info/cpu_intel.odin +++ b/core/sys/info/cpu_intel.odin @@ -50,11 +50,12 @@ CPU_Feature :: enum u64 { CPU_Features :: distinct bit_set[CPU_Feature; u64] -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +// `cpuid` is a barrier so we try not performing this query this more than necessary. +// `atomic_load_explicit` is also a barrier, so we're doing this lookup only once, before `main()` +@(private) _features: CPU_Features @(init, private) -init_cpu_features :: proc "c" () { +_init_cpu_features :: proc "contextless" () { is_set :: #force_inline proc "c" (bit: u32, value: u32) -> bool { return (value>>bit) & 0x1 != 0 } @@ -66,29 +67,27 @@ init_cpu_features :: proc "c" () { max_id, _, _, _ := cpuid(0, 0) if max_id < 1 { + _features = {} return } - set: CPU_Features - _, _, ecx1, edx1 := cpuid(1, 0) - try_set(&set, .sse2, 26, edx1) - try_set(&set, .sse3, 0, ecx1) - try_set(&set, .pclmulqdq, 1, ecx1) - try_set(&set, .ssse3, 9, ecx1) - try_set(&set, .fma, 12, ecx1) - try_set(&set, .sse41, 19, ecx1) - try_set(&set, .sse42, 20, ecx1) - try_set(&set, .popcnt, 23, ecx1) - try_set(&set, .aes, 25, ecx1) - try_set(&set, .os_xsave, 27, ecx1) - try_set(&set, .rdrand, 30, ecx1) + try_set(&_features, .sse2, 26, edx1) + try_set(&_features, .sse3, 0, ecx1) + try_set(&_features, .pclmulqdq, 1, ecx1) + try_set(&_features, .ssse3, 9, ecx1) + try_set(&_features, .fma, 12, ecx1) + try_set(&_features, .sse41, 19, ecx1) + try_set(&_features, .sse42, 20, ecx1) + try_set(&_features, .popcnt, 23, ecx1) + try_set(&_features, .aes, 25, ecx1) + try_set(&_features, .os_xsave, 27, ecx1) + try_set(&_features, .rdrand, 30, ecx1) when ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD { // xgetbv is an illegal instruction under FreeBSD 13, OpenBSD 7.1 and NetBSD 10 // return before probing further - cpu_features = set return } @@ -99,15 +98,15 @@ init_cpu_features :: proc "c" () { // after they started checking both OSXSAVE and XSAVE. // // See: crbug.com/375968 - os_supports_avx := false + os_supports_avx := false os_supports_avx512 := false - if .os_xsave in set && is_set(26, ecx1) { + if .os_xsave in _features && is_set(26, ecx1) { eax, _ := xgetbv(0) - os_supports_avx = is_set(1, eax) && is_set(2, eax) + os_supports_avx = is_set(1, eax) && is_set(2, eax) os_supports_avx512 = is_set(5, eax) && is_set(6, eax) && is_set(7, eax) } if os_supports_avx { - try_set(&set, .avx, 28, ecx1) + try_set(&_features, .avx, 28, ecx1) } if max_id < 7 { @@ -115,56 +114,61 @@ init_cpu_features :: proc "c" () { } _, ebx7, ecx7, edx7 := cpuid(7, 0) - try_set(&set, .bmi1, 3, ebx7) - try_set(&set, .sha, 29, ebx7) + try_set(&_features, .bmi1, 3, ebx7) + try_set(&_features, .sha, 29, ebx7) if os_supports_avx { - try_set(&set, .avx2, 5, ebx7) + try_set(&_features, .avx2, 5, ebx7) } if os_supports_avx512 { - try_set(&set, .avx512f, 16, ebx7) - try_set(&set, .avx512dq, 17, ebx7) - try_set(&set, .avx512ifma, 21, ebx7) - try_set(&set, .avx512pf, 26, ebx7) - try_set(&set, .avx512er, 27, ebx7) - try_set(&set, .avx512cd, 28, ebx7) - try_set(&set, .avx512bw, 30, ebx7) + try_set(&_features, .avx512f, 16, ebx7) + try_set(&_features, .avx512dq, 17, ebx7) + try_set(&_features, .avx512ifma, 21, ebx7) + try_set(&_features, .avx512pf, 26, ebx7) + try_set(&_features, .avx512er, 27, ebx7) + try_set(&_features, .avx512cd, 28, ebx7) + try_set(&_features, .avx512bw, 30, ebx7) // XMM/YMM are also required for 128/256-bit instructions if os_supports_avx { - try_set(&set, .avx512vl, 31, ebx7) + try_set(&_features, .avx512vl, 31, ebx7) } - try_set(&set, .avx512vbmi, 1, ecx7) - try_set(&set, .avx512vbmi2, 6, ecx7) - try_set(&set, .avx512vnni, 11, ecx7) - try_set(&set, .avx512bitalg, 12, ecx7) - try_set(&set, .avx512vpopcntdq, 14, ecx7) + try_set(&_features, .avx512vbmi, 1, ecx7) + try_set(&_features, .avx512vbmi2, 6, ecx7) + try_set(&_features, .avx512vnni, 11, ecx7) + try_set(&_features, .avx512bitalg, 12, ecx7) + try_set(&_features, .avx512vpopcntdq, 14, ecx7) - try_set(&set, .avx512vp2intersect, 8, edx7) - try_set(&set, .avx512fp16, 23, edx7) + try_set(&_features, .avx512vp2intersect, 8, edx7) + try_set(&_features, .avx512fp16, 23, edx7) eax7_1, _, _, _ := cpuid(7, 1) - try_set(&set, .avx512bf16, 5, eax7_1) + try_set(&_features, .avx512bf16, 5, eax7_1) } - try_set(&set, .bmi2, 8, ebx7) - try_set(&set, .erms, 9, ebx7) - try_set(&set, .rdseed, 18, ebx7) - try_set(&set, .adx, 19, ebx7) - - cpu_features = set + try_set(&_features, .bmi2, 8, ebx7) + try_set(&_features, .erms, 9, ebx7) + try_set(&_features, .rdseed, 18, ebx7) + try_set(&_features, .adx, 19, ebx7) } @(private) -_cpu_name_buf: [72]u8 +_cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return _features +} + +// `cpuid` is a barrier so we try not performing this query this more than necessary. +// `atomic_load_explicit` is also a barrier, so we're doing this lookup only once, before `main()` +@(private) _name_buf: [72]u8 +@(private) _name: string @(init, private) -init_cpu_name :: proc "c" () { +_init_cpu_name :: proc "contextless" () { number_of_extended_ids, _, _, _ := cpuid(0x8000_0000, 0) if number_of_extended_ids < 0x8000_0004 { return } - _buf := (^[0x12]u32)(&_cpu_name_buf) + _buf := (^[0x12]u32)(&_name_buf) _buf[ 0], _buf[ 1], _buf[ 2], _buf[ 3] = cpuid(0x8000_0002, 0) _buf[ 4], _buf[ 5], _buf[ 6], _buf[ 7] = cpuid(0x8000_0003, 0) _buf[ 8], _buf[ 9], _buf[10], _buf[11] = cpuid(0x8000_0004, 0) @@ -172,12 +176,16 @@ init_cpu_name :: proc "c" () { // Some CPUs like may include leading or trailing spaces. Trim them. // e.g. ` Intel(R) Xeon(R) CPU E5-1650 v2 @ 3.50GHz` - brand := string(_cpu_name_buf[:]) - for len(brand) > 0 && brand[0] == 0 || brand[0] == ' ' { - brand = brand[1:] + _name = string(_name_buf[:]) + for len(_name) > 0 && _name[0] == 0 || _name[0] == ' ' { + _name = _name[1:] } - for len(brand) > 0 && brand[len(brand) - 1] == 0 || brand[len(brand) - 1] == ' ' { - brand = brand[:len(brand) - 1] + for len(_name) > 0 && _name[len(_name) - 1] == 0 || _name[len(_name) - 1] == ' ' { + _name = _name[:len(_name) - 1] } - cpu_name = brand } + +@(private) +_cpu_name :: proc "contextless" () -> (name: string) { + return _name +} \ No newline at end of file diff --git a/core/sys/info/cpu_linux_arm.odin b/core/sys/info/cpu_linux_arm.odin index 6408decb7..492b51c8b 100644 --- a/core/sys/info/cpu_linux_arm.odin +++ b/core/sys/info/cpu_linux_arm.odin @@ -2,11 +2,19 @@ #+build linux package sysinfo +import "base:runtime" import "core:sys/linux" +import "core:strconv" import "core:strings" +@(private) +_cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return _features +} + @(init, private) -init_cpu_features :: proc() { +_init_cpu_features :: proc "contextless" () { + context = runtime.default_context() fd, err := linux.open("/proc/cpuinfo", {}) if err != .NONE { return } defer linux.close(fd) @@ -16,9 +24,6 @@ init_cpu_features :: proc() { n, rerr := linux.read(fd, buf[:]) if rerr != .NONE || n == 0 { return } - features: CPU_Features - defer cpu_features = features - str := string(buf[:n]) for line in strings.split_lines_iterator(&str) { key, _, value := strings.partition(line, ":") @@ -29,37 +34,68 @@ init_cpu_features :: proc() { for feature in strings.split_by_byte_iterator(&value, ' ') { switch feature { - case "asimd", "neon": features += { .asimd } - case "fp": features += { .floatingpoint } - case "asimdhp": features += { .asimdhp } - case "asimdbf16": features += { .bf16 } - case "fcma": features += { .fcma } - case "asimdfhm": features += { .fhm } - case "fphp", "half": features += { .fp16 } - case "frint": features += { .frint } - case "i8mm": features += { .i8mm } - case "jscvt": features += { .jscvt } - case "asimdrdm": features += { .rdm } + case "asimd", "neon": _features += { .asimd } + case "fp": _features += { .floatingpoint } + case "asimdhp": _features += { .asimdhp } + case "asimdbf16": _features += { .bf16 } + case "fcma": _features += { .fcma } + case "asimdfhm": _features += { .fhm } + case "fphp", "half": _features += { .fp16 } + case "frint": _features += { .frint } + case "i8mm": _features += { .i8mm } + case "jscvt": _features += { .jscvt } + case "asimdrdm": _features += { .rdm } - case "flagm": features += { .flagm } - case "flagm2": features += { .flagm2 } - case "crc32": features += { .crc32 } + case "flagm": _features += { .flagm } + case "flagm2": _features += { .flagm2 } + case "crc32": _features += { .crc32 } - case "atomics": features += { .lse } - case "lrcpc": features += { .lrcpc } - case "ilrcpc": features += { .lrcpc2 } + case "atomics": _features += { .lse } + case "lrcpc": _features += { .lrcpc } + case "ilrcpc": _features += { .lrcpc2 } - case "aes": features += { .aes } - case "pmull": features += { .pmull } - case "sha1": features += { .sha1 } - case "sha2": features += { .sha256 } - case "sha3": features += { .sha3 } - case "sha512": features += { .sha512 } + case "aes": _features += { .aes } + case "pmull": _features += { .pmull } + case "sha1": _features += { .sha1 } + case "sha2": _features += { .sha256 } + case "sha3": _features += { .sha3 } + case "sha512": _features += { .sha512 } - case "sb": features += { .sb } - case "ssbs": features += { .ssbs } + case "sb": _features += { .sb } + case "ssbs": _features += { .ssbs } } } break } } + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + context = runtime.default_context() + fd, err := linux.open("/proc/cpuinfo", {}) + if err != .NONE { return } + defer linux.close(fd) + + // This is probably enough right? + buf: [4096]byte + n, rerr := linux.read(fd, buf[:]) + if rerr != .NONE || n == 0 { return } + + physical_ok, logical_ok: bool + + str := string(buf[:n]) + for line in strings.split_lines_iterator(&str) { + key, _, value := strings.partition(line, ":") + key = strings.trim_space(key) + value = strings.trim_space(value) + + if key == "cpu cores" && !physical_ok{ + physical, physical_ok = strconv.parse_int(value) + } + + if key == "siblings" && !logical_ok{ + logical, logical_ok = strconv.parse_int(value) + } + } + return physical, logical, physical_ok || logical_ok +} \ No newline at end of file diff --git a/core/sys/info/cpu_linux_intel.odin b/core/sys/info/cpu_linux_intel.odin new file mode 100644 index 000000000..1823678ee --- /dev/null +++ b/core/sys/info/cpu_linux_intel.odin @@ -0,0 +1,39 @@ +#+build i386, amd64 +#+build linux +package sysinfo + +import "base:runtime" +import "core:sys/linux" +import "core:strings" +import "core:strconv" + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + context = runtime.default_context() + fd, err := linux.open("/proc/cpuinfo", {}) + if err != .NONE { return } + defer linux.close(fd) + + // This is probably enough right? + buf: [4096]byte + n, rerr := linux.read(fd, buf[:]) + if rerr != .NONE || n == 0 { return } + + physical_ok, logical_ok: bool + + str := string(buf[:n]) + for line in strings.split_lines_iterator(&str) { + key, _, value := strings.partition(line, ":") + key = strings.trim_space(key) + value = strings.trim_space(value) + + if key == "cpu cores" && !physical_ok{ + physical, physical_ok = strconv.parse_int(value) + } + + if key == "siblings" && !logical_ok{ + logical, logical_ok = strconv.parse_int(value) + } + } + return physical, logical, physical_ok || logical_ok +} \ No newline at end of file diff --git a/core/sys/info/cpu_linux_riscv64.odin b/core/sys/info/cpu_linux_riscv64.odin index 84f6134d4..519c6b315 100644 --- a/core/sys/info/cpu_linux_riscv64.odin +++ b/core/sys/info/cpu_linux_riscv64.odin @@ -3,14 +3,13 @@ package sysinfo import "base:intrinsics" - +import "base:runtime" import "core:sys/linux" +import "core:strconv" +import "core:strings" @(init, private) -init_cpu_features :: proc() { - _features: CPU_Features - defer cpu_features = _features - +_init_cpu_features :: proc "contextless" () { HWCAP_Bits :: enum u64 { I = 'I' - 'A', M = 'M' - 'A', @@ -81,11 +80,11 @@ init_cpu_features :: proc() { } err := linux.riscv_hwprobe(raw_data(pairs), len(pairs), 0, nil, {}) if err != nil { - assert(err == .ENOSYS, "unexpected error from riscv_hwprobe()") + assert_contextless(err == .ENOSYS, "unexpected error from riscv_hwprobe()") return } - assert(pairs[0].key == .IMA_EXT_0) + assert_contextless(pairs[0].key == .IMA_EXT_0) exts := pairs[0].value.ima_ext_0 exts -= { .FD, .C, .V } _features += transmute(CPU_Features)exts @@ -97,7 +96,7 @@ init_cpu_features :: proc() { _features += { .Misaligned_Supported } } } else { - assert(pairs[1].key == .CPUPERF_0) + assert_contextless(pairs[1].key == .CPUPERF_0) if .FAST in pairs[1].value.cpu_perf_0 { _features += { .Misaligned_Supported, .Misaligned_Fast } } else if .UNSUPPORTED not_in pairs[1].value.cpu_perf_0 { @@ -107,7 +106,43 @@ init_cpu_features :: proc() { } } -@(init, private) -init_cpu_name :: proc() { - cpu_name = "RISCV64" +@(private) +_cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return _features } + +@(private) +_cpu_name :: proc() -> (name: string) { + return "RISCV64" +} + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + context = runtime.default_context() // No allocations, only needed because `core:strings` wants it. + fd, err := linux.open("/proc/cpuinfo", {}) + if err != .NONE { return } + defer linux.close(fd) + + // This is probably enough right? + buf: [4096]byte + n, rerr := linux.read(fd, buf[:]) + if rerr != .NONE || n == 0 { return } + + physical_ok, logical_ok: bool + + str := string(buf[:n]) + for line in strings.split_lines_iterator(&str) { + key, _, value := strings.partition(line, ":") + key = strings.trim_space(key) + value = strings.trim_space(value) + + if key == "cpu cores" && !physical_ok{ + physical, physical_ok = strconv.parse_int(value) + } + + if key == "siblings" && !logical_ok{ + logical, logical_ok = strconv.parse_int(value) + } + } + return physical, logical, physical_ok || logical_ok +} \ No newline at end of file diff --git a/core/sys/info/cpu_other.odin b/core/sys/info/cpu_other.odin new file mode 100644 index 000000000..53e901275 --- /dev/null +++ b/core/sys/info/cpu_other.odin @@ -0,0 +1,14 @@ +#+build openbsd, freebsd, netbsd +package sysinfo + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + return 0, 0, false +} + +when ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64 { + @(private) + _cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return {} + } +} diff --git a/core/sys/info/cpu_riscv64.odin b/core/sys/info/cpu_riscv64.odin index c3319c48c..9303e6e79 100644 --- a/core/sys/info/cpu_riscv64.odin +++ b/core/sys/info/cpu_riscv64.odin @@ -96,5 +96,6 @@ CPU_Feature :: enum u64 { CPU_Features :: distinct bit_set[CPU_Feature; u64] -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +// Looking up CPU features is expensive on RISCV, and `atomic_load_explicit` +// is also a barrier, so we're doing this lookup only once, before `main()` +@(private) _features: CPU_Features \ No newline at end of file diff --git a/core/sys/info/cpu_wasm.odin b/core/sys/info/cpu_wasm.odin new file mode 100644 index 000000000..f33f7cbb4 --- /dev/null +++ b/core/sys/info/cpu_wasm.odin @@ -0,0 +1,20 @@ +#+build wasm32, wasm64p32 +package sysinfo + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + return 0, 0, false +} + +CPU_Feature :: enum u64 {} +CPU_Features :: distinct bit_set[CPU_Feature; u64] + +@(private) +_cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return {} +} + +@(private) +_cpu_name :: proc() -> (name: string) { + return "wasm32" when ODIN_ARCH == .wasm32 else "wasm64p32" +} \ No newline at end of file diff --git a/core/sys/info/cpu_windows.odin b/core/sys/info/cpu_windows.odin new file mode 100644 index 000000000..604ec3641 --- /dev/null +++ b/core/sys/info/cpu_windows.odin @@ -0,0 +1,35 @@ +package sysinfo + +import sys "core:sys/windows" +import "base:intrinsics" + +@(private) +_cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + // Reportedly, Windows Server supports a maximum of 256 logical cores. + // The most scratch memory we need therefore is 8192 bytes = 256 * size_of(sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION) + infos: [256]sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION + + // Query for the required buffer size. + returned_length: sys.DWORD + sys.GetLogicalProcessorInformation(nil, &returned_length) + + if int(returned_length) > size_of(infos) { + return 0, 0, false + } + + count := int(returned_length) / size_of(sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION) + + // If it still doesn't work, return + if ok := sys.GetLogicalProcessorInformation(raw_data(infos[:]), &returned_length); !ok { + return 0, 0, false + } + + for info in infos[:count] { + #partial switch info.Relationship { + case .RelationProcessorCore: physical += 1 + case .RelationNumaNode: logical += int(intrinsics.count_ones(info.ProcessorMask)) + } + } + + return physical, logical, true +} \ No newline at end of file diff --git a/core/sys/info/doc.odin b/core/sys/info/doc.odin index 2fd34b864..b235eb5f4 100644 --- a/core/sys/info/doc.odin +++ b/core/sys/info/doc.odin @@ -1,23 +1,13 @@ /* -Copyright 2022 Jeroen van Rijn . -Made available under Odin's BSD-3 license. - -List of contributors: - Jeroen van Rijn: Initial implementation. - Laytan: ARM and RISC-V CPU feature detection, iOS/macOS platform overhaul. -*/ - -/* -Package `core:sys/info` gathers system information on: -Windows, Linux, macOS, FreeBSD & OpenBSD. +Gathers system information on `Windows`, `Linux`, `macOS`, `FreeBSD` & `OpenBSD`. Simply import the package and you'll have access to the OS version, RAM amount and CPU information. On Windows, GPUs will also be enumerated using the registry. -CPU feature flags can be tested against `cpu_features`, where applicable, e.g. -`if .aes in info.cpu_features.? { ... }` +CPU feature flags can be tested against `cpu_features`, where applicable, e.g.: +`if .aes in info.cpu_features() { ... }` Example: package main @@ -26,63 +16,101 @@ Example: import si "core:sys/info" main :: proc() { - fmt.printfln("Odin: %v", ODIN_VERSION) - fmt.printfln("OS: %v", si.os_version.as_string) - fmt.printfln("OS: %#v", si.os_version) - fmt.printfln("CPU: %v", si.cpu_name) - fmt.printfln("RAM: %#.1M", si.ram.total_ram) + fmt.printfln("Odin: %v", ODIN_VERSION) + if version, version_ok := si.os_version(context.allocator); version_ok { + defer si.destroy_os_version(version, context.allocator) + fmt.printfln("OS (full): %v", version.full) + fmt.printfln("OS (rel): %v", version.release) + fmt.printfln("OS: %v", version.os) + fmt.printfln("Kernel: %v", version.kernel) + } + fmt.printfln("CPU: %v", si.cpu_name()) + fmt.printfln(" %v", si.cpu_features()) + if physical, logical, cores_ok := si.cpu_core_count(); cores_ok { + fmt.printfln("CPU cores: %vc/%vt", physical, logical) + } - // fmt.printfln("Features: %v", si.cpu_features) - // fmt.printfln("MacOS version: %v", si.macos_version) + if total_ram, free_ram, total_swap, free_swap, ram_ok := si.ram_stats(); ram_ok { + fmt.printfln("RAM: %#.1M/%#.1M", free_ram, total_ram) + fmt.printfln("SWAP: %#.1M/%#.1M", free_swap, total_swap) + } - fmt.println() - for gpu, i in si.gpus { - fmt.printfln("GPU #%v:", i) - fmt.printfln("\tVendor: %v", gpu.vendor_name) - fmt.printfln("\tModel: %v", gpu.model_name) - fmt.printfln("\tVRAM: %#.1M", gpu.total_ram) + it: si.GPU_Iterator + for gpu, i in si.iterate_gpus(&it) { + fmt.printfln("%d:", i) + fmt.printfln("\tVendor: %v", gpu.vendor) + fmt.printfln("\tModel: %v", gpu.model) + fmt.printfln("\tVRAM: %#.1M", gpu.vram) + fmt.printfln("\tDriver: %v", gpu.driver) } } -- Example Windows output: + /* + Example Windows output: - Odin: dev-2022-09 - OS: Windows 10 Professional (version: 20H2), build: 19042.1466 - OS: OS_Version{ - platform = "Windows", - major = 10, - minor = 0, - patch = 0, - build = [ - 19042, - 1466, - ], - version = "20H2", - as_string = "Windows 10 Professional (version: 20H2), build: 19042.1466", - } - CPU: AMD Ryzen 7 1800X Eight-Core Processor - RAM: 64.0 GiB - GPU #0: - Vendor: Advanced Micro Devices, Inc. - Model: Radeon RX Vega - VRAM: 8.0 GiB + Odin: dev-2026-02 + OS (full): Windows 10 Professional (version: 22H2), build: 19045.6575 + OS (rel): 22H2 + OS: Version{major = 10, minor = 0, patch = 0} + Kernel: Version{major = 10, minor = 19045, patch = 6575} + CPU: AMD Ryzen 9 5950X 16-Core Processor + CPU_Features{aes, adx, avx, avx2, bmi1, bmi2, erms, fma, os_xsave, pclmulqdq, popcnt, rdrand, rdseed, sha, sse2, sse3, ssse3, sse41, sse42} + CPU cores: 16c/32t + RAM: 32.1 GiB/63.9 GiB + SWAP: 21.6 GiB/73.4 GiB -- Example macOS output: + GPU #0: + Vendor: Advanced Micro Devices, Inc. + Model: AMD Radeon RX 9070 + VRAM: 15.9 GiB + Driver: 32.0.22029.1019 - ODIN: dev-2022-09 - OS: OS_Version{ - platform = "MacOS", - major = 21, - minor = 5, - patch = 0, - build = [ - 0, - 0, - ], - version = "21F79", - as_string = "macOS Monterey 12.4 (build 21F79, kernel 21.5.0)", - } - CPU: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz - RAM: 8.0 GiB + Example Linux output: + + Odin: dev-2026-02 + OS (full): Ubuntu 24.04.3 LTS, Linux 6.6.87.2-microsoft-standard-WSL2 + OS (rel): microsoft-standard-WSL2 + OS: Version{major = 24, minor = 4, patch = 3} + Kernel: Version{major = 6, minor = 6, patch = 87} + CPU: AMD Ryzen 9 5950X 16-Core Processor + CPU_Features{aes, adx, avx, avx2, bmi1, bmi2, erms, fma, os_xsave, pclmulqdq, popcnt, rdrand, rdseed, sha, sse2, sse3, ssse3, sse41, sse42} + CPU cores: 16c/32t + RAM: 29.2 GiB/31.3 GiB + SWAP: 8.0 GiB/8.0 GiB + + Example macOS output: + + Odin: dev-2026-02 + OS (full): macOS Tahoe 26.3.0 (build 25D125, kernel 25.3.0) + OS (rel): 25D125 + OS: Version{major = 26, minor = 3, patch = 0} + Kernel: Version{major = 25, minor = 3, patch = 0} + CPU: Apple M4 Pro + CPU_Features{asimd, floatingpoint, asimdhp, bf16, fcma, fhm, fp16, frint, i8mm, jscvt, rdm, flagm, flagm2, crc32, lse, lrcpc, lrcpc2, aes, pmull, sha1, sha256, sha512, sha3, sb} + CPU cores: 12c/12t + RAM: 0.0 B/24.0 GiB + SWAP: 0.0 B/0.0 B + + Example FreeBSD output: + + Odin: dev-2026-02 + OS (full): FreeBSD 15.0-RELEASE-p2 releng/15.0-n281005-5fb0f8e9e61d GENERIC, revision 199506 + OS (rel): + OS: Version{major = 15, minor = 0, patch = 199506} + Kernel: Version{major = 15, minor = 0, patch = 199506} + CPU: AMD Ryzen 9 5950X 16-Core Processor + CPU_Features{aes, fma, os_xsave, pclmulqdq, popcnt, rdrand, sse2, sse3, ssse3, sse41, sse42} + RAM: 7.6 GiB/7.9 GiB + SWAP: 0.0 B/0.0 B + */ */ package sysinfo + +/* +Copyright 2022 Jeroen van Rijn . +Made available under Odin's license. + +List of contributors: + Jeroen van Rijn: Initial implementation. + Laytan: ARM and RISC-V CPU feature detection, iOS/macOS platform overhaul. +*/ \ No newline at end of file diff --git a/core/sys/info/platform_bsd.odin b/core/sys/info/platform_bsd.odin index 6bb32cd3d..431b48200 100644 --- a/core/sys/info/platform_bsd.odin +++ b/core/sys/info/platform_bsd.odin @@ -1,25 +1,20 @@ #+build openbsd, netbsd package sysinfo -import sys "core:sys/unix" -import "core:strings" -import "core:strconv" import "base:runtime" +import "core:strings" +import sys "core:sys/unix" -@(private) -version_string_buf: [1024]u8 - -@(init, private) -init_os_version :: proc () { +_os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { when ODIN_OS == .NetBSD { - os_version.platform = .NetBSD + res.platform = .NetBSD } else { - os_version.platform = .OpenBSD + res.platform = .OpenBSD } kernel_version_buf: [1024]u8 - b := strings.builder_from_bytes(version_string_buf[:]) + b := strings.builder_make_none(allocator = allocator, loc = loc) // Retrieve kernel info using `sysctl`, e.g. OpenBSD and NetBSD mib := []i32{sys.CTL_KERN, sys.KERN_OSTYPE} if !sys.sysctl(mib, &kernel_version_buf) { @@ -37,19 +32,8 @@ init_os_version :: proc () { version := string(cstring(raw_data(kernel_version_buf[:]))) strings.write_string(&b, version) - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - // Parse kernel version - triplet := strings.split(version, ".", context.temp_allocator) - if len(triplet) == 2 { - major, major_ok := strconv.parse_int(triplet[0]) - minor, minor_ok := strconv.parse_int(triplet[1]) - - if major_ok && minor_ok { - os_version.major = major - os_version.minor = minor - } - } + res.kernel = _parse_version(version) // Retrieve kernel revision using `sysctl`, e.g. 199506 mib = []i32{sys.CTL_KERN, sys.KERN_OSREV} @@ -57,20 +41,27 @@ init_os_version :: proc () { if !sys.sysctl(mib, &revision) { return } - os_version.patch = revision + res.kernel.patch = revision strings.write_string(&b, ", build ") strings.write_int(&b, revision) // Finalize pretty name. - os_version.as_string = strings.to_string(b) + res.full = strings.to_string(b) + + return res, true } -@(init, private) -init_ram :: proc() { +@(private) +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { // Retrieve RAM info using `sysctl` mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM64} - mem_size: u64 - if sys.sysctl(mib, &mem_size) { - ram.total_ram = int(mem_size) + if sys.sysctl(mib, &total_ram) { + ok = true } -} + + mib = []i32{sys.CTL_HW, sys.HW_USERMEM64} + if sys.sysctl(mib, &free_ram) { + ok = true + } + return +} \ No newline at end of file diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin index 7dc49bcd1..fe0b5ab2b 100644 --- a/core/sys/info/platform_darwin.odin +++ b/core/sys/info/platform_darwin.odin @@ -1,19 +1,16 @@ package sysinfo -import "core:strconv" +import "base:runtime" import "core:strings" import "core:sys/unix" import NS "core:sys/darwin/Foundation" @(private) -version_string_buf: [1024]u8 - -@(init, private) -init_platform :: proc() { +_os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { ws :: strings.write_string wi :: strings.write_int - b := strings.builder_from_bytes(version_string_buf[:]) + b := strings.builder_make_none(allocator = allocator, loc = loc) version: NS.OperatingSystemVersion { @@ -21,19 +18,17 @@ init_platform :: proc() { info := NS.ProcessInfo.processInfo() version = info->operatingSystemVersion() - mem := info->physicalMemory() - - ram.total_ram = int(mem) } - macos_version = {int(version.majorVersion), int(version.minorVersion), int(version.patchVersion)} + res.os = {int(version.majorVersion), int(version.minorVersion), int(version.patchVersion)} - when ODIN_PLATFORM_SUBTARGET == .iOS { - os_version.platform = .iOS + when ODIN_PLATFORM_SUBTARGET_IOS { + res.platform = .iOS ws(&b, "iOS") } else { - os_version.platform = .MacOS + res.platform = .MacOS switch version.majorVersion { + case 26: ws(&b, "macOS Tahoe") case 15: ws(&b, "macOS Sequoia") case 14: ws(&b, "macOS Sonoma") case 13: ws(&b, "macOS Ventura") @@ -68,34 +63,37 @@ init_platform :: proc() { { build_buf: [12]u8 mib := []i32{unix.CTL_KERN, unix.KERN_OSVERSION} - ok := unix.sysctl(mib, &build_buf) - build := string(cstring(raw_data(build_buf[:]))) if ok else "Unknown" - + build := "Unknown" + if unix.sysctl(mib, &build_buf) { + build = string(cstring(raw_data(build_buf[:]))) + } ws(&b, " (build ") - build_start := len(b.buf) ws(&b, build) - os_version.version = string(b.buf[build_start:][:len(build)]) + res.release = string(b.buf[build_start:][:len(build)]) } { // Match on XNU kernel version version_bits: [12]u8 // enough for 999.999.999\x00 mib := []i32{unix.CTL_KERN, unix.KERN_OSRELEASE} - ok := unix.sysctl(mib, &version_bits) - kernel := string(cstring(raw_data(version_bits[:]))) if ok else "Unknown" - - major, _, tail := strings.partition(kernel, ".") - minor, _, patch := strings.partition(tail, ".") - - os_version.major, _ = strconv.parse_int(major, 10) - os_version.minor, _ = strconv.parse_int(minor, 10) - os_version.patch, _ = strconv.parse_int(patch, 10) - + kernel := "Unknown" + if unix.sysctl(mib, &version_bits) { + kernel = string(cstring(raw_data(version_bits[:]))) + res.kernel = _parse_version(kernel) + } ws(&b, ", kernel ") ws(&b, kernel) ws(&b, ")") } - os_version.as_string = string(b.buf[:]) + res.full = strings.to_string(b) + return res, true } + +@(private) +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { + NS.scoped_autoreleasepool() + info := NS.ProcessInfo.processInfo() + return i64(info->physicalMemory()), 0, 0, 0, true +} \ No newline at end of file diff --git a/core/sys/info/platform_freebsd.odin b/core/sys/info/platform_freebsd.odin index b26fb7875..6f32d4232 100644 --- a/core/sys/info/platform_freebsd.odin +++ b/core/sys/info/platform_freebsd.odin @@ -2,19 +2,15 @@ package sysinfo import sys "core:sys/unix" import "core:strings" -import "core:strconv" import "base:runtime" @(private) -version_string_buf: [1024]u8 - -@(init, private) -init_os_version :: proc () { - os_version.platform = .FreeBSD +_os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { + res.platform = .FreeBSD kernel_version_buf: [1024]u8 - b := strings.builder_from_bytes(version_string_buf[:]) + b := strings.builder_make_none(allocator = allocator, loc = loc) // Retrieve kernel info using `sysctl`, e.g. FreeBSD 13.1-RELEASE-p2 GENERIC mib := []i32{sys.CTL_KERN, sys.KERN_VERSION} if !sys.sysctl(mib, &kernel_version_buf) { @@ -25,21 +21,18 @@ init_os_version :: proc () { pretty_name = strings.trim(pretty_name, "\n") strings.write_string(&b, pretty_name) - // l := strings.builder_len(b) - // Retrieve kernel revision using `sysctl`, e.g. 199506 mib = []i32{sys.CTL_KERN, sys.KERN_OSREV} revision: int if !sys.sysctl(mib, &revision) { return } - os_version.patch = revision strings.write_string(&b, ", revision ") strings.write_int(&b, revision) // Finalize pretty name. - os_version.as_string = strings.to_string(b) + res.full = strings.to_string(b) // Retrieve kernel release using `sysctl`, e.g. 13.1-RELEASE-p2 mib = []i32{sys.CTL_KERN, sys.KERN_OSRELEASE} @@ -47,32 +40,28 @@ init_os_version :: proc () { return } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - // Parse kernel version release := string(cstring(raw_data(kernel_version_buf[:]))) - version_bits := strings.split_n(release, "-", 2, context.temp_allocator) - if len(version_bits) > 1 { - // Parse major, minor from KERN_OSRELEASE - triplet := strings.split(version_bits[0], ".", context.temp_allocator) - if len(triplet) == 2 { - major, major_ok := strconv.parse_int(triplet[0]) - minor, minor_ok := strconv.parse_int(triplet[1]) + version_bits, _, _ := strings.partition(release, "-") + res.kernel = _parse_version(version_bits) + res.kernel.patch = revision - if major_ok && minor_ok { - os_version.major = major - os_version.minor = minor - } - } - } + res.os = res.kernel + + return res, true } -@(init, private) -init_ram :: proc() { +@(private) +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { // Retrieve RAM info using `sysctl` mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM} - mem_size: u64 - if sys.sysctl(mib, &mem_size) { - ram.total_ram = int(mem_size) + if sys.sysctl(mib, &total_ram) { + ok = true } -} \ No newline at end of file + + mib = []i32{sys.CTL_HW, sys.HW_USERMEM} + if sys.sysctl(mib, &free_ram) { + ok = true + } + return +} diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin index 9c342e567..eef77afa0 100644 --- a/core/sys/info/platform_linux.odin +++ b/core/sys/info/platform_linux.odin @@ -1,19 +1,16 @@ package sysinfo import "base:intrinsics" - +import "base:runtime" import "core:strconv" import "core:strings" import "core:sys/linux" @(private) -version_string_buf: [1024]u8 +_os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { + res.platform = .Linux -@(init, private) -init_os_version :: proc () { - os_version.platform = .Linux - - b := strings.builder_from_bytes(version_string_buf[:]) + b := strings.builder_make_none(allocator = allocator, loc = loc) // Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS` pretty_parse: { @@ -23,10 +20,7 @@ init_os_version :: proc () { break pretty_parse } - defer { - cerrno := linux.close(fd) - assert(cerrno == .NONE, "Failed to close the file descriptor") - } + defer linux.close(fd) os_release_buf: [2048]u8 n, read_errno := linux.read(fd, os_release_buf[:]) @@ -36,17 +30,27 @@ init_os_version :: proc () { } release := string(os_release_buf[:n]) - // Search the line in the file until we find "PRETTY_NAME=" - NEEDLE :: "PRETTY_NAME=\"" - _, _, post := strings.partition(release, NEEDLE) - if len(post) > 0 { - end := strings.index_any(post, "\"\n") - if end > -1 && post[end] == '"' { - strings.write_string(&b, post[:end]) + { + // Search the line in the file until we find "PRETTY_NAME=" + _, _, post := strings.partition(release, `PRETTY_NAME="`) + if len(post) > 0 { + end := strings.index_any(post, "\"\n") + if end > -1 && post[end] == '"' { + strings.write_string(&b, post[:end]) + } + } + if strings.builder_len(b) == 0 { + strings.write_string(&b, "Unknown Linux Distro") } } - if strings.builder_len(b) == 0 { - strings.write_string(&b, "Unknown Linux Distro") + + { + // Search the line in the file until we find "VERSION=" + _, _, post := strings.partition(release, `VERSION="`) + if len(post) > 0 { + pre, _, _ := strings.partition(post, ` `) + res.os = _parse_version(pre) + } } } @@ -63,43 +67,112 @@ init_os_version :: proc () { strings.write_string(&b, string(cstring(&uts.release[0]))) release_str := string(b.buf[release_i:]) - os_version.as_string = strings.to_string(b) + res.full = strings.to_string(b) // Parse the Linux version out of the release string version_loop: { version_num, _, version_suffix := strings.partition(release_str, "-") - os_version.version = version_suffix + res.release = version_suffix + res.kernel = _parse_version(version_num) - i: int - for part in strings.split_iterator(&version_num, ".") { - defer i += 1 + } + return res, true +} - dst: ^int - switch i { - case 0: dst = &os_version.major - case 1: dst = &os_version.minor - case 2: dst = &os_version.patch - case: break version_loop - } +@(private) +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { + // This is here for some of the strings procedures + context = runtime.default_context() - num, ok := strconv.parse_int(part) - if !ok { break version_loop } + // The approach is to read /proc/meminfo for the memory information. We do this over + // reading sysinfo() since sysinfo() only returns MemFree, which is based on the amount + // of free pages. The value we actually want is MemAvailable inside meminfo since it is + // estimated around being about to evict things out of the page cache. + fd, errno := linux.open("/proc/meminfo", {}) + if errno != .NONE { + // This should never happen since something would be wrong with the system + // if /proc/meminfo wasn't able to be opened for any reason. But, in the + // event that this _does_ happen, let's just try to recover through the + // syscall + sys_info: linux.Sys_Info + sysinfo_errno := linux.sysinfo(&sys_info) + assert_contextless(sysinfo_errno == .NONE, "If this has failed, there is no recovery from this") - dst^ = num + total_ram = i64(sys_info.totalram) * i64(sys_info.mem_unit) + free_ram = i64(sys_info.freeram) * i64(sys_info.mem_unit) + total_swap = i64(sys_info.totalswap) * i64(sys_info.mem_unit) + free_swap = i64(sys_info.freeswap) * i64(sys_info.mem_unit) + + ok = true + + return + } + + defer linux.close(fd) + + // We need a relatively large size to store all the info + meminfo_buf: [4096]u8 + n, read_errno := linux.read(fd, meminfo_buf[:]) + if read_errno != .NONE { + sys_info: linux.Sys_Info + sysinfo_errno := linux.sysinfo(&sys_info) + assert_contextless(sysinfo_errno == .NONE, "If this has failed, there is no recovery from this") + + total_ram = i64(sys_info.totalram) * i64(sys_info.mem_unit) + free_ram = i64(sys_info.freeram) * i64(sys_info.mem_unit) + total_swap = i64(sys_info.totalswap) * i64(sys_info.mem_unit) + free_swap = i64(sys_info.freeswap) * i64(sys_info.mem_unit) + + ok = true + + return + } + meminfo := string(meminfo_buf[:n]) + + // Fallback in the event MemAvailable is not found or is invalid in its value + mem_free: i64 + + mem_unit :: 1024 + for line in strings.split_lines_iterator(&meminfo) { + if len(line) == 0 { + continue + } + + colon_idx := strings.index(line, ":") + if colon_idx < 0 { + continue + } + + key := strings.trim_space(line[:colon_idx]) + value_str := strings.trim_space(strings.trim_suffix(line[colon_idx + 1:], "kB")) + + value, conv_ok := strconv.parse_i64(value_str, 10) + if !conv_ok { + continue + } + + switch key { + case "MemTotal": + total_ram = value * mem_unit + case "MemFree": + mem_free = value * mem_unit + case "MemAvailable": + free_ram = value * mem_unit + case "SwapTotal": + total_swap = value * mem_unit + case "SwapFree": + free_swap = value * mem_unit } } -} -@(init, private) -init_ram :: proc() { - // Retrieve RAM info using `sysinfo` - sys_info: linux.Sys_Info - errno := linux.sysinfo(&sys_info) - assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!") - ram = RAM{ - total_ram = int(sys_info.totalram) * int(sys_info.mem_unit), - free_ram = int(sys_info.freeram) * int(sys_info.mem_unit), - total_swap = int(sys_info.totalswap) * int(sys_info.mem_unit), - free_swap = int(sys_info.freeswap) * int(sys_info.mem_unit), + if free_ram == 0 || free_ram > total_ram { + // We opt to return MemFree here if MemAvailable is not found or is broken to some degree. + // This will act as a predictable fallback, but shouldn't ever really occur unless the user + // is on Linux < 3.14 + free_ram = mem_free } -} + + ok = true + + return +} \ No newline at end of file diff --git a/core/sys/info/platform_wasm.odin b/core/sys/info/platform_wasm.odin new file mode 100644 index 000000000..2778862e9 --- /dev/null +++ b/core/sys/info/platform_wasm.odin @@ -0,0 +1,14 @@ +#+build wasm32, wasm64p32 +package sysinfo + +import "base:runtime" + +@(private) +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { + return +} + +@(private) +_os_version :: proc(allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { + return {}, false +} \ No newline at end of file diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin index 4c00ddadf..fbaf071b9 100644 --- a/core/sys/info/platform_windows.odin +++ b/core/sys/info/platform_windows.odin @@ -1,35 +1,27 @@ package sysinfo +import "base:intrinsics" +import "base:runtime" +import "core:strings" +import "core:unicode/utf16" import sys "core:sys/windows" -import "base:intrinsics" -import "core:strings" -import "core:unicode/utf16" - -import "core:fmt" -import "base:runtime" @(private) -version_string_buf: [1024]u8 - -@(init, private) -init_os_version :: proc () { +_os_version :: proc (allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { /* - NOTE(Jeroen): - `GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10. - `RtlGetVersion` will return the true version. - - Rather than include the WinDDK, we ask the kernel directly. - `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion` is for the minor build version (Update Build Release) + NOTE(Jeroen): + `GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10. + `RtlGetVersion` will return the true version. + Rather than include the WinDDK, we ask the kernel directly. + `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion` is for the minor build version (Update Build Release) */ - os_version.platform = .Windows + res.platform = .Windows osvi: sys.OSVERSIONINFOEXW osvi.dwOSVersionInfoSize = size_of(osvi) - status := sys.RtlGetVersion(&osvi) - - if status != 0 { - return + if status := sys.RtlGetVersion(&osvi); status != 0 { + return res, false } product_type: sys.Windows_Product_Type @@ -39,11 +31,13 @@ init_os_version :: proc () { &product_type, ) - os_version.major = int(osvi.dwMajorVersion) - os_version.minor = int(osvi.dwMinorVersion) - os_version.build[0] = int(osvi.dwBuildNumber) + res.os.major = int(osvi.dwMajorVersion) + res.os.minor = int(osvi.dwMinorVersion) + res.kernel.major = int(osvi.dwMajorVersion) + res.kernel.minor = int(osvi.dwBuildNumber) + + b := strings.builder_make_none(allocator = allocator, loc = loc) - b := strings.builder_from_bytes(version_string_buf[:]) strings.write_string(&b, "Windows ") switch osvi.dwMajorVersion { @@ -121,13 +115,13 @@ init_os_version :: proc () { } // Grab DisplayVersion - os_version.version = format_display_version(&b) + res.release = format_display_version(&b) // Grab build number and UBR - os_version.build[1] = format_build_number(&b, int(osvi.dwBuildNumber)) + res.kernel.patch = format_build_number(&b, int(osvi.dwBuildNumber)) // Finish the string - os_version.as_string = strings.to_string(b) + res.full = strings.to_string(b) format_windows_product_type :: proc (b: ^strings.Builder, prod_type: sys.Windows_Product_Type) { #partial switch prod_type { @@ -222,14 +216,14 @@ init_os_version :: proc () { // Grab Windows DisplayVersion (like 20H02) format_display_version :: proc (b: ^strings.Builder) -> (version: string) { - dv, ok := read_reg_string( + scratch: [512]u8 + + if dv, ok := read_reg_string( sys.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "DisplayVersion", - ) - defer delete(dv) // It'll be interned into `version_string_buf` - - if ok { + scratch[:], + ); ok { strings.write_string(b, " (version: ") l := strings.builder_len(b^) strings.write_string(b, dv) @@ -241,13 +235,11 @@ init_os_version :: proc () { // Grab build number and UBR format_build_number :: proc (b: ^strings.Builder, major_build: int) -> (ubr: int) { - res, ok := read_reg_i32( + if res, ok := read_reg_i32( sys.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "UBR", - ) - - if ok { + ); ok { ubr = int(res) strings.write_string(b, ", build: ") strings.write_int(b, major_build) @@ -256,79 +248,117 @@ init_os_version :: proc () { } return } -} -@(init, private) -init_ram :: proc() { - state: sys.MEMORYSTATUSEX - - state.dwLength = size_of(state) - ok := sys.GlobalMemoryStatusEx(&state) - if !ok { - return - } - ram = RAM{ - total_ram = int(state.ullTotalPhys), - free_ram = int(state.ullAvailPhys), - total_swap = int(state.ullTotalPageFil), - free_swap = int(state.ullAvailPageFil), - } -} - -@(init, private) -init_gpu_info :: proc() { - - GPU_INFO_BASE :: "SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\" - - gpu_list: [dynamic]GPU - gpu_index: int - - for { - key := fmt.tprintf("%v\\%04d", GPU_INFO_BASE, gpu_index) - - if vendor, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "ProviderName"); ok { - append(&gpu_list, GPU{vendor_name = vendor}) - } else { - break - } - - if desc, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc"); ok { - gpu_list[gpu_index].model_name = desc - } - - if vram, ok := read_reg_i64(sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize"); ok { - gpu_list[gpu_index].total_ram = int(vram) - } - gpu_index += 1 - } - gpus = gpu_list[:] + return res, true } @(private) -read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok: bool) { +_ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { + state: sys.MEMORYSTATUSEX + + state.dwLength = size_of(state) + if ok := sys.GlobalMemoryStatusEx(&state); !ok { + return + } + + total_ram = i64(state.ullTotalPhys) + free_ram = i64(state.ullAvailPhys) + total_swap = i64(state.ullTotalPageFil) + free_swap = i64(state.ullAvailPageFil) + ok = true + + return +} + +_iterate_gpus :: proc(it: ^GPU_Iterator, minimum_vram := i64(256 * 1024 * 1024)) -> (gpu: GPU, index: int, ok: bool) { + GPU_ROOT_KEY :: `SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}` + + defer it.index += 1 + + gpu_key: sys.HKEY + if status := sys.RegOpenKeyExW( + sys.HKEY_LOCAL_MACHINE, + GPU_ROOT_KEY, + 0, + sys.KEY_ENUMERATE_SUB_KEYS, + &gpu_key, + ); status != i32(sys.ERROR_SUCCESS) { + return {}, it.index, false + } + defer sys.RegCloseKey(gpu_key) + + buf_wstring: [100]u16 + buf_len := u32(len(buf_wstring)) + buf_key: [4 * len(buf_wstring)]u8 + buf_leaf: [100]u8 + leaf: string + + gpu_loop: { + defer it._index += 1 + + if status := sys.RegEnumKeyW( + gpu_key, + auto_cast it._index, + &buf_wstring[0], + buf_len, + ); status != i32(sys.ERROR_SUCCESS) { + return {}, it.index, false + } + + utf16.decode_to_utf8(buf_leaf[:], buf_wstring[:]) + leaf = string(cstring(&buf_leaf[0])) + + // Skip leaves that are not of the form 000x + if is_integer(leaf) { + break gpu_loop + } + } + + n := copy(buf_key[:], GPU_ROOT_KEY) + buf_key[n] = '\\' + copy(buf_key[n+1:], leaf) + + key_len := len(GPU_ROOT_KEY) + len(leaf) + 1 + + utf16.encode_string(buf_wstring[:], string(buf_key[:key_len])) + key := cstring16(&buf_wstring[0]) + + // Determine if this is a real GPU, or perhaps a screen mirroring or RDP driver + // Real devices tend to have more than 256 MiB of VRAM + gpu.vram, _ = read_reg_i64 (sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize") + if gpu.vram < minimum_vram { + return + } + + // Real devices tend to have a matching PCI device + matching, _ := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "MatchingDeviceId", it._buffer[:100]) + if !strings.has_prefix(matching, "PCI\\VEN") { + return + } + + gpu.vendor, _ = read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "ProviderName", it._buffer[ 0:][:100]) + gpu.model, _ = read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc", it._buffer[100:][:100]) + gpu.driver, _ = read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverVersion", it._buffer[200:][:100]) + + return gpu, it.index, true +} + +@(private) +read_reg_string :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16, res_buf: []u8) -> (res: string, ok: bool) { if len(subkey) == 0 || len(val) == 0 { return } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - - BUF_SIZE :: 1024 - key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - - utf16.encode_string(key_name_wide, subkey) - utf16.encode_string(val_name_wide, val) - - result_wide := make([]u16, BUF_SIZE, context.temp_allocator) - result_size := sys.DWORD(BUF_SIZE * size_of(u16)) + buf_utf16: [1024]u16 + result_size := sys.DWORD(size_of(buf_utf16)) status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + subkey, + val, sys.RRF_RT_REG_SZ, nil, - raw_data(result_wide[:]), + raw_data(buf_utf16[:]), &result_size, ) if status != 0 { @@ -336,31 +366,22 @@ read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok return } - // Result string will be allocated for the caller. - result_utf8 := make([]u8, BUF_SIZE * 4, context.temp_allocator) - utf16.decode_to_utf8(result_utf8, result_wide[:result_size]) - return strings.clone_from_cstring(cstring(raw_data(result_utf8))), true + utf16.decode_to_utf8(res_buf[:], buf_utf16[:result_size / size_of(u16)]) + res = string(cstring(&res_buf[0])) + return res, true } + @(private) -read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool) { +read_reg_i32 :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16) -> (res: i32, ok: bool) { if len(subkey) == 0 || len(val) == 0 { return } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - - BUF_SIZE :: 1024 - key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - - utf16.encode_string(key_name_wide, subkey) - utf16.encode_string(val_name_wide, val) - result_size := sys.DWORD(size_of(i32)) status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + subkey, + val, sys.RRF_RT_REG_DWORD, nil, &res, @@ -368,26 +389,18 @@ read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool ) return res, status == 0 } + @(private) -read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool) { +read_reg_i64 :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16) -> (res: i64, ok: bool) { if len(subkey) == 0 || len(val) == 0 { return } - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - - BUF_SIZE :: 1024 - key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) - - utf16.encode_string(key_name_wide, subkey) - utf16.encode_string(val_name_wide, val) - result_size := sys.DWORD(size_of(i64)) status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + subkey, + val, sys.RRF_RT_REG_QWORD, nil, &res, @@ -395,3 +408,20 @@ read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool ) return res, status == 0 } + +@(private) +is_integer :: proc "contextless" (s: string) -> (ok: bool) { + if s == "" { + return + } + + ok = true + + for r in s { + switch r { + case '0'..='9': continue + case: return false + } + } + return +} \ No newline at end of file diff --git a/core/sys/info/sysinfo.odin b/core/sys/info/sysinfo.odin index f624a1718..ad120b264 100644 --- a/core/sys/info/sysinfo.odin +++ b/core/sys/info/sysinfo.odin @@ -1,15 +1,109 @@ package sysinfo -when !(ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64) { - #assert(false, "This package is unsupported on this architecture.") +import "base:runtime" +import "core:strings" +import "core:strconv" + +#assert( + ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || \ + ODIN_ARCH == .arm32 || ODIN_ARCH == .arm64 || \ + ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 || \ + ODIN_ARCH == .riscv64, + "This package is unsupported on this architecture.") + +/* +Retrieves the number of physical and logical CPU cores + +Returns: +- physical: The number of physical cores +- logical: The number of logical cores +- ok: `true` when we could retrieve the CPU information, `false` otherwise +*/ +cpu_core_count :: proc "contextless" () -> (physical: int, logical: int, ok: bool) { + return _cpu_core_count() } -os_version: OS_Version -ram: RAM -gpus: []GPU +/* +Returns CPU features where available -// Only on MacOS, contains the actual MacOS version, while the `os_version` contains the kernel version. -macos_version: Version +The results are looked up before `main` enters and cached + +Returns: +- features: An architecture-specific `bit_set`, empty if we couldn't retrieve them +*/ +cpu_features :: proc "contextless" () -> (features: CPU_Features) { + return _cpu_features() +} + +/* +Returns the CPU's name + +The results are looked up before `main` enters and cached + +Returns: +- name: A `string` containing the CPU model name, empty if the lookup failed +*/ +cpu_name :: proc() -> (name: string) { + return _cpu_name() +} + +/* +Retrieves RAM statistics + +Unavailable stats will be returned as `0` bytes + +Returns: +- total_ram: Total RAM reported by the operating system, in bytes +- free_ram: Free RAM reported by the operating system, in bytes +- total_swap: Total SWAP reported by the operating system, in bytes +- free_swap: Free SWAP reported by the operating system, in bytes +- ok: `true` when we could retrieve RAM statistics, `false` otherwise +*/ +ram_stats :: proc "contextless" () -> (total_ram, free_ram, total_swap, free_swap: i64, ok: bool) { + return _ram_stats() +} + +/* +Retrieves OS version information + +*Allocates Using Provided Allocator* + +You can use `destroy_os_version` to free the results + +Inputs: +- allocator: A `runtime.Allocator` on which the version strings will be allocated +- loc: The caller location + +Returns: +- res: An `OS_Version` struct +- ok: `true` when we could retrieve OS version information, `false` otherwise +*/ +os_version :: proc(allocator: runtime.Allocator, loc := #caller_location) -> (res: OS_Version, ok: bool) { + return _os_version(allocator = allocator, loc = loc) +} + +/* +Releases an `OS_Version`'s strings + +*Frees Using Provided Allocator* + +Inputs: +- version: An `OS_Version` struct +- allocator: A `runtime.Allocator` on which the version strings will be freed +*/ +destroy_os_version :: proc(version: OS_Version, allocator: runtime.Allocator) { + delete(version.full, allocator) + // `version.release` is part of `version.full` and does not need to be freed separately. +} + +OS_Version :: struct { + platform: OS_Version_Platform, // Windows, Linux, MacOS, iOS, etc. + full: string, // e.g. Windows 10 Professional (version: 22H2), build: 19045.6575 + release: string, // e.g. 22H2 + + os: Version, // e.g. {major = 10, minor = 10, patch = 0} + kernel: Version, // e.g. {major = 10, minor = 19045, patch = 6575} +} OS_Version_Platform :: enum { Unknown, @@ -26,25 +120,69 @@ Version :: struct { major, minor, patch: int, } -OS_Version :: struct { - platform: OS_Version_Platform, +/* +Iterates over GPU adapters - using _: Version, - build: [2]int, - version: string, +On Windows: Enumerates `Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}` +Elsewhere: Unsupported at the moment, returns `{}, 0, false` - as_string: string, -} +Important: The `vendor` name, `model` name and `driver` version strings are backed by the `GPU_Iterator`. +Clone them if you want to these to persist. -RAM :: struct { - total_ram: int, - free_ram: int, - total_swap: int, - free_swap: int, +Inputs: +- it: A pointer to a `GPU_Iterator` +- minimum_vram: The number of bytes of VRAM an adapter has to have to be considered, default 256 MiB + (This excludes most screen mirroring / remote desktop drivers) + +Returns: + gpu: A `GPU` struct which contains `vendor` name, `model` name, `driver` version and `vram` in bytes + index: Loop index, optional + ok: `true` if this was a success and we should continue, `false` otherwise +*/ +iterate_gpus :: proc(it: ^GPU_Iterator, minimum_vram := i64(256 * 1024 * 1024)) -> (gpu: GPU, index: int, ok: bool) { + when ODIN_OS == .Windows { + return _iterate_gpus(it, minimum_vram) + } else { + // Not implemented on another OS, yet + return {}, 0, false + } } GPU :: struct { - vendor_name: string, - model_name: string, - total_ram: int, + vendor: string, + model: string, + driver: string, + vram: i64, } + +GPU_Iterator :: struct { + // Public iterator index + index: int, + + // Internal buffer + index + _buffer: [512]u8, + _index: int, +} + +@(private) +_parse_version :: proc (str: string) -> (res: Version) { + str := str + i: int + for part in strings.split_iterator(&str, ".") { + defer i += 1 + dst: ^int + switch i { + case 0: dst = &res.major + case 1: dst = &res.minor + case 2: dst = &res.patch + case: return + } + + if num, num_ok := strconv.parse_int(part); !num_ok { + return + } else { + dst^ = num + } + } + return +} \ No newline at end of file diff --git a/core/sys/kqueue/kqueue.odin b/core/sys/kqueue/kqueue.odin index 56be1cf7a..b51f3426f 100644 --- a/core/sys/kqueue/kqueue.odin +++ b/core/sys/kqueue/kqueue.odin @@ -2,7 +2,7 @@ package kqueue when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -32,6 +32,7 @@ kevent :: proc(kq: KQ, change_list: []KEvent, event_list: []KEvent, timeout: ^po timeout, ) if n_events == -1 { + n_events = 0 err = posix.errno() } return @@ -60,6 +61,7 @@ Filter :: enum _Filter_Backing { Proc = _FILTER_PROC, // Check for changes to the subject process. Signal = _FILTER_SIGNAL, // Check for signals delivered to the process. Timer = _FILTER_TIMER, // Timers. + User = _FILTER_USER, // User events. } RW_Flag :: enum u32 { @@ -82,18 +84,30 @@ Proc_Flag :: enum u32 { Exit = log2(0x80000000), // Process exited. Fork = log2(0x40000000), // Process forked. Exec = log2(0x20000000), // Process exec'd. - Signal = log2(0x08000000), // Shared with `Filter.Signal`. } Proc_Flags :: bit_set[Proc_Flag; u32] Timer_Flag :: enum u32 { Seconds = log2(0x00000001), // Data is seconds. - USeconds = log2(0x00000002), // Data is microseconds. - NSeconds = log2(_NOTE_NSECONDS), // Data is nanoseconds. + USeconds = log2(_NOTE_USECONDS), // Data is microseconds. Absolute = log2(_NOTE_ABSOLUTE), // Absolute timeout. } Timer_Flags :: bit_set[Timer_Flag; u32] +User_Flag :: enum u32 { + Trigger = log2(0x01000000), + FFAnd = log2(0x40000000), + FFOr = log2(0x80000000), +} +User_Flags :: bit_set[User_Flag; u32] + +USER_FLAGS_COPY :: User_Flags{.FFOr, .FFAnd} +USER_FLAGS_CONTROL_MASK :: transmute(User_Flags)u32(0xc0000000) +USER_FLAGS_MASK :: transmute(User_Flags)u32(0x00FFFFFF) + +// Data is nanoseconds. +TIMER_FLAGS_NSECONDS :: _TIMER_FLAGS_NSECONDS + when ODIN_OS == .Darwin { _Filter_Backing :: distinct i16 @@ -106,10 +120,14 @@ when ODIN_OS == .Darwin { _FILTER_PROC :: -5 _FILTER_SIGNAL :: -6 _FILTER_TIMER :: -7 + _FILTER_USER :: -10 + _NOTE_USECONDS :: 0x00000002 _NOTE_NSECONDS :: 0x00000004 _NOTE_ABSOLUTE :: 0x00000008 + _TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))} + KEvent :: struct #align(4) { // Value used to identify this event. The exact interpretation is determined by the attached filter. ident: uintptr, @@ -119,11 +137,12 @@ when ODIN_OS == .Darwin { flags: Flags, // Filter specific flags. fflags: struct #raw_union { - rw: RW_Flags, - vnode: VNode_Flags, - fproc: Proc_Flags, + rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`, + vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`, + fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`, // vm: VM_Flags, - timer: Timer_Flags, + timer: Timer_Flags `raw_union_tag:"filter=.Timer"`, + user: User_Flags `raw_union_tag:"filter=.User"`, }, // Filter specific data. data: c.long /* intptr_t */, @@ -143,9 +162,13 @@ when ODIN_OS == .Darwin { _FILTER_PROC :: -5 _FILTER_SIGNAL :: -6 _FILTER_TIMER :: -7 + _FILTER_USER :: -11 - _NOTE_NSECONDS :: 0x00000004 - _NOTE_ABSOLUTE :: 0x00000008 + _NOTE_USECONDS :: 0x00000004 + _NOTE_NSECONDS :: 0x00000008 + _NOTE_ABSOLUTE :: 0x00000010 + + _TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))} KEvent :: struct { // Value used to identify this event. The exact interpretation is determined by the attached filter. @@ -156,11 +179,12 @@ when ODIN_OS == .Darwin { flags: Flags, // Filter specific flags. fflags: struct #raw_union { - rw: RW_Flags, - vnode: VNode_Flags, - fproc: Proc_Flags, + rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`, + vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`, + fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`, // vm: VM_Flags, - timer: Timer_Flags, + timer: Timer_Flags `raw_union_tag:"filter=.Timer"`, + user: User_Flags `raw_union_tag:"filter=.User"`, }, // Filter specific data. data: i64, @@ -181,11 +205,14 @@ when ODIN_OS == .Darwin { _FILTER_PROC :: 4 _FILTER_SIGNAL :: 5 _FILTER_TIMER :: 6 + _FILTER_USER :: 8 - _NOTE_NSECONDS :: 0x00000003 + _NOTE_USECONDS :: 0x00000002 _NOTE_ABSOLUTE :: 0x00000010 - KEvent :: struct #align(4) { + _TIMER_FLAGS_NSECONDS :: Timer_Flags{.Seconds, .USeconds} + + KEvent :: struct { // Value used to identify this event. The exact interpretation is determined by the attached filter. ident: uintptr, // Filter for event. @@ -194,18 +221,17 @@ when ODIN_OS == .Darwin { flags: Flags, // Filter specific flags. fflags: struct #raw_union { - rw: RW_Flags, - vnode: VNode_Flags, - fproc: Proc_Flags, + rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`, + vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`, + fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`, // vm: VM_Flags, - timer: Timer_Flags, + timer: Timer_Flags `raw_union_tag:"filter=.Timer"`, + user: User_Flags `raw_union_tag:"filter=.User"`, }, // Filter specific data. data: i64, // Opaque user data passed through the kernel unchanged. udata: rawptr, - // Extensions. - ext: [4]u64, } } else when ODIN_OS == .OpenBSD { @@ -219,10 +245,14 @@ when ODIN_OS == .Darwin { _FILTER_PROC :: -5 _FILTER_SIGNAL :: -6 _FILTER_TIMER :: -7 + _FILTER_USER :: -10 - _NOTE_NSECONDS :: 0x00000003 + _NOTE_USECONDS :: 0x00000002 + _NOTE_NSECONDS :: 0x00000004 _NOTE_ABSOLUTE :: 0x00000010 + _TIMER_FLAGS_NSECONDS :: Timer_Flags{Timer_Flag(log2(_NOTE_NSECONDS))} + KEvent :: struct #align(4) { // Value used to identify this event. The exact interpretation is determined by the attached filter. ident: uintptr, @@ -232,11 +262,12 @@ when ODIN_OS == .Darwin { flags: Flags, // Filter specific flags. fflags: struct #raw_union { - rw: RW_Flags, - vnode: VNode_Flags, - fproc: Proc_Flags, + rw: RW_Flags `raw_union_tag:"filter=.Read, filter=.Write"`, + vnode: VNode_Flags `raw_union_tag:"filter=.VNode"`, + fproc: Proc_Flags `raw_union_tag:"filter=.Proc"`, // vm: VM_Flags, - timer: Timer_Flags, + timer: Timer_Flags `raw_union_tag:"filter=.Timer"`, + user: User_Flags `raw_union_tag:"filter=.User"`, }, // Filter specific data. data: i64, @@ -245,12 +276,20 @@ when ODIN_OS == .Darwin { } } +when ODIN_OS == .NetBSD { + @(private) + LKEVENT :: "__kevent50" +} else { + @(private) + LKEVENT :: "kevent" +} + @(private) log2 :: intrinsics.constant_log2 foreign lib { @(link_name="kqueue") _kqueue :: proc() -> KQ --- - @(link_name="kevent") + @(link_name=LKEVENT) _kevent :: proc(kq: KQ, change_list: [^]KEvent, n_changes: c.int, event_list: [^]KEvent, n_events: c.int, timeout: ^posix.timespec) -> c.int --- } diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 53660dc8f..9ce352bf6 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -449,7 +449,7 @@ FLock_Type :: enum i16 { /* Bits for FD_Notifications */ -FD_Notifications_Bits :: enum { +FD_Notifications_Bits :: enum i32 { ACCESS = 0, MODIFY = 1, CREATE = 2, @@ -579,7 +579,7 @@ Inotify_Event_Bits :: enum u32 { /* Bits for Mem_Protection bitfield */ -Mem_Protection_Bits :: enum{ +Mem_Protection_Bits :: enum { READ = 0, WRITE = 1, EXEC = 2, @@ -594,11 +594,13 @@ Mem_Protection_Bits :: enum{ /* Bits for Map_Flags + + See `constants.odin` for `MAP_SHARED_VALIDATE` and `MAP_HUGE_16KB`, et al. */ Map_Flags_Bits :: enum { SHARED = 0, PRIVATE = 1, - SHARED_VALIDATE = 2, + DROPPABLE = 3, FIXED = 4, ANONYMOUS = 5, // platform-dependent section start @@ -1616,36 +1618,39 @@ PER_HPUX :: 0x0010 PER_MASK :: 0x00ff /* - Bits for access modes for shared memory + Bits for SystemV IPC flags. + + In this enum, access modes are common for any shared memory. Prefixed + entries (i.e. `IPC_` or `SHM_`) denote flags, where `IPC_` are common flags + for all SystemV IPC primitives, and `SHM_`, `SEM_` and `MSG_` are specific + to shared memory segments, semaphores and message queues respectively. + + These bits overlap, because they are meant to be used within the + context of specific procedures. Creation flags, used for `*get` procedures, + and usage flags used by all other IPC procedures. Do not mix creation and + usage flags, as well as flags prefixed differently (excluding `IPC_` + prefix). */ -IPC_Mode_Bits :: enum { +IPC_Flags_Bits :: enum { + // Access modes for shared memory. WROTH = 1, RDOTH = 2, WRGRP = 4, RDGRP = 5, WRUSR = 7, RDUSR = 8, - DEST = 9, - LOCKED = 10, -} - -/* - Shared memory flags bits -*/ -IPC_Flags_Bits :: enum { + // Creation flags for shared memory. IPC_CREAT = 9, IPC_EXCL = 10, - IPC_NOWAIT = 11, - // Semaphore - SEM_UNDO = 9, - // Shared memory SHM_HUGETLB = 11, SHM_NORESERVE = 12, + // Usage flags for shared memory. + IPC_NOWAIT = 11, + SEM_UNDO = 9, SHM_RDONLY = 12, SHM_RND = 13, SHM_REMAP = 14, SHM_EXEC = 15, - // Message queue MSG_NOERROR = 12, MSG_EXCEPT = 13, MSG_COPY = 14, @@ -1685,17 +1690,17 @@ IPC_Cmd :: enum i16 { /* File locking operation bits */ -FLock_Op_Bits :: enum { - SH = 1, - EX = 2, - NB = 4, - UN = 8, +FLock_Op_Bits :: enum i32 { + SH = 0, + EX = 1, + NB = 2, + UN = 3, } /* ptrace requests */ -PTrace_Request :: enum { +PTrace_Request :: enum i32 { TRACEME = 0, PEEKTEXT = 1, PEEKDATA = 2, @@ -1742,7 +1747,7 @@ PTrace_Request :: enum { /* ptrace options */ -PTrace_Options_Bits :: enum { +PTrace_Options_Bits :: enum i32 { TRACESYSGOOD = 0, TRACEFORK = 1, TRACEVFORK = 2, @@ -1833,7 +1838,7 @@ Clock_Id :: enum { Bits for POSIX interval timer flags. */ ITimer_Flags_Bits :: enum { - ABSTIME = 1, + ABSTIME = 0, } /* @@ -1959,3 +1964,345 @@ RISCV_HWProbe_Misaligned_Scalar_Perf :: enum { UNSUPPORTED, } +IO_Uring_Enter_Flags_Bits :: enum { + GETEVENTS, + SQ_WAKEUP, + SQ_WAIT, + EXT_ARG, // Available since Linux 5.11 + REGISTERED_RING, +} + +IO_Uring_Register_Opcode :: enum uint { + REGISTER_BUFFERS = 0, + UNREGISTER_BUFFERS = 1, + REGISTER_FILES = 2, + UNREGISTER_FILES = 3, + REGISTER_EVENTFD = 4, + UNREGISTER_EVENTFD = 5, + REGISTER_FILES_UPDATE = 6, + REGISTER_EVENTFD_ASYNC = 7, + REGISTER_PROBE = 8, + REGISTER_PERSONALITY = 9, + UNREGISTER_PERSONALITY = 10, + REGISTER_RESTRICTIONS = 11, + REGISTER_ENABLE_RINGS = 12, + /* extended with tagging */ + REGISTER_FILES2 = 13, + REGISTER_FILES_UPDATE2 = 14, + REGISTER_BUFFERS2 = 15, + REGISTER_BUFFERS_UPDATE = 16, + /* set/clear io-wq thread affinities */ + REGISTER_IOWQ_AFF = 17, + UNREGISTER_IOWQ_AFF = 18, + /* set/get max number of io-wq workers */ + REGISTER_IOWQ_MAX_WORKERS = 19, + /* register/unregister io_uring fd with the ring */ + REGISTER_RING_FDS = 20, + UNREGISTER_RING_FDS = 21, + /* register ring based provide buffer group */ + REGISTER_PBUF_RING = 22, + UNREGISTER_PBUF_RING = 23, + /* sync cancelation API */ + REGISTER_SYNC_CANCEL = 24, + /* register a range of fixed file slots for automatic slot allocation */ + REGISTER_FILE_ALLOC_RANGE = 25, + /* this goes last */ + REGISTER_LAST, + /* flag added to the opcode to use a registered ring fd */ + REGISTER_USE_REGISTERED_RING = 1 << 31, +} + +IO_Uring_Setup_Flags_Bits :: enum { + // io_context is polled. + IOPOLL, + // SQ poll thread. + SQPOLL, + // sq_thread_cpu is valid. + SQ_AFF, + // app defines CQ size. + CQSIZE, + // clamp SQ/CQ ring sizes. + CLAMP, + // attach to existing wq. + ATTACH_WQ, + // start with ring disabled. + R_DISABLED, + // continue submit on error. + SUBMIT_ALL, + // Cooperative task running. When requests complete, they often require + // forcing the submitter to transition to the kernel to complete. If this + // flag is set, work will be done when the task transitions anyway, rather + // than force an inter-processor interrupt reschedule. This avoids interrupting + // a task running in userspace, and saves an IPI. + COOP_TASKRUN, + // If COOP_TASKRUN is set, get notified if task work is available for + // running and a kernel transition would be needed to run it. This sets + // IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN. + TASKRUN_FLAG, + // SQEs are 128 bytes. + SQE128, + // CQEs are 32 bytes. + CQE32, + // Only one task is allowed to submit requests + SINGLE_ISSUER, + // Defer running task work to get events. + // Rather than running bits of task work whenever the task transitions + // try to do it just before it is needed. + DEFER_TASKRUN, +} + +IO_Uring_Features_Bits :: enum { + SINGLE_MMAP, + NODROP, + SUBMIT_STABLE, + RW_CUR_POS, + CUR_PERSONALITY, + FAST_POLL, + POLL_32BITS, + SQPOLL_NONFIXED, + EXT_ARG, + NATIVE_WORKERS, + RSRC_TAGS, +} + +IO_Uring_CQE_Flags_Bits :: enum { + // If set, the upper 16 bits are the buffer ID. + BUFFER, + // If set, parent SQE will generate more CQE entries. + MORE, + // If set, more data to read after socket recv. + SOCK_NONEMPTY, + // Set for notification CQEs. Can be used to distinct them from sends. + NOTIF, +} + +IO_Uring_OP :: enum u8 { + NOP, + READV, + WRITEV, + FSYNC, + READ_FIXED, + WRITE_FIXED, + POLL_ADD, + POLL_REMOVE, + SYNC_FILE_RANGE, + SENDMSG, + RECVMSG, + TIMEOUT, + TIMEOUT_REMOVE, + ACCEPT, + ASYNC_CANCEL, + LINK_TIMEOUT, + CONNECT, + FALLOCATE, + OPENAT, + CLOSE, + FILES_UPDATE, + STATX, + READ, + WRITE, + FADVISE, + MADVISE, + SEND, + RECV, + OPENAT2, + EPOLL_CTL, + SPLICE, + PROVIDE_BUFFERS, + REMOVE_BUFFERS, + TEE, + SHUTDOWN, + RENAMEAT, + UNLINKAT, + MKDIRAT, + SYMLINKAT, + LINKAT, + MSG_RING, + FSETXATTR, + SETXATTR, + FGETXATTR, + GETXATTR, + SOCKET, + URING_CMD, + SEND_ZC, + SENDMSG_ZC, + READ_MULTISHOT, + WAITID, + FUTEX_WAIT, + FUTEX_WAKE, + FUTEX_WAITV, + FIXED_FD_INSTALL, + FTRUNCATE, + BIND, + LISTEN, +} + +IO_Uring_SQE_Flags_Bits :: enum { + // Use fixed fileset. + FIXED_FILE, + // Issue after inflight IO. + IO_DRAIN, + // Links next sqe. + IO_LINK, + // Like LINK, but stronger. + IO_HARDLINK, + // Always go async. + ASYNC, + // Select buffer from sq.buf_group. + BUFFER_SELECT, + // Don't post CQE if request succeeded. + CQE_SKIP_SUCCESS, +} + +IO_Uring_Poll_Add_Flags_Bits :: enum { + ADD_MULTI, + UPDATE_EVENTS, + UPDATE_USER_DATA, + ADD_LEVEL, +} + +IO_Uring_Fsync_Flags_Bits :: enum { + DATASYNC, +} + +IO_Uring_Timeout_Flags_Bits :: enum { + ABS, + UPDATE, + BOOTTIME, + REALTIME, + LINK_TIMEOUT_UPDATE, + ETIME_SUCCESS, +} + +IO_Uring_Cmd_Flags_Bits :: enum { + // use registered buffer; pass this flag along with setting sqe.buf_index. + FIXED, +} + +IO_Uring_Splice_Flags_Bits :: enum { + MOVE, + NONBLOCK, + MORE, + GIFT, + F_FD_IN_FIXED = 31, +} + +IO_Uring_Accept_Flags_Bits :: enum { + MULTISHOT, +} + +IO_Uring_Send_Recv_Flags_Bits :: enum { + /* + If set, instead of first attempting to send + or receive and arm poll if that yields an + -EAGAIN result, arm poll upfront and skip + the initial transfer attempt. + */ + RECVSEND_POLL_FIRST, + /* + Multishot recv. Sets IORING_CQE_F_MORE if + the handler will continue to report + CQEs on behalf of the same SQE. + */ + RECV_MULTISHOT, + /* + Use registered buffers, the index is stored in + the buf_index field. + */ + RECVSEND_FIXED_BUF, + /* + If set, SEND[MSG]_ZC should report + the zerocopy usage in cqe.res + for the IORING_CQE_F_NOTIF cqe. + 0 is reported if zerocopy was actually possible. + IORING_NOTIF_USAGE_ZC_COPIED if data was copied + (at least partially). + */ + SEND_ZC_REPORT_USAGE, +} + +IO_Uring_Submission_Queue_Flags_Bits :: enum { + NEED_WAKEUP, + CQ_OVERFLOW, + TASKRUN, +} + +Mount_Flags_Bits :: enum { + RDONLY = log2(1), + NOSUID = log2(2), + NODEV = log2(4), + NOEXEC = log2(8), + SYNCHRONOUS = log2(16), + REMOUNT = log2(32), + MANDLOCK = log2(64), + DIRSYNC = log2(128), + NOATIME = log2(1024), + NODIRATIME = log2(2048), + BIND = log2(4096), + MOVE = log2(8192), + REC = log2(16384), + SILENT = log2(32768), + POSIXACL = log2(1<<16), + UNBINDABLE = log2(1<<17), + PRIVATE = log2(1<<18), + SLAVE = log2(1<<19), + SHARED = log2(1<<20), + RELATIME = log2(1<<21), + KERNMOUNT = log2(1<<22), + I_VERSION = log2(1<<23), + STRICTATIME = log2(1<<24), + LAZYTIME = log2(1<<25), + ACTIVE = log2(1<<30), + NOUSER = log2(1<<31), + NOSYMFOLLOW = log2(256), +} + +Umount2_Flags_Bits :: enum { + MNT_FORCE = log2(0x00000001), + MNT_DETACH = log2(0x00000002), + MNT_EXPIRE = log2(0x00000004), + UMOUNT_NOFOLLOW = log2(0x00000008), + UMOUNT_UNUSED = log2(0x80000000), +} + +Swap_Flags_Bits :: enum { + PREFER = log2(0x8000), + DISCARD = log2(0x10000), +} + +Eventfd_Flags_Bits :: enum { + SEMAPHORE, + CLOEXEC = auto_cast Open_Flags_Bits.CLOEXEC, + NONBLOCK = auto_cast Open_Flags_Bits.NONBLOCK, +} + +Sched_Policy :: enum u32 { + OTHER = 0, + BATCH = 3, + IDLE = 5, + FIFO = 1, + RR = 2, + DEADLINE = 6, +} + +Sched_Flag_Bits :: enum { + RESET_ON_FORK = log2(0x01), + RECLAIM = log2(0x02), + DL_OVERRUN = log2(0x04), + KEEP_POLICY = log2(0x08), + KEEP_PARAMS = log2(0x10), + UTIL_CLAMP_MIN = log2(0x20), + UTIL_CLAMP_MAX = log2(0x40), +} + +Sched_Attr_Flag_Bits :: enum {} + +/* + See `constants.odin` for `MFD_HUGE_16KB`, et al. +*/ +Memfd_Create_Flag_Bits :: enum { + CLOEXEC = log2(0x1), + ALLOW_SEALING = log2(0x2), + HUGETLB = log2(0x4), +} + diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index b3bbcafb3..4de57f40b 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -54,6 +54,8 @@ PRIO_MIN :: -20 SIGRTMIN :: Signal(32) SIGRTMAX :: Signal(64) +_NSIG :: 65 + S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFIFO} S_IFSOCK :: Mode{.IFREG, .IFDIR} S_IFLNK :: Mode{.IFREG, .IFCHR} @@ -373,3 +375,52 @@ PTRACE_SECCOMP_GET_FILTER :: PTrace_Seccomp_Get_Filter_Type(.SECCOMP_GET_FIL PTRACE_SECCOMP_GET_METADATA :: PTrace_Seccomp_Get_Metadata_Type(.SECCOMP_GET_METADATA) PTRACE_GET_SYSCALL_INFO :: PTrace_Get_Syscall_Info_Type(.GET_SYSCALL_INFO) PTRACE_GET_RSEQ_CONFIGURATION :: PTrace_Get_RSeq_Configuration_Type(.GET_RSEQ_CONFIGURATION) + +MAP_SHARED_VALIDATE :: Map_Flags{.SHARED, .PRIVATE} + +MAP_HUGE_SHIFT :: 26 +MAP_HUGE_MASK :: 63 + +MAP_HUGE_16KB :: transmute(Map_Flags)(u32(14) << MAP_HUGE_SHIFT) +MAP_HUGE_64KB :: transmute(Map_Flags)(u32(16) << MAP_HUGE_SHIFT) +MAP_HUGE_512KB :: transmute(Map_Flags)(u32(19) << MAP_HUGE_SHIFT) +MAP_HUGE_1MB :: transmute(Map_Flags)(u32(20) << MAP_HUGE_SHIFT) +MAP_HUGE_2MB :: transmute(Map_Flags)(u32(21) << MAP_HUGE_SHIFT) +MAP_HUGE_8MB :: transmute(Map_Flags)(u32(23) << MAP_HUGE_SHIFT) +MAP_HUGE_16MB :: transmute(Map_Flags)(u32(24) << MAP_HUGE_SHIFT) +MAP_HUGE_32MB :: transmute(Map_Flags)(u32(25) << MAP_HUGE_SHIFT) +MAP_HUGE_256MB :: transmute(Map_Flags)(u32(28) << MAP_HUGE_SHIFT) +MAP_HUGE_512MB :: transmute(Map_Flags)(u32(29) << MAP_HUGE_SHIFT) +MAP_HUGE_1GB :: transmute(Map_Flags)(u32(30) << MAP_HUGE_SHIFT) +MAP_HUGE_2GB :: transmute(Map_Flags)(u32(31) << MAP_HUGE_SHIFT) +MAP_HUGE_16GB :: transmute(Map_Flags)(u32(34) << MAP_HUGE_SHIFT) + +MFD_HUGE_16KB :: transmute(Memfd_Create_Flags)(u32(14) << MAP_HUGE_SHIFT) +MFD_HUGE_64KB :: transmute(Memfd_Create_Flags)(u32(16) << MAP_HUGE_SHIFT) +MFD_HUGE_512KB :: transmute(Memfd_Create_Flags)(u32(19) << MAP_HUGE_SHIFT) +MFD_HUGE_1MB :: transmute(Memfd_Create_Flags)(u32(20) << MAP_HUGE_SHIFT) +MFD_HUGE_2MB :: transmute(Memfd_Create_Flags)(u32(21) << MAP_HUGE_SHIFT) +MFD_HUGE_8MB :: transmute(Memfd_Create_Flags)(u32(23) << MAP_HUGE_SHIFT) +MFD_HUGE_16MB :: transmute(Memfd_Create_Flags)(u32(24) << MAP_HUGE_SHIFT) +MFD_HUGE_32MB :: transmute(Memfd_Create_Flags)(u32(25) << MAP_HUGE_SHIFT) +MFD_HUGE_256MB :: transmute(Memfd_Create_Flags)(u32(28) << MAP_HUGE_SHIFT) +MFD_HUGE_512MB :: transmute(Memfd_Create_Flags)(u32(29) << MAP_HUGE_SHIFT) +MFD_HUGE_1GB :: transmute(Memfd_Create_Flags)(u32(30) << MAP_HUGE_SHIFT) +MFD_HUGE_2GB :: transmute(Memfd_Create_Flags)(u32(31) << MAP_HUGE_SHIFT) +MFD_HUGE_16GB :: transmute(Memfd_Create_Flags)(u32(34) << MAP_HUGE_SHIFT) + +/* Get window size */ +TIOCGWINSZ :: 0x5413 + +IORING_TIMEOUT_CLOCK_MASK :: IO_Uring_Timeout_Flags{.BOOTTIME, .REALTIME} +IORING_TIMEOUT_UPDATE_MASK :: IO_Uring_Timeout_Flags{.UPDATE, .LINK_TIMEOUT_UPDATE} + +IORING_OFF_SQ_RING :: 0 +IORING_OFF_CQ_RING :: 0x8000000 +IORING_OFF_SQES :: 0x10000000 +IORING_OFF_PBUF_RING :: 0x80000000 +IORING_OFF_PBUF_SHIFT :: 16 +IORING_OFF_MMAP_MASK :: 0xf8000000 + +SWAP_FLAG_PRIO_SHIFT :: u32(0) +SWAP_FLAG_PRIO_MASK :: u32(0x7fff) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 985623e85..0b5c252b9 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -213,7 +213,7 @@ rt_sigreturn :: proc "c" () -> ! { /* Alter an action taken by a process. */ -rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action($U)) -> Errno { +rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno { // NOTE(jason): It appears that the restorer is required for i386 and amd64 when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 { sigaction.flags += {.RESTORER} @@ -419,7 +419,15 @@ dup :: proc "contextless" (fd: Fd) -> (Fd, Errno) { dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) { when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 { ret := syscall(SYS_dup3, old, new, 0) - return errno_unwrap(ret, Fd) + + // Differences between dup2 and dup3 are: + // - dup3 takes a flags argument + // - dup2 does not return EINVAL + fd, errno := errno_unwrap(ret, Fd) + if errno == .EINVAL { + errno = .NONE + } + return fd, errno } else { ret := syscall(SYS_dup2, old, new) return errno_unwrap(ret, Fd) @@ -510,7 +518,7 @@ sendfile :: proc "contextless" (out_fd: Fd, in_fd: Fd, offset: ^i64, count: uint Available since Linux 2.0. */ socket :: proc "contextless" (domain: Address_Family, socktype: Socket_Type, sockflags: Socket_FD_Flags, protocol: Protocol) -> (Fd, Errno) { - sock_type_flags: int = cast(int) socktype | transmute(int) sockflags + sock_type_flags: int = cast(int) socktype | cast(int) transmute(i32) sockflags ret := syscall(SYS_socket, domain, sock_type_flags, protocol) return errno_unwrap(ret, Fd) } @@ -543,7 +551,7 @@ where T == Sock_Addr_Any { addr_len: i32 = size_of(T) - ret := syscall(SYS_accept4, sock, addr, &addr_len, transmute(int) sockflags) + ret := syscall(SYS_accept4, sock, addr, &addr_len, transmute(i32) sockflags) return errno_unwrap(ret, Fd) } @@ -1413,7 +1421,7 @@ umask :: proc "contextless" (mask: Mode) -> Mode { Available since Linux 1.0. */ gettimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) { - ret := syscall(SYS_gettimeofday, tv) + ret := syscall(SYS_gettimeofday, tv, rawptr(nil)) return Errno(-ret) } @@ -2043,22 +2051,71 @@ setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) - return Errno(-ret) } -// TODO(flysand): sched_setparam - -// TODO(flysand): sched_getparam - -// TODO(flysand): sched_setscheduler - -// TODO(flysand): sched_getscheduler - -// TODO(flysand): sched_get_priority_max - -// TODO(flysand): sched_get_priority_min - -// TODO(flysand): sched_rr_get_interval +/* + Set scheduling parameters. + Available since Linux 2.0. +*/ +sched_setparam :: proc "contextless" (pid: Pid, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_setparam, pid, param) + return Errno(-ret) +} /* - Lock and memory. + Get scheduling parameters. + Available since Linux 2.0. +*/ +sched_getparam :: proc "contextless" (pid: Pid, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_getparam, pid, param) + return Errno(-ret) +} + +/* + Set scheduling policy/parameters. + Available since Linux 2.0. +*/ +sched_setscheduler :: proc "contextless" (pid: Pid, policy: i32, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_setscheduler, pid, policy, param) + return Errno(-ret) +} + +/* + Get scheduling policy/parameters. + Available since Linux 2.0. +*/ +sched_getscheduler :: proc "contextless" (pid: Pid, policy: i32, param: ^Sched_Param) -> (i32, Errno) { + ret := syscall(SYS_sched_getscheduler, pid) + return errno_unwrap(ret, i32) +} + +/* + Get static priority range. + Available since Linux 2.0. +*/ +sched_get_priority_max :: proc "contextless" (policy: i32) -> (i32, Errno) { + ret := syscall(SYS_sched_get_priority_max, policy) + return errno_unwrap(ret, i32) +} + +/* + Get static priority range. + Available since Linux 2.0. +*/ +sched_get_priority_min :: proc "contextless" (policy: i32) -> (i32, Errno) { + ret := syscall(SYS_sched_get_priority_min, policy) + return errno_unwrap(ret, i32) +} + +/* + get the SCHED_RR interval for the named process. + Available since Linux 2.0. +*/ +sched_rr_get_interval :: proc "contextless" (pid: Pid, tp: ^Time_Spec) -> (Errno) { + ret := syscall(SYS_sched_rr_get_interval, pid, tp) + return Errno(-ret) +} + +/* + Lock memory. Available since Linux 2.0. If flags specified, available since Linux 4.4. */ @@ -2100,19 +2157,67 @@ munlockall :: proc "contextless" () -> (Errno) { return Errno(-ret) } -// TODO(flysand): vhangup +/* + Virtually hangup the current terminal + Available since Linux 1.0. +*/ +vhangup :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_vhangup) + return Errno(-ret) +} -// TODO(flysand): modify_ldt +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Get or set local descriptor table + Available since Linux 2.1 + */ + modify_ldt :: proc "contextless" (func: i32, ptr: rawptr, bytecount: uint) -> (int, Errno) { + ret := syscall(SYS_modify_ldt, func, ptr, bytecount) + return errno_unwrap(ret, int) + } +} -// TODO(flysand): pivot_root +/* + Change the root mount + Available since Linux 2.3.41 +*/ +pivot_root :: proc "contextless" (new_root: cstring, old_root: cstring) -> (Errno) { + ret := syscall(SYS_pivot_root, cast(rawptr) new_root, cast(rawptr) old_root) + return Errno(-ret) +} // TODO(flysand): _sysctl +// Deprecated and discouraged -// TODO(flysand): prctl +/* + Operations on a process or thread + Available since Linux 2.1.57 +*/ +prctl :: proc "contextless" (op: i32, args: ..uint) -> (Errno) { + assert_contextless(len(args) <= 4) + ret := syscall(SYS_prctl, op, args[0], args[1], args[2], args[3]) + return Errno(-ret) +} -// TODO(flysand): arch_prctl +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Set architecture-specific thread state + Available since Linux 2.6.19 + */ + arch_prctl :: proc "contextless" (op: i32, addr: uint) -> (Errno) { + ret := syscall(SYS_arch_prctl, op, addr) + return Errno(-ret) + } +} -// TODO(flysand): adj_timex +/* + Display or set the kernel time variables + Available since Linux 1.0. +*/ +adjtimex :: proc "contextless" (buf: ^Timex) -> (Clock_State, Errno) { + ret := syscall(SYS_adjtimex, buf) + return errno_unwrap(ret, Clock_State) +} /* Set limits on resources. @@ -2123,21 +2228,86 @@ setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno return Errno(-ret) } -// TODO(flysand): sync +/* + Change root directory + Available since Linux 1.0. +*/ +chroot :: proc "contextless" (pathname: cstring) -> (Errno) { + ret := syscall(SYS_chroot, cast(rawptr) pathname) + return Errno(-ret) +} -// TODO(flysand): acct +/* + Commit filesystem caches to disk + Available since Linux 1.0. +*/ +sync :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_sync) + return Errno(-ret) +} -// TODO(flysand): settimeofday +/* + Switch process accounting on or off + Available since Linux 2.3.23 +*/ +acct :: proc "contextless" (filename: cstring) -> (Errno) { + ret := syscall(SYS_acct, cast(rawptr) filename) + return Errno(-ret) +} -// TODO(flysand): mount +/* + Set Time + Available since Linux 1.0 +*/ +settimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) { + ret := syscall(SYS_settimeofday, tv, rawptr(nil)) + return Errno(-ret) +} -// TODO(flysand): umount2 +/* + Mount filesystem + Available since Linux 1.0 +*/ +mount :: proc "contextless" (source: cstring, target: cstring, filesystemtype: cstring, mountflags: Mount_Flags, data: rawptr) -> (Errno) { + ret := syscall(SYS_mount, cast(rawptr) source, cast(rawptr) target, cast(rawptr) filesystemtype, transmute(uint) mountflags, data) + return Errno(-ret) +} -// TODO(flysand): swapon +/* + Unmount filesystem + Available since Linux 2.1 +*/ +umount2 :: proc "contextless" (target: cstring, flags: Umount2_Flags) -> (Errno) { + ret := syscall(SYS_umount2, cast(rawptr) target, transmute(u32) flags) + return Errno(-ret) +} -// TODO(flysand): swapoff +/* + Start swapping to file/device + Available since Linux 2.0 +*/ +swapon :: proc "contextless" (path: cstring, swapflags: Swap_Flags) -> (Errno) { + ret := syscall(SYS_swapon, cast(rawptr) path, transmute(u32) swapflags) + return Errno(-ret) +} -// TODO(flysand): reboot +/* + Stop swapping to file/device + Available since Linux 2.0 +*/ +swapoff :: proc "contextless" (path: cstring) -> (Errno) { + ret := syscall(SYS_swapoff, cast(rawptr) path) + return Errno(-ret) +} + +/* + Reboot or enable/disable Ctrl-Alt-Del + Available since Linux 1.0 +*/ +reboot :: proc "contextless" (magic: Reboot_Magic, magic2: Reboot_Magic, op: Reboot_Operation, arg: rawptr) -> (Errno) { + ret := syscall(SYS_reboot, cast(i32)magic, cast(i32)magic2, cast(i32)op, arg) + return Errno(-ret) +} /* Set hostname. @@ -2160,16 +2330,48 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) { } // TODO(flysand): iopl +// deprecated -// TODO(flysand): ioperm +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Set port input/output permissions + Available since Linux 1.0 + */ + ioperm :: proc "contextless" (form: u32, num: u32, turn_on: i32) -> (Errno) { + ret := syscall(SYS_ioperm, form, num, turn_on) + return Errno(-ret) + } +} -// TODO(flysand): init_module +/* + Load a kernel module + Available since Linux 2.2 +*/ +init_module :: proc "contextless" (module_image: rawptr, size: u32, param_values: cstring) -> (Errno) { + ret := syscall(SYS_init_module, module_image, size, cast(rawptr) param_values) + return Errno(-ret) +} -// TODO(flysand): delete_module +/* + Unload a kernel module + Available since Linux 2.2 +*/ +delete_module :: proc "contextless" (name: cstring, flags: u32) -> (Errno) { + ret := syscall(SYS_delete_module, cast(rawptr) name, flags) + return Errno(-ret) +} -// TODO(flysand): quotactl +/* + Manipulate disk quotas + Available since Linux 2.0 +*/ +quotactl :: proc "contextless" (op: i32, special: cstring, id: i32, addr: rawptr) -> (Errno) { + ret := syscall(SYS_quotactl, op, cast(rawptr) special, id, addr) + return Errno(-ret) +} // TODO(flysand): nfsservctl +/// No longer present after 3.1 // TODO(flysand): getpmsg @@ -2193,31 +2395,122 @@ gettid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_gettid) } -// TODO(flysand): readahead +/* + Initiate a file readahead into page cache + Available since Linux 2.1 +*/ +readahead :: proc "contextless" (fd: Fd, offset: int, count: uint) -> (Errno) { + ret := syscall(SYS_readahead, fd, offset, count) + return Errno(-ret) +} -// TODO(flysand): setxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +setxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_setxattr, cast(rawptr) path, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): lsetxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +lsetxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_lsetxattr, cast(rawptr) path, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): fsetxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +fsetxattr :: proc "contextless" (fd: Fd, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_fsetxattr, fd, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): getxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +getxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_getxattr, cast(rawptr) path, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): lgetxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +lgetxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_lgetxattr, cast(rawptr) path, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): fgetxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +fgetxattr :: proc "contextless" (fd: Fd, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_fgetxattr, fd, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): listxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +listxattr :: proc "contextless" (path: cstring, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_listxattr, cast(rawptr) path, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): llistxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +llistxattr :: proc "contextless" (path: cstring, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_llistxattr, cast(rawptr) path, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): flistxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +flistxattr :: proc "contextless" (fd: Fd, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_flistxattr, fd, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): removexattr +/* + Remove an extended attribute + Available since Linux 2.6.25 +*/ +removexattr :: proc "contextless" (path: cstring, name: cstring) -> (Errno) { + ret := syscall(SYS_removexattr, cast(rawptr) path, cast(rawptr) name) + return Errno(-ret) +} -// TODO(flysand): lremovexattr +/* + Remove an extended attribute + Available since Linux 2.6 +*/ +lremovexattr :: proc "contextless" (path: cstring, name: cstring) -> (Errno) { + ret := syscall(SYS_lremovexattr, cast(rawptr) path, cast(rawptr) name) + return Errno(-ret) +} -// TODO(flysand): fremovexattr +/* + Remove an extended attribute + Available since Linux 2.6.25 +*/ +fremovexattr :: proc "contextless" (fd: Fd, name: cstring) -> (Errno) { + ret := syscall(SYS_fremovexattr, fd, cast(rawptr) name) + return Errno(-ret) +} /* Get current time in seconds. @@ -2324,9 +2617,29 @@ futex :: proc{ futex_wake_bitset, } -// TODO(flysand): sched_setaffinity +/* + Set a thread's CPU affinity mask. + Available since Linux 2.6. + + If you are running on a system with less than 128 cores you can use `linux.Cpu_Set` as the type for the mask argument. + Otherwise use an array of integers. +*/ +sched_setaffinity :: proc "contextless" (pid: Pid, cpusetsize: uint, mask: rawptr) -> (int, Errno) { + ret := syscall(SYS_sched_setaffinity, pid, cpusetsize, mask) + return errno_unwrap(ret, int) +} -// TODO(flysand): sched_getaffinity +/* + Get a thread's CPU affinity mask. + Available since Linux 2.6. + + If you are running on a system with less than 128 cores you can use `linux.Cpu_Set` as the type for the mask argument. + Otherwise use an array of integers. +*/ +sched_getaffinity :: proc "contextless" (pid: Pid, cpusetsize: uint, mask: rawptr) -> (int, Errno) { + ret := syscall(SYS_sched_getaffinity, pid, cpusetsize, mask) + return errno_unwrap(ret, int) +} // TODO(flysand): set_thread_area @@ -2756,15 +3069,39 @@ epoll_pwait :: proc(epfd: Fd, events: [^]EPoll_Event, count: i32, timeout: i32, // TODO(flysand): signalfd -// TODO(flysand): timerfd_create +/* + Create Linux file descriptor based timer. + Available since Linux 2.6.25 +*/ +timerfd_create :: proc "contextless" (clock_id: Clock_Id, flags: Open_Flags) -> (Fd, Errno) { + ret := syscall(SYS_timerfd_create, clock_id, transmute(u32)flags) + return errno_unwrap2(ret, Fd) +} -// TODO(flysand): eventfd +eventfd :: proc "contextless" (initval: u32, flags: Eventfd_Flags) -> (Fd, Errno) { + ret := syscall(SYS_eventfd2, initval, transmute(i32)flags) + return errno_unwrap2(ret, Fd) +} // TODO(flysand): fallocate -// TODO(flysand): timerfd_settime +/* + Arm/disarm the state of the Linux file descriptor based timer. + Available since Linux 2.6.25 +*/ +timerfd_settime :: proc "contextless" (fd: Fd, flags: ITimer_Flags, new_value: ^ITimer_Spec, old_value: ^ITimer_Spec) -> Errno { + ret := syscall(SYS_timerfd_settime, fd, transmute(u32)flags, new_value, old_value) + return Errno(-ret) +} -// TODO(flysand): timerfd_gettime +/* + Get the state of the Linux file descriptor based timer. + Available since Linux 2.6.25 +*/ +timerfd_gettime :: proc "contextless" (fd: Fd, curr_value: ^ITimer_Spec) -> Errno { + ret := syscall(SYS_timerfd_gettime, fd, curr_value) + return Errno(-ret) +} // TODO(flysand): accept4 @@ -2843,7 +3180,14 @@ sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg // TODO(flysand): setns -// TODO(flysand): getcpu +/* + Determine CPU and NUMA node on which the calling thread is running. + Available since Linux 2.6.19. +*/ +getcpu :: proc "contextless" (cpu, node: ^u32) -> (Errno) { + ret := syscall(SYS_getcpu, cpu, node) + return Errno(-ret) +} // TODO(flysand): process_vm_readv @@ -2853,9 +3197,23 @@ sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg // TODO(flysand): finit_module -// TODO(flysand): sched_setattr +/* + Set scheduling policy and attributes. + Available since Linux 3.14. +*/ +sched_setattr :: proc "contextless" (pid: Pid, attr: ^Sched_Attr, flags: Sched_Attr_Flags) -> (Errno) { + ret := syscall(SYS_sched_setattr, pid, attr, transmute(u32)flags) + return Errno(-ret) +} -// TODO(flysand): sched_getattr +/* + Get scheduling policy and attributes. + Available since Linux 3.14. +*/ +sched_getattr :: proc "contextless" (pid: Pid, attr: ^Sched_Attr, size: u32, flags: Sched_Attr_Flags) -> (Errno) { + ret := syscall(SYS_sched_getattr, pid, attr, transmute(u32)flags) + return Errno(-ret) +} /* Rename the file with names relative to the specified dirfd's with other options. @@ -2873,7 +3231,14 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er return errno_unwrap(ret, int) } -// TODO(flysand): memfd_create +/* + Create an anonymous file. + Available since Linux 3.17. +*/ +memfd_create :: proc "contextless" (name: cstring, flags: Memfd_Create_Flags) -> (Fd, Errno) { + ret := syscall(SYS_memfd_create, cast(rawptr)name, transmute(u32)flags) + return errno_unwrap(ret, Fd) +} // TODO(flysand): kexec_file_load @@ -2927,11 +3292,46 @@ statx :: proc "contextless" (dir: Fd, pathname: cstring, flags: FD_Flags, mask: // TODO(flysand): pidfd_send_signal -// TODO(flysand): io_uring_setup +/* + Setup a context for performing asynchronous I/O. -// TODO(flysand): io_uring_enter + Available since Linux 5.1 +*/ +io_uring_setup :: proc "contextless" (entries: u32, params: ^IO_Uring_Params) -> (Fd, Errno) { + ret := syscall(SYS_io_uring_setup, entries, params) + return errno_unwrap(ret, Fd) +} -// TODO(flysand): io_uring_register +/* + Initiate and/or complete I/O using the shared submission and completion queues. + + Available since Linux 5.1 +*/ +io_uring_enter :: proc "contextless" (fd: Fd, to_submit: u32, min_complete: u32, flags: IO_Uring_Enter_Flags, sig: ^Sig_Set) -> (int, Errno) { + ret := syscall(SYS_io_uring_enter, fd, to_submit, min_complete, transmute(u32)flags, sig, size_of(Sig_Set) if sig != nil else 0) + return errno_unwrap(ret, int) +} + +/* + Initiate and.or complete I/O using the shared submission and completion queues. + + Available since Linux 5.11 +*/ +io_uring_enter2 :: proc "contextless" (fd: Fd, to_submit: u32, min_complete: u32, flags: IO_Uring_Enter_Flags, arg: ^IO_Uring_Getevents_Arg) -> (int, Errno) { + assert_contextless(.EXT_ARG in flags) + ret := syscall(SYS_io_uring_enter, fd, to_submit, min_complete, transmute(u32)flags, arg, size_of(IO_Uring_Getevents_Arg)) + return errno_unwrap(ret, int) +} + +/* + Register files or user buffers for asynchronous I/O. + + Available since Linux 5.1 +*/ +io_uring_register :: proc "contextless" (fd: Fd, opcode: IO_Uring_Register_Opcode, arg: rawptr, nr_args: u32) -> Errno { + ret := syscall(SYS_io_uring_register, fd, opcode, arg, nr_args) + return Errno(-ret) +} // TODO(flysand): open_tree diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 8f2284f56..d3b2c883b 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -288,7 +288,7 @@ Rename_Flags :: bit_set[Rename_Flags_Bits; u32] /* Directory entry record. - Recommended iterate these with `dirent_iterator()`, + Recommended to iterate these with `dirent_iterate_buf()`, and obtain the name via `dirent_name()`. */ Dirent :: struct { @@ -368,6 +368,8 @@ Mem_Protection :: bit_set[Mem_Protection_Bits; i32] /* Flags for mmap. + + See `constants.odin` for `MAP_SHARED_VALIDATE` and `MAP_HUGE_16KB`, et al. */ Map_Flags :: bit_set[Map_Flags_Bits; i32] @@ -745,10 +747,10 @@ Sig_Action_Special :: enum uint { } Sig_Action_Flags :: bit_set[Sig_Action_Flag; uint] -Sig_Action :: struct($T: typeid) { +Sig_Action :: struct { using _u: struct #raw_union { handler: Sig_Handler_Fn, - sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T), + sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: rawptr), special: Sig_Action_Special, }, flags: Sig_Action_Flags, @@ -761,7 +763,7 @@ Sig_Action :: struct($T: typeid) { Note, on linux these are technically passed by OR'ing together with Socket_Type, our wrapper does this under the hood. */ -Socket_FD_Flags :: bit_set[Socket_FD_Flags_Bits; int] +Socket_FD_Flags :: bit_set[Socket_FD_Flags_Bits; i32] /* Address family for the socket. @@ -930,22 +932,17 @@ RUsage :: struct { Struct used for IO operations */ IO_Vec :: struct { - base: rawptr, + base: [^]byte, len: uint, } /* - Access mode for shared memory -*/ -IPC_Mode :: bit_set[IPC_Mode_Bits; u32] - -/* - Flags used by IPC objects + Access modes and flags used by SystemV IPC procedures. */ IPC_Flags :: bit_set[IPC_Flags_Bits; i16] /* - Permissions for IPC objects + Permissions for SystemV IPC primitives. */ IPC_Perm :: struct { key: Key, @@ -953,7 +950,7 @@ IPC_Perm :: struct { gid: u32, cuid: u32, cgid: u32, - mode: IPC_Mode, + mode: IPC_Flags, // Only contains mode flags. seq: u16, _: [2 + 2*size_of(int)]u8, } @@ -1449,9 +1446,25 @@ EPoll_Data :: struct #raw_union { u64: u64, } -EPoll_Event :: struct #packed { - events: EPoll_Event_Set, - data: EPoll_Data, +/* + Linux kernel only packs this struct on x86_64. + include/uapi/linux/eventpoll.h: + #ifdef __x86_64__ + #define EPOLL_PACKED __attribute__((packed)) + #else + #define EPOLL_PACKED + #endif +*/ +when ODIN_ARCH == .amd64 { + EPoll_Event :: struct #packed { + events: EPoll_Event_Set, + data: EPoll_Data, + } +} else { + EPoll_Event :: struct { + events: EPoll_Event_Set, + data: EPoll_Data, + } } /* @@ -1475,3 +1488,295 @@ RISCV_HWProbe :: struct { raw: u64, }, } + +IO_Uring_Params :: struct { + sq_entries: u32, + cq_entries: u32, + flags: IO_Uring_Setup_Flags, + sq_thread_cpu: u32, + sq_thread_idle: u32, + features: IO_Uring_Features, + wq_fd: u32, + resv: [3]u32, + sq_off: IO_SQ_Ring_Offsets, + cq_off: IO_CQ_Ring_Offsets, +} + +IO_Uring_Setup_Flags :: bit_set[IO_Uring_Setup_Flags_Bits; u32] + +IO_Uring_Features :: bit_set[IO_Uring_Features_Bits; u32] + +IO_SQ_Ring_Offsets :: struct { + head: u32, + tail: u32, + ring_mask: u32, + ring_entries: u32, + flags: u32, + dropped: u32, + array: u32, + resv1: u32, + user_addr: u64, +} + +IO_CQ_Ring_Offsets :: struct { + head: u32, + tail: u32, + ring_mask: u32, + ring_entries: u32, + overflow: u32, + cqes: u32, + flags: u32, + resv1: u32, + user_addr: u64, +} + +IO_Uring_Enter_Flags :: bit_set[IO_Uring_Enter_Flags_Bits; u32] + +IO_Uring_Getevents_Arg :: struct #min_field_align(8) { + sigmask: ^Sig_Set, + sigmask_sz: u32, + // pad: u32, + ts: ^Time_Spec, +} +#assert(align_of(IO_Uring_Getevents_Arg) == 8) + +IO_Uring_Rsrc_Register :: struct($T: typeid) { + nr: u32, + resv: u32, + resv2: u64, + using _: struct #min_field_align(8) { + data: [^]T, + tags: [^]u64, + }, +} + +IO_Uring_Rsrc_Update2 :: struct($T: typeid) { + offset: u32, + resv: u32, + using _: struct #min_field_align(8) { + data: [^]T, + tags: [^]u64, + }, + nr: u32, + resv2: u32, +} + +// The completion queue entry when the .CQE32 flag is not set on setup. +IO_Uring_CQE :: struct { + // sq.data submission passed back. + user_data: u64, + // result code for this event. + res: i32, + flags: IO_Uring_CQE_Flags, +} +#assert(size_of(IO_Uring_CQE) == 16) + +// The completion queue entry when the .CQE32 flag is set on setup. +IO_Uring_CQE32 :: struct { + using _: IO_Uring_CQE, + pad: u64, + pad2: u64, +} +#assert(size_of(IO_Uring_CQE32) == 32) + +IO_Uring_CQE_Flags :: bit_set[IO_Uring_CQE_Flags_Bits; u32] +IO_Uring_SQE_Flags :: bit_set[IO_Uring_SQE_Flags_Bits; u8] + +// The submission queue entry when the .SQE128 flag is not set on setup. +IO_Uring_SQE :: struct { + opcode: IO_Uring_OP, + flags: IO_Uring_SQE_Flags, + using __ioprio: struct #raw_union { + ioprio: u16, + sq_accept_flags: IO_Uring_Accept_Flags, + sq_send_recv_flags: IO_Uring_Send_Recv_Flags `raw_union_tag:"opcode=.SENDMSG, opcode=.RECVMSG, opcode=.SEND, opcode=.RECV"`, + }, + fd: Fd, + using __offset: struct #raw_union { + // Offset into file. + off: u64 `raw_union_tag:"opcode=.READV, opcode=.WRITEV, opcode=.SPLICE, opcode=.POLL_REMOVE, opcode=.EPOLL_CTL, opcode=.TIMEOUT, opcode=.ACCEPT, opcode=.CONNECT, opcode=.READ, opcode=.WRITE, opcode=.FILES_UPDATE, opcode=.SOCKET"`, + addr2: u64 `raw_union_tag:"opcode=.SEND, opcode=.BIND"`, + using _: struct { + cmd_op: u32, + __pad1: u32, + }, + statx: ^Statx `raw_union_tag:"opcode=.STATX"`, + }, + using __iovecs: struct #raw_union { + // Pointer to buffer or iovecs. + addr: u64 `raw_union_tag:"opcode=.READV, opcode=.WRITEV, opcode=.POLL_REMOVE, opcode=.EPOLL_CTL, opcode=.SENDMSG, opcode=.RECVMSG, opcode=.SEND, opcode=.RECV, opcode=.TIMEOUT, opcode=.TIMEOUT_REMOVE, opcode=.ACCEPT, opcode=.ASYNC_CANCEL, opcode=.LINK_TIMEOUT, opcode=.CONNECT, opcode=.MADVISE, opcode=.OPENAT, opcode=.STATX, opcode=.READ, opcode=.WRITE, opcode=.FILES_UPDATE, opcode=.BIND, opcode=.LISTEN"`, + splice_off_in: u64 `raw_union_tag:"opcode=.SPLICE"`, + using _: struct { + level: u32, + optname: u32, + }, + }, + using __len: struct #raw_union { + // Buffer size or number of iovecs. + len: u32 `raw_union_tag:"opcode=.READV, opcode=.WRITEV, opcode=.SPLICE, opcode=.SEND, opcode=.RECV, opcode=.TIMEOUT, opcode=.LINK_TIMEOUT, opcode=.MADVISE, opcode=.OPENAT, opcode=.READ, opcode=.WRITE, opcode=.TEE, opcode=.FILES_UPDATE, opcode=.SOCKET"`, + poll_flags: IO_Uring_Poll_Add_Flags `raw_union_tag:"opcode=.POLL_ADD, opcode=.POLL_REMOVE"`, + statx_mask: Statx_Mask `raw_union_tag:"opcode=.STATX"`, + epoll_ctl_op: EPoll_Ctl_Opcode `raw_union_tag:"opcode=.EPOLL_CTL"`, + shutdown_how: Shutdown_How `raw_union_tag:"opcode=.SHUTDOWN"`, + }, + using __contents: struct #raw_union { + rw_flags: i32 `raw_union_tag:"opcode=.READV, opcode=.WRITEV, opcode=.SOCKET"`, + fsync_flags: IO_Uring_Fsync_Flags `raw_union_tag:"opcode=.FSYNC"`, + // compatibility. + poll_events: Fd_Poll_Events `raw_union_tag:"opcode=.POLL_ADD, opcode=.POLL_REMOVE"`, + // word-reversed for BE. + poll32_events: u32, + sync_range_flags: u32, + msg_flags: Socket_Msg `raw_union_tag:"opcode=.SENDMSG, opcode=.RECVMSG, opcode=.SEND, opcode=.RECV"`, + timeout_flags: IO_Uring_Timeout_Flags `raw_union_tag:"opcode=.TIMEOUT, opcode=.TIMEOUT_REMOVE, opcode=.LINK_TIMEOUT"`, + accept_flags: Socket_FD_Flags `raw_union_tag:"opcode=.ACCEPT"`, + cancel_flags: u32, + open_flags: Open_Flags `raw_union_tag:"opcode=.OPENAT"`, + statx_flags: FD_Flags `raw_union_tag:"opcode=.STATX"`, + fadvise_advice: u32 `raw_union_tag:"opcode=.MADVISE"`, + splice_flags: IO_Uring_Splice_Flags `raw_union_tag:"opcode=.SPLICE, opcode=.TEE"`, + rename_flags: u32, + unlink_flags: u32, + hardlink_flags: u32, + xattr_flags: u32, + msg_ring_flags: u32, + uring_cmd_flags: IO_Uring_Cmd_Flags, + }, + // Data to be passed back at completion time. + user_data: u64, + using __buffer: struct #raw_union { + // Index into fixed buffers, if used. + buf_index: u16, + // For grouped buffer selection. + buf_group: u16, + }, + // Personality to use, if used. + personality: u16, + using _: struct #raw_union { + splice_fd_in: Fd `raw_union_tag:"opcode=.SPLICE, opcode=.TEE"`, + file_index: u32 `raw_union_tag:"opcode=.ACCEPT, opcode=.OPENAT, opcode=.CLOSE, opcode=.SOCKET"`, + using _: struct { + addr_len: u16 `raw_union_tag:"opcode=.SEND"`, + __pad3: [1]u16, + }, + }, + using __: struct #raw_union { + using _: struct { + addr3: u64, + __pad2: [1]u64, + }, + }, +} +#assert(size_of(IO_Uring_SQE) == 64) + +// The submission queue entry when the .SQE128 flag is set on setup. +IO_Uring_SQE128 :: struct { + using _: IO_Uring_SQE, + cmd: [64]byte, +} +#assert(size_of(IO_Uring_SQE128) == 128) + +IO_Uring_Poll_Add_Flags :: bit_set[IO_Uring_Poll_Add_Flags_Bits; u32] + +IO_Uring_Fsync_Flags :: bit_set[IO_Uring_Fsync_Flags_Bits; u32] + +IO_Uring_Timeout_Flags :: bit_set[IO_Uring_Timeout_Flags_Bits; u32] + +IO_Uring_Cmd_Flags :: bit_set[IO_Uring_Cmd_Flags_Bits; u32] + +IO_Uring_Splice_Flags :: bit_set[IO_Uring_Splice_Flags_Bits; u32] + +IO_Uring_Accept_Flags :: bit_set[IO_Uring_Accept_Flags_Bits; u16] + +IO_Uring_Send_Recv_Flags :: bit_set[IO_Uring_Send_Recv_Flags_Bits; u16] + +IO_Uring_Submission_Queue_Flags :: bit_set[IO_Uring_Submission_Queue_Flags_Bits; u32] + +Clock_State :: enum i32 { + TIME_OK = 0, + TIME_INS = 1, + TIME_DEL = 2, + TIME_OOP = 3, + TIME_WAIT = 4, + TIME_ERROR = 5, +} + +Timex :: struct { + modes: u32, + offset: int, + freq: int, + maxerror: int, + esterror: int, + status: i32, + constant: int, + precision: int, + tolerance: int, + time: Time_Val, + tick: int, + ppsfreq: int, + jitter: int, + shift: i32, + stabil: int, + jitcnt: int, + calcnt: int, + errcnt: int, + stbcnt: int, + tai: i32, +} + +Reboot_Magic :: enum u64 { + RB_MAGIC_1 = 0xfee1dead, + RB_MAGIC_2 = 672274793, + RB_MAGIC_2A = 85072278, // Since Linux 2.1.17 + RB_MAGIC_2B = 369367448, // Since Linux 2.1.97 + RB_MAGIC_2C = 537993216, // Since Linux 2.5.71 +} + +Reboot_Operation :: enum u64 { + RB_DISABLE_CAD = 0, + RB_ENABLE_CAD = 0x89abcdef, + RB_HALT_SYSTEM = 0xcdef0123, + RB_KEXEC = 0x45584543, + RB_POWER_OFF = 0x4321fedc, + RB_AUTOBOOT = 0x01234567, + RB_AUTOBOOT_2 = 0xa1b2c3d4, + RB_SW_SUSPEND = 0xd000fce2, +} + +Mount_Flags :: bit_set[Mount_Flags_Bits; uint] + +Umount2_Flags :: bit_set[Umount2_Flags_Bits; u32] + +Swap_Flags :: bit_set[Swap_Flags_Bits; u32] + +Eventfd_Flags :: bit_set[Eventfd_Flags_Bits; i32] + +Cpu_Set :: bit_set[0 ..< 128] + +Sched_Param :: struct { + sched_priority: i32, +} + +Sched_Flags :: bit_set[Sched_Flag_Bits; u32] + +Sched_Attr :: struct { + size: u32, + + sched_policy: Sched_Policy, + sched_flags: Sched_Flags, + sched_nice: i32, + sched_priority: u32, + + /* For the DEADLINE policy */ + sched_runtime: u64, + sched_deadline: u64, + sched_period: u64, + + /* Utilization hints */ + sched_util_min: u32, + sched_util_max: u32, +} + +Sched_Attr_Flags :: bit_set[Sched_Attr_Flag_Bits; u32] + +Memfd_Create_Flags :: bit_set[Memfd_Create_Flag_Bits; u32] diff --git a/core/sys/linux/uring/doc.odin b/core/sys/linux/uring/doc.odin new file mode 100644 index 000000000..8b9ae5ee8 --- /dev/null +++ b/core/sys/linux/uring/doc.odin @@ -0,0 +1,88 @@ +/* +Wrapper/convenience package over the raw io_uring syscalls, providing help with setup, creation, and operating the ring. + +The following example shows a simple `cat` program implementation using the package. + +Example: + package main + + import "base:runtime" + + import "core:fmt" + import "core:os" + import "core:sys/linux" + import "core:sys/linux/uring" + + Request :: struct { + path: cstring, + buffer: []byte, + completion: linux.IO_Uring_CQE, + } + + main :: proc() { + if len(os.args) < 2 { + fmt.eprintfln("Usage: %s [file name] <[file name] ...>", os.args[0]) + os.exit(1) + } + + requests := make_soa(#soa []Request, len(os.args)-1) + defer delete(requests) + + ring: uring.Ring + params := uring.DEFAULT_PARAMS + err := uring.init(&ring, ¶ms) + fmt.assertf(err == nil, "uring.init: %v", err) + defer uring.destroy(&ring) + + for &request, i in requests { + request.path = runtime.args__[i+1] + // sets up a read requests and adds it to the ring buffer. + submit_read_request(request.path, &request.buffer, &ring) + } + + ulen := u32(len(requests)) + + // submit the requests and wait for them to complete right away. + n, serr := uring.submit(&ring, ulen) + fmt.assertf(serr == nil, "uring.submit: %v", serr) + assert(n == ulen) + + // copy the completed requests out of the ring buffer. + cn := uring.copy_cqes_ready(&ring, requests.completion[:ulen]) + assert(cn == ulen) + + for request in requests { + // check result of the requests. + fmt.assertf(request.completion.res >= 0, "read %q failed: %v", request.path, linux.Errno(-request.completion.res)) + // print out. + fmt.print(string(request.buffer)) + + delete(request.buffer) + } + } + + submit_read_request :: proc(path: cstring, buffer: ^[]byte, ring: ^uring.Ring) { + fd, err := linux.open(path, {}) + fmt.assertf(err == nil, "open(%q): %v", path, err) + + file_sz := get_file_size(fd) + + buffer^ = make([]byte, file_sz) + + _, ok := uring.read(ring, 0, fd, buffer^, 0) + assert(ok, "could not get read sqe") + } + + get_file_size :: proc(fd: linux.Fd) -> uint { + st: linux.Stat + err := linux.fstat(fd, &st) + fmt.assertf(err == nil, "fstat: %v", err) + + if linux.S_ISREG(st.mode) { + return uint(st.size) + } + + panic("not a regular file") + } +*/ +package uring diff --git a/core/sys/linux/uring/ops.odin b/core/sys/linux/uring/ops.odin new file mode 100644 index 000000000..7b3392e98 --- /dev/null +++ b/core/sys/linux/uring/ops.odin @@ -0,0 +1,847 @@ +package uring + +import "core:sys/linux" + +// Do not perform any I/O. This is useful for testing the performance of the uring implementation itself. +nop :: proc(ring: ^Ring, user_data: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .NOP + sqe.user_data = user_data + + ok = true + return +} + +// Vectored read operation, see also readv(2). +readv :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, iovs: []linux.IO_Vec, off: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .READV + sqe.fd = fd + sqe.addr = cast(u64)uintptr(raw_data(iovs)) + sqe.len = u32(len(iovs)) + sqe.off = off + sqe.user_data = user_data + + ok = true + return +} + +// Vectored write operation, see also writev(2). +writev :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, iovs: []linux.IO_Vec, off: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .WRITEV + sqe.fd = fd + sqe.addr = cast(u64)uintptr(raw_data(iovs)) + sqe.len = u32(len(iovs)) + sqe.off = off + sqe.user_data = user_data + + ok = true + return +} + +read_fixed :: proc() { + unimplemented() +} + +write_fixed :: proc() { + unimplemented() +} + +/* +File sync. See also fsync(2). + +Optionally off and len can be used to specify a range within the file to be synced rather than syncing the entire file, which is the default behavior. + +Note that, while I/O is initiated in the order in which it appears in the submission queue, completions are unordered. +For example, an application which places a write I/O followed by an fsync in the submission queue cannot expect the fsync to apply to the write. +The two operations execute in parallel, so the fsync may complete before the write is issued to the storage. +The same is also true for previously issued writes that have not completed prior to the fsync. +To enforce ordering one may utilize linked SQEs, +IOSQE_IO_DRAIN or wait for the arrival of CQEs of requests which have to be ordered before a given request before submitting its SQE. +*/ +fsync :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, flags: linux.IO_Uring_Fsync_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .FSYNC + sqe.fsync_flags = flags + sqe.fd = fd + sqe.user_data = user_data + + ok = true + return +} + +/* +Poll the fd specified in the submission queue entry for the events specified in the poll_events field. + +Unlike poll or epoll without EPOLLONESHOT, by default this interface always works in one shot mode. +That is, once the poll operation is completed, it will have to be resubmitted. + +If IORING_POLL_ADD_MULTI is set in the SQE len field, then the poll will work in multi shot mode instead. +That means it'll repatedly trigger when the requested event becomes true, and hence multiple CQEs can be generated from this single SQE. +The CQE flags field will have IORING_CQE_F_MORE set on completion if the application should expect further CQE entries from the original request. +If this flag isn't set on completion, then the poll request has been terminated and no further events will be generated. +This mode is available since 5.13. + +This command works like an async poll(2) and the completion event result is the returned mask of events. + +Without IORING_POLL_ADD_MULTI and the initial poll operation with IORING_POLL_ADD_MULTI the operation is level triggered, +i.e. if there is data ready or events pending etc. +at the time of submission a corresponding CQE will be posted. +Potential further completions beyond the first caused by a IORING_POLL_ADD_MULTI are edge triggered. +*/ +poll_add :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, events: linux.Fd_Poll_Events, flags: linux.IO_Uring_Poll_Add_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .POLL_ADD + sqe.fd = fd + sqe.poll_events = events + sqe.poll_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +Remove an existing poll request. + +If found, the res field of the struct io_uring_cqe will contain 0. +If not found, res will contain -ENOENT, or -EALREADY if the poll request was in the process of completing already. +*/ +poll_remove :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, events: linux.Fd_Poll_Events) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .POLL_REMOVE + sqe.fd = fd + sqe.poll_events = events + sqe.user_data = user_data + + ok = true + return +} + +/* +Update the events of an existing poll request. + +The request will update an existing poll request with the mask of events passed in with this request. +The lookup is based on the user_data field of the original SQE submitted. + +Updating an existing poll is available since 5.13. +*/ +poll_update_events :: proc(ring: ^Ring, user_data: u64, orig_user_data: u64, fd: linux.Fd, events: linux.Fd_Poll_Events) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .POLL_REMOVE + sqe.fd = fd + sqe.addr = orig_user_data + sqe.poll_events = events + sqe.user_data = user_data + sqe.poll_flags = {.UPDATE_EVENTS} + + ok = true + return +} + +/* +Update the user data of an existing poll request. + +The request will update the user_data of an existing poll request based on the value passed. + +Updating an existing poll is available since 5.13. +*/ +poll_update_user_data :: proc(ring: ^Ring, user_data: u64, orig_user_data: u64, new_user_data: u64, fd: linux.Fd) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .POLL_REMOVE + sqe.fd = fd + sqe.off = orig_user_data + sqe.addr = new_user_data + sqe.user_data = user_data + sqe.poll_flags = {.UPDATE_USER_DATA} + + ok = true + return +} + +/* +Add, remove or modify entries in the interest list of epoll(7). + +See epoll_ctl(2) for details of the system call. + +Available since 5.6. +*/ +epoll_ctl :: proc(ring: ^Ring, user_data: u64, epfd: linux.Fd, op: linux.EPoll_Ctl_Opcode, fd: linux.Fd, event: ^linux.EPoll_Event) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .EPOLL_CTL + sqe.fd = epfd + sqe.off = u64(fd) + sqe.epoll_ctl_op = op + sqe.addr = cast(u64)uintptr(event) + sqe.user_data = user_data + + ok = true + return +} + +sync_file_range :: proc() { + unimplemented() +} + +/* +Issue the equivalent of a sendmsg(2) system call. + +See also sendmsg(2) for the general description of the related system call. + +poll_first: if set, uring will assume the socket is currently full and attempting to send data will be unsuccessful. +For this case, uring will arm internal poll and trigger a send of the data when there is enough space available. +This initial send attempt can be wasteful for the case where the socket is expected to be full, setting this flag will +bypass the initial send attempt and go straight to arming poll. +If poll does indicate that data can be sent, the operation will proceed. + +Available since 5.3. +*/ +sendmsg :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, msghdr: ^linux.Msg_Hdr, flags: linux.Socket_Msg, poll_first := false) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .SENDMSG + sqe.fd = fd + sqe.addr = cast(u64)uintptr(msghdr) + sqe.msg_flags = flags + sqe.user_data = user_data + sqe.sq_send_recv_flags = {.RECVSEND_POLL_FIRST} if poll_first else {} + + ok = true + return +} + +/* +Works just like sendmsg, but receives instead of sends. + +poll_first: If set, uring will assume the socket is currently empty and attempting to receive data will be unsuccessful. +For this case, uring will arm internal poll and trigger a receive of the data when the socket has data to be read. +This initial receive attempt can be wasteful for the case where the socket is expected to be empty, setting this flag will bypass the initial receive attempt and go straight to arming poll. +If poll does indicate that data is ready to be received, the operation will proceed. + +Available since 5.3. +*/ +recvmsg :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, msghdr: ^linux.Msg_Hdr, flags: linux.Socket_Msg, poll_first := false) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .RECVMSG + sqe.fd = fd + sqe.addr = cast(u64)uintptr(msghdr) + sqe.msg_flags = flags + sqe.user_data = user_data + sqe.sq_send_recv_flags = {.RECVSEND_POLL_FIRST} if poll_first else {} + + ok = true + return +} + +/* +Issue the equivalent of a send(2) system call. + +See also send(2) for the general description of the related system call. + +poll_first: If set, uring will assume the socket is currently full and attempting to send data will be unsuccessful. +For this case, uring will arm internal poll and trigger a send of the data when there is enough space available. +This initial send attempt can be wasteful for the case where the socket is expected to be full, setting this flag will bypass the initial send attempt and go straight to arming poll. +If poll does indicate that data can be sent, the operation will proceed. + +Available since 5.6. +*/ +send :: proc(ring: ^Ring, user_data: u64, sockfd: linux.Fd, buf: []byte, flags: linux.Socket_Msg, poll_first := false) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .SEND + sqe.fd = sockfd + sqe.addr = cast(u64)uintptr(raw_data(buf)) + sqe.len = u32(len(buf)) + sqe.msg_flags = flags + sqe.user_data = user_data + sqe.sq_send_recv_flags = {.RECVSEND_POLL_FIRST} if poll_first else {} + + ok = true + return +} + +sendto :: proc(ring: ^Ring, user_data: u64, sockfd: linux.Fd, buf: []byte, flags: linux.Socket_Msg, dest: ^$T, poll_first := false) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) + where T == linux.Sock_Addr_In || T == linux.Sock_Addr_In6 || T == linux.Sock_Addr_Un || T == linux.Sock_Addr_Any { + + sqe = send(ring, user_data, sockfd, buf, flags, poll_first) or_return + sqe.addr2 = u64(uintptr(dest)) + sqe.addr_len = u16(size_of(T)) + + ok = true + return +} + +/* +Works just like send, but receives instead of sends. + +poll_first: If set, uring will assume the socket is currently empty and attempting to receive data will be unsuccessful. +For this case, uring will arm internal poll and trigger a receive of the data when the socket has data to be read. +This initial receive attempt can be wasteful for the case where the socket is expected to be empty, setting this flag will bypass the initial receive attempt and go straight to arming poll. +If poll does indicate that data is ready to be received, the operation will proceed. + +Available since 5.6. +*/ +recv :: proc(ring: ^Ring, user_data: u64, sockfd: linux.Fd, buf: []byte, flags: linux.Socket_Msg, poll_first := false) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .RECV + sqe.fd = sockfd + sqe.addr = cast(u64)uintptr(raw_data(buf)) + sqe.len = cast(u32)uintptr(len(buf)) + sqe.msg_flags = flags + sqe.user_data = user_data + sqe.sq_send_recv_flags = {.RECVSEND_POLL_FIRST} if poll_first else {} + + ok = true + return +} + +/* +Register a timeout operation. + +The timeout will complete when either the timeout expires, or after the specified number of +events complete (if `count` is greater than `0`). + +`flags` may be `0` for a relative timeout, or `IORING_TIMEOUT_ABS` for an absolute timeout. + +The completion event result will be `-ETIME` if the timeout completed through expiration, +`0` if the timeout completed after the specified number of events, or `-ECANCELED` if the +timeout was removed before it expired. + +uring timeouts use the `CLOCK.MONOTONIC` clock source. +*/ +timeout :: proc(ring: ^Ring, user_data: u64, ts: ^linux.Time_Spec, count: u32, flags: linux.IO_Uring_Timeout_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .TIMEOUT + sqe.fd = -1 + sqe.addr = cast(u64)uintptr(ts) + sqe.len = 1 + sqe.off = u64(count) + sqe.timeout_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +Rmove an existing timeout operation. + +The timeout is identified by it's `user_data`. + +The completion event result will be `0` if the timeout was found and cancelled successfully, +`-EBUSY` if the timeout was found but expiration was already in progress, or +`-ENOENT` if the timeout was not found. +*/ +timeout_remove :: proc(ring: ^Ring, user_data: u64, timeout_user_data: u64, flags: linux.IO_Uring_Timeout_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .TIMEOUT_REMOVE + sqe.fd = -1 + sqe.addr = timeout_user_data + sqe.timeout_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of an accept4(2) system call. + +See also accept4(2) for the general description of the related system call. + +If the file_index field is set to a positive number, the file won't be installed into the normal file table as usual +but will be placed into the fixed file table at index file_index - 1. +In this case, instead of returning a file descriptor, the result will contain either 0 on success or an error. +If the index points to a valid empty slot, the installation is guaranteed to not fail. +If there is already a file in the slot, it will be replaced, similar to IORING_OP_FILES_UPDATE. +Please note that only uring has access to such files and no other syscall can use them. See IOSQE_FIXED_FILE and IORING_REGISTER_FILES. + +Available since 5.5. +*/ +accept :: proc(ring: ^Ring, user_data: u64, sockfd: linux.Fd, addr: ^$T, addr_len: ^i32, flags: linux.Socket_FD_Flags, file_index: u32 = 0) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) +where T == linux.Sock_Addr_In || T == linux.Sock_Addr_In6 || T == linux.Sock_Addr_Un || T == linux.Sock_Addr_Any { + + sqe = get_sqe(ring) or_return + sqe.opcode = .ACCEPT + sqe.fd = sockfd + sqe.addr = cast(u64)uintptr(addr) + sqe.off = cast(u64)uintptr(addr_len) + sqe.accept_flags = flags + sqe.user_data = user_data + sqe.file_index = file_index + + ok = true + return +} + +/* +Attempt to cancel an already issued request. + +The request is identified by it's user data. + +The cancelation request will complete with one of the following results codes. + +If found, the res field of the cqe will contain 0. +If not found, res will contain -ENOENT. + +If found and attempted canceled, the res field will contain -EALREADY. +In this case, the request may or may not terminate. +In general, requests that are interruptible (like socket IO) will get canceled, while disk IO requests cannot be canceled if already started. + +Available since 5.5. +*/ +async_cancel :: proc(ring: ^Ring, orig_user_data: u64, user_data: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .ASYNC_CANCEL + sqe.addr = orig_user_data + sqe.user_data = user_data + + ok = true + return +} + +/* +Adds a link timeout operation. + +You need to set linux.IOSQE_IO_LINK to flags of the target operation +and then call this method right after the target operation. +See https://lwn.net/Articles/803932/ for detail. + +If the dependent request finishes before the linked timeout, the timeout +is canceled. If the timeout finishes before the dependent request, the +dependent request will be canceled. + +The completion event result of the link_timeout will be +`-ETIME` if the timeout finishes before the dependent request +(in this case, the completion event result of the dependent request will +be `-ECANCELED`), or +`-EALREADY` if the dependent request finishes before the linked timeout. + +Available since 5.5. +*/ +link_timeout :: proc(ring: ^Ring, user_data: u64, ts: ^linux.Time_Spec, flags: linux.IO_Uring_Timeout_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring, 0) or_return + sqe.opcode = .LINK_TIMEOUT + sqe.fd = -1 + sqe.addr = cast(u64)uintptr(ts) + sqe.len = 1 + sqe.timeout_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a connect(2) system call. + +See also connect(2) for the general description of the related system call. + +Available since 5.5. +*/ +connect :: proc(ring: ^Ring, user_data: u64, sockfd: linux.Fd, addr: ^$T) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) +where T == linux.Sock_Addr_In || T == linux.Sock_Addr_In6 || T == linux.Sock_Addr_Un || T == linux.Sock_Addr_Any { + + sqe = get_sqe(ring) or_return + sqe.opcode = .CONNECT + sqe.fd = sockfd + sqe.addr = cast(u64)uintptr(addr) + sqe.off = size_of(T) + sqe.user_data = user_data + + ok = true + return +} + +fallocate :: proc() { + unimplemented() +} + +fadvise :: proc() { + unimplemented() +} + +/* +Issue the equivalent of a madvise(2) system call. + +See also madvise(2) for the general description of the related system call. + +Available since 5.6. +*/ +madvise :: proc(ring: ^Ring, user_data: u64, addr: rawptr, size: u32, advise: linux.MAdvice) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .MADVISE + sqe.addr = u64(uintptr(addr)) + sqe.len = size + sqe.fadvise_advice = cast(u32)transmute(int)advise + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a openat(2) system call. + +See also openat(2) for the general description of the related system call. + +Available since 5.6. + +If the file_index is set to a positive number, +the file won't be installed into the normal file table as usual but will be placed into the fixed file table at index file_index - 1. +In this case, instead of returning a file descriptor, the result will contain either 0 on success or an error. +If the index points to a valid empty slot, the installation is guaranteed to not fail. +If there is already a file in the slot, it will be replaced, similar to IORING_OP_FILES_UPDATE. +Please note that only uring has access to such files and no other syscall can use them. +See IOSQE_FIXED_FILE and IORING_REGISTER_FILES. + +Available since 5.15. +*/ +openat :: proc(ring: ^Ring, user_data: u64, dirfd: linux.Fd, path: cstring, mode: linux.Mode, flags: linux.Open_Flags, file_index: u32 = 0) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .OPENAT + sqe.fd = dirfd + sqe.addr = cast(u64)transmute(uintptr)path + sqe.len = transmute(u32)mode + sqe.open_flags = flags + sqe.user_data = user_data + sqe.file_index = file_index + + ok = true + return +} + +openat2 :: proc() { + unimplemented() +} + +/* +Issue the equivalent of a close(2) system call. + +See also close(2) for the general description of the related system call. + +Available since 5.6. + +If the file_index field is set to a positive number, this command can be used to close files that were +direct opened through IORING_OP_OPENAT, IORING_OP_OPENAT2, or IORING_OP_ACCEPT using the uring specific direct descriptors. +Note that only one of the descriptor fields may be set. +The direct close feature is available since the 5.15 kernel, where direct descriptors were introduced. +*/ +close :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, file_index: u32 = 0) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .CLOSE + sqe.fd = fd + sqe.user_data = user_data + sqe.file_index = file_index + + ok = true + return +} + +/* +Issue the equivalent of a statx(2) system call. + +See also statx(2) for the general description of the related system call. + +Available since 5.6. +*/ +statx :: proc(ring: ^Ring, user_data: u64, dirfd: linux.Fd, pathname: cstring, flags: linux.FD_Flags, mask: linux.Statx_Mask, buf: ^linux.Statx) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .STATX + sqe.fd = dirfd + sqe.addr = cast(u64)transmute(uintptr)pathname + sqe.statx_flags = flags + sqe.statx_mask = mask + sqe.statx = buf + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a pread(2) system call. + +If offset is set to -1 , the offset will use (and advance) the file position, like the read(2) system calls. +These are non-vectored versions of the IORING_OP_READV and IORING_OP_WRITEV opcodes. +See also read(2) for the general description of the related system call. + +Available since 5.6. +*/ +read :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, buf: []u8, offset: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .READ + sqe.fd = fd + sqe.addr = cast(u64)uintptr(raw_data(buf)) + sqe.len = u32(len(buf)) + sqe.off = offset + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a pwrite(2) system call. + +If offset is set to -1 , the offset will use (and advance) the file position, like the read(2) system calls. +These are non-vectored versions of the IORING_OP_READV and IORING_OP_WRITEV opcodes. +See also write(2) for the general description of the related system call. + +Available since 5.6. +*/ +write :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, buf: []u8, offset: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .WRITE + sqe.fd = fd + sqe.addr = cast(u64)uintptr(raw_data(buf)) + sqe.len = u32(len(buf)) + sqe.off = offset + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a splice(2) system call. + +A sentinel value of -1 is used to pass the equivalent of a NULL for the offsets to splice(2). + +Please note that one of the file descriptors must refer to a pipe. +See also splice(2) for the general description of the related system call. + +Available since 5.7. + +*/ +splice :: proc(ring: ^Ring, user_data: u64, fd_in: linux.Fd, off_in: i64, fd_out: linux.Fd, off_out: i64, len: u32, flags: linux.IO_Uring_Splice_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .SPLICE + sqe.splice_fd_in = fd_in + sqe.splice_off_in = cast(u64)off_in + sqe.fd = fd_out + sqe.off = cast(u64)off_out + sqe.len = len + sqe.splice_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +Issue the equivalent of a tee(2) system call. + +Please note that both of the file descriptors must refer to a pipe. +See also tee(2) for the general description of the related system call. + +Available since 5.8. +*/ +tee :: proc(ring: ^Ring, user_data: u64, fd_in: linux.Fd, fd_out: linux.Fd, len: u32, flags: linux.IO_Uring_Splice_Flags) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .TEE + sqe.splice_fd_in = fd_in + sqe.fd = fd_out + sqe.len = len + sqe.splice_flags = flags + sqe.user_data = user_data + + ok = true + return +} + +/* +This command is an alternative to using IORING_REGISTER_FILES_UPDATE which then works in an async fashion, like the rest of the uring commands. + +Note that the array of file descriptors pointed to in addr must remain valid until this operation has completed. + +Available since 5.6. +*/ +files_update :: proc(ring: ^Ring, user_data: u64, fds: []linux.Fd, off: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .FILES_UPDATE + sqe.addr = cast(u64)uintptr(raw_data(fds)) + sqe.len = cast(u32)len(fds) + sqe.off = off + sqe.user_data = user_data + + ok = true + return +} + +provide_buffers :: proc() { + unimplemented() +} + +remove_buffers :: proc() { + unimplemented() +} + +/* +Issue the equivalent of a shutdown(2) system call. + +Available since 5.11. +*/ +shutdown :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, how: linux.Shutdown_How) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .SHUTDOWN + sqe.fd = fd + sqe.shutdown_how = how + sqe.user_data = user_data + + ok = true + return +} + +renameat :: proc() { + unimplemented() +} + +unlinkat :: proc() { + unimplemented() +} + +mkdirat :: proc() { + unimplemented() +} + +symlinkat :: proc() { + unimplemented() +} + +linkat :: proc() { + unimplemented() +} + +msg_ring :: proc() { + unimplemented() +} + +/* +Issue the equivalent of a socket(2) system call. + +See also socket(2) for the general description of the related system call. + +Available since 5.19. + +If the file_index field is set to a positive number, the file won't be installed into the normal file +table as usual but will be placed into the fixed file table at index file_index - 1. +In this case, instead of returning a file descriptor, the result will contain either 0 on success or an error. +If the index points to a valid empty slot, the installation is guaranteed to not fail. +If there is already a file in the slot, it will be replaced, similar to IORING_OP_FILES_UPDATE. +Please note that only uring has access to such files and no other syscall can use them. +See IOSQE_FIXED_FILE and IORING_REGISTER_FILES. +*/ +socket :: proc(ring: ^Ring, user_data: u64, domain: linux.Address_Family, socktype: linux.Socket_Type, protocol: linux.Protocol, file_index: u32 = 0) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .SOCKET + sqe.user_data = user_data + sqe.fd = cast(linux.Fd)domain + sqe.off = cast(u64)socktype + sqe.len = cast(u32)protocol + sqe.rw_flags = {} + sqe.file_index = file_index + + ok = true + return +} + +uring_cmd :: proc() { + unimplemented() +} + +send_zc :: proc() { + unimplemented() +} + +sendmsg_zc :: proc() { + unimplemented() +} + +waitid :: proc() { + unimplemented() +} + +setxattr :: proc() { + unimplemented() +} + +getxattr :: proc() { + unimplemented() +} + +fsetxattr :: proc() { + unimplemented() +} + +fgetxattr :: proc() { + unimplemented() +} + +/* +Issues the equivalent of the bind(2) system call. + +Available since 6.11. +*/ +bind :: proc(ring: ^Ring, user_data: u64, sock: linux.Fd, addr: ^$T) -> (sqe: linux.IO_Uring_SQE, ok: bool) + where + T == linux.Sock_Addr_In || + T == linux.Sock_Addr_In6 || + T == linux.Sock_Addr_Un || + T == linux.Sock_Addr_Any +{ + sqe = get_sqe(ring) or_return + sqe.opcode = .BIND + sqe.user_data = user_data + sqe.fd = sock + sqe.addr = cast(u64)uintptr(addr) + sqe.addr2 = size_of(T) + + ok = true + return +} + +/* +Issues the equivalent of the listen(2) system call. + +fd must contain the file descriptor of the socket and addr must contain the backlog parameter, i.e. the maximum amount of pending queued connections. + +Available since 6.11. +*/ +listen :: proc(ring: ^Ring, user_data: u64, fd: linux.Fd, backlog: u64) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sqe = get_sqe(ring) or_return + sqe.opcode = .LISTEN + sqe.user_data = user_data + sqe.fd = fd + sqe.addr = backlog + + ok = true + return +} + +ftruncate :: proc() { + unimplemented() +} + +read_multishot :: proc() { + unimplemented() +} + +futex_wait :: proc() { + unimplemented() +} + +futex_wake :: proc() { + unimplemented() +} + +futex_waitv :: proc() { + unimplemented() +} + +fixed_fd_install :: proc() { + unimplemented() +} + +fixed_file :: proc() { + unimplemented() +} diff --git a/core/sys/linux/uring/uring.odin b/core/sys/linux/uring/uring.odin new file mode 100644 index 000000000..8e4315e6a --- /dev/null +++ b/core/sys/linux/uring/uring.odin @@ -0,0 +1,294 @@ +package uring + +import "core:math" +import "core:sync" +import "core:sys/linux" + +DEFAULT_THREAD_IDLE_MS :: 1000 +DEFAULT_ENTRIES :: 32 +MAX_ENTRIES :: 4096 + +Ring :: struct { + fd: linux.Fd, + sq: Submission_Queue, + cq: Completion_Queue, + flags: linux.IO_Uring_Setup_Flags, + features: linux.IO_Uring_Features, +} + +DEFAULT_PARAMS :: linux.IO_Uring_Params { + sq_thread_idle = DEFAULT_THREAD_IDLE_MS, +} + +// Initialize and setup an uring, `entries` must be a power of 2 between 1 and 4096. +init :: proc(ring: ^Ring, params: ^linux.IO_Uring_Params, entries: u32 = DEFAULT_ENTRIES) -> (err: linux.Errno) { + assert(entries <= MAX_ENTRIES, "too many entries") + assert(entries != 0, "entries must be positive") + assert(math.is_power_of_two(int(entries)), "entries must be a power of two") + + fd := linux.io_uring_setup(entries, params) or_return + defer if err != nil { linux.close(fd) } + + if .SINGLE_MMAP not_in params.features { + // NOTE: Could support this, but currently isn't. + err = .ENOSYS + return + } + + assert(.CQE32 not_in params.flags, "unsupported flag") // NOTE: Could support this by making IO_Uring generic. + assert(.SQE128 not_in params.flags, "unsupported flag") // NOTE: Could support this by making IO_Uring generic. + + sq := submission_queue_make(fd, params) or_return + + ring.fd = fd + ring.sq = sq + ring.cq = completion_queue_make(fd, params, &sq) + ring.flags = params.flags + ring.features = params.features + + return +} + +destroy :: proc(ring: ^Ring) { + assert(ring.fd >= 0) + submission_queue_destroy(&ring.sq) + linux.close(ring.fd) + ring.fd = -1 +} + +// Returns a pointer to a vacant submission queue entry, or nil if the submission queue is full. +// NOTE: extra is so you can make sure there is space for related entries, defaults to 1 so +// a link timeout op can always be added after another. +get_sqe :: proc(ring: ^Ring, extra: int = 1) -> (sqe: ^linux.IO_Uring_SQE, ok: bool) { + sq := &ring.sq + head: u32 = sync.atomic_load_explicit(sq.head, .Acquire) + next := sq.sqe_tail + 1 + + if int(next - head) > len(sq.sqes)-extra { + sqe = nil + ok = false + return + } + + sqe = &sq.sqes[sq.sqe_tail & sq.mask] + sqe^ = {} + + sq.sqe_tail = next + ok = true + return +} + +free_space :: proc(ring: ^Ring) -> int { + sq := &ring.sq + head := sync.atomic_load_explicit(sq.head, .Acquire) + next := sq.sqe_tail + 1 + free := len(sq.sqes) - int(next - head) + assert(free >= 0) + return free +} + +// Sync internal state with kernel ring state on the submission queue side. +// Returns the number of all pending events in the submission queue. +// Rationale is to determine that an enter call is needed. +flush_sq :: proc(ring: ^Ring) -> (n_pending: u32) { + sq := &ring.sq + to_submit := sq.sqe_tail - sq.sqe_head + if to_submit != 0 { + tail := sq.tail^ + i: u32 = 0 + for ; i < to_submit; i += 1 { + sq.array[tail & sq.mask] = sq.sqe_head & sq.mask + tail += 1 + sq.sqe_head += 1 + } + sync.atomic_store_explicit(sq.tail, tail, .Release) + } + n_pending = sq_ready(ring) + return +} + +// Returns true if we are not using an SQ thread (thus nobody submits but us), +// or if IORING_SQ_NEED_WAKEUP is set and the SQ thread must be explicitly awakened. +// For the latter case, we set the SQ thread wakeup flag. +// Matches the implementation of sq_ring_needs_enter() in liburing. +sq_ring_needs_enter :: proc(ring: ^Ring, flags: ^linux.IO_Uring_Enter_Flags) -> bool { + assert(flags^ == {}) + if .SQPOLL not_in ring.flags { return true } + if .NEED_WAKEUP in sync.atomic_load_explicit(ring.sq.flags, .Relaxed) { + flags^ += {.SQ_WAKEUP} + return true + } + return false +} + + +// Submits the submission queue entries acquired via get_sqe(). +// Returns the number of entries submitted. +// Optionally wait for a number of events by setting `wait_nr`, and/or set a maximum wait time by setting `timeout`. +submit :: proc(ring: ^Ring, wait_nr: u32 = 0, timeout: ^linux.Time_Spec = nil) -> (n_submitted: u32, err: linux.Errno) { + n_submitted = flush_sq(ring) + flags: linux.IO_Uring_Enter_Flags + if sq_ring_needs_enter(ring, &flags) || wait_nr > 0 { + if wait_nr > 0 || .IOPOLL in ring.flags { + flags += {.GETEVENTS} + } + + flags += {.EXT_ARG} + ext: linux.IO_Uring_Getevents_Arg + ext.ts = timeout + + n_submitted_: int + n_submitted_, err = linux.io_uring_enter2(ring.fd, n_submitted, wait_nr, flags, &ext) + assert(n_submitted_ >= 0) + n_submitted = u32(n_submitted_) + } + return +} + +// Returns the number of submission queue entries in the submission queue. +sq_ready :: proc(ring: ^Ring) -> u32 { + // Always use the shared ring state (i.e. head and not sqe_head) to avoid going out of sync, + // see https://github.com/axboe/liburing/issues/92. + return ring.sq.sqe_tail - sync.atomic_load_explicit(ring.sq.head, .Acquire) +} + +// Returns the number of completion queue entries in the completion queue (yet to consume). +cq_ready :: proc(ring: ^Ring) -> (n_ready: u32) { + return sync.atomic_load_explicit(ring.cq.tail, .Acquire) - ring.cq.head^ +} + +// Copies as many CQEs as are ready, and that can fit into the destination `cqes` slice. +// If none are available, enters into the kernel to wait for at most `wait_nr` CQEs. +// Returns the number of CQEs copied, advancing the CQ ring. +// Provides all the wait/peek methods found in liburing, but with batching and a single method. +// TODO: allow for timeout. +copy_cqes :: proc(ring: ^Ring, cqes: []linux.IO_Uring_CQE, wait_nr: u32) -> (n_copied: u32, err: linux.Errno) { + n_copied = copy_cqes_ready(ring, cqes) + if n_copied > 0 { return } + if wait_nr > 0 || cq_ring_needs_flush(ring) { + _ = linux.io_uring_enter(ring.fd, 0, wait_nr, {.GETEVENTS}, nil) or_return + n_copied = copy_cqes_ready(ring, cqes) + } + return +} + +copy_cqes_ready :: proc(ring: ^Ring, cqes: []linux.IO_Uring_CQE) -> (n_copied: u32) { + n_ready := cq_ready(ring) + n_copied = min(u32(len(cqes)), n_ready) + head := ring.cq.head^ + tail := head + n_copied + shift := u32(.CQE32 in ring.flags) + + i := 0 + for head != tail { + cqes[i] = ring.cq.cqes[(head & ring.cq.mask) << shift] + head += 1 + i += 1 + } + cq_advance(ring, n_copied) + return +} + +cq_ring_needs_flush :: proc(ring: ^Ring) -> bool { + return .CQ_OVERFLOW in sync.atomic_load_explicit(ring.sq.flags, .Relaxed) +} + +// For advanced use cases only that implement custom completion queue methods. +// If you use copy_cqes() or copy_cqe() you must not call cqe_seen() or cq_advance(). +// Must be called exactly once after a zero-copy CQE has been processed by your application. +// Not idempotent, calling more than once will result in other CQEs being lost. +// Matches the implementation of cqe_seen() in liburing. +cqe_seen :: proc(ring: ^Ring) { + cq_advance(ring, 1) +} + +// For advanced use cases only that implement custom completion queue methods. +// Matches the implementation of cq_advance() in liburing. +cq_advance :: proc(ring: ^Ring, count: u32) { + if count == 0 { return } + sync.atomic_store_explicit(ring.cq.head, ring.cq.head^ + count, .Release) +} + +Submission_Queue :: struct { + head: ^u32, + tail: ^u32, + mask: u32, + flags: ^linux.IO_Uring_Submission_Queue_Flags, + dropped: ^u32, + array: []u32, + sqes: []linux.IO_Uring_SQE, + mmap: []u8, + mmap_sqes: []u8, + + // We use `sqe_head` and `sqe_tail` in the same way as liburing: + // We increment `sqe_tail` (but not `tail`) for each call to `get_sqe()`. + // We then set `tail` to `sqe_tail` once, only when these events are actually submitted. + // This allows us to amortize the cost of the @atomicStore to `tail` across multiple SQEs. + sqe_head: u32, + sqe_tail: u32, +} + +submission_queue_make :: proc(fd: linux.Fd, params: ^linux.IO_Uring_Params) -> (sq: Submission_Queue, err: linux.Errno) { + assert(fd >= 0, "uninitialized queue fd") + assert(.SINGLE_MMAP in params.features, "unsupported feature") // NOTE: Could support this, but currently isn't. + + sq_size := params.sq_off.array + params.sq_entries * size_of(u32) + cq_size := params.cq_off.cqes + params.cq_entries * size_of(linux.IO_Uring_CQE) + size := max(sq_size, cq_size) + + // PERF: .POPULATE commits all pages right away, is that desired? + + cqe_map := cast([^]byte)(linux.mmap(0, uint(size), {.READ, .WRITE}, {.SHARED, .POPULATE}, fd, linux.IORING_OFF_SQ_RING) or_return) + defer if err != nil { linux.munmap(cqe_map, uint(size)) } + + size_sqes := params.sq_entries * size_of(linux.IO_Uring_SQE) + sqe_map := cast([^]byte)(linux.mmap(0, uint(size_sqes), {.READ, .WRITE}, {.SHARED, .POPULATE}, fd, linux.IORING_OFF_SQES) or_return) + + array := cast([^]u32)cqe_map[params.sq_off.array:] + sqes := cast([^]linux.IO_Uring_SQE)sqe_map + + sq.head = cast(^u32)&cqe_map[params.sq_off.head] + sq.tail = cast(^u32)&cqe_map[params.sq_off.tail] + sq.mask = (cast(^u32)&cqe_map[params.sq_off.ring_mask])^ + sq.flags = cast(^linux.IO_Uring_Submission_Queue_Flags)&cqe_map[params.sq_off.flags] + sq.dropped = cast(^u32)&cqe_map[params.sq_off.dropped] + sq.array = array[:params.sq_entries] + sq.sqes = sqes[:params.sq_entries] + sq.mmap = cqe_map[:size] + sq.mmap_sqes = sqe_map[:size_sqes] + + return +} + +submission_queue_destroy :: proc(sq: ^Submission_Queue) -> (err: linux.Errno) { + err = linux.munmap(raw_data(sq.mmap), uint(len(sq.mmap))) + err2 := linux.munmap(raw_data(sq.mmap_sqes), uint(len(sq.mmap_sqes))) + if err == nil { err = err2 } + return +} + +Completion_Queue :: struct { + head: ^u32, + tail: ^u32, + mask: u32, + overflow: ^u32, + cqes: []linux.IO_Uring_CQE, +} + +completion_queue_make :: proc(fd: linux.Fd, params: ^linux.IO_Uring_Params, sq: ^Submission_Queue) -> Completion_Queue { + assert(fd >= 0, "uninitialized queue fd") + assert(.SINGLE_MMAP in params.features, "required feature SINGLE_MMAP not supported") + + mmap := sq.mmap + cqes := cast([^]linux.IO_Uring_CQE)&mmap[params.cq_off.cqes] + + return( + { + head = cast(^u32)&mmap[params.cq_off.head], + tail = cast(^u32)&mmap[params.cq_off.tail], + mask = (cast(^u32)&mmap[params.cq_off.ring_mask])^, + overflow = cast(^u32)&mmap[params.cq_off.overflow], + cqes = cqes[:params.cq_entries], + } \ + ) +} diff --git a/core/sys/linux/wrappers.odin b/core/sys/linux/wrappers.odin index 7b0dc61e2..53eb80f86 100644 --- a/core/sys/linux/wrappers.odin +++ b/core/sys/linux/wrappers.odin @@ -54,22 +54,45 @@ WCOREDUMP :: #force_inline proc "contextless" (s: u32) -> bool { // TODO: sigaddset etc -/// Iterate the results of getdents -/// Only iterates as much data as loaded in the buffer -/// In case you need to iterate *all* files in a directory -/// consider using dirent_get_iterate -/// -/// Example of using dirent_iterate_buf -/// // Get dirents into a buffer -/// buf: [128]u8 -/// sys.getdents(dirfd, buf[:]) -/// // Print the names of the files -/// for dir in sys.dirent_iterate_buf(buf[:], &offs) { -/// name := sys.dirent_name(dir) -/// fmt.println(name) -/// } -/// This function doesn't automatically make a request -/// for the buffer to be refilled +/* +Iterate the results of `getdents()`. + +This procedure extracts a directory entry from `buf` at the offset `offs`. +`offs` will be modified to store an offset to the possible next directory entry +in `buf`. The procedure only iterates as much data as loaded in the buffer and +does not automatically make a request for the buffer to be refilled. + +Inputs: +- buf: A byte buffer with data from `getdents()` +- offs: An offset to the next possible directory entry in `buf` + +Returns: +- A pointer to a directory entry in `buf`, or `nil` +- A bool value denoting if a valid directory entry is returned + +Example: + + import "core:fmt" + import "core:sys/linux" + + print_names :: proc(dirfd: linux.Fd) { + // Get dirents into a buffer. + buf: [128]u8 + // Loop until there are no more entries. + for { + written, err := linux.getdents(dirfd, buf[:]) + if err != .NONE || written == 0 { + break + } + // Print the names of the files. + offset : int + for dir in linux.dirent_iterate_buf(buf[:written], &offset) { + name := linux.dirent_name(dir) + fmt.println(name) + } + } + } +*/ dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent, cont: bool) { // Stopped iterating when there's no space left if offs^ >= len(buf) { @@ -82,8 +105,17 @@ dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent, return dirent, true } -/// Obtain the name of dirent as a string -/// The lifetime of the string is bound to the lifetime of the provided dirent structure +/* +Obtain the name of dirent as a string. + +The lifetime of the returned string is bound to the lifetime of the provided dirent structure. + +Inputs: +- dirent: A directory entry + +Returns: +- A name of the entry +*/ dirent_name :: proc "contextless" (dirent: ^Dirent) -> string #no_bounds_check { str := ([^]u8)(&dirent.name) // Dirents are aligned to 8 bytes, so there is guaranteed to be a null diff --git a/core/sys/orca/macros.odin b/core/sys/orca/macros.odin index 12adfdb91..14b270bef 100644 --- a/core/sys/orca/macros.odin +++ b/core/sys/orca/macros.odin @@ -1,7 +1,7 @@ -// File contains implementations of the Orca API that are defined as macros in Orca. - package orca +// Implementations of the `Orca` API that are defined as macros in Orca. + //////////////////////////////////////////////////////////////////////////////// // Helpers for logging, asserting and aborting. //////////////////////////////////////////////////////////////////////////////// diff --git a/core/sys/orca/odin.odin b/core/sys/orca/odin.odin index c59b990cf..bdda9aa5b 100644 --- a/core/sys/orca/odin.odin +++ b/core/sys/orca/odin.odin @@ -1,7 +1,7 @@ -// File contains Odin specific helpers. - package orca +// File contains Odin specific helpers. + import "base:runtime" create_odin_logger :: proc(lowest := runtime.Logger_Level.Debug, ident := "") -> runtime.Logger { diff --git a/core/sys/orca/orca.odin b/core/sys/orca/orca.odin index abcf42fe2..a0fe0a041 100644 --- a/core/sys/orca/orca.odin +++ b/core/sys/orca/orca.odin @@ -1,12 +1,13 @@ +// Bindings for the Orca platform +// +// See: [[ https://orca-app.dev ]] + package orca import "core:c" char :: c.char -// currently missing in the api.json -window :: distinct u64 - // currently missing in the api.json pool :: struct { arena: arena, @@ -139,17 +140,6 @@ UNICODE_VARIATION_SELECTORS_SUPPLEMENT :: unicode_range { 0xe0100, 239 } UNICODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A :: unicode_range { 0xf0000, 65533 } UNICODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B :: unicode_range { 0x100000, 65533 } -clock_kind :: enum c.int { - MONOTONIC, - UPTIME, - DATE, -} - -@(default_calling_convention="c", link_prefix="oc_") -foreign { - clock_time :: proc(clock: clock_kind) -> f64 --- -} - file_write_slice :: proc(file: file, slice: []char) -> u64 { return file_write(file, u64(len(slice)), raw_data(slice)) } @@ -201,6 +191,26 @@ foreign { mat2x3_rotate :: proc(radians: f32) -> mat2x3 --- // Return a 2x3 matrix representing a translation. mat2x3_translate :: proc(x: f32, y: f32) -> mat2x3 --- + // Return a 2x3 matrix representing a scale. + mat2x3_scale :: proc(x: f32, y: f32) -> mat2x3 --- +} + +//////////////////////////////////////////////////////////////////////////////// +// API for sampling the system clock. +//////////////////////////////////////////////////////////////////////////////// + +clock_kind :: enum u32 { + // A clock incrementing monotonically. + MONOTONIC = 0, + // A clock incrementing monotonically during uptime. + UPTIME = 1, + // A clock driven by the platform time. + DATE = 2, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + clock_time :: proc(clock: clock_kind) -> f64 --- } //////////////////////////////////////////////////////////////////////////////// @@ -351,10 +361,14 @@ foreign { arena_init_with_options :: proc(arena: ^arena, options: ^arena_options) --- // Release all resources allocated to a memory arena. arena_cleanup :: proc(arena: ^arena) --- - // Allocate a block of memory from an arena. + // Allocate a zero initialized block of memory from an arena. arena_push :: proc(arena: ^arena, size: u64) -> rawptr --- - // Allocate an aligned block of memory from an arena. + // Allocate an aligned, zero initialized block of memory from an arena. arena_push_aligned :: proc(arena: ^arena, size: u64, alignment: u32) -> rawptr --- + // Allocate a block of memory from an arena. + arena_push_uninitialized :: proc(arena: ^arena, size: u64) -> rawptr --- + // Allocate an aligned block of memory from an arena. + arena_push_aligned_uninitialized :: proc(arena: ^arena, size: u64, alignment: u32) -> rawptr --- // Reset an arena. All memory that was previously allocated from this arena is released to the arena, and can be reallocated by later calls to `oc_arena_push` and similar functions. No memory is actually released _to the system_. arena_clear :: proc(arena: ^arena) --- // Begin a memory scope. This creates an `oc_arena_scope` object that stores the current offset of the arena. The arena can later be reset to that offset by calling `oc_arena_scope_end`, releasing all memory that was allocated within the scope to the arena. @@ -527,15 +541,15 @@ utf8_status :: enum u32 { // The operation unexpectedly encountered the end of the utf8 sequence. OUT_OF_BOUNDS = 1, // A continuation byte was encountered where a leading byte was expected. - UNEXPECTED_CONTINUATION_BYTE = 3, + UNEXPECTED_CONTINUATION_BYTE = 2, // A leading byte was encountered in the middle of the encoding of utf8 codepoint. - UNEXPECTED_LEADING_BYTE = 4, + UNEXPECTED_LEADING_BYTE = 3, // The utf8 sequence contains an invalid byte. - INVALID_BYTE = 5, + INVALID_BYTE = 4, // The operation encountered an invalid utf8 codepoint. - INVALID_CODEPOINT = 6, + INVALID_CODEPOINT = 5, // The utf8 sequence contains an overlong encoding of a utf8 codepoint. - OVERLONG_ENCODING = 7, + OVERLONG_ENCODING = 6, } // A type representing the result of decoding of utf8-encoded codepoint. @@ -1041,6 +1055,9 @@ file_dialog_result :: struct { selection: str8_list, } +// An opaque handle identifying a window. +window :: distinct u64 + @(default_calling_convention="c", link_prefix="oc_") foreign { // Set the title of the application's window. @@ -1051,8 +1068,93 @@ foreign { request_quit :: proc() --- // Convert a scancode to a keycode, according to current keyboard layout. scancode_to_keycode :: proc(scanCode: scan_code) -> key_code --- +} + +//////////////////////////////////////////////////////////////////////////////// +// Application user input. +//////////////////////////////////////////////////////////////////////////////// + +key_state :: struct { + lastUpdate: u64, + transitionCount: u32, + repeatCount: u32, + down: bool, + sysClicked: bool, + sysDoubleClicked: bool, + sysTripleClicked: bool, +} + +keyboard_state :: struct { + keys: [349]key_state, + mods: keymod_flags, +} + +mouse_state :: struct { + lastUpdate: u64, + posValid: bool, + pos: vec2, + delta: vec2, + wheel: vec2, + using _: struct #raw_union { + buttons: [5]key_state, + using _: struct { + left: key_state, + right: key_state, + middle: key_state, + ext1: key_state, + ext2: key_state, + }, + }, +} + +BACKING_SIZE :: 64 + +text_state :: struct { + lastUpdate: u64, + backing: [64]utf32, + codePoints: str32, +} + +clipboard_state :: struct { + lastUpdate: u64, + pastedText: str8, +} + +input_state :: struct { + frameCounter: u64, + keyboard: keyboard_state, + mouse: mouse_state, + text: text_state, + clipboard: clipboard_state, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + input_process_event :: proc(arena: ^arena, state: ^input_state, event: ^event) --- + input_next_frame :: proc(state: ^input_state) --- + key_down :: proc(state: ^input_state, key: key_code) -> bool --- + key_press_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_release_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_repeat_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_down_scancode :: proc(state: ^input_state, key: scan_code) -> bool --- + key_press_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + key_release_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + key_repeat_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + mouse_down :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_pressed :: proc(state: ^input_state, button: mouse_button) -> u8 --- + mouse_released :: proc(state: ^input_state, button: mouse_button) -> u8 --- + mouse_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_double_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_position :: proc(state: ^input_state) -> vec2 --- + mouse_delta :: proc(state: ^input_state) -> vec2 --- + mouse_wheel :: proc(state: ^input_state) -> vec2 --- + input_text_utf32 :: proc(arena: ^arena, state: ^input_state) -> str32 --- + input_text_utf8 :: proc(arena: ^arena, state: ^input_state) -> str8 --- // Put a string in the clipboard. clipboard_set_string :: proc(string: str8) --- + clipboard_pasted :: proc(state: ^input_state) -> bool --- + clipboard_pasted_text :: proc(state: ^input_state) -> str8 --- + key_mods :: proc(state: ^input_state) -> keymod_flags --- } //////////////////////////////////////////////////////////////////////////////// @@ -1070,7 +1172,7 @@ file :: distinct u64 // Flags for the `oc_file_open()` function. file_open_flag :: enum u16 { // Open the file in 'append' mode. All writes append data at the end of the file. - APPEND = 1, + APPEND = 0, // Truncate the file to 0 bytes when opening. TRUNCATE, // Create the file if it does not exist. @@ -1087,7 +1189,7 @@ file_open_flags :: bit_set[file_open_flag; u16] // This enum describes the access permissions of a file handle. file_access_flag :: enum u16 { // The file handle can be used for reading from the file. - READ = 1, + READ = 0, // The file handle can be used for writing to the file. WRITE, } @@ -1239,7 +1341,7 @@ file_type :: enum u32 { // A type describing file permissions. file_perm_flag :: enum u16 { - OTHER_EXEC = 1, + OTHER_EXEC = 0, OTHER_WRITE, OTHER_READ, GROUP_EXEC, @@ -1269,6 +1371,18 @@ file_status :: struct { modificationDate: datestamp, } +// An type describing a list of enumerated files in a given directory. +file_list :: struct { + list: list, + eltCount: u64, +} + +file_listdir_elt :: struct { + listElt: list_elt, + basename: str8, + type: file_type, +} + @(default_calling_convention="c", link_prefix="oc_") foreign { // Send a single I/O request and wait for its completion. @@ -1296,6 +1410,7 @@ foreign { file_get_status :: proc(file: file) -> file_status --- file_size :: proc(file: file) -> u64 --- file_open_with_request :: proc(path: str8, rights: file_access, flags: file_open_flags) -> file --- + file_listdir :: proc(arena: ^arena, directory: str8) -> file_list --- } //////////////////////////////////////////////////////////////////////////////// @@ -1700,87 +1815,6 @@ foreign { // Graphical User Interface API. //////////////////////////////////////////////////////////////////////////////// -key_state :: struct { - lastUpdate: u64, - transitionCount: u32, - repeatCount: u32, - down: bool, - sysClicked: bool, - sysDoubleClicked: bool, - sysTripleClicked: bool, -} - -keyboard_state :: struct { - keys: [349]key_state, - mods: keymod_flags, -} - -mouse_state :: struct { - lastUpdate: u64, - posValid: bool, - pos: vec2, - delta: vec2, - wheel: vec2, - using _: struct #raw_union { - buttons: [5]key_state, - using _: struct { - left: key_state, - right: key_state, - middle: key_state, - ext1: key_state, - ext2: key_state, - }, - }, -} - -BACKING_SIZE :: 64 - -text_state :: struct { - lastUpdate: u64, - backing: [64]utf32, - codePoints: str32, -} - -clipboard_state :: struct { - lastUpdate: u64, - pastedText: str8, -} - -input_state :: struct { - frameCounter: u64, - keyboard: keyboard_state, - mouse: mouse_state, - text: text_state, - clipboard: clipboard_state, -} - -@(default_calling_convention="c", link_prefix="oc_") -foreign { - input_process_event :: proc(arena: ^arena, state: ^input_state, event: ^event) --- - input_next_frame :: proc(state: ^input_state) --- - key_down :: proc(state: ^input_state, key: key_code) -> bool --- - key_press_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_release_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_repeat_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_down_scancode :: proc(state: ^input_state, key: scan_code) -> bool --- - key_press_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - key_release_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - key_repeat_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - mouse_down :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_pressed :: proc(state: ^input_state, button: mouse_button) -> u8 --- - mouse_released :: proc(state: ^input_state, button: mouse_button) -> u8 --- - mouse_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_double_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_position :: proc(state: ^input_state) -> vec2 --- - mouse_delta :: proc(state: ^input_state) -> vec2 --- - mouse_wheel :: proc(state: ^input_state) -> vec2 --- - input_text_utf32 :: proc(arena: ^arena, state: ^input_state) -> str32 --- - input_text_utf8 :: proc(arena: ^arena, state: ^input_state) -> str8 --- - clipboard_pasted :: proc(state: ^input_state) -> bool --- - clipboard_pasted_text :: proc(state: ^input_state) -> str8 --- - key_mods :: proc(state: ^input_state) -> keymod_flags --- -} - //////////////////////////////////////////////////////////////////////////////// // Graphical User Interface Core API. //////////////////////////////////////////////////////////////////////////////// @@ -1854,11 +1888,11 @@ ui_attribute_mask :: enum u32 { SIZE_WIDTH = 1, SIZE_HEIGHT = 2, LAYOUT_AXIS = 4, - LAYOUT_ALIGN_X = 64, - LAYOUT_ALIGN_Y = 128, - LAYOUT_SPACING = 32, LAYOUT_MARGIN_X = 8, LAYOUT_MARGIN_Y = 16, + LAYOUT_SPACING = 32, + LAYOUT_ALIGN_X = 64, + LAYOUT_ALIGN_Y = 128, FLOATING_X = 256, FLOATING_Y = 512, FLOAT_TARGET_X = 1024, @@ -1870,10 +1904,10 @@ ui_attribute_mask :: enum u32 { COLOR = 65536, BG_COLOR = 131072, BORDER_COLOR = 262144, - BORDER_SIZE = 2097152, - ROUNDNESS = 4194304, FONT = 524288, FONT_SIZE = 1048576, + BORDER_SIZE = 2097152, + ROUNDNESS = 4194304, DRAW_MASK = 8388608, ANIMATION_TIME = 16777216, ANIMATION_MASK = 33554432, @@ -1895,6 +1929,7 @@ ui_box_size :: [2]ui_size ui_box_floating :: [2]bool +// These bits *disable* the corresponding element when they're set. ui_draw_mask :: enum u32 { BACKGROUND = 1, BORDER = 2, diff --git a/core/sys/posix/arpa_inet.odin b/core/sys/posix/arpa_inet.odin index ac850ed49..566c75155 100644 --- a/core/sys/posix/arpa_inet.odin +++ b/core/sys/posix/arpa_inet.odin @@ -1,12 +1,10 @@ -#+build darwin, linux, freebsd, openbsd, netbsd, haiku +#+build darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" -} else when ODIN_OS == .Haiku { - foreign import lib "system:network" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -50,7 +48,6 @@ foreign lib { af: AF, // INET or INET6 src: cstring, dst: rawptr, // either ^in_addr or ^in_addr6 - size: socklen_t, // size_of(dst^) ) -> pton_result --- } diff --git a/core/sys/posix/dirent.odin b/core/sys/posix/dirent.odin index 1394f6b9e..f6cef70ce 100644 --- a/core/sys/posix/dirent.odin +++ b/core/sys/posix/dirent.odin @@ -1,10 +1,10 @@ -#+build darwin, linux, freebsd, openbsd, netbsd, haiku +#+build darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -227,15 +227,4 @@ when ODIN_OS == .Darwin { d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */ } -} else when ODIN_OS == .Haiku { - - dirent :: struct { - d_dev: dev_t, /* device */ - d_pdev: dev_t, /* parent device (only for queries) */ - d_ino: ino_t, /* inode number */ - d_pino: ino_t, /* parent inode (only for queries) */ - d_reclen: c.ushort, /* length of this record, not the name */ - d_name: [0]c.char `fmt:"s,0"`, /* name of the entry (null byte terminated) */ - } - } diff --git a/core/sys/posix/dlfcn.odin b/core/sys/posix/dlfcn.odin index e84b29d79..6c96b0079 100644 --- a/core/sys/posix/dlfcn.odin +++ b/core/sys/posix/dlfcn.odin @@ -4,11 +4,14 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { foreign import lib "system:dl" } else { - foreign import lib "system:c" + foreign import lib { + "system:c", + "system:dl", + } } // dlfcn.h - dynamic linking diff --git a/core/sys/posix/errno.odin b/core/sys/posix/errno.odin index bb4e9e045..ba77e8aaf 100644 --- a/core/sys/posix/errno.odin +++ b/core/sys/posix/errno.odin @@ -1,4 +1,4 @@ -#+build windows, darwin, linux, freebsd, openbsd, netbsd, haiku +#+build windows, darwin, linux, freebsd, openbsd, netbsd package posix import "core:c" @@ -536,92 +536,4 @@ when ODIN_OS == .Darwin { ETXTBSY :: 139 EWOULDBLOCK :: 140 EXDEV :: 18 -} else when ODIN_OS == .Haiku { - _HAIKU_USE_POSITIVE_POSIX_ERRORS :: libc._HAIKU_USE_POSITIVE_POSIX_ERRORS - _POSIX_ERROR_FACTOR :: libc._POSIX_ERROR_FACTOR - - _GENERAL_ERROR_BASE :: min(c.int) - _OS_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x1000 - _STORAGE_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x6000 - _POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000 - - EIO :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 1) // B_IO_ERROR - EACCES :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 2) // B_PERMISSION_DENIED - EINVAL :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 5) // B_BAD_VALUE - ETIMEDOUT :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 9) // B_TIMED_OUT - EINTR :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 10) // B_INTERRUPTED - EAGAIN :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* SysV compatibility */ - EWOULDBLOCK :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* BSD compatibility */ - EBUSY :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 14) // B_BUSY - EPERM :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 15) // B_NOT_ALLOWED - EFAULT :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x301) // B_BAD_ADDRESS - ENOEXEC :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x302) // B_NOT_AN_EXECUTABLE - EBADF :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 0) // B_FILE_ERROR - EEXIST :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 2) // B_FILE_EXISTS - ENOENT :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 3) // B_ENTRY_NOT_FOUND - ENAMETOOLONG :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 4) // B_NAME_TOO_LONG - ENOTDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 5) // B_NOT_A_DIRECTORY - ENOTEMPTY :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 6) // B_DIRECTORY_NOT_EMPTY - ENOSPC :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 7) // B_DEVICE_FULL - EROFS :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 8) // B_READ_ONLY_DEVICE - EISDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 9) // B_IS_A_DIRECTORY - EMFILE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 10) // B_NO_MORE_FDS - EXDEV :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 11) // B_CROSS_DEVICE_LINK - ELOOP :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 12) // B_LINK_LIMIT - EPIPE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 13) // B_BUSTED_PIPE - ENOMEM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 0) when _HAIKU_USE_POSITIVE_POSIX_ERRORS else (_GENERAL_ERROR_BASE + 0) // B_NO_MEMORY - E2BIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 1) - ECHILD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 2) - EDEADLK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 3) - EFBIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 4) - EMLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 5) - ENFILE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 6) - ENODEV :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 7) - ENOLCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 8) - ENOSYS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 9) - ENOTTY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 10) - ENXIO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 11) - ESPIPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 12) - ESRCH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 13) - EPROTOTYPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 18) - EPROTONOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 19) - EAFNOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 21) - EADDRINUSE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 22) - EADDRNOTAVAIL :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 23) - ENETDOWN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 24) - ENETUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 25) - ENETRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 26) - ECONNABORTED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 27) - ECONNRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 28) - EISCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 29) - ENOTCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 30) - ECONNREFUSED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 32) - EHOSTUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 33) - ENOPROTOOPT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 34) - ENOBUFS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 35) - EINPROGRESS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 36) - EALREADY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 37) - ENOMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 39) - ESTALE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 40) - EOVERFLOW :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 41) - EMSGSIZE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 42) - EOPNOTSUPP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 43) - ENOTSOCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 44) - EBADMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 46) - ECANCELED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 47) - EDESTADDRREQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 48) - EDQUOT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 49) - EIDRM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 50) - EMULTIHOP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 51) - ENODATA :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 52) - ENOLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 53) - ENOSR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 54) - ENOSTR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 55) - ENOTSUP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 56) - EPROTO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 57) - ETIME :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 58) - ETXTBSY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 59) - ENOTRECOVERABLE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 61) - EOWNERDEAD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 62) } - diff --git a/core/sys/posix/fcntl.odin b/core/sys/posix/fcntl.odin index bc0b5b5ba..05a084a8e 100644 --- a/core/sys/posix/fcntl.odin +++ b/core/sys/posix/fcntl.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, openbsd, freebsd, netbsd, haiku +#+build linux, darwin, openbsd, freebsd, netbsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -70,7 +70,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]] */ - openat :: proc(fd: FD, path: cstring, flags: O_Flags, mode: mode_t = {}) -> FD --- + openat :: proc(fd: FD, path: cstring, flags: O_Flags, #c_vararg mode: ..mode_t) -> FD --- } FCNTL_Cmd :: enum c.int { @@ -409,72 +409,6 @@ when ODIN_OS == .Darwin { l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ } -} else when ODIN_OS == .Haiku { - - off_t :: distinct c.int64_t - pid_t :: distinct c.int32_t - - /* commands that can be passed to fcntl() */ - F_DUPFD :: 0x0001 /* duplicate fd */ - F_GETFD :: 0x0002 /* get fd flags */ - F_SETFD :: 0x0004 /* set fd flags */ - F_GETFL :: 0x0008 /* get file status flags and access mode */ - F_SETFL :: 0x0010 /* set file status flags */ - F_GETLK :: 0x0020 /* get locking information */ - F_SETLK :: 0x0080 /* set locking information */ - F_SETLKW :: 0x0100 /* as above, but waits if blocked */ - F_DUPFD_CLOEXEC :: 0x0200 /* duplicate fd with close on exec set */ - F_GETOWN :: -1 // NOTE: Not supported. - F_SETOWN :: -1 // NOTE: Not supported. - - /* advisory locking types */ - F_RDLCK :: 0x0040 /* read or shared lock */ - F_UNLCK :: 0x0200 /* unlock */ - F_WRLCK :: 0x0400 /* write or exclusive lock */ - - /* file descriptor flags for fcntl() */ - FD_CLOEXEC :: 1 - - O_CLOEXEC :: 0x00000040 - O_CREAT :: 0x0200 - O_DIRECTORY :: 0x00200000 - O_EXCL :: 0x0100 - O_NOCTTY :: 0x1000 - O_NOFOLLOW :: 0x00080000 - O_TRUNC :: 0x0400 - - _O_TTY_INIT :: 0 - O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers - - O_APPEND :: 0x0800 - O_DSYNC :: 0x040000 - O_NONBLOCK :: 0x0080 - O_SYNC :: 0x010000 - O_RSYNC :: 0x020000 - - O_EXEC :: 0x04000000 // NOTE: not defined in the headers - O_RDONLY :: 0 - O_RDWR :: 0x0002 - O_WRONLY :: 0x0001 - - _O_SEARCH :: 0 - O_SEARCH :: O_Flags{} // NOTE: not defined in the headers - - AT_FDCWD: FD: -100 - - AT_EACCESS :: 0x08 - AT_SYMLINK_NOFOLLOW :: 0x01 - AT_SYMLINK_FOLLOW :: 0x02 - AT_REMOVEDIR :: 0x04 - - flock :: struct { - l_type: Lock_Type, /* [PSX] type of lock */ - l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ - l_start: off_t, /* [PSX] relative offset in bytes */ - l_len: off_t, /* [PSX] size; if 0 then until EOF */ - l_pid: pid_t, /* [PSX] process ID of the process holding the lock */ - } - } else when ODIN_OS == .Linux { off_t :: distinct c.int64_t diff --git a/core/sys/posix/fnmatch.odin b/core/sys/posix/fnmatch.odin index 04c3d2888..ff0cfa6ea 100644 --- a/core/sys/posix/fnmatch.odin +++ b/core/sys/posix/fnmatch.odin @@ -1,10 +1,10 @@ -#+build darwin, linux, openbsd, freebsd, netbsd, haiku +#+build darwin, linux, openbsd, freebsd, netbsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -46,7 +46,7 @@ FNM_Flag_Bits :: enum c.int { } FNM_Flags :: bit_set[FNM_Flag_Bits; c.int] -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { FNM_NOMATCH :: 1 diff --git a/core/sys/posix/glob.odin b/core/sys/posix/glob.odin index fb90b7546..88e0cffc7 100644 --- a/core/sys/posix/glob.odin +++ b/core/sys/posix/glob.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -109,7 +109,7 @@ when ODIN_OS == .Darwin { GLOB_NOMATCH :: -3 GLOB_NOSPACE :: -1 -} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku { +} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { glob_t :: struct { gl_pathc: c.size_t, /* [PSX] count of paths matched by pattern */ @@ -134,7 +134,7 @@ when ODIN_OS == .Darwin { GLOB_ERR :: 0x0004 GLOB_MARK :: 0x0008 GLOB_NOCHECK :: 0x0010 - GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD || ODIN_OS == .Haiku else 0x0100 + GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD else 0x0100 GLOB_NOSORT :: 0x0020 GLOB_ABORTED :: -2 diff --git a/core/sys/posix/grp.odin b/core/sys/posix/grp.odin index 3694308a0..0b3d70fec 100644 --- a/core/sys/posix/grp.odin +++ b/core/sys/posix/grp.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -115,7 +115,7 @@ foreign lib { getgrnam_r :: proc(name: cstring, grp: ^group, buffer: [^]byte, bufsize: c.size_t, result: ^^group) -> Errno --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Linux { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { gid_t :: distinct c.uint32_t diff --git a/core/sys/posix/langinfo.odin b/core/sys/posix/langinfo.odin index 1fddfe280..bd4afbacb 100644 --- a/core/sys/posix/langinfo.odin +++ b/core/sys/posix/langinfo.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -143,7 +143,7 @@ nl_item :: enum nl_item_t { CRNCYSTR = CRNCYSTR, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD { // NOTE: declared with `_t` so we can enumerate the real `nl_info`. nl_item_t :: distinct c.int @@ -210,7 +210,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku { YESEXPR :: 52 NOEXPR :: 53 - CRNCYSTR :: 54 when ODIN_OS == .Haiku else 56 + CRNCYSTR :: 56 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { diff --git a/core/sys/posix/libgen.odin b/core/sys/posix/libgen.odin index 2354bf70d..5c7fa1536 100644 --- a/core/sys/posix/libgen.odin +++ b/core/sys/posix/libgen.odin @@ -1,8 +1,8 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/locale.odin b/core/sys/posix/locale.odin index bbe10e803..5b8d7c216 100644 --- a/core/sys/posix/locale.odin +++ b/core/sys/posix/locale.odin @@ -1,4 +1,4 @@ -#+build windows, linux, darwin, netbsd, openbsd, freebsd, haiku +#+build windows, linux, darwin, netbsd, openbsd, freebsd package posix import "core:c/libc" diff --git a/core/sys/posix/monetary.odin b/core/sys/posix/monetary.odin index a444bff09..556defa0f 100644 --- a/core/sys/posix/monetary.odin +++ b/core/sys/posix/monetary.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/net_if.odin b/core/sys/posix/net_if.odin index 774d11b72..182a049d1 100644 --- a/core/sys/posix/net_if.odin +++ b/core/sys/posix/net_if.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/netdb.odin b/core/sys/posix/netdb.odin index ff1cb9d4c..4fe233711 100644 --- a/core/sys/posix/netdb.odin +++ b/core/sys/posix/netdb.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -319,7 +319,7 @@ Info_Errno :: enum c.int { OVERFLOW = EAI_OVERFLOW, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { hostent :: struct { h_name: cstring, /* [PSX] official name of host */ @@ -444,23 +444,6 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS NI_NUMERICSCOPE :: 0x100 NI_DGRAM :: 16 - } else when ODIN_OS == .Haiku { - - AI_PASSIVE :: 0x001 - AI_CANONNAME :: 0x002 - AI_NUMERICHOST :: 0x004 - AI_NUMERICSERV :: 0x008 - AI_V4MAPPED :: 0x800 - AI_ALL :: 0x100 - AI_ADDRCONFIG :: 0x400 - - NI_NOFQDN :: 0x01 - NI_NUMERICHOST :: 0x02 - NI_NAMEREQD :: 0x04 - NI_NUMERICSERV :: 0x08 - NI_DGRAM :: 0x10 - NI_NUMERICSCOPE :: 0x40 - } when ODIN_OS == .OpenBSD { diff --git a/core/sys/posix/netinet_in.odin b/core/sys/posix/netinet_in.odin index ec05915de..9295f9913 100644 --- a/core/sys/posix/netinet_in.odin +++ b/core/sys/posix/netinet_in.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -31,31 +31,20 @@ Protocol :: enum c.int { UDP = IPPROTO_UDP, } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { in_addr :: struct { s_addr: in_addr_t, /* [PSX] big endian address */ } - when ODIN_OS == .Haiku { - in6_addr :: struct #packed { - using _: struct #raw_union { - s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ - __u6_addr16: [8]c.uint16_t, - __u6_addr32: [4]c.uint32_t, - }, - } - } else { - in6_addr :: struct { - using _: struct #raw_union { - s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ - __u6_addr16: [8]c.uint16_t, - __u6_addr32: [4]c.uint32_t, - }, - } + in6_addr :: struct { + using _: struct #raw_union { + s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ + __u6_addr16: [8]c.uint16_t, + __u6_addr32: [4]c.uint32_t, + }, } - when ODIN_OS == .Linux { sockaddr_in :: struct { @@ -88,13 +77,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS } else { - when ODIN_OS == .Haiku { - @(private) - _SIN_ZEROSIZE :: 24 - } else { - @(private) - _SIN_ZEROSIZE :: 8 - } + @(private) + _SIN_ZEROSIZE :: 8 sockaddr_in :: struct { sin_len: c.uint8_t, @@ -118,23 +102,13 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ipv6mr_interface: c.uint, /* [PSX] interface index */ } - when ODIN_OS == .Haiku { - IPV6_JOIN_GROUP :: 28 - IPV6_LEAVE_GROUP :: 29 - IPV6_MULTICAST_HOPS :: 25 - IPV6_MULTICAST_IF :: 24 - IPV6_MULTICAST_LOOP :: 26 - IPV6_UNICAST_HOPS :: 27 - IPV6_V6ONLY :: 30 - } else { - IPV6_JOIN_GROUP :: 12 - IPV6_LEAVE_GROUP :: 13 - IPV6_MULTICAST_HOPS :: 10 - IPV6_MULTICAST_IF :: 9 - IPV6_MULTICAST_LOOP :: 11 - IPV6_UNICAST_HOPS :: 4 - IPV6_V6ONLY :: 27 - } + IPV6_JOIN_GROUP :: 12 + IPV6_LEAVE_GROUP :: 13 + IPV6_MULTICAST_HOPS :: 10 + IPV6_MULTICAST_IF :: 9 + IPV6_MULTICAST_LOOP :: 11 + IPV6_UNICAST_HOPS :: 4 + IPV6_V6ONLY :: 27 } diff --git a/core/sys/posix/poll.odin b/core/sys/posix/poll.odin index 44ec767a6..5a2628096 100644 --- a/core/sys/posix/poll.odin +++ b/core/sys/posix/poll.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -6,7 +6,7 @@ import "base:intrinsics" import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -25,7 +25,7 @@ foreign lib { poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int --- } -when ODIN_OS == .Haiku { +when ODIN_OS == .Linux { nfds_t :: c.ulong } else { nfds_t :: c.uint @@ -57,7 +57,7 @@ Poll_Event_Bits :: enum c.short { } Poll_Event :: bit_set[Poll_Event_Bits; c.short] -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { pollfd :: struct { fd: FD, /* [PSX] the following descriptor being polled */ @@ -65,35 +65,17 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS revents: Poll_Event, /* [PSX] the output event flags */ } - when ODIN_OS == .Haiku { + POLLIN :: 0x0001 + POLLRDNORM :: 0x0040 + POLLRDBAND :: 0x0080 + POLLPRI :: 0x0002 + POLLOUT :: 0x0004 + POLLWRNORM :: POLLOUT + POLLWRBAND :: 0x0100 - POLLIN :: 0x0001 /* any readable data available */ - POLLOUT :: 0x0002 /* file descriptor is writeable */ - POLLRDNORM :: POLLIN - POLLWRNORM :: POLLOUT - POLLRDBAND :: 0x0008 /* priority readable data */ - POLLWRBAND :: 0x0010 /* priority data can be written */ - POLLPRI :: 0x0020 /* high priority readable data */ - - POLLERR :: 0x0004 /* errors pending */ - POLLHUP :: 0x0080 /* disconnected */ - POLLNVAL :: 0x1000 /* invalid file descriptor */ - - } else { - - POLLIN :: 0x0001 - POLLRDNORM :: 0x0040 - POLLRDBAND :: 0x0080 - POLLPRI :: 0x0002 - POLLOUT :: 0x0004 - POLLWRNORM :: POLLOUT - POLLWRBAND :: 0x0100 - - POLLERR :: 0x0008 - POLLHUP :: 0x0010 - POLLNVAL :: 0x0020 - - } + POLLERR :: 0x0008 + POLLHUP :: 0x0010 + POLLNVAL :: 0x0020 } else when ODIN_OS == .Linux { diff --git a/core/sys/posix/posix.odin b/core/sys/posix/posix.odin index d56217407..49353e875 100644 --- a/core/sys/posix/posix.odin +++ b/core/sys/posix/posix.odin @@ -1,5 +1,5 @@ /* -Raw bindings for most POSIX APIs. +Raw bindings for most `POSIX` APIs. Targets glibc and musl compatibility. @@ -31,7 +31,7 @@ Unimplemented headers: - iso646.h | Impossible - math.h | See `core:c/libc` - mqueue.h | Targets don't seem to have implemented it -- regex.h | See `core:regex` +- regex.h | See `core:text/regex` - search.h | Not useful in Odin - spawn.h | Use `fork`, `execve`, etc. - stdarg.h | See `core:c/libc` @@ -53,6 +53,8 @@ import "base:intrinsics" import "core:c" +IS_SUPPORTED :: _IS_SUPPORTED + result :: enum c.int { // Use `errno` and `strerror` for more information. FAIL = -1, diff --git a/core/sys/posix/posix_other.odin b/core/sys/posix/posix_other.odin new file mode 100644 index 000000000..5ffedc953 --- /dev/null +++ b/core/sys/posix/posix_other.odin @@ -0,0 +1,9 @@ +#+build !linux +#+build !darwin +#+build !netbsd +#+build !openbsd +#+build !freebsd +package posix + +_IS_SUPPORTED :: false + diff --git a/core/sys/posix/posix_unix.odin b/core/sys/posix/posix_unix.odin new file mode 100644 index 000000000..1aa251099 --- /dev/null +++ b/core/sys/posix/posix_unix.odin @@ -0,0 +1,5 @@ +#+build linux, darwin, netbsd, openbsd, freebsd +package posix + +_IS_SUPPORTED :: true + diff --git a/core/sys/posix/pthread.odin b/core/sys/posix/pthread.odin index 36a3cd7b3..84073c26f 100644 --- a/core/sys/posix/pthread.odin +++ b/core/sys/posix/pthread.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux { foreign import lib "system:pthread" } else { @@ -124,7 +124,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getscope.html ]] */ - pthread_attr_setscope :: proc(attr: ^pthread_attr_t, contentionscope: ^Thread_Scope) -> Errno --- + pthread_attr_setscope :: proc(attr: ^pthread_attr_t, contentionscope: Thread_Scope) -> Errno --- /* Get the area of storage to be used for the created thread's stack. @@ -400,7 +400,7 @@ when ODIN_OS == .Darwin { PTHREAD_SCOPE_PROCESS :: 2 PTHREAD_SCOPE_SYSTEM :: 1 - pthread_t :: distinct u64 + pthread_t :: distinct rawptr pthread_attr_t :: struct { __sig: c.long, @@ -554,56 +554,6 @@ when ODIN_OS == .Darwin { sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */ } -} else when ODIN_OS == .Haiku { - - PTHREAD_CANCEL_ASYNCHRONOUS :: 2 - PTHREAD_CANCEL_DEFERRED :: 0 - - PTHREAD_CANCEL_DISABLE :: 1 - PTHREAD_CANCEL_ENABLE :: 0 - - PTHREAD_CANCELED :: rawptr(uintptr(1)) - - PTHREAD_CREATE_DETACHED :: 0x1 - PTHREAD_CREATE_JOINABLE :: 0 - - PTHREAD_EXPLICIT_SCHED :: 0 - PTHREAD_INHERIT_SCHED :: 0x4 - - PTHREAD_PRIO_INHERIT :: 1 - PTHREAD_PRIO_NONE :: 0 - PTHREAD_PRIO_PROTECT :: 2 - - PTHREAD_PROCESS_SHARED :: 1 - PTHREAD_PROCESS_PRIVATE :: 0 - - PTHREAD_SCOPE_PROCESS :: 0 - PTHREAD_SCOPE_SYSTEM :: 0x2 - - pthread_t :: distinct rawptr - pthread_attr_t :: distinct rawptr - pthread_key_t :: distinct c.int - - pthread_mutex_t :: struct { - flags: u32, - lock: i32, - unused: i32, - owner: i32, - owner_count: i32, - } - - pthread_cond_t :: struct { - flags: u32, - unused: i32, - mutex: ^pthread_mutex_t, - waiter_count: i32, - lock: i32, - } - - sched_param :: struct { - sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */ - } - } else when ODIN_OS == .Linux { PTHREAD_CANCEL_DEFERRED :: 0 @@ -632,8 +582,16 @@ when ODIN_OS == .Darwin { pthread_t :: distinct c.ulong + when ODIN_ARCH == .arm64 { + @(private) + __SIZEOF_PTHREAD_ATTR_T :: 64 + } else { + @(private) + __SIZEOF_PTHREAD_ATTR_T :: 56 + } + pthread_attr_t :: struct #raw_union { - __size: [56]c.char, // NOTE: may be smaller depending on libc or arch, but never larger. + __size: [__SIZEOF_PTHREAD_ATTR_T]c.char, __align: c.long, } diff --git a/core/sys/posix/pwd.odin b/core/sys/posix/pwd.odin index 75d15c899..5069aeb9f 100644 --- a/core/sys/posix/pwd.odin +++ b/core/sys/posix/pwd.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -176,16 +176,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { pw_shell: cstring, /* Shell program. */ } -} else when ODIN_OS == .Haiku { - - passwd :: struct { - pw_name: cstring, /* [PSX] user name */ - pw_passwd: cstring, /* encrypted password */ - pw_uid: uid_t, /* [PSX] user uid */ - pw_gid: gid_t, /* [PSX] user gid */ - pw_dir: cstring, /* Home directory. */ - pw_shell: cstring, /* Shell program. */ - pw_gecos: cstring, /* Real name. */ - } - } diff --git a/core/sys/posix/sched.odin b/core/sys/posix/sched.odin index 82b335653..a8b509cc6 100644 --- a/core/sys/posix/sched.odin +++ b/core/sys/posix/sched.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -101,11 +101,4 @@ when ODIN_OS == .Darwin { SCHED_FIFO :: 1 SCHED_RR :: 2 -} else when ODIN_OS == .Haiku { - - SCHED_FIFO :: 1 - SCHED_RR :: 2 - // SCHED_SPORADIC :: 3 NOTE: not a thing on freebsd, netbsd and probably others, leaving it out - SCHED_OTHER :: 4 - } diff --git a/core/sys/posix/setjmp.odin b/core/sys/posix/setjmp.odin index 926dbd3ad..a26bdb93e 100644 --- a/core/sys/posix/setjmp.odin +++ b/core/sys/posix/setjmp.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/signal.odin b/core/sys/posix/signal.odin index d2f737946..603c50d71 100644 --- a/core/sys/posix/signal.odin +++ b/core/sys/posix/signal.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -6,7 +6,7 @@ import "base:intrinsics" import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -50,7 +50,7 @@ foreign lib { /* Send a signal to a thread. - + As with kill, if sig is 0, only validation (of the pthread_t given) is done and no signal is sent. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html ]] @@ -124,7 +124,7 @@ foreign lib { sigignore :: proc(sig: Signal) -> result --- /* - Removes sig from the signal mask of the calling process and suspend the calling process until + Removes sig from the signal mask of the calling process and suspend the calling process until a signal is received. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]] @@ -166,7 +166,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html ]] */ @(link_name=LSIGPENDING) - sigpending :: proc(set: ^sigset_t) -> result --- + sigpending :: proc(set: ^sigset_t) -> result --- /* Wait for one of the given signals. @@ -333,7 +333,7 @@ SS_Flag_Bits :: enum c.int { SS_Flags :: bit_set[SS_Flag_Bits; c.int] Sig :: enum c.int { - // Resulting set is the union of the current set and the signal set and the complement of + // Resulting set is the union of the current set and the signal set and the complement of // the signal set pointed to by the argument. BLOCK = SIG_BLOCK, // Resulting set is the intersection of the current set and the complement of the signal set @@ -395,6 +395,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -535,6 +536,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -699,6 +701,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -876,6 +879,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -1036,6 +1040,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGPOLL :: 29 SIGSYS :: 31 @@ -1084,7 +1089,7 @@ when ODIN_OS == .Darwin { @(private) __SI_MAX_SIZE :: 128 - when size_of(int) == 8 { + when size_of(int) == 8 { @(private) _pad0 :: struct { _pad0: c.int, @@ -1181,150 +1186,4 @@ when ODIN_OS == .Darwin { SI_MESGQ :: -3 SI_ASYNCIO :: -4 -} else when ODIN_OS == .Haiku { - - // Request that signal be held - SIG_HOLD :: rawptr(uintptr(3)) - - uid_t :: distinct c.uint32_t - sigset_t :: distinct u64 - - SIGHUP :: 1 // hangup -- tty is gone! - //SIGINT :: 2 // interrupt - SIGQUIT :: 3 // `quit' special character typed in tty - //SIGILL :: 4 // illegal instruction - SIGCHLD :: 5 // child process exited - //SIGABRT :: 6 // abort() called, dont' catch - SIGPIPE :: 7 // write to a pipe w/no readers - //SIGFPE :: 8 // floating point exception - SIGKILL :: 9 // kill a team (not catchable) - SIGSTOP :: 10 // suspend a thread (not catchable) - //SIGSEGV :: 11 // segmentation violation (read: invalid pointer) - SIGCONT :: 12 // continue execution if suspended - SIGTSTP :: 13 // `stop' special character typed in tty - SIGALRM :: 14 // an alarm has gone off (see alarm()) - //SIGTERM :: 15 // termination requested - SIGTTIN :: 16 // read of tty from bg process - SIGTTOU :: 17 // write to tty from bg process - SIGUSR1 :: 18 // app defined signal 1 - SIGUSR2 :: 19 // app defined signal 2 - SIGWINCH :: 20 // tty window size changed - SIGKILLTHR :: 21 // be specific: kill just the thread, not team - SIGTRAP :: 22 // Trace/breakpoint trap - SIGPOLL :: 23 // Pollable event - SIGPROF :: 24 // Profiling timer expired - SIGSYS :: 25 // Bad system call - SIGURG :: 26 // High bandwidth data is available at socket - SIGVTALRM :: 27 // Virtual timer expired - SIGXCPU :: 28 // CPU time limit exceeded - SIGXFSZ :: 29 // File size limit exceeded - SIGBUS :: 30 // access to undefined portion of a memory object - - // NOTE: this is actually defined as `sigaction`, but due to the function with the same name - // `_t` has been added. - - sigaction_t :: struct { - using _: struct #raw_union { - sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */ - sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */ - }, - sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */ - sa_flags: SA_Flags, /* [PSX] special flags */ - sa_userdata: rawptr, /* will be passed to the signal handler, BeOS extension */ - } - - SIG_BLOCK :: 1 - SIG_UNBLOCK :: 2 - SIG_SETMASK :: 3 - - SA_NOCLDSTOP :: 0x01 - SA_NOCLDWAIT :: 0x02 - SA_RESETHAND :: 0x04 - SA_NODEFER :: 0x08 - SA_RESTART :: 0x10 - SA_ONSTACK :: 0x20 - SA_SIGINFO :: 0x40 - - SS_ONSTACK :: 1 - SS_DISABLE :: 2 - - MINSIGSTKSZ :: 8192 - SIGSTKSZ :: 16384 - - stack_t :: struct { - ss_sp: rawptr, /* [PSX] stack base or pointer */ - ss_size: c.size_t, /* [PSX] stack size */ - ss_flags: SS_Flags, /* [PSX] flags */ - } - - siginfo_t :: struct { - si_signo: Signal, /* [PSX] signal number */ - si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */ - ill: ILL_Code, - fpe: FPE_Code, - segv: SEGV_Code, - bus: BUS_Code, - trap: TRAP_Code, - chld: CLD_Code, - poll: POLL_Code, - any: Any_Code, - }, - si_errno: Errno, /* [PSX] errno value associated with this signal */ - si_pid: pid_t, /* sending process ID */ - si_uid: uid_t, /* real user ID of sending process */ - si_addr: rawptr, /* address of faulting instruction */ - si_status: c.int, /* exit value or signal */ - si_band: c.long, /* band event for SIGPOLL */ - si_value: sigval, /* signal value */ - } - - /* any signal */ - SI_USER :: 0 /* signal sent by user */ - SI_QUEUE :: 1 /* signal sent by sigqueue() */ - SI_TIMER :: 2 /* signal sent on timer_settime() timeout */ - SI_ASYNCIO :: 3 /* signal sent on asynchronous I/O completion */ - SI_MESGQ :: 4 /* signal sent on arrival of message on empty message queue */ - /* SIGILL */ - ILL_ILLOPC :: 10 /* illegal opcode */ - ILL_ILLOPN :: 11 /* illegal operand */ - ILL_ILLADR :: 12 /* illegal addressing mode */ - ILL_ILLTRP :: 13 /* illegal trap */ - ILL_PRVOPC :: 14 /* privileged opcode */ - ILL_PRVREG :: 15 /* privileged register */ - ILL_COPROC :: 16 /* coprocessor error */ - ILL_BADSTK :: 17 /* internal stack error */ - /* SIGFPE */ - FPE_INTDIV :: 20 /* integer division by zero */ - FPE_INTOVF :: 21 /* integer overflow */ - FPE_FLTDIV :: 22 /* floating-point division by zero */ - FPE_FLTOVF :: 23 /* floating-point overflow */ - FPE_FLTUND :: 24 /* floating-point underflow */ - FPE_FLTRES :: 25 /* floating-point inexact result */ - FPE_FLTINV :: 26 /* invalid floating-point operation */ - FPE_FLTSUB :: 27 /* subscript out of range */ - /* SIGSEGV */ - SEGV_MAPERR :: 30 /* address not mapped to object */ - SEGV_ACCERR :: 31 /* invalid permissions for mapped object */ - /* SIGBUS */ - BUS_ADRALN :: 40 /* invalid address alignment */ - BUS_ADRERR :: 41 /* nonexistent physical address */ - BUS_OBJERR :: 42 /* object-specific hardware error */ - /* SIGTRAP */ - TRAP_BRKPT :: 50 /* process breakpoint */ - TRAP_TRACE :: 51 /* process trace trap. */ - /* SIGCHLD */ - CLD_EXITED :: 60 /* child exited */ - CLD_KILLED :: 61 /* child terminated abnormally without core dump */ - CLD_DUMPED :: 62 /* child terminated abnormally with core dump */ - CLD_TRAPPED :: 63 /* traced child trapped */ - CLD_STOPPED :: 64 /* child stopped */ - CLD_CONTINUED :: 65 /* stopped child continued */ - /* SIGPOLL */ - POLL_IN :: 70 /* input available */ - POLL_OUT :: 71 /* output available */ - POLL_MSG :: 72 /* input message available */ - POLL_ERR :: 73 /* I/O error */ - POLL_PRI :: 74 /* high priority input available */ - POLL_HUP :: 75 /* device disconnected */ - } diff --git a/core/sys/posix/signal_libc.odin b/core/sys/posix/signal_libc.odin index 7a054ddd7..f6a24b762 100644 --- a/core/sys/posix/signal_libc.odin +++ b/core/sys/posix/signal_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, windows, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -9,7 +9,7 @@ import "core:c/libc" when ODIN_OS == .Windows { foreign import lib "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin new file mode 100644 index 000000000..a884b69f3 --- /dev/null +++ b/core/sys/posix/spawn.odin @@ -0,0 +1,21 @@ +#+build linux, darwin, openbsd, freebsd, netbsd +package posix + +when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +foreign lib { + /* + Creates a child process from a provided filepath + spawnp searches directories on the path for the file + + Returns: 0 on success, with the child pid returned in the pid argument, or error values on failure. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html ]] + */ + posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- + posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno --- +} diff --git a/core/sys/posix/stdio.odin b/core/sys/posix/stdio.odin index 24464dfd8..69c8ad3cb 100644 --- a/core/sys/posix/stdio.odin +++ b/core/sys/posix/stdio.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/stdio_libc.odin b/core/sys/posix/stdio_libc.odin index 12706970d..a6921ab7d 100644 --- a/core/sys/posix/stdio_libc.odin +++ b/core/sys/posix/stdio_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -10,7 +10,7 @@ when ODIN_OS == .Windows { "system:legacy_stdio_definitions.lib", } } else when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/stdlib.odin b/core/sys/posix/stdlib.odin index 5f1ae1908..c8d5bec60 100644 --- a/core/sys/posix/stdlib.odin +++ b/core/sys/posix/stdlib.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -6,7 +6,7 @@ import "base:intrinsics" import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/stdlib_libc.odin b/core/sys/posix/stdlib_libc.odin index 6574026f4..749d39f27 100644 --- a/core/sys/posix/stdlib_libc.odin +++ b/core/sys/posix/stdlib_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, windows, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -9,7 +9,7 @@ import "core:c/libc" when ODIN_OS == .Windows { foreign import lib "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -60,7 +60,7 @@ wctomb :: libc.wctomb mbstowcs :: libc.mbstowcs wcstombs :: libc.wcstombs -free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { +free :: #force_inline proc "c" (ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { libc.free(rawptr(ptr)) } diff --git a/core/sys/posix/string.odin b/core/sys/posix/string.odin index 3f9dbb43e..d427b2620 100644 --- a/core/sys/posix/string.odin +++ b/core/sys/posix/string.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/string_libc.odin b/core/sys/posix/string_libc.odin index 72164cc4c..a95ce9370 100644 --- a/core/sys/posix/string_libc.odin +++ b/core/sys/posix/string_libc.odin @@ -1,10 +1,10 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, windows, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Windows { foreign import lib "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/sys_ipc.odin b/core/sys/posix/sys_ipc.odin index bf5938ce1..1c6b2c8de 100644 --- a/core/sys/posix/sys_ipc.odin +++ b/core/sys/posix/sys_ipc.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -111,27 +111,4 @@ when ODIN_OS == .Darwin { IPC_SET :: 1 IPC_STAT :: 2 -} else when ODIN_OS == .Haiku { - - key_t :: distinct c.int32_t - - ipc_perm :: struct { - key: key_t, - uid: uid_t, /* [PSX] owner's user ID */ - gid: gid_t, /* [PSX] owner's group ID */ - cuid: uid_t, /* [PSX] creator's user ID */ - cgid: gid_t, /* [PSX] creator's group ID */ - mode: mode_t, /* [PSX] read/write perms */ - } - - IPC_CREAT :: 0o01000 - IPC_EXCL :: 0o02000 - IPC_NOWAIT :: 0o04000 - - IPC_PRIVATE :: key_t(0) - - IPC_RMID :: 0 - IPC_SET :: 1 - IPC_STAT :: 2 - } diff --git a/core/sys/posix/sys_mman.odin b/core/sys/posix/sys_mman.odin index 0594672ae..1bf3615dc 100644 --- a/core/sys/posix/sys_mman.odin +++ b/core/sys/posix/sys_mman.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -92,7 +92,12 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html ]] */ - shm_open :: proc(name: cstring, oflag: O_Flags, mode: mode_t) -> FD --- + when ODIN_OS == .Darwin { + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shm_open.2.html + shm_open :: proc(name: cstring, oflag: O_Flags, #c_vararg args: ..any) -> FD --- + } else { + shm_open :: proc(name: cstring, oflag: O_Flags, mode: mode_t) -> FD --- + } /* Removes a shared memory object. diff --git a/core/sys/posix/sys_msg.odin b/core/sys/posix/sys_msg.odin index c578b1fc6..6f9f0a84f 100644 --- a/core/sys/posix/sys_msg.odin +++ b/core/sys/posix/sys_msg.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -171,22 +171,4 @@ when ODIN_OS == .Darwin { __unused: [2]c.ulong, } -} else when ODIN_OS == .Haiku { - - msgqnum_t :: distinct c.uint32_t - msglen_t :: distinct c.uint32_t - - MSG_NOERROR :: 0o10000 - - msqid_ds :: struct { - msg_perm: ipc_perm, /* [PSX] operation permission structure */ - msg_qnum: msgqnum_t, /* [PSX] number of messages currently on queue */ - msg_qbytes: msglen_t, /* [PSX] maximum number of bytes allowed on queue */ - msg_lspid: pid_t, /* [PSX] process ID of last msgsnd() */ - msg_lrpid: pid_t, /* [PSX] process ID of last msgrcv() */ - msg_stime: time_t, /* [PSX] time of last msgsnd() */ - msg_rtime: time_t, /* [PSX] time of last msgrcv() */ - msg_ctime: time_t, /* [PSX] time of last change */ - } - } diff --git a/core/sys/posix/sys_resource.odin b/core/sys/posix/sys_resource.odin index ae478382a..28a562955 100644 --- a/core/sys/posix/sys_resource.odin +++ b/core/sys/posix/sys_resource.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -96,21 +96,15 @@ when ODIN_OS == .NetBSD { @(private) LGETRUSAGE :: "getrusage" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { PRIO_PROCESS :: 0 PRIO_PGRP :: 1 PRIO_USER :: 2 - when ODIN_OS == .Haiku { - rlim_t :: distinct c.ulong - } else { - rlim_t :: distinct c.uint64_t - } + rlim_t :: distinct c.uint64_t - when ODIN_OS == .Haiku { - RLIM_INFINITY :: rlim_t(0xFFFFFFFF) - } else when ODIN_OS == .Linux { + when ODIN_OS == .Linux { RLIM_INFINITY :: ~rlim_t(0) } else { RLIM_INFINITY :: (rlim_t(1) << 63) - 1 @@ -151,29 +145,19 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ru_nivcsw: c.long, /* involuntary " */ } - when ODIN_OS == .Haiku { - RLIMIT_CORE :: 0 - RLIMIT_CPU :: 1 - RLIMIT_DATA :: 2 - RLIMIT_FSIZE :: 3 - RLIMIT_NOFILE :: 4 - RLIMIT_STACK :: 5 - RLIMIT_AS :: 6 - } else { - RLIMIT_CORE :: 4 - RLIMIT_CPU :: 0 - RLIMIT_DATA :: 2 - RLIMIT_FSIZE :: 1 - RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8 - RLIMIT_STACK :: 3 + RLIMIT_CORE :: 4 + RLIMIT_CPU :: 0 + RLIMIT_DATA :: 2 + RLIMIT_FSIZE :: 1 + RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8 + RLIMIT_STACK :: 3 - when ODIN_OS == .Linux { - RLIMIT_AS :: 9 - } else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { - RLIMIT_AS :: 5 - } else { - RLIMIT_AS :: 10 - } + when ODIN_OS == .Linux { + RLIMIT_AS :: 9 + } else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { + RLIMIT_AS :: 5 + } else { + RLIMIT_AS :: 10 } } diff --git a/core/sys/posix/sys_select.odin b/core/sys/posix/sys_select.odin index a75e58de6..c9dfbe194 100644 --- a/core/sys/posix/sys_select.odin +++ b/core/sys/posix/sys_select.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "base:intrinsics" @@ -6,7 +6,7 @@ import "base:intrinsics" import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -56,9 +56,9 @@ when ODIN_OS == .NetBSD { LSELECT :: "select" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { - suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long) + suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long) timeval :: struct { tv_sec: time_t, /* [PSX] seconds */ @@ -75,14 +75,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS @(private) ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t) - when ODIN_OS == .Haiku { - fd_set :: struct #align(ALIGN) { - fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t, - } - } else { - fd_set :: struct #align(ALIGN) { - fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t, - } + fd_set :: struct #align(ALIGN) { + fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t, } @(private) diff --git a/core/sys/posix/sys_sem.odin b/core/sys/posix/sys_sem.odin index 069315f87..423af75eb 100644 --- a/core/sys/posix/sys_sem.odin +++ b/core/sys/posix/sys_sem.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -18,7 +18,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/semctl.html ]] */ @(link_name=LSEMCTL) - semctl :: proc(semid: FD, semnum: c.int, cmd: Sem_Cmd, arg: ^semun = nil) -> c.int --- + semctl :: proc(semid: FD, semnum: c.int, cmd: Sem_Cmd, #c_vararg args: ..semun) -> c.int --- /* Returns the semaphore identifier associated with key. @@ -39,6 +39,9 @@ foreign lib { } Sem_Cmd :: enum c.int { + RMID = IPC_RMID, + SET = IPC_SET, + STAT = IPC_STAT, // Returns the value of semncnt. GETNCNT = GETNCNT, // Returns the value of sempid. @@ -137,41 +140,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS SETVAL :: 16 SETALL :: 17 - semid_ds :: struct { - sem_perm: ipc_perm, // [PSX] operation permission structure - sem_otime: time_t, // [PSX] last semop() - __sem_otime_high: c.ulong, - sem_ctime: time_t, // [PSX] last time changed by semctl() - __sem_ctime_high: c.ulong, - sem_nsems: c.ulong, // [PSX] number of semaphores in set - __glibc_reserved3: c.ulong, - __glibc_reserved4: c.ulong, - } - - sembuf :: struct { - sem_num: c.ushort, /* [PSX] semaphore number */ - sem_op: c.short, /* [PSX] semaphore operation */ - sem_flg: c.short, /* [PSX] operation flags */ - } - -} else when ODIN_OS == .Haiku { - - SEM_UNDO :: 10 // undo the operation on exit - - // Commands for `semctl'. - GETPID :: 3 - GETVAL :: 4 - GETALL :: 5 - GETNCNT :: 6 - GETZCNT :: 7 - SETVAL :: 8 - SETALL :: 9 - - semid_ds :: struct { - sem_perm: ipc_perm, // [PSX] operation permission structure - sem_nsems: c.ushort, // [PSX] number of semaphores in set - sem_otime: time_t, // [PSX] last semop() - sem_ctime: time_t, // [PSX] last time changed by semctl() + when ODIN_ARCH == .arm64 { + semid_ds :: struct { + sem_perm: ipc_perm, // [PSX] operation permission structure + sem_otime: time_t, // [PSX] last semop() + sem_ctime: time_t, // [PSX] last time changed by semctl() + sem_nsems: c.ulong, // [PSX] number of semaphores in set + __glibc_reserved3: c.ulong, + __glibc_reserved4: c.ulong, + } + } else { + semid_ds :: struct { + sem_perm: ipc_perm, // [PSX] operation permission structure + sem_otime: time_t, // [PSX] last semop() + __sem_otime_high: c.ulong, + sem_ctime: time_t, // [PSX] last time changed by semctl() + __sem_ctime_high: c.ulong, + sem_nsems: c.ulong, // [PSX] number of semaphores in set + __glibc_reserved3: c.ulong, + __glibc_reserved4: c.ulong, + } } sembuf :: struct { diff --git a/core/sys/posix/sys_shm.odin b/core/sys/posix/sys_shm.odin index 8f3c56b9c..8ee16e5a3 100644 --- a/core/sys/posix/sys_shm.odin +++ b/core/sys/posix/sys_shm.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/sys_socket.odin b/core/sys/posix/sys_socket.odin index 0645893d0..8bc04fa90 100644 --- a/core/sys/posix/sys_socket.odin +++ b/core/sys/posix/sys_socket.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -328,17 +328,12 @@ when ODIN_OS == .NetBSD { @(private) LSOCKET :: "socket" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { socklen_t :: distinct c.uint - when ODIN_OS == .Haiku { - @(private) - _SA_DATASIZE :: 30 - } else { - @(private) - _SA_DATASIZE :: 14 - } + @(private) + _SA_DATASIZE :: 14 when ODIN_OS == .Linux { _sa_family_t :: distinct c.ushort @@ -363,11 +358,6 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS _SS_PAD1SIZE :: 6 @(private) _SS_PAD2SIZE :: 240 - } else when ODIN_OS == .Haiku { - @(private) - _SS_PAD1SIZE :: 6 - @(private) - _SS_PAD2SIZE :: 112 } else when ODIN_OS == .Linux { @(private) _SS_SIZE :: 128 @@ -499,26 +489,6 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS SO_RCVTIMEO :: 66 SO_SNDTIMEO :: 67 - } else when ODIN_OS == .Haiku { - SOL_SOCKET :: -1 - - SO_ACCEPTCONN :: 0x00000001 - SO_BROADCAST :: 0x00000002 - SO_DEBUG :: 0x00000004 - SO_DONTROUTE :: 0x00000008 - SO_ERROR :: 0x40000007 - SO_KEEPALIVE :: 0x00000010 - SO_OOBINLINE :: 0x00000020 - SO_RCVBUF :: 0x40000004 - SO_RCVLOWAT :: 0x40000005 - SO_REUSEADDR :: 0x00000040 - SO_SNDBUF :: 0x40000001 - SO_SNDLOWAT :: 0x40000002 - SO_TYPE :: 0x40000008 - - SO_LINGER :: 0x00000200 - SO_RCVTIMEO :: 0x40000006 - SO_SNDTIMEO :: 0x40000003 } else { SOL_SOCKET :: 0xffff @@ -556,11 +526,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS } // The maximum backlog queue length for listen(). - when ODIN_OS == .Haiku { - SOMAXCONN :: 32 - } else { - SOMAXCONN :: 128 - } + SOMAXCONN :: 128 when ODIN_OS == .Linux { MSG_CTRUNC :: 0x008 @@ -586,18 +552,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS MSG_NOSIGNAL :: 0x00020000 } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { MSG_NOSIGNAL :: 0x0400 - } else when ODIN_OS == .Haiku { - MSG_NOSIGNAL :: 0x800 } } - when ODIN_OS == .Haiku { - AF_INET :: 1 - AF_UNIX :: 9 - } else { - AF_INET :: 2 - AF_UNIX :: 1 - } + AF_INET :: 2 + AF_UNIX :: 1 when ODIN_OS == .Darwin { AF_INET6 :: 30 @@ -607,8 +566,6 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS AF_INET6 :: 24 } else when ODIN_OS == .Linux { AF_INET6 :: 10 - } else when ODIN_OS == .Haiku { - AF_INET6 :: 5 } SHUT_RD :: 0 diff --git a/core/sys/posix/sys_stat.odin b/core/sys/posix/sys_stat.odin index 265356e54..c11c83c42 100644 --- a/core/sys/posix/sys_stat.odin +++ b/core/sys/posix/sys_stat.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -428,36 +428,6 @@ when ODIN_OS == .Darwin { UTIME_NOW :: -2 UTIME_OMIT :: -1 -} else when ODIN_OS == .Haiku { - - dev_t :: distinct c.int32_t - nlink_t :: distinct c.int32_t - _mode_t :: distinct c.uint32_t - blkcnt_t :: distinct c.int64_t - blksize_t :: distinct c.int32_t - ino_t :: distinct c.int64_t - - stat_t :: struct { - st_dev: dev_t, /* [PSX] ID of device containing file */ - st_ino: ino_t, /* [PSX] file serial number */ - st_mode: mode_t, /* [PSX] mode of file */ - st_nlink: nlink_t, /* [PSX] number of hard links */ - st_uid: uid_t, /* [PSX] user ID of the file */ - st_gid: gid_t, /* [PSX] group ID of the file */ - st_size: off_t, /* [PSX] file size, in bytes */ - st_rdev: dev_t, /* [PSX] device ID */ - st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */ - st_atim: timespec, /* [PSX] time of last access */ - st_mtim: timespec, /* [PSX] time of last data modification */ - st_ctim: timespec, /* [PSX] time of last status change */ - st_crtim: timespec, /* [PSX] time of last status change */ - st_type: c.uint32_t, - st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */ - } - - UTIME_NOW :: 1000000000 - UTIME_OMIT :: 1000000001 - } else when ODIN_OS == .Linux { dev_t :: distinct u64 diff --git a/core/sys/posix/sys_statvfs.odin b/core/sys/posix/sys_statvfs.odin index 47c810135..1a332c5ce 100644 --- a/core/sys/posix/sys_statvfs.odin +++ b/core/sys/posix/sys_statvfs.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/sys_time.odin b/core/sys/posix/sys_time.odin index 94eafec85..64cc3d2be 100644 --- a/core/sys/posix/sys_time.odin +++ b/core/sys/posix/sys_time.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -78,15 +78,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS ITIMER_VIRTUAL :: 1 ITIMER_PROF :: 2 -} else when ODIN_OS == .Haiku { - - itimerval :: struct { - it_interval: timeval, /* [PSX] timer interval */ - it_value: timeval, /* [PSX] current value */ - } - - ITIMER_REAL :: 1 - ITIMER_VIRTUAL :: 2 - ITIMER_PROF :: 3 - } diff --git a/core/sys/posix/sys_times.odin b/core/sys/posix/sys_times.odin index 73db489a7..16b9e75f0 100644 --- a/core/sys/posix/sys_times.odin +++ b/core/sys/posix/sys_times.odin @@ -1,8 +1,8 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD { @(private) LTIMES :: "times" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { tms :: struct { tms_utime: clock_t, /* [PSX] user CPU time */ diff --git a/core/sys/posix/sys_uio.odin b/core/sys/posix/sys_uio.odin index 5770f8058..030b99a88 100644 --- a/core/sys/posix/sys_uio.odin +++ b/core/sys/posix/sys_uio.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } @@ -31,7 +31,7 @@ foreign libc { writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { iovec :: struct { iov_base: rawptr, /* [PSX] base address of I/O memory region */ diff --git a/core/sys/posix/sys_un.odin b/core/sys/posix/sys_un.odin index 167bf3ce1..ca5c4ee31 100644 --- a/core/sys/posix/sys_un.odin +++ b/core/sys/posix/sys_un.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -20,12 +20,4 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS sun_path: [108]c.char, /* [PSX] socket pathname */ } -} else when ODIN_OS == .Haiku { - - sockaddr_un :: struct { - sun_len: c.uint8_t, - sun_family: sa_family_t, /* [PSX] address family */ - sun_path: [126]c.char, /* [PSX] socket pathname */ - } - } diff --git a/core/sys/posix/sys_utsname.odin b/core/sys/posix/sys_utsname.odin index 5ea8807a7..f29230c62 100644 --- a/core/sys/posix/sys_utsname.odin +++ b/core/sys/posix/sys_utsname.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -38,10 +38,10 @@ foreign lib { uname :: proc(uname: ^utsname) -> c.int --- } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { @(private) - _SYS_NAMELEN :: 32 when ODIN_OS == .Haiku else 256 + _SYS_NAMELEN :: 256 utsname :: struct { sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */ diff --git a/core/sys/posix/sys_wait.odin b/core/sys/posix/sys_wait.odin index d3bcdfddd..751a184a0 100644 --- a/core/sys/posix/sys_wait.odin +++ b/core/sys/posix/sys_wait.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -443,55 +443,4 @@ when ODIN_OS == .Darwin { return x == 0xffff } -} else when ODIN_OS == .Haiku { - - id_t :: distinct c.int32_t - - WCONTINUED :: 0x04 - WNOHANG :: 0x01 - WUNTRACED :: 0x02 - - WEXITED :: 0x08 - WNOWAIT :: 0x20 - WSTOPPED :: 0x10 - - _P_ALL :: 0 - _P_PID :: 1 - _P_PGID :: 2 - - @(private) - _WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool { - return (x & ~(c.int)(0xff)) == 0 - } - - @(private) - _WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int { - return x & 0xff - } - - @(private) - _WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool { - return ((x >> 8) & 0xff) != 0 - } - - @(private) - _WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { - return Signal((x >> 8) & 0xff) - } - - @(private) - _WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool { - return ((x >> 16) & 0xff) != 0 - } - - @(private) - _WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal { - return Signal((x >> 16) & 0xff) - } - - @(private) - _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool { - return (x & 0x20000) != 0 - } - } diff --git a/core/sys/posix/termios.odin b/core/sys/posix/termios.odin index 4ca884e87..c63cfa797 100644 --- a/core/sys/posix/termios.odin +++ b/core/sys/posix/termios.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -138,31 +138,19 @@ CLocal_Flag_Bits :: enum tcflag_t { } CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t] -when ODIN_OS == .Haiku { - CControl_Flag_Bits :: enum tcflag_t { - // CS7 = log2(CS7), /* 7 bits (default) */ - CS8 = log2(CS8), /* 8 bits */ - CSTOPB = log2(CSTOPB), /* send 2 stop bits */ - CREAD = log2(CREAD), /* enable receiver */ - PARENB = log2(PARENB), /* parity enable */ - PARODD = log2(PARODD), /* odd parity, else even */ - HUPCL = log2(HUPCL), /* hang up on last close */ - CLOCAL = log2(CLOCAL), /* ignore modem status lines */ - } -} else { - CControl_Flag_Bits :: enum tcflag_t { - // CS5 = log2(CS5), /* 5 bits (pseudo) (default) */ - CS6 = log2(CS6), /* 6 bits */ - CS7 = log2(CS7), /* 7 bits */ - CS8 = log2(CS8), /* 8 bits */ - CSTOPB = log2(CSTOPB), /* send 2 stop bits */ - CREAD = log2(CREAD), /* enable receiver */ - PARENB = log2(PARENB), /* parity enable */ - PARODD = log2(PARODD), /* odd parity, else even */ - HUPCL = log2(HUPCL), /* hang up on last close */ - CLOCAL = log2(CLOCAL), /* ignore modem status lines */ - } +CControl_Flag_Bits :: enum tcflag_t { + // CS5 = log2(CS5), /* 5 bits (pseudo) (default) */ + CS6 = log2(CS6), /* 6 bits */ + CS7 = log2(CS7), /* 7 bits */ + CS8 = log2(CS8), /* 8 bits */ + CSTOPB = log2(CSTOPB), /* send 2 stop bits */ + CREAD = log2(CREAD), /* enable receiver */ + PARENB = log2(PARENB), /* parity enable */ + PARODD = log2(PARODD), /* odd parity, else even */ + HUPCL = log2(HUPCL), /* hang up on last close */ + CLOCAL = log2(CLOCAL), /* ignore modem status lines */ } + CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t] // character size mask @@ -610,151 +598,4 @@ when ODIN_OS == .Darwin { TCOOFF :: 0 TCOON :: 1 -} else when ODIN_OS == .Haiku { - - cc_t :: distinct c.uchar - _speed_t :: distinct c.uint32_t - tcflag_t :: distinct c.uint16_t - - // Same as speed_t, but 16-bit. - CSpeed :: enum tcflag_t { - B0 = B0, - B50 = B50, - B75 = B75, - B110 = B110, - B134 = B134, - B150 = B150, - B200 = B200, - B300 = B300, - B600 = B600, - B1200 = B1200, - B1800 = B1800, - B2400 = B2400, - B4800 = B4800, - B9600 = B9600, - B19200 = B19200, - B38400 = B38400, - } - - termios :: struct { - c_iflag: CInput_Flags, /* [XBD] input flags */ - c_ispeed: CSpeed, /* input speed */ - c_oflag: COutput_Flags, /* [XBD] output flags */ - c_ospeed: CSpeed, /* output speed */ - c_cflag: CControl_Flags, /* [XBD] control flags */ - c_ispeed_high: tcflag_t, /* high word of input baudrate */ - c_lflag: CLocal_Flags, /* [XBD] local flag */ - c_ospeed_high: tcflag_t, /* high word of output baudrate */ - c_line: c.char, - _padding: c.uchar, - _padding2: c.uchar, - c_cc: [NCCS]cc_t, - } - - NCCS :: 11 - - VINTR :: 0 - VQUIT :: 1 - VERASE :: 2 - VKILL :: 3 - VEOF :: 4 - VEOL :: 5 - VMIN :: 4 - VTIME :: 5 - VEOL2 :: 6 - VSWTCH :: 7 - VSTART :: 8 - VSTOP :: 9 - VSUSP :: 10 - - IGNBRK :: 0x01 /* ignore break condition */ - BRKINT :: 0x02 /* break sends interrupt */ - IGNPAR :: 0x04 /* ignore characters with parity errors */ - PARMRK :: 0x08 /* mark parity errors */ - INPCK :: 0x10 /* enable input parity checking */ - ISTRIP :: 0x20 /* strip high bit from characters */ - INLCR :: 0x40 /* maps newline to CR on input */ - IGNCR :: 0x80 /* ignore carriage returns */ - ICRNL :: 0x100 /* map CR to newline on input */ - IXON :: 0x400 /* enable input SW flow control */ - IXANY :: 0x800 /* any character will restart input */ - IXOFF :: 0x1000 /* enable output SW flow control */ - - OPOST :: 0x01 /* enable postprocessing of output */ - ONLCR :: 0x04 /* map NL to CR-NL on output */ - OCRNL :: 0x08 /* map CR to NL on output */ - ONOCR :: 0x10 /* no CR output when at column 0 */ - ONLRET :: 0x20 /* newline performs CR function */ - OFILL :: 0x40 /* use fill characters for delays */ - OFDEL :: 0x80 /* Fills are DEL, otherwise NUL */ - _NLDLY :: 0x100 /* Newline delays: */ - NL0 :: 0x000 - NL1 :: 0x100 - _CRDLY :: 0x600 /* Carriage return delays: */ - CR0 :: 0x000 - CR1 :: 0x200 - CR2 :: 0x400 - CR3 :: 0x600 - _TABDLY :: 0x1800 /* Tab delays: */ - TAB0 :: 0x0000 - TAB1 :: 0x0800 - TAB3 :: 0x1800 - _BSDLY :: 0x2000 /* Backspace delays: */ - BS0 :: 0x0000 - BS1 :: 0x2000 - _VTDLY :: 0x4000 /* Vertical tab delays: */ - VT0 :: 0x0000 - VT1 :: 0x4000 - _FFDLY :: 0x8000 /* Form feed delays: */ - FF0 :: 0x0000 - FF1 :: 0x8000 - - B0 :: 0x00 /* hang up */ - B50 :: 0x01 /* 50 baud */ - B75 :: 0x02 - B110 :: 0x03 - B134 :: 0x04 - B150 :: 0x05 - B200 :: 0x06 - B300 :: 0x07 - B600 :: 0x08 - B1200 :: 0x09 - B1800 :: 0x0A - B2400 :: 0x0B - B4800 :: 0x0C - B9600 :: 0x0D - B19200 :: 0x0E - B38400 :: 0x0F - - _CSIZE :: 0x20 /* character size */ - //CS5 :: 0x00 /* only 7 and 8 bits supported */ - //CS6 :: 0x00 /* Note, it was not very wise to set all of these */ - //CS7 :: 0x00 /* to zero, but there is not much we can do about it*/ - CS8 :: 0x20 - CSTOPB :: 0x40 /* send 2 stop bits, not 1 */ - CREAD :: 0x80 /* enable receiver */ - PARENB :: 0x100 /* parity enable */ - PARODD :: 0x200 /* odd parity, else even */ - HUPCL :: 0x400 /* hangs up on last close */ - CLOCAL :: 0x800 /* indicates local line */ - - ISIG :: 0x01 /* enable signals */ - ICANON :: 0x02 /* Canonical input */ - ECHO :: 0x08 /* Enable echo */ - ECHOE :: 0x10 /* Echo erase as bs-sp-bs */ - ECHOK :: 0x20 /* Echo nl after kill */ - ECHONL :: 0x40 /* Echo nl */ - NOFLSH :: 0x80 /* Disable flush after int or quit */ - TOSTOP :: 0x100 /* stop bg processes that write to tty */ - IEXTEN :: 0x200 /* implementation defined extensions */ - - TCIFLUSH :: 1 - TCOFLUSH :: 2 - TCIOFLUSH :: 3 - - TCIOFF :: 0x04 - TCION :: 0x08 - TCOOFF :: 0x01 - TCOON :: 0x02 - } diff --git a/core/sys/posix/time.odin b/core/sys/posix/time.odin index 88f0153f4..c571d6ee8 100644 --- a/core/sys/posix/time.odin +++ b/core/sys/posix/time.odin @@ -1,11 +1,11 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" import "core:c/libc" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -230,17 +230,6 @@ when ODIN_OS == .Darwin { getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD. -} else when ODIN_OS == .Haiku { - - clockid_t :: distinct c.int32_t - - CLOCK_MONOTONIC :: 0 - CLOCK_PROCESS_CPUTIME_ID :: -2 - CLOCK_REALTIME :: -1 - CLOCK_THREAD_CPUTIME_ID :: -3 - - getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on Haiku. - } else when ODIN_OS == .Linux { clockid_t :: distinct c.int diff --git a/core/sys/posix/ulimit.odin b/core/sys/posix/ulimit.odin index 0f87641fa..892f6dee4 100644 --- a/core/sys/posix/ulimit.odin +++ b/core/sys/posix/ulimit.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/unistd.odin b/core/sys/posix/unistd.odin index b8020317c..29376046c 100644 --- a/core/sys/posix/unistd.odin +++ b/core/sys/posix/unistd.odin @@ -1,10 +1,10 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -2032,174 +2032,4 @@ when ODIN_OS == .Darwin { // NOTE: Not implemented. _POSIX_VDISABLE :: 0 -} else when ODIN_OS == .Haiku { - - _F_OK :: 0 - X_OK :: 1 - W_OK :: 2 - R_OK :: 4 - - F_LOCK :: 1 - F_TEST :: 3 - F_TLOCK :: 2 - F_ULOCK :: 0 - - _CS_PATH :: 1 - _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFF32_CFLAGS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFF32_LDFLAGS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFF32_LIBS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS :: 0 // Undefined. - _CS_POSIX_V6_ILP32_OFFBIG_LIBS :: 0 // Undefined. - _CS_POSIX_V6_LP64_OFF64_CFLAGS :: 0 // Undefined. - _CS_POSIX_V6_LP64_OFF64_LDFLAGS :: 0 // Undefined. - _CS_POSIX_V6_LP64_OFF64_LIBS :: 0 // Undefined. - _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS :: 0 // Undefined. - _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS :: 0 // Undefined. - _CS_POSIX_V6_LPBIG_OFFBIG_LIBS :: 0 // Undefined. - - _SC_ASYNCHRONOUS_IO :: 0 // Undefined. - _SC_RAW_SOCKETS :: 0 // Undefined. - _SC_SS_REPL_MAX :: 0 // Undefined. - _SC_TRACE_EVENT_NAME_MAX :: 0 // Undefined. - _SC_TRACE_NAME_MAX :: 0 // Undefined. - _SC_TRACE_SYS_MAX :: 0 // Undefined. - _SC_TRACE_USER_EVENT_MAX :: 0 // Undefined. - - _PC_CHOWN_RESTRICTED :: 1 - _PC_MAX_CANON :: 2 - _PC_MAX_INPUT :: 3 - _PC_NAME_MAX :: 4 - _PC_NO_TRUNC :: 5 - _PC_PATH_MAX :: 6 - _PC_PIPE_BUF :: 7 - _PC_VDISABLE :: 8 - _PC_LINK_MAX :: 25 - _PC_SYNC_IO :: 26 - _PC_ASYNC_IO :: 27 - _PC_PRIO_IO :: 28 - _PC_FILESIZEBITS :: 30 - _PC_REC_INCR_XFER_SIZE :: 31 - _PC_REC_MAX_XFER_SIZE :: 32 - _PC_REC_MIN_XFER_SIZE :: 33 - _PC_REC_XFER_ALIGN :: 34 - _PC_ALLOC_SIZE_MIN :: 35 - _PC_SYMLINK_MAX :: 36 - _PC_2_SYMLINKS :: 37 - - _SC_ARG_MAX :: 15 - _SC_CHILD_MAX :: 16 - _SC_CLK_TCK :: 17 - _SC_JOB_CONTROL :: 18 - _SC_NGROUPS_MAX :: 19 - _SC_OPEN_MAX :: 20 - _SC_SAVED_IDS :: 21 - _SC_STREAM_MAX :: 22 - _SC_TZNAME_MAX :: 23 - _SC_VERSION :: 24 - _SC_GETGR_R_SIZE_MAX :: 25 - _SC_GETPW_R_SIZE_MAX :: 26 - _SC_PAGE_SIZE :: 27 - _SC_PAGESIZE :: _SC_PAGE_SIZE - _SC_SEM_NSEMS_MAX :: 28 - _SC_SEM_VALUE_MAX :: 29 - _SC_SEMAPHORES :: 30 - _SC_THREADS :: 31 - _SC_IOV_MAX :: 32 - _SC_NPROCESSORS_CONF :: 34 - _SC_NPROCESSORS_ONLN :: 35 - _SC_ATEXIT_MAX :: 37 - _SC_MAPPED_FILES :: 45 - _SC_THREAD_PROCESS_SHARED :: 46 - _SC_THREAD_STACK_MIN :: 47 - _SC_THREAD_ATTR_STACKADDR :: 48 - _SC_THREAD_ATTR_STACKSIZE :: 49 - _SC_THREAD_PRIORITY_SCHEDULING :: 50 - _SC_REALTIME_SIGNALS :: 51 - _SC_MEMORY_PROTECTION :: 52 - _SC_SIGQUEUE_MAX :: 53 - _SC_RTSIG_MAX :: 54 - _SC_MONOTONIC_CLOCK :: 55 - _SC_DELAYTIMER_MAX :: 56 - _SC_TIMER_MAX :: 57 - _SC_TIMERS :: 58 - _SC_CPUTIME :: 59 - _SC_THREAD_CPUTIME :: 60 - _SC_HOST_NAME_MAX :: 61 - _SC_REGEXP :: 62 - _SC_SYMLOOP_MAX :: 63 - _SC_SHELL :: 64 - _SC_TTY_NAME_MAX :: 65 - _SC_ADVISORY_INFO :: 66 - _SC_BARRIERS :: 67 - _SC_CLOCK_SELECTION :: 68 - _SC_FSYNC :: 69 - _SC_IPV6 :: 70 - _SC_MEMLOCK :: 71 - _SC_MEMLOCK_RANGE :: 72 - _SC_MESSAGE_PASSING :: 73 - _SC_PRIORITIZED_IO :: 74 - _SC_PRIORITY_SCHEDULING :: 75 - _SC_READER_WRITER_LOCKS :: 76 - _SC_SHARED_MEMORY_OBJECTS :: 77 - _SC_SPAWN :: 78 - _SC_SPIN_LOCKS :: 79 - _SC_SPORADIC_SERVER :: 80 - _SC_SYNCHRONIZED_IO :: 81 - _SC_THREAD_PRIO_INHERIT :: 82 - _SC_THREAD_PRIO_PROTECT :: 83 - _SC_THREAD_SAFE_FUNCTIONS :: 86 - _SC_THREAD_SPORADIC_SERVER :: 87 - _SC_TIMEOUTS :: 88 - _SC_TRACE :: 89 - _SC_TRACE_EVENT_FILTER :: 90 - _SC_TRACE_INHERIT :: 91 - _SC_TRACE_LOG :: 92 - _SC_TYPED_MEMORY_OBJECTS :: 93 - _SC_V6_ILP32_OFF32 :: 94 - _SC_V6_ILP32_OFFBIG :: 95 - _SC_V6_LP64_OFF64 :: 96 - _SC_V6_LPBIG_OFFBIG :: 97 - _SC_2_C_BIND :: 102 - _SC_2_C_DEV :: 103 - _SC_2_CHAR_TERM :: 104 - _SC_2_FORT_DEV :: 105 - _SC_2_FORT_RUN :: 106 - _SC_2_LOCALEDEF :: 107 - _SC_2_PBS :: 108 - _SC_2_PBS_ACCOUNTING :: 109 - _SC_2_PBS_CHECKPOINT :: 110 - _SC_2_PBS_LOCATE :: 111 - _SC_2_PBS_MESSAGE :: 112 - _SC_2_PBS_TRACK :: 113 - _SC_2_SW_DEV :: 114 - _SC_2_UPE :: 115 - _SC_2_VERSION :: 116 - _SC_XOPEN_CRYPT :: 117 - _SC_XOPEN_ENH_I18N :: 118 - _SC_XOPEN_REALTIME :: 119 - _SC_XOPEN_REALTIME_THREADS :: 120 - _SC_XOPEN_SHM :: 121 - _SC_XOPEN_STREAMS :: 122 - _SC_XOPEN_UNIX :: 123 - _SC_XOPEN_VERSION :: 125 - _SC_AIO_LISTIO_MAX :: 126 - _SC_AIO_MAX :: 127 - _SC_AIO_PRIO_DELTA_MAX :: 128 - _SC_BC_BASE_MAX :: 129 - _SC_BC_DIM_MAX :: 130 - _SC_BC_SCALE_MAX :: 131 - _SC_BC_STRING_MAX :: 132 - _SC_COLL_WEIGHTS_MAX :: 133 - _SC_EXPR_NEST_MAX :: 134 - _SC_LINE_MAX :: 135 - _SC_LOGIN_NAME_MAX :: 136 - _SC_MQ_OPEN_MAX :: 137 - _SC_MQ_PRIO_MAX :: 138 - _SC_THREAD_DESTRUCTOR_ITERATIONS :: 139 - _SC_THREAD_KEYS_MAX :: 140 - _SC_THREAD_THREADS_MAX :: 141 - _SC_RE_DUP_MAX :: 142 - } diff --git a/core/sys/posix/unistd_libc.odin b/core/sys/posix/unistd_libc.odin index 74edb6862..b8e0a7df9 100644 --- a/core/sys/posix/unistd_libc.odin +++ b/core/sys/posix/unistd_libc.odin @@ -1,4 +1,4 @@ -#+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, windows, darwin, netbsd, openbsd, freebsd package posix import "core:c" @@ -6,7 +6,7 @@ import "core:c" when ODIN_OS == .Windows { foreign import lib "system:libucrt.lib" } else when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/posix/utime.odin b/core/sys/posix/utime.odin index 98c8166d6..0adc3263e 100644 --- a/core/sys/posix/utime.odin +++ b/core/sys/posix/utime.odin @@ -1,8 +1,8 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd package posix when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } @@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD { @(private) LUTIME :: "utime" } -when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku { +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { utimbuf :: struct { actime: time_t, /* [PSX] access time (seconds since epoch) */ diff --git a/core/sys/posix/wordexp.odin b/core/sys/posix/wordexp.odin index a9e6f39a7..92d6aba40 100644 --- a/core/sys/posix/wordexp.odin +++ b/core/sys/posix/wordexp.odin @@ -4,7 +4,7 @@ package posix import "core:c" when ODIN_OS == .Darwin { - foreign import lib "system:System.framework" + foreign import lib "system:System" } else { foreign import lib "system:c" } diff --git a/core/sys/unix/sysctl_freebsd.odin b/core/sys/unix/sysctl_freebsd.odin index f5fee6c6c..cdd591a5b 100644 --- a/core/sys/unix/sysctl_freebsd.odin +++ b/core/sys/unix/sysctl_freebsd.odin @@ -3,7 +3,7 @@ package unix import "base:intrinsics" -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := u64(size_of(T)) diff --git a/core/sys/unix/sysctl_netbsd.odin b/core/sys/unix/sysctl_netbsd.odin index ad89b9ad4..b70740721 100644 --- a/core/sys/unix/sysctl_netbsd.odin +++ b/core/sys/unix/sysctl_netbsd.odin @@ -8,7 +8,7 @@ foreign libc { @(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 --- } -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := c.size_t(size_of(T)) res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0) diff --git a/core/sys/unix/sysctl_openbsd.odin b/core/sys/unix/sysctl_openbsd.odin index 49c9b6336..a18b334c5 100644 --- a/core/sys/unix/sysctl_openbsd.odin +++ b/core/sys/unix/sysctl_openbsd.odin @@ -9,7 +9,7 @@ foreign libc { @(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 --- } -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := c.size_t(size_of(T)) res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0) @@ -46,4 +46,5 @@ CTL_HW :: 6 HW_VERSION :: 16 HW_SERIALNO :: 17 HW_UUID :: 18 - HW_PHYSMEM64 :: 19 \ No newline at end of file + HW_PHYSMEM64 :: 19 + HW_USERMEM64 :: 20 \ No newline at end of file diff --git a/core/sys/wasm/js/dom.odin b/core/sys/wasm/js/dom.odin index 902dfc941..6dd9dbf45 100644 --- a/core/sys/wasm/js/dom.odin +++ b/core/sys/wasm/js/dom.odin @@ -15,13 +15,15 @@ foreign dom_lib { get_element_value_string_length :: proc(id: string) -> int --- set_element_key_string :: proc(id: string, key: string, value: string) --- - get_element_key_string_length :: proc(id: string, key: string, ) -> int --- + get_element_key_string_length :: proc(id: string, key: string) -> int --- device_pixel_ratio :: proc() -> f64 --- window_set_scroll :: proc(x, y: f64) --- set_element_style :: proc(id: string, key: string, value: string) --- + + set_document_title :: proc(title: string) --- } get_element_value_string :: proc "contextless" (id: string, buf: []byte) -> string { diff --git a/core/sys/wasm/js/events.odin b/core/sys/wasm/js/events.odin index 37a6e6c35..f5a47c06b 100644 --- a/core/sys/wasm/js/events.odin +++ b/core/sys/wasm/js/events.odin @@ -373,12 +373,32 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba return _remove_window_event_listener(event_kind_string[kind], user_data, callback, use_capture) } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="add_document_event_listener") + _add_document_event_listener :: proc(name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _add_document_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture) +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="remove_document_event_listener") + _remove_document_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _remove_document_event_listener(event_kind_string[kind], user_data, callback, use_capture) +} + remove_event_listener_from_event :: proc(e: Event) -> bool { from_use_capture_false: bool from_use_capture_true: bool if e.id == "" { from_use_capture_false = remove_window_event_listener(e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_window_event_listener(e.kind, e.user_data, e.callback, true) + from_use_capture_false |= remove_document_event_listener(e.kind, e.user_data, e.callback, false) + from_use_capture_true |= remove_document_event_listener(e.kind, e.user_data, e.callback, true) } else { from_use_capture_false = remove_event_listener(e.id, e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_event_listener(e.id, e.kind, e.user_data, e.callback, true) diff --git a/core/sys/wasm/js/events_all_targets.odin b/core/sys/wasm/js/events_all_targets.odin index 6439396c5..903252c7a 100644 --- a/core/sys/wasm/js/events_all_targets.odin +++ b/core/sys/wasm/js/events_all_targets.odin @@ -275,6 +275,14 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba panic("vendor:wasm/js not supported on non JS targets") } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + remove_event_listener_from_event :: proc(e: Event) -> bool { panic("vendor:wasm/js not supported on non JS targets") } diff --git a/core/sys/wasm/js/memory_all_targets.odin b/core/sys/wasm/js/memory_all_targets.odin index e80d13c0b..69a789145 100644 --- a/core/sys/wasm/js/memory_all_targets.odin +++ b/core/sys/wasm/js/memory_all_targets.odin @@ -1,14 +1,14 @@ #+build !js package wasm_js_interface -import "core:mem" +import "base:runtime" PAGE_SIZE :: 64 * 1024 -page_alloc :: proc(page_count: int) -> (data: []byte, err: mem.Allocator_Error) { +page_alloc :: proc(page_count: int) -> (data: []byte, err: runtime.Allocator_Error) { panic("vendor:wasm/js not supported on non-js targets") } -page_allocator :: proc() -> mem.Allocator { +page_allocator :: proc() -> runtime.Allocator { panic("vendor:wasm/js not supported on non-js targets") } diff --git a/core/sys/wasm/js/memory_js.odin b/core/sys/wasm/js/memory_js.odin index 8232cd0c9..df3191b29 100644 --- a/core/sys/wasm/js/memory_js.odin +++ b/core/sys/wasm/js/memory_js.odin @@ -1,11 +1,11 @@ #+build js wasm32, js wasm64p32 package wasm_js_interface -import "core:mem" +import "base:runtime" import "base:intrinsics" PAGE_SIZE :: 64 * 1024 -page_alloc :: proc(page_count: int) -> (data: []byte, err: mem.Allocator_Error) { +page_alloc :: proc(page_count: int) -> (data: []byte, err: runtime.Allocator_Error) { prev_page_count := intrinsics.wasm_memory_grow(0, uintptr(page_count)) if prev_page_count < 0 { return nil, .Out_Of_Memory @@ -15,11 +15,11 @@ page_alloc :: proc(page_count: int) -> (data: []byte, err: mem.Allocator_Error) return ptr[:page_count * PAGE_SIZE], nil } -page_allocator :: proc() -> mem.Allocator { - procedure :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, +page_allocator :: proc() -> runtime.Allocator { + procedure :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, - location := #caller_location) -> ([]byte, mem.Allocator_Error) { + location := #caller_location) -> ([]byte, runtime.Allocator_Error) { switch mode { case .Alloc, .Alloc_Non_Zeroed: assert(size % PAGE_SIZE == 0) @@ -27,7 +27,7 @@ page_allocator :: proc() -> mem.Allocator { case .Resize, .Free, .Free_All, .Query_Info, .Resize_Non_Zeroed: return nil, .Mode_Not_Implemented case .Query_Features: - set := (^mem.Allocator_Mode_Set)(old_memory) + set := (^runtime.Allocator_Mode_Set)(old_memory) if set != nil { set^ = {.Alloc, .Query_Features} } diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index d5faa5210..4d19916bd 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -10,7 +10,7 @@ function getElement(name) { } function stripNewline(str) { - return str.replace(/\n/, ' ') + return str.replace(/\n/, ' ') } class WasmMemoryInterface { @@ -40,22 +40,14 @@ class WasmMemoryInterface { } - loadF32Array(addr, len) { - let array = new Float32Array(this.memory.buffer, addr, len); - return array; - } - loadF64Array(addr, len) { - let array = new Float64Array(this.memory.buffer, addr, len); - return array; - } - loadU32Array(addr, len) { - let array = new Uint32Array(this.memory.buffer, addr, len); - return array; - } - loadI32Array(addr, len) { - let array = new Int32Array(this.memory.buffer, addr, len); - return array; - } + loadF32Array(addr, len) { return new Float32Array(this.memory.buffer, addr, len); } + loadF64Array(addr, len) { return new Float64Array(this.memory.buffer, addr, len); } + loadU32Array(addr, len) { return new Uint32Array(this.memory.buffer, addr, len); } + loadI32Array(addr, len) { return new Int32Array(this.memory.buffer, addr, len); } + loadU16Array(addr, len) { return new Uint16Array(this.memory.buffer, addr, len); } + loadI16Array(addr, len) { return new Int16Array(this.memory.buffer, addr, len); } + loadU8Array(addr, len) { return new Uint8Array(this.memory.buffer, addr, len); } + loadI8Array(addr, len) { return new Int8Array(this.memory.buffer, addr, len); } loadU8(addr) { return this.mem.getUint8 (addr); } @@ -110,16 +102,12 @@ class WasmMemoryInterface { } loadCstring(ptr) { - return this.loadCstringDirect(this.loadPtr(ptr)); - } - - loadCstringDirect(start) { - if (start == 0) { + if (ptr == 0) { return null; } let len = 0; - for (; this.mem.getUint8(start+len) != 0; len += 1) {} - return this.loadString(start, len); + for (; this.mem.getUint8(ptr+len) != 0; len += 1) {} + return this.loadString(ptr, len); } storeU8(addr, value) { this.mem.setUint8 (addr, value); } @@ -204,6 +192,7 @@ class WebGLInterface { this.transformFeedbacks = []; this.syncs = []; this.programInfos = {}; + this.extensions = []; } get mem() { @@ -229,6 +218,9 @@ class WebGLInterface { } else { this.ctxVersion = 1.0; } + + this.extensions = this.ctx.getSupportedExtensions(); + return true; } @@ -285,6 +277,30 @@ class WebGLInterface { return source; } + loadTypedArrayFromTexelType(type, size, data) { + switch (type) { + case this.ctx.SHORT: return this.mem.loadI16Array(data, size/2); + case this.ctx.UNSIGNED_SHORT_5_5_5_1: + case this.ctx.UNSIGNED_SHORT_5_6_5: + case this.ctx.UNSIGNED_SHORT_4_4_4_4: + case this.ctx.UNSIGNED_SHORT: + case this.ctx.HALF_FLOAT: return this.mem.loadU16Array(data, size/2); + case this.ctx.FLOAT: return this.mem.loadF32Array(data, size/4); + case this.ctx.INT: return this.mem.loadI32Array(data, size/4) + case this.ctx.UNSIGNED_INT_24_8: + case this.ctx.UNSIGNED_INT_5_9_9_9_REV: + case this.ctx.UNSIGNED_INT_10F_11F_11F_REV: + case this.ctx.UNSIGNED_INT_2_10_10_10_REV: + case this.ctx.UNSIGNED_INT: return this.mem.loadU32Array(data, size/4) + case this.ctx.BYTE: return this.mem.loadI8Array(data, size); + case this.ctx.UNSIGNED_BYTE: return this.mem.loadU8Array(data, size); + case this.ctx.FLOAT_32_UNSIGNED_INT_24_8_REV: + throw new Error("Source data of type FLOAT_32_UNSIGNED_INT_24_8_REV must be null"); + } + + throw new Error(`Unsupported texture data type: 0x${type.toString(16)}`); + } + getWebGL1Interface() { return { SetCurrentContextById: (name_ptr, name_len) => { @@ -331,10 +347,30 @@ class WebGLInterface { IsExtensionSupported: (name_ptr, name_len) => { let name = this.mem.loadString(name_ptr, name_len); - let extensions = this.ctx.getSupportedExtensions(); + let extensions = this.extensions; return extensions.indexOf(name) !== -1 }, + GetSupportedExtensionFromIndex: (index, buf_ptr, buf_len, length_ptr) => { + let extensions = this.extensions; + if (index < 0 || index >= extensions.length) { + return false; + } + + let ext = extensions[index]; + const n = Math.min(buf_len, ext.length); + ext = ext.substring(0, n); + this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(ext)); + + this.mem.storeInt(length_ptr, n); + + return true; + }, + + GetExtension: (name_ptr, name_len) => { + let name = this.mem.loadString(name_ptr, name_len); + this.ctx.getExtension(name); + }, GetError: () => { let err = this.lastError; @@ -396,6 +432,9 @@ class WebGLInterface { BindTexture: (target, texture) => { this.ctx.bindTexture(target, texture ? this.textures[texture] : null) }, + BindRenderbuffer: (target, renderbuffer) => { + this.ctx.bindRenderbuffer(target, renderbuffer ? this.renderbuffers[renderbuffer] : null) + }, BlendColor: (red, green, blue, alpha) => { this.ctx.blendColor(red, green, blue, alpha); }, @@ -617,6 +656,9 @@ class WebGLInterface { FramebufferTexture2D: (target, attachment, textarget, texture, level) => { this.ctx.framebufferTexture2D(target, attachment, textarget, this.textures[texture], level); }, + CheckFramebufferStatus: (target) => { + return this.ctx.checkFramebufferStatus(target) + }, FrontFace: (mode) => { this.ctx.frontFace(mode); }, @@ -626,6 +668,52 @@ class WebGLInterface { this.ctx.generateMipmap(target); }, + GetBufferParameter: (target, pname) => { + return this.ctx.getBufferParameter(target, pname); + }, + + + GetActiveAttrib: (program, index, size_ptr, type_ptr, name_buf_ptr, name_buf_len, name_len_ptr) => { + const info = this.ctx.getActiveAttrib(this.programs[program], index); + + if (size_ptr) { + this.mem.storeInt(size_ptr, info.size); + } + + if (type_ptr) { + this.mem.storeI32(type_ptr, info.type); + } + + if (name_buf_ptr && name_buf_len > 0) { + let n = Math.min(name_buf_len, info.name.length); + let name = info.name.substring(0, n); + this.mem.loadBytes(name_buf_ptr, name_buf_len).set(new TextEncoder().encode(name)); + this.mem.storeInt(name_len_ptr, n); + } else if (name_len_ptr) { + this.mem.storeInt(name_len_ptr, info.name.length); + } + }, + + GetActiveUniform: (program, index, size_ptr, type_ptr, name_buf_ptr, name_buf_len, name_len_ptr) => { + let info = this.ctx.getActiveUniform(this.programs[program], index); + + if (size_ptr) { + this.mem.storeInt(size_ptr, info.size); + } + + if (type_ptr) { + this.mem.storeI32(type_ptr, info.type); + } + + if (name_buf_ptr && name_buf_len > 0) { + let n = Math.min(name_buf_len, info.name.length); + let name = info.name.substring(0, n); + this.mem.loadBytes(name_buf_ptr, name_buf_len).set(new TextEncoder().encode(name)); + this.mem.storeInt(name_len_ptr, n); + } else if (name_len_ptr) { + this.mem.storeInt(name_len_ptr, info.name.length); + } + }, GetAttribLocation: (program, name_ptr, name_len) => { let name = this.mem.loadString(name_ptr, name_len); @@ -787,7 +875,8 @@ class WebGLInterface { TexImage2D: (target, level, internalformat, width, height, border, format, type, size, data) => { if (data) { - this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, this.mem.loadBytes(data, size)); + const texelData = this.loadTypedArrayFromTexelType(type, size, data); + this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, texelData); } else { this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, null); } @@ -799,7 +888,8 @@ class WebGLInterface { this.ctx.texParameteri(target, pname, param); }, TexSubImage2D: (target, level, xoffset, yoffset, width, height, format, type, size, data) => { - this.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, this.mem.loadBytes(data, size)); + const texelData = this.loadTypedArrayFromTexelType(type, size, data); + this.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, texelData); }, @@ -813,6 +903,40 @@ class WebGLInterface { Uniform3i: (location, v0, v1, v2) => { this.ctx.uniform3i(this.uniforms[location], v0, v1, v2); }, Uniform4i: (location, v0, v1, v2, v3) => { this.ctx.uniform4i(this.uniforms[location], v0, v1, v2, v3); }, + Uniform1fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 1*count); + this.ctx.uniform1fv(this.uniforms[location], array); + }, + Uniform2fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 2*count); + this.ctx.uniform2fv(this.uniforms[location], array); + }, + Uniform3fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 3*count); + this.ctx.uniform3fv(this.uniforms[location], array); + }, + Uniform4fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 4*count); + this.ctx.uniform4fv(this.uniforms[location], array); + }, + + Uniform1iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 1*count); + this.ctx.uniform1iv(this.uniforms[location], array); + }, + Uniform2iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 2*count); + this.ctx.uniform2iv(this.uniforms[location], array); + }, + Uniform3iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 3*count); + this.ctx.uniform3iv(this.uniforms[location], array); + }, + Uniform4iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 4*count); + this.ctx.uniform4iv(this.uniforms[location], array); + }, + UniformMatrix2fv: (location, addr) => { let array = this.mem.loadF32Array(addr, 2*2); this.ctx.uniformMatrix2fv(this.uniforms[location], false, array); @@ -899,7 +1023,10 @@ class WebGLInterface { }, /* Texture objects */ - + TexStorage2D: (target, levels, internalformat, width, height) => { + this.assertWebGL2(); + this.ctx.texStorage2D(target, levels, internalformat, width, height); + }, TexStorage3D: (target, levels, internalformat, width, height, depth) => { this.assertWebGL2(); this.ctx.texStorage3D(target, levels, internalformat, width, height, depth); @@ -907,14 +1034,16 @@ class WebGLInterface { TexImage3D: (target, level, internalformat, width, height, depth, border, format, type, size, data) => { this.assertWebGL2(); if (data) { - this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, this.mem.loadBytes(data, size)); + const texelData = this.loadTypedArrayFromTexelType(type, size, data); + this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, texelData); } else { this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, null); } }, TexSubImage3D: (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, size, data) => { this.assertWebGL2(); - this.ctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, this.mem.loadBytes(data, size)); + const texelData = this.loadTypedArrayFromTexelType(type, size, data); + this.ctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texelData); }, CompressedTexImage3D: (target, level, internalformat, width, height, depth, border, imageSize, data) => { this.assertWebGL2(); @@ -1227,15 +1356,34 @@ class WebGLInterface { this.assertWebGL2(); return this.ctx.getUniformBlockIndex(this.programs[program], this.mem.loadString(uniformBlockName_ptr, uniformBlockName_len)); }, - // any getActiveUniformBlockParameter(WebGLProgram program, GLuint uniformBlockIndex, GLenum pname); - GetActiveUniformBlockName: (program, uniformBlockIndex, buf_ptr, buf_len, length_ptr) => { + GetActiveUniformBlockName: (program, uniformBlockIndex, name_buf_ptr, name_buf_len, name_length_ptr) => { this.assertWebGL2(); let name = this.ctx.getActiveUniformBlockName(this.programs[program], uniformBlockIndex); - let n = Math.min(buf_len, name.length); - name = name.substring(0, n); - this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(name)) - this.mem.storeInt(length_ptr, n); + if (name_buf_ptr && name_buf_len > 0) { + let n = Math.min(name_buf_len, name.length); + name = name.substring(0, n); + this.mem.loadBytes(name_buf_ptr, name_buf_len).set(new TextEncoder().encode(name)); + this.mem.storeInt(name_length_ptr, n); + } else if (name_length_ptr) { + this.mem.storeInt(name_length_ptr, name.length); + } + }, + GetActiveUniforms: (program, uniformIndices_ptr, uniformIndices_len, pname, res_ptr) => { + this.assertWebGL2(); + let indices = this.mem.loadU32Array(uniformIndices_ptr, uniformIndices_len); + this.ctx.getActiveUniforms(this.programs[program], indices, pname) + this.mem.loadI32Array(res_ptr, indices.length).set(indices) + }, + GetActiveUniformBlockParameter: (program, uniformBlockIndex, pname, params_ptr) => { + this.assertWebGL2(); + let res = this.ctx.getActiveUniformBlockParameter(this.programs[program], uniformBlockIndex, pname); + + if (res instanceof Uint32Array) { // for pname GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES + this.mem.loadU32Array(params_ptr, res.length).set(res) + } else { + this.mem.storeI32(params_ptr, res) + } }, UniformBlockBinding: (program, uniformBlockIndex, uniformBlockBinding) => { this.assertWebGL2(); @@ -1705,6 +1853,28 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { return true; }, + add_document_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + let key = listener_key('document', name, data, callback, !!use_capture); + if (wasmMemoryInterface.listenerMap.has(key)) { + return false; + } + + let listener = (e) => { + let event_data = {}; + event_data.id_ptr = 0; + event_data.id_len = 0; + event_data.event = e; + event_data.name_code = name_code; + + onEventReceived(event_data, data, callback); + }; + wasmMemoryInterface.listenerMap.set(key, listener); + element.addEventListener(name, listener, !!use_capture); + return true; + }, + remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback, use_capture) => { let id = wasmMemoryInterface.loadString(id_ptr, id_len); let name = wasmMemoryInterface.loadString(name_ptr, name_len); @@ -1737,6 +1907,20 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { element.removeEventListener(name, listener, !!use_capture); return true; }, + remove_document_event_listener: (name_ptr, name_len, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + + let key = listener_key('document', name, data, callback, !!use_capture); + let listener = wasmMemoryInterface.listenerMap.get(key); + if (listener === undefined) { + return false; + } + wasmMemoryInterface.listenerMap.delete(key); + + element.removeEventListener(name, listener, !!use_capture); + return true; + }, event_stop_propagation: () => { if (event_temp.data && event_temp.data.event) { @@ -1771,6 +1955,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { return false; }, + // Writes a struct of type `Gamepad_State`, see `core/sys/wasm/js/events.odin` get_gamepad_state: (gamepad_id, ep) => { let index = gamepad_id; let gps = navigator.getGamepads(); @@ -1868,7 +2053,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { if (buf_len > 0 && buf_ptr) { let n = Math.min(buf_len, str.length); str = str.substring(0, n); - this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(str)) + wasmMemoryInterface.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(str)) return n; } } @@ -1917,6 +2102,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { } }, + set_document_title: (title_ptr, title_len) => { + let title = wasmMemoryInterface.loadString(title_ptr, title_len); + document.title = title; + }, + get_element_key_f64: (id_ptr, id_len, key_ptr, key_len) => { let id = wasmMemoryInterface.loadString(id_ptr, id_len); let key = wasmMemoryInterface.loadString(key_ptr, key_len); @@ -1932,7 +2122,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { if (buf_len > 0 && buf_ptr) { let n = Math.min(buf_len, str.length); str = str.substring(0, n); - this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(str)) + wasmMemoryInterface.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(str)) return n; } } @@ -2038,12 +2228,14 @@ async function runWasm(wasmPath, consoleElement, extraForeignImports, wasmMemory if (exports.memory) { if (wasmMemoryInterface.memory) { - console.warn("WASM module exports memory, but `runWasm` was given an interface with existing memory too"); + console.warn('WASM module exports memory, but `runWasm` was given an interface with existing memory too. Did you mean to use `-extra-linker-flags:"--import-memory"` to tell the compiler not to export memory?'); } wasmMemoryInterface.setMemory(exports.memory); } - exports._start(); + if (exports._start) { + exports._start(); + } // Define a `@export step :: proc(delta_time: f64) -> (keep_going: bool) {` // in your app and it will get called every frame. @@ -2061,7 +2253,9 @@ async function runWasm(wasmPath, consoleElement, extraForeignImports, wasmMemory prevTimeStamp = currTimeStamp; if (!exports.step(dt, odin_ctx)) { - exports._end(); + if (exports._end) { + exports._end(); + } return; } @@ -2070,7 +2264,9 @@ async function runWasm(wasmPath, consoleElement, extraForeignImports, wasmMemory window.requestAnimationFrame(step); } else { - exports._end(); + if (exports._end) { + exports._end(); + } } return; diff --git a/core/sys/win32/removal.odin b/core/sys/win32/removal.odin deleted file mode 100644 index 09c16aa05..000000000 --- a/core/sys/win32/removal.odin +++ /dev/null @@ -1,3 +0,0 @@ -package sys_win32 - -#panic(`"core:sys/win32" has been removed. Please use "core:sys/windows"`) \ No newline at end of file diff --git a/core/sys/windows/advapi32.odin b/core/sys/windows/advapi32.odin index f834511d4..7097ebdbd 100644 --- a/core/sys/windows/advapi32.odin +++ b/core/sys/windows/advapi32.odin @@ -167,6 +167,13 @@ foreign advapi32 { lpftLastWriteTime: ^FILETIME, ) -> LSTATUS --- + RegEnumKeyW :: proc( + hKey: HKEY, + dwIndex: DWORD, + lpName: LPWSTR, + cchName: DWORD, + ) -> LSTATUS --- + RegEnumKeyExW :: proc( hKey: HKEY, dwIndex: DWORD, @@ -221,7 +228,7 @@ foreign advapi32 { } PTOKEN_INFORMATION_CLASS :: ^TOKEN_INFORMATION_CLASS -TOKEN_INFORMATION_CLASS :: enum i32 { +TOKEN_INFORMATION_CLASS :: enum c_int { TokenUser = 1, TokenGroups, TokenPrivileges, @@ -275,7 +282,7 @@ TOKEN_INFORMATION_CLASS :: enum i32 { } PSID_NAME_USE :: ^SID_NAME_USE -SID_NAME_USE :: enum i32 { +SID_NAME_USE :: enum c_int { SidTypeUser = 1, SidTypeGroup, SidTypeDomain, @@ -296,35 +303,35 @@ TOKEN_USER :: struct { PSID_AND_ATTRIBUTES :: ^SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES :: struct { - Sid: rawptr, + Sid: rawptr, Attributes: ULONG, } PTOKEN_TYPE :: ^TOKEN_TYPE TOKEN_TYPE :: enum { - TokenPrimary = 1, + TokenPrimary = 1, TokenImpersonation = 2, } PTOKEN_STATISTICS :: ^TOKEN_STATISTICS TOKEN_STATISTICS :: struct { - TokenId: LUID, - AuthenticationId: LUID, - ExpirationTime: LARGE_INTEGER, - TokenType: TOKEN_TYPE, + TokenId: LUID, + AuthenticationId: LUID, + ExpirationTime: LARGE_INTEGER, + TokenType: TOKEN_TYPE, ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL, - DynamicCharged: DWORD, - DynamicAvailable: DWORD, - GroupCount: DWORD, - PrivilegeCount: DWORD, - ModifiedId: LUID, + DynamicCharged: DWORD, + DynamicAvailable: DWORD, + GroupCount: DWORD, + PrivilegeCount: DWORD, + ModifiedId: LUID, } TOKEN_SOURCE_LENGTH :: 8 PTOKEN_SOURCE :: ^TOKEN_SOURCE TOKEN_SOURCE :: struct { - SourceName: [TOKEN_SOURCE_LENGTH]CHAR, + SourceName: [TOKEN_SOURCE_LENGTH]CHAR, SourceIdentifier: LUID, } @@ -332,7 +339,7 @@ TOKEN_SOURCE :: struct { PTOKEN_PRIVILEGES :: ^TOKEN_PRIVILEGES TOKEN_PRIVILEGES :: struct { PrivilegeCount: DWORD, - Privileges: [0]LUID_AND_ATTRIBUTES, + Privileges: [0]LUID_AND_ATTRIBUTES, } PTOKEN_PRIMARY_GROUP :: ^TOKEN_PRIMARY_GROUP @@ -347,16 +354,16 @@ TOKEN_OWNER :: struct { PTOKEN_GROUPS_AND_PRIVILEGES :: ^TOKEN_GROUPS_AND_PRIVILEGES TOKEN_GROUPS_AND_PRIVILEGES :: struct { - SidCount: DWORD, - SidLength: DWORD, - Sids: PSID_AND_ATTRIBUTES, - RestrictedSidCount: DWORD, + SidCount: DWORD, + SidLength: DWORD, + Sids: PSID_AND_ATTRIBUTES, + RestrictedSidCount: DWORD, RestrictedSidLength: DWORD, - RestrictedSids: PSID_AND_ATTRIBUTES, - PrivilegeCount: DWORD, - PrivilegeLength: DWORD, - Privileges: PLUID_AND_ATTRIBUTES, - AuthenticationId: LUID, + RestrictedSids: PSID_AND_ATTRIBUTES, + PrivilegeCount: DWORD, + PrivilegeLength: DWORD, + Privileges: PLUID_AND_ATTRIBUTES, + AuthenticationId: LUID, } PTOKEN_DEFAULT_DACL :: ^TOKEN_DEFAULT_DACL @@ -367,8 +374,8 @@ TOKEN_DEFAULT_DACL :: struct { PACL :: ^ACL ACL :: struct { AclRevision: BYTE, - Sbz1: BYTE, - AclSize: WORD, - AceCount: WORD, - Sbz2: WORD, + Sbz1: BYTE, + AclSize: WORD, + AceCount: WORD, + Sbz2: WORD, } diff --git a/core/sys/windows/comctl32.odin b/core/sys/windows/comctl32.odin index d954f952c..70eb42f84 100644 --- a/core/sys/windows/comctl32.odin +++ b/core/sys/windows/comctl32.odin @@ -5,9 +5,10 @@ foreign import "system:Comctl32.lib" @(default_calling_convention="system") foreign Comctl32 { - InitCommonControlsEx :: proc(picce: ^INITCOMMONCONTROLSEX) -> BOOL --- + InitCommonControlsEx :: proc(picce: ^INITCOMMONCONTROLSEX) -> BOOL --- LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT --- - SetWindowSubclass :: proc(hwnd: HWND, pfnSubclass: SUBCLASSPROC, uIdSubclass: UINT_PTR, dwRefData: DWORD_PTR) --- + SetWindowSubclass :: proc(hwnd: HWND, pfnSubclass: SUBCLASSPROC, uIdSubclass: UINT_PTR, dwRefData: DWORD_PTR) --- + DefSubclassProc :: proc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT --- } ICC_LISTVIEW_CLASSES :: 0x00000001 @@ -155,85 +156,85 @@ ILP_NORMAL :: 0 ILP_DOWNLEVEL :: 1 IMAGELISTDRAWPARAMS :: struct { - cbSize: DWORD, - himl: HIMAGELIST, - i: i32, - hdcDst: HDC, - x: i32, - y: i32, - cx: i32, - cy: i32, - xBitmap: i32, - yBitmap: i32, - rgbBk: COLORREF, - rgbFg: COLORREF, - fStyle: UINT, - dwRop: DWORD, - fState: DWORD, - Frame: DWORD, + cbSize: DWORD, + himl: HIMAGELIST, + i: c_int, + hdcDst: HDC, + x: c_int, + y: c_int, + cx: c_int, + cy: c_int, + xBitmap: c_int, + yBitmap: c_int, + rgbBk: COLORREF, + rgbFg: COLORREF, + fStyle: UINT, + dwRop: DWORD, + fState: DWORD, + Frame: DWORD, crEffect: COLORREF, } LPIMAGELISTDRAWPARAMS :: ^IMAGELISTDRAWPARAMS IMAGEINFO :: struct { hbmImage: HBITMAP, - hbmMask: HBITMAP, - Unused1: i32, - Unused2: i32, - rcImage: RECT, + hbmMask: HBITMAP, + Unused1: c_int, + Unused2: c_int, + rcImage: RECT, } LPIMAGEINFO :: ^IMAGEINFO @(default_calling_convention="system") foreign Comctl32 { - ImageList_Create :: proc(cx, cy: i32, flags: UINT, cInitial, cGrow: i32) -> HIMAGELIST --- - ImageList_Destroy :: proc(himl: HIMAGELIST) -> BOOL --- - ImageList_GetImageCount :: proc(himl: HIMAGELIST) -> i32 --- - ImageList_SetImageCount :: proc(himl: HIMAGELIST, uNewCount: UINT) -> BOOL --- - ImageList_Add :: proc(himl: HIMAGELIST, hbmImage, hbmMask: HBITMAP) -> i32 --- - ImageList_ReplaceIcon :: proc(himl: HIMAGELIST, i: i32, hicon: HICON) -> i32 --- - ImageList_SetBkColor :: proc(himl: HIMAGELIST, clrBk: COLORREF) -> COLORREF --- - ImageList_GetBkColor :: proc(himl: HIMAGELIST) -> COLORREF --- - ImageList_SetOverlayImage :: proc(himl: HIMAGELIST, iImage: i32, iOverlay: i32) -> BOOL --- - ImageList_Draw :: proc(himl: HIMAGELIST, i: i32, hdcDst: HDC, x, y: i32, fStyle: UINT) -> BOOL --- - ImageList_Replace :: proc(himl: HIMAGELIST, i: i32, hbmImage, hbmMask: HBITMAP) -> BOOL --- - ImageList_AddMasked :: proc(himl: HIMAGELIST, hbmImage: HBITMAP, crMask: COLORREF) -> i32 --- - ImageList_DrawEx :: proc(himl: HIMAGELIST, i: i32, hdcDst: HDC, x, y, dx, dy: i32, rgbBk, rgbFg: COLORREF, fStyle: UINT) -> BOOL --- - ImageList_DrawIndirect :: proc(pimldp: ^IMAGELISTDRAWPARAMS) -> BOOL --- - ImageList_Remove :: proc(himl: HIMAGELIST, i: i32) -> BOOL --- - ImageList_GetIcon :: proc(himl: HIMAGELIST, i: i32, flags: UINT) -> HICON --- - ImageList_LoadImageW :: proc(hi: HINSTANCE, lpbmp: LPCWSTR, cx, cgrow: i32, crMask: COLORREF, uType, uFlags: UINT) -> HIMAGELIST --- - ImageList_Copy :: proc(himlDst: HIMAGELIST, iDst: i32, himlSrc: HIMAGELIST, iSrc: i32, uFlags: UINT) -> BOOL --- - ImageList_BeginDrag :: proc(himlTrack: HIMAGELIST, iTrack, dxHotspot, dyHotspot: i32) -> BOOL --- - ImageList_EndDrag :: proc() --- - ImageList_DragEnter :: proc(hwndLock: HWND, x, y: i32) -> BOOL --- - ImageList_DragLeave :: proc(hwndLock: HWND) -> BOOL --- - ImageList_DragMove :: proc(x, y: i32) -> BOOL --- - ImageList_SetDragCursorImage :: proc(himlDrag: HIMAGELIST, iDrag, dxHotspot, dyHotspot: i32) -> BOOL --- - ImageList_DragShowNolock :: proc(fShow: BOOL) -> BOOL --- - ImageList_GetDragImage :: proc(ppt, pptHotspot: ^POINT) -> HIMAGELIST --- - ImageList_Read :: proc(pstm: ^IStream) -> HIMAGELIST --- - ImageList_Write :: proc(himl: HIMAGELIST, pstm: ^IStream) -> BOOL --- - ImageList_ReadEx :: proc(dwFlags: DWORD, pstm: ^IStream, riid: REFIID, ppv: PVOID) -> HRESULT --- - ImageList_WriteEx :: proc(himl: HIMAGELIST, dwFlags: DWORD, pstm: ^IStream) -> HRESULT --- - ImageList_GetIconSize :: proc(himl: HIMAGELIST, cx, cy: ^i32) -> BOOL --- - ImageList_SetIconSize :: proc(himl: HIMAGELIST, cx, cy: i32) -> BOOL --- - ImageList_GetImageInfo :: proc(himl: HIMAGELIST, i: i32, pImageInfo: ^IMAGEINFO) -> BOOL --- - ImageList_Merge :: proc(himl1: HIMAGELIST, i1: i32, himl2: HIMAGELIST, i2: i32, dx, dy: i32) -> HIMAGELIST --- - ImageList_Duplicate :: proc(himl: HIMAGELIST) -> HIMAGELIST --- - HIMAGELIST_QueryInterface :: proc(himl: HIMAGELIST, riid: REFIID, ppv: rawptr) -> HRESULT --- + ImageList_Create :: proc(cx, cy: c_int, flags: UINT, cInitial, cGrow: c_int) -> HIMAGELIST --- + ImageList_Destroy :: proc(himl: HIMAGELIST) -> BOOL --- + ImageList_GetImageCount :: proc(himl: HIMAGELIST) -> c_int --- + ImageList_SetImageCount :: proc(himl: HIMAGELIST, uNewCount: UINT) -> BOOL --- + ImageList_Add :: proc(himl: HIMAGELIST, hbmImage, hbmMask: HBITMAP) -> c_int --- + ImageList_ReplaceIcon :: proc(himl: HIMAGELIST, i: c_int, hicon: HICON) -> c_int --- + ImageList_SetBkColor :: proc(himl: HIMAGELIST, clrBk: COLORREF) -> COLORREF --- + ImageList_GetBkColor :: proc(himl: HIMAGELIST) -> COLORREF --- + ImageList_SetOverlayImage :: proc(himl: HIMAGELIST, iImage: c_int, iOverlay: c_int) -> BOOL --- + ImageList_Draw :: proc(himl: HIMAGELIST, i: c_int, hdcDst: HDC, x, y: c_int, fStyle: UINT) -> BOOL --- + ImageList_Replace :: proc(himl: HIMAGELIST, i: c_int, hbmImage, hbmMask: HBITMAP) -> BOOL --- + ImageList_AddMasked :: proc(himl: HIMAGELIST, hbmImage: HBITMAP, crMask: COLORREF) -> c_int --- + ImageList_DrawEx :: proc(himl: HIMAGELIST, i: c_int, hdcDst: HDC, x, y, dx, dy: c_int, rgbBk, rgbFg: COLORREF, fStyle: UINT) -> BOOL --- + ImageList_DrawIndirect :: proc(pimldp: ^IMAGELISTDRAWPARAMS) -> BOOL --- + ImageList_Remove :: proc(himl: HIMAGELIST, i: c_int) -> BOOL --- + ImageList_GetIcon :: proc(himl: HIMAGELIST, i: c_int, flags: UINT) -> HICON --- + ImageList_LoadImageW :: proc(hi: HINSTANCE, lpbmp: LPCWSTR, cx, cgrow: c_int, crMask: COLORREF, uType, uFlags: UINT) -> HIMAGELIST --- + ImageList_Copy :: proc(himlDst: HIMAGELIST, iDst: c_int, himlSrc: HIMAGELIST, iSrc: c_int, uFlags: UINT) -> BOOL --- + ImageList_BeginDrag :: proc(himlTrack: HIMAGELIST, iTrack, dxHotspot, dyHotspot: c_int) -> BOOL --- + ImageList_EndDrag :: proc() --- + ImageList_DragEnter :: proc(hwndLock: HWND, x, y: c_int) -> BOOL --- + ImageList_DragLeave :: proc(hwndLock: HWND) -> BOOL --- + ImageList_DragMove :: proc(x, y: c_int) -> BOOL --- + ImageList_SetDragCursorImage :: proc(himlDrag: HIMAGELIST, iDrag, dxHotspot, dyHotspot: c_int) -> BOOL --- + ImageList_DragShowNolock :: proc(fShow: BOOL) -> BOOL --- + ImageList_GetDragImage :: proc(ppt, pptHotspot: ^POINT) -> HIMAGELIST --- + ImageList_Read :: proc(pstm: ^IStream) -> HIMAGELIST --- + ImageList_Write :: proc(himl: HIMAGELIST, pstm: ^IStream) -> BOOL --- + ImageList_ReadEx :: proc(dwFlags: DWORD, pstm: ^IStream, riid: REFIID, ppv: PVOID) -> HRESULT --- + ImageList_WriteEx :: proc(himl: HIMAGELIST, dwFlags: DWORD, pstm: ^IStream) -> HRESULT --- + ImageList_GetIconSize :: proc(himl: HIMAGELIST, cx, cy: ^c_int) -> BOOL --- + ImageList_SetIconSize :: proc(himl: HIMAGELIST, cx, cy: c_int) -> BOOL --- + ImageList_GetImageInfo :: proc(himl: HIMAGELIST, i: c_int, pImageInfo: ^IMAGEINFO) -> BOOL --- + ImageList_Merge :: proc(himl1: HIMAGELIST, i1: c_int, himl2: HIMAGELIST, i2: c_int, dx, dy: c_int) -> HIMAGELIST --- + ImageList_Duplicate :: proc(himl: HIMAGELIST) -> HIMAGELIST --- + HIMAGELIST_QueryInterface :: proc(himl: HIMAGELIST, riid: REFIID, ppv: rawptr) -> HRESULT --- } -ImageList_AddIcon :: #force_inline proc "system" (himl: HIMAGELIST, hicon: HICON) -> i32 { +ImageList_AddIcon :: #force_inline proc "system" (himl: HIMAGELIST, hicon: HICON) -> c_int { return ImageList_ReplaceIcon(himl, -1, hicon) } ImageList_RemoveAll :: #force_inline proc "system" (himl: HIMAGELIST) -> BOOL { return ImageList_Remove(himl, -1) } -ImageList_ExtractIcon :: #force_inline proc "system" (hi: HINSTANCE, himl: HIMAGELIST, i: i32) -> HICON { +ImageList_ExtractIcon :: #force_inline proc "system" (hi: HINSTANCE, himl: HIMAGELIST, i: c_int) -> HICON { return ImageList_GetIcon(himl, i, 0) } -ImageList_LoadBitmap :: #force_inline proc "system" (hi: HINSTANCE, lpbmp: LPCWSTR, cx, cGrow: i32, crMask: COLORREF) -> HIMAGELIST { +ImageList_LoadBitmap :: #force_inline proc "system" (hi: HINSTANCE, lpbmp: LPCWSTR, cx, cGrow: c_int, crMask: COLORREF) -> HIMAGELIST { return ImageList_LoadImageW(hi, lpbmp, cx, cGrow, crMask, IMAGE_BITMAP, 0) } @@ -409,7 +410,7 @@ Header_SetFilterChangeTimeout :: #force_inline proc "system" (hwnd: HWND, i: c_i return cast(c_int)SendMessageW(hwnd,HDM_SETFILTERCHANGETIMEOUT,0,cast(LPARAM)i) } Header_EditFilter :: #force_inline proc "system" (hwnd: HWND, i: c_int, fDiscardChanges: BOOL) -> BOOL { - return cast(BOOL)SendMessageW(hwnd,HDM_EDITFILTER,cast(WPARAM)i,MAKELPARAM(fDiscardChanges,0)) + return cast(BOOL)SendMessageW(hwnd,HDM_EDITFILTER,cast(WPARAM)i,MAKELPARAM(int(fDiscardChanges),0)) } Header_ClearFilter :: #force_inline proc "system" (hwnd: HWND, i: c_int) -> BOOL { return cast(BOOL)SendMessageW(hwnd,HDM_CLEARFILTER,cast(WPARAM)i,0) @@ -573,10 +574,10 @@ Button_GetTextMargin :: #force_inline proc "system" (hwnd: HWND, pmargin: ^RECT) return cast(BOOL)SendMessageW(hwnd, BCM_GETTEXTMARGIN, 0, cast(LPARAM)uintptr(pmargin)) } Button_SetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(psz)) + return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(rawptr(psz))) } Button_GetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR, pcc: ^c_int) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(psz)) + return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(rawptr(psz))) } Button_GetNoteLength :: #force_inline proc "system" (hwnd: HWND) -> LRESULT { return SendMessageW(hwnd, BCM_GETNOTELENGTH, 0, 0) @@ -604,10 +605,10 @@ EDITBALLOONTIP :: struct { PEDITBALLOONTIP :: ^EDITBALLOONTIP Edit_SetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(lpcwText)) + return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(rawptr(lpcwText))) } Edit_SetCueBannerTextFocused :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR, fDrawFocused: BOOL) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(lpcwText)) + return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(rawptr(lpcwText))) } Edit_GetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpwText: LPWSTR, cchText: LONG) -> BOOL { return cast(BOOL)SendMessageW(hwnd, EM_GETCUEBANNER, uintptr(lpwText), cast(LPARAM)cchText) @@ -1197,13 +1198,13 @@ ListView_GetItemPosition :: #force_inline proc "system" (hwnd: HWND, i: c_int, p return cast(BOOL)SendMessageW(hwnd, LVM_GETITEMPOSITION, cast(WPARAM)i, cast(LPARAM)uintptr(ppt)) } ListView_GetStringWidth :: #force_inline proc "system" (hwndLV: HWND, psz: LPCWSTR) -> c_int { - return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(psz)) + return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(rawptr(psz))) } ListView_HitTest :: #force_inline proc "system" (hwndLV: HWND, pinfo: ^LV_HITTESTINFO) -> c_int { return cast(c_int)SendMessageW(hwndLV, LVM_HITTEST, 0, cast(LPARAM)uintptr(pinfo)) } ListView_EnsureVisible :: #force_inline proc "system" (hwndLV: HWND, i: c_int, fPartialOK: BOOL) -> BOOL { - return cast(BOOL)SendMessageW(hwndLV, LVM_ENSUREVISIBLE, cast(WPARAM)i, MAKELPARAM(fPartialOK,0)) + return cast(BOOL)SendMessageW(hwndLV, LVM_ENSUREVISIBLE, cast(WPARAM)i, MAKELPARAM(int(fPartialOK),0)) } ListView_Scroll :: #force_inline proc "system" (hwndLV: HWND, dx,dy: c_int) -> BOOL { return cast(BOOL)SendMessageW(hwndLV, LVM_SCROLL, cast(WPARAM)dx, cast(LPARAM)dy) @@ -1609,9 +1610,9 @@ LPTV_ITEMEXW :: LPTVITEMEXW TVINSERTSTRUCTW :: struct { hParent: HTREEITEM, hInsertAfter: HTREEITEM, - _: struct #raw_union { - itemex: TVITEMEXW, - item: TV_ITEMW, + using _: struct #raw_union { + itemex: TVITEMEXW, + item: TV_ITEMW, }, } TV_INSERTSTRUCTW :: TVINSERTSTRUCTW @@ -1703,7 +1704,7 @@ TreeView_Expand :: #force_inline proc "system" (hwnd: HWND, hitem: HTREEITEM, co } TreeView_GetItemRect :: #force_inline proc "system" (hwnd: HWND, hitem: HTREEITEM, prc: ^RECT, code: UINT) -> BOOL { alias: struct #raw_union { - rc: ^RECT, + rc: ^RECT, hitem: ^HTREEITEM, } @@ -2081,7 +2082,7 @@ TabCtrl_DeselectAll :: #force_inline proc "system" (hwnd: HWND, fExcludeFocus: B SendMessageW(hwnd, TCM_DESELECTALL, cast(WPARAM)fExcludeFocus, 0) } TabCtrl_HighlightItem :: #force_inline proc "system" (hwnd: HWND, i: c_int, fHighlight: BOOL) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, TCM_HIGHLIGHTITEM, cast(WPARAM)i, cast(LPARAM)MAKELONG(fHighlight,0)) + return cast(BOOL)SendMessageW(hwnd, TCM_HIGHLIGHTITEM, cast(WPARAM)i, cast(LPARAM)MAKELONG(int(fHighlight),0)) } TabCtrl_SetExtendedStyle :: #force_inline proc "system" (hwnd: HWND, dw: DWORD) -> DWORD { return cast(DWORD)SendMessageW(hwnd, TCM_SETEXTENDEDSTYLE, 0, cast(LPARAM)dw) diff --git a/core/sys/windows/dbghelp.odin b/core/sys/windows/dbghelp.odin index e32b4c874..4904c5fb4 100644 --- a/core/sys/windows/dbghelp.odin +++ b/core/sys/windows/dbghelp.odin @@ -55,23 +55,54 @@ MINIDUMP_CALLBACK_INFORMATION :: struct { CallbackParam: PVOID, } +MINIDUMP_CALLBACK_TYPE :: enum ULONG { + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback, + IsProcessSnapshotCallback, + VmStartCallback, + VmQueryCallback, + VmPreReadCallback, + VmPostReadCallback, +} + +MINIDUMP_SECONDARY_FLAG :: enum ULONG { + WithoutPowerInfo = 0, +} +MINIDUMP_SECONDARY_FLAGS :: distinct bit_set[MINIDUMP_SECONDARY_FLAG; ULONG] +MiniSecondaryWithoutPowerInfo :: MINIDUMP_SECONDARY_FLAGS{.WithoutPowerInfo} +MiniSecondaryValidFlags :: MINIDUMP_SECONDARY_FLAGS{.WithoutPowerInfo} + MINIDUMP_CALLBACK_INPUT :: struct { ProcessId: ULONG, ProcessHandle: HANDLE, - CallbackType: ULONG, + CallbackType: MINIDUMP_CALLBACK_TYPE, using _: struct #raw_union { - Status: HRESULT, - Thread: MINIDUMP_THREAD_CALLBACK, - ThreadEx: MINIDUMP_THREAD_EX_CALLBACK, - Module: MINIDUMP_MODULE_CALLBACK, - IncludeThread: MINIDUMP_INCLUDE_THREAD_CALLBACK, - IncludeModule: MINIDUMP_INCLUDE_MODULE_CALLBACK, - Io: MINIDUMP_IO_CALLBACK, - ReadMemoryFailure: MINIDUMP_READ_MEMORY_FAILURE_CALLBACK, - SecondaryFlags: ULONG, - VmQuery: MINIDUMP_VM_QUERY_CALLBACK, - VmPreRead: MINIDUMP_VM_PRE_READ_CALLBACK, - VmPostRead: MINIDUMP_VM_POST_READ_CALLBACK, + Status: HRESULT `raw_union_tag:"KernelMinidumpStatusCallback"`, + Thread: MINIDUMP_THREAD_CALLBACK `raw_union_tag:"ThreadCallback"`, + ThreadEx: MINIDUMP_THREAD_EX_CALLBACK `raw_union_tag:"ThreadExCallback"`, + Module: MINIDUMP_MODULE_CALLBACK `raw_union_tag:"ModuleCallback"`, + IncludeThread: MINIDUMP_INCLUDE_THREAD_CALLBACK `raw_union_tag:"IncludeThreadCallback"`, + IncludeModule: MINIDUMP_INCLUDE_MODULE_CALLBACK `raw_union_tag:"IncludeModuleCallback"`, + Io: MINIDUMP_IO_CALLBACK `raw_union_tag:"IoStartCallback,IoWriteAllCallback,IoFinishCallback"`, + ReadMemoryFailure: MINIDUMP_READ_MEMORY_FAILURE_CALLBACK `raw_union_tag:"ReadMemoryFailureCallback"`, + SecondaryFlags: MINIDUMP_SECONDARY_FLAGS `raw_union_tag:"SecondaryFlagsCallback"`, + VmQuery: MINIDUMP_VM_QUERY_CALLBACK `raw_union_tag:"VmQueryCallback"`, + VmPreRead: MINIDUMP_VM_PRE_READ_CALLBACK `raw_union_tag:"VmPreReadCallback"`, + VmPostRead: MINIDUMP_VM_POST_READ_CALLBACK `raw_union_tag:"VmPostReadCallback"`, }, } diff --git a/core/sys/windows/dnsapi.odin b/core/sys/windows/dnsapi.odin index 728813696..73e565118 100644 --- a/core/sys/windows/dnsapi.odin +++ b/core/sys/windows/dnsapi.odin @@ -5,6 +5,6 @@ foreign import "system:Dnsapi.lib" @(default_calling_convention="system") foreign Dnsapi { - DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DNS_QUERY_OPTIONS, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- - DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) --- + DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DNS_QUERY_OPTIONS, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- + DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) --- } diff --git a/core/sys/windows/dwmapi.odin b/core/sys/windows/dwmapi.odin index e86730660..0980c2e94 100644 --- a/core/sys/windows/dwmapi.odin +++ b/core/sys/windows/dwmapi.odin @@ -47,9 +47,9 @@ DWM_WINDOW_CORNER_PREFERENCE :: enum c_int { @(default_calling_convention="system") foreign dwmapi { - DwmFlush :: proc() -> HRESULT --- - DwmIsCompositionEnabled :: proc(pfEnabled: ^BOOL) -> HRESULT --- + DwmFlush :: proc() -> HRESULT --- + DwmIsCompositionEnabled :: proc(pfEnabled: ^BOOL) -> HRESULT --- DwmExtendFrameIntoClientArea :: proc(hWnd: HWND, pMarInset: PMARGINS) -> HRESULT --- - DwmGetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: PVOID, cbAttribute: DWORD) -> HRESULT --- - DwmSetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: LPCVOID, cbAttribute: DWORD) -> HRESULT --- + DwmGetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: PVOID, cbAttribute: DWORD) -> HRESULT --- + DwmSetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: LPCVOID, cbAttribute: DWORD) -> HRESULT --- } diff --git a/core/sys/windows/gdi32.odin b/core/sys/windows/gdi32.odin index cf762bb18..2ff346c7e 100644 --- a/core/sys/windows/gdi32.odin +++ b/core/sys/windows/gdi32.odin @@ -1,96 +1,105 @@ #+build windows package sys_windows -import "core:math/fixed" - foreign import gdi32 "system:Gdi32.lib" @(default_calling_convention="system") foreign gdi32 { - GetDeviceCaps :: proc(hdc: HDC, index: INT) -> INT --- + GetDeviceCaps :: proc(hdc: HDC, index: INT) -> INT --- GetStockObject :: proc(i: INT) -> HGDIOBJ --- - SelectObject :: proc(hdc: HDC, h: HGDIOBJ) -> HGDIOBJ --- - DeleteObject :: proc(ho: HGDIOBJ) -> BOOL --- - SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- - SetBkMode :: proc(hdc: HDC, mode: BKMODE) -> INT --- + SelectObject :: proc(hdc: HDC, h: HGDIOBJ) -> HGDIOBJ --- + DeleteObject :: proc(ho: HGDIOBJ) -> BOOL --- + SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- + SetBkMode :: proc(hdc: HDC, mode: BKMODE) -> INT --- CreateCompatibleDC :: proc(hdc: HDC) -> HDC --- - DeleteDC :: proc(hdc: HDC) -> BOOL --- - CancelDC :: proc(hdc: HDC) -> BOOL --- - SaveDC :: proc(hdc: HDC) -> INT --- - RestoreDC :: proc(hdc: HDC, nSavedDC: INT) -> BOOL --- + DeleteDC :: proc(hdc: HDC) -> BOOL --- + CancelDC :: proc(hdc: HDC) -> BOOL --- + SaveDC :: proc(hdc: HDC) -> INT --- + RestoreDC :: proc(hdc: HDC, nSavedDC: INT) -> BOOL --- CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH --- - CreateDIBitmap :: proc(hdc: HDC, pbmih: ^BITMAPINFOHEADER, flInit: DWORD, pjBits: VOID, pbmi: ^BITMAPINFO, iUsage: UINT) -> HBITMAP --- - CreateDIBSection :: proc(hdc: HDC, pbmi: ^BITMAPINFO, usage: UINT, ppvBits: ^^VOID, hSection: HANDLE, offset: DWORD) -> HBITMAP --- - StretchDIBits :: proc(hdc: HDC, xDest, yDest, DestWidth, DestHeight, xSrc, ySrc, SrcWidth, SrcHeight: INT, lpBits: VOID, lpbmi: ^BITMAPINFO, iUsage: UINT, rop: DWORD) -> INT --- - StretchBlt :: proc(hdcDest: HDC, xDest, yDest, wDest, hDest: INT, hdcSrc: HDC, xSrc, ySrc, wSrc, hSrc: INT, rop: DWORD) -> BOOL --- + CreateBitmap :: proc(nWidth: INT, nHeight: INT, nPlanes: UINT, nBitCount: UINT, lpBits: LPVOID) -> HBITMAP --- + CreateDIBitmap :: proc(hdc: HDC, pbmih: ^BITMAPINFOHEADER, flInit: DWORD, pjBits: PVOID, pbmi: ^BITMAPINFO, iUsage: UINT) -> HBITMAP --- + CreateDIBSection :: proc(hdc: HDC, pbmi: ^BITMAPINFO, usage: UINT, ppvBits: ^PVOID, hSection: HANDLE, offset: DWORD) -> HBITMAP --- + StretchDIBits :: proc(hdc: HDC, xDest, yDest, DestWidth, DestHeight, xSrc, ySrc, SrcWidth, SrcHeight: INT, lpBits: LPVOID, lpbmi: ^BITMAPINFO, iUsage: UINT, rop: DWORD) -> INT --- + StretchBlt :: proc(hdcDest: HDC, xDest, yDest, wDest, hDest: INT, hdcSrc: HDC, xSrc, ySrc, wSrc, hSrc: INT, rop: DWORD) -> BOOL --- - SetPixelFormat :: proc(hdc: HDC, format: INT, ppfd: ^PIXELFORMATDESCRIPTOR) -> BOOL --- - ChoosePixelFormat :: proc(hdc: HDC, ppfd: ^PIXELFORMATDESCRIPTOR) -> INT --- + SetPixelFormat :: proc(hdc: HDC, format: INT, ppfd: ^PIXELFORMATDESCRIPTOR) -> BOOL --- + ChoosePixelFormat :: proc(hdc: HDC, ppfd: ^PIXELFORMATDESCRIPTOR) -> INT --- DescribePixelFormat :: proc(hdc: HDC, iPixelFormat: INT, nBytes: UINT, ppfd: ^PIXELFORMATDESCRIPTOR) -> INT --- - SwapBuffers :: proc(hdc: HDC) -> BOOL --- + SwapBuffers :: proc(hdc: HDC) -> BOOL --- SetDCBrushColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- GetDCBrushColor :: proc(hdc: HDC) -> COLORREF --- - PatBlt :: proc(hdc: HDC, x, y, w, h: INT, rop: DWORD) -> BOOL --- - Rectangle :: proc(hdc: HDC, left, top, right, bottom: INT) -> BOOL --- + PatBlt :: proc(hdc: HDC, x, y, w, h: INT, rop: DWORD) -> BOOL --- - CreateFontW :: proc(cHeight, cWidth, cEscapement, cOrientation, cWeight: INT, bItalic, bUnderline, bStrikeOut, iCharSet, iOutPrecision: DWORD, iClipPrecision, iQuality, iPitchAndFamily: DWORD, pszFaceName: LPCWSTR) -> HFONT --- - CreateFontIndirectW :: proc(lplf: ^LOGFONTW) -> HFONT --- + CreateFontW :: proc(cHeight, cWidth, cEscapement, cOrientation, cWeight: INT, bItalic, bUnderline, bStrikeOut, iCharSet, iOutPrecision: DWORD, iClipPrecision, iQuality, iPitchAndFamily: DWORD, pszFaceName: LPCWSTR) -> HFONT --- + CreateFontIndirectW :: proc(lplf: ^LOGFONTW) -> HFONT --- CreateFontIndirectExW :: proc(unnamedParam1: ^ENUMLOGFONTEXDVW) -> HFONT --- - AddFontResourceW :: proc(unnamedParam1: LPCWSTR) -> INT --- - AddFontResourceExW :: proc(name: LPCWSTR, fl: DWORD, res: PVOID) -> INT --- - AddFontMemResourceEx :: proc(pFileView: PVOID, cjSize: DWORD, pvResrved: PVOID, pNumFonts: ^DWORD) -> HANDLE --- - EnumFontsW :: proc(hdc: HDC, lpLogfont: LPCWSTR, lpProc: FONTENUMPROCW, lParam: LPARAM) -> INT --- - EnumFontFamiliesW :: proc(hdc: HDC, lpLogfont: LPCWSTR, lpProc: FONTENUMPROCW, lParam: LPARAM) -> INT --- - EnumFontFamiliesExW :: proc(hdc: HDC, lpLogfont: LPLOGFONTW, lpProc: FONTENUMPROCW, lParam: LPARAM, dwFlags: DWORD) -> INT --- + AddFontResourceW :: proc(unnamedParam1: LPCWSTR) -> INT --- + AddFontResourceExW :: proc(name: LPCWSTR, fl: DWORD, res: PVOID) -> INT --- + AddFontMemResourceEx :: proc(pFileView: PVOID, cjSize: DWORD, pvResrved: PVOID, pNumFonts: ^DWORD) -> HANDLE --- + EnumFontsW :: proc(hdc: HDC, lpLogfont: LPCWSTR, lpProc: FONTENUMPROCW, lParam: LPARAM) -> INT --- + EnumFontFamiliesW :: proc(hdc: HDC, lpLogfont: LPCWSTR, lpProc: FONTENUMPROCW, lParam: LPARAM) -> INT --- + EnumFontFamiliesExW :: proc(hdc: HDC, lpLogfont: LPLOGFONTW, lpProc: FONTENUMPROCW, lParam: LPARAM, dwFlags: DWORD) -> INT --- - TextOutW :: proc(hdc: HDC, x, y: INT, lpString: LPCWSTR, c: INT) -> BOOL --- + TextOutW :: proc(hdc: HDC, x, y: INT, lpString: LPCWSTR, c: INT) -> BOOL --- GetTextExtentPoint32W :: proc(hdc: HDC, lpString: LPCWSTR, c: INT, psizl: LPSIZE) -> BOOL --- - GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL --- + GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL --- CreateSolidBrush :: proc(color: COLORREF) -> HBRUSH --- - GetObjectW :: proc(h: HANDLE, c: INT, pv: LPVOID) -> int --- + GetObjectW :: proc(h: HANDLE, c: INT, pv: LPVOID) -> c_int --- CreateCompatibleBitmap :: proc(hdc: HDC, cx, cy: INT) -> HBITMAP --- - BitBlt :: proc(hdc: HDC, x, y, cx, cy: INT, hdcSrc: HDC, x1, y1: INT, rop: DWORD) -> BOOL --- - GetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start, cLines: UINT, lpvBits: LPVOID, lpbmi: ^BITMAPINFO, usage: UINT) -> INT --- - SetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start: UINT, cLines: UINT, lpBits: VOID, lpbmi: ^BITMAPINFO, ColorUse: UINT) -> INT --- - SetDIBColorTable :: proc(hdc: HDC, iStart: UINT, cEntries: UINT, prgbq: ^RGBQUAD) -> UINT --- - GetDIBColorTable :: proc(hdc: HDC, iStart: UINT, cEntries: UINT, prgbq: ^RGBQUAD) -> UINT --- + BitBlt :: proc(hdc: HDC, x, y, cx, cy: INT, hdcSrc: HDC, x1, y1: INT, rop: DWORD) -> BOOL --- + GetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start, cLines: UINT, lpvBits: LPVOID, lpbmi: ^BITMAPINFO, usage: UINT) -> INT --- + SetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start: UINT, cLines: UINT, lpBits: PVOID, lpbmi: ^BITMAPINFO, ColorUse: UINT) -> INT --- + SetDIBColorTable :: proc(hdc: HDC, iStart: UINT, cEntries: UINT, prgbq: ^RGBQUAD) -> UINT --- + GetDIBColorTable :: proc(hdc: HDC, iStart: UINT, cEntries: UINT, prgbq: ^RGBQUAD) -> UINT --- - CreatePen :: proc(iStyle, cWidth: INT, color: COLORREF) -> HPEN --- - ExtCreatePen :: proc(iPenStyle, cWidth: DWORD, plbrush: ^LOGBRUSH, cStyle: DWORD, pstyle: ^DWORD) -> HPEN --- + CreatePen :: proc(iStyle, cWidth: INT, color: COLORREF) -> HPEN --- + ExtCreatePen :: proc(iPenStyle, cWidth: DWORD, plbrush: ^LOGBRUSH, cStyle: DWORD, pstyle: ^DWORD) -> HPEN --- SetDCPenColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- GetDCPenColor :: proc(hdc: HDC) -> COLORREF --- - CreatePalette :: proc(plpal: ^LOGPALETTE) -> HPALETTE --- - SelectPalette :: proc(hdc: HDC, hPal: HPALETTE, bForceBkgd: BOOL) -> HPALETTE --- + CreatePalette :: proc(plpal: ^LOGPALETTE) -> HPALETTE --- + SelectPalette :: proc(hdc: HDC, hPal: HPALETTE, bForceBkgd: BOOL) -> HPALETTE --- RealizePalette :: proc(hdc: HDC) -> UINT --- SetTextColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- - RoundRect :: proc(hdc: HDC, left: INT, top: INT, right: INT, bottom: INT, width: INT, height: INT) -> BOOL --- - SetPixel :: proc(hdc: HDC, x: INT, y: INT, color: COLORREF) -> COLORREF --- + SetPixel :: proc(hdc: HDC, x: INT, y: INT, color: COLORREF) -> COLORREF --- GdiTransparentBlt :: proc(hdcDest: HDC, xoriginDest, yoriginDest, wDest, hDest: INT, hdcSrc: HDC, xoriginSrc, yoriginSrc, wSrc, hSrc: INT, crTransparent: UINT) -> BOOL --- - GdiGradientFill :: proc(hdc: HDC, pVertex: PTRIVERTEX, nVertex: ULONG, pMesh: PVOID, nCount: ULONG, ulMode: ULONG) -> BOOL --- - GdiAlphaBlend :: proc(hdcDest: HDC, xoriginDest, yoriginDest, wDest, hDest: INT, hdcSrc: HDC, xoriginSrc, yoriginSrc, wSrc, hSrc: INT, ftn: BLENDFUNCTION) -> BOOL --- + GdiGradientFill :: proc(hdc: HDC, pVertex: PTRIVERTEX, nVertex: ULONG, pMesh: PVOID, nCount: ULONG, ulMode: ULONG) -> BOOL --- + GdiAlphaBlend :: proc(hdcDest: HDC, xoriginDest, yoriginDest, wDest, hDest: INT, hdcSrc: HDC, xoriginSrc, yoriginSrc, wSrc, hSrc: INT, ftn: BLENDFUNCTION) -> BOOL --- + + // Filled Shape Functions + Rectangle :: proc(hdc: HDC, left, top, right, bottom: c_int) -> BOOL --- + Ellipse :: proc(hdc: HDC, left, top, right, bottom: c_int) -> BOOL --- + RoundRect :: proc(hdc: HDC, left, top, right, bottom, width, height: c_int) -> BOOL --- + Pie :: proc(hdc: HDC, left, right, top, bottom, xr1, yr1, xr2, yr2: c_int) -> BOOL --- + Chord :: proc(hdc: HDC, x1, y1, x2, y2, x3, y3, x4, y4: c_int) -> BOOL --- + Polygon :: proc(hdc: HDC, apt: [^]POINT, cpt: c_int) -> BOOL --- + PolyPolygon :: proc(hdc: HDC, apt: [^]POINT, asz: [^]c_int, csz: c_int) -> BOOL --- } +@(require_results) RGB :: #force_inline proc "contextless" (#any_int r, g, b: int) -> COLORREF { return COLORREF(DWORD(BYTE(r)) | (DWORD(BYTE(g)) << 8) | (DWORD(BYTE(b)) << 16)) } +@(require_results) PALETTERGB :: #force_inline proc "contextless" (#any_int r, g, b: int) -> COLORREF { return 0x02000000 | RGB(r, g, b) } +@(require_results) PALETTEINDEX :: #force_inline proc "contextless" (#any_int i: int) -> COLORREF { return COLORREF(DWORD(0x01000000) | DWORD(WORD(i))) } -FXPT2DOT30 :: distinct fixed.Fixed(i32, 30) +FXPT2DOT30 :: distinct i32 // fixed.Fixed(i32, 30) CIEXYZ :: struct { ciexyzX, ciexyzY, ciexyzZ: FXPT2DOT30, @@ -143,6 +152,13 @@ BKMODE :: enum { OPAQUE = 2, } +ICONINFO :: struct { + fIcon: BOOL, + xHotspot, yHotspot: DWORD, + hbmMask, hbmColor: HBITMAP, +} +PICONINFO :: ^ICONINFO + ICONINFOEXW :: struct { cbSize: DWORD, fIcon: BOOL, @@ -154,17 +170,21 @@ ICONINFOEXW :: struct { } PICONINFOEXW :: ^ICONINFOEXW -AC_SRC_OVER :: 0x00 +AC_SRC_OVER :: 0x00 AC_SRC_ALPHA :: 0x01 TransparentBlt :: GdiTransparentBlt -GradientFill :: GdiGradientFill -AlphaBlend :: GdiAlphaBlend +GradientFill :: GdiGradientFill +AlphaBlend :: GdiAlphaBlend COLOR16 :: USHORT TRIVERTEX :: struct { - x, y: LONG, - Red, Green, Blue, Alpha: COLOR16, + x: LONG, + y: LONG, + Red: COLOR16, + Green: COLOR16, + Blue: COLOR16, + Alpha: COLOR16, } PTRIVERTEX :: ^TRIVERTEX @@ -179,7 +199,10 @@ GRADIENT_RECT :: struct { PGRADIENT_RECT :: ^GRADIENT_RECT BLENDFUNCTION :: struct { - BlendOp, BlendFlags, SourceConstantAlpha, AlphaFormat: BYTE, + BlendOp: BYTE, + BlendFlags: BYTE, + SourceConstantAlpha: BYTE, + AlphaFormat: BYTE, } GRADIENT_FILL_RECT_H : ULONG : 0x00000000 @@ -350,4 +373,4 @@ NEWTEXTMETRICW :: struct { ntmAvgWidth: UINT, } -FONTENUMPROCW :: #type proc(lpelf: ^ENUMLOGFONTW, lpntm: ^NEWTEXTMETRICW, FontType: DWORD, lParam: LPARAM) -> INT +FONTENUMPROCW :: #type proc "system" (lpelf: ^ENUMLOGFONTW, lpntm: ^NEWTEXTMETRICW, FontType: DWORD, lParam: LPARAM) -> INT diff --git a/core/sys/windows/hidpi.odin b/core/sys/windows/hidpi.odin index 5e9787527..2cf2b2f34 100644 --- a/core/sys/windows/hidpi.odin +++ b/core/sys/windows/hidpi.odin @@ -1,213 +1,212 @@ #+build windows package sys_windows -import "core:c" HIDD_CONFIGURATION :: struct { - cookie: PVOID, - size: ULONG, + cookie: PVOID, + size: ULONG, RingBufferSize: ULONG, } PHIDD_CONFIGURATION :: ^HIDD_CONFIGURATION HIDD_ATTRIBUTES :: struct { - Size: ULONG, - VendorID: USHORT, - ProductID: USHORT, + Size: ULONG, + VendorID: USHORT, + ProductID: USHORT, VersionNumber: USHORT, } PHIDD_ATTRIBUTES :: ^HIDD_ATTRIBUTES HIDP_CAPS :: struct { - Usage: USAGE, - UsagePage: USAGE, - InputReportByteLength: USHORT, - OutputReportByteLength: USHORT, - FeatureReportByteLength: USHORT, - Reserved: [17]USHORT, + Usage: USAGE, + UsagePage: USAGE, + InputReportByteLength: USHORT, + OutputReportByteLength: USHORT, + FeatureReportByteLength: USHORT, + Reserved: [17]USHORT, NumberLinkCollectionNodes: USHORT, - NumberInputButtonCaps: USHORT, - NumberInputValueCaps: USHORT, - NumberInputDataIndices: USHORT, - NumberOutputButtonCaps: USHORT, - NumberOutputValueCaps: USHORT, - NumberOutputDataIndices: USHORT, - NumberFeatureButtonCaps: USHORT, - NumberFeatureValueCaps: USHORT, - NumberFeatureDataIndices: USHORT, + NumberInputButtonCaps: USHORT, + NumberInputValueCaps: USHORT, + NumberInputDataIndices: USHORT, + NumberOutputButtonCaps: USHORT, + NumberOutputValueCaps: USHORT, + NumberOutputDataIndices: USHORT, + NumberFeatureButtonCaps: USHORT, + NumberFeatureValueCaps: USHORT, + NumberFeatureDataIndices: USHORT, } PHIDP_CAPS :: ^HIDP_CAPS HIDP_BUTTON_CAPS :: struct { - UsagePage: USAGE, - ReportID: UCHAR, - IsAlias: BOOLEAN, - BitField: USHORT, - LinkCollection: USHORT, - LinkUsage: USAGE, - LinkUsagePage: USAGE, - IsRange: BOOLEAN, - IsStringRange: BOOLEAN, + UsagePage: USAGE, + ReportID: UCHAR, + IsAlias: BOOLEAN, + BitField: USHORT, + LinkCollection: USHORT, + LinkUsage: USAGE, + LinkUsagePage: USAGE, + IsRange: BOOLEAN, + IsStringRange: BOOLEAN, IsDesignatorRange: BOOLEAN, - IsAbsolute: BOOLEAN, - ReportCount: USHORT, - Reserved2: USHORT, - Reserved: [9]ULONG, + IsAbsolute: BOOLEAN, + ReportCount: USHORT, + Reserved2: USHORT, + Reserved: [9]ULONG, using _: struct #raw_union { Range: struct { - UsageMin: USAGE, - UsageMax: USAGE, - StringMin: USHORT, - StringMax: USHORT, + UsageMin: USAGE, + UsageMax: USAGE, + StringMin: USHORT, + StringMax: USHORT, DesignatorMin: USHORT, DesignatorMax: USHORT, - DataIndexMin: USHORT, - DataIndexMax: USHORT, - }, + DataIndexMin: USHORT, + DataIndexMax: USHORT, + } `raw_union_tag:"IsRange=true"`, NotRange: struct { - Usage: USAGE, - Reserved1: USAGE, - StringIndex: USHORT, - Reserved2: USHORT, + Usage: USAGE, + Reserved1: USAGE, + StringIndex: USHORT, + Reserved2: USHORT, DesignatorIndex: USHORT, - Reserved3: USHORT, - DataIndex: USHORT, - Reserved4: USHORT, - }, + Reserved3: USHORT, + DataIndex: USHORT, + Reserved4: USHORT, + } `raw_union_tag:"IsRange=false"`, }, } PHIDP_BUTTON_CAPS :: ^HIDP_BUTTON_CAPS HIDP_VALUE_CAPS :: struct { - UsagePage: USAGE, - ReportID: UCHAR, - IsAlias: BOOLEAN, - BitField: USHORT, - LinkCollection: USHORT, - LinkUsage: USAGE, - LinkUsagePage: USAGE, - IsRange: BOOLEAN, - IsStringRange: BOOLEAN, + UsagePage: USAGE, + ReportID: UCHAR, + IsAlias: BOOLEAN, + BitField: USHORT, + LinkCollection: USHORT, + LinkUsage: USAGE, + LinkUsagePage: USAGE, + IsRange: BOOLEAN, + IsStringRange: BOOLEAN, IsDesignatorRange: BOOLEAN, - IsAbsolute: BOOLEAN, - HasNull: BOOLEAN, - Reserved: UCHAR, - BitSize: USHORT, - ReportCount: USHORT, - Reserved2: [5]USHORT, - UnitsExp: ULONG, - Units: ULONG, - LogicalMin: LONG, - LogicalMax: LONG, - PhysicalMin: LONG, - PhysicalMax: LONG, + IsAbsolute: BOOLEAN, + HasNull: BOOLEAN, + Reserved: UCHAR, + BitSize: USHORT, + ReportCount: USHORT, + Reserved2: [5]USHORT, + UnitsExp: ULONG, + Units: ULONG, + LogicalMin: LONG, + LogicalMax: LONG, + PhysicalMin: LONG, + PhysicalMax: LONG, using _: struct #raw_union { Range: struct { - UsageMin: USAGE, - UsageMax: USAGE, - StringMin: USHORT, - StringMax: USHORT, + UsageMin: USAGE, + UsageMax: USAGE, + StringMin: USHORT, + StringMax: USHORT, DesignatorMin: USHORT, DesignatorMax: USHORT, - DataIndexMin: USHORT, - DataIndexMax: USHORT, - }, + DataIndexMin: USHORT, + DataIndexMax: USHORT, + } `raw_union_tag:"IsRange=true"`, NotRange: struct { - Usage: USAGE, - Reserved1: USAGE, - StringIndex: USHORT, - Reserved2: USHORT, + Usage: USAGE, + Reserved1: USAGE, + StringIndex: USHORT, + Reserved2: USHORT, DesignatorIndex: USHORT, - Reserved3: USHORT, - DataIndex: USHORT, - Reserved4: USHORT, - }, + Reserved3: USHORT, + DataIndex: USHORT, + Reserved4: USHORT, + } `raw_union_tag:"IsRange=false"`, }, } PHIDP_VALUE_CAPS :: ^HIDP_VALUE_CAPS HIDP_DATA :: struct { DataIndex: USHORT, - Reserved: USHORT, + Reserved: USHORT, using _ : struct #raw_union { RawValue: ULONG, - On: BOOLEAN, + On: BOOLEAN, }, } PHIDP_DATA :: ^HIDP_DATA HIDP_LINK_COLLECTION_NODE :: struct { - LinkUsage: USAGE, - LinkUsagePage: USAGE, - Parent: USHORT, + LinkUsage: USAGE, + LinkUsagePage: USAGE, + Parent: USHORT, NumberOfChildren: USHORT, - NextSibling: USHORT, - FirstChild: USHORT, - CollectionType: [8]ULONG, - IsAlias: [1]ULONG, - Reserved: [23]ULONG, - UserContext: PVOID, + NextSibling: USHORT, + FirstChild: USHORT, + CollectionType: [8]ULONG, + IsAlias: [1]ULONG, + Reserved: [23]ULONG, + UserContext: PVOID, } PHIDP_LINK_COLLECTION_NODE :: ^HIDP_LINK_COLLECTION_NODE HIDP_PREPARSED_DATA :: rawptr PHIDP_PREPARSED_DATA :: ^HIDP_PREPARSED_DATA -HIDP_REPORT_TYPE :: enum c.int { +HIDP_REPORT_TYPE :: enum c_int { Input, Output, Feature, } -HIDP_STATUS_SUCCESS : NTSTATUS : 0x110000 -HIDP_STATUS_NULL : NTSTATUS : -2146369535 //0x80110001 -HIDP_STATUS_INVALID_PREPARSED_DATA : NTSTATUS : -1072627711 //0xC0110001 -HIDP_STATUS_INVALID_REPORT_TYPE : NTSTATUS : -1072627710 //0xC0110002 -HIDP_STATUS_INVALID_REPORT_LENGTH : NTSTATUS : -1072627709 //0xC0110003 -HIDP_STATUS_USAGE_NOT_FOUND : NTSTATUS : -1072627708 //0xC0110004 -HIDP_STATUS_VALUE_OUT_OF_RANGE : NTSTATUS : -1072627707 //0xC0110005 -HIDP_STATUS_BAD_LOG_PHY_VALUES : NTSTATUS : -1072627706 //0xC0100006 -HIDP_STATUS_BUFFER_TOO_SMALL : NTSTATUS : -1072627705 //0xC0110007 -HIDP_STATUS_INTERNAL_ERROR : NTSTATUS : -1072627704 //0xC0110008 -HIDP_STATUS_I8042_TRANS_UNKNOWN : NTSTATUS : -1072627703 //0xC0110009 -HIDP_STATUS_INCOMPATIBLE_REPORT_ID : NTSTATUS : -1072627702 //0xC011000A -HIDP_STATUS_NOT_VALUE_ARRAY : NTSTATUS : -1072627701 //0xC011000B -HIDP_STATUS_IS_VALUE_ARRAY : NTSTATUS : -1072627700 //0xC011000C -HIDP_STATUS_DATA_INDEX_NOT_FOUND : NTSTATUS : -1072627699 //0xC011000D +HIDP_STATUS_SUCCESS : NTSTATUS : 0x110000 +HIDP_STATUS_NULL : NTSTATUS : -2146369535 //0x80110001 +HIDP_STATUS_INVALID_PREPARSED_DATA : NTSTATUS : -1072627711 //0xC0110001 +HIDP_STATUS_INVALID_REPORT_TYPE : NTSTATUS : -1072627710 //0xC0110002 +HIDP_STATUS_INVALID_REPORT_LENGTH : NTSTATUS : -1072627709 //0xC0110003 +HIDP_STATUS_USAGE_NOT_FOUND : NTSTATUS : -1072627708 //0xC0110004 +HIDP_STATUS_VALUE_OUT_OF_RANGE : NTSTATUS : -1072627707 //0xC0110005 +HIDP_STATUS_BAD_LOG_PHY_VALUES : NTSTATUS : -1072627706 //0xC0100006 +HIDP_STATUS_BUFFER_TOO_SMALL : NTSTATUS : -1072627705 //0xC0110007 +HIDP_STATUS_INTERNAL_ERROR : NTSTATUS : -1072627704 //0xC0110008 +HIDP_STATUS_I8042_TRANS_UNKNOWN : NTSTATUS : -1072627703 //0xC0110009 +HIDP_STATUS_INCOMPATIBLE_REPORT_ID : NTSTATUS : -1072627702 //0xC011000A +HIDP_STATUS_NOT_VALUE_ARRAY : NTSTATUS : -1072627701 //0xC011000B +HIDP_STATUS_IS_VALUE_ARRAY : NTSTATUS : -1072627700 //0xC011000C +HIDP_STATUS_DATA_INDEX_NOT_FOUND : NTSTATUS : -1072627699 //0xC011000D HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE : NTSTATUS : -1072627698 //0xC011000E -HIDP_STATUS_BUTTON_NOT_PRESSED : NTSTATUS : -1072627697 //0xC011000F -HIDP_STATUS_REPORT_DOES_NOT_EXIST : NTSTATUS : -1072627696 //0xC0110010 -HIDP_STATUS_NOT_IMPLEMENTED : NTSTATUS : -1072627680 //0xC0110020 -HIDP_STATUS_NOT_BUTTON_ARRAY : NTSTATUS : -1072627679 //0xC0110021 +HIDP_STATUS_BUTTON_NOT_PRESSED : NTSTATUS : -1072627697 //0xC011000F +HIDP_STATUS_REPORT_DOES_NOT_EXIST : NTSTATUS : -1072627696 //0xC0110010 +HIDP_STATUS_NOT_IMPLEMENTED : NTSTATUS : -1072627680 //0xC0110020 +HIDP_STATUS_NOT_BUTTON_ARRAY : NTSTATUS : -1072627679 //0xC0110021 HIDP_STATUS_I8242_TRANS_UNKNOWN :: HIDP_STATUS_I8042_TRANS_UNKNOWN foreign import hid "system:hid.lib" @(default_calling_convention="system") foreign hid { - HidP_GetCaps :: proc(PreparsedData: PHIDP_PREPARSED_DATA, Capabilities: PHIDP_CAPS) -> NTSTATUS --- - HidP_GetButtonCaps :: proc(ReportType: HIDP_REPORT_TYPE, ButtonCaps: PHIDP_BUTTON_CAPS, ButtonCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- - HidP_GetValueCaps :: proc(ReportType: HIDP_REPORT_TYPE, ValueCaps: PHIDP_VALUE_CAPS, ValueCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- - HidP_GetUsages :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, UsageList: PUSAGE, UsageLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- - HidP_GetUsageValue :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, Usage: USAGE, UsageValue: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- - HidP_GetData :: proc(ReportType: HIDP_REPORT_TYPE, DataList: PHIDP_DATA, DataLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- + HidP_GetCaps :: proc(PreparsedData: PHIDP_PREPARSED_DATA, Capabilities: PHIDP_CAPS) -> NTSTATUS --- + HidP_GetButtonCaps :: proc(ReportType: HIDP_REPORT_TYPE, ButtonCaps: PHIDP_BUTTON_CAPS, ButtonCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- + HidP_GetValueCaps :: proc(ReportType: HIDP_REPORT_TYPE, ValueCaps: PHIDP_VALUE_CAPS, ValueCapsLength: PUSHORT, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- + HidP_GetUsages :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, UsageList: PUSAGE, UsageLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- + HidP_GetUsageValue :: proc(ReportType: HIDP_REPORT_TYPE, UsagePage: USAGE, LinkCollection: USHORT, Usage: USAGE, UsageValue: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- + HidP_GetData :: proc(ReportType: HIDP_REPORT_TYPE, DataList: PHIDP_DATA, DataLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA, Report: PCHAR, ReportLength: ULONG) -> NTSTATUS --- HidP_GetLinkCollectionNodes :: proc(LinkCollectionNodes: PHIDP_LINK_COLLECTION_NODE, LinkCollectionNodesLength: PULONG, PreparsedData: PHIDP_PREPARSED_DATA) -> NTSTATUS --- - HidD_GetAttributes :: proc(HidDeviceObject: HANDLE, Attributes: PHIDD_ATTRIBUTES) -> BOOLEAN --- - HidD_GetHidGuid :: proc(HidGuid: LPGUID) --- - HidD_GetPreparsedData :: proc(HidDeviceObject: HANDLE, PreparsedData: ^PHIDP_PREPARSED_DATA) -> BOOLEAN --- - HidD_FreePreparsedData :: proc(PreparsedData: PHIDP_PREPARSED_DATA) -> BOOLEAN --- - HidD_FlushQueue :: proc(HidDeviceObject: HANDLE) -> BOOLEAN --- - HidD_GetConfiguration :: proc(HidDeviceObject: HANDLE, Configuration: PHIDD_CONFIGURATION, ConfigurationLength: ULONG) -> BOOLEAN --- - HidD_SetConfiguration :: proc(HidDeviceObject: HANDLE, Configuration: PHIDD_CONFIGURATION, ConfigurationLength: ULONG) -> BOOLEAN --- - HidD_GetFeature :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- - HidD_SetFeature :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- - HidD_GetInputReport :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- - HidD_SetOutputReport :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- - HidD_GetNumInputBuffers :: proc(HidDeviceObject: HANDLE, NumberBuffers: PULONG) -> BOOLEAN --- - HidD_SetNumInputBuffers :: proc(HidDeviceObject: HANDLE, NumberBuffers: ULONG) -> BOOLEAN --- + HidD_GetAttributes :: proc(HidDeviceObject: HANDLE, Attributes: PHIDD_ATTRIBUTES) -> BOOLEAN --- + HidD_GetHidGuid :: proc(HidGuid: LPGUID) --- + HidD_GetPreparsedData :: proc(HidDeviceObject: HANDLE, PreparsedData: ^PHIDP_PREPARSED_DATA) -> BOOLEAN --- + HidD_FreePreparsedData :: proc(PreparsedData: PHIDP_PREPARSED_DATA) -> BOOLEAN --- + HidD_FlushQueue :: proc(HidDeviceObject: HANDLE) -> BOOLEAN --- + HidD_GetConfiguration :: proc(HidDeviceObject: HANDLE, Configuration: PHIDD_CONFIGURATION, ConfigurationLength: ULONG) -> BOOLEAN --- + HidD_SetConfiguration :: proc(HidDeviceObject: HANDLE, Configuration: PHIDD_CONFIGURATION, ConfigurationLength: ULONG) -> BOOLEAN --- + HidD_GetFeature :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- + HidD_SetFeature :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- + HidD_GetInputReport :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- + HidD_SetOutputReport :: proc(HidDeviceObject: HANDLE, ReportBuffer: PVOID, ReportBufferLength: ULONG) -> BOOLEAN --- + HidD_GetNumInputBuffers :: proc(HidDeviceObject: HANDLE, NumberBuffers: PULONG) -> BOOLEAN --- + HidD_SetNumInputBuffers :: proc(HidDeviceObject: HANDLE, NumberBuffers: ULONG) -> BOOLEAN --- HidD_GetPhysicalDescriptor :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- HidD_GetManufacturerString :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- - HidD_GetProductString :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- - HidD_GetIndexedString :: proc(HidDeviceObject: HANDLE, StringIndex: ULONG, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- + HidD_GetProductString :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- + HidD_GetIndexedString :: proc(HidDeviceObject: HANDLE, StringIndex: ULONG, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- HidD_GetSerialNumberString :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- - HidD_GetMsGenreDescriptor :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- + HidD_GetMsGenreDescriptor :: proc(HidDeviceObject: HANDLE, Buffer: PVOID, BufferLength: ULONG) -> BOOLEAN --- } diff --git a/core/sys/windows/hidusage.odin b/core/sys/windows/hidusage.odin index eb2a85f2e..5f87bea2d 100644 --- a/core/sys/windows/hidusage.odin +++ b/core/sys/windows/hidusage.odin @@ -4,260 +4,260 @@ package sys_windows USAGE :: distinct USHORT PUSAGE :: ^USAGE -HID_USAGE_PAGE_UNDEFINED :: 0x00 -HID_USAGE_PAGE_GENERIC :: 0x01 -HID_USAGE_PAGE_SIMULATION :: 0x02 -HID_USAGE_PAGE_VR :: 0x03 -HID_USAGE_PAGE_SPORT :: 0x04 -HID_USAGE_PAGE_GAME :: 0x05 -HID_USAGE_PAGE_GENERIC_DEVICE :: 0x06 -HID_USAGE_PAGE_KEYBOARD :: 0x07 -HID_USAGE_PAGE_LED :: 0x08 -HID_USAGE_PAGE_BUTTON :: 0x09 -HID_USAGE_PAGE_ORDINAL :: 0x0A -HID_USAGE_PAGE_TELEPHONY :: 0x0B -HID_USAGE_PAGE_CONSUMER :: 0x0C -HID_USAGE_PAGE_DIGITIZER :: 0x0D -HID_USAGE_PAGE_HAPTICS :: 0x0E -HID_USAGE_PAGE_PID :: 0x0F -HID_USAGE_PAGE_UNICODE :: 0x10 -HID_USAGE_PAGE_ALPHANUMERIC :: 0x14 -HID_USAGE_PAGE_SENSOR :: 0x20 -HID_USAGE_PAGE_LIGHTING_ILLUMINATION :: 0x59 -HID_USAGE_PAGE_BARCODE_SCANNER :: 0x8C -HID_USAGE_PAGE_WEIGHING_DEVICE :: 0x8D -HID_USAGE_PAGE_MAGNETIC_STRIPE_READER :: 0x8E -HID_USAGE_PAGE_CAMERA_CONTROL :: 0x90 -HID_USAGE_PAGE_ARCADE :: 0x91 +HID_USAGE_PAGE_UNDEFINED :: 0x00 +HID_USAGE_PAGE_GENERIC :: 0x01 +HID_USAGE_PAGE_SIMULATION :: 0x02 +HID_USAGE_PAGE_VR :: 0x03 +HID_USAGE_PAGE_SPORT :: 0x04 +HID_USAGE_PAGE_GAME :: 0x05 +HID_USAGE_PAGE_GENERIC_DEVICE :: 0x06 +HID_USAGE_PAGE_KEYBOARD :: 0x07 +HID_USAGE_PAGE_LED :: 0x08 +HID_USAGE_PAGE_BUTTON :: 0x09 +HID_USAGE_PAGE_ORDINAL :: 0x0A +HID_USAGE_PAGE_TELEPHONY :: 0x0B +HID_USAGE_PAGE_CONSUMER :: 0x0C +HID_USAGE_PAGE_DIGITIZER :: 0x0D +HID_USAGE_PAGE_HAPTICS :: 0x0E +HID_USAGE_PAGE_PID :: 0x0F +HID_USAGE_PAGE_UNICODE :: 0x10 +HID_USAGE_PAGE_ALPHANUMERIC :: 0x14 +HID_USAGE_PAGE_SENSOR :: 0x20 +HID_USAGE_PAGE_LIGHTING_ILLUMINATION :: 0x59 +HID_USAGE_PAGE_BARCODE_SCANNER :: 0x8C +HID_USAGE_PAGE_WEIGHING_DEVICE :: 0x8D +HID_USAGE_PAGE_MAGNETIC_STRIPE_READER :: 0x8E +HID_USAGE_PAGE_CAMERA_CONTROL :: 0x90 +HID_USAGE_PAGE_ARCADE :: 0x91 HID_USAGE_PAGE_MICROSOFT_BLUETOOTH_HANDSFREE :: 0xFFF3 -HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN :: 0xFF00 -HID_USAGE_PAGE_VENDOR_DEFINED_END :: 0xFFFF +HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN :: 0xFF00 +HID_USAGE_PAGE_VENDOR_DEFINED_END :: 0xFFFF -HID_USAGE_GENERIC_POINTER :: 0x01 -HID_USAGE_GENERIC_MOUSE :: 0x02 -HID_USAGE_GENERIC_JOYSTICK :: 0x04 -HID_USAGE_GENERIC_GAMEPAD :: 0x05 -HID_USAGE_GENERIC_KEYBOARD :: 0x06 -HID_USAGE_GENERIC_KEYPAD :: 0x07 -HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER :: 0x08 -HID_USAGE_GENERIC_TABLET_PC_SYSTEM_CTL :: 0x09 +HID_USAGE_GENERIC_POINTER :: 0x01 +HID_USAGE_GENERIC_MOUSE :: 0x02 +HID_USAGE_GENERIC_JOYSTICK :: 0x04 +HID_USAGE_GENERIC_GAMEPAD :: 0x05 +HID_USAGE_GENERIC_KEYBOARD :: 0x06 +HID_USAGE_GENERIC_KEYPAD :: 0x07 +HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER :: 0x08 +HID_USAGE_GENERIC_TABLET_PC_SYSTEM_CTL :: 0x09 HID_USAGE_GENERIC_PORTABLE_DEVICE_CONTROL :: 0x0D -HID_USAGE_GENERIC_INTERACTIVE_CONTROL :: 0x0E -HID_USAGE_GENERIC_SYSTEM_CTL :: 0x80 +HID_USAGE_GENERIC_INTERACTIVE_CONTROL :: 0x0E +HID_USAGE_GENERIC_SYSTEM_CTL :: 0x80 -HID_USAGE_GENERIC_X :: 0x30 -HID_USAGE_GENERIC_Y :: 0x31 -HID_USAGE_GENERIC_Z :: 0x32 -HID_USAGE_GENERIC_RX :: 0x33 -HID_USAGE_GENERIC_RY :: 0x34 -HID_USAGE_GENERIC_RZ :: 0x35 -HID_USAGE_GENERIC_SLIDER :: 0x36 -HID_USAGE_GENERIC_DIAL :: 0x37 -HID_USAGE_GENERIC_WHEEL :: 0x38 -HID_USAGE_GENERIC_HATSWITCH :: 0x39 -HID_USAGE_GENERIC_COUNTED_BUFFER :: 0x3A -HID_USAGE_GENERIC_BYTE_COUNT :: 0x3B -HID_USAGE_GENERIC_MOTION_WAKEUP :: 0x3C -HID_USAGE_GENERIC_START :: 0x3D -HID_USAGE_GENERIC_SELECT :: 0x3E -HID_USAGE_GENERIC_VX :: 0x40 -HID_USAGE_GENERIC_VY :: 0x41 -HID_USAGE_GENERIC_VZ :: 0x42 -HID_USAGE_GENERIC_VBRX :: 0x43 -HID_USAGE_GENERIC_VBRY :: 0x44 -HID_USAGE_GENERIC_VBRZ :: 0x45 -HID_USAGE_GENERIC_VNO :: 0x46 -HID_USAGE_GENERIC_FEATURE_NOTIFICATION :: 0x47 -HID_USAGE_GENERIC_RESOLUTION_MULTIPLIER :: 0x48 -HID_USAGE_GENERIC_SYSCTL_POWER :: 0x81 -HID_USAGE_GENERIC_SYSCTL_SLEEP :: 0x82 -HID_USAGE_GENERIC_SYSCTL_WAKE :: 0x83 -HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU :: 0x84 -HID_USAGE_GENERIC_SYSCTL_MAIN_MENU :: 0x85 -HID_USAGE_GENERIC_SYSCTL_APP_MENU :: 0x86 -HID_USAGE_GENERIC_SYSCTL_HELP_MENU :: 0x87 -HID_USAGE_GENERIC_SYSCTL_MENU_EXIT :: 0x88 -HID_USAGE_GENERIC_SYSCTL_MENU_SELECT :: 0x89 -HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT :: 0x8A -HID_USAGE_GENERIC_SYSCTL_MENU_LEFT :: 0x8B -HID_USAGE_GENERIC_SYSCTL_MENU_UP :: 0x8C -HID_USAGE_GENERIC_SYSCTL_MENU_DOWN :: 0x8D -HID_USAGE_GENERIC_SYSCTL_COLD_RESTART :: 0x8E -HID_USAGE_GENERIC_SYSCTL_WARM_RESTART :: 0x8F -HID_USAGE_GENERIC_DPAD_UP :: 0x90 -HID_USAGE_GENERIC_DPAD_DOWN :: 0x91 -HID_USAGE_GENERIC_DPAD_RIGHT :: 0x92 -HID_USAGE_GENERIC_DPAD_LEFT :: 0x93 -HID_USAGE_GENERIC_SYSCTL_FN :: 0x97 -HID_USAGE_GENERIC_SYSCTL_FN_LOCK :: 0x98 -HID_USAGE_GENERIC_SYSCTL_FN_LOCK_INDICATOR :: 0x99 -HID_USAGE_GENERIC_SYSCTL_DISMISS_NOTIFICATION :: 0x9A -HID_USAGE_GENERIC_SYSCTL_DOCK :: 0xA0 -HID_USAGE_GENERIC_SYSCTL_UNDOCK :: 0xA1 -HID_USAGE_GENERIC_SYSCTL_SETUP :: 0xA2 -HID_USAGE_GENERIC_SYSCTL_SYS_BREAK :: 0xA3 -HID_USAGE_GENERIC_SYSCTL_SYS_DBG_BREAK :: 0xA4 -HID_USAGE_GENERIC_SYSCTL_APP_BREAK :: 0xA5 -HID_USAGE_GENERIC_SYSCTL_APP_DBG_BREAK :: 0xA6 -HID_USAGE_GENERIC_SYSCTL_MUTE :: 0xA7 -HID_USAGE_GENERIC_SYSCTL_HIBERNATE :: 0xA8 -HID_USAGE_GENERIC_SYSCTL_DISP_INVERT :: 0xB0 -HID_USAGE_GENERIC_SYSCTL_DISP_INTERNAL :: 0xB1 -HID_USAGE_GENERIC_SYSCTL_DISP_EXTERNAL :: 0xB2 -HID_USAGE_GENERIC_SYSCTL_DISP_BOTH :: 0xB3 -HID_USAGE_GENERIC_SYSCTL_DISP_DUAL :: 0xB4 -HID_USAGE_GENERIC_SYSCTL_DISP_TOGGLE :: 0xB5 -HID_USAGE_GENERIC_SYSCTL_DISP_SWAP :: 0xB6 -HID_USAGE_GENERIC_SYSCTL_DISP_AUTOSCALE :: 0xB7 -HID_USAGE_GENERIC_SYSTEM_DISPLAY_ROTATION_LOCK_BUTTON :: 0xC9 +HID_USAGE_GENERIC_X :: 0x30 +HID_USAGE_GENERIC_Y :: 0x31 +HID_USAGE_GENERIC_Z :: 0x32 +HID_USAGE_GENERIC_RX :: 0x33 +HID_USAGE_GENERIC_RY :: 0x34 +HID_USAGE_GENERIC_RZ :: 0x35 +HID_USAGE_GENERIC_SLIDER :: 0x36 +HID_USAGE_GENERIC_DIAL :: 0x37 +HID_USAGE_GENERIC_WHEEL :: 0x38 +HID_USAGE_GENERIC_HATSWITCH :: 0x39 +HID_USAGE_GENERIC_COUNTED_BUFFER :: 0x3A +HID_USAGE_GENERIC_BYTE_COUNT :: 0x3B +HID_USAGE_GENERIC_MOTION_WAKEUP :: 0x3C +HID_USAGE_GENERIC_START :: 0x3D +HID_USAGE_GENERIC_SELECT :: 0x3E +HID_USAGE_GENERIC_VX :: 0x40 +HID_USAGE_GENERIC_VY :: 0x41 +HID_USAGE_GENERIC_VZ :: 0x42 +HID_USAGE_GENERIC_VBRX :: 0x43 +HID_USAGE_GENERIC_VBRY :: 0x44 +HID_USAGE_GENERIC_VBRZ :: 0x45 +HID_USAGE_GENERIC_VNO :: 0x46 +HID_USAGE_GENERIC_FEATURE_NOTIFICATION :: 0x47 +HID_USAGE_GENERIC_RESOLUTION_MULTIPLIER :: 0x48 +HID_USAGE_GENERIC_SYSCTL_POWER :: 0x81 +HID_USAGE_GENERIC_SYSCTL_SLEEP :: 0x82 +HID_USAGE_GENERIC_SYSCTL_WAKE :: 0x83 +HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU :: 0x84 +HID_USAGE_GENERIC_SYSCTL_MAIN_MENU :: 0x85 +HID_USAGE_GENERIC_SYSCTL_APP_MENU :: 0x86 +HID_USAGE_GENERIC_SYSCTL_HELP_MENU :: 0x87 +HID_USAGE_GENERIC_SYSCTL_MENU_EXIT :: 0x88 +HID_USAGE_GENERIC_SYSCTL_MENU_SELECT :: 0x89 +HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT :: 0x8A +HID_USAGE_GENERIC_SYSCTL_MENU_LEFT :: 0x8B +HID_USAGE_GENERIC_SYSCTL_MENU_UP :: 0x8C +HID_USAGE_GENERIC_SYSCTL_MENU_DOWN :: 0x8D +HID_USAGE_GENERIC_SYSCTL_COLD_RESTART :: 0x8E +HID_USAGE_GENERIC_SYSCTL_WARM_RESTART :: 0x8F +HID_USAGE_GENERIC_DPAD_UP :: 0x90 +HID_USAGE_GENERIC_DPAD_DOWN :: 0x91 +HID_USAGE_GENERIC_DPAD_RIGHT :: 0x92 +HID_USAGE_GENERIC_DPAD_LEFT :: 0x93 +HID_USAGE_GENERIC_SYSCTL_FN :: 0x97 +HID_USAGE_GENERIC_SYSCTL_FN_LOCK :: 0x98 +HID_USAGE_GENERIC_SYSCTL_FN_LOCK_INDICATOR :: 0x99 +HID_USAGE_GENERIC_SYSCTL_DISMISS_NOTIFICATION :: 0x9A +HID_USAGE_GENERIC_SYSCTL_DOCK :: 0xA0 +HID_USAGE_GENERIC_SYSCTL_UNDOCK :: 0xA1 +HID_USAGE_GENERIC_SYSCTL_SETUP :: 0xA2 +HID_USAGE_GENERIC_SYSCTL_SYS_BREAK :: 0xA3 +HID_USAGE_GENERIC_SYSCTL_SYS_DBG_BREAK :: 0xA4 +HID_USAGE_GENERIC_SYSCTL_APP_BREAK :: 0xA5 +HID_USAGE_GENERIC_SYSCTL_APP_DBG_BREAK :: 0xA6 +HID_USAGE_GENERIC_SYSCTL_MUTE :: 0xA7 +HID_USAGE_GENERIC_SYSCTL_HIBERNATE :: 0xA8 +HID_USAGE_GENERIC_SYSCTL_DISP_INVERT :: 0xB0 +HID_USAGE_GENERIC_SYSCTL_DISP_INTERNAL :: 0xB1 +HID_USAGE_GENERIC_SYSCTL_DISP_EXTERNAL :: 0xB2 +HID_USAGE_GENERIC_SYSCTL_DISP_BOTH :: 0xB3 +HID_USAGE_GENERIC_SYSCTL_DISP_DUAL :: 0xB4 +HID_USAGE_GENERIC_SYSCTL_DISP_TOGGLE :: 0xB5 +HID_USAGE_GENERIC_SYSCTL_DISP_SWAP :: 0xB6 +HID_USAGE_GENERIC_SYSCTL_DISP_AUTOSCALE :: 0xB7 +HID_USAGE_GENERIC_SYSTEM_DISPLAY_ROTATION_LOCK_BUTTON :: 0xC9 HID_USAGE_GENERIC_SYSTEM_DISPLAY_ROTATION_LOCK_SLIDER_SWITCH :: 0xCA -HID_USAGE_GENERIC_CONTROL_ENABLE :: 0xCB +HID_USAGE_GENERIC_CONTROL_ENABLE :: 0xCB -HID_USAGE_SIMULATION_FLIGHT_SIMULATION_DEVICE :: 0x01 -HID_USAGE_SIMULATION_AUTOMOBILE_SIMULATION_DEVICE :: 0x02 -HID_USAGE_SIMULATION_TANK_SIMULATION_DEVICE :: 0x03 -HID_USAGE_SIMULATION_SPACESHIP_SIMULATION_DEVICE :: 0x04 -HID_USAGE_SIMULATION_SUBMARINE_SIMULATION_DEVICE :: 0x05 -HID_USAGE_SIMULATION_SAILING_SIMULATION_DEVICE :: 0x06 -HID_USAGE_SIMULATION_MOTORCYCLE_SIMULATION_DEVICE :: 0x07 -HID_USAGE_SIMULATION_SPORTS_SIMULATION_DEVICE :: 0x08 -HID_USAGE_SIMULATION_AIRPLANE_SIMULATION_DEVICE :: 0x09 -HID_USAGE_SIMULATION_HELICOPTER_SIMULATION_DEVICE :: 0x0A +HID_USAGE_SIMULATION_FLIGHT_SIMULATION_DEVICE :: 0x01 +HID_USAGE_SIMULATION_AUTOMOBILE_SIMULATION_DEVICE :: 0x02 +HID_USAGE_SIMULATION_TANK_SIMULATION_DEVICE :: 0x03 +HID_USAGE_SIMULATION_SPACESHIP_SIMULATION_DEVICE :: 0x04 +HID_USAGE_SIMULATION_SUBMARINE_SIMULATION_DEVICE :: 0x05 +HID_USAGE_SIMULATION_SAILING_SIMULATION_DEVICE :: 0x06 +HID_USAGE_SIMULATION_MOTORCYCLE_SIMULATION_DEVICE :: 0x07 +HID_USAGE_SIMULATION_SPORTS_SIMULATION_DEVICE :: 0x08 +HID_USAGE_SIMULATION_AIRPLANE_SIMULATION_DEVICE :: 0x09 +HID_USAGE_SIMULATION_HELICOPTER_SIMULATION_DEVICE :: 0x0A HID_USAGE_SIMULATION_MAGIC_CARPET_SIMULATION_DEVICE :: 0x0B -HID_USAGE_SIMULATION_BICYCLE_SIMULATION_DEVICE :: 0x0C -HID_USAGE_SIMULATION_FLIGHT_CONTROL_STICK :: 0x20 -HID_USAGE_SIMULATION_FLIGHT_STICK :: 0x21 -HID_USAGE_SIMULATION_CYCLIC_CONTROL :: 0x22 -HID_USAGE_SIMULATION_CYCLIC_TRIM :: 0x23 -HID_USAGE_SIMULATION_FLIGHT_YOKE :: 0x24 -HID_USAGE_SIMULATION_TRACK_CONTROL :: 0x25 +HID_USAGE_SIMULATION_BICYCLE_SIMULATION_DEVICE :: 0x0C +HID_USAGE_SIMULATION_FLIGHT_CONTROL_STICK :: 0x20 +HID_USAGE_SIMULATION_FLIGHT_STICK :: 0x21 +HID_USAGE_SIMULATION_CYCLIC_CONTROL :: 0x22 +HID_USAGE_SIMULATION_CYCLIC_TRIM :: 0x23 +HID_USAGE_SIMULATION_FLIGHT_YOKE :: 0x24 +HID_USAGE_SIMULATION_TRACK_CONTROL :: 0x25 -HID_USAGE_SIMULATION_AILERON :: 0xB0 -HID_USAGE_SIMULATION_AILERON_TRIM :: 0xB1 -HID_USAGE_SIMULATION_ANTI_TORQUE_CONTROL :: 0xB2 -HID_USAGE_SIMULATION_AUTOPIOLOT_ENABLE :: 0xB3 -HID_USAGE_SIMULATION_CHAFF_RELEASE :: 0xB4 -HID_USAGE_SIMULATION_COLLECTIVE_CONTROL :: 0xB5 -HID_USAGE_SIMULATION_DIVE_BRAKE :: 0xB6 +HID_USAGE_SIMULATION_AILERON :: 0xB0 +HID_USAGE_SIMULATION_AILERON_TRIM :: 0xB1 +HID_USAGE_SIMULATION_ANTI_TORQUE_CONTROL :: 0xB2 +HID_USAGE_SIMULATION_AUTOPIOLOT_ENABLE :: 0xB3 +HID_USAGE_SIMULATION_CHAFF_RELEASE :: 0xB4 +HID_USAGE_SIMULATION_COLLECTIVE_CONTROL :: 0xB5 +HID_USAGE_SIMULATION_DIVE_BRAKE :: 0xB6 HID_USAGE_SIMULATION_ELECTRONIC_COUNTERMEASURES :: 0xB7 -HID_USAGE_SIMULATION_ELEVATOR :: 0xB8 -HID_USAGE_SIMULATION_ELEVATOR_TRIM :: 0xB9 -HID_USAGE_SIMULATION_RUDDER :: 0xBA -HID_USAGE_SIMULATION_THROTTLE :: 0xBB -HID_USAGE_SIMULATION_FLIGHT_COMMUNICATIONS :: 0xBC -HID_USAGE_SIMULATION_FLARE_RELEASE :: 0xBD -HID_USAGE_SIMULATION_LANDING_GEAR :: 0xBE -HID_USAGE_SIMULATION_TOE_BRAKE :: 0xBF -HID_USAGE_SIMULATION_TRIGGER :: 0xC0 -HID_USAGE_SIMULATION_WEAPONS_ARM :: 0xC1 -HID_USAGE_SIMULATION_WEAPONS_SELECT :: 0xC2 -HID_USAGE_SIMULATION_WING_FLAPS :: 0xC3 -HID_USAGE_SIMULATION_ACCELLERATOR :: 0xC4 -HID_USAGE_SIMULATION_BRAKE :: 0xC5 -HID_USAGE_SIMULATION_CLUTCH :: 0xC6 -HID_USAGE_SIMULATION_SHIFTER :: 0xC7 -HID_USAGE_SIMULATION_STEERING :: 0xC8 -HID_USAGE_SIMULATION_TURRET_DIRECTION :: 0xC9 -HID_USAGE_SIMULATION_BARREL_ELEVATION :: 0xCA -HID_USAGE_SIMULATION_DIVE_PLANE :: 0xCB -HID_USAGE_SIMULATION_BALLAST :: 0xCC -HID_USAGE_SIMULATION_BICYCLE_CRANK :: 0xCD -HID_USAGE_SIMULATION_HANDLE_BARS :: 0xCE -HID_USAGE_SIMULATION_FRONT_BRAKE :: 0xCF -HID_USAGE_SIMULATION_REAR_BRAKE :: 0xD0 +HID_USAGE_SIMULATION_ELEVATOR :: 0xB8 +HID_USAGE_SIMULATION_ELEVATOR_TRIM :: 0xB9 +HID_USAGE_SIMULATION_RUDDER :: 0xBA +HID_USAGE_SIMULATION_THROTTLE :: 0xBB +HID_USAGE_SIMULATION_FLIGHT_COMMUNICATIONS :: 0xBC +HID_USAGE_SIMULATION_FLARE_RELEASE :: 0xBD +HID_USAGE_SIMULATION_LANDING_GEAR :: 0xBE +HID_USAGE_SIMULATION_TOE_BRAKE :: 0xBF +HID_USAGE_SIMULATION_TRIGGER :: 0xC0 +HID_USAGE_SIMULATION_WEAPONS_ARM :: 0xC1 +HID_USAGE_SIMULATION_WEAPONS_SELECT :: 0xC2 +HID_USAGE_SIMULATION_WING_FLAPS :: 0xC3 +HID_USAGE_SIMULATION_ACCELLERATOR :: 0xC4 +HID_USAGE_SIMULATION_BRAKE :: 0xC5 +HID_USAGE_SIMULATION_CLUTCH :: 0xC6 +HID_USAGE_SIMULATION_SHIFTER :: 0xC7 +HID_USAGE_SIMULATION_STEERING :: 0xC8 +HID_USAGE_SIMULATION_TURRET_DIRECTION :: 0xC9 +HID_USAGE_SIMULATION_BARREL_ELEVATION :: 0xCA +HID_USAGE_SIMULATION_DIVE_PLANE :: 0xCB +HID_USAGE_SIMULATION_BALLAST :: 0xCC +HID_USAGE_SIMULATION_BICYCLE_CRANK :: 0xCD +HID_USAGE_SIMULATION_HANDLE_BARS :: 0xCE +HID_USAGE_SIMULATION_FRONT_BRAKE :: 0xCF +HID_USAGE_SIMULATION_REAR_BRAKE :: 0xD0 -HID_USAGE_VR_BELT :: 0x01 -HID_USAGE_VR_BODY_SUIT :: 0x02 -HID_USAGE_VR_FLEXOR :: 0x03 -HID_USAGE_VR_GLOVE :: 0x04 -HID_USAGE_VR_HEAD_TRACKER :: 0x05 +HID_USAGE_VR_BELT :: 0x01 +HID_USAGE_VR_BODY_SUIT :: 0x02 +HID_USAGE_VR_FLEXOR :: 0x03 +HID_USAGE_VR_GLOVE :: 0x04 +HID_USAGE_VR_HEAD_TRACKER :: 0x05 HID_USAGE_VR_HEAD_MOUNTED_DISPLAY :: 0x06 -HID_USAGE_VR_HAND_TRACKER :: 0x07 -HID_USAGE_VR_OCULOMETER :: 0x08 -HID_USAGE_VR_VEST :: 0x09 -HID_USAGE_VR_ANIMATRONIC_DEVICE :: 0x0A +HID_USAGE_VR_HAND_TRACKER :: 0x07 +HID_USAGE_VR_OCULOMETER :: 0x08 +HID_USAGE_VR_VEST :: 0x09 +HID_USAGE_VR_ANIMATRONIC_DEVICE :: 0x0A -HID_USAGE_VR_STEREO_ENABLE :: 0x20 +HID_USAGE_VR_STEREO_ENABLE :: 0x20 HID_USAGE_VR_DISPLAY_ENABLE :: 0x21 -HID_USAGE_SPORT_BASEBALL_BAT :: 0x01 -HID_USAGE_SPORT_GOLF_CLUB :: 0x02 +HID_USAGE_SPORT_BASEBALL_BAT :: 0x01 +HID_USAGE_SPORT_GOLF_CLUB :: 0x02 HID_USAGE_SPORT_ROWING_MACHINE :: 0x03 -HID_USAGE_SPORT_TREADMILL :: 0x04 -HID_USAGE_SPORT_STICK_TYPE :: 0x38 +HID_USAGE_SPORT_TREADMILL :: 0x04 +HID_USAGE_SPORT_STICK_TYPE :: 0x38 -HID_USAGE_SPORT_OAR :: 0x30 -HID_USAGE_SPORT_SLOPE :: 0x31 -HID_USAGE_SPORT_RATE :: 0x32 -HID_USAGE_SPORT_STICK_SPEED :: 0x33 +HID_USAGE_SPORT_OAR :: 0x30 +HID_USAGE_SPORT_SLOPE :: 0x31 +HID_USAGE_SPORT_RATE :: 0x32 +HID_USAGE_SPORT_STICK_SPEED :: 0x33 HID_USAGE_SPORT_STICK_FACE_ANGLE :: 0x34 -HID_USAGE_SPORT_HEEL_TOE :: 0x35 -HID_USAGE_SPORT_FOLLOW_THROUGH :: 0x36 -HID_USAGE_SPORT_TEMPO :: 0x37 -HID_USAGE_SPORT_HEIGHT :: 0x39 -HID_USAGE_SPORT_PUTTER :: 0x50 -HID_USAGE_SPORT_1_IRON :: 0x51 -HID_USAGE_SPORT_2_IRON :: 0x52 -HID_USAGE_SPORT_3_IRON :: 0x53 -HID_USAGE_SPORT_4_IRON :: 0x54 -HID_USAGE_SPORT_5_IRON :: 0x55 -HID_USAGE_SPORT_6_IRON :: 0x56 -HID_USAGE_SPORT_7_IRON :: 0x57 -HID_USAGE_SPORT_8_IRON :: 0x58 -HID_USAGE_SPORT_9_IRON :: 0x59 -HID_USAGE_SPORT_10_IRON :: 0x5A -HID_USAGE_SPORT_11_IRON :: 0x5B -HID_USAGE_SPORT_SAND_WEDGE :: 0x5C -HID_USAGE_SPORT_LOFT_WEDGE :: 0x5D -HID_USAGE_SPORT_POWER_WEDGE :: 0x5E -HID_USAGE_SPORT_1_WOOD :: 0x5F -HID_USAGE_SPORT_3_WOOD :: 0x60 -HID_USAGE_SPORT_5_WOOD :: 0x61 -HID_USAGE_SPORT_7_WOOD :: 0x62 -HID_USAGE_SPORT_9_WOOD :: 0x63 +HID_USAGE_SPORT_HEEL_TOE :: 0x35 +HID_USAGE_SPORT_FOLLOW_THROUGH :: 0x36 +HID_USAGE_SPORT_TEMPO :: 0x37 +HID_USAGE_SPORT_HEIGHT :: 0x39 +HID_USAGE_SPORT_PUTTER :: 0x50 +HID_USAGE_SPORT_1_IRON :: 0x51 +HID_USAGE_SPORT_2_IRON :: 0x52 +HID_USAGE_SPORT_3_IRON :: 0x53 +HID_USAGE_SPORT_4_IRON :: 0x54 +HID_USAGE_SPORT_5_IRON :: 0x55 +HID_USAGE_SPORT_6_IRON :: 0x56 +HID_USAGE_SPORT_7_IRON :: 0x57 +HID_USAGE_SPORT_8_IRON :: 0x58 +HID_USAGE_SPORT_9_IRON :: 0x59 +HID_USAGE_SPORT_10_IRON :: 0x5A +HID_USAGE_SPORT_11_IRON :: 0x5B +HID_USAGE_SPORT_SAND_WEDGE :: 0x5C +HID_USAGE_SPORT_LOFT_WEDGE :: 0x5D +HID_USAGE_SPORT_POWER_WEDGE :: 0x5E +HID_USAGE_SPORT_1_WOOD :: 0x5F +HID_USAGE_SPORT_3_WOOD :: 0x60 +HID_USAGE_SPORT_5_WOOD :: 0x61 +HID_USAGE_SPORT_7_WOOD :: 0x62 +HID_USAGE_SPORT_9_WOOD :: 0x63 HID_USAGE_GAME_3D_GAME_CONTROLLER :: 0x01 -HID_USAGE_GAME_PINBALL_DEVICE :: 0x02 -HID_USAGE_GAME_GUN_DEVICE :: 0x03 -HID_USAGE_GAME_POINT_OF_VIEW :: 0x20 -HID_USAGE_GAME_GUN_SELECTOR :: 0x32 -HID_USAGE_GAME_GAMEPAD_FIRE_JUMP :: 0x37 -HID_USAGE_GAME_GAMEPAD_TRIGGER :: 0x39 +HID_USAGE_GAME_PINBALL_DEVICE :: 0x02 +HID_USAGE_GAME_GUN_DEVICE :: 0x03 +HID_USAGE_GAME_POINT_OF_VIEW :: 0x20 +HID_USAGE_GAME_GUN_SELECTOR :: 0x32 +HID_USAGE_GAME_GAMEPAD_FIRE_JUMP :: 0x37 +HID_USAGE_GAME_GAMEPAD_TRIGGER :: 0x39 -HID_USAGE_GAME_TURN_RIGHT_LEFT :: 0x21 +HID_USAGE_GAME_TURN_RIGHT_LEFT :: 0x21 HID_USAGE_GAME_PITCH_FORWARD_BACK :: 0x22 -HID_USAGE_GAME_ROLL_RIGHT_LEFT :: 0x23 -HID_USAGE_GAME_MOVE_RIGHT_LEFT :: 0x24 -HID_USAGE_GAME_MOVE_FORWARD_BACK :: 0x25 -HID_USAGE_GAME_MOVE_UP_DOWN :: 0x26 -HID_USAGE_GAME_LEAN_RIGHT_LEFT :: 0x27 -HID_USAGE_GAME_LEAN_FORWARD_BACK :: 0x28 -HID_USAGE_GAME_POV_HEIGHT :: 0x29 -HID_USAGE_GAME_FLIPPER :: 0x2A -HID_USAGE_GAME_SECONDARY_FLIPPER :: 0x2B -HID_USAGE_GAME_BUMP :: 0x2C -HID_USAGE_GAME_NEW_GAME :: 0x2D -HID_USAGE_GAME_SHOOT_BALL :: 0x2E -HID_USAGE_GAME_PLAYER :: 0x2F -HID_USAGE_GAME_GUN_BOLT :: 0x30 -HID_USAGE_GAME_GUN_CLIP :: 0x31 -HID_USAGE_GAME_GUN_SINGLE_SHOT :: 0x33 -HID_USAGE_GAME_GUN_BURST :: 0x34 -HID_USAGE_GAME_GUN_AUTOMATIC :: 0x35 -HID_USAGE_GAME_GUN_SAFETY :: 0x36 +HID_USAGE_GAME_ROLL_RIGHT_LEFT :: 0x23 +HID_USAGE_GAME_MOVE_RIGHT_LEFT :: 0x24 +HID_USAGE_GAME_MOVE_FORWARD_BACK :: 0x25 +HID_USAGE_GAME_MOVE_UP_DOWN :: 0x26 +HID_USAGE_GAME_LEAN_RIGHT_LEFT :: 0x27 +HID_USAGE_GAME_LEAN_FORWARD_BACK :: 0x28 +HID_USAGE_GAME_POV_HEIGHT :: 0x29 +HID_USAGE_GAME_FLIPPER :: 0x2A +HID_USAGE_GAME_SECONDARY_FLIPPER :: 0x2B +HID_USAGE_GAME_BUMP :: 0x2C +HID_USAGE_GAME_NEW_GAME :: 0x2D +HID_USAGE_GAME_SHOOT_BALL :: 0x2E +HID_USAGE_GAME_PLAYER :: 0x2F +HID_USAGE_GAME_GUN_BOLT :: 0x30 +HID_USAGE_GAME_GUN_CLIP :: 0x31 +HID_USAGE_GAME_GUN_SINGLE_SHOT :: 0x33 +HID_USAGE_GAME_GUN_BURST :: 0x34 +HID_USAGE_GAME_GUN_AUTOMATIC :: 0x35 +HID_USAGE_GAME_GUN_SAFETY :: 0x36 -HID_USAGE_GENERIC_DEVICE_BATTERY_STRENGTH :: 0x20 -HID_USAGE_GENERIC_DEVICE_WIRELESS_CHANNEL :: 0x21 -HID_USAGE_GENERIC_DEVICE_WIRELESS_ID :: 0x22 -HID_USAGE_GENERIC_DEVICE_DISCOVER_WIRELESS_CONTROL :: 0x23 +HID_USAGE_GENERIC_DEVICE_BATTERY_STRENGTH :: 0x20 +HID_USAGE_GENERIC_DEVICE_WIRELESS_CHANNEL :: 0x21 +HID_USAGE_GENERIC_DEVICE_WIRELESS_ID :: 0x22 +HID_USAGE_GENERIC_DEVICE_DISCOVER_WIRELESS_CONTROL :: 0x23 HID_USAGE_GENERIC_DEVICE_SECURITY_CODE_CHAR_ENTERED :: 0x24 -HID_USAGE_GENERIC_DEVICE_SECURITY_CODE_CHAR_ERASED :: 0x25 -HID_USAGE_GENERIC_DEVICE_SECURITY_CODE_CLEARED :: 0x26 +HID_USAGE_GENERIC_DEVICE_SECURITY_CODE_CHAR_ERASED :: 0x25 +HID_USAGE_GENERIC_DEVICE_SECURITY_CODE_CLEARED :: 0x26 // Error "keys" -HID_USAGE_KEYBOARD_NOEVENT :: 0x00 -HID_USAGE_KEYBOARD_ROLLOVER :: 0x01 -HID_USAGE_KEYBOARD_POSTFAIL :: 0x02 +HID_USAGE_KEYBOARD_NOEVENT :: 0x00 +HID_USAGE_KEYBOARD_ROLLOVER :: 0x01 +HID_USAGE_KEYBOARD_POSTFAIL :: 0x02 HID_USAGE_KEYBOARD_UNDEFINED :: 0x03 // Letters @@ -265,32 +265,32 @@ HID_USAGE_KEYBOARD_aA :: 0x04 HID_USAGE_KEYBOARD_zZ :: 0x1D // Numbers -HID_USAGE_KEYBOARD_ONE :: 0x1E +HID_USAGE_KEYBOARD_ONE :: 0x1E HID_USAGE_KEYBOARD_ZERO :: 0x27 // Modifier Keys -HID_USAGE_KEYBOARD_LCTRL :: 0xE0 -HID_USAGE_KEYBOARD_LSHFT :: 0xE1 -HID_USAGE_KEYBOARD_LALT :: 0xE2 -HID_USAGE_KEYBOARD_LGUI :: 0xE3 -HID_USAGE_KEYBOARD_RCTRL :: 0xE4 -HID_USAGE_KEYBOARD_RSHFT :: 0xE5 -HID_USAGE_KEYBOARD_RALT :: 0xE6 -HID_USAGE_KEYBOARD_RGUI :: 0xE7 +HID_USAGE_KEYBOARD_LCTRL :: 0xE0 +HID_USAGE_KEYBOARD_LSHFT :: 0xE1 +HID_USAGE_KEYBOARD_LALT :: 0xE2 +HID_USAGE_KEYBOARD_LGUI :: 0xE3 +HID_USAGE_KEYBOARD_RCTRL :: 0xE4 +HID_USAGE_KEYBOARD_RSHFT :: 0xE5 +HID_USAGE_KEYBOARD_RALT :: 0xE6 +HID_USAGE_KEYBOARD_RGUI :: 0xE7 HID_USAGE_KEYBOARD_SCROLL_LOCK :: 0x47 -HID_USAGE_KEYBOARD_NUM_LOCK :: 0x53 -HID_USAGE_KEYBOARD_CAPS_LOCK :: 0x39 +HID_USAGE_KEYBOARD_NUM_LOCK :: 0x53 +HID_USAGE_KEYBOARD_CAPS_LOCK :: 0x39 // Function keys -HID_USAGE_KEYBOARD_F1 :: 0x3A -HID_USAGE_KEYBOARD_F2 :: 0x3B -HID_USAGE_KEYBOARD_F3 :: 0x3C -HID_USAGE_KEYBOARD_F4 :: 0x3D -HID_USAGE_KEYBOARD_F5 :: 0x3E -HID_USAGE_KEYBOARD_F6 :: 0x3F -HID_USAGE_KEYBOARD_F7 :: 0x40 -HID_USAGE_KEYBOARD_F8 :: 0x41 -HID_USAGE_KEYBOARD_F9 :: 0x42 +HID_USAGE_KEYBOARD_F1 :: 0x3A +HID_USAGE_KEYBOARD_F2 :: 0x3B +HID_USAGE_KEYBOARD_F3 :: 0x3C +HID_USAGE_KEYBOARD_F4 :: 0x3D +HID_USAGE_KEYBOARD_F5 :: 0x3E +HID_USAGE_KEYBOARD_F6 :: 0x3F +HID_USAGE_KEYBOARD_F7 :: 0x40 +HID_USAGE_KEYBOARD_F8 :: 0x41 +HID_USAGE_KEYBOARD_F9 :: 0x42 HID_USAGE_KEYBOARD_F10 :: 0x43 HID_USAGE_KEYBOARD_F11 :: 0x44 HID_USAGE_KEYBOARD_F12 :: 0x45 @@ -315,103 +315,103 @@ HID_USAGE_KEYBOARD_PRINT_SCREEN :: 0x46 HID_USAGE_KEYBOARD_DELETE_FORWARD :: 0x4C // Numeric Keypad -HID_USAGE_KEYBOARD_KEYPAD_1_AND_END :: 0x59 +HID_USAGE_KEYBOARD_KEYPAD_1_AND_END :: 0x59 HID_USAGE_KEYBOARD_KEYPAD_0_AND_INSERT :: 0x62 -HID_USAGE_LED_NUM_LOCK :: 0x01 -HID_USAGE_LED_CAPS_LOCK :: 0x02 -HID_USAGE_LED_SCROLL_LOCK :: 0x03 -HID_USAGE_LED_COMPOSE :: 0x04 -HID_USAGE_LED_KANA :: 0x05 -HID_USAGE_LED_POWER :: 0x06 -HID_USAGE_LED_SHIFT :: 0x07 -HID_USAGE_LED_DO_NOT_DISTURB :: 0x08 -HID_USAGE_LED_MUTE :: 0x09 -HID_USAGE_LED_TONE_ENABLE :: 0x0A -HID_USAGE_LED_HIGH_CUT_FILTER :: 0x0B -HID_USAGE_LED_LOW_CUT_FILTER :: 0x0C -HID_USAGE_LED_EQUALIZER_ENABLE :: 0x0D -HID_USAGE_LED_SOUND_FIELD_ON :: 0x0E -HID_USAGE_LED_SURROUND_FIELD_ON :: 0x0F -HID_USAGE_LED_REPEAT :: 0x10 -HID_USAGE_LED_STEREO :: 0x11 +HID_USAGE_LED_NUM_LOCK :: 0x01 +HID_USAGE_LED_CAPS_LOCK :: 0x02 +HID_USAGE_LED_SCROLL_LOCK :: 0x03 +HID_USAGE_LED_COMPOSE :: 0x04 +HID_USAGE_LED_KANA :: 0x05 +HID_USAGE_LED_POWER :: 0x06 +HID_USAGE_LED_SHIFT :: 0x07 +HID_USAGE_LED_DO_NOT_DISTURB :: 0x08 +HID_USAGE_LED_MUTE :: 0x09 +HID_USAGE_LED_TONE_ENABLE :: 0x0A +HID_USAGE_LED_HIGH_CUT_FILTER :: 0x0B +HID_USAGE_LED_LOW_CUT_FILTER :: 0x0C +HID_USAGE_LED_EQUALIZER_ENABLE :: 0x0D +HID_USAGE_LED_SOUND_FIELD_ON :: 0x0E +HID_USAGE_LED_SURROUND_FIELD_ON :: 0x0F +HID_USAGE_LED_REPEAT :: 0x10 +HID_USAGE_LED_STEREO :: 0x11 HID_USAGE_LED_SAMPLING_RATE_DETECT :: 0x12 -HID_USAGE_LED_SPINNING :: 0x13 -HID_USAGE_LED_CAV :: 0x14 -HID_USAGE_LED_CLV :: 0x15 +HID_USAGE_LED_SPINNING :: 0x13 +HID_USAGE_LED_CAV :: 0x14 +HID_USAGE_LED_CLV :: 0x15 HID_USAGE_LED_RECORDING_FORMAT_DET :: 0x16 -HID_USAGE_LED_OFF_HOOK :: 0x17 -HID_USAGE_LED_RING :: 0x18 -HID_USAGE_LED_MESSAGE_WAITING :: 0x19 -HID_USAGE_LED_DATA_MODE :: 0x1A -HID_USAGE_LED_BATTERY_OPERATION :: 0x1B -HID_USAGE_LED_BATTERY_OK :: 0x1C -HID_USAGE_LED_BATTERY_LOW :: 0x1D -HID_USAGE_LED_SPEAKER :: 0x1E -HID_USAGE_LED_HEAD_SET :: 0x1F -HID_USAGE_LED_HOLD :: 0x20 -HID_USAGE_LED_MICROPHONE :: 0x21 -HID_USAGE_LED_COVERAGE :: 0x22 -HID_USAGE_LED_NIGHT_MODE :: 0x23 -HID_USAGE_LED_SEND_CALLS :: 0x24 -HID_USAGE_LED_CALL_PICKUP :: 0x25 -HID_USAGE_LED_CONFERENCE :: 0x26 -HID_USAGE_LED_STAND_BY :: 0x27 -HID_USAGE_LED_CAMERA_ON :: 0x28 -HID_USAGE_LED_CAMERA_OFF :: 0x29 -HID_USAGE_LED_ON_LINE :: 0x2A -HID_USAGE_LED_OFF_LINE :: 0x2B -HID_USAGE_LED_BUSY :: 0x2C -HID_USAGE_LED_READY :: 0x2D -HID_USAGE_LED_PAPER_OUT :: 0x2E -HID_USAGE_LED_PAPER_JAM :: 0x2F -HID_USAGE_LED_REMOTE :: 0x30 -HID_USAGE_LED_FORWARD :: 0x31 -HID_USAGE_LED_REVERSE :: 0x32 -HID_USAGE_LED_STOP :: 0x33 -HID_USAGE_LED_REWIND :: 0x34 -HID_USAGE_LED_FAST_FORWARD :: 0x35 -HID_USAGE_LED_PLAY :: 0x36 -HID_USAGE_LED_PAUSE :: 0x37 -HID_USAGE_LED_RECORD :: 0x38 -HID_USAGE_LED_ERROR :: 0x39 -HID_USAGE_LED_SELECTED_INDICATOR :: 0x3A -HID_USAGE_LED_IN_USE_INDICATOR :: 0x3B +HID_USAGE_LED_OFF_HOOK :: 0x17 +HID_USAGE_LED_RING :: 0x18 +HID_USAGE_LED_MESSAGE_WAITING :: 0x19 +HID_USAGE_LED_DATA_MODE :: 0x1A +HID_USAGE_LED_BATTERY_OPERATION :: 0x1B +HID_USAGE_LED_BATTERY_OK :: 0x1C +HID_USAGE_LED_BATTERY_LOW :: 0x1D +HID_USAGE_LED_SPEAKER :: 0x1E +HID_USAGE_LED_HEAD_SET :: 0x1F +HID_USAGE_LED_HOLD :: 0x20 +HID_USAGE_LED_MICROPHONE :: 0x21 +HID_USAGE_LED_COVERAGE :: 0x22 +HID_USAGE_LED_NIGHT_MODE :: 0x23 +HID_USAGE_LED_SEND_CALLS :: 0x24 +HID_USAGE_LED_CALL_PICKUP :: 0x25 +HID_USAGE_LED_CONFERENCE :: 0x26 +HID_USAGE_LED_STAND_BY :: 0x27 +HID_USAGE_LED_CAMERA_ON :: 0x28 +HID_USAGE_LED_CAMERA_OFF :: 0x29 +HID_USAGE_LED_ON_LINE :: 0x2A +HID_USAGE_LED_OFF_LINE :: 0x2B +HID_USAGE_LED_BUSY :: 0x2C +HID_USAGE_LED_READY :: 0x2D +HID_USAGE_LED_PAPER_OUT :: 0x2E +HID_USAGE_LED_PAPER_JAM :: 0x2F +HID_USAGE_LED_REMOTE :: 0x30 +HID_USAGE_LED_FORWARD :: 0x31 +HID_USAGE_LED_REVERSE :: 0x32 +HID_USAGE_LED_STOP :: 0x33 +HID_USAGE_LED_REWIND :: 0x34 +HID_USAGE_LED_FAST_FORWARD :: 0x35 +HID_USAGE_LED_PLAY :: 0x36 +HID_USAGE_LED_PAUSE :: 0x37 +HID_USAGE_LED_RECORD :: 0x38 +HID_USAGE_LED_ERROR :: 0x39 +HID_USAGE_LED_SELECTED_INDICATOR :: 0x3A +HID_USAGE_LED_IN_USE_INDICATOR :: 0x3B HID_USAGE_LED_MULTI_MODE_INDICATOR :: 0x3C -HID_USAGE_LED_INDICATOR_ON :: 0x3D -HID_USAGE_LED_INDICATOR_FLASH :: 0x3E +HID_USAGE_LED_INDICATOR_ON :: 0x3D +HID_USAGE_LED_INDICATOR_FLASH :: 0x3E HID_USAGE_LED_INDICATOR_SLOW_BLINK :: 0x3F HID_USAGE_LED_INDICATOR_FAST_BLINK :: 0x40 -HID_USAGE_LED_INDICATOR_OFF :: 0x41 -HID_USAGE_LED_FLASH_ON_TIME :: 0x42 -HID_USAGE_LED_SLOW_BLINK_ON_TIME :: 0x43 -HID_USAGE_LED_SLOW_BLINK_OFF_TIME :: 0x44 -HID_USAGE_LED_FAST_BLINK_ON_TIME :: 0x45 -HID_USAGE_LED_FAST_BLINK_OFF_TIME :: 0x46 -HID_USAGE_LED_INDICATOR_COLOR :: 0x47 -HID_USAGE_LED_RED :: 0x48 -HID_USAGE_LED_GREEN :: 0x49 -HID_USAGE_LED_AMBER :: 0x4A -HID_USAGE_LED_GENERIC_INDICATOR :: 0x4B -HID_USAGE_LED_SYSTEM_SUSPEND :: 0x4C -HID_USAGE_LED_EXTERNAL_POWER :: 0x4D +HID_USAGE_LED_INDICATOR_OFF :: 0x41 +HID_USAGE_LED_FLASH_ON_TIME :: 0x42 +HID_USAGE_LED_SLOW_BLINK_ON_TIME :: 0x43 +HID_USAGE_LED_SLOW_BLINK_OFF_TIME :: 0x44 +HID_USAGE_LED_FAST_BLINK_ON_TIME :: 0x45 +HID_USAGE_LED_FAST_BLINK_OFF_TIME :: 0x46 +HID_USAGE_LED_INDICATOR_COLOR :: 0x47 +HID_USAGE_LED_RED :: 0x48 +HID_USAGE_LED_GREEN :: 0x49 +HID_USAGE_LED_AMBER :: 0x4A +HID_USAGE_LED_GENERIC_INDICATOR :: 0x4B +HID_USAGE_LED_SYSTEM_SUSPEND :: 0x4C +HID_USAGE_LED_EXTERNAL_POWER :: 0x4D -HID_USAGE_TELEPHONY_PHONE :: 0x01 -HID_USAGE_TELEPHONY_ANSWERING_MACHINE :: 0x02 -HID_USAGE_TELEPHONY_MESSAGE_CONTROLS :: 0x03 -HID_USAGE_TELEPHONY_HANDSET :: 0x04 -HID_USAGE_TELEPHONY_HEADSET :: 0x05 -HID_USAGE_TELEPHONY_KEYPAD :: 0x06 +HID_USAGE_TELEPHONY_PHONE :: 0x01 +HID_USAGE_TELEPHONY_ANSWERING_MACHINE :: 0x02 +HID_USAGE_TELEPHONY_MESSAGE_CONTROLS :: 0x03 +HID_USAGE_TELEPHONY_HANDSET :: 0x04 +HID_USAGE_TELEPHONY_HEADSET :: 0x05 +HID_USAGE_TELEPHONY_KEYPAD :: 0x06 HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON :: 0x07 -HID_USAGE_TELEPHONY_REDIAL :: 0x24 -HID_USAGE_TELEPHONY_TRANSFER :: 0x25 -HID_USAGE_TELEPHONY_DROP :: 0x26 -HID_USAGE_TELEPHONY_LINE :: 0x2A -HID_USAGE_TELEPHONY_RING_ENABLE :: 0x2D -HID_USAGE_TELEPHONY_SEND :: 0x31 -HID_USAGE_TELEPHONY_KEYPAD_0 :: 0xB0 -HID_USAGE_TELEPHONY_KEYPAD_D :: 0xBF -HID_USAGE_TELEPHONY_HOST_AVAILABLE :: 0xF1 +HID_USAGE_TELEPHONY_REDIAL :: 0x24 +HID_USAGE_TELEPHONY_TRANSFER :: 0x25 +HID_USAGE_TELEPHONY_DROP :: 0x26 +HID_USAGE_TELEPHONY_LINE :: 0x2A +HID_USAGE_TELEPHONY_RING_ENABLE :: 0x2D +HID_USAGE_TELEPHONY_SEND :: 0x31 +HID_USAGE_TELEPHONY_KEYPAD_0 :: 0xB0 +HID_USAGE_TELEPHONY_KEYPAD_D :: 0xBF +HID_USAGE_TELEPHONY_HOST_AVAILABLE :: 0xF1 HID_USAGE_CONSUMERCTRL :: 0x01 @@ -420,271 +420,271 @@ HID_USAGE_CONSUMER_CHANNEL_INCREMENT :: 0x9C HID_USAGE_CONSUMER_CHANNEL_DECREMENT :: 0x9D // transport control -HID_USAGE_CONSUMER_PLAY :: 0xB0 -HID_USAGE_CONSUMER_PAUSE :: 0xB1 -HID_USAGE_CONSUMER_RECORD :: 0xB2 -HID_USAGE_CONSUMER_FAST_FORWARD :: 0xB3 -HID_USAGE_CONSUMER_REWIND :: 0xB4 +HID_USAGE_CONSUMER_PLAY :: 0xB0 +HID_USAGE_CONSUMER_PAUSE :: 0xB1 +HID_USAGE_CONSUMER_RECORD :: 0xB2 +HID_USAGE_CONSUMER_FAST_FORWARD :: 0xB3 +HID_USAGE_CONSUMER_REWIND :: 0xB4 HID_USAGE_CONSUMER_SCAN_NEXT_TRACK :: 0xB5 HID_USAGE_CONSUMER_SCAN_PREV_TRACK :: 0xB6 -HID_USAGE_CONSUMER_STOP :: 0xB7 -HID_USAGE_CONSUMER_PLAY_PAUSE :: 0xCD +HID_USAGE_CONSUMER_STOP :: 0xB7 +HID_USAGE_CONSUMER_PLAY_PAUSE :: 0xCD // GameDVR -HID_USAGE_CONSUMER_GAMEDVR_OPEN_GAMEBAR :: 0xD0 -HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_RECORD :: 0xD1 -HID_USAGE_CONSUMER_GAMEDVR_RECORD_CLIP :: 0xD2 -HID_USAGE_CONSUMER_GAMEDVR_SCREENSHOT :: 0xD3 -HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_INDICATOR :: 0xD4 +HID_USAGE_CONSUMER_GAMEDVR_OPEN_GAMEBAR :: 0xD0 +HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_RECORD :: 0xD1 +HID_USAGE_CONSUMER_GAMEDVR_RECORD_CLIP :: 0xD2 +HID_USAGE_CONSUMER_GAMEDVR_SCREENSHOT :: 0xD3 +HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_INDICATOR :: 0xD4 HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_MICROPHONE :: 0xD5 -HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_CAMERA :: 0xD6 -HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_BROADCAST :: 0xD7 +HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_CAMERA :: 0xD6 +HID_USAGE_CONSUMER_GAMEDVR_TOGGLE_BROADCAST :: 0xD7 // audio -HID_USAGE_CONSUMER_VOLUME :: 0xE0 -HID_USAGE_CONSUMER_BALANCE :: 0xE1 -HID_USAGE_CONSUMER_MUTE :: 0xE2 -HID_USAGE_CONSUMER_BASS :: 0xE3 -HID_USAGE_CONSUMER_TREBLE :: 0xE4 -HID_USAGE_CONSUMER_BASS_BOOST :: 0xE5 -HID_USAGE_CONSUMER_SURROUND_MODE :: 0xE6 -HID_USAGE_CONSUMER_LOUDNESS :: 0xE7 -HID_USAGE_CONSUMER_MPX :: 0xE8 +HID_USAGE_CONSUMER_VOLUME :: 0xE0 +HID_USAGE_CONSUMER_BALANCE :: 0xE1 +HID_USAGE_CONSUMER_MUTE :: 0xE2 +HID_USAGE_CONSUMER_BASS :: 0xE3 +HID_USAGE_CONSUMER_TREBLE :: 0xE4 +HID_USAGE_CONSUMER_BASS_BOOST :: 0xE5 +HID_USAGE_CONSUMER_SURROUND_MODE :: 0xE6 +HID_USAGE_CONSUMER_LOUDNESS :: 0xE7 +HID_USAGE_CONSUMER_MPX :: 0xE8 HID_USAGE_CONSUMER_VOLUME_INCREMENT :: 0xE9 HID_USAGE_CONSUMER_VOLUME_DECREMENT :: 0xEA // supplementary audio -HID_USAGE_CONSUMER_BASS_INCREMENT :: 0x152 -HID_USAGE_CONSUMER_BASS_DECREMENT :: 0x153 +HID_USAGE_CONSUMER_BASS_INCREMENT :: 0x152 +HID_USAGE_CONSUMER_BASS_DECREMENT :: 0x153 HID_USAGE_CONSUMER_TREBLE_INCREMENT :: 0x154 HID_USAGE_CONSUMER_TREBLE_DECREMENT :: 0x155 // Application Launch HID_USAGE_CONSUMER_AL_CONFIGURATION :: 0x183 -HID_USAGE_CONSUMER_AL_EMAIL :: 0x18A -HID_USAGE_CONSUMER_AL_CALCULATOR :: 0x192 -HID_USAGE_CONSUMER_AL_BROWSER :: 0x194 -HID_USAGE_CONSUMER_AL_SEARCH :: 0x1C6 +HID_USAGE_CONSUMER_AL_EMAIL :: 0x18A +HID_USAGE_CONSUMER_AL_CALCULATOR :: 0x192 +HID_USAGE_CONSUMER_AL_BROWSER :: 0x194 +HID_USAGE_CONSUMER_AL_SEARCH :: 0x1C6 // Application Control -HID_USAGE_CONSUMER_AC_SEARCH :: 0x221 -HID_USAGE_CONSUMER_AC_GOTO :: 0x222 -HID_USAGE_CONSUMER_AC_HOME :: 0x223 -HID_USAGE_CONSUMER_AC_BACK :: 0x224 -HID_USAGE_CONSUMER_AC_FORWARD :: 0x225 -HID_USAGE_CONSUMER_AC_STOP :: 0x226 -HID_USAGE_CONSUMER_AC_REFRESH :: 0x227 -HID_USAGE_CONSUMER_AC_PREVIOUS :: 0x228 -HID_USAGE_CONSUMER_AC_NEXT :: 0x229 +HID_USAGE_CONSUMER_AC_SEARCH :: 0x221 +HID_USAGE_CONSUMER_AC_GOTO :: 0x222 +HID_USAGE_CONSUMER_AC_HOME :: 0x223 +HID_USAGE_CONSUMER_AC_BACK :: 0x224 +HID_USAGE_CONSUMER_AC_FORWARD :: 0x225 +HID_USAGE_CONSUMER_AC_STOP :: 0x226 +HID_USAGE_CONSUMER_AC_REFRESH :: 0x227 +HID_USAGE_CONSUMER_AC_PREVIOUS :: 0x228 +HID_USAGE_CONSUMER_AC_NEXT :: 0x229 HID_USAGE_CONSUMER_AC_BOOKMARKS :: 0x22A -HID_USAGE_CONSUMER_AC_PAN :: 0x238 +HID_USAGE_CONSUMER_AC_PAN :: 0x238 // Keyboard Extended Attributes (defined on consumer page in HUTRR42) -HID_USAGE_CONSUMER_EXTENDED_KEYBOARD_ATTRIBUTES_COLLECTION :: 0x2C0 -HID_USAGE_CONSUMER_KEYBOARD_FORM_FACTOR :: 0x2C1 -HID_USAGE_CONSUMER_KEYBOARD_KEY_TYPE :: 0x2C2 -HID_USAGE_CONSUMER_KEYBOARD_PHYSICAL_LAYOUT :: 0x2C3 -HID_USAGE_CONSUMER_VENDOR_SPECIFIC_KEYBOARD_PHYSICAL_LAYOUT :: 0x2C4 -HID_USAGE_CONSUMER_KEYBOARD_IETF_LANGUAGE_TAG_INDEX :: 0x2C5 +HID_USAGE_CONSUMER_EXTENDED_KEYBOARD_ATTRIBUTES_COLLECTION :: 0x2C0 +HID_USAGE_CONSUMER_KEYBOARD_FORM_FACTOR :: 0x2C1 +HID_USAGE_CONSUMER_KEYBOARD_KEY_TYPE :: 0x2C2 +HID_USAGE_CONSUMER_KEYBOARD_PHYSICAL_LAYOUT :: 0x2C3 +HID_USAGE_CONSUMER_VENDOR_SPECIFIC_KEYBOARD_PHYSICAL_LAYOUT :: 0x2C4 +HID_USAGE_CONSUMER_KEYBOARD_IETF_LANGUAGE_TAG_INDEX :: 0x2C5 HID_USAGE_CONSUMER_IMPLEMENTED_KEYBOARD_INPUT_ASSIST_CONTROLS :: 0x2C6 -HID_USAGE_DIGITIZER_DIGITIZER :: 0x01 -HID_USAGE_DIGITIZER_PEN :: 0x02 -HID_USAGE_DIGITIZER_LIGHT_PEN :: 0x03 -HID_USAGE_DIGITIZER_TOUCH_SCREEN :: 0x04 -HID_USAGE_DIGITIZER_TOUCH_PAD :: 0x05 -HID_USAGE_DIGITIZER_WHITE_BOARD :: 0x06 -HID_USAGE_DIGITIZER_COORD_MEASURING :: 0x07 -HID_USAGE_DIGITIZER_3D_DIGITIZER :: 0x08 -HID_USAGE_DIGITIZER_STEREO_PLOTTER :: 0x09 -HID_USAGE_DIGITIZER_ARTICULATED_ARM :: 0x0A -HID_USAGE_DIGITIZER_ARMATURE :: 0x0B -HID_USAGE_DIGITIZER_MULTI_POINT :: 0x0C -HID_USAGE_DIGITIZER_FREE_SPACE_WAND :: 0x0D -HID_USAGE_DIGITIZER_HEAT_MAP :: 0x0F -HID_USAGE_DIGITIZER_STYLUS :: 0x20 -HID_USAGE_DIGITIZER_PUCK :: 0x21 -HID_USAGE_DIGITIZER_FINGER :: 0x22 +HID_USAGE_DIGITIZER_DIGITIZER :: 0x01 +HID_USAGE_DIGITIZER_PEN :: 0x02 +HID_USAGE_DIGITIZER_LIGHT_PEN :: 0x03 +HID_USAGE_DIGITIZER_TOUCH_SCREEN :: 0x04 +HID_USAGE_DIGITIZER_TOUCH_PAD :: 0x05 +HID_USAGE_DIGITIZER_WHITE_BOARD :: 0x06 +HID_USAGE_DIGITIZER_COORD_MEASURING :: 0x07 +HID_USAGE_DIGITIZER_3D_DIGITIZER :: 0x08 +HID_USAGE_DIGITIZER_STEREO_PLOTTER :: 0x09 +HID_USAGE_DIGITIZER_ARTICULATED_ARM :: 0x0A +HID_USAGE_DIGITIZER_ARMATURE :: 0x0B +HID_USAGE_DIGITIZER_MULTI_POINT :: 0x0C +HID_USAGE_DIGITIZER_FREE_SPACE_WAND :: 0x0D +HID_USAGE_DIGITIZER_HEAT_MAP :: 0x0F +HID_USAGE_DIGITIZER_STYLUS :: 0x20 +HID_USAGE_DIGITIZER_PUCK :: 0x21 +HID_USAGE_DIGITIZER_FINGER :: 0x22 HID_USAGE_DIGITIZER_TABLET_FUNC_KEYS :: 0x39 HID_USAGE_DIGITIZER_PROG_CHANGE_KEYS :: 0x3A -HID_USAGE_DIGITIZER_TIP_PRESSURE :: 0x30 -HID_USAGE_DIGITIZER_BARREL_PRESSURE :: 0x31 -HID_USAGE_DIGITIZER_IN_RANGE :: 0x32 -HID_USAGE_DIGITIZER_TOUCH :: 0x33 -HID_USAGE_DIGITIZER_UNTOUCH :: 0x34 -HID_USAGE_DIGITIZER_TAP :: 0x35 -HID_USAGE_DIGITIZER_QUALITY :: 0x36 -HID_USAGE_DIGITIZER_DATA_VALID :: 0x37 -HID_USAGE_DIGITIZER_TRANSDUCER_INDEX :: 0x38 -HID_USAGE_DIGITIZER_BATTERY_STRENGTH :: 0x3B -HID_USAGE_DIGITIZER_INVERT :: 0x3C -HID_USAGE_DIGITIZER_X_TILT :: 0x3D -HID_USAGE_DIGITIZER_Y_TILT :: 0x3E -HID_USAGE_DIGITIZER_AZIMUTH :: 0x3F -HID_USAGE_DIGITIZER_ALTITUDE :: 0x40 -HID_USAGE_DIGITIZER_TWIST :: 0x41 -HID_USAGE_DIGITIZER_TIP_SWITCH :: 0x42 -HID_USAGE_DIGITIZER_SECONDARY_TIP_SWITCH :: 0x43 -HID_USAGE_DIGITIZER_BARREL_SWITCH :: 0x44 -HID_USAGE_DIGITIZER_ERASER :: 0x45 -HID_USAGE_DIGITIZER_TABLET_PICK :: 0x46 -HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL :: 0x5B +HID_USAGE_DIGITIZER_TIP_PRESSURE :: 0x30 +HID_USAGE_DIGITIZER_BARREL_PRESSURE :: 0x31 +HID_USAGE_DIGITIZER_IN_RANGE :: 0x32 +HID_USAGE_DIGITIZER_TOUCH :: 0x33 +HID_USAGE_DIGITIZER_UNTOUCH :: 0x34 +HID_USAGE_DIGITIZER_TAP :: 0x35 +HID_USAGE_DIGITIZER_QUALITY :: 0x36 +HID_USAGE_DIGITIZER_DATA_VALID :: 0x37 +HID_USAGE_DIGITIZER_TRANSDUCER_INDEX :: 0x38 +HID_USAGE_DIGITIZER_BATTERY_STRENGTH :: 0x3B +HID_USAGE_DIGITIZER_INVERT :: 0x3C +HID_USAGE_DIGITIZER_X_TILT :: 0x3D +HID_USAGE_DIGITIZER_Y_TILT :: 0x3E +HID_USAGE_DIGITIZER_AZIMUTH :: 0x3F +HID_USAGE_DIGITIZER_ALTITUDE :: 0x40 +HID_USAGE_DIGITIZER_TWIST :: 0x41 +HID_USAGE_DIGITIZER_TIP_SWITCH :: 0x42 +HID_USAGE_DIGITIZER_SECONDARY_TIP_SWITCH :: 0x43 +HID_USAGE_DIGITIZER_BARREL_SWITCH :: 0x44 +HID_USAGE_DIGITIZER_ERASER :: 0x45 +HID_USAGE_DIGITIZER_TABLET_PICK :: 0x46 +HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL :: 0x5B HID_USAGE_DIGITIZER_HEAT_MAP_PROTOCOL_VENDOR_ID :: 0x6A -HID_USAGE_DIGITIZER_HEAT_MAP_PROTOCOL_VERSION :: 0x6B -HID_USAGE_DIGITIZER_HEAT_MAP_FRAME_DATA :: 0x6C -HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_PART2 :: 0x6E -HID_USAGE_DIGITIZER_TRANSDUCER_VENDOR :: 0x91 -HID_USAGE_DIGITIZER_TRANSDUCER_PRODUCT :: 0x92 -HID_USAGE_DIGITIZER_TRANSDUCER_CONNECTED :: 0xA2 +HID_USAGE_DIGITIZER_HEAT_MAP_PROTOCOL_VERSION :: 0x6B +HID_USAGE_DIGITIZER_HEAT_MAP_FRAME_DATA :: 0x6C +HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_PART2 :: 0x6E +HID_USAGE_DIGITIZER_TRANSDUCER_VENDOR :: 0x91 +HID_USAGE_DIGITIZER_TRANSDUCER_PRODUCT :: 0x92 +HID_USAGE_DIGITIZER_TRANSDUCER_CONNECTED :: 0xA2 HID_USAGE_HAPTICS_SIMPLE_CONTROLLER :: 0x01 HID_USAGE_HAPTICS_WAVEFORM_LIST :: 0x10 HID_USAGE_HAPTICS_DURATION_LIST :: 0x11 -HID_USAGE_HAPTICS_AUTO_TRIGGER :: 0x20 -HID_USAGE_HAPTICS_MANUAL_TRIGGER :: 0x21 +HID_USAGE_HAPTICS_AUTO_TRIGGER :: 0x20 +HID_USAGE_HAPTICS_MANUAL_TRIGGER :: 0x21 HID_USAGE_HAPTICS_AUTO_ASSOCIATED_CONTROL :: 0x22 -HID_USAGE_HAPTICS_INTENSITY :: 0x23 -HID_USAGE_HAPTICS_REPEAT_COUNT :: 0x24 -HID_USAGE_HAPTICS_RETRIGGER_PERIOD :: 0x25 -HID_USAGE_HAPTICS_WAVEFORM_VENDOR_PAGE :: 0x26 -HID_USAGE_HAPTICS_WAVEFORM_VENDOR_ID :: 0x27 -HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME :: 0x28 +HID_USAGE_HAPTICS_INTENSITY :: 0x23 +HID_USAGE_HAPTICS_REPEAT_COUNT :: 0x24 +HID_USAGE_HAPTICS_RETRIGGER_PERIOD :: 0x25 +HID_USAGE_HAPTICS_WAVEFORM_VENDOR_PAGE :: 0x26 +HID_USAGE_HAPTICS_WAVEFORM_VENDOR_ID :: 0x27 +HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME :: 0x28 // Waveform types -HID_USAGE_HAPTICS_WAVEFORM_BEGIN :: 0x1000 -HID_USAGE_HAPTICS_WAVEFORM_STOP :: 0x1001 -HID_USAGE_HAPTICS_WAVEFORM_NULL :: 0x1002 -HID_USAGE_HAPTICS_WAVEFORM_CLICK :: 0x1003 -HID_USAGE_HAPTICS_WAVEFORM_BUZZ :: 0x1004 -HID_USAGE_HAPTICS_WAVEFORM_RUMBLE :: 0x1005 -HID_USAGE_HAPTICS_WAVEFORM_PRESS :: 0x1006 +HID_USAGE_HAPTICS_WAVEFORM_BEGIN :: 0x1000 +HID_USAGE_HAPTICS_WAVEFORM_STOP :: 0x1001 +HID_USAGE_HAPTICS_WAVEFORM_NULL :: 0x1002 +HID_USAGE_HAPTICS_WAVEFORM_CLICK :: 0x1003 +HID_USAGE_HAPTICS_WAVEFORM_BUZZ :: 0x1004 +HID_USAGE_HAPTICS_WAVEFORM_RUMBLE :: 0x1005 +HID_USAGE_HAPTICS_WAVEFORM_PRESS :: 0x1006 HID_USAGE_HAPTICS_WAVEFORM_RELEASE :: 0x1007 -HID_USAGE_HAPTICS_WAVEFORM_END :: 0x1FFF +HID_USAGE_HAPTICS_WAVEFORM_END :: 0x1FFF HID_USAGE_HAPTICS_WAVEFORM_VENDOR_BEGIN :: 0x2000 -HID_USAGE_HAPTICS_WAVEFORM_VENDOR_END :: 0x2FFF +HID_USAGE_HAPTICS_WAVEFORM_VENDOR_END :: 0x2FFF -HID_USAGE_ALPHANUMERIC_ALPHANUMERIC_DISPLAY :: 0x01 -HID_USAGE_ALPHANUMERIC_BITMAPPED_DISPLAY :: 0x02 +HID_USAGE_ALPHANUMERIC_ALPHANUMERIC_DISPLAY :: 0x01 +HID_USAGE_ALPHANUMERIC_BITMAPPED_DISPLAY :: 0x02 HID_USAGE_ALPHANUMERIC_DISPLAY_ATTRIBUTES_REPORT :: 0x20 -HID_USAGE_ALPHANUMERIC_DISPLAY_CONTROL_REPORT :: 0x24 -HID_USAGE_ALPHANUMERIC_CHARACTER_REPORT :: 0x2B -HID_USAGE_ALPHANUMERIC_DISPLAY_STATUS :: 0x2D -HID_USAGE_ALPHANUMERIC_CURSOR_POSITION_REPORT :: 0x32 -HID_USAGE_ALPHANUMERIC_FONT_REPORT :: 0x3B -HID_USAGE_ALPHANUMERIC_FONT_DATA :: 0x3C -HID_USAGE_ALPHANUMERIC_CHARACTER_ATTRIBUTE :: 0x48 -HID_USAGE_ALPHANUMERIC_PALETTE_REPORT :: 0x85 -HID_USAGE_ALPHANUMERIC_PALETTE_DATA :: 0x88 -HID_USAGE_ALPHANUMERIC_BLIT_REPORT :: 0x8A -HID_USAGE_ALPHANUMERIC_BLIT_DATA :: 0x8F -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON :: 0x90 +HID_USAGE_ALPHANUMERIC_DISPLAY_CONTROL_REPORT :: 0x24 +HID_USAGE_ALPHANUMERIC_CHARACTER_REPORT :: 0x2B +HID_USAGE_ALPHANUMERIC_DISPLAY_STATUS :: 0x2D +HID_USAGE_ALPHANUMERIC_CURSOR_POSITION_REPORT :: 0x32 +HID_USAGE_ALPHANUMERIC_FONT_REPORT :: 0x3B +HID_USAGE_ALPHANUMERIC_FONT_DATA :: 0x3C +HID_USAGE_ALPHANUMERIC_CHARACTER_ATTRIBUTE :: 0x48 +HID_USAGE_ALPHANUMERIC_PALETTE_REPORT :: 0x85 +HID_USAGE_ALPHANUMERIC_PALETTE_DATA :: 0x88 +HID_USAGE_ALPHANUMERIC_BLIT_REPORT :: 0x8A +HID_USAGE_ALPHANUMERIC_BLIT_DATA :: 0x8F +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON :: 0x90 -HID_USAGE_ALPHANUMERIC_ASCII_CHARACTER_SET :: 0x21 -HID_USAGE_ALPHANUMERIC_DATA_READ_BACK :: 0x22 -HID_USAGE_ALPHANUMERIC_FONT_READ_BACK :: 0x23 -HID_USAGE_ALPHANUMERIC_CLEAR_DISPLAY :: 0x25 -HID_USAGE_ALPHANUMERIC_DISPLAY_ENABLE :: 0x26 -HID_USAGE_ALPHANUMERIC_SCREEN_SAVER_DELAY :: 0x27 -HID_USAGE_ALPHANUMERIC_SCREEN_SAVER_ENABLE :: 0x28 -HID_USAGE_ALPHANUMERIC_VERTICAL_SCROLL :: 0x29 -HID_USAGE_ALPHANUMERIC_HORIZONTAL_SCROLL :: 0x2A -HID_USAGE_ALPHANUMERIC_DISPLAY_DATA :: 0x2C -HID_USAGE_ALPHANUMERIC_STATUS_NOT_READY :: 0x2E -HID_USAGE_ALPHANUMERIC_STATUS_READY :: 0x2F +HID_USAGE_ALPHANUMERIC_ASCII_CHARACTER_SET :: 0x21 +HID_USAGE_ALPHANUMERIC_DATA_READ_BACK :: 0x22 +HID_USAGE_ALPHANUMERIC_FONT_READ_BACK :: 0x23 +HID_USAGE_ALPHANUMERIC_CLEAR_DISPLAY :: 0x25 +HID_USAGE_ALPHANUMERIC_DISPLAY_ENABLE :: 0x26 +HID_USAGE_ALPHANUMERIC_SCREEN_SAVER_DELAY :: 0x27 +HID_USAGE_ALPHANUMERIC_SCREEN_SAVER_ENABLE :: 0x28 +HID_USAGE_ALPHANUMERIC_VERTICAL_SCROLL :: 0x29 +HID_USAGE_ALPHANUMERIC_HORIZONTAL_SCROLL :: 0x2A +HID_USAGE_ALPHANUMERIC_DISPLAY_DATA :: 0x2C +HID_USAGE_ALPHANUMERIC_STATUS_NOT_READY :: 0x2E +HID_USAGE_ALPHANUMERIC_STATUS_READY :: 0x2F HID_USAGE_ALPHANUMERIC_ERR_NOT_A_LOADABLE_CHARACTER :: 0x30 HID_USAGE_ALPHANUMERIC_ERR_FONT_DATA_CANNOT_BE_READ :: 0x31 -HID_USAGE_ALPHANUMERIC_ROW :: 0x33 -HID_USAGE_ALPHANUMERIC_COLUMN :: 0x34 -HID_USAGE_ALPHANUMERIC_ROWS :: 0x35 -HID_USAGE_ALPHANUMERIC_COLUMNS :: 0x36 -HID_USAGE_ALPHANUMERIC_CURSOR_PIXEL_POSITIONING :: 0x37 -HID_USAGE_ALPHANUMERIC_CURSOR_MODE :: 0x38 -HID_USAGE_ALPHANUMERIC_CURSOR_ENABLE :: 0x39 -HID_USAGE_ALPHANUMERIC_CURSOR_BLINK :: 0x3A -HID_USAGE_ALPHANUMERIC_CHAR_WIDTH :: 0x3D -HID_USAGE_ALPHANUMERIC_CHAR_HEIGHT :: 0x3E -HID_USAGE_ALPHANUMERIC_CHAR_SPACING_HORIZONTAL :: 0x3F -HID_USAGE_ALPHANUMERIC_CHAR_SPACING_VERTICAL :: 0x40 -HID_USAGE_ALPHANUMERIC_UNICODE_CHAR_SET :: 0x41 -HID_USAGE_ALPHANUMERIC_FONT_7_SEGMENT :: 0x42 -HID_USAGE_ALPHANUMERIC_7_SEGMENT_DIRECT_MAP :: 0x43 -HID_USAGE_ALPHANUMERIC_FONT_14_SEGMENT :: 0x44 -HID_USAGE_ALPHANUMERIC_14_SEGMENT_DIRECT_MAP :: 0x45 -HID_USAGE_ALPHANUMERIC_DISPLAY_BRIGHTNESS :: 0x46 -HID_USAGE_ALPHANUMERIC_DISPLAY_CONTRAST :: 0x47 -HID_USAGE_ALPHANUMERIC_ATTRIBUTE_READBACK :: 0x49 -HID_USAGE_ALPHANUMERIC_ATTRIBUTE_DATA :: 0x4A -HID_USAGE_ALPHANUMERIC_CHAR_ATTR_ENHANCE :: 0x4B -HID_USAGE_ALPHANUMERIC_CHAR_ATTR_UNDERLINE :: 0x4C -HID_USAGE_ALPHANUMERIC_CHAR_ATTR_BLINK :: 0x4D -HID_USAGE_ALPHANUMERIC_BITMAP_SIZE_X :: 0x80 -HID_USAGE_ALPHANUMERIC_BITMAP_SIZE_Y :: 0x81 -HID_USAGE_ALPHANUMERIC_BIT_DEPTH_FORMAT :: 0x83 -HID_USAGE_ALPHANUMERIC_DISPLAY_ORIENTATION :: 0x84 -HID_USAGE_ALPHANUMERIC_PALETTE_DATA_SIZE :: 0x86 -HID_USAGE_ALPHANUMERIC_PALETTE_DATA_OFFSET :: 0x87 -HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_X1 :: 0x8B -HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_Y1 :: 0x8C -HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_X2 :: 0x8D -HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_Y2 :: 0x8E -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_ID :: 0x91 -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_SIDE :: 0x92 -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_OFFSET1 :: 0x93 -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_OFFSET2 :: 0x94 -HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_REPORT :: 0x95 +HID_USAGE_ALPHANUMERIC_ROW :: 0x33 +HID_USAGE_ALPHANUMERIC_COLUMN :: 0x34 +HID_USAGE_ALPHANUMERIC_ROWS :: 0x35 +HID_USAGE_ALPHANUMERIC_COLUMNS :: 0x36 +HID_USAGE_ALPHANUMERIC_CURSOR_PIXEL_POSITIONING :: 0x37 +HID_USAGE_ALPHANUMERIC_CURSOR_MODE :: 0x38 +HID_USAGE_ALPHANUMERIC_CURSOR_ENABLE :: 0x39 +HID_USAGE_ALPHANUMERIC_CURSOR_BLINK :: 0x3A +HID_USAGE_ALPHANUMERIC_CHAR_WIDTH :: 0x3D +HID_USAGE_ALPHANUMERIC_CHAR_HEIGHT :: 0x3E +HID_USAGE_ALPHANUMERIC_CHAR_SPACING_HORIZONTAL :: 0x3F +HID_USAGE_ALPHANUMERIC_CHAR_SPACING_VERTICAL :: 0x40 +HID_USAGE_ALPHANUMERIC_UNICODE_CHAR_SET :: 0x41 +HID_USAGE_ALPHANUMERIC_FONT_7_SEGMENT :: 0x42 +HID_USAGE_ALPHANUMERIC_7_SEGMENT_DIRECT_MAP :: 0x43 +HID_USAGE_ALPHANUMERIC_FONT_14_SEGMENT :: 0x44 +HID_USAGE_ALPHANUMERIC_14_SEGMENT_DIRECT_MAP :: 0x45 +HID_USAGE_ALPHANUMERIC_DISPLAY_BRIGHTNESS :: 0x46 +HID_USAGE_ALPHANUMERIC_DISPLAY_CONTRAST :: 0x47 +HID_USAGE_ALPHANUMERIC_ATTRIBUTE_READBACK :: 0x49 +HID_USAGE_ALPHANUMERIC_ATTRIBUTE_DATA :: 0x4A +HID_USAGE_ALPHANUMERIC_CHAR_ATTR_ENHANCE :: 0x4B +HID_USAGE_ALPHANUMERIC_CHAR_ATTR_UNDERLINE :: 0x4C +HID_USAGE_ALPHANUMERIC_CHAR_ATTR_BLINK :: 0x4D +HID_USAGE_ALPHANUMERIC_BITMAP_SIZE_X :: 0x80 +HID_USAGE_ALPHANUMERIC_BITMAP_SIZE_Y :: 0x81 +HID_USAGE_ALPHANUMERIC_BIT_DEPTH_FORMAT :: 0x83 +HID_USAGE_ALPHANUMERIC_DISPLAY_ORIENTATION :: 0x84 +HID_USAGE_ALPHANUMERIC_PALETTE_DATA_SIZE :: 0x86 +HID_USAGE_ALPHANUMERIC_PALETTE_DATA_OFFSET :: 0x87 +HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_X1 :: 0x8B +HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_Y1 :: 0x8C +HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_X2 :: 0x8D +HID_USAGE_ALPHANUMERIC_BLIT_RECTANGLE_Y2 :: 0x8E +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_ID :: 0x91 +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_SIDE :: 0x92 +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_OFFSET1 :: 0x93 +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_OFFSET2 :: 0x94 +HID_USAGE_ALPHANUMERIC_SOFT_BUTTON_REPORT :: 0x95 -HID_USAGE_LAMPARRAY :: 0x01 -HID_USAGE_LAMPARRAY_ATTRBIUTES_REPORT :: 0x02 -HID_USAGE_LAMPARRAY_LAMP_COUNT :: 0x03 -HID_USAGE_LAMPARRAY_BOUNDING_BOX_WIDTH_IN_MICROMETERS :: 0x04 -HID_USAGE_LAMPARRAY_BOUNDING_BOX_HEIGHT_IN_MICROMETERS :: 0x05 -HID_USAGE_LAMPARRAY_BOUNDING_BOX_DEPTH_IN_MICROMETERS :: 0x06 -HID_USAGE_LAMPARRAY_KIND :: 0x07 +HID_USAGE_LAMPARRAY :: 0x01 +HID_USAGE_LAMPARRAY_ATTRBIUTES_REPORT :: 0x02 +HID_USAGE_LAMPARRAY_LAMP_COUNT :: 0x03 +HID_USAGE_LAMPARRAY_BOUNDING_BOX_WIDTH_IN_MICROMETERS :: 0x04 +HID_USAGE_LAMPARRAY_BOUNDING_BOX_HEIGHT_IN_MICROMETERS :: 0x05 +HID_USAGE_LAMPARRAY_BOUNDING_BOX_DEPTH_IN_MICROMETERS :: 0x06 +HID_USAGE_LAMPARRAY_KIND :: 0x07 HID_USAGE_LAMPARRAY_MIN_UPDATE_INTERVAL_IN_MICROSECONDS :: 0x08 // 0x09 - 0x1F Reserved -HID_USAGE_LAMPARRAY_LAMP_ATTRIBUTES_REQUEST_REPORT :: 0x20 -HID_USAGE_LAMPARRAY_LAMP_ID :: 0x21 +HID_USAGE_LAMPARRAY_LAMP_ATTRIBUTES_REQUEST_REPORT :: 0x20 +HID_USAGE_LAMPARRAY_LAMP_ID :: 0x21 HID_USAGE_LAMPARRAY_LAMP_ATTRIBUTES_RESPONSE_REPORT :: 0x22 -HID_USAGE_LAMPARRAY_POSITION_X_IN_MICROMETERS :: 0x23 -HID_USAGE_LAMPARRAY_POSITION_Y_IN_MICROMETERS :: 0x24 -HID_USAGE_LAMPARRAY_POSITION_Z_IN_MICROMETERS :: 0x25 -HID_USAGE_LAMPARRAY_LAMP_PURPOSES :: 0x26 -HID_USAGE_LAMPARRAY_UPDATE_LATENCY_IN_MICROSECONDS :: 0x27 -HID_USAGE_LAMPARRAY_RED_LEVEL_COUNT :: 0x28 -HID_USAGE_LAMPARRAY_GREEN_LEVEL_COUNT :: 0x29 -HID_USAGE_LAMPARRAY_BLUE_LEVEL_COUNT :: 0x2A -HID_USAGE_LAMPARRAY_INTENSITY_LEVEL_COUNT :: 0x2B -HID_USAGE_LAMPARRAY_IS_PROGRAMMABLE :: 0x2C -HID_USAGE_LAMPARRAY_INPUT_BINDING :: 0x2D +HID_USAGE_LAMPARRAY_POSITION_X_IN_MICROMETERS :: 0x23 +HID_USAGE_LAMPARRAY_POSITION_Y_IN_MICROMETERS :: 0x24 +HID_USAGE_LAMPARRAY_POSITION_Z_IN_MICROMETERS :: 0x25 +HID_USAGE_LAMPARRAY_LAMP_PURPOSES :: 0x26 +HID_USAGE_LAMPARRAY_UPDATE_LATENCY_IN_MICROSECONDS :: 0x27 +HID_USAGE_LAMPARRAY_RED_LEVEL_COUNT :: 0x28 +HID_USAGE_LAMPARRAY_GREEN_LEVEL_COUNT :: 0x29 +HID_USAGE_LAMPARRAY_BLUE_LEVEL_COUNT :: 0x2A +HID_USAGE_LAMPARRAY_INTENSITY_LEVEL_COUNT :: 0x2B +HID_USAGE_LAMPARRAY_IS_PROGRAMMABLE :: 0x2C +HID_USAGE_LAMPARRAY_INPUT_BINDING :: 0x2D // 0x2E - 0x4F Reserved -HID_USAGE_LAMPARRAY_LAMP_MULTI_UPDATE_REPORT :: 0x50 -HID_USAGE_LAMPARRAY_LAMP_RED_UPDATE_CHANNEL :: 0x51 -HID_USAGE_LAMPARRAY_LAMP_GREEN_UPDATE_CHANNEL :: 0x52 -HID_USAGE_LAMPARRAY_LAMP_BLUE_UPDATE_CHANNEL :: 0x53 +HID_USAGE_LAMPARRAY_LAMP_MULTI_UPDATE_REPORT :: 0x50 +HID_USAGE_LAMPARRAY_LAMP_RED_UPDATE_CHANNEL :: 0x51 +HID_USAGE_LAMPARRAY_LAMP_GREEN_UPDATE_CHANNEL :: 0x52 +HID_USAGE_LAMPARRAY_LAMP_BLUE_UPDATE_CHANNEL :: 0x53 HID_USAGE_LAMPARRAY_LAMP_INTENSITY_UPDATE_CHANNEL :: 0x54 -HID_USAGE_LAMPARRAY_LAMP_UPDATE_FLAGS :: 0x55 +HID_USAGE_LAMPARRAY_LAMP_UPDATE_FLAGS :: 0x55 // 0x55 - 0x5F Reserved HID_USAGE_LAMPARRAY_LAMP_RANGE_UPDATE_REPORT :: 0x60 -HID_USAGE_LAMPARRAY_LAMP_ID_START :: 0x61 -HID_USAGE_LAMPARRAY_LAMP_ID_END :: 0x62 +HID_USAGE_LAMPARRAY_LAMP_ID_START :: 0x61 +HID_USAGE_LAMPARRAY_LAMP_ID_END :: 0x62 // 0x63 - 0x6F Reserved -HID_USAGE_LAMPARRAY_CONTROL_REPORT :: 0x70 +HID_USAGE_LAMPARRAY_CONTROL_REPORT :: 0x70 HID_USAGE_LAMPARRAY_AUTONOMOUS_MODE :: 0x71 HID_USAGE_CAMERA_AUTO_FOCUS :: 0x20 -HID_USAGE_CAMERA_SHUTTER :: 0x21 +HID_USAGE_CAMERA_SHUTTER :: 0x21 HID_USAGE_MS_BTH_HF_DIALNUMBER :: 0x21 HID_USAGE_MS_BTH_HF_DIALMEMORY :: 0x22 diff --git a/core/sys/windows/icu.odin b/core/sys/windows/icu.odin index 6ed8c9b40..7be9ce4c6 100644 --- a/core/sys/windows/icu.odin +++ b/core/sys/windows/icu.odin @@ -10,5 +10,8 @@ UError :: enum i32 { @(default_calling_convention="system") foreign icu { ucal_getWindowsTimeZoneID :: proc(id: wstring, len: i32, winid: wstring, winidCapacity: i32, status: ^UError) -> i32 --- - ucal_getDefaultTimeZone :: proc(result: wstring, cap: i32, status: ^UError) -> i32 --- + ucal_getDefaultTimeZone :: proc(result: wstring, cap: i32, status: ^UError) -> i32 --- } + + +// NOTE(bill): all of these types actually do use `i32` and not `c_int` diff --git a/core/sys/windows/ioringapi.odin b/core/sys/windows/ioringapi.odin new file mode 100644 index 000000000..0e3b89722 --- /dev/null +++ b/core/sys/windows/ioringapi.odin @@ -0,0 +1,106 @@ +#+build windows +package sys_windows + +foreign import ioringapi "system:kernel32.lib" + +HIORING :: distinct rawptr + +IORING_SQE_FLAG :: enum u32 { + DRAIN_PRECEDING_OPS = 0, // 0x00000001 +} +IORING_SQE_FLAGS :: bit_set[IORING_SQE_FLAG; u32] + +// Reserved for future use; currently no flags defined +IORING_CREATE_REQUIRED_FLAG :: enum u32 {} +IORING_CREATE_REQUIRED_FLAGS :: bit_set[IORING_CREATE_REQUIRED_FLAG; u32] + +IORING_CREATE_ADVISORY_FLAG :: enum u32 { + SKIP_BUILDER_PARAM_CHECKS = 0, // 0x00000001 +} +IORING_CREATE_ADVISORY_FLAGS :: bit_set[IORING_CREATE_ADVISORY_FLAG; u32] + +IORING_CREATE_FLAGS :: struct { + Required: IORING_CREATE_REQUIRED_FLAGS, + Advisory: IORING_CREATE_ADVISORY_FLAGS, +} + +IORING_INFO :: struct { + Version: IORING_VERSION, + Flags: IORING_CREATE_FLAGS, + SubmissionQueueSize: UINT32, + CompletionQueueSize: UINT32, +} + +IORING_CAPABILITIES :: struct { + MaxVersion: IORING_VERSION, + MaxSubmissionQueueSize: UINT32, + MaxCompletionQueueSize: UINT32, + FeatureFlags: IORING_FEATURE_FLAGS, +} + +IORING_REF_KIND :: enum i32 { + RAW, + REGISTERED, +} + +IORING_HANDLE_REF :: struct { + Kind: IORING_REF_KIND, + HandleUnion: struct #raw_union { + Handle: HANDLE, + Index: UINT32, + }, +} + +IORING_BUFFER_REF :: struct { + Kind: IORING_REF_KIND, + BufferUnion: struct #raw_union { + Address: rawptr, + IndexAndOffset: IORING_REGISTERED_BUFFER, + }, +} + +IORING_CQE :: struct { + UserData: UINT_PTR, + ResultCode: HRESULT, + Information: ULONG_PTR, +} + +// Types below are from winbase.h and winnt.h +FILE_WRITE_FLAG :: enum u32 { + WRITE_THROUGH = 0, // 0x000000001 +} +FILE_WRITE_FLAGS :: bit_set[FILE_WRITE_FLAG ;u32] + +FILE_FLUSH_MODE :: enum i32 { + DEFAULT, + DATA, + MIN_METADATA, + NO_SYNC, +} + +FILE_SEGMENT_ELEMENT :: struct #raw_union { + Buffer: PVOID64, + Alignment: ULONGLONG, +} + + +@(default_calling_convention="system") +foreign ioringapi { + QueryIoRingCapabilities :: proc(capabilities: ^IORING_CAPABILITIES) -> HRESULT --- + IsIoRingOpSupported :: proc(ioRing: HIORING, op: IORING_OP_CODE) -> BOOL --- + CreateIoRing :: proc(ioringVersion: IORING_VERSION, flags: IORING_CREATE_FLAGS, submissionQueueSize: UINT32, completionQueueSize: UINT32, h: ^HIORING) -> HRESULT --- + GetIoRingInfo :: proc(ioRing: HIORING, info: ^IORING_INFO) -> HRESULT --- + SubmitIoRing :: proc(ioRing: HIORING, waitOperations: UINT32, milliseconds: UINT32, submittedEntries: ^UINT32) -> HRESULT --- + CloseIoRing :: proc(ioRing: HIORING) -> HRESULT --- + PopIoRingCompletion :: proc(ioRing: HIORING, cqe: ^IORING_CQE) -> HRESULT --- + SetIoRingCompletionEvent :: proc(ioRing: HIORING, hEvent: HANDLE) -> HRESULT --- + + BuildIoRingCancelRequest :: proc(ioRing: HIORING, file: IORING_HANDLE_REF, opToCancel: UINT_PTR, userData: UINT_PTR) -> HRESULT --- + BuildIoRingReadFile :: proc(ioRing: HIORING, fileRef: IORING_HANDLE_REF, dataRef: IORING_BUFFER_REF, numberOfBytesToRead: UINT32, fileOffset: UINT64, userData: UINT_PTR, sqeFlags: IORING_SQE_FLAGS) -> HRESULT --- + BuildIoRingRegisterFileHandles :: proc(ioRing: HIORING, count: UINT32, handles: [^]HANDLE, userData: UINT_PTR) -> HRESULT --- + BuildIoRingRegisterBuffers :: proc(ioRing: HIORING, count: UINT32, buffers: [^]IORING_BUFFER_INFO, userData: UINT_PTR) -> HRESULT --- + BuildIoRingWriteFile :: proc(ioRing: HIORING, fileRef: IORING_HANDLE_REF, bufferRef: IORING_BUFFER_REF, numberOfBytesToWrite: UINT32, fileOffset: UINT64, writeFlags: FILE_WRITE_FLAGS, userData: UINT_PTR, sqeFlags: IORING_SQE_FLAGS) -> HRESULT --- + BuildIoRingFlushFile :: proc(ioRing: HIORING, fileRef: IORING_HANDLE_REF, flushMode: FILE_FLUSH_MODE, userData: UINT_PTR, sqeFlags: IORING_SQE_FLAGS) -> HRESULT --- + BuildIoRingReadFileScatter :: proc(ioRing: HIORING, fileRef: IORING_HANDLE_REF, segmentCount: UINT32, segmentArray: [^]FILE_SEGMENT_ELEMENT, numberOfBytesToRead: UINT32, fileOffset: UINT64, userData: UINT_PTR, sqeFlags: IORING_SQE_FLAGS) -> HRESULT --- + BuildIoRingWriteFileGather :: proc(ioRing: HIORING, fileRef: IORING_HANDLE_REF, segmentCount: UINT32, segmentArray: [^]FILE_SEGMENT_ELEMENT, numberOfBytesToWrite: UINT32, fileOffset: UINT64, writeFlags: FILE_WRITE_FLAGS, userData: UINT_PTR, sqeFlags: IORING_SQE_FLAGS) -> HRESULT --- +} diff --git a/core/sys/windows/ip_helper.odin b/core/sys/windows/ip_helper.odin index 7a6e545ac..74ffa95b9 100644 --- a/core/sys/windows/ip_helper.odin +++ b/core/sys/windows/ip_helper.odin @@ -38,9 +38,9 @@ IP_Adapter_Addresses :: struct { FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP, FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP, FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP, - DnsSuffix: ^u16, - Description: ^u16, - FriendlyName: ^u16, + DnsSuffix: cstring16, + Description: cstring16, + FriendlyName: cstring16, PhysicalAddress: [8]u8, PhysicalAddressLength: u32, Anonymous2: struct #raw_union { @@ -141,7 +141,7 @@ IP_ADAPTER_DNS_SERVER_ADDRESS_XP :: struct { Address: SOCKET_ADDRESS, } -IF_OPER_STATUS :: enum i32 { +IF_OPER_STATUS :: enum c_int { Up = 1, Down = 2, Testing = 3, @@ -160,17 +160,17 @@ NET_LUID_LH :: struct #raw_union { SOCKET_ADDRESS :: struct { lpSockaddr: ^SOCKADDR, - iSockaddrLength: i32, + iSockaddrLength: INT, } -NET_IF_CONNECTION_TYPE :: enum i32 { +NET_IF_CONNECTION_TYPE :: enum c_int { NET_IF_CONNECTION_DEDICATED = 1, NET_IF_CONNECTION_PASSIVE = 2, NET_IF_CONNECTION_DEMAND = 3, NET_IF_CONNECTION_MAXIMUM = 4, } -TUNNEL_TYPE :: enum i32 { +TUNNEL_TYPE :: enum c_int { TUNNEL_TYPE_NONE = 0, TUNNEL_TYPE_OTHER = 1, TUNNEL_TYPE_DIRECT = 2, @@ -179,7 +179,7 @@ TUNNEL_TYPE :: enum i32 { TUNNEL_TYPE_TEREDO = 14, TUNNEL_TYPE_IPHTTPS = 15, } -NL_PREFIX_ORIGIN :: enum i32 { +NL_PREFIX_ORIGIN :: enum c_int { IpPrefixOriginOther = 0, IpPrefixOriginManual = 1, IpPrefixOriginWellKnown = 2, @@ -188,7 +188,7 @@ NL_PREFIX_ORIGIN :: enum i32 { IpPrefixOriginUnchanged = 16, } -NL_SUFFIX_ORIGIN :: enum i32 { +NL_SUFFIX_ORIGIN :: enum c_int { NlsoOther = 0, NlsoManual = 1, NlsoWellKnown = 2, @@ -204,7 +204,7 @@ NL_SUFFIX_ORIGIN :: enum i32 { IpSuffixOriginUnchanged = 16, } -NL_DAD_STATE :: enum i32 { +NL_DAD_STATE :: enum c_int { NldsInvalid = 0, NldsTentative = 1, NldsDuplicate = 2, @@ -223,7 +223,7 @@ foreign iphlpapi { The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer. See: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses */ - @(link_name="GetAdaptersAddresses") get_adapters_addresses :: proc( + GetAdaptersAddresses :: proc( family: Address_Family, flags: GAA_Flags, _reserved: rawptr, @@ -232,3 +232,5 @@ foreign iphlpapi { ) -> ULONG --- } + +get_adapters_addresses :: GetAdaptersAddresses \ No newline at end of file diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 266dcdbf4..9b08d7ba6 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -30,6 +30,18 @@ EV_RXCHAR :: DWORD(0x0001) EV_RXFLAG :: DWORD(0x0002) EV_TXEMPTY :: DWORD(0x0004) +WAITORTIMERCALLBACK :: #type proc "system" (lpParameter: PVOID, TimerOrWaitFired: BOOLEAN) + +PAPCFUNC :: #type proc "system" (Parameter: ULONG_PTR) + +WT_EXECUTEDEFAULT :: 0x00000000 +WT_EXECUTEINIOTHREAD :: 0x00000001 +WT_EXECUTEINPERSISTENTTHREAD :: 0x00000080 +WT_EXECUTEINWAITTHREAD :: 0x00000004 +WT_EXECUTELONGFUNCTION :: 0x00000010 +WT_EXECUTEONLYONCE :: 0x00000008 +WT_TRANSFER_IMPERSONATION :: 0x00000100 + @(default_calling_convention="system") foreign kernel32 { OutputDebugStringA :: proc(lpOutputString: LPCSTR) --- // The only A thing that is allowed @@ -60,15 +72,15 @@ foreign kernel32 { // https://learn.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents GetNumberOfConsoleInputEvents :: proc(hConsoleInput: HANDLE, lpcNumberOfEvents: LPDWORD) -> BOOL --- - GetConsoleMode :: proc(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL --- - SetConsoleMode :: proc(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL --- + GetConsoleMode :: proc(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL --- + SetConsoleMode :: proc(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL --- SetConsoleCursorPosition :: proc(hConsoleHandle: HANDLE, dwCursorPosition: COORD) -> BOOL --- - SetConsoleTextAttribute :: proc(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL --- - GetConsoleCP :: proc() -> CODEPAGE --- - SetConsoleCP :: proc(wCodePageID: CODEPAGE) -> BOOL --- - GetConsoleOutputCP :: proc() -> CODEPAGE --- - SetConsoleOutputCP :: proc(wCodePageID: CODEPAGE) -> BOOL --- - FlushConsoleInputBuffer :: proc(hConsoleInput: HANDLE) -> BOOL --- + SetConsoleTextAttribute :: proc(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL --- + GetConsoleCP :: proc() -> CODEPAGE --- + SetConsoleCP :: proc(wCodePageID: CODEPAGE) -> BOOL --- + GetConsoleOutputCP :: proc() -> CODEPAGE --- + SetConsoleOutputCP :: proc(wCodePageID: CODEPAGE) -> BOOL --- + FlushConsoleInputBuffer :: proc(hConsoleInput: HANDLE) -> BOOL --- GetFileInformationByHandle :: proc(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) -> BOOL --- @@ -82,11 +94,11 @@ foreign kernel32 { dwBufferSize: DWORD) -> BOOL --- - AddVectoredExceptionHandler :: proc(FirstHandler: ULONG, VectoredHandler: PVECTORED_EXCEPTION_HANDLER) -> LPVOID --- - AddVectoredContinueHandler :: proc(FirstHandler: ULONG, VectoredHandler: PVECTORED_EXCEPTION_HANDLER) -> LPVOID --- + AddVectoredExceptionHandler :: proc(FirstHandler: ULONG, VectoredHandler: PVECTORED_EXCEPTION_HANDLER) -> LPVOID --- + AddVectoredContinueHandler :: proc(FirstHandler: ULONG, VectoredHandler: PVECTORED_EXCEPTION_HANDLER) -> LPVOID --- RemoveVectoredExceptionHandler :: proc(Handle: LPVOID) -> DWORD --- - RemoveVectoredContinueHandler :: proc(Handle: LPVOID) -> DWORD --- - RaiseException :: proc(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! --- + RemoveVectoredContinueHandler :: proc(Handle: LPVOID) -> DWORD --- + RaiseException :: proc(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! --- SetUnhandledExceptionFilter :: proc(lpTopLevelExceptionFilter: LPTOP_LEVEL_EXCEPTION_FILTER) -> LPTOP_LEVEL_EXCEPTION_FILTER --- @@ -103,31 +115,31 @@ foreign kernel32 { lpFileInformation: LPVOID, dwBufferSize: DWORD) -> BOOL --- - InitializeCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- + InitializeCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- InitializeCriticalSectionAndSpinCount :: proc(CriticalSection: ^CRITICAL_SECTION, dwSpinCount: DWORD) -> BOOL --- - EnterCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- - TryEnterCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) -> BOOLEAN --- - LeaveCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- - DeleteCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- + EnterCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- + TryEnterCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) -> BOOLEAN --- + LeaveCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- + DeleteCriticalSection :: proc(CriticalSection: ^CRITICAL_SECTION) --- - RemoveDirectoryW :: proc(lpPathName: LPCWSTR) -> BOOL --- - SetFileAttributesW :: proc(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL --- - SetLastError :: proc(dwErrCode: DWORD) --- - GetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL --- - SetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL --- - ClearCommError :: proc(hFile: HANDLE, lpErrors: ^Com_Error, lpStat: ^COMSTAT) -> BOOL --- - GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- - SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- - SetCommMask :: proc(handle: HANDLE, dwEvtMap: DWORD) -> BOOL --- - GetCommMask :: proc(handle: HANDLE, lpEvtMask: LPDWORD) -> BOOL --- - WaitCommEvent :: proc(handle: HANDLE, lpEvtMask: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL --- - GetCommandLineW :: proc() -> LPCWSTR --- - GetTempPathW :: proc(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD --- - GetTempFileNameW :: proc(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: c_int, lpTempFileName: LPWSTR) -> c_uint --- - GetCurrentProcess :: proc() -> HANDLE --- + RemoveDirectoryW :: proc(lpPathName: LPCWSTR) -> BOOL --- + SetFileAttributesW :: proc(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL --- + SetLastError :: proc(dwErrCode: DWORD) --- + GetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL --- + SetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL --- + ClearCommError :: proc(hFile: HANDLE, lpErrors: ^Com_Error, lpStat: ^COMSTAT) -> BOOL --- + GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- + SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL --- + SetCommMask :: proc(handle: HANDLE, dwEvtMap: DWORD) -> BOOL --- + GetCommMask :: proc(handle: HANDLE, lpEvtMask: LPDWORD) -> BOOL --- + WaitCommEvent :: proc(handle: HANDLE, lpEvtMask: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL --- + GetCommandLineW :: proc() -> LPCWSTR --- + GetTempPathW :: proc(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD --- + GetTempFileNameW :: proc(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: c_int, lpTempFileName: LPWSTR) -> c_uint --- + GetCurrentProcess :: proc() -> HANDLE --- GetCurrentProcessId :: proc() -> DWORD --- - GetCurrentThread :: proc() -> HANDLE --- - GetCurrentThreadId :: proc() -> DWORD --- + GetCurrentThread :: proc() -> HANDLE --- + GetCurrentThreadId :: proc() -> DWORD --- GetProcessTimes :: proc( hProcess: HANDLE, lpCreationTime: LPFILETIME, @@ -136,7 +148,7 @@ foreign kernel32 { lpUserTime: LPFILETIME, ) -> BOOL --- GetStdHandle :: proc(which: DWORD) -> HANDLE --- - ExitProcess :: proc(uExitCode: c_uint) -> ! --- + ExitProcess :: proc(uExitCode: c_uint) -> ! --- DeviceIoControl :: proc( hDevice: HANDLE, dwIoControlCode: DWORD, @@ -164,14 +176,15 @@ foreign kernel32 { dwCreationFlags: DWORD, lpThreadId: LPDWORD, ) -> HANDLE --- - SwitchToThread :: proc() -> BOOL --- - ResumeThread :: proc(thread: HANDLE) -> DWORD --- - GetThreadPriority :: proc(thread: HANDLE) -> c_int --- - SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL --- + SwitchToThread :: proc() -> BOOL --- + ResumeThread :: proc(thread: HANDLE) -> DWORD --- + GetThreadPriority :: proc(thread: HANDLE) -> c_int --- + SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL --- + GetThreadDescription :: proc(hThread: HANDLE, ppszThreadDescription: ^PCWSTR) -> HRESULT --- SetThreadDescription :: proc(hThread: HANDLE, lpThreadDescription: PCWSTR) -> HRESULT --- - GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL --- - TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL --- - SuspendThread :: proc(hThread: HANDLE) -> DWORD --- + GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL --- + TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL --- + SuspendThread :: proc(hThread: HANDLE) -> DWORD --- GetProcessAffinityMask :: proc( hProcess: HANDLE, @@ -212,6 +225,16 @@ foreign kernel32 { ) -> BOOL --- WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- WaitForSingleObjectEx :: proc(hHandle: HANDLE, dwMilliseconds: DWORD, bAlterable: BOOL) -> DWORD --- + EnterSynchronizationBarrier :: proc( + lpBarrier: ^SYNCHRONIZATION_BARRIER, + dwFlags: SYNCHRONIZATION_BARRIER_FLAGS, + ) -> BOOL --- + InitializeSynchronizationBarrier :: proc( + lpBarrier: ^SYNCHRONIZATION_BARRIER, + lTotalThreads: LONG, + lSpinCount: LONG, + ) -> BOOL --- + DeleteSynchronizationBarrier :: proc(lpBarrier: ^SYNCHRONIZATION_BARRIER) -> BOOL --- Sleep :: proc(dwMilliseconds: DWORD) --- GetProcessId :: proc(handle: HANDLE) -> DWORD --- CopyFileW :: proc( @@ -236,17 +259,17 @@ foreign kernel32 { nsize: DWORD, args: rawptr, ) -> DWORD --- - TlsAlloc :: proc() -> DWORD --- - TlsFree :: proc(dwTlsIndex: DWORD) -> BOOL --- - TlsGetValue :: proc(dwTlsIndex: DWORD) -> LPVOID --- - TlsSetValue :: proc(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL --- - GetLastError :: proc() -> DWORD --- + TlsAlloc :: proc() -> DWORD --- + TlsFree :: proc(dwTlsIndex: DWORD) -> BOOL --- + TlsGetValue :: proc(dwTlsIndex: DWORD) -> LPVOID --- + TlsSetValue :: proc(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL --- + GetLastError :: proc() -> DWORD --- QueryPerformanceFrequency :: proc(lpFrequency: ^LARGE_INTEGER) -> BOOL --- - QueryPerformanceCounter :: proc(lpPerformanceCount: ^LARGE_INTEGER) -> BOOL --- - GetExitCodeProcess :: proc(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL --- - TerminateProcess :: proc(hProcess: HANDLE, uExitCode: UINT) -> BOOL --- - OpenProcess :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE --- - OpenThread :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwThreadId: DWORD) -> HANDLE --- + QueryPerformanceCounter :: proc(lpPerformanceCount: ^LARGE_INTEGER) -> BOOL --- + GetExitCodeProcess :: proc(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL --- + TerminateProcess :: proc(hProcess: HANDLE, uExitCode: UINT) -> BOOL --- + OpenProcess :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE --- + OpenThread :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwThreadId: DWORD) -> HANDLE --- GetThreadContext :: proc( hThread: HANDLE, lpContext: LPCONTEXT, @@ -257,7 +280,7 @@ foreign kernel32 { ) -> BOOL --- CreateProcessW :: proc( lpApplicationName: LPCWSTR, - lpCommandLine: LPWSTR, + lpCommandLine: LPCWSTR, lpProcessAttributes: LPSECURITY_ATTRIBUTES, lpThreadAttributes: LPSECURITY_ATTRIBUTES, bInheritHandles: BOOL, @@ -341,6 +364,22 @@ foreign kernel32 { hTemplateFile: HANDLE, ) -> HANDLE --- + LockFileEx :: proc( + hFile: HANDLE, + dwFLags: DWORD, + dwReserved: DWORD, + nNumberOfBytesToLockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL --- + UnlockFileEx :: proc( + hFile: HANDLE, + dwReserved: DWORD, + nNumberOfBytesToUnlockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL --- + GetFileTime :: proc( hFile: HANDLE, lpCreationTime: LPFILETIME, @@ -349,14 +388,14 @@ foreign kernel32 { ) -> BOOL --- CompareFileTime :: proc(lpFileTime1: LPFILETIME, lpFileTime2: LPFILETIME) -> LONG --- - FindFirstFileW :: proc(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE --- - FindNextFileW :: proc(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL --- - FindClose :: proc(findFile: HANDLE) -> BOOL --- - GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE --- - GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- - GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- - GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- - FileTimeToSystemTime :: proc(lpFileTime: ^FILETIME, lpSystemTime: ^SYSTEMTIME) -> BOOL --- + FindFirstFileW :: proc(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE --- + FindNextFileW :: proc(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL --- + FindClose :: proc(findFile: HANDLE) -> BOOL --- + GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE --- + GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- + GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- + GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- + FileTimeToSystemTime :: proc(lpFileTime: ^FILETIME, lpSystemTime: ^SYSTEMTIME) -> BOOL --- SystemTimeToTzSpecificLocalTime :: proc( lpTimeZoneInformation: ^TIME_ZONE_INFORMATION, lpUniversalTime: ^SYSTEMTIME, @@ -372,6 +411,12 @@ foreign kernel32 { bInitialState: BOOL, lpName: LPCWSTR, ) -> HANDLE --- + CreateEventExW :: proc( + lpEventAttributes: LPSECURITY_ATTRIBUTES, + lpName: LPCWSTR, + dwFlags: DWORD, + dwDesiredAccess: DWORD, + ) -> HANDLE --- ResetEvent :: proc(hEvent: HANDLE) -> BOOL --- SetEvent :: proc(hEvent: HANDLE) -> BOOL --- WaitForMultipleObjects :: proc( @@ -405,7 +450,8 @@ foreign kernel32 { lpTotalBytesAvail: ^u32, lpBytesLeftThisMessage: ^u32, ) -> BOOL --- - CancelIo :: proc(handle: HANDLE) -> BOOL --- + CancelIo :: proc(handle: HANDLE) -> BOOL --- + CancelIoEx :: proc(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL --- GetOverlappedResult :: proc( hFile: HANDLE, lpOverlapped: LPOVERLAPPED, @@ -413,19 +459,20 @@ foreign kernel32 { bWait: BOOL, ) -> BOOL --- GetProcessHeap :: proc() -> HANDLE --- - HeapAlloc :: proc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID --- - HeapReAlloc :: proc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID --- - HeapFree :: proc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL --- + HeapAlloc :: proc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID --- + HeapReAlloc :: proc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID --- + HeapFree :: proc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL --- - LocalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID --- + LocalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID --- LocalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID --- - LocalFree :: proc(mem: LPVOID) -> LPVOID --- + LocalFree :: proc(mem: LPVOID) -> LPVOID --- - GlobalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID --- + GlobalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID --- GlobalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID --- - GlobalFree :: proc(mem: LPVOID) -> LPVOID --- + GlobalFree :: proc(mem: LPVOID) -> LPVOID --- + GlobalSize :: proc(Mem: LPVOID) -> SIZE_T --- - GlobalLock :: proc(hMem: HGLOBAL) -> LPVOID --- + GlobalLock :: proc(hMem: HGLOBAL) -> LPVOID --- GlobalUnlock :: proc(hMem: HGLOBAL) -> BOOL --- ReadDirectoryChangesW :: proc( @@ -438,21 +485,32 @@ foreign kernel32 { lpOverlapped: LPOVERLAPPED, lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, ) -> BOOL --- + ReadDirectoryChangesExW :: proc( + hDirectory: HANDLE, + lpBuffer: LPVOID, + nBufferLength: DWORD, + bWatchSubtree: BOOL, + dwNotifyFilter: DWORD, + lpBytesReturned: LPDWORD, + lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ReadDirectoryNotifyInformationClass: READ_DIRECTORY_NOTIFY_INFORMATION_CLASS, + ) -> BOOL --- FindFirstChangeNotificationW :: proc( lpPathName: LPWSTR, bWatchSubtree: BOOL, dwNotifyFilter: DWORD, ) -> HANDLE --- - FindNextChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL --- + FindNextChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL --- FindCloseChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL --- InitializeSRWLock :: proc(SRWLock: ^SRWLOCK) --- AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) --- TryAcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) -> BOOLEAN --- ReleaseSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) --- - AcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- - TryAcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) -> BOOLEAN --- - ReleaseSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- + AcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- + TryAcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) -> BOOLEAN --- + ReleaseSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- InitializeConditionVariable :: proc(ConditionVariable: ^CONDITION_VARIABLE) --- WakeConditionVariable :: proc(ConditionVariable: ^CONDITION_VARIABLE) --- @@ -461,41 +519,42 @@ foreign kernel32 { SleepConditionVariableSRW :: proc(ConditionVariable: ^CONDITION_VARIABLE, SRWLock: ^SRWLOCK, dwMilliseconds: DWORD, Flags: LONG) -> BOOL --- - GetFileType :: proc(file_handle: HANDLE) -> DWORD --- - SetFilePointer :: proc(file_handle: HANDLE, distance_to_move: LONG, distance_to_move_high: ^LONG, move_method: DWORD) -> DWORD --- - GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^LARGE_INTEGER) -> BOOL --- - GetFileAttributesW :: proc(lpFileName: LPCWSTR) -> DWORD --- - GetFileAttributesExW :: proc(lpFileName: LPCWSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID) -> BOOL --- - GetSystemInfo :: proc(system_info: ^SYSTEM_INFO) --- - GetVersionExW :: proc(osvi: ^OSVERSIONINFOEXW) --- - GetSystemDirectoryW :: proc(lpBuffer: LPWSTR, uSize: UINT) -> UINT --- - GetWindowsDirectoryW :: proc(lpBuffer: LPWSTR, uSize: UINT) -> UINT --- - GetSystemDefaultLangID :: proc() -> LANGID --- - GetSystemDefaultLCID :: proc() -> LCID --- + GetFileType :: proc(file_handle: HANDLE) -> DWORD --- + SetFilePointer :: proc(file_handle: HANDLE, distance_to_move: LONG, distance_to_move_high: ^LONG, move_method: DWORD) -> DWORD --- + GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^LARGE_INTEGER) -> BOOL --- + GetFileAttributesW :: proc(lpFileName: LPCWSTR) -> DWORD --- + GetFileAttributesExW :: proc(lpFileName: LPCWSTR, fInfoLevelId: GET_FILEEX_INFO_LEVELS, lpFileInformation: LPVOID) -> BOOL --- + GetSystemInfo :: proc(system_info: ^SYSTEM_INFO) --- + GetVersionExW :: proc(osvi: ^OSVERSIONINFOEXW) --- + GetSystemDirectoryW :: proc(lpBuffer: LPWSTR, uSize: UINT) -> UINT --- + GetWindowsDirectoryW :: proc(lpBuffer: LPWSTR, uSize: UINT) -> UINT --- + GetSystemDefaultLangID :: proc() -> LANGID --- + GetSystemDefaultLCID :: proc() -> LCID --- GetSystemDefaultLocaleName :: proc(lpLocaleName: LPWSTR, cchLocaleName: INT) -> INT --- - LCIDToLocaleName :: proc(Locale: LCID, lpName: LPWSTR, cchName: INT, dwFlags: DWORD) -> INT --- - LocaleNameToLCID :: proc(lpName: LPCWSTR, dwFlags: DWORD) -> LCID --- - SetDllDirectoryW :: proc(lpPathName: LPCWSTR) -> BOOL --- - AddDllDirectory :: proc(NewDirectory: PCWSTR) -> rawptr --- - RemoveDllDirectory :: proc(Cookie: rawptr) -> BOOL --- - LoadLibraryW :: proc(c_str: LPCWSTR) -> HMODULE --- - LoadLibraryExW :: proc(c_str: LPCWSTR, hFile: HANDLE, dwFlags: LoadLibraryEx_Flags) -> HMODULE --- - FreeLibrary :: proc(h: HMODULE) -> BOOL --- - GetProcAddress :: proc(h: HMODULE, c_str: LPCSTR) -> rawptr --- + LCIDToLocaleName :: proc(Locale: LCID, lpName: LPWSTR, cchName: INT, dwFlags: DWORD) -> INT --- + LocaleNameToLCID :: proc(lpName: LPCWSTR, dwFlags: DWORD) -> LCID --- + SetDllDirectoryW :: proc(lpPathName: LPCWSTR) -> BOOL --- + AddDllDirectory :: proc(NewDirectory: PCWSTR) -> rawptr --- + RemoveDllDirectory :: proc(Cookie: rawptr) -> BOOL --- + LoadLibraryW :: proc(c_str: LPCWSTR) -> HMODULE --- + LoadLibraryExW :: proc(c_str: LPCWSTR, hFile: HANDLE, dwFlags: LoadLibraryEx_Flags) -> HMODULE --- + FreeLibrary :: proc(h: HMODULE) -> BOOL --- + FreeLibraryAndExitThread :: proc(hLibModule: HMODULE, dwExitCode: DWORD) --- + GetProcAddress :: proc(h: HMODULE, c_str: LPCSTR) -> rawptr --- - LoadResource :: proc(hModule: HMODULE, hResInfo: HRSRC) -> HGLOBAL --- - FreeResource :: proc(hResData: HGLOBAL) -> BOOL --- - LockResource :: proc(hResData: HGLOBAL) -> LPVOID --- - SizeofResource :: proc(hModule: HMODULE, hResInfo: HRSRC) -> DWORD --- - FindResourceW :: proc(hModule: HMODULE, lpName: LPCWSTR, lpType: LPCWSTR) -> HRSRC --- - FindResourceExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, wLanguage: LANGID) -> HRSRC --- - EnumResourceNamesW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR) -> BOOL --- - EnumResourceNamesExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- - EnumResourceTypesExW :: proc(hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- - EnumResourceLanguagesExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, lpEnumFunc: ENUMRESLANGPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- - LookupIconIdFromDirectory :: proc(presbits: PBYTE, fIcon: BOOL) -> INT --- + LoadResource :: proc(hModule: HMODULE, hResInfo: HRSRC) -> HGLOBAL --- + FreeResource :: proc(hResData: HGLOBAL) -> BOOL --- + LockResource :: proc(hResData: HGLOBAL) -> LPVOID --- + SizeofResource :: proc(hModule: HMODULE, hResInfo: HRSRC) -> DWORD --- + FindResourceW :: proc(hModule: HMODULE, lpName: LPCWSTR, lpType: LPCWSTR) -> HRSRC --- + FindResourceExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, wLanguage: LANGID) -> HRSRC --- + EnumResourceNamesW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR) -> BOOL --- + EnumResourceNamesExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpEnumFunc: ENUMRESNAMEPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- + EnumResourceTypesExW :: proc(hModule: HMODULE, lpEnumFunc: ENUMRESTYPEPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- + EnumResourceLanguagesExW :: proc(hModule: HMODULE, lpType: LPCWSTR, lpName: LPCWSTR, lpEnumFunc: ENUMRESLANGPROCW, lParam: LONG_PTR, dwFlags: DWORD, LangId: LANGID) -> BOOL --- + LookupIconIdFromDirectory :: proc(presbits: PBYTE, fIcon: BOOL) -> INT --- LookupIconIdFromDirectoryEx :: proc(presbits: PBYTE, fIcon: BOOL, cxDesired: INT, cyDesired: INT, Flags: UINT) -> INT --- - CreateIconFromResourceEx :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD, cxDesired: INT, cyDesired: INT, Flags: UINT) -> HICON --- + CreateIconFromResourceEx :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD, cxDesired: INT, cyDesired: INT, Flags: UINT) -> HICON --- GetFullPathNameW :: proc(filename: LPCWSTR, buffer_length: DWORD, buffer: LPCWSTR, file_part: ^LPCWSTR) -> DWORD --- GetLongPathNameW :: proc(short, long: LPCWSTR, len: DWORD) -> DWORD --- @@ -508,21 +567,22 @@ foreign kernel32 { CreatePipe :: proc(hReadPipe, hWritePipe: ^HANDLE, lpPipeAttributes: LPSECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL --- - ConnectNamedPipe :: proc(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL --- + ConnectNamedPipe :: proc(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL --- DisconnectNamedPipe :: proc(hNamedPipe: HANDLE) -> BOOL --- - WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL --- + WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL --- - AllocConsole :: proc() -> BOOL --- - AttachConsole :: proc(dwProcessId: DWORD) -> BOOL --- - SetConsoleCtrlHandler :: proc(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL --- - GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- - FreeConsole :: proc() -> BOOL --- - GetConsoleWindow :: proc() -> HWND --- - GetConsoleScreenBufferInfo :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO) -> BOOL --- - SetConsoleScreenBufferSize :: proc(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL --- - SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL --- - GetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- - SetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- + AllocConsole :: proc() -> BOOL --- + AttachConsole :: proc(dwProcessId: DWORD) -> BOOL --- + SetConsoleCtrlHandler :: proc(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL --- + GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- + FreeConsole :: proc() -> BOOL --- + GetConsoleWindow :: proc() -> HWND --- + GetConsoleScreenBufferInfo :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO) -> BOOL --- + GetConsoleScreenBufferInfoEx :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfoEx: PCONSOLE_SCREEN_BUFFER_INFOEX) -> BOOL --- + SetConsoleScreenBufferSize :: proc(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL --- + SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL --- + GetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- + SetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL --- GetDiskFreeSpaceExW :: proc( lpDirectoryName: LPCWSTR, @@ -536,19 +596,33 @@ foreign kernel32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setfilecompletionnotificationmodes) SetFileCompletionNotificationModes :: proc(FileHandle: HANDLE, Flags: u8) -> BOOL --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-createiocompletionport) - CreateIoCompletionPort :: proc(FileHandle: HANDLE, ExistingCompletionPort: HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) -> HANDLE --- + CreateIoCompletionPort :: proc(FileHandle: HANDLE, ExistingCompletionPort: HANDLE, CompletionKey: ULONG_PTR, NumberOfConcurrentThreads: DWORD) -> HANDLE --- //[MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getqueuedcompletionstatus) - GetQueuedCompletionStatus :: proc(CompletionPort: HANDLE, lpNumberOfBytesTransferred: ^DWORD, lpCompletionKey: PULONG_PTR, lpOverlapped: ^^OVERLAPPED, dwMilliseconds: DWORD) -> BOOL --- + GetQueuedCompletionStatus :: proc(CompletionPort: HANDLE, lpNumberOfBytesTransferred: ^DWORD, lpCompletionKey: PULONG_PTR, lpOverlapped: ^^OVERLAPPED, dwMilliseconds: DWORD) -> BOOL --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getqueuedcompletionstatusex) - GetQueuedCompletionStatusEx :: proc(CompletionPort: HANDLE, lpCompletionPortEntries: ^OVERLAPPED_ENTRY, ulCount: c_ulong, ulNumEntriesRemoved: ^c_ulong, dwMilliseconds: DWORD, fAlertable: BOOL) -> BOOL --- + GetQueuedCompletionStatusEx :: proc(CompletionPort: HANDLE, lpCompletionPortEntries: ^OVERLAPPED_ENTRY, ulCount: c_ulong, ulNumEntriesRemoved: ^c_ulong, dwMilliseconds: DWORD, fAlertable: BOOL) -> BOOL --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-postqueuedcompletionstatus) - PostQueuedCompletionStatus :: proc(CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: c_ulong, lpOverlapped: ^OVERLAPPED) -> BOOL --- + PostQueuedCompletionStatus :: proc(CompletionPort: HANDLE, dwNumberOfBytesTransferred: DWORD, dwCompletionKey: ULONG_PTR, lpOverlapped: ^OVERLAPPED) -> BOOL --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation) - GetHandleInformation :: proc(hObject: HANDLE, lpdwFlags: ^DWORD) -> BOOL --- + GetHandleInformation :: proc(hObject: HANDLE, lpdwFlags: ^DWORD) -> BOOL --- RtlCaptureStackBackTrace :: proc(FramesToSkip: ULONG, FramesToCapture: ULONG, BackTrace: [^]PVOID, BackTraceHash: PULONG) -> USHORT --- + RtlNtStatusToDosError :: proc(status: NTSTATUS) -> ULONG --- GetSystemPowerStatus :: proc(lpSystemPowerStatus: ^SYSTEM_POWER_STATUS) -> BOOL --- + + RegisterWaitForSingleObject :: proc( + phNewWaitObject: PHANDLE, + hObject: HANDLE, + Callback: WAITORTIMERCALLBACK, + Context: PVOID, + dwMilliseconds: ULONG, + dwFlags: ULONG, + ) -> BOOL --- + + UnregisterWaitEx :: proc(WaitHandle: HANDLE, CompletionEvent: HANDLE) -> BOOL --- + + QueueUserAPC :: proc(pfnAPC: PAPCFUNC, hThread: HANDLE, dwData: ULONG_PTR) -> DWORD --- } DEBUG_PROCESS :: 0x00000001 @@ -599,44 +673,44 @@ THREAD_PRIORITY_IDLE :: THREAD_BASE_PRIORITY_IDLE THREAD_MODE_BACKGROUND_BEGIN :: 0x00010000 THREAD_MODE_BACKGROUND_END :: 0x00020000 -PROCESS_ALL_ACCESS :: 0x000F0000 | SYNCHRONIZE | 0xFFFF -PROCESS_CREATE_PROCESS :: 0x0080 -PROCESS_CREATE_THREAD :: 0x0002 -PROCESS_DUP_HANDLE :: 0x0040 -PROCESS_QUERY_INFORMATION :: 0x0400 +PROCESS_ALL_ACCESS :: 0x000F0000 | SYNCHRONIZE | 0xFFFF +PROCESS_CREATE_PROCESS :: 0x0080 +PROCESS_CREATE_THREAD :: 0x0002 +PROCESS_DUP_HANDLE :: 0x0040 +PROCESS_QUERY_INFORMATION :: 0x0400 PROCESS_QUERY_LIMITED_INFORMATION :: 0x1000 -PROCESS_SET_INFORMATION :: 0x0200 -PROCESS_SET_QUOTA :: 0x0100 -PROCESS_SUSPEND_RESUME :: 0x0800 -PROCESS_TERMINATE :: 0x0001 -PROCESS_VM_OPERATION :: 0x0008 -PROCESS_VM_READ :: 0x0010 -PROCESS_VM_WRITE :: 0x0020 +PROCESS_SET_INFORMATION :: 0x0200 +PROCESS_SET_QUOTA :: 0x0100 +PROCESS_SUSPEND_RESUME :: 0x0800 +PROCESS_TERMINATE :: 0x0001 +PROCESS_VM_OPERATION :: 0x0008 +PROCESS_VM_READ :: 0x0010 +PROCESS_VM_WRITE :: 0x0020 THREAD_ALL_ACCESS :: \ - THREAD_DIRECT_IMPERSONATION | - THREAD_GET_CONTEXT | - THREAD_IMPERSONATE | - THREAD_QUERY_INFORMATION | + THREAD_DIRECT_IMPERSONATION | + THREAD_GET_CONTEXT | + THREAD_IMPERSONATE | + THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION | - THREAD_SET_CONTEXT | - THREAD_SET_INFORMATION | - THREAD_SET_LIMITED_INFORMATION | - THREAD_SET_THREAD_TOKEN | - THREAD_SUSPEND_RESUME | - THREAD_TERMINATE | + THREAD_SET_CONTEXT | + THREAD_SET_INFORMATION | + THREAD_SET_LIMITED_INFORMATION | + THREAD_SET_THREAD_TOKEN | + THREAD_SUSPEND_RESUME | + THREAD_TERMINATE | SYNCHRONIZE -THREAD_DIRECT_IMPERSONATION :: 0x0200 -THREAD_GET_CONTEXT :: 0x0008 -THREAD_IMPERSONATE :: 0x0100 -THREAD_QUERY_INFORMATION :: 0x0040 +THREAD_DIRECT_IMPERSONATION :: 0x0200 +THREAD_GET_CONTEXT :: 0x0008 +THREAD_IMPERSONATE :: 0x0100 +THREAD_QUERY_INFORMATION :: 0x0040 THREAD_QUERY_LIMITED_INFORMATION :: 0x0800 -THREAD_SET_CONTEXT :: 0x0010 -THREAD_SET_INFORMATION :: 0x0020 -THREAD_SET_LIMITED_INFORMATION :: 0x0400 -THREAD_SET_THREAD_TOKEN :: 0x0080 -THREAD_SUSPEND_RESUME :: 0x0002 -THREAD_TERMINATE :: 0x0001 +THREAD_SET_CONTEXT :: 0x0010 +THREAD_SET_INFORMATION :: 0x0020 +THREAD_SET_LIMITED_INFORMATION :: 0x0400 +THREAD_SET_THREAD_TOKEN :: 0x0080 +THREAD_SUSPEND_RESUME :: 0x0002 +THREAD_TERMINATE :: 0x0001 COPY_FILE_FAIL_IF_EXISTS :: 0x00000001 COPY_FILE_RESTARTABLE :: 0x00000002 @@ -674,6 +748,9 @@ FILE_MAP_RESERVE :: DWORD(0x80000000) FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000) FILE_MAP_LARGE_PAGES :: DWORD(0x20000000) +LOCKFILE_FAIL_IMMEDIATELY :: DWORD (0x00000001) +LOCKFILE_EXCLUSIVE_LOCK :: DWORD(0x00000002) + // Flags for `SetFileCompletionNotificationModes`. FILE_SKIP_COMPLETION_PORT_ON_SUCCESS :: 0x1 FILE_SKIP_SET_EVENT_ON_HANDLE :: 0x2 @@ -691,16 +768,16 @@ PAGE_NOCACHE :: 0x200 PAGE_WRITECOMBINE :: 0x400 MEMORY_BASIC_INFORMATION :: struct { - BaseAddress: PVOID, - AllocationBase: PVOID, + BaseAddress: PVOID, + AllocationBase: PVOID, AllocationProtect: DWORD, - PartitionId: WORD, - RegionSize: SIZE_T, - State: DWORD, - Protect: DWORD, - Type: DWORD, + PartitionId: WORD, + RegionSize: SIZE_T, + State: DWORD, + Protect: DWORD, + Type: DWORD, } -PMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION +PMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION LPMEMORY_BASIC_INFORMATION :: ^MEMORY_BASIC_INFORMATION MEM_COMMIT :: 0x1000 @@ -718,97 +795,97 @@ MEM_4MB_PAGES :: 0x80000000 @(default_calling_convention="system") foreign kernel32 { VirtualAlloc :: proc( - lpAddress: LPVOID, - dwSize: SIZE_T, + lpAddress: LPVOID, + dwSize: SIZE_T, flAllocationType: DWORD, - flProtect: DWORD, + flProtect: DWORD, ) -> LPVOID --- VirtualProtect :: proc( - lpAddress: LPVOID, - dwSize: SIZE_T, - flNewProtect: DWORD, + lpAddress: LPVOID, + dwSize: SIZE_T, + flNewProtect: DWORD, lpflOldProtect: PDWORD, ) -> BOOL --- VirtualFree :: proc( - lpAddress: LPVOID, - dwSize: SIZE_T, + lpAddress: LPVOID, + dwSize: SIZE_T, dwFreeType: DWORD, ) -> BOOL --- VirtualQuery :: proc( lpAddress: LPCVOID, - lpBuffer: PMEMORY_BASIC_INFORMATION, - dwLength: SIZE_T, + lpBuffer: PMEMORY_BASIC_INFORMATION, + dwLength: SIZE_T, ) -> SIZE_T --- VirtualAllocEx :: proc( - hProcess: HANDLE, - lpAddress: LPVOID, - dwSize: SIZE_T, + hProcess: HANDLE, + lpAddress: LPVOID, + dwSize: SIZE_T, flAllocationType: DWORD, - flProtect: DWORD, + flProtect: DWORD, ) -> LPVOID --- VirtualFreeEx :: proc( - hProcess: HANDLE, - lpAddress: LPVOID, - dwSize: SIZE_T, + hProcess: HANDLE, + lpAddress: LPVOID, + dwSize: SIZE_T, dwFreeType: DWORD, ) -> BOOL --- VirtualProtectEx :: proc( - hProcess: HANDLE, - lpAddress: LPVOID, - dwSize: SIZE_T, - flNewProtect: DWORD, + hProcess: HANDLE, + lpAddress: LPVOID, + dwSize: SIZE_T, + flNewProtect: DWORD, lpflOldProtect: PDWORD, ) -> BOOL --- VirtualQueryEx :: proc( - hProcess: HANDLE, + hProcess: HANDLE, lpAddress: LPCVOID, - lpBuffer: PMEMORY_BASIC_INFORMATION, - dwLength: SIZE_T, + lpBuffer: PMEMORY_BASIC_INFORMATION, + dwLength: SIZE_T, ) -> SIZE_T --- ReadProcessMemory :: proc( - hProcess: HANDLE, - lpBaseAddress: LPCVOID, - lpBuffer: LPVOID, - nSize: SIZE_T, + hProcess: HANDLE, + lpBaseAddress: LPCVOID, + lpBuffer: LPVOID, + nSize: SIZE_T, lpNumberOfBytesRead: ^SIZE_T, ) -> BOOL --- WriteProcessMemory :: proc( - hProcess: HANDLE, - lpBaseAddress: LPVOID, - lpBuffer: LPCVOID, - nSize: SIZE_T, + hProcess: HANDLE, + lpBaseAddress: LPVOID, + lpBuffer: LPCVOID, + nSize: SIZE_T, lpNumberOfBytesWritten: ^SIZE_T, ) -> BOOL --- CreateFileMappingW :: proc( - hFile: HANDLE, + hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, - flProtect: DWORD, - dwMaximumSizeHigh: DWORD, - dwMaximumSizeLow: DWORD, - lpName: LPCWSTR, + flProtect: DWORD, + dwMaximumSizeHigh: DWORD, + dwMaximumSizeLow: DWORD, + lpName: LPCWSTR, ) -> HANDLE --- OpenFileMappingW :: proc( dwDesiredAccess: DWORD, - bInheritHandle: BOOL, - lpName: LPCWSTR, + bInheritHandle: BOOL, + lpName: LPCWSTR, ) -> HANDLE --- MapViewOfFile :: proc( - hFileMappingObject: HANDLE, - dwDesiredAccess: DWORD, - dwFileOffsetHigh: DWORD, - dwFileOffsetLow: DWORD, + hFileMappingObject: HANDLE, + dwDesiredAccess: DWORD, + dwFileOffsetHigh: DWORD, + dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, ) -> LPVOID --- MapViewOfFileEx :: proc( - hFileMappingObject: HANDLE, - dwDesiredAccess: DWORD, - dwFileOffsetHigh: DWORD, - dwFileOffsetLow: DWORD, + hFileMappingObject: HANDLE, + dwDesiredAccess: DWORD, + dwFileOffsetHigh: DWORD, + dwFileOffsetLow: DWORD, dwNumberOfBytesToMap: SIZE_T, - lpBaseAddress: LPVOID, + lpBaseAddress: LPVOID, ) -> LPVOID --- FlushViewOfFile :: proc( - lpBaseAddress: LPCVOID, + lpBaseAddress: LPCVOID, dwNumberOfBytesToFlush: SIZE_T, ) -> BOOL --- UnmapViewOfFile :: proc( @@ -816,36 +893,36 @@ foreign kernel32 { ) -> BOOL --- GetLargePageMinimum :: proc() -> SIZE_T --- GetProcessWorkingSetSizeEx :: proc( - hProcess: HANDLE, + hProcess: HANDLE, lpMinimumWorkingSetSize: PSIZE_T, lpMaximumWorkingSetSize: PSIZE_T, - Flags: PDWORD, + Flags: PDWORD, ) -> BOOL --- SetProcessWorkingSetSizeEx :: proc( - hProcess: HANDLE, + hProcess: HANDLE, dwMinimumWorkingSetSize: SIZE_T, dwMaximumWorkingSetSize: SIZE_T, - Flags: DWORD, + Flags: DWORD, ) -> BOOL --- VirtualLock :: proc( lpAddress: LPVOID, - dwSize: SIZE_T, + dwSize: SIZE_T, ) -> BOOL --- VirtualUnlock :: proc( lpAddress: LPVOID, - dwSize: SIZE_T, + dwSize: SIZE_T, ) -> BOOL --- GetWriteWatch :: proc( - dwFlags: DWORD, - lpBaseAddress: PVOID, - dwRegionSize: SIZE_T, - lpAddresses: ^PVOID, - lpdwCount: ^ULONG_PTR, + dwFlags: DWORD, + lpBaseAddress: PVOID, + dwRegionSize: SIZE_T, + lpAddresses: ^PVOID, + lpdwCount: ^ULONG_PTR, lpdwGranularity: LPDWORD, ) -> UINT --- ResetWriteWatch :: proc( lpBaseAddress: LPVOID, - dwRegionSize: SIZE_T, + dwRegionSize: SIZE_T, ) -> UINT --- } @@ -857,7 +934,6 @@ MEMORY_RESOURCE_NOTIFICATION_TYPE :: enum c_int { LowMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.LowMemoryResourceNotification HighMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.HighMemoryResourceNotification - @(default_calling_convention="system") foreign kernel32 { CreateMemoryResourceNotification :: proc( @@ -879,27 +955,27 @@ foreign kernel32 { GetSystemFileCacheSize :: proc( lpMinimumFileCacheSize: PSIZE_T, lpMaximumFileCacheSize: PSIZE_T, - lpFlags: PDWORD, + lpFlags: PDWORD, ) -> BOOL --- SetSystemFileCacheSize :: proc( MinimumFileCacheSize: SIZE_T, MaximumFileCacheSize: SIZE_T, - Flags: DWORD, + Flags: DWORD, ) -> BOOL --- CreateFileMappingNumaW :: proc( - hFile: HANDLE, + hFile: HANDLE, lpFileMappingAttributes: LPSECURITY_ATTRIBUTES, - flProtect: DWORD, - dwMaximumSizeHigh: DWORD, - dwMaximumSizeLow: DWORD, - lpName: LPCWSTR, - nndPreferred: DWORD, + flProtect: DWORD, + dwMaximumSizeHigh: DWORD, + dwMaximumSizeLow: DWORD, + lpName: LPCWSTR, + nndPreferred: DWORD, ) -> HANDLE --- } WIN32_MEMORY_RANGE_ENTRY :: struct { VirtualAddress: PVOID, - NumberOfBytes: SIZE_T, + NumberOfBytes: SIZE_T, } PWIN32_MEMORY_RANGE_ENTRY :: ^WIN32_MEMORY_RANGE_ENTRY @@ -907,56 +983,56 @@ PWIN32_MEMORY_RANGE_ENTRY :: ^WIN32_MEMORY_RANGE_ENTRY @(default_calling_convention="system") foreign kernel32 { PrefetchVirtualMemory :: proc( - hProcess: HANDLE, - NumberOfEntries: ULONG_PTR, + hProcess: HANDLE, + NumberOfEntries: ULONG_PTR, VirtualAddresses: PWIN32_MEMORY_RANGE_ENTRY, - Flags: ULONG, + Flags: ULONG, ) -> BOOL --- CreateFileMappingFromApp :: proc( - hFile: HANDLE, + hFile: HANDLE, SecurityAttributes: PSECURITY_ATTRIBUTES, - PageProtection: ULONG, - MaximumSize: ULONG64, - Name: PCWSTR, + PageProtection: ULONG, + MaximumSize: ULONG64, + Name: PCWSTR, ) -> HANDLE --- MapViewOfFileFromApp :: proc( hFileMappingObject: HANDLE, - DesiredAccess: ULONG, - FileOffset: ULONG64, + DesiredAccess: ULONG, + FileOffset: ULONG64, NumberOfBytesToMap: SIZE_T, ) -> PVOID --- UnmapViewOfFileEx :: proc( BaseAddress: PVOID, - UnmapFlags: ULONG, + UnmapFlags: ULONG, ) -> BOOL --- AllocateUserPhysicalPages :: proc( - hProcess: HANDLE, + hProcess: HANDLE, NumberOfPages: PULONG_PTR, - PageArray: PULONG_PTR, + PageArray: PULONG_PTR, ) -> BOOL --- FreeUserPhysicalPages :: proc( - hProcess: HANDLE, + hProcess: HANDLE, NumberOfPages: PULONG_PTR, - PageArray: PULONG_PTR, + PageArray: PULONG_PTR, ) -> BOOL --- MapUserPhysicalPages :: proc( VirtualAddress: PVOID, - NumberOfPages: ULONG_PTR, - PageArray: PULONG_PTR, + NumberOfPages: ULONG_PTR, + PageArray: PULONG_PTR, ) -> BOOL --- AllocateUserPhysicalPagesNuma :: proc( - hProcess: HANDLE, + hProcess: HANDLE, NumberOfPages: PULONG_PTR, - PageArray: PULONG_PTR, - nndPreferred: DWORD, + PageArray: PULONG_PTR, + nndPreferred: DWORD, ) -> BOOL --- VirtualAllocExNuma :: proc( - hProcess: HANDLE, - lpAddress: LPVOID, - dwSize: SIZE_T, + hProcess: HANDLE, + lpAddress: LPVOID, + dwSize: SIZE_T, flAllocationType: DWORD, - flProtect: DWORD, - nndPreferred: DWORD, + flProtect: DWORD, + nndPreferred: DWORD, ) -> LPVOID --- } @@ -964,28 +1040,20 @@ MEHC_PATROL_SCRUBBER_PRESENT :: ULONG(0x1) @(default_calling_convention="system") foreign kernel32 { - GetMemoryErrorHandlingCapabilities :: proc( - Capabilities: PULONG, - ) -> BOOL --- + GetMemoryErrorHandlingCapabilities :: proc(Capabilities: PULONG) -> BOOL --- } @(default_calling_convention="system") foreign kernel32 { - GlobalMemoryStatusEx :: proc( - lpBuffer: ^MEMORYSTATUSEX, - ) -> BOOL --- + GlobalMemoryStatusEx :: proc(lpBuffer: ^MEMORYSTATUSEX) -> BOOL --- } PBAD_MEMORY_CALLBACK_ROUTINE :: #type proc "system" () @(default_calling_convention="system") foreign kernel32 { - RegisterBadMemoryNotification :: proc( - Callback: PBAD_MEMORY_CALLBACK_ROUTINE, - ) -> PVOID --- - UnregisterBadMemoryNotification :: proc( - RegistrationHandle: PVOID, - ) -> BOOL --- + RegisterBadMemoryNotification :: proc(Callback: PBAD_MEMORY_CALLBACK_ROUTINE) -> PVOID --- + UnregisterBadMemoryNotification :: proc(RegistrationHandle: PVOID) -> BOOL --- } OFFER_PRIORITY :: enum c_int { @@ -1003,33 +1071,33 @@ VmOfferPriorityNormal :: OFFER_PRIORITY.VmOfferPriorityNormal foreign kernel32 { OfferVirtualMemory :: proc( VirtualAddress: PVOID, - Size: SIZE_T, - Priority: OFFER_PRIORITY, + Size: SIZE_T, + Priority: OFFER_PRIORITY, ) -> DWORD --- ReclaimVirtualMemory :: proc( VirtualAddress: PVOID, - Size: SIZE_T, + Size: SIZE_T, ) -> DWORD --- DiscardVirtualMemory :: proc( VirtualAddress: PVOID, - Size: SIZE_T, + Size: SIZE_T, ) -> DWORD --- VirtualAllocFromApp :: proc( - BaseAddress: PVOID, - Size: SIZE_T, + BaseAddress: PVOID, + Size: SIZE_T, AllocationType: ULONG, - Protection: ULONG, + Protection: ULONG, ) -> PVOID --- VirtualProtectFromApp :: proc( - Address: PVOID, - Size: SIZE_T, + Address: PVOID, + Size: SIZE_T, NewProtection: ULONG, OldProtection: PULONG, ) -> BOOL --- OpenFileMappingFromApp :: proc( DesiredAccess: ULONG, InheritHandle: BOOL, - Name: PCWSTR, + Name: PCWSTR, ) -> HANDLE --- } @@ -1039,54 +1107,48 @@ WIN32_MEMORY_INFORMATION_CLASS :: enum c_int { MemoryRegionInfo :: WIN32_MEMORY_INFORMATION_CLASS.MemoryRegionInfo WIN32_MEMORY_REGION_INFORMATION :: struct { - AllocationBase: PVOID, + AllocationBase: PVOID, AllocationProtect: ULONG, - u: WIN32_MEMORY_REGION_INFORMATION_u, + using DUMMYUNIONNAME: struct #raw_union { + _: [1]u32, + Flags: ULONG, + using DUMMYSTRUCTNAME: bit_field ULONG { + Private: ULONG | 1, + MappedDataFile: ULONG | 1, + MappedImage: ULONG | 1, + MappedPageFile: ULONG | 1, + MappedPhysical: ULONG | 1, + DirectMapped: ULONG | 1, + Reserved: ULONG | 26, + }, + }, RegionSize: SIZE_T, CommitSize: SIZE_T, } -WIN32_MEMORY_REGION_INFORMATION_u :: struct #raw_union { - u: [1]u32, - Flags: ULONG, - s: WIN32_MEMORY_REGION_INFORMATION_u_s, -} -WIN32_MEMORY_REGION_INFORMATION_u_s :: struct { - Bitfield: ULONG, -} -WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG -/*bit_field #align(align_of(ULONG)) { - Private : 1-0, - MappedDataFile : 2-1, - MappedImage : 3-2, - MappedPageFile : 4-3, - MappedPhysical : 5-4, - DirectMapped : 6-5, - Reserved : 32-6, -}*/ @(default_calling_convention="system") foreign one_core { QueryVirtualMemoryInformation :: proc( - Process: HANDLE, - VirtualAddress: PVOID, + Process: HANDLE, + VirtualAddress: PVOID, MemoryInformationClass: WIN32_MEMORY_INFORMATION_CLASS, - MemoryInformation: PVOID, - MemoryInformationSize: SIZE_T, - ReturnSize: PSIZE_T, + MemoryInformation: PVOID, + MemoryInformationSize: SIZE_T, + ReturnSize: PSIZE_T, ) -> BOOL --- MapViewOfFileNuma2 :: proc( FileMappingHandle: HANDLE, - ProcessHandle: HANDLE, - Offset: ULONG64, - BaseAddress: PVOID, - ViewSize: SIZE_T, - AllocationType: ULONG, - PageProtection: ULONG, - PreferredNode: ULONG, + ProcessHandle: HANDLE, + Offset: ULONG64, + BaseAddress: PVOID, + ViewSize: SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, + PreferredNode: ULONG, ) -> PVOID --- GetCommPorts :: proc( - lpPortNumbers: PULONG, - uPortNumbersCount: ULONG, + lpPortNumbers: PULONG, + uPortNumbersCount: ULONG, puPortNumbersFound: PULONG, ) -> ULONG --- } @@ -1096,12 +1158,12 @@ NUMA_NO_PREFERRED_NODE :: 0xffffffff MapViewOfFile2 :: #force_inline proc "system" ( FileMappingHandle: HANDLE, - ProcessHandle: HANDLE, - Offset: ULONG64, - BaseAddress: PVOID, - ViewSize: SIZE_T, - AllocationType: ULONG, - PageProtection: ULONG, + ProcessHandle: HANDLE, + Offset: ULONG64, + BaseAddress: PVOID, + ViewSize: SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, ) -> PVOID { return MapViewOfFileNuma2( FileMappingHandle, @@ -1119,8 +1181,8 @@ MapViewOfFile2 :: #force_inline proc "system" ( foreign kernel32 { UnmapViewOfFile2 :: proc( ProcessHandle: HANDLE, - BaseAddress: PVOID, - UnmapFlags: ULONG, + BaseAddress: PVOID, + UnmapFlags: ULONG, ) -> BOOL --- } @@ -1131,10 +1193,83 @@ foreign kernel32 { OSMinorVersion: DWORD, SpMajorVersion: DWORD, SpMinorVersion: DWORD, - product_type: ^Windows_Product_Type, + product_type: ^Windows_Product_Type, ) -> BOOL --- } + +MEM_REPLACE_PLACEHOLDER :: 0x00004000 +MEM_RESERVE_PLACEHOLDER :: 0x00040000 +MEM_PRESERVE_PLACEHOLDER :: 0x00000002 +MEM_RESET_UNDO :: 0x1000000 +MEM_64K_PAGES :: 0x20400000 +MEM_PHYSICAL :: 0x00400000 + +MEM_EXTENDED_PARAMETER_TYPE :: enum c_int { + MemExtendedParameterInvalidType = 0, + MemExtendedParameterAddressRequirements, + MemExtendedParameterNumaNode, + MemExtendedParameterPartitionHandle, + MemExtendedParameterUserPhysicalHandle, + MemExtendedParameterAttributeFlags, + MemExtendedParameterImageMachine, +} + +MEM_EXTENDED_PARAMETER_NONPAGED :: 0x02 +MEM_EXTENDED_PARAMETER_NONPAGED_LARGE :: 0x08 +MEM_EXTENDED_PARAMETER_NONPAGED_HUGE :: 0x10 +MEM_EXTENDED_PARAMETER_EC_CODE :: 0x40 + +MEM_ADDRESS_REQUIREMENTS :: struct { + LowestStartingAddress: PVOID, + HighestEndingAddress: PVOID, + Alignment: SIZE_T, +} +PMEM_ADDRESS_REQUIREMENTS :: ^MEM_ADDRESS_REQUIREMENTS + +MEM_EXTENDED_PARAMETER_TYPE_BITS :: 8 + +MEM_EXTENDED_PARAMETER :: struct { + using DUMMYSTRUCTNAME: bit_field DWORD64 { + Type: MEM_EXTENDED_PARAMETER_TYPE | MEM_EXTENDED_PARAMETER_TYPE_BITS, + Reserved: DWORD64 | 64 - MEM_EXTENDED_PARAMETER_TYPE_BITS, + }, + using DUMMYUNIONNAME: struct #raw_union { + ULong64: DWORD64, + Pointer: PVOID, + Size: SIZE_T, + Handle: HANDLE, + ULong: DWORD, + }, +} + + +@(default_calling_convention="system") +foreign one_core { + VirtualAlloc2 :: proc( + Process: HANDLE, + BaseAddress: LPVOID, + Size: SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, + ExtendedParameters: ^MEM_EXTENDED_PARAMETER, + ParameterCount: ULONG, + ) -> LPVOID --- + + MapViewOfFile3 :: proc( + FileMappingHandle: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: PVOID, + Offset: ULONG64, + ViewSize: SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, + ExtendedParameters: ^MEM_EXTENDED_PARAMETER, + ParameterCount: ULONG, + ) -> PVOID --- +} + + HandlerRoutine :: proc "system" (dwCtrlType: DWORD) -> BOOL PHANDLER_ROUTINE :: HandlerRoutine @@ -1145,10 +1280,10 @@ LPFIBER_START_ROUTINE :: #type proc "system" (lpFiberParameter: LPVOID) @(default_calling_convention = "system") foreign kernel32 { - CreateFiber :: proc(dwStackSize: SIZE_T, lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID) -> LPVOID --- - DeleteFiber :: proc(lpFiber: LPVOID) --- + CreateFiber :: proc(dwStackSize: SIZE_T, lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID) -> LPVOID --- + DeleteFiber :: proc(lpFiber: LPVOID) --- ConvertThreadToFiber :: proc(lpParameter: LPVOID) -> LPVOID --- - SwitchToFiber :: proc(lpFiber: LPVOID) --- + SwitchToFiber :: proc(lpFiber: LPVOID) --- } LOGICAL_PROCESSOR_RELATIONSHIP :: enum c_int { @@ -1171,11 +1306,11 @@ PROCESSOR_CACHE_TYPE :: enum c_int { } CACHE_DESCRIPTOR :: struct { - Level: BYTE, + Level: BYTE, Associativity: BYTE, - LineSize: WORD, - Size: DWORD, - Type: PROCESSOR_CACHE_TYPE, + LineSize: WORD, + Size: DWORD, + Type: PROCESSOR_CACHE_TYPE, } ProcessorCore :: struct { @@ -1184,17 +1319,16 @@ ProcessorCore :: struct { NumaNode :: struct { NodeNumber: DWORD, } -DUMMYUNIONNAME_u :: struct #raw_union { - Core: ProcessorCore, - Node: NumaNode, - Cache: CACHE_DESCRIPTOR, - Reserved: [2]ULONGLONG, -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct { ProcessorMask: ULONG_PTR, - Relationship: LOGICAL_PROCESSOR_RELATIONSHIP, - DummyUnion: DUMMYUNIONNAME_u, + Relationship: LOGICAL_PROCESSOR_RELATIONSHIP, + using DUMMYUNIONNAME: struct #raw_union { + ProcessorCore: ProcessorCore `raw_union_tag:"Relationship=RelationProcessorCore"`, + NumaNode: NumaNode `raw_union_tag:"Relationship=RelationNumaNode"`, + Cache: CACHE_DESCRIPTOR `raw_union_tag:"Relationship=RelationCache"`, + Reserved: [2]ULONGLONG, + }, } SYSTEM_POWER_STATUS :: struct { @@ -1266,6 +1400,6 @@ ACTCTX_FLAG_HMODULE_VALID :: 0x080 @(default_calling_convention="system") foreign kernel32 { - CreateActCtxW :: proc(pActCtx: ^ACTCTXW) -> HANDLE --- + CreateActCtxW :: proc(pActCtx: ^ACTCTXW) -> HANDLE --- ActivateActCtx :: proc(hActCtx: HANDLE, lpCookie: ^ULONG_PTR) -> BOOL --- } diff --git a/core/sys/windows/key_codes.odin b/core/sys/windows/key_codes.odin index 0991ca4b3..a2910ecd1 100644 --- a/core/sys/windows/key_codes.odin +++ b/core/sys/windows/key_codes.odin @@ -3,11 +3,11 @@ package sys_windows // https://docs.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input KF_EXTENDED :: 0x0100 -KF_DLGMODE :: 0x0800 +KF_DLGMODE :: 0x0800 KF_MENUMODE :: 0x1000 -KF_ALTDOWN :: 0x2000 -KF_REPEAT :: 0x4000 -KF_UP :: 0x8000 +KF_ALTDOWN :: 0x2000 +KF_REPEAT :: 0x4000 +KF_UP :: 0x8000 // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes // Virtual Keys, Standard Set diff --git a/core/sys/windows/mswsock.odin b/core/sys/windows/mswsock.odin new file mode 100644 index 000000000..9019fc821 --- /dev/null +++ b/core/sys/windows/mswsock.odin @@ -0,0 +1,40 @@ +#+build windows +package sys_windows + +foreign import mswsock "system:mswsock.lib" + +foreign mswsock { + TransmitFile :: proc( + hSocket: SOCKET, + hFile: HANDLE, + nNumberOfBytesToWrite: DWORD, + nNumberOfBytesPerSend: DWORD, + lpOverlapped: LPOVERLAPPED, + lpTransmitBuffers: rawptr, + dwReserved: DWORD, + ) -> BOOL --- + + AcceptEx :: proc( + sListenSocket: SOCKET, + sAcceptSocket: SOCKET, + lpOutputBuffer: PVOID, + dwReceiveDataLength: DWORD, + dwLocalAddressLength: DWORD, + dwRemoteAddressLength: DWORD, + lpdwBytesReceived: LPDWORD, + lpOverlapped: LPOVERLAPPED, + ) -> BOOL --- + + GetAcceptExSockaddrs :: proc( + lpOutputBuffer: PVOID, + dwReceiveDataLength: DWORD, + dwLocalAddressLength: DWORD, + dwRemoteAddressLength: DWORD, + LocalSockaddr: ^^sockaddr, + LocalSockaddrLength: LPINT, + RemoteSockaddr: ^^sockaddr, + RemoteSockaddrLength: LPINT, + ) --- +} + +SO_UPDATE_CONNECT_CONTEXT :: 0x7010 \ No newline at end of file diff --git a/core/sys/windows/netapi32.odin b/core/sys/windows/netapi32.odin index 9442193ca..759c5847a 100644 --- a/core/sys/windows/netapi32.odin +++ b/core/sys/windows/netapi32.odin @@ -7,32 +7,32 @@ foreign import netapi32 "system:Netapi32.lib" foreign netapi32 { NetUserAdd :: proc( servername: wstring, - level: DWORD, - user_info: ^USER_INFO_1, // Perhaps make this a #raw_union with USER_INFO1..4 when we need the other levels. - parm_err: ^DWORD, + level: DWORD, + user_info: ^USER_INFO_1, // Perhaps make this a #raw_union with USER_INFO1..4 when we need the other levels. + parm_err: ^DWORD, ) -> NET_API_STATUS --- NetUserDel :: proc( servername: wstring, - username: wstring, + username: wstring, ) -> NET_API_STATUS --- NetUserGetInfo :: proc( servername: wstring, - username: wstring, - level: DWORD, - user_info: ^USER_INFO_1, + username: wstring, + level: DWORD, + user_info: ^USER_INFO_1, ) -> NET_API_STATUS --- NetLocalGroupAddMembers :: proc( - servername: wstring, - groupname: wstring, - level: DWORD, + servername: wstring, + groupname: wstring, + level: DWORD, group_members_info: ^LOCALGROUP_MEMBERS_INFO_0, // Actually a variably sized array of these. - totalentries: DWORD, + totalentries: DWORD, ) -> NET_API_STATUS --- NetLocalGroupDelMembers :: proc( - servername: wstring, - groupname: wstring, - level: DWORD, + servername: wstring, + groupname: wstring, + level: DWORD, group_members_info: ^LOCALGROUP_MEMBERS_INFO_0, // Actually a variably sized array of these. - totalentries: DWORD, + totalentries: DWORD, ) -> NET_API_STATUS --- } \ No newline at end of file diff --git a/core/sys/windows/ntdll.odin b/core/sys/windows/ntdll.odin index 747130749..41deaa1c4 100644 --- a/core/sys/windows/ntdll.odin +++ b/core/sys/windows/ntdll.odin @@ -36,6 +36,36 @@ foreign ntdll_lib { QueryFlags: ULONG, FileName : PUNICODE_STRING, ) -> NTSTATUS --- + + NtCreateFile :: proc( + FileHandle: PHANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: POBJECT_ATTRIBUTES, + IoStatusBlock: PIO_STATUS_BLOCK, + AllocationSize: PLARGE_INTEGER, + FileAttributes: ULONG, + ShareAccess: ULONG, + CreateDisposition: ULONG, + CreateOptions: ULONG, + EaBuffer: PVOID, + EaLength: ULONG, + ) -> NTSTATUS --- + + + NtAssociateWaitCompletionPacket :: proc( + WaitCompletionPacketHandle: HANDLE, + IoCompletionHandle: HANDLE, + TargetObjectHandle: HANDLE, + KeyContext: PVOID, + ApcContext: PVOID, + IoStatus: NTSTATUS, + IoStatusInformation: ULONG_PTR, + AlreadySignaled: ^BOOLEAN, + ) -> NTSTATUS --- + + NtDelayExecution :: proc(Alertable: BOOL, DelayInterval: PLARGE_INTEGER) -> NTSTATUS --- + + ZwSetTimerResolution :: proc(RequestedResolution: ULONG, Set: BOOLEAN, ActualResolution: PULONG) -> NTSTATUS --- } @@ -256,4 +286,13 @@ RTL_DRIVE_LETTER_CURDIR :: struct { LIST_ENTRY :: struct { Flink: ^LIST_ENTRY, Blink: ^LIST_ENTRY, -} \ No newline at end of file +} + +FILE_SUPERSEDE :: 0x00000000 +FILE_OPEN :: 0x00000001 +FILE_CREATE :: 0x00000002 +FILE_OPEN_IF :: 0x00000003 +FILE_OVERWRITE :: 0x00000004 +FILE_OVERWRITE_IF :: 0x00000005 + +FILE_NON_DIRECTORY_FILE :: 0x00000040 diff --git a/core/sys/windows/ntioring_x.odin b/core/sys/windows/ntioring_x.odin new file mode 100644 index 000000000..18626069b --- /dev/null +++ b/core/sys/windows/ntioring_x.odin @@ -0,0 +1,42 @@ +#+build windows +package sys_windows + + +IORING_SUBMIT_WAIT_ALL :: max(u32) + +IORING_VERSION :: enum i32 { + INVALID, + _1, + _2, + _3 = 300, + _4 = 400, +} + +IORING_FEATURE_FLAG :: enum u32 { + UM_EMULATION = 0, // 0x00000001 + SET_COMPLETION_EVENT = 1, // 0x00000002 +} + +IORING_FEATURE_FLAGS :: bit_set[IORING_FEATURE_FLAG; u32] + +IORING_OP_CODE :: enum i32 { + NOP, + READ, + REGISTER_FILES, + REGISTER_BUFFERS, + CANCEL, + WRITE, + FLUSH, + READ_SCATTER, + WRITE_GATHER, +} + +IORING_BUFFER_INFO :: struct { + Address: rawptr, + Length: u32, +} + +IORING_REGISTERED_BUFFER :: struct { + BufferIndex: u32, + Offset: u32, +} diff --git a/core/sys/windows/ole32.odin b/core/sys/windows/ole32.odin index 8535a6f87..f93ecc820 100644 --- a/core/sys/windows/ole32.odin +++ b/core/sys/windows/ole32.odin @@ -1,6 +1,8 @@ package sys_windows -foreign import "system:Ole32.lib" +// Don't add a `#+build windows` guard to this file. It's used for `dxgi` on non-Windows platforms, for example. + +foreign import Ole32 "system:Ole32.lib" //objbase.h // Note(Dragos): https://learn.microsoft.com/en-us/windows/win32/api/objbase/ne-objbase-coinit makes you believe that MULTITHREADED == 3. That is wrong. See definition of objbase.h @@ -25,11 +27,12 @@ COINIT :: enum DWORD { SPEED_OVER_MEMORY = 0x8, } +IUnknown_UUID_STRING :: "00000000-0000-0000-C000-000000000046" +IUnknown_UUID := &IID{0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} +IUnknownVtbl :: IUnknown_VTable IUnknown :: struct { using _iunknown_vtable: ^IUnknown_VTable, } - -IUnknownVtbl :: IUnknown_VTable IUnknown_VTable :: struct { QueryInterface: proc "system" (This: ^IUnknown, riid: REFIID, ppvObject: ^rawptr) -> HRESULT, AddRef: proc "system" (This: ^IUnknown) -> ULONG, @@ -40,30 +43,32 @@ LPUNKNOWN :: ^IUnknown @(default_calling_convention="system") foreign Ole32 { - CoInitialize :: proc(reserved: rawptr = nil) -> HRESULT --- + CoInitialize :: proc(reserved: rawptr = nil) -> HRESULT --- CoInitializeEx :: proc(reserved: rawptr = nil, co_init: COINIT = .APARTMENTTHREADED) -> HRESULT --- CoUninitialize :: proc() --- CoCreateInstance :: proc( - rclsid: REFCLSID, - pUnkOuter: LPUNKNOWN, + rclsid: REFCLSID, + pUnkOuter: LPUNKNOWN, dwClsContext: DWORD, - riid: REFIID, - ppv: ^LPVOID, + riid: REFIID, + ppv: ^LPVOID, ) -> HRESULT --- - CoTaskMemFree :: proc(pv: rawptr) --- + CoTaskMemAlloc :: proc(cb: SIZE_T) -> rawptr --- + CoTaskMemRealloc :: proc(pv: rawptr, cb: SIZE_T) -> rawptr --- + CoTaskMemFree :: proc(pv: rawptr) --- - CLSIDFromProgID :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- - CLSIDFromProgIDEx :: proc(lpszProgID, LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- - CLSIDFromString :: proc(lpsz: LPOLESTR, pclsid: LPCLSID) -> HRESULT --- - IIDFromString :: proc(lpsz: LPOLESTR, lpiid: LPIID) -> HRESULT --- - ProgIDFromCLSID :: proc(clsid: REFCLSID, lplpszProgID: ^LPOLESTR) -> HRESULT --- - StringFromCLSID :: proc(rclsid: REFCLSID, lplpsz: ^LPOLESTR) -> HRESULT --- - StringFromGUID2 :: proc(rclsid: REFCLSID, lplpsz: LPOLESTR, cchMax: INT) -> INT --- - StringFromIID :: proc(rclsid: REFIID, lplpsz: ^LPOLESTR) -> HRESULT --- + CLSIDFromProgID :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- + CLSIDFromProgIDEx :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- + CLSIDFromString :: proc(lpsz: LPOLESTR, pclsid: LPCLSID) -> HRESULT --- + IIDFromString :: proc(lpsz: LPOLESTR, lpiid: LPIID) -> HRESULT --- + ProgIDFromCLSID :: proc(clsid: REFCLSID, lplpszProgID: ^LPOLESTR) -> HRESULT --- + StringFromCLSID :: proc(rclsid: REFCLSID, lplpsz: ^LPOLESTR) -> HRESULT --- + StringFromGUID2 :: proc(rclsid: REFCLSID, lplpsz: LPOLESTR, cchMax: INT) -> INT --- + StringFromIID :: proc(rclsid: REFIID, lplpsz: ^LPOLESTR) -> HRESULT --- - PropVariantClear :: proc(pvar: ^PROPVARIANT) -> HRESULT --- - PropVariantCopy :: proc(pvarDest: ^PROPVARIANT, pvarSrc: ^PROPVARIANT) -> HRESULT --- + PropVariantClear :: proc(pvar: ^PROPVARIANT) -> HRESULT --- + PropVariantCopy :: proc(pvarDest: ^PROPVARIANT, pvarSrc: ^PROPVARIANT) -> HRESULT --- FreePropVariantArray :: proc(cVariants: ULONG, rgvars: ^PROPVARIANT) -> HRESULT --- } diff --git a/core/sys/windows/psapi.odin b/core/sys/windows/psapi.odin new file mode 100644 index 000000000..3345ced1b --- /dev/null +++ b/core/sys/windows/psapi.odin @@ -0,0 +1,9 @@ +#+build windows +package sys_windows + +foreign import psapi "system:Psapi.lib" + +@(default_calling_convention="system") +foreign psapi { + EnumProcessModules :: proc(hProcess: HANDLE, lphModule: ^HMODULE, cb: DWORD, lpcbNeeded: LPDWORD) -> BOOL --- +} \ No newline at end of file diff --git a/core/sys/windows/scan_codes.odin b/core/sys/windows/scan_codes.odin new file mode 100644 index 000000000..54949c2f6 --- /dev/null +++ b/core/sys/windows/scan_codes.odin @@ -0,0 +1,172 @@ +#+build windows +package sys_windows + +// Win32 scan codes for QWERTY layout +// https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input#scan-codes + +KB_SYS_POWERDOWN :: 0xE05E +KB_SYS_SLEEP :: 0xE05F +KB_SYS_WAKEUP :: 0xE063 +KB_ERR_ROLLOVER :: 0x00FF + +KB_A :: 0x001E +KB_B :: 0x0030 +KB_C :: 0x002E +KB_D :: 0x0020 +KB_E :: 0x0012 +KB_F :: 0x0021 +KB_G :: 0x0022 +KB_H :: 0x0023 +KB_I :: 0x0017 +KB_J :: 0x0024 +KB_K :: 0x0025 +KB_L :: 0x0026 +KB_M :: 0x0032 +KB_N :: 0x0031 +KB_O :: 0x0018 +KB_P :: 0x0019 +KB_Q :: 0x0010 +KB_R :: 0x0013 +KB_S :: 0x001F +KB_T :: 0x0014 +KB_U :: 0x0016 +KB_V :: 0x002F +KB_W :: 0x0011 +KB_X :: 0x002D +KB_Y :: 0x0015 +KB_Z :: 0x002C + +KB_1_BANG :: 0x0002 +KB_2_AT :: 0x0003 +KB_3_HASH :: 0x0004 +KB_4_DOLLAR :: 0x0005 +KB_5_PERCENT :: 0x0006 +KB_6_CARET :: 0x0007 +KB_7_AMPERSAND :: 0x0008 +KB_8_STAR :: 0x0009 +KB_9_LEFTBRACKET :: 0x000A +KB_0_RIGHTBRACKET :: 0x000B + +KB_RETURN_ENTER :: 0x001C +KB_ESCAPE :: 0x0001 +KB_DELETE :: 0x000E +KB_TAB :: 0x000F +KB_SPACEBAR :: 0x0039 +KB_DASH_UNDERSCORE :: 0x000C +KB_EQUALS_PLUS :: 0x000D +KB_LEFTBRACE :: 0x001A +KB_RIGHTBRACE :: 0x001B +KB_PIPE_SLASH :: 0x002B +KB_NONUS :: 0x002B +KB_SEMICOLON_COLON :: 0x0027 +KB_APOSTR_DOUBLEQUOT :: 0x0028 +KB_GRAVEACC_TILDE :: 0x0029 +KB_COMMA :: 0x0033 +KB_PERIOD :: 0x0034 +KB_QUESTIONMARK :: 0x0035 +KB_CAPSLOCK :: 0x003A + +KB_F1 :: 0x003B +KB_F2 :: 0x003C +KB_F3 :: 0x003D +KB_F4 :: 0x003E +KB_F5 :: 0x003F +KB_F6 :: 0x0040 +KB_F7 :: 0x0041 +KB_F8 :: 0x0042 +KB_F9 :: 0x0043 +KB_F10 :: 0x0044 +KB_F11 :: 0x0057 +KB_F12 :: 0x0058 + +KB_PRINTSCREEN :: 0xE037 +KB_SCROLLLOCK :: 0x0046 +KB_PAUSE :: 0xE11D45 +KB_INSERT :: 0xE052 +KB_HOME :: 0xE047 +KB_PAGEUP :: 0xE049 +KB_DELETEFORWARD :: 0xE053 +KB_END :: 0xE04F +KB_PAGEDOWN :: 0xE051 +KB_RIGHTARROW :: 0xE04D +KB_LEFTARROW :: 0xE04B +KB_DOWNARROW :: 0xE050 +KB_UPARROW :: 0xE048 + +KP_NUMLOCK_CLEAR :: 0x0045 +KP_FORWARDSLASH :: 0xE035 +KP_STAR :: 0x0037 +KP_DASH :: 0x004A +KP_PLUS :: 0x004E +KP_ENTER :: 0xE01C +KP_1_END :: 0x004F +KP_2_DOWNARROW :: 0x0050 +KP_3_PAGEDN :: 0x0051 +KP_4_LEFTARROW :: 0x004B +KP_5 :: 0x004C +KP_6_RIGHTARROW :: 0x004D +KP_7_HOME :: 0x0047 +KP_8_UPARROW :: 0x0048 +KP_9_PAGEUP :: 0x0049 +KP_0_INSERT :: 0x0052 +KP_PERIOD :: 0x0053 + +KB_NONUS_SLASHBAR :: 0x0056 +KB_APPLICATION :: 0xE05D +KB_POWER :: 0xE05E +KB_EQUALS :: 0x0059 +KB_F13 :: 0x0064 +KB_F14 :: 0x0065 +KB_F15 :: 0x0066 +KB_F16 :: 0x0067 +KB_F17 :: 0x0068 +KB_F18 :: 0x0069 +KB_F19 :: 0x006A +KB_F20 :: 0x006B +KB_F21 :: 0x006C +KB_F22 :: 0x006D +KB_F23 :: 0x006E +KB_F24 :: 0x0076 + +KP_COMMA :: 0x007E + +KB_INTERNATIONAL1 :: 0x0073 +KB_INTERNATIONAL2 :: 0x0070 +KB_INTERNATIONAL3 :: 0x007D +KB_INTERNATIONAL4 :: 0x0079 +KB_INTERNATIONAL5 :: 0x007B +KB_INTERNATIONAL6 :: 0x005C + +KB_LANG1 :: 0x0072 +KB_LANG2 :: 0x0071 +KB_LANG3 :: 0x0078 +KB_LANG4 :: 0x0077 +KB_LANG5 :: 0x0076 + +KB_LEFTCONTROL :: 0x001D +KB_LEFTSHIFT :: 0x002A +KB_LEFTALT :: 0x0038 +KB_LEFTGUI :: 0xE05B +KB_RIGHTCONTROL :: 0xE01D +KB_RIGHTSHIFT :: 0x0036 +KB_RIGHTALT :: 0xE038 +KB_RIGHTGUI :: 0xE05C + +FN_SCANNEXTTRACK :: 0xE019 +FN_SCANPREVTRACK :: 0xE010 +FN_STOP :: 0xE024 +FN_PLAY_PAUSE :: 0xE022 +FN_MUTE :: 0xE020 +FN_VOLUMEINC :: 0xE030 +FN_VOLUMEDEC :: 0xE02E +FN_AL_CONSUMERCTRLCONFIG :: 0xE06D +FN_AL_EMAILREADER :: 0xE06C +FN_AL_CALCULATOR :: 0xE021 +FN_AL_LOCALMACHINEBROWSER :: 0xE06B +FN_AC_SEARCH :: 0xE065 +FN_AC_HOME :: 0xE032 +FN_AC_BACK :: 0xE06A +FN_AC_FORWARD :: 0xE069 +FN_AC_STOP :: 0xE068 +FN_AC_REFRESH :: 0xE067 +FN_AC_BOOKMARKS :: 0xE066 diff --git a/core/sys/windows/shcore.odin b/core/sys/windows/shcore.odin index 08a76ebe6..c7d784fe8 100644 --- a/core/sys/windows/shcore.odin +++ b/core/sys/windows/shcore.odin @@ -8,18 +8,18 @@ foreign import shcore "system:Shcore.lib" foreign shcore { GetProcessDpiAwareness :: proc(hprocess: HANDLE, value: ^PROCESS_DPI_AWARENESS) -> HRESULT --- SetProcessDpiAwareness :: proc(value: PROCESS_DPI_AWARENESS) -> HRESULT --- - GetDpiForMonitor :: proc(hmonitor: HMONITOR, dpiType: MONITOR_DPI_TYPE, dpiX: ^UINT, dpiY: ^UINT) -> HRESULT --- + GetDpiForMonitor :: proc(hmonitor: HMONITOR, dpiType: MONITOR_DPI_TYPE, dpiX: ^UINT, dpiY: ^UINT) -> HRESULT --- } PROCESS_DPI_AWARENESS :: enum DWORD { - PROCESS_DPI_UNAWARE = 0, - PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2, } MONITOR_DPI_TYPE :: enum DWORD { MDT_EFFECTIVE_DPI = 0, - MDT_ANGULAR_DPI = 1, - MDT_RAW_DPI = 2, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, MDT_DEFAULT, } diff --git a/core/sys/windows/shell32.odin b/core/sys/windows/shell32.odin index 54cee718c..0fdcc69d7 100644 --- a/core/sys/windows/shell32.odin +++ b/core/sys/windows/shell32.odin @@ -22,29 +22,33 @@ foreign shell32 { ) -> c_int --- SHFileOperationW :: proc(lpFileOp: LPSHFILEOPSTRUCTW) -> c_int --- SHGetFolderPathW :: proc(hwnd: HWND, csidl: c_int, hToken: HANDLE, dwFlags: DWORD, pszPath: LPWSTR) -> HRESULT --- - SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR --- + SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR --- Shell_NotifyIconW :: proc(dwMessage: DWORD, lpData: ^NOTIFYICONDATAW) -> BOOL --- - SHChangeNotify :: proc(wEventId: LONG, uFlags: UINT, dwItem1: LPCVOID, dwItem2: LPCVOID) --- + SHChangeNotify :: proc(wEventId: LONG, uFlags: UINT, dwItem1: LPCVOID, dwItem2: LPCVOID) --- SHGetKnownFolderIDList :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppidl: rawptr) -> HRESULT --- - SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT --- - SHGetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppszPath: ^LPWSTR) -> HRESULT --- + SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT --- + SHGetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppszPath: ^LPWSTR) -> HRESULT --- - ExtractIconExW :: proc(pszFile: LPCWSTR, nIconIndex: INT, phiconLarge: ^HICON, phiconSmall: ^HICON, nIcons: UINT) -> UINT --- + SHCreateItemFromParsingName :: proc(pszPath: PCWSTR, pbc: ^IBindCtx, riid: REFIID, ppv: ^rawptr) -> HRESULT --- + + ExtractIconExW :: proc(pszFile: LPCWSTR, nIconIndex: INT, phiconLarge: ^HICON, phiconSmall: ^HICON, nIcons: UINT) -> UINT --- DragAcceptFiles :: proc(hWnd: HWND, fAccept: BOOL) --- - DragQueryPoint :: proc(hDrop: HDROP, ppt: ^POINT) -> BOOL --- - DragQueryFileW :: proc(hDrop: HDROP, iFile: UINT, lpszFile: LPWSTR, cch: UINT) -> UINT --- - DragFinish :: proc(hDrop: HDROP) --- // @New + DragQueryPoint :: proc(hDrop: HDROP, ppt: ^POINT) -> BOOL --- + DragQueryFileW :: proc(hDrop: HDROP, iFile: UINT, lpszFile: LPWSTR, cch: UINT) -> UINT --- + DragFinish :: proc(hDrop: HDROP) --- // @New + + AssocCreateForClasses :: proc (rgClasses: [^]ASSOCIATIONELEMENT, cClasses: ULONG, riid: REFIID, ppv: ^rawptr) -> HRESULT --- } APPBARDATA :: struct { - cbSize: DWORD, - hWnd: HWND, + cbSize: DWORD, + hWnd: HWND, uCallbackMessage: UINT, - uEdge: UINT, - rc: RECT, - lParam: LPARAM, + uEdge: UINT, + rc: RECT, + lParam: LPARAM, } PAPPBARDATA :: ^APPBARDATA diff --git a/core/sys/windows/shlwapi.odin b/core/sys/windows/shlwapi.odin index 095fff304..19a255331 100644 --- a/core/sys/windows/shlwapi.odin +++ b/core/sys/windows/shlwapi.odin @@ -9,4 +9,12 @@ foreign shlwapi { PathFindExtensionW :: proc(pszPath: wstring) -> wstring --- PathFindFileNameW :: proc(pszPath: wstring) -> wstring --- SHAutoComplete :: proc(hwndEdit: HWND, dwFlags: DWORD) -> LWSTDAPI --- + + AssocCreate :: proc(clsid: CLSID, riid: REFIID, ppv: ^rawptr) -> HRESULT --- + SHGetAssocKeys :: proc(pqa: ^IQueryAssociations, rgKeys: [^]HKEY, cKeys: DWORD) -> HRESULT --- + AssocQueryStringW :: proc(flags: ASSOCF, str: ASSOCSTR, pszAssoc: LPCWSTR, pszExtra: LPCWSTR, pszOut: LPWSTR, pcchOut: ^DWORD) -> LWSTDAPI --- + AssocQueryStringByKeyW :: proc(flags: ASSOCF, str: ASSOCSTR, hkAssoc: HKEY, pszExtra: LPCWSTR, pszOut: LPWSTR, pcchOut: ^DWORD) -> HRESULT --- + AssocQueryKeyW :: proc(flags: ASSOCF, key: ASSOCKEY, pszAssoc: LPCWSTR, pszExtra: LPCWSTR, phkeyOut: ^HKEY) -> HRESULT --- + AssocIsDangerous :: proc(pszAssoc: PCWSTR) -> HRESULT --- + AssocGetPerceivedType :: proc(pszExt: PCWSTR, ptype: ^PERCEIVED, pflag: ^PERCEIVEDFLAG, ppszType: ^PWSTR) -> HRESULT --- } diff --git a/core/sys/windows/tlhelp.odin b/core/sys/windows/tlhelp.odin index 006c9c330..b23b4b06a 100644 --- a/core/sys/windows/tlhelp.odin +++ b/core/sys/windows/tlhelp.odin @@ -5,22 +5,22 @@ foreign import kernel32 "system:Kernel32.lib" @(default_calling_convention="system") foreign kernel32 { - CreateToolhelp32Snapshot :: proc (dwFlags: DWORD, th32ProcessID: DWORD) -> HANDLE --- - Process32FirstW :: proc (hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL --- - Process32NextW :: proc (hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL --- - Thread32First :: proc (hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL --- - Thread32Next :: proc (hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL --- - Module32FirstW :: proc (hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL --- - Module32NextW :: proc (hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL --- - Heap32ListFirst :: proc (hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL --- - Heap32ListNext :: proc (hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL --- - Heap32First :: proc (lphe: LPHEAPENTRY32, th32ProcessID: DWORD, th32HeapID: ULONG_PTR) -> BOOL --- - Heap32Next :: proc (lphe: LPHEAPENTRY32) -> BOOL --- - Toolhelp32ReadProcessMemory :: proc ( - th32ProcessID: DWORD, - lpBaseAddress: LPCVOID, - lpBuffer: LPVOID, - cbRead: SIZE_T, + CreateToolhelp32Snapshot :: proc(dwFlags: DWORD, th32ProcessID: DWORD) -> HANDLE --- + Process32FirstW :: proc(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL --- + Process32NextW :: proc(hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL --- + Thread32First :: proc(hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL --- + Thread32Next :: proc(hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL --- + Module32FirstW :: proc(hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL --- + Module32NextW :: proc(hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL --- + Heap32ListFirst :: proc(hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL --- + Heap32ListNext :: proc(hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL --- + Heap32First :: proc(lphe: LPHEAPENTRY32, th32ProcessID: DWORD, th32HeapID: ULONG_PTR) -> BOOL --- + Heap32Next :: proc(lphe: LPHEAPENTRY32) -> BOOL --- + Toolhelp32ReadProcessMemory :: proc( + th32ProcessID: DWORD, + lpBaseAddress: LPCVOID, + lpBuffer: LPVOID, + cbRead: SIZE_T, lpNumberOfBytesRead: ^SIZE_T, ) -> BOOL --- } @@ -36,66 +36,66 @@ TH32CS_SNAPMODULE32 :: 0x00000010 TH32CS_SNAPALL :: TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE PROCESSENTRY32W :: struct { - dwSize: DWORD, - cntUsage: DWORD, - th32ProcessID: DWORD, - th32DefaultHeapID: ULONG_PTR, - th32ModuleID: DWORD, - cntThreads: DWORD, + dwSize: DWORD, + cntUsage: DWORD, + th32ProcessID: DWORD, + th32DefaultHeapID: ULONG_PTR, + th32ModuleID: DWORD, + cntThreads: DWORD, th32ParentProcessID: DWORD, - pcPriClassBase: LONG, - dwFlags: DWORD, - szExeFile: [MAX_PATH]WCHAR, + pcPriClassBase: LONG, + dwFlags: DWORD, + szExeFile: [MAX_PATH]WCHAR, } LPPROCESSENTRY32W :: ^PROCESSENTRY32W THREADENTRY32 :: struct { - dwSize: DWORD, - cntUsage: DWORD, - th32ThreadID: DWORD, + dwSize: DWORD, + cntUsage: DWORD, + th32ThreadID: DWORD, th32OwnerProcessID: DWORD, - tpBasePri: LONG, - tpDeltaPri: LONG, - dwFlags: DWORD, + tpBasePri: LONG, + tpDeltaPri: LONG, + dwFlags: DWORD, } LPTHREADENTRY32 :: ^THREADENTRY32 MODULEENTRY32W :: struct { - dwSize: DWORD, - th32ModuleID: DWORD, + dwSize: DWORD, + th32ModuleID: DWORD, th32ProcessID: DWORD, - GlblcntUsage: DWORD, - ProccntUsage: DWORD, - modBaseAddr: ^BYTE, - modBaseSize: DWORD, - hModule: HMODULE, - szModule: [MAX_MODULE_NAME32 + 1]WCHAR, - szExePath: [MAX_PATH]WCHAR, + GlblcntUsage: DWORD, + ProccntUsage: DWORD, + modBaseAddr: ^BYTE, + modBaseSize: DWORD, + hModule: HMODULE, + szModule: [MAX_MODULE_NAME32 + 1]WCHAR, + szExePath: [MAX_PATH]WCHAR, } LPMODULEENTRY32W :: ^MODULEENTRY32W HEAPLIST32 :: struct { - dwSize: SIZE_T, + dwSize: SIZE_T, th32ProcessID: DWORD, - th32HeapID: ULONG_PTR, - dwFlags: DWORD, + th32HeapID: ULONG_PTR, + dwFlags: DWORD, } LPHEAPLIST32 :: ^HEAPLIST32 HEAPENTRY32 :: struct { - dwSize: SIZE_T, - hHandle: HANDLE, - dwAddress: ULONG_PTR, - dwBlockSize: SIZE_T, - dwFlags: DWORD, - dwLockCount: DWORD, - dwResvd: DWORD, + dwSize: SIZE_T, + hHandle: HANDLE, + dwAddress: ULONG_PTR, + dwBlockSize: SIZE_T, + dwFlags: DWORD, + dwLockCount: DWORD, + dwResvd: DWORD, th32ProcessID: DWORD, - th32HeapID: ULONG_PTR, + th32HeapID: ULONG_PTR, } LPHEAPENTRY32 :: ^HEAPENTRY32 diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index f698b63d4..0f80e0b18 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -1,5 +1,7 @@ package sys_windows +// Don't add a `#+build windows` guard to this file. It's used for `dxgi` on non-Windows platforms, for example. + import "core:c" c_char :: c.char @@ -15,75 +17,75 @@ c_ushort :: c.ushort size_t :: c.size_t wchar_t :: c.wchar_t -DWORD :: c_ulong -DWORDLONG :: c.ulonglong -QWORD :: c.ulonglong -HANDLE :: distinct LPVOID -PHANDLE :: ^HANDLE -HINSTANCE :: HANDLE -HMODULE :: distinct HINSTANCE -HRESULT :: distinct LONG -HWND :: distinct HANDLE -HDC :: distinct HANDLE -HMONITOR :: distinct HANDLE -HICON :: distinct HANDLE -HCURSOR :: distinct HANDLE -HMENU :: distinct HANDLE -HBRUSH :: distinct HANDLE -HPEN :: distinct HANDLE -HGDIOBJ :: distinct HANDLE -HBITMAP :: distinct HANDLE -HPALETTE :: distinct HANDLE -HGLOBAL :: distinct HANDLE -HHOOK :: distinct HANDLE -HWINEVENTHOOK :: distinct HANDLE -HKEY :: distinct HANDLE -HDESK :: distinct HANDLE -HFONT :: distinct HANDLE -HRGN :: distinct HANDLE -HRSRC :: distinct HANDLE -HWINSTA :: distinct HANDLE -HACCEL :: distinct HANDLE -BOOL :: distinct b32 -BYTE :: distinct u8 -BOOLEAN :: distinct b8 -GROUP :: distinct c_uint -LARGE_INTEGER :: distinct c_longlong -ULARGE_INTEGER :: distinct c_ulonglong +DWORD :: c_ulong +DWORDLONG :: c.ulonglong +QWORD :: c.ulonglong +HANDLE :: distinct LPVOID +PHANDLE :: ^HANDLE +HINSTANCE :: HANDLE +HMODULE :: distinct HINSTANCE +HRESULT :: distinct LONG +HWND :: distinct HANDLE +HDC :: distinct HANDLE +HMONITOR :: distinct HANDLE +HICON :: distinct HANDLE +HCURSOR :: distinct HANDLE +HMENU :: distinct HANDLE +HBRUSH :: distinct HANDLE +HPEN :: distinct HANDLE +HGDIOBJ :: distinct HANDLE +HBITMAP :: distinct HANDLE +HPALETTE :: distinct HANDLE +HGLOBAL :: distinct HANDLE +HHOOK :: distinct HANDLE +HWINEVENTHOOK :: distinct HANDLE +HKEY :: distinct HANDLE +HDESK :: distinct HANDLE +HFONT :: distinct HANDLE +HRGN :: distinct HANDLE +HRSRC :: distinct HANDLE +HWINSTA :: distinct HANDLE +HACCEL :: distinct HANDLE +BOOL :: distinct b32 +BYTE :: distinct u8 +BOOLEAN :: distinct b8 +GROUP :: distinct c_uint +LARGE_INTEGER :: distinct c_longlong +ULARGE_INTEGER :: distinct c_ulonglong PULARGE_INTEGER :: ^ULARGE_INTEGER -LONG :: c_long -UINT :: c_uint -INT :: c_int -SHORT :: c_short -USHORT :: c_ushort -WCHAR :: wchar_t -SIZE_T :: uint -PSIZE_T :: ^SIZE_T -WORD :: u16 -CHAR :: c_char -ULONG_PTR :: uint -PULONG_PTR :: ^ULONG_PTR -LPULONG_PTR :: ^ULONG_PTR -DWORD_PTR :: ULONG_PTR -LONG_PTR :: int -INT_PTR :: int -UINT_PTR :: uintptr -ULONG :: c_ulong -ULONGLONG :: c_ulonglong -LONGLONG :: c_longlong -UCHAR :: BYTE -NTSTATUS :: c.long -COLORREF :: DWORD -LPCOLORREF :: ^COLORREF -LPARAM :: LONG_PTR -WPARAM :: UINT_PTR -LRESULT :: LONG_PTR -LPRECT :: ^RECT -LPPOINT :: ^POINT -LSTATUS :: LONG -PHKEY :: ^HKEY -PUSHORT :: ^USHORT -PCHAR :: ^CHAR +LONG :: c_long +UINT :: c_uint +INT :: c_int +SHORT :: c_short +USHORT :: c_ushort +WCHAR :: wchar_t +SIZE_T :: uint +PSIZE_T :: ^SIZE_T +WORD :: u16 +CHAR :: c_char +ULONG_PTR :: uint +PULONG_PTR :: ^ULONG_PTR +LPULONG_PTR :: ^ULONG_PTR +DWORD_PTR :: ULONG_PTR +LONG_PTR :: int +INT_PTR :: int +UINT_PTR :: uintptr +ULONG :: c_ulong +ULONGLONG :: c_ulonglong +LONGLONG :: c_longlong +UCHAR :: BYTE +NTSTATUS :: c.long +COLORREF :: DWORD +LPCOLORREF :: ^COLORREF +LPARAM :: LONG_PTR +WPARAM :: UINT_PTR +LRESULT :: LONG_PTR +LPRECT :: ^RECT +LPPOINT :: ^POINT +LSTATUS :: LONG +PHKEY :: ^HKEY +PUSHORT :: ^USHORT +PCHAR :: ^CHAR UINT8 :: u8 UINT16 :: u16 @@ -101,68 +103,87 @@ LONG32 :: i32 ULONG64 :: u64 LONG64 :: i64 -DWORD64 :: u64 +DWORD64 :: u64 PDWORD64 :: ^DWORD64 PDWORD_PTR :: ^DWORD_PTR -ATOM :: distinct WORD +ATOM :: distinct WORD -wstring :: [^]WCHAR -PWSTR :: [^]WCHAR +wstring :: cstring16 +PWSTR :: cstring16 -PBYTE :: ^BYTE -LPBYTE :: ^BYTE -PBOOL :: ^BOOL -LPBOOL :: ^BOOL -LPCSTR :: cstring -LPCWSTR :: wstring -LPCTSTR :: wstring -LPDWORD :: ^DWORD -PCSTR :: cstring -PCWSTR :: wstring -PDWORD :: ^DWORD -LPHANDLE :: ^HANDLE -LPOVERLAPPED :: ^OVERLAPPED +PBYTE :: ^BYTE +LPBYTE :: ^BYTE +PBOOL :: ^BOOL +LPBOOL :: ^BOOL +LPCSTR :: cstring +LPCWSTR :: wstring +LPCTSTR :: wstring +LPDWORD :: ^DWORD +PCSTR :: cstring +PCWSTR :: wstring +PDWORD :: ^DWORD +LPHANDLE :: ^HANDLE +LPOVERLAPPED :: ^OVERLAPPED LPPROCESS_INFORMATION :: ^PROCESS_INFORMATION -PSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES +PSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES LPSECURITY_ATTRIBUTES :: ^SECURITY_ATTRIBUTES -LPSTARTUPINFOW :: ^STARTUPINFOW -LPTRACKMOUSEEVENT :: ^TRACKMOUSEEVENT -VOID :: rawptr -PVOID :: rawptr -LPVOID :: rawptr -PINT :: ^INT -LPINT :: ^INT -PUINT :: ^UINT -LPUINT :: ^UINT -LPWCH :: ^WCHAR -LPWORD :: ^WORD -PULONG :: ^ULONG -LPWIN32_FIND_DATAW :: ^WIN32_FIND_DATAW -LPWSADATA :: ^WSADATA -LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO -LPSTR :: ^CHAR -LPWSTR :: ^WCHAR -OLECHAR :: WCHAR -BSTR :: ^OLECHAR -LPOLESTR :: ^OLECHAR -LPCOLESTR :: LPCSTR -LPFILETIME :: ^FILETIME -LPWSABUF :: ^WSABUF -LPWSAOVERLAPPED :: distinct rawptr -LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr -LPCVOID :: rawptr -SCODE :: LONG -PSCODE :: ^SCODE +LPSTARTUPINFOW :: ^STARTUPINFOW +LPTRACKMOUSEEVENT :: ^TRACKMOUSEEVENT +VOID :: rawptr +PVOID :: rawptr +PVOID64 :: rawptr +LPVOID :: rawptr +PINT :: ^INT +LPINT :: ^INT +PUINT :: ^UINT +LPUINT :: ^UINT +LPWCH :: ^WCHAR +LPWORD :: ^WORD +PULONG :: ^ULONG +LPWIN32_FIND_DATAW :: ^WIN32_FIND_DATAW +LPWSADATA :: ^WSADATA +LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO +LPSTR :: ^CHAR +LPWSTR :: ^WCHAR +OLECHAR :: WCHAR +BSTR :: ^OLECHAR -PACCESS_TOKEN :: PVOID +LPOLESTR :: cstring16 +LPCOLESTR :: LPCSTR +LPFILETIME :: ^FILETIME +LPWSABUF :: ^WSABUF + +WSAEVENT :: HANDLE + +WSAOVERLAPPED :: struct { + Internal: DWORD, + InternalHigh: DWORD, + Offset: DWORD, + OffsetHigh: DWORD, + hEvent: WSAEVENT, +} + +LPWSAOVERLAPPED :: ^WSAOVERLAPPED +LPWSAOVERLAPPED_COMPLETION_ROUTINE :: #type proc "system" ( + dwError: DWORD, + cbTransferred: DWORD, + lpOverlapped: LPWSAOVERLAPPED, + dwFlags: DWORD, +) + +LPCVOID :: rawptr +SCODE :: LONG +PSCODE :: ^SCODE + +PACCESS_TOKEN :: PVOID PSECURITY_DESCRIPTOR :: PVOID -PSID :: PVOID -PCLAIMS_BLOB :: PVOID +PSID :: PVOID +PCLAIMS_BLOB :: PVOID PCONDITION_VARIABLE :: ^CONDITION_VARIABLE -PLARGE_INTEGER :: ^LARGE_INTEGER -PSRWLOCK :: ^SRWLOCK +PLARGE_INTEGER :: ^LARGE_INTEGER +PSRWLOCK :: ^SRWLOCK CREATE_WAITABLE_TIMER_MANUAL_RESET :: 0x00000001 CREATE_WAITABLE_TIMER_HIGH_RESOLUTION :: 0x00000002 @@ -183,28 +204,28 @@ LPSIZE :: ^SIZE MAXLONG :: 0x7fffffff -FILE_ATTRIBUTE_READONLY: DWORD : 0x00000001 -FILE_ATTRIBUTE_HIDDEN: DWORD : 0x00000002 -FILE_ATTRIBUTE_SYSTEM: DWORD : 0x00000004 -FILE_ATTRIBUTE_DIRECTORY: DWORD : 0x00000010 -FILE_ATTRIBUTE_ARCHIVE: DWORD : 0x00000020 -FILE_ATTRIBUTE_DEVICE: DWORD : 0x00000040 -FILE_ATTRIBUTE_NORMAL: DWORD : 0x00000080 -FILE_ATTRIBUTE_TEMPORARY: DWORD : 0x00000100 -FILE_ATTRIBUTE_SPARSE_FILE: DWORD : 0x00000200 -FILE_ATTRIBUTE_REPARSE_Point: DWORD : 0x00000400 -FILE_ATTRIBUTE_REPARSE_POINT: DWORD : 0x00000400 -FILE_ATTRIBUTE_COMPRESSED: DWORD : 0x00000800 -FILE_ATTRIBUTE_OFFLINE: DWORD : 0x00001000 -FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: DWORD : 0x00002000 -FILE_ATTRIBUTE_ENCRYPTED: DWORD : 0x00004000 +FILE_ATTRIBUTE_READONLY : DWORD : 0x00000001 +FILE_ATTRIBUTE_HIDDEN : DWORD : 0x00000002 +FILE_ATTRIBUTE_SYSTEM : DWORD : 0x00000004 +FILE_ATTRIBUTE_DIRECTORY : DWORD : 0x00000010 +FILE_ATTRIBUTE_ARCHIVE : DWORD : 0x00000020 +FILE_ATTRIBUTE_DEVICE : DWORD : 0x00000040 +FILE_ATTRIBUTE_NORMAL : DWORD : 0x00000080 +FILE_ATTRIBUTE_TEMPORARY : DWORD : 0x00000100 +FILE_ATTRIBUTE_SPARSE_FILE : DWORD : 0x00000200 +FILE_ATTRIBUTE_REPARSE_Point : DWORD : 0x00000400 +FILE_ATTRIBUTE_REPARSE_POINT : DWORD : 0x00000400 +FILE_ATTRIBUTE_COMPRESSED : DWORD : 0x00000800 +FILE_ATTRIBUTE_OFFLINE : DWORD : 0x00001000 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : DWORD : 0x00002000 +FILE_ATTRIBUTE_ENCRYPTED : DWORD : 0x00004000 -FILE_SHARE_READ: DWORD : 0x00000001 -FILE_SHARE_WRITE: DWORD : 0x00000002 -FILE_SHARE_DELETE: DWORD : 0x00000004 -FILE_GENERIC_ALL: DWORD : 0x10000000 -FILE_GENERIC_EXECUTE: DWORD : 0x20000000 -FILE_GENERIC_READ: DWORD : 0x80000000 +FILE_SHARE_READ : DWORD : 0x00000001 +FILE_SHARE_WRITE : DWORD : 0x00000002 +FILE_SHARE_DELETE : DWORD : 0x00000004 +FILE_GENERIC_ALL : DWORD : 0x10000000 +FILE_GENERIC_EXECUTE : DWORD : 0x20000000 +FILE_GENERIC_READ : DWORD : 0x80000000 FILE_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF FILE_ACTION_ADDED :: 0x00000001 @@ -222,11 +243,11 @@ FILE_NOTIFY_CHANGE_LAST_ACCESS :: 0x00000020 FILE_NOTIFY_CHANGE_CREATION :: 0x00000040 FILE_NOTIFY_CHANGE_SECURITY :: 0x00000100 -CREATE_NEW: DWORD : 1 -CREATE_ALWAYS: DWORD : 2 -OPEN_ALWAYS: DWORD : 4 -OPEN_EXISTING: DWORD : 3 -TRUNCATE_EXISTING: DWORD : 5 +CREATE_NEW : DWORD : 1 +CREATE_ALWAYS : DWORD : 2 +OPEN_ALWAYS : DWORD : 4 +OPEN_EXISTING : DWORD : 3 +TRUNCATE_EXISTING : DWORD : 5 FILE_READ_DATA : DWORD : 0x00000001 FILE_LIST_DIRECTORY : DWORD : 0x00000001 @@ -248,11 +269,12 @@ GENERIC_WRITE : DWORD : 0x40000000 GENERIC_EXECUTE : DWORD : 0x20000000 GENERIC_ALL : DWORD : 0x10000000 -FILE_GENERIC_WRITE: DWORD : STANDARD_RIGHTS_WRITE | - FILE_WRITE_DATA | +FILE_GENERIC_WRITE : DWORD : \ + STANDARD_RIGHTS_WRITE | + FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | - FILE_WRITE_EA | - FILE_APPEND_DATA | + FILE_WRITE_EA | + FILE_APPEND_DATA | SYNCHRONIZE SECURITY_SQOS_PRESENT: DWORD : 0x00100000 @@ -274,7 +296,7 @@ PROTECTED_SACL_SECURITY_INFORMATION :: 0x40000000 UNPROTECTED_DACL_SECURITY_INFORMATION :: 0x20000000 UNPROTECTED_SACL_SECURITY_INFORMATION :: 0x10000000 -GET_FILEEX_INFO_LEVELS :: distinct i32 +GET_FILEEX_INFO_LEVELS :: distinct c_int GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0 GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1 @@ -297,13 +319,13 @@ POWER_REQUEST_CONTEXT_DETAILED_STRING :: DIAGNOSTIC_REASON_DETAILED_STRING REASON_CONTEXT :: struct { Version: ULONG, - Flags: DWORD, + Flags: DWORD, Reason: struct #raw_union { Detailed: struct { LocalizedReasonModule: HMODULE, - LocalizedReasonId: ULONG, - ReasonStringCount: ULONG, - ReasonStrings: ^LPWSTR, + LocalizedReasonId: ULONG, + ReasonStringCount: ULONG, + ReasonStrings: [^]LPWSTR `fmt:"v,ReasonStringCount"`, }, SimpleReasonString: LPWSTR, }, @@ -324,9 +346,9 @@ RRF_RT_ANY :: 0x0000ffff RRF_NOEXPAND :: 0x10000000 RRF_ZEROONFAILURE :: 0x20000000 -ACCESS_MASK :: DWORD +ACCESS_MASK :: DWORD PACCESS_MASK :: ^ACCESS_MASK -REGSAM :: ACCESS_MASK +REGSAM :: ACCESS_MASK // Reserved Key Handles. HKEY_CLASSES_ROOT :: HKEY(uintptr(0x80000000)) @@ -368,12 +390,13 @@ KEY_WOW64_RES :: 0x0300 KEY_READ :: (STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE) KEY_WRITE :: (STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE) KEY_EXECUTE :: (KEY_READ) & (~SYNCHRONIZE) -KEY_ALL_ACCESS :: (STANDARD_RIGHTS_ALL | - KEY_QUERY_VALUE | - KEY_SET_VALUE | - KEY_CREATE_SUB_KEY | +KEY_ALL_ACCESS :: ( + STANDARD_RIGHTS_ALL | + KEY_QUERY_VALUE | + KEY_SET_VALUE | + KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | - KEY_NOTIFY | + KEY_NOTIFY | KEY_CREATE_LINK) & (~SYNCHRONIZE) // Open/Create Options @@ -385,17 +408,19 @@ REG_OPTION_BACKUP_RESTORE :: 0x00000004 REG_OPTION_OPEN_LINK :: 0x00000008 REG_OPTION_DONT_VIRTUALIZE :: 0x00000010 -REG_LEGAL_OPTION :: REG_OPTION_RESERVED | - REG_OPTION_NON_VOLATILE | - REG_OPTION_VOLATILE | - REG_OPTION_CREATE_LINK | +REG_LEGAL_OPTION :: \ + REG_OPTION_RESERVED | + REG_OPTION_NON_VOLATILE | + REG_OPTION_VOLATILE | + REG_OPTION_CREATE_LINK | REG_OPTION_BACKUP_RESTORE | - REG_OPTION_OPEN_LINK | + REG_OPTION_OPEN_LINK | REG_OPTION_DONT_VIRTUALIZE -REG_OPEN_LEGAL_OPTION :: REG_OPTION_RESERVED | +REG_OPEN_LEGAL_OPTION :: \ + REG_OPTION_RESERVED | REG_OPTION_BACKUP_RESTORE | - REG_OPTION_OPEN_LINK | + REG_OPTION_OPEN_LINK | REG_OPTION_DONT_VIRTUALIZE // Key creation/open disposition @@ -437,10 +462,11 @@ REG_NOTIFY_CHANGE_LAST_SET :: 0x00000004 REG_NOTIFY_CHANGE_SECURITY :: 0x00000008 REG_NOTIFY_THREAD_AGNOSTIC :: 0x10000000 -REG_LEGAL_CHANGE_FILTER :: REG_NOTIFY_CHANGE_NAME | +REG_LEGAL_CHANGE_FILTER :: \ + REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | - REG_NOTIFY_CHANGE_LAST_SET | - REG_NOTIFY_CHANGE_SECURITY | + REG_NOTIFY_CHANGE_LAST_SET | + REG_NOTIFY_CHANGE_SECURITY | REG_NOTIFY_THREAD_AGNOSTIC // Predefined Value Types. @@ -461,9 +487,9 @@ REG_QWORD_LITTLE_ENDIAN :: 11 BSMINFO :: struct { cbSize: UINT, - hdesk: HDESK, - hwnd: HWND, - luid: LUID, + hdesk: HDESK, + hwnd: HWND, + luid: LUID, } PBSMINFO :: ^BSMINFO @@ -545,37 +571,37 @@ COLOR_BTNHILIGHT :: COLOR_BTNHIGHLIGHT // Common Control Notification Code Ranges NM_FIRST :: 0 -NM_LAST :: ~DWORD(99 - 1) -LVN_FIRST :: ~DWORD(100 - 1) -LVN_LAST :: ~DWORD(199 - 1) -HDN_FIRST :: ~DWORD(300 - 1) -HDN_LAST :: ~DWORD(399 - 1) -TVN_FIRST :: ~DWORD(400 - 1) -TVN_LAST :: ~DWORD(499 - 1) -TTN_FIRST :: ~DWORD(520 - 1) -TTN_LAST :: ~DWORD(549 - 1) -TCN_FIRST :: ~DWORD(550 - 1) -TCN_LAST :: ~DWORD(580 - 1) -CDN_FIRST :: ~DWORD(601 - 1) -CDN_LAST :: ~DWORD(699 - 1) -TBN_FIRST :: ~DWORD(700 - 1) -TBN_LAST :: ~DWORD(720 - 1) -UDN_FIRST :: ~DWORD(721 - 1) -UDN_LAST :: ~DWORD(740 - 1) -MCN_FIRST :: ~DWORD(750 - 1) -MCN_LAST :: ~DWORD(759 - 1) -DTN_FIRST :: ~DWORD(760 - 1) -DTN_LAST :: ~DWORD(799 - 1) -CBEN_FIRST :: ~DWORD(800 - 1) -CBEN_LAST :: ~DWORD(830 - 1) -RBN_FIRST :: ~DWORD(831 - 1) -RBN_LAST :: ~DWORD(859 - 1) -IPN_FIRST :: ~DWORD(860 - 1) -IPN_LAST :: ~DWORD(879 - 1) -SBN_FIRST :: ~DWORD(880 - 1) -SBN_LAST :: ~DWORD(899 - 1) -PGN_FIRST :: ~DWORD(900 - 1) -PGN_LAST :: ~DWORD(950 - 1) +NM_LAST :: ~DWORD( 99 - 1) +LVN_FIRST :: ~DWORD( 100 - 1) +LVN_LAST :: ~DWORD( 199 - 1) +HDN_FIRST :: ~DWORD( 300 - 1) +HDN_LAST :: ~DWORD( 399 - 1) +TVN_FIRST :: ~DWORD( 400 - 1) +TVN_LAST :: ~DWORD( 499 - 1) +TTN_FIRST :: ~DWORD( 520 - 1) +TTN_LAST :: ~DWORD( 549 - 1) +TCN_FIRST :: ~DWORD( 550 - 1) +TCN_LAST :: ~DWORD( 580 - 1) +CDN_FIRST :: ~DWORD( 601 - 1) +CDN_LAST :: ~DWORD( 699 - 1) +TBN_FIRST :: ~DWORD( 700 - 1) +TBN_LAST :: ~DWORD( 720 - 1) +UDN_FIRST :: ~DWORD( 721 - 1) +UDN_LAST :: ~DWORD( 740 - 1) +MCN_FIRST :: ~DWORD( 750 - 1) +MCN_LAST :: ~DWORD( 759 - 1) +DTN_FIRST :: ~DWORD( 760 - 1) +DTN_LAST :: ~DWORD( 799 - 1) +CBEN_FIRST :: ~DWORD( 800 - 1) +CBEN_LAST :: ~DWORD( 830 - 1) +RBN_FIRST :: ~DWORD( 831 - 1) +RBN_LAST :: ~DWORD( 859 - 1) +IPN_FIRST :: ~DWORD( 860 - 1) +IPN_LAST :: ~DWORD( 879 - 1) +SBN_FIRST :: ~DWORD( 880 - 1) +SBN_LAST :: ~DWORD( 899 - 1) +PGN_FIRST :: ~DWORD( 900 - 1) +PGN_LAST :: ~DWORD( 950 - 1) WMN_FIRST :: ~DWORD(1000 - 1) WMN_LAST :: ~DWORD(1200 - 1) BCN_FIRST :: ~DWORD(1250 - 1) @@ -1255,61 +1281,61 @@ HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> WINEVENTPROC :: #type proc "system" ( hWinEventHook: HWINEVENTHOOK, - event: DWORD, - hwnd: HWND, - idObject, idChild: LONG, + event: DWORD, + hwnd: HWND, + idObject, idChild: LONG, idEventThread, dwmsEventTime: DWORD, ) CWPRETSTRUCT :: struct { lResult: LRESULT, - lParam: LPARAM, - wParam: WPARAM, + lParam: LPARAM, + wParam: WPARAM, message: UINT, - hwnd: HWND, + hwnd: HWND, } MSLLHOOKSTRUCT :: struct { - pt: POINT, - mouseData: DWORD, - flags: DWORD, - time: DWORD, + pt: POINT, + mouseData: DWORD, + flags: DWORD, + time: DWORD, dwExtraInfo: ULONG_PTR, } KBDLLHOOKSTRUCT :: struct { - vkCode: DWORD, - scanCode: DWORD, - flags: DWORD, - time: DWORD, + vkCode: DWORD, + scanCode: DWORD, + flags: DWORD, + time: DWORD, dwExtraInfo: ULONG_PTR, } MOUSEINPUT :: struct { - dx: LONG, - dy: LONG, - mouseData: DWORD, - dwFlags: DWORD, - time: DWORD, + dx: LONG, + dy: LONG, + mouseData: DWORD, + dwFlags: DWORD, + time: DWORD, dwExtraInfo: ULONG_PTR, } KEYBDINPUT :: struct { - wVk: WORD, - wScan: WORD, - dwFlags: DWORD, - time: DWORD, + wVk: WORD, + wScan: WORD, + dwFlags: DWORD, + time: DWORD, dwExtraInfo: ULONG_PTR, } HARDWAREINPUT :: struct { - uMsg: DWORD, + uMsg: DWORD, wParamL: WORD, wParamH: WORD, } INPUT_TYPE :: enum DWORD { - MOUSE = 0, + MOUSE = 0, KEYBOARD = 1, HARDWARE = 2, } @@ -1317,128 +1343,128 @@ INPUT_TYPE :: enum DWORD { INPUT :: struct { type: INPUT_TYPE, using _: struct #raw_union { - mi: MOUSEINPUT, - ki: KEYBDINPUT, - hi: HARDWAREINPUT, + mi: MOUSEINPUT `raw_union_tag:"type=MOUSE"`, + ki: KEYBDINPUT `raw_union_tag:"type=KEYBOARD"`, + hi: HARDWAREINPUT `raw_union_tag:"type=HARDWARE"`, }, } -MOUSEEVENTF_MOVE :: 0x0001 -MOUSEEVENTF_LEFTDOWN :: 0x0002 -MOUSEEVENTF_LEFTUP :: 0x0004 -MOUSEEVENTF_RIGHTDOWN :: 0x0008 -MOUSEEVENTF_RIGHTUP :: 0x0010 -MOUSEEVENTF_MIDDLEDOWN :: 0x0020 -MOUSEEVENTF_MIDDLEUP :: 0x0040 -MOUSEEVENTF_XDOWN :: 0x0080 -MOUSEEVENTF_XUP :: 0x0100 -MOUSEEVENTF_WHEEL :: 0x0800 -MOUSEEVENTF_HWHEEL :: 0x1000 +MOUSEEVENTF_MOVE :: 0x0001 +MOUSEEVENTF_LEFTDOWN :: 0x0002 +MOUSEEVENTF_LEFTUP :: 0x0004 +MOUSEEVENTF_RIGHTDOWN :: 0x0008 +MOUSEEVENTF_RIGHTUP :: 0x0010 +MOUSEEVENTF_MIDDLEDOWN :: 0x0020 +MOUSEEVENTF_MIDDLEUP :: 0x0040 +MOUSEEVENTF_XDOWN :: 0x0080 +MOUSEEVENTF_XUP :: 0x0100 +MOUSEEVENTF_WHEEL :: 0x0800 +MOUSEEVENTF_HWHEEL :: 0x1000 MOUSEEVENTF_MOVE_NOCOALESCE :: 0x2000 -MOUSEEVENTF_VIRTUALDESK :: 0x4000 -MOUSEEVENTF_ABSOLUTE :: 0x8000 +MOUSEEVENTF_VIRTUALDESK :: 0x4000 +MOUSEEVENTF_ABSOLUTE :: 0x8000 WNDCLASSA :: struct { - style: UINT, - lpfnWndProc: WNDPROC, - cbClsExtra: c_int, - cbWndExtra: c_int, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, + style: UINT, + lpfnWndProc: WNDPROC, + cbClsExtra: c_int, + cbWndExtra: c_int, + hInstance: HINSTANCE, + hIcon: HICON, + hCursor: HCURSOR, hbrBackground: HBRUSH, - lpszMenuName: LPCSTR, + lpszMenuName: LPCSTR, lpszClassName: LPCSTR, } WNDCLASSW :: struct { - style: UINT, - lpfnWndProc: WNDPROC, - cbClsExtra: c_int, - cbWndExtra: c_int, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, + style: UINT, + lpfnWndProc: WNDPROC, + cbClsExtra: c_int, + cbWndExtra: c_int, + hInstance: HINSTANCE, + hIcon: HICON, + hCursor: HCURSOR, hbrBackground: HBRUSH, - lpszMenuName: LPCWSTR, + lpszMenuName: LPCWSTR, lpszClassName: LPCWSTR, } WNDCLASSEXA :: struct { - cbSize: UINT, - style: UINT, - lpfnWndProc: WNDPROC, - cbClsExtra: c_int, - cbWndExtra: c_int, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, + cbSize: UINT, + style: UINT, + lpfnWndProc: WNDPROC, + cbClsExtra: c_int, + cbWndExtra: c_int, + hInstance: HINSTANCE, + hIcon: HICON, + hCursor: HCURSOR, hbrBackground: HBRUSH, - lpszMenuName: LPCSTR, + lpszMenuName: LPCSTR, lpszClassName: LPCSTR, - hIconSm: HICON, + hIconSm: HICON, } WNDCLASSEXW :: struct { - cbSize: UINT, - style: UINT, - lpfnWndProc: WNDPROC, - cbClsExtra: c_int, - cbWndExtra: c_int, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, + cbSize: UINT, + style: UINT, + lpfnWndProc: WNDPROC, + cbClsExtra: c_int, + cbWndExtra: c_int, + hInstance: HINSTANCE, + hIcon: HICON, + hCursor: HCURSOR, hbrBackground: HBRUSH, - lpszMenuName: LPCWSTR, + lpszMenuName: LPCWSTR, lpszClassName: LPCWSTR, - hIconSm: HICON, + hIconSm: HICON, } MSG :: struct { - hwnd: HWND, + hwnd: HWND, message: UINT, - wParam: WPARAM, - lParam: LPARAM, - time: DWORD, - pt: POINT, + wParam: WPARAM, + lParam: LPARAM, + time: DWORD, + pt: POINT, } LPMSG :: ^MSG NOTIFYICONDATAW :: struct { - cbSize: DWORD, - hWnd: HWND, - uID: UINT, - uFlags: UINT, + cbSize: DWORD, + hWnd: HWND, + uID: UINT, + uFlags: UINT, uCallbackMessage: UINT, - hIcon: HICON, - szTip: [128]WCHAR, - dwState: DWORD, - dwStateMask: DWORD, - szInfo: [256]WCHAR, + hIcon: HICON, + szTip: [128]WCHAR, + dwState: DWORD, + dwStateMask: DWORD, + szInfo: [256]WCHAR, using _: struct #raw_union { uTimeout: UINT, uVersion: UINT, }, - szInfoTitle: [64]WCHAR, - dwInfoFlags: DWORD, - guidItem: GUID, + szInfoTitle: [64]WCHAR, + dwInfoFlags: DWORD, + guidItem: GUID, hBalloonIcon: HICON, } -NIF_MESSAGE :: 0x00000001 -NIF_ICON :: 0x00000002 -NIF_TIP :: 0x00000004 -NIF_STATE :: 0x00000008 -NIF_INFO :: 0x00000010 -NIF_GUID :: 0x00000020 +NIF_MESSAGE :: 0x00000001 +NIF_ICON :: 0x00000002 +NIF_TIP :: 0x00000004 +NIF_STATE :: 0x00000008 +NIF_INFO :: 0x00000010 +NIF_GUID :: 0x00000020 NIF_REALTIME :: 0x00000040 -NIF_SHOWTIP :: 0x00000080 +NIF_SHOWTIP :: 0x00000080 -NIM_ADD :: 0x00000000 -NIM_MODIFY :: 0x00000001 -NIM_DELETE :: 0x00000002 -NIM_SETFOCUS :: 0x00000003 +NIM_ADD :: 0x00000000 +NIM_MODIFY :: 0x00000001 +NIM_DELETE :: 0x00000002 +NIM_SETFOCUS :: 0x00000003 NIM_SETVERSION :: 0x00000004 // Menu flags for Add/Check/EnableMenuItem() @@ -1448,37 +1474,37 @@ MF_APPEND :: 0x00000100 MF_DELETE :: 0x00000200 MF_REMOVE :: 0x00001000 -MF_BYCOMMAND :: 0x00000000 +MF_BYCOMMAND :: 0x00000000 MF_BYPOSITION :: 0x00000400 MF_SEPARATOR :: 0x00000800 -MF_ENABLED :: 0x00000000 -MF_GRAYED :: 0x00000001 +MF_ENABLED :: 0x00000000 +MF_GRAYED :: 0x00000001 MF_DISABLED :: 0x00000002 -MF_UNCHECKED :: 0x00000000 -MF_CHECKED :: 0x00000008 +MF_UNCHECKED :: 0x00000000 +MF_CHECKED :: 0x00000008 MF_USECHECKBITMAPS :: 0x00000200 -MF_STRING :: 0x00000000 -MF_BITMAP :: 0x00000004 +MF_STRING :: 0x00000000 +MF_BITMAP :: 0x00000004 MF_OWNERDRAW :: 0x00000100 -MF_POPUP :: 0x00000010 +MF_POPUP :: 0x00000010 MF_MENUBARBREAK :: 0x00000020 -MF_MENUBREAK :: 0x00000040 +MF_MENUBREAK :: 0x00000040 MF_UNHILITE :: 0x00000000 -MF_HILITE :: 0x00000080 +MF_HILITE :: 0x00000080 -MF_DEFAULT :: 0x00001000 -MF_SYSMENU :: 0x00002000 -MF_HELP :: 0x00004000 +MF_DEFAULT :: 0x00001000 +MF_SYSMENU :: 0x00002000 +MF_HELP :: 0x00004000 MF_RIGHTJUSTIFY :: 0x00004000 MF_MOUSESELECT :: 0x00008000 -MF_END :: 0x00000080 // Obsolete -- only used by old RES files +MF_END :: 0x00000080 // Obsolete -- only used by old RES files // Menu flags for Add/Check/EnableMenuItem() MFS_GRAYED :: 0x00000003 @@ -1491,27 +1517,27 @@ MFS_UNHILITE :: MF_UNHILITE MFS_DEFAULT :: MF_DEFAULT // Flags for TrackPopupMenu -TPM_LEFTBUTTON :: 0x0000 -TPM_RIGHTBUTTON :: 0x0002 -TPM_LEFTALIGN :: 0x0000 -TPM_CENTERALIGN :: 0x0004 -TPM_RIGHTALIGN :: 0x0008 -TPM_TOPALIGN :: 0x0000 +TPM_LEFTBUTTON :: 0x0000 +TPM_RIGHTBUTTON :: 0x0002 +TPM_LEFTALIGN :: 0x0000 +TPM_CENTERALIGN :: 0x0004 +TPM_RIGHTALIGN :: 0x0008 +TPM_TOPALIGN :: 0x0000 TPM_VCENTERALIGN :: 0x0010 -TPM_BOTTOMALIGN :: 0x0020 +TPM_BOTTOMALIGN :: 0x0020 -TPM_HORIZONTAL :: 0x0000 /* Horz alignment matters more */ -TPM_VERTICAL :: 0x0040 /* Vert alignment matters more */ -TPM_NONOTIFY :: 0x0080 /* Don't send any notification msgs */ -TPM_RETURNCMD :: 0x0100 -TPM_RECURSE :: 0x0001 +TPM_HORIZONTAL :: 0x0000 /* Horz alignment matters more */ +TPM_VERTICAL :: 0x0040 /* Vert alignment matters more */ +TPM_NONOTIFY :: 0x0080 /* Don't send any notification msgs */ +TPM_RETURNCMD :: 0x0100 +TPM_RECURSE :: 0x0001 TPM_HORPOSANIMATION :: 0x0400 TPM_HORNEGANIMATION :: 0x0800 TPM_VERPOSANIMATION :: 0x1000 TPM_VERNEGANIMATION :: 0x2000 -TPM_NOANIMATION :: 0x4000 -TPM_LAYOUTRTL :: 0x8000 -TPM_WORKAREA :: 0x10000 +TPM_NOANIMATION :: 0x4000 +TPM_LAYOUTRTL :: 0x8000 +TPM_WORKAREA :: 0x10000 // WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes HTERROR :: -2 @@ -1545,42 +1571,42 @@ HTCLOSE :: 20 HTHELP :: 21 TEXTMETRICW :: struct { - tmHeight: LONG, - tmAscent: LONG, - tmDescent: LONG, - tmInternalLeading: LONG, - tmExternalLeading: LONG, - tmAveCharWidth: LONG, - tmMaxCharWidth: LONG, - tmWeight: LONG, - tmOverhang: LONG, + tmHeight: LONG, + tmAscent: LONG, + tmDescent: LONG, + tmInternalLeading: LONG, + tmExternalLeading: LONG, + tmAveCharWidth: LONG, + tmMaxCharWidth: LONG, + tmWeight: LONG, + tmOverhang: LONG, tmDigitizedAspectX: LONG, tmDigitizedAspectY: LONG, - tmFirstChar: WCHAR, - tmLastChar: WCHAR, - tmDefaultChar: WCHAR, - tmBreakChar: WCHAR, - tmItalic: BYTE, - tmUnderlined: BYTE, - tmStruckOut: BYTE, - tmPitchAndFamily: BYTE, - tmCharSet: BYTE, + tmFirstChar: WCHAR, + tmLastChar: WCHAR, + tmDefaultChar: WCHAR, + tmBreakChar: WCHAR, + tmItalic: BYTE, + tmUnderlined: BYTE, + tmStruckOut: BYTE, + tmPitchAndFamily: BYTE, + tmCharSet: BYTE, } LPTEXTMETRICW :: ^TEXTMETRICW PAINTSTRUCT :: struct { - hdc: HDC, - fErase: BOOL, - rcPaint: RECT, - fRestore: BOOL, - fIncUpdate: BOOL, + hdc: HDC, + fErase: BOOL, + rcPaint: RECT, + fRestore: BOOL, + fIncUpdate: BOOL, rgbReserved: [32]BYTE, } TRACKMOUSEEVENT :: struct { - cbSize: DWORD, - dwFlags: DWORD, - hwndTrack: HWND, + cbSize: DWORD, + dwFlags: DWORD, + hwndTrack: HWND, dwHoverTime: DWORD, } @@ -1640,16 +1666,16 @@ MAX_LINKID_TEXT :: 48 L_MAX_URL_LENGTH :: 2048 + 32 + len("://") LITEM :: struct { - mask: UINT, - iLink: c_int, - state: UINT, + mask: UINT, + iLink: c_int, + state: UINT, stateMask: UINT, - szID: [MAX_LINKID_TEXT]WCHAR, - szUrl: [L_MAX_URL_LENGTH]WCHAR, + szID: [MAX_LINKID_TEXT]WCHAR, + szUrl: [L_MAX_URL_LENGTH]WCHAR, } NMLINK :: struct { - hdr: NMHDR, + hdr: NMHDR, item: LITEM, } @@ -1660,12 +1686,12 @@ NMHDR :: struct { } NMCUSTOMDRAW :: struct { - hdr: NMHDR, + hdr: NMHDR, dwDrawStage: DWORD, - hdc: HDC, - rc: RECT, - dwItemSpec: DWORD_PTR, - uItemState: UINT, + hdc: HDC, + rc: RECT, + dwItemSpec: DWORD_PTR, + uItemState: UINT, lItemlParam: LPARAM, } @@ -1698,17 +1724,17 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22 NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM -PCZZWSTR :: ^WCHAR +PCZZWSTR :: cstring16 SHFILEOPSTRUCTW :: struct { - hwnd: HWND, - wFunc: UINT, - pFrom: PCZZWSTR, - pTo: PCZZWSTR, - fFlags: FILEOP_FLAGS, + hwnd: HWND, + wFunc: UINT, + pFrom: PCZZWSTR, + pTo: PCZZWSTR, + fFlags: FILEOP_FLAGS, fAnyOperationsAborted: BOOL, - hNameMappings: LPVOID, - lpszProgressTitle: PCWSTR, // only used if FOF_SIMPLEPROGRESS + hNameMappings: LPVOID, + lpszProgressTitle: PCWSTR, // only used if FOF_SIMPLEPROGRESS } LPSHFILEOPSTRUCTW :: ^SHFILEOPSTRUCTW @@ -1741,7 +1767,7 @@ FOF_NO_UI :: (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FILEOP_FLAGS :: WORD DEVMODEW :: struct { - dmDeviceName: [32]wchar_t, + dmDeviceName: [32]wchar_t, dmSpecVersion: WORD, dmDriverVersion: WORD, dmSize: WORD, @@ -1887,7 +1913,7 @@ WS_MINIMIZE : UINT : 0x2000_0000 WS_MINIMIZEBOX : UINT : 0x0002_0000 WS_OVERLAPPED : UINT : 0x0000_0000 WS_OVERLAPPEDWINDOW : UINT : WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX -WS_POPUP : UINT : 0x8000_0000 +WS_POPUP : UINT : 0x8000_0000 WS_POPUPWINDOW : UINT : WS_POPUP | WS_BORDER | WS_SYSMENU WS_SIZEBOX : UINT : 0x0004_0000 WS_SYSMENU : UINT : 0x0008_0000 @@ -2227,24 +2253,24 @@ SEE_MASK_FLAG_LOG_USAGE :: 0x04000000 SEE_MASK_FLAG_HINST_IS_SITE :: 0x08000000 SHELLEXECUTEINFOW :: struct { - cbSize: DWORD, // in, required, sizeof of this structure - fMask: ULONG, // in, SEE_MASK_XXX values - hwnd: HWND, // in, optional - lpVerb: LPCWSTR, // in, optional when unspecified the default verb is choosen - lpFile: LPCWSTR, // in, either this value or lpIDList must be specified - lpParameters: LPCWSTR, // in, optional - lpDirectory: LPCWSTR, // in, optional - nShow: c.int, // in, required - hInstApp: HINSTANCE, // out when SEE_MASK_NOCLOSEPROCESS is specified - lpIDList: rawptr, // in, valid when SEE_MASK_IDLIST is specified, PCIDLIST_ABSOLUTE, for use with SEE_MASK_IDLIST & SEE_MASK_INVOKEIDLIST - lpClass: LPCWSTR, // in, valid when SEE_MASK_CLASSNAME is specified - hkeyClass: HKEY, // in, valid when SEE_MASK_CLASSKEY is specified - dwHotKey: DWORD, // in, valid when SEE_MASK_HOTKEY is specified - DUMMYUNIONNAME: struct #raw_union { - hIcon: HANDLE, // not used - hMonitor: HANDLE, // in, valid when SEE_MASK_HMONITOR specified + cbSize: DWORD, // in, required, sizeof of this structure + fMask: ULONG, // in, SEE_MASK_XXX values + hwnd: HWND, // in, optional + lpVerb: LPCWSTR, // in, optional when unspecified the default verb is choosen + lpFile: LPCWSTR, // in, either this value or lpIDList must be specified + lpParameters: LPCWSTR, // in, optional + lpDirectory: LPCWSTR, // in, optional + nShow: c_int, // in, required + hInstApp: HINSTANCE, // out when SEE_MASK_NOCLOSEPROCESS is specified + lpIDList: rawptr, // in, valid when SEE_MASK_IDLIST is specified, PCIDLIST_ABSOLUTE, for use with SEE_MASK_IDLIST & SEE_MASK_INVOKEIDLIST + lpClass: LPCWSTR, // in, valid when SEE_MASK_CLASSNAME is specified + hkeyClass: HKEY, // in, valid when SEE_MASK_CLASSKEY is specified + dwHotKey: DWORD, // in, valid when SEE_MASK_HOTKEY is specified + using DUMMYUNIONNAME: struct #raw_union { + hIcon: HANDLE, // not used + hMonitor: HANDLE, // in, valid when SEE_MASK_HMONITOR specified }, - hProcess: HANDLE, // out, valid when SEE_MASK_NOCLOSEPROCESS specified + hProcess: HANDLE, // out, valid when SEE_MASK_NOCLOSEPROCESS specified } LPSHELLEXECUTEINFOW :: ^SHELLEXECUTEINFOW @@ -2291,9 +2317,9 @@ WA_CLICKACTIVE :: 2 // Struct pointed to by WM_GETMINMAXINFO lParam MINMAXINFO :: struct { - ptReserved: POINT, - ptMaxSize: POINT, - ptMaxPosition: POINT, + ptReserved: POINT, + ptMaxSize: POINT, + ptMaxPosition: POINT, ptMinTrackSize: POINT, ptMaxTrackSize: POINT, } @@ -2514,53 +2540,53 @@ STOCK_LAST :: 19 CLR_INVALID :: 0xFFFFFFFF RGBQUAD :: struct { - rgbBlue: BYTE, - rgbGreen: BYTE, - rgbRed: BYTE, + rgbBlue: BYTE, + rgbGreen: BYTE, + rgbRed: BYTE, rgbReserved: BYTE, } PIXELFORMATDESCRIPTOR :: struct { - nSize: WORD, - nVersion: WORD, - dwFlags: DWORD, - iPixelType: BYTE, - cColorBits: BYTE, - cRedBits: BYTE, - cRedShift: BYTE, - cGreenBits: BYTE, - cGreenShift: BYTE, - cBlueBits: BYTE, - cBlueShift: BYTE, - cAlphaBits: BYTE, - cAlphaShift: BYTE, - cAccumBits: BYTE, - cAccumRedBits: BYTE, + nSize: WORD, + nVersion: WORD, + dwFlags: DWORD, + iPixelType: BYTE, + cColorBits: BYTE, + cRedBits: BYTE, + cRedShift: BYTE, + cGreenBits: BYTE, + cGreenShift: BYTE, + cBlueBits: BYTE, + cBlueShift: BYTE, + cAlphaBits: BYTE, + cAlphaShift: BYTE, + cAccumBits: BYTE, + cAccumRedBits: BYTE, cAccumGreenBits: BYTE, - cAccumBlueBits: BYTE, + cAccumBlueBits: BYTE, cAccumAlphaBits: BYTE, - cDepthBits: BYTE, - cStencilBits: BYTE, - cAuxBuffers: BYTE, - iLayerType: BYTE, - bReserved: BYTE, - dwLayerMask: DWORD, - dwVisibleMask: DWORD, - dwDamageMask: DWORD, + cDepthBits: BYTE, + cStencilBits: BYTE, + cAuxBuffers: BYTE, + iLayerType: BYTE, + bReserved: BYTE, + dwLayerMask: DWORD, + dwVisibleMask: DWORD, + dwDamageMask: DWORD, } BITMAPINFOHEADER :: struct { - biSize: DWORD, - biWidth: LONG, - biHeight: LONG, - biPlanes: WORD, - biBitCount: WORD, - biCompression: DWORD, - biSizeImage: DWORD, + biSize: DWORD, + biWidth: LONG, + biHeight: LONG, + biPlanes: WORD, + biBitCount: WORD, + biCompression: DWORD, + biSizeImage: DWORD, biXPelsPerMeter: LONG, biYPelsPerMeter: LONG, - biClrUsed: DWORD, - biClrImportant: DWORD, + biClrUsed: DWORD, + biClrImportant: DWORD, } BITMAPINFO :: struct { @@ -2668,64 +2694,66 @@ CONDITION_VARIABLE_INIT :: CONDITION_VARIABLE{} SRWLOCK_INIT :: SRWLOCK{} // Flags in STARTUPINFOW.dwFlags. -STARTF_USESHOWWINDOW: DWORD : 0x00000001 -STARTF_USESIZE: DWORD : 0x00000002 -STARTF_USEPOSITION: DWORD : 0x00000004 -STARTF_USECOUNTCHARS: DWORD : 0x00000008 -STARTF_USEFILLATTRIBUTE: DWORD : 0x00000010 -STARTF_RUNFULLSCREEN: DWORD : 0x00000020 // ignored for non-x86 platforms -STARTF_FORCEONFEEDBACK: DWORD : 0x00000040 -STARTF_FORCEOFFFEEDBACK: DWORD : 0x00000080 -STARTF_USESTDHANDLES: DWORD : 0x00000100 +STARTF_USESHOWWINDOW : DWORD : 0x00000001 +STARTF_USESIZE : DWORD : 0x00000002 +STARTF_USEPOSITION : DWORD : 0x00000004 +STARTF_USECOUNTCHARS : DWORD : 0x00000008 +STARTF_USEFILLATTRIBUTE : DWORD : 0x00000010 +STARTF_RUNFULLSCREEN : DWORD : 0x00000020 // ignored for non-x86 platforms +STARTF_FORCEONFEEDBACK : DWORD : 0x00000040 +STARTF_FORCEOFFFEEDBACK : DWORD : 0x00000080 +STARTF_USESTDHANDLES : DWORD : 0x00000100 // WINVER >= 0x400 -STARTF_USEHOTKEY: DWORD : 0x00000200 -STARTF_TITLEISLINKNAME: DWORD : 0x00000800 -STARTF_TITLEISAPPID: DWORD : 0x00001000 -STARTF_PREVENTPINNING: DWORD : 0x00002000 +STARTF_USEHOTKEY : DWORD : 0x00000200 +STARTF_TITLEISLINKNAME : DWORD : 0x00000800 +STARTF_TITLEISAPPID : DWORD : 0x00001000 +STARTF_PREVENTPINNING : DWORD : 0x00002000 // WINVER >= 0x600 -STARTF_UNTRUSTEDSOURCE: DWORD : 0x00008000 +STARTF_UNTRUSTEDSOURCE : DWORD : 0x00008000 VOLUME_NAME_DOS: DWORD : 0x0 -MOVEFILE_COPY_ALLOWED: DWORD: 0x2 -MOVEFILE_CREATE_HARDLINK: DWORD: 0x10 -MOVEFILE_DELAY_UNTIL_REBOOT: DWORD: 0x4 -MOVEFILE_FAIL_IF_NOT_TRACKABLE: DWORD: 0x20 -MOVEFILE_REPLACE_EXISTING: DWORD : 0x1 -MOVEFILE_WRITE_THROUGH: DWORD: 0x8 +MOVEFILE_COPY_ALLOWED : DWORD : 0x2 +MOVEFILE_CREATE_HARDLINK : DWORD : 0x10 +MOVEFILE_DELAY_UNTIL_REBOOT : DWORD : 0x4 +MOVEFILE_FAIL_IF_NOT_TRACKABLE : DWORD : 0x20 +MOVEFILE_REPLACE_EXISTING : DWORD : 0x1 +MOVEFILE_WRITE_THROUGH : DWORD : 0x8 -FILE_BEGIN: DWORD : 0 -FILE_CURRENT: DWORD : 1 -FILE_END: DWORD : 2 +FILE_BEGIN : DWORD : 0 +FILE_CURRENT : DWORD : 1 +FILE_END : DWORD : 2 -WAIT_OBJECT_0: DWORD : 0x00000000 -WAIT_TIMEOUT: DWORD : 258 -WAIT_FAILED: DWORD : 0xFFFFFFFF +WAIT_OBJECT_0 : DWORD : 0x00000000 +WAIT_TIMEOUT : DWORD : 258 +WAIT_FAILED : DWORD : 0xFFFFFFFF -FILE_FLAG_WRITE_THROUGH: DWORD : 0x80000000 -FILE_FLAG_OVERLAPPED: DWORD : 0x40000000 -FILE_FLAG_NO_BUFFERING: DWORD : 0x20000000 -FILE_FLAG_RANDOM_ACCESS: DWORD : 0x10000000 -FILE_FLAG_SEQUENTIAL_SCAN: DWORD : 0x08000000 -FILE_FLAG_DELETE_ON_CLOSE: DWORD : 0x04000000 -FILE_FLAG_BACKUP_SEMANTICS: DWORD : 0x02000000 -FILE_FLAG_POSIX_SEMANTICS: DWORD : 0x01000000 -FILE_FLAG_SESSION_AWARE: DWORD : 0x00800000 -FILE_FLAG_OPEN_REPARSE_POINT: DWORD : 0x00200000 -FILE_FLAG_OPEN_NO_RECALL: DWORD : 0x00100000 -FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000 +WAIT_IO_COMPLETION: DWORD : 0x000000C0 -PIPE_ACCESS_INBOUND: DWORD : 0x00000001 -PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002 -PIPE_ACCESS_DUPLEX: DWORD : 0x00000003 -PIPE_WAIT: DWORD : 0x00000000 -PIPE_TYPE_BYTE: DWORD : 0x00000000 -PIPE_TYPE_MESSAGE: DWORD : 0x00000004 -PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008 -PIPE_READMODE_BYTE: DWORD : 0x00000000 -PIPE_READMODE_MESSAGE: DWORD : 0x00000002 -PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000 +FILE_FLAG_WRITE_THROUGH : DWORD : 0x80000000 +FILE_FLAG_OVERLAPPED : DWORD : 0x40000000 +FILE_FLAG_NO_BUFFERING : DWORD : 0x20000000 +FILE_FLAG_RANDOM_ACCESS : DWORD : 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN : DWORD : 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE : DWORD : 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS : DWORD : 0x02000000 +FILE_FLAG_POSIX_SEMANTICS : DWORD : 0x01000000 +FILE_FLAG_SESSION_AWARE : DWORD : 0x00800000 +FILE_FLAG_OPEN_REPARSE_POINT : DWORD : 0x00200000 +FILE_FLAG_OPEN_NO_RECALL : DWORD : 0x00100000 +FILE_FLAG_FIRST_PIPE_INSTANCE : DWORD : 0x00080000 + +PIPE_ACCESS_INBOUND : DWORD : 0x00000001 +PIPE_ACCESS_OUTBOUND : DWORD : 0x00000002 +PIPE_ACCESS_DUPLEX : DWORD : 0x00000003 +PIPE_WAIT : DWORD : 0x00000000 +PIPE_TYPE_BYTE : DWORD : 0x00000000 +PIPE_TYPE_MESSAGE : DWORD : 0x00000004 +PIPE_REJECT_REMOTE_CLIENTS : DWORD : 0x00000008 +PIPE_READMODE_BYTE : DWORD : 0x00000000 +PIPE_READMODE_MESSAGE : DWORD : 0x00000002 +PIPE_ACCEPT_REMOTE_CLIENTS : DWORD : 0x00000000 FD_SETSIZE :: 64 @@ -2739,10 +2767,10 @@ HANDLE_FLAG_INHERIT: DWORD : 0x00000001 HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002 GENERIC_MAPPING :: struct { - GenericRead: ACCESS_MASK, - GenericWrite: ACCESS_MASK, + GenericRead: ACCESS_MASK, + GenericWrite: ACCESS_MASK, GenericExecute: ACCESS_MASK, - GenericAll: ACCESS_MASK, + GenericAll: ACCESS_MASK, } PGENERIC_MAPPING :: ^GENERIC_MAPPING @@ -2758,14 +2786,14 @@ ANYSIZE_ARRAY :: 1 PLUID_AND_ATTRIBUTES :: ^LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES :: struct { - Luid: LUID, + Luid: LUID, Attributes: DWORD, } PRIVILEGE_SET :: struct { PrivilegeCount: DWORD, - Control: DWORD, - Privilege: [ANYSIZE_ARRAY]LUID_AND_ATTRIBUTES, + Control: DWORD, + Privilege: [ANYSIZE_ARRAY]LUID_AND_ATTRIBUTES `fmt:"v,PrivilegeCount"`, } PPRIVILEGE_SET :: ^PRIVILEGE_SET @@ -2780,7 +2808,8 @@ TOKEN_ADJUST_GROUPS :: 0x0040 TOKEN_ADJUST_DEFAULT :: 0x0080 TOKEN_ADJUST_SESSIONID :: 0x0100 -TOKEN_ALL_ACCESS_P :: STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY |\ +TOKEN_ALL_ACCESS_P :: \ + STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT TOKEN_ALL_ACCESS :: TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_SESSIONID @@ -2803,8 +2832,8 @@ CP_UTF8 :: 65001 // UTF-8 translation LCID :: DWORD LANGID :: WORD -LANG_NEUTRAL :: 0x00 -LANG_INVARIANT :: 0x7f +LANG_NEUTRAL :: 0x00 +LANG_INVARIANT :: 0x7f SUBLANG_NEUTRAL :: 0x00 // language neutral SUBLANG_DEFAULT :: 0x01 // user default @@ -2815,7 +2844,7 @@ WC_ERR_INVALID_CHARS :: 128 MAX_PATH :: 0x00000104 MAX_PATH_WIDE :: 0x8000 -INVALID_FILE_ATTRIBUTES :: DWORD(0xffff_ffff) +INVALID_FILE_ATTRIBUTES :: DWORD(0xffff_ffff) FILE_TYPE_DISK :: 0x0001 FILE_TYPE_CHAR :: 0x0002 @@ -2826,33 +2855,33 @@ POINT :: struct {x, y: LONG} PWINDOWPOS :: ^WINDOWPOS WINDOWPOS :: struct { - hwnd: HWND, + hwnd: HWND, hwndInsertAfter: HWND, - x: c_int, - y: c_int, - cx: c_int, - cy: c_int, + x: c_int, + y: c_int, + cx: c_int, + cy: c_int, flags: UINT, } when size_of(uintptr) == 4 { WSADATA :: struct { - wVersion: WORD, - wHighVersion: WORD, - szDescription: [WSADESCRIPTION_LEN + 1]u8, + wVersion: WORD, + wHighVersion: WORD, + szDescription: [WSADESCRIPTION_LEN + 1]u8, szSystemStatus: [WSASYS_STATUS_LEN + 1]u8, - iMaxSockets: u16, - iMaxUdpDg: u16, - lpVendorInfo: ^u8, + iMaxSockets: u16, + iMaxUdpDg: u16, + lpVendorInfo: [^]u8, } } else when size_of(uintptr) == 8 { WSADATA :: struct { - wVersion: WORD, - wHighVersion: WORD, - iMaxSockets: u16, - iMaxUdpDg: u16, - lpVendorInfo: ^u8, - szDescription: [WSADESCRIPTION_LEN + 1]u8, + wVersion: WORD, + wHighVersion: WORD, + iMaxSockets: u16, + iMaxUdpDg: u16, + lpVendorInfo: ^u8, + szDescription: [WSADESCRIPTION_LEN + 1]u8, szSystemStatus: [WSASYS_STATUS_LEN + 1]u8, } } else { @@ -2861,71 +2890,71 @@ when size_of(uintptr) == 4 { WSABUF :: struct { len: ULONG, - buf: ^CHAR, + buf: [^]CHAR `fmt"q,len"`, } WSAPROTOCOL_INFO :: struct { - dwServiceFlags1: DWORD, - dwServiceFlags2: DWORD, - dwServiceFlags3: DWORD, - dwServiceFlags4: DWORD, - dwProviderFlags: DWORD, - ProviderId: GUID, - dwCatalogEntryId: DWORD, - ProtocolChain: WSAPROTOCOLCHAIN, - iVersion: c_int, - iAddressFamily: c_int, - iMaxSockAddr: c_int, - iMinSockAddr: c_int, - iSocketType: c_int, - iProtocol: c_int, + dwServiceFlags1: DWORD, + dwServiceFlags2: DWORD, + dwServiceFlags3: DWORD, + dwServiceFlags4: DWORD, + dwProviderFlags: DWORD, + ProviderId: GUID, + dwCatalogEntryId: DWORD, + ProtocolChain: WSAPROTOCOLCHAIN, + iVersion: c_int, + iAddressFamily: c_int, + iMaxSockAddr: c_int, + iMinSockAddr: c_int, + iSocketType: c_int, + iProtocol: c_int, iProtocolMaxOffset: c_int, - iNetworkByteOrder: c_int, - iSecurityScheme: c_int, - dwMessageSize: DWORD, + iNetworkByteOrder: c_int, + iSecurityScheme: c_int, + dwMessageSize: DWORD, dwProviderReserved: DWORD, - szProtocol: [WSAPROTOCOL_LEN + 1]u16, + szProtocol: [WSAPROTOCOL_LEN + 1]u16, } WIN32_FILE_ATTRIBUTE_DATA :: struct { dwFileAttributes: DWORD, - ftCreationTime: FILETIME, + ftCreationTime: FILETIME, ftLastAccessTime: FILETIME, - ftLastWriteTime: FILETIME, - nFileSizeHigh: DWORD, - nFileSizeLow: DWORD, + ftLastWriteTime: FILETIME, + nFileSizeHigh: DWORD, + nFileSizeLow: DWORD, } FILE_INFO_BY_HANDLE_CLASS :: enum c_int { - FileBasicInfo = 0, - FileStandardInfo = 1, - FileNameInfo = 2, - FileRenameInfo = 3, - FileDispositionInfo = 4, - FileAllocationInfo = 5, - FileEndOfFileInfo = 6, - FileStreamInfo = 7, - FileCompressionInfo = 8, - FileAttributeTagInfo = 9, - FileIdBothDirectoryInfo = 10, // 0xA + FileBasicInfo = 0, + FileStandardInfo = 1, + FileNameInfo = 2, + FileRenameInfo = 3, + FileDispositionInfo = 4, + FileAllocationInfo = 5, + FileEndOfFileInfo = 6, + FileStreamInfo = 7, + FileCompressionInfo = 8, + FileAttributeTagInfo = 9, + FileIdBothDirectoryInfo = 10, // 0xA FileIdBothDirectoryRestartInfo = 11, // 0xB - FileIoPriorityHintInfo = 12, // 0xC - FileRemoteProtocolInfo = 13, // 0xD - FileFullDirectoryInfo = 14, // 0xE - FileFullDirectoryRestartInfo = 15, // 0xF - FileStorageInfo = 16, // 0x10 - FileAlignmentInfo = 17, // 0x11 - FileIdInfo = 18, // 0x12 - FileIdExtdDirectoryInfo = 19, // 0x13 + FileIoPriorityHintInfo = 12, // 0xC + FileRemoteProtocolInfo = 13, // 0xD + FileFullDirectoryInfo = 14, // 0xE + FileFullDirectoryRestartInfo = 15, // 0xF + FileStorageInfo = 16, // 0x10 + FileAlignmentInfo = 17, // 0x11 + FileIdInfo = 18, // 0x12 + FileIdExtdDirectoryInfo = 19, // 0x13 FileIdExtdDirectoryRestartInfo = 20, // 0x14 MaximumFileInfoByHandlesClass, } FILE_BASIC_INFO :: struct { - CreationTime: LARGE_INTEGER, + CreationTime: LARGE_INTEGER, LastAccessTime: LARGE_INTEGER, - LastWriteTime: LARGE_INTEGER, - ChangeTime: LARGE_INTEGER, + LastWriteTime: LARGE_INTEGER, + ChangeTime: LARGE_INTEGER, FileAttributes: DWORD, } @@ -2941,39 +2970,39 @@ FILE_NOTIFY_INFORMATION :: struct { } REPARSE_DATA_BUFFER :: struct { - ReparseTag: c_uint, + ReparseTag: c_uint, ReparseDataLength: c_ushort, - Reserved: c_ushort, - rest: [0]byte, + Reserved: c_ushort, + rest: [0]byte, } SYMBOLIC_LINK_REPARSE_BUFFER :: struct { SubstituteNameOffset: c_ushort, SubstituteNameLength: c_ushort, - PrintNameOffset: c_ushort, - PrintNameLength: c_ushort, - Flags: c_ulong, - PathBuffer: WCHAR, + PrintNameOffset: c_ushort, + PrintNameLength: c_ushort, + Flags: c_ulong, + PathBuffer: WCHAR, } MOUNT_POINT_REPARSE_BUFFER :: struct { SubstituteNameOffset: c_ushort, SubstituteNameLength: c_ushort, - PrintNameOffset: c_ushort, - PrintNameLength: c_ushort, - PathBuffer: WCHAR, + PrintNameOffset: c_ushort, + PrintNameLength: c_ushort, + PathBuffer: WCHAR, } LPPROGRESS_ROUTINE :: #type proc "system" ( - TotalFileSize: LARGE_INTEGER, - TotalBytesTransferred: LARGE_INTEGER, - StreamSize: LARGE_INTEGER, + TotalFileSize: LARGE_INTEGER, + TotalBytesTransferred: LARGE_INTEGER, + StreamSize: LARGE_INTEGER, StreamBytesTransferred: LARGE_INTEGER, - dwStreamNumber: DWORD, - dwCallbackReason: DWORD, - hSourceFile: HANDLE, - hDestinationFile: HANDLE, - lpData: LPVOID, + dwStreamNumber: DWORD, + dwCallbackReason: DWORD, + hSourceFile: HANDLE, + hDestinationFile: HANDLE, + lpData: LPVOID, ) -> DWORD CONDITION_VARIABLE :: struct { @@ -2984,21 +3013,36 @@ SRWLOCK :: struct { } CRITICAL_SECTION :: struct { CriticalSectionDebug: LPVOID, - LockCount: LONG, - RecursionCount: LONG, - OwningThread: HANDLE, - LockSemaphore: HANDLE, - SpinCount: ULONG_PTR, + LockCount: LONG, + RecursionCount: LONG, + OwningThread: HANDLE, + LockSemaphore: HANDLE, + SpinCount: ULONG_PTR, } +SYNCHRONIZATION_BARRIER :: struct { + Reserved1: DWORD, + Reserved2: DWORD, + Reserved3: [2]ULONG_PTR, + Reserved4: DWORD, + Reserved5: DWORD, +} + +SYNCHRONIZATION_BARRIER_FLAG :: enum { + SPIN_ONLY = 0, + BLOCK_ONLY = 1, + NO_DELETE = 2, +} +SYNCHRONIZATION_BARRIER_FLAGS :: distinct bit_set[SYNCHRONIZATION_BARRIER_FLAG; DWORD] + REPARSE_MOUNTPOINT_DATA_BUFFER :: struct { - ReparseTag: DWORD, - ReparseDataLength: DWORD, - Reserved: WORD, - ReparseTargetLength: WORD, + ReparseTag: DWORD, + ReparseDataLength: DWORD, + Reserved: WORD, + ReparseTargetLength: WORD, ReparseTargetMaximumLength: WORD, - Reserved1: WORD, - ReparseTarget: WCHAR, + Reserved1: WORD, + ReparseTarget: WCHAR, } GUID :: struct { @@ -3021,12 +3065,12 @@ LPGUID :: ^GUID LPCGUID :: ^GUID REFIID :: ^GUID -REFGUID :: GUID -IID :: GUID -LPIID :: ^IID -CLSID :: GUID +REFGUID :: GUID +IID :: GUID +LPIID :: ^IID +CLSID :: GUID REFCLSID :: ^CLSID -LPCLSID :: ^CLSID +LPCLSID :: ^CLSID CLSCTX_INPROC_SERVER :: 0x1 CLSCTX_INPROC_HANDLER :: 0x2 @@ -3059,46 +3103,46 @@ CLSCTX_PS_DLL :: 0x80000000 CLSCTX_ALL :: CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER WSAPROTOCOLCHAIN :: struct { - ChainLen: c_int, - ChainEntries: [MAX_PROTOCOL_CHAIN]DWORD, + ChainLen: c_int, + ChainEntries: [MAX_PROTOCOL_CHAIN]DWORD `fmt:"v,ChainLen"`, } SECURITY_ATTRIBUTES :: struct { - nLength: DWORD, + nLength: DWORD, lpSecurityDescriptor: LPVOID, - bInheritHandle: BOOL, + bInheritHandle: BOOL, } PROCESS_INFORMATION :: struct { - hProcess: HANDLE, - hThread: HANDLE, + hProcess: HANDLE, + hThread: HANDLE, dwProcessId: DWORD, - dwThreadId: DWORD, + dwThreadId: DWORD, } STARTUPINFOW :: struct { - cb: DWORD, - lpReserved: LPWSTR, - lpDesktop: LPWSTR, - lpTitle: LPWSTR, - dwX: DWORD, - dwY: DWORD, - dwXSize: DWORD, - dwYSize: DWORD, - dwXCountChars: DWORD, - dwYCountChars: DWORD, + cb: DWORD, + lpReserved: LPWSTR, + lpDesktop: LPWSTR, + lpTitle: LPWSTR, + dwX: DWORD, + dwY: DWORD, + dwXSize: DWORD, + dwYSize: DWORD, + dwXCountChars: DWORD, + dwYCountChars: DWORD, dwFillAttribute: DWORD, - dwFlags: DWORD, - wShowWindow: WORD, - cbReserved2: WORD, - lpReserved2: LPBYTE, - hStdInput: HANDLE, - hStdOutput: HANDLE, - hStdError: HANDLE, + dwFlags: DWORD, + wShowWindow: WORD, + cbReserved2: WORD, + lpReserved2: LPBYTE, + hStdInput: HANDLE, + hStdOutput: HANDLE, + hStdError: HANDLE, } FILETIME :: struct { - dwLowDateTime: DWORD, + dwLowDateTime: DWORD, dwHighDateTime: DWORD, } @@ -3115,6 +3159,7 @@ OBJECT_ATTRIBUTES :: struct { SecurityDescriptor: rawptr, SecurityQualityOfService: rawptr, } +POBJECT_ATTRIBUTES :: ^OBJECT_ATTRIBUTES PUNICODE_STRING :: ^UNICODE_STRING UNICODE_STRING :: struct { @@ -3124,10 +3169,15 @@ UNICODE_STRING :: struct { } OVERLAPPED :: struct { - Internal: ^c_ulong, + Internal: ^c_ulong, InternalHigh: ^c_ulong, - Offset: DWORD, - OffsetHigh: DWORD, + using _: struct #raw_union { + using _: struct { + Offset: DWORD, + OffsetHigh: DWORD, + }, + OffsetFull: u64, // Convenience field to set Offset and OffsetHigh with one value. + }, hEvent: HANDLE, } @@ -3139,11 +3189,18 @@ OVERLAPPED_ENTRY :: struct { } LPOVERLAPPED_COMPLETION_ROUTINE :: #type proc "system" ( - dwErrorCode: DWORD, + dwErrorCode: DWORD, dwNumberOfBytesTransfered: DWORD, - lpOverlapped: LPOVERLAPPED, + lpOverlapped: LPOVERLAPPED, ) +READ_DIRECTORY_NOTIFY_INFORMATION_CLASS :: enum c_int { + ReadDirectoryNotifyInformation = 1, + ReadDirectoryNotifyExtendedInformation, + ReadDirectoryNotifyFullInformation, + ReadDirectoryNotifyMaximumInformation, +} + ADDRESS_MODE :: enum c_int { AddrMode1616, AddrMode1632, @@ -3164,7 +3221,7 @@ fd_set :: struct { } timeval :: struct { - tv_sec: c_long, + tv_sec: c_long, tv_usec: c_long, } @@ -3199,145 +3256,145 @@ STATUS_PRIVILEGED_INSTRUCTION :: 0xC0000096 EXCEPTION_RECORD :: struct { - ExceptionCode: DWORD, - ExceptionFlags: DWORD, - ExceptionRecord: ^EXCEPTION_RECORD, - ExceptionAddress: LPVOID, - NumberParameters: DWORD, - ExceptionInformation: [EXCEPTION_MAXIMUM_PARAMETERS]LPVOID, + ExceptionCode: DWORD, + ExceptionFlags: DWORD, + ExceptionRecord: ^EXCEPTION_RECORD, + ExceptionAddress: LPVOID, + NumberParameters: DWORD, + ExceptionInformation: [EXCEPTION_MAXIMUM_PARAMETERS]LPVOID `fmt:"v,NumberParameters"`, } CONTEXT :: struct { - P1Home: DWORD64, - P2Home: DWORD64, - P3Home: DWORD64, - P4Home: DWORD64, - P5Home: DWORD64, - P6Home: DWORD64, + P1Home: DWORD64, + P2Home: DWORD64, + P3Home: DWORD64, + P4Home: DWORD64, + P5Home: DWORD64, + P6Home: DWORD64, ContextFlags: DWORD, - MxCsr: DWORD, - SegCs: WORD, - SegDs: WORD, - SegEs: WORD, - SegFs: WORD, - SegGs: WORD, - SegSs: WORD, - EFlags: DWORD, - Dr0: DWORD64, - Dr1: DWORD64, - Dr2: DWORD64, - Dr3: DWORD64, - Dr6: DWORD64, - Dr7: DWORD64, - Rax: DWORD64, - Rcx: DWORD64, - Rdx: DWORD64, - Rbx: DWORD64, - Rsp: DWORD64, - Rbp: DWORD64, - Rsi: DWORD64, - Rdi: DWORD64, - R8: DWORD64, - R9: DWORD64, - R10: DWORD64, - R11: DWORD64, - R12: DWORD64, - R13: DWORD64, - R14: DWORD64, - R15: DWORD64, - Rip: DWORD64, - _: struct #raw_union { + MxCsr: DWORD, + SegCs: WORD, + SegDs: WORD, + SegEs: WORD, + SegFs: WORD, + SegGs: WORD, + SegSs: WORD, + EFlags: DWORD, + Dr0: DWORD64, + Dr1: DWORD64, + Dr2: DWORD64, + Dr3: DWORD64, + Dr6: DWORD64, + Dr7: DWORD64, + Rax: DWORD64, + Rcx: DWORD64, + Rdx: DWORD64, + Rbx: DWORD64, + Rsp: DWORD64, + Rbp: DWORD64, + Rsi: DWORD64, + Rdi: DWORD64, + R8: DWORD64, + R9: DWORD64, + R10: DWORD64, + R11: DWORD64, + R12: DWORD64, + R13: DWORD64, + R14: DWORD64, + R15: DWORD64, + Rip: DWORD64, + using _: struct #raw_union { FltSave: XMM_SAVE_AREA32, - Q: [16]NEON128, - D: [32]ULONGLONG, - _: struct { + Q: [16]NEON128, + D: [32]ULONGLONG, + using _: struct { Header: [2]M128A, Legacy: [8]M128A, - Xmm0: M128A, - Xmm1: M128A, - Xmm2: M128A, - Xmm3: M128A, - Xmm4: M128A, - Xmm5: M128A, - Xmm6: M128A, - Xmm7: M128A, - Xmm8: M128A, - Xmm9: M128A, - Xmm10: M128A, - Xmm11: M128A, - Xmm12: M128A, - Xmm13: M128A, - Xmm14: M128A, - Xmm15: M128A, + Xmm0: M128A, + Xmm1: M128A, + Xmm2: M128A, + Xmm3: M128A, + Xmm4: M128A, + Xmm5: M128A, + Xmm6: M128A, + Xmm7: M128A, + Xmm8: M128A, + Xmm9: M128A, + Xmm10: M128A, + Xmm11: M128A, + Xmm12: M128A, + Xmm13: M128A, + Xmm14: M128A, + Xmm15: M128A, }, S: [32]DWORD, }, - VectorRegister: [26]M128A, - VectorControl: DWORD64, - DebugControl: DWORD64, - LastBranchToRip: DWORD64, - LastBranchFromRip: DWORD64, - LastExceptionToRip: DWORD64, + VectorRegister: [26]M128A, + VectorControl: DWORD64, + DebugControl: DWORD64, + LastBranchToRip: DWORD64, + LastBranchFromRip: DWORD64, + LastExceptionToRip: DWORD64, LastExceptionFromRip: DWORD64, } -PCONTEXT :: ^CONTEXT +PCONTEXT :: ^CONTEXT LPCONTEXT :: ^CONTEXT when size_of(uintptr) == 32 { XSAVE_FORMAT :: struct #align(16) { - ControlWord: WORD, - StatusWord: WORD, - TagWord: BYTE, - Reserved1: BYTE, - ErrorOpcode: WORD, - ErrorOffset: DWORD, - ErrorSelector: WORD, - Reserved2: WORD, - DataOffset: DWORD, - DataSelector: WORD, - Reserved3: WORD, - MxCsr: DWORD, - MxCsr_Mask: DWORD, + ControlWord: WORD, + StatusWord: WORD, + TagWord: BYTE, + Reserved1: BYTE, + ErrorOpcode: WORD, + ErrorOffset: DWORD, + ErrorSelector: WORD, + Reserved2: WORD, + DataOffset: DWORD, + DataSelector: WORD, + Reserved3: WORD, + MxCsr: DWORD, + MxCsr_Mask: DWORD, FloatRegisters: [8]M128A, // 32-bit specific - XmmRegisters: [8]M128A, - Reserved4: [192]BYTE, - StackControl: [7]DWORD, - Cr0NpxState: DWORD, + XmmRegisters: [8]M128A, + Reserved4: [192]BYTE, + StackControl: [7]DWORD, + Cr0NpxState: DWORD, } } else { XSAVE_FORMAT :: struct #align(16) { - ControlWord: WORD, - StatusWord: WORD, - TagWord: BYTE, - Reserved1: BYTE, - ErrorOpcode: WORD, - ErrorOffset: DWORD, - ErrorSelector: WORD, - Reserved2: WORD, - DataOffset: DWORD, - DataSelector: WORD, - Reserved3: WORD, - MxCsr: DWORD, - MxCsr_Mask: DWORD, + ControlWord: WORD, + StatusWord: WORD, + TagWord: BYTE, + Reserved1: BYTE, + ErrorOpcode: WORD, + ErrorOffset: DWORD, + ErrorSelector: WORD, + Reserved2: WORD, + DataOffset: DWORD, + DataSelector: WORD, + Reserved3: WORD, + MxCsr: DWORD, + MxCsr_Mask: DWORD, FloatRegisters: [8]M128A, // 64-bit specific - XmmRegisters: [16]M128A, - Reserved4: [96]BYTE, + XmmRegisters: [16]M128A, + Reserved4: [96]BYTE, } } XMM_SAVE_AREA32 :: XSAVE_FORMAT M128A :: struct { - Low: ULONGLONG, + Low: ULONGLONG, High: LONGLONG, } NEON128 :: struct { - Low: ULONGLONG, + Low: ULONGLONG, High: LONGLONG, } @@ -3354,9 +3411,21 @@ CONSOLE_READCONSOLE_CONTROL :: struct { dwCtrlWakeupMask: ULONG, dwControlKeyState: ULONG, } - PCONSOLE_READCONSOLE_CONTROL :: ^CONSOLE_READCONSOLE_CONTROL +CONSOLE_SCREEN_BUFFER_INFOEX :: struct { + cbSize: ULONG, + dwSize: COORD, + dwCursorPosition: COORD, + wAttributes: WORD, + srWindow: SMALL_RECT, + dwMaximumWindowSize: COORD, + wPopupAttributes: WORD, + bFullscreenSupported: BOOL, + ColorTable: [16]COLORREF, +} +PCONSOLE_SCREEN_BUFFER_INFOEX :: ^CONSOLE_SCREEN_BUFFER_INFOEX + BY_HANDLE_FILE_INFORMATION :: struct { dwFileAttributes: DWORD, ftCreationTime: FILETIME, @@ -3369,7 +3438,6 @@ BY_HANDLE_FILE_INFORMATION :: struct { nFileIndexHigh: DWORD, nFileIndexLow: DWORD, } - LPBY_HANDLE_FILE_INFORMATION :: ^BY_HANDLE_FILE_INFORMATION FILE_STANDARD_INFO :: struct { @@ -3385,6 +3453,19 @@ FILE_ATTRIBUTE_TAG_INFO :: struct { ReparseTag: DWORD, } +// getaddrinfo flags https://learn.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoa +AI_PASSIVE :: 0x01 +AI_CANONNAME :: 0x02 +AI_NUMERICHOST :: 0x04 +AI_ALL :: 0x0100 +AI_ADDRCONFIG :: 0x0400 +AI_V4MAPPED :: 0x0800 +AI_NON_AUTHORITATIVE :: 0x04000 +AI_SECURE :: 0x08000 +AI_RETURN_PREFERRED_NAMES :: 0x010000 +AI_FQDN :: 0x00020000 +AI_FILESERVER :: 0x00040000 + PADDRINFOEXW :: ^ADDRINFOEXW LPADDRINFOEXW :: ^ADDRINFOEXW ADDRINFOEXW :: struct { @@ -3402,9 +3483,9 @@ ADDRINFOEXW :: struct { } LPLOOKUPSERVICE_COMPLETION_ROUTINE :: #type proc "system" ( - dwErrorCode: DWORD, + dwErrorCode: DWORD, dwNumberOfBytesTransfered: DWORD, - lpOverlapped: LPOVERLAPPED, + lpOverlapped: LPOVERLAPPED, ) @@ -3414,18 +3495,18 @@ SYSTEM_INFO :: struct { dwOemID: DWORD, using _: struct #raw_union { wProcessorArchitecture: WORD, - wReserved: WORD, // reserved + wReserved: WORD, // reserved }, }, - dwPageSize: DWORD, + dwPageSize: DWORD, lpMinimumApplicationAddress: LPVOID, lpMaximumApplicationAddress: LPVOID, - dwActiveProcessorMask: DWORD_PTR, - dwNumberOfProcessors: DWORD, - dwProcessorType: DWORD, - dwAllocationGranularity: DWORD, - wProcessorLevel: WORD, - wProcessorRevision: WORD, + dwActiveProcessorMask: DWORD_PTR, + dwNumberOfProcessors: DWORD, + dwProcessorType: DWORD, + dwAllocationGranularity: DWORD, + wProcessorLevel: WORD, + wProcessorRevision: WORD, } // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw @@ -3462,12 +3543,12 @@ LoadLibraryEx_Flags :: distinct bit_set[LoadLibraryEx_Flag] // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-quota_limits // Used in LogonUserExW PQUOTA_LIMITS :: struct { - PagedPoolLimit: SIZE_T, - NonPagedPoolLimit: SIZE_T, + PagedPoolLimit: SIZE_T, + NonPagedPoolLimit: SIZE_T, MinimumWorkingSetSize: SIZE_T, MaximumWorkingSetSize: SIZE_T, - PagefileLimit: SIZE_T, - TimeLimit: LARGE_INTEGER, + PagefileLimit: SIZE_T, + TimeLimit: LARGE_INTEGER, } Logon32_Type :: enum DWORD { @@ -3492,14 +3573,14 @@ Logon32_Provider :: enum DWORD { // Used in LoadUserProfileW PROFILEINFOW :: struct { - dwSize: DWORD, - dwFlags: DWORD, - lpUserName: LPWSTR, + dwSize: DWORD, + dwFlags: DWORD, + lpUserName: LPWSTR, lpProfilePath: LPWSTR, lpDefaultPath: LPWSTR, - lpServerName: LPWSTR, - lpPolicyPath: LPWSTR, - hProfile: HANDLE, + lpServerName: LPWSTR, + lpPolicyPath: LPWSTR, + hProfile: HANDLE, } SECURITY_MAX_SID_SIZE :: 68 @@ -3556,14 +3637,14 @@ USER_INFO_FLAG :: enum DWORD { USER_INFO_FLAGS :: distinct bit_set[USER_INFO_FLAG] USER_INFO_1 :: struct #packed { - name: LPWSTR, - password: LPWSTR, // Max password length is defined in LM20_PWLEN. + name: LPWSTR, + password: LPWSTR, // Max password length is defined in LM20_PWLEN. password_age: DWORD, - priv: USER_PRIV, - home_dir: LPWSTR, - comment: LPWSTR, - flags: USER_INFO_FLAGS, - script_path: LPWSTR, + priv: USER_PRIV, + home_dir: LPWSTR, + comment: LPWSTR, + flags: USER_INFO_FLAGS, + script_path: LPWSTR, } // #assert(size_of(USER_INFO_1) == 50) @@ -3572,320 +3653,320 @@ LOCALGROUP_MEMBERS_INFO_0 :: struct #packed { } NET_API_STATUS :: enum DWORD { - Success = 0, - ERROR_ACCESS_DENIED = 5, - MemberInAlias = 1378, - NetNotStarted = 2102, - UnknownServer = 2103, - ShareMem = 2104, - NoNetworkResource = 2105, - RemoteOnly = 2106, - DevNotRedirected = 2107, - ServerNotStarted = 2114, - ItemNotFound = 2115, - UnknownDevDir = 2116, - RedirectedPath = 2117, - DuplicateShare = 2118, - NoRoom = 2119, - TooManyItems = 2121, - InvalidMaxUsers = 2122, - BufTooSmall = 2123, - RemoteErr = 2127, - LanmanIniError = 2131, - NetworkError = 2136, - WkstaInconsistentState = 2137, - WkstaNotStarted = 2138, - BrowserNotStarted = 2139, - InternalError = 2140, - BadTransactConfig = 2141, - InvalidAPI = 2142, - BadEventName = 2143, - DupNameReboot = 2144, - CfgCompNotFound = 2146, - CfgParamNotFound = 2147, - LineTooLong = 2149, - QNotFound = 2150, - JobNotFound = 2151, - DestNotFound = 2152, - DestExists = 2153, - QExists = 2154, - QNoRoom = 2155, - JobNoRoom = 2156, - DestNoRoom = 2157, - DestIdle = 2158, - DestInvalidOp = 2159, - ProcNoRespond = 2160, - SpoolerNotLoaded = 2161, - DestInvalidState = 2162, - QInvalidState = 2163, - JobInvalidState = 2164, - SpoolNoMemory = 2165, - DriverNotFound = 2166, - DataTypeInvalid = 2167, - ProcNotFound = 2168, - ServiceTableLocked = 2180, - ServiceTableFull = 2181, - ServiceInstalled = 2182, - ServiceEntryLocked = 2183, - ServiceNotInstalled = 2184, - BadServiceName = 2185, - ServiceCtlTimeout = 2186, - ServiceCtlBusy = 2187, - BadServiceProgName = 2188, - ServiceNotCtrl = 2189, - ServiceKillProc = 2190, - ServiceCtlNotValid = 2191, - NotInDispatchTbl = 2192, - BadControlRecv = 2193, - ServiceNotStarting = 2194, - AlreadyLoggedOn = 2200, - NotLoggedOn = 2201, - BadUsername = 2202, - BadPassword = 2203, - UnableToAddName_W = 2204, - UnableToAddName_F = 2205, - UnableToDelName_W = 2206, - UnableToDelName_F = 2207, - LogonsPaused = 2209, - LogonServerConflict = 2210, - LogonNoUserPath = 2211, - LogonScriptError = 2212, - StandaloneLogon = 2214, - LogonServerNotFound = 2215, - LogonDomainExists = 2216, - NonValidatedLogon = 2217, - ACFNotFound = 2219, - GroupNotFound = 2220, - UserNotFound = 2221, - ResourceNotFound = 2222, - GroupExists = 2223, - UserExists = 2224, - ResourceExists = 2225, - NotPrimary = 2226, - ACFNotLoaded = 2227, - ACFNoRoom = 2228, - ACFFileIOFail = 2229, - ACFTooManyLists = 2230, - UserLogon = 2231, - ACFNoParent = 2232, - CanNotGrowSegment = 2233, - SpeGroupOp = 2234, - NotInCache = 2235, - UserInGroup = 2236, - UserNotInGroup = 2237, - AccountUndefined = 2238, - AccountExpired = 2239, - InvalidWorkstation = 2240, - InvalidLogonHours = 2241, - PasswordExpired = 2242, - PasswordCantChange = 2243, - PasswordHistConflict = 2244, - PasswordTooShort = 2245, - PasswordTooRecent = 2246, - InvalidDatabase = 2247, - DatabaseUpToDate = 2248, - SyncRequired = 2249, - UseNotFound = 2250, - BadAsgType = 2251, - DeviceIsShared = 2252, - SameAsComputerName = 2253, - NoComputerName = 2270, - MsgAlreadyStarted = 2271, - MsgInitFailed = 2272, - NameNotFound = 2273, - AlreadyForwarded = 2274, - AddForwarded = 2275, - AlreadyExists = 2276, - TooManyNames = 2277, - DelComputerName = 2278, - LocalForward = 2279, - GrpMsgProcessor = 2280, - PausedRemote = 2281, - BadReceive = 2282, - NameInUse = 2283, - MsgNotStarted = 2284, - NotLocalName = 2285, - NoForwardName = 2286, - RemoteFull = 2287, - NameNotForwarded = 2288, - TruncatedBroadcast = 2289, - InvalidDevice = 2294, - WriteFault = 2295, - DuplicateName = 2297, - DeleteLater = 2298, - IncompleteDel = 2299, - MultipleNets = 2300, - NetNameNotFound = 2310, - DeviceNotShared = 2311, - ClientNameNotFound = 2312, - FileIdNotFound = 2314, - ExecFailure = 2315, - TmpFile = 2316, - TooMuchData = 2317, - DeviceShareConflict = 2318, - BrowserTableIncomplete = 2319, - NotLocalDomain = 2320, - IsDfsShare = 2321, - DevInvalidOpCode = 2331, - DevNotFound = 2332, - DevNotOpen = 2333, - BadQueueDevString = 2334, - BadQueuePriority = 2335, - NoCommDevs = 2337, - QueueNotFound = 2338, - BadDevString = 2340, - BadDev = 2341, - InUseBySpooler = 2342, - CommDevInUse = 2343, - InvalidComputer = 2351, - MaxLenExceeded = 2354, - BadComponent = 2356, - CantType = 2357, - TooManyEntries = 2362, - ProfileFileTooBig = 2370, - ProfileOffset = 2371, - ProfileCleanup = 2372, - ProfileUnknownCmd = 2373, - ProfileLoadErr = 2374, - ProfileSaveErr = 2375, - LogOverflow = 2377, - LogFileChanged = 2378, - LogFileCorrupt = 2379, - SourceIsDir = 2380, - BadSource = 2381, - BadDest = 2382, - DifferentServers = 2383, - RunSrvPaused = 2385, - ErrCommRunSrv = 2389, - ErrorExecingGhost = 2391, - ShareNotFound = 2392, - InvalidLana = 2400, - OpenFiles = 2401, - ActiveConns = 2402, - BadPasswordCore = 2403, - DevInUse = 2404, - LocalDrive = 2405, - AlertExists = 2430, - TooManyAlerts = 2431, - NoSuchAlert = 2432, - BadRecipient = 2433, - AcctLimitExceeded = 2434, - InvalidLogSeek = 2440, - BadUasConfig = 2450, - InvalidUASOp = 2451, - LastAdmin = 2452, - DCNotFound = 2453, - LogonTrackingError = 2454, - NetlogonNotStarted = 2455, - CanNotGrowUASFile = 2456, - TimeDiffAtDC = 2457, - PasswordMismatch = 2458, - NoSuchServer = 2460, - NoSuchSession = 2461, - NoSuchConnection = 2462, - TooManyServers = 2463, - TooManySessions = 2464, - TooManyConnections = 2465, - TooManyFiles = 2466, - NoAlternateServers = 2467, - TryDownLevel = 2470, - UPSDriverNotStarted = 2480, - UPSInvalidConfig = 2481, - UPSInvalidCommPort = 2482, - UPSSignalAsserted = 2483, - UPSShutdownFailed = 2484, - BadDosRetCode = 2500, - ProgNeedsExtraMem = 2501, - BadDosFunction = 2502, - RemoteBootFailed = 2503, - BadFileCheckSum = 2504, - NoRplBootSystem = 2505, - RplLoadrNetBiosErr = 2506, - RplLoadrDiskErr = 2507, - ImageParamErr = 2508, - TooManyImageParams = 2509, - NonDosFloppyUsed = 2510, - RplBootRestart = 2511, - RplSrvrCallFailed = 2512, - CantConnectRplSrvr = 2513, - CantOpenImageFile = 2514, - CallingRplSrvr = 2515, - StartingRplBoot = 2516, - RplBootServiceTerm = 2517, - RplBootStartFailed = 2518, - RPL_CONNECTED = 2519, - BrowserConfiguredToNotRun = 2550, - RplNoAdaptersStarted = 2610, - RplBadRegistry = 2611, - RplBadDatabase = 2612, - RplRplfilesShare = 2613, - RplNotRplServer = 2614, - RplCannotEnum = 2615, - RplWkstaInfoCorrupted = 2616, - RplWkstaNotFound = 2617, - RplWkstaNameUnavailable = 2618, - RplProfileInfoCorrupted = 2619, - RplProfileNotFound = 2620, - RplProfileNameUnavailable = 2621, - RplProfileNotEmpty = 2622, - RplConfigInfoCorrupted = 2623, - RplConfigNotFound = 2624, - RplAdapterInfoCorrupted = 2625, - RplInternal = 2626, - RplVendorInfoCorrupted = 2627, - RplBootInfoCorrupted = 2628, - RplWkstaNeedsUserAcct = 2629, - RplNeedsRPLUSERAcct = 2630, - RplBootNotFound = 2631, - RplIncompatibleProfile = 2632, - RplAdapterNameUnavailable = 2633, - RplConfigNotEmpty = 2634, - RplBootInUse = 2635, - RplBackupDatabase = 2636, - RplAdapterNotFound = 2637, - RplVendorNotFound = 2638, - RplVendorNameUnavailable = 2639, - RplBootNameUnavailable = 2640, - RplConfigNameUnavailable = 2641, - DfsInternalCorruption = 2660, - DfsVolumeDataCorrupt = 2661, - DfsNoSuchVolume = 2662, - DfsVolumeAlreadyExists = 2663, - DfsAlreadyShared = 2664, - DfsNoSuchShare = 2665, - DfsNotALeafVolume = 2666, - DfsLeafVolume = 2667, - DfsVolumeHasMultipleServers = 2668, - DfsCantCreateJunctionPoint = 2669, - DfsServerNotDfsAware = 2670, - DfsBadRenamePath = 2671, - DfsVolumeIsOffline = 2672, - DfsNoSuchServer = 2673, - DfsCyclicalName = 2674, - DfsNotSupportedInServerDfs = 2675, - DfsDuplicateService = 2676, + Success = 0, + ERROR_ACCESS_DENIED = 5, + MemberInAlias = 1378, + NetNotStarted = 2102, + UnknownServer = 2103, + ShareMem = 2104, + NoNetworkResource = 2105, + RemoteOnly = 2106, + DevNotRedirected = 2107, + ServerNotStarted = 2114, + ItemNotFound = 2115, + UnknownDevDir = 2116, + RedirectedPath = 2117, + DuplicateShare = 2118, + NoRoom = 2119, + TooManyItems = 2121, + InvalidMaxUsers = 2122, + BufTooSmall = 2123, + RemoteErr = 2127, + LanmanIniError = 2131, + NetworkError = 2136, + WkstaInconsistentState = 2137, + WkstaNotStarted = 2138, + BrowserNotStarted = 2139, + InternalError = 2140, + BadTransactConfig = 2141, + InvalidAPI = 2142, + BadEventName = 2143, + DupNameReboot = 2144, + CfgCompNotFound = 2146, + CfgParamNotFound = 2147, + LineTooLong = 2149, + QNotFound = 2150, + JobNotFound = 2151, + DestNotFound = 2152, + DestExists = 2153, + QExists = 2154, + QNoRoom = 2155, + JobNoRoom = 2156, + DestNoRoom = 2157, + DestIdle = 2158, + DestInvalidOp = 2159, + ProcNoRespond = 2160, + SpoolerNotLoaded = 2161, + DestInvalidState = 2162, + QInvalidState = 2163, + JobInvalidState = 2164, + SpoolNoMemory = 2165, + DriverNotFound = 2166, + DataTypeInvalid = 2167, + ProcNotFound = 2168, + ServiceTableLocked = 2180, + ServiceTableFull = 2181, + ServiceInstalled = 2182, + ServiceEntryLocked = 2183, + ServiceNotInstalled = 2184, + BadServiceName = 2185, + ServiceCtlTimeout = 2186, + ServiceCtlBusy = 2187, + BadServiceProgName = 2188, + ServiceNotCtrl = 2189, + ServiceKillProc = 2190, + ServiceCtlNotValid = 2191, + NotInDispatchTbl = 2192, + BadControlRecv = 2193, + ServiceNotStarting = 2194, + AlreadyLoggedOn = 2200, + NotLoggedOn = 2201, + BadUsername = 2202, + BadPassword = 2203, + UnableToAddName_W = 2204, + UnableToAddName_F = 2205, + UnableToDelName_W = 2206, + UnableToDelName_F = 2207, + LogonsPaused = 2209, + LogonServerConflict = 2210, + LogonNoUserPath = 2211, + LogonScriptError = 2212, + StandaloneLogon = 2214, + LogonServerNotFound = 2215, + LogonDomainExists = 2216, + NonValidatedLogon = 2217, + ACFNotFound = 2219, + GroupNotFound = 2220, + UserNotFound = 2221, + ResourceNotFound = 2222, + GroupExists = 2223, + UserExists = 2224, + ResourceExists = 2225, + NotPrimary = 2226, + ACFNotLoaded = 2227, + ACFNoRoom = 2228, + ACFFileIOFail = 2229, + ACFTooManyLists = 2230, + UserLogon = 2231, + ACFNoParent = 2232, + CanNotGrowSegment = 2233, + SpeGroupOp = 2234, + NotInCache = 2235, + UserInGroup = 2236, + UserNotInGroup = 2237, + AccountUndefined = 2238, + AccountExpired = 2239, + InvalidWorkstation = 2240, + InvalidLogonHours = 2241, + PasswordExpired = 2242, + PasswordCantChange = 2243, + PasswordHistConflict = 2244, + PasswordTooShort = 2245, + PasswordTooRecent = 2246, + InvalidDatabase = 2247, + DatabaseUpToDate = 2248, + SyncRequired = 2249, + UseNotFound = 2250, + BadAsgType = 2251, + DeviceIsShared = 2252, + SameAsComputerName = 2253, + NoComputerName = 2270, + MsgAlreadyStarted = 2271, + MsgInitFailed = 2272, + NameNotFound = 2273, + AlreadyForwarded = 2274, + AddForwarded = 2275, + AlreadyExists = 2276, + TooManyNames = 2277, + DelComputerName = 2278, + LocalForward = 2279, + GrpMsgProcessor = 2280, + PausedRemote = 2281, + BadReceive = 2282, + NameInUse = 2283, + MsgNotStarted = 2284, + NotLocalName = 2285, + NoForwardName = 2286, + RemoteFull = 2287, + NameNotForwarded = 2288, + TruncatedBroadcast = 2289, + InvalidDevice = 2294, + WriteFault = 2295, + DuplicateName = 2297, + DeleteLater = 2298, + IncompleteDel = 2299, + MultipleNets = 2300, + NetNameNotFound = 2310, + DeviceNotShared = 2311, + ClientNameNotFound = 2312, + FileIdNotFound = 2314, + ExecFailure = 2315, + TmpFile = 2316, + TooMuchData = 2317, + DeviceShareConflict = 2318, + BrowserTableIncomplete = 2319, + NotLocalDomain = 2320, + IsDfsShare = 2321, + DevInvalidOpCode = 2331, + DevNotFound = 2332, + DevNotOpen = 2333, + BadQueueDevString = 2334, + BadQueuePriority = 2335, + NoCommDevs = 2337, + QueueNotFound = 2338, + BadDevString = 2340, + BadDev = 2341, + InUseBySpooler = 2342, + CommDevInUse = 2343, + InvalidComputer = 2351, + MaxLenExceeded = 2354, + BadComponent = 2356, + CantType = 2357, + TooManyEntries = 2362, + ProfileFileTooBig = 2370, + ProfileOffset = 2371, + ProfileCleanup = 2372, + ProfileUnknownCmd = 2373, + ProfileLoadErr = 2374, + ProfileSaveErr = 2375, + LogOverflow = 2377, + LogFileChanged = 2378, + LogFileCorrupt = 2379, + SourceIsDir = 2380, + BadSource = 2381, + BadDest = 2382, + DifferentServers = 2383, + RunSrvPaused = 2385, + ErrCommRunSrv = 2389, + ErrorExecingGhost = 2391, + ShareNotFound = 2392, + InvalidLana = 2400, + OpenFiles = 2401, + ActiveConns = 2402, + BadPasswordCore = 2403, + DevInUse = 2404, + LocalDrive = 2405, + AlertExists = 2430, + TooManyAlerts = 2431, + NoSuchAlert = 2432, + BadRecipient = 2433, + AcctLimitExceeded = 2434, + InvalidLogSeek = 2440, + BadUasConfig = 2450, + InvalidUASOp = 2451, + LastAdmin = 2452, + DCNotFound = 2453, + LogonTrackingError = 2454, + NetlogonNotStarted = 2455, + CanNotGrowUASFile = 2456, + TimeDiffAtDC = 2457, + PasswordMismatch = 2458, + NoSuchServer = 2460, + NoSuchSession = 2461, + NoSuchConnection = 2462, + TooManyServers = 2463, + TooManySessions = 2464, + TooManyConnections = 2465, + TooManyFiles = 2466, + NoAlternateServers = 2467, + TryDownLevel = 2470, + UPSDriverNotStarted = 2480, + UPSInvalidConfig = 2481, + UPSInvalidCommPort = 2482, + UPSSignalAsserted = 2483, + UPSShutdownFailed = 2484, + BadDosRetCode = 2500, + ProgNeedsExtraMem = 2501, + BadDosFunction = 2502, + RemoteBootFailed = 2503, + BadFileCheckSum = 2504, + NoRplBootSystem = 2505, + RplLoadrNetBiosErr = 2506, + RplLoadrDiskErr = 2507, + ImageParamErr = 2508, + TooManyImageParams = 2509, + NonDosFloppyUsed = 2510, + RplBootRestart = 2511, + RplSrvrCallFailed = 2512, + CantConnectRplSrvr = 2513, + CantOpenImageFile = 2514, + CallingRplSrvr = 2515, + StartingRplBoot = 2516, + RplBootServiceTerm = 2517, + RplBootStartFailed = 2518, + RPL_CONNECTED = 2519, + BrowserConfiguredToNotRun = 2550, + RplNoAdaptersStarted = 2610, + RplBadRegistry = 2611, + RplBadDatabase = 2612, + RplRplfilesShare = 2613, + RplNotRplServer = 2614, + RplCannotEnum = 2615, + RplWkstaInfoCorrupted = 2616, + RplWkstaNotFound = 2617, + RplWkstaNameUnavailable = 2618, + RplProfileInfoCorrupted = 2619, + RplProfileNotFound = 2620, + RplProfileNameUnavailable = 2621, + RplProfileNotEmpty = 2622, + RplConfigInfoCorrupted = 2623, + RplConfigNotFound = 2624, + RplAdapterInfoCorrupted = 2625, + RplInternal = 2626, + RplVendorInfoCorrupted = 2627, + RplBootInfoCorrupted = 2628, + RplWkstaNeedsUserAcct = 2629, + RplNeedsRPLUSERAcct = 2630, + RplBootNotFound = 2631, + RplIncompatibleProfile = 2632, + RplAdapterNameUnavailable = 2633, + RplConfigNotEmpty = 2634, + RplBootInUse = 2635, + RplBackupDatabase = 2636, + RplAdapterNotFound = 2637, + RplVendorNotFound = 2638, + RplVendorNameUnavailable = 2639, + RplBootNameUnavailable = 2640, + RplConfigNameUnavailable = 2641, + DfsInternalCorruption = 2660, + DfsVolumeDataCorrupt = 2661, + DfsNoSuchVolume = 2662, + DfsVolumeAlreadyExists = 2663, + DfsAlreadyShared = 2664, + DfsNoSuchShare = 2665, + DfsNotALeafVolume = 2666, + DfsLeafVolume = 2667, + DfsVolumeHasMultipleServers = 2668, + DfsCantCreateJunctionPoint = 2669, + DfsServerNotDfsAware = 2670, + DfsBadRenamePath = 2671, + DfsVolumeIsOffline = 2672, + DfsNoSuchServer = 2673, + DfsCyclicalName = 2674, + DfsNotSupportedInServerDfs = 2675, + DfsDuplicateService = 2676, DfsCantRemoveLastServerShare = 2677, - DfsVolumeIsInterDfs = 2678, - DfsInconsistent = 2679, - DfsServerUpgraded = 2680, - DfsDataIsIdentical = 2681, - DfsCantRemoveDfsRoot = 2682, - DfsChildOrParentInDfs = 2683, - DfsInternalError = 2690, - SetupAlreadyJoined = 2691, - SetupNotJoined = 2692, - SetupDomainController = 2693, - DefaultJoinRequired = 2694, - InvalidWorkgroupName = 2695, + DfsVolumeIsInterDfs = 2678, + DfsInconsistent = 2679, + DfsServerUpgraded = 2680, + DfsDataIsIdentical = 2681, + DfsCantRemoveDfsRoot = 2682, + DfsChildOrParentInDfs = 2683, + DfsInternalError = 2690, + SetupAlreadyJoined = 2691, + SetupNotJoined = 2692, + SetupDomainController = 2693, + DefaultJoinRequired = 2694, + InvalidWorkgroupName = 2695, NameUsesIncompatibleCodePage = 2696, - ComputerAccountNotFound = 2697, - PersonalSku = 2698, - SetupCheckDNSConfig = 2699, - PasswordMustChange = 2701, - AccountLockedOut = 2702, - PasswordTooLong = 2703, - PasswordNotComplexEnough = 2704, - PasswordFilterError = 2705, + ComputerAccountNotFound = 2697, + PersonalSku = 2698, + SetupCheckDNSConfig = 2699, + PasswordMustChange = 2701, + AccountLockedOut = 2702, + PasswordTooLong = 2703, + PasswordNotComplexEnough = 2704, + PasswordFilterError = 2705, } @@ -4040,12 +4121,12 @@ IMAGE_DEBUG_DIRECTORY :: struct { IMAGE_DEBUG_TYPE_CODEVIEW :: 2 -SICHINTF :: DWORD -SHCONTF :: DWORD -SFGAOF :: ULONG +SICHINTF :: DWORD +SHCONTF :: DWORD +SFGAOF :: ULONG FILEOPENDIALOGOPTIONS :: DWORD -REFPROPERTYKEY :: ^PROPERTYKEY -REFPROPVARIANT :: ^PROPVARIANT +REFPROPERTYKEY :: ^PROPERTYKEY +REFPROPVARIANT :: ^PROPVARIANT SIGDN :: enum c_int { NORMALDISPLAY = 0, @@ -4070,74 +4151,102 @@ SIATTRIBFLAGS :: enum c_int { FDAP :: enum c_int { BOTTOM = 0, - TOP = 1, + TOP = 1, } FDE_SHAREVIOLATION_RESPONSE :: enum c_int { DEFAULT = 0, - ACCEPT = 1, - REFUSE = 2, + ACCEPT = 1, + REFUSE = 2, } GETPROPERTYSTOREFLAGS :: enum c_int { - DEFAULT = 0, - HANDLERPROPERTIESONLY = 0x1, - READWRITE = 0x2, - TEMPORARY = 0x4, - FASTPROPERTIESONLY = 0x8, - OPENSLOWITEM = 0x10, - DELAYCREATION = 0x20, - BESTEFFORT = 0x40, - NO_OPLOCK = 0x80, - PREFERQUERYPROPERTIES = 0x100, - EXTRINSICPROPERTIES = 0x200, - EXTRINSICPROPERTIESONLY = 0x400, - VOLATILEPROPERTIES = 0x800, - VOLATILEPROPERTIESONLY = 0x1000, - MASK_VALID = 0x1fff, + DEFAULT = 0, + HANDLERPROPERTIESONLY = 0x1, + READWRITE = 0x2, + TEMPORARY = 0x4, + FASTPROPERTIESONLY = 0x8, + OPENSLOWITEM = 0x10, + DELAYCREATION = 0x20, + BESTEFFORT = 0x40, + NO_OPLOCK = 0x80, + PREFERQUERYPROPERTIES = 0x100, + EXTRINSICPROPERTIES = 0x200, + EXTRINSICPROPERTIESONLY = 0x400, + VOLATILEPROPERTIES = 0x800, + VOLATILEPROPERTIESONLY = 0x1000, + MASK_VALID = 0x1fff, } PROPERTYKEY :: struct { fmtid: GUID, - pid: DWORD, + pid: DWORD, } BIND_OPTS :: struct { - cbStruct: DWORD, - grfFlags: DWORD, - grfMode: DWORD, + cbStruct: DWORD, + grfFlags: DWORD, + grfMode: DWORD, dwTickCountDeadline: DWORD, } STATSTG :: struct { - pwcsName: LPOLESTR, - type: DWORD, - cbSize: ULARGE_INTEGER, - mtime: FILETIME, - ctime: FILETIME, - atime: FILETIME, - grfMode: DWORD, + pwcsName: LPOLESTR, + type: DWORD, + cbSize: ULARGE_INTEGER, + mtime: FILETIME, + ctime: FILETIME, + atime: FILETIME, + grfMode: DWORD, grfLocksSupported: DWORD, - clsid: CLSID, - grfStateBits: DWORD, - reserved: DWORD, + clsid: CLSID, + grfStateBits: DWORD, + reserved: DWORD, } COMDLG_FILTERSPEC :: struct { pszName, pszSpec: LPCWSTR, } +PERCEIVED :: enum c_int { + FIRST = -3, + CUSTOM = -3, + UNSPECIFIED = -2, + FOLDER = -1, + UNKNOWN = 0, + TEXT = 1, + IMAGE = 2, + AUDIO = 3, + VIDEO = 4, + COMPRESSED = 5, + DOCUMENT = 6, + SYSTEM = 7, + APPLICATION = 8, + GAMEMEDIA = 9, + CONTACTS = 10, + LAST = 10, +} + +PERCEIVEDFLAG :: DWORD +PERCEIVEDFLAG_UNDEFINED :: 0x0000 +PERCEIVEDFLAG_SOFTCODED :: 0x0001 +PERCEIVEDFLAG_HARDCODED :: 0x0002 +PERCEIVEDFLAG_NATIVESUPPORT :: 0x0004 +PERCEIVEDFLAG_GDIPLUS :: 0x0010 +PERCEIVEDFLAG_WMSDK :: 0x0020 +PERCEIVEDFLAG_ZIPFOLDER :: 0x0040 + DECIMAL :: struct { wReserved: USHORT, - _: struct #raw_union { - _: struct { + using _: struct #raw_union { + using _: struct { scale, sign: BYTE, }, signscale: USHORT, }, Hi32: ULONG, - _: struct #raw_union { - _: struct { + using _: struct #raw_union { + using _: struct { Lo32, Mid32: ULONG, }, Lo64: ULONGLONG, @@ -4208,16 +4317,19 @@ SHACF_AUTOAPPEND_FORCE_OFF :: 0x80000000 // Ignore the registry default and fo LWSTDAPI :: HRESULT -CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}} -CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}} -CLSID_TaskbarList := &GUID{0x56FDF344, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} +CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}} +CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}} +CLSID_TaskbarList := &GUID{0x56FDF344, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} +CLSID_QueryAssociations := GUID{0xa07034fd, 0x6caa, 0x4954, {0xac, 0x3f, 0x97, 0xa2, 0x72, 0x16, 0xf9, 0x8a}} -IID_IFileDialog := &GUID{0x42F85136, 0xDB7E, 0x439C, {0x85, 0xF1, 0xE4, 0x07, 0x5D, 0x13, 0x5F, 0xC8}} -IID_IFileSaveDialog := &GUID{0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}} -IID_IFileOpenDialog := &GUID{0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}} -IID_ITaskbarList := &GUID{0x56FDF342, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} -IID_ITaskbarList2 := &GUID{0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}} -IID_ITaskbarList3 := &GUID{0xea1afb91, 0x9e28, 0x4b86, {0x90, 0xe9, 0x9e, 0x9f, 0x8a, 0x5e, 0xef, 0xaf}} +IID_IShellItem := &GUID{0x43826d1e, 0xe718, 0x42ee, {0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe}} +IID_IFileDialog := &GUID{0x42F85136, 0xDB7E, 0x439C, {0x85, 0xF1, 0xE4, 0x07, 0x5D, 0x13, 0x5F, 0xC8}} +IID_IFileSaveDialog := &GUID{0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}} +IID_IFileOpenDialog := &GUID{0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}} +IID_ITaskbarList := &GUID{0x56FDF342, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} +IID_ITaskbarList2 := &GUID{0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}} +IID_ITaskbarList3 := &GUID{0xea1afb91, 0x9e28, 0x4b86, {0x90, 0xe9, 0x9e, 0x9f, 0x8a, 0x5e, 0xef, 0xaf}} +IID_IQueryAssociations := &GUID{0xc46ca590, 0x3c3f, 0x11d2, {0xbe, 0xe6, 0x00, 0x00, 0xf8, 0x05, 0xca, 0x57}} IModalWindow :: struct #raw_union { #subtype IUnknown: IUnknown, @@ -4600,6 +4712,91 @@ ITaskbarList3Vtbl :: struct { SetThumbnailClip: proc "system" (this: ^ITaskbarList3, hwnd: HWND, prcClip: ^RECT) -> HRESULT, } +ASSOCF_Bits :: enum c_int { + INIT_NOREMAPCLSID = 0, + INIT_BYEXENAME = 1, + OPEN_BYEXENAME = 1, + INIT_DEFAULTTOSTAR = 2, + INIT_DEFAULTTOFOLDER = 3, + NOUSERSETTINGS = 4, + NOTRUNCATE = 5, + VERIFY = 6, + REMAPRUNDLL = 7, + NOFIXUPS = 8, + IGNOREBASECLASS = 9, + INIT_IGNOREUNKNOWN = 10, + INIT_FIXED_PROGID = 11, + IS_PROTOCOL = 12, + INIT_FOR_FILE = 13, + IS_FULL_URI = 14, + PER_MACHINE_ONLY = 15, + APP_TO_APP = 16, +} +ASSOCF :: bit_set[ASSOCF_Bits; c_int] + +ASSOCSTR :: enum c_int { + COMMAND = 1, + EXECUTABLE, + FRIENDLYDOCNAME, + FRIENDLYAPPNAME, + NOOPEN, + SHELLNEWVALUE, + DDECOMMAND, + DDEIFEXEC, + DDEAPPLICATION, + DDETOPIC, + INFOTIP, + QUICKTIP, + TILEINFO, + CONTENTTYPE, + DEFAULTICON, + SHELLEXTENSION, + DROPTARGET, + DELEGATEEXECUTE, + SUPPORTED_URI_PROTOCOLS, + PROGID, + APPID, + APPPUBLISHER, + APPICONREFERENCE, + MAX, +} + +ASSOCKEY :: enum c_int { + SHELLEXECCLASS = 1, + APP, + CLASS, + BASECLASS, + MAX, +} + +ASSOCDATA :: enum c_int { + MSIDESCRIPTOR = 1, + NOACTIVATEHANDLER, + UNUSED1, + HASPERUSERASSOC, + EDITFLAGS, + VALUE, + MAX, +} + +ASSOCENUM :: enum c_int { + NONE, +} + +IQueryAssociations :: struct #raw_union { + #subtype IUnknown: IUnknown, + using Vtbl: ^IQueryAssociationsVtbl, +} + +IQueryAssociationsVtbl :: struct { + using IUnknownVtbl: IUnknownVtbl, + Init: proc "system" (this: ^IQueryAssociations, flags: ASSOCF, pszAssoc: LPCWSTR, hkProgid: HKEY, hwnd: HWND) -> HRESULT, + GetString: proc "system" (this: ^IQueryAssociations, flags: ASSOCF, str: ASSOCSTR, pszExtra: LPCWSTR, pszOut: LPWSTR, pcchOut: ^DWORD) -> HRESULT, + GetKey: proc "system" (this: ^IQueryAssociations, flags: ASSOCF, key: ASSOCKEY, pszExtra: LPCWSTR, phkeyOut: ^HKEY) -> HRESULT, + GetData: proc "system" (this: ^IQueryAssociations, flags: ASSOCF, data: ASSOCDATA, pszExtra: LPCWSTR, pvOut: rawptr, pcbOut: ^DWORD) -> HRESULT, + GetEnum: proc "system" (this: ^IQueryAssociations, flags: ASSOCF, assocenum: ASSOCENUM, pszExtra: LPCWSTR, riid: REFIID, ppvOut: ^rawptr) -> HRESULT, +} + MEMORYSTATUSEX :: struct { dwLength: DWORD, dwMemoryLoad: DWORD, @@ -4713,24 +4910,24 @@ Windows_Product_Type :: enum DWORD { WEB_SERVER_CORE = 0x0000001D, // Web Server (core installation) } -ENABLE_ECHO_INPUT : DWORD : 0x0004 -ENABLE_INSERT_MODE : DWORD : 0x0020 -ENABLE_LINE_INPUT : DWORD : 0x0002 -ENABLE_MOUSE_INPUT : DWORD : 0x0010 -ENABLE_PROCESSED_INPUT : DWORD : 0x0001 -ENABLE_QUICK_EDIT_MODE : DWORD : 0x0040 -ENABLE_WINDOW_INPUT : DWORD : 0x0008 -ENABLE_VIRTUAL_TERMINAL_INPUT : DWORD : 0x0200 -ENABLE_PROCESSED_OUTPUT : DWORD : 0x0001 -ENABLE_WRAP_AT_EOL_OUTPUT : DWORD : 0x0002 +ENABLE_ECHO_INPUT : DWORD : 0x0004 +ENABLE_INSERT_MODE : DWORD : 0x0020 +ENABLE_LINE_INPUT : DWORD : 0x0002 +ENABLE_MOUSE_INPUT : DWORD : 0x0010 +ENABLE_PROCESSED_INPUT : DWORD : 0x0001 +ENABLE_QUICK_EDIT_MODE : DWORD : 0x0040 +ENABLE_WINDOW_INPUT : DWORD : 0x0008 +ENABLE_VIRTUAL_TERMINAL_INPUT : DWORD : 0x0200 +ENABLE_PROCESSED_OUTPUT : DWORD : 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT : DWORD : 0x0002 ENABLE_VIRTUAL_TERMINAL_PROCESSING : DWORD : 0x0004 -DISABLE_NEWLINE_AUTO_RETURN : DWORD : 0x0008 -ENABLE_LVB_GRID_WORLDWIDE : DWORD : 0x0010 +DISABLE_NEWLINE_AUTO_RETURN : DWORD : 0x0008 +ENABLE_LVB_GRID_WORLDWIDE : DWORD : 0x0010 -CTRL_C_EVENT : DWORD : 0 -CTRL_BREAK_EVENT : DWORD : 1 -CTRL_CLOSE_EVENT : DWORD : 2 -CTRL_LOGOFF_EVENT : DWORD : 5 +CTRL_C_EVENT : DWORD : 0 +CTRL_BREAK_EVENT : DWORD : 1 +CTRL_CLOSE_EVENT : DWORD : 2 +CTRL_LOGOFF_EVENT : DWORD : 5 CTRL_SHUTDOWN_EVENT : DWORD : 6 COORD :: struct { @@ -4739,45 +4936,45 @@ COORD :: struct { } SMALL_RECT :: struct { - Left: SHORT, - Top: SHORT, - Right: SHORT, + Left: SHORT, + Top: SHORT, + Right: SHORT, Bottom: SHORT, } CONSOLE_SCREEN_BUFFER_INFO :: struct { - dwSize: COORD, - dwCursorPosition: COORD, - wAttributes: WORD, - srWindow: SMALL_RECT, + dwSize: COORD, + dwCursorPosition: COORD, + wAttributes: WORD, + srWindow: SMALL_RECT, dwMaximumWindowSize: COORD, } CONSOLE_CURSOR_INFO :: struct { - dwSize: DWORD, + dwSize: DWORD, bVisible: BOOL, } PCONSOLE_SCREEN_BUFFER_INFO :: ^CONSOLE_SCREEN_BUFFER_INFO -PCONSOLE_CURSOR_INFO :: ^CONSOLE_CURSOR_INFO +PCONSOLE_CURSOR_INFO :: ^CONSOLE_CURSOR_INFO Event_Type :: enum WORD { - KEY_EVENT = 0x0001, - MOUSE_EVENT = 0x0002, + KEY_EVENT = 0x0001, + MOUSE_EVENT = 0x0002, WINDOW_BUFFER_SIZE_EVENT = 0x0004, - MENU_EVENT = 0x0008, - FOCUS_EVENT = 0x0010, + MENU_EVENT = 0x0008, + FOCUS_EVENT = 0x0010, } INPUT_RECORD :: struct { EventType: Event_Type, Event: struct #raw_union { - KeyEvent: KEY_EVENT_RECORD, - MouseEvent: MOUSE_EVENT_RECORD, - WindowBufferSizeEvent: WINDOW_BUFFER_SIZE_RECORD, - MenuEvent: MENU_EVENT_RECORD, - FocusEvent: FOCUS_EVENT_RECORD, + KeyEvent: KEY_EVENT_RECORD `raw_union_tag:"EventType=KEY_EVENT"`, + MouseEvent: MOUSE_EVENT_RECORD `raw_union_tag:"EventType=MOUSE_EVENT"`, + WindowBufferSizeEvent: WINDOW_BUFFER_SIZE_RECORD `raw_union_tag:"EventType=WINDOW_BUFFER_SIZE_EVENT"`, + MenuEvent: MENU_EVENT_RECORD `raw_union_tag:"EventType=MENU_EVENT"`, + FocusEvent: FOCUS_EVENT_RECORD `raw_union_tag:"EventType=FOCUS_EVENT"`, }, } @@ -4807,10 +5004,10 @@ KEY_EVENT_RECORD :: struct { } MOUSE_EVENT_RECORD :: struct { - dwMousePosition: COORD, - dwButtonState: DWORD, + dwMousePosition: COORD, + dwButtonState: DWORD, dwControlKeyState: DWORD, - dwEventFlags: DWORD, + dwEventFlags: DWORD, } WINDOW_BUFFER_SIZE_RECORD :: struct { @@ -4845,6 +5042,12 @@ SOMAXCONN :: 128 // The number of messages that can be queued in memory after SOCKET_ERROR :: -1 // Networking errors +WSA_INVALID_HANDLE :: 6 // Specified event object handle is invalid. +WSA_NOT_ENOUGH_MEMORY :: 8 // Insufficient memory available. +WSA_INVALID_PARAMETER :: 87 // One or more parameters are invalid. +WSA_OPERATION_ABORTED :: 995 // Overlapped operation aborted. +WSA_IO_INCOMPLETE :: 996 // Overlapped I/O event object not in signaled state. +WSA_IO_PENDING :: 997 // Overlapped operations will complete later. WSAEINTR :: 10004 // Call interrupted. CancelBlockingCall was called. (This is different on Linux.) WSAEACCES :: 10013 // If you try to bind a Udp socket to the broadcast address without the socket option set. WSAEFAULT :: 10014 // A pointer that was passed to a WSA function is invalid, such as a buffer size is smaller than you said it was @@ -4930,16 +5133,16 @@ SO_SNDBUF : c_int : 0x1001 SO_ERROR : c_int : 0x1007 SO_BROADCAST : c_int : 0x0020 -TCP_NODELAY: c_int : 0x0001 -IP_TTL: c_int : 4 -IPV6_V6ONLY: c_int : 27 -IP_MULTICAST_LOOP: c_int : 11 -IPV6_MULTICAST_LOOP: c_int : 11 -IP_MULTICAST_TTL: c_int : 10 -IP_ADD_MEMBERSHIP: c_int : 12 +TCP_NODELAY : c_int : 0x0001 +IP_TTL : c_int : 4 +IPV6_V6ONLY : c_int : 27 +IP_MULTICAST_LOOP : c_int : 11 +IPV6_MULTICAST_LOOP : c_int : 11 +IP_MULTICAST_TTL : c_int : 10 +IP_ADD_MEMBERSHIP : c_int : 12 -IPV6_ADD_MEMBERSHIP: c_int : 12 -IPV6_DROP_MEMBERSHIP: c_int : 13 +IPV6_ADD_MEMBERSHIP : c_int : 12 +IPV6_DROP_MEMBERSHIP : c_int : 13 MAX_PROTOCOL_CHAIN: DWORD : 7 @@ -4953,8 +5156,8 @@ MSG_OOB : c_int : 1 // `send`/`recv` should process out-of-band data. MSG_PEEK : c_int : 2 // `recv` should not remove the data from the buffer. Only valid for non-overlapped operations. -SOCKET :: distinct uintptr // TODO -socklen_t :: c_int +SOCKET :: distinct uintptr // TODO +socklen_t :: c_int ADDRESS_FAMILY :: USHORT ip_mreq :: struct { @@ -4980,7 +5183,7 @@ ADDRINFOA :: struct { ai_socktype: c_int, ai_protocol: c_int, ai_addrlen: size_t, - ai_canonname: ^c_char, + ai_canonname: [^]c_char `fmt:"q,ai_addrlen"`, ai_addr: ^SOCKADDR, ai_next: ^ADDRINFOA, } @@ -5013,18 +5216,18 @@ in6_addr :: struct { } -DNS_STATUS :: distinct DWORD // zero is success -DNS_INFO_NO_RECORDS :: 9501 +DNS_STATUS :: distinct DWORD // zero is success +DNS_INFO_NO_RECORDS :: 9501 DNS_QUERY_NO_RECURSION :: 0x00000004 DNS_RECORD :: struct { // aka DNS_RECORDA - pNext: ^DNS_RECORD, - pName: cstring, - wType: WORD, + pNext: ^DNS_RECORD, + pName: cstring, + wType: WORD, wDataLength: USHORT, - Flags: DWORD, - dwTtl: DWORD, - _: DWORD, + Flags: DWORD, + dwTtl: DWORD, + _: DWORD, Data: struct #raw_union #align(4) { CNAME: DNS_PTR_DATAA, A: u32be, // Ipv4 Address @@ -5045,8 +5248,8 @@ DNS_PTR_DATAA :: cstring DNS_MX_DATAA :: struct { pNameExchange: cstring, // the hostname - wPreference: WORD, // lower values preferred - _: WORD, // padding. + wPreference: WORD, // lower values preferred + _: WORD, // padding. } DNS_SRV_DATAA :: struct { pNameTarget: cstring, @@ -5091,8 +5294,8 @@ ENUMRESTYPEPROCW :: #type proc (hModule: HMODULE, lpType: LPCWSTR, lParam: LONG_ ENUMRESLANGPROCW :: #type proc (hModule: HMODULE, lpType: LPCWSTR, lpName: LPWSTR, wIDLanguage: LANGID, lParam: LONG_PTR)-> BOOL DTR_Control :: enum byte { - Disable = 0, - Enable = 1, + Disable = 0, + Enable = 1, Handshake = 2, } RTS_Control :: enum byte { @@ -5109,9 +5312,9 @@ Parity :: enum byte { Space = 4, } Stop_Bits :: enum byte { - One = 0, + One = 0, One_And_A_Half = 1, - Two = 2, + Two = 2, } DCB :: struct { @@ -5147,34 +5350,78 @@ DCB :: struct { } COMMTIMEOUTS :: struct { - ReadIntervalTimeout: DWORD, - ReadTotalTimeoutMultiplier: DWORD, - ReadTotalTimeoutConstant: DWORD, + ReadIntervalTimeout: DWORD, + ReadTotalTimeoutMultiplier: DWORD, + ReadTotalTimeoutConstant: DWORD, WriteTotalTimeoutMultiplier: DWORD, - WriteTotalTimeoutConstant: DWORD, + WriteTotalTimeoutConstant: DWORD, } -Com_Stat_Bits :: enum { - fCtsHold, - fDsrHold, - fRlsdHold, - fXoffHold, - fXoffSent, - fEof, - fTxim, -} COMSTAT :: struct { - bits: bit_set[Com_Stat_Bits; DWORD], - cbInQue: DWORD, + using _: bit_field DWORD { + fCtsHold: BOOL | 1, + fDsrHold: BOOL | 1, + fRlsdHol: BOOL | 1, + fXoffHol: BOOL | 1, + fXoffSen: BOOL | 1, + fEof: BOOL | 1, + fTxim: BOOL | 1, + fReserved: DWORD | 25, + }, + cbInQue: DWORD, cbOutQue: DWORD, } -Com_Error_Bits :: enum { +Com_Error_Bits :: enum DWORD { RXOVER, OVERRUN, RXPARITY, FRAME, BREAK, } -Com_Error :: bit_set[Com_Error_Bits; DWORD] +Com_Error :: distinct bit_set[Com_Error_Bits; DWORD] +FILETYPEATTRIBUTEFLAG :: enum DWORD { + Exclude = 0, + Show = 1, + HasExtension = 2, + NoEdit = 3, + NoRemove = 4, + NoNewVerb = 5, + NoEditVerb = 6, + NoRemoveVerb = 7, + NoEditDesc = 8, + NoEditIcon = 9, + NoEditDflt = 10, + NoEditVerbCmd = 11, + NoEditVerbExe = 12, + NoDDE = 13, + NoEditMIME = 15, + OpenIsSafe = 16, + AlwaysUnsafe = 17, + NoRecentDocs = 20, + SafeForElevation = 21, + AlwaysUseDirectInvoke = 22, +} +FILETYPEATTRIBUTEFLAGS :: bit_set[FILETYPEATTRIBUTEFLAG; DWORD] + +ASSOCCLASS :: enum c_int { + SHELL_KEY = 0, + PROGID_KEY, + PROGID_STR, + CLSID_KEY, + CLSID_STR, + APP_KEY, + APP_STR, + SYSTEM_STR, + FOLDER, + STAR, + FIXED_PROGID_STR, + PROTOCOL_STR, +} + +ASSOCIATIONELEMENT :: struct { + ac: ASSOCCLASS, + hkClass: HKEY, + pszClass: PCWSTR, +} diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index 49ebb49cb..d2f54b127 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -2,12 +2,11 @@ package sys_windows import "base:intrinsics" -import "core:c" foreign import user32 "system:User32.lib" @(default_calling_convention="system") foreign user32 { - GetClassInfoW :: proc(hInstance: HINSTANCE, lpClassName: LPCWSTR, lpWndClass: ^WNDCLASSW) -> BOOL --- + GetClassInfoW :: proc(hInstance: HINSTANCE, lpClassName: LPCWSTR, lpWndClass: ^WNDCLASSW) -> BOOL --- GetClassInfoExW :: proc(hInstance: HINSTANCE, lpszClass: LPCWSTR, lpwcx: ^WNDCLASSEXW) -> BOOL --- GetClassLongW :: proc(hWnd: HWND, nIndex: INT) -> DWORD --- @@ -20,67 +19,70 @@ foreign user32 { GetParent :: proc(hWnd: HWND) -> HWND --- SetWinEventHook :: proc( - eventMin, eventMax: DWORD, - hmodWinEventProc: HMODULE, - pfnWinEvenProc: WINEVENTPROC, + eventMin, eventMax: DWORD, + hmodWinEventProc: HMODULE, + pfnWinEvenProc: WINEVENTPROC, idProcess, idThread: DWORD, - dwFlags: WinEventFlags, + dwFlags: WinEventFlags, ) -> HWINEVENTHOOK --- + UnhookWinEvent :: proc(winEventHook: HWINEVENTHOOK) -> BOOL --- IsChild :: proc(hWndParent, hWnd: HWND) -> BOOL --- - RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM --- + RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM --- RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM --- UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL --- - RegisterHotKey :: proc(hnwd: HWND, id: c.int, fsModifiers: UINT, vk: UINT) -> BOOL --- + RegisterHotKey :: proc(hnwd: HWND, id: c_int, fsModifiers: UINT, vk: UINT) -> BOOL --- CreateWindowExW :: proc( - dwExStyle: DWORD, - lpClassName: LPCWSTR, - lpWindowName: LPCWSTR, - dwStyle: DWORD, + dwExStyle: DWORD, + lpClassName: LPCWSTR, + lpWindowName: LPCWSTR, + dwStyle: DWORD, X, Y, nWidth, nHeight: INT, - hWndParent: HWND, - hMenu: HMENU, - hInstance: HINSTANCE, - lpParam: LPVOID, + hWndParent: HWND, + hMenu: HMENU, + hInstance: HINSTANCE, + lpParam: LPVOID, ) -> HWND --- GetWindowThreadProcessId :: proc(hwnd: HWND, lpdwProcessId: LPDWORD) -> DWORD --- DestroyWindow :: proc(hWnd: HWND) -> BOOL --- - ShowWindow :: proc(hWnd: HWND, nCmdShow: INT) -> BOOL --- - IsWindow :: proc(hWnd: HWND) -> BOOL --- - IsWindowVisible :: proc(hwnd: HWND) -> BOOL --- - IsWindowEnabled :: proc(hwnd: HWND) -> BOOL --- - IsIconic :: proc(hwnd: HWND) -> BOOL --- - IsZoomed :: proc(hwnd: HWND) -> BOOL --- - BringWindowToTop :: proc(hWnd: HWND) -> BOOL --- - GetTopWindow :: proc(hWnd: HWND) -> HWND --- + ShowWindow :: proc(hWnd: HWND, nCmdShow: INT) -> BOOL --- + IsWindow :: proc(hWnd: HWND) -> BOOL --- + IsWindowVisible :: proc(hwnd: HWND) -> BOOL --- + IsWindowEnabled :: proc(hwnd: HWND) -> BOOL --- + IsIconic :: proc(hwnd: HWND) -> BOOL --- + IsZoomed :: proc(hwnd: HWND) -> BOOL --- + BringWindowToTop :: proc(hWnd: HWND) -> BOOL --- + GetTopWindow :: proc(hWnd: HWND) -> HWND --- + GetWindow :: proc(hwnd: HWND, uCmd: UINT) -> HWND --- SetForegroundWindow :: proc(hWnd: HWND) -> BOOL --- GetForegroundWindow :: proc() -> HWND --- - GetDesktopWindow :: proc() -> HWND --- - UpdateWindow :: proc(hWnd: HWND) -> BOOL --- - SetActiveWindow :: proc(hWnd: HWND) -> HWND --- - GetActiveWindow :: proc() -> HWND --- - SetFocus :: proc(hWnd: HWND) -> HWND --- - GetFocus :: proc() -> HWND --- - RedrawWindow :: proc(hwnd: HWND, lprcUpdate: LPRECT, hrgnUpdate: HRGN, flags: RedrawWindowFlags) -> BOOL --- - SetParent :: proc(hWndChild: HWND, hWndNewParent: HWND) -> HWND --- - SetPropW :: proc(hWnd: HWND, lpString: LPCWSTR, hData: HANDLE) -> BOOL --- - GetPropW :: proc(hWnd: HWND, lpString: LPCWSTR) -> HANDLE --- - RemovePropW :: proc(hWnd: HWND, lpString: LPCWSTR) -> HANDLE --- - EnumPropsW :: proc(hWnd: HWND, lpEnumFunc: PROPENUMPROCW) -> INT --- - EnumPropsExW :: proc(hWnd: HWND, lpEnumFunc: PROPENUMPROCW, lParam: LPARAM) -> INT --- - GetMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> INT --- + GetDesktopWindow :: proc() -> HWND --- + UpdateWindow :: proc(hWnd: HWND) -> BOOL --- + SetActiveWindow :: proc(hWnd: HWND) -> HWND --- + GetActiveWindow :: proc() -> HWND --- + SetFocus :: proc(hWnd: HWND) -> HWND --- + GetFocus :: proc() -> HWND --- + RedrawWindow :: proc(hwnd: HWND, lprcUpdate: LPRECT, hrgnUpdate: HRGN, flags: RedrawWindowFlags) -> BOOL --- + SetParent :: proc(hWndChild: HWND, hWndNewParent: HWND) -> HWND --- + SetPropW :: proc(hWnd: HWND, lpString: LPCWSTR, hData: HANDLE) -> BOOL --- + GetPropW :: proc(hWnd: HWND, lpString: LPCWSTR) -> HANDLE --- + RemovePropW :: proc(hWnd: HWND, lpString: LPCWSTR) -> HANDLE --- + EnumPropsW :: proc(hWnd: HWND, lpEnumFunc: PROPENUMPROCW) -> INT --- + EnumPropsExW :: proc(hWnd: HWND, lpEnumFunc: PROPENUMPROCW, lParam: LPARAM) -> INT --- + GetMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> INT --- + GetMessageExtraInfo :: proc() -> LPARAM --- TranslateMessage :: proc(lpMsg: ^MSG) -> BOOL --- DispatchMessageW :: proc(lpMsg: ^MSG) -> LRESULT --- - WaitMessage :: proc() -> BOOL --- - MsgWaitForMultipleObjects :: proc(nCount: DWORD, pHandles: ^HANDLE, fWaitAll: BOOL, dwMilliseconds: DWORD, dwWakeMask: DWORD) -> DWORD --- + WaitMessage :: proc() -> BOOL --- + MsgWaitForMultipleObjects :: proc(nCount: DWORD, pHandles: [^]HANDLE, fWaitAll: BOOL, dwMilliseconds: DWORD, dwWakeMask: DWORD) -> DWORD --- PeekMessageA :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) -> BOOL --- PeekMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) -> BOOL --- @@ -100,97 +102,98 @@ foreign user32 { DefWindowProcA :: proc(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- DefWindowProcW :: proc(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- - FindWindowA :: proc(lpClassName: LPCSTR, lpWindowName: LPCSTR) -> HWND --- - FindWindowW :: proc(lpClassName: LPCWSTR, lpWindowName: LPCWSTR) -> HWND --- + FindWindowA :: proc(lpClassName: LPCSTR, lpWindowName: LPCSTR) -> HWND --- + FindWindowW :: proc(lpClassName: LPCWSTR, lpWindowName: LPCWSTR) -> HWND --- FindWindowExA :: proc(hWndParent: HWND, hWndChildAfter: HWND, lpszClass: LPCSTR, lpszWindow: LPCSTR) -> HWND --- FindWindowExW :: proc(hWndParent: HWND, hWndChildAfter: HWND, lpszClass: LPCWSTR, lpszWindow: LPCWSTR) -> HWND --- - LoadIconA :: proc(hInstance: HINSTANCE, lpIconName: LPCSTR) -> HICON --- - LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON --- + LoadIconA :: proc(hInstance: HINSTANCE, lpIconName: LPCSTR) -> HICON --- + LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON --- GetIconInfoExW :: proc(hIcon: HICON, piconinfo: PICONINFOEXW) -> BOOL --- - LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR --- - LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR --- - LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx, cy: INT, fuLoad: UINT) -> HANDLE --- + LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR --- + LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR --- + LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx, cy: INT, fuLoad: UINT) -> HANDLE --- - CreateIcon :: proc(hInstance: HINSTANCE, nWidth, nHeight: INT, cPlanes: BYTE, cBitsPixel: BYTE, lpbANDbits: PBYTE, lpbXORbits: PBYTE) -> HICON --- + CreateIcon :: proc(hInstance: HINSTANCE, nWidth, nHeight: INT, cPlanes: BYTE, cBitsPixel: BYTE, lpbANDbits: PBYTE, lpbXORbits: PBYTE) -> HICON --- CreateIconFromResource :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD) -> HICON --- - DestroyIcon :: proc(hIcon: HICON) -> BOOL --- - DrawIcon :: proc(hDC: HDC, X, Y: INT, hIcon: HICON) -> BOOL --- + CreateIconIndirect :: proc(piconinfo: PICONINFO) -> HICON --- + DestroyIcon :: proc(hIcon: HICON) -> BOOL --- + DrawIcon :: proc(hDC: HDC, X, Y: INT, hIcon: HICON) -> BOOL --- - CreateCursor :: proc(hInst: HINSTANCE, xHotSpot, yHotSpot, nWidth, nHeight: INT, pvANDPlane: PVOID, pvXORPlane: PVOID) -> HCURSOR --- + CreateCursor :: proc(hInst: HINSTANCE, xHotSpot, yHotSpot, nWidth, nHeight: INT, pvANDPlane: PVOID, pvXORPlane: PVOID) -> HCURSOR --- DestroyCursor :: proc(hCursor: HCURSOR) -> BOOL --- - GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- - GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- - ClientToScreen :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL --- - ScreenToClient :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL --- - SetWindowPos :: proc(hWnd: HWND, hWndInsertAfter: HWND, X, Y, cx, cy: INT, uFlags: UINT) -> BOOL --- - MoveWindow :: proc(hWnd: HWND, X, Y, hWidth, hHeight: INT, bRepaint: BOOL) -> BOOL --- - GetSystemMetrics :: proc(nIndex: INT) -> INT --- - AdjustWindowRect :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL) -> BOOL --- - AdjustWindowRectEx :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD) -> BOOL --- + GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- + GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- + ClientToScreen :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL --- + ScreenToClient :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL --- + SetWindowPos :: proc(hWnd: HWND, hWndInsertAfter: HWND, X, Y, cx, cy: INT, uFlags: UINT) -> BOOL --- + MoveWindow :: proc(hWnd: HWND, X, Y, hWidth, hHeight: INT, bRepaint: BOOL) -> BOOL --- + GetSystemMetrics :: proc(nIndex: INT) -> INT --- + AdjustWindowRect :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL) -> BOOL --- + AdjustWindowRectEx :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD) -> BOOL --- AdjustWindowRectExForDpi :: proc(lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD, dpi: UINT) -> BOOL --- SystemParametersInfoW :: proc(uiAction, uiParam: UINT, pvParam: PVOID, fWinIni: UINT) -> BOOL --- - GetMonitorInfoW :: proc(hMonitor: HMONITOR, lpmi: LPMONITORINFO) -> BOOL --- + GetMonitorInfoW :: proc(hMonitor: HMONITOR, lpmi: LPMONITORINFO) -> BOOL --- GetWindowDC :: proc(hWnd: HWND) -> HDC --- - GetDC :: proc(hWnd: HWND) -> HDC --- - GetDCEx :: proc(hWnd: HWND, hrgnClip: HRGN, flags: DWORD) -> HDC --- - ReleaseDC :: proc(hWnd: HWND, hDC: HDC) -> INT --- + GetDC :: proc(hWnd: HWND) -> HDC --- + GetDCEx :: proc(hWnd: HWND, hrgnClip: HRGN, flags: DWORD) -> HDC --- + ReleaseDC :: proc(hWnd: HWND, hDC: HDC) -> INT --- GetDlgCtrlID :: proc(hWnd: HWND) -> INT --- - GetDlgItem :: proc(hDlg: HWND, nIDDlgItem: INT) -> HWND --- + GetDlgItem :: proc(hDlg: HWND, nIDDlgItem: INT) -> HWND --- - CreateMenu :: proc() -> HMENU --- - CreatePopupMenu :: proc() -> HMENU --- - DeleteMenu :: proc(hMenu: HMENU, uPosition: UINT, uFlags: UINT) -> BOOL --- - DestroyMenu :: proc(hMenu: HMENU) -> BOOL --- - InsertMenuW :: proc(hMenu: HMENU, uPosition: UINT, uFlags: UINT, uIDNewItem: UINT_PTR, lpNewItem: LPCWSTR) -> BOOL --- - AppendMenuW :: proc(hMenu: HMENU, uFlags: UINT, uIDNewItem: UINT_PTR, lpNewItem: LPCWSTR) -> BOOL --- - GetMenu :: proc(hWnd: HWND) -> HMENU --- - SetMenu :: proc(hWnd: HWND, hMenu: HMENU) -> BOOL --- - TrackPopupMenu :: proc(hMenu: HMENU, uFlags: UINT, x, y: INT, nReserved: INT, hWnd: HWND, prcRect: ^RECT) -> INT --- + CreateMenu :: proc() -> HMENU --- + CreatePopupMenu :: proc() -> HMENU --- + DeleteMenu :: proc(hMenu: HMENU, uPosition: UINT, uFlags: UINT) -> BOOL --- + DestroyMenu :: proc(hMenu: HMENU) -> BOOL --- + InsertMenuW :: proc(hMenu: HMENU, uPosition: UINT, uFlags: UINT, uIDNewItem: UINT_PTR, lpNewItem: LPCWSTR) -> BOOL --- + AppendMenuW :: proc(hMenu: HMENU, uFlags: UINT, uIDNewItem: UINT_PTR, lpNewItem: LPCWSTR) -> BOOL --- + GetMenu :: proc(hWnd: HWND) -> HMENU --- + SetMenu :: proc(hWnd: HWND, hMenu: HMENU) -> BOOL --- + TrackPopupMenu :: proc(hMenu: HMENU, uFlags: UINT, x, y: INT, nReserved: INT, hWnd: HWND, prcRect: ^RECT) -> INT --- RegisterWindowMessageW :: proc(lpString: LPCWSTR) -> UINT --- CreateAcceleratorTableW :: proc(paccel: LPACCEL, cAccel: INT) -> HACCEL --- DestroyAcceleratorTable :: proc(hAccel: HACCEL) -> BOOL --- - LoadAcceleratorsW :: proc(hInstance: HINSTANCE, lpTableName: LPCWSTR) -> HACCEL --- - TranslateAcceleratorW :: proc(hWnd: HWND, hAccTable: HACCEL, lpMsg: LPMSG) -> INT --- - CopyAcceleratorTableW :: proc(hAccelSrc: HACCEL, lpAccelDst: LPACCEL, cAccelEntries: INT) -> INT --- + LoadAcceleratorsW :: proc(hInstance: HINSTANCE, lpTableName: LPCWSTR) -> HACCEL --- + TranslateAcceleratorW :: proc(hWnd: HWND, hAccTable: HACCEL, lpMsg: LPMSG) -> INT --- + CopyAcceleratorTableW :: proc(hAccelSrc: HACCEL, lpAccelDst: LPACCEL, cAccelEntries: INT) -> INT --- - InsertMenuItemW :: proc(hmenu: HMENU, item: UINT, fByPosition: BOOL, lpmi: LPMENUITEMINFOW) -> BOOL --- - GetMenuItemInfoW :: proc(hmenu: HMENU, item: UINT, fByPosition: BOOL, lpmii: LPMENUITEMINFOW) -> BOOL --- - SetMenuItemInfoW :: proc(hmenu: HMENU, item: UINT, fByPositon: BOOL, lpmii: LPMENUITEMINFOW) -> BOOL --- + InsertMenuItemW :: proc(hmenu: HMENU, item: UINT, fByPosition: BOOL, lpmi: LPMENUITEMINFOW) -> BOOL --- + GetMenuItemInfoW :: proc(hmenu: HMENU, item: UINT, fByPosition: BOOL, lpmii: LPMENUITEMINFOW) -> BOOL --- + SetMenuItemInfoW :: proc(hmenu: HMENU, item: UINT, fByPositon: BOOL, lpmii: LPMENUITEMINFOW) -> BOOL --- GetMenuDefaultItem :: proc(hMenu: HMENU, fByPos: UINT, gmdiFlags: UINT) -> UINT --- SetMenuDefaultItem :: proc(hMenu: HMENU, uItem: UINT, fByPos: UINT) -> BOOL --- - GetMenuItemRect :: proc(hWnd: HWND, hMenu: HMENU, uItem: UINT, lprcItem: LPRECT) -> c_int --- + GetMenuItemRect :: proc(hWnd: HWND, hMenu: HMENU, uItem: UINT, lprcItem: LPRECT) -> c_int --- - GetUpdateRect :: proc(hWnd: HWND, lpRect: LPRECT, bErase: BOOL) -> BOOL --- - ValidateRect :: proc(hWnd: HWND, lpRect: ^RECT) -> BOOL --- + GetUpdateRect :: proc(hWnd: HWND, lpRect: LPRECT, bErase: BOOL) -> BOOL --- + ValidateRect :: proc(hWnd: HWND, lpRect: ^RECT) -> BOOL --- InvalidateRect :: proc(hWnd: HWND, lpRect: ^RECT, bErase: BOOL) -> BOOL --- BeginPaint :: proc(hWnd: HWND, lpPaint: ^PAINTSTRUCT) -> HDC --- - EndPaint :: proc(hWnd: HWND, lpPaint: ^PAINTSTRUCT) -> BOOL --- + EndPaint :: proc(hWnd: HWND, lpPaint: ^PAINTSTRUCT) -> BOOL --- - GetCapture :: proc() -> HWND --- - SetCapture :: proc(hWnd: HWND) -> HWND --- - ReleaseCapture :: proc() -> BOOL --- + GetCapture :: proc() -> HWND --- + SetCapture :: proc(hWnd: HWND) -> HWND --- + ReleaseCapture :: proc() -> BOOL --- TrackMouseEvent :: proc(lpEventTrack: LPTRACKMOUSEEVENT) -> BOOL --- - GetKeyState :: proc(nVirtKey: INT) -> SHORT --- + GetKeyState :: proc(nVirtKey: INT) -> SHORT --- GetAsyncKeyState :: proc(vKey: INT) -> SHORT --- GetKeyboardState :: proc(lpKeyState: PBYTE) -> BOOL --- MapVirtualKeyW :: proc(uCode: UINT, uMapType: UINT) -> UINT --- - ToUnicode :: proc(nVirtKey: UINT, wScanCode: UINT, lpKeyState: ^BYTE, pwszBuff: LPWSTR, cchBuff: INT, wFlags: UINT) -> INT --- + ToUnicode :: proc(nVirtKey: UINT, wScanCode: UINT, lpKeyState: ^BYTE, pwszBuff: LPWSTR, cchBuff: INT, wFlags: UINT) -> INT --- - SetWindowsHookExW :: proc(idHook: INT, lpfn: HOOKPROC, hmod: HINSTANCE, dwThreadId: DWORD) -> HHOOK --- + SetWindowsHookExW :: proc(idHook: INT, lpfn: HOOKPROC, hmod: HINSTANCE, dwThreadId: DWORD) -> HHOOK --- UnhookWindowsHookEx :: proc(hhk: HHOOK) -> BOOL --- - CallNextHookEx :: proc(hhk: HHOOK, nCode: INT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- + CallNextHookEx :: proc(hhk: HHOOK, nCode: INT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- - SetTimer :: proc(hWnd: HWND, nIDEvent: UINT_PTR, uElapse: UINT, lpTimerFunc: TIMERPROC) -> UINT_PTR --- + SetTimer :: proc(hWnd: HWND, nIDEvent: UINT_PTR, uElapse: UINT, lpTimerFunc: TIMERPROC) -> UINT_PTR --- KillTimer :: proc(hWnd: HWND, uIDEvent: UINT_PTR) -> BOOL --- // MessageBoxA :: proc(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT) -> INT --- @@ -198,143 +201,165 @@ foreign user32 { // MessageBoxExA :: proc(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT, wLanguageId: WORD) -> INT --- MessageBoxExW :: proc(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT, wLanguageId: WORD) -> INT --- - ClipCursor :: proc(lpRect: LPRECT) -> BOOL --- + ClipCursor :: proc(lpRect: LPRECT) -> BOOL --- GetCursorPos :: proc(lpPoint: LPPOINT) -> BOOL --- SetCursorPos :: proc(X, Y: INT) -> BOOL --- - SetCursor :: proc(hCursor: HCURSOR) -> HCURSOR --- + SetCursor :: proc(hCursor: HCURSOR) -> HCURSOR --- when !intrinsics.is_package_imported("raylib") { ShowCursor :: proc(bShow: BOOL) -> INT --- } - EnumDisplayDevicesW :: proc (lpDevice: LPCWSTR, iDevNum: DWORD, lpDisplayDevice: PDISPLAY_DEVICEW, dwFlags: DWORD) -> BOOL --- + EnumDisplayDevicesW :: proc(lpDevice: LPCWSTR, iDevNum: DWORD, lpDisplayDevice: PDISPLAY_DEVICEW, dwFlags: DWORD) -> BOOL --- EnumDisplaySettingsW :: proc(lpszDeviceName: LPCWSTR, iModeNum: DWORD, lpDevMode: ^DEVMODEW) -> BOOL --- - MonitorFromPoint :: proc(pt: POINT, dwFlags: Monitor_From_Flags) -> HMONITOR --- - MonitorFromRect :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR --- - MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR --- + WindowFromPoint :: proc(pt: POINT) -> HWND --- + MonitorFromPoint :: proc(pt: POINT, dwFlags: Monitor_From_Flags) -> HMONITOR --- + MonitorFromRect :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR --- + MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR --- EnumDisplayMonitors :: proc(hdc: HDC, lprcClip: LPRECT, lpfnEnum: Monitor_Enum_Proc, dwData: LPARAM) -> BOOL --- - EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL --- + EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL --- EnumChildWindows :: proc(hWndParent: HWND, lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL --- - IsProcessDPIAware :: proc() -> BOOL --- + IsProcessDPIAware :: proc() -> BOOL --- SetProcessDPIAware :: proc() -> BOOL --- - SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT --- - GetThreadDpiAwarenessContext :: proc() -> DPI_AWARENESS_CONTEXT --- - GetWindowDpiAwarenessContext :: proc(hwnd: HWND) -> DPI_AWARENESS_CONTEXT --- + SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT --- + GetThreadDpiAwarenessContext :: proc() -> DPI_AWARENESS_CONTEXT --- + GetWindowDpiAwarenessContext :: proc(hwnd: HWND) -> DPI_AWARENESS_CONTEXT --- GetDpiFromDpiAwarenessContext :: proc(value: DPI_AWARENESS_CONTEXT) -> UINT --- - GetDpiForWindow :: proc(hwnd: HWND) -> UINT --- + GetDpiForWindow :: proc(hwnd: HWND) -> UINT --- SetProcessDpiAwarenessContext :: proc(value: DPI_AWARENESS_CONTEXT) -> BOOL --- BroadcastSystemMessageW :: proc( - flags: DWORD, + flags: DWORD, lpInfo: LPDWORD, - Msg: UINT, + Msg: UINT, wParam: WPARAM, lParam: LPARAM, ) -> c_long --- BroadcastSystemMessageExW :: proc( - flags: DWORD, - lpInfo: LPDWORD, - Msg: UINT, - wParam: WPARAM, - lParam: LPARAM, + flags: DWORD, + lpInfo: LPDWORD, + Msg: UINT, + wParam: WPARAM, + lParam: LPARAM, pbsmInfo: PBSMINFO, ) -> c_long --- SendMessageTimeoutW :: proc( - hWnd: HWND, - Msg: UINT, - wParam: WPARAM, - lParam: LPARAM, - fuFlags: UINT, - uTimeout: UINT, + hWnd: HWND, + Msg: UINT, + wParam: WPARAM, + lParam: LPARAM, + fuFlags: UINT, + uTimeout: UINT, lpdwResult: PDWORD_PTR, ) -> LRESULT --- - GetSysColor :: proc(nIndex: INT) -> DWORD --- + GetSysColor :: proc(nIndex: INT) -> DWORD --- GetSysColorBrush :: proc(nIndex: INT) -> HBRUSH --- - SetSysColors :: proc(cElements: INT, lpaElements: ^INT, lpaRgbValues: ^COLORREF) -> BOOL --- - MessageBeep :: proc(uType: UINT) -> BOOL --- + SetSysColors :: proc(cElements: INT, lpaElements: [^]INT, lpaRgbValues: ^COLORREF) -> BOOL --- + MessageBeep :: proc(uType: UINT) -> BOOL --- - IsDialogMessageW :: proc(hDlg: HWND, lpMsg: LPMSG) -> BOOL --- + IsDialogMessageW :: proc(hDlg: HWND, lpMsg: LPMSG) -> BOOL --- GetWindowTextLengthW :: proc(hWnd: HWND) -> INT --- - GetWindowTextW :: proc(hWnd: HWND, lpString: LPWSTR, nMaxCount: INT) -> INT --- - SetWindowTextW :: proc(hWnd: HWND, lpString: LPCWSTR) -> BOOL --- - CallWindowProcW :: proc(lpPrevWndFunc: WNDPROC, hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- - EnableWindow :: proc(hWnd: HWND, bEnable: BOOL) -> BOOL --- + GetWindowTextW :: proc(hWnd: HWND, lpString: LPWSTR, nMaxCount: INT) -> INT --- + SetWindowTextW :: proc(hWnd: HWND, lpString: LPCWSTR) -> BOOL --- + CallWindowProcW :: proc(lpPrevWndFunc: WNDPROC, hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT --- + EnableWindow :: proc(hWnd: HWND, bEnable: BOOL) -> BOOL --- - DefRawInputProc :: proc(paRawInput: ^PRAWINPUT, nInput: INT, cbSizeHeader: UINT) -> LRESULT --- - GetRawInputBuffer :: proc(pRawInput: PRAWINPUT, pcbSize: PUINT, cbSizeHeader: UINT) -> UINT --- - GetRawInputData :: proc(hRawInput: HRAWINPUT, uiCommand: UINT, pData: LPVOID, pcbSize: PUINT, cbSizeHeader: UINT) -> UINT --- - GetRawInputDeviceInfoW :: proc(hDevice: HANDLE, uiCommand: UINT, pData: LPVOID, pcbSize: PUINT) -> UINT --- - GetRawInputDeviceList :: proc(pRawInputDeviceList: PRAWINPUTDEVICELIST, puiNumDevices: PUINT, cbSize: UINT) -> UINT --- + DefRawInputProc :: proc(paRawInput: ^PRAWINPUT, nInput: INT, cbSizeHeader: UINT) -> LRESULT --- + GetRawInputBuffer :: proc(pRawInput: PRAWINPUT, pcbSize: PUINT, cbSizeHeader: UINT) -> UINT --- + GetRawInputData :: proc(hRawInput: HRAWINPUT, uiCommand: UINT, pData: LPVOID, pcbSize: PUINT, cbSizeHeader: UINT) -> UINT --- + GetRawInputDeviceInfoW :: proc(hDevice: HANDLE, uiCommand: UINT, pData: LPVOID, pcbSize: PUINT) -> UINT --- + GetRawInputDeviceList :: proc(pRawInputDeviceList: PRAWINPUTDEVICELIST, puiNumDevices: PUINT, cbSize: UINT) -> UINT --- GetRegisteredRawInputDevices :: proc(pRawInputDevices: PRAWINPUTDEVICE, puiNumDevices: PUINT, cbSize: UINT) -> UINT --- - RegisterRawInputDevices :: proc(pRawInputDevices: PCRAWINPUTDEVICE, uiNumDevices: UINT, cbSize: UINT) -> BOOL --- + RegisterRawInputDevices :: proc(pRawInputDevices: PCRAWINPUTDEVICE, uiNumDevices: UINT, cbSize: UINT) -> BOOL --- SendInput :: proc(cInputs: UINT, pInputs: [^]INPUT, cbSize: INT) -> UINT --- SetLayeredWindowAttributes :: proc(hWnd: HWND, crKey: COLORREF, bAlpha: BYTE, dwFlags: DWORD) -> BOOL --- - FillRect :: proc(hDC: HDC, lprc: ^RECT, hbr: HBRUSH) -> int --- - EqualRect :: proc(lprc1, lprc2: ^RECT) -> BOOL --- - OffsetRect :: proc(lprc1: ^RECT, dx, dy: INT) -> BOOL --- - InflateRect :: proc(lprc1: ^RECT, dx, dy: INT) -> BOOL --- + FillRect :: proc(hDC: HDC, lprc: ^RECT, hbr: HBRUSH) -> c_int --- + FrameRect :: proc(hDC: HDC, lprc: ^RECT, hbr: HBRUSH) -> c_int --- + InvertRect :: proc(hDC: HDC, lprc: ^RECT) -> BOOL --- + EqualRect :: proc(lprc1, lprc2: ^RECT) -> BOOL --- + OffsetRect :: proc(lprc1: ^RECT, dx, dy: INT) -> BOOL --- + InflateRect :: proc(lprc1: ^RECT, dx, dy: INT) -> BOOL --- IntersectRect :: proc(lprcDst, lprcSrc1, lprcSrc2: ^RECT) -> BOOL --- - SubtractRect :: proc(lprcDst, lprcSrc1, lprcSrc2: ^RECT) -> BOOL --- - UnionRect :: proc(lprcDst, lprcSrc1, lprcSrc2: ^RECT) -> BOOL --- - IsRectEmpty :: proc(lprc: ^RECT) -> BOOL --- - SetRectEmpty :: proc(lprc: ^RECT) -> BOOL --- - CopyRect :: proc(lprcDst, lprcSrc: ^RECT) -> BOOL --- + SubtractRect :: proc(lprcDst, lprcSrc1, lprcSrc2: ^RECT) -> BOOL --- + UnionRect :: proc(lprcDst, lprcSrc1, lprcSrc2: ^RECT) -> BOOL --- + IsRectEmpty :: proc(lprc: ^RECT) -> BOOL --- + SetRectEmpty :: proc(lprc: ^RECT) -> BOOL --- + CopyRect :: proc(lprcDst, lprcSrc: ^RECT) -> BOOL --- - GetWindowInfo :: proc(hwnd: HWND, pwi: PWINDOWINFO) -> BOOL --- - GetWindowPlacement :: proc(hWnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL --- - SetWindowPlacement :: proc(hwnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL --- - SetWindowRgn :: proc(hWnd: HWND, hRgn: HRGN, bRedraw: BOOL) -> int --- - CreateRectRgnIndirect :: proc(lprect: ^RECT) -> HRGN --- - GetSystemMetricsForDpi :: proc(nIndex: int, dpi: UINT) -> int --- + GetWindowInfo :: proc(hwnd: HWND, pwi: PWINDOWINFO) -> BOOL --- + GetWindowPlacement :: proc(hWnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL --- + SetWindowPlacement :: proc(hwnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL --- + SetWindowRgn :: proc(hWnd: HWND, hRgn: HRGN, bRedraw: BOOL) -> c_int --- + CreateRectRgnIndirect :: proc(lprect: ^RECT) -> HRGN --- + GetSystemMetricsForDpi :: proc(nIndex: c_int, dpi: UINT) -> c_int --- GetCursorInfo :: proc(pci: PCURSORINFO) -> BOOL --- - GetSystemMenu :: proc(hWnd: HWND, bRevert: BOOL) -> HMENU --- - EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL --- + GetSystemMenu :: proc(hWnd: HWND, bRevert: BOOL) -> HMENU --- + EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL --- MenuItemFromPoint :: proc(hWnd: HWND, hMenu: HMENU, ptScreen: POINT) -> INT --- - DrawTextW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat) -> INT --- + DrawTextW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat) -> INT --- DrawTextExW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat, lpdtp: PDRAWTEXTPARAMS) -> INT --- - GetLocaleInfoEx :: proc(lpLocaleName: LPCWSTR, LCType: LCTYPE, lpLCData: LPWSTR, cchData: INT) -> INT --- + GetLocaleInfoEx :: proc(lpLocaleName: LPCWSTR, LCType: LCTYPE, lpLCData: LPWSTR, cchData: INT) -> INT --- IsValidLocaleName :: proc(lpLocaleName: LPCWSTR) -> BOOL --- ResolveLocaleName :: proc(lpNameToResolve: LPCWSTR, lpLocaleName: LPWSTR, cchLocaleName: INT) -> INT --- - IsValidCodePage :: proc(CodePage: UINT) -> BOOL --- - GetACP :: proc() -> CODEPAGE --- - GetCPInfoExW :: proc(CodePage: CODEPAGE, dwFlags: DWORD, lpCPInfoEx: LPCPINFOEXW) -> BOOL --- + IsValidCodePage :: proc(CodePage: UINT) -> BOOL --- + GetACP :: proc() -> CODEPAGE --- + GetCPInfoExW :: proc(CodePage: CODEPAGE, dwFlags: DWORD, lpCPInfoEx: LPCPINFOEXW) -> BOOL --- - GetProcessWindowStation :: proc() -> HWINSTA --- + GetProcessWindowStation :: proc() -> HWINSTA --- GetUserObjectInformationW :: proc(hObj: HANDLE, nIndex: GetUserObjectInformationFlags, pvInfo: PVOID, nLength: DWORD, lpnLengthNeeded: LPDWORD) -> BOOL --- - OpenClipboard :: proc(hWndNewOwner: HWND) -> BOOL --- - CloseClipboard :: proc() -> BOOL --- - GetClipboardData :: proc(uFormat: UINT) -> HANDLE --- - SetClipboardData :: proc(uFormat: UINT, hMem: HANDLE) -> HANDLE --- - IsClipboardFormatAvailable :: proc(format: UINT) -> BOOL --- - EmptyClipboard :: proc() -> BOOL --- + OpenClipboard :: proc(hWndNewOwner: HWND) -> BOOL --- + CloseClipboard :: proc() -> BOOL --- + GetClipboardData :: proc(uFormat: UINT) -> HANDLE --- + SetClipboardData :: proc(uFormat: UINT, hMem: HANDLE) -> HANDLE --- + IsClipboardFormatAvailable :: proc(format: UINT) -> BOOL --- + EmptyClipboard :: proc() -> BOOL --- + AddClipboardFormatListener :: proc(hwnd: HWND) -> BOOL --- + ChangeClipboardChain :: proc(hWndRemove: HWND, hWndNewNext: HWND) -> BOOL --- + CountClipboardFormats :: proc() -> c_int --- + EnumClipboardFormats :: proc(format: UINT) -> UINT --- + GetClipboardFormatNameW :: proc(format: UINT, lpszFormatName: LPWSTR, cchMaxCount: c_int) -> c_int --- + GetClipboardOwner :: proc() -> HWND--- + GetClipboardSequenceNumber :: proc() -> DWORD --- + GetClipboardViewer :: proc() -> HWND --- + GetOpenClipboardWindow :: proc() -> HWND --- + GetPriorityClipboardFormat :: proc(paFormatPriorityList: ^UINT, cFormats: c_int) -> c_int --- + GetUpdatedClipboardFormats :: proc(lpuiFormats: ^UINT, cFormats: UINT, pcFormatsOut: ^UINT) -> BOOL --- + RegisterClipboardFormatW :: proc(lpszFormat: LPCWSTR ) -> UINT --- + RemoveClipboardFormatListener :: proc(hwnd: HWND) -> BOOL --- + SetClipboardViewer :: proc(hWndNewViewer: HWND) -> HWND --- + + SetScrollInfo :: proc(hwnd: HWND, nBar: c_int, lpsi: ^SCROLLINFO, redraw: BOOL) -> c_int --- + GetScrollInfo :: proc(hwnd: HWND, nBar: c_int, lpsi: ^SCROLLINFO) -> BOOL --- + ShowScrollBar :: proc(hwnd: HWND, nBar: c_int, bShow: BOOL) -> BOOL --- + EnableScrollBar :: proc(hwnd: HWND, wSBflags: UINT, wArrows: UINT) -> BOOL --- } CreateWindowW :: #force_inline proc "system" ( - lpClassName: LPCTSTR, + lpClassName: LPCTSTR, lpWindowName: LPCTSTR, - dwStyle: DWORD, - X: INT, - Y: INT, - nWidth: INT, - nHeight: INT, - hWndParent: HWND, - hMenu: HMENU, - hInstance: HINSTANCE, - lpParam: LPVOID, + dwStyle: DWORD, + X: INT, + Y: INT, + nWidth: INT, + nHeight: INT, + hWndParent: HWND, + hMenu: HMENU, + hInstance: HINSTANCE, + lpParam: LPVOID, ) -> HWND { return CreateWindowExW( 0, @@ -369,35 +394,52 @@ when ODIN_ARCH == .amd64 { SetWindowLongPtrW :: SetWindowLongW } +@(require_results) GET_SC_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> INT { return INT(wParam) & 0xFFF0 } +@(require_results) GET_WHEEL_DELTA_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> c_short { return cast(c_short)HIWORD(cast(DWORD)wParam) } +@(require_results) GET_KEYSTATE_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> WORD { return LOWORD(cast(DWORD)wParam) } +@(require_results) GET_NCHITTEST_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> c_short { return cast(c_short)LOWORD(cast(DWORD)wParam) } +@(require_results) GET_XBUTTON_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> WORD { return HIWORD(cast(DWORD)wParam) } // Retrieves the input code from wParam in WM_INPUT message. +@(require_results) GET_RAWINPUT_CODE_WPARAM :: #force_inline proc "contextless" (wParam: WPARAM) -> RAWINPUT_CODE { return RAWINPUT_CODE(wParam & 0xFF) } +@(require_results) MAKEINTRESOURCEW :: #force_inline proc "contextless" (#any_int i: int) -> LPWSTR { return cast(LPWSTR)uintptr(WORD(i)) } +@(require_results) +RAWINPUT_ALIGN :: proc "contextless" (x: uintptr) -> uintptr { + return (x + size_of(uintptr) - 1) & ~uintptr(size_of(uintptr) - 1) +} + +@(require_results) +NEXTRAWINPUTBLOCK :: proc "contextless" (ptr: ^RAWINPUT) -> ^RAWINPUT { + return cast(^RAWINPUT)RAWINPUT_ALIGN(uintptr(ptr) + uintptr(ptr.header.dwSize)) +} + Monitor_From_Flags :: enum DWORD { MONITOR_DEFAULTTONULL = 0x00000000, // Returns NULL MONITOR_DEFAULTTOPRIMARY = 0x00000001, // Returns a handle to the primary display monitor @@ -405,7 +447,7 @@ Monitor_From_Flags :: enum DWORD { } Monitor_Enum_Proc :: #type proc "system" (HMONITOR, HDC, LPRECT, LPARAM) -> BOOL -Window_Enum_Proc :: #type proc "system" (HWND, LPARAM) -> BOOL +Window_Enum_Proc :: #type proc "system" (HWND, LPARAM) -> BOOL USER_DEFAULT_SCREEN_DPI :: 96 DPI_AWARENESS_CONTEXT :: distinct HANDLE @@ -415,7 +457,7 @@ DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE :: DPI_AWARENESS_CONTEXT(~uintptr(2)) DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 :: DPI_AWARENESS_CONTEXT(~uintptr(3)) // -4 DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED :: DPI_AWARENESS_CONTEXT(~uintptr(4)) // -5 -RAWINPUT_CODE :: enum { +RAWINPUT_CODE :: enum DWORD { // The input is in the regular message flow, // the app is required to call DefWindowProc // so that the system can perform clean ups. @@ -426,16 +468,16 @@ RAWINPUT_CODE :: enum { } RAWINPUTHEADER :: struct { - dwType: DWORD, - dwSize: DWORD, + dwType: DWORD, + dwSize: DWORD, hDevice: HANDLE, - wParam: WPARAM, + wParam: WPARAM, } RAWHID :: struct { dwSizeHid: DWORD, - dwCount: DWORD, - bRawData: [1]BYTE, + dwCount: DWORD, + bRawData: [1]BYTE, } RAWMOUSE :: struct { @@ -447,27 +489,27 @@ RAWMOUSE :: struct { usButtonData: USHORT, }, }, - ulRawButtons: ULONG, - lLastX: LONG, - lLastY: LONG, + ulRawButtons: ULONG, + lLastX: LONG, + lLastY: LONG, ulExtraInformation: ULONG, } RAWKEYBOARD :: struct { - MakeCode: USHORT, - Flags: USHORT, - Rserved: USHORT, - VKey: USHORT, - Message: UINT, + MakeCode: USHORT, + Flags: USHORT, + Rserved: USHORT, + VKey: USHORT, + Message: UINT, ExtraInformation: ULONG, } RAWINPUT :: struct { header: RAWINPUTHEADER, data: struct #raw_union { - mouse: RAWMOUSE, + mouse: RAWMOUSE, keyboard: RAWKEYBOARD, - hid: RAWHID, + hid: RAWHID, }, } @@ -476,42 +518,42 @@ HRAWINPUT :: distinct LPARAM RAWINPUTDEVICE :: struct { usUsagePage: USHORT, - usUsage: USHORT, - dwFlags: DWORD, - hwndTarget: HWND, + usUsage: USHORT, + dwFlags: DWORD, + hwndTarget: HWND, } -PRAWINPUTDEVICE :: ^RAWINPUTDEVICE +PRAWINPUTDEVICE :: ^RAWINPUTDEVICE PCRAWINPUTDEVICE :: PRAWINPUTDEVICE RAWINPUTDEVICELIST :: struct { hDevice: HANDLE, - dwType: DWORD, + dwType: DWORD, } PRAWINPUTDEVICELIST :: ^RAWINPUTDEVICELIST RID_DEVICE_INFO_HID :: struct { - dwVendorId: DWORD, - dwProductId: DWORD, + dwVendorId: DWORD, + dwProductId: DWORD, dwVersionNumber: DWORD, - usUsagePage: USHORT, - usUsage: USHORT, + usUsagePage: USHORT, + usUsage: USHORT, } RID_DEVICE_INFO_KEYBOARD :: struct { - dwType: DWORD, - dwSubType: DWORD, - dwKeyboardMode: DWORD, + dwType: DWORD, + dwSubType: DWORD, + dwKeyboardMode: DWORD, dwNumberOfFunctionKeys: DWORD, - dwNumberOfIndicators: DWORD, - dwNumberOfKeysTotal: DWORD, + dwNumberOfIndicators: DWORD, + dwNumberOfKeysTotal: DWORD, } RID_DEVICE_INFO_MOUSE :: struct { - dwId: DWORD, - dwNumberOfButtons: DWORD, - dwSampleRate: DWORD, + dwId: DWORD, + dwNumberOfButtons: DWORD, + dwSampleRate: DWORD, fHasHorizontalWheel: BOOL, } @@ -519,103 +561,103 @@ RID_DEVICE_INFO :: struct { cbSize: DWORD, dwType: DWORD, using DUMMYUNIONNAME: struct #raw_union { - mouse: RID_DEVICE_INFO_MOUSE, - keyboard: RID_DEVICE_INFO_KEYBOARD, - hid: RID_DEVICE_INFO_HID, + mouse: RID_DEVICE_INFO_MOUSE `raw_union_tag:"dwType=0"`, + keyboard: RID_DEVICE_INFO_KEYBOARD `raw_union_tag:"dwType=1"`, + hid: RID_DEVICE_INFO_HID `raw_union_tag:"dwType=2"`, }, } -RIDEV_REMOVE :: 0x00000001 -RIDEV_EXCLUDE :: 0x00000010 -RIDEV_PAGEONLY :: 0x00000020 -RIDEV_NOLEGACY :: 0x00000030 -RIDEV_INPUTSINK :: 0x00000100 +RIDEV_REMOVE :: 0x00000001 +RIDEV_EXCLUDE :: 0x00000010 +RIDEV_PAGEONLY :: 0x00000020 +RIDEV_NOLEGACY :: 0x00000030 +RIDEV_INPUTSINK :: 0x00000100 RIDEV_CAPTUREMOUSE :: 0x00000200 -RIDEV_NOHOTKEYS :: 0x00000200 -RIDEV_APPKEYS :: 0x00000400 -RIDEV_EXINPUTSINK :: 0x00001000 -RIDEV_DEVNOTIFY :: 0x00002000 +RIDEV_NOHOTKEYS :: 0x00000200 +RIDEV_APPKEYS :: 0x00000400 +RIDEV_EXINPUTSINK :: 0x00001000 +RIDEV_DEVNOTIFY :: 0x00002000 RID_HEADER :: 0x10000005 -RID_INPUT :: 0x10000003 +RID_INPUT :: 0x10000003 RIDI_PREPARSEDDATA :: 0x20000005 -RIDI_DEVICENAME :: 0x20000007 -RIDI_DEVICEINFO :: 0x2000000b +RIDI_DEVICENAME :: 0x20000007 +RIDI_DEVICEINFO :: 0x2000000b -RIM_TYPEMOUSE :: 0 +RIM_TYPEMOUSE :: 0 RIM_TYPEKEYBOARD :: 1 -RIM_TYPEHID :: 2 +RIM_TYPEHID :: 2 -RI_KEY_MAKE :: 0 -RI_KEY_BREAK :: 1 -RI_KEY_E0 :: 2 -RI_KEY_E1 :: 4 +RI_KEY_MAKE :: 0 +RI_KEY_BREAK :: 1 +RI_KEY_E0 :: 2 +RI_KEY_E1 :: 4 RI_KEY_TERMSRV_SET_LED :: 8 -RI_KEY_TERMSRV_SHADOW :: 0x10 +RI_KEY_TERMSRV_SHADOW :: 0x10 -MOUSE_MOVE_RELATIVE :: 0x00 -MOUSE_MOVE_ABSOLUTE :: 0x01 -MOUSE_VIRTUAL_DESKTOP :: 0x02 +MOUSE_MOVE_RELATIVE :: 0x00 +MOUSE_MOVE_ABSOLUTE :: 0x01 +MOUSE_VIRTUAL_DESKTOP :: 0x02 MOUSE_ATTRIBUTES_CHANGED :: 0x04 -MOUSE_MOVE_NOCOALESCE :: 0x08 +MOUSE_MOVE_NOCOALESCE :: 0x08 -RI_MOUSE_BUTTON_1_DOWN :: 0x0001 -RI_MOUSE_LEFT_BUTTON_DOWN :: RI_MOUSE_BUTTON_1_DOWN -RI_MOUSE_BUTTON_1_UP :: 0x0002 -RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP -RI_MOUSE_BUTTON_2_DOWN :: 0x0004 -RI_MOUSE_RIGHT_BUTTON_DOWN :: RI_MOUSE_BUTTON_2_DOWN -RI_MOUSE_BUTTON_2_UP :: 0x0008 -RI_MOUSE_RIGHT_BUTTON_UP :: RI_MOUSE_BUTTON_2_UP -RI_MOUSE_BUTTON_3_DOWN :: 0x0010 +RI_MOUSE_BUTTON_1_DOWN :: 0x0001 +RI_MOUSE_LEFT_BUTTON_DOWN :: RI_MOUSE_BUTTON_1_DOWN +RI_MOUSE_BUTTON_1_UP :: 0x0002 +RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP +RI_MOUSE_BUTTON_2_DOWN :: 0x0004 +RI_MOUSE_RIGHT_BUTTON_DOWN :: RI_MOUSE_BUTTON_2_DOWN +RI_MOUSE_BUTTON_2_UP :: 0x0008 +RI_MOUSE_RIGHT_BUTTON_UP :: RI_MOUSE_BUTTON_2_UP +RI_MOUSE_BUTTON_3_DOWN :: 0x0010 RI_MOUSE_MIDDLE_BUTTON_DOWN :: RI_MOUSE_BUTTON_3_DOWN -RI_MOUSE_BUTTON_3_UP :: 0x0020 -RI_MOUSE_MIDDLE_BUTTON_UP :: RI_MOUSE_BUTTON_3_UP -RI_MOUSE_BUTTON_4_DOWN :: 0x0040 -RI_MOUSE_BUTTON_4_UP :: 0x0080 -RI_MOUSE_BUTTON_5_DOWN :: 0x0100 -RI_MOUSE_BUTTON_5_UP :: 0x0200 -RI_MOUSE_WHEEL :: 0x0400 -RI_MOUSE_HWHEEL :: 0x0800 +RI_MOUSE_BUTTON_3_UP :: 0x0020 +RI_MOUSE_MIDDLE_BUTTON_UP :: RI_MOUSE_BUTTON_3_UP +RI_MOUSE_BUTTON_4_DOWN :: 0x0040 +RI_MOUSE_BUTTON_4_UP :: 0x0080 +RI_MOUSE_BUTTON_5_DOWN :: 0x0100 +RI_MOUSE_BUTTON_5_UP :: 0x0200 +RI_MOUSE_WHEEL :: 0x0400 +RI_MOUSE_HWHEEL :: 0x0800 WINDOWPLACEMENT :: struct { - length: UINT, - flags: UINT, - showCmd: UINT, - ptMinPosition: POINT, - ptMaxPosition: POINT, + length: UINT, + flags: UINT, + showCmd: UINT, + ptMinPosition: POINT, + ptMaxPosition: POINT, rcNormalPosition: RECT, } WINDOWINFO :: struct { - cbSize: DWORD, - rcWindow: RECT, - rcClient: RECT, - dwStyle: DWORD, - dwExStyle: DWORD, - dwWindowStatus: DWORD, + cbSize: DWORD, + rcWindow: RECT, + rcClient: RECT, + dwStyle: DWORD, + dwExStyle: DWORD, + dwWindowStatus: DWORD, cxWindowBorders: UINT, cyWindowBorders: UINT, - atomWindowType: ATOM, + atomWindowType: ATOM, wCreatorVersion: WORD, } PWINDOWINFO :: ^WINDOWINFO CURSORINFO :: struct { - cbSize: DWORD, - flags: DWORD, - hCursor: HCURSOR, + cbSize: DWORD, + flags: DWORD, + hCursor: HCURSOR, ptScreenPos: POINT, } PCURSORINFO :: ^CURSORINFO DRAWTEXTPARAMS :: struct { - cbSize: UINT, - iTabLength: INT, - iLeftMargin: INT, - iRightMargin: INT, + cbSize: UINT, + iTabLength: INT, + iLeftMargin: INT, + iRightMargin: INT, uiLengthDrawn: UINT, } PDRAWTEXTPARAMS :: ^DRAWTEXTPARAMS @@ -673,12 +715,12 @@ GetUserObjectInformationFlags :: enum INT { } USEROBJECTFLAGS :: struct { - fInherit: BOOL, + fInherit: BOOL, fReserved: BOOL, - dwFlags: DWORD, + dwFlags: DWORD, } -PROPENUMPROCW :: #type proc(unnamedParam1: HWND, unnamedParam2: LPCWSTR, unnamedParam3: HANDLE) -> BOOL +PROPENUMPROCW :: #type proc(unnamedParam1: HWND, unnamedParam2: LPCWSTR, unnamedParam3: HANDLE) -> BOOL PROPENUMPROCEXW :: #type proc(unnamedParam1: HWND, unnamedParam2: LPCWSTR, unnamedParam3: HANDLE, unnamedParam4: ULONG_PTR) -> BOOL RT_CURSOR :: LPWSTR(uintptr(0x00000001)) @@ -713,8 +755,8 @@ MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID :: LPWSTR(uintptr(0x00000010) ACCEL :: struct { /* Also called the flags field */ fVirt: BYTE, - key: WORD, - cmd: WORD, + key: WORD, + cmd: WORD, } LPACCEL :: ^ACCEL @@ -730,32 +772,32 @@ MIIM_BITMAP :: 0x00000080 MIIM_FTYPE :: 0x00000100 MENUITEMINFOW :: struct { - cbSize: UINT, - fMask: UINT, - fType: UINT, // used if MIIM_TYPE (4.0) or MIIM_FTYPE (>4.0) - fState: UINT, // used if MIIM_STATE - wID: UINT, // used if MIIM_ID - hSubMenu: HMENU, // used if MIIM_SUBMENU - hbmpChecked: HBITMAP, // used if MIIM_CHECKMARKS + cbSize: UINT, + fMask: UINT, + fType: UINT, // used if MIIM_TYPE (4.0) or MIIM_FTYPE (>4.0) + fState: UINT, // used if MIIM_STATE + wID: UINT, // used if MIIM_ID + hSubMenu: HMENU, // used if MIIM_SUBMENU + hbmpChecked: HBITMAP, // used if MIIM_CHECKMARKS hbmpUnchecked: HBITMAP, // used if MIIM_CHECKMARKS - dwItemData: ULONG_PTR, // used if MIIM_DATA - dwTypeData: LPWSTR, // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) - cch: UINT, // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) - hbmpItem: HBITMAP, // used if MIIM_BITMAP + dwItemData: ULONG_PTR, // used if MIIM_DATA + dwTypeData: LPWSTR, // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) + cch: UINT, // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) + hbmpItem: HBITMAP, // used if MIIM_BITMAP } LPMENUITEMINFOW :: ^MENUITEMINFOW DISPLAY_DEVICEW :: struct { - cb: DWORD, - DeviceName: [32]WCHAR, + cb: DWORD, + DeviceName: [32]WCHAR, DeviceString: [128]WCHAR, - StateFlags: DWORD, - DeviceID: [128]WCHAR, - DeviceKey: [128]WCHAR, + StateFlags: DWORD, + DeviceID: [128]WCHAR, + DeviceKey: [128]WCHAR, } PDISPLAY_DEVICEW :: ^DISPLAY_DEVICEW // OUTOFCONTEXT is the zero value, use {} -WinEventFlags :: bit_set[WinEventFlag; DWORD] +WinEventFlags :: distinct bit_set[WinEventFlag; DWORD] WinEventFlag :: enum DWORD { SKIPOWNTHREAD = 0, @@ -792,7 +834,7 @@ CF_PRIVATEFIRST :: 0x0200 CF_PRIVATELAST :: 0x02FF STICKYKEYS :: struct { - cbSize: UINT, + cbSize: UINT, dwFlags: DWORD, } LPSTICKYKEYS :: ^STICKYKEYS @@ -822,7 +864,7 @@ SKF_LALTLATCHED :: 0x10000000 SKF_RALTLATCHED :: 0x20000000 TOGGLEKEYS :: struct { - cbSize: UINT, + cbSize: UINT, dwFlags: DWORD, } LPTOGGLEKEYS :: ^TOGGLEKEYS @@ -835,10 +877,10 @@ TKF_HOTKEYSOUND :: 0x10 TKF_INDICATOR :: 0x20 FILTERKEYS :: struct { - cbSize: UINT, - dwFlags: DWORD, - iWaitMSec: DWORD, - iDelayMSec: DWORD, + cbSize: UINT, + dwFlags: DWORD, + iWaitMSec: DWORD, + iDelayMSec: DWORD, iRepeatMSec: DWORD, iBounceMSec: DWORD, } @@ -853,21 +895,95 @@ FKF_INDICATOR :: 0x20 FKF_CLICKON :: 0x40 NONCLIENTMETRICSW :: struct { - cbSize: UINT, - iBorderWidth: i32, - iScrollWidth: i32, - iScrollHeight: i32, - iCaptionWidth: i32, - iCaptionHeight: i32, - lfCaptionFont: LOGFONTW, - iSmCaptionWidth: i32, - iSmCaptionHeight: i32, - lfSmCaptionFont: LOGFONTW, - iMenuWidth: i32, - iMenuHeight: i32, - lfMenuFont: LOGFONTW, - lfStatusFont: LOGFONTW, - lfMessageFont: LOGFONTW, - iPaddedBorderWidth: i32, + cbSize: UINT, + iBorderWidth: c_int, + iScrollWidth: c_int, + iScrollHeight: c_int, + iCaptionWidth: c_int, + iCaptionHeight: c_int, + lfCaptionFont: LOGFONTW, + iSmCaptionWidth: c_int, + iSmCaptionHeight: c_int, + lfSmCaptionFont: LOGFONTW, + iMenuWidth: c_int, + iMenuHeight: c_int, + lfMenuFont: LOGFONTW, + lfStatusFont: LOGFONTW, + lfMessageFont: LOGFONTW, + iPaddedBorderWidth: c_int, } LPNONCLIENTMETRICSW :: ^NONCLIENTMETRICSW + +LWA_COLORKEY :: 0x1 +LWA_ALPHA :: 0x2 + +SCROLLINFO :: struct { + cbSize: UINT, + fMask: UINT, + nMin: c_int, + nMax: c_int, + nPage: UINT, + nPos: c_int, + nTrackPos: c_int, +} +LPSCROLLINFO :: ^SCROLLINFO + +// Scroll Bar Constants +SB_MIN :: 0 +SB_HORZ :: 0 +SB_VERT :: 1 +SB_CTL :: 2 +SB_BOTH :: 3 + +// Scroll Bar Commands +SB_LINEUP :: 0 +SB_LINELEFT :: 0 +SB_LINEDOWN :: 1 +SB_LINERIGHT :: 1 +SB_PAGEUP :: 2 +SB_PAGELEFT :: 2 +SB_PAGEDOWN :: 3 +SB_PAGERIGHT :: 3 +SB_THUMBPOSITION :: 4 +SB_THUMBTRACK :: 5 +SB_TOP :: 6 +SB_LEFT :: 6 +SB_BOTTOM :: 7 +SB_RIGHT :: 7 +SB_ENDSCROLL :: 8 + +// Constants for SCROLLINFO.fMask +SIF_RANGE :: 0x0001 +SIF_PAGE :: 0x0002 +SIF_POS :: 0x0004 +SIF_DISABLENOSCROLL :: 0x0008 +SIF_TRACKPOS :: 0x0010 +SIF_ALL :: (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS) + +// EnableScrollBar() flags +ESB_ENABLE_BOTH :: 0x0000 +ESB_DISABLE_BOTH :: 0x0003 +ESB_DISABLE_LEFT :: 0x0001 +ESB_DISABLE_RIGHT :: 0x0002 +ESB_DISABLE_UP :: 0x0001 +ESB_DISABLE_DOWN :: 0x0002 +ESB_DISABLE_LTUP :: ESB_DISABLE_LEFT +ESB_DISABLE_RTDN :: ESB_DISABLE_RIGHT + +// Command constants for GetWindow +GW_HWNDFIRST :: 0 +GW_HWNDLAST :: 1 +GW_HWNDNEXT :: 2 +GW_HWNDPREV :: 3 +GW_OWNER :: 4 +GW_CHILD :: 5 +GW_ENABLEDPOPUP :: 6 +GW_MAX :: 6 + +COPYDATASTRUCT :: struct { + dwData: ULONG_PTR, + cbData: DWORD, + lpData: PVOID, +} + +PCOPYDATASTRUCT :: ^COPYDATASTRUCT diff --git a/core/sys/windows/userenv.odin b/core/sys/windows/userenv.odin index 2a2209d2c..1ed731407 100644 --- a/core/sys/windows/userenv.odin +++ b/core/sys/windows/userenv.odin @@ -5,19 +5,22 @@ foreign import userenv "system:Userenv.lib" @(default_calling_convention="system") foreign userenv { - GetUserProfileDirectoryW :: proc(hToken: HANDLE, - lpProfileDir: LPWSTR, - lpcchSize: ^DWORD) -> BOOL --- + GetUserProfileDirectoryW :: proc( + hToken: HANDLE, + lpProfileDir: LPWSTR, + lpcchSize: ^DWORD, + ) -> BOOL --- + LoadUserProfileW :: proc( - hToken: HANDLE, + hToken: HANDLE, lpProfileInfo: ^PROFILEINFOW, ) -> BOOL --- // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-createprofile // The caller must have administrator privileges to call this function. CreateProfile :: proc( - pszUserSid: LPCWSTR, - pszUserName: LPCWSTR, + pszUserSid: LPCWSTR, + pszUserName: LPCWSTR, pszProfilePath: wstring, cchProfilePath: DWORD, ) -> u32 --- @@ -25,15 +28,15 @@ foreign userenv { // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-deleteprofilew // The caller must have administrative privileges to delete a user's profile. DeleteProfileW :: proc( - lpSidString: LPCWSTR, - lpProfilePath: LPCWSTR, + lpSidString: LPCWSTR, + lpProfilePath: LPCWSTR, lpComputerName: LPCWSTR, ) -> BOOL --- // https://docs.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertsidtostringsida // To turn a SID into a string SID to use with CreateProfile & DeleteProfileW. ConvertSidToStringSidW :: proc( - Sid: ^SID, + Sid: ^SID, StringSid: ^LPCWSTR, ) -> BOOL --- } diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index b3eb800bc..fc2b61033 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -7,123 +7,244 @@ import "base:intrinsics" L :: intrinsics.constant_utf16_cstring // https://learn.microsoft.com/en-us/windows/win32/winmsg/makeword +@(require_results) MAKEWORD :: #force_inline proc "contextless" (#any_int a, b: int) -> WORD { return WORD(BYTE(DWORD_PTR(a) & 0xff)) | (WORD(BYTE(DWORD_PTR(b) & 0xff)) << 8) } // https://learn.microsoft.com/en-us/windows/win32/winmsg/makelong +@(require_results) MAKELONG :: #force_inline proc "contextless" (#any_int a, b: int) -> LONG { return LONG(WORD(DWORD_PTR(a) & 0xffff)) | (LONG(WORD(DWORD_PTR(b) & 0xffff)) << 16) } // https://learn.microsoft.com/en-us/windows/win32/winmsg/loword +@(require_results) LOWORD :: #force_inline proc "contextless" (#any_int x: int) -> WORD { return WORD(x & 0xffff) } // https://learn.microsoft.com/en-us/windows/win32/winmsg/hiword +@(require_results) HIWORD :: #force_inline proc "contextless" (#any_int x: int) -> WORD { return WORD(x >> 16) } // https://learn.microsoft.com/en-us/windows/win32/winmsg/lobyte +@(require_results) LOBYTE :: #force_inline proc "contextless" (w: WORD) -> BYTE { return BYTE((DWORD_PTR(w)) & 0xff) } // https://learn.microsoft.com/en-us/windows/win32/winmsg/hibyte +@(require_results) HIBYTE :: #force_inline proc "contextless" (w: WORD) -> BYTE { return BYTE(((DWORD_PTR(w)) >> 8) & 0xff) } // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-makewparam +@(require_results) MAKEWPARAM :: #force_inline proc "contextless" (#any_int l, h: int) -> WPARAM { return WPARAM(MAKELONG(l, h)) } // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-makelparam +@(require_results) MAKELPARAM :: #force_inline proc "contextless" (#any_int l, h: int) -> LPARAM { return LPARAM(MAKELONG(l, h)) } // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-makelresult +@(require_results) MAKELRESULT :: #force_inline proc "contextless" (#any_int l, h: int) -> LRESULT { return LRESULT(MAKELONG(l, h)) } // https://learn.microsoft.com/en-us/windows/win32/api/windowsx/nf-windowsx-get_x_lparam +@(require_results) GET_X_LPARAM :: #force_inline proc "contextless" (lp: LPARAM) -> c_int { return cast(c_int)cast(c_short)LOWORD(cast(DWORD)lp) } // https://learn.microsoft.com/en-us/windows/win32/api/windowsx/nf-windowsx-get_y_lparam +@(require_results) GET_Y_LPARAM :: #force_inline proc "contextless" (lp: LPARAM) -> c_int { return cast(c_int)cast(c_short)HIWORD(cast(DWORD)lp) } // https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-makelcid +@(require_results) MAKELCID :: #force_inline proc "contextless" (lgid, srtid: WORD) -> LCID { return (DWORD(WORD(srtid)) << 16) | DWORD(WORD(lgid)) } // https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-makelangid +@(require_results) MAKELANGID :: #force_inline proc "contextless" (p, s: WORD) -> DWORD { return DWORD(WORD(s)) << 10 | DWORD(WORD(p)) } +@(require_results) LANGIDFROMLCID :: #force_inline proc "contextless" (lcid: LCID) -> LANGID { return LANGID(lcid) } -// this one gave me trouble as it do not mask the values. -// the _ in the name is also off comparing to the c code -// i can't find any usage in the odin repo -@(deprecated = "use MAKEWORD") -MAKE_WORD :: #force_inline proc "contextless" (x, y: WORD) -> WORD { - return x << 8 | y -} - -utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 { - if len(s) < 1 { +@(require_results) +utf8_to_utf16_alloc :: proc(s: string, allocator := context.temp_allocator) -> []u16 { + s_length := len(s) + if s_length < 1 { + return nil + } + if s_length > cast(int)max(c_int) { + // Unsupported (input string is excessively long). return nil } b := transmute([]byte)s cstr := raw_data(b) - n := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0) - if n == 0 { + n := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, c_int(s_length), nil, 0) + if n <= 0 || cast(int)n >= max(int) { + // If n is equal to or greater than max(int), then we will not be able + // to create a big enough slice with the null terminator. + // NOTE: This only affects 32-bit systems and is purely pedantic because + // the system will never be able to allocate that much memory. return nil } - text := make([]u16, n+1, allocator) + text := make([]u16, cast(int)n + 1, allocator) + if text == nil { + return nil + } - n1 := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, i32(len(s)), raw_data(text), n) - if n1 == 0 { + n1 := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, cstr, c_int(s_length), raw_data(text), n) + if n1 <= 0 { delete(text, allocator) return nil } + // null-terminate the result here, even though the null element is not + // part of the slice. This is done to prevent callers which relied on + // this behavior, and is also expected by utf8_to_wstring_alloc. text[n] = 0 - for n >= 1 && text[n-1] == 0 { - n -= 1 - } return text[:n] } -utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstring { - if res := utf8_to_utf16(s, allocator); len(res) > 0 { - return raw_data(res) + +@(require_results) +utf8_to_utf16_buf :: proc(buf: []u16, s: string) -> []u16 { + buf_length := len(buf) + if buf_length < 1 { + return nil } - return nil + s_length := len(s) + if s_length == 0 { + return nil + } + if s_length > cast(int)max(c_int) { + // Unsupported (input string is excessively long). + return nil + } + if buf_length > cast(int)max(c_int) { + buf_length = cast(int)max(c_int) + } + elements_written := MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, raw_data(s), c_int(s_length), raw_data(buf), cast(c_int)buf_length) + if elements_written <= 0 { + // Insufficient buffer size, empty input string, or invalid characters. Contents of the buffer may have been modified. + return nil + } + + // To be consistent with utf8_to_utf16_alloc, the output string + // is null-terminated here in the buffer, even though the terminating null character + // is not part of the returned slice. + if buf_length <= cast(int)elements_written { + // The terminating null character does not fit. + // Need at least a length of (elements_written+1). + return nil + } + buf[elements_written] = 0 + return buf[:elements_written] } -wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) { +// Converts a regular UTF-8 `string` to UTF-16. +// +// The conversion includes any null characters present in the input string. +// +// Returns `nil` on conversion failure. +// +// Conversion may fail due to an invalid byte sequence in the input string, +// or an insufficient buffer size (`utf8_to_utf16_buf` only), +// or allocation failure (`utf8_to_utf16_alloc` only). +// +// The result of converting an empty string is indistinguishable from conversion failure. +utf8_to_utf16 :: proc{utf8_to_utf16_alloc, utf8_to_utf16_buf} + +@(require_results) +utf8_to_wstring_alloc :: proc(s: string, allocator := context.temp_allocator) -> wstring { + if len(s) == 0 { + // Empty string. Needs special care because an empty string + // is different from conversion failure. + buf := make([]u16, 1, allocator) + if buf == nil { + return nil + } + buf[0] = 0 + return wstring(raw_data(buf)) + } + // utf8_to_utf16 null-terminates the result in the allocated memory block, + // however, the null character is not part of the returned slice (it is just beyond). + // The conversion to wstring will bypass this implicit overrun. + res := utf8_to_utf16(s, allocator) + if len(res) > 0 { + return wstring(raw_data(res)) + } else { + // Conversion failure. + return nil + } +} + +@(require_results) +utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring { + buf_length := len(buf) + if buf_length == 0 { + // Insufficient buffer size, even for an empty string. + return nil + } + if len(s) == 0 { + // Empty string. Needs special care because an empty string + // is different from conversion failure. + buf[0] = 0 + return wstring(raw_data(buf)) + } + // utf8_to_utf16 null-terminates the result in the buffer, + // however, the null character is not part of the returned slice (it is just beyond). + // The conversion to wstring will bypass this implicit overrun. + res := utf8_to_utf16(buf[:], s) + if len(res) > 0 { + return wstring(raw_data(res)) + } else { + // Conversion failure. + return nil + } +} + +// Converts a regular UTF-8 `string` to UTF-16, and returns the result as a +// null-terminated `wstring`, or `nil` on conversion failure. +// +// Conversion may fail due to an invalid byte sequence in the input string, +// or an insufficient buffer size (`utf8_to_wstring_buf` only), +// or allocation failure (`utf8_to_wstring_alloc` only). +// +// An empty string is valid, and results in a value distinct from `nil`. +utf8_to_wstring :: proc{utf8_to_wstring_alloc, utf8_to_wstring_buf} + +@(require_results) +wstring_to_utf8_alloc :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) { context.allocator = allocator if N == 0 { return } - n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N) if N > 0 else -1, nil, 0, nil, nil) + n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, c_int(N) if N > 0 else -1, nil, 0, nil, nil) if n == 0 { return } @@ -135,7 +256,7 @@ wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) // will not be null terminated. text := make([]byte, n) or_return - n1 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), raw_data(text), n, nil, nil) + n1 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, c_int(N), raw_data(text), n, nil, nil) if n1 == 0 { delete(text, allocator) return @@ -150,17 +271,86 @@ wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) return string(text[:n]), nil } -utf16_to_utf8 :: proc(s: []u16, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) { +@(require_results) +wstring_to_utf8_buf :: proc(buf: []u8, s: wstring, N := -1) -> (res: string) { + n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, c_int(N), nil, 0, nil, nil) + if n == 0 { + return + } else if int(n) > len(buf) { + return + } + + n2 := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, c_int(N), raw_data(buf), n, nil, nil) + if n2 == 0 { + return + } else if int(n2) > len(buf) { + return + } + + for i in 0.. (res: string, err: runtime.Allocator_Error) { if len(s) == 0 { return "", nil } - return wstring_to_utf8(raw_data(s), len(s), allocator) + return wstring_to_utf8(wstring(raw_data(s)), len(s), allocator) } +/* +Converts a UTF-16 string into a regular UTF-8 `string`, using `buf` as its backing. +If the input is null-terminated, only the part of the input string leading up +to it will be converted. + +*Uses `buf` for backing* + +Inputs: +- s: The string to be converted +- buf: Backing buffer for result string + +Returns: +- res: A converted string, backed byu `buf` +*/ +@(require_results) +utf16_to_utf8_buf :: proc(buf: []u8, s: []u16) -> (res: string) { + if len(s) == 0 { + return + } + return wstring_to_utf8(buf, wstring(raw_data(s)), len(s)) +} + +utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf} + + // AdvAPI32, NetAPI32 and UserENV helpers. -allowed_username :: proc(username: string) -> bool { - contains_any :: proc(s, chars: string) -> bool { +@(require_results) +allowed_username :: proc "contextless" (username: string) -> bool { + contains_any :: proc "contextless" (s, chars: string) -> bool { if chars == "" { return false } @@ -202,8 +392,8 @@ allowed_username :: proc(username: string) -> bool { } // Returns .Success on success. +@(require_results) _add_user :: proc(servername: string, username: string, password: string) -> (ok: NET_API_STATUS) { - servername_w: wstring username_w: []u16 password_w: []u16 @@ -213,7 +403,7 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok servername_w = nil } else { server := utf8_to_utf16(servername, context.temp_allocator) - servername_w = &server[0] + servername_w = wstring(&server[0]) } if len(username) == 0 || len(username) > LM20_UNLEN { @@ -254,8 +444,8 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok return } +@(require_results) get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: string, sid := SID{}, ok: bool) { - username_w := utf8_to_utf16(username, context.temp_allocator) cbsid: DWORD computer_name_size: DWORD @@ -263,7 +453,7 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s res := LookupAccountNameW( nil, // Look on this computer first - &username_w[0], + wstring(&username_w[0]), &sid, &cbsid, nil, @@ -275,14 +465,14 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s return "", {}, false } - cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator) + cname_w := make([]u16, computer_name_size, context.temp_allocator) res = LookupAccountNameW( nil, - &username_w[0], + wstring(&username_w[0]), &sid, &cbsid, - &cname_w[0], + wstring(&cname_w[0]), &computer_name_size, &pe_use, ) @@ -296,8 +486,8 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s return } +@(require_results) get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { - username_w := utf8_to_utf16(username, context.temp_allocator) cbsid: DWORD computer_name_size: DWORD @@ -305,7 +495,7 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { res := LookupAccountNameW( nil, // Look on this computer first - &username_w[0], + wstring(&username_w[0]), sid, &cbsid, nil, @@ -317,14 +507,14 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { return false } - cname_w := make([]u16, min(computer_name_size, 1), context.temp_allocator) + cname_w := make([]u16, computer_name_size, context.temp_allocator) res = LookupAccountNameW( nil, - &username_w[0], + wstring(&username_w[0]), sid, &cbsid, - &cname_w[0], + wstring(&cname_w[0]), &computer_name_size, &pe_use, ) @@ -343,7 +533,7 @@ add_user_to_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupAddMembers( nil, - &group_name[0], + wstring(&group_name[0]), 0, &group_member, 1, @@ -358,7 +548,7 @@ add_del_from_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupDelMembers( nil, - &group_name[0], + cstring16(&group_name[0]), 0, &group_member, 1, @@ -366,6 +556,7 @@ add_del_from_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { return } +@(require_results) add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) { username_w := utf8_to_utf16(username, context.temp_allocator) @@ -380,19 +571,19 @@ add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) { if res == false { return false, "" } - defer LocalFree(sb) + defer LocalFree(rawptr(sb)) pszProfilePath := make([]u16, 257, context.temp_allocator) res2 := CreateProfile( sb, - &username_w[0], - &pszProfilePath[0], + cstring16(&username_w[0]), + cstring16(&pszProfilePath[0]), 257, ) if res2 != 0 { return false, "" } - profile_path = wstring_to_utf8(&pszProfilePath[0], 257) or_else "" + profile_path = wstring_to_utf8(wstring(&pszProfilePath[0]), 257) or_else "" return true, profile_path } @@ -410,7 +601,7 @@ delete_user_profile :: proc(username: string) -> (ok: bool) { if res == false { return false } - defer LocalFree(sb) + defer LocalFree(rawptr(sb)) res2 := DeleteProfileW( sb, @@ -463,13 +654,13 @@ delete_user :: proc(servername: string, username: string) -> (ok: bool) { servername_w = nil } else { server := utf8_to_utf16(servername, context.temp_allocator) - servername_w = &server[0] + servername_w = wstring(&server[0]) } username_w := utf8_to_utf16(username) res := NetUserDel( servername_w, - &username_w[0], + wstring(&username_w[0]), ) if res != .Success { return false @@ -501,9 +692,9 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P user_token: HANDLE ok = bool(LogonUserW( - lpszUsername = &username_w[0], - lpszDomain = &domain_w[0], - lpszPassword = &password_w[0], + lpszUsername = wstring(&username_w[0]), + lpszDomain = wstring(&domain_w[0]), + lpszPassword = wstring(&password_w[0]), dwLogonType = .NEW_CREDENTIALS, dwLogonProvider = .WINNT50, phToken = &user_token, @@ -516,12 +707,11 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P } si := STARTUPINFOW{} si.cb = size_of(STARTUPINFOW) - pi := pi ok = bool(CreateProcessAsUserW( user_token, - &app_w[0], - &commandline_w[0], + wstring(&app_w[0]), + wstring(&commandline_w[0]), nil, // lpProcessAttributes, nil, // lpThreadAttributes, false, // bInheritHandles, @@ -543,11 +733,11 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P } } -ensure_winsock_initialized :: proc() { +ensure_winsock_initialized :: proc "contextless" () { @static gate := false @static initted := false - if initted { + if intrinsics.atomic_load(&initted) { return } @@ -559,7 +749,7 @@ ensure_winsock_initialized :: proc() { unused_info: WSADATA version_requested := WORD(2) << 8 | 2 res := WSAStartup(version_requested, &unused_info) - assert(res == 0, "unable to initialized Winsock2") + assert_contextless(res == 0, "unable to initialized Winsock2") - initted = true + intrinsics.atomic_store(&initted, true) } diff --git a/core/sys/windows/ux_theme.odin b/core/sys/windows/ux_theme.odin index 679d9998f..e19800246 100644 --- a/core/sys/windows/ux_theme.odin +++ b/core/sys/windows/ux_theme.odin @@ -3,11 +3,73 @@ package sys_windows foreign import uxtheme "system:UxTheme.lib" -MARGINS :: distinct [4]i32 +MARGINS :: struct { + cxLeftWidth: c_int, + cxRightWidth: c_int, + cyTopHeight: c_int, + cyBottomHeight: c_int, +} PMARGINS :: ^MARGINS @(default_calling_convention="system") foreign uxtheme { - IsThemeActive :: proc() -> BOOL --- - SetWindowTheme :: proc(hWnd: HWND, pszSubAppName, pszSubIdList: LPCWSTR) -> HRESULT --- + IsThemeActive :: proc() -> BOOL --- + GetWindowTheme :: proc(hwnd: HWND) -> HTHEME --- + SetWindowTheme :: proc(hWnd: HWND, pszSubAppName, pszSubIdList: LPCWSTR) -> HRESULT --- + + // Buffered painting and buffered animation + BufferedPaintInit :: proc() -> HRESULT --- + BufferedPaintUnInit :: proc() -> HRESULT --- + + BeginBufferedPaint :: proc(hdcTarget: HDC, prcTarget: ^RECT, dwFormat: BP_BUFFERFORMAT, pPaintParams: ^BP_PAINTPARAMS, phdc: ^HDC) -> HPAINTBUFFER --- + EndBufferedPaint :: proc(hBufferedPaint: HPAINTBUFFER, fUpdateTarget: BOOL) -> HRESULT --- + + GetBufferedPaintTargetRect :: proc(hBufferedPaint: HPAINTBUFFER, prc: ^RECT) -> HRESULT --- + GetBufferedPaintTargetDC :: proc(hBufferedPaint: HPAINTBUFFER) -> HDC --- + GetBufferedPaintDC :: proc(hBufferedPaint: HPAINTBUFFER) -> HDC --- + GetBufferedPaintBits :: proc(hBufferedPaint, ppbBuffer: ^[^]RGBQUAD, pcxRow: ^c_int) -> HRESULT --- + + BufferedPaintClear :: proc(hBufferedPaint: HPAINTBUFFER, prc: ^RECT) -> HRESULT --- + BufferedPaintSetAlpha :: proc(hBufferedPaint: HPAINTBUFFER, prc: ^RECT, alpha: BYTE) -> HRESULT --- + + BufferedPaintStopAllAnimations :: proc(hwnd: HWND) -> HRESULT --- + BeginBufferedAnimation :: proc(hwnd: HWND, hdcTarget: HDC, prcTarget: ^RECT, dwFormat: BP_BUFFERFORMAT, pPaintParams: ^BP_PAINTPARAMS, pAnimationParams: ^BP_ANIMATIONPARAMS, phdcFrom: ^HDC, phdcTo: ^HDC) -> HANIMATIONBUFFER --- + BufferedPaintRenderAnimation :: proc(hwnd: HWND, hdcTarget: HDC) -> BOOL --- +} + +HTHEME :: distinct HANDLE +HPAINTBUFFER :: distinct HANDLE +HANIMATIONBUFFER :: distinct HANDLE + +BP_BUFFERFORMAT :: enum c_int { + BPBF_COMPATIBLEBITMAP, + BPBF_DIB, + BPBF_TOPDOWNDIB, + BPBF_TOPDOWNMONODIB, +} + +BP_ANIMATIONSTYLE :: enum c_int { + BPAS_NONE, + BPAS_LINEAR, + BPAS_CUBIC, + BPAS_SINE, +} + +// Constants for BP_PAINTPARAMS.dwFlags +BPPF_ERASE :: 0x0001 +BPPF_NOCLIP :: 0x0002 +BPPF_NONCLIENT :: 0x0004 + +BP_ANIMATIONPARAMS :: struct { + cbSize: DWORD, + dwFlags: DWORD, + style: BP_ANIMATIONSTYLE, + dwDuration: DWORD, +} + +BP_PAINTPARAMS :: struct { + cbSize: DWORD, + dwFlags: DWORD, + prcExclude: ^RECT, + pBlendFunction: ^BLENDFUNCTION, } diff --git a/core/sys/windows/wgl.odin b/core/sys/windows/wgl.odin index 8fea55c3d..532a987eb 100644 --- a/core/sys/windows/wgl.odin +++ b/core/sys/windows/wgl.odin @@ -1,8 +1,6 @@ #+build windows package sys_windows -import "core:c" - foreign import "system:Opengl32.lib" CONTEXT_MAJOR_VERSION_ARB :: 0x2091 @@ -54,9 +52,9 @@ GLYPHMETRICSFLOAT :: struct { gmfCellIncY: f32, } -CreateContextAttribsARBType :: #type proc "c" (hdc: HDC, hShareContext: rawptr, attribList: [^]c.int) -> HGLRC -ChoosePixelFormatARBType :: #type proc "c" (hdc: HDC, attribIList: [^]c.int, attribFList: [^]f32, maxFormats: DWORD, formats: [^]c.int, numFormats: [^]DWORD) -> BOOL -SwapIntervalEXTType :: #type proc "c" (interval: c.int) -> bool +CreateContextAttribsARBType :: #type proc "c" (hdc: HDC, hShareContext: rawptr, attribList: [^]c_int) -> HGLRC +ChoosePixelFormatARBType :: #type proc "c" (hdc: HDC, attribIList: [^]c_int, attribFList: [^]f32, maxFormats: DWORD, formats: [^]c_int, numFormats: [^]DWORD) -> BOOL +SwapIntervalEXTType :: #type proc "c" (interval: c_int) -> bool GetExtensionsStringARBType :: #type proc "c" (HDC) -> cstring // Procedures @@ -73,17 +71,18 @@ foreign Opengl32 { wglGetProcAddress :: proc(c_str: cstring) -> rawptr --- wglDeleteContext :: proc(HGLRC: HGLRC) -> BOOL --- wglCopyContext :: proc(src, dst: HGLRC, mask: UINT) -> BOOL --- - wglCreateLayerContext :: proc(hdc: HDC, layer_plane: c.int) -> HGLRC --- - wglDescribeLayerPlane :: proc(hdc: HDC, pixel_format, layer_plane: c.int, bytes: UINT, pd: LPLAYERPLANEDESCRIPTOR) -> BOOL --- + wglCreateLayerContext :: proc(hdc: HDC, layer_plane: c_int) -> HGLRC --- + wglDescribeLayerPlane :: proc(hdc: HDC, pixel_format, layer_plane: c_int, bytes: UINT, pd: LPLAYERPLANEDESCRIPTOR) -> BOOL --- wglGetCurrentContext :: proc() -> HGLRC --- wglGetCurrentDC :: proc() -> HDC --- - wglGetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c.int, cr: ^COLORREF) -> c.int --- - wglRealizeLayerPalette :: proc(hdc: HDC, layer_plane: c.int, realize: BOOL) -> BOOL --- - wglSetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c.int, cr: ^COLORREF) -> c.int --- + wglGetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c_int, cr: ^COLORREF) -> c_int --- + wglRealizeLayerPalette :: proc(hdc: HDC, layer_plane: c_int, realize: BOOL) -> BOOL --- + wglSetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c_int, cr: ^COLORREF) -> c_int --- wglShareLists :: proc(HGLRC1, HGLRC2: HGLRC) -> BOOL --- wglSwapLayerBuffers :: proc(hdc: HDC, planes: DWORD) -> BOOL --- - wglUseFontBitmaps :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- - wglUseFontOutlines :: proc(hdc: HDC, first, count, list_base: DWORD, deviation, extrusion: f32, format: c.int, gmf: LPGLYPHMETRICSFLOAT) -> BOOL --- + wglUseFontBitmapsA :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- + wglUseFontBitmapsW :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- + wglUseFontOutlines :: proc(hdc: HDC, first, count, list_base: DWORD, deviation, extrusion: f32, format: c_int, gmf: LPGLYPHMETRICSFLOAT) -> BOOL --- } // Used by vendor:OpenGL @@ -92,7 +91,7 @@ gl_set_proc_address :: proc(p: rawptr, name: cstring) { func := wglGetProcAddress(name) switch uintptr(func) { case 0, 1, 2, 3, ~uintptr(0): - module := LoadLibraryW(L("opengl32.dll")) + module := LoadLibraryW("opengl32.dll") func = GetProcAddress(module, name) } (^rawptr)(p)^ = func diff --git a/core/sys/windows/winerror.odin b/core/sys/windows/winerror.odin index 61a7d9d86..2807ca0f8 100644 --- a/core/sys/windows/winerror.odin +++ b/core/sys/windows/winerror.odin @@ -173,6 +173,9 @@ FACILITY :: enum DWORD { EAS = 85, WEB = 885, WEB_SOCKET = 886, + XAUDIO2 = 896, + XAPO = 897, + GAMEINPUT = 906, MOBILE = 1793, SQLITE = 1967, SERVICE_FABRIC = 1968, @@ -219,9 +222,11 @@ ERROR_LOCK_FAILED : DWORD : 167 ERROR_ALREADY_EXISTS : DWORD : 183 ERROR_NO_DATA : DWORD : 232 ERROR_ENVVAR_NOT_FOUND : DWORD : 203 +ERROR_MR_MID_NOT_FOUND : DWORD : 317 ERROR_OPERATION_ABORTED : DWORD : 995 ERROR_IO_PENDING : DWORD : 997 ERROR_NO_UNICODE_TRANSLATION : DWORD : 1113 +ERROR_NOT_FOUND : DWORD : 1168 ERROR_TIMEOUT : DWORD : 1460 ERROR_DATATYPE_MISMATCH : DWORD : 1629 ERROR_UNSUPPORTED_TYPE : DWORD : 1630 @@ -231,6 +236,7 @@ ERROR_PIPE_BUSY : DWORD : 231 // https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values S_OK :: 0x00000000 // Operation successful +S_FALSE :: 0x00000001 E_NOTIMPL :: 0x80004001 // Not implemented E_NOINTERFACE :: 0x80004002 // No such interface supported E_POINTER :: 0x80004003 // Pointer that is not valid @@ -242,6 +248,13 @@ E_HANDLE :: 0x80070006 // Handle that is not valid E_OUTOFMEMORY :: 0x8007000E // Failed to allocate necessary memory E_INVALIDARG :: 0x80070057 // One or more arguments are not valid +SEC_E_INCOMPLETE_MESSAGE :: 0x80090318 + +SEC_I_INCOMPLETE_CREDENTIALS :: 0x00090320 +SEC_I_CONTINUE_NEEDED :: 0x00090312 +SEC_I_CONTEXT_EXPIRED :: 0x00090317 +SEC_I_RENEGOTIATE :: 0x00090321 + // Severity values SEVERITY :: enum DWORD { SUCCESS = 0, @@ -270,6 +283,10 @@ MAKE_HRESULT :: #force_inline proc "contextless" (#any_int sev: int, #any_int fa return HRESULT((uint(sev)<<31) | (uint(fac)<<16) | (uint(code))) } +HRESULT_FROM_WIN32 :: #force_inline proc "contextless" (#any_int code: int) -> HRESULT { + return HRESULT(code) <= 0 ? HRESULT(code) : HRESULT(uint(code & 0x0000FFFF) | (uint(FACILITY.WIN32) << 16) | 0x80000000) +} + DECODE_HRESULT :: #force_inline proc "contextless" (#any_int hr: int) -> (SEVERITY, FACILITY, int) { return HRESULT_SEVERITY(hr), HRESULT_FACILITY(hr), HRESULT_CODE(hr) } diff --git a/core/sys/windows/winmm.odin b/core/sys/windows/winmm.odin index 3c7ec80e7..d1848cb7b 100644 --- a/core/sys/windows/winmm.odin +++ b/core/sys/windows/winmm.odin @@ -12,28 +12,28 @@ foreign winmm { timeEndPeriod :: proc(uPeriod: UINT) -> MMRESULT --- timeGetTime :: proc() -> DWORD --- - waveOutGetNumDevs :: proc() -> UINT --- - waveOutGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwoc: LPWAVEOUTCAPSW, cbwoc: UINT) -> MMRESULT --- - waveOutGetVolume :: proc(hwo: HWAVEOUT, pdwVolume: LPDWORD) -> MMRESULT --- - waveOutSetVolume :: proc(hwo: HWAVEOUT, dwVolume: DWORD) -> MMRESULT --- - waveOutGetErrorTextW :: proc(mmrError: MMRESULT, pszText: LPWSTR, cchText: UINT) -> MMRESULT --- - waveOutOpen :: proc(phwo: LPHWAVEOUT, uDeviceID: UINT, pwfx: LPCWAVEFORMATEX, dwCallback: DWORD_PTR, dwInstance: DWORD_PTR, fdwOpen: DWORD) -> MMRESULT --- - waveOutClose :: proc(hwo: HWAVEOUT) -> MMRESULT --- - waveOutPrepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- + waveOutGetNumDevs :: proc() -> UINT --- + waveOutGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwoc: LPWAVEOUTCAPSW, cbwoc: UINT) -> MMRESULT --- + waveOutGetVolume :: proc(hwo: HWAVEOUT, pdwVolume: LPDWORD) -> MMRESULT --- + waveOutSetVolume :: proc(hwo: HWAVEOUT, dwVolume: DWORD) -> MMRESULT --- + waveOutGetErrorTextW :: proc(mmrError: MMRESULT, pszText: LPWSTR, cchText: UINT) -> MMRESULT --- + waveOutOpen :: proc(phwo: LPHWAVEOUT, uDeviceID: UINT, pwfx: LPCWAVEFORMATEX, dwCallback: DWORD_PTR, dwInstance: DWORD_PTR, fdwOpen: DWORD) -> MMRESULT --- + waveOutClose :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutPrepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- waveOutUnprepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- - waveOutWrite :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- - waveOutPause :: proc(hwo: HWAVEOUT) -> MMRESULT --- - waveOutRestart :: proc(hwo: HWAVEOUT) -> MMRESULT --- - waveOutReset :: proc(hwo: HWAVEOUT) -> MMRESULT --- - waveOutBreakLoop :: proc(hwo: HWAVEOUT) -> MMRESULT --- - waveOutGetPosition :: proc(hwo: HWAVEOUT, pmmt: LPMMTIME, cbmmt: UINT) -> MMRESULT --- - waveOutGetPitch :: proc(hwo: HWAVEOUT, pdwPitch: LPDWORD) -> MMRESULT --- - waveOutSetPitch :: proc(hwo: HWAVEOUT, pdwPitch: DWORD) -> MMRESULT --- + waveOutWrite :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- + waveOutPause :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutRestart :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutReset :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutBreakLoop :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutGetPosition :: proc(hwo: HWAVEOUT, pmmt: LPMMTIME, cbmmt: UINT) -> MMRESULT --- + waveOutGetPitch :: proc(hwo: HWAVEOUT, pdwPitch: LPDWORD) -> MMRESULT --- + waveOutSetPitch :: proc(hwo: HWAVEOUT, pdwPitch: DWORD) -> MMRESULT --- waveOutGetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: LPDWORD) -> MMRESULT --- waveOutSetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: DWORD) -> MMRESULT --- - waveOutGetID :: proc(hwo: HWAVEOUT, puDeviceID: LPUINT) -> MMRESULT --- + waveOutGetID :: proc(hwo: HWAVEOUT, puDeviceID: LPUINT) -> MMRESULT --- - waveInGetNumDevs :: proc() -> UINT --- + waveInGetNumDevs :: proc() -> UINT --- waveInGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwic: LPWAVEINCAPSW, cbwic: UINT) -> MMRESULT --- PlaySoundW :: proc(pszSound: LPCWSTR, hmod: HMODULE, fdwSound: DWORD) -> BOOL --- @@ -265,17 +265,17 @@ HWAVE :: distinct HANDLE HWAVEIN :: distinct HANDLE HWAVEOUT :: distinct HANDLE -LPHWAVEIN :: ^HWAVEIN +LPHWAVEIN :: ^HWAVEIN LPHWAVEOUT :: ^HWAVEOUT // https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-timer-structures MMTIME :: struct { wType: MMTIME_TYPE, u: struct #raw_union { - ms: DWORD, - sample: DWORD, - cb: DWORD, - ticks: DWORD, + ms: DWORD `raw_union_tag:"wType=TIME_MS"`, + sample: DWORD `raw_union_tag:"wType=TIME_SAMPLES"`, + cb: DWORD `raw_union_tag:"wType=TIME_BYTES"`, + ticks: DWORD `raw_union_tag:"wType=TIME_TICKS"`, smpte: struct { hour: BYTE, min: BYTE, @@ -284,10 +284,10 @@ MMTIME :: struct { fps: BYTE, dummy: BYTE, pad: [2]BYTE, - }, + } `raw_union_tag:"wType=TIME_SMPTE"`, midi: struct { songptrpos: DWORD, - }, + } `raw_union_tag:"wType=TIME_MIDI"`, }, } LPMMTIME :: ^MMTIME @@ -307,14 +307,290 @@ MMTIME_TYPE :: enum UINT { TIME_TICKS = 0x0020, } -MAXPNAMELEN :: 32 +MAXPNAMELEN :: 32 MAXERRORLENGTH :: 256 -MMVERSION :: UINT +MMVERSION :: UINT + +// Input is four characters string +// Output is little-endian u32 representation +@(require_results) +MAKEFOURCC :: #force_inline proc "contextless" (s: [4]byte) -> DWORD { + return (DWORD(s[0])) | (DWORD(s[1]) << 8) | (DWORD(s[2]) << 16) | (DWORD(s[3]) << 24 ) +} /* flags for wFormatTag field of WAVEFORMAT */ WAVE_FORMAT_PCM :: 1 -WAVEFORMATEX :: struct { +WAVE_FORMAT_UNKNOWN :: 0x0000 /* Microsoft Corporation */ +WAVE_FORMAT_ADPCM :: 0x0002 /* Microsoft Corporation */ +WAVE_FORMAT_IEEE_FLOAT :: 0x0003 /* Microsoft Corporation */ +WAVE_FORMAT_VSELP :: 0x0004 /* Compaq Computer Corp. */ +WAVE_FORMAT_IBM_CVSD :: 0x0005 /* IBM Corporation */ +WAVE_FORMAT_ALAW :: 0x0006 /* Microsoft Corporation */ +WAVE_FORMAT_MULAW :: 0x0007 /* Microsoft Corporation */ +WAVE_FORMAT_DTS :: 0x0008 /* Microsoft Corporation */ +WAVE_FORMAT_DRM :: 0x0009 /* Microsoft Corporation */ +WAVE_FORMAT_WMAVOICE9 :: 0x000A /* Microsoft Corporation */ +WAVE_FORMAT_WMAVOICE10 :: 0x000B /* Microsoft Corporation */ +WAVE_FORMAT_OKI_ADPCM :: 0x0010 /* OKI */ +WAVE_FORMAT_DVI_ADPCM :: 0x0011 /* Intel Corporation */ +WAVE_FORMAT_IMA_ADPCM :: WAVE_FORMAT_DVI_ADPCM /* Intel Corporation */ +WAVE_FORMAT_MEDIASPACE_ADPCM :: 0x0012 /* Videologic */ +WAVE_FORMAT_SIERRA_ADPCM :: 0x0013 /* Sierra Semiconductor Corp */ +WAVE_FORMAT_G723_ADPCM :: 0x0014 /* Antex Electronics Corporation */ +WAVE_FORMAT_DIGISTD :: 0x0015 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIGIFIX :: 0x0016 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIALOGIC_OKI_ADPCM :: 0x0017 /* Dialogic Corporation */ +WAVE_FORMAT_MEDIAVISION_ADPCM :: 0x0018 /* Media Vision, Inc. */ +WAVE_FORMAT_CU_CODEC :: 0x0019 /* Hewlett-Packard Company */ +WAVE_FORMAT_HP_DYN_VOICE :: 0x001A /* Hewlett-Packard Company */ +WAVE_FORMAT_YAMAHA_ADPCM :: 0x0020 /* Yamaha Corporation of America */ +WAVE_FORMAT_SONARC :: 0x0021 /* Speech Compression */ +WAVE_FORMAT_DSPGROUP_TRUESPEECH :: 0x0022 /* DSP Group, Inc */ +WAVE_FORMAT_ECHOSC1 :: 0x0023 /* Echo Speech Corporation */ +WAVE_FORMAT_AUDIOFILE_AF36 :: 0x0024 /* Virtual Music, Inc. */ +WAVE_FORMAT_APTX :: 0x0025 /* Audio Processing Technology */ +WAVE_FORMAT_AUDIOFILE_AF10 :: 0x0026 /* Virtual Music, Inc. */ +WAVE_FORMAT_PROSODY_1612 :: 0x0027 /* Aculab plc */ +WAVE_FORMAT_LRC :: 0x0028 /* Merging Technologies S.A. */ +WAVE_FORMAT_DOLBY_AC2 :: 0x0030 /* Dolby Laboratories */ +WAVE_FORMAT_GSM610 :: 0x0031 /* Microsoft Corporation */ +WAVE_FORMAT_MSNAUDIO :: 0x0032 /* Microsoft Corporation */ +WAVE_FORMAT_ANTEX_ADPCME :: 0x0033 /* Antex Electronics Corporation */ +WAVE_FORMAT_CONTROL_RES_VQLPC :: 0x0034 /* Control Resources Limited */ +WAVE_FORMAT_DIGIREAL :: 0x0035 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIGIADPCM :: 0x0036 /* DSP Solutions, Inc. */ +WAVE_FORMAT_CONTROL_RES_CR10 :: 0x0037 /* Control Resources Limited */ +WAVE_FORMAT_NMS_VBXADPCM :: 0x0038 /* Natural MicroSystems */ +WAVE_FORMAT_CS_IMAADPCM :: 0x0039 /* Crystal Semiconductor IMA ADPCM */ +WAVE_FORMAT_ECHOSC3 :: 0x003A /* Echo Speech Corporation */ +WAVE_FORMAT_ROCKWELL_ADPCM :: 0x003B /* Rockwell International */ +WAVE_FORMAT_ROCKWELL_DIGITALK :: 0x003C /* Rockwell International */ +WAVE_FORMAT_XEBEC :: 0x003D /* Xebec Multimedia Solutions Limited */ +WAVE_FORMAT_G721_ADPCM :: 0x0040 /* Antex Electronics Corporation */ +WAVE_FORMAT_G728_CELP :: 0x0041 /* Antex Electronics Corporation */ +WAVE_FORMAT_MSG723 :: 0x0042 /* Microsoft Corporation */ +WAVE_FORMAT_INTEL_G723_1 :: 0x0043 /* Intel Corp. */ +WAVE_FORMAT_INTEL_G729 :: 0x0044 /* Intel Corp. */ +WAVE_FORMAT_SHARP_G726 :: 0x0045 /* Sharp */ +WAVE_FORMAT_MPEG :: 0x0050 /* Microsoft Corporation */ +WAVE_FORMAT_RT24 :: 0x0052 /* InSoft, Inc. */ +WAVE_FORMAT_PAC :: 0x0053 /* InSoft, Inc. */ +WAVE_FORMAT_MPEGLAYER3 :: 0x0055 /* ISO/MPEG Layer3 Format Tag */ +WAVE_FORMAT_LUCENT_G723 :: 0x0059 /* Lucent Technologies */ +WAVE_FORMAT_CIRRUS :: 0x0060 /* Cirrus Logic */ +WAVE_FORMAT_ESPCM :: 0x0061 /* ESS Technology */ +WAVE_FORMAT_VOXWARE :: 0x0062 /* Voxware Inc */ +WAVE_FORMAT_CANOPUS_ATRAC :: 0x0063 /* Canopus, co., Ltd. */ +WAVE_FORMAT_G726_ADPCM :: 0x0064 /* APICOM */ +WAVE_FORMAT_G722_ADPCM :: 0x0065 /* APICOM */ +WAVE_FORMAT_DSAT :: 0x0066 /* Microsoft Corporation */ +WAVE_FORMAT_DSAT_DISPLAY :: 0x0067 /* Microsoft Corporation */ +WAVE_FORMAT_VOXWARE_BYTE_ALIGNED :: 0x0069 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC8 :: 0x0070 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC10 :: 0x0071 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC16 :: 0x0072 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC20 :: 0x0073 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT24 :: 0x0074 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT29 :: 0x0075 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT29HW :: 0x0076 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_VR12 :: 0x0077 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_VR18 :: 0x0078 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_TQ40 :: 0x0079 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_SC3 :: 0x007A /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_SC3_1 :: 0x007B /* Voxware Inc */ +WAVE_FORMAT_SOFTSOUND :: 0x0080 /* Softsound, Ltd. */ +WAVE_FORMAT_VOXWARE_TQ60 :: 0x0081 /* Voxware Inc */ +WAVE_FORMAT_MSRT24 :: 0x0082 /* Microsoft Corporation */ +WAVE_FORMAT_G729A :: 0x0083 /* AT&T Labs, Inc. */ +WAVE_FORMAT_MVI_MVI2 :: 0x0084 /* Motion Pixels */ +WAVE_FORMAT_DF_G726 :: 0x0085 /* DataFusion Systems (Pty) (Ltd) */ +WAVE_FORMAT_DF_GSM610 :: 0x0086 /* DataFusion Systems (Pty) (Ltd) */ +WAVE_FORMAT_ISIAUDIO :: 0x0088 /* Iterated Systems, Inc. */ +WAVE_FORMAT_ONLIVE :: 0x0089 /* OnLive! Technologies, Inc. */ +WAVE_FORMAT_MULTITUDE_FT_SX20 :: 0x008A /* Multitude Inc. */ +WAVE_FORMAT_INFOCOM_ITS_G721_ADPCM :: 0x008B /* Infocom */ +WAVE_FORMAT_CONVEDIA_G729 :: 0x008C /* Convedia Corp. */ +WAVE_FORMAT_CONGRUENCY :: 0x008D /* Congruency Inc. */ +WAVE_FORMAT_SBC24 :: 0x0091 /* Siemens Business Communications Sys */ +WAVE_FORMAT_DOLBY_AC3_SPDIF :: 0x0092 /* Sonic Foundry */ +WAVE_FORMAT_MEDIASONIC_G723 :: 0x0093 /* MediaSonic */ +WAVE_FORMAT_PROSODY_8KBPS :: 0x0094 /* Aculab plc */ +WAVE_FORMAT_ZYXEL_ADPCM :: 0x0097 /* ZyXEL Communications, Inc. */ +WAVE_FORMAT_PHILIPS_LPCBB :: 0x0098 /* Philips Speech Processing */ +WAVE_FORMAT_PACKED :: 0x0099 /* Studer Professional Audio AG */ +WAVE_FORMAT_MALDEN_PHONYTALK :: 0x00A0 /* Malden Electronics Ltd. */ +WAVE_FORMAT_RACAL_RECORDER_GSM :: 0x00A1 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_G720_A :: 0x00A2 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_G723_1 :: 0x00A3 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_TETRA_ACELP :: 0x00A4 /* Racal recorders */ +WAVE_FORMAT_NEC_AAC :: 0x00B0 /* NEC Corp. */ +WAVE_FORMAT_RAW_AAC1 :: 0x00FF /* For Raw AAC, with format block AudioSpecificConfig() (as defined by MPEG-4), that follows WAVEFORMATEX */ +WAVE_FORMAT_RHETOREX_ADPCM :: 0x0100 /* Rhetorex Inc. */ +WAVE_FORMAT_IRAT :: 0x0101 /* BeCubed Software Inc. */ +WAVE_FORMAT_VIVO_G723 :: 0x0111 /* Vivo Software */ +WAVE_FORMAT_VIVO_SIREN :: 0x0112 /* Vivo Software */ +WAVE_FORMAT_PHILIPS_CELP :: 0x0120 /* Philips Speech Processing */ +WAVE_FORMAT_PHILIPS_GRUNDIG :: 0x0121 /* Philips Speech Processing */ +WAVE_FORMAT_DIGITAL_G723 :: 0x0123 /* Digital Equipment Corporation */ +WAVE_FORMAT_SANYO_LD_ADPCM :: 0x0125 /* Sanyo Electric Co., Ltd. */ +WAVE_FORMAT_SIPROLAB_ACEPLNET :: 0x0130 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_ACELP4800 :: 0x0131 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_ACELP8V3 :: 0x0132 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_G729 :: 0x0133 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_G729A :: 0x0134 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_KELVIN :: 0x0135 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_VOICEAGE_AMR :: 0x0136 /* VoiceAge Corp. */ +WAVE_FORMAT_G726ADPCM :: 0x0140 /* Dictaphone Corporation */ +WAVE_FORMAT_DICTAPHONE_CELP68 :: 0x0141 /* Dictaphone Corporation */ +WAVE_FORMAT_DICTAPHONE_CELP54 :: 0x0142 /* Dictaphone Corporation */ +WAVE_FORMAT_QUALCOMM_PUREVOICE :: 0x0150 /* Qualcomm, Inc. */ +WAVE_FORMAT_QUALCOMM_HALFRATE :: 0x0151 /* Qualcomm, Inc. */ +WAVE_FORMAT_TUBGSM :: 0x0155 /* Ring Zero Systems, Inc. */ +WAVE_FORMAT_MSAUDIO1 :: 0x0160 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO2 :: 0x0161 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO3 :: 0x0162 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO_LOSSLESS :: 0x0163 /* Microsoft Corporation */ +WAVE_FORMAT_WMASPDIF :: 0x0164 /* Microsoft Corporation */ +WAVE_FORMAT_UNISYS_NAP_ADPCM :: 0x0170 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_ULAW :: 0x0171 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_ALAW :: 0x0172 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_16K :: 0x0173 /* Unisys Corp. */ +WAVE_FORMAT_SYCOM_ACM_SYC008 :: 0x0174 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_G726L :: 0x0175 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_CELP54 :: 0x0176 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_CELP68 :: 0x0177 /* SyCom Technologies */ +WAVE_FORMAT_KNOWLEDGE_ADVENTURE_ADPCM :: 0x0178 /* Knowledge Adventure, Inc. */ +WAVE_FORMAT_FRAUNHOFER_IIS_MPEG2_AAC :: 0x0180 /* Fraunhofer IIS */ +WAVE_FORMAT_DTS_DS :: 0x0190 /* Digital Theatre Systems, Inc. */ +WAVE_FORMAT_CREATIVE_ADPCM :: 0x0200 /* Creative Labs, Inc */ +WAVE_FORMAT_CREATIVE_FASTSPEECH8 :: 0x0202 /* Creative Labs, Inc */ +WAVE_FORMAT_CREATIVE_FASTSPEECH10 :: 0x0203 /* Creative Labs, Inc */ +WAVE_FORMAT_UHER_ADPCM :: 0x0210 /* UHER informatic GmbH */ +WAVE_FORMAT_ULEAD_DV_AUDIO :: 0x0215 /* Ulead Systems, Inc. */ +WAVE_FORMAT_ULEAD_DV_AUDIO_1 :: 0x0216 /* Ulead Systems, Inc. */ +WAVE_FORMAT_QUARTERDECK :: 0x0220 /* Quarterdeck Corporation */ +WAVE_FORMAT_ILINK_VC :: 0x0230 /* I-link Worldwide */ +WAVE_FORMAT_RAW_SPORT :: 0x0240 /* Aureal Semiconductor */ +WAVE_FORMAT_ESST_AC3 :: 0x0241 /* ESS Technology, Inc. */ +WAVE_FORMAT_GENERIC_PASSTHRU :: 0x0249 +WAVE_FORMAT_IPI_HSX :: 0x0250 /* Interactive Products, Inc. */ +WAVE_FORMAT_IPI_RPELP :: 0x0251 /* Interactive Products, Inc. */ +WAVE_FORMAT_CS2 :: 0x0260 /* Consistent Software */ +WAVE_FORMAT_SONY_SCX :: 0x0270 /* Sony Corp. */ +WAVE_FORMAT_SONY_SCY :: 0x0271 /* Sony Corp. */ +WAVE_FORMAT_SONY_ATRAC3 :: 0x0272 /* Sony Corp. */ +WAVE_FORMAT_SONY_SPC :: 0x0273 /* Sony Corp. */ +WAVE_FORMAT_TELUM_AUDIO :: 0x0280 /* Telum Inc. */ +WAVE_FORMAT_TELUM_IA_AUDIO :: 0x0281 /* Telum Inc. */ +WAVE_FORMAT_NORCOM_VOICE_SYSTEMS_ADPCM :: 0x0285 /* Norcom Electronics Corp. */ +WAVE_FORMAT_FM_TOWNS_SND :: 0x0300 /* Fujitsu Corp. */ +WAVE_FORMAT_MICRONAS :: 0x0350 /* Micronas Semiconductors, Inc. */ +WAVE_FORMAT_MICRONAS_CELP833 :: 0x0351 /* Micronas Semiconductors, Inc. */ +WAVE_FORMAT_BTV_DIGITAL :: 0x0400 /* Brooktree Corporation */ +WAVE_FORMAT_INTEL_MUSIC_CODER :: 0x0401 /* Intel Corp. */ +WAVE_FORMAT_INDEO_AUDIO :: 0x0402 /* Ligos */ +WAVE_FORMAT_QDESIGN_MUSIC :: 0x0450 /* QDesign Corporation */ +WAVE_FORMAT_ON2_VP7_AUDIO :: 0x0500 /* On2 Technologies */ +WAVE_FORMAT_ON2_VP6_AUDIO :: 0x0501 /* On2 Technologies */ +WAVE_FORMAT_VME_VMPCM :: 0x0680 /* AT&T Labs, Inc. */ +WAVE_FORMAT_TPC :: 0x0681 /* AT&T Labs, Inc. */ +WAVE_FORMAT_LIGHTWAVE_LOSSLESS :: 0x08AE /* Clearjump */ +WAVE_FORMAT_OLIGSM :: 0x1000 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLIADPCM :: 0x1001 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLICELP :: 0x1002 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLISBC :: 0x1003 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLIOPR :: 0x1004 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_LH_CODEC :: 0x1100 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_CELP :: 0x1101 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC8 :: 0x1102 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC12 :: 0x1103 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC16 :: 0x1104 /* Lernout & Hauspie */ +WAVE_FORMAT_NORRIS :: 0x1400 /* Norris Communications, Inc. */ +WAVE_FORMAT_ISIAUDIO_2 :: 0x1401 /* ISIAudio */ +WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS :: 0x1500 /* AT&T Labs, Inc. */ +WAVE_FORMAT_MPEG_ADTS_AAC :: 0x1600 /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_RAW_AAC :: 0x1601 /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_LOAS :: 0x1602 /* Microsoft Corporation (MPEG-4 Audio Transport Streams (LOAS/LATM) */ +WAVE_FORMAT_NOKIA_MPEG_ADTS_AAC :: 0x1608 /* Microsoft Corporation */ +WAVE_FORMAT_NOKIA_MPEG_RAW_AAC :: 0x1609 /* Microsoft Corporation */ +WAVE_FORMAT_VODAFONE_MPEG_ADTS_AAC :: 0x160A /* Microsoft Corporation */ +WAVE_FORMAT_VODAFONE_MPEG_RAW_AAC :: 0x160B /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_HEAAC :: 0x1610 /* Microsoft Corporation (MPEG-2 AAC or MPEG-4 HE-AAC v1/v2 streams with any payload (ADTS, ADIF, LOAS/LATM, RAW). Format block includes MP4 AudioSpecificConfig() -- see HEAACWAVEFORMAT below */ +WAVE_FORMAT_VOXWARE_RT24_SPEECH :: 0x181C /* Voxware Inc. */ +WAVE_FORMAT_SONICFOUNDRY_LOSSLESS :: 0x1971 /* Sonic Foundry */ +WAVE_FORMAT_INNINGS_TELECOM_ADPCM :: 0x1979 /* Innings Telecom Inc. */ +WAVE_FORMAT_LUCENT_SX8300P :: 0x1C07 /* Lucent Technologies */ +WAVE_FORMAT_LUCENT_SX5363S :: 0x1C0C /* Lucent Technologies */ +WAVE_FORMAT_CUSEEME :: 0x1F03 /* CUSeeMe */ +WAVE_FORMAT_NTCSOFT_ALF2CM_ACM :: 0x1FC4 /* NTCSoft */ +WAVE_FORMAT_DVM :: 0x2000 /* FAST Multimedia AG */ +WAVE_FORMAT_DTS2 :: 0x2001 +WAVE_FORMAT_MAKEAVIS :: 0x3313 +WAVE_FORMAT_DIVIO_MPEG4_AAC :: 0x4143 /* Divio, Inc. */ +WAVE_FORMAT_NOKIA_ADAPTIVE_MULTIRATE :: 0x4201 /* Nokia */ +WAVE_FORMAT_DIVIO_G726 :: 0x4243 /* Divio, Inc. */ +WAVE_FORMAT_LEAD_SPEECH :: 0x434C /* LEAD Technologies */ +WAVE_FORMAT_LEAD_VORBIS :: 0x564C /* LEAD Technologies */ +WAVE_FORMAT_WAVPACK_AUDIO :: 0x5756 /* xiph.org */ +WAVE_FORMAT_ALAC :: 0x6C61 /* Apple Lossless */ +WAVE_FORMAT_OGG_VORBIS_MODE_1 :: 0x674F /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_2 :: 0x6750 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_3 :: 0x6751 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_1_PLUS :: 0x676F /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_2_PLUS :: 0x6770 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_3_PLUS :: 0x6771 /* Ogg Vorbis */ +WAVE_FORMAT_3COM_NBX :: 0x7000 /* 3COM Corp. */ +WAVE_FORMAT_OPUS :: 0x704F /* Opus */ +WAVE_FORMAT_FAAD_AAC :: 0x706D +WAVE_FORMAT_AMR_NB :: 0x7361 /* AMR Narrowband */ +WAVE_FORMAT_AMR_WB :: 0x7362 /* AMR Wideband */ +WAVE_FORMAT_AMR_WP :: 0x7363 /* AMR Wideband Plus */ +WAVE_FORMAT_GSM_AMR_CBR :: 0x7A21 /* GSMA/3GPP */ +WAVE_FORMAT_GSM_AMR_VBR_SID :: 0x7A22 /* GSMA/3GPP */ +WAVE_FORMAT_COMVERSE_INFOSYS_G723_1 :: 0xA100 /* Comverse Infosys */ +WAVE_FORMAT_COMVERSE_INFOSYS_AVQSBC :: 0xA101 /* Comverse Infosys */ +WAVE_FORMAT_COMVERSE_INFOSYS_SBC :: 0xA102 /* Comverse Infosys */ +WAVE_FORMAT_SYMBOL_G729_A :: 0xA103 /* Symbol Technologies */ +WAVE_FORMAT_VOICEAGE_AMR_WB :: 0xA104 /* VoiceAge Corp. */ +WAVE_FORMAT_INGENIENT_G726 :: 0xA105 /* Ingenient Technologies, Inc. */ +WAVE_FORMAT_MPEG4_AAC :: 0xA106 /* ISO/MPEG-4 */ +WAVE_FORMAT_ENCORE_G726 :: 0xA107 /* Encore Software */ +WAVE_FORMAT_ZOLL_ASAO :: 0xA108 /* ZOLL Medical Corp. */ +WAVE_FORMAT_SPEEX_VOICE :: 0xA109 /* xiph.org */ +WAVE_FORMAT_VIANIX_MASC :: 0xA10A /* Vianix LLC */ +WAVE_FORMAT_WM9_SPECTRUM_ANALYZER :: 0xA10B /* Microsoft */ +WAVE_FORMAT_WMF_SPECTRUM_ANAYZER :: 0xA10C /* Microsoft */ +WAVE_FORMAT_GSM_610 :: 0xA10D +WAVE_FORMAT_GSM_620 :: 0xA10E +WAVE_FORMAT_GSM_660 :: 0xA10F +WAVE_FORMAT_GSM_690 :: 0xA110 +WAVE_FORMAT_GSM_ADAPTIVE_MULTIRATE_WB :: 0xA111 +WAVE_FORMAT_POLYCOM_G722 :: 0xA112 /* Polycom */ +WAVE_FORMAT_POLYCOM_G728 :: 0xA113 /* Polycom */ +WAVE_FORMAT_POLYCOM_G729_A :: 0xA114 /* Polycom */ +WAVE_FORMAT_POLYCOM_SIREN :: 0xA115 /* Polycom */ +WAVE_FORMAT_GLOBAL_IP_ILBC :: 0xA116 /* Global IP */ +WAVE_FORMAT_RADIOTIME_TIME_SHIFT_RADIO :: 0xA117 /* RadioTime */ +WAVE_FORMAT_NICE_ACA :: 0xA118 /* Nice Systems */ +WAVE_FORMAT_NICE_ADPCM :: 0xA119 /* Nice Systems */ +WAVE_FORMAT_VOCORD_G721 :: 0xA11A /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G726 :: 0xA11B /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G722_1 :: 0xA11C /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G728 :: 0xA11D /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G729 :: 0xA11E /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G729_A :: 0xA11F /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G723_1 :: 0xA120 /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_LBC :: 0xA121 /* Vocord Telecom */ +WAVE_FORMAT_NICE_G728 :: 0xA122 /* Nice Systems */ +WAVE_FORMAT_FRACE_TELECOM_G729 :: 0xA123 /* France Telecom */ +WAVE_FORMAT_CODIAN :: 0xA124 /* CODIAN */ +WAVE_FORMAT_DOLBY_AC4 :: 0xAC40 /* Dolby AC-4 */ +WAVE_FORMAT_FLAC :: 0xF1AC /* flac.sourceforge.net */ +WAVE_FORMAT_EXTENSIBLE :: 0xFFFE /* Microsoft */ + + +WAVEFORMATEX :: struct #packed { wFormatTag: WORD, nChannels: WORD, nSamplesPerSec: DWORD, @@ -325,6 +601,20 @@ WAVEFORMATEX :: struct { } LPCWAVEFORMATEX :: ^WAVEFORMATEX +// New wave format development should be based on the WAVEFORMATEXTENSIBLE structure. +// WAVEFORMATEXTENSIBLE allows you to avoid having to register a new format tag with Microsoft. +// Simply define a new GUID value for the WAVEFORMATEXTENSIBLE.SubFormat field and use WAVE_FORMAT_EXTENSIBLE in the WAVEFORMATEXTENSIBLE.Format.wFormatTag field. +WAVEFORMATEXTENSIBLE :: struct #packed { + using Format: WAVEFORMATEX, + Samples: struct #raw_union { + wValidBitsPerSample: WORD, /* bits of precision */ + wSamplesPerBlock: WORD, /* valid if wBitsPerSample==0 */ + wReserved: WORD, /* If neither applies, set to zero. */ + }, + dwChannelMask: SPEAKER_FLAGS, /* which channels are present in stream */ + SubFormat: GUID, +} + WAVEHDR :: struct { lpData: LPSTR, /* pointer to locked data buffer */ dwBufferLength: DWORD, /* length of data buffer */ @@ -360,26 +650,50 @@ WAVEOUTCAPSW :: struct { } LPWAVEOUTCAPSW :: ^WAVEOUTCAPSW +SPEAKER_FLAGS :: distinct bit_set[SPEAKER_FLAG; DWORD] +SPEAKER_FLAG :: enum DWORD { + FRONT_LEFT = 0, + FRONT_RIGHT = 1, + FRONT_CENTER = 2, + LOW_FREQUENCY = 3, + BACK_LEFT = 4, + BACK_RIGHT = 5, + FRONT_LEFT_OF_CENTER = 6, + FRONT_RIGHT_OF_CENTER = 7, + BACK_CENTER = 8, + SIDE_LEFT = 9, + SIDE_RIGHT = 10, + TOP_CENTER = 11, + TOP_FRONT_LEFT = 12, + TOP_FRONT_CENTER = 13, + TOP_FRONT_RIGHT = 14, + TOP_BACK_LEFT = 15, + TOP_BACK_CENTER = 16, + TOP_BACK_RIGHT = 17, + //RESERVED = 0x7FFC0000, // bit mask locations reserved for future use + ALL = 31, // used to specify that any possible permutation of speaker configurations +} + // flag values for PlaySound -SND_SYNC :: 0x0000 /* play synchronously (default) */ -SND_ASYNC :: 0x0001 /* play asynchronously */ -SND_NODEFAULT :: 0x0002 /* silence (!default) if sound not found */ -SND_MEMORY :: 0x0004 /* pszSound points to a memory file */ -SND_LOOP :: 0x0008 /* loop the sound until next sndPlaySound */ -SND_NOSTOP :: 0x0010 /* don't stop any currently playing sound */ +SND_SYNC :: 0x0000 /* play synchronously (default) */ +SND_ASYNC :: 0x0001 /* play asynchronously */ +SND_NODEFAULT :: 0x0002 /* silence (!default) if sound not found */ +SND_MEMORY :: 0x0004 /* pszSound points to a memory file */ +SND_LOOP :: 0x0008 /* loop the sound until next sndPlaySound */ +SND_NOSTOP :: 0x0010 /* don't stop any currently playing sound */ -SND_NOWAIT :: 0x00002000 /* don't wait if the driver is busy */ -SND_ALIAS :: 0x00010000 /* name is a registry alias */ -SND_ALIAS_ID :: 0x00110000 /* alias is a predefined ID */ -SND_FILENAME :: 0x00020000 /* name is file name */ -SND_RESOURCE :: 0x00040004 /* name is resource name or atom */ +SND_NOWAIT :: 0x00002000 /* don't wait if the driver is busy */ +SND_ALIAS :: 0x00010000 /* name is a registry alias */ +SND_ALIAS_ID :: 0x00110000 /* alias is a predefined ID */ +SND_FILENAME :: 0x00020000 /* name is file name */ +SND_RESOURCE :: 0x00040004 /* name is resource name or atom */ -SND_PURGE :: 0x0040 /* purge non-static events for task */ -SND_APPLICATION :: 0x0080 /* look for application specific association */ +SND_PURGE :: 0x0040 /* purge non-static events for task */ +SND_APPLICATION :: 0x0080 /* look for application specific association */ -SND_SENTRY :: 0x00080000 /* Generate a SoundSentry event with this sound */ -SND_RING :: 0x00100000 /* Treat this as a "ring" from a communications app - don't duck me */ -SND_SYSTEM :: 0x00200000 /* Treat this as a system sound */ +SND_SENTRY :: 0x00080000 /* Generate a SoundSentry event with this sound */ +SND_RING :: 0x00100000 /* Treat this as a "ring" from a communications app - don't duck me */ +SND_SYSTEM :: 0x00200000 /* Treat this as a system sound */ CALLBACK_TYPEMASK :: 0x00070000 /* callback type mask */ diff --git a/core/sys/windows/winnls.odin b/core/sys/windows/winnls.odin index ffb2638d5..9c2c219ef 100644 --- a/core/sys/windows/winnls.odin +++ b/core/sys/windows/winnls.odin @@ -5,8 +5,8 @@ LCTYPE :: distinct DWORD LOCALE_NAME_MAX_LENGTH :: 85 LOCALE_NAME_USER_DEFAULT :: 0 -LOCALE_NAME_INVARIANT : wstring = L("") -LOCALE_NAME_SYSTEM_DEFAULT : wstring = L("!x-sys-default-locale") +LOCALE_NAME_INVARIANT : wstring = "" +LOCALE_NAME_SYSTEM_DEFAULT : wstring = "!x-sys-default-locale" // String Length Maximums. // 5 ranges, 2 bytes ea., 0 term. @@ -16,16 +16,16 @@ MAX_DEFAULTCHAR :: 2 CPINFOEXW :: struct{ // Maximum length, in bytes, of a character in the code page. - MaxCharSize: UINT, + MaxCharSize: UINT, // The default is usually the "?" character for the code page. - DefaultChar: [MAX_DEFAULTCHAR]BYTE, + DefaultChar: [MAX_DEFAULTCHAR]BYTE, // A fixed-length array of lead byte ranges, for which the number of lead byte ranges is variable. - LeadByte: [MAX_LEADBYTES]BYTE, + LeadByte: [MAX_LEADBYTES]BYTE, // The default is usually the "?" character or the katakana middle dot character. UnicodeDefaultChar: WCHAR, // Code page value. This value reflects the code page passed to the GetCPInfoEx function. - CodePage: CODEPAGE, + CodePage: CODEPAGE, // Full name of the code page. - CodePageName: [MAX_PATH]WCHAR, + CodePageName: [MAX_PATH]WCHAR, } LPCPINFOEXW :: ^CPINFOEXW diff --git a/core/sys/windows/winver.odin b/core/sys/windows/winver.odin index 47751dab7..3ec6ce056 100644 --- a/core/sys/windows/winver.odin +++ b/core/sys/windows/winver.odin @@ -5,14 +5,14 @@ foreign import version "system:version.lib" @(default_calling_convention = "system") foreign version { - GetFileVersionInfoSizeW :: proc(lpwstrFilename: LPCWSTR, lpdwHandle: LPDWORD) -> DWORD --- - GetFileVersionInfoW :: proc(lptstrFilename: LPCWSTR, dwHandle: DWORD, dwLen: DWORD, lpData: LPVOID) -> BOOL --- + GetFileVersionInfoSizeW :: proc(lpwstrFilename: LPCWSTR, lpdwHandle: LPDWORD) -> DWORD --- + GetFileVersionInfoW :: proc(lptstrFilename: LPCWSTR, dwHandle: DWORD, dwLen: DWORD, lpData: LPVOID) -> BOOL --- GetFileVersionInfoSizeExW :: proc(dwFlags: FILE_VER_GET_FLAGS, lpwstrFilename: LPCWSTR, lpdwHandle: LPDWORD) -> DWORD --- - GetFileVersionInfoExW :: proc(dwFlags: FILE_VER_GET_FLAGS, lpwstrFilename: LPCWSTR, dwHandle, dwLen: DWORD, lpData: LPVOID) -> DWORD --- + GetFileVersionInfoExW :: proc(dwFlags: FILE_VER_GET_FLAGS, lpwstrFilename: LPCWSTR, dwHandle, dwLen: DWORD, lpData: LPVOID) -> BOOL --- - VerLanguageNameW :: proc(wLang: DWORD, szLang: LPWSTR, cchLang: DWORD) -> DWORD --- - VerQueryValueW :: proc(pBlock: LPCVOID, lpSubBlock: LPCWSTR, lplpBuffer: ^LPVOID, puLen: PUINT) -> BOOL --- + VerLanguageNameW :: proc(wLang: DWORD, szLang: LPWSTR, cchLang: DWORD) -> DWORD --- + VerQueryValueW :: proc(pBlock: LPCVOID, lpSubBlock: LPCWSTR, lplpBuffer: ^LPVOID, puLen: PUINT) -> BOOL --- } FILE_VER_GET :: enum DWORD {LOCALISED, NEUTRAL, PREFETCHED} diff --git a/core/sys/windows/wow64_apiset.odin b/core/sys/windows/wow64_apiset.odin index 3d29b786e..cce0ab2cc 100644 --- a/core/sys/windows/wow64_apiset.odin +++ b/core/sys/windows/wow64_apiset.odin @@ -5,30 +5,30 @@ foreign import kernel32 "system:Kernel32.lib" @(default_calling_convention="system") foreign kernel32 { - GetSystemWow64Directory2W :: proc (lpBuffer: LPWSTR, uSize: UINT, ImageFileMachineTyp: WORD) -> UINT --- - GetSystemWow64DirectoryW :: proc (lpBuffer: LPWSTR, uSize: UINT) -> UINT --- - IsWow64GuestMachineSupported :: proc (WowGuestMachine: USHORT, MachineIsSupported: ^BOOL) -> HRESULT --- - IsWow64Process :: proc (hProcess: HANDLE, Wow64Process: PBOOL) -> BOOL --- - IsWow64Process2 :: proc (hProcess: HANDLE, pProcessMachine: ^USHORT, pNativeMachine: ^USHORT) -> BOOL --- - Wow64EnableWow64FsRedirection :: proc (Wow64FsEnableRedirection: BOOLEAN) -> BOOLEAN --- - Wow64DisableWow64FsRedirection :: proc (OldValue: ^PVOID) -> BOOL --- - Wow64RevertWow64FsRedirection :: proc (OlValue: PVOID) -> BOOL --- - Wow64GetThreadContext :: proc (hThread: HANDLE, lpContext: PWOW64_CONTEXT) -> BOOL --- - Wow64SetThreadContext :: proc(hThread: HANDLE, lpContext: ^WOW64_CONTEXT) -> BOOL --- + GetSystemWow64Directory2W :: proc(lpBuffer: LPWSTR, uSize: UINT, ImageFileMachineTyp: WORD) -> UINT --- + GetSystemWow64DirectoryW :: proc(lpBuffer: LPWSTR, uSize: UINT) -> UINT --- + IsWow64GuestMachineSupported :: proc(WowGuestMachine: USHORT, MachineIsSupported: ^BOOL) -> HRESULT --- + IsWow64Process :: proc(hProcess: HANDLE, Wow64Process: PBOOL) -> BOOL --- + IsWow64Process2 :: proc(hProcess: HANDLE, pProcessMachine: ^USHORT, pNativeMachine: ^USHORT) -> BOOL --- + Wow64EnableWow64FsRedirection :: proc(Wow64FsEnableRedirection: BOOLEAN) -> BOOLEAN --- + Wow64DisableWow64FsRedirection :: proc(OldValue: ^PVOID) -> BOOL --- + Wow64RevertWow64FsRedirection :: proc(OlValue: PVOID) -> BOOL --- + Wow64GetThreadContext :: proc(hThread: HANDLE, lpContext: PWOW64_CONTEXT) -> BOOL --- + Wow64SetThreadContext :: proc(hThread: HANDLE, lpContext: ^WOW64_CONTEXT) -> BOOL --- Wow64SetThreadDefaultGuestMachine :: proc(Machine: USHORT) -> USHORT --- - Wow64SuspendThread :: proc (hThread: HANDLE) -> DWORD --- + Wow64SuspendThread :: proc(hThread: HANDLE) -> DWORD --- } WOW64_CONTEXT_i386 :: 0x00010000 -WOW64_CONTEXT_CONTROL :: (WOW64_CONTEXT_i386 | 0x00000001) -WOW64_CONTEXT_INTEGER :: (WOW64_CONTEXT_i386 | 0x00000002) +WOW64_CONTEXT_CONTROL :: (WOW64_CONTEXT_i386 | 0x00000001) +WOW64_CONTEXT_INTEGER :: (WOW64_CONTEXT_i386 | 0x00000002) WOW64_CONTEXT_SEGMENTS :: (WOW64_CONTEXT_i386 | 0x00000004) -WOW64_CONTEXT_FLOATING_POINT :: (WOW64_CONTEXT_i386 | 0x00000008) -WOW64_CONTEXT_DEBUG_REGISTERS :: (WOW64_CONTEXT_i386 | 0x00000010) +WOW64_CONTEXT_FLOATING_POINT :: (WOW64_CONTEXT_i386 | 0x00000008) +WOW64_CONTEXT_DEBUG_REGISTERS :: (WOW64_CONTEXT_i386 | 0x00000010) WOW64_CONTEXT_EXTENDED_REGISTERS :: (WOW64_CONTEXT_i386 | 0x00000020) -WOW64_CONTEXT_FULL :: (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS) +WOW64_CONTEXT_FULL :: (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS) WOW64_CONTEXT_ALL :: ( WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | @@ -41,45 +41,45 @@ WOW64_SIZE_OF_80387_REGISTERS :: 80 WOW64_MAXIMUM_SUPPORTED_EXTENSION :: 512 WOW64_CONTEXT :: struct { - ContextFlags: DWORD, - Dr0: DWORD, - Dr1: DWORD, - Dr2: DWORD, - Dr3: DWORD, - Dr6: DWORD, - Dr7: DWORD, - FloatSave: WOW64_FLOATING_SAVE_AREA, - SegGs: DWORD, - SegFs: DWORD, - SegEs: DWORD, - SegDs: DWORD, - Edi: DWORD, - Esi: DWORD, - Ebx: DWORD, - Edx: DWORD, - Ecx: DWORD, - Eax: DWORD, - Ebp: DWORD, - Eip: DWORD, - SegCs: DWORD, - EFlags: DWORD, - Esp: DWORD, - SegSs: DWORD, + ContextFlags: DWORD, + Dr0: DWORD, + Dr1: DWORD, + Dr2: DWORD, + Dr3: DWORD, + Dr6: DWORD, + Dr7: DWORD, + FloatSave: WOW64_FLOATING_SAVE_AREA, + SegGs: DWORD, + SegFs: DWORD, + SegEs: DWORD, + SegDs: DWORD, + Edi: DWORD, + Esi: DWORD, + Ebx: DWORD, + Edx: DWORD, + Ecx: DWORD, + Eax: DWORD, + Ebp: DWORD, + Eip: DWORD, + SegCs: DWORD, + EFlags: DWORD, + Esp: DWORD, + SegSs: DWORD, ExtendedRegisters: [WOW64_MAXIMUM_SUPPORTED_EXTENSION]BYTE, } PWOW64_CONTEXT :: ^WOW64_CONTEXT WOW64_FLOATING_SAVE_AREA :: struct { - ControlWord: DWORD, - StatusWord: DWORD, - TagWord: DWORD, - ErrorOffset: DWORD, + ControlWord: DWORD, + StatusWord: DWORD, + TagWord: DWORD, + ErrorOffset: DWORD, ErrorSelector: DWORD, - DataOffset: DWORD, - DataSelector: DWORD, - RegisterArea: [WOW64_SIZE_OF_80387_REGISTERS]BYTE, - Cr0NpxState: DWORD, + DataOffset: DWORD, + DataSelector: DWORD, + RegisterArea: [WOW64_SIZE_OF_80387_REGISTERS]BYTE, + Cr0NpxState: DWORD, } PWOW64_FLOATING_SAVE_AREA :: ^WOW64_FLOATING_SAVE_AREA \ No newline at end of file diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index d808bcd09..2221e37fa 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -35,18 +35,19 @@ WSANETWORKEVENTS :: struct { iErrorCode: [FD_MAX_EVENTS]c_int, } -WSAEVENT :: HANDLE WSAID_ACCEPTEX :: GUID{0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} WSAID_GETACCEPTEXSOCKADDRS :: GUID{0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} -WSAID_CONNECTX :: GUID{0x25a207b9, 0xddf3, 0x4660, {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} +WSAID_CONNECTEX :: GUID{0x25a207b9, 0xddf3, 0x4660, {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} SIO_GET_EXTENSION_FUNCTION_POINTER :: IOC_INOUT | IOC_WS2 | 6 +SIO_UDP_CONNRESET :: IOC_IN | IOC_VENDOR | 12 -IOC_OUT :: 0x40000000 -IOC_IN :: 0x80000000 -IOC_INOUT :: (IOC_IN | IOC_OUT) -IOC_WS2 :: 0x08000000 +IOC_OUT :: 0x40000000 +IOC_IN :: 0x80000000 +IOC_INOUT :: (IOC_IN | IOC_OUT) +IOC_WS2 :: 0x08000000 +IOC_VENDOR :: 0x18000000 SO_UPDATE_ACCEPT_CONTEXT :: 28683 @@ -82,6 +83,17 @@ Example Load: } */ +LPFN_GETACCEPTEXSOCKADDRS :: #type proc "system" ( + lpOutputBuffer: PVOID, + dwReceiveDataLength: DWORD, + dwLocalAddressLength: DWORD, + dwRemoteAddressLength: DWORD, + LocalSockaddr: ^^sockaddr, + LocalSockaddrLength: LPINT, + RemoteSockaddr: ^^sockaddr, + RemoteSockaddrLength: LPINT, +) + foreign import ws2_32 "system:Ws2_32.lib" @(default_calling_convention="system") foreign ws2_32 { @@ -96,41 +108,69 @@ foreign ws2_32 { WSAPoll :: proc(fdArray: ^WSA_POLLFD, fds: c_ulong, timeout: c_int) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaduplicatesocketw) WSADuplicateSocketW :: proc( - s: SOCKET, - dwProcessId: DWORD, + s: SOCKET, + dwProcessId: DWORD, lpProtocolInfo: LPWSAPROTOCOL_INFO, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend) WSASend :: proc( - s: SOCKET, - lpBuffers: LPWSABUF, - dwBufferCount: DWORD, + s: SOCKET, + lpBuffers: LPWSABUF, + dwBufferCount: DWORD, lpNumberOfBytesSent: LPDWORD, - dwFlags: DWORD, - lpOverlapped: LPWSAOVERLAPPED, + dwFlags: DWORD, + lpOverlapped: LPWSAOVERLAPPED, + lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, + ) -> c_int --- + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasendto) + WSASendTo :: proc( + s: SOCKET, + lpBuffers: LPWSABUF, + dwBufferCount: DWORD, + lpNumberOfBytesSent: LPDWORD, + dwFlags: DWORD, + lpTo: ^sockaddr, + iToLen: c_int, + lpOverlapped: LPWSAOVERLAPPED, lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsarecv) WSARecv :: proc( - s: SOCKET, - lpBuffers: LPWSABUF, - dwBufferCount: DWORD, + s: SOCKET, + lpBuffers: LPWSABUF, + dwBufferCount: DWORD, lpNumberOfBytesRecvd: LPDWORD, - lpFlags: LPDWORD, - lpOverlapped: LPWSAOVERLAPPED, - lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, + lpFlags: LPDWORD, + lpOverlapped: LPWSAOVERLAPPED, + lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, + ) -> c_int --- + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsarecvfrom) + WSARecvFrom :: proc( + s: SOCKET, + lpBuffers: LPWSABUF, + dwBufferCount: DWORD, + lpNumberOfBytesRecvd: LPDWORD, + lpFlags: LPDWORD, + lpFrom: ^sockaddr, + lpFromlen: LPINT, + lpOverlapped: LPWSAOVERLAPPED, + lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketw) WSASocketW :: proc( - af: c_int, - kind: c_int, - protocol: c_int, + af: c_int, + kind: c_int, + protocol: c_int, lpProtocolInfo: LPWSAPROTOCOL_INFO, - g: GROUP, - dwFlags: DWORD, + g: GROUP, + dwFlags: DWORD, ) -> SOCKET --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaioctl) WSAIoctl :: proc(s: SOCKET, dwIoControlCode: DWORD, lpvInBuffer: rawptr, cbInBuffer: DWORD, lpvOutBuffer: rawptr, cbOutBuffer: DWORD, lpcbBytesReturned: ^DWORD, lpOverlapped: ^OVERLAPPED, lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE) -> c_int --- + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsacreateevent) + WSACreateEvent :: proc() -> WSAEVENT --- + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsacloseevent) + WSACloseEvent :: proc(hEvent: WSAEVENT) -> bool --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaeventselect) WSAEventSelect :: proc(s: SOCKET, hEventObject: WSAEVENT, lNetworkEvents: i32) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsawaitformultipleevents) @@ -141,8 +181,8 @@ foreign ws2_32 { WSAGetOverlappedResult :: proc(s: SOCKET, lpOverlapped: ^OVERLAPPED, lpcbTransfer: ^DWORD, fWait: BOOL, lpdwFlags: ^DWORD) -> BOOL --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket) socket :: proc( - af: c_int, - type: c_int, + af: c_int, + type: c_int, protocol: c_int, ) -> SOCKET --- @@ -156,20 +196,20 @@ foreign ws2_32 { send :: proc(socket: SOCKET, buf: rawptr, len: c_int, flags: c_int) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom) recvfrom :: proc( - socket: SOCKET, - buf: rawptr, - len: c_int, - flags: c_int, - addr: ^SOCKADDR_STORAGE_LH, + socket: SOCKET, + buf: rawptr, + len: c_int, + flags: c_int, + addr: ^SOCKADDR_STORAGE_LH, addrlen: ^c_int, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto) sendto :: proc( - socket: SOCKET, - buf: rawptr, - len: c_int, - flags: c_int, - addr: ^SOCKADDR_STORAGE_LH, + socket: SOCKET, + buf: rawptr, + len: c_int, + flags: c_int, + addr: ^SOCKADDR_STORAGE_LH, addrlen: c_int, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown) @@ -179,16 +219,18 @@ foreign ws2_32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt) setsockopt :: proc( - s: SOCKET, - level: c_int, + s: SOCKET, + level: c_int, optname: c_int, - optval: rawptr, - optlen: c_int, + optval: rawptr, + optlen: c_int, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockname) getsockname :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: ^c_int) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getpeername) getpeername :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: ^c_int) -> c_int --- + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostname) + gethostname :: proc(name: [^]c_char, namelen: c_int) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind) bind :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: socklen_t) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen) @@ -197,10 +239,10 @@ foreign ws2_32 { connect :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, len: c_int) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo) getaddrinfo :: proc( - node: cstring, + node: cstring, service: cstring, - hints: ^ADDRINFOA, - res: ^^ADDRINFOA, + hints: ^ADDRINFOA, + res: ^^ADDRINFOA, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-freeaddrinfo) freeaddrinfo :: proc(res: ^ADDRINFOA) --- @@ -220,28 +262,28 @@ foreign ws2_32 { lpHandle: LPHANDLE) -> INT --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select) select :: proc( - nfds: c_int, - readfds: ^fd_set, - writefds: ^fd_set, - exceptfds: ^fd_set, - timeout: ^timeval, + nfds: c_int, + readfds: [^]fd_set, + writefds: [^]fd_set, + exceptfds: [^]fd_set, + timeout: ^timeval, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt) getsockopt :: proc( - s: SOCKET, - level: c_int, + s: SOCKET, + level: c_int, optname: c_int, - optval: ^c_char, - optlen: ^c_int, + optval: [^]c_char, + optlen: ^c_int, ) -> c_int --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohl) ntohl :: proc(netlong: c_ulong) -> c_ulong --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs) ntohs :: proc(netshort: c_ushort) -> c_ushort --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl) - @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types") + // Prefer using endian-specific integers instead, https://odin-lang.org/docs/overview/#basic-types htonl :: proc(hostlong: c_ulong) -> c_ulong --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons) - @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types") + // Prefer using endian-specific integers instead, https://odin-lang.org/docs/overview/#basic-types htons :: proc(hostshort: c_ushort) -> c_ushort --- } diff --git a/core/sys/windows/xinput.odin b/core/sys/windows/xinput.odin index 0089f88cb..f8fd45bc9 100644 --- a/core/sys/windows/xinput.odin +++ b/core/sys/windows/xinput.odin @@ -57,9 +57,9 @@ XINPUT_GAMEPAD_BUTTON_BIT :: enum WORD { XINPUT_GAMEPAD_BUTTON :: distinct bit_set[XINPUT_GAMEPAD_BUTTON_BIT;WORD] // Gamepad thresholds -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE: SHORT : 7849 -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE: SHORT : 8689 -XINPUT_GAMEPAD_TRIGGER_THRESHOLD: SHORT : 30 +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE : SHORT : 7849 +XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE : SHORT : 8689 +XINPUT_GAMEPAD_TRIGGER_THRESHOLD : SHORT : 30 // Flags to pass to XInputGetCapabilities // Corresponds to log2(XINPUT_FLAG_...) @@ -199,12 +199,12 @@ XINPUT_KEYSTROKE :: struct { // XInput APIs @(default_calling_convention = "system") foreign xinput { - XInputGetState :: proc(user: XUSER, pState: ^XINPUT_STATE) -> System_Error --- - XInputSetState :: proc(user: XUSER, pVibration: ^XINPUT_VIBRATION) -> System_Error --- - XInputGetCapabilities :: proc(user: XUSER, dwFlags: XINPUT_FLAG, pCapabilities: ^XINPUT_CAPABILITIES) -> System_Error --- - XInputEnable :: proc(enable: BOOL) --- - XInputGetAudioDeviceIds :: proc(user: XUSER, pRenderDeviceId: LPWSTR, pRenderCount: ^UINT, pCaptureDeviceId: LPWSTR, pCaptureCount: ^UINT) -> System_Error --- - XInputGetBatteryInformation :: proc(user: XUSER, devType: BATTERY_DEVTYPE, pBatteryInformation: ^XINPUT_BATTERY_INFORMATION) -> System_Error --- - XInputGetKeystroke :: proc(user: XUSER, dwReserved: DWORD, pKeystroke: ^XINPUT_KEYSTROKE) -> System_Error --- + XInputGetState :: proc(user: XUSER, pState: ^XINPUT_STATE) -> System_Error --- + XInputSetState :: proc(user: XUSER, pVibration: ^XINPUT_VIBRATION) -> System_Error --- + XInputGetCapabilities :: proc(user: XUSER, dwFlags: XINPUT_FLAG, pCapabilities: ^XINPUT_CAPABILITIES) -> System_Error --- + XInputEnable :: proc(enable: BOOL) --- + XInputGetAudioDeviceIds :: proc(user: XUSER, pRenderDeviceId: LPWSTR, pRenderCount: ^UINT, pCaptureDeviceId: LPWSTR, pCaptureCount: ^UINT) -> System_Error --- + XInputGetBatteryInformation :: proc(user: XUSER, devType: BATTERY_DEVTYPE, pBatteryInformation: ^XINPUT_BATTERY_INFORMATION) -> System_Error --- + XInputGetKeystroke :: proc(user: XUSER, dwReserved: DWORD, pKeystroke: ^XINPUT_KEYSTROKE) -> System_Error --- XInputGetDSoundAudioDeviceGuids :: proc(user: XUSER, pDSoundRenderGuid: ^GUID, pDSoundCaptureGuid: ^GUID) -> System_Error --- } diff --git a/core/encoding/ansi/ansi.odin b/core/terminal/ansi/ansi.odin similarity index 89% rename from core/encoding/ansi/ansi.odin rename to core/terminal/ansi/ansi.odin index 5550a1671..89220253c 100644 --- a/core/encoding/ansi/ansi.odin +++ b/core/terminal/ansi/ansi.odin @@ -32,12 +32,14 @@ DSR :: "6n" // Device Status Report // CSI: private sequences -SCP :: "s" // Save Current Cursor Position -RCP :: "u" // Restore Saved Cursor Position -DECAWM_ON :: "?7h" // Auto Wrap Mode (Enabled) -DECAWM_OFF :: "?7l" // Auto Wrap Mode (Disabled) -DECTCEM_SHOW :: "?25h" // Text Cursor Enable Mode (Visible) -DECTCEM_HIDE :: "?25l" // Text Cursor Enable Mode (Invisible) +SCP :: "s" // Save Current Cursor Position +RCP :: "u" // Restore Saved Cursor Position +DECAWM_ON :: "?7h" // Auto Wrap Mode (Enabled) +DECAWM_OFF :: "?7l" // Auto Wrap Mode (Disabled) +DECTCEM_SHOW :: "?25h" // Text Cursor Enable Mode (Visible) +DECTCEM_HIDE :: "?25l" // Text Cursor Enable Mode (Invisible) +DECASB_ENTER :: "?1049h" // Alternate Screen Buffer (Enter) +DECASB_EXIT :: "?1049l" // Alternate Screen Buffer (Exit) // SGR sequences diff --git a/core/encoding/ansi/doc.odin b/core/terminal/ansi/doc.odin similarity index 79% rename from core/encoding/ansi/doc.odin rename to core/terminal/ansi/doc.odin index 966e6be00..7f1d30b1b 100644 --- a/core/encoding/ansi/doc.odin +++ b/core/terminal/ansi/doc.odin @@ -1,7 +1,6 @@ /* -package ansi implements constant references to many widely-supported ANSI -escape codes, primarily used in terminal emulators for enhanced graphics, such -as colors, text styling, and animated displays. +Constant references to many widely-supported `ANSI` escape codes. +Primarily used in terminal emulators for enhanced graphics, such as colors, text styling, and animated displays. For example, you can print out a line of cyan text like this: fmt.println(ansi.CSI + ansi.FG_CYAN + ansi.SGR + "Hellope!" + ansi.CSI + ansi.RESET + ansi.SGR) diff --git a/core/terminal/internal_os.odin b/core/terminal/internal_os.odin new file mode 100644 index 000000000..127cbae54 --- /dev/null +++ b/core/terminal/internal_os.odin @@ -0,0 +1,82 @@ +#+build !freestanding +#+build !js +#+private +package terminal + +import "base:runtime" +import "core:os" +import "core:strings" + +// Reference documentation: +// +// - [[ https://no-color.org/ ]] +// - [[ https://github.com/termstandard/colors ]] +// - [[ https://invisible-island.net/ncurses/terminfo.src.html ]] + +get_no_color :: proc() -> bool { + buf: [128]u8 + if no_color, err := os.lookup_env(buf[:], "NO_COLOR"); err == nil { + return no_color != "" + } + return false +} + +get_environment_color :: proc() -> Color_Depth { + buf: [128]u8 + // `COLORTERM` is non-standard but widespread and unambiguous. + if colorterm, err := os.lookup_env(buf[:], "COLORTERM"); err == nil { + // These are the only values that are typically advertised that have + // anything to do with color depth. + if colorterm == "truecolor" || colorterm == "24bit" { + return .True_Color + } + } + + if term, err := os.lookup_env(buf[:], "TERM"); err == nil { + if strings.contains(term, "-truecolor") { + return .True_Color + } + if strings.contains(term, "-256color") { + return .Eight_Bit + } + if strings.contains(term, "-16color") { + return .Four_Bit + } + + // The `terminfo` database, which is stored in binary on *nix + // platforms, has an undocumented format that is not guaranteed to be + // portable, so beyond this point, we can only make safe assumptions. + // + // This section should only be necessary for terminals that do not + // define any of the previous environment values. + // + // Only a small sampling of some common values are checked here. + switch term { + case "ansi", "konsole", "putty", "rxvt", "rxvt-color", "screen", + "st", "tmux", "vte", "xterm", "xterm-color": + return .Three_Bit + } + } + + return .None +} + +@(init) +init_terminal :: proc "contextless" () { + _init_terminal() + + context = runtime.default_context() + + // We respect `NO_COLOR` specifically as a color-disabler but not as a + // blanket ban on any terminal manipulation codes, hence why this comes + // after `_init_terminal` which will allow Windows to enable Virtual + // Terminal Processing for non-color control sequences. + if !get_no_color() { + color_enabled = color_depth > .None + } +} + +@(fini) +fini_terminal :: proc "contextless" () { + _fini_terminal() +} \ No newline at end of file diff --git a/core/terminal/terminal.odin b/core/terminal/terminal.odin new file mode 100644 index 000000000..86d928649 --- /dev/null +++ b/core/terminal/terminal.odin @@ -0,0 +1,35 @@ +// Interaction with the command line interface (`CLI`) of the system. +package terminal + +/* +This describes the range of colors that a terminal is capable of supporting. +*/ +Color_Depth :: enum { + None, // No color support + Three_Bit, // 8 colors + Four_Bit, // 16 colors + Eight_Bit, // 256 colors + True_Color, // 24-bit true color +} + +/* +Returns true if the `File` is attached to a terminal. + +This is normally true for `os.stdout` and `os.stderr` unless they are +redirected to a file. +*/ +@(require_results) +is_terminal :: proc(f: $T) -> bool { + return _is_terminal(f) +} + +/* +This is true if the terminal is accepting any form of colored text output. +*/ +color_enabled: bool + +/* +This value reports the color depth support as reported by the terminal at the +start of the program. +*/ +color_depth: Color_Depth diff --git a/core/terminal/terminal_js.odin b/core/terminal/terminal_js.odin new file mode 100644 index 000000000..78c6c240f --- /dev/null +++ b/core/terminal/terminal_js.odin @@ -0,0 +1,13 @@ +#+private +#+build js +package terminal + +_is_terminal :: proc "contextless" (handle: any) -> bool { + return true +} + +_init_terminal :: proc "contextless" () { + color_depth = .None +} + +_fini_terminal :: proc "contextless" () { } \ No newline at end of file diff --git a/core/terminal/terminal_posix.odin b/core/terminal/terminal_posix.odin new file mode 100644 index 000000000..62a79797b --- /dev/null +++ b/core/terminal/terminal_posix.odin @@ -0,0 +1,17 @@ +#+private +#+build linux, darwin, netbsd, openbsd, freebsd +package terminal + +import "base:runtime" +import "core:os" + +_is_terminal :: proc "contextless" (f: ^os.File) -> bool { + return os.is_tty(f) +} + +_init_terminal :: proc "contextless" () { + context = runtime.default_context() + color_depth = get_environment_color() +} + +_fini_terminal :: proc "contextless" () { } diff --git a/core/terminal/terminal_windows.odin b/core/terminal/terminal_windows.odin new file mode 100644 index 000000000..64244e1ac --- /dev/null +++ b/core/terminal/terminal_windows.odin @@ -0,0 +1,60 @@ +#+private +package terminal + +import "base:runtime" +import "core:os" +import "core:sys/windows" + +_is_terminal :: proc "contextless" (f: ^os.File) -> bool { + return os.is_tty(f) +} + +old_modes: [2]struct{ + handle: windows.DWORD, + mode: windows.DWORD, +} = { + {windows.STD_OUTPUT_HANDLE, 0}, + {windows.STD_ERROR_HANDLE, 0}, +} + +_init_terminal :: proc "contextless" () { + vtp_enabled: bool + + for &v in old_modes { + handle := windows.GetStdHandle(v.handle) + if handle == windows.INVALID_HANDLE || handle == nil { + return + } + if windows.GetConsoleMode(handle, &v.mode) { + windows.SetConsoleMode(handle, v.mode | windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + + new_mode: windows.DWORD + windows.GetConsoleMode(handle, &new_mode) + + if new_mode & (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0 { + vtp_enabled = true + } + } + } + + if vtp_enabled { + // This color depth is available on Windows 10 since build 10586. + color_depth = .Four_Bit + } else { + context = runtime.default_context() + + // The user may be on a non-default terminal emulator. + color_depth = get_environment_color() + } +} + +_fini_terminal :: proc "contextless" () { + for v in old_modes { + handle := windows.GetStdHandle(v.handle) + if handle == windows.INVALID_HANDLE || handle == nil { + return + } + + windows.SetConsoleMode(handle, v.mode) + } +} diff --git a/core/testing/doc.odin b/core/testing/doc.odin new file mode 100644 index 000000000..73b907933 --- /dev/null +++ b/core/testing/doc.odin @@ -0,0 +1,44 @@ +/* +The implementation of the `odin test` runner and procedures user tests can use for this purpose. + +Defineables through `#config`: + + // Specify how many threads to use when running tests. + TEST_THREADS : int : #config(ODIN_TEST_THREADS, 0) + // Track the memory used by each test. + TRACKING_MEMORY : bool : #config(ODIN_TEST_TRACK_MEMORY, true) + // Always report how much memory is used, even when there are no leaks or bad frees. + ALWAYS_REPORT_MEMORY : bool : #config(ODIN_TEST_ALWAYS_REPORT_MEMORY, false) + // Treat memory leaks and bad frees as errors. + FAIL_ON_BAD_MEMORY : bool : #config(ODIN_TEST_FAIL_ON_BAD_MEMORY, false) + // Specify how much memory each thread allocator starts with. + PER_THREAD_MEMORY : int : #config(ODIN_TEST_THREAD_MEMORY, mem. ROLLBACK_STACK_DEFAULT_BLOCK_SIZE) + // Select a specific set of tests to run by name. + // Each test is separated by a comma and may optionally include the package name. + // This may be useful when running tests on multiple packages with `-all-packages`. + // The format is: `package.test_name,test_name_only,...` + TEST_NAMES : string : #config(ODIN_TEST_NAMES, "") + // Show the fancy animated progress report. + // This requires terminal color support, as well as STDOUT to not be redirected to a file. + FANCY_OUTPUT : bool : #config(ODIN_TEST_FANCY, true) + // Copy failed tests to the clipboard when done. + USE_CLIPBOARD : bool : #config(ODIN_TEST_CLIPBOARD, false) + // How many test results to show at a time per package. + PROGRESS_WIDTH : int : #config(ODIN_TEST_PROGRESS_WIDTH, 24) + // This is the random seed that will be sent to each test. + // If it is unspecified, it will be set to the system cycle counter at startup. + SHARED_RANDOM_SEED : u64 : #config(ODIN_TEST_RANDOM_SEED, 0) + // Set the lowest log level for this test run. + LOG_LEVEL_DEFAULT : string : "debug" when ODIN_DEBUG else "info" + LOG_LEVEL : string : #config(ODIN_TEST_LOG_LEVEL, LOG_LEVEL_DEFAULT) + // Report a message at the info level when a test has changed its state. + LOG_STATE_CHANGES : bool : #config(ODIN_TEST_LOG_STATE_CHANGES, false) + // Show only the most necessary logging information. + USING_SHORT_LOGS : bool : #config(ODIN_TEST_SHORT_LOGS, false) + // Output a report of the tests to the given path. + JSON_REPORT : string : #config(ODIN_TEST_JSON_REPORT, "") + // Print the full file path for failed test cases on a new line + // in a way that's friendly to regex capture for an editor's "go to error". + GO_TO_ERROR : bool : #config(ODIN_TEST_GO_TO_ERROR, false) +*/ +package testing diff --git a/core/testing/events.odin b/core/testing/events.odin index 1a47e2d68..1d07e8c5b 100644 --- a/core/testing/events.odin +++ b/core/testing/events.odin @@ -3,7 +3,7 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Total rewrite. diff --git a/core/testing/logging.odin b/core/testing/logging.odin index 041489dab..3138a745b 100644 --- a/core/testing/logging.odin +++ b/core/testing/logging.odin @@ -3,7 +3,7 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Ginger Bill: Initial implementation. @@ -83,7 +83,31 @@ format_log_text :: proc(level: runtime.Logger_Level, text: string, options: runt log.do_level_header(options, &buf, level) log.do_time_header(options, &buf, at_time) - log.do_location_header(options, &buf, location) - + when GO_TO_ERROR { + do_go_to_error_friendly_location(options, &buf, location) + } else { + log.do_location_header(options, &buf, location) + } return fmt.aprintf("%s%s", strings.to_string(buf), text, allocator = allocator) } + +do_go_to_error_friendly_location :: proc(opts: log.Options, buf: ^strings.Builder, location := #caller_location) { + if log.Location_Header_Opts & opts == nil { + return + } + fmt.sbprint(buf, "\n") + + file := location.file_path + fmt.sbprint(buf, file) + + fmt.sbprint(buf, "(") + fmt.sbprint(buf, location.line) + fmt.sbprint(buf, ":") + fmt.sbprint(buf, location.column) + fmt.sbprint(buf, ")") + + if .Procedure in opts { + fmt.sbprintf(buf, ":%s()", location.procedure) + } + fmt.sbprint(buf, " ") +} \ No newline at end of file diff --git a/core/testing/reporting.odin b/core/testing/reporting.odin index 6752cd79b..e72be3a04 100644 --- a/core/testing/reporting.odin +++ b/core/testing/reporting.odin @@ -3,19 +3,19 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Total rewrite. */ import "base:runtime" -import "core:encoding/ansi" import "core:fmt" import "core:io" import "core:mem" import "core:path/filepath" import "core:strings" +import "core:terminal/ansi" // Definitions of colors for use in the test runner. SGR_RESET :: ansi.CSI + ansi.RESET + ansi.SGR diff --git a/core/testing/runner.odin b/core/testing/runner.odin index 83a5ac4e7..9033d078e 100644 --- a/core/testing/runner.odin +++ b/core/testing/runner.odin @@ -3,62 +3,70 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Ginger Bill: Initial implementation. Feoramund: Total rewrite. */ -import "base:intrinsics" -import "base:runtime" -import "core:bytes" -import "core:encoding/ansi" -@require import "core:encoding/base64" -@require import "core:encoding/json" -import "core:fmt" -import "core:io" -@require import "core:log" -import "core:math/rand" -import "core:mem" -import "core:os" -import "core:slice" -@require import "core:strings" -import "core:sync/chan" -import "core:thread" -import "core:time" +import "base:intrinsics" +import "base:runtime" +import "core:bytes" +@(require) import "core:encoding/base64" +@(require) import "core:encoding/json" +import "core:fmt" +import "core:io" +@(require) import "core:log" +import "core:math/rand" +import "core:mem" +import "core:os" +import "core:slice" +@(require) import "core:strings" +import "core:sync/chan" +import "core:terminal" +import "core:terminal/ansi" +import "core:thread" +import "core:time" +import "core:path/slashpath" // Specify how many threads to use when running tests. -TEST_THREADS : int : #config(ODIN_TEST_THREADS, 0) +TEST_THREADS : int : #config(ODIN_TEST_THREADS, 0) // Track the memory used by each test. -TRACKING_MEMORY : bool : #config(ODIN_TEST_TRACK_MEMORY, true) +TRACKING_MEMORY : bool : #config(ODIN_TEST_TRACK_MEMORY, true) // Always report how much memory is used, even when there are no leaks or bad frees. ALWAYS_REPORT_MEMORY : bool : #config(ODIN_TEST_ALWAYS_REPORT_MEMORY, false) // Treat memory leaks and bad frees as errors. -FAIL_ON_BAD_MEMORY : bool : #config(ODIN_TEST_FAIL_ON_BAD_MEMORY, false) +FAIL_ON_BAD_MEMORY : bool : #config(ODIN_TEST_FAIL_ON_BAD_MEMORY, false) // Specify how much memory each thread allocator starts with. PER_THREAD_MEMORY : int : #config(ODIN_TEST_THREAD_MEMORY, mem.ROLLBACK_STACK_DEFAULT_BLOCK_SIZE) // Select a specific set of tests to run by name. // Each test is separated by a comma and may optionally include the package name. // This may be useful when running tests on multiple packages with `-all-packages`. // The format is: `package.test_name,test_name_only,...` -TEST_NAMES : string : #config(ODIN_TEST_NAMES, "") +TEST_NAMES : string : #config(ODIN_TEST_NAMES, "") // Show the fancy animated progress report. -FANCY_OUTPUT : bool : #config(ODIN_TEST_FANCY, true) +// This requires terminal color support, as well as STDOUT to not be redirected to a file. +FANCY_OUTPUT : bool : #config(ODIN_TEST_FANCY, true) // Copy failed tests to the clipboard when done. -USE_CLIPBOARD : bool : #config(ODIN_TEST_CLIPBOARD, false) +USE_CLIPBOARD : bool : #config(ODIN_TEST_CLIPBOARD, false) // How many test results to show at a time per package. -PROGRESS_WIDTH : int : #config(ODIN_TEST_PROGRESS_WIDTH, 24) +PROGRESS_WIDTH : int : #config(ODIN_TEST_PROGRESS_WIDTH, 24) // This is the random seed that will be sent to each test. // If it is unspecified, it will be set to the system cycle counter at startup. -SHARED_RANDOM_SEED : u64 : #config(ODIN_TEST_RANDOM_SEED, 0) +SHARED_RANDOM_SEED : u64 : #config(ODIN_TEST_RANDOM_SEED, 0) // Set the lowest log level for this test run. LOG_LEVEL_DEFAULT : string : "debug" when ODIN_DEBUG else "info" -LOG_LEVEL : string : #config(ODIN_TEST_LOG_LEVEL, LOG_LEVEL_DEFAULT) +LOG_LEVEL : string : #config(ODIN_TEST_LOG_LEVEL, LOG_LEVEL_DEFAULT) +// Report a message at the info level when a test has changed its state. +LOG_STATE_CHANGES : bool : #config(ODIN_TEST_LOG_STATE_CHANGES, false) // Show only the most necessary logging information. -USING_SHORT_LOGS : bool : #config(ODIN_TEST_SHORT_LOGS, false) +USING_SHORT_LOGS : bool : #config(ODIN_TEST_SHORT_LOGS, false) // Output a report of the tests to the given path. -JSON_REPORT : string : #config(ODIN_TEST_JSON_REPORT, "") +JSON_REPORT : string : #config(ODIN_TEST_JSON_REPORT, "") +// Print the full file path for failed test cases on a new line +// in a way that's friendly to regex capture for an editor's "go to error". +GO_TO_ERROR : bool : #config(ODIN_TEST_GO_TO_ERROR, false) get_log_level :: #force_inline proc() -> runtime.Logger_Level { when LOG_LEVEL == "debug" { return .Debug } else @@ -70,6 +78,9 @@ get_log_level :: #force_inline proc() -> runtime.Logger_Level { } } +@(private) global_log_colors_disabled: bool +@(private) global_ansi_disabled: bool + JSON :: struct { total: int, success: int, @@ -129,16 +140,21 @@ run_test_task :: proc(task: thread.Task) { context.assertion_failure_proc = test_assertion_failure_proc + logger_options := Default_Test_Logger_Opts + if global_log_colors_disabled { + logger_options -= {.Terminal_Color} + } + context.logger = { procedure = test_logger_proc, data = &data.t, lowest_level = get_log_level(), - options = Default_Test_Logger_Opts, + options = logger_options, } - random_generator_state: runtime.Default_Random_State + random_generator_state: rand.Xoshiro256_Random_State context.random_generator = { - procedure = runtime.default_random_generator_proc, + procedure = rand.xoshiro256_random_generator_proc, data = &random_generator_state, } rand.reset(data.t.seed) @@ -181,6 +197,53 @@ run_test_task :: proc(task: thread.Task) { }) } +Options :: struct { + // Equivalent to the TEST_NAMES compile-time definition, but used dynamically at runtime. + test_names: string, +} + +parse_cli_options :: proc(argv: []string, opts: ^Options, stdout, stderr: io.Writer) { + test_names: strings.Builder + + for arg in argv { + if strings.starts_with(arg, "-tests:") { + _, _, tests := strings.partition(arg, ":") + if len(tests) < 1 { + fmt.wprintln(stderr, "No test names specified for '-tests:'") + os.exit(-1) + } + + if strings.builder_len(test_names) > 0 { + strings.write_byte(&test_names, ',') + } + strings.write_string(&test_names, tests) + } else if arg == "-help" { + exe_name := "test" + if path, err := os.get_executable_path(context.temp_allocator); err == nil { + exe_name = slashpath.base(path) + } + + fmt.wprintfln(stdout, "Usage: %v [OPTIONS]", exe_name) + fmt.wprintfln(stdout, "OPTIONS:") + fmt.wprintln(stdout, " -help:") + fmt.wprintln(stdout, " Display this help text and exit.") + fmt.wprintln(stdout) + fmt.wprintln(stdout, " -tests:") + fmt.wprintln(stdout, " Specify a specific set of tests to run by name.\n" + + " Each test is separated by a comma and may optionally include the package name.\n" + + " This may be useful when running tests on multiple packages with `-all-packages`.\n" + + " The format is: `package.test_name,test_name_only,...`") + fmt.wprintln(stdout) + os.exit(0) + } else { + fmt.wprintfln(stderr, "Unknown argument encountered '%v'", arg) + os.exit(-1) + } + } + + opts.test_names = strings.to_string(test_names) +} + runner :: proc(internal_tests: []Internal_Test) -> bool { BATCH_BUFFER_SIZE :: 32 * mem.Kilobyte POOL_BLOCK_SIZE :: 16 * mem.Kilobyte @@ -204,61 +267,74 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { } } - when ODIN_OS == .Windows { - console_ansi_init() - } - stdout := io.to_writer(os.stream_from_handle(os.stdout)) - stderr := io.to_writer(os.stream_from_handle(os.stderr)) + // `-vet` needs parameters to be shadowed by themselves first as an + // explicit declaration, to allow the next line to work. + // NOTE(@harold): Moved out of scope below as it's no longer under a `when` block, but under `if`. + internal_tests := internal_tests + + stdout := os.to_stream(os.stdout) + stderr := os.to_stream(os.stderr) + + // The animations are only ever shown through STDOUT; + // STDERR is used exclusively for logging regardless of error level. + global_log_colors_disabled = !terminal.color_enabled || !terminal.is_terminal(os.stderr) + global_ansi_disabled = !terminal.is_terminal(os.stdout) + + should_show_animations := FANCY_OUTPUT && terminal.color_enabled && !global_ansi_disabled + + // -- Parse CLI options + opts: Options + parse_cli_options(os.args[1:], &opts, stdout, stderr) + + test_names: string = TEST_NAMES + if len(opts.test_names) > 0 { + test_names = opts.test_names + } // -- Prepare test data. alloc_error: mem.Allocator_Error - when TEST_NAMES != "" { - select_internal_tests: [dynamic]Internal_Test - defer delete(select_internal_tests) + select_internal_tests: [dynamic]Internal_Test + defer delete(select_internal_tests) - { - index_list := TEST_NAMES - for selector in strings.split_iterator(&index_list, ",") { - // Temp allocator is fine since we just need to identify which test it's referring to. - split_selector := strings.split(selector, ".", context.temp_allocator) + if test_names != "" { + index_list := test_names + for selector in strings.split_iterator(&index_list, ",") { + // Temp allocator is fine since we just need to identify which test it's referring to. + split_selector := strings.split(selector, ".", context.temp_allocator) - found := false - switch len(split_selector) { - case 1: - // Only the test name? - #no_bounds_check name := split_selector[0] - find_test_by_name: for it in internal_tests { - if it.name == name { - found = true - _, alloc_error = append(&select_internal_tests, it) - fmt.assertf(alloc_error == nil, "Error appending to select internal tests: %v", alloc_error) - break find_test_by_name - } - } - case 2: - #no_bounds_check pkg := split_selector[0] - #no_bounds_check name := split_selector[1] - find_test_by_pkg_and_name: for it in internal_tests { - if it.pkg == pkg && it.name == name { - found = true - _, alloc_error = append(&select_internal_tests, it) - fmt.assertf(alloc_error == nil, "Error appending to select internal tests: %v", alloc_error) - break find_test_by_pkg_and_name - } + found := false + switch len(split_selector) { + case 1: + // Only the test name? + #no_bounds_check name := split_selector[0] + find_test_by_name: for it in internal_tests { + if it.name == name { + found = true + _, alloc_error = append(&select_internal_tests, it) + fmt.assertf(alloc_error == nil, "Error appending to select internal tests: %v", alloc_error) + break find_test_by_name } } - if !found { - fmt.wprintfln(stderr, "No test found for the name: %q", selector) + case 2: + #no_bounds_check pkg := split_selector[0] + #no_bounds_check name := split_selector[1] + find_test_by_pkg_and_name: for it in internal_tests { + if it.pkg == pkg && it.name == name { + found = true + _, alloc_error = append(&select_internal_tests, it) + fmt.assertf(alloc_error == nil, "Error appending to select internal tests: %v", alloc_error) + break find_test_by_pkg_and_name + } } } + if !found { + fmt.wprintfln(stderr, "No test found for the name: %q", selector) + } } - // `-vet` needs parameters to be shadowed by themselves first as an - // explicit declaration, to allow the next line to work. - internal_tests := internal_tests // Intentional shadow with user-specified tests. internal_tests = select_internal_tests[:] } @@ -268,12 +344,12 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { total_done_count := 0 total_test_count := len(internal_tests) - when !FANCY_OUTPUT { - // This is strictly for updating the window title when the progress - // report is disabled. We're otherwise able to depend on the call to - // `needs_to_redraw`. - last_done_count := -1 - } + + // This is strictly for updating the window title when the progress + // report is disabled. We're otherwise able to depend on the call to + // `needs_to_redraw`. + last_done_count := -1 + if total_test_count == 0 { // Exit early. @@ -299,7 +375,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { // -- Set thread count. when TEST_THREADS == 0 { - thread_count := os.processor_core_count() + thread_count := os.get_processor_core_count() } else { thread_count := max(1, TEST_THREADS) } @@ -342,31 +418,31 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { fmt.assertf(alloc_error == nil, "Error allocating memory for test report: %v", alloc_error) defer destroy_report(&report) - when FANCY_OUTPUT { - // We cannot make use of the ANSI save/restore cursor codes, because they - // work by absolute screen coordinates. This will cause unnecessary - // scrollback if we print at the bottom of someone's terminal. - ansi_redraw_string := fmt.aprintf( - // ANSI for "go up N lines then erase the screen from the cursor forward." - ansi.CSI + "%i" + ansi.CPL + ansi.CSI + ansi.ED + - // We'll combine this with the window title format string, since it - // can be printed at the same time. - "%s", - // 1 extra line for the status bar. - 1 + len(report.packages), OSC_WINDOW_TITLE) - assert(len(ansi_redraw_string) > 0, "Error allocating ANSI redraw string.") - defer delete(ansi_redraw_string) - thread_count_status_string: string = --- - { - PADDING :: PROGRESS_COLUMN_SPACING + PROGRESS_WIDTH + // We cannot make use of the ANSI save/restore cursor codes, because they + // work by absolute screen coordinates. This will cause unnecessary + // scrollback if we print at the bottom of someone's terminal. + ansi_redraw_string := fmt.aprintf( + // ANSI for "go up N lines then erase the screen from the cursor forward." + ansi.CSI + "%i" + ansi.CPL + ansi.CSI + ansi.ED + + // We'll combine this with the window title format string, since it + // can be printed at the same time. + "%s", + // 1 extra line for the status bar. + 1 + len(report.packages), OSC_WINDOW_TITLE) + assert(len(ansi_redraw_string) > 0, "Error allocating ANSI redraw string.") + defer delete(ansi_redraw_string) - unpadded := fmt.tprintf("%i thread%s", thread_count, "" if thread_count == 1 else "s") - thread_count_status_string = fmt.aprintf("%- *[1]s", unpadded, report.pkg_column_len + PADDING) - assert(len(thread_count_status_string) > 0, "Error allocating thread count status string.") - } - defer delete(thread_count_status_string) + thread_count_status_string: string = --- + { + PADDING :: PROGRESS_COLUMN_SPACING + PROGRESS_WIDTH + + unpadded := fmt.tprintf("%i thread%s", thread_count, "" if thread_count == 1 else "s") + thread_count_status_string = fmt.aprintf("%- *[1]s", unpadded, report.pkg_column_len + PADDING) + assert(len(thread_count_status_string) > 0, "Error allocating thread count status string.") } + defer delete(thread_count_status_string) + task_data_slots: []Task_Data = --- task_data_slots, alloc_error = make([]Task_Data, thread_count) @@ -442,11 +518,16 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { // digging through the source to divine everywhere it is used for that. shared_log_allocator := context.allocator + logger_options := Default_Test_Logger_Opts - {.Short_File_Path, .Line, .Procedure} + if global_log_colors_disabled { + logger_options -= {.Terminal_Color} + } + context.logger = { procedure = runner_logger_proc, data = &log_messages, lowest_level = get_log_level(), - options = Default_Test_Logger_Opts - {.Short_File_Path, .Line, .Procedure}, + options = logger_options, } run_index: int @@ -481,11 +562,13 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { setup_signal_handler() - fmt.wprint(stdout, ansi.CSI + ansi.DECTCEM_HIDE) + if !global_ansi_disabled { + fmt.wprint(stdout, ansi.CSI + ansi.DECTCEM_HIDE) + } - when FANCY_OUTPUT { - signals_were_raised := false + signals_were_raised := false + if should_show_animations { redraw_report(stdout, report) draw_status_bar(stdout, thread_count_status_string, total_done_count, total_test_count) } @@ -611,8 +694,8 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { total_done_count += 1 } - when ODIN_DEBUG { - log.debugf("Test #%i %s.%s changed state to %v.", task_channel.test_index, it.pkg, it.name, event.new_state) + when LOG_STATE_CHANGES { + log.infof("Test #%i %s.%s changed state to %v.", task_channel.test_index, it.pkg, it.name, event.new_state) } pkg.last_change_state = event.new_state @@ -703,25 +786,26 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { break main_loop } - when FANCY_OUTPUT { - // Because the bounds checking procs send directly to STDERR with - // no way to redirect or handle them, we need to at least try to - // let the user see those messages when using the animated progress - // report. This flag may be set by the block of code below if a - // signal is raised. - // - // It'll be purely by luck if the output is interleaved properly, - // given the nature of non-thread-safe printing. - // - // At worst, if Odin did not print any error for this signal, we'll - // just re-display the progress report. The fatal log error message - // should be enough to clue the user in that something dire has - // occurred. - bypass_progress_overwrite := false - } + + // Because the bounds checking procs send directly to STDERR with + // no way to redirect or handle them, we need to at least try to + // let the user see those messages when using the animated progress + // report. This flag may be set by the block of code below if a + // signal is raised. + // + // It'll be purely by luck if the output is interleaved properly, + // given the nature of non-thread-safe printing. + // + // At worst, if Odin did not print any error for this signal, we'll + // just re-display the progress report. The fatal log error message + // should be enough to clue the user in that something dire has + // occurred. + bypass_progress_overwrite := false + if test_index, reason, ok := should_stop_test(); ok { - #no_bounds_check report.all_test_states[test_index] = .Failed + passed := reason == .Successful_Stop + #no_bounds_check report.all_test_states[test_index] = .Successful if passed else .Failed #no_bounds_check it := internal_tests[test_index] #no_bounds_check pkg := report.packages_by_name[it.pkg] pkg.frame_ready = false @@ -742,7 +826,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { fmt.assertf(task_data != nil, "A signal (%v) was raised to stop test #%i %s.%s, but its task data is missing.", reason, test_index, it.pkg, it.name) - if !task_data.t._fail_now_called { + if !passed && !task_data.t._fail_now_called { if test_index not_in failed_test_reason_map { // We only write a new error message here if there wasn't one // already, because the message we can provide based only on @@ -752,7 +836,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { log.fatalf("Caught signal to stop test #%i %s.%s for: %v.", test_index, it.pkg, it.name, reason) } - when FANCY_OUTPUT { + if should_show_animations { bypass_progress_overwrite = true signals_were_raised = true } @@ -760,13 +844,17 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { end_t(&task_data.t) - total_failure_count += 1 + if passed { + total_success_count += 1 + } else { + total_failure_count += 1 + } total_done_count += 1 } // -- Redraw. - when FANCY_OUTPUT { + if should_show_animations { if len(log_messages) == 0 && !needs_to_redraw(report) { continue main_loop } @@ -776,7 +864,9 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { } } else { if total_done_count != last_done_count { - fmt.wprintf(stdout, OSC_WINDOW_TITLE, total_done_count, total_test_count) + if !(global_ansi_disabled || !FANCY_OUTPUT) { + fmt.wprintf(stdout, OSC_WINDOW_TITLE, total_done_count, total_test_count) + } last_done_count = total_done_count } @@ -801,7 +891,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { clear(&log_messages) bytes.buffer_reset(&batch_buffer) - when FANCY_OUTPUT { + if should_show_animations { redraw_report(batch_writer, report) draw_status_bar(batch_writer, thread_count_status_string, total_done_count, total_test_count) fmt.wprint(stdout, bytes.buffer_to_string(&batch_buffer)) @@ -822,7 +912,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { finished_in := time.since(start_time) - when !FANCY_OUTPUT { + if !should_show_animations || !terminal.is_terminal(os.stderr) { // One line to space out the results, since we don't have the status // bar in plain mode. fmt.wprintln(batch_writer) @@ -836,24 +926,28 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { if total_done_count != total_test_count { not_run_count := total_test_count - total_done_count + message := " %i %s left undone." if global_log_colors_disabled else " " + SGR_READY + "%i" + SGR_RESET + " %s left undone." fmt.wprintf(batch_writer, - " " + SGR_READY + "%i" + SGR_RESET + " %s left undone.", + message, not_run_count, "test was" if not_run_count == 1 else "tests were") } if total_success_count == total_test_count { + message := " %s successful." if global_log_colors_disabled else " %s " + SGR_SUCCESS + "successful." + SGR_RESET fmt.wprintfln(batch_writer, - " %s " + SGR_SUCCESS + "successful." + SGR_RESET, + message, "The test was" if total_test_count == 1 else "All tests were") } else if total_failure_count > 0 { if total_failure_count == total_test_count { + message := " %s failed." if global_log_colors_disabled else " %s " + SGR_FAILED + "failed." + SGR_RESET fmt.wprintfln(batch_writer, - " %s " + SGR_FAILED + "failed." + SGR_RESET, + message, "The test" if total_test_count == 1 else "All tests") } else { + message := " %i test%s failed." if global_log_colors_disabled else " " + SGR_FAILED + "%i" + SGR_RESET + " test%s failed." fmt.wprintfln(batch_writer, - " " + SGR_FAILED + "%i" + SGR_RESET + " test%s failed.", + message, total_failure_count, "" if total_failure_count == 1 else "s") } @@ -907,9 +1001,11 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { } } - fmt.wprint(stdout, ansi.CSI + ansi.DECTCEM_SHOW) + if !global_ansi_disabled { + fmt.wprint(stdout, ansi.CSI + ansi.DECTCEM_SHOW) + } - when FANCY_OUTPUT { + if should_show_animations { if signals_were_raised { fmt.wprintln(batch_writer, ` Signals were raised during this test run. Log messages are likely to have collided with each other. @@ -922,11 +1018,7 @@ To partly mitigate this, redirect STDERR to a file or use the -define:ODIN_TEST_ when JSON_REPORT != "" { json_report: JSON - mode: int - when ODIN_OS != .Windows { - mode = os.S_IRUSR|os.S_IWUSR|os.S_IRGRP|os.S_IROTH - } - json_fd, err := os.open(JSON_REPORT, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode) + json_fd, err := os.open(JSON_REPORT, {.Write, .Create, .Trunc}, {.Read_User, .Write_User, .Read_Group, .Read_Other}) fmt.assertf(err == nil, "unable to open file %q for writing of JSON report, error: %v", JSON_REPORT, err) defer os.close(json_fd) @@ -945,8 +1037,8 @@ To partly mitigate this, redirect STDERR to a file or use the -define:ODIN_TEST_ json_report.success = total_success_count json_report.duration = finished_in - err := json.marshal_to_writer(os.stream_from_handle(json_fd), json_report, &{ pretty = true }) - fmt.assertf(err == nil, "Error writing JSON report: %v", err) + json_err := json.marshal_to_writer(os.to_stream(json_fd), json_report, &{ pretty = true }) + fmt.assertf(json_err == nil, "Error writing JSON report: %v", json_err) } return total_success_count == total_test_count diff --git a/core/testing/runner_windows.odin b/core/testing/runner_windows.odin deleted file mode 100644 index 401804c71..000000000 --- a/core/testing/runner_windows.odin +++ /dev/null @@ -1,22 +0,0 @@ -#+private -package testing - -import win32 "core:sys/windows" - -console_ansi_init :: proc() { - stdout := win32.GetStdHandle(win32.STD_OUTPUT_HANDLE) - if stdout != win32.INVALID_HANDLE && stdout != nil { - old_console_mode: u32 - if win32.GetConsoleMode(stdout, &old_console_mode) { - win32.SetConsoleMode(stdout, old_console_mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } - - stderr := win32.GetStdHandle(win32.STD_ERROR_HANDLE) - if stderr != win32.INVALID_HANDLE && stderr != nil { - old_console_mode: u32 - if win32.GetConsoleMode(stderr, &old_console_mode) { - win32.SetConsoleMode(stderr, old_console_mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } -} diff --git a/core/testing/signal_handler.odin b/core/testing/signal_handler.odin index 2f1f7c89a..b33732a30 100644 --- a/core/testing/signal_handler.odin +++ b/core/testing/signal_handler.odin @@ -3,7 +3,7 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Total rewrite. @@ -12,8 +12,26 @@ package testing import "base:runtime" import "core:log" +@(private, thread_local) +local_test_expected_failures: struct { + signal: i32, + + message_count: int, + messages: [MAX_EXPECTED_ASSERTIONS_PER_TEST]string, + + location_count: int, + locations: [MAX_EXPECTED_ASSERTIONS_PER_TEST]runtime.Source_Code_Location, +} + +@(private, thread_local) +local_test_assertion_raised: struct { + message: string, + location: runtime.Source_Code_Location, +} + Stop_Reason :: enum { Unknown, + Successful_Stop, Illegal_Instruction, Arithmetic_Error, Segmentation_Fault, @@ -21,7 +39,12 @@ Stop_Reason :: enum { } test_assertion_failure_proc :: proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! { - log.fatalf("%s: %s", prefix, message, location = loc) + if local_test_expected_failures.message_count + local_test_expected_failures.location_count > 0 { + local_test_assertion_raised = { message, loc } + log.debugf("%s\n\tmessage: %q\n\tlocation: %w", prefix, message, loc) + } else { + log.fatalf("%s: %s", prefix, message, location = loc) + } runtime.trap() } diff --git a/core/testing/signal_handler_libc.odin b/core/testing/signal_handler_libc.odin index 281fbde40..16a33810a 100644 --- a/core/testing/signal_handler_libc.odin +++ b/core/testing/signal_handler_libc.odin @@ -1,33 +1,37 @@ #+private -#+build windows, linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Total rewrite. + blob1807: Windows Win32 API rewrite. */ import "base:intrinsics" import "core:c/libc" -import "core:encoding/ansi" -import "core:sync" import "core:os" +import "core:sync" +import "core:terminal/ansi" @(private="file") stop_runner_flag: libc.sig_atomic_t @(private="file") stop_test_gate: sync.Mutex @(private="file") stop_test_index: libc.sig_atomic_t -@(private="file") stop_test_reason: libc.sig_atomic_t +@(private="file") stop_test_signal: libc.sig_atomic_t +@(private="file") stop_test_passed: libc.sig_atomic_t @(private="file") stop_test_alert: libc.sig_atomic_t + @(private="file", thread_local) local_test_index: libc.sig_atomic_t @(private="file", thread_local) local_test_index_set: bool + // Windows does not appear to have a SIGTRAP, so this is defined here, instead // of in the libc package, just so there's no confusion about it being // available there. @@ -63,9 +67,11 @@ stop_test_callback :: proc "c" (sig: libc.int) { // NOTE(Feoramund): Using these write calls in a signal handler is // undefined behavior in C99 but possibly tolerated in POSIX 2008. // Either way, we may as well try to salvage what we can. - show_cursor := ansi.CSI + ansi.DECTCEM_SHOW - libc.fwrite(raw_data(show_cursor), size_of(byte), len(show_cursor), libc.stdout) - libc.fflush(libc.stdout) + if !global_ansi_disabled { + show_cursor := ansi.CSI + ansi.DECTCEM_SHOW + libc.fwrite(raw_data(show_cursor), size_of(byte), len(show_cursor), libc.stdout) + libc.fflush(libc.stdout) + } // This is an attempt at being compliant by avoiding printf. sigbuf: [8]byte @@ -85,7 +91,7 @@ stop_test_callback :: proc "c" (sig: libc.int) { advisory_a := ` The test runner's main thread has caught an unrecoverable error (signal ` advisory_b := `) and will now forcibly terminate. -This is a dire bug and should be reported to the Odin developers. +Unless you terminated the tests yourself, this could be a dire bug and should be reported to the Odin developers. ` libc.fwrite(raw_data(advisory_a), size_of(byte), len(advisory_a), libc.stderr) libc.fwrite(raw_data(sigstr), size_of(byte), len(sigstr), libc.stderr) @@ -97,7 +103,30 @@ This is a dire bug and should be reported to the Odin developers. if sync.mutex_guard(&stop_test_gate) { intrinsics.atomic_store(&stop_test_index, local_test_index) - intrinsics.atomic_store(&stop_test_reason, cast(libc.sig_atomic_t)sig) + intrinsics.atomic_store(&stop_test_signal, cast(libc.sig_atomic_t)sig) + passed: bool + check_passing: { + if location := local_test_assertion_raised.location; location != {} { + for i in 0.. (test_index: int, reason: Stop_Reason, ok: bool) intrinsics.atomic_store(&stop_test_alert, 0) test_index = cast(int)intrinsics.atomic_load(&stop_test_index) - switch intrinsics.atomic_load(&stop_test_reason) { - case libc.SIGFPE: reason = .Arithmetic_Error - case libc.SIGILL: reason = .Illegal_Instruction - case libc.SIGSEGV: reason = .Segmentation_Fault - case SIGTRAP: reason = .Unhandled_Trap + if cast(bool)intrinsics.atomic_load(&stop_test_passed) { + reason = .Successful_Stop + } else { + switch intrinsics.atomic_load(&stop_test_signal) { + case libc.SIGFPE: reason = .Arithmetic_Error + case libc.SIGILL: reason = .Illegal_Instruction + case libc.SIGSEGV: reason = .Segmentation_Fault + case SIGTRAP: reason = .Unhandled_Trap + } } ok = true } diff --git a/core/testing/signal_handler_other.odin b/core/testing/signal_handler_other.odin index 81f575495..243271b60 100644 --- a/core/testing/signal_handler_other.odin +++ b/core/testing/signal_handler_other.odin @@ -5,12 +5,11 @@ #+build !freebsd #+build !openbsd #+build !netbsd -#+build !haiku package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Total rewrite. diff --git a/core/testing/signal_handler_posix.odin b/core/testing/signal_handler_posix.odin index 0efba27dc..1bfcc875b 100644 --- a/core/testing/signal_handler_posix.odin +++ b/core/testing/signal_handler_posix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, netbsd, openbsd, freebsd, haiku +#+build linux, darwin, netbsd, openbsd, freebsd #+private package testing diff --git a/core/testing/signal_handler_windows.odin b/core/testing/signal_handler_windows.odin index 74ebe2998..f9d0f85a7 100644 --- a/core/testing/signal_handler_windows.odin +++ b/core/testing/signal_handler_windows.odin @@ -1,6 +1,213 @@ #+private +#+build windows package testing -__setup_signal_handler :: proc() {} +/* + (c) Copyright 2024 Feoramund . + Made available under Odin's license. + + List of contributors: + Feoramund: Total rewrite. + blob1807: Windows Win32 API rewrite. +*/ + +import "base:runtime" +import "base:intrinsics" + +import "core:os" +import "core:sync" +import "core:c/libc" +import "core:strconv" +import "core:terminal/ansi" + +import win32 "core:sys/windows" + + +@(private="file") stop_runner_flag: int + +@(private="file") stop_test_gate: sync.Mutex +@(private="file") stop_test_index: int +@(private="file") stop_test_signal: win32.DWORD +@(private="file") stop_test_passed: bool +@(private="file") stop_test_alert: int + + +when ODIN_ARCH == .i386 { + // Thread-local storage is problematic on Windows i386 + @(private="file") + local_test_index: int + @(private="file") + local_test_index_set: bool +} else { + @(private="file", thread_local) + local_test_index: int + @(private="file", thread_local) + local_test_index_set: bool +} + + +@(private="file") +stop_runner_callback :: proc "system" (ctrl_type: win32.DWORD) -> win32.BOOL { + if ctrl_type == win32.CTRL_C_EVENT { + prev := intrinsics.atomic_add(&stop_runner_flag, 1) + + // If the flag was already set (if this is the second signal sent for example), + // consider this a forced (not graceful) exit. + if prev > 0 { + os.exit(1) + } + // Say we've hanndled the signal. + return true + } + + // This will also get called for other events which we don't handle for. + // Instead we pass it on to the next handler. + return false +} + +@(private) +stop_test_callback :: proc "system" (info: ^win32.EXCEPTION_POINTERS) -> win32.LONG { + if !local_test_index_set { + // We're a thread created by a test thread. + // + // There's nothing we can do to inform the test runner about who + // signalled, so hopefully the test will handle their own sub-threads. + return win32.EXCEPTION_CONTINUE_SEARCH + } + + context = runtime.default_context() + code := info.ExceptionRecord.ExceptionCode + + if local_test_index == -1 { + // We're the test runner, and we ourselves have caught a signal from + // which there is no recovery. + // + // The most we can do now is make sure the user's cursor is visible, + // nuke the entire processs, and hope a useful core dump survives. + if !global_ansi_disabled { + show_cursor := ansi.CSI + ansi.DECTCEM_SHOW + os.write_string(os.stdout, show_cursor) + os.flush(os.stdout) + } + + expbuf: [8]byte + expstr := strconv.write_uint(expbuf[:], cast(u64)code, 16) + for &c in expbuf { + if 'a' <= c && c <= 'f' { + c -= 32 + } + } + + advisory_a := ` +The test runner's main thread has caught an unrecoverable error (exception 0x` + advisory_b := `) and will now forcibly terminate. +This is a dire bug and should be reported to the Odin developers. +` + os.write_string(os.stderr, advisory_a) + os.write_string(os.stderr, expstr) + os.write_string(os.stderr, advisory_b) + os.flush(os.stderr) + + win32.TerminateProcess(win32.GetCurrentProcess(), 1) + } + + if sync.mutex_guard(&stop_test_gate) { + intrinsics.atomic_store(&stop_test_index, local_test_index) + intrinsics.atomic_store(&stop_test_signal, code) + passed: bool + check_passing: { + if location := local_test_assertion_raised.location; location != {} { + for i in 0.. bool { + return intrinsics.atomic_load(&stop_runner_flag) == 1 +} + +@(private="file") +unlock_stop_test_gate :: proc(_: int, _: Stop_Reason, ok: bool) { + if ok { + sync.mutex_unlock(&stop_test_gate) + } +} + +@(deferred_out=unlock_stop_test_gate) +_should_stop_test :: proc() -> (test_index: int, reason: Stop_Reason, ok: bool) { + if intrinsics.atomic_load(&stop_test_alert) == 1 { + intrinsics.atomic_store(&stop_test_alert, 0) + + test_index = intrinsics.atomic_load(&stop_test_index) + if intrinsics.atomic_load(&stop_test_passed) { + reason = .Successful_Stop + } else { + switch intrinsics.atomic_load(&stop_test_signal) { + case win32.EXCEPTION_ARRAY_BOUNDS_EXCEEDED: reason = .Illegal_Instruction + case win32.EXCEPTION_ILLEGAL_INSTRUCTION: reason = .Illegal_Instruction + case win32.EXCEPTION_ACCESS_VIOLATION: reason = .Segmentation_Fault + case win32.EXCEPTION_BREAKPOINT: reason = .Unhandled_Trap + case win32.EXCEPTION_SINGLE_STEP: reason = .Unhandled_Trap + + case win32.EXCEPTION_FLT_DENORMAL_OPERAND ..= win32.EXCEPTION_INT_OVERFLOW: + reason = .Arithmetic_Error + } + } + ok = true + } + + return +} -_test_thread_cancel :: proc "contextless" () {} diff --git a/core/testing/testing.odin b/core/testing/testing.odin index 09bf6dc0e..7182f77f5 100644 --- a/core/testing/testing.odin +++ b/core/testing/testing.odin @@ -2,7 +2,7 @@ package testing /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Ginger Bill: Initial implementation. @@ -21,6 +21,8 @@ import "core:mem" _ :: reflect // alias reflect to nothing to force visibility for -vet _ :: mem // in case TRACKING_MEMORY is not enabled +MAX_EXPECTED_ASSERTIONS_PER_TEST :: 5 + // IMPORTANT NOTE: Compiler requires this layout Test_Signature :: proc(^T) @@ -155,3 +157,74 @@ set_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location location = loc, }) } + +/* +Let the test runner know that it should expect an assertion failure from a +specific location in the source code for this test. + +In the event that an assertion fails, a debug message will be logged with its +exact message and location in a copyable format to make it convenient to write +tests which use this API. + +This procedure may be called up to 5 times with different locations. + +This is a limitation for the sake of simplicity in the implementation, and you +should consider breaking up your tests into smaller procedures if you need to +check for asserts in more than 2 places. +*/ +expect_assert_from :: proc(t: ^T, expected_place: runtime.Source_Code_Location, caller_loc := #caller_location) { + count := local_test_expected_failures.location_count + if count == MAX_EXPECTED_ASSERTIONS_PER_TEST { + panic("This test cannot handle that many expected assertions based on matching the location.", caller_loc) + } + local_test_expected_failures.locations[count] = expected_place + local_test_expected_failures.location_count += 1 +} + +/* +Let the test runner know that it should expect an assertion failure with a +specific message for this test. + +In the event that an assertion fails, a debug message will be logged with its +exact message and location in a copyable format to make it convenient to write +tests which use this API. + +This procedure may be called up to 5 times with different messages. + +This is a limitation for the sake of simplicity in the implementation, and you +should consider breaking up your tests into smaller procedures if you need to +check for more than a couple different assertion messages. +*/ +expect_assert_message :: proc(t: ^T, expected_message: string, caller_loc := #caller_location) { + count := local_test_expected_failures.message_count + if count == MAX_EXPECTED_ASSERTIONS_PER_TEST { + panic("This test cannot handle that many expected assertions based on matching the message.", caller_loc) + } + local_test_expected_failures.messages[count] = expected_message + local_test_expected_failures.message_count += 1 +} + +expect_assert :: proc { + expect_assert_from, + expect_assert_message, +} + +/* +Let the test runner know that it should expect a signal to be raised within +this test. + +This API is for advanced users, as arbitrary signals will not be caught; only +the ones already handled by the test runner, such as + +- SIGINT, (interrupt) +- SIGTERM, (polite termination) +- SIGILL, (illegal instruction) +- SIGFPE, (arithmetic error) +- SIGSEGV, and (segmentation fault) +- SIGTRAP (only on POSIX systems). (trap / debug trap) + +Note that only one signal can be expected per test. +*/ +expect_signal :: proc(t: ^T, #any_int sig: i32) { + local_test_expected_failures.signal = sig +} diff --git a/core/text/edit/text_edit.odin b/core/text/edit/text_edit.odin index 49adad4d9..58e184309 100644 --- a/core/text/edit/text_edit.odin +++ b/core/text/edit/text_edit.odin @@ -1,4 +1,6 @@ /* +Text edit primitives to use in a text box. + Based off the articles by rxi: - [[ https://rxi.github.io/textbox_behaviour.html ]] - [[ https://rxi.github.io/a_simple_undo_system.html ]] @@ -22,6 +24,7 @@ State :: struct { up_index, down_index: int, // multi-lines + translate_by_grapheme: bool, // translates by codepoint by default // undo undo: [dynamic]^Undo_State, @@ -300,14 +303,32 @@ translate_position :: proc(s: ^State, t: Translation) -> int { case .End: pos = len(buf) case .Left: - pos -= 1 - for pos >= 0 && is_continuation_byte(buf[pos]) { + if s.translate_by_grapheme { + // TODO(bill): determine if there is a faster way to determine the last grapheme + // rather than iterate across the entire string (which may be very slow) + it := utf8.decode_grapheme_iterator_make(string(buf[:pos])) + g: utf8.Grapheme + for { + _, g = utf8.decode_grapheme_iterate(&it) or_break + } + pos -= max(g.width, 1) + } else { pos -= 1 + for pos >= 0 && is_continuation_byte(buf[pos]) { + pos -= 1 + } } case .Right: - pos += 1 - for pos < len(buf) && is_continuation_byte(buf[pos]) { + if s.translate_by_grapheme { + it := utf8.decode_grapheme_iterator_make(string(buf[pos:])) + + _, g, _ := utf8.decode_grapheme_iterate(&it) + pos += max(g.width, 1) + } else { pos += 1 + for pos < len(buf) && is_continuation_byte(buf[pos]) { + pos += 1 + } } case .Up: pos = s.up_index diff --git a/core/text/i18n/doc.odin b/core/text/i18n/doc.odin index d590fd123..14a095229 100644 --- a/core/text/i18n/doc.odin +++ b/core/text/i18n/doc.odin @@ -1,6 +1,6 @@ /* -The `i18n` package is a flexible and easy to use way to localise applications. +A flexible and easy way to add translations/internationalization (`i18n`) to applications. It has two calls to get a translation: `get()` and `get_n()`, which the user can alias into something like `T` and `Tn` with statements like: @@ -51,8 +51,6 @@ Example: Tn :: i18n.get_n mo :: proc() { - using fmt - err: i18n.Error // Parse MO file and set it as the active translation so we can omit `get`'s "catalog" parameter. @@ -62,26 +60,24 @@ Example: if err != .None { return } // These are in the .MO catalog. - println("-----") - println(T("")) - println("-----") - println(T("There are 69,105 leaves here.")) - println("-----") - println(T("Hellope, World!")) - println("-----") + fmt.println("-----") + fmt.println(T("")) + fmt.println("-----") + fmt.println(T("There are 69,105 leaves here.")) + fmt.println("-----") + fmt.println(T("Hellope, World!")) + fmt.println("-----") // We pass 1 into `T` to get the singular format string, then 1 again into printf. - printf(Tn("There is %d leaf.\n", 1), 1) + fmt.printf(Tn("There is %d leaf.\n", 1), 1) // We pass 42 into `T` to get the plural format string, then 42 again into printf. - printf(Tn("There is %d leaf.\n", 42), 42) + fmt.printf(Tn("There is %d leaf.\n", 42), 42) // This isn't in the translation catalog, so the key is passed back untranslated. - println("-----") - println(T("Come visit us on Discord!")) + fmt.println("-----") + fmt.println(T("Come visit us on Discord!")) } qt :: proc() { - using fmt - err: i18n.Error // Parse QT file and set it as the active translation so we can omit `get`'s "catalog" parameter. @@ -91,18 +87,18 @@ Example: if err != .None { return } // These are in the .TS catalog. As you can see they have sections. - println("--- Page section ---") - println("Page:Text for translation =", T("Page", "Text for translation")) - println("-----") - println("Page:Also text to translate =", T("Page", "Also text to translate")) - println("-----") - println("--- installscript section ---") - println("installscript:99 bottles of beer on the wall =", T("installscript", "99 bottles of beer on the wall")) - println("-----") - println("--- apple_count section ---") - println("apple_count:%d apple(s) =") - println("\t 1 =", Tn("apple_count", "%d apple(s)", 1)) - println("\t 42 =", Tn("apple_count", "%d apple(s)", 42)) + fmt.println("--- Page section ---") + fmt.println("Page:Text for translation =", T("Page", "Text for translation")) + fmt.println("-----") + fmt.println("Page:Also text to translate =", T("Page", "Also text to translate")) + fmt.println("-----") + fmt.println("--- installscript section ---") + fmt.println("installscript:99 bottles of beer on the wall =", T("installscript", "99 bottles of beer on the wall")) + fmt.println("-----") + fmt.println("--- apple_count section ---") + fmt.println("apple_count:%d apple(s) =") + fmt.println("\t 1 =", Tn("apple_count", "%d apple(s)", 1)) + fmt.println("\t 42 =", Tn("apple_count", "%d apple(s)", 42)) } */ package i18n diff --git a/core/text/i18n/gettext.odin b/core/text/i18n/gettext.odin index 3ac9109ef..b0e3dae67 100644 --- a/core/text/i18n/gettext.odin +++ b/core/text/i18n/gettext.odin @@ -3,7 +3,7 @@ package i18n A parser for GNU GetText .MO files. Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. A from-scratch implementation based after the specification found here: https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html @@ -14,7 +14,6 @@ package i18n List of contributors: Jeroen van Rijn: Initial implementation. */ -import "core:os" import "core:strings" import "core:bytes" @@ -28,22 +27,17 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur return {}, .MO_File_Invalid } - /* - Check magic. Should be 0x950412de in native Endianness. - */ + // Check magic. Should be 0x950412de in native Endianness. native := true magic := read_u32(data, native) or_return if magic != 0x950412de { native = false - magic = read_u32(data, native) or_return - + magic = read_u32(data, native) or_return if magic != 0x950412de { return {}, .MO_File_Invalid_Signature } } - /* - We can ignore version_minor at offset 6. - */ + // We can ignore version_minor at offset 6. version_major := read_u16(data[4:]) or_return if version_major > 1 { return {}, .MO_File_Unsupported_Version } @@ -53,17 +47,13 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur if count == 0 { return {}, .Empty_Translation_Catalog } - /* - Initalize Translation, interner and optional pluralizer. - */ + // Initalize Translation, interner and optional pluralizer. translation = new(Translation) translation.pluralize = pluralizer strings.intern_init(&translation.intern, allocator, allocator) for n := u32(0); n < count; n += 1 { - /* - Grab string's original length and offset. - */ + // Grab string's original length and offset. offset := original_offset + 8 * n if len(data) < int(offset + 8) { return translation, .MO_File_Invalid } @@ -82,9 +72,7 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur key_data := data[o_offset:][:o_length] val_data := data[t_offset:][:t_length] - /* - Could be a pluralized string. - */ + // Could be a pluralized string. zero := []byte{0} keys := bytes.split(key_data, zero); defer delete(keys) vals := bytes.split(val_data, zero); defer delete(vals) @@ -137,22 +125,7 @@ parse_mo_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTIONS, plur return } -parse_mo_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { - context.allocator = allocator - - data, data_ok := os.read_entire_file(filename) - defer delete(data) - - if !data_ok { return {}, .File_Error } - - return parse_mo_from_bytes(data, options, pluralizer, allocator) -} - -parse_mo :: proc { parse_mo_file, parse_mo_from_bytes } - -/* - Helpers. -*/ +@(private) read_u32 :: proc(data: []u8, native_endian := true) -> (res: u32, err: Error) { if len(data) < size_of(u32) { return 0, .Premature_EOF } @@ -169,6 +142,7 @@ read_u32 :: proc(data: []u8, native_endian := true) -> (res: u32, err: Error) { } } +@(private) read_u16 :: proc(data: []u8, native_endian := true) -> (res: u16, err: Error) { if len(data) < size_of(u16) { return 0, .Premature_EOF } diff --git a/core/text/i18n/i18_js.odin b/core/text/i18n/i18_js.odin new file mode 100644 index 000000000..73e8535a5 --- /dev/null +++ b/core/text/i18n/i18_js.odin @@ -0,0 +1,16 @@ +#+build freestanding +#+build js +package i18n +/* + Internationalization helpers. + + Copyright 2021-2022 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. +*/ +@(private) +parse_qt :: proc { parse_qt_linguist_from_bytes } + +parse_mo :: proc { parse_mo_from_bytes } \ No newline at end of file diff --git a/core/text/i18n/i18n.odin b/core/text/i18n/i18n.odin index 0190ef0f7..148fe229f 100644 --- a/core/text/i18n/i18n.odin +++ b/core/text/i18n/i18n.odin @@ -3,12 +3,12 @@ package i18n Internationalization helpers. Copyright 2021-2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. */ -import "core:strings" +import "core:strings" // Currently active catalog. ACTIVE: ^Translation diff --git a/core/text/i18n/i18n_os.odin b/core/text/i18n/i18n_os.odin new file mode 100644 index 000000000..7a7995612 --- /dev/null +++ b/core/text/i18n/i18n_os.odin @@ -0,0 +1,38 @@ +#+build !freestanding +#+build !js +package i18n +/* + Internationalization helpers. + + Copyright 2021-2022 Jeroen van Rijn . + Made available under Odin's license. + + List of contributors: + Jeroen van Rijn: Initial implementation. +*/ +import "base:runtime" +import "core:os" + +@(private) +read_file :: proc(filename: string, allocator: runtime.Allocator) -> (data: []u8, err: Error) { + file_data, file_err := os.read_entire_file(filename, allocator) + if file_err != nil { + return {}, .File_Error + } + return file_data, nil +} + +parse_qt_linguist_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { + data := read_file(filename, allocator) or_return + return parse_qt_linguist_from_bytes(data, options, pluralizer, allocator) +} + +parse_qt :: proc { parse_qt_linguist_file, parse_qt_linguist_from_bytes } + +parse_mo_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { + data := read_file(filename, allocator) or_return + defer delete(data) + return parse_mo_from_bytes(data, options, pluralizer, allocator) +} + +parse_mo :: proc { parse_mo_file, parse_mo_from_bytes } \ No newline at end of file diff --git a/core/text/i18n/qt_linguist.odin b/core/text/i18n/qt_linguist.odin index bdd3f5fd7..9c5791b67 100644 --- a/core/text/i18n/qt_linguist.odin +++ b/core/text/i18n/qt_linguist.odin @@ -3,7 +3,7 @@ package i18n A parser for Qt Linguist TS files. Copyright 2022 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. A from-scratch implementation based after the specification found here: https://doc.qt.io/qt-5/linguist-ts-file-format.html @@ -11,7 +11,6 @@ package i18n List of contributors: Jeroen van Rijn: Initial implementation. */ -import "core:os" import "core:encoding/xml" import "core:strings" @@ -56,9 +55,7 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI return nil, .TS_File_Parse_Error } - /* - Initalize Translation, interner and optional pluralizer. - */ + // Initalize Translation, interner and optional pluralizer. translation = new(Translation) translation.pluralize = pluralizer strings.intern_init(&translation.intern, allocator, allocator) @@ -69,7 +66,6 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI child_id := get_id(value) or_return // These should be s. - if ts.elements[child_id].ident != "context" { return translation, .TS_File_Expected_Context } @@ -158,13 +154,3 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI return } -parse_qt_linguist_file :: proc(filename: string, options := DEFAULT_PARSE_OPTIONS, pluralizer: proc(int) -> int = nil, allocator := context.allocator) -> (translation: ^Translation, err: Error) { - context.allocator = allocator - - data, data_ok := os.read_entire_file(filename) - if !data_ok { return {}, .File_Error } - - return parse_qt_linguist_from_bytes(data, options, pluralizer, allocator) -} - -parse_qt :: proc { parse_qt_linguist_file, parse_qt_linguist_from_bytes } \ No newline at end of file diff --git a/core/text/match/strlib.odin b/core/text/match/strlib.odin index 819f464c5..c836253ec 100644 --- a/core/text/match/strlib.odin +++ b/core/text/match/strlib.odin @@ -1,3 +1,4 @@ +// A Lua-like string match algorithm. package text_match import "base:runtime" @@ -9,11 +10,12 @@ MAX_CAPTURES :: 32 Capture :: struct { init: int, - len: int, + len: int, } Match :: struct { - byte_start, byte_end: int, + byte_start: int, + byte_end: int, } Error :: enum { @@ -27,18 +29,19 @@ Error :: enum { Match_Invalid, } -L_ESC :: '%' -CAP_POSITION :: -2 +L_ESC :: '%' +CAP_POSITION :: -2 CAP_UNFINISHED :: -1 -INVALID :: -1 +INVALID :: -1 Match_State :: struct { - src: string, + src: string, pattern: string, - level: int, + level: int, capture: [MAX_CAPTURES]Capture, } +@(require_results) match_class :: proc(c: rune, cl: rune) -> (res: bool) { switch unicode.to_lower(cl) { case 'a': res = is_alpha(c) @@ -65,19 +68,23 @@ is_punct :: unicode.is_punct is_space :: unicode.is_space is_cntrl :: unicode.is_control +@(require_results) is_alnum :: proc(c: rune) -> bool { return unicode.is_alpha(c) || unicode.is_digit(c) } +@(require_results) is_graph :: proc(c: rune) -> bool { return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || unicode.is_digit(c) } +@(require_results) is_xdigit :: proc(c: rune) -> bool { return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || unicode.is_digit(c) } // find the first utf8 charater and its size, return an error if the character is an error +@(require_results) utf8_peek :: proc(bytes: string) -> (c: rune, size: int, err: Error) { c, size = utf8.decode_rune_in_string(bytes) @@ -90,6 +97,7 @@ utf8_peek :: proc(bytes: string) -> (c: rune, size: int, err: Error) { // find the first utf8 charater and its size and advance the index // return an error if the character is an error +@(require_results) utf8_advance :: proc(bytes: string, index: ^int) -> (c: rune, err: Error) { size: int c, size = utf8.decode_rune_in_string(bytes[index^:]) @@ -103,10 +111,12 @@ utf8_advance :: proc(bytes: string, index: ^int) -> (c: rune, err: Error) { } // continuation byte? +@(require_results) is_cont :: proc(b: byte) -> bool { return b & 0xc0 == 0x80 } +@(require_results) utf8_prev :: proc(bytes: string, a, b: int) -> int { b := b @@ -117,6 +127,7 @@ utf8_prev :: proc(bytes: string, a, b: int) -> int { return a < b ? b - 1 : a } +@(require_results) utf8_next :: proc(bytes: string, a: int) -> int { a := a b := len(bytes) @@ -128,6 +139,7 @@ utf8_next :: proc(bytes: string, a: int) -> int { return a < b ? a + 1 : b } +@(require_results) check_capture :: proc(ms: ^Match_State, l: rune) -> (int, Error) { l := int(l - '1') @@ -138,6 +150,7 @@ check_capture :: proc(ms: ^Match_State, l: rune) -> (int, Error) { return l, .OK } +@(require_results) capture_to_close :: proc(ms: ^Match_State) -> (int, Error) { level := ms.level - 1 @@ -152,6 +165,7 @@ capture_to_close :: proc(ms: ^Match_State) -> (int, Error) { return 0, .Invalid_Pattern_Capture } +@(require_results) class_end :: proc(ms: ^Match_State, p: int) -> (step: int, err: Error) { step = p ch := utf8_advance(ms.pattern, &step) or_return @@ -163,7 +177,7 @@ class_end :: proc(ms: ^Match_State, p: int) -> (step: int, err: Error) { return } - utf8_advance(ms.pattern, &step) or_return + _ = utf8_advance(ms.pattern, &step) or_return case '[': // fine with step by 1 @@ -198,6 +212,7 @@ class_end :: proc(ms: ^Match_State, p: int) -> (step: int, err: Error) { return } +@(require_results) match_bracket_class :: proc(ms: ^Match_State, c: rune, p, ec: int) -> (sig: bool, err: Error) { sig = true p := p @@ -240,6 +255,7 @@ match_bracket_class :: proc(ms: ^Match_State, c: rune, p, ec: int) -> (sig: bool return } +@(require_results) single_match :: proc(ms: ^Match_State, s, p, ep: int) -> (matched: bool, schar_size: int, err: Error) { if s >= len(ms.src) { return @@ -254,13 +270,16 @@ single_match :: proc(ms: ^Match_State, s, p, ep: int) -> (matched: bool, schar_s case L_ESC: pchar_next, _ := utf8_peek(ms.pattern[p + psize:]) or_return matched = match_class(schar, pchar_next) - case '[': matched = match_bracket_class(ms, schar, p, ep - 1) or_return - case: matched = schar == pchar + case '[': + matched = match_bracket_class(ms, schar, p, ep - 1) or_return + case: + matched = schar == pchar } return } +@(require_results) match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { if p >= len(ms.pattern) - 1 { return INVALID, .Invalid_Pattern_Capture @@ -300,13 +319,13 @@ match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) return INVALID, .OK } +@(require_results) max_expand :: proc(ms: ^Match_State, s, p, ep: int) -> (res: int, err: Error) { m := s // count up matches for { matched, size := single_match(ms, m, p, ep) or_return - if !matched { break } @@ -316,7 +335,6 @@ max_expand :: proc(ms: ^Match_State, s, p, ep: int) -> (res: int, err: Error) { for s <= m { result := match(ms, m, ep + 1) or_return - if result != INVALID { return result, .OK } @@ -331,6 +349,7 @@ max_expand :: proc(ms: ^Match_State, s, p, ep: int) -> (res: int, err: Error) { return INVALID, .OK } +@(require_results) min_expand :: proc(ms: ^Match_State, s, p, ep: int) -> (res: int, err: Error) { s := s @@ -339,19 +358,19 @@ min_expand :: proc(ms: ^Match_State, s, p, ep: int) -> (res: int, err: Error) { if result != INVALID { return result, .OK - } else { - // TODO receive next step maybe? - matched, rune_size := single_match(ms, s, p, ep) or_return + } + // TODO receive next step maybe? + matched, rune_size := single_match(ms, s, p, ep) or_return - if matched { - s += rune_size - } else { - return INVALID, .OK - } + if matched { + s += rune_size + } else { + return INVALID, .OK } } } +@(require_results) start_capture :: proc(ms: ^Match_State, s, p, what: int) -> (res: int, err: Error) { level := ms.level @@ -366,6 +385,7 @@ start_capture :: proc(ms: ^Match_State, s, p, what: int) -> (res: int, err: Erro return } +@(require_results) end_capture :: proc(ms: ^Match_State, s, p: int) -> (res: int, err: Error) { l := capture_to_close(ms) or_return @@ -379,6 +399,7 @@ end_capture :: proc(ms: ^Match_State, s, p: int) -> (res: int, err: Error) { return } +@(require_results) match_capture :: proc(ms: ^Match_State, s: int, char: rune) -> (res: int, err: Error) { index := check_capture(ms, char) or_return length := ms.capture[index].len @@ -390,6 +411,7 @@ match_capture :: proc(ms: ^Match_State, s: int, char: rune) -> (res: int, err: E return INVALID, .OK } +@(require_results) match :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { s := s p := p @@ -431,7 +453,6 @@ match :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { // balanced string case 'b': s = match_balance(ms, s, p + 2) or_return - if s != INVALID { // eg after %b() return match(ms, s, p + 4) @@ -460,7 +481,7 @@ match :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { } m1 := match_bracket_class(ms, previous, p, ep - 1) or_return - m2 := match_bracket_class(ms, current, p, ep - 1) or_return + m2 := match_bracket_class(ms, current, p, ep - 1) or_return if !m1 && m2 { return match(ms, s, ep) @@ -486,6 +507,7 @@ match :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { return s, .OK } +@(require_results) match_default :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) { s := s ep := class_end(ms, p) or_return @@ -495,8 +517,10 @@ match_default :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) epc := ep < len(ms.pattern) ? ms.pattern[ep] : 0 switch epc { - case '*', '?', '-': return match(ms, s, ep + 1) - case: s = INVALID + case '*', '?', '-': + return match(ms, s, ep + 1) + case: + s = INVALID } } else { epc := ep < len(ms.pattern) ? ms.pattern[ep] : 0 @@ -505,22 +529,23 @@ match_default :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error) case '?': result := match(ms, s + ssize, ep + 1) or_return - if result != INVALID { - s = result - } else { + if result == INVALID { return match(ms, s, ep + 1) } + s = result case '+': s = max_expand(ms, s + ssize, p, ep) or_return - case '*': s = max_expand(ms, s, p, ep) or_return - case '-': s = min_expand(ms, s, p, ep) or_return - case: return match(ms, s + ssize, ep) + case '*': s = max_expand(ms, s, p, ep) or_return + case '-': s = min_expand(ms, s, p, ep) or_return + case: + return match(ms, s + ssize, ep) } } return s, .OK } +@(require_results) push_onecapture :: proc(ms: ^Match_State, i: int, s: int, e: int, matches: []Match) -> (err: Error) { if i >= ms.level { if i == 0 { @@ -533,22 +558,21 @@ push_onecapture :: proc(ms: ^Match_State, i: int, s: int, e: int, matches: []M length := ms.capture[i].len switch length { - case CAP_UNFINISHED: err = .Unfinished_Capture - case CAP_POSITION: matches[i] = { init, init + 1 } - case: matches[i] = { init, init + length } + case CAP_UNFINISHED: + err = .Unfinished_Capture + case CAP_POSITION: + matches[i] = { init, init + 1 } + case: + matches[i] = { init, init + length } } } return } -push_captures :: proc( - ms: ^Match_State, - s: int, - e: int, - matches: []Match, -) -> (nlevels: int, err: Error) { - nlevels = 1 if ms.level == 0 && s != -1 else ms.level +@(require_results) +push_captures :: proc(ms: ^Match_State, s, e: int, matches: []Match) -> (nlevels: int, err: Error) { + nlevels = 1 if ms.level == 0 && s >= 0 else ms.level for i in 0.. int { for i in 0.. int { return -1 } +@(require_results) lmem_find :: proc(s1, s2: string) -> int { l1 := len(s1) l2 := len(s2) if l2 == 0 { return 0 - } else if l2 > l1 { + } + if l2 > l1 { return -1 - } else { - init := strings.index_byte(s1, s2[0]) - end := init + l2 + } - for end <= l1 && init != -1 { - init += 1 + init := strings.index_byte(s1, s2[0]) + end := init + l2 - if s1[init - 1:end] == s2 { - return init - 1 - } else { - next := strings.index_byte(s1[init:], s2[0]) + for end <= l1 && init >= 0 { + init += 1 - if next == -1 { - return -1 - } else { - init = init + next - end = init + l2 - } - } + if s1[init - 1:end] == s2 { + return init - 1 } + next := strings.index_byte(s1[init:], s2[0]) + + if next == -1 { + return -1 + } + init = init + next + end = init + l2 } return -1 @@ -618,36 +644,28 @@ lmem_find :: proc(s1, s2: string) -> int { // find a pattern with in a haystack with an offset // allow_memfind will speed up simple searches -find_aux :: proc( - haystack: string, - pattern: string, - offset: int, - allow_memfind: bool, - matches: ^[MAX_CAPTURES]Match, -) -> (captures: int, err: Error) { +find_aux :: proc(haystack, pattern: string, offset: int, allow_memfind: bool, matches: ^[MAX_CAPTURES]Match) -> (captures: int, err: Error) { s := offset p := 0 specials_idx := index_special(pattern) if allow_memfind && specials_idx == -1 { - if index := lmem_find(haystack[s:], pattern); index != -1 { + if index := lmem_find(haystack[s:], pattern); index >= 0 { matches[0] = { index + s, index + s + len(pattern) } captures = 1 - return - } else { - return } + return } pattern := pattern anchor: bool if len(pattern) > 0 && pattern[0] == '^' { - anchor = true + anchor = true pattern = pattern[1:] } ms := Match_State { - src = haystack, + src = haystack, pattern = pattern, } @@ -684,11 +702,8 @@ find_aux :: proc( // rest has to be used from captures // assumes captures is zeroed on first iteration // resets captures to zero on last iteration -gmatch :: proc( - haystack: ^string, - pattern: string, - captures: ^[MAX_CAPTURES]Match, -) -> (res: string, ok: bool) { +@(require_results) +gmatch :: proc(haystack: ^string, pattern: string, captures: ^[MAX_CAPTURES]Match) -> (res: string, ok: bool) { haystack^ = haystack[captures[0].byte_end:] if len(haystack) > 0 { length, err := find_aux(haystack^, pattern, 0, false, captures) @@ -707,24 +722,17 @@ gmatch :: proc( } // gsub with builder, replace patterns found with the replace content -gsub_builder :: proc( - builder: ^strings.Builder, - haystack: string, - pattern: string, - replace: string, -) -> string { +@(require_results) +gsub_builder :: proc(builder: ^strings.Builder, haystack, pattern, replace: string) -> string { // find matches captures: [MAX_CAPTURES]Match haystack := haystack for { length, err := find_aux(haystack, pattern, 0, false, &captures) - - // done - if length == 0 { + if length == 0 { // done break } - if err != .OK { return {} } @@ -746,21 +754,17 @@ gsub_builder :: proc( } // uses temp builder to build initial string - then allocates the result -gsub_allocator :: proc( - haystack: string, - pattern: string, - replace: string, - allocator := context.allocator, -) -> string { +@(require_results) +gsub_allocator :: proc(haystack, pattern, replace: string, allocator := context.allocator) -> string { builder := strings.builder_make(0, 256, context.temp_allocator) return gsub_builder(&builder, haystack, pattern, replace) } Gsub_Proc :: proc( // optional passed data - data: rawptr, + data: rawptr, // word match found - word: string, + word: string, // current haystack for found captures haystack: string, // found captures - empty for no captures @@ -768,20 +772,14 @@ Gsub_Proc :: proc( ) // call a procedure on every match in the haystack -gsub_with :: proc( - haystack: string, - pattern: string, - data: rawptr, - call: Gsub_Proc, -) { +gsub_with :: proc(haystack, pattern: string, data: rawptr, call: Gsub_Proc) { // find matches captures: [MAX_CAPTURES]Match haystack := haystack for { length := find_aux(haystack, pattern, 0, false, &captures) or_break - // done - if length == 0 { + if length == 0 { // done break } @@ -800,11 +798,8 @@ gsub :: proc { gsub_builder, gsub_allocator } // iterative find with zeroth capture only // assumes captures is zeroed on first iteration // resets captures to zero on last iteration -gfind :: proc( - haystack: ^string, - pattern: string, - captures: ^[MAX_CAPTURES]Match, -) -> (res: string, ok: bool) { +@(require_results) +gfind :: proc(haystack: ^string, pattern: string, captures: ^[MAX_CAPTURES]Match) -> (res: string, ok: bool) { haystack^ = haystack[captures[0].byte_end:] if len(haystack) > 0 { length, err := find_aux(haystack^, pattern, 0, true, captures) @@ -822,10 +817,8 @@ gfind :: proc( } // rebuilds a pattern into a case insensitive pattern -pattern_case_insensitive_builder :: proc( - builder: ^strings.Builder, - pattern: string, -) -> (res: string) { +@(require_results) +pattern_case_insensitive_builder :: proc(builder: ^strings.Builder, pattern: string) -> string { p := pattern last_percent: bool @@ -849,11 +842,8 @@ pattern_case_insensitive_builder :: proc( return strings.to_string(builder^) } -pattern_case_insensitive_allocator :: proc( - pattern: string, - cap: int = 256, - allocator := context.allocator, -) -> (res: string) { +@(require_results) +pattern_case_insensitive_allocator :: proc(pattern: string, cap: int = 256, allocator := context.allocator) -> string { builder := strings.builder_make(0, cap, context.temp_allocator) return pattern_case_insensitive_builder(&builder, pattern) } @@ -877,6 +867,7 @@ Matcher :: struct { } // init using haystack & pattern and an optional byte offset +@(require_results) matcher_init :: proc(haystack, pattern: string, offset: int = 0) -> (res: Matcher) { res.haystack = haystack res.pattern = pattern @@ -886,13 +877,14 @@ matcher_init :: proc(haystack, pattern: string, offset: int = 0) -> (res: Matche } // find the first match and return the byte start / end position in the string, true on success +@(require_results) matcher_find :: proc(matcher: ^Matcher) -> (start, end: int, ok: bool) #no_bounds_check { matcher.captures_length, matcher.err = find_aux( matcher.haystack, matcher.pattern, matcher.offset, - true, - &matcher.captures, + allow_memfind=true, + matches=&matcher.captures, ) ok = matcher.captures_length > 0 && matcher.err == .OK match := matcher.captures[0] @@ -902,13 +894,14 @@ matcher_find :: proc(matcher: ^Matcher) -> (start, end: int, ok: bool) #no_bound } // find the first match and return the matched word, true on success +@(require_results) matcher_match :: proc(matcher: ^Matcher) -> (word: string, ok: bool) #no_bounds_check { matcher.captures_length, matcher.err = find_aux( matcher.haystack, matcher.pattern, matcher.offset, - false, - &matcher.captures, + allow_memfind=false, + matches=&matcher.captures, ) ok = matcher.captures_length > 0 && matcher.err == .OK match := matcher.captures[0] @@ -917,6 +910,7 @@ matcher_match :: proc(matcher: ^Matcher) -> (word: string, ok: bool) #no_bounds_ } // get the capture at the "correct" spot, as spot 0 is reserved for the first match +@(require_results) matcher_capture :: proc(matcher: ^Matcher, index: int, loc := #caller_location) -> string #no_bounds_check { runtime.bounds_check_error_loc(loc, index + 1, MAX_CAPTURES - 1) cap := matcher.captures[index + 1] @@ -924,6 +918,7 @@ matcher_capture :: proc(matcher: ^Matcher, index: int, loc := #caller_location) } // get the raw match out of the captures, skipping spot 0 +@(require_results) matcher_capture_raw :: proc(matcher: ^Matcher, index: int, loc := #caller_location) -> Match #no_bounds_check { runtime.bounds_check_error_loc(loc, index + 1, MAX_CAPTURES - 1) return matcher.captures[index + 1] @@ -933,6 +928,7 @@ matcher_capture_raw :: proc(matcher: ^Matcher, index: int, loc := #caller_locati matcher_gmatch :: matcher_match_iter // iteratively match the haystack till it cant find any matches +@(require_results) matcher_match_iter :: proc(matcher: ^Matcher) -> (res: string, index: int, ok: bool) { if len(matcher.iter) > 0 { matcher.captures_length, matcher.err = find_aux( @@ -962,6 +958,7 @@ matcher_match_iter :: proc(matcher: ^Matcher) -> (res: string, index: int, ok: b } // get a slice of all valid captures above the first match +@(require_results) matcher_captures_slice :: proc(matcher: ^Matcher) -> []Match { return matcher.captures[1:matcher.captures_length] } diff --git a/core/text/regex/common/common.odin b/core/text/regex/common/common.odin index 4a303e0a3..cfbbe53ba 100644 --- a/core/text/regex/common/common.odin +++ b/core/text/regex/common/common.odin @@ -1,9 +1,9 @@ -// This package helps break dependency cycles. +// This package helps break dependency cycles for the regular expression engine. package regex_common /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -14,9 +14,9 @@ MAX_CAPTURE_GROUPS :: max(#config(ODIN_REGEX_MAX_CAPTURE_GROUPS, 10), 10) MAX_PROGRAM_SIZE :: int(max(i16)) MAX_CLASSES :: int(max(u8)) +ODIN_DEBUG_REGEX :: #config(ODIN_DEBUG_REGEX, false) + Flag :: enum u8 { - // Global: try to match the pattern anywhere in the string. - Global, // Multiline: treat `^` and `$` as if they also match newlines. Multiline, // Case Insensitive: treat `a-z` as if it was also `A-Z`. @@ -36,7 +36,6 @@ Flags :: bit_set[Flag; u8] @(rodata) Flag_To_Letter := #sparse[Flag]u8 { - .Global = 'g', .Multiline = 'm', .Case_Insensitive = 'i', .Ignore_Whitespace = 'x', diff --git a/core/text/regex/common/debugging.odin b/core/text/regex/common/debugging.odin index 0e4161a92..055bbd20d 100644 --- a/core/text/regex/common/debugging.odin +++ b/core/text/regex/common/debugging.odin @@ -2,22 +2,15 @@ package regex_common /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. */ -@require import "core:os" import "core:io" import "core:strings" -ODIN_DEBUG_REGEX :: #config(ODIN_DEBUG_REGEX, false) - -when ODIN_DEBUG_REGEX { - debug_stream := os.stream_from_handle(os.stderr) -} - write_padded_hex :: proc(w: io.Writer, #any_int n, zeroes: int) { sb := strings.builder_make() defer strings.builder_destroy(&sb) diff --git a/core/text/regex/common/os.odin b/core/text/regex/common/os.odin new file mode 100644 index 000000000..75d84a5d3 --- /dev/null +++ b/core/text/regex/common/os.odin @@ -0,0 +1,25 @@ +#+build !freestanding +#+build !js +package regex_common + +/* + (c) Copyright 2024 Feoramund . + Made available under Odin's license. + + List of contributors: + Feoramund: Initial implementation. +*/ + +@(require) import "base:runtime" +@(require) import "core:io" +@(require) import "core:os" + +debug_stream: io.Stream + +when ODIN_DEBUG_REGEX { + @(init) + init_debug_stream :: proc "contextless" () { + context = runtime.default_context() + debug_stream = os.to_stream(os.stderr) + } +} \ No newline at end of file diff --git a/core/text/regex/compiler/compiler.odin b/core/text/regex/compiler/compiler.odin index b3ded0104..3b38cc1b8 100644 --- a/core/text/regex/compiler/compiler.odin +++ b/core/text/regex/compiler/compiler.odin @@ -2,7 +2,7 @@ package regex_compiler /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -43,9 +43,16 @@ Node_Match_All_And_Escape :: parser.Node_Match_All_And_Escape Opcode :: virtual_machine.Opcode Program :: [dynamic]Opcode -JUMP_SIZE :: size_of(Opcode) + 1 * size_of(u16) -SPLIT_SIZE :: size_of(Opcode) + 2 * size_of(u16) +Jump :: virtual_machine.Jump +Split :: virtual_machine.Split +Wait_For_Byte :: virtual_machine.Wait_For_Byte +Wait_For_Rune :: virtual_machine.Wait_For_Rune +Wait_For_Rune_Class :: virtual_machine.Wait_For_Rune_Class +Wait_For_Rune_Class_Negated :: virtual_machine.Wait_For_Rune_Class_Negated +Save :: virtual_machine.Save +JUMP_SIZE :: size_of(Jump) +SPLIT_SIZE :: size_of(Split) Compiler :: struct { flags: common.Flags, @@ -141,15 +148,13 @@ map_all_classes :: proc(tree: Node, collection: ^[dynamic]Rune_Class_Data) { append_raw :: #force_inline proc(code: ^Program, data: $T) { // NOTE: This is system-dependent endian. - for b in transmute([size_of(T)]byte)data { - append(code, cast(Opcode)b) - } + data := transmute([size_of(T)]Opcode)data + append(code, ..data[:]) } inject_raw :: #force_inline proc(code: ^Program, start: int, data: $T) { // NOTE: This is system-dependent endian. - for b, i in transmute([size_of(T)]byte)data { - inject_at(code, start + i, cast(Opcode)b) - } + data := transmute([size_of(T)]Opcode)data + inject_at(code, start, ..data[:]) } @require_results @@ -195,8 +200,12 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { case ^Node_Anchor: if .Multiline in c.flags { - append(&code, Opcode.Multiline_Open) - append(&code, Opcode.Multiline_Close) + if specific.start { + append(&code, Opcode.Assert_Start_Multiline) + } else { + append(&code, Opcode.Multiline_Open) + append(&code, Opcode.Multiline_Close) + } } else { if specific.start { append(&code, Opcode.Assert_Start) @@ -216,8 +225,8 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { code = generate_code(c, specific.inner) if specific.capture && .No_Capture not_in c.flags { - inject_at(&code, 0, Opcode.Save) - inject_at(&code, 1, Opcode(2 * specific.capture_id)) + save := Save{.Save, Opcode(2 * specific.capture_id)} + inject_raw(&code, 0, save) append(&code, Opcode.Save) append(&code, Opcode(2 * specific.capture_id + 1)) @@ -232,9 +241,8 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { // Avoiding duplicate allocation by reusing `left`. code = left - inject_at(&code, 0, Opcode.Split) - inject_raw(&code, size_of(byte) , i16(SPLIT_SIZE)) - inject_raw(&code, size_of(byte) + size_of(i16), i16(SPLIT_SIZE + left_len + JUMP_SIZE)) + split := Split{.Split, i16(SPLIT_SIZE), i16(SPLIT_SIZE + left_len + JUMP_SIZE)} + inject_raw(&code, 0, split) append(&code, Opcode.Jump) append_raw(&code, i16(len(right) + JUMP_SIZE)) @@ -255,9 +263,8 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { code = generate_code(c, specific.inner) original_len := len(code) - inject_at(&code, 0, Opcode.Split) - inject_raw(&code, size_of(byte) , i16(SPLIT_SIZE)) - inject_raw(&code, size_of(byte) + size_of(i16), i16(SPLIT_SIZE + original_len + JUMP_SIZE)) + split := Split{.Split, i16(SPLIT_SIZE), i16(SPLIT_SIZE + original_len + JUMP_SIZE)} + inject_raw(&code, 0, split) append(&code, Opcode.Jump) append_raw(&code, i16(-original_len - SPLIT_SIZE)) @@ -266,9 +273,8 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { code = generate_code(c, specific.inner) original_len := len(code) - inject_at(&code, 0, Opcode.Split) - inject_raw(&code, size_of(byte) , i16(SPLIT_SIZE + original_len + JUMP_SIZE)) - inject_raw(&code, size_of(byte) + size_of(i16), i16(SPLIT_SIZE)) + split := Split{.Split, i16(SPLIT_SIZE + original_len + JUMP_SIZE), i16(SPLIT_SIZE)} + inject_raw(&code, 0, split) append(&code, Opcode.Jump) append_raw(&code, i16(-original_len - SPLIT_SIZE)) @@ -355,17 +361,15 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { code = generate_code(c, specific.inner) original_len := len(code) - inject_at(&code, 0, Opcode.Split) - inject_raw(&code, size_of(byte) , i16(SPLIT_SIZE)) - inject_raw(&code, size_of(byte) + size_of(i16), i16(SPLIT_SIZE + original_len)) + split := Split{.Split, i16(SPLIT_SIZE), i16(SPLIT_SIZE + original_len)} + inject_raw(&code, 0, split) case ^Node_Optional_Non_Greedy: code = generate_code(c, specific.inner) original_len := len(code) - inject_at(&code, 0, Opcode.Split) - inject_raw(&code, size_of(byte) , i16(SPLIT_SIZE + original_len)) - inject_raw(&code, size_of(byte) + size_of(i16), i16(SPLIT_SIZE)) + split := Split{.Split, i16(SPLIT_SIZE + original_len), i16(SPLIT_SIZE)} + inject_raw(&code, 0, split) case ^Node_Match_All_And_Escape: append(&code, Opcode.Match_All_And_Escape) @@ -401,70 +405,64 @@ compile :: proc(tree: Node, flags: common.Flags) -> (code: Program, class_data: pc_open := 0 - add_global: if .Global in flags { + optimize_opening: { // Check if the opening to the pattern is predictable. // If so, use one of the optimized Wait opcodes. iter := virtual_machine.Opcode_Iterator{ code[:], 0 } seek_loop: for opcode, pc in virtual_machine.iterate_opcodes(&iter) { #partial switch opcode { case .Byte: - inject_at(&code, pc_open, Opcode.Wait_For_Byte) - pc_open += size_of(Opcode) - inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) - pc_open += size_of(u8) - break add_global + wait := Wait_For_Byte{.Wait_For_Byte, code[pc + size_of(Opcode) + pc_open]} + inject_raw(&code, pc_open, wait) + pc_open += size_of(Wait_For_Byte) + break optimize_opening case .Rune: operand := intrinsics.unaligned_load(cast(^rune)&code[pc+1]) - inject_at(&code, pc_open, Opcode.Wait_For_Rune) - pc_open += size_of(Opcode) - inject_raw(&code, pc_open, operand) - pc_open += size_of(rune) - break add_global + wait := Wait_For_Rune{.Wait_For_Rune, operand} + inject_raw(&code, pc_open, wait) + pc_open += size_of(Wait_For_Rune) + break optimize_opening case .Rune_Class: - inject_at(&code, pc_open, Opcode.Wait_For_Rune_Class) - pc_open += size_of(Opcode) - inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) - pc_open += size_of(u8) - break add_global + wait := Wait_For_Rune_Class{.Wait_For_Rune_Class, code[pc + size_of(Opcode) + pc_open]} + inject_raw(&code, pc_open, wait) + pc_open += size_of(Wait_For_Rune_Class) + break optimize_opening case .Rune_Class_Negated: - inject_at(&code, pc_open, Opcode.Wait_For_Rune_Class_Negated) - pc_open += size_of(Opcode) - inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) - pc_open += size_of(u8) - break add_global + wait := Wait_For_Rune_Class_Negated{.Wait_For_Rune_Class_Negated, code[pc + size_of(Opcode) + pc_open]} + inject_raw(&code, pc_open, wait) + pc_open += size_of(Wait_For_Rune_Class_Negated) + break optimize_opening case .Save: continue + + case .Assert_Start, .Assert_Start_Multiline: + break optimize_opening + case: break seek_loop } } // `.*?` - inject_at(&code, pc_open, Opcode.Split) - pc_open += size_of(byte) - inject_raw(&code, pc_open, i16(SPLIT_SIZE + size_of(byte) + JUMP_SIZE)) - pc_open += size_of(i16) - inject_raw(&code, pc_open, i16(SPLIT_SIZE)) - pc_open += size_of(i16) - - inject_at(&code, pc_open, Opcode.Wildcard) - pc_open += size_of(byte) - - inject_at(&code, pc_open, Opcode.Jump) - pc_open += size_of(byte) - inject_raw(&code, pc_open, i16(-size_of(byte) - SPLIT_SIZE)) - pc_open += size_of(i16) - + split := Split{.Split, i16(SPLIT_SIZE + size_of(byte) + JUMP_SIZE), i16(SPLIT_SIZE)} + jump := Jump{.Jump, i16(-size_of(byte) - SPLIT_SIZE)} + pack := struct { + a: Split, + b: Opcode, + c: Jump, + } { split, Opcode.Wildcard, jump } + inject_raw(&code, pc_open, pack) + pc_open += size_of(Split) + size_of(byte) + size_of(Jump) } if .No_Capture not_in flags { // `(` - inject_at(&code, pc_open, Opcode.Save) - inject_at(&code, pc_open + size_of(byte), Opcode(0x00)) + save := Save{.Save, Opcode(0x00)} + inject_raw(&code, pc_open, save) // `)` append(&code, Opcode.Save); append(&code, Opcode(0x01)) diff --git a/core/text/regex/compiler/debugging.odin b/core/text/regex/compiler/debugging.odin index 142cb8839..864049451 100644 --- a/core/text/regex/compiler/debugging.odin +++ b/core/text/regex/compiler/debugging.odin @@ -2,7 +2,7 @@ package regex_compiler /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/text/regex/compiler/doc.odin b/core/text/regex/compiler/doc.odin index 8c876d837..ec33ae8c9 100644 --- a/core/text/regex/compiler/doc.odin +++ b/core/text/regex/compiler/doc.odin @@ -1,6 +1,5 @@ /* -package regex_compiler implements a bytecode compiler for the virtual machine -included alongside it. +A bytecode compiler for the virtual machine included alongside it. Operands larger than u8 are written in system endian order. diff --git a/core/text/regex/doc.odin b/core/text/regex/doc.odin index 61ab8b80e..ba29659dc 100644 --- a/core/text/regex/doc.odin +++ b/core/text/regex/doc.odin @@ -1,6 +1,5 @@ /* -package regex implements a complete suite for using Regular Expressions to -match and capture text. +A complete suite for using Regular Expressions to match and capture text. Regular expressions are used to describe how a piece of text can match to another, using a pattern language. diff --git a/core/text/regex/optimizer/doc.odin b/core/text/regex/optimizer/doc.odin index 7f2c84c8d..279cbafba 100644 --- a/core/text/regex/optimizer/doc.odin +++ b/core/text/regex/optimizer/doc.odin @@ -1,6 +1,7 @@ /* -package regex_optimizer implements an optimizer which acts upon the AST of a -parsed regular expression pattern, transforming it in-place without moving to a +An optimizer for the regular expression AST. + +Acts upon the AST of a parsed regular expression pattern, transforming it in-place without moving to a compilation step. Where possible, it aims to reduce branching as much as possible in the diff --git a/core/text/regex/optimizer/optimizer.odin b/core/text/regex/optimizer/optimizer.odin index e23cc1bc5..93d7e6eef 100644 --- a/core/text/regex/optimizer/optimizer.odin +++ b/core/text/regex/optimizer/optimizer.odin @@ -2,7 +2,7 @@ package regex_optimizer /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/text/regex/parser/debugging.odin b/core/text/regex/parser/debugging.odin index e060f58c2..f910db796 100644 --- a/core/text/regex/parser/debugging.odin +++ b/core/text/regex/parser/debugging.odin @@ -2,7 +2,7 @@ package regex_parser /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/text/regex/parser/doc.odin b/core/text/regex/parser/doc.odin index f518e518d..1f78a0b99 100644 --- a/core/text/regex/parser/doc.odin +++ b/core/text/regex/parser/doc.odin @@ -1,6 +1,5 @@ /* -package regex_parser implements a Pratt parser, also known as a Top-Down -Operator Precedence parser, for parsing tokenized regular expression patterns. +A `Pratt` parser (a.k.a. Top-Down Operator Precedence parser) for parsing tokenized regular expression patterns. References: - https://dl.acm.org/doi/10.1145/512927.512931 diff --git a/core/text/regex/parser/parser.odin b/core/text/regex/parser/parser.odin index 038d4cb85..38561a077 100644 --- a/core/text/regex/parser/parser.odin +++ b/core/text/regex/parser/parser.odin @@ -2,7 +2,7 @@ package regex_parser /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/text/regex/regex.odin b/core/text/regex/regex.odin index c805740f7..eae95b7e5 100644 --- a/core/text/regex/regex.odin +++ b/core/text/regex/regex.odin @@ -2,7 +2,7 @@ package regex /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -28,8 +28,6 @@ Creation_Error :: enum { Expected_Delimiter, // An unknown letter was supplied to `create_by_user` after the last delimiter. Unknown_Flag, - // An unsupported flag was supplied. - Unsupported_Flag, } Error :: union #shared_nil { @@ -69,7 +67,6 @@ Regular_Expression :: struct { /* An iterator to repeatedly match a pattern against a string, to be used with `*_iterator` procedures. -Note: Does not handle `.Multiline` properly. */ Match_Iterator :: struct { regex: Regular_Expression, @@ -77,6 +74,8 @@ Match_Iterator :: struct { vm: virtual_machine.Machine, idx: int, temp: runtime.Allocator, + threads: int, + done: bool, } /* @@ -101,7 +100,6 @@ create :: proc( permanent_allocator := context.allocator, temporary_allocator := context.temp_allocator, ) -> (result: Regular_Expression, err: Error) { - // For the sake of speed and simplicity, we first run all the intermediate // processes such as parsing and compilation through the temporary // allocator. @@ -166,7 +164,6 @@ to escape the delimiter if found in the middle of the string. All runes after the closing delimiter will be parsed as flags: -- 'g': Global - 'm': Multiline - 'i': Case_Insensitive - 'x': Ignore_Whitespace @@ -243,7 +240,6 @@ create_by_user :: proc( // to `end` here. for r in pattern[start + end:] { switch r { - case 'g': flags += { .Global } case 'm': flags += { .Multiline } case 'i': flags += { .Case_Insensitive } case 'x': flags += { .Ignore_Whitespace } @@ -282,18 +278,13 @@ create_iterator :: proc( permanent_allocator := context.allocator, temporary_allocator := context.temp_allocator, ) -> (result: Match_Iterator, err: Error) { - flags := flags - flags += {.Global} // We're iterating over a string, so the next match could start anywhere - - if .Multiline in flags { - return {}, .Unsupported_Flag - } result.regex = create(pattern, flags, permanent_allocator, temporary_allocator) or_return - result.capture = preallocate_capture() + result.capture = preallocate_capture(permanent_allocator) result.temp = temporary_allocator - result.vm = virtual_machine.create(result.regex.program, str) + result.vm = virtual_machine.create(result.regex.program, str, permanent_allocator) result.vm.class_data = result.regex.class_data + result.threads = max(1, virtual_machine.opcode_count(result.vm.code) - 1) return } @@ -442,7 +433,6 @@ match_with_preallocated_capture :: proc( /* Iterate over a `Match_Iterator` and return successive captures. -Note: Does not handle `.Multiline` properly. Inputs: - it: Pointer to the `Match_Iterator` to iterate over. @@ -457,8 +447,27 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: assert(len(it.capture.pos) >= common.MAX_CAPTURE_GROUPS, "Pre-allocated RegEx capture `pos` must be at least 10 elements long.") + // Guard against situations in which the iterator should finish. + if it.done { + return + } + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + if it.idx > 0 { + // Reset the state needed to `virtual_machine.run` again. + it.vm.top_thread = 0 + it.vm.current_rune = rune(0) + it.vm.current_rune_size = 0 + for i in 0.. (result: Capture, index: int, ok: } } + if !ok { + // Match failed, bail out. + return + } + + if it.vm.string_pointer == sp_before { + // The string pointer did not move, but there was a match. + // + // At this point, the pattern supplied to the iterator will infinitely + // loop if we do not intervene. + it.done = true + } + if it.vm.string_pointer == len(it.vm.memory) { + // The VM hit the end of the string. + // + // We do not check at the start, because a match of pattern `$` + // against string "" is valid and must return a match. + // + // This check prevents a double-match of `$` against a non-empty string. + it.done = true + } + str := string(it.vm.memory) num_groups: int @@ -488,9 +519,7 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: num_groups = n } - defer if ok { - it.idx += 1 - } + defer it.idx += 1 if num_groups > 0 { result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]} @@ -504,8 +533,25 @@ match :: proc { match_iterator, } +/* +Reset an iterator, allowing it to be run again as if new. + +Inputs: +- it: The iterator to reset. +*/ reset :: proc(it: ^Match_Iterator) { - it.idx = 0 + it.done = false + it.idx = 0 + it.vm.string_pointer = 0 + + it.vm.top_thread = 0 + it.vm.current_rune = rune(0) + it.vm.current_rune_size = 0 + it.vm.last_rune = rune(0) + for i in 0... - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. diff --git a/core/text/regex/virtual_machine/doc.odin b/core/text/regex/virtual_machine/doc.odin index 1b0694565..ba7441399 100644 --- a/core/text/regex/virtual_machine/doc.odin +++ b/core/text/regex/virtual_machine/doc.odin @@ -1,7 +1,6 @@ /* -package regex_vm implements a threaded virtual machine for interpreting -regular expressions, based on the designs described by Russ Cox and attributed -to both Ken Thompson and Rob Pike. +A threaded virtual machine for interpreting regular expressions. +Based on the designs described by Russ Cox and attributed to both Ken Thompson and Rob Pike. The virtual machine executes all threads in lock step, i.e. the string pointer does not advance until all threads have finished processing the current rune. @@ -109,34 +108,42 @@ For more information, see: https://swtch.com/~rsc/regexp/regexp2.html (0x0A) Assert_Start - Asserts that the thread is at the beginning of a string. + Asserts that the thread is at the beginning of the string. - (0x0B) Assert_End + (0x0B) Assert_Start_Multiline - Asserts that the thread is at the end of a string. + This opcode is compiled in only when the `Multiline` flag is present as a + replacement for the `^` text anchor. - (0x0C) Assert_Word_Boundary + Asserts that the thread is at the beginning of the string or previously + parsed either a "\n" or "\r". + + (0x0C) Assert_End + + Asserts that the thread is at the end of the string. + + (0x0D) Assert_Word_Boundary Asserts that the thread is on a word boundary, which can be the start or end of the text. This examines both the current rune and the next rune. - (0x0D) Assert_Non_Word_Boundary + (0x0E) Assert_Non_Word_Boundary A modified version of Assert_Word_Boundary that returns the opposite value. - (0x0E) Multiline_Open + (0x0F) Multiline_Open - This opcode is compiled in only when the `Multiline` flag is present, and - it replaces both `^` and `$` text anchors. + This opcode is compiled in only when the `Multiline` flag is present as a + replacement for the `$` text anchor. - It asserts that either the current thread is on one of the string - boundaries, or it consumes a `\n` or `\r` character. + It asserts that either the current thread is at the end of the string, + or it consumes a `\n` or `\r` character. If a `\r` character is consumed, the PC will be advanced to the sibling `Multiline_Close` opcode to optionally consume a `\n` character on the next frame. - (0x0F) Multiline_Close + (0x10) Multiline_Close This opcode is always present after `Multiline_Open`. @@ -144,10 +151,10 @@ For more information, see: https://swtch.com/~rsc/regexp/regexp2.html For example, Windows newlines are represented by the characters `\r\n`, whereas UNIX newlines are `\n` and Macintosh newlines are `\r`. - (0x10) Wait_For_Byte - (0x11) Wait_For_Rune - (0x12) Wait_For_Rune_Class - (0x13) Wait_For_Rune_Class_Negated + (0x11) Wait_For_Byte + (0x12) Wait_For_Rune + (0x13) Wait_For_Rune_Class + (0x14) Wait_For_Rune_Class_Negated These opcodes are an optimization around restarting threads on failed matches when the beginning to a pattern is predictable and the Global flag @@ -156,7 +163,7 @@ For more information, see: https://swtch.com/~rsc/regexp/regexp2.html They will cause the VM to wait for the next rune to match before splitting, as would happen in the un-optimized version. - (0x14) Match_All_And_Escape + (0x15) Match_All_And_Escape This opcode is an optimized version of `.*$` or `.+$` that causes the active thread to immediately work on escaping the program by following all diff --git a/core/text/regex/virtual_machine/util.odin b/core/text/regex/virtual_machine/util.odin index fa94a139f..3809ca98a 100644 --- a/core/text/regex/virtual_machine/util.odin +++ b/core/text/regex/virtual_machine/util.odin @@ -2,7 +2,7 @@ package regex_vm /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -34,6 +34,7 @@ iterate_opcodes :: proc(iter: ^Opcode_Iterator) -> (opcode: Opcode, pc: int, ok: case .Split: iter.pc += size_of(Opcode) + 2 * size_of(u16) case .Save: iter.pc += size_of(Opcode) + size_of(u8) case .Assert_Start: iter.pc += size_of(Opcode) + case .Assert_Start_Multiline: iter.pc += size_of(Opcode) case .Assert_End: iter.pc += size_of(Opcode) case .Assert_Word_Boundary: iter.pc += size_of(Opcode) case .Assert_Non_Word_Boundary: iter.pc += size_of(Opcode) @@ -64,6 +65,7 @@ opcode_to_name :: proc(opcode: Opcode) -> (str: string) { case .Split: str = "Split" case .Save: str = "Save" case .Assert_Start: str = "Assert_Start" + case .Assert_Start_Multiline: str = "Assert_Start_Multiline" case .Assert_End: str = "Assert_End" case .Assert_Word_Boundary: str = "Assert_Word_Boundary" case .Assert_Non_Word_Boundary: str = "Assert_Non_Word_Boundary" diff --git a/core/text/regex/virtual_machine/virtual_machine.odin b/core/text/regex/virtual_machine/virtual_machine.odin index ab1dfbec1..3751e0974 100644 --- a/core/text/regex/virtual_machine/virtual_machine.odin +++ b/core/text/regex/virtual_machine/virtual_machine.odin @@ -2,7 +2,7 @@ package regex_vm /* (c) Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Feoramund: Initial implementation. @@ -37,16 +37,46 @@ Opcode :: enum u8 { Split = 0x08, // | u16, u16 Save = 0x09, // | u8 Assert_Start = 0x0A, // | - Assert_End = 0x0B, // | - Assert_Word_Boundary = 0x0C, // | - Assert_Non_Word_Boundary = 0x0D, // | - Multiline_Open = 0x0E, // | - Multiline_Close = 0x0F, // | - Wait_For_Byte = 0x10, // | u8 - Wait_For_Rune = 0x11, // | i32 - Wait_For_Rune_Class = 0x12, // | u8 - Wait_For_Rune_Class_Negated = 0x13, // | u8 - Match_All_And_Escape = 0x14, // | + Assert_Start_Multiline = 0x0B, // | + Assert_End = 0x0C, // | + Assert_Word_Boundary = 0x0D, // | + Assert_Non_Word_Boundary = 0x0E, // | + Multiline_Open = 0x0F, // | + Multiline_Close = 0x10, // | + Wait_For_Byte = 0x11, // | u8 + Wait_For_Rune = 0x12, // | i32 + Wait_For_Rune_Class = 0x13, // | u8 + Wait_For_Rune_Class_Negated = 0x14, // | u8 + Match_All_And_Escape = 0x15, // | +} +Jump :: struct #packed { + opcode: Opcode, + target: i16, +} +Split :: struct #packed { + opcode: Opcode, + left: i16, + right: i16, +} +Wait_For_Byte :: struct #packed { + opcode: Opcode, + operand: Opcode, +} +Wait_For_Rune :: struct #packed { + opcode: Opcode, + operand: rune, +} +Wait_For_Rune_Class :: struct #packed { + opcode: Opcode, + operand: Opcode, +} +Wait_For_Rune_Class_Negated :: struct #packed { + opcode: Opcode, + operand: Opcode, +} +Save :: struct #packed { + opcode: Opcode, + operand: Opcode, } Thread :: struct { @@ -77,6 +107,8 @@ Machine :: struct { current_rune_size: int, next_rune: rune, next_rune_size: int, + + last_rune: rune, } @@ -169,6 +201,12 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: pc += size_of(Opcode) continue } + case .Assert_Start_Multiline: + sp := vm.string_pointer+vm.current_rune_size + if sp == 0 || vm.last_rune == '\n' || vm.last_rune == '\r' { + pc += size_of(Opcode) + continue + } case .Assert_End: sp := vm.string_pointer+vm.current_rune_size if sp == len(vm.memory) { @@ -177,24 +215,12 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: } case .Multiline_Open: sp := vm.string_pointer+vm.current_rune_size - if sp == 0 || sp == len(vm.memory) { - if vm.next_rune == '\r' || vm.next_rune == '\n' { - // The VM is currently on a newline at the string boundary, - // so consume the newline next frame. - when common.ODIN_DEBUG_REGEX { - io.write_string(common.debug_stream, "*** New thread added [PC:") - common.write_padded_hex(common.debug_stream, pc, 4) - io.write_string(common.debug_stream, "]\n") - } - vm.next_threads[vm.top_thread] = Thread{ pc = pc, saved = saved } - vm.top_thread += 1 - } else { - // Skip the `Multiline_Close` opcode. - pc += 2 * size_of(Opcode) - continue - } + if sp == len(vm.memory) { + // Skip the `Multiline_Close` opcode. + pc += 2 * size_of(Opcode) + continue } else { - // Not on a string boundary. + // Not at the end of the string. // Try to consume a newline next frame in the other opcode loop. when common.ODIN_DEBUG_REGEX { io.write_string(common.debug_stream, "*** New thread added [PC:") @@ -206,28 +232,24 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: } case .Assert_Word_Boundary: sp := vm.string_pointer+vm.current_rune_size - if sp == 0 || sp == len(vm.memory) { + + left_is_wc := sp > 0 && is_word_class(vm.current_rune) + right_is_wc := sp < len(vm.memory) && is_word_class(vm.next_rune) + + if left_is_wc != right_is_wc { pc += size_of(Opcode) continue - } else { - last_rune_is_wc := is_word_class(vm.current_rune) - this_rune_is_wc := is_word_class(vm.next_rune) - - if last_rune_is_wc && !this_rune_is_wc || !last_rune_is_wc && this_rune_is_wc { - pc += size_of(Opcode) - continue - } } + case .Assert_Non_Word_Boundary: sp := vm.string_pointer+vm.current_rune_size - if sp != 0 && sp != len(vm.memory) { - last_rune_is_wc := is_word_class(vm.current_rune) - this_rune_is_wc := is_word_class(vm.next_rune) - if last_rune_is_wc && this_rune_is_wc || !last_rune_is_wc && !this_rune_is_wc { - pc += size_of(Opcode) - continue - } + left_is_wc := sp > 0 && is_word_class(vm.current_rune) + right_is_wc := sp < len(vm.memory) && is_word_class(vm.next_rune) + + if left_is_wc == right_is_wc { + pc += size_of(Opcode) + continue } case .Wait_For_Byte: @@ -329,10 +351,10 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: run :: proc(vm: ^Machine, $UNICODE_MODE: bool) -> (saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, ok: bool) #no_bounds_check { when UNICODE_MODE { - vm.next_rune, vm.next_rune_size = utf8.decode_rune_in_string(vm.memory) + vm.next_rune, vm.next_rune_size = utf8.decode_rune_in_string(vm.memory[vm.string_pointer:]) } else { if len(vm.memory) > 0 { - vm.next_rune = cast(rune)vm.memory[0] + vm.next_rune = cast(rune)vm.memory[vm.string_pointer] vm.next_rune_size = 1 } } @@ -613,6 +635,7 @@ run :: proc(vm: ^Machine, $UNICODE_MODE: bool) -> (saved: ^[2 * common.MAX_CAPTU break } + vm.last_rune = vm.current_rune vm.string_pointer += vm.current_rune_size } @@ -652,4 +675,4 @@ destroy :: proc(vm: Machine, allocator := context.allocator) { delete(vm.busy_map) free(vm.threads) free(vm.next_threads) -} \ No newline at end of file +} diff --git a/core/text/scanner/scanner.odin b/core/text/scanner/scanner.odin index 24dbcc8a4..9445df58c 100644 --- a/core/text/scanner/scanner.odin +++ b/core/text/scanner/scanner.odin @@ -1,4 +1,4 @@ -// package text/scanner provides a scanner and tokenizer for UTF-8-encoded text. +// A scanner and tokenizer for UTF-8-encoded text. // It takes a string providing the source, which then can be tokenized through // repeated calls to the scan procedure. // For compatibility with existing tooling and languages, the NUL character is not allowed. @@ -285,6 +285,7 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { case 'o': return "octal literal" case 'z': return "dozenal literal" case 'x': return "hexadecimal literal" + case 'h': return "hexadecimal literal" } return "decimal literal" } @@ -340,8 +341,10 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { case 'x': ch = advance(s) base, prefix = 16, 'x' - case: + case 'o': + ch = advance(s) base, prefix = 8, 'o' + case: digsep = 1 // Leading zero } } else { @@ -360,7 +363,8 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { base, prefix = 12, 'z' case 'h': tok = Float - fallthrough + ch = advance(s) + base, prefix = 16, 'h' case 'x': ch = advance(s) base, prefix = 16, 'x' @@ -447,7 +451,7 @@ scan_string :: proc(s: ^Scanner, quote: rune) -> (n: int) { ch := advance(s) for ch != quote { if ch == '\n' || ch < 0 { - error(s, "literal no terminated") + error(s, "literal not terminated") return } if ch == '\\' { diff --git a/core/text/table/doc.odin b/core/text/table/doc.odin index 63275bbc1..d91763661 100644 --- a/core/text/table/doc.odin +++ b/core/text/table/doc.odin @@ -1,5 +1,5 @@ /* -The package `table` implements plain-text/markdown/HTML/custom rendering of tables. +Plain-text/markdown/HTML/custom rendering of tables. **Custom rendering.** Example: @@ -195,6 +195,7 @@ Example: scripts :: proc(w: io.Writer) { t: table.Table table.init(&t) + defer table.destroy(&t) table.caption(&t, "Tést Suite") table.padding(&t, 1, 3) table.header_of_aligned_values(&t, {{.Left, "Script"}, {.Center, "Sample"}}) @@ -224,9 +225,7 @@ Example: } main :: proc() { - stdout := os.stream_from_handle(os.stdout) - - scripts(stdout) + scripts(os.to_stream(os.stdout)) } Output: @@ -274,6 +273,7 @@ Example: box_drawing :: proc(w: io.Writer) { t: table.Table table.init(&t) + defer table.destroy(&t) table.caption(&t, "Box Drawing Example") table.padding(&t, 2, 2) table.header_of_aligned_values(&t, {{.Left, "Operating System"}, {.Center, "Year Introduced"}}) @@ -299,9 +299,7 @@ Example: } main :: proc() { - stdout := os.stream_from_handle(os.stdout) - - box_drawing(stdout) + box_drawing(os.to_stream(os.stdout)) } While the decorations support multi-codepoint Unicode graphemes, do note that diff --git a/core/text/table/table.odin b/core/text/table/table.odin index 66a7d442b..204263e54 100644 --- a/core/text/table/table.odin +++ b/core/text/table/table.odin @@ -1,6 +1,6 @@ /* Copyright 2023 oskarnp - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: oskarnp: Initial implementation. diff --git a/core/text/table/utility.odin b/core/text/table/utility.odin index 0e56fd968..675fa6b10 100644 --- a/core/text/table/utility.odin +++ b/core/text/table/utility.odin @@ -1,3 +1,5 @@ +#+build !freestanding +#+build !js package text_table import "core:io" @@ -5,7 +7,7 @@ import "core:os" import "core:strings" stdio_writer :: proc() -> io.Writer { - return io.to_writer(os.stream_from_handle(os.stdout)) + return os.to_stream(os.stdout) } strings_builder_writer :: proc(b: ^strings.Builder) -> io.Writer { diff --git a/core/thread/thread.odin b/core/thread/thread.odin index c7fd082ac..a07801b98 100644 --- a/core/thread/thread.odin +++ b/core/thread/thread.odin @@ -1,10 +1,14 @@ +// Multi-threading operations to spawn threads and thread pools. package thread import "base:runtime" import "core:mem" import "base:intrinsics" -_ :: intrinsics +@(private) +unall :: intrinsics.unaligned_load +@(private) +unals :: intrinsics.unaligned_store /* Value, specifying whether `core:thread` functionality is available on the @@ -39,7 +43,8 @@ Type representing a thread handle and the associated with that thread data. Thread :: struct { using specific: Thread_Os_Specific, flags: bit_set[Thread_State; u8], - // Thread ID. + // Thread ID. Depending on the platform, may start out as 0 (zero) until the thread + // has had a chance to run. id: int, // The thread procedure. procedure: Thread_Proc, @@ -257,8 +262,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` @@ -290,8 +297,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` @@ -327,8 +336,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` @@ -339,7 +350,9 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex thread_proc :: proc(t: ^Thread) { fn := cast(proc(T))t.data assert(t.user_index >= 1) - data := (^T)(&t.user_args[0])^ + + data := unall((^T)(&t.user_args)) + fn(data) } if t = create(thread_proc, priority); t == nil { @@ -348,9 +361,7 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex t.data = rawptr(fn) t.user_index = 1 - data := data - - mem.copy(&t.user_args[0], &data, size_of(T)) + unals((^T)(&t.user_args), data) if self_cleanup { intrinsics.atomic_or(&t.flags, {.Self_Cleanup}) @@ -370,8 +381,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` @@ -383,9 +396,10 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), fn := cast(proc(T1, T2))t.data assert(t.user_index >= 2) - user_args := mem.slice_to_bytes(t.user_args[:]) - arg1 := (^T1)(raw_data(user_args))^ - arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^ + ptr := uintptr(&t.user_args) + + arg1 := unall((^T1)(rawptr(ptr))) + arg2 := unall((^T2)(rawptr(ptr + size_of(T1)))) fn(arg1, arg2) } @@ -395,11 +409,10 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), t.data = rawptr(fn) t.user_index = 2 - arg1, arg2 := arg1, arg2 - user_args := mem.slice_to_bytes(t.user_args[:]) + ptr := uintptr(&t.user_args) - n := copy(user_args, mem.ptr_to_bytes(&arg1)) - _ = copy(user_args[n:], mem.ptr_to_bytes(&arg2)) + unals((^T1)(rawptr(ptr)), arg1) + unals((^T2)(rawptr(ptr + size_of(T1))), arg2) if self_cleanup { intrinsics.atomic_or(&t.flags, {.Self_Cleanup}) @@ -419,8 +432,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` @@ -432,10 +447,11 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr fn := cast(proc(T1, T2, T3))t.data assert(t.user_index >= 3) - user_args := mem.slice_to_bytes(t.user_args[:]) - arg1 := (^T1)(raw_data(user_args))^ - arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^ - arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^ + ptr := uintptr(&t.user_args) + + arg1 := unall((^T1)(rawptr(ptr))) + arg2 := unall((^T2)(rawptr(ptr + size_of(T1)))) + arg3 := unall((^T3)(rawptr(ptr + size_of(T1) + size_of(T2)))) fn(arg1, arg2, arg3) } @@ -445,12 +461,11 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr t.data = rawptr(fn) t.user_index = 3 - arg1, arg2, arg3 := arg1, arg2, arg3 - user_args := mem.slice_to_bytes(t.user_args[:]) + ptr := uintptr(&t.user_args) - n := copy(user_args, mem.ptr_to_bytes(&arg1)) - n += copy(user_args[n:], mem.ptr_to_bytes(&arg2)) - _ = copy(user_args[n:], mem.ptr_to_bytes(&arg3)) + unals((^T1)(rawptr(ptr)), arg1) + unals((^T2)(rawptr(ptr + size_of(T1))), arg2) + unals((^T3)(rawptr(ptr + size_of(T1) + size_of(T2))), arg3) if self_cleanup { intrinsics.atomic_or(&t.flags, {.Self_Cleanup}) @@ -470,8 +485,10 @@ to execute. The thread will have priority specified by the `priority` parameter. If `self_cleanup` is specified, after the thread finishes the execution of the `fn` procedure, the resources associated with the thread are going to be -automatically freed. **Do not** dereference the `^Thread` pointer, if this -flag is specified. +automatically freed. + +**Do not** dereference the `^Thread` pointer, if this flag is specified. +That includes calling `join`, which needs to dereference ^Thread`. **IMPORTANT**: If `init_context` is specified and the default temporary allocator is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()` diff --git a/core/thread/thread_other.odin b/core/thread/thread_other.odin index dde2a8e48..878119cbd 100644 --- a/core/thread/thread_other.odin +++ b/core/thread/thread_other.odin @@ -37,7 +37,7 @@ _destroy :: proc(thread: ^Thread) { unimplemented("core:thread procedure not supported on target") } -_terminate :: proc(using thread : ^Thread, exit_code: int) { +_terminate :: proc(thread : ^Thread, exit_code: int) { unimplemented("core:thread procedure not supported on target") } diff --git a/core/thread/thread_pool.odin b/core/thread/thread_pool.odin index 59bf90620..10f1438d7 100644 --- a/core/thread/thread_pool.odin +++ b/core/thread/thread_pool.odin @@ -3,7 +3,7 @@ package thread /* thread.Pool Copyright 2022 eisbehr - Made available under Odin's BSD-3 license. + Made available under Odin's license. */ import "base:intrinsics" @@ -20,6 +20,9 @@ Task :: struct { allocator: mem.Allocator, } +Thread_Init_Proc :: #type proc(thread: ^Thread, user_data: rawptr) +Thread_Fini_Proc :: #type proc(thread: ^Thread, user_data: rawptr) + // Do not access the pool's members directly while the pool threads are running, // since they use different kinds of locking and mutual exclusion devices. // Careless access can and will lead to nasty bugs. Once initialized, the @@ -36,6 +39,13 @@ Pool :: struct { num_done: int, // end of atomics + // called once per thread at startup + thread_init_proc: Thread_Init_Proc, + thread_init_data: rawptr, + // called once per thread at shutdown + thread_fini_proc: Thread_Fini_Proc, + thread_fini_data: rawptr, + is_running: bool, threads: []^Thread, @@ -55,6 +65,10 @@ pool_thread_runner :: proc(t: ^Thread) { data := cast(^Pool_Thread_Data)t.data pool := data.pool + if pool.thread_init_proc != nil { + pool.thread_init_proc(t, pool.thread_init_data) + } + for intrinsics.atomic_load(&pool.is_running) { sync.wait(&pool.sem_available) @@ -66,6 +80,10 @@ pool_thread_runner :: proc(t: ^Thread) { } } + if pool.thread_fini_proc != nil { + pool.thread_fini_proc(t, pool.thread_fini_data) + } + sync.post(&pool.sem_available, 1) } @@ -73,13 +91,26 @@ pool_thread_runner :: proc(t: ^Thread) { // it is destroyed. // // The thread pool requires an allocator which it either owns, or which is thread safe. -pool_init :: proc(pool: ^Pool, allocator: mem.Allocator, thread_count: int) { +pool_init :: proc( + pool: ^Pool, + allocator: mem.Allocator, + thread_count: int, + init_proc: Thread_Init_Proc = nil, + init_data: rawptr = nil, + fini_proc: Thread_Init_Proc = nil, + fini_data: rawptr = nil, +){ context.allocator = allocator pool.allocator = allocator queue.init(&pool.tasks) pool.tasks_done = make([dynamic]Task) pool.threads = make([]^Thread, max(thread_count, 1)) + pool.thread_init_proc = init_proc + pool.thread_fini_proc = fini_proc + pool.thread_init_data = init_data + pool.thread_fini_data = fini_data + pool.is_running = true for _, i in pool.threads { @@ -120,6 +151,20 @@ pool_join :: proc(pool: ^Pool) { yield() + unstarted_count: int + for t in pool.threads { + flags := intrinsics.atomic_load(&t.flags) + if .Started not_in flags { + unstarted_count += 1 + } + } + + // most likely the user forgot to call `pool_start` + // exit here, so we don't hang forever + if len(pool.threads) == unstarted_count { + return + } + started_count: int for started_count < len(pool.threads) { started_count = 0 diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index ff79cfcbc..02e628df5 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd #+private package thread @@ -22,32 +22,21 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { __unix_thread_entry_proc :: proc "c" (t: rawptr) -> rawptr { t := (^Thread)(t) - // We need to give the thread a moment to start up before we enable cancellation. - // NOTE(laytan): setting to .DISABLE on darwin, with .ENABLE pthread_cancel would deadlock - // most of the time, don't ask me why. - can_set_thread_cancel_state := posix.pthread_setcancelstate(.DISABLE when ODIN_OS == .Darwin else .ENABLE, nil) == nil - t.id = sync.current_thread_id() - if .Started not_in sync.atomic_load(&t.flags) { + for (.Started not_in sync.atomic_load(&t.flags)) { sync.wait(&t.start_ok) } - if .Joined in sync.atomic_load(&t.flags) { - return nil - } - // Enable thread's cancelability. - // NOTE(laytan): Darwin does not correctly/fully support all of this, not doing this does - // actually make pthread_cancel work in the capacity of my tests, while executing this would - // basically always make it deadlock. - if ODIN_OS != .Darwin && can_set_thread_cancel_state { - err := posix.pthread_setcancelstate(.ENABLE, nil) - assert_contextless(err == nil) + err := posix.pthread_setcancelstate(.ENABLE, nil) + assert_contextless(err == nil) - err = posix.pthread_setcanceltype(.ASYNCHRONOUS, nil) - assert_contextless(err == nil) - } + // NOTE(laytan): .ASYNCHRONOUS should make `pthread_cancel` cancel immediately + // instead of waiting for a cancellation point. + // This does not seem to work on at least Darwin and NetBSD though. + err = posix.pthread_setcanceltype(.ASYNCHRONOUS, nil) + assert_contextless(err == nil) { init_context := t.init_context @@ -85,11 +74,16 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { } defer posix.pthread_attr_destroy(&attrs) - // NOTE(tetra, 2019-11-01): These only fail if their argument is invalid. + stacksize: posix.rlimit + if res := posix.getrlimit(.STACK, &stacksize); res == .OK && stacksize.rlim_cur > 0 { + _ = posix.pthread_attr_setstacksize(&attrs, uint(stacksize.rlim_cur)) + } + res: posix.Errno + // NOTE(tetra, 2019-11-01): These only fail if their argument is invalid. res = posix.pthread_attr_setdetachstate(&attrs, .CREATE_JOINABLE) assert(res == nil) - when ODIN_OS != .Haiku && ODIN_OS != .NetBSD { + when ODIN_OS != .NetBSD { res = posix.pthread_attr_setinheritsched(&attrs, .EXPLICIT_SCHED) assert(res == nil) } @@ -102,7 +96,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { // Set thread priority. policy: posix.Sched_Policy - when ODIN_OS != .Haiku && ODIN_OS != .NetBSD { + when ODIN_OS != .NetBSD { res = posix.pthread_attr_getschedpolicy(&attrs, &policy) assert(res == nil) } @@ -113,7 +107,11 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { high := posix.sched_get_priority_max(policy) switch priority { case .Normal: // Okay - case .Low: params.sched_priority = low + 1 + case .Low: + params.sched_priority = low + 1 + if params.sched_priority >= high { + params.sched_priority = low + } case .High: params.sched_priority = high } res = posix.pthread_attr_setschedparam(&attrs, ¶ms) @@ -124,7 +122,6 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { free(thread, thread.creation_allocator) return nil } - return thread } @@ -149,10 +146,13 @@ _join :: proc(t: ^Thread) { // Prevent non-started threads from blocking main thread with initial wait // condition. - if .Started not_in sync.atomic_load(&t.flags) { + for (.Started not_in sync.atomic_load(&t.flags)) { _start(t) } + posix.pthread_join(t.unix_thread, nil) + + t.flags += {.Joined} } _join_multiple :: proc(threads: ..^Thread) { diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index cc73a2d6a..358e3e7f1 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -13,6 +13,7 @@ Thread_Os_Specific :: struct { win32_thread: win32.HANDLE, win32_thread_id: win32.DWORD, mutex: sync.Mutex, + start_ok: sync.Sema, } _thread_priority_map := [Thread_Priority]i32{ @@ -27,12 +28,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { __windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD { t := (^Thread)(t_) - if .Joined in sync.atomic_load(&t.flags) { - return 0 + for (.Started not_in sync.atomic_load(&t.flags)) { + sync.wait(&t.start_ok) } - t.id = sync.current_thread_id() - { init_context := t.init_context @@ -76,6 +75,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { thread.procedure = procedure thread.win32_thread = win32_thread thread.win32_thread_id = win32_thread_id + thread.id = int(win32_thread_id) ok := win32.SetThreadPriority(win32_thread, _thread_priority_map[priority]) assert(ok == true) @@ -103,16 +103,15 @@ _join :: proc(t: ^Thread) { return } - t.flags += {.Joined} - - if .Started not_in t.flags { - t.flags += {.Started} - win32.ResumeThread(t.win32_thread) + for (.Started not_in sync.atomic_load(&t.flags)) { + _start(t) } win32.WaitForSingleObject(t.win32_thread, win32.INFINITE) win32.CloseHandle(t.win32_thread) t.win32_thread = win32.INVALID_HANDLE + + t.flags += {.Joined} } _join_multiple :: proc(threads: ..^Thread) { @@ -136,6 +135,7 @@ _join_multiple :: proc(threads: ..^Thread) { for t in threads { win32.CloseHandle(t.win32_thread) t.win32_thread = win32.INVALID_HANDLE + t.flags += {.Joined} } } diff --git a/core/time/iso8601.odin b/core/time/iso8601.odin index f00107226..e2341f76d 100644 --- a/core/time/iso8601.odin +++ b/core/time/iso8601.odin @@ -27,6 +27,7 @@ is specified in the string, that timezone is applied to time. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) iso8601_to_time_utc :: proc(iso_datetime: string, is_leap: ^bool = nil) -> (res: Time, consumed: int) { offset: int res, offset, consumed = iso8601_to_time_and_offset(iso_datetime, is_leap) @@ -59,6 +60,7 @@ minutes. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) iso8601_to_time_and_offset :: proc(iso_datetime: string, is_leap: ^bool = nil) -> (res: Time, utc_offset: int, consumed: int) { moment, offset, leap_second, count := iso8601_to_components(iso_datetime) if count == 0 { @@ -102,6 +104,7 @@ minutes. e.g. it'll return hour = 25 if that's what it's given in the specified string. */ +@(require_results) iso8601_to_components :: proc(iso_datetime: string) -> (res: dt.DateTime, utc_offset: int, is_leap: bool, consumed: int) { moment, offset, count, leap_second, ok := _iso8601_to_components(iso_datetime) if !ok { diff --git a/core/time/perf.odin b/core/time/perf.odin index 265a20edf..2db1f4034 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -13,6 +13,7 @@ Tick :: struct { /* Obtain the current tick. */ +@(require_results) tick_now :: proc "contextless" () -> Tick { return _tick_now() } @@ -20,6 +21,7 @@ tick_now :: proc "contextless" () -> Tick { /* Add duration to a tick. */ +@(require_results) tick_add :: proc "contextless" (t: Tick, d: Duration) -> Tick { return Tick{t._nsec + i64(d)} } @@ -27,6 +29,7 @@ tick_add :: proc "contextless" (t: Tick, d: Duration) -> Tick { /* Obtain the difference between ticks. */ +@(require_results) tick_diff :: proc "contextless" (start, end: Tick) -> Duration { d := end._nsec - start._nsec return Duration(d) @@ -43,6 +46,7 @@ then the returned duration is 0. This procedure is meant to be used in a loop, or in other scenarios, where one might want to obtain time between multiple ticks at specific points. */ +@(require_results) tick_lap_time :: proc "contextless" (prev: ^Tick) -> Duration { d: Duration t := tick_now() @@ -56,6 +60,7 @@ tick_lap_time :: proc "contextless" (prev: ^Tick) -> Duration { /* Obtain the duration since last tick. */ +@(require_results) tick_since :: proc "contextless" (start: Tick) -> Duration { return tick_diff(start, tick_now()) } @@ -101,9 +106,12 @@ This procedure checks if the CPU contains an invariant TSC (Time stamp counter). Invariant TSC is a feature of modern processors that allows them to run their TSC at a fixed frequency, independent of ACPI state, and CPU frequency. */ +@(require_results) has_invariant_tsc :: proc "contextless" () -> bool { when ODIN_ARCH == .amd64 { return x86_has_invariant_tsc() + } else when ODIN_ARCH == .arm64 { + return true } return false @@ -120,6 +128,7 @@ dividing the readings from TSC by the duration of the sleep. The duration of sleep can be controlled by `fallback_sleep` parameter. */ +@(require_results) tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) { if !has_invariant_tsc() { return 0, false @@ -185,6 +194,8 @@ Benchmark_Options :: struct { // `benchmark()` procedure will output the average number of megabytes // processed per second, using the `processed` field of this struct. megabytes_per_second: f64, + // For user specified data in the callbacks + user_data: rawptr, } /* diff --git a/core/time/rfc3339.odin b/core/time/rfc3339.odin index 20e8ea0bb..3e0bab916 100644 --- a/core/time/rfc3339.odin +++ b/core/time/rfc3339.odin @@ -31,6 +31,7 @@ offset applied to it. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) rfc3339_to_time_utc :: proc(rfc_datetime: string, is_leap: ^bool = nil) -> (res: Time, consumed: int) { offset: int @@ -67,6 +68,7 @@ by the RFC 3339 string. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) rfc3339_to_time_and_offset :: proc(rfc_datetime: string, is_leap: ^bool = nil) -> (res: Time, utc_offset: int, consumed: int) { moment, offset, leap_second, count := rfc3339_to_components(rfc_datetime) if count == 0 { @@ -109,6 +111,7 @@ represented by the RFC 3339 string. Performs no validation on whether components are valid, e.g. it'll return hour = 25 if that's what it's given */ +@(require_results) rfc3339_to_components :: proc(rfc_datetime: string) -> (res: dt.DateTime, utc_offset: int, is_leap: bool, consumed: int) { moment, offset, count, leap_second, ok := _rfc3339_to_components(rfc_datetime) if !ok { @@ -198,6 +201,7 @@ The boolean `ok` is false if the `time` is not a valid datetime, or if allocatin - `utc_offset`: offset in minutes wrt UTC (ie. the timezone) - `include_nanos`: whether to include nanoseconds in the result. */ +@(require_results) time_to_rfc3339 :: proc(time: Time, utc_offset : int = 0, include_nanos := true, allocator := context.allocator) -> (res: string, ok: bool) { utc_offset := utc_offset diff --git a/core/time/time.odin b/core/time/time.odin index b488f951c..438d74569 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -1,3 +1,4 @@ +// `Time`-related procedures and types, including `sleep`, `now`, and string formatting of moments. package time import "base:intrinsics" @@ -115,6 +116,7 @@ Stopwatch :: struct { /* Obtain the current time. */ +@(require_results) now :: proc "contextless" () -> Time { return _now() } @@ -161,6 +163,7 @@ This procedure obtains the total time, counted by the stopwatch. If the stopwatc isn't stopped at the time of calling this procedure, the time between the last start and the current time is also accounted for. */ +@(require_results) stopwatch_duration :: proc "contextless" (stopwatch: Stopwatch) -> Duration { if !stopwatch.running { return stopwatch._accumulation @@ -171,6 +174,7 @@ stopwatch_duration :: proc "contextless" (stopwatch: Stopwatch) -> Duration { /* Calculate the duration elapsed between two times. */ +@(require_results) diff :: proc "contextless" (start, end: Time) -> Duration { d := end._nsec - start._nsec return Duration(d) @@ -179,6 +183,7 @@ diff :: proc "contextless" (start, end: Time) -> Duration { /* Calculate the duration elapsed since a specific time. */ +@(require_results) since :: proc "contextless" (start: Time) -> Duration { return diff(start, now()) } @@ -186,6 +191,7 @@ since :: proc "contextless" (start: Time) -> Duration { /* Obtain the number of nanoseconds in a duration. */ +@(require_results) duration_nanoseconds :: proc "contextless" (d: Duration) -> i64 { return i64(d) } @@ -193,6 +199,7 @@ duration_nanoseconds :: proc "contextless" (d: Duration) -> i64 { /* Obtain the number of microseconds in a duration. */ +@(require_results) duration_microseconds :: proc "contextless" (d: Duration) -> f64 { return duration_seconds(d) * 1e6 } @@ -200,6 +207,7 @@ duration_microseconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of milliseconds in a duration. */ +@(require_results) duration_milliseconds :: proc "contextless" (d: Duration) -> f64 { return duration_seconds(d) * 1e3 } @@ -207,6 +215,7 @@ duration_milliseconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of seconds in a duration. */ +@(require_results) duration_seconds :: proc "contextless" (d: Duration) -> f64 { sec := d / Second nsec := d % Second @@ -216,6 +225,7 @@ duration_seconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of minutes in a duration. */ +@(require_results) duration_minutes :: proc "contextless" (d: Duration) -> f64 { min := d / Minute nsec := d % Minute @@ -225,6 +235,7 @@ duration_minutes :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of hours in a duration. */ +@(require_results) duration_hours :: proc "contextless" (d: Duration) -> f64 { hour := d / Hour nsec := d % Hour @@ -248,6 +259,7 @@ Returns: Example: time.duration_round(my_duration, time.Second) */ +@(require_results) duration_round :: proc "contextless" (d, m: Duration) -> Duration { _less_than_half :: #force_inline proc "contextless" (x, y: Duration) -> bool { return u64(x)+u64(x) < u64(y) @@ -294,6 +306,7 @@ Returns: Example: time.duration_round(my_duration, time.Second) */ +@(require_results) duration_truncate :: proc "contextless" (d, m: Duration) -> Duration { return d if m <= 0 else d - d%m } @@ -301,6 +314,7 @@ duration_truncate :: proc "contextless" (d, m: Duration) -> Duration { /* Parse time into date components. */ +@(require_results) date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) { year, month, day, _ = _abs_date(_time_abs(t), true) return @@ -309,6 +323,7 @@ date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) { /* Obtain the year of the date specified by time. */ +@(require_results) year :: proc "contextless" (t: Time) -> (year: int) { year, _, _, _ = _date(t, true) return @@ -317,6 +332,7 @@ year :: proc "contextless" (t: Time) -> (year: int) { /* Obtain the month of the date specified by time. */ +@(require_results) month :: proc "contextless" (t: Time) -> (month: Month) { _, month, _, _ = _date(t, true) return @@ -325,6 +341,7 @@ month :: proc "contextless" (t: Time) -> (month: Month) { /* Obtain the day of the date specified by time. */ +@(require_results) day :: proc "contextless" (t: Time) -> (day: int) { _, _, day, _ = _date(t, true) return @@ -333,6 +350,7 @@ day :: proc "contextless" (t: Time) -> (day: int) { /* Obtain the week day of the date specified by time. */ +@(require_results) weekday :: proc "contextless" (t: Time) -> (weekday: Weekday) { abs := _time_abs(t) sec := (abs + u64(Weekday.Monday) * SECONDS_PER_DAY) % SECONDS_PER_WEEK @@ -352,6 +370,7 @@ precise_clock :: proc { precise_clock_from_time, precise_clock_from_duration, pr /* Obtain the time components from a time. */ +@(require_results) clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) { hour, min, sec, _ = precise_clock_from_time(t) return @@ -360,6 +379,7 @@ clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) { /* Obtain the time components from a time, including nanoseconds. */ +@(require_results) precise_clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec, nanos: int) { // Time in nanoseconds since 1-1-1970 00:00 _sec, _nanos := t._nsec / 1e9, t._nsec % 1e9 @@ -376,6 +396,7 @@ precise_clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec, nano /* Obtain the time components from a duration. */ +@(require_results) clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) { return clock_from_seconds(u64(d/1e9)) } @@ -383,6 +404,7 @@ clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) /* Obtain the time components from a duration, including nanoseconds. */ +@(require_results) precise_clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec, nanos: int) { return precise_clock_from_time({_nsec=i64(d)}) } @@ -390,6 +412,7 @@ precise_clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, s /* Obtain the time components from a stopwatch's total. */ +@(require_results) clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: int) { return clock_from_duration(stopwatch_duration(s)) } @@ -397,6 +420,7 @@ clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: in /* Obtain the time components from a stopwatch's total, including nanoseconds */ +@(require_results) precise_clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec, nanos: int) { return precise_clock_from_duration(stopwatch_duration(s)) } @@ -404,6 +428,7 @@ precise_clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, /* Obtain the time components from the number of seconds. */ +@(require_results) clock_from_seconds :: proc "contextless" (in_sec: u64) -> (hour, min, sec: int) { sec = int(in_sec % SECONDS_PER_DAY) hour = sec / SECONDS_PER_HOUR @@ -435,6 +460,7 @@ Example: now := time.now() fmt.println(time.to_string_hms(now, buf[:])) */ +@(require_results) time_to_string_hms :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_HMS_LEN) h, m, s := clock(t) @@ -468,6 +494,7 @@ Example: d := time.since(earlier) fmt.println(time.to_string_hms(now, buf[:])) */ +@(require_results) duration_to_string_hms :: proc(d: Duration, buf: []u8) -> (res: string) #no_bounds_check { return time_to_string_hms(Time{_nsec=i64(d)}, buf) } @@ -493,11 +520,15 @@ Example: fmt.println(time.to_string_hms_12(now, buf[:])) fmt.println(time.to_string_hms_12(now, buf[:], {"㏂", "㏘"})) */ +@(require_results) to_string_hms_12 :: proc(t: Time, buf: []u8, ampm: [2]string = {" am", " pm"}) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_HMS_LEN + max(len(ampm[0]), len(ampm[1]))) h, m, s := clock(t) _h := h % 12 + if _h == 0 { + _h = 12 + } buf[7] = '0' + u8(s % 10); s /= 10 buf[6] = '0' + u8(s) buf[5] = ':' @@ -507,7 +538,7 @@ to_string_hms_12 :: proc(t: Time, buf: []u8, ampm: [2]string = {" am", " pm"}) - buf[1] = '0' + u8(_h% 10); _h /= 10 buf[0] = '0' + u8(_h) - if h < 13 { + if h < 12 { copy(buf[8:], ampm[0]) return string(buf[:MIN_HMS_LEN+len(ampm[0])]) } else { @@ -531,6 +562,7 @@ Example: now := time.now() fmt.println(time.to_string_yyyy_mm_dd(now, buf[:])) */ +@(require_results) to_string_yyyy_mm_dd :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -565,6 +597,7 @@ Example: now := time.now() fmt.println(time.to_string_yy_mm_dd(now, buf[:])) */ +@(require_results) to_string_yy_mm_dd :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -597,6 +630,7 @@ Example: now := time.now() fmt.println(time.to_string_dd_mm_yyyy(now, buf[:])) */ +@(require_results) to_string_dd_mm_yyyy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -631,6 +665,7 @@ Example: now := time.now() fmt.println(time.to_string_dd_mm_yy(now, buf[:])) */ +@(require_results) to_string_dd_mm_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -663,6 +698,7 @@ Example: now := time.now() fmt.println(time.to_string_mm_dd_yyyy(now, buf[:])) */ +@(require_results) to_string_mm_dd_yyyy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -697,6 +733,7 @@ Example: now := time.now() fmt.println(time.to_string_mm_dd_yy(now, buf[:])) */ +@(require_results) to_string_mm_dd_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -717,6 +754,7 @@ to_string_mm_dd_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check /* Read the timestamp counter of the CPU. */ +@(require_results) read_cycle_counter :: proc "contextless" () -> u64 { return u64(intrinsics.read_cycle_counter()) } @@ -724,6 +762,7 @@ read_cycle_counter :: proc "contextless" () -> u64 { /* Obtain time from unix seconds and unix nanoseconds. */ +@(require_results) unix :: proc "contextless" (sec: i64, nsec: i64) -> Time { sec, nsec := sec, nsec if nsec < 0 || nsec >= 1e9 { @@ -741,6 +780,7 @@ unix :: proc "contextless" (sec: i64, nsec: i64) -> Time { /* Obtain time from unix nanoseconds. */ +@(require_results) from_nanoseconds :: #force_inline proc "contextless" (nsec: i64) -> Time { return Time{nsec} } @@ -753,6 +793,7 @@ to_unix_seconds :: time_to_unix /* Obtain the Unix timestamp in seconds from a Time. */ +@(require_results) time_to_unix :: proc "contextless" (t: Time) -> i64 { return t._nsec/1e9 } @@ -765,6 +806,7 @@ to_unix_nanoseconds :: time_to_unix_nano /* Obtain the Unix timestamp in nanoseconds from a Time. */ +@(require_results) time_to_unix_nano :: proc "contextless" (t: Time) -> i64 { return t._nsec } @@ -772,6 +814,7 @@ time_to_unix_nano :: proc "contextless" (t: Time) -> i64 { /* Add duration to a time. */ +@(require_results) time_add :: proc "contextless" (t: Time, d: Duration) -> Time { return Time{t._nsec + i64(d)} } @@ -838,18 +881,18 @@ UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE -@(private) +@(private, require_results) _date :: proc "contextless" (t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) { year, month, day, yday = _abs_date(_time_abs(t), full) return } -@(private) +@(private, require_results) _time_abs :: proc "contextless" (t: Time) -> u64 { return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE) } -@(private) +@(private, require_results) _abs_date :: proc "contextless" (abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { d := abs / SECONDS_PER_DAY @@ -915,7 +958,8 @@ This procedure calculates the time from datetime components supplied in the arguments to this procedure. If the datetime components don't represent a valid datetime, the function returns `false` in the second argument. */ -components_to_time :: proc "contextless" (#any_int year, #any_int month, #any_int day, #any_int hour, #any_int minute, #any_int second: i64, #any_int nsec := i64(0)) -> (t: Time, ok: bool) { +@(require_results) +components_to_time :: proc "contextless" (#any_int year, #any_int month, #any_int day, #any_int hour, #any_int minute, #any_int second: i64, #any_int nsec := i64(0)) -> (t: Time, ok: bool) #optional_ok { this_date, err := dt.components_to_datetime(year, month, day, hour, minute, second, nsec) if err != .None { return @@ -929,6 +973,7 @@ Convert datetime into time. If the datetime represents a time outside of a valid range, `false` is returned as the second return value. See `Time` for the representable range. */ +@(require_results) compound_to_time :: proc "contextless" (datetime: dt.DateTime) -> (t: Time, ok: bool) { unix_epoch := dt.DateTime{{1970, 1, 1}, {0, 0, 0, 0}, nil} delta, err := dt.sub(datetime, unix_epoch) @@ -957,6 +1002,7 @@ datetime_to_time :: proc{components_to_time, compound_to_time} /* Convert time into datetime. */ +@(require_results) time_to_datetime :: proc "contextless" (t: Time) -> (dt.DateTime, bool) { unix_epoch := dt.DateTime{{1970, 1, 1}, {0, 0, 0, 0}, nil} @@ -975,6 +1021,7 @@ time_to_compound :: time_to_datetime /* Check if a year is a leap year. */ +@(require_results) is_leap_year :: proc "contextless" (year: int) -> (leap: bool) { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) } diff --git a/core/time/time_essence.odin b/core/time/time_essence.odin deleted file mode 100644 index 89883f0b9..000000000 --- a/core/time/time_essence.odin +++ /dev/null @@ -1,19 +0,0 @@ -#+private -package time - -import "core:sys/es" - -_IS_SUPPORTED :: true - -_now :: proc "contextless" () -> Time { - // TODO Replace once there's a proper time API. - return Time{_nsec = i64(es.TimeStampMs() * 1e6)} -} - -_sleep :: proc "contextless" (d: Duration) { - es.Sleep(u64(d/Millisecond)) -} - -_tick_now :: proc "contextless" () -> Tick { - return Tick{_nsec = i64(es.TimeStampMs() * 1e6)} -} diff --git a/core/time/time_js.odin b/core/time/time_js.odin index 9175fbfe9..0e021dc88 100644 --- a/core/time/time_js.odin +++ b/core/time/time_js.odin @@ -24,7 +24,7 @@ _sleep :: proc "contextless" (d: Duration) { _tick_now :: proc "contextless" () -> Tick { foreign odin_env { - tick_now :: proc "contextless" () -> f32 --- + tick_now :: proc "contextless" () -> f64 --- } return Tick{i64(tick_now()*1e6)} } diff --git a/core/time/time_other.odin b/core/time/time_other.odin index 3f0f06e9b..7f57df452 100644 --- a/core/time/time_other.odin +++ b/core/time/time_other.odin @@ -1,5 +1,4 @@ #+private -#+build !essence #+build !js #+build !linux #+build !openbsd @@ -9,7 +8,6 @@ #+build !wasi #+build !windows #+build !orca -#+build !haiku package time _IS_SUPPORTED :: false diff --git a/core/time/time_unix.odin b/core/time/time_unix.odin index c384d6d07..61c4e91d3 100644 --- a/core/time/time_unix.odin +++ b/core/time/time_unix.odin @@ -1,5 +1,5 @@ #+private -#+build darwin, freebsd, openbsd, netbsd, haiku +#+build darwin, freebsd, openbsd, netbsd package time import "core:sys/posix" diff --git a/core/time/timezone/tz_js.odin b/core/time/timezone/tz_js.odin new file mode 100644 index 000000000..d63e40033 --- /dev/null +++ b/core/time/timezone/tz_js.odin @@ -0,0 +1,13 @@ +#+build js +#+private +package timezone + +import "core:time/datetime" + +local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: bool) { + return +} + +_region_load :: proc(_reg_str: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, success: bool) { + return nil, true +} \ No newline at end of file diff --git a/core/time/timezone/tz_os.odin b/core/time/timezone/tz_os.odin new file mode 100644 index 000000000..fae4980c3 --- /dev/null +++ b/core/time/timezone/tz_os.odin @@ -0,0 +1,19 @@ +#+build !freestanding +#+build !js +package timezone + +import "core:os" +import "core:time/datetime" + +load_tzif_file :: proc(filename: string, region_name: string, allocator := context.allocator) -> (out: ^datetime.TZ_Region, ok: bool) { + tzif_data, tzif_err := os.read_entire_file(filename, allocator) + if tzif_err != nil { + return nil, false + } + defer delete(tzif_data, allocator) + return parse_tzif(tzif_data, region_name, allocator) +} + +region_load_from_file :: proc(file_path, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { + return load_tzif_file(file_path, reg, allocator) +} \ No newline at end of file diff --git a/core/time/timezone/tz_unix.odin b/core/time/timezone/tz_unix.odin index 990e78d41..3939b3265 100644 --- a/core/time/timezone/tz_unix.odin +++ b/core/time/timezone/tz_unix.odin @@ -4,17 +4,17 @@ package timezone import "core:os" import "core:strings" -import "core:path/filepath" import "core:time/datetime" +import "core:path/filepath" local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: bool) { local_str, ok := os.lookup_env("TZ", allocator) if !ok { orig_localtime_path := "/etc/localtime" - path, err := os.absolute_path_from_relative(orig_localtime_path, allocator) + path, err := os.get_absolute_path(orig_localtime_path, allocator) if err != nil { // If we can't find /etc/localtime, fallback to UTC - if err == .ENOENT { + if err == .Not_Exist { str, err2 := strings.clone("UTC", allocator) if err2 != nil { return } return str, true @@ -28,16 +28,20 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: // This is a hackaround, because FreeBSD copies rather than softlinks their local timezone file, // *sometimes* and then stores the original name of the timezone in /var/db/zoneinfo instead if path == orig_localtime_path { - data := os.read_entire_file("/var/db/zoneinfo", allocator) or_return + data, data_err := os.read_entire_file("/var/db/zoneinfo", allocator) + if data_err != nil { + return "", false + } return strings.trim_right_space(string(data)), true } // Looking for tz path (ex fmt: "UTC", "Etc/UTC" or "America/Los_Angeles") - path_dir, path_file := filepath.split(path) + path_dir, path_file := os.split_path(path) + if path_dir == "" { return } - upper_path_dir, upper_path_chunk := filepath.split(path_dir[:len(path_dir)-1]) + upper_path_dir, upper_path_chunk := os.split_path(path_dir[:len(path_dir)]) if upper_path_dir == "" { return } @@ -47,8 +51,8 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: if err != nil { return } return region_str, true } else { - region_str, err := filepath.join({upper_path_chunk, path_file}, allocator = allocator) - if err != nil { return } + region_str, region_str_err := os.join_path({upper_path_chunk, path_file}, allocator = allocator) + if region_str_err != nil { return } return region_str, true } } @@ -81,9 +85,29 @@ _region_load :: proc(_reg_str: string, allocator := context.allocator) -> (out_r } defer if _reg_str == "local" { delete(reg_str, allocator) } - db_path := "/usr/share/zoneinfo" - region_path := filepath.join({db_path, reg_str}, allocator) - defer delete(region_path, allocator) + tzdir_str, tzdir_ok := os.lookup_env("TZDIR", allocator) + defer if tzdir_ok { delete(tzdir_str, allocator) } - return load_tzif_file(region_path, reg_str, allocator) -} + if tzdir_ok { + region_path, err := filepath.join({tzdir_str, reg_str}, allocator) + if err != nil { return nil, false } + defer delete(region_path, allocator) + + if tz_reg, ok := load_tzif_file(region_path, reg_str, allocator); ok { + return tz_reg, true + } + } + + db_paths := []string{"/usr/share/zoneinfo", "/share/zoneinfo", "/etc/zoneinfo"} + for db_path in db_paths { + region_path, err := filepath.join({db_path, reg_str}, allocator) + if err != nil { return nil, false} + defer delete(region_path, allocator) + + if tz_reg, ok := load_tzif_file(region_path, reg_str, allocator); ok { + return tz_reg, true + } + } + + return nil, false +} \ No newline at end of file diff --git a/core/time/timezone/tz_windows.odin b/core/time/timezone/tz_windows.odin index 8dc5f533c..fe00719a2 100644 --- a/core/time/timezone/tz_windows.odin +++ b/core/time/timezone/tz_windows.odin @@ -159,9 +159,9 @@ iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) -> status: windows.UError iana_name_wstr := windows.utf8_to_wstring(iana_name, allocator) - defer free(iana_name_wstr, allocator) + defer free(rawptr(iana_name_wstr), allocator) - wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, raw_data(wintz_name_buffer[:]), len(wintz_name_buffer), &status) + wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, cstring16(raw_data(wintz_name_buffer[:])), len(wintz_name_buffer), &status) if status != .U_ZERO_ERROR { return } @@ -178,7 +178,7 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: iana_name_buffer: [128]u16 status: windows.UError - zone_str_len := windows.ucal_getDefaultTimeZone(raw_data(iana_name_buffer[:]), len(iana_name_buffer), &status) + zone_str_len := windows.ucal_getDefaultTimeZone(cstring16(raw_data(iana_name_buffer[:])), len(iana_name_buffer), &status) if status != .U_ZERO_ERROR { return } @@ -291,7 +291,7 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re defer delete(tz_key, allocator) tz_key_wstr := windows.utf8_to_wstring(tz_key, allocator) - defer free(tz_key_wstr, allocator) + defer free(rawptr(tz_key_wstr), allocator) key: windows.HKEY res := windows.RegOpenKeyExW(windows.HKEY_LOCAL_MACHINE, tz_key_wstr, 0, windows.KEY_READ, &key) diff --git a/core/time/timezone/tzdate.odin b/core/time/timezone/tzdate.odin index 8e900ec11..29e8ad25c 100644 --- a/core/time/timezone/tzdate.odin +++ b/core/time/timezone/tzdate.odin @@ -1,3 +1,4 @@ +// Timezone lookup. package timezone import "core:fmt" @@ -9,10 +10,6 @@ region_load :: proc(reg: string, allocator := context.allocator) -> (out_reg: ^ return _region_load(reg, allocator) } -region_load_from_file :: proc(file_path, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { - return load_tzif_file(file_path, reg, allocator) -} - region_load_from_buffer :: proc(buffer: []u8, reg: string, allocator := context.allocator) -> (out_reg: ^datetime.TZ_Region, ok: bool) { return parse_tzif(buffer, reg, allocator) } diff --git a/core/time/timezone/tzif.odin b/core/time/timezone/tzif.odin index 3fec7be53..3b92364ac 100644 --- a/core/time/timezone/tzif.odin +++ b/core/time/timezone/tzif.odin @@ -1,12 +1,10 @@ package timezone -import "base:intrinsics" - -import "core:slice" -import "core:strings" -import "core:os" -import "core:strconv" -import "core:time/datetime" +import "base:intrinsics" +import "core:slice" +import "core:strings" +import "core:strconv" +import "core:time/datetime" // Implementing RFC8536 [https://datatracker.ietf.org/doc/html/rfc8536] @@ -68,13 +66,6 @@ tzif_data_block_size :: proc(hdr: ^TZif_Header, version: TZif_Version) -> (block int(hdr.isutcnt), true } - -load_tzif_file :: proc(filename: string, region_name: string, allocator := context.allocator) -> (out: ^datetime.TZ_Region, ok: bool) { - tzif_data := os.read_entire_file_from_filename(filename, allocator) or_return - defer delete(tzif_data, allocator) - return parse_tzif(tzif_data, region_name, allocator) -} - @private is_alphabetic :: proc(ch: u8) -> bool { // ('A' -> 'Z') || ('a' -> 'z') @@ -577,12 +568,7 @@ parse_tzif :: proc(_buffer: []u8, region_name: string, allocator := context.allo footer_str := string(buffer[:end_idx]) // UTC is a special case, we don't need to alloc - if len(local_time_types) == 1 { - name := cstring(raw_data(timezone_string_table[local_time_types[0].idx:])) - if name != "UTC" { - return - } - + if len(local_time_types) == 1 && local_time_types[0].utoff == 0 { return nil, true } diff --git a/core/time/tsc_darwin.odin b/core/time/tsc_darwin.odin index 3726cff49..2efd35f20 100644 --- a/core/time/tsc_darwin.odin +++ b/core/time/tsc_darwin.odin @@ -1,10 +1,17 @@ #+private package time -import "core:sys/unix" +import "base:intrinsics" +@require import "core:sys/unix" _get_tsc_frequency :: proc "contextless" () -> (freq: u64, ok: bool) { - unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return + when ODIN_ARCH == .amd64 { + unix.sysctlbyname("machdep.tsc.frequency", &freq) or_return + } else when ODIN_ARCH == .arm64 { + freq = u64(intrinsics.read_cycle_counter_frequency()) + } else { + return + } ok = true return } diff --git a/core/time/tsc_linux.odin b/core/time/tsc_linux.odin index a83634414..f59a0338b 100644 --- a/core/time/tsc_linux.odin +++ b/core/time/tsc_linux.odin @@ -2,32 +2,38 @@ #+build linux package time -import linux "core:sys/linux" +import "base:intrinsics" +@(require) import linux "core:sys/linux" _get_tsc_frequency :: proc "contextless" () -> (u64, bool) { - // Get the file descriptor for the perf mapping - perf_attr := linux.Perf_Event_Attr{} - perf_attr.size = size_of(perf_attr) - perf_attr.type = .HARDWARE - perf_attr.config.hw = .INSTRUCTIONS - perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV} - fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {}) - if perf_errno != nil { - return 0, false + when ODIN_ARCH == .arm64 { + frequency := u64(intrinsics.read_cycle_counter_frequency()) + return frequency, true + } else { + // Get the file descriptor for the perf mapping + perf_attr := linux.Perf_Event_Attr{} + perf_attr.size = size_of(perf_attr) + perf_attr.type = .HARDWARE + perf_attr.config.hw = .INSTRUCTIONS + perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV} + fd, perf_errno := linux.perf_event_open(&perf_attr, linux.Pid(0), -1, linux.Fd(-1), {}) + if perf_errno != nil { + return 0, false + } + defer linux.close(fd) + // Map it into the memory + page_size : uint = 4096 + addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd) + if mmap_errno != nil { + return 0, false + } + defer linux.munmap(addr, page_size) + // Get the frequency from the mapped page + event_page := cast(^linux.Perf_Event_Mmap_Page) addr + if .User_Time not_in event_page.cap.flags { + return 0, false + } + frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult)) + return frequency, true } - defer linux.close(fd) - // Map it into the memory - page_size : uint = 4096 - addr, mmap_errno := linux.mmap(0, page_size, {.READ}, {.SHARED}, fd) - if mmap_errno != nil { - return 0, false - } - defer linux.munmap(addr, page_size) - // Get the frequency from the mapped page - event_page := cast(^linux.Perf_Event_Mmap_Page) addr - if .User_Time not_in event_page.cap.flags { - return 0, false - } - frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult)) - return frequency, true } diff --git a/core/unicode/doc.odin b/core/unicode/doc.odin new file mode 100644 index 000000000..302fd59e1 --- /dev/null +++ b/core/unicode/doc.odin @@ -0,0 +1,2 @@ +// Data and procedures to test properties of `Unicode` code points. +package unicode \ No newline at end of file diff --git a/core/unicode/fold.odin b/core/unicode/fold.odin new file mode 100644 index 000000000..2e0d7225c --- /dev/null +++ b/core/unicode/fold.odin @@ -0,0 +1,79 @@ +package unicode + +// simple_fold iterates over the Unicode code points equivalent under the Unicode defined simple case folding. +// simple_fold returns the smallest rune > r if one exists, or the smallest rune >= 0. +// If no valid Unicode code point exists, r is returned. +// +// Example: +// simple_fold('A') == 'a' +// simple_fold('a') == 'A' +// simple_fold('Z') == 'z' +// simple_fold('z') == 'Z' +// simple_fold('7') == '7' +// simple_fold('k') == '\u212a' (Kelvin symbol, K) +// simple_fold('\u212a') == 'k' +// simple_fold(-3) == -3 +@(require_results) +simple_fold :: proc(r: rune) -> rune #no_bounds_check { + Fold_Pair :: struct { + from: u16, + to: u16, + } + + @(static, rodata) + ASCII_FOLD := [MAX_ASCII + 1]u16{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x212a, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x017f, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + } + + @(static, rodata) + CASE_ORBIT := [?]Fold_Pair{ + {0x004B, 0x006B}, {0x0053, 0x0073}, {0x006B, 0x212A}, {0x0073, 0x017F}, {0x00B5, 0x039C}, {0x00C5, 0x00E5}, {0x00DF, 0x1E9E}, + {0x00E5, 0x212B}, {0x0130, 0x0130}, {0x0131, 0x0131}, {0x017F, 0x0053}, {0x01C4, 0x01C5}, {0x01C5, 0x01C6}, {0x01C6, 0x01C4}, + {0x01C7, 0x01C8}, {0x01C8, 0x01C9}, {0x01C9, 0x01C7}, {0x01CA, 0x01CB}, {0x01CB, 0x01CC}, {0x01CC, 0x01CA}, {0x01F1, 0x01F2}, + {0x01F2, 0x01F3}, {0x01F3, 0x01F1}, {0x0345, 0x0399}, {0x0392, 0x03B2}, {0x0395, 0x03B5}, {0x0398, 0x03B8}, {0x0399, 0x03B9}, + {0x039A, 0x03BA}, {0x039C, 0x03BC}, {0x03A0, 0x03C0}, {0x03A1, 0x03C1}, {0x03A3, 0x03C2}, {0x03A6, 0x03C6}, {0x03A9, 0x03C9}, + {0x03B2, 0x03D0}, {0x03B5, 0x03F5}, {0x03B8, 0x03D1}, {0x03B9, 0x1FBE}, {0x03BA, 0x03F0}, {0x03BC, 0x00B5}, {0x03C0, 0x03D6}, + {0x03C1, 0x03F1}, {0x03C2, 0x03C3}, {0x03C3, 0x03A3}, {0x03C6, 0x03D5}, {0x03C9, 0x2126}, {0x03D0, 0x0392}, {0x03D1, 0x03F4}, + {0x03D5, 0x03A6}, {0x03D6, 0x03A0}, {0x03F0, 0x039A}, {0x03F1, 0x03A1}, {0x03F4, 0x0398}, {0x03F5, 0x0395}, {0x0412, 0x0432}, + {0x0414, 0x0434}, {0x041E, 0x043E}, {0x0421, 0x0441}, {0x0422, 0x0442}, {0x042A, 0x044A}, {0x0432, 0x1C80}, {0x0434, 0x1C81}, + {0x043E, 0x1C82}, {0x0441, 0x1C83}, {0x0442, 0x1C84}, {0x044A, 0x1C86}, {0x0462, 0x0463}, {0x0463, 0x1C87}, {0x1C80, 0x0412}, + {0x1C81, 0x0414}, {0x1C82, 0x041E}, {0x1C83, 0x0421}, {0x1C84, 0x1C85}, {0x1C85, 0x0422}, {0x1C86, 0x042A}, {0x1C87, 0x0462}, + {0x1C88, 0xA64A}, {0x1E60, 0x1E61}, {0x1E61, 0x1E9B}, {0x1E9B, 0x1E60}, {0x1E9E, 0x00DF}, {0x1FBE, 0x0345}, {0x2126, 0x03A9}, + {0x212A, 0x004B}, {0x212B, 0x00C5}, {0xA64A, 0xA64B}, {0xA64B, 0x1C88}, + } + + if r < 0 || r > MAX_RUNE { + return r + } + if int(r) < len(ASCII_FOLD) { + return rune(ASCII_FOLD[r]) + } + + lo, hi := 0, len(CASE_ORBIT) + for lo < hi { + m := int(uint(lo+hi) >> 1) + if rune(CASE_ORBIT[m].from) < r { + lo = m + 1 + } else { + hi = m + } + } + + if lo < len(CASE_ORBIT) && rune(CASE_ORBIT[lo].from) == r { + return rune(CASE_ORBIT[lo].to) + } + + + l := to_lower(r) + if l != r { + return l + } + return to_upper(r) +} diff --git a/core/unicode/generated.odin b/core/unicode/generated.odin new file mode 100644 index 000000000..bfea47a87 --- /dev/null +++ b/core/unicode/generated.odin @@ -0,0 +1,2335 @@ +package unicode + +/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ + +/* + This file is generated from UnicodeData.txt and PropList.txt. These files + are part of the Unicode Database (UCD) and are covered by the license + listed further down. They may be downloaded from the following locations; + + https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt + https://www.unicode.org/license.txt + + ------------------------------------------------------------------------------ + UNICODE LICENSE V3 + + COPYRIGHT AND PERMISSION NOTICE + + Copyright © 1991-2026 Unicode, Inc. + + NOTICE TO USER: Carefully read the following legal agreement. BY + DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR + SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE + TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT + DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of data files and any associated documentation (the "Data Files") or + software and any associated documentation (the "Software") to deal in the + Data Files or Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, and/or sell + copies of the Data Files or Software, and to permit persons to whom the + Data Files or Software are furnished to do so, provided that either (a) + this copyright and permission notice appear with all copies of the Data + Files or Software, or (b) this copyright and permission notice appear in + associated Documentation. + + THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + THIRD PARTY RIGHTS. + + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE + BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA + FILES OR SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in these Data Files or Software without prior written + authorization of the copyright holder. + +*/ + +Range :: struct { + single_16 : []u16, + ranges_16 : []u16, + single_32 : []i32, + ranges_32 : []i32, +} + +@(rodata) +ll_singles16 := [?]u16{ + 0x00B5, 0x0101, 0x0103, 0x0105, 0x0107, 0x0109, 0x010B, 0x010D, + 0x010F, 0x0111, 0x0113, 0x0115, 0x0117, 0x0119, 0x011B, 0x011D, + 0x011F, 0x0121, 0x0123, 0x0125, 0x0127, 0x0129, 0x012B, 0x012D, + 0x012F, 0x0131, 0x0133, 0x0135, 0x013A, 0x013C, 0x013E, 0x0140, + 0x0142, 0x0144, 0x0146, 0x014B, 0x014D, 0x014F, 0x0151, 0x0153, + 0x0155, 0x0157, 0x0159, 0x015B, 0x015D, 0x015F, 0x0161, 0x0163, + 0x0165, 0x0167, 0x0169, 0x016B, 0x016D, 0x016F, 0x0171, 0x0173, + 0x0175, 0x0177, 0x017A, 0x017C, 0x0183, 0x0185, 0x0188, 0x0192, + 0x0195, 0x019E, 0x01A1, 0x01A3, 0x01A5, 0x01A8, 0x01AD, 0x01B0, + 0x01B4, 0x01B6, 0x01C6, 0x01C9, 0x01CC, 0x01CE, 0x01D0, 0x01D2, + 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DF, 0x01E1, 0x01E3, 0x01E5, + 0x01E7, 0x01E9, 0x01EB, 0x01ED, 0x01F3, 0x01F5, 0x01F9, 0x01FB, + 0x01FD, 0x01FF, 0x0201, 0x0203, 0x0205, 0x0207, 0x0209, 0x020B, + 0x020D, 0x020F, 0x0211, 0x0213, 0x0215, 0x0217, 0x0219, 0x021B, + 0x021D, 0x021F, 0x0221, 0x0223, 0x0225, 0x0227, 0x0229, 0x022B, + 0x022D, 0x022F, 0x0231, 0x023C, 0x0242, 0x0247, 0x0249, 0x024B, + 0x024D, 0x0371, 0x0373, 0x0377, 0x0390, 0x03D9, 0x03DB, 0x03DD, + 0x03DF, 0x03E1, 0x03E3, 0x03E5, 0x03E7, 0x03E9, 0x03EB, 0x03ED, + 0x03F5, 0x03F8, 0x0461, 0x0463, 0x0465, 0x0467, 0x0469, 0x046B, + 0x046D, 0x046F, 0x0471, 0x0473, 0x0475, 0x0477, 0x0479, 0x047B, + 0x047D, 0x047F, 0x0481, 0x048B, 0x048D, 0x048F, 0x0491, 0x0493, + 0x0495, 0x0497, 0x0499, 0x049B, 0x049D, 0x049F, 0x04A1, 0x04A3, + 0x04A5, 0x04A7, 0x04A9, 0x04AB, 0x04AD, 0x04AF, 0x04B1, 0x04B3, + 0x04B5, 0x04B7, 0x04B9, 0x04BB, 0x04BD, 0x04BF, 0x04C2, 0x04C4, + 0x04C6, 0x04C8, 0x04CA, 0x04CC, 0x04D1, 0x04D3, 0x04D5, 0x04D7, + 0x04D9, 0x04DB, 0x04DD, 0x04DF, 0x04E1, 0x04E3, 0x04E5, 0x04E7, + 0x04E9, 0x04EB, 0x04ED, 0x04EF, 0x04F1, 0x04F3, 0x04F5, 0x04F7, + 0x04F9, 0x04FB, 0x04FD, 0x04FF, 0x0501, 0x0503, 0x0505, 0x0507, + 0x0509, 0x050B, 0x050D, 0x050F, 0x0511, 0x0513, 0x0515, 0x0517, + 0x0519, 0x051B, 0x051D, 0x051F, 0x0521, 0x0523, 0x0525, 0x0527, + 0x0529, 0x052B, 0x052D, 0x052F, 0x1C8A, 0x1E01, 0x1E03, 0x1E05, + 0x1E07, 0x1E09, 0x1E0B, 0x1E0D, 0x1E0F, 0x1E11, 0x1E13, 0x1E15, + 0x1E17, 0x1E19, 0x1E1B, 0x1E1D, 0x1E1F, 0x1E21, 0x1E23, 0x1E25, + 0x1E27, 0x1E29, 0x1E2B, 0x1E2D, 0x1E2F, 0x1E31, 0x1E33, 0x1E35, + 0x1E37, 0x1E39, 0x1E3B, 0x1E3D, 0x1E3F, 0x1E41, 0x1E43, 0x1E45, + 0x1E47, 0x1E49, 0x1E4B, 0x1E4D, 0x1E4F, 0x1E51, 0x1E53, 0x1E55, + 0x1E57, 0x1E59, 0x1E5B, 0x1E5D, 0x1E5F, 0x1E61, 0x1E63, 0x1E65, + 0x1E67, 0x1E69, 0x1E6B, 0x1E6D, 0x1E6F, 0x1E71, 0x1E73, 0x1E75, + 0x1E77, 0x1E79, 0x1E7B, 0x1E7D, 0x1E7F, 0x1E81, 0x1E83, 0x1E85, + 0x1E87, 0x1E89, 0x1E8B, 0x1E8D, 0x1E8F, 0x1E91, 0x1E93, 0x1E9F, + 0x1EA1, 0x1EA3, 0x1EA5, 0x1EA7, 0x1EA9, 0x1EAB, 0x1EAD, 0x1EAF, + 0x1EB1, 0x1EB3, 0x1EB5, 0x1EB7, 0x1EB9, 0x1EBB, 0x1EBD, 0x1EBF, + 0x1EC1, 0x1EC3, 0x1EC5, 0x1EC7, 0x1EC9, 0x1ECB, 0x1ECD, 0x1ECF, + 0x1ED1, 0x1ED3, 0x1ED5, 0x1ED7, 0x1ED9, 0x1EDB, 0x1EDD, 0x1EDF, + 0x1EE1, 0x1EE3, 0x1EE5, 0x1EE7, 0x1EE9, 0x1EEB, 0x1EED, 0x1EEF, + 0x1EF1, 0x1EF3, 0x1EF5, 0x1EF7, 0x1EF9, 0x1EFB, 0x1EFD, 0x1FBE, + 0x210A, 0x2113, 0x212F, 0x2134, 0x2139, 0x214E, 0x2184, 0x2C61, + 0x2C68, 0x2C6A, 0x2C6C, 0x2C71, 0x2C81, 0x2C83, 0x2C85, 0x2C87, + 0x2C89, 0x2C8B, 0x2C8D, 0x2C8F, 0x2C91, 0x2C93, 0x2C95, 0x2C97, + 0x2C99, 0x2C9B, 0x2C9D, 0x2C9F, 0x2CA1, 0x2CA3, 0x2CA5, 0x2CA7, + 0x2CA9, 0x2CAB, 0x2CAD, 0x2CAF, 0x2CB1, 0x2CB3, 0x2CB5, 0x2CB7, + 0x2CB9, 0x2CBB, 0x2CBD, 0x2CBF, 0x2CC1, 0x2CC3, 0x2CC5, 0x2CC7, + 0x2CC9, 0x2CCB, 0x2CCD, 0x2CCF, 0x2CD1, 0x2CD3, 0x2CD5, 0x2CD7, + 0x2CD9, 0x2CDB, 0x2CDD, 0x2CDF, 0x2CE1, 0x2CEC, 0x2CEE, 0x2CF3, + 0x2D27, 0x2D2D, 0xA641, 0xA643, 0xA645, 0xA647, 0xA649, 0xA64B, + 0xA64D, 0xA64F, 0xA651, 0xA653, 0xA655, 0xA657, 0xA659, 0xA65B, + 0xA65D, 0xA65F, 0xA661, 0xA663, 0xA665, 0xA667, 0xA669, 0xA66B, + 0xA66D, 0xA681, 0xA683, 0xA685, 0xA687, 0xA689, 0xA68B, 0xA68D, + 0xA68F, 0xA691, 0xA693, 0xA695, 0xA697, 0xA699, 0xA69B, 0xA723, + 0xA725, 0xA727, 0xA729, 0xA72B, 0xA72D, 0xA733, 0xA735, 0xA737, + 0xA739, 0xA73B, 0xA73D, 0xA73F, 0xA741, 0xA743, 0xA745, 0xA747, + 0xA749, 0xA74B, 0xA74D, 0xA74F, 0xA751, 0xA753, 0xA755, 0xA757, + 0xA759, 0xA75B, 0xA75D, 0xA75F, 0xA761, 0xA763, 0xA765, 0xA767, + 0xA769, 0xA76B, 0xA76D, 0xA76F, 0xA77A, 0xA77C, 0xA77F, 0xA781, + 0xA783, 0xA785, 0xA787, 0xA78C, 0xA78E, 0xA791, 0xA797, 0xA799, + 0xA79B, 0xA79D, 0xA79F, 0xA7A1, 0xA7A3, 0xA7A5, 0xA7A7, 0xA7A9, + 0xA7AF, 0xA7B5, 0xA7B7, 0xA7B9, 0xA7BB, 0xA7BD, 0xA7BF, 0xA7C1, + 0xA7C3, 0xA7C8, 0xA7CA, 0xA7CD, 0xA7CF, 0xA7D1, 0xA7D3, 0xA7D5, + 0xA7D7, 0xA7D9, 0xA7DB, 0xA7F6, 0xA7FA, +} + +@(rodata) +ll_ranges16 := [?]u16{ + 0x0061, 0x007A, + 0x00DF, 0x00F6, + 0x00F8, 0x00FF, + 0x0137, 0x0138, + 0x0148, 0x0149, + 0x017E, 0x0180, + 0x018C, 0x018D, + 0x0199, 0x019B, + 0x01AA, 0x01AB, + 0x01B9, 0x01BA, + 0x01BD, 0x01BF, + 0x01DC, 0x01DD, + 0x01EF, 0x01F0, + 0x0233, 0x0239, + 0x023F, 0x0240, + 0x024F, 0x0293, + 0x0296, 0x02AF, + 0x037B, 0x037D, + 0x03AC, 0x03CE, + 0x03D0, 0x03D1, + 0x03D5, 0x03D7, + 0x03EF, 0x03F3, + 0x03FB, 0x03FC, + 0x0430, 0x045F, + 0x04CE, 0x04CF, + 0x0560, 0x0588, + 0x10D0, 0x10FA, + 0x10FD, 0x10FF, + 0x13F8, 0x13FD, + 0x1C80, 0x1C88, + 0x1D00, 0x1D2B, + 0x1D6B, 0x1D77, + 0x1D79, 0x1D9A, + 0x1E95, 0x1E9D, + 0x1EFF, 0x1F07, + 0x1F10, 0x1F15, + 0x1F20, 0x1F27, + 0x1F30, 0x1F37, + 0x1F40, 0x1F45, + 0x1F50, 0x1F57, + 0x1F60, 0x1F67, + 0x1F70, 0x1F7D, + 0x1F80, 0x1F87, + 0x1F90, 0x1F97, + 0x1FA0, 0x1FA7, + 0x1FB0, 0x1FB4, + 0x1FB6, 0x1FB7, + 0x1FC2, 0x1FC4, + 0x1FC6, 0x1FC7, + 0x1FD0, 0x1FD3, + 0x1FD6, 0x1FD7, + 0x1FE0, 0x1FE7, + 0x1FF2, 0x1FF4, + 0x1FF6, 0x1FF7, + 0x210E, 0x210F, + 0x213C, 0x213D, + 0x2146, 0x2149, + 0x2C30, 0x2C5F, + 0x2C65, 0x2C66, + 0x2C73, 0x2C74, + 0x2C76, 0x2C7B, + 0x2CE3, 0x2CE4, + 0x2D00, 0x2D25, + 0xA72F, 0xA731, + 0xA771, 0xA778, + 0xA793, 0xA795, + 0xAB30, 0xAB5A, + 0xAB60, 0xAB68, + 0xAB70, 0xABBF, + 0xFB00, 0xFB06, + 0xFB13, 0xFB17, + 0xFF41, 0xFF5A, +} + +@(rodata) +ll_singles32 := [?]i32{ + 0x1D4BB, 0x1D7CB, +} + +@(rodata) +ll_ranges32 := [?]i32{ + 0x10428, 0x1044F, + 0x104D8, 0x104FB, + 0x10597, 0x105A1, + 0x105A3, 0x105B1, + 0x105B3, 0x105B9, + 0x105BB, 0x105BC, + 0x10CC0, 0x10CF2, + 0x10D70, 0x10D85, + 0x118C0, 0x118DF, + 0x16E60, 0x16E7F, + 0x16EBB, 0x16ED3, + 0x1D41A, 0x1D433, + 0x1D44E, 0x1D454, + 0x1D456, 0x1D467, + 0x1D482, 0x1D49B, + 0x1D4B6, 0x1D4B9, + 0x1D4BD, 0x1D4C3, + 0x1D4C5, 0x1D4CF, + 0x1D4EA, 0x1D503, + 0x1D51E, 0x1D537, + 0x1D552, 0x1D56B, + 0x1D586, 0x1D59F, + 0x1D5BA, 0x1D5D3, + 0x1D5EE, 0x1D607, + 0x1D622, 0x1D63B, + 0x1D656, 0x1D66F, + 0x1D68A, 0x1D6A5, + 0x1D6C2, 0x1D6DA, + 0x1D6DC, 0x1D6E1, + 0x1D6FC, 0x1D714, + 0x1D716, 0x1D71B, + 0x1D736, 0x1D74E, + 0x1D750, 0x1D755, + 0x1D770, 0x1D788, + 0x1D78A, 0x1D78F, + 0x1D7AA, 0x1D7C2, + 0x1D7C4, 0x1D7C9, + 0x1DF00, 0x1DF09, + 0x1DF0B, 0x1DF1E, + 0x1DF25, 0x1DF2A, + 0x1E922, 0x1E943, +} + +ll_ranges := Range{ + single_16 = ll_singles16[:], + ranges_16 = ll_ranges16[:], + single_32 = ll_singles32[:], + ranges_32 = ll_ranges32[:], +} + +@(rodata) +lm_singles16 := [?]u16{ + 0x02EC, 0x02EE, 0x0374, 0x037A, 0x0559, 0x0640, 0x07FA, 0x081A, + 0x0824, 0x0828, 0x08C9, 0x0971, 0x0E46, 0x0EC6, 0x10FC, 0x17D7, + 0x1843, 0x1AA7, 0x1D78, 0x2071, 0x207F, 0x2D6F, 0x2E2F, 0x3005, + 0x303B, 0xA015, 0xA60C, 0xA67F, 0xA770, 0xA788, 0xA9CF, 0xA9E6, + 0xAA70, 0xAADD, 0xAB69, 0xFF70, +} + +@(rodata) +lm_ranges16 := [?]u16{ + 0x02B0, 0x02C1, + 0x02C6, 0x02D1, + 0x02E0, 0x02E4, + 0x06E5, 0x06E6, + 0x07F4, 0x07F5, + 0x1C78, 0x1C7D, + 0x1D2C, 0x1D6A, + 0x1D9B, 0x1DBF, + 0x2090, 0x209C, + 0x2C7C, 0x2C7D, + 0x3031, 0x3035, + 0x309D, 0x309E, + 0x30FC, 0x30FE, + 0xA4F8, 0xA4FD, + 0xA69C, 0xA69D, + 0xA717, 0xA71F, + 0xA7F1, 0xA7F4, + 0xA7F8, 0xA7F9, + 0xAAF3, 0xAAF4, + 0xAB5C, 0xAB5F, + 0xFF9E, 0xFF9F, +} + +@(rodata) +lm_singles32 := [?]i32{ + 0x10D4E, 0x10D6F, 0x10EC5, 0x11DD9, 0x16FE3, 0x1E4EB, 0x1E6FF, 0x1E94B, +} + +@(rodata) +lm_ranges32 := [?]i32{ + 0x10780, 0x10785, + 0x10787, 0x107B0, + 0x107B2, 0x107BA, + 0x16B40, 0x16B43, + 0x16D40, 0x16D42, + 0x16D6B, 0x16D6C, + 0x16F93, 0x16F9F, + 0x16FE0, 0x16FE1, + 0x16FF2, 0x16FF3, + 0x1AFF0, 0x1AFF3, + 0x1AFF5, 0x1AFFB, + 0x1AFFD, 0x1AFFE, + 0x1E030, 0x1E06D, + 0x1E137, 0x1E13D, +} + +lm_ranges := Range{ + single_16 = lm_singles16[:], + ranges_16 = lm_ranges16[:], + single_32 = lm_singles32[:], + ranges_32 = lm_ranges32[:], +} + +@(rodata) +lo_singles16 := [?]u16{ + 0x00AA, 0x00BA, 0x01BB, 0x06D5, 0x06FF, 0x0710, 0x07B1, 0x093D, + 0x0950, 0x09B2, 0x09BD, 0x09CE, 0x09FC, 0x0A5E, 0x0ABD, 0x0AD0, + 0x0AF9, 0x0B3D, 0x0B71, 0x0B83, 0x0B9C, 0x0BD0, 0x0C3D, 0x0C80, + 0x0CBD, 0x0D3D, 0x0D4E, 0x0DBD, 0x0E84, 0x0EA5, 0x0EBD, 0x0F00, + 0x103F, 0x1061, 0x108E, 0x1258, 0x12C0, 0x17DC, 0x18AA, 0x1CFA, + 0x3006, 0x303C, 0x309F, 0x30FF, 0xA66E, 0xA78F, 0xA7F7, 0xA8FB, + 0xAA7A, 0xAAB1, 0xAAC0, 0xAAC2, 0xAAF2, 0xFB1D, 0xFB3E, +} + +@(rodata) +lo_ranges16 := [?]u16{ + 0x01C0, 0x01C3, + 0x0294, 0x0295, + 0x05D0, 0x05EA, + 0x05EF, 0x05F2, + 0x0620, 0x063F, + 0x0641, 0x064A, + 0x066E, 0x066F, + 0x0671, 0x06D3, + 0x06EE, 0x06EF, + 0x06FA, 0x06FC, + 0x0712, 0x072F, + 0x074D, 0x07A5, + 0x07CA, 0x07EA, + 0x0800, 0x0815, + 0x0840, 0x0858, + 0x0860, 0x086A, + 0x0870, 0x0887, + 0x0889, 0x088F, + 0x08A0, 0x08C8, + 0x0904, 0x0939, + 0x0958, 0x0961, + 0x0972, 0x0980, + 0x0985, 0x098C, + 0x098F, 0x0990, + 0x0993, 0x09A8, + 0x09AA, 0x09B0, + 0x09B6, 0x09B9, + 0x09DC, 0x09DD, + 0x09DF, 0x09E1, + 0x09F0, 0x09F1, + 0x0A05, 0x0A0A, + 0x0A0F, 0x0A10, + 0x0A13, 0x0A28, + 0x0A2A, 0x0A30, + 0x0A32, 0x0A33, + 0x0A35, 0x0A36, + 0x0A38, 0x0A39, + 0x0A59, 0x0A5C, + 0x0A72, 0x0A74, + 0x0A85, 0x0A8D, + 0x0A8F, 0x0A91, + 0x0A93, 0x0AA8, + 0x0AAA, 0x0AB0, + 0x0AB2, 0x0AB3, + 0x0AB5, 0x0AB9, + 0x0AE0, 0x0AE1, + 0x0B05, 0x0B0C, + 0x0B0F, 0x0B10, + 0x0B13, 0x0B28, + 0x0B2A, 0x0B30, + 0x0B32, 0x0B33, + 0x0B35, 0x0B39, + 0x0B5C, 0x0B5D, + 0x0B5F, 0x0B61, + 0x0B85, 0x0B8A, + 0x0B8E, 0x0B90, + 0x0B92, 0x0B95, + 0x0B99, 0x0B9A, + 0x0B9E, 0x0B9F, + 0x0BA3, 0x0BA4, + 0x0BA8, 0x0BAA, + 0x0BAE, 0x0BB9, + 0x0C05, 0x0C0C, + 0x0C0E, 0x0C10, + 0x0C12, 0x0C28, + 0x0C2A, 0x0C39, + 0x0C58, 0x0C5A, + 0x0C5C, 0x0C5D, + 0x0C60, 0x0C61, + 0x0C85, 0x0C8C, + 0x0C8E, 0x0C90, + 0x0C92, 0x0CA8, + 0x0CAA, 0x0CB3, + 0x0CB5, 0x0CB9, + 0x0CDC, 0x0CDE, + 0x0CE0, 0x0CE1, + 0x0CF1, 0x0CF2, + 0x0D04, 0x0D0C, + 0x0D0E, 0x0D10, + 0x0D12, 0x0D3A, + 0x0D54, 0x0D56, + 0x0D5F, 0x0D61, + 0x0D7A, 0x0D7F, + 0x0D85, 0x0D96, + 0x0D9A, 0x0DB1, + 0x0DB3, 0x0DBB, + 0x0DC0, 0x0DC6, + 0x0E01, 0x0E30, + 0x0E32, 0x0E33, + 0x0E40, 0x0E45, + 0x0E81, 0x0E82, + 0x0E86, 0x0E8A, + 0x0E8C, 0x0EA3, + 0x0EA7, 0x0EB0, + 0x0EB2, 0x0EB3, + 0x0EC0, 0x0EC4, + 0x0EDC, 0x0EDF, + 0x0F40, 0x0F47, + 0x0F49, 0x0F6C, + 0x0F88, 0x0F8C, + 0x1000, 0x102A, + 0x1050, 0x1055, + 0x105A, 0x105D, + 0x1065, 0x1066, + 0x106E, 0x1070, + 0x1075, 0x1081, + 0x1100, 0x1248, + 0x124A, 0x124D, + 0x1250, 0x1256, + 0x125A, 0x125D, + 0x1260, 0x1288, + 0x128A, 0x128D, + 0x1290, 0x12B0, + 0x12B2, 0x12B5, + 0x12B8, 0x12BE, + 0x12C2, 0x12C5, + 0x12C8, 0x12D6, + 0x12D8, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x135A, + 0x1380, 0x138F, + 0x1401, 0x166C, + 0x166F, 0x167F, + 0x1681, 0x169A, + 0x16A0, 0x16EA, + 0x16F1, 0x16F8, + 0x1700, 0x1711, + 0x171F, 0x1731, + 0x1740, 0x1751, + 0x1760, 0x176C, + 0x176E, 0x1770, + 0x1780, 0x17B3, + 0x1820, 0x1842, + 0x1844, 0x1878, + 0x1880, 0x1884, + 0x1887, 0x18A8, + 0x18B0, 0x18F5, + 0x1900, 0x191E, + 0x1950, 0x196D, + 0x1970, 0x1974, + 0x1980, 0x19AB, + 0x19B0, 0x19C9, + 0x1A00, 0x1A16, + 0x1A20, 0x1A54, + 0x1B05, 0x1B33, + 0x1B45, 0x1B4C, + 0x1B83, 0x1BA0, + 0x1BAE, 0x1BAF, + 0x1BBA, 0x1BE5, + 0x1C00, 0x1C23, + 0x1C4D, 0x1C4F, + 0x1C5A, 0x1C77, + 0x1CE9, 0x1CEC, + 0x1CEE, 0x1CF3, + 0x1CF5, 0x1CF6, + 0x2135, 0x2138, + 0x2D30, 0x2D67, + 0x2D80, 0x2D96, + 0x2DA0, 0x2DA6, + 0x2DA8, 0x2DAE, + 0x2DB0, 0x2DB6, + 0x2DB8, 0x2DBE, + 0x2DC0, 0x2DC6, + 0x2DC8, 0x2DCE, + 0x2DD0, 0x2DD6, + 0x2DD8, 0x2DDE, + 0x3041, 0x3096, + 0x30A1, 0x30FA, + 0x3105, 0x312F, + 0x3131, 0x318E, + 0x31A0, 0x31BF, + 0x31F0, 0x31FF, + 0x3400, 0x4DBF, + 0x4E00, 0x9FFF, + 0xA000, 0xA014, + 0xA016, 0xA48C, + 0xA4D0, 0xA4F7, + 0xA500, 0xA60B, + 0xA610, 0xA61F, + 0xA62A, 0xA62B, + 0xA6A0, 0xA6E5, + 0xA7FB, 0xA801, + 0xA803, 0xA805, + 0xA807, 0xA80A, + 0xA80C, 0xA822, + 0xA840, 0xA873, + 0xA882, 0xA8B3, + 0xA8F2, 0xA8F7, + 0xA8FD, 0xA8FE, + 0xA90A, 0xA925, + 0xA930, 0xA946, + 0xA960, 0xA97C, + 0xA984, 0xA9B2, + 0xA9E0, 0xA9E4, + 0xA9E7, 0xA9EF, + 0xA9FA, 0xA9FE, + 0xAA00, 0xAA28, + 0xAA40, 0xAA42, + 0xAA44, 0xAA4B, + 0xAA60, 0xAA6F, + 0xAA71, 0xAA76, + 0xAA7E, 0xAAAF, + 0xAAB5, 0xAAB6, + 0xAAB9, 0xAABD, + 0xAADB, 0xAADC, + 0xAAE0, 0xAAEA, + 0xAB01, 0xAB06, + 0xAB09, 0xAB0E, + 0xAB11, 0xAB16, + 0xAB20, 0xAB26, + 0xAB28, 0xAB2E, + 0xABC0, 0xABE2, + 0xAC00, 0xD7A3, + 0xD7B0, 0xD7C6, + 0xD7CB, 0xD7FB, + 0xF900, 0xFA6D, + 0xFA70, 0xFAD9, + 0xFB1F, 0xFB28, + 0xFB2A, 0xFB36, + 0xFB38, 0xFB3C, + 0xFB40, 0xFB41, + 0xFB43, 0xFB44, + 0xFB46, 0xFBB1, + 0xFBD3, 0xFD3D, + 0xFD50, 0xFD8F, + 0xFD92, 0xFDC7, + 0xFDF0, 0xFDFB, + 0xFE70, 0xFE74, + 0xFE76, 0xFEFC, + 0xFF66, 0xFF6F, + 0xFF71, 0xFF9D, + 0xFFA0, 0xFFBE, + 0xFFC2, 0xFFC7, + 0xFFCA, 0xFFCF, + 0xFFD2, 0xFFD7, + 0xFFDA, 0xFFDC, +} + +@(rodata) +lo_singles32 := [?]i32{ + 0x10808, 0x1083C, 0x10A00, 0x10D4F, 0x10F27, 0x11075, 0x11144, 0x11147, + 0x11176, 0x111DA, 0x111DC, 0x11288, 0x1133D, 0x11350, 0x1138B, 0x1138E, + 0x113B7, 0x113D1, 0x113D3, 0x114C7, 0x11644, 0x116B8, 0x11909, 0x1193F, + 0x11941, 0x119E1, 0x119E3, 0x11A00, 0x11A3A, 0x11A50, 0x11A9D, 0x11C40, + 0x11D46, 0x11D98, 0x11F02, 0x11FB0, 0x16F50, 0x18CFF, 0x1B132, 0x1B155, + 0x1DF0A, 0x1E14E, 0x1E5F0, 0x1E6FE, 0x1EE24, 0x1EE27, 0x1EE39, 0x1EE3B, + 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, + 0x1EE5D, 0x1EE5F, 0x1EE64, 0x1EE7E, +} + +@(rodata) +lo_ranges32 := [?]i32{ + 0x10000, 0x1000B, + 0x1000D, 0x10026, + 0x10028, 0x1003A, + 0x1003C, 0x1003D, + 0x1003F, 0x1004D, + 0x10050, 0x1005D, + 0x10080, 0x100FA, + 0x10280, 0x1029C, + 0x102A0, 0x102D0, + 0x10300, 0x1031F, + 0x1032D, 0x10340, + 0x10342, 0x10349, + 0x10350, 0x10375, + 0x10380, 0x1039D, + 0x103A0, 0x103C3, + 0x103C8, 0x103CF, + 0x10450, 0x1049D, + 0x10500, 0x10527, + 0x10530, 0x10563, + 0x105C0, 0x105F3, + 0x10600, 0x10736, + 0x10740, 0x10755, + 0x10760, 0x10767, + 0x10800, 0x10805, + 0x1080A, 0x10835, + 0x10837, 0x10838, + 0x1083F, 0x10855, + 0x10860, 0x10876, + 0x10880, 0x1089E, + 0x108E0, 0x108F2, + 0x108F4, 0x108F5, + 0x10900, 0x10915, + 0x10920, 0x10939, + 0x10940, 0x10959, + 0x10980, 0x109B7, + 0x109BE, 0x109BF, + 0x10A10, 0x10A13, + 0x10A15, 0x10A17, + 0x10A19, 0x10A35, + 0x10A60, 0x10A7C, + 0x10A80, 0x10A9C, + 0x10AC0, 0x10AC7, + 0x10AC9, 0x10AE4, + 0x10B00, 0x10B35, + 0x10B40, 0x10B55, + 0x10B60, 0x10B72, + 0x10B80, 0x10B91, + 0x10C00, 0x10C48, + 0x10D00, 0x10D23, + 0x10D4A, 0x10D4D, + 0x10E80, 0x10EA9, + 0x10EB0, 0x10EB1, + 0x10EC2, 0x10EC4, + 0x10EC6, 0x10EC7, + 0x10F00, 0x10F1C, + 0x10F30, 0x10F45, + 0x10F70, 0x10F81, + 0x10FB0, 0x10FC4, + 0x10FE0, 0x10FF6, + 0x11003, 0x11037, + 0x11071, 0x11072, + 0x11083, 0x110AF, + 0x110D0, 0x110E8, + 0x11103, 0x11126, + 0x11150, 0x11172, + 0x11183, 0x111B2, + 0x111C1, 0x111C4, + 0x11200, 0x11211, + 0x11213, 0x1122B, + 0x1123F, 0x11240, + 0x11280, 0x11286, + 0x1128A, 0x1128D, + 0x1128F, 0x1129D, + 0x1129F, 0x112A8, + 0x112B0, 0x112DE, + 0x11305, 0x1130C, + 0x1130F, 0x11310, + 0x11313, 0x11328, + 0x1132A, 0x11330, + 0x11332, 0x11333, + 0x11335, 0x11339, + 0x1135D, 0x11361, + 0x11380, 0x11389, + 0x11390, 0x113B5, + 0x11400, 0x11434, + 0x11447, 0x1144A, + 0x1145F, 0x11461, + 0x11480, 0x114AF, + 0x114C4, 0x114C5, + 0x11580, 0x115AE, + 0x115D8, 0x115DB, + 0x11600, 0x1162F, + 0x11680, 0x116AA, + 0x11700, 0x1171A, + 0x11740, 0x11746, + 0x11800, 0x1182B, + 0x118FF, 0x11906, + 0x1190C, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x1192F, + 0x119A0, 0x119A7, + 0x119AA, 0x119D0, + 0x11A0B, 0x11A32, + 0x11A5C, 0x11A89, + 0x11AB0, 0x11AF8, + 0x11BC0, 0x11BE0, + 0x11C00, 0x11C08, + 0x11C0A, 0x11C2E, + 0x11C72, 0x11C8F, + 0x11D00, 0x11D06, + 0x11D08, 0x11D09, + 0x11D0B, 0x11D30, + 0x11D60, 0x11D65, + 0x11D67, 0x11D68, + 0x11D6A, 0x11D89, + 0x11DB0, 0x11DD8, + 0x11DDA, 0x11DDB, + 0x11EE0, 0x11EF2, + 0x11F04, 0x11F10, + 0x11F12, 0x11F33, + 0x12000, 0x12399, + 0x12480, 0x12543, + 0x12F90, 0x12FF0, + 0x13000, 0x1342F, + 0x13441, 0x13446, + 0x13460, 0x143FA, + 0x14400, 0x14646, + 0x16100, 0x1611D, + 0x16800, 0x16A38, + 0x16A40, 0x16A5E, + 0x16A70, 0x16ABE, + 0x16AD0, 0x16AED, + 0x16B00, 0x16B2F, + 0x16B63, 0x16B77, + 0x16B7D, 0x16B8F, + 0x16D43, 0x16D6A, + 0x16F00, 0x16F4A, + 0x17000, 0x187FF, + 0x18800, 0x18CD5, + 0x18D00, 0x18D1E, + 0x18D80, 0x18DF2, + 0x1B000, 0x1B122, + 0x1B150, 0x1B152, + 0x1B164, 0x1B167, + 0x1B170, 0x1B2FB, + 0x1BC00, 0x1BC6A, + 0x1BC70, 0x1BC7C, + 0x1BC80, 0x1BC88, + 0x1BC90, 0x1BC99, + 0x1E100, 0x1E12C, + 0x1E290, 0x1E2AD, + 0x1E2C0, 0x1E2EB, + 0x1E4D0, 0x1E4EA, + 0x1E5D0, 0x1E5ED, + 0x1E6C0, 0x1E6DE, + 0x1E6E0, 0x1E6E2, + 0x1E6E4, 0x1E6E5, + 0x1E6E7, 0x1E6ED, + 0x1E6F0, 0x1E6F4, + 0x1E7E0, 0x1E7E6, + 0x1E7E8, 0x1E7EB, + 0x1E7ED, 0x1E7EE, + 0x1E7F0, 0x1E7FE, + 0x1E800, 0x1E8C4, + 0x1EE00, 0x1EE03, + 0x1EE05, 0x1EE1F, + 0x1EE21, 0x1EE22, + 0x1EE29, 0x1EE32, + 0x1EE34, 0x1EE37, + 0x1EE4D, 0x1EE4F, + 0x1EE51, 0x1EE52, + 0x1EE61, 0x1EE62, + 0x1EE67, 0x1EE6A, + 0x1EE6C, 0x1EE72, + 0x1EE74, 0x1EE77, + 0x1EE79, 0x1EE7C, + 0x1EE80, 0x1EE89, + 0x1EE8B, 0x1EE9B, + 0x1EEA1, 0x1EEA3, + 0x1EEA5, 0x1EEA9, + 0x1EEAB, 0x1EEBB, + 0x20000, 0x2A6DF, + 0x2A700, 0x2B73F, + 0x2B740, 0x2B81D, + 0x2B820, 0x2CEAD, + 0x2CEB0, 0x2EBE0, + 0x2EBF0, 0x2EE5D, + 0x2F800, 0x2FA1D, + 0x30000, 0x3134A, + 0x31350, 0x323AF, + 0x323B0, 0x33479, +} + +lo_ranges := Range{ + single_16 = lo_singles16[:], + ranges_16 = lo_ranges16[:], + single_32 = lo_singles32[:], + ranges_32 = lo_ranges32[:], +} + +@(rodata) +lt_singles16 := [?]u16{ + 0x01C5, 0x01C8, 0x01CB, 0x01F2, 0x1FBC, 0x1FCC, 0x1FFC, +} + +@(rodata) +lt_ranges16 := [?]u16{ + 0x1F88, 0x1F8F, + 0x1F98, 0x1F9F, + 0x1FA8, 0x1FAF, +} + +lt_ranges := Range{ + single_16 = lt_singles16[:], + ranges_16 = lt_ranges16[:], +} + +@(rodata) +lu_singles16 := [?]u16{ + 0x0100, 0x0102, 0x0104, 0x0106, 0x0108, 0x010A, 0x010C, 0x010E, + 0x0110, 0x0112, 0x0114, 0x0116, 0x0118, 0x011A, 0x011C, 0x011E, + 0x0120, 0x0122, 0x0124, 0x0126, 0x0128, 0x012A, 0x012C, 0x012E, + 0x0130, 0x0132, 0x0134, 0x0136, 0x0139, 0x013B, 0x013D, 0x013F, + 0x0141, 0x0143, 0x0145, 0x0147, 0x014A, 0x014C, 0x014E, 0x0150, + 0x0152, 0x0154, 0x0156, 0x0158, 0x015A, 0x015C, 0x015E, 0x0160, + 0x0162, 0x0164, 0x0166, 0x0168, 0x016A, 0x016C, 0x016E, 0x0170, + 0x0172, 0x0174, 0x0176, 0x017B, 0x017D, 0x0184, 0x01A2, 0x01A4, + 0x01A9, 0x01AC, 0x01B5, 0x01BC, 0x01C4, 0x01C7, 0x01CA, 0x01CD, + 0x01CF, 0x01D1, 0x01D3, 0x01D5, 0x01D7, 0x01D9, 0x01DB, 0x01DE, + 0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E8, 0x01EA, 0x01EC, 0x01EE, + 0x01F1, 0x01F4, 0x01FA, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204, + 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, 0x0210, 0x0212, 0x0214, + 0x0216, 0x0218, 0x021A, 0x021C, 0x021E, 0x0220, 0x0222, 0x0224, + 0x0226, 0x0228, 0x022A, 0x022C, 0x022E, 0x0230, 0x0232, 0x0241, + 0x0248, 0x024A, 0x024C, 0x024E, 0x0370, 0x0372, 0x0376, 0x037F, + 0x0386, 0x038C, 0x03CF, 0x03D8, 0x03DA, 0x03DC, 0x03DE, 0x03E0, + 0x03E2, 0x03E4, 0x03E6, 0x03E8, 0x03EA, 0x03EC, 0x03EE, 0x03F4, + 0x03F7, 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, + 0x046E, 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x047C, + 0x047E, 0x0480, 0x048A, 0x048C, 0x048E, 0x0490, 0x0492, 0x0494, + 0x0496, 0x0498, 0x049A, 0x049C, 0x049E, 0x04A0, 0x04A2, 0x04A4, + 0x04A6, 0x04A8, 0x04AA, 0x04AC, 0x04AE, 0x04B0, 0x04B2, 0x04B4, + 0x04B6, 0x04B8, 0x04BA, 0x04BC, 0x04BE, 0x04C3, 0x04C5, 0x04C7, + 0x04C9, 0x04CB, 0x04CD, 0x04D0, 0x04D2, 0x04D4, 0x04D6, 0x04D8, + 0x04DA, 0x04DC, 0x04DE, 0x04E0, 0x04E2, 0x04E4, 0x04E6, 0x04E8, + 0x04EA, 0x04EC, 0x04EE, 0x04F0, 0x04F2, 0x04F4, 0x04F6, 0x04F8, + 0x04FA, 0x04FC, 0x04FE, 0x0500, 0x0502, 0x0504, 0x0506, 0x0508, + 0x050A, 0x050C, 0x050E, 0x0510, 0x0512, 0x0514, 0x0516, 0x0518, + 0x051A, 0x051C, 0x051E, 0x0520, 0x0522, 0x0524, 0x0526, 0x0528, + 0x052A, 0x052C, 0x052E, 0x10C7, 0x10CD, 0x1C89, 0x1E00, 0x1E02, + 0x1E04, 0x1E06, 0x1E08, 0x1E0A, 0x1E0C, 0x1E0E, 0x1E10, 0x1E12, + 0x1E14, 0x1E16, 0x1E18, 0x1E1A, 0x1E1C, 0x1E1E, 0x1E20, 0x1E22, + 0x1E24, 0x1E26, 0x1E28, 0x1E2A, 0x1E2C, 0x1E2E, 0x1E30, 0x1E32, + 0x1E34, 0x1E36, 0x1E38, 0x1E3A, 0x1E3C, 0x1E3E, 0x1E40, 0x1E42, + 0x1E44, 0x1E46, 0x1E48, 0x1E4A, 0x1E4C, 0x1E4E, 0x1E50, 0x1E52, + 0x1E54, 0x1E56, 0x1E58, 0x1E5A, 0x1E5C, 0x1E5E, 0x1E60, 0x1E62, + 0x1E64, 0x1E66, 0x1E68, 0x1E6A, 0x1E6C, 0x1E6E, 0x1E70, 0x1E72, + 0x1E74, 0x1E76, 0x1E78, 0x1E7A, 0x1E7C, 0x1E7E, 0x1E80, 0x1E82, + 0x1E84, 0x1E86, 0x1E88, 0x1E8A, 0x1E8C, 0x1E8E, 0x1E90, 0x1E92, + 0x1E94, 0x1E9E, 0x1EA0, 0x1EA2, 0x1EA4, 0x1EA6, 0x1EA8, 0x1EAA, + 0x1EAC, 0x1EAE, 0x1EB0, 0x1EB2, 0x1EB4, 0x1EB6, 0x1EB8, 0x1EBA, + 0x1EBC, 0x1EBE, 0x1EC0, 0x1EC2, 0x1EC4, 0x1EC6, 0x1EC8, 0x1ECA, + 0x1ECC, 0x1ECE, 0x1ED0, 0x1ED2, 0x1ED4, 0x1ED6, 0x1ED8, 0x1EDA, + 0x1EDC, 0x1EDE, 0x1EE0, 0x1EE2, 0x1EE4, 0x1EE6, 0x1EE8, 0x1EEA, + 0x1EEC, 0x1EEE, 0x1EF0, 0x1EF2, 0x1EF4, 0x1EF6, 0x1EF8, 0x1EFA, + 0x1EFC, 0x1EFE, 0x1F59, 0x1F5B, 0x1F5D, 0x1F5F, 0x2102, 0x2107, + 0x2115, 0x2124, 0x2126, 0x2128, 0x2145, 0x2183, 0x2C60, 0x2C67, + 0x2C69, 0x2C6B, 0x2C72, 0x2C75, 0x2C82, 0x2C84, 0x2C86, 0x2C88, + 0x2C8A, 0x2C8C, 0x2C8E, 0x2C90, 0x2C92, 0x2C94, 0x2C96, 0x2C98, + 0x2C9A, 0x2C9C, 0x2C9E, 0x2CA0, 0x2CA2, 0x2CA4, 0x2CA6, 0x2CA8, + 0x2CAA, 0x2CAC, 0x2CAE, 0x2CB0, 0x2CB2, 0x2CB4, 0x2CB6, 0x2CB8, + 0x2CBA, 0x2CBC, 0x2CBE, 0x2CC0, 0x2CC2, 0x2CC4, 0x2CC6, 0x2CC8, + 0x2CCA, 0x2CCC, 0x2CCE, 0x2CD0, 0x2CD2, 0x2CD4, 0x2CD6, 0x2CD8, + 0x2CDA, 0x2CDC, 0x2CDE, 0x2CE0, 0x2CE2, 0x2CEB, 0x2CED, 0x2CF2, + 0xA640, 0xA642, 0xA644, 0xA646, 0xA648, 0xA64A, 0xA64C, 0xA64E, + 0xA650, 0xA652, 0xA654, 0xA656, 0xA658, 0xA65A, 0xA65C, 0xA65E, + 0xA660, 0xA662, 0xA664, 0xA666, 0xA668, 0xA66A, 0xA66C, 0xA680, + 0xA682, 0xA684, 0xA686, 0xA688, 0xA68A, 0xA68C, 0xA68E, 0xA690, + 0xA692, 0xA694, 0xA696, 0xA698, 0xA69A, 0xA722, 0xA724, 0xA726, + 0xA728, 0xA72A, 0xA72C, 0xA72E, 0xA732, 0xA734, 0xA736, 0xA738, + 0xA73A, 0xA73C, 0xA73E, 0xA740, 0xA742, 0xA744, 0xA746, 0xA748, + 0xA74A, 0xA74C, 0xA74E, 0xA750, 0xA752, 0xA754, 0xA756, 0xA758, + 0xA75A, 0xA75C, 0xA75E, 0xA760, 0xA762, 0xA764, 0xA766, 0xA768, + 0xA76A, 0xA76C, 0xA76E, 0xA779, 0xA77B, 0xA780, 0xA782, 0xA784, + 0xA786, 0xA78B, 0xA78D, 0xA790, 0xA792, 0xA796, 0xA798, 0xA79A, + 0xA79C, 0xA79E, 0xA7A0, 0xA7A2, 0xA7A4, 0xA7A6, 0xA7A8, 0xA7B6, + 0xA7B8, 0xA7BA, 0xA7BC, 0xA7BE, 0xA7C0, 0xA7C2, 0xA7C9, 0xA7CE, + 0xA7D0, 0xA7D2, 0xA7D4, 0xA7D6, 0xA7D8, 0xA7DA, 0xA7DC, 0xA7F5, +} + +@(rodata) +lu_ranges16 := [?]u16{ + 0x0041, 0x005A, + 0x00C0, 0x00D6, + 0x00D8, 0x00DE, + 0x0178, 0x0179, + 0x0181, 0x0182, + 0x0186, 0x0187, + 0x0189, 0x018B, + 0x018E, 0x0191, + 0x0193, 0x0194, + 0x0196, 0x0198, + 0x019C, 0x019D, + 0x019F, 0x01A0, + 0x01A6, 0x01A7, + 0x01AE, 0x01AF, + 0x01B1, 0x01B3, + 0x01B7, 0x01B8, + 0x01F6, 0x01F8, + 0x023A, 0x023B, + 0x023D, 0x023E, + 0x0243, 0x0246, + 0x0388, 0x038A, + 0x038E, 0x038F, + 0x0391, 0x03A1, + 0x03A3, 0x03AB, + 0x03D2, 0x03D4, + 0x03F9, 0x03FA, + 0x03FD, 0x042F, + 0x04C0, 0x04C1, + 0x0531, 0x0556, + 0x10A0, 0x10C5, + 0x13A0, 0x13F5, + 0x1C90, 0x1CBA, + 0x1CBD, 0x1CBF, + 0x1F08, 0x1F0F, + 0x1F18, 0x1F1D, + 0x1F28, 0x1F2F, + 0x1F38, 0x1F3F, + 0x1F48, 0x1F4D, + 0x1F68, 0x1F6F, + 0x1FB8, 0x1FBB, + 0x1FC8, 0x1FCB, + 0x1FD8, 0x1FDB, + 0x1FE8, 0x1FEC, + 0x1FF8, 0x1FFB, + 0x210B, 0x210D, + 0x2110, 0x2112, + 0x2119, 0x211D, + 0x212A, 0x212D, + 0x2130, 0x2133, + 0x213E, 0x213F, + 0x2C00, 0x2C2F, + 0x2C62, 0x2C64, + 0x2C6D, 0x2C70, + 0x2C7E, 0x2C80, + 0xA77D, 0xA77E, + 0xA7AA, 0xA7AE, + 0xA7B0, 0xA7B4, + 0xA7C4, 0xA7C7, + 0xA7CB, 0xA7CC, + 0xFF21, 0xFF3A, +} + +@(rodata) +lu_singles32 := [?]i32{ + 0x1D49C, 0x1D4A2, 0x1D546, 0x1D7CA, +} + +@(rodata) +lu_ranges32 := [?]i32{ + 0x10400, 0x10427, + 0x104B0, 0x104D3, + 0x10570, 0x1057A, + 0x1057C, 0x1058A, + 0x1058C, 0x10592, + 0x10594, 0x10595, + 0x10C80, 0x10CB2, + 0x10D50, 0x10D65, + 0x118A0, 0x118BF, + 0x16E40, 0x16E5F, + 0x16EA0, 0x16EB8, + 0x1D400, 0x1D419, + 0x1D434, 0x1D44D, + 0x1D468, 0x1D481, + 0x1D49E, 0x1D49F, + 0x1D4A5, 0x1D4A6, + 0x1D4A9, 0x1D4AC, + 0x1D4AE, 0x1D4B5, + 0x1D4D0, 0x1D4E9, + 0x1D504, 0x1D505, + 0x1D507, 0x1D50A, + 0x1D50D, 0x1D514, + 0x1D516, 0x1D51C, + 0x1D538, 0x1D539, + 0x1D53B, 0x1D53E, + 0x1D540, 0x1D544, + 0x1D54A, 0x1D550, + 0x1D56C, 0x1D585, + 0x1D5A0, 0x1D5B9, + 0x1D5D4, 0x1D5ED, + 0x1D608, 0x1D621, + 0x1D63C, 0x1D655, + 0x1D670, 0x1D689, + 0x1D6A8, 0x1D6C0, + 0x1D6E2, 0x1D6FA, + 0x1D71C, 0x1D734, + 0x1D756, 0x1D76E, + 0x1D790, 0x1D7A8, + 0x1E900, 0x1E921, +} + +lu_ranges := Range{ + single_16 = lu_singles16[:], + ranges_16 = lu_ranges16[:], + single_32 = lu_singles32[:], + ranges_32 = lu_ranges32[:], +} + +@(rodata) +mc_singles16 := [?]u16{ + 0x0903, 0x093B, 0x09D7, 0x0A03, 0x0A83, 0x0AC9, 0x0B3E, 0x0B40, + 0x0B57, 0x0BD7, 0x0CBE, 0x0CF3, 0x0D57, 0x0F7F, 0x1031, 0x1038, + 0x108F, 0x1715, 0x1734, 0x17B6, 0x1A55, 0x1A57, 0x1A61, 0x1B04, + 0x1B35, 0x1B3B, 0x1B82, 0x1BA1, 0x1BAA, 0x1BE7, 0x1BEE, 0x1CE1, + 0x1CF7, 0xA827, 0xA983, 0xAA4D, 0xAA7B, 0xAA7D, 0xAAEB, 0xAAF5, + 0xABEC, +} + +@(rodata) +mc_ranges16 := [?]u16{ + 0x093E, 0x0940, + 0x0949, 0x094C, + 0x094E, 0x094F, + 0x0982, 0x0983, + 0x09BE, 0x09C0, + 0x09C7, 0x09C8, + 0x09CB, 0x09CC, + 0x0A3E, 0x0A40, + 0x0ABE, 0x0AC0, + 0x0ACB, 0x0ACC, + 0x0B02, 0x0B03, + 0x0B47, 0x0B48, + 0x0B4B, 0x0B4C, + 0x0BBE, 0x0BBF, + 0x0BC1, 0x0BC2, + 0x0BC6, 0x0BC8, + 0x0BCA, 0x0BCC, + 0x0C01, 0x0C03, + 0x0C41, 0x0C44, + 0x0C82, 0x0C83, + 0x0CC0, 0x0CC4, + 0x0CC7, 0x0CC8, + 0x0CCA, 0x0CCB, + 0x0CD5, 0x0CD6, + 0x0D02, 0x0D03, + 0x0D3E, 0x0D40, + 0x0D46, 0x0D48, + 0x0D4A, 0x0D4C, + 0x0D82, 0x0D83, + 0x0DCF, 0x0DD1, + 0x0DD8, 0x0DDF, + 0x0DF2, 0x0DF3, + 0x0F3E, 0x0F3F, + 0x102B, 0x102C, + 0x103B, 0x103C, + 0x1056, 0x1057, + 0x1062, 0x1064, + 0x1067, 0x106D, + 0x1083, 0x1084, + 0x1087, 0x108C, + 0x109A, 0x109C, + 0x17BE, 0x17C5, + 0x17C7, 0x17C8, + 0x1923, 0x1926, + 0x1929, 0x192B, + 0x1930, 0x1931, + 0x1933, 0x1938, + 0x1A19, 0x1A1A, + 0x1A63, 0x1A64, + 0x1A6D, 0x1A72, + 0x1B3D, 0x1B41, + 0x1B43, 0x1B44, + 0x1BA6, 0x1BA7, + 0x1BEA, 0x1BEC, + 0x1BF2, 0x1BF3, + 0x1C24, 0x1C2B, + 0x1C34, 0x1C35, + 0x302E, 0x302F, + 0xA823, 0xA824, + 0xA880, 0xA881, + 0xA8B4, 0xA8C3, + 0xA952, 0xA953, + 0xA9B4, 0xA9B5, + 0xA9BA, 0xA9BB, + 0xA9BE, 0xA9C0, + 0xAA2F, 0xAA30, + 0xAA33, 0xAA34, + 0xAAEE, 0xAAEF, + 0xABE3, 0xABE4, + 0xABE6, 0xABE7, + 0xABE9, 0xABEA, +} + +@(rodata) +mc_singles32 := [?]i32{ + 0x11000, 0x11002, 0x11082, 0x1112C, 0x11182, 0x111CE, 0x11235, 0x11357, + 0x113C2, 0x113C5, 0x113CF, 0x11445, 0x114B9, 0x114C1, 0x115BE, 0x1163E, + 0x116AC, 0x116B6, 0x1171E, 0x11726, 0x11838, 0x1193D, 0x11940, 0x11942, + 0x119E4, 0x11A39, 0x11A97, 0x11B61, 0x11B65, 0x11B67, 0x11C2F, 0x11C3E, + 0x11CA9, 0x11CB1, 0x11CB4, 0x11D96, 0x11F03, 0x11F41, +} + +@(rodata) +mc_ranges32 := [?]i32{ + 0x110B0, 0x110B2, + 0x110B7, 0x110B8, + 0x11145, 0x11146, + 0x111B3, 0x111B5, + 0x111BF, 0x111C0, + 0x1122C, 0x1122E, + 0x11232, 0x11233, + 0x112E0, 0x112E2, + 0x11302, 0x11303, + 0x1133E, 0x1133F, + 0x11341, 0x11344, + 0x11347, 0x11348, + 0x1134B, 0x1134D, + 0x11362, 0x11363, + 0x113B8, 0x113BA, + 0x113C7, 0x113CA, + 0x113CC, 0x113CD, + 0x11435, 0x11437, + 0x11440, 0x11441, + 0x114B0, 0x114B2, + 0x114BB, 0x114BE, + 0x115AF, 0x115B1, + 0x115B8, 0x115BB, + 0x11630, 0x11632, + 0x1163B, 0x1163C, + 0x116AE, 0x116AF, + 0x11720, 0x11721, + 0x1182C, 0x1182E, + 0x11930, 0x11935, + 0x11937, 0x11938, + 0x119D1, 0x119D3, + 0x119DC, 0x119DF, + 0x11A57, 0x11A58, + 0x11D8A, 0x11D8E, + 0x11D93, 0x11D94, + 0x11EF5, 0x11EF6, + 0x11F34, 0x11F35, + 0x11F3E, 0x11F3F, + 0x1612A, 0x1612C, + 0x16F51, 0x16F87, + 0x16FF0, 0x16FF1, + 0x1D165, 0x1D166, + 0x1D16D, 0x1D172, +} + +mc_ranges := Range{ + single_16 = mc_singles16[:], + ranges_16 = mc_ranges16[:], + single_32 = mc_singles32[:], + ranges_32 = mc_ranges32[:], +} + +@(rodata) +me_singles16 := [?]u16{ + 0x1ABE, +} + +@(rodata) +me_ranges16 := [?]u16{ + 0x0488, 0x0489, + 0x20DD, 0x20E0, + 0x20E2, 0x20E4, + 0xA670, 0xA672, +} + +me_ranges := Range{ + single_16 = me_singles16[:], + ranges_16 = me_ranges16[:], +} + +@(rodata) +mn_singles16 := [?]u16{ + 0x05BF, 0x05C7, 0x0670, 0x0711, 0x07FD, 0x093A, 0x093C, 0x094D, + 0x0981, 0x09BC, 0x09CD, 0x09FE, 0x0A3C, 0x0A51, 0x0A75, 0x0ABC, + 0x0ACD, 0x0B01, 0x0B3C, 0x0B3F, 0x0B4D, 0x0B82, 0x0BC0, 0x0BCD, + 0x0C00, 0x0C04, 0x0C3C, 0x0C81, 0x0CBC, 0x0CBF, 0x0CC6, 0x0D4D, + 0x0D81, 0x0DCA, 0x0DD6, 0x0E31, 0x0EB1, 0x0F35, 0x0F37, 0x0F39, + 0x0FC6, 0x1082, 0x108D, 0x109D, 0x17C6, 0x17DD, 0x180F, 0x18A9, + 0x1932, 0x1A1B, 0x1A56, 0x1A60, 0x1A62, 0x1A7F, 0x1B34, 0x1B3C, + 0x1B42, 0x1BE6, 0x1BED, 0x1CED, 0x1CF4, 0x20E1, 0x2D7F, 0xA66F, + 0xA802, 0xA806, 0xA80B, 0xA82C, 0xA8FF, 0xA9B3, 0xA9E5, 0xAA43, + 0xAA4C, 0xAA7C, 0xAAB0, 0xAAC1, 0xAAF6, 0xABE5, 0xABE8, 0xABED, + 0xFB1E, +} + +@(rodata) +mn_ranges16 := [?]u16{ + 0x0300, 0x036F, + 0x0483, 0x0487, + 0x0591, 0x05BD, + 0x05C1, 0x05C2, + 0x05C4, 0x05C5, + 0x0610, 0x061A, + 0x064B, 0x065F, + 0x06D6, 0x06DC, + 0x06DF, 0x06E4, + 0x06E7, 0x06E8, + 0x06EA, 0x06ED, + 0x0730, 0x074A, + 0x07A6, 0x07B0, + 0x07EB, 0x07F3, + 0x0816, 0x0819, + 0x081B, 0x0823, + 0x0825, 0x0827, + 0x0829, 0x082D, + 0x0859, 0x085B, + 0x0897, 0x089F, + 0x08CA, 0x08E1, + 0x08E3, 0x0902, + 0x0941, 0x0948, + 0x0951, 0x0957, + 0x0962, 0x0963, + 0x09C1, 0x09C4, + 0x09E2, 0x09E3, + 0x0A01, 0x0A02, + 0x0A41, 0x0A42, + 0x0A47, 0x0A48, + 0x0A4B, 0x0A4D, + 0x0A70, 0x0A71, + 0x0A81, 0x0A82, + 0x0AC1, 0x0AC5, + 0x0AC7, 0x0AC8, + 0x0AE2, 0x0AE3, + 0x0AFA, 0x0AFF, + 0x0B41, 0x0B44, + 0x0B55, 0x0B56, + 0x0B62, 0x0B63, + 0x0C3E, 0x0C40, + 0x0C46, 0x0C48, + 0x0C4A, 0x0C4D, + 0x0C55, 0x0C56, + 0x0C62, 0x0C63, + 0x0CCC, 0x0CCD, + 0x0CE2, 0x0CE3, + 0x0D00, 0x0D01, + 0x0D3B, 0x0D3C, + 0x0D41, 0x0D44, + 0x0D62, 0x0D63, + 0x0DD2, 0x0DD4, + 0x0E34, 0x0E3A, + 0x0E47, 0x0E4E, + 0x0EB4, 0x0EBC, + 0x0EC8, 0x0ECE, + 0x0F18, 0x0F19, + 0x0F71, 0x0F7E, + 0x0F80, 0x0F84, + 0x0F86, 0x0F87, + 0x0F8D, 0x0F97, + 0x0F99, 0x0FBC, + 0x102D, 0x1030, + 0x1032, 0x1037, + 0x1039, 0x103A, + 0x103D, 0x103E, + 0x1058, 0x1059, + 0x105E, 0x1060, + 0x1071, 0x1074, + 0x1085, 0x1086, + 0x135D, 0x135F, + 0x1712, 0x1714, + 0x1732, 0x1733, + 0x1752, 0x1753, + 0x1772, 0x1773, + 0x17B4, 0x17B5, + 0x17B7, 0x17BD, + 0x17C9, 0x17D3, + 0x180B, 0x180D, + 0x1885, 0x1886, + 0x1920, 0x1922, + 0x1927, 0x1928, + 0x1939, 0x193B, + 0x1A17, 0x1A18, + 0x1A58, 0x1A5E, + 0x1A65, 0x1A6C, + 0x1A73, 0x1A7C, + 0x1AB0, 0x1ABD, + 0x1ABF, 0x1ADD, + 0x1AE0, 0x1AEB, + 0x1B00, 0x1B03, + 0x1B36, 0x1B3A, + 0x1B6B, 0x1B73, + 0x1B80, 0x1B81, + 0x1BA2, 0x1BA5, + 0x1BA8, 0x1BA9, + 0x1BAB, 0x1BAD, + 0x1BE8, 0x1BE9, + 0x1BEF, 0x1BF1, + 0x1C2C, 0x1C33, + 0x1C36, 0x1C37, + 0x1CD0, 0x1CD2, + 0x1CD4, 0x1CE0, + 0x1CE2, 0x1CE8, + 0x1CF8, 0x1CF9, + 0x1DC0, 0x1DFF, + 0x20D0, 0x20DC, + 0x20E5, 0x20F0, + 0x2CEF, 0x2CF1, + 0x2DE0, 0x2DFF, + 0x302A, 0x302D, + 0x3099, 0x309A, + 0xA674, 0xA67D, + 0xA69E, 0xA69F, + 0xA6F0, 0xA6F1, + 0xA825, 0xA826, + 0xA8C4, 0xA8C5, + 0xA8E0, 0xA8F1, + 0xA926, 0xA92D, + 0xA947, 0xA951, + 0xA980, 0xA982, + 0xA9B6, 0xA9B9, + 0xA9BC, 0xA9BD, + 0xAA29, 0xAA2E, + 0xAA31, 0xAA32, + 0xAA35, 0xAA36, + 0xAAB2, 0xAAB4, + 0xAAB7, 0xAAB8, + 0xAABE, 0xAABF, + 0xAAEC, 0xAAED, + 0xFE00, 0xFE0F, + 0xFE20, 0xFE2F, +} + +@(rodata) +mn_singles32 := [?]i32{ + 0x101FD, 0x102E0, 0x10A3F, 0x11001, 0x11070, 0x110C2, 0x11173, 0x111CF, + 0x11234, 0x1123E, 0x11241, 0x112DF, 0x11340, 0x113CE, 0x113D0, 0x113D2, + 0x11446, 0x1145E, 0x114BA, 0x1163D, 0x116AB, 0x116AD, 0x116B7, 0x1171D, + 0x1171F, 0x1193E, 0x11943, 0x119E0, 0x11A47, 0x11B60, 0x11B66, 0x11C3F, + 0x11D3A, 0x11D47, 0x11D95, 0x11D97, 0x11F40, 0x11F42, 0x11F5A, 0x13440, + 0x16F4F, 0x16FE4, 0x1DA75, 0x1DA84, 0x1E08F, 0x1E2AE, 0x1E6E3, 0x1E6E6, + 0x1E6F5, +} + +@(rodata) +mn_ranges32 := [?]i32{ + 0x10376, 0x1037A, + 0x10A01, 0x10A03, + 0x10A05, 0x10A06, + 0x10A0C, 0x10A0F, + 0x10A38, 0x10A3A, + 0x10AE5, 0x10AE6, + 0x10D24, 0x10D27, + 0x10D69, 0x10D6D, + 0x10EAB, 0x10EAC, + 0x10EFA, 0x10EFF, + 0x10F46, 0x10F50, + 0x10F82, 0x10F85, + 0x11038, 0x11046, + 0x11073, 0x11074, + 0x1107F, 0x11081, + 0x110B3, 0x110B6, + 0x110B9, 0x110BA, + 0x11100, 0x11102, + 0x11127, 0x1112B, + 0x1112D, 0x11134, + 0x11180, 0x11181, + 0x111B6, 0x111BE, + 0x111C9, 0x111CC, + 0x1122F, 0x11231, + 0x11236, 0x11237, + 0x112E3, 0x112EA, + 0x11300, 0x11301, + 0x1133B, 0x1133C, + 0x11366, 0x1136C, + 0x11370, 0x11374, + 0x113BB, 0x113C0, + 0x113E1, 0x113E2, + 0x11438, 0x1143F, + 0x11442, 0x11444, + 0x114B3, 0x114B8, + 0x114BF, 0x114C0, + 0x114C2, 0x114C3, + 0x115B2, 0x115B5, + 0x115BC, 0x115BD, + 0x115BF, 0x115C0, + 0x115DC, 0x115DD, + 0x11633, 0x1163A, + 0x1163F, 0x11640, + 0x116B0, 0x116B5, + 0x11722, 0x11725, + 0x11727, 0x1172B, + 0x1182F, 0x11837, + 0x11839, 0x1183A, + 0x1193B, 0x1193C, + 0x119D4, 0x119D7, + 0x119DA, 0x119DB, + 0x11A01, 0x11A0A, + 0x11A33, 0x11A38, + 0x11A3B, 0x11A3E, + 0x11A51, 0x11A56, + 0x11A59, 0x11A5B, + 0x11A8A, 0x11A96, + 0x11A98, 0x11A99, + 0x11B62, 0x11B64, + 0x11C30, 0x11C36, + 0x11C38, 0x11C3D, + 0x11C92, 0x11CA7, + 0x11CAA, 0x11CB0, + 0x11CB2, 0x11CB3, + 0x11CB5, 0x11CB6, + 0x11D31, 0x11D36, + 0x11D3C, 0x11D3D, + 0x11D3F, 0x11D45, + 0x11D90, 0x11D91, + 0x11EF3, 0x11EF4, + 0x11F00, 0x11F01, + 0x11F36, 0x11F3A, + 0x13447, 0x13455, + 0x1611E, 0x16129, + 0x1612D, 0x1612F, + 0x16AF0, 0x16AF4, + 0x16B30, 0x16B36, + 0x16F8F, 0x16F92, + 0x1BC9D, 0x1BC9E, + 0x1CF00, 0x1CF2D, + 0x1CF30, 0x1CF46, + 0x1D167, 0x1D169, + 0x1D17B, 0x1D182, + 0x1D185, 0x1D18B, + 0x1D1AA, 0x1D1AD, + 0x1D242, 0x1D244, + 0x1DA00, 0x1DA36, + 0x1DA3B, 0x1DA6C, + 0x1DA9B, 0x1DA9F, + 0x1DAA1, 0x1DAAF, + 0x1E000, 0x1E006, + 0x1E008, 0x1E018, + 0x1E01B, 0x1E021, + 0x1E023, 0x1E024, + 0x1E026, 0x1E02A, + 0x1E130, 0x1E136, + 0x1E2EC, 0x1E2EF, + 0x1E4EC, 0x1E4EF, + 0x1E5EE, 0x1E5EF, + 0x1E6EE, 0x1E6EF, + 0x1E8D0, 0x1E8D6, + 0x1E944, 0x1E94A, + 0xE0100, 0xE01EF, +} + +mn_ranges := Range{ + single_16 = mn_singles16[:], + ranges_16 = mn_ranges16[:], + single_32 = mn_singles32[:], + ranges_32 = mn_ranges32[:], +} + +@(rodata) +nd_ranges16 := [?]u16{ + 0x0030, 0x0039, + 0x0660, 0x0669, + 0x06F0, 0x06F9, + 0x07C0, 0x07C9, + 0x0966, 0x096F, + 0x09E6, 0x09EF, + 0x0A66, 0x0A6F, + 0x0AE6, 0x0AEF, + 0x0B66, 0x0B6F, + 0x0BE6, 0x0BEF, + 0x0C66, 0x0C6F, + 0x0CE6, 0x0CEF, + 0x0D66, 0x0D6F, + 0x0DE6, 0x0DEF, + 0x0E50, 0x0E59, + 0x0ED0, 0x0ED9, + 0x0F20, 0x0F29, + 0x1040, 0x1049, + 0x1090, 0x1099, + 0x17E0, 0x17E9, + 0x1810, 0x1819, + 0x1946, 0x194F, + 0x19D0, 0x19D9, + 0x1A80, 0x1A89, + 0x1A90, 0x1A99, + 0x1B50, 0x1B59, + 0x1BB0, 0x1BB9, + 0x1C40, 0x1C49, + 0x1C50, 0x1C59, + 0xA620, 0xA629, + 0xA8D0, 0xA8D9, + 0xA900, 0xA909, + 0xA9D0, 0xA9D9, + 0xA9F0, 0xA9F9, + 0xAA50, 0xAA59, + 0xABF0, 0xABF9, + 0xFF10, 0xFF19, +} + +@(rodata) +nd_ranges32 := [?]i32{ + 0x104A0, 0x104A9, + 0x10D30, 0x10D39, + 0x10D40, 0x10D49, + 0x11066, 0x1106F, + 0x110F0, 0x110F9, + 0x11136, 0x1113F, + 0x111D0, 0x111D9, + 0x112F0, 0x112F9, + 0x11450, 0x11459, + 0x114D0, 0x114D9, + 0x11650, 0x11659, + 0x116C0, 0x116C9, + 0x116D0, 0x116E3, + 0x11730, 0x11739, + 0x118E0, 0x118E9, + 0x11950, 0x11959, + 0x11BF0, 0x11BF9, + 0x11C50, 0x11C59, + 0x11D50, 0x11D59, + 0x11DA0, 0x11DA9, + 0x11DE0, 0x11DE9, + 0x11F50, 0x11F59, + 0x16130, 0x16139, + 0x16A60, 0x16A69, + 0x16AC0, 0x16AC9, + 0x16B50, 0x16B59, + 0x16D70, 0x16D79, + 0x1CCF0, 0x1CCF9, + 0x1D7CE, 0x1D7FF, + 0x1E140, 0x1E149, + 0x1E2F0, 0x1E2F9, + 0x1E4F0, 0x1E4F9, + 0x1E5F1, 0x1E5FA, + 0x1E950, 0x1E959, + 0x1FBF0, 0x1FBF9, +} + +nd_ranges := Range{ + ranges_16 = nd_ranges16[:], + ranges_32 = nd_ranges32[:], +} + +@(rodata) +nl_singles16 := [?]u16{ + 0x3007, +} + +@(rodata) +nl_ranges16 := [?]u16{ + 0x16EE, 0x16F0, + 0x2160, 0x2182, + 0x2185, 0x2188, + 0x3021, 0x3029, + 0x3038, 0x303A, + 0xA6E6, 0xA6EF, +} + +@(rodata) +nl_singles32 := [?]i32{ + 0x10341, 0x1034A, +} + +@(rodata) +nl_ranges32 := [?]i32{ + 0x10140, 0x10174, + 0x103D1, 0x103D5, + 0x12400, 0x1246E, + 0x16FF4, 0x16FF6, +} + +nl_ranges := Range{ + single_16 = nl_singles16[:], + ranges_16 = nl_ranges16[:], + single_32 = nl_singles32[:], + ranges_32 = nl_ranges32[:], +} + +@(rodata) +no_singles16 := [?]u16{ + 0x00B9, 0x19DA, 0x2070, 0x2189, 0x2CFD, +} + +@(rodata) +no_ranges16 := [?]u16{ + 0x00B2, 0x00B3, + 0x00BC, 0x00BE, + 0x09F4, 0x09F9, + 0x0B72, 0x0B77, + 0x0BF0, 0x0BF2, + 0x0C78, 0x0C7E, + 0x0D58, 0x0D5E, + 0x0D70, 0x0D78, + 0x0F2A, 0x0F33, + 0x1369, 0x137C, + 0x17F0, 0x17F9, + 0x2074, 0x2079, + 0x2080, 0x2089, + 0x2150, 0x215F, + 0x2460, 0x249B, + 0x24EA, 0x24FF, + 0x2776, 0x2793, + 0x3192, 0x3195, + 0x3220, 0x3229, + 0x3248, 0x324F, + 0x3251, 0x325F, + 0x3280, 0x3289, + 0x32B1, 0x32BF, + 0xA830, 0xA835, +} + +@(rodata) +no_ranges32 := [?]i32{ + 0x10107, 0x10133, + 0x10175, 0x10178, + 0x1018A, 0x1018B, + 0x102E1, 0x102FB, + 0x10320, 0x10323, + 0x10858, 0x1085F, + 0x10879, 0x1087F, + 0x108A7, 0x108AF, + 0x108FB, 0x108FF, + 0x10916, 0x1091B, + 0x109BC, 0x109BD, + 0x109C0, 0x109CF, + 0x109D2, 0x109FF, + 0x10A40, 0x10A48, + 0x10A7D, 0x10A7E, + 0x10A9D, 0x10A9F, + 0x10AEB, 0x10AEF, + 0x10B58, 0x10B5F, + 0x10B78, 0x10B7F, + 0x10BA9, 0x10BAF, + 0x10CFA, 0x10CFF, + 0x10E60, 0x10E7E, + 0x10F1D, 0x10F26, + 0x10F51, 0x10F54, + 0x10FC5, 0x10FCB, + 0x11052, 0x11065, + 0x111E1, 0x111F4, + 0x1173A, 0x1173B, + 0x118EA, 0x118F2, + 0x11C5A, 0x11C6C, + 0x11FC0, 0x11FD4, + 0x16B5B, 0x16B61, + 0x16E80, 0x16E96, + 0x1D2C0, 0x1D2D3, + 0x1D2E0, 0x1D2F3, + 0x1D360, 0x1D378, + 0x1E8C7, 0x1E8CF, + 0x1EC71, 0x1ECAB, + 0x1ECAD, 0x1ECAF, + 0x1ECB1, 0x1ECB4, + 0x1ED01, 0x1ED2D, + 0x1ED2F, 0x1ED3D, + 0x1F100, 0x1F10C, +} + +no_ranges := Range{ + single_16 = no_singles16[:], + ranges_16 = no_ranges16[:], + ranges_32 = no_ranges32[:], +} + +@(rodata) +pc_singles16 := [?]u16{ + 0x005F, 0x2054, 0xFF3F, +} + +@(rodata) +pc_ranges16 := [?]u16{ + 0x203F, 0x2040, + 0xFE33, 0xFE34, + 0xFE4D, 0xFE4F, +} + +pc_ranges := Range{ + single_16 = pc_singles16[:], + ranges_16 = pc_ranges16[:], +} + +@(rodata) +pd_singles16 := [?]u16{ + 0x002D, 0x058A, 0x05BE, 0x1400, 0x1806, 0x2E17, 0x2E1A, 0x2E40, + 0x2E5D, 0x301C, 0x3030, 0x30A0, 0xFE58, 0xFE63, 0xFF0D, +} + +@(rodata) +pd_ranges16 := [?]u16{ + 0x2010, 0x2015, + 0x2E3A, 0x2E3B, + 0xFE31, 0xFE32, +} + +@(rodata) +pd_singles32 := [?]i32{ + 0x10D6E, 0x10EAD, +} + +pd_ranges := Range{ + single_16 = pd_singles16[:], + ranges_16 = pd_ranges16[:], + single_32 = pd_singles32[:], +} + +@(rodata) +pe_singles16 := [?]u16{ + 0x0029, 0x005D, 0x007D, 0x0F3B, 0x0F3D, 0x169C, 0x2046, 0x207E, + 0x208E, 0x2309, 0x230B, 0x232A, 0x2769, 0x276B, 0x276D, 0x276F, + 0x2771, 0x2773, 0x2775, 0x27C6, 0x27E7, 0x27E9, 0x27EB, 0x27ED, + 0x27EF, 0x2984, 0x2986, 0x2988, 0x298A, 0x298C, 0x298E, 0x2990, + 0x2992, 0x2994, 0x2996, 0x2998, 0x29D9, 0x29DB, 0x29FD, 0x2E23, + 0x2E25, 0x2E27, 0x2E29, 0x2E56, 0x2E58, 0x2E5A, 0x2E5C, 0x3009, + 0x300B, 0x300D, 0x300F, 0x3011, 0x3015, 0x3017, 0x3019, 0x301B, + 0xFD3E, 0xFE18, 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, + 0xFE42, 0xFE44, 0xFE48, 0xFE5A, 0xFE5C, 0xFE5E, 0xFF09, 0xFF3D, + 0xFF5D, 0xFF60, 0xFF63, +} + +@(rodata) +pe_ranges16 := [?]u16{ + 0x301E, 0x301F, +} + +pe_ranges := Range{ + single_16 = pe_singles16[:], + ranges_16 = pe_ranges16[:], +} + +@(rodata) +pf_singles16 := [?]u16{ + 0x00BB, 0x2019, 0x201D, 0x203A, 0x2E03, 0x2E05, 0x2E0A, 0x2E0D, + 0x2E1D, 0x2E21, +} + +pf_ranges := Range{ + single_16 = pf_singles16[:], +} + +@(rodata) +pi_singles16 := [?]u16{ + 0x00AB, 0x2018, 0x201F, 0x2039, 0x2E02, 0x2E04, 0x2E09, 0x2E0C, + 0x2E1C, 0x2E20, +} + +@(rodata) +pi_ranges16 := [?]u16{ + 0x201B, 0x201C, +} + +pi_ranges := Range{ + single_16 = pi_singles16[:], + ranges_16 = pi_ranges16[:], +} + +@(rodata) +po_singles16 := [?]u16{ + 0x002A, 0x002C, 0x005C, 0x00A1, 0x00A7, 0x00BF, 0x037E, 0x0387, + 0x0589, 0x05C0, 0x05C3, 0x05C6, 0x061B, 0x06D4, 0x085E, 0x0970, + 0x09FD, 0x0A76, 0x0AF0, 0x0C77, 0x0C84, 0x0DF4, 0x0E4F, 0x0F14, + 0x0F85, 0x10FB, 0x166E, 0x1CD3, 0x2053, 0x2D70, 0x2E0B, 0x2E1B, + 0x2E41, 0x303D, 0x30FB, 0xA673, 0xA67E, 0xA8FC, 0xA95F, 0xABEB, + 0xFE19, 0xFE30, 0xFE68, 0xFF0A, 0xFF0C, 0xFF3C, 0xFF61, +} + +@(rodata) +po_ranges16 := [?]u16{ + 0x0021, 0x0023, + 0x0025, 0x0027, + 0x002E, 0x002F, + 0x003A, 0x003B, + 0x003F, 0x0040, + 0x00B6, 0x00B7, + 0x055A, 0x055F, + 0x05F3, 0x05F4, + 0x0609, 0x060A, + 0x060C, 0x060D, + 0x061D, 0x061F, + 0x066A, 0x066D, + 0x0700, 0x070D, + 0x07F7, 0x07F9, + 0x0830, 0x083E, + 0x0964, 0x0965, + 0x0E5A, 0x0E5B, + 0x0F04, 0x0F12, + 0x0FD0, 0x0FD4, + 0x0FD9, 0x0FDA, + 0x104A, 0x104F, + 0x1360, 0x1368, + 0x16EB, 0x16ED, + 0x1735, 0x1736, + 0x17D4, 0x17D6, + 0x17D8, 0x17DA, + 0x1800, 0x1805, + 0x1807, 0x180A, + 0x1944, 0x1945, + 0x1A1E, 0x1A1F, + 0x1AA0, 0x1AA6, + 0x1AA8, 0x1AAD, + 0x1B4E, 0x1B4F, + 0x1B5A, 0x1B60, + 0x1B7D, 0x1B7F, + 0x1BFC, 0x1BFF, + 0x1C3B, 0x1C3F, + 0x1C7E, 0x1C7F, + 0x1CC0, 0x1CC7, + 0x2016, 0x2017, + 0x2020, 0x2027, + 0x2030, 0x2038, + 0x203B, 0x203E, + 0x2041, 0x2043, + 0x2047, 0x2051, + 0x2055, 0x205E, + 0x2CF9, 0x2CFC, + 0x2CFE, 0x2CFF, + 0x2E00, 0x2E01, + 0x2E06, 0x2E08, + 0x2E0E, 0x2E16, + 0x2E18, 0x2E19, + 0x2E1E, 0x2E1F, + 0x2E2A, 0x2E2E, + 0x2E30, 0x2E39, + 0x2E3C, 0x2E3F, + 0x2E43, 0x2E4F, + 0x2E52, 0x2E54, + 0x3001, 0x3003, + 0xA4FE, 0xA4FF, + 0xA60D, 0xA60F, + 0xA6F2, 0xA6F7, + 0xA874, 0xA877, + 0xA8CE, 0xA8CF, + 0xA8F8, 0xA8FA, + 0xA92E, 0xA92F, + 0xA9C1, 0xA9CD, + 0xA9DE, 0xA9DF, + 0xAA5C, 0xAA5F, + 0xAADE, 0xAADF, + 0xAAF0, 0xAAF1, + 0xFE10, 0xFE16, + 0xFE45, 0xFE46, + 0xFE49, 0xFE4C, + 0xFE50, 0xFE52, + 0xFE54, 0xFE57, + 0xFE5F, 0xFE61, + 0xFE6A, 0xFE6B, + 0xFF01, 0xFF03, + 0xFF05, 0xFF07, + 0xFF0E, 0xFF0F, + 0xFF1A, 0xFF1B, + 0xFF1F, 0xFF20, + 0xFF64, 0xFF65, +} + +@(rodata) +po_singles32 := [?]i32{ + 0x1039F, 0x103D0, 0x1056F, 0x10857, 0x1091F, 0x1093F, 0x10A7F, 0x10ED0, + 0x111CD, 0x111DB, 0x112A9, 0x1145D, 0x114C6, 0x116B9, 0x1183B, 0x119E2, + 0x11BE1, 0x11FFF, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E5FF, +} + +@(rodata) +po_ranges32 := [?]i32{ + 0x10100, 0x10102, + 0x10A50, 0x10A58, + 0x10AF0, 0x10AF6, + 0x10B39, 0x10B3F, + 0x10B99, 0x10B9C, + 0x10F55, 0x10F59, + 0x10F86, 0x10F89, + 0x11047, 0x1104D, + 0x110BB, 0x110BC, + 0x110BE, 0x110C1, + 0x11140, 0x11143, + 0x11174, 0x11175, + 0x111C5, 0x111C8, + 0x111DD, 0x111DF, + 0x11238, 0x1123D, + 0x113D4, 0x113D5, + 0x113D7, 0x113D8, + 0x1144B, 0x1144F, + 0x1145A, 0x1145B, + 0x115C1, 0x115D7, + 0x11641, 0x11643, + 0x11660, 0x1166C, + 0x1173C, 0x1173E, + 0x11944, 0x11946, + 0x11A3F, 0x11A46, + 0x11A9A, 0x11A9C, + 0x11A9E, 0x11AA2, + 0x11B00, 0x11B09, + 0x11C41, 0x11C45, + 0x11C70, 0x11C71, + 0x11EF7, 0x11EF8, + 0x11F43, 0x11F4F, + 0x12470, 0x12474, + 0x12FF1, 0x12FF2, + 0x16A6E, 0x16A6F, + 0x16B37, 0x16B3B, + 0x16D6D, 0x16D6F, + 0x16E97, 0x16E9A, + 0x1DA87, 0x1DA8B, + 0x1E95E, 0x1E95F, +} + +po_ranges := Range{ + single_16 = po_singles16[:], + ranges_16 = po_ranges16[:], + single_32 = po_singles32[:], + ranges_32 = po_ranges32[:], +} + +@(rodata) +ps_singles16 := [?]u16{ + 0x0028, 0x005B, 0x007B, 0x0F3A, 0x0F3C, 0x169B, 0x201A, 0x201E, + 0x2045, 0x207D, 0x208D, 0x2308, 0x230A, 0x2329, 0x2768, 0x276A, + 0x276C, 0x276E, 0x2770, 0x2772, 0x2774, 0x27C5, 0x27E6, 0x27E8, + 0x27EA, 0x27EC, 0x27EE, 0x2983, 0x2985, 0x2987, 0x2989, 0x298B, + 0x298D, 0x298F, 0x2991, 0x2993, 0x2995, 0x2997, 0x29D8, 0x29DA, + 0x29FC, 0x2E22, 0x2E24, 0x2E26, 0x2E28, 0x2E42, 0x2E55, 0x2E57, + 0x2E59, 0x2E5B, 0x3008, 0x300A, 0x300C, 0x300E, 0x3010, 0x3014, + 0x3016, 0x3018, 0x301A, 0x301D, 0xFD3F, 0xFE17, 0xFE35, 0xFE37, + 0xFE39, 0xFE3B, 0xFE3D, 0xFE3F, 0xFE41, 0xFE43, 0xFE47, 0xFE59, + 0xFE5B, 0xFE5D, 0xFF08, 0xFF3B, 0xFF5B, 0xFF5F, 0xFF62, +} + +ps_ranges := Range{ + single_16 = ps_singles16[:], +} + +@(rodata) +sc_singles16 := [?]u16{ + 0x0024, 0x058F, 0x060B, 0x09FB, 0x0AF1, 0x0BF9, 0x0E3F, 0x17DB, + 0xA838, 0xFDFC, 0xFE69, 0xFF04, +} + +@(rodata) +sc_ranges16 := [?]u16{ + 0x00A2, 0x00A5, + 0x07FE, 0x07FF, + 0x09F2, 0x09F3, + 0x20A0, 0x20C1, + 0xFFE0, 0xFFE1, + 0xFFE5, 0xFFE6, +} + +@(rodata) +sc_singles32 := [?]i32{ + 0x1E2FF, 0x1ECB0, +} + +@(rodata) +sc_ranges32 := [?]i32{ + 0x11FDD, 0x11FE0, +} + +sc_ranges := Range{ + single_16 = sc_singles16[:], + ranges_16 = sc_ranges16[:], + single_32 = sc_singles32[:], + ranges_32 = sc_ranges32[:], +} + +@(rodata) +sk_singles16 := [?]u16{ + 0x005E, 0x0060, 0x00A8, 0x00AF, 0x00B4, 0x00B8, 0x02ED, 0x0375, + 0x0888, 0x1FBD, 0xAB5B, 0xFF3E, 0xFF40, 0xFFE3, +} + +@(rodata) +sk_ranges16 := [?]u16{ + 0x02C2, 0x02C5, + 0x02D2, 0x02DF, + 0x02E5, 0x02EB, + 0x02EF, 0x02FF, + 0x0384, 0x0385, + 0x1FBF, 0x1FC1, + 0x1FCD, 0x1FCF, + 0x1FDD, 0x1FDF, + 0x1FED, 0x1FEF, + 0x1FFD, 0x1FFE, + 0x309B, 0x309C, + 0xA700, 0xA716, + 0xA720, 0xA721, + 0xA789, 0xA78A, + 0xAB6A, 0xAB6B, + 0xFBB2, 0xFBC2, +} + +@(rodata) +sk_ranges32 := [?]i32{ + 0x1F3FB, 0x1F3FF, +} + +sk_ranges := Range{ + single_16 = sk_singles16[:], + ranges_16 = sk_ranges16[:], + ranges_32 = sk_ranges32[:], +} + +@(rodata) +sm_singles16 := [?]u16{ + 0x002B, 0x007C, 0x007E, 0x00AC, 0x00B1, 0x00D7, 0x00F7, 0x03F6, + 0x2044, 0x2052, 0x2118, 0x214B, 0x21A0, 0x21A3, 0x21A6, 0x21AE, + 0x21D2, 0x21D4, 0x237C, 0x25B7, 0x25C1, 0x266F, 0xFB29, 0xFE62, + 0xFF0B, 0xFF5C, 0xFF5E, 0xFFE2, +} + +@(rodata) +sm_ranges16 := [?]u16{ + 0x003C, 0x003E, + 0x0606, 0x0608, + 0x207A, 0x207C, + 0x208A, 0x208C, + 0x2140, 0x2144, + 0x2190, 0x2194, + 0x219A, 0x219B, + 0x21CE, 0x21CF, + 0x21F4, 0x22FF, + 0x2320, 0x2321, + 0x239B, 0x23B3, + 0x23DC, 0x23E1, + 0x25F8, 0x25FF, + 0x27C0, 0x27C4, + 0x27C7, 0x27E5, + 0x27F0, 0x27FF, + 0x2900, 0x2982, + 0x2999, 0x29D7, + 0x29DC, 0x29FB, + 0x29FE, 0x2AFF, + 0x2B30, 0x2B44, + 0x2B47, 0x2B4C, + 0xFE64, 0xFE66, + 0xFF1C, 0xFF1E, + 0xFFE9, 0xFFEC, +} + +@(rodata) +sm_singles32 := [?]i32{ + 0x1CEF0, 0x1D6C1, 0x1D6DB, 0x1D6FB, 0x1D715, 0x1D735, 0x1D74F, 0x1D76F, + 0x1D789, 0x1D7A9, 0x1D7C3, +} + +@(rodata) +sm_ranges32 := [?]i32{ + 0x10D8E, 0x10D8F, + 0x1EEF0, 0x1EEF1, + 0x1F8D0, 0x1F8D8, +} + +sm_ranges := Range{ + single_16 = sm_singles16[:], + ranges_16 = sm_ranges16[:], + single_32 = sm_singles32[:], + ranges_32 = sm_ranges32[:], +} + +@(rodata) +so_singles16 := [?]u16{ + 0x00A6, 0x00A9, 0x00AE, 0x00B0, 0x0482, 0x06DE, 0x06E9, 0x07F6, + 0x09FA, 0x0B70, 0x0BFA, 0x0C7F, 0x0D4F, 0x0D79, 0x0F13, 0x0F34, + 0x0F36, 0x0F38, 0x166D, 0x1940, 0x2114, 0x2125, 0x2127, 0x2129, + 0x212E, 0x214A, 0x214F, 0x21D3, 0x3004, 0x3020, 0x31EF, 0x3250, + 0xA839, 0xFFE4, 0xFFE8, +} + +@(rodata) +so_ranges16 := [?]u16{ + 0x058D, 0x058E, + 0x060E, 0x060F, + 0x06FD, 0x06FE, + 0x0BF3, 0x0BF8, + 0x0F01, 0x0F03, + 0x0F15, 0x0F17, + 0x0F1A, 0x0F1F, + 0x0FBE, 0x0FC5, + 0x0FC7, 0x0FCC, + 0x0FCE, 0x0FCF, + 0x0FD5, 0x0FD8, + 0x109E, 0x109F, + 0x1390, 0x1399, + 0x19DE, 0x19FF, + 0x1B61, 0x1B6A, + 0x1B74, 0x1B7C, + 0x2100, 0x2101, + 0x2103, 0x2106, + 0x2108, 0x2109, + 0x2116, 0x2117, + 0x211E, 0x2123, + 0x213A, 0x213B, + 0x214C, 0x214D, + 0x218A, 0x218B, + 0x2195, 0x2199, + 0x219C, 0x219F, + 0x21A1, 0x21A2, + 0x21A4, 0x21A5, + 0x21A7, 0x21AD, + 0x21AF, 0x21CD, + 0x21D0, 0x21D1, + 0x21D5, 0x21F3, + 0x2300, 0x2307, + 0x230C, 0x231F, + 0x2322, 0x2328, + 0x232B, 0x237B, + 0x237D, 0x239A, + 0x23B4, 0x23DB, + 0x23E2, 0x2429, + 0x2440, 0x244A, + 0x249C, 0x24E9, + 0x2500, 0x25B6, + 0x25B8, 0x25C0, + 0x25C2, 0x25F7, + 0x2600, 0x266E, + 0x2670, 0x2767, + 0x2794, 0x27BF, + 0x2800, 0x28FF, + 0x2B00, 0x2B2F, + 0x2B45, 0x2B46, + 0x2B4D, 0x2B73, + 0x2B76, 0x2BFF, + 0x2CE5, 0x2CEA, + 0x2E50, 0x2E51, + 0x2E80, 0x2E99, + 0x2E9B, 0x2EF3, + 0x2F00, 0x2FD5, + 0x2FF0, 0x2FFF, + 0x3012, 0x3013, + 0x3036, 0x3037, + 0x303E, 0x303F, + 0x3190, 0x3191, + 0x3196, 0x319F, + 0x31C0, 0x31E5, + 0x3200, 0x321E, + 0x322A, 0x3247, + 0x3260, 0x327F, + 0x328A, 0x32B0, + 0x32C0, 0x33FF, + 0x4DC0, 0x4DFF, + 0xA490, 0xA4C6, + 0xA828, 0xA82B, + 0xA836, 0xA837, + 0xAA77, 0xAA79, + 0xFBC3, 0xFBD2, + 0xFD40, 0xFD4F, + 0xFD90, 0xFD91, + 0xFDC8, 0xFDCF, + 0xFDFD, 0xFDFF, + 0xFFED, 0xFFEE, + 0xFFFC, 0xFFFD, +} + +@(rodata) +so_singles32 := [?]i32{ + 0x101A0, 0x10AC8, 0x1173F, 0x16B45, 0x1BC9C, 0x1D245, 0x1E14F, 0x1ECAC, + 0x1ED2E, 0x1F7F0, 0x1FAC8, 0x1FBFA, +} + +@(rodata) +so_ranges32 := [?]i32{ + 0x10137, 0x1013F, + 0x10179, 0x10189, + 0x1018C, 0x1018E, + 0x10190, 0x1019C, + 0x101D0, 0x101FC, + 0x10877, 0x10878, + 0x10ED1, 0x10ED8, + 0x11FD5, 0x11FDC, + 0x11FE1, 0x11FF1, + 0x16B3C, 0x16B3F, + 0x1CC00, 0x1CCEF, + 0x1CCFA, 0x1CCFC, + 0x1CD00, 0x1CEB3, + 0x1CEBA, 0x1CED0, + 0x1CEE0, 0x1CEEF, + 0x1CF50, 0x1CFC3, + 0x1D000, 0x1D0F5, + 0x1D100, 0x1D126, + 0x1D129, 0x1D164, + 0x1D16A, 0x1D16C, + 0x1D183, 0x1D184, + 0x1D18C, 0x1D1A9, + 0x1D1AE, 0x1D1EA, + 0x1D200, 0x1D241, + 0x1D300, 0x1D356, + 0x1D800, 0x1D9FF, + 0x1DA37, 0x1DA3A, + 0x1DA6D, 0x1DA74, + 0x1DA76, 0x1DA83, + 0x1DA85, 0x1DA86, + 0x1F000, 0x1F02B, + 0x1F030, 0x1F093, + 0x1F0A0, 0x1F0AE, + 0x1F0B1, 0x1F0BF, + 0x1F0C1, 0x1F0CF, + 0x1F0D1, 0x1F0F5, + 0x1F10D, 0x1F1AD, + 0x1F1E6, 0x1F202, + 0x1F210, 0x1F23B, + 0x1F240, 0x1F248, + 0x1F250, 0x1F251, + 0x1F260, 0x1F265, + 0x1F300, 0x1F3FA, + 0x1F400, 0x1F6D8, + 0x1F6DC, 0x1F6EC, + 0x1F6F0, 0x1F6FC, + 0x1F700, 0x1F7D9, + 0x1F7E0, 0x1F7EB, + 0x1F800, 0x1F80B, + 0x1F810, 0x1F847, + 0x1F850, 0x1F859, + 0x1F860, 0x1F887, + 0x1F890, 0x1F8AD, + 0x1F8B0, 0x1F8BB, + 0x1F8C0, 0x1F8C1, + 0x1F900, 0x1FA57, + 0x1FA60, 0x1FA6D, + 0x1FA70, 0x1FA7C, + 0x1FA80, 0x1FA8A, + 0x1FA8E, 0x1FAC6, + 0x1FACD, 0x1FADC, + 0x1FADF, 0x1FAEA, + 0x1FAEF, 0x1FAF8, + 0x1FB00, 0x1FB92, + 0x1FB94, 0x1FBEF, +} + +so_ranges := Range{ + single_16 = so_singles16[:], + ranges_16 = so_ranges16[:], + single_32 = so_singles32[:], + ranges_32 = so_ranges32[:], +} + +@(rodata) +zs_singles16 := [?]u16{ + 0x0020, 0x00A0, 0x1680, 0x202F, 0x205F, 0x3000, +} + +@(rodata) +zs_ranges16 := [?]u16{ + 0x2000, 0x200A, +} + +zs_ranges := Range{ + single_16 = zs_singles16[:], + ranges_16 = zs_ranges16[:], +} + +@(rodata) +extra_digits_singles16 := [?]u16{ + 0x00B9, 0x19DA, 0x2070, 0x24EA, 0x24FF, +} + +@(rodata) +extra_digits_ranges16 := [?]u16{ + 0x00B2, 0x00B3, + 0x1369, 0x1371, + 0x2074, 0x2079, + 0x2080, 0x2089, + 0x2460, 0x2468, + 0x2474, 0x247C, + 0x2488, 0x2490, + 0x24F5, 0x24FD, + 0x2776, 0x277E, + 0x2780, 0x2788, + 0x278A, 0x2792, +} + +@(rodata) +extra_digits_ranges32 := [?]i32{ + 0x10A40, 0x10A43, + 0x10E60, 0x10E68, + 0x11052, 0x1105A, + 0x1F100, 0x1F10A, +} + +extra_digits_ranges := Range{ + single_16 = extra_digits_singles16[:], + ranges_16 = extra_digits_ranges16[:], + ranges_32 = extra_digits_ranges32[:], +} + +@(rodata) +other_lowercase_singles16 := [?]u16{ + 0x00AA, 0x00BA, 0x0345, 0x037A, 0x10FC, 0x1D78, 0x2071, 0x207F, + 0xA770, 0xAB69, +} + +@(rodata) +other_lowercase_ranges16 := [?]u16{ + 0x02B0, 0x02B8, + 0x02C0, 0x02C1, + 0x02E0, 0x02E4, + 0x1D2C, 0x1D6A, + 0x1D9B, 0x1DBF, + 0x2090, 0x209C, + 0x2170, 0x217F, + 0x24D0, 0x24E9, + 0x2C7C, 0x2C7D, + 0xA69C, 0xA69D, + 0xA7F1, 0xA7F4, + 0xA7F8, 0xA7F9, + 0xAB5C, 0xAB5F, +} + +@(rodata) +other_lowercase_singles32 := [?]i32{ + 0x10780, +} + +@(rodata) +other_lowercase_ranges32 := [?]i32{ + 0x10783, 0x10785, + 0x10787, 0x107B0, + 0x107B2, 0x107BA, + 0x1E030, 0x1E06D, +} + +other_lowercase_ranges := Range{ + single_16 = other_lowercase_singles16[:], + ranges_16 = other_lowercase_ranges16[:], + single_32 = other_lowercase_singles32[:], + ranges_32 = other_lowercase_ranges32[:], +} + +@(rodata) +other_uppercase_ranges16 := [?]u16{ + 0x2160, 0x216F, + 0x24B6, 0x24CF, +} + +@(rodata) +other_uppercase_ranges32 := [?]i32{ + 0x1F130, 0x1F149, + 0x1F150, 0x1F169, + 0x1F170, 0x1F189, +} + +other_uppercase_ranges := Range{ + ranges_16 = other_uppercase_ranges16[:], + ranges_32 = other_uppercase_ranges32[:], +} + diff --git a/core/unicode/inrange.odin b/core/unicode/inrange.odin new file mode 100644 index 000000000..fa433a741 --- /dev/null +++ b/core/unicode/inrange.odin @@ -0,0 +1,45 @@ +package unicode + +/* +Check to see if the rune `r` is in `range` +*/ +in_range :: proc(r: rune, range: Range) -> bool { + + if r <= 0xFFFF { + r16 := cast(u16) r + + length := len(range.ranges_16) + index := binary_search(r16, range.ranges_16, length/2, 2) if length > 0 else -1 + if index >= 0 && range.ranges_16[index] <= r16 && range.ranges_16[index+1] >= r16 { + return true + } + + length = len(range.single_16) + index = binary_search(r16, range.single_16, length, 1) if length > 0 else -1 + if index >= 0 && range.single_16[index] == r16 { + return true + } + } + + r32 := cast(i32) r + + length := len(range.ranges_32) + index := binary_search(r32, range.ranges_32, length/2, 2) if length >0 else -1 + if index >= 0 && range.ranges_32[index] <= r32 && range.ranges_32[index+1] >= r32 { + return true + } + + length = len(range.single_32) + index = binary_search(r32, range.single_32, length, 1) if length > 0 else -1 + if index >= 0 && range.single_32[index] == r32 { + return true + } + + + return false +} + + + + + diff --git a/core/unicode/letter.odin b/core/unicode/letter.odin index e6d0261c6..92aee9a68 100644 --- a/core/unicode/letter.odin +++ b/core/unicode/letter.odin @@ -1,6 +1,8 @@ package unicode -MAX_RUNE :: '\U00010fff' // Maximum valid unicode code point +import "base:runtime" + +MAX_RUNE :: '\U0010ffff' // Maximum valid unicode code point REPLACEMENT_CHAR :: '\ufffd' // Represented an invalid code point MAX_ASCII :: '\u007f' // Maximum ASCII value MAX_LATIN1 :: '\u00ff' // Maximum Latin-1 value @@ -11,7 +13,8 @@ ZERO_WIDTH_JOINER :: '\u200D' WORD_JOINER :: '\u2060' @(require_results) -binary_search :: proc(c: i32, table: []i32, length, stride: int) -> int { +binary_search :: proc(c: $T, table: []T, length, stride: int, loc := #caller_location) -> int #no_bounds_check { + runtime.bounds_check_error_loc(loc, length*stride-1, len(table)) n := length t := 0 for n > 1 { @@ -31,7 +34,7 @@ binary_search :: proc(c: i32, table: []i32, length, stride: int) -> int { } @(require_results) -to_lower :: proc(r: rune) -> rune { +to_lower :: proc(r: rune) -> rune #no_bounds_check { c := i32(r) p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3) if p >= 0 && to_lower_ranges[p] <= c && c <= to_lower_ranges[p+1] { @@ -44,7 +47,7 @@ to_lower :: proc(r: rune) -> rune { return rune(c) } @(require_results) -to_upper :: proc(r: rune) -> rune { +to_upper :: proc(r: rune) -> rune #no_bounds_check { c := i32(r) p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3) if p >= 0 && to_upper_ranges[p] <= c && c <= to_upper_ranges[p+1] { @@ -57,7 +60,7 @@ to_upper :: proc(r: rune) -> rune { return rune(c) } @(require_results) -to_title :: proc(r: rune) -> rune { +to_title :: proc(r: rune) -> rune #no_bounds_check { c := i32(r) p := binary_search(c, to_upper_singlets[:], len(to_title_singlets)/2, 2) if p >= 0 && c == to_upper_singlets[p] { @@ -68,42 +71,36 @@ to_title :: proc(r: rune) -> rune { @(require_results) -is_lower :: proc(r: rune) -> bool { +is_lower :: proc(r: rune) -> bool #no_bounds_check { if r <= MAX_ASCII { return u32(r)-'a' < 26 } - c := i32(r) - p := binary_search(c, to_upper_ranges[:], len(to_upper_ranges)/3, 3) - if p >= 0 && to_upper_ranges[p] <= c && c <= to_upper_ranges[p+1] { - return true - } - p = binary_search(c, to_upper_singlets[:], len(to_upper_singlets)/2, 2) - if p >= 0 && c == to_upper_singlets[p] { - return true - } - return false + return in_range(r, ll_ranges) || in_range(r, other_lowercase_ranges) } @(require_results) -is_upper :: proc(r: rune) -> bool { +is_upper :: proc(r: rune) -> bool #no_bounds_check { if r <= MAX_ASCII { return u32(r)-'A' < 26 } - c := i32(r) - p := binary_search(c, to_lower_ranges[:], len(to_lower_ranges)/3, 3) - if p >= 0 && to_lower_ranges[p] <= c && c <= to_lower_ranges[p+1] { - return true - } - p = binary_search(c, to_lower_singlets[:], len(to_lower_singlets)/2, 2) - if p >= 0 && c == to_lower_singlets[p] { - return true - } - return false + return in_range(r, lu_ranges) || in_range(r, other_uppercase_ranges) } is_alpha :: is_letter + +/* +Return true if the rune `r` is a letter. Being a letter means that the rune has +the Unicode general category property of L. In practice, the character will have +a general category property of Ll, Lm, Lo, Lt, or Lu. + +Inputs: +- r: The rune which will be check for having the property of being a letter. + +Returns: +`true` when the rune `r` is a letter. `false` will be returned in all other cases. +*/ @(require_results) -is_letter :: proc(r: rune) -> bool { +is_letter :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pLmask != 0 } @@ -111,16 +108,9 @@ is_letter :: proc(r: rune) -> bool { return true } - c := i32(r) - p := binary_search(c, alpha_ranges[:], len(alpha_ranges)/2, 2) - if p >= 0 && alpha_ranges[p] <= c && c <= alpha_ranges[p+1] { - return true - } - p = binary_search(c, alpha_singlets[:], len(alpha_singlets), 1) - if p >= 0 && c == alpha_singlets[p] { - return true - } - return false + ll_lu := in_range(r, ll_ranges) || in_range(r, lu_ranges) + + return ll_lu || in_range(r, lo_ranges) || in_range(r, lt_ranges) || in_range(r, lm_ranges) } @(require_results) @@ -128,18 +118,52 @@ is_title :: proc(r: rune) -> bool { return is_upper(r) && is_lower(r) } +/* +Returns true if the rune `r` is in the General Category Nd + +Inputs: +- r: The run to check if it is in the general category Nd. + +Returns: +`true` if the rune is in the general category Nd and `false` otherwise + +*/ +is_decimal :: proc(r: rune) -> bool { + return in_range(r, nd_ranges) +} + +/* +This function determincs if a rune is a digit. To be a digit the +charage either has a Numeric_Type of Digit or Decimal. + +Inputs: +- r: The rune to check if it is a digit. + +Returns: +`true` if the rune `r` is a digit, `false` in all other cases + +*/ @(require_results) is_digit :: proc(r: rune) -> bool { if r <= MAX_LATIN1 { - return '0' <= r && r <= '9' + return ('0' <= r && r <= '9') || r == 0x00B9 || (r >= 0x00B2 && r <= 0x0B3) } + + if in_range(r, nd_ranges) { + return true + } + + if in_range(r, extra_digits_ranges) { + return true + } + return false } is_white_space :: is_space @(require_results) -is_space :: proc(r: rune) -> bool { +is_space :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { switch r { case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xa0: @@ -173,11 +197,20 @@ is_graphic :: proc(r: rune) -> bool { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pg != 0 } + + if is_letter(r) || is_number(r) || is_punct(r) || is_symbol(r) || in_range(r, zs_ranges) { + return true + } + + if in_range(r, mc_ranges) || in_range(r, me_ranges) || in_range(r, mn_ranges) { + return true + } + return false } @(require_results) -is_print :: proc(r: rune) -> bool { +is_print :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pp != 0 } @@ -185,34 +218,63 @@ is_print :: proc(r: rune) -> bool { } @(require_results) -is_control :: proc(r: rune) -> bool { +is_control :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pC != 0 } return false } +/* +Checks to see if the rune `r` is a number. This means the rune is a member +of the general category Nd, Nl, or No. + +Inputs: +r: The rune to check if it is number. + +Returns: +`true` if the ruen belongs to the general category Nd, Nl, or No. `false` +is return in all other cases. + +*/ @(require_results) -is_number :: proc(r: rune) -> bool { +is_number :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pN != 0 } - return false + + return in_range(r, nd_ranges) || in_range(r, nl_ranges) || in_range(r, no_ranges) } @(require_results) -is_punct :: proc(r: rune) -> bool { +is_punct :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pP != 0 } - return false + + if in_range(r, pc_ranges) || in_range(r, pd_ranges) || in_range(r, pe_ranges) { + return true + } + + if in_range(r, pf_ranges) || in_range(r, pi_ranges) || in_range(r, po_ranges) { + return true + } + + return in_range(r, ps_ranges) } @(require_results) -is_symbol :: proc(r: rune) -> bool { +is_symbol :: proc(r: rune) -> bool #no_bounds_check { if u32(r) <= MAX_LATIN1 { return char_properties[u8(r)]&pS != 0 } + + s := in_range(r, sc_ranges) || in_range(r, sm_ranges) + + if s || in_range(r, so_ranges) || in_range(r, sk_ranges) { + return true + } + return false } @@ -267,7 +329,7 @@ is_prepended_concatenation_mark :: proc(r: rune) -> bool { // General_Category=Spacing_Mark @(require_results) -is_spacing_mark :: proc(r: rune) -> bool { +is_spacing_mark :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, spacing_mark_ranges[:], len(spacing_mark_ranges)/2, 2) if p >= 0 && spacing_mark_ranges[p] <= c && c <= spacing_mark_ranges[p+1] { @@ -278,7 +340,7 @@ is_spacing_mark :: proc(r: rune) -> bool { // General_Category=Nonspacing_Mark @(require_results) -is_nonspacing_mark :: proc(r: rune) -> bool { +is_nonspacing_mark :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, nonspacing_mark_ranges[:], len(nonspacing_mark_ranges)/2, 2) if p >= 0 && nonspacing_mark_ranges[p] <= c && c <= nonspacing_mark_ranges[p+1] { @@ -289,7 +351,7 @@ is_nonspacing_mark :: proc(r: rune) -> bool { // Extended_Pictographic @(require_results) -is_emoji_extended_pictographic :: proc(r: rune) -> bool { +is_emoji_extended_pictographic :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, emoji_extended_pictographic_ranges[:], len(emoji_extended_pictographic_ranges)/2, 2) if p >= 0 && emoji_extended_pictographic_ranges[p] <= c && c <= emoji_extended_pictographic_ranges[p+1] { @@ -300,7 +362,7 @@ is_emoji_extended_pictographic :: proc(r: rune) -> bool { // Grapheme_Extend @(require_results) -is_grapheme_extend :: proc(r: rune) -> bool { +is_grapheme_extend :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, grapheme_extend_ranges[:], len(grapheme_extend_ranges)/2, 2) if p >= 0 && grapheme_extend_ranges[p] <= c && c <= grapheme_extend_ranges[p+1] { @@ -330,7 +392,7 @@ is_hangul_syllable_trailing :: proc(r: rune) -> bool { // Hangul_Syllable_Type=LV_Syllable @(require_results) -is_hangul_syllable_lv :: proc(r: rune) -> bool { +is_hangul_syllable_lv :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, hangul_syllable_lv_singlets[:], len(hangul_syllable_lv_singlets), 1) if p >= 0 && c == hangul_syllable_lv_singlets[p] { @@ -341,7 +403,7 @@ is_hangul_syllable_lv :: proc(r: rune) -> bool { // Hangul_Syllable_Type=LVT_Syllable @(require_results) -is_hangul_syllable_lvt :: proc(r: rune) -> bool { +is_hangul_syllable_lvt :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, hangul_syllable_lvt_ranges[:], len(hangul_syllable_lvt_ranges)/2, 2) if p >= 0 && hangul_syllable_lvt_ranges[p] <= c && c <= hangul_syllable_lvt_ranges[p+1] { @@ -397,7 +459,7 @@ is_indic_conjunct_break_linker :: proc(r: rune) -> bool { // Indic_Conjunct_Break=Consonant @(require_results) -is_indic_conjunct_break_consonant :: proc(r: rune) -> bool { +is_indic_conjunct_break_consonant :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, indic_conjunct_break_consonant_ranges[:], len(indic_conjunct_break_consonant_ranges)/2, 2) if p >= 0 && indic_conjunct_break_consonant_ranges[p] <= c && c <= indic_conjunct_break_consonant_ranges[p+1] { @@ -408,7 +470,7 @@ is_indic_conjunct_break_consonant :: proc(r: rune) -> bool { // Indic_Conjunct_Break=Extend @(require_results) -is_indic_conjunct_break_extend :: proc(r: rune) -> bool { +is_indic_conjunct_break_extend :: proc(r: rune) -> bool #no_bounds_check { c := i32(r) p := binary_search(c, indic_conjunct_break_extend_ranges[:], len(indic_conjunct_break_extend_ranges)/2, 2) if p >= 0 && indic_conjunct_break_extend_ranges[p] <= c && c <= indic_conjunct_break_extend_ranges[p+1] { @@ -459,7 +521,7 @@ is_gcb_extend_class :: proc(r: rune) -> bool { // - 1 in all other cases. // @(require_results) -normalized_east_asian_width :: proc(r: rune) -> int { +normalized_east_asian_width :: proc(r: rune) -> int #no_bounds_check { // This is a different interpretation of the BOM which occurs in the middle of text. ZERO_WIDTH_NO_BREAK_SPACE :: '\uFEFF' diff --git a/core/unicode/tables.odin b/core/unicode/tables.odin index c0b3fe434..abbf9189b 100644 --- a/core/unicode/tables.odin +++ b/core/unicode/tables.odin @@ -540,6 +540,7 @@ to_upper_ranges := [?]i32{ @(rodata) to_upper_singlets := [?]i32{ + 0x00df, 8115, 0x00ff, 621, 0x0101, 499, 0x0103, 499, @@ -1204,6 +1205,7 @@ to_lower_singlets := [?]i32{ 0x1e90, 501, 0x1e92, 501, 0x1e94, 501, + 0x1e9e, -7115, 0x1ea0, 501, 0x1ea2, 501, 0x1ea4, 501, diff --git a/core/unicode/tools/generate_entity_table.odin b/core/unicode/tools/generate_entity_table.odin index 020ef94e4..7d53e5497 100644 --- a/core/unicode/tools/generate_entity_table.odin +++ b/core/unicode/tools/generate_entity_table.odin @@ -1,233 +1,12 @@ -package xml_example +package xml_tools -import "core:encoding/xml" -import "core:os" +import "core:encoding/xml" +import "core:os" import path "core:path/filepath" -import "core:mem" -import "core:strings" -import "core:strconv" -import "core:slice" -import "core:fmt" - -/* - Silent error handler for the parser. -*/ -Error_Handler :: proc(pos: xml.Pos, fmt: string, args: ..any) {} - -OPTIONS :: xml.Options{ flags = { .Ignore_Unsupported, }, expected_doctype = "unicode", } - -Entity :: struct { - name: string, - codepoint: rune, - description: string, -} - -generate_encoding_entity_table :: proc() { - filename := path.join({ODIN_ROOT, "tests", "core", "assets", "XML", "unicode.xml"}) - defer delete(filename) - - generated_filename := path.join({ODIN_ROOT, "core", "encoding", "entity", "generated.odin"}) - defer delete(generated_filename) - - doc, err := xml.load_from_file(filename, OPTIONS, Error_Handler) - defer xml.destroy(doc) - - if err != .None { - fmt.printf("Load/Parse error: %v\n", err) - if err == .File_Error { - fmt.printf("\"%v\" not found. Did you run \"tests\\download_assets.py\"?", filename) - } - os.exit(1) - } - - fmt.printf("\"%v\" loaded and parsed.\n", filename) - - generated_buf: strings.Builder - defer strings.builder_destroy(&generated_buf) - w := strings.to_writer(&generated_buf) - - charlist_id, charlist_ok := xml.find_child_by_ident(doc, 0, "charlist") - if !charlist_ok { - fmt.eprintln("Could not locate top-level `` tag.") - os.exit(1) - } - - charlist := doc.elements[charlist_id] - - fmt.printf("Found `` with %v children.\n", len(charlist.value)) - - entity_map: map[string]Entity - names: [dynamic]string - - min_name_length := max(int) - max_name_length := min(int) - shortest_name: string - longest_name: string - - count := 0 - for char_id in charlist.value { - id := char_id.(xml.Element_ID) - char := doc.elements[id] - - if char.ident != "character" { - fmt.eprintf("Expected ``, got `<%v>`\n", char.ident) - os.exit(1) - } - - if codepoint_string, ok := xml.find_attribute_val_by_key(doc, id, "dec"); !ok { - fmt.eprintln("`` attribute not found.") - os.exit(1) - } else { - codepoint := strconv.atoi(codepoint_string) - - desc, desc_ok := xml.find_child_by_ident(doc, id, "description") - description := "" - if len(doc.elements[desc].value) == 1 { - description = doc.elements[desc].value[0].(string) - } - - /* - For us to be interested in this codepoint, it has to have at least one entity. - */ - - nth := 0 - for { - character_entity := xml.find_child_by_ident(doc, id, "entity", nth) or_break - nth += 1 - name := xml.find_attribute_val_by_key(doc, character_entity, "id") or_continue - if len(name) == 0 { - /* - Invalid name. Skip. - */ - continue - } - - if name == "\"\"" { - fmt.printf("%#v\n", char) - fmt.printf("%#v\n", character_entity) - } - - if len(name) > max_name_length { longest_name = name } - if len(name) < min_name_length { shortest_name = name } - - min_name_length = min(min_name_length, len(name)) - max_name_length = max(max_name_length, len(name)) - - e := Entity{ - name = name, - codepoint = rune(codepoint), - description = description, - } - - if name in entity_map { - continue - } - - entity_map[name] = e - append(&names, name) - count += 1 - } - } - } - - /* - Sort by name. - */ - slice.sort(names[:]) - - fmt.printf("Found %v unique `&name;` -> rune mappings.\n", count) - fmt.printf("Shortest name: %v (%v)\n", shortest_name, min_name_length) - fmt.printf("Longest name: %v (%v)\n", longest_name, max_name_length) - - /* - Generate table. - */ - fmt.wprintln(w, "package encoding_unicode_entity") - fmt.wprintln(w, "") - fmt.wprintln(w, GENERATED) - fmt.wprintln(w, "") - fmt.wprintf (w, TABLE_FILE_PROLOG) - fmt.wprintln(w, "") - - fmt.wprintf (w, "// `&%v;`\n", shortest_name) - fmt.wprintf (w, "XML_NAME_TO_RUNE_MIN_LENGTH :: %v\n", min_name_length) - fmt.wprintf (w, "// `&%v;`\n", longest_name) - fmt.wprintf (w, "XML_NAME_TO_RUNE_MAX_LENGTH :: %v\n", max_name_length) - fmt.wprintln(w, "") - - fmt.wprintln(w, -` -/* - Input: - entity_name - a string, like "copy" that describes a user-encoded Unicode entity as used in XML. - - Returns: - "decoded" - The decoded rune if found by name, or -1 otherwise. - "ok" - true if found, false if not. - - IMPORTANT: XML processors (including browsers) treat these names as case-sensitive. So do we. -*/ -named_xml_entity_to_rune :: proc(name: string) -> (decoded: rune, ok: bool) { - /* - Early out if the name is too short or too long. - min as a precaution in case the generated table has a bogus value. - */ - if len(name) < min(1, XML_NAME_TO_RUNE_MIN_LENGTH) || len(name) > XML_NAME_TO_RUNE_MAX_LENGTH { - return -1, false - } - - switch rune(name[0]) { -`) - - prefix := '?' - should_close := false - - for v in names { - if rune(v[0]) != prefix { - if should_close { - fmt.wprintln(w, "\t\t}\n") - } - - prefix = rune(v[0]) - fmt.wprintf (w, "\tcase '%v':\n", prefix) - fmt.wprintln(w, "\t\tswitch name {") - } - - e := entity_map[v] - - fmt.wprintf(w, "\t\tcase \"%v\":", e.name) - for i := len(e.name); i < max_name_length; i += 1 { - fmt.wprintf(w, " ") - } - fmt.wprintf(w, " // %v\n", e.description) - fmt.wprintf(w, "\t\t\treturn %v, true\n", rune_to_string(e.codepoint)) - - should_close = true - } - fmt.wprintln(w, "\t\t}") - fmt.wprintln(w, "\t}") - fmt.wprintln(w, "\treturn -1, false") - fmt.wprintln(w, "}\n") - fmt.wprintln(w, GENERATED) - - fmt.println() - fmt.println(strings.to_string(generated_buf)) - fmt.println() - - written := os.write_entire_file(generated_filename, transmute([]byte)strings.to_string(generated_buf)) - - if written { - fmt.printf("Successfully written generated \"%v\".\n", generated_filename) - } else { - fmt.printf("Failed to write generated \"%v\".\n", generated_filename) - } - - delete(entity_map) - delete(names) - for &name in names { - free(&name) - } -} +import "core:strings" +import "core:strconv" +import "core:slice" +import "core:fmt" GENERATED :: `/* ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ @@ -235,14 +14,14 @@ GENERATED :: `/* TABLE_FILE_PROLOG :: `/* This file is generated from "https://github.com/w3c/xml-entities/blob/gh-pages/unicode.xml". - + UPDATE: - - Ensure the XML file was downloaded using "tests\core\download_assets.py". + - Ensure the XML file was downloaded using "tests\core\download_assets.py", given the path to the "tests\assets" directory. - Run "core/unicode/tools/generate_entity_table.odin" Odin unicode generated tables: https://github.com/odin-lang/Odin/tree/master/core/encoding/entity - Copyright David Carlisle 1999-2023 + Copyright David Carlisle 1999-2025 Use and distribution of this code are permitted under the terms of the W3C Software Notice and License. @@ -262,33 +41,326 @@ TABLE_FILE_PROLOG :: `/* */ ` -rune_to_string :: proc(r: rune) -> (res: string) { - res = fmt.tprintf("%08x", int(r)) - for len(res) > 2 && res[:2] == "00" { - res = res[2:] - } - return fmt.tprintf("rune(0x%v)", res) +// Silent error handler for the parser. +Error_Handler :: proc(pos: xml.Pos, fmt: string, args: ..any) {} + +OPTIONS :: xml.Options{ flags = { .Ignore_Unsupported, }, expected_doctype = "unicode", } + +Entity :: struct { + codepoints: [2]rune, + name: string, // &name; + description: string, } -is_dotted_name :: proc(name: string) -> (dotted: bool) { - for r in name { - if r == '.' { return true} - } - return false +Character :: struct { + codepoint: rune, + category: string, + description: string, } main :: proc() { - track: mem.Tracking_Allocator - mem.tracking_allocator_init(&track, context.allocator) - context.allocator = mem.tracking_allocator(&track) + filename, err_xml := path.join({ODIN_ROOT, "tests", "core", "assets", "XML", "unicode.xml"}, context.allocator) + defer delete(filename) - generate_encoding_entity_table() + if err_xml != .None { + fmt.eprintfln("Join path error for unicode.xml: %v", err_xml) + os.exit(1) + } - if len(track.allocation_map) > 0 { - fmt.println() - for _, v in track.allocation_map { - fmt.printf("%v Leaked %v bytes.\n", v.location, v.size) + doc, err := xml.load_from_file(filename, OPTIONS, Error_Handler) + defer xml.destroy(doc) + + if err != .None { + fmt.eprintfln("Load/Parse error: %v", err) + if err == .File_Error { + fmt.eprintfln("%q not found. Did you run \"tests\\download_assets.py\"?", filename) + } + os.exit(1) + } + + fmt.printfln("%q loaded and parsed.", filename) + + charlist_id, charlist_ok := xml.find_child_by_ident(doc, 0, "charlist") + if !charlist_ok { + fmt.eprintln("Could not locate top-level `` tag.") + os.exit(1) + } + + charlist := doc.elements[charlist_id] + + fmt.printfln("Found `` with %v children.", len(charlist.value)) + + // These are for `core:encoding/entity`, and only keep track of codepoints which have + // one or more children pointing to it. + // + // This means that this array can have the same codepoint appear more than once, e.g. + // `Aring` and `angst` are both a capital A with a circle. The latter is the Angstrom symbol. + entities: [dynamic]Entity + defer delete(entities) + entity_map: map[string]Entity + defer delete(entity_map) + + min_name_length := max(int) + max_name_length := min(int) + shortest_name: string + longest_name: string + + // This is for `core:unicode`'s tables and has all children of `` + characters: [dynamic]Character + defer delete(characters) + + for char_id in charlist.value { + id := char_id.(xml.Element_ID) + char := doc.elements[id] + + if char.ident != "character" { + fmt.eprintfln("Expected `` child to be ``, got `<%v>`", char.ident) + os.exit(1) + } + + // `dec` is the codepoint, or codepoints separated by a `-`. + codepoint_string, ok := xml.find_attribute_val_by_key(doc, id, "dec") + if !ok { + fmt.eprintln("`` attribute not found.") + os.exit(1) + } + + r1, _, r2 := strings.partition(codepoint_string, "-") + + codepoint, codepoint2: int + codepoint, _ = strconv.parse_int(r1) + if r2 != "" { + codepoint2, _ = strconv.parse_int(r2) + } + + // This is the description we add to `core:encoding/entity`'s generated table + desc, desc_ok := xml.find_child_by_ident(doc, id, "description") + assert(desc_ok) + description := "" + if len(doc.elements[desc].value) == 1 { + description = doc.elements[desc].value[0].(string) + } + + // For us to be interested in a character for `core:unicode`, it has to have `` + // + // Not present for e.g. MULTIPLE CHARACTER OPERATOR: arccos + // and some maths characters without a character category + if unicodedata, unicodedata_ok := xml.find_child_by_ident(doc, id, "unicodedata"); unicodedata_ok { + // Not present for some math characters, e.g. codepoint: 10913-824, desc: "DOUBLE NESTED LESS-THAN with slash" + if category_string, category_ok := xml.find_attribute_val_by_key(doc, unicodedata, "category"); category_ok { + // These should only consist of a single rune. + assert(codepoint2 == 0) + append(&characters, Character{ + codepoint = rune(codepoint), + description = description, + category = category_string, + }) + } + } + + // For us to be interested in this codepoint for `core:encoding/entity`, it has to have at least one ``. + nth := 0 + for { + character_entity := xml.find_child_by_ident(doc, id, "entity", nth) or_break + nth += 1 + name := xml.find_attribute_val_by_key(doc, character_entity, "id") or_continue + if len(name) == 0 { + // Invalid name. Skip. + continue + } + + if len(name) > max_name_length { longest_name = name } + if len(name) < min_name_length { shortest_name = name } + + min_name_length = min(min_name_length, len(name)) + max_name_length = max(max_name_length, len(name)) + + if name in entity_map { + continue + } + + e := Entity{ + name = name, + codepoints = {rune(codepoint), rune(codepoint2)}, + description = description, + } + + entity_map[name] = e + append(&entities, e) } } - fmt.println("Done and cleaned up!") + + write_encoding_entitities_table(entities[:], shortest_name, longest_name, min_name_length, max_name_length) + fmt.println() + write_unicode_category_tables(characters[:]) + + // Not a library, no need to clean up. +} + +write_encoding_entitities_table :: proc(entities: []Entity, shortest_name, longest_name: string, min_name_length, max_name_length: int) { + fmt.printfln("Found %v unique `&name;` -> rune mappings.", len(entities)) + fmt.printfln("Shortest name: %v (%v)", shortest_name, min_name_length) + fmt.printfln("Longest name: %v (%v)", longest_name, max_name_length) + + generated_filename, err_generated := path.join({ODIN_ROOT, "core", "encoding", "entity", "generated.odin"}, context.allocator) + defer delete(generated_filename) + + if err_generated != .None { + fmt.eprintfln("Join path error for generated.odin: %v", err_generated) + os.exit(1) + } + + generated_buf: strings.Builder + defer strings.builder_destroy(&generated_buf) + w := strings.to_writer(&generated_buf) + + // Generate table. + fmt.wprintln(w, "package encoding_unicode_entity") + fmt.wprintln(w, "") + fmt.wprintln(w, GENERATED) + fmt.wprintln(w, "") + fmt.wprintf (w, TABLE_FILE_PROLOG) + fmt.wprintln(w, "") + + fmt.wprintfln(w, "// `&%v;`", shortest_name) + fmt.wprintfln(w, "XML_NAME_TO_RUNE_MIN_LENGTH :: %v", min_name_length) + fmt.wprintfln(w, "// `&%v;`", longest_name) + fmt.wprintfln(w, "XML_NAME_TO_RUNE_MAX_LENGTH :: %v", max_name_length) + fmt.wprintln(w, "") + + fmt.wprintln(w, +` +/* + Input: + entity_name - a string, like "copy" that describes a user-encoded Unicode entity as used in XML. + + Returns: + "decoded" - The decoded runes if found by name, or all zero otherwise. + "rune_count" - The number of decoded runes + "ok" - true if found, false if not. + + IMPORTANT: XML processors (including browsers) treat these names as case-sensitive. So do we. +*/ +named_xml_entity_to_rune :: proc(name: string) -> (decoded: [2]rune, rune_count: int, ok: bool) { + /* + Early out if the name is too short or too long. + min as a precaution in case the generated table has a bogus value. + */ + if len(name) < min(1, XML_NAME_TO_RUNE_MIN_LENGTH) || len(name) > XML_NAME_TO_RUNE_MAX_LENGTH { + return + } + + switch rune(name[0]) {`) + + prefix := '?' + should_close := false + + slice.sort_by(entities, proc(a, b: Entity) -> bool { + return a.name < b.name + }) + + for e in entities { + if rune(e.name[0]) != prefix { + if should_close { + fmt.wprintln(w, "\t\t}\n") + } + + prefix = rune(e.name[0]) + fmt.wprintfln(w, "\tcase '%v':", prefix) + fmt.wprintln(w, "\t\tswitch name {") + } + + fmt.wprintf(w, "\t\tcase \"%v\":", e.name) + for i := len(e.name); i < max_name_length; i += 1 { + fmt.wprintf(w, " ") + } + fmt.wprintf(w, " // %v\n", e.description) + if e.codepoints[1] != 0 { + fmt.wprintf(w, "\t\t\treturn {{%q, %q}}, 2, true\n", e.codepoints[0], e.codepoints[1]) + } else { + fmt.wprintf(w, "\t\t\treturn {{%q, 0}}, 1, true\n", e.codepoints[0]) + } + should_close = true + } + fmt.wprintln(w, "\t\t}") + fmt.wprintln(w, "\t}") + fmt.wprintln(w, "\treturn") + fmt.wprintln(w, "}\n") + fmt.wprintln(w, GENERATED) + + fmt.println() + when ODIN_DEBUG { + fmt.println(strings.to_string(generated_buf)) + fmt.println() + } + + written := os.write_entire_file(generated_filename, transmute([]byte)strings.to_string(generated_buf)) + + if written == nil { + fmt.printfln("Successfully written generated \"%v\".", generated_filename) + } else { + fmt.printfln("Failed to write generated \"%v\".", generated_filename) + } +} + +write_unicode_category_tables :: proc(characters: []Character) { + fmt.printfln("Found %v codepoints with a category.", len(characters)) + + // Sort by `category`, then `codepoints` + slice.sort_by(characters, proc(a, b: Character) -> bool { + return a.category < b.category && a.codepoint < b.codepoint + }) + + nd_range_start := rune(-1) + nd_range_end := rune(-1) + nd_last: rune + for c in characters { + // Find contiguous ranges for the `Nd` category + if c.category == "Nd" { + defer nd_last = c.codepoint + + // New range start + if c.codepoint != nd_last + 1 { + nd_range_end = nd_last + if nd_range_start != rune(-1) { + // Found a range + // fmt.printfln("%r (%d) - %r (%d) // %s", nd_range_start, nd_range_start, nd_range_end, nd_range_end, c.description) + } + nd_range_start = c.codepoint + } + } + } + + /* + Lu Letter, Uppercase + Ll Letter, Lowercase + Lt Letter, Titlecase + Lm Letter, Modifier + Lo Letter, Other + Mn Mark, Nonspacing + Mc Mark, Spacing Combining + Me Mark, Enclosing + Nd Number, Decimal Digit + Nl Number, Letter + No Number, Other + Pc Punctuation, Connector + Pd Punctuation, Dash + Ps Punctuation, Open + Pe Punctuation, Close + Pi Punctuation, Initial quote (may behave like Ps or Pe depending on usage) + Pf Punctuation, Final quote (may behave like Ps or Pe depending on usage) + Po Punctuation, Other + Sm Symbol, Math + Sc Symbol, Currency + Sk Symbol, Modifier + So Symbol, Other + Zs Separator, Space + Zl Separator, Line + Zp Separator, Paragraph + Cc Other, Control + Cf Other, Format + Cs Other, Surrogate + Co Other, Private Use + Cn Other, Not Assigned (no characters in the file have this property) + */ } \ No newline at end of file diff --git a/core/unicode/tools/ucd/generate_unicode.odin b/core/unicode/tools/ucd/generate_unicode.odin new file mode 100644 index 000000000..9494674a1 --- /dev/null +++ b/core/unicode/tools/ucd/generate_unicode.odin @@ -0,0 +1,287 @@ +package ucd + +import "core:fmt" +import "core:os" +import "core:strings" +import "core:mem" +import "core:io" +import "core:log" + +// Table 2-3. Types of Code Points +// Table 4-4. General_Category Values page 229 +// Reference https://www.unicode.org/reports/tr44/ + +/* +Formats a `Dynamic_Range` into a set of fixed length arrays and writes them to an `io.Writer`. +The value of the parameter `name` will be used as a prefix to the array names. + +If a dynamic array contained in the `range` is empty, no corresponding fixed length array will be written. + +Inputs: +- writer: The `io.Writer` to be written to. +- name: Prefix to add to any array that is written to `writer` +- range: `The Dynamic_Range` to format and write to writer. +*/ +write_range_arrays :: proc(writer: io.Writer, name: string, range: Dynamic_Range) { + if len(range.single_16) > 0 { + fmt.wprintln(writer, "@(rodata)") + fmt.wprintf(writer, "%s_singles16 := [?]u16{{", name) + for v, count in range.single_16 { + if count % 8 == 0 { + fmt.wprintf(writer, "\n\t0x%4X,", v) + continue + } else { + fmt.wprintf(writer, " 0x%4X,", v) + } + } + fmt.wprintln(writer, "\n}\n") + } + + if len(range.ranges_16) > 0 { + fmt.wprintln(writer, "@(rodata)") + fmt.wprintfln(writer, "%s_ranges16 := [?]u16{{", name) + for v in range.ranges_16 { + fmt.wprintfln(writer, "\t0x%4X, 0x%4X,", v.first, v.last) + } + fmt.wprintln(writer, "}\n") + } + + if len(range.single_32) > 0 { + fmt.wprintln(writer, "@(rodata)") + fmt.wprintf(writer, "%s_singles32 := [?]i32{{", name) + for v, count in range.single_32 { + if count % 8 == 0 { + fmt.wprintf(writer, "\n\t0x%4X,", v) + continue + } else { + fmt.wprintf(writer, " 0x%4X,", v) + } + } + fmt.wprintln(writer, "\n}\n") + } + + if len(range.ranges_32) > 0 { + fmt.wprintln(writer, "@(rodata)") + fmt.wprintfln(writer, "%s_ranges32 := [?]i32{{", name) + for v in range.ranges_32 { + fmt.wprintfln(writer, "\t0x%4X, 0x%4X,", v.first, v.last) + } + fmt.wprintln(writer, "}\n") + } + + return +} + +write_range :: proc(writer: io.Writer, name: union{string, General_Category}, range: Dynamic_Range) { + buffer: [128]byte + str: string + + switch n in name { + case string: + assert(len(n) <= len(buffer)) + copy(buffer[:], n) + str = string(buffer[:len(n)]) + + case General_Category: + str = fmt.bprintf(buffer[:], "%s", n) + } + + // lowercase table names + for &b in buffer[0:len(str)] { + if b >= 'A' && b <= 'Z' { + b += ('a' - 'A') + } + } + + write_range_arrays(writer, str, range) + + fmt.wprintfln(writer, "%s_ranges := Range{{", str) + if len(range.single_16) > 0 { + fmt.wprintfln(writer, "\tsingle_16 = %s_singles16[:],", str) + } + if len(range.ranges_16) > 0 { + fmt.wprintfln(writer, "\tranges_16 = %s_ranges16[:],", str) + } + if len(range.single_32) > 0 { + fmt.wprintfln(writer, "\tsingle_32 = %s_singles32[:],", str) + } + if len(range.ranges_32) > 0 { + fmt.wprintfln(writer, "\tranges_32 = %s_ranges32[:],", str) + } + fmt.wprintln(writer, "}\n") + + return +} + +GENERATED :: `/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ +` + +MESSAGE :: `/* + This file is generated from UnicodeData.txt and PropList.txt. These files + are part of the Unicode Database (UCD) and are covered by the license + listed further down. They may be downloaded from the following locations; + + https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt + https://www.unicode.org/license.txt + + ------------------------------------------------------------------------------ + UNICODE LICENSE V3 + + COPYRIGHT AND PERMISSION NOTICE + + Copyright © 1991-2026 Unicode, Inc. + + NOTICE TO USER: Carefully read the following legal agreement. BY + DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR + SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE + TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT + DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of data files and any associated documentation (the "Data Files") or + software and any associated documentation (the "Software") to deal in the + Data Files or Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, and/or sell + copies of the Data Files or Software, and to permit persons to whom the + Data Files or Software are furnished to do so, provided that either (a) + this copyright and permission notice appear with all copies of the Data + Files or Software, or (b) this copyright and permission notice appear in + associated Documentation. + + THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + THIRD PARTY RIGHTS. + + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE + BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA + FILES OR SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in these Data Files or Software without prior written + authorization of the copyright holder. + +*/ +` + +main :: proc() { + track: mem.Tracking_Allocator + + mem.tracking_allocator_init(&track, context.allocator) + defer { + if len(track.allocation_map) > 0 { + fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map)) + for _, entry in track.allocation_map { + fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location) + } + } + mem.tracking_allocator_destroy(&track) + } + + context.allocator = mem.tracking_allocator(&track) + + context.logger = log.create_console_logger() + defer log.destroy_console_logger(context.logger) + + ucd_path := ODIN_ROOT + "tests/core/assets/UCD/UnicodeData.txt" + + unicode_data, ucd_err := load_unicode_data(ucd_path) + if ucd_err != nil { + log.errorf("Error loading Unicode data. %s", ucd_err) + } + defer destroy_unicode_data(unicode_data) + + general_category_ranges := gc_ranges(&unicode_data) + defer destroy_general_category_ranges(general_category_ranges) + + extra_digits := extra_digits(&unicode_data) + defer destroy_dynamic_range(extra_digits) + + + proplist_path := ODIN_ROOT + "tests/core/assets/UCD/PropList.txt" + proplist, proplist_err := load_property_list(proplist_path) + if proplist_err != nil { + log.errorf("Error loading PropList.txt. %s", proplist_err) + return + } + defer destroy_property_list(proplist) + + sb := strings.builder_make_len_cap(0, 1024*32) + defer strings.builder_destroy(&sb) + + writer := strings.to_writer(&sb) + + fmt.wprintfln(writer, "package unicode\n") + fmt.wprintln(writer, GENERATED) + fmt.wprintln(writer, MESSAGE) + + Range_Type :: "Range :: struct {\n" + + "\tsingle_16 : []u16,\n" + + "\tranges_16 : []u16,\n" + + "\tsingle_32 : []i32,\n" + + "\tranges_32 : []i32,\n" + + "}\n" + + fmt.wprintfln(writer, "%s", Range_Type) + + //List of the general categories to skip when generating the code for + //core/unicode/generated.txt. + to_exclude := [?]General_Category{ + .Cc, // Control, a C0 or C1 control code + .Cf, // Format, a format control character + .Cn, // Unassigned, a reserved unassigned code point or a noncharacter + .Co, // Private_Use, a private-use character + .Cs, // Surrogate, a surrogate code point + // .Ll, // Lowercase_Letter, a lowercase letter + // .Lm, // Modifier_Letter, a modifier letter + // .Lo, // Other_Letter, other letters, including syllables and ideographs + // .Lt, // Titlecase_Letter, a digraph encoded as a single character, with first part uppercase + // .Lu, // Uppercase_Letter, an uppercase letter + // .Mc, // Spacing_Mark, a spacing combining mark (positive advance width) + // .Me, // Enclosing_Mark, an enclosing combining mark + // .Mn, // Nonspacing_Mark, a nonspacing combining mark (zero advance width) + //.Nd, // Decimal_Number, a decimal digit + //.Nl, // Letter_Number, a letterlike numeric character + //.No, // Other_Number, a numeric character of other type + // .Pc, // Connector_Punctuation, a connecting punctuation mark, like a tie + // .Pd, // Dash_Punctuation, a dash or hyphen punctuation mark + // .Pe, // Close_Punctuation, a closing punctuation mark (of a pair) + // .Pf, // Final_Punctuation, a final quotation mark + // .Pi, // Initial_Punctuation, an initial quotation mark + // .Po, // Other_Punctuation, a punctuation mark of other type + // .Ps, // Open_Punctuation, an opening punctuation mark (of a pair) + // .Sc, // Currency_Symbol, a currency sign + // .Sk, // Modifier_Symbol, a non-letterlike modifier symbol + // .Sm, // Math_Symbol, a symbol of mathematical use + // .So, // Other_Symbol, a symbol of other type + .Zl, // Line_Separator, U+2028 LINE SEPARATOR only + .Zp, // Paragraph_Separator, U+2029 PARAGRAPH SEPARATOR only + //.Zs, // Space_Separator, a space character (of various non-zero widths) + } + + write_loop: for range, category in general_category_ranges { + for excluded in to_exclude { + if category == excluded { + continue write_loop + } + } + write_range(writer, category, range) + } + + write_range(writer, "extra_digits", extra_digits) + write_range(writer, "other_lowercase", proplist[.Other_Lowercase]) + write_range(writer, "other_uppercase", proplist[.Other_Uppercase]) + + file_name := ODIN_ROOT + "core/unicode/generated.odin" + + if write_error := os.write_entire_file_from_string(file_name, strings.to_string(sb)); write_error != nil { + log.errorf("Error %v writing %q", write_error, file_name) + } +} \ No newline at end of file diff --git a/core/unicode/tools/ucd/string_to.odin b/core/unicode/tools/ucd/string_to.odin new file mode 100644 index 000000000..873c162b7 --- /dev/null +++ b/core/unicode/tools/ucd/string_to.odin @@ -0,0 +1,163 @@ +package ucd + +string_to_general_category :: proc "contextless" (str: string) -> (gc: General_Category, err: Error) { + switch str { + case "Lu": gc = .Lu + case "Ll": gc = .Ll + case "Lt": gc = .Lt + case "Lm": gc = .Lm + case "Lo": gc = .Lo + case "Mn": gc = .Mn + case "Mc": gc = .Mc + case "Me": gc = .Me + case "Nd": gc = .Nd + case "Nl": gc = .Nl + case "No": gc = .No + case "Pc": gc = .Pc + case "Pd": gc = .Pd + case "Ps": gc = .Ps + case "Pe": gc = .Pe + case "Pi": gc = .Pi + case "Pf": gc = .Pf + case "Po": gc = .Po + case "Sm": gc = .Sm + case "Sc": gc = .Sc + case "Sk": gc = .Sk + case "So": gc = .So + case "Zs": gc = .Zs + case "Zl": gc = .Zl + case "Zp": gc = .Zp + case "Cc": gc = .Cc + case "Cf": gc = .Cf + case "Cs": gc = .Cs + case "Co": gc = .Co + case "Cn": gc = .Cn + case: err = .Invalid_General_Category + } + return +} + +string_to_proplist_property :: proc(str: string) -> (prop: Prop_List_Property, err: Error) { + switch str { + case "White_Space": prop = .White_Space + case "Bidi_Control": prop = .Bidi_Control + case "Join_Control": prop = .Join_Control + case "Dash": prop = .Dash + case "Hyphen": prop = .Hyphen + case "Quotation_Mark": prop = .Quotation_Mark + case "Terminal_Punctuation": prop = .Terminal_Punctuation + case "Other_Math": prop = .Other_Math + case "Hex_Digit": prop = .Hex_Digit + case "ASCII_Hex_Digit": prop = .ASCII_Hex_Digit + case "Other_Alphabetic": prop = .Other_Alphabetic + case "Ideographic": prop = .Ideographic + case "Diacritic": prop = .Diacritic + case "Extender": prop = .Extender + case "Other_Lowercase": prop = .Other_Lowercase + case "Other_Uppercase": prop = .Other_Uppercase + case "Noncharacter_Code_Point": prop = .Noncharacter_Code_Point + case "Other_Grapheme_Extend": prop = .Other_Grapheme_Extend + case "IDS_Binary_Operator": prop = .IDS_Binary_Operator + case "IDS_Trinary_Operator": prop = .IDS_Trinary_Operator + case "IDS_Unary_Operator": prop = .IDS_Unary_Operator + case "Radical": prop = .Radical + case "Unified_Ideograph": prop = .Unified_Ideograph + case "Other_Default_Ignorable_Code_Point": prop = .Other_Default_Ignorable_Code_Point + case "Deprecated": prop = .Deprecated + case "Soft_Dotted": prop = .Soft_Dotted + case "Logical_Order_Exception": prop = .Logical_Order_Exception + case "Other_ID_Start": prop = .Other_ID_Start + case "Other_ID_Continue": prop = .Other_ID_Continue + case "ID_Compat_Math_Continue": prop = .ID_Compat_Math_Continue + case "ID_Compat_Math_Start": prop = .ID_Compat_Math_Start + case "Sentence_Terminal": prop = .Sentence_Terminal + case "Variation_Selector": prop = .Variation_Selector + case "Pattern_White_Space": prop = .Pattern_White_Space + case "Pattern_Syntax": prop = .Pattern_Syntax + case "Prepended_Concatenation_Mark": prop = .Prepended_Concatenation_Mark + case "Regional_Indicator": prop = .Regional_Indicator + case "Modifier_Combining_Mark": prop = .Modifier_Combining_Mark + case: prop = .Unknown + err = UCD_Error.Unknown_Property + } + return +} + +@(deprecated="Unused?") +string_to_age :: proc "contextless" (str: string) -> (age: Age) { + switch str { + case "1.1": age = .Age_1_1 + case "2.0": age = .Age_2_0 + case "2.1": age = .Age_2_1 + case "3.0": age = .Age_3_0 + case "3.1": age = .Age_3_1 + case "3.2": age = .Age_3_2 + case "4.0": age = .Age_4_0 + case "4.1": age = .Age_4_1 + case "5.0": age = .Age_5_0 + case "5.1": age = .Age_5_1 + case "5.2": age = .Age_5_2 + case "6.0": age = .Age_6_0 + case "6.1": age = .Age_6_1 + case "6.2": age = .Age_6_2 + case "6.3": age = .Age_6_3 + case "7.0": age = .Age_7_0 + case "8.0": age = .Age_8_0 + case "9.0": age = .Age_9_0 + case "10.0": age = .Age_10_0 + case "11.0": age = .Age_11_0 + case "12.0": age = .Age_12_0 + case "12.1": age = .Age_12_1 + case "13.0": age = .Age_13_0 + case "14.0": age = .Age_14_0 + case "15.0": age = .Age_15_0 + case "15.1": age = .Age_15_1 + case "16.0": age = .Age_16_0 + case "17.0": age = .Age_17_0 + case "unassigned": age = .Age_Unassigned + case: age = .Age_Unknown + } + return +} + +@(deprecated="Unused?") +string_to_paired_bracket_type :: proc "contextless" (str: string) -> (pbt: Paired_Bracket_Type) { + switch str { + case "o": pbt = .Open + case "c": pbt = .Close + case "n": pbt = .None + case: pbt = .Unknown + } + return +} + +@(deprecated="Unused?") +string_to_bidi_class :: proc "contextless" (str: string) -> (class: Bidi_Class) { + switch str { + case "AL": class = .AL + case "AN": class = .AN + case "B": class = .B + case "BN": class = .BN + case "CS": class = .CS + case "EN": class = .EN + case "ES": class = .ES + case "ET": class = .ET + case "FSI": class = .FSI + case "L": class = .L + case "LRE": class = .LRE + case "LRI": class = .LRI + case "LRO": class = .LRO + case "NSM": class = .NSM + case "ON": class = .ON + case "PDF": class = .PDF + case "PDI": class = .PDI + case "R": class = .R + case "RLE": class = .RLE + case "RLI": class = .RLI + case "RLO": class = .RLO + case "S": class = .S + case "WS": class = .WS + case: class = .Unknown + } + return +} diff --git a/core/unicode/tools/ucd/types.odin b/core/unicode/tools/ucd/types.odin new file mode 100644 index 000000000..5b87f96f8 --- /dev/null +++ b/core/unicode/tools/ucd/types.odin @@ -0,0 +1,694 @@ +package ucd + +import "core:os" + +Age :: enum byte { + Age_Unknown = 0, + Age_1_1, + Age_2_0, + Age_2_1, + Age_3_0, + Age_3_1, + Age_3_2, + Age_4_0, + Age_4_1, + Age_5_0, + Age_5_1, + Age_5_2, + Age_6_0, + Age_6_1, + Age_6_2, + Age_6_3, + Age_7_0, + Age_8_0, + Age_9_0, + Age_10_0, + Age_11_0, + Age_12_0, + Age_12_1, + Age_13_0, + Age_14_0, + Age_15_0, + Age_15_1, + Age_16_0, + Age_17_0, + Age_Unassigned, +} + +General_Category :: enum { + Cc, // Control, a C0 or C1 control code + Cf, // Format, a format control character + Cn, // Unassigned, a reserved unassigned code point or a noncharacter + Co, // Private_Use, a private-use character + Cs, // Surrogate, a surrogate code point + Ll, // Lowercase_Letter, a lowercase letter + Lm, // Modifier_Letter, a modifier letter + Lo, // Other_Letter, other letters, including syllables and ideographs + Lt, // Titlecase_Letter, a digraph encoded as a single character, with first part uppercase + Lu, // Uppercase_Letter, an uppercase letter + Mc, // Spacing_Mark, a spacing combining mark (positive advance width) + Me, // Enclosing_Mark, an enclosing combining mark + Mn, // Nonspacing_Mark, a nonspacing combining mark (zero advance width) + Nd, // Decimal_Number, a decimal digit + Nl, // Letter_Number, a letterlike numeric character + No, // Other_Number, a numeric character of other type + Pc, // Connector_Punctuation, a connecting punctuation mark, like a tie + Pd, // Dash_Punctuation, a dash or hyphen punctuation mark + Pe, // Close_Punctuation, a closing punctuation mark (of a pair) + Pf, // Final_Punctuation, a final quotation mark + Pi, // Initial_Punctuation, an initial quotation mark + Po, // Other_Punctuation, a punctuation mark of other type + Ps, // Open_Punctuation, an opening punctuation mark (of a pair) + Sc, // Currency_Symbol, a currency sign + Sk, // Modifier_Symbol, a non-letterlike modifier symbol + Sm, // Math_Symbol, a symbol of mathematical use + So, // Other_Symbol, a symbol of other type + Zl, // Line_Separator, U+2028 LINE SEPARATOR only + Zp, // Paragraph_Separator, U+2029 PARAGRAPH SEPARATOR only + Zs, // Space_Separator, a space character (of various non-zero widths) +} + +Block :: enum { + Nil = 0, + Adlam, + Aegean_Numbers, + Ahom, + Alchemical, + Alphabetic_PF, + Anatolian_Hieroglyphs, + Ancient_Greek_Music, + Ancient_Greek_Numbers, + Ancient_Symbols, + Arabic, + Arabic_Ext_A, + Arabic_Ext_B, + Arabic_Ext_C, + Arabic_Math, + Arabic_PF_A, + Arabic_PF_B, + Arabic_Sup, + Armenian, + Arrows, + ASCII, + Avestan, + Balinese, + Bamum, + Bamum_Sup, + Bassa_Vah, + Batak, + Bengali, + Beria_Erfe, + Bhaiksuki, + Block_Elements, + Bopomofo, + Bopomofo_Ext, + Box_Drawing, + Brahmi, + Braille, + Buginese, + Buhid, + Byzantine_Music, + Carian, + Caucasian_Albanian, + Chakma, + Cham, + Cherokee, + Cherokee_Sup, + Chess_Symbols, + Chorasmian, + CJK, + CJK_Compat, + CJK_Compat_Forms, + CJK_Compat_Ideographs, + CJK_Compat_Ideographs_Sup, + CJK_Ext_A, + CJK_Ext_B, + CJK_Ext_C, + CJK_Ext_D, + CJK_Ext_E, + CJK_Ext_F, + CJK_Ext_G, + CJK_Ext_H, + CJK_Ext_I, + CJK_Ext_J, + CJK_Radicals_Sup, + CJK_Strokes, + CJK_Symbols, + Compat_Jamo, + Control_Pictures, + Coptic, + Coptic_Epact_Numbers, + Counting_Rod, + Cuneiform, + Cuneiform_Numbers, + Currency_Symbols, + Cypriot_Syllabary, + Cypro_Minoan, + Cyrillic, + Cyrillic_Ext_A, + Cyrillic_Ext_B, + Cyrillic_Ext_C, + Cyrillic_Ext_D, + Cyrillic_Sup, + Deseret, + Devanagari, + Devanagari_Ext, + Devanagari_Ext_A, + Diacriticals, + Diacriticals_Ext, + Diacriticals_For_Symbols, + Diacriticals_Sup, + Dingbats, + Dives_Akuru, + Dogra, + Domino, + Duployan, + Early_Dynastic_Cuneiform, + Egyptian_Hieroglyph_Format_Controls, + Egyptian_Hieroglyphs, + Egyptian_Hieroglyphs_Ext_A, + Elbasan, + Elymaic, + Emoticons, + Enclosed_Alphanum, + Enclosed_Alphanum_Sup, + Enclosed_CJK, + Enclosed_Ideographic_Sup, + Ethiopic, + Ethiopic_Ext, + Ethiopic_Ext_A, + Ethiopic_Ext_B, + Ethiopic_Sup, + Garay, + Geometric_Shapes, + Geometric_Shapes_Ext, + Georgian, + Georgian_Ext, + Georgian_Sup, + Glagolitic, + Glagolitic_Sup, + Gothic, + Grantha, + Greek, + Greek_Ext, + Gujarati, + Gunjala_Gondi, + Gurmukhi, + Gurung_Khema, + Half_And_Full_Forms, + Half_Marks, + Hangul, + Hanifi_Rohingya, + Hanunoo, + Hatran, + Hebrew, + High_PU_Surrogates, + High_Surrogates, + Hiragana, + IDC, + Ideographic_Symbols, + Imperial_Aramaic, + Indic_Number_Forms, + Indic_Siyaq_Numbers, + Inscriptional_Pahlavi, + Inscriptional_Parthian, + IPA_Ext, + Jamo, + Jamo_Ext_A, + Jamo_Ext_B, + Javanese, + Kaithi, + Kaktovik_Numerals, + Kana_Ext_A, + Kana_Ext_B, + Kana_Sup, + Kanbun, + Kangxi, + Kannada, + Katakana, + Katakana_Ext, + Kawi, + Kayah_Li, + Kharoshthi, + Khitan_Small_Script, + Khmer, + Khmer_Symbols, + Khojki, + Khudawadi, + Kirat_Rai, + Lao, + Latin_1_Sup, + Latin_Ext_A, + Latin_Ext_Additional, + Latin_Ext_B, + Latin_Ext_C, + Latin_Ext_D, + Latin_Ext_E, + Latin_Ext_F, + Latin_Ext_G, + Lepcha, + Letterlike_Symbols, + Limbu, + Linear_A, + Linear_B_Ideograms, + Linear_B_Syllabary, + Lisu, + Lisu_Sup, + Low_Surrogates, + Lycian, + Lydian, + Mahajani, + Mahjong, + Makasar, + Malayalam, + Mandaic, + Manichaean, + Marchen, + Masaram_Gondi, + Math_Alphanum, + Math_Operators, + Mayan_Numerals, + Medefaidrin, + Meetei_Mayek, + Meetei_Mayek_Ext, + Mende_Kikakui, + Meroitic_Cursive, + Meroitic_Hieroglyphs, + Miao, + Misc_Arrows, + Misc_Math_Symbols_A, + Misc_Math_Symbols_B, + Misc_Pictographs, + Misc_Symbols, + Misc_Symbols_Sup, + Misc_Technical, + Modi, + Modifier_Letters, + Modifier_Tone_Letters, + Mongolian, + Mongolian_Sup, + Mro, + Multani, + Music, + Myanmar, + Myanmar_Ext_A, + Myanmar_Ext_B, + Myanmar_Ext_C, + Nabataean, + Nag_Mundari, + Nandinagari, + NB, + New_Tai_Lue, + Newa, + NKo, + Number_Forms, + Nushu, + Nyiakeng_Puachue_Hmong, + OCR, + Ogham, + Ol_Chiki, + Ol_Onal, + Old_Hungarian, + Old_Italic, + Old_North_Arabian, + Old_Permic, + Old_Persian, + Old_Sogdian, + Old_South_Arabian, + Old_Turkic, + Old_Uyghur, + Oriya, + Ornamental_Dingbats, + Osage, + Osmanya, + Ottoman_Siyaq_Numbers, + Pahawh_Hmong, + Palmyrene, + Pau_Cin_Hau, + Phags_Pa, + Phaistos, + Phoenician, + Phonetic_Ext, + Phonetic_Ext_Sup, + Playing_Cards, + Psalter_Pahlavi, + PUA, + Punctuation, + Rejang, + Rumi, + Runic, + Samaritan, + Saurashtra, + Sharada, + Sharada_Sup, + Shavian, + Shorthand_Format_Controls, + Siddham, + Sidetic, + Sinhala, + Sinhala_Archaic_Numbers, + Small_Forms, + Small_Kana_Ext, + Sogdian, + Sora_Sompeng, + Soyombo, + Specials, + Sundanese, + Sundanese_Sup, + Sunuwar, + Sup_Arrows_A, + Sup_Arrows_B, + Sup_Arrows_C, + Sup_Math_Operators, + Sup_PUA_A, + Sup_PUA_B, + Sup_Punctuation, + Sup_Symbols_And_Pictographs, + Super_And_Sub, + Sutton_SignWriting, + Syloti_Nagri, + Symbols_And_Pictographs_Ext_A, + Symbols_For_Legacy_Computing, + Symbols_For_Legacy_Computing_Sup, + Syriac, + Syriac_Sup, + Tagalog, + Tagbanwa, + Tags, + Tai_Le, + Tai_Tham, + Tai_Viet, + Tai_Xuan_Jing, + Tai_Yo, + Takri, + Tamil, + Tamil_Sup, + Tangsa, + Tangut, + Tangut_Components, + Tangut_Components_Sup, + Tangut_Sup, + Telugu, + Thaana, + Thai, + Tibetan, + Tifinagh, + Tirhuta, + Todhri, + Tolong_Siki, + Toto, + Transport_And_Map, + Tulu_Tigalari, + UCAS, + UCAS_Ext, + UCAS_Ext_A, + Ugaritic, + Vai, + Vedic_Ext, + Vertical_Forms, + Vithkuqi, + VS, + VS_Sup, + Wancho, + Warang_Citi, + Yezidi, + Yi_Radicals, + Yi_Syllables, + Yijing, + Zanabazar_Square, + Znamenny_Music, +} + +Combining_Class :: distinct byte + +Paired_Bracket_Type :: enum { + Unknown, + Open, + Close, + None, +} + +Bidi_Class :: enum { + Unknown, // + L, // Left-to-Right LRM + R, // Right-to-Left RLM + AL, // Right-to-Left Arabic ALM + EN, // European Number + ES, // European Number Separator + ET, // European Number Terminator + AN, // Arabic Number + CS, // Common Number Separator + NSM, // Nonspacing Mark + BN, // Boundary Neutral + B, // Paragraph Separator + S, // Segment Separator + WS, // Whitespace + ON, // Other Neutrals + LRE, // Left-to-Right Embedding LRE + LRO, // Left-to-Right Override LRO + RLE, // Right-to-Left Embedding RLE + RLO, // Right-to-Left Override RLO + PDF, // Pop Directional Format PDF + LRI, // Left-to-Right Isolate LRI + RLI, // Right-to-Left Isolate RLI + FSI, // First Strong Isolate FSI + PDI, // Pop Directional Isolate PDI +} + +Bidi :: struct { + bc: Bidi_Class, + bmg: Maybe(rune), // mirrored glyph + m: bool, // Bidi mirrored + c: bool, // Bidi control property + pb: Paired_Bracket_Type, // bidi paired bracket type + bpb: rune, // bidi paired bracket properties +} + +Decomposition_Type :: enum { + Nil = 0, + can, + com, + enc, + fin, + font, + fra, + init, + iso, + med, + nar, + nb, + sml, + sqr, + sub, + sup, + vert, + wid, + none, +} + +Trinary_Bool :: enum { + Maybe = -1, + False = 0, + True = 1, +} + +Decomposition_Mapping :: distinct [dynamic]rune + +Decomposition :: struct { + dt: Decomposition_Type, // Decomposition type + dm: Decomposition_Mapping, // Decomposition Mapping + ce: bool, // Composition Exclusion + comp_ex: bool, // Full Composition Exclusion + nfc_quick_check: Trinary_Bool, + nfd_quick_check: bool, + nfkc_quick_check: Trinary_Bool, + nfkd_quick_check: bool, +} + +Numeric_Type :: enum { + None = 0, // None + Decimal, // De + Digit, // Di + Numeric, // Nu +} + +/* +Note: Value is NAN when numberator and denominator ar 0 +*/ +Numberic_Value :: struct { + numerator: int, + denominator: int, +} + +Char :: struct { + cp: rune, + name: string, + gc: General_Category, + ccc: Combining_Class, + bc: Bidi_Class, + dt: Decomposition_Type, + dm: Decomposition_Mapping, + nt: Numeric_Type, + nv: Numberic_Value, + bm: bool, + name1: string, + sum: string, // Simple uppercase mapping + slm: string, // Simple lowercase mapping + stm: string, // Simple titlecase_mapping +} + +Char_Range :: struct { + first_cp: rune, + last_cp: rune, + name: string, + gc: General_Category, + ccc: Combining_Class, + bc: Bidi_Class, + dt: Decomposition_Type, + dm: Decomposition_Mapping, + nt: Numeric_Type, + nv: Numberic_Value, + bm: bool, + name1: string, + sum: string, // Simple uppercase mapping + slm: string, // Simple lowercase mapping + stm: string, // Simple titlecase_mapping +} + +Chars :: union { + Char, + Char_Range, +} + +Unicode_Data :: distinct [dynamic]Chars + + +Prop_List_Property :: enum { + Unknown, + White_Space, + Bidi_Control, + Join_Control, + Dash, + Hyphen, + Quotation_Mark, + Terminal_Punctuation, + Other_Math, + Hex_Digit, + ASCII_Hex_Digit, + Other_Alphabetic, + Ideographic, + Diacritic, + Extender, + Other_Lowercase, + Other_Uppercase, + Noncharacter_Code_Point, + Other_Grapheme_Extend, + IDS_Binary_Operator, + IDS_Trinary_Operator, + IDS_Unary_Operator, + Radical, + Unified_Ideograph, + Other_Default_Ignorable_Code_Point, + Deprecated, + Soft_Dotted, + Logical_Order_Exception, + Other_ID_Start, + Other_ID_Continue, + ID_Compat_Math_Continue, + ID_Compat_Math_Start, + Sentence_Terminal, + Variation_Selector, + Pattern_White_Space, + Pattern_Syntax, + Prepended_Concatenation_Mark, + Regional_Indicator, + Modifier_Combining_Mark, +} + +UCD_Error :: enum { + XML_LOAD_ERROR, + XML_Not_UCD, + Nil_XML_Document, + Element_Not_Repertoire, + Extra_Fields, + Unknown_Property, + Unknown_Bidi_Class, + + NO_REPERTOIRE, + UNEXPECTED_STRING, + Invalid_Hex_Number, + Invalid_General_Category, + UnicodeData_6_Too_Long, + UnicodeData_6_Invalid, + UnicodeData_7_Too_Long, + UnicodeData_7_Invalid, +} + + +Error :: union #shared_nil { + UCD_Error, + os.Error, +} + +Range_u16 :: struct { + first: u16, + last: u16, +} + +Range_i32 :: struct { + first: i32, + last: i32, +} + +Range_Rune :: struct { + first: rune, + last: rune, +} + +Dynamic_Range :: struct { + single_16: [dynamic]u16, + ranges_16: [dynamic]Range_u16, + single_32: [dynamic]i32, + ranges_32: [dynamic]Range_i32, +} + +append_to_dynamic_range :: proc(dr: ^Dynamic_Range, range: Range_Rune, allocator := context.allocator) { + if range.first == range.last && range.first <= 0xFFFF { + if len(dr.single_16) == 0 { + dr.single_16 = make([dynamic]u16, 0, 512, allocator) + } + append(&dr.single_16, cast(u16)range.first) + } else if range.first == range.last { + if len(dr.single_32) == 0 { + dr.single_32 = make([dynamic]i32, 0, 512, allocator) + } + append(&dr.single_32, cast(i32)range.first) + + } else if range.first <= 0xFFFF && range.last <= 0xFFFF { + if len(dr.ranges_16) == 0 { + dr.ranges_16 = make([dynamic]Range_u16, 0, 128, allocator) + } + r := Range_u16{ cast(u16)range.first, cast(u16)range.last} + append(&dr.ranges_16, r) + + } else { + if len(dr.ranges_32) == 0 { + dr.ranges_32 = make([dynamic]Range_i32, 0, 128, allocator) + } + r := Range_i32{ cast(i32)range.first, cast(i32)range.last} + append(&dr.ranges_32, r) + } +} + +destroy_dynamic_range :: proc(dr: Dynamic_Range) { + delete(dr.ranges_16) + delete(dr.ranges_32) + delete(dr.single_16) + delete(dr.single_32) +} + +destroy_general_category_ranges :: proc(gcr: [General_Category]Dynamic_Range) { + for r in gcr { + destroy_dynamic_range(r) + } +} \ No newline at end of file diff --git a/core/unicode/tools/ucd/ucd.odin b/core/unicode/tools/ucd/ucd.odin new file mode 100644 index 000000000..165147bbd --- /dev/null +++ b/core/unicode/tools/ucd/ucd.odin @@ -0,0 +1,290 @@ +package ucd + +import "core:strings" +import "core:os" +import "core:strconv" + +decode_rune :: proc(str: string) -> (cp1, cp2: rune, err: Error) { + head, _, tail := strings.partition(str, "..") + + if _cp1, _ok := strconv.parse_int(head, 16); !_ok { + return 0, 0, .Invalid_Hex_Number + } else { + cp1 = rune(_cp1) + } + + if len(tail) == 0 { + return cp1, cp1, nil + } + + if _cp2, _ok := strconv.parse_int(tail, 16); !_ok { + return 0, 0, .Invalid_Hex_Number + } else { + cp2 = rune(_cp2) + } + return +} + +load_unicode_data :: proc(filename: string, allocator := context.allocator) -> (unicode_data: Unicode_Data, err: Error) { + data := os.read_entire_file(filename, context.temp_allocator) or_return + defer free_all(context.temp_allocator) + + first_cp: rune + + str := string(data) + line_loop: for _line in strings.split_lines_iterator(&str) { + // Ignore any comments + line, _, _ := strings.partition(_line, "#") + + // Skip empty lines + if len(line) == 0 { continue } + + is_range := false + cp: rune + name: string + gc: General_Category + num_6: string + num_7: string + nt := Numeric_Type.None + + field_num := 0 + for _field in strings.split_iterator(&line, ";") { + defer field_num += 1 + field := strings.trim_space(_field) + + switch field_num { + case 0: // Code point + cp, _ = decode_rune(field) or_return + + case 1: // Name + if len(field) > 9 && field[0] == '<' && strings.ends_with(field, ", First>") { + first_cp = cp + continue line_loop + } + + if len(field) > 9 && field[0] == '<' && strings.ends_with(field, ", Last>") { + name = strings.clone(field[1:len(field)-7], allocator) + is_range = true + } else { + name = strings.clone(field[:], allocator) + } + + case 2: // General_Category + // NOTE: This is currently igorning a possible error it should probably be fixed + gc, _ = string_to_general_category(field) + + case 3: // Canonical_Combining_Class + case 4: // Bidi Class + case 5: // Decomposition_Type and Decomposition_Mapping + // Numeric_Type and Numeric_Value + case 6: + num_6 = field + + case 7: + num_7 = field + + case 8: + switch { + case num_6 != "" && num_7 != "" && field != "" : + nt = .Decimal + + case num_6 == "" && num_7 != "" && field != "" : + nt = .Digit + + case num_6 == "" && num_7 == "" && field != "" : + nt = .Numeric + + case: + nt = .None + } + + case 9: // Bidi mirrored + case 10: // Unicode 1 Name (Obsolete as of 6.2.0) + case 11: // should be null + case 12: + case 13: + case 14: + case: + err = .Extra_Fields + return + } + } + + if is_range { + append(&unicode_data, Char_Range { + gc = gc, + first_cp = first_cp, + last_cp = cp, + name = name, + nt = nt, + }) + } else { + append(&unicode_data, Char{ + gc = gc, + cp = cp, + name = name, + nt = nt, + }) + } + } + return +} + +destroy_unicode_data :: proc(unicode_data: Unicode_Data) { + for point in unicode_data { + switch p in point { + case Char: + delete(p.name) + case Char_Range: + delete(p.name) + } + } + delete(unicode_data) +} + + +gc_ranges :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (lst: [General_Category]Dynamic_Range) { + range := Range_Rune{ + first = -1, + last = -1, + } + gc: General_Category + + for point in ud { + switch p in point { + case Char: + if range.first != -1 && (p.cp != range.last + 1 || p.gc != gc) { + append_to_dynamic_range(&lst[gc], range, allocator) + range.first = -1 + range.last = -1 + } + + range.first = rune(min(u32(range.first), u32(p.cp))) + gc = p.gc + range.last = p.cp + + case Char_Range: + if range.first != -1 { + append_to_dynamic_range(&lst[gc], range, allocator) + } + + range.first = p.first_cp + range.last = p.last_cp + append_to_dynamic_range(&lst[p.gc], range ,allocator) + range.first = -1 + range.last = -1 + } + } + + if range.first != -1 { + append_to_dynamic_range(&lst[gc], range, allocator) + } + + return +} + + +extra_digits :: proc(ud: ^Unicode_Data, allocator := context.allocator) -> (Dynamic_Range) { + range := Range_Rune { + first = -1, + last = -1, + } + + exd: Dynamic_Range + for point in ud { + switch p in point { + + case Char: + exd_type := p.gc != .Nd && (p.nt == .Decimal || p.nt == .Digit) + + if range.first != -1 && (p.cp != range.last + 1 || !exd_type) { + append_to_dynamic_range(&exd, range, allocator) + range.first = -1 + range.last = -1 + } + + if exd_type { + range.first = rune(min(u32(range.first), u32(p.cp))) + range.last = p.cp + } + + case Char_Range: + exd_type := p.gc != .Nd && (p.nt == .Decimal || p.nt == .Digit) + + if range.first != -1 { + append_to_dynamic_range(&exd, range, allocator) + } + + if exd_type { + range.first = p.first_cp + range.last = p.last_cp + append_to_dynamic_range(&exd, range ,allocator) + } + range.first = -1 + range.last = -1 + } + } + if range.first != -1 { + append_to_dynamic_range(&exd, range, allocator) + } + + return exd +} + +/* +Data contained in the Unicode fiel PropList.txt + +A `Prop_List` is the data contained in the Unicode Database (UCD) file `PropList.txt`. +It is created with the procedure `load_property_list` and destroyed with the procedure `destroy_property_list`. +*/ +Prop_List :: [Prop_List_Property]Dynamic_Range + +/* +This function destroys a `Prop_List` created by `load_property_list`. + +Inputs: +- props: The Prop_List to destroy +*/ +destroy_property_list :: proc(props: Prop_List) { + for r in props { + delete(r.ranges_16) + delete(r.ranges_32) + delete(r.single_16) + delete(r.single_32) + } +} + + + +load_property_list :: proc(filename: string, allocator := context.allocator) -> (props: Prop_List, err: Error) { + data := os.read_entire_file(filename, allocator) or_return + defer delete(data) + + str := string(data) + for _line in strings.split_lines_iterator(&str) { + line, _, _ := strings.partition(_line, "#") + if len(line) == 0 { + continue + } + + rr: Range_Rune + prop: Prop_List_Property + + i := 0 + for _field in strings.split_iterator(&line, ";") { + defer i += 1 + field := strings.trim_space(_field) + + switch i { + // Code point or code point range + case 0: rr.first, rr.last = decode_rune(field) or_return + case 1: prop = string_to_proplist_property(field) or_return + case: return {}, .Extra_Fields + } + } + + append_to_dynamic_range(&props[prop], rr, allocator) + } + + return +} diff --git a/core/unicode/utf16/utf16.odin b/core/unicode/utf16/utf16.odin index e2bcf7f68..7396cb9e8 100644 --- a/core/unicode/utf16/utf16.odin +++ b/core/unicode/utf16/utf16.odin @@ -1,5 +1,7 @@ +// Procedures and constants to support text-encoding in the `UTF-16` character encoding. package utf16 +@(require) import "base:runtime" import "core:unicode/utf8" REPLACEMENT_CHAR :: '\ufffd' @@ -11,11 +13,11 @@ _surr3 :: 0xe000 _surr_self :: 0x10000 -is_surrogate :: proc(r: rune) -> bool { +is_surrogate :: proc "contextless" (r: rune) -> bool { return _surr1 <= r && r < _surr3 } -decode_surrogate_pair :: proc(r1, r2: rune) -> rune { +decode_surrogate_pair :: proc "contextless" (r1, r2: rune) -> rune { if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 { return (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self } @@ -23,7 +25,7 @@ decode_surrogate_pair :: proc(r1, r2: rune) -> rune { } -encode_surrogate_pair :: proc(c: rune) -> (r1, r2: rune) { +encode_surrogate_pair :: proc "contextless" (c: rune) -> (r1, r2: rune) { r := c if r < _surr_self || r > MAX_RUNE { return REPLACEMENT_CHAR, REPLACEMENT_CHAR @@ -32,24 +34,24 @@ encode_surrogate_pair :: proc(c: rune) -> (r1, r2: rune) { return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff } -encode :: proc(d: []u16, s: []rune) -> int { +encode :: proc "contextless" (d: []u16, s: []rune) -> int { n, m := 0, len(d) loop: for r in s { switch r { case 0..<_surr1, _surr3 ..< _surr_self: - if m+1 < n { break loop } + if n >= m { break loop } d[n] = u16(r) n += 1 case _surr_self ..= MAX_RUNE: - if m+2 < n { break loop } + if n+1 >= m { break loop } r1, r2 := encode_surrogate_pair(r) d[n] = u16(r1) d[n+1] = u16(r2) n += 2 case: - if m+1 < n { break loop } + if n >= m { break loop } d[n] = u16(REPLACEMENT_CHAR) n += 1 } @@ -58,24 +60,24 @@ encode :: proc(d: []u16, s: []rune) -> int { } -encode_string :: proc(d: []u16, s: string) -> int { +encode_string :: proc "contextless" (d: []u16, s: string) -> int { n, m := 0, len(d) loop: for r in s { switch r { case 0..<_surr1, _surr3 ..< _surr_self: - if m+1 < n { break loop } + if n >= m { break loop } d[n] = u16(r) n += 1 case _surr_self ..= MAX_RUNE: - if m+2 < n { break loop } + if n+1 >= m { break loop } r1, r2 := encode_surrogate_pair(r) d[n] = u16(r1) d[n+1] = u16(r2) n += 2 case: - if m+1 < n { break loop } + if n >= m { break loop } d[n] = u16(REPLACEMENT_CHAR) n += 1 } @@ -83,7 +85,7 @@ encode_string :: proc(d: []u16, s: string) -> int { return n } -decode :: proc(d: []rune, s: []u16) -> (n: int) { +decode :: proc "contextless" (d: []rune, s: []u16) -> (n: int) { for i := 0; i < len(s); i += 1 { if n >= len(d) { return @@ -106,7 +108,57 @@ decode :: proc(d: []rune, s: []u16) -> (n: int) { return } -rune_count :: proc(s: []u16) -> (n: int) { +decode_rune_in_string :: proc "contextless" (s: string16) -> (r: rune, width: int) { + r = rune(REPLACEMENT_CHAR) + n := len(s) + if n < 1 { + return + } + width = 1 + + + switch c := s[0]; { + case c < _surr1, _surr3 <= c: + r = rune(c) + case _surr1 <= c && c < _surr2 && 1 < len(s) && + _surr2 <= s[1] && s[1] < _surr3: + r = decode_surrogate_pair(rune(c), rune(s[1])) + width += 1 + } + return +} + +string_to_runes :: proc "odin" (s: string16, allocator := context.allocator) -> (runes: []rune, err: runtime.Allocator_Error) #optional_allocator_error { + n := rune_count(s) + + runes = make([]rune, n, allocator) or_return + i := 0 + for r in s { + runes[i] = r + i += 1 + } + return +} + + +rune_count :: proc{ + rune_count_in_string, + rune_count_in_slice, +} +rune_count_in_string :: proc "contextless" (s: string16) -> (n: int) { + for i := 0; i < len(s); i += 1 { + c := s[i] + if _surr1 <= c && c < _surr2 && i+1 < len(s) && + _surr2 <= s[i+1] && s[i+1] < _surr3 { + i += 1 + } + n += 1 + } + return +} + + +rune_count_in_slice :: proc "contextless" (s: []u16) -> (n: int) { for i := 0; i < len(s); i += 1 { c := s[i] if _surr1 <= c && c < _surr2 && i+1 < len(s) && @@ -119,7 +171,7 @@ rune_count :: proc(s: []u16) -> (n: int) { } -decode_to_utf8 :: proc(d: []byte, s: []u16) -> (n: int) { +decode_to_utf8 :: proc "contextless" (d: []byte, s: []u16) -> (n: int) { for i := 0; i < len(s); i += 1 { if n >= len(d) { return @@ -139,4 +191,4 @@ decode_to_utf8 :: proc(d: []byte, s: []u16) -> (n: int) { n += copy(d[n:], b[:w]) } return -} +} \ No newline at end of file diff --git a/core/unicode/utf8/grapheme.odin b/core/unicode/utf8/grapheme.odin index 50d1789ab..d8f6557b6 100644 --- a/core/unicode/utf8/grapheme.odin +++ b/core/unicode/utf8/grapheme.odin @@ -23,9 +23,40 @@ normalized_east_asian_width :: unicode.normalized_east_asian_width Grapheme :: struct { byte_index: int, rune_index: int, - width: int, + width: int, } + +Grapheme_Cluster_Sequence :: enum { + None, + Indic, + Emoji, + Regional, +} + +Grapheme_Iterator :: struct { + str: string, + curr_offset: int, + + grapheme_count: int, // The number of graphemes in the string + rune_count: int, // The number of runes in the string + width: int, // The widrth of the string in number of monospace cells + + last_rune: rune, + last_rune_breaks_forward: bool, + + last_width: int, + last_grapheme_count: int, + + bypass_next_rune: bool, + + regional_indicator_counter: int, + + current_sequence: Grapheme_Cluster_Sequence, + continue_sequence: bool, +} + + /* Count the individual graphemes in a UTF-8 string. @@ -39,7 +70,9 @@ Returns: */ @(require_results) grapheme_count :: proc(str: string) -> (graphemes, runes, width: int) { - _, graphemes, runes, width = decode_grapheme_clusters(str, false) + it := decode_grapheme_iterator_make(str) + for _, _ in decode_grapheme_iterate(&it) {/**/} + graphemes, runes, width = it.grapheme_count, it.rune_count, it.width return } @@ -70,155 +103,100 @@ decode_grapheme_clusters :: proc( rune_count: int, width: int, ) { - // The following procedure implements text segmentation by breaking on - // Grapheme Cluster Boundaries[1], using the values[2] and rules[3] from - // the Unicode® Standard Annex #29, entitled: - // - // UNICODE TEXT SEGMENTATION - // - // Version: Unicode 15.1.0 - // Date: 2023-08-16 - // Revision: 43 - // - // This procedure is conformant[4] to UAX29-C1-1, otherwise known as the - // extended, non-legacy ruleset. - // - // Please see the references below for more information. - // - // - // NOTE(Feoramund): This procedure has not been highly optimized. - // A couple opportunities were taken to bypass repeated checking when a - // rune is outside of certain codepoint ranges, but little else has been - // done. Standard switches, conditionals, and binary search are used to - // see if a rune fits into a certain category. - // - // I did find that only one prior rune of state was necessary to build an - // algorithm that successfully passes all 4,835 test cases provided with - // this implementation from the Unicode organization's website. - // - // My initial implementation tracked explicit breaks and counted them once - // the string iteration had terminated. I've found this current - // implementation to be far simpler and need no allocations (unless the - // caller wants position data). - // - // Most rules work backwards instead of forwards which has helped keep this - // simple, despite its length and verbosity. - // - // - // The implementation has been left verbose and in the order described by - // the specification, to enable better readability and future upkeep. - // - // Some possible optimizations might include: - // - // - saving the type of `last_rune` instead of the exact rune. - // - reordering rules. - // - combining tables. - // - // - // [1]: https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries - // [2]: https://www.unicode.org/reports/tr29/#Default_Grapheme_Cluster_Table - // [3]: https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules - // [4]: https://www.unicode.org/reports/tr29/#Conformance - - // Additionally, this procedure now takes into account Standard Annex #11, - // in order to estimate how visually wide the string will appear on a - // monospaced display. This can only ever be a rough guess, as this tends - // to be an implementation detail relating to which fonts are being used, - // how codepoints are interpreted and drawn, if codepoint sequences are - // interpreted correctly, and et cetera. - // - // For example, a program may not properly interpret an emoji modifier - // sequence and print the component glyphs instead of one whole glyph. - // - // See here for more information: https://www.unicode.org/reports/tr11/ - // - // NOTE: There is no explicit mention of what to do with zero-width spaces - // as far as grapheme cluster segmentation goes, therefore this - // implementation may count and return graphemes with a `width` of zero. - // - // Treat them as any other space. - - Grapheme_Cluster_Sequence :: enum { - None, - Indic, - Emoji, - Regional, - } - context.allocator = allocator - last_rune: rune - last_rune_breaks_forward: bool + it := decode_grapheme_iterator_make(str) + for _, grapheme in decode_grapheme_iterate(&it) { + if track_graphemes { + append(&graphemes, grapheme) + } + } - last_width: int - last_grapheme_count: int + grapheme_count = it.grapheme_count + rune_count = it.rune_count + width = it.width + return +} - bypass_next_rune: bool +@(require_results) +decode_grapheme_iterator_make :: proc(str: string) -> (it: Grapheme_Iterator) { + it.str = str + return +} - regional_indicator_counter: int +@(require_results) +decode_grapheme_iterate :: proc(it: ^Grapheme_Iterator) -> (text: string, grapheme: Grapheme, ok: bool) { + for it.curr_offset < len(it.str) { + if ok { + return + } - current_sequence: Grapheme_Cluster_Sequence - continue_sequence: bool + str := it.str[it.curr_offset:] + this_rune, this_rune_width := decode_rune(str) + byte_index := it.curr_offset + it.curr_offset += this_rune_width - for this_rune, byte_index in str { defer { // "Break at the start and end of text, unless the text is empty." // // GB1: sot ÷ Any // GB2: Any ÷ eot - if rune_count == 0 && grapheme_count == 0 { - grapheme_count += 1 + if it.rune_count == 0 && it.grapheme_count == 0 { + it.grapheme_count += 1 } - if grapheme_count > last_grapheme_count { - width += normalized_east_asian_width(this_rune) - if track_graphemes { - append(&graphemes, Grapheme{ - byte_index, - rune_count, - width - last_width, - }) + if it.grapheme_count > it.last_grapheme_count { + it.width += normalized_east_asian_width(this_rune) + grapheme = Grapheme{ + byte_index, + it.rune_count, + it.width - it.last_width, } - last_grapheme_count = grapheme_count - last_width = width + text = it.str[byte_index:][:grapheme.width] + ok = true + + + it.last_grapheme_count = it.grapheme_count + it.last_width = it.width } - last_rune = this_rune - rune_count += 1 + it.last_rune = this_rune + it.rune_count += 1 - if !continue_sequence { - current_sequence = .None - regional_indicator_counter = 0 + if !it.continue_sequence { + it.current_sequence = .None + it.regional_indicator_counter = 0 } - continue_sequence = false + it.continue_sequence = false } + // "Do not break between a CR and LF. Otherwise, break before and after controls." // // GB3: CR × LF // GB4: (Control | CR | LF) ÷ // GB5: ÷ (Control | CR | LF) - if this_rune == '\n' && last_rune == '\r' { - last_rune_breaks_forward = false - bypass_next_rune = false + if this_rune == '\n' && it.last_rune == '\r' { + it.last_rune_breaks_forward = false + it.bypass_next_rune = false continue } if is_control(this_rune) { - grapheme_count += 1 - last_rune_breaks_forward = true - bypass_next_rune = true + it.grapheme_count += 1 + it.last_rune_breaks_forward = true + it.bypass_next_rune = true continue } // (This check is for rules that work forwards, instead of backwards.) - if bypass_next_rune { - if last_rune_breaks_forward { - grapheme_count += 1 - last_rune_breaks_forward = false + if it.bypass_next_rune { + if it.last_rune_breaks_forward { + it.grapheme_count += 1 + it.last_rune_breaks_forward = false } - bypass_next_rune = false + it.bypass_next_rune = false continue } @@ -227,7 +205,7 @@ decode_grapheme_clusters :: proc( // * 0xA9 and 0xAE are in the Extended_Pictographic range, // which is checked later in GB11. if this_rune != 0xA9 && this_rune != 0xAE && this_rune <= 0x2FF { - grapheme_count += 1 + it.grapheme_count += 1 continue } @@ -241,30 +219,30 @@ decode_grapheme_clusters :: proc( if is_hangul_syllable_leading(this_rune) || is_hangul_syllable_lv(this_rune) || is_hangul_syllable_lvt(this_rune) { - if !is_hangul_syllable_leading(last_rune) { - grapheme_count += 1 + if !is_hangul_syllable_leading(it.last_rune) { + it.grapheme_count += 1 } continue } if is_hangul_syllable_vowel(this_rune) { - if is_hangul_syllable_leading(last_rune) || - is_hangul_syllable_vowel(last_rune) || - is_hangul_syllable_lv(last_rune) { + if is_hangul_syllable_leading(it.last_rune) || + is_hangul_syllable_vowel(it.last_rune) || + is_hangul_syllable_lv(it.last_rune) { continue } - grapheme_count += 1 + it.grapheme_count += 1 continue } if is_hangul_syllable_trailing(this_rune) { - if is_hangul_syllable_trailing(last_rune) || - is_hangul_syllable_lvt(last_rune) || - is_hangul_syllable_lv(last_rune) || - is_hangul_syllable_vowel(last_rune) { + if is_hangul_syllable_trailing(it.last_rune) || + is_hangul_syllable_lvt(it.last_rune) || + is_hangul_syllable_lv(it.last_rune) || + is_hangul_syllable_vowel(it.last_rune) { continue } - grapheme_count += 1 + it.grapheme_count += 1 continue } } @@ -273,25 +251,25 @@ decode_grapheme_clusters :: proc( // // GB9: × (Extend | ZWJ) if this_rune == ZERO_WIDTH_JOINER { - continue_sequence = true + it.continue_sequence = true continue } if is_gcb_extend_class(this_rune) { // (Support for GB9c.) - if current_sequence == .Indic { + if it.current_sequence == .Indic { if is_indic_conjunct_break_extend(this_rune) && ( - is_indic_conjunct_break_linker(last_rune) || - is_indic_conjunct_break_consonant(last_rune) ) { - continue_sequence = true + is_indic_conjunct_break_linker(it.last_rune) || + is_indic_conjunct_break_consonant(it.last_rune) ) { + it.continue_sequence = true continue } - if is_indic_conjunct_break_linker(this_rune) && ( - is_indic_conjunct_break_linker(last_rune) || - is_indic_conjunct_break_extend(last_rune) || - is_indic_conjunct_break_consonant(last_rune) ) { - continue_sequence = true + if is_indic_conjunct_break_linker(this_rune) && ( + is_indic_conjunct_break_linker(it.last_rune) || + is_indic_conjunct_break_extend(it.last_rune) || + is_indic_conjunct_break_consonant(it.last_rune) ) { + it.continue_sequence = true continue } @@ -299,10 +277,10 @@ decode_grapheme_clusters :: proc( } // (Support for GB11.) - if current_sequence == .Emoji && ( - is_gcb_extend_class(last_rune) || - is_emoji_extended_pictographic(last_rune) ) { - continue_sequence = true + if it.current_sequence == .Emoji && ( + is_gcb_extend_class(it.last_rune) || + is_emoji_extended_pictographic(it.last_rune) ) { + it.continue_sequence = true } continue @@ -318,8 +296,8 @@ decode_grapheme_clusters :: proc( } if is_gcb_prepend_class(this_rune) { - grapheme_count += 1 - bypass_next_rune = true + it.grapheme_count += 1 + it.bypass_next_rune = true continue } @@ -328,40 +306,40 @@ decode_grapheme_clusters :: proc( // // GB9c: \p{InCB=Consonant} [ \p{InCB=Extend} \p{InCB=Linker} ]* \p{InCB=Linker} [ \p{InCB=Extend} \p{InCB=Linker} ]* × \p{InCB=Consonant} if is_indic_conjunct_break_consonant(this_rune) { - if current_sequence == .Indic { - if last_rune == ZERO_WIDTH_JOINER || - is_indic_conjunct_break_linker(last_rune) { - continue_sequence = true + if it.current_sequence == .Indic { + if it.last_rune == ZERO_WIDTH_JOINER || + is_indic_conjunct_break_linker(it.last_rune) { + it.continue_sequence = true } else { - grapheme_count += 1 + it.grapheme_count += 1 } } else { - grapheme_count += 1 - current_sequence = .Indic - continue_sequence = true + it.grapheme_count += 1 + it.current_sequence = .Indic + it.continue_sequence = true } continue } if is_indic_conjunct_break_extend(this_rune) { - if current_sequence == .Indic { - if is_indic_conjunct_break_consonant(last_rune) || - is_indic_conjunct_break_linker(last_rune) { - continue_sequence = true + if it.current_sequence == .Indic { + if is_indic_conjunct_break_consonant(it.last_rune) || + is_indic_conjunct_break_linker(it.last_rune) { + it.continue_sequence = true } else { - grapheme_count += 1 + it.grapheme_count += 1 } } continue } if is_indic_conjunct_break_linker(this_rune) { - if current_sequence == .Indic { - if is_indic_conjunct_break_extend(last_rune) || - is_indic_conjunct_break_linker(last_rune) { - continue_sequence = true + if it.current_sequence == .Indic { + if is_indic_conjunct_break_extend(it.last_rune) || + is_indic_conjunct_break_linker(it.last_rune) { + it.continue_sequence = true } else { - grapheme_count += 1 + it.grapheme_count += 1 } } continue @@ -375,11 +353,11 @@ decode_grapheme_clusters :: proc( // // GB11: \p{Extended_Pictographic} Extend* ZWJ × \p{Extended_Pictographic} if is_emoji_extended_pictographic(this_rune) { - if current_sequence != .Emoji || last_rune != ZERO_WIDTH_JOINER { - grapheme_count += 1 + if it.current_sequence != .Emoji || it.last_rune != ZERO_WIDTH_JOINER { + it.grapheme_count += 1 } - current_sequence = .Emoji - continue_sequence = true + it.current_sequence = .Emoji + it.continue_sequence = true continue } @@ -390,13 +368,13 @@ decode_grapheme_clusters :: proc( // GB12: sot (RI RI)* RI × RI // GB13: [^RI] (RI RI)* RI × RI if is_regional_indicator(this_rune) { - if regional_indicator_counter & 1 == 0 { - grapheme_count += 1 + if it.regional_indicator_counter & 1 == 0 { + it.grapheme_count += 1 } - current_sequence = .Regional - continue_sequence = true - regional_indicator_counter += 1 + it.current_sequence = .Regional + it.continue_sequence = true + it.regional_indicator_counter += 1 continue } @@ -404,8 +382,8 @@ decode_grapheme_clusters :: proc( // "Otherwise, break everywhere." // // GB999: Any ÷ Any - grapheme_count += 1 + it.grapheme_count += 1 } return -} +} \ No newline at end of file diff --git a/core/unicode/utf8/utf8.odin b/core/unicode/utf8/utf8.odin index 67f8a8be9..c53b2e3a4 100644 --- a/core/unicode/utf8/utf8.odin +++ b/core/unicode/utf8/utf8.odin @@ -1,5 +1,8 @@ +// Procedures and constants to support text-encoding in the `UTF-8` character encoding. package utf8 +@(require) import "base:runtime" + RUNE_ERROR :: '\ufffd' RUNE_SELF :: 0x80 RUNE_BOM :: 0xfeff @@ -59,7 +62,8 @@ accept_sizes := [256]u8{ 0xf5..=0xff = 0xf1, // ascii, size 1 } -encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) { +@(require_results) +encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) #no_bounds_check { r := c buf: [4]u8 @@ -100,15 +104,17 @@ decode_rune :: proc{ decode_rune_in_string, decode_rune_in_bytes, } +@(require_results) decode_rune_in_string :: #force_inline proc "contextless" (s: string) -> (rune, int) { return decode_rune_in_bytes(transmute([]u8)s) } -decode_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) { +@(require_results) +decode_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) #no_bounds_check { n := len(s) if n < 1 { return RUNE_ERROR, 0 } - s0 := s[0] + #no_bounds_check s0 := s[0] x := accept_sizes[s0] if x >= 0xF0 { mask := rune(x) << 31 >> 31 // NOTE(bill): Create 0x0000 or 0xffff. @@ -140,10 +146,11 @@ decode_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) { return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4 } -string_to_runes :: proc "odin" (s: string, allocator := context.allocator) -> (runes: []rune) { +@(require_results) +string_to_runes :: proc "odin" (s: string, allocator := context.allocator) -> (runes: []rune, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { n := rune_count_in_string(s) - runes = make([]rune, n, allocator) + runes = make([]rune, n, allocator) or_return i := 0 for r in s { runes[i] = r @@ -152,14 +159,15 @@ string_to_runes :: proc "odin" (s: string, allocator := context.allocator) -> (r return } -runes_to_string :: proc "odin" (runes: []rune, allocator := context.allocator) -> string { +@(require_results) +runes_to_string :: proc "odin" (runes: []rune, allocator := context.allocator) -> (s: string, err: runtime.Allocator_Error) #optional_allocator_error #no_bounds_check { byte_count := 0 for r in runes { _, w := encode_rune(r) byte_count += w } - bytes := make([]byte, byte_count, allocator) + bytes := make([]byte, byte_count, allocator) or_return offset := 0 for r in runes { b, w := encode_rune(r) @@ -167,7 +175,8 @@ runes_to_string :: proc "odin" (runes: []rune, allocator := context.allocator) - offset += w } - return string(bytes) + s = string(bytes) + return } @@ -176,10 +185,12 @@ decode_last_rune :: proc{ decode_last_rune_in_bytes, } +@(require_results) decode_last_rune_in_string :: #force_inline proc "contextless" (s: string) -> (rune, int) { return decode_last_rune_in_bytes(transmute([]u8)s) } -decode_last_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) { +@(require_results) +decode_last_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) #no_bounds_check { r: rune size: int start, end, limit: int @@ -211,6 +222,7 @@ decode_last_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) { return r, size } +@(require_results) rune_at_pos :: proc "contextless" (s: string, pos: int) -> rune { if pos < 0 { return RUNE_ERROR @@ -226,7 +238,8 @@ rune_at_pos :: proc "contextless" (s: string, pos: int) -> rune { return RUNE_ERROR } -rune_string_at_pos :: proc "contextless" (s: string, pos: int) -> string { +@(require_results) +rune_string_at_pos :: proc "contextless" (s: string, pos: int) -> string #no_bounds_check { if pos < 0 { return "" } @@ -242,13 +255,15 @@ rune_string_at_pos :: proc "contextless" (s: string, pos: int) -> string { return "" } -rune_at :: proc "contextless" (s: string, byte_index: int) -> rune { +@(require_results) +rune_at :: proc "contextless" (s: string, byte_index: int) -> rune #no_bounds_check { r, _ := decode_rune_in_string(s[byte_index:]) return r } // Returns the byte position of rune at position pos in s with an optional start byte position. // Returns -1 if it runs out of the string. +@(require_results) rune_offset :: proc "contextless" (s: string, pos: int, start: int = 0) -> int { if pos < 0 { return -1 @@ -264,6 +279,7 @@ rune_offset :: proc "contextless" (s: string, pos: int, start: int = 0) -> int { return -1 } +@(require_results) valid_rune :: proc "contextless" (r: rune) -> bool { if r < 0 { return false @@ -275,7 +291,8 @@ valid_rune :: proc "contextless" (r: rune) -> bool { return true } -valid_string :: proc "contextless" (s: string) -> bool { +@(require_results) +valid_string :: proc "contextless" (s: string) -> bool #no_bounds_check { n := len(s) for i := 0; i < n; { si := s[i] @@ -300,7 +317,7 @@ valid_string :: proc "contextless" (s: string) -> bool { return false } else if size == 3 { // Okay - } else if d := s[i+3]; b < 0x80 || 0xbf < d { + } else if d := s[i+3]; d < 0x80 || 0xbf < d { return false } i += size @@ -308,6 +325,7 @@ valid_string :: proc "contextless" (s: string) -> bool { return true } +@(require_results) rune_start :: #force_inline proc "contextless" (b: u8) -> bool { return b&0xc0 != 0x80 } @@ -317,10 +335,12 @@ rune_count :: proc{ rune_count_in_bytes, } +@(require_results) rune_count_in_string :: #force_inline proc(s: string) -> int { return rune_count_in_bytes(transmute([]u8)s) } -rune_count_in_bytes :: proc "contextless" (s: []u8) -> int { +@(require_results) +rune_count_in_bytes :: proc "contextless" (s: []u8) -> int #no_bounds_check { count := 0 n := len(s) @@ -359,6 +379,7 @@ rune_count_in_bytes :: proc "contextless" (s: []u8) -> int { } +@(require_results) rune_size :: proc "contextless" (r: rune) -> int { switch { case r < 0: return -1 @@ -380,7 +401,8 @@ full_rune :: proc{ // full_rune_in_bytes reports if the bytes in b begin with a full utf-8 encoding of a rune or not // An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR) -full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool { +@(require_results) +full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool #no_bounds_check { n := len(b) if n == 0 { return false @@ -400,6 +422,7 @@ full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool { // full_rune_in_string reports if the bytes in s begin with a full utf-8 encoding of a rune or not // An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR) +@(require_results) full_rune_in_string :: proc "contextless" (s: string) -> bool { return full_rune_in_bytes(transmute([]byte)s) } diff --git a/core/unicode/utf8/utf8string/string.odin b/core/unicode/utf8/utf8string/string.odin index 4b0fe7241..7ece469a4 100644 --- a/core/unicode/utf8/utf8string/string.odin +++ b/core/unicode/utf8/utf8string/string.odin @@ -1,3 +1,4 @@ +// A convenient and efficient way to index strings by `Unicode` code point (`rune`) rather than byte. package utf8string import "core:unicode/utf8" diff --git a/examples/all/all_js.odin b/examples/all/all_js.odin new file mode 100644 index 000000000..8dbc320d0 --- /dev/null +++ b/examples/all/all_js.odin @@ -0,0 +1,158 @@ +#+build js +package all + +// Imports "every" package +// This is useful for knowing what exists and producing documentation with `odin doc` + +@(require) import "core:bufio" +@(require) import "core:bytes" +@(require) import "core:c" + +@(require) import "core:compress" +@(require) import "core:compress/shoco" +// @(require) import "core:compress/gzip" +@(require) import "core:compress/zlib" + +@(require) import "core:container/avl" +@(require) import "core:container/bit_array" +@(require) import "core:container/priority_queue" +@(require) import "core:container/queue" +@(require) import "core:container/small_array" +@(require) import "core:container/lru" +@(require) import "core:container/intrusive/list" +@(require) import "core:container/rbtree" +@(require) import "core:container/topological_sort" + +@(require) import "core:crypto" +@(require) import "core:crypto/aead" +@(require) import "core:crypto/aegis" +@(require) import "core:crypto/aes" +@(require) import "core:crypto/argon2id" +@(require) import "core:crypto/blake2b" +@(require) import "core:crypto/blake2s" +@(require) import "core:crypto/chacha20" +@(require) import "core:crypto/chacha20poly1305" +@(require) import chash "core:crypto/hash" +@(require) import "core:crypto/deoxysii" +@(require) import "core:crypto/ecdh" +@(require) import "core:crypto/ecdsa" +@(require) import "core:crypto/ed25519" +@(require) import "core:crypto/hkdf" +@(require) import "core:crypto/hmac" +@(require) import "core:crypto/kmac" +@(require) import "core:crypto/legacy/keccak" +@(require) import "core:crypto/legacy/md5" +@(require) import "core:crypto/legacy/sha1" +@(require) import "core:crypto/mldsa" +@(require) import "core:crypto/mlkem" +@(require) import cnoise "core:crypto/noise" +@(require) import "core:crypto/pbkdf2" +@(require) import "core:crypto/poly1305" +@(require) import "core:crypto/ristretto255" +@(require) import "core:crypto/sha2" +@(require) import "core:crypto/sha3" +@(require) import "core:crypto/shake" +@(require) import "core:crypto/sm3" +@(require) import "core:crypto/tuplehash" +@(require) import "core:crypto/x25519" +@(require) import "core:crypto/x448" + +@(require) import "core:debug/pe" +@(require) import "core:debug/trace" + +@(require) import "core:dynlib" +@(require) import "core:net" + +@(require) import "core:encoding/base32" +@(require) import "core:encoding/base64" +@(require) import "core:encoding/cbor" +@(require) import "core:encoding/csv" +@(require) import "core:encoding/endian" +@(require) import "core:encoding/hxa" +@(require) import "core:encoding/ini" +@(require) import "core:encoding/json" +@(require) import "core:encoding/pem" +@(require) import "core:encoding/varint" +@(require) import "core:encoding/xml" +@(require) import "core:encoding/uuid" +@(require) import "core:encoding/uuid/legacy" + +@(require) import "core:fmt" +@(require) import "core:hash" +@(require) import "core:hash/xxhash" + +@(require) import "core:image" +@(require) import "core:image/bmp" +@(require) import "core:image/netpbm" +@(require) import "core:image/png" +@(require) import "core:image/qoi" +@(require) import "core:image/tga" + +@(require) import "core:io" +@(require) import "core:log" + +@(require) import "core:math" +@(require) import "core:math/big" +@(require) import "core:math/bits" +@(require) import "core:math/fixed" +@(require) import "core:math/linalg" +@(require) import "core:math/linalg/glsl" +@(require) import "core:math/linalg/hlsl" +@(require) import "core:math/noise" +@(require) import "core:math/rand" +@(require) import "core:math/ease" +@(require) import "core:math/cmplx" + +@(require) import "core:mem" +@(require) import "core:mem/tlsf" +// Not supported on JS +// @(require) import "core:mem/virtual" + +@(require) import "core:odin/ast" +@(require) import doc_format "core:odin/doc-format" + +@(require) import "core:odin/tokenizer" +@(require) import "core:path/slashpath" + +@(require) import "core:relative" + +@(require) import "core:reflect" +@(require) import "base:runtime" +@(require) import "base:sanitizer" +@(require) import "core:simd" +@(require) import "core:simd/x86" +@(require) import "core:slice" +@(require) import "core:slice/heap" +@(require) import "core:sort" +@(require) import "core:strconv" +@(require) import "core:strings" +@(require) import "core:sync" + +@(require) import "core:terminal" +@(require) import "core:terminal/ansi" + +@(require) import "core:text/edit" +@(require) import "core:text/i18n" +@(require) import "core:text/match" +@(require) import "core:text/regex" +@(require) import "core:text/scanner" +// Not supported on JS, uses `core:mem/virtual`. +@(require) import "core:text/table" + +@(require) import "core:thread" +@(require) import "core:time" +@(require) import "core:time/datetime" +@(require) import "core:time/timezone" + + +@(require) import "core:sys/orca" +@(require) import "core:sys/info" +@(require) import "core:sys/wasm/js" +@(require) import "core:sys/wasm/wasi" + +@(require) import "core:unicode" +@(require) import "core:unicode/utf8" +@(require) import "core:unicode/utf8/utf8string" +@(require) import "core:unicode/utf16" + +main :: proc() {} diff --git a/examples/all/all_linux.odin b/examples/all/all_linux.odin index ca51d6562..d7d005ba0 100644 --- a/examples/all/all_linux.odin +++ b/examples/all/all_linux.odin @@ -1,6 +1,6 @@ #+build linux package all -import linux "core:sys/linux" - -_ :: linux \ No newline at end of file +@(require) import "core:sys/linux" +@(require) import "core:sys/linux/uring" +@(require) import "vendor:x11/xlib" diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 0a17227b8..b8655a89e 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -1,279 +1,170 @@ +#+build !js package all // Imports every package // This is useful for knowing what exists and producing documentation with `odin doc` -import bufio "core:bufio" -import bytes "core:bytes" +@(require) import "core:bufio" +@(require) import "core:bytes" -import c "core:c" -import libc "core:c/libc" +@(require) import "core:c" +@(require) import "core:c/libc" -import compress "core:compress" -import shoco "core:compress/shoco" -import gzip "core:compress/gzip" -import zlib "core:compress/zlib" +@(require) import "core:compress" +@(require) import "core:compress/shoco" +@(require) import "core:compress/gzip" +@(require) import "core:compress/zlib" -import avl "core:container/avl" -import bit_array "core:container/bit_array" -import priority_queue "core:container/priority_queue" -import queue "core:container/queue" -import small_array "core:container/small_array" -import lru "core:container/lru" -import list "core:container/intrusive/list" -import rbtree "core:container/rbtree" -import topological_sort "core:container/topological_sort" +@(require) import "core:container/avl" +@(require) import "core:container/bit_array" +@(require) import "core:container/handle_map" +@(require) import "core:container/intrusive/list" +@(require) import "core:container/lru" +@(require) import "core:container/pool" +@(require) import "core:container/priority_queue" +@(require) import "core:container/queue" +@(require) import "core:container/rbtree" +@(require) import "core:container/small_array" +@(require) import "core:container/topological_sort" +@(require) import "core:container/xar" -import crypto "core:crypto" -import aead "core:crypto/aead" -import aegis "core:crypto/aegis" -import aes "core:crypto/aes" -import blake2b "core:crypto/blake2b" -import blake2s "core:crypto/blake2s" -import chacha20 "core:crypto/chacha20" -import chacha20poly1305 "core:crypto/chacha20poly1305" -import crypto_hash "core:crypto/hash" -import deoxysii "core:crypto/deoxysii" -import ed25519 "core:crypto/ed25519" -import hkdf "core:crypto/hkdf" -import hmac "core:crypto/hmac" -import kmac "core:crypto/kmac" -import keccak "core:crypto/legacy/keccak" -import md5 "core:crypto/legacy/md5" -import sha1 "core:crypto/legacy/sha1" -import pbkdf2 "core:crypto/pbkdf2" -import poly1305 "core:crypto/poly1305" -import ristretto255 "core:crypto/ristretto255" -import sha2 "core:crypto/sha2" -import sha3 "core:crypto/sha3" -import shake "core:crypto/shake" -import sm3 "core:crypto/sm3" -import tuplehash "core:crypto/tuplehash" -import x25519 "core:crypto/x25519" -import x448 "core:crypto/x448" +@(require) import "core:crypto" +@(require) import "core:crypto/aead" +@(require) import "core:crypto/aegis" +@(require) import "core:crypto/aes" +@(require) import "core:crypto/argon2id" +@(require) import "core:crypto/blake2b" +@(require) import "core:crypto/blake2s" +@(require) import "core:crypto/chacha20" +@(require) import "core:crypto/chacha20poly1305" +@(require) import chash "core:crypto/hash" +@(require) import "core:crypto/deoxysii" +@(require) import "core:crypto/ecdh" +@(require) import "core:crypto/ecdsa" +@(require) import "core:crypto/ed25519" +@(require) import "core:crypto/hkdf" +@(require) import "core:crypto/hmac" +@(require) import "core:crypto/kmac" +@(require) import "core:crypto/legacy/keccak" +@(require) import "core:crypto/legacy/md5" +@(require) import "core:crypto/legacy/sha1" +@(require) import "core:crypto/mldsa" +@(require) import "core:crypto/mlkem" +@(require) import cnoise "core:crypto/noise" +@(require) import "core:crypto/pbkdf2" +@(require) import "core:crypto/poly1305" +@(require) import "core:crypto/ristretto255" +@(require) import "core:crypto/sha2" +@(require) import "core:crypto/sha3" +@(require) import "core:crypto/shake" +@(require) import "core:crypto/sm3" +@(require) import "core:crypto/tuplehash" +@(require) import "core:crypto/x25519" +@(require) import "core:crypto/x448" -import pe "core:debug/pe" -import trace "core:debug/trace" +@(require) import "core:debug/pe" +@(require) import "core:debug/trace" -import dynlib "core:dynlib" -import net "core:net" +@(require) import "core:dynlib" +@(require) import "core:net" -import ansi "core:encoding/ansi" -import base32 "core:encoding/base32" -import base64 "core:encoding/base64" -import cbor "core:encoding/cbor" -import csv "core:encoding/csv" -import endian "core:encoding/endian" -import hxa "core:encoding/hxa" -import ini "core:encoding/ini" -import json "core:encoding/json" -import varint "core:encoding/varint" -import xml "core:encoding/xml" -import uuid "core:encoding/uuid" -import uuid_legacy "core:encoding/uuid/legacy" +@(require) import "core:encoding/base32" +@(require) import "core:encoding/base64" +@(require) import "core:encoding/cbor" +@(require) import "core:encoding/csv" +@(require) import "core:encoding/endian" +@(require) import "core:encoding/hxa" +@(require) import "core:encoding/ini" +@(require) import "core:encoding/json" +@(require) import "core:encoding/pem" +@(require) import "core:encoding/varint" +@(require) import "core:encoding/xml" +@(require) import "core:encoding/uuid" +@(require) import "core:encoding/uuid/legacy" -import fmt "core:fmt" -import hash "core:hash" -import xxhash "core:hash/xxhash" +@(require) import "core:fmt" +@(require) import "core:hash" +@(require) import "core:hash/xxhash" -import image "core:image" -import bmp "core:image/bmp" -import netpbm "core:image/netpbm" -import png "core:image/png" -import qoi "core:image/qoi" -import tga "core:image/tga" +@(require) import "core:image" +@(require) import "core:image/bmp" +@(require) import "core:image/netpbm" +@(require) import "core:image/png" +@(require) import "core:image/qoi" +@(require) import "core:image/tga" +@(require) import "core:image/jpeg" -import io "core:io" -import log "core:log" +@(require) import "core:io" +@(require) import "core:log" -import math "core:math" -import big "core:math/big" -import bits "core:math/bits" -import fixed "core:math/fixed" -import linalg "core:math/linalg" -import glm "core:math/linalg/glsl" -import hlm "core:math/linalg/hlsl" -import noise "core:math/noise" -import rand "core:math/rand" -import ease "core:math/ease" -import cmplx "core:math/cmplx" +@(require) import "core:math" +@(require) import "core:math/big" +@(require) import "core:math/bits" +@(require) import "core:math/fixed" +@(require) import "core:math/linalg" +@(require) import "core:math/linalg/glsl" +@(require) import "core:math/linalg/hlsl" +@(require) import "core:math/noise" +@(require) import "core:math/rand" +@(require) import "core:math/ease" +@(require) import "core:math/cmplx" -import mem "core:mem" -import tlsf "core:mem/tlsf" -import virtual "core:mem/virtual" +@(require) import "core:mem" +@(require) import "core:mem/tlsf" +@(require) import "core:mem/virtual" -import ast "core:odin/ast" -import doc_format "core:odin/doc-format" -import odin_parser "core:odin/parser" -import odin_tokenizer "core:odin/tokenizer" +@(require) import "core:nbio" -import spall "core:prof/spall" +@(require) import "core:odin/ast" +@(require) import doc_format "core:odin/doc-format" +@(require) import "core:odin/parser" +@(require) import "core:odin/tokenizer" -import os "core:os" +@(require) import "core:prof/spall" -import slashpath "core:path/slashpath" -import filepath "core:path/filepath" +@(require) import "core:os" +@(require) import "core:os/old" -import relative "core:relative" +@(require) import "core:path/slashpath" +@(require) import "core:path/filepath" -import reflect "core:reflect" -import runtime "base:runtime" -import sanitizer "base:sanitizer" -import simd "core:simd" -import x86 "core:simd/x86" -import slice "core:slice" -import slice_heap "core:slice/heap" -import sort "core:sort" -import strconv "core:strconv" -import strings "core:strings" -import sync "core:sync" -import testing "core:testing" +@(require) import "core:relative" -import edit "core:text/edit" -import i18n "core:text/i18n" -import match "core:text/match" -import regex "core:text/regex" -import scanner "core:text/scanner" -import table "core:text/table" +@(require) import "core:reflect" +@(require) import "base:runtime" +@(require) import "base:sanitizer" +@(require) import "core:simd" +@(require) import "core:simd/x86" +@(require) import "core:slice" +@(require) import "core:slice/heap" +@(require) import "core:sort" +@(require) import "core:strconv" +@(require) import "core:strings" +@(require) import "core:sync" +@(require) import "core:testing" -import thread "core:thread" -import time "core:time" -import datetime "core:time/datetime" -import timezone "core:time/timezone" -import flags "core:flags" +@(require) import "core:terminal" +@(require) import "core:terminal/ansi" -import orca "core:sys/orca" -import sysinfo "core:sys/info" +@(require) import "core:text/edit" +@(require) import "core:text/i18n" +@(require) import "core:text/match" +@(require) import "core:text/regex" +@(require) import "core:text/scanner" +@(require) import "core:text/table" -import unicode "core:unicode" -import utf8 "core:unicode/utf8" -import utf8string "core:unicode/utf8/utf8string" -import utf16 "core:unicode/utf16" +@(require) import "core:thread" +@(require) import "core:time" +@(require) import "core:time/datetime" +@(require) import "core:time/timezone" +@(require) import "core:flags" -main :: proc(){} +@(require) import "core:sys/orca" +@(require) import "core:sys/info" +@(require) import "core:unicode" +@(require) import "core:unicode/utf8" +@(require) import "core:unicode/utf8/utf8string" +@(require) import "core:unicode/utf16" -_ :: bufio -_ :: bytes -_ :: c -_ :: libc -_ :: compress -_ :: shoco -_ :: gzip -_ :: zlib -_ :: avl -_ :: bit_array -_ :: priority_queue -_ :: queue -_ :: small_array -_ :: lru -_ :: list -_ :: rbtree -_ :: topological_sort -_ :: crypto -_ :: crypto_hash -_ :: aead -_ :: aegis -_ :: aes -_ :: blake2b -_ :: blake2s -_ :: chacha20 -_ :: chacha20poly1305 -_ :: deoxysii -_ :: ed25519 -_ :: hmac -_ :: hkdf -_ :: kmac -_ :: keccak -_ :: md5 -_ :: pbkdf2 -_ :: poly1305 -_ :: ristretto255 -_ :: sha1 -_ :: sha2 -_ :: sha3 -_ :: shake -_ :: sm3 -_ :: tuplehash -_ :: x25519 -_ :: x448 -_ :: pe -_ :: trace -_ :: dynlib -_ :: net -_ :: ansi -_ :: base32 -_ :: base64 -_ :: csv -_ :: hxa -_ :: ini -_ :: json -_ :: varint -_ :: xml -_ :: endian -_ :: cbor -_ :: fmt -_ :: hash -_ :: xxhash -_ :: image -_ :: bmp -_ :: netpbm -_ :: png -_ :: qoi -_ :: tga -_ :: io -_ :: log -_ :: math -_ :: big -_ :: bits -_ :: fixed -_ :: linalg -_ :: glm -_ :: hlm -_ :: noise -_ :: rand -_ :: ease -_ :: cmplx -_ :: mem -_ :: tlsf -_ :: virtual -_ :: ast -_ :: doc_format -_ :: odin_parser -_ :: odin_tokenizer -_ :: os -_ :: spall -_ :: slashpath -_ :: filepath -_ :: relative -_ :: reflect -_ :: runtime -_ :: simd -_ :: x86 -_ :: slice -_ :: slice_heap -_ :: sort -_ :: strconv -_ :: strings -_ :: sync -_ :: testing -_ :: scanner -_ :: i18n -_ :: match -_ :: regex -_ :: table -_ :: edit -_ :: thread -_ :: time -_ :: datetime -_ :: timezone -_ :: flags -_ :: orca -_ :: sysinfo -_ :: unicode -_ :: uuid -_ :: uuid_legacy -_ :: utf8 -_ :: utf8string -_ :: utf16 -_ :: sanitizer +main :: proc() {} diff --git a/examples/all/all_posix.odin b/examples/all/all_posix.odin index 61b33a5c6..3e05f74ff 100644 --- a/examples/all/all_posix.odin +++ b/examples/all/all_posix.odin @@ -1,8 +1,5 @@ #+build darwin, openbsd, freebsd, netbsd package all -import posix "core:sys/posix" -import kqueue "core:sys/kqueue" - -_ :: posix -_ :: kqueue +@(require) import "core:sys/posix" +@(require) import "core:sys/kqueue" \ No newline at end of file diff --git a/examples/all/all_vendor.odin b/examples/all/all_vendor.odin index b224a3bbe..1605ea8a7 100644 --- a/examples/all/all_vendor.odin +++ b/examples/all/all_vendor.odin @@ -1,106 +1,54 @@ +#+build !js package all -import cgltf "vendor:cgltf" -// import commonmark "vendor:commonmark" -import ENet "vendor:ENet" -import exr "vendor:OpenEXRCore" -import ggpo "vendor:ggpo" -import gl "vendor:OpenGL" -import glfw "vendor:glfw" -import microui "vendor:microui" -import miniaudio "vendor:miniaudio" -import PM "vendor:portmidi" -import rl "vendor:raylib" -import zlib "vendor:zlib" +@(require) import "vendor:cgltf" +@(require) import "vendor:curl" +@(require) import "vendor:ENet" +@(require) import "vendor:OpenEXRCore" +@(require) import "vendor:ggpo" +@(require) import "vendor:OpenGL" +@(require) import "vendor:glfw" +@(require) import "vendor:microui" +@(require) import "vendor:miniaudio" +@(require) import "vendor:portmidi" +@(require) import "vendor:raylib" +@(require) import "vendor:zlib" -import SDL "vendor:sdl2" -import SDLNet "vendor:sdl2/net" -import IMG "vendor:sdl2/image" -import MIX "vendor:sdl2/mixer" -import TTF "vendor:sdl2/ttf" +@(require) import "vendor:sdl2" +@(require) import "vendor:sdl2/net" +@(require) import "vendor:sdl2/image" +@(require) import "vendor:sdl2/mixer" +@(require) import "vendor:sdl2/ttf" -import vk "vendor:vulkan" +@(require) import "vendor:vulkan" // NOTE(bill): only one can be checked at a time -import lua_5_4 "vendor:lua/5.4" - -import nvg "vendor:nanovg" -import nvg_gl "vendor:nanovg/gl" -import fontstash "vendor:fontstash" - -import xlib "vendor:x11/xlib" - -_ :: cgltf -// _ :: commonmark -_ :: ENet -_ :: exr -_ :: ggpo -_ :: gl -_ :: glfw -_ :: microui -_ :: miniaudio -_ :: PM -_ :: rl -_ :: zlib - -_ :: SDL -_ :: SDLNet -_ :: IMG -_ :: MIX -_ :: TTF - -_ :: vk - -_ :: lua_5_4 - -_ :: nvg -_ :: nvg_gl -_ :: fontstash - -_ :: xlib - +@(require) import lua54 "vendor:lua/5.4" +@(require) import "vendor:nanovg" +@(require) import "vendor:nanovg/gl" +@(require) import "vendor:fontstash" // NOTE: needed for doc generator +@(require) import "core:sys/darwin/Foundation" +@(require) import "core:sys/darwin/CoreFoundation" +@(require) import "core:sys/darwin/CoreGraphics" +@(require) import "core:sys/darwin/Security" +@(require) import "vendor:darwin/CoreVideo" +@(require) import "vendor:darwin/Metal" +@(require) import "vendor:darwin/MetalKit" +@(require) import "vendor:darwin/QuartzCore" -import NS "core:sys/darwin/Foundation" -import CF "core:sys/darwin/CoreFoundation" -import SEC "core:sys/darwin/Security" -import MTL "vendor:darwin/Metal" -import MTK "vendor:darwin/MetalKit" -import CA "vendor:darwin/QuartzCore" +@(require) import "vendor:directx/dxc" +@(require) import "vendor:directx/d3d11" +@(require) import "vendor:directx/d3d12" +@(require) import "vendor:directx/dxgi" +@(require) import "vendor:commonmark" -_ :: NS -_ :: CF -_ :: SEC -_ :: MTL -_ :: MTK -_ :: CA +@(require) import "vendor:stb/easy_font" +@(require) import stbi "vendor:stb/image" +@(require) import "vendor:stb/rect_pack" +@(require) import "vendor:stb/truetype" +@(require) import "vendor:stb/vorbis" -import DXC "vendor:directx/dxc" -import D3D11 "vendor:directx/d3d11" -import D3D12 "vendor:directx/d3d12" -import DXGI "vendor:directx/dxgi" - -_ :: DXC -_ :: D3D11 -_ :: D3D12 -_ :: DXGI - - -import cm "vendor:commonmark" -_ :: cm - - -import stb_easy_font "vendor:stb/easy_font" -import stbi "vendor:stb/image" -import stbrp "vendor:stb/rect_pack" -import stbtt "vendor:stb/truetype" -import stb_vorbis "vendor:stb/vorbis" - -_ :: stb_easy_font -_ :: stbi -_ :: stbrp -_ :: stbtt -_ :: stb_vorbis - +@(require) import "vendor:kb_text_shape" diff --git a/examples/all/all_vendor_js.odin b/examples/all/all_vendor_js.odin new file mode 100644 index 000000000..d7975541d --- /dev/null +++ b/examples/all/all_vendor_js.odin @@ -0,0 +1,13 @@ +#+build js +package all + +@(require) import "vendor:box2d" +@(require) import "vendor:cgltf" +@(require) import "vendor:fontstash" +@(require) import "vendor:microui" +@(require) import "vendor:stb/easy_font" +@(require) import "vendor:stb/image" +@(require) import "vendor:stb/rect_pack" +@(require) import "vendor:stb/truetype" +@(require) import "vendor:wgpu" +@(require) import "vendor:wasm/WebGL" \ No newline at end of file diff --git a/examples/all/all_vendor_windows.odin b/examples/all/all_vendor_windows.odin index df6542cdd..8a0c29eaf 100644 --- a/examples/all/all_vendor_windows.odin +++ b/examples/all/all_vendor_windows.odin @@ -1,12 +1,10 @@ +#+build windows package all -import wgpu "vendor:wgpu" -import b2 "vendor:box2d" -import game_input "vendor:windows/GameInput" -import XAudio2 "vendor:windows/XAudio2" - -_ :: wgpu -_ :: b2 -_ :: game_input -_ :: XAudio2 - +@(require) import "vendor:compress/lz4" +@(require) import "vendor:wgpu/glfwglue" +@(require) import "vendor:wgpu/sdl2glue" +@(require) import "vendor:wgpu" +@(require) import "vendor:box2d" +@(require) import "vendor:windows/GameInput" +@(require) import "vendor:windows/XAudio2" \ No newline at end of file diff --git a/examples/all/sdl3/all_sdl3.odin b/examples/all/sdl3/all_sdl3.odin new file mode 100644 index 000000000..550275af0 --- /dev/null +++ b/examples/all/sdl3/all_sdl3.odin @@ -0,0 +1,13 @@ +/* +Imports all packages using SDL3, can't go in the parent directory +because SDL2 and SDL3 will have naming conflicts. +*/ +package all_sdl3 + +import SDL "vendor:sdl3" +import IMG "vendor:sdl3/image" +import TTF "vendor:sdl3/ttf" + +_ :: SDL +_ :: IMG +_ :: TTF diff --git a/examples/all/sdl3/all_sdl3_windows.odin b/examples/all/sdl3/all_sdl3_windows.odin new file mode 100644 index 000000000..28a0fec90 --- /dev/null +++ b/examples/all/sdl3/all_sdl3_windows.odin @@ -0,0 +1,5 @@ +package all_sdl3 + +import wgpu_sdl3_glue "vendor:wgpu/sdl3glue" + +_ :: wgpu_sdl3_glue diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index c559d4771..a12217548 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -1,5 +1,5 @@ #+vet !using-stmt !using-param -#+feature dynamic-literals +#+feature dynamic-literals using-stmt package main import "core:fmt" @@ -11,6 +11,7 @@ import "core:reflect" import "base:runtime" import "base:intrinsics" import "core:math/big" +import "core:math/rand" /* Odin is a general-purpose programming language with distinct typing built @@ -750,6 +751,11 @@ union_type :: proc() { } using_statement :: proc() { + // IMPORTANT NOTE: `using` as a statement is an opt-in feature which can be abled + // by adding `#+feature using-stmt` to be beginning of the file + // + // `using` as a struct field modifier remains available always + fmt.println("\n# using statement") // using can used to bring entities declared in a scope/namespace // into the current scope. This can be applied to import names, struct @@ -1215,19 +1221,6 @@ threading_example :: proc() { } thread.pool_start(&pool) - - { - // Wait a moment before we cancel a thread - time.sleep(5 * time.Millisecond) - - // Allow one thread to print at a time. - for !did_acquire(&print_mutex) { thread.yield() } - - thread.terminate(pool.threads[N - 1], 0) - fmt.println("Canceled last thread") - print_mutex = false - } - thread.pool_finish(&pool) } } @@ -1613,7 +1606,7 @@ where_clauses :: proc() { where intrinsics.type_is_numeric(E) { x := a.y*b.z - a.z*b.y y := a.z*b.x - a.x*b.z - z := a.x*b.y - a.y*b.z + z := a.x*b.y - a.y*b.x return T{x, y, z} } @@ -2254,7 +2247,7 @@ arbitrary_precision_mathematics :: proc() { cb := big.internal_count_bits(a) if print_name { - fmt.printf(name) + fmt.print(name) } if err != nil { fmt.printf(" (Error: %v) ", err) @@ -2271,6 +2264,10 @@ arbitrary_precision_mathematics :: proc() { a, b, c, d, e, f, res := &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{} defer big.destroy(a, b, c, d, e, f, res) + // Set the context RNG to something that does not require + // cryptographic entropy (not supported on all targets). + context.random_generator = rand.xoshiro256_random_generator() + // How many bits should the random prime be? bits := 64 // Number of Rabin-Miller trials, -1 for automatic. diff --git a/misc/get-date.c b/misc/get-date.c index bf5b32738..b3eb1be78 100644 --- a/misc/get-date.c +++ b/misc/get-date.c @@ -9,5 +9,5 @@ int main(int arg_count, char const **arg_ptr) { time_t t = time(NULL); struct tm* now = localtime(&t); - printf("%04d%02d%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday); + printf("%04d-%02d-%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday); } \ No newline at end of file diff --git a/misc/shell.bat b/misc/shell.bat index 73232da61..bfd3780e9 100644 --- a/misc/shell.bat +++ b/misc/shell.bat @@ -5,7 +5,7 @@ rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 1> NUL rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL -call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 1> NUL set _NO_DEBUG_HEAP=1 set ODIN_IGNORE_MSVC_CHECK=1 diff --git a/odin.ebnf b/odin.ebnf new file mode 100644 index 000000000..4efa54b1e --- /dev/null +++ b/odin.ebnf @@ -0,0 +1,489 @@ +/* The Odin Programming Language Expressed as in EBNF */ + +/* +EBNF representation of itself: + +Production = name "=" [ Expression ] "." ; +Expression = Alternative { "|" Alternative } ; +Alternative = Term { Term } ; +Term = name | token [ "…" token ] | Group | Option | Repetition ; +Group = "(" Expression ")" ; +Option = "[" Expression "]" ; +Repetition = "{" Expression "}" ; +*/ + + +/* Tokens for Lexical Grammar */ + +IDENT = ( LETTER | "_" ) { LETTER | DIGIT | "_" } ; +LETTER = "a".."z" | "A".."Z" | "_" | UNICODE_LETTER ; + +INT_LIT = DECIMAL_LIT | BINARY_LIT | OCTAL_LIT | DOZENAL_LIT | HEX_LIT ; +DECIMAL_LIT = DIGIT { [ "_" ] DIGIT } ; +BINARY_LIT = "0b" BIN_DIGIT { [ "_" ] BIN_DIGIT } ; +OCTAL_LIT = "0o" OCT_DIGIT { [ "_" ] OCT_DIGIT } ; +DOZENAL_LIT = "0z" DOZ_DIGIT { [ "_" ] DOZ_DIGIT } ; +HEX_LIT = "0x" HEX_DIGIT { [ "_" ] HEX_DIGIT } ; + +FLOAT_LIT = DIGIT { DIGIT } "." DIGIT { DIGIT } [ EXPONENT ] + | DIGIT { DIGIT } EXPONENT + | "0h" HEX_DIGIT { [ "_" HEX_DIGIT ]} ; + +EXPONENT = ( "e" | "E" ) [ "+" | "-" ] DIGIT { DIGIT } ; + +IMAGINARY_LIT = ( INT_LIT | FLOAT_LIT ) ( "i" | "j" | "k" ) ; + +RUNE_LIT = "'" ( CHAR | ESCAPE_SEQ ) "'" ; + +STRING_LIT = '"' { CHAR | ESCAPE_SEQ } '"' ; +RAW_STRING_LIT = "`" { ANY_CHAR } "`" ; + +ESCAPE_SEQ = "\" ( "a" | "b" | "e" | "f" | "n" | "r" | "t" | "v" + | "\\" | '"' | "'" + | OCT_DIGIT OCT_DIGIT OCT_DIGIT + | "x" HEX_DIGIT HEX_DIGIT + | "u" HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT + | "U" HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT + HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT ) ; + +DIGIT = "0".."9" ; +BIN_DIGIT = "0" | "1" ; +OCT_DIGIT = "0".."7" ; +DOZ_DIGIT = "0".."9" | "a"| "b" | "A" | "B" ; +HEX_DIGIT = "0".."9" | "a".."f" | "A".."F" ; + +COMMENT = "//" { ANY_CHAR } NEWLINE + | "/*" { ANY_CHAR | COMMENT } "*/" /* nestable */ + | "#!" { ANY_CHAR } NEWLINE ; + +/* Odin uses automatic semicolon insertion similar to Go/Python: + a newline acts as ";" after certain tokens such as IDENT, + literals, ")", "]", "}", "^", "---", "break", "continue", + "fallthrough", "return", "or_return", "or_break", "or_continue". + + During parsing, ";" will be ignored with matching brackets in expressions similar to Python: + "(" ")" + "[" "]" + "{" "}" +*/ + + + +/* Syntax Grammar */ + +/* NOTE: Any directive such as "#partial" can also be written with any number of whitespace after the "#" + This grammar is simplified to represent minimize the need for "#" "partial" +*/ + +/* Source File Structure */ + +File = { FileTag } PackageDecl ";" { TopLevelStmt } ; +FileTag = "#+" IDENT [ TagValue ] NEWLINE ; /* #+build, #+private, #+feature, … */ +TagValue = { ANY_CHAR } ; +PackageDecl = "package" IDENT ; + +TopLevelStmt = ImportDecl ";" + | ForeignImportDecl ";" + | ForeignBlock ";" + | WhenStmt + | Decl ";" ; + + +/* Import Declarations */ + +ImportDecl = { Attribute } "import" [ IDENT ] STRING_LIT ; + +ForeignImportDecl = { Attribute } "foreign" "import" [ IDENT ] ( STRING_LIT | "{" ForeignImportPathList "}" ) ; + +ForeignImportPathList = Expr { "," Expr } [ "," ] ; + +/* Value Declarations */ + +Decl = { Attribute } ValueDecl ; + +ValueDecl = IdentList ":" Type + | IdentList ":" [ Type ] "=" ExprList + | IdentList ":" [ Type ] ":" ExprList ; + +IdentList = IDENT { "," IDENT } ; +ExprList = Expr { "," Expr } ; + +/* Foreign Block Declaration */ + +ForeignBlock = { Attribute } "foreign" [ IDENT ] "{" { ForeignDecl ";" } "}" ; + +ForeignDecl = { Attribute } ValueDecl ; + + +/* Statements */ + +Stmt = EmptyStmt + | Decl ";" + | ExprStmt ";" + | AssignStmt ";" + | BlockStmt + | IfStmt + | WhenStmt + | ForStmt + | SwitchStmt + | TypeSwitchStmt + | DeferStmt + | ReturnStmt ";" + | BranchStmt ";" + | UsingStmt ";" + | Attribute Stmt + | Label Stmt + | ForeignBlock + | DirectiveStmt ; + + +EmptyStmt = ";" ; + +/* Directive Statements */ + +DirectiveStmt = "#assert" "(" Expr [ "," STRING_LIT ] ")" + | "#panic" "(" STRING_LIT ")" + | "#force_inline" CallBody + | "#force_no_inline" CallBody + | "#must_tail" CallBody ; + +/* Block Statement */ + +BlockStmt = [ Label ] "{" StmtList "}" ; +StmtList = { Stmt } ; +Label = IDENT ":" ; + +/* Assignment Statements */ + +ExprStmt = Expr ; + +AssignStmt = ExprList AssignOp ExprList ; + +AssignOp = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "%%=" + | "|=" | "~=" | "&=" | "&~=" + | "<<=" | ">>=" | "&&=" | "||=" ; + +/* Control Flow */ + +IfStmt = "if" [ SimpleStmt ";" ] Expr StmtBody + { "else" "if" [ SimpleStmt ";" ] Expr StmtBody } + [ "else" StmtBody ] ; + +WhenStmt = "when" Expr StmtBody + { "else" "when" Expr StmtBody } + [ "else" StmtBody ] ; + +ForStmt = [ Label ] [ ForDirectivePrefix ] + "for" [ ForHead ] StmtBody ; + +ForDirectivePrefix = "#reverse" + | "#unroll" [ CallBody ] ; + +ForHead = RangeClause + | ForCondition + | ForCClause ; + +ForCondition = Expr ; + +ForCClause = [ SimpleStmt ] ";" [ Expr ] ";" [ SimpleStmt ] ; + +RangeClause = [ [ SimpleStmt ] ";" ] [ [ "&" ] IDENT { "," [ "&" ] IDENT } "in" ] RangeExpr ; + +RangeExpr = Expr + | Expr "..<" Expr + | Expr "..=" Expr ; + +SwitchStmt = [ Label ] [ "#partial" ] "switch" [ SimpleStmt ";" ] [ Expr ] + "{" { CaseClause } "}" ; + +CaseClause = "case" [ ExprList ] ":" StmtList ; + +TypeSwitchStmt = [ Label ] [ "#partial" ] "switch" IDENT "in" Expr + "{" { TypeCaseClause } "}" ; + +TypeCaseClause = "case" [ TypeList ] ":" StmtList ; + +TypeList = Type { "," Type } ; + + +/* Branch & Defer */ + +BranchStmt = "break" [ IDENT ] + | "continue" [ IDENT ] + | "fallthrough" ; + +DeferStmt = "defer" ( Stmt | ( "{" StmtList "}" ) ) ; + +ReturnStmt = [ ReturnStmtDirectivePrefix ] "return" [ ExprList ] ; +ReturnStmtDirectivePrefix = "#force_inline" | "#force_no_inline" | "#must_tail" ; + +/* Using Statement */ + +UsingStmt = "using" ( IdentList | Expr ) ; + +/* Simple Statement (used in control flow init) */ + +SimpleStmt = ExprStmt | AssignStmt | ValueDecl ; + +/* Body for Control Flow */ + +StmtBody = "{" StmtList "}" + | "do" Stmt ; /* must be on the same line as the initial token of the statement */ + +/* Expressions */ + +/* Binary Expressions + Operator Precedence (low -> high) +*/ + +Expr = OrElseExpr ; + +OrElseExpr = TernaryExpr { "or_else" TernaryExpr } ; + +TernaryExpr = RangeExprLvl + | RangeExprLvl "?" RangeExprLvl ":" TernaryExpr + | RangeExprLvl "if" RangeExprLvl "else" TernaryExpr + | RangeExprLvl "when" RangeExprLvl "else" TernaryExpr ; + +RangeExprLvl = LogicalOrExpr [ "..<" | "..=" ] LogicalOrExpr ; + +LogicalOrExpr = LogicalAndExpr { "||" LogicalAndExpr } ; +LogicalAndExpr = ComparisonExpr { "&&" ComparisonExpr } ; + +ComparisonExpr = AddExpr { CompareOp AddExpr } ; +CompareOp = "==" | "!=" | "<" | "<=" | ">" | ">=" ; + +AddExpr = MulExpr { AddOp MulExpr } ; +AddOp = "+" | "-" | "|" | "~" | "in" | "not_in" ; + +MulExpr = UnaryExpr { MulOp UnaryExpr } ; +MulOp = "*" | "/" | "%" | "%%" | "&" | "&~" | "<<" | ">>" ; + +/* Unary Expression */ + +UnaryExpr = PostfixExpr + | UnaryOp UnaryExpr + | "cast" "(" Type ")" UnaryExpr + | "transmute" "(" Type ")" UnaryExpr + | "auto_cast" UnaryExpr + | "." IDENT /* implicit selector */; + +UnaryOp = "+" | "-" | "~" | "&" | "!" ; + + +/* Postfix / Operand Expressions */ + +PostfixExpr = Operand { PostfixOp } ; + +PostfixOp = CallBody /* call */ + | "->" IDENT CallBody /* selector call */ + | "." IDENT /* field selector */ + | "." "?" /* inferred type assertion */ + | "." "(" Type ")" /* type assertion */ + | "[" Expr "]" /* index */ + | "[" [ Expr ] ":" [ Expr ] "]" /* slice */ + | "[" Expr "," Expr "]" /* matrix index */ + | "^" /* pointer deref */ + | PostfixOrOp ; + +CallBody = "(" [ ArgList ] ")" ; + + +PostfixOrOp = "or_return" + | "or_break" [ IDENT ] + | "or_continue" [ IDENT ] ; + +ArgList = Arg { "," Arg } [ "," ] ; +Arg = [ IDENT "=" ] Expr + | ".." Expr ; /* spread */ + + +Operand = IDENT + | "---" /* unintialized expression */ + | "context" + | "typeid" + | Literal + | "(" Expr ")" + | ProcLiteral + | ProcGroup + | [ "#partial" ] CompoundLiteral + | DirectiveExpr + | Type ; + +DirectiveExpr = "#" IDENT ; /* Used as the catch all */ + + +/* Literals */ + +Literal = INT_LIT + | FLOAT_LIT + | IMAGINARY_LIT + | RUNE_LIT + | STRING_LIT + | RAW_STRING_LIT ; + + + +CompoundLiteral = [ Type ] "{" [ ElementList ] "}" ; + +ElementList = Element { "," Element } [ "," ] ; + +Element = Expr [ "=" Expr ] + | ( Expr "..<" Expr | Expr "..=" Expr ) "=" Expr ; + +/* Types */ + +Type = TypeName + | TypeLit + | "(" Type ")" + | "distinct" Type + | "typeid" + | "#type" Type ; + +TypeName = IDENT + | QualifiedIdent + | PolyType ; + +QualifiedIdent = IDENT "." IDENT ; + +PolyType = "$" IDENT [ "/" Type ] ; + +TypeLit = PointerType + | MultiPointerType + | ArrayType + | SliceType + | DynArrayType + | FixedCapDynArrayType + | MapType + | StructType + | UnionType + | EnumType + | BitSetType + | BitFieldType + | ProcType + | MatrixType + | SimdType + | SOAType ; + + +PointerType = "^" Type ; +MultiPointerType = "[^]" Type ; + + + +ArrayType = "[" Expr "]" Type /* fixed-length or enumerated array */ + | "[" "?" "]" Type /* infer-length array */ + | "[" EnumType "]" Type ; /* enumerated array */ + +SliceType = "[" "]" Type ; + +DynArrayType = "[" "dynamic" "]" Type ; + +FixedCapDynArrayType = "[" "dynamic" ";" Expr "]" Type ; /* [dynamic; N]T */ + +MapType = "map" "[" Type "]" Type ; + + +StructType = "struct" + [ "(" PolyParamList ")" ] + [ StructDirectives ] + [ WhereClause ] + "{" [ FieldList ] "}" ; + +StructDirectives = { "#packed" + | "#raw_union" + | "#align" "(" Expr ")" + | "#min_field_align" "(" Expr ")" + | "#max_field_align" "(" Expr ")" + | "#simple" + | "#all_or_none" } ; + +FieldList = Field { "," Field } [ "," ] ; + +Field = FieldNameList ":" Type [ FieldTag ] ; + +FieldNameList = FieldName { "," FieldName } ; +FieldName = [ "using" | "#subtype" ] IDENT ; + +FieldTag = STRING_LIT | RAW_STRING_LIT ; + +UnionType = "union" + [ "(" PolyParamList ")" ] + [ UnionDirectives ] + [ WhereClause ] + "{" [ TypeList ] "}" ; + +UnionDirectives = { "#no_nil" + | "#shared_nil" + | "#align" "(" Expr ")" } ; + + +EnumType = "enum" [ Type ] "{" [ EnumFieldList ] "}" ; + +EnumFieldList = EnumField { "," EnumField } [ "," ] ; +EnumField = IDENT [ "=" Expr ] ; + + +BitSetType = "bit_set" "[" ( Type | RangeExpr ) [ ";" Type ] "]" ; + +BitFieldType = "bit_field" Type "{" [ BitFieldList ] "}" ; + +BitFieldList = BitFieldField { "," BitFieldField } [ "," ] ; +BitFieldField = IDENT ":" Type "|" Expr ; + + +ProcType = "proc" [ CallingConvention ] "(" [ ProcParamList ] ")" + [ "->" ProcResults ] ; + +ProcLiteral = ProcType [ WhereClause ] ( ProcBody | "---" ) ; /* --- = no body / foreign */ +ProcGroup = "proc" "{" ProcGroupList "}" ; /* procedure group */ + + +ProcBody = "{" { Stmt } "}" +ProcGroupList = Expr { "," Expr } [ "," ] ; + +CallingConvention = STRING_LIT ; /* "odin", "c", "std", "contextless", "fast", "none", etc. */ + +ProcParamList = ProcParam { "," ProcParam } [ "," ] ; + +ProcParam = [ ParamPrefix ] PolyIdentList ":" [ ParamModifier ] ProcParamType [ "=" Expr ] ; + +ProcParamType = Type + | "typeid" "/" ProcParamType ; + +PolyIdent = [ "$" ] IDENT ; +PolyIdentList = PolyIdent { "," PolyIdent } ; + +ParamPrefix = "using" + | "#no_alias" + | "#any_int" + | "#by_ptr" + | "#c_vararg" + | "#no_broadcast" ; + +ParamModifier = ".." ; /* variadic */ + +ProcResults = Type + | "(" [ FieldList ] ")" ; + +MatrixType = [ "#row_major" | "#column_major" ] "matrix" "[" Expr "," Expr "]" Type ; + + +SimdType = "#simd" "[" Expr "]" Type ; + + +SOAType = "#soa" ( ArrayType | SliceType | DynArrayType | FixedCapDynArrayType ) ; + + +PolyParamList = PolyParam { "," PolyParam } ; +PolyParam = PolyIdent ":" Type ; + +WhereClause = "where" ConstraintExpr { "," ConstraintExpr } ; +ConstraintExpr = Expr ; + + +Attribute = "@" "(" AttrElemList ")" + | "@" IDENT ; /* shorthand: @private */ + +AttrElemList = AttrElem { "," AttrElem } [ "," ] ; +AttrElem = IDENT [ "=" Expr ] ; \ No newline at end of file diff --git a/src/array.cpp b/src/array.cpp index ec2c97d0e..9cf7c6ce3 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -449,6 +449,20 @@ gb_internal void array_unordered_remove(Array *array, isize index) { array_pop(array); } +template +gb_internal void array_inject_at(Array *array, isize index, T value) { + GB_ASSERT(0 <= index); + + isize n = gb_max(array->count, index); + isize new_size = n+1; + array_resize(array, new_size); + + gb_memmove(array->data+index+1, array->data+index, gb_size_of(T)*(array->count-index-1)); + array->data[index] = value; +} + + + template diff --git a/src/big_int.cpp b/src/big_int.cpp index 0b0a9a400..a8ea2079b 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -16,14 +16,25 @@ void MP_FREE(void *mem, size_t size) { #else void *MP_MALLOC(size_t size) { - return gb_alloc(permanent_allocator(), cast(isize)size); + Arena *arena = get_arena(ThreadArena_Permanent); + return arena_alloc(arena, cast(isize)size, 16); } void *MP_REALLOC(void *mem, size_t oldsize, size_t newsize) { - return gb_resize(permanent_allocator(), mem, cast(isize)oldsize, cast(isize)newsize); + if (newsize < oldsize) { + return mem; + } + if (newsize == 0) { + return mem; + } + Arena *arena = get_arena(ThreadArena_Permanent); + void *new_mem = arena_alloc(arena, cast(isize)newsize, 16); + gb_memcopy(new_mem, mem, oldsize); + return new_mem; } void *MP_CALLOC(size_t nmemb, size_t size) { - size_t total = nmemb*size; - return gb_alloc(permanent_allocator(), cast(isize)total); + Arena *arena = get_arena(ThreadArena_Permanent); + isize total_size = cast(isize)(nmemb * size); + return arena_alloc(arena, total_size, 16); } void MP_FREE(void *mem, size_t size) { // DO NOTHING @@ -46,6 +57,8 @@ gb_internal void big_int_dealloc(BigInt *dst) { mp_clear(dst); } +gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x); + gb_internal BigInt big_int_make(BigInt const *b, bool abs=false); gb_internal BigInt big_int_make_abs(BigInt const *b); gb_internal BigInt big_int_make_u64(u64 x); @@ -197,8 +210,13 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success BigInt b = {}; big_int_from_u64(&b, base); + defer (big_int_dealloc(&b)); + mp_zero(dst); + BigInt digit = {}; + defer (big_int_dealloc(&digit)); + isize i = 0; for (; i < len; i++) { Rune r = cast(Rune)text[i]; @@ -224,9 +242,10 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success } break; } - BigInt val = big_int_make_u64(v); + + big_int_from_u64(&digit, v); big_int_mul_eq(dst, &b); - big_int_add_eq(dst, &val); + big_int_add_eq(dst, &digit); } if (i < len && (text[i] == 'e' || text[i] == 'E')) { i += 1; @@ -235,6 +254,7 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success if (text[i] == '+') { i += 1; } + u64 exp = 0; for (; i < len; i++) { char r = cast(char)text[i]; @@ -251,8 +271,19 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success exp *= 10; exp += v; } + + // NOTE(Jeroen): A valid integer can never have an exponent larger than 308 (per `max(f64)`). + // As an integer, not even larger than `max(u128)` which has a base 10 exponent of 38. + // But we also use this path to parse float literals like those in `core:math.pow10_f64`, + // so we have to stick with 1e308. + if (exp > 308) { + *success = false; + return; + } + BigInt tmp = {}; mp_init(&tmp); + defer (big_int_dealloc(&tmp)); big_int_exp_u64(&tmp, &b, exp, success); big_int_mul_eq(dst, &tmp); } @@ -264,6 +295,10 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success +gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x) { + return mp_count_bits(x) <= 64; +} + gb_internal u64 big_int_to_u64(BigInt const *x) { GB_ASSERT(x->sign == 0); return mp_get_u64(x); @@ -396,6 +431,14 @@ gb_internal void big_int_rem(BigInt *z, BigInt const *x, BigInt const *y) { big_int_quo_rem(x, y, &q, z); big_int_dealloc(&q); } +gb_internal void big_int_mod_mod(BigInt *z, BigInt const *x, BigInt const *y) { + BigInt q = {}; + big_int_rem(&q, x, y); + big_int_add(&q, &q, y); + big_int_rem(z, &q, y); + big_int_dealloc(&q); + +} gb_internal void big_int_euclidean_mod(BigInt *z, BigInt const *x, BigInt const *y) { BigInt y0 = {}; diff --git a/src/bug_report.cpp b/src/bug_report.cpp index 0a617fe39..98a376895 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -540,6 +540,7 @@ gb_internal void report_os_info() { } switch (major) { + case 26: gb_printf("macOS Tahoe"); break; case 15: gb_printf("macOS Sequoia"); break; case 14: gb_printf("macOS Sonoma"); break; case 13: gb_printf("macOS Ventura"); break; @@ -667,8 +668,14 @@ gb_internal void print_bug_report_help() { gb_printf("-nightly"); #endif + String version = {}; + #ifdef GIT_SHA - gb_printf(":%s", GIT_SHA); + version.text = cast(u8 *)GIT_SHA; + version.len = gb_strlen(GIT_SHA); + if (version != "") { + gb_printf(":%.*s", LIT(version)); + } #endif gb_printf("\n"); diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c941e0f68..e6267bb3d 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -9,6 +9,7 @@ // #endif #define DEFAULT_MAX_ERROR_COLLECTOR_COUNT (36) +#define DEFAULT_DID_YOU_MEAN_LIMIT (10) enum TargetOsKind : u16 { TargetOs_Invalid, @@ -16,11 +17,9 @@ enum TargetOsKind : u16 { TargetOs_windows, TargetOs_darwin, TargetOs_linux, - TargetOs_essence, TargetOs_freebsd, TargetOs_openbsd, TargetOs_netbsd, - TargetOs_haiku, TargetOs_wasi, TargetOs_js, @@ -31,6 +30,22 @@ enum TargetOsKind : u16 { TargetOs_COUNT, }; +gb_global String target_os_names[TargetOs_COUNT] = { + str_lit(""), + str_lit("windows"), + str_lit("darwin"), + str_lit("linux"), + str_lit("freebsd"), + str_lit("openbsd"), + str_lit("netbsd"), + + str_lit("wasi"), + str_lit("js"), + str_lit("orca"), + + str_lit("freestanding"), +}; + enum TargetArchKind : u16 { TargetArch_Invalid, @@ -45,6 +60,17 @@ enum TargetArchKind : u16 { TargetArch_COUNT, }; +gb_global String target_arch_names[TargetArch_COUNT] = { + str_lit(""), + str_lit("amd64"), + str_lit("i386"), + str_lit("arm32"), + str_lit("arm64"), + str_lit("wasm32"), + str_lit("wasm64p32"), + str_lit("riscv64"), +}; + enum TargetEndianKind : u8 { TargetEndian_Little, TargetEndian_Big, @@ -52,6 +78,11 @@ enum TargetEndianKind : u8 { TargetEndian_COUNT, }; +gb_global String target_endian_names[TargetEndian_COUNT] = { + str_lit("little"), + str_lit("big"), +}; + enum TargetABIKind : u16 { TargetABI_Default, @@ -61,7 +92,14 @@ enum TargetABIKind : u16 { TargetABI_COUNT, }; +gb_global String target_abi_names[TargetABI_COUNT] = { + str_lit(""), + str_lit("win64"), + str_lit("sysv"), +}; + enum Windows_Subsystem : u8 { + Windows_Subsystem_UNKNOWN, Windows_Subsystem_BOOT_APPLICATION, Windows_Subsystem_CONSOLE, // Default, Windows_Subsystem_EFI_APPLICATION, @@ -75,59 +113,32 @@ enum Windows_Subsystem : u8 { Windows_Subsystem_COUNT, }; +gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { + str_lit(""), + str_lit("BOOT_APPLICATION"), + str_lit("CONSOLE"), // Default + str_lit("EFI_APPLICATION"), + str_lit("EFI_BOOT_SERVICE_DRIVER"), + str_lit("EFI_ROM"), + str_lit("EFI_RUNTIME_DRIVER"), + str_lit("NATIVE"), + str_lit("POSIX"), + str_lit("WINDOWS"), + str_lit("WINDOWSCE"), +}; + struct MicroarchFeatureList { String microarch; String features; }; -gb_global String target_os_names[TargetOs_COUNT] = { - str_lit(""), - str_lit("windows"), - str_lit("darwin"), - str_lit("linux"), - str_lit("essence"), - str_lit("freebsd"), - str_lit("openbsd"), - str_lit("netbsd"), - str_lit("haiku"), - - str_lit("wasi"), - str_lit("js"), - str_lit("orca"), - - str_lit("freestanding"), -}; - -gb_global String target_arch_names[TargetArch_COUNT] = { - str_lit(""), - str_lit("amd64"), - str_lit("i386"), - str_lit("arm32"), - str_lit("arm64"), - str_lit("wasm32"), - str_lit("wasm64p32"), - str_lit("riscv64"), -}; - #if defined(GB_SYSTEM_WINDOWS) #include #else #include #endif - #include "build_settings_microarch.cpp" -gb_global String target_endian_names[TargetEndian_COUNT] = { - str_lit("little"), - str_lit("big"), -}; - -gb_global String target_abi_names[TargetABI_COUNT] = { - str_lit(""), - str_lit("win64"), - str_lit("sysv"), -}; - gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, TargetEndian_Little, @@ -138,19 +149,6 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, }; -gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { - str_lit("BOOT_APPLICATION"), - str_lit("CONSOLE"), // Default - str_lit("EFI_APPLICATION"), - str_lit("EFI_BOOT_SERVICE_DRIVER"), - str_lit("EFI_ROM"), - str_lit("EFI_RUNTIME_DRIVER"), - str_lit("NATIVE"), - str_lit("POSIX"), - str_lit("WINDOWS"), - str_lit("WINDOWSCE"), -}; - #ifndef ODIN_VERSION_RAW #define ODIN_VERSION_RAW "dev-unknown-unknown" #endif @@ -170,15 +168,18 @@ struct TargetMetrics { enum Subtarget : u32 { Subtarget_Default, - Subtarget_iOS, + Subtarget_iPhone, + Subtarget_iPhoneSimulator, Subtarget_Android, - + Subtarget_COUNT, + Subtarget_Invalid, // NOTE(harold): Must appear after _COUNT as this is not a real subtarget }; gb_global String subtarget_strings[Subtarget_COUNT] = { str_lit(""), - str_lit("ios"), + str_lit("iphone"), + str_lit("iphonesimulator"), str_lit("android"), }; @@ -245,9 +246,10 @@ gb_global char const *odin_command_strings[32] = { enum CmdDocFlag : u32 { - CmdDocFlag_Short = 1<<0, - CmdDocFlag_AllPackages = 1<<1, - CmdDocFlag_DocFormat = 1<<2, + CmdDocFlag_Short = 1<<0, + CmdDocFlag_InSourceOrder = 1<<1, + CmdDocFlag_AllPackages = 1<<2, + CmdDocFlag_DocFormat = 1<<3, }; enum TimingsExportFormat : i32 { @@ -276,6 +278,13 @@ enum RelocMode : u8 { RelocMode_DynamicNoPIC, }; +enum StackProtector : u8 { + StackProtector_None, + StackProtector_Ssp, + StackProtector_SspReq, + StackProtector_SspStrong, +}; + enum BuildPath : u8 { BuildPath_Main_Package, // Input Path to the package directory (or file) we're building. BuildPath_RC, // Input Path for .rc file, can be set with `-resource:`. @@ -287,7 +296,7 @@ enum BuildPath : u8 { BuildPath_VS_LIB, // vs_library_path BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`. - BuildPath_PDB, // Output Path for .pdb file, can be overridden with `-pdb-name:`. + BuildPath_Symbols, // Output Path for .pdb or .dSym file, can be overridden with `-pdb-name:`. BuildPathCOUNT, }; @@ -305,6 +314,7 @@ enum VetFlags : u64 { VetFlag_Cast = 1u<<8, VetFlag_Tabs = 1u<<9, VetFlag_UnusedProcedures = 1u<<10, + VetFlag_ExplicitAllocators = 1u<<11, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, @@ -338,6 +348,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Tabs; } else if (name == "unused-procedures") { return VetFlag_UnusedProcedures; + } else if (name == "explicit-allocators") { + return VetFlag_ExplicitAllocators; } return VetFlag_NONE; } @@ -345,12 +357,50 @@ u64 get_vet_flag_from_name(String const &name) { enum OptInFeatureFlags : u64 { OptInFeatureFlag_NONE = 0, OptInFeatureFlag_DynamicLiterals = 1u<<0, + + OptInFeatureFlag_GlobalContext = 1u<<1, + + OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<2, + OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<3, + OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<4, + OptInFeatureFlag_IntegerDivisionByZero_AllBits = 1u<<5, + + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap| + OptInFeatureFlag_IntegerDivisionByZero_Zero| + OptInFeatureFlag_IntegerDivisionByZero_Self| + OptInFeatureFlag_IntegerDivisionByZero_AllBits, + + OptInFeatureFlag_ForceTypeAssert = 1u<<6, + OptInFeatureFlag_UsingStmt = 1u<<7, }; u64 get_feature_flag_from_name(String const &name) { if (name == "dynamic-literals") { return OptInFeatureFlag_DynamicLiterals; } + if (name == "integer-division-by-zero:trap") { + return OptInFeatureFlag_IntegerDivisionByZero_Trap; + } + if (name == "integer-division-by-zero:zero") { + return OptInFeatureFlag_IntegerDivisionByZero_Zero; + } + if (name == "integer-division-by-zero:self") { + return OptInFeatureFlag_IntegerDivisionByZero_Self; + } + if (name == "integer-division-by-zero:all-bits") { + return OptInFeatureFlag_IntegerDivisionByZero_AllBits; + } + if (name == "using-stmt") { + return OptInFeatureFlag_UsingStmt; + } + if (name == "force-type-assert") { + return OptInFeatureFlag_ForceTypeAssert; + } + + + if (name == "global-context") { + return OptInFeatureFlag_GlobalContext; + } return OptInFeatureFlag_NONE; } @@ -375,35 +425,58 @@ struct BuildCacheData { }; +enum LTOKind : i32 { + LTO_None, + LTO_Thin, + LTO_Thin_Files, +}; + enum LinkerChoice : i32 { Linker_Invalid = -1, Linker_Default = 0, Linker_lld, Linker_radlink, + Linker_mold, Linker_COUNT, }; +enum SourceCodeLocationInfo : u8 { + SourceCodeLocationInfo_Normal = 0, + SourceCodeLocationInfo_Obfuscated = 1, + SourceCodeLocationInfo_Filename = 2, + SourceCodeLocationInfo_None = 3, +}; + String linker_choices[Linker_COUNT] = { str_lit("default"), str_lit("lld"), str_lit("radlink"), + str_lit("mold"), }; +enum IntegerDivisionByZeroKind : u8 { + IntegerDivisionByZero_Trap, + IntegerDivisionByZero_Zero, + IntegerDivisionByZero_Self, + IntegerDivisionByZero_AllBits, +}; + + // This stores the information for the specify architecture of this build struct BuildContext { // Constants - String ODIN_OS; // Target operating system - String ODIN_ARCH; // Target architecture - String ODIN_VENDOR; // Compiler vendor - String ODIN_VERSION; // Compiler version - String ODIN_ROOT; // Odin ROOT - String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name - String ODIN_WINDOWS_SUBSYSTEM; // Empty string for non-Windows targets - bool ODIN_DEBUG; // Odin in debug mode - bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not - bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) - bool ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) + String ODIN_OS; // Target operating system + String ODIN_ARCH; // Target architecture + String ODIN_VENDOR; // Compiler vendor + String ODIN_VERSION; // Compiler version + String ODIN_ROOT; // Odin ROOT + String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name + Windows_Subsystem ODIN_WINDOWS_SUBSYSTEM; // .Console, .Windows + bool ODIN_DEBUG; // Odin in debug mode + bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not + bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) + bool ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) bool ODIN_FOREIGN_ERROR_PROCEDURES; bool ODIN_VALGRIND_SUPPORT; @@ -441,6 +514,7 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; + bool keep_executable; bool generate_docs; bool custom_optimization_level; i32 optimization_level; @@ -454,11 +528,13 @@ struct BuildContext { bool show_more_timings; bool show_defineables; String export_defineables_file; + bool ignore_unused_defineables; bool show_system_calls; bool keep_temp_files; bool ignore_unknown_attributes; bool no_bounds_check; bool no_type_assert; + bool dynamic_literals; // Opt-in to `#+feature dynamic-literals` project-wide. bool no_output_files; bool no_crt; bool no_rpath; @@ -468,6 +544,11 @@ struct BuildContext { bool different_os; bool keep_object_files; bool disallow_do; + bool show_import_graph; + + bool webkit_switch_workaround; + + IntegerDivisionByZeroKind integer_division_by_zero_behaviour; LinkerChoice linker_choice; @@ -490,37 +571,55 @@ struct BuildContext { bool ignore_microsoft_magic; bool linker_map_file; + bool build_diagnostics; + bool use_single_module; bool use_separate_modules; + LTOKind lto_kind; bool module_per_file; bool cached; BuildCacheData build_cache_data; bool internal_no_inline; bool internal_by_value; + bool internal_weak_monomorphization; + bool internal_ignore_llvm_verification; + bool internal_llvm_no_sroa; + + bool enable_rvo; bool no_threaded_checker; bool show_debug_messages; + int did_you_mean_limit; + bool copy_file_contents; bool no_rtti; bool dynamic_map_calls; - bool obfuscate_source_code_locations; + SourceCodeLocationInfo source_code_location_info; bool min_link_libs; + String export_linked_libs_path; + bool print_linker_flags; - RelocMode reloc_mode; + RelocMode reloc_mode; + StackProtector stack_protector; + bool disable_red_zone; + bool disable_unwind; + bool no_plt; isize max_error_count; - bool tilde_backend; + bool bedrock; + bool disable_non_constant_globals; + bool disable_init_fini; u32 cmd_doc_flags; @@ -690,20 +789,6 @@ gb_global TargetMetrics target_netbsd_arm64 = { str_lit("aarch64-unknown-netbsd-elf"), }; -gb_global TargetMetrics target_haiku_amd64 = { - TargetOs_haiku, - TargetArch_amd64, - 8, 8, AMD64_MAX_ALIGNMENT, 32, - str_lit("x86_64-unknown-haiku"), -}; - -gb_global TargetMetrics target_essence_amd64 = { - TargetOs_essence, - TargetArch_amd64, - 8, 8, AMD64_MAX_ALIGNMENT, 32, - str_lit("x86_64-pc-none-elf"), -}; - gb_global TargetMetrics target_freestanding_wasm32 = { TargetOs_freestanding, @@ -770,10 +855,19 @@ gb_global TargetMetrics target_freestanding_amd64_win64 = { TargetOs_freestanding, TargetArch_amd64, 8, 8, AMD64_MAX_ALIGNMENT, 32, - str_lit("x86_64-pc-none-msvc"), + str_lit("x86_64-pc-windows-msvc"), TargetABI_Win64, }; +gb_global TargetMetrics target_freestanding_amd64_mingw = { + TargetOs_freestanding, + TargetArch_amd64, + 8, 8, AMD64_MAX_ALIGNMENT, 32, + str_lit("x86_64-pc-windows-gnu"), + TargetABI_Win64, +}; + + gb_global TargetMetrics target_freestanding_arm64 = { TargetOs_freestanding, TargetArch_arm64, @@ -804,8 +898,6 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("darwin_amd64"), &target_darwin_amd64 }, { str_lit("darwin_arm64"), &target_darwin_arm64 }, - { str_lit("essence_amd64"), &target_essence_amd64 }, - { str_lit("linux_i386"), &target_linux_i386 }, { str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("linux_arm64"), &target_linux_arm64 }, @@ -823,7 +915,6 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("netbsd_arm64"), &target_netbsd_arm64 }, { str_lit("openbsd_amd64"), &target_openbsd_amd64 }, - { str_lit("haiku_amd64"), &target_haiku_amd64 }, { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 }, { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, @@ -836,6 +927,7 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv }, { str_lit("freestanding_amd64_win64"), &target_freestanding_amd64_win64 }, + { str_lit("freestanding_amd64_mingw"), &target_freestanding_amd64_mingw }, { str_lit("freestanding_arm64"), &target_freestanding_arm64 }, { str_lit("freestanding_arm32"), &target_freestanding_arm32 }, @@ -847,7 +939,7 @@ gb_global NamedTargetMetrics *selected_target_metrics; gb_global Subtarget selected_subtarget; -gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr) { +gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr, String *subtarget_str = nullptr) { String os_name = str; String subtarget = {}; auto part = string_partition(str, str_lit(":")); @@ -864,18 +956,26 @@ gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtar break; } } - if (subtarget_) *subtarget_ = Subtarget_Default; - if (subtarget.len != 0) { - if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) { - if (subtarget_) *subtarget_ = Subtarget_Default; - } else { - for (isize i = 1; i < Subtarget_COUNT; i++) { - if (str_eq_ignore_case(subtarget_strings[i], subtarget)) { - if (subtarget_) *subtarget_ = cast(Subtarget)i; - break; + if (subtarget_str) *subtarget_str = subtarget; + + if (subtarget_) { + if (subtarget.len != 0) { + *subtarget_ = Subtarget_Invalid; + + if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) { + *subtarget_ = Subtarget_Default; + + } else { + for (isize i = 1; i < Subtarget_COUNT; i++) { + if (str_eq_ignore_case(subtarget_strings[i], subtarget)) { + *subtarget_ = cast(Subtarget)i; + break; + } } } + } else { + *subtarget_ = Subtarget_Default; } } @@ -900,14 +1000,6 @@ gb_internal bool is_excluded_target_filename(String name) { return true; } - if (build_context.command_kind != Command_test) { - String test_suffix = str_lit("_test"); - if (string_ends_with(name, test_suffix) && name != test_suffix) { - // Ignore *_test.odin files - return true; - } - } - String str1 = {}; String str2 = {}; isize n = 0; @@ -1062,10 +1154,10 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); + text = permanent_alloc_array(len+1); GetModuleFileNameW(nullptr, text, cast(int)len); - path = string16_to_string(heap_allocator(), make_string16(text, len)); + path = string16_to_string(heap_allocator(), make_string16(cast(u16 *)text, len)); for (i = path.len-1; i >= 0; i--) { u8 c = path[i]; @@ -1084,58 +1176,6 @@ gb_internal String internal_odin_root_dir(void) { return path; } -#elif defined(GB_SYSTEM_HAIKU) - -#include - -gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_); - -gb_internal String internal_odin_root_dir(void) { - String path = global_module_path; - isize len, i; - u8 *text; - - if (global_module_path_set) { - return global_module_path; - } - - auto path_buf = array_make(heap_allocator(), 300); - defer (array_free(&path_buf)); - - len = 0; - for (;;) { - u32 sz = path_buf.count; - int res = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, nullptr, &path_buf[0], sz); - if(res == B_OK) { - len = sz; - break; - } else { - array_resize(&path_buf, sz + 1); - } - } - - mutex_lock(&string_buffer_mutex); - defer (mutex_unlock(&string_buffer_mutex)); - - text = gb_alloc_array(permanent_allocator(), u8, len + 1); - gb_memmove(text, &path_buf[0], len); - - path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr); - - for (i = path.len-1; i >= 0; i--) { - u8 c = path[i]; - if (c == '/' || c == '\\') { - break; - } - path.len--; - } - - global_module_path = path; - global_module_path_set = true; - - return path; -} - #elif defined(GB_SYSTEM_OSX) #include @@ -1169,7 +1209,7 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), u8, len + 1); + text = permanent_alloc_array(len + 1); gb_memmove(text, &path_buf[0], len); path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr); @@ -1330,7 +1370,7 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), u8, len + 1); + text = permanent_alloc_array(len + 1); gb_memmove(text, &path_buf[0], len); @@ -1363,14 +1403,14 @@ gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) { mutex_lock(&fullpath_mutex); - len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr); + len = GetFullPathNameW(cast(wchar_t *)&string16[0], 0, nullptr, nullptr); if (len != 0) { - wchar_t *text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); - GetFullPathNameW(&string16[0], len, text, nullptr); + wchar_t *text = permanent_alloc_array(len+1); + GetFullPathNameW(cast(wchar_t *)&string16[0], len, text, nullptr); mutex_unlock(&fullpath_mutex); text[len] = 0; - result = string16_to_string(a, make_string16(text, len)); + result = string16_to_string(a, make_string16(cast(u16 *)text, len)); result = string_trim_whitespace(result); // Replace Windows style separators @@ -1589,7 +1629,20 @@ gb_internal void init_android_values(bool with_sdk) { gb_exit(1); } - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + switch (bc->metrics.arch) { + case TargetArch_arm64: + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = str_lit("aarch64-linux-android"); + break; + case TargetArch_arm32: + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = str_lit("arm-linux-androideabi"); + break; + case TargetArch_amd64: + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = str_lit("x86_64-linux-android"); + break; + case TargetArch_i386: + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = str_lit("i686-linux-android"); + break; + } char buf[32] = {}; gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); @@ -1638,6 +1691,55 @@ gb_internal char *token_pos_to_string(TokenPos const &pos) { return s; } +gb_internal String normalize_minimum_os_version_string(String version) { + GB_ASSERT(version.len > 0); + + gbString normalized = gb_string_make(permanent_allocator(), ""); + + int granularity = 0; + String_Iterator it = {version, 0}; + for (;; granularity++) { + String str = string_split_iterator(&it, '.'); + if (str == "") break; + if (granularity > 0) { + normalized = gb_string_appendc(normalized, "."); + } + normalized = gb_string_append_length(normalized, str.text, str.len); + } + + for (; granularity < 3; granularity++) { + normalized = gb_string_appendc(normalized, ".0"); + } + + return make_string_c(normalized); +} + +gb_internal void init_build_context_error_pos_style() { + build_context.ODIN_ERROR_POS_STYLE = ErrorPosStyle_Default; + + char const *found = gb_get_env("ODIN_ERROR_POS_STYLE", permanent_allocator()); + if (found) { + ErrorPosStyle kind = ErrorPosStyle_Default; + String style = make_string_c(found); + style = string_trim_whitespace(style); + if (style == "" || style == "default" || style == "odin") { + kind = ErrorPosStyle_Default; + } else if (style == "unix" || style == "gcc" || style == "clang" || style == "llvm") { + kind = ErrorPosStyle_Unix; + } else { + gb_printf_err("Invalid ODIN_ERROR_POS_STYLE: got %.*s\n", LIT(style)); + gb_printf_err("Valid formats:\n"); + gb_printf_err("\t\"default\" or \"odin\"\n"); + gb_printf_err("\t\tpath(line:column) message\n"); + gb_printf_err("\t\"unix\"\n"); + gb_printf_err("\t\tpath:line:column: message\n"); + gb_exit(1); + } + + build_context.ODIN_ERROR_POS_STYLE = kind; + } +} + gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subtarget) { BuildContext *bc = &build_context; @@ -1654,30 +1756,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->max_error_count = DEFAULT_MAX_ERROR_COLLECTOR_COUNT; } - { - char const *found = gb_get_env("ODIN_ERROR_POS_STYLE", permanent_allocator()); - if (found) { - ErrorPosStyle kind = ErrorPosStyle_Default; - String style = make_string_c(found); - style = string_trim_whitespace(style); - if (style == "" || style == "default" || style == "odin") { - kind = ErrorPosStyle_Default; - } else if (style == "unix" || style == "gcc" || style == "clang" || style == "llvm") { - kind = ErrorPosStyle_Unix; - } else { - gb_printf_err("Invalid ODIN_ERROR_POS_STYLE: got %.*s\n", LIT(style)); - gb_printf_err("Valid formats:\n"); - gb_printf_err("\t\"default\" or \"odin\"\n"); - gb_printf_err("\t\tpath(line:column) message\n"); - gb_printf_err("\t\"unix\"\n"); - gb_printf_err("\t\tpath:line:column: message\n"); - gb_exit(1); - } - - build_context.ODIN_ERROR_POS_STYLE = kind; - } - } - bc->copy_file_contents = true; TargetMetrics *metrics = nullptr; @@ -1705,8 +1783,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta #else metrics = &target_netbsd_amd64; #endif - #elif defined(GB_SYSTEM_HAIKU) - metrics = &target_haiku_amd64; #elif defined(GB_CPU_ARM) metrics = &target_linux_arm64; #elif defined(GB_CPU_RISCV) @@ -1771,7 +1847,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (bc->disable_red_zone) { if (is_arch_wasm() && bc->metrics.os == TargetOs_freestanding) { - gb_printf_err("-disable-red-zone is not support for this target"); + gb_printf_err("-disable-red-zone is not supported on this target"); gb_exit(1); } } @@ -1780,14 +1856,16 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->no_entry_point = true; } else { if (bc->no_rtti) { - gb_printf_err("-no-rtti is only allowed on freestanding targets\n"); - gb_exit(1); + if (!bc->bedrock) { + gb_printf_err("-no-rtti is only allowed on freestanding targets or '-bedrock'\n"); + gb_exit(1); + } } } // Default to subsystem:CONSOLE on Windows targets - if (bc->ODIN_WINDOWS_SUBSYSTEM == "" && bc->metrics.os == TargetOs_windows) { - bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_CONSOLE]; + if (bc->ODIN_WINDOWS_SUBSYSTEM == Windows_Subsystem_UNKNOWN && bc->metrics.os == TargetOs_windows) { + bc->ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_CONSOLE; } if (subtarget == Subtarget_Android) { @@ -1814,26 +1892,85 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } } - if (metrics->os == TargetOs_darwin && subtarget == Subtarget_iOS) { - switch (metrics->arch) { - case TargetArch_arm64: - bc->metrics.target_triplet = str_lit("arm64-apple-ios"); - break; - case TargetArch_amd64: - bc->metrics.target_triplet = str_lit("x86_64-apple-ios"); - break; - default: - GB_PANIC("Unknown architecture for darwin"); + if (metrics->os == TargetOs_darwin) { + switch (subtarget) { + case Subtarget_iPhone: + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("arm64-apple-ios"); + break; + default: + GB_PANIC("Unknown architecture for -subtarget:iphone"); + } + break; + case Subtarget_iPhoneSimulator: + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("arm64-apple-ios-simulator"); + break; + case TargetArch_amd64: + bc->metrics.target_triplet = str_lit("x86_64-apple-ios-simulator"); + break; + default: + GB_PANIC("Unknown architecture for -subtarget:iphonesimulator"); + } + break; + } + } else if (metrics->os == TargetOs_openbsd) { + // Always use PIC for OpenBSD: it defaults to PIE + if (bc->reloc_mode == RelocMode_Default) { + bc->reloc_mode = RelocMode_PIC; + } + } else if (metrics->arch == TargetArch_riscv64) { + // NOTE(laytan): didn't seem to work without this. + if (bc->reloc_mode == RelocMode_Default) { + bc->reloc_mode = RelocMode_PIC; } } else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) { switch (metrics->arch) { case TargetArch_arm64: - bc->metrics.target_triplet = str_lit("aarch64-none-linux-android"); + bc->metrics.target_triplet = str_lit("aarch64-linux-android"); + bc->reloc_mode = RelocMode_PIC; + break; + case TargetArch_arm32: + bc->metrics.target_triplet = str_lit("armv7a-linux-androideabi"); + bc->reloc_mode = RelocMode_PIC; + break; + case TargetArch_amd64: + bc->metrics.target_triplet = str_lit("x86_64-linux-android"); + bc->reloc_mode = RelocMode_PIC; + break; + case TargetArch_i386: + bc->metrics.target_triplet = str_lit("i686-linux-android"); bc->reloc_mode = RelocMode_PIC; break; default: GB_PANIC("Unknown architecture for -subtarget:android"); } + } else if (metrics->os == TargetOs_linux) { + if (bc->reloc_mode == RelocMode_Default) { + bc->reloc_mode = RelocMode_PIC; + } + switch (metrics->arch) { + case TargetArch_arm64: + case TargetArch_amd64: + bc->no_plt = LLVM_VERSION_MAJOR >= 19; + break; + } + } + + if (metrics->os == TargetOs_windows || + metrics->os == TargetOs_darwin || + metrics->os == TargetOs_linux || + metrics->os == TargetOs_freebsd || + metrics->os == TargetOs_openbsd || + metrics->os == TargetOs_netbsd) { + // -stack-protector is supported + } else { + if (bc->stack_protector != StackProtector_None) { + gb_printf_err("-stack-protector is not supported on this target\n"); + gb_exit(1); + } } if (bc->metrics.os == TargetOs_windows) { @@ -1850,6 +1987,13 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta str_lit("-target "), bc->metrics.target_triplet, str_lit(" ")); } else if (is_arch_wasm()) { gbString link_flags = gb_string_make(heap_allocator(), " "); + + // NOTE(laytan): Put the stack first in the memory, + // causing a stack overflow to error immediately instead of corrupting globals. + link_flags = gb_string_appendc(link_flags, "--stack-first "); + // NOTE(laytan): default stack size is 64KiB, up to a more reasonable 1MiB. + link_flags = gb_string_appendc(link_flags, "-z stack-size=1048576 "); + // link_flags = gb_string_appendc(link_flags, "--export-all "); // link_flags = gb_string_appendc(link_flags, "--export-table "); // if (bc->metrics.arch == TargetArch_wasm64) { @@ -1882,10 +2026,25 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta // does not annoy the user with version warnings. if (metrics->os == TargetOs_darwin) { if (!bc->minimum_os_version_string_given) { - bc->minimum_os_version_string = str_lit("11.0.0"); + if (subtarget == Subtarget_Default) { + bc->minimum_os_version_string = str_lit("11.0.0"); + } else if (subtarget == Subtarget_iPhone || subtarget == Subtarget_iPhoneSimulator) { + // NOTE(harold): We default to 17.4 on iOS because that's when os_sync_wait_on_address was added and + // we'd like to avoid any potential App Store issues by using the private ulock_* there. + bc->minimum_os_version_string = str_lit("17.4.0"); + } } - if (subtarget == Subtarget_Default) { + bc->minimum_os_version_string = normalize_minimum_os_version_string(bc->minimum_os_version_string); + + if (subtarget == Subtarget_iPhoneSimulator) { + // For the iPhoneSimulator subtarget, the version must be between 'ios' and '-simulator'. + String suffix = str_lit("-simulator"); + GB_ASSERT(string_ends_with(bc->metrics.target_triplet, suffix)); + + String prefix = substring(bc->metrics.target_triplet, 0, bc->metrics.target_triplet.len - suffix.len); + bc->metrics.target_triplet = concatenate3_strings(permanent_allocator(), prefix, bc->minimum_os_version_string, suffix); + } else { bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } } else if (selected_subtarget == Subtarget_Android) { @@ -1914,11 +2073,28 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->use_separate_modules = false; } - - // TODO: Static map calls are bugged on `amd64sysv` abi. - if (bc->metrics.os != TargetOs_windows && bc->metrics.arch == TargetArch_amd64) { - // ENFORCE DYNAMIC MAP CALLS - bc->dynamic_map_calls = true; + if (bc->lto_kind == LTO_Thin || bc->lto_kind == LTO_Thin_Files) { +#if LLVM_VERSION_MAJOR < 17 + gb_printf_err("-lto:thin requires LLVM 17 or later\n"); + gb_exit(1); +#endif + if (bc->build_mode == BuildMode_Assembly || bc->build_mode == BuildMode_LLVM_IR) { + gb_printf_err("-lto:thin is incompatible with -build-mode:asm and -build-mode:llvm-ir\n"); + gb_exit(1); + } +#if defined(GB_SYSTEM_WINDOWS) + if (bc->linker_choice != Linker_lld) { + gb_printf_err("-lto:thin on Windows requires -linker:lld\n"); + gb_exit(1); + } +#endif + if (bc->use_single_module) { + gb_printf_err("Warning: -lto:thin overrides -use-single-module; separate modules will be used\n"); + } + bc->use_separate_modules = true; + if (bc->lto_kind == LTO_Thin_Files) { + bc->module_per_file = true; + } } bc->ODIN_VALGRIND_SUPPORT = false; @@ -1962,8 +2138,15 @@ gb_internal bool check_target_feature_is_valid(String const &feature, TargetArch String_Iterator it = {feature, 0}; for (;;) { String str = string_split_iterator(&it, ','); - if (str == "") break; - if (!check_single_target_feature_is_valid(feature_list, str)) { + String feature_str = str; + if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { + feature_str = substring(feature_str, 1, feature_str.len); + if (feature_str == "") { + return false; + } + } + if (feature_str == "") break; + if (!check_single_target_feature_is_valid(feature_list, feature_str)) { if (invalid) *invalid = str; return false; } @@ -2003,8 +2186,26 @@ gb_internal bool check_target_feature_is_enabled(String const &feature, String * String_Iterator it = {feature, 0}; for (;;) { String str = string_split_iterator(&it, ','); - if (str == "") break; - if (!string_set_exists(&build_context.target_features_set, str)) { + String feature_str = str; + bool want_enabled = true; + if (string_starts_with(feature_str, '+') || string_starts_with(feature_str, '-')) { + want_enabled = feature_str[0] == '+'; + feature_str = substring(feature_str, 1, feature_str.len); + } + if (feature_str == "") break; + + String plus_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); + String minus_str = concatenate_strings(temporary_allocator(), make_string_c("-"), feature_str); + + bool has_raw = string_set_exists(&build_context.target_features_set, feature_str); + bool has_plus = string_set_exists(&build_context.target_features_set, plus_str); + bool has_minus = string_set_exists(&build_context.target_features_set, minus_str); + + // NOTE(jakubtomsu): this way "feature" and "+feature" is ALWAYS equivalent, + // and also allows the minus sign to do a final override. + bool is_enabled = (has_plus || has_raw) && !has_minus; + + if (want_enabled != is_enabled) { if (not_enabled) *not_enabled = str; return false; } @@ -2026,6 +2227,36 @@ gb_internal bool check_target_feature_is_superset_of(String const &superset, Str return true; } +gb_internal String infer_object_extension_from_build_context() { + String output_extension = {}; + if (is_arch_wasm()) { + output_extension = STR_LIT("wasm.o"); + } else { + switch (build_context.metrics.os) { + case TargetOs_windows: + output_extension = STR_LIT("obj"); + break; + default: + case TargetOs_darwin: + case TargetOs_linux: + + case TargetOs_freestanding: + switch (build_context.metrics.abi) { + default: + case TargetABI_Default: + case TargetABI_SysV: + output_extension = STR_LIT("o"); + break; + case TargetABI_Win64: + output_extension = STR_LIT("obj"); + break; + } + break; + } + } + return output_extension; +} + // NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate. // We've previously called `parse_build_flags`, so `out_filepath` should be set. gb_internal bool init_build_paths(String init_filename) { @@ -2069,10 +2300,6 @@ gb_internal bool init_build_paths(String init_filename) { } } - if (bc->pdb_filepath.len > 0) { - bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath); - } - if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) { // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest. Find_Result find_result = find_visual_studio_and_windows_sdk(); @@ -2136,9 +2363,6 @@ gb_internal bool init_build_paths(String init_filename) { output_extension = STR_LIT("so"); } else if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); - } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { - // Do nothing: we don't want the .bin extension - // when cross compiling } else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) { // Add .bin extension to avoid collision // with package directory name @@ -2162,13 +2386,8 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("lib"); } - }else if (build_context.build_mode == BuildMode_Object) { - // By default use a .o object extension. - output_extension = STR_LIT("o"); - - if (build_context.metrics.os == TargetOs_windows) { - output_extension = STR_LIT("obj"); - } + } else if (build_context.build_mode == BuildMode_Object) { + output_extension = infer_object_extension_from_build_context(); } else if (build_context.build_mode == BuildMode_Assembly) { // By default use a .S asm extension. output_extension = STR_LIT("S"); @@ -2188,7 +2407,7 @@ gb_internal bool init_build_paths(String init_filename) { return false; } else if (bc->build_paths[BuildPath_Output].ext.len == 0) { gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file)); - return false; + return false; } } } else { @@ -2214,11 +2433,34 @@ gb_internal bool init_build_paths(String init_filename) { while (output_name.len > 0 && (output_name[output_name.len-1] == '/' || output_name[output_name.len-1] == '\\')) { output_name.len -= 1; } + // Only trim the extension if it's an Odin source file. + // This lets people build folders with extensions or files beginning with dots. + if (path_extension(output_name) == ".odin" && !path_is_directory(output_name)) { + output_name = remove_extension_from_path(output_name); + } output_name = remove_directory_from_path(output_name); - output_name = remove_extension_from_path(output_name); output_name = copy_string(ha, string_trim_whitespace(output_name)); - output_path = path_from_string(ha, output_name); - + // This is `path_from_string` without the extension trimming. + Path res = {}; + if (output_name.len > 0) { + String fullpath = path_to_full_path(ha, output_name); + defer (gb_free(ha, fullpath.text)); + + res.basename = directory_from_path(fullpath); + res.basename = copy_string(ha, res.basename); + + if (path_is_directory(fullpath)) { + if (res.basename.len > 0 && res.basename.text[res.basename.len - 1] == '/') { + res.basename.len--; + } + } else { + isize name_start = (res.basename.len > 0) ? res.basename.len + 1 : res.basename.len; + res.name = substring(fullpath, name_start, fullpath.len); + res.name = copy_string(ha, res.name); + } + } + output_path = res; + // Note(Dragos): This is a fix for empty filenames // Turn the trailing folder into the file name if (output_path.name.len == 0) { @@ -2248,6 +2490,26 @@ gb_internal bool init_build_paths(String init_filename) { bc->build_paths[BuildPath_Output] = output_path; } + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows) { + if (bc->pdb_filepath.len > 0) { + bc->build_paths[BuildPath_Symbols] = path_from_string(ha, bc->pdb_filepath); + } else { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("pdb")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } else if (build_context.metrics.os == TargetOs_darwin) { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("dSYM")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } + // Do we have an extension? We might not if the output filename was supplied. if (bc->build_paths[BuildPath_Output].ext.len == 0) { if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) { @@ -2283,9 +2545,10 @@ gb_internal bool init_build_paths(String init_filename) { case TargetOs_windows: case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n"); + gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n"); return false; } } @@ -2293,12 +2556,10 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.sanitizer_flags & SanitizerFlag_Memory) { switch (build_context.metrics.os) { case TargetOs_linux: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:memory is only supported on linux\n"); - return false; - } - if (build_context.metrics.os != TargetOs_linux) { + gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n"); return false; } } @@ -2307,9 +2568,10 @@ gb_internal bool init_build_paths(String init_filename) { switch (build_context.metrics.os) { case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:thread is only supported on linux and darwin\n"); + gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n"); return false; } } @@ -2319,11 +2581,9 @@ gb_internal bool init_build_paths(String init_filename) { switch (build_context.metrics.os) { case TargetOs_linux: case TargetOs_darwin: - case TargetOs_essence: case TargetOs_freebsd: case TargetOs_openbsd: case TargetOs_netbsd: - case TargetOs_haiku: gb_printf_err("-no-crt on Unix systems requires either -default-to-nil-allocator or -default-to-panic-allocator to also be present, because the default allocator requires CRT\n"); no_crt_checks_failed = true; } @@ -2333,11 +2593,9 @@ gb_internal bool init_build_paths(String init_filename) { switch (build_context.metrics.os) { case TargetOs_linux: case TargetOs_darwin: - case TargetOs_essence: case TargetOs_freebsd: case TargetOs_openbsd: case TargetOs_netbsd: - case TargetOs_haiku: gb_printf_err("-no-crt on Unix systems requires the -no-thread-local flag to also be present, because the TLS is inaccessible without CRT\n"); no_crt_checks_failed = true; } @@ -2349,4 +2607,3 @@ gb_internal bool init_build_paths(String init_filename) { return true; } - diff --git a/src/build_settings_microarch.cpp b/src/build_settings_microarch.cpp index 16fb2196f..d3010522d 100644 --- a/src/build_settings_microarch.cpp +++ b/src/build_settings_microarch.cpp @@ -2,7 +2,1169 @@ #error "LLVM_VERSION_MAJOR is not defined!" #endif -#if LLVM_VERSION_MAJOR >= 20 + +#if LLVM_VERSION_MAJOR >= 22 +// Generated with the featuregen script in `misc/featuregen` +gb_global String target_microarch_list[TargetArch_COUNT] = { + // TargetArch_Invalid: + str_lit(""), + // TargetArch_amd64: + str_lit("alderlake,amdfam10,arrowlake,arrowlake-s,arrowlake_s,athlon,athlon-4,athlon-fx,athlon-mp,athlon-tbird,athlon-xp,athlon64,athlon64-sse3,atom,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,bonnell,broadwell,btver1,btver2,c3,c3-2,cannonlake,cascadelake,clearwaterforest,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,diamondrapids,emeraldrapids,generic,geode,goldmont,goldmont-plus,goldmont_plus,gracemont,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,i386,i486,i586,i686,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k6,k6-2,k6-3,k8,k8-sse3,knl,knm,lakemont,lunarlake,meteorlake,mic_avx512,nehalem,nocona,novalake,opteron,opteron-sse3,pantherlake,penryn,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,wildcatlake,winchip-c6,winchip2,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,yonah,znver1,znver2,znver3,znver4,znver5"), + // TargetArch_i386: + str_lit("alderlake,amdfam10,arrowlake,arrowlake-s,arrowlake_s,athlon,athlon-4,athlon-fx,athlon-mp,athlon-tbird,athlon-xp,athlon64,athlon64-sse3,atom,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,bonnell,broadwell,btver1,btver2,c3,c3-2,cannonlake,cascadelake,clearwaterforest,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,diamondrapids,emeraldrapids,generic,geode,goldmont,goldmont-plus,goldmont_plus,gracemont,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,i386,i486,i586,i686,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k6,k6-2,k6-3,k8,k8-sse3,knl,knm,lakemont,lunarlake,meteorlake,mic_avx512,nehalem,nocona,novalake,opteron,opteron-sse3,pantherlake,penryn,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,wildcatlake,winchip-c6,winchip2,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,yonah,znver1,znver2,znver3,znver4,znver5"), + // TargetArch_arm32: + str_lit("arm1020e,arm1020t,arm1022e,arm10e,arm10tdmi,arm1136j-s,arm1136jf-s,arm1156t2-s,arm1156t2f-s,arm1176jz-s,arm1176jzf-s,arm710t,arm720t,arm7tdmi,arm7tdmi-s,arm8,arm810,arm9,arm920,arm920t,arm922t,arm926ej-s,arm940t,arm946e-s,arm966e-s,arm968e-s,arm9e,arm9tdmi,cortex-a12,cortex-a15,cortex-a17,cortex-a32,cortex-a35,cortex-a5,cortex-a510,cortex-a53,cortex-a55,cortex-a57,cortex-a7,cortex-a710,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78ae,cortex-a78c,cortex-a8,cortex-a9,cortex-m0,cortex-m0plus,cortex-m1,cortex-m23,cortex-m3,cortex-m33,cortex-m35p,cortex-m4,cortex-m52,cortex-m55,cortex-m7,cortex-m85,cortex-r4,cortex-r4f,cortex-r5,cortex-r52,cortex-r52plus,cortex-r7,cortex-r8,cortex-x1,cortex-x1c,cyclone,ep9312,exynos-m3,exynos-m4,exynos-m5,generic,iwmmxt,krait,kryo,mpcore,mpcorenovfp,neoverse-n1,neoverse-n2,neoverse-v1,sc000,sc300,star-mc1,star-mc3,strongarm,strongarm110,strongarm1100,strongarm1110,swift,xscale"), + // TargetArch_arm64: + str_lit("a64fx,ampere1,ampere1a,ampere1b,ampere1c,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a17,apple-a18,apple-a19,apple-a7,apple-a8,apple-a9,apple-m1,apple-m2,apple-m3,apple-m4,apple-m5,apple-s10,apple-s4,apple-s5,apple-s6,apple-s7,apple-s8,apple-s9,c1-nano,c1-premium,c1-pro,c1-ultra,carmel,cobalt-100,cortex-a320,cortex-a34,cortex-a35,cortex-a510,cortex-a520,cortex-a520ae,cortex-a53,cortex-a55,cortex-a57,cortex-a65,cortex-a65ae,cortex-a710,cortex-a715,cortex-a72,cortex-a720,cortex-a720ae,cortex-a725,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78ae,cortex-a78c,cortex-r82,cortex-r82ae,cortex-x1,cortex-x1c,cortex-x2,cortex-x3,cortex-x4,cortex-x925,cyclone,exynos-m3,exynos-m4,exynos-m5,falkor,fujitsu-monaka,gb10,generic,grace,kryo,neoverse-512tvb,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-n3,neoverse-v1,neoverse-v2,neoverse-v3,neoverse-v3ae,olympus,oryon-1,saphira,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tsv110"), + // TargetArch_wasm32: + str_lit("bleeding-edge,generic,lime1,mvp"), + // TargetArch_wasm64p32: + str_lit("bleeding-edge,generic,lime1,mvp"), + // TargetArch_riscv64: + str_lit("andes-45-series,andes-a25,andes-a45,andes-ax25,andes-ax45,andes-ax45mpv,andes-n45,andes-nx45,generic,generic-ooo,generic-rv32,generic-rv64,mips-p8700,rocket,rocket-rv32,rocket-rv64,rp2350-hazard3,sifive-7-series,sifive-e20,sifive-e21,sifive-e24,sifive-e31,sifive-e34,sifive-e76,sifive-p450,sifive-p470,sifive-p550,sifive-p670,sifive-p870,sifive-s21,sifive-s51,sifive-s54,sifive-s76,sifive-u54,sifive-u74,sifive-x280,sifive-x390,spacemit-x60,syntacore-scr1-base,syntacore-scr1-max,syntacore-scr3-rv32,syntacore-scr3-rv64,syntacore-scr4-rv32,syntacore-scr4-rv64,syntacore-scr5-rv32,syntacore-scr5-rv64,syntacore-scr7,tt-ascalon-d8,veyron-v1,xiangshan-kunminghu,xiangshan-nanhu"), +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global String target_features_list[TargetArch_COUNT] = { + // TargetArch_Invalid: + str_lit(""), + // TargetArch_amd64: + str_lit("16bit-mode,32bit-mode,64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,avx,avx10.1,avx10.1-512,avx10.2,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,branchfusion,ccmp,cf,cldemote,clflushopt,clwb,clzero,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-lzcnt-tzcnt,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-popcnt,false-deps-range,fast-11bytenop,fast-15bytenop,fast-7bytenop,fast-bextr,fast-dpwssd,fast-gather,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fast-vector-shift-masks,faster-shift-than-shuffle,fma,fma4,fsgsbase,fsrm,fxsr,gfni,harden-sls-ijmp,harden-sls-ret,hreset,idivl-to-divb,idivq-to-divl,inline-asm-use-gpr32,invpcid,kl,lea-sp,lea-uses-ag,lvi-cfi,lvi-load-hardening,lwp,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,mwaitx,ndd,nf,no-bypass-delay,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pad-short-functions,pclmul,pconfig,pku,popcnt,ppx,prefer-128-bit,prefer-256-bit,prefer-legacy-setcc,prefer-mask-registers,prefer-movmsk-over-vtest,prefer-no-gather,prefer-no-scatter,prefetchi,prfchw,ptwrite,push2pop2,raoint,rdpid,rdpru,rdrnd,rdseed,retpoline,retpoline-external-thunk,retpoline-indirect-branches,retpoline-indirect-calls,rtm,sahf,sbb-dep-breaking,serialize,seses,sgx,sha,sha512,shstk,slow-3ops-lea,slow-incdec,slow-lea,slow-pmaddwd,slow-pmulld,slow-pmullq,slow-shld,slow-two-mem-ops,slow-unaligned-mem-16,slow-unaligned-mem-32,sm3,sm4,soft-float,sse,sse-unaligned-mem,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tagged-globals,tbm,tsxldtrk,tuning-fast-imm-vector-shift,uintr,use-glm-div-sqrt-costs,use-slm-arith-costs,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,widekl,x32,x87,xop,xsave,xsavec,xsaveopt,xsaves,zu"), + // TargetArch_i386: + str_lit("16bit-mode,32bit-mode,64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,avx,avx10.1,avx10.1-512,avx10.2,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,branchfusion,ccmp,cf,cldemote,clflushopt,clwb,clzero,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-lzcnt-tzcnt,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-popcnt,false-deps-range,fast-11bytenop,fast-15bytenop,fast-7bytenop,fast-bextr,fast-dpwssd,fast-gather,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fast-vector-shift-masks,faster-shift-than-shuffle,fma,fma4,fsgsbase,fsrm,fxsr,gfni,harden-sls-ijmp,harden-sls-ret,hreset,idivl-to-divb,idivq-to-divl,inline-asm-use-gpr32,invpcid,kl,lea-sp,lea-uses-ag,lvi-cfi,lvi-load-hardening,lwp,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,mwaitx,ndd,nf,no-bypass-delay,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pad-short-functions,pclmul,pconfig,pku,popcnt,ppx,prefer-128-bit,prefer-256-bit,prefer-legacy-setcc,prefer-mask-registers,prefer-movmsk-over-vtest,prefer-no-gather,prefer-no-scatter,prefetchi,prfchw,ptwrite,push2pop2,raoint,rdpid,rdpru,rdrnd,rdseed,retpoline,retpoline-external-thunk,retpoline-indirect-branches,retpoline-indirect-calls,rtm,sahf,sbb-dep-breaking,serialize,seses,sgx,sha,sha512,shstk,slow-3ops-lea,slow-incdec,slow-lea,slow-pmaddwd,slow-pmulld,slow-pmullq,slow-shld,slow-two-mem-ops,slow-unaligned-mem-16,slow-unaligned-mem-32,sm3,sm4,soft-float,sse,sse-unaligned-mem,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tagged-globals,tbm,tsxldtrk,tuning-fast-imm-vector-shift,uintr,use-glm-div-sqrt-costs,use-slm-arith-costs,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,widekl,x32,x87,xop,xsave,xsavec,xsaveopt,xsaves,zu"), + // TargetArch_arm32: + str_lit("32bit,8msecext,a12,a15,a17,a32,a35,a5,a53,a55,a57,a7,a72,a73,a75,a76,a77,a78c,a8,a9,aapcs-frame-chain,aclass,acquire-release,aes,armv4,armv4t,armv5t,armv5te,armv5tej,armv6,armv6-m,armv6j,armv6k,armv6kz,armv6s-m,armv6t2,armv7-a,armv7-m,armv7-r,armv7e-m,armv7k,armv7s,armv7ve,armv8-a,armv8-m.base,armv8-m.main,armv8-r,armv8.1-a,armv8.1-m.main,armv8.2-a,armv8.3-a,armv8.4-a,armv8.5-a,armv8.6-a,armv8.7-a,armv8.8-a,armv8.9-a,armv9-a,armv9.1-a,armv9.2-a,armv9.3-a,armv9.4-a,armv9.5-a,armv9.6-a,armv9.7-a,atomics-32,avoid-movs-shop,avoid-muls,avoid-partial-cpsr,bf16,big-endian-instructions,branch-align-64,cde,cdecp0,cdecp1,cdecp2,cdecp3,cdecp4,cdecp5,cdecp6,cdecp7,cheap-predicable-cpsr,clrbhb,cortex-a510,cortex-a710,cortex-a78,cortex-a78ae,cortex-x1,cortex-x1c,crc,crypto,d32,db,dfb,disable-postra-scheduler,dont-widen-vmovs,dotprod,dsp,execute-only,expand-fp-mlx,exynos,fix-cmse-cve-2021-35465,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpao,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,harden-sls-blr,harden-sls-nocomdat,harden-sls-retbr,hwdiv,hwdiv-arm,i8mm,iwmmxt,iwmmxt2,krait,kryo,lob,long-calls,loop-align,m3,m55,m7,m85,mclass,mp,muxed-units,mve,mve.fp,mve1beat,mve2beat,mve4beat,neon,neon-fpmovs,neonfp,neoverse-v1,no-branch-predictor,no-bti-at-return-twice,no-movt,no-neg-immediates,noarm,nonpipelined-vfp,pacbti,perfmon,prefer-ishst,prefer-vmovsr,prof-unpr,r4,r5,r52,r52plus,r7,ras,rclass,read-tp-tpidrprw,read-tp-tpidruro,read-tp-tpidrurw,reserve-r9,ret-addr-stack,sb,sha2,slow-fp-brcc,slow-load-D-subreg,slow-odd-reg,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,soft-float,splat-vfp-neon,strict-align,swift,thumb-mode,thumb2,trustzone,use-mipipeliner,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.1m.main,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8.9a,v8m,v8m.main,v9.1a,v9.2a,v9.3a,v9.4a,v9.5a,v9.6a,v9.7a,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vldn-align,vmlx-forwarding,vmlx-hazards,wide-stride-vfp,xscale,zcz"), + // TargetArch_arm64: + str_lit("CONTEXTIDREL2,a320,a35,a510,a520,a520ae,a53,a55,a57,a64fx,a65,a710,a715,a72,a720,a720ae,a73,a75,a76,a77,a78,a78ae,a78c,addr-lsl-slow-14,aes,aggressive-fma,aggressive-interleaving,all,alternate-sextload-cvt-f32-pattern,altnzcv,alu-lsl-fast,am,ampere1,ampere1a,ampere1b,ampere1c,amvs,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a17,apple-a7,apple-m4,apple-m5,arith-bcc-fusion,arith-cbz-fusion,ascend-store-address,avoid-ldapur,balance-fp-ops,bf16,brbe,bti,btie,c1-nano,c1-premium,c1-pro,c1-ultra,call-saved-x10,call-saved-x11,call-saved-x12,call-saved-x13,call-saved-x14,call-saved-x15,call-saved-x18,call-saved-x8,call-saved-x9,carmel,ccdp,ccidx,ccpp,chk,clrbhb,cmh,cmp-bcc-fusion,cmpbr,complxnum,cortex-a725,cortex-r82,cortex-r82ae,cortex-x1,cortex-x2,cortex-x3,cortex-x4,cortex-x925,cpa,crc,crypto,cssc,d128,disable-fast-inc-vl,disable-latency-sched-heuristic,disable-ldp,disable-maximize-scalable-bandwidth,disable-stp,disable-unpredicated-ld-st-lower,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,execute-only,exynos-cheap-as-move,exynosm3,exynosm4,f16f32dot,f16f32mm,f16mm,f32mm,f64mm,f8f16mm,f8f32mm,falkor,faminmax,fgt,fix-cortex-a53-835769,flagm,fmv,force-32bit-jump-tables,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fprcvt,fptoint,fujitsu-monaka,fullfp16,fuse-address,fuse-addsub-2reg-const1,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-cset,fuse-literals,gcie,gcs,harden-sls-blr,harden-sls-nocomdat,harden-sls-retbr,hbc,hcx,i8mm,ite,jsconv,kryo,ldp-aligned-only,lor,ls64,lscp,lse,lse128,lse2,lsfe,lsui,lut,max-interleave-factor-4,mec,mops,mops-go,mpam,mpamv2,mte,mtetc,neon,neoverse512tvb,neoversee1,neoversen1,neoversen2,neoversen3,neoversev1,neoversev2,neoversev3,neoversev3AE,nmi,no-bti-at-return-twice,no-neg-immediates,no-sve-fp-ld1r,no-zcz-fpr64,nv,occmo,olympus,oryon-1,outline-atomics,pan,pan-rwv,pauth,pauth-lr,pcdphint,perfmon,poe2,pops,predictable-select-expensive,predres,prfm-slc-target,rand,ras,rasv2,rcpc,rcpc-immo,rcpc3,rdm,reserve-lr-for-ra,reserve-x1,reserve-x10,reserve-x11,reserve-x12,reserve-x13,reserve-x14,reserve-x15,reserve-x18,reserve-x2,reserve-x20,reserve-x21,reserve-x22,reserve-x23,reserve-x24,reserve-x25,reserve-x26,reserve-x27,reserve-x28,reserve-x3,reserve-x4,reserve-x5,reserve-x6,reserve-x7,reserve-x9,rme,saphira,sb,sel2,sha2,sha3,slow-misaligned-128store,slow-paired-128,slow-strqro-store,sm4,sme,sme-b16b16,sme-f16f16,sme-f64f64,sme-f8f16,sme-f8f32,sme-fa64,sme-i16i64,sme-lutv2,sme-mop4,sme-tmop,sme2,sme2p1,sme2p2,sme2p3,spe,spe-eef,specres2,specrestrict,ssbs,ssve-aes,ssve-bitperm,ssve-fexpa,ssve-fp8dot2,ssve-fp8dot4,ssve-fp8fma,store-pair-suppress,stp-aligned-only,strict-align,sve,sve-aes,sve-aes2,sve-b16b16,sve-b16mm,sve-bfscale,sve-bitperm,sve-f16f32mm,sve-sha3,sve-sm4,sve2,sve2-aes,sve2-bitperm,sve2-sha3,sve2-sm4,sve2p1,sve2p2,sve2p3,tagged-globals,tev,the,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tlb-rmi,tlbid,tlbiw,tpidr-el1,tpidr-el2,tpidr-el3,tpidrro-el0,tracev8.4,trbe,tsv110,uaops,use-experimental-zeroing-pseudos,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-reciprocal-square-root,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8.9a,v8a,v8r,v9.1a,v9.2a,v9.3a,v9.4a,v9.5a,v9.6a,v9.7a,v9a,vh,wfxt,xs,zcm-fpr128,zcm-fpr32,zcm-fpr64,zcm-gpr32,zcm-gpr64,zcz-fp-workaround,zcz-fpr128,zcz-gpr32,zcz-gpr64"), + // TargetArch_wasm32: + str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,gc,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call,wide-arithmetic"), + // TargetArch_wasm64p32: + str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,gc,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call,wide-arithmetic"), + // TargetArch_riscv64: + str_lit("32bit,64bit,a,add-load-fusion,addi-load-fusion,andes45,auipc-addi-fusion,auipc-load-fusion,b,bfext-fusion,c,conditional-cmv-fusion,d,disable-latency-sched-heuristic,disable-misched-load-clustering,disable-misched-store-clustering,disable-postmisched-load-clustering,disable-postmisched-store-clustering,dlen-factor-2,e,enable-vsetvli-sched-heuristic,exact-asm,experimental,experimental-p,experimental-rvm23u32,experimental-smpmpmt,experimental-svukte,experimental-xrivosvisni,experimental-xrivosvizip,experimental-xsfmclic,experimental-xsfsclic,experimental-zibi,experimental-zicfilp,experimental-zicfiss,experimental-zvbc32e,experimental-zvfbfa,experimental-zvfofp8min,experimental-zvkgs,experimental-zvqdotq,f,forced-atomics,h,i,ld-add-fusion,log-vrgather,lui-addi-fusion,lui-load-fusion,m,mips-p8700,no-default-unroll,no-sink-splat-operands,no-trailing-seq-cst-fence,optimized-nf2-segment-load-store,optimized-nf3-segment-load-store,optimized-nf4-segment-load-store,optimized-nf5-segment-load-store,optimized-nf6-segment-load-store,optimized-nf7-segment-load-store,optimized-nf8-segment-load-store,optimized-zero-stride-load,permissive-zalrsc,predictable-select-expensive,prefer-vsetvli-over-read-vlenb,prefer-w-inst,q,relax,reserve-x1,reserve-x10,reserve-x11,reserve-x12,reserve-x13,reserve-x14,reserve-x15,reserve-x16,reserve-x17,reserve-x18,reserve-x19,reserve-x2,reserve-x20,reserve-x21,reserve-x22,reserve-x23,reserve-x24,reserve-x25,reserve-x26,reserve-x27,reserve-x28,reserve-x29,reserve-x3,reserve-x30,reserve-x31,reserve-x4,reserve-x5,reserve-x6,reserve-x7,reserve-x8,reserve-x9,rva20s64,rva20u64,rva22s64,rva22u64,rva23s64,rva23u64,rvb23s64,rvb23u64,rvi20u32,rvi20u64,save-restore,sdext,sdtrig,sha,shcounterenw,shgatpa,shifted-zextw-fusion,shlcofideleg,short-forward-branch-ialu,short-forward-branch-iload,short-forward-branch-iminmax,short-forward-branch-imul,shtvala,shvsatpa,shvstvala,shvstvecd,shxadd-load-fusion,sifive7,single-element-vec-fp64,smaia,smcdeleg,smcntrpmf,smcsrind,smctr,smdbltrp,smepmp,smmpm,smnpm,smrnmi,smstateen,ssaia,ssccfg,ssccptr,sscofpmf,sscounterenw,sscsrind,ssctr,ssdbltrp,ssnpm,sspm,ssqosid,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svadu,svbare,svinval,svnapot,svpbmt,svvptc,tagged-globals,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,ventana-veyron,vl-dependent-latency,vxrm-pipeline-flush,xandesbfhcvt,xandesperf,xandesvbfhcvt,xandesvdot,xandesvpackfph,xandesvsinth,xandesvsintload,xcvalu,xcvbi,xcvbitmanip,xcvelw,xcvmac,xcvmem,xcvsimd,xmipscbop,xmipscmov,xmipsexectl,xmipslsp,xqccmp,xqci,xqcia,xqciac,xqcibi,xqcibm,xqcicli,xqcicm,xqcics,xqcicsr,xqciint,xqciio,xqcilb,xqcili,xqcilia,xqcilo,xqcilsm,xqcisim,xqcisls,xqcisync,xsfcease,xsfmm128t,xsfmm16t,xsfmm32a16f,xsfmm32a32f,xsfmm32a8f,xsfmm32a8i,xsfmm32t,xsfmm64a64f,xsfmm64t,xsfmmbase,xsfvcp,xsfvfbfexp16e,xsfvfexp16e,xsfvfexp32e,xsfvfexpa,xsfvfexpa64e,xsfvfnrclipxfqf,xsfvfwmaccqqq,xsfvqmaccdod,xsfvqmaccqoq,xsifivecdiscarddlone,xsifivecflushdlone,xsmtvdot,xtheadba,xtheadbb,xtheadbs,xtheadcmo,xtheadcondmov,xtheadfmemidx,xtheadmac,xtheadmemidx,xtheadmempair,xtheadsync,xtheadvdot,xventanacondops,xwchc,za128rs,za64rs,zaamo,zabha,zacas,zalasr,zalrsc,zama16b,zawrs,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zcb,zcd,zce,zcf,zclsd,zcmop,zcmp,zcmt,zdinx,zexth-fusion,zextw-fusion,zfa,zfbfmin,zfh,zfhmin,zfinx,zhinx,zhinxmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccamoc,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zilsd,zilsd-4byte-align,zimop,zk,zkn,zknd,zkne,zknh,zkr,zks,zksed,zksh,zkt,zmmul,ztso,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknha,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl1024b,zvl128b,zvl16384b,zvl2048b,zvl256b,zvl32768b,zvl32b,zvl4096b,zvl512b,zvl64b,zvl65536b,zvl8192b"), +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global int target_microarch_counts[TargetArch_COUNT] = { + // TargetArch_Invalid: + 0, + // TargetArch_amd64: + 131, + // TargetArch_i386: + 131, + // TargetArch_arm32: + 96, + // TargetArch_arm64: + 98, + // TargetArch_wasm32: + 4, + // TargetArch_wasm64p32: + 4, + // TargetArch_riscv64: + 51, +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global MicroarchFeatureList microarch_features_list[] = { + // TargetArch_amd64: + { str_lit("alderlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("amdfam10"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("arrowlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake-s"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake_s"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("athlon"), str_lit("64bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-fx"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-mp"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-tbird"), str_lit("64bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-xp"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("atom"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("atom_sse4_2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("atom_sse4_2_movbe"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fsgsbase,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("barcelona"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("bdver1"), str_lit("64bit,64bit-mode,aes,avx,branchfusion,cmov,crc32,cx16,cx8,fast-11bytenop,fast-scalar-shift-masks,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver2"), str_lit("64bit,64bit-mode,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver3"), str_lit("64bit,64bit-mode,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bdver4"), str_lit("64bit,64bit-mode,aes,avx,avx2,bmi,bmi2,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bonnell"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("broadwell"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("btver1"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-15bytenop,fast-imm16,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,ssse3,vzeroupper,x87") }, + { str_lit("btver2"), str_lit("64bit,64bit-mode,aes,avx,bmi,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,x87,xsave,xsaveopt") }, + { str_lit("c3"), str_lit("64bit-mode,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("c3-2"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("cannonlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vl,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,sha,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cascadelake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("clearwaterforest"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cooperlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("core-avx-i"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core-avx2"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core2"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_sse4_1"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_ssse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2nd_gen_avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_3rd_gen_avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx_tsx"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx_tsx"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_aes_pclmulqdq"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("core_i7_sse4_2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7-avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("diamondrapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,avx,avx10.1,avx10.2,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,ccmp,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-256-bit,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("emeraldrapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("generic"), str_lit("64bit,64bit-mode,cx8,fast-15bytenop,fast-scalar-fsqrt,idivq-to-divl,macrofusion,slow-3ops-lea,sse,sse2,vzeroupper,x87") }, + { str_lit("geode"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("goldmont"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont-plus"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont_plus"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("gracemont"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("grandridge"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids-d"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids_d"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("haswell"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("i386"), str_lit("64bit-mode,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i486"), str_lit("64bit-mode,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i586"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i686"), str_lit("64bit-mode,cmov,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("icelake-client"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake-server"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_client"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_server"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("ivybridge"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("k6"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k6-2"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k6-3"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("knl"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("knm"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,avx512vpopcntdq,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("lakemont"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper") }, + { str_lit("lunarlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("meteorlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("mic_avx512"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("nehalem"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("nocona"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("novalake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx10.1,avx10.2,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,ccmp,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("opteron"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("opteron-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pantherlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("penryn"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("pentium"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-mmx"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium2"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium3"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium3m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4_sse3"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pentium_ii"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_iii"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_iii_no_xmm_regs"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_mmx"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_pro"), str_lit("64bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentiumpro"), str_lit("64bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("prescott"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("raptorlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("rocketlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sandybridge"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("sapphirerapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sierraforest"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("silvermont"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("skx"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake-avx512"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake_avx512"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("slm"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("tigerlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("tremont"), str_lit("64bit,64bit-mode,aes,clflushopt,clwb,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,gfni,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("westmere"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("wildcatlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("winchip-c6"), str_lit("64bit-mode,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("winchip2"), str_lit("64bit-mode,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64"), str_lit("64bit,64bit-mode,cmov,cx8,fxsr,idivq-to-divl,macrofusion,mmx,nopl,slow-3ops-lea,slow-incdec,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64-v2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,nopl,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("x86-64-v3"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("x86-64-v4"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,prefer-256-bit,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("yonah"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("znver1"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver2"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver3"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver4"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver5"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxvnni,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,mwaitx,nopl,pclmul,pku,popcnt,prefetchi,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + // TargetArch_i386: + { str_lit("alderlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("amdfam10"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("arrowlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake-s"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake_s"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("athlon"), str_lit("32bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("athlon-4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon-fx"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-mp"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon-tbird"), str_lit("32bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("athlon-xp"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon64"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("atom"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("atom_sse4_2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("atom_sse4_2_movbe"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fsgsbase,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("barcelona"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("bdver1"), str_lit("32bit-mode,64bit,aes,avx,branchfusion,cmov,crc32,cx16,cx8,fast-11bytenop,fast-scalar-shift-masks,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver2"), str_lit("32bit-mode,64bit,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver3"), str_lit("32bit-mode,64bit,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bdver4"), str_lit("32bit-mode,64bit,aes,avx,avx2,bmi,bmi2,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bonnell"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("broadwell"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("btver1"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-15bytenop,fast-imm16,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,ssse3,vzeroupper,x87") }, + { str_lit("btver2"), str_lit("32bit-mode,64bit,aes,avx,bmi,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,x87,xsave,xsaveopt") }, + { str_lit("c3"), str_lit("32bit-mode,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("c3-2"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("cannonlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vl,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,sha,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cascadelake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("clearwaterforest"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cooperlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("core-avx-i"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core-avx2"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core2"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_sse4_1"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_ssse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2nd_gen_avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_3rd_gen_avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx_tsx"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx_tsx"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_aes_pclmulqdq"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("core_i7_sse4_2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7-avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("diamondrapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,avx,avx10.1,avx10.2,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,ccmp,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-256-bit,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("emeraldrapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("generic"), str_lit("32bit-mode,64bit,cx8,fast-15bytenop,fast-scalar-fsqrt,idivq-to-divl,macrofusion,slow-3ops-lea,vzeroupper,x87") }, + { str_lit("geode"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("goldmont"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont-plus"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont_plus"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("gracemont"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("grandridge"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids-d"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids_d"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("haswell"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("i386"), str_lit("32bit-mode,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i486"), str_lit("32bit-mode,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i586"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i686"), str_lit("32bit-mode,cmov,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("icelake-client"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake-server"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_client"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_server"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("ivybridge"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("k6"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k6-2"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k6-3"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k8"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("knl"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("knm"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,avx512vpopcntdq,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("lakemont"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper") }, + { str_lit("lunarlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("meteorlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("mic_avx512"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("nehalem"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("nocona"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("novalake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx10.1,avx10.2,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,ccmp,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("opteron"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("opteron-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pantherlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("penryn"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("pentium"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium-m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-mmx"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium2"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium3"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium3m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4_sse3"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pentium_ii"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium_iii"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium_iii_no_xmm_regs"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium_m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_mmx"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium_pro"), str_lit("32bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentiumpro"), str_lit("32bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("prescott"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("raptorlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("rocketlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sandybridge"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("sapphirerapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sierraforest"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("silvermont"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("skx"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake-avx512"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake_avx512"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("slm"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("tigerlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,shstk,slow-pmullq,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("tremont"), str_lit("32bit-mode,64bit,aes,clflushopt,clwb,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,gfni,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("westmere"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("wildcatlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,slow-pmullq,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("winchip-c6"), str_lit("32bit-mode,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("winchip2"), str_lit("32bit-mode,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("x86-64"), str_lit("32bit-mode,64bit,cmov,cx8,fxsr,idivq-to-divl,macrofusion,mmx,nopl,slow-3ops-lea,slow-incdec,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64-v2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,nopl,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("x86-64-v3"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("x86-64-v4"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,prefer-256-bit,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("yonah"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("znver1"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver2"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver3"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver4"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver5"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxvnni,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,mwaitx,nopl,pclmul,pku,popcnt,prefetchi,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + // TargetArch_arm32: + { str_lit("arm1020e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm1020t"), str_lit("armv5t,v4t,v5t") }, + { str_lit("arm1022e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm10e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm10tdmi"), str_lit("armv5t,v4t,v5t") }, + { str_lit("arm1136j-s"), str_lit("armv6,dsp,v4t,v5t,v5te,v6") }, + { str_lit("arm1136jf-s"), str_lit("armv6,dsp,fp64,fpregs,fpregs64,slowfpvmlx,v4t,v5t,v5te,v6,vfp2,vfp2sp") }, + { str_lit("arm1156t2-s"), str_lit("armv6t2,dsp,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v8m") }, + { str_lit("arm1156t2f-s"), str_lit("armv6t2,dsp,fp64,fpregs,fpregs64,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v8m,vfp2,vfp2sp") }, + { str_lit("arm1176jz-s"), str_lit("armv6kz,trustzone,v4t,v5t,v5te,v6,v6k") }, + { str_lit("arm1176jzf-s"), str_lit("armv6kz,fp64,fpregs,fpregs64,slowfpvmlx,trustzone,v4t,v5t,v5te,v6,v6k,vfp2,vfp2sp") }, + { str_lit("arm710t"), str_lit("armv4t,v4t") }, + { str_lit("arm720t"), str_lit("armv4t,v4t") }, + { str_lit("arm7tdmi"), str_lit("armv4t,v4t") }, + { str_lit("arm7tdmi-s"), str_lit("armv4t,v4t") }, + { str_lit("arm8"), str_lit("armv4") }, + { str_lit("arm810"), str_lit("armv4") }, + { str_lit("arm9"), str_lit("armv4t,v4t") }, + { str_lit("arm920"), str_lit("armv4t,v4t") }, + { str_lit("arm920t"), str_lit("armv4t,v4t") }, + { str_lit("arm922t"), str_lit("armv4t,v4t") }, + { str_lit("arm926ej-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm940t"), str_lit("armv4t,v4t") }, + { str_lit("arm946e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm966e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm968e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm9e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm9tdmi"), str_lit("armv4t,v4t") }, + { str_lit("cortex-a12"), str_lit("a12,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding") }, + { str_lit("cortex-a15"), str_lit("a15,aclass,armv7-a,avoid-partial-cpsr,d32,db,dont-widen-vmovs,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,muxed-units,neon,perfmon,ret-addr-stack,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vldn-align") }, + { str_lit("cortex-a17"), str_lit("a17,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding") }, + { str_lit("cortex-a32"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a35"), str_lit("a35,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a5"), str_lit("a5,aclass,armv7-a,d32,db,dsp,fp16,fp64,fpregs,fpregs64,mp,neon,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vmlx-forwarding") }, + { str_lit("cortex-a510"), str_lit("aclass,acquire-release,armv9-a,bf16,cortex-a710,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a53"), str_lit("a53,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a55"), str_lit("a55,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a57"), str_lit("a57,aclass,acquire-release,aes,armv8-a,avoid-partial-cpsr,cheap-predicable-cpsr,crc,crypto,d32,db,dsp,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a7"), str_lit("a7,aclass,armv7-a,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-a710"), str_lit("aclass,acquire-release,armv9-a,bf16,cortex-a710,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a72"), str_lit("a72,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a73"), str_lit("a73,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a75"), str_lit("a75,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a76"), str_lit("a76,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a76ae"), str_lit("a76,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a77"), str_lit("a77,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-a78,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78ae"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-a78ae,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78c"), str_lit("a78c,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a8"), str_lit("a8,aclass,armv7-a,d32,db,dsp,fp64,fpregs,fpregs64,neon,nonpipelined-vfp,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-a9"), str_lit("a9,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,expand-fp-mlx,fp16,fp64,fpregs,fpregs64,mp,muxed-units,neon,neon-fpmovs,perfmon,prefer-vmovsr,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vldn-align,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-m0"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m0plus"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m1"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m23"), str_lit("8msecext,acquire-release,armv8-m.base,db,hwdiv,mclass,no-branch-predictor,no-movt,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m,v7clrex,v8m") }, + { str_lit("cortex-m3"), str_lit("armv7-m,db,hwdiv,loop-align,m3,mclass,no-branch-predictor,noarm,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("cortex-m33"), str_lit("8msecext,acquire-release,armv8-m.main,avoid-muls,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m35p"), str_lit("8msecext,acquire-release,armv8-m.main,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m4"), str_lit("armv7e-m,db,dsp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m52"), str_lit("8msecext,acquire-release,armv8.1-m.main,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,loop-align,mclass,mve,mve.fp,mve1beat,no-branch-predictor,noarm,pacbti,ras,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m55"), str_lit("8msecext,acquire-release,armv8.1-m.main,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,loop-align,m55,mclass,mve,mve.fp,no-branch-predictor,noarm,ras,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m7"), str_lit("armv7e-m,branch-align-64,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs64,hwdiv,m7,mclass,noarm,thumb-mode,thumb2,use-mipipeliner,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m85"), str_lit("8msecext,acquire-release,armv8.1-m.main,branch-align-64,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,m85,mclass,mve,mve.fp,noarm,pacbti,ras,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-r4"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,hwdiv,perfmon,r4,rclass,ret-addr-stack,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("cortex-r4f"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp64,fpregs,fpregs64,hwdiv,perfmon,r4,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r5"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,perfmon,r5,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r52"), str_lit("acquire-release,armv8-r,crc,d32,db,dfb,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,r52,rclass,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-r52plus"), str_lit("acquire-release,armv8-r,crc,d32,db,dfb,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,r52plus,rclass,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-r7"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,r7,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r8"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-x1"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-x1,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-x1c"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-x1c,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cyclone"), str_lit("aclass,acquire-release,aes,armv8-a,avoid-movs-shop,avoid-partial-cpsr,crc,crypto,d32,db,disable-postra-scheduler,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,neonfp,perfmon,ret-addr-stack,sha2,slowfpvfmx,slowfpvmlx,swift,thumb2,trustzone,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,zcz") }, + { str_lit("ep9312"), str_lit("armv4t,v4t") }, + { str_lit("exynos-m3"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dont-widen-vmovs,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("exynos-m4"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dont-widen-vmovs,dotprod,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ras,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("exynos-m5"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dont-widen-vmovs,dotprod,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ras,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("generic"), str_lit("") }, + { str_lit("iwmmxt"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("krait"), str_lit("aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,krait,muxed-units,neon,perfmon,ret-addr-stack,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vldn-align,vmlx-forwarding") }, + { str_lit("kryo"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,kryo,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("mpcore"), str_lit("armv6k,fp64,fpregs,fpregs64,slowfpvmlx,v4t,v5t,v5te,v6,v6k,vfp2,vfp2sp") }, + { str_lit("mpcorenovfp"), str_lit("armv6k,v4t,v5t,v5te,v6,v6k") }, + { str_lit("neoverse-n1"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("neoverse-n2"), str_lit("aclass,acquire-release,armv9-a,bf16,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("neoverse-v1"), str_lit("aclass,acquire-release,aes,armv8.4-a,bf16,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("sc000"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("sc300"), str_lit("armv7-m,db,hwdiv,m3,mclass,no-branch-predictor,noarm,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("star-mc1"), str_lit("8msecext,acquire-release,armv8-m.main,avoid-muls,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("star-mc3"), str_lit("8msecext,acquire-release,armv8.1-m.main,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,loop-align,mclass,mve,mve.fp,mve1beat,no-branch-predictor,noarm,pacbti,ras,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("strongarm"), str_lit("armv4") }, + { str_lit("strongarm110"), str_lit("armv4") }, + { str_lit("strongarm1100"), str_lit("armv4") }, + { str_lit("strongarm1110"), str_lit("armv4") }, + { str_lit("swift"), str_lit("aclass,armv7-a,avoid-movs-shop,avoid-partial-cpsr,d32,db,disable-postra-scheduler,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,neonfp,perfmon,prefer-ishst,prof-unpr,ret-addr-stack,slow-load-D-subreg,slow-odd-reg,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,swift,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vmlx-hazards,wide-stride-vfp") }, + { str_lit("xscale"), str_lit("armv5te,v4t,v5t,v5te") }, + // TargetArch_arm64: + { str_lit("a64fx"), str_lit("CONTEXTIDREL2,a64fx,aes,aggressive-fma,arith-bcc-fusion,ccpp,complxnum,crc,disable-unpredicated-ld-st-lower,el2vmsa,el3,fp-armv8,fullfp16,lor,lse,max-interleave-factor-4,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rdm,sha2,store-pair-suppress,sve,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("ampere1"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,max-interleave-factor-4,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("ampere1a"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1a,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-addsub-2reg-const1,fuse-adrp-add,fuse-aes,fuse-literals,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("ampere1b"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1b,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,cssc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,hcx,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs") }, + { str_lit("ampere1c"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1c,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,cssc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,faminmax,fgt,flagm,fp-armv8,fp16fml,fp8,fp8fma,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,lut,max-interleave-factor-4,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,specrestrict,ssbs,store-pair-suppress,sve,sve-aes,sve-b16b16,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("apple-a10"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a10,arith-bcc-fusion,arith-cbz-fusion,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,lor,neon,no-zcz-fpr64,pan,perfmon,rdm,sha2,store-pair-suppress,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a11"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a11,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,lor,lse,neon,no-zcz-fpr64,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a12"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,no-zcz-fpr64,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a13"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a14"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,alternate-sextload-cvt-f32-pattern,altnzcv,am,apple-a14,arith-bcc-fusion,arith-cbz-fusion,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a15"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a15,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a16"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a17"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a17,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a18"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m4,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-f64f64,sme-i16i64,sme2,specrestrict,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a19"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m5,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,cssc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hbc,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-b16b16,sme-f16f16,sme-f64f64,sme-i16i64,sme2,sme2p1,specres2,specrestrict,sve-b16b16,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a7"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,no-zcz-fpr64,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr128,zcm-gpr64,zcz-fp-workaround,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a8"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,no-zcz-fpr64,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr128,zcm-gpr64,zcz-fp-workaround,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-a9"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,no-zcz-fpr64,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr128,zcm-gpr64,zcz-fp-workaround,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-m1"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,alternate-sextload-cvt-f32-pattern,altnzcv,am,apple-a14,arith-bcc-fusion,arith-cbz-fusion,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-m2"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a15,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-m3"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-m4"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m4,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-f64f64,sme-i16i64,sme2,specrestrict,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-m5"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m5,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,cssc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hbc,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-b16b16,sme-f16f16,sme-f64f64,sme-i16i64,sme2,sme2p1,specres2,specrestrict,sve-b16b16,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s10"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s4"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,no-zcz-fpr64,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s5"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,no-zcz-fpr64,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s6"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s7"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s8"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("apple-s9"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,no-zcz-fpr64,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr128,zcm-gpr64,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("c1-nano"), str_lit("CONTEXTIDREL2,altnzcv,am,amvs,bf16,bti,c1-nano,ccdp,ccidx,ccpp,chk,clrbhb,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hbc,hcx,i8mm,jsconv,lor,lse,lse2,mops,mpam,mte,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rcpc3,rdm,sb,sel2,sme,sme2,specres2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("c1-premium"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,c1-premium,ccdp,ccidx,ccpp,chk,clrbhb,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hbc,hcx,i8mm,jsconv,lor,lse,lse2,mops,mpam,mte,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rcpc3,rdm,sb,sel2,sme,sme2,spe,spe-eef,specres2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("c1-pro"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,c1-pro,ccdp,ccidx,ccpp,chk,clrbhb,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hbc,hcx,i8mm,jsconv,lor,lse,lse2,mops,mpam,mte,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rcpc3,rdm,sb,sel2,sme,sme2,spe,spe-eef,specres2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("c1-ultra"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,c1-ultra,ccdp,ccidx,ccpp,chk,clrbhb,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hbc,hcx,i8mm,jsconv,lor,lse,lse2,mops,mpam,mte,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rcpc3,rdm,sb,sel2,sme,sme2,spe,spe-eef,specres2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("carmel"), str_lit("CONTEXTIDREL2,aes,carmel,ccpp,crc,el2vmsa,el3,fp-armv8,fullfp16,lor,lse,neon,pan,pan-rwv,ras,rdm,sha2,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cobalt-100"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,disable-maximize-scalable-bandwidth,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a320"), str_lit("CONTEXTIDREL2,a320,aggressive-interleaving,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a34"), str_lit("a35,aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,sha2,v8a") }, + { str_lit("cortex-a35"), str_lit("a35,aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,sha2,v8a") }, + { str_lit("cortex-a510"), str_lit("CONTEXTIDREL2,a510,altnzcv,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a520"), str_lit("CONTEXTIDREL2,a520,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a520ae"), str_lit("CONTEXTIDREL2,a520ae,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a53"), str_lit("a53,aes,balance-fp-ops,crc,el2vmsa,el3,fp-armv8,fuse-adrp-add,fuse-aes,neon,perfmon,sha2,use-postra-scheduler,use-wzr-to-vec-move,v8a") }, + { str_lit("cortex-a55"), str_lit("CONTEXTIDREL2,a55,aes,ccpp,crc,dotprod,el2vmsa,el3,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,ras,rcpc,rdm,sha2,uaops,use-postra-scheduler,use-wzr-to-vec-move,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a57"), str_lit("a57,addr-lsl-slow-14,aes,balance-fp-ops,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,fuse-literals,max-interleave-factor-4,neon,perfmon,predictable-select-expensive,sha2,use-postra-scheduler,v8a") }, + { str_lit("cortex-a65"), str_lit("CONTEXTIDREL2,a65,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a65ae"), str_lit("CONTEXTIDREL2,a65,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a710"), str_lit("CONTEXTIDREL2,a710,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a715"), str_lit("CONTEXTIDREL2,a715,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a72"), str_lit("a72,addr-lsl-slow-14,aes,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,fuse-literals,neon,perfmon,predictable-select-expensive,sha2,v8a") }, + { str_lit("cortex-a720"), str_lit("CONTEXTIDREL2,a720,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a720ae"), str_lit("CONTEXTIDREL2,a720ae,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a725"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,cortex-a725,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a73"), str_lit("a73,addr-lsl-slow-14,aes,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,neon,perfmon,predictable-select-expensive,sha2,v8a") }, + { str_lit("cortex-a75"), str_lit("CONTEXTIDREL2,a75,addr-lsl-slow-14,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a76"), str_lit("CONTEXTIDREL2,a76,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a76ae"), str_lit("CONTEXTIDREL2,a76,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a77"), str_lit("CONTEXTIDREL2,a77,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78"), str_lit("CONTEXTIDREL2,a78,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78ae"), str_lit("CONTEXTIDREL2,a78ae,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78c"), str_lit("CONTEXTIDREL2,a78c,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,lor,lse,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-r82"), str_lit("CONTEXTIDREL2,ccdp,ccpp,complxnum,cortex-r82,crc,dit,dotprod,flagm,fp-armv8,fp16fml,fpac,fullfp16,jsconv,lse,neon,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8r") }, + { str_lit("cortex-r82ae"), str_lit("CONTEXTIDREL2,ccdp,ccpp,complxnum,cortex-r82ae,crc,dit,dotprod,flagm,fp-armv8,fp16fml,fpac,fullfp16,jsconv,lse,neon,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8r") }, + { str_lit("cortex-x1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,cortex-x1,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-x1c"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,cortex-x1,crc,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,lse2,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rcpc-immo,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-x2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,cortex-x2,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-x3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x3,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-x4"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x4,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-x925"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x925,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cyclone"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,no-zcz-fpr64,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr128,zcm-gpr64,zcz-fp-workaround,zcz-fpr128,zcz-gpr32,zcz-gpr64") }, + { str_lit("exynos-m3"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,exynos-cheap-as-move,exynosm3,force-32bit-jump-tables,fp-armv8,fuse-address,fuse-adrp-add,fuse-aes,fuse-csel,fuse-literals,max-interleave-factor-4,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,use-postra-scheduler,v8a") }, + { str_lit("exynos-m4"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,dotprod,el2vmsa,el3,exynos-cheap-as-move,exynosm4,force-32bit-jump-tables,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-csel,fuse-literals,lor,lse,max-interleave-factor-4,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh,zcz-gpr32,zcz-gpr64") }, + { str_lit("exynos-m5"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,dotprod,el2vmsa,el3,exynos-cheap-as-move,exynosm4,force-32bit-jump-tables,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-csel,fuse-literals,lor,lse,max-interleave-factor-4,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh,zcz-gpr32,zcz-gpr64") }, + { str_lit("falkor"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,falkor,fp-armv8,max-interleave-factor-4,neon,perfmon,predictable-select-expensive,rdm,sha2,slow-strqro-store,store-pair-suppress,use-postra-scheduler,v8a,zcz-gpr32,zcz-gpr64") }, + { str_lit("fujitsu-monaka"), str_lit("CONTEXTIDREL2,aes,altnzcv,am,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,clrbhb,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,faminmax,fgt,flagm,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fptoint,fujitsu-monaka,fullfp16,hbc,hcx,i8mm,jsconv,lor,ls64,lse,lse2,lut,mec,mops,mpam,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,sha2,sha3,sm4,specres2,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("gb10"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x925,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,spe-eef,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("generic"), str_lit("enable-select-opt,ete,fp-armv8,fuse-adrp-add,fuse-aes,neon,trbe,use-postra-scheduler") }, + { str_lit("grace"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,neoversev2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("kryo"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,fp-armv8,kryo,max-interleave-factor-4,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,use-postra-scheduler,v8a,zcz-gpr32,zcz-gpr64") }, + { str_lit("neoverse-512tvb"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,am,bf16,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fp16fml,fpac,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,neoverse512tvb,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,rand,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,sm4,spe,ssbs,sve,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh") }, + { str_lit("neoverse-e1"), str_lit("CONTEXTIDREL2,aes,ccpp,crc,dotprod,el2vmsa,el3,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,neoversee1,pan,pan-rwv,perfmon,ras,rcpc,rdm,sha2,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("neoverse-n1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,neoversen1,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("neoverse-n2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,disable-maximize-scalable-bandwidth,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("neoverse-n3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen3,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("neoverse-v1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,am,bf16,ccdp,ccidx,ccpp,complxnum,crc,disable-maximize-scalable-bandwidth,dit,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fp16fml,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,mpam,neon,neoversev1,no-sve-fp-ld1r,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,rand,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,sm4,spe,ssbs,sve,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh") }, + { str_lit("neoverse-v2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,mte,neon,neoversev2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("neoverse-v3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,brbe,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,ls64,lse,lse2,max-interleave-factor-4,mpam,mte,neon,neoversev3,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("neoverse-v3ae"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,brbe,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,fuse-csel,fuse-cset,hcx,i8mm,jsconv,lor,ls64,lse,lse2,max-interleave-factor-4,mpam,mte,neon,neoversev3AE,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("olympus"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,amvs,bf16,brbe,bti,ccdp,ccidx,ccpp,chk,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,faminmax,fgt,flagm,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,ls64,lse,lse2,lut,max-interleave-factor-4,mec,mpam,mte,neon,nv,olympus,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,sha2,sha3,sm4,spe,spe-eef,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("oryon-1"), str_lit("CONTEXTIDREL2,aes,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,fgt,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-crypto-eor,i8mm,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,nv,oryon-1,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("saphira"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,am,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,jsconv,lor,lse,lse2,max-interleave-factor-4,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rcpc-immo,rdm,saphira,sel2,sha2,spe,store-pair-suppress,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcz-gpr32,zcz-gpr64") }, + { str_lit("thunderx"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderx,use-postra-scheduler,v8a") }, + { str_lit("thunderx2t99"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,arith-bcc-fusion,crc,el2vmsa,el3,fp-armv8,lor,lse,max-interleave-factor-4,neon,pan,predictable-select-expensive,rdm,sha2,store-pair-suppress,thunderx2t99,use-postra-scheduler,v8.1a,v8a,vh") }, + { str_lit("thunderx3t110"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,arith-bcc-fusion,balance-fp-ops,ccidx,ccpp,complxnum,crc,el2vmsa,el3,fp-armv8,jsconv,lor,lse,max-interleave-factor-4,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,store-pair-suppress,strict-align,thunderx3t110,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8a,vh") }, + { str_lit("thunderxt81"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt81,use-postra-scheduler,v8a") }, + { str_lit("thunderxt83"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt83,use-postra-scheduler,v8a") }, + { str_lit("thunderxt88"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt88,use-postra-scheduler,v8a") }, + { str_lit("tsv110"), str_lit("CONTEXTIDREL2,aes,ccpp,complxnum,crc,dotprod,el2vmsa,el3,fp-armv8,fp16fml,fullfp16,fuse-aes,jsconv,lor,lse,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,spe,store-pair-suppress,tsv110,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + // TargetArch_wasm32: + { str_lit("bleeding-edge"), str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,gc,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call") }, + { str_lit("generic"), str_lit("bulk-memory,bulk-memory-opt,call-indirect-overlong,multivalue,mutable-globals,nontrapping-fptoint,reference-types,sign-ext") }, + { str_lit("lime1"), str_lit("bulk-memory-opt,call-indirect-overlong,extended-const,multivalue,mutable-globals,nontrapping-fptoint,sign-ext") }, + { str_lit("mvp"), str_lit("") }, + // TargetArch_wasm64p32: + { str_lit("bleeding-edge"), str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,gc,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call") }, + { str_lit("generic"), str_lit("bulk-memory,bulk-memory-opt,call-indirect-overlong,multivalue,mutable-globals,nontrapping-fptoint,reference-types,sign-ext") }, + { str_lit("lime1"), str_lit("bulk-memory-opt,call-indirect-overlong,extended-const,multivalue,mutable-globals,nontrapping-fptoint,sign-ext") }, + { str_lit("mvp"), str_lit("") }, + // TargetArch_riscv64: + { str_lit("andes-45-series"), str_lit("andes45,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler") }, + { str_lit("andes-a25"), str_lit("32bit,a,c,d,f,i,m,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-a45"), str_lit("32bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax25"), str_lit("64bit,a,c,d,f,i,m,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax45"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax45mpv"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler,v,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvl128b,zvl32b,zvl64b") }, + { str_lit("andes-n45"), str_lit("32bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-nx45"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("generic"), str_lit("64bit,i,optimized-nf2-segment-load-store") }, + { str_lit("generic-ooo"), str_lit("") }, + { str_lit("generic-rv32"), str_lit("32bit,i,optimized-nf2-segment-load-store") }, + { str_lit("generic-rv64"), str_lit("64bit,i,optimized-nf2-segment-load-store") }, + { str_lit("mips-p8700"), str_lit("64bit,a,c,d,f,i,m,mips-p8700,xmipscbop,xmipscmov,xmipsexectl,xmipslsp,zaamo,zalrsc,zba,zbb,zca,zicsr,zifencei,zmmul") }, + { str_lit("rocket"), str_lit("") }, + { str_lit("rocket-rv32"), str_lit("32bit,i,zicsr,zifencei") }, + { str_lit("rocket-rv64"), str_lit("64bit,i,zicsr,zifencei") }, + { str_lit("rp2350-hazard3"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zba,zbb,zbkb,zbs,zca,zcb,zcmp,zicsr,zifencei,zmmul") }, + { str_lit("sifive-7-series"), str_lit("no-default-unroll,short-forward-branch-ialu,sifive7,use-postra-scheduler") }, + { str_lit("sifive-e20"), str_lit("32bit,c,i,m,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e21"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e24"), str_lit("32bit,a,c,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e31"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e34"), str_lit("32bit,a,c,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e76"), str_lit("32bit,a,c,f,i,m,no-default-unroll,short-forward-branch-ialu,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-p450"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul") }, + { str_lit("sifive-p470"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,xsifivecdiscarddlone,xsifivecflushdlone,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-p550"), str_lit("64bit,a,auipc-addi-fusion,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zba,zbb,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-p670"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-p870"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,supm,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,za64rs,zaamo,zalrsc,zama16b,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkr,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-s21"), str_lit("64bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s51"), str_lit("64bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s54"), str_lit("64bit,a,c,d,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s76"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zihintpause,zmmul") }, + { str_lit("sifive-u54"), str_lit("64bit,a,c,d,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-u74"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,short-forward-branch-ialu,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-x280"), str_lit("64bit,a,c,d,dlen-factor-2,f,i,m,no-default-unroll,optimized-nf2-segment-load-store,optimized-zero-stride-load,short-forward-branch-ialu,sifive7,use-postra-scheduler,v,vl-dependent-latency,zaamo,zalrsc,zba,zbb,zca,zfh,zfhmin,zicsr,zifencei,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvl128b,zvl256b,zvl32b,zvl512b,zvl64b") }, + { str_lit("sifive-x390"), str_lit("64bit,a,b,c,d,dlen-factor-2,experimental-zicfilp,experimental-zicfiss,f,i,m,no-default-unroll,optimized-nf2-segment-load-store,optimized-zero-stride-load,short-forward-branch-ialu,sifive7,single-element-vec-fp64,use-postra-scheduler,v,vl-dependent-latency,xsifivecdiscarddlone,xsifivecflushdlone,za64rs,zaamo,zalrsc,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkr,zkt,zmmul,zvbb,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkt,zvl1024b,zvl128b,zvl256b,zvl32b,zvl512b,zvl64b") }, + { str_lit("spacemit-x60"), str_lit("64bit,a,b,c,d,dlen-factor-2,f,i,m,optimized-nf2-segment-load-store,optimized-nf3-segment-load-store,optimized-nf4-segment-load-store,ssccptr,sscofpmf,sscounterenw,sstc,sstvala,sstvecd,svade,svbare,svinval,svnapot,svpbmt,unaligned-scalar-mem,v,vxrm-pipeline-flush,xsmtvdot,za64rs,zaamo,zalrsc,zba,zbb,zbc,zbkc,zbs,zca,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintpause,zihpm,zkt,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvkt,zvl128b,zvl256b,zvl32b,zvl64b") }, + { str_lit("syntacore-scr1-base"), str_lit("32bit,c,i,no-default-unroll,zca,zicsr,zifencei") }, + { str_lit("syntacore-scr1-max"), str_lit("32bit,c,i,m,no-default-unroll,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr3-rv32"), str_lit("32bit,c,i,m,no-default-unroll,use-postra-scheduler,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr3-rv64"), str_lit("64bit,a,c,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr4-rv32"), str_lit("32bit,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr4-rv64"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr5-rv32"), str_lit("32bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr5-rv64"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr7"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,v,zaamo,zalrsc,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zicsr,zifencei,zkn,zknd,zkne,zknh,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvl128b,zvl32b,zvl64b") }, + { str_lit("tt-ascalon-d8"), str_lit("64bit,a,b,c,d,f,h,i,log-vrgather,m,no-default-unroll,optimized-nf2-segment-load-store,optimized-nf3-segment-load-store,optimized-nf4-segment-load-store,optimized-nf5-segment-load-store,optimized-nf6-segment-load-store,optimized-nf7-segment-load-store,optimized-nf8-segment-load-store,optimized-zero-stride-load,sha,shcounterenw,shgatpa,shtvala,shvsatpa,shvstvala,shvstvecd,smaia,ssaia,ssccptr,sscofpmf,sscounterenw,ssnpm,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svbare,svinval,svnapot,svpbmt,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,za64rs,zaamo,zalrsc,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvkned,zvkng,zvknhb,zvkt,zvl128b,zvl256b,zvl32b,zvl64b") }, + { str_lit("veyron-v1"), str_lit("64bit,a,add-load-fusion,auipc-addi-fusion,auipc-load-fusion,c,d,disable-misched-load-clustering,disable-postmisched-load-clustering,disable-postmisched-store-clustering,f,i,lui-addi-fusion,lui-load-fusion,m,shifted-zextw-fusion,ventana-veyron,xventanacondops,zaamo,zalrsc,zba,zbb,zbc,zbs,zca,zexth-fusion,zextw-fusion,zicbom,zicbop,zicboz,zicntr,zicsr,zifencei,zihintpause,zihpm,zmmul") }, + { str_lit("xiangshan-kunminghu"), str_lit("64bit,a,b,c,d,f,h,i,m,no-default-unroll,sha,shcounterenw,shgatpa,shifted-zextw-fusion,shtvala,shvsatpa,shvstvala,shvstvecd,smaia,smcsrind,smdbltrp,smmpm,smnpm,smrnmi,smstateen,ssaia,ssccptr,sscofpmf,sscounterenw,sscsrind,ssdbltrp,ssnpm,sspm,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svbare,svinval,svnapot,svpbmt,v,za64rs,zaamo,zacas,zalrsc,zawrs,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zcb,zcmop,zexth-fusion,zextw-fusion,zfa,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkn,zknd,zkne,zknh,zks,zksed,zksh,zkt,zmmul,zvbb,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvkb,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("xiangshan-nanhu"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,shifted-zextw-fusion,svinval,zaamo,zalrsc,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zexth-fusion,zextw-fusion,zicbom,zicboz,zicsr,zifencei,zkn,zknd,zkne,zknh,zksed,zksh,zmmul") }, +}; + +#elif LLVM_VERSION_MAJOR == 21 +// Generated with the featuregen script in `misc/featuregen` +gb_global String target_microarch_list[TargetArch_COUNT] = { + // TargetArch_Invalid: + str_lit(""), + // TargetArch_amd64: + str_lit("alderlake,amdfam10,arrowlake,arrowlake-s,arrowlake_s,athlon,athlon-4,athlon-fx,athlon-mp,athlon-tbird,athlon-xp,athlon64,athlon64-sse3,atom,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,bonnell,broadwell,btver1,btver2,c3,c3-2,cannonlake,cascadelake,clearwaterforest,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,diamondrapids,emeraldrapids,generic,geode,goldmont,goldmont-plus,goldmont_plus,gracemont,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,i386,i486,i586,i686,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k6,k6-2,k6-3,k8,k8-sse3,knl,knm,lakemont,lunarlake,meteorlake,mic_avx512,nehalem,nocona,opteron,opteron-sse3,pantherlake,penryn,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,winchip-c6,winchip2,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,yonah,znver1,znver2,znver3,znver4,znver5"), + // TargetArch_i386: + str_lit("alderlake,amdfam10,arrowlake,arrowlake-s,arrowlake_s,athlon,athlon-4,athlon-fx,athlon-mp,athlon-tbird,athlon-xp,athlon64,athlon64-sse3,atom,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,bonnell,broadwell,btver1,btver2,c3,c3-2,cannonlake,cascadelake,clearwaterforest,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,diamondrapids,emeraldrapids,generic,geode,goldmont,goldmont-plus,goldmont_plus,gracemont,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,i386,i486,i586,i686,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k6,k6-2,k6-3,k8,k8-sse3,knl,knm,lakemont,lunarlake,meteorlake,mic_avx512,nehalem,nocona,opteron,opteron-sse3,pantherlake,penryn,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,winchip-c6,winchip2,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,yonah,znver1,znver2,znver3,znver4,znver5"), + // TargetArch_arm32: + str_lit("arm1020e,arm1020t,arm1022e,arm10e,arm10tdmi,arm1136j-s,arm1136jf-s,arm1156t2-s,arm1156t2f-s,arm1176jz-s,arm1176jzf-s,arm710t,arm720t,arm7tdmi,arm7tdmi-s,arm8,arm810,arm9,arm920,arm920t,arm922t,arm926ej-s,arm940t,arm946e-s,arm966e-s,arm968e-s,arm9e,arm9tdmi,cortex-a12,cortex-a15,cortex-a17,cortex-a32,cortex-a35,cortex-a5,cortex-a510,cortex-a53,cortex-a55,cortex-a57,cortex-a7,cortex-a710,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78ae,cortex-a78c,cortex-a8,cortex-a9,cortex-m0,cortex-m0plus,cortex-m1,cortex-m23,cortex-m3,cortex-m33,cortex-m35p,cortex-m4,cortex-m52,cortex-m55,cortex-m7,cortex-m85,cortex-r4,cortex-r4f,cortex-r5,cortex-r52,cortex-r52plus,cortex-r7,cortex-r8,cortex-x1,cortex-x1c,cyclone,ep9312,exynos-m3,exynos-m4,exynos-m5,generic,iwmmxt,krait,kryo,mpcore,mpcorenovfp,neoverse-n1,neoverse-n2,neoverse-v1,sc000,sc300,star-mc1,strongarm,strongarm110,strongarm1100,strongarm1110,swift,xscale"), + // TargetArch_arm64: + str_lit("a64fx,ampere1,ampere1a,ampere1b,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a17,apple-a18,apple-a7,apple-a8,apple-a9,apple-m1,apple-m2,apple-m3,apple-m4,apple-s10,apple-s4,apple-s5,apple-s6,apple-s7,apple-s8,apple-s9,carmel,cobalt-100,cortex-a320,cortex-a34,cortex-a35,cortex-a510,cortex-a520,cortex-a520ae,cortex-a53,cortex-a55,cortex-a57,cortex-a65,cortex-a65ae,cortex-a710,cortex-a715,cortex-a72,cortex-a720,cortex-a720ae,cortex-a725,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78ae,cortex-a78c,cortex-r82,cortex-r82ae,cortex-x1,cortex-x1c,cortex-x2,cortex-x3,cortex-x4,cortex-x925,cyclone,exynos-m3,exynos-m4,exynos-m5,falkor,fujitsu-monaka,gb10,generic,grace,kryo,neoverse-512tvb,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-n3,neoverse-v1,neoverse-v2,neoverse-v3,neoverse-v3ae,olympus,oryon-1,saphira,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tsv110"), + // TargetArch_wasm32: + str_lit("bleeding-edge,generic,lime1,mvp"), + // TargetArch_wasm64p32: + str_lit("bleeding-edge,generic,lime1,mvp"), + // TargetArch_riscv64: + str_lit("andes-45-series,andes-a25,andes-a45,andes-ax25,andes-ax45,andes-ax45mpv,andes-n45,andes-nx45,generic,generic-ooo,generic-rv32,generic-rv64,mips-p8700,rocket,rocket-rv32,rocket-rv64,rp2350-hazard3,sifive-7-series,sifive-e20,sifive-e21,sifive-e24,sifive-e31,sifive-e34,sifive-e76,sifive-p450,sifive-p470,sifive-p550,sifive-p670,sifive-p870,sifive-s21,sifive-s51,sifive-s54,sifive-s76,sifive-u54,sifive-u74,sifive-x280,sifive-x390,spacemit-x60,syntacore-scr1-base,syntacore-scr1-max,syntacore-scr3-rv32,syntacore-scr3-rv64,syntacore-scr4-rv32,syntacore-scr4-rv64,syntacore-scr5-rv32,syntacore-scr5-rv64,syntacore-scr7,tt-ascalon-d8,veyron-v1,xiangshan-kunminghu,xiangshan-nanhu"), +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global String target_features_list[TargetArch_COUNT] = { + // TargetArch_Invalid: + str_lit(""), + // TargetArch_amd64: + str_lit("16bit-mode,32bit-mode,64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,amx-transpose,avx,avx10.1-256,avx10.1-512,avx10.2-256,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,branchfusion,ccmp,cf,cldemote,clflushopt,clwb,clzero,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-lzcnt-tzcnt,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-popcnt,false-deps-range,fast-11bytenop,fast-15bytenop,fast-7bytenop,fast-bextr,fast-dpwssd,fast-gather,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fast-vector-shift-masks,faster-shift-than-shuffle,fma,fma4,fsgsbase,fsrm,fxsr,gfni,harden-sls-ijmp,harden-sls-ret,hreset,idivl-to-divb,idivq-to-divl,inline-asm-use-gpr32,invpcid,kl,lea-sp,lea-uses-ag,lvi-cfi,lvi-load-hardening,lwp,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,mwaitx,ndd,nf,no-bypass-delay,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pad-short-functions,pclmul,pconfig,pku,popcnt,ppx,prefer-128-bit,prefer-256-bit,prefer-mask-registers,prefer-movmsk-over-vtest,prefer-no-gather,prefer-no-scatter,prefetchi,prfchw,ptwrite,push2pop2,raoint,rdpid,rdpru,rdrnd,rdseed,retpoline,retpoline-external-thunk,retpoline-indirect-branches,retpoline-indirect-calls,rtm,sahf,sbb-dep-breaking,serialize,seses,sgx,sha,sha512,shstk,slow-3ops-lea,slow-incdec,slow-lea,slow-pmaddwd,slow-pmulld,slow-shld,slow-two-mem-ops,slow-unaligned-mem-16,slow-unaligned-mem-32,sm3,sm4,soft-float,sse,sse-unaligned-mem,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tagged-globals,tbm,tsxldtrk,tuning-fast-imm-vector-shift,uintr,use-glm-div-sqrt-costs,use-slm-arith-costs,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,widekl,x87,xop,xsave,xsavec,xsaveopt,xsaves,zu"), + // TargetArch_i386: + str_lit("16bit-mode,32bit-mode,64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,amx-transpose,avx,avx10.1-256,avx10.1-512,avx10.2-256,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,branchfusion,ccmp,cf,cldemote,clflushopt,clwb,clzero,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-lzcnt-tzcnt,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-popcnt,false-deps-range,fast-11bytenop,fast-15bytenop,fast-7bytenop,fast-bextr,fast-dpwssd,fast-gather,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fast-vector-shift-masks,faster-shift-than-shuffle,fma,fma4,fsgsbase,fsrm,fxsr,gfni,harden-sls-ijmp,harden-sls-ret,hreset,idivl-to-divb,idivq-to-divl,inline-asm-use-gpr32,invpcid,kl,lea-sp,lea-uses-ag,lvi-cfi,lvi-load-hardening,lwp,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,mwaitx,ndd,nf,no-bypass-delay,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pad-short-functions,pclmul,pconfig,pku,popcnt,ppx,prefer-128-bit,prefer-256-bit,prefer-mask-registers,prefer-movmsk-over-vtest,prefer-no-gather,prefer-no-scatter,prefetchi,prfchw,ptwrite,push2pop2,raoint,rdpid,rdpru,rdrnd,rdseed,retpoline,retpoline-external-thunk,retpoline-indirect-branches,retpoline-indirect-calls,rtm,sahf,sbb-dep-breaking,serialize,seses,sgx,sha,sha512,shstk,slow-3ops-lea,slow-incdec,slow-lea,slow-pmaddwd,slow-pmulld,slow-shld,slow-two-mem-ops,slow-unaligned-mem-16,slow-unaligned-mem-32,sm3,sm4,soft-float,sse,sse-unaligned-mem,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tagged-globals,tbm,tsxldtrk,tuning-fast-imm-vector-shift,uintr,use-glm-div-sqrt-costs,use-slm-arith-costs,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,widekl,x87,xop,xsave,xsavec,xsaveopt,xsaves,zu"), + // TargetArch_arm32: + str_lit("32bit,8msecext,a12,a15,a17,a32,a35,a5,a53,a55,a57,a7,a72,a73,a75,a76,a77,a78c,a8,a9,aapcs-frame-chain,aclass,acquire-release,aes,armv4,armv4t,armv5t,armv5te,armv5tej,armv6,armv6-m,armv6j,armv6k,armv6kz,armv6s-m,armv6t2,armv7-a,armv7-m,armv7-r,armv7e-m,armv7k,armv7s,armv7ve,armv8-a,armv8-m.base,armv8-m.main,armv8-r,armv8.1-a,armv8.1-m.main,armv8.2-a,armv8.3-a,armv8.4-a,armv8.5-a,armv8.6-a,armv8.7-a,armv8.8-a,armv8.9-a,armv9-a,armv9.1-a,armv9.2-a,armv9.3-a,armv9.4-a,armv9.5-a,armv9.6-a,atomics-32,avoid-movs-shop,avoid-muls,avoid-partial-cpsr,bf16,big-endian-instructions,branch-align-64,cde,cdecp0,cdecp1,cdecp2,cdecp3,cdecp4,cdecp5,cdecp6,cdecp7,cheap-predicable-cpsr,clrbhb,cortex-a510,cortex-a710,cortex-a78,cortex-a78ae,cortex-x1,cortex-x1c,crc,crypto,d32,db,dfb,disable-postra-scheduler,dont-widen-vmovs,dotprod,dsp,execute-only,expand-fp-mlx,exynos,fix-cmse-cve-2021-35465,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpao,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,harden-sls-blr,harden-sls-nocomdat,harden-sls-retbr,hwdiv,hwdiv-arm,i8mm,iwmmxt,iwmmxt2,krait,kryo,lob,long-calls,loop-align,m3,m55,m7,m85,mclass,mp,muxed-units,mve,mve.fp,mve1beat,mve2beat,mve4beat,nacl-trap,neon,neon-fpmovs,neonfp,neoverse-v1,no-branch-predictor,no-bti-at-return-twice,no-movt,no-neg-immediates,noarm,nonpipelined-vfp,pacbti,perfmon,prefer-ishst,prefer-vmovsr,prof-unpr,r4,r5,r52,r52plus,r7,ras,rclass,read-tp-tpidrprw,read-tp-tpidruro,read-tp-tpidrurw,reserve-r9,ret-addr-stack,sb,sha2,slow-fp-brcc,slow-load-D-subreg,slow-odd-reg,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,soft-float,splat-vfp-neon,strict-align,swift,thumb-mode,thumb2,trustzone,use-mipipeliner,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.1m.main,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8.9a,v8m,v8m.main,v9.1a,v9.2a,v9.3a,v9.4a,v9.5a,v9.6a,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vldn-align,vmlx-forwarding,vmlx-hazards,wide-stride-vfp,xscale,zcz"), + // TargetArch_arm64: + str_lit("CONTEXTIDREL2,a320,a35,a510,a520,a520ae,a53,a55,a57,a64fx,a65,a710,a715,a72,a720,a720ae,a73,a75,a76,a77,a78,a78ae,a78c,addr-lsl-slow-14,aes,aggressive-fma,all,alternate-sextload-cvt-f32-pattern,altnzcv,alu-lsl-fast,am,ampere1,ampere1a,ampere1b,amvs,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a17,apple-a7,apple-m4,arith-bcc-fusion,arith-cbz-fusion,ascend-store-address,avoid-ldapur,balance-fp-ops,bf16,brbe,bti,call-saved-x10,call-saved-x11,call-saved-x12,call-saved-x13,call-saved-x14,call-saved-x15,call-saved-x18,call-saved-x8,call-saved-x9,carmel,ccdp,ccidx,ccpp,chk,clrbhb,cmp-bcc-fusion,cmpbr,complxnum,cortex-a725,cortex-r82,cortex-r82ae,cortex-x1,cortex-x2,cortex-x3,cortex-x4,cortex-x925,cpa,crc,crypto,cssc,d128,disable-fast-inc-vl,disable-latency-sched-heuristic,disable-ldp,disable-stp,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,execute-only,exynos-cheap-as-move,exynosm3,exynosm4,f32mm,f64mm,f8f16mm,f8f32mm,falkor,faminmax,fgt,fix-cortex-a53-835769,flagm,fmv,force-32bit-jump-tables,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fprcvt,fptoint,fujitsu-monaka,fullfp16,fuse-address,fuse-addsub-2reg-const1,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,gcs,harden-sls-blr,harden-sls-nocomdat,harden-sls-retbr,hbc,hcx,i8mm,ite,jsconv,kryo,ldp-aligned-only,lor,ls64,lse,lse128,lse2,lsfe,lsui,lut,mec,mops,mpam,mte,neon,neoverse512tvb,neoversee1,neoversen1,neoversen2,neoversen3,neoversev1,neoversev2,neoversev3,neoversev3AE,nmi,no-bti-at-return-twice,no-neg-immediates,no-sve-fp-ld1r,no-zcz-fp,nv,occmo,olympus,oryon-1,outline-atomics,pan,pan-rwv,pauth,pauth-lr,pcdphint,perfmon,pops,predictable-select-expensive,predres,prfm-slc-target,rand,ras,rasv2,rcpc,rcpc-immo,rcpc3,rdm,reserve-lr-for-ra,reserve-x1,reserve-x10,reserve-x11,reserve-x12,reserve-x13,reserve-x14,reserve-x15,reserve-x18,reserve-x2,reserve-x20,reserve-x21,reserve-x22,reserve-x23,reserve-x24,reserve-x25,reserve-x26,reserve-x27,reserve-x28,reserve-x3,reserve-x4,reserve-x5,reserve-x6,reserve-x7,reserve-x9,rme,saphira,sb,sel2,sha2,sha3,slow-misaligned-128store,slow-paired-128,slow-strqro-store,sm4,sme,sme-b16b16,sme-f16f16,sme-f64f64,sme-f8f16,sme-f8f32,sme-fa64,sme-i16i64,sme-lutv2,sme-mop4,sme-tmop,sme2,sme2p1,sme2p2,spe,spe-eef,specres2,specrestrict,ssbs,ssve-aes,ssve-bitperm,ssve-fexpa,ssve-fp8dot2,ssve-fp8dot4,ssve-fp8fma,store-pair-suppress,stp-aligned-only,strict-align,sve,sve-aes,sve-aes2,sve-b16b16,sve-bfscale,sve-bitperm,sve-f16f32mm,sve-sha3,sve-sm4,sve2,sve2-aes,sve2-bitperm,sve2-sha3,sve2-sm4,sve2p1,sve2p2,tagged-globals,the,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tlb-rmi,tlbiw,tme,tpidr-el1,tpidr-el2,tpidr-el3,tpidrro-el0,tracev8.4,trbe,tsv110,uaops,use-experimental-zeroing-pseudos,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,use-reciprocal-square-root,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8.9a,v8a,v8r,v9.1a,v9.2a,v9.3a,v9.4a,v9.5a,v9.6a,v9a,vh,wfxt,xs,zcm-fpr32,zcm-fpr64,zcm-gpr32,zcm-gpr64,zcz,zcz-fp-workaround,zcz-gp"), + // TargetArch_wasm32: + str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call,wide-arithmetic"), + // TargetArch_wasm64p32: + str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call,wide-arithmetic"), + // TargetArch_riscv64: + str_lit("32bit,64bit,a,andes45,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,disable-latency-sched-heuristic,dlen-factor-2,e,exact-asm,experimental,experimental-p,experimental-rvm23u32,experimental-smctr,experimental-ssctr,experimental-svukte,experimental-xqccmp,experimental-xqcia,experimental-xqciac,experimental-xqcibi,experimental-xqcibm,experimental-xqcicli,experimental-xqcicm,experimental-xqcics,experimental-xqcicsr,experimental-xqciint,experimental-xqciio,experimental-xqcilb,experimental-xqcili,experimental-xqcilia,experimental-xqcilo,experimental-xqcilsm,experimental-xqcisim,experimental-xqcisls,experimental-xqcisync,experimental-xrivosvisni,experimental-xrivosvizip,experimental-xsfmclic,experimental-xsfsclic,experimental-zalasr,experimental-zicfilp,experimental-zicfiss,experimental-zvbc32e,experimental-zvkgs,experimental-zvqdotq,f,forced-atomics,h,i,ld-add-fusion,log-vrgather,lui-addi-fusion,m,mips-p8700,no-default-unroll,no-sink-splat-operands,no-trailing-seq-cst-fence,optimized-nf2-segment-load-store,optimized-nf3-segment-load-store,optimized-nf4-segment-load-store,optimized-nf5-segment-load-store,optimized-nf6-segment-load-store,optimized-nf7-segment-load-store,optimized-nf8-segment-load-store,optimized-zero-stride-load,predictable-select-expensive,prefer-vsetvli-over-read-vlenb,prefer-w-inst,q,relax,reserve-x1,reserve-x10,reserve-x11,reserve-x12,reserve-x13,reserve-x14,reserve-x15,reserve-x16,reserve-x17,reserve-x18,reserve-x19,reserve-x2,reserve-x20,reserve-x21,reserve-x22,reserve-x23,reserve-x24,reserve-x25,reserve-x26,reserve-x27,reserve-x28,reserve-x29,reserve-x3,reserve-x30,reserve-x31,reserve-x4,reserve-x5,reserve-x6,reserve-x7,reserve-x8,reserve-x9,rva20s64,rva20u64,rva22s64,rva22u64,rva23s64,rva23u64,rvb23s64,rvb23u64,rvi20u32,rvi20u64,save-restore,sdext,sdtrig,sha,shcounterenw,shgatpa,shifted-zextw-fusion,shlcofideleg,short-forward-branch-opt,shtvala,shvsatpa,shvstvala,shvstvecd,sifive7,smaia,smcdeleg,smcntrpmf,smcsrind,smdbltrp,smepmp,smmpm,smnpm,smrnmi,smstateen,ssaia,ssccfg,ssccptr,sscofpmf,sscounterenw,sscsrind,ssdbltrp,ssnpm,sspm,ssqosid,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svadu,svbare,svinval,svnapot,svpbmt,svvptc,tagged-globals,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,ventana-veyron,vl-dependent-latency,vxrm-pipeline-flush,xandesbfhcvt,xandesperf,xandesvbfhcvt,xandesvdot,xandesvpackfph,xandesvsintload,xcvalu,xcvbi,xcvbitmanip,xcvelw,xcvmac,xcvmem,xcvsimd,xmipscbop,xmipscmov,xmipslsp,xsfcease,xsfmm128t,xsfmm16t,xsfmm32a16f,xsfmm32a32f,xsfmm32a8f,xsfmm32a8i,xsfmm32t,xsfmm64a64f,xsfmm64t,xsfmmbase,xsfvcp,xsfvfnrclipxfqf,xsfvfwmaccqqq,xsfvqmaccdod,xsfvqmaccqoq,xsifivecdiscarddlone,xsifivecflushdlone,xtheadba,xtheadbb,xtheadbs,xtheadcmo,xtheadcondmov,xtheadfmemidx,xtheadmac,xtheadmemidx,xtheadmempair,xtheadsync,xtheadvdot,xventanacondops,xwchc,za128rs,za64rs,zaamo,zabha,zacas,zalrsc,zama16b,zawrs,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zcb,zcd,zce,zcf,zclsd,zcmop,zcmp,zcmt,zdinx,zexth-fusion,zextw-fusion,zfa,zfbfmin,zfh,zfhmin,zfinx,zhinx,zhinxmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccamoc,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zilsd,zimop,zk,zkn,zknd,zkne,zknh,zkr,zks,zksed,zksh,zkt,zmmul,ztso,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknha,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl1024b,zvl128b,zvl16384b,zvl2048b,zvl256b,zvl32768b,zvl32b,zvl4096b,zvl512b,zvl64b,zvl65536b,zvl8192b"), +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global int target_microarch_counts[TargetArch_COUNT] = { + // TargetArch_Invalid: + 0, + // TargetArch_amd64: + 129, + // TargetArch_i386: + 129, + // TargetArch_arm32: + 95, + // TargetArch_arm64: + 91, + // TargetArch_wasm32: + 4, + // TargetArch_wasm64p32: + 4, + // TargetArch_riscv64: + 51, +}; + +// Generated with the featuregen script in `misc/featuregen` +gb_global MicroarchFeatureList microarch_features_list[] = { + // TargetArch_amd64: + { str_lit("alderlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("amdfam10"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("arrowlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake-s"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake_s"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("athlon"), str_lit("64bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-fx"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-mp"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-tbird"), str_lit("64bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-xp"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("atom"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("atom_sse4_2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("atom_sse4_2_movbe"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fsgsbase,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("barcelona"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("bdver1"), str_lit("64bit,64bit-mode,aes,avx,branchfusion,cmov,crc32,cx16,cx8,fast-11bytenop,fast-scalar-shift-masks,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver2"), str_lit("64bit,64bit-mode,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver3"), str_lit("64bit,64bit-mode,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bdver4"), str_lit("64bit,64bit-mode,aes,avx,avx2,bmi,bmi2,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bonnell"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("broadwell"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("btver1"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-15bytenop,fast-imm16,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,ssse3,vzeroupper,x87") }, + { str_lit("btver2"), str_lit("64bit,64bit-mode,aes,avx,bmi,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,x87,xsave,xsaveopt") }, + { str_lit("c3"), str_lit("64bit-mode,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("c3-2"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("cannonlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vl,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,sha,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cascadelake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("clearwaterforest"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cooperlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("core-avx-i"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core-avx2"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core2"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_sse4_1"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_ssse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2nd_gen_avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_3rd_gen_avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx_tsx"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx_tsx"), str_lit("64bit,64bit-mode,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_aes_pclmulqdq"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("core_i7_sse4_2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7-avx"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("diamondrapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,amx-transpose,avx,avx10.1-256,avx10.1-512,avx10.2-256,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,ccmp,cf,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-256-bit,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("emeraldrapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("generic"), str_lit("64bit,64bit-mode,cx8,fast-15bytenop,fast-scalar-fsqrt,idivq-to-divl,macrofusion,slow-3ops-lea,sse,sse2,vzeroupper,x87") }, + { str_lit("geode"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("goldmont"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont-plus"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont_plus"), str_lit("64bit,64bit-mode,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("gracemont"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("grandridge"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids-d"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids_d"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("haswell"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("i386"), str_lit("64bit-mode,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i486"), str_lit("64bit-mode,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i586"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("i686"), str_lit("64bit-mode,cmov,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("icelake-client"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake-server"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_client"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_server"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("ivybridge"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("k6"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k6-2"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k6-3"), str_lit("64bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("knl"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("knm"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,avx512vpopcntdq,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("lakemont"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper") }, + { str_lit("lunarlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("meteorlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("mic_avx512"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("nehalem"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("nocona"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("opteron"), str_lit("64bit,64bit-mode,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("opteron-sse3"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pantherlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("penryn"), str_lit("64bit,64bit-mode,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("pentium"), str_lit("64bit-mode,cx8,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-mmx"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium2"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium3"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium3m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4_sse3"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pentium_ii"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_iii"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_iii_no_xmm_regs"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_m"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_mmx"), str_lit("64bit-mode,cx8,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_pro"), str_lit("64bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentiumpro"), str_lit("64bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("prescott"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("raptorlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("rocketlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sandybridge"), str_lit("64bit,64bit-mode,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("sapphirerapids"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sierraforest"), str_lit("64bit,64bit-mode,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("silvermont"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("skx"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake-avx512"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake_avx512"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("slm"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("tigerlake"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("tremont"), str_lit("64bit,64bit-mode,aes,clflushopt,clwb,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,gfni,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("westmere"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("winchip-c6"), str_lit("64bit-mode,mmx,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("winchip2"), str_lit("64bit-mode,mmx,prfchw,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64"), str_lit("64bit,64bit-mode,cmov,cx8,fxsr,idivq-to-divl,macrofusion,mmx,nopl,slow-3ops-lea,slow-incdec,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64-v2"), str_lit("64bit,64bit-mode,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,nopl,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("x86-64-v3"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("x86-64-v4"), str_lit("64bit,64bit-mode,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,prefer-256-bit,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("yonah"), str_lit("64bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("znver1"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver2"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver3"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver4"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,evex512,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver5"), str_lit("64bit,64bit-mode,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxvnni,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,evex512,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,mwaitx,nopl,pclmul,pku,popcnt,prefetchi,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + // TargetArch_i386: + { str_lit("alderlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("amdfam10"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("arrowlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake-s"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("arrowlake_s"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("athlon"), str_lit("32bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("athlon-4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon-fx"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon-mp"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon-tbird"), str_lit("32bit-mode,cmov,cx8,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("athlon-xp"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,prfchw,slow-shld,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("athlon64"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("athlon64-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("atom"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("atom_sse4_2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("atom_sse4_2_movbe"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fsgsbase,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("barcelona"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,idivq-to-divl,lzcnt,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,vzeroupper,x87") }, + { str_lit("bdver1"), str_lit("32bit-mode,64bit,aes,avx,branchfusion,cmov,crc32,cx16,cx8,fast-11bytenop,fast-scalar-shift-masks,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver2"), str_lit("32bit-mode,64bit,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave") }, + { str_lit("bdver3"), str_lit("32bit-mode,64bit,aes,avx,bmi,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bdver4"), str_lit("32bit-mode,64bit,aes,avx,avx2,bmi,bmi2,branchfusion,cmov,crc32,cx16,cx8,f16c,fast-11bytenop,fast-bextr,fast-movbe,fast-scalar-shift-masks,fma,fma4,fsgsbase,fxsr,idivq-to-divl,lwp,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,tbm,vzeroupper,x87,xop,xsave,xsaveopt") }, + { str_lit("bonnell"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-imm16,fxsr,idivl-to-divb,idivq-to-divl,lea-sp,lea-uses-ag,mmx,movbe,no-bypass-delay,nopl,pad-short-functions,sahf,slow-two-mem-ops,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("broadwell"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("btver1"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-15bytenop,fast-imm16,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,nopl,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4a,ssse3,vzeroupper,x87") }, + { str_lit("btver2"), str_lit("32bit-mode,64bit,aes,avx,bmi,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-hops,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-shift-masks,fast-vector-shift-masks,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prfchw,sahf,sbb-dep-breaking,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,x87,xsave,xsaveopt") }, + { str_lit("c3"), str_lit("32bit-mode,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("c3-2"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("cannonlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vl,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,sha,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cascadelake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("clearwaterforest"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("cooperlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,avx512vnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("core-avx-i"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core-avx2"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core2"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_sse4_1"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("core_2_duo_ssse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,ssse3,vzeroupper,x87") }, + { str_lit("core_2nd_gen_avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_3rd_gen_avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_4th_gen_avx_tsx"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_5th_gen_avx_tsx"), str_lit("32bit-mode,64bit,adx,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("core_aes_pclmulqdq"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("core_i7_sse4_2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("corei7-avx"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("diamondrapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-avx512,amx-bf16,amx-complex,amx-fp16,amx-fp8,amx-int8,amx-movrs,amx-tf32,amx-tile,amx-transpose,avx,avx10.1-256,avx10.1-512,avx10.2-256,avx10.2-512,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,branch-hint,ccmp,cf,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,egpr,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,movrs,ndd,nf,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,ppx,prefer-256-bit,prefetchi,prfchw,ptwrite,push2pop2,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,usermsr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves,zu") }, + { str_lit("emeraldrapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("generic"), str_lit("32bit-mode,64bit,cx8,fast-15bytenop,fast-scalar-fsqrt,idivq-to-divl,macrofusion,slow-3ops-lea,vzeroupper,x87") }, + { str_lit("geode"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("goldmont"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont-plus"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("goldmont_plus"), str_lit("32bit-mode,64bit,aes,clflushopt,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("gracemont"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("grandridge"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids-d"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("graniterapids_d"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-complex,amx-fp16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,branch-hint,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("haswell"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("i386"), str_lit("32bit-mode,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i486"), str_lit("32bit-mode,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i586"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("i686"), str_lit("32bit-mode,cmov,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("icelake-client"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake-server"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_client"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("icelake_server"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("ivybridge"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fsgsbase,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,rdrnd,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("k6"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k6-2"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k6-3"), str_lit("32bit-mode,cx8,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("k8"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("k8-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("knl"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("knm"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,avx512vpopcntdq,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("lakemont"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper") }, + { str_lit("lunarlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("meteorlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("mic_avx512"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avx512cd,avx512f,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,fast-gather,fast-imm16,fast-movbe,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,nopl,pclmul,popcnt,prefer-mask-registers,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,slow-incdec,slow-pmaddwd,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,x87,xsave,xsaveopt") }, + { str_lit("nehalem"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("nocona"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("opteron"), str_lit("32bit-mode,64bit,cmov,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("opteron-sse3"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fast-scalar-shift-masks,fxsr,mmx,nopl,prfchw,sbb-dep-breaking,slow-shld,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pantherlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint16,avxvnniint8,bmi,bmi2,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prefetchi,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,sha512,shstk,slow-3ops-lea,sm3,sm4,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("penryn"), str_lit("32bit-mode,64bit,cmov,cx16,cx8,fxsr,macrofusion,mmx,nopl,sahf,slow-unaligned-mem-16,sse,sse2,sse3,sse4.1,ssse3,vzeroupper,x87") }, + { str_lit("pentium"), str_lit("32bit-mode,cx8,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium-m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium-mmx"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium2"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium3"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium3m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium4m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_4_sse3"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("pentium_ii"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium_iii"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium_iii_no_xmm_regs"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,vzeroupper,x87") }, + { str_lit("pentium_m"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,vzeroupper,x87") }, + { str_lit("pentium_mmx"), str_lit("32bit-mode,cx8,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentium_pro"), str_lit("32bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("pentiumpro"), str_lit("32bit-mode,cmov,cx8,nopl,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("prescott"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("raptorlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avxvnni,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,f16c,false-deps-perm,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,idivq-to-divl,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-movmsk-over-vtest,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("rocketlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sandybridge"), str_lit("32bit-mode,64bit,avx,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsaveopt") }, + { str_lit("sapphirerapids"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,amx-bf16,amx-int8,amx-tile,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512fp16,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,avxvnni,bmi,bmi2,cldemote,clflushopt,clwb,cmov,crc32,cx16,cx8,enqcmd,ermsb,evex512,f16c,false-deps-getmant,false-deps-mulc,false-deps-mullq,false-deps-perm,false-deps-range,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pconfig,pku,popcnt,prefer-256-bit,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tsxldtrk,tuning-fast-imm-vector-shift,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("sierraforest"), str_lit("32bit-mode,64bit,adx,aes,avx,avx2,avxifma,avxneconvert,avxvnni,avxvnniint8,bmi,bmi2,cldemote,clflushopt,clwb,cmov,cmpccxadd,crc32,cx16,cx8,enqcmd,f16c,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,gfni,hreset,invpcid,kl,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,nopl,pclmul,pconfig,pku,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,serialize,sha,shstk,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,uintr,vaes,vpclmulqdq,vzeroupper,waitpkg,widekl,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("silvermont"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("skx"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,clflushopt,cmov,crc32,cx16,cx8,ermsb,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake-avx512"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("skylake_avx512"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,faster-shift-than-shuffle,fma,fsgsbase,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdrnd,rdseed,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("slm"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-7bytenop,fast-imm16,fast-movbe,fxsr,idivq-to-divl,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,rdrnd,sahf,slow-incdec,slow-lea,slow-pmulld,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-slm-arith-costs,vzeroupper,x87") }, + { str_lit("tigerlake"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,bmi,bmi2,clflushopt,clwb,cmov,crc32,cx16,cx8,ermsb,evex512,f16c,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,no-bypass-delay-blend,no-bypass-delay-mov,no-bypass-delay-shuffle,nopl,pclmul,pku,popcnt,prefer-256-bit,prfchw,rdpid,rdrnd,rdseed,sahf,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,ssse3,tuning-fast-imm-vector-shift,vaes,vpclmulqdq,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("tremont"), str_lit("32bit-mode,64bit,aes,clflushopt,clwb,cmov,crc32,cx16,cx8,fast-imm16,fast-movbe,fsgsbase,fxsr,gfni,mmx,movbe,no-bypass-delay,nopl,pclmul,popcnt,prfchw,ptwrite,rdpid,rdrnd,rdseed,sahf,sha,slow-incdec,slow-lea,slow-two-mem-ops,sse,sse2,sse3,sse4.1,sse4.2,ssse3,use-glm-div-sqrt-costs,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("westmere"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,fxsr,idivq-to-divl,macrofusion,mmx,no-bypass-delay-mov,nopl,pclmul,popcnt,sahf,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("winchip-c6"), str_lit("32bit-mode,mmx,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("winchip2"), str_lit("32bit-mode,mmx,prfchw,slow-unaligned-mem-16,vzeroupper,x87") }, + { str_lit("x86-64"), str_lit("32bit-mode,64bit,cmov,cx8,fxsr,idivq-to-divl,macrofusion,mmx,nopl,slow-3ops-lea,slow-incdec,sse,sse2,vzeroupper,x87") }, + { str_lit("x86-64-v2"), str_lit("32bit-mode,64bit,cmov,crc32,cx16,cx8,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fxsr,idivq-to-divl,macrofusion,mmx,nopl,popcnt,sahf,slow-3ops-lea,slow-unaligned-mem-32,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87") }, + { str_lit("x86-64-v3"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,bmi,bmi2,cmov,crc32,cx16,cx8,f16c,false-deps-lzcnt-tzcnt,false-deps-popcnt,fast-15bytenop,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("x86-64-v4"), str_lit("32bit-mode,64bit,allow-light-256-bit,avx,avx2,avx512bw,avx512cd,avx512dq,avx512f,avx512vl,bmi,bmi2,cmov,crc32,cx16,cx8,evex512,f16c,false-deps-popcnt,fast-15bytenop,fast-gather,fast-scalar-fsqrt,fast-shld-rotate,fast-variable-crosslane-shuffle,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fxsr,idivq-to-divl,lzcnt,macrofusion,mmx,movbe,nopl,popcnt,prefer-256-bit,sahf,slow-3ops-lea,sse,sse2,sse3,sse4.1,sse4.2,ssse3,vzeroupper,x87,xsave") }, + { str_lit("yonah"), str_lit("32bit-mode,cmov,cx8,fxsr,mmx,nopl,slow-unaligned-mem-16,sse,sse2,sse3,vzeroupper,x87") }, + { str_lit("znver1"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver2"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fxsr,idivq-to-divl,lzcnt,mmx,movbe,mwaitx,nopl,pclmul,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,slow-shld,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver3"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,f16c,fast-15bytenop,fast-bextr,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver4"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vpopcntdq,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,evex512,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,mwaitx,nopl,pclmul,pku,popcnt,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + { str_lit("znver5"), str_lit("32bit-mode,64bit,adx,aes,allow-light-256-bit,avx,avx2,avx512bf16,avx512bitalg,avx512bw,avx512cd,avx512dq,avx512f,avx512ifma,avx512vbmi,avx512vbmi2,avx512vl,avx512vnni,avx512vp2intersect,avx512vpopcntdq,avxvnni,bmi,bmi2,branchfusion,clflushopt,clwb,clzero,cmov,crc32,cx16,cx8,evex512,f16c,fast-15bytenop,fast-bextr,fast-dpwssd,fast-imm16,fast-lzcnt,fast-movbe,fast-scalar-fsqrt,fast-scalar-shift-masks,fast-variable-perlane-shuffle,fast-vector-fsqrt,fma,fsgsbase,fsrm,fxsr,gfni,idivq-to-divl,invpcid,lzcnt,macrofusion,mmx,movbe,movdir64b,movdiri,mwaitx,nopl,pclmul,pku,popcnt,prefetchi,prfchw,rdpid,rdpru,rdrnd,rdseed,sahf,sbb-dep-breaking,sha,shstk,sse,sse2,sse3,sse4.1,sse4.2,sse4a,ssse3,vaes,vpclmulqdq,vzeroupper,wbnoinvd,x87,xsave,xsavec,xsaveopt,xsaves") }, + // TargetArch_arm32: + { str_lit("arm1020e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm1020t"), str_lit("armv5t,v4t,v5t") }, + { str_lit("arm1022e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm10e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm10tdmi"), str_lit("armv5t,v4t,v5t") }, + { str_lit("arm1136j-s"), str_lit("armv6,dsp,v4t,v5t,v5te,v6") }, + { str_lit("arm1136jf-s"), str_lit("armv6,dsp,fp64,fpregs,fpregs64,slowfpvmlx,v4t,v5t,v5te,v6,vfp2,vfp2sp") }, + { str_lit("arm1156t2-s"), str_lit("armv6t2,dsp,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v8m") }, + { str_lit("arm1156t2f-s"), str_lit("armv6t2,dsp,fp64,fpregs,fpregs64,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v8m,vfp2,vfp2sp") }, + { str_lit("arm1176jz-s"), str_lit("armv6kz,trustzone,v4t,v5t,v5te,v6,v6k") }, + { str_lit("arm1176jzf-s"), str_lit("armv6kz,fp64,fpregs,fpregs64,slowfpvmlx,trustzone,v4t,v5t,v5te,v6,v6k,vfp2,vfp2sp") }, + { str_lit("arm710t"), str_lit("armv4t,v4t") }, + { str_lit("arm720t"), str_lit("armv4t,v4t") }, + { str_lit("arm7tdmi"), str_lit("armv4t,v4t") }, + { str_lit("arm7tdmi-s"), str_lit("armv4t,v4t") }, + { str_lit("arm8"), str_lit("armv4") }, + { str_lit("arm810"), str_lit("armv4") }, + { str_lit("arm9"), str_lit("armv4t,v4t") }, + { str_lit("arm920"), str_lit("armv4t,v4t") }, + { str_lit("arm920t"), str_lit("armv4t,v4t") }, + { str_lit("arm922t"), str_lit("armv4t,v4t") }, + { str_lit("arm926ej-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm940t"), str_lit("armv4t,v4t") }, + { str_lit("arm946e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm966e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm968e-s"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm9e"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("arm9tdmi"), str_lit("armv4t,v4t") }, + { str_lit("cortex-a12"), str_lit("a12,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding") }, + { str_lit("cortex-a15"), str_lit("a15,aclass,armv7-a,avoid-partial-cpsr,d32,db,dont-widen-vmovs,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,muxed-units,perfmon,ret-addr-stack,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vldn-align") }, + { str_lit("cortex-a17"), str_lit("a17,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding") }, + { str_lit("cortex-a32"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a35"), str_lit("a35,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a5"), str_lit("a5,aclass,armv7-a,d32,db,dsp,fp16,fp64,fpregs,fpregs64,mp,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vmlx-forwarding") }, + { str_lit("cortex-a510"), str_lit("aclass,acquire-release,armv9-a,bf16,cortex-a710,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a53"), str_lit("a53,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a55"), str_lit("a55,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a57"), str_lit("a57,aclass,acquire-release,aes,armv8-a,avoid-partial-cpsr,cheap-predicable-cpsr,crc,crypto,d32,db,dsp,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a7"), str_lit("a7,aclass,armv7-a,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-a710"), str_lit("aclass,acquire-release,armv9-a,bf16,cortex-a710,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a72"), str_lit("a72,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fix-cortex-a57-aes-1742098,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a73"), str_lit("a73,aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a75"), str_lit("a75,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a76"), str_lit("a76,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a76ae"), str_lit("a76,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a77"), str_lit("a77,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-a78,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78ae"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-a78ae,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a78c"), str_lit("a78c,aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-a8"), str_lit("a8,aclass,armv7-a,d32,db,dsp,fp64,fpregs,fpregs64,nonpipelined-vfp,perfmon,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-a9"), str_lit("a9,aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,expand-fp-mlx,fp16,fp64,fpregs,fpregs64,mp,muxed-units,neon-fpmovs,perfmon,prefer-vmovsr,ret-addr-stack,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vldn-align,vmlx-forwarding,vmlx-hazards") }, + { str_lit("cortex-m0"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m0plus"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m1"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("cortex-m23"), str_lit("8msecext,acquire-release,armv8-m.base,db,hwdiv,mclass,no-branch-predictor,no-movt,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m,v7clrex,v8m") }, + { str_lit("cortex-m3"), str_lit("armv7-m,db,hwdiv,loop-align,m3,mclass,no-branch-predictor,noarm,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("cortex-m33"), str_lit("8msecext,acquire-release,armv8-m.main,avoid-muls,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m35p"), str_lit("8msecext,acquire-release,armv8-m.main,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m4"), str_lit("armv7e-m,db,dsp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("cortex-m52"), str_lit("8msecext,acquire-release,armv8.1-m.main,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,loop-align,mclass,mve,mve.fp,mve1beat,no-branch-predictor,noarm,pacbti,ras,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m55"), str_lit("8msecext,acquire-release,armv8.1-m.main,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,loop-align,m55,mclass,mve,mve.fp,no-branch-predictor,noarm,ras,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m7"), str_lit("armv7e-m,branch-align-64,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs64,hwdiv,m7,mclass,noarm,thumb-mode,thumb2,use-mipipeliner,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-m85"), str_lit("8msecext,acquire-release,armv8.1-m.main,branch-align-64,db,dsp,fp-armv8d16,fp-armv8d16sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,lob,m85,mclass,mve,mve.fp,noarm,pacbti,ras,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8.1m.main,v8m,v8m.main,vfp2,vfp2sp,vfp3d16,vfp3d16sp,vfp4d16,vfp4d16sp") }, + { str_lit("cortex-r4"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,hwdiv,perfmon,r4,rclass,ret-addr-stack,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("cortex-r4f"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp64,fpregs,fpregs64,hwdiv,perfmon,r4,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r5"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,perfmon,r5,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r52"), str_lit("acquire-release,armv8-r,crc,d32,db,dfb,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,r52,rclass,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-r52plus"), str_lit("acquire-release,armv8-r,crc,d32,db,dfb,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpao,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,r52plus,rclass,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-r7"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,r7,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-r8"), str_lit("armv7-r,avoid-partial-cpsr,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,perfmon,rclass,ret-addr-stack,slow-fp-brcc,slowfpvfmx,slowfpvmlx,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3d16,vfp3d16sp") }, + { str_lit("cortex-x1"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-x1,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cortex-x1c"), str_lit("aclass,acquire-release,aes,armv8.2-a,cortex-x1c,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("cyclone"), str_lit("aclass,acquire-release,aes,armv8-a,avoid-movs-shop,avoid-partial-cpsr,crc,crypto,d32,db,disable-postra-scheduler,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,neonfp,perfmon,ret-addr-stack,sha2,slowfpvfmx,slowfpvmlx,swift,thumb2,trustzone,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,zcz") }, + { str_lit("ep9312"), str_lit("armv4t,v4t") }, + { str_lit("exynos-m3"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dont-widen-vmovs,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("exynos-m4"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dont-widen-vmovs,dotprod,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ras,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("exynos-m5"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dont-widen-vmovs,dotprod,dsp,expand-fp-mlx,exynos,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,fuse-aes,fuse-literals,hwdiv,hwdiv-arm,mp,neon,perfmon,prof-unpr,ras,ret-addr-stack,sha2,slow-fp-brcc,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,splat-vfp-neon,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization,wide-stride-vfp,zcz") }, + { str_lit("generic"), str_lit("") }, + { str_lit("iwmmxt"), str_lit("armv5te,v4t,v5t,v5te") }, + { str_lit("krait"), str_lit("aclass,armv7-a,avoid-partial-cpsr,d32,db,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,krait,muxed-units,perfmon,ret-addr-stack,thumb2,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vldn-align,vmlx-forwarding") }, + { str_lit("kryo"), str_lit("aclass,acquire-release,aes,armv8-a,crc,crypto,d32,db,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,kryo,mp,neon,perfmon,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("mpcore"), str_lit("armv6k,fp64,fpregs,fpregs64,slowfpvmlx,v4t,v5t,v5te,v6,v6k,vfp2,vfp2sp") }, + { str_lit("mpcorenovfp"), str_lit("armv6k,v4t,v5t,v5te,v6,v6k") }, + { str_lit("neoverse-n1"), str_lit("aclass,acquire-release,aes,armv8.2-a,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("neoverse-n2"), str_lit("aclass,acquire-release,armv9-a,bf16,crc,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp16fml,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sb,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8m,v9a,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("neoverse-v1"), str_lit("aclass,acquire-release,aes,armv8.4-a,bf16,crc,crypto,d32,db,dotprod,dsp,fp-armv8,fp-armv8d16,fp-armv8d16sp,fp-armv8sp,fp16,fp64,fpregs,fpregs16,fpregs64,fullfp16,hwdiv,hwdiv-arm,i8mm,mp,neon,perfmon,ras,sha2,thumb2,trustzone,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8,v8.1a,v8.2a,v8.3a,v8.4a,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,virtualization") }, + { str_lit("sc000"), str_lit("armv6-m,db,mclass,no-branch-predictor,noarm,strict-align,thumb-mode,v4t,v5t,v5te,v6,v6m") }, + { str_lit("sc300"), str_lit("armv7-m,db,hwdiv,m3,mclass,no-branch-predictor,noarm,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m") }, + { str_lit("star-mc1"), str_lit("8msecext,acquire-release,armv8-m.main,avoid-muls,db,dsp,fix-cmse-cve-2021-35465,fp-armv8d16sp,fp16,fpregs,hwdiv,loop-align,mclass,no-branch-predictor,noarm,slowfpvfmx,slowfpvmlx,thumb-mode,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,v8m.main,vfp2sp,vfp3d16sp,vfp4d16sp") }, + { str_lit("strongarm"), str_lit("armv4") }, + { str_lit("strongarm110"), str_lit("armv4") }, + { str_lit("strongarm1100"), str_lit("armv4") }, + { str_lit("strongarm1110"), str_lit("armv4") }, + { str_lit("swift"), str_lit("aclass,armv7-a,avoid-movs-shop,avoid-partial-cpsr,d32,db,disable-postra-scheduler,dsp,fp16,fp64,fpregs,fpregs64,hwdiv,hwdiv-arm,mp,neonfp,perfmon,prefer-ishst,prof-unpr,ret-addr-stack,slow-load-D-subreg,slow-odd-reg,slow-vdup32,slow-vgetlni32,slowfpvfmx,slowfpvmlx,swift,thumb2,use-misched,v4t,v5t,v5te,v6,v6k,v6m,v6t2,v7,v7clrex,v8m,vfp2,vfp2sp,vfp3,vfp3d16,vfp3d16sp,vfp3sp,vfp4,vfp4d16,vfp4d16sp,vfp4sp,vmlx-hazards,wide-stride-vfp") }, + { str_lit("xscale"), str_lit("armv5te,v4t,v5t,v5te") }, + // TargetArch_arm64: + { str_lit("a64fx"), str_lit("CONTEXTIDREL2,a64fx,aes,aggressive-fma,arith-bcc-fusion,ccpp,complxnum,crc,el2vmsa,el3,fp-armv8,fullfp16,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rdm,sha2,store-pair-suppress,sve,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("ampere1"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("ampere1a"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1a,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-addsub-2reg-const1,fuse-adrp-add,fuse-aes,fuse-literals,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("ampere1b"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,altnzcv,alu-lsl-fast,am,ampere1b,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,cssc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,fgt,flagm,fp-armv8,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,hcx,i8mm,jsconv,ldp-aligned-only,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,specrestrict,ssbs,store-pair-suppress,stp-aligned-only,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs") }, + { str_lit("apple-a10"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a10,arith-bcc-fusion,arith-cbz-fusion,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,lor,neon,pan,perfmon,rdm,sha2,store-pair-suppress,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a11"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a11,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,lor,lse,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a12"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a13"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a14"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,alternate-sextload-cvt-f32-pattern,altnzcv,am,apple-a14,arith-bcc-fusion,arith-cbz-fusion,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a15"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a15,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a16"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a17"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a17,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a18"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m4,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-f64f64,sme-i16i64,sme2,specrestrict,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-a7"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr64,zcm-gpr64,zcz,zcz-fp-workaround,zcz-gp") }, + { str_lit("apple-a8"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr64,zcm-gpr64,zcz,zcz-fp-workaround,zcz-gp") }, + { str_lit("apple-a9"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr64,zcm-gpr64,zcz,zcz-fp-workaround,zcz-gp") }, + { str_lit("apple-m1"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,alternate-sextload-cvt-f32-pattern,altnzcv,am,apple-a14,arith-bcc-fusion,arith-cbz-fusion,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-m2"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a15,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-m3"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-m4"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-m4,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sme,sme-f64f64,sme-i16i64,sme2,specrestrict,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,vh,wfxt,xs,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s10"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s4"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s5"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,apple-a12,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,neon,pan,pan-rwv,pauth,perfmon,ras,rcpc,rdm,sha2,store-pair-suppress,uaops,v8.1a,v8.2a,v8.3a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s6"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s7"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s8"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,am,apple-a13,arith-bcc-fusion,arith-cbz-fusion,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,fp16fml,fullfp16,fuse-aes,fuse-crypto-eor,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("apple-s9"), str_lit("CONTEXTIDREL2,aes,alternate-sextload-cvt-f32-pattern,altnzcv,am,amvs,apple-a16,arith-bcc-fusion,arith-cbz-fusion,bf16,bti,ccdp,ccpp,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,ecv,el2vmsa,el3,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-crypto-eor,fuse-csel,fuse-literals,hcx,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,specrestrict,ssbs,store-pair-suppress,tlb-rmi,tracev8.4,uaops,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh,zcm-fpr64,zcm-gpr64,zcz,zcz-gp") }, + { str_lit("carmel"), str_lit("CONTEXTIDREL2,aes,carmel,ccpp,crc,el2vmsa,el3,fp-armv8,fullfp16,lor,lse,neon,pan,pan-rwv,ras,rdm,sha2,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cobalt-100"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a320"), str_lit("CONTEXTIDREL2,a320,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a34"), str_lit("a35,aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,sha2,v8a") }, + { str_lit("cortex-a35"), str_lit("a35,aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,sha2,v8a") }, + { str_lit("cortex-a510"), str_lit("CONTEXTIDREL2,a510,altnzcv,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a520"), str_lit("CONTEXTIDREL2,a520,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a520ae"), str_lit("CONTEXTIDREL2,a520ae,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a53"), str_lit("a53,aes,balance-fp-ops,crc,el2vmsa,el3,fp-armv8,fuse-adrp-add,fuse-aes,neon,perfmon,sha2,use-postra-scheduler,v8a") }, + { str_lit("cortex-a55"), str_lit("CONTEXTIDREL2,a55,aes,ccpp,crc,dotprod,el2vmsa,el3,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,ras,rcpc,rdm,sha2,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a57"), str_lit("a57,addr-lsl-slow-14,aes,balance-fp-ops,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,fuse-literals,neon,perfmon,predictable-select-expensive,sha2,use-postra-scheduler,v8a") }, + { str_lit("cortex-a65"), str_lit("CONTEXTIDREL2,a65,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a65ae"), str_lit("CONTEXTIDREL2,a65,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a710"), str_lit("CONTEXTIDREL2,a710,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a715"), str_lit("CONTEXTIDREL2,a715,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-a72"), str_lit("a72,addr-lsl-slow-14,aes,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,fuse-literals,neon,perfmon,predictable-select-expensive,sha2,v8a") }, + { str_lit("cortex-a720"), str_lit("CONTEXTIDREL2,a720,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a720ae"), str_lit("CONTEXTIDREL2,a720ae,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a725"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,cortex-a725,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-a73"), str_lit("a73,addr-lsl-slow-14,aes,crc,el2vmsa,el3,enable-select-opt,fp-armv8,fuse-adrp-add,fuse-aes,neon,perfmon,predictable-select-expensive,sha2,v8a") }, + { str_lit("cortex-a75"), str_lit("CONTEXTIDREL2,a75,addr-lsl-slow-14,aes,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a76"), str_lit("CONTEXTIDREL2,a76,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a76ae"), str_lit("CONTEXTIDREL2,a76,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a77"), str_lit("CONTEXTIDREL2,a77,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,ssbs,uaops,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78"), str_lit("CONTEXTIDREL2,a78,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78ae"), str_lit("CONTEXTIDREL2,a78ae,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-a78c"), str_lit("CONTEXTIDREL2,a78c,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,crc,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-r82"), str_lit("CONTEXTIDREL2,ccdp,ccpp,complxnum,cortex-r82,crc,dit,dotprod,flagm,fp-armv8,fp16fml,fpac,fullfp16,jsconv,lse,neon,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8r") }, + { str_lit("cortex-r82ae"), str_lit("CONTEXTIDREL2,ccdp,ccpp,complxnum,cortex-r82ae,crc,dit,dotprod,flagm,fp-armv8,fp16fml,fpac,fullfp16,jsconv,lse,neon,pan,pan-rwv,pauth,perfmon,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8r") }, + { str_lit("cortex-x1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,cortex-x1,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-x1c"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,cmp-bcc-fusion,cortex-x1,crc,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,lse2,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rcpc-immo,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("cortex-x2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,cortex-x2,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-x3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x3,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("cortex-x4"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x4,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cortex-x925"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x925,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("cyclone"), str_lit("aes,alternate-sextload-cvt-f32-pattern,apple-a7,arith-bcc-fusion,arith-cbz-fusion,disable-latency-sched-heuristic,el2vmsa,el3,fp-armv8,fuse-aes,fuse-crypto-eor,neon,perfmon,sha2,store-pair-suppress,v8a,zcm-fpr64,zcm-gpr64,zcz,zcz-fp-workaround,zcz-gp") }, + { str_lit("exynos-m3"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,exynos-cheap-as-move,exynosm3,force-32bit-jump-tables,fp-armv8,fuse-address,fuse-adrp-add,fuse-aes,fuse-csel,fuse-literals,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,use-postra-scheduler,v8a") }, + { str_lit("exynos-m4"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,dotprod,el2vmsa,el3,exynos-cheap-as-move,exynosm4,force-32bit-jump-tables,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-csel,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh,zcz,zcz-gp") }, + { str_lit("exynos-m5"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,arith-bcc-fusion,arith-cbz-fusion,ccpp,crc,dotprod,el2vmsa,el3,exynos-cheap-as-move,exynosm4,force-32bit-jump-tables,fp-armv8,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-arith-logic,fuse-csel,fuse-literals,lor,lse,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,store-pair-suppress,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh,zcz,zcz-gp") }, + { str_lit("falkor"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,falkor,fp-armv8,neon,perfmon,predictable-select-expensive,rdm,sha2,slow-strqro-store,store-pair-suppress,use-postra-scheduler,v8a,zcz,zcz-gp") }, + { str_lit("fujitsu-monaka"), str_lit("CONTEXTIDREL2,aes,altnzcv,am,amvs,arith-bcc-fusion,bf16,bti,ccdp,ccidx,ccpp,clrbhb,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,faminmax,fgt,flagm,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fptoint,fujitsu-monaka,fullfp16,hbc,hcx,i8mm,jsconv,lor,ls64,lse,lse2,lut,mec,mops,mpam,neon,nmi,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,sha2,sha3,sm4,specres2,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8.8a,v8a,v9.1a,v9.2a,v9.3a,v9a,vh,wfxt,xs") }, + { str_lit("gb10"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,complxnum,cortex-x925,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,spe-eef,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("generic"), str_lit("enable-select-opt,ete,fp-armv8,fuse-adrp-add,fuse-aes,neon,trbe,use-postra-scheduler") }, + { str_lit("grace"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversev2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("kryo"), str_lit("aes,alu-lsl-fast,crc,el2vmsa,el3,fp-armv8,kryo,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,use-postra-scheduler,v8a,zcz,zcz-gp") }, + { str_lit("neoverse-512tvb"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,am,bf16,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fp16fml,fpac,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,neon,neoverse512tvb,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,rand,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,sm4,spe,ssbs,sve,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh") }, + { str_lit("neoverse-e1"), str_lit("CONTEXTIDREL2,aes,ccpp,crc,dotprod,el2vmsa,el3,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,neoversee1,pan,pan-rwv,perfmon,ras,rcpc,rdm,sha2,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("neoverse-n1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,ccpp,crc,dotprod,el2vmsa,el3,enable-select-opt,fp-armv8,fullfp16,fuse-adrp-add,fuse-aes,lor,lse,neon,neoversen1,pan,pan-rwv,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,spe,ssbs,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + { str_lit("neoverse-n2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,ras,rcpc,rcpc-immo,rdm,sb,sel2,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("neoverse-n3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversen3,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("neoverse-v1"), str_lit("CONTEXTIDREL2,addr-lsl-slow-14,aes,alu-lsl-fast,am,bf16,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,enable-select-opt,flagm,fp-armv8,fp16fml,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,neon,neoversev1,no-sve-fp-ld1r,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,rand,ras,rcpc,rcpc-immo,rdm,sel2,sha2,sha3,sm4,spe,ssbs,sve,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh") }, + { str_lit("neoverse-v2"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,avoid-ldapur,bf16,bti,ccdp,ccidx,ccpp,cmp-bcc-fusion,complxnum,crc,disable-latency-sched-heuristic,dit,dotprod,el2vmsa,el3,enable-select-opt,ete,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,i8mm,jsconv,lor,lse,lse2,mpam,mte,neon,neoversev2,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,spe,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8a,v9a,vh") }, + { str_lit("neoverse-v3"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,brbe,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,ls64,lse,lse2,mpam,mte,neon,neoversev3,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("neoverse-v3ae"), str_lit("CONTEXTIDREL2,altnzcv,alu-lsl-fast,am,amvs,avoid-ldapur,bf16,brbe,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,fgt,flagm,fp-armv8,fp16fml,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,ls64,lse,lse2,mpam,mte,neon,neoversev3AE,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,spe,spe-eef,specrestrict,ssbs,sve,sve-bitperm,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("olympus"), str_lit("CONTEXTIDREL2,aes,altnzcv,alu-lsl-fast,am,amvs,bf16,brbe,bti,ccdp,ccidx,ccpp,chk,cmp-bcc-fusion,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,ete,faminmax,fgt,flagm,fp-armv8,fp16fml,fp8,fp8dot2,fp8dot4,fp8fma,fpac,fptoint,fullfp16,fuse-adrp-add,fuse-aes,hcx,i8mm,jsconv,lor,ls64,lse,lse2,lut,mec,mpam,mte,neon,nv,olympus,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,predres,rand,ras,rcpc,rcpc-immo,rdm,rme,sb,sel2,sha2,sha3,sm4,spe,spe-eef,specrestrict,ssbs,sve,sve-aes,sve-bitperm,sve-sha3,sve-sm4,sve2,tlb-rmi,tracev8.4,trbe,uaops,use-fixed-over-scalable-if-equal-cost,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8.7a,v8a,v9.1a,v9.2a,v9a,vh,wfxt,xs") }, + { str_lit("oryon-1"), str_lit("CONTEXTIDREL2,aes,altnzcv,am,amvs,bf16,bti,ccdp,ccidx,ccpp,complxnum,crc,dit,dotprod,ecv,el2vmsa,el3,enable-select-opt,fgt,flagm,fp-armv8,fp16fml,fptoint,fullfp16,fuse-address,fuse-adrp-add,fuse-aes,fuse-crypto-eor,i8mm,jsconv,lor,lse,lse2,mpam,neon,nv,oryon-1,pan,pan-rwv,pauth,perfmon,predres,rand,ras,rcpc,rcpc-immo,rdm,sb,sel2,sha2,sha3,sm4,spe,specrestrict,ssbs,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8.5a,v8.6a,v8a,vh") }, + { str_lit("saphira"), str_lit("CONTEXTIDREL2,aes,alu-lsl-fast,am,ccidx,ccpp,complxnum,crc,dit,dotprod,el2vmsa,el3,flagm,fp-armv8,jsconv,lor,lse,lse2,mpam,neon,nv,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rcpc-immo,rdm,saphira,sel2,sha2,spe,store-pair-suppress,tlb-rmi,tracev8.4,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8.4a,v8a,vh,zcz,zcz-gp") }, + { str_lit("thunderx"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderx,use-postra-scheduler,v8a") }, + { str_lit("thunderx2t99"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,arith-bcc-fusion,crc,el2vmsa,el3,fp-armv8,lor,lse,neon,pan,predictable-select-expensive,rdm,sha2,store-pair-suppress,thunderx2t99,use-postra-scheduler,v8.1a,v8a,vh") }, + { str_lit("thunderx3t110"), str_lit("CONTEXTIDREL2,aes,aggressive-fma,arith-bcc-fusion,balance-fp-ops,ccidx,ccpp,complxnum,crc,el2vmsa,el3,fp-armv8,jsconv,lor,lse,neon,pan,pan-rwv,pauth,perfmon,predictable-select-expensive,ras,rcpc,rdm,sha2,store-pair-suppress,strict-align,thunderx3t110,uaops,use-postra-scheduler,v8.1a,v8.2a,v8.3a,v8a,vh") }, + { str_lit("thunderxt81"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt81,use-postra-scheduler,v8a") }, + { str_lit("thunderxt83"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt83,use-postra-scheduler,v8a") }, + { str_lit("thunderxt88"), str_lit("aes,crc,el2vmsa,el3,fp-armv8,neon,perfmon,predictable-select-expensive,sha2,store-pair-suppress,thunderxt88,use-postra-scheduler,v8a") }, + { str_lit("tsv110"), str_lit("CONTEXTIDREL2,aes,ccpp,complxnum,crc,dotprod,el2vmsa,el3,fp-armv8,fp16fml,fullfp16,fuse-aes,jsconv,lor,lse,neon,pan,pan-rwv,perfmon,ras,rdm,sha2,spe,store-pair-suppress,tsv110,uaops,use-postra-scheduler,v8.1a,v8.2a,v8a,vh") }, + // TargetArch_wasm32: + { str_lit("bleeding-edge"), str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call") }, + { str_lit("generic"), str_lit("bulk-memory,bulk-memory-opt,call-indirect-overlong,multivalue,mutable-globals,nontrapping-fptoint,reference-types,sign-ext") }, + { str_lit("lime1"), str_lit("bulk-memory-opt,call-indirect-overlong,extended-const,multivalue,mutable-globals,nontrapping-fptoint,sign-ext") }, + { str_lit("mvp"), str_lit("") }, + // TargetArch_wasm64p32: + { str_lit("bleeding-edge"), str_lit("atomics,bulk-memory,bulk-memory-opt,call-indirect-overlong,exception-handling,extended-const,fp16,multimemory,multivalue,mutable-globals,nontrapping-fptoint,reference-types,relaxed-simd,sign-ext,simd128,tail-call") }, + { str_lit("generic"), str_lit("bulk-memory,bulk-memory-opt,call-indirect-overlong,multivalue,mutable-globals,nontrapping-fptoint,reference-types,sign-ext") }, + { str_lit("lime1"), str_lit("bulk-memory-opt,call-indirect-overlong,extended-const,multivalue,mutable-globals,nontrapping-fptoint,sign-ext") }, + { str_lit("mvp"), str_lit("") }, + // TargetArch_riscv64: + { str_lit("andes-45-series"), str_lit("andes45,no-default-unroll,short-forward-branch-opt,use-postra-scheduler") }, + { str_lit("andes-a25"), str_lit("32bit,a,c,d,f,i,m,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-a45"), str_lit("32bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax25"), str_lit("64bit,a,c,d,f,i,m,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax45"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-ax45mpv"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,use-postra-scheduler,v,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvl128b,zvl32b,zvl64b") }, + { str_lit("andes-n45"), str_lit("32bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("andes-nx45"), str_lit("64bit,a,andes45,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,use-postra-scheduler,xandesperf,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("generic"), str_lit("64bit,i,optimized-nf2-segment-load-store") }, + { str_lit("generic-ooo"), str_lit("") }, + { str_lit("generic-rv32"), str_lit("32bit,i,optimized-nf2-segment-load-store") }, + { str_lit("generic-rv64"), str_lit("64bit,i,optimized-nf2-segment-load-store") }, + { str_lit("mips-p8700"), str_lit("64bit,a,c,d,f,i,m,mips-p8700,xmipscbop,xmipscmov,xmipslsp,zaamo,zalrsc,zba,zbb,zca,zicsr,zifencei,zmmul") }, + { str_lit("rocket"), str_lit("") }, + { str_lit("rocket-rv32"), str_lit("32bit,i,zicsr,zifencei") }, + { str_lit("rocket-rv64"), str_lit("64bit,i,zicsr,zifencei") }, + { str_lit("rp2350-hazard3"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zba,zbb,zbkb,zbs,zca,zcb,zcmp,zicsr,zifencei,zmmul") }, + { str_lit("sifive-7-series"), str_lit("no-default-unroll,short-forward-branch-opt,sifive7,use-postra-scheduler") }, + { str_lit("sifive-e20"), str_lit("32bit,c,i,m,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e21"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e24"), str_lit("32bit,a,c,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e31"), str_lit("32bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e34"), str_lit("32bit,a,c,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-e76"), str_lit("32bit,a,c,f,i,m,no-default-unroll,short-forward-branch-opt,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-p450"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul") }, + { str_lit("sifive-p470"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,xsifivecdiscarddlone,xsifivecflushdlone,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-p550"), str_lit("64bit,a,auipc-addi-fusion,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zba,zbb,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-p670"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,za64rs,zaamo,zalrsc,zba,zbb,zbs,zca,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicsr,zifencei,zihintntl,zihintpause,zihpm,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-p870"), str_lit("64bit,a,auipc-addi-fusion,b,c,conditional-cmv-fusion,d,f,i,lui-addi-fusion,m,no-default-unroll,no-sink-splat-operands,supm,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,vxrm-pipeline-flush,za64rs,zaamo,zalrsc,zama16b,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkr,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvknc,zvkned,zvkng,zvknhb,zvks,zvksc,zvksed,zvksg,zvksh,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("sifive-s21"), str_lit("64bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s51"), str_lit("64bit,a,c,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s54"), str_lit("64bit,a,c,d,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-s76"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zihintpause,zmmul") }, + { str_lit("sifive-u54"), str_lit("64bit,a,c,d,f,i,m,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-u74"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,short-forward-branch-opt,sifive7,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("sifive-x280"), str_lit("64bit,a,c,d,dlen-factor-2,f,i,m,no-default-unroll,optimized-nf2-segment-load-store,optimized-zero-stride-load,short-forward-branch-opt,sifive7,use-postra-scheduler,v,vl-dependent-latency,zaamo,zalrsc,zba,zbb,zca,zfh,zfhmin,zicsr,zifencei,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvl128b,zvl256b,zvl32b,zvl512b,zvl64b") }, + { str_lit("sifive-x390"), str_lit("64bit,a,b,c,d,dlen-factor-2,experimental-zicfilp,experimental-zicfiss,f,i,m,no-default-unroll,optimized-nf2-segment-load-store,optimized-zero-stride-load,short-forward-branch-opt,sifive7,use-postra-scheduler,v,vl-dependent-latency,xsifivecdiscarddlone,xsifivecflushdlone,za64rs,zaamo,zalrsc,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkr,zkt,zmmul,zvbb,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkt,zvl1024b,zvl128b,zvl256b,zvl32b,zvl512b,zvl64b") }, + { str_lit("spacemit-x60"), str_lit("64bit,a,b,c,d,dlen-factor-2,f,i,m,optimized-nf2-segment-load-store,optimized-nf3-segment-load-store,optimized-nf4-segment-load-store,ssccptr,sscofpmf,sscounterenw,sstc,sstvala,sstvecd,svade,svbare,svinval,svnapot,svpbmt,unaligned-scalar-mem,v,vxrm-pipeline-flush,za64rs,zaamo,zalrsc,zba,zbb,zbc,zbkc,zbs,zca,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintpause,zihpm,zkt,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvkt,zvl128b,zvl256b,zvl32b,zvl64b") }, + { str_lit("syntacore-scr1-base"), str_lit("32bit,c,i,no-default-unroll,zca,zicsr,zifencei") }, + { str_lit("syntacore-scr1-max"), str_lit("32bit,c,i,m,no-default-unroll,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr3-rv32"), str_lit("32bit,c,i,m,no-default-unroll,use-postra-scheduler,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr3-rv64"), str_lit("64bit,a,c,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr4-rv32"), str_lit("32bit,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr4-rv64"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr5-rv32"), str_lit("32bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr5-rv64"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,zaamo,zalrsc,zca,zicsr,zifencei,zmmul") }, + { str_lit("syntacore-scr7"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,use-postra-scheduler,v,zaamo,zalrsc,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zicsr,zifencei,zkn,zknd,zkne,zknh,zmmul,zve32f,zve32x,zve64d,zve64f,zve64x,zvl128b,zvl32b,zvl64b") }, + { str_lit("tt-ascalon-d8"), str_lit("64bit,a,b,c,d,f,h,i,log-vrgather,m,no-default-unroll,optimized-zero-stride-load,sha,shcounterenw,shgatpa,shtvala,shvsatpa,shvstvala,shvstvecd,smaia,ssaia,ssccptr,sscofpmf,sscounterenw,ssnpm,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svbare,svinval,svnapot,svpbmt,unaligned-scalar-mem,unaligned-vector-mem,use-postra-scheduler,v,za64rs,zaamo,zalrsc,zawrs,zba,zbb,zbs,zca,zcb,zcmop,zfa,zfbfmin,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkt,zmmul,zvbb,zvbc,zve32f,zve32x,zve64d,zve64f,zve64x,zvfbfmin,zvfbfwma,zvfh,zvfhmin,zvkb,zvkg,zvkn,zvkned,zvkng,zvknhb,zvkt,zvl128b,zvl256b,zvl32b,zvl64b") }, + { str_lit("veyron-v1"), str_lit("64bit,a,auipc-addi-fusion,c,d,f,i,ld-add-fusion,lui-addi-fusion,m,shifted-zextw-fusion,ventana-veyron,xventanacondops,zaamo,zalrsc,zba,zbb,zbc,zbs,zca,zexth-fusion,zextw-fusion,zicbom,zicbop,zicboz,zicntr,zicsr,zifencei,zihintpause,zihpm,zmmul") }, + { str_lit("xiangshan-kunminghu"), str_lit("64bit,a,b,c,d,f,h,i,m,no-default-unroll,sha,shcounterenw,shgatpa,shifted-zextw-fusion,shtvala,shvsatpa,shvstvala,shvstvecd,smaia,smcsrind,smdbltrp,smmpm,smnpm,smrnmi,smstateen,ssaia,ssccptr,sscofpmf,sscounterenw,sscsrind,ssdbltrp,ssnpm,sspm,ssstateen,ssstrict,sstc,sstvala,sstvecd,ssu64xl,supm,svade,svbare,svinval,svnapot,svpbmt,v,za64rs,zaamo,zacas,zalrsc,zawrs,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zcb,zcmop,zexth-fusion,zextw-fusion,zfa,zfh,zfhmin,zic64b,zicbom,zicbop,zicboz,ziccamoa,ziccif,zicclsm,ziccrse,zicntr,zicond,zicsr,zifencei,zihintntl,zihintpause,zihpm,zimop,zkn,zknd,zkne,zknh,zks,zksed,zksh,zkt,zmmul,zvbb,zve32f,zve32x,zve64d,zve64f,zve64x,zvfh,zvfhmin,zvkb,zvkt,zvl128b,zvl32b,zvl64b") }, + { str_lit("xiangshan-nanhu"), str_lit("64bit,a,c,d,f,i,m,no-default-unroll,shifted-zextw-fusion,svinval,zaamo,zalrsc,zba,zbb,zbc,zbkb,zbkc,zbkx,zbs,zca,zexth-fusion,zextw-fusion,zicbom,zicboz,zicsr,zifencei,zkn,zknd,zkne,zknh,zksed,zksh,zmmul") }, +}; +#elif LLVM_VERSION_MAJOR == 20 // Generated with the featuregen script in `misc/featuregen` gb_global String target_microarch_list[TargetArch_COUNT] = { // TargetArch_Invalid: diff --git a/src/bundle_command.cpp b/src/bundle_command.cpp index cd0cd589f..c19f29220 100644 --- a/src/bundle_command.cpp +++ b/src/bundle_command.cpp @@ -83,7 +83,7 @@ i32 bundle_android(String original_init_directory) { return 1; } - int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + int *dir_numbers = temporary_alloc_array(possible_valid_dirs.count); char buf[1024] = {}; for_array(i, possible_valid_dirs) { @@ -186,7 +186,11 @@ i32 bundle_android(String original_init_directory) { gb_string_clear(cmd); cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); +#if defined(GB_SYSTEM_WINDOWS) + cmd = gb_string_appendc(cmd, "apksigner.bat"); +#else cmd = gb_string_appendc(cmd, "apksigner"); +#endif cmd = gb_string_appendc(cmd, " sign"); String keystore = normalize_path(temporary_allocator(), build_context.android_keystore, NIX_SEPARATOR_STRING); diff --git a/src/cached.cpp b/src/cached.cpp index efdadce7b..61b5d01b4 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -231,7 +231,7 @@ Array cache_gather_envs() { wchar_t *curr_string = strings; while (curr_string && *curr_string) { - String16 wstr = make_string16_c(curr_string); + String16 wstr = make_string16_c(cast(u16 *)curr_string); curr_string += wstr.len+1; String str = string16_to_string(temporary_allocator(), wstr); if (string_starts_with(str, str_lit("CURR_DATE_TIME="))) { diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index dd9896927..90048f004 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1,17 +1,31 @@ typedef bool (BuiltinTypeIsProc)(Type *t); +gb_internal int enum_constant_entity_cmp(void const* a, void const* b) { + Entity const *ea = *(cast(Entity const **)a); + Entity const *eb = *(cast(Entity const **)b); + GB_ASSERT(ea->kind == Entity_Constant && eb->kind == Entity_Constant); + GB_ASSERT(ea->Constant.value.kind == ExactValue_Integer && eb->Constant.value.kind == ExactValue_Integer); + + return big_int_cmp(&ea->Constant.value.value_integer, &eb->Constant.value.value_integer); +} + gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end - BuiltinProc__type_simple_boolean_begin] = { nullptr, // BuiltinProc__type_simple_boolean_begin is_type_boolean, + is_type_bit_field, is_type_integer, is_type_rune, is_type_float, is_type_complex, is_type_quaternion, is_type_string, + is_type_string16, + is_type_cstring, + is_type_cstring16, is_type_typeid, is_type_any, + is_type_endian_platform, is_type_endian_little, is_type_endian_big, @@ -22,7 +36,8 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_indexable, is_type_sliceable, is_type_comparable, - is_type_simple_compare, + is_type_simple_compare, // easily compared using memcmp + is_type_nearly_simple_compare, // easily compared using memcmp (including floats) is_type_dereferenceable, is_type_valid_for_keys, is_type_valid_for_matrix_elems, @@ -34,7 +49,6 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_enumerated_array, is_type_slice, is_type_dynamic_array, - is_type_map, is_type_struct, is_type_union, @@ -43,6 +57,10 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_bit_set, is_type_simd_vector, is_type_matrix, + is_type_raw_union, + is_type_fixed_capacity_dynamic_array, + + is_type_internally_pointer_like, is_type_polymorphic_record_specialized, is_type_polymorphic_record_unspecialized, @@ -147,6 +165,11 @@ gb_internal bool does_require_msgSend_stret(Type *return_type) { if (return_type == nullptr) { return false; } + + if (build_context.metrics.os != TargetOs_darwin) { + return false; + } + if (build_context.metrics.arch == TargetArch_i386 || build_context.metrics.arch == TargetArch_amd64) { i64 struct_limit = type_size_of(t_uintptr) << 1; return type_size_of(return_type) > struct_limit; @@ -193,7 +216,7 @@ gb_internal ObjcMsgKind get_objc_proc_kind(Type *return_type) { return ObjcMsg_normal; } -gb_internal void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_type, Slice param_types) { +void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_type, Slice param_types) { ObjcMsgKind kind = get_objc_proc_kind(return_type); Scope *scope = create_scope(c->info, nullptr); @@ -231,6 +254,12 @@ gb_internal void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_t try_to_add_package_dependency(c, "runtime", "objc_msgSend_fpret"); try_to_add_package_dependency(c, "runtime", "objc_msgSend_fp2ret"); try_to_add_package_dependency(c, "runtime", "objc_msgSend_stret"); + + Slice args = call->CallExpr.args; + if (args.count > 0 && args[0]->tav.objc_super_target) { + try_to_add_package_dependency(c, "runtime", "objc_msgSendSuper2"); + try_to_add_package_dependency(c, "runtime", "objc_msgSendSuper2_stret"); + } } gb_internal bool is_constant_string(CheckerContext *c, String const &builtin_name, Ast *expr, String *name_) { @@ -337,7 +366,7 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan } isize const arg_offset = 1; - auto param_types = slice_make(permanent_allocator(), ce->args.count-arg_offset); + auto param_types = permanent_slice_make(ce->args.count-arg_offset); param_types[0] = t_objc_id; param_types[1] = sel_type; @@ -440,6 +469,400 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan return true; } break; + + case BuiltinProc_objc_block: + { + // NOTE(harold): The last argument specified in the call is the handler proc, + // any other arguments before it are capture by-copy arguments. + auto param_operands = permanent_slice_make(ce->args.count); + + isize capture_arg_count = ce->args.count - 1; + + // NOTE(harold): The first argument is already checked at check_builtin_procedure(). + // Checking again would invalidate the Entity -> Value map for direct arguments if it's the handler proc. + param_operands[0] = *operand; + + for (isize i = 0; i < ce->args.count-1; i++) { + Operand x = {}; + check_expr(c, &x, ce->args[i]); + + switch (x.mode) { + case Addressing_Value: + case Addressing_Context: + case Addressing_Variable: + case Addressing_Constant: + param_operands[i] = x; + break; + + default: + gbString e = expr_to_string(x.expr); + gbString t = type_to_string(x.type); + error(x.expr, "'%.*s' capture arguments must be values, but got %s of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + } + + // Validate handler proc + Operand handler = {}; + + if (capture_arg_count == 0) { + // It's already been checked and assigned + handler = param_operands[0]; + } else { + check_expr_or_type(c, &handler, ce->args[capture_arg_count]); + param_operands[capture_arg_count] = handler; + } + + if (!is_operand_value(handler) || handler.type->kind != Type_Proc) { + gbString e = expr_to_string(handler.expr); + gbString t = type_to_string(handler.type); + error(handler.expr, "'%.*s' expected a procedure, but got '%s' of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + + Ast *handler_node = unparen_expr(handler.expr); + + // Only direct reference to procs are allowed + switch (handler_node->kind) { + case Ast_ProcLit: break; // ok + case Ast_Ident: { + auto& ident = handler_node->Ident; + + if (ident.entity == nullptr) { + error(handler.expr, "'%.*s' failed to resolve entity from expression", LIT(builtin_name)); + return false; + } + + if (ident.entity.load()->kind != Entity_Procedure) { + gbString e = expr_to_string(handler_node); + + ERROR_BLOCK(); + error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name)); + if(ident.entity.load()->kind == Entity_Variable) { + error_line("\tSuggestion: Variables referencing a procedure are not allowed, they are not a direct procedure reference."); + } else { + error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e); // NOTE(harold): Is this case possible to hit? + } + error_line("\n\t Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name)); + + gb_string_free(e); + return false; + } + } break; + + default: { + gbString e = expr_to_string(handler_node); + ERROR_BLOCK(); + error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name)); + if( handler_node->kind == Ast_CallExpr) { + error_line("\tSuggestion: Do not use a procedure returned from another procedure."); + } else { + error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e); + } + error_line("\n\t Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name)); + + gb_string_free(e); + } return false; + } // End switch + + auto& handler_type_proc = handler.type->Proc; + + if (capture_arg_count > handler_type_proc.param_count) { + error(handler.expr, "'%.*s' captured arguments exceeded the handler's parameter count", LIT(builtin_name)); + return false; + } + + // If the handler proc is odin calling convention, but there must be a context defined in this scope. + if (handler_type_proc.calling_convention == ProcCC_Odin) { + if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { + ERROR_BLOCK(); + error(handler.expr, "The handler procedure for '%.*s' requires a context, but no context is defined in the current scope", LIT(builtin_name)); + error_line("\tSuggestion: 'context = runtime.default_context()', or use the \"c\" calling convention for the handler procedure"); + return false; + } + } + + // At most a single return value is supported + if (handler_type_proc.result_count > 1) { + error(handler_type_proc.node->ProcType.results, "Handler procedures for '%.*s' cannot have multiple return values", LIT(builtin_name)); + return false; + } + + // Ensure that captured args are assignable to the handler's corresponding capture params + if (handler_type_proc.param_count > 0) { + auto& handler_param_types = handler.type->Proc.params->Tuple.variables; + Slice handler_capture_param_types = slice(handler_param_types, handler_param_types.count - capture_arg_count, handler_param_types.count); + + for (isize i = 0; i < capture_arg_count; i++) { + Operand op = param_operands[i]; + if (!check_is_assignable_to(c, &op, handler_capture_param_types[i]->type)) { + gbString e = expr_to_string(op.expr); + gbString src = type_to_string(op.type); + gbString dst = type_to_string(handler_capture_param_types[i]->type); + error(op.expr, "'%.*s' captured value '%s' of type '%s' is not assignable to type '%s'", LIT(builtin_name), e, src, dst); + gb_string_free(e); + gb_string_free(src); + gb_string_free(dst); + return false; + } + } + } + + ProcCallingConvention cc = handler_type_proc.calling_convention; + switch (cc) { + case ProcCC_Odin: + case ProcCC_Contextless: + case ProcCC_CDecl: + break; // ok + default: + ERROR_BLOCK(); + + error(handler.expr, "'%.*s' Invalid calling convention for block procedure.", LIT(builtin_name)); + error_line("\tSuggestion: Do not specify a calling convention ot else use \"c\" or \"cotextless\""); + return false; + } + + if (handler_type_proc.is_polymorphic) { + error(handler.expr, "'%.*s' Unspecialized polymorphic procedures are not allowed.", LIT(builtin_name)); + return false; + } + + // Create the specialized Objc_Block type that this intrinsic will return + Token ident = {}; + ident.kind = Token_Ident; + ident.string = str_lit("Objc_Block"); + ident.pos = ast_token(call).pos; + + Token l_paren = {}; + l_paren.kind = Token_OpenParen; + l_paren.string = str_lit("("); + l_paren.pos = ident.pos; + + Token r_paren = {}; + r_paren.kind = Token_CloseParen; + l_paren.string = str_lit(")"); + r_paren.pos = ident.pos; + + // Remove the capture args from the resulting Objc_Block type signature + Ast* handler_proc_type_copy = clone_ast(handler_type_proc.node); + handler_proc_type_copy->ProcType.params->FieldList.list.count -= capture_arg_count; + + // Make sure the Objc_Block's specialized proc is always "c" calling conv, + // even if we have a context, as the invoker is always "c". + // This allows us to have compatibility with the target block types with either calling convention used. + handler_proc_type_copy->ProcType.calling_convention = ProcCC_CDecl; + + Array poly_args = {}; + array_init(&poly_args, permanent_allocator(), 1, 1); + poly_args[0] = handler_proc_type_copy; + + + Type *t_Objc_Block = find_core_type(c->checker, str_lit("Objc_Block")); + Operand poly_op = {}; + poly_op.type = t_Objc_Block; + poly_op.mode = Addressing_Type; + + Ast *poly_call = ast_call_expr(nullptr, ast_ident(nullptr, ident), poly_args, l_paren, r_paren, {}); + + auto err = check_polymorphic_record_type(c, &poly_op, poly_call); + + if (err != 0) { + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + error(handler.expr, "'%.*s' failed to determine resulting Objc_Block handler procedure", LIT(builtin_name)); + return false; + } + + GB_ASSERT(poly_op.type != t_Objc_Block); + GB_ASSERT(poly_op.mode == Addressing_Type); + + bool is_global_block = capture_arg_count == 0 && handler_type_proc.calling_convention != ProcCC_Odin; + if (is_global_block) { + try_to_add_package_dependency(c, "runtime", "_NSConcreteGlobalBlock"); + } else { + try_to_add_package_dependency(c, "runtime", "_NSConcreteStackBlock"); + } + + *operand = poly_op; + operand->type = alloc_type_pointer(operand->type); + operand->mode = Addressing_Value; + return true; + } break; + + case BuiltinProc_objc_super: + { + // Must be a pointer to an Objective-C object. + Type *objc_obj = operand->type; + if (!is_type_objc_ptr_to_object(objc_obj)) { + gbString e = expr_to_string(operand->expr); + gbString t = type_to_string(objc_obj); + error(operand->expr, "'%.*s' expected a pointer to an Objective-C object, but got '%s' of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + + if (operand->mode != Addressing_Value && operand->mode != Addressing_Variable) { + gbString e = expr_to_string(operand->expr); + gbString t = type_to_string(operand->type); + error(operand->expr, "'%.*s' expression '%s', of type %s, must be a value or variable.", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + + Type *obj_type = type_deref(objc_obj); + GB_ASSERT(obj_type->kind == Type_Named); + + // NOTE(harold) Track original type before transforming it to the superclass. + // This is needed because objc_msgSendSuper2 must start its search on the subclass, not the superclass. + call->tav.objc_super_target = obj_type; + + // The superclass type must be known at compile time. We require this so that the selector method expressions + // methods are resolved to the superclass's methods instead of the subclass's. + Type *superclass = obj_type->Named.type_name->TypeName.objc_superclass; + if (superclass == nullptr) { + gbString t = type_to_string(obj_type); + error(operand->expr, "'%.*s' target object '%.*s' does not have an Objective-C superclass. One must be set via the @(objc_superclass) attribute", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + GB_ASSERT(superclass->Named.type_name->TypeName.objc_class_name.len > 0); + + operand->type = alloc_type_pointer(superclass); + return true; + + } break; + } +} + +gb_internal bool check_builtin_c_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) { + String const &builtin_name = builtin_procs[id].name; + + ast_node(ce, CallExpr, call); + switch (id) { + default: + GB_PANIC("Implement objective built-in procedure: %.*s", LIT(builtin_name)); + return false; + + case BuiltinProc_c_va_start: { + Operand list = {}; + check_expr(c, &list, ce->args[0]); + if (list.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(list.type, t_c_va_list_ptr)) { + gbString lpt = type_to_string(t_c_va_list_ptr); + gbString t = type_to_string(list.type); + error(list.expr, "'%.*s' expected a value of type %s, got type %s", LIT(builtin_name), lpt, t); + gb_string_free(t); + gb_string_free(lpt); + return false; + } + + Operand args = {}; + check_expr(c, &args, ce->args[1]); + if (list.mode == Addressing_Invalid) { + return false; + } + Entity *e = entity_of_node(args.expr); + if (e == nullptr || (e->flags & EntityFlag_CVarArg) == 0) { + error(list.expr, "'%.*s' expected a `#c_vararg` parameter", LIT(builtin_name)); + } + + operand->mode = Addressing_NoValue; + operand->type = nullptr; + return true; + + } break; + + case BuiltinProc_c_va_end: { + Operand list = {}; + check_expr(c, &list, ce->args[0]); + if (list.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(list.type, t_c_va_list_ptr)) { + gbString lpt = type_to_string(t_c_va_list_ptr); + gbString t = type_to_string(list.type); + error(list.expr, "'%.*s' expected a value of type %s, got type %s", LIT(builtin_name), lpt, t); + gb_string_free(t); + gb_string_free(lpt); + return false; + } + + operand->mode = Addressing_NoValue; + operand->type = nullptr; + return true; + + } break; + + case BuiltinProc_c_va_copy: { + Operand dst = {}; + check_expr(c, &dst, ce->args[0]); + if (dst.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(dst.type, t_c_va_list_ptr)) { + gbString lpt = type_to_string(t_c_va_list_ptr); + gbString t = type_to_string(dst.type); + error(dst.expr, "'%.*s' expected a value of type %s, got type %s", LIT(builtin_name), lpt, t); + gb_string_free(t); + gb_string_free(lpt); + return false; + } + + Operand src = {}; + check_expr(c, &src, ce->args[1]); + if (src.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(src.type, t_c_va_list_ptr)) { + gbString lpt = type_to_string(t_c_va_list_ptr); + gbString t = type_to_string(src.type); + error(src.expr, "'%.*s' expected a value of type %s, got type %s", LIT(builtin_name), lpt, t); + gb_string_free(t); + gb_string_free(lpt); + return false; + } + + operand->mode = Addressing_NoValue; + operand->type = nullptr; + return true; + + } break; + + case BuiltinProc_c_va_arg: { + Operand list = {}; + check_expr(c, &list, ce->args[0]); + if (list.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(list.type, t_c_va_list_ptr)) { + gbString lpt = type_to_string(t_c_va_list_ptr); + gbString t = type_to_string(list.type); + error(list.expr, "'%.*s' expected a value of type %s, got type %s", LIT(builtin_name), lpt, t); + gb_string_free(t); + gb_string_free(lpt); + return false; + } + + + Type *type = check_type(c, ce->args[1]); + if (type == nullptr || type == t_invalid) { + error(ce->args[1], "'%.*s' expected a type as the second parameter to intrinsics.%.*s", LIT(builtin_name)); + return false; + } + + operand->mode = Addressing_Value; + operand->type = type; + return true; + } break; } } @@ -485,6 +908,8 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan case BuiltinProc_simd_div: case BuiltinProc_simd_min: case BuiltinProc_simd_max: + case BuiltinProc_simd_pairwise_add: + case BuiltinProc_simd_pairwise_sub: { Operand x = {}; Operand y = {}; @@ -591,14 +1016,24 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan Operand x = {}; Operand y = {}; check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; - check_expr_with_type_hint(c, &y, ce->args[1], x.type); if (y.mode == Addressing_Invalid) return false; - convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; + check_expr(c, &y, ce->args[1]); if (y.mode == Addressing_Invalid) return false; if (!is_type_simd_vector(x.type)) { error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); return false; } if (!is_type_simd_vector(y.type)) { - error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + if (is_type_untyped(y.type) || is_type_unsigned(y.type)) { + Type *rhs_type = type_unsigned_equivalent(x.type); + convert_to_typed(c, &y, rhs_type); if (y.mode == Addressing_Invalid) return false; + } else { + convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; + } + } + + if (!is_type_simd_vector(y.type)) { + gbString s = type_to_string(y.type); + error(y.expr, "'%.*s' expected a simd vector type or unsigned integer, got %s", LIT(builtin_name), s); + gb_string_free(s); return false; } GB_ASSERT(x.type->kind == Type_SimdVector); @@ -740,7 +1175,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan // masked_load (ptr: rawptr, values: #simd[N]T, mask: #simd[N]int_or_bool) -> #simd[N]T // masked_store(ptr: rawptr, values: #simd[N]T, mask: #simd[N]int_or_bool) - // masked_expand_load (ptr: rawptr, values: #simd[N]T, mask: #simd[N]int_or_bool) -> #simd[N]T + // masked_expand_load (ptr: rawptr, values: #simd[N]T, mask: #simd[N]int_or_bool) -> #simd[N]T // masked_compress_store(ptr: rawptr, values: #simd[N]T, mask: #simd[N]int_or_bool) Operand ptr = {}; @@ -970,9 +1405,9 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return false; } Type *elem = base_array_type(x.type); - if (!is_type_boolean(elem)) { + if (!is_type_boolean(elem) && !is_type_integer(elem)) { gbString xs = type_to_string(x.type); - error(x.expr, "'%.*s' expected a #simd type with a boolean element, got '%s'", LIT(builtin_name), xs); + error(x.expr, "'%.*s' expected a #simd type with a boolean or an integer element, got '%s'", LIT(builtin_name), xs); gb_string_free(xs); return false; } @@ -1091,6 +1526,35 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_odd_even: + { + Operand x = {}; + Operand y = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &y, ce->args[1], x.type); if (y.mode == Addressing_Invalid) return false; + convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + if (!is_type_simd_vector(y.type)) { + error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + if (!are_types_identical(x.type, y.type)) { + gbString xs = type_to_string(x.type); + gbString ys = type_to_string(y.type); + error(x.expr, "'%.*s' expected 2 arguments of the same type, got '%s' vs '%s'", LIT(builtin_name), xs, ys); + gb_string_free(ys); + gb_string_free(xs); + return false; + } + + operand->mode = Addressing_Value; + operand->type = x.type; + return true; + } + case BuiltinProc_simd_select: { Operand cond = {}; @@ -1110,8 +1574,8 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan Operand x = {}; Operand y = {}; - check_expr(c, &x, ce->args[1]); if (x.mode == Addressing_Invalid) return false; - check_expr_with_type_hint(c, &y, ce->args[2], x.type); if (y.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &x, ce->args[1], type_hint); if (x.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &y, ce->args[2], x.type); if (y.mode == Addressing_Invalid) return false; convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false; if (!is_type_simd_vector(x.type)) { error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); @@ -1144,16 +1608,129 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } - case BuiltinProc_simd_ceil: - case BuiltinProc_simd_floor: - case BuiltinProc_simd_trunc: - case BuiltinProc_simd_nearest: + case BuiltinProc_simd_runtime_swizzle: + { + if (ce->args.count != 2) { + error(call, "'%.*s' expected 2 arguments, got %td", LIT(builtin_name), ce->args.count); + return false; + } + + Operand src = {}; + Operand indices = {}; + check_expr(c, &src, ce->args[0]); if (src.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &indices, ce->args[1], src.type); if (indices.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(src.type)) { + error(src.expr, "'%.*s' expected first argument to be a simd vector", LIT(builtin_name)); + return false; + } + if (!is_type_simd_vector(indices.type)) { + error(indices.expr, "'%.*s' expected second argument (indices) to be a simd vector", LIT(builtin_name)); + return false; + } + + Type *src_elem = base_array_type(src.type); + Type *indices_elem = base_array_type(indices.type); + + if (!is_type_integer(src_elem)) { + gbString src_str = type_to_string(src.type); + error(src.expr, "'%.*s' expected first argument to be a simd vector of integers, got '%s'", LIT(builtin_name), src_str); + gb_string_free(src_str); + return false; + } + + if (!is_type_integer(indices_elem)) { + gbString indices_str = type_to_string(indices.type); + error(indices.expr, "'%.*s' expected indices to be a simd vector of integers, got '%s'", LIT(builtin_name), indices_str); + gb_string_free(indices_str); + return false; + } + + if (!are_types_identical(src.type, indices.type)) { + gbString src_str = type_to_string(src.type); + gbString indices_str = type_to_string(indices.type); + error(indices.expr, "'%.*s' expected both arguments to have the same type, got '%s' vs '%s'", LIT(builtin_name), src_str, indices_str); + gb_string_free(indices_str); + gb_string_free(src_str); + return false; + } + + operand->mode = Addressing_Value; + operand->type = src.type; + return true; + } + + case BuiltinProc_simd_sums_of_n: { Operand x = {}; check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; if (!is_type_simd_vector(x.type)) { - error(x.expr, "'%.*s' expected a simd vector boolean type", LIT(builtin_name)); + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + Type *bt = base_type(x.type); + u64 max_count = cast(u64)bt->SimdVector.count; + Type *elem = bt->SimdVector.elem; + + u64 n = 0; + + Operand y = {}; + check_expr(c, &y, ce->args[1]); if (y.mode == Addressing_Invalid) return false; + { + Type *arg_type = base_type(y.type); + if (!is_type_integer(arg_type) || y.mode != Addressing_Constant) { + error(y.expr, "Indices to '%.*s' must be constant integers", LIT(builtin_name)); + return false; + } + + if (big_int_is_neg(&y.value.value_integer)) { + error(y.expr, "Negative '%.*s' index", LIT(builtin_name)); + return false; + } + + n = exact_value_to_u64(y.value); + } + + if (!(is_power_of_two_u64(n) && n >= 2)) { + error(y.expr, "'%.*s' requires a power of two 'n' parameter >= 2, got %llu", LIT(builtin_name), cast(unsigned long long)n); + return false; + } + + if (n > max_count) { + error(y.expr, "'%.*s' requires that the 'n' parameter is <= than the #simd length, got %llu vs %llu", LIT(builtin_name), cast(unsigned long long)n, cast(unsigned long long) max_count); + return false; + } + + if (max_count % n != 0) { + error(y.expr, "'%.*s' requires the #simd length to be a multiple of the 'n' parameter, got #simd length=%llu, n=%llu", LIT(builtin_name), cast(unsigned long long) max_count, cast(unsigned long long)n); + return false; + } + + operand->mode = Addressing_Value; + + u64 result_count = max_count/n; + if (result_count == 1) { + operand->type = elem; + } else { + operand->type = alloc_type_simd_vector(result_count, elem); + } + return true; + + } + + case BuiltinProc_simd_ceil: + case BuiltinProc_simd_floor: + case BuiltinProc_simd_trunc: + case BuiltinProc_simd_nearest: + case BuiltinProc_simd_approx_recip: + case BuiltinProc_simd_approx_recip_sqrt: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); return false; } Type *elem = base_array_type(x.type); @@ -1268,21 +1845,115 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan } Type *elem = base_array_type(x.type); i64 count = get_array_type_count(x.type); - i64 sz = type_size_of(elem); - Type *bit_elem = nullptr; - switch (sz) { - case 1: bit_elem = t_u8; break; - case 2: bit_elem = t_u16; break; - case 4: bit_elem = t_u32; break; - case 8: bit_elem = t_u64; break; - } - GB_ASSERT(bit_elem != nullptr); + Type *bit_elem = type_unsigned_equivalent(elem); operand->type = alloc_type_simd_vector(count, bit_elem); operand->mode = Addressing_Value; return true; } + case BuiltinProc_simd_to_bits_signed: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + Type *elem = base_array_type(x.type); + i64 count = get_array_type_count(x.type); + Type *bit_elem = type_signed_equivalent(elem); + + operand->type = alloc_type_simd_vector(count, bit_elem); + operand->mode = Addressing_Value; + return true; + } + + case BuiltinProc_simd_interleave: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + + for (isize i = 1; i < ce->args.count; i++) { + Operand y = {}; + check_expr_with_type_hint(c, &y, ce->args[i], x.type); if (y.mode == Addressing_Invalid) return false; + if (!is_type_simd_vector(y.type)) { + error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + if (!are_types_identical(x.type, y.type)) { + gbString a = type_to_string(x.type); + gbString b = type_to_string(y.type); + error(y.expr, "'%.*s' all argument types must match, expected %s, got %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + } + + Type *elem = base_array_type(x.type); + i64 base_count = get_array_type_count(x.type); + i64 count = base_count * cast(i64)ce->args.count; + + i64 max_count = 64; + if (count > max_count) { + error(ce->proc, "'%.*s' exceeds the maximum #simd count %lld, got %lld", cast(long long)max_count, cast(long long)count); + return false; + } + + operand->type = alloc_type_simd_vector(count, elem); + operand->mode = Addressing_Value; + return true; + } + + case BuiltinProc_simd_deinterleave: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name)); + return false; + } + + Type *elem = base_array_type(x.type); + i64 max_count = get_array_type_count(x.type); + + Operand n = {}; + check_expr(c, &n, ce->args[1]); if (n.mode == Addressing_Invalid) return false; + if (n.mode != Addressing_Constant) { + error(n.expr, "'%.*s' expected a constant integer divisible by the count of the #simd vector", LIT(builtin_name)); + return false; + } + if (n.value.kind != ExactValue_Integer) { + error(n.expr, "'%.*s' expected a constant integer divisible by the count of the #simd vector", LIT(builtin_name)); + return false; + } + i64 divisor = exact_value_to_i64(n.value); + if (divisor < 1 || divisor > max_count || (max_count % divisor != 0)) { + error(n.expr, "'%.*s' expected a constant integer divisible by the count of the #simd vector , got %lld, which must have been divisible by %lld", LIT(builtin_name), cast(long long)divisor, cast(long long)max_count); + return false; + } + + Type *base_vector = alloc_type_simd_vector(max_count / divisor, elem); + + Type **field_types = temporary_alloc_array(cast(isize)divisor); + for (i64 i = 0; i < divisor; i++) { + field_types[i] = base_vector; + } + + operand->type = alloc_type_tuple_from_field_types(field_types, divisor, false, false); + operand->mode = Addressing_Value; + return true; + } + break; + + case BuiltinProc_simd_x86__MM_SHUFFLE: { Operand x[4] = {}; @@ -1359,7 +2030,7 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String } defer ({ if (cache == nullptr) { - LoadFileCache *new_cache = gb_alloc_item(permanent_allocator(), LoadFileCache); + LoadFileCache *new_cache = permanent_alloc_item(); new_cache->path = path; new_cache->data = data; new_cache->file_error = file_error; @@ -1397,7 +2068,7 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String case LoadFileTier_Contents: { isize file_size = cast(isize)gb_file_size(&f); if (file_size > 0) { - u8 *ptr = cast(u8 *)gb_alloc(permanent_allocator(), file_size+1); + u8 *ptr = permanent_alloc_array(file_size+1); gb_file_read_at(&f, ptr, file_size, 0); ptr[file_size] = '\0'; data.text = ptr; @@ -1602,7 +2273,7 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c } defer ({ if (cache == nullptr) { - LoadDirectoryCache *new_cache = gb_alloc_item(permanent_allocator(), LoadDirectoryCache); + LoadDirectoryCache *new_cache = permanent_alloc_item(); new_cache->path = path; new_cache->files = file_caches; new_cache->file_error = file_error; @@ -2065,13 +2736,14 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } String name = arg->Ident.token.string; + auto interned = arg->Ident.interned; operand->type = def.type; operand->mode = def.mode; operand->value = def.value; - Entity *found = scope_lookup_current(config_pkg->scope, name); + Entity *found = scope_lookup_current(config_pkg->scope, interned); if (found != nullptr) { if (found->kind != Entity_Constant) { error(arg, "'#config' entity '%.*s' found but expected a constant", LIT(name)); @@ -2138,6 +2810,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_min: case BuiltinProc_max: case BuiltinProc_type_is_subtype_of: + case BuiltinProc_type_is_superset_of: case BuiltinProc_objc_send: case BuiltinProc_objc_find_selector: case BuiltinProc_objc_find_class: @@ -2222,8 +2895,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_objc_register_selector: case BuiltinProc_objc_register_class: case BuiltinProc_objc_ivar_get: + case BuiltinProc_objc_block: + case BuiltinProc_objc_super: return check_builtin_objc_procedure(c, operand, call, id, type_hint); + case BuiltinProc_c_va_start: + case BuiltinProc_c_va_end: + case BuiltinProc_c_va_copy: + case BuiltinProc_c_va_arg: + return check_builtin_c_procedure(c, operand, call, id, type_hint); + case BuiltinProc___entry_point: operand->mode = Addressing_NoValue; operand->type = nullptr; @@ -2260,13 +2941,23 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (is_type_string(op_type) && id == BuiltinProc_len) { if (operand->mode == Addressing_Constant) { mode = Addressing_Constant; - String str = operand->value.value_string; - value = exact_value_i64(str.len); + + if (operand->value.kind == ExactValue_String) { + String str = operand->value.value_string; + value = exact_value_i64(str.len); + } else if (operand->value.kind == ExactValue_String16) { + String16 str = operand->value.value_string16; + value = exact_value_i64(str.len); + } else { + GB_PANIC("Unhandled value kind: %d", operand->value.kind); + } type = t_untyped_integer; } else { mode = Addressing_Value; if (is_type_cstring(op_type)) { add_package_dependency(c, "runtime", "cstring_len"); + } else if (is_type_cstring16(op_type)) { + add_package_dependency(c, "runtime", "cstring16_len"); } } } else if (is_type_array(op_type)) { @@ -2274,6 +2965,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As mode = Addressing_Constant; value = exact_value_i64(at->Array.count); type = t_untyped_integer; + } else if (is_type_fixed_capacity_dynamic_array(op_type)) { + Type *at = core_type(op_type); + if (id == BuiltinProc_cap) { + mode = Addressing_Constant; + value = exact_value_i64(at->FixedCapacityDynamicArray.capacity); + type = t_untyped_integer; + } else { + GB_ASSERT(id == BuiltinProc_len); + mode = Addressing_Value; + } } else if (is_type_enumerated_array(op_type) && id == BuiltinProc_len) { Type *at = core_type(op_type); mode = Addressing_Constant; @@ -2318,7 +3019,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (mode == Addressing_Invalid) { gbString t = type_to_string(operand->type); - error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t); + if (is_type_bit_set(op_type) && id == BuiltinProc_len) { + error(call, "'%.*s' is not supported for '%s', did you mean 'card'?", LIT(builtin_name), t); + } else { + error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t); + } return false; } @@ -2331,6 +3036,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_size_of: { // size_of :: proc(Type or expr) -> untyped int + if (ce->args[0]->kind == Ast_UnaryExpr) { + ast_node(arg, UnaryExpr, ce->args[0]); + if (arg->op.kind == Token_And) { + ERROR_BLOCK(); + + warning(ce->args[0], "'size_of(&x)' returns the size of a pointer, not the size of x"); + error_line("\tSuggestion: Use 'size_of(rawptr)' if you want the size of the pointer"); + } + } + Operand o = {}; check_expr_or_type(c, &o, ce->args[0]); if (o.mode == Addressing_Invalid) { @@ -2419,7 +3134,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } GB_ASSERT(type != nullptr); - String field_name = {}; + InternedString field_name = {}; if (field_arg == nullptr) { error(call, "Expected an identifier for field argument"); @@ -2427,17 +3142,17 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } if (field_arg->kind == Ast_Ident) { - field_name = field_arg->Ident.token.string; + field_name = field_arg->Ident.interned; } - if (field_name.len == 0) { + if (field_name.value == 0) { error(field_arg, "Expected an identifier for field argument"); return false; } - if (is_type_array(type)) { + if (is_type_array(type) || is_type_bit_field(type)) { gbString t = type_to_string(type); - error(field_arg, "Invalid a struct type for '%.*s', got '%s'", LIT(builtin_name), t); + error(field_arg, "Expected a struct type for '%.*s', got '%s'", LIT(builtin_name), t); gb_string_free(t); return false; } @@ -2462,19 +3177,19 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As ERROR_BLOCK(); gbString type_str = type_to_string_shorthand(type); error(ce->args[0], - "'%s' has no field named '%.*s'", type_str, LIT(field_name)); + "'%s' has no field named '%s'", type_str, field_name.cstring()); gb_string_free(type_str); Type *bt = base_type(type); if (bt->kind == Type_Struct) { - check_did_you_mean_type(field_name, bt->Struct.fields); + check_did_you_mean_type(field_name.string(), bt->Struct.fields); } return false; } if (sel.indirect) { gbString type_str = type_to_string_shorthand(type); error(ce->args[0], - "Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str); + "Field '%s' is embedded via a pointer in '%s'", field_name.cstring(), type_str); gb_string_free(type_str); return false; } @@ -2506,7 +3221,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } GB_ASSERT(type != nullptr); - String field_name = {}; + InternedString field_name = {}; if (field_arg == nullptr) { error(call, "Expected a constant (not-empty) string for field argument"); @@ -2516,9 +3231,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Operand x = {}; check_expr(c, &x, field_arg); if (x.mode == Addressing_Constant && x.value.kind == ExactValue_String) { - field_name = x.value.value_string; + field_name = string_interner_insert(x.value.value_string); } - if (field_name.len == 0) { + if (field_name.value == 0) { error(field_arg, "Expected a constant (non-empty) string for field argument"); return false; } @@ -2536,19 +3251,19 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As ERROR_BLOCK(); gbString type_str = type_to_string_shorthand(type); error(ce->args[0], - "'%s' has no field named '%.*s'", type_str, LIT(field_name)); + "'%s' has no field named '%s'", type_str, field_name.cstring()); gb_string_free(type_str); Type *bt = base_type(type); if (bt->kind == Type_Struct) { - check_did_you_mean_type(field_name, bt->Struct.fields); + check_did_you_mean_type(field_name.string(), bt->Struct.fields); } return false; } if (sel.indirect) { gbString type_str = type_to_string_shorthand(type); error(ce->args[0], - "Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str); + "Field '%s' is embedded via a pointer in '%s'", field_name.string(), type_str); gb_string_free(type_str); return false; } @@ -2568,6 +3283,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // check_assignment(c, operand, nullptr, str_lit("argument of 'type_of'")); if (o.mode == Addressing_Invalid || o.mode == Addressing_Builtin) { + Entity *e = entity_of_node(expr); + if (e != nullptr && + e->state == EntityState_InProgress && + e->type == nullptr) { + gbString s = expr_to_string(expr); + error(expr, "Invalid cyclic type usage from 'type_of', got '%s'", s); + gb_string_free(s); + } return false; } if (o.type == nullptr || o.type == t_invalid || is_type_asm_proc(o.type)) { @@ -2871,8 +3594,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // quaternion :: proc(imag, jmag, kmag, real: float_type) -> complex_type Operand xyzw[4] = {}; - u32 first_index = 0; - // NOTE(bill): Invalid will be the default till fixed operand->type = t_invalid; operand->mode = Addressing_Invalid; @@ -2917,6 +3638,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (fields_set[*index]) { error(field->field, "Previously assigned field: '%.*s'", LIT(name)); + return false; } fields_set[*index] = style; @@ -2933,7 +3655,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (!ok || index < 0) { return false; } - first_index = cast(u32)index; *refs[index] = o; } @@ -2958,12 +3679,17 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } - for (u32 i = 0; i < 4; i++ ){ - u32 j = (i + first_index) % 4; - if (j == first_index) { - convert_to_typed(c, &xyzw[j], xyzw[(first_index+1)%4].type); if (xyzw[j].mode == Addressing_Invalid) return false; - } else { - convert_to_typed(c, &xyzw[j], xyzw[first_index].type); if (xyzw[j].mode == Addressing_Invalid) return false; + // The first typed value found, if any exist, will dictate the type for all untyped values. + for (u32 i = 0; i < 4; i++) { + if (is_type_typed(xyzw[i].type)) { + for (u32 j = 0; j < 4; j++) { + // `convert_to_typed` should check if it is typed already. + convert_to_typed(c, &xyzw[j], xyzw[i].type); + if (xyzw[j].mode == Addressing_Invalid) { + return false; + } + } + break; } } if (xyzw[0].mode == Addressing_Constant && @@ -2987,7 +3713,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As gbString ty = type_to_string(xyzw[1].type); gbString tz = type_to_string(xyzw[2].type); gbString tw = type_to_string(xyzw[3].type); - error(call, "Mismatched types to 'quaternion', 'x=%s' vs 'y=%s' vs 'z=%s' vs 'w=%s'", tx, ty, tz, tw); + error(call, "Mismatched types to 'quaternion', 'w=%s' vs 'x=%s' vs 'y=%s' vs 'z=%s'", tw, tx, ty, tz); gb_string_free(tw); gb_string_free(tz); gb_string_free(ty); @@ -3023,7 +3749,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->mode = Addressing_Constant; } - BasicKind kind = core_type(xyzw[first_index].type)->Basic.kind; + BasicKind kind = core_type(xyzw[0].type)->Basic.kind; switch (kind) { case Basic_f16: operand->type = t_quaternion64; break; case Basic_f32: operand->type = t_quaternion128; break; @@ -3217,18 +3943,17 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As gb_string_free(type_str); return false; } - gbAllocator a = permanent_allocator(); Type *tuple = alloc_type_tuple(); if (is_type_struct(type)) { isize variable_count = type->Struct.fields.count; - slice_init(&tuple->Tuple.variables, a, variable_count); + tuple->Tuple.variables = permanent_slice_make(variable_count); // NOTE(bill): don't copy the entities, this should be good enough gb_memmove_array(tuple->Tuple.variables.data, type->Struct.fields.data, variable_count); } else if (is_type_array(type)) { isize variable_count = cast(isize)type->Array.count; - slice_init(&tuple->Tuple.variables, a, variable_count); + tuple->Tuple.variables = permanent_slice_make(variable_count); for (isize i = 0; i < variable_count; i++) { tuple->Tuple.variables[i] = alloc_entity_array_elem(nullptr, blank_token, type->Array.elem, cast(i32)i); } @@ -3243,6 +3968,194 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_compress_values: { + Operand *ops = temporary_alloc_array(ce->args.count); + + isize value_count = 0; + + for_array(i, ce->args) { + Ast *arg = ce->args[i]; + Operand *op = &ops[i]; + check_multi_expr(c, op, arg); + if (op->mode == Addressing_Invalid) { + return false; + } + + if (op->type == nullptr || op->type == t_invalid) { + gbString s = expr_to_string(op->expr); + error(op->expr, "Invalid expression to '%.*s', got %s", LIT(builtin_name), s); + gb_string_free(s); + } + if (is_type_tuple(op->type)) { + value_count += op->type->Tuple.variables.count; + } else { + value_count += 1; + } + } + + GB_ASSERT(value_count >= 1); + + if (value_count == 1) { + *operand = ops[0]; + break; + } + + if (type_hint != nullptr) { + Type *th = base_type(type_hint); + if (th->kind == Type_Struct) { + if (value_count == th->Struct.fields.count) { + isize index = 0; + for_array(i, ce->args) { + Operand *op = &ops[i]; + if (is_type_tuple(op->type)) { + for (Entity *v : op->type->Tuple.variables) { + Operand x = {}; + x.mode = Addressing_Value; + x.type = v->type; + check_assignment(c, &x, th->Struct.fields[index++]->type, builtin_name); + if (x.mode == Addressing_Invalid) { + return false; + } + } + } else { + check_assignment(c, op, th->Struct.fields[index++]->type, builtin_name); + if (op->mode == Addressing_Invalid) { + return false; + } + } + } + + operand->type = type_hint; + operand->mode = Addressing_Value; + break; + } + } else if (is_type_array_like(th)) { + if (cast(i64)value_count == get_array_type_count(th)) { + Type *elem = base_array_type(th); + for_array(i, ce->args) { + Operand *op = &ops[i]; + if (is_type_tuple(op->type)) { + for (Entity *v : op->type->Tuple.variables) { + Operand x = {}; + x.mode = Addressing_Value; + x.type = v->type; + check_assignment(c, &x, elem, builtin_name); + if (x.mode == Addressing_Invalid) { + return false; + } + } + } else { + check_assignment(c, op, elem, builtin_name); + if (op->mode == Addressing_Invalid) { + return false; + } + } + } + + operand->type = type_hint; + operand->mode = Addressing_Value; + break; + } + } + } + + bool all_types_the_same = true; + Type *last_type = nullptr; + for_array(i, ce->args) { + Operand *op = &ops[i]; + if (is_type_tuple(op->type)) { + if (last_type == nullptr) { + op->type->Tuple.variables[0]->type; + } + for (Entity *v : op->type->Tuple.variables) { + if (!are_types_identical(last_type, v->type)) { + all_types_the_same = false; + break; + } + last_type = v->type; + } + } else { + if (last_type == nullptr) { + last_type = op->type; + } else { + if (!are_types_identical(last_type, op->type)) { + all_types_the_same = false; + break; + } + last_type = op->type; + } + } + } + + if (all_types_the_same) { + Type *elem_type = default_type(last_type); + if (is_type_untyped(elem_type)) { + gbString s = expr_to_string(call); + error(call, "Invalid use of '%s' in '%.*s'", s, LIT(builtin_name)); + gb_string_free(s); + return false; + } + + operand->type = alloc_type_array(elem_type, value_count); + operand->mode = Addressing_Value; + } else { + Type *st = alloc_type_struct_complete(); + st->Struct.fields = permanent_slice_make(value_count); + st->Struct.tags = permanent_alloc_array(value_count); + st->Struct.offsets = permanent_alloc_array(value_count); + + Scope *scope = create_scope(c->info, nullptr); + + Token token = {}; + token.kind = Token_Ident; + token.pos = ast_token(call).pos; + + isize index = 0; + for_array(i, ce->args) { + Operand *op = &ops[i]; + if (is_type_tuple(op->type)) { + for (Entity *v : op->type->Tuple.variables) { + Type *t = default_type(v->type); + if (is_type_untyped(t)) { + gbString s = expr_to_string(op->expr); + error(op->expr, "Invalid use of '%s' in '%.*s'", s, LIT(builtin_name)); + gb_string_free(s); + return false; + } + + gbString s = gb_string_make_reserve(permanent_allocator(), 32); + s = gb_string_append_fmt(s, "v%lld", cast(long long)index); + token.string = make_string_c(s); + Entity *e = alloc_entity_field(scope, token, t, false, cast(i32)index, EntityState_Resolved); + st->Struct.fields[index++] = e; + } + } else { + Type *t = default_type(op->type); + if (is_type_untyped(t)) { + gbString s = expr_to_string(op->expr); + error(op->expr, "Invalid use of '%s' in '%.*s'", s, LIT(builtin_name)); + gb_string_free(s); + return false; + } + + gbString s = gb_string_make_reserve(permanent_allocator(), 32); + s = gb_string_append_fmt(s, "v%lld", cast(long long)index); + token.string = make_string_c(s); + Entity *e = alloc_entity_field(scope, token, t, false, cast(i32)index, EntityState_Resolved); + st->Struct.fields[index++] = e; + } + } + + + gb_unused(type_size_of(st)); + + operand->type = st; + operand->mode = Addressing_Value; + } + break; + } + + case BuiltinProc_min: { // min :: proc($T: typeid) -> ordered // min :: proc(a: ..ordered) -> ordered @@ -3861,7 +4774,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } if (!fail && first_is_field_value) { for_array(i, names) { - Selection sel = lookup_field(et, names[i], false); + Selection sel = lookup_field(et, string_interner_insert(names[i]), false); if (sel.entity == nullptr) { goto soa_zip_end; } @@ -3889,7 +4802,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As elem = alloc_type_struct(); elem->Struct.scope = s; elem->Struct.fields = slice_from_array(fields); - elem->Struct.tags = gb_alloc_array(permanent_allocator(), String, fields.count); + elem->Struct.tags = permanent_alloc_array(fields.count); elem->Struct.node = dummy_node_struct; type_set_offsets(elem); wait_signal_set(&elem->Struct.fields_wait_signal); @@ -3921,7 +4834,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As gb_string_free(s); return false; } - auto types = slice_make(permanent_allocator(), t->Struct.fields.count-1); + auto types = permanent_slice_make(t->Struct.fields.count-1); for_array(i, types) { Entity *f = t->Struct.fields[i]; GB_ASSERT(f->type->kind == Type_MultiPointer); @@ -4214,6 +5127,42 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_constant_floor: + case BuiltinProc_constant_trunc: + case BuiltinProc_constant_ceil: + case BuiltinProc_constant_round: + { + Operand o = {}; + check_expr(c, &o, ce->args[0]); + + if (!is_type_integer_or_float(o.type) && (o.mode != Addressing_Constant)) { + error(ce->args[0], "Expected a constant number for '%.*s'", LIT(builtin_name)); + return false; + } + operand->mode = Addressing_Constant; + operand->type = o.type; + + ExactValue value = o.value; + if (value.kind == ExactValue_Integer) { + // do nothing + } else if (value.kind == ExactValue_Float) { + f64 f = value.value_float; + switch (id) { + case BuiltinProc_constant_floor: f = floor(f); break; + case BuiltinProc_constant_trunc: f = trunc(f); break; + case BuiltinProc_constant_ceil: f = ceil(f); break; + case BuiltinProc_constant_round: f = round(f); break; + default: + GB_PANIC("Unhandled built-in: %.*s", LIT(builtin_name)); + break; + } + value = exact_value_float(f); + } + + operand->value = value; + break; + } + case BuiltinProc_soa_struct: { Operand x = {}; Operand y = {}; @@ -4257,8 +5206,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (is_type_array(elem)) { Type *old_array = base_type(elem); soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = slice_make(heap_allocator(), cast(isize)old_array->Array.count); - soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, cast(isize)old_array->Array.count); + soa_struct->Struct.fields = permanent_slice_make(cast(isize)old_array->Array.count); + soa_struct->Struct.tags = permanent_alloc_array(cast(isize)old_array->Array.count); soa_struct->Struct.node = operand->expr; soa_struct->Struct.soa_kind = StructSoa_Fixed; soa_struct->Struct.soa_elem = elem; @@ -4290,8 +5239,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Type *old_struct = base_type(elem); soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = slice_make(heap_allocator(), old_struct->Struct.fields.count); - soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, old_struct->Struct.fields.count); + soa_struct->Struct.fields = permanent_slice_make(old_struct->Struct.fields.count); + soa_struct->Struct.tags = permanent_alloc_array(old_struct->Struct.fields.count); soa_struct->Struct.node = operand->expr; soa_struct->Struct.soa_kind = StructSoa_Fixed; soa_struct->Struct.soa_elem = elem; @@ -4331,6 +5280,138 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_concatenate: { + Operand lhs = {}; + + check_expr_with_type_hint(c, &lhs, ce->args[0], type_hint); + if (lhs.mode == Addressing_Invalid) { + return false; + } + if (lhs.mode != Addressing_Constant) { + error(lhs.expr, "'%.*s' expects a constant array or slice", LIT(builtin_name)); + return false; + } + operand->type = lhs.type; + operand->mode = Addressing_Value; + + if (!is_type_slice(lhs.type) && !is_type_array(lhs.type)) { + gbString a = type_to_string(lhs.type); + error(lhs.expr, "'%.*s' expects a constant array or slice, got %s", LIT(builtin_name), a); + gb_string_free(a); + return false; + } + if (lhs.value.kind != ExactValue_Compound) { + gbString a = exact_value_to_string(lhs.value); + error(lhs.expr, "Expected a compound literal value for '%.*s', got '%s'", LIT(builtin_name), a); + gb_string_free(a); + return false; + } + + ast_node(lhs_cl, CompoundLit, lhs.value.value_compound); + + for (Ast *elem : lhs_cl->elems) { + if (elem->kind == Ast_FieldValue) { + error(elem, "'%.*s' does not allow the use of 'field = value' to be concatenated together", LIT(builtin_name)); + return false; + } + } + + Type *elem_type = base_any_array_type(lhs.type); + + for (isize i = 1; i < ce->args.count; i++) { + Operand extra = {}; + if (is_type_slice(lhs.type)) { + check_expr_with_type_hint(c, &extra, ce->args[i], lhs.type); + } else { + check_expr(c, &extra, ce->args[i]); + } + if (extra.mode == Addressing_Invalid) { + return false; + } + if (extra.mode != Addressing_Constant) { + error(extra.expr, "'%.*s' expects a constant array or slice", LIT(builtin_name)); + return false; + } + + if (is_type_slice(lhs.type)) { + if (!are_types_identical(lhs.type, extra.type)) { + gbString a = type_to_string(lhs.type); + gbString b = type_to_string(extra.type); + error(extra.expr, "'%.*s' expects constant values of the same slice type, got '%s' vs '%s'", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + } else if (is_type_array(lhs.type)) { + if (!is_type_array(extra.type)) { + gbString a = type_to_string(extra.type); + error(extra.expr, "'%.*s' expects a constant array or slice, got %s", LIT(builtin_name), a); + gb_string_free(a); + return false; + } + Type *extra_elem_type = base_array_type(extra.type); + if (!are_types_identical(elem_type, extra_elem_type)) { + gbString a = type_to_string(elem_type); + gbString b = type_to_string(extra_elem_type); + error(extra.expr, "'%.*s' expects constant values of the same element-type, got '%s' vs '%s'", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + } else { + GB_PANIC("Unhandled type: %s", type_to_string(lhs.type)); + } + + if (extra.value.kind != ExactValue_Compound) { + gbString a = exact_value_to_string(extra.value); + error(extra.expr, "Expected a compound literal value for '%.*s', got '%s'", LIT(builtin_name), a); + gb_string_free(a); + return false; + } + + ast_node(extra_cl, CompoundLit, extra.value.value_compound); + + + for (Ast *elem : extra_cl->elems) { + if (elem->kind == Ast_FieldValue) { + error(elem, "'%.*s' does not allow the use of 'field = value' to be concatenated together", LIT(builtin_name)); + return false; + } + } + } + + isize count_needed = 0; + + for (Ast *arg : ce->args) { + ExactValue value = arg->tav.value; + GB_ASSERT(value.kind == ExactValue_Compound); + ast_node(cl, CompoundLit, value.value_compound); + count_needed += cl->elems.count; + } + + Array new_elems = {}; + array_init(&new_elems, permanent_allocator(), 0, count_needed); + + for (Ast *arg : ce->args) { + ExactValue value = arg->tav.value; + GB_ASSERT(value.kind == ExactValue_Compound); + ast_node(cl, CompoundLit, value.value_compound); + array_add_elems(&new_elems, cl->elems.data, cl->elems.count); + } + + Ast *new_compound_lit = ast_compound_lit(lhs.expr->file(), nullptr, new_elems, ast_token(lhs.expr), ast_end_token(ce->args[ce->args.count-1])); + + operand->mode = Addressing_Constant; + operand->value = exact_value_compound(new_compound_lit); + + if (is_type_slice(lhs.type)) { + operand->type = lhs.type; + } else { + operand->type = alloc_type_array(elem_type, new_elems.count); + } + break; + } + case BuiltinProc_alloca: { Operand sz = {}; @@ -4421,7 +5502,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; case Type_Basic: if (t->Basic.kind == Basic_string) { - operand->type = alloc_type_multi_pointer(t_u8); + operand->type = t_u8_multi_ptr; + } else if (t->Basic.kind == Basic_string16) { + operand->type = t_u16_multi_ptr; } break; case Type_Pointer: @@ -4432,6 +5515,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case Type_Array: case Type_EnumeratedArray: case Type_SimdVector: + case Type_FixedCapacityDynamicArray: operand->type = alloc_type_multi_pointer(base_array_type(base)); break; case Type_Matrix: @@ -4451,6 +5535,15 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } break; + case BuiltinProc_read_cycle_counter_frequency: + if (build_context.metrics.arch != TargetArch_arm64) { + error(call, "'%.*s' is only allowed on arm64 targets", LIT(builtin_name)); + return false; + } + operand->mode = Addressing_Value; + operand->type = t_i64; + break; + case BuiltinProc_read_cycle_counter: operand->mode = Addressing_Value; operand->type = t_i64; @@ -4460,6 +5553,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_count_zeros: case BuiltinProc_count_trailing_zeros: case BuiltinProc_count_leading_zeros: + case BuiltinProc_count_trailing_ones: + case BuiltinProc_count_leading_ones: case BuiltinProc_reverse_bits: { Operand x = {}; @@ -4557,6 +5652,27 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As v += 1; } break; + + case BuiltinProc_count_trailing_ones: + for (u64 i = 0; i < bit_size; i++) { + u8 b = cast(u8)(i & 7); + u8 j = cast(u8)(i >> 3); + if ((rop[j] & (1 << b)) == 0) { + break; + } + v += 1; + } + break; + case BuiltinProc_count_leading_ones: + for (u64 i = bit_size-1; i < bit_size; i--) { + u8 b = cast(u8)(i & 7); + u8 j = cast(u8)(i >> 3); + if ((rop[j] & (1 << b)) == 0) { + break; + } + v += 1; + } + break; } @@ -4580,7 +5696,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } - if (!is_type_integer_like(x.type) && !is_type_float(x.type)) { + if (is_type_simd_vector(x.type)) { + Type *elem = base_array_type(x.type); + if (!is_type_integer_like(elem)) { + gbString xts = type_to_string(x.type); + error(x.expr, "#simd values passed to '%.*s' must have an element of an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_name), xts); + gb_string_free(xts); + } + } else if (!is_type_integer_like(x.type) && !is_type_float(x.type)) { gbString xts = type_to_string(x.type); error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set) or float, got %s", LIT(builtin_name), xts); gb_string_free(xts); @@ -4639,6 +5762,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } } + if (!are_types_identical(x.type, y.type)) { + gbString xts = type_to_string(x.type); + gbString yts = type_to_string(y.type); + error(x.expr, "Mismatched types for '%.*s', got %s vs %s", LIT(builtin_name), xts, yts); + gb_string_free(yts); + gb_string_free(xts); + return false; + } operand->mode = Addressing_Value; operand->type = make_optional_ok_type(default_type(x.type)); @@ -4682,6 +5813,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } } + if (!are_types_identical(x.type, y.type)) { + gbString xts = type_to_string(x.type); + gbString yts = type_to_string(y.type); + error(x.expr, "Mismatched types for '%.*s', got %s vs %s", LIT(builtin_name), xts, yts); + gb_string_free(yts); + gb_string_free(xts); + return false; + } operand->mode = Addressing_Value; operand->type = default_type(x.type); @@ -5401,7 +6540,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } if (sz >= 64) { - if (is_type_unsigned(x.type)) { + if (is_type_unsigned(x.type) || is_type_unsigned(y.type)) { add_package_dependency(c, "runtime", "umodti3", true); add_package_dependency(c, "runtime", "udivti3", true); } else { @@ -5462,6 +6601,33 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->type = x.type; } break; + + case BuiltinProc_likely: + case BuiltinProc_unlikely: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); + if (x.mode == Addressing_Invalid) { + return false; + } + if (!is_type_boolean(x.type)) { + gbString xt = type_to_string(x.type); + error(x.expr, "Expected a boolean expression to '%.*s', got %s", LIT(builtin_name), xt); + gb_string_free(xt); + *operand = x; // minimize error propagation + return true; + } + + if (x.mode == Addressing_Constant) { + // NOTE(bill): just completely ignore this intrinsic entirely + *operand = x; + return true; + } + + operand->mode = Addressing_Value; + operand->type = x.type; + } + break; case BuiltinProc_prefetch_read_instruction: case BuiltinProc_prefetch_read_data: @@ -5525,8 +6691,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As switch (build_context.metrics.os) { case TargetOs_darwin: case TargetOs_linux: - case TargetOs_essence: - case TargetOs_haiku: switch (build_context.metrics.arch) { case TargetArch_i386: case TargetArch_amd64: @@ -5672,7 +6836,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } Type *new_type = alloc_type_union(); - auto variants = slice_make(permanent_allocator(), bt->Union.variants.count); + auto variants = permanent_slice_make(bt->Union.variants.count); for_array(i, bt->Union.variants) { variants[i] = alloc_type_pointer(bt->Union.variants[i]); } @@ -5689,6 +6853,87 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } operand->mode = Addressing_Type; break; + case BuiltinProc_type_integer_to_unsigned: + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + if (is_type_polymorphic(operand->type)) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + { + Type *bt = base_type(operand->type); + + if (bt->kind != Type_Basic || + (bt->Basic.flags & BasicFlag_Unsigned) != 0 || + (bt->Basic.flags & BasicFlag_Integer) == 0) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a signed integer type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + if ((bt->Basic.flags & BasicFlag_Untyped) != 0) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-untyped integer type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + Type *u_type = &basic_types[bt->Basic.kind + 1]; + + operand->type = u_type; + } + break; + case BuiltinProc_type_integer_to_signed: + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + if (is_type_polymorphic(operand->type)) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + { + Type *bt = base_type(operand->type); + + if (bt->kind != Type_Basic || + (bt->Basic.flags & BasicFlag_Unsigned) == 0 || + (bt->Basic.flags & BasicFlag_Integer) == 0) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected an unsigned integer type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + if ((bt->Basic.flags & BasicFlag_Untyped) != 0) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-untyped integer type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + if (bt->Basic.kind == Basic_uintptr) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Type %s does not have a signed integer mapping for '%.*s'", t, LIT(builtin_name)); + gb_string_free(t); + return false; + } + + Type *u_type = &basic_types[bt->Basic.kind - 1]; + + operand->type = u_type; + } + break; case BuiltinProc_type_merge: { operand->mode = Addressing_Type; @@ -5774,12 +7019,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_boolean: + case BuiltinProc_type_is_bit_field: case BuiltinProc_type_is_integer: case BuiltinProc_type_is_rune: case BuiltinProc_type_is_float: case BuiltinProc_type_is_complex: case BuiltinProc_type_is_quaternion: case BuiltinProc_type_is_string: + case BuiltinProc_type_is_string16: + case BuiltinProc_type_is_cstring: + case BuiltinProc_type_is_cstring16: case BuiltinProc_type_is_typeid: case BuiltinProc_type_is_any: case BuiltinProc_type_is_endian_platform: @@ -5792,7 +7041,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_indexable: case BuiltinProc_type_is_sliceable: case BuiltinProc_type_is_comparable: - case BuiltinProc_type_is_simple_compare: + case BuiltinProc_type_is_simple_compare: // easily compared using memcmp + case BuiltinProc_type_is_nearly_simple_compare: // easily compared using memcmp (including floats) case BuiltinProc_type_is_dereferenceable: case BuiltinProc_type_is_valid_map_key: case BuiltinProc_type_is_valid_matrix_elements: @@ -5811,6 +7061,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_bit_set: case BuiltinProc_type_is_simd_vector: case BuiltinProc_type_is_matrix: + case BuiltinProc_type_is_raw_union: + case BuiltinProc_type_is_fixed_capacity_dynamic_array: + case BuiltinProc_type_is_internally_pointer_like: case BuiltinProc_type_is_specialized_polymorphic_record: case BuiltinProc_type_is_unspecialized_polymorphic_record: case BuiltinProc_type_has_nil: @@ -5873,11 +7126,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As check_expr(c, &x, ce->args[1]); if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { - error(ce->args[1], "Expected a const string for field argument"); + error(ce->args[1], "Expected a constant string for field argument"); return false; } - String field_name = x.value.value_string; + InternedString field_name = string_interner_insert(x.value.value_string); Selection sel = lookup_field(type, field_name, false); operand->mode = Addressing_Constant; @@ -5953,16 +7206,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As check_expr(c, &x, ce->args[1]); if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { - error(ce->args[1], "Expected a const string for field argument"); + error(ce->args[1], "Expected a constant string for field argument"); return false; } - String field_name = x.value.value_string; + InternedString field_name = string_interner_insert(x.value.value_string); Selection sel = lookup_field(type, field_name, false); if (sel.index.count == 0) { gbString t = type_to_string(type); - error(ce->args[1], "'%.*s' is not a field of type %s", LIT(field_name), t); + error(ce->args[1], "'%s' is not a field of type %s", field_name.cstring(), t); gb_string_free(t); return false; } @@ -5971,6 +7224,68 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } break; + + case BuiltinProc_type_field_bit_offset: + case BuiltinProc_type_field_bit_size: + { + Operand op = {}; + Type *bt = check_type(c, ce->args[0]); + Type *type = base_type(bt); + if (type == nullptr || type == t_invalid) { + error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + if (!is_type_bit_field(type)) { + error(operand->expr, "Expected a bit field type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Operand x = {}; + check_expr(c, &x, ce->args[1]); + + if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { + error(ce->args[1], "Expected a constant string for field argument"); + return false; + } + + InternedString field_name = string_interner_insert(x.value.value_string); + + i64 bit_offset = 0; + i64 bit_size = 0; + for_array(i, type->BitField.fields) { + Entity *f = type->BitField.fields[i]; + if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { + continue; + } + auto str = entity_interned_name(f); + if (field_name == str) { + bit_offset = type->BitField.bit_offsets[i]; + bit_size = type->BitField.bit_sizes[i]; + break; + } + } + + i64 value = 0; + switch (id) { + case BuiltinProc_type_field_bit_offset: + value = bit_offset; + break; + case BuiltinProc_type_field_bit_size: + value = bit_size; + break; + default: + GB_ASSERT(false); + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + operand->value = exact_value_i64(value); + break; + } + break; case BuiltinProc_type_is_specialization_of: { @@ -6090,9 +7405,13 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // NOTE(jakubtomsu): forces calculation of variant_block_size type_size_of(u); - // NOTE(Jeroen): A tag offset of zero is perfectly fine if all members of the union are empty structs. - // What matters is that the tag size is > 0. - GB_ASSERT(u->Union.tag_size > 0); + if (u->Union.tag_size == 0) { + GB_ASSERT(is_type_union_maybe_pointer(u)); + } else { + // NOTE(Jeroen): A tag offset of zero is perfectly fine if all members of the union are empty structs. + // What matters is that the tag size is > 0. + GB_ASSERT(u->Union.tag_size > 0); + } operand->mode = Addressing_Constant; operand->type = t_untyped_integer; @@ -6474,6 +7793,28 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; + case BuiltinProc_type_proc_calling_convention: + if (operand->mode != Addressing_Type || !is_type_proc(operand->type)) { + error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name)); + return false; + } else { + if (is_type_polymorphic(operand->type)) { + error(operand->expr, "Expected a non-polymorphic procedure type for '%.*s'", LIT(builtin_name)); + return false; + } + + Type *pt = base_type(operand->type); + GB_ASSERT(pt->kind == Type_Proc); + ProcCallingConvention cc = pt->Proc.calling_convention; + + operand->mode = Addressing_Constant; + operand->type = t_odin_calling_convention; + operand->value = exact_value_i64(cc); + } + + break; + + case BuiltinProc_type_polymorphic_record_parameter_count: operand->value = exact_value_i64(0); if (operand->mode != Addressing_Type) { @@ -6573,6 +7914,129 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->type = t_untyped_bool; } break; + case BuiltinProc_type_is_superset_of: + { + Operand op_super = {}; + Operand op_sub = {}; + + check_expr_or_type(c, &op_super, ce->args[0]); + if (op_super.mode != Addressing_Type) { + gbString e = expr_to_string(op_super.expr); + error(op_super.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + check_expr_or_type(c, &op_sub, ce->args[1]); + if (op_sub.mode != Addressing_Type) { + gbString e = expr_to_string(op_sub.expr); + error(op_sub.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + + Type *super = op_super.type; + Type *sub = op_sub.type; + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + super = base_type(super); + sub = base_type(sub); + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + if (super->kind != sub->kind) { + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + if (super->kind == Type_Enum) { + if (sub->Enum.fields.count > super->Enum.fields.count) { + operand->value = exact_value_bool(false); + return true; + } + + + Type *base_super = base_enum_type(super); + Type *base_sub = base_enum_type(sub); + if (base_super == base_sub && base_super == nullptr) { + // okay + } else if (!are_types_identical(base_type(base_super), base_type(base_sub))) { + operand->value = exact_value_bool(false); + return true; + } + + for (Entity *f_sub : sub->Enum.fields) { + bool found = false; + + if (f_sub->kind != Entity_Constant) { + continue; + } + + for (Entity *f_super : super->Enum.fields) { + if (f_super->kind != Entity_Constant) { + continue; + } + + if (f_sub->token.string == f_super->token.string) { + if (compare_exact_values(Token_CmpEq, f_sub->Constant.value, f_super->Constant.value)) { + found = true; + break; + } + } + } + + if (!found) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } else if (super->kind == Type_Union) { + if (sub->Union.variants.count > super->Union.variants.count) { + operand->value = exact_value_bool(false); + return true; + } + if (sub->Union.kind != super->Union.kind) { + operand->value = exact_value_bool(false); + return true; + } + + for_array(i, sub->Union.variants) { + Type *t_sub = sub->Union.variants[i]; + Type *t_super = super->Union.variants[i]; + if (!are_types_identical(t_sub, t_super)) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind and either an enum or union, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + case BuiltinProc_type_field_index_of: { Operand op = {}; @@ -6586,29 +8050,29 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As check_expr(c, &x, ce->args[1]); if (!is_type_string(x.type) || x.mode != Addressing_Constant || x.value.kind != ExactValue_String) { - error(ce->args[1], "Expected a const string for field argument"); + error(ce->args[1], "Expected a constant string for field argument"); return false; } - String field_name = x.value.value_string; + InternedString field_name = string_interner_insert(x.value.value_string); Selection sel = lookup_field(type, field_name, false); if (sel.entity == nullptr) { ERROR_BLOCK(); gbString type_str = type_to_string(bt); error(ce->args[0], - "'%s' has no field named '%.*s'", type_str, LIT(field_name)); + "'%s' has no field named '%s'", type_str, field_name.cstring()); gb_string_free(type_str); if (bt->kind == Type_Struct) { - check_did_you_mean_type(field_name, bt->Struct.fields); + check_did_you_mean_type(field_name.string(), bt->Struct.fields); } return false; } if (sel.indirect) { gbString type_str = type_to_string(bt); error(ce->args[0], - "Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str); + "Field '%s' is embedded via a pointer in '%s'", field_name.cstring(), type_str); gb_string_free(type_str); return false; } @@ -6620,6 +8084,31 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } break; + case BuiltinProc_type_fixed_capacity_dynamic_array_len_offset: + { + Operand op = {}; + Type *bt = check_type(c, ce->args[0]); + Type *type = base_type(bt); + if (type == nullptr || type == t_invalid) { + error(ce->args[0], "Expected a fixed capacity dynamic array type for '%.*s'", LIT(builtin_name)); + return false; + } + if (!is_type_fixed_capacity_dynamic_array(type)) { + error(ce->args[0], "Expected a fixed capacity dynamic array type for '%.*s'", LIT(builtin_name)); + return false; + } + + i64 sz = type_size_of(type); + gb_unused(sz); + i64 offset = type_offset_of(type, 1); + + operand->mode = Addressing_Constant; + operand->value = exact_value_u64(cast(u64)offset); + operand->type = t_uintptr; + break; + } + break; + case BuiltinProc_type_bit_set_backing_type: { Operand op = {}; @@ -6640,6 +8129,50 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_type_enum_is_contiguous: + { + Operand op = {}; + Type *bt = check_type(c, ce->args[0]); + Type *type = base_type(bt); + if (type == nullptr || type == t_invalid) { + error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + if (!is_type_enum(type)) { + gbString t = type_to_string(type); + error(ce->args[0], "Expected an enum type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + auto enum_constants = array_make(temporary_allocator(), type->Enum.fields.count); + array_copy(&enum_constants, type->Enum.fields, 0); + array_sort(enum_constants, enum_constant_entity_cmp); + + BigInt minus_one = big_int_make_i64(-1); + defer (big_int_dealloc(&minus_one)); + BigInt diff = {}; + + bool contiguous = true; + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + + for (isize i = 0; i < enum_constants.count - 1; i++) { + BigInt curr = enum_constants[i]->Constant.value.value_integer; + BigInt next = enum_constants[i + 1]->Constant.value.value_integer; + big_int_sub(&diff, &curr, &next); + defer (big_int_dealloc(&diff)); + + if (!big_int_is_zero(&diff) && big_int_cmp(&diff, &minus_one) != 0) { + contiguous = false; + break; + } + } + + operand->value = exact_value_bool(contiguous); + break; + } + case BuiltinProc_type_equal_proc: { Operand op = {}; @@ -6721,12 +8254,28 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_type_canonical_name: + { + Operand op = {}; + Type *type = check_type(c, ce->args[0]); + Type *bt = base_type(type); + if (bt == nullptr || bt == t_invalid) { + error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_string; + operand->value = exact_value_string(type_to_canonical_string(permanent_allocator(), type)); + break; + } + case BuiltinProc_procedure_of: { Ast *call_expr = unparen_expr(ce->args[0]); Operand op = {}; check_expr_base(c, &op, ce->args[0], nullptr); - if (op.mode != Addressing_Value && !(call_expr && call_expr->kind == Ast_CallExpr)) { + if (op.mode != Addressing_Value || call_expr == nullptr || call_expr->kind != Ast_CallExpr) { error(ce->args[0], "Expected a call expression for '%.*s'", LIT(builtin_name)); return false; } @@ -6773,7 +8322,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } operand->mode = Addressing_Value; - operand->type = alloc_type_multi_pointer(t_u16); + if (type_hint != nullptr && is_type_cstring16(type_hint)) { + operand->type = type_hint; + } else { + operand->type = alloc_type_multi_pointer(t_u16); + } operand->value = {}; break; } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index d53c3c6b7..edb9f4883 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -145,13 +145,6 @@ gb_internal void check_init_variables(CheckerContext *ctx, Entity **lhs, isize l if (d != nullptr) { d->init_expr = o->expr; } - - if (o->type && is_type_no_copy(o->type)) { - ERROR_BLOCK(); - if (check_no_copy_assignment(*o, str_lit("initialization"))) { - error_line("\tInitialization of a #no_copy type must be either implicitly zero, a constant literal, or a return value from a call expression"); - } - } } if (rhs_count > 0 && lhs_count != rhs_count) { error(lhs[0]->token, "Assignment count mismatch '%td' = '%td'", lhs_count, rhs_count); @@ -163,14 +156,15 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e // NOTE(bill): The original_entity's scope may not be same scope that it was inserted into // e.g. file entity inserted into its package scope String original_name = original_entity->token.string; + auto original_intern = entity_interned_name(original_entity); + u32 hash = original_entity->interned_name_hash.load(); + Scope *found_scope = nullptr; Entity *found_entity = nullptr; - scope_lookup_parent(original_entity->scope, original_name, &found_scope, &found_entity); + scope_lookup_parent(original_entity->scope, original_intern, &found_scope, &found_entity, hash); if (found_scope == nullptr) { return; } - rw_mutex_lock(&found_scope->mutex); - defer (rw_mutex_unlock(&found_scope->mutex)); // IMPORTANT NOTE(bill, 2021-04-10): Overriding behaviour was flawed in that the // original entity was still used check checked, but the checking was only @@ -179,7 +173,9 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e // Therefore two things can be done: the type can be assigned to state that it // has been "evaluated" and the variant data can be copied across - string_map_set(&found_scope->elements, original_name, new_entity); + rw_mutex_lock(&found_scope->mutex); + scope_map_insert(&found_scope->elements, original_intern, hash, new_entity); + rw_mutex_unlock(&found_scope->mutex); original_entity->flags |= EntityFlag_Overridden; original_entity->type = new_entity->type; @@ -525,6 +521,8 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, AttributeContext ac = {}; check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac); + e->deprecated_message = ac.deprecated_message; + if (e->kind == Entity_TypeName && ac.objc_class != "") { e->TypeName.objc_class_name = ac.objc_class; @@ -566,6 +564,11 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *super = ac.objc_superclass; while (super != nullptr) { + if (super->kind != Type_Named) { + error(e->token, "@(objc_superclass) Referenced type must be a named struct"); + break; + } + if (type_set_update(&super_set, super)) { error(e->token, "@(objc_superclass) Superclass hierarchy cycle encountered"); break; @@ -573,11 +576,6 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, check_single_global_entity(ctx->checker, super->Named.type_name, super->Named.type_name->decl_info); - if (super->kind != Type_Named) { - error(e->token, "@(objc_superclass) Referenced type must be a named struct"); - break; - } - Type* named_type = base_named_type(super); GB_ASSERT(named_type->kind == Type_Named); @@ -594,9 +592,7 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, super = named_type->Named.type_name->TypeName.objc_superclass; } } else { - if (ac.objc_superclass != nullptr) { - error(e->token, "@(objc_superclass) may only be applied when the @(obj_implement) attribute is also applied"); - } else if (ac.objc_ivar != nullptr) { + if (ac.objc_ivar != nullptr) { error(e->token, "@(objc_ivar) may only be applied when the @(obj_implement) attribute is also applied"); } else if (ac.objc_context_provider != nullptr) { error(e->token, "@(objc_context_provider) may only be applied when the @(obj_implement) attribute is also applied"); @@ -609,6 +605,13 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, } else if (ac.objc_is_implementation) { error(e->token, "@(objc_implement) may only be applied when the @(objc_class) attribute is also applied"); } + + if (ac.raddbg_type_view) { + RaddbgTypeView type_view = {}; + type_view.type = e->type; + type_view.view = ac.raddbg_type_view_string; + mpsc_enqueue(&ctx->info->raddbg_type_views_queue, type_view); + } } @@ -822,6 +825,12 @@ gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) { if (sig_compare(is_type_cstring, is_type_u8_multi_ptr, x, y)) { return true; } + if (sig_compare(is_type_cstring16, is_type_u16_ptr, x, y)) { + return true; + } + if (sig_compare(is_type_cstring16, is_type_u16_multi_ptr, x, y)) { + return true; + } if (sig_compare(is_type_uintptr, is_type_rawptr, x, y)) { return true; @@ -845,6 +854,50 @@ gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) { } } + Type *x_base = base_type(x); + Type *y_base = base_type(y); + + if (x_base == y_base) { + return true; + } + + if (x_base->kind == y_base->kind && + x_base->kind == Type_Struct) { + i64 xs = type_size_of(x_base); + i64 ys = type_size_of(y_base); + + i64 xa = type_align_of(x_base); + i64 ya = type_align_of(y_base); + + + if (x_base->Struct.is_raw_union == y_base->Struct.is_raw_union && + xs == ys && xa == ya) { + if (xs > 16) { + // @@ABI NOTE(bill): Just allow anything over 16-bytes to be allowed, because on all current ABIs + // it will be passed by point + // NOTE(bill): this must be changed when ABI changes + return true; + } + if (x_base->Struct.is_raw_union) { + return true; + } + if (x->Struct.fields.count == y->Struct.fields.count) { + for (isize i = 0; i < x->Struct.fields.count; i++) { + Entity *a = x->Struct.fields[i]; + Entity *b = y->Struct.fields[i]; + bool similar = signature_parameter_similar_enough(a->type, b->type); + if (!similar) { + // NOTE(bill): If the fields are not similar enough, then stop. + goto end; + } + } + } + // HACK NOTE(bill): Allow this for the time begin until it actually becomes a practical problem + return true; + } + } + +end:; return are_types_identical(x, y); } @@ -942,7 +995,7 @@ gb_internal Entity *init_entity_foreign_library(CheckerContext *ctx, Entity *e) error(ident, "foreign library names must be an identifier"); } else { String name = ident->Ident.token.string; - Entity *found = scope_lookup(ctx->scope, name); + Entity *found = scope_lookup(ctx->scope, ident->Ident.interned, ident->Ident.hash); if (found == nullptr) { if (is_blank_ident(name)) { @@ -1001,41 +1054,63 @@ gb_internal String handle_link_name(CheckerContext *ctx, Token token, String lin gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeContext &ac) { - if (!(ac.objc_name.len || ac.objc_is_class_method || ac.objc_type)) { + if (!ac.objc_type) { return; } - if (ac.objc_name.len == 0 && ac.objc_is_class_method) { - error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); - } else if (ac.objc_type == nullptr) { - error(e->token, "@(objc_name) requires that @(objc_type) to be set"); - } else if (ac.objc_name.len == 0 && ac.objc_type) { - error(e->token, "@(objc_name) is required with @(objc_type)"); - } else { - Type *t = ac.objc_type; - GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage. - Entity *tn = t->Named.type_name; + Type *t = ac.objc_type; + GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage. - GB_ASSERT(tn->kind == Entity_TypeName); + // Attempt to infer th objc_name automatically if the proc name contains + // the type name objc_type's name, followed by an underscore, as a prefix. + if (ac.objc_name.len == 0) { + String proc_name = e->token.string; + String type_name = t->Named.name; - if (tn->scope != e->scope) { - error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); + if (proc_name.len > type_name.len + 1 && + proc_name[type_name.len] == '_' && + str_eq(type_name, substring(proc_name, 0, type_name.len)) + ) { + ac.objc_name = substring(proc_name, type_name.len+1, proc_name.len); } else { + error(e->token, "@(objc_name) requires that @(objc_type) be set or inferred " + "by prefixing the proc name with the type and underscore: MyObjcType_myProcName :: proc()."); + } + } - // Enable implementation by default if the class is an implementer too and - // @objc_implement was not set to false explicitly in this proc. - bool implement = tn->TypeName.objc_is_implementation; - if (ac.objc_is_disabled_implement) { - implement = false; - } + Entity *tn = t->Named.type_name; + GB_ASSERT(tn->kind == Entity_TypeName); + + if (tn->scope != e->scope) { + error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); + } else { + // Enable implementation by default if the class is an implementer too and + // @objc_implement was not set to false explicitly in this proc. + bool implement = tn->TypeName.objc_is_implementation; + if( ac.objc_is_implementation && !tn->TypeName.objc_is_implementation ) { + error(e->token, "Cannot apply @(objc_is_implement) to a procedure whose type does not also have @(objc_is_implement) set"); + } + + if (ac.objc_is_disabled_implement) { + implement = false; + } + + String objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name; + + if (e->kind == Entity_Procedure) { + bool has_body = e->decl_info->proc_lit->ProcLit.body != nullptr; + e->Procedure.is_objc_impl_or_import = implement || !has_body; + e->Procedure.is_objc_class_method = ac.objc_is_class_method; + e->Procedure.objc_selector_name = objc_selector; + e->Procedure.objc_class = tn; + + auto &proc = e->type->Proc; + Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil; if (implement) { - GB_ASSERT(e->kind == Entity_Procedure); - - auto &proc = e->type->Proc; - Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil; - - if (!tn->TypeName.objc_is_implementation) { + if( !has_body ) { + error(e->token, "Procedures with @(objc_is_implement) must have a body"); + } else if (!tn->TypeName.objc_is_implementation) { error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied"); } else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) { error(e->token, "Objective-C instance methods implementations require the first parameter to be a pointer to the class type set by @(objc_type)"); @@ -1048,7 +1123,7 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon } else { // Always export unconditionally // NOTE(harold): This means check_objc_methods() MUST be called before - // e->Procedure.is_export is set in check_proc_decl()! + // e->Procedure.is_export is set in check_proc_decl()! if (ac.is_export) { error(e->token, "Explicit export not allowed when @(objc_implement) is set. It set exported implicitly"); } @@ -1060,7 +1135,7 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon ac.linkage = STR_LIT("strong"); auto method = ObjcMethodData{ ac, e }; - method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name; + method.ac.objc_selector = objc_selector; CheckerInfo *info = ctx->info; mutex_lock(&info->objc_method_mutex); @@ -1076,45 +1151,70 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon map_set(&info->objc_method_implementations, t, list); } } - } else if (ac.objc_selector != "") { - error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C implementations."); + } else if (!has_body) { + if (ac.objc_selector == "The @(objc_selector) attribute is required for imported Objective-C methods.") { + return; + } else if (proc.calling_convention != ProcCC_CDecl) { + error(e->token, "Imported Objective-C methods must use the \"c\" calling convention"); + return; + } else if (tn->TypeName.objc_context_provider) { + error(e->token, "Imported Objective-C class '%.*s' must not declare context providers.", tn->type->Named.name); + return; + } else if (tn->TypeName.objc_is_implementation) { + error(e->token, "Imported Objective-C methods used in a class with @(objc_implement) is not allowed."); + return; + } else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) { + error(e->token, "Objective-C instance methods require the first parameter to be a pointer to the class type set by @(objc_type)"); + return; + } } - - mutex_lock(&global_type_name_objc_metadata_mutex); - defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); - - if (!tn->TypeName.objc_metadata) { - tn->TypeName.objc_metadata = create_type_name_obj_c_metadata(); + else if(ac.objc_selector != "") { + error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C method implementations or are imported."); + return; } - auto *md = tn->TypeName.objc_metadata; - mutex_lock(md->mutex); - defer (mutex_unlock(md->mutex)); + } else { + GB_ASSERT(e->kind == Entity_ProcGroup); + if (tn->TypeName.objc_is_implementation) { + error(e->token, "Objective-C procedure groups cannot use the @(objc_implement) attribute."); + return; + } + } - if (!ac.objc_is_class_method) { - bool ok = true; - for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { - if (entry.name == ac.objc_name) { - error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); - ok = false; - break; - } + + mutex_lock(&global_type_name_objc_metadata_mutex); + defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); + + if (!tn->TypeName.objc_metadata) { + tn->TypeName.objc_metadata = create_type_name_obj_c_metadata(); + } + auto *md = tn->TypeName.objc_metadata; + mutex_lock(md->mutex); + defer (mutex_unlock(md->mutex)); + + if (!ac.objc_is_class_method) { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { + if (entry.interned.string() == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); + ok = false; + break; } - if (ok) { - array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); - } - } else { - bool ok = true; - for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { - if (entry.name == ac.objc_name) { - error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); - ok = false; - break; - } - } - if (ok) { - array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); + } + if (ok) { + array_add(&md->value_entries, TypeNameObjCMetadataEntry{string_interner_insert(ac.objc_name), e}); + } + } else { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { + if (entry.interned.string() == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); + ok = false; + break; } } + if (ok) { + array_add(&md->type_entries, TypeNameObjCMetadataEntry{string_interner_insert(ac.objc_name), e}); + } } } } @@ -1234,6 +1334,10 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { e->flags |= EntityFlag_Fini; } + if (build_context.disable_init_fini && (e->flags & (EntityFlag_Init|EntityFlag_Fini))) { + error(e->token, "@(init) and @(fini) have been disabled with '-disable-init-fini'"); + } + if (ac.set_cold) { e->flags |= EntityFlag_Cold; } @@ -1334,12 +1438,16 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { has_instrumentation = false; e->flags |= EntityFlag_Require; } else if (ac.instrumentation_enter) { + init_core_source_code_location(ctx->checker); if (!is_valid_instrumentation_call(e->type)) { init_core_source_code_location(ctx->checker); gbString s = type_to_string(e->type); error(e->token, "@(instrumentation_enter) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s); gb_string_free(s); } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { + error(e->token, "@(instrumentation_enter) procedures must be declared at the file scope"); + } MUTEX_GUARD(&ctx->info->instrumentation_mutex); if (ctx->info->instrumentation_enter_entity != nullptr) { error(e->token, "@(instrumentation_enter) has already been set"); @@ -1356,6 +1464,9 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { error(e->token, "@(instrumentation_exit) procedures must have the type '%s', got %s", instrumentation_proc_type_str, s); gb_string_free(s); } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { + error(e->token, "@(instrumentation_exit) procedures must be declared at the file scope"); + } MUTEX_GUARD(&ctx->info->instrumentation_mutex); if (ctx->info->instrumentation_exit_entity != nullptr) { error(e->token, "@(instrumentation_exit) has already been set"); @@ -1370,10 +1481,19 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { e->Procedure.has_instrumentation = has_instrumentation; e->Procedure.no_sanitize_address = ac.no_sanitize_address; + e->Procedure.no_sanitize_memory = ac.no_sanitize_memory; + e->Procedure.no_sanitize_thread = ac.no_sanitize_thread; + + e->Procedure.fast_math_flags = ac.fast_math_flags; e->deprecated_message = ac.deprecated_message; e->warning_message = ac.warning_message; ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix, ac.link_suffix); + + if (ac.link_section.len > 0) { + e->Procedure.link_section = ac.link_section; + } + if (ac.has_disabled_proc) { if (ac.disabled_proc) { e->flags |= EntityFlag_Disabled; @@ -1414,10 +1534,26 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { error(e->token, "Procedure type of 'main' was expected to be 'proc()', got %s", str); gb_string_free(str); } - if (pt->calling_convention != default_calling_convention()) { - error(e->token, "Procedure 'main' cannot have a custom calling convention"); + if (build_context.bedrock) { + switch (pt->calling_convention) { + case ProcCC_Odin: + case ProcCC_Contextless: + // Okay + break; + default: + error(e->token, "Procedure 'main' cannot have a custom calling convention beyond \"odin\" and \"contextless\" with '-bedrock'"); + pt->calling_convention = ProcCC_Odin; + break; + } + + } else { + if (pt->calling_convention != default_calling_convention()) { + error(e->token, "Procedure 'main' cannot have a custom calling convention"); + } + pt->calling_convention = default_calling_convention(); + } - pt->calling_convention = default_calling_convention(); + if (e->pkg->kind == Package_Init) { if (ctx->info->entry_point != nullptr) { error(e->token, "Redeclaration of the entry pointer procedure 'main'"); @@ -1447,9 +1583,9 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { if (is_foreign) { error(pl->body, "A foreign procedure cannot have a body"); } - if (proc_type->Proc.c_vararg) { - error(pl->body, "A procedure with a '#c_vararg' field cannot have a body and must be foreign"); - } + // if (proc_type->Proc.c_vararg) { + // error(pl->body, "A procedure with a '#c_vararg' field cannot have a body and must be foreign"); + // } d->scope = ctx->scope; @@ -1457,7 +1593,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { if (!pt->is_polymorphic) { check_procedure_later(ctx->checker, ctx->file, e->token, d, proc_type, pl->body, pl->tags); } - } else if (!is_foreign) { + } else if (!is_foreign && !e->Procedure.is_objc_impl_or_import) { if (e->Procedure.is_export) { error(e->token, "Foreign export procedures must have a body"); } else { @@ -1504,7 +1640,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { if (is_arch_wasm() && foreign_library != nullptr) { // NOTE(bill): this must be delayed because the foreign import paths might not be evaluated yet until much later mpsc_enqueue(&ctx->info->foreign_decls_to_check, e); - } else { + } else if (!e->Procedure.is_objc_impl_or_import) { check_foreign_procedure(ctx, e, d); } } else { @@ -1527,7 +1663,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { "\tother at %s", LIT(name), token_pos_to_string(pos)); } else if (name == "main") { - if (d->entity->pkg->kind != Package_Runtime) { + if (d->entity.load()->pkg->kind != Package_Runtime) { error(d->proc_lit, "The link name 'main' is reserved for internal use"); } } else { @@ -1543,7 +1679,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } } -gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, Ast *init_expr) { +gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_expr) { GB_ASSERT(e->type == nullptr); GB_ASSERT(e->kind == Entity_Variable); @@ -1662,9 +1798,36 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast Operand o = {}; check_expr_with_type_hint(ctx, &o, init_expr, e->type); + if (check_vet_shadowing_assignment(ctx->checker, e, init_expr)) { + error(e->token, "Illegal declaration cycle of `%.*s`", LIT(e->token.string)); + o.mode = Addressing_Invalid; + o.type = t_invalid; + e->type = t_invalid; + } check_init_variable(ctx, e, &o, str_lit("variable declaration")); if (e->Variable.is_rodata && o.mode != Addressing_Constant) { + ERROR_BLOCK(); error(o.expr, "Variables declared with @(rodata) must have constant initialization"); + Ast *expr = unparen_expr(o.expr); + if (is_type_struct(e->type) && expr && expr->kind == Ast_CompoundLit) { + ast_node(cl, CompoundLit, expr); + for (Ast *elem_ : cl->elems) { + Ast *elem = elem_; + if (elem->kind == Ast_FieldValue) { + elem = elem->FieldValue.value; + } + elem = unparen_expr(elem); + + Entity *e = entity_of_node(elem); + if (elem->tav.mode != Addressing_Constant && e == nullptr && elem->kind != Ast_ProcLit) { + Token tok = ast_token(elem); + TokenPos pos = tok.pos; + gbString s = type_to_string(type_of_expr(elem)); + error_line("%s Element is not constant, which is required for @(rodata), of type %s\n", token_pos_to_string(pos), s); + gb_string_free(s); + } + } + } } check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed"); @@ -1686,9 +1849,25 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D PtrSet entity_set = {}; ptr_set_init(&entity_set, 2*pg->args.count); - for (Ast *arg : pg->args) { + for (Ast *arg_ : pg->args) { + Ast *arg = arg_; Entity *e = nullptr; Operand o = {}; + if (arg->kind == Ast_BinaryExpr && arg->BinaryExpr.op.kind == Token_where) { + Ast *cond_expr = arg->BinaryExpr.right; + Operand cond = {}; + check_expr(ctx, &cond, cond_expr); + if (cond.mode != Addressing_Invalid) { + if (cond.mode != Addressing_Constant || !is_type_boolean(cond.type) || cond.value.kind != ExactValue_Bool) { + error(arg, "Expected a constant binary expression for the 'where' clause"); + } else if (!cond.value.value_bool) { + continue; + } + } + + arg = arg->BinaryExpr.left; + } + if (arg->kind == Ast_Ident) { e = check_ident(ctx, &o, arg, nullptr, nullptr, true); } else if (arg->kind == Ast_SelectorExpr) { @@ -1753,7 +1932,8 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, D ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type); bool both_have_where_clauses = false; - if (p->decl_info->proc_lit != nullptr && q->decl_info->proc_lit != nullptr) { + if (p->decl_info != nullptr && q->decl_info != nullptr && + p->decl_info->proc_lit != nullptr && q->decl_info->proc_lit != nullptr) { GB_ASSERT(p->decl_info->proc_lit->kind == Ast_ProcLit); GB_ASSERT(q->decl_info->proc_lit->kind == Ast_ProcLit); auto pl = &p->decl_info->proc_lit->ProcLit; @@ -1836,9 +2016,34 @@ gb_internal void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, c.scope = d->scope; c.decl = d; c.type_level = 0; + c.curr_proc_calling_convention = ProcCC_Contextless; + + auto prev_flags = c.scope->flags; + defer (c.scope->flags = prev_flags); + + if (check_feature_flags(ctx, d->decl_node) & OptInFeatureFlag_GlobalContext) { + c.scope->flags |= ScopeFlag_ContextDefined; + } else { + c.scope->flags &= ~ScopeFlag_ContextDefined; + } + e->parent_proc_decl = c.curr_proc_decl; e->state = EntityState_InProgress; + bool track_cycle_path = false; + switch (e->kind) { + case Entity_Variable: + case Entity_Constant: + case Entity_TypeName: + track_cycle_path = true; + break; + } + if (track_cycle_path) { + check_type_path_push(&c, e); + } + defer (if (track_cycle_path) { + check_type_path_pop(&c); + }); switch (e->kind) { case Entity_Variable: @@ -1882,7 +2087,7 @@ gb_internal void add_deps_from_child_to_parent(DeclInfo *decl) { rw_mutex_shared_lock(&decl->deps_mutex); rw_mutex_lock(&decl->parent->deps_mutex); - for (Entity *e : decl->deps) { + FOR_PTR_SET(e, decl->deps) { ptr_set_add(&decl->parent->deps, e); } @@ -1934,8 +2139,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de ctx->curr_proc_sig = type; ctx->curr_proc_calling_convention = type->Proc.calling_convention; - if (decl->parent && decl->entity && decl->parent->entity) { - decl->entity->parent_proc_decl = decl->parent; + if (decl->parent && decl->entity.load() && decl->parent->entity) { + decl->entity.load()->parent_proc_decl = decl->parent; } if (ctx->pkg->name != "runtime") { @@ -1948,9 +2153,9 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de ast_node(bs, BlockStmt, body); + TEMPORARY_ALLOCATOR_GUARD(); Array using_entities = {}; - using_entities.allocator = heap_allocator(); - defer (array_free(&using_entities)); + using_entities.allocator = temporary_allocator(); { if (type->Proc.param_count > 0) { @@ -2019,7 +2224,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de rw_mutex_unlock(&ctx->scope->mutex); - bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated); + bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated.load(std::memory_order_relaxed)); if (!where_clause_ok) { // NOTE(bill, 2019-08-31): Don't check the body as the where clauses failed return false; @@ -2037,15 +2242,15 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de } GB_ASSERT(decl->proc_checked_state != ProcCheckedState_Checked); - if (decl->defer_use_checked) { + if (decl->defer_use_checked.load(std::memory_order_relaxed)) { GB_ASSERT(is_type_polymorphic(type, true)); - error(token, "Defer Use Checked: %.*s", LIT(decl->entity->token.string)); - GB_ASSERT(decl->defer_use_checked == false); + error(token, "Defer Use Checked: %.*s", LIT(decl->entity.load()->token.string)); + GB_ASSERT(decl->defer_use_checked.load(std::memory_order_relaxed) == false); } check_stmt_list(ctx, bs->stmts, Stmt_CheckScopeDecls); - decl->defer_use_checked = true; + decl->defer_use_checked.store(true, std::memory_order_relaxed); for (Ast *stmt : bs->stmts) { if (stmt->kind == Ast_ValueDecl) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 10b37bbf3..4709691c5 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -129,6 +129,8 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type gb_internal bool is_exact_value_zero(ExactValue const &v); +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(CheckerContext *c, Ast *node); + enum LoadDirectiveResult { LoadDirective_Success = 0, LoadDirective_Error = 1, @@ -151,13 +153,19 @@ gb_internal bool is_load_directive_call(Ast *call) { gb_internal LoadDirectiveResult check_load_directive(CheckerContext *c, Operand *operand, Ast *call, Type *type_hint, bool err_on_not_found); gb_internal void check_did_you_mean_print(DidYouMeanAnswers *d, char const *prefix = "") { + int limit = build_context.did_you_mean_limit; auto results = did_you_mean_results(d); + int count = 0; if (results.count != 0) { error_line("\tSuggestion: Did you mean?\n"); for (auto const &result : results) { String const &target = result.target; error_line("\t\t%s%.*s\n", prefix, LIT(target)); // error_line("\t\t%.*s %td\n", LIT(target), results[i].distance); + if (limit > 0 && ++count == limit) { + error_line("\t\t... and %td more ...", results.count - limit); + break; + } } } } @@ -175,11 +183,11 @@ gb_internal void populate_check_did_you_mean_objc_entity(StringSet *set, Entity if (is_type) { for (auto const &entry : objc_metadata->type_entries) { - string_set_add(set, entry.name); + string_set_add(set, entry.interned.string()); } } else { for (auto const &entry : objc_metadata->value_entries) { - string_set_add(set, entry.name); + string_set_add(set, entry.interned.string()); } } @@ -263,6 +271,9 @@ gb_internal void check_did_you_mean_scope(String const &name, Scope *scope, char gb_internal Entity *entity_from_expr(Ast *expr) { expr = unparen_expr(expr); + if (expr == nullptr) { + return nullptr; + } switch (expr->kind) { case Ast_Ident: return expr->Ident.entity; @@ -488,7 +499,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E rw_mutex_shared_unlock(&gen_procs->mutex); // @local-mutex } else { - gen_procs = gb_alloc_item(permanent_allocator(), GenProcsData); + gen_procs = permanent_alloc_item(); gen_procs->procs.allocator = heap_allocator(); base_entity->Procedure.gen_procs = gen_procs; mutex_unlock(&base_entity->Procedure.gen_procs_mutex); // @entity-mutex @@ -503,7 +514,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E // NOTE(bill): Reset scope from the failed procedure type scope->head_child.store(nullptr, std::memory_order_relaxed); - string_map_clear(&scope->elements); + scope_map_clear(&scope->elements); ptr_set_clear(&scope->imported); // LEAK NOTE(bill): Cloning this AST may be leaky but this is not really an issue due to arena-based allocation @@ -525,7 +536,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E DeclInfo *decl = other->decl_info; if (decl->proc_checked_state != ProcCheckedState_Checked) { - ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); + ProcInfo *proc_info = permanent_alloc_item(); proc_info->file = other->file; proc_info->token = other->token; proc_info->decl = decl; @@ -582,6 +593,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E d->proc_lit = proc_lit; d->proc_checked_state = ProcCheckedState_Unchecked; d->defer_use_checked = false; + d->para_poly_original = old_decl->entity; Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); entity->state.store(EntityState_Resolved); @@ -603,7 +615,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E entity->flags |= EntityFlag_Disabled; } - d->entity = entity; + d->entity.store(entity); AstFile *file = nullptr; { @@ -618,7 +630,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E array_add(&gen_procs->procs, entity); rw_mutex_unlock(&gen_procs->mutex); // @local-mutex - ProcInfo *proc_info = gb_alloc_item(permanent_allocator(), ProcInfo); + ProcInfo *proc_info = permanent_alloc_item(); proc_info->file = file; proc_info->token = token; proc_info->decl = d; @@ -643,7 +655,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E gb_internal bool check_polymorphic_procedure_assignment(CheckerContext *c, Operand *operand, Type *type, Ast *poly_def_node, PolyProcData *poly_proc_data) { if (operand->expr == nullptr) return false; - Entity *base_entity = entity_of_node(operand->expr); + Entity *base_entity = entity_from_expr(operand->expr); if (base_entity == nullptr) return false; return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_def_node, poly_proc_data); } @@ -655,6 +667,7 @@ gb_internal bool find_or_generate_polymorphic_procedure_from_parameters(CheckerC gb_internal bool check_type_specialization_to(CheckerContext *c, Type *specialization, Type *type, bool compound, bool modify_type); gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool compound, bool modify_type); gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type); +gb_internal bool check_proc_params_assignable(CheckerContext *c, Type *x, Type *y); #define MAXIMUM_TYPE_DISTANCE 10 @@ -816,9 +829,11 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand } } - if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) { - if (c->in_enum_type) { - return 3; + if (c != nullptr) { + if (is_type_enum(dst) && are_types_identical(dst->Enum.base_type, operand->type)) { + if (c->in_enum_type) { + return 3; + } } } @@ -876,7 +891,7 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand if (score >= 0) { return score+2; } - } else if (is_type_untyped(src)) { + } else if (is_type_untyped(src) || is_type_struct(type_deref(src))) { // allow for subtyping of structs i64 prev_lowest_score = -1; i64 lowest_score = -1; for (Type *vt : dst->Union.variants) { @@ -913,8 +928,12 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand add_entity_use(c, operand->expr, e); return 4; } + + if (is_type_proc(src) && are_proc_properties_identical(dst,src) && check_proc_params_assignable(c, dst, src)) { + return 4; + } } - + if (is_type_complex_or_quaternion(dst)) { Type *elem = base_complex_elem_type(dst); if (are_types_identical(elem, base_type(src))) { @@ -995,14 +1014,34 @@ gb_internal i64 assign_score_function(i64 distance, bool is_variadic=false) { gb_internal bool check_is_assignable_to_with_score(CheckerContext *c, Operand *operand, Type *type, i64 *score_, bool is_variadic=false, bool allow_array_programming=true) { - i64 score = 0; - i64 distance = check_distance_between_types(c, operand, type, allow_array_programming); - bool ok = distance >= 0; - if (ok) { - score = assign_score_function(distance, is_variadic); + if (c == nullptr) { + GB_ASSERT(operand->mode == Addressing_Value); + GB_ASSERT(is_type_typed(operand->type)); } - if (score_) *score_ = score; - return ok; + if (operand->mode == Addressing_Invalid || type == t_invalid) { + if (score_) *score_ = 0; + return false; + } + + // Handle polymorphic procedure used as default parameter + if (operand->mode == Addressing_Value && is_type_proc(type) && is_type_proc(operand->type)) { + Entity *e = entity_from_expr(operand->expr); + if (e != nullptr && e->kind == Entity_Procedure && is_type_polymorphic(e->type) && !is_type_polymorphic(type)) { + // Special case: Allow a polymorphic procedure to be used as default value for concrete proc type + // during the initial check. It will be properly instantiated when actually used. + if (score_) *score_ = assign_score_function(1); + return true; + } + } + + i64 score = check_distance_between_types(c, operand, type, allow_array_programming); + if (score >= 0) { + if (score_) *score_ = assign_score_function(score, is_variadic); + return true; + } + + if (score_) *score_ = 0; + return false; } @@ -1018,6 +1057,51 @@ gb_internal bool internal_check_is_assignable_to(Type *src, Type *dst) { return check_is_assignable_to(nullptr, &x, dst); } +gb_internal bool check_proc_params_assignable(CheckerContext *c, Type *dst, Type *src) { + GB_ASSERT(dst->kind == Type_Proc); + GB_ASSERT(src->kind == Type_Proc); + + if (!dst->Proc.params || !src->Proc.params) { + return false; + } + + if (!are_types_identical(src->Proc.results, dst->Proc.results)) { + return false; + } + + auto& dst_tuple = dst->Proc.params->Tuple; + auto& src_tuple = src->Proc.params->Tuple; + + if (dst_tuple.variables.count == src_tuple.variables.count && dst_tuple.is_packed == src_tuple.is_packed) { + for_array(i, dst_tuple.variables) { + Entity *edst = dst_tuple.variables[i]; + Entity *esrc = src_tuple.variables[i]; + + if (edst->kind != esrc->kind || !are_types_identical(edst->type, esrc->type)) { + + // Pointers to subtype fields that are at byte offset 0 are OK + if (edst->type->kind == Type_Pointer && esrc->type->kind == Type_Pointer && + is_type_struct(esrc->type->Pointer.elem) && + check_is_assignable_to_using_offset_zero_subtype(esrc->type->Pointer.elem, edst->type->Pointer.elem)) { + continue; + } + + return false; + } + + if (edst->kind == Entity_Constant && !compare_exact_values(Token_CmpEq, edst->Constant.value, esrc->Constant.value)) { + // NOTE(bill): This is needed for polymorphic procedures + return false; + } + } + + return true; + } + + return false; +} + + gb_internal AstPackage *get_package_of_type(Type *type) { for (;;) { if (type == nullptr) { @@ -1056,18 +1140,25 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ return; } - // Grab definite or indefinite article matching `context_name`, or "" if not found. - String article = error_article(context_name); + if (operand->mode == Addressing_Type && is_type_typeid(type)) { + add_type_info_type(c, operand->type); + add_type_and_value(c, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type)); + return; + } if (is_type_untyped(operand->type)) { Type *target_type = type; if (type == nullptr || is_type_any(type)) { if (type == nullptr && is_type_untyped_uninit(operand->type)) { + String article = error_article(context_name); // Grab definite or indefinite article matching `context_name`, or "" if not found. + error(operand->expr, "Use of --- in %.*s%.*s", LIT(article), LIT(context_name)); operand->mode = Addressing_Invalid; return; } if (type == nullptr && is_type_untyped_nil(operand->type)) { + String article = error_article(context_name); // Grab definite or indefinite article matching `context_name`, or "" if not found. + error(operand->expr, "Use of untyped nil in %.*s%.*s", LIT(article), LIT(context_name)); operand->mode = Addressing_Invalid; return; @@ -1105,7 +1196,11 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ x.mode = Addressing_Value; x.type = t; if (check_is_assignable_to(c, &x, type)) { - add_entity_use(c, operand->expr, e); + if (operand->expr->kind == Ast_SelectorExpr) { + add_entity_use(c, operand->expr->SelectorExpr.selector, e); + } else { + add_entity_use(c, operand->expr, e); + } good = true; break; } @@ -1121,6 +1216,8 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ defer (gb_string_free(op_type_str)); defer (gb_string_free(expr_str)); + String article = error_article(context_name); // Grab definite or indefinite article matching `context_name`, or "" if not found. + // TODO(bill): is this a good enough error message? error(operand->expr, "Cannot assign overloaded procedure group '%s' to '%s' in %.*s%.*s", @@ -1149,6 +1246,8 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ defer (gb_string_free(op_type_str)); defer (gb_string_free(expr_str)); + String article = error_article(context_name); // Grab definite or indefinite article matching `context_name`, or "" if not found. + switch (operand->mode) { case Addressing_Builtin: error(operand->expr, @@ -1291,7 +1390,7 @@ gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source Type *gt = *gt_; GB_ASSERT(gt->kind == Type_Generic); - Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.name); + Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.interned_name, 0); GB_ASSERT(e != nullptr); if (e->kind == Entity_TypeName) { *gt_ = nullptr; @@ -1378,6 +1477,17 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T return is_polymorphic_type_assignable(c, poly->MultiPointer.elem, source->Pointer.elem, true, modify_type); } return false; + + case Type_SoaPointer: + if (source->kind == Type_SoaPointer) { + isize level = check_is_assignable_to_using_subtype(source->SoaPointer.elem, poly->SoaPointer.elem, /*level*/0, /*src_is_ptr*/false, /*allow_polymorphic*/true); + if (level > 0) { + return true; + } + return is_polymorphic_type_assignable(c, poly->SoaPointer.elem, source->SoaPointer.elem, true, modify_type); + } + return false; + case Type_Array: if (source->kind == Type_Array) { if (poly->Array.generic_count != nullptr) { @@ -1392,7 +1502,7 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T if (poly->Array.generic_count != nullptr) { Type *gt = poly->Array.generic_count; GB_ASSERT(gt->kind == Type_Generic); - Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.name); + Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.interned_name, 0); GB_ASSERT(e != nullptr); if (e->kind == Entity_TypeName) { Type *index = source->EnumeratedArray.index; @@ -1452,6 +1562,22 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T return is_polymorphic_type_assignable(c, poly->DynamicArray.elem, source->DynamicArray.elem, true, modify_type); } return false; + + case Type_FixedCapacityDynamicArray: + if (source->kind == Type_FixedCapacityDynamicArray) { + if (poly->FixedCapacityDynamicArray.generic_capacity != nullptr) { + if (!polymorphic_assign_index(&poly->FixedCapacityDynamicArray.generic_capacity, + &poly->FixedCapacityDynamicArray.capacity, + source->FixedCapacityDynamicArray.capacity)) { + return false; + } + } + if (poly->FixedCapacityDynamicArray.capacity == source->FixedCapacityDynamicArray.capacity) { + return is_polymorphic_type_assignable(c, poly->FixedCapacityDynamicArray.elem, source->FixedCapacityDynamicArray.elem, true, modify_type); + } + } + return false; + case Type_Slice: if (source->kind == Type_Slice) { return is_polymorphic_type_assignable(c, poly->Slice.elem, source->Slice.elem, true, modify_type); @@ -1463,6 +1589,11 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T case Type_BitSet: if (source->kind == Type_BitSet) { + if (!is_type_polymorphic(poly->BitSet.elem)) { + if (poly->BitSet.upper != source->BitSet.upper || poly->BitSet.lower != source->BitSet.lower) { + return false; + } + } if (!is_polymorphic_type_assignable(c, poly->BitSet.elem, source->BitSet.elem, true, modify_type)) { return false; } @@ -1711,9 +1842,9 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam GB_ASSERT(n->kind == Ast_Ident); o->mode = Addressing_Invalid; o->expr = n; - String name = n->Ident.token.string; + auto name = n->Ident.token.string; - Entity *e = scope_lookup(c->scope, name); + Entity *e = scope_lookup(c->scope, n->Ident.interned, n->Ident.hash); if (e == nullptr) { if (is_blank_ident(name)) { error(n, "'_' cannot be used as a value"); @@ -1793,6 +1924,16 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam if (e->state == EntityState_Unresolved) { check_entity_decl(c, e, nullptr, named_type); } + switch (e->kind) { + case Entity_Constant: + case Entity_Variable: + case Entity_TypeName: + if (check_cycle(c, e, true)) { + o->type = t_invalid; + return e; + } + break; + } if (e->type == nullptr) { // TODO(bill): Which is correct? return or compiler_error? // compiler_error("How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(name)); @@ -1990,6 +2131,10 @@ gb_internal bool check_binary_op(CheckerContext *c, Operand *o, Token op) { /*fallthrough*/ case Token_Mul: case Token_MulEq: + if (is_type_bit_set(type)) { + error(op, "Operator '%.*s' is not allowed with bit sets", LIT(op.string)); + return false; + } case Token_AddEq: if (is_type_bit_set(type)) { return true; @@ -2070,6 +2215,36 @@ gb_internal bool check_binary_op(CheckerContext *c, Operand *o, Token op) { } +gb_internal bool check_update_float_precision(ExactValue *value, Type *type) { + type = core_type(type); + if (type->kind != Type_Basic) { + return false; + } + + switch (type->Basic.kind) { + case Basic_f16: + case Basic_f16le: + case Basic_f16be: + // TODO(bill): This is not technically correct for 16-bit floats, but it will be better than before + /*fallthrough*/ + case Basic_f32: + case Basic_f32le: + case Basic_f32be: + { + f64 x_64 = exact_value_to_f64(*value); + f32 x_32 = cast(f32)x_64; + if (cast(f64)x_32 != x_64) { + // make sure there IS precision loss + *value = exact_value_float(cast(f64)x_32); + return true; + } + } + break; + } + + return false; +} + gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Type *type, ExactValue *out_value) { if (in_value.kind == ExactValue_Invalid) { @@ -2083,11 +2258,11 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i } else if (is_type_boolean(type)) { return in_value.kind == ExactValue_Bool; } else if (is_type_string(type)) { + if (in_value.kind == ExactValue_String16) { + return is_type_string16(type) || is_type_cstring16(type); + } return in_value.kind == ExactValue_String; } else if (is_type_integer(type) || is_type_rune(type)) { - if (in_value.kind == ExactValue_Bool) { - return false; - } ExactValue v = exact_value_to_integer(in_value); if (v.kind != ExactValue_Integer) { return false; @@ -2102,9 +2277,13 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i BigInt i = v.value_integer; i64 byte_size = type_size_of(type); - BigInt umax = {}; - BigInt imin = {}; - BigInt imax = {}; + BigInt umax; + BigInt imin; + BigInt imax; + + u64 umax_64 = 0; + i64 imin_64 = 0; + i64 imax_64 = 0; if (c->bit_field_bit_size > 0) { i64 bit_size = gb_min(cast(i64)(8*byte_size), cast(i64)c->bit_field_bit_size); @@ -2127,10 +2306,10 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i big_int_shl_eq(&imax, &bi); mp_decr(&imax); } else { - if (byte_size < 16) { - big_int_from_u64(&umax, unsigned_integer_maxs[byte_size]); - big_int_from_i64(&imin, signed_integer_mins[byte_size]); - big_int_from_i64(&imax, signed_integer_maxs[byte_size]); + if (byte_size <= 8) { + umax_64 = unsigned_integer_maxs[byte_size]; + imin_64 = signed_integer_mins[byte_size]; + imax_64 = signed_integer_maxs[byte_size]; } else { big_int_from_u64(&umax, 1); big_int_from_i64(&imin, 1); @@ -2158,16 +2337,27 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i case Basic_i16: case Basic_i32: case Basic_i64: - case Basic_i128: case Basic_int: case Basic_i16le: case Basic_i32le: case Basic_i64le: - case Basic_i128le: case Basic_i16be: case Basic_i32be: case Basic_i64be: + if (c->bit_field_bit_size == 0) { + // return imin <= i && i <= imax; + if (!big_int_can_be_represented_in_64_bits(&i)) { + return false; + } + + i64 val64 = big_int_to_i64(&i); + + return imin_64 <= val64 && val64 <= imax_64; + } + /*fallthrough*/ + case Basic_i128le: + case Basic_i128: case Basic_i128be: { // return imin <= i && i <= imax; @@ -2180,17 +2370,30 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i case Basic_u16: case Basic_u32: case Basic_u64: - case Basic_u128: case Basic_uint: case Basic_uintptr: case Basic_u16le: case Basic_u32le: case Basic_u64le: - case Basic_u128le: case Basic_u16be: case Basic_u32be: case Basic_u64be: + if (c->bit_field_bit_size == 0) { + if (big_int_is_neg(&i)) { + return false; + } + if (!big_int_can_be_represented_in_64_bits(&i)) { + return false; + } + u64 val64 = big_int_to_u64(&i); + + return val64 <= umax_64; + + } + /*fallthrough*/ + case Basic_u128: + case Basic_u128le: case Basic_u128be: { // return 0ull <= i && i <= umax; @@ -2208,18 +2411,20 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i if (v.kind != ExactValue_Float) { return false; } + check_update_float_precision(&v, type); if (out_value) *out_value = v; switch (type->Basic.kind) { case Basic_f16: - case Basic_f32: - case Basic_f64: - return true; - case Basic_f16le: case Basic_f16be: + /*fallthrough*/ + case Basic_f32: case Basic_f32le: case Basic_f32be: + return true; + + case Basic_f64: case Basic_f64le: case Basic_f64be: return true; @@ -2297,11 +2502,28 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i if (in_value.kind == ExactValue_String) { return false; } + if (in_value.kind == ExactValue_String16) { + return false; + } if (out_value) *out_value = in_value; } else if (is_type_bit_set(type)) { if (in_value.kind == ExactValue_Integer) { return true; } + } else if (is_type_typeid(type)) { + + if (in_value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, in_value.value_compound); + if (cl->elems.count == 0) { + in_value = exact_value_typeid(nullptr); + } else { + return false; + } + } + if (in_value.kind == ExactValue_Typeid) { + if (out_value) *out_value = in_value; + return true; + } } return false; @@ -2401,27 +2623,27 @@ gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o Type *s = src->Array.elem; Type *d = dst->Slice.elem; if (are_types_identical(s, d)) { - error_line("\tSuggestion: the array expression may be sliced with %s[:]\n", a); + error_line("\tSuggestion: The array expression may be sliced with %s[:]\n", a); } } else if (is_type_dynamic_array(src) && is_type_slice(dst)) { Type *s = src->DynamicArray.elem; Type *d = dst->Slice.elem; if (are_types_identical(s, d)) { - error_line("\tSuggestion: the dynamic array expression may be sliced with %s[:]\n", a); + error_line("\tSuggestion: The dynamic array expression may be sliced with %s[:]\n", a); } }else if (are_types_identical(src, dst) && !are_types_identical(o->type, type)) { - error_line("\tSuggestion: the expression may be directly casted to type %s\n", b); + error_line("\tSuggestion: The expression may be directly casted to type %s\n", b); } else if (are_types_identical(src, t_string) && is_type_u8_slice(dst)) { - error_line("\tSuggestion: a string may be transmuted to %s\n", b); - error_line("\t This is an UNSAFE operation as string data is assumed to be immutable, \n"); + error_line("\tSuggestion: A string may be transmuted to %s\n", b); + error_line("\t This is an UNSAFE operation as string data is assumed to be immutable,\n"); error_line("\t whereas slices in general are assumed to be mutable.\n"); } else if (is_type_u8_slice(src) && are_types_identical(dst, t_string) && o->mode != Addressing_Constant) { - error_line("\tSuggestion: the expression may be casted to %s\n", b); + error_line("\tSuggestion: The expression may be casted to %s\n", b); } else if (check_integer_exceed_suggestion(c, o, type, max_bit_size)) { return; } else if (is_expr_inferred_fixed_array(c->type_hint_expr) && is_type_array_like(type) && is_type_array_like(o->type)) { gbString s = expr_to_string(c->type_hint_expr); - error_line("\tSuggestion: make sure that `%s` is attached to the compound literal directly\n", s); + error_line("\tSuggestion: Make sure that `%s` is attached to the compound literal directly\n", s); gb_string_free(s); } else if (is_type_pointer(type) && o->mode == Addressing_Variable && @@ -2432,7 +2654,8 @@ gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o } else if (is_type_pointer(o->type) && are_types_identical(type_deref(o->type), type)) { gbString s = expr_to_string(o->expr); - error_line("\tSuggestion: Did you mean `%s^`\n", s); + if (s[0] == '&') error_line("\tSuggestion: Did you mean `%s`\n", &s[1]); + else error_line("\tSuggestion: Did you mean `%s^`\n", s); gb_string_free(s); } } @@ -2727,6 +2950,43 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * return; } + + case Token_MulMul: { // 'expand_values' operator + if (!o->type) { + return; + } + + Type *type = base_type(o->type); + if (!is_type_struct(type) && !is_type_array(type)) { + gbString type_str = type_to_string(o->type); + error(node, "Expected a struct or array type to 'expand_values', got '%s'", type_str); + gb_string_free(type_str); + return; + } + + Type *tuple = alloc_type_tuple(); + + if (is_type_struct(type)) { + isize variable_count = type->Struct.fields.count; + tuple->Tuple.variables = permanent_slice_make(variable_count); + // NOTE(bill): don't copy the entities, this should be good enough + gb_memmove_array(tuple->Tuple.variables.data, type->Struct.fields.data, variable_count); + } else if (is_type_array(type)) { + isize variable_count = cast(isize)type->Array.count; + tuple->Tuple.variables = permanent_slice_make(variable_count); + for (isize i = 0; i < variable_count; i++) { + tuple->Tuple.variables[i] = alloc_entity_array_elem(nullptr, blank_token, type->Array.elem, cast(i32)i); + } + } + o->type = tuple; + o->mode = Addressing_Value; + + if (tuple->Tuple.variables.count == 1) { + o->type = tuple->Tuple.variables[0]->type; + } + + return; + } } if (!check_unary_op(c, o, op)) { @@ -2839,6 +3099,14 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t add_package_dependency(c, "runtime", "string_eq"); add_package_dependency(c, "runtime", "string_ne"); break; + case Basic_cstring16: + add_package_dependency(c, "runtime", "cstring16_eq"); + add_package_dependency(c, "runtime", "cstring16_ne"); + break; + case Basic_string16: + add_package_dependency(c, "runtime", "string16_eq"); + add_package_dependency(c, "runtime", "string16_ne"); + break; } break; case Type_Struct: @@ -2886,14 +3154,21 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper if (check_is_assignable_to(c, x, y->type) || check_is_assignable_to(c, y, x->type)) { + if (x->type->failure || y->type->failure) { + // // skip any failures + x->mode = Addressing_Value; + x->type = t_untyped_bool; + return; + } + Type *err_type = x->type; bool defined = false; switch (op) { case Token_CmpEq: case Token_NotEq: - defined = (is_type_comparable(x->type) && is_type_comparable(y->type)) || - (is_operand_nil(*x) && type_has_nil(y->type)) || - (is_operand_nil(*y) && type_has_nil(x->type)); + defined = ((is_operand_nil(*x) && type_has_nil(y->type)) || + (is_operand_nil(*y) && type_has_nil(x->type)) || + is_type_comparable(x->type) && is_type_comparable(y->type)); break; case Token_Lt: case Token_Gt: @@ -3010,7 +3285,25 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper case Token_Lt: add_package_dependency(c, "runtime", "cstring_lt"); break; case Token_Gt: add_package_dependency(c, "runtime", "cstring_gt"); break; case Token_LtEq: add_package_dependency(c, "runtime", "cstring_le"); break; - case Token_GtEq: add_package_dependency(c, "runtime", "cstring_gt"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "cstring_ge"); break; + } + } else if (is_type_cstring16(x->type) && is_type_cstring16(y->type)) { + switch (op) { + case Token_CmpEq: add_package_dependency(c, "runtime", "cstring16_eq"); break; + case Token_NotEq: add_package_dependency(c, "runtime", "cstring16_ne"); break; + case Token_Lt: add_package_dependency(c, "runtime", "cstring16_lt"); break; + case Token_Gt: add_package_dependency(c, "runtime", "cstring16_gt"); break; + case Token_LtEq: add_package_dependency(c, "runtime", "cstring16_le"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "cstring16_ge"); break; + } + } else if (is_type_string16(x->type) || is_type_string16(y->type)) { + switch (op) { + case Token_CmpEq: add_package_dependency(c, "runtime", "string16_eq"); break; + case Token_NotEq: add_package_dependency(c, "runtime", "string16_ne"); break; + case Token_Lt: add_package_dependency(c, "runtime", "string16_lt"); break; + case Token_Gt: add_package_dependency(c, "runtime", "string16_gt"); break; + case Token_LtEq: add_package_dependency(c, "runtime", "string16_le"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "string16_ge"); break; } } else if (is_type_string(x->type) || is_type_string(y->type)) { switch (op) { @@ -3019,7 +3312,7 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper case Token_Lt: add_package_dependency(c, "runtime", "string_lt"); break; case Token_Gt: add_package_dependency(c, "runtime", "string_gt"); break; case Token_LtEq: add_package_dependency(c, "runtime", "string_le"); break; - case Token_GtEq: add_package_dependency(c, "runtime", "string_gt"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "string_ge"); break; } } else if (is_type_complex(x->type) || is_type_complex(y->type)) { switch (op) { @@ -3063,127 +3356,123 @@ gb_internal void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *nod GB_ASSERT(node->kind == Ast_BinaryExpr); ast_node(be, BinaryExpr, node); - ExactValue x_val = {}; - if (x->mode == Addressing_Constant) { - x_val = exact_value_to_integer(x->value); - } - - bool x_is_untyped = is_type_untyped(x->type); - if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) { - gbString err_str = expr_to_string(x->expr); - error(node, "Shifted operand '%s' must be an integer", err_str); - gb_string_free(err_str); - x->mode = Addressing_Invalid; - return; - } - - if (is_type_unsigned(y->type)) { - - } else if (is_type_untyped(y->type)) { + bool y_is_untyped = is_type_untyped(y->type); + if (y_is_untyped) { convert_to_typed(c, y, t_untyped_integer); if (y->mode == Addressing_Invalid) { + if (is_type_simd_vector(x->type)) { + char const *s = be->op.kind == Token_Shl ? "shl" : "shr"; + error_line("\tSuggestion: Use 'simd.%s' or 'simd.%s_masked'\n", s, s); + } x->mode = Addressing_Invalid; return; } - } else { - gbString err_str = expr_to_string(y->expr); - error(node, "Shift amount '%s' must be an unsigned integer", err_str); - gb_string_free(err_str); + } else if (!is_type_unsigned(y->type)) { + ERROR_BLOCK(); + + gbString y_str = expr_to_string(y->expr); + error(y->expr, "Shift amount '%s' must be an unsigned integer", y_str); + gb_string_free(y_str); + if (is_type_simd_vector(x->type)) { + char const *s = be->op.kind == Token_Shl ? "shl" : "shr"; + error_line("\tSuggestion: Use 'simd.%s' or 'simd.%s_masked'\n", s, s); + } + x->mode = Addressing_Invalid; return; } + bool x_is_untyped = is_type_untyped(x->type); + if (!(x_is_untyped || is_type_integer(x->type))) { + gbString x_str = expr_to_string(x->expr); + error(x->expr, "Shifted operand '%s' must be an integer", x_str); + gb_string_free(x_str); + x->mode = Addressing_Invalid; + return; + } + + if (y->mode == Addressing_Constant) { + if (big_int_is_neg(&y->value.value_integer)) { + gbString y_str = expr_to_string(y->expr); + error(y->expr, "Shift amount '%s' cannot be negative", y_str); + gb_string_free(y_str); + x->mode = Addressing_Invalid; + return; + } + + BigInt max_shift = {}; + big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT); + + if (big_int_cmp(&y->value.value_integer, &max_shift) > 0) { + gbString y_str = expr_to_string(y->expr); + error(y->expr, "Shift amount '%s' must be <= %u", y_str, MAX_BIG_INT_SHIFT); + gb_string_free(y_str); + x->mode = Addressing_Invalid; + return; + } + + if (x->mode == Addressing_Constant) { + if (x_is_untyped) { + convert_to_typed(c, x, t_untyped_integer); + if (x->mode == Addressing_Invalid) { + return; + } + + x->expr = node; + x->value = exact_value_shift(be->op.kind, exact_value_to_integer(x->value), exact_value_to_integer(y->value)); + + check_is_expressible(c, x, x->type); - if (x->mode == Addressing_Constant) { - if (y->mode == Addressing_Constant) { - ExactValue y_val = exact_value_to_integer(y->value); - if (y_val.kind != ExactValue_Integer) { - gbString err_str = expr_to_string(y->expr); - error(node, "Shift amount '%s' must be an unsigned integer", err_str); - gb_string_free(err_str); - x->mode = Addressing_Invalid; return; } - BigInt max_shift = {}; - big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT); - - if (big_int_cmp(&y_val.value_integer, &max_shift) > 0) { - gbString err_str = expr_to_string(y->expr); - error(node, "Shift amount too large: '%s'", err_str); - gb_string_free(err_str); - x->mode = Addressing_Invalid; - return; - } - - if (!is_type_integer(x->type)) { - // NOTE(bill): It could be an untyped float but still representable - // as an integer - x->type = t_untyped_integer; - } - x->expr = node; - x->value = exact_value_shift(be->op.kind, x_val, y_val); + x->value = exact_value_shift(be->op.kind, x->value, y->value); + check_is_expressible(c, x, x->type); - if (is_type_typed(x->type)) { - check_is_expressible(c, x, x->type); - } return; } - TokenPos pos = ast_token(x->expr).pos; - if (x_is_untyped) { - if (x->expr != nullptr) { - x->expr->tav.is_lhs = true; - } - x->mode = Addressing_Value; - if (type_hint) { - if (is_type_integer(type_hint)) { - convert_to_typed(c, x, type_hint); - } else { - gbString x_str = expr_to_string(x->expr); - gbString to_type = type_to_string(type_hint); - error(node, "Conversion of shifted operand '%s' to '%s' is not allowed", x_str, to_type); - gb_string_free(x_str); - gb_string_free(to_type); - x->mode = Addressing_Invalid; - } - } else if (!is_type_integer(x->type)) { - gbString x_str = expr_to_string(x->expr); - error(node, "Non-integer shifted operand '%s' is not allowed", x_str); - gb_string_free(x_str); - x->mode = Addressing_Invalid; - } - // x->value = x_val; - return; + if (y_is_untyped) { + convert_to_typed(c, y, t_uint); } - } - if (y->mode == Addressing_Constant && big_int_is_neg(&y->value.value_integer)) { - gbString err_str = expr_to_string(y->expr); - error(node, "Shift amount cannot be negative: '%s'", err_str); - gb_string_free(err_str); - } - - if (!is_type_integer(x->type)) { - gbString err_str = expr_to_string(x->expr); - error(node, "Shift operand '%s' must be an integer", err_str); - gb_string_free(err_str); - x->mode = Addressing_Invalid; return; } - if (is_type_untyped(y->type)) { - convert_to_typed(c, y, t_uint); - } + if (x->mode == Addressing_Constant) { + if (x_is_untyped) { + if (type_hint) { + if (is_type_integer(type_hint)) { + convert_to_typed(c, x, type_hint); + } else if (is_type_any(type_hint)) { + convert_to_typed(c, x, default_type(t_untyped_integer)); + } else { + gbString x_str = expr_to_string(x->expr); + gbString type_str = type_to_string(type_hint); + error(x->expr, "Shifted operand '%s' cannot convert to non-integer type '%s'", x_str, type_str); + gb_string_free(x_str); + gb_string_free(type_str); + x->mode = Addressing_Invalid; + return; + } + } else { + check_is_expressible(c, x, default_type(t_untyped_integer)); + } + if (x->mode == Addressing_Invalid) { + return; + } + } - x->mode = Addressing_Value; + x->mode = Addressing_Value; + } } - - gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { + if (are_types_identical(operand->type, y)) { + return true; + } if (check_is_assignable_to(c, operand, y)) { return true; } @@ -3219,10 +3508,23 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type if (is_constant && is_type_untyped(src) && is_type_string(src)) { if (is_type_u8_array(dst)) { + GB_ASSERT(operand->value.kind == ExactValue_String); String s = operand->value.value_string; return s.len == dst->Array.count; } + if (is_type_u16_array(dst)) { + if (operand->value.kind == ExactValue_String16) { + String16 s = operand->value.value_string16; + return s.len == dst->Array.count; + } + GB_ASSERT(operand->value.kind == ExactValue_String); + String16 s = string_to_string16(heap_allocator(), operand->value.value_string); + defer (gb_free(heap_allocator(), s.text)); + + return s.len == dst->Array.count; + } if (is_type_rune_array(dst)) { + GB_ASSERT(operand->value.kind == ExactValue_String); String s = operand->value.value_string; return gb_utf8_strnlen(s.text, s.len) == dst->Array.count; } @@ -3230,8 +3532,13 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type if (dst->kind == Type_Array && src->kind == Type_Array) { - if (are_types_identical(dst->Array.elem, src->Array.elem)) { - return dst->Array.count == src->Array.count; + if (dst->Array.count == src->Array.count) { + if (are_types_identical(dst->Array.elem, src->Array.elem)) { + return true; + } + Operand op = *operand; + op.type = src->Array.elem; + return check_is_castable_to(c, &op, dst->Array.elem); } } @@ -3337,6 +3644,11 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type return true; } + // []u16 <-> string16 (not cstring16) + if (is_type_u16_slice(src) && (is_type_string16(dst) && !is_type_cstring16(dst))) { + return true; + } + // cstring -> string if (are_types_identical(src, t_cstring) && are_types_identical(dst, t_string)) { if (operand->mode != Addressing_Constant) { @@ -3344,6 +3656,14 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type } return true; } + // cstring16 -> string16 + if (are_types_identical(src, t_cstring16) && are_types_identical(dst, t_string16)) { + if (operand->mode != Addressing_Constant) { + add_package_dependency(c, "runtime", "cstring16_to_string16"); + } + return true; + } + // cstring -> ^u8 if (are_types_identical(src, t_cstring) && is_type_u8_ptr(dst)) { return !is_constant; @@ -3369,6 +3689,34 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type if (is_type_rawptr(src) && are_types_identical(dst, t_cstring)) { return !is_constant; } + + // cstring -> ^u16 + if (are_types_identical(src, t_cstring16) && is_type_u16_ptr(dst)) { + return !is_constant; + } + // cstring -> [^]u16 + if (are_types_identical(src, t_cstring16) && is_type_u16_multi_ptr(dst)) { + return !is_constant; + } + // cstring16 -> rawptr + if (are_types_identical(src, t_cstring16) && is_type_rawptr(dst)) { + return !is_constant; + } + + + // ^u16 -> cstring16 + if (is_type_u16_ptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // [^]u16 -> cstring + if (is_type_u16_multi_ptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // rawptr -> cstring16 + if (is_type_rawptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // proc <-> proc if (is_type_proc(src) && is_type_proc(dst)) { if (is_type_polymorphic(dst)) { @@ -3424,16 +3772,17 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) { bool is_const_expr = x->mode == Addressing_Constant; + Type *bt = base_type(type); if (is_const_expr && is_type_constant_type(bt)) { + Type *elem = core_array_type(bt); + if (core_type(bt)->kind == Type_Basic) { - if (check_representable_as_constant(c, x->value, bt, &x->value)) { - return true; - } else if (check_is_castable_to(c, x, type)) { - if (is_type_pointer(type)) { - return true; - } - } + return check_representable_as_constant(c, x->value, type, &x->value) || + (is_type_pointer(type) && check_is_castable_to(c, x, type)); + } else if (!are_types_identical(elem, bt) && elem->kind == Type_Basic && x->type->kind == Type_Basic) { + return check_representable_as_constant(c, x->value, elem, &x->value) || + (is_type_pointer(elem) && check_is_castable_to(c, x, elem)); } else if (check_is_castable_to(c, x, type)) { x->value = {}; x->mode = Addressing_Value; @@ -3445,6 +3794,9 @@ gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) } else if (is_type_slice(type) && is_type_string(x->type)) { x->mode = Addressing_Value; } else if (is_type_union(type)) { + if (is_type_union_constantable(type)) { + return true; + } x->mode = Addressing_Value; } if (x->mode == Addressing_Value) { @@ -3458,7 +3810,14 @@ gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forbid_identical = false) { if (!is_operand_value(*x)) { + ERROR_BLOCK(); error(x->expr, "Only values can be casted"); + if (is_type_typeid(type)) { + gbString expr_str = expr_to_string(x->expr); + defer (gb_string_free(expr_str)); + + error_line("\tSuggestion: 'typeid_of(%s)'", expr_str); + } x->mode = Addressing_Invalid; return; } @@ -3549,6 +3908,24 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forb } } + if (is_const_expr) { + Type *src = core_type(x->type); + Type *dst = core_type(type); + + if (is_type_string(src) && is_type_string(dst)) { + bool src_utf16 = is_type_string16(src) || is_type_cstring16(src); + bool dst_utf16 = is_type_string16(dst) || is_type_cstring16(dst); + + if (!src_utf16 && dst_utf16) { + x->value = exact_value_string16(string_to_string16(permanent_allocator(), x->value.value_string)); + } + + if (src_utf16 && !dst_utf16) { + x->value = exact_value_string(string16_to_string(permanent_allocator(), x->value.value_string16)); + } + } + } + x->type = type; } @@ -3617,7 +3994,7 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type if (types_have_same_internal_endian(src_t, dst_t)) { ExactValue src_v = exact_value_to_integer(o->value); GB_ASSERT(src_v.kind == ExactValue_Integer || src_v.kind == ExactValue_Invalid); - BigInt v = src_v.value_integer; + BigInt v = big_int_make(&src_v.value_integer); BigInt smax = {}; BigInt umax = {}; @@ -3864,6 +4241,59 @@ matrix_error: } +gb_internal void check_binary_expr_dependency(CheckerContext *c, Token op, Type *bt, bool REQUIRE) { + if (op.kind == Token_Mod || op.kind == Token_ModEq || + op.kind == Token_ModMod || op.kind == Token_ModModEq) { + if (bt->kind == Type_Basic) switch (bt->Basic.kind) { + case Basic_u128: add_package_dependency(c, "runtime", "umodti3", REQUIRE); break; + case Basic_i128: add_package_dependency(c, "runtime", "modti3", REQUIRE); break; + } + } else if (op.kind == Token_Quo || op.kind == Token_QuoEq) { + if (bt->kind == Type_Basic) switch (bt->Basic.kind) { + case Basic_complex32: add_package_dependency(c, "runtime", "quo_complex32"); break; + case Basic_complex64: add_package_dependency(c, "runtime", "quo_complex64"); break; + case Basic_complex128: add_package_dependency(c, "runtime", "quo_complex128"); break; + case Basic_quaternion64: add_package_dependency(c, "runtime", "quo_quaternion64"); break; + case Basic_quaternion128: add_package_dependency(c, "runtime", "quo_quaternion128"); break; + case Basic_quaternion256: add_package_dependency(c, "runtime", "quo_quaternion256"); break; + + case Basic_u128: add_package_dependency(c, "runtime", "udivti3", REQUIRE); break; + case Basic_i128: add_package_dependency(c, "runtime", "divti3", REQUIRE); break; + } + } else if (op.kind == Token_Mul || op.kind == Token_MulEq) { + if (bt->kind == Type_Basic) switch (bt->Basic.kind) { + case Basic_quaternion64: add_package_dependency(c, "runtime", "mul_quaternion64"); break; + case Basic_quaternion128: add_package_dependency(c, "runtime", "mul_quaternion128"); break; + case Basic_quaternion256: add_package_dependency(c, "runtime", "mul_quaternion256"); break; + + + case Basic_u128: + case Basic_i128: + if (is_arch_wasm()) { + add_package_dependency(c, "runtime", "__multi3", REQUIRE); + } + break; + } + } else if (op.kind == Token_Shl || op.kind == Token_ShlEq) { + if (bt->kind == Type_Basic) switch (bt->Basic.kind) { + case Basic_u128: + case Basic_i128: + if (is_arch_wasm()) { + add_package_dependency(c, "runtime", "__ashlti3", REQUIRE); + } + break; + } + } else if (op.kind == Token_Shr || op.kind == Token_ShrEq) { + if (bt->kind == Type_Basic) switch (bt->Basic.kind) { + case Basic_u128: + case Basic_i128: + if (is_arch_wasm()) { + add_package_dependency(c, "runtime", "__lshrti3", REQUIRE); + } + break; + } + } +} gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint, bool use_lhs_as_type_hint=false) { GB_ASSERT(node->kind == Ast_BinaryExpr); @@ -3968,15 +4398,19 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ i64 upper = yt->BitSet.upper; if (lower <= key && key <= upper) { - i64 bit = 1ll<mode = Addressing_Constant; x->type = t_untyped_bool; if (op.kind == Token_in) { - x->value = exact_value_bool((bit & bits) != 0); + x->value = exact_value_bool(!big_int_is_zero(&mask)); } else { - x->value = exact_value_bool((bit & bits) == 0); + x->value = exact_value_bool(big_int_is_zero(&mask)); } x->expr = node; return; @@ -4005,7 +4439,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ default: if (is_ise_expr(be->left)) { // Evalute the right before the left for an '.X' expression - check_expr_or_type(c, y, be->right, type_hint); + check_expr_or_type(c, y, be->right, token_is_comparison(op.kind) ? nullptr : type_hint); if (can_use_other_type_as_type_hint(use_lhs_as_type_hint, y->type)) { // RHS in this case check_expr_or_type(c, x, be->left, y->type); @@ -4017,7 +4451,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ if (can_use_other_type_as_type_hint(use_lhs_as_type_hint, x->type)) { check_expr_with_type_hint(c, y, be->right, x->type); } else { - check_expr_with_type_hint(c, y, be->right, type_hint); + check_expr_with_type_hint(c, y, be->right, token_is_comparison(op.kind) ? nullptr : type_hint); } } break; @@ -4061,58 +4495,10 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ } bool REQUIRE = true; - Type *bt = base_type(x->type); - if (op.kind == Token_Mod || op.kind == Token_ModEq || - op.kind == Token_ModMod || op.kind == Token_ModModEq) { - if (bt->kind == Type_Basic) switch (bt->Basic.kind) { - case Basic_u128: add_package_dependency(c, "runtime", "umodti3", REQUIRE); break; - case Basic_i128: add_package_dependency(c, "runtime", "modti3", REQUIRE); break; - } - } else if (op.kind == Token_Quo || op.kind == Token_QuoEq) { - if (bt->kind == Type_Basic) switch (bt->Basic.kind) { - case Basic_complex32: add_package_dependency(c, "runtime", "quo_complex32"); break; - case Basic_complex64: add_package_dependency(c, "runtime", "quo_complex64"); break; - case Basic_complex128: add_package_dependency(c, "runtime", "quo_complex128"); break; - case Basic_quaternion64: add_package_dependency(c, "runtime", "quo_quaternion64"); break; - case Basic_quaternion128: add_package_dependency(c, "runtime", "quo_quaternion128"); break; - case Basic_quaternion256: add_package_dependency(c, "runtime", "quo_quaternion256"); break; - - case Basic_u128: add_package_dependency(c, "runtime", "udivti3", REQUIRE); break; - case Basic_i128: add_package_dependency(c, "runtime", "divti3", REQUIRE); break; - } - } else if (op.kind == Token_Mul || op.kind == Token_MulEq) { - if (bt->kind == Type_Basic) switch (bt->Basic.kind) { - case Basic_quaternion64: add_package_dependency(c, "runtime", "mul_quaternion64"); break; - case Basic_quaternion128: add_package_dependency(c, "runtime", "mul_quaternion128"); break; - case Basic_quaternion256: add_package_dependency(c, "runtime", "mul_quaternion256"); break; - - - case Basic_u128: - case Basic_i128: - if (is_arch_wasm()) { - add_package_dependency(c, "runtime", "__multi3", REQUIRE); - } - break; - } - } else if (op.kind == Token_Shl || op.kind == Token_ShlEq) { - if (bt->kind == Type_Basic) switch (bt->Basic.kind) { - case Basic_u128: - case Basic_i128: - if (is_arch_wasm()) { - add_package_dependency(c, "runtime", "__ashlti3", REQUIRE); - } - break; - } - } else if (op.kind == Token_Shr || op.kind == Token_ShrEq) { - if (bt->kind == Type_Basic) switch (bt->Basic.kind) { - case Basic_u128: - case Basic_i128: - if (is_arch_wasm()) { - add_package_dependency(c, "runtime", "__lshrti3", REQUIRE); - } - break; - } - } + Type *btx = base_type(x->type); + Type *bty = base_type(y->type); + check_binary_expr_dependency(c, op, btx, REQUIRE); + check_binary_expr_dependency(c, op, bty, REQUIRE); if (token_is_shift(op.kind)) { check_shift(c, x, y, node, type_hint); @@ -4227,7 +4613,25 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ } if (fail) { - error(y->expr, "Division by zero not allowed"); + if (is_type_integer(x->type) || (x->mode == Addressing_Constant && x->value.kind == ExactValue_Integer)) { + if (check_for_integer_division_by_zero(c, node) != IntegerDivisionByZero_Trap) { + // Okay + break; + } + } + + switch (op.kind) { + case Token_Mod: + case Token_ModMod: + case Token_ModEq: + case Token_ModModEq: + error(y->expr, "Division by zero through '%.*s' not allowed", LIT(token_strings[op.kind])); + break; + case Token_Quo: + case Token_QuoEq: + error(y->expr, "Division by zero not allowed"); + break; + } x->mode = Addressing_Invalid; return; } @@ -4267,7 +4671,62 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ } } - x->value = exact_binary_operator_value(op.kind, a, b); + match_exact_values(&a, &b); + + + IntegerDivisionByZeroKind zero_behaviour = check_for_integer_division_by_zero(c, node); + if (zero_behaviour != IntegerDivisionByZero_Trap && + b.kind == ExactValue_Integer && big_int_is_zero(&b.value_integer) && + (op.kind == Token_QuoEq || op.kind == Token_Mod || op.kind == Token_ModMod)) { + if (op.kind == Token_QuoEq) { + switch (zero_behaviour) { + case IntegerDivisionByZero_Zero: + // x/0 == 0 + x->value = b; + break; + case IntegerDivisionByZero_Self: + // x/0 == x + x->value = a; + break; + case IntegerDivisionByZero_AllBits: + // x/0 == 0b111...111 + if (is_type_untyped(x->type)) { + x->value = exact_value_i64(-1); + } else { + x->value = exact_unary_operator_value(Token_Xor, b, cast(i32)(8*type_size_of(x->type)), is_type_unsigned(x->type)); + } + break; + } + } else { + /* + NOTE(bill): @integer division by zero rules + + truncated: r = a - b*trunc(a/b) + floored: r = a - b*floor(a/b) + + If and only if (⟺) a/0 == 0, then (a%0 == a) or (a%%0 == a) + If and only if (⟺) a/0 == a, then (a%0 == 0) or (a%%0 == 0) + If and only if (⟺) a/0 == 0b111..., then (a%0 == a) or (a%%0 == a) + */ + + switch (zero_behaviour) { + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + // x%0 == x + x->value = a; + break; + case IntegerDivisionByZero_Self: + // x%0 == 0 + x->value = b; + break; + } + } + } else if (is_type_array_like(x->type)) { + x->mode = Addressing_Value; + return; + } else { + x->value = exact_binary_operator_value(op.kind, a, b); + } if (is_type_typed(x->type)) { if (node != nullptr) { @@ -4485,7 +4944,6 @@ gb_internal ExactValue convert_exact_value_for_type(ExactValue v, Type *type) { } gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) { - // GB_ASSERT_NOT_NULL(target_type); if (target_type == nullptr || operand->mode == Addressing_Invalid || operand->mode == Addressing_Type || is_type_typed(operand->type) || @@ -4519,44 +4977,52 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar switch (t->kind) { case Type_Basic: if (operand->mode == Addressing_Constant) { - check_is_expressible(c, operand, t); + check_is_expressible(c, operand, target_type); if (operand->mode == Addressing_Invalid) { return; } update_untyped_expr_value(c, operand->expr, operand->value); - } else { - switch (operand->type->Basic.kind) { - case Basic_UntypedBool: - if (!is_type_boolean(target_type)) { - operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); - return; - } - break; - case Basic_UntypedInteger: - case Basic_UntypedFloat: - case Basic_UntypedComplex: - case Basic_UntypedQuaternion: - case Basic_UntypedRune: - if (!is_type_numeric(target_type)) { - operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); - return; - } - break; + } - case Basic_UntypedNil: - if (is_type_any(target_type)) { - // target_type = t_untyped_nil; - } else if (is_type_cstring(target_type)) { - // target_type = t_untyped_nil; - } else if (!type_has_nil(target_type)) { - operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); - return; - } - break; + switch (operand->type->Basic.kind) { + case Basic_UntypedBool: + if (!is_type_boolean(target_type)) { + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; } + break; + case Basic_UntypedInteger: + case Basic_UntypedFloat: + case Basic_UntypedComplex: + case Basic_UntypedQuaternion: + case Basic_UntypedRune: + if (!is_type_numeric(target_type)) { + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; + } + break; + + case Basic_UntypedNil: + if (is_type_any(target_type)) { + // target_type = t_untyped_nil; + } else if (is_type_cstring(target_type)) { + // target_type = t_untyped_nil; + } else if (is_type_cstring16(target_type)) { + // target_type = t_untyped_nil; + } else if (!type_has_nil(target_type)) { + operand->mode = Addressing_Invalid; + convert_untyped_error(c, operand, target_type); + return; + } + break; + } + + switch (operand->type->Basic.kind) { + case Basic_UntypedFloat: + check_update_float_precision(&operand->value, t); + break; } break; @@ -4576,6 +5042,19 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar if (rune_count == t->Array.count) { break; } + } else if (is_type_u16_array(t)) { + String16 s = string_to_string16(heap_allocator(), operand->value.value_string); + defer (gb_free(heap_allocator(), s.text)); + if (s.len == t->Array.count) { + break; + } + } + } else if (operand->value.kind == ExactValue_String16) { + String16 s = operand->value.value_string16; + if (is_type_u16_array(t)) { + if (s.len == t->Array.count) { + break; + } } } operand->mode = Addressing_Invalid; @@ -4647,7 +5126,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar TEMPORARY_ALLOCATOR_GUARD(); isize count = t->Union.variants.count; - ValidIndexAndScore *valids = gb_alloc_array(temporary_allocator(), ValidIndexAndScore, count); + ValidIndexAndScore *valids = temporary_alloc_array(count); isize valid_count = 0; isize first_success_index = -1; for_array(i, t->Union.variants) { @@ -4688,7 +5167,10 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar break; } operand->type = new_type; - operand->mode = Addressing_Value; + if (operand->mode != Addressing_Constant || + !elem_type_can_be_constant(operand->type)) { + operand->mode = Addressing_Value; + } break; } else if (valid_count > 1) { ERROR_BLOCK(); @@ -4881,7 +5363,8 @@ gb_internal bool check_index_value(CheckerContext *c, Type *main_type, bool open TEMPORARY_ALLOCATOR_GUARD(); String idx_str = big_int_to_string(temporary_allocator(), &i); gbString expr_str = expr_to_string(operand.expr, temporary_allocator()); - error(operand.expr, "Index '%s' is out of bounds range 0..<%lld, got %.*s", expr_str, max_count, LIT(idx_str)); + char range_type = open_range ? '=' : '<'; + error(operand.expr, "Index '%s' is out of bounds range 0..%c%lld, got %.*s", expr_str, range_type, max_count, LIT(idx_str)); return false; } @@ -4906,6 +5389,12 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v if (success_) *success_ = true; if (finish_) *finish_ = true; return exact_value_u64(val); + } else if (value.kind == ExactValue_String16) { + GB_ASSERT(0 <= index && index < value.value_string.len); + u16 val = value.value_string16[index]; + if (success_) *success_ = true; + if (finish_) *finish_ = true; + return exact_value_u64(val); } if (value.kind != ExactValue_Compound) { if (success_) *success_ = true; @@ -4924,16 +5413,19 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v } if (cl->elems[0]->kind == Ast_FieldValue) { - if (is_type_struct(node->tav.type)) { + if (is_type_raw_union(node->tav.type)) { + if (success_) *success_ = false; + if (finish_) *finish_ = true; + return empty_exact_value; + } else if (is_type_struct(node->tav.type)) { bool found = false; for (Ast *elem : cl->elems) { if (elem->kind != Ast_FieldValue) { continue; } ast_node(fv, FieldValue, elem); - String name = fv->field->Ident.token.string; + auto name = fv->field->Ident.interned; Selection sub_sel = lookup_field(node->tav.type, name, false); - defer (array_free(&sub_sel.index)); if (sub_sel.index.count > 0 && sub_sel.index[0] == index) { value = fv->value->tav.value; @@ -4986,6 +5478,11 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v } } else { TypeAndValue index_tav = fv->field->tav; + if (index_tav.mode != Addressing_Constant) { + if (success_) *success_ = false; + if (finish_) *finish_ = true; + return empty_exact_value; + } GB_ASSERT(index_tav.mode == Addressing_Constant); ExactValue index_value = index_tav.value; if (is_type_enumerated_array(node->tav.type)) { @@ -5193,8 +5690,12 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast * return e; } } else */if (node->kind == Ast_Ident) { + Entity *e = node->Ident.entity.load(); + if (e != nullptr) { + return e; + } String name = node->Ident.token.string; - return scope_lookup(c->scope, name); + return scope_lookup(c->scope, node->Ident.interned, node->Ident.hash); } else if (!ident_only) if (node->kind == Ast_SelectorExpr) { ast_node(se, SelectorExpr, node); if (se->token.kind == Token_ArrowRight) { @@ -5216,7 +5717,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast * if (op_expr->kind == Ast_Ident) { String op_name = op_expr->Ident.token.string; - Entity *e = scope_lookup(c->scope, op_name); + Entity *e = scope_lookup(c->scope, op_expr->Ident.interned, op_expr->Ident.hash); if (e == nullptr) { return nullptr; } @@ -5229,7 +5730,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast * // If you can clean this up, please do but be really careful String import_name = op_name; Scope *import_scope = e->ImportName.scope; - String entity_name = selector->Ident.token.string; + auto entity_name = selector->Ident.interned; check_op_expr = false; entity = scope_lookup_current(import_scope, entity_name); @@ -5255,7 +5756,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast * } if (entity == nullptr && selector->kind == Ast_Ident) { - String field_name = selector->Ident.token.string; + auto field_name = selector->Ident.interned; if (is_type_dynamic_array(type_deref(operand.type))) { init_mem_allocator(c->checker); } @@ -5313,7 +5814,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod if (op_expr->kind == Ast_Ident) { String op_name = op_expr->Ident.token.string; - Entity *e = scope_lookup(c->scope, op_name); + Entity *e = scope_lookup(c->scope, op_expr->Ident.interned, op_expr->Ident.hash); add_entity_use(c, op_expr, e); expr_entity = e; @@ -5331,6 +5832,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod String import_name = op_name; Scope *import_scope = e->ImportName.scope; String entity_name = selector->Ident.token.string; + InternedString entity_name_interned = selector->Ident.interned; if (import_scope == nullptr) { ERROR_BLOCK(); @@ -5341,7 +5843,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod } check_op_expr = false; - entity = scope_lookup_current(import_scope, entity_name); + entity = scope_lookup_current(import_scope, entity_name_interned); bool allow_builtin = false; if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { ERROR_BLOCK(); @@ -5353,16 +5855,6 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod return nullptr; } - check_entity_decl(c, entity, nullptr, nullptr); - if (entity->kind == Entity_ProcGroup) { - operand->mode = Addressing_ProcGroup; - operand->proc_group = entity; - - add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); - return entity; - } - GB_ASSERT_MSG(entity->type != nullptr, "%.*s (%.*s)", LIT(entity->token.string), LIT(entity_strings[entity->kind])); - if (!is_entity_exported(entity, allow_builtin)) { gbString sel_str = expr_to_string(selector); error(node, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name)); @@ -5373,36 +5865,15 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod // return nullptr; } + check_entity_decl(c, entity, nullptr, nullptr); if (entity->kind == Entity_ProcGroup) { - Array procs = entity->ProcGroup.entities; - bool skip = false; - for (Entity *p : procs) { - Type *t = base_type(p->type); - if (t == t_invalid) { - continue; - } + operand->mode = Addressing_ProcGroup; + operand->proc_group = entity; - Operand x = {}; - x.mode = Addressing_Value; - x.type = t; - if (type_hint != nullptr) { - if (check_is_assignable_to(c, &x, type_hint)) { - entity = p; - skip = true; - break; - } - } - } - - if (!skip) { - GB_ASSERT(entity != nullptr); - operand->mode = Addressing_ProcGroup; - operand->type = t_invalid; - operand->expr = node; - operand->proc_group = entity; - return entity; - } + add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); + return entity; } + GB_ASSERT_MSG(entity->type != nullptr, "%.*s (%.*s)", LIT(entity->token.string), LIT(entity_strings[entity->kind])); } } @@ -5420,7 +5891,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod } if (entity == nullptr && selector->kind == Ast_Ident) { - String field_name = selector->Ident.token.string; + auto field_name = selector->Ident.interned; Type *t = type_deref(operand->type); if (t == nullptr) { error(operand->expr, "Cannot use a selector expression on 0-value expression"); @@ -5441,8 +5912,18 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod } } + if (operand->type && is_type_simd_vector(type_deref(operand->type))) { + String field_name = selector->Ident.token.string; + if (field_name.len == 1) { + error(op_expr, "Extracting an element from a #simd array using .%.*s syntax is disallowed, prefer `simd.extract`", LIT(field_name)); + } else { + error(op_expr, "Extracting elements from a #simd array using .%.*s syntax is disallowed, prefer `swizzle`", LIT(field_name)); + } + return nullptr; + } + if (entity == nullptr && selector->kind == Ast_Ident && operand->type != nullptr && - (is_type_array(type_deref(operand->type)) || is_type_simd_vector(type_deref(operand->type)))) { + (is_type_array(type_deref(operand->type)))) { String field_name = selector->Ident.token.string; if (1 < field_name.len && field_name.len <= 4) { u8 swizzles_xyzw[4] = {'x', 'y', 'z', 'w'}; @@ -5497,7 +5978,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod Type *original_type = operand->type; Type *array_type = base_type(type_deref(original_type)); - GB_ASSERT(array_type->kind == Type_Array || array_type->kind == Type_SimdVector); + GB_ASSERT(array_type->kind == Type_Array); i64 array_count = get_array_type_count(array_type); @@ -5538,10 +6019,6 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod break; } - if (array_type->kind == Type_SimdVector) { - operand->mode = Addressing_Value; - } - Entity *swizzle_entity = alloc_entity_variable(nullptr, make_token_ident(field_name), operand->type, EntityState_Resolved); add_type_and_value(c, operand->expr, operand->mode, operand->type, operand->value); return swizzle_entity; @@ -5657,14 +6134,9 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod operand->type = entity->type; operand->expr = node; - if (entity->flags & EntityFlag_BitFieldField) { - add_package_dependency(c, "runtime", "__write_bits"); - add_package_dependency(c, "runtime", "__read_bits"); - } - switch (entity->kind) { case Entity_Constant: - operand->value = entity->Constant.value; + operand->value = entity->Constant.value; operand->mode = Addressing_Constant; if (operand->value.kind == ExactValue_Procedure) { Entity *proc = strip_entity_wrapping(operand->value.value_procedure); @@ -5753,15 +6225,14 @@ gb_internal bool is_type_valid_atomic_type(Type *elem) { gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = false, Scope **out_scope = nullptr) { switch (node->kind) { case_ast_node(i, Ident, node); - String name = i->token.string; if (nested) { - Entity *e = scope_lookup_current(s, name); + Entity *e = scope_lookup_current(s, i->interned, i->hash); if (e != nullptr) { if (out_scope) *out_scope = e->scope; return true; } } else { - Entity *e = scope_lookup(s, name); + Entity *e = scope_lookup(s, i->interned, i->hash); if (e != nullptr) { if (out_scope) *out_scope = e->scope; return true; @@ -5780,22 +6251,6 @@ gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = fals return false; } -gb_internal bool check_no_copy_assignment(Operand const &o, String const &context) { - if (o.type && is_type_no_copy(o.type)) { - Ast *expr = unparen_expr(o.expr); - if (expr && o.mode != Addressing_Constant && o.mode != Addressing_Type) { - if (expr->kind == Ast_CallExpr) { - // Okay - } else { - error(o.expr, "Invalid use of #no_copy value in %.*s", LIT(context)); - return true; - } - } - } - return false; -} - - gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array const &lhs, Array *operands, Slice const &rhs) { bool optional_ok = false; isize tuple_index = 0; @@ -5866,7 +6321,6 @@ gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array for (Entity *e : tuple->variables) { o.type = e->type; array_add(operands, o); - check_no_copy_assignment(o, str_lit("assignment")); } tuple_index += tuple->variables.count; @@ -5881,12 +6335,12 @@ typedef u32 UnpackFlags; enum UnpackFlag : u32 { UnpackFlag_None = 0, UnpackFlag_AllowOk = 1<<0, - UnpackFlag_IsVariadic = 1<<1, - UnpackFlag_AllowUndef = 1<<2, + UnpackFlag_AllowUndef = 1<<1, }; -gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array *operands, Slice const &rhs_arguments, UnpackFlags flags) { +gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array *operands, Slice const &rhs_arguments, UnpackFlags flags, + isize variadic_index = -1) { auto const &add_dependencies_from_unpacking = [](CheckerContext *c, Entity **lhs, isize lhs_count, isize tuple_index, isize tuple_count) -> isize { if (lhs == nullptr || c->decl == nullptr) { return tuple_count; @@ -5902,7 +6356,7 @@ gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize } rw_mutex_shared_lock(&decl->deps_mutex); rw_mutex_lock(&c->decl->deps_mutex); - for (Entity *dep : decl->deps) { + FOR_PTR_SET(dep, decl->deps) { ptr_set_add(&c->decl->deps, dep); } rw_mutex_unlock(&c->decl->deps_mutex); @@ -5911,11 +6365,14 @@ gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize return tuple_count; }; - bool allow_ok = (flags & UnpackFlag_AllowOk) != 0; - bool is_variadic = (flags & UnpackFlag_IsVariadic) != 0; bool allow_undef = (flags & UnpackFlag_AllowUndef) != 0; + bool is_variadic = variadic_index > -1; + if (!is_variadic) { + variadic_index = lhs_count; + } + bool optional_ok = false; isize tuple_index = 0; for (Ast *rhs : rhs_arguments) { @@ -5931,26 +6388,18 @@ gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize Type *type_hint = nullptr; - - if (lhs != nullptr && tuple_index < lhs_count) { - // NOTE(bill): override DeclInfo for dependency - Entity *e = lhs[tuple_index]; - if (e != nullptr) { - type_hint = e->type; - if (e->flags & EntityFlag_Ellipsis) { - GB_ASSERT(is_type_slice(e->type)); - GB_ASSERT(e->type->kind == Type_Slice); - type_hint = e->type->Slice.elem; + if (lhs != nullptr) { + if (tuple_index < variadic_index) { + // NOTE(bill): override DeclInfo for dependency + Entity *e = lhs[tuple_index]; + if (e != nullptr) { + type_hint = e->type; } - } - } else if (lhs != nullptr && tuple_index >= lhs_count && is_variadic) { - // NOTE(bill): override DeclInfo for dependency - Entity *e = lhs[lhs_count-1]; - if (e != nullptr) { - type_hint = e->type; - if (e->flags & EntityFlag_Ellipsis) { + } else if (is_variadic) { + Entity *e = lhs[variadic_index]; + if (e != nullptr) { + GB_ASSERT(e->flags & EntityFlag_Ellipsis); GB_ASSERT(is_type_slice(e->type)); - GB_ASSERT(e->type->kind == Type_Slice); type_hint = e->type->Slice.elem; } } @@ -6063,7 +6512,6 @@ gb_internal isize get_procedure_param_count_excluding_defaults(Type *pt, isize * continue; } } - break; } } @@ -6097,7 +6545,8 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A Entity *entity, Type *proc_type, Array positional_operands, Array const &named_operands, CallArgumentErrorMode show_error_mode, - CallArgumentData *data) { + CallArgumentData *data, + bool checking_proc_group) { TEMPORARY_ALLOCATOR_GUARD(); CallArgumentError err = CallArgumentError_None; @@ -6134,7 +6583,7 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } GB_ASSERT(ce->split_args); - auto visited = slice_make(temporary_allocator(), pt->param_count); + auto visited = temporary_slice_make(pt->param_count); auto ordered_operands = array_make(temporary_allocator(), pt->param_count); defer ({ for (Operand const &o : ordered_operands) { @@ -6149,11 +6598,16 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A positional_operand_count = gb_min(positional_operands.count, pt->variadic_index); } else if (positional_operand_count > pt->param_count) { err = CallArgumentError_TooManyArguments; - char const *err_fmt = "Too many arguments for '%s', expected %td arguments, got %td"; if (show_error) { gbString proc_str = expr_to_string(ce->proc); defer (gb_string_free(proc_str)); - error(call, err_fmt, proc_str, param_count_excluding_defaults, positional_operands.count); + if (param_count_excluding_defaults != pt->param_count) { + char const *err_fmt = "Too many arguments for '%s', expected %td..=%td arguments, got %td"; + error(call, err_fmt, proc_str, param_count_excluding_defaults, pt->param_count, positional_operands.count); + } else { + char const *err_fmt = "Too many arguments for '%s', expected %td arguments, got %td"; + error(call, err_fmt, proc_str, pt->param_count, positional_operands.count); + } } return err; } @@ -6258,29 +6712,48 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } - for (Operand const &o : ordered_operands) { - if (o.mode != Addressing_Invalid) { - check_no_copy_assignment(o, str_lit("procedure call expression")); - } - } - for (isize i = 0; i < pt->param_count; i++) { if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; + bool context_allocator_error = false; if (e->kind == Entity_Variable) { if (e->Variable.param_value.kind != ParameterValue_Invalid) { - ordered_operands[i].mode = Addressing_Value; - ordered_operands[i].type = e->type; - ordered_operands[i].expr = e->Variable.param_value.original_ast_expr; + if (ast_file_vet_explicit_allocators(c->file) && !checking_proc_group) { + // NOTE(lucas): check if we are trying to default to context.allocator or context.temp_allocator + if (e->Variable.param_value.original_ast_expr->kind == Ast_SelectorExpr) { + auto& expr = e->Variable.param_value.original_ast_expr->SelectorExpr.expr; + auto& selector = e->Variable.param_value.original_ast_expr->SelectorExpr.selector; + if (expr->kind == Ast_Implicit && + expr->Implicit.string == STR_LIT("context") && + selector->kind == Ast_Ident && + (selector->Ident.token.string == STR_LIT("allocator") || + selector->Ident.token.string == STR_LIT("temp_allocator"))) { + context_allocator_error = true; + } + } + } - dummy_argument_count += 1; - score += assign_score_function(1); - continue; + if (!context_allocator_error) { + ordered_operands[i].mode = Addressing_Value; + ordered_operands[i].type = e->type; + if (e->Variable.param_value.kind == ParameterValue_Nil) + ordered_operands[i].type = t_untyped_nil; + ordered_operands[i].expr = e->Variable.param_value.original_ast_expr; + + dummy_argument_count += 1; + score += assign_score_function(1); + continue; + } } } if (show_error) { - if (e->kind == Entity_TypeName) { + if (context_allocator_error) { + gbString str = type_to_string(e->type); + error(call, "Parameter '%.*s' of type '%s' must be explicitly provided in procedure call", + LIT(e->token.string), str); + gb_string_free(str); + } else if (e->kind == Entity_TypeName) { error(call, "Type parameter '%.*s' is missing in procedure call", LIT(e->token.string)); } else if (e->kind == Entity_Constant && e->Constant.value.kind != ExactValue_Invalid) { @@ -6302,7 +6775,7 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A if (!check_is_assignable_to_with_score(c, o, param_type, &s, param_is_variadic, allow_array_programming)) { bool ok = false; if (e && (e->flags & EntityFlag_AnyInt)) { - if (is_type_integer(param_type)) { + if (is_type_integer(param_type) && (is_type_integer(o->type) || is_type_enum(o->type))) { ok = check_is_castable_to(c, o, param_type); } } @@ -6332,6 +6805,21 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } } + if (e && e->kind == Entity_Constant && is_type_proc(e->type)) { + bool ok = false; + if (o->mode == Addressing_Constant) { + ok = true; + } else if (o->value.kind == ExactValue_Procedure) { + ok = true; + } + + if (!ok) { + if (show_error) { + error(o->expr, "Expected a constant procedure value for the argument '%.*s'", LIT(e->token.string)); + } + err = CallArgumentError_NoneConstantParameter; + } + } if (!err && is_type_any(param_type)) { add_type_info_type(c, o->type); @@ -6490,17 +6978,16 @@ gb_internal bool is_call_expr_field_value(AstCallExpr *ce) { return ce->args[0]->kind == Ast_FieldValue; } -gb_internal Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize *lhs_count_, bool *is_variadic) { +gb_internal Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize *lhs_count_) { Entity **lhs = nullptr; isize lhs_count = -1; - if (proc_type == nullptr) { + if (proc_type == nullptr || proc_type == t_invalid) { return nullptr; } GB_ASSERT(is_type_proc(proc_type)); TypeProc *pt = &base_type(proc_type)->Proc; - *is_variadic = pt->variadic; if (!pt->is_polymorphic || pt->is_poly_specialized) { if (pt->params != nullptr) { @@ -6556,7 +7043,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco Entity *e = entry.value; switch (e->kind) { case Entity_TypeName: { - if (print_count == 0) error_line("\n\tWith the following definitions:\n"); + // if (print_count == 0) error_line("\n\tWith the following definitions:\n"); gbString str = type_to_string(e->type); error_line("\t\t%.*s :: %s;\n", LIT(e->token.string), str); @@ -6675,7 +7162,8 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera Entity *e, Type *proc_type, Array const &positional_operands, Array const &named_operands, CallArgumentErrorMode show_error_mode, - CallArgumentData *data) { + CallArgumentData *data, + bool checking_proc_group) { bool return_on_failure = show_error_mode == CallArgumentErrorMode::NoErrors; @@ -6694,9 +7182,12 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera GB_ASSERT(proc_type != nullptr); proc_type = base_type(proc_type); + if (proc_type == t_invalid) { + return false; + } GB_ASSERT(proc_type->kind == Type_Proc); - CallArgumentError err = check_call_arguments_internal(c, call, e, proc_type, positional_operands, named_operands, show_error_mode, data); + CallArgumentError err = check_call_arguments_internal(c, call, e, proc_type, positional_operands, named_operands, show_error_mode, data, checking_proc_group); if (return_on_failure && err != CallArgumentError_None) { return false; } @@ -6821,31 +7312,40 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, array_unordered_remove(&procs, proc_index); continue; } + if (!pt->Proc.variadic && max_arg_count != ISIZE_MAX && param_count < max_arg_count) { + array_unordered_remove(&procs, proc_index); + continue; + } proc_index++; } } Entity **lhs = nullptr; isize lhs_count = -1; - bool is_variadic = false; + i32 variadic_index = -1; - auto positional_operands = array_make(heap_allocator(), 0, 0); - auto named_operands = array_make(heap_allocator(), 0, 0); - defer (array_free(&positional_operands)); - defer (array_free(&named_operands)); + TEMPORARY_ALLOCATOR_GUARD(); + + auto positional_operands = array_make(temporary_allocator(), 0, 0); + auto named_operands = array_make(temporary_allocator(), 0, 0); if (procs.count == 1) { Entity *e = procs[0]; - - lhs = populate_proc_parameter_list(c, e->type, &lhs_count, &is_variadic); - check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, is_variadic ? UnpackFlag_IsVariadic : UnpackFlag_None); + Type *pt = base_type(e->type); + if (pt != nullptr && is_type_proc(pt)) { + lhs = populate_proc_parameter_list(c, pt, &lhs_count); + if (pt->Proc.variadic) { + variadic_index = pt->Proc.variadic_index; + } + } + check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, UnpackFlag_None, variadic_index); if (check_named_arguments(c, e->type, named_args, &named_operands, true)) { check_call_arguments_single(c, call, operand, e, e->type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); } return data; } @@ -6868,7 +7368,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, if (proc_arg_count >= 0) { lhs_count = proc_arg_count; if (lhs_count > 0) { - lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count); + lhs = gb_alloc_array(temporary_allocator(), Entity *, lhs_count); for (isize param_index = 0; param_index < lhs_count; param_index++) { Entity *e = nullptr; for (Entity *p : procs) { @@ -6898,11 +7398,30 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, } lhs[param_index] = e; } + + for (Entity *p : procs) { + Type *pt = base_type(p->type); + if (!(pt != nullptr && is_type_proc(pt))) { + continue; + } + + if (pt->Proc.is_polymorphic) { + if (variadic_index == -1) { + variadic_index = pt->Proc.variadic_index; + } else if (variadic_index != pt->Proc.variadic_index) { + variadic_index = -1; + break; + } + } else { + variadic_index = -1; + break; + } + } } } } - check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, is_variadic ? UnpackFlag_IsVariadic : UnpackFlag_None); + check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, UnpackFlag_None, variadic_index); for_array(i, named_args) { Ast *arg = named_args[i]; @@ -6935,13 +7454,9 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, array_add(&named_operands, o); } - gb_free(heap_allocator(), lhs); + auto valids = array_make(temporary_allocator(), 0, procs.count); - auto valids = array_make(heap_allocator(), 0, procs.count); - defer (array_free(&valids)); - - auto proc_entities = array_make(heap_allocator(), 0, procs.count*2 + 1); - defer (array_free(&proc_entities)); + auto proc_entities = array_make(temporary_allocator(), 0, procs.count*2 + 1); for (Entity *proc : procs) { array_add(&proc_entities, proc); } @@ -6951,6 +7466,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, gbString expr_name = expr_to_string(operand->expr); defer (gb_string_free(expr_name)); + c->in_proc_group = true; for_array(i, procs) { Entity *p = procs[i]; if (p->flags & EntityFlag_Disabled) { @@ -6970,7 +7486,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, p, pt, positional_operands, named_operands, CallArgumentErrorMode::NoErrors, - &data); + &data, true); if (!is_a_candidate) { continue; } @@ -6993,6 +7509,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, array_add(&valids, item); } } + c->in_proc_group = false; if (max_matched_features > 0) { for_array(i, valids) { @@ -7022,18 +7539,45 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, } } + // auto print_argument_types = [&]() { + // error_line("\tGiven argument types: ("); + // isize i = 0; + // for (Operand const &o : positional_operands) { + // if (i++ > 0) error_line(", "); + // gbString type = type_to_string(o.type); + // defer (gb_string_free(type)); + // error_line("%s", type); + // } + // for (Operand const &o : named_operands) { + // if (i++ > 0) error_line(", "); + + // gbString type = type_to_string(o.type); + // defer (gb_string_free(type)); + + // if (i < ce->split_args->named.count) { + // Ast *named_field = ce->split_args->named[i]; + // ast_node(fv, FieldValue, named_field); + + // gbString field = expr_to_string(fv->field); + // defer (gb_string_free(field)); + + // error_line("%s = %s", field, type); + // } else { + // error_line("%s", type); + // } + // } + // error_line(")\n"); + // }; + auto print_argument_types = [&]() { - error_line("\tGiven argument types: ("); + error_line("\tGiven argument types:\n"); isize i = 0; for (Operand const &o : positional_operands) { - if (i++ > 0) error_line(", "); gbString type = type_to_string(o.type); defer (gb_string_free(type)); - error_line("%s", type); + error_line("\t • %s\n", type); } for (Operand const &o : named_operands) { - if (i++ > 0) error_line(", "); - gbString type = type_to_string(o.type); defer (gb_string_free(type)); @@ -7044,12 +7588,11 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, gbString field = expr_to_string(fv->field); defer (gb_string_free(field)); - error_line("%s = %s", field, type); + error_line("\t • %s = %s\n", field, type); } else { - error_line("%s", type); + error_line("\t • %s\n", type); } } - error_line(")\n"); }; if (valids.count == 0) { @@ -7065,12 +7608,9 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, if (procs.count == 0) { procs = proc_group_entities_cloned(c, *operand); } - if (procs.count > 0) { - error_line("Did you mean to use one of the following:\n"); - } // Try to reduce the list further for `$T: typeid` like parameters - bool *possibly_ignore = gb_alloc_array(temporary_allocator(), bool, procs.count); + bool *possibly_ignore = temporary_alloc_array(procs.count); isize possibly_ignore_set = 0; if (true) { @@ -7158,12 +7698,88 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, } isize max_spaces = gb_max(max_name_length, max_type_length); - char *spaces = gb_alloc_array(temporary_allocator(), char, max_spaces+1); + char *spaces = temporary_alloc_array(max_spaces+1); for (isize i = 0; i < max_spaces; i++) { spaces[i] = ' '; } spaces[max_spaces] = 0; + { + // TODO(bill): This is absolutely awful code, that needs improving a lot + + bool try_addr = false; + isize try_addr_idx = -1; + + for_array(i, procs) { + if (possibly_ignore_set != 0 && possibly_ignore[i]) { + continue; + } + Entity *proc = procs[i]; + TokenPos pos = proc->token.pos; + Type *t = base_type(proc->type); + if (t == t_invalid) continue; + GB_ASSERT(t->kind == Type_Proc); + if (t->Proc.params && t->Proc.params->Tuple.variables.count > 0) { + isize n = gb_min(t->Proc.params->Tuple.variables.count, positional_operands.count); + for (isize i = 0; i < n; i++) { + Type *dst = t->Proc.params->Tuple.variables[i]->type; + Operand src = positional_operands[i]; + if (check_is_assignable_to(c, &src, dst)) { + // okay + } else if (check_is_assignable_to(c, &src, type_deref(dst))) { + try_addr = true; + if (try_addr_idx < 0) { + try_addr_idx = i; + } + } + } + } + } + + if (try_addr) { + error_line(" \n"); + error_line("\tSuggestion:\n"); + error_line("\t\t%s(", expr_name); + isize i = 0; + for (Operand const &o : positional_operands) { + if (i++ > 0) error_line(", "); + gbString expr = expr_to_string(o.expr); + defer (gb_string_free(expr)); + + if (i-1 == try_addr_idx) { + error_line("&"); + } + error_line("%s", expr); + } + for (Operand const &o : named_operands) { + if (i++ > 0) error_line(", "); + + gbString expr = expr_to_string(o.expr); + defer (gb_string_free(expr)); + + if (i < ce->split_args->named.count) { + Ast *named_field = ce->split_args->named[i]; + ast_node(fv, FieldValue, named_field); + + gbString field = expr_to_string(fv->field); + defer (gb_string_free(field)); + + error_line("%s = %s", field, expr); + } else { + error_line("%s", expr); + } + } + error_line(")\n"); + + error_line(" \n"); // extra spaces to prevent newlines being consumed by the error handling syste, + } + } + + + if (procs.count > 0) { + error_line("Did you mean one of the following overloads?\n"); + } + for_array(i, procs) { if (possibly_ignore_set != 0 && possibly_ignore[i]) { continue; @@ -7210,6 +7826,30 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, } data.result_type = t_invalid; + if (procs.count > 0) { + Type *first_type = base_type(procs[0]->type); + GB_ASSERT(first_type->kind == Type_Proc); + Type *first_results = first_type->Proc.results; + bool all_the_same = true; + for (isize i = 1; i < procs.count; i++) { + Type *type = base_type(procs[i]->type); + if (type->kind != Type_Proc) { + all_the_same = false; + break; + } + Type *results = type->Proc.results; + if (!are_types_identical(first_results, results)) { + all_the_same = false; + break; + } + } + if (all_the_same && first_results != nullptr) { + GB_ASSERT_MSG(is_type_tuple(first_results), "%s", type_to_string(first_results)); + data.result_type = first_results; + } + } + + } else if (valids.count > 1) { ERROR_BLOCK(); @@ -7273,13 +7913,11 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, Entity *e = proc_entities[valids[0].index]; GB_ASSERT(e != nullptr); - Array named_operands = {}; - check_call_arguments_single(c, call, operand, e, e->type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); return data; } @@ -7320,7 +7958,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op } named_args = slice(ce->args, positional_args.count, ce->args.count); - auto split_args = gb_alloc_item(permanent_allocator(), AstSplitArgs); + auto split_args = permanent_alloc_item(); split_args->positional = positional_args; split_args->named = named_args; ce->split_args = split_args; @@ -7333,20 +7971,22 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op return check_call_arguments_proc_group(c, operand, call); } - auto positional_operands = array_make(heap_allocator(), 0, positional_args.count); - auto named_operands = array_make(heap_allocator(), 0, 0); + TEMPORARY_ALLOCATOR_GUARD(); - defer (array_free(&positional_operands)); - defer (array_free(&named_operands)); + auto positional_operands = array_make(temporary_allocator(), 0, positional_args.count); + auto named_operands = array_make(temporary_allocator(), 0, 0); if (positional_args.count > 0) { - isize lhs_count = -1; - bool is_variadic = false; Entity **lhs = nullptr; + isize lhs_count = -1; + i32 variadic_index = -1; if (pt != nullptr) { - lhs = populate_proc_parameter_list(c, proc_type, &lhs_count, &is_variadic); + lhs = populate_proc_parameter_list(c, proc_type, &lhs_count); + if (pt->variadic) { + variadic_index = pt->variadic_index; + } } - check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, is_variadic ? UnpackFlag_IsVariadic : UnpackFlag_None); + check_unpack_arguments(c, lhs, lhs_count, &positional_operands, positional_args, UnpackFlag_None, variadic_index); } if (named_args.count > 0) { @@ -7389,7 +8029,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op nullptr, proc_type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); } else if (pt) { data.result_type = pt->results; } @@ -7421,6 +8061,8 @@ gb_internal isize lookup_polymorphic_record_parameter(Type *t, String parameter_ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *operand, Ast *call) { + TEMPORARY_ALLOCATOR_GUARD(); + ast_node(ce, CallExpr, call); Type *original_type = operand->type; @@ -7429,7 +8071,6 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O bool show_error = true; Array operands = {}; - defer (array_free(&operands)); CallArgumentError err = CallArgumentError_None; @@ -7437,15 +8078,17 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O { // NOTE(bill, 2019-10-26): Allow a cycle in the parameters but not in the fields themselves auto prev_type_path = c->type_path; + c->type_path = new_checker_type_path(); defer ({ destroy_checker_type_path(c->type_path); c->type_path = prev_type_path; }); + TEMPORARY_ALLOCATOR_GUARD(); if (is_call_expr_field_value(ce)) { named_fields = true; - operands = array_make(heap_allocator(), ce->args.count); + operands = array_make(temporary_allocator(), ce->args.count); for_array(i, ce->args) { Ast *arg = ce->args[i]; ast_node(fv, FieldValue, arg); @@ -7477,7 +8120,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O } } else { - operands = array_make(heap_allocator(), 0, 2*ce->args.count); + operands = array_make(temporary_allocator(), 0, 2*ce->args.count); Entity **lhs = nullptr; isize lhs_count = -1; @@ -7519,7 +8162,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O } else { TEMPORARY_ALLOCATOR_GUARD(); - bool *visited = gb_alloc_array(temporary_allocator(), bool, param_count); + bool *visited = temporary_alloc_array(param_count); // LEAK(bill) ordered_operands = array_make(permanent_allocator(), param_count); @@ -7703,11 +8346,10 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O { GenTypesData *found_gen_types = ensure_polymorphic_record_entity_has_gen_types(c, original_type); - mutex_lock(&found_gen_types->mutex); defer (mutex_unlock(&found_gen_types->mutex)); - Entity *found_entity = find_polymorphic_record_entity(found_gen_types, param_count, ordered_operands); + Entity *found_entity = find_polymorphic_record_entity(found_gen_types, param_count, ordered_operands); if (found_entity) { operand->mode = Addressing_Type; operand->type = found_entity->type; @@ -7767,7 +8409,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O s = gb_string_append_fmt(s, "$%.*s", LIT(name)); if (v->kind == Entity_TypeName) { - if (v->type->kind != Type_Generic) { + if (v->type != nullptr && v->type->kind != Type_Generic) { s = gb_string_append_fmt(s, "="); s = write_type_to_string(s, v->type, false); } @@ -7835,8 +8477,171 @@ gb_internal bool check_call_parameter_mixture(Slice const &args, char con return Expr_Stmt; \ } +gb_internal ExprKind check_call_expr_as_type_cast(CheckerContext *c, Operand *operand, Ast *call, Slice const &args, Type *type_hint) { + GB_ASSERT(operand->mode == Addressing_Type); + Type *t = operand->type; + if (is_type_polymorphic_record(t)) { + CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction"); -gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice const &args, ProcInlining inlining, Type *type_hint) { + if (!is_type_named(t)) { + gbString s = expr_to_string(operand->expr); + error(call, "Illegal use of an unnamed polymorphic record, %s", s); + gb_string_free(s); + operand->mode = Addressing_Invalid; + operand->type = t_invalid;; + return Expr_Expr; + } + auto err = check_polymorphic_record_type(c, operand, call); + if (err == 0) { + Ast *ident = operand->expr; + while (ident->kind == Ast_SelectorExpr) { + Ast *s = ident->SelectorExpr.selector; + ident = s; + } + Type *ot = operand->type; + GB_ASSERT(ot->kind == Type_Named); + Entity *e = ot->Named.type_name; + add_entity_use(c, ident, e); + add_type_and_value(c, call, Addressing_Type, ot, empty_exact_value); + } else { + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + } + } else { + CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("type conversion"); + + operand->mode = Addressing_Invalid; + isize arg_count = args.count; + switch (arg_count) { + case 0: + { + gbString str = type_to_string(t); + error(call, "Missing argument in conversion to '%s'", str); + gb_string_free(str); + } break; + default: + { + gbString str = type_to_string(t); + if (t->kind == Type_Basic) { + ERROR_BLOCK(); + switch (t->Basic.kind) { + case Basic_complex32: + case Basic_complex64: + case Basic_complex128: + error(call, "Too many arguments in conversion to '%s'", str); + error_line("\tSuggestion: %s(1+2i) or construct with 'complex'\n", str); + break; + case Basic_quaternion64: + case Basic_quaternion128: + case Basic_quaternion256: + error(call, "Too many arguments in conversion to '%s'", str); + error_line("\tSuggestion: %s(1+2i+3j+4k) or construct with 'quaternion'\n", str); + break; + default: + error(call, "Too many arguments in conversion to '%s'", str); + } + } else { + error(call, "Too many arguments in conversion to '%s'", str); + } + gb_string_free(str); + } break; + case 1: { + Ast *arg = args[0]; + if (arg->kind == Ast_FieldValue) { + error(call, "'field = value' cannot be used in a type conversion"); + arg = arg->FieldValue.value; + // NOTE(bill): Carry on the cast regardless + } + check_expr_with_type_hint(c, operand, arg, t); + if (operand->mode != Addressing_Invalid) { + if (is_type_polymorphic(t)) { + error(call, "A polymorphic type cannot be used in a type conversion"); + } else { + // NOTE(bill): Otherwise the compiler can override the polymorphic type + // as it assumes it is determining the type + check_cast(c, operand, t); + } + } + operand->type = t; + operand->expr = call; + + + if (operand->mode != Addressing_Invalid) { + update_untyped_expr_type(c, arg, t, false); + check_representable_as_constant(c, operand->value, t, &operand->value); + } + break; + } + } + } + return Expr_Expr; +} + + +void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_type, Slice param_types); + +gb_internal void check_objc_call_expr(CheckerContext *c, Operand *operand, Ast *call, Entity *proc_entity, Type *proc_type) { + auto &proc = proc_type->Proc; + Slice params = proc.params ? proc.params->Tuple.variables : Slice{}; + + Type *self_type = nullptr; + isize params_start = 1; + + ast_node(ce, CallExpr, call); + + Type *return_type = proc.result_count == 0 ? nullptr : proc.results->Tuple.variables[0]->type; + bool is_return_instancetype = return_type != nullptr && return_type == t_objc_instancetype; + + if (proc_entity->Procedure.is_objc_class_method) { + if (is_return_instancetype) { + if (ce->proc->kind == Ast_SelectorExpr) { + ast_node(se, SelectorExpr, ce->proc); + + // NOTE(harold): These should have already been checked, right? + GB_ASSERT(se->expr->tav.mode == Addressing_Type && se->expr->tav.type->kind == Type_Named); + + return_type = alloc_type_pointer(se->expr->tav.type); + } else { + return_type = proc_entity->Procedure.objc_class->type; + } + } + + self_type = t_objc_Class; + params_start = 0; + } else { + GB_ASSERT(ce->args.count > 0); + GB_ASSERT(is_type_objc_ptr_to_object(params[0]->type)); + + if (ce->args[0]->tav.objc_super_target) { + self_type = t_objc_super_ptr; + } else { + self_type = ce->args[0]->tav.type; + } + + if (is_return_instancetype) { + // NOTE(harold): These should have already been checked, right? + GB_ASSERT(ce->args[0]->tav.type && ce->args[0]->tav.type->kind == Type_Pointer && ce->args[0]->tav.type->Pointer.elem->kind == Type_Named); + + return_type = ce->args[0]->tav.type; + } + } + + auto param_types = slice_make(permanent_allocator(), proc.param_count + 2 - params_start); + param_types[0] = self_type; + param_types[1] = t_objc_SEL; + + for (isize i = params_start; i < params.count; i++) { + param_types[i+2-params_start] = params[i]->type; + } + + if (is_return_instancetype) { + operand->type = return_type; + } + + add_objc_proc_type(c, call, return_type, param_types); +} + +gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *proc, Slice const &args, ProcInlining inlining, ProcTailing tailing, Type *type_hint) { if (proc != nullptr && proc->kind == Ast_BasicDirective) { ast_node(bd, BasicDirective, proc); @@ -7867,7 +8672,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c return Expr_Expr; } if (inlining != ProcInlining_none) { - error(call, "Inlining operators are not allowed on built-in procedures"); + error(call, "Inlining directives are not allowed on built-in procedures"); + } + if (tailing != ProcTailing_none) { + error(call, "Tailing directives are not allowed on built-in procedures"); } } else { if (proc != nullptr) { @@ -7891,79 +8699,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } if (operand->mode == Addressing_Type) { - Type *t = operand->type; - if (is_type_polymorphic_record(t)) { - CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("polymorphic type construction"); - - if (!is_type_named(t)) { - gbString s = expr_to_string(operand->expr); - error(call, "Illegal use of an unnamed polymorphic record, %s", s); - gb_string_free(s); - operand->mode = Addressing_Invalid; - operand->type = t_invalid;; - return Expr_Expr; - } - auto err = check_polymorphic_record_type(c, operand, call); - if (err == 0) { - Ast *ident = operand->expr; - while (ident->kind == Ast_SelectorExpr) { - Ast *s = ident->SelectorExpr.selector; - ident = s; - } - Type *ot = operand->type; - GB_ASSERT(ot->kind == Type_Named); - Entity *e = ot->Named.type_name; - add_entity_use(c, ident, e); - add_type_and_value(c, call, Addressing_Type, ot, empty_exact_value); - } else { - operand->mode = Addressing_Invalid; - operand->type = t_invalid; - } - } else { - CHECK_CALL_PARAMETER_MIXTURE_OR_RETURN("type conversion"); - - operand->mode = Addressing_Invalid; - isize arg_count = args.count; - switch (arg_count) { - case 0: - { - gbString str = type_to_string(t); - error(call, "Missing argument in conversion to '%s'", str); - gb_string_free(str); - } break; - default: - { - gbString str = type_to_string(t); - error(call, "Too many arguments in conversion to '%s'", str); - gb_string_free(str); - } break; - case 1: { - Ast *arg = args[0]; - if (arg->kind == Ast_FieldValue) { - error(call, "'field = value' cannot be used in a type conversion"); - arg = arg->FieldValue.value; - // NOTE(bill): Carry on the cast regardless - } - check_expr_with_type_hint(c, operand, arg, t); - if (operand->mode != Addressing_Invalid) { - if (is_type_polymorphic(t)) { - error(call, "A polymorphic type cannot be used in a type conversion"); - } else { - // NOTE(bill): Otherwise the compiler can override the polymorphic type - // as it assumes it is determining the type - check_cast(c, operand, t); - } - } - operand->type = t; - operand->expr = call; - if (operand->mode != Addressing_Invalid) { - update_untyped_expr_type(c, arg, t, false); - } - break; - } - } - } - return Expr_Expr; + return check_call_expr_as_type_cast(c, operand, call, args, type_hint); } if (operand->mode == Addressing_Builtin) { @@ -8050,7 +8786,13 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) { if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { - error(call, "'context' has not been defined within this scope, but is required for this procedure call"); + ERROR_BLOCK(); + if (c->scope->flags & ScopeFlag_File) { + error(call, "Procedures requiring a 'context' cannot be called at the global scope"); + } else { + error(call, "'context' has not been defined within this scope, but is required for this procedure call"); + error_line("\tSuggestion: 'context = runtime.default_context()'"); + } } } @@ -8075,6 +8817,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } bool is_call_inlined = false; + bool is_call_tailed = true; switch (inlining) { case ProcInlining_inline: @@ -8109,6 +8852,23 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } } + switch (tailing) { + case ProcTailing_none: + break; + case ProcTailing_must_tail: + is_call_tailed = true; + if (c->curr_proc_sig == nullptr || !are_types_identical(c->curr_proc_sig, pt)) { + ERROR_BLOCK(); + gbString a = type_to_string(pt); + gbString b = type_to_string(c->curr_proc_sig); + error(call, "Use of '#must_tail' of a procedure must have the same type as the procedure it was called within"); + error_line("\tCall type: %s, parent type: %s", a, b); + gb_string_free(b); + gb_string_free(a); + } + break; + } + { String invalid; if (pt->kind == Type_Proc && pt->Proc.require_target_feature.len != 0) { @@ -8129,9 +8889,10 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (c->curr_proc_decl == nullptr) { error(call, "Calling a '#force_inline' procedure that enables target features is not allowed at file scope"); } else { - GB_ASSERT(c->curr_proc_decl->entity); - GB_ASSERT(c->curr_proc_decl->entity->type->kind == Type_Proc); - String scope_features = c->curr_proc_decl->entity->type->Proc.enable_target_feature; + Entity *e = c->curr_proc_decl->entity.load(); + GB_ASSERT(e); + GB_ASSERT(e->type->kind == Type_Proc); + String scope_features = e->type->Proc.enable_target_feature; if (!check_target_feature_is_superset_of(scope_features, pt->Proc.enable_target_feature, &invalid)) { ERROR_BLOCK(); error(call, "Inlined procedure enables target feature '%.*s', this requires the calling procedure to at least enable the same feature", LIT(invalid)); @@ -8163,6 +8924,12 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } } + Entity *proc_entity = entity_from_expr(call->CallExpr.proc); + bool is_objc_call = proc_entity && proc_entity->kind == Entity_Procedure && proc_entity->Procedure.is_objc_impl_or_import; + if (is_objc_call) { + check_objc_call_expr(c, operand, call, proc_entity, pt); + } + return Expr_Expr; } @@ -8197,6 +8964,7 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 case Type_Basic: if (t->Basic.kind == Basic_string) { if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String); *max_count = o->value.value_string.len; } if (o->mode != Addressing_Constant) { @@ -8204,6 +8972,16 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 } o->type = t_u8; return true; + } else if (t->Basic.kind == Basic_string16) { + if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String16); + *max_count = o->value.value_string16.len; + } + if (o->mode != Addressing_Constant) { + o->mode = Addressing_Value; + } + o->type = t_u16; + return true; } else if (t->Basic.kind == Basic_UntypedString) { if (o->mode == Addressing_Constant) { *max_count = o->value.value_string.len; @@ -8271,10 +9049,27 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 o->mode = Addressing_Variable; } return true; + + case Type_FixedCapacityDynamicArray: + o->type = t->FixedCapacityDynamicArray.elem; + if (indirection) { + o->mode = Addressing_Variable; + } else if (o->mode != Addressing_Variable && + o->mode != Addressing_Constant) { + o->mode = Addressing_Value; + } + return true; + case Type_Struct: if (t->Struct.soa_kind != StructSoa_None) { - if (t->Struct.soa_kind == StructSoa_Fixed) { + switch (t->Struct.soa_kind) { + case StructSoa_Fixed: *max_count = t->Struct.soa_count; + break; + case StructSoa_Slice: + case StructSoa_Dynamic: + indirection = o->mode != Addressing_Constant; + break; } o->type = t->Struct.soa_elem; if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable || indirection) { @@ -8413,10 +9208,20 @@ gb_internal bool check_range(CheckerContext *c, Ast *node, bool is_for_loop, Ope return true; } -gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Operand *o) { +gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Operand *o, Type *field_type) { if (is_operand_nil(*o)) { return true; } + if (is_type_any(field_type)) { + return false; + } + if (field_type != nullptr && is_type_typeid(field_type)) { + if (o->mode == Addressing_Type) { + add_type_info_type(c, o->type); + return true; + } + } + Ast *expr = unparen_expr(o->expr); if (expr != nullptr) { Entity *e = strip_entity_wrapping(entity_from_expr(expr)); @@ -8427,6 +9232,12 @@ gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Opera add_type_and_value(c, expr, Addressing_Constant, type_of_expr(expr), exact_value_procedure(expr)); return true; } + + if (e != nullptr && e->kind == Entity_Variable && e->Variable.is_rodata) { + // DeclInfo *d = e->decl_info; + // TODO(bill): rodata inlining for non-indirect values + // e.g. **NOT** []T{...} + } } return o->mode == Addressing_Constant; } @@ -8437,7 +9248,7 @@ gb_internal bool attempt_implicit_selector_expr(CheckerContext *c, Operand *o, A Type *enum_type = base_type(th); GB_ASSERT(enum_type->kind == Type_Enum); - String name = ise->selector->Ident.token.string; + auto name = ise->selector->Ident.interned; Entity *e = scope_lookup_current(enum_type->Enum.scope, name); if (e == nullptr) { @@ -8657,7 +9468,7 @@ gb_internal void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Op isize count = multi_map_count(seen, key); if (count) { TEMPORARY_ALLOCATOR_GUARD(); - TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count); + TypeAndToken *taps = temporary_alloc_array(count); multi_map_get_all(seen, key, taps); for (isize i = 0; i < count; i++) { @@ -8689,7 +9500,6 @@ gb_internal void add_constant_switch_case(CheckerContext *ctx, SeenMap *seen, Op multi_map_insert(seen, key, tap); } - gb_internal void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind upper_op, Operand const &x, Operand const &lhs, Operand const &rhs) { if (is_type_enum(x.type)) { // TODO(bill): Fix this logic so it's fast!!! @@ -8718,10 +9528,50 @@ gb_internal void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, TokenKind u } } } + gb_internal void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, Operand const &x) { add_constant_switch_case(ctx, seen, x); } +gb_internal void add_type_switch_case(CheckerContext *ctx, SeenMap *seen, Operand operand) { + if (operand.mode != Addressing_Type) { + return ; + } + + uintptr key = type_hash_canonical_type(operand.type); + GB_ASSERT(key != 0); + + isize count = multi_map_count(seen, key); + if (count) { + TEMPORARY_ALLOCATOR_GUARD(); + TypeAndToken *taps = temporary_alloc_array(count); + + multi_map_get_all(seen, key, taps); + for (isize i = 0; i < count; i++) { + TypeAndToken tap = taps[i]; + if (!are_types_identical(tap.type, operand.type)) { + continue; + } + + TokenPos pos = tap.token.pos; + gbString expr_str = expr_to_string(operand.expr); + error(operand.expr, + "Duplicate case '%s'\n" + "\tprevious case at %s", + expr_str, + token_pos_to_string(pos)); + gb_string_free(expr_str); + } + } + + TypeAndToken tap = { operand.type, ast_token(operand.expr) }; + multi_map_insert(seen, key, tap); +} + +gb_internal void add_type_to_seen_map(CheckerContext *ctx, SeenMap *seen, Operand const &x) { + add_type_switch_case(ctx, seen, x); +} + gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ast_node(bd, BasicDirective, node); @@ -8731,23 +9581,52 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A String name = bd->name.string; if (name == "file") { String file = get_file_path_string(bd->token.pos.file_id); - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: file = obfuscate_string(file, "F"); + break; + case SourceCodeLocationInfo_Filename: + file = last_path_element(file); + break; + case SourceCodeLocationInfo_None: + file = str_lit(""); + break; } o->type = t_untyped_string; o->value = exact_value_string(file); } else if (name == "directory") { String file = get_file_path_string(bd->token.pos.file_id); String path = dir_from_path(file); - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: path = obfuscate_string(path, "D"); + break; + case SourceCodeLocationInfo_Filename: + path = last_path_element(path); + break; + case SourceCodeLocationInfo_None: + path = str_lit(""); + break; } o->type = t_untyped_string; o->value = exact_value_string(path); } else if (name == "line") { i32 line = bd->token.pos.line; - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: line = obfuscate_i32(line); + break; + case SourceCodeLocationInfo_Filename: + break; + case SourceCodeLocationInfo_None: + line = 0; + break; } o->type = t_untyped_integer; o->value = exact_value_i64(line); @@ -8758,8 +9637,17 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A o->value = exact_value_string(str_lit("")); } else { String p = c->proc_name; - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: p = obfuscate_string(p, "P"); + break; + case SourceCodeLocationInfo_Filename: + break; + case SourceCodeLocationInfo_None: + p = str_lit(""); + break; } o->type = t_untyped_string; o->value = exact_value_string(p); @@ -8814,6 +9702,52 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A return kind; } + +gb_internal void check_expr_as_value_for_ternary(CheckerContext *c, Operand *o, Ast *e, Type *type_hint) { + check_expr_base(c, o, e, type_hint); + check_not_tuple(c, o); + error_operand_no_value(o); + + switch (o->mode) { + case Addressing_Type: { + ERROR_BLOCK(); + gbString expr_str = expr_to_string(o->expr); + defer (gb_string_free(expr_str)); + + error(o->expr, "A type '%s' cannot be used as a runtime value", expr_str); + + error_line("\tSuggestion: If a runtime 'typeid' is wanted, use 'typeid_of' to convert a type\n"); + + o->mode = Addressing_Invalid; + + } break; + + case Addressing_Builtin: { + ERROR_BLOCK(); + gbString expr_str = expr_to_string(o->expr); + defer (gb_string_free(expr_str)); + + error(o->expr, "A built-in procedure '%s' cannot be used as a runtime value", expr_str); + + error_line("\tNote: Built-in procedures are implemented by the compiler and might not be actually instantiated procedures\n"); + + o->mode = Addressing_Invalid; + } break; + + case Addressing_ProcGroup: { + ERROR_BLOCK(); + gbString expr_str = expr_to_string(o->expr); + defer (gb_string_free(expr_str)); + + error(o->expr, "Cannot use overloaded procedure '%s' as a runtime value", expr_str); + + error_line("\tNote: Please specify which procedure in the procedure group to use, via cast or type inference\n"); + + o->mode = Addressing_Invalid; + } break; + } +} + gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind kind = Expr_Expr; Operand cond = {Addressing_Invalid}; @@ -8822,12 +9756,16 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n node->viral_state_flags |= te->cond->viral_state_flags; if (cond.mode != Addressing_Invalid && !is_type_boolean(cond.type)) { + ERROR_BLOCK(); error(te->cond, "Non-boolean condition in ternary if expression"); + if (is_type_simd_vector(cond.type)) { + error_line("\tSuggestion: Use 'simd.select' a ternary-like operation is required\n"); + } } Operand x = {Addressing_Invalid}; Operand y = {Addressing_Invalid}; - check_expr_or_type(c, &x, te->x, type_hint); + check_expr_as_value_for_ternary(c, &x, te->x, type_hint); node->viral_state_flags |= te->x->viral_state_flags; if (te->y != nullptr) { @@ -8835,7 +9773,7 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n if (type_hint == nullptr && is_type_typed(x.type)) { th = x.type; } - check_expr_or_type(c, &y, te->y, th); + check_expr_as_value_for_ternary(c, &y, te->y, th); node->viral_state_flags |= te->y->viral_state_flags; } else { error(node, "A ternary expression must have an else clause"); @@ -8862,6 +9800,20 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n return kind; } + if (x.mode == Addressing_Builtin && y.mode == Addressing_Builtin) { + if (type_hint == nullptr) { + error(node, "Built-in procedures cannot be used within a ternary expression since they have no well-defined signature"); + return kind; + } + } + + if (x.mode == Addressing_ProcGroup && y.mode == Addressing_ProcGroup) { + if (type_hint == nullptr) { + error(node, "Procedure groups cannot be used within a ternary expression since they have no well-defined signature that can be inferred without a context"); + return kind; + } + } + // NOTE(bill, 2023-01-30): Allow for expression like this: // x: union{f32} = f32(123) if cond else nil if (type_hint && !is_type_any(type_hint)) { @@ -9235,6 +10187,10 @@ gb_internal ExprKind check_or_branch_expr(CheckerContext *c, Operand *o, Ast *no } } + if (c->in_defer) { + error(node, "'%.*s' cannot be used within a 'defer'", LIT(name)); + } + return Expr_Expr; } @@ -9250,7 +10206,7 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicekind == Type_BitField) { - assignment_str = str_lit("bit_field literal"); + assignment_str = str_lit("'bit_field' literal"); } for (Ast *elem : elems) { @@ -9262,23 +10218,26 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicefield; if (ident->kind == Ast_ImplicitSelectorExpr) { gbString expr_str = expr_to_string(ident); - error(ident, "Field names do not start with a '.', remove the '.' in structure literal", expr_str); + error(ident, "Field names do not start with a '.', remove the '.' in %.*s", expr_str, LIT(assignment_str)); gb_string_free(expr_str); ident = ident->ImplicitSelectorExpr.selector; } if (ident->kind != Ast_Ident) { gbString expr_str = expr_to_string(ident); - error(elem, "Invalid field name '%s' in structure literal", expr_str); + error(elem, "Invalid field name '%s' in %.*s", expr_str, LIT(assignment_str)); gb_string_free(expr_str); continue; } String name = ident->Ident.token.string; + auto interned = ident->Ident.interned; - Selection sel = lookup_field(type, name, o->mode == Addressing_Type); + Selection sel = lookup_field(type, interned, o->mode == Addressing_Type); bool is_unknown = sel.entity == nullptr; if (is_unknown) { - error(ident, "Unknown field '%.*s' in structure literal", LIT(name)); + gbString s = type_to_string(type); + error(ident, "Unknown field '%.*s' in %.*s", LIT(name), LIT(assignment_str)); + gb_string_free(s); continue; } @@ -9332,7 +10291,7 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, SliceArray.elem; break; case Type_BitField: - is_constant = false; + // is_constant = false; ft = bt->BitField.fields[index]->type; break; default: @@ -9340,8 +10299,7 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicevalue, field->type); - if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { + if (elem_cannot_be_constant(field->type)) { is_constant = false; } if (is_constant) { - is_constant = check_is_operand_compound_lit_constant(c, &o); + is_constant = check_is_operand_compound_lit_constant(c, &o, field->type); } + if (bt->kind == Type_BitField) { + if (is_type_different_to_arch_endianness(field->type)) { + is_constant = false; + } + } + u8 prev_bit_field_bit_size = c->bit_field_bit_size; if (field->kind == Entity_Variable && field->Variable.bit_field_bit_size) { @@ -9393,6 +10357,57 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicebit_field_bit_size = prev_bit_field_bit_size; } + + if (bt->kind == Type_Struct && bt->Struct.is_all_or_none && elems.count > 0 && bt->Struct.fields.count > 0) { + PtrSet missing_fields = {}; + defer (ptr_set_destroy(&missing_fields)); + + for_array(i, bt->Struct.fields) { + Entity *field = bt->Struct.fields[i]; + String name = field->token.string; + if (is_blank_ident(name) || name == "") { + continue; + } + bool found = string_set_exists(&fields_visited, name); + String *raw_union = string_map_get(&fields_visited_through_raw_union, name); + if (!found && raw_union == nullptr) { + ptr_set_add(&missing_fields, field); + } + } + + if (missing_fields.count > 0) { + Ast *expr = o->expr; + if (expr == nullptr) { + GB_ASSERT(elems.count > 0); + expr = elems[elems.count-1]; + } + + ERROR_BLOCK(); + + if (build_context.terse_errors) { + gbString fields_string = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(fields_string)); + isize i = 0; + FOR_PTR_SET(field, missing_fields) { + if (i > 0) { + fields_string = gb_string_appendc(fields_string, ", "); + } + String name = field->token.string; + fields_string = gb_string_append_length(fields_string, name.text, name.len); + i += 1; + } + + error(expr, "All or none of the fields must be assigned to a struct with '#all_or_none' applied, missing fields: %s", fields_string); + } else { + error(expr, "All or none of the fields must be assigned to a struct with '#all_or_none' applied, missing fields:"); + FOR_PTR_SET(field, missing_fields) { + gbString s = type_to_string(field->type); + error_line("\t%.*s: %s\n", LIT(field->token.string), s); + gb_string_free(s); + } + } + } + } } gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) { @@ -9413,7 +10428,10 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) { } gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) { - if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) { + if (cl->elems.count == 0) { + return false; + } + if ((check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0 && !build_context.dynamic_literals) { ERROR_BLOCK(); error(node, "Compound literals of dynamic types are disabled by default"); error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n"); @@ -9424,9 +10442,31 @@ gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCom error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n"); } return false; + } else if (c->curr_proc_decl != nullptr && c->curr_proc_calling_convention != ProcCC_Odin) { + if (c->scope != nullptr && (c->scope->flags & ScopeFlag_ContextDefined) == 0) { + error(node, "Compound literals of dynamic types require a 'context' to defined"); + } } - return cl->elems.count > 0; + return true; +} + +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(CheckerContext *c, Ast *node) { + // TODO(bill): per file `#+feature` flags + u64 flags = check_feature_flags(c, node); + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Trap) != 0) { + return IntegerDivisionByZero_Trap; + } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) != 0) { + return IntegerDivisionByZero_Zero; + } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Self) != 0) { + return IntegerDivisionByZero_Self; + } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_AllBits) != 0) { + return IntegerDivisionByZero_AllBits; + } + return build_context.integer_division_by_zero_behaviour; } gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { @@ -9439,6 +10479,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } bool is_to_be_determined_array_count = false; bool is_constant = true; + bool is_soa = false; Ast *type_expr = cl->type; @@ -9471,8 +10512,14 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * GB_ASSERT(tag->kind == Ast_BasicDirective); String name = tag->BasicDirective.name.string; if (name == "soa") { - error(node, "#soa arrays are not supported for compound literals"); - return kind; + is_soa = true; + if (count == nullptr) { + error(node, "#soa slices are not supported for compound literals"); + return kind; + } else if (count->kind == Ast_UnaryExpr && + count->UnaryExpr.op.kind == Token_Question) { + error(node, "#soa fixed length arrays must specify their length and cannot use ?"); + } } } } @@ -9482,7 +10529,8 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * GB_ASSERT(tag->kind == Ast_BasicDirective); String name = tag->BasicDirective.name.string; if (name == "soa") { - error(node, "#soa arrays are not supported for compound literals"); + is_soa = true; + error(node, "#soa dynamic arrays are not supported for compound literals"); return kind; } } @@ -9511,112 +10559,146 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * switch (t->kind) { - case Type_Struct: { + case Type_Struct: if (cl->elems.count == 0) { break; // NOTE(bill): No need to init } - if (t->Struct.soa_kind != StructSoa_None) { - error(node, "#soa arrays are not supported for compound literals"); - break; - } + if (t->Struct.soa_kind == StructSoa_None) { + if (t->Struct.is_raw_union) { + if (cl->elems.count > 0) { + // NOTE: unions cannot be constant + is_constant = elem_type_can_be_constant(t); - if (t->Struct.is_raw_union) { - if (cl->elems.count > 0) { - // NOTE: unions cannot be constant - is_constant = false; - - if (cl->elems[0]->kind != Ast_FieldValue) { - gbString type_str = type_to_string(type); - error(node, "%s ('struct #raw_union') compound literals are only allowed to contain 'field = value' elements", type_str); - gb_string_free(type_str); - } else { - if (cl->elems.count != 1) { + if (cl->elems[0]->kind != Ast_FieldValue) { gbString type_str = type_to_string(type); - error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count); + error(node, "%s ('struct #raw_union') compound literals are only allowed to contain 'field = value' elements", type_str); gb_string_free(type_str); } else { - check_compound_literal_field_values(c, cl->elems, o, type, is_constant); + if (cl->elems.count != 1) { + gbString type_str = type_to_string(type); + error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count); + gb_string_free(type_str); + } else { + check_compound_literal_field_values(c, cl->elems, o, type, is_constant); + } + } + } + break; + } + + wait_signal_until_available(&t->Struct.fields_wait_signal); + isize field_count = t->Struct.fields.count; + isize min_field_count = t->Struct.fields.count; + for (isize i = min_field_count-1; i >= 0; i--) { + Entity *e = t->Struct.fields[i]; + GB_ASSERT(e->kind == Entity_Variable); + if (e->Variable.param_value.kind != ParameterValue_Invalid) { + min_field_count--; + } else { + break; + } + } + + if (cl->elems[0]->kind == Ast_FieldValue) { + check_compound_literal_field_values(c, cl->elems, o, type, is_constant); + } else { + bool seen_field_value = false; + + isize handled_elem_count = 0; + isize index = 0; + for (Ast *elem : cl->elems) { + defer (index += 1); + + Entity *field = nullptr; + if (elem->kind == Ast_FieldValue) { + seen_field_value = true; + error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); + continue; + } else if (seen_field_value) { + error(elem, "Value elements cannot be used after a 'field = value'"); + continue; + } + if (index >= field_count) { + error(elem, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count); + break; + } + + if (field == nullptr) { + field = t->Struct.fields[index]; + } + + Operand o = {}; + check_multi_expr_with_type_hint(c, &o, elem, field->type); + if (is_type_tuple(o.type)) { + is_constant = false; + + TypeTuple *tt = &o.type->Tuple; + isize jj = 0; + for (Entity *src_field : tt->variables) { + Operand src_o = o; + src_o.type = src_field->type; + + field = t->Struct.fields[index + (jj++)]; + + check_assignment(c, &src_o, field->type, str_lit("structure literal")); + } + + index += tt->variables.count-1; + + handled_elem_count += tt->variables.count; + } else { + check_not_tuple(c, &o); + + if (elem_cannot_be_constant(field->type)) { + is_constant = false; + } + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &o, field->type); + } + + check_assignment(c, &o, field->type, str_lit("structure literal")); + + handled_elem_count += 1; + } + + } + if (cl->elems.count < field_count) { + if (min_field_count < field_count) { + if (cl->elems.count < min_field_count) { + error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count); + } + } else if (handled_elem_count != field_count) { + error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count); } } } + + break; + } else if (t->Struct.soa_kind != StructSoa_Fixed) { + error(node, "#soa slices and dynamic arrays are not supported for compound literals"); break; } - - wait_signal_until_available(&t->Struct.fields_wait_signal); - isize field_count = t->Struct.fields.count; - isize min_field_count = t->Struct.fields.count; - for (isize i = min_field_count-1; i >= 0; i--) { - Entity *e = t->Struct.fields[i]; - GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.param_value.kind != ParameterValue_Invalid) { - min_field_count--; - } else { - break; - } - } - - if (cl->elems[0]->kind == Ast_FieldValue) { - check_compound_literal_field_values(c, cl->elems, o, type, is_constant); - } else { - bool seen_field_value = false; - - for_array(index, cl->elems) { - Entity *field = nullptr; - Ast *elem = cl->elems[index]; - if (elem->kind == Ast_FieldValue) { - seen_field_value = true; - error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed"); - continue; - } else if (seen_field_value) { - error(elem, "Value elements cannot be used after a 'field = value'"); - continue; - } - if (index >= field_count) { - error(elem, "Too many values in structure literal, expected %td, got %td", field_count, cl->elems.count); - break; - } - - if (field == nullptr) { - field = t->Struct.fields[index]; - } - - Operand o = {}; - check_expr_or_type(c, &o, elem, field->type); - - if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) { - is_constant = false; - } - if (is_constant) { - is_constant = check_is_operand_compound_lit_constant(c, &o); - } - - check_assignment(c, &o, field->type, str_lit("structure literal")); - } - if (cl->elems.count < field_count) { - if (min_field_count < field_count) { - if (cl->elems.count < min_field_count) { - error(cl->close, "Too few values in structure literal, expected at least %td, got %td", min_field_count, cl->elems.count); - } - } else { - error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count); - } - } - } - - break; - } + /*fallthrough*/ case Type_Slice: case Type_Array: case Type_DynamicArray: case Type_SimdVector: case Type_Matrix: + case Type_FixedCapacityDynamicArray: { Type *elem_type = nullptr; String context_name = {}; i64 max_type_count = -1; - if (t->kind == Type_Slice) { + if (t->kind == Type_Struct) { + GB_ASSERT(t->Struct.soa_kind == StructSoa_Fixed); + elem_type = t->Struct.soa_elem; + context_name = str_lit("#soa array literal"); + if (!is_to_be_determined_array_count) { + max_type_count = t->Struct.soa_count; + } + } else if (t->kind == Type_Slice) { elem_type = t->Slice.elem; context_name = str_lit("slice literal"); } else if (t->kind == Type_Array) { @@ -9625,10 +10707,20 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * if (!is_to_be_determined_array_count) { max_type_count = t->Array.count; } + } else if (t->kind == Type_Array) { + elem_type = t->Array.elem; + context_name = str_lit("array literal"); + if (!is_to_be_determined_array_count) { + max_type_count = t->Array.count; + } } else if (t->kind == Type_DynamicArray) { elem_type = t->DynamicArray.elem; context_name = str_lit("dynamic array literal"); is_constant = false; + } else if (t->kind == Type_FixedCapacityDynamicArray) { + elem_type = t->FixedCapacityDynamicArray.elem; + context_name = str_lit("fixed capacity dynamic array literal"); + max_type_count = t->FixedCapacityDynamicArray.capacity; } else if (t->kind == Type_SimdVector) { elem_type = t->SimdVector.elem; context_name = str_lit("simd vector literal"); @@ -9642,6 +10734,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } + i64 max = 0; Type *bet = base_type(elem_type); @@ -9716,7 +10809,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } } else { Operand op_index = {}; check_expr(c, &op_index, fv->field); @@ -9748,14 +10843,17 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } } } cl->max_count = max; } else { - isize index = 0; - for (; index < cl->elems.count; index++) { + for (isize index = 0; index < cl->elems.count; index++) { + defer (max += 1); + Ast *e = cl->elems[index]; if (e == nullptr) { error(node, "Invalid literal element"); @@ -9772,14 +10870,24 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } Operand operand = {}; - check_expr_with_type_hint(c, &operand, e, elem_type); - check_assignment(c, &operand, elem_type, context_name); + check_multi_expr_with_type_hint(c, &operand, e, elem_type); + if (is_type_tuple(operand.type)) { + is_constant = false; + TypeTuple *tt = &operand.type->Tuple; + for_array(jj, tt->variables) { + Operand oo = operand; + oo.type = tt->variables[jj]->type; + check_assignment(c, &oo, elem_type, context_name); + } - is_constant = is_constant && operand.mode == Addressing_Constant; - } + max += tt->variables.count-1; + } else { + check_assignment(c, &operand, elem_type, context_name); - if (max < index) { - max = index; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } + } } } @@ -9792,6 +10900,21 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max); } } + } else if (t->kind == Type_Struct) { + GB_ASSERT(t->Struct.soa_kind == StructSoa_Fixed); + if (is_to_be_determined_array_count) { + t->Struct.soa_count = cast(i32)max; + } else if (cl->elems.count > 0 && cl->elems[0]->kind != Ast_FieldValue) { + if (0 < max && max < t->Struct.soa_count) { + error(node, "Expected %lld values for this #soa array literal, got %lld", cast(long long)t->Struct.soa_count, cast(long long)max); + } + } + } else if (t->kind == Type_FixedCapacityDynamicArray) { + if (max > t->FixedCapacityDynamicArray.capacity) { + error(node, "Expected a maximum of %lld values for this fixed capacity dynamic array, got %lld", + cast(long long)t->FixedCapacityDynamicArray.capacity, + cast(long long)max); + } } @@ -9817,6 +10940,8 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } } + cl->max_count = max; + break; } @@ -9940,7 +11065,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } TokenKind upper_op = Token_LtEq; if (op.kind == Token_RangeHalf) { @@ -9981,7 +11108,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } add_to_seen_map(c, &seen, op_index); } @@ -10011,7 +11140,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, e, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } } if (max < index) { @@ -10108,8 +11239,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * continue; } String name = fv->field->Ident.token.string; + auto interned = fv->field->Ident.interned; - Selection sel = lookup_field(type, name, o->mode == Addressing_Type); + Selection sel = lookup_field(type, interned, o->mode == Addressing_Type); if (sel.entity == nullptr) { error(elem, "Unknown field '%.*s' in 'any' literal", LIT(name)); continue; @@ -10215,52 +11347,48 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * is_constant = false; } - if (cl->elems[0]->kind == Ast_FieldValue) { - error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed"); - is_constant = false; - } else { - for (Ast *elem : cl->elems) { - if (elem->kind == Ast_FieldValue) { - error(elem, "'field = value' in a bit_set a literal is not allowed"); + for (Ast *elem : cl->elems) { + if (elem->kind == Ast_FieldValue) { + error(elem, "'field = value' in a bit_set literal is not allowed"); + is_constant = false; + continue; + } + + check_expr_with_type_hint(c, o, elem, et); + + if (is_constant) { + is_constant = o->mode == Addressing_Constant; + } + + if (elem->kind == Ast_BinaryExpr) { + switch (elem->BinaryExpr.op.kind) { + case Token_Or: + { + gbString x = expr_to_string(elem->BinaryExpr.left); + gbString y = expr_to_string(elem->BinaryExpr.right); + gbString e = expr_to_string(elem); + error(elem, "Was the following intended? '%s, %s'; if not, surround the expression with parentheses '(%s)'", x, y, e); + gb_string_free(e); + gb_string_free(y); + gb_string_free(x); + } + break; + } + } + + check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal")); + if (o->mode == Addressing_Constant) { + i64 lower = t->BitSet.lower; + i64 upper = t->BitSet.upper; + i64 v = exact_value_to_i64(o->value); + if (lower <= v && v <= upper) { + // okay + } else { + gbString s = expr_to_string(o->expr); + error(elem, "Bit field value out of bounds, %s (%lld) not in the range %lld .. %lld", s, v, lower, upper); + gb_string_free(s); continue; } - - check_expr_with_type_hint(c, o, elem, et); - - if (is_constant) { - is_constant = o->mode == Addressing_Constant; - } - - if (elem->kind == Ast_BinaryExpr) { - switch (elem->BinaryExpr.op.kind) { - case Token_Or: - { - gbString x = expr_to_string(elem->BinaryExpr.left); - gbString y = expr_to_string(elem->BinaryExpr.right); - gbString e = expr_to_string(elem); - error(elem, "Was the following intended? '%s, %s'; if not, surround the expression with parentheses '(%s)'", x, y, e); - gb_string_free(e); - gb_string_free(y); - gb_string_free(x); - } - break; - } - } - - check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal")); - if (o->mode == Addressing_Constant) { - i64 lower = t->BitSet.lower; - i64 upper = t->BitSet.upper; - i64 v = exact_value_to_i64(o->value); - if (lower <= v && v <= upper) { - // okay - } else { - gbString s = expr_to_string(o->expr); - error(elem, "Bit field value out of bounds, %s (%lld) not in the range %lld .. %lld", s, v, lower, upper); - gb_string_free(s); - continue; - } - } } } break; @@ -10269,7 +11397,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * if (cl->elems.count == 0) { break; // NOTE(bill): No need to init } - is_constant = false; + // is_constant = false; if (cl->elems[0]->kind != Ast_FieldValue) { gbString type_str = type_to_string(type); error(node, "%s ('bit_field') compound literals are only allowed to contain 'field = value' elements", type_str); @@ -10484,8 +11612,20 @@ gb_internal ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *no end:; if ((c->state_flags & StateFlag_no_type_assert) == 0) { - add_package_dependency(c, "runtime", "type_assertion_check"); - add_package_dependency(c, "runtime", "type_assertion_check2"); + bool has_context = true; + if (c->proc_name.len == 0 && c->curr_proc_sig == nullptr) { + has_context = false; + } else if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { + has_context = false; + } + + if (has_context) { + add_package_dependency(c, "runtime", "type_assertion_check_with_context"); + add_package_dependency(c, "runtime", "type_assertion_check2_with_context"); + } else { + add_package_dependency(c, "runtime", "type_assertion_check_contextless"); + add_package_dependency(c, "runtime", "type_assertion_check2_contextless"); + } } return kind; } @@ -10621,7 +11761,7 @@ gb_internal ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast } } - auto modified_args = slice_make(heap_allocator(), ce->args.count+1); + auto modified_args = permanent_slice_make(ce->args.count+1); modified_args[0] = first_arg; slice_copy(&modified_args, ce->args, 1); ce->args = modified_args; @@ -10659,11 +11799,11 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, check_expr_with_type_hint(c, &key, ie->index, t->Map.key); } check_assignment(c, &key, t->Map.key, str_lit("map index")); - if (key.mode == Addressing_Invalid) { - o->mode = Addressing_Invalid; - o->expr = node; - return kind; - } + // if (key.mode == Addressing_Invalid) { + // o->mode = Addressing_Invalid; + // o->expr = node; + // return kind; + // } o->mode = Addressing_MapIndex; o->type = t->Map.value; o->expr = node; @@ -10683,6 +11823,8 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, // Okay } else if (is_type_enumerated_array(t)) { // Okay + } else if (is_type_fixed_capacity_dynamic_array(t)) { + // Okay } else if (is_type_string(t)) { // Okay } else if (is_type_matrix(t)) { @@ -10693,6 +11835,8 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, } if (!valid) { + ERROR_BLOCK(); + gbString str = expr_to_string(o->expr); gbString type_str = type_to_string(o->type); defer (gb_string_free(str)); @@ -10702,6 +11846,10 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, } else { error(o->expr, "Cannot index '%s' of type '%s'", str, type_str); } + if (is_type_simd_vector(o->type)) { + error_line("\tSuggestion: Use 'simd.extract' or 'simd.replace' instead depending on the situation\n"); + } + o->mode = Addressing_Invalid; o->expr = node; return kind; @@ -10786,9 +11934,17 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { valid = true; if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String); max_count = o->value.value_string.len; } o->type = type_deref(o->type); + } else if (t->Basic.kind == Basic_string16) { + valid = true; + if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String16); + max_count = o->value.value_string16.len; + } + o->type = type_deref(o->type); } break; @@ -10821,6 +11977,19 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, o->type = alloc_type_slice(t->DynamicArray.elem); break; + case Type_FixedCapacityDynamicArray: + valid = true; + if (o->mode != Addressing_Variable && !is_type_pointer(o->type)) { + gbString str = expr_to_string(node); + error(node, "Cannot slice a fixed capacity dynamic array '%s', value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + o->type = alloc_type_slice(t->FixedCapacityDynamicArray.elem); + break; + case Type_Struct: if (is_type_soa_struct(t)) { valid = true; @@ -10841,9 +12010,14 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, case Type_EnumeratedArray: { + ERROR_BLOCK(); + gbString str = expr_to_string(o->expr); gbString type_str = type_to_string(o->type); error(o->expr, "Cannot slice '%s' of type '%s', as enumerated arrays cannot be sliced", str, type_str); + + error_line("\tSuggestion: Slicing an enumerated array does not make much sense, but if you need such a construct, use 'slice.enumerated_array'\n"); + gb_string_free(type_str); gb_string_free(str); o->mode = Addressing_Invalid; @@ -10943,15 +12117,21 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, o->expr = node; return kind; } - - String s = {}; - if (o->value.kind == ExactValue_String) { - s = o->value.value_string; - } - o->mode = Addressing_Constant; o->type = t; - o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + + if (o->value.kind == ExactValue_String16) { + String16 s = o->value.value_string16; + + o->value = exact_value_string16(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + } else { + String s = {}; + if (o->value.kind == ExactValue_String) { + s = o->value.value_string; + } + + o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + } } return kind; } @@ -10996,7 +12176,16 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast return kind; case_end; - case_ast_node(i, Implicit, node) + case_ast_node(ht, HelperType, node); + Type *type = check_type(c, ht->type); + if (type != nullptr && type != t_invalid) { + o->mode = Addressing_Type; + o->type = type; + } + return kind; + case_end; + + case_ast_node(i, Implicit, node); switch (i->kind) { case Token_context: { @@ -11032,7 +12221,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast case_ast_node(u, Uninit, node); o->mode = Addressing_Value; o->type = t_untyped_uninit; - error(node, "Use of --- outside of variable declaration"); + error(node, "Global variables will always be zeroed if left unassigned, --- is disallowed"); case_end; @@ -11040,6 +12229,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast Type *t = t_invalid; switch (node->tav.value.kind) { case ExactValue_String: t = t_untyped_string; break; + case ExactValue_String16: t = t_string16; break; // TODO(bill): determine this correctly case ExactValue_Float: t = t_untyped_float; break; case ExactValue_Complex: t = t_untyped_complex; break; case ExactValue_Quaternion: t = t_untyped_quaternion; break; @@ -11109,6 +12299,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast o->mode = Addressing_Value; o->type = type; + o->value = exact_value_procedure(node); case_end; case_ast_node(te, TernaryIfExpr, node); @@ -11214,6 +12405,17 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast if (o->mode != Addressing_Invalid) { check_unary_expr(c, o, ue->op, node); + } else { + ERROR_BLOCK(); + gbString s = expr_to_string(ue->expr); + defer (gb_string_free(s)); + + error(node, "Cannot address value '%s' as it has not got a determined type yet", s); + + Entity *e = entity_of_node(ue->expr); + if (e != nullptr && e->kind == Entity_Variable) { + error_line("\tSuggestion: Add an explicit type to the declaration of '%.*s' rather than relying on type inference", LIT(e->token.string)); + } } o->expr = node; return Expr_Expr; @@ -11256,7 +12458,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast case_end; case_ast_node(ce, CallExpr, node); - return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, type_hint); + return check_call_expr(c, o, node, ce->proc, ce->args, ce->inlining, ce->tailing, type_hint); case_end; case_ast_node(de, DerefExpr, node); @@ -11264,6 +12466,13 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast node->viral_state_flags |= de->expr->viral_state_flags; if (o->mode == Addressing_Invalid) { + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } else if (o->mode == Addressing_Type) { + gbString str = expr_to_string(o->expr); + error(o->expr, "Cannot dereference '%s' because it is a type", str); + o->mode = Addressing_Invalid; o->expr = node; return kind; @@ -11351,6 +12560,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast case Ast_MultiPointerType: case Ast_ArrayType: case Ast_DynamicArrayType: + case Ast_FixedCapacityDynamicArrayType: case Ast_StructType: case Ast_UnionType: case Ast_EnumType: @@ -11428,6 +12638,10 @@ gb_internal void check_multi_expr_with_type_hint(CheckerContext *c, Operand *o, error_operand_no_value(o); break; case Addressing_Type: + if (type_hint != nullptr && is_type_typeid(type_hint)) { + add_type_info_type(c, o->type); + return; + } error_operand_not_expression(o); break; } @@ -11469,6 +12683,8 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) { return !v.value_bool; case ExactValue_String: return v.value_string.len == 0; + case ExactValue_String16: + return v.value_string16.len == 0; case ExactValue_Integer: return big_int_is_zero(&v.value_integer); case ExactValue_Float: @@ -11518,6 +12734,25 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) { +gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, ExactValue y) { + ast_node(x_cl, CompoundLit, x.value_compound); + ast_node(y_cl, CompoundLit, y.value_compound); + + if (x_cl->elems.count != y_cl->elems.count) { + return false; + } + + bool test = op == Token_CmpEq; + + for (isize i = 0; i < x_cl->elems.count; i++) { + Ast *lhs = x_cl->elems[i]; + Ast *rhs = y_cl->elems[i]; + if (compare_exact_values(op, lhs->tav.value, rhs->tav.value) != test) { + return !test; + } + } + return test; +} @@ -11836,6 +13071,15 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan str = write_expr_to_string(str, at->elem, shorthand); case_end; + case_ast_node(at, FixedCapacityDynamicArrayType, node); + if (at->tag) { + str = write_expr_to_string(str, at->tag, false); + } + str = gb_string_appendc(str, "[dynamic; "); + str = write_expr_to_string(str, at->capacity, false); + str = gb_string_append_rune(str, ']'); + str = write_expr_to_string(str, at->elem, shorthand); + case_end; case_ast_node(at, DynamicArrayType, node); if (at->tag) { str = write_expr_to_string(str, at->tag, false); @@ -11969,6 +13213,12 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan case_end; case_ast_node(ce, CallExpr, node); + switch (ce->tailing) { + case ProcTailing_must_tail: + str = gb_string_appendc(str, "#must_tail "); + break; + } + switch (ce->inlining) { case ProcInlining_inline: str = gb_string_appendc(str, "#force_inline "); @@ -12036,8 +13286,10 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan str = write_expr_to_string(str, st->polymorphic_params, shorthand); str = gb_string_appendc(str, ") "); } - if (st->is_packed) str = gb_string_appendc(str, "#packed "); - if (st->is_raw_union) str = gb_string_appendc(str, "#raw_union "); + if (st->is_packed) str = gb_string_appendc(str, "#packed "); + if (st->is_raw_union) str = gb_string_appendc(str, "#raw_union "); + if (st->is_all_or_none) str = gb_string_appendc(str, "#all_or_none "); + if (st->is_simple) str = gb_string_appendc(str, "#simple "); if (st->align) { str = gb_string_appendc(str, "#align "); str = write_expr_to_string(str, st->align, shorthand); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1b44ff4d7..222222559 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -418,7 +418,7 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { -gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) { +gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs, String context_name) { if (rhs->mode == Addressing_Invalid) { return nullptr; } @@ -430,8 +430,6 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O Ast *node = unparen_expr(lhs->expr); - check_no_copy_assignment(*rhs, str_lit("assignment")); - // NOTE(bill): Ignore assignments to '_' if (is_blank_ident(node)) { check_assignment(ctx, rhs, nullptr, str_lit("assignment to '_' identifier")); @@ -486,7 +484,7 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O } if (ident_node != nullptr) { ast_node(i, Ident, ident_node); - e = scope_lookup(ctx->scope, i->token.string); + e = scope_lookup(ctx->scope, i->interned, i->hash); if (e != nullptr && e->kind == Entity_Variable) { used = (e->flags & EntityFlag_Used) != 0; // NOTE(bill): Make backup just in case } @@ -630,7 +628,7 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O ctx->bit_field_bit_size = lhs_e->Variable.bit_field_bit_size; } - check_assignment(ctx, rhs, assignment_type, str_lit("assignment")); + check_assignment(ctx, rhs, assignment_type, context_name); ctx->bit_field_bit_size = prev_bit_field_bit_size; @@ -790,12 +788,19 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, rw_mutex_lock(&scope->mutex); defer (rw_mutex_unlock(&scope->mutex)); - for (auto const &entry : scope->elements) { - String name = entry.key; - Entity *decl = entry.value; - if (!is_entity_exported(decl, true)) continue; + for (u32 i = 0; i < scope->elements.cap; i++) { + if (!scope->elements.slots[i].hash) { + continue; + } - Entity *found = scope_insert_with_name(ctx->scope, name, decl); + Entity *decl = scope->elements.slots[i].value; + if (!is_entity_exported(decl, true)) { + continue; + } + u32 hash = scope->elements.slots[i].hash; + auto interned = scope->elements.keys[i]; + + Entity *found = scope_insert_with_name(ctx->scope, interned, hash, decl); if (found != nullptr) { gbString expr_str = expr_to_string(expr); error(us->token, @@ -976,7 +981,14 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod Type *t = base_type(operand.type); switch (t->kind) { case Type_Basic: - if (is_type_string(t) && t->Basic.kind != Basic_cstring) { + if (is_type_string16(t) && t->Basic.kind != Basic_cstring) { + val0 = t_rune; + val1 = t_int; + inline_for_depth = exact_value_i64(operand.value.value_string.len); + if (unroll_count > 0) { + error(node, "#unroll(%lld) does not support strings", cast(long long)unroll_count); + } + } else if (is_type_string(t) && t->Basic.kind != Basic_cstring) { val0 = t_rune; val1 = t_int; inline_for_depth = exact_value_i64(operand.value.value_string.len); @@ -1013,16 +1025,31 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod inline_for_depth = exact_value_i64(unroll_count); } break; + case Type_FixedCapacityDynamicArray: + if (unroll_count > 0) { + val0 = t->FixedCapacityDynamicArray.elem; + val1 = t_int; + inline_for_depth = exact_value_i64(unroll_count); + } + break; } } if (val0 == nullptr) { + ERROR_BLOCK(); gbString s = expr_to_string(operand.expr); gbString t = type_to_string(operand.type); + defer (gb_string_free(s)); + defer (gb_string_free(t)); error(operand.expr, "Cannot iterate over '%s' of type '%s' in an '#unroll for' statement", s, t); - gb_string_free(t); - gb_string_free(s); - } else if (operand.mode != Addressing_Constant && unroll_count <= 0) { + + if (is_type_slice(operand.type) || is_type_dynamic_array(operand.type) || is_type_fixed_capacity_dynamic_array(operand.type)) { + error_line("\tSuggestion: An unroll count `#unroll(N)` must be specified with an array of a runtime-known length\n"); + } + + } else if (operand.mode != Addressing_Constant && ( + unroll_count <= 0 && + compare_exact_values(Token_CmpEq, inline_for_depth, exact_value_i64(0)))) { error(operand.expr, "An '#unroll for' expression must be known at compile time"); } } @@ -1046,7 +1073,7 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod Entity *found = nullptr; if (!is_blank_ident(str)) { - found = scope_lookup_current(ctx->scope, str); + found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash); } if (found == nullptr) { entity = alloc_entity_variable(ctx->scope, token, type, EntityState_Resolved); @@ -1103,8 +1130,8 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod } } - check_stmt(ctx, irs->body, mod_flags); - + u32 new_flags = mod_flags & ~Stmt_BreakAllowed & ~Stmt_ContinueAllowed; + check_stmt(ctx, irs->body, new_flags); } gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { @@ -1238,7 +1265,11 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs); - if (is_type_string(x.type)) { + if (is_type_string16(x.type)) { + // NOTE(bill): Force dependency for strings here + add_package_dependency(ctx, "runtime", "string16_le"); + add_package_dependency(ctx, "runtime", "string16_lt"); + } else if (is_type_string(x.type)) { // NOTE(bill): Force dependency for strings here add_package_dependency(ctx, "runtime", "string_le"); add_package_dependency(ctx, "runtime", "string_lt"); @@ -1265,6 +1296,7 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags } t = default_type(t); add_type_info_type(ctx, t); + add_type_to_seen_map(ctx, &seen, y); } else { convert_to_typed(ctx, &y, x.type); if (y.mode == Addressing_Invalid) { @@ -1444,6 +1476,14 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ return; } + if (switch_kind == TypeSwitch_Union) { + if (is_addressed) { + if (x.mode != Addressing_Variable && !is_type_pointer(x.type)) { + error(lhs->Ident.token, "The element variable '%.*s' cannot be made addressable", LIT(lhs->Ident.token.string)); + } + } + } + Ast *nil_seen = nullptr; TypeSet seen = {}; @@ -1593,6 +1633,20 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ error_line("\tSuggestion: Was '#partial switch' wanted?\n"); } } + + if (build_context.strict_style) { + Token stok = ss->token; + for_array(i, bs->stmts) { + Ast *stmt = bs->stmts[i]; + if (stmt->kind != Ast_CaseClause) { + continue; + } + Token ctok = stmt->CaseClause.token; + if (ctok.pos.column > stok.pos.column) { + error(ctok, "With '-strict-style', 'case' statements must share the same column as the 'switch' token"); + } + } + } } gb_internal void check_block_stmt_for_errors(CheckerContext *ctx, Ast *body) { @@ -1680,11 +1734,17 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) TEMPORARY_ALLOCATOR_GUARD(); - u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed; check_open_scope(ctx, node); check_label(ctx, rs->label, node); + Operand init = {}; + if (rs->init != nullptr) { + check_stmt(ctx, rs->init, mod_flags); + } + + u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed; + auto vals = array_make(temporary_allocator(), 0, 2); auto entities = array_make(temporary_allocator(), 0, 2); bool is_map = false; @@ -1699,6 +1759,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) bool is_range = false; bool is_possibly_addressable = true; isize max_val_count = 2; + if (is_ast_range(expr)) { ast_node(ie, BinaryExpr, expr); Operand x = {}; @@ -1758,7 +1819,16 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) switch (t->kind) { case Type_Basic: - if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { + if (t->Basic.kind == Basic_string16) { + is_possibly_addressable = false; + array_add(&vals, t_rune); + array_add(&vals, t_int); + if (is_reverse) { + add_package_dependency(ctx, "runtime", "string16_decode_last_rune"); + } else { + add_package_dependency(ctx, "runtime", "string16_decode_rune"); + } + } else if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { is_possibly_addressable = false; array_add(&vals, t_rune); array_add(&vals, t_int); @@ -1780,10 +1850,11 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) error(node, "Iteration over a bit_set of an enum is not allowed runtime type information (RTTI) has been disallowed"); } if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) { - String name = rs->vals[0]->Ident.token.string; - Entity *found = scope_lookup(ctx->scope, name); + AstIdent *ident = &rs->vals[0]->Ident; + Entity *found = scope_lookup(ctx->scope, ident->interned, ident->hash); if (found && are_types_identical(found->type, t->BitSet.elem)) { ERROR_BLOCK(); + String name = ident->token.string; gbString s = expr_to_string(expr); error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s); error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n"); @@ -1804,6 +1875,12 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) array_add(&vals, t_int); break; + case Type_FixedCapacityDynamicArray: + is_possibly_addressable = operand.mode == Addressing_Variable || is_ptr; + array_add(&vals, t->FixedCapacityDynamicArray.elem); + array_add(&vals, t_int); + break; + case Type_DynamicArray: is_possibly_addressable = true; array_add(&vals, t->DynamicArray.elem); @@ -1825,10 +1902,11 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) error(node, "#reverse for is not supported for map types, as maps are unordered"); } if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) { - String name = rs->vals[0]->Ident.token.string; - Entity *found = scope_lookup(ctx->scope, name); + AstIdent *ident = &rs->vals[0]->Ident; + Entity *found = scope_lookup(ctx->scope, ident->interned, ident->hash); if (found && are_types_identical(found->type, t->Map.key)) { ERROR_BLOCK(); + String name = ident->token.string; gbString s = expr_to_string(expr); error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s); error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n"); @@ -1848,7 +1926,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) error_line("\tMultiple return valued parameters in a range statement are limited to a minimum of 1 usable values with a trailing boolean for the conditional, got %td\n", count); break; } - enum : isize {MAXIMUM_COUNT = 100}; + enum : isize {MAXIMUM_COUNT = 20}; if (count > MAXIMUM_COUNT) { ERROR_BLOCK(); check_not_tuple(ctx, &operand); @@ -1864,7 +1942,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) break; } - max_val_count = count; + max_val_count = count-1; for (Entity *e : t->Tuple.variables) { array_add(&vals, e->type); @@ -1884,6 +1962,20 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) if (is_reverse) { error(node, "#reverse for is not supported for multiple return valued parameters"); } + + Ast *expr = unparen_expr(operand.expr); + if (expr->kind == Ast_CallExpr) { + Type *p = base_type(type_of_expr(expr->CallExpr.proc)); + if (p != nullptr && p->kind == Type_Proc) { + if (p->Proc.require_results) { + if (rs->vals.count < max_val_count) { + TokenPos start = ast_token(rs->vals[0]).pos; + TokenPos end = ast_end_pos(rs->vals[rs->vals.count-1]); + error_range(start, end, "Expected %td identifier%s, got %td", max_val_count, max_val_count == 1 ? "" : "s", rs->vals.count); + } + } + } + } } break; @@ -1931,7 +2023,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) } auto rhs = slice_from_array(vals); - auto lhs = slice_make(temporary_allocator(), rhs.count); + auto lhs = temporary_slice_make(rhs.count); slice_copy(&lhs, rs->vals); isize addressable_index = cast(isize)is_map; @@ -1955,7 +2047,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) Entity *found = nullptr; if (!is_blank_ident(str)) { - found = scope_lookup_current(ctx->scope, str); + found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash); } if (found == nullptr) { entity = alloc_entity_variable(ctx->scope, token, type, EntityState_Resolved); @@ -2049,7 +2141,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f Entity *found = nullptr; // NOTE(bill): Ignore assignments to '_' if (!is_blank_ident(str)) { - found = scope_lookup_current(ctx->scope, str); + found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash); new_name_count += 1; } if (found == nullptr) { @@ -2108,10 +2200,12 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f if (init_type == nullptr) { init_type = t_invalid; } else if (is_type_polymorphic(base_type(init_type))) { + /* DISABLED: This error seems too aggressive for instantiated generic types. gbString str = type_to_string(init_type); error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); gb_string_free(str); init_type = t_invalid; + */ } if (init_type == t_invalid && entity_count == 1 && (mod_flags & (Stmt_BreakAllowed|Stmt_FallthroughAllowed))) { Entity *e = entities[0]; @@ -2175,7 +2269,9 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f error(e->token, "'thread_local' variables cannot be declared within a defer statement"); } } - e->Variable.thread_local_model = ac.thread_local_model; + if (!build_context.no_thread_local) { + e->Variable.thread_local_model = ac.thread_local_model; + } } if (ac.is_static && ac.thread_local_model != "") { @@ -2402,7 +2498,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { isize lhs_count = as->lhs.count; if (lhs_count == 0) { - error(as->op, "Missing lhs in assignment statement"); + error(as->op, "Missing LHS in assignment statement"); return; } @@ -2435,7 +2531,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { if (lhs_to_ignore[i]) { continue; } - check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i]); + check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i], str_lit("assignment")); } if (lhs_count != rhs_count) { error(as->lhs[0], "Assignment count mismatch '%td' = '%td'", lhs_count, rhs_count); @@ -2445,11 +2541,11 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { // a += 1; // Single-sided Token op = as->op; if (as->lhs.count != 1 || as->rhs.count != 1) { - error(op, "Assignment operation '%.*s' requires single-valued expressions", LIT(op.string)); + error(op, "Assignment operator '%.*s' requires single-valued operands", LIT(op.string)); return; } if (!gb_is_between(op.kind, Token__AssignOpBegin+1, Token__AssignOpEnd-1)) { - error(op, "Unknown Assignment operation '%.*s'", LIT(op.string)); + error(op, "Unknown assignment operator '%.*s'", LIT(op.string)); return; } Operand lhs = {Addressing_Invalid}; @@ -2458,15 +2554,16 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { ast_node(be, BinaryExpr, binary_expr); be->op = op; be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add)); - // NOTE(bill): Only use the first one will be used + // NOTE(bill): Only use the first one will be used be->left = as->lhs[0]; be->right = as->rhs[0]; check_expr(ctx, &lhs, as->lhs[0]); check_binary_expr(ctx, &rhs, binary_expr, nullptr, true); if (rhs.mode != Addressing_Invalid) { - // NOTE(bill): Only use the first one will be used - check_assignment_variable(ctx, &lhs, &rhs); + be->op.string = substring(be->op.string, 0, be->op.string.len - 1); + rhs.expr = binary_expr; + check_assignment_variable(ctx, &lhs, &rhs, str_lit("assignment operation")); } } } @@ -2504,6 +2601,82 @@ gb_internal void check_if_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { check_close_scope(ctx); } +// NOTE(bill): This is very basic escape analysis +// This needs to be improved tremendously, and a lot of it done during the +// middle-end (or LLVM side) to improve checks and error messages +void check_unsafe_return(Operand const &o, Type *type, Ast *expr) { + auto const unsafe_return_error = [](Operand const &o, char const *msg, Type *extra_type=nullptr) { + gbString s = expr_to_string(o.expr); + if (extra_type) { + gbString t = type_to_string(extra_type); + error(o.expr, "It is unsafe to return %s ('%s') of type ('%s') from a procedure, as it uses the current stack frame's memory", msg, s, t); + gb_string_free(t); + } else { + error(o.expr, "It is unsafe to return %s ('%s') from a procedure, as it uses the current stack frame's memory", msg, s); + } + gb_string_free(s); + }; + + if (type == nullptr || expr == nullptr) { + return; + } + + if (expr->kind == Ast_CompoundLit && is_type_slice(type)) { + ast_node(cl, CompoundLit, expr); + if (cl->elems.count == 0) { + return; + } + unsafe_return_error(o, "a compound literal of a slice"); + } else if (expr->kind == Ast_UnaryExpr && expr->UnaryExpr.op.kind == Token_And) { + Ast *x = unparen_expr(expr->UnaryExpr.expr); + Entity *e = entity_of_node(x); + if (is_entity_local_variable(e)) { + unsafe_return_error(o, "the address of a local variable"); + } else if (x->kind == Ast_CompoundLit) { + unsafe_return_error(o, "the address of a compound literal"); + } else if (x->kind == Ast_IndexExpr) { + Entity *f = entity_of_node(x->IndexExpr.expr); + if (f && (is_type_array_like(f->type) || is_type_matrix(f->type))) { + if (is_entity_local_variable(f)) { + unsafe_return_error(o, "the address of an indexed variable", f->type); + } + } + } else if (x->kind == Ast_MatrixIndexExpr) { + Entity *f = entity_of_node(x->MatrixIndexExpr.expr); + if (f && (is_type_matrix(f->type) && is_entity_local_variable(f))) { + unsafe_return_error(o, "the address of an indexed variable", f->type); + } + } + } else if (expr->kind == Ast_SliceExpr) { + Ast *x = unparen_expr(expr->SliceExpr.expr); + Entity *e = entity_of_node(x); + if (is_entity_local_variable(e) && is_type_array(e->type)) { + unsafe_return_error(o, "a slice of a local variable"); + } else if (x->kind == Ast_CompoundLit) { + unsafe_return_error(o, "a slice of a compound literal"); + } + } else if (o.mode == Addressing_Constant && is_type_slice(type)) { + if (is_load_directive_call(o.expr)) { + return; + } + + ERROR_BLOCK(); + unsafe_return_error(o, "a compound literal of a slice"); + error_line("\tNote: A constant slice value will use the memory of the current stack frame\n"); + } else if (expr->kind == Ast_CompoundLit) { + ast_node(cl, CompoundLit, expr); + for (Ast *elem : cl->elems) { + if (elem->kind == Ast_FieldValue) { + ast_node(fv, FieldValue, elem); + Entity *e = entity_of_node(fv->field); + if (e != nullptr) { + check_unsafe_return(o, e->type, fv->value); + } + } + } + } +} + gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) { ast_node(rs, ReturnStmt, node); @@ -2532,8 +2705,9 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) { result_count = proc_type->Proc.results->Tuple.variables.count; } - auto operands = array_make(heap_allocator(), 0, 2*rs->results.count); - defer (array_free(&operands)); + TEMPORARY_ALLOCATOR_GUARD(); + + auto operands = array_make(temporary_allocator(), 0, 2*rs->results.count); check_unpack_arguments(ctx, result_entities, result_count, &operands, rs->results, UnpackFlag_AllowOk); @@ -2579,61 +2753,7 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) { expr = unparen_expr(arg); } - auto unsafe_return_error = [](Operand const &o, char const *msg, Type *extra_type=nullptr) { - gbString s = expr_to_string(o.expr); - if (extra_type) { - gbString t = type_to_string(extra_type); - error(o.expr, "It is unsafe to return %s ('%s') of type ('%s') from a procedure, as it uses the current stack frame's memory", msg, s, t); - gb_string_free(t); - } else { - error(o.expr, "It is unsafe to return %s ('%s') from a procedure, as it uses the current stack frame's memory", msg, s); - } - gb_string_free(s); - }; - - - // NOTE(bill): This is very basic escape analysis - // This needs to be improved tremendously, and a lot of it done during the - // middle-end (or LLVM side) to improve checks and error messages - if (expr->kind == Ast_CompoundLit && is_type_slice(o.type)) { - ast_node(cl, CompoundLit, expr); - if (cl->elems.count == 0) { - continue; - } - unsafe_return_error(o, "a compound literal of a slice"); - } else if (expr->kind == Ast_UnaryExpr && expr->UnaryExpr.op.kind == Token_And) { - Ast *x = unparen_expr(expr->UnaryExpr.expr); - Entity *e = entity_of_node(x); - if (is_entity_local_variable(e)) { - unsafe_return_error(o, "the address of a local variable"); - } else if (x->kind == Ast_CompoundLit) { - unsafe_return_error(o, "the address of a compound literal"); - } else if (x->kind == Ast_IndexExpr) { - Entity *f = entity_of_node(x->IndexExpr.expr); - if (f && (is_type_array_like(f->type) || is_type_matrix(f->type))) { - if (is_entity_local_variable(f)) { - unsafe_return_error(o, "the address of an indexed variable", f->type); - } - } - } else if (x->kind == Ast_MatrixIndexExpr) { - Entity *f = entity_of_node(x->MatrixIndexExpr.expr); - if (f && (is_type_matrix(f->type) && is_entity_local_variable(f))) { - unsafe_return_error(o, "the address of an indexed variable", f->type); - } - } - } else if (expr->kind == Ast_SliceExpr) { - Ast *x = unparen_expr(expr->SliceExpr.expr); - Entity *e = entity_of_node(x); - if (is_entity_local_variable(e) && is_type_array(e->type)) { - unsafe_return_error(o, "a slice of a local variable"); - } else if (x->kind == Ast_CompoundLit) { - unsafe_return_error(o, "a slice of a compound literal"); - } - } else if (o.mode == Addressing_Constant && is_type_slice(o.type)) { - ERROR_BLOCK(); - unsafe_return_error(o, "a compound literal of a slice"); - error_line("\tNote: A constant slice value will use the memory of the current stack frame\n"); - } + check_unsafe_return(o, o.type, expr); } } @@ -2761,6 +2881,10 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) Ast *stmt = ds->stmt; Ast *original_stmt = stmt; + if (stmt->kind == Ast_BlockStmt && stmt->BlockStmt.stmts.count == 0) { + break; // empty defer statement + } + bool is_singular = true; while (is_singular && stmt->kind == Ast_BlockStmt) { Ast *inner_stmt = nullptr; @@ -2853,6 +2977,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) case Ast_BlockStmt: case Ast_IfStmt: case Ast_SwitchStmt: + case Ast_TypeSwitchStmt: if (token.kind != Token_break) { error(bs->label, "Label '%.*s' can only be used with 'break'", LIT(e->token.string)); } @@ -2878,10 +3003,12 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) error(us->token, "Empty 'using' list"); return; } - if (check_vet_flags(node) & VetFlag_UsingStmt) { + + u64 feature_flags = check_feature_flags(ctx, node); + if ((feature_flags & OptInFeatureFlag_UsingStmt) == 0) { ERROR_BLOCK(); - error(node, "'using' as a statement is not allowed when '-vet' or '-vet-using' is applied"); - error_line("\t'using' is considered bad practice to use as a statement outside of immediate refactoring\n"); + error(node, "'using' has been disallowed as it is considered bad practice to use as a statement outside of immediate refactoring"); + error_line("\tIf you do require it for refactoring purposes or legacy code, it can be enabled on a per-file basis with '#+feature using-stmt'\n"); } for (Ast *expr : us->list) { diff --git a/src/check_type.cpp b/src/check_type.cpp index 452da4023..212f7dbe4 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1,11 +1,14 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_type, Type **out_type_, Ast *expr, bool allow_caller_location); gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Operand const &operand); gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array const *operands); +gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field, Type *t, isize level); gb_internal void populate_using_array_index(CheckerContext *ctx, Ast *node, AstField *field, Type *t, String name, i32 idx) { t = base_type(t); GB_ASSERT(t->kind == Type_Array); - Entity *e = scope_lookup_current(ctx->scope, name); + InternedString interned = string_interner_insert(name); + + Entity *e = scope_lookup_current(ctx->scope, interned); if (e != nullptr) { gbString str = nullptr; defer (gb_string_free(str)); @@ -31,38 +34,44 @@ gb_internal void populate_using_array_index(CheckerContext *ctx, Ast *node, AstF } } +gb_internal void populate_using_entity_scope_field(CheckerContext *ctx, Ast *node, AstField *parent_field, Type *original_type, isize level, Entity* field_entity) { + GB_ASSERT(field_entity->kind == Entity_Variable); + String name = field_entity->token.string; + InternedString interned = entity_interned_name(field_entity); + Entity *e = scope_lookup_current(ctx->scope, interned); + if (e != nullptr && name != "_") { + gbString ot = type_to_string(original_type); + // TODO(bill): Better type error + if (node != nullptr) { + gbString str = expr_to_string(node); + error(e->token, "'%.*s' is already declared in '%s', through 'using' from '%s'", LIT(name), str, ot); + gb_string_free(str); + } else { + error(e->token, "'%.*s' is already declared, through 'using' from '%s'", LIT(name), ot); + } + gb_string_free(ot); + } else { + add_entity(ctx, ctx->scope, nullptr, field_entity); + if (field_entity->flags & EntityFlag_Using) { + populate_using_entity_scope(ctx, node, parent_field, field_entity->type, level+1); + } + } +} + gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field, Type *t, isize level) { if (t == nullptr) { return; } Type *original_type = t; t = base_type(type_deref(t)); - gbString str = nullptr; - defer (gb_string_free(str)); - if (node != nullptr) { - str = expr_to_string(node); - } if (t->kind == Type_Struct) { for (Entity *f : t->Struct.fields) { - GB_ASSERT(f->kind == Entity_Variable); - String name = f->token.string; - Entity *e = scope_lookup_current(ctx->scope, name); - if (e != nullptr && name != "_") { - gbString ot = type_to_string(original_type); - // TODO(bill): Better type error - if (str != nullptr) { - error(e->token, "'%.*s' is already declared in '%s', through 'using' from '%s'", LIT(name), str, ot); - } else { - error(e->token, "'%.*s' is already declared, through 'using' from '%s'", LIT(name), ot); - } - gb_string_free(ot); - } else { - add_entity(ctx, ctx->scope, nullptr, f); - if (f->flags & EntityFlag_Using) { - populate_using_entity_scope(ctx, node, field, f->type, level+1); - } - } + populate_using_entity_scope_field(ctx, node, field, original_type, level, f); + } + } else if (t->kind == Type_BitField) { + for (Entity *f : t->BitField.fields) { + populate_using_entity_scope_field(ctx, node, field, original_type, level, f); } } else if (t->kind == Type_Array && t->Array.count <= 4) { switch (t->Array.count) { @@ -102,9 +111,6 @@ gb_internal bool does_field_type_allow_using(Type *t) { gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slice *fields, String **tags, Slice const ¶ms, isize init_field_capacity, Type *struct_type, String context) { - auto fields_array = array_make(heap_allocator(), 0, init_field_capacity); - auto tags_array = array_make(heap_allocator(), 0, init_field_capacity); - GB_ASSERT(node->kind == Ast_StructType); GB_ASSERT(struct_type->kind == Type_Struct); @@ -117,9 +123,21 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slice(permanent_allocator(), 0, init_field_capacity); + auto tags_array = array_make(permanent_allocator(), 0, init_field_capacity); + + defer (GB_ASSERT(fields_array.count == init_field_capacity)); + + // Allocate all at once + Entity *entities_to_use = permanent_alloc_array(variable_count); + isize entities_to_use_index = 0; + i32 field_src_index = 0; i32 field_group_index = -1; for_array(i, params) { + *fields = slice_from_array(fields_array); + *tags = tags_array.data; Ast *param = params[i]; if (param->kind != Ast_Field) { continue; @@ -165,7 +183,17 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, SliceIdent.token; - Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index); + // Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index); + Entity *field = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(field, Entity_Variable, ctx->scope, name_token, type); + + field->interned_name.store(name->Ident.interned); + field->interned_name_hash.store(name->Ident.hash); + + field->flags |= EntityFlag_Field; + if (is_using) field->flags |= EntityFlag_Using; + field->Variable.field_index = field_src_index; + add_entity(ctx, ctx->scope, name, field); field->Variable.field_group_index = field_group_index; if (is_subtype) { @@ -267,28 +295,39 @@ gb_internal bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_, gb_internal GenTypesData *ensure_polymorphic_record_entity_has_gen_types(CheckerContext *ctx, Type *original_type) { - mutex_lock(&ctx->info->gen_types_mutex); // @@global - GenTypesData *found_gen_types = nullptr; - auto *found_gen_types_ptr = map_get(&ctx->info->gen_types, original_type); - if (found_gen_types_ptr == nullptr) { - GenTypesData *gen_types = gb_alloc_item(permanent_allocator(), GenTypesData); + + GB_ASSERT(original_type->kind == Type_Named); + mutex_lock(&original_type->Named.gen_types_data_mutex); + if (original_type->Named.gen_types_data == nullptr) { + GenTypesData *gen_types = permanent_alloc_item(); gen_types->types = array_make(heap_allocator()); - map_set(&ctx->info->gen_types, original_type, gen_types); - found_gen_types_ptr = map_get(&ctx->info->gen_types, original_type); + original_type->Named.gen_types_data = gen_types; } - found_gen_types = *found_gen_types_ptr; - GB_ASSERT(found_gen_types != nullptr); - mutex_unlock(&ctx->info->gen_types_mutex); // @@global + found_gen_types = original_type->Named.gen_types_data; + + mutex_unlock(&original_type->Named.gen_types_data_mutex); + return found_gen_types; } gb_internal void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_type, Type *original_type) { GB_ASSERT(is_type_named(named_type)); + GB_ASSERT(original_type->kind == Type_Named); gbAllocator a = heap_allocator(); Scope *s = ctx->scope->parent; + AstPackage *pkg = nullptr; + if (original_type->Named.type_name && original_type->Named.type_name->pkg) { + pkg = original_type->Named.type_name->pkg; + } + + if (pkg == nullptr) { + // NOTE(bill): if the `pkg` cannot be determined, default to the current context's pkg instead + pkg = ctx->pkg; + } + Entity *e = nullptr; { Token token = ast_token(node); @@ -300,12 +339,12 @@ gb_internal void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, T e = alloc_entity_type_name(s, token, named_type); e->state = EntityState_Resolved; e->file = ctx->file; - e->pkg = ctx->pkg; + e->pkg = pkg; + e->TypeName.original_type_for_parapoly = original_type; add_entity_use(ctx, node, e); } named_type->Named.type_name = e; - GB_ASSERT(original_type->kind == Type_Named); e->TypeName.objc_class_name = original_type->Named.type_name->TypeName.objc_class_name; // TODO(bill): Is this even correct? Or should the metadata be copied? e->TypeName.objc_metadata = original_type->Named.type_name->TypeName.objc_metadata; @@ -401,7 +440,7 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly Ast *s = type_expr->TypeidType.specialization; specialization = check_type(ctx, s); } - type = alloc_type_generic(ctx->scope, 0, str_lit(""), specialization); + type = alloc_type_generic(ctx->scope, 0, string_interner_insert(str_lit("")), specialization); } else { type = check_type(ctx, type_expr); if (is_type_polymorphic(type)) { @@ -625,7 +664,7 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * isize min_field_count = 0; for_array(field_index, st->fields) { - Ast *field = st->fields[field_index]; + Ast *field = st->fields[field_index]; switch (field->kind) { case_ast_node(f, ValueDecl, field); min_field_count += f->names.count; @@ -643,10 +682,10 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * context = str_lit("struct #raw_union"); } - struct_type->Struct.node = node; - struct_type->Struct.scope = ctx->scope; - struct_type->Struct.is_packed = st->is_packed; - struct_type->Struct.is_no_copy = st->is_no_copy; + struct_type->Struct.node = node; + struct_type->Struct.scope = ctx->scope; + struct_type->Struct.is_packed = st->is_packed; + struct_type->Struct.is_all_or_none = st->is_all_or_none; struct_type->Struct.polymorphic_params = check_record_polymorphic_params( ctx, st->polymorphic_params, &struct_type->Struct.is_polymorphic, @@ -668,6 +707,21 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * gb_unused(where_clause_ok); } check_struct_fields(ctx, node, &struct_type->Struct.fields, &struct_type->Struct.tags, st->fields, min_field_count, struct_type, context); + + if (st->is_simple) { + bool success = true; + for (Entity *f : struct_type->Struct.fields) { + if (!is_type_nearly_simple_compare(f->type)) { + gbString s = type_to_string(f->type); + error(f->token, "'struct #simple' requires all fields to be at least 'nearly simple compare', got %s", s); + gb_string_free(s); + } + } + if (success) { + struct_type->Struct.is_simple = true; + } + } + wait_signal_set(&struct_type->Struct.fields_wait_signal); } @@ -753,11 +807,19 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no if (t != nullptr && t != t_invalid) { bool ok = true; t = default_type(t); - if (is_type_untyped(t) || is_type_empty_union(t)) { + if (is_type_untyped(t)) { ok = false; gbString str = type_to_string(t); error(node, "Invalid variant type in union '%s'", str); gb_string_free(str); + } else if (is_type_empty_union(t)) { + Type *base = base_type(t); + if (base == nullptr || base->kind != Type_Union || base->Union.node == nullptr) { + ok = false; + gbString str = type_to_string(t); + error(node, "Invalid variant type in union '%s'", str); + gb_string_free(str); + } } else { for_array(j, variants) { if (union_variant_index_types_equal(t, variants[j])) { @@ -861,6 +923,10 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam scope_reserve(ctx->scope, et->fields.count); + // Allocate all at once + Entity *entities_to_use = permanent_alloc_array(et->fields.count); + isize entities_to_use_index = 0; + for_array(i, et->fields) { Ast *field = et->fields[i]; Ast *ident = nullptr; @@ -905,9 +971,6 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam // NOTE(bill): Skip blank identifiers if (is_blank_ident(name)) { continue; - } else if (name == "names") { - error(field, "'names' is a reserved identifier for enumerations"); - continue; } if (min_value_set) { @@ -931,7 +994,15 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam max_value_set = true; } - Entity *e = alloc_entity_constant(ctx->scope, ident->Ident.token, constant_type, iota); + // Entity *e = alloc_entity_constant(ctx->scope, ident->Ident.token, constant_type, iota); + Entity *e = &entities_to_use[entities_to_use_index++]; + Token token = ident->Ident.token; + INTERNAL_ENTITY_INIT(e, Entity_Constant, ctx->scope, token, constant_type); + + e->interned_name.store(ident->Ident.interned); + e->interned_name_hash.store(ident->Ident.hash); + + e->Constant.value = iota; e->identifier = ident; e->flags |= EntityFlag_Visited; e->state = EntityState_Resolved; @@ -939,7 +1010,9 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam e->Constant.docs = docs; e->Constant.comment = comment; - if (scope_lookup_current(ctx->scope, name) != nullptr) { + auto interned = entity_interned_name(e); + + if (scope_lookup_current(ctx->scope, interned) != nullptr) { error(ident, "'%.*s' is already declared in this enumeration", LIT(name)); } else { add_entity(ctx, ctx->scope, nullptr, e); @@ -1001,6 +1074,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, CommentGroup *comment = f->comment; String name = f->name->Ident.token.string; + InternedString interned = f->name->Ident.interned; if (f->type == nullptr) { error(field, "A bit_field's field must have a type"); @@ -1051,7 +1125,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, gb_string_free(s); } - if (scope_lookup_current(ctx->scope, name) != nullptr) { + if (scope_lookup_current(ctx->scope, interned) != nullptr) { error(f->name, "'%.*s' is already declared in this bit_field", LIT(name)); } else { i64 bit_size_i64 = exact_value_to_i64(bit_size); @@ -1097,7 +1171,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, GB_ASSERT(fields.count <= bf->fields.count); - auto bit_offsets = slice_make(permanent_allocator(), fields.count); + auto bit_offsets = permanent_slice_make(fields.count); i64 curr_offset = 0; for_array(i, bit_sizes) { bit_offsets[i] = curr_offset; @@ -1203,6 +1277,7 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t ast_node(bs, BitSetType, node); GB_ASSERT(type->kind == Type_BitSet); type->BitSet.node = node; + type->BitSet.elem = t_invalid; /* i64 const DEFAULT_BITS = cast(i64)(8*build_context.word_size); */ i64 const MAX_BITS = 128; @@ -1425,6 +1500,68 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t } +// If `specialization` is a polymorphic-record specialization that has been published into +// its originating record's `gen_types` cache, return that cache's `GenTypesData`. Its +// `RecursiveMutex` guards concurrent `find_polymorphic_record_entity` reads, so the +// in-place finalization below must hold it. Returns nullptr otherwise. +gb_internal GenTypesData *gen_types_data_of_specialization(Type *specialization) { + if (specialization != nullptr && + specialization->kind == Type_Named && + specialization->Named.type_name != nullptr) { + Type *orig = specialization->Named.type_name->TypeName.original_type_for_parapoly; + if (orig != nullptr && orig->kind == Type_Named) { + return orig->Named.gen_types_data; + } + } + return nullptr; +} + +gb_internal bool check_type_specialization_to_internal(CheckerContext *ctx, Type *specialization, Type *type, TypeTuple *s_tuple, TypeTuple *t_tuple, bool modify_type) { + GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); + for_array(i, s_tuple->variables) { + Entity *s_e = s_tuple->variables[i]; + Entity *t_e = t_tuple->variables[i]; + Type *st = s_e->type; + Type *tt = t_e->type; + + // NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types + if (st->kind == Type_Generic && t_e->kind == Entity_Constant) { + Entity *e = scope_lookup(st->Generic.scope, st->Generic.interned_name, 0); + GB_ASSERT(e != nullptr); + if (modify_type) { + e->kind = Entity_Constant; + e->Constant.value = t_e->Constant.value; + e->type = t_e->type; + } + } else { + if (st->kind == Type_Basic && tt->kind == Type_Basic && + s_e->kind == Entity_Constant && t_e->kind == Entity_Constant) { + if (!compare_exact_values(Token_CmpEq, s_e->Constant.value, t_e->Constant.value)) + return false; + } else { + bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type); + if (!ok) { + // TODO(bill, 2021-08-19): is this logic correct? + return false; + } + } + } + } + + if (modify_type) { + // NOTE(bill): This is needed in order to change the actual type but still have the types defined within it. + // `specialization` may already be published in a polymorphic record's gen_types cache; + // finalize it under that record's (recursive) gen_types mutex so a concurrent + // find_polymorphic_record_entity on another thread cannot observe a torn Type. + GenTypesData *gen_types = gen_types_data_of_specialization(specialization); + if (gen_types != nullptr) mutex_lock(&gen_types->mutex); + gb_memmove(specialization, type, gb_size_of(Type)); + if (gen_types != nullptr) mutex_unlock(&gen_types->mutex); + } + + return true; +} + gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *specialization, Type *type, bool compound, bool modify_type) { if (type == nullptr || type == t_invalid) { @@ -1461,43 +1598,7 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special TypeTuple *s_tuple = get_record_polymorphic_params(s); TypeTuple *t_tuple = get_record_polymorphic_params(t); - GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); - for_array(i, s_tuple->variables) { - Entity *s_e = s_tuple->variables[i]; - Entity *t_e = t_tuple->variables[i]; - Type *st = s_e->type; - Type *tt = t_e->type; - - // NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types - if (st->kind == Type_Generic && t_e->kind == Entity_Constant) { - Entity *e = scope_lookup(st->Generic.scope, st->Generic.name); - GB_ASSERT(e != nullptr); - if (modify_type) { - e->kind = Entity_Constant; - e->Constant.value = t_e->Constant.value; - e->type = t_e->type; - } - } else { - if (st->kind == Type_Basic && tt->kind == Type_Basic && - s_e->kind == Entity_Constant && t_e->kind == Entity_Constant) { - if (!compare_exact_values(Token_CmpEq, s_e->Constant.value, t_e->Constant.value)) - return false; - } else { - bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type); - if (!ok) { - // TODO(bill, 2021-08-19): is this logic correct? - return false; - } - } - } - } - - if (modify_type) { - // NOTE(bill): This is needed in order to change the actual type but still have the types defined within it - gb_memmove(specialization, type, gb_size_of(Type)); - } - - return true; + return check_type_specialization_to_internal(ctx, specialization, type, s_tuple, t_tuple, modify_type); } } else if (t->kind == Type_Union) { if (t->Union.polymorphic_parent == nullptr && @@ -1514,37 +1615,7 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special TypeTuple *s_tuple = get_record_polymorphic_params(s); TypeTuple *t_tuple = get_record_polymorphic_params(t); - GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); - for_array(i, s_tuple->variables) { - Entity *s_e = s_tuple->variables[i]; - Entity *t_e = t_tuple->variables[i]; - Type *st = s_e->type; - Type *tt = t_e->type; - - // NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types - if (st->kind == Type_Generic && t_e->kind == Entity_Constant) { - Entity *e = scope_lookup(st->Generic.scope, st->Generic.name); - GB_ASSERT(e != nullptr); - if (modify_type) { - e->kind = Entity_Constant; - e->Constant.value = t_e->Constant.value; - e->type = t_e->type; - } - } else { - bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type); - if (!ok) { - // TODO(bill, 2021-08-19): is this logic correct? - return false; - } - } - } - - if (modify_type) { - // NOTE(bill): This is needed in order to change the actual type but still have the types defined within it - gb_memmove(specialization, type, gb_size_of(Type)); - } - - return true; + return check_type_specialization_to_internal(ctx, specialization, type, s_tuple, t_tuple, modify_type); } } @@ -1565,11 +1636,18 @@ gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *pol bool show_error = modify_type && !ctx->hide_polymorphic_errors; if (!is_operand_value(operand)) { if (show_error) { + ERROR_BLOCK(); + gbString pts = type_to_string(poly_type); gbString ots = type_to_string(operand.type, true); defer (gb_string_free(pts)); defer (gb_string_free(ots)); error(operand.expr, "Cannot determine polymorphic type from parameter: '%s' to '%s'", ots, pts); + + if (operand.mode == Addressing_Type) { + error_line("\tSuggestion: Are you trying to pass a type to a value parameter?\n"); + } + } return t_invalid; } @@ -1601,6 +1679,12 @@ gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *pol error_line("\tSuggestion: Try slicing the value with '%s[:]'\n", os); gb_string_free(os); } + } else if (is_type_pointer(poly_type)) { + if (is_polymorphic_type_assignable(ctx, type_deref(poly_type), operand.type, /*compound*/false, /*modify_type*/false)) { + gbString os = expr_to_string(operand.expr); + error_line("\tSuggestion: Did you mean '&%s'?\n", os); + gb_string_free(os); + } } } return t_invalid; @@ -1617,6 +1701,8 @@ gb_internal bool is_expr_from_a_parameter(CheckerContext *ctx, Ast *expr) { } else if (expr->kind == Ast_Ident) { Operand x= {}; Entity *e = check_ident(ctx, &x, expr, nullptr, nullptr, true); + GB_ASSERT(e != nullptr); + if (e->flags & EntityFlag_Param) { return true; } @@ -1793,6 +1879,11 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para bool is_c_vararg = false; auto variables = array_make(permanent_allocator(), 0, variable_count); i32 field_group_index = -1; + + + Entity *entities_to_use = permanent_alloc_array(variable_count); + isize entities_to_use_index = 0; + for_array(i, params) { Ast *param = params[i]; if (param->kind != Ast_Field) { @@ -1811,11 +1902,14 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para Type *specialization = nullptr; bool is_using = (p->flags&FieldFlag_using) != 0; - if ((check_vet_flags(param) & VetFlag_UsingParam) && is_using) { - ERROR_BLOCK(); - error(param, "'using' on a procedure parameter is not allowed when '-vet' or '-vet-using-param' is applied"); - error_line("\t'using' is considered bad practice to use as a statement/procedure parameter outside of immediate refactoring\n"); + + u64 feature_flags = check_feature_flags(ctx, param); + + if (is_using && (feature_flags & OptInFeatureFlag_UsingStmt) == 0) { + ERROR_BLOCK(); + error(param, "'using' has been disallowed as it is considered bad practice to use as a statement/procedure parameter outside of immediate refactoring"); + error_line("\tIf you do require it for refactoring purposes or legacy code, it can be enabled on a per-file basis with '#+feature using-stmt'\n"); } if (type_expr == nullptr) { @@ -1851,7 +1945,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para detemine_type_from_operand = true; type = t_invalid; } else { - type = alloc_type_generic(ctx->scope, 0, str_lit(""), specialization); + type = alloc_type_generic(ctx->scope, 0, string_interner_insert(str_lit("")), specialization); } } else { type = t_typeid; @@ -1910,9 +2004,18 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para case ParameterValue_Location: case ParameterValue_Expression: case ParameterValue_Value: + // Special case for polymorphic procedures as default values + if (param_value.ast_value != nullptr) { + Entity *e = entity_from_expr(param_value.ast_value); + if (e != nullptr && e->kind == Entity_Procedure && is_type_polymorphic(e->type)) { + // Allow polymorphic procedures as default parameter values + // The type will be correctly determined at call site + break; + } + } gbString str = type_to_string(type); error(params[i], "A default value for a parameter must not be a polymorphic constant type, got %s", str); - gb_string_free(str); + gb_string_free(str); break; } } @@ -2020,7 +2123,12 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para p->flags &= ~FieldFlag_no_capture; } - param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved); + param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_TypeName, scope, name->Ident.token, type); + param->state = EntityState_Resolved; + param->interned_name.store(name->Ident.interned); + param->interned_name_hash.store(name->Ident.hash); + param->TypeName.is_type_alias = true; } else { ExactValue poly_const = {}; @@ -2067,7 +2175,9 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para if (op.mode == Addressing_Constant) { poly_const = op.value; } else { - error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr)); + if (!ctx->in_proc_group) { + error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr)); + } success = false; } } @@ -2172,10 +2282,36 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para // failed } - param = alloc_entity_const_param(scope, name->Ident.token, type, poly_const, is_type_polymorphic(type)); + // param = alloc_entity_const_param(scope, name->Ident.token, type, poly_const, is_type_polymorphic(type)); + + param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Constant, scope, name->Ident.token, type); + + param->flags |= EntityFlag_Used|EntityFlag_Param; + if (is_type_polymorphic(type)) { + param->flags |= EntityFlag_PolyConst; + } + param->Constant.value = poly_const; + + param->interned_name.store(name->Ident.interned); + param->interned_name_hash.store(name->Ident.hash); + param->Constant.field_group_index = field_group_index; } else { - param = alloc_entity_param(scope, name->Ident.token, type, is_using, true); + // param = alloc_entity_param(scope, name->Ident.token, type, is_using, true); + + param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, name->Ident.token, type); + + param->state = EntityState_Resolved; + param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Value; + if (is_using) { + param->flags |= EntityFlag_Using; + } + + param->interned_name.store(name->Ident.interned); + param->interned_name_hash.store(name->Ident.hash); + param->Variable.param_value = param_value; param->Variable.field_group_index = field_group_index; param->Variable.type_expr = type_expr; @@ -2257,6 +2393,56 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para return tuple; } +// Check if an AST node references any polymorphic type parameters +// TODO(bill): is this even complete enough? +gb_internal bool ast_references_poly_params(Scope *scope, Ast *node) { + if (node == nullptr) { + return false; + } + switch (node->kind) { + case Ast_Ident: { + Entity *e = scope_lookup(scope, node->Ident.interned, node->Ident.hash); + if (e != nullptr && e->kind == Entity_TypeName && e->type != nullptr && e->type->kind == Type_Generic) { + return true; + } + return false; + } + case Ast_SelectorExpr: + return ast_references_poly_params(scope, node->SelectorExpr.expr); + case Ast_IndexExpr: + return ast_references_poly_params(scope, node->IndexExpr.expr); + case Ast_CallExpr: + for (Ast *arg : node->CallExpr.args) { + if (ast_references_poly_params(scope, arg)) { + return true; + } + } + return ast_references_poly_params(scope, node->CallExpr.proc); + case Ast_CompoundLit: + return ast_references_poly_params(scope, node->CompoundLit.type); + case Ast_UnaryExpr: + return ast_references_poly_params(scope, node->UnaryExpr.expr); + case Ast_ParenExpr: + return ast_references_poly_params(scope, node->ParenExpr.expr); + case Ast_DerefExpr: + return ast_references_poly_params(scope, node->DerefExpr.expr); + case Ast_PointerType: + return ast_references_poly_params(scope, node->PointerType.type); + case Ast_ArrayType: + return ast_references_poly_params(scope, node->ArrayType.elem) || + ast_references_poly_params(scope, node->ArrayType.count); + case Ast_FixedCapacityDynamicArrayType: + return ast_references_poly_params(scope, node->FixedCapacityDynamicArrayType.elem) || + ast_references_poly_params(scope, node->FixedCapacityDynamicArrayType.capacity); + case Ast_DynamicArrayType: + return ast_references_poly_params(scope, node->DynamicArrayType.elem); + case Ast_MapType: + return ast_references_poly_params(scope, node->MapType.key) || + ast_references_poly_params(scope, node->MapType.value); + } + return false; +} + gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { if (_results == nullptr) { return nullptr; @@ -2278,6 +2464,9 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res } } + Entity *entities_to_use = permanent_alloc_array(variable_count); + isize entities_to_use_index = 0; + auto variables = array_make(permanent_allocator(), 0, variable_count); i32 field_group_index = -1; for_array(i, results) { @@ -2291,7 +2480,14 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res if (field->type == nullptr) { param_value = handle_parameter_value(ctx, nullptr, &type, default_value, false); } else { - type = check_type(ctx, field->type); + if (ctx->allow_polymorphic_types && ast_references_poly_params(ctx->scope, field->type)) { + gbString name = expr_to_string(field->type); + type = alloc_type_generic(ctx->scope, 0, string_interner_insert(make_string_c(name)), nullptr); + gb_string_free(name); + } else { + type = check_type(ctx, field->type); + } + if (default_value != nullptr) { param_value = handle_parameter_value(ctx, type, nullptr, default_value, false); @@ -2311,7 +2507,12 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res if (field->names.count == 0) { Token token = ast_token(field->type); token.string = str_lit(""); - Entity *param = alloc_entity_param(scope, token, type, false, false); + // Entity *param = alloc_entity_param(scope, token, type, false, false); + Entity *param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type); + param->state = EntityState_Resolved; + param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result; + param->Variable.param_value = param_value; param->Variable.field_group_index = -1; array_add(&variables, param); @@ -2334,8 +2535,17 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res error(name, "Result value cannot be a blank identifer `_`"); } - Entity *param = alloc_entity_param(scope, token, type, false, false); - param->flags |= EntityFlag_Result; + // Entity *param = alloc_entity_param(scope, token, type, false, false); + Entity *param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type); + param->state = EntityState_Resolved; + param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result; + + if (name->kind == Ast_Ident) { + param->interned_name.store(name->Ident.interned); + param->interned_name_hash.store(name->Ident.hash); + } + param->Variable.param_value = param_value; param->Variable.field_group_index = field_group_index; array_add(&variables, param); @@ -2637,6 +2847,12 @@ gb_internal i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) { error(e, "Array count too large, %.*s", LIT(str)); gb_free(a, str.text); return 0; + } else if (o->value.kind == ExactValue_Float) { + u64 u = cast(u64)o->value.value_float; + f64 f = cast(f64)u; + if (f == o->value.value_float) { + return u; + } } } @@ -2687,7 +2903,7 @@ gb_internal Type *get_map_cell_type(Type *type) { // Padding exists Type *s = alloc_type_struct(); Scope *scope = create_scope(nullptr, nullptr); - s->Struct.fields = slice_make(permanent_allocator(), 2); + s->Struct.fields = permanent_slice_make(2); s->Struct.fields[0] = alloc_entity_field(scope, make_token_ident("v"), alloc_type_array(type, len), false, 0, EntityState_Resolved); s->Struct.fields[1] = alloc_entity_field(scope, make_token_ident("_"), alloc_type_array(t_u8, padding), false, 1, EntityState_Resolved); s->Struct.scope = scope; @@ -2712,7 +2928,7 @@ gb_internal void init_map_internal_debug_types(Type *type) { Type *metadata_type = alloc_type_struct(); Scope *metadata_scope = create_scope(nullptr, nullptr); - metadata_type->Struct.fields = slice_make(permanent_allocator(), 5); + metadata_type->Struct.fields = permanent_slice_make(5); metadata_type->Struct.fields[0] = alloc_entity_field(metadata_scope, make_token_ident("key"), key, false, 0, EntityState_Resolved); metadata_type->Struct.fields[1] = alloc_entity_field(metadata_scope, make_token_ident("value"), value, false, 1, EntityState_Resolved); metadata_type->Struct.fields[2] = alloc_entity_field(metadata_scope, make_token_ident("hash"), t_uintptr, false, 2, EntityState_Resolved); @@ -2730,7 +2946,7 @@ gb_internal void init_map_internal_debug_types(Type *type) { Scope *scope = create_scope(nullptr, nullptr); Type *debug_type = alloc_type_struct(); - debug_type->Struct.fields = slice_make(permanent_allocator(), 3); + debug_type->Struct.fields = permanent_slice_make(3); debug_type->Struct.fields[0] = alloc_entity_field(scope, make_token_ident("data"), metadata_type, false, 0, EntityState_Resolved); debug_type->Struct.fields[1] = alloc_entity_field(scope, make_token_ident("len"), t_int, false, 1, EntityState_Resolved); debug_type->Struct.fields[2] = alloc_entity_field(scope, make_token_ident("allocator"), t_allocator, false, 2, EntityState_Resolved); @@ -2852,6 +3068,10 @@ gb_internal void check_map_type(CheckerContext *ctx, Type *type, Ast *node) { init_core_map_type(ctx->checker); init_map_internal_types(type); + + if (build_context.bedrock) { + error(node, "'map' is not a valid type when using '-bedrock'"); + } } gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node) { @@ -2963,13 +3183,13 @@ gb_internal bool complete_soa_type(Checker *checker, Type *t, bool wait_to_finis if (wait_to_finish) { wait_signal_until_available(&old_struct->Struct.fields_wait_signal); } else { - GB_ASSERT(old_struct->Struct.fields_wait_signal.futex.load()); + GB_ASSERT(old_struct->Struct.fields_wait_signal.futex.load() != 0); } field_count = old_struct->Struct.fields.count; - t->Struct.fields = slice_make(permanent_allocator(), field_count+extra_field_count); - t->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count); + t->Struct.fields = permanent_slice_make(field_count+extra_field_count); + t->Struct.tags = permanent_alloc_array(field_count+extra_field_count); auto const &add_entity = [](Scope *scope, Entity *entity) { @@ -3087,7 +3307,7 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e if (is_polymorphic) { field_count = 0; - soa_struct->Struct.fields = slice_make(permanent_allocator(), field_count+extra_field_count); + soa_struct->Struct.fields = permanent_slice_make(field_count+extra_field_count); soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count); soa_struct->Struct.soa_count = 0; @@ -3097,10 +3317,10 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e Type *old_array = base_type(elem); field_count = cast(isize)old_array->Array.count; - soa_struct->Struct.fields = slice_make(permanent_allocator(), field_count+extra_field_count); + soa_struct->Struct.fields = permanent_slice_make(field_count+extra_field_count); soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count); - string_map_init(&scope->elements, 8); + scope_map_init(&scope->elements); String params_xyzw[4] = { str_lit("x"), @@ -3139,8 +3359,8 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e if (old_struct->Struct.fields_wait_signal.futex.load()) { field_count = old_struct->Struct.fields.count; - soa_struct->Struct.fields = slice_make(permanent_allocator(), field_count+extra_field_count); - soa_struct->Struct.tags = gb_alloc_array(permanent_allocator(), String, field_count+extra_field_count); + soa_struct->Struct.fields = permanent_slice_make(field_count+extra_field_count); + soa_struct->Struct.tags = permanent_alloc_array(field_count+extra_field_count); for_array(i, old_struct->Struct.fields) { Entity *old_field = old_struct->Struct.fields[i]; @@ -3198,7 +3418,7 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e add_type_info_type(ctx, soa_struct); wait_signal_set(&soa_struct->Struct.fields_wait_signal); } else { - SoaTypeWorkerData *wd = gb_alloc_item(permanent_allocator(), SoaTypeWorkerData); + SoaTypeWorkerData *wd = permanent_alloc_item(); wd->ctx = *ctx; wd->type = soa_struct; wd->wait_to_finish = true; @@ -3275,7 +3495,7 @@ gb_internal void check_array_type_internal(CheckerContext *ctx, Ast *e, Type **t } if (count < 0) { - error(at->count, "? can only be used in conjuction with compound literals"); + error(at->count, "? can only be used in conjunction with compound literals"); count = 0; } @@ -3335,7 +3555,7 @@ gb_internal void check_array_type_internal(CheckerContext *ctx, Ast *e, Type **t } } gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_type) { - GB_ASSERT_NOT_NULL(type); + GB_ASSERT(type != nullptr); if (e == nullptr) { *type = t_invalid; return true; @@ -3413,7 +3633,7 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T Ast *s = pt->specialization; specific = check_type(&c, s); } - Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific); + Type *t = alloc_type_generic(ctx->scope, 0, ident->Ident.interned, specific); if (ctx->allow_polymorphic_types) { if (ctx->disallow_polymorphic_return_types) { error(ident, "Undeclared polymorphic parameter '%.*s' in return type", LIT(token.string)); @@ -3492,6 +3712,8 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T case_ast_node(pt, PointerType, e); CheckerContext c = *ctx; + + TEMPORARY_ALLOCATOR_GUARD(); c.type_path = new_checker_type_path(); defer (destroy_checker_type_path(c.type_path)); @@ -3589,6 +3811,32 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T *type = alloc_type_dynamic_array(elem); } set_base_type(named_type, *type); + + return true; + case_end; + + case_ast_node(dat, FixedCapacityDynamicArrayType, e); + Operand o = {}; + i64 capacity = check_array_count(ctx, &o, dat->capacity); + Type *generic_type = nullptr; + if (o.mode == Addressing_Type && o.type->kind == Type_Generic) { + generic_type = o.type; + } + + if (capacity < 0) { + error(dat->capacity, "? can only be used in conjunction with compound literals of fixed-length arrays"); + capacity = 0; + } + + + Type *elem = check_type(ctx, dat->elem); + if (dat->tag != nullptr) { + GB_ASSERT(dat->tag->kind == Ast_BasicDirective); + String name = dat->tag->BasicDirective.name.string; + error(dat->tag, "Invalid tag applied to fixed capacity dynamic array, got #%.*s", LIT(name)); + } + *type = alloc_type_fixed_capacity_dynamic_array(elem, capacity, generic_type); + set_base_type(named_type, *type); return true; case_end; @@ -3719,6 +3967,20 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T set_base_type(named_type, *type); return true; case_end; + + default: { + Operand o = {}; + check_expr_base(ctx, &o, e, nullptr); + + if (o.mode == Addressing_Constant && + o.value.kind == ExactValue_Typeid) { + Type *t = o.value.value_typeid; + if (t != nullptr && t != t_invalid) { + *type = t; + return true; + } + } + } } *type = t_invalid; @@ -3796,7 +4058,11 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) #if 0 error(e, "Invalid type definition of '%.*s'", LIT(type->Named.name)); #endif - type->Named.base = t_invalid; + if (type->Named.type_name->TypeName.is_type_alias) { + // NOTE(laytan): keep it null, type declaration is a mini "cycle" to be filled later. + } else { + type->Named.base = t_invalid; + } } if (is_type_polymorphic(type)) { @@ -3814,7 +4080,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) } #endif - if (is_type_typed(type)) { + if (type->kind == Type_Named && type->Named.base == nullptr || is_type_typed(type)) { add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value); } else { gbString name = type_to_string(type); diff --git a/src/checker.cpp b/src/checker.cpp index 17575668f..48863e706 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -55,7 +55,8 @@ gb_internal bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *f gb_internal void scope_reserve(Scope *scope, isize count) { - string_map_reserve(&scope->elements, 2*count); + scope_map_reserve(&scope->elements, 2*count); + // string_map_reserve(&scope->elements, 2*count); } gb_internal void entity_graph_node_set_destroy(EntityGraphNodeSet *s) { @@ -123,7 +124,7 @@ gb_internal void import_graph_node_set_add(ImportGraphNodeSet *s, ImportGraphNod // } gb_internal ImportGraphNode *import_graph_node_create(gbAllocator a, AstPackage *pkg) { - ImportGraphNode *n = gb_alloc_item(a, ImportGraphNode); + ImportGraphNode *n = permanent_alloc_item(); n->pkg = pkg; n->scope = pkg->scope; return n; @@ -163,7 +164,6 @@ gb_internal void import_graph_node_swap(ImportGraphNode **data, isize i, isize j gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { - gb_zero_item(d); if (parent) { mutex_lock(&parent->next_mutex); d->next_sibling = parent->next_child; @@ -181,7 +181,7 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { } gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) { - DeclInfo *d = gb_alloc_item(permanent_allocator(), DeclInfo); + DeclInfo *d = permanent_alloc_item(); init_decl_info(d, scope, parent); return d; } @@ -214,7 +214,8 @@ gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) { gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent) { - Scope *s = gb_alloc_item(permanent_allocator(), Scope); + Scope *s = permanent_alloc_item(); + scope_map_init(&s->elements); s->parent = parent; if (parent != nullptr && parent != builtin_pkg->scope) { @@ -238,8 +239,7 @@ gb_internal Scope *create_scope_from_file(CheckerInfo *info, AstFile *f) { isize init_elements_capacity = gb_max(DEFAULT_SCOPE_CAPACITY, 2*f->total_file_decl_count); Scope *s = create_scope(info, f->pkg->scope); - string_map_init(&s->elements, init_elements_capacity); - + scope_reserve(s, init_elements_capacity); s->flags |= ScopeFlag_File; s->file = f; @@ -256,9 +256,10 @@ gb_internal Scope *create_scope_from_package(CheckerContext *c, AstPackage *pkg) total_pkg_decl_count += file->total_file_decl_count; } - isize init_elements_capacity = gb_max(DEFAULT_SCOPE_CAPACITY, 2*total_pkg_decl_count); + // isize init_elements_capacity = gb_max(DEFAULT_SCOPE_CAPACITY, 2*total_pkg_decl_count); Scope *s = create_scope(c->info, builtin_pkg->scope); - string_map_init(&s->elements, init_elements_capacity); + scope_map_reserve(&s->elements, 2*total_pkg_decl_count); + // string_map_init(&s->elements, init_elements_capacity); s->flags |= ScopeFlag_Pkg; s->pkg = pkg; @@ -285,7 +286,7 @@ gb_internal void destroy_scope(Scope *scope) { destroy_scope(child); } - string_map_destroy(&scope->elements); + // string_map_destroy(&scope->elements); ptr_set_destroy(&scope->imported); // NOTE(bill): No need to free scope as it "should" be allocated in an arena (except for the global scope) @@ -371,27 +372,36 @@ gb_internal void check_close_scope(CheckerContext *c) { } -gb_internal Entity *scope_lookup_current(Scope *s, String const &name) { - Entity **found = string_map_get(&s->elements, name); +gb_internal Entity *scope_lookup_current(Scope *s, InternedString name, u32 hash) { + // Entity **found = string_map_get(&s->elements, name); + if (hash == 0) { + hash = name.hash(); + } + Entity *found = scope_map_get(&s->elements, name, hash); if (found) { - return *found; + return found; } return nullptr; } -gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **scope_, Entity **entity_) { +gb_global std::atomic in_single_threaded_checker_stage; + +gb_internal void scope_lookup_parent(Scope *scope, InternedString name, Scope **scope_, Entity **entity_, u32 hash) { + bool is_single_threaded = in_single_threaded_checker_stage.load(std::memory_order_relaxed); if (scope != nullptr) { bool gone_thru_proc = false; bool gone_thru_package = false; - StringHashKey key = string_hash_string(name); + if (!hash) { + hash = name.hash(); + } for (Scope *s = scope; s != nullptr; s = s->parent) { - Entity **found = nullptr; - rw_mutex_shared_lock(&s->mutex); - found = string_map_get(&s->elements, key); - rw_mutex_shared_unlock(&s->mutex); + Entity *found = nullptr; + if (!is_single_threaded) rw_mutex_shared_lock(&s->mutex); + found = scope_map_get(&s->elements, name, hash); + if (!is_single_threaded) rw_mutex_shared_unlock(&s->mutex); if (found) { - Entity *e = *found; + Entity *e = found; if (gone_thru_proc) { if (e->kind == Entity_Label) { continue; @@ -424,41 +434,40 @@ gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **s if (scope_) *scope_ = nullptr; } -gb_internal Entity *scope_lookup(Scope *s, String const &name) { +gb_internal Entity *scope_lookup(Scope *s, InternedString interned, u32 hash) { Entity *entity = nullptr; - scope_lookup_parent(s, name, nullptr, &entity); + scope_lookup_parent(s, interned, nullptr, &entity, hash); return entity; } -gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, String const &name, Entity *entity) { - if (name == "") { +gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, InternedString name, u32 hash, Entity *entity) { + if (name.value == 0) { return nullptr; } - StringHashKey key = string_hash_string(name); - Entity **found = nullptr; + Entity *found = nullptr; Entity *result = nullptr; - found = string_map_get(&s->elements, key); + found = scope_map_get(&s->elements, name, hash); if (found) { - if (entity != *found) { - result = *found; + if (entity != found) { + result = found; } goto end; } if (s->parent != nullptr && (s->parent->flags & ScopeFlag_Proc) != 0) { - found = string_map_get(&s->parent->elements, key); + found = scope_map_get(&s->parent->elements, name, hash); if (found) { - if ((*found)->flags & EntityFlag_Result) { - if (entity != *found) { - result = *found; + if (found->flags & EntityFlag_Result) { + if (entity != found) { + result = found; } goto end; } } } - string_map_set(&s->elements, key, entity); + scope_map_insert(&s->elements, name, hash, entity); if (entity->scope == nullptr) { entity->scope = s; } @@ -467,37 +476,39 @@ end:; } -gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity *entity) { - if (name == "") { +gb_internal Entity *scope_insert_with_name(Scope *s, InternedString name, u32 hash, Entity *entity) { + if (name.value == 0) { return nullptr; } - StringHashKey key = string_hash_string(name); - Entity **found = nullptr; + Entity *found = nullptr; Entity *result = nullptr; rw_mutex_lock(&s->mutex); - found = string_map_get(&s->elements, key); + found = scope_map_get(&s->elements, name, hash); if (found) { - if (entity != *found) { - result = *found; + if (entity != found) { + result = found; } goto end; } if (s->parent != nullptr && (s->parent->flags & ScopeFlag_Proc) != 0) { - found = string_map_get(&s->parent->elements, key); + rw_mutex_shared_lock(&s->parent->mutex); + found = scope_map_get(&s->parent->elements, name, hash); if (found) { - if ((*found)->flags & EntityFlag_Result) { - if (entity != *found) { - result = *found; + if (found->flags & EntityFlag_Result) { + if (entity != found) { + result = found; } + rw_mutex_shared_unlock(&s->parent->mutex); goto end; } } + rw_mutex_shared_unlock(&s->parent->mutex); } - string_map_set(&s->elements, key, entity); + scope_map_insert(&s->elements, name, hash, entity); if (entity->scope == nullptr) { entity->scope = s; } @@ -507,20 +518,22 @@ end:; return result; } -gb_global bool in_single_threaded_checker_stage = false; - gb_internal Entity *scope_insert(Scope *s, Entity *entity) { - String name = entity->token.string; - if (in_single_threaded_checker_stage) { - return scope_insert_with_name_no_mutex(s, name, entity); + auto name = entity_interned_name(entity); + u32 hash = entity->interned_name_hash.load(std::memory_order_relaxed); + GB_ASSERT(hash != 0); + if (in_single_threaded_checker_stage.load(std::memory_order_relaxed)) { + return scope_insert_with_name_no_mutex(s, name, hash, entity); } else { - return scope_insert_with_name(s, name, entity); + return scope_insert_with_name(s, name, hash, entity); } } gb_internal Entity *scope_insert_no_mutex(Scope *s, Entity *entity) { - String name = entity->token.string; - return scope_insert_with_name_no_mutex(s, name, entity); + auto name = string_interner_insert(entity->token.string); + u32 hash = entity->interned_name_hash.load(std::memory_order_relaxed); + GB_ASSERT(hash != 0); + return scope_insert_with_name_no_mutex(s, name, hash, entity); } @@ -565,6 +578,26 @@ gb_internal u64 check_feature_flags(CheckerContext *c, Ast *node) { return 0; } +gb_internal u64 check_feature_flags(Entity *e) { + if (e == nullptr) { + return 0; + } + AstFile *file = nullptr; + if (e->file == nullptr) { + file = e->file; + } + if (file == nullptr) { + if (e->decl_info && e->decl_info->decl_node) { + file = e->decl_info->decl_node->file(); + } + } + if (file != nullptr && file->feature_flags_set) { + return file->feature_flags; + } + return 0; +} + + enum VettedEntityKind { VettedEntity_Invalid, @@ -634,7 +667,8 @@ gb_internal bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) { return false; } - Entity *shadowed = scope_lookup(parent, name); + auto interned = entity_interned_name(e); + Entity *shadowed = scope_lookup(parent, interned, e->interned_name_hash.load()); if (shadowed == nullptr) { return false; } @@ -702,9 +736,10 @@ gb_internal bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) { gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_flags, bool per_entity) { u64 original_vet_flags = vet_flags; + + TEMPORARY_ALLOCATOR_GUARD(); Array vetted_entities = {}; - array_init(&vetted_entities, heap_allocator()); - defer (array_free(&vetted_entities)); + array_init(&vetted_entities, temporary_allocator()); rw_mutex_shared_lock(&scope->mutex); for (auto const &entry : scope->elements) { @@ -728,12 +763,17 @@ gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_fl bool is_unused = false; if (vet_unused && check_vet_unused(c, e, &ve_unused)) { is_unused = true; - } else if (vet_unused_procedures && - e->kind == Entity_Procedure) { + } else if (vet_unused_procedures && e->kind == Entity_Procedure) { if (e->flags&EntityFlag_Used) { is_unused = false; } else if (e->flags & EntityFlag_Require) { is_unused = false; + } else if (e->flags & EntityFlag_Init) { + is_unused = false; + } else if (e->flags & EntityFlag_Fini) { + is_unused = false; + } else if (e->Procedure.is_export) { + is_unused = false; } else if (e->pkg && e->pkg->kind == Package_Init && e->token.string == "main") { is_unused = false; } else { @@ -751,14 +791,19 @@ gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_fl array_add(&vetted_entities, ve_unused); } else if (is_shadowed) { array_add(&vetted_entities, ve_shadowed); - } else if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using|EntityFlag_Static|EntityFlag_Field)) == 0 && !e->Variable.is_global) { + } else if (e->kind == Entity_Variable && + ((e->flags & (EntityFlag_Param|EntityFlag_Using|EntityFlag_Static|EntityFlag_Field)) == 0 || + (e->flags & EntityFlag_Result) != 0) && + !e->Variable.is_global) { i64 sz = type_size_of(e->type); // TODO(bill): When is a good size warn? // Is >256 KiB good enough? if (sz > 1ll<<18) { bool is_ref = false; - if((e->flags & EntityFlag_ForValue) != 0) { + if ((e->flags & EntityFlag_ForValue) != 0) { is_ref = type_deref(e->Variable.for_loop_parent_type) != NULL; + } else if ((e->flags & EntityFlag_SwitchValue) != 0) { + is_ref = !(e->flags & EntityFlag_Value); } if(!is_ref) { gbString type_str = type_to_string(e->type); @@ -827,9 +872,13 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) { gb_internal void add_dependency(CheckerInfo *info, DeclInfo *d, Entity *e) { - rw_mutex_lock(&d->deps_mutex); - ptr_set_add(&d->deps, e); - rw_mutex_unlock(&d->deps_mutex); + if (in_single_threaded_checker_stage.load(std::memory_order_relaxed)) { + ptr_set_add(&d->deps, e); + } else { + rw_mutex_lock(&d->deps_mutex); + ptr_set_add(&d->deps, e); + rw_mutex_unlock(&d->deps_mutex); + } } gb_internal void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type *type) { if (d == nullptr || type == nullptr) { @@ -886,10 +935,28 @@ gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) { return *found; } + +gb_internal AstPackage *try_get_core_package(CheckerInfo *info, String name) { + if (name == "runtime") { + return get_runtime_package(info); + } + + gbAllocator a = heap_allocator(); + String path = get_fullpath_core_collection(a, name, nullptr); + defer (gb_free(a, path.text)); + auto found = string_map_get(&info->packages, path); + if (found == nullptr) { + return nullptr; + } + return *found; +} + gb_internal void add_package_dependency(CheckerContext *c, char const *package_name, char const *name, bool required=false) { String n = make_string_c(name); + u32 hash = 0; + InternedString key = string_interner_insert(n, 0, &hash); AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); - Entity *e = scope_lookup(p->scope, n); + Entity *e = scope_lookup(p->scope, key, hash); GB_ASSERT_MSG(e != nullptr, "%s", name); GB_ASSERT(c->decl != nullptr); e->flags |= EntityFlag_Used; @@ -901,8 +968,10 @@ gb_internal void add_package_dependency(CheckerContext *c, char const *package_n gb_internal void try_to_add_package_dependency(CheckerContext *c, char const *package_name, char const *name) { String n = make_string_c(name); + u32 hash = 0; + InternedString key = string_interner_insert(n, 0, &hash); AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); - Entity *e = scope_lookup(p->scope, n); + Entity *e = scope_lookup(p->scope, key, hash); if (e == nullptr) { return; } @@ -961,7 +1030,7 @@ gb_internal void add_global_type_entity(String name, Type *type) { gb_internal AstPackage *create_builtin_package(char const *name) { gbAllocator a = permanent_allocator(); - AstPackage *pkg = gb_alloc_item(a, AstPackage); + AstPackage *pkg = permanent_alloc_item(); pkg->name = make_string_c(name); pkg->kind = Package_Builtin; @@ -976,14 +1045,14 @@ struct GlobalEnumValue { i64 value; }; -gb_internal Slice add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count, Type **enum_type_ = nullptr) { +gb_internal Slice add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count, Type **enum_type_ = nullptr, Type *backing_type = nullptr) { Scope *scope = create_scope(nullptr, builtin_pkg->scope); Entity *entity = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved); Type *enum_type = alloc_type_enum(); Type *named_type = alloc_type_named(type_name, enum_type, entity); set_base_type(named_type, enum_type); - enum_type->Enum.base_type = t_int; + enum_type->Enum.base_type = backing_type ? backing_type : t_int; enum_type->Enum.scope = scope; entity->type = named_type; @@ -1052,6 +1121,14 @@ gb_internal void init_universal(void) { // Types for (isize i = 0; i < gb_count_of(basic_types); i++) { String const &name = basic_types[i].Basic.name; + if (build_context.bedrock) { + if ((basic_types[i].Basic.flags & BasicFlag_Integer) != 0 && + basic_types[i].Basic.size == 16) { + // disallow 128-bit integers + continue; + } + } + add_global_type_entity(name, &basic_types[i]); } add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]); @@ -1073,11 +1150,32 @@ gb_internal void init_universal(void) { add_global_bool_constant("true", true); add_global_bool_constant("false", false); - add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); - add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); - add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); - add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); - add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); + add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); + add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); + add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); + + add_global_bool_constant("ODIN_BEDROCK", bc->bedrock); + + { + GlobalEnumValue values[Windows_Subsystem_COUNT] = { + {"Unknown", Windows_Subsystem_UNKNOWN}, + {"Boot_Application", Windows_Subsystem_BOOT_APPLICATION}, + {"Console", Windows_Subsystem_CONSOLE}, + {"EFI_Application", Windows_Subsystem_EFI_APPLICATION}, + {"EFI_Boot_Service_Driver", Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER}, + {"EFI_Rom", Windows_Subsystem_EFI_ROM}, + {"EFI_Runtime_Driver", Windows_Subsystem_EFI_RUNTIME_DRIVER}, + {"Native", Windows_Subsystem_NATIVE}, + {"Posix", Windows_Subsystem_POSIX}, + {"Windows", Windows_Subsystem_WINDOWS}, + {"Windows_CE", Windows_Subsystem_WINDOWSCE}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Windows_Subsystem_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM_STRING", windows_subsystem_names[bc->ODIN_WINDOWS_SUBSYSTEM]); + } { GlobalEnumValue values[TargetOs_COUNT] = { @@ -1085,9 +1183,7 @@ gb_internal void init_universal(void) { {"Windows", TargetOs_windows}, {"Darwin", TargetOs_darwin}, {"Linux", TargetOs_linux}, - {"Essence", TargetOs_essence}, {"FreeBSD", TargetOs_freebsd}, - {"Haiku", TargetOs_haiku}, {"OpenBSD", TargetOs_openbsd}, {"NetBSD", TargetOs_netbsd}, {"WASI", TargetOs_wasi}, @@ -1097,7 +1193,7 @@ gb_internal void init_universal(void) { }; auto fields = add_global_enum_type(str_lit("Odin_OS_Type"), values, gb_count_of(values)); - add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); + add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); add_global_string_constant("ODIN_OS_STRING", target_os_names[bc->metrics.os]); } @@ -1147,9 +1243,10 @@ gb_internal void init_universal(void) { { GlobalEnumValue values[Subtarget_COUNT] = { - {"Default", Subtarget_Default}, - {"iOS", Subtarget_iOS}, - {"Android", Subtarget_Android}, + {"Default", Subtarget_Default}, + {"iPhone", Subtarget_iPhone}, + {"iPhoneSimulator", Subtarget_iPhoneSimulator}, + {"Android", Subtarget_Android}, }; auto fields = add_global_enum_type(str_lit("Odin_Platform_Subtarget_Type"), values, gb_count_of(values)); @@ -1166,6 +1263,41 @@ gb_internal void init_universal(void) { add_global_enum_constant(fields, "ODIN_ERROR_POS_STYLE", build_context.ODIN_ERROR_POS_STYLE); } + { + GlobalEnumValue values[OdinFastMath_COUNT] = {}; + for (unsigned i = 0; i < OdinFastMath_COUNT; i++) { + values[i] = {OdinFastMathFlag_strings[i], i}; + } + + auto fields = add_global_enum_type(str_lit("Fast_Math_Flag"), values, gb_count_of(values), &t_fast_math_flag, t_u8); + + GB_ASSERT(t_fast_math_flag->kind == Type_Named); + scope_insert(intrinsics_pkg->scope, t_fast_math_flag->Named.type_name); + + Type *bs = alloc_type_bit_set(); + bs->BitSet.elem = t_fast_math_flag; + bs->BitSet.underlying = t_u32; + bs->BitSet.lower = 0; + bs->BitSet.upper = OdinFastMath_COUNT-1; + bs->BitSet.node = nullptr; + + + { + String type_name = str_lit("Fast_Math_Flags"); + + Scope *scope = create_scope(nullptr, builtin_pkg->scope); + Entity *entity = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved); + + Type *named_type = alloc_type_named(type_name, bs, entity); + set_base_type(named_type, bs); + entity->type = named_type; + + t_fast_math_flags = named_type; + + scope_insert(intrinsics_pkg->scope, entity); + } + } + { GlobalEnumValue values[OdinAtomicMemoryOrder_COUNT] = { {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_relaxed], OdinAtomicMemoryOrder_relaxed}, @@ -1181,6 +1313,32 @@ gb_internal void init_universal(void) { scope_insert(intrinsics_pkg->scope, t_atomic_memory_order->Named.type_name); } + { + GlobalEnumValue values[ProcCC_MAX] = { + {"Invalid", ProcCC_Invalid}, + {"Odin", ProcCC_Odin}, + {"Contextless", ProcCC_Contextless}, + {"CDecl", ProcCC_CDecl}, + {"Std_Call", ProcCC_StdCall}, + {"Fast_Call", ProcCC_FastCall}, + + {"None", ProcCC_None}, + {"Naked", ProcCC_Naked}, + + {"_", ProcCC_InlineAsm}, + + {"Win64", ProcCC_Win64}, + {"SysV", ProcCC_SysV}, + + {"PreserveNone", ProcCC_PreserveNone}, + {"PreserveMost", ProcCC_PreserveMost}, + {"PreserveAll", ProcCC_PreserveAll}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Calling_Convention"), values, gb_count_of(values), &t_odin_calling_convention, t_u8); + add_global_enum_constant(fields, "ODIN_DEFAULT_CALLING_CONVENTION", default_calling_convention()); + } + { int minimum_os_version = 0; if (build_context.minimum_os_version_string != "") { @@ -1209,7 +1367,6 @@ gb_internal void init_universal(void) { add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti); add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT); - add_global_bool_constant("ODIN_TILDE", bc->tilde_backend); add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp())); @@ -1280,6 +1437,9 @@ gb_internal void init_universal(void) { BuiltinProcId id = cast(BuiltinProcId)i; String name = builtin_procs[i].name; if (name != "") { + u32 hash = 0; + InternedString interned = string_interner_insert(name, 0, &hash); + Entity *entity = alloc_entity(Entity_Builtin, nullptr, make_token_ident(name), t_invalid); entity->Builtin.id = id; switch (builtin_procs[i].pkg) { @@ -1288,7 +1448,7 @@ gb_internal void init_universal(void) { break; case BuiltinProcPkg_intrinsics: add_global_entity(entity, intrinsics_pkg->scope); - GB_ASSERT(scope_lookup_current(intrinsics_pkg->scope, name) != nullptr); + GB_ASSERT(scope_lookup_current(intrinsics_pkg->scope, interned, hash) != nullptr); break; } } @@ -1338,13 +1498,15 @@ gb_internal void init_universal(void) { } - t_u8_ptr = alloc_type_pointer(t_u8); - t_u8_multi_ptr = alloc_type_multi_pointer(t_u8); - t_int_ptr = alloc_type_pointer(t_int); - t_i64_ptr = alloc_type_pointer(t_i64); - t_f64_ptr = alloc_type_pointer(t_f64); - t_u8_slice = alloc_type_slice(t_u8); - t_string_slice = alloc_type_slice(t_string); + t_u8_ptr = alloc_type_pointer(t_u8); + t_u8_multi_ptr = alloc_type_multi_pointer(t_u8); + t_u16_ptr = alloc_type_pointer(t_u16); + t_u16_multi_ptr = alloc_type_multi_pointer(t_u16); + t_int_ptr = alloc_type_pointer(t_int); + t_i64_ptr = alloc_type_pointer(t_i64); + t_f64_ptr = alloc_type_pointer(t_f64); + t_u8_slice = alloc_type_slice(t_u8); + t_string_slice = alloc_type_slice(t_string); // intrinsics types for objective-c stuff { @@ -1357,6 +1519,74 @@ gb_internal void init_universal(void) { t_objc_SEL = alloc_type_pointer(t_objc_selector); t_objc_Class = alloc_type_pointer(t_objc_class); t_objc_Ivar = alloc_type_pointer(t_objc_ivar); + + t_objc_instancetype = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_instancetype"), t_objc_id); + } + + // intrinsics types for C stuff + { + Scope *scope = create_scope(nullptr, nullptr); + + auto dummy_field = [](Scope *scope, Type *type, i32 field_index, char const *name = nullptr) -> Entity * { + auto token = blank_token; + if (name) { + token.string = make_string_c(name); + } + return alloc_entity_field(scope, token, type, false, 0, EntityState_Resolved); + }; + + auto fields = array_make(permanent_allocator(), 0, 8); + + switch (build_context.metrics.arch) { + case TargetArch_amd64: + switch (build_context.metrics.os) { + case TargetOs_freestanding: + /*check*/ + case TargetOs_linux: + case TargetOs_freebsd: + case TargetOs_netbsd: + case TargetOs_openbsd: + array_add(&fields, dummy_field(scope, t_u32, 0, "gp_offset")); + array_add(&fields, dummy_field(scope, t_u32, 1, "fp_offset")); + array_add(&fields, dummy_field(scope, t_rawptr, 2, "overflow_arg_area")); + array_add(&fields, dummy_field(scope, t_rawptr, 3, "reg_save_area")); + break; + } + break; + + case TargetArch_arm64: + switch (build_context.metrics.os) { + case TargetOs_darwin: + // AARCH64 architecture is different to other arm64 platforms + array_add(&fields, dummy_field(scope, t_rawptr, 0)); + break; + + case TargetOs_freestanding: + case TargetOs_linux: + case TargetOs_freebsd: + case TargetOs_netbsd: + case TargetOs_openbsd: // Not sure if this is correct + array_add(&fields, dummy_field(scope, t_rawptr, 0, "__stack")); + array_add(&fields, dummy_field(scope, t_rawptr, 1, "__gr_top")); + array_add(&fields, dummy_field(scope, t_rawptr, 2, "__vr_top")); + array_add(&fields, dummy_field(scope, t_i32, 3, "__gr_offs")); + array_add(&fields, dummy_field(scope, t_i32, 4, "__vr_offs")); + break; + } + break; + } + + if (fields.count == 0) { + array_add(&fields, dummy_field(scope, t_rawptr, 0)); + } + + Type *va_list_struct = alloc_type_struct_complete(); + va_list_struct->Struct.scope = scope; + va_list_struct->Struct.fields = slice_from_array(fields); + GB_ASSERT(type_size_of(va_list_struct) > 0); + + t_c_va_list = add_global_type_name(intrinsics_pkg->scope, str_lit("c_va_list"), va_list_struct); + t_c_va_list_ptr = alloc_type_pointer(t_c_va_list); } } @@ -1372,13 +1602,10 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->entities, a); map_init(&i->global_untyped); string_map_init(&i->foreigns); - // map_init(&i->gen_procs); - map_init(&i->gen_types); type_set_init(&i->min_dep_type_info_set); map_init(&i->min_dep_type_info_index_map); - // map_init(&i->type_info_map); string_map_init(&i->files); string_map_init(&i->packages); array_init(&i->variable_init_order, a); @@ -1394,7 +1621,8 @@ gb_internal void init_checker_info(CheckerInfo *i) { map_init(&i->objc_method_implementations); string_map_init(&i->load_file_cache); - array_init(&i->all_procedures, heap_allocator()); + array_init(&i->all_procedures, a); + mpsc_init(&i->all_procedures_queue, a); mpsc_init(&i->entity_queue, a); // 1<<20); mpsc_init(&i->definition_queue, a); //); // 1<<20); @@ -1404,6 +1632,9 @@ gb_internal void init_checker_info(CheckerInfo *i) { mpsc_init(&i->foreign_decls_to_check, a); // 1<<10); mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used + mpsc_init(&i->raddbg_type_views_queue, a); + array_init(&i->raddbg_type_views, a); + string_map_init(&i->load_directory_cache); map_init(&i->load_directory_map); } @@ -1413,8 +1644,6 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { array_free(&i->entities); map_destroy(&i->global_untyped); string_map_destroy(&i->foreigns); - // map_destroy(&i->gen_procs); - map_destroy(&i->gen_types); type_set_destroy(&i->min_dep_type_info_set); map_destroy(&i->min_dep_type_info_index_map); @@ -1425,6 +1654,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { array_free(&i->required_foreign_imports_through_force); array_free(&i->defineables); + array_free(&i->all_procedures); + + mpsc_destroy(&i->all_procedures_queue); + mpsc_destroy(&i->entity_queue); mpsc_destroy(&i->definition_queue); mpsc_destroy(&i->required_global_variable_queue); @@ -1432,23 +1665,32 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { mpsc_destroy(&i->foreign_imports_to_check_fullpaths); mpsc_destroy(&i->foreign_decls_to_check); + mpsc_destroy(&i->raddbg_type_views_queue); + array_free(&i->raddbg_type_views); + map_destroy(&i->objc_msgSend_types); + string_set_destroy(&i->obcj_class_name_set); + map_destroy(&i->objc_method_implementations); + + // NOTE(harold): Disabling this: It can cause the 'count == 0' assert to trigger + // when there's checker errors and the queue is still full as it did not reach the generation stage. + // mpsc_destroy(&i->objc_class_implementations); + string_map_destroy(&i->load_file_cache); string_map_destroy(&i->load_directory_cache); map_destroy(&i->load_directory_map); } -gb_internal CheckerContext make_checker_context(Checker *c) { - CheckerContext ctx = {}; - ctx.checker = c; - ctx.info = &c->info; - ctx.scope = builtin_pkg->scope; - ctx.pkg = builtin_pkg; +gb_internal void init_checker_context(CheckerContext *ctx, Checker *c) { + ctx->checker = c; + ctx->info = &c->info; + ctx->scope = builtin_pkg->scope; + ctx->pkg = builtin_pkg; - ctx.type_path = new_checker_type_path(); - ctx.type_level = 0; - return ctx; + ctx->type_path = new_checker_type_path(); + ctx->type_level = 0; } + gb_internal void destroy_checker_context(CheckerContext *ctx) { destroy_checker_type_path(ctx->type_path); } @@ -1513,7 +1755,7 @@ gb_internal void init_checker(Checker *c) { mpsc_init(&c->global_untyped_queue, a); // , 1<<20); mpsc_init(&c->soa_types_to_complete, a); // , 1<<20); - c->builtin_ctx = make_checker_context(c); + init_checker_context(&c->builtin_ctx, c); } gb_internal void destroy_checker(Checker *c) { @@ -1655,7 +1897,7 @@ gb_internal void check_remove_expr_info(CheckerContext *c, Ast *e) { } gb_internal isize type_info_index(CheckerInfo *info, TypeInfoPair pair, bool error_on_failure) { - mutex_lock(&info->minimum_dependency_type_info_mutex); + rw_mutex_shared_lock(&info->minimum_dependency_type_info_mutex); isize entry_index = -1; u64 hash = pair.hash; @@ -1663,7 +1905,7 @@ gb_internal isize type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err if (found_entry_index) { entry_index = *found_entry_index; } - mutex_unlock(&info->minimum_dependency_type_info_mutex); + rw_mutex_shared_unlock(&info->minimum_dependency_type_info_mutex); if (error_on_failure && entry_index < 0) { compiler_error("Type_Info for '%s' could not be found", type_to_string(pair.type)); @@ -1701,6 +1943,21 @@ gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, check_set_expr_info(c, expr, mode, type, value); } +struct alignas(GB_CACHE_LINE_SIZE) TypeAndValueMutexStripes { + BlockingMutex mutex; + u8 padding[GB_CACHE_LINE_SIZE - gb_size_of(BlockingMutex)]; +}; + +enum { TypeAndValueMutexStripes_COUNT = 128 }; +gb_global TypeAndValueMutexStripes tav_mutex_stripes[TypeAndValueMutexStripes_COUNT]; + +gb_internal BlockingMutex *tav_mutex_for_node(Ast *node) { + GB_ASSERT(node != nullptr); + uintptr h = cast(uintptr)node; + h ^= h >> 6; + return &tav_mutex_stripes[h % TypeAndValueMutexStripes_COUNT].mutex; +} + gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) { if (expr == nullptr) { return; @@ -1712,12 +1969,16 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo return; } - BlockingMutex *mutex = &ctx->info->type_and_value_mutex; - if (ctx->decl) { - mutex = &ctx->decl->type_and_value_mutex; - } else if (ctx->pkg) { - mutex = &ctx->pkg->type_and_value_mutex; - } + BlockingMutex *mutex = tav_mutex_for_node(expr); + + /* Previous logic: + BlockingMutex *mutex = &ctx->info->type_and_value_mutex; + if (ctx->decl) { + mutex = &ctx->decl->type_and_value_mutex; + } else if (ctx->pkg) { + mutex = &ctx->pkg->type_and_value_mutex; + } + */ mutex_lock(mutex); Ast *prev_expr = nullptr; @@ -1740,6 +2001,9 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo } expr = unparen_expr(expr); + if (expr == nullptr) { + break; + }; } mutex_unlock(mutex); } @@ -1983,8 +2247,8 @@ gb_internal void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, En add_entity_definition(info, identifier, e); GB_ASSERT(e->decl_info == nullptr); e->decl_info = d; - d->entity = e; e->pkg = c->pkg; + d->entity.store(e); isize queue_count = -1; bool is_lazy = false; @@ -2030,7 +2294,7 @@ gb_internal void add_type_info_type(CheckerContext *c, Type *t) { } gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { - if (t == nullptr) { + if (t == nullptr || c == nullptr) { return; } @@ -2125,7 +2389,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { case Type_BitSet: add_type_info_type_internal(c, bt->BitSet.elem); - add_type_info_type_internal(c, bt->BitSet.underlying); + add_type_info_type_internal(c, bit_set_to_int(bt)); break; case Type_Pointer: @@ -2161,6 +2425,11 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_type_internal(c, t_int); break; + case Type_FixedCapacityDynamicArray: + add_type_info_type_internal(c, bt->FixedCapacityDynamicArray.elem); + add_type_info_type_internal(c, t_int); + break; + case Type_Enum: add_type_info_type_internal(c, bt->Enum.base_type); break; @@ -2285,16 +2554,14 @@ gb_internal void check_procedure_later(Checker *c, ProcInfo *info) { } if (DEBUG_CHECK_ALL_PROCEDURES) { - MUTEX_GUARD_BLOCK(&c->info.all_procedures_mutex) { - GB_ASSERT(info != nullptr); - GB_ASSERT(info->decl != nullptr); - array_add(&c->info.all_procedures, info); - } + GB_ASSERT(info != nullptr); + GB_ASSERT(info->decl != nullptr); + mpsc_enqueue(&c->info.all_procedures_queue, info); } } gb_internal void check_procedure_later(Checker *c, AstFile *file, Token token, DeclInfo *decl, Type *type, Ast *body, u64 tags) { - ProcInfo *info = gb_alloc_item(permanent_allocator(), ProcInfo); + ProcInfo *info = permanent_alloc_item(); info->file = file; info->token = token; info->decl = decl; @@ -2317,7 +2584,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { return; } - if (type_set_update(&c->info.min_dep_type_info_set, t)) { + if (type_set_update_with_mutex(&c->info.min_dep_type_info_set, t, &c->info.min_dep_type_info_set_mutex)) { return; } @@ -2366,7 +2633,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { case Type_BitSet: add_min_dep_type_info(c, bt->BitSet.elem); - add_min_dep_type_info(c, bt->BitSet.underlying); + add_min_dep_type_info(c, bit_set_to_int(bt)); break; case Type_Pointer: @@ -2401,6 +2668,12 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { add_min_dep_type_info(c, t_int); break; + case Type_FixedCapacityDynamicArray: + add_min_dep_type_info(c, bt->FixedCapacityDynamicArray.elem); + add_min_dep_type_info(c, alloc_type_pointer(bt->FixedCapacityDynamicArray.elem)); + add_min_dep_type_info(c, alloc_type_array(bt->FixedCapacityDynamicArray.elem, bt->FixedCapacityDynamicArray.capacity)); + add_min_dep_type_info(c, t_int); + case Type_Enum: add_min_dep_type_info(c, bt->Enum.base_type); break; @@ -2492,15 +2765,15 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } } +gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity); + +gb_global std::atomic global_checker_ptr; gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { if (entity == nullptr) { return; } - CheckerInfo *info = &c->info; - auto *set = &info->minimum_dependency_set; - if (entity->type != nullptr && is_type_polymorphic(entity->type)) { DeclInfo *decl = decl_info_of_entity(entity); @@ -2509,7 +2782,7 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { } } - if (ptr_set_update(set, entity)) { + if (entity->min_dep_count.fetch_add(1, std::memory_order_relaxed) > 0) { return; } @@ -2520,31 +2793,112 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { for (TypeInfoPair const tt : decl->type_info_deps) { add_min_dep_type_info(c, tt.type); } - - for (Entity *e : decl->deps) { - add_dependency_to_set(c, e); - if (e->kind == Entity_Procedure && e->Procedure.is_foreign) { - Entity *fl = e->Procedure.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set(c, fl); + FOR_PTR_SET(e, decl->deps) { + switch (e->kind) { + case Entity_Procedure: + if (e->Procedure.is_foreign) { + Entity *fl = e->Procedure.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set(c, fl); + } } - } else if (e->kind == Entity_Variable && e->Variable.is_foreign) { - Entity *fl = e->Variable.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set(c, fl); + break; + case Entity_Variable: + if (e->Variable.is_foreign) { + Entity *fl = e->Variable.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set(c, fl); + } } + break; } } + + FOR_PTR_SET(e, decl->deps) { + add_dependency_to_set(c, e); + } + +} +gb_internal WORKER_TASK_PROC(add_dependency_to_set_worker) { + Checker *c = global_checker_ptr.load(std::memory_order_relaxed); + Entity *entity = cast(Entity *)data; + if (entity == nullptr) { + return 0; + } + + if (entity->type != nullptr && + is_type_polymorphic(entity->type)) { + DeclInfo *decl = decl_info_of_entity(entity); + if (decl != nullptr && decl->gen_proc_type == nullptr) { + return 0; + } + } + + if (entity->min_dep_count.fetch_add(1, std::memory_order_relaxed) > 0) { + return 0; + } + + DeclInfo *decl = decl_info_of_entity(entity); + if (decl == nullptr) { + return 0; + } + for (TypeInfoPair const tt : decl->type_info_deps) { + add_min_dep_type_info(c, tt.type); + } + + FOR_PTR_SET(e, decl->deps) { + switch (e->kind) { + case Entity_Procedure: + if (e->Procedure.is_foreign) { + Entity *fl = e->Procedure.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set_threaded(c, fl); + } + } + break; + case Entity_Variable: + if (e->Variable.is_foreign) { + Entity *fl = e->Variable.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set_threaded(c, fl); + } + } + break; + } + } + + FOR_PTR_SET(e, decl->deps) { + add_dependency_to_set_threaded(c, e); + } + + return 0; } + +gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity) { + if (entity == nullptr) { + return; + } + thread_pool_add_task(add_dependency_to_set_worker, entity); +} + + gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String const &name) { - Entity *e = scope_lookup(scope, name); + u32 hash = 0; + auto interned = string_interner_insert(name, 0, &hash); + Entity *e = scope_lookup(scope, interned, hash); if (e == nullptr) { return; } @@ -2556,11 +2910,15 @@ gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String co gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *pkg) { AstPackage *testing_package = get_core_package(&c->info, str_lit("testing")); Scope *testing_scope = testing_package->scope; - Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature")); + u32 hash = 0; + InternedString interned = string_interner_insert(str_lit("Test_Signature"), 0, &hash); + Entity *test_signature = scope_lookup_current(testing_scope, interned, hash); - Scope *s = pkg->scope; - for (auto const &entry : s->elements) { - Entity *e = entry.value; + for_array(i, c->info.entities) { + Entity *e = c->info.entities[i]; + if (e->pkg != pkg) { + continue; + } if (e->kind != Entity_Procedure) { continue; } @@ -2592,27 +2950,35 @@ gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *p } gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *start) { + // auto const &add_to_set = add_dependency_to_set; + auto const &add_to_set = add_dependency_to_set_threaded; + + Scope *builtin_scope = builtin_pkg->scope; for_array(i, c->info.definitions) { Entity *e = c->info.definitions[i]; - if (e->scope == builtin_pkg->scope) { + if (e->scope == builtin_scope) { if (e->type == nullptr) { - add_dependency_to_set(c, e); + add_to_set(c, e); + } + } else if (e->kind == Entity_Procedure) { + if (e->Procedure.is_export) { + add_to_set(c, e); + } + } else if (e->kind == Entity_Variable) { + if (e->Variable.is_export) { + add_to_set(c, e); } - } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { - add_dependency_to_set(c, e); - } else if (e->kind == Entity_Variable && e->Variable.is_export) { - add_dependency_to_set(c, e); } } for (Entity *e; mpsc_dequeue(&c->info.required_foreign_imports_through_force_queue, &e); /**/) { array_add(&c->info.required_foreign_imports_through_force, e); - add_dependency_to_set(c, e); + add_to_set(c, e); } for (Entity *e; mpsc_dequeue(&c->info.required_global_variable_queue, &e); /**/) { e->flags |= EntityFlag_Used; - add_dependency_to_set(c, e); + add_to_set(c, e); } for_array(i, c->info.entities) { @@ -2620,16 +2986,16 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st switch (e->kind) { case Entity_Variable: if (e->Variable.is_export) { - add_dependency_to_set(c, e); + add_to_set(c, e); } else if (e->flags & EntityFlag_Require) { - add_dependency_to_set(c, e); + add_to_set(c, e); } break; case Entity_Procedure: if (e->Procedure.is_export) { - add_dependency_to_set(c, e); + add_to_set(c, e); } else if (e->flags & EntityFlag_Require) { - add_dependency_to_set(c, e); + add_to_set(c, e); } if (e->flags & EntityFlag_Init) { Type *t = base_type(e->type); @@ -2644,6 +3010,15 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_init = false; } + u64 feature_flags = check_feature_flags(e); + if ((feature_flags & OptInFeatureFlag_GlobalContext) == 0) { + if (t->Proc.calling_convention != ProcCC_Contextless) { + ERROR_BLOCK(); + error(e->token, "@(init) procedures must be declared as \"contextless\""); + error_line("\tSuggestion: this can be bypassed, for the time being, with '#+feature global-context'"); + } + } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { error(e->token, "@(init) procedures must be declared at the file scope"); is_init = false; @@ -2658,8 +3033,9 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st error(e->token, "An @(init) procedure must not use a blank identifier as its name"); } + if (is_init) { - add_dependency_to_set(c, e); + add_to_set(c, e); array_add(&c->info.init_procedures, e); } } else if (e->flags & EntityFlag_Fini) { @@ -2675,6 +3051,15 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_fini = false; } + u64 feature_flags = check_feature_flags(e); + if ((feature_flags & OptInFeatureFlag_GlobalContext) == 0) { + if (t->Proc.calling_convention != ProcCC_Contextless) { + ERROR_BLOCK(); + error(e->token, "@(fini) procedures must be declared as \"contextless\""); + error_line("\tSuggestion: this can be bypassed, for the time being, with '#+feature global-context'"); + } + } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { error(e->token, "@(fini) procedures must be declared at the file scope"); is_fini = false; @@ -2685,7 +3070,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st } if (is_fini) { - add_dependency_to_set(c, e); + add_to_set(c, e); array_add(&c->info.fini_procedures, e); } } @@ -2702,7 +3087,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st Entity *e = entry.value; if (e != nullptr) { e->flags |= EntityFlag_Used; - add_dependency_to_set(c, e); + add_to_set(c, e); } } @@ -2717,16 +3102,11 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st } } else if (start != nullptr) { start->flags |= EntityFlag_Used; - add_dependency_to_set(c, start); + add_to_set(c, start); } } gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { - isize entity_count = c->info.entities.count; - isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor - - ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); - #define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ if (condition) { \ String entities[] = {__VA_ARGS__}; \ @@ -2768,7 +3148,7 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { str_lit("aeabi_d2h") ); - FORCE_ADD_RUNTIME_ENTITIES(is_arch_wasm() && !build_context.tilde_backend, + FORCE_ADD_RUNTIME_ENTITIES(is_arch_wasm(), // // Extended data type internal procedures // str_lit("umodti3"), // str_lit("udivti3"), @@ -2825,12 +3205,13 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { generate_minimum_dependency_set_internal(c, start); + thread_pool_wait(); + #undef FORCE_ADD_RUNTIME_ENTITIES } -gb_internal bool is_entity_a_dependency(Entity *e) { - if (e == nullptr) return false; +gb_internal gb_inline bool is_entity_a_dependency(Entity *e) { switch (e->kind) { case Entity_Procedure: return true; @@ -2843,83 +3224,112 @@ gb_internal bool is_entity_a_dependency(Entity *e) { return false; } -gb_internal Array generate_entity_dependency_graph(CheckerInfo *info, gbAllocator allocator) { - PtrMap M = {}; - map_init(&M, info->entities.count); - defer (map_destroy(&M)); +gb_internal Array generate_entity_dependency_graph(CheckerInfo *info, Arena *arena) { + PtrMap M_procs = {}; + PtrMap M_vars = {}; + PtrMap M_other = {}; + + map_init(&M_procs, info->entities.count); + defer (map_destroy(&M_procs)); + + map_init(&M_vars, info->entities.count); + defer (map_destroy(&M_vars)); + + map_init(&M_other, info->entities.count); + defer (map_destroy(&M_other)); + for_array(i, info->entities) { Entity *e = info->entities[i]; - if (is_entity_a_dependency(e)) { - EntityGraphNode *n = gb_alloc_item(allocator, EntityGraphNode); - n->entity = e; - map_set(&M, e, n); + if (e == nullptr || !is_entity_a_dependency(e)) { + continue; + } + EntityGraphNode *n = arena_alloc_item(arena); + n->entity = e; + switch (e->kind) { + case Entity_Procedure: map_set(&M_procs, e, n); break; + case Entity_Variable: map_set(&M_vars, e, n); break; + default: map_set(&M_other, e, n); break; } } TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 1"); // Calculate edges for graph M - for (auto const &entry : M) { + for (auto const &entry : M_procs) { EntityGraphNode *n = entry.value; Entity *e = n->entity; DeclInfo *decl = decl_info_of_entity(e); GB_ASSERT(decl != nullptr); - for (Entity *dep : decl->deps) { + FOR_PTR_SET(dep, decl->deps) { + GB_ASSERT(dep != nullptr); if (dep->flags & EntityFlag_Field) { continue; } - GB_ASSERT(dep != nullptr); - if (is_entity_a_dependency(dep)) { - EntityGraphNode *m = map_must_get(&M, dep); - entity_graph_node_set_add(&n->succ, m); - entity_graph_node_set_add(&m->pred, n); + if (!is_entity_a_dependency(dep)) { + continue; } + EntityGraphNode *m = nullptr; + + switch (dep->kind) { + case Entity_Procedure: m = map_must_get(&M_procs, dep); break; + case Entity_Variable: m = map_must_get(&M_vars, dep); break; + default: m = map_must_get(&M_other, dep); break; + } + entity_graph_node_set_add(&n->succ, m); + entity_graph_node_set_add(&m->pred, n); } } - TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 2"); - auto G = array_make(allocator, 0, M.count); + TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 2a (init)"); - for (auto const &m_entry : M) { - auto *e = m_entry.key; + auto G = array_make(arena_allocator(arena), 0, M_procs.count + M_vars.count + M_other.count); + + TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 2b (procs)"); + + for (auto const &m_entry : M_procs) { EntityGraphNode *n = m_entry.value; - if (e->kind == Entity_Procedure) { - // Connect each pred 'p' of 'n' with each succ 's' and from - // the procedure node - for (EntityGraphNode *p : n->pred) { - // Ignore self-cycles - if (p != n) { - // Each succ 's' of 'n' becomes a succ of 'p', and - // each pred 'p' of 'n' becomes a pred of 's' - for (EntityGraphNode *s : n->succ) { - // Ignore self-cycles - if (s != n) { - if (p->entity->kind == Entity_Procedure && - s->entity->kind == Entity_Procedure) { - // NOTE(bill, 2020-11-15): Only care about variable initialization ordering - // TODO(bill): This is probably wrong!!!! - continue; - } - // IMPORTANT NOTE/TODO(bill, 2020-11-15): These three calls take the majority of the - // the time to process - entity_graph_node_set_add(&p->succ, s); - entity_graph_node_set_add(&s->pred, p); - // Remove edge to 'n' - entity_graph_node_set_remove(&s->pred, n); - } - } - - // Remove edge to 'n' - entity_graph_node_set_remove(&p->succ, n); - } + // Connect each pred 'p' of 'n' with each succ 's' and from + // the procedure node + FOR_PTR_SET(p, n->pred) { + // Ignore self-cycles + if (p == n) { + continue; } - } else if (e->kind == Entity_Variable) { - array_add(&G, n); + // Each succ 's' of 'n' becomes a succ of 'p', and + // each pred 'p' of 'n' becomes a pred of 's' + FOR_PTR_SET(s, n->succ) { + // Ignore self-cycles + if (s == n) { + continue; + } + if (p->entity->kind == Entity_Procedure && + s->entity->kind == Entity_Procedure) { + // NOTE(bill, 2020-11-15): Only care about variable initialization ordering + // TODO(bill): This is probably wrong!!!! + continue; + } + // IMPORTANT NOTE/TODO(bill, 2020-11-15): These three calls take the majority of the + // the time to process + entity_graph_node_set_add(&p->succ, s); + entity_graph_node_set_add(&s->pred, p); + // Remove edge to 'n' + entity_graph_node_set_remove(&s->pred, n); + } + + // Remove edge to 'n' + entity_graph_node_set_remove(&p->succ, n); } } + TIME_SECTION("generate_entity_dependency_graph: Calculate edges for graph M - Part 2c (vars)"); + + for (auto const &m_entry : M_vars) { + EntityGraphNode *n = m_entry.value; + array_add(&G, n); + } + TIME_SECTION("generate_entity_dependency_graph: Dependency Count Checker"); for_array(i, G) { EntityGraphNode *n = G[i]; @@ -2958,7 +3368,9 @@ gb_internal void check_single_global_entity(Checker *c, Entity *e, DeclInfo *d); gb_internal Entity *find_core_entity(Checker *c, String name) { - Entity *e = scope_lookup_current(c->info.runtime_package->scope, name); + u32 hash = 0; + InternedString interned = string_interner_insert(name, 0, &hash); + Entity *e = scope_lookup_current(c->info.runtime_package->scope, interned, hash); if (e == nullptr) { compiler_error("Could not find type declaration for '%.*s'\n" , LIT(name)); @@ -2968,7 +3380,9 @@ gb_internal Entity *find_core_entity(Checker *c, String name) { } gb_internal Type *find_core_type(Checker *c, String name) { - Entity *e = scope_lookup_current(c->info.runtime_package->scope, name); + u32 hash = 0; + InternedString interned = string_interner_insert(name, 0, &hash); + Entity *e = scope_lookup_current(c->info.runtime_package->scope, interned, hash); if (e == nullptr) { compiler_error("Could not find type declaration for '%.*s'\n" , LIT(name)); @@ -2983,8 +3397,10 @@ gb_internal Type *find_core_type(Checker *c, String name) { gb_internal Entity *find_entity_in_pkg(CheckerInfo *info, String const &pkg, String const &name) { + u32 hash = 0; + InternedString interned = string_interner_insert(name, 0, &hash); AstPackage *package = get_core_package(info, pkg); - Entity *e = scope_lookup_current(package->scope, name); + Entity *e = scope_lookup_current(package->scope, interned, hash); if (e == nullptr) { compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name)); // NOTE(bill): This will exit the program as it's cannot continue without it! @@ -2993,8 +3409,10 @@ gb_internal Entity *find_entity_in_pkg(CheckerInfo *info, String const &pkg, Str } gb_internal Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String const &name) { + u32 hash = 0; + InternedString interned = string_interner_insert(name, 0, &hash); AstPackage *package = get_core_package(info, pkg); - Entity *e = scope_lookup_current(package->scope, name); + Entity *e = scope_lookup_current(package->scope, interned, hash); if (e == nullptr) { compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name)); // NOTE(bill): This will exit the program as it's cannot continue without it! @@ -3003,18 +3421,25 @@ gb_internal Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String return e->type; } +gb_internal gb_thread_local std::atomic *> checker_type_path_free_list; + gb_internal CheckerTypePath *new_checker_type_path() { - gbAllocator a = heap_allocator(); - auto *tp = gb_alloc_item(a, CheckerTypePath); - array_init(tp, a, 0, 16); - return tp; + // TODO(bill): Cache to reuse `CheckerTypePath + + auto *tp = atomic_freelist_get(checker_type_path_free_list); + if (tp == nullptr) { + tp = permanent_alloc_item >(); + array_init(&tp->value, permanent_allocator(), 0, 16); + } + return &tp->value; } -gb_internal void destroy_checker_type_path(CheckerTypePath *tp) { - array_free(tp); - gb_free(heap_allocator(), tp); -} +gb_internal void destroy_checker_type_path(CheckerTypePath *path) { + auto *tp = cast(AtomicFreelist *)path; + array_clear(&tp->value); + atomic_freelist_put(checker_type_path_free_list, tp); +} gb_internal void check_type_path_push(CheckerContext *c, Entity *e) { GB_ASSERT(c->type_path != nullptr); @@ -3074,6 +3499,9 @@ gb_internal void init_core_type_info(Checker *c) { GB_ASSERT(tis->fields.count == 5); + Entity *type_info_string_encoding_kind = find_core_entity(c, str_lit("Type_Info_String_Encoding_Kind")); + t_type_info_string_encoding_kind = type_info_string_encoding_kind->type; + Entity *type_info_variant = tis->fields[4]; Type *tiv_type = type_info_variant->type; GB_ASSERT(is_type_union(tiv_type)); @@ -3105,6 +3533,7 @@ gb_internal void init_core_type_info(Checker *c) { t_type_info_matrix = find_core_type(c, str_lit("Type_Info_Matrix")); t_type_info_soa_pointer = find_core_type(c, str_lit("Type_Info_Soa_Pointer")); t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); + t_type_info_fixed_capacity_dynamic_array = find_core_type(c, str_lit("Type_Info_Fixed_Capacity_Dynamic_Array")); t_type_info_named_ptr = alloc_type_pointer(t_type_info_named); t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer); @@ -3133,6 +3562,7 @@ gb_internal void init_core_type_info(Checker *c) { t_type_info_matrix_ptr = alloc_type_pointer(t_type_info_matrix); t_type_info_soa_pointer_ptr = alloc_type_pointer(t_type_info_soa_pointer); t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field); + t_type_info_fixed_capacity_dynamic_array_ptr = alloc_type_pointer(t_type_info_fixed_capacity_dynamic_array); } gb_internal void init_mem_allocator(Checker *c) { @@ -3184,19 +3614,33 @@ gb_internal void init_core_map_type(Checker *c) { t_raw_map_ptr = alloc_type_pointer(t_raw_map); } +gb_internal void init_core_objc_c(Checker *c) { + if (build_context.metrics.os == TargetOs_darwin) { + t_objc_super = find_core_type(c, str_lit("objc_super")); + t_objc_super_ptr = alloc_type_pointer(t_objc_super); + } +} + gb_internal void init_preload(Checker *c) { init_core_type_info(c); init_mem_allocator(c); init_core_context(c); init_core_source_code_location(c); init_core_map_type(c); + init_core_objc_c(c); } -gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) { +gb_internal void check_expr_with_type_hint(CheckerContext *c, Operand *o, Ast *e, Type *t); + +gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value, Type *type_hint = nullptr) { ExactValue ev = {}; if (value != nullptr) { Operand op = {}; - check_expr(c, &op, value); + if (type_hint != nullptr) { + check_expr_with_type_hint(c, &op, value, type_hint); + } else { + check_expr(c, &op, value); + } if (op.mode) { if (op.mode == Addressing_Constant) { ev = op.value; @@ -3208,6 +3652,52 @@ gb_internal ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) return ev; } +gb_internal bool is_foreign_name_valid(String const &name) { + if (name.len == 0) { + return false; + } + isize offset = 0; + while (offset < name.len) { + Rune rune; + isize remaining = name.len - offset; + isize width = utf8_decode(name.text+offset, remaining, &rune); + if (rune == GB_RUNE_INVALID && width == 1) { + return false; + } else if (rune == GB_RUNE_BOM && remaining > 0) { + return false; + } + + // TODO(bill, 2026-06-02): This entire logic needs to be completely figured out + // as to what should be allowed or not + // The original limitations of `-$._ +` and alphanumeric was more of an assumption + // than the actual technical limitations of all linkers. + if (offset == 0) { + switch (rune) { + case '-': + case '$': + case '.': + case '_': + case ':': + break; + default: + if (!gb_char_is_alpha(cast(char)rune)) + return false; + break; + } + } else { + int n = utf8proc_charwidth(rune); + if (n <= 0) { + // not a printable character + return false; + } + } + + offset += width; + } + + return true; +} + #define ATTRIBUTE_USER_TAG_NAME "tag" @@ -3348,7 +3838,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { return true; } else if (name == "test") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->test = true; return true; @@ -3396,13 +3886,13 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { return true; } else if (name == "init") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->init = true; return true; } else if (name == "fini") { if (value != nullptr) { - error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name)); + error(value, "Expected no value for '%.*s'", LIT(name)); } ac->fini = true; return true; @@ -3568,6 +4058,17 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { error(elem, "Expected a string value for '%.*s'", LIT(name)); } return true; + } else if (name == "link_section") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + ac->link_section = ev.value_string; + if (!is_foreign_name_valid(ac->link_section)) { + error(elem, "Invalid link section: %.*s", LIT(ac->link_section)); + } + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; } else if (name == "deprecated") { ExactValue ev = check_decl_attribute_value(c, value); @@ -3752,6 +4253,30 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } ac->no_sanitize_address = true; return true; + } else if (name == "no_sanitize_memory") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->no_sanitize_memory = true; + return true; + } else if (name == "no_sanitize_thread") { + if (value != nullptr) { + error(value, "'%.*s' expects no parameter", LIT(name)); + } + ac->no_sanitize_thread = true; + return true; + } else if (name == "fast_math") { + if (value == nullptr) { + error(elem, "Expected a constant bit_set of type 'intrinsics.Fast_Math_Flags' for '%.*s'", LIT(name)); + } else { + ExactValue ev = check_decl_attribute_value(c, value, t_fast_math_flags); + if (ev.kind != ExactValue_Integer) { + error(elem, "Expected a constant bit_set of type 'intrinsics.Fast_Math_Flags' for '%.*s'", LIT(name)); + } else { + ac->fast_math_flags = exact_value_to_u64(ev); + } + } + return true; } return false; } @@ -3788,6 +4313,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { } else if (ev.kind == ExactValue_String) { String model = ev.value_string; if (model == "default" || + model == "globaldynamic" || model == "localdynamic" || model == "initialexec" || model == "localexec") { @@ -3796,6 +4322,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { ERROR_BLOCK(); error(elem, "Invalid thread local model '%.*s'. Valid models:", LIT(model)); error_line("\tdefault\n"); + error_line("\tglobaldynamic\n"); error_line("\tlocaldynamic\n"); error_line("\tinitialexec\n"); error_line("\tlocalexec\n"); @@ -3917,6 +4444,7 @@ gb_internal DECL_ATTRIBUTE_PROC(const_decl_attribute) { name == "link_name" || name == "link_prefix" || name == "link_suffix" || + name == "rodata" || false) { error(elem, "@(%.*s) is not supported for compile time constant value declarations", LIT(name)); return true; @@ -3987,6 +4515,35 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) { return true; } + } else if (name == "raddbg_type_view") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->raddbg_type_view = true; + } else if (ev.kind == ExactValue_String) { + ac->raddbg_type_view = true; + ac->raddbg_type_view_string = ev.value_string; + + if (ev.value_string.len == 0) { + error(elem, "Expected a non-empty string for '%.*s'", LIT(name)); + } + } else { + error(elem, "Expected a string or no value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "deprecated") { + ExactValue ev = check_decl_attribute_value(c, value); + + if (ev.kind == ExactValue_String) { + String msg = ev.value_string; + if (msg.len == 0) { + error(elem, "Deprecation message cannot be an empty string"); + } else { + ac->deprecated_message = msg; + } + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; } return false; } @@ -4232,7 +4789,9 @@ gb_internal void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array< if (name == "builtin") { mutex_lock(&ctx->info->builtin_mutex); add_entity(ctx, builtin_pkg->scope, nullptr, e); - GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr); + auto interned = entity_interned_name(e); + u32 hash = e->interned_name_hash.load(); + GB_ASSERT(scope_lookup(builtin_pkg->scope, interned, hash) != nullptr); if (value != nullptr) { error(value, "'builtin' cannot have a field value"); } @@ -4574,9 +5133,9 @@ gb_internal bool correct_single_type_alias(CheckerContext *c, Entity *e) { gb_internal bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) { bool correction = false; for (u32 n = s->elements.count, i = n-1; i < n; i--) { - auto const &entry = s->elements.entries[i]; - Entity *e = entry.value; - if (entry.hash && e != nullptr) { + auto const &slot = s->elements.slots[i]; + Entity *e = slot.value; + if (slot.hash && e != nullptr) { correction |= correct_single_type_alias(c, e); } } @@ -4707,8 +5266,8 @@ gb_internal void check_collect_entities(CheckerContext *c, Slice const &n } gb_internal CheckerContext *create_checker_context(Checker *c) { - CheckerContext *ctx = gb_alloc_item(permanent_allocator(), CheckerContext); - *ctx = make_checker_context(c); + CheckerContext *ctx = permanent_alloc_item(); + init_checker_context(ctx, c); return ctx; } @@ -4746,7 +5305,7 @@ gb_internal void check_single_global_entity(Checker *c, Entity *e, DeclInfo *d) } gb_internal void check_all_global_entities(Checker *c) { - in_single_threaded_checker_stage = true; + in_single_threaded_checker_stage.store(true, std::memory_order_relaxed); // NOTE(bill): This must be single threaded // Don't bother trying @@ -4768,7 +5327,7 @@ gb_internal void check_all_global_entities(Checker *c) { } } - in_single_threaded_checker_stage = false; + in_single_threaded_checker_stage.store(false, std::memory_order_relaxed); } @@ -4857,26 +5416,22 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMapscope != nullptr); + AstPackage *child_pkg = *found; + GB_ASSERT(child_pkg->scope != nullptr); - id->package = pkg; + id->package = child_pkg; - ImportGraphNode **found_node = nullptr; - ImportGraphNode *m = nullptr; - ImportGraphNode *n = nullptr; - - found_node = map_get(M, pkg); + ImportGraphNode **found_node = map_get(M, child_pkg); GB_ASSERT(found_node != nullptr); - m = *found_node; + ImportGraphNode *child = *found_node; found_node = map_get(M, parent_pkg); GB_ASSERT(found_node != nullptr); - n = *found_node; + ImportGraphNode *parent = *found_node; - import_graph_node_set_add(&n->succ, m); - import_graph_node_set_add(&m->pred, n); - ptr_set_add(&m->scope->imported, n->scope); + import_graph_node_set_add(&parent->succ, child); + import_graph_node_set_add(&child->pred, parent); + ptr_set_add(&parent->scope->imported, child->scope); case_end; case_ast_node(ws, WhenStmt, decl); @@ -4906,14 +5461,14 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMap generate_import_dependency_graph(Checker *c) { +gb_internal Array generate_import_dependency_graph(Checker *c, gbAllocator allocator) { PtrMap M = {}; map_init(&M, 2*c->parser->packages.count); defer (map_destroy(&M)); for_array(i, c->parser->packages) { AstPackage *pkg = c->parser->packages[i]; - ImportGraphNode *n = import_graph_node_create(heap_allocator(), pkg); + ImportGraphNode *n = import_graph_node_create(allocator, pkg); map_set(&M, pkg, n); } @@ -4930,7 +5485,7 @@ gb_internal Array generate_import_dependency_graph(Checker *c } Array G = {}; - array_init(&G, heap_allocator(), 0, M.count); + array_init(&G, allocator, 0, M.count); isize i = 0; for (auto const &entry : M) { @@ -4949,7 +5504,7 @@ struct ImportPathItem { Ast * decl; }; -gb_internal Array find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet *visited) { +gb_internal Array find_import_path(Checker *c, AstPackage *start, AstPackage *end, PtrSet *visited, gbAllocator allocator) { Array empty_path = {}; if (ptr_set_update(visited, start)) { @@ -4983,11 +5538,11 @@ gb_internal Array find_import_path(Checker *c, AstPackage *start ImportPathItem item = {pkg, decl}; if (pkg == end) { - auto path = array_make(heap_allocator()); + auto path = array_make(allocator); array_add(&path, item); return path; } - auto next_path = find_import_path(c, pkg, end, visited); + auto next_path = find_import_path(c, pkg, end, visited, allocator); if (next_path.count > 0) { array_add(&next_path, item); return next_path; @@ -5067,9 +5622,10 @@ gb_internal void check_add_import_decl(CheckerContext *ctx, Ast *decl) { GB_ASSERT(scope->flags&ScopeFlag_Pkg); - if (ptr_set_update(&parent_scope->imported, scope)) { - // error(token, "Multiple import of the same file within this scope"); - } + ptr_set_add(&parent_scope->imported, scope); + // if (ptr_set_update(&parent_scope->imported, scope)) { + // // error(token, "Multiple import of the same file within this scope"); + // } String import_name = path_to_entity_name(id->import_name.string, id->fullpath, false); if (is_blank_ident(import_name)) { @@ -5156,7 +5712,8 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { } gb_internal void check_foreign_import_fullpaths(Checker *c) { - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); UntypedExprInfoMap untyped = {}; defer (map_destroy(&untyped)); @@ -5539,7 +6096,7 @@ gb_internal void check_collect_entities_all(Checker *c) { for (isize i = 0; i < thread_count; i++) { auto *wd = &collect_entity_worker_data[i]; wd->c = c; - wd->ctx = make_checker_context(c); + init_checker_context(&wd->ctx, c); map_init(&wd->untyped); } @@ -5580,7 +6137,7 @@ gb_internal void check_export_entities(Checker *c) { for (isize i = 0; i < thread_count; i++) { auto *wd = &collect_entity_worker_data[i]; map_clear(&wd->untyped); - wd->ctx = make_checker_context(c); + init_checker_context(&wd->ctx, c); } for (auto const &entry : c->info.packages) { @@ -5591,14 +6148,9 @@ gb_internal void check_export_entities(Checker *c) { } gb_internal void check_import_entities(Checker *c) { - Array dep_graph = generate_import_dependency_graph(c); - defer ({ - for_array(i, dep_graph) { - import_graph_node_destroy(dep_graph[i], heap_allocator()); - } - array_free(&dep_graph); - }); + TEMPORARY_ALLOCATOR_GUARD(); + Array dep_graph = generate_import_dependency_graph(c, temporary_allocator()); TIME_SECTION("check_import_entities - sort packages"); // NOTE(bill): Priority queue @@ -5608,8 +6160,7 @@ gb_internal void check_import_entities(Checker *c) { defer (ptr_set_destroy(&emitted)); Array package_order = {}; - array_init(&package_order, heap_allocator(), 0, c->parser->packages.count); - defer (array_free(&package_order)); + array_init(&package_order, temporary_allocator(), 0, c->parser->packages.count); while (pq.queue.count > 0) { ImportGraphNode *n = priority_queue_pop(&pq); @@ -5617,11 +6168,12 @@ gb_internal void check_import_entities(Checker *c) { AstPackage *pkg = n->pkg; if (n->dep_count > 0) { + TEMPORARY_ALLOCATOR_GUARD(); + PtrSet visited = {}; defer (ptr_set_destroy(&visited)); - auto path = find_import_path(c, pkg, pkg, &visited); - defer (array_free(&path)); + auto path = find_import_path(c, pkg, pkg, &visited, temporary_allocator()); if (path.count > 1) { ImportPathItem item = path[path.count-1]; @@ -5636,7 +6188,7 @@ gb_internal void check_import_entities(Checker *c) { } } - for (ImportGraphNode *p : n->pred) { + FOR_PTR_SET(p, n->pred) { p->dep_count = gb_max(p->dep_count-1, 0); priority_queue_fix(&pq, p->index); } @@ -5652,7 +6204,8 @@ gb_internal void check_import_entities(Checker *c) { } TIME_SECTION("check_import_entities - collect file decls"); - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); UntypedExprInfoMap untyped = {}; defer (map_destroy(&untyped)); @@ -5690,8 +6243,8 @@ gb_internal void check_import_entities(Checker *c) { } TIME_SECTION("check_import_entities - check delayed entities"); - for_array(i, package_order) { - ImportGraphNode *node = package_order[i]; + for (isize pkg_index = 0; pkg_index < package_order.count; pkg_index++) { + ImportGraphNode *node = package_order[pkg_index]; GB_ASSERT(node->scope->flags&ScopeFlag_Pkg); AstPackage *pkg = node->scope->pkg; @@ -5717,9 +6270,20 @@ gb_internal void check_import_entities(Checker *c) { reset_checker_context(&ctx, f, &untyped); ctx.collect_delayed_decls = true; + + bool will_recheck_foreign_block = false; for (Ast *decl : f->delayed_decls_queues[AstDelayQueue_ForeignBlock]) { - check_add_foreign_block_decl(&ctx, decl); + if (check_add_foreign_block_decl(&ctx, decl)) { + pkg_index -= 1; // Re-check package + will_recheck_foreign_block = true; + break; + } } + + if (will_recheck_foreign_block) { + break; + } + array_clear(&f->delayed_decls_queues[AstDelayQueue_ForeignBlock]); } @@ -5739,9 +6303,9 @@ gb_internal void check_import_entities(Checker *c) { } -gb_internal Array find_entity_path(Entity *start, Entity *end, PtrSet *visited = nullptr); +gb_internal Array find_entity_path(Entity *start, Entity *end, gbAllocator allocator, PtrSet *visited = nullptr); -gb_internal bool find_entity_path_tuple(Type *tuple, Entity *end, PtrSet *visited, Array *path_) { +gb_internal bool find_entity_path_tuple(Type *tuple, Entity *end, gbAllocator allocator, PtrSet *visited, Array *path_) { GB_ASSERT(path_ != nullptr); if (tuple == nullptr) { return false; @@ -5753,14 +6317,15 @@ gb_internal bool find_entity_path_tuple(Type *tuple, Entity *end, PtrSetdeps) { + + FOR_PTR_SET(dep, var_decl->deps) { if (dep == end) { - auto path = array_make(heap_allocator()); + auto path = array_make(allocator); array_add(&path, dep); *path_ = path; return true; } - auto next_path = find_entity_path(dep, end, visited); + auto next_path = find_entity_path(dep, end, allocator, visited); if (next_path.count > 0) { array_add(&next_path, dep); *path_ = next_path; @@ -5772,7 +6337,7 @@ gb_internal bool find_entity_path_tuple(Type *tuple, Entity *end, PtrSet find_entity_path(Entity *start, Entity *end, PtrSet *visited) { +gb_internal Array find_entity_path(Entity *start, Entity *end, gbAllocator allocator, PtrSet *visited) { PtrSet visited_ = {}; bool made_visited = false; if (visited == nullptr) { @@ -5796,20 +6361,20 @@ gb_internal Array find_entity_path(Entity *start, Entity *end, PtrSet< GB_ASSERT(t->kind == Type_Proc); Array path = {}; - if (find_entity_path_tuple(t->Proc.params, end, visited, &path)) { + if (find_entity_path_tuple(t->Proc.params, end, allocator, visited, &path)) { return path; } - if (find_entity_path_tuple(t->Proc.results, end, visited, &path)) { + if (find_entity_path_tuple(t->Proc.results, end, allocator, visited, &path)) { return path; } } else { - for (Entity *dep : decl->deps) { + FOR_PTR_SET(dep, decl->deps) { if (dep == end) { - auto path = array_make(heap_allocator()); + auto path = array_make(allocator); array_add(&path, dep); return path; } - auto next_path = find_entity_path(dep, end, visited); + auto next_path = find_entity_path(dep, end, allocator, visited); if (next_path.count > 0) { array_add(&next_path, dep); return next_path; @@ -5825,13 +6390,10 @@ gb_internal void calculate_global_init_order(Checker *c) { CheckerInfo *info = &c->info; TIME_SECTION("calculate_global_init_order: generate entity dependency graph"); - Array dep_graph = generate_entity_dependency_graph(info, heap_allocator()); - defer ({ - for_array(i, dep_graph) { - entity_graph_node_destroy(dep_graph[i], heap_allocator()); - } - array_free(&dep_graph); - }); + Arena *temporary_arena = get_arena(ThreadArena_Temporary); + ArenaTempGuard temporary_arena_guard(temporary_arena); + + Array dep_graph = generate_entity_dependency_graph(info, temporary_arena); TIME_SECTION("calculate_global_init_order: priority queue create"); // NOTE(bill): Priority queue @@ -5846,8 +6408,8 @@ gb_internal void calculate_global_init_order(Checker *c) { Entity *e = n->entity; if (n->dep_count > 0) { - auto path = find_entity_path(e, e); - defer (array_free(&path)); + TEMPORARY_ALLOCATOR_GUARD(); + auto path = find_entity_path(e, e, temporary_allocator()); if (path.count > 0) { Entity *e = path[0]; @@ -5860,7 +6422,7 @@ gb_internal void calculate_global_init_order(Checker *c) { } } - for (EntityGraphNode *p : n->pred) { + FOR_PTR_SET(p, n->pred) { p->dep_count -= 1; p->dep_count = gb_max(p->dep_count, 0); priority_queue_fix(&pq, p->index); @@ -5927,7 +6489,7 @@ gb_internal void check_procedure_later_from_entity(Checker *c, Entity *e, char c GB_ASSERT(e->decl_info != nullptr); - ProcInfo *pi = gb_alloc_item(permanent_allocator(), ProcInfo); + ProcInfo *pi = permanent_alloc_item(); pi->file = e->file; pi->token = e->token; pi->decl = e->decl_info; @@ -5964,7 +6526,7 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u switch (pi->decl->proc_checked_state.load()) { case ProcCheckedState_InProgress: if (e) { - GB_ASSERT(global_procedure_body_in_worker_queue.load()); + GB_ASSERT(global_procedure_body_in_worker_queue.load() != 0); } return false; case ProcCheckedState_Checked: @@ -6003,7 +6565,8 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u } } - CheckerContext ctx = make_checker_context(c); + CheckerContext ctx = {}; + init_checker_context(&ctx, c); defer (destroy_checker_context(&ctx)); reset_checker_context(&ctx, pi->file, untyped); ctx.decl = pi->decl; @@ -6053,7 +6616,7 @@ gb_internal bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *u add_untyped_expressions(&c->info, ctx.untyped); rw_mutex_shared_lock(&ctx.decl->deps_mutex); - for (Entity *dep : ctx.decl->deps) { + FOR_PTR_SET(dep, ctx.decl->deps) { if (dep && dep->kind == Entity_Procedure && (dep->flags & EntityFlag_ProcBodyChecked) == 0) { check_procedure_later_from_entity(c, dep, NULL); @@ -6082,8 +6645,10 @@ gb_internal void check_unchecked_bodies(Checker *c) { // use the `procs_to_check` array global_procedure_body_in_worker_queue = false; - for (Entity *e : c->info.minimum_dependency_set) { - check_procedure_later_from_entity(c, e, "check_unchecked_bodies"); + for (Entity *e : c->info.entities) { + if (e->min_dep_count.load(std::memory_order_relaxed) > 0) { + check_procedure_later_from_entity(c, e, "check_unchecked_bodies"); + } } if (!global_procedure_body_in_worker_queue) { @@ -6106,8 +6671,9 @@ gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) { defer (map_destroy(&untyped)); - for_array(i, c->info.all_procedures) { - ProcInfo *pi = c->info.all_procedures[i]; + array_reserve(&c->info.all_procedures, c->info.all_procedures_queue.count.load()); + + for (ProcInfo *pi = nullptr; mpsc_dequeue(&c->info.all_procedures_queue, &pi); /**/) { GB_ASSERT(pi != nullptr); GB_ASSERT(pi->decl != nullptr); Entity *e = pi->decl->entity; @@ -6122,6 +6688,8 @@ gb_internal void check_safety_all_procedures_for_unchecked(Checker *c) { consume_proc_info(c, pi, &untyped); } } + + array_add(&c->info.all_procedures, pi); } } @@ -6216,7 +6784,7 @@ gb_internal WORKER_TASK_PROC(check_proc_info_worker_proc) { gb_internal void check_init_worker_data(Checker *c) { u32 thread_count = cast(u32)global_thread_pool.threads.count; - check_procedure_bodies_worker_data = gb_alloc_array(permanent_allocator(), CheckProcedureBodyWorkerData, thread_count); + check_procedure_bodies_worker_data = permanent_alloc_array(thread_count); for (isize i = 0; i < thread_count; i++) { check_procedure_bodies_worker_data[i].c = c; @@ -6278,7 +6846,7 @@ gb_internal Type *tuple_to_pointers(Type *ot) { Type *t = alloc_type_tuple(); - t->Tuple.variables = slice_make(heap_allocator(), ot->Tuple.variables.count); + t->Tuple.variables = permanent_slice_make(ot->Tuple.variables.count); Scope *scope = nullptr; for_array(i, t->Tuple.variables) { @@ -6320,7 +6888,16 @@ gb_internal void check_deferred_procedures(Checker *c) { continue; } - GB_ASSERT(is_type_proc(src->type)); + if (dst->flags & EntityFlag_Disabled) { + // Prevent procedures that have been disabled from acting as deferrals. + src->Procedure.deferred_procedure = {}; + continue; + } + + if (!is_type_proc(src->type)) { + error(src->token, "Invalid procedure type found during deferred procedure checking"); + continue; + } GB_ASSERT(is_type_proc(dst->type)); Type *src_params = base_type(src->type)->Proc.params; Type *src_results = base_type(src->type)->Proc.results; @@ -6475,6 +7052,271 @@ gb_internal void check_deferred_procedures(Checker *c) { } +gb_internal void handle_raddbg_type_view(Checker *c, RaddbgTypeView const &type_view) { + auto const struct_tag_lookup = [](String tag, char const *key_c, String *value_) -> bool { + String t = tag; + String key = make_string_c(key_c); + while (t.len != 0) { + isize i = 0; + while (i < t.len && t[i] == ' ') { // Skip whitespace + i += 1; + } + t.text += i; + t.len -= i; + if (t.len == 0) { + break; + } + + i = 0; + + while (i < t.len) { + u8 c = t[i]; + if (c == ':' || c == '"') { + break; + } else if ((0 <= c && c < ' ') || (0x7f <= c && c <= 0x9f)) { + // break if control character is found + break; + } + i += 1; + } + + if (i == 0) { + break; + } + if (i+1 >= t.len) { + break; + } + if (t[i] != ':' || t[i+1] != '"') { + break; + } + String name = {t.text, i}; + t = {t.text+i+1, t.len-(i+1)}; + + i = 1; + while (i < t.len && t[i] != '"') { // find closing quote + if (t[i] == '\\') { + i += 1; // Skip escaped characters + } + i += 1; + } + if (i >= t.len) { + break; + } + + String value = {t.text, i+1}; + t = {t.text+i+1, t.len-(i+1)}; + + if (key == name) { + value = {value.text+1, i-1}; + value = string_trim_whitespace(value); + if (value_) *value_ = value; + return true; + } + } + return false; + }; + + auto const parse_int = [](String s, isize *offset_, u64 *result_) -> bool { + isize offset = *offset_; + isize new_offset = *offset_; + + u64 result = 0; + + while (new_offset < s.len) { + u8 c = s[new_offset]; + if (!('0' <= c && c <= '9')) { + break; + } + + new_offset += 1; + result *= 10; + result += u64(c)-'0'; + } + + *offset_ = new_offset; + *result_ = result; + return new_offset > offset; + }; + + Type *type = type_view.type; + if (type == nullptr || type == t_invalid) { + return; + } + String view = type_view.view; + if (view.len != 0) { + array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); + return; + } + + // NOTE(bill): Generate one automatically from the struct field tags if they exist + // If it cannot be generated, it'll be ignored/err + + Type *bt = base_type(type); + if (is_type_struct(type)) { + GB_ASSERT(bt->kind == Type_Struct); + if (bt->Struct.tags != nullptr) { + bool found_any = false; + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + String tag = bt->Struct.tags[i]; + String value = {}; + if (struct_tag_lookup(tag, "raddbg", &value)) { + found_any = true; + } else if (struct_tag_lookup(tag, "fmt", &value)) { + found_any = true; + } + } + + if (!found_any) { + return; + } + + gbString s = gb_string_make(heap_allocator(), ""); + + s = gb_string_appendc(s, "rows($"); + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + Entity *field = bt->Struct.fields[i]; + GB_ASSERT(field != nullptr); + String name = field->token.string; + String tag = bt->Struct.tags[i]; + String value = {}; + bool custom_rule = false; + + bool raddbg_seen = false; + if (struct_tag_lookup(tag, "raddbg", &value)) { + raddbg_seen = true; + if (value == "-") { + // Ignore this field entirely; + continue; + } + } + + s = gb_string_appendc(s, ", "); + + if (raddbg_seen) { + if (value == "") { + // ignore + } else { + s = gb_string_append_length(s, value.text, value.len); + custom_rule = true; + } + } else if (struct_tag_lookup(tag, "fmt", &value)) { + if (value == "" || value == "-") { + // ignore + } else { + auto p = string_partition(value, make_string_c(",")); + String head = p.head; + String tail = p.tail; + + isize i = 0; + + for (bool ok = true; ok && i < head.len; i += 1) { + switch (head[i]) { + case '+': + case '-': + case ' ': + case '#': + case '0': + break; + default: + i -= 1; + ok = false; + break; + } + } + + u64 prec = 0; + u64 width = 0; + bool width_ok = parse_int(head, &i, &width); + bool prec_ok = false; + if (i < head.len && head[i] == '.') { + i += 1; + prec_ok = parse_int(head, &i, &prec); + } + + + Rune verb = 0; + if (i >= head.len || head[i] == ' ') { + verb = 'v'; + } else { + utf8_decode(head.text+i, head.len-i, &verb); + } + + isize paren_count = 0; + + + if (width_ok) { + s = gb_string_appendc(s, "digits("); + custom_rule = true; + } + + switch (verb) { + case 'b': + s = gb_string_appendc(s, "bin("); + paren_count += 1; + break; + case 'd': + s = gb_string_appendc(s, "dec("); + paren_count += 1; + break; + case 'x': + case 'X': + s = gb_string_appendc(s, "hex("); + paren_count += 1; + break; + case 'o': + s = gb_string_appendc(s, "oct("); + paren_count += 1; + break; + } + + + if (tail.len != 0 && tail != "0") { + s = gb_string_appendc(s, "array("); + s = gb_string_append_length(s, name.text, name.len); + if (is_type_slice(field->type) || is_type_dynamic_array(field->type)) { + s = gb_string_appendc(s, ".data"); + } + s = gb_string_appendc(s, ", "); + s = gb_string_append_length(s, tail.text, tail.len); + s = gb_string_appendc(s, ")"); + custom_rule = true; + } else { + s = gb_string_append_length(s, name.text, name.len); + custom_rule = true; + } + + + for (isize j = 0; j < paren_count; j++) { + s = gb_string_appendc(s, ")"); + custom_rule = true; + } + if (width_ok) { + s = gb_string_append_fmt(s, ", %llu)", cast(unsigned long long)width); + } + } + } + + if (!custom_rule) { + s = gb_string_append_length(s, name.text, name.len); + } + } + + s = gb_string_appendc(s, ")"); + + view = make_string((u8 const *)s, gb_string_length(s)); + } + } + + if (view.len == 0) { + // Ignore the type, it didn't anything custom + return; + } + + array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); +} + gb_internal void check_objc_context_provider_procedures(Checker *c) { for (Entity *e = nullptr; mpsc_dequeue(&c->procs_with_objc_context_provider_to_check, &e); /**/) { GB_ASSERT(e->kind == Entity_TypeName); @@ -6513,9 +7355,11 @@ gb_internal void check_objc_context_provider_procedures(Checker *c) { } } -gb_internal void check_unique_package_names(Checker *c) { +gb_internal bool check_unique_package_names(Checker *c) { ERROR_BLOCK(); + bool ok = true; + StringMap pkgs = {}; // Key: package name string_map_init(&pkgs, 2*c->info.packages.count); defer (string_map_destroy(&pkgs)); @@ -6540,6 +7384,7 @@ gb_internal void check_unique_package_names(Checker *c) { continue; } + ok = false; begin_error_block(); error(curr, "Duplicate declaration of 'package %.*s'", LIT(name)); @@ -6562,6 +7407,8 @@ gb_internal void check_unique_package_names(Checker *c) { end_error_block(); } + + return ok; } gb_internal void check_add_entities_from_queues(Checker *c) { @@ -6586,6 +7433,7 @@ gb_internal void check_merge_queues_into_arrays(Checker *c) { } check_add_entities_from_queues(c); check_add_definitions_from_queues(c); + thread_pool_wait(); } gb_internal GB_COMPARE_PROC(init_procedures_cmp) { @@ -6640,17 +7488,23 @@ gb_internal void check_sort_init_and_fini_procedures(Checker *c) { } gb_internal void add_type_info_for_type_definitions(Checker *c) { - for_array(i, c->info.definitions) { - Entity *e = c->info.definitions[i]; - if (e->kind == Entity_TypeName && e->type != nullptr) { + for (Entity *e : c->info.definitions) { + if (e->kind == Entity_TypeName && e->type != nullptr && is_type_typed(e->type)) { + #if 0 i64 align = type_align_of(e->type); - if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { + if (align > 0 && e->min_dep_count.load(std::memory_order_relaxed) > 0) { add_type_info_type(&c->builtin_ctx, e->type); } + #else + if (e->min_dep_count.load(std::memory_order_relaxed) > 0) { + add_type_info_type(&c->builtin_ctx, e->type); + } + #endif } } } +#if 0 gb_internal void check_walk_all_dependencies(DeclInfo *decl) { if (decl == nullptr) { return; @@ -6672,9 +7526,116 @@ gb_internal void check_update_dependency_tree_for_procedures(Checker *c) { check_walk_all_dependencies(decl); } } +#else +gb_internal void check_walk_all_dependencies(DeclInfo *decl); + +gb_internal WORKER_TASK_PROC(check_walk_all_dependencies_worker_proc) { + if (data == nullptr) { + return 0; + } + DeclInfo *decl = cast(DeclInfo *)data; + + for (DeclInfo *child = decl->next_child; child != nullptr; child = child->next_sibling) { + thread_pool_add_task(check_walk_all_dependencies_worker_proc, child); + check_walk_all_dependencies(child); + } + + add_deps_from_child_to_parent(decl); + return 0; +} + +gb_internal void check_walk_all_dependencies(DeclInfo *decl) { + if (decl != nullptr) { + thread_pool_add_task(check_walk_all_dependencies_worker_proc, decl); + } +} + +gb_internal void check_update_dependency_tree_for_procedures(Checker *c) { + mutex_lock(&c->nested_proc_lits_mutex); + for (DeclInfo *decl : c->nested_proc_lits) { + check_walk_all_dependencies(decl); + } + mutex_unlock(&c->nested_proc_lits_mutex); + for (Entity *e : c->info.entities) { + DeclInfo *decl = e->decl_info; + check_walk_all_dependencies(decl); + } + + thread_pool_wait(); +} +#endif + +gb_internal WORKER_TASK_PROC(check_scope_usage_file_worker) { + Checker *c = global_checker_ptr.load(std::memory_order_relaxed); + AstFile *f = cast(AstFile *)data; + u64 vet_flags = ast_file_vet_flags(f); + check_scope_usage(c, f->scope, vet_flags); + return 0; +} + +gb_internal WORKER_TASK_PROC(check_scope_usage_pkg_worker) { + Checker *c = global_checker_ptr.load(std::memory_order_relaxed); + AstPackage *pkg = cast(AstPackage *)data; + check_scope_usage_internal(c, pkg->scope, 0, true); + return 0; +} + + + +gb_internal void check_all_scope_usages(Checker *c) { + for (auto const &entry : c->info.files) { + AstFile *f = entry.value; + thread_pool_add_task(check_scope_usage_file_worker, f); + } + for (auto const &entry : c->info.packages) { + AstPackage *pkg = entry.value; + thread_pool_add_task(check_scope_usage_pkg_worker, pkg); + } + + thread_pool_wait(); +} + + +gb_internal void check_for_type_cycles(Checker *c) { + // NOTE(bill): Check for illegal cyclic type declarations + for_array(i, c->info.definitions) { + Entity *e = c->info.definitions[i]; + if (e->kind != Entity_TypeName) { + continue; + } + if (e->type != nullptr && is_type_typed(e->type)) { + if (e->TypeName.is_type_alias) { + // Ignore for the time being + } else { + (void)type_align_of(e->type); + } + } + } +} + +gb_internal void check_for_inline_cycles(Checker *c) { + for_array(i, c->info.definitions) { + Entity *e = c->info.definitions[i]; + if (e->kind != Entity_Procedure) { + continue; + } + DeclInfo *decl = e->decl_info; + ast_node(pl, ProcLit, decl->proc_lit); + if (pl->inlining == ProcInlining_inline) { + FOR_PTR_SET(dep, decl->deps) { + if (dep == e) { + error(e->token, "Cannot inline recursive procedure '%.*s'", LIT(e->token.string)); + break; + } + } + } + } +} gb_internal void check_parsed_files(Checker *c) { + global_checker_ptr.store(c, std::memory_order_relaxed); + TIME_SECTION("map full filepaths to scope"); add_type_info_type(&c->builtin_ctx, t_invalid); @@ -6738,16 +7699,9 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("add entities from procedure bodies"); check_merge_queues_into_arrays(c); - TIME_SECTION("check scope usage"); - for (auto const &entry : c->info.files) { - AstFile *f = entry.value; - u64 vet_flags = ast_file_vet_flags(f); - check_scope_usage(c, f->scope, vet_flags); - } - for (auto const &entry : c->info.packages) { - AstPackage *pkg = entry.value; - check_scope_usage_internal(c, pkg->scope, 0, true); - } + TIME_SECTION("check all scope usages"); + check_all_scope_usages(c); + TIME_SECTION("add basic type information"); // Add "Basic" type information @@ -6755,30 +7709,24 @@ gb_internal void check_parsed_files(Checker *c) { Type *t = &basic_types[i]; if (t->Basic.size > 0 && (t->Basic.flags & BasicFlag_LLVM) == 0) { + if (build_context.bedrock) { + if ((t->Basic.flags & BasicFlag_Integer) != 0 && + t->Basic.size == 16) { + // disallow 128-bit integers + continue; + } + } + add_type_info_type(&c->builtin_ctx, t); } } check_merge_queues_into_arrays(c); - TIME_SECTION("check for type cycles and inline cycles"); - // NOTE(bill): Check for illegal cyclic type declarations - for_array(i, c->info.definitions) { - Entity *e = c->info.definitions[i]; - if (e->kind == Entity_TypeName && e->type != nullptr) { - (void)type_align_of(e->type); - } else if (e->kind == Entity_Procedure) { - DeclInfo *decl = e->decl_info; - ast_node(pl, ProcLit, decl->proc_lit); - if (pl->inlining == ProcInlining_inline) { - for (Entity *dep : decl->deps) { - if (dep == e) { - error(e->token, "Cannot inline recursive procedure '%.*s'", LIT(e->token.string)); - break; - } - } - } - } - } + TIME_SECTION("check for type cycles"); + check_for_type_cycles(c); + + TIME_SECTION("check for inline cycles"); + check_for_inline_cycles(c); TIME_SECTION("check deferred procedures"); check_deferred_procedures(c); @@ -6803,11 +7751,9 @@ gb_internal void check_parsed_files(Checker *c) { check_unchecked_bodies(c); TIME_SECTION("check #soa types"); - check_merge_queues_into_arrays(c); - thread_pool_wait(); - TIME_SECTION("update minimum dependency set"); + TIME_SECTION("update minimum dependency set again"); generate_minimum_dependency_set_internal(c, c->info.entry_point); // NOTE(laytan): has to be ran after generate_minimum_dependency_set, @@ -6823,7 +7769,7 @@ gb_internal void check_parsed_files(Checker *c) { Scope *s = c->info.init_scope; GB_ASSERT(s != nullptr); GB_ASSERT(s->flags&ScopeFlag_Init); - Entity *e = scope_lookup_current(s, str_lit("main")); + Entity *e = scope_lookup_current(s, string_interner_insert(str_lit("main"))); if (e == nullptr) { Token token = {}; token.pos.file_id = 0; @@ -6853,7 +7799,7 @@ gb_internal void check_parsed_files(Checker *c) { debugf("Total Procedure Bodies Checked: %td\n", total_bodies_checked.load(std::memory_order_relaxed)); TIME_SECTION("check unique package names"); - check_unique_package_names(c); + bool package_names_are_unique = check_unique_package_names(c); TIME_SECTION("sanity checks"); check_merge_queues_into_arrays(c); @@ -6872,7 +7818,6 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("add untyped expression values"); - // Add untyped expression values for (UntypedExprInfo u = {}; mpsc_dequeue(&c->global_untyped_queue, &u); /**/) { GB_ASSERT(u.expr != nullptr && u.info != nullptr); if (is_type_typed(u.info->type)) { @@ -6883,9 +7828,10 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("initialize and check for collisions in type info array"); { + TEMPORARY_ALLOCATOR_GUARD(); + Array type_info_types; // sorted after filled - array_init(&type_info_types, heap_allocator()); - defer (array_free(&type_info_types)); + array_init(&type_info_types, temporary_allocator()); for (auto const &tt : c->info.min_dep_type_info_set) { array_add(&type_info_types, tt); @@ -6910,12 +7856,13 @@ gb_internal void check_parsed_files(Checker *c) { c->info.type_info_types_hash_map[index] = tt; bool exists = map_set_if_not_previously_exists(&c->info.min_dep_type_info_index_map, tt.hash, index); - if (exists) { + // Because we've already written a nice error about a duplicate package declaration, skip this panic if the package names aren't unique. + if (package_names_are_unique && exists) { for (auto const &entry : c->info.min_dep_type_info_index_map) { if (entry.key != tt.hash) { continue; } - auto const &other = type_info_types[entry.value]; + auto const &other = c->info.type_info_types_hash_map[entry.value]; if (are_types_identical_unique_tuples(tt.type, other.type)) { continue; } @@ -6948,6 +7895,11 @@ gb_internal void check_parsed_files(Checker *c) { } } + TIME_SECTION("collate type info stuff"); + for (RaddbgTypeView type_view; mpsc_dequeue(&c->info.raddbg_type_views_queue, &type_view); /**/) { + handle_raddbg_type_view(c, type_view); + } + TIME_SECTION("type check finish"); } diff --git a/src/checker.hpp b/src/checker.hpp index 0cdfd69ab..cd2e580d8 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -140,6 +140,8 @@ struct AttributeContext { bool instrumentation_enter : 1; bool instrumentation_exit : 1; bool no_sanitize_address : 1; + bool no_sanitize_memory : 1; + bool no_sanitize_thread : 1; bool rodata : 1; bool ignore_duplicates : 1; u32 optimization_mode; // ProcedureOptimizationMode @@ -160,6 +162,11 @@ struct AttributeContext { String require_target_feature; // required by the target micro-architecture String enable_target_feature; // will be enabled for the procedure only + + u64 fast_math_flags; + + bool raddbg_type_view; + String raddbg_type_view_string; }; gb_internal gb_inline AttributeContext make_attribute_context(String link_prefix, String link_suffix) { @@ -205,7 +212,7 @@ struct DeclInfo { Scope * scope; - Entity *entity; + std::atomic entity; Ast * decl_node; Ast * type_expr; @@ -214,14 +221,16 @@ struct DeclInfo { Ast * proc_lit; // Ast_ProcLit Type * gen_proc_type; // Precalculated - bool is_using; - bool where_clauses_evaluated; - bool foreign_require_results; + Entity * para_poly_original; + + bool is_using; + bool foreign_require_results; + std::atomic where_clauses_evaluated; std::atomic proc_checked_state; - BlockingMutex proc_checked_mutex; - isize defer_used; - bool defer_use_checked; + BlockingMutex proc_checked_mutex; + isize defer_used; + std::atomic defer_use_checked; CommentGroup *comment; CommentGroup *docs; @@ -243,7 +252,7 @@ struct DeclInfo { i64 variadic_reuse_max_align; // NOTE(bill): this is to prevent a race condition since these procedure literals can be created anywhere at any time - struct lbModule *code_gen_module; + std::atomic code_gen_module; }; // ProcInfo stores the information needed for checking a procedure @@ -259,6 +268,264 @@ struct ProcInfo { }; +enum { DEFAULT_SCOPE_CAPACITY = 32 }; + + +struct ScopeMapSlot { + u32 hash; + u32 _pad; + Entity *value; +}; + +enum { SCOPE_MAP_INLINE_CAP = 16 }; + +struct ScopeMap { + InternedString inline_keys [SCOPE_MAP_INLINE_CAP]; + ScopeMapSlot inline_slots[SCOPE_MAP_INLINE_CAP]; + InternedString *keys; + ScopeMapSlot * slots; + u32 count; + u32 cap; +}; + +gb_internal gb_inline u32 scope_map_max_load(u32 cap) { + return cap - (cap>>2); // 75% +} + +gb_internal gb_inline void scope_map_init(ScopeMap *m) { + m->cap = SCOPE_MAP_INLINE_CAP; + m->slots = m->inline_slots; + m->keys = m->inline_keys; +} + + +gb_internal Entity *scope_map_insert_for_rehash( + InternedString *keys, ScopeMapSlot *slots, u32 mask, + InternedString key, u32 hash, Entity *value) { + u32 pos = hash & mask; + u32 dist = 0; + + for (;;) { + ScopeMapSlot *s = &slots[pos]; + + if (s->hash == 0) { + keys[pos] = key; + s->hash = hash; + s->value = value; + return nullptr; + } + + u32 existing_dist = (pos - s->hash) & mask; + + if (dist > existing_dist) { + auto tmp_key = keys[pos]; + u32 tmp_hash = s->hash; + Entity *tmp_value = s->value; + + keys[pos] = key; + s->hash = hash; + s->value = value; + + hash = tmp_hash; + value = tmp_value; + key = tmp_key; + dist = existing_dist; + } + + dist += 1; + pos = (pos+1) & mask; + } +} + +gb_internal gb_inline void scope_map_allocate_entries(u32 cap, InternedString **keys, ScopeMapSlot **slots) { + Arena *arena = get_arena(ThreadArena_Permanent); + isize size = (gb_size_of(InternedString) + gb_size_of(ScopeMapSlot)) * cap; + u8 *data = cast(u8 *)arena_alloc(arena, size, 8); + + *keys = cast(InternedString *)data; + *slots = cast(ScopeMapSlot *)(*keys + cap); + + // *keys = permanent_alloc_array(cap); + // *slots = permanent_alloc_array(cap); +} + + +gb_internal void scope_map_grow(ScopeMap *m) { + u32 new_cap = m->cap << 1; + u32 new_mask = new_cap - 1; + + InternedString *new_keys; + ScopeMapSlot * new_slots; + scope_map_allocate_entries(new_cap, &new_keys, &new_slots); + + if (m->count > 0) { + for (u32 i = 0; i < m->cap; i++) { + if (m->slots[i].hash) { + scope_map_insert_for_rehash(new_keys, new_slots, new_mask, + m->keys[i], m->slots[i].hash, m->slots[i].value); + } + } + } + + m->slots = new_slots; + m->keys = new_keys; + m->cap = new_cap; +} + +gb_internal void scope_map_reserve(ScopeMap *m, isize capacity) { + if (m->slots == nullptr) { + scope_map_init(m); + } + u32 new_cap = next_pow2_u32(cast(u32)capacity); + if (m->cap < new_cap && new_cap > SCOPE_MAP_INLINE_CAP) { + scope_map_allocate_entries(new_cap, &m->keys, &m->slots); + m->cap = new_cap; + } +} + + + +gb_internal Entity *scope_map_insert(ScopeMap *m, InternedString key, u32 hash, Entity *value) { + if (m->slots == nullptr) { + scope_map_init(m); + } + if (m->count >= scope_map_max_load(m->cap)) { + scope_map_grow(m); + } + + u32 mask = m->cap-1; + u32 pos = hash & mask; + u32 dist = 0; + + for (;;) { + ScopeMapSlot *s = &m->slots[pos]; + + if (s->hash == 0) { + m->keys[pos] = key; + s->hash = hash; + s->value = value; + m->count += 1; + return nullptr; + } + + if (s->hash == hash && m->keys[pos] == key) { + Entity *old = s->value; + s->value = value; + return old; + } + + u32 existing_dist = (pos - s->hash) & mask; + + if (dist > existing_dist) { + auto tmp_key = m->keys[pos]; + u32 tmp_hash = s->hash; + Entity *tmp_value = s->value; + + m->keys[pos] = key; + s->hash = hash; + s->value = value; + + key = tmp_key; + hash = tmp_hash; + value = tmp_value; + dist = existing_dist; + } + + dist += 1; + pos = (pos+1) & mask; + } +} + +gb_internal Entity *scope_map_get(ScopeMap *m, InternedString key, u32 hash) { + u32 mask = m->cap-1; + u32 pos = hash & mask; + u32 dist = 0; + for (;;) { + ScopeMapSlot *s = &m->slots[pos]; + u32 curr_hash = s->hash; + if (curr_hash == 0) { + return nullptr; + } + + u32 existing_dist = (pos - curr_hash) & mask; + if (dist > existing_dist) { + return nullptr; + } + if (curr_hash == hash && m->keys[pos] == key) { + return s->value; + } + + dist += 1; + pos = (pos + 1) & mask; + } +} + +gb_internal void scope_map_clear(ScopeMap *m) { + gb_memset(m->slots, 0, gb_size_of(*m->slots) * m->cap); + m->count = 0; +} + +struct ScopeMapIterator { + ScopeMap const *map; + u32 index; + + ScopeMapIterator &operator++() noexcept { + for (;;) { + ++index; + if (map->cap == index) { + return *this; + } + ScopeMapSlot *s = map->slots+index; + if (s->hash) { + return *this; + } + } + } + + bool operator==(ScopeMapIterator const &other) const noexcept { + return this->map == other.map && this->index == other.index; + } + + operator ScopeMapSlot *() const { + return map->slots+index; + } +}; + + +gb_internal ScopeMapIterator end(ScopeMap &m) noexcept { + return ScopeMapIterator{&m, m.cap}; +} +gb_internal ScopeMapIterator const end(ScopeMap const &m) noexcept { + return ScopeMapIterator{&m, m.cap}; +} +gb_internal ScopeMapIterator begin(ScopeMap &m) noexcept { + if (m.count == 0) { + return end(m); + } + + u32 index = 0; + while (index < m.cap) { + if (m.slots[index].hash) { + break; + } + index++; + } + return ScopeMapIterator{&m, index}; +} +gb_internal ScopeMapIterator const begin(ScopeMap const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + u32 index = 0; + while (index < m.cap) { + if (m.slots[index].hash) { + break; + } + index++; + } + return ScopeMapIterator{&m, index}; +} enum ScopeFlag : i32 { ScopeFlag_Pkg = 1<<1, @@ -274,7 +541,6 @@ enum ScopeFlag : i32 { ScopeFlag_ContextDefined = 1<<16, }; -enum { DEFAULT_SCOPE_CAPACITY = 32 }; struct Scope { Ast * node; @@ -285,7 +551,7 @@ struct Scope { i32 index; // within a procedure RwMutex mutex; - StringMap elements; + ScopeMap elements; PtrSet imported; DeclInfo *decl_info; @@ -305,11 +571,12 @@ struct EntityGraphNode; typedef PtrSet EntityGraphNodeSet; struct EntityGraphNode { - Entity * entity; // Procedure, Variable, Constant + Entity *entity; // Procedure, Variable, Constant + EntityGraphNodeSet pred; EntityGraphNodeSet succ; - isize index; // Index in array/queue - isize dep_count; + isize index; // Index in array/queue + isize dep_count; }; @@ -426,6 +693,11 @@ struct Defineable { String pos_str; }; +struct RaddbgTypeView { + Type * type; + String view; +}; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Checker *checker; @@ -439,9 +711,11 @@ struct CheckerInfo { AstPackage * init_package; Scope * init_scope; Entity * entry_point; - PtrSet minimum_dependency_set; - BlockingMutex minimum_dependency_type_info_mutex; + + RwMutex minimum_dependency_type_info_mutex; PtrMap min_dep_type_info_index_map; + + RWSpinLock min_dep_type_info_set_mutex; TypeSet min_dep_type_info_set; Array type_info_types_hash_map; // 2 * type_info_types.count @@ -468,8 +742,6 @@ struct CheckerInfo { RecursiveMutex lazy_mutex; // Mutex required for lazy type checking of specific files - BlockingMutex gen_types_mutex; - PtrMap gen_types; // BlockingMutex type_info_mutex; // NOT recursive // Array type_info_types; @@ -486,6 +758,9 @@ struct CheckerInfo { MPSCQueue foreign_imports_to_check_fullpaths; MPSCQueue foreign_decls_to_check; + MPSCQueue raddbg_type_views_queue; + Array raddbg_type_views; + MPSCQueue intrinsics_entry_point_usage; BlockingMutex objc_objc_msgSend_mutex; @@ -502,7 +777,7 @@ struct CheckerInfo { BlockingMutex load_file_mutex; StringMap load_file_cache; - BlockingMutex all_procedures_mutex; + MPSCQueue all_procedures_queue; Array all_procedures; BlockingMutex instrumentation_mutex; @@ -551,6 +826,7 @@ struct CheckerContext { u32 stmt_flags; bool in_enum_type; + bool in_proc_group; bool collect_delayed_decls; bool allow_polymorphic_types; bool disallow_polymorphic_return_types; // NOTE(zen3ger): no poly type decl in return types @@ -608,9 +884,9 @@ gb_internal isize type_info_index (CheckerInfo *info, TypeInfoPair gb_internal Entity *entity_of_node(Ast *expr); -gb_internal Entity *scope_lookup_current(Scope *s, String const &name); -gb_internal Entity *scope_lookup (Scope *s, String const &name); -gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_); +// gb_internal Entity *scope_lookup_current(Scope *s, String const &name, u32 hash=0); +gb_internal Entity *scope_lookup (Scope *s, InternedString interned, u32 hash); +gb_internal void scope_lookup_parent (Scope *s, InternedString name, Scope **scope_, Entity **entity_, u32 hash); gb_internal Entity *scope_insert (Scope *s, Entity *entity); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index c7bd3a7a7..e492ca7b2 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -26,6 +26,7 @@ enum BuiltinProcId { BuiltinProc_conj, BuiltinProc_expand_values, + BuiltinProc_compress_values, BuiltinProc_min, BuiltinProc_max, @@ -48,6 +49,11 @@ enum BuiltinProcId { BuiltinProc_constant_log2, + BuiltinProc_constant_floor, + BuiltinProc_constant_trunc, + BuiltinProc_constant_ceil, + BuiltinProc_constant_round, + BuiltinProc_transpose, BuiltinProc_outer_product, BuiltinProc_hadamard_product, @@ -55,16 +61,21 @@ enum BuiltinProcId { BuiltinProc_soa_struct, + BuiltinProc_concatenate, + BuiltinProc_alloca, BuiltinProc_cpu_relax, BuiltinProc_trap, BuiltinProc_debug_trap, BuiltinProc_read_cycle_counter, + BuiltinProc_read_cycle_counter_frequency, BuiltinProc_count_ones, BuiltinProc_count_zeros, BuiltinProc_count_trailing_zeros, BuiltinProc_count_leading_zeros, + BuiltinProc_count_trailing_ones, + BuiltinProc_count_leading_ones, BuiltinProc_reverse_bits, BuiltinProc_byte_swap, @@ -133,6 +144,8 @@ BuiltinProc__atomic_end, BuiltinProc_fixed_point_div_sat, BuiltinProc_expect, + BuiltinProc_likely, + BuiltinProc_unlikely, BuiltinProc__simd_begin, BuiltinProc_simd_add, @@ -190,13 +203,24 @@ BuiltinProc__simd_begin, BuiltinProc_simd_shuffle, BuiltinProc_simd_select, + BuiltinProc_simd_runtime_swizzle, + BuiltinProc_simd_odd_even, + + BuiltinProc_simd_sums_of_n, + + BuiltinProc_simd_pairwise_add, + BuiltinProc_simd_pairwise_sub, BuiltinProc_simd_ceil, BuiltinProc_simd_floor, BuiltinProc_simd_trunc, BuiltinProc_simd_nearest, + BuiltinProc_simd_approx_recip, + BuiltinProc_simd_approx_recip_sqrt, + BuiltinProc_simd_to_bits, + BuiltinProc_simd_to_bits_signed, BuiltinProc_simd_lanes_reverse, BuiltinProc_simd_lanes_rotate_left, @@ -211,6 +235,9 @@ BuiltinProc__simd_begin, BuiltinProc_simd_indices, + BuiltinProc_simd_interleave, + BuiltinProc_simd_deinterleave, + // Platform specific SIMD intrinsics BuiltinProc_simd_x86__MM_SHUFFLE, @@ -223,6 +250,7 @@ BuiltinProc__simd_end, BuiltinProc_x86_cpuid, BuiltinProc_x86_xgetbv, + // Constant type tests BuiltinProc__type_begin, @@ -234,14 +262,21 @@ BuiltinProc__type_begin, BuiltinProc_type_convert_variants_to_pointers, BuiltinProc_type_merge, + BuiltinProc_type_integer_to_unsigned, + BuiltinProc_type_integer_to_signed, + BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_boolean, + BuiltinProc_type_is_bit_field, BuiltinProc_type_is_integer, BuiltinProc_type_is_rune, BuiltinProc_type_is_float, BuiltinProc_type_is_complex, BuiltinProc_type_is_quaternion, BuiltinProc_type_is_string, + BuiltinProc_type_is_string16, + BuiltinProc_type_is_cstring, + BuiltinProc_type_is_cstring16, BuiltinProc_type_is_typeid, BuiltinProc_type_is_any, @@ -256,6 +291,7 @@ BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_sliceable, BuiltinProc_type_is_comparable, BuiltinProc_type_is_simple_compare, // easily compared using memcmp + BuiltinProc_type_is_nearly_simple_compare, // easily compared using memcmp (including floats) BuiltinProc_type_is_dereferenceable, BuiltinProc_type_is_valid_map_key, BuiltinProc_type_is_valid_matrix_elements, @@ -275,6 +311,10 @@ BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_bit_set, BuiltinProc_type_is_simd_vector, BuiltinProc_type_is_matrix, + BuiltinProc_type_is_raw_union, + BuiltinProc_type_is_fixed_capacity_dynamic_array, + + BuiltinProc_type_is_internally_pointer_like, BuiltinProc_type_is_specialized_polymorphic_record, BuiltinProc_type_is_unspecialized_polymorphic_record, @@ -288,6 +328,9 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_has_field, BuiltinProc_type_field_type, + + BuiltinProc_type_field_bit_offset, + BuiltinProc_type_field_bit_size, BuiltinProc_type_is_specialization_of, @@ -311,15 +354,22 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_proc_parameter_type, BuiltinProc_type_proc_return_type, + BuiltinProc_type_proc_calling_convention, + BuiltinProc_type_polymorphic_record_parameter_count, BuiltinProc_type_polymorphic_record_parameter_value, BuiltinProc_type_is_subtype_of, + BuiltinProc_type_is_superset_of, BuiltinProc_type_field_index_of, + BuiltinProc_type_fixed_capacity_dynamic_array_len_offset, + BuiltinProc_type_bit_set_backing_type, + BuiltinProc_type_enum_is_contiguous, + BuiltinProc_type_equal_proc, BuiltinProc_type_hasher_proc, BuiltinProc_type_map_info, @@ -327,6 +377,8 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_has_shared_fields, + BuiltinProc_type_canonical_name, + BuiltinProc__type_end, BuiltinProc_procedure_of, @@ -339,6 +391,13 @@ BuiltinProc__type_end, BuiltinProc_objc_register_selector, BuiltinProc_objc_register_class, BuiltinProc_objc_ivar_get, + BuiltinProc_objc_block, + BuiltinProc_objc_super, + + BuiltinProc_c_va_start, + BuiltinProc_c_va_end, + BuiltinProc_c_va_copy, + BuiltinProc_c_va_arg, BuiltinProc_constant_utf16_cstring, @@ -376,6 +435,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("conj"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("expand_values"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, + {STR_LIT("compress_values"), 1, true, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("min"), 1, true, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("max"), 1, true, Expr_Expr, BuiltinProcPkg_builtin}, @@ -397,7 +457,11 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("has_target_feature"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("constant_log2"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_log2"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_floor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_trunc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_ceil"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_round"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("transpose"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("outer_product"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -406,17 +470,22 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("soa_struct"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type + {STR_LIT("concatenate"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("alloca"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("cpu_relax"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("trap"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics, /*diverging*/true}, {STR_LIT("debug_trap"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics, /*diverging*/false}, {STR_LIT("read_cycle_counter"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("read_cycle_counter_frequency"), 0, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_ones"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_trailing_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("count_leading_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("count_trailing_ones"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("count_leading_ones"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("reverse_bits"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("byte_swap"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -484,7 +553,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("fixed_point_mul_sat"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("fixed_point_div_sat"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("expect"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("expect"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("likely"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("unlikely"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -544,13 +615,24 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_runtime_swizzle"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_odd_even"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("simd_sums_of_n"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("simd_pairwise_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_pairwise_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_ceil") , 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_floor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_trunc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_nearest"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_approx_recip"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_approx_recip_sqrt"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_to_bits"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_to_bits_signed"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_lanes_reverse"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_lanes_rotate_left"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -565,6 +647,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_indices"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_interleave"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_deinterleave"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_x86__MM_SHUFFLE"), 4, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, @@ -583,14 +668,21 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_convert_variants_to_pointers"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_merge"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_integer_to_unsigned"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_integer_to_signed"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_bit_field"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_integer"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_rune"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_float"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_complex"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_quaternion"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_string"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_string16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_cstring16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_typeid"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -605,6 +697,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_sliceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_comparable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_nearly_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_dereferenceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_map_key"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_matrix_elements"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -624,6 +717,10 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_bit_set"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_simd_vector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_matrix"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_raw_union"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_fixed_capacity_dynamic_array"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("type_is_internally_pointer_like"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_specialized_polymorphic_record"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_unspecialized_polymorphic_record"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -636,6 +733,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_has_field"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_field_type"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("type_field_bit_offset"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_field_bit_size"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_specialization_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, @@ -659,21 +759,29 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_proc_parameter_type"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_proc_return_type"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_proc_calling_convention"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_polymorphic_record_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_polymorphic_record_parameter_value"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_subtype_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_superset_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics }, {STR_LIT("type_field_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_fixed_capacity_dynamic_array_len_offset"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_bit_set_backing_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_enum_is_contiguous"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics }, + {STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_map_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_map_cell_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_has_shared_fields"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_canonical_name"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, @@ -688,6 +796,14 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("objc_register_selector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("objc_register_class"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("objc_ivar_get"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, + {STR_LIT("objc_block"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("objc_super"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("c_va_start"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("c_va_end"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("c_va_copy"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("c_va_arg"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("constant_utf16_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/common.cpp b/src/common.cpp index ad1e5a851..89964309b 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -9,7 +9,9 @@ #if defined(GB_SYSTEM_WINDOWS) -#define NOMINMAX 1 +#define NOMINMAX 1 +#define WINDOWS_LEAN_AND_MEAN 1 +#define VC_EXTRALEAN 1 #include #undef NOMINMAX #endif @@ -59,6 +61,11 @@ template struct TypeIsPtrSizedInteger { enum {value = false}; }; template <> struct TypeIsPtrSizedInteger { enum {value = true}; }; template <> struct TypeIsPtrSizedInteger { enum {value = true}; }; +template struct TypeIs64BitInteger { enum {value = false}; }; +template <> struct TypeIs64BitInteger { enum {value = true}; }; +template <> struct TypeIs64BitInteger { enum {value = true}; }; + + #include "unicode.cpp" #include "array.cpp" @@ -80,6 +87,13 @@ gb_internal gb_inline bool is_power_of_two(i64 x) { return !(x & (x-1)); } +gb_internal gb_inline bool is_power_of_two_u64(u64 x) { + if (x == 0) { + return false; + } + return !(x & (x-1)); +} + gb_internal int isize_cmp(isize x, isize y) { if (x < y) { return -1; @@ -350,9 +364,11 @@ gb_global bool global_module_path_set = false; #include "ptr_map.cpp" #include "ptr_set.cpp" #include "string_map.cpp" +#include "string16_map.cpp" #include "string_set.cpp" #include "priority_queue.cpp" #include "thread_pool.cpp" +#include "string_interner.cpp" gb_internal String obfuscate_string(String const &s, char const *prefix) { @@ -375,48 +391,6 @@ gb_internal i32 obfuscate_i32(i32 i) { } - -struct StringIntern { - StringIntern *next; - isize len; - char str[1]; -}; - -PtrMap string_intern_map = {}; // Key: u64 -gb_global Arena string_intern_arena = {}; - -gb_internal char const *string_intern(char const *text, isize len) { - u64 hash = gb_fnv64a(text, len); - uintptr key = cast(uintptr)(hash ? hash : 1); - StringIntern **found = map_get(&string_intern_map, key); - if (found) { - for (StringIntern *it = *found; it != nullptr; it = it->next) { - if (it->len == len && gb_strncmp(it->str, (char *)text, len) == 0) { - return it->str; - } - } - } - - StringIntern *new_intern = cast(StringIntern *)arena_alloc(&string_intern_arena, gb_offset_of(StringIntern, str) + len + 1, gb_align_of(StringIntern)); - new_intern->len = len; - new_intern->next = found ? *found : nullptr; - gb_memmove(new_intern->str, text, len); - new_intern->str[len] = 0; - map_set(&string_intern_map, key, new_intern); - return new_intern->str; -} - -gb_internal char const *string_intern(String const &string) { - return string_intern(cast(char const *)string.text, string.len); -} - -gb_internal void init_string_interner(void) { - map_init(&string_intern_map); -} - - - - gb_internal i32 next_pow2(i32 n) { if (n <= 0) { return 0; @@ -669,7 +643,7 @@ gb_internal gb_inline f64 gb_sqrt(f64 x) { gb_internal wchar_t **command_line_to_wargv(wchar_t *cmd_line, int *_argc) { u32 i, j; - u32 len = cast(u32)string16_len(cmd_line); + u32 len = cast(u32)string16_len(cast(u16 *)cmd_line); i = ((len+2)/2)*gb_size_of(void *) + gb_size_of(void *); wchar_t **argv = cast(wchar_t **)GlobalAlloc(GMEM_FIXED, i + (len+2)*gb_size_of(wchar_t)); diff --git a/src/common_memory.cpp b/src/common_memory.cpp index 47b2796a9..c8fe7c3d7 100644 --- a/src/common_memory.cpp +++ b/src/common_memory.cpp @@ -2,6 +2,25 @@ #include #endif +#ifdef __ANDROID__ + +// Bionic may not provide aligned_alloc. +// Provide a fallback using posix_memalign and ensure the alignment +// satisfies its requirement (multiple of pointer size). +static void* android_aligned_alloc(size_t align, size_t size) { + void* allocated; + + const size_t ptr_size = sizeof(void*); + align = (align + (ptr_size - 1)) / ptr_size * ptr_size; + + if (posix_memalign(&allocated, align, size) != 0) + return NULL; + return allocated; +} +#define aligned_alloc android_aligned_alloc + +#endif + template gb_internal gb_inline U bit_cast(V &v) { return reinterpret_cast(v); } @@ -40,6 +59,7 @@ struct MemoryBlock { u8 * base; isize size; isize used; + isize committed; }; struct Arena { @@ -48,13 +68,14 @@ struct Arena { // BlockingMutex mutex; isize temp_count; Thread * parent_thread; + bool custom_arena; }; enum { DEFAULT_MINIMUM_BLOCK_SIZE = 8ll*1024ll*1024ll }; gb_global isize DEFAULT_PAGE_SIZE = 4096; -gb_internal MemoryBlock *virtual_memory_alloc(isize size); +gb_internal MemoryBlock *virtual_memory_alloc(isize size, bool commit); gb_internal void virtual_memory_dealloc(MemoryBlock *block); gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment); gb_internal void arena_free_all(Arena *arena); @@ -82,7 +103,7 @@ gb_internal void thread_init_arenas(Thread *t) { gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { GB_ASSERT(gb_is_power_of_two(alignment)); - GB_ASSERT(arena->parent_thread == get_current_thread()); + GB_ASSERT(arena->custom_arena || arena->parent_thread == get_current_thread()); isize size = 0; if (arena->curr_block != nullptr) { @@ -95,7 +116,7 @@ gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { isize block_size = gb_max(size, arena->minimum_block_size); - MemoryBlock *new_block = virtual_memory_alloc(block_size); + MemoryBlock *new_block = virtual_memory_alloc(block_size, true); new_block->prev = arena->curr_block; arena->curr_block = new_block; } @@ -113,6 +134,69 @@ gb_internal void *arena_alloc(Arena *arena, isize min_size, isize alignment) { return ptr; } +gb_internal void *platform_virtual_memory_alloc_internal(isize total_size, bool commit); +gb_internal bool platform_virtual_memory_commit_internal(void *data, isize commit_amount); + +struct StaticArena { + u8 * data; + isize used; + isize committed; + isize reserved; + isize commit_block_size; +}; + +enum {STATIC_ARENA_DEFAULT_COMMIT_BLOCK_SIZE = 8<<20}; + +gb_internal void static_arena_init(StaticArena *arena, isize reserve_size, isize commit_block_size) { + GB_ASSERT(gb_is_power_of_two(reserve_size)); + GB_ASSERT(gb_is_power_of_two(commit_block_size)); + GB_ASSERT(commit_block_size <= reserve_size); + arena->data = cast(u8 *)platform_virtual_memory_alloc_internal(reserve_size, false); + arena->reserved = reserve_size; + arena->commit_block_size = commit_block_size; +} + +gb_internal void static_arena_commit_memory(StaticArena *arena, isize amount) { + isize blocks = (amount + arena->commit_block_size-1)/arena->commit_block_size; + isize total_amount = blocks * arena->commit_block_size; + + if (total_amount > arena->reserved - arena->committed) { + total_amount = arena->reserved - arena->committed; + } + + platform_virtual_memory_commit_internal(arena->data + arena->committed, total_amount); + arena->committed += total_amount; +} + +gb_internal void *static_arena_alloc(StaticArena *arena, isize size, isize alignment) { + GB_ASSERT(gb_is_power_of_two(alignment)); + + size = align_formula_isize(size, alignment); + + u8 *curr = arena->data + arena->used; + curr = cast(u8 *)align_formula_ptr(curr, alignment); + + u8 *end = curr + size; + if (end-arena->data > arena->committed) { + isize needed = (end - arena->data) - arena->committed; + static_arena_commit_memory(arena, needed); + } + GB_ASSERT_MSG(end-arena->data <= arena->committed, "out of memory for the static arena"); + + arena->used = end - arena->data; + + return curr; +} + + + + +template +gb_internal T *arena_alloc_item(Arena *arena) { + return cast(T *)arena_alloc(arena, gb_size_of(T), gb_align_of(T)); +} + + gb_internal void arena_free_all(Arena *arena) { while (arena->curr_block != nullptr) { MemoryBlock *free_block = arena->curr_block; @@ -131,10 +215,13 @@ struct PlatformMemoryBlock { gb_global std::atomic global_platform_memory_total_usage; gb_global PlatformMemoryBlock global_platform_memory_block_sentinel; -gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size); +gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size, bool commit); gb_internal void platform_virtual_memory_free(PlatformMemoryBlock *block); gb_internal void platform_virtual_memory_protect(void *memory, isize size); +gb_internal void *platform_virtual_memory_alloc_internal(isize total_size, bool commit); +gb_internal bool platform_virtual_memory_commit_internal(void *data, isize commit_amount); + #if defined(GB_SYSTEM_WINDOWS) gb_internal void platform_virtual_memory_init(void) { global_platform_memory_block_sentinel.prev = &global_platform_memory_block_sentinel; @@ -146,14 +233,20 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); GB_ASSERT(gb_is_power_of_two(DEFAULT_PAGE_SIZE)); } - gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size) { - PlatformMemoryBlock *pmblock = (PlatformMemoryBlock *)VirtualAlloc(0, total_size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - if (pmblock == nullptr) { + gb_internal void *platform_virtual_memory_alloc_internal(isize total_size, bool commit) { + DWORD flags = commit ? MEM_RESERVE|MEM_COMMIT : MEM_RESERVE; + void *mem = VirtualAlloc(0, total_size, flags, PAGE_READWRITE); + if (mem == nullptr) { gb_printf_err("Out of Virtual memory, oh no...\n"); gb_printf_err("Requested: %lld bytes\n", cast(long long)total_size); gb_printf_err("Total Usage: %lld bytes\n", cast(long long)global_platform_memory_total_usage); - GB_ASSERT_MSG(pmblock != nullptr, "Out of Virtual Memory, oh no..."); + GB_ASSERT_MSG(mem != nullptr, "Out of Virtual Memory, oh no..."); } + return mem; + } + + gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size, bool commit) { + PlatformMemoryBlock *pmblock = cast(PlatformMemoryBlock *)platform_virtual_memory_alloc_internal(total_size, commit); global_platform_memory_total_usage.fetch_add(total_size); return pmblock; } @@ -166,6 +259,16 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); BOOL is_protected = VirtualProtect(memory, size, PAGE_NOACCESS, &old_protect); GB_ASSERT(is_protected); } + + gb_internal bool platform_virtual_memory_commit_internal(void *data, isize commit_amount) { + void *res = VirtualAlloc(data, commit_amount, MEM_COMMIT, PAGE_READWRITE); + if (res == nullptr) { + GB_PANIC("Out of Virtual Memory, oh no...\n"); + GB_ASSERT_MSG(res != nullptr, "Out of Virtual Memory, oh no..."); + return false; + } + return true; + } #else #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) #define MAP_ANONYMOUS MAP_ANON @@ -178,9 +281,20 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); DEFAULT_PAGE_SIZE = gb_max(DEFAULT_PAGE_SIZE, cast(isize)sysconf(_SC_PAGE_SIZE)); GB_ASSERT(gb_is_power_of_two(DEFAULT_PAGE_SIZE)); } + + gb_internal void *platform_virtual_memory_alloc_internal(isize total_size, bool commit) { + void *mem = mmap(nullptr, total_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (mem == nullptr) { + gb_printf_err("Out of Virtual memory, oh no...\n"); + gb_printf_err("Requested: %lld bytes\n", cast(long long)total_size); + gb_printf_err("Total Usage: %lld bytes\n", cast(long long)global_platform_memory_total_usage); + GB_ASSERT_MSG(mem != nullptr, "Out of Virtual Memory, oh no..."); + } + return mem; + } - gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size) { - PlatformMemoryBlock *pmblock = (PlatformMemoryBlock *)mmap(nullptr, total_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc(isize total_size, bool commit) { + PlatformMemoryBlock *pmblock = cast(PlatformMemoryBlock *)platform_virtual_memory_alloc_internal(total_size, commit); if (pmblock == nullptr) { gb_printf_err("Out of Virtual memory, oh no...\n"); gb_printf_err("Requested: %lld bytes\n", cast(long long)total_size); @@ -190,6 +304,9 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); global_platform_memory_total_usage.fetch_add(total_size); return pmblock; } + gb_internal PlatformMemoryBlock *platform_virtual_memory_alloc_uncommited(isize total_size) { + return platform_virtual_memory_alloc(total_size, false); + } gb_internal void platform_virtual_memory_free(PlatformMemoryBlock *block) { isize size = block->total_size; global_platform_memory_total_usage.fetch_sub(size); @@ -199,9 +316,19 @@ gb_internal void platform_virtual_memory_protect(void *memory, isize size); int err = mprotect(memory, size, PROT_NONE); GB_ASSERT(err == 0); } + + gb_internal bool platform_virtual_memory_commit_internal(void *data, isize commit_amount) { + int err = mprotect(data, commit_amount, PROT_READ | PROT_WRITE); + if (err != 0) { + GB_PANIC("Out of Virtual Memory, oh no...\n"); + GB_ASSERT_MSG(err == 0, "Out of Virtual Memory, oh no..."); + return false; + } + return true; + } #endif -gb_internal MemoryBlock *virtual_memory_alloc(isize size) { +gb_internal MemoryBlock *virtual_memory_alloc(isize size, bool commit) { isize const page_size = DEFAULT_PAGE_SIZE; isize total_size = size + gb_size_of(PlatformMemoryBlock); @@ -217,7 +344,7 @@ gb_internal MemoryBlock *virtual_memory_alloc(isize size) { do_protection = true; } - PlatformMemoryBlock *pmblock = platform_virtual_memory_alloc(total_size); + PlatformMemoryBlock *pmblock = platform_virtual_memory_alloc(total_size, commit); GB_ASSERT_MSG(pmblock != nullptr, "Out of Virtual Memory, oh no..."); pmblock->block.base = cast(u8 *)pmblock + base_offset; @@ -346,7 +473,7 @@ gb_internal gbAllocator arena_allocator(Arena *arena) { gb_internal GB_ALLOCATOR_PROC(arena_allocator_proc) { void *ptr = nullptr; Arena *arena = cast(Arena *)allocator_data; - GB_ASSERT_NOT_NULL(arena); + GB_ASSERT(arena != nullptr); switch (type) { case gbAllocation_Alloc: @@ -393,6 +520,52 @@ gb_internal Arena *get_arena(ThreadArenaKind kind) { return nullptr; } +template +gb_internal T *arena_alloc_array(Arena *arena, isize count) { + return cast(T *)arena_alloc(arena, gb_size_of(T)*count, gb_align_of(T)); +} + +template +gb_internal T *permanent_alloc_item() { + Arena *arena = get_arena(ThreadArena_Permanent); + return arena_alloc_item(arena); +} + +template +gb_internal T *permanent_alloc_array(isize count) { + Arena *arena = get_arena(ThreadArena_Permanent); + return arena_alloc_array(arena, count); +} + +template +gb_internal Slice permanent_slice_make(isize count) { + Arena *arena = get_arena(ThreadArena_Permanent); + T *data = arena_alloc_array(arena, count); + return {data, count}; +} + +template +gb_internal T *temporary_alloc_item() { + Arena *arena = get_arena(ThreadArena_Temporary); + return arena_alloc_item(arena); +} + +template +gb_internal T *temporary_alloc_array(isize count) { + Arena *arena = get_arena(ThreadArena_Temporary); + return arena_alloc_array(arena, count); +} + +template +gb_internal Slice temporary_slice_make(isize count) { + Arena *arena = get_arena(ThreadArena_Temporary); + T *data = arena_alloc_array(arena, count); + return {data, count}; +} + + + + gb_internal GB_ALLOCATOR_PROC(thread_arena_allocator_proc) { @@ -432,15 +605,16 @@ gb_internal gbAllocator permanent_allocator() { } gb_internal gbAllocator temporary_allocator() { - return {thread_arena_allocator_proc, cast(void *)cast(uintptr)ThreadArena_Permanent}; + // return {thread_arena_allocator_proc, cast(void *)cast(uintptr)ThreadArena_Temporary}; + return permanent_allocator(); } #define TEMP_ARENA_GUARD(arena) ArenaTempGuard GB_DEFER_3(_arena_guard_){arena} -// #define TEMPORARY_ALLOCATOR_GUARD() -#define TEMPORARY_ALLOCATOR_GUARD() TEMP_ARENA_GUARD(get_arena(ThreadArena_Temporary)) +// #define TEMPORARY_ALLOCATOR_GUARD() TEMP_ARENA_GUARD(get_arena(ThreadArena_Temporary)) +#define TEMPORARY_ALLOCATOR_GUARD() #define PERMANENT_ALLOCATOR_GUARD() diff --git a/src/docs.cpp b/src/docs.cpp index 004134a5c..1d8886edb 100644 --- a/src/docs.cpp +++ b/src/docs.cpp @@ -55,6 +55,37 @@ gb_internal GB_COMPARE_PROC(cmp_entities_for_printing) { return res; } +gb_internal GB_COMPARE_PROC(cmp_entities_for_printing_by_order_in_src) { + GB_ASSERT(a != nullptr); + GB_ASSERT(b != nullptr); + Entity *x = *cast(Entity **)a; + Entity *y = *cast(Entity **)b; + int res = 0; + if (x->pkg != y->pkg) { + if (x->pkg == nullptr) { + return -1; + } + if (y->pkg == nullptr) { + return +1; + } + res = string_compare(x->pkg->name, y->pkg->name); + if (res != 0) { + return res; + } + } + + u64 sx = x->order_in_src; + u64 sy = y->order_in_src; + res = u64_cmp(sx, sy); + + if (res) { + return res; + } + res = i32_cmp(x->token.pos.offset, y->token.pos.offset); + + return res; +} + gb_internal GB_COMPARE_PROC(cmp_ast_package_by_name) { GB_ASSERT(a != nullptr); GB_ASSERT(b != nullptr); @@ -237,18 +268,37 @@ gb_internal void print_doc_package(CheckerInfo *info, AstPackage *pkg) { } array_add(&entities, e); } - array_sort(entities, cmp_entities_for_printing); + + bool in_src_order = build_context.cmd_doc_flags & CmdDocFlag_InSourceOrder; + + if (in_src_order) { + array_sort(entities, cmp_entities_for_printing_by_order_in_src); + } else { + array_sort(entities, cmp_entities_for_printing); + } bool show_docs = (build_context.cmd_doc_flags & CmdDocFlag_Short) == 0; + AstFile *curr_file = nullptr; EntityKind curr_entity_kind = Entity_Invalid; for (Entity *e : entities) { - if (curr_entity_kind != e->kind) { - if (curr_entity_kind != Entity_Invalid) { - print_doc_line(0, ""); + if (in_src_order) { + if (curr_file != e->file) { + if (curr_file != nullptr) { + print_doc_line(0, ""); + } + curr_file = e->file; + String filename = remove_directory_from_path(curr_file->fullpath); + print_doc_line(1, "file: %.*s", LIT(filename)); + } + } else { + if (curr_entity_kind != e->kind) { + if (curr_entity_kind != Entity_Invalid) { + print_doc_line(0, ""); + } + curr_entity_kind = e->kind; + print_doc_line(1, "%s", print_entity_names[e->kind]); } - curr_entity_kind = e->kind; - print_doc_line(1, "%s", print_entity_names[e->kind]); } Ast *type_expr = nullptr; @@ -303,7 +353,6 @@ gb_internal void print_doc_package(CheckerInfo *info, AstPackage *pkg) { print_doc_line(2, filename); } } - } gb_internal void generate_documentation(Checker *c) { diff --git a/src/docs_format.cpp b/src/docs_format.cpp index 6378971d0..30dcf40b9 100644 --- a/src/docs_format.cpp +++ b/src/docs_format.cpp @@ -15,7 +15,7 @@ struct OdinDocVersionType { #define OdinDocVersionType_Major 0 #define OdinDocVersionType_Minor 3 -#define OdinDocVersionType_Patch 1 +#define OdinDocVersionType_Patch 2 struct OdinDocHeaderBase { u8 magic[8]; @@ -59,31 +59,31 @@ struct OdinDocPosition { }; enum OdinDocTypeKind : u32 { - OdinDocType_Invalid = 0, - OdinDocType_Basic = 1, - OdinDocType_Named = 2, - OdinDocType_Generic = 3, - OdinDocType_Pointer = 4, - OdinDocType_Array = 5, - OdinDocType_EnumeratedArray = 6, - OdinDocType_Slice = 7, - OdinDocType_DynamicArray = 8, - OdinDocType_Map = 9, - OdinDocType_Struct = 10, - OdinDocType_Union = 11, - OdinDocType_Enum = 12, - OdinDocType_Tuple = 13, - OdinDocType_Proc = 14, - OdinDocType_BitSet = 15, - OdinDocType_SimdVector = 16, - OdinDocType_SOAStructFixed = 17, - OdinDocType_SOAStructSlice = 18, - OdinDocType_SOAStructDynamic = 19, - - OdinDocType_MultiPointer = 22, - OdinDocType_Matrix = 23, - OdinDocType_SoaPointer = 24, - OdinDocType_BitField = 25, + OdinDocType_Invalid = 0, + OdinDocType_Basic = 1, + OdinDocType_Named = 2, + OdinDocType_Generic = 3, + OdinDocType_Pointer = 4, + OdinDocType_Array = 5, + OdinDocType_EnumeratedArray = 6, + OdinDocType_Slice = 7, + OdinDocType_DynamicArray = 8, + OdinDocType_Map = 9, + OdinDocType_Struct = 10, + OdinDocType_Union = 11, + OdinDocType_Enum = 12, + OdinDocType_Tuple = 13, + OdinDocType_Proc = 14, + OdinDocType_BitSet = 15, + OdinDocType_SimdVector = 16, + OdinDocType_SOAStructFixed = 17, + OdinDocType_SOAStructSlice = 18, + OdinDocType_SOAStructDynamic = 19, + OdinDocType_MultiPointer = 22, + OdinDocType_Matrix = 23, + OdinDocType_SoaPointer = 24, + OdinDocType_BitField = 25, + OdinDocType_FixedCapacityDynamicArray = 26, }; enum OdinDocTypeFlag_Basic : u32 { @@ -94,6 +94,7 @@ enum OdinDocTypeFlag_Struct : u32 { OdinDocTypeFlag_Struct_polymorphic = 1<<0, OdinDocTypeFlag_Struct_packed = 1<<1, OdinDocTypeFlag_Struct_raw_union = 1<<2, + OdinDocTypeFlag_Struct_all_or_none = 1<<3, }; enum OdinDocTypeFlag_Union : u32 { @@ -124,21 +125,78 @@ enum { struct OdinDocType { OdinDocTypeKind kind; + // Type_Kind specific used by some types + // Underlying flag types: + // .Basic - Type_Flags_Basic + // .Struct - Type_Flags_Struct + // .Union - Type_Flags_Union + // .Proc - Type_Flags_Proc + // .Bit_Set - Type_Flags_Bit_Set u32 flags; + + // Used by: + // .Basic + // .Named + // .Generic OdinDocString name; + + // Used By: .Struct, .Union OdinDocString custom_align; - // Used by some types + // Used by: + // .Array - 1 count: 0=len + // .Enumerated_Array - 1 count: 0=len + // .SOA_Struct_Fixed - 1 count: 0=len + // .Bit_Set - 2 count: 0=lower, 1=upper + // .Simd_Vector - 1 count: 0=len + // .Matrix - 2 count: 0=row_count, 1=column_count + // .Struct - <=2 count: 0=min_field_align, 1=max_field_align + // .Fixed_Capacity_Dynamic_Array - 1 count: 0=cap u32 elem_count_len; i64 elem_counts[OdinDocType_ElemsCap]; - // Each of these is esed by some types, not all + // Used by: .Procedures + // blank implies the "odin" calling convention OdinDocString calling_convention; + + // Used by: + // .Named - 1 type: 0=base type + // .Generic - <1 type: 0=specialization + // .Pointer - 1 type: 0=element + // .Array - 1 type: 0=element (and 1=generic index (if exists)) + // .Enumerated_Array - 2 types: 0=index and 1=element + // .Slice - 1 type: 0=element + // .Dynamic_Array - 1 type: 0=element + // .Map - 2 types: 0=key, 1=value + // .SOA_Struct_Fixed - 1 type: underlying SOA struct element + // .SOA_Struct_Slice - 1 type: underlying SOA struct element + // .SOA_Struct_Dynamic - 1 type: underlying SOA struct element + // .Union - 0+ types: variants + // .Enum - <1 type: 0=base type + // .Proc - 2 types: 0=parameters, 1=results + // .Bit_Set - <=2 types: 0=element type, 1=underlying type (Underlying_Type flag will be set) + // .Simd_Vector - 1 type: 0=element + // .Relative_Pointer - 2 types: 0=pointer type, 1=base integer + // .Multi_Pointer - 1 type: 0=element + // .Matrix - 1 type: 0=element + // .Soa_Pointer - 1 type: 0=element + // .Bit_Field - 1 type: 0=backing type + // .Fixed_Capacity_Dynamic_Array - 1 type: 0=element (and 1=generic index (if exists)) OdinDocArray types; + + // Used by: + // .Named - 1 field for the definition + // .Struct - fields + // .Enum - fields + // .Parameters - parameters (procedures only) OdinDocArray entities; + + // Used By: .Struct, .Union OdinDocTypeIndex polmorphic_params; + // Used By: .Struct, .Union OdinDocArray where_clauses; - OdinDocArray tags; // struct field tags + // Used By: .Struct + OdinDocArray tags; }; struct OdinDocAttribute { diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index a92ffc7ad..7a12d0875 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -43,7 +43,7 @@ struct OdinDocWriter { }; gb_internal OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e); -gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type); +gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type, bool cache); template gb_internal void odin_doc_writer_item_tracker_init(OdinDocWriterItemTracker *t, isize size) { @@ -370,7 +370,7 @@ gb_internal OdinDocString odin_doc_pkg_doc_string(OdinDocWriter *w, AstPackage * if (pkg == nullptr) { return {}; } - auto buf = array_make(permanent_allocator(), 0, 0); // Minor leak + auto buf = array_make(heap_allocator(), 0, 0); for_array(i, pkg->files) { AstFile *f = pkg->files[i]; @@ -380,31 +380,37 @@ gb_internal OdinDocString odin_doc_pkg_doc_string(OdinDocWriter *w, AstPackage * } } - return odin_doc_write_string_without_cache(w, make_string(buf.data, buf.count)); + String str = string_intern_string(make_string(buf.data, buf.count)); + array_free(&buf); + return odin_doc_write_string_without_cache(w, str); } gb_internal OdinDocString odin_doc_comment_group_string(OdinDocWriter *w, CommentGroup *g) { if (g == nullptr) { return {}; } - auto buf = array_make(permanent_allocator(), 0, 0); // Minor leak + auto buf = array_make(heap_allocator(), 0, 0); odin_doc_append_comment_group_string(&buf, g); - return odin_doc_write_string_without_cache(w, make_string(buf.data, buf.count)); + String str = string_intern_string(make_string(buf.data, buf.count)); + array_free(&buf); + return odin_doc_write_string_without_cache(w, str); } -gb_internal OdinDocString odin_doc_expr_string(OdinDocWriter *w, Ast *expr) { +gb_internal OdinDocString odin_doc_expr_string(OdinDocWriter *w, Ast *expr, bool use_shorthand=false) { if (expr == nullptr) { return {}; } - gbString s = write_expr_to_string( // Minor leak - gb_string_make(permanent_allocator(), ""), + gbString s = write_expr_to_string( + gb_string_make(heap_allocator(), ""), expr, - build_context.cmd_doc_flags & CmdDocFlag_Short + use_shorthand || (build_context.cmd_doc_flags & CmdDocFlag_Short) ); + String str = string_intern_string(make_string(cast(u8 *)s, gb_string_length(s))); + gb_string_free(s); - return odin_doc_write_string(w, make_string(cast(u8 *)s, gb_string_length(s))); + return odin_doc_write_string(w, str); } gb_internal OdinDocArray odin_doc_attributes(OdinDocWriter *w, Array const &attributes) { @@ -467,8 +473,8 @@ gb_internal OdinDocArray odin_doc_where_clauses(OdinDocWriter *w, return odin_write_slice(w, clauses.data, clauses.count); } -gb_internal OdinDocArray odin_doc_type_as_slice(OdinDocWriter *w, Type *type) { - OdinDocTypeIndex index = odin_doc_type(w, type); +gb_internal OdinDocArray odin_doc_type_as_slice(OdinDocWriter *w, Type *type, bool cache=true) { + OdinDocTypeIndex index = odin_doc_type(w, type, cache); return odin_write_item_as_slice(w, index); } @@ -479,7 +485,7 @@ gb_internal OdinDocArray odin_doc_add_entity_as_slice(OdinDo -gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { +gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type, bool cache=true) { if (type == nullptr) { return 0; } @@ -491,10 +497,13 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { } } - u64 type_hash = type_hash_canonical_type(type); - OdinDocTypeIndex *found = map_get(&w->type_cache, type_hash); - if (found) { - return *found; + u64 type_hash = {0}; + if (cache) { + type_hash = type_hash_canonical_type(type); + OdinDocTypeIndex *found = map_get(&w->type_cache, type_hash); + if (found) { + return *found; + } } @@ -502,7 +511,9 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { OdinDocType doc_type = {}; OdinDocTypeIndex type_index = 0; type_index = odin_doc_write_item(w, &w->types, &doc_type, &dst); - map_set(&w->type_cache, type_hash, type_index); + if (cache) { + map_set(&w->type_cache, type_hash, type_index); + } switch (type->kind) { case Type_Basic: @@ -527,7 +538,10 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { doc_type.kind = OdinDocType_Generic; doc_type.name = odin_doc_write_string(w, name); if (type->Generic.specialized) { - doc_type.types = odin_doc_type_as_slice(w, type->Generic.specialized); + // NOTE(laytan): do not look at the cache for the specialization, it would resolve + // to the same entry as the type itself because `default_type` resolves to the + // specialization of a generic type. + doc_type.types = odin_doc_type_as_slice(w, type->Generic.specialized, cache=false); } } break; @@ -547,7 +561,14 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { doc_type.kind = OdinDocType_Array; doc_type.elem_count_len = 1; doc_type.elem_counts[0] = type->Array.count; - doc_type.types = odin_doc_type_as_slice(w, type->Array.elem); + if (type->Array.generic_count != nullptr) { + OdinDocTypeIndex types[2] = {}; + types[0] = odin_doc_type(w, type->Array.elem); + types[1] = odin_doc_type(w, type->Array.generic_count); + doc_type.types = odin_write_slice(w, types, gb_count_of(types)); + } else { + doc_type.types = odin_doc_type_as_slice(w, type->Array.elem); + } break; case Type_EnumeratedArray: doc_type.kind = OdinDocType_EnumeratedArray; @@ -568,6 +589,20 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { doc_type.kind = OdinDocType_DynamicArray; doc_type.types = odin_doc_type_as_slice(w, type->DynamicArray.elem); break; + case Type_FixedCapacityDynamicArray: + doc_type.kind = OdinDocType_FixedCapacityDynamicArray; + doc_type.elem_count_len = 1; + doc_type.elem_counts[0] = type->FixedCapacityDynamicArray.capacity; + + if (type->FixedCapacityDynamicArray.generic_capacity != nullptr) { + OdinDocTypeIndex types[2] = {}; + types[0] = odin_doc_type(w, type->FixedCapacityDynamicArray.elem); + types[1] = odin_doc_type(w, type->FixedCapacityDynamicArray.generic_capacity); + doc_type.types = odin_write_slice(w, types, gb_count_of(types)); + } else { + doc_type.types = odin_doc_type_as_slice(w, type->FixedCapacityDynamicArray.elem); + } + break; case Type_Map: doc_type.kind = OdinDocType_Map; { @@ -612,6 +647,13 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { if (type->Struct.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Struct_polymorphic; } if (type->Struct.is_packed) { doc_type.flags |= OdinDocTypeFlag_Struct_packed; } if (type->Struct.is_raw_union) { doc_type.flags |= OdinDocTypeFlag_Struct_raw_union; } + if (type->Struct.is_all_or_none) { doc_type.flags |= OdinDocTypeFlag_Struct_all_or_none; } + + if (type->Struct.custom_min_field_align > 0 || type->Struct.custom_max_field_align > 0) { + doc_type.elem_count_len = 2; + doc_type.elem_counts[0] = cast(u32)gb_max(type->Struct.custom_min_field_align, 0); + doc_type.elem_counts[1] = cast(u32)gb_max(type->Struct.custom_max_field_align, 0); + } auto fields = array_make(heap_allocator(), type->Struct.fields.count); defer (array_free(&fields)); @@ -634,8 +676,10 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { auto tags = array_make(heap_allocator(), type->Struct.fields.count); defer (array_free(&tags)); - for_array(i, type->Struct.fields) { - tags[i] = odin_doc_write_string(w, type->Struct.tags[i]); + if (type->Struct.tags != nullptr) { + for_array(i, type->Struct.fields) { + tags[i] = odin_doc_write_string(w, type->Struct.tags[i]); + } } doc_type.tags = odin_write_slice(w, tags.data, tags.count); @@ -882,7 +926,16 @@ gb_internal OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) OdinDocString init_string = {}; if (init_expr) { - init_string = odin_doc_expr_string(w, init_expr); + bool use_shorthand = false; + if (e->kind == Entity_Variable) { + Ast *expr = init_expr; + if (expr->kind == Ast_CompoundLit) { + if (expr->CompoundLit.elems.count > 512) { + use_shorthand = true; + } + } + } + init_string = odin_doc_expr_string(w, init_expr, use_shorthand); } else { if (e->kind == Entity_Constant) { if (e->Constant.flags & EntityConstantFlag_ImplicitEnumValue) { @@ -890,7 +943,10 @@ gb_internal OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) } else if (e->Constant.param_value.original_ast_expr) { init_string = odin_doc_expr_string(w, e->Constant.param_value.original_ast_expr); } else { - init_string = odin_doc_write_string(w, make_string_c(exact_value_to_string(e->Constant.value))); + gbString s = exact_value_to_string(e->Constant.value); + String str = string_intern_string(make_string(cast(u8 *)s, gb_string_length(s))); + gb_string_free(s); + init_string = odin_doc_write_string(w, str); } } else if (e->kind == Entity_Variable) { if (e->Variable.param_value.original_ast_expr) { @@ -1006,9 +1062,12 @@ gb_internal OdinDocArray odin_doc_add_pkg_entries(OdinDocWrit auto entries = array_make(heap_allocator(), 0, w->entity_cache.count); defer (array_free(&entries)); - for (auto const &element : pkg->scope->elements) { - String name = element.key; - Entity *e = element.value; + for (isize i = 0; i < pkg->scope->elements.cap; i++) { + if (!pkg->scope->elements.slots[i].hash) { + continue; + } + auto interned = pkg->scope->elements.keys[i]; + Entity *e = pkg->scope->elements.slots[i].value; switch (e->kind) { case Entity_Invalid: case Entity_Nil: @@ -1036,7 +1095,7 @@ gb_internal OdinDocArray odin_doc_add_pkg_entries(OdinDocWrit } OdinDocScopeEntry entry = {}; - entry.name = odin_doc_write_string(w, name); + entry.name = odin_doc_write_string(w, interned.string()); entry.entity = odin_doc_add_entity(w, e); array_add(&entries, entry); } @@ -1163,4 +1222,4 @@ gb_internal void odin_doc_write(CheckerInfo *info, char const *filename) { gb_internal bool is_in_doc_writer(void) { return g_in_doc_writer.load(); -} \ No newline at end of file +} diff --git a/src/entity.cpp b/src/entity.cpp index a16779419..31f90023b 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -141,7 +141,7 @@ enum ProcedureOptimizationMode : u8 { BlockingMutex global_type_name_objc_metadata_mutex; struct TypeNameObjCMetadataEntry { - String name; + InternedString interned; Entity *entity; }; struct TypeNameObjCMetadata { @@ -151,8 +151,8 @@ struct TypeNameObjCMetadata { }; gb_internal TypeNameObjCMetadata *create_type_name_obj_c_metadata() { - TypeNameObjCMetadata *md = gb_alloc_item(permanent_allocator(), TypeNameObjCMetadata); - md->mutex = gb_alloc_item(permanent_allocator(), BlockingMutex); + TypeNameObjCMetadata *md = permanent_alloc_item(); + md->mutex = permanent_alloc_item(); array_init(&md->type_entries, heap_allocator()); array_init(&md->value_entries, heap_allocator()); return md; @@ -164,12 +164,17 @@ struct Entity { u64 id; std::atomic flags; std::atomic state; + std::atomic min_dep_count; Token token; Scope * scope; Type * type; std::atomic identifier; // Can be nullptr + + std::atomic interned_name; + std::atomic interned_name_hash; + DeclInfo * decl_info; - DeclInfo * parent_proc_decl; // nullptr if in file/global scope + std::atomic parent_proc_decl; // nullptr if in file/global scope AstFile * file; AstPackage *pkg; @@ -179,14 +184,8 @@ struct Entity { Entity * aliased_of; - union { - struct lbModule *code_gen_module; - struct cgModule *cg_module; - }; - union { - struct lbProcedure *code_gen_procedure; - struct cgProcedure *cg_procedure; - }; + std::atomic code_gen_module; + std::atomic code_gen_procedure; u64 order_in_src; String deprecated_message; @@ -233,6 +232,7 @@ struct Entity { } Variable; struct { Type * type_parameter_specialization; + Type * original_type_for_parapoly; String ir_mangled_name; bool is_type_alias; bool objc_is_implementation; @@ -249,11 +249,17 @@ struct Entity { String link_name; String link_prefix; String link_suffix; + String link_section; + String objc_selector_name; + Entity *objc_class; DeferredProcedure deferred_procedure; struct GenProcsData *gen_procs; BlockingMutex gen_procs_mutex; ProcedureOptimizationMode optimization_mode; + + u64 fast_math_flags; + bool is_foreign : 1; bool is_export : 1; bool generated_from_polymorphic : 1; @@ -263,6 +269,10 @@ struct Entity { bool uses_branch_location : 1; bool is_anonymous : 1; bool no_sanitize_address : 1; + bool no_sanitize_memory : 1; + bool no_sanitize_thread : 1; + bool is_objc_impl_or_import : 1; + bool is_objc_class_method : 1; } Procedure; struct { Array entities; @@ -292,6 +302,16 @@ struct Entity { }; }; +gb_internal InternedString entity_interned_name(Entity *entity) { + auto name = entity->interned_name.load(); + if (name.value == 0) { + name = string_interner_insert(entity->token.string); + entity->interned_name.store(name); + entity->interned_name_hash.store(name.hash()); + } + return name; +} + gb_internal bool is_entity_kind_exported(EntityKind kind, bool allow_builtin = false) { switch (kind) { case Entity_Builtin: @@ -336,18 +356,24 @@ gb_internal bool entity_has_deferred_procedure(Entity *e) { gb_global std::atomic global_entity_id; +// NOTE(bill): This exists to allow for bulk allocations of entities all at once to improve performance for type generation +#define INTERNAL_ENTITY_INIT(e_, kind_, scope_, token_, type_) do { \ + (e_)->kind = (kind_); \ + (e_)->state = EntityState_Unresolved; \ + (e_)->scope = (scope_); \ + (e_)->token = (token_); \ + (e_)->type = (type_); \ + (e_)->id = 1 + global_entity_id.fetch_add(1); \ + if ((token_).pos.file_id) { \ + e_->file = thread_unsafe_get_ast_file_from_id((token_).pos.file_id); \ + } \ +} while (0) + + gb_internal Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) { - gbAllocator a = permanent_allocator(); - Entity *entity = gb_alloc_item(a, Entity); - entity->kind = kind; - entity->state = EntityState_Unresolved; - entity->scope = scope; - entity->token = token; - entity->type = type; - entity->id = 1 + global_entity_id.fetch_add(1); - if (token.pos.file_id) { - entity->file = thread_safe_get_ast_file_from_id(token.pos.file_id); - } + Entity *entity = permanent_alloc_item(); + INTERNAL_ENTITY_INIT(entity, kind, scope, token, type); + entity_interned_name(entity); return entity; } @@ -362,7 +388,7 @@ gb_internal Entity *alloc_entity_using_variable(Entity *parent, Token token, Typ token.pos = parent->token.pos; Entity *entity = alloc_entity(Entity_Variable, parent->scope, token, type); entity->using_parent = parent; - entity->parent_proc_decl = parent->parent_proc_decl; + entity->parent_proc_decl.store(parent->parent_proc_decl, std::memory_order_relaxed); entity->using_expr = using_expr; entity->flags |= EntityFlag_Using; entity->flags |= EntityFlag_Used; @@ -384,10 +410,9 @@ gb_internal Entity *alloc_entity_type_name(Scope *scope, Token token, Type *type } gb_internal Entity *alloc_entity_param(Scope *scope, Token token, Type *type, bool is_using, bool is_value) { - Entity *entity = alloc_entity_variable(scope, token, type); + Entity *entity = alloc_entity_variable(scope, token, type, EntityState_Resolved); entity->flags |= EntityFlag_Used; entity->flags |= EntityFlag_Param; - entity->state = EntityState_Resolved; if (is_using) entity->flags |= EntityFlag_Using; if (is_value) entity->flags |= EntityFlag_Value; return entity; @@ -404,11 +429,10 @@ gb_internal Entity *alloc_entity_const_param(Scope *scope, Token token, Type *ty gb_internal Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_index, EntityState state = EntityState_Unresolved) { - Entity *entity = alloc_entity_variable(scope, token, type); + Entity *entity = alloc_entity_variable(scope, token, type, state); entity->Variable.field_index = field_index; if (is_using) entity->flags |= EntityFlag_Using; entity->flags |= EntityFlag_Field; - entity->state = state; return entity; } diff --git a/src/error.cpp b/src/error.cpp index 1492b00c7..53bc01654 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -86,7 +86,7 @@ gb_internal char *token_pos_to_string(TokenPos const &pos); gb_internal bool set_file_path_string(i32 index, String const &path) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); if (index >= global_file_path_strings.count) { @@ -99,14 +99,14 @@ gb_internal bool set_file_path_string(i32 index, String const &path) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); if (index >= global_files.count) { @@ -118,13 +118,13 @@ gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { ok = true; } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal String get_file_path_string(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); String path = {}; @@ -133,13 +133,13 @@ gb_internal String get_file_path_string(i32 index) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return path; } gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); AstFile *file = nullptr; @@ -148,7 +148,18 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); + return file; +} + + +// use AFTER PARSER +gb_internal AstFile *thread_unsafe_get_ast_file_from_id(i32 index) { + GB_ASSERT(index >= 0); + AstFile *file = nullptr; + if (index < global_files.count) { + file = global_files[index]; + } return file; } @@ -823,7 +834,7 @@ gb_internal int error_value_cmp(void const *a, void const *b) { gb_global String error_article_table[][2] = { {str_lit("a "), str_lit("bit_set literal")}, {str_lit("a "), str_lit("constant declaration")}, - {str_lit("a "), str_lit("dynamiic array literal")}, + {str_lit("a "), str_lit("dynamic array literal")}, {str_lit("a "), str_lit("map index")}, {str_lit("a "), str_lit("map literal")}, {str_lit("a "), str_lit("matrix literal")}, diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 37751c8f1..184a8f2e4 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -1,8 +1,6 @@ #include #include -gb_global BlockingMutex hash_exact_value_mutex; - struct Ast; struct HashKey; struct Type; @@ -29,10 +27,27 @@ enum ExactValueKind { ExactValue_Compound = 8, ExactValue_Procedure = 9, ExactValue_Typeid = 10, + ExactValue_String16 = 11, ExactValue_Count, }; +gb_global char const *exact_value_kind_string[ExactValue_Count] = { + "Invalid", + + "Bool", + "String", + "Integer", + "Float", + "Complex", + "Quaternion", + "Pointer", + "Compound", + "Procedure", + "Typeid", + "String16", +}; + struct ExactValue { ExactValueKind kind; union { @@ -46,15 +61,13 @@ struct ExactValue { Ast * value_compound; Ast * value_procedure; Type * value_typeid; + String16 value_string16; }; }; gb_global ExactValue const empty_exact_value = {}; gb_internal uintptr hash_exact_value(ExactValue v) { - mutex_lock(&hash_exact_value_mutex); - defer (mutex_unlock(&hash_exact_value_mutex)); - uintptr res = 0; switch (v.kind) { @@ -66,6 +79,9 @@ gb_internal uintptr hash_exact_value(ExactValue v) { case ExactValue_String: res = gb_fnv32a(v.value_string.text, v.value_string.len); break; + case ExactValue_String16: + res = gb_fnv32a(v.value_string.text, v.value_string.len*gb_size_of(u16)); + break; case ExactValue_Integer: { u32 key = gb_fnv32a(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); @@ -118,6 +134,11 @@ gb_internal ExactValue exact_value_string(String string) { result.value_string = string; return result; } +gb_internal ExactValue exact_value_string16(String16 string) { + ExactValue result = {ExactValue_String16}; + result.value_string16 = string; + return result; +} gb_internal ExactValue exact_value_i64(i64 i) { ExactValue result = {ExactValue_Integer}; @@ -141,7 +162,7 @@ gb_internal ExactValue exact_value_float(f64 f) { gb_internal ExactValue exact_value_complex(f64 real, f64 imag) { ExactValue result = {ExactValue_Complex}; - result.value_complex = gb_alloc_item(permanent_allocator(), Complex128); + result.value_complex = permanent_alloc_item(); result.value_complex->real = real; result.value_complex->imag = imag; return result; @@ -149,7 +170,7 @@ gb_internal ExactValue exact_value_complex(f64 real, f64 imag) { gb_internal ExactValue exact_value_quaternion(f64 real, f64 imag, f64 jmag, f64 kmag) { ExactValue result = {ExactValue_Quaternion}; - result.value_quaternion = gb_alloc_item(permanent_allocator(), Quaternion256); + result.value_quaternion = permanent_alloc_item(); result.value_quaternion->real = real; result.value_quaternion->imag = imag; result.value_quaternion->jmag = jmag; @@ -332,7 +353,10 @@ gb_internal ExactValue exact_value_float_from_string(String string) { f64 f = bit_cast(u); return exact_value_float(f); } else { - GB_PANIC("Invalid hexadecimal float, expected 8 or 16 digits, got %td", digit_count); + // GB_PANIC("Invalid hexadecimal float, expected 4, 8, or 16 digits, got %td", digit_count); + // NOTE(bill): This should be caught by the tokenizer, so just pretend it's an f64 + f64 f = bit_cast(u); + return exact_value_float(f); } } @@ -433,7 +457,7 @@ gb_internal ExactValue exact_value_to_complex(ExactValue v) { // return exact_value_complex(v.value_quaternion.real, v.value_quaternion.imag); } ExactValue r = {ExactValue_Invalid}; - v.value_complex = gb_alloc_item(permanent_allocator(), Complex128); + v.value_complex = permanent_alloc_item(); return r; } gb_internal ExactValue exact_value_to_quaternion(ExactValue v) { @@ -448,7 +472,7 @@ gb_internal ExactValue exact_value_to_quaternion(ExactValue v) { return v; } ExactValue r = {ExactValue_Invalid}; - v.value_quaternion = gb_alloc_item(permanent_allocator(), Quaternion256); + v.value_quaternion = permanent_alloc_item(); return r; } @@ -656,6 +680,7 @@ gb_internal i32 exact_value_order(ExactValue const &v) { return 0; case ExactValue_Bool: case ExactValue_String: + case ExactValue_String16: return 1; case ExactValue_Integer: return 2; @@ -689,6 +714,7 @@ gb_internal void match_exact_values(ExactValue *x, ExactValue *y) { case ExactValue_Bool: case ExactValue_String: + case ExactValue_String16: case ExactValue_Quaternion: case ExactValue_Pointer: case ExactValue_Compound: @@ -770,7 +796,7 @@ gb_internal ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, E case Token_Quo: return exact_value_float(fmod(big_int_to_f64(a), big_int_to_f64(b))); case Token_QuoEq: big_int_quo(&c, a, b); break; // NOTE(bill): Integer division case Token_Mod: big_int_rem(&c, a, b); break; - case Token_ModMod: big_int_euclidean_mod(&c, a, b); break; + case Token_ModMod: big_int_mod_mod(&c, a, b); break; case Token_And: big_int_and(&c, a, b); break; case Token_Or: big_int_or(&c, a, b); break; case Token_Xor: big_int_xor(&c, a, b); break; @@ -891,7 +917,18 @@ gb_internal ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, E gb_memmove(data, sx.text, sx.len); gb_memmove(data+sx.len, sy.text, sy.len); return exact_value_string(make_string(data, len)); - break; + } + case ExactValue_String16: { + if (op != Token_Add) goto error; + + // NOTE(bill): How do you minimize this over allocation? + String16 sx = x.value_string16; + String16 sy = y.value_string16; + isize len = sx.len+sy.len; + u16 *data = gb_alloc_array(permanent_allocator(), u16, len); + gb_memmove(data, sx.text, sx.len*gb_size_of(u16)); + gb_memmove(data+sx.len, sy.text, sy.len*gb_size_of(u16)); + return exact_value_string16(make_string16(data, len)); } } @@ -924,6 +961,8 @@ gb_internal gb_inline i32 cmp_f64(f64 a, f64 b) { return (a > b) - (a < b); } +gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, ExactValue y); + gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) { match_exact_values(&x, &y); @@ -994,6 +1033,19 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) } break; } + case ExactValue_String16: { + String16 a = x.value_string16; + String16 b = y.value_string16; + switch (op) { + case Token_CmpEq: return a == b; + case Token_NotEq: return a != b; + case Token_Lt: return a < b; + case Token_LtEq: return a <= b; + case Token_Gt: return a > b; + case Token_GtEq: return a >= b; + } + break; + } case ExactValue_Pointer: { switch (op) { @@ -1019,9 +1071,19 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) case Token_NotEq: return x.value_typeid != y.value_typeid; } break; + + case ExactValue_Compound: + if (op != Token_CmpEq && op != Token_NotEq) { + return false; + } + + if (x.kind != y.kind) { + return false; + } + return compare_exact_values_compound_lit(op, x, y); } - GB_PANIC("Invalid comparison"); + GB_PANIC("Invalid comparison: %d", x.kind); return false; } @@ -1050,6 +1112,20 @@ gb_internal gbString write_exact_value_to_string(gbString str, ExactValue const gb_free(heap_allocator(), s.text); return str; } + case ExactValue_String16: { + String s = quote_to_ascii(heap_allocator(), v.value_string16); + string_limit = gb_max(string_limit, 36); + if (s.len <= string_limit) { + str = gb_string_append_length(str, s.text, s.len); + } else { + isize n = string_limit/5; + str = gb_string_append_length(str, s.text, n); + str = gb_string_append_fmt(str, "\"..%lld chars..\"", s.len-(2*n)); + str = gb_string_append_length(str, s.text+s.len-n, n); + } + gb_free(heap_allocator(), s.text); + return str; + } case ExactValue_Integer: { String s = big_int_to_string(heap_allocator(), &v.value_integer); str = gb_string_append_length(str, s.text, s.len); diff --git a/src/gb/gb.h b/src/gb/gb.h index a1b659637..84bbc2e0e 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -87,10 +87,6 @@ extern "C" { #ifndef GB_SYSTEM_NETBSD #define GB_SYSTEM_NETBSD 1 #endif - #elif defined(__HAIKU__) || defined(__haiku__) - #ifndef GB_SYSTEM_HAIKU - #define GB_SYSTEM_HAIKU 1 - #endif #else #error This UNIX operating system is not supported #endif @@ -219,7 +215,7 @@ extern "C" { #endif #include // NOTE(bill): malloc on linux #include - #if !defined(GB_SYSTEM_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__HAIKU__) + #if !defined(GB_SYSTEM_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include @@ -267,13 +263,6 @@ extern "C" { #define lseek64 lseek #endif -#if defined(GB_SYSTEM_HAIKU) - #include - #include - #include - #define lseek64 lseek -#endif - #if defined(GB_SYSTEM_UNIX) #include #endif @@ -497,7 +486,11 @@ typedef i32 b32; // NOTE(bill): Prefer this!!! #if !defined(gb_no_asan) #if defined(_MSC_VER) - #define gb_no_asan __declspec(no_sanitize_address) + #if _MSC_VER >= 1930 + #define gb_no_asan __declspec(no_sanitize_address) + #else + #define gb_no_asan + #endif #else #define gb_no_asan __attribute__((disable_sanitizer_instrumentation)) #endif @@ -710,13 +703,15 @@ extern "C++" { } while (0) #endif + +#if defined(DISABLE_ASSERT) +#define GB_ASSERT(cond) gb_unused(cond) +#endif + #ifndef GB_ASSERT #define GB_ASSERT(cond) GB_ASSERT_MSG(cond, NULL) #endif -#ifndef GB_ASSERT_NOT_NULL -#define GB_ASSERT_NOT_NULL(ptr) GB_ASSERT_MSG((ptr) != NULL, #ptr " must not be NULL") -#endif // NOTE(bill): Things that shouldn't happen with a message! #ifndef GB_PANIC @@ -841,13 +836,6 @@ typedef struct gbAffinity { isize thread_count; isize threads_per_core; } gbAffinity; -#elif defined(GB_SYSTEM_HAIKU) -typedef struct gbAffinity { - b32 is_accurate; - isize core_count; - isize thread_count; - isize threads_per_core; -} gbAffinity; #else #error TODO(bill): Unknown system #endif @@ -2505,7 +2493,13 @@ extern "C" { #pragma warning(disable:4127) // Conditional expression is constant #endif +gb_internal void print_all_errors(void); +gb_internal bool any_errors(void); +gb_internal bool any_warnings(void); void gb_assert_handler(char const *prefix, char const *condition, char const *file, i32 line, char const *msg, ...) { + if (any_errors() || any_warnings()) { + print_all_errors(); + } gb_printf_err("%s(%d): %s: ", file, line, prefix); if (condition) gb_printf_err( "`%s` ", condition); @@ -2516,6 +2510,7 @@ void gb_assert_handler(char const *prefix, char const *condition, char const *fi va_end(va); } gb_printf_err("\n"); + gb_printf_err("This is a compiler error. Please report this.\n"); } b32 gb_is_power_of_two(isize x) { @@ -3035,8 +3030,6 @@ gb_inline u32 gb_thread_current_id(void) { __asm__("mov %%fs:0x10,%0" : "=r"(thread_id)); #elif defined(GB_SYSTEM_LINUX) thread_id = gettid(); -#elif defined(GB_SYSTEM_HAIKU) - thread_id = find_thread(NULL); #elif defined(GB_SYSTEM_FREEBSD) thread_id = pthread_getthreadid_np(); #elif defined(GB_SYSTEM_NETBSD) @@ -3249,9 +3242,6 @@ b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { //info.affinity_tag = cast(integer_t)index; //result = thread_policy_set(thread, THREAD_AFFINITY_POLICY, cast(thread_policy_t)&info, THREAD_AFFINITY_POLICY_COUNT); -#if !defined(GB_SYSTEM_HAIKU) - result = pthread_setaffinity_np(thread, sizeof(cpuset_t), &mn); -#endif return result == 0; } @@ -3332,29 +3322,6 @@ isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { return a->threads_per_core; } -#elif defined(GB_SYSTEM_HAIKU) -#include - -void gb_affinity_init(gbAffinity *a) { - a->core_count = sysconf(_SC_NPROCESSORS_ONLN); - a->threads_per_core = 1; - a->is_accurate = a->core_count > 0; - a->core_count = a->is_accurate ? a->core_count : 1; - a->thread_count = a->core_count; -} - -void gb_affinity_destroy(gbAffinity *a) { - gb_unused(a); -} - -b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { - return true; -} - -isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { - GB_ASSERT(0 <= core && core < a->core_count); - return a->threads_per_core; -} #else #error TODO(bill): Unknown system #endif @@ -3715,7 +3682,7 @@ gb_inline i32 gb_strcmp(char const *s1, char const *s2) { } gb_inline char *gb_strcpy(char *dest, char const *source) { - GB_ASSERT_NOT_NULL(dest); + GB_ASSERT(dest != NULL); if (source) { char *str = dest; while (*source) *str++ = *source++; @@ -3725,7 +3692,7 @@ gb_inline char *gb_strcpy(char *dest, char const *source) { gb_inline char *gb_strncpy(char *dest, char const *source, isize len) { - GB_ASSERT_NOT_NULL(dest); + GB_ASSERT(dest != NULL); if (source) { char *str = dest; while (len > 0 && *source) { @@ -3742,7 +3709,7 @@ gb_inline char *gb_strncpy(char *dest, char const *source, isize len) { gb_inline isize gb_strlcpy(char *dest, char const *source, isize len) { isize result = 0; - GB_ASSERT_NOT_NULL(dest); + GB_ASSERT(dest != NULL); if (source) { char const *source_start = source; char *str = dest; @@ -4865,8 +4832,8 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) { u64 h = seed ^ (len * m); u64 const *data = cast(u64 const *)data_; - u8 const *data2 = cast(u8 const *)data_; u64 const* end = data + (len / 8); + u8 const *data2 = cast(u8 const *)end; while (data != end) { u64 k = *data++; @@ -5632,7 +5599,7 @@ gbFileContents gb_file_read_contents(gbAllocator a, b32 zero_terminate, char con void gb_file_free_contents(gbFileContents *fc) { if (fc == NULL || fc->size == 0) return; - GB_ASSERT_NOT_NULL(fc->data); + GB_ASSERT(fc->data != NULL); gb_free(fc->allocator, fc->data); fc->data = NULL; fc->size = 0; @@ -5644,7 +5611,7 @@ void gb_file_free_contents(gbFileContents *fc) { gb_inline b32 gb_path_is_absolute(char const *path) { b32 result = false; - GB_ASSERT_NOT_NULL(path); + GB_ASSERT(path != NULL); #if defined(GB_SYSTEM_WINDOWS) result == (gb_strlen(path) > 2) && gb_char_is_alpha(path[0]) && @@ -5659,7 +5626,7 @@ gb_inline b32 gb_path_is_relative(char const *path) { return !gb_path_is_absolut gb_inline b32 gb_path_is_root(char const *path) { b32 result = false; - GB_ASSERT_NOT_NULL(path); + GB_ASSERT(path != NULL); #if defined(GB_SYSTEM_WINDOWS) result = gb_path_is_absolute(path) && (gb_strlen(path) == 3); #else @@ -5670,14 +5637,14 @@ gb_inline b32 gb_path_is_root(char const *path) { gb_inline char const *gb_path_base_name(char const *path) { char const *ls; - GB_ASSERT_NOT_NULL(path); + GB_ASSERT(path != NULL); ls = gb_char_last_occurence(path, '/'); return (ls == NULL) ? path : ls+1; } gb_inline char const *gb_path_extension(char const *path) { char const *ld; - GB_ASSERT_NOT_NULL(path); + GB_ASSERT(path != NULL); ld = gb_char_last_occurence(path, '.'); return (ld == NULL) ? NULL : ld+1; } diff --git a/src/linker.cpp b/src/linker.cpp index d648326b5..5b3cbb395 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -105,7 +105,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { gb_printf_err("executing `orca sdk-path` did not produce output\n"); return 1; } - inputs = gb_string_append_fmt(inputs, " \"%s/orca-libc/lib/crt1.o\" \"%s/orca-libc/lib/libc.o\"", orca_sdk_path, orca_sdk_path); + inputs = gb_string_append_fmt(inputs, " \"%s/orca-libc/lib/crt1.o\" \"%s/orca-libc/lib/libc.a\"", orca_sdk_path, orca_sdk_path); extra_orca_flags = gb_string_append_fmt(extra_orca_flags, " -L \"%s/bin\" -lorca_wasm --export-dynamic", orca_sdk_path); } @@ -133,17 +133,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { bool is_cross_linking = false; bool is_android = false; - if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { -#if defined(GB_SYSTEM_UNIX) - result = system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s", - LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags)); -#else - gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", - LIT(target_os_names[build_context.metrics.os]), - LIT(target_arch_names[build_context.metrics.arch]) - ); -#endif - } else if (build_context.cross_compiling && (build_context.different_os || selected_subtarget != Subtarget_Default)) { + if (build_context.cross_compiling && (build_context.different_os || selected_subtarget != Subtarget_Default)) { switch (selected_subtarget) { case Subtarget_Android: is_cross_linking = true; @@ -161,21 +151,32 @@ gb_internal i32 linker_stage(LinkerData *gen) { try_cross_linking:; #if defined(GB_SYSTEM_WINDOWS) + String section_name = str_lit("msvc-link"); bool is_windows = build_context.metrics.os == TargetOs_windows; #else + String section_name = str_lit("lld-link"); bool is_windows = false; #endif bool is_osx = build_context.metrics.os == TargetOs_darwin; + switch (build_context.linker_choice) { + case Linker_Default: break; + case Linker_lld: section_name = str_lit("lld-link"); break; + #if defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_NETBSD) + case Linker_mold: section_name = str_lit("mold-link"); break; + #endif + #if defined(GB_SYSTEM_WINDOWS) + case Linker_radlink: section_name = str_lit("rad-link"); break; + #endif + default: + gb_printf_err("'%.*s' linker is not supported on this platform\n", LIT(linker_choices[build_context.linker_choice])); + return 1; + } + + if (is_windows) { - String section_name = str_lit("msvc-link"); - switch (build_context.linker_choice) { - case Linker_Default: break; - case Linker_lld: section_name = str_lit("lld-link"); break; - case Linker_radlink: section_name = str_lit("rad-link"); break; - } timings_start_section(timings, section_name); gbString lib_str = gb_string_make(heap_allocator(), ""); @@ -277,13 +278,20 @@ try_cross_linking:; if (build_context.build_mode == BuildMode_DynamicLibrary) { link_settings = gb_string_append_fmt(link_settings, " /DLL"); + if (build_context.no_entry_point) { + link_settings = gb_string_append_fmt(link_settings, " /NOENTRY"); + } } else { - link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup"); + // For i386 with CRT, libcmt provides the entry point + // For other cases or no_crt, we need to specify the entry point + if (!(build_context.metrics.arch == TargetArch_i386 && !build_context.no_crt)) { + link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup"); + } } - if (build_context.pdb_filepath != "") { - String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); - link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); + if (build_context.build_paths[BuildPath_Symbols].name != "") { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(symbol_path)); } if (build_context.build_mode != BuildMode_StaticLibrary) { @@ -310,6 +318,12 @@ try_cross_linking:; String windows_sdk_bin_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Win_SDK_Bin_Path]); defer (gb_free(heap_allocator(), windows_sdk_bin_path.text)); + gbString lld_lto_flags = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(lld_lto_flags)); + if (build_context.lto_kind != LTO_None) { + lld_lto_flags = gb_string_append_fmt(lld_lto_flags, "/opt:lldltojobs=%d ", build_context.thread_count); + } + switch (build_context.linker_choice) { case Linker_lld: result = system_exec_command_line_app("msvc-lld-link", @@ -318,13 +332,15 @@ try_cross_linking:; "%.*s " "%.*s " "%s " + "%s " "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), - lib_str + lib_str, + lld_lto_flags ); if (result) { @@ -341,7 +357,7 @@ try_cross_linking:; "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -404,7 +420,7 @@ try_cross_linking:; "", LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -416,7 +432,8 @@ try_cross_linking:; } } } else { - timings_start_section(timings, str_lit("ld-link")); + + timings_start_section(timings, section_name); int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; @@ -428,8 +445,10 @@ try_cross_linking:; // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); + bool has_odin_clang_path_env = true; if (clang_path == NULL) { clang_path = "clang"; + has_odin_clang_path_env = false; } // NOTE(vassvik): needs to add the root to the library search paths, so that the full filenames of the library @@ -543,6 +562,19 @@ try_cross_linking:; LIT(obj_file), LIT(build_context.extra_assembler_flags) ); + } else if (build_context.metrics.arch == TargetArch_arm64) { + result = system_exec_command_line_app("clang", + "%s \"%.*s\" " + "-c -o \"%.*s\" " + "-target %.*s " + "%.*s " + "", + clang_path, + LIT(asm_file), + LIT(obj_file), + LIT(build_context.metrics.target_triplet), + LIT(build_context.extra_assembler_flags) + ); } else { // `nasm` only compiles x86 assembly. // Note(bumbread): I'm assuming nasm is installed on the host machine. @@ -589,7 +621,7 @@ try_cross_linking:; // Do not add libc again, this is added later already, and omitted with // the `-no-crt` flag, not skipping here would cause duplicate library // warnings when linking on darwin and might link libc silently even with `-no-crt`. - if (lib == str_lit("System.framework") || lib == str_lit("c")) { + if (lib == str_lit("System.framework") || lib == str_lit("System") || lib == str_lit("c")) { continue; } @@ -648,7 +680,7 @@ try_cross_linking:; defer (gb_string_free(glue)); glue = gb_string_append_fmt(glue, "bin/clang"); - glue = gb_string_append_fmt(glue, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + glue = gb_string_append_fmt(glue, " --target=%.*s%d ", LIT(build_context.metrics.target_triplet), ODIN_ANDROID_API_LEVEL); glue = gb_string_appendc(glue, "-c \""); glue = gb_string_append_length(glue, ODIN_ANDROID_NDK.text, ODIN_ANDROID_NDK.len); glue = gb_string_appendc(glue, "sources/android/native_app_glue/android_native_app_glue.c"); @@ -669,8 +701,9 @@ try_cross_linking:; glue = gb_string_appendc(glue, "\"-I"); glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); - glue = gb_string_appendc(glue, "sysroot/usr/include/aarch64-linux-android/"); - glue = gb_string_appendc(glue, "\" "); + glue = gb_string_appendc(glue, "sysroot/usr/include/"); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_LIB.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB.len); + glue = gb_string_appendc(glue, "/\" "); glue = gb_string_appendc(glue, "-Wno-macro-redefined "); @@ -717,7 +750,21 @@ try_cross_linking:; } if (build_context.build_mode == BuildMode_StaticLibrary) { - compiler_error("TODO(bill): -build-mode:static on non-windows targets"); + TIME_SECTION("Static Library Creation"); + + gbString ar_command = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(ar_command)); + + ar_command = gb_string_appendc(ar_command, "ar rcs "); + ar_command = gb_string_append_fmt(ar_command, "\"%.*s\" ", LIT(output_filename)); + ar_command = gb_string_appendc(ar_command, object_files); + + result = system_exec_command_line_app("ar", ar_command); + if (result) { + return result; + } + + return result; } // NOTE(dweiler): We use clang as a frontend for the linker as there are @@ -755,14 +802,18 @@ try_cross_linking:; } if (build_context.build_mode == BuildMode_Executable && build_context.reloc_mode == RelocMode_PIC) { - // Do not disable PIE, let the linker choose. (most likely you want it enabled) + if (build_context.metrics.os == TargetOs_linux) { + // Linux does not enable PIE by default but required for ASLR + link_settings = gb_string_appendc(link_settings, "-pie "); + } else { + // Do not disable PIE, let the linker choose. (most likely you want it enabled) + } } else if (build_context.build_mode != BuildMode_DynamicLibrary) { if (build_context.metrics.os != TargetOs_openbsd - && build_context.metrics.os != TargetOs_haiku && build_context.metrics.arch != TargetArch_riscv64 && !is_android ) { - // OpenBSD and Haiku default to PIE executable. do not pass -no-pie for it. + // OpenBSD defaults to PIE executable, do not pass -no-pie for it. link_settings = gb_string_appendc(link_settings, "-no-pie "); } } @@ -770,7 +821,65 @@ try_cross_linking:; gbString platform_lib_str = gb_string_make(heap_allocator(), ""); defer (gb_string_free(platform_lib_str)); if (build_context.metrics.os == TargetOs_darwin) { - platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -L/usr/local/lib "); + // Get the SDK path. + gbString darwin_sdk_path = gb_string_make(temporary_allocator(), ""); + + char const* darwin_platform_name = "MacOSX"; + char const* darwin_xcrun_sdk_name = "macosx"; + char const* darwin_min_version_id = "macosx"; + + const char* original_clang_path = clang_path; + + // NOTE(harold): We set the clang_path to run through xcrun because otherwise it complaints about the the sysroot + // being set to 'MacOSX' even though we've set the sysroot to the correct SDK (-Wincompatible-sysroot). + // This is because it is likely not using the SDK's toolchain Apple Clang but another one installed in the system. + switch (selected_subtarget) { + case Subtarget_iPhone: + darwin_platform_name = "iPhoneOS"; + darwin_xcrun_sdk_name = "iphoneos"; + darwin_min_version_id = "ios"; + if (!has_odin_clang_path_env) { + clang_path = "xcrun --sdk iphoneos clang"; + } + break; + case Subtarget_iPhoneSimulator: + darwin_platform_name = "iPhoneSimulator"; + darwin_xcrun_sdk_name = "iphonesimulator"; + darwin_min_version_id = "ios-simulator"; + if (!has_odin_clang_path_env) { + clang_path = "xcrun --sdk iphonesimulator clang"; + } + break; + } + + gbString darwin_find_sdk_cmd = gb_string_make(temporary_allocator(), ""); + darwin_find_sdk_cmd = gb_string_append_fmt(darwin_find_sdk_cmd, "xcrun --sdk %s --show-sdk-path", darwin_xcrun_sdk_name); + + if (!system_exec_command_line_app_output(darwin_find_sdk_cmd, &darwin_sdk_path)) { + + // Fallback to default clang, since `xcrun --sdk` did not work. + clang_path = original_clang_path; + + // Best-effort fallback to known locations + gbString darwin_sdk_path = gb_string_make(temporary_allocator(), ""); + darwin_sdk_path = gb_string_append_fmt(darwin_sdk_path, "/Library/Developer/CommandLineTools/SDKs/%s.sdk", darwin_platform_name); + + if (!path_is_directory(make_string_c(darwin_sdk_path))) { + gb_string_clear(darwin_sdk_path); + darwin_sdk_path = gb_string_append_fmt(darwin_sdk_path, "/Applications/Xcode.app/Contents/Developer/Platforms/%s.platform/Developer/SDKs/%s.sdk", darwin_platform_name); + + if (!path_is_directory(make_string_c(darwin_sdk_path))) { + gb_printf_err("Failed to find %s SDK\n", darwin_platform_name); + return -1; + } + } + } else { + // Trim the trailing newline. + darwin_sdk_path = gb_string_trim_space(darwin_sdk_path); + } + platform_lib_str = gb_string_append_fmt(platform_lib_str, "--sysroot %s ", darwin_sdk_path); + + platform_lib_str = gb_string_appendc(platform_lib_str, "-L/usr/local/lib "); // Homebrew's default library path, checking if it exists to avoid linking warnings. if (gb_file_exists("/opt/homebrew/lib")) { @@ -784,14 +893,31 @@ try_cross_linking:; // Only specify this flag if the user has given a minimum version to target. // This will cause warnings to show up for mismatched libraries. - if (build_context.minimum_os_version_string_given) { - link_settings = gb_string_append_fmt(link_settings, "-mmacosx-version-min=%.*s ", LIT(build_context.minimum_os_version_string)); + // NOTE(harold): For device subtargets we have to explicitly set the default version to + // avoid the same warning since we configure our own minimum version when compiling for devices. + if (build_context.minimum_os_version_string_given || selected_subtarget != Subtarget_Default) { + link_settings = gb_string_append_fmt(link_settings, "-m%s-version-min=%.*s ", darwin_min_version_id, LIT(build_context.minimum_os_version_string)); } if (build_context.build_mode != BuildMode_DynamicLibrary) { // This points the linker to where the entry point is link_settings = gb_string_appendc(link_settings, "-e _main "); } + } else if (build_context.metrics.os == TargetOs_freebsd) { + if (build_context.sanitizer_flags & (SanitizerFlag_Address | SanitizerFlag_Memory)) { + // It's imperative that `pthread` is linked before `libc`, + // otherwise ASan/MSan will be unable to call `pthread_key_create` + // because FreeBSD's `libthr` implementation of `pthread` + // needs to replace the relevant stubs first. + // + // (Presumably TSan implements its own `pthread` interface, + // which is why it isn't required.) + // + // See: https://reviews.llvm.org/D39254 + platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread "); + } + // FreeBSD pkg installs third-party shared libraries in /usr/local/lib. + platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-L/usr/local/lib "); } else if (build_context.metrics.os == TargetOs_openbsd) { // OpenBSD ports install shared libraries in /usr/local/lib. Also, we must explicitly link libpthread. platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread -Wl,-L/usr/local/lib "); @@ -799,6 +925,9 @@ try_cross_linking:; // need to pass -z nobtcfi in order to allow the resulting program to run under // OpenBSD 7.4 and newer. Once support is added at compile time, this can be dropped. platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-z,nobtcfi "); + } else if (build_context.metrics.os == TargetOs_linux) { + // required for RELRO + platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-z,now -Wl,-z,relro "); } if (is_android) { @@ -807,7 +936,10 @@ try_cross_linking:; GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len != 0); platform_lib_str = gb_string_appendc(platform_lib_str, "\"-L"); - platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.len); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len); + platform_lib_str = gb_string_appendc(platform_lib_str, "usr/lib/"); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB.len); + platform_lib_str = gb_string_append_fmt(platform_lib_str, "/%d", ODIN_ANDROID_API_LEVEL); platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); platform_lib_str = gb_string_appendc(platform_lib_str, "-landroid "); @@ -852,11 +984,25 @@ try_cross_linking:; gbString ndk_bin_directory = gb_string_make_length(temporary_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); link_command_line = gb_string_appendc(link_command_line, ndk_bin_directory); link_command_line = gb_string_appendc(link_command_line, "bin/clang"); - link_command_line = gb_string_append_fmt(link_command_line, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + link_command_line = gb_string_append_fmt(link_command_line, " --target=%.*s%d ", LIT(build_context.metrics.target_triplet), ODIN_ANDROID_API_LEVEL); } else { link_command_line = gb_string_appendc(link_command_line, clang_path); } link_command_line = gb_string_appendc(link_command_line, " -Wno-unused-command-line-argument "); + + if (build_context.lto_kind != LTO_None) { + link_command_line = gb_string_appendc(link_command_line, " -flto=thin"); + link_command_line = gb_string_append_fmt(link_command_line, " -flto-jobs=%d ", build_context.thread_count); + + if (build_context.ODIN_DEBUG) { + link_command_line = gb_string_appendc(link_command_line, " -g "); + } + + if (is_osx && !build_context.minimum_os_version_string_given) { + link_command_line = gb_string_appendc(link_command_line, " -Wno-override-module "); + } + } + link_command_line = gb_string_appendc(link_command_line, object_files); link_command_line = gb_string_append_fmt(link_command_line, " -o \"%.*s\" ", LIT(output_filename)); link_command_line = gb_string_append_fmt(link_command_line, " %s ", platform_lib_str); @@ -873,6 +1019,9 @@ try_cross_linking:; if (build_context.linker_choice == Linker_lld) { link_command_line = gb_string_append_fmt(link_command_line, " -fuse-ld=lld"); result = system_exec_command_line_app("lld-link", link_command_line); + } else if (build_context.linker_choice == Linker_mold) { + link_command_line = gb_string_append_fmt(link_command_line, " -fuse-ld=mold"); + result = system_exec_command_line_app("mold-link", link_command_line); } else { result = system_exec_command_line_app("ld-link", link_command_line); } diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index c8e1ca764..6aabe456f 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -144,7 +144,11 @@ gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType LLVMContextRef c = ft->ctx; LLVMAttributeRef noalias_attr = lb_create_enum_attribute(c, "noalias"); LLVMAttributeRef nonnull_attr = lb_create_enum_attribute(c, "nonnull"); +#if LLVM_VERSION_MAJOR >= 21 + LLVMAttributeRef nocapture_attr = lb_create_string_attribute(c, make_string_c("captures"), make_string_c("none")); +#else LLVMAttributeRef nocapture_attr = lb_create_enum_attribute(c, "nocapture"); +#endif unsigned arg_index = offset; for (unsigned i = 0; i < arg_count; i++) { @@ -385,7 +389,7 @@ namespace lbAbi386 { gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->args = compute_arg_types(c, arg_types, arg_count); ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple); @@ -467,7 +471,7 @@ namespace lbAbiAmd64Win64 { gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->args = compute_arg_types(c, arg_types, arg_count); ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple); @@ -522,11 +526,30 @@ namespace lbAbiAmd64Win64 { } }; + +gb_internal bool is_llvm_type_slice_like(LLVMTypeRef type) { + if (!lb_is_type_kind(type, LLVMStructTypeKind)) { + return false; + } + if (LLVMCountStructElementTypes(type) != 2) { + return false; + } + LLVMTypeRef fields[2] = {}; + LLVMGetStructElementTypes(type, fields); + if (!lb_is_type_kind(fields[0], LLVMPointerTypeKind)) { + return false; + } + return lb_is_type_kind(fields[1], LLVMIntegerTypeKind) && lb_sizeof(fields[1]) == 8; + +} + // NOTE(bill): I hate `namespace` in C++ but this is just because I don't want to prefix everything namespace lbAbiAmd64SysV { enum RegClass { RegClass_NoClass, RegClass_Int, + RegClass_SSEHs, + RegClass_SSEHv, RegClass_SSEFs, RegClass_SSEFv, RegClass_SSEDs, @@ -545,6 +568,8 @@ namespace lbAbiAmd64SysV { gb_internal bool is_sse(RegClass reg_class) { switch (reg_class) { + case RegClass_SSEHs: + case RegClass_SSEHv: case RegClass_SSEFs: case RegClass_SSEFv: case RegClass_SSEDs: @@ -592,7 +617,7 @@ namespace lbAbiAmd64SysV { gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->calling_convention = calling_convention; @@ -648,23 +673,6 @@ namespace lbAbiAmd64SysV { return false; } - gb_internal bool is_llvm_type_slice_like(LLVMTypeRef type) { - if (!lb_is_type_kind(type, LLVMStructTypeKind)) { - return false; - } - if (LLVMCountStructElementTypes(type) != 2) { - return false; - } - LLVMTypeRef fields[2] = {}; - LLVMGetStructElementTypes(type, fields); - if (!lb_is_type_kind(fields[0], LLVMPointerTypeKind)) { - return false; - } - return lb_is_type_kind(fields[1], LLVMIntegerTypeKind) && lb_sizeof(fields[1]) == 8; - - } - - gb_internal bool is_aggregate(LLVMTypeRef type) { LLVMTypeKind kind = LLVMGetTypeKind(type); switch (kind) { @@ -693,6 +701,8 @@ namespace lbAbiAmd64SysV { case RegClass_Int: needed_int += 1; break; + case RegClass_SSEHs: + case RegClass_SSEHv: case RegClass_SSEFs: case RegClass_SSEFv: case RegClass_SSEDs: @@ -804,6 +814,8 @@ namespace lbAbiAmd64SysV { to_write = RegClass_Memory; } else if (newv == RegClass_SSEUp) { switch (oldv) { + case RegClass_SSEHv: + case RegClass_SSEHs: case RegClass_SSEFv: case RegClass_SSEFs: case RegClass_SSEDv: @@ -850,14 +862,18 @@ namespace lbAbiAmd64SysV { } else if (oldv == RegClass_SSEUp) { oldv = RegClass_SSEDv; } else if (is_sse(oldv)) { - i++; - while (i != e && oldv == RegClass_SSEUp) { - i++; + for (i++; i < e; i++) { + RegClass v = (*cls)[cast(isize)i]; + if (v != RegClass_SSEUp) { + break; + } } } else if (oldv == RegClass_X87) { - i++; - while (i != e && oldv == RegClass_X87Up) { - i++; + for (i++; i < e; i++) { + RegClass v = (*cls)[cast(isize)i]; + if (v != RegClass_X87Up) { + break; + } } } else { i++; @@ -914,6 +930,7 @@ namespace lbAbiAmd64SysV { sz -= rs; break; } + case RegClass_SSEHv: case RegClass_SSEFv: case RegClass_SSEDv: case RegClass_SSEInt8: @@ -924,6 +941,10 @@ namespace lbAbiAmd64SysV { unsigned elems_per_word = 0; LLVMTypeRef elem_type = nullptr; switch (reg_class) { + case RegClass_SSEHv: + elems_per_word = 4; + elem_type = LLVMHalfTypeInContext(c); + break; case RegClass_SSEFv: elems_per_word = 2; elem_type = LLVMFloatTypeInContext(c); @@ -958,6 +979,10 @@ namespace lbAbiAmd64SysV { continue; } break; + case RegClass_SSEHs: + array_add(&types, LLVMHalfTypeInContext(c)); + sz -= 2; + break; case RegClass_SSEFs: array_add(&types, LLVMFloatTypeInContext(c)); sz -= 4; @@ -977,7 +1002,7 @@ namespace lbAbiAmd64SysV { return types[0]; } - return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, sz == 0); + return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, false); } gb_internal void classify_with(LLVMTypeRef t, Array *cls, i64 ix, i64 off) { @@ -1004,9 +1029,11 @@ namespace lbAbiAmd64SysV { break; } case LLVMPointerTypeKind: - case LLVMHalfTypeKind: unify(cls, ix + off/8, RegClass_Int); break; + case LLVMHalfTypeKind: + unify(cls, ix + off/8, (off%8 != 0) ? RegClass_SSEHv : RegClass_SSEHs); + break; case LLVMFloatTypeKind: unify(cls, ix + off/8, (off%8 == 4) ? RegClass_SSEFv : RegClass_SSEFs); break; @@ -1046,10 +1073,9 @@ namespace lbAbiAmd64SysV { i64 elem_sz = lb_sizeof(elem); LLVMTypeKind elem_kind = LLVMGetTypeKind(elem); RegClass reg = RegClass_NoClass; - unsigned elem_width = LLVMGetIntTypeWidth(elem); switch (elem_kind) { - case LLVMIntegerTypeKind: - case LLVMHalfTypeKind: + case LLVMIntegerTypeKind: { + unsigned elem_width = LLVMGetIntTypeWidth(elem); switch (elem_width) { case 8: reg = RegClass_SSEInt8; break; case 16: reg = RegClass_SSEInt16; break; @@ -1065,6 +1091,10 @@ namespace lbAbiAmd64SysV { GB_PANIC("Unhandled integer width for vector type %u", elem_width); } break; + }; + case LLVMHalfTypeKind: + reg = RegClass_SSEHv; + break; case LLVMFloatTypeKind: reg = RegClass_SSEFv; break; @@ -1098,7 +1128,7 @@ namespace lbAbiArm64 { gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->args = compute_arg_types(c, arg_types, arg_count); ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple); @@ -1231,38 +1261,24 @@ namespace lbAbiArm64 { } } else { i64 size = lb_sizeof(return_type); - if (size <= 16) { - LLVMTypeRef cast_type = nullptr; - - if (size == 0) { - cast_type = LLVMStructTypeInContext(c, nullptr, 0, false); - } else if (size <= 8) { - cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8)); - } else { - unsigned count = cast(unsigned)((size+7)/8); - - LLVMTypeRef llvm_i64 = LLVMIntTypeInContext(c, 64); - LLVMTypeRef *types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, count); - - i64 size_copy = size; - for (unsigned i = 0; i < count; i++) { - if (size_copy >= 8) { - types[i] = llvm_i64; - } else { - types[i] = LLVMIntTypeInContext(c, 8*cast(unsigned)size_copy); - } - size_copy -= 8; - } - GB_ASSERT(size_copy <= 0); - cast_type = LLVMStructTypeInContext(c, types, count, true); - } - return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr); - } else { + if (size > 16) { LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO(); LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type); return lb_arg_type_indirect(return_type, attr); } + + GB_ASSERT(size <= 16); + LLVMTypeRef cast_type = nullptr; + if (size == 0) { + cast_type = LLVMStructTypeInContext(c, nullptr, 0, false); + } else if (size <= 8) { + cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8)); + } else { + LLVMTypeRef llvm_i64 = LLVMIntTypeInContext(c, 64); + cast_type = llvm_array_type(llvm_i64, 2); + } + return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr); } } @@ -1327,17 +1343,19 @@ namespace lbAbiWasm { registers/arguments if possible rather than by pointer. */ gb_internal Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention, Type *original_type); - gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type); + gb_internal lbArgType compute_return_type(lbFunctionType *ft, LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, Type* original_type); enum {MAX_DIRECT_STRUCT_SIZE = 32}; gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->calling_convention = calling_convention; ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention, original_type); - ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple); + + GB_ASSERT(original_type->kind == Type_Proc); + ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple, original_type->Proc.results); return ft; } @@ -1373,7 +1391,7 @@ namespace lbAbiWasm { return false; } - gb_internal bool type_can_be_direct(LLVMTypeRef type, ProcCallingConvention calling_convention) { + gb_internal bool type_can_be_direct(LLVMTypeRef type, Type *original_type, ProcCallingConvention calling_convention) { LLVMTypeKind kind = LLVMGetTypeKind(type); i64 sz = lb_sizeof(type); if (sz == 0) { @@ -1386,9 +1404,21 @@ namespace lbAbiWasm { return false; } else if (kind == LLVMStructTypeKind) { unsigned count = LLVMCountStructElementTypes(type); - if (count == 1) { - return type_can_be_direct(LLVMStructGetTypeAtIndex(type, 0), calling_convention); + + // NOTE(laytan): raw unions are always structs with 1 field in LLVM, need to check our own def. + Type *bt = base_type(original_type); + if (bt->kind == Type_Struct && bt->Struct.is_raw_union) { + count = cast(unsigned)bt->Struct.fields.count; } + + if (count == 1) { + return type_can_be_direct( + LLVMStructGetTypeAtIndex(type, 0), + type_internal_index(original_type, 0), + calling_convention + ); + } + } else if (is_basic_register_type(type)) { return true; } @@ -1412,7 +1442,7 @@ namespace lbAbiWasm { return false; } - gb_internal lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type, ProcCallingConvention calling_convention) { + gb_internal lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type, Type *original_type, ProcCallingConvention calling_convention) { LLVMTypeKind kind = LLVMGetTypeKind(type); GB_ASSERT(kind == LLVMArrayTypeKind || kind == LLVMStructTypeKind); @@ -1420,15 +1450,15 @@ namespace lbAbiWasm { if (sz == 0) { return lb_arg_type_ignore(type); } - if (type_can_be_direct(type, calling_convention)) { + if (type_can_be_direct(type, original_type, calling_convention)) { return lb_arg_type_direct(type); } return lb_arg_type_indirect(type, nullptr); } - gb_internal lbArgType pseudo_slice(LLVMContextRef c, LLVMTypeRef type, ProcCallingConvention calling_convention) { + gb_internal lbArgType pseudo_slice(LLVMContextRef c, LLVMTypeRef type, Type *original_type, ProcCallingConvention calling_convention) { if (build_context.metrics.ptr_size < build_context.metrics.int_size && - type_can_be_direct(type, calling_convention)) { + type_can_be_direct(type, original_type, calling_convention)) { LLVMTypeRef types[2] = { LLVMStructGetTypeAtIndex(type, 0), // ignore padding @@ -1437,7 +1467,7 @@ namespace lbAbiWasm { LLVMTypeRef new_type = LLVMStructTypeInContext(c, types, gb_count_of(types), false); return lb_arg_type_direct(type, new_type, nullptr, nullptr); } else { - return is_struct(c, type, calling_convention); + return is_struct(c, type, original_type, calling_convention); } } @@ -1458,9 +1488,9 @@ namespace lbAbiWasm { LLVMTypeKind kind = LLVMGetTypeKind(t); if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) { if (is_type_slice(ptype) || is_type_string(ptype)) { - args[i] = pseudo_slice(c, t, calling_convention); + args[i] = pseudo_slice(c, t, ptype, calling_convention); } else { - args[i] = is_struct(c, t, calling_convention); + args[i] = is_struct(c, t, ptype, calling_convention); } } else { args[i] = non_struct(c, t, false); @@ -1469,11 +1499,11 @@ namespace lbAbiWasm { return args; } - gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type) { + gb_internal lbArgType compute_return_type(lbFunctionType *ft, LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, Type* original_type) { if (!return_is_defined) { return lb_arg_type_direct(LLVMVoidTypeInContext(c)); } else if (lb_is_type_kind(return_type, LLVMStructTypeKind) || lb_is_type_kind(return_type, LLVMArrayTypeKind)) { - if (type_can_be_direct(return_type, ft->calling_convention)) { + if (type_can_be_direct(return_type, original_type, ft->calling_convention)) { return lb_arg_type_direct(return_type); } else if (ft->calling_convention != ProcCC_CDecl) { i64 sz = lb_sizeof(return_type); @@ -1485,7 +1515,35 @@ namespace lbAbiWasm { } } - LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO(); + // Multiple returns. + if (return_is_tuple) { \ + lbArgType return_arg = {}; + if (lb_is_type_kind(return_type, LLVMStructTypeKind)) { + unsigned field_count = LLVMCountStructElementTypes(return_type); + if (field_count > 1) { + ft->original_arg_count = ft->args.count; + ft->multiple_return_original_type = return_type; + + for (unsigned i = 0; i < field_count-1; i++) { + LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(return_type, i); + LLVMTypeRef field_pointer_type = LLVMPointerType(field_type, 0); + lbArgType ret_partial = lb_arg_type_direct(field_pointer_type); + array_add(&ft->args, ret_partial); + } + + return_arg = compute_return_type( + ft, + c, + LLVMStructGetTypeAtIndex(return_type, field_count-1), + true, false, + type_internal_index(original_type, field_count-1) + ); + } + } + if (return_arg.type != nullptr) { + return return_arg; + } + } LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type); return lb_arg_type_indirect(return_type, attr); @@ -1500,7 +1558,7 @@ namespace lbAbiArm32 { gb_internal LB_ABI_INFO(abi_info) { LLVMContextRef c = m->ctx; - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention); ft->ret = compute_return_type(c, return_type, return_is_defined); @@ -1809,7 +1867,7 @@ namespace lbAbiRiscv64 { } gb_internal LB_ABI_INFO(abi_info) { - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = m->ctx; ft->calling_convention = calling_convention; @@ -1831,7 +1889,7 @@ gb_internal LB_ABI_INFO(lb_get_abi_info_internal) { case ProcCC_None: case ProcCC_InlineAsm: { - lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); + lbFunctionType *ft = permanent_alloc_item(); ft->ctx = c; ft->args = array_make(lb_function_type_args_allocator(), arg_count); for (unsigned i = 0; i < arg_count; i++) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 1be652107..f9e049621 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -8,9 +8,15 @@ #endif #ifndef LLVM_IGNORE_VERIFICATION -#define LLVM_IGNORE_VERIFICATION 0 +#define LLVM_IGNORE_VERIFICATION build_context.internal_ignore_llvm_verification #endif +#ifndef LLVM_WEAK_MONOMORPHIZATION +#define LLVM_WEAK_MONOMORPHIZATION (USE_SEPARATE_MODULES && build_context.internal_weak_monomorphization) +#endif + +#define LLVM_SET_INTERNAL_WEAK_LINKAGE(value) LLVMSetLinkage(value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage); + #include "llvm_backend.hpp" #include "llvm_abi.cpp" @@ -33,12 +39,10 @@ gb_internal String get_default_microarchitecture() { // x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3 // x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL - if (ODIN_LLVM_MINIMUM_VERSION_12) { - if (build_context.metrics.os == TargetOs_freestanding) { - default_march = str_lit("x86-64"); - } else { - default_march = str_lit("x86-64-v2"); - } + if (build_context.metrics.os == TargetOs_freestanding) { + default_march = str_lit("x86-64"); + } else { + default_march = str_lit("x86-64-v2"); } } else if (build_context.metrics.arch == TargetArch_riscv64) { default_march = str_lit("generic-rv64"); @@ -62,6 +66,19 @@ gb_internal String get_final_microarchitecture() { gb_internal String get_default_features() { BuildContext *bc = &build_context; + if (bc->microarch == str_lit("native")) { + String features = make_string_c(LLVMGetHostCPUFeatures()); + + // Update the features string so LLVM uses it later. + if (bc->target_features_string.len > 0) { + bc->target_features_string = concatenate3_strings(permanent_allocator(), features, str_lit(","), bc->target_features_string); + } else { + bc->target_features_string = features; + } + + return features; + } + int off = 0; for (int i = 0; i < bc->metrics.arch; i += 1) { off += target_microarch_counts[i]; @@ -167,16 +184,16 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) { LLVMValueRef other_global = nullptr; if (ec.e->kind == Entity_Variable) { other_global = LLVMGetNamedGlobal(ec.other_module->mod, ec.cname); - if (other_global) { - LLVMSetLinkage(other_global, LLVMWeakAnyLinkage); + if (other_global && (LLVMGetInitializer(other_global) != nullptr || LLVMIsExternallyInitialized(other_global))) { + LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global); if (!ec.e->Variable.is_export && !ec.e->Variable.is_foreign) { LLVMSetVisibility(other_global, LLVMHiddenVisibility); } } } else if (ec.e->kind == Entity_Procedure) { other_global = LLVMGetNamedFunction(ec.other_module->mod, ec.cname); - if (other_global) { - LLVMSetLinkage(other_global, LLVMWeakAnyLinkage); + if (other_global && LLVMCountBasicBlocks(other_global) != 0) { + LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global); if (!ec.e->Procedure.is_export && !ec.e->Procedure.is_foreign) { LLVMSetVisibility(other_global, LLVMHiddenVisibility); } @@ -235,33 +252,19 @@ gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx gb_internal String lb_internal_gen_name_from_type(char const *prefix, Type *type) { gbString str = gb_string_make(permanent_allocator(), prefix); - u64 hash = type_hash_canonical_type(type); - str = gb_string_appendc(str, "-"); - str = gb_string_append_fmt(str, "%llu", cast(unsigned long long)hash); + str = gb_string_appendc(str, "$$"); + gbString ct = temp_canonical_string(type); + str = gb_string_append_length(str, ct, gb_string_length(ct)); String proc_name = make_string(cast(u8 const *)str, gb_string_length(str)); return proc_name; } - -gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { - type = base_type(type); - GB_ASSERT(is_type_comparable(type)); +gb_internal void lb_equal_proc_generate_body(lbModule *m, lbProcedure *p) { + Type *type = p->internal_gen_type; Type *pt = alloc_type_pointer(type); LLVMTypeRef ptr_type = lb_type(m, pt); - String proc_name = lb_internal_gen_name_from_type("__$equal", type); - lbProcedure **found = string_map_get(&m->gen_procs, proc_name); - lbProcedure *compare_proc = nullptr; - if (found) { - compare_proc = *found; - GB_ASSERT(compare_proc != nullptr); - return {compare_proc->value, compare_proc->type}; - } - - - lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); - string_map_set(&m->gen_procs, proc_name, p); lb_begin_procedure_body(p); LLVMSetLinkage(p->value, LLVMInternalLinkage); @@ -389,9 +392,29 @@ gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { } lb_end_procedure_body(p); +} - compare_proc = p; - return {compare_proc->value, compare_proc->type}; +gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type) { + type = base_type(type); + GB_ASSERT(is_type_comparable(type)); + + String proc_name = lb_internal_gen_name_from_type("__$equal", type); + lbProcedure **found = string_map_get(&m->gen_procs, proc_name); + if (found) { + lbProcedure *p = *found; + GB_ASSERT(p != nullptr); + return {p->value, p->type}; + } + + lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); + string_map_set(&m->gen_procs, proc_name, p); + p->internal_gen_type = type; + p->generate_body = lb_equal_proc_generate_body; + + // p->generate_body(m, p); + mpsc_enqueue(&m->procedures_to_generate, p); + + return {p->value, p->type}; } gb_internal lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue seed) { @@ -620,6 +643,7 @@ gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type) { #define LLVM_SET_VALUE_NAME(value, name) LLVMSetValueName2((value), (name), gb_count_of((name))-1); + gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { GB_ASSERT(!build_context.dynamic_map_calls); type = base_type(type); @@ -634,6 +658,9 @@ gb_internal lbValue lb_map_get_proc_for_type(lbModule *m, Type *type) { lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_map_get_proc); string_map_set(&m->gen_procs, proc_name, p); + + p->internal_gen_type = type; + lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); @@ -1153,15 +1180,6 @@ gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_pt return lb_emit_runtime_call(p, "__dynamic_map_reserve", args); } - -struct lbGlobalVariable { - lbValue var; - lbValue init; - DeclInfo *decl; - bool is_initialized; -}; - - gb_internal lbProcedure *lb_create_objc_names(lbModule *main_module) { if (build_context.metrics.os != TargetOs_darwin) { return nullptr; @@ -1264,7 +1282,13 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { case Basic_string: return build_context.metrics.int_size == 4 ? str_lit("{string=*i}") : str_lit("{string=*q}"); + case Basic_string16: + return build_context.metrics.int_size == 4 ? str_lit("{string16=*i}") : str_lit("{string16=*q}"); + case Basic_cstring: return str_lit("*"); + case Basic_cstring16: return str_lit("*"); + + case Basic_any: return str_lit("{any=^v^v}"); // rawptr + ^Type_Info case Basic_typeid: @@ -1300,18 +1324,8 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { const bool is_union = base->kind == Type_Union; if (!is_union) { - // Check for objc_SEL - if (internal_check_is_assignable_to(base, t_objc_SEL)) { - return str_lit(":"); - } - - // Check for objc_Class - if (internal_check_is_assignable_to(base, t_objc_SEL)) { - return str_lit("#"); - } - // Treat struct as an Objective-C Class? - if (has_type_got_objc_class_attribute(base) && pointer_depth == 0) { + if (has_type_got_objc_class_attribute(t) && pointer_depth == 0) { return str_lit("#"); } } @@ -1332,12 +1346,12 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { s = gb_string_append_length(s, "=", 1); if (!is_union) { - for( auto& f : base->Struct.fields ) { + for (auto &f : base->Struct.fields) { String field_type = lb_get_objc_type_encoding(f->type, pointer_depth); s = gb_string_append_length(s, field_type.text, field_type.len); } } else { - for( auto& v : base->Union.variants ) { + for (auto &v : base->Union.variants) { String variant_type = lb_get_objc_type_encoding(v, pointer_depth); s = gb_string_append_length(s, variant_type.text, variant_type.len); } @@ -1354,6 +1368,17 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { return str_lit("?"); case Type_Pointer: { + // NOTE: These types are pointers, so we must check here for special cases + // Check for objc_SEL + if (internal_check_is_assignable_to(t, t_objc_SEL)) { + return str_lit(":"); + } + + // Check for objc_Class + if (internal_check_is_assignable_to(t, t_objc_Class)) { + return str_lit("#"); + } + String pointee = lb_get_objc_type_encoding(t->Pointer.elem, pointer_depth +1); // Special case for Objective-C Objects if (pointer_depth == 0 && pointee == "@") { @@ -1405,8 +1430,21 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { return str_lit("?"); case Type_Proc: return str_lit("?"); - case Type_BitSet: - return lb_get_objc_type_encoding(t->BitSet.underlying, pointer_depth); + case Type_BitSet: { + Type *bitset_integer_type = t->BitSet.underlying; + if (!bitset_integer_type) { + switch (t->cached_size) { + case 1: bitset_integer_type = t_u8; break; + case 2: bitset_integer_type = t_u16; break; + case 4: bitset_integer_type = t_u32; break; + case 8: bitset_integer_type = t_u64; break; + case 16: bitset_integer_type = t_u128; break; + } + } + GB_ASSERT_MSG(bitset_integer_type, "Could not determine bit_set integer size for objc_type_encoding"); + + return lb_get_objc_type_encoding(bitset_integer_type, pointer_depth); + } case Type_SimdVector: { String type_str = lb_get_objc_type_encoding(t->SimdVector.elem, pointer_depth); @@ -1440,7 +1478,10 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { struct lbObjCGlobalClass { lbObjCGlobal g; - lbValue class_value; // Local registered class value + union { + lbValue class_value; // Local registered class value + lbAddr class_global; // Global class pointer. Placeholder for class implementations which are registered in order of definition. + }; }; gb_internal void lb_register_objc_thing( @@ -1470,44 +1511,43 @@ gb_internal void lb_register_objc_thing( LLVMSetInitializer(v.value, LLVMConstNull(t)); } - lbValue class_ptr = {}; - lbValue class_name = lb_const_value(m, t_cstring, exact_value_string(g.name)); - // If this class requires an implementation, save it for registration below. if (g.class_impl_type != nullptr) { // Make sure the superclass has been initialized before us - lbValue superclass_value = lb_const_nil(m, t_objc_Class); - auto &tn = g.class_impl_type->Named.type_name->TypeName; Type *superclass = tn.objc_superclass; if (superclass != nullptr) { - auto& superclass_global = string_map_must_get(&class_map, superclass->Named.type_name->TypeName.objc_class_name); + auto &superclass_global = string_map_must_get(&class_map, superclass->Named.type_name->TypeName.objc_class_name); lb_register_objc_thing(handled, m, args, class_impls, class_map, p, superclass_global.g, call); - GB_ASSERT(superclass_global.class_value.value); - - superclass_value = superclass_global.class_value; + GB_ASSERT(superclass_global.class_global.addr.value); } - args.count = 3; - args[0] = superclass_value; - args[1] = class_name; - args[2] = lb_const_int(m, t_uint, 0); - class_ptr = lb_emit_runtime_call(p, "objc_allocateClassPair", args); + lbObjCGlobalClass impl_global = {}; + impl_global.g = g; + impl_global.class_global = addr; - array_add(&class_impls, lbObjCGlobalClass{g, class_ptr}); + array_add(&class_impls, impl_global); + + lbObjCGlobalClass* class_global = string_map_get(&class_map, g.name); + if (class_global != nullptr) { + class_global->class_global = addr; + } } else { + lbValue class_ptr = {}; + lbValue class_name = lb_const_value(m, t_cstring, exact_value_string(g.name)); + args.count = 1; args[0] = class_name; class_ptr = lb_emit_runtime_call(p, call, args); - } - lb_addr_store(p, addr, class_ptr); + lb_addr_store(p, addr, class_ptr); - lbObjCGlobalClass* class_global = string_map_get(&class_map, g.name); - if (class_global != nullptr) { - class_global->class_value = class_ptr; + lbObjCGlobalClass* class_global = string_map_get(&class_map, g.name); + if (class_global != nullptr) { + class_global->class_value = class_ptr; + } } } @@ -1531,6 +1571,7 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { for (Entity *e = {}; mpsc_dequeue(&gen->info->objc_class_implementations, &e); /**/) { GB_ASSERT(e->kind == Entity_TypeName && e->TypeName.objc_is_implementation); lb_handle_objc_find_or_register_class(p, e->TypeName.objc_class_name, e->type); + error(e->token, "Objective-C related things are not allowed with '-bedrock'"); } // Ensure classes that have been implicitly referenced through @@ -1555,12 +1596,18 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { } for (auto pair : class_set) { - auto& tn = pair.type->Named.type_name->TypeName; + Entity *e = pair.type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + auto &tn = e->TypeName; Type *class_impl = !tn.objc_is_implementation ? nullptr : pair.type; lb_handle_objc_find_or_register_class(p, tn.objc_class_name, class_impl); + + if (build_context.bedrock) { + error(e->token, "Objective-C related things are not allowed with '-bedrock'"); + } } for (lbObjCGlobal g = {}; mpsc_dequeue(&gen->objc_classes, &g); /**/) { - array_add( &referenced_classes, g ); + array_add(&referenced_classes, g); } // Add all class globals to a map so that we can look them up dynamically @@ -1570,7 +1617,7 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { string_map_init(&global_class_map, (usize)gen->objc_classes.count); defer (string_map_destroy(&global_class_map)); - for (lbObjCGlobal g :referenced_classes) { + for (lbObjCGlobal g : referenced_classes) { string_map_set(&global_class_map, g.name, lbObjCGlobalClass{g}); } @@ -1578,21 +1625,21 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { lb_begin_procedure_body(p); // Register class globals, gathering classes that must be implemented - for (auto& kv : global_class_map) { + for (auto &kv : global_class_map) { lb_register_objc_thing(handled, m, args, class_impls, global_class_map, p, kv.value.g, "objc_lookUpClass"); } // Prefetch selectors for implemented methods so that they can also be registered. - for (const auto& cd : class_impls) { - auto& g = cd.g; + for (auto const &cd : class_impls) { + auto &g = cd.g; Type *class_type = g.class_impl_type; - Array* methods = map_get(&m->info->objc_method_implementations, class_type); + Array *methods = map_get(&m->info->objc_method_implementations, class_type); if (!methods) { continue; } - for (const ObjcMethodData& md : *methods) { + for (ObjcMethodData const &md : *methods) { lb_handle_objc_find_or_register_selector(p, md.ac.objc_selector); } } @@ -1615,11 +1662,44 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { map_set(&ivar_map, g.class_impl_type, g); } - for (const auto &cd : class_impls) { + for (auto const &cd : class_impls) { auto &g = cd.g; - Type *class_type = g.class_impl_type; + + Type *class_type = g.class_impl_type; Type *class_ptr_type = alloc_type_pointer(class_type); - lbValue class_value = cd.class_value; + Entity *e = class_type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + + if (build_context.bedrock) { + error(e->token, "Objective-C related things are not allowed with '-bedrock'"); + } + + // Begin class registration: create class pair and update global reference + lbValue class_value = {}; + + { + lbValue superclass_value = lb_const_nil(m, t_objc_Class); + + auto &tn = e->TypeName; + Type *superclass = tn.objc_superclass; + + if (superclass != nullptr) { + auto& superclass_global = string_map_must_get(&global_class_map, tn.objc_class_name); + superclass_value = superclass_global.class_value; + } + + args.count = 3; + args[0] = superclass_value; + args[1] = lb_const_value(m, t_cstring, exact_value_string(g.name)); + args[2] = lb_const_int(m, t_uint, 0); + class_value = lb_emit_runtime_call(p, "objc_allocateClassPair", args); + + lbObjCGlobalClass &mapped_global = string_map_must_get(&global_class_map, tn.objc_class_name); + lb_addr_store(p, mapped_global.class_global, class_value); + + mapped_global.class_value = class_value; + } + Type *ivar_type = class_type->Named.type_name->TypeName.objc_ivar; @@ -1639,20 +1719,34 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { is_context_provider_ivar = ivar_type != nullptr && internal_check_is_assignable_to(contex_provider_self_named_type, ivar_type); } - Array *methods = map_get(&m->info->objc_method_implementations, class_type); if (!methods) { continue; } + // Check if it has any class methods ahead of time so that we know to grab the meta_class + lbValue meta_class_value = {}; for (const ObjcMethodData &md : *methods) { - GB_ASSERT( md.proc_entity->kind == Entity_Procedure); + if (!md.ac.objc_is_class_method) { + continue; + } + + // Get the meta_class + args.count = 1; + args[0] = class_value; + meta_class_value = lb_emit_runtime_call(p, "object_getClass", args); + + break; + } + + for (const ObjcMethodData &md : *methods) { + GB_ASSERT(md.proc_entity->kind == Entity_Procedure); Type *method_type = md.proc_entity->type; String proc_name = make_string_c("__$objc_method::"); proc_name = concatenate_strings(temporary_allocator(), proc_name, g.name); proc_name = concatenate_strings(temporary_allocator(), proc_name, str_lit("::")); - proc_name = concatenate_strings( permanent_allocator(), proc_name, md.ac.objc_name); + proc_name = concatenate_strings(permanent_allocator(), proc_name, md.ac.objc_name); wrapper_args.count = 2; wrapper_args[0] = md.ac.objc_is_class_method ? t_objc_Class : class_ptr_type; @@ -1683,17 +1777,21 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { wrapper_results_tuple, method_type->Proc.result_count, false, ProcCC_CDecl); lbProcedure *wrapper_proc = lb_create_dummy_procedure(m, proc_name, wrapper_proc_type); - lb_add_attribute_to_proc(wrapper_proc->module, wrapper_proc->value, "nounwind"); + + lb_add_function_type_attributes(wrapper_proc->value, lb_get_function_type(m, wrapper_proc_type), ProcCC_CDecl); // Emit the wrapper - LLVMSetLinkage(wrapper_proc->value, LLVMExternalLinkage); + // LLVMSetLinkage(wrapper_proc->value, LLVMInternalLinkage); + LLVMSetDLLStorageClass(wrapper_proc->value, LLVMDLLExportStorageClass); + lb_add_attribute_to_proc(wrapper_proc->module, wrapper_proc->value, "nounwind"); + lb_begin_procedure_body(wrapper_proc); { + LLVMValueRef context_addr = nullptr; if (method_type->Proc.calling_convention == ProcCC_Odin) { GB_ASSERT(context_provider); // Emit the get odin context call - get_context_args[0] = lbValue { wrapper_proc->raw_input_parameters[0], contex_provider_self_ptr_type, @@ -1709,44 +1807,58 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { get_context_args[0] = lb_handle_objc_ivar_for_objc_object_pointer(wrapper_proc, real_self); } - lbValue context = lb_emit_call(wrapper_proc, context_provider_proc_value, get_context_args); - lbAddr context_addr = lb_addr(lb_address_from_load_or_generate_local(wrapper_proc, context)); - lb_push_context_onto_stack(wrapper_proc, context_addr); + lbValue context = lb_emit_call(wrapper_proc, context_provider_proc_value, get_context_args); + context_addr = lb_address_from_load(wrapper_proc, context).value;//lb_address_from_load_or_generate_local(wrapper_proc, context)); + // context_addr = LLVMGetOperand(context.value, 0); } + isize method_forward_arg_count = method_param_count + method_param_offset; + isize method_forward_return_arg_offset = 0; + auto raw_method_args = array_make(temporary_allocator(), 0, method_forward_arg_count+1); - auto method_call_args = array_make(temporary_allocator(), method_param_count + method_param_offset); + lbValue method_proc_value = lb_find_procedure_value_from_entity(m, md.proc_entity); + lbFunctionType* ft = lb_get_function_type(m, method_type); + bool has_return = false; + lbArgKind return_kind = {}; + + if (wrapper_results_tuple != nullptr) { + has_return = true; + return_kind = ft->ret.kind; + + if (return_kind == lbArg_Indirect) { + method_forward_return_arg_offset = 1; + array_add(&raw_method_args, wrapper_proc->return_ptr.addr.value); + } + } if (!md.ac.objc_is_class_method) { - method_call_args[0] = lbValue { - wrapper_proc->raw_input_parameters[0], - class_ptr_type, - }; + array_add(&raw_method_args, wrapper_proc->raw_input_parameters[method_forward_return_arg_offset]); } for (isize i = 0; i < method_param_count; i++) { - method_call_args[i+method_param_offset] = lbValue { - wrapper_proc->raw_input_parameters[i+2], - method_type->Proc.params->Tuple.variables[i+method_param_offset]->type, - }; + array_add(&raw_method_args, wrapper_proc->raw_input_parameters[i+2+method_forward_return_arg_offset]); + } + + if (method_type->Proc.calling_convention == ProcCC_Odin) { + array_add(&raw_method_args, context_addr); } - lbValue method_proc_value = lb_find_procedure_value_from_entity(m, md.proc_entity); // Call real procedure for method from here, passing the parameters expected, if any. - lbValue return_value = lb_emit_call(wrapper_proc, method_proc_value, method_call_args); + LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(m, method_type); + LLVMValueRef ret_val_raw = LLVMBuildCall2(wrapper_proc->builder, fnp, method_proc_value.value, raw_method_args.data, (unsigned)raw_method_args.count, ""); - if (wrapper_results_tuple != nullptr) { - auto &result_var = method_type->Proc.results->Tuple.variables[0]; - return_value = lb_emit_conv(wrapper_proc, return_value, result_var->type); - lb_build_return_stmt_internal(wrapper_proc, return_value, result_var->token.pos); + if (has_return && return_kind != lbArg_Indirect) { + LLVMBuildRet(wrapper_proc->builder, ret_val_raw); + } + else { + LLVMBuildRetVoid(wrapper_proc->builder); } } lb_end_procedure_body(wrapper_proc); - // Add the method to the class String method_encoding = str_lit("v"); - // TODO (harold): Checker must ensure that objc_methods have a single return value or none! + GB_ASSERT(method_type->Proc.result_count <= 1); if (method_type->Proc.result_count != 0) { method_encoding = lb_get_objc_type_encoding(method_type->Proc.results->Tuple.variables[0]->type); @@ -1758,8 +1870,8 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { method_encoding = concatenate_strings(temporary_allocator(), method_encoding, str_lit("#:")); } - for (isize i = method_param_offset; i < method_param_count; i++) { - Type *param_type = method_type->Proc.params->Tuple.variables[i]->type; + for (isize i = 0; i < method_param_count; i++) { + Type *param_type = method_type->Proc.params->Tuple.variables[i + method_param_offset]->type; String param_encoding = lb_get_objc_type_encoding(param_type); method_encoding = concatenate_strings(temporary_allocator(), method_encoding, param_encoding); @@ -1770,13 +1882,15 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { GB_ASSERT(sel_address); lbValue selector_value = lb_addr_load(p, *sel_address); + lbValue target_class = !md.ac.objc_is_class_method ? class_value : meta_class_value; + args.count = 4; - args[0] = class_value; // Class + args[0] = target_class; // Class args[1] = selector_value; // SEL args[2] = lbValue { wrapper_proc->value, wrapper_proc->type }; args[3] = lb_const_value(m, t_cstring, exact_value_string(method_encoding)); - // TODO(harold): Emit check BOOL result and panic if false. + // TODO(harold): Emit check BOOL result and panic if false? lb_emit_runtime_call(p, "class_addMethod", args); } // End methods @@ -1824,7 +1938,7 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { // Defined in an external package, define it now in the main package LLVMTypeRef t = lb_type(m, t_int); - lbValue global{}; + lbValue global = {}; global.value = LLVMAddGlobal(m->mod, t, g.global_name); global.type = t_int_ptr; @@ -1833,7 +1947,10 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { ivar_addr = lb_addr(global); } - String class_name = g.class_impl_type->Named.type_name->TypeName.objc_class_name; + Entity *e = g.class_impl_type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + + String class_name = e->TypeName.objc_class_name; lbValue class_value = string_map_must_get(&global_class_map, class_name).class_value; args.count = 2; @@ -1847,6 +1964,10 @@ gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { lbValue ivar_offset_int = lb_emit_conv(p, ivar_offset, t_int); lb_addr_store(p, ivar_addr, ivar_offset_int); + + if (build_context.bedrock) { + error(e->token, "Objective-C related things are not allowed with '-bedrock'"); + } } lb_end_procedure_body(p); @@ -1876,12 +1997,16 @@ gb_internal void lb_verify_function(lbModule *m, lbProcedure *p, bool dump_ll=fa } gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) { + if (LLVM_IGNORE_VERIFICATION) { + return 0; + } + char *llvm_error = nullptr; defer (LLVMDisposeMessage(llvm_error)); lbModule *m = cast(lbModule *)data; if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) { - gb_printf_err("LLVM Error:\n%s\n", llvm_error); + gb_printf_err("LLVM Error in module %s:\n%s\n", m->module_name, llvm_error); if (build_context.keep_temp_files) { TIME_SECTION("LLVM Print Module to File"); String filepath_ll = lb_filepath_ll_for_module(m); @@ -1897,6 +2022,144 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) { return 0; } +gb_internal bool lb_init_global_var(lbModule *m, lbProcedure *p, Entity *e, Ast *init_expr, lbGlobalVariable &var) { + if (init_expr != nullptr) { + lbValue init = lb_build_expr(p, init_expr); + if (init.value == nullptr) { + LLVMTypeRef global_type = llvm_addr_type(p->module, var.var); + if (is_type_untyped_nil(init.type)) { + LLVMSetInitializer(var.var.value, LLVMConstNull(global_type)); + var.is_initialized = true; + + if (e->Variable.is_rodata) { + LLVMSetGlobalConstant(var.var.value, true); + } + return true; + } + GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr)); + } + + if (is_type_any(e->type)) { + var.init = init; + } else if (lb_is_const_or_global(init)) { + if (!var.is_initialized) { + if (is_type_proc(init.type)) { + init.value = LLVMConstPointerCast(init.value, lb_type(p->module, init.type)); + } + LLVMSetInitializer(var.var.value, init.value); + var.is_initialized = true; + + if (e->Variable.is_rodata) { + LLVMSetGlobalConstant(var.var.value, true); + } + return true; + } + } else { + var.init = init; + } + } + + if (var.init.value != nullptr) { + GB_ASSERT(!var.is_initialized); + Type *t = type_deref(var.var.type); + + // NOTE: 'any' literals or 'any's that point to other variables can be handled by the generic path + if (is_type_any(t) && !is_type_any(var.init.type) && init_expr->tav.mode != Addressing_Variable) { + // NOTE(bill): Edge case for 'any' type + Type *var_type = default_type(var.init.type); + gbString var_name = gb_string_make(permanent_allocator(), "__$global_any::"); + gbString e_str = string_canonical_entity_name(temporary_allocator(), e); + var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str)); + lbAddr g = lb_add_global_generated_with_name(m, var_type, {}, make_string_c(var_name)); + lb_addr_store(p, g, var.init); + lbValue gp = lb_addr_get_ptr(p, g); + + lbValue data = lb_emit_struct_ep(p, var.var, 0); + lbValue ti = lb_emit_struct_ep(p, var.var, 1); + lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr)); + lb_emit_store(p, ti, lb_typeid(p->module, var_type)); + } else { + i64 sz = type_size_of(e->type); + if (sz >= 4 * 1024) { + warning(init_expr, "[Possible Code Generation Issue] Non-constant initialization is large (%lld bytes), and might cause problems with LLVM", cast(long long)sz); + } + + LLVMTypeRef vt = llvm_addr_type(p->module, var.var); + lbValue src0 = lb_emit_conv(p, var.init, t); + LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt); + LLVMValueRef dst = var.var.value; + LLVMBuildStore(p->builder, src, dst); + } + + var.is_initialized = true; + + if (build_context.disable_non_constant_globals) { + error(e->token, "Non-constant initialization of a global variable is disallowed with '-disable_non_constant_globals'"); + } + } + return false; +} + + +gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedure *p) { + lb_begin_procedure_body(p); + + lb_setup_type_info_data(m); + + if (p->objc_names) { + LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(m, p->objc_names->type), p->objc_names->value, nullptr, 0, ""); + } + Type *dummy_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); + LLVMTypeRef raw_dummy_type = lb_type_internal_for_procedures_raw(m, dummy_type); + + for (auto &var : *p->global_variables) { + if (var.is_initialized) { + continue; + } + + lbModule *entity_module = m; + + Entity *e = var.decl->entity; + GB_ASSERT(e->kind == Entity_Variable); + e->code_gen_module = entity_module; + Ast *init_expr = var.decl->init_expr; + + if (init_expr == nullptr && var.init.value == nullptr) { + continue; + } + + if (false && type_size_of(e->type) > 8) { + String ename = lb_get_entity_name(m, e); + gbString name = gb_string_make(permanent_allocator(), ""); + name = gb_string_appendc(name, "__$startup$"); + name = gb_string_append_length(name, ename.text, ename.len); + + lbProcedure *dummy = lb_create_dummy_procedure(m, make_string_c(name), dummy_type); + dummy->is_startup = true; + LLVMSetVisibility(dummy->value, LLVMHiddenVisibility); + LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value); + + lb_begin_procedure_body(dummy); + lb_init_global_var(m, dummy, e, init_expr, var); + lb_end_procedure_body(dummy); + + LLVMValueRef context_ptr = lb_find_or_generate_context_ptr(p).addr.value; + LLVMValueRef cast_ctx = LLVMBuildBitCast(p->builder, context_ptr, LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0), ""); + LLVMBuildCall2(p->builder, raw_dummy_type, dummy->value, &cast_ctx, 1, ""); + } else { + lb_init_global_var(m, p, e, init_expr, var); + } + } + CheckerInfo *info = m->gen->info; + + for (Entity *e : info->init_procedures) { + lbValue value = lb_find_procedure_value_from_entity(m, e); + lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none); + } + + + lb_end_procedure_body(p); +} gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array &global_variables) { // Startup Runtime @@ -1904,107 +2167,21 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type); p->is_startup = true; + if (build_context.no_plt) { + lb_add_attribute_to_proc(p->module, p->value, "nonlazybind"); + } lb_add_attribute_to_proc(p->module, p->value, "optnone"); lb_add_attribute_to_proc(p->module, p->value, "noinline"); - lb_begin_procedure_body(p); + // Make sure shared libraries call their own runtime startup on Linux. + LLVMSetVisibility(p->value, LLVMHiddenVisibility); + LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value); - lb_setup_type_info_data(main_module); + p->global_variables = &global_variables; + p->objc_names = objc_names; - if (objc_names) { - LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, ""); - } + lb_create_startup_runtime_generate_body(main_module, p); - for (auto &var : global_variables) { - if (var.is_initialized) { - continue; - } - - lbModule *entity_module = main_module; - - Entity *e = var.decl->entity; - GB_ASSERT(e->kind == Entity_Variable); - e->code_gen_module = entity_module; - - Ast *init_expr = var.decl->init_expr; - if (init_expr != nullptr) { - lbValue init = lb_build_expr(p, init_expr); - if (init.value == nullptr) { - LLVMTypeRef global_type = llvm_addr_type(p->module, var.var); - if (is_type_untyped_nil(init.type)) { - LLVMSetInitializer(var.var.value, LLVMConstNull(global_type)); - var.is_initialized = true; - - if (e->Variable.is_rodata) { - LLVMSetGlobalConstant(var.var.value, true); - } - continue; - } - GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr)); - } - - if (is_type_any(e->type) || is_type_union(e->type)) { - var.init = init; - } else if (lb_is_const_or_global(init)) { - if (!var.is_initialized) { - if (is_type_proc(init.type)) { - init.value = LLVMConstPointerCast(init.value, lb_type(p->module, init.type)); - } - LLVMSetInitializer(var.var.value, init.value); - var.is_initialized = true; - - if (e->Variable.is_rodata) { - LLVMSetGlobalConstant(var.var.value, true); - } - continue; - } - } else { - var.init = init; - } - } - - if (var.init.value != nullptr) { - GB_ASSERT(!var.is_initialized); - Type *t = type_deref(var.var.type); - - if (is_type_any(t)) { - // NOTE(bill): Edge case for 'any' type - Type *var_type = default_type(var.init.type); - gbString var_name = gb_string_make(permanent_allocator(), "__$global_any::"); - gbString e_str = string_canonical_entity_name(temporary_allocator(), e); - var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str)); - lbAddr g = lb_add_global_generated_with_name(main_module, var_type, var.init, make_string_c(var_name)); - lb_addr_store(p, g, var.init); - lbValue gp = lb_addr_get_ptr(p, g); - - lbValue data = lb_emit_struct_ep(p, var.var, 0); - lbValue ti = lb_emit_struct_ep(p, var.var, 1); - lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr)); - lb_emit_store(p, ti, lb_type_info(p, var_type)); - } else { - LLVMTypeRef vt = llvm_addr_type(p->module, var.var); - lbValue src0 = lb_emit_conv(p, var.init, t); - LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt); - LLVMValueRef dst = var.var.value; - LLVMBuildStore(p->builder, src, dst); - } - - var.is_initialized = true; - } - - - } - CheckerInfo *info = main_module->gen->info; - - for (Entity *e : info->init_procedures) { - lbValue value = lb_find_procedure_value_from_entity(main_module, e); - lb_emit_call(p, value, {}, ProcInlining_none); - } - - - lb_end_procedure_body(p); - - lb_verify_function(main_module, p); return p; } @@ -2013,16 +2190,23 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_CLEANUP_RUNTIME_PROC_NAME), proc_type); p->is_startup = true; + if (build_context.no_plt) { + lb_add_attribute_to_proc(p->module, p->value, "nonlazybind"); + } lb_add_attribute_to_proc(p->module, p->value, "optnone"); lb_add_attribute_to_proc(p->module, p->value, "noinline"); + // Make sure shared libraries call their own runtime cleanup on Linux. + LLVMSetVisibility(p->value, LLVMHiddenVisibility); + LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value); + lb_begin_procedure_body(p); CheckerInfo *info = main_module->gen->info; for (Entity *e : info->fini_procedures) { lbValue value = lb_find_procedure_value_from_entity(main_module, e); - lb_emit_call(p, value, {}, ProcInlining_none); + lb_emit_call(p, value, {}, ProcInlining_none, ProcTailing_none); } lb_end_procedure_body(p); @@ -2041,7 +2225,7 @@ gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) { for (Entity *e : m->global_procedures_to_create) { (void)lb_get_entity_name(m, e); - array_add(&m->procedures_to_generate, lb_create_procedure(m, e)); + mpsc_enqueue(&m->procedures_to_generate, lb_create_procedure(m, e)); } return 0; } @@ -2065,8 +2249,6 @@ gb_internal GB_COMPARE_PROC(llvm_global_entity_cmp) { } gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, CheckerInfo *info, bool do_threading) { - auto *min_dep_set = &info->minimum_dependency_set; - for (Entity *e : info->entities) { String name = e->token.string; Scope * scope = e->scope; @@ -2090,7 +2272,7 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker break; case Entity_Constant: if (build_context.ODIN_DEBUG) { - add_debug_info_for_global_constant_from_entity(gen, e); + lb_add_debug_info_for_global_constant_from_entity(gen, e); } break; } @@ -2103,18 +2285,28 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker } } - if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + if (!polymorphic_struct && e->min_dep_count.load(std::memory_order_relaxed) == 0) { // NOTE(bill): Nothing depends upon it so doesn't need to be built continue; } + // if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + // // NOTE(bill): Nothing depends upon it so doesn't need to be built + // continue; + // } + lbModule *m = &gen->default_module; if (USE_SEPARATE_MODULES) { - m = lb_module_of_entity(gen, e); + m = lb_module_of_entity(gen, e, m); } GB_ASSERT(m != nullptr); if (e->kind == Entity_Procedure) { + if (e->Procedure.is_foreign && e->Procedure.is_objc_impl_or_import) { + // Do not generate declarations for foreign Objective-C methods. These are called indirectly through the Objective-C runtime. + continue; + } + array_add(&m->global_procedures_to_create, e); } else if (e->kind == Entity_TypeName) { array_add(&m->global_types_to_create, e); @@ -2184,7 +2376,12 @@ gb_internal WORKER_TASK_PROC(lb_llvm_emit_worker_proc) { auto wd = cast(lbLLVMEmitWorker *)data; - if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) { + if (build_context.lto_kind != LTO_None) { + if (LLVMWriteBitcodeToFile(wd->m->mod, cast(char *)wd->filepath_obj.text)) { + gb_printf_err("Failed to write bitcode file: %.*s\n", LIT(wd->filepath_obj)); + exit_with_errors(); + } + } else if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); exit_with_errors(); } @@ -2226,7 +2423,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { lb_llvm_function_pass_per_function_internal(m, m->gen->objc_names); } - for (lbProcedure *p : m->procedures_to_generate) { + MUTEX_GUARD_BLOCK(&m->generated_procedures_mutex) for (lbProcedure *p : m->generated_procedures) { if (p->body != nullptr) { // Build Procedure lbFunctionPassManagerKind pass_manager_kind = lbFunctionPassManager_default; if (p->flags & lbProcedureFlag_WithoutMemcpyPass) { @@ -2265,17 +2462,23 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) { } +void lb_remove_unused_functions_and_globals(lbGenerator *gen) { + for (auto &entry : gen->modules) { + lbModule *m = entry.value; + lb_run_remove_unused_function_pass(m); + lb_run_remove_unused_globals_pass(m); + } +} + struct lbLLVMModulePassWorkerData { lbModule *m; LLVMTargetMachineRef target_machine; + bool do_threading; }; gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { auto wd = cast(lbLLVMModulePassWorkerData *)data; - lb_run_remove_unused_function_pass(wd->m); - lb_run_remove_unused_globals_pass(wd->m); - LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager(); lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level); LLVMRunPassManager(module_pass_manager, wd->m->mod); @@ -2295,14 +2498,21 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { // tsan - Linux, Darwin // ubsan - Linux, Darwin, Windows (NOT SUPPORTED WITH LLVM C-API) - if (build_context.sanitizer_flags & SanitizerFlag_Address) { - array_add(&passes, "asan"); - } - if (build_context.sanitizer_flags & SanitizerFlag_Memory) { - array_add(&passes, "msan"); - } - if (build_context.sanitizer_flags & SanitizerFlag_Thread) { - array_add(&passes, "tsan"); + // With LTO, sanitizer passes run at link time (via -fsanitize= linker flags) + // where the linker has whole-program visibility. Running them here too would + // double-instrument every module, producing "Redundant instrumentation" warnings. + // Per-function sanitize attributes in the bitcode are preserved and respected + // by the linker's sanitizer pass. + if (build_context.lto_kind == LTO_None) { + if (build_context.sanitizer_flags & SanitizerFlag_Address) { + array_add(&passes, "asan"); + } + if (build_context.sanitizer_flags & SanitizerFlag_Memory) { + array_add(&passes, "msan"); + } + if (build_context.sanitizer_flags & SanitizerFlag_Thread) { + array_add(&passes, "tsan"); + } } if (passes.count == 0) { @@ -2351,6 +2561,17 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { return 1; } #endif + + if (LLVM_IGNORE_VERIFICATION) { + return 0; + } + + if (wd->do_threading) { + thread_pool_add_task(lb_llvm_module_verification_worker_proc, wd->m); + } else { + lb_llvm_module_verification_worker_proc(wd->m); + } + return 0; } @@ -2358,8 +2579,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { gb_internal WORKER_TASK_PROC(lb_generate_procedures_worker_proc) { lbModule *m = cast(lbModule *)data; - for (isize i = 0; i < m->procedures_to_generate.count; i++) { - lbProcedure *p = m->procedures_to_generate[i]; + for (lbProcedure *p = nullptr; mpsc_dequeue(&m->procedures_to_generate, &p); /**/) { lb_generate_procedure(p->module, p); } return 0; @@ -2383,15 +2603,22 @@ gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) { gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) { lbModule *m = cast(lbModule *)data; - for (isize i = 0; i < m->missing_procedures_to_check.count; i++) { - lbProcedure *p = m->missing_procedures_to_check[i]; - debugf("Generate missing procedure: %.*s module %p\n", LIT(p->name), m); - lb_generate_procedure(m, p); + for (lbProcedure *p = nullptr; mpsc_dequeue(&m->missing_procedures_to_check, &p); /**/) { + if (!p->is_done.load(std::memory_order_relaxed)) { + debugf("Generate missing procedure: %.*s module %p\n", LIT(p->name), m); + lb_generate_procedure(m, p); + } + + for (lbProcedure *nested = nullptr; mpsc_dequeue(&m->procedures_to_generate, &nested); /**/) { + mpsc_enqueue(&m->missing_procedures_to_check, nested); + } } return 0; } gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_threading) { + isize retry_count = 0; +retry:; if (do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; @@ -2406,6 +2633,20 @@ gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_thread lb_generate_missing_procedures_to_check_worker_proc(m); } } + + for (auto const &entry : gen->modules) { + lbModule *m = entry.value; + if (m->missing_procedures_to_check.count != 0) { + if (retry_count > gen->modules.count) { + GB_ASSERT(m->missing_procedures_to_check.count == 0); + } + + retry_count += 1; + goto retry; + } + GB_ASSERT(m->missing_procedures_to_check.count == 0); + GB_ASSERT(m->procedures_to_generate.count == 0); + } } gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) { @@ -2433,27 +2674,25 @@ gb_internal void lb_llvm_function_passes(lbGenerator *gen, bool do_threading) { } -gb_internal void lb_llvm_module_passes(lbGenerator *gen, bool do_threading) { +gb_internal void lb_llvm_module_passes_and_verification(lbGenerator *gen, bool do_threading) { if (do_threading) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData); + auto wd = permanent_alloc_item(); wd->m = m; wd->target_machine = m->target_machine; + wd->do_threading = true; - if (do_threading) { - thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd); - } else { - lb_llvm_module_pass_worker_proc(wd); - } + thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd); } thread_pool_wait(); } else { for (auto const &entry : gen->modules) { lbModule *m = entry.value; - auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData); + auto wd = permanent_alloc_item(); wd->m = m; wd->target_machine = m->target_machine; + wd->do_threading = false; lb_llvm_module_pass_worker_proc(wd); } } @@ -2496,7 +2735,6 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { gbString path = gb_string_make_length(heap_allocator(), basename.text, basename.len); path = gb_string_appendc(path, "/"); - path = gb_string_append_length(path, name.text, name.len); if (USE_SEPARATE_MODULES) { GB_ASSERT(m->module_name != nullptr); @@ -2508,6 +2746,8 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { } path = gb_string_append_length(path, s.text, s.len); + } else { + path = gb_string_append_length(path, name.text, name.len); } if (use_temporary_directory) { @@ -2517,70 +2757,24 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { String ext = {}; - if (build_context.build_mode == BuildMode_Assembly) { - ext = STR_LIT(".S"); + if (build_context.lto_kind != LTO_None) { + ext = STR_LIT("bc"); + } else if (build_context.build_mode == BuildMode_Assembly) { + ext = STR_LIT("S"); + } else if (build_context.build_mode == BuildMode_Object) { + // Allow a user override for the object extension. + ext = build_context.build_paths[BuildPath_Output].ext; } else { - if (is_arch_wasm()) { - ext = STR_LIT(".wasm.o"); - } else { - switch (build_context.metrics.os) { - case TargetOs_windows: - ext = STR_LIT(".obj"); - break; - default: - case TargetOs_darwin: - case TargetOs_linux: - case TargetOs_essence: - ext = STR_LIT(".o"); - break; - - case TargetOs_freestanding: - switch (build_context.metrics.abi) { - default: - case TargetABI_Default: - case TargetABI_SysV: - ext = STR_LIT(".o"); - break; - case TargetABI_Win64: - ext = STR_LIT(".obj"); - break; - } - break; - } - } + ext = infer_object_extension_from_build_context(); } + path = gb_string_append_length(path, ".", 1); path = gb_string_append_length(path, ext.text, ext.len); return make_string(cast(u8 *)path, gb_string_length(path)); } - -gb_internal bool lb_llvm_module_verification(lbGenerator *gen, bool do_threading) { - if (LLVM_IGNORE_VERIFICATION) { - return true; - } - - if (do_threading) { - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - thread_pool_add_task(lb_llvm_module_verification_worker_proc, m); - } - thread_pool_wait(); - - } else { - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - if (lb_llvm_module_verification_worker_proc(m)) { - return false; - } - } - } - - return true; -} - gb_internal void lb_add_foreign_library_paths(lbGenerator *gen) { for (auto const &entry : gen->modules) { lbModule *m = entry.value; @@ -2615,7 +2809,7 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading) array_add(&gen->output_object_paths, filepath_obj); array_add(&gen->output_temp_paths, filepath_ll); - auto *wd = gb_alloc_item(permanent_allocator(), lbLLVMEmitWorker); + auto *wd = permanent_alloc_item(); wd->target_machine = m->target_machine; wd->code_gen_file_type = code_gen_file_type; wd->filepath_obj = filepath_obj; @@ -2640,7 +2834,13 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading) TIME_SECTION_WITH_LEN(section_name, gb_string_length(section_name)); - if (LLVMTargetMachineEmitToFile(m->target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) { + if (build_context.lto_kind != LTO_None) { + if (LLVMWriteBitcodeToFile(m->mod, cast(char *)filepath_obj.text)) { + gb_printf_err("Failed to write bitcode file: %.*s\n", LIT(filepath_obj)); + exit_with_errors(); + return false; + } + } else if (LLVMTargetMachineEmitToFile(m->target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); exit_with_errors(); return false; @@ -2676,8 +2876,15 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("fdwReason"), t_u32, false, true); params->Tuple.variables[2] = alloc_entity_param(nullptr, make_token_ident("lpReserved"), t_rawptr, false, true); call_cleanup = false; - } else if (build_context.metrics.os == TargetOs_windows && (build_context.metrics.arch == TargetArch_i386 || build_context.no_crt)) { + } else if (build_context.metrics.os == TargetOs_windows && build_context.no_crt) { name = str_lit("mainCRTStartup"); + } else if (build_context.metrics.os == TargetOs_windows && build_context.metrics.arch == TargetArch_i386 && !build_context.no_crt) { + // Windows i386 with CRT: libcmt expects _main (main with underscore prefix) + name = str_lit("main"); + has_args = true; + slice_init(¶ms->Tuple.variables, permanent_allocator(), 2); + params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true); + params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true); } else if (is_arch_wasm()) { name = str_lit("_start"); call_cleanup = false; @@ -2712,7 +2919,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star } lbValue startup_runtime_value = {startup_runtime->value, startup_runtime->type}; - lb_emit_call(p, startup_runtime_value, {}, ProcInlining_none); + lb_emit_call(p, startup_runtime_value, {}, ProcInlining_none, ProcTailing_none); if (build_context.command_kind == Command_test) { Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test")); @@ -2765,19 +2972,30 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star args[0] = lb_addr_load(p, all_tests_slice); lbValue result = lb_emit_call(p, runner, args); - lbValue exit_runner = lb_find_package_value(m, str_lit("os"), str_lit("exit")); + lbValue exit_runner = {}; + { + AstPackage *pkg = get_runtime_package(m->info); + + String name = str_lit("exit"); + Entity *e = scope_lookup_current(pkg->scope, string_interner_insert(name)); + if (e == nullptr) { + compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg->name), LIT(name)); + } + exit_runner = lb_find_value_from_entity(m, e); + } + auto exit_args = array_make(temporary_allocator(), 1); exit_args[0] = lb_emit_select(p, result, lb_const_int(m, t_int, 0), lb_const_int(m, t_int, 1)); - lb_emit_call(p, exit_runner, exit_args, ProcInlining_none); + lb_emit_call(p, exit_runner, exit_args, ProcInlining_none, ProcTailing_none); } else { if (m->info->entry_point != nullptr) { lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); - lb_emit_call(p, entry_point, {}, ProcInlining_no_inline); + lb_emit_call(p, entry_point, {}, ProcInlining_no_inline, ProcTailing_none); } if (call_cleanup) { lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type}; - lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none); + lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none, ProcTailing_none); } if (is_dll_main) { @@ -2803,16 +3021,19 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star } gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p) { - if (p->is_done) { + if (p->is_done.load(std::memory_order_relaxed)) { return; } + if (p->body != nullptr) { // Build Procedure m->curr_procedure = p; lb_begin_procedure_body(p); lb_build_stmt(p, p->body); lb_end_procedure_body(p); - p->is_done = true; + p->is_done.store(true, std::memory_order_relaxed); m->curr_procedure = nullptr; + } else if (p->generate_body != nullptr) { + p->generate_body(m, p); } // Add Flags @@ -2821,6 +3042,9 @@ gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p) { } lb_verify_function(m, p, true); + + MUTEX_GUARD(&m->generated_procedures_mutex); + array_add(&m->generated_procedures, p); } @@ -2835,8 +3059,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lbModule *default_module = &gen->default_module; CheckerInfo *info = gen->info; - auto *min_dep_set = &info->minimum_dependency_set; - switch (build_context.metrics.arch) { case TargetArch_amd64: case TargetArch_i386: @@ -2907,8 +3129,14 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMCodeModel code_mode = LLVMCodeModelDefault; if (is_arch_wasm()) { code_mode = LLVMCodeModelJITDefault; + debugf("LLVM code mode: LLVMCodeModelJITDefault\n"); } else if (is_arch_x86() && build_context.metrics.os == TargetOs_freestanding) { code_mode = LLVMCodeModelKernel; + debugf("LLVM code mode: LLVMCodeModelKernel\n"); + } + + if (code_mode == LLVMCodeModelDefault) { + debugf("LLVM code mode: LLVMCodeModelDefault\n"); } String llvm_cpu = get_final_microarchitecture(); @@ -2924,7 +3152,10 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } first = false; - llvm_features = gb_string_appendc(llvm_features, "+"); + if (*str.text != '+' && *str.text != '-') { + llvm_features = gb_string_appendc(llvm_features, "+"); + } + llvm_features = gb_string_append_length(llvm_features, str.text, str.len); } @@ -2948,46 +3179,18 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { // NOTE(bill, 2021-05-04): Target machines must be unique to each module because they are not thread safe auto target_machines = array_make(permanent_allocator(), 0, gen->modules.count); - // NOTE(dweiler): Dynamic libraries require position-independent code. - LLVMRelocMode reloc_mode = LLVMRelocDefault; - if (build_context.build_mode == BuildMode_DynamicLibrary) { - reloc_mode = LLVMRelocPIC; - } - - switch (build_context.reloc_mode) { - case RelocMode_Default: - if (build_context.metrics.os == TargetOs_openbsd || build_context.metrics.os == TargetOs_haiku) { - // Always use PIC for OpenBSD and Haiku: they default to PIE - reloc_mode = LLVMRelocPIC; - } - - if (build_context.metrics.arch == TargetArch_riscv64) { - // NOTE(laytan): didn't seem to work without this. - reloc_mode = LLVMRelocPIC; - } - - break; - case RelocMode_Static: - reloc_mode = LLVMRelocStatic; - break; - case RelocMode_PIC: - reloc_mode = LLVMRelocPIC; - break; - case RelocMode_DynamicNoPIC: - reloc_mode = LLVMRelocDynamicNoPic; - break; - } - for (auto const &entry : gen->modules) { LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine( target, target_triple, (const char *)llvm_cpu.text, llvm_features, code_gen_level, - reloc_mode, + get_reloc_mode(), code_mode); lbModule *m = entry.value; m->target_machine = target_machine; - LLVMSetModuleDataLayout(m->mod, LLVMCreateTargetDataLayout(target_machine)); + LLVMTargetDataRef data_layout = LLVMCreateTargetDataLayout(target_machine); + LLVMSetModuleDataLayout(m->mod, data_layout); + LLVMDisposeTargetData(data_layout); #if LLVM_VERSION_MAJOR >= 18 if (build_context.fast_isel) { @@ -3122,6 +3325,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g, LLVMInternalLinkage); lb_make_global_private_const(g); + lb_set_odin_rtti_section(g); return lb_addr({g, alloc_type_pointer(t)}); }; @@ -3151,6 +3355,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { String link_name = e->Procedure.link_name; if (e->pkg->kind == Package_Runtime) { if (link_name == "main" || + link_name == "_main" || link_name == "DllMain" || link_name == "WinMain" || link_name == "wWinMain" || @@ -3173,7 +3378,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { continue; } - if (!ptr_set_exists(min_dep_set, e)) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } @@ -3183,62 +3388,32 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } GB_ASSERT(e->kind == Entity_Variable); + bool is_foreign = e->Variable.is_foreign; bool is_export = e->Variable.is_export; + lbModule *default_module = &gen->default_module; + + lbModule *m = default_module; + lbModule *e_module = lb_module_of_entity(gen, e, default_module); + + bool const split_globals_across_modules = false; + if (split_globals_across_modules) { + m = e_module; + } - lbModule *m = &gen->default_module; String name = lb_get_entity_name(m, e); - lbValue g = {}; - g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name)); - g.type = alloc_type_pointer(e->type); - if (e->Variable.thread_local_model != "") { - LLVMSetThreadLocal(g.value, true); - - String m = e->Variable.thread_local_model; - LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; - if (m == "default") { - mode = LLVMGeneralDynamicTLSModel; - } else if (m == "localdynamic") { - mode = LLVMLocalDynamicTLSModel; - } else if (m == "initialexec") { - mode = LLVMInitialExecTLSModel; - } else if (m == "localexec") { - mode = LLVMLocalExecTLSModel; - } else { - GB_PANIC("Unhandled thread local mode %.*s", LIT(m)); - } - LLVMSetThreadLocalMode(g.value, mode); - } - if (is_foreign) { - LLVMSetLinkage(g.value, LLVMExternalLinkage); - LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass); - LLVMSetExternallyInitialized(g.value, true); - lb_add_foreign_library_path(m, e->Variable.foreign_library); - } else { - LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type))); - } - if (is_export) { - LLVMSetLinkage(g.value, LLVMDLLExportLinkage); - LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass); - } else if (!is_foreign) { - LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage); - } - lb_set_linkage_from_entity_flags(m, g.value, e->flags); - LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type)); - - if (e->Variable.link_section.len > 0) { - LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section)); - } - lbGlobalVariable var = {}; - var.var = g; var.decl = decl; + lbValue g = {}; + g.type = alloc_type_pointer(e->type); + g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name)); + if (decl->init_expr != nullptr) { TypeAndValue tav = type_and_value_of_expr(decl->init_expr); - if (!is_type_any(e->type) && !is_type_union(e->type)) { + if (!is_type_any(e->type)) { if (tav.mode != Addressing_Invalid) { if (tav.value.kind != ExactValue_Invalid) { auto cc = LB_CONST_CONTEXT_DEFAULT; @@ -3247,7 +3422,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { cc.link_section = e->Variable.link_section; ExactValue v = tav.value; - lbValue init = lb_const_value(m, tav.type, v, cc); + lbValue init = lb_const_value(m, e->type, v, tav.type, cc); + + + LLVMDeleteGlobal(g.value); + g.value = nullptr; + g.value = LLVMAddGlobal(m->mod, LLVMTypeOf(init.value), alloc_cstring(permanent_allocator(), name)); + LLVMSetInitializer(g.value, init.value); var.is_initialized = true; if (cc.is_rodata) { @@ -3266,16 +3447,33 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMSetGlobalConstant(g.value, true); } + + lb_apply_thread_local_model(g.value, e->Variable.thread_local_model); + + if (is_foreign) { + LLVMSetLinkage(g.value, LLVMExternalLinkage); + LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass); + LLVMSetExternallyInitialized(g.value, true); + lb_add_foreign_library_path(m, e->Variable.foreign_library); + } else if (LLVMGetInitializer(g.value) == nullptr) { + LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type))); + } + if (is_export) { + LLVMSetLinkage(g.value, LLVMDLLExportLinkage); + LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass); + } else if (!is_foreign) { + LLVM_SET_INTERNAL_WEAK_LINKAGE(g.value); + } + lb_set_linkage_from_entity_flags(m, g.value, e->flags); + LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type)); + + if (e->Variable.link_section.len > 0) { + LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section)); + } if (e->flags & EntityFlag_Require) { lb_append_to_compiler_used(m, g.value); } - array_add(&global_variables, var); - - lb_add_entity(m, e, g); - lb_add_member(m, name, g); - - if (m->debug_builder) { String global_name = e->token.string; if (global_name.len != 0 && global_name != "_") { @@ -3304,6 +3502,49 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMGlobalSetMetadata(g.value, 0, global_variable_metadata); } } + + if (default_module == m) { + g.value = LLVMConstPointerCast(g.value, lb_type(m, alloc_type_pointer(e->type))); + + var.var = g; + array_add(&global_variables, var); + } else { + lbValue local_g = {}; + local_g.type = alloc_type_pointer(e->type); + local_g.value = LLVMAddGlobal(default_module->mod, lb_type(default_module, e->type), alloc_cstring(permanent_allocator(), name)); + LLVMSetLinkage(local_g.value, LLVMExternalLinkage); + + var.var = local_g; + array_add(&global_variables, var); + + lb_add_entity(default_module, e, local_g); + lb_add_member(default_module, name, local_g); + } + + lb_add_entity(m, e, g); + lb_add_member(m, name, g); + } + + if (build_context.ODIN_DEBUG) { + // Custom `.raddbg` section for its debugger + if (build_context.metrics.os == TargetOs_windows) { + lbModule *m = default_module; + LLVMModuleRef mod = m->mod; + LLVMContextRef ctx = m->ctx; + + { + LLVMTypeRef type = LLVMArrayType(LLVMInt8TypeInContext(ctx), 1); + LLVMValueRef global = LLVMAddGlobal(mod, type, "raddbg_is_attached_byte_marker"); + LLVMSetInitializer(global, LLVMConstNull(type)); + LLVMSetSection(global, ".raddbg"); + } + + if (gen->info->entry_point) { + String mangled_name = lb_get_entity_name(m, gen->info->entry_point); + char const *str = alloc_cstring(temporary_allocator(), mangled_name); + lb_add_raddbg_string(m, "entry_point: \"", str, "\""); + } + } } TIME_SECTION("LLVM Runtime Objective-C Names Creation"); @@ -3319,7 +3560,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (build_context.ODIN_DEBUG) { for (auto const &entry : builtin_pkg->scope->elements) { Entity *e = entry.value; - add_debug_info_for_global_constant_from_entity(gen, e); + lb_add_debug_info_for_global_constant_from_entity(gen, e); } } @@ -3349,6 +3590,96 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (build_context.ODIN_DEBUG) { TIME_SECTION("LLVM Debug Info Complete Types and Finalize"); lb_debug_info_complete_types_and_finalize(gen); + + // Custom `.raddbg` section for its debugger + if (build_context.metrics.os == TargetOs_windows) { + lbModule *m = default_module; + LLVMModuleRef mod = m->mod; + LLVMContextRef ctx = m->ctx; + + lb_add_raddbg_string(m, "type_view: {type: \"[]?\", expr: \"array(data, len)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"string\", expr: \"array(data, len)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"[dynamic]?\", expr: \"rows($, array(data, len), len, cap, allocator)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"[dynamic;?]?\", expr: \"rows($, array(data, len), len)\"}"); + + // column major matrices + lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"columns($.data, $[0])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[2, ?]?\", expr: \"columns($.data, $[0], $[1])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[3, ?]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[4, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[5, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[6, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[7, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[8, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[9, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[10, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[11, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[12, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[13, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[14, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[15, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[16, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); + + // row major matrices + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 1]?\", expr: \"columns($.data, $[0])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 2]?\", expr: \"columns($.data, $[0], $[1])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 3]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 4]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 5]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 6]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 7]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 8]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 9]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 10]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 11]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 12]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 13]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 14]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 15]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 16]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); + + + TEMPORARY_ALLOCATOR_GUARD(); + for (RaddbgTypeView const &type_view : gen->info->raddbg_type_views) { + if (type_view.type == nullptr) { + continue; + } + + if (type_view.view.len == 0) { + continue; + } + + String t_str = type_to_canonical_string(temporary_allocator(), type_view.type); + + gbString s = gb_string_make(temporary_allocator(), ""); + + s = gb_string_appendc(s, "type_view: {type: \""); + s = gb_string_append_length(s, t_str.text, t_str.len); + s = gb_string_appendc(s, "\", expr: \""); + s = gb_string_append_length(s, type_view.view.text, type_view.view.len); + s = gb_string_appendc(s, "\"}"); + + lb_add_raddbg_string(m, s); + } + + TEMPORARY_ALLOCATOR_GUARD(); + u32 global_name_index = 0; + for (String str = {}; mpsc_dequeue(&gen->raddebug_section_strings, &str); /**/) { + LLVMValueRef data = LLVMConstStringInContext(ctx, cast(char const *)str.text, cast(unsigned)str.len, false); + LLVMTypeRef type = LLVMTypeOf(data); + + gbString global_name = gb_string_make(temporary_allocator(), "raddbg_data__"); + global_name = gb_string_append_fmt(global_name, "%u", global_name_index); + global_name_index += 1; + + LLVMValueRef global = LLVMAddGlobal(mod, type, global_name); + + LLVMSetInitializer(global, data); + LLVMSetAlignment(global, 1); + + LLVMSetSection(global, ".raddbg"); + } + } } if (do_threading) { @@ -3364,15 +3695,23 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } + TIME_SECTION("LLVM Add Foreign Library Paths"); + lb_add_foreign_library_paths(gen); + TIME_SECTION("LLVM Function Pass"); lb_llvm_function_passes(gen, do_threading && !build_context.ODIN_DEBUG); - TIME_SECTION("LLVM Module Pass"); - lb_llvm_module_passes(gen, do_threading); + TIME_SECTION("LLVM Remove Unused Functions and Globals"); + lb_remove_unused_functions_and_globals(gen); - TIME_SECTION("LLVM Module Verification"); - if (!lb_llvm_module_verification(gen, do_threading)) { - return false; + TIME_SECTION("LLVM Module Pass and Verification"); + lb_llvm_module_passes_and_verification(gen, do_threading); + + TIME_SECTION("LLVM Correct Entity Linkage"); + lb_correct_entity_linkage(gen); + + if (build_context.build_diagnostics) { + lb_do_build_diagnostics(gen); } llvm_error = nullptr; @@ -3401,11 +3740,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { } } - TIME_SECTION("LLVM Add Foreign Library Paths"); - lb_add_foreign_library_paths(gen); - - TIME_SECTION("LLVM Correct Entity Linkage"); - lb_correct_entity_linkage(gen); //////////////////////////////////////////// for (auto const &entry: gen->modules) { @@ -3431,36 +3765,48 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (build_context.sanitizer_flags & SanitizerFlag_Address) { - if (build_context.metrics.os == TargetOs_windows) { + switch (build_context.metrics.os) { + case TargetOs_windows: { auto paths = array_make(heap_allocator(), 0, 1); String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib")); array_add(&paths, path); Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib")); array_add(&gen->foreign_libraries, lib); - } else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + } break; + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=address"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Memory) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=memory"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Thread) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=thread"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread")); } + break; } } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 408e35f3c..fb8d0f89a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -23,22 +23,8 @@ #include #endif -#if LLVM_VERSION_MAJOR < 11 -#error "LLVM Version 11 is the minimum required" -#elif LLVM_VERSION_MAJOR == 12 && !(LLVM_VERSION_MINOR > 0 || LLVM_VERSION_PATCH > 0) -#error "If LLVM Version 12.x.y is wanted, at least LLVM 12.0.1 is required" -#endif - -#if LLVM_VERSION_MAJOR > 12 || (LLVM_VERSION_MAJOR == 12 && LLVM_VERSION_MINOR >= 0 && LLVM_VERSION_PATCH > 0) -#define ODIN_LLVM_MINIMUM_VERSION_12 1 -#else -#define ODIN_LLVM_MINIMUM_VERSION_12 0 -#endif - -#if LLVM_VERSION_MAJOR > 13 || (LLVM_VERSION_MAJOR == 13 && LLVM_VERSION_MINOR >= 0 && LLVM_VERSION_PATCH > 0) -#define ODIN_LLVM_MINIMUM_VERSION_13 1 -#else -#define ODIN_LLVM_MINIMUM_VERSION_13 0 +#if LLVM_VERSION_MAJOR < 14 +#error "LLVM Version 14 is the minimum required" #endif #if LLVM_VERSION_MAJOR > 14 || (LLVM_VERSION_MAJOR == 14 && LLVM_VERSION_MINOR >= 0 && LLVM_VERSION_PATCH > 0) @@ -147,9 +133,13 @@ struct lbModule { LLVMModuleRef mod; LLVMContextRef ctx; + Checker *checker; + struct lbGenerator *gen; LLVMTargetMachineRef target_machine; + lbModule *polymorphic_module; + CheckerInfo *info; AstPackage *pkg; // possibly associated AstFile *file; // possibly associated @@ -171,18 +161,23 @@ struct lbModule { StringMap members; StringMap procedures; PtrMap procedure_values; - Array missing_procedures_to_check; - StringMap const_strings; + MPSCQueue missing_procedures_to_check; + + StringMap const_strings; + String16Map const_string16s; PtrMap function_type_map; StringMap gen_procs; // key is the canonicalized name - Array procedures_to_generate; + MPSCQueue procedures_to_generate; Array global_procedures_to_create; Array global_types_to_create; + BlockingMutex generated_procedures_mutex; + Array generated_procedures; + lbProcedure *curr_procedure; LLVMBuilderRef const_dummy_builder; @@ -197,6 +192,7 @@ struct lbModule { StringMap objc_classes; StringMap objc_selectors; StringMap objc_ivars; + isize objc_next_block_id; // Used to name objective-c blocks. Tracked per module. PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info @@ -230,8 +226,7 @@ struct lbGenerator : LinkerData { PtrMap modules_through_ctx; lbModule default_module; - RecursiveMutex anonymous_proc_lits_mutex; - PtrMap anonymous_proc_lits; + lbModule *equal_module; isize used_module_count; @@ -243,6 +238,7 @@ struct lbGenerator : LinkerData { MPSCQueue objc_selectors; MPSCQueue objc_classes; MPSCQueue objc_ivars; + MPSCQueue raddebug_section_strings; }; @@ -294,6 +290,7 @@ struct lbDefer { isize scope_index; isize context_stack_count; lbBlock * block; + TokenPos pos; union { Ast *stmt; struct { @@ -326,6 +323,14 @@ struct lbVariadicReuseSlices { lbAddr slice_addr; }; +struct lbGlobalVariable { + lbValue var; + lbValue init; + DeclInfo *decl; + bool is_initialized; +}; + + struct lbProcedure { u32 flags; u16 state_flags; @@ -341,6 +346,7 @@ struct lbProcedure { Ast * body; u64 tags; ProcInlining inlining; + ProcTailing tailing; bool is_foreign; bool is_export; bool is_entry_point; @@ -348,11 +354,12 @@ struct lbProcedure { lbFunctionType *abi_function_type; - LLVMValueRef value; - LLVMBuilderRef builder; - bool is_done; + LLVMValueRef value; + LLVMBuilderRef builder; + std::atomic is_done; lbAddr return_ptr; + Entity * sret_rvo_entity; // Local aliases of `return_ptr` Array defer_stmts; Array blocks; Array branch_blocks; @@ -388,6 +395,12 @@ struct lbProcedure { PtrMap tuple_fix_map; Array asan_stack_locals; + + void (*generate_body)(lbModule *m, lbProcedure *p); + Array *global_variables; + lbProcedure *objc_names; + + Type *internal_gen_type; // map_set, map_get, etc. }; @@ -407,10 +420,12 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c); gb_internal String lb_mangle_name(Entity *e); gb_internal String lb_get_entity_name(lbModule *m, Entity *e); +gb_internal LLVMAttributeRef lb_create_string_attribute(LLVMContextRef ctx, String const &key, String const &value); gb_internal LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value=0); gb_internal LLVMAttributeRef lb_create_enum_attribute_with_type(LLVMContextRef ctx, char const *name, LLVMTypeRef type); gb_internal void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name, u64 value); gb_internal void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *name); +gb_internal void lb_add_nocapture_proc_attribute_at_index(lbProcedure *p, isize index); gb_internal lbProcedure *lb_create_procedure(lbModule *module, Entity *entity, bool ignore_body=false); @@ -431,7 +446,7 @@ static lbConstContext const LB_CONST_CONTEXT_DEFAULT_NO_LOCAL = {false, false, { gb_internal lbValue lb_const_nil(lbModule *m, Type *type); gb_internal lbValue lb_const_undef(lbModule *m, Type *type); -gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc = LB_CONST_CONTEXT_DEFAULT); +gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Type *value_type=nullptr, lbConstContext cc = LB_CONST_CONTEXT_DEFAULT); gb_internal lbValue lb_const_bool(lbModule *m, Type *type, bool value); gb_internal lbValue lb_const_int(lbModule *m, Type *type, u64 value); @@ -472,7 +487,7 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node); gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t); gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right); -gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, ProcInlining inlining = ProcInlining_none); +gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, ProcInlining inlining = ProcInlining_none, ProcTailing tailing = ProcTailing_none, lbValue *sret_dst = nullptr); gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t); gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x); @@ -480,8 +495,10 @@ gb_internal void lb_emit_jump(lbProcedure *p, lbBlock *target_block); gb_internal void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, lbBlock *false_block); gb_internal void lb_start_block(lbProcedure *p, lbBlock *b); -gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr); - +gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr, lbValue *sret_dst = nullptr); +gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type); +gb_internal void lb_begin_procedure_body(lbProcedure *p); +gb_internal void lb_end_procedure_body(lbProcedure *p); gb_internal lbAddr lb_find_or_generate_context_ptr(lbProcedure *p); gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx); @@ -516,6 +533,7 @@ gb_internal lbValue lb_dynamic_array_elem(lbProcedure *p, lbValue da); gb_internal lbValue lb_dynamic_array_len(lbProcedure *p, lbValue da); gb_internal lbValue lb_dynamic_array_cap(lbProcedure *p, lbValue da); gb_internal lbValue lb_dynamic_array_allocator(lbProcedure *p, lbValue da); +gb_internal lbValue lb_fixed_capacity_dynamic_array_len(lbProcedure *p, lbValue da); gb_internal lbValue lb_map_len(lbProcedure *p, lbValue value); gb_internal lbValue lb_map_cap(lbProcedure *p, lbValue value); gb_internal lbValue lb_soa_struct_len(lbProcedure *p, lbValue value); @@ -577,7 +595,7 @@ gb_internal lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, As gb_internal lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block); gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_); -gb_internal LLVMValueRef llvm_const_named_struct_internal(LLVMTypeRef t, LLVMValueRef *values, isize value_count_); +gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeRef t, LLVMValueRef *values, isize value_count_); gb_internal void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name); gb_internal lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type *t); @@ -603,7 +621,12 @@ gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef p gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile); gb_internal gb_inline i64 lb_max_zero_init_size(void) { - return cast(i64)(4*build_context.int_size); + if (build_context.metrics.os == TargetOs_darwin && build_context.metrics.arch == TargetArch_arm64) { + // https://github.com/odin-lang/Odin/issues/6347 + return cast(i64)(4*build_context.int_size); + } else { + return cast(i64)(8); + } } gb_internal LLVMTypeRef OdinLLVMGetArrayElementType(LLVMTypeRef type); @@ -625,6 +648,11 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen #endif } +gb_internal lbValue lb_emit_struct_iv(lbProcedure *p, lbValue agg, lbValue field, i32 index); +gb_internal lbValue lb_build_struct_value(lbProcedure *p, Type *type, lbValue *fields, isize count); +gb_internal lbValue lb_make_slice_value(lbProcedure *p, Type *slice_type, lbValue elem, lbValue len); +gb_internal lbValue lb_make_string_value(lbProcedure *p, Type *string_type, lbValue elem, lbValue len); + gb_internal String lb_internal_gen_name_from_type(char const *prefix, Type *type); @@ -655,6 +683,7 @@ enum lbCallingConventionKind : unsigned { lbCallingConvention_PreserveAll = 15, lbCallingConvention_Swift = 16, lbCallingConvention_CXX_FAST_TLS = 17, + lbCallingConvention_PreserveNone = 21, lbCallingConvention_FirstTargetCC = 64, lbCallingConvention_X86_StdCall = 64, lbCallingConvention_X86_FastCall = 65, @@ -708,6 +737,10 @@ lbCallingConventionKind const lb_calling_convention_map[ProcCC_MAX] = { lbCallingConvention_Win64, // ProcCC_Win64, lbCallingConvention_X86_64_SysV, // ProcCC_SysV, + lbCallingConvention_PreserveNone, // ProcCC_PreserveNone, + lbCallingConvention_PreserveMost, // ProcCC_PreserveMost, + lbCallingConvention_PreserveAll, // ProcCC_PreserveAll, + }; enum : LLVMDWARFTypeEncoding { diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index dada2cff5..0a77ddc3d 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1,3 +1,12 @@ +gb_internal LLVMValueRef lb_const_low_bits_mask(LLVMTypeRef type, u64 bit_count) { + GB_ASSERT(bit_count <= 64); + if (bit_count == 0) { + return LLVMConstInt(type, 0, false); + } + u64 mask = bit_count == 64 ? ~0ull : (1ull< %s", LLVMPrintValueToString(val), LLVMPrintTypeToString(dst)); - // NOTE(bill): It's not possible to do a bit cast on a struct, why was this code even here in the first place? - // It seems mostly to exist to get around the "anonymous -> named" struct assignments - // return LLVMConstBitCast(val, dst); - return val; - default: - GB_PANIC("Unhandled const cast %s to %s", LLVMPrintTypeToString(src), LLVMPrintTypeToString(dst)); + } + case LLVMStructTypeKind: { + GB_ASSERT_MSG(lb_sizeof(dst) == lb_sizeof(src), "dst:%s vs src:%s (dst:%lld vs src:%lld)", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src), + cast(long long)lb_sizeof(dst), + cast(long long)lb_sizeof(src)); + + unsigned src_n = LLVMCountStructElementTypes(src); + unsigned dst_n = LLVMCountStructElementTypes(dst); + if (src_n != dst_n) goto failure; + + if (LLVM_VERSION_MAJOR > 14) { + return val; + } + + LLVMValueRef *field_vals = temporary_alloc_array(dst_n); + for (unsigned i = 0; i < dst_n; i++) { + LLVMValueRef field_val = llvm_const_extract_value(m, val, i); + if (field_val == nullptr) goto failure; + + LLVMTypeRef dst_elem_ty = LLVMStructGetTypeAtIndex(dst, i); + LLVMTypeRef src_elem_ty = LLVMTypeOf(field_val); + + GB_ASSERT_MSG(lb_sizeof(dst_elem_ty) == lb_sizeof(src_elem_ty), "dst:%s vs src:%s (dst:%lld vs src:%lld) to %s from %s", LLVMPrintTypeToString(dst_elem_ty), LLVMPrintTypeToString(src_elem_ty), + cast(long long)lb_sizeof(dst_elem_ty), + cast(long long)lb_sizeof(src_elem_ty), + LLVMPrintTypeToString(dst), + LLVMPrintTypeToString(src) + ); + + field_vals[i] = llvm_const_cast(m, field_val, dst_elem_ty, failure_); + if (failure_ && *failure_) goto failure; + } + + if (!LLVMIsLiteralStruct(dst)) { + return LLVMConstNamedStruct(dst, field_vals, dst_n); + } else { + return LLVMConstStructInContext(m->ctx, field_vals, dst_n, LLVMIsPackedStruct(dst)); + } + } + case LLVMArrayTypeKind: { + goto failure; + } } +failure: + if (failure_) *failure_ = true; return val; } @@ -122,19 +170,38 @@ gb_internal lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) { gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) { + GB_ASSERT(!is_type_string16(t)); if (build_context.metrics.ptr_size < build_context.metrics.int_size) { LLVMValueRef values[3] = { data, LLVMConstNull(lb_type(m, t_i32)), len, }; - return llvm_const_named_struct_internal(lb_type(m, t), values, 3); + return llvm_const_named_struct_internal(m, lb_type(m, t), values, 3); } else { LLVMValueRef values[2] = { data, len, }; - return llvm_const_named_struct_internal(lb_type(m, t), values, 2); + return llvm_const_named_struct_internal(m, lb_type(m, t), values, 2); + } +} + +gb_internal LLVMValueRef llvm_const_string16_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) { + GB_ASSERT(is_type_string16(t)); + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + LLVMValueRef values[3] = { + data, + LLVMConstNull(lb_type(m, t_i32)), + len, + }; + return llvm_const_named_struct_internal(m, lb_type(m, t), values, 3); + } else { + LLVMValueRef values[2] = { + data, + len, + }; + return llvm_const_named_struct_internal(m, lb_type(m, t), values, 2); } } @@ -146,12 +213,11 @@ gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValue unsigned value_count = cast(unsigned)value_count_; unsigned elem_count = LLVMCountStructElementTypes(struct_type); if (elem_count == value_count) { - return llvm_const_named_struct_internal(struct_type, values, value_count_); + return llvm_const_named_struct_internal(m, struct_type, values, value_count_); } Type *bt = base_type(t); - GB_ASSERT(bt->kind == Type_Struct); - - GB_ASSERT(value_count_ == bt->Struct.fields.count); + GB_ASSERT(bt->kind == Type_Struct || bt->kind == Type_Union); + GB_ASSERT(bt->kind != Type_Struct || value_count_ == bt->Struct.fields.count); auto field_remapping = lb_get_struct_remapping(m, t); unsigned values_with_padding_count = elem_count; @@ -166,25 +232,40 @@ gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValue } } - return llvm_const_named_struct_internal(struct_type, values_with_padding, values_with_padding_count); + return llvm_const_named_struct_internal(m, struct_type, values_with_padding, values_with_padding_count); } -gb_internal LLVMValueRef llvm_const_named_struct_internal(LLVMTypeRef t, LLVMValueRef *values, isize value_count_) { +gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeRef t, LLVMValueRef *values, isize value_count_) { unsigned value_count = cast(unsigned)value_count_; unsigned elem_count = LLVMCountStructElementTypes(t); GB_ASSERT_MSG(value_count == elem_count, "%s %u %u", LLVMPrintTypeToString(t), value_count, elem_count); + bool failure = false; for (unsigned i = 0; i < elem_count; i++) { LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, i); - values[i] = llvm_const_cast(values[i], elem_type); + values[i] = llvm_const_cast(m, values[i], elem_type, &failure); + } + + if (failure) { + return LLVMConstStructInContext(m->ctx, values, value_count, true); } return LLVMConstNamedStruct(t, values, value_count); } -gb_internal LLVMValueRef llvm_const_array(LLVMTypeRef elem_type, LLVMValueRef *values, isize value_count_) { +gb_internal LLVMValueRef llvm_const_array(lbModule *m, LLVMTypeRef elem_type, LLVMValueRef *values, isize value_count_) { unsigned value_count = cast(unsigned)value_count_; + bool failure = false; for (unsigned i = 0; i < value_count; i++) { - values[i] = llvm_const_cast(values[i], elem_type); + values[i] = llvm_const_cast(m, values[i], elem_type, &failure); } + if (failure) { + return LLVMConstStructInContext(m->ctx, values, value_count, false); + } + for (unsigned i = 0; i < value_count; i++) { + if (elem_type != LLVMTypeOf(values[i])) { + return LLVMConstStructInContext(m->ctx, values, value_count, false); + } + } + return LLVMConstArray(elem_type, values, value_count); } @@ -238,6 +319,10 @@ gb_internal lbValue lb_const_string(lbModule *m, String const &value) { return lb_const_value(m, t_string, exact_value_string(value)); } +gb_internal lbValue lb_const_string(lbModule *m, String16 const &value) { + return lb_const_value(m, t_string16, exact_value_string16(value)); +} + gb_internal lbValue lb_const_bool(lbModule *m, Type *type, bool value) { lbValue res = {}; @@ -292,12 +377,26 @@ gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String cons i32 line = pos.line; i32 column = pos.column; - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: file = obfuscate_string(file, "F"); procedure = obfuscate_string(procedure, "P"); - line = obfuscate_i32(line); - column = obfuscate_i32(column); + line = obfuscate_i32(line); + column = obfuscate_i32(column); + break; + case SourceCodeLocationInfo_Filename: + file = last_path_element(file); + break; + case SourceCodeLocationInfo_None: + file = str_lit(""); + procedure = str_lit(""); + + line = 0; + column = 0; + break; } LLVMValueRef fields[4] = {}; @@ -424,13 +523,20 @@ gb_internal LLVMValueRef lb_build_constant_array_values(lbModule *m, Type *type, return lb_addr_load(p, v).value; } - return llvm_const_array(lb_type(m, elem_type), values, cast(unsigned int)count); + return llvm_const_array(m, lb_type(m, elem_type), values, cast(unsigned int)count); } gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, BigInt const *a) { if (big_int_is_zero(a)) { return LLVMConstNull(lb_type(m, original_type)); } + + BigInt val = {}; + big_int_init(&val, a); + + if (big_int_is_neg(&val)) { + mp_incr(&val); + } size_t sz = cast(size_t)type_size_of(original_type); u64 rop64[4] = {}; // 2 u64 is the maximum we will ever need, so doubling it will be fine :P @@ -442,10 +548,10 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi size_t nails = 0; mp_endian endian = MP_LITTLE_ENDIAN; - max_count = mp_pack_count(a, nails, size); + max_count = mp_pack_count(&val, nails, size); if (sz < max_count) { debug_print_big_int(a); - gb_printf_err("%s -> %tu\n", type_to_string(original_type), sz);; + gb_printf_err("%s -> %tu\n", type_to_string(original_type), sz); } GB_ASSERT_MSG(sz >= max_count, "max_count: %tu, sz: %tu, written: %tu, type %s", max_count, sz, written, type_to_string(original_type)); GB_ASSERT(gb_size_of(rop64) >= sz); @@ -453,7 +559,7 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi mp_err err = mp_pack(rop, sz, &written, MP_LSB_FIRST, size, endian, nails, - a); + &val); GB_ASSERT(err == MP_OKAY); if (!is_type_endian_little(original_type)) { @@ -464,12 +570,18 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi } } + if (big_int_is_neg(a)) { + // sizeof instead of sz for sign extend to work properly + for (size_t i = 0; i < sizeof rop64; i++) { + rop[i] = ~rop[i]; + } + } + + big_int_dealloc(&val); + GB_ASSERT(!is_type_array(original_type)); LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((sz+7)/8), cast(u64 *)rop); - if (big_int_is_neg(a)) { - value = LLVMConstNeg(value); - } return value; } @@ -494,13 +606,316 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel, } - if (is_type_raw_union(ft) || is_type_typeid(ft)) { + if (is_type_raw_union(ft)) { return false; } return lb_is_elem_const(elem, ft); } -gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc) { +#if LLVM_VERSION_MAJOR == 14 +LLVMValueRef llvm_const_pad_to_size(lbModule *m, LLVMValueRef val, LLVMTypeRef dst_ty) { + LLVMContextRef ctx = m->ctx; + LLVMTargetDataRef td = LLVMGetModuleDataLayout(m->mod); + LLVMTypeRef src_ty = LLVMTypeOf(val); + unsigned src_bits = (unsigned)LLVMSizeOfTypeInBits(td, src_ty); + unsigned dst_bits = (unsigned)LLVMSizeOfTypeInBits(td, dst_ty); + + LLVMValueRef as_int = nullptr; + LLVMTypeKind src_kind = LLVMGetTypeKind(src_ty); + + if (src_kind == LLVMIntegerTypeKind || + src_kind == LLVMFloatTypeKind || + src_kind == LLVMDoubleTypeKind || + src_kind == LLVMPointerTypeKind || + src_kind == LLVMVectorTypeKind) { + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstBitCast(val, src_int_ty); + + } else if (src_kind == LLVMArrayTypeKind) { + unsigned elem_count = LLVMGetArrayLength(src_ty); + LLVMTypeRef elem_ty = LLVMGetElementType(src_ty); + unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty); + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstInt(src_int_ty, 0, false); + + for (unsigned i = 0; i < elem_count; i++) { + LLVMValueRef elem = llvm_const_extract_value(m, val, i); + LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits); + LLVMValueRef elem_int = llvm_const_pad_to_size(m, elem, elem_int_ty); + LLVMValueRef shifted = LLVMConstShl(LLVMConstZExt(elem_int, src_int_ty), LLVMConstInt(src_int_ty, i * elem_bits, false)); + as_int = LLVMConstOr(as_int, shifted); + } + } else if (src_kind == LLVMStructTypeKind) { + unsigned field_count = LLVMCountStructElementTypes(src_ty); + LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits); + as_int = LLVMConstInt(src_int_ty, 0, false); + + for (unsigned i = 0; i < field_count; i++) { + LLVMTypeRef field_ty = LLVMStructGetTypeAtIndex(src_ty, i); + unsigned field_bits = (unsigned)LLVMSizeOfTypeInBits(td, field_ty); + LLVMValueRef field = llvm_const_extract_value(m, val, i); + + LLVMTypeRef field_int_ty = LLVMIntTypeInContext(ctx, field_bits); + LLVMValueRef field_int = llvm_const_pad_to_size(m, field, field_int_ty); + + uint64_t field_offset_bytes = LLVMOffsetOfElement(td, src_ty, i); + uint64_t field_offset_bits = field_offset_bytes * 8; + + LLVMValueRef shifted = LLVMConstShl(LLVMConstZExt(field_int, src_int_ty), LLVMConstInt(src_int_ty, field_offset_bits, false)); + as_int = LLVMConstOr(as_int, shifted); + } + } else { + gb_printf_err("unsupported const_pad source type: %s\n", LLVMPrintTypeToString(src_ty)); + return nullptr; + } + + if (src_bits != dst_bits) { + LLVMTypeRef dst_int_ty = LLVMIntTypeInContext(ctx, dst_bits); + if (src_bits < dst_bits) { + as_int = LLVMConstZExt(as_int, dst_int_ty); + } else { + as_int = LLVMConstTrunc(as_int, dst_int_ty); + } + } + + LLVMTypeKind dst_kind = LLVMGetTypeKind(dst_ty); + + if (dst_kind == LLVMIntegerTypeKind || + dst_kind == LLVMFloatTypeKind || + dst_kind == LLVMDoubleTypeKind || + dst_kind == LLVMPointerTypeKind || + dst_kind == LLVMVectorTypeKind) { + return LLVMConstBitCast(as_int, dst_ty); + + } else if (dst_kind == LLVMArrayTypeKind) { + unsigned elem_count = LLVMGetArrayLength(dst_ty); + LLVMTypeRef elem_ty = LLVMGetElementType(dst_ty); + unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty); + + LLVMValueRef *elems = temporary_alloc_array(elem_count); + LLVMTypeRef as_int_ty = LLVMTypeOf(as_int); + + for (unsigned i = 0; i < elem_count; i++) { + LLVMValueRef shifted = LLVMConstLShr(as_int, LLVMConstInt(as_int_ty, i * elem_bits, false)); + LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits); + LLVMValueRef trunc = LLVMConstTrunc(shifted, elem_int_ty); + elems[i] = llvm_const_pad_to_size(m, trunc, elem_ty); + } + + return LLVMConstArray(elem_ty, elems, elem_count); + } + + gb_printf_err("unsupported const_pad destination type: %s\n", LLVMPrintTypeToString(dst_ty)); + return nullptr; +} +#endif + +gb_internal void lb_const_array_spread(lbModule *m, lbConstContext cc, Type *array, ExactValue value, lbValue *res, Type *value_type) { + GB_ASSERT(array->kind == Type_Array); + + i64 count = array->Array.count; + Type *elem = array->Array.elem; + + lbValue single_elem = lb_const_value(m, elem, value, value_type, cc); + + LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)count); + for (i64 i = 0; i < count; i++) { + elems[i] = single_elem.value; + } + + res->value = llvm_const_array(m, lb_type(m, elem), elems, cast(unsigned)count); +} + +gb_internal LLVMValueRef lb_fill_fixed_capacity_dynamic_array(lbModule *m, i64 elem_count, Type *original_type, LLVMValueRef *values, lbConstContext cc) { + Type *bt = base_type(original_type); + GB_ASSERT(bt->kind == Type_FixedCapacityDynamicArray); + Type *elem_type = bt->FixedCapacityDynamicArray.elem; + i64 capacity = bt->FixedCapacityDynamicArray.capacity; + + Type *array_backing_type = alloc_type_array(elem_type, capacity); + LLVMValueRef array_backing = lb_build_constant_array_values(m, array_backing_type, elem_type, cast(isize)capacity, values, cc); + LLVMValueRef array_len = lb_const_int(m, t_int, elem_count).value; + + isize svalue_count = 0; + LLVMValueRef svalues[3] = {}; + svalues[svalue_count++] = array_backing; + i64 padding = bt->FixedCapacityDynamicArray.padding_needed; + if (padding > 0) { + svalues[svalue_count++] = LLVMConstNull(lb_type_padding_filler(m, padding, 1)); + } + svalues[svalue_count++] = array_len; + + return llvm_const_named_struct(m, original_type, svalues, svalue_count); +} + +gb_internal lbValue lb_const_value_bit_field(lbModule *m, Type *type, Ast *value_compound) { + ast_node(cl, CompoundLit, value_compound); + + TEMPORARY_ALLOCATOR_GUARD(); + + Type *bt = base_type(type); + + // Type *backing_type = core_type(bt->BitField.backing_type); + + struct FieldData { + Type *field_type; + u64 bit_offset; + u64 bit_size; + }; + auto values = array_make(temporary_allocator(), 0, cl->elems.count); + auto fields = array_make(temporary_allocator(), 0, cl->elems.count); + + for (Ast *elem : cl->elems) { + ast_node(fv, FieldValue, elem); + InternedString interned = fv->field->Ident.interned; + Selection sel = lookup_field(bt, interned, false); + GB_ASSERT(sel.is_bit_field); + GB_ASSERT(!sel.indirect); + GB_ASSERT(sel.index.count == 1); + GB_ASSERT(sel.entity != nullptr); + + i64 index = sel.index[0]; + Entity *f = bt->BitField.fields[index]; + GB_ASSERT(f == sel.entity); + i64 bit_offset = bt->BitField.bit_offsets[index]; + i64 bit_size = bt->BitField.bit_sizes[index]; + GB_ASSERT(bit_size > 0); + + Type *field_type = sel.entity->type; + if (fv->value->tav.mode != Addressing_Constant) { + continue; + } + lbValue field_expr = lb_const_value(m, field_type, fv->value->tav.value, field_type); + array_add(&values, field_expr); + array_add(&fields, FieldData{field_type, cast(u64)bit_offset, cast(u64)bit_size}); + } + + // NOTE(bill): inline insertion sort should be good enough, right? + for (isize i = 1; i < values.count; i++) { + for (isize j = i; + j > 0 && fields[i].bit_offset < fields[j].bit_offset; + j--) { + auto vtmp = values[j]; + values[j] = values[j-1]; + values[j-1] = vtmp; + + auto ftmp = fields[j]; + fields[j] = fields[j-1]; + fields[j-1] = ftmp; + } + } + + bool any_fields_different_endian = false; + for (auto const &f : fields) { + if (is_type_different_to_arch_endianness(f.field_type)) { + // NOTE(bill): Just be slow for this, to be correct + any_fields_different_endian = true; + break; + } + } + GB_ASSERT(!any_fields_different_endian); + + + Type *backing_type = core_type(bt->BitField.backing_type); + GB_ASSERT(is_type_integer(backing_type) || + (is_type_array(backing_type) && is_type_integer(backing_type->Array.elem))); + + if (is_type_integer(backing_type)) { + // SINGLE INTEGER BACKING ONLY + + LLVMTypeRef lit = lb_type(m, backing_type); + + LLVMValueRef res = LLVMConstInt(lit, 0, false); + + for (isize i = 0; i < fields.count; i++) { + auto const &f = fields[i]; + + LLVMValueRef mask = lb_const_low_bits_mask(lit, f.bit_size); + + LLVMValueRef elem = values[i].value; + if (lb_sizeof(lit) < lb_sizeof(LLVMTypeOf(elem))) { + elem = LLVMBuildTrunc(m->const_dummy_builder, elem, lit, ""); + } else { + elem = LLVMBuildZExt(m->const_dummy_builder, elem, lit, ""); + } + elem = LLVMBuildAnd(m->const_dummy_builder, elem, mask, ""); + + elem = LLVMBuildShl(m->const_dummy_builder, elem, LLVMConstInt(lit, f.bit_offset, false), ""); + + res = LLVMBuildOr(m->const_dummy_builder, res, elem, ""); + } + + return {res, type}; + } else if (is_type_array(backing_type)) { + // ARRAY OF INTEGER BACKING + + i64 array_count = backing_type->Array.count; + LLVMTypeRef lit = lb_type(m, core_type(backing_type->Array.elem)); + + LLVMValueRef *elems = gb_alloc_array(temporary_allocator(), LLVMValueRef, array_count); + for (i64 i = 0; i < array_count; i++) { + elems[i] = LLVMConstInt(lit, 0, false); + } + + u64 elem_bit_size = cast(u64)(8*type_size_of(backing_type->Array.elem)); + u64 curr_bit_offset = 0; + for (isize i = 0; i < fields.count; i++) { + auto const &f = fields[i]; + + LLVMValueRef val = values[i].value; + LLVMTypeRef vt = lb_type(m, values[i].type); + + curr_bit_offset = f.bit_offset; + + for (u64 bits_to_set = f.bit_size; + bits_to_set > 0; + /**/) { + i64 elem_idx = curr_bit_offset/elem_bit_size; + u64 elem_bit_offset = curr_bit_offset%elem_bit_size; + + u64 mask_width = gb_min(bits_to_set, elem_bit_size-elem_bit_offset); + GB_ASSERT(mask_width > 0); + bits_to_set -= mask_width; + + LLVMValueRef mask = lb_const_low_bits_mask(vt, mask_width); + + LLVMValueRef to_set = LLVMBuildAnd(m->const_dummy_builder, val, mask, ""); + + if (elem_bit_offset != 0) { + to_set = LLVMBuildShl(m->const_dummy_builder, to_set, LLVMConstInt(vt, elem_bit_offset, false), ""); + } + to_set = LLVMBuildTrunc(m->const_dummy_builder, to_set, lit, ""); + + if (LLVMIsNull(elems[elem_idx])) { + elems[elem_idx] = to_set; // don't even bother doing `0 | to_set` + } else { + elems[elem_idx] = LLVMBuildOr(m->const_dummy_builder, elems[elem_idx], to_set, ""); + } + + if (mask_width != 0) { + val = LLVMBuildLShr(m->const_dummy_builder, val, LLVMConstInt(vt, mask_width, false), ""); + } + curr_bit_offset += mask_width; + } + + GB_ASSERT_MSG(curr_bit_offset == f.bit_offset + f.bit_size, "%llu == %llu + %llu", + cast(unsigned long long)curr_bit_offset, + cast(unsigned long long)f.bit_offset, + cast(unsigned long long)f.bit_size + ); + } + + LLVMValueRef res = LLVMConstArray(lit, elems, cast(unsigned)array_count); + return {res, type}; + } else { + // SLOW STORAGE + GB_PANIC("TODO(bill): bit_field storage of an unknown kind"); + return {}; + } +} + + +gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, Type *value_type, lbConstContext cc) { if (cc.allow_local) { cc.is_rodata = false; } @@ -512,28 +927,176 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb lbValue res = {}; res.type = original_type; - type = core_type(type); - value = convert_exact_value_for_type(value, type); - - if (value.kind == ExactValue_Typeid) { - return lb_typeid(m, value.value_typeid); + if (!is_type_bit_field(original_type)) { + type = core_type(type); + value = convert_exact_value_for_type(value, type); } - if (value.kind == ExactValue_Invalid) { - return lb_const_nil(m, original_type); + bool is_local = cc.allow_local && m->curr_procedure != nullptr; + + + if (is_type_union(type) && is_type_union_constantable(type)) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Union); + if (bt->Union.variants.count == 0) { + return lb_const_nil(m, original_type); + } else if (bt->Union.variants.count == 1) { + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + if (cl->type == nullptr) { + return lb_const_nil(m, original_type); + } + if (are_types_identical(type_of_expr(cl->type), original_type)) { + return lb_const_nil(m, original_type); + } + } + } + + if (value_type == t_untyped_nil) { + return lb_const_nil(m, original_type); + } + + Type *t = bt->Union.variants[0]; + lbValue cv = lb_const_value(m, t, value, value_type, cc); + GB_ASSERT(LLVMIsConstant(cv.value)); + + LLVMTypeRef llvm_type = lb_type(m, original_type); + + if (is_type_union_maybe_pointer(type)) { + LLVMValueRef values[1] = {cv.value}; + res.value = llvm_const_named_struct_internal(m, llvm_type, values, 1); + res.type = original_type; + return res; + } else { + LLVMValueRef values[4] = {}; + isize value_count = 0; + + // Payload + values[value_count++] = cv.value; + + unsigned tag_value = 1; + if (bt->Union.kind == UnionType_no_nil) { + tag_value = 0; + } + + // Tag + values[value_count++] = LLVMConstInt(LLVMStructGetTypeAtIndex(llvm_type, 1), tag_value, false);; + + if (LLVMCountStructElementTypes(llvm_type) > 2) { + GB_ASSERT(LLVMCountStructElementTypes(llvm_type) == 3); + // Padding + values[value_count++] = LLVMConstNull(LLVMStructGetTypeAtIndex(llvm_type, 2)); + } + + res.value = llvm_const_named_struct_internal(m, llvm_type, values, value_count); + res.type = original_type; + return res; + } + } else { + if (value_type == nullptr) { + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(m, original_type); + } + value_type = type_of_expr(value.value_compound); + } else if (value.kind == ExactValue_Invalid) { + return lb_const_nil(m, original_type); + } + } else if (value_type == t_untyped_nil) { + return lb_const_nil(m, original_type); + } + + GB_ASSERT_MSG(value_type != nullptr, "%s :: %s", type_to_string(original_type), exact_value_to_string(value)); + + i64 block_size = bt->Union.variant_block_size; + + while (are_types_identical(value_type, original_type)) { + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(m, original_type); + } + + value_type = type_of_expr(value.value_compound); + if (!are_types_identical(value_type, original_type)) { + break; + } + + GB_PANIC("%s --> %s vs %s", + expr_to_string(value.value_compound), + temp_canonical_string(value_type), temp_canonical_string(original_type)); + + } else if (value.kind == ExactValue_Invalid) { + return lb_const_nil(m, original_type); + } + + GB_PANIC("(value.kind=%s) %s vs %s", + exact_value_kind_string[value.kind], + temp_canonical_string(value_type), temp_canonical_string(original_type)); + } + // union_multiple_allow_compound:; + + lbValue cv = lb_const_value(m, value_type, value, value_type, cc); + Type *variant_type = cv.type; + + LLVMValueRef values[4] = {}; + unsigned value_count = 0; + + #if LLVM_VERSION_MAJOR == 14 + LLVMTypeRef block_type = lb_type_internal_union_block_type(m, bt); + values[value_count++] = llvm_const_pad_to_size(m, cv.value, block_type); + #else + values[value_count++] = cv.value; + if (block_size != type_size_of(variant_type)) { + LLVMTypeRef padding_type = lb_type_padding_filler(m, block_size - type_size_of(variant_type), 1); + values[value_count++] = LLVMConstNull(padding_type); + } + #endif + + Type *tag_type = union_tag_type(bt); + LLVMTypeRef llvm_tag_type = lb_type(m, tag_type); + i64 tag_index = union_variant_index_checked(bt, variant_type); + GB_ASSERT(tag_index >= 0); + values[value_count++] = LLVMConstInt(llvm_tag_type, tag_index, false); + i64 used_size = block_size + type_size_of(tag_type); + i64 union_size = type_size_of(bt); + i64 padding = union_size - used_size; + if (padding > 0) { + LLVMTypeRef padding_type = lb_type_padding_filler(m, padding, 1); + values[value_count++] = LLVMConstNull(padding_type); + } + + res.value = LLVMConstStructInContext(m->ctx, values, value_count, true); + gb_printf_err("%s\n", LLVMPrintValueToString(res.value)); + + return res; + } } if (value.kind == ExactValue_Procedure) { lbValue res = {}; - Ast *expr = unparen_expr(value.value_procedure); - GB_ASSERT(expr != nullptr); - if (expr->kind == Ast_ProcLit) { - res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr); - } else { + for (;;) { + Ast *expr = unparen_expr(value.value_procedure); + GB_ASSERT(expr != nullptr); + if (expr->kind == Ast_ProcLit) { + res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr); + break; + } Entity *e = entity_from_expr(expr); - res = lb_find_procedure_value_from_entity(m, e); + GB_ASSERT(e != nullptr); + if (e->kind != Entity_Constant) { + res = lb_find_procedure_value_from_entity(m, e); + break; + } + value = e->Constant.value; + GB_ASSERT(value.kind == ExactValue_Procedure); + } + if (res.value == nullptr) { + // This is an unspecialized polymorphic procedure, return nil or dummy value + return lb_const_nil(m, original_type); } - GB_ASSERT(res.value != nullptr); GB_ASSERT(LLVMGetValueKind(res.value) == LLVMFunctionValueKind); if (LLVMGetIntrinsicID(res.value) == 0) { @@ -543,7 +1106,23 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return res; } - bool is_local = cc.allow_local && m->curr_procedure != nullptr; + // NOTE(bill): This has to be done AFTER the union stuff + if (value.kind == ExactValue_Invalid) { + return lb_const_nil(m, original_type); + } + + + if (value.kind == ExactValue_Typeid) { + return lb_typeid(m, value.value_typeid); + } + + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(m, original_type); + } + } + // GB_ASSERT_MSG(is_type_typed(type), "%s", type_to_string(type)); @@ -552,6 +1131,10 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb GB_ASSERT(is_type_slice(type)); res.value = lb_find_or_add_entity_string_byte_slice_with_type(m, value.value_string, original_type).value; return res; + } else if (value.kind == ExactValue_String16) { + GB_ASSERT(is_type_slice(type)); + res.value = lb_find_or_add_entity_string16_slice_with_type(m, value.value_string16, original_type).value; + return res; } else { ast_node(cl, CompoundLit, value.value_compound); @@ -562,19 +1145,39 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb count = gb_max(cast(isize)cl->max_count, count); Type *elem = base_type(type)->Slice.elem; Type *t = alloc_type_array(elem, count); - lbValue backing_array = lb_const_value(m, t, value, cc); + lbValue backing_array = lb_const_value(m, t, value, nullptr, cc); LLVMValueRef array_data = nullptr; + if (is_local) { // NOTE(bill, 2020-06-08): This is a bit of a hack but a "constant" slice needs // its backing data on the stack lbProcedure *p = m->curr_procedure; LLVMTypeRef llvm_type = lb_type(m, t); - array_data = llvm_alloca(p, llvm_type, 16); + unsigned alignment = cast(unsigned)gb_max(type_align_of(t), 16); + + + bool do_local_copy = false; + if (do_local_copy) { + array_data = llvm_alloca(p, llvm_type, alignment); + + LLVMValueRef local_copy = llvm_alloca(p, LLVMTypeOf(backing_array.value), alignment); + LLVMBuildStore(p->builder, backing_array.value, local_copy); + + LLVMBuildMemCpy(p->builder, + array_data, alignment, + local_copy, alignment, + LLVMConstInt(lb_type(m, t_int), type_size_of(t), false) + ); + } else { + array_data = llvm_alloca(p, LLVMTypeOf(backing_array.value), alignment); + LLVMBuildStore(p->builder, backing_array.value, array_data); + + array_data = LLVMBuildPointerCast(p->builder, array_data, LLVMPointerType(llvm_type, 0), ""); + } - LLVMBuildStore(p->builder, backing_array.value, array_data); { LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; @@ -596,7 +1199,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb String name = make_string(cast(u8 const *)str, gb_string_length(str)); Entity *e = alloc_entity_constant(nullptr, make_token_ident(name), t, value); - array_data = LLVMAddGlobal(m->mod, lb_type(m, t), str); + array_data = LLVMAddGlobal(m->mod, LLVMTypeOf(backing_array.value), str); LLVMSetInitializer(array_data, backing_array.value); if (cc.link_section.len > 0) { @@ -607,15 +1210,14 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } lbValue g = {}; - g.value = array_data; + g.value = LLVMConstPointerCast(array_data, LLVMPointerType(lb_type(m, t), 0)); g.type = t; lb_add_entity(m, e, g); lb_add_member(m, name, g); { - LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; - LLVMValueRef ptr = LLVMConstInBoundsGEP2(lb_type(m, t), array_data, indices, 2); + LLVMValueRef ptr = g.value; LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true); LLVMValueRef values[2] = {ptr, len}; @@ -626,34 +1228,50 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } - } else if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) { - if (is_type_rune_array(type)) { - i64 count = type->Array.count; - Type *elem = type->Array.elem; - LLVMTypeRef et = lb_type(m, elem); + } else if (is_type_rune_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) { + i64 count = type->Array.count; + Type *elem = type->Array.elem; + LLVMTypeRef et = lb_type(m, elem); - Rune rune; - isize offset = 0; - isize width = 1; - String s = value.value_string; + Rune rune; + isize offset = 0; + isize width = 1; + String s = value.value_string; - LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)count); + LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)count); - for (i64 i = 0; i < count && offset < s.len; i++) { - width = utf8_decode(s.text+offset, s.len-offset, &rune); - offset += width; + for (i64 i = 0; i < count && offset < s.len; i++) { + width = utf8_decode(s.text+offset, s.len-offset, &rune); + offset += width; - elems[i] = LLVMConstInt(et, rune, true); + elems[i] = LLVMConstInt(et, rune, true); - } - GB_ASSERT(offset == s.len); - - res.value = llvm_const_array(et, elems, cast(unsigned)count); - return res; } - // NOTE(bill, 2021-10-07): Allow for array programming value constants - Type *core_elem = core_array_type(type); - return lb_const_value(m, core_elem, value, cc); + GB_ASSERT(offset == s.len); + + res.value = llvm_const_array(m, et, elems, cast(unsigned)count); + return res; + } else if (is_type_u16_array(type) && (value.kind == ExactValue_String || value.kind == ExactValue_String16) && !is_type_u8(core_array_type(type))) { + i64 count = type->Array.count; + Type *elem = type->Array.elem; + LLVMTypeRef et = lb_type(m, elem); + + String16 s = {}; + if (value.kind == ExactValue_String16) { + s = value.value_string16; + } else { + s = string_to_string16(temporary_allocator(), value.value_string); + } + + LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)count); + + for (isize i = 0; i < s.len; i++) { + elems[i] = LLVMConstInt(et, s.text[i], false); + + } + + res.value = llvm_const_array(m, et, elems, cast(unsigned)count); + return res; } else if (is_type_u8_array(type) && value.kind == ExactValue_String) { GB_ASSERT(type->Array.count == value.value_string.len); LLVMValueRef data = LLVMConstStringInContext(ctx, @@ -664,21 +1282,9 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return res; } else if (is_type_array(type) && value.kind != ExactValue_Invalid && - value.kind != ExactValue_String && value.kind != ExactValue_Compound) { - - i64 count = type->Array.count; - Type *elem = type->Array.elem; - - - lbValue single_elem = lb_const_value(m, elem, value, cc); - - LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)count); - for (i64 i = 0; i < count; i++) { - elems[i] = single_elem.value; - } - - res.value = llvm_const_array(lb_type(m, elem), elems, cast(unsigned)count); + + lb_const_array_spread(m, cc, type, value, &res, value_type); return res; } else if (is_type_matrix(type) && value.kind != ExactValue_Invalid && @@ -689,8 +1295,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb Type *elem = type->Matrix.elem; - lbValue single_elem = lb_const_value(m, elem, value, cc); - single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem)); + lbValue single_elem = lb_const_value(m, elem, value, value_type, cc); + single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr); i64 total_elem_count = matrix_type_total_internal_elems(type); LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count); @@ -711,8 +1317,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 count = type->SimdVector.count; Type *elem = type->SimdVector.elem; - lbValue single_elem = lb_const_value(m, elem, value, cc); - single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem)); + lbValue single_elem = lb_const_value(m, elem, value, value_type, cc); + single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr); LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count); for (i64 i = 0; i < count; i++) { @@ -734,7 +1340,55 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb { bool custom_link_section = cc.link_section.len > 0; - LLVMValueRef ptr = lb_find_or_add_entity_string_ptr(m, value.value_string, custom_link_section); + LLVMValueRef ptr = nullptr; + lbValue res = {}; + res.type = default_type(original_type); + + isize len = value.value_string.len; + + if (is_type_string16(res.type) || is_type_cstring16(res.type)) { + TEMPORARY_ALLOCATOR_GUARD(); + String16 s16 = string_to_string16(temporary_allocator(), value.value_string); + len = s16.len; + ptr = lb_find_or_add_entity_string16_ptr(m, s16, custom_link_section); + } else { + ptr = lb_find_or_add_entity_string_ptr(m, value.value_string, custom_link_section); + } + + if (custom_link_section) { + LLVMSetSection(ptr, alloc_cstring(permanent_allocator(), cc.link_section)); + } + + if (is_type_cstring(res.type) || is_type_cstring16(res.type)) { + res.value = ptr; + } else { + if (len == 0) { + if (is_type_string16(res.type)) { + ptr = LLVMConstNull(lb_type(m, t_u16_ptr)); + } else { + ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + } + } + LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), len, true); + GB_ASSERT(is_type_string(original_type)); + + if (is_type_string16(res.type)) { + res.value = llvm_const_string16_internal(m, original_type, ptr, str_len); + } else { + res.value = llvm_const_string_internal(m, original_type, ptr, str_len); + } + } + + return res; + } + + case ExactValue_String16: + { + GB_ASSERT(is_type_string16(res.type) || is_type_cstring16(res.type)); + + bool custom_link_section = cc.link_section.len > 0; + + LLVMValueRef ptr = lb_find_or_add_entity_string16_ptr(m, value.value_string16, custom_link_section); lbValue res = {}; res.type = default_type(original_type); @@ -742,21 +1396,22 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb LLVMSetSection(ptr, alloc_cstring(permanent_allocator(), cc.link_section)); } - if (is_type_cstring(res.type)) { + if (is_type_cstring16(res.type)) { res.value = ptr; } else { - if (value.value_string.len == 0) { + if (value.value_string16.len == 0) { ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); } - LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string.len, true); + LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string16.len, true); GB_ASSERT(is_type_string(original_type)); - res.value = llvm_const_string_internal(m, original_type, ptr, str_len); + res.value = llvm_const_string16_internal(m, original_type, ptr, str_len); } return res; } + case ExactValue_Integer: if (is_type_pointer(type) || is_type_multi_pointer(type) || is_type_proc(type)) { LLVMTypeRef t = lb_type(m, original_type); @@ -846,8 +1501,152 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return res; case ExactValue_Compound: - if (is_type_slice(type)) { - return lb_const_value(m, type, value, cc); + if (is_type_bit_field(original_type)) { + return lb_const_value_bit_field(m, original_type, value.value_compound); + } else if (is_type_slice(type)) { + return lb_const_value(m, type, value, value_type, cc); + } else if (is_type_soa_struct(type)) { + GB_ASSERT(type->kind == Type_Struct); + GB_ASSERT(type->Struct.soa_kind == StructSoa_Fixed); + ast_node(cl, CompoundLit, value.value_compound); + Type *elem_type = type->Struct.soa_elem; + isize elem_count = cl->elems.count; + if (elem_count == 0 || !elem_type_can_be_constant(elem_type)) { + return lb_const_nil(m, original_type); + } + if (cl->elems[0]->kind == Ast_FieldValue) { + TEMPORARY_ALLOCATOR_GUARD(); + + // TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand + + isize elem_count = cast(isize)type->Struct.soa_count; + + LLVMValueRef *aos_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, elem_count); + + isize value_index = 0; + for (i64 i = 0; i < elem_count; i++) { + bool found = false; + + for (isize j = 0; j < elem_count; j++) { + Ast *elem = cl->elems[j]; + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op != Token_RangeHalf) { + hi += 1; + } + if (lo == i) { + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + for (i64 k = lo; k < hi; k++) { + aos_values[value_index++] = val; + } + + found = true; + i += (hi-lo-1); + break; + } + } else { + TypeAndValue index_tav = fv->field->tav; + GB_ASSERT(index_tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(index_tav.value); + if (index == i) { + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + aos_values[value_index++] = val; + found = true; + break; + } + } + } + + if (!found) { + aos_values[value_index++] = nullptr; + } + } + + + isize field_count = type->Struct.fields.count; + LLVMValueRef *soa_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, field_count); + + for (isize i = 0; i < field_count; i++) { + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, elem_count); + + Entity *f = type->Struct.fields[i]; + Type *array_type = f->type; + GB_ASSERT(array_type->kind == Type_Array); + Type *field_type = array_type->Array.elem; + + for (isize j = 0; j < elem_count; j++) { + LLVMValueRef v = aos_values[j]; + if (v != nullptr) { + values[j] = llvm_const_extract_value(m, v, cast(unsigned)i); + } else { + values[j] = LLVMConstNull(lb_type(m, field_type)); + } + } + + soa_values[i] = lb_build_constant_array_values(m, array_type, field_type, elem_count, values, cc); + } + + res.value = llvm_const_named_struct(m, type, soa_values, field_count); + return res; + } else { + GB_ASSERT_MSG(elem_count == type->Struct.soa_count, "%td != %td", elem_count, type->Struct.soa_count); + + TEMPORARY_ALLOCATOR_GUARD(); + + isize elem_count = cast(isize)type->Struct.soa_count; + + LLVMValueRef *aos_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, elem_count); + + for (isize i = 0; i < elem_count; i++) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + aos_values[i] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + } + for (isize i = elem_count; i < type->Struct.soa_count; i++) { + aos_values[i] = nullptr; + } + + isize field_count = type->Struct.fields.count; + LLVMValueRef *soa_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, field_count); + + for (isize i = 0; i < field_count; i++) { + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, elem_count); + + Entity *f = type->Struct.fields[i]; + Type *array_type = f->type; + GB_ASSERT(array_type->kind == Type_Array); + Type *field_type = array_type->Array.elem; + + for (isize j = 0; j < elem_count; j++) { + LLVMValueRef v = aos_values[j]; + if (v != nullptr) { + values[j] = llvm_const_extract_value(m, v, cast(unsigned)i); + } else { + values[j] = LLVMConstNull(lb_type(m, field_type)); + } + } + + soa_values[i] = lb_build_constant_array_values(m, array_type, field_type, elem_count, values, cc); + } + + res.value = llvm_const_named_struct(m, type, soa_values, field_count); + return res; + } } else if (is_type_array(type)) { ast_node(cl, CompoundLit, value.value_compound); Type *elem_type = type->Array.elem; @@ -855,7 +1654,17 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb if (elem_count == 0 || !elem_type_can_be_constant(elem_type)) { return lb_const_nil(m, original_type); } - if (cl->elems[0]->kind == Ast_FieldValue) { + if (are_types_identical(value.value_compound->tav.type, elem_type)) { + // Compound is of array item type; expand its value to all items in array. + LLVMValueRef* values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)type->Array.count); + + for (isize i = 0; i < type->Array.count; i++) { + values[i] = lb_const_value(m, elem_type, value, elem_type, cc).value; + } + + res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->Array.count, values, cc); + return res; + } else if (cl->elems[0]->kind == Ast_FieldValue) { // TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)type->Array.count); @@ -881,7 +1690,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } if (lo == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; for (i64 k = lo; k < hi; k++) { values[value_index++] = val; } @@ -896,7 +1705,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 index = exact_value_to_i64(index_tav.value); if (index == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; values[value_index++] = val; found = true; break; @@ -912,17 +1721,25 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->Array.count, values, cc); return res; } else { - GB_ASSERT_MSG(elem_count == type->Array.count, "%td != %td", elem_count, type->Array.count); + // Assume that compound value is an array literal + GB_ASSERT_MSG(elem_count <= type->Array.count, "%td <= %td", elem_count, type->Array.count); LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)type->Array.count); + isize elem_index = 0; for (isize i = 0; i < elem_count; i++) { TypeAndValue tav = cl->elems[i]->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - values[i] = lb_const_value(m, elem_type, tav.value, cc).value; + if (is_type_tuple(tav.type)) { + elem_index += tav.type->Tuple.variables.count; + } else { + values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + } } - for (isize i = elem_count; i < type->Array.count; i++) { - values[i] = LLVMConstNull(lb_type(m, elem_type)); + for (isize i = 0; i < type->Array.count; i++) { + if (values[i] == nullptr) { + values[i] = LLVMConstNull(lb_type(m, elem_type)); + } } res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->Array.count, values, cc); @@ -965,7 +1782,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } if (lo == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; for (i64 k = lo; k < hi; k++) { values[value_index++] = val; } @@ -980,7 +1797,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 index = exact_value_to_i64(index_tav.value); if (index == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; values[value_index++] = val; found = true; break; @@ -996,20 +1813,137 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->EnumeratedArray.count, values, cc); return res; } else { - GB_ASSERT_MSG(elem_count == type->EnumeratedArray.count, "%td != %td", elem_count, type->EnumeratedArray.count); + // Assume that compound value is an array literal + GB_ASSERT_MSG(elem_count <= type->EnumeratedArray.count, "%td <= %td", elem_count, type->EnumeratedArray.count); LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)type->EnumeratedArray.count); + isize elem_index = 0; for (isize i = 0; i < elem_count; i++) { TypeAndValue tav = cl->elems[i]->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - values[i] = lb_const_value(m, elem_type, tav.value, cc).value; + if (is_type_tuple(tav.type)) { + elem_index += tav.type->Tuple.variables.count; + } else { + values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + } } - for (isize i = elem_count; i < type->EnumeratedArray.count; i++) { - values[i] = LLVMConstNull(lb_type(m, elem_type)); + for (isize i = 0; i < type->EnumeratedArray.count; i++) { + if (values[i] == nullptr) { + values[i] = LLVMConstNull(lb_type(m, elem_type)); + } } - res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->EnumeratedArray.count, values, cc); + res.value = lb_build_constant_array_values(m, type, elem_type, cast(isize)type->Array.count, values, cc); + return res; + } + } else if (is_type_fixed_capacity_dynamic_array(type)) { + ast_node(cl, CompoundLit, value.value_compound); + Type *elem_type = type->FixedCapacityDynamicArray.elem; + i64 capacity = type->FixedCapacityDynamicArray.capacity; + isize elem_count = cl->elems.count; + if (elem_count == 0 || !elem_type_can_be_constant(elem_type)) { + return lb_const_nil(m, original_type); + } + if (cl->elems[0]->kind == Ast_FieldValue) { + // TODO(bill): This is O(N*M) and will be quite slow; it should probably be sorted before hand + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)capacity); + + i64 max_index = -1; + isize value_index = 0; + for (i64 i = 0; i < capacity; i++) { + bool found = false; + + for (isize j = 0; j < elem_count; j++) { + Ast *elem = cl->elems[j]; + ast_node(fv, FieldValue, elem); + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op != Token_RangeHalf) { + hi += 1; + } + max_index = gb_max(max_index, hi-1); + + if (lo == i) { + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + for (i64 k = lo; k < hi; k++) { + values[value_index++] = val; + } + + found = true; + i += (hi-lo-1); + break; + } + } else { + TypeAndValue index_tav = fv->field->tav; + GB_ASSERT(index_tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(index_tav.value); + + max_index = gb_max(max_index, index); + + if (index == i) { + TypeAndValue tav = fv->value->tav; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + values[value_index++] = val; + found = true; + break; + } + } + } + + if (!found) { + values[value_index++] = LLVMConstNull(lb_type(m, elem_type)); + } + } + + i64 count = max_index+1; + GB_ASSERT(0 < count); + GB_ASSERT(count <= capacity); + + res.value = lb_fill_fixed_capacity_dynamic_array(m, count, original_type, values, cc); + return res; + } else if (are_types_identical(value.value_compound->tav.type, elem_type)) { + // Compound is of array item type; expand its value to all items in array. + LLVMValueRef* values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)capacity); + + for (isize i = 0; i < capacity; i++) { + values[i] = lb_const_value(m, elem_type, value, elem_type, cc).value; + } + + res.value = lb_fill_fixed_capacity_dynamic_array(m, capacity, original_type, values, cc); + return res; + } else { + // Assume that compound value is an array literal + GB_ASSERT_MSG(elem_count <= capacity, "%td <= %td", elem_count, capacity); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)capacity); + + isize elem_index = 0; + for (isize i = 0; i < elem_count; i++) { + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + if (is_type_tuple(tav.type)) { + elem_index += tav.type->Tuple.variables.count; + } else { + values[elem_index++] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; + } + } + for (isize i = 0; i < capacity; i++) { + if (values[i] == nullptr) { + values[i] = LLVMConstNull(lb_type(m, elem_type)); + } + } + + res.value = lb_fill_fixed_capacity_dynamic_array(m, elem_index, original_type, values, cc); return res; } } else if (is_type_simd_vector(type)) { @@ -1048,7 +1982,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } if (lo == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; for (i64 k = lo; k < hi; k++) { values[value_index++] = val; } @@ -1063,7 +1997,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 index = exact_value_to_i64(index_tav.value); if (index == i) { TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; values[value_index++] = val; found = true; break; @@ -1082,7 +2016,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb for (isize i = 0; i < elem_count; i++) { TypeAndValue tav = cl->elems[i]->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - values[i] = lb_const_value(m, elem_type, tav.value, cc).value; + values[i] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; } LLVMTypeRef et = lb_type(m, elem_type); @@ -1090,7 +2024,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb values[i] = LLVMConstNull(et); } for (isize i = 0; i < total_elem_count; i++) { - values[i] = llvm_const_cast(values[i], et); + values[i] = llvm_const_cast(m, values[i], et, /*failure_*/nullptr); } res.value = LLVMConstVector(values, cast(unsigned)total_elem_count); @@ -1104,6 +2038,39 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } if (is_type_raw_union(type)) { + if (is_type_raw_union_constantable(type)) { + GB_ASSERT(cl->elems.count == 1); + GB_ASSERT(cl->elems[0]->kind == Ast_FieldValue); + ast_node(fv, FieldValue, cl->elems[0]); + Entity *f = entity_of_node(fv->field); + + TypeAndValue tav = fv->value->tav; + if (tav.value.kind != ExactValue_Invalid) { + lbValue value = lb_const_value(m, f->type, tav.value, f->type, cc); + + LLVMValueRef values[2]; + unsigned value_count = 0; + + values[value_count++] = value.value; + + i64 union_alignment = type_align_of(type); + i64 value_alignment = type_align_of(f->type); + i64 alignment = gb_max(gb_min(value_alignment, union_alignment), 1); + + i64 union_size = type_size_of(type); + i64 value_size = lb_sizeof(LLVMTypeOf(value.value)); + i64 padding = union_size-value_size; + if (padding > 0) { + LLVMTypeRef padding_type = lb_type_padding_filler(m, padding, alignment); + values[value_count++] = LLVMConstNull(padding_type); + } + + LLVMValueRef res = LLVMConstStructInContext(m->ctx, values, value_count, /*packed*/padding > 0); + + return {res, original_type}; + } + + } return lb_const_nil(m, original_type); } @@ -1120,24 +2087,28 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb for (isize i = 0; i < elem_count; i++) { ast_node(fv, FieldValue, cl->elems[i]); String name = fv->field->Ident.token.string; + InternedString interned = fv->field->Ident.interned; TypeAndValue tav = fv->value->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - Selection sel = lookup_field(type, name, false); + Selection sel = lookup_field(type, interned, false); GB_ASSERT(!sel.indirect); Entity *f = type->Struct.fields[sel.index[0]]; i32 index = field_remapping[f->Variable.field_index]; if (elem_type_can_be_constant(f->type)) { if (sel.index.count == 1) { - values[index] = lb_const_value(m, f->type, tav.value, cc).value; + lbValue value = lb_const_value(m, f->type, tav.value, tav.type, cc); + LLVMTypeRef value_type = LLVMTypeOf(value.value); + GB_ASSERT_MSG(lb_sizeof(value_type) == type_size_of(f->type), "%s vs %s", LLVMPrintTypeToString(value_type), type_to_string(f->type)); + values[index] = value.value; visited[index] = true; } else { if (!visited[index]) { auto new_cc = cc; new_cc.allow_local = false; - values[index] = lb_const_value(m, f->type, {}, new_cc).value; + values[index] = lb_const_value(m, f->type, {}, nullptr, new_cc).value; visited[index] = true; } @@ -1177,7 +2148,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } } if (is_constant) { - LLVMValueRef elem_value = lb_const_value(m, tav.type, tav.value, cc).value; + LLVMValueRef elem_value = lb_const_value(m, cv_type, tav.value, tav.type, cc).value; if (LLVMIsConstant(elem_value) && LLVMIsConstant(values[index])) { values[index] = llvm_const_insert_value(m, values[index], elem_value, idx_list, idx_list_len); } else if (is_local) { @@ -1221,17 +2192,32 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } } } else { + isize multiple_return_offset = 0; for_array(i, cl->elems) { - Entity *f = type->Struct.fields[i]; + Entity *f = type->Struct.fields[i+multiple_return_offset]; TypeAndValue tav = cl->elems[i]->tav; - ExactValue val = {}; - if (tav.mode != Addressing_Invalid) { - val = tav.value; + + // INFO: dead code: + + // ExactValue val = {}; + // if (tav.mode != Addressing_Invalid) { + // val = tav.value; + // } + + if (is_type_tuple(tav.type)){ + multiple_return_offset += tav.type->Tuple.variables.count-1; } i32 index = field_remapping[f->Variable.field_index]; + + if (elem_type_can_be_constant(f->type)) { - values[index] = lb_const_value(m, f->type, val, cc).value; + lbValue value = lb_const_value(m, f->type, tav.value, tav.type, cc); + LLVMTypeRef value_type = LLVMTypeOf(value.value); + isize lb_sizeof_value_type = lb_sizeof(value_type); + isize type_size_of_f_type = type_size_of(f->type); + GB_ASSERT_MSG(lb_sizeof_value_type ==type_size_of_f_type, "%s vs %s", LLVMPrintTypeToString(value_type), type_to_string(f->type)); + values[index] = value.value; visited[index] = true; } } @@ -1257,7 +2243,9 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb } if (is_constant) { - res.value = llvm_const_named_struct_internal(struct_type, values, cast(unsigned)value_count); + res.value = llvm_const_named_struct_internal(m, struct_type, values, cast(unsigned)value_count); + LLVMTypeRef res_type = LLVMTypeOf(res.value); + GB_ASSERT(lb_sizeof(res_type) == lb_sizeof(struct_type)); return res; } else { // TODO(bill): THIS IS HACK BUT IT WORKS FOR WHAT I NEED @@ -1271,7 +2259,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb new_values[i] = LLVMConstNull(LLVMTypeOf(old_value)); } } - LLVMValueRef constant_value = llvm_const_named_struct_internal(struct_type, new_values, cast(unsigned)value_count); + LLVMValueRef constant_value = llvm_const_named_struct_internal(m, struct_type, new_values, cast(unsigned)value_count); GB_ASSERT(is_local); lbProcedure *p = m->curr_procedure; @@ -1365,7 +2353,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; for (i64 k = lo; k < hi; k++) { i64 offset = matrix_row_major_index_to_offset(type, k); GB_ASSERT(values[offset] == nullptr); @@ -1377,7 +2365,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 index = exact_value_to_i64(index_tav.value); GB_ASSERT(index < max_count); TypeAndValue tav = fv->value->tav; - LLVMValueRef val = lb_const_value(m, elem_type, tav.value, cc).value; + LLVMValueRef val = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; i64 offset = matrix_row_major_index_to_offset(type, index); GB_ASSERT(values[offset] == nullptr); values[offset] = val; @@ -1401,7 +2389,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb GB_ASSERT(tav.mode != Addressing_Invalid); i64 offset = 0; offset = matrix_row_major_index_to_offset(type, i); - values[offset] = lb_const_value(m, elem_type, tav.value, cc).value; + values[offset] = lb_const_value(m, elem_type, tav.value, tav.type, cc).value; } for (isize i = 0; i < total_count; i++) { if (values[i] == nullptr) { @@ -1425,4 +2413,3 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return lb_const_nil(m, original_type); } - diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 53c007d8d..d3e63cbf7 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -18,6 +18,25 @@ gb_internal void lb_set_llvm_metadata(lbModule *m, void *key, LLVMMetadataRef va } } +gb_internal void lb_add_raddbg_string(lbModule *m, String const &str) { + mpsc_enqueue(&m->gen->raddebug_section_strings, copy_string(permanent_allocator(), str)); +} + +gb_internal void lb_add_raddbg_string(lbModule *m, char const *cstr) { + mpsc_enqueue(&m->gen->raddebug_section_strings, copy_string(permanent_allocator(), make_string_c(cstr))); +} + +gb_internal void lb_add_raddbg_string(lbModule *m, char const *a, char const *b) { + String str = concatenate_strings(permanent_allocator(), make_string_c(a), make_string_c(b)); + mpsc_enqueue(&m->gen->raddebug_section_strings, str); +} + +gb_internal void lb_add_raddbg_string(lbModule *m, char const *a, char const *b, char const *c) { + String str = concatenate3_strings(permanent_allocator(), make_string_c(a), make_string_c(b), make_string_c(c)); + mpsc_enqueue(&m->gen->raddebug_section_strings, str); +} + + gb_internal LLVMMetadataRef lb_get_current_debug_scope(lbProcedure *p) { GB_ASSERT_MSG(p->debug_info != nullptr, "missing debug information for %.*s", LIT(p->name)); @@ -390,6 +409,69 @@ gb_internal LLVMMetadataRef lb_debug_dynamic_array(lbModule *m, Type *type, Stri return final_decl; } +gb_internal LLVMMetadataRef lb_debug_fixed_capacity_dynamic_array(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_FixedCapacityDynamicArray); + + unsigned const int_bits = cast(unsigned)(8*build_context.int_size); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( + m->debug_builder, DW_TAG_structure_type, + cast(char const *)name.text, cast(size_t)name.len, + scope, file, line, 0, size_in_bits, align_in_bits, LLVMDIFlagZero, "", 0 + ); + + lb_set_llvm_metadata(m, type, temp_forward_decl); + + unsigned element_count = 2; + LLVMMetadataRef elements[2]; + + // LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->DynamicArray.scope); + LLVMMetadataRef member_scope = nullptr; + + Type *elem_type = alloc_type_array(bt->FixedCapacityDynamicArray.elem, bt->FixedCapacityDynamicArray.capacity); + elements[0] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "data", 4, + file, line, + 8*cast(u64)type_size_of(elem_type), 8*cast(u32)type_align_of(elem_type), + 0, + LLVMDIFlagZero, lb_debug_type(m, elem_type) + ); + + i64 len_offset_in_bits = 8*type_offset_of(bt, 1); + + elements[1] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "len", 3, + file, line, + int_bits, int_bits, + len_offset_in_bits, + LLVMDIFlagZero, lb_debug_type(m, t_int) + ); + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType( + m->debug_builder, scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + nullptr, + elements, element_count, + 0, + nullptr, + "", 0 + ); + + LLVMMetadataReplaceAllUsesWith(temp_forward_decl, final_decl); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + + gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { Type *bt = base_type(type); GB_ASSERT(bt->kind == Type_Union); @@ -564,22 +646,21 @@ gb_internal LLVMMetadataRef lb_debug_bitfield(lbModule *m, Type *type, String na u64 size_in_bits = 8*type_size_of(bt); u32 align_in_bits = 8*cast(u32)type_align_of(bt); - unsigned element_count = cast(unsigned)bt->BitField.fields.count; - LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count); + unsigned element_count = cast(unsigned)bt->BitField.fields.count; + LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count); - u64 offset_in_bits = 0; - for (unsigned i = 0; i < element_count; i++) { - Entity *f = bt->BitField.fields[i]; - u8 bit_size = bt->BitField.bit_sizes[i]; - GB_ASSERT(f->kind == Entity_Variable); - String name = f->token.string; - elements[i] = LLVMDIBuilderCreateBitFieldMemberType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, line, - bit_size, offset_in_bits, 0, - LLVMDIFlagZero, lb_debug_type(m, f->type) - ); - - offset_in_bits += bit_size; - } + u64 offset_in_bits = 0; + for (unsigned i = 0; i < element_count; i++) { + Entity *f = bt->BitField.fields[i]; + u8 bit_size = bt->BitField.bit_sizes[i]; + GB_ASSERT(f->kind == Entity_Variable); + String name = f->token.string; + elements[i] = LLVMDIBuilderCreateBitFieldMemberType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, line, + bit_size, offset_in_bits, 0, + LLVMDIFlagZero, lb_debug_type(m, f->type) + ); + offset_in_bits += bit_size; + } LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType( m->debug_builder, scope, @@ -686,7 +767,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_uintptr: return lb_debug_type_basic_type(m, str_lit("uintptr"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned); case Basic_typeid: - return lb_debug_type_basic_type(m, str_lit("typeid"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned); + return lb_debug_type_basic_type(m, str_lit("typeid"), 64, LLVMDWARFTypeEncoding_Unsigned); // Endian Specific Types case Basic_i16le: return lb_debug_type_basic_type(m, str_lit("i16le"), 16, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagLittleEndian); @@ -711,22 +792,22 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_i128be: return lb_debug_type_basic_type(m, str_lit("i128be"), 128, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagBigEndian); case Basic_u128be: return lb_debug_type_basic_type(m, str_lit("u128be"), 128, LLVMDWARFTypeEncoding_Unsigned, LLVMDIFlagBigEndian); - case Basic_f16be: return lb_debug_type_basic_type(m, str_lit("f16be"), 16, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); - case Basic_f32be: return lb_debug_type_basic_type(m, str_lit("f32be"), 32, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); - case Basic_f64be: return lb_debug_type_basic_type(m, str_lit("f64be"), 64, LLVMDWARFTypeEncoding_Float, LLVMDIFlagLittleEndian); + case Basic_f16be: return lb_debug_type_basic_type(m, str_lit("f16be"), 16, LLVMDWARFTypeEncoding_Float, LLVMDIFlagBigEndian); + case Basic_f32be: return lb_debug_type_basic_type(m, str_lit("f32be"), 32, LLVMDWARFTypeEncoding_Float, LLVMDIFlagBigEndian); + case Basic_f64be: return lb_debug_type_basic_type(m, str_lit("f64be"), 64, LLVMDWARFTypeEncoding_Float, LLVMDIFlagBigEndian); case Basic_complex32: { LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f16, 0*16); elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 1*16); - return lb_debug_basic_struct(m, str_lit("complex32"), 64, 32, elements, gb_count_of(elements)); + return lb_debug_basic_struct(m, str_lit("complex32"), 32, 16, elements, gb_count_of(elements)); } case Basic_complex64: { LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f32, 0*32); - elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 2*32); + elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 1*32); return lb_debug_basic_struct(m, str_lit("complex64"), 64, 32, elements, gb_count_of(elements)); } case Basic_complex128: @@ -744,7 +825,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f16, 1*16); elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f16, 2*16); elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f16, 3*16); - return lb_debug_basic_struct(m, str_lit("quaternion64"), 128, 32, elements, gb_count_of(elements)); + return lb_debug_basic_struct(m, str_lit("quaternion64"), 64, 16, elements, gb_count_of(elements)); } case Basic_quaternion128: { @@ -762,7 +843,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f64, 1*64); elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f64, 2*64); elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f64, 3*64); - return lb_debug_basic_struct(m, str_lit("quaternion256"), 256, 32, elements, gb_count_of(elements)); + return lb_debug_basic_struct(m, str_lit("quaternion256"), 256, 64, elements, gb_count_of(elements)); } @@ -774,6 +855,8 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { } case Basic_string: { + // NOTE(bill): size_of(^u8) <= size_of(int) + LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("data"), t_u8_ptr, 0); elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, int_bits); @@ -784,12 +867,28 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("char"), 8, LLVMDWARFTypeEncoding_Unsigned); return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring", 7); } + + case Basic_string16: + { + // NOTE(bill): size_of(^u16) <= size_of(int) + + LLVMMetadataRef elements[2] = {}; + elements[0] = lb_debug_struct_field(m, str_lit("data"), t_u16_ptr, 0); + elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, int_bits); + return lb_debug_basic_struct(m, str_lit("string16"), 2*int_bits, int_bits, elements, gb_count_of(elements)); + } + case Basic_cstring16: + { + LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("wchar_t"), 16, LLVMDWARFTypeEncoding_Unsigned); + return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring16", 7); + } + case Basic_any: { LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0); - elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, ptr_bits); - return lb_debug_basic_struct(m, str_lit("any"), 2*ptr_bits, ptr_bits, elements, gb_count_of(elements)); + elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, 64); // typeid is always 64 bits in size and 64 bits in alignment + return lb_debug_basic_struct(m, str_lit("any"), 128, 64, elements, gb_count_of(elements)); } // Untyped types @@ -811,6 +910,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { GB_PANIC("Type_Named should be handled in lb_debug_type separately"); case Type_SoaPointer: + // TODO(bill): This is technically incorrect and needs fixing return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->SoaPointer.elem), int_bits, int_bits, 0, nullptr, 0); case Type_Pointer: return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), ptr_bits, ptr_bits, 0, nullptr, 0); @@ -862,6 +962,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Type_BitSet: return lb_debug_bitset( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); case Type_Enum: return lb_debug_enum( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); case Type_BitField: return lb_debug_bitfield( m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); + case Type_FixedCapacityDynamicArray: return lb_debug_fixed_capacity_dynamic_array(m, type, type_to_canonical_string(temporary_allocator(), type), nullptr, nullptr, 0); case Type_Tuple: if (type->Tuple.variables.count == 1) { @@ -924,6 +1025,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { } case Type_Matrix: { + #if 0 LLVMMetadataRef subscripts[1] = {}; subscripts[0] = LLVMDIBuilderGetOrCreateSubrange(m->debug_builder, 0ll, @@ -935,6 +1037,66 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { 8*cast(unsigned)type_align_of(type), lb_debug_type(m, type->Matrix.elem), subscripts, gb_count_of(subscripts)); + #else + LLVMMetadataRef subscripts[2] = {}; + subscripts[0] = LLVMDIBuilderGetOrCreateSubrange(m->debug_builder, 0ll, type->Matrix.row_count); + subscripts[1] = LLVMDIBuilderGetOrCreateSubrange(m->debug_builder, 0ll, type->Matrix.column_count); + + LLVMMetadataRef scope = nullptr; + LLVMMetadataRef array_type = nullptr; + + uint64_t size_in_bits = 8*cast(uint64_t)(type_size_of(type)); + unsigned align_in_bits = 8*cast(unsigned)(type_align_of(type)); + + if (type->Matrix.is_row_major) { + LLVMMetadataRef base = LLVMDIBuilderCreateArrayType(m->debug_builder, + 8*cast(uint64_t)(type_size_of(type->Matrix.elem) * type->Matrix.column_count), + 8*cast(unsigned)type_align_of(type->Matrix.elem), + lb_debug_type(m, type->Matrix.elem), + subscripts+1, 1); + array_type = LLVMDIBuilderCreateArrayType(m->debug_builder, + size_in_bits, + align_in_bits, + base, + subscripts+0, 1); + } else { + LLVMMetadataRef base = LLVMDIBuilderCreateArrayType(m->debug_builder, + 8*cast(uint64_t)(type_size_of(type->Matrix.elem) * type->Matrix.row_count), + 8*cast(unsigned)type_align_of(type->Matrix.elem), + lb_debug_type(m, type->Matrix.elem), + subscripts+0, 1); + array_type = LLVMDIBuilderCreateArrayType(m->debug_builder, + size_in_bits, + align_in_bits, + base, + subscripts+1, 1); + } + + LLVMMetadataRef elements[1] = {}; + elements[0] = LLVMDIBuilderCreateMemberType(m->debug_builder, scope, + "data", 4, + nullptr, 0, + size_in_bits, align_in_bits, 0, LLVMDIFlagZero, + array_type + ); + + gbString name = temp_canonical_string(type); + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType( + m->debug_builder, scope, + name, gb_string_length(name), + nullptr, 0, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + nullptr, + elements, 1, + 0, + nullptr, + "", 0 + ); + + return final_decl; + #endif } } @@ -1186,7 +1348,7 @@ gb_internal void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx } -gb_internal String debug_info_mangle_constant_name(Entity *e, gbAllocator const &allocator, bool *did_allocate_) { +gb_internal String lb_debug_info_mangle_constant_name(Entity *e, gbAllocator const &allocator, bool *did_allocate_) { String name = e->token.string; if (e->pkg && e->pkg->name.len > 0) { gbString s = string_canonical_entity_name(allocator, e); @@ -1196,7 +1358,7 @@ gb_internal String debug_info_mangle_constant_name(Entity *e, gbAllocator const return name; } -gb_internal void add_debug_info_global_variable_expr(lbModule *m, String const &name, LLVMMetadataRef dtype, LLVMMetadataRef expr) { +gb_internal void lb_add_debug_info_global_variable_expr(lbModule *m, String const &name, LLVMMetadataRef dtype, LLVMMetadataRef expr) { LLVMMetadataRef scope = nullptr; LLVMMetadataRef file = nullptr; unsigned line = 0; @@ -1212,20 +1374,20 @@ gb_internal void add_debug_info_global_variable_expr(lbModule *m, String const & expr, decl, 8/*AlignInBits*/); } -gb_internal void add_debug_info_for_global_constant_internal_i64(lbModule *m, Entity *e, LLVMMetadataRef dtype, i64 v) { +gb_internal void lb_add_debug_info_for_global_constant_internal_i64(lbModule *m, Entity *e, LLVMMetadataRef dtype, i64 v) { LLVMMetadataRef expr = LLVMDIBuilderCreateConstantValueExpression(m->debug_builder, v); TEMPORARY_ALLOCATOR_GUARD(); - String name = debug_info_mangle_constant_name(e, temporary_allocator(), nullptr); + String name = lb_debug_info_mangle_constant_name(e, temporary_allocator(), nullptr); - add_debug_info_global_variable_expr(m, name, dtype, expr); + lb_add_debug_info_global_variable_expr(m, name, dtype, expr); if ((e->pkg && e->pkg->kind == Package_Init) || (e->scope && (e->scope->flags & ScopeFlag_Global))) { - add_debug_info_global_variable_expr(m, e->token.string, dtype, expr); + lb_add_debug_info_global_variable_expr(m, e->token.string, dtype, expr); } } -gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen, Entity *e) { +gb_internal void lb_add_debug_info_for_global_constant_from_entity(lbGenerator *gen, Entity *e) { if (e == nullptr || e->kind != Entity_Constant) { return; } @@ -1234,7 +1396,7 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen } lbModule *m = &gen->default_module; if (USE_SEPARATE_MODULES) { - m = lb_module_of_entity(gen, e); + m = lb_module_of_entity(gen, e, m); } GB_ASSERT(m != nullptr); @@ -1256,14 +1418,14 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen dtype = lb_debug_type(m, e->type); } - add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + lb_add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } else if (is_type_rune(e->type)) { ExactValue const &value = e->Constant.value; if (value.kind == ExactValue_Integer) { LLVMMetadataRef dtype = lb_debug_type(m, t_rune); i64 v = exact_value_to_i64(value); - add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + lb_add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } else if (is_type_boolean(e->type)) { ExactValue const &value = e->Constant.value; @@ -1271,7 +1433,7 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type)); i64 v = cast(i64)value.value_bool; - add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + lb_add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } else if (is_type_enum(e->type)) { ExactValue const &value = e->Constant.value; @@ -1284,14 +1446,70 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen v = cast(i64)exact_value_to_u64(value); } - add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + lb_add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } else if (is_type_pointer(e->type)) { ExactValue const &value = e->Constant.value; if (value.kind == ExactValue_Integer) { LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type)); i64 v = cast(i64)exact_value_to_u64(value); - add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); + lb_add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } } + +gb_internal void lb_add_debug_label(lbProcedure *p, Ast *label, lbBlock *target) { +// NOTE(tf2spi): LLVM-C DILabel API used only existed for major versions 20+ +#if LLVM_VERSION_MAJOR >= 20 + if (p == nullptr || p->debug_info == nullptr) { + return; + } + if (target == nullptr || label == nullptr || label->kind != Ast_Label) { + return; + } + Token label_token = label->Label.token; + if (is_blank_ident(label_token.string)) { + return; + } + lbModule *m = p->module; + if (m == nullptr) { + return; + } + + AstFile *file = label->file(); + LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, file); + if (llvm_file == nullptr) { + debugf("llvm file not found for label\n"); + return; + } + LLVMMetadataRef llvm_scope = p->debug_info; + if(llvm_scope == nullptr) { + debugf("llvm scope not found for label\n"); + return; + } + LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, label_token.pos); + LLVMBasicBlockRef llvm_block = target->block; + if (llvm_block == nullptr || llvm_debug_loc == nullptr) { + return; + } + LLVMMetadataRef llvm_label = LLVMDIBuilderCreateLabel( + m->debug_builder, + llvm_scope, + (const char *)label_token.string.text, + (size_t)label_token.string.len, + llvm_file, + label_token.pos.line, + + // NOTE(tf2spi): Defaults to false in LLVM API, but I'd rather not take chances + // Always preserve the label no matter what when debugging + true + ); + GB_ASSERT(llvm_label != nullptr); + (void)LLVMDIBuilderInsertLabelAtEnd( + m->debug_builder, + llvm_label, + llvm_debug_loc, + llvm_block + ); +#endif +} diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 0909b189a..7eb32279e 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1,4 +1,6 @@ gb_internal lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise); +gb_internal lbValue lb_build_slice_expr_value(lbProcedure *p, Ast *expr); +gb_internal lbValue lb_expand_values(lbProcedure *p, lbValue val, Type *type); gb_internal lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *final_type) { lbModule *m = p->module; @@ -242,25 +244,18 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, LLVMValueRef v0 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 0, ""), ""); LLVMValueRef v1 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 1, ""), ""); - lbAddr addr = lb_add_local_generated(p, x.type, false); - LLVMTypeRef type = llvm_addr_type(p->module, addr.addr); - LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, "")); - LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, "")); - return lb_addr_load(p, addr); - + Type *et = base_complex_elem_type(x.type); + lbValue fields[2] = {{v0, et}, {v1, et}}; + return lb_build_struct_value(p, x.type, fields, gb_count_of(fields)); } else if (is_type_quaternion(x.type)) { LLVMValueRef v0 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 0, ""), ""); LLVMValueRef v1 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 1, ""), ""); LLVMValueRef v2 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 2, ""), ""); LLVMValueRef v3 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 3, ""), ""); - lbAddr addr = lb_add_local_generated(p, x.type, false); - LLVMTypeRef type = llvm_addr_type(p->module, addr.addr); - LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, "")); - LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, "")); - LLVMBuildStore(p->builder, v2, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 2, "")); - LLVMBuildStore(p->builder, v3, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 3, "")); - return lb_addr_load(p, addr); + Type *et = base_complex_elem_type(x.type); + lbValue fields[4] = {{v0, et}, {v1, et}, {v2, et}, {v3, et}}; + return lb_build_struct_value(p, x.type, fields, gb_count_of(fields)); } else if (is_type_simd_vector(x.type)) { Type *elem = base_array_type(x.type); if (is_type_float(elem)) { @@ -282,6 +277,70 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, return res; } +gb_internal u64 lb_get_file_feature_flags(lbProcedure *p, Ast *expr = nullptr) { + AstFile *file = nullptr; + + if (expr != nullptr) { + file = expr->file(); + } + + if (file != nullptr) { + // it is now set + } else if (p->body && p->body->file()) { + file = p->body->file(); + } else if (p->type_expr && p->type_expr->file()) { + file = p->type_expr->file(); + } else if (p->entity && p->entity->file) { + file = p->entity->file; + } + + if (file != nullptr && file->feature_flags_set) { + return file->feature_flags; + } + return 0; +} + + + +gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero_behaviour(lbProcedure *p) { + u64 flags = lb_get_file_feature_flags(p); + + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Trap) { + return IntegerDivisionByZero_Trap; + } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) { + return IntegerDivisionByZero_Zero; + } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Self) { + return IntegerDivisionByZero_Self; + } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_AllBits) { + return IntegerDivisionByZero_AllBits; + } + + return build_context.integer_division_by_zero_behaviour; +} + + +gb_internal bool is_simd_able_type(Type *t) { + if (t->kind != Type_Basic) { + return false; + } + + if (t->Basic.flags & (BasicFlag_Boolean|BasicFlag_Integer|BasicFlag_Float|BasicFlag_Rune)) { + TypeEndianKind kind = type_endian_kind_of(t); + switch (kind) { + case TypeEndian_Platform: return true; + case TypeEndian_Little: return build_context.endian_kind == TargetEndian_Little; + case TypeEndian_Big: return build_context.endian_kind == TargetEndian_Big; + } + } + return false; +} + +// TODO(bill): is this a sensible limit? +#define MAX_SIMD_ARRAY_COUNT_FOR_INLINING 64 + gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, lbValue *res_) { GB_ASSERT(is_type_array_like(type)); @@ -354,7 +413,6 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu } } else { - switch (op) { case Token_Add: z = LLVMBuildAdd(p->builder, x, y, ""); @@ -366,17 +424,15 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu z = LLVMBuildMul(p->builder, x, y, ""); break; case Token_Quo: - if (is_type_unsigned(integral_type)) { - z = LLVMBuildUDiv(p->builder, x, y, ""); - } else { - z = LLVMBuildSDiv(p->builder, x, y, ""); + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildUDiv : LLVMBuildSDiv; + z = call(p->builder, x, y, ""); } break; case Token_Mod: - if (is_type_unsigned(integral_type)) { - z = LLVMBuildURem(p->builder, x, y, ""); - } else { - z = LLVMBuildSRem(p->builder, x, y, ""); + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildURem : LLVMBuildSRem; + z = call(p->builder, x, y, ""); } break; case Token_ModMod: @@ -418,6 +474,121 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu } } + + i64 count = get_array_type_count(type); + if (false && + count <= MAX_SIMD_ARRAY_COUNT_FOR_INLINING && + is_simd_able_type(elem_type) && is_simd_able_type(elem_type)) { + Type *integral_type = elem_type; + + LLVMTypeRef vector_elem_type = lb_type(p->module, integral_type); + LLVMTypeRef vector_type = LLVMVectorType(vector_elem_type, cast(unsigned)count); + + if (is_type_bit_set(integral_type)) { + switch (op) { + case Token_Add: op = Token_Or; break; + case Token_Sub: op = Token_AndNot; break; + } + Type *u = bit_set_to_int(type); + if (is_type_array(u)) { + return false; + } + } + + LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), ""); + LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), ""); + LLVMValueRef x = OdinLLVMBuildLoad(p, vector_type, lhs_vp); + LLVMValueRef y = OdinLLVMBuildLoad(p, vector_type, rhs_vp); + LLVMSetAlignment(x, cast(unsigned)type_align_of(integral_type)); + LLVMSetAlignment(y, cast(unsigned)type_align_of(integral_type)); + + LLVMValueRef z = nullptr; + + if (is_type_float(integral_type)) { + switch (op) { + case Token_Add: + z = LLVMBuildFAdd(p->builder, x, y, ""); + break; + case Token_Sub: + z = LLVMBuildFSub(p->builder, x, y, ""); + break; + case Token_Mul: + z = LLVMBuildFMul(p->builder, x, y, ""); + break; + case Token_Quo: + z = LLVMBuildFDiv(p->builder, x, y, ""); + break; + case Token_Mod: + z = LLVMBuildFRem(p->builder, x, y, ""); + break; + default: + GB_PANIC("Unsupported vector operation %.*s", LIT(token_strings[op])); + break; + } + + } else { + switch (op) { + case Token_Add: + z = LLVMBuildAdd(p->builder, x, y, ""); + break; + case Token_Sub: + z = LLVMBuildSub(p->builder, x, y, ""); + break; + case Token_Mul: + z = LLVMBuildMul(p->builder, x, y, ""); + break; + case Token_Quo: + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildUDiv : LLVMBuildSDiv; + z = call(p->builder, x, y, ""); + } + break; + case Token_Mod: + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildURem : LLVMBuildSRem; + z = call(p->builder, x, y, ""); + } + break; + case Token_ModMod: + if (is_type_unsigned(integral_type)) { + z = LLVMBuildURem(p->builder, x, y, ""); + } else { + LLVMValueRef a = LLVMBuildSRem(p->builder, x, y, ""); + LLVMValueRef b = LLVMBuildAdd(p->builder, a, y, ""); + z = LLVMBuildSRem(p->builder, b, y, ""); + } + break; + case Token_And: + z = LLVMBuildAnd(p->builder, x, y, ""); + break; + case Token_AndNot: + z = LLVMBuildAnd(p->builder, x, LLVMBuildNot(p->builder, y, ""), ""); + break; + case Token_Or: + z = LLVMBuildOr(p->builder, x, y, ""); + break; + case Token_Xor: + z = LLVMBuildXor(p->builder, x, y, ""); + break; + default: + GB_PANIC("Unsupported vector operation"); + break; + } + } + + + if (z != nullptr) { + lbAddr res = lb_add_local_generated_temp(p, type, lb_alignof(vector_type)); + + LLVMValueRef vp = LLVMBuildPointerCast(p->builder, res.addr.value, LLVMPointerType(vector_type, 0), ""); + LLVMValueRef store = LLVMBuildStore(p->builder, z, vp); + LLVMSetAlignment(store, cast(unsigned)type_align_of(type)); + lbValue v = lb_addr_load(p, res); + if (res_) *res_ = v; + return true; + } + } + return false; } @@ -442,7 +613,6 @@ gb_internal lbValue lb_emit_arith_array(lbProcedure *p, TokenKind op, lbValue lh bool inline_array_arith = lb_can_try_to_inline_array_arith(type); if (inline_array_arith) { - auto dst_ptrs = slice_make(temporary_allocator(), n); auto a_loads = slice_make(temporary_allocator(), n); @@ -494,7 +664,7 @@ gb_internal lbValue lb_emit_arith_array(lbProcedure *p, TokenKind op, lbValue lh } } -gb_internal bool lb_is_matrix_simdable(Type *t) { +gb_internal bool lb_is_matrix_simdable(Type *t, bool ignore_layout=false) { Type *mt = base_type(t); GB_ASSERT(mt->kind == Type_Matrix); @@ -519,12 +689,14 @@ gb_internal bool lb_is_matrix_simdable(Type *t) { // it's not aligned well enough to use the vector instructions return false; } - if ((mt->Matrix.row_count & 1) ^ (mt->Matrix.column_count & 1)) { + if ((mt->Matrix.row_count & 1) && (mt->Matrix.column_count & 1)) { return false; } if (mt->Matrix.is_row_major) { - // TODO(bill): make #row_major matrices work with SIMD - return false; + if (!ignore_layout) { + // TODO(bill): make #row_major matrices work with SIMD + return false; + } } if (elem->kind == Type_Basic) { @@ -607,7 +779,7 @@ gb_internal LLVMValueRef lb_matrix_to_trimmed_vector(lbProcedure *p, lbValue m) } -gb_internal lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *type) { +gb_internal lbValue lb_emit_matrix_transpose(lbProcedure *p, lbValue m, Type *type) { if (is_type_array(m.type)) { i32 rank = type_math_rank(m.type); if (rank == 2) { @@ -637,35 +809,44 @@ gb_internal lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *typ Type *mt = base_type(m.type); GB_ASSERT(mt->kind == Type_Matrix); - if (lb_is_matrix_simdable(mt)) { + Type *rt = base_type(type); + if (rt->kind == Type_Matrix && rt->Matrix.is_row_major != mt->Matrix.is_row_major) { + if (rt->Matrix.row_count == mt->Matrix.column_count && + rt->Matrix.column_count == mt->Matrix.row_count) { + lbValue res = m; + res.type = type; + return res; + } + + GB_PANIC("TODO: transpose with changing layout"); + } + + if (lb_is_matrix_simdable(mt, true) && lb_is_matrix_simdable(type, true)) { + auto const do_u32 = [](lbProcedure *p, u32 val) -> LLVMValueRef { + return LLVMConstInt(lb_type(p->module, t_u32), val, false); + }; + unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt); unsigned row_count = cast(unsigned)mt->Matrix.row_count; unsigned column_count = cast(unsigned)mt->Matrix.column_count; - - auto rows = slice_make(permanent_allocator(), row_count); - auto mask_elems = slice_make(permanent_allocator(), column_count); + unsigned other_stride = (row_count*column_count)/stride; LLVMValueRef vector = lb_matrix_to_vector(p, m); + auto mask_elems = slice_make(permanent_allocator(), row_count * column_count); for (unsigned i = 0; i < row_count; i++) { for (unsigned j = 0; j < column_count; j++) { - unsigned offset = stride*j + i; - mask_elems[j] = lb_const_int(p->module, t_u32, offset).value; + mask_elems[other_stride*i + j] = do_u32(p, stride*j + i); } - - // transpose mask - LLVMValueRef mask = LLVMConstVector(mask_elems.data, column_count); - LLVMValueRef row = llvm_basic_shuffle(p, vector, mask); - rows[i] = row; } + LLVMValueRef mask = LLVMConstVector(mask_elems.data, cast(unsigned)mask_elems.count); + LLVMValueRef transposed_vector = llvm_basic_shuffle(p, vector, mask); + lbAddr res = lb_add_local_generated(p, type, false); - lbAddr res = lb_add_local_generated(p, type, true); - for_array(i, rows) { - LLVMValueRef row = rows[i]; - lbValue dst_row_ptr = lb_emit_matrix_epi(p, res.addr, 0, i); - LLVMValueRef ptr = dst_row_ptr.value; - ptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(LLVMTypeOf(row), 0), ""); - LLVMBuildStore(p->builder, row, ptr); - } + LLVMValueRef res_ptr = res.addr.value; + res_ptr = LLVMBuildPointerCast(p->builder, res_ptr, LLVMPointerType(LLVMTypeOf(transposed_vector), 0), ""); + + LLVMValueRef store = LLVMBuildStore(p->builder, transposed_vector, res_ptr); + LLVMSetAlignment(store, cast(unsigned)type_align_of(type)); return lb_addr_load(p, res); } @@ -684,8 +865,10 @@ gb_internal lbValue lb_emit_matrix_tranpose(lbProcedure *p, lbValue m, Type *typ return lb_addr_load(p, res); } -gb_internal lbValue lb_matrix_cast_vector_to_type(lbProcedure *p, LLVMValueRef vector, Type *type) { - lbAddr res = lb_add_local_generated(p, type, true); +gb_internal lbAddr llvm_add_local_generated_from_vector(lbProcedure *p, Type *type, LLVMValueRef vector) { + GB_ASSERT(LLVMGetTypeKind(LLVMTypeOf(vector)) == LLVMVectorTypeKind); + + lbAddr res = lb_add_local_generated(p, type, false); LLVMValueRef res_ptr = res.addr.value; unsigned alignment = cast(unsigned)gb_max(type_align_of(type), lb_alignof(LLVMTypeOf(vector))); LLVMSetAlignment(res_ptr, alignment); @@ -693,9 +876,16 @@ gb_internal lbValue lb_matrix_cast_vector_to_type(lbProcedure *p, LLVMValueRef v res_ptr = LLVMBuildPointerCast(p->builder, res_ptr, LLVMPointerType(LLVMTypeOf(vector), 0), ""); LLVMBuildStore(p->builder, vector, res_ptr); + return res; +} + +gb_internal lbValue lb_matrix_cast_vector_to_type(lbProcedure *p, LLVMValueRef vector, Type *type) { + lbAddr res = llvm_add_local_generated_from_vector(p, type, vector); return lb_addr_load(p, res); } + + gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type) { if (is_type_array(m.type)) { // no-op @@ -713,31 +903,6 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type lbValue n = lb_const_int(p->module, t_int, type_size_of(type)); lb_mem_copy_non_overlapping(p, res.addr, m_ptr, n); - // i64 row_count = mt->Matrix.row_count; - // i64 column_count = mt->Matrix.column_count; - // TEMPORARY_ALLOCATOR_GUARD(); - - // auto srcs = array_make(temporary_allocator(), 0, row_count*column_count); - // auto dsts = array_make(temporary_allocator(), 0, row_count*column_count); - - // for (i64 j = 0; j < column_count; j++) { - // for (i64 i = 0; i < row_count; i++) { - // lbValue src = lb_emit_matrix_ev(p, m, i, j); - // array_add(&srcs, src); - // } - // } - - // for (i64 j = 0; j < column_count; j++) { - // for (i64 i = 0; i < row_count; i++) { - // lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count); - // array_add(&dsts, dst); - // } - // } - - // GB_ASSERT(srcs.count == dsts.count); - // for_array(i, srcs) { - // lb_emit_store(p, dsts[i], srcs[i]); - // } return lb_addr_load(p, res); } @@ -776,6 +941,10 @@ gb_internal lbValue lb_emit_outer_product(lbProcedure *p, lbValue a, lbValue b, gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, Type *type) { // TODO(bill): Handle edge case for f16 types on x86(-64) platforms + auto const do_u32 = [](lbProcedure *p, u32 val) -> LLVMValueRef { + return LLVMConstInt(lb_type(p->module, t_u32), val, false); + }; + Type *xt = base_type(lhs.type); Type *yt = base_type(rhs.type); @@ -792,50 +961,183 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, unsigned inner = cast(unsigned)xt->Matrix.column_count; unsigned outer_columns = cast(unsigned)yt->Matrix.column_count; - if (!xt->Matrix.is_row_major && lb_is_matrix_simdable(xt)) { - unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt); - unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt); + if (lb_is_matrix_simdable(xt, true)) { + if (!xt->Matrix.is_row_major) { // #column_major + unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt); + unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt); - auto x_rows = slice_make(permanent_allocator(), outer_rows); - auto y_columns = slice_make(permanent_allocator(), outer_columns); + LLVMValueRef x_vector = lb_matrix_to_vector(p, lhs); + LLVMValueRef y_vector = lb_matrix_to_vector(p, rhs); - LLVMValueRef x_vector = lb_matrix_to_vector(p, lhs); - LLVMValueRef y_vector = lb_matrix_to_vector(p, rhs); + if (outer_rows == outer_columns && outer_rows == inner && (inner & 1) == 0) { + // square matrix calculation + unsigned N = outer_columns; - auto mask_elems = slice_make(permanent_allocator(), inner); - for (unsigned i = 0; i < outer_rows; i++) { - for (unsigned j = 0; j < inner; j++) { - unsigned offset = x_stride*j + i; - mask_elems[j] = lb_const_int(p->module, t_u32, offset).value; + auto x_columns = slice_make(permanent_allocator(), N); + auto y_columns = slice_make(permanent_allocator(), N); + + for (unsigned i = 0; i < N; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, x_stride*i, N); + LLVMValueRef column = llvm_basic_shuffle(p, x_vector, mask); + x_columns[i] = column; + } + + for (unsigned i = 0; i < N; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, y_stride*i, N); + LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask); + y_columns[i] = column; + } + + + auto z_columns = slice_make(permanent_allocator(), N); + auto mask_elems = slice_make(permanent_allocator(), N); + + for (unsigned i = 0; i < N; i++) { + for (unsigned j = 0; j < N; j++) { + LLVMValueRef mask = llvm_mask_same(p->module, j, N); + mask_elems[j] = llvm_basic_shuffle(p, y_columns[i], mask); + } + z_columns[i] = llvm_vector_mul_pairwise_reduce_add(p, mask_elems, x_columns); + } + + lbAddr res = lb_add_local_generated(p, type, false); + LLVMValueRef dest_ptr = res.addr.value; + + LLVMTypeRef dest_ptr_type = LLVMPointerType(LLVMTypeOf(z_columns[0]), 0); + dest_ptr = LLVMBuildPointerCast(p->builder, dest_ptr, dest_ptr_type, ""); + for (unsigned i = 0; i < N; i++) { + LLVMValueRef indices[] = {do_u32(p, i)}; + LLVMValueRef dst = LLVMBuildInBoundsGEP2(p->builder, LLVMTypeOf(z_columns[0]), dest_ptr, indices, 1, ""); + LLVMBuildStore(p->builder, z_columns[i], dst); + } + + return lb_addr_load(p, res); } - // transpose mask - LLVMValueRef mask = LLVMConstVector(mask_elems.data, inner); - LLVMValueRef row = llvm_basic_shuffle(p, x_vector, mask); - x_rows[i] = row; - } - for (unsigned i = 0; i < outer_columns; i++) { - LLVMValueRef mask = llvm_mask_iota(p->module, y_stride*i, inner); - LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask); - y_columns[i] = column; - } + auto x_rows = slice_make(permanent_allocator(), outer_rows); + auto y_columns = slice_make(permanent_allocator(), outer_columns); - lbAddr res = lb_add_local_generated(p, type, true); - for_array(i, x_rows) { - LLVMValueRef x_row = x_rows[i]; - for_array(j, y_columns) { - LLVMValueRef y_column = y_columns[j]; - LLVMValueRef elem = llvm_vector_dot(p, x_row, y_column); - lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j); - LLVMBuildStore(p->builder, elem, dst.value); + auto mask_elems = slice_make(permanent_allocator(), inner); + for (unsigned i = 0; i < outer_rows; i++) { + for (unsigned j = 0; j < inner; j++) { + unsigned offset = x_stride*j + i; + mask_elems[j] = do_u32(p, offset); + } + + // transpose mask + LLVMValueRef mask = LLVMConstVector(mask_elems.data, inner); + LLVMValueRef row = llvm_basic_shuffle(p, x_vector, mask); + x_rows[i] = row; } + + for (unsigned i = 0; i < outer_columns; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, y_stride*i, inner); + LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask); + y_columns[i] = column; + } + + lbAddr res = lb_add_local_generated(p, type, false); + for_array(i, x_rows) { + LLVMValueRef x_row = x_rows[i]; + for_array(j, y_columns) { + LLVMValueRef y_column = y_columns[j]; + LLVMValueRef elem = llvm_vector_dot(p, x_row, y_column); + lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j); + LLVMBuildStore(p->builder, elem, dst.value); + } + } + return lb_addr_load(p, res); + } else { // #row_major + unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt); + unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt); + + LLVMValueRef x_vector = lb_matrix_to_vector(p, lhs); + LLVMValueRef y_vector = lb_matrix_to_vector(p, rhs); + + if (outer_rows == outer_columns && outer_rows == inner && (inner & 1) == 0) { + // square matrix calculation + unsigned N = outer_columns; + + auto x_rows = slice_make(permanent_allocator(), N); + auto y_rows = slice_make(permanent_allocator(), N); + + for (unsigned i = 0; i < N; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, x_stride*i, N); + LLVMValueRef column = llvm_basic_shuffle(p, x_vector, mask); + x_rows[i] = column; + } + + for (unsigned i = 0; i < N; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, y_stride*i, N); + LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask); + y_rows[i] = column; + } + + + auto z_rows = slice_make(permanent_allocator(), N); + auto mask_elems = slice_make(permanent_allocator(), N); + + for (unsigned i = 0; i < N; i++) { + for (unsigned j = 0; j < N; j++) { + LLVMValueRef mask = llvm_mask_same(p->module, j, N); + mask_elems[j] = llvm_basic_shuffle(p, x_rows[i], mask); + } + z_rows[i] = llvm_vector_mul_pairwise_reduce_add(p, mask_elems, y_rows); + } + + lbAddr res = lb_add_local_generated(p, type, false); + LLVMValueRef dest_ptr = res.addr.value; + + LLVMTypeRef dest_ptr_type = LLVMPointerType(LLVMTypeOf(z_rows[0]), 0); + dest_ptr = LLVMBuildPointerCast(p->builder, dest_ptr, dest_ptr_type, ""); + for (unsigned i = 0; i < N; i++) { + LLVMValueRef indices[] = {do_u32(p, i)}; + LLVMValueRef dst = LLVMBuildInBoundsGEP2(p->builder, LLVMTypeOf(z_rows[0]), dest_ptr, indices, 1, ""); + LLVMBuildStore(p->builder, z_rows[i], dst); + } + + return lb_addr_load(p, res); + } + + auto x_rows = slice_make(permanent_allocator(), outer_rows); + auto y_columns = slice_make(permanent_allocator(), outer_columns); + + for (unsigned i = 0; i < outer_rows; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, x_stride*i, inner); + LLVMValueRef row = llvm_basic_shuffle(p, x_vector, mask); + x_rows[i] = row; + } + + auto mask_elems = slice_make(permanent_allocator(), inner); + for (unsigned i = 0; i < outer_columns; i++) { + for (unsigned j = 0; j < inner; j++) { + unsigned offset = x_stride*j + i; + mask_elems[j] = do_u32(p, offset); + } + + // transpose mask + LLVMValueRef mask = LLVMConstVector(mask_elems.data, inner); + LLVMValueRef column = llvm_basic_shuffle(p, y_vector, mask); + y_columns[i] = column; + } + + lbAddr res = lb_add_local_generated(p, type, false); + for_array(i, x_rows) { + LLVMValueRef x_row = x_rows[i]; + for_array(j, y_columns) { + LLVMValueRef y_column = y_columns[j]; + LLVMValueRef elem = llvm_vector_dot(p, x_row, y_column); + lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j); + LLVMBuildStore(p->builder, elem, dst.value); + } + } + return lb_addr_load(p, res); } - return lb_addr_load(p, res); } if (!xt->Matrix.is_row_major) { - lbAddr res = lb_add_local_generated(p, type, true); + lbAddr res = lb_add_local_generated(p, type, false); auto inners = slice_make(permanent_allocator(), inner); @@ -859,7 +1161,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, return lb_addr_load(p, res); } else { - lbAddr res = lb_add_local_generated(p, type, true); + lbAddr res = lb_add_local_generated(p, type, false); auto inners = slice_make(permanent_allocator(), inner); @@ -911,41 +1213,49 @@ gb_internal lbValue lb_emit_matrix_mul_vector(lbProcedure *p, lbValue lhs, lbVal LLVMValueRef matrix_vector = lb_matrix_to_vector(p, lhs); - for (unsigned column_index = 0; column_index < column_count; column_index++) { - LLVMValueRef mask = llvm_mask_iota(p->module, stride*column_index, row_count); + for (unsigned i = 0; i < column_count; i++) { + LLVMValueRef mask = llvm_mask_iota(p->module, stride*i, row_count); LLVMValueRef column = llvm_basic_shuffle(p, matrix_vector, mask); - m_columns[column_index] = column; + m_columns[i] = column; } - for (unsigned row_index = 0; row_index < column_count; row_index++) { - LLVMValueRef value = lb_emit_struct_ev(p, rhs, row_index).value; - LLVMValueRef row = llvm_vector_broadcast(p, value, row_count); - v_rows[row_index] = row; - } + if (LLVMIsALoadInst(rhs.value)) { + LLVMValueRef rhs_ptr = LLVMGetOperand(rhs.value, 0); + LLVMTypeRef vector_type = LLVMVectorType(lb_type(p->module, elem), cast(unsigned)vector_count); + LLVMValueRef rhs_vector = LLVMBuildLoad2(p->builder, vector_type, rhs_ptr, ""); + LLVMSetAlignment(rhs_vector, cast(unsigned)type_align_of(type)); - GB_ASSERT(column_count > 0); - - LLVMValueRef vector = nullptr; - for (i64 i = 0; i < column_count; i++) { - if (i == 0) { - vector = llvm_vector_mul(p, m_columns[i], v_rows[i]); - } else { - vector = llvm_vector_mul_add(p, m_columns[i], v_rows[i], vector); + for (unsigned i = 0; i < column_count; i++) { + LLVMValueRef mask = llvm_mask_same(p->module, i, row_count); + v_rows[i] = llvm_basic_shuffle(p, rhs_vector, mask); + } + } else { + for (unsigned row_index = 0; row_index < column_count; row_index++) { + LLVMValueRef value = LLVMBuildExtractValue(p->builder, rhs.value, row_index, ""); + LLVMValueRef row = llvm_vector_broadcast(p, value, row_count); + v_rows[row_index] = row; } } + LLVMValueRef vector = llvm_vector_mul_pairwise_reduce_add(p, m_columns, v_rows); return lb_matrix_cast_vector_to_type(p, vector, type); } lbAddr res = lb_add_local_generated(p, type, true); + Type *vector_elem_type = base_array_type(rhs.type); + for (i64 i = 0; i < mt->Matrix.row_count; i++) { for (i64 j = 0; j < mt->Matrix.column_count; j++) { lbValue dst = lb_emit_matrix_epi(p, res.addr, i, 0); lbValue d0 = lb_emit_load(p, dst); lbValue a = lb_emit_matrix_ev(p, lhs, i, j); - lbValue b = lb_emit_struct_ev(p, rhs, cast(i32)j); + + + LLVMValueRef b_value = LLVMBuildExtractValue(p->builder, rhs.value, cast(unsigned)j, ""); + lbValue b = {b_value, vector_elem_type}; + lbValue c = lb_emit_mul_add(p, a, b, d0, elem); lb_emit_store(p, dst, c); } @@ -994,41 +1304,29 @@ gb_internal lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbVal } for (unsigned column_index = 0; column_index < row_count; column_index++) { - LLVMValueRef value = lb_emit_struct_ev(p, lhs, column_index).value; + LLVMValueRef value = LLVMBuildExtractValue(p->builder, lhs.value, column_index, ""); LLVMValueRef row = llvm_vector_broadcast(p, value, column_count); v_rows[column_index] = row; } - GB_ASSERT(row_count > 0); - - LLVMValueRef vector = nullptr; - for (i64 i = 0; i < row_count; i++) { - if (i == 0) { - vector = llvm_vector_mul(p, v_rows[i], m_columns[i]); - } else { - vector = llvm_vector_mul_add(p, v_rows[i], m_columns[i], vector); - } - } - - lbAddr res = lb_add_local_generated(p, type, true); - LLVMValueRef res_ptr = res.addr.value; - unsigned alignment = cast(unsigned)gb_max(type_align_of(type), lb_alignof(LLVMTypeOf(vector))); - LLVMSetAlignment(res_ptr, alignment); - - res_ptr = LLVMBuildPointerCast(p->builder, res_ptr, LLVMPointerType(LLVMTypeOf(vector), 0), ""); - LLVMBuildStore(p->builder, vector, res_ptr); + LLVMValueRef vector = llvm_vector_mul_pairwise_reduce_add(p, v_rows, m_columns); + lbAddr res = llvm_add_local_generated_from_vector(p, type, vector); return lb_addr_load(p, res); } lbAddr res = lb_add_local_generated(p, type, true); + Type *vector_elem_type = base_array_type(rhs.type); + for (i64 j = 0; j < mt->Matrix.column_count; j++) { for (i64 k = 0; k < mt->Matrix.row_count; k++) { lbValue dst = lb_emit_matrix_epi(p, res.addr, 0, j); lbValue d0 = lb_emit_load(p, dst); - lbValue a = lb_emit_struct_ev(p, lhs, cast(i32)k); + LLVMValueRef a_value = LLVMBuildExtractValue(p->builder, lhs.value, cast(unsigned)k, ""); + lbValue a = {a_value, vector_elem_type}; + lbValue b = lb_emit_matrix_ev(p, rhs, k, j); lbValue c = lb_emit_mul_add(p, a, b, d0, elem); lb_emit_store(p, dst, c); @@ -1111,6 +1409,306 @@ gb_internal lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue l return {}; } +gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, bool is_signed) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef all_bits = LLVMConstNot(zero); + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); + + auto *call = is_signed ? LLVMBuildSDiv : LLVMBuildUDiv; + + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Self: + return lhs; + case IntegerDivisionByZero_Zero: + return zero; + case IntegerDivisionByZero_AllBits: + return all_bits; + } + } else { + if (!is_signed && lb_sizeof(type) <= 8) { + u64 v = cast(u64)LLVMConstIntGetZExtValue(rhs); + if (v == 1) { + return lhs; + } else if (is_power_of_two_u64(v)) { + u64 n = floor_log2(v); + LLVMValueRef bits = LLVMConstInt(type, n, false); + return LLVMBuildLShr(p->builder, lhs, bits, ""); + } + } + + return call(p->builder, lhs, rhs, ""); + } + } + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + incoming_values[0] = call(p->builder, lhs, rhs, ""); + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + incoming_values[1] = zero; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = lhs; + break; + case IntegerDivisionByZero_AllBits: + incoming_values[1] = all_bits; + break; + } + LLVMValueRef res = nullptr; + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Self: + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + GB_ASSERT(incoming_blocks[0] == safe_block->block); + GB_ASSERT(incoming_blocks[1] == edge_case_block->block); + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} + +gb_internal LLVMValueRef lb_integer_division_fixed_point_intrinsics(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, LLVMValueRef scale, Type *platform_type, char const *name) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef all_bits = LLVMConstNot(zero); + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); + + auto const do_op = [&]() -> LLVMValueRef { + LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; + + LLVMValueRef args[3] = { + lhs, + rhs, + scale }; + + return lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + }; + + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Self: + return lhs; + case IntegerDivisionByZero_Zero: + return zero; + } + } else { + return do_op(); + } + } + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + incoming_values[0] = do_op(); + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + incoming_values[1] = zero; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = lhs; + break; + case IntegerDivisionByZero_AllBits: + incoming_values[1] = all_bits; + break; + } + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + LLVMValueRef res = nullptr; + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Self: + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} + + +gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, bool is_unsigned, bool is_floored) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + LLVMValueRef zero = LLVMConstNull(type); + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); + + auto const do_op = [&]() -> LLVMValueRef { + if (is_floored) { // %% + if (is_unsigned) { + return LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + LLVMValueRef a = LLVMBuildSRem(p->builder, lhs, rhs, ""); + LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs, ""); + LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs, ""); + return c; + } + } else { // % + if (is_unsigned) { + return LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + return LLVMBuildSRem(p->builder, lhs, rhs, ""); + } + } + }; + + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Trap: + break; + case IntegerDivisionByZero_Self: + return zero; + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + return lhs; + } + } else { + return do_op(); + } + } + + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "mod.safe"); + lbBlock *edge_case_block = lb_create_block(p, "mod.edge"); + lbBlock *done_block = lb_create_block(p, "mod.done"); + + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + incoming_values[0] = do_op(); + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + /* + NOTE(bill): @integer division by zero rules + + truncated: r = a - b*trunc(a/b) + floored: r = a - b*floor(a/b) + + If and only if (⟺) a/0 == 0, then (a%0 == a) or (a%%0 == a) + If and only if (⟺) a/0 == a, then (a%0 == 0) or (a%%0 == 0) + */ + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + incoming_values[1] = lhs; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = zero; + break; + } + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + LLVMValueRef res = incoming_values[0]; + + switch (behaviour) { + case IntegerDivisionByZero_Trap: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Self: + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) { @@ -1139,7 +1737,6 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV } } - lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later lbValue a = lb_emit_struct_ev(p, lhs, 0); lbValue b = lb_emit_struct_ev(p, lhs, 1); lbValue c = lb_emit_struct_ev(p, rhs, 0); @@ -1177,10 +1774,9 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV } } - lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), real); - lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), imag); - return lb_addr_load(p, res); + lbValue fields[2] = {real, imag}; + return lb_build_struct_value(p, type, fields, gb_count_of(fields)); } else if (is_type_quaternion(type)) { lhs = lb_emit_conv(p, lhs, type); rhs = lb_emit_conv(p, rhs, type); @@ -1193,7 +1789,6 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV immediate_type = t_f32; } - lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later lbValue x0 = lb_emit_struct_ev(p, lhs, 0); lbValue x1 = lb_emit_struct_ev(p, lhs, 1); lbValue x2 = lb_emit_struct_ev(p, lhs, 2); @@ -1221,10 +1816,6 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV lbValue z2 = lb_emit_arith(p, op, x2, y2, immediate_type); lbValue z3 = lb_emit_arith(p, op, x3, y3, immediate_type); - lbValue d0 = lb_emit_struct_ep(p, res.addr, 0); - lbValue d1 = lb_emit_struct_ep(p, res.addr, 1); - lbValue d2 = lb_emit_struct_ep(p, res.addr, 2); - lbValue d3 = lb_emit_struct_ep(p, res.addr, 3); if (immediate_type != ft) { z0 = lb_emit_conv(p, z0, ft); @@ -1233,12 +1824,8 @@ gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbV z3 = lb_emit_conv(p, z3, ft); } - lb_emit_store(p, d0, z0); - lb_emit_store(p, d1, z1); - lb_emit_store(p, d2, z2); - lb_emit_store(p, d3, z3); - - return lb_addr_load(p, res); + lbValue fields[4] = {z0, z1, z2, z3}; + return lb_build_struct_value(p, type, fields, gb_count_of(fields)); } else if (op == Token_Mul) { TEMPORARY_ALLOCATOR_GUARD(); @@ -1350,33 +1937,20 @@ handle_op:; if (is_type_float(integral_type)) { res.value = LLVMBuildFDiv(p->builder, lhs.value, rhs.value, ""); return res; - } else if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildUDiv(p->builder, lhs.value, rhs.value, ""); + } else { + res.value = lb_integer_division(p, lhs.value, rhs.value, !is_type_unsigned(integral_type)); return res; } - res.value = LLVMBuildSDiv(p->builder, lhs.value, rhs.value, ""); - return res; case Token_Mod: if (is_type_float(integral_type)) { res.value = LLVMBuildFRem(p->builder, lhs.value, rhs.value, ""); return res; - } else if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildURem(p->builder, lhs.value, rhs.value, ""); - return res; } - res.value = LLVMBuildSRem(p->builder, lhs.value, rhs.value, ""); + res.value = lb_integer_modulo(p, lhs.value, rhs.value, is_type_unsigned(integral_type), /*is_floored*/false); return res; case Token_ModMod: - if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildURem(p->builder, lhs.value, rhs.value, ""); - return res; - } else { - LLVMValueRef a = LLVMBuildSRem(p->builder, lhs.value, rhs.value, ""); - LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs.value, ""); - LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs.value, ""); - res.value = c; - return res; - } + res.value = lb_integer_modulo(p, lhs.value, rhs.value, is_type_unsigned(integral_type), /*is_floored*/true); + return res; case Token_And: res.value = LLVMBuildAnd(p->builder, lhs.value, rhs.value, ""); @@ -1559,16 +2133,24 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { return lb_emit_conv(p, cmp, type); } else if (lb_is_empty_string_constant(be->right) && !is_type_union(be->left->tav.type)) { // `x == ""` or `x != ""` + Type *str_type = t_string; + if (is_type_string16(be->left->tav.type) || is_type_cstring16(be->left->tav.type)) { + str_type = t_string16; + } lbValue s = lb_build_expr(p, be->left); - s = lb_emit_conv(p, s, t_string); + s = lb_emit_conv(p, s, str_type); lbValue len = lb_string_len(p, s); lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0)); Type *type = default_type(tv.type); return lb_emit_conv(p, cmp, type); } else if (lb_is_empty_string_constant(be->left) && !is_type_union(be->right->tav.type)) { // `"" == x` or `"" != x` + Type *str_type = t_string; + if (is_type_string16(be->right->tav.type) || is_type_cstring16(be->right->tav.type)) { + str_type = t_string16; + } lbValue s = lb_build_expr(p, be->right); - s = lb_emit_conv(p, s, t_string); + s = lb_emit_conv(p, s, str_type); lbValue len = lb_string_len(p, s); lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0)); Type *type = default_type(tv.type); @@ -1656,6 +2238,8 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { res.type = t; res.value = llvm_cstring(m, str); return res; + } else if (src->kind == Type_Basic && src->Basic.kind == Basic_string16 && dst->Basic.kind == Basic_cstring16) { + GB_PANIC("TODO(bill): UTF-16 string"); } // if (is_type_float(dst)) { // return value; @@ -1795,6 +2379,38 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } + + if (is_type_cstring16(src) && is_type_u16_ptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_u16_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_cstring16(src) && is_type_u16_multi_ptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_u16_multi_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_cstring16(src) && is_type_rawptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_rawptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + + if (are_types_identical(src, t_cstring16) && are_types_identical(dst, t_string16)) { + TEMPORARY_ALLOCATOR_GUARD(); + + lbValue c = lb_emit_conv(p, value, t_cstring16); + auto args = array_make(temporary_allocator(), 1); + args[0] = c; + lbValue s = lb_emit_runtime_call(p, "cstring16_to_string16", args); + return lb_emit_conv(p, s, dst); + } + + + // integer -> boolean if (is_type_integer(src) && is_type_boolean(dst)) { lbValue res = {}; @@ -1847,77 +2463,63 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { if (is_type_complex(src) && is_type_complex(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, false); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft); lbValue imag = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 1), imag); - return lb_addr_load(p, gen); + + lbValue fields[2] = {real, imag}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_quaternion(src) && is_type_quaternion(dst)) { // @QuaternionLayout Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, false); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue q0 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft); lbValue q1 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft); lbValue q2 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 2), ft); lbValue q3 = lb_emit_conv(p, lb_emit_struct_ev(p, value, 3), ft); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), q0); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 1), q1); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 2), q2); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), q3); - return lb_addr_load(p, gen); + + lbValue fields[4] = {q0, q1, q2, q3}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_integer(src) && is_type_complex(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, true); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, value, ft); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real); - return lb_addr_load(p, gen); + lbValue fields[2] = {real, lb_const_nil(m, ft)}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_float(src) && is_type_complex(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, true); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, value, ft); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real); - return lb_addr_load(p, gen); + lbValue fields[2] = {real, lb_const_nil(m, ft)}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_integer(src) && is_type_quaternion(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, true); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, value, ft); + lbValue zero = lb_const_nil(m, ft); // @QuaternionLayout - lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), real); - return lb_addr_load(p, gen); + lbValue fields[4] = {zero, zero, zero, real}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_float(src) && is_type_quaternion(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, true); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, value, ft); + lbValue zero = lb_const_nil(m, ft); // @QuaternionLayout - lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), real); - return lb_addr_load(p, gen); + lbValue fields[4] = {zero, zero, zero, real}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } if (is_type_complex(src) && is_type_quaternion(dst)) { Type *ft = base_complex_elem_type(dst); - lbAddr gen = lb_add_local_generated(p, t, true); - lbValue gp = lb_addr_get_ptr(p, gen); lbValue real = lb_emit_conv(p, lb_emit_struct_ev(p, value, 0), ft); lbValue imag = lb_emit_conv(p, lb_emit_struct_ev(p, value, 1), ft); + lbValue zero = lb_const_nil(m, ft); // @QuaternionLayout - lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), real); - lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), imag); - return lb_addr_load(p, gen); + lbValue fields[4] = {imag, zero, zero, real}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } // float <-> integer @@ -2149,7 +2751,6 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } for (Type *vt : dst->Union.variants) { if (src_type == t_llvm_bool && is_type_boolean(vt)) { - value = lb_emit_conv(p, value, vt); lbAddr parent = lb_add_local_generated(p, t, true); lb_emit_store_union_variant(p, parent.addr, value, vt); return lb_addr_load(p, parent); @@ -2210,13 +2811,14 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { Type *dt = t; + TEMPORARY_ALLOCATOR_GUARD(); + GB_ASSERT(is_type_struct(st) || is_type_raw_union(st)); Selection sel = {}; - sel.index.allocator = heap_allocator(); - defer (array_free(&sel.index)); + sel.index.allocator = temporary_allocator(); if (lookup_subtype_polymorphic_selection(t, src_type, &sel)) { if (sel.entity == nullptr) { - GB_PANIC("invalid subtype cast %s -> ", type_to_string(src_type), type_to_string(t)); + GB_PANIC("invalid subtype cast %s -> %s", type_to_string(src_type), type_to_string(t)); } if (st_is_ptr) { lbValue res = lb_emit_deep_field_gep(p, value, sel); @@ -2296,6 +2898,29 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return res; } + // [^]u16 <-> cstring16 + if (is_type_u16_multi_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_cstring16(src) && is_type_u16_multi_ptr(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_u16_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_cstring16(src) && is_type_u16_ptr(dst)) { + return lb_emit_transmute(p, value, t); + } + + + // []u16 <-> string16 + if (is_type_u16_slice(src) && is_type_string16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_string16(src) && is_type_u16_slice(dst)) { + return lb_emit_transmute(p, value, t); + } + // []byte/[]u8 <-> string if (is_type_u8_slice(src) && is_type_string(dst)) { return lb_emit_transmute(p, value, t); @@ -2304,6 +2929,167 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return lb_emit_transmute(p, value, t); } + + if (is_type_array(dst) && is_type_array(src)) { + Type *dst_elem = base_array_type(dst); + Type *src_elem = base_array_type(src); + if (dst->Array.count == src->Array.count && + !is_type_array_like(dst->Array.elem) && + !is_type_array_like(src->Array.elem)) { + if (are_types_identical(dst_elem, src_elem)) { + lbValue v = value; + v.type = t; + return v; + } + i64 count = dst->Array.count; + + Type *de = core_type(dst_elem); + Type *se = core_type(src_elem); + if (count <= MAX_SIMD_ARRAY_COUNT_FOR_INLINING && + is_simd_able_type(se)) { + // NOTE(bill, 2026-04-23): These types are simd-able meaning you can use the direct vector operators + // But we need to be careful when it comes to alignment and tell LLVM that it is only aligned + // to the element type and not the natural vector size + // + // This is to give it a proper hint that this can be done as a vector even when `-o:speed` is not set + if (is_simd_able_type(de)) { + lbAddr v = lb_add_local_generated(p, t, false); // do not zero anything because it will be filled + + lbValue psrc = lb_address_from_load_or_generate_local(p, value); + lbValue pdst = v.addr; + + i64 de_sz = type_size_of(de); + i64 se_sz = type_size_of(se); + + LLVMOpcode op = cast(LLVMOpcode)0; + + if (is_type_float(se)) { + if (is_type_float(de)) { + if (de_sz == se_sz) { op = LLVMBitCast; } + else if (de_sz < se_sz) { op = LLVMFPTrunc; } + else { op = LLVMFPExt; } + } else { + GB_ASSERT(is_type_integer_like(de) || is_type_rune(de)); + if (is_type_unsigned(de) || is_type_boolean(de)) { op = LLVMFPToUI; } + else { op = LLVMFPToSI; } + } + } else { + GB_ASSERT(is_type_integer_like(se) || is_type_rune(se)); + + if (is_type_float(de)) { + if (is_type_unsigned(se) || is_type_boolean(se)) { op = LLVMUIToFP; } + else { op = LLVMSIToFP; } + } else { + if (de_sz == se_sz) { + op = LLVMBitCast; + } else if (de_sz < se_sz) { + op = LLVMTrunc; + } else { + op = (is_type_unsigned(se) || is_type_boolean(se)) ? LLVMZExt : LLVMSExt; // zero extent + } + } + } + + GB_ASSERT(op != 0); + + LLVMTypeRef src_vector_type = LLVMVectorType(lb_type(p->module, se), cast(unsigned)count); + LLVMTypeRef dst_vector_type = LLVMVectorType(lb_type(p->module, de), cast(unsigned)count); + + LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, psrc.value, LLVMPointerType(src_vector_type, 0), ""); + LLVMValueRef dst_ptr = LLVMBuildPointerCast(p->builder, pdst.value, LLVMPointerType(dst_vector_type, 0), ""); + + LLVMValueRef src_vector = LLVMBuildLoad2(p->builder, src_vector_type, src_ptr, ""); + LLVMSetAlignment(src_vector, cast(unsigned)type_align_of(se)); + + LLVMValueRef dst_vector = LLVMBuildCast(p->builder, op, src_vector, dst_vector_type, ""); + + LLVMValueRef store = LLVMBuildStore(p->builder, dst_vector, dst_ptr); + LLVMSetAlignment(store, cast(unsigned)type_align_of(de)); + + return lb_addr_load(p, v); + } else if (is_type_complex(de)) { + GB_ASSERT(is_type_float(se)); + + Type *cde = base_complex_elem_type(de); + + lbAddr v = lb_add_local_generated(p, t, false); // do not zero anything because it will be filled + + i64 cde_sz = type_size_of(cde); + i64 se_sz = type_size_of(se); + + lbValue psrc = lb_address_from_load_or_generate_local(p, value); + lbValue pdst = v.addr; + + LLVMOpcode op = cast(LLVMOpcode)0; + + if (cde_sz == se_sz) { op = LLVMBitCast; } + else if (cde_sz < se_sz) { op = LLVMFPTrunc; } + else { op = LLVMFPExt; } + + LLVMTypeRef src_vector_type = LLVMVectorType(lb_type(p->module, se), cast(unsigned)count); + LLVMTypeRef dst_vector_type = LLVMVectorType(lb_type(p->module, cde), cast(unsigned)count); + + LLVMValueRef src_ptr = LLVMBuildPointerCast(p->builder, psrc.value, LLVMPointerType(src_vector_type, 0), ""); + LLVMValueRef dst_ptr = LLVMBuildPointerCast(p->builder, pdst.value, LLVMPointerType(dst_vector_type, 0), ""); + + LLVMValueRef src_vector = LLVMBuildLoad2(p->builder, src_vector_type, src_ptr, ""); + LLVMSetAlignment(src_vector, cast(unsigned)type_align_of(se)); + + LLVMValueRef dst_vector = LLVMBuildCast(p->builder, op, src_vector, dst_vector_type, ""); + LLVMValueRef dst_zero = LLVMConstNull(dst_vector_type); + + LLVMValueRef *dst_mask_scalars = gb_alloc_array(temporary_allocator(), LLVMValueRef, count*2); + LLVMTypeRef llvm_i32 = lb_type(p->module, t_i32); + for (i64 i = 0; i < count; i++) { + dst_mask_scalars[i*2 + 0] = LLVMConstInt(llvm_i32, cast(u64)i, false); + dst_mask_scalars[i*2 + 1] = LLVMConstInt(llvm_i32, cast(u64)(count+i), false); + } + + LLVMValueRef dst_mask = LLVMConstVector(dst_mask_scalars, cast(unsigned)(count*2)); + dst_vector = LLVMBuildShuffleVector(p->builder, dst_vector, dst_zero, dst_mask, ""); + + + LLVMValueRef store = LLVMBuildStore(p->builder, dst_vector, dst_ptr); + LLVMSetAlignment(store, cast(unsigned)type_align_of(de)); + + return lb_addr_load(p, v); + } + } + + lbAddr v = lb_add_local_generated(p, t, true); + + lbValue psrc = lb_address_from_load_or_generate_local(p, value); + lbValue pdst = v.addr; + + if (count > MAX_SIMD_ARRAY_COUNT_FOR_INLINING) { + auto loop_data = lb_loop_start(p, count, t_int); + + lbValue sp = lb_emit_array_ep(p, psrc, loop_data.idx); + lbValue dp = lb_emit_array_ep(p, pdst, loop_data.idx); + + lbValue s = lb_emit_load(p, sp); + s = lb_emit_conv(p, s, dst_elem); + lb_emit_store(p, dp, s); + + lb_loop_end(p, loop_data); + } else { + + for (i64 i = 0; i < count; i++) { + lbValue sp = lb_emit_array_epi(p, psrc, i); + lbValue dp = lb_emit_array_epi(p, pdst, i); + + lbValue s = lb_emit_load(p, sp); + s = lb_emit_conv(p, s, dst_elem); + lb_emit_store(p, dp, s); + } + + } + + return lb_addr_load(p, v); + } + } + + if (is_type_array_like(dst)) { Type *elem = base_array_type(dst); isize index_count = cast(isize)get_array_type_count(dst); @@ -2355,7 +3141,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { Type *elem = base_array_type(dst); lbValue e = lb_emit_conv(p, value, elem); lbAddr v = lb_add_local_generated(p, t, false); - lbValue zero = lb_const_value(p->module, elem, exact_value_i64(0), LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); + lbValue zero = lb_const_value(p->module, elem, exact_value_i64(0), elem, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); for (i64 j = 0; j < dst->Matrix.column_count; j++) { for (i64 i = 0; i < dst->Matrix.row_count; i++) { lbValue ptr = lb_emit_matrix_epi(p, v.addr, i, j); @@ -2392,7 +3178,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { lb_emit_store(p, d, s); } else if (i == j) { lbValue d = lb_emit_matrix_epi(p, v.addr, i, j); - lbValue s = lb_const_value(p->module, dst->Matrix.elem, exact_value_i64(1), LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); + lbValue s = lb_const_value(p->module, dst->Matrix.elem, exact_value_i64(1), dst->Matrix.elem, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); lb_emit_store(p, d, s); } } @@ -2435,8 +3221,6 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return lb_const_nil(p->module, t); } - lbAddr result = lb_add_local_generated(p, t, true); - Type *st = default_type(src_type); lbValue data = lb_address_from_load_or_generate_local(p, value); @@ -2445,13 +3229,8 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { data = lb_emit_conv(p, data, t_rawptr); lbValue id = lb_typeid(p->module, st); - lbValue any_data = lb_emit_struct_ep(p, result.addr, 0); - lbValue any_id = lb_emit_struct_ep(p, result.addr, 1); - - lb_emit_store(p, any_data, data); - lb_emit_store(p, any_id, id); - - return lb_addr_load(p, result); + lbValue fields[2] = {data, id}; + return lb_build_struct_value(p, t, fields, gb_count_of(fields)); } @@ -2518,10 +3297,13 @@ gb_internal lbValue lb_emit_c_vararg(lbProcedure *p, lbValue arg, Type *type) { gb_internal lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right, Type *type) { GB_ASSERT((is_type_struct(type) || is_type_soa_pointer(type) || is_type_union(type)) && is_type_comparable(type)); + lbValue left_ptr = lb_address_from_load_or_generate_local(p, left); lbValue right_ptr = lb_address_from_load_or_generate_local(p, right); + i64 size = type_size_of(type); + lbValue res = {}; - if (type_size_of(type) == 0) { + if (size == 0) { switch (op_kind) { case Token_CmpEq: return lb_const_bool(p->module, t_bool, true); @@ -2530,8 +3312,23 @@ gb_internal lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValu } GB_PANIC("invalid operator"); } + TEMPORARY_ALLOCATOR_GUARD(); + if (is_type_simple_compare(type)) { + // if (size <= 8) { + // LLVMTypeRef int_type = LLVMIntTypeInContext(p->module->ctx, cast(unsigned)(size*8)); + // LLVMValueRef l = OdinLLVMBuildLoad(p, int_type, LLVMBuildPointerCast(p->builder, left_ptr.value, LLVMPointerType(int_type, 0), "")); + // LLVMValueRef r = OdinLLVMBuildLoad(p, int_type, LLVMBuildPointerCast(p->builder, right_ptr.value, LLVMPointerType(int_type, 0), "")); + + // LLVMIntPredicate pred = (op_kind == Token_CmpEq) ? LLVMIntEQ : LLVMIntNE; + // LLVMValueRef cmp = LLVMBuildICmp(p->builder, pred, l, r, ""); + + // res.value = cmp; + // res.type = t_bool; + // return res; + // } + // TODO(bill): Test to see if this is actually faster!!!! auto args = array_make(temporary_allocator(), 3); args[0] = lb_emit_conv(p, left_ptr, t_rawptr); @@ -2545,6 +3342,7 @@ gb_internal lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValu args[1] = lb_emit_conv(p, right_ptr, t_rawptr); res = lb_emit_call(p, value, args); } + if (op_kind == Token_NotEq) { res = lb_emit_unary_arith(p, Token_Not, res, res.type); } @@ -2572,6 +3370,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left return nil_check; } + if (are_types_identical(a, b)) { // NOTE(bill): No need for a conversion } else if ((lb_is_const(left) && !is_type_array(left.type)) || lb_is_const_nil(left)) { @@ -2584,15 +3383,20 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left if (internal_check_is_assignable_to(right.type, left.type)) { right = lb_emit_conv(p, right, left.type); } - return lb_emit_comp_against_nil(p, op_kind, right); + if (LLVMTypeOf(left.value) == LLVMTypeOf(right.value)) { + return lb_emit_comp_against_nil(p, op_kind, right); + } } left = lb_emit_conv(p, left, right.type); } else if ((lb_is_const(right) && !is_type_array(right.type)) || lb_is_const_nil(right)) { + if (lb_is_const_nil(right)) { if (internal_check_is_assignable_to(left.type, right.type)) { left = lb_emit_conv(p, left, right.type); } - return lb_emit_comp_against_nil(p, op_kind, left); + if (LLVMTypeOf(left.value) == LLVMTypeOf(right.value)) { + return lb_emit_comp_against_nil(p, op_kind, left); + } } right = lb_emit_conv(p, right, left.type); } else { @@ -2638,6 +3442,11 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left } if (is_type_array_like(a)) { Type *tl = base_type(a); + bool inline_array_arith = lb_can_try_to_inline_array_arith(tl); + if (inline_array_arith && is_type_bit_field(left.type)) { + left = lb_emit_transmute(p, left, tl); + right = lb_emit_transmute(p, right, tl); + } lbValue lhs = lb_address_from_load_or_generate_local(p, left); lbValue rhs = lb_address_from_load_or_generate_local(p, right); @@ -2652,7 +3461,6 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left cmp_op = Token_And; } - bool inline_array_arith = lb_can_try_to_inline_array_arith(tl); i32 count = 0; switch (tl->kind) { case Type_Array: count = cast(i32)tl->Array.count; break; @@ -2710,7 +3518,53 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left return lb_compare_records(p, op_kind, left, right, b); } + + if (is_type_string16(a) || is_type_cstring16(a)) { + if (is_type_cstring16(a) && is_type_cstring16(b)) { + left = lb_emit_conv(p, left, t_cstring16); + right = lb_emit_conv(p, right, t_cstring16); + char const *runtime_procedure = nullptr; + switch (op_kind) { + case Token_CmpEq: runtime_procedure = "cstring16_eq"; break; + case Token_NotEq: runtime_procedure = "cstring16_ne"; break; + case Token_Lt: runtime_procedure = "cstring16_lt"; break; + case Token_Gt: runtime_procedure = "cstring16_gt"; break; + case Token_LtEq: runtime_procedure = "cstring16_le"; break; + case Token_GtEq: runtime_procedure = "cstring16_ge"; break; + } + GB_ASSERT(runtime_procedure != nullptr); + + auto args = array_make(permanent_allocator(), 2); + args[0] = left; + args[1] = right; + return lb_emit_runtime_call(p, runtime_procedure, args); + } + + + if (is_type_cstring16(a) ^ is_type_cstring16(b)) { + left = lb_emit_conv(p, left, t_string16); + right = lb_emit_conv(p, right, t_string16); + } + + char const *runtime_procedure = nullptr; + switch (op_kind) { + case Token_CmpEq: runtime_procedure = "string16_eq"; break; + case Token_NotEq: runtime_procedure = "string16_ne"; break; + case Token_Lt: runtime_procedure = "string16_lt"; break; + case Token_Gt: runtime_procedure = "string16_gt"; break; + case Token_LtEq: runtime_procedure = "string16_le"; break; + case Token_GtEq: runtime_procedure = "string16_ge"; break; + } + GB_ASSERT(runtime_procedure != nullptr); + + auto args = array_make(permanent_allocator(), 2); + args[0] = left; + args[1] = right; + return lb_emit_runtime_call(p, runtime_procedure, args); + } + if (is_type_string(a)) { + if (is_type_cstring(a) && is_type_cstring(b)) { left = lb_emit_conv(p, left, t_cstring); right = lb_emit_conv(p, right, t_cstring); @@ -3056,6 +3910,13 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); } return res; + case Basic_cstring16: + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, x.value, ""); + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); + } + return res; case Basic_any: { // TODO(bill): is this correct behaviour for nil comparison for any? @@ -3150,7 +4011,7 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, } } break; - + case Type_SoaPointer: { // NOTE(bill): An SoaPointer is essentially just a pointer for nil comparison @@ -3366,6 +4227,17 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { Type *type = type_of_expr(ue_expr); GB_ASSERT(!is_type_tuple(type)); + bool do_type_check = true; + if (build_context.no_type_assert) { + u64 feature_flags = lb_get_file_feature_flags(p, ue_expr); + if ((feature_flags & OptInFeatureFlag_ForceTypeAssert) == 0) { + do_type_check = false; + } + + } else if ((p->state_flags & StateFlag_no_type_assert) != 0) { + do_type_check = false; + } + lbValue e = lb_build_expr(p, ta->expr); Type *t = type_deref(e.type); if (is_type_union(t)) { @@ -3377,7 +4249,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { Type *dst_type = type; - if (!build_context.no_type_assert && (p->state_flags & StateFlag_no_type_assert) == 0) { + if (do_type_check) { lbValue src_tag = {}; lbValue dst_tag = {}; if (is_type_union_maybe_pointer(src_type)) { @@ -3404,7 +4276,12 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { args[4] = lb_typeid(p->module, src_type); args[5] = lb_typeid(p->module, dst_type); } - lb_emit_runtime_call(p, "type_assertion_check", args); + + char const *name = "type_assertion_check_contextless"; + if (p->context_stack.count > 0) { + name = "type_assertion_check_with_context"; + } + lb_emit_runtime_call(p, name, args); } lbValue data_ptr = v; @@ -3415,21 +4292,33 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { v = lb_emit_load(p, v); } lbValue data_ptr = lb_emit_struct_ev(p, v, 0); - if (!build_context.no_type_assert && (p->state_flags & StateFlag_no_type_assert) == 0) { + if (do_type_check) { GB_ASSERT(!build_context.no_rtti); lbValue any_id = lb_emit_struct_ev(p, v, 1); + isize arg_count = 6; + if (build_context.no_rtti) { + arg_count = 4; + } + lbValue id = lb_typeid(p->module, type); lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); - auto args = array_make(permanent_allocator(), 6); + auto args = array_make(permanent_allocator(), arg_count); args[0] = ok; lb_set_file_line_col(p, array_slice(args, 1, args.count), pos); - args[4] = any_id; - args[5] = id; - lb_emit_runtime_call(p, "type_assertion_check", args); + if (!build_context.no_rtti) { + args[4] = any_id; + args[5] = id; + } + + char const *name = "type_assertion_check_contextless"; + if (p->context_stack.count > 0) { + name = "type_assertion_check_with_context"; + } + lb_emit_runtime_call(p, name, args); } return lb_emit_conv(p, data_ptr, tv.type); @@ -3499,6 +4388,20 @@ gb_internal lbValue lb_build_expr(lbProcedure *p, Ast *expr) { return res; } +gb_internal Type *lb_build_expr_original_const_type(Ast *expr) { + expr = unparen_expr(expr); + Type *type = type_of_expr(expr); + if (is_type_union(type)) { + if (expr->kind == Ast_CallExpr) { + if (expr->CallExpr.proc->tav.mode == Addressing_Type) { + Type *res = lb_build_expr_original_const_type(expr->CallExpr.args[0]); + return res; + } + } + } + return type_of_expr(expr); +} + gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { lbModule *m = p->module; @@ -3511,8 +4414,9 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { if (tv.value.kind != ExactValue_Invalid) { + Type *original_type = lb_build_expr_original_const_type(expr); // NOTE(bill): Short on constant values - return lb_const_value(p->module, type, tv.value, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); + return lb_const_value(p->module, type, tv.value, original_type, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); } else if (tv.mode == Addressing_Type) { // NOTE(bill, 2023-01-16): is this correct? I hope so at least return lb_typeid(m, tv.type); @@ -3593,7 +4497,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { TypeAndValue tav = type_and_value_of_expr(expr); GB_ASSERT(tav.mode == Addressing_Constant); - return lb_const_value(p->module, type, tv.value); + return lb_const_value(p->module, type, tv.value, tv.type, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL); case_end; case_ast_node(se, SelectorCallExpr, expr); @@ -3602,10 +4506,18 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { case_end; case_ast_node(te, TernaryIfExpr, expr); + GB_ASSERT(te->y != nullptr); + Type *type = default_type(type_of_expr(expr)); + if (lb_is_expr_trivial(te->x) && lb_is_expr_trivial(te->y)) { + lbValue cond = lb_build_expr(p, te->cond); + lbValue x = lb_emit_conv(p, lb_build_expr(p, te->x), type); + lbValue y = lb_emit_conv(p, lb_build_expr(p, te->y), type); + return lb_emit_select(p, cond, x, y); + } + LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; - GB_ASSERT(te->y != nullptr); lbBlock *then = lb_create_block(p, "if.then"); lbBlock *done = lb_create_block(p, "if.done"); // NOTE(bill): Append later lbBlock *else_ = lb_create_block(p, "if.else"); @@ -3613,7 +4525,6 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { lb_build_cond(p, te->cond, then, else_); lb_start_block(p, then); - Type *type = default_type(type_of_expr(expr)); LLVMTypeRef llvm_type = lb_type(p->module, type); incoming_values[0] = lb_emit_conv(p, lb_build_expr(p, te->x), type).value; @@ -3748,6 +4659,11 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { switch (ue->op.kind) { case Token_And: return lb_build_unary_and(p, expr); + case Token_MulMul: + { + lbValue val = lb_build_expr(p, ue->expr); + return lb_expand_values(p, val, type); + } default: { lbValue v = lb_build_expr(p, ue->expr); @@ -3780,13 +4696,31 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { return lb_build_expr(p, se->expr); } } + { + Type *src_type = base_type(type_of_expr(se->expr)); + if (is_type_pointer(src_type)) { + src_type = base_type(type_deref(src_type)); + } + + if (is_type_slice(src_type) || + is_type_dynamic_array(src_type) || + is_type_string(src_type) || + is_type_string16(src_type)) { + return lb_build_slice_expr_value(p, expr); + } + + if (is_type_multi_pointer(src_type) && se->high != nullptr) { + return lb_build_slice_expr_value(p, expr); + } + } + return lb_addr_load(p, lb_build_addr(p, expr)); case_end; case_ast_node(ie, IndexExpr, expr); return lb_addr_load(p, lb_build_addr(p, expr)); case_end; - + case_ast_node(ie, MatrixIndexExpr, expr); return lb_addr_load(p, lb_build_addr(p, expr)); case_end; @@ -3835,9 +4769,9 @@ gb_internal lbAddr lb_get_soa_variable_addr(lbProcedure *p, Entity *e) { } gb_internal lbValue lb_get_using_variable(lbProcedure *p, Entity *e) { GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); - String name = e->token.string; + InternedString interned = entity_interned_name(e); Entity *parent = e->using_parent; - Selection sel = lookup_field(parent->type, name, false); + Selection sel = lookup_field(parent->type, interned, false); GB_ASSERT(sel.entity != nullptr); lbValue *pv = map_get(&p->module->values, parent); @@ -3852,7 +4786,7 @@ gb_internal lbValue lb_get_using_variable(lbProcedure *p, Entity *e) { } else if (pv != nullptr) { v = *pv; } else { - GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(name)); + GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(e->token.string)); v = lb_build_addr_ptr(p, e->using_expr); } GB_ASSERT(v.value != nullptr); @@ -3874,7 +4808,7 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp GB_ASSERT(e != nullptr); if (e->kind == Entity_Constant) { Type *t = default_type(type_of_expr(expr)); - lbValue v = lb_const_value(p->module, t, e->Constant.value); + lbValue v = lb_const_value(p->module, t, e->Constant.value, e->type, LB_CONST_CONTEXT_DEFAULT_NO_LOCAL); if (LLVMIsConstant(v.value)) { lbAddr g = lb_add_global_generated_from_procedure(p, t, v); return g; @@ -3984,13 +4918,14 @@ gb_internal void lb_build_addr_compound_lit_populate(lbProcedure *p, SliceDynamicArray.elem; break; case Type_SimdVector: et = bt->SimdVector.elem; break; case Type_Matrix: et = bt->Matrix.elem; break; + case Type_FixedCapacityDynamicArray: et = bt->FixedCapacityDynamicArray.elem; break; } GB_ASSERT(et != nullptr); + isize elem_index = 0; // NOTE(bill): Separate value, gep, store into their own chunks - for_array(i, elems) { - Ast *elem = elems[i]; + for (Ast *elem : elems) { if (elem->kind == Ast_FieldValue) { ast_node(fv, FieldValue, elem); if (bt->kind != Type_DynamicArray && lb_is_elem_const(fv->value, et)) { @@ -4060,22 +4995,39 @@ gb_internal void lb_build_addr_compound_lit_populate(lbProcedure *p, Slicekind != Type_DynamicArray && lb_is_elem_const(elem, et)) { + elem_index++; continue; } lbValue field_expr = lb_build_expr(p, elem); - GB_ASSERT(!is_type_tuple(field_expr.type)); - lbValue ev = lb_emit_conv(p, field_expr, et); + if (is_type_tuple(field_expr.type)) { + TypeTuple *tt = &field_expr.type->Tuple; + for_array(jj, tt->variables) { + lbValue sub_field_expr = lb_emit_struct_ev(p, field_expr, cast(i32)jj); + lbValue ev = lb_emit_conv(p, sub_field_expr, et); - lbCompoundLitElemTempData data = {}; - data.value = ev; - if (bt->kind == Type_Matrix) { - data.elem_index = matrix_row_major_index_to_offset(bt, i); + lbCompoundLitElemTempData data = {}; + data.value = ev; + if (bt->kind == Type_Matrix) { + data.elem_index = matrix_row_major_index_to_offset(bt, elem_index++); + } else { + data.elem_index = elem_index++; + } + array_add(temp_data, data); + } } else { - data.elem_index = i; + lbValue ev = lb_emit_conv(p, field_expr, et); + + lbCompoundLitElemTempData data = {}; + data.value = ev; + if (bt->kind == Type_Matrix) { + data.elem_index = matrix_row_major_index_to_offset(bt, elem_index++); + } else { + data.elem_index = elem_index++; + } + array_add(temp_data, data); } - array_add(temp_data, data); } } } @@ -4152,6 +5104,8 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } } lbValue val = lb_emit_ptr_offset(p, field, index); + // make sure it's ^T and not [^]T + val.type = alloc_type_multi_pointer_to_pointer(val.type); return lb_addr(val); } @@ -4189,6 +5143,25 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { return lb_addr(elem); } + case Type_FixedCapacityDynamicArray: { + lbValue array = {}; + array = lb_build_addr_ptr(p, ie->expr); + if (deref) { + array = lb_emit_load(p, array); + } + lbValue index = lb_build_expr(p, ie->index); + index = lb_emit_conv(p, index, t_int); + + lbValue array_ptr = lb_emit_struct_ep(p, array, 0); + lbValue elem = lb_emit_array_ep(p, array_ptr, index); + + auto index_tv = type_and_value_of_expr(ie->index); + lbValue len = lb_emit_struct_ep(p, array, 1); + len = lb_emit_load(p, len); + lb_emit_bounds_check(p, ast_token(ie->index), index, len); + return lb_addr(elem); + } + case Type_EnumeratedArray: { lbValue array = {}; array = lb_build_addr_ptr(p, ie->expr); @@ -4298,12 +5271,13 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } - case Type_Basic: { // Basic_string + case Type_Basic: { // Basic_string/Basic_string16 lbValue str; lbValue elem; lbValue len; lbValue index; + str = lb_build_expr(p, ie->expr); if (deref) { str = lb_emit_load(p, str); @@ -4321,6 +5295,216 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } +gb_internal lbValue lb_build_slice_expr_value(lbProcedure *p, Ast *expr) { + ast_node(se, SliceExpr, expr); + + if (true) { + // NOTE(bill): Fused nested slice chain: src[a:b][c:d][e:f]... + // Walk a chain of nested SliceExprs down to the root source, then apply + // each slice's bounds check and offset on raw (ptr, len) SSA values, + // building a single aggregate at the end. + + + Ast *inner_ast = unparen_expr(se->expr); + if (inner_ast->kind == Ast_SliceExpr) { + enum {MAX_CHAIN = 8}; // this is more than enough in practice + + // Collect the chain: slices[0] is innermost, slices[n-1] is outer-most `se`. + Ast *chain[MAX_CHAIN] = {}; // bounded depth + isize chain_count = 0; + chain[chain_count++] = expr; // outer-most + + Ast *root = inner_ast; + while (root->kind == Ast_SliceExpr && chain_count < MAX_CHAIN) { + chain[chain_count++] = root; + root = unparen_expr(root->SliceExpr.expr); + } + + Type *root_type = base_type(type_of_expr(root)); + if (is_type_pointer(root_type)) { + root_type = base_type(type_deref(root_type)); + } + if (is_type_slice(root_type) || + is_type_dynamic_array(root_type) || + is_type_string(root_type) || + is_type_string16(root_type)) { + lbModule *m = p->module; + + // Evaluate the root source and extract raw (ptr, len). + lbValue src = lb_build_expr(p, root); + Type *src_type = base_type(src.type); + if (is_type_pointer(src_type)) { + src_type = base_type(type_deref(src_type)); + src = lb_emit_load(p, src); + } + + lbValue cur_ptr = {}; + lbValue cur_len = {}; + if (is_type_slice(src_type)) { + cur_ptr = lb_slice_elem(p, src); + cur_len = lb_slice_len(p, src); + } else if (is_type_dynamic_array(src_type)) { + cur_ptr = lb_dynamic_array_elem(p, src); + cur_len = lb_dynamic_array_len(p, src); + } else { + GB_ASSERT(is_type_string(src_type) || is_type_string16(src_type)); + cur_ptr = lb_string_elem(p, src); + cur_len = lb_string_len(p, src); + } + + // Apply each slice innermost-first (reverse of collection order). + for (isize i = chain_count - 1; i >= 0; i--) { + AstSliceExpr *s = &chain[i]->SliceExpr; + + lbValue lo = lb_const_int(m, t_int, 0); + lbValue hi = {}; + if (s->low != nullptr) { + lo = lb_correct_endianness(p, lb_build_expr(p, s->low)); + } + if (s->high != nullptr) { + hi = lb_correct_endianness(p, lb_build_expr(p, s->high)); + } + if (hi.value == nullptr) { + hi = cur_len; + } + + bool no_indices = s->low == nullptr && s->high == nullptr; + if (!no_indices) { + lb_emit_slice_bounds_check(p, s->open, lo, hi, cur_len, s->low != nullptr); + } + + cur_ptr = (s->low == nullptr) ? cur_ptr : lb_emit_ptr_offset(p, cur_ptr, lo); + cur_len = (s->low == nullptr) ? lb_emit_conv(p, hi, t_int) : lb_emit_arith(p, Token_Sub, hi, lo, t_int); + } + + // Single aggregate construction. + Type *result_type = type_of_expr(expr); + if (is_type_string(result_type)) { + return lb_make_string_value(p, result_type, cur_ptr, cur_len); + } + return lb_make_slice_value(p, result_type, cur_ptr, cur_len); + } + } + } + + lbValue base = lb_build_expr(p, se->expr); + Type *type = base_type(base.type); + + if (is_type_pointer(type)) { + type = base_type(type_deref(type)); + base = lb_emit_load(p, base); + } + + lbValue low = lb_const_int(p->module, t_int, 0); + lbValue high = {}; + + if (se->low != nullptr) { + low = lb_correct_endianness(p, lb_build_expr(p, se->low)); + } + if (se->high != nullptr) { + high = lb_correct_endianness(p, lb_build_expr(p, se->high)); + } + + bool no_indices = se->low == nullptr && se->high == nullptr; + + switch (type->kind) { + case Type_Slice: { + Type *slice_type = type; + lbValue len = lb_slice_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_slice_elem(p, base), low); + lbValue new_len = (se->low == nullptr) + ? lb_emit_conv(p, high, t_int) + : lb_emit_arith(p, Token_Sub, high, low, t_int); + + return lb_make_slice_value(p, slice_type, elem, new_len); + } + + case Type_DynamicArray: { + Type *elem_type = type->DynamicArray.elem; + Type *slice_type = alloc_type_slice(elem_type); + + lbValue len = lb_dynamic_array_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low); + lbValue new_len = (se->low == nullptr) + ? lb_emit_conv(p, high, t_int) + : lb_emit_arith(p, Token_Sub, high, low, t_int); + + return lb_make_slice_value(p, slice_type, elem, new_len); + } + + case Type_Basic: { + if (is_type_string16(type)) { + GB_ASSERT_MSG(are_types_identical(type, t_string16), "got %s", type_to_string(type)); + lbValue len = lb_string_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low); + lbValue new_len = (se->low == nullptr) + ? lb_emit_conv(p, high, t_int) + : lb_emit_arith(p, Token_Sub, high, low, t_int); + + return lb_make_string_value(p, t_string16, elem, new_len); + } + GB_ASSERT_MSG(are_types_identical(type, t_string), "got %s", type_to_string(type)); + lbValue len = lb_string_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low); + lbValue new_len = (se->low == nullptr) + ? lb_emit_conv(p, high, t_int) + : lb_emit_arith(p, Token_Sub, high, low, t_int); + + return lb_make_string_value(p, t_string, elem, new_len); + } + + case Type_MultiPointer: { + GB_ASSERT(se->high != nullptr); + Type *elem_type = type->MultiPointer.elem; + Type *slice_type = alloc_type_slice(elem_type); + + low = lb_emit_conv(p, low, t_int); + high = lb_emit_conv(p, high, t_int); + + lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high); + + LLVMValueRef indices[1] = {low.value}; + lbValue ptr = {}; + ptr.value = LLVMBuildGEP2(p->builder, lb_type(p->module, elem_type), base.value, indices, 1, ""); + ptr.type = alloc_type_pointer(elem_type); + + lbValue new_len = (se->low == nullptr) + ? lb_emit_conv(p, high, t_int) + : lb_emit_arith(p, Token_Sub, high, low, t_int); + + return lb_make_slice_value(p, slice_type, ptr, new_len); + } + + default: + GB_PANIC("lb_build_slice_expr_value: unexpected type %s", type_to_string(base.type)); + return {}; + } +} + gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { ast_node(se, SliceExpr, expr); @@ -4431,7 +5615,48 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { return slice; } + case Type_FixedCapacityDynamicArray: { + Type *elem_type = type->FixedCapacityDynamicArray.elem; + Type *slice_type = alloc_type_slice(elem_type); + + lbValue len = lb_fixed_capacity_dynamic_array_len(p, base); + if (high.value == nullptr) high = len; + + bool low_const = type_and_value_of_expr(se->low).mode == Addressing_Constant; + bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant; + + if (!low_const || !high_const) { + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + } + lbValue data_ptr = lb_addr_get_ptr(p, addr); + lbValue array_ptr = lb_emit_struct_ep(p, data_ptr, 0); + lbValue elem = lb_emit_ptr_offset(p, lb_array_elem(p, array_ptr), low); + lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + lbAddr slice = lb_add_local_generated(p, slice_type, false); + lb_fill_slice(p, slice, elem, new_len); + return slice; + } + case Type_Basic: { + if (is_type_string16(type)) { + GB_ASSERT_MSG(are_types_identical(type, t_string16), "got %s", type_to_string(type)); + lbValue len = lb_string_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low); + lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + lbAddr str = lb_add_local_generated(p, t_string16, false); + lb_fill_string(p, str, elem, new_len); + return str; + } GB_ASSERT_MSG(are_types_identical(type, t_string), "got %s", type_to_string(type)); lbValue len = lb_string_len(p, base); if (high.value == nullptr) high = len; @@ -4518,6 +5743,157 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { return {}; } +gb_internal void lb_build_struct_compound_lit_field_assignment(lbProcedure *p, lbValue comp_lit_ptr, Entity *field_entity, isize index, lbValue field_expr, bool is_raw_union) { + Type *ft = field_entity->type; + + lbValue gep = {}; + if (is_raw_union) { + gep = lb_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft)); + } else { + gep = lb_emit_struct_ep(p, comp_lit_ptr, cast(i32)index); + } + + Type *fet = field_expr.type; + GB_ASSERT(fet->kind != Type_Tuple); + + if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) { + if (union_is_variant_of(ft, fet)) { + // NOTE(bill, 2026-03-15): If it's a direct assignment for a variant to the + // direct union we can just assign it directly to minimize wasted code generation + // + // TODO(bill): Allow this for deeply nested unions too e.g. union{union{T}} + GB_ASSERT_MSG(union_variant_index_checked(ft, fet) >= 0, "%s", type_to_string(fet)); + GB_ASSERT(are_types_identical(type_deref(gep.type), ft)); + + lb_emit_store_union_variant(p, gep, field_expr, fet); + } else { + lbValue fv = lb_emit_conv(p, field_expr, ft); + lb_emit_store(p, gep, fv); + } + } else { + lbValue fv = lb_emit_conv(p, field_expr, ft); + lb_emit_store(p, gep, fv); + } +} + +gb_internal void lb_build_addr_struct_compound_lit_populate(lbProcedure *p, Ast *expr, Type *type, lbAddr v) { + ast_node(cl, CompoundLit, expr); + + // TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment. + // NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Struct); + GB_ASSERT(bt->Struct.soa_kind == StructSoa_None); + TypeStruct *st = &bt->Struct; + + if (cl->elems.count == 0) { + return; + } + + bool is_raw_union = st->is_raw_union; + + lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr))); + lbValue comp_lit_ptr = lb_addr_get_ptr(p, v); + + if (cl->elems[0]->kind == Ast_FieldValue) { + for (Ast *elem : cl->elems) { + lbValue field_expr = {}; + Entity *field = nullptr; + + ast_node(fv, FieldValue, elem); + InternedString interned = fv->field->Ident.interned; + Selection sel = lookup_field(bt, interned, false); + GB_ASSERT(!sel.indirect); + + elem = fv->value; + if (sel.index.count > 1) { + if (lb_is_nested_possibly_constant(type, sel, elem)) { + continue; + } + field_expr = lb_build_expr(p, elem); + field_expr = lb_emit_conv(p, field_expr, sel.entity->type); + if (sel.is_bit_field) { + Selection sub_sel = trim_selection(sel); + lbValue trimmed_dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sub_sel); + Type *bf = base_type(type_deref(trimmed_dst.type)); + if (is_type_pointer(bf)) { + trimmed_dst = lb_emit_load(p, trimmed_dst); + bf = base_type(type_deref(trimmed_dst.type)); + } + GB_ASSERT(bf->kind == Type_BitField); + + isize idx = sel.index[sel.index.count-1]; + lbAddr dst = lb_addr_bit_field(trimmed_dst, bf->BitField.fields[idx]->type, bf->BitField.bit_offsets[idx], bf->BitField.bit_sizes[idx]); + lb_addr_store(p, dst, field_expr); + + } else { + lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel); + lb_emit_store(p, dst, field_expr); + } + continue; + } + + isize index = sel.index[0]; + + field = st->fields[index]; + Type *ft = field->type; + if (!is_raw_union && !is_type_typeid(ft) && lb_is_elem_const(elem, ft)) { + continue; + } + + field_expr = lb_build_expr(p, elem); + + lb_build_struct_compound_lit_field_assignment(p, comp_lit_ptr, field, index, field_expr, is_raw_union); + } + + return; + } + + GB_ASSERT(!is_raw_union); + + isize field_index = 0; + + for (Ast *elem : cl->elems) { + if (is_type_tuple(elem->tav.type)) { + lbValue tuple_field_expr = lb_build_expr(p, elem); + GB_ASSERT(is_type_tuple(tuple_field_expr.type)); + + TypeTuple *tt = &tuple_field_expr.type->Tuple; + for_array(jj, tt->variables) { + isize index = field_index++; + GB_ASSERT(st->fields[index]->Variable.field_index == index); + Selection sel = lookup_field_from_index(bt, index); + GB_ASSERT(sel.index.count == 1); + GB_ASSERT(!sel.indirect); + index = sel.index[0]; + + Entity *field = st->fields[index]; + lbValue field_expr = lb_emit_struct_ev(p, tuple_field_expr, cast(i32)jj); + + lb_build_struct_compound_lit_field_assignment(p, comp_lit_ptr, field, index, field_expr, is_raw_union); + } + continue; + } + + isize index = field_index++; + GB_ASSERT(st->fields[index]->Variable.field_index == index); + Selection sel = lookup_field_from_index(bt, index); + GB_ASSERT(sel.index.count == 1); + GB_ASSERT(!sel.indirect); + index = sel.index[0]; + + Entity *field = st->fields[index]; + Type *ft = field->type; + if (!is_type_typeid(ft) && lb_is_elem_const(elem, ft)) { + continue; + } + + lbValue field_expr = lb_build_expr(p, elem); + + lb_build_struct_compound_lit_field_assignment(p, comp_lit_ptr, field, index, field_expr, is_raw_union); + } +} + gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { ast_node(cl, CompoundLit, expr); @@ -4530,12 +5906,13 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { Type *et = nullptr; switch (bt->kind) { - case Type_Array: et = bt->Array.elem; break; - case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break; - case Type_Slice: et = bt->Slice.elem; break; - case Type_BitSet: et = bt->BitSet.elem; break; - case Type_SimdVector: et = bt->SimdVector.elem; break; - case Type_Matrix: et = bt->Matrix.elem; break; + case Type_Array: et = bt->Array.elem; break; + case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break; + case Type_Slice: et = bt->Slice.elem; break; + case Type_BitSet: et = bt->BitSet.elem; break; + case Type_SimdVector: et = bt->SimdVector.elem; break; + case Type_Matrix: et = bt->Matrix.elem; break; + case Type_FixedCapacityDynamicArray: et = bt->FixedCapacityDynamicArray.elem; break; } String proc_name = {}; @@ -4562,8 +5939,8 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { for (Ast *elem : cl->elems) { ast_node(fv, FieldValue, elem); - String name = fv->field->Ident.token.string; - Selection sel = lookup_field(bt, name, false); + InternedString interned = fv->field->Ident.interned; + Selection sel = lookup_field(bt, interned, false); GB_ASSERT(sel.is_bit_field); GB_ASSERT(!sel.indirect); GB_ASSERT(sel.index.count == 1); @@ -4629,13 +6006,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { for (isize i = 0; i < fields.count; i++) { auto const &f = fields[i]; - LLVMValueRef mask = LLVMConstInt(lit, 1, false); - #if LLVM_VERSION_MAJOR >= 19 - mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(lit, f.bit_size, false), ""); - #else - mask = LLVMConstShl(mask, LLVMConstInt(lit, f.bit_size, false)); - #endif - mask = LLVMConstSub(mask, LLVMConstInt(lit, 1, false)); + LLVMValueRef mask = lb_const_low_bits_mask(lit, f.bit_size); LLVMValueRef elem = values[i].value; if (lb_sizeof(lit) < lb_sizeof(LLVMTypeOf(elem))) { @@ -4681,13 +6052,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { GB_ASSERT(mask_width > 0); bits_to_set -= mask_width; - LLVMValueRef mask = LLVMConstInt(vt, 1, false); - #if LLVM_VERSION_MAJOR >= 19 - mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(vt, mask_width, false), ""); - #else - mask = LLVMConstShl(mask, LLVMConstInt(vt, mask_width, false)); - #endif - mask = LLVMConstSub(mask, LLVMConstInt(vt, 1, false)); + LLVMValueRef mask = lb_const_low_bits_mask(vt, mask_width); LLVMValueRef to_set = LLVMBuildAnd(p->builder, val, mask, ""); @@ -4749,102 +6114,15 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { return v; } - case Type_Struct: { - // TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment. - // NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR - bool is_raw_union = is_type_raw_union(bt); - GB_ASSERT(is_type_struct(bt) || is_raw_union); - TypeStruct *st = &bt->Struct; - if (cl->elems.count > 0) { - lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr))); - lbValue comp_lit_ptr = lb_addr_get_ptr(p, v); - - for_array(field_index, cl->elems) { - Ast *elem = cl->elems[field_index]; - - lbValue field_expr = {}; - Entity *field = nullptr; - isize index = field_index; - - if (elem->kind == Ast_FieldValue) { - ast_node(fv, FieldValue, elem); - String name = fv->field->Ident.token.string; - Selection sel = lookup_field(bt, name, false); - GB_ASSERT(!sel.indirect); - - elem = fv->value; - if (sel.index.count > 1) { - if (lb_is_nested_possibly_constant(type, sel, elem)) { - continue; - } - field_expr = lb_build_expr(p, elem); - field_expr = lb_emit_conv(p, field_expr, sel.entity->type); - if (sel.is_bit_field) { - Selection sub_sel = trim_selection(sel); - lbValue trimmed_dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sub_sel); - Type *bf = base_type(type_deref(trimmed_dst.type)); - if (is_type_pointer(bf)) { - trimmed_dst = lb_emit_load(p, trimmed_dst); - bf = base_type(type_deref(trimmed_dst.type)); - } - GB_ASSERT(bf->kind == Type_BitField); - - isize idx = sel.index[sel.index.count-1]; - lbAddr dst = lb_addr_bit_field(trimmed_dst, bf->BitField.fields[idx]->type, bf->BitField.bit_offsets[idx], bf->BitField.bit_sizes[idx]); - lb_addr_store(p, dst, field_expr); - - } else { - lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel); - lb_emit_store(p, dst, field_expr); - } - continue; - } - - index = sel.index[0]; - } else { - Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index); - GB_ASSERT(sel.index.count == 1); - GB_ASSERT(!sel.indirect); - index = sel.index[0]; - } - - field = st->fields[index]; - Type *ft = field->type; - if (!is_raw_union && !is_type_typeid(ft) && lb_is_elem_const(elem, ft)) { - continue; - } - - field_expr = lb_build_expr(p, elem); - - lbValue gep = {}; - if (is_raw_union) { - gep = lb_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft)); - } else { - gep = lb_emit_struct_ep(p, comp_lit_ptr, cast(i32)index); - } - - Type *fet = field_expr.type; - GB_ASSERT(fet->kind != Type_Tuple); - - // HACK TODO(bill): THIS IS A MASSIVE HACK!!!! - if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) { - GB_ASSERT_MSG(union_variant_index(ft, fet) >= 0, "%s", type_to_string(fet)); - - lb_emit_store_union_variant(p, gep, field_expr, fet); - } else { - lbValue fv = lb_emit_conv(p, field_expr, ft); - lb_emit_store(p, gep, fv); - } - } - } + case Type_Struct: + lb_build_addr_struct_compound_lit_populate(p, expr, type, v); break; - } case Type_Map: { if (cl->elems.count == 0) { break; } - GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals); + GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals || build_context.dynamic_literals); lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); gb_unused(err); @@ -4929,11 +6207,30 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { break; } + case Type_FixedCapacityDynamicArray: { + if (cl->elems.count > 0) { + lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr))); + + auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); + + lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type); + + lbValue dst_ptr = lb_addr_get_ptr(p, v); + for_array(i, temp_data) { + i32 index = cast(i32)(temp_data[i].elem_index); + temp_data[i].gep = lb_emit_array_epi(p, dst_ptr, index); + } + + lb_build_addr_compound_lit_assign_array(p, temp_data); + } + break; + } + case Type_DynamicArray: { if (cl->elems.count == 0) { break; } - GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals); + GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals || build_context.dynamic_literals); Type *et = bt->DynamicArray.elem; lbValue size = lb_const_int(p->module, t_int, type_size_of(et)); @@ -4995,12 +6292,12 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { if (elem->kind == Ast_FieldValue) { ast_node(fv, FieldValue, elem); - Selection sel = lookup_field(bt, fv->field->Ident.token.string, false); + Selection sel = lookup_field(bt, fv->field->Ident.interned, false); index = sel.index[0]; elem = fv->value; } else { TypeAndValue tav = type_and_value_of_expr(elem); - Selection sel = lookup_field(bt, field_names[field_index], false); + Selection sel = lookup_field(bt, string_interner_insert(field_names[field_index]), false); index = sel.index[0]; } @@ -5115,6 +6412,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { } + gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { switch (expr->kind) { case_ast_node(i, Implicit, expr); @@ -5142,7 +6440,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { case_ast_node(se, SelectorExpr, expr); Ast *sel_node = unparen_expr(se->selector); if (sel_node->kind == Ast_Ident) { - String selector = sel_node->Ident.token.string; + InternedString selector = sel_node->Ident.interned; TypeAndValue tav = type_and_value_of_expr(se->expr); if (tav.mode == Addressing_Invalid) { @@ -5162,7 +6460,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { GB_ASSERT(e->kind == Entity_Procedure); return lb_addr(lb_find_value_from_entity(p->module, e)); } - GB_PANIC("Unreachable %.*s", LIT(selector)); + GB_PANIC("Unreachable %s", selector.cstring()); } if (se->swizzle_count > 0) { @@ -5273,11 +6571,12 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { } else { item = lb_emit_ptr_offset(p, lb_emit_load(p, arr), index); } + + // make sure it's ^T and not [^]T + item.type = alloc_type_multi_pointer_to_pointer(item.type); if (sub_sel.index.count > 0) { item = lb_emit_deep_field_gep(p, item, sub_sel); } - // make sure it's ^T and not [^]T - item.type = alloc_type_multi_pointer_to_pointer(item.type); return lb_addr(item); } else if (addr.kind == lbAddr_Swizzle) { @@ -5316,11 +6615,11 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { if (is_type_union(t)) { Type *type = type_of_expr(expr); lbAddr v = lb_add_local_generated(p, type, false); - lb_addr_store(p, v, lb_emit_union_cast(p, lb_build_expr(p, ta->expr), type, pos)); + lb_addr_store(p, v, lb_emit_union_cast(p, e, type, pos)); return v; } else if (is_type_any(t)) { Type *type = type_of_expr(expr); - return lb_emit_any_cast_addr(p, lb_build_expr(p, ta->expr), type, pos); + return lb_emit_any_cast_addr(p, e, type, pos); } else { GB_PANIC("TODO(bill): type assertion %s", type_to_string(e.type)); } @@ -5449,7 +6748,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { case_ast_node(ac, AutoCast, expr); return lb_build_addr(p, ac->expr); case_end; - + case_ast_node(te, TernaryIfExpr, expr); LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; @@ -5486,12 +6785,12 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { return lb_addr(res); case_end; - + case_ast_node(oe, OrElseExpr, expr); lbValue ptr = lb_address_from_load_or_generate_local(p, lb_build_expr(p, expr)); return lb_addr(ptr); case_end; - + case_ast_node(oe, OrReturnExpr, expr); lbValue ptr = lb_address_from_load_or_generate_local(p, lb_build_expr(p, expr)); return lb_addr(ptr); @@ -5557,4 +6856,3 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { return {}; } - diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index cfd1bd456..5f00db5e0 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1,5 +1,6 @@ gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token); gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len); +gb_internal LLVMRelocMode get_reloc_mode(); gb_global Entity *lb_global_type_info_data_entity = {}; gb_global lbAddr lb_global_type_info_member_types = {}; @@ -15,7 +16,9 @@ gb_global isize lb_global_type_info_member_offsets_index = 0; gb_global isize lb_global_type_info_member_usings_index = 0; gb_global isize lb_global_type_info_member_tags_index = 0; -gb_internal void lb_init_module(lbModule *m, Checker *c) { +gb_internal WORKER_TASK_PROC(lb_init_module_worker_proc) { + lbModule *m = cast(lbModule *)data; + Checker *c = m->checker; m->info = &c->info; @@ -46,11 +49,29 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { } module_name = gb_string_appendc(module_name, "builtin"); } + if (m->polymorphic_module == m) { + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } + module_name = gb_string_appendc(module_name, "$parapoly"); + } m->module_name = module_name; m->ctx = LLVMContextCreate(); m->mod = LLVMModuleCreateWithNameInContext(m->module_name, m->ctx); // m->debug_builder = nullptr; + if (build_context.no_plt) { + LLVMAddModuleFlag(m->mod, + LLVMModuleFlagBehaviorWarning, + "RtLibUseGOT", 11, + LLVMValueAsMetadata(LLVMConstInt(LLVMInt32TypeInContext(m->ctx), 1, true))); + } + + LLVMAddModuleFlag(m->mod, + LLVMModuleFlagBehaviorWarning, + "PIC Level", 9, + LLVMValueAsMetadata(LLVMConstInt(LLVMInt32TypeInContext(m->ctx), get_reloc_mode(), true))); + if (build_context.ODIN_DEBUG) { enum {DEBUG_METADATA_VERSION = 3}; @@ -85,18 +106,23 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { string_map_init(&m->members); string_map_init(&m->procedures); string_map_init(&m->const_strings); + string16_map_init(&m->const_string16s); map_init(&m->function_type_map); string_map_init(&m->gen_procs); if (USE_SEPARATE_MODULES) { - array_init(&m->procedures_to_generate, a, 0, 1<<10); + mpsc_init(&m->procedures_to_generate, a); map_init(&m->procedure_values, 1<<11); + array_init(&m->generated_procedures, a, 0, 1<<10); } else { - array_init(&m->procedures_to_generate, a, 0, c->info.all_procedures.count); + mpsc_init(&m->procedures_to_generate, a); map_init(&m->procedure_values, c->info.all_procedures.count*2); + array_init(&m->generated_procedures, a, 0, c->info.all_procedures.count*2); } + + array_init(&m->global_procedures_to_create, a, 0, 1024); array_init(&m->global_types_to_create, a, 0, 1024); - array_init(&m->missing_procedures_to_check, a, 0, 16); + mpsc_init(&m->missing_procedures_to_check, a); map_init(&m->debug_values); string_map_init(&m->objc_classes); @@ -112,6 +138,15 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { m->const_dummy_builder = LLVMCreateBuilderInContext(m->ctx); + return 0; +} + +gb_internal void lb_init_module(lbModule *m, bool do_threading) { + if (do_threading) { + thread_pool_add_task(lb_init_module_worker_proc, m); + } else { + lb_init_module_worker_proc(m); + } } gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { @@ -124,6 +159,10 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { return false; } + isize thread_count = gb_max(build_context.thread_count, 1); + isize worker_count = thread_count-1; + bool do_threading = !!(LLVMIsMultithreaded() && USE_SEPARATE_MODULES && MULTITHREAD_OBJECT_GENERATION && worker_count > 0); + String init_fullpath = c->parser->init_fullpath; linker_data_init(gen, &c->info, init_fullpath); @@ -135,35 +174,102 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { map_init(&gen->modules, gen->info->packages.count*2); map_init(&gen->modules_through_ctx, gen->info->packages.count*2); - map_init(&gen->anonymous_proc_lits, 1024); if (USE_SEPARATE_MODULES) { - bool module_per_file = build_context.module_per_file && build_context.optimization_level <= 0; + bool module_per_file = build_context.module_per_file && (build_context.optimization_level <= 0 || build_context.lto_kind != LTO_None); for (auto const &entry : gen->info->packages) { AstPackage *pkg = entry.value; - auto m = gb_alloc_item(permanent_allocator(), lbModule); + auto m = permanent_alloc_item(); m->pkg = pkg; m->gen = gen; + m->checker = c; map_set(&gen->modules, cast(void *)pkg, m); - lb_init_module(m, c); - if (!module_per_file) { + lb_init_module(m, do_threading); + + if (LLVM_WEAK_MONOMORPHIZATION) { + auto pm = permanent_alloc_item(); + pm->pkg = pkg; + pm->gen = gen; + pm->checker = c; + m->polymorphic_module = pm; + pm->polymorphic_module = pm; + + map_set(&gen->modules, cast(void *)pm, pm); // point to itself just add it to the list + + lb_init_module(pm, do_threading); + } + + bool allow_for_per_file = pkg->kind == Package_Runtime || module_per_file; + + #if 0 + if (!allow_for_per_file) { + if (pkg->files.count >= 20) { + isize proc_count = 0; + for (Entity *e : gen->info->entities) { + if (e->kind != Entity_Procedure) { + continue; + } + if (e->Procedure.is_foreign) { + continue; + } + if (e->pkg == pkg) { + proc_count += 1; + } + } + + if (proc_count >= 300) { + allow_for_per_file = true; + } + } + } + #endif + + if (!allow_for_per_file) { continue; } // NOTE(bill): Probably per file is not a good idea, so leave this for later for (AstFile *file : pkg->files) { - auto m = gb_alloc_item(permanent_allocator(), lbModule); + auto m = permanent_alloc_item(); m->file = file; - m->pkg = pkg; - m->gen = gen; + m->pkg = pkg; + m->gen = gen; + m->checker = c; map_set(&gen->modules, cast(void *)file, m); - lb_init_module(m, c); + lb_init_module(m, do_threading); + + + if (LLVM_WEAK_MONOMORPHIZATION) { + auto pm = permanent_alloc_item(); + pm->file = file; + pm->pkg = pkg; + pm->gen = gen; + pm->checker = c; + m->polymorphic_module = pm; + pm->polymorphic_module = pm; + + map_set(&gen->modules, cast(void *)pm, pm); // point to itself just add it to the list + + lb_init_module(pm, do_threading); + } } } + + if (LLVM_WEAK_MONOMORPHIZATION) { + lbModule *m = permanent_alloc_item(); + gen->equal_module = m; + m->gen = gen; + m->checker = c; + map_set(&gen->modules, cast(void *)m, m); // point to itself just add it to the list + lb_init_module(m, do_threading); + } } gen->default_module.gen = gen; + gen->default_module.checker = c; map_set(&gen->modules, cast(void *)1, &gen->default_module); - lb_init_module(&gen->default_module, c); + lb_init_module(&gen->default_module, do_threading); + + thread_pool_wait(); for (auto const &entry : gen->modules) { lbModule *m = entry.value; @@ -175,6 +281,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { mpsc_init(&gen->objc_selectors, heap_allocator()); mpsc_init(&gen->objc_classes, heap_allocator()); mpsc_init(&gen->objc_ivars, heap_allocator()); + mpsc_init(&gen->raddebug_section_strings, heap_allocator()); return true; } @@ -401,13 +508,14 @@ gb_internal lbModule *lb_module_of_expr(lbGenerator *gen, Ast *expr) { return &gen->default_module; } -gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e) { - GB_ASSERT(e != nullptr); +gb_internal lbModule *lb_module_of_entity_internal(lbGenerator *gen, Entity *e, lbModule *curr_module) { lbModule **found = nullptr; - if (e->kind == Entity_Procedure && - e->decl_info && - e->decl_info->code_gen_module) { - return e->decl_info->code_gen_module; + + if (e->kind == Entity_Procedure && e->decl_info) { + lbModule *mod = e->decl_info->code_gen_module.load(std::memory_order_relaxed); + if (mod) { + return mod; + } } if (e->file) { found = map_get(&gen->modules, cast(void *)e->file); @@ -426,6 +534,22 @@ gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e) { return &gen->default_module; } + +gb_internal lbModule *lb_module_of_entity(lbGenerator *gen, Entity *e, lbModule *curr_module) { + GB_ASSERT(e != nullptr); + GB_ASSERT(curr_module != nullptr); + lbModule *m = lb_module_of_entity_internal(gen, e, curr_module); + + if (USE_SEPARATE_MODULES) { + if (e->kind == Entity_Procedure && e->Procedure.generated_from_polymorphic) { + if (m->polymorphic_module) { + return m->polymorphic_module; + } + } + } + return m; +} + gb_internal lbAddr lb_addr(lbValue addr) { lbAddr v = {lbAddr_Default, addr}; return v; @@ -545,8 +669,11 @@ gb_internal lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) { break; case lbAddr_Swizzle: + GB_PANIC("lbAddr_Swizzle should be handled elsewhere"); + break; + case lbAddr_SwizzleLarge: - // TOOD(bill): is this good enough logic? + GB_PANIC("lbAddr_SwizzleLarge should be handled elsewhere"); break; } @@ -564,10 +691,22 @@ gb_internal void lb_set_file_line_col(lbProcedure *p, Array arr, TokenP i32 line = pos.line; i32 col = pos.column; - if (build_context.obfuscate_source_code_locations) { + switch (build_context.source_code_location_info) { + case SourceCodeLocationInfo_Normal: + break; + case SourceCodeLocationInfo_Obfuscated: file = obfuscate_string(file, "F"); line = obfuscate_i32(line); col = obfuscate_i32(col); + break; + case SourceCodeLocationInfo_Filename: + file = last_path_element(file); + break; + case SourceCodeLocationInfo_None: + file = str_lit(""); + line = 0; + col = 0; + break; } arr[0] = lb_find_or_add_entity_string(p->module, file, false); @@ -575,11 +714,52 @@ gb_internal void lb_set_file_line_col(lbProcedure *p, Array arr, TokenP arr[2] = lb_const_int(p->module, t_i32, col); } -gb_internal void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index, lbValue len) { +gb_internal bool lb_bounds_check_disabled(lbProcedure *p) { if (build_context.no_bounds_check) { - return; + return true; } if ((p->state_flags & StateFlag_no_bounds_check) != 0) { + return true; + } + return false; +} + +gb_internal bool lb_bounds_check_short_circuit(lbProcedure *p, lbValue index, lbValue len) { + if (lb_bounds_check_disabled(p)) { + return true; + } + + if (LLVMIsConstant(index.value) && LLVMIsConstant(len.value)) { + i64 i = LLVMConstIntGetSExtValue(index.value); + i64 n = LLVMConstIntGetSExtValue(len.value); + if (0 <= i && i < n) { + return true; + } + } + + if (LLVMIsAInstruction(index.value)) { + LLVMOpcode op = LLVMGetInstructionOpcode(index.value); + if (op == LLVMURem) { + LLVMValueRef divisor = LLVMGetOperand(index.value, 1); + if (divisor == len.value) { + return true; + } + } else if (op == LLVMAnd) { + LLVMValueRef mask = LLVMGetOperand(index.value, 1); + if (LLVMIsConstant(mask) && LLVMIsConstant(len.value)) { + i64 m = LLVMConstIntGetSExtValue(mask); + i64 l = LLVMConstIntGetSExtValue(len.value); + if (l > 0 && (l & (l-1)) == 0 && m == l-1) { + return true; + } + } + } + } + return false; +} + +gb_internal void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index, lbValue len) { + if (lb_bounds_check_short_circuit(p, index, len)) { return; } @@ -597,10 +777,7 @@ gb_internal void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index } gb_internal void lb_emit_matrix_bounds_check(lbProcedure *p, Token token, lbValue row_index, lbValue column_index, lbValue row_count, lbValue column_count) { - if (build_context.no_bounds_check) { - return; - } - if ((p->state_flags & StateFlag_no_bounds_check) != 0) { + if (lb_bounds_check_disabled(p)) { return; } @@ -623,13 +800,19 @@ gb_internal void lb_emit_matrix_bounds_check(lbProcedure *p, Token token, lbValu gb_internal void lb_emit_multi_pointer_slice_bounds_check(lbProcedure *p, Token token, lbValue low, lbValue high) { - if (build_context.no_bounds_check) { + if (lb_bounds_check_disabled(p)) { return; } - if ((p->state_flags & StateFlag_no_bounds_check) != 0) { - return; + + if (LLVMIsConstant(low.value) && LLVMIsConstant(high.value)) { + i64 i = LLVMConstIntGetSExtValue(low.value); + i64 n = LLVMConstIntGetSExtValue(high.value); + if (i < n) { + return; + } } + low = lb_emit_conv(p, low, t_int); high = lb_emit_conv(p, high, t_int); @@ -642,12 +825,18 @@ gb_internal void lb_emit_multi_pointer_slice_bounds_check(lbProcedure *p, Token } gb_internal void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue low, lbValue high, lbValue len, bool lower_value_used) { - if (build_context.no_bounds_check) { + if (lb_bounds_check_disabled(p)) { return; } - if ((p->state_flags & StateFlag_no_bounds_check) != 0) { + if (!lower_value_used && lb_bounds_check_short_circuit(p, high, len)) { return; } + // if (lower_value_used && + // lb_bounds_check_short_circuit(p, low, high) && + // lb_bounds_check_short_circuit(p, low, len) && + // lb_bounds_check_short_circuit(p, high, len)) { + // return; + // } high = lb_emit_conv(p, high, t_int); @@ -775,6 +964,113 @@ gb_internal LLVMValueRef OdinLLVMBuildLoadAligned(lbProcedure *p, LLVMTypeRef ty return result; } +// gb_internal void OdinLLVMBuildUnalignedStore(lbProcedure *p, LLVMValueRef dst, LLVMValueRef src, Type *ptr_type) { +// Type *t = type_deref(ptr_type); + +// if (is_type_simd_vector(t)) { +// LLVMValueRef store = LLVMBuildStore(p->builder, src, dst); +// LLVMSetAlignment(store, 1); +// } else { +// lb_mem_copy_non_overlapping(p, {dst, ptr_type}, {src, ptr_type}, lb_const_int(p->module, t_int, type_size_of(t)), false); +// } + +// } +gb_internal LLVMValueRef OdinLLVMBuildUnalignedLoad(lbProcedure *p, LLVMValueRef src, Type *ptr_type) { + LLVMTypeRef type = lb_type(p->module, type_deref(ptr_type)); + + src = LLVMBuildPointerCast(p->builder, src, lb_type(p->module, ptr_type), ""); + LLVMValueRef load = LLVMBuildLoad2(p->builder, type, src, ""); + LLVMSetAlignment(load, 1); + return load; +} + +gb_internal void lb_copy_bits(lbProcedure *p, + LLVMValueRef dst, + LLVMValueRef src, + u64 buf_bytes, + u64 dst_bit, + u64 src_bit, + u64 size_bits +) { + if (size_bits == 0) { + return; + } + GB_ASSERT(size_bits <= 64); // this routine assembles the field in a single u64 + + auto ptr_offset = [](lbProcedure *p, LLVMValueRef ptr, u64 offset) -> LLVMValueRef { + LLVMValueRef indices[1] = {LLVMConstInt(lb_type(p->module, t_u64), offset, false)}; + ptr = LLVMBuildPointerCast(p->builder, ptr, lb_type(p->module, t_u8_ptr), ""); + return LLVMBuildGEP2(p->builder, lb_type(p->module, t_u8), ptr, indices, 1, ""); + }; + + LLVMTypeRef llvm_u8 = lb_type(p->module, t_u8); + LLVMTypeRef llvm_u64 = lb_type(p->module, t_u64); + + dst = LLVMBuildPointerCast(p->builder, dst, lb_type(p->module, t_u8_ptr), ""); + src = LLVMBuildPointerCast(p->builder, src, lb_type(p->module, t_u8_ptr), ""); + + u64 src_byte = src_bit >> 3; + u64 dst_byte = dst_bit >> 3; + u64 src_shift = src_bit & 7; + u64 dst_shift = dst_bit & 7; + + u64 src_need_bytes = (src_shift + size_bits + 7) >> 3; // 1..9, exact span of the field + u64 dst_need_bytes = (dst_shift + size_bits + 7) >> 3; // 1..9, exact span of the field + + // These spans are exactly the bytes the field occupies, so they are in bounds + // whenever the field is. (buf_bytes must bound the buffer each pointer refers to.) + GB_ASSERT(src_byte + src_need_bytes <= buf_bytes); + GB_ASSERT(dst_byte + dst_need_bytes <= buf_bytes); + + u64 mask = ~cast(u64)0; + if (size_bits < 64) { + mask = ((cast(u64)1) << size_bits) - 1; + } + + // Gather: read exactly src_need_bytes bytes, pack the field into the low size_bits of `bits` --- + LLVMValueRef bits = LLVMConstInt(llvm_u64, 0, false); + for (u64 i = 0; i < src_need_bytes; i++) { + LLVMValueRef byte = OdinLLVMBuildUnalignedLoad(p, ptr_offset(p, src, src_byte + i), t_u8_ptr); + byte = LLVMBuildZExt(p->builder, byte, llvm_u64, ""); + + // byte i sits at frame bit i*8; the field starts at frame bit src_shift + if (i*8 >= src_shift) { + u64 sh = i*8 - src_shift; // 0..63 (sh==64 only needs i==8, which requires src_shift>=1) + byte = LLVMBuildShl (p->builder, byte, LLVMConstInt(llvm_u64, sh, false), ""); + } else { + u64 sh = src_shift - i*8; // 1..7 + byte = LLVMBuildLShr(p->builder, byte, LLVMConstInt(llvm_u64, sh, false), ""); + } + bits = LLVMBuildOr(p->builder, bits, byte, ""); + } + bits = LLVMBuildAnd(p->builder, bits, LLVMConstInt(llvm_u64, mask, false), ""); + + // Scatter: write exactly dst_need_bytes bytes, each a masked read-modify-write --- + for (u64 i = 0; i < dst_need_bytes; i++) { + LLVMValueRef contrib = nullptr; + u64 byte_mask = 0; // which bits (0..7) of this byte belong to the field + + if (i*8 >= dst_shift) { + u64 sh = i*8 - dst_shift; + contrib = LLVMBuildLShr(p->builder, bits, LLVMConstInt(llvm_u64, sh, false), ""); + byte_mask = (mask >> sh) & 0xff; + } else { + u64 sh = dst_shift - i*8; // 1..7 + contrib = LLVMBuildShl(p->builder, bits, LLVMConstInt(llvm_u64, sh, false), ""); + byte_mask = (mask << sh) & 0xff; + } + contrib = LLVMBuildTrunc(p->builder, contrib, llvm_u8, ""); + contrib = LLVMBuildAnd(p->builder, contrib, LLVMConstInt(llvm_u8, byte_mask, false), ""); + + LLVMValueRef old = OdinLLVMBuildUnalignedLoad(p, ptr_offset(p, dst, dst_byte + i), t_u8_ptr); + old = LLVMBuildAnd(p->builder, old, LLVMConstInt(llvm_u8, (~byte_mask) & 0xff, false), ""); + + LLVMValueRef merged = LLVMBuildOr(p->builder, old, contrib, ""); + LLVMValueRef store = LLVMBuildStore(p->builder, merged, ptr_offset(p, dst, dst_byte + i)); + LLVMSetAlignment(store, 1); + } +} + gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { if (addr.addr.value == nullptr) { return; @@ -792,6 +1088,7 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { if (addr.kind == lbAddr_BitField) { lbValue dst = addr.addr; + lbValue src = {}; if (is_type_endian_big(addr.bitfield.type)) { i64 shift_amount = 8*type_size_of(value.type) - addr.bitfield.bit_size; lbValue shifted_value = value; @@ -799,33 +1096,17 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { shifted_value.value, LLVMConstInt(LLVMTypeOf(shifted_value.value), shift_amount, false), ""); - lbValue src = lb_address_from_load_or_generate_local(p, shifted_value); - - auto args = array_make(temporary_allocator(), 4); - args[0] = dst; - args[1] = src; - args[2] = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_offset); - args[3] = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_size); - lb_emit_runtime_call(p, "__write_bits", args); - } else if ((addr.bitfield.bit_offset % 8) == 0 && - (addr.bitfield.bit_size % 8) == 0) { - lbValue src = lb_address_from_load_or_generate_local(p, value); - - lbValue byte_offset = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_offset/8); - lbValue byte_size = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_size/8); - lbValue dst_offset = lb_emit_conv(p, dst, t_u8_ptr); - dst_offset = lb_emit_ptr_offset(p, dst_offset, byte_offset); - lb_mem_copy_non_overlapping(p, dst_offset, src, byte_size); + src = lb_address_from_load_or_generate_local(p, shifted_value); } else { - lbValue src = lb_address_from_load_or_generate_local(p, value); - - auto args = array_make(temporary_allocator(), 4); - args[0] = dst; - args[1] = src; - args[2] = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_offset); - args[3] = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_size); - lb_emit_runtime_call(p, "__write_bits", args); + src = lb_address_from_load_or_generate_local(p, value); } + + u64 buf_bytes = cast(u64)type_size_of(type_deref(dst.type)); + u64 dst_bit = cast(u64)addr.bitfield.bit_offset; + u64 src_bit = cast(u64)0; + u64 size_bits = cast(u64)addr.bitfield.bit_size; + + lb_copy_bits(p, dst.value, src.value, buf_bytes, dst_bit, src_bit, size_bits); return; } else if (addr.kind == lbAddr_Map) { lb_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); @@ -887,8 +1168,8 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { Type *t = base_type(type_deref(addr.addr.type)); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); lbValue len = lb_soa_struct_len(p, addr.addr); - if (addr.soa.index_expr != nullptr) { - lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), index, len); + if (addr.soa.index_expr != nullptr && (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) { + lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len); } } @@ -921,7 +1202,7 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { GB_ASSERT(value.value != nullptr); value = lb_emit_conv(p, value, lb_addr_type(addr)); - lbValue dst = lb_addr_get_ptr(p, addr); + lbValue dst = addr.addr; lbValue src = lb_address_from_load_or_generate_local(p, value); { lbValue src_ptrs[4] = {}; @@ -947,7 +1228,7 @@ gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { GB_ASSERT(value.value != nullptr); value = lb_emit_conv(p, value, lb_addr_type(addr)); - lbValue dst = lb_addr_get_ptr(p, addr); + lbValue dst = addr.addr; lbValue src = lb_address_from_load_or_generate_local(p, value); for_array(i, addr.swizzle_large.indices) { lbValue src_ptr = lb_emit_array_epi(p, src, i); @@ -1107,53 +1388,28 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { } } - i64 total_bitfield_bit_size = 8*type_size_of(lb_addr_type(addr)); i64 dst_byte_size = type_size_of(addr.bitfield.type); lbAddr dst = lb_add_local_generated(p, addr.bitfield.type, true); lbValue src = addr.addr; - lbValue bit_offset = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_offset); - lbValue bit_size = lb_const_int(p->module, t_uintptr, addr.bitfield.bit_size); - lbValue byte_offset = lb_const_int(p->module, t_uintptr, (addr.bitfield.bit_offset+7)/8); - lbValue byte_size = lb_const_int(p->module, t_uintptr, (addr.bitfield.bit_size+7)/8); - GB_ASSERT(type_size_of(addr.bitfield.type) >= ((addr.bitfield.bit_size+7)/8)); lbValue r = {}; - if (is_type_endian_big(addr.bitfield.type)) { - auto args = array_make(temporary_allocator(), 4); - args[0] = dst.addr; - args[1] = src; - args[2] = bit_offset; - args[3] = bit_size; - lb_emit_runtime_call(p, "__read_bits", args); + u64 buf_bytes = cast(u64)type_size_of(type_deref(src.type)); + u64 dst_bit = cast(u64)0; + u64 src_bit = cast(u64)addr.bitfield.bit_offset; + u64 size_bits = cast(u64)addr.bitfield.bit_size; + + lb_copy_bits(p, dst.addr.value, src.value, buf_bytes, dst_bit, src_bit, size_bits); + r = lb_addr_load(p, dst); + if (is_type_endian_big(addr.bitfield.type)) { LLVMValueRef shift_amount = LLVMConstInt( lb_type(p->module, lb_addr_type(dst)), 8*dst_byte_size - addr.bitfield.bit_size, false ); - r = lb_addr_load(p, dst); r.value = LLVMBuildShl(p->builder, r.value, shift_amount, ""); - } else if ((addr.bitfield.bit_offset % 8) == 0) { - do_mask = 8*dst_byte_size != addr.bitfield.bit_size; - - lbValue copy_size = byte_size; - lbValue src_offset = lb_emit_conv(p, src, t_u8_ptr); - src_offset = lb_emit_ptr_offset(p, src_offset, byte_offset); - if (addr.bitfield.bit_offset + 8*dst_byte_size <= total_bitfield_bit_size) { - copy_size = lb_const_int(p->module, t_uintptr, dst_byte_size); - } - lb_mem_copy_non_overlapping(p, dst.addr, src_offset, copy_size, false); - r = lb_addr_load(p, dst); - } else { - auto args = array_make(temporary_allocator(), 4); - args[0] = dst.addr; - args[1] = src; - args[2] = bit_offset; - args[3] = bit_size; - lb_emit_runtime_call(p, "__read_bits", args); - r = lb_addr_load(p, dst); } Type *t = addr.bitfield.type; @@ -1372,7 +1628,7 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { } gb_internal lbValue lb_const_union_tag(lbModule *m, Type *u, Type *v) { - return lb_const_value(m, union_tag_type(u), exact_value_i64(union_variant_index(u, v))); + return lb_const_value(m, union_tag_type(u), exact_value_i64(union_variant_index_checked(u, v))); } gb_internal lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) { @@ -1391,9 +1647,14 @@ gb_internal lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) { unsigned element_count = LLVMCountStructElementTypes(uvt); GB_ASSERT_MSG(element_count >= 2, "element_count=%u (%s) != (%s)", element_count, type_to_string(ut), LLVMPrintTypeToString(uvt)); + + LLVMValueRef ptr = u.value; + ptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(uvt, 0), ""); + lbValue tag_ptr = {}; - tag_ptr.value = LLVMBuildStructGEP2(p->builder, uvt, u.value, 1, ""); + tag_ptr.value = LLVMBuildStructGEP2(p->builder, uvt, ptr, 1, ""); tag_ptr.type = alloc_type_pointer(tag_type); + tag_ptr.value = LLVMBuildPointerCast(p->builder, tag_ptr.value, lb_type(p->module, tag_ptr.type), ""); return tag_ptr; } @@ -1412,13 +1673,17 @@ gb_internal void lb_emit_store_union_variant_tag(lbProcedure *p, lbValue parent, // No tag needed! } else { lbValue tag_ptr = lb_emit_union_tag_ptr(p, parent); - lb_emit_store(p, tag_ptr, lb_const_union_tag(p->module, t, variant_type)); + lbValue tag = lb_const_union_tag(p->module, t, variant_type); + lb_emit_store(p, tag_ptr, tag); } } gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbValue variant, Type *variant_type) { Type *pt = base_type(type_deref(parent.type)); GB_ASSERT(pt->kind == Type_Union); + + GB_ASSERT_MSG(union_is_variant_of(pt, variant_type), "%s %s", type_to_string(pt), type_to_string(variant_type)); + if (pt->Union.kind == UnionType_shared_nil) { GB_ASSERT(type_size_of(variant_type)); @@ -1588,13 +1853,13 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t "\n\tArgTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", LLVMPrintTypeToString(arg.type), j, ft->args.count, - LLVMGetTypeContext(arg.type), ft->ctx, LLVMGetGlobalContext()); + LLVMGetTypeContext(arg.type), ft->ctx); } GB_ASSERT_MSG(LLVMGetTypeContext(ft->ret.type) == ft->ctx, "\n\t%s" "\n\tRetTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", LLVMPrintTypeToString(ft->ret.type), - LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext()); + LLVMGetTypeContext(ft->ret.type), ft->ctx); } for (unsigned i = 0; i < param_count; i++) { if (params_by_ptr[i]) { @@ -1612,13 +1877,97 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t GB_ASSERT_MSG(LLVMGetTypeContext(new_abi_fn_type) == m->ctx, "\n\tFuncTypeCtx: %p\n\tCurrentCtx: %p\n\tGlobalCtx: %p", - LLVMGetTypeContext(new_abi_fn_type), m->ctx, LLVMGetGlobalContext()); + LLVMGetTypeContext(new_abi_fn_type), m->ctx); map_set(&m->func_raw_types, type, new_abi_fn_type); return new_abi_fn_type; - } + + +gb_internal LLVMTypeRef lb_type_internal_union_block_type(lbModule *m, Type *type) { + GB_ASSERT(type->kind == Type_Union); + + if (type->Union.variants.count <= 0) { + return nullptr; + } + if (type->Union.variants.count == 1) { + return lb_type(m, type->Union.variants[0]); + } + + i64 align = type_align_of(type); + + unsigned block_size = cast(unsigned)type->Union.variant_block_size; + if (block_size == 0) { + return lb_type_padding_filler(m, block_size, align); + } + + bool all_pointers = align == build_context.ptr_size; + for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) { + Type *t = type->Union.variants[i]; + if (!is_type_internally_pointer_like(t)) { + all_pointers = false; + } + } + if (all_pointers) { + return lb_type(m, t_rawptr); + } + + { + Type *pt = type->Union.variants[0]; + for (isize i = 1; i < type->Union.variants.count; i++) { + Type *t = type->Union.variants[i]; + if (!are_types_identical(pt, t)) { + goto end_check_for_all_the_same; + } + } + return lb_type(m, pt); + } end_check_for_all_the_same:; + + { + Type *first_different = nullptr; + for (isize i = 0; i < type->Union.variants.count; i++) { + Type *t = type->Union.variants[i]; + if (type_size_of(t) == 0) { + continue; + } + if (first_different == nullptr) { + first_different = t; + } else if (!are_types_identical(first_different, t)) { + goto end_rest_zero_except_one; + } + } + if (first_different != nullptr) { + return lb_type(m, first_different); + } + } end_rest_zero_except_one:; + + // { + // LLVMTypeRef first_different = nullptr; + // for (isize i = 0; i < type->Union.variants.count; i++) { + // Type *t = type->Union.variants[i]; + // if (type_size_of(t) == 0) { + // continue; + // } + // if (first_different == nullptr) { + // first_different = lb_type(m, base_type(t)); + // } else { + // LLVMTypeRef llvm_t = lb_type(m, base_type(t)); + // if (llvm_t != first_different) { + // goto end_rest_zero_except_one_llvm_like; + // } + // } + // } + // if (first_different != nullptr) { + // return first_different; + // } + // } end_rest_zero_except_one_llvm_like:; + + + return lb_type_padding_filler(m, block_size, align); +} + + gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMContextRef ctx = m->ctx; i64 size = type_size_of(type); // Check size @@ -1796,6 +2145,37 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } case Basic_cstring: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0); + + + case Basic_string16: + { + char const *name = "..string16"; + LLVMTypeRef type = LLVMGetTypeByName(m->mod, name); + if (type != nullptr) { + return type; + } + type = LLVMStructCreateNamed(ctx, name); + + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + GB_ASSERT(build_context.metrics.ptr_size == 4); + GB_ASSERT(build_context.metrics.int_size == 8); + LLVMTypeRef fields[3] = { + LLVMPointerType(lb_type(m, t_u16), 0), + lb_type(m, t_i32), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 3, false); + } else { + LLVMTypeRef fields[2] = { + LLVMPointerType(lb_type(m, t_u16), 0), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 2, false); + } + return type; + } + case Basic_cstring16: return LLVMPointerType(LLVMInt16TypeInContext(ctx), 0); + case Basic_any: { char const *name = "..any"; @@ -1991,6 +2371,26 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } break; + case Type_FixedCapacityDynamicArray: + { + unsigned field_count = 0; + + LLVMTypeRef fields[3] = {}; + m->internal_type_level += 1; + fields[field_count++] = llvm_array_type(lb_type(m, type->FixedCapacityDynamicArray.elem), type->FixedCapacityDynamicArray.capacity); + m->internal_type_level -= 1; + + gb_unused(type_size_of(type)); + if (type->FixedCapacityDynamicArray.padding_needed > 0) { + fields[field_count++] = lb_type_padding_filler(m, type->FixedCapacityDynamicArray.padding_needed, 1); // padding + } + + fields[field_count++] = lb_type(m, t_int); // len + + return LLVMStructTypeInContext(ctx, fields, field_count, false); + } + break; + case Type_Map: init_map_internal_debug_types(type); GB_ASSERT(t_raw_map != nullptr); @@ -2004,8 +2404,9 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { i64 full_type_align = type_align_of(type); GB_ASSERT(full_type_size % full_type_align == 0); - if (type->Struct.is_raw_union) { + bool requires_packing = type->Struct.is_packed; + if (type->Struct.is_raw_union) { lbStructFieldRemapping field_remapping = {}; slice_init(&field_remapping, permanent_allocator(), 1); @@ -2013,7 +2414,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { fields[0] = lb_type_padding_filler(m, full_type_size, full_type_align); field_remapping[0] = 0; - LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); + LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), requires_packing); map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); return struct_type; @@ -2033,7 +2434,6 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } i64 prev_offset = 0; - bool requires_packing = type->Struct.is_packed; for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) { Entity *field = type->Struct.fields[field_index]; i64 offset = type->Struct.offsets[field_index]; @@ -2099,28 +2499,14 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef fields[] = {lb_type(m, type->Union.variants[0])}; return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); } + bool is_packed = false; - unsigned block_size = cast(unsigned)type->Union.variant_block_size; - - auto fields = array_make(temporary_allocator(), 0, 3); + auto fields = array_make(temporary_allocator(), 0, 4); if (is_type_union_maybe_pointer(type)) { LLVMTypeRef variant = lb_type(m, type->Union.variants[0]); array_add(&fields, variant); - } else { - LLVMTypeRef block_type = nullptr; - - bool all_pointers = align == build_context.ptr_size; - for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) { - Type *t = type->Union.variants[i]; - if (!is_type_internally_pointer_like(t)) { - all_pointers = false; - } - } - if (all_pointers) { - block_type = lb_type(m, t_rawptr); - } else { - block_type = lb_type_padding_filler(m, block_size, align); - } + } else if (type->Union.variants.count == 1) { + LLVMTypeRef block_type = lb_type(m, type->Union.variants[0]); LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); array_add(&fields, block_type); @@ -2131,9 +2517,23 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef padding_type = lb_type_padding_filler(m, padding, align); array_add(&fields, padding_type); } + is_packed = true; + } else { + LLVMTypeRef block_type = lb_type_internal_union_block_type(m, type); + + LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); + array_add(&fields, block_type); + array_add(&fields, tag_type); + i64 used_size = lb_sizeof(block_type) + lb_sizeof(tag_type); + i64 padding = size - used_size; + if (padding > 0) { + LLVMTypeRef padding_type = lb_type_padding_filler(m, padding, align); + array_add(&fields, padding_type); + } + is_packed = true; } - return LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, false); + return LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, is_packed); } break; @@ -2202,7 +2602,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { field_count = 3; } LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count); - fields[0] = LLVMPointerType(lb_type(m, type->Pointer.elem), 0); + fields[0] = LLVMPointerType(lb_type(m, type->SoaPointer.elem), 0); if (bigger_int) { fields[1] = lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size); fields[2] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size); @@ -2214,6 +2614,14 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_BitField: return lb_type_internal(m, type->BitField.backing_type); + + case Type_Generic: + if (type->Generic.specialized) { + return lb_type_internal(m, type->Generic.specialized); + } else { + // For unspecialized generics, use a pointer type as a placeholder + return LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0); + } } GB_PANIC("Invalid type %s", type_to_string(type)); @@ -2236,6 +2644,13 @@ gb_internal LLVMTypeRef lb_type(lbModule *m, Type *type) { m->internal_type_level += 1; llvm_type = lb_type_internal(m, type); m->internal_type_level -= 1; + + // { + // i64 tsz = type_size_of(type); + // i64 lsz = lb_sizeof(llvm_type); + // GB_ASSERT_MSG(tsz == lsz, "%s %lld vs %lld %s", type_to_string(type), cast(long long)tsz, cast(long long)lsz, LLVMPrintTypeToString(llvm_type)); + // } + if (m->internal_type_level == 0) { map_set(&m->types, type, llvm_type); } @@ -2299,29 +2714,9 @@ gb_internal LLVMAttributeRef lb_create_enum_attribute_with_type(LLVMContextRef c unsigned kind = 0; String s = make_string_c(name); - #if ODIN_LLVM_MINIMUM_VERSION_12 - kind = LLVMGetEnumAttributeKindForName(name, s.len); - GB_ASSERT_MSG(kind != 0, "unknown attribute: %s", name); - return LLVMCreateTypeAttribute(ctx, kind, type); - #else - // NOTE(2021-02-25, bill); All this attributes require a type associated with them - // and the current LLVM C API does not expose this functionality yet. - // It is better to ignore the attributes for the time being - if (s == "byval") { - // return nullptr; - } else if (s == "byref") { - return nullptr; - } else if (s == "preallocated") { - return nullptr; - } else if (s == "sret") { - // return nullptr; - } - - - kind = LLVMGetEnumAttributeKindForName(name, s.len); - GB_ASSERT_MSG(kind != 0, "unknown attribute: %s", name); - return LLVMCreateEnumAttribute(ctx, kind, 0); - #endif + kind = LLVMGetEnumAttributeKindForName(name, s.len); + GB_ASSERT_MSG(kind != 0, "unknown attribute: %s", name); + return LLVMCreateTypeAttribute(ctx, kind, type); } gb_internal LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value) { @@ -2364,6 +2759,20 @@ gb_internal void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, cha lb_add_proc_attribute_at_index(p, index, name, 0); } +gb_internal void lb_add_proc_attribute_at_index_with_string(lbProcedure *p, isize index, String const &name, String const &value) { + LLVMAttributeRef attr = lb_create_string_attribute(p->module->ctx, name, value); + GB_ASSERT(attr != nullptr); + LLVMAddAttributeAtIndex(p->value, cast(unsigned)index, attr); +} + +gb_internal void lb_add_nocapture_proc_attribute_at_index(lbProcedure *p, isize index) { + #if LLVM_VERSION_MAJOR >= 21 + lb_add_proc_attribute_at_index_with_string(p, index, make_string_c("captures"), make_string_c("none")); + #else + lb_add_proc_attribute_at_index(p, index, "nocapture"); + #endif +} + gb_internal void lb_add_attribute_to_proc(lbModule *m, LLVMValueRef proc_value, char const *name, u64 value=0) { LLVMAddAttributeAtIndex(proc_value, LLVMAttributeIndex_FunctionIndex, lb_create_enum_attribute(m->ctx, name, value)); } @@ -2379,6 +2788,31 @@ gb_internal void lb_add_attribute_to_proc_with_string(lbModule *m, LLVMValueRef } +gb_internal bool lb_apply_thread_local_model(LLVMValueRef value, String model) { + if (model != "") { + LLVMSetThreadLocal(value, true); + + LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; + if (model == "default") { + mode = LLVMGeneralDynamicTLSModel; + } else if (model == "globaldynamic") { + mode = LLVMGeneralDynamicTLSModel; + } else if (model == "localdynamic") { + mode = LLVMLocalDynamicTLSModel; + } else if (model == "initialexec") { + mode = LLVMInitialExecTLSModel; + } else if (model == "localexec") { + mode = LLVMLocalExecTLSModel; + } else { + GB_PANIC("Unhandled thread local mode %.*s", LIT(model)); + } + LLVMSetThreadLocalMode(value, mode); + return true; + } + + return false; +} + gb_internal void lb_add_edge(lbBlock *from, lbBlock *to) { LLVMValueRef instr = LLVMGetLastInstruction(from->block); @@ -2390,7 +2824,7 @@ gb_internal void lb_add_edge(lbBlock *from, lbBlock *to) { gb_internal lbBlock *lb_create_block(lbProcedure *p, char const *name, bool append) { - lbBlock *b = gb_alloc_item(permanent_allocator(), lbBlock); + lbBlock *b = permanent_alloc_item(); b->block = LLVMCreateBasicBlockInContext(p->module->ctx, name); b->appended = false; if (append) { @@ -2517,10 +2951,13 @@ general_end:; } } - src_size = align_formula(src_size, src_align); - dst_size = align_formula(dst_size, dst_align); + // NOTE(laytan): even though this logic seems sound, the Address Sanitizer does not + // want you to load/store the space of a value that is there for alignment. +#if 0 + i64 aligned_src_size = align_formula(src_size, src_align); + i64 aligned_dst_size = align_formula(dst_size, dst_align); - if (LLVMIsALoadInst(val) && (src_size >= dst_size && src_align >= dst_align)) { + if (LLVMIsALoadInst(val) && (aligned_src_size >= aligned_dst_size && src_align >= dst_align)) { LLVMValueRef val_ptr = LLVMGetOperand(val, 0); val_ptr = LLVMBuildPointerCast(p->builder, val_ptr, LLVMPointerType(dst_type, 0), ""); LLVMValueRef loaded_val = OdinLLVMBuildLoad(p, dst_type, val_ptr); @@ -2528,8 +2965,60 @@ general_end:; // LLVMSetAlignment(loaded_val, gb_min(src_align, dst_align)); return loaded_val; + } +#endif + + if (src_size > dst_size) { + GB_ASSERT(p->decl_block != p->curr_block); + // NOTE(laytan): src is bigger than dst, need to memcpy the part of src we want. + + LLVMTypeRef llvm_src_type = LLVMPointerType(src_type, 0); + LLVMTypeRef llvm_dst_type = LLVMPointerType(dst_type, 0); + + LLVMValueRef val_ptr; + if (LLVMIsALoadInst(val)) { + val_ptr = LLVMGetOperand(val, 0); + } else if (LLVMIsAAllocaInst(val)) { + val_ptr = LLVMBuildPointerCast(p->builder, val, llvm_src_type, ""); + } else { + // NOTE(laytan): we need a pointer to memcpy from. + LLVMValueRef val_copy = llvm_alloca(p, src_type, src_align); + val_ptr = LLVMBuildPointerCast(p->builder, val_copy, llvm_src_type, ""); + LLVMBuildStore(p->builder, val, val_ptr); + } + + i64 max_align = gb_max(lb_alignof(src_type), lb_alignof(dst_type)); + max_align = gb_max(max_align, 16); + + LLVMValueRef ptr = llvm_alloca(p, dst_type, max_align); + LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, llvm_dst_type, ""); + + LLVMTypeRef types[3] = { + llvm_dst_type, + llvm_src_type, + lb_type(p->module, t_int) + }; + + LLVMValueRef args[4] = { + nptr, + val_ptr, + LLVMConstInt(LLVMIntTypeInContext(p->module->ctx, 8*cast(unsigned)build_context.int_size), dst_size, 0), + LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, 0), + }; + + lb_call_intrinsic( + p, + "llvm.memcpy.inline", + args, + gb_count_of(args), + types, + gb_count_of(types) + ); + + return OdinLLVMBuildLoad(p, dst_type, ptr); } else { GB_ASSERT(p->decl_block != p->curr_block); + GB_ASSERT(dst_size >= src_size); i64 max_align = gb_max(lb_alignof(src_type), lb_alignof(dst_type)); max_align = gb_max(max_align, 16); @@ -2582,6 +3071,57 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String co } } +gb_internal LLVMValueRef lb_find_or_add_entity_string16_ptr(lbModule *m, String16 const &str, bool custom_link_section) { + String16HashKey key = {}; + LLVMValueRef *found = nullptr; + + if (!custom_link_section) { + key = string_hash_string(str); + found = string16_map_get(&m->const_string16s, key); + } + if (found != nullptr) { + return *found; + } + + + + LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; + + LLVMValueRef data = nullptr; + { + LLVMTypeRef llvm_u16 = LLVMInt16TypeInContext(m->ctx); + + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, str.len+1); + + for (isize i = 0; i < str.len; i++) { + values[i] = LLVMConstInt(llvm_u16, str.text[i], false); + } + values[str.len] = LLVMConstInt(llvm_u16, 0, false); + + data = LLVMConstArray(llvm_u16, values, cast(unsigned)(str.len+1)); + } + + + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csbs$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + + LLVMTypeRef type = LLVMTypeOf(data); + LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); + LLVMSetInitializer(global_data, data); + lb_make_global_private_const(global_data); + LLVMSetAlignment(global_data, 2); + + LLVMValueRef ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); + if (!custom_link_section) { + string16_map_set(&m->const_string16s, key, ptr); + } + return ptr; +} + gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str, bool custom_link_section) { LLVMValueRef ptr = nullptr; if (str.len != 0) { @@ -2624,11 +3164,16 @@ gb_internal lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule * } else { ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); } + i64 align = MINIMUM_SLICE_ALIGNMENT; if (!is_type_u8_slice(slice_type)) { Type *bt = base_type(slice_type); Type *elem = bt->Slice.elem; i64 sz = type_size_of(elem); + align = gb_max(type_align_of(elem), align); GB_ASSERT(sz > 0); + GB_ASSERT(align > 0); + + LLVMSetAlignment(global_data, (u32)align); ptr = LLVMConstPointerCast(ptr, lb_type(m, alloc_type_pointer(elem))); data_len /= sz; } @@ -2642,6 +3187,65 @@ gb_internal lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule * return res; } +gb_internal lbValue lb_find_or_add_entity_string16_slice_with_type(lbModule *m, String16 const &str, Type *slice_type) { + GB_ASSERT(is_type_slice(slice_type)); + LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; + LLVMValueRef data = nullptr; + { + LLVMTypeRef llvm_u16 = LLVMInt16TypeInContext(m->ctx); + + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, str.len+1); + + for (isize i = 0; i < str.len; i++) { + values[i] = LLVMConstInt(llvm_u16, str.text[i], false); + } + values[str.len] = LLVMConstInt(llvm_u16, 0, false); + + data = LLVMConstArray(llvm_u16, values, cast(unsigned)(str.len+1)); + } + + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csba$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + + LLVMTypeRef type = LLVMTypeOf(data); + LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); + LLVMSetInitializer(global_data, data); + lb_make_global_private_const(global_data); + LLVMSetAlignment(global_data, 2); + + i64 data_len = str.len; + LLVMValueRef ptr = nullptr; + if (data_len != 0) { + ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); + } else { + ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + } + i64 align = MINIMUM_SLICE_ALIGNMENT; + if (!is_type_u16_slice(slice_type)) { + Type *bt = base_type(slice_type); + Type *elem = bt->Slice.elem; + i64 sz = type_size_of(elem); + align = gb_max(type_align_of(elem), align); + GB_ASSERT(sz > 0); + GB_ASSERT(align > 0); + + LLVMSetAlignment(global_data, (u32)align); + ptr = LLVMConstPointerCast(ptr, lb_type(m, alloc_type_pointer(elem))); + data_len /= sz; + } + + LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), data_len, true); + LLVMValueRef values[2] = {ptr, len}; + + lbValue res = {}; + res.value = llvm_const_named_struct(m, slice_type, values, 2); + res.type = slice_type; + return res; +} gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) { @@ -2675,7 +3279,7 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e return lb_find_procedure_value_from_entity(m, e); } if (USE_SEPARATE_MODULES) { - lbModule *other_module = lb_module_of_entity(m->gen, e); + lbModule *other_module = lb_module_of_entity(m->gen, e, m); if (other_module != m) { String name = lb_get_entity_name(other_module, e); @@ -2705,6 +3309,7 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) { lbGenerator *gen = m->gen; + GB_ASSERT(e != nullptr); GB_ASSERT(is_type_proc(e->type)); e = strip_entity_wrapping(e); GB_ASSERT(e != nullptr); @@ -2722,7 +3327,7 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) lbModule *other_module = m; if (USE_SEPARATE_MODULES) { - other_module = lb_module_of_entity(gen, e); + other_module = lb_module_of_entity(gen, e, m); } if (other_module == m) { debugf("Missing Procedure (lb_find_procedure_value_from_entity): %.*s module %p\n", LIT(e->token.string), m); @@ -2730,10 +3335,15 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) ignore_body = other_module != m; lbProcedure *missing_proc = lb_create_procedure(m, e, ignore_body); - if (ignore_body) { - mutex_lock(&gen->anonymous_proc_lits_mutex); - defer (mutex_unlock(&gen->anonymous_proc_lits_mutex)); + if (missing_proc == nullptr) { + // This is an unspecialized polymorphic procedure, which should not be codegen'd + lbValue dummy = {}; + dummy.value = nullptr; + dummy.type = nullptr; + return dummy; + } + if (ignore_body) { GB_ASSERT(other_module != nullptr); rw_mutex_shared_lock(&other_module->values_mutex); auto *found = map_get(&other_module->values, e); @@ -2741,10 +3351,10 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) if (found == nullptr) { // THIS IS THE RACE CONDITION lbProcedure *missing_proc_in_other_module = lb_create_procedure(other_module, e, false); - array_add(&other_module->missing_procedures_to_check, missing_proc_in_other_module); + mpsc_enqueue(&other_module->missing_procedures_to_check, missing_proc_in_other_module); } } else { - array_add(&m->missing_procedures_to_check, missing_proc); + mpsc_enqueue(&m->missing_procedures_to_check, missing_proc); } rw_mutex_shared_lock(&m->values_mutex); @@ -2762,18 +3372,16 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { lbGenerator *gen = m->gen; - - mutex_lock(&gen->anonymous_proc_lits_mutex); - defer (mutex_unlock(&gen->anonymous_proc_lits_mutex)); - - TokenPos pos = ast_token(expr).pos; - lbProcedure **found = map_get(&gen->anonymous_proc_lits, expr); - if (found) { - return lb_find_procedure_value_from_entity(m, (*found)->entity); - } + gb_unused(gen); ast_node(pl, ProcLit, expr); + if (pl->decl->entity.load() != nullptr) { + return lb_find_procedure_value_from_entity(m, pl->decl->entity.load()); + } + + TokenPos pos = ast_token(expr).pos; + // NOTE(bill): Generate a new name // parent$count isize name_len = prefix_name.len + 6 + 11; @@ -2791,30 +3399,51 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr token.string = name; Entity *e = alloc_entity_procedure(nullptr, token, type, pl->tags); e->file = expr->file(); + e->scope = e->file->scope; + + lbModule *target_module = m; + GB_ASSERT(target_module != nullptr); // NOTE(bill): this is to prevent a race condition since these procedure literals can be created anywhere at any time - pl->decl->code_gen_module = m; + pl->decl->code_gen_module = target_module; e->decl_info = pl->decl; - pl->decl->entity = e; e->parent_proc_decl = pl->decl->parent; e->Procedure.is_anonymous = true; e->flags |= EntityFlag_ProcBodyChecked; - lbProcedure *p = lb_create_procedure(m, e); - GB_ASSERT(e->code_gen_module == m); + pl->decl->entity.store(e); - lbValue value = {}; - value.value = p->value; - value.type = p->type; - map_set(&gen->anonymous_proc_lits, expr, p); - array_add(&m->procedures_to_generate, p); - if (parent != nullptr) { - array_add(&parent->children, p); + if (target_module != m) { + rw_mutex_shared_lock(&target_module->values_mutex); + lbValue *found = map_get(&target_module->values, e); + rw_mutex_shared_unlock(&target_module->values_mutex); + if (found == nullptr) { + lbProcedure *missing_proc_in_target_module = lb_create_procedure(target_module, e, false); + mpsc_enqueue(&target_module->missing_procedures_to_check, missing_proc_in_target_module); + } + + lbProcedure *p = lb_create_procedure(m, e, true); + + lbValue value = {}; + value.value = p->value; + value.type = p->type; + return value; } else { - string_map_set(&m->members, name, value); + lbProcedure *p = lb_create_procedure(m, e); + + lbValue value = {}; + value.value = p->value; + value.type = p->type; + + mpsc_enqueue(&m->procedures_to_generate, p); + if (parent != nullptr) { + array_add(&parent->children, p); + } else { + string_map_set(&m->members, name, value); + } + return value; } - return value; } @@ -2823,11 +3452,18 @@ gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lb GB_ASSERT(type != nullptr); type = default_type(type); + LLVMTypeRef actual_type = lb_type(m, type); + if (value.value != nullptr) { + LLVMTypeRef value_type = LLVMTypeOf(value.value); + GB_ASSERT_MSG(lb_sizeof(actual_type) == lb_sizeof(value_type), "%s vs %s", LLVMPrintTypeToString(actual_type), LLVMPrintTypeToString(value_type)); + actual_type = value_type; + } + Scope *scope = nullptr; Entity *e = alloc_entity_variable(scope, make_token_ident(name), type); lbValue g = {}; g.type = alloc_type_pointer(type); - g.value = LLVMAddGlobal(m->mod, lb_type(m, type), alloc_cstring(temporary_allocator(), name)); + g.value = LLVMAddGlobal(m->mod, actual_type, alloc_cstring(temporary_allocator(), name)); if (value.value != nullptr) { GB_ASSERT_MSG(LLVMIsConstant(value.value), LLVMPrintValueToString(value.value)); LLVMSetInitializer(g.value, value.value); @@ -2835,6 +3471,8 @@ gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lb LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, type))); } + g.value = LLVMConstPointerCast(g.value, lb_type(m, g.type)); + lb_add_entity(m, e, g); lb_add_member(m, name, g); @@ -2864,7 +3502,7 @@ gb_internal lbAddr lb_add_global_generated_from_procedure(lbProcedure *p, Type * gb_internal lbValue lb_find_runtime_value(lbModule *m, String const &name) { AstPackage *p = m->info->runtime_package; - Entity *e = scope_lookup_current(p->scope, name); + Entity *e = scope_lookup_current(p->scope, string_interner_insert(name)); return lb_find_value_from_entity(m, e); } gb_internal lbValue lb_find_package_value(lbModule *m, String const &pkg, String const &name) { @@ -2897,7 +3535,7 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { } if (USE_SEPARATE_MODULES) { - lbModule *other_module = lb_module_of_entity(m->gen, e); + lbModule *other_module = lb_module_of_entity(m->gen, e, m); bool is_external = other_module != m; if (!is_external) { @@ -2922,25 +3560,7 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { lb_set_entity_from_other_modules_linkage_correctly(other_module, e, name); - if (e->Variable.thread_local_model != "") { - LLVMSetThreadLocal(g.value, true); - - String m = e->Variable.thread_local_model; - LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; - if (m == "default") { - mode = LLVMGeneralDynamicTLSModel; - } else if (m == "localdynamic") { - mode = LLVMLocalDynamicTLSModel; - } else if (m == "initialexec") { - mode = LLVMInitialExecTLSModel; - } else if (m == "localexec") { - mode = LLVMLocalExecTLSModel; - } else { - GB_PANIC("Unhandled thread local mode %.*s", LIT(m)); - } - LLVMSetThreadLocalMode(g.value, mode); - } - + lb_apply_thread_local_model(g.value, e->Variable.thread_local_model); return g; } @@ -3089,7 +3709,30 @@ gb_internal lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e, bool zero } gb_internal lbAddr lb_add_local_generated(lbProcedure *p, Type *type, bool zero_init) { +#if 0 return lb_add_local(p, type, nullptr, zero_init); +#else + LLVMTypeRef llvm_type = lb_type(p->module, type); + + unsigned alignment = cast(unsigned)gb_max(type_align_of(type), lb_alignof(llvm_type)); + if (is_type_matrix(type)) { + alignment *= 2; // NOTE(bill): Just in case + } + + // This positions in the entry block, emits alloca, then restores position. + LLVMValueRef ptr = llvm_alloca(p, llvm_type, alignment, ""); + + if (zero_init) { + // Emit the zero-init store at the current position (not entry block) + // so it respects control flow. But the alloca itself is in entry. + lb_mem_zero_ptr(p, ptr, type, alignment); + } + + lbValue val = {}; + val.value = ptr; + val.type = alloc_type_pointer(type); + return lb_addr(val); +#endif } gb_internal lbAddr lb_add_local_generated_temp(lbProcedure *p, Type *type, i64 min_alignment) { @@ -3110,3 +3753,25 @@ gb_internal void lb_set_linkage_from_entity_flags(lbModule *m, LLVMValueRef valu LLVMSetLinkage(value, LLVMLinkOnceAnyLinkage); } } + +LLVMRelocMode get_reloc_mode() { + // NOTE(dweiler): Dynamic libraries require position-independent code. + LLVMRelocMode reloc_mode = LLVMRelocDefault; + if (build_context.build_mode == BuildMode_DynamicLibrary) { + reloc_mode = LLVMRelocPIC; + } + switch (build_context.reloc_mode) { + case RelocMode_Default: + break; + case RelocMode_Static: + reloc_mode = LLVMRelocStatic; + break; + case RelocMode_PIC: + reloc_mode = LLVMRelocPIC; + break; + case RelocMode_DynamicNoPIC: + reloc_mode = LLVMRelocDynamicNoPic; + break; + } + return reloc_mode; +} diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 8d5cfcb70..47ea90703 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -48,13 +48,6 @@ gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPas // return LLVMIsAAllocaInst(value) != nullptr; // } - -#if LLVM_VERSION_MAJOR < 12 -#define LLVM_ADD_CONSTANT_VALUE_PASS(fpm) LLVMAddConstantPropagationPass(fpm) -#else -#define LLVM_ADD_CONSTANT_VALUE_PASS(fpm) -#endif - gb_internal bool lb_opt_ignore(i32 optimization_level) { return optimization_level < 0; } @@ -70,7 +63,6 @@ gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, } else { LLVMAddPromoteMemoryToRegisterPass(fpm); LLVMAddMergedLoadStoreMotionPass(fpm); - LLVM_ADD_CONSTANT_VALUE_PASS(fpm); if (!build_context.ODIN_DEBUG) { LLVMAddEarlyCSEPass(fpm); } @@ -135,10 +127,8 @@ gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPas LLVMAddMemCpyOptPass(fpm); LLVMAddPromoteMemoryToRegisterPass(fpm); LLVMAddMergedLoadStoreMotionPass(fpm); - LLVM_ADD_CONSTANT_VALUE_PASS(fpm); LLVMAddEarlyCSEPass(fpm); - LLVM_ADD_CONSTANT_VALUE_PASS(fpm); LLVMAddMergedLoadStoreMotionPass(fpm); LLVMAddPromoteMemoryToRegisterPass(fpm); LLVMAddCFGSimplificationPass(fpm); @@ -183,7 +173,6 @@ gb_internal void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i3 LLVMAddBitTrackingDCEPass(mpm); LLVMAddJumpThreadingPass(mpm); - LLVM_ADD_CONSTANT_VALUE_PASS(mpm); LLVMAddLICMPass(mpm); LLVMAddLoopRerollPass(mpm); @@ -249,7 +238,6 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac if (optimization_level >= 2) { LLVMAddEarlyCSEPass(mpm); - LLVM_ADD_CONSTANT_VALUE_PASS(mpm); LLVMAddLICMPass(mpm); LLVMAddLoopUnswitchPass(mpm); LLVMAddCFGSimplificationPass(mpm); @@ -282,6 +270,55 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac optimization of Odin programs **************************************************************************/ +gb_internal void lb_run_fast_float_math_pass(lbProcedure *p) { + Entity *e = p->entity; + if (e == nullptr) { + return; + } + GB_ASSERT(e->kind == Entity_Procedure); + + + u64 fast_math_flags = e->Procedure.fast_math_flags; + LLVMFastMathFlags llvm_flags = 0; + if (fast_math_flags & OdinFastMath_Allow_Reassoc) llvm_flags |= LLVMFastMathAllowReassoc; + if (fast_math_flags & OdinFastMath_No_NaNs) llvm_flags |= LLVMFastMathNoNaNs; + if (fast_math_flags & OdinFastMath_No_Infs) llvm_flags |= LLVMFastMathNoInfs; + if (fast_math_flags & OdinFastMath_No_Signed_Zeros) llvm_flags |= LLVMFastMathNoSignedZeros; + if (fast_math_flags & OdinFastMath_Allow_Reciprocal) llvm_flags |= LLVMFastMathAllowReciprocal; + if (fast_math_flags & OdinFastMath_Allow_Contract) llvm_flags |= LLVMFastMathAllowContract; + if (fast_math_flags & OdinFastMath_Approx_Func) llvm_flags |= LLVMFastMathApproxFunc; + + if (llvm_flags == 0) { + return; + } + + for (LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(p->value); + block != nullptr; + block = LLVMGetNextBasicBlock(block)) { + for (LLVMValueRef instr = LLVMGetFirstInstruction(block); + instr != nullptr; + instr = LLVMGetNextInstruction(instr)) { + switch (LLVMGetInstructionOpcode(instr)) { + case LLVMFNeg: + case LLVMFAdd: + case LLVMFSub: + case LLVMFMul: + case LLVMFDiv: + case LLVMFRem: + case LLVMFPToUI: + case LLVMFPToSI: + case LLVMUIToFP: + case LLVMSIToFP: + case LLVMFPTrunc: + case LLVMFPExt: + case LLVMFCmp: + LLVMSetFastMathFlags(instr, llvm_flags); + break; + } + } + } +} + gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { unsigned debug_declare_id = LLVMLookupIntrinsicID("llvm.dbg.declare", 16); GB_ASSERT(debug_declare_id != 0); @@ -321,7 +358,15 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { // NOTE(bill): Explicit instructions are set here because some instructions could have side effects switch (LLVMGetInstructionOpcode(curr_instr)) { - // case LLVMAlloca: + case LLVMAlloca: + if (map_get(&p->tuple_fix_map, curr_instr) != nullptr) { + // NOTE(bill, 2025-12-27): Remove temporary tuple fix alloca instructions + // if they are never used + removal_count += 1; + LLVMInstructionEraseFromParent(curr_instr); + was_dead_instructions = true; + } + break; case LLVMLoad: if (LLVMGetVolatile(curr_instr)) { break; @@ -479,6 +524,9 @@ gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedur if (p == nullptr) { return; } + + lb_run_fast_float_math_pass(p); + // NOTE(bill): LLVMAddDCEPass doesn't seem to be exported in the official DLL's for LLVM // which means we cannot rely upon it // This is also useful for read the .ll for debug purposes because a lot of instructions @@ -516,8 +564,9 @@ gb_internal void llvm_delete_function(LLVMValueRef func) { LLVMDeleteFunction(func); } -gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef value) { - LLVMValueRef global = LLVMGetNamedGlobal(m->mod, "llvm.compiler.used"); +// Helper to append a value to an llvm metadata array global (llvm.used or llvm.compiler.used) +gb_internal void lb_append_to_llvm_used_list(lbModule *m, LLVMValueRef value, char const *list_name) { + LLVMValueRef global = LLVMGetNamedGlobal(m->mod, list_name); LLVMValueRef *constants; int operands = 1; @@ -547,33 +596,43 @@ gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef value) { constants[operands - 1] = LLVMConstBitCast(value, Int8PtrTy); LLVMValueRef initializer = LLVMConstArray(Int8PtrTy, constants, operands); - global = LLVMAddGlobal(m->mod, ATy, "llvm.compiler.used"); + global = LLVMAddGlobal(m->mod, ATy, list_name); LLVMSetLinkage(global, LLVMAppendingLinkage); LLVMSetSection(global, "llvm.metadata"); LLVMSetInitializer(global, initializer); } +gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef value) { + lb_append_to_llvm_used_list(m, value, "llvm.compiler.used"); +} + +// llvm.used survives LTO linker optimizations (unlike llvm.compiler.used) +gb_internal void lb_append_to_used(lbModule *m, LLVMValueRef value) { + lb_append_to_llvm_used_list(m, value, "llvm.used"); +} + gb_internal void lb_run_remove_unused_function_pass(lbModule *m) { isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; - // Custom remove dead function pass + + // Custom remove dead function pass (for internal linkage functions) for (; pass_count < max_pass_count; pass_count++) { - bool was_dead = false; + bool was_dead = false; for (LLVMValueRef func = LLVMGetFirstFunction(m->mod); func != nullptr; /**/ ) { LLVMValueRef curr_func = func; func = LLVMGetNextFunction(func); - + LLVMUseRef first_use = LLVMGetFirstUse(curr_func); if (first_use != nullptr) { continue; } String name = {}; name.text = cast(u8 *)LLVMGetValueName2(curr_func, cast(size_t *)&name.len); - + if (LLVMIsDeclaration(curr_func)) { // Ignore for the time being continue; @@ -582,7 +641,7 @@ gb_internal void lb_run_remove_unused_function_pass(lbModule *m) { if (linkage != LLVMInternalLinkage) { continue; } - + Entity **found = map_get(&m->procedure_values, curr_func); if (found && *found) { Entity *e = *found; @@ -592,7 +651,7 @@ gb_internal void lb_run_remove_unused_function_pass(lbModule *m) { continue; } } - + llvm_delete_function(curr_func); was_dead = true; removal_count += 1; diff --git a/src/llvm_backend_passes.cpp b/src/llvm_backend_passes.cpp index bea95ce8e..50d450c52 100644 --- a/src/llvm_backend_passes.cpp +++ b/src/llvm_backend_passes.cpp @@ -3,7 +3,18 @@ array_add(&passes, "function(annotation-remarks)"); break; case 0: - array_add(&passes, "always-inline"); + if (build_context.internal_llvm_no_sroa) { + // Old -o:minimal behavior + array_add(&passes, "always-inline"); + } else { + array_add(&passes, "annotation2metadata"); + array_add(&passes, "inferattrs"); + array_add(&passes, "forceattrs"); + array_add(&passes, "function(sroa,early-cse<>)"); + array_add(&passes, "always-inline"); + array_add(&passes, "function(sroa,instsimplify,simplifycfg)"); + // array_add(&passes, "verify"); + } array_add(&passes, "function(annotation-remarks)"); break; case 1: @@ -263,7 +274,7 @@ function( ), verify )"); -#else +#elif LLVM_VERSION_MAJOR < 22 // LLVM 20 & 21 (same config) array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -395,6 +406,144 @@ function( verify )"); +#else // LLVM 22 +// Passes removed: coro, openmp + array_add(&passes, u8R"( +memprof-remove-attributes, +annotation2metadata, +forceattrs, +inferattrs, +function( + ee-instrument<>, + lower-expect, + simplifycfg, + sroa, + early-cse<> +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function( + invalidate +), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + function( + sroa, + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + extra-simple-loop-unswitch-passes, + loop-deletion, + loop-unroll-full + ), + sroa, + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa( + licm + ), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + drop-unnecessary-assumes, + float2int, + lower-constant-intrinsics, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + drop-unnecessary-assumes, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + sroa, + infer-alignment, + instcombine, + loop-mssa( + licm + ), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +alloc-token, +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); + #endif break; // default @@ -656,7 +805,7 @@ function( ), verify )"); -#else +#elif LLVM_VERSION_MAJOR < 22 // LLVM 20 & 21 (same config) array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -789,6 +938,145 @@ function( ), verify )"); + +#else // LLVM 22 +// Passes removed: coro, openmp + array_add(&passes, u8R"( +memprof-remove-attributes, +annotation2metadata, +forceattrs, +inferattrs, +function( + ee-instrument<>, + lower-expect, + simplifycfg, + sroa, + early-cse<> +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function( + invalidate +), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + function( + sroa, + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + libcalls-shrinkwrap, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + extra-simple-loop-unswitch-passes, + loop-deletion, + loop-unroll-full + ), + sroa, + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa( + licm + ), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + drop-unnecessary-assumes, + float2int, + lower-constant-intrinsics, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + drop-unnecessary-assumes, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + sroa, + infer-alignment, + instcombine, + loop-mssa( + licm + ), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +alloc-token, +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); #endif break; @@ -1052,7 +1340,7 @@ function( ), verify )"); -#else +#elif LLVM_VERSION_MAJOR < 22 // LLVM 20 & 21 (same config) array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -1190,6 +1478,148 @@ verify )"); +#else // LLVM 22 +// Passes removed: coro, openmp + array_add(&passes, u8R"( +memprof-remove-attributes, +annotation2metadata, +forceattrs, +inferattrs, +function( + ee-instrument<>, + lower-expect, + simplifycfg, + sroa, + early-cse<>, + callsite-splitting +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function( + invalidate +), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + argpromotion, + function( + sroa, + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + libcalls-shrinkwrap, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + extra-simple-loop-unswitch-passes, + loop-deletion, + loop-unroll-full + ), + sroa, + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa( + licm + ), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + drop-unnecessary-assumes, + float2int, + lower-constant-intrinsics, + chr, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + drop-unnecessary-assumes, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + sroa, + infer-alignment, + instcombine, + loop-mssa( + licm + ), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +alloc-token, +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); + #endif break; - } \ No newline at end of file + } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 7ce1230d6..7994ab4ba 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2,6 +2,9 @@ gb_internal LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLV unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); GB_ASSERT_MSG(id != 0, "Unable to find %s", name); LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, type_count); + if (build_context.no_plt) { + lb_add_attribute_to_proc(p->module, ip, "nonlazybind"); + } LLVMTypeRef call_type = LLVMIntrinsicGetType(p->module->ctx, id, types, type_count); return LLVMBuildCall2(p->builder, call_type, ip, args, arg_count, ""); } @@ -12,9 +15,9 @@ gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue sr len = lb_emit_conv(p, len, t_int); char const *name = "llvm.memmove"; - if (LLVMIsConstant(len.value)) { + if (!p->is_startup && LLVMIsConstant(len.value)) { i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value); - if (const_len <= 4*build_context.int_size) { + if (const_len <= lb_max_zero_init_size()) { name = "llvm.memmove.inline"; } } @@ -41,9 +44,9 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu len = lb_emit_conv(p, len, t_int); char const *name = "llvm.memcpy"; - if (LLVMIsConstant(len.value)) { + if (!p->is_startup && LLVMIsConstant(len.value)) { i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value); - if (const_len <= 4*build_context.int_size) { + if (const_len <= lb_max_zero_init_size()) { name = "llvm.memcpy.inline"; } } @@ -67,6 +70,14 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) { GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); + // Skip codegen for unspecialized polymorphic procedures + if (is_type_polymorphic(entity->type) && !entity->Procedure.is_foreign) { + Type *bt = base_type(entity->type); + if (bt->kind == Type_Proc && bt->Proc.is_polymorphic && !bt->Proc.is_poly_specialized) { + // Do not generate code for unspecialized polymorphic procedures + return nullptr; + } + } if (!entity->Procedure.is_foreign) { if ((entity->flags & EntityFlag_ProcBodyChecked) == 0) { GB_PANIC("%.*s :: %s (was parapoly: %d %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true), is_type_polymorphic(entity->type, false)); @@ -76,7 +87,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i String link_name = {}; if (ignore_body) { - lbModule *other_module = lb_module_of_entity(m->gen, entity); + lbModule *other_module = lb_module_of_entity(m->gen, entity, m); link_name = lb_get_entity_name(other_module, entity); } else { link_name = lb_get_entity_name(m, entity); @@ -91,8 +102,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i } } - - lbProcedure *p = gb_alloc_item(permanent_allocator(), lbProcedure); + lbProcedure *p = permanent_alloc_item(); p->module = m; entity->code_gen_module = m; @@ -110,6 +120,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i p->type_expr = decl->type_expr; p->body = pl->body; p->inlining = pl->inlining; + p->tailing = pl->tailing; p->is_foreign = entity->Procedure.is_foreign; p->is_export = entity->Procedure.is_export; p->is_entry_point = false; @@ -145,6 +156,26 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i lb_ensure_abi_function_type(m, p); lb_add_function_type_attributes(p->value, p->abi_function_type, p->abi_function_type->calling_convention); + if (build_context.no_plt) { + lb_add_attribute_to_proc(m, p->value, "nonlazybind"); + } + + switch (build_context.stack_protector) { + case StackProtector_Ssp: + lb_add_attribute_to_proc(m, p->value, "ssp"); + break; + case StackProtector_SspReq: + lb_add_attribute_to_proc(m, p->value, "sspreq"); + break; + case StackProtector_SspStrong: + lb_add_attribute_to_proc(m, p->value, "sspstrong"); + break; + } + + if (build_context.disable_unwind) { + lb_add_attribute_to_proc(m, p->value, "nounwind"); + } + if (pt->Proc.diverging) { lb_add_attribute_to_proc(m, p->value, "noreturn"); } @@ -189,12 +220,15 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i for (;;) { String str = string_split_iterator(&it, ','); if (str == "") break; + bool add_prefix = !(string_starts_with(str, '+') || string_starts_with(str, '-')); if (!first) { feature_str = gb_string_appendc(feature_str, ","); } first = false; - feature_str = gb_string_appendc(feature_str, "+"); + if (add_prefix) { + feature_str = gb_string_appendc(feature_str, "+"); + } feature_str = gb_string_append_length(feature_str, str.text, str.len); } @@ -233,13 +267,14 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i } } } - lb_set_linkage_from_entity_flags(p->module, p->value, entity->flags); - if (p->is_foreign) { lb_set_wasm_procedure_import_attributes(p->value, entity, p->name); } + if (entity->Procedure.link_section.len > 0) { + LLVMSetSection(p->value, alloc_cstring(permanent_allocator(), entity->Procedure.link_section)); + } // NOTE(bill): offset==0 is the return value isize offset = 1; @@ -265,7 +300,7 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i } if (e->flags&EntityFlag_NoCapture) { if (is_type_internally_pointer_like(e->type)) { - lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture"); + lb_add_nocapture_proc_attribute_at_index(p, offset+parameter_index); } } parameter_index += 1; @@ -277,6 +312,20 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i LLVMSetLinkage(p->value, LLVMExternalLinkage); } + lb_set_linkage_from_entity_flags(p->module, p->value, entity->flags); + + // With LTO on all platforms, required procedures with external linkage need to be added to + // llvm.used to survive linker-level dead code elimination. This is necessary because + // LLVM may generate implicit calls to runtime builtins (e.g., __extendhfsf2 for f16 + // conversions) during instruction lowering, after the IR is finalized. + if (build_context.lto_kind != LTO_None) { + if (entity->flags & EntityFlag_Require) { + LLVMLinkage linkage = LLVMGetLinkage(p->value); + if (linkage != LLVMInternalLinkage) { + lb_append_to_used(m, p->value); + } + } + } if (m->debug_builder) { // Debug Information Type *bt = base_type(p->type); @@ -337,10 +386,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i if (build_context.sanitizer_flags & SanitizerFlag_Address && !entity->Procedure.no_sanitize_address) { lb_add_attribute_to_proc(m, p->value, "sanitize_address"); } - if (build_context.sanitizer_flags & SanitizerFlag_Memory) { + if (build_context.sanitizer_flags & SanitizerFlag_Memory && !entity->Procedure.no_sanitize_memory) { lb_add_attribute_to_proc(m, p->value, "sanitize_memory"); } - if (build_context.sanitizer_flags & SanitizerFlag_Thread) { + if (build_context.sanitizer_flags & SanitizerFlag_Thread && !entity->Procedure.no_sanitize_thread) { lb_add_attribute_to_proc(m, p->value, "sanitize_thread"); } } @@ -371,7 +420,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name GB_ASSERT_MSG(found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name)); } - lbProcedure *p = gb_alloc_item(permanent_allocator(), lbProcedure); + lbProcedure *p = permanent_alloc_item(); p->module = m; p->name = link_name; @@ -381,6 +430,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name p->body = nullptr; p->tags = 0; p->inlining = ProcInlining_none; + p->tailing = ProcTailing_none; p->is_foreign = false; p->is_export = false; p->is_entry_point = false; @@ -423,7 +473,7 @@ gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name if (pt->Proc.calling_convention == ProcCC_Odin) { lb_add_proc_attribute_at_index(p, offset+parameter_index, "noalias"); lb_add_proc_attribute_at_index(p, offset+parameter_index, "nonnull"); - lb_add_proc_attribute_at_index(p, offset+parameter_index, "nocapture"); + lb_add_nocapture_proc_attribute_at_index(p, offset+parameter_index); } return p; } @@ -538,6 +588,9 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { GB_ASSERT(p->type != nullptr); lb_ensure_abi_function_type(p->module, p); + if (p->type->Proc.calling_convention == ProcCC_Odin) { + lb_push_context_onto_stack_from_implicit_parameter(p); + } { lbFunctionType *ft = p->abi_function_type; @@ -594,6 +647,11 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { continue; } + if (e->flags & EntityFlag_CVarArg) { + GB_ASSERT(i+1 == params->variables.count); + continue; + } + lbArgType *arg_type = &ft->args[param_index]; defer (param_index += 1); @@ -661,7 +719,7 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { lbAddr res = {}; if (p->entity && p->entity->decl_info && - p->entity->decl_info->defer_use_checked && + p->entity->decl_info->defer_use_checked.load(std::memory_order_relaxed) && p->entity->decl_info->defer_used == 0) { // NOTE(bill): this is a bodge to get around the issue of the problem BELOW @@ -735,9 +793,6 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { } } - if (p->type->Proc.calling_convention == ProcCC_Odin) { - lb_push_context_onto_stack_from_implicit_parameter(p); - } lb_set_debug_position_to_procedure_begin(p); if (p->debug_info != nullptr) { @@ -790,9 +845,8 @@ gb_internal void lb_end_procedure_body(lbProcedure *p) { gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) { GB_ASSERT(pd->body != nullptr); lbModule *m = p->module; - auto *min_dep_set = &m->info->minimum_dependency_set; - if (ptr_set_exists(min_dep_set, e) == false) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { // NOTE(bill): Nothing depends upon it so doesn't need to be built return; } @@ -816,6 +870,10 @@ gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) e->Procedure.link_name = name; lbProcedure *nested_proc = lb_create_procedure(p->module, e); + if (nested_proc == nullptr) { + // This is an unspecialized polymorphic procedure, skip codegen + return; + } e->code_gen_procedure = nested_proc; lbValue value = {}; @@ -824,7 +882,7 @@ gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) lb_add_entity(m, e, value); array_add(&p->children, nested_proc); - array_add(&m->procedures_to_generate, nested_proc); + mpsc_enqueue(&m->procedures_to_generate, nested_proc); } @@ -846,7 +904,7 @@ gb_internal Array lb_value_to_array(lbProcedure *p, gbAllocator const & -gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, Array const &processed_args, Type *abi_rt, lbAddr context_ptr, ProcInlining inlining) { +gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, Array const &processed_args, Type *abi_rt, lbAddr context_ptr, ProcInlining inlining, ProcTailing tailing) { GB_ASSERT(p->module->ctx == LLVMGetTypeContext(LLVMTypeOf(value.value))); unsigned arg_count = cast(unsigned)processed_args.count; @@ -911,13 +969,14 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue arg_type != param_type) { LLVMTypeKind arg_kind = LLVMGetTypeKind(arg_type); LLVMTypeKind param_kind = LLVMGetTypeKind(param_type); - if (arg_kind == param_kind && - arg_kind == LLVMPointerTypeKind) { - // NOTE(bill): LLVM's newer `ptr` only type system seems to fail at times - // I don't know why... - args[i] = LLVMBuildPointerCast(p->builder, args[i], param_type, ""); - arg_type = param_type; - continue; + if (arg_kind == param_kind) { + if (arg_kind == LLVMPointerTypeKind) { + // NOTE(bill): LLVM's newer `ptr` only type system seems to fail at times + // I don't know why... + args[i] = LLVMBuildPointerCast(p->builder, args[i], param_type, ""); + arg_type = param_type; + continue; + } } } @@ -962,6 +1021,17 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue break; } + switch (tailing) { + case ProcTailing_none: + break; + case ProcTailing_must_tail: + LLVMSetTailCall(ret, true); + #if LLVM_VERSION_MAJOR > 17 + LLVMSetTailCallKind(ret, LLVMTailCallKindMustTail); + #endif + break; + } + lbValue res = {}; res.value = ret; res.type = abi_rt; @@ -972,7 +1042,8 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue gb_internal lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name) { AstPackage *pkg = m->info->runtime_package; - Entity *e = scope_lookup_current(pkg->scope, name); + Entity *e = scope_lookup_current(pkg->scope, string_interner_insert(name)); + GB_ASSERT_MSG(e != nullptr, "Runtime procedure not found: %s", name); return lb_find_procedure_value_from_entity(m, e); } @@ -987,15 +1058,14 @@ gb_internal lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) { lbValue res = {}; Type *t = val.type; if (is_type_complex(t)) { - res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, false)); lbValue real = lb_emit_struct_ev(p, val, 0); lbValue imag = lb_emit_struct_ev(p, val, 1); imag = lb_emit_unary_arith(p, Token_Sub, imag, imag.type); - lb_emit_store(p, lb_emit_struct_ep(p, res, 0), real); - lb_emit_store(p, lb_emit_struct_ep(p, res, 1), imag); + + lbValue fields[2] = {real, imag}; + return lb_build_struct_value(p, type, fields, gb_count_of(fields)); } else if (is_type_quaternion(t)) { // @QuaternionLayout - res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, false)); lbValue real = lb_emit_struct_ev(p, val, 3); lbValue imag = lb_emit_struct_ev(p, val, 0); lbValue jmag = lb_emit_struct_ev(p, val, 1); @@ -1003,10 +1073,9 @@ gb_internal lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) { imag = lb_emit_unary_arith(p, Token_Sub, imag, imag.type); jmag = lb_emit_unary_arith(p, Token_Sub, jmag, jmag.type); kmag = lb_emit_unary_arith(p, Token_Sub, kmag, kmag.type); - lb_emit_store(p, lb_emit_struct_ep(p, res, 3), real); - lb_emit_store(p, lb_emit_struct_ep(p, res, 0), imag); - lb_emit_store(p, lb_emit_struct_ep(p, res, 1), jmag); - lb_emit_store(p, lb_emit_struct_ep(p, res, 2), kmag); + + lbValue fields[4] = {imag, jmag, kmag, real}; + return lb_build_struct_value(p, type, fields, gb_count_of(fields)); } else if (is_type_array_like(t)) { res = lb_addr_get_ptr(p, lb_add_local_generated(p, type, true)); Type *elem_type = base_array_type(t); @@ -1034,7 +1103,7 @@ gb_internal lbValue lb_emit_conjugate(lbProcedure *p, lbValue val, Type *type) { return lb_emit_load(p, res); } -gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, ProcInlining inlining) { +gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, ProcInlining inlining, ProcTailing tailing, lbValue *sret_dst) { lbModule *m = p->module; Type *pt = base_type(value.type); @@ -1061,6 +1130,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c lbValue result = {}; + isize ignored_args = 0; auto processed_args = array_make(permanent_allocator(), 0, args.count); { @@ -1083,6 +1153,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c lbArgType *arg = &ft->args[param_index]; if (arg->kind == lbArg_Ignore) { param_index += 1; + ignored_args += 1; continue; } @@ -1154,11 +1225,16 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c } if (return_by_pointer) { - lbValue return_ptr = lb_add_local_generated(p, rt, true).addr; - lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining); + lbValue return_ptr = {}; + if (sret_dst != nullptr) { + return_ptr = *sret_dst; + } else { + return_ptr = lb_add_local_generated(p, rt, true).addr; + } + lb_emit_call_internal(p, value, return_ptr, processed_args, nullptr, context_ptr, inlining, tailing); result = lb_emit_load(p, return_ptr); } else if (rt != nullptr) { - result = lb_emit_call_internal(p, value, {}, processed_args, rt, context_ptr, inlining); + result = lb_emit_call_internal(p, value, {}, processed_args, rt, context_ptr, inlining, tailing); if (ft->ret.cast_type) { result.value = OdinLLVMBuildTransmute(p, result.value, ft->ret.cast_type); } @@ -1171,7 +1247,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c result = lb_emit_conv(p, result, rt); } } else { - lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining); + lb_emit_call_internal(p, value, {}, processed_args, nullptr, context_ptr, inlining, tailing); } if (original_rt != rt) { @@ -1191,7 +1267,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c auto tuple_fix_values = slice_make(permanent_allocator(), ret_count); auto tuple_geps = slice_make(permanent_allocator(), ret_count); - isize offset = ft->original_arg_count; + isize offset = ft->original_arg_count - ignored_args; for (isize j = 0; j < ret_count-1; j++) { lbValue ret_arg_ptr = processed_args[offset + j]; lbValue ret_arg = lb_emit_load(p, ret_arg_ptr); @@ -1199,15 +1275,6 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c } tuple_fix_values[ret_count-1] = result; - #if 0 - for (isize j = 0; j < ret_count; j++) { - tuple_geps[j] = lb_emit_struct_ep(p, result_ptr, cast(i32)j); - } - for (isize j = 0; j < ret_count; j++) { - lb_emit_store(p, tuple_geps[j], tuple_fix_values[j]); - } - #endif - result = lb_emit_load(p, result_ptr); lbTupleFix tf = {tuple_fix_values}; @@ -1269,13 +1336,55 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c } } - lb_add_defer_proc(p, p->scope_index, deferred, result_as_args); + lb_add_defer_proc(p, p->scope_index, deferred, result_as_args, e->token.pos); } } return result; } +gb_internal lbValue lb_expand_values(lbProcedure *p, lbValue val, Type *type) { + Type *t = base_type(val.type); + + if (!is_type_tuple(type)) { + if (t->kind == Type_Struct) { + GB_ASSERT(t->Struct.fields.count == 1); + return lb_emit_struct_ev(p, val, 0); + } else if (t->kind == Type_Array) { + GB_ASSERT(t->Array.count == 1); + return lb_emit_struct_ev(p, val, 0); + } else { + GB_PANIC("Unknown type of expand_values"); + } + + } + + GB_ASSERT(is_type_tuple(type)); + // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops + lbValue tuple = lb_addr_get_ptr(p, lb_add_local_generated(p, type, false)); + if (t->kind == Type_Struct) { + for_array(src_index, t->Struct.fields) { + Entity *field = t->Struct.fields[src_index]; + i32 field_index = field->Variable.field_index; + lbValue f = lb_emit_struct_ev(p, val, field_index); + lbValue ep = lb_emit_struct_ep(p, tuple, cast(i32)src_index); + lb_emit_store(p, ep, f); + } + } else if (is_type_array_like(t)) { + // TODO(bill): Clean-up this code + lbValue ap = lb_address_from_load_or_generate_local(p, val); + i32 n = cast(i32)get_array_type_count(t); + for (i32 i = 0; i < n; i++) { + lbValue f = lb_emit_load(p, lb_emit_array_epi(p, ap, i)); + lbValue ep = lb_emit_struct_ep(p, tuple, i); + lb_emit_store(p, ep, f); + } + } else { + GB_PANIC("Unknown type of expand_values"); + } + return lb_emit_load(p, tuple); +} + gb_internal LLVMValueRef llvm_splat_int(i64 count, LLVMTypeRef type, i64 value, bool is_signed=false) { LLVMValueRef v = LLVMConstInt(type, value, is_signed); LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); @@ -1285,6 +1394,105 @@ gb_internal LLVMValueRef llvm_splat_int(i64 count, LLVMTypeRef type, i64 value, return LLVMConstVector(values, cast(unsigned)count); } +gb_internal bool lb_llvm_simd_bulk_op_unary(lbProcedure *p, lbValue arg, LLVMValueRef *result_, char const *intrinsic_name, unsigned default_width, LLVMValueRef *extra_args=nullptr, unsigned extra_args_count=0) { + if (intrinsic_name == nullptr || default_width == 0) { + return false; + } + + auto do_call_intrinsic = [](lbProcedure *p, char const *intrinsic_name, LLVMValueRef val, LLVMValueRef *extra_args, unsigned extra_args_count) -> LLVMValueRef { + if (extra_args && extra_args_count > 0) { + LLVMValueRef *args = gb_alloc_array(temporary_allocator(), LLVMValueRef, extra_args_count+1); + args[0] = val; + gb_memcopy(args+1, extra_args, gb_size_of(extra_args[0]) * extra_args_count); + + return lb_call_intrinsic(p, intrinsic_name, args, extra_args_count+1, nullptr, 0); + } else { + LLVMValueRef args[1] = {val}; + return lb_call_intrinsic(p, intrinsic_name, args, gb_count_of(args), nullptr, 0); + } + }; + + TEMPORARY_ALLOCATOR_GUARD(); + + Type *vt = base_type(arg.type); + GB_ASSERT(is_type_simd_vector(vt)); + + LLVMValueRef val = arg.value; + unsigned count = cast(unsigned)vt->SimdVector.count; + Type *elem = base_type(vt->SimdVector.elem); + + if (count < default_width) { + LLVMValueRef *grow_indices = gb_alloc_array(temporary_allocator(), LLVMValueRef, default_width); + LLVMValueRef *shrink_indices = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + + for (unsigned i = 0; i < count; i++) { + ExactValue idx = is_type_float(elem) ? + exact_value_float(cast(f64)i) : + exact_value_u64(i); + shrink_indices[i] = lb_const_value(p->module, elem, idx).value; + grow_indices[i] = shrink_indices[i]; + } + for (unsigned i = count; i < default_width; i++) { + grow_indices[i] = shrink_indices[0]; + } + + LLVMValueRef grow_mask = LLVMConstVector(grow_indices, default_width); + LLVMValueRef shrink_mask = LLVMConstVector(shrink_indices, count); + + val = LLVMBuildShuffleVector(p->builder, val, val, grow_mask, ""); + + val = do_call_intrinsic(p, intrinsic_name, val, extra_args, extra_args_count); + val = LLVMBuildShuffleVector(p->builder, val, val, shrink_mask, ""); + *result_ = val; + return true; + } else if (count == default_width) { + val = do_call_intrinsic(p, intrinsic_name, val, extra_args, extra_args_count); + *result_ = val; + return true; + } else { + GB_ASSERT(count > default_width); + unsigned parts_count = count/default_width; + LLVMValueRef *parts = gb_alloc_array(temporary_allocator(), LLVMValueRef, parts_count); + for (unsigned i = 0; i < parts_count; i++) { + LLVMValueRef *indices = gb_alloc_array(temporary_allocator(), LLVMValueRef, default_width); + for (unsigned i = 0; i < default_width; i++) { + indices[i] = lb_const_value(p->module, t_u32, exact_value_u64(4*i+0)).value; + } + + parts[i] = LLVMBuildShuffleVector(p->builder, val, val, LLVMConstVector(indices, default_width), ""); + } + + for (unsigned i = 0; i < parts_count; i++) { + parts[i] = do_call_intrinsic(p, intrinsic_name, parts[i], extra_args, extra_args_count); + } + + LLVMValueRef *indices = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + for (unsigned j = 0; j < count; j++) { + indices[j] = lb_const_value(p->module, t_u32, exact_value_i64(j)).value; + } + + u64 sub_parts_remaining = parts_count; + + while (sub_parts_remaining > 1) { + for (unsigned i = 0; i < sub_parts_remaining; i += 2) { + unsigned indices_count = 2*cast(unsigned)(cast(u64)count/sub_parts_remaining); + + parts[i] = LLVMBuildShuffleVector(p->builder, parts[i], parts[i+1], LLVMConstVector(indices, indices_count), ""); + } + + for (u64 i = 2; i < sub_parts_remaining; i += 2) { + parts[i/2] = parts[i]; + } + + + sub_parts_remaining >>= 1; + } + + *result_ = parts[0]; + return true; + } +} + gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, BuiltinProcId builtin_id) { ast_node(ce, CallExpr, expr); @@ -1301,7 +1509,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn Type *elem = type->SimdVector.elem; i64 count = type->SimdVector.count; - LLVMValueRef *scalars = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + LLVMValueRef *scalars = temporary_alloc_array(count); for (i64 i = 0; i < count; i++) { scalars[i] = lb_const_value(m, elem, exact_value_i64(i)).value; } @@ -1309,6 +1517,55 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn res.value = LLVMConstVector(scalars, cast(unsigned)count); return res; } + + case BuiltinProc_simd_interleave: + { + int n = cast(int)ce->args.count; + + if (n == 1) { + lbValue arg = lb_build_expr(p, ce->args[0]); + res.value = arg.value; + return res; + } + + Type *vector_type = type_of_expr(ce->args[0]); + + LLVMValueRef *args = temporary_alloc_array(n); + for (int i = 0; i < n; i++) { + lbValue arg = lb_build_expr(p, ce->args[i]); + arg = lb_emit_conv(p, arg, vector_type); + args[i] = arg.value; + } + + gbString name = gb_string_make(heap_allocator(), ""); + name = gb_string_append_fmt(name, "llvm.vector.interleave%d", n); + defer (gb_string_free(name)); + + LLVMTypeRef types[1] = {lb_type(m, tv.type)}; + res.value = lb_call_intrinsic(p, name, args, n, types, gb_count_of(types)); + return res; + } + + case BuiltinProc_simd_deinterleave: + { + lbValue arg0 = lb_build_expr(p, ce->args[0]); + LLVMTypeRef types[1] = {lb_type(m, arg0.type)}; + + GB_ASSERT(ce->args[1]->tav.value.kind == ExactValue_Integer); + int n = cast(int)exact_value_to_i64(ce->args[1]->tav.value); + + if (n == 1) { + res.value = arg0.value; + return res; + } + + gbString name = gb_string_make(heap_allocator(), ""); + name = gb_string_append_fmt(name, "llvm.vector.deinterleave%d", n); + defer (gb_string_free(name)); + + res.value = lb_call_intrinsic(p, name, &arg0.value, 1, types, gb_count_of(types)); + return res; + } } lbValue arg0 = {}; if (ce->args.count > 0) arg0 = lb_build_expr(p, ce->args[0]); @@ -1645,13 +1902,19 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn LLVMValueRef args[1] = { arg0.value }; res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + res.type = base_array_type(arg0.type); + + if (!is_type_boolean(res.type)) { + res = lb_emit_conv(p, res, tv.type); + } + return res; } case BuiltinProc_simd_extract_lsbs: case BuiltinProc_simd_extract_msbs: { - Type *vt = arg0.type; + Type *vt = base_type(arg0.type); GB_ASSERT(vt->kind == Type_SimdVector); i64 elem_bits = 8*type_size_of(elem); @@ -1679,7 +1942,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn case BuiltinProc_simd_shuffle: { - Type *vt = arg0.type; + Type *vt = base_type(arg0.type); GB_ASSERT(vt->kind == Type_SimdVector); i64 indices_count = ce->args.count-2; @@ -1698,6 +1961,30 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_odd_even: + { + Type *vt = base_type(arg0.type); + GB_ASSERT(vt->kind == Type_SimdVector); + + u64 indices_count = cast(u64)vt->SimdVector.count; + + LLVMValueRef *vals = gb_alloc_array(temporary_allocator(), LLVMValueRef, indices_count); + + for (u64 i = 0; i < indices_count/2; i++) { + u64 val = 2*i + 1; + vals[i] = LLVMConstInt(lb_type(p->module, t_u32), val, false); + } + for (u64 i = 0; i < indices_count/2; i++) { + u64 val = 2*i + indices_count; + vals[i+indices_count/2] = LLVMConstInt(lb_type(p->module, t_u32), val, false); + } + + LLVMValueRef indices = LLVMConstVector(vals, cast(unsigned)indices_count); + + res.value = LLVMBuildShuffleVector(p->builder, arg0.value, arg1.value, indices, ""); + return res; + } + case BuiltinProc_simd_select: { LLVMValueRef cond = arg0.value; @@ -1709,6 +1996,423 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_runtime_swizzle: + { + LLVMValueRef src = arg0.value; + LLVMValueRef indices = lb_build_expr(p, ce->args[1]).value; + + Type *vt = base_type(arg0.type); + GB_ASSERT(vt->kind == Type_SimdVector); + i64 count = vt->SimdVector.count; + Type *elem_type = vt->SimdVector.elem; + i64 elem_size = type_size_of(elem_type); + + // Determine strategy based on element size and target architecture + char const *intrinsic_name = nullptr; + bool use_hardware_runtime_swizzle = false; + + // 8-bit elements: Use dedicated table lookup instructions + if (elem_size == 1) { + use_hardware_runtime_swizzle = true; + + if (build_context.metrics.arch == TargetArch_amd64 || build_context.metrics.arch == TargetArch_i386) { + // x86/x86-64: Use pshufb intrinsics + switch (count) { + case 16: + intrinsic_name = "llvm.x86.ssse3.pshuf.b.128"; + break; + case 32: + intrinsic_name = "llvm.x86.avx2.pshuf.b"; + break; + case 64: + intrinsic_name = "llvm.x86.avx512.pshuf.b.512"; + break; + default: + use_hardware_runtime_swizzle = false; + break; + } + } else if (build_context.metrics.arch == TargetArch_arm64) { + // ARM64: Use NEON tbl intrinsics with automatic table splitting + switch (count) { + case 16: + intrinsic_name = "llvm.aarch64.neon.tbl1"; + break; + case 32: + intrinsic_name = "llvm.aarch64.neon.tbl2"; + break; + case 48: + intrinsic_name = "llvm.aarch64.neon.tbl3"; + break; + case 64: + intrinsic_name = "llvm.aarch64.neon.tbl4"; + break; + default: + use_hardware_runtime_swizzle = false; + break; + } + } else if (build_context.metrics.arch == TargetArch_arm32) { + // ARM32: Use NEON vtbl intrinsics with automatic table splitting + switch (count) { + case 8: + intrinsic_name = "llvm.arm.neon.vtbl1"; + break; + case 16: + intrinsic_name = "llvm.arm.neon.vtbl2"; + break; + case 24: + intrinsic_name = "llvm.arm.neon.vtbl3"; + break; + case 32: + intrinsic_name = "llvm.arm.neon.vtbl4"; + break; + default: + use_hardware_runtime_swizzle = false; + break; + } + } else if (build_context.metrics.arch == TargetArch_wasm32 || build_context.metrics.arch == TargetArch_wasm64p32) { + // WebAssembly: Use swizzle (only supports 16-byte vectors) + if (count == 16) { + intrinsic_name = "llvm.wasm.swizzle"; + } else { + use_hardware_runtime_swizzle = false; + } + } else { + use_hardware_runtime_swizzle = false; + } + } + + if (use_hardware_runtime_swizzle && intrinsic_name != nullptr) { + // Use dedicated hardware swizzle instruction + + // Check if required target features are enabled + bool features_enabled = true; + if (build_context.metrics.arch == TargetArch_amd64 || build_context.metrics.arch == TargetArch_i386) { + // x86/x86-64 feature checking + if (count == 16) { + // SSE/SSSE3 for 128-bit vectors + if (!check_target_feature_is_enabled(str_lit("ssse3"), nullptr)) { + features_enabled = false; + } + } else if (count == 32) { + // AVX2 requires ssse3 + avx2 features + if (!check_target_feature_is_enabled(str_lit("ssse3"), nullptr) || + !check_target_feature_is_enabled(str_lit("avx2"), nullptr)) { + features_enabled = false; + } + } else if (count == 64) { + // AVX512 requires ssse3 + avx2 + avx512f + avx512bw features + if (!check_target_feature_is_enabled(str_lit("ssse3"), nullptr) || + !check_target_feature_is_enabled(str_lit("avx2"), nullptr) || + !check_target_feature_is_enabled(str_lit("avx512f"), nullptr) || + !check_target_feature_is_enabled(str_lit("avx512bw"), nullptr)) { + features_enabled = false; + } + } + } else if (build_context.metrics.arch == TargetArch_arm64 || build_context.metrics.arch == TargetArch_arm32) { + // ARM/ARM64 feature checking - NEON is required for all table/swizzle ops + if (!check_target_feature_is_enabled(str_lit("neon"), nullptr)) { + features_enabled = false; + } + } + + if (features_enabled) { + // Add target features to function attributes for LLVM instruction selection + if (build_context.metrics.arch == TargetArch_amd64 || build_context.metrics.arch == TargetArch_i386) { + // x86/x86-64 function attributes + if (count == 16) { + // SSE/SSSE3 for 128-bit vectors + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+ssse3")); + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("128")); + } else if (count == 32) { + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+avx,+avx2,+ssse3")); + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("256")); + } else if (count == 64) { + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+avx,+avx2,+avx512f,+avx512bw,+ssse3")); + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("512")); + } + } else if (build_context.metrics.arch == TargetArch_arm64) { + // ARM64 function attributes - enable NEON for swizzle instructions + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+neon")); + // Set appropriate vector width for multi-swizzle operations + if (count >= 32) { + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("256")); + } + } else if (build_context.metrics.arch == TargetArch_arm32) { + // ARM32 function attributes - enable NEON for swizzle instructions + lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+neon")); + } + + // Handle ARM's multi-swizzle intrinsics by splitting the src vector. + // tbl[N]/vtbl[N] only produce <16 x i8>/<8 x i8>, so we issue one call + // per output chunk and concat the results. + if ((build_context.metrics.arch == TargetArch_arm64 && count > 16) || + (build_context.metrics.arch == TargetArch_arm32 && count > 8)) { + bool is_arm64 = build_context.metrics.arch == TargetArch_arm64; + i64 lane = is_arm64 ? 16 : 8; + int num_tables = cast(int)(count / lane); + GB_ASSERT_MSG(count % lane == 0, "ARM src size must be multiple of %lld bytes, got %lld bytes", lane, count); + GB_ASSERT_MSG(num_tables <= 4, "ARM NEON supports maximum 4 tables, got %d tables for %lld-byte vector", num_tables, count); + + LLVMTypeRef i32_type = LLVMInt32TypeInContext(p->module->ctx); + LLVMTypeRef i8_type = LLVMInt8TypeInContext(p->module->ctx); + LLVMTypeRef vN_type = LLVMVectorType(i8_type, cast(unsigned)lane); + + // Split src/indices into N lane-sized chunks + LLVMValueRef src_parts[4]; + LLVMValueRef idx_parts[4]; + for (int i = 0; i < num_tables; i++) { + LLVMValueRef mask[16]; + for (int j = 0; j < lane; j++) { + mask[j] = LLVMConstInt(i32_type, cast(unsigned)(i * lane + j), false); + } + LLVMValueRef shuffle_mask = LLVMConstVector(mask, cast(unsigned)lane); + src_parts[i] = LLVMBuildShuffleVector(p->builder, src, LLVMGetUndef(LLVMTypeOf(src)), shuffle_mask, ""); + idx_parts[i] = LLVMBuildShuffleVector(p->builder, indices, LLVMGetUndef(LLVMTypeOf(indices)), shuffle_mask, ""); + } + + // One tbl/vtbl call per output chunk; same N tables, different indices. + // ARM64 tbl[N] is overloaded on result type; ARM32 vtbl[N] has fixed <8 x i8>. + LLVMTypeRef overload_types[1] = { vN_type }; + LLVMTypeRef *overloads_arg = is_arm64 ? overload_types : nullptr; + unsigned overloads_count = is_arm64 ? 1 : 0; + LLVMValueRef out_parts[4]; + for (int c = 0; c < num_tables; c++) { + LLVMValueRef args[5]; + for (int i = 0; i < num_tables; i++) args[i] = src_parts[i]; + args[num_tables] = idx_parts[c]; + out_parts[c] = lb_call_intrinsic(p, intrinsic_name, args, num_tables + 1, overloads_arg, overloads_count); + } + + // Concat out_parts[0..num_tables) into by pair-wise + // shufflevector. shufflevector requires equal-sized operands, so we + // pad the right-hand chunk to acc_size with undef on each step. + LLVMValueRef acc = out_parts[0]; + i64 acc_size = lane; + for (int c = 1; c < num_tables; c++) { + LLVMValueRef rhs = out_parts[c]; + if (acc_size > lane) { + LLVMValueRef pad[64]; + for (i64 k = 0; k < acc_size; k++) { + pad[k] = (k < lane) ? LLVMConstInt(i32_type, cast(unsigned)k, false) : LLVMGetUndef(i32_type); + } + rhs = LLVMBuildShuffleVector(p->builder, rhs, LLVMGetUndef(LLVMTypeOf(rhs)), LLVMConstVector(pad, cast(unsigned)acc_size), ""); + } + i64 new_size = acc_size + lane; + LLVMValueRef concat[64]; + for (i64 k = 0; k < acc_size; k++) concat[k] = LLVMConstInt(i32_type, cast(unsigned)k, false); + for (i64 k = 0; k < lane; k++) concat[acc_size + k] = LLVMConstInt(i32_type, cast(unsigned)(acc_size+k), false); + acc = LLVMBuildShuffleVector(p->builder, acc, rhs, LLVMConstVector(concat, cast(unsigned)new_size), ""); + acc_size = new_size; + } + res.value = acc; + } else { + // Single runtime swizzle case (x86, WebAssembly, ARM single-table) + LLVMValueRef args[2] = { src, indices }; + if (build_context.metrics.arch == TargetArch_arm64) { + // ARM64 tbl1 is overloaded on result type; others are fixed + LLVMTypeRef overload_types[1] = { LLVMTypeOf(indices) }; + res.value = lb_call_intrinsic(p, intrinsic_name, args, gb_count_of(args), overload_types, 1); + } else { + res.value = lb_call_intrinsic(p, intrinsic_name, args, gb_count_of(args), nullptr, 0); + } + } + return res; + } else { + // Features not enabled, fall back to emulation + use_hardware_runtime_swizzle = false; + } + } + + // Fallback: Emulate with extracts and inserts for all element sizes + GB_ASSERT(count > 0 && count <= 64); // Sanity check + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + LLVMTypeRef i32_type = LLVMInt32TypeInContext(p->module->ctx); + LLVMTypeRef elem_llvm_type = lb_type(p->module, elem_type); + + // Calculate mask based on element size and vector count + i64 max_index = count - 1; + LLVMValueRef index_mask; + + if (elem_size == 1) { + // 8-bit: mask to src size (like pshufb behavior) + index_mask = LLVMConstInt(elem_llvm_type, max_index, false); + } else if (elem_size == 2) { + // 16-bit: mask to src size + index_mask = LLVMConstInt(elem_llvm_type, max_index, false); + } else if (elem_size == 4) { + // 32-bit: mask to src size + index_mask = LLVMConstInt(elem_llvm_type, max_index, false); + } else { + // 64-bit: mask to src size + index_mask = LLVMConstInt(elem_llvm_type, max_index, false); + } + + for (i64 i = 0; i < count; i++) { + LLVMValueRef idx_i = LLVMConstInt(i32_type, cast(unsigned)i, false); + LLVMValueRef index_elem = LLVMBuildExtractElement(p->builder, indices, idx_i, ""); + + // Mask index to valid range + LLVMValueRef masked_index = LLVMBuildAnd(p->builder, index_elem, index_mask, ""); + + // Convert to i32 for extractelement + LLVMValueRef index_i32; + if (LLVMGetIntTypeWidth(LLVMTypeOf(masked_index)) < 32) { + index_i32 = LLVMBuildZExt(p->builder, masked_index, i32_type, ""); + } else if (LLVMGetIntTypeWidth(LLVMTypeOf(masked_index)) > 32) { + index_i32 = LLVMBuildTrunc(p->builder, masked_index, i32_type, ""); + } else { + index_i32 = masked_index; + } + + values[i] = LLVMBuildExtractElement(p->builder, src, index_i32, ""); + } + + // Build result vector + res.value = LLVMGetUndef(LLVMTypeOf(src)); + for (i64 i = 0; i < count; i++) { + LLVMValueRef idx_i = LLVMConstInt(i32_type, cast(unsigned)i, false); + res.value = LLVMBuildInsertElement(p->builder, res.value, values[i], idx_i, ""); + } + return res; + } + + + case BuiltinProc_simd_sums_of_n: + { + TEMPORARY_ALLOCATOR_GUARD(); + + Type *vt = base_type(arg0.type); + GB_ASSERT(vt->kind == Type_SimdVector); + bool is_float = is_type_float(vt->SimdVector.elem); + LLVMTypeRef llvm_elem = lb_type(m, elem); + + LLVMValueRef val = arg0.value; + LLVMTypeRef llvm_u32 = lb_type(m, t_u32); + + u64 max_count = cast(u64)vt->SimdVector.count; + + GB_ASSERT(ce->args[1]->tav.mode == Addressing_Constant); + u64 n = exact_value_to_u64(ce->args[1]->tav.value); + GB_ASSERT(max_count >= n); + GB_ASSERT(max_count % n == 0); + + u64 new_size = max_count / n; + + if (max_count == n) { + LLVMValueRef args[2] = {}; + isize args_count = 0; + + char const *name = nullptr; + if (is_float) { + name = "llvm.vector.reduce.fadd"; + args[args_count++] = LLVMConstReal(llvm_elem, 0.0); + } else { + name = "llvm.vector.reduce.add"; + } + + args[args_count++] = arg0.value; + + LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)}; + res.value = lb_call_intrinsic(p, name, args, cast(unsigned)args_count, types, gb_count_of(types)); + return res; + } else if (n == 2) { + LLVMValueRef *left_vals = gb_alloc_array(temporary_allocator(), LLVMValueRef, new_size); + LLVMValueRef *right_vals = gb_alloc_array(temporary_allocator(), LLVMValueRef, new_size); + for (u64 i = 0; i < new_size; i++) { + left_vals[i] = LLVMConstInt(llvm_u32, 2*i, false); + right_vals[i] = LLVMConstInt(llvm_u32, 2*i+1, false); + } + LLVMValueRef left_indices = LLVMConstVector(left_vals, cast(unsigned)new_size); + LLVMValueRef right_indices = LLVMConstVector(right_vals, cast(unsigned)new_size); + + LLVMValueRef left = LLVMBuildShuffleVector(p->builder, val, val, left_indices, ""); + LLVMValueRef right = LLVMBuildShuffleVector(p->builder, val, val, right_indices, ""); + + if (is_float) { + res.value = LLVMBuildFAdd(p->builder, left, right, ""); + } else { + res.value = LLVMBuildAdd(p->builder, left, right, ""); + } + } else { + LLVMValueRef *shuffled = gb_alloc_array(temporary_allocator(), LLVMValueRef, new_size); + LLVMValueRef *reductions = gb_alloc_array(temporary_allocator(), LLVMValueRef, new_size); + + for (u64 i = 0; i < new_size; i++) { + u64 offset = i*n; + LLVMValueRef *index_vals = gb_alloc_array(temporary_allocator(), LLVMValueRef, n); + for (u64 j = 0; j < n; j++) { + index_vals[j] = LLVMConstInt(llvm_u32, offset+j, false); + } + + LLVMValueRef indices = LLVMConstVector(index_vals, cast(unsigned)n); + shuffled[i] = LLVMBuildShuffleVector(p->builder, val, val, indices, ""); + } + for (u64 i = 0; i < new_size; i++) { + LLVMValueRef args[2] = {}; + isize args_count = 0; + + char const *name = nullptr; + if (is_float) { + name = "llvm.vector.reduce.fadd"; + args[args_count++] = LLVMConstReal(llvm_elem, 0.0); + } else { + name = "llvm.vector.reduce.add"; + } + + args[args_count++] = shuffled[i]; + + LLVMTypeRef this_simd_type = LLVMVectorType(llvm_elem, cast(unsigned)n); + LLVMTypeRef types[1] = {this_simd_type}; + reductions[i] = lb_call_intrinsic(p, name, args, cast(unsigned)args_count, types, gb_count_of(types)); + } + + res.value = LLVMConstNull(LLVMVectorType(llvm_elem, cast(unsigned)new_size)); + for (u64 i = 0; i < new_size; i++) { + LLVMValueRef idx = LLVMConstInt(llvm_u32, i, false); + res.value = LLVMBuildInsertElement(p->builder, res.value, reductions[i], idx, ""); + } + } + + return res; + + } break; + + case BuiltinProc_simd_pairwise_add: + case BuiltinProc_simd_pairwise_sub: + if (is_float) { + switch (builtin_id) { + case BuiltinProc_simd_pairwise_add: op_code = LLVMFAdd; break; + case BuiltinProc_simd_pairwise_sub: op_code = LLVMFSub; break; + } + } else { + switch (builtin_id) { + case BuiltinProc_simd_pairwise_add: op_code = LLVMAdd; break; + case BuiltinProc_simd_pairwise_sub: op_code = LLVMSub; break; + } + } + if (op_code) { + LLVMValueRef a = arg0.value; + LLVMValueRef b = arg1.value; + + unsigned count = LLVMGetVectorSize(LLVMTypeOf(a)); + + LLVMValueRef *evens = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + LLVMValueRef *odds = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + LLVMTypeRef llvm_u32 = lb_type(m, t_u32); + for (unsigned i = 0; i < count; i++) { + evens[i] = LLVMConstInt(llvm_u32, 2*i, false); + odds[i] = LLVMConstInt(llvm_u32, 2*i + 1, false); + } + + LLVMValueRef x = LLVMBuildShuffleVector(p->builder, a, b, LLVMConstVector(evens, count), ""); + LLVMValueRef y = LLVMBuildShuffleVector(p->builder, a, b, LLVMConstVector(odds, count), ""); + + res.value = LLVMBuildBinOp(p->builder, op_code, x, y, ""); + return res; + } + break; + case BuiltinProc_simd_ceil: case BuiltinProc_simd_floor: case BuiltinProc_simd_trunc: @@ -1729,6 +2433,193 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + + case BuiltinProc_simd_approx_recip: + { + Type *vt = base_type(arg0.type); + GB_ASSERT(is_type_simd_vector(vt)); + + LLVMValueRef val = arg0.value; + i64 count = vt->SimdVector.count; + Type *elem = base_type(vt->SimdVector.elem); + + char const *intrinsic_name = nullptr; + unsigned default_width = 0; + LLVMValueRef *extra_args = nullptr; + unsigned extra_args_count = 0; + + String features_to_enable = {}; + String min_legal_vector_width = {}; + + // TODO(bill): Good optimizations for more than SSE + // e.g. AVX, ARM64, etc + if ((build_context.metrics.arch == TargetArch_i386 || build_context.metrics.arch == TargetArch_amd64)) { + if (are_types_identical(elem, t_f32)) { + intrinsic_name = "llvm.x86.sse.rcp.ps"; + default_width = 4; + + if (count >= 8) { + if (check_target_feature_is_enabled(str_lit("avx"), nullptr)) { + intrinsic_name = "llvm.x86.avx.rcp.ps.256"; + default_width = 8; + } + } + + if (count >= 16) { + if (check_target_feature_is_enabled(str_lit("avx512vl"), nullptr)) { + features_to_enable = str_lit("+avx512f,+evex512"); + min_legal_vector_width = str_lit("512"); + + intrinsic_name = "llvm.x86.avx512.rcp14.ps.512"; + default_width = 16; + + extra_args_count = 2; + extra_args = gb_alloc_array(temporary_allocator(), LLVMValueRef, extra_args_count); + + extra_args[0] = LLVMGetUndef(LLVMVectorType(lb_type(p->module, t_f32), 16)); + extra_args[1] = LLVMConstInt(lb_type(p->module, t_i16), (1u<<16) - 1, true); + } + } + } + } + + + if (lb_llvm_simd_bulk_op_unary(p, arg0, &res.value, intrinsic_name, default_width, extra_args, extra_args_count)) { + if (features_to_enable.len > 0) lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), features_to_enable); + if (min_legal_vector_width.len > 0) lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), min_legal_vector_width); + + return res; + } + + LLVMValueRef one = lb_const_value(p->module, vt->SimdVector.elem, exact_value_float(1)).value; + LLVMValueRef *ones = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + for (i64 i = 0; i < count; i++) { + ones[i] = one; + } + LLVMValueRef one_vector = LLVMConstVector(ones, cast(unsigned)count); + res.value = LLVMBuildFDiv(p->builder, one_vector, val, ""); + return res; + } + + case BuiltinProc_simd_approx_recip_sqrt: + { + auto const_broadcast_vector_float = [](lbProcedure *p, Type *elem_type, i64 count, f64 elem) -> LLVMValueRef { + LLVMValueRef val = lb_const_value(p->module, elem_type, exact_value_float(elem)).value; + return llvm_vector_broadcast(p, val, cast(unsigned)count); + }; + auto const_broadcast_vector_unsigned = [](lbProcedure *p, Type *elem_type, i64 count, u64 elem) -> LLVMValueRef { + LLVMValueRef val = lb_const_value(p->module, elem_type, exact_value_u64(elem)).value; + return llvm_vector_broadcast(p, val, cast(unsigned)count); + }; + + + Type *vt = base_type(arg0.type); + GB_ASSERT(is_type_simd_vector(vt)); + Type *elem = base_type(vt->SimdVector.elem); + LLVMValueRef val = arg0.value; + i64 count = vt->SimdVector.count; + + char const *intrinsic_name = nullptr; + unsigned default_width = 0; + LLVMValueRef *extra_args = nullptr; + unsigned extra_args_count = 0; + + String features_to_enable = {}; + String min_legal_vector_width = {}; + + // TODO(bill): Good optimizations for more than SSE + // e.g. AVX, ARM64, etc + if ((build_context.metrics.arch == TargetArch_i386 || build_context.metrics.arch == TargetArch_amd64)) { + if (are_types_identical(elem, t_f32)) { + intrinsic_name = "llvm.x86.sse.rsqrt.ps"; + default_width = 4; + + if (count >= 8) { + if (check_target_feature_is_enabled(str_lit("avx"), nullptr)) { + intrinsic_name = "llvm.x86.avx.rsqrt.ps.256"; + default_width = 8; + } + } + if (count >= 16) { + if (check_target_feature_is_enabled(str_lit("avx512vl"), nullptr)) { + features_to_enable = str_lit("+avx512f,+evex512"); + min_legal_vector_width = str_lit("512"); + + intrinsic_name = "llvm.x86.avx512.rsqrt14.ps.512"; + default_width = 16; + + extra_args_count = 2; + extra_args = gb_alloc_array(temporary_allocator(), LLVMValueRef, extra_args_count); + + extra_args[0] = LLVMGetUndef(LLVMVectorType(lb_type(p->module, t_f32), 16)); + extra_args[1] = LLVMConstInt(lb_type(p->module, t_i16), (1u<<16) - 1, true); + } + } + } + } + + if (lb_llvm_simd_bulk_op_unary(p, arg0, &res.value, intrinsic_name, default_width, extra_args, extra_args_count)) { + if (features_to_enable.len > 0) lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), features_to_enable); + if (min_legal_vector_width.len > 0) lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), min_legal_vector_width); + + return res; + } + + if (are_types_identical(elem, t_f64)) { + LLVMValueRef half = const_broadcast_vector_float(p, elem, count, 0.5); + LLVMValueRef three_halfs = const_broadcast_vector_float(p, elem, count, 1.5); + LLVMValueRef unsigned_one_vector = const_broadcast_vector_unsigned(p, t_u64, count, 1); + + LLVMValueRef half_val = LLVMBuildFMul(p->builder, val, half, ""); + + // Initial Guess based on log2(f) + LLVMValueRef magic = const_broadcast_vector_unsigned(p, t_u64, count, 0x5FE6EB50C7B537A9ull); + + // i = (transmute(u64)val >> 1) + LLVMValueRef i = LLVMBuildBitCast(p->builder, val, LLVMTypeOf(magic), ""); + i = LLVMBuildLShr(p->builder, i, unsigned_one_vector, ""); + + // magic - (transmute(u64)val - i) + // what the fuck? + LLVMValueRef guess = LLVMBuildSub(p->builder, magic, i, ""); + + guess = LLVMBuildBitCast(p->builder, guess, LLVMTypeOf(val), ""); + + + // Newton-Raphson Iteration + // guess = guess * (-(half_val * guess) * guess + 1.5) + for (isize i = 0; i < 1; i++) { + LLVMValueRef half_guess = LLVMBuildFMul(p->builder, half_val, guess, ""); + half_guess = LLVMBuildFNeg(p->builder, half_guess, ""); + + LLVMValueRef nma = nullptr; // -(half_val * guess) * guess + 1.5 + { + char const *name = "llvm.fma"; + LLVMTypeRef types[1] = {lb_type(p->module, vt)}; + LLVMValueRef args[3] = { half_guess, guess, three_halfs }; + nma = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + } + + // guess = guess * nma + guess = LLVMBuildFMul(p->builder, guess, nma, ""); + } + + res.value = guess; + return res; + } else { + + char const *name = "llvm.sqrt"; + LLVMTypeRef types[1] = {lb_type(p->module, vt)}; + LLVMValueRef args[1] = { val }; + res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + + LLVMValueRef one_vector = const_broadcast_vector_float(p, elem, count, 1.0); + res.value = LLVMBuildFDiv(p->builder, one_vector, res.value, ""); + return res; + } + } + + case BuiltinProc_simd_lanes_reverse: { i64 count = get_array_type_count(arg0.type); @@ -1816,6 +2707,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn } case BuiltinProc_simd_to_bits: + case BuiltinProc_simd_to_bits_signed: { res.value = LLVMBuildBitCast(p->builder, arg0.value, lb_type(m, tv.type), ""); return res; @@ -1856,6 +2748,8 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn auto alignment = cast(unsigned long long)type_align_of(base_array_type(arg1.type)); LLVMValueRef align = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), alignment, false); + i32 align_idx = -1; + unsigned arg_count = 4; LLVMValueRef args[4] = {}; switch (builtin_id) { @@ -1863,20 +2757,34 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn types[1] = lb_type(p->module, t_rawptr); /*fallthrough*/ case BuiltinProc_simd_gather: - args[0] = ptr; - args[1] = align; - args[2] = mask; - args[3] = val; + if (LLVM_VERSION_MAJOR >= 22) { + arg_count = 3; + args[0] = ptr; align_idx = 0; + args[1] = mask; + args[2] = val; + } else { + args[0] = ptr; + args[1] = align; + args[2] = mask; + args[3] = val; + } break; case BuiltinProc_simd_masked_store: types[1] = lb_type(p->module, t_rawptr); /*fallthrough*/ case BuiltinProc_simd_scatter: - args[0] = val; - args[1] = ptr; - args[2] = align; - args[3] = mask; + if (LLVM_VERSION_MAJOR >= 22) { + arg_count = 3; + args[0] = val; + args[1] = ptr; align_idx = 1; + args[2] = mask; + } else { + args[0] = val; + args[1] = ptr; + args[2] = align; + args[3] = mask; + } break; case BuiltinProc_simd_masked_expand_load: @@ -1897,6 +2805,10 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn } res.value = lb_call_intrinsic(p, name, args, arg_count, types, type_count); + if (align_idx >= 0) { + LLVMAttributeRef align_attr = lb_create_enum_attribute(p->module->ctx, "align", alignment); + LLVMAddAttributeAtIndex(res.value, align_idx, align_attr); + } return res; } @@ -1927,8 +2839,10 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu Entity *e = entity_of_node(ident); GB_ASSERT(e != nullptr); - if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity != nullptr) { - procedure = e->parent_proc_decl->entity->token.string; + DeclInfo *parent_proc_decl = e->parent_proc_decl.load(std::memory_order_relaxed); + if (parent_proc_decl != nullptr && + parent_proc_decl->entity != nullptr) { + procedure = parent_proc_decl->entity.load()->token.string; } else { procedure = str_lit(""); } @@ -1950,12 +2864,12 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu LLVMValueRef values[2] = {}; values[0] = lb_const_string(m, file_name).value; - values[1] = lb_const_string(m, file->data).value; + values[1] = lb_const_value(m, t_u8_slice, exact_value_string(file->data)).value; LLVMValueRef element = llvm_const_named_struct(m, t_load_directory_file, values, gb_count_of(values)); elements[i] = element; } - LLVMValueRef backing_array = llvm_const_array(lb_type(m, t_load_directory_file), elements, count); + LLVMValueRef backing_array = llvm_const_array(m, lb_type(m, t_load_directory_file), elements, count); Type *array_type = alloc_type_array(t_load_directory_file, count); lbAddr backing_array_addr = lb_add_global_generated_from_procedure(p, array_type, {backing_array, array_type}); @@ -2006,6 +2920,10 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } if (is_type_cstring(t)) { return lb_cstring_len(p, v); + } else if (is_type_cstring16(t)) { + return lb_cstring16_len(p, v); + } else if (is_type_string16(t)) { + return lb_string_len(p, v); } else if (is_type_string(t)) { return lb_string_len(p, v); } else if (is_type_array(t)) { @@ -2014,6 +2932,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu return lb_slice_len(p, v); } else if (is_type_dynamic_array(t)) { return lb_dynamic_array_len(p, v); + } else if (is_type_fixed_capacity_dynamic_array(t)) { + return lb_fixed_capacity_dynamic_array_len(p, v); } else if (is_type_map(t)) { return lb_map_len(p, v); } else if (is_type_soa_struct(t)) { @@ -2035,6 +2955,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu GB_PANIC("Unreachable"); } else if (is_type_array(t)) { GB_PANIC("Array lengths are constant"); + } else if (is_type_fixed_capacity_dynamic_array(t)) { + GB_PANIC("Fixed capacity dynamic array capacities are constant"); } else if (is_type_slice(t)) { return lb_slice_len(p, v); } else if (is_type_dynamic_array(t)) { @@ -2193,45 +3115,69 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu case BuiltinProc_expand_values: { lbValue val = lb_build_expr(p, ce->args[0]); - Type *t = base_type(val.type); + return lb_expand_values(p, val, tv.type); + } - if (!is_type_tuple(tv.type)) { - if (t->kind == Type_Struct) { - GB_ASSERT(t->Struct.fields.count == 1); - return lb_emit_struct_ev(p, val, 0); - } else if (t->kind == Type_Array) { - GB_ASSERT(t->Array.count == 1); - return lb_emit_struct_ev(p, val, 0); + case BuiltinProc_compress_values: { + isize value_count = 0; + for (Ast *arg : ce->args) { + Type *t = arg->tav.type; + if (is_type_tuple(t)) { + value_count += t->Tuple.variables.count; } else { - GB_PANIC("Unknown type of expand_values"); + value_count += 1; } - } - GB_ASSERT(is_type_tuple(tv.type)); - // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops - lbValue tuple = lb_addr_get_ptr(p, lb_add_local_generated(p, tv.type, false)); - if (t->kind == Type_Struct) { - for_array(src_index, t->Struct.fields) { - Entity *field = t->Struct.fields[src_index]; - i32 field_index = field->Variable.field_index; - lbValue f = lb_emit_struct_ev(p, val, field_index); - lbValue ep = lb_emit_struct_ep(p, tuple, cast(i32)src_index); - lb_emit_store(p, ep, f); + if (value_count == 1) { + lbValue x = lb_build_expr(p, ce->args[0]); + x = lb_emit_conv(p, x, tv.type); + return x; + } + + Type *dt = base_type(tv.type); + lbAddr addr = lb_add_local_generated(p, tv.type, true); + if (is_type_struct(dt) || is_type_tuple(dt)) { + i32 index = 0; + for (Ast *arg : ce->args) { + lbValue x = lb_build_expr(p, arg); + if (is_type_tuple(x.type)) { + for (isize i = 0; i < x.type->Tuple.variables.count; i++) { + lbValue y = lb_emit_tuple_ev(p, x, cast(i32)i); + lbValue ptr = lb_emit_struct_ep(p, addr.addr, index++); + y = lb_emit_conv(p, y, type_deref(ptr.type)); + lb_emit_store(p, ptr, y); + } + } else { + lbValue ptr = lb_emit_struct_ep(p, addr.addr, index++); + x = lb_emit_conv(p, x, type_deref(ptr.type)); + lb_emit_store(p, ptr, x); + } } - } else if (is_type_array_like(t)) { - // TODO(bill): Clean-up this code - lbValue ap = lb_address_from_load_or_generate_local(p, val); - i32 n = cast(i32)get_array_type_count(t); - for (i32 i = 0; i < n; i++) { - lbValue f = lb_emit_load(p, lb_emit_array_epi(p, ap, i)); - lbValue ep = lb_emit_struct_ep(p, tuple, i); - lb_emit_store(p, ep, f); + GB_ASSERT(index == value_count); + } else if (is_type_array_like(dt)) { + i32 index = 0; + for (Ast *arg : ce->args) { + lbValue x = lb_build_expr(p, arg); + if (is_type_tuple(x.type)) { + for (isize i = 0; i < x.type->Tuple.variables.count; i++) { + lbValue y = lb_emit_tuple_ev(p, x, cast(i32)i); + lbValue ptr = lb_emit_array_epi(p, addr.addr, index++); + y = lb_emit_conv(p, y, type_deref(ptr.type)); + lb_emit_store(p, ptr, y); + } + } else { + lbValue ptr = lb_emit_array_epi(p, addr.addr, index++); + x = lb_emit_conv(p, x, type_deref(ptr.type)); + lb_emit_store(p, ptr, x); + } } + GB_ASSERT(index == value_count); } else { - GB_PANIC("Unknown type of expand_values"); + GB_PANIC("TODO(bill): compress_values -> %s", type_to_string(tv.type)); } - return lb_emit_load(p, tuple); + + return lb_addr_load(p, addr); } case BuiltinProc_min: { @@ -2333,7 +3279,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu case BuiltinProc_transpose: { lbValue m = lb_build_expr(p, ce->args[0]); - return lb_emit_matrix_tranpose(p, m, tv.type); + return lb_emit_matrix_transpose(p, m, tv.type); } case BuiltinProc_outer_product: @@ -2383,6 +3329,11 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu res = lb_emit_conv(p, res, tv.type); } else if (t->Basic.kind == Basic_cstring) { res = lb_emit_conv(p, x, tv.type); + } else if (t->Basic.kind == Basic_string16) { + res = lb_string_elem(p, x); + res = lb_emit_conv(p, res, tv.type); + } else if (t->Basic.kind == Basic_cstring16) { + res = lb_emit_conv(p, x, tv.type); } break; case Type_Pointer: @@ -2466,12 +3417,33 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } return res; } + case BuiltinProc_read_cycle_counter_frequency: + { + lbValue res = {}; + res.type = tv.type; + + if (build_context.metrics.arch == TargetArch_arm64) { + LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false); + bool has_side_effects = false; + LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs $0, cntfrq_el0"), str_lit("=r"), has_side_effects); + GB_ASSERT(the_asm != nullptr); + res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); + } + + return res; + } case BuiltinProc_count_trailing_zeros: return lb_emit_count_trailing_zeros(p, lb_build_expr(p, ce->args[0]), tv.type); case BuiltinProc_count_leading_zeros: return lb_emit_count_leading_zeros(p, lb_build_expr(p, ce->args[0]), tv.type); + case BuiltinProc_count_trailing_ones: + return lb_emit_count_trailing_ones(p, lb_build_expr(p, ce->args[0]), tv.type); + case BuiltinProc_count_leading_ones: + return lb_emit_count_leading_ones(p, lb_build_expr(p, ce->args[0]), tv.type); + + case BuiltinProc_count_ones: return lb_emit_count_ones(p, lb_build_expr(p, ce->args[0]), tv.type); case BuiltinProc_count_zeros: @@ -2700,15 +3672,18 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu LLVMSetMetadata(instr, kind_id, LLVMMetadataAsValue(p->module->ctx, node)); } break; - case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break; - case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; + case BuiltinProc_volatile_store: + LLVMSetVolatile(instr, true); + break; + case BuiltinProc_atomic_store: + LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); + LLVMSetVolatile(instr, true); + break; case BuiltinProc_atomic_store_explicit: { auto ordering = llvm_atomic_ordering_from_odin(ce->args[2]); LLVMSetOrdering(instr, ordering); - if (ordering == LLVMAtomicOrderingUnordered) { - LLVMSetVolatile(instr, true); - } + LLVMSetVolatile(instr, true); } break; } @@ -2734,15 +3709,18 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } break; break; - case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break; - case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; + case BuiltinProc_volatile_load: + LLVMSetVolatile(instr, true); + break; + case BuiltinProc_atomic_load: + LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); + LLVMSetVolatile(instr, true); + break; case BuiltinProc_atomic_load_explicit: { auto ordering = llvm_atomic_ordering_from_odin(ce->args[1]); LLVMSetOrdering(instr, ordering); - if (ordering == LLVMAtomicOrderingUnordered) { - LLVMSetVolatile(instr, true); - } + LLVMSetVolatile(instr, true); } break; } @@ -2827,9 +3805,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu lbValue res = {}; res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false); res.type = tv.type; - if (ordering == LLVMAtomicOrderingUnordered) { - LLVMSetVolatile(res.value, true); - } + LLVMSetVolatile(res.value, true); return res; } @@ -2865,9 +3841,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu single_threaded ); LLVMSetWeak(value, weak); - if (success_ordering == LLVMAtomicOrderingUnordered || failure_ordering == LLVMAtomicOrderingUnordered) { - LLVMSetVolatile(value, true); - } + LLVMSetVolatile(value, true); if (is_type_tuple(tv.type)) { Type *fix_typed = alloc_type_tuple(); @@ -2930,16 +3904,22 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } GB_ASSERT(name != nullptr); - LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; lbValue res = {}; + res.type = platform_type; - LLVMValueRef args[3] = { + if (id == BuiltinProc_fixed_point_div || + id == BuiltinProc_fixed_point_div_sat) { + res.value = lb_integer_division_fixed_point_intrinsics(p, x.value, y.value, scale.value, platform_type, name); + } else { + LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; + + LLVMValueRef args[3] = { x.value, y.value, scale.value }; - res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); - res.type = platform_type; + res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + } return lb_emit_conv(p, res, tv.type); } @@ -2960,6 +3940,24 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu return lb_emit_conv(p, res, t); } + case BuiltinProc_likely: + case BuiltinProc_unlikely: + { + Type *t = default_type(tv.type); + lbValue x = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t); + lbValue y = lb_const_bool(p->module, t, id == BuiltinProc_likely); + + char const *name = "llvm.expect"; + + LLVMTypeRef types[1] = {lb_type(p->module, t)}; + lbValue res = {}; + LLVMValueRef args[2] = { x.value, y.value }; + + res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + res.type = t; + return lb_emit_conv(p, res, t); + } + case BuiltinProc_prefetch_read_instruction: case BuiltinProc_prefetch_read_data: case BuiltinProc_prefetch_write_instruction: @@ -3375,6 +4373,55 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr); case BuiltinProc_objc_register_class: return lb_handle_objc_register_class(p, expr); case BuiltinProc_objc_ivar_get: return lb_handle_objc_ivar_get(p, expr); + case BuiltinProc_objc_block: return lb_handle_objc_block(p, expr); + case BuiltinProc_objc_super: return lb_handle_objc_super(p, expr); + + + case BuiltinProc_c_va_start: + { + lbValue ptr = lb_build_expr(p, ce->args[0]); + lbValue args = lb_build_expr(p, ce->args[1]); + + gb_unused(args); + + LLVMValueRef va_start_args[] = {ptr.value}; + LLVMTypeRef va_start_types[] = {lb_type(p->module, ptr.type)}; + LLVMValueRef res = lb_call_intrinsic(p, "llvm.va_start", va_start_args, gb_count_of(va_start_args), va_start_types, gb_count_of(va_start_types)); + gb_unused(res); + + return {}; + } break; + case BuiltinProc_c_va_end: + { + lbValue ptr = lb_build_expr(p, ce->args[0]); + + LLVMValueRef va_end_args[] = {ptr.value}; + LLVMTypeRef va_end_types[] = {lb_type(p->module, ptr.type)}; + LLVMValueRef res = lb_call_intrinsic(p, "llvm.va_end", va_end_args, gb_count_of(va_end_args), va_end_types, gb_count_of(va_end_types)); + gb_unused(res); + + return {}; + } break; + case BuiltinProc_c_va_copy: + { + lbValue dst = lb_build_expr(p, ce->args[0]); + lbValue src = lb_build_expr(p, ce->args[1]); + + LLVMValueRef va_end_args[] = {dst.value, src.value}; + LLVMTypeRef va_end_types[] = {lb_type(p->module, dst.type)}; + LLVMValueRef res = lb_call_intrinsic(p, "llvm.va_copy", va_end_args, gb_count_of(va_end_args), va_end_types, gb_count_of(va_end_types)); + gb_unused(res); + + return {}; + } break; + case BuiltinProc_c_va_arg: + { + lbValue ptr = lb_build_expr(p, ce->args[0]); + Type *type = type_of_expr(ce->args[1]); + LLVMValueRef value = LLVMBuildVAArg(p->builder, ptr.value, lb_type(p->module, type), ""); + + return {value, type}; + } break; case BuiltinProc_constant_utf16_cstring: @@ -3699,13 +4746,13 @@ gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, } -gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr); +gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbValue *sret_dst = nullptr); -gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) { +gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr, lbValue *sret_dst) { expr = unparen_expr(expr); ast_node(ce, CallExpr, expr); - lbValue res = lb_build_call_expr_internal(p, expr); + lbValue res = lb_build_call_expr_internal(p, expr, sret_dst); if (ce->optional_ok_one) { GB_ASSERT(is_type_tuple(res.type)); @@ -3726,7 +4773,7 @@ gb_internal void lb_add_values_to_array(lbProcedure *p, Array *args, lb } } -gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { +gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr, lbValue *sret_dst) { lbModule *m = p->module; TypeAndValue tv = type_and_value_of_expr(expr); @@ -3744,21 +4791,23 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { } Ast *proc_expr = unparen_expr(ce->proc); + Entity *proc_entity = entity_of_node(proc_expr); + if (proc_mode == Addressing_Builtin) { - Entity *e = entity_of_node(proc_expr); BuiltinProcId id = BuiltinProc_Invalid; - if (e != nullptr) { - id = cast(BuiltinProcId)e->Builtin.id; + if (proc_entity != nullptr) { + id = cast(BuiltinProcId)proc_entity->Builtin.id; } else { id = BuiltinProc_DIRECTIVE; } return lb_build_builtin_proc(p, expr, tv, id); } + bool is_objc_call = proc_entity && proc_entity->Procedure.is_objc_impl_or_import; + // NOTE(bill): Regular call lbValue value = {}; - Entity *proc_entity = entity_of_node(proc_expr); if (proc_entity != nullptr) { if (proc_entity->flags & EntityFlag_Disabled) { GB_ASSERT(tv.type == nullptr); @@ -3792,11 +4841,13 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { } } - if (value.value == nullptr) { + if (is_objc_call) { + value.type = proc_tv.type; + } else if (value.value == nullptr) { value = lb_build_expr(p, proc_expr); } - GB_ASSERT(value.value != nullptr); + GB_ASSERT(value.value != nullptr || is_objc_call); Type *proc_type_ = base_type(value.type); GB_ASSERT(proc_type_->kind == Type_Proc); TypeProc *pt = &proc_type_->Proc; @@ -4024,6 +5075,30 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { isize final_count = is_c_vararg ? args.count : pt->param_count; auto call_args = array_slice(args, 0, final_count); - return lb_emit_call(p, value, call_args, ce->inlining); + + if (is_objc_call) { + return lb_handle_objc_auto_send(p, expr, slice(call_args, 0, call_args.count)); + } + + + ProcInlining inlining = ce->inlining; + ProcTailing tailing = ce->tailing; + + if (tailing == ProcTailing_none && + proc_entity && proc_entity->kind == Entity_Procedure && + proc_entity->decl_info && + proc_entity->decl_info->proc_lit) { + ast_node(pl, ProcLit, proc_entity->decl_info->proc_lit); + + if (pl->inlining != ProcInlining_none) { + inlining = pl->inlining; + } + + if (pl->tailing != ProcTailing_none) { + tailing = pl->tailing; + } + } + + return lb_emit_call(p, value, call_args, inlining, tailing, sret_dst); } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 89737a454..54447820a 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1,10 +1,133 @@ +#define LB_ENABLE_BASIC_RVO true +#define LB_ENABLE_ADVANCED_RVO build_context.enable_rvo + +// NOTE(bill): @RVO Check if a call expression returns by sret with a return type matching dst_type. +// Returns the callee's function type if eligible for copy elision, nullptr otherwise. +gb_internal lbFunctionType *lb_call_sret_eligible(lbProcedure *p, Ast *call_expr, Type *dst_type) { + GB_ASSERT(call_expr->kind == Ast_CallExpr); + Ast *proc_expr = unparen_expr(call_expr->CallExpr.proc); + TypeAndValue proc_tv = type_and_value_of_expr(proc_expr); + if (proc_tv.mode == Addressing_Type || proc_tv.mode == Addressing_Builtin) { + return nullptr; + } + Type *pt = base_type(proc_tv.type); + if (pt == nullptr || pt->kind != Type_Proc || pt->Proc.results == nullptr) { + return nullptr; + } + lbFunctionType *callee_ft = lb_get_function_type(p->module, pt); + if (callee_ft->ret.kind != lbArg_Indirect) { + return nullptr; + } + Type *callee_ret = reduce_tuple_to_single_type(pt->Proc.results); + if (callee_ret == nullptr || !are_types_identical(dst_type, callee_ret)) { + return nullptr; + } + return callee_ft; +} + +// NOTE(bill): @RVO `sret` scan for `x := call(); ...; return x` pattern. +// When matched, `x` alloca will be the sret pointer itself, eliminating +// the copy from `x` to the sret buffer on return. +gb_internal void lb_scan_for_sret_rvo(lbProcedure *p) { + if (p->body == nullptr || p->body->kind != Ast_BlockStmt) { + return; + } + Type *proc_type = p->type; + if (proc_type->Proc.result_count != 1 || proc_type->Proc.results == nullptr) { + return; + } + lbFunctionType *ft = lb_get_function_type(p->module, proc_type); + if (ft->ret.kind != lbArg_Indirect) { + return; + } + + Slice stmts = p->body->BlockStmt.stmts; + if (stmts.count < 2) { + return; + } + + // Last stmt must be `return x` where x is an identifier + Ast *last = stmts[stmts.count - 1]; + if (last->kind != Ast_ReturnStmt) { + return; + } + Slice results = last->ReturnStmt.results; + if (results.count != 1) { + return; + } + Ast *ret_expr = unparen_expr(results[0]); + if (ret_expr->kind != Ast_Ident) { + return; + } + Entity *ret_entity = entity_of_node(ret_expr); + if (ret_entity == nullptr || ret_entity->kind != Entity_Variable) { + return; + } + + Type *ret_type = reduce_tuple_to_single_type(proc_type->Proc.results); + if (ret_type == nullptr || !are_types_identical(ret_entity->type, ret_type)) { + return; + } + + // Walk backwards from the second-to-last stmt to find `x := call()` + // Everything between must be safe (no reassignment of x, no control flow) + i64 decl_index = -1; + for (i64 i = stmts.count - 2; i >= 0; i--) { + Ast *stmt = stmts[i]; + switch (stmt->kind) { + case Ast_ValueDecl: { + AstValueDecl *vd = &stmt->ValueDecl; + if (!vd->is_mutable) { + // constant decl — safe, keep scanning + continue; + } + if (vd->names.count == 1 && vd->values.count == 1) { + Entity *e = entity_of_node(vd->names[0]); + if (e == ret_entity) { + Ast *rhs = unparen_expr(vd->values[0]); + if (rhs->kind == Ast_CallExpr && lb_call_sret_eligible(p, rhs, e->type)) { + decl_index = i; + } + goto done_scanning; + } + } + // Some other mutable ValueDecl — safe as long as it doesn't involve ret_entity + for (Ast *name : vd->names) { + if (entity_of_node(name) == ret_entity) { + goto done_scanning; + } + } + continue; + } + case Ast_ExprStmt: + // Expression statements (reads, function calls) are safe + continue; + case Ast_AssignStmt: { + // Check if any lhs is our entity + for (Ast *lhs : stmt->AssignStmt.lhs) { + Ast *l = unparen_expr(lhs); + if (l->kind == Ast_Ident && entity_of_node(l) == ret_entity) { + goto done_scanning; + } + } + continue; + } + default: + // Control flow or anything else — bail + goto done_scanning; + } + } +done_scanning: + if (decl_index >= 0) { + p->sret_rvo_entity = ret_entity; + } +} + gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { if (vd == nullptr || vd->is_mutable) { return; } - auto *min_dep_set = &p->module->info->minimum_dependency_set; - for (Ast *ident : vd->names) { GB_ASSERT(ident->kind == Ast_Ident); Entity *e = entity_of_node(ident); @@ -21,7 +144,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) } } - if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + if (!polymorphic_struct && e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } @@ -56,7 +179,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) if (gpd) { rw_mutex_shared_lock(&gpd->mutex); for (Entity *e : gpd->procs) { - if (!ptr_set_exists(min_dep_set, e)) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } DeclInfo *d = decl_info_of_entity(e); @@ -94,7 +217,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) value.value = nested_proc->value; value.type = nested_proc->type; - array_add(&p->module->procedures_to_generate, nested_proc); + mpsc_enqueue(&p->module->procedures_to_generate, nested_proc); array_add(&p->children, nested_proc); string_map_set(&p->module->members, name, value); } @@ -136,9 +259,8 @@ gb_internal lbBranchBlocks lb_lookup_branch_blocks(lbProcedure *p, Ast *ident) { return empty; } - gb_internal lbTargetList *lb_push_target_list(lbProcedure *p, Ast *label, lbBlock *break_, lbBlock *continue_, lbBlock *fallthrough_) { - lbTargetList *tl = gb_alloc_item(permanent_allocator(), lbTargetList); + lbTargetList *tl = permanent_alloc_item(); tl->prev = p->target_list; tl->break_ = break_; tl->continue_ = continue_; @@ -365,6 +487,14 @@ gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_ } break; } + case Type_FixedCapacityDynamicArray: { + if (val_type != nullptr) { + lbValue data = lb_emit_struct_ep(p, expr, 0); + val = lb_emit_load(p, lb_emit_array_ep(p, data, idx)); + } + break; + } + case Type_Slice: { if (val_type != nullptr) { lbValue elem = lb_slice_elem(p, expr); @@ -623,6 +753,121 @@ gb_internal void lb_build_range_string(lbProcedure *p, lbValue expr, Type *val_t if (done_) *done_ = done; } +gb_internal void lb_build_range_string16(lbProcedure *p, lbValue expr, Type *val_type, + lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_, + bool is_reverse) { + + lbModule *m = p->module; + lbValue count = lb_const_int(m, t_int, 0); + Type *expr_type = base_type(expr.type); + switch (expr_type->kind) { + case Type_Basic: + count = lb_string_len(p, expr); + break; + default: + GB_PANIC("Cannot do range_string of %s", type_to_string(expr_type)); + break; + } + + lbValue val = {}; + lbValue idx = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + lbBlock *body = nullptr; + + loop = lb_create_block(p, "for.string16.loop"); + body = lb_create_block(p, "for.string16.body"); + done = lb_create_block(p, "for.string16.done"); + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lbValue offset = {}; + lbValue cond = {}; + + if (!is_reverse) { + /* + for c, offset in str { + ... + } + + offset := 0 + for offset < len(str) { + c, _w := string16_decode_rune(str[offset:]) + ... + offset += _w + } + */ + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + + offset = lb_addr_load(p, offset_); + cond = lb_emit_comp(p, Token_Lt, offset, count); + } else { + // NOTE(bill): REVERSED LOGIC + /* + #reverse for c, offset in str { + ... + } + + offset := len(str) + for offset > 0 { + c, _w := string16_decode_last_rune(str[:offset]) + offset -= _w + ... + } + */ + lb_addr_store(p, offset_, count); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + offset = lb_addr_load(p, offset_); + cond = lb_emit_comp(p, Token_Gt, offset, lb_const_int(m, t_int, 0)); + } + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + + lbValue rune_and_len = {}; + if (!is_reverse) { + lbValue str_elem = lb_emit_ptr_offset(p, lb_string_elem(p, expr), offset); + lbValue str_len = lb_emit_arith(p, Token_Sub, count, offset, t_int); + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_string16(p, str_elem, str_len); + + rune_and_len = lb_emit_runtime_call(p, "string16_decode_rune", args); + lbValue len = lb_emit_struct_ev(p, rune_and_len, 1); + lb_addr_store(p, offset_, lb_emit_arith(p, Token_Add, offset, len, t_int)); + + idx = offset; + } else { + // NOTE(bill): REVERSED LOGIC + lbValue str_elem = lb_string_elem(p, expr); + lbValue str_len = offset; + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_string16(p, str_elem, str_len); + + rune_and_len = lb_emit_runtime_call(p, "string16_decode_last_rune", args); + lbValue len = lb_emit_struct_ev(p, rune_and_len, 1); + lb_addr_store(p, offset_, lb_emit_arith(p, Token_Sub, offset, len, t_int)); + + idx = lb_addr_load(p, offset_); + } + + + if (val_type != nullptr) { + val = lb_emit_struct_ev(p, rune_and_len, 0); + } + + if (val_) *val_ = val; + if (idx_) *idx_ = idx; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + + gb_internal Ast *lb_strip_and_prefix(Ast *ident) { if (ident != nullptr) { @@ -644,6 +889,10 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lb_open_scope(p, scope); + if (rs->init != nullptr) { + lb_build_stmt(p, rs->init); + } + Ast *val0 = rs->vals.count > 0 ? lb_strip_and_prefix(rs->vals[0]) : nullptr; Ast *val1 = rs->vals.count > 1 ? lb_strip_and_prefix(rs->vals[1]) : nullptr; Type *val0_type = nullptr; @@ -688,6 +937,18 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lbBlock *body = lb_create_block(p, "for.interval.body"); lbBlock *done = lb_create_block(p, "for.interval.done"); + // TODO(tf2spi): This is inlined in more than several places. + // Putting this in a function might be preferred. + // LLVMSetCurrentDebugLocation2 has side effects, + // so I didn't want to hide that before it got reviewed. + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.interval.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -723,6 +984,10 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lb_close_scope(p, lbDeferExit_Default, nullptr, node->left); lb_pop_target_list(p); + if (p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, rs->body)); + } + if (check != nullptr) { lb_emit_jump(p, check); lb_start_block(p, check); @@ -820,6 +1085,10 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s lb_open_scope(p, scope); + if (rs->init != nullptr) { + lb_build_stmt(p, rs->init); + } + lbBlock *loop = lb_create_block(p, "for.tuple.loop"); lb_emit_jump(p, loop); lb_start_block(p, loop); @@ -855,6 +1124,9 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body); lb_pop_target_list(p); + if (p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, rs->body)); + } lb_emit_jump(p, loop); lb_start_block(p, done); } @@ -871,6 +1143,9 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs lb_open_scope(p, scope); + if (rs->init != nullptr) { + lb_build_stmt(p, rs->init); + } Ast *val0 = rs->vals.count > 0 ? lb_strip_and_prefix(rs->vals[0]) : nullptr; Ast *val1 = rs->vals.count > 1 ? lb_strip_and_prefix(rs->vals[1]) : nullptr; @@ -893,6 +1168,14 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs lbAddr index = lb_add_local_generated(p, t_int, false); + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.soa.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } if (!is_reverse) { /* for x, i in array { @@ -970,13 +1253,15 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs lb_store_range_stmt_val(p, val1, lb_addr_load(p, index)); } - lb_push_target_list(p, rs->label, done, loop, nullptr); lb_build_stmt(p, rs->body); lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body); lb_pop_target_list(p); + if (p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, rs->body)); + } lb_emit_jump(p, loop); lb_start_block(p, done); @@ -1012,6 +1297,10 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lb_open_scope(p, scope); + if (rs->init != nullptr) { + lb_build_stmt(p, rs->init); + } + Ast *val0 = rs->vals.count > 0 ? lb_strip_and_prefix(rs->vals[0]) : nullptr; Ast *val1 = rs->vals.count > 1 ? lb_strip_and_prefix(rs->vals[1]) : nullptr; Type *val0_type = nullptr; @@ -1029,6 +1318,15 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lbBlock *done = nullptr; bool is_map = false; + if (rs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.range.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, rs->label)); + lb_add_debug_label(p, rs->label, label); + } + if (tav.mode == Addressing_Type) { lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done); } else { @@ -1045,10 +1343,22 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc break; } case Type_Array: { - lbValue array = lb_build_addr_ptr(p, expr); - if (is_type_pointer(type_deref(array.type))) { - array = lb_emit_load(p, array); + lbValue array; + lbAddr addr = lb_build_addr(p, expr); + switch (addr.kind) { + case lbAddr_Swizzle: + case lbAddr_SwizzleLarge: + // NOTE(laytan): apply the swizzle. + array = lb_address_from_load(p, lb_addr_load(p, addr)); + break; + default: + array = lb_addr_get_ptr(p, addr); + if (is_type_pointer(type_deref(array.type))) { + array = lb_emit_load(p, array); + } + break; } + lbAddr count_ptr = lb_add_local_generated(p, t_int, false); lb_addr_store(p, count_ptr, lb_const_int(p->module, t_int, et->Array.count)); lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse); @@ -1064,6 +1374,15 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse); break; } + case Type_FixedCapacityDynamicArray: { + lbValue array = lb_build_addr_ptr(p, expr); + if (is_type_pointer(type_deref(array.type))) { + array = lb_emit_load(p, array); + } + lbValue count_ptr = lb_emit_struct_ep(p, array, 1); + lb_build_range_indexed(p, array, val0_type, count_ptr, &val, &key, &loop, &done, rs->reverse); + break; + } case Type_DynamicArray: { lbValue count_ptr = {}; lbValue array = lb_build_addr_ptr(p, expr); @@ -1099,7 +1418,11 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc } Type *t = base_type(string.type); GB_ASSERT(!is_type_cstring(t)); - lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + if (is_type_string16(t)) { + lb_build_range_string16(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + } else { + lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + } break; } case Type_Tuple: @@ -1174,6 +1497,9 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body); lb_pop_target_list(p); + if (p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, rs->body)); + } lb_emit_jump(p, loop); lb_start_block(p, done); } @@ -1183,6 +1509,10 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * lb_open_scope(p, scope); // Open scope here + if (rs->init != nullptr) { + lb_build_stmt(p, rs->init); + } + Ast *val0 = lb_strip_and_prefix(rs->val0); Ast *val1 = lb_strip_and_prefix(rs->val1); Type *val0_type = nullptr; @@ -1278,12 +1608,13 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * if (unroll_count_ev.kind == ExactValue_Invalid) { - GB_ASSERT(expr->tav.mode == Addressing_Constant); Type *t = base_type(expr->tav.type); switch (t->kind) { case Type_Basic: + GB_ASSERT(expr->tav.mode == Addressing_Constant); + GB_ASSERT(is_type_string(t)); { ExactValue value = expr->tav.value; @@ -1376,6 +1707,19 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt * break; } + case Type_FixedCapacityDynamicArray: { + lbValue array = lb_build_expr(p, expr); + if (!is_type_pointer(array.type)) { + array = lb_address_from_load_or_generate_local(p, array); + } + GB_ASSERT(is_type_pointer(array.type)); + + count_ptr = lb_emit_struct_ep(p, array, 1); + + data_ptr = lb_emit_conv(p, array, alloc_type_pointer(t->FixedCapacityDynamicArray.elem)); + break; + } + case Type_Array: { lbValue array = lb_build_expr(p, expr); count_ptr = lb_add_local_generated(p, t_int, false).addr; @@ -1530,6 +1874,14 @@ gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, boo gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *scope) { lb_open_scope(p, scope); + if (ss->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "switch.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, ss->label)); + lb_add_debug_label(p, ss->label, label); + } if (ss->init != nullptr) { lb_build_stmt(p, ss->init); } @@ -1556,7 +1908,45 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * Ast *clause = body->stmts[i]; ast_node(cc, CaseClause, clause); - body_blocks[i] = lb_create_block(p, cc->list.count == 0 ? "switch.default.body" : "switch.case.body"); + char const *block_name = cc->list.count == 0 ? "switch.default.body" : "switch.case.body"; + + if (is_trivial && cc->list.count >= 1) { + gbString bn = gb_string_make(heap_allocator(), "switch.case."); + + Ast *first = cc->list[0]; + if (first->tav.mode == Addressing_Type) { + bn = gb_string_appendc(bn, "type."); + } else if (is_type_rune(first->tav.type)) { + bn = gb_string_appendc(bn, "rune."); + } else { + bn = gb_string_appendc(bn, "value."); + } + + for_array(i, cc->list) { + if (i > 0) { + bn = gb_string_appendc(bn, ".."); + } + + Ast *expr = cc->list[i]; + if (expr->tav.mode == Addressing_Type) { + bn = write_type_to_string(bn, expr->tav.type, false); + } else { + ExactValue value = expr->tav.value; + if (is_type_rune(expr->tav.type) && value.kind == ExactValue_Integer) { + Rune r = cast(Rune)exact_value_to_i64(value); + u8 rune_temp[6] = {}; + isize size = gb_utf8_encode_rune(rune_temp, r); + bn = gb_string_append_length(bn, rune_temp, size); + } else { + bn = write_exact_value_to_string(bn, value, 1024); + } + } + } + + block_name = cast(char const *)bn; + } + + body_blocks[i] = lb_create_block(p, block_name); if (cc->list.count == 0) { default_block = body_blocks[i]; } @@ -1604,6 +1994,10 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * } lbBlock *next_cond = nullptr; + if (p->debug_info != nullptr) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_end_location_from_ast(p, clause)); + } + for (Ast *expr : cc->list) { expr = unparen_expr(expr); @@ -1736,6 +2130,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, lbBlock *done) { ast_node(cc, CaseClause, clause); + // NOTE(tf2spi): Debug info for label not generated here on purpose lb_push_target_list(p, label, done, nullptr, nullptr); lb_build_stmt_list(p, cc->stmts); lb_close_scope(p, lbDeferExit_Default, body, clause); @@ -1797,7 +2192,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss num_cases += cc->list.count; if (cc->list.count == 0) { GB_ASSERT(default_block == nullptr); - default_block = lb_create_block(p, "typeswitch.default.body"); + default_block = lb_create_block(p, "typeswitch.case.default"); else_block = default_block; } } @@ -1877,7 +2272,16 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss continue; } - lbBlock *body = lb_create_block(p, "typeswitch.body"); + char const *body_name = "typeswitch.case"; + + if (!are_types_identical(case_entity->type, parent_base_type)) { + gbString canonical_name = temp_canonical_string(case_entity->type); + gbString bn = gb_string_make(heap_allocator(), "typeswitch.case."); + bn = gb_string_append_length(bn, canonical_name, gb_string_length(canonical_name)); + body_name = cast(char const *)bn; + } + + lbBlock *body = lb_create_block(p, body_name); if (p->debug_info != nullptr) { LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, clause)); } @@ -1888,7 +2292,13 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss lbValue on_val = {}; if (switch_kind == TypeSwitch_Union) { Type *ut = base_type(type_deref(parent.type)); - on_val = lb_const_union_tag(m, ut, case_type); + if (is_type_untyped_nil(case_type)) { + GB_ASSERT(type_has_nil(ut)); + saw_nil = true; + on_val = lb_const_int(m, union_tag_type(ut), 0); + } else { + on_val = lb_const_union_tag(m, ut, case_type); + } } else if (switch_kind == TypeSwitch_Any) { if (is_type_untyped_nil(case_type)) { @@ -1957,14 +2367,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { for_array(i, vd->names) { lbValue value = {}; - if (vd->values.count > 0) { - GB_ASSERT(vd->names.count == vd->values.count); - Ast *ast_value = vd->values[i]; - GB_ASSERT(ast_value->tav.mode == Addressing_Constant || - ast_value->tav.mode == Addressing_Invalid); - value = lb_const_value(p->module, ast_value->tav.type, ast_value->tav.value, LB_CONST_CONTEXT_DEFAULT_NO_LOCAL); - } Ast *ident = vd->names[i]; GB_ASSERT(!is_blank_ident(ident)); @@ -1972,6 +2375,19 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { GB_ASSERT(e->flags & EntityFlag_Static); String name = e->token.string; + if (vd->values.count > 0) { + GB_ASSERT(vd->names.count == vd->values.count); + Ast *ast_value = vd->values[i]; + GB_ASSERT(ast_value->tav.mode == Addressing_Constant || + ast_value->tav.mode == Addressing_Invalid); + + auto cc = LB_CONST_CONTEXT_DEFAULT_NO_LOCAL; + if (e->Variable.is_rodata) { + cc.is_rodata = true; + } + value = lb_const_value(p->module, ast_value->tav.type, ast_value->tav.value, nullptr, cc); + } + String mangled_name = {}; { gbString str = gb_string_make_length(permanent_allocator(), p->name.text, p->name.len); @@ -1986,33 +2402,46 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) { LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(p->module, e->type), c_name); LLVMSetAlignment(global, cast(u32)type_align_of(e->type)); LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type))); - if (value.value != nullptr) { - LLVMSetInitializer(global, value.value); - } + if (e->Variable.is_rodata) { LLVMSetGlobalConstant(global, true); } - if (e->Variable.thread_local_model != "") { - LLVMSetThreadLocal(global, true); - String m = e->Variable.thread_local_model; - LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel; - if (m == "default") { - mode = LLVMGeneralDynamicTLSModel; - } else if (m == "localdynamic") { - mode = LLVMLocalDynamicTLSModel; - } else if (m == "initialexec") { - mode = LLVMInitialExecTLSModel; - } else if (m == "localexec") { - mode = LLVMLocalExecTLSModel; - } else { - GB_PANIC("Unhandled thread local mode %.*s", LIT(m)); - } - LLVMSetThreadLocalMode(global, mode); - } else { + if (!lb_apply_thread_local_model(global, e->Variable.thread_local_model)) { LLVMSetLinkage(global, LLVMInternalLinkage); } + if (value.value != nullptr) { + if (is_type_any(e->type)) { + Type *var_type = default_type(value.type); + + gbString var_name = gb_string_make(temporary_allocator(), "__$static_any::"); + var_name = gb_string_append_length(var_name, mangled_name.text, mangled_name.len); + + lbAddr var_global = lb_add_global_generated_with_name(p->module, var_type, value, make_string_c(var_name), nullptr); + LLVMValueRef var_global_ref = var_global.addr.value; + + if (e->Variable.is_rodata) { + LLVMSetGlobalConstant(var_global_ref, true); + } + + if (!lb_apply_thread_local_model(var_global_ref, e->Variable.thread_local_model)) { + LLVMSetLinkage(var_global_ref, LLVMInternalLinkage); + } + + auto vals = array_make(temporary_allocator(), 0, 3); + array_add(&vals, lb_emit_conv(p, var_global.addr, t_rawptr).value); + if (build_context.metrics.ptr_size == 4) { + array_add(&vals, LLVMConstNull(lb_type_padding_filler(p->module, 4, 4))); + } + array_add(&vals, lb_typeid(p->module, var_type).value); + + LLVMValueRef init = llvm_const_named_struct(p->module, e->type, vals.data, vals.count); + LLVMSetInitializer(global, init); + } else { + LLVMSetInitializer(global, value.value); + } + } lbValue global_val = {global, alloc_type_pointer(e->type)}; lb_add_entity(p->module, e, global_val); @@ -2164,6 +2593,45 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice const &return if (return_count == 1) { Entity *e = tuple->variables[0]; + + if (LB_ENABLE_BASIC_RVO && res_count == 1 && return_by_pointer) { + Ast *ret_expr = unparen_expr(return_results[0]); + + // NOTE(bill): @RVO for `return call()` in a procedure which uses `sret` and has no defers + // This forwards the sret pointer directly to the callee + if (p->defer_stmts.count == 0) { + if (ret_expr->kind == Ast_CallExpr && lb_call_sret_eligible(p, ret_expr, e->type)) { + lbValue sret_ptr = p->return_ptr.addr; + lb_build_call_expr(p, ret_expr, &sret_ptr); + if (p->type->Proc.has_named_results && e->token.string != "") { + res = lb_emit_load(p, p->return_ptr.addr); + rw_mutex_shared_lock(&p->module->values_mutex); + lbValue found = map_must_get(&p->module->values, e); + rw_mutex_shared_unlock(&p->module->values_mutex); + lb_emit_store(p, found, lb_emit_conv(p, res, e->type)); + } + LLVMBuildRetVoid(p->builder); + return; + } + } + + // NOTE(bill): @RVO for `x := call(); ...; return x` + if (p->sret_rvo_entity != nullptr) { + if (ret_expr->kind == Ast_Ident) { + Entity *ret_e = entity_of_node(ret_expr); + if (ret_e == p->sret_rvo_entity) { + lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos); + LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block); + if (!lb_is_instr_terminating(instr)) { + LLVMBuildRetVoid(p->builder); + } + return; + } + } + } + } + + if (res_count == 0) { rw_mutex_shared_lock(&p->module->values_mutex); lbValue found = map_must_get(&p->module->values, e); @@ -2263,33 +2731,26 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice const &return } else { Type *ret_type = p->type->Proc.results; - // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops - if (return_by_pointer) { - res = p->return_ptr.addr; - } else { - res = lb_add_local_generated(p, ret_type, false).addr; - } - auto result_values = slice_make(temporary_allocator(), results.count); - auto result_eps = slice_make(temporary_allocator(), results.count); - for_array(i, results) { result_values[i] = lb_emit_conv(p, results[i], tuple->variables[i]->type); } - for_array(i, results) { - result_eps[i] = lb_emit_struct_ep(p, res, cast(i32)i); - } - for_array(i, result_eps) { - lb_emit_store(p, result_eps[i], result_values[i]); - } if (return_by_pointer) { + res = p->return_ptr.addr; + auto result_eps = slice_make(temporary_allocator(), results.count); + for_array(i, results) { + result_eps[i] = lb_emit_struct_ep(p, res, cast(i32)i); + } + for_array(i, result_eps) { + lb_emit_store(p, result_eps[i], result_values[i]); + } lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos); LLVMBuildRetVoid(p->builder); return; } - res = lb_emit_load(p, res); + res = lb_build_struct_value(p, ret_type, result_values.data, result_values.count); } } lb_build_return_stmt_internal(p, res, pos); @@ -2307,6 +2768,14 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) { else_ = lb_create_block(p, "if.else"); } if (is->label != nullptr) { + if (p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "if.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, is->label)); + lb_add_debug_label(p, is->label, label); + } lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr); tl->is_block = true; } @@ -2399,12 +2868,19 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { lb_push_target_list(p, fs->label, done, post, nullptr); + if (fs->label != nullptr && p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "for.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, fs->label)); + lb_add_debug_label(p, fs->label, label); + } if (fs->init != nullptr) { - #if 1 lbBlock *init = lb_create_block(p, "for.init"); lb_emit_jump(p, init); lb_start_block(p, init); - #endif + lb_build_stmt(p, fs->init); } @@ -2420,7 +2896,6 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) { lb_start_block(p, body); } - lb_build_stmt(p, fs->body); lb_pop_target_list(p); @@ -2584,6 +3059,23 @@ gb_internal void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr } gb_internal void lb_build_assign_stmt(lbProcedure *p, AstAssignStmt *as) { if (as->op.kind == Token_Eq) { + if (LB_ENABLE_ADVANCED_RVO) { + // @RVO for single assignments `x = call()` + if (as->lhs.count == 1 && as->rhs.count == 1 && !is_blank_ident(as->lhs[0])) { + Ast *rhs_expr = unparen_expr(as->rhs[0]); + if (rhs_expr->kind == Ast_CallExpr) { + lbAddr lval = lb_build_addr(p, as->lhs[0]); + if (LLVMIsAAllocaInst(lval.addr.value) && lval.kind == lbAddr_Default) { + if (lb_call_sret_eligible(p, rhs_expr, lb_addr_type(lval))) { + lbValue dst = lval.addr; + lb_build_call_expr(p, rhs_expr, &dst); + return; + } + } + } + } + } + auto lvals = array_make(permanent_allocator(), 0, as->lhs.count); for (Ast *lhs : as->lhs) { @@ -2694,9 +3186,21 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { case_ast_node(bs, BlockStmt, node); + lbBlock *body = nullptr; lbBlock *done = nullptr; if (bs->label != nullptr) { + if (p->debug_info != nullptr) { + lbBlock *label = lb_create_block(p, "block.label"); + lb_emit_jump(p, label); + lb_start_block(p, label); + + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, bs->label)); + lb_add_debug_label(p, bs->label, label); + } + body = lb_create_block(p, "block.body"); done = lb_create_block(p, "block.done"); + lb_emit_jump(p, body); + lb_start_block(p, body); lbTargetList *tl = lb_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } @@ -2757,6 +3261,27 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { } } } else { + if (LB_ENABLE_ADVANCED_RVO) { + // @RVO: for `x := call()` + if (vd->names.count == 1 && values.count == 1 && !is_blank_ident(vd->names[0])) { + Ast *rhs_expr = unparen_expr(values[0]); + Entity *e = entity_of_node(vd->names[0]); + if (rhs_expr->kind == Ast_CallExpr && e != nullptr && lb_call_sret_eligible(p, rhs_expr, e->type)) { + lbValue dst = {}; + if (e == p->sret_rvo_entity) { + dst = p->return_ptr.addr; + lb_add_entity(p->module, e, dst); + lb_add_debug_local_variable(p, dst.value, e->type, e->token); + } else { + lbAddr local = lb_add_local(p, e->type, e, true); + dst = local.addr; + } + lb_build_call_expr(p, rhs_expr, &dst); + break; + } + } + } + auto lvals_preused = slice_make(temporary_allocator(), vd->names.count); auto lvals = slice_make(temporary_allocator(), vd->names.count); auto inits = array_make(temporary_allocator(), 0, lvals.count); @@ -2906,6 +3431,9 @@ gb_internal void lb_build_defer_stmt(lbProcedure *p, lbDefer const &d) { if (d.kind == lbDefer_Node) { lb_build_stmt(p, d.stmt); } else if (d.kind == lbDefer_Proc) { + if (p->debug_info != nullptr && d.pos.line > 0) { + LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_token_pos(p, d.pos)); + } lb_emit_call(p, d.proc.deferred, d.proc.result_as_args); } } @@ -2982,10 +3510,11 @@ gb_internal void lb_add_defer_node(lbProcedure *p, isize scope_index, Ast *stmt) d->scope_index = scope_index; d->context_stack_count = p->context_stack.count; d->block = p->curr_block; - d->stmt = stmt; + d->pos = ast_token(stmt).pos; + d->stmt = stmt; } -gb_internal void lb_add_defer_proc(lbProcedure *p, isize scope_index, lbValue deferred, Array const &result_as_args) { +gb_internal void lb_add_defer_proc(lbProcedure *p, isize scope_index, lbValue deferred, Array const &result_as_args, TokenPos pos) { Type *pt = base_type(p->type); GB_ASSERT(pt->kind == Type_Proc); if (pt->Proc.calling_convention == ProcCC_Odin) { @@ -2996,6 +3525,7 @@ gb_internal void lb_add_defer_proc(lbProcedure *p, isize scope_index, lbValue de d->kind = lbDefer_Proc; d->scope_index = p->scope_index; d->block = p->curr_block; + d->pos = pos; d->context_stack_count = p->context_stack.count; d->proc.deferred = deferred; d->proc.result_as_args = result_as_args; diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index ad4250f3c..9b9d3e8eb 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -1,4 +1,10 @@ +gb_internal void lb_set_odin_rtti_section(LLVMValueRef value) { + if (build_context.metrics.os != TargetOs_darwin) { + LLVMSetSection(value, ".odinti"); + } +} + gb_internal isize lb_type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err_on_not_found=true) { isize index = type_info_index(info, pair, err_on_not_found); if (index >= 0) { @@ -63,6 +69,7 @@ gb_internal u64 lb_typeid_kind(lbModule *m, Type *type, u64 id=0) { case Type_SimdVector: kind = Typeid_Simd_Vector; break; case Type_SoaPointer: kind = Typeid_SoaPointer; break; case Type_BitField: kind = Typeid_Bit_Field; break; + case Type_FixedCapacityDynamicArray: kind = Typeid_Fixed_Capacity_Dynamic_Array; break; } return kind; @@ -175,15 +182,9 @@ gb_internal LLVMTypeRef *lb_setup_modified_types_for_type_info(lbModule *m, isiz stypes[0] = lb_type(m, tibt->Struct.fields[0]->type); stypes[1] = lb_type(m, tibt->Struct.fields[1]->type); stypes[2] = lb_type(m, tibt->Struct.fields[2]->type); - isize variant_index = 0; - if (build_context.ptr_size == 8) { - stypes[3] = lb_type(m, t_i32); // padding - stypes[4] = lb_type(m, tibt->Struct.fields[3]->type); - variant_index = 5; - } else { - stypes[3] = lb_type(m, tibt->Struct.fields[3]->type); - variant_index = 4; - } + stypes[3] = lb_type(m, t_i32); // padding + stypes[4] = lb_type(m, tibt->Struct.fields[3]->type); + isize variant_index = 5; LLVMTypeRef *modified_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, Typeid__COUNT); GB_ASSERT(Typeid__COUNT == ut->Union.variants.count); @@ -200,10 +201,10 @@ gb_internal LLVMTypeRef *lb_setup_modified_types_for_type_info(lbModule *m, isiz vtypes[0] = lb_type(m, t); vtypes[1] = padding; vtypes[2] = tag; - LLVMTypeRef variant_type = LLVMStructType(vtypes, gb_count_of(vtypes), true); + LLVMTypeRef variant_type = LLVMStructTypeInContext(m->ctx, vtypes, gb_count_of(vtypes), true); stypes[variant_index] = variant_type; - LLVMTypeRef modified_type = LLVMStructType(stypes, cast(unsigned)(variant_index+1), false); + LLVMTypeRef modified_type = LLVMStructTypeInContext(m->ctx, stypes, cast(unsigned)(variant_index+1), false); modified_types[i] = modified_type; } @@ -221,6 +222,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ gb_snprintf(name, 63, "__$ti-%lld", cast(long long)index); LLVMValueRef g = LLVMAddGlobal(m->mod, type, name); lb_make_global_private_const(g); + lb_set_odin_rtti_section(g); return g; }; @@ -295,7 +297,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ (name##_values)[i] = LLVMConstNull(elem); \ } \ } \ - LLVMSetInitializer(name.addr.value, llvm_const_array(elem, name##_values, at->Array.count)); \ + LLVMSetInitializer(name.addr.value, llvm_const_array(m, elem, name##_values, at->Array.count)); \ }) type_info_allocate_values(lb_global_type_info_member_types); @@ -353,16 +355,9 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ small_const_values[0] = LLVMConstInt(lb_type(m, t_int), size, true); small_const_values[1] = LLVMConstInt(lb_type(m, t_int), align, true); small_const_values[2] = type_info_flags.value; - - unsigned variant_index = 0; - if (build_context.ptr_size == 8) { - small_const_values[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 3)); - small_const_values[4] = id.value; - variant_index = 5; - } else { - small_const_values[3] = id.value; - variant_index = 4; - } + small_const_values[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 3)); + small_const_values[4] = id.value; + unsigned variant_index = 5; LLVMTypeRef full_variant_type = LLVMStructGetTypeAtIndex(stype, variant_index); unsigned full_variant_elem_count = LLVMCountStructElementTypes(full_variant_type); @@ -387,8 +382,9 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ String proc_name = {}; if (t->Named.type_name->parent_proc_decl) { DeclInfo *decl = t->Named.type_name->parent_proc_decl; - if (decl->entity && decl->entity->kind == Entity_Procedure) { - proc_name = decl->entity->token.string; + Entity *e = decl->entity.load(); + if (e && e->kind == Entity_Procedure) { + proc_name = e->token.string; } } TokenPos pos = t->Named.type_name->token.pos; @@ -518,14 +514,48 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ break; case Basic_string: - tag_type = t_type_info_string; + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, false).value, + lb_const_int(m, t_type_info_string_encoding_kind, 0).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } break; case Basic_cstring: { tag_type = t_type_info_string; - LLVMValueRef vals[1] = { + LLVMValueRef vals[2] = { lb_const_bool(m, t_bool, true).value, + lb_const_int(m, t_type_info_string_encoding_kind, 0).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Basic_string16: + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, false).value, + lb_const_int(m, t_type_info_string_encoding_kind, 1).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + + case Basic_cstring16: + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, true).value, + lb_const_int(m, t_type_info_string_encoding_kind, 1).value, }; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); @@ -615,6 +645,21 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); break; } + case Type_FixedCapacityDynamicArray: { + tag_type = t_type_info_fixed_capacity_dynamic_array; + + i64 len_offset = type_offset_of(t, 1); + + LLVMValueRef vals[4] = { + get_type_info_ptr(m, t->FixedCapacityDynamicArray.elem), + lb_const_int(m, t_int, type_size_of(t->FixedCapacityDynamicArray.elem)).value, + lb_const_int(m, t_int, t->FixedCapacityDynamicArray.capacity).value, + lb_const_int(m, t_uintptr, len_offset).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + break; + } case Type_Slice: { tag_type = t_type_info_slice; @@ -710,12 +755,14 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value; } - LLVMValueRef name_init = llvm_const_array(lb_type(m, t_string), name_values, cast(unsigned)fields.count); - LLVMValueRef value_init = llvm_const_array(lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count); + LLVMValueRef name_init = llvm_const_array(m, lb_type(m, t_string), name_values, cast(unsigned)fields.count); + LLVMValueRef value_init = llvm_const_array(m, lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count); LLVMSetInitializer(name_array.value, name_init); LLVMSetInitializer(value_array.value, value_init); LLVMSetGlobalConstant(name_array.value, true); LLVMSetGlobalConstant(value_array.value, true); + lb_set_odin_rtti_section(name_array.value); + lb_set_odin_rtti_section(value_array.value); lbValue v_count = lb_const_int(m, t_int, fields.count); @@ -786,10 +833,10 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ { u8 flags = 0; - if (t->Struct.is_packed) flags |= 1<<0; - if (t->Struct.is_raw_union) flags |= 1<<1; - if (t->Struct.is_no_copy) flags |= 1<<2; - if (t->Struct.custom_align) flags |= 1<<3; + if (t->Struct.is_packed) flags |= 1<<0; + if (t->Struct.is_raw_union) flags |= 1<<1; + if (t->Struct.is_all_or_none) flags |= 1<<2; + if (t->Struct.custom_align) flags |= 1<<3; vals[6] = lb_const_int(m, t_u8, flags).value; if (is_type_comparable(t) && !is_type_simple_compare(t)) { @@ -892,15 +939,25 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ GB_ASSERT(is_type_typed(t->BitSet.elem)); - LLVMValueRef vals[4] = { - get_type_info_ptr(m, t->BitSet.elem), - LLVMConstNull(lb_type(m, t_type_info_ptr)), - lb_const_int(m, t_i64, t->BitSet.lower).value, - lb_const_int(m, t_i64, t->BitSet.upper).value, + LLVMValueRef vals[5] = { + get_type_info_ptr(m, t->BitSet.elem), // ^Type_Info + nullptr, // ^Type_Info + nullptr, // bool + lb_const_int(m, t_i64, t->BitSet.lower).value, // i64 + lb_const_int(m, t_i64, t->BitSet.upper).value, // i64 }; + Type *underlying = nullptr; + bool explicit_underlying = false; if (t->BitSet.underlying != nullptr) { + underlying = t->BitSet.underlying; + explicit_underlying = true; vals[1] = get_type_info_ptr(m, t->BitSet.underlying); + vals[2] = lb_const_bool(m, t_bool, true).value; + } else { + underlying = bit_set_to_int(t); } + vals[1] = get_type_info_ptr(m, underlying); + vals[2] = lb_const_bool(m, t_bool, explicit_underlying).value; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); } @@ -1007,7 +1064,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ i64 tag_index = 0; if (tag_type != nullptr) { - tag_index = union_variant_index(ut, tag_type); + tag_index = union_variant_index_checked(ut, tag_type); } GB_ASSERT(tag_index <= Typeid__COUNT); @@ -1056,6 +1113,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ LLVMValueRef giant_array = lb_global_type_info_data_ptr(m).value; LLVMSetInitializer(giant_array, giant_const); lb_make_global_private_const(giant_array); + lb_set_odin_rtti_section(giant_array); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 521553147..a92e8610e 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -6,6 +6,7 @@ gb_internal bool lb_is_type_aggregate(Type *t) { case Type_Basic: switch (t->Basic.kind) { case Basic_string: + case Basic_string16: case Basic_any: return true; @@ -88,7 +89,7 @@ gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef p bool is_inlinable = false; i64 const_len = 0; - if (LLVMIsConstant(len)) { + if (!p->is_startup && LLVMIsConstant(len)) { const_len = cast(i64)LLVMConstIntGetSExtValue(len); // TODO(bill): Determine when it is better to do the `*.inline` versions if (const_len <= lb_max_zero_init_size()) { @@ -190,6 +191,23 @@ gb_internal lbValue lb_emit_clamp(lbProcedure *p, Type *t, lbValue x, lbValue mi return z; } +gb_internal lbValue lb_emit_string16(lbProcedure *p, lbValue str_elem, lbValue str_len) { + if (false && lb_is_const(str_elem) && lb_is_const(str_len)) { + LLVMValueRef values[2] = { + str_elem.value, + str_len.value, + }; + lbValue res = {}; + res.type = t_string16; + res.value = llvm_const_named_struct(p->module, t_string16, values, gb_count_of(values)); + return res; + } else { + lbAddr res = lb_add_local_generated(p, t_string16, false); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), str_elem); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), str_len); + return lb_addr_load(p, res); + } +} gb_internal lbValue lb_emit_string(lbProcedure *p, lbValue str_elem, lbValue str_len) { @@ -268,7 +286,18 @@ gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) { } } - if (is_type_simd_vector(src) && is_type_simd_vector(dst)) { + bool is_simd_vector_bitcastable = false; + if (is_type_simd_vector(src)) { + if (is_type_simd_vector(dst)) { + if (!is_type_internally_pointer_like(src->SimdVector.elem) && !is_type_internally_pointer_like(dst->SimdVector.elem)) { + is_simd_vector_bitcastable = true; + } + } else if (is_type_integer(dst) && is_type_endian_platform(dst)) { + is_simd_vector_bitcastable = true; + } + } + + if (is_simd_vector_bitcastable) { res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(p->module, t), ""); return res; } else if (is_type_array_like(src) && (is_type_simd_vector(dst) || is_type_integer_128bit(dst))) { @@ -413,6 +442,50 @@ gb_internal lbValue lb_emit_try_has_value(lbProcedure *p, lbValue rhs) { return has_value; } +gb_internal bool lb_is_type_trivial(Type *type) { + Type *bt = base_type(type); + if (is_type_integer(bt) || is_type_float(bt) || is_type_boolean(bt) || + is_type_pointer(bt) || is_type_enum(bt) || is_type_rune(bt) || is_type_typeid((bt))) { + return true; + } + return false; +} + +gb_internal bool lb_is_expr_trivial(Ast *e) { + Type *type = default_type(type_of_expr(e)); + if (lb_is_type_trivial(type)) { + e = unparen_expr(e); + TypeAndValue tav = type_and_value_of_expr(e); + if (tav.mode == Addressing_Constant) { + return true; + } + if (e->kind == Ast_Ident) { + return true; + } + if (e->kind == Ast_SelectorExpr) { + Ast *operand = unparen_expr(e->SelectorExpr.expr); + if (operand && operand->kind == Ast_Ident) { + // If the operand is a pointer, thus deferences it, disallow it + Type *ot = type_of_expr(operand); + if (ot == nullptr || is_type_pointer(ot)) { + return false; + } + return true; + } + } + if (e->kind == Ast_UnaryExpr && e->UnaryExpr.op.kind != Token_And) { + Ast *operand = unparen_expr(e->UnaryExpr.expr); + TypeAndValue otav = type_and_value_of_expr(operand); + if (otav.mode == Addressing_Constant) { + return true; + } + if (operand->kind == Ast_Ident) { + return true; + } + } + } + return false; +} gb_internal lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, TypeAndValue const &tv) { if (arg->state_flags & StateFlag_DirectiveWasFalse) { @@ -442,6 +515,13 @@ gb_internal lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, Ty lb_start_block(p, then); return lb_emit_conv(p, lhs, type); } else { + if (lb_is_type_trivial(type) && lb_is_expr_trivial(else_expr)) { + lbValue has_value = lb_emit_try_has_value(p, rhs); + lbValue then_val = lb_emit_conv(p, lhs, type); + lbValue else_val = lb_emit_conv(p, lb_build_expr(p, else_expr), type); + return lb_emit_select(p, has_value, then_val, else_val); + } + LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; @@ -623,6 +703,18 @@ gb_internal lbValue lb_emit_count_leading_zeros(lbProcedure *p, lbValue x, Type return res; } +gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type); + +gb_internal lbValue lb_emit_count_trailing_ones(lbProcedure *p, lbValue x, Type *type) { + lbValue z = lb_emit_unary_arith(p, Token_Xor, x, type); + return lb_emit_count_trailing_zeros(p, z, type); +} + +gb_internal lbValue lb_emit_count_leading_ones(lbProcedure *p, lbValue x, Type *type) { + lbValue z = lb_emit_unary_arith(p, Token_Xor, x, type); + return lb_emit_count_leading_zeros(p, z, type); +} + gb_internal lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type) { @@ -778,7 +870,12 @@ gb_internal lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type args[5] = lb_typeid(m, dst_type); args[6] = lb_emit_conv(p, value_, t_rawptr); } - lb_emit_runtime_call(p, "type_assertion_check2", args); + + char const *name = "type_assertion_check2_contextless"; + if (p->context_stack.count > 0) { + name = "type_assertion_check2_with_context"; + } + lb_emit_runtime_call(p, name, args); } return lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 0)); @@ -852,7 +949,11 @@ gb_internal lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *ty args[5] = dst_typeid; args[6] = lb_emit_struct_ev(p, value, 0); } - lb_emit_runtime_call(p, "type_assertion_check2", args); + char const *name = "type_assertion_check2_contextless"; + if (p->context_stack.count > 0) { + name = "type_assertion_check2_with_context"; + } + lb_emit_runtime_call(p, name, args); } return lb_addr(lb_emit_struct_ep(p, v.addr, 0)); @@ -956,9 +1057,12 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t) mutex_lock(&m->types_mutex); - auto *field_remapping = map_get(&m->struct_field_remapping, cast(void *)struct_type); + // NOTE(jakub): It's very important to check the type pointer first, + // because two disctinct but similar structs can end up with the same LLVMTypeRef after interning. + // (For example struct{u16,u8} looks identical to LLVM as struct{u16,u8,u8} once padding fields are inserted.) + auto *field_remapping = map_get(&m->struct_field_remapping, cast(void *)t); if (field_remapping == nullptr) { - field_remapping = map_get(&m->struct_field_remapping, cast(void *)t); + field_remapping = map_get(&m->struct_field_remapping, cast(void *)struct_type); } mutex_unlock(&m->types_mutex); @@ -969,6 +1073,9 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t) gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { if (t->kind == Type_Struct) { + if (t->Struct.is_raw_union) { + return 0; + } auto field_remapping = lb_get_struct_remapping(m, t); return field_remapping[index]; } else if (is_type_any(t) && build_context.ptr_size == 4) { @@ -977,11 +1084,13 @@ gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { switch (index) { case 0: return 0; // data case 1: return 2; // id + default: GB_PANIC("index > 1"); } } else if (build_context.ptr_size != build_context.int_size) { switch (t->kind) { case Type_Basic: - if (t->Basic.kind != Basic_string) { + if (t->Basic.kind != Basic_string && + t->Basic.kind != Basic_string16) { break; } /*fallthrough*/ @@ -1010,6 +1119,17 @@ gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { break; } } + if (t->kind == Type_FixedCapacityDynamicArray) { + switch (index) { + case 0: return 0; // data + case 1: + if (t->FixedCapacityDynamicArray.padding_needed > 0) { + return 2; + } + return 1; + } + } + return index; } @@ -1160,6 +1280,11 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { case 0: result_type = alloc_type_pointer(t->Slice.elem); break; case 1: result_type = t_int; break; } + } else if (is_type_string16(t)) { + switch (index) { + case 0: result_type = t_u16_ptr; break; + case 1: result_type = t_int; break; + } } else if (is_type_string(t)) { switch (index) { case 0: result_type = t_u8_ptr; break; @@ -1169,6 +1294,7 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { switch (index) { case 0: result_type = t_rawptr; break; case 1: result_type = t_typeid; break; + default: GB_PANIC("index > 1"); } } else if (is_type_dynamic_array(t)) { switch (index) { @@ -1177,6 +1303,11 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { case 2: result_type = t_int; break; case 3: result_type = t_allocator; break; } + } else if (is_type_fixed_capacity_dynamic_array(t)) { + switch (index) { + case 0: result_type = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break; + case 1: result_type = t_int; break; + } } else if (is_type_map(t)) { init_map_internal_debug_types(t); Type *itp = alloc_type_pointer(t_raw_map); @@ -1273,6 +1404,12 @@ gb_internal lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { switch (t->kind) { case Type_Basic: switch (t->Basic.kind) { + case Basic_string16: + switch (index) { + case 0: result_type = t_u16_ptr; break; + case 1: result_type = t_int; break; + } + break; case Basic_string: switch (index) { case 0: result_type = t_u8_ptr; break; @@ -1336,6 +1473,12 @@ gb_internal lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { } break; + case Type_FixedCapacityDynamicArray: + switch (index) { + case 0: result_type = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break; + case 1: result_type = t_int; break; + } + case Type_Map: { init_map_internal_debug_types(t); @@ -1440,6 +1583,10 @@ gb_internal lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection e = lb_emit_struct_ep(p, e, index); break; + case Basic_string16: + e = lb_emit_struct_ep(p, e, index); + break; + default: GB_PANIC("un-gep-able type %s", type_to_string(type)); break; @@ -1495,16 +1642,27 @@ gb_internal lbValue lb_emit_array_epi(lbProcedure *p, lbValue s, isize index) { Type *t = s.type; GB_ASSERT(is_type_pointer(t)); Type *st = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); + GB_ASSERT(0 <= index); + if (is_type_fixed_capacity_dynamic_array(st)) { + lbValue data = lb_emit_struct_ep(p, s, 0); + return lb_emit_epi(p, data, index); + } + + GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); return lb_emit_epi(p, s, index); } gb_internal lbValue lb_emit_array_epi(lbModule *m, lbValue s, isize index) { Type *t = s.type; GB_ASSERT(is_type_pointer(t)); Type *st = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); GB_ASSERT(0 <= index); + if (is_type_fixed_capacity_dynamic_array(st)) { + lbValue data = lb_emit_epi(m, s, 0); + return lb_emit_epi(m, data, index); + } + + GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); return lb_emit_epi(m, s, index); } @@ -1591,14 +1749,25 @@ gb_internal lbValue lb_emit_matrix_ep(lbProcedure *p, lbValue s, lbValue row, lb return res; } - gb_internal lbValue lb_emit_matrix_ev(lbProcedure *p, lbValue s, isize row, isize column) { - Type *st = base_type(s.type); - GB_ASSERT_MSG(is_type_matrix(st), "%s", type_to_string(st)); - - lbValue value = lb_address_from_load_or_generate_local(p, s); - lbValue ptr = lb_emit_matrix_epi(p, value, row, column); - return lb_emit_load(p, ptr); + Type *t = s.type; + Type *mt = base_type(t); + GB_ASSERT_MSG(is_type_matrix(mt), "%s", type_to_string(mt)); + + isize stride_elems = matrix_type_stride_in_elems(mt); + + isize index = -1; + + if (mt->Matrix.is_row_major) { + index = column + (row * stride_elems); + } else { + index = row + (column * stride_elems); + } + + lbValue res = {}; + res.value = LLVMBuildExtractValue(p->builder, s.value, cast(unsigned)index, ""); + res.type = base_array_type(mt); + return res; } gb_internal void lb_fill_slice(lbProcedure *p, lbAddr const &slice, lbValue base_elem, lbValue len) { @@ -1624,13 +1793,53 @@ gb_internal void lb_fill_string(lbProcedure *p, lbAddr const &string, lbValue ba lb_emit_store(p, lb_emit_struct_ep(p, ptr, 1), len); } +gb_internal lbValue lb_emit_struct_iv(lbProcedure *p, lbValue agg, lbValue field, i32 index) { + Type *t = base_type(agg.type); + i32 mapped_index = lb_convert_struct_index(p->module, t, index); + lbValue res = {}; + res.value = LLVMBuildInsertValue(p->builder, agg.value, field.value, cast(unsigned)mapped_index, ""); + res.type = agg.type; + return res; +} + +gb_internal lbValue lb_build_struct_value(lbProcedure *p, Type *type, lbValue *fields, isize count) { + LLVMTypeRef llvm_type = lb_type(p->module, type); + lbValue agg = {}; + // agg.value = LLVMGetPoison(llvm_type); + agg.value = LLVMConstNull(llvm_type); + agg.type = type; + for (isize i = 0; i < count; i++) { + agg = lb_emit_struct_iv(p, agg, fields[i], cast(i32)i); + } + return agg; +} + +gb_internal lbValue lb_make_slice_value(lbProcedure *p, Type *slice_type, lbValue elem, lbValue len) { + GB_ASSERT(is_type_slice(slice_type)); + lbValue fields[2] = {elem, len}; + return lb_build_struct_value(p, slice_type, fields, 2); +} + +gb_internal lbValue lb_make_string_value(lbProcedure *p, Type *string_type, lbValue elem, lbValue len) { + GB_ASSERT(is_type_string(string_type)); + lbValue fields[2] = {elem, len}; + return lb_build_struct_value(p, string_type, fields, 2); +} + + gb_internal lbValue lb_string_elem(lbProcedure *p, lbValue string) { Type *t = base_type(string.type); + if (t->kind == Type_Basic && t->Basic.kind == Basic_string16) { + return lb_emit_struct_ev(p, string, 0); + } GB_ASSERT(t->kind == Type_Basic && t->Basic.kind == Basic_string); return lb_emit_struct_ev(p, string, 0); } gb_internal lbValue lb_string_len(lbProcedure *p, lbValue string) { Type *t = base_type(string.type); + if (t->kind == Type_Basic && t->Basic.kind == Basic_string16) { + return lb_emit_struct_ev(p, string, 1); + } GB_ASSERT_MSG(t->kind == Type_Basic && t->Basic.kind == Basic_string, "%s", type_to_string(t)); return lb_emit_struct_ev(p, string, 1); } @@ -1641,6 +1850,12 @@ gb_internal lbValue lb_cstring_len(lbProcedure *p, lbValue value) { args[0] = lb_emit_conv(p, value, t_cstring); return lb_emit_runtime_call(p, "cstring_len", args); } +gb_internal lbValue lb_cstring16_len(lbProcedure *p, lbValue value) { + GB_ASSERT(is_type_cstring16(value.type)); + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_conv(p, value, t_cstring16); + return lb_emit_runtime_call(p, "cstring16_len", args); +} gb_internal lbValue lb_array_elem(lbProcedure *p, lbValue array_ptr) { @@ -1670,6 +1885,11 @@ gb_internal lbValue lb_dynamic_array_cap(lbProcedure *p, lbValue da) { return lb_emit_struct_ev(p, da, 2); } +gb_internal lbValue lb_fixed_capacity_dynamic_array_len(lbProcedure *p, lbValue da) { + GB_ASSERT(is_type_fixed_capacity_dynamic_array(da.type)); + return lb_emit_struct_ev(p, da, 1); +} + gb_internal lbValue lb_map_len(lbProcedure *p, lbValue value) { GB_ASSERT_MSG(is_type_map(value.type) || are_types_identical(value.type, t_raw_map), "%s", type_to_string(value.type)); lbValue len = lb_emit_struct_ev(p, value, 1); @@ -1832,6 +2052,15 @@ gb_internal LLVMValueRef llvm_mask_zero(lbModule *m, unsigned count) { return LLVMConstNull(LLVMVectorType(lb_type(m, t_u32), count)); } +gb_internal LLVMValueRef llvm_mask_same(lbModule *m, unsigned value, unsigned count) { + auto iota = slice_make(temporary_allocator(), count); + for (unsigned i = 0; i < count; i++) { + iota[i] = lb_const_int(m, t_u32, value).value; + } + return LLVMConstVector(iota.data, count); +} + + #define LLVM_VECTOR_DUMMY_VALUE(type) LLVMGetUndef((type)) // #define LLVM_VECTOR_DUMMY_VALUE(type) LLVMConstNull((type)) @@ -2005,6 +2234,30 @@ gb_internal LLVMValueRef llvm_vector_mul(lbProcedure *p, LLVMValueRef a, LLVMVal return LLVMBuildFMul(p->builder, a, b, ""); } +gb_internal LLVMValueRef llvm_vector_mul_pairwise_reduce_add(lbProcedure *p, Slice const &a, Slice const &b) { + GB_ASSERT(a.count == b.count); + + auto temps = slice_make(temporary_allocator(), a.count); + for (unsigned i = 0; i < a.count; i++) { + temps[i] = llvm_vector_mul(p, a[i], b[i]); + } + + unsigned k = cast(unsigned)a.count; + while (k > 1) { + unsigned half = k/2; + for (unsigned j = 0; j < half; j++) { + temps[j] = llvm_vector_add(p, temps[2*j + 0], temps[2*j + 1]); + } + + if ((k&1) != 0) { + temps[half] = temps[k-1]; + } + k = (k+1)/2; + } + + return temps[0]; +} + gb_internal LLVMValueRef llvm_vector_dot(lbProcedure *p, LLVMValueRef a, LLVMValueRef b) { return llvm_vector_reduce_add(p, llvm_vector_mul(p, a, b)); @@ -2044,15 +2297,14 @@ gb_internal LLVMValueRef llvm_vector_mul_add(lbProcedure *p, LLVMValueRef a, LLV } } + gb_internal LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, String const &clobbers, bool has_side_effects=true, bool is_align_stack=false, LLVMInlineAsmDialect dialect=LLVMInlineAsmDialectATT) { return LLVMGetInlineAsm(func_type, cast(char *)str.text, cast(size_t)str.len, cast(char *)clobbers.text, cast(size_t)clobbers.len, has_side_effects, is_align_stack, - dialect - #if LLVM_VERSION_MAJOR >= 13 - , /*CanThrow*/false - #endif + dialect, + /*CanThrow*/false ); } @@ -2217,6 +2469,431 @@ gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) { return lb_handle_objc_ivar_for_objc_object_pointer(p, self); } +gb_internal void lb_create_objc_block_helper_procs( + lbModule *m, LLVMTypeRef block_lit_type, isize capture_field_offset, isize block_id, + Slice capture_values, Slice objc_object_indices, + lbProcedure *&out_copy_helper, lbProcedure *&out_dispose_helper +) { + gbString copy_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$%s::objc_block_copy_helper_%lld", m->module_name, block_id); + gbString dispose_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$%s::objc_block_dispose_helper_%lld", m->module_name, block_id); + + // copy: Block_Literal *dst, Block_Literal *src, i32 field_apropos + // dispose: Block_Literal *src, i32 field_apropos + Type *types[3] = { t_rawptr, t_rawptr, t_i32 }; + + Type *copy_tuple = alloc_type_tuple_from_field_types(types, 3, false, true); + Type *dispose_tuple = alloc_type_tuple_from_field_types(&types[1], 2, false, true); + + Type *copy_proc_type = alloc_type_proc(nullptr, copy_tuple, 3, nullptr, 0, false, ProcCC_CDecl); + Type *dispose_proc_type = alloc_type_proc(nullptr, dispose_tuple, 2, nullptr, 0, false, ProcCC_CDecl); + + lbProcedure *copy_proc = lb_create_dummy_procedure(m, make_string((u8*)copy_helper_name, gb_string_length(copy_helper_name)), copy_proc_type); + lbProcedure *dispose_proc = lb_create_dummy_procedure(m, make_string((u8*)dispose_helper_name, gb_string_length(dispose_helper_name)), dispose_proc_type); + LLVMSetLinkage(copy_proc->value, LLVMPrivateLinkage); + LLVMSetLinkage(dispose_proc->value, LLVMPrivateLinkage); + + + const int BLOCK_FIELD_IS_OBJECT = 3; // id, NSObject, __attribute__((NSObject)), block, ... + const int BLOCK_FIELD_IS_BLOCK = 7; // a block variable + + Type *block_base_type = find_core_type(m->info->checker, str_lit("Objc_Block")); + + auto is_object_objc_block = [](Type *type, Type *block_base_type) -> bool { + + Type *base = base_type(type_deref(type)); + GB_ASSERT(base->kind == Type_Struct); + + while (is_type_polymorphic_record_specialized(base)) { + if (base->Struct.polymorphic_parent) { + base = base->Struct.polymorphic_parent; + + if (base == block_base_type) { + return true; + } + base = base_type(base); + GB_ASSERT(base->kind == Type_Struct); + } + } + + return false; + }; + + lb_begin_procedure_body(copy_proc); + lb_begin_procedure_body(dispose_proc); + { + for (isize object_index : objc_object_indices) { + const auto field_offset = unsigned(capture_field_offset+object_index); + + Type *field_type = capture_values[object_index].type; + LLVMTypeRef field_raw_type = lb_type(m, field_type); + + GB_ASSERT(is_type_objc_object(field_type)); + bool is_block_obj = is_object_objc_block(field_type, block_base_type); + + auto copy_args = array_make(temporary_allocator(), 3, 3); + auto dispose_args = array_make(temporary_allocator(), 2, 2); + + // Copy helper + { + LLVMValueRef dst_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[0], field_offset, ""); + LLVMValueRef src_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[1], field_offset, ""); + + lbValue dst_value = {}, src_value = {}; + dst_value.type = alloc_type_pointer(field_type); + dst_value.value = dst_field; + + src_value.type = field_type; + src_value.value = LLVMBuildLoad2(copy_proc->builder, field_raw_type, src_field, ""); + + copy_args[0] = dst_value; + copy_args[1] = src_value; + copy_args[2] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT)); + + lb_emit_runtime_call(copy_proc, "_Block_object_assign", copy_args); + } + + // Dispose helper + { + LLVMValueRef src_field = LLVMBuildStructGEP2(dispose_proc->builder, block_lit_type, dispose_proc->raw_input_parameters[0], field_offset, ""); + lbValue src_value = {}; + src_value.type = field_type; + src_value.value = LLVMBuildLoad2(dispose_proc->builder, field_raw_type, src_field, ""); + + dispose_args[0] = src_value; + dispose_args[1] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT)); + + lb_emit_runtime_call(dispose_proc, "_Block_object_dispose", dispose_args); + } + } + } + lb_end_procedure_body(copy_proc); + lb_end_procedure_body(dispose_proc); + + + out_copy_helper = copy_proc; + out_dispose_helper = dispose_proc; +} + +gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { + /// #See: https://clang.llvm.org/docs/Block-ABI-Apple.html + /// https://www.newosxbook.com/src.php?tree=xnu&file=/libkern/libkern/Block_private.h + /// https://github.com/llvm/llvm-project/blob/21f1f9558df3830ffa637def364e3c0cb0dbb3c0/compiler-rt/lib/BlocksRuntime/Block_private.h + /// https://github.com/apple-oss-distributions/libclosure/blob/3668b0837f47be3cc1c404fb5e360f4ff178ca13/runtime.cpp + ast_node(ce, CallExpr, expr); + GB_ASSERT(ce->args.count > 0); + + lbModule *m = p->module; + + const isize block_id = m->objc_next_block_id++; + const isize capture_arg_count = ce->args.count - 1; + + Type *block_result_type = type_of_expr(expr); + GB_ASSERT(block_result_type != nullptr && block_result_type->kind == Type_Pointer); + + LLVMTypeRef lb_type_rawptr = lb_type(m, t_rawptr); + LLVMTypeRef lb_type_i32 = lb_type(m, t_i32); + LLVMTypeRef lb_type_int = lb_type(m, t_int); + + // Build user proc + // Type * user_proc_type = type_of_expr(ce->args[capture_arg_count]); + lbValue user_proc_value = lb_build_expr(p, ce->args[capture_arg_count]); + auto& user_proc = user_proc_value.type->Proc; + GB_ASSERT(user_proc_value.type->kind == Type_Proc); + + const bool is_global = capture_arg_count == 0 && user_proc.calling_convention != ProcCC_Odin; + const isize block_forward_args = user_proc.param_count - capture_arg_count; + const isize capture_fields_offset = user_proc.calling_convention != ProcCC_Odin ? 5 : 6; + + Ast *proc_lit = unparen_expr(ce->args[capture_arg_count]); + if (proc_lit->kind == Ast_Ident) { + proc_lit = proc_lit->Ident.entity.load()->decl_info->proc_lit; + } + GB_ASSERT(proc_lit->kind == Ast_ProcLit); + + lbProcedure *copy_helper = {}, *dispose_helper = {}; + + // Build captured arguments & collect the ones that are Objective-C objects + auto captured_values = array_make(temporary_allocator(), capture_arg_count, capture_arg_count); + auto objc_captures = array_make(temporary_allocator()); + + for (isize i = 0; i < capture_arg_count; i++) { + captured_values[i] = lb_build_expr(p, ce->args[i]); + + if (is_type_pointer(captured_values[i].type) && is_type_objc_object(captured_values[i].type)) { + array_add(&objc_captures, i); + } + } + + const bool has_objc_fields = objc_captures.count > 0; + + + // Create proc with the block signature + // (takes a block literal pointer as the first parameter, followed by any expected ones from the user's proc) + gbString block_invoker_name = gb_string_append_fmt(gb_string_make(permanent_allocator(), ""), "__$%s::objc_block_invoker_%lld", m->module_name, block_id); + + // Add + 1 because the first parameter received is the block literal pointer itself + auto invoker_args = array_make(temporary_allocator(), block_forward_args + 1, block_forward_args + 1); + invoker_args[0] = t_rawptr; + + GB_ASSERT(block_forward_args <= user_proc.param_count); + if (user_proc.param_count > 0) { + Slice user_proc_param_types = user_proc.params->Tuple.variables; + for (isize i = 0; i < block_forward_args; i++) { + invoker_args[i+1] = user_proc_param_types[i]->type; + } + } + + GB_ASSERT(user_proc.result_count <= 1); + + Type *invoker_args_tuple = alloc_type_tuple_from_field_types(invoker_args.data, invoker_args.count, false, true); + Type *invoker_results_tuple = nullptr; + if (user_proc.result_count > 0) { + invoker_results_tuple = alloc_type_tuple_from_field_types(&user_proc.results->Tuple.variables[0]->type, 1, false, true); + } + + Type *invoker_proc_type = alloc_type_proc(nullptr, invoker_args_tuple, invoker_args_tuple->Tuple.variables.count, + invoker_results_tuple, user_proc.result_count, false, ProcCC_CDecl); + + lbProcedure *invoker_proc = lb_create_dummy_procedure(m, make_string((u8*)block_invoker_name, + gb_string_length(block_invoker_name)), invoker_proc_type); + + LLVMSetLinkage(invoker_proc->value, LLVMPrivateLinkage); + lb_add_function_type_attributes(invoker_proc->value, lb_get_function_type(m, invoker_proc_type), ProcCC_CDecl); + + // Create the block descriptor and block literal + gbString block_lit_type_name = gb_string_make(temporary_allocator(), ""); + block_lit_type_name = gb_string_append_fmt(block_lit_type_name, "__$%s::ObjC_Block_Literal_%lld", m->module_name, block_id); + + gbString block_desc_type_name = gb_string_make(temporary_allocator(), ""); + block_desc_type_name = gb_string_append_fmt(block_desc_type_name, "__$%s::ObjC_Block_Descriptor_%lld", m->module_name,block_id); + + LLVMTypeRef block_lit_type = {}; + LLVMTypeRef block_desc_type = {}; + LLVMValueRef block_desc_initializer = {}; + + { + block_desc_type = LLVMStructCreateNamed(m->ctx, block_desc_type_name); + + LLVMTypeRef fields_types[4] = { + lb_type_int, // Reserved + lb_type_int, // Block size + lb_type_rawptr, // Copy helper func pointer + lb_type_rawptr, // Dispose helper func pointer + }; + + LLVMStructSetBody(block_desc_type, fields_types, has_objc_fields ? 4 : 2, false); + } + + { + block_lit_type = LLVMStructCreateNamed(m->ctx, block_lit_type_name); + + auto fields = array_make(temporary_allocator()); + + array_add(&fields, lb_type_rawptr); // isa + array_add(&fields, lb_type_i32); // flags + array_add(&fields, lb_type_i32); // reserved + array_add(&fields, lb_type_rawptr); // invoke + array_add(&fields, block_desc_type); // descriptor + + if (user_proc.calling_convention == ProcCC_Odin) { + array_add(&fields, lb_type(m, t_context)); // context + } + + // From here on, fields for the captured vars are added + for (lbValue cap_arg : captured_values) { + array_add(&fields, lb_type(m, cap_arg.type)); + } + + LLVMStructSetBody(block_lit_type, fields.data, (unsigned)fields.count, false); + } + + // Generate copy and dispose helper functions for captured params that are Objective-C objects (or a Block) + if (has_objc_fields) { + lb_create_objc_block_helper_procs(m, block_lit_type, capture_fields_offset, block_id, + slice(captured_values, 0, captured_values.count), + slice(objc_captures, 0, objc_captures.count), + copy_helper, dispose_helper); + } + + { + LLVMValueRef fields_values[4] = { + lb_const_int(m, t_int, 0).value, // Reserved + lb_const_int(m, t_int, u64(lb_sizeof(block_lit_type))).value, // Block size + has_objc_fields ? copy_helper->value : nullptr, // Copy helper + has_objc_fields ? dispose_helper->value : nullptr, // Dispose helper + }; + + block_desc_initializer = LLVMConstNamedStruct(block_desc_type, fields_values, has_objc_fields ? 4 : 2); + } + + // Create global block descriptor + gbString desc_global_name = gb_string_make(temporary_allocator(), ""); + desc_global_name = gb_string_append_fmt(desc_global_name, "__$%s::objc_block_desc_%lld", m->module_name, block_id); + + LLVMValueRef p_descriptor = LLVMAddGlobal(m->mod, block_desc_type, desc_global_name); + LLVMSetInitializer(p_descriptor, block_desc_initializer); + + + /// Invoker body + lb_begin_procedure_body(invoker_proc); + { + // Reserve 2 extra arguments for: Indirect return values and context. + auto call_args = array_make(temporary_allocator(), 0, user_proc.param_count + 2); + + isize block_literal_arg_index = 0; + + lbFunctionType* user_proc_ft = lb_get_function_type(m, user_proc_value.type); + + lbArgKind return_kind = {}; + + GB_ASSERT(user_proc.result_count <= 1); + if (user_proc.result_count > 0) { + return_kind = user_proc_ft->ret.kind; + + if (return_kind == lbArg_Indirect) { + // Forward indirect return value + array_add(&call_args, invoker_proc->raw_input_parameters[0]); + block_literal_arg_index = 1; + } + } + + // Forward raw arguments + for (isize i = block_literal_arg_index+1; i < invoker_proc->raw_input_parameters.count; i++) { + array_add(&call_args, invoker_proc->raw_input_parameters[i]); + } + + LLVMValueRef block_literal = invoker_proc->raw_input_parameters[block_literal_arg_index]; + + // Copy capture parameters from the block literal + isize capture_arg_in_user_proc_start_index = user_proc_ft->args.count - capture_arg_count; + if (user_proc.calling_convention == ProcCC_Odin) { + capture_arg_in_user_proc_start_index -= 1; + } + + for (isize i = 0; i < capture_arg_count; i++) { + LLVMValueRef cap_value = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, unsigned(capture_fields_offset + i), ""); + + // Don't emit load if indirect. Pass the pointer as-is + isize cap_arg_index_in_user_proc = capture_arg_in_user_proc_start_index + i; + + if (user_proc_ft->args[cap_arg_index_in_user_proc].kind != lbArg_Indirect) { + cap_value = OdinLLVMBuildLoad(invoker_proc, lb_type(invoker_proc->module, captured_values[i].type), cap_value); + } + + array_add(&call_args, cap_value); + } + + // Push context, if needed + if (user_proc.calling_convention == ProcCC_Odin) { + LLVMValueRef p_context = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, 5, "context"); + array_add(&call_args, p_context); + } + + LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(m, user_proc_value.type); + LLVMValueRef ret_val = LLVMBuildCall2(invoker_proc->builder, fnp, user_proc_value.value, call_args.data, (unsigned)call_args.count, ""); + + if (user_proc.result_count > 0 && return_kind != lbArg_Indirect) { + LLVMBuildRet(invoker_proc->builder, ret_val); + } + else { + LLVMBuildRetVoid(invoker_proc->builder); + } + } + lb_end_procedure_body(invoker_proc); + + + /// Create local block literal + const int BLOCK_HAS_COPY_DISPOSE = (1 << 25); + const int BLOCK_IS_GLOBAL = (1 << 28); + + int raw_flags = is_global ? BLOCK_IS_GLOBAL : 0; + if (has_objc_fields) { + raw_flags |= BLOCK_HAS_COPY_DISPOSE; + } + + gbString block_var_name = gb_string_make(temporary_allocator(), "__$objc_block_literal_"); + block_var_name = gb_string_append_fmt(block_var_name, "%lld", block_id); + + lbValue block_result = {}; + block_result.type = block_result_type; + + lbValue isa_val = lb_find_runtime_value(m, is_global ? str_lit("_NSConcreteGlobalBlock") : str_lit("_NSConcreteStackBlock")); + lbValue flags_val = lb_const_int(m, t_i32, (u64)raw_flags); + lbValue reserved_val = lb_const_int(m, t_i32, 0); + + if (is_global) { + LLVMValueRef p_block_lit = LLVMAddGlobal(m->mod, block_lit_type, block_var_name); + block_result.value = p_block_lit; + + LLVMValueRef fields_values[5] = { + isa_val.value, // isa + flags_val.value, // flags + reserved_val.value, // reserved + invoker_proc->value, // invoke + p_descriptor // descriptor + }; + + LLVMValueRef g_block_lit_initializer = LLVMConstNamedStruct(block_lit_type, fields_values, gb_count_of(fields_values)); + LLVMSetInitializer(p_block_lit, g_block_lit_initializer); + + } else { + LLVMValueRef p_block_lit = llvm_alloca(p, block_lit_type, lb_alignof(block_lit_type), block_var_name); + block_result.value = p_block_lit; + + // Initialize it + LLVMValueRef f_isa = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 0, "isa"); + LLVMValueRef f_flags = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 1, "flags"); + LLVMValueRef f_reserved = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 2, "reserved"); + LLVMValueRef f_invoke = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 3, "invoke"); + LLVMValueRef f_descriptor = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 4, "descriptor"); + + LLVMBuildStore(p->builder, isa_val.value, f_isa); + LLVMBuildStore(p->builder, flags_val.value, f_flags); + LLVMBuildStore(p->builder, reserved_val.value, f_reserved); + LLVMBuildStore(p->builder, invoker_proc->value, f_invoke); + LLVMBuildStore(p->builder, p_descriptor, f_descriptor); + + // Store current context, if there is one + if (user_proc.calling_convention == ProcCC_Odin) { + LLVMValueRef f_context = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 5, "context"); + lbAddr p_current_context = lb_find_or_generate_context_ptr(p); + + LLVMValueRef context_size = LLVMConstInt(LLVMInt64TypeInContext(m->ctx), (u64)lb_sizeof(lb_type(m, t_context)), false); + LLVMBuildMemCpy(p->builder, f_context, lb_try_get_alignment(f_context, 1), + p_current_context.addr.value, lb_try_get_alignment(p_current_context.addr.value, 1), context_size); + } + + // Store captured args into the block + for (isize i = 0; i < captured_values.count; i++) { + lbValue capture_arg = captured_values[i]; + + unsigned field_index = unsigned(capture_fields_offset + i); + LLVMValueRef f_capture = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, field_index, "capture_arg"); + + lbValue f_capture_val = {}; + f_capture_val.type = alloc_type_pointer(capture_arg.type); + f_capture_val.value = f_capture; + + lb_emit_store(p, f_capture_val, capture_arg); + } + } + + return block_result; +} + +gb_internal lbValue lb_handle_objc_block_invoke(lbProcedure *p, Ast *expr) { + return {}; +} + +gb_internal lbValue lb_handle_objc_super(lbProcedure *p, Ast *expr) { + ast_node(ce, CallExpr, expr); + GB_ASSERT(ce->args.count == 1); + + // NOTE(harold): This doesn't actually do anything by itself, + // it has an effect when used on the left side of a selector call expression. + return lb_build_expr(p, ce->args[0]); +} + gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { ast_node(ce, CallExpr, expr); @@ -2330,6 +3007,124 @@ gb_internal lbValue lb_handle_objc_send(lbProcedure *p, Ast *expr) { return lb_emit_call(p, the_proc, args); } +gb_internal lbValue lb_handle_objc_auto_send(lbProcedure *p, Ast *expr, Slice const arg_values) { + ast_node(ce, CallExpr, expr); + + lbModule *m = p->module; + CheckerInfo *info = m->info; + ObjcMsgData data = map_must_get(&info->objc_msgSend_types, expr); + + Type *proc_type = data.proc_type; + GB_ASSERT(proc_type != nullptr); + + Entity *objc_method_ent = entity_of_node(ce->proc); + GB_ASSERT(objc_method_ent != nullptr); + GB_ASSERT(objc_method_ent->kind == Entity_Procedure); + GB_ASSERT(objc_method_ent->Procedure.objc_selector_name.len > 0); + + auto &proc = proc_type->Proc; + GB_ASSERT(proc.param_count >= 2); + + Type *objc_super_orig_type = nullptr; + if (ce->args.count > 0) { + objc_super_orig_type = unparen_expr(ce->args[0])->tav.objc_super_target; + } + + isize arg_offset = 1; + lbValue id = {}; + if (!objc_method_ent->Procedure.is_objc_class_method) { + GB_ASSERT(ce->args.count > 0); + id = arg_values[0]; + + if (objc_super_orig_type) { + GB_ASSERT(objc_super_orig_type->kind == Type_Named); + + auto& tn = objc_super_orig_type->Named.type_name->TypeName; + lbAddr p_supercls = lb_handle_objc_find_or_register_class(p, tn.objc_class_name, tn.objc_is_implementation ? objc_super_orig_type : nullptr); + + lbValue supercls = lb_addr_load(p, p_supercls); + lbAddr p_objc_super = lb_add_local_generated(p, t_objc_super, false); + + lbValue f_id = lb_emit_struct_ep(p, p_objc_super.addr, 0); + lbValue f_superclass = lb_emit_struct_ep(p, p_objc_super.addr, 1); + + id = lb_emit_conv(p, id, t_objc_id); + lb_emit_store(p, f_id, id); + lb_emit_store(p, f_superclass, supercls); + + id = p_objc_super.addr; + } + } else { + Entity *objc_class = objc_method_ent->Procedure.objc_class; + if (ce->proc->kind == Ast_SelectorExpr) { + // NOTE (harold): If called via a selector expression (ex: Foo.alloc()), then we should use + // the lhs-side to determine the class. This allows for class methods to be called + // with the correct class as the target, even when the method is defined in a superclass. + ast_node(se, SelectorExpr, ce->proc); + GB_ASSERT(se->expr->tav.mode == Addressing_Type && se->expr->tav.type->kind == Type_Named); + + objc_class = entity_from_expr(se->expr); + GB_ASSERT(objc_class); + GB_ASSERT(objc_class->kind == Entity_TypeName); + + if (objc_class->TypeName.is_type_alias) { + objc_class = objc_class->type->Named.type_name; + } + + GB_ASSERT(objc_class->TypeName.objc_class_name != ""); + } + + Type *class_impl_type = objc_class->TypeName.objc_is_implementation ? objc_class->type : nullptr; + + id = lb_addr_load(p, lb_handle_objc_find_or_register_class(p, objc_class->TypeName.objc_class_name, class_impl_type)); + arg_offset = 0; + } + + lbValue sel = lb_addr_load(p, lb_handle_objc_find_or_register_selector(p, objc_method_ent->Procedure.objc_selector_name)); + + auto args = array_make(permanent_allocator(), 0, arg_values.count + 2 - arg_offset); + + array_add(&args, id); + array_add(&args, sel); + + for (isize i = arg_offset; i < ce->args.count; i++) { + array_add(&args, arg_values[i]); + } + + lbValue the_proc = {}; + + if (!objc_super_orig_type) { + switch (data.kind) { + default: + GB_PANIC("unhandled ObjcMsgKind %u", data.kind); + break; + case ObjcMsg_normal: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend")); break; + case ObjcMsg_fpret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_fpret")); break; + case ObjcMsg_fp2ret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_fp2ret")); break; + case ObjcMsg_stret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_stret")); break; + } + } else { + switch (data.kind) { + default: + GB_PANIC("unhandled ObjcMsgKind %u", data.kind); + break; + case ObjcMsg_normal: + case ObjcMsg_fpret: + case ObjcMsg_fp2ret: + the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSendSuper2")); + break; + case ObjcMsg_stret: + the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSendSuper2_stret")); + break; + } + } + + the_proc = lb_emit_conv(p, the_proc, data.proc_type); + + return lb_emit_call(p, the_proc, args); +} + + gb_internal LLVMAtomicOrdering llvm_atomic_ordering_from_odin(ExactValue const &value) { GB_ASSERT(value.kind == ExactValue_Integer); i64 v = exact_value_to_i64(value); @@ -2350,3 +3145,292 @@ gb_internal LLVMAtomicOrdering llvm_atomic_ordering_from_odin(Ast *expr) { ExactValue value = type_and_value_of_expr(expr).value; return llvm_atomic_ordering_from_odin(value); } + + + +struct lbDiagParaPolyEntry { + Entity *entity; + String canonical_name; + isize count; + isize total_code_size; +}; + +gb_internal isize lb_total_code_size(lbProcedure *p) { + isize instruction_count = 0; + + LLVMBasicBlockRef first = LLVMGetFirstBasicBlock(p->value); + + for (LLVMBasicBlockRef block = first; block != nullptr; block = LLVMGetNextBasicBlock(block)) { + for (LLVMValueRef instr = LLVMGetFirstInstruction(block); instr != nullptr; instr = LLVMGetNextInstruction(instr)) { + instruction_count += 1; + } + } + return instruction_count; + +} + +gb_internal void lb_do_para_poly_diagnostics(lbGenerator *gen) { + PtrMap procs = {}; + map_init(&procs); + defer (map_destroy(&procs)); + + for (auto &entry : gen->modules) { + lbModule *m = entry.value; + for (lbProcedure *p : m->generated_procedures) { + Entity *e = p->entity; + if (e == nullptr) { + continue; + } + if (p->builder == nullptr) { + continue; + } + + DeclInfo *d = e->decl_info; + Entity *para_poly_parent = d->para_poly_original; + if (para_poly_parent == nullptr) { + continue; + } + + lbDiagParaPolyEntry *entry = map_get(&procs, para_poly_parent); + if (entry == nullptr) { + lbDiagParaPolyEntry entry = {}; + entry.entity = para_poly_parent; + entry.count = 0; + + + gbString w = string_canonical_entity_name(permanent_allocator(), entry.entity); + String name = make_string_c(w); + + for (isize i = 0; i < name.len; i++) { + String s = substring(name, i, name.len); + if (string_starts_with(s, str_lit(":proc"))) { + name = substring(name, 0, i); + break; + } + } + + entry.canonical_name = name; + + map_set(&procs, para_poly_parent, entry); + } + entry = map_get(&procs, para_poly_parent); + GB_ASSERT(entry != nullptr); + entry->count += 1; + entry->total_code_size += lb_total_code_size(p); + } + } + + + auto entries = array_make(heap_allocator(), 0, procs.count); + defer (array_free(&entries)); + + for (auto &entry : procs) { + array_add(&entries, entry.value); + } + + array_sort(entries, [](void const *a, void const *b) -> int { + lbDiagParaPolyEntry *x = cast(lbDiagParaPolyEntry *)a; + lbDiagParaPolyEntry *y = cast(lbDiagParaPolyEntry *)b; + if (x->total_code_size > y->total_code_size) { + return -1; + } + if (x->total_code_size < y->total_code_size) { + return +1; + } + return string_compare(x->canonical_name, y->canonical_name); + }); + + + gb_printf("Parametric Polymorphic Procedure Diagnostics\n"); + gb_printf("------------------------------------------------------------------------------------------\n"); + + gb_printf("Sorted by Total Instruction Count Descending (Top 100)\n\n"); + gb_printf("Total Instruction Count | Instantiation Count | Average Instruction Count | Procedure Name\n"); + + isize max_count = 100; + for (auto &entry : entries) { + isize code_size = entry.total_code_size; + isize count = entry.count; + String name = entry.canonical_name; + + f64 average = cast(f64)code_size / cast(f64)gb_max(count, 1); + + gb_printf("%23td | %19td | %25.2f | %.*s\n", code_size, count, average, LIT(name)); + if (max_count-- <= 0) { + break; + } + } + + gb_printf("------------------------------------------------------------------------------------------\n"); + + array_sort(entries, [](void const *a, void const *b) -> int { + lbDiagParaPolyEntry *x = cast(lbDiagParaPolyEntry *)a; + lbDiagParaPolyEntry *y = cast(lbDiagParaPolyEntry *)b; + if (x->count > y->count) { + return -1; + } + if (x->count < y->count) { + return +1; + } + + return string_compare(x->canonical_name, y->canonical_name); + }); + + gb_printf("Sorted by Total Instantiation Count Descending (Top 100)\n\n"); + gb_printf("Instantiation Count | Total Instruction Count | Average Instruction Count | Procedure Name\n"); + + max_count = 100; + for (auto &entry : entries) { + isize code_size = entry.total_code_size; + isize count = entry.count; + String name = entry.canonical_name; + + + f64 average = cast(f64)code_size / cast(f64)gb_max(count, 1); + + gb_printf("%19td | %23td | %25.2f | %.*s\n", count, code_size, average, LIT(name)); + if (max_count-- <= 0) { + break; + } + } + + gb_printf("------------------------------------------------------------------------------------------\n"); + + + array_sort(entries, [](void const *a, void const *b) -> int { + lbDiagParaPolyEntry *x = cast(lbDiagParaPolyEntry *)a; + lbDiagParaPolyEntry *y = cast(lbDiagParaPolyEntry *)b; + if (x->count < y->count) { + return -1; + } + if (x->count > y->count) { + return +1; + } + + if (x->total_code_size > y->total_code_size) { + return -1; + } + if (x->total_code_size < y->total_code_size) { + return +1; + } + + return string_compare(x->canonical_name, y->canonical_name); + }); + + gb_printf("Single Instanced Parametric Polymorphic Procedures\n\n"); + gb_printf("Instruction Count | Procedure Name\n"); + for (auto &entry : entries) { + isize code_size = entry.total_code_size; + isize count = entry.count; + String name = entry.canonical_name; + if (count != 1) { + break; + } + + gb_printf("%17td | %.*s\n", code_size, LIT(name)); + } + +} + +struct lbDiagModuleEntry { + lbModule *m; + String name; + isize global_internal_count; + isize global_external_count; + isize proc_internal_count; + isize proc_external_count; + isize total_instruction_count; +}; + +gb_internal void lb_do_module_diagnostics(lbGenerator *gen) { + Array modules = {}; + array_init(&modules, heap_allocator()); + defer (array_free(&modules)); + + for (auto &em : gen->modules) { + lbModule *m = em.value; + + { + lbDiagModuleEntry entry = {}; + entry.m = m; + entry.name = make_string_c(m->module_name); + array_add(&modules, entry); + } + lbDiagModuleEntry &entry = modules[modules.count-1]; + + for (LLVMValueRef p = LLVMGetFirstFunction(m->mod); p != nullptr; p = LLVMGetNextFunction(p)) { + LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(p); + if (block == nullptr) { + entry.proc_external_count += 1; + } else { + entry.proc_internal_count += 1; + + for (; block != nullptr; block = LLVMGetNextBasicBlock(block)) { + for (LLVMValueRef i = LLVMGetFirstInstruction(block); i != nullptr; i = LLVMGetNextInstruction(i)) { + entry.total_instruction_count += 1; + } + } + } + } + + for (LLVMValueRef g = LLVMGetFirstGlobal(m->mod); g != nullptr; g = LLVMGetNextGlobal(g)) { + LLVMLinkage linkage = LLVMGetLinkage(g); + if (linkage == LLVMExternalLinkage) { + entry.global_external_count += 1; + } else { + entry.global_internal_count += 1; + } + } + } + + array_sort(modules, [](void const *a, void const *b) -> int { + lbDiagModuleEntry *x = cast(lbDiagModuleEntry *)a; + lbDiagModuleEntry *y = cast(lbDiagModuleEntry *)b; + + if (x->total_instruction_count > y->total_instruction_count) { + return -1; + } + if (x->total_instruction_count < y->total_instruction_count) { + return +1; + } + + return string_compare(x->name, y->name); + }); + + gb_printf("Module Diagnostics\n\n"); + gb_printf("Total Instructions | Global Internals | Global Externals | Proc Internals | Proc Externals | Files | Instructions/File | Instructions/Proc | Module Name\n"); + gb_printf("-------------------+------------------+------------------+----------------+----------------+-------+-------------------+-------------------+------------\n"); + for (auto &entry : modules) { + isize file_count = 1; + if (entry.m->file != nullptr) { + file_count = 1; + } else if (entry.m->pkg) { + file_count = entry.m->pkg->files.count; + } + + f64 instructions_per_file = cast(f64)entry.total_instruction_count / gb_max(1.0, cast(f64)file_count); + f64 instructions_per_proc = cast(f64)entry.total_instruction_count / gb_max(1.0, cast(f64)entry.proc_internal_count); + + gb_printf("%18td | %16td | %16td | %14td | %14td | %5td | %17.1f | %17.1f | %s \n", + entry.total_instruction_count, + entry.global_internal_count, + entry.global_external_count, + entry.proc_internal_count, + entry.proc_external_count, + file_count, + instructions_per_file, + instructions_per_proc, + entry.m->module_name); + } + + +} + +gb_internal void lb_do_build_diagnostics(lbGenerator *gen) { + lb_do_para_poly_diagnostics(gen); + gb_printf("------------------------------------------------------------------------------------------\n"); + gb_printf("------------------------------------------------------------------------------------------\n\n"); + lb_do_module_diagnostics(gen); + gb_printf("------------------------------------------------------------------------------------------\n"); + gb_printf("------------------------------------------------------------------------------------------\n\n"); +} diff --git a/src/main.cpp b/src/main.cpp index b2cfbe018..da0e6c5b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,6 +62,7 @@ gb_global Timings global_timings = {0}; #else #include #include +#include #endif #include "parser.hpp" @@ -76,16 +77,6 @@ gb_global Timings global_timings = {0}; #include "linker.cpp" #include "bundle_command.cpp" -#if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) -#define ALLOW_TILDE 1 -#else -#define ALLOW_TILDE 0 -#endif - -#if ALLOW_TILDE -#include "tilde.cpp" -#endif - #include "llvm_backend.cpp" #include "bug_report.cpp" @@ -142,9 +133,9 @@ gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char con } wcmd = string_to_string16(permanent_allocator(), make_string(cast(u8 *)cmd_line, cmd_len-1)); - if (CreateProcessW(nullptr, wcmd.text, - nullptr, nullptr, true, 0, nullptr, nullptr, - &start_info, &pi)) { + if (CreateProcessW(nullptr, cast(wchar_t *)wcmd.text, + nullptr, nullptr, true, 0, nullptr, nullptr, + &start_info, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code); @@ -163,6 +154,8 @@ gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char con } exit_code = system(cmd_line); if (exit_on_err && WIFSIGNALED(exit_code)) { + struct rlimit limit = { 0, 0, }; + setrlimit(RLIMIT_CORE, &limit); raise(WTERMSIG(exit_code)); } if (WIFEXITED(exit_code)) { @@ -185,11 +178,44 @@ gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, return exit_code; } -gb_internal void system_must_exec_command_line_app(char const *name, char const *fmt, ...) { - va_list va; - va_start(va, fmt); - system_exec_command_line_app_internal(/* exit_on_err= */ true, name, fmt, va); - va_end(va); +#if defined(GB_SYSTEM_WINDOWS) +#include +#else +#include +extern char **environ; +#endif + +int run_subprocess(const char *name, const char **args) { +#if defined(GB_SYSTEM_WINDOWS) + return (int)_spawnv(_P_WAIT, name, args); +#else + pid_t pid; + int status; + status = posix_spawn(&pid, name, NULL, NULL, (char *const *)args, environ); + if (status != 0) { + gb_printf_err("Could not spawn subprocess: %s\n", strerror(errno)); + return -1; + } + + for (;;) { + if (waitpid(pid, &status, WUNTRACED) < 0) { + gb_printf_err("Could not wait on subprocess: (pid: %d): %s\n", pid, strerror(errno)); + return -1; + } + + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + struct rlimit limit = { 0, 0, }; + setrlimit(RLIMIT_CORE, &limit); + raise(WTERMSIG(status)); + return -1; + } else if (WIFSTOPPED(status)) { + return -1; + } + } + GB_PANIC("Subprocess failure"); +#endif } #if defined(GB_SYSTEM_WINDOWS) @@ -232,7 +258,7 @@ gb_internal Array setup_args(int argc, char const **argv) { wchar_t **wargv = command_line_to_wargv(GetCommandLineW(), &wargc); auto args = array_make(a, 0, wargc); for (isize i = 0; i < wargc; i++) { - wchar_t *warg = wargv[i]; + u16 *warg = cast(u16 *)wargv[i]; isize wlen = string16_len(warg); String16 wstr = make_string16(warg, wlen); String arg = string16_to_string(a, wstr); @@ -278,10 +304,10 @@ gb_internal void usage(String argv0, String argv1 = {}) { print_usage_line(1, " One must contain the program's entry point, all must be in the same package."); print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform."); - print_usage_line(1, "check Parses, and type checks a directory of .odin files."); + print_usage_line(1, "check Parses and type checks a directory of .odin files."); print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program."); print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); - print_usage_line(1, "doc Generates documentation on a directory of .odin files."); + print_usage_line(1, "doc Generates documentation from a directory of .odin files."); print_usage_line(1, "version Prints version."); print_usage_line(1, "report Prints information useful to reporting a bug."); print_usage_line(1, "root Prints the root path where Odin looks for the builtin collections."); @@ -302,6 +328,7 @@ enum BuildFlagKind { BuildFlag_ShowUnused, BuildFlag_ShowUnusedWithLocation, BuildFlag_ShowMoreTimings, + BuildFlag_ShowImportGraph, BuildFlag_ExportTimings, BuildFlag_ExportTimingsFile, BuildFlag_ExportDependencies, @@ -312,26 +339,29 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, + BuildFlag_KeepExecutable, BuildFlag_Target, BuildFlag_Subtarget, BuildFlag_Debug, BuildFlag_DisableAssert, BuildFlag_NoBoundsCheck, + BuildFlag_WebkitSwitchWorkaround, BuildFlag_NoTypeAssert, BuildFlag_NoDynamicLiterals, + BuildFlag_DynamicLiterals, BuildFlag_NoCRT, BuildFlag_NoRPath, BuildFlag_NoEntryPoint, - BuildFlag_UseLLD, - BuildFlag_UseRADLink, BuildFlag_Linker, BuildFlag_UseSeparateModules, BuildFlag_UseSingleModule, BuildFlag_NoThreadedChecker, BuildFlag_ShowDebugMessages, + BuildFlag_DidYouMeanLimit, BuildFlag_ShowDefineables, BuildFlag_ExportDefineables, + BuildFlag_IgnoreUnusedDefineables, BuildFlag_Vet, BuildFlag_VetShadowing, @@ -358,8 +388,11 @@ enum BuildFlagKind { BuildFlag_NoThreadLocal, BuildFlag_RelocMode, + BuildFlag_StackProtector, BuildFlag_DisableRedZone, + BuildFlag_DisableUnwind, + BuildFlag_DisallowDo, BuildFlag_DefaultToNilAllocator, BuildFlag_DefaultToPanicAllocator, @@ -368,12 +401,14 @@ enum BuildFlagKind { BuildFlag_NoRTTI, BuildFlag_DynamicMapCalls, BuildFlag_ObfuscateSourceCodeLocations, + BuildFlag_SourceCodeLocations, BuildFlag_Compact, BuildFlag_GlobalDefinitions, BuildFlag_GoToDefinitions, BuildFlag_Short, + BuildFlag_InSourceOrder, BuildFlag_AllPackages, BuildFlag_DocFormat, @@ -388,6 +423,15 @@ enum BuildFlagKind { BuildFlag_MinLinkLibs, BuildFlag_PrintLinkerFlags, + BuildFlag_ExportLinkedLibraries, + + BuildFlag_IntegerDivisionByZero, + + BuildFlag_BuildDiagnostics, + + BuildFlag_Bedrock, + BuildFlag_DisableNonConstantGlobals, + BuildFlag_DisableInitFini, // internal use only BuildFlag_InternalFastISel, @@ -398,10 +442,13 @@ enum BuildFlagKind { BuildFlag_InternalCached, BuildFlag_InternalNoInline, BuildFlag_InternalByValue, - - BuildFlag_Tilde, + BuildFlag_InternalWeakMonomorphization, + BuildFlag_InternalLLVMVerification, + BuildFlag_InternalLLVMNoSROA, + BuildFlag_InternalEnableRVO, BuildFlag_Sanitize, + BuildFlag_LTO, #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, @@ -518,6 +565,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_OptimizationMode, str_lit("o"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ShowMoreTimings, str_lit("show-more-timings"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_ShowImportGraph, str_lit("show-import-graph"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimings, str_lit("export-timings"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimingsFile, str_lit("export-timings-file"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_ExportDependencies, str_lit("export-dependencies"), BuildFlagParam_String, Command__does_build); @@ -530,27 +578,30 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message + add_flag(&build_flags, BuildFlag_KeepExecutable, str_lit("keep-executable"), BuildFlagParam_None, Command__does_build | Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_WebkitSwitchWorkaround, str_lit("webkit-switch-workaround"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoTypeAssert, str_lit("no-type-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DynamicLiterals, str_lit("dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoRPath, str_lit("no-rpath"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); - add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_UseRADLink, str_lit("radlink"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_Linker, str_lit("linker"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_UseSeparateModules, str_lit("use-separate-modules"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_UseSingleModule, str_lit("use-single-module"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoThreadedChecker, str_lit("no-threaded-checker"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ShowDebugMessages, str_lit("show-debug-messages"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_DidYouMeanLimit, str_lit("did-you-mean-limit"), BuildFlagParam_Integer, Command__does_check); add_flag(&build_flags, BuildFlag_ShowDefineables, str_lit("show-defineables"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExportDefineables, str_lit("export-defineables"), BuildFlagParam_String, Command__does_check); + add_flag(&build_flags, BuildFlag_IgnoreUnusedDefineables, str_lit("ignore-unused-defineables"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetUnused, str_lit("vet-unused"), BuildFlagParam_None, Command__does_check); @@ -576,8 +627,11 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_bundle_android); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_StackProtector, str_lit("stack-protector"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_DisableUnwind, str_lit("disable-unwind"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_DisallowDo, str_lit("disallow-do"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DefaultToNilAllocator, str_lit("default-to-nil-allocator"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DefaultToPanicAllocator, str_lit("default-to-panic-allocator"),BuildFlagParam_None, Command__does_check); @@ -590,9 +644,11 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_DynamicMapCalls, str_lit("dynamic-map-calls"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ObfuscateSourceCodeLocations, str_lit("obfuscate-source-code-locations"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_SourceCodeLocations, str_lit("source-code-locations"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc); - add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc | Command_test); + add_flag(&build_flags, BuildFlag_InSourceOrder, str_lit("in-source-order"), BuildFlagParam_None, Command_doc); + add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc | Command_test | Command_build); add_flag(&build_flags, BuildFlag_DocFormat, str_lit("doc-format"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_IgnoreWarnings, str_lit("ignore-warnings"), BuildFlagParam_None, Command_all); @@ -604,9 +660,18 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_MaxErrorCount, str_lit("max-error-count"), BuildFlagParam_Integer, Command_all); add_flag(&build_flags, BuildFlag_MinLinkLibs, str_lit("min-link-libs"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_ExportLinkedLibraries, str_lit("export-linked-libs-file"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build); + add_flag(&build_flags, BuildFlag_IntegerDivisionByZero, str_lit("integer-division-by-zero"), BuildFlagParam_String, Command__does_check); + + add_flag(&build_flags, BuildFlag_BuildDiagnostics, str_lit("build-diagnostics"), BuildFlagParam_None, Command__does_build); + + add_flag(&build_flags, BuildFlag_Bedrock, str_lit("bedrock"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DisableNonConstantGlobals, str_lit("disable-non-constant-globals"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DisableInitFini, str_lit("disable-init-fini"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_InternalFastISel, str_lit("internal-fast-isel"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); @@ -615,12 +680,14 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_InternalCached, str_lit("internal-cached"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalNoInline, str_lit("internal-no-inline"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalByValue, str_lit("internal-by-value"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalWeakMonomorphization, str_lit("internal-weak-monomorphization"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalLLVMVerification, str_lit("internal-ignore-llvm-verification"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalLLVMNoSROA, str_lit("internal-llvm-no-sroa"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalEnableRVO, str_lit("internal-enable-rvo"), BuildFlagParam_None, Command_all); -#if ALLOW_TILDE - add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); -#endif add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); + add_flag(&build_flags, BuildFlag_LTO, str_lit("lto"), BuildFlagParam_String, Command__does_build); #if defined(GB_SYSTEM_WINDOWS) @@ -846,6 +913,10 @@ gb_internal bool parse_build_flags(Array args) { build_context.show_timings = true; build_context.show_more_timings = true; break; + case BuildFlag_ShowImportGraph: + GB_ASSERT(value.kind == ExactValue_Invalid); + build_context.show_import_graph = true; + break; case BuildFlag_ExportTimings: { GB_ASSERT(value.kind == ExactValue_String); /* @@ -925,6 +996,11 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_IgnoreUnusedDefineables: { + GB_ASSERT(value.kind == ExactValue_Invalid); + build_context.ignore_unused_defineables = true; + break; + } case BuildFlag_ShowSystemCalls: { GB_ASSERT(value.kind == ExactValue_Invalid); build_context.show_system_calls = true; @@ -1045,7 +1121,7 @@ gb_internal bool parse_build_flags(Array args) { break; } - char const *key = string_intern(name); + char const *key = string_intern_cstring(name); if (map_get(&build_context.defined_values, key) != nullptr) { gb_printf_err("Defined constant '%.*s' already exists\n", LIT(name)); @@ -1191,6 +1267,9 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_KeepExecutable: + build_context.keep_executable = true; + break; case BuildFlag_Debug: build_context.ODIN_DEBUG = true; @@ -1201,12 +1280,18 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoBoundsCheck: build_context.no_bounds_check = true; break; + case BuildFlag_WebkitSwitchWorkaround: + build_context.webkit_switch_workaround = true; + break; case BuildFlag_NoTypeAssert: build_context.no_type_assert = true; break; case BuildFlag_NoDynamicLiterals: gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n"); break; + case BuildFlag_DynamicLiterals: + build_context.dynamic_literals = true; + break; case BuildFlag_NoCRT: build_context.no_crt = true; break; @@ -1219,14 +1304,6 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoThreadLocal: build_context.no_thread_local = true; break; - case BuildFlag_UseLLD: - gb_printf_err("Warning: Use of -lld has been deprecated in favour of -linker:lld\n"); - build_context.linker_choice = Linker_lld; - break; - case BuildFlag_UseRADLink: - gb_printf_err("Warning: Use of -lld has been deprecated in favour of -linker:radlink\n"); - build_context.linker_choice = Linker_radlink; - break; case BuildFlag_Linker: { GB_ASSERT(value.kind == ExactValue_String); @@ -1272,27 +1349,35 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_ShowDebugMessages: build_context.show_debug_messages = true; break; + + case BuildFlag_DidYouMeanLimit: + { + GB_ASSERT(value.kind == ExactValue_Integer); + isize count = cast(isize)big_int_to_i64(&value.value_integer); + if (count <= 0) { + gb_printf_err("%.*s expected a positive non-zero number, got %.*s\n", LIT(name), LIT(param)); + build_context.did_you_mean_limit = DEFAULT_DID_YOU_MEAN_LIMIT; + } else { + build_context.did_you_mean_limit = (int)count; + } + } + break; + case BuildFlag_Vet: build_context.vet_flags |= VetFlag_All; break; - case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; - case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; - case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; - case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; - case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; - case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; - case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; - case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; - case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; - case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; - case BuildFlag_VetUnusedProcedures: - build_context.vet_flags |= VetFlag_UnusedProcedures; - if (!set_flags[BuildFlag_VetPackages]) { - gb_printf_err("-%.*s must be used with -vet-packages\n", LIT(name)); - bad_flags = true; - } - break; + case BuildFlag_VetUnusedVariables: build_context.vet_flags |= VetFlag_UnusedVariables; break; + case BuildFlag_VetUnusedImports: build_context.vet_flags |= VetFlag_UnusedImports; break; + case BuildFlag_VetUnused: build_context.vet_flags |= VetFlag_Unused; break; + case BuildFlag_VetShadowing: build_context.vet_flags |= VetFlag_Shadowing; break; + case BuildFlag_VetUsingStmt: build_context.vet_flags |= VetFlag_UsingStmt; break; + case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; + case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; + case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; + case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; + case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; + case BuildFlag_VetUnusedProcedures: build_context.vet_flags |= VetFlag_UnusedProcedures; break; case BuildFlag_VetPackages: { @@ -1394,9 +1479,33 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_StackProtector: { + GB_ASSERT(value.kind == ExactValue_String); + String v = value.value_string; + if (v == "none") { + build_context.stack_protector = StackProtector_None; + } else if (v == "base") { + build_context.stack_protector = StackProtector_Ssp; + } else if (v == "all") { + build_context.stack_protector = StackProtector_SspReq; + } else if (v == "strong") { + build_context.stack_protector = StackProtector_SspStrong; + } else { + gb_printf_err("-stack-protector flag expected one of the following\n"); + gb_printf_err("\tnone\n"); + gb_printf_err("\tbase\n"); + gb_printf_err("\tall\n"); + gb_printf_err("\tstrong\n"); + bad_flags = true; + } + } case BuildFlag_DisableRedZone: build_context.disable_red_zone = true; break; + case BuildFlag_DisableUnwind: + build_context.disable_unwind = true; + break; + case BuildFlag_DisallowDo: build_context.disallow_do = true; break; @@ -1412,7 +1521,23 @@ gb_internal bool parse_build_flags(Array args) { break; case BuildFlag_ObfuscateSourceCodeLocations: - build_context.obfuscate_source_code_locations = true; + gb_printf_err("'-obfuscate-source-code-locations' is now deprecated in favor of '-source-code-locations:obfuscated'\n"); + build_context.source_code_location_info = SourceCodeLocationInfo_Obfuscated; + break; + + case BuildFlag_SourceCodeLocations: + if (str_eq_ignore_case(value.value_string, str_lit("normal"))) { + build_context.source_code_location_info = SourceCodeLocationInfo_Normal; + } else if (str_eq_ignore_case(value.value_string, str_lit("obfuscated"))) { + build_context.source_code_location_info = SourceCodeLocationInfo_Obfuscated; + } else if (str_eq_ignore_case(value.value_string, str_lit("filename"))) { + build_context.source_code_location_info = SourceCodeLocationInfo_Filename; + } else if (str_eq_ignore_case(value.value_string, str_lit("none"))) { + build_context.source_code_location_info = SourceCodeLocationInfo_None; + } else { + gb_printf_err("-source-code-locations: options are 'normal', 'obfuscated', 'filename', and 'none'\n"); + bad_flags = true; + } break; case BuildFlag_DefaultToNilAllocator: @@ -1439,6 +1564,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_Short: build_context.cmd_doc_flags |= CmdDocFlag_Short; break; + case BuildFlag_InSourceOrder: + build_context.cmd_doc_flags |= CmdDocFlag_InSourceOrder; + break; case BuildFlag_AllPackages: build_context.cmd_doc_flags |= CmdDocFlag_AllPackages; build_context.test_all_packages = true; @@ -1487,7 +1615,7 @@ gb_internal bool parse_build_flags(Array args) { } else if (str_eq_ignore_case(value.value_string, str_lit("unix"))) { build_context.ODIN_ERROR_POS_STYLE = ErrorPosStyle_Unix; } else { - gb_printf_err("-error-pos-style options are 'unix', 'odin' and 'default' (odin)\n"); + gb_printf_err("-error-pos-style options are 'unix', 'odin', and 'default' (odin)\n"); bad_flags = true; } break; @@ -1507,10 +1635,52 @@ gb_internal bool parse_build_flags(Array args) { build_context.min_link_libs = true; break; + case BuildFlag_ExportLinkedLibraries: + build_context.export_linked_libs_path = string_trim_whitespace(value.value_string); + if (build_context.export_linked_libs_path.len == 0) { + gb_printf_err("-%.*s specified an empty path\n", LIT(name)); + bad_flags = true; + } + break; + case BuildFlag_PrintLinkerFlags: build_context.print_linker_flags = true; break; + case BuildFlag_IntegerDivisionByZero: + GB_ASSERT(value.kind == ExactValue_String); + if (str_eq_ignore_case(value.value_string, "trap")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Trap; + } else if (str_eq_ignore_case(value.value_string, "zero")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Zero; + } else if (str_eq_ignore_case(value.value_string, "self")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Self; + } else if (str_eq_ignore_case(value.value_string, "all-bits")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_AllBits; + } else { + gb_printf_err("-integer-division-by-zero options are 'trap', 'zero', 'self', and 'all-bits'.\n"); + bad_flags = true; + } + break; + + case BuildFlag_BuildDiagnostics: + build_context.build_diagnostics = true; + break; + + case BuildFlag_Bedrock: + build_context.bedrock = true; + build_context.no_rtti = true; + build_context.disable_non_constant_globals = true; + build_context.disable_init_fini = true; + break; + + case BuildFlag_DisableNonConstantGlobals: + build_context.disable_non_constant_globals = true; + break; + case BuildFlag_DisableInitFini: + build_context.disable_init_fini = true; + break; + case BuildFlag_InternalFastISel: build_context.fast_isel = true; break; @@ -1537,14 +1707,28 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalByValue: build_context.internal_by_value = true; break; - - case BuildFlag_Tilde: - build_context.tilde_backend = true; + case BuildFlag_InternalWeakMonomorphization: + build_context.internal_weak_monomorphization = true; break; + case BuildFlag_InternalLLVMVerification: + build_context.internal_ignore_llvm_verification = true; + break; + case BuildFlag_InternalLLVMNoSROA: + build_context.internal_llvm_no_sroa = true; + break; + case BuildFlag_InternalEnableRVO: + build_context.enable_rvo = true; + break; + case BuildFlag_Sanitize: GB_ASSERT(value.kind == ExactValue_String); + if (build_context.sanitizer_flags != 0) { + gb_printf_err("-sanitize: may only be used once\n"); + bad_flags = true; + } + if (str_eq_ignore_case(value.value_string, str_lit("address"))) { build_context.sanitizer_flags |= SanitizerFlag_Address; } else if (str_eq_ignore_case(value.value_string, str_lit("memory"))) { @@ -1557,6 +1741,38 @@ gb_internal bool parse_build_flags(Array args) { } break; + case BuildFlag_LTO: + GB_ASSERT(value.kind == ExactValue_String); + if (str_eq_ignore_case(value.value_string, str_lit("thin"))) { + build_context.lto_kind = LTO_Thin; + if (build_context.linker_choice == Linker_Invalid || build_context.linker_choice == Linker_Default) { + build_context.linker_choice = Linker_lld; + } + if (!build_context.use_separate_modules) { + build_context.use_separate_modules = true; + if (build_context.use_single_module) { + gb_printf_err("-linker: cannot be used with -use-single-module\n"); + bad_flags = true; + } + } + } else if (str_eq_ignore_case(value.value_string, str_lit("thin-files"))) { + build_context.lto_kind = LTO_Thin_Files; + if (build_context.linker_choice == Linker_Invalid) { + build_context.linker_choice = Linker_lld; + } + if (!build_context.use_separate_modules) { + build_context.use_separate_modules = true; + if (build_context.use_single_module) { + gb_printf_err("-linker: cannot be used with -use-single-module\n"); + bad_flags = true; + } + } + } else { + gb_printf_err("-lto: options are 'thin' and 'thin-files'\n"); + bad_flags = true; + } + break; + #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { @@ -1617,9 +1833,9 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); String subsystem = value.value_string; bool subsystem_found = false; - for (int i = 0; i < Windows_Subsystem_COUNT; i++) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) { - build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem(i); subsystem_found = true; break; } @@ -1628,7 +1844,7 @@ gb_internal bool parse_build_flags(Array args) { // WINDOW is a hidden alias for WINDOWS. Check it. String subsystem_windows_alias = str_lit("WINDOW"); if (!subsystem_found && str_eq_ignore_case(subsystem, subsystem_windows_alias)) { - build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_WINDOWS]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_WINDOWS; subsystem_found = true; break; } @@ -1636,8 +1852,8 @@ gb_internal bool parse_build_flags(Array args) { if (!subsystem_found) { gb_printf_err("Invalid -subsystem string, got %.*s. Expected one of:\n", LIT(subsystem)); gb_printf_err("\t"); - for (int i = 0; i < Windows_Subsystem_COUNT; i++) { - if (i > 0) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { + if (i > 1) { gb_printf_err(", "); } gb_printf_err("%.*s", LIT(windows_subsystem_names[i])); @@ -1701,6 +1917,11 @@ gb_internal bool parse_build_flags(Array args) { } } + if (set_flags[BuildFlag_VetUnusedProcedures] && !set_flags[BuildFlag_VetPackages]) { + gb_printf_err("-vet-unused-procedures must be used with -vet-packages\n"); + bad_flags = true; + } + if ((!(build_context.export_timings_format == TimingsExportUnspecified)) && (build_context.export_timings_file.len == 0)) { gb_printf_err("`-export-timings:` requires `-export-timings-file:` to be specified as well\n"); bad_flags = true; @@ -1723,6 +1944,14 @@ gb_internal bool parse_build_flags(Array args) { bad_flags = true; } + + if ((build_context.command_kind & (Command_doc | Command_test)) == 0 && build_context.test_all_packages) { + gb_printf_err("`-test-all-packages` can only be used with `odin build -build-mode:test`, `odin test`, or `odin doc`.\n"); + bad_flags = true; + } + + if (build_context.did_you_mean_limit == 0) build_context.did_you_mean_limit = DEFAULT_DID_YOU_MEAN_LIMIT; + return !bad_flags; } @@ -1947,6 +2176,72 @@ gb_internal void show_defineables(Checker *c) { } } +gb_internal void show_import_graph(Checker *c) { + Parser *p = c->parser; + + gb_printf("digraph odin_import_graph {\n\tnode [shape=box];\n"); + + int cluster_counter = 0; + for (LibraryCollections coll : library_collections) { + gb_printf("\tsubgraph cluster_%i {\n", cluster_counter); + gb_printf("\t\tlabel = \"%.*s\";\n", LIT(coll.name)); + gb_printf("\t\tnode [style=filled, fillcolor=white];\n"); + if (coll.name =="core") { + gb_printf("\t\tbgcolor = lightsalmon;\n"); + } else if (coll.name =="vendor") { + gb_printf("\t\tbgcolor = lightblue;\n"); + } else if (coll.name =="base") { + gb_printf("\t\tbgcolor = lightcoral;\n"); + gb_printf("\t\tintrinsics;\n"); + gb_printf("\t\tbuiltin;\n"); + } + for (AstPackage *pkg : p->packages) { + if (string_starts_with(pkg->fullpath, coll.path)) { + gb_printf("\t\t\"%.*s\";\n", LIT(pkg->fullpath)); + } + } + gb_printf("\t}\n"); + cluster_counter += 1; + } + + for (AstPackage *pkg : p->packages) { + for (int i = 0; i < pkg->files.count; i++) { + AstFile *file = pkg->files[i]; + for(Ast *imp : file->imports) { + GB_ASSERT(imp->kind == Ast_ImportDecl); + + bool exists = false; + for (int j = i + 1; j < pkg->files.count; j++) { + AstFile *other_file = pkg->files[j]; + for(Ast *other_imp : other_file->imports) { + GB_ASSERT(other_imp->kind == Ast_ImportDecl); + if (0 == string_compare(imp->ImportDecl.fullpath, other_imp->ImportDecl.fullpath)) { + exists = true; + break; + } + } + if (exists) { + break; + } + } + + if (exists) { + continue; + } + + String path = imp->ImportDecl.fullpath; + if (imp->ImportDecl.package != nullptr) { + path = imp->ImportDecl.package->fullpath; + } + + gb_printf("\t\"%.*s\" -> \"%.*s\";\n", LIT(pkg->fullpath), LIT(path)); + } + } + } + + gb_printf("}\n\n"); +} + gb_internal void show_timings(Checker *c, Timings *t) { Parser *p = c->parser; isize lines = p->total_line_count; @@ -1975,39 +2270,39 @@ gb_internal void show_timings(Checker *c, Timings *t) { if (build_context.show_debug_messages && build_context.show_more_timings) { { - gb_printf("\n"); - gb_printf("Total Lines - %td\n", lines); - gb_printf("Total Tokens - %td\n", tokens); - gb_printf("Total Files - %td\n", files); - gb_printf("Total Packages - %td\n", packages); - gb_printf("Total File Size - %td\n", total_file_size); - gb_printf("\n"); + gb_printf_err("\n"); + gb_printf_err("Total Lines - %td\n", lines); + gb_printf_err("Total Tokens - %td\n", tokens); + gb_printf_err("Total Files - %td\n", files); + gb_printf_err("Total Packages - %td\n", packages); + gb_printf_err("Total File Size - %td\n", total_file_size); + gb_printf_err("\n"); } { f64 time = total_tokenizing_time; - gb_printf("Tokenization Only\n"); - gb_printf("LOC/s - %.3f\n", cast(f64)lines/time); - gb_printf("us/LOC - %.3f\n", 1.0e6*time/cast(f64)lines); - gb_printf("Tokens/s - %.3f\n", cast(f64)tokens/time); - gb_printf("us/Token - %.3f\n", 1.0e6*time/cast(f64)tokens); - gb_printf("bytes/s - %.3f\n", cast(f64)total_file_size/time); - gb_printf("MiB/s - %.3f\n", cast(f64)(total_file_size/time)/(1024*1024)); - gb_printf("us/bytes - %.3f\n", 1.0e6*time/cast(f64)total_file_size); + gb_printf_err("Tokenization Only\n"); + gb_printf_err("LOC/s - %.3f\n", cast(f64)lines/time); + gb_printf_err("us/LOC - %.3f\n", 1.0e6*time/cast(f64)lines); + gb_printf_err("Tokens/s - %.3f\n", cast(f64)tokens/time); + gb_printf_err("us/Token - %.3f\n", 1.0e6*time/cast(f64)tokens); + gb_printf_err("bytes/s - %.3f\n", cast(f64)total_file_size/time); + gb_printf_err("MiB/s - %.3f\n", cast(f64)(total_file_size/time)/(1024*1024)); + gb_printf_err("us/bytes - %.3f\n", 1.0e6*time/cast(f64)total_file_size); - gb_printf("\n"); + gb_printf_err("\n"); } { f64 time = total_parsing_time; - gb_printf("Parsing Only\n"); - gb_printf("LOC/s - %.3f\n", cast(f64)lines/time); - gb_printf("us/LOC - %.3f\n", 1.0e6*time/cast(f64)lines); - gb_printf("Tokens/s - %.3f\n", cast(f64)tokens/time); - gb_printf("us/Token - %.3f\n", 1.0e6*time/cast(f64)tokens); - gb_printf("bytes/s - %.3f\n", cast(f64)total_file_size/time); - gb_printf("MiB/s - %.3f\n", cast(f64)(total_file_size/time)/(1024*1024)); - gb_printf("us/bytes - %.3f\n", 1.0e6*time/cast(f64)total_file_size); + gb_printf_err("Parsing Only\n"); + gb_printf_err("LOC/s - %.3f\n", cast(f64)lines/time); + gb_printf_err("us/LOC - %.3f\n", 1.0e6*time/cast(f64)lines); + gb_printf_err("Tokens/s - %.3f\n", cast(f64)tokens/time); + gb_printf_err("us/Token - %.3f\n", 1.0e6*time/cast(f64)tokens); + gb_printf_err("bytes/s - %.3f\n", cast(f64)total_file_size/time); + gb_printf_err("MiB/s - %.3f\n", cast(f64)(total_file_size/time)/(1024*1024)); + gb_printf_err("us/bytes - %.3f\n", 1.0e6*time/cast(f64)total_file_size); - gb_printf("\n"); + gb_printf_err("\n"); } { TimeStamp ts = {}; @@ -2020,16 +2315,16 @@ gb_internal void show_timings(Checker *c, Timings *t) { GB_ASSERT(ts.label == "parse files"); f64 parse_time = time_stamp_as_s(ts, t->freq); - gb_printf("Parse pass\n"); - gb_printf("LOC/s - %.3f\n", cast(f64)lines/parse_time); - gb_printf("us/LOC - %.3f\n", 1.0e6*parse_time/cast(f64)lines); - gb_printf("Tokens/s - %.3f\n", cast(f64)tokens/parse_time); - gb_printf("us/Token - %.3f\n", 1.0e6*parse_time/cast(f64)tokens); - gb_printf("bytes/s - %.3f\n", cast(f64)total_file_size/parse_time); - gb_printf("MiB/s - %.3f\n", cast(f64)(total_file_size/parse_time)/(1024*1024)); - gb_printf("us/bytes - %.3f\n", 1.0e6*parse_time/cast(f64)total_file_size); + gb_printf_err("Parse pass\n"); + gb_printf_err("LOC/s - %.3f\n", cast(f64)lines/parse_time); + gb_printf_err("us/LOC - %.3f\n", 1.0e6*parse_time/cast(f64)lines); + gb_printf_err("Tokens/s - %.3f\n", cast(f64)tokens/parse_time); + gb_printf_err("us/Token - %.3f\n", 1.0e6*parse_time/cast(f64)tokens); + gb_printf_err("bytes/s - %.3f\n", cast(f64)total_file_size/parse_time); + gb_printf_err("MiB/s - %.3f\n", cast(f64)(total_file_size/parse_time)/(1024*1024)); + gb_printf_err("us/bytes - %.3f\n", 1.0e6*parse_time/cast(f64)total_file_size); - gb_printf("\n"); + gb_printf_err("\n"); } { TimeStamp ts = {}; @@ -2050,27 +2345,27 @@ gb_internal void show_timings(Checker *c, Timings *t) { ts.finish = ts_end.finish; f64 parse_time = time_stamp_as_s(ts, t->freq); - gb_printf("Checker pass\n"); - gb_printf("LOC/s - %.3f\n", cast(f64)lines/parse_time); - gb_printf("us/LOC - %.3f\n", 1.0e6*parse_time/cast(f64)lines); - gb_printf("Tokens/s - %.3f\n", cast(f64)tokens/parse_time); - gb_printf("us/Token - %.3f\n", 1.0e6*parse_time/cast(f64)tokens); - gb_printf("bytes/s - %.3f\n", cast(f64)total_file_size/parse_time); - gb_printf("MiB/s - %.3f\n", (cast(f64)total_file_size/parse_time)/(1024*1024)); - gb_printf("us/bytes - %.3f\n", 1.0e6*parse_time/cast(f64)total_file_size); - gb_printf("\n"); + gb_printf_err("Checker pass\n"); + gb_printf_err("LOC/s - %.3f\n", cast(f64)lines/parse_time); + gb_printf_err("us/LOC - %.3f\n", 1.0e6*parse_time/cast(f64)lines); + gb_printf_err("Tokens/s - %.3f\n", cast(f64)tokens/parse_time); + gb_printf_err("us/Token - %.3f\n", 1.0e6*parse_time/cast(f64)tokens); + gb_printf_err("bytes/s - %.3f\n", cast(f64)total_file_size/parse_time); + gb_printf_err("MiB/s - %.3f\n", (cast(f64)total_file_size/parse_time)/(1024*1024)); + gb_printf_err("us/bytes - %.3f\n", 1.0e6*parse_time/cast(f64)total_file_size); + gb_printf_err("\n"); } { f64 total_time = t->total_time_seconds; - gb_printf("Total pass\n"); - gb_printf("LOC/s - %.3f\n", cast(f64)lines/total_time); - gb_printf("us/LOC - %.3f\n", 1.0e6*total_time/cast(f64)lines); - gb_printf("Tokens/s - %.3f\n", cast(f64)tokens/total_time); - gb_printf("us/Token - %.3f\n", 1.0e6*total_time/cast(f64)tokens); - gb_printf("bytes/s - %.3f\n", cast(f64)total_file_size/total_time); - gb_printf("MiB/s - %.3f\n", cast(f64)(total_file_size/total_time)/(1024*1024)); - gb_printf("us/bytes - %.3f\n", 1.0e6*total_time/cast(f64)total_file_size); - gb_printf("\n"); + gb_printf_err("Total pass\n"); + gb_printf_err("LOC/s - %.3f\n", cast(f64)lines/total_time); + gb_printf_err("us/LOC - %.3f\n", 1.0e6*total_time/cast(f64)lines); + gb_printf_err("Tokens/s - %.3f\n", cast(f64)tokens/total_time); + gb_printf_err("us/Token - %.3f\n", 1.0e6*total_time/cast(f64)tokens); + gb_printf_err("bytes/s - %.3f\n", cast(f64)total_file_size/total_time); + gb_printf_err("MiB/s - %.3f\n", cast(f64)(total_file_size/total_time)/(1024*1024)); + gb_printf_err("us/bytes - %.3f\n", 1.0e6*total_time/cast(f64)total_file_size); + gb_printf_err("\n"); } } } @@ -2186,6 +2481,63 @@ gb_internal void export_dependencies(Checker *c) { } } +gb_internal void export_linked_libraries(LinkerData *gen) { + gbFile f = {}; + char * fileName = (char *)build_context.export_linked_libs_path.text; + gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); + if (err != gbFileError_None) { + gb_printf_err("Failed to export linked library list to: %s\n", fileName); + exit_with_errors(); + return; + } + defer (gb_file_close(&f)); + + StringSet min_libs_set = {}; + string_set_init(&min_libs_set, 64); + defer (string_set_destroy(&min_libs_set)); + + for (auto *e : gen->foreign_libraries) { + GB_ASSERT(e->kind == Entity_LibraryName); + ast_node(imp, ForeignImportDecl, e->LibraryName.decl); + + for (isize i = 0; i < e->LibraryName.paths.count; i++) { + String lib_path = string_trim_whitespace(e->LibraryName.paths[i]); + if (lib_path.len == 0) { + continue; + } + + if (string_set_update(&min_libs_set, lib_path)) { + continue; + } + + gb_fprintf(&f, "%.*s\t", LIT(lib_path)); + + String ext = path_extension(lib_path, false); + if (str_eq_ignore_case(ext, "a") || str_eq_ignore_case(ext, "lib") || + str_eq_ignore_case(ext, "o") || str_eq_ignore_case(ext, "obj") + ) { + gb_fprintf(&f, "static"); + } else { + gb_fprintf(&f, "dynamic"); + } + + gb_fprintf(&f, "\t"); + + Ast *file_path = imp->filepaths[i]; + GB_ASSERT(file_path->tav.mode == Addressing_Constant && file_path->tav.value.kind == ExactValue_String); + String file_path_str = file_path->tav.value.value_string; + + if (string_starts_with(file_path_str, str_lit("system:"))) { + gb_fprintf(&f, "system"); + } else { + gb_fprintf(&f, "user"); + } + + gb_fprintf(&f, "\n"); + } + } +} + gb_internal void remove_temp_files(lbGenerator *gen) { if (build_context.keep_temp_files) return; @@ -2221,20 +2573,30 @@ gb_internal void remove_temp_files(lbGenerator *gen) { } -gb_internal void print_show_help(String const arg0, String command, String optional_flag = {}) { +gb_internal int print_show_help(String const arg0, String command, String optional_flag = {}) { + bool help_resolved = false; + bool printed_usage_header = false; + bool printed_flags_header = false; + if (command == "help" && optional_flag.len != 0 && optional_flag[0] != '-') { command = optional_flag; optional_flag = {}; } - print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0)); - print_usage_line(0, "Usage:"); - print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command)); - print_usage_line(0, ""); - defer (print_usage_line(0, "")); - + auto const print_usage_header_once = [&help_resolved, &printed_usage_header, arg0, command]() { + if (printed_usage_header) { + return; + } + print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0)); + print_usage_line(0, "Usage:"); + print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command)); + print_usage_line(0, ""); + help_resolved = true; + printed_usage_header = true; + }; if (command == "build") { + print_usage_header_once(); print_usage_line(1, "build Compiles directory of .odin files as an executable."); print_usage_line(2, "One must contain the program's entry point, all must be in the same package."); print_usage_line(2, "Use `-file` to build a single file instead."); @@ -2243,6 +2605,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(3, "odin build Builds package in ."); print_usage_line(3, "odin build filename.odin -file Builds single-file package, must contain entry point."); } else if (command == "run") { + print_usage_header_once(); print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); print_usage_line(2, "Append an empty flag and then the args, '-- ', to specify args for the output."); print_usage_line(2, "Examples:"); @@ -2250,28 +2613,40 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(3, "odin run Builds and runs package in ."); print_usage_line(3, "odin run filename.odin -file Builds and runs single-file package, must contain entry point."); } else if (command == "check") { + print_usage_header_once(); print_usage_line(1, "check Parses and type checks directory of .odin files."); print_usage_line(2, "Examples:"); print_usage_line(3, "odin check . Type checks package in current directory."); print_usage_line(3, "odin check Type checks package in ."); print_usage_line(3, "odin check filename.odin -file Type checks single-file package, must contain entry point."); } else if (command == "test") { + print_usage_header_once(); print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); } else if (command == "doc") { + print_usage_header_once(); print_usage_line(1, "doc Generates documentation from a directory of .odin files."); print_usage_line(2, "Examples:"); print_usage_line(3, "odin doc . Generates documentation on package in current directory."); print_usage_line(3, "odin doc Generates documentation on package in ."); print_usage_line(3, "odin doc filename.odin -file Generates documentation on single-file package."); } else if (command == "version") { + print_usage_header_once(); print_usage_line(1, "version Prints version."); } else if (command == "strip-semicolon") { + print_usage_header_once(); print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); } else if (command == "bundle") { + print_usage_header_once(); print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform"); print_usage_line(2, "Supported platforms:"); print_usage_line(3, "android"); + } else if (command == "report") { + print_usage_header_once(); + print_usage_line(1, "report Prints information useful to reporting a bug."); + } else if (command == "root") { + print_usage_header_once(); + print_usage_line(1, "root Prints the root path where Odin looks for the builtin collections."); } bool doc = command == "doc"; @@ -2293,13 +2668,10 @@ gb_internal void print_show_help(String const arg0, String command, String optio check = true; } - print_usage_line(0, ""); - print_usage_line(1, "Flags"); - print_usage_line(0, ""); - auto const print_flag = [&optional_flag](char const *flag) -> bool { + auto const print_flag = [&optional_flag, &help_resolved, &printed_flags_header, print_usage_header_once](char const *flag) -> bool { if (optional_flag.len != 0) { String f = make_string_c(flag); isize i = string_index_byte(f, ':'); @@ -2310,6 +2682,14 @@ gb_internal void print_show_help(String const arg0, String command, String optio return false; } } + print_usage_header_once(); + if (!printed_flags_header) { + print_usage_line(0, ""); + print_usage_line(1, "Flags"); + print_usage_line(0, ""); + printed_flags_header = true; + } + help_resolved = true; print_usage_line(0, ""); print_usage_line(1, flag); return true; @@ -2327,24 +2707,37 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } + if (check) { + if (print_flag("-bedrock")) { + print_usage_line(2, "Disables numerous features. List of disabled features:"); + print_usage_line(3, "`map` types"); + print_usage_line(3, "128-bit integer types"); + print_usage_line(3, "runtime type information (-no-rtti)"); + print_usage_line(3, "non-constant global variables (-disable-non-constant-globals)"); + print_usage_line(3, "@(init) @(fini) (-disable-init-fini)"); + print_usage_line(3, "Anything Objective-C related"); + print_usage_line(3, "The default paths to the library collections 'core' and 'vendor'"); + } + } + if (build) { if (print_flag("-build-mode:")) { print_usage_line(2, "Sets the build mode."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-build-mode:exe Builds as an executable."); - print_usage_line(3, "-build-mode:test Builds as an executable that executes tests."); - print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library."); - print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library."); - print_usage_line(3, "-build-mode:dynamic Builds as a dynamically linked library."); - print_usage_line(3, "-build-mode:lib Builds as a statically linked library."); - print_usage_line(3, "-build-mode:static Builds as a statically linked library."); - print_usage_line(3, "-build-mode:obj Builds as an object file."); - print_usage_line(3, "-build-mode:object Builds as an object file."); - print_usage_line(3, "-build-mode:assembly Builds as an assembly file."); - print_usage_line(3, "-build-mode:assembler Builds as an assembly file."); - print_usage_line(3, "-build-mode:asm Builds as an assembly file."); - print_usage_line(3, "-build-mode:llvm-ir Builds as an LLVM IR file."); - print_usage_line(3, "-build-mode:llvm Builds as an LLVM IR file."); + print_usage_line(3, "-build-mode:exe Builds as an executable."); + print_usage_line(3, "-build-mode:test Builds as an executable that executes tests."); + print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:dynamic Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:lib Builds as a statically linked library."); + print_usage_line(3, "-build-mode:static Builds as a statically linked library."); + print_usage_line(3, "-build-mode:obj Builds as an object file."); + print_usage_line(3, "-build-mode:object Builds as an object file."); + print_usage_line(3, "-build-mode:assembly Builds as an assembly file."); + print_usage_line(3, "-build-mode:assembler Builds as an assembly file."); + print_usage_line(3, "-build-mode:asm Builds as an assembly file."); + print_usage_line(3, "-build-mode:llvm-ir Builds as an LLVM IR file."); + print_usage_line(3, "-build-mode:llvm Builds as an LLVM IR file."); } } @@ -2353,22 +2746,22 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Defines a library collection used for imports."); print_usage_line(2, "Example: -collection:shared=dir/to/shared"); print_usage_line(2, "Usage in Code:"); - print_usage_line(3, "import \"shared:foo\""); + print_usage_line(3, "import \"shared:foo\""); } if (print_flag("-custom-attribute:")) { print_usage_line(2, "Add a custom attribute which will be ignored if it is unknown."); print_usage_line(2, "This can be used with metaprogramming tools."); print_usage_line(2, "Examples:"); - print_usage_line(3, "-custom-attribute:my_tag"); - print_usage_line(3, "-custom-attribute:my_tag,the_other_thing"); - print_usage_line(3, "-custom-attribute:my_tag -custom-attribute:the_other_thing"); + print_usage_line(3, "-custom-attribute:my_tag"); + print_usage_line(3, "-custom-attribute:my_tag,the_other_thing"); + print_usage_line(3, "-custom-attribute:my_tag -custom-attribute:the_other_thing"); } } if (run_or_build) { if (print_flag("-debug")) { - print_usage_line(2, "Enables debug information, and defines the global constant ODIN_DEBUG to be 'true'."); + print_usage_line(2, "Enables debug information, and defines the global constant ODIN_DEBUG to be 'true'. Sets -o:none by default."); } } @@ -2385,7 +2778,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Defines a scalar boolean, integer or string as global constant."); print_usage_line(2, "Example: -define:SPAM=123"); print_usage_line(2, "Usage in code:"); - print_usage_line(3, "#config(SPAM, default_value)"); + print_usage_line(3, "#config(SPAM, default_value)"); } } @@ -2393,7 +2786,15 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-disable-assert")) { print_usage_line(2, "Disables the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'."); } + } + if (check) { + if (print_flag("-disable-init-fini")) { + print_usage_line(2, "Disables the ability to use @(init) and @(fini) procedures"); + } + } + + if (run_or_build) { if (print_flag("-disable-red-zone")) { print_usage_line(2, "Disables red zone on a supported freestanding target."); } @@ -2403,8 +2804,13 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-disallow-do")) { print_usage_line(2, "Disallows the 'do' keyword in the project."); } + + if (print_flag("-disable-non-constant-globals")) { + print_usage_line(2, "Disables any global variables which are not initialized with global constants"); + } } + if (doc) { if (print_flag("-doc-format")) { print_usage_line(2, "Generates documentation as the .odin-doc format (useful for external tooling)."); @@ -2420,9 +2826,9 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (check) { if (print_flag("-error-pos-style:")) { print_usage_line(2, "Available options:"); - print_usage_line(3, "-error-pos-style:unix file/path:45:3:"); - print_usage_line(3, "-error-pos-style:odin file/path(45:3)"); - print_usage_line(3, "-error-pos-style:default (Defaults to 'odin'.)"); + print_usage_line(3, "-error-pos-style:unix file/path:45:3:"); + print_usage_line(3, "-error-pos-style:odin file/path(45:3)"); + print_usage_line(3, "-error-pos-style:default (Defaults to 'odin'.)"); } if (print_flag("-export-defineables:")) { @@ -2433,8 +2839,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-export-dependencies:")) { print_usage_line(2, "Exports dependencies to one of a few formats. Requires `-export-dependencies-file`."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-export-dependencies:make Exports in Makefile format"); - print_usage_line(3, "-export-dependencies:json Exports in JSON format"); + print_usage_line(3, "-export-dependencies:make Exports in Makefile format"); + print_usage_line(3, "-export-dependencies:json Exports in JSON format"); } if (print_flag("-export-dependencies-file:")) { @@ -2445,8 +2851,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-export-timings:")) { print_usage_line(2, "Exports timings to one of a few formats. Requires `-show-timings` or `-show-more-timings`."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-export-timings:json Exports compile time stats to JSON."); - print_usage_line(3, "-export-timings:csv Exports compile time stats to CSV."); + print_usage_line(3, "-export-timings:json Exports compile time stats to JSON."); + print_usage_line(3, "-export-timings:csv Exports compile time stats to CSV."); } if (print_flag("-export-timings-file:")) { @@ -2494,7 +2900,20 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-ignore-warnings")) { print_usage_line(2, "Ignores warning messages."); } + } + if (check) { + if (print_flag("-integer-division-by-zero:")) { + print_usage_line(2, "Specifies the default behaviour for integer division by zero."); + print_usage_line(2, "Available Options:"); + print_usage_line(3, "-integer-division-by-zero:trap Trap on division/modulo/remainder by zero"); + print_usage_line(3, "-integer-division-by-zero:zero x/0 == 0 and x%%0 == x and x%%%%0 == x"); + print_usage_line(3, "-integer-division-by-zero:self x/0 == x and x%%0 == 0 and x%%%%0 == 0"); + print_usage_line(3, "-integer-division-by-zero:all-bits x/0 == ~T(0) and x%%0 == x and x%%%%0 == x"); + } + } + + if (check) { if (print_flag("-json-errors")) { print_usage_line(2, "Prints the error messages as json to stderr."); } @@ -2510,6 +2929,14 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } + if (test_only || run_or_build) { + if (print_flag("-keep-executable")) { + print_usage_line(2, "Keep the executable generated by `odin test` or `odin run` after running it. We clean it up by default."); + print_usage_line(2, "If you build your program or test using `odin build`, the compiler does not automatically execute"); + print_usage_line(2, "the resulting program, and this option is not applicable."); + } + } + if (run_or_build) { if (print_flag("-linker:")) { print_usage_line(2, "Specify the linker to use."); @@ -2519,8 +2946,12 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } - if (print_flag("-lld")) { - print_usage_line(2, "Uses the LLD linker rather than the default."); + if (print_flag("-lto:")) { + print_usage_line(2, "States that the project is to be build with link-time optimizations."); + print_usage_line(2, "This also enables '-use-separate-modules' (if not already set) and `-linker:lld"); + print_usage_line(2, "Choices:"); + print_usage_line(3, "thin (one module per package)"); + print_usage_line(3, "thin-files (one module file)"); } } @@ -2530,15 +2961,21 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Must be an integer >0."); print_usage_line(2, "If not set, the default max error count is %d.", DEFAULT_MAX_ERROR_COLLECTOR_COUNT); } + + if (print_flag("-did-you-mean-limit:")) { + print_usage_line(2, "Sets the maximum number of suggestions the compiler provides."); + print_usage_line(2, "Must be an integer >0."); + print_usage_line(2, "If not set, the default limit is %d.", DEFAULT_DID_YOU_MEAN_LIMIT); + } } if (run_or_build) { if (print_flag("-microarch:")) { print_usage_line(2, "Specifies the specific micro-architecture for the build in a string."); print_usage_line(2, "Examples:"); - print_usage_line(3, "-microarch:sandybridge"); - print_usage_line(3, "-microarch:native"); - print_usage_line(3, "-microarch:\"?\" for a list"); + print_usage_line(3, "-microarch:sandybridge"); + print_usage_line(3, "-microarch:native"); + print_usage_line(3, "-microarch:\"?\" for a list"); } } @@ -2562,6 +2999,11 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Disables bounds checking program wide."); } + if (print_flag("-webkit-switch-workaround")) { + print_usage_line(2, "Constrains 'typeid' values to 63 bits to avoid an OMG JIT crash in WebKit when running WASM builds."); + print_usage_line(2, "Only needed for 'js_wasm32'/'js_wasm64p32' targets run in Safari/WebKit. See: https://github.com/odin-lang/Odin/issues/6810"); + } + if (print_flag("-no-crt")) { print_usage_line(2, "Disables automatic linking with the C Run Time."); } @@ -2595,19 +3037,25 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-o:")) { print_usage_line(2, "Sets the optimization mode for compilation."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-o:none"); - print_usage_line(3, "-o:minimal"); - print_usage_line(3, "-o:size"); - print_usage_line(3, "-o:speed"); + print_usage_line(3, "-o:none"); + print_usage_line(3, "-o:minimal"); + print_usage_line(3, "-o:size"); + print_usage_line(3, "-o:speed"); if (LB_USE_NEW_PASS_SYSTEM) { print_usage_line(3, "-o:aggressive (use this with caution)"); } - print_usage_line(2, "The default is -o:minimal."); + print_usage_line(2, "The default is -o:minimal. If -debug is set, the default is -o:none."); } - if (print_flag("-obfuscate-source-code-locations")) { - print_usage_line(2, "Obfuscate the file and procedure strings, and line and column numbers, stored with a 'runtime.Source_Code_Location' value."); + if (print_flag("-source-code-locations:")) { + print_usage_line(2, "Processes the file and procedure strings, and line and column numbers, stored with a 'runtime.Source_Code_Location' value."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-source-code-locations:normal"); + print_usage_line(3, "-source-code-locations:obfuscated"); + print_usage_line(3, "-source-code-locations:filename"); + print_usage_line(3, "-source-code-locations:none"); + print_usage_line(2, "The default is -source-code-locations:normal."); } @@ -2619,7 +3067,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (doc) { if (print_flag("-out:")) { - print_usage_line(2, "Sets the base name of the resultig .odin-doc file."); + print_usage_line(2, "Sets the base name of the resulting .odin-doc file."); print_usage_line(2, "The extension can be optionally included; the resulting file will always have an extension of '.odin-doc'."); print_usage_line(2, "Example: -out:foo"); } @@ -2642,17 +3090,23 @@ gb_internal void print_show_help(String const arg0, String command, String optio } if (run_or_build) { - if (print_flag("-radlink")) { - print_usage_line(2, "Uses the RAD linker rather than the default."); - } - if (print_flag("-reloc-mode:")) { print_usage_line(2, "Specifies the reloc mode."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-reloc-mode:default"); - print_usage_line(3, "-reloc-mode:static"); - print_usage_line(3, "-reloc-mode:pic"); - print_usage_line(3, "-reloc-mode:dynamic-no-pic"); + print_usage_line(3, "-reloc-mode:default"); + print_usage_line(3, "-reloc-mode:static"); + print_usage_line(3, "-reloc-mode:pic"); + print_usage_line(3, "-reloc-mode:dynamic-no-pic"); + } + + if (print_flag("-stack-protector:")) { + print_usage_line(2, "Specifies the stack protector."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-stack-protector:default"); + print_usage_line(3, "-stack-protector:none"); + print_usage_line(3, "-stack-protector:base"); + print_usage_line(3, "-stack-protector:all"); + print_usage_line(3, "-stack-protector:strong"); } #if defined(GB_SYSTEM_WINDOWS) @@ -2667,10 +3121,9 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-sanitize:")) { print_usage_line(2, "Enables sanitization analysis."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-sanitize:address"); - print_usage_line(3, "-sanitize:memory"); - print_usage_line(3, "-sanitize:thread"); - print_usage_line(2, "NOTE: This flag can be used multiple times."); + print_usage_line(3, "-sanitize:address"); + print_usage_line(3, "-sanitize:memory"); + print_usage_line(3, "-sanitize:thread"); } } @@ -2678,6 +3131,9 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-short")) { print_usage_line(2, "Shows shortened documentation for the packages."); } + if (print_flag("-in-source-order")) { + print_usage_line(2, "Shows documentation for the packages in source order within each file."); + } } if (check) { @@ -2685,10 +3141,18 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Shows an overview of all the #config/#defined usages in the project."); } + if (print_flag("-ignore-unused-defineables")) { + print_usage_line(2, "Silence warning/error if a -define doesn't have at least one #config/#defined usage."); + } + if (print_flag("-show-system-calls")) { print_usage_line(2, "Prints the whole command and arguments for calls to external tools like linker and assembler."); } + if (print_flag("-show-import-graph")) { + print_usage_line(2, "Shows dot graph text format of the import graph of a project."); + } + if (print_flag("-show-timings")) { print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds."); } @@ -2714,7 +3178,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons."); print_usage_line(2, "Errs on missing trailing commas followed by a newline."); print_usage_line(2, "Errs on deprecated syntax."); - print_usage_line(2, "Errs when the attached-brace style in not adhered to (also known as 1TBS)."); + print_usage_line(2, "Errs when the attached-brace style is not adhered to (also known as 1TBS)."); print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); } } @@ -2730,23 +3194,42 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "[Windows only]"); print_usage_line(2, "Defines the subsystem for the application."); print_usage_line(2, "Available options:"); - print_usage_line(3, "-subsystem:console"); - print_usage_line(3, "-subsystem:windows"); + print_usage_line(3, "-subsystem:console"); + print_usage_line(3, "-subsystem:windows"); } #endif + } + if (build) { + if (print_flag("-subtarget:")) { + print_usage_line(2, "[Darwin and Linux only]"); + print_usage_line(2, "Available subtargets:"); + String prefix = str_lit("-subtarget:"); + for (u32 i = 1; i < Subtarget_COUNT; i++) { + String name = subtarget_strings[i]; + String help_string = concatenate_strings(temporary_allocator(), prefix, name); + print_usage_line(3, (const char *)help_string.text); + } + } + } + + if (run_or_build) { if (print_flag("-target-features:")) { print_usage_line(2, "Specifies CPU features to enable on top of the enabled features implied by -microarch."); print_usage_line(2, "Examples:"); - print_usage_line(3, "-target-features:atomics"); - print_usage_line(3, "-target-features:\"sse2,aes\""); - print_usage_line(3, "-target-features:\"?\" for a list"); + print_usage_line(3, "-target-features:atomics"); + print_usage_line(3, "-target-features:\"sse2,aes\""); + print_usage_line(3, "-target-features:\"?\" for a list"); } } if (check) { if (print_flag("-target:")) { print_usage_line(2, "Sets the target for the executable to be built in."); + print_usage_line(2, "Examples:"); + print_usage_line(3, "-target:linux_amd64"); + print_usage_line(3, "-target:windows_amd64"); + print_usage_line(3, "-target:\"?\" for a list"); } if (print_flag("-terse-errors")) { @@ -2777,11 +3260,11 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-vet")) { print_usage_line(2, "Does extra checks on the code."); print_usage_line(2, "Extra checks include:"); - print_usage_line(3, "-vet-unused"); - print_usage_line(3, "-vet-unused-variables"); - print_usage_line(3, "-vet-unused-imports"); - print_usage_line(3, "-vet-shadowing"); - print_usage_line(3, "-vet-using-stmt"); + print_usage_line(3, "-vet-unused"); + print_usage_line(3, "-vet-unused-variables"); + print_usage_line(3, "-vet-unused-imports"); + print_usage_line(3, "-vet-shadowing"); + print_usage_line(3, "-vet-using-stmt"); } if (print_flag("-vet-cast")) { @@ -2867,6 +3350,21 @@ gb_internal void print_show_help(String const arg0, String command, String optio print_usage_line(2, "If this is omitted, the terminal will prompt you to provide it."); } } + + if (!help_resolved) { + usage(arg0); + print_usage_line(0, ""); + if (command == "help") { + print_usage_line(0, "'%.*s' is not a recognized flag.", LIT(optional_flag)); + } else { + print_usage_line(0, "'%.*s' is not a recognized command.", LIT(command)); + } + return 1; + } + + print_usage_line(0, ""); + + return 0; } gb_internal void print_show_unused(Checker *c) { @@ -2908,7 +3406,8 @@ gb_internal void print_show_unused(Checker *c) { if (e->token.string == "_") { continue; } - if (ptr_set_exists(&info->minimum_dependency_set, e)) { + + if (e->min_dep_count.load(std::memory_order_relaxed) > 0) { continue; } array_add(&unused, e); @@ -3144,6 +3643,32 @@ gb_internal int strip_semicolons(Parser *parser) { return cast(int)failed; } +gb_internal void setup_bedrock_mode(void) { + if (!build_context.bedrock) { + return; + } + + bool seen_core = false; + bool seen_vendor = false; + for (isize i = 0; i < library_collections.count; /**/) { + if (!seen_core && library_collections[i].name == "core") { + array_ordered_remove(&library_collections, i); + seen_core = true; + continue; + } + + if (!seen_vendor && library_collections[i].name == "vendor") { + array_ordered_remove(&library_collections, i); + seen_vendor = true; + continue; + } + + i += 1; + } + + build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; +} + gb_internal void init_terminal(void) { TIME_SECTION("init terminal"); build_context.has_ansi_terminal_colours = false; @@ -3231,14 +3756,52 @@ int main(int arg_count, char const **arg_ptr) { TIME_SECTION("init args"); map_init(&build_context.defined_values); build_context.extra_packages.allocator = heap_allocator(); + + init_build_context_error_pos_style(); Array args = setup_args(arg_count, arg_ptr); + Array run_args = array_make(heap_allocator(), 0, arg_count); + defer (array_free(&run_args)); String command = args[1]; String init_filename = {}; - String run_args_string = {}; isize last_non_run_arg = args.count; + isize double_dash_pos = -1; + for_array(i, args) { + if (args[i] == "--") { + double_dash_pos = i; + break; + } + + if (args[i] == "-help" || args[i] == "--help") { + build_context.show_help = true; + return print_show_help(args[0], command); + } + } + + if (args.count > 2) { + // NOTE(bill): Allow for both `odin command path -flags` and `odin command -flags path` + // To do this, if the first argument after the command and last argument is NOT a flag, + // then put that last parameter first + isize end_arg = double_dash_pos >= 0 ? double_dash_pos : args.count-1; + if (args[1] == "bundle" && args.count > 4) { + if (string_starts_with(args[3], str_lit("-")) && + !string_starts_with(args[end_arg], str_lit("-"))) { + String possible_path = args[end_arg]; + array_ordered_remove(&args, end_arg); + array_inject_at(&args, 3, possible_path); + } + } else if (args.count > 3) { + if (string_starts_with(args[2], str_lit("-")) && + !string_starts_with(args[end_arg], str_lit("-"))) { + String possible_path = args[end_arg]; + array_ordered_remove(&args, end_arg); + array_inject_at(&args, 2, possible_path); + } + } + } + bool run_output = false; if (command == "run" || command == "test") { if (args.count < 3) { @@ -3250,9 +3813,6 @@ int main(int arg_count, char const **arg_ptr) { build_context.command_kind = Command_test; } - Array run_args = array_make(heap_allocator(), 0, arg_count); - defer (array_free(&run_args)); - isize run_args_start_idx = -1; for_array(i, args) { if (args[i] == "--") { @@ -3274,7 +3834,6 @@ int main(int arg_count, char const **arg_ptr) { } } args = array_slice(args, 0, last_non_run_arg); - run_args_string = string_join_and_quote(heap_allocator(), run_args); init_filename = args[2]; run_output = true; @@ -3332,6 +3891,10 @@ int main(int arg_count, char const **arg_ptr) { return 1; #endif } else if (command == "version") { + if (args.count != 2) { + usage(args[0]); + return 1; + } build_context.command_kind = Command_version; gb_printf("%.*s version %.*s", LIT(args[0]), LIT(ODIN_VERSION)); @@ -3346,6 +3909,10 @@ int main(int arg_count, char const **arg_ptr) { gb_printf("\n"); return 0; } else if (command == "report") { + if (args.count != 2) { + usage(args[0]); + return 1; + } build_context.command_kind = Command_bug_report; print_bug_report_help(); return 0; @@ -3354,8 +3921,7 @@ int main(int arg_count, char const **arg_ptr) { usage(args[0]); return 1; } else { - print_show_help(args[0], args[1], args[2]); - return 0; + return print_show_help(args[0], args[1], args[2]); } } else if (command == "bundle") { if (args.count < 4) { @@ -3371,6 +3937,14 @@ int main(int arg_count, char const **arg_ptr) { } init_filename = args[3]; } else if (command == "root") { + if (args.count != 2) { + usage(args[0]); + return 1; + } + // NOTE(Jeroen): `odin root` omits a newline on purpose so that it can be used in scripts. + // e.g. `ODIN_CORE="$(odin root)core"`. + // Human convenience is not a consideration. + // Further pull requests to add a newline will be closed without comment. gb_printf("%.*s", LIT(odin_root_dir())); return 0; } else if (command == "clear-cache") { @@ -3386,9 +3960,21 @@ int main(int arg_count, char const **arg_ptr) { init_filename = copy_string(permanent_allocator(), init_filename); - if (init_filename == "-help" || - init_filename == "--help") { - build_context.show_help = true; + build_context.command = command; + + string_set_init(&build_context.custom_attributes); + string_set_init(&build_context.vet_packages); + + if (!parse_build_flags(args)) { + return 1; + } + + if (build_context.show_help) { + return print_show_help(args[0], command); + } + + if (build_context.bedrock) { + setup_bedrock_mode(); } if (init_filename.len > 0 && !build_context.show_help) { @@ -3402,6 +3988,47 @@ int main(int arg_count, char const **arg_ptr) { break; } } + if (!single_file_package) { + isize colon_pos = -1; + for (isize j = 0; j < init_filename.len; j++) { + if (init_filename[j] == ':') { + colon_pos = j; + break; + } + } + if (colon_pos > 0) { + String collection_name = substring(init_filename, 0, colon_pos); + String file_str = substring(init_filename, colon_pos+1, init_filename.len); + + if (collection_name == "core") { + bool replace_with_base = false; + if (string_starts_with(file_str, str_lit("runtime"))) { + replace_with_base = true; + } else if (string_starts_with(file_str, str_lit("intrinsics"))) { + replace_with_base = true; + } if (string_starts_with(file_str, str_lit("builtin"))) { + replace_with_base = true; + } + + if (replace_with_base) { + collection_name = str_lit("base"); + } + } + + String base_dir = {}; + if (find_library_collection_path(collection_name, &base_dir)) { + bool ok = false; + String fullpath = string_trim_whitespace(get_fullpath_relative(permanent_allocator(), base_dir, file_str, &ok)); + if (ok) { + init_filename = fullpath; + if (path_is_directory(init_filename)) { + goto filename_check_success; + } + } + } + } + + } if (!single_file_package) { gb_printf_err("ERROR: `%.*s %.*s` takes a package/directory as its first argument.\n", LIT(args[0]), LIT(command)); @@ -3428,23 +4055,11 @@ int main(int arg_count, char const **arg_ptr) { return 1; } } + + filename_check_success:; } } - build_context.command = command; - - string_set_init(&build_context.custom_attributes); - string_set_init(&build_context.vet_packages); - - if (!parse_build_flags(args)) { - return 1; - } - - if (build_context.show_help) { - print_show_help(args[0], command); - return 0; - } - if (command == "bundle") { return bundle(init_filename); } @@ -3460,6 +4075,11 @@ int main(int arg_count, char const **arg_ptr) { // print_usage_line(0, "%.*s 32-bit is not yet supported for this platform", LIT(args[0])); // return 1; // } + + // Warn about Windows i386 thread-local storage limitations + if (build_context.metrics.arch == TargetArch_i386 && build_context.metrics.os == TargetOs_windows) { + gb_printf_err("Warning: Thread-local storage is disabled on Windows i386.\n"); + } // Check chosen microarchitecture. If not found or ?, print list. bool print_microarch_list = true; @@ -3537,10 +4157,16 @@ int main(int arg_count, char const **arg_ptr) { for (;;) { String item = string_split_iterator(&target_it, ','); if (item == "") break; + + String stripped_item = item; + if (*stripped_item.text == '+' || *stripped_item.text == '-') { + stripped_item.text++; + stripped_item.len--; + } String invalid; - if (!check_target_feature_is_valid_for_target_arch(item, &invalid) && item != str_lit("help")) { - if (item != str_lit("?")) { + if (!check_target_feature_is_valid_for_target_arch(stripped_item, &invalid) && stripped_item != str_lit("help")) { + if (stripped_item != str_lit("?")) { gb_printf_err("Unkown target feature '%.*s'.\n", LIT(invalid)); } gb_printf("Possible -target-features for target %.*s are:\n", LIT(target_arch_names[build_context.metrics.arch])); @@ -3564,8 +4190,25 @@ int main(int arg_count, char const **arg_ptr) { return 1; } - - string_set_add(&build_context.target_features_set, item); + + // Ensure the feature name always has +/- prefix. If there isn't, default to '+' + String feature_str = item; + if (*feature_str.text != '+' && *feature_str.text != '-') { + feature_str = concatenate_strings(temporary_allocator(), make_string_c("+"), feature_str); + } + + // Ensure there is only a single entry for each feature in the target set. + // If the negative exists, override the existing value with the current one. + String neg_feature_str = clone_string(temporary_allocator(), feature_str); + switch (*neg_feature_str.text) { + case '+': *neg_feature_str.text = '-'; break; + case '-': *neg_feature_str.text = '+'; break; + default: GB_ASSERT(false); break; + } + + string_set_remove(&build_context.target_features_set, neg_feature_str); + + string_set_add(&build_context.target_features_set, feature_str); } } @@ -3587,6 +4230,7 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_debug_messages) { debugf("Selected microarch: %.*s\n", LIT(march)); debugf("Default microarch features: %.*s\n", LIT(default_features)); + debugf("Target triplet: %.*s\n", LIT(build_context.metrics.target_triplet)); for_array(i, build_context.build_paths) { String build_path = path_to_string(heap_allocator(), build_context.build_paths[i]); debugf("build_paths[%ld]: %.*s\n", i, LIT(build_path)); @@ -3601,8 +4245,8 @@ int main(int arg_count, char const **arg_ptr) { init_universal(); // TODO(bill): prevent compiling without a linker - Parser *parser = gb_alloc_item(permanent_allocator(), Parser); - Checker *checker = gb_alloc_item(permanent_allocator(), Checker); + Parser * parser = permanent_alloc_item(); + Checker *checker = permanent_alloc_item(); bool failed_to_cache_parsing = false; MAIN_TIME_SECTION("parse files"); @@ -3637,7 +4281,9 @@ int main(int arg_count, char const **arg_ptr) { MAIN_TIME_SECTION("type check"); check_parsed_files(checker); - check_defines(&build_context, checker); + if (!build_context.ignore_unused_defineables) { + check_defines(&build_context, checker); + } if (any_errors()) { print_all_errors(); return 1; @@ -3674,6 +4320,9 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_timings) { show_timings(checker, &global_timings); } + if (build_context.show_import_graph) { + show_import_graph(checker); + } return 0; } @@ -3685,6 +4334,9 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_timings) { show_timings(checker, &global_timings); } + if (build_context.show_import_graph) { + show_import_graph(checker); + } if (global_error_collector.count != 0) { return 1; @@ -3701,35 +4353,8 @@ int main(int arg_count, char const **arg_ptr) { failed_to_cache_parsing = true; } -#if ALLOW_TILDE - if (build_context.tilde_backend) { - LinkerData linker_data = {}; - MAIN_TIME_SECTION("Tilde Code Gen"); - if (!cg_generate_code(checker, &linker_data)) { - return 1; - } - - switch (build_context.build_mode) { - case BuildMode_Executable: - case BuildMode_StaticLibrary: - case BuildMode_DynamicLibrary: - i32 result = linker_stage(&linker_data); - if (result) { - if (build_context.show_timings) { - show_timings(checker, &global_timings); - } - - if (build_context.export_dependencies_format != DependenciesExportUnspecified) { - export_dependencies(checker); - } - return result; - } - break; - } - } else -#endif { - lbGenerator *gen = gb_alloc_item(permanent_allocator(), lbGenerator); + lbGenerator *gen = permanent_alloc_item(); if (!lb_init_generator(gen, checker)) { return 1; } @@ -3749,11 +4374,18 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_timings) { show_timings(checker, &global_timings); } + if (build_context.show_import_graph) { + show_import_graph(checker); + } if (build_context.export_dependencies_format != DependenciesExportUnspecified) { export_dependencies(checker); } return result; + } else { + if (build_context.export_linked_libs_path != "") { + export_linked_libraries(gen); + } } break; } @@ -3762,6 +4394,14 @@ int main(int arg_count, char const **arg_ptr) { remove_temp_files(gen); } + if (any_errors()) { + print_all_errors(); + return 1; + } + if (any_warnings()) { + print_all_errors(); + } + end_of_code_gen:; if (build_context.export_dependencies_format != DependenciesExportUnspecified) { @@ -3782,12 +4422,45 @@ end_of_code_gen:; if (build_context.show_timings) { show_timings(checker, &global_timings); } + if (build_context.show_import_graph) { + show_import_graph(checker); + } if (run_output) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); - system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); + const char* exe_name_cstring = alloc_cstring(heap_allocator(), exe_name); + Array run_args_cstring = array_make(heap_allocator(), 0, run_args.count); + defer({ + for_array(i, run_args_cstring) { gb_free(heap_allocator(), (void*)run_args_cstring[i]); } + array_free(&run_args_cstring); + }); + + array_add(&run_args_cstring, exe_name_cstring); + for_array(i, run_args) { + array_add(&run_args_cstring, alloc_cstring(heap_allocator(), run_args[i])); + } + array_add(&run_args_cstring, NULL); + + int subprocess_res = run_subprocess(exe_name_cstring, run_args_cstring.data); + if (subprocess_res) { + gb_exit(subprocess_res); + } + if (!build_context.keep_executable) { + char const *filename = cast(char const *)exe_name.text; + gb_file_remove(filename); + + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.os == TargetOs_darwin) { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + defer (gb_free(heap_allocator(), symbol_path.text)); + + filename = cast(char const *)symbol_path.text; + gb_file_remove(filename); + } + } + } } return 0; } diff --git a/src/microsoft_craziness.h b/src/microsoft_craziness.h index b0fd22a23..933607a2a 100644 --- a/src/microsoft_craziness.h +++ b/src/microsoft_craziness.h @@ -59,7 +59,7 @@ struct Find_Result { }; gb_internal String mc_wstring_to_string(wchar_t const *str) { - return string16_to_string(mc_allocator, make_string16_c(str)); + return string16_to_string(mc_allocator, make_string16_c(cast(u16 *)str)); } gb_internal String16 mc_string_to_wstring(String str) { @@ -103,7 +103,7 @@ gb_internal HANDLE mc_find_first(String wildcard, MC_Find_Data *find_data) { String16 wildcard_wide = mc_string_to_wstring(wildcard); defer (mc_free(wildcard_wide)); - HANDLE handle = FindFirstFileW(wildcard_wide.text, &_find_data); + HANDLE handle = FindFirstFileW(cast(wchar_t *)wildcard_wide.text, &_find_data); if (handle == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; find_data->file_attributes = _find_data.dwFileAttributes; diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 6aa933e86..67ca9e278 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -57,10 +57,13 @@ gb_internal isize type_set__find(TypeSet *s, TypeInfoPair pair) { usize mask = s->capacity-1; usize hash_index = cast(usize)hash & mask; for (usize i = 0; i < s->capacity; i++) { - Type *key = s->keys[hash_index].type; - if (are_types_identical_unique_tuples(key, pair.type)) { + auto *e = &s->keys[hash_index]; + u64 hash = e->hash; + Type *key = e->type; + if (hash == pair.hash && + are_types_identical_unique_tuples(key, pair.type)) { return hash_index; - } else if (key == 0) { + } else if (key == nullptr) { return -1; } hash_index = (hash_index+1)&mask; @@ -164,6 +167,48 @@ gb_internal bool type_set_update(TypeSet *s, Type *ptr) { // returns true if it return type_set_update(s, pair); } +gb_internal bool type_set_update_with_mutex(TypeSet *s, TypeInfoPair pair, RWSpinLock *m) { // returns true if it previously existsed + rwlock_acquire_upgrade(m); + if (type_set_exists(s, pair)) { + rwlock_release_upgrade(m); + return true; + } + + rwlock_release_upgrade_and_acquire_write(m); + defer (rwlock_release_write(m)); + + if (s->keys == nullptr) { + type_set_init(s); + } else if (type_set__full(s)) { + type_set_grow(s); + } + GB_ASSERT(s->count < s->capacity); + GB_ASSERT(s->capacity >= 0); + + usize mask = s->capacity-1; + usize hash = cast(usize)pair.hash; + usize hash_index = (cast(usize)hash) & mask; + GB_ASSERT(hash_index < s->capacity); + for (usize i = 0; i < s->capacity; i++) { + TypeInfoPair *key = &s->keys[hash_index]; + GB_ASSERT(!are_types_identical_unique_tuples(key->type, pair.type)); + if (key->hash == TYPE_SET_TOMBSTONE || key->hash == 0) { + *key = pair; + s->count++; + return false; + } + hash_index = (hash_index+1)&mask; + } + + GB_PANIC("ptr set out of memory"); + return false; +} + +gb_internal bool type_set_update_with_mutex(TypeSet *s, Type *ptr, RWSpinLock *m) { // returns true if it previously existsed + TypeInfoPair pair = {ptr, type_hash_canonical_type(ptr)}; + return type_set_update_with_mutex(s, pair, m); +} + gb_internal Type *type_set_add(TypeSet *s, Type *ptr) { type_set_update(s, ptr); @@ -197,9 +242,146 @@ gb_internal gb_inline void type_set_clear(TypeSet *s) { typedef TYPE_WRITER_PROC(TypeWriterProc); +enum { SIP_BLOCK_SIZE = 8 }; + +struct SipHashContext { + u64 v0, v1, v2, v3; // State values + u64 k0, k1; // Split key + isize c_rounds; // Number of message rounds + isize d_rounds; // Number of finalization rounds + u8 buf[SIP_BLOCK_SIZE]; // Provided data + isize last_block; // offset from last block + isize total_length; + bool is_initialized; +}; + +struct TypeidHashContext { + SipHashContext sip; +}; + + +void typeid_hash_context_init(TypeidHashContext *hash_ctx) { + SipHashContext *sip = &hash_ctx->sip; + sip->c_rounds = 2; + sip->d_rounds = 4; + + // some random numbers to act as the seed + sip->k0 = 0xa6592ea25e04ac3cull; + sip->k1 = 0xba3cba04ed28a9aeull; + + // + sip->v0 = 0x736f6d6570736575 ^ sip->k0; + sip->v1 = 0x646f72616e646f6d ^ sip->k1; + sip->v2 = 0x6c7967656e657261 ^ sip->k0; + sip->v3 = 0x7465646279746573 ^ sip->k1; + + sip->last_block = 0; + sip->total_length = 0; + + sip->is_initialized = true; +} + +u64 rotate_left64(u64 x, u64 k) { + static u64 const n = 64; + u64 s = k & (n-1); + return (x<>(n-2)); +} + +void sip_compress(SipHashContext *sip) { + sip->v0 += sip->v1; + sip->v1 = rotate_left64(sip->v1, 13); + sip->v1 ^= sip->v0; + sip->v0 = rotate_left64(sip->v0, 32); + sip->v2 += sip->v3; + sip->v3 = rotate_left64(sip->v3, 16); + sip->v3 ^= sip->v2; + sip->v0 += sip->v3; + sip->v3 = rotate_left64(sip->v3, 21); + sip->v3 ^= sip->v0; + sip->v2 += sip->v1; + sip->v1 = rotate_left64(sip->v1, 17); + sip->v1 ^= sip->v2; + sip->v2 = rotate_left64(sip->v2, 32); +} + +void sip_block(SipHashContext *sip, void const *ptr, isize len) { + u8 const *data = cast(u8 const *)ptr; + while (len >= SIP_BLOCK_SIZE) { + u64 m = 0; + gb_memcopy(&m, data, 8); + + sip->v3 ^= m; + + for (isize i = 0; i < sip->c_rounds; i++) { + sip_compress(sip); + } + + sip->v0 ^= m; + + data += SIP_BLOCK_SIZE; + len -= SIP_BLOCK_SIZE; + } +} + +void typeid_hash_context_update(TypeidHashContext *ctx, void const *ptr, isize len) { + GB_ASSERT(ctx->sip.is_initialized); + SipHashContext *sip = &ctx->sip; + + u8 const *data = cast(u8 const *)ptr; + sip->total_length += len; + if (sip->last_block > 0) { + isize n = gb_min(SIP_BLOCK_SIZE - sip->last_block, len); + gb_memcopy(sip->buf + sip->last_block, data, n); + sip->last_block += n; + if (sip->last_block == SIP_BLOCK_SIZE) { + sip_block(sip, sip->buf, SIP_BLOCK_SIZE); + sip->last_block = 0; + } + data += n; + len -= n; + } + + if (len >= SIP_BLOCK_SIZE) { + isize n = len & ~(SIP_BLOCK_SIZE-1); + sip_block(sip, data, n); + data += n; + len -= n; + } + if (len > 0) { + isize n = gb_min(SIP_BLOCK_SIZE, len); + gb_memcopy(sip->buf, data, n); + sip->last_block = n; + } +} + +u64 typeid_hash_context_fini(TypeidHashContext *ctx) { + GB_ASSERT(ctx->sip.is_initialized); + SipHashContext *sip = &ctx->sip; + + u8 tmp[SIP_BLOCK_SIZE] = {}; + gb_memcopy(tmp, sip->buf, gb_min(sip->last_block, SIP_BLOCK_SIZE)); + tmp[7] = u8(sip->total_length & 0xff); + sip_block(sip, tmp, SIP_BLOCK_SIZE); + + sip->v2 ^= 0xff; + + for (isize i = 0; i < sip->d_rounds; i++) { + sip_compress(sip); + } + + u64 res = sip->v0 ^ sip->v1 ^ sip->v2 ^ sip->v3; + + *sip = {}; + + return res ? res : 1; +} + + + struct TypeWriter { - TypeWriterProc *proc; - void *user_data; + TypeWriterProc * proc; + void * user_data; + TypeidHashContext hash_ctx; }; bool type_writer_append(TypeWriter *w, void const *ptr, isize len) { @@ -244,13 +426,14 @@ void type_writer_destroy_string(TypeWriter *w) { TYPE_WRITER_PROC(type_writer_hasher_writer_proc) { - u64 *seed = cast(u64 *)w->user_data; - *seed = fnv64a(ptr, len, *seed); + TypeidHashContext *ctx = cast(TypeidHashContext *)w->user_data; + typeid_hash_context_update(ctx, ptr, len); return true; } -void type_writer_make_hasher(TypeWriter *w, u64 *hash) { - w->user_data = hash; +void type_writer_make_hasher(TypeWriter *w, TypeidHashContext *ctx) { + typeid_hash_context_init(ctx); + w->user_data = ctx; w->proc = type_writer_hasher_writer_proc; } @@ -328,12 +511,30 @@ gb_internal u64 type_hash_canonical_type(Type *type) { if (type == nullptr) { return 0; } - u64 hash = fnv64a(nullptr, 0); - TypeWriter w = {}; - type_writer_make_hasher(&w, &hash); - write_type_to_canonical_string(&w, type); + u64 prev_hash = type->canonical_hash.load(std::memory_order_relaxed); + if (prev_hash != 0) { + return prev_hash; + } - return hash ? hash : 1; + TypeWriter w = {}; + type_writer_make_hasher(&w, &w.hash_ctx); + write_type_to_canonical_string(&w, type); + u64 hash = typeid_hash_context_fini(&w.hash_ctx); + if (build_context.webkit_switch_workaround) { + // Clear the top bit so every `typeid` is in [1, 2^63). A `switch` over a + // typeid (e.g. a type switch over `any` in core:fmt) then has a case-value + // span < 2^63. WebKit's B3/OMG wasm JIT computes a switch's value range as + // a signed i64 (max - min); a span >= 2^63 overflows and makes it build a + // pathologically-sized jump table, OOM-crashing the tab. + // WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=317022 + // Odin issue/PR: https://github.com/odin-lang/Odin/issues/6810 + hash &= 0x7fffffffffffffffull; + hash = hash ? hash : 1; + } + + type->canonical_hash.store(hash, std::memory_order_relaxed); + + return hash; } gb_internal String type_to_canonical_string(gbAllocator allocator, Type *type) { @@ -364,13 +565,15 @@ gb_internal gbString string_canonical_entity_name(gbAllocator allocator, Entity gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) { GB_ASSERT(e != nullptr); - if (e->kind == Entity_Procedure || e->kind == Entity_TypeName) { + if (e->kind == Entity_Procedure || e->kind == Entity_TypeName || e->kind == Entity_Variable) { if (e->kind == Entity_Procedure && (e->Procedure.is_export || e->Procedure.is_foreign)) { // no prefix return; } - if (e->parent_proc_decl) { - Entity *p = e->parent_proc_decl->entity; + InternedString interned = entity_interned_name(e); + + if (e->parent_proc_decl.load(std::memory_order_relaxed)) { + Entity *p = e->parent_proc_decl.load(std::memory_order_relaxed)->entity; write_canonical_parent_prefix(w, p); type_writer_append(w, p->token.string.text, p->token.string.len); if (is_type_polymorphic(p->type)) { @@ -379,7 +582,7 @@ gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) { } type_writer_appendc(w, CANONICAL_NAME_SEPARATOR); - } else if (e->pkg && (scope_lookup_current(e->pkg->scope, e->token.string) == e)) { + } else if (e->pkg && (scope_lookup_current(e->pkg->scope, interned) == e)) { type_writer_append(w, e->pkg->name.text, e->pkg->name.len); if (e->pkg->name == "llvm") { type_writer_appendc(w, "$"); @@ -474,6 +677,11 @@ gb_internal void write_canonical_entity_name(TypeWriter *w, Entity *e) { } else if (s->flags & (ScopeFlag_Builtin)) { goto write_base_name; } + + if (e->kind == Entity_TypeName) { + goto write_base_name; + } + gb_printf_err("%s WEIRD ENTITY TYPE %s %u %p\n", token_pos_to_string(e->token.pos), type_to_string(e->type), s->flags, s->decl_info); auto const print_scope_flags = [](Scope *s) { @@ -490,7 +698,7 @@ gb_internal void write_canonical_entity_name(TypeWriter *w, Entity *e) { }; print_scope_flags(s); - GB_PANIC("weird entity %.*s", LIT(e->token.string)); + GB_PANIC("weird entity %.*s (%.*s)", LIT(e->token.string), LIT(entity_strings[e->kind])); } if (e->pkg != nullptr) { type_writer_append(w, e->pkg->name.text, e->pkg->name.len); @@ -505,7 +713,13 @@ write_base_name: Type *params = nullptr; Entity *parent = type_get_polymorphic_parent(e->type, ¶ms); - if (parent && (parent->token.string == e->token.string)) { + if (parent && (e->token.string == parent->token.string)) { + // Check for `distinct` forms + type_writer_append(w, parent->token.string.text, parent->token.string.len); + write_canonical_params(w, params); + } else if (parent && string_starts_with(e->token.string, parent->token.string) && + string_contains_char(e->token.string, '(')) { + // Check for named specialization forms type_writer_append(w, parent->token.string.text, parent->token.string.len); write_canonical_params(w, params); } else { @@ -547,8 +761,8 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { return; } - type = default_type(type); - GB_ASSERT(!is_type_untyped(type)); + // type = default_type(type); + // GB_ASSERT(!is_type_untyped(type)); switch (type->kind) { case Type_Basic: @@ -587,6 +801,10 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { type_writer_appendc(w, "[dynamic]"); write_type_to_canonical_string(w, type->DynamicArray.elem); return; + case Type_FixedCapacityDynamicArray: + type_writer_append_fmt(w, "[dynamic;%lld]", cast(long long)type->FixedCapacityDynamicArray.capacity); + write_type_to_canonical_string(w, type->FixedCapacityDynamicArray.elem); + return; case Type_SimdVector: type_writer_append_fmt(w, "#simd[%lld]", cast(long long)type->SimdVector.count); write_type_to_canonical_string(w, type->SimdVector.elem); @@ -637,7 +855,8 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { } else { type_writer_append_fmt(w, "%lld", type->BitSet.lower); type_writer_append_fmt(w, CANONICAL_RANGE_OPERATOR); - type_writer_append_fmt(w, "%lld", type->BitSet.upper); + write_type_to_canonical_string(w, type->BitSet.elem); + type_writer_append_fmt(w, "(%lld)", type->BitSet.upper); } if (type->BitSet.underlying != nullptr) { type_writer_appendc(w, ";"); @@ -685,9 +904,9 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { write_canonical_params(w, type->Struct.polymorphic_params); } - if (type->Struct.is_packed) type_writer_appendc(w, "#packed"); - if (type->Struct.is_raw_union) type_writer_appendc(w, "#raw_union"); - if (type->Struct.is_no_copy) type_writer_appendc(w, "#no_copy"); + if (type->Struct.is_packed) type_writer_appendc(w, "#packed"); + if (type->Struct.is_raw_union) type_writer_appendc(w, "#raw_union"); + if (type->Struct.is_all_or_none) type_writer_appendc(w, "#all_or_none"); if (type->Struct.custom_min_field_align != 0) type_writer_append_fmt(w, "#min_field_align(%lld)", cast(long long)type->Struct.custom_min_field_align); if (type->Struct.custom_max_field_align != 0) type_writer_append_fmt(w, "#max_field_align(%lld)", cast(long long)type->Struct.custom_max_field_align); if (type->Struct.custom_align != 0) type_writer_append_fmt(w, "#align(%lld)", cast(long long)type->Struct.custom_align); @@ -698,6 +917,14 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { if (i > 0) { type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR); } + + if (f->flags & EntityFlags_IsSubtype) { + type_writer_appendc(w, "#subtype "); + } + + if (f->flags & EntityFlag_Using) { + type_writer_appendc(w, "using "); + } type_writer_append(w, f->token.string.text, f->token.string.len); type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR); write_type_to_canonical_string(w, f->type); @@ -756,15 +983,18 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { type_writer_appendc(w, "/"); write_type_to_canonical_string(w, type->Generic.specialized); } + } else if (type->Generic.specialized) { + // If we have a specialized type, use that instead of panicking + write_type_to_canonical_string(w, type->Generic.specialized); } else { - GB_PANIC("Type_Generic should never be hit"); + // For unspecialized generics, use a generic placeholder string + type_writer_appendc(w, "rawptr"); } return; case Type_Named: if (type->Named.type_name != nullptr) { write_canonical_entity_name(w, type->Named.type_name); - return; } else { type_writer_append(w, type->Named.name.text, type->Named.name.len); } diff --git a/src/name_canonicalization.hpp b/src/name_canonicalization.hpp index 304aff42e..00b450fbe 100644 --- a/src/name_canonicalization.hpp +++ b/src/name_canonicalization.hpp @@ -102,6 +102,8 @@ gb_internal Type *type_set_add (TypeSet *s, Type *ptr); gb_internal Type *type_set_add (TypeSet *s, TypeInfoPair pair); gb_internal bool type_set_update (TypeSet *s, Type *ptr); // returns true if it previously existed gb_internal bool type_set_update (TypeSet *s, TypeInfoPair pair); // returns true if it previously existed +gb_internal bool type_set_update_with_mutex(TypeSet *s, TypeInfoPair pair, RWSpinLock *m); +gb_internal bool type_set_update_with_mutex(TypeSet *s, Type *ptr, RWSpinLock *m); gb_internal bool type_set_exists (TypeSet *s, Type *ptr); gb_internal void type_set_remove (TypeSet *s, Type *ptr); gb_internal void type_set_clear (TypeSet *s); diff --git a/src/parser.cpp b/src/parser.cpp index a397585e8..03e9073ca 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,5 +1,7 @@ #include "parser_pos.cpp" +gb_global std::atomic g_parsing_done; + gb_internal bool in_vet_packages(AstFile *file) { if (file == nullptr) { return true; @@ -33,6 +35,10 @@ gb_internal bool ast_file_vet_deprecated(AstFile *f) { return (ast_file_vet_flags(f) & VetFlag_Deprecated) != 0; } +gb_internal bool ast_file_vet_explicit_allocators(AstFile *f) { + return (ast_file_vet_flags(f) & VetFlag_ExplicitAllocators) != 0; +} + gb_internal bool file_allow_newline(AstFile *f) { bool is_strict = build_context.strict_style || ast_file_vet_style(f); return !is_strict; @@ -172,7 +178,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) { return nullptr; } if (f == nullptr) { - f = node->thread_safe_file(); + if (g_parsing_done.load(std::memory_order_relaxed)) { + f = node->file(); + } else { + f = node->thread_safe_file(); + } } Ast *n = alloc_ast_node(f, node->kind); gb_memmove(n, node, ast_node_size(node->kind)); @@ -343,12 +353,14 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) { break; case Ast_RangeStmt: n->RangeStmt.label = clone_ast(n->RangeStmt.label, f); + n->RangeStmt.init = clone_ast(n->RangeStmt.init, f); n->RangeStmt.vals = clone_ast_array(n->RangeStmt.vals, f); n->RangeStmt.expr = clone_ast(n->RangeStmt.expr, f); n->RangeStmt.body = clone_ast(n->RangeStmt.body, f); break; case Ast_UnrollRangeStmt: n->UnrollRangeStmt.args = clone_ast_array(n->UnrollRangeStmt.args, f); + n->UnrollRangeStmt.init = clone_ast(n->UnrollRangeStmt.init, f); n->UnrollRangeStmt.val0 = clone_ast(n->UnrollRangeStmt.val0, f); n->UnrollRangeStmt.val1 = clone_ast(n->UnrollRangeStmt.val1, f); n->UnrollRangeStmt.expr = clone_ast(n->UnrollRangeStmt.expr, f); @@ -444,6 +456,12 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) { break; case Ast_DynamicArrayType: n->DynamicArrayType.elem = clone_ast(n->DynamicArrayType.elem, f); + n->DynamicArrayType.tag = clone_ast(n->DynamicArrayType.tag, f); + break; + case Ast_FixedCapacityDynamicArrayType: + n->FixedCapacityDynamicArrayType.elem = clone_ast(n->FixedCapacityDynamicArrayType.elem, f); + n->FixedCapacityDynamicArrayType.capacity = clone_ast(n->FixedCapacityDynamicArrayType.capacity, f); + n->FixedCapacityDynamicArrayType.tag = clone_ast(n->FixedCapacityDynamicArrayType.tag, f); break; case Ast_StructType: n->StructType.fields = clone_ast_array(n->StructType.fields, f); @@ -504,6 +522,22 @@ gb_internal void error(Ast *node, char const *fmt, ...) { } } +gb_internal void error_range(TokenPos start, TokenPos end, char const *fmt, ...) { + GB_ASSERT(start.file_id == end.file_id); + GB_ASSERT(start.line == end.line); + GB_ASSERT(start.column <= end.column); + GB_ASSERT(start.offset <= end.offset); + + va_list va; + va_start(va, fmt); + error_va(start, end, fmt, va); + va_end(va); + if (start.file_id != 0) { + AstFile *f = thread_safe_get_ast_file_from_id(start.file_id); + f->error_count += 1; + } +} + gb_internal void syntax_error_with_verbose(Ast *node, char const *fmt, ...) { Token token = {}; TokenPos end_pos = {}; @@ -739,7 +773,9 @@ gb_internal Ast *ast_matrix_index_expr(AstFile *f, Ast *expr, Token open, Token gb_internal Ast *ast_ident(AstFile *f, Token token) { Ast *result = alloc_ast_node(f, Ast_Ident); - result->Ident.token = token; + result->Ident.token = token; + result->Ident.hash = string_hash(token.string); + result->Ident.interned = string_interner_insert(token.string); return result; } @@ -756,6 +792,7 @@ gb_internal Ast *ast_uninit(AstFile *f, Token token) { gb_internal ExactValue exact_value_from_token(AstFile *f, Token const &token) { String s = token.string; + string_interner_insert(s); switch (token.kind) { case Token_Rune: if (!unquote_string(ast_allocator(f), &s, 0)) { @@ -775,7 +812,12 @@ gb_internal ExactValue exact_value_from_token(AstFile *f, Token const &token) { syntax_error(token, "Invalid integer literal"); break; case Token_Float: - syntax_error(token, "Invalid float literal"); + // NOTE(Jeroen): Could be an integer, see `exact_value_float_from_string` + if (!string_contains_char(s, '.') && !string_contains_char(s, '-')) { + syntax_error(token, "Invalid integer literal"); + } else { + syntax_error(token, "Invalid float literal"); + } break; default: syntax_error(token, "Invalid token literal"); @@ -807,6 +849,7 @@ gb_internal Ast *ast_basic_directive(AstFile *f, Token token, Token name) { Ast *result = alloc_ast_node(f, Ast_BasicDirective); result->BasicDirective.token = token; result->BasicDirective.name = name; + string_interner_insert(name.string); if (string_starts_with(name.string, str_lit("load"))) { f->seen_load_directive_count++; } @@ -1028,9 +1071,10 @@ gb_internal Ast *ast_for_stmt(AstFile *f, Token token, Ast *init, Ast *cond, Ast return result; } -gb_internal Ast *ast_range_stmt(AstFile *f, Token token, Slice vals, Token in_token, Ast *expr, Ast *body) { +gb_internal Ast *ast_range_stmt(AstFile *f, Token token, Ast *init, Slice vals, Token in_token, Ast *expr, Ast *body) { Ast *result = alloc_ast_node(f, Ast_RangeStmt); result->RangeStmt.token = token; + result->RangeStmt.init = init; result->RangeStmt.vals = vals; result->RangeStmt.in_token = in_token; result->RangeStmt.expr = expr; @@ -1038,9 +1082,10 @@ gb_internal Ast *ast_range_stmt(AstFile *f, Token token, Slice vals, Toke return result; } -gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Slice args, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) { +gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Ast *init, Slice args, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) { Ast *result = alloc_ast_node(f, Ast_UnrollRangeStmt); result->UnrollRangeStmt.unroll_token = unroll_token; + result->UnrollRangeStmt.init = init; result->UnrollRangeStmt.args = args; result->UnrollRangeStmt.for_token = for_token; result->UnrollRangeStmt.val0 = val0; @@ -1218,8 +1263,16 @@ gb_internal Ast *ast_dynamic_array_type(AstFile *f, Token token, Ast *elem) { return result; } +gb_internal Ast *ast_fixed_capacity_dynamic_array_type(AstFile *f, Token token, Ast *capacity, Ast *elem) { + Ast *result = alloc_ast_node(f, Ast_FixedCapacityDynamicArrayType); + result->FixedCapacityDynamicArrayType.token = token; + result->FixedCapacityDynamicArrayType.capacity = capacity; + result->FixedCapacityDynamicArrayType.elem = elem; + return result; +} + gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice fields, isize field_count, - Ast *polymorphic_params, bool is_packed, bool is_raw_union, bool is_no_copy, + Ast *polymorphic_params, bool is_packed, bool is_raw_union, bool is_all_or_none, bool is_simple, Ast *align, Ast *min_field_align, Ast *max_field_align, Token where_token, Array const &where_clauses) { Ast *result = alloc_ast_node(f, Ast_StructType); @@ -1229,7 +1282,8 @@ gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice fields, i result->StructType.polymorphic_params = polymorphic_params; result->StructType.is_packed = is_packed; result->StructType.is_raw_union = is_raw_union; - result->StructType.is_no_copy = is_no_copy; + result->StructType.is_all_or_none = is_all_or_none; + result->StructType.is_simple = is_simple; result->StructType.align = align; result->StructType.min_field_align = min_field_align; result->StructType.max_field_align = max_field_align; @@ -1402,9 +1456,6 @@ gb_internal Token consume_comment(AstFile *f, isize *end_line_) { if (end_line_) *end_line_ = end_line; next_token0(f); - if (f->curr_token.pos.line > tok.pos.line || tok.kind == Token_EOF) { - end_line++; - } return tok; } @@ -1428,7 +1479,7 @@ gb_internal CommentGroup *consume_comment_group(AstFile *f, isize n, isize *end_ CommentGroup *comments = nullptr; if (list.count > 0) { - comments = gb_alloc_item(permanent_allocator(), CommentGroup); + comments = permanent_alloc_item(); comments->list = slice_from_array(list); array_add(&f->comments, comments); } @@ -1436,27 +1487,30 @@ gb_internal CommentGroup *consume_comment_group(AstFile *f, isize n, isize *end_ } gb_internal void consume_comment_groups(AstFile *f, Token prev) { - if (f->curr_token.kind == Token_Comment) { - CommentGroup *comment = nullptr; - isize end_line = 0; - - if (f->curr_token.pos.line == prev.pos.line) { - comment = consume_comment_group(f, 0, &end_line); - if (f->curr_token.pos.line != end_line || f->curr_token.kind == Token_EOF) { - f->line_comment = comment; - } - } - - end_line = -1; - while (f->curr_token.kind == Token_Comment) { - comment = consume_comment_group(f, 1, &end_line); - } - if (end_line+1 == f->curr_token.pos.line || end_line < 0) { - f->lead_comment = comment; - } - - GB_ASSERT(f->curr_token.kind != Token_Comment); + if (f->curr_token.kind != Token_Comment) { + return; } + CommentGroup *comment = nullptr; + isize end_line = 0; + + if (f->curr_token.pos.line == prev.pos.line) { + comment = consume_comment_group(f, 0, &end_line); + if (f->curr_token.pos.line != end_line || + f->curr_token.pos.line == prev.pos.line+1 || + f->curr_token.kind == Token_EOF) { + f->line_comment = comment; + } + } + + end_line = -1; + while (f->curr_token.kind == Token_Comment) { + comment = consume_comment_group(f, 1, &end_line); + } + if (end_line+1 == f->curr_token.pos.line || end_line < 0) { + f->lead_comment = comment; + } + + GB_ASSERT(f->curr_token.kind != Token_Comment); } gb_internal gb_inline bool ignore_newlines(AstFile *f) { @@ -1985,9 +2039,6 @@ gb_internal Ast *parse_literal_value(AstFile *f, Ast *type) { } gb_internal Ast *parse_value(AstFile *f) { - if (f->curr_token.kind == Token_OpenBrace) { - return parse_literal_value(f, nullptr); - } Ast *value; bool prev_allow_range = f->allow_range; f->allow_range = true; @@ -2006,54 +2057,6 @@ gb_internal void check_proc_add_tag(AstFile *f, Ast *tag_expr, u64 *tags, ProcTa *tags |= tag; } -gb_internal bool is_foreign_name_valid(String const &name) { - if (name.len == 0) { - return false; - } - isize offset = 0; - while (offset < name.len) { - Rune rune; - isize remaining = name.len - offset; - isize width = utf8_decode(name.text+offset, remaining, &rune); - if (rune == GB_RUNE_INVALID && width == 1) { - return false; - } else if (rune == GB_RUNE_BOM && remaining > 0) { - return false; - } - - if (offset == 0) { - switch (rune) { - case '-': - case '$': - case '.': - case '_': - break; - default: - if (!gb_char_is_alpha(cast(char)rune)) - return false; - break; - } - } else { - switch (rune) { - case '-': - case '$': - case '.': - case '_': - break; - default: - if (!gb_char_is_alphanumeric(cast(char)rune)) { - return false; - } - break; - } - } - - offset += width; - } - - return true; -} - gb_internal void parse_proc_tags(AstFile *f, u64 *tags) { GB_ASSERT(tags != nullptr); @@ -2162,38 +2165,50 @@ gb_internal bool ast_on_same_line(Token const &x, Ast *yp) { return x.pos.line == y.pos.line; } -gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) { +gb_internal Ast *parse_inlining_or_tailing_operand(AstFile *f, Token token) { Ast *expr = parse_unary_expr(f, false); Ast *e = strip_or_return_expr(expr); if (e == nullptr) { return expr; } if (e->kind != Ast_ProcLit && e->kind != Ast_CallExpr) { - syntax_error(expr, "%.*s must be followed by a procedure literal or call, got %.*s", LIT(token.string), LIT(ast_strings[expr->kind])); + syntax_error(expr, "%.*s must be followed by a procedure literal or call, got %.*s", LIT(token.string), LIT(ast_strings[e->kind])); return ast_bad_expr(f, token, f->curr_token); } ProcInlining pi = ProcInlining_none; + ProcTailing pt = ProcTailing_none; if (token.kind == Token_Ident) { if (token.string == "force_inline") { pi = ProcInlining_inline; } else if (token.string == "force_no_inline") { pi = ProcInlining_no_inline; + } else if (token.string == "must_tail") { + pt = ProcTailing_must_tail; } } if (pi != ProcInlining_none) { if (e->kind == Ast_ProcLit) { - if (expr->ProcLit.inlining != ProcInlining_none && - expr->ProcLit.inlining != pi) { + if (e->ProcLit.inlining != ProcInlining_none && + e->ProcLit.inlining != pi) { syntax_error(expr, "Cannot apply both '#force_inline' and '#force_no_inline' to a procedure literal"); } - expr->ProcLit.inlining = pi; + e->ProcLit.inlining = pi; } else if (e->kind == Ast_CallExpr) { - if (expr->CallExpr.inlining != ProcInlining_none && - expr->CallExpr.inlining != pi) { + if (e->CallExpr.inlining != ProcInlining_none && + e->CallExpr.inlining != pi) { syntax_error(expr, "Cannot apply both '#force_inline' and '#force_no_inline' to a procedure call"); } - expr->CallExpr.inlining = pi; + e->CallExpr.inlining = pi; + } + } + + if (pt != ProcTailing_none) { + if (e->kind == Ast_ProcLit) { + syntax_error(expr, "'#must_call' can only be applied to a procedure call, not the procedure literal"); + e->ProcLit.tailing = pt; + } else if (e->kind == Ast_CallExpr) { + e->CallExpr.tailing = pt; } } @@ -2421,9 +2436,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { Ast *original_type = parse_type(f); Ast *type = unparen_expr(original_type); switch (type->kind) { - case Ast_ArrayType: type->ArrayType.tag = tag; break; - case Ast_DynamicArrayType: type->DynamicArrayType.tag = tag; break; - case Ast_PointerType: type->PointerType.tag = tag; break; + case Ast_ArrayType: type->ArrayType.tag = tag; break; + case Ast_DynamicArrayType: type->DynamicArrayType.tag = tag; break; + case Ast_PointerType: type->PointerType.tag = tag; break; + case Ast_FixedCapacityDynamicArrayType: type->FixedCapacityDynamicArrayType.tag = tag; break; default: syntax_error(type, "Expected an array or pointer type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind])); break; @@ -2493,8 +2509,9 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(tag, "#relative types have now been removed in favour of \"core:relative\""); return ast_relative_type(f, tag, type); } else if (name.string == "force_inline" || - name.string == "force_no_inline") { - return parse_force_inlining_operand(f, name); + name.string == "force_no_inline" || + name.string == "must_tail") { + return parse_inlining_or_tailing_operand(f, name); } return ast_basic_directive(f, token, name); } @@ -2511,8 +2528,14 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { while (f->curr_token.kind != Token_CloseBrace && f->curr_token.kind != Token_EOF) { Ast *elem = parse_expr(f, false); - array_add(&args, elem); + if (f->curr_token.kind == Token_where) { + Token where = expect_token(f, Token_where); + Ast *cond = parse_expr(f, false); + elem = ast_binary_expr(f, where, elem, cond); + } + + array_add(&args, elem); if (!allow_field_separator(f)) { break; } @@ -2652,8 +2675,25 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { } else if (f->curr_token.kind == Token_Question) { count_expr = ast_unary_expr(f, expect_token(f, Token_Question), nullptr); } else if (allow_token(f, Token_dynamic)) { + Ast *capacity = nullptr; + if (f->curr_token.kind == Token_Semicolon && f->curr_token.string == ";") { + expect_token(f, Token_Semicolon); + capacity = parse_expr(f, false); + } else if (allow_token(f, Token_Comma) || allow_token(f, Token_Semicolon)) { + String p = token_to_string(f->prev_token); + syntax_error(token_end_of_line(f, f->prev_token), "Expected a semicolon, got a %.*s", LIT(p)); + + capacity = parse_expr(f, false); + } expect_token(f, Token_CloseBracket); - return ast_dynamic_array_type(f, token, parse_type(f)); + + Ast *elem = parse_type(f); + + if (capacity == nullptr) { + return ast_dynamic_array_type(f, token, elem); + } else { + return ast_fixed_capacity_dynamic_array_type(f, token, capacity, elem); + } } else if (f->curr_token.kind != Token_CloseBracket) { f->expr_level++; count_expr = parse_expr(f, false); @@ -2725,7 +2765,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { while (allow_token(f, Token_Comma)) { Ast *dummy_name = parse_ident(f); if (!err_once) { - error(dummy_name, "'bit_field' fields do not support multiple names per field"); + syntax_error(dummy_name, "'bit_field' fields do not support multiple names per field"); err_once = true; } } @@ -2759,8 +2799,9 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { Token token = expect_token(f, Token_struct); Ast *polymorphic_params = nullptr; bool is_packed = false; + bool is_all_or_none = false; bool is_raw_union = false; - bool no_copy = false; + bool is_simple = false; Ast *align = nullptr; Ast *min_field_align = nullptr; Ast *max_field_align = nullptr; @@ -2788,6 +2829,11 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); } is_packed = true; + } else if (tag.string == "all_or_none") { + if (is_all_or_none) { + syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); + } + is_all_or_none = true; } else if (tag.string == "align") { if (align) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); @@ -2837,16 +2883,16 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { error_line("\tSuggestion: #max_field_align(%s)", s); gb_string_free(s); } - }else if (tag.string == "raw_union") { + } else if (tag.string == "raw_union") { if (is_raw_union) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); } is_raw_union = true; - } else if (tag.string == "no_copy") { - if (no_copy) { + } else if (tag.string == "simple") { + if (is_simple) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); } - no_copy = true; + is_simple = true; } else { syntax_error(tag, "Invalid struct tag '#%.*s'", LIT(tag.string)); } @@ -2854,9 +2900,9 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { f->expr_level = prev_level; - if (is_raw_union && is_packed) { - is_packed = false; - syntax_error(token, "'#raw_union' cannot also be '#packed'"); + if (is_raw_union && is_all_or_none) { + is_all_or_none = false; + syntax_error(token, "'#raw_union' cannot also be '#all_or_none'"); } Token where_token = {}; @@ -2887,7 +2933,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { parser_check_polymorphic_record_parameters(f, polymorphic_params); - return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_raw_union, no_copy, align, min_field_align, max_field_align, where_token, where_clauses); + return ast_struct_type(f, token, decls, name_count, + polymorphic_params, is_packed, is_raw_union, is_all_or_none, is_simple, + align, min_field_align, max_field_align, + where_token, where_clauses); } break; case Token_union: { @@ -3089,6 +3138,8 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { } else { dialect = InlineAsmDialect_Intel; } + } else { + syntax_error(token, "Invalid directive on inline asm expression: '#%.*s'", LIT(token.string)); } } else { syntax_error(f->curr_token, "Expected an identifier after hash"); @@ -3121,6 +3172,7 @@ gb_internal bool is_literal_type(Ast *node) { case Ast_StructType: case Ast_UnionType: case Ast_EnumType: + case Ast_FixedCapacityDynamicArrayType: case Ast_DynamicArrayType: case Ast_MapType: case Ast_BitSetType: @@ -3274,6 +3326,8 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { case Token_OpenBracket: { bool prev_allow_range = f->allow_range; f->allow_range = false; + defer (f->allow_range = prev_allow_range); + Token open = {}, close = {}, interval = {}; Ast *indices[2] = {}; @@ -3282,6 +3336,21 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { f->expr_level++; open = expect_token(f, Token_OpenBracket); + if (f->curr_token.kind == Token_CloseBracket) { + ERROR_BLOCK(); + syntax_error(f->curr_token, "Expected an operand, got ]"); + close = expect_token(f, Token_CloseBracket); + + if (f->allow_type) { + gbString s = expr_to_string(operand); + error_line("\tSuggestion: If a type was wanted, did you mean '[]%s'?", s); + gb_string_free(s); + } + + operand = ast_index_expr(f, operand, nullptr, open, close); + break; + } + switch (f->curr_token.kind) { case Token_Ellipsis: case Token_RangeFull: @@ -3331,7 +3400,6 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { operand = ast_index_expr(f, operand, indices[0], open, close); } - f->allow_range = prev_allow_range; } break; case Token_Pointer: // Deference @@ -3408,9 +3476,13 @@ gb_internal Ast *parse_unary_expr(AstFile *f, bool lhs) { case Token_Xor: case Token_And: case Token_Not: + case Token_MulMul: // 'expand_values' operator case Token_Mul: // Used for error handling when people do C-like things { Token token = advance_token(f); + if (token.kind == Token_Not) { + skip_possible_newline(f); + } Ast *expr = parse_unary_expr(f, lhs); return ast_unary_expr(f, token, expr); } @@ -3971,6 +4043,10 @@ gb_internal ProcCallingConvention string_to_calling_convention(String const &s) if (s == "win64") return ProcCC_Win64; if (s == "sysv") return ProcCC_SysV; + if (s == "preserve/none") return ProcCC_PreserveNone; + if (s == "preserve/most") return ProcCC_PreserveMost; + if (s == "preserve/all") return ProcCC_PreserveAll; + if (s == "system") { if (build_context.metrics.os == TargetOs_windows) { return ProcCC_StdCall; @@ -3982,6 +4058,71 @@ gb_internal ProcCallingConvention string_to_calling_convention(String const &s) return ProcCC_Invalid; } +gb_internal bool is_ast_generic(Ast *a) { + bool is_generic = false; + if (a != nullptr) { + switch (a->kind) { + case Ast_TypeidType: + is_generic = a->TypeidType.specialization != nullptr; + break; + case Ast_PolyType: + is_generic = true; + break; + case Ast_ProcType: + is_generic = a->ProcType.generic; + break; + case Ast_PointerType: + is_generic = is_ast_generic(a->PointerType.type); + break; + case Ast_MultiPointerType: + is_generic = is_ast_generic(a->MultiPointerType.type); + break; + case Ast_ArrayType: + is_generic = is_ast_generic(a->ArrayType.elem) || is_ast_generic(a->ArrayType.count); + break; + case Ast_DynamicArrayType: + is_generic = is_ast_generic(a->DynamicArrayType.elem); + break; + case Ast_FixedCapacityDynamicArrayType: + is_generic = is_ast_generic(a->FixedCapacityDynamicArrayType.elem) || is_ast_generic(a->FixedCapacityDynamicArrayType.capacity); + break; + case Ast_BitSetType: + is_generic = is_ast_generic(a->BitSetType.elem); + break; + case Ast_MapType: + is_generic = is_ast_generic(a->MapType.key) || is_ast_generic(a->MapType.value); + break; + case Ast_MatrixType: + is_generic = is_ast_generic(a->MatrixType.row_count) || is_ast_generic(a->MatrixType.column_count) || is_ast_generic(a->MatrixType.elem); + break; + } + } + return is_generic; +} + +gb_internal bool is_field_list_generic(AstFieldList *field_list, bool check_names) { + bool is_generic = false; + + for (Ast *param : field_list->list) { + ast_node(field, Field, param); + if (is_ast_generic(field->type)) { + is_generic = true; + goto end; + } + if (!check_names || field->type == nullptr) { + continue; + } + for (Ast *name : field->names) { + if (name->kind == Ast_PolyType) { + is_generic = true; + goto end; + } + } + } +end: + return is_generic; +} + gb_internal Ast *parse_proc_type(AstFile *f, Token proc_token) { Ast *params = nullptr; Ast *results = nullptr; @@ -4017,24 +4158,11 @@ gb_internal Ast *parse_proc_type(AstFile *f, Token proc_token) { results = parse_results(f, &diverging); u64 tags = 0; - bool is_generic = false; - - for (Ast *param : params->FieldList.list) { - ast_node(field, Field, param); - if (field->type != nullptr) { - if (field->type->kind == Ast_PolyType) { - is_generic = true; - goto end; - } - for (Ast *name : field->names) { - if (name->kind == Ast_PolyType) { - is_generic = true; - goto end; - } - } - } + bool is_generic = is_field_list_generic(¶ms->FieldList, true); + if (!is_generic && (results != nullptr)) { + is_generic = is_field_list_generic(&results->FieldList, false); } -end: + return ast_proc_type(f, proc_token, params, results, tags, cc, is_generic, diverging); } @@ -4092,18 +4220,33 @@ gb_internal FieldFlag is_token_field_prefix(AstFile *f) { return FieldFlag_using; case Token_Hash: - advance_token(f); - switch (f->curr_token.kind) { - case Token_Ident: - for (i32 i = 0; i < gb_count_of(parse_field_prefix_mappings); i++) { - auto const &mapping = parse_field_prefix_mappings[i]; - if (mapping.token_kind == Token_Hash) { - if (f->curr_token.string == mapping.name) { - return mapping.flag; - } + { + // Check for types first before fields + Token tok = peek_token(f); + if (tok.kind == Token_Ident) { + if (tok.string == "simd" || + tok.string == "type" || + tok.string == "row_major" || + tok.string == "column_major" || + tok.string == "sparse" || + tok.string == "soa") { + return FieldFlag_Invalid; } } - break; + + advance_token(f); + switch (f->curr_token.kind) { + case Token_Ident: + for (i32 i = 0; i < gb_count_of(parse_field_prefix_mappings); i++) { + auto const &mapping = parse_field_prefix_mappings[i]; + if (mapping.token_kind == Token_Hash) { + if (f->curr_token.string == mapping.name) { + return mapping.flag; + } + } + } + break; + } } return FieldFlag_Unknown; } @@ -4804,7 +4947,7 @@ gb_internal Ast *parse_for_stmt(AstFile *f) { body = parse_block_stmt(f, false); } - return ast_range_stmt(f, token, {}, in_token, rhs, body); + return ast_range_stmt(f, token, init, {}, in_token, rhs, body); } if (f->curr_token.kind != Token_Semicolon) { @@ -4819,9 +4962,21 @@ gb_internal Ast *parse_for_stmt(AstFile *f) { cond = nullptr; if (f->curr_token.kind == Token_OpenBrace || f->curr_token.kind == Token_do) { - syntax_error(f->curr_token, "Expected ';', followed by a condition expression and post statement, got %.*s", LIT(token_strings[f->curr_token.kind])); + syntax_error(f->curr_token, "Expected ';', followed by a condition expression and post statement, or 'x in y' style loop, got %.*s", LIT(token_strings[f->curr_token.kind])); } else { if (f->curr_token.kind != Token_Semicolon) { + if (f->curr_token.kind == Token_Ident) { + // for init; x in y { } + Token next_token = peek_token(f); + if (next_token.kind == Token_in || next_token.kind == Token_Comma) { + cond = parse_simple_stmt(f, StmtAllowFlag_In); + if (cond->kind == Ast_AssignStmt && cond->AssignStmt.op.kind == Token_in) { + is_range = true; + } + goto range_skip; + } + } + cond = parse_simple_stmt(f, StmtAllowFlag_None); } @@ -4839,6 +4994,7 @@ gb_internal Ast *parse_for_stmt(AstFile *f) { } } +range_skip:; if (allow_token(f, Token_do)) { body = parse_do_body(f, token, "the for statement"); @@ -4854,7 +5010,7 @@ gb_internal Ast *parse_for_stmt(AstFile *f) { if (cond->AssignStmt.rhs.count > 0) { rhs = cond->AssignStmt.rhs[0]; } - return ast_range_stmt(f, token, vals, in_token, rhs, body); + return ast_range_stmt(f, token, init, vals, in_token, rhs, body); } cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression")); @@ -5017,6 +5173,10 @@ gb_internal Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { syntax_error(import_name, "'using import' is not allowed, please use the import name explicitly"); } + if (file_path.string == "\".\"") { + // syntax_error(import_name, "Cannot cyclicly import packages"); + } + expect_semicolon(f); return s; } @@ -5184,6 +5344,7 @@ gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) { } Token for_token = expect_token(f, Token_for); + Ast *init = nullptr; Ast *val0 = nullptr; Ast *val1 = nullptr; Token in_token = {}; @@ -5226,7 +5387,7 @@ gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) { if (bad_stmt) { return ast_bad_stmt(f, unroll_token, f->curr_token); } - return ast_unroll_range_stmt(f, unroll_token, slice_from_array(args), for_token, val0, val1, in_token, expr, body); + return ast_unroll_range_stmt(f, unroll_token, init, slice_from_array(args), for_token, val0, val1, in_token, expr, body); } gb_internal Ast *parse_stmt(AstFile *f) { @@ -5251,7 +5412,10 @@ gb_internal Ast *parse_stmt(AstFile *f) { case Token_Xor: case Token_Not: case Token_And: - case Token_Mul: // Used for error handling when people do C-like things + // Used for error handling when people do C-like things + case Token_Mul: + case Token_Increment: + case Token_Decrement: s = parse_simple_stmt(f, StmtAllowFlag_Label); expect_semicolon(f); return s; @@ -5344,9 +5508,15 @@ gb_internal Ast *parse_stmt(AstFile *f) { s = parse_stmt(f); switch (s->kind) { case Ast_SwitchStmt: + if (s->SwitchStmt.partial) { + syntax_error(token, "#partial already applied to a switch statement"); + } s->SwitchStmt.partial = true; break; case Ast_TypeSwitchStmt: + if (s->TypeSwitchStmt.partial) { + syntax_error(token, "#partial already applied to a switch statement"); + } s->TypeSwitchStmt.partial = true; break; case Ast_EmptyStmt: @@ -5362,8 +5532,9 @@ gb_internal Ast *parse_stmt(AstFile *f) { expect_semicolon(f); return stmt; } else if (name.string == "force_inline" || - name.string == "force_no_inline") { - Ast *expr = parse_force_inlining_operand(f, name); + name.string == "force_no_inline" || + name.string == "must_tail") { + Ast *expr = parse_inlining_or_tailing_operand(f, name); Ast *stmt = ast_expr_stmt(f, expr); expect_semicolon(f); return stmt; @@ -5652,7 +5823,7 @@ gb_internal WORKER_TASK_PROC(parser_worker_proc) { ParserWorkerData *wd = cast(ParserWorkerData *)data; ParseFileError err = process_imported_file(wd->parser, wd->imported_file); if (err != ParseFile_None) { - auto *node = gb_alloc_item(permanent_allocator(), ParseFileErrorNode); + auto *node = permanent_alloc_item(); node->err = err; MUTEX_GUARD_BLOCK(&wd->parser->file_error_mutex) { @@ -5672,7 +5843,7 @@ gb_internal WORKER_TASK_PROC(parser_worker_proc) { gb_internal void parser_add_file_to_process(Parser *p, AstPackage *pkg, FileInfo fi, TokenPos pos) { ImportedFile f = {pkg, fi, pos, p->file_to_process_count++}; f.pos.file_id = cast(i32)(f.index+1); - auto wd = gb_alloc_item(permanent_allocator(), ParserWorkerData); + auto wd = permanent_alloc_item(); wd->parser = p; wd->imported_file = f; thread_pool_add_task(parser_worker_proc, wd); @@ -5709,7 +5880,7 @@ gb_internal void parser_add_foreign_file_to_process(Parser *p, AstPackage *pkg, // TODO(bill): Use a better allocator ImportedFile f = {pkg, fi, pos, p->file_to_process_count++}; f.pos.file_id = cast(i32)(f.index+1); - auto wd = gb_alloc_item(permanent_allocator(), ForeignFileWorkerData); + auto wd = permanent_alloc_item(); wd->parser = p; wd->imported_file = f; wd->foreign_kind = kind; @@ -5729,7 +5900,7 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const path = copy_string(permanent_allocator(), path); - AstPackage *pkg = gb_alloc_item(permanent_allocator(), AstPackage); + AstPackage *pkg = permanent_alloc_item(); pkg->kind = kind; pkg->fullpath = path; array_init(&pkg->files, permanent_allocator()); @@ -5781,12 +5952,17 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const return nullptr; } + if (string_ends_with(path, str_lit(".odin"))) { + error(pos, "'import' declarations cannot import directories with a .odin extension/suffix"); + return nullptr; + } + isize files_with_ext = 0; isize files_to_reserve = 1; // always reserve 1 for (FileInfo fi : list) { String name = fi.name; String ext = path_extension(name); - if (ext == FILE_EXT) { + if (ext == FILE_EXT && !fi.is_dir) { files_with_ext += 1; } if (ext == FILE_EXT && !is_excluded_target_filename(name)) { @@ -5811,7 +5987,7 @@ gb_internal AstPackage *try_add_import_path(Parser *p, String path, String const for (FileInfo fi : list) { String name = fi.name; String ext = path_extension(name); - if (ext == FILE_EXT) { + if (ext == FILE_EXT && !fi.is_dir) { if (is_excluded_target_filename(name)) { continue; } @@ -5959,6 +6135,12 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node has_windows_drive = true; } } + + for (isize i = 0; i < original_string.len; i++) { + if (original_string.text[i] == '\\') { + original_string.text[i] = '/'; + } + } } #endif @@ -6168,9 +6350,28 @@ gb_internal String build_tag_get_token(String s, String *out) { return s; } +// returns true on failure +gb_internal bool build_require_space_after(String s, String prefix) { + GB_ASSERT(string_starts_with(s, prefix)); + + if (s.len == prefix.len) { + return false; + } + String stripped = string_trim_whitespace(substring(s, prefix.len, s.len)); + + if (s[prefix.len] != ' ' && stripped.len != 0) { + return true; + } + return false; +} + gb_internal bool parse_build_tag(Token token_for_pos, String s) { String const prefix = str_lit("build"); GB_ASSERT(string_starts_with(s, prefix)); + if (build_require_space_after(s, prefix)) { + syntax_error(token_for_pos, "Expected a space after #+%.*s", LIT(prefix)); + return true; + } s = string_trim_whitespace(substring(s, prefix.len, s.len)); if (s.len == 0) { @@ -6209,9 +6410,15 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { continue; } - Subtarget subtarget = Subtarget_Default; + if (p == "bedrock") { + this_kind_correct = build_context.bedrock == !is_notted; + continue; + } - TargetOsKind os = get_target_os_from_string(p, &subtarget); + Subtarget subtarget = Subtarget_Invalid; + String subtarget_str = {}; + + TargetOsKind os = get_target_os_from_string(p, &subtarget, &subtarget_str); TargetArchKind arch = get_target_arch_from_string(p); num_tokens += 1; @@ -6222,10 +6429,29 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { break; } + bool is_ios_subtarget = false; + if (subtarget == Subtarget_Invalid) { + // Special case for pseudo subtarget + if (!str_eq_ignore_case(subtarget_str, "ios")) { + syntax_error(token_for_pos, "Invalid subtarget '%.*s'.", LIT(subtarget_str)); + break; + } + + is_ios_subtarget = true; + } + + if (os != TargetOs_Invalid) { this_kind_os_seen = true; - bool same_subtarget = (subtarget == Subtarget_Default) || (subtarget == selected_subtarget); + // NOTE: Only testing for 'default' and not 'generic' because the 'generic' nomenclature implies any subtarget. + bool is_explicit_default_subtarget = str_eq_ignore_case(subtarget_str, "default"); + bool same_subtarget = (subtarget == Subtarget_Default && !is_explicit_default_subtarget) || (subtarget == selected_subtarget); + + // Special case for iPhone or iPhoneSimulator + if (is_ios_subtarget && (selected_subtarget == Subtarget_iPhone || selected_subtarget == Subtarget_iPhoneSimulator)) { + same_subtarget = true; + } GB_ASSERT(arch == TargetArch_Invalid); if (is_notted) { @@ -6254,7 +6480,7 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { return any_correct; } -gb_internal String vet_tag_get_token(String s, String *out) { +gb_internal String vet_tag_get_token(String s, String *out, bool allow_colon) { s = string_trim_whitespace(s); isize n = 0; while (n < s.len) { @@ -6262,7 +6488,7 @@ gb_internal String vet_tag_get_token(String s, String *out) { isize width = utf8_decode(&s[n], s.len-n, &rune); if (n == 0 && rune == '!') { - } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != '-') { + } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != '-' && !(allow_colon && rune == ':')) { isize k = gb_max(gb_max(n, width), 1); *out = substring(s, k, s.len); return substring(s, 0, k); @@ -6274,21 +6500,23 @@ gb_internal String vet_tag_get_token(String s, String *out) { } -gb_internal u64 parse_vet_tag(Token token_for_pos, String s) { +gb_internal u64 parse_vet_tag(Token token_for_pos, String s, u64 base_vet_flags) { String const prefix = str_lit("vet"); GB_ASSERT(string_starts_with(s, prefix)); + if (build_require_space_after(s, prefix)) { + syntax_error(token_for_pos, "Expected a space after #+%.*s", LIT(prefix)); + return true; + } s = string_trim_whitespace(substring(s, prefix.len, s.len)); + u64 vet_flags = base_vet_flags; + if (s.len == 0) { - return VetFlag_All; + vet_flags |= VetFlag_All; } - - u64 vet_flags = 0; - u64 vet_not_flags = 0; - while (s.len > 0) { - String p = string_trim_whitespace(vet_tag_get_token(s, &s)); + String p = string_trim_whitespace(vet_tag_get_token(s, &s, /*allow_colon*/false)); if (p.len == 0) { break; } @@ -6299,16 +6527,16 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) { p = substring(p, 1, p.len); if (p.len == 0) { syntax_error(token_for_pos, "Expected a vet flag name after '!'"); - return build_context.vet_flags; + return vet_flags; } } u64 flag = get_vet_flag_from_name(p); if (flag != VetFlag_NONE) { if (is_notted) { - vet_not_flags |= flag; + vet_flags = vet_flags &~ flag; } else { - vet_flags |= flag; + vet_flags |= flag; } } else { ERROR_BLOCK(); @@ -6325,26 +6553,21 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) { error_line("\textra\n"); error_line("\tcast\n"); error_line("\ttabs\n"); - return build_context.vet_flags; + error_line("\texplicit-allocators\n"); + return vet_flags; } } - if (vet_flags == 0 && vet_not_flags == 0) { - return build_context.vet_flags; - } - if (vet_flags == 0 && vet_not_flags != 0) { - return build_context.vet_flags &~ vet_not_flags; - } - if (vet_flags != 0 && vet_not_flags == 0) { - return vet_flags; - } - GB_ASSERT(vet_flags != 0 && vet_not_flags != 0); - return vet_flags &~ vet_not_flags; + return vet_flags; } gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { String const prefix = str_lit("feature"); GB_ASSERT(string_starts_with(s, prefix)); + if (build_require_space_after(s, prefix)) { + syntax_error(token_for_pos, "Expected a space after #+%.*s", LIT(prefix)); + return true; + } s = string_trim_whitespace(substring(s, prefix.len, s.len)); if (s.len == 0) { @@ -6355,7 +6578,7 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { u64 feature_not_flags = 0; while (s.len > 0) { - String p = string_trim_whitespace(vet_tag_get_token(s, &s)); + String p = string_trim_whitespace(vet_tag_get_token(s, &s, /*allow_colon*/true)); if (p.len == 0) { break; } @@ -6377,26 +6600,49 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { } else { feature_flags |= flag; } + if (is_notted) { + switch (flag) { + case OptInFeatureFlag_IntegerDivisionByZero_Trap: + case OptInFeatureFlag_IntegerDivisionByZero_Zero: + case OptInFeatureFlag_IntegerDivisionByZero_AllBits: + syntax_error(token_for_pos, "Feature flag does not support notting with '!' - '%.*s'", LIT(p)); + break; + } + } } else { ERROR_BLOCK(); syntax_error(token_for_pos, "Invalid feature flag name: %.*s", LIT(p)); error_line("\tExpected one of the following\n"); error_line("\tdynamic-literals\n"); + error_line("\tglobal-context\n"); + error_line("\tusing-stmt\n"); + error_line("\tinteger-division-by-zero:trap\n"); + error_line("\tinteger-division-by-zero:zero\n"); + error_line("\tinteger-division-by-zero:self\n"); + error_line("\tinteger-division-by-zero:all-bits\n"); return OptInFeatureFlag_NONE; } } + u64 res = OptInFeatureFlag_NONE; + if (feature_flags == 0 && feature_not_flags == 0) { - return OptInFeatureFlag_NONE; + res = OptInFeatureFlag_NONE; + } else if (feature_flags == 0 && feature_not_flags != 0) { + res = OptInFeatureFlag_NONE &~ feature_not_flags; + } else if (feature_flags != 0 && feature_not_flags == 0) { + res = feature_flags; + } else { + GB_ASSERT(feature_flags != 0 && feature_not_flags != 0); + res = feature_flags &~ feature_not_flags; } - if (feature_flags == 0 && feature_not_flags != 0) { - return OptInFeatureFlag_NONE &~ feature_not_flags; + + u64 idbz_count = gb_count_set_bits(res & OptInFeatureFlag_IntegerDivisionByZero_ALL); + if (idbz_count > 1) { + syntax_error(token_for_pos, "Only one integer-division-by-zero feature flag can be enabled"); } - if (feature_flags != 0 && feature_not_flags == 0) { - return feature_flags; - } - GB_ASSERT(feature_flags != 0 && feature_not_flags != 0); - return feature_flags &~ feature_not_flags; + + return res; } gb_internal String dir_from_path(String path) { @@ -6497,8 +6743,12 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f) return false; } } else if (string_starts_with(lc, str_lit("vet"))) { - f->vet_flags = parse_vet_tag(tok, lc); + f->vet_flags = parse_vet_tag(tok, lc, ast_file_vet_flags(f)); f->vet_flags_set = true; + } else if (string_starts_with(lc, str_lit("test"))) { + if ((build_context.command_kind & Command_test) == 0) { + return false; + } } else if (string_starts_with(lc, str_lit("ignore"))) { return false; } else if (string_starts_with(lc, str_lit("private"))) { @@ -6526,7 +6776,7 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f) } else if (lc == "no-instrumentation") { f->flags |= AstFile_NoInstrumentation; } else { - error(tok, "Unknown tag '%.*s'", LIT(lc)); + syntax_error(tok, "Unknown tag '%.*s'", LIT(lc)); } return true; @@ -6544,11 +6794,6 @@ gb_internal bool parse_file(Parser *p, AstFile *f) { String filepath = f->tokenizer.fullpath; String base_dir = dir_from_path(filepath); - if (f->curr_token.kind == Token_Comment) { - consume_comment_groups(f, f->prev_token); - } - - CommentGroup *docs = f->lead_comment; Array tags = array_make(temporary_allocator()); bool first_invalid_token_set = false; @@ -6570,6 +6815,8 @@ gb_internal bool parse_file(Parser *p, AstFile *f) { } } + CommentGroup *docs = f->lead_comment; + if (f->curr_token.kind != Token_package) { ERROR_BLOCK(); @@ -6609,37 +6856,12 @@ gb_internal bool parse_file(Parser *p, AstFile *f) { } f->package_name = package_name.string; - { - if (docs != nullptr && docs->list.count > 0) { - for (Token const &tok : docs->list) { - GB_ASSERT(tok.kind == Token_Comment); - String str = tok.string; - - if (!string_starts_with(str, str_lit("//"))) { - continue; - } - - String lc = string_trim_whitespace(substring(str, 2, str.len)); - if (string_starts_with(lc, str_lit("+"))) { - syntax_warning(tok, "'//+' is deprecated: Use '#+' instead"); - String lt = substring(lc, 1, lc.len); - if (parse_file_tag(lt, tok, f) == false) { - return false; - } - } - } - } - - for (Token const &tok : tags) { - GB_ASSERT(tok.kind == Token_FileTag); - String str = tok.string; - - if (string_starts_with(str, str_lit("#+"))) { - String lt = string_trim_whitespace(substring(str, 2, str.len)); - if (parse_file_tag(lt, tok, f) == false) { - return false; - } - } + for (Token const &tok : tags) { + GB_ASSERT(tok.kind == Token_FileTag); + GB_ASSERT(string_starts_with(tok.string, str_lit("#+"))); + String lt = string_trim_whitespace(substring(tok.string, 2, tok.string.len)); + if (parse_file_tag(lt, tok, f) == false) { + return false; } } @@ -6689,7 +6911,7 @@ gb_internal ParseFileError process_imported_file(Parser *p, ImportedFile importe FileInfo fi = imported_file.fi; TokenPos pos = imported_file.pos; - AstFile *file = gb_alloc_item(permanent_allocator(), AstFile); + AstFile *file = permanent_alloc_item(); file->pkg = pkg; file->id = cast(i32)(imported_file.index+1); TokenPos err_pos = {0}; @@ -6869,6 +7091,8 @@ gb_internal ParseFileError parse_packages(Parser *p, String init_filename) { } } + g_parsing_done.store(true, std::memory_order_relaxed); + return ParseFile_None; } diff --git a/src/parser.hpp b/src/parser.hpp index d2dd22667..e423cb9b2 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -27,10 +27,29 @@ enum AddressingMode : u8 { Addressing_SwizzleVariable = 14, // Swizzle indexed variable }; +gb_global String const addressing_mode_strings[] = { + str_lit("Invalid"), + str_lit("NoValue"), + str_lit("Value"), + str_lit("Context"), + str_lit("Variable"), + str_lit("Constant"), + str_lit("Type"), + str_lit("Builtin"), + str_lit("ProcGroup"), + str_lit("MapIndex"), + str_lit("OptionalOk"), + str_lit("OptionalOkPtr"), + str_lit("SoaVariable"), + str_lit("SwizzleValue"), + str_lit("SwizzleVariable"), +}; + struct TypeAndValue { Type * type; AddressingMode mode; - bool is_lhs; // Debug info + bool is_lhs; // Debug info + Type * objc_super_target; // Original type of the Obj-C object before being converted to the superclass' type by the objc_super() intrinsic. ExactValue value; }; @@ -244,12 +263,17 @@ struct ForeignFileWorkerData { -enum ProcInlining { - ProcInlining_none = 0, - ProcInlining_inline = 1, +enum ProcInlining : u8 { + ProcInlining_none = 0, + ProcInlining_inline = 1, ProcInlining_no_inline = 2, }; +enum ProcTailing : u8 { + ProcTailing_none = 0, + ProcTailing_must_tail = 1, +}; + enum ProcTag { ProcTag_bounds_check = 1<<0, ProcTag_no_bounds_check = 1<<1, @@ -277,6 +301,9 @@ enum ProcCallingConvention : i32 { ProcCC_Win64 = 9, ProcCC_SysV = 10, + ProcCC_PreserveNone = 11, + ProcCC_PreserveMost = 12, + ProcCC_PreserveAll = 13, ProcCC_MAX, @@ -296,9 +323,15 @@ gb_global char const *proc_calling_convention_strings[ProcCC_MAX] = { "inlineasm", "win64", "sysv", + "preserve/none", + "preserve/most", + "preserve/all", }; gb_internal ProcCallingConvention default_calling_convention(void) { + if (build_context.bedrock) { + // return ProcCC_Contextless; + } return ProcCC_Odin; } @@ -394,8 +427,10 @@ struct AstSplitArgs { #define AST_KINDS \ AST_KIND(Ident, "identifier", struct { \ - Token token; \ - Entity *entity; \ + Token token; \ + std::atomic entity; \ + u32 hash; \ + InternedString interned; \ }) \ AST_KIND(Implicit, "implicit", Token) \ AST_KIND(Uninit, "uninitialized value", Token) \ @@ -421,6 +456,7 @@ struct AstSplitArgs { Ast *body; \ u64 tags; \ ProcInlining inlining; \ + ProcTailing tailing; \ Token where_token; \ Slice where_clauses; \ DeclInfo *decl; \ @@ -466,6 +502,7 @@ AST_KIND(_ExprBegin, "", bool) \ Token close; \ Token ellipsis; \ ProcInlining inlining; \ + ProcTailing tailing; \ bool optional_ok_one; \ bool was_selector; \ AstSplitArgs *split_args; \ @@ -554,6 +591,7 @@ AST_KIND(_ComplexStmtBegin, "", bool) \ Scope *scope; \ Token token; \ Ast *label; \ + Ast *init; \ Slice vals; \ Token in_token; \ Ast *expr; \ @@ -563,6 +601,7 @@ AST_KIND(_ComplexStmtBegin, "", bool) \ AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \ Scope *scope; \ Token unroll_token; \ + Ast *init; \ Slice args; \ Token for_token; \ Ast *val0; \ @@ -729,8 +768,14 @@ AST_KIND(_TypeBegin, "", bool) \ }) \ AST_KIND(DynamicArrayType, "dynamic array type", struct { \ Token token; \ - Ast *elem; \ - Ast *tag; \ + Ast *elem; \ + Ast *tag; \ + }) \ + AST_KIND(FixedCapacityDynamicArrayType, "fixed capacity dynamic array type", struct { \ + Token token; \ + Ast *capacity; \ + Ast *elem; \ + Ast *tag; \ }) \ AST_KIND(StructType, "struct type", struct { \ Scope *scope; \ @@ -746,6 +791,8 @@ AST_KIND(_TypeBegin, "", bool) \ bool is_packed; \ bool is_raw_union; \ bool is_no_copy; \ + bool is_all_or_none; \ + bool is_simple; \ }) \ AST_KIND(UnionType, "union type", struct { \ Scope *scope; \ @@ -821,19 +868,19 @@ gb_global isize const ast_variant_sizes[] = { }; struct AstCommonStuff { - AstKind kind; // u16 - u8 state_flags; - u8 viral_state_flags; - i32 file_id; - TypeAndValue tav; // NOTE(bill): Making this a pointer is slower + AstKind kind; // u16 + u8 state_flags; + std::atomic viral_state_flags; + i32 file_id; + TypeAndValue tav; // NOTE(bill): Making this a pointer is slower }; struct Ast { - AstKind kind; // u16 - u8 state_flags; - u8 viral_state_flags; - i32 file_id; - TypeAndValue tav; // NOTE(bill): Making this a pointer is slower + AstKind kind; // u16 + u8 state_flags; + std::atomic viral_state_flags; + i32 file_id; + TypeAndValue tav; // NOTE(bill): Making this a pointer is slower // IMPORTANT NOTE(bill): This must be at the end since the AST is allocated to be size of the variant union { diff --git a/src/parser_pos.cpp b/src/parser_pos.cpp index 1ffd3a82f..1d2b5090a 100644 --- a/src/parser_pos.cpp +++ b/src/parser_pos.cpp @@ -107,6 +107,7 @@ gb_internal Token ast_token(Ast *node) { case Ast_MultiPointerType: return node->MultiPointerType.token; case Ast_ArrayType: return node->ArrayType.token; case Ast_DynamicArrayType: return node->DynamicArrayType.token; + case Ast_FixedCapacityDynamicArrayType: return node->FixedCapacityDynamicArrayType.token; case Ast_StructType: return node->StructType.token; case Ast_UnionType: return node->UnionType.token; case Ast_EnumType: return node->EnumType.token; @@ -342,6 +343,7 @@ Token ast_end_token(Ast *node) { case Ast_MultiPointerType: return ast_end_token(node->MultiPointerType.type); case Ast_ArrayType: return ast_end_token(node->ArrayType.elem); case Ast_DynamicArrayType: return ast_end_token(node->DynamicArrayType.elem); + case Ast_FixedCapacityDynamicArrayType: return ast_end_token(node->FixedCapacityDynamicArrayType.elem); case Ast_StructType: if (node->StructType.fields.count > 0) { return ast_end_token(node->StructType.fields[node->StructType.fields.count-1]); diff --git a/src/path.cpp b/src/path.cpp index d5e982088..786ea3b9c 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -130,7 +130,7 @@ gb_internal String directory_from_path(String const &s) { String16 wstr = string_to_string16(a, path); defer (gb_free(a, wstr.text)); - i32 attribs = GetFileAttributesW(wstr.text); + i32 attribs = GetFileAttributesW(cast(wchar_t *)wstr.text); if (attribs < 0) return false; return (attribs & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -360,7 +360,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) defer (gb_free(a, wstr.text)); WIN32_FIND_DATAW file_data = {}; - HANDLE find_file = FindFirstFileW(wstr.text, &file_data); + HANDLE find_file = FindFirstFileW(cast(wchar_t *)wstr.text, &file_data); if (find_file == INVALID_HANDLE_VALUE) { return ReadDirectory_Unknown; } @@ -372,7 +372,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) wchar_t *filename_w = file_data.cFileName; u64 size = cast(u64)file_data.nFileSizeLow; size |= (cast(u64)file_data.nFileSizeHigh) << 32; - String name = string16_to_string(a, make_string16_c(filename_w)); + String name = string16_to_string(a, make_string16_c(cast(u16 *)filename_w)); if (name == "." || name == "..") { gb_free(a, name.text); continue; @@ -400,7 +400,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) return ReadDirectory_None; } -#elif defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) || defined(GB_SYSTEM_NETBSD) || defined(GB_SYSTEM_HAIKU) +#elif defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) || defined(GB_SYSTEM_NETBSD) #include @@ -494,7 +494,7 @@ gb_internal bool write_directory(String path) { #else gb_internal bool write_directory(String path) { String16 wstr = string_to_string16(heap_allocator(), path); - LPCWSTR wdirectory_name = wstr.text; + LPCWSTR wdirectory_name = cast(wchar_t *)wstr.text; HANDLE directory = CreateFileW(wdirectory_name, GENERIC_WRITE, diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 61f703cf1..6ee3ec16d 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -10,11 +10,31 @@ enum { enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; -static void *const MAP_TOMBSTONE = (void *)~(uintptr)0; + +template +struct PtrMapConstant { + static gb_inline T const TOMBSTONE() { + return (T)reinterpret_cast(~(uintptr)0); + } +}; + +template <> +struct PtrMapConstant { + static gb_inline u64 const TOMBSTONE() { + return ~(u64)0; + } +}; +template <> +struct PtrMapConstant { + static gb_inline i64 const TOMBSTONE() { + return ~(i64)0; + } +}; template struct PtrMapEntry { - static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); + static_assert(TypeIsPointer::value || TypeIsPtrSizedInteger::value || TypeIs64BitInteger::value, + "PtrMapEntry::K must be a pointer or 8-byte integer"); K key; V value; @@ -99,7 +119,7 @@ gb_internal void map__insert(PtrMap *h, K key, V const &value) { MapIndex original_index = index; do { auto *entry = h->entries+index; - if (!entry->key || entry->key == cast(K)MAP_TOMBSTONE) { + if (!entry->key || entry->key == PtrMapConstant::TOMBSTONE()) { entry->key = key; entry->value = value; h->count += 1; @@ -147,7 +167,7 @@ gb_internal void map_reserve(PtrMap *h, isize cap) { for (u32 i = 0; i < h->capacity; i++) { auto *entry = h->entries+i; if (entry->key && - entry->key != cast(K)MAP_TOMBSTONE) { + entry->key != PtrMapConstant::TOMBSTONE()) { map__insert(&new_h, entry->key, entry->value); } } @@ -257,7 +277,7 @@ template gb_internal void map_remove(PtrMap *h, K key) { MapIndex found_index = 0; if (map_try_get(h, key, &found_index)) { - h->entries[found_index].key = cast(K)MAP_TOMBSTONE; + h->entries[found_index].key = cast(K)PtrMapConstant::TOMBSTONE(); h->count -= 1; } } @@ -367,7 +387,7 @@ struct PtrMapIterator { return *this; } PtrMapEntry *entry = map->entries+index; - if (entry->key && entry->key != cast(K)MAP_TOMBSTONE) { + if (entry->key && entry->key != PtrMapConstant::TOMBSTONE()) { return *this; } } @@ -404,7 +424,7 @@ gb_internal PtrMapIterator begin(PtrMap &m) noexcept { MapIndex index = 0; while (index < m.capacity) { auto key = m.entries[index].key; - if (key && key != cast(K)MAP_TOMBSTONE) { + if (key && key != PtrMapConstant::TOMBSTONE()) { break; } index++; @@ -420,7 +440,7 @@ gb_internal PtrMapIterator const begin(PtrMap const &m) noexcept { MapIndex index = 0; while (index < m.capacity) { auto key = m.entries[index].key; - if (key && key != cast(K)MAP_TOMBSTONE) { + if (key && key != PtrMapConstant::TOMBSTONE()) { break; } index++; @@ -447,7 +467,8 @@ struct MapFindResult { template struct OrderedInsertPtrMapEntry { - static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); + static_assert(TypeIsPointer::value || TypeIsPtrSizedInteger::value || TypeIs64BitInteger::value, + "OrderedInsertPtrMapEntry::K must be a pointer or 8-byte integer"); K key; V value; diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 5097e2bb6..3d30bb35e 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -1,11 +1,14 @@ +enum {PTR_SET_INLINE_CAP = 16}; + template struct PtrSet { static_assert(TypeIsPointer::value || TypeIsPtrSizedInteger::value, "PtrSet::T must be a pointer"); static constexpr uintptr TOMBSTONE = ~(uintptr)(0ull); - T * keys; - usize count; - usize capacity; + T * keys; + u32 count; + u32 capacity; + T inline_keys[PTR_SET_INLINE_CAP]; }; template gb_internal void ptr_set_init (PtrSet *s, isize capacity = 16); @@ -16,25 +19,34 @@ template gb_internal bool ptr_set_exists (PtrSet *s, T ptr); template gb_internal void ptr_set_remove (PtrSet *s, T ptr); template gb_internal void ptr_set_clear (PtrSet *s); +#define FOR_PTR_SET(element, set_) for (auto *it = &(set_).keys[0], element = it ? *it : nullptr; (set_).keys != nullptr && it < &(set_).keys[(set_).capacity]; it++) if (element = *it, (*it != nullptr && *it != cast(void *)~(uintptr)(0ull))) + gb_internal gbAllocator ptr_set_allocator(void) { - return heap_allocator(); + // return heap_allocator(); + return permanent_allocator(); } template gb_internal void ptr_set_init(PtrSet *s, isize capacity) { GB_ASSERT(s->keys == nullptr); if (capacity != 0) { - capacity = next_pow2_isize(gb_max(16, capacity)); - s->keys = gb_alloc_array(ptr_set_allocator(), T, capacity); + capacity = next_pow2_isize(gb_max(PTR_SET_INLINE_CAP, capacity)); + if (capacity > PTR_SET_INLINE_CAP) { + s->keys = gb_alloc_array(ptr_set_allocator(), T, capacity); + } else { + s->keys = s->inline_keys; + } // This memory will be zeroed, no need to explicitly zero it } s->count = 0; - s->capacity = capacity; + s->capacity = cast(u32)capacity; } template gb_internal void ptr_set_destroy(PtrSet *s) { - gb_free(ptr_set_allocator(), s->keys); + if (s->keys != s->inline_keys) { + gb_free(ptr_set_allocator(), s->keys); + } s->keys = nullptr; s->count = 0; s->capacity = 0; @@ -44,16 +56,10 @@ template gb_internal isize ptr_set__find(PtrSet *s, T ptr) { GB_ASSERT(ptr != 0); if (s->count != 0) { - #if 0 - for (usize i = 0; i < s->capacity; i++) { - if (s->keys[i] == ptr) { - return i; - } - } - #else u32 hash = ptr_map_hash_key(ptr); usize mask = s->capacity-1; usize hash_index = cast(usize)hash & mask; + for (usize i = 0; i < s->capacity; i++) { T key = s->keys[hash_index]; if (key == ptr) { @@ -63,14 +69,14 @@ gb_internal isize ptr_set__find(PtrSet *s, T ptr) { } hash_index = (hash_index+1)&mask; } - #endif } return -1; } template gb_internal bool ptr_set__full(PtrSet *s) { - return 0.75f * s->capacity <= s->count; + usize grow_at = s->capacity - (s->capacity>>2); + return s->count >= grow_at; } template @@ -83,7 +89,7 @@ gb_internal gb_inline void ptr_set_grow(PtrSet *old_set) { PtrSet new_set = {}; ptr_set_init(&new_set, gb_max(old_set->capacity<<1, 16)); - for (T ptr : *old_set) { + FOR_PTR_SET(ptr, *old_set) { bool was_new = ptr_set_update(&new_set, ptr); GB_ASSERT(!was_new); } @@ -120,10 +126,50 @@ gb_internal bool ptr_set_update(PtrSet *s, T ptr) { // returns true if it pre usize hash_index = (cast(usize)hash) & mask; GB_ASSERT(hash_index < s->capacity); for (usize i = 0; i < s->capacity; i++) { - T *key = &s->keys[hash_index]; - GB_ASSERT(*key != ptr); - if (*key == (T)PtrSet::TOMBSTONE || *key == 0) { - *key = ptr; + T *key_ptr = &s->keys[hash_index]; + T key = *key_ptr; + GB_ASSERT(key != ptr); + if (key == (T)PtrSet::TOMBSTONE || key == 0) { + *key_ptr = ptr; + s->count++; + return false; + } + hash_index = (hash_index+1)&mask; + } + + GB_PANIC("ptr set out of memory"); + return false; +} + +template +gb_internal bool ptr_set_update_with_mutex(PtrSet *s, T ptr, RWSpinLock *m) { // returns true if it previously existsed + rwlock_acquire_upgrade(m); + if (ptr_set_exists(s, ptr)) { + rwlock_release_upgrade(m); + return true; + } + + rwlock_release_upgrade_and_acquire_write(m); + defer (rwlock_release_write(m)); + + if (s->keys == nullptr) { + ptr_set_init(s); + } else if (ptr_set__full(s)) { + ptr_set_grow(s); + } + GB_ASSERT(s->count < s->capacity); + GB_ASSERT(s->capacity >= 0); + + usize mask = s->capacity-1; + u32 hash = ptr_map_hash_key(ptr); + usize hash_index = (cast(usize)hash) & mask; + GB_ASSERT(hash_index < s->capacity); + for (usize i = 0; i < s->capacity; i++) { + T *key_ptr = &s->keys[hash_index]; + T key = *key_ptr; + GB_ASSERT(key != ptr); + if (key == (T)PtrSet::TOMBSTONE || key == 0) { + *key_ptr = ptr; s->count++; return false; } @@ -144,11 +190,36 @@ gb_internal T ptr_set_add(PtrSet *s, T ptr) { template gb_internal void ptr_set_remove(PtrSet *s, T ptr) { isize index = ptr_set__find(s, ptr); - if (index >= 0) { - GB_ASSERT(s->count > 0); - s->keys[index] = (T)PtrSet::TOMBSTONE; - s->count--; + if (index < 0) { + return; } + +#if 0 + u32 mask = s->capacity-1; + u32 i = cast(u32)index; + s->count -= 1; + + for (;;) { + u32 next = (i + 1) & mask; + T key = s->keys[next]; + if (key == 0) { + break; + } + + u32 natural = ptr_map_hash_key(key) & mask; + + if (((next - natural) & mask) == 0) { + break; + } + s->keys[i] = key; + i = next; + } + s->keys[i] = 0; +#else + GB_ASSERT(s->count > 0); + s->keys[index] = (T)PtrSet::TOMBSTONE; + s->count--; +#endif } template @@ -157,7 +228,7 @@ gb_internal gb_inline void ptr_set_clear(PtrSet *s) { gb_zero_size(s->keys, s->capacity*gb_size_of(T)); } -template +/*template struct PtrSetIterator { PtrSet *set; usize index; @@ -201,4 +272,6 @@ gb_internal PtrSetIterator begin(PtrSet &set) noexcept { template gb_internal PtrSetIterator end(PtrSet &set) noexcept { return PtrSetIterator{&set, set.capacity}; -} \ No newline at end of file +}*/ + + diff --git a/src/queue.cpp b/src/queue.cpp index dee9ad1f8..563fbe69e 100644 --- a/src/queue.cpp +++ b/src/queue.cpp @@ -36,7 +36,8 @@ gb_internal void mpsc_destroy(MPSCQueue *q) { template gb_internal MPSCNode *mpsc_alloc_node(MPSCQueue *q, T const &value) { - auto new_node = gb_alloc_item(heap_allocator(), MPSCNode); + // auto new_node = gb_alloc_item(heap_allocator(), MPSCNode); + auto new_node = permanent_alloc_item >(); new_node->value = value; return new_node; } diff --git a/src/string.cpp b/src/string.cpp index ae8d066b1..977327bcd 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -26,15 +26,14 @@ struct String_Iterator { // NOTE(bill): String16 is only used for Windows due to its file directories struct String16 { - wchar_t *text; - isize len; - wchar_t const &operator[](isize i) const { + u16 * text; + isize len; + u16 const &operator[](isize i) const { GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); return text[i]; } }; - gb_internal gb_inline String make_string(u8 const *text, isize len) { String s; s.text = cast(u8 *)text; @@ -45,19 +44,19 @@ gb_internal gb_inline String make_string(u8 const *text, isize len) { return s; } - -gb_internal gb_inline String16 make_string16(wchar_t const *text, isize len) { +gb_internal gb_inline String16 make_string16(u16 const *text, isize len) { String16 s; - s.text = cast(wchar_t *)text; + s.text = cast(u16 *)text; s.len = len; return s; } -gb_internal isize string16_len(wchar_t const *s) { + +gb_internal isize string16_len(u16 const *s) { if (s == nullptr) { return 0; } - wchar_t const *p = s; + u16 const *p = s; while (*p) { p++; } @@ -69,7 +68,7 @@ gb_internal gb_inline String make_string_c(char const *text) { return make_string(cast(u8 *)cast(void *)text, gb_strlen(text)); } -gb_internal gb_inline String16 make_string16_c(wchar_t const *text) { +gb_internal gb_inline String16 make_string16_c(u16 const *text) { return make_string16(text, string16_len(text)); } @@ -80,6 +79,13 @@ gb_internal String substring(String const &s, isize lo, isize hi) { return make_string(s.text+lo, hi-lo); } +gb_internal String16 substring(String16 const &s, isize lo, isize hi) { + isize max = s.len; + GB_ASSERT_MSG(lo <= hi && hi <= max, "%td..%td..%td", lo, hi, max); + + return make_string16(s.text+lo, hi-lo); +} + gb_internal char *alloc_cstring(gbAllocator a, String s) { char *c_str = gb_alloc_array(a, char, s.len+1); @@ -145,6 +151,27 @@ gb_internal int string_compare(String const &a, String const &b) { return res; } + +gb_internal int string16_compare(String16 const &a, String16 const &b) { + if (a.text == b.text) { + return cast(int)(a.len - b.len); + } + if (a.text == nullptr) { + return -1; + } + if (b.text == nullptr) { + return +1; + } + + uintptr n = gb_min(a.len, b.len); + int res = memcmp(a.text, b.text, n*gb_size_of(u16)); + if (res == 0) { + res = cast(int)(a.len - b.len); + } + return res; +} + + gb_internal isize string_index_byte(String const &s, u8 x) { for (isize i = 0; i < s.len; i++) { if (s.text[i] == x) { @@ -155,8 +182,9 @@ gb_internal isize string_index_byte(String const &s, u8 x) { } gb_internal gb_inline bool str_eq(String const &a, String const &b) { - if (a.len != b.len) return false; - if (a.len == 0) return true; + if (a.len != b.len) return false; + if (a.len == 0) return true; + if (a.text == b.text) return true; return memcmp(a.text, b.text, a.len) == 0; } gb_internal gb_inline bool str_ne(String const &a, String const &b) { return !str_eq(a, b); } @@ -182,6 +210,26 @@ template gb_internal bool operator >= (String const &a, char const (&b template <> bool operator == (String const &a, char const (&b)[1]) { return a.len == 0; } template <> bool operator != (String const &a, char const (&b)[1]) { return a.len != 0; } + +gb_internal gb_inline bool str_eq(String16 const &a, String16 const &b) { + if (a.len != b.len) return false; + if (a.len == 0) return true; + return memcmp(a.text, b.text, a.len) == 0; +} +gb_internal gb_inline bool str_ne(String16 const &a, String16 const &b) { return !str_eq(a, b); } +gb_internal gb_inline bool str_lt(String16 const &a, String16 const &b) { return string16_compare(a, b) < 0; } +gb_internal gb_inline bool str_gt(String16 const &a, String16 const &b) { return string16_compare(a, b) > 0; } +gb_internal gb_inline bool str_le(String16 const &a, String16 const &b) { return string16_compare(a, b) <= 0; } +gb_internal gb_inline bool str_ge(String16 const &a, String16 const &b) { return string16_compare(a, b) >= 0; } + +gb_internal gb_inline bool operator == (String16 const &a, String16 const &b) { return str_eq(a, b); } +gb_internal gb_inline bool operator != (String16 const &a, String16 const &b) { return str_ne(a, b); } +gb_internal gb_inline bool operator < (String16 const &a, String16 const &b) { return str_lt(a, b); } +gb_internal gb_inline bool operator > (String16 const &a, String16 const &b) { return str_gt(a, b); } +gb_internal gb_inline bool operator <= (String16 const &a, String16 const &b) { return str_le(a, b); } +gb_internal gb_inline bool operator >= (String16 const &a, String16 const &b) { return str_ge(a, b); } + + gb_internal gb_inline bool string_starts_with(String const &s, String const &prefix) { if (prefix.len > s.len) { return false; @@ -444,17 +492,7 @@ gb_internal bool string_contains_string(String const &haystack, String const &ne gb_internal String filename_from_path(String s) { isize i = string_extension_position(s); if (i >= 0) { - s = substring(s, 0, i); - return s; - } - if (i > 0) { - isize j = 0; - for (j = s.len-1; j >= 0; j--) { - if (is_separator(s[j])) { - break; - } - } - return substring(s, j+1, s.len); + return substring(s, 0, i); } return make_string(nullptr, 0); } @@ -470,6 +508,13 @@ gb_internal String filename_without_directory(String s) { return substring(s, gb_max(j+1, 0), s.len); } +gb_internal String clone_string(gbAllocator a, String const &x) { + u8 *data = gb_alloc_array(a, u8, x.len+1); + gb_memmove(data, x.text, x.len); + data[x.len] = 0; + return make_string(data, x.len); +} + gb_internal String concatenate_strings(gbAllocator a, String const &x, String const &y) { isize len = x.len+y.len; u8 *data = gb_alloc_array(a, u8, len+1); @@ -586,23 +631,109 @@ gb_internal String normalize_path(gbAllocator a, String const &path, String cons return WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, widechar_input, input_length, output, output_size, nullptr, nullptr); } #elif defined(GB_SYSTEM_UNIX) || defined(GB_SYSTEM_OSX) + #include - #include + gb_internal void utf16_encode_surrogate_pair(Rune r, u16 *r1, u16 *r2) { + static Rune const _surr_self = 0x10000; + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + Rune r_ = r - _surr_self; + *r1 = _surr1 + ((r_ >> 10) & 0x3ff); + *r2 = _surr2 + (r_ & 0x3ff); + } + + gb_internal isize utf16_decode(u16 const *s, isize n, Rune *r) { + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + static Rune const _surr3 = 0xe000; + static Rune const _surr_self = 0x10000; + if (n < 1) { + *r = GB_RUNE_INVALID; + return 0; + } + u16 c = s[0]; + if (c < 0xd800 || c > 0xdfff) { + *r = cast(Rune)c; + return 1; + } + if (c >= 0xdc00) { + *r = GB_RUNE_INVALID; + return 1; + } + if (n < 2) { + *r = GB_RUNE_INVALID; + return 1; + } + u16 c2 = s[1]; + if (c2 < 0xdc00 || c2 > 0xdfff) { + *r = GB_RUNE_INVALID; + return 1; + } + *r = (((c-_surr1)<<10) | (c2 - _surr2)) + _surr_self; + return 2; + } gb_internal int convert_multibyte_to_widechar(char const *multibyte_input, usize input_length, wchar_t *output, usize output_size) { - iconv_t conv = iconv_open("WCHAR_T", "UTF-8"); - size_t result = iconv(conv, cast(char **)&multibyte_input, &input_length, cast(char **)&output, &output_size); - iconv_close(conv); + u16 *out = cast(u16 *)output; + String s = make_string(cast(u8 const *)multibyte_input, input_length); + isize i = 0; + isize output_len = 0; + while (i < s.len) { + Rune r = 0; + isize width = utf8_decode(s.text + i, s.len - i, &r); + if (r == GB_RUNE_INVALID) { + return -1; + } + i += width; + if (r < 0x10000) { + if (out) { + if (cast(usize)output_len+1 > output_size) { + return -1; + } + out[output_len] = cast(u16)r; + } + output_len += 1; + } else { + if (out) { + if (cast(usize)output_len+2 > output_size) { + return -1; + } + u16 r1, r2; + utf16_encode_surrogate_pair(r, &r1, &r2); + out[output_len+0] = r1; + out[output_len+1] = r2; + } + output_len += 2; + } + } - return cast(int)result; + return cast(int)output_len; } gb_internal int convert_widechar_to_multibyte(wchar_t const *widechar_input, usize input_length, char* output, usize output_size) { - iconv_t conv = iconv_open("UTF-8", "WCHAR_T"); - size_t result = iconv(conv, cast(char**) &widechar_input, &input_length, cast(char **)&output, &output_size); - iconv_close(conv); + u16 const *in = cast(u16 const *)widechar_input; + isize i = 0; + isize output_len = 0; + while (i < input_length) { + Rune r; + isize width = utf16_decode(in + i, input_length - i, &r); + if (r == GB_RUNE_INVALID) { + return -1; + } + i += width; - return cast(int)result; + u8 buf[4]; + isize char_len = gb_utf8_encode_rune(buf, r); + + if(output) { + if (cast(usize)output_len+cast(usize)char_len > output_size) { + return -1; + } + gb_memmove(output + output_len, buf, char_len); + } + output_len += char_len; + } + return cast(int)output_len; } #else #error Implement system @@ -611,10 +742,9 @@ gb_internal String normalize_path(gbAllocator a, String const &path, String cons -// TODO(bill): Make this non-windows specific gb_internal String16 string_to_string16(gbAllocator a, String s) { int len, len1; - wchar_t *text; + u16 *text; if (s.len < 1) { return make_string16(nullptr, 0); @@ -625,15 +755,14 @@ gb_internal String16 string_to_string16(gbAllocator a, String s) { return make_string16(nullptr, 0); } - text = gb_alloc_array(a, wchar_t, len+1); + text = gb_alloc_array(a, u16, len+1); - len1 = convert_multibyte_to_widechar(cast(char *)s.text, cast(int)s.len, text, cast(int)len); + len1 = convert_multibyte_to_widechar(cast(char *)s.text, cast(int)s.len, cast(wchar_t *)text, cast(int)len); if (len1 == 0) { gb_free(a, text); return make_string16(nullptr, 0); } text[len] = 0; - return make_string16(text, len); } @@ -646,7 +775,7 @@ gb_internal String string16_to_string(gbAllocator a, String16 s) { return make_string(nullptr, 0); } - len = convert_widechar_to_multibyte(s.text, cast(int)s.len, nullptr, 0); + len = convert_widechar_to_multibyte(cast(wchar_t *)s.text, cast(int)s.len, nullptr, 0); if (len == 0) { return make_string(nullptr, 0); } @@ -654,7 +783,7 @@ gb_internal String string16_to_string(gbAllocator a, String16 s) { text = gb_alloc_array(a, u8, len+1); - len1 = convert_widechar_to_multibyte(s.text, cast(int)s.len, cast(char *)text, cast(int)len); + len1 = convert_widechar_to_multibyte(cast(wchar_t *)s.text, cast(int)s.len, cast(char *)text, cast(int)len); if (len1 == 0) { gb_free(a, text); return make_string(nullptr, 0); @@ -674,9 +803,9 @@ gb_internal String temporary_directory(gbAllocator allocator) { return String{0}; } DWORD len = gb_max(MAX_PATH, n); - wchar_t *b = gb_alloc_array(heap_allocator(), wchar_t, len+1); + u16 *b = gb_alloc_array(heap_allocator(), u16, len+1); defer (gb_free(heap_allocator(), b)); - n = GetTempPathW(len, b); + n = GetTempPathW(len, cast(wchar_t *)b); if (n == 3 && b[1] == ':' && b[2] == '\\') { } else if (n > 0 && b[n-1] == '\\') { @@ -791,6 +920,104 @@ gb_internal String quote_to_ascii(gbAllocator a, String str, u8 quote='"') { return res; } +gb_internal Rune decode_surrogate_pair(u16 r1, u16 r2) { + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + static Rune const _surr3 = 0xe000; + static Rune const _surr_self = 0x10000; + + if (_surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3) { + return (((r1-_surr1)<<10) | (r2 - _surr2)) + _surr_self; + } + return GB_RUNE_INVALID; +} + +gb_internal String quote_to_ascii(gbAllocator a, String16 str, u8 quote='"') { + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + static Rune const _surr3 = 0xe000; + static Rune const _surr_self = 0x10000; + + u16 *s = cast(u16 *)str.text; + isize n = str.len; + auto buf = array_make(a, 0, n*2); + array_add(&buf, quote); + for (isize width = 0; n > 0; s += width, n -= width) { + Rune r = cast(Rune)s[0]; + width = 1; + if (r < _surr1 || _surr3 <= r) { + r = cast(Rune)r; + } else if (_surr1 <= r && r < _surr2) { + if (n>1) { + r = decode_surrogate_pair(s[0], s[1]); + if (r != GB_RUNE_INVALID) { + width = 2; + } + } else { + r = GB_RUNE_INVALID; + } + } + if (width == 1 && r == GB_RUNE_INVALID) { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'x'); + array_add(&buf, cast(u8)lower_hex[s[0]>>4]); + array_add(&buf, cast(u8)lower_hex[s[0]&0xf]); + continue; + } + + if (r == quote || r == '\\') { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, u8(r)); + continue; + } + if (r < 0x80 && is_printable(r)) { + array_add(&buf, u8(r)); + continue; + } + switch (r) { + case '\a': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + default: + if (r < ' ') { + u8 b = cast(u8)r; + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'x'); + array_add(&buf, cast(u8)lower_hex[b>>4]); + array_add(&buf, cast(u8)lower_hex[b&0xf]); + } + if (r > GB_RUNE_MAX) { + r = 0XFFFD; + } + if (r < 0x10000) { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'u'); + for (isize i = 12; i >= 0; i -= 4) { + array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]); + } + } else { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'U'); + for (isize i = 28; i >= 0; i -= 4) { + array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]); + } + } + } + } + + + + array_add(&buf, quote); + String res = {}; + res.text = buf.data; + res.len = buf.count; + return res; +} + diff --git a/src/string16_map.cpp b/src/string16_map.cpp new file mode 100644 index 000000000..c9e2eb817 --- /dev/null +++ b/src/string16_map.cpp @@ -0,0 +1,538 @@ +GB_STATIC_ASSERT(sizeof(MapIndex) == sizeof(u32)); + + +struct String16HashKey { + String16 string; + u32 hash; + + operator String16() const noexcept { + return this->string; + } + operator String16 const &() const noexcept { + return this->string; + } +}; +gb_internal gb_inline u32 string_hash(String16 const &s) { + u32 res = fnv32a(s.text, s.len*gb_size_of(u16)) & 0x7fffffff; + return res | (res == 0); +} + +gb_internal gb_inline String16HashKey string_hash_string(String16 const &s) { + String16HashKey hash_key = {}; + hash_key.hash = string_hash(s); + hash_key.string = s; + return hash_key; +} + + +#if 1 /* old string map */ + +template +struct String16MapEntry { + String16 key; + u32 hash; + MapIndex next; + T value; +}; + +template +struct String16Map { + MapIndex * hashes; + usize hashes_count; + String16MapEntry *entries; + u32 count; + u32 entries_capacity; +}; + + +template gb_internal void string16_map_init (String16Map *h, usize capacity = 16); +template gb_internal void string16_map_destroy (String16Map *h); + +template gb_internal T * string16_map_get (String16Map *h, String16HashKey const &key); +template gb_internal T & string16_map_must_get(String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_set (String16Map *h, String16HashKey const &key, T const &value); + +// template gb_internal void string16_map_remove (String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_clear (String16Map *h); +template gb_internal void string16_map_grow (String16Map *h); +template gb_internal void string16_map_reserve (String16Map *h, usize new_count); + +gb_internal gbAllocator string16_map_allocator(void) { + return heap_allocator(); +} + +template +gb_internal gb_inline void string16_map_init(String16Map *h, usize capacity) { + capacity = next_pow2_isize(capacity); + string16_map_reserve(h, capacity); +} + +template +gb_internal gb_inline void string16_map_destroy(String16Map *h) { + gb_free(string16_map_allocator(), h->hashes); + gb_free(string16_map_allocator(), h->entries); +} + + +template +gb_internal void string16_map__resize_hashes(String16Map *h, usize count) { + h->hashes_count = cast(u32)resize_array_raw(&h->hashes, string16_map_allocator(), h->hashes_count, count, MAP_CACHE_LINE_SIZE); +} + + +template +gb_internal void string16_map__reserve_entries(String16Map *h, usize capacity) { + h->entries_capacity = cast(u32)resize_array_raw(&h->entries, string16_map_allocator(), h->entries_capacity, capacity, MAP_CACHE_LINE_SIZE); +} + + +template +gb_internal MapIndex string16_map__add_entry(String16Map *h, u32 hash, String16 const &key) { + String16MapEntry e = {}; + e.key = key; + e.hash = hash; + e.next = MAP_SENTINEL; + if (h->count+1 >= h->entries_capacity) { + string16_map__reserve_entries(h, gb_max(h->entries_capacity*2, 4)); + } + h->entries[h->count++] = e; + return cast(MapIndex)(h->count-1); +} + +template +gb_internal MapFindResult string16_map__find(String16Map *h, u32 hash, String16 const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry->hash == hash && entry->key == key) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return fr; +} + +template +gb_internal MapFindResult string16_map__find_from_entry(String16Map *h, String16MapEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(e->hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return fr; +} + +template +gb_internal b32 string16_map__full(String16Map *h) { + return 0.75f * h->hashes_count <= h->count; +} + +template +gb_inline void string16_map_grow(String16Map *h) { + isize new_count = gb_max(h->hashes_count<<1, 16); + string16_map_reserve(h, new_count); +} + + +template +gb_internal void string16_map_reset_entries(String16Map *h) { + for (u32 i = 0; i < h->hashes_count; i++) { + h->hashes[i] = MAP_SENTINEL; + } + for (isize i = 0; i < h->count; i++) { + MapFindResult fr; + String16MapEntry *e = &h->entries[i]; + e->next = MAP_SENTINEL; + fr = string16_map__find_from_entry(h, e); + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes[fr.hash_index] = cast(MapIndex)i; + } else { + h->entries[fr.entry_prev].next = cast(MapIndex)i; + } + } +} + +template +gb_internal void string16_map_reserve(String16Map *h, usize cap) { + if (h->count*2 < h->hashes_count) { + return; + } + string16_map__reserve_entries(h, cap); + string16_map__resize_hashes(h, cap*2); + string16_map_reset_entries(h); +} + +template +gb_internal T *string16_map_get(String16Map *h, u32 hash, String16 const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry->hash == hash && entry->key == key) { + return &entry->value; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return nullptr; +} + + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16HashKey const &key) { + return string16_map_get(h, key.hash, key.string); +} +template +gb_internal T &string16_map_must_get(String16Map *h, u32 hash, String16 const &key) { + isize index = string16_map__find(h, hash, key).entry_index; + GB_ASSERT(index != MAP_SENTINEL); + return h->entries[index].value; +} + +template +gb_internal T &string16_map_must_get(String16Map *h, String16HashKey const &key) { + return string16_map_must_get(h, key.hash, key.string); +} + +template +gb_internal void string16_map_set(String16Map *h, u32 hash, String16 const &key, T const &value) { + MapIndex index; + MapFindResult fr; + if (h->hashes_count == 0) { + string16_map_grow(h); + } + fr = string16_map__find(h, hash, key); + if (fr.entry_index != MAP_SENTINEL) { + index = fr.entry_index; + } else { + index = string16_map__add_entry(h, hash, key); + if (fr.entry_prev != MAP_SENTINEL) { + h->entries[fr.entry_prev].next = index; + } else { + h->hashes[fr.hash_index] = index; + } + } + h->entries[index].value = value; + + if (string16_map__full(h)) { + string16_map_grow(h); + } +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16HashKey const &key, T const &value) { + string16_map_set(h, key.hash, key.string, value); +} + + +template +gb_internal gb_inline void string16_map_clear(String16Map *h) { + h->count = 0; + for (u32 i = 0; i < h->hashes_count; i++) { + h->hashes[i] = MAP_SENTINEL; + } +} + + + +template +gb_internal String16MapEntry *begin(String16Map &m) noexcept { + return m.entries; +} +template +gb_internal String16MapEntry const *begin(String16Map const &m) noexcept { + return m.entries; +} + + +template +gb_internal String16MapEntry *end(String16Map &m) noexcept { + return m.entries + m.count; +} + +template +gb_internal String16MapEntry const *end(String16Map const &m) noexcept { + return m.entries + m.count; +} + +#else /* new string map */ + +template +struct StringMapEntry { + String key; + u32 hash; + T value; +}; + +template +struct StringMap { + String16MapEntry *entries; + u32 count; + u32 capacity; +}; + + +template gb_internal void string16_map_init (String16Map *h, usize capacity = 16); +template gb_internal void string16_map_destroy (String16Map *h); + +template gb_internal T * string16_map_get (String16Map *h, String16 const &key); +template gb_internal T * string16_map_get (String16Map *h, String16HashKey const &key); + +template gb_internal T & string16_map_must_get(String16Map *h, String16 const &key); +template gb_internal T & string16_map_must_get(String16Map *h, String16HashKey const &key); + +template gb_internal void string16_map_set (String16Map *h, String16 const &key, T const &value); +template gb_internal void string16_map_set (String16Map *h, String16HashKey const &key, T const &value); + +// template gb_internal void string16_map_remove (String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_clear (String16Map *h); +template gb_internal void string16_map_grow (String16Map *h); +template gb_internal void string16_map_reserve (String16Map *h, usize new_count); + +gb_internal gbAllocator string16_map_allocator(void) { + return heap_allocator(); +} + +template +gb_internal gb_inline void string16_map_init(String16Map *h, usize capacity) { + capacity = next_pow2_isize(capacity); + string16_map_reserve(h, capacity); +} + +template +gb_internal gb_inline void string16_map_destroy(String16Map *h) { + gb_free(string16_map_allocator(), h->entries); +} + + +template +gb_internal void string16_map__insert(String16Map *h, u32 hash, String16 const &key, T const &value) { + if (h->count+1 >= h->capacity) { + string16_map_grow(h); + } + GB_ASSERT(h->count+1 < h->capacity); + + u32 mask = h->capacity-1; + MapIndex index = hash & mask; + MapIndex original_index = index; + do { + auto *entry = h->entries+index; + if (entry->hash == 0) { + entry->key = key; + entry->hash = hash; + entry->value = value; + + h->count += 1; + return; + } + index = (index+1)&mask; + } while (index != original_index); + + GB_PANIC("Full map"); +} + +template +gb_internal b32 string16_map__full(String16Map *h) { + return 0.75f * h->count <= h->capacity; +} + +template +gb_inline void string16_map_grow(String16Map *h) { + isize new_capacity = gb_max(h->capacity<<1, 16); + string16_map_reserve(h, new_capacity); +} + + +template +gb_internal void string16_map_reserve(String16Map *h, usize cap) { + if (cap < h->capacity) { + return; + } + cap = next_pow2_isize(cap); + + String16Map new_h = {}; + new_h.count = 0; + new_h.capacity = cast(u32)cap; + new_h.entries = gb_alloc_array(string16_map_allocator(), String16MapEntry, new_h.capacity); + + if (h->count) { + for (u32 i = 0; i < h->capacity; i++) { + auto *entry = h->entries+i; + if (entry->hash) { + string16_map__insert(&new_h, entry->hash, entry->key, entry->value); + } + } + } + string16_map_destroy(h); + *h = new_h; +} + +template +gb_internal T *string16_map_get(String16Map *h, u32 hash, String16 const &key) { + if (h->count == 0) { + return nullptr; + } + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + u32 curr_hash = entry->hash; + if (curr_hash == 0) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (curr_hash == hash && entry->key == key) { + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); + return nullptr; +} + + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16HashKey const &key) { + return string16_map_get(h, key.hash, key.string); +} + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16 const &key) { + return string16_map_get(h, string_hash(key), key); +} + +template +gb_internal T &string16_map_must_get(String16Map *h, u32 hash, String16 const &key) { + T *found = string16_map_get(h, hash, key); + GB_ASSERT(found != nullptr); + return *found; +} + +template +gb_internal T &string16_map_must_get(String16Map *h, String16HashKey const &key) { + return string16_map_must_get(h, key.hash, key.string); +} + +template +gb_internal gb_inline T &string16_map_must_get(String16Map *h, String16 const &key) { + return string16_map_must_get(h, string_hash(key), key); +} + +template +gb_internal void string16_map_set(String16Map *h, u32 hash, String16 const &key, T const &value) { + if (h->count == 0) { + string16_map_grow(h); + } + auto *found = string16_map_get(h, hash, key); + if (found) { + *found = value; + return; + } + string16_map__insert(h, hash, key, value); +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16 const &key, T const &value) { + string16_map_set(h, string_hash_string(key), value); +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16HashKey const &key, T const &value) { + string16_map_set(h, key.hash, key.string, value); +} + + +template +gb_internal gb_inline void string16_map_clear(String16Map *h) { + h->count = 0; + gb_zero_array(h->entries, h->capacity); +} + + +template +struct StringMapIterator { + String16Map *map; + MapIndex index; + + StringMapIterator &operator++() noexcept { + for (;;) { + ++index; + if (map->capacity == index) { + return *this; + } + String16MapEntry *entry = map->entries+index; + if (entry->hash != 0) { + return *this; + } + } + } + + bool operator==(StringMapIterator const &other) const noexcept { + return this->map == other->map && this->index == other->index; + } + + operator String16MapEntry *() const { + return map->entries+index; + } +}; + + +template +gb_internal StringMapIterator end(String16Map &m) noexcept { + return StringMapIterator{&m, m.capacity}; +} + +template +gb_internal StringMapIterator const end(String16Map const &m) noexcept { + return StringMapIterator{&m, m.capacity}; +} + + + +template +gb_internal StringMapIterator begin(String16Map &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator{&m, index}; +} +template +gb_internal StringMapIterator const begin(String16Map const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator{&m, index}; +} + +#endif \ No newline at end of file diff --git a/src/string_interner.cpp b/src/string_interner.cpp new file mode 100644 index 000000000..916263fa3 --- /dev/null +++ b/src/string_interner.cpp @@ -0,0 +1,231 @@ +#define STRING_INTERNER_CELL_WIDTH 8 +#define STRING_INTERNER_MUTEX_STRIPE_COUNT 1024 +#define STRING_INTERNER_MUTEX_STRIPE_MASK (STRING_INTERNER_MUTEX_STRIPE_COUNT - 1) +#define STRING_INTERNER_THREAD_LOCAL_SIZE (1024 * 1024 * 2) +#define STRING_INTERN_CACHE_LINE (2*GB_CACHE_LINE_SIZE) + +struct InternedString { + u32 value; + bool operator==(InternedString other) const { + return this->value == other.value; + } + + String string() const; + char const *cstring() const; + u32 hash() const; + + bool is_blank() const; +}; +struct alignas(STRING_INTERN_CACHE_LINE) StringInternCell { + std::atomic hashes [STRING_INTERNER_CELL_WIDTH]; + InternedString offsets[STRING_INTERNER_CELL_WIDTH]; + std::atomic next; +}; + +struct alignas(STRING_INTERN_CACHE_LINE) PaddedMutex { + BlockingMutex m; +}; + +struct alignas(STRING_INTERN_CACHE_LINE) PaddedI64 { + std::atomic value; +}; + +struct StringInterner { + StringInternCell *cells; + u64 cell_mask; + PaddedMutex mutexes[STRING_INTERNER_MUTEX_STRIPE_COUNT]; + StaticArena arena; + PaddedMutex arena_mutex; + bool track_count; + PaddedI64 count; +}; + +gb_internal StringInterner *string_interner_create(); +gb_internal InternedString string_interner_insert(String str, u32 hash=0, u32 *new_hash_=nullptr); +gb_internal String string_interner_load(InternedString interned); + +gb_global StringInterner *g_string_interner; +gb_global InternedString g_interned_blank_ident; + +struct StringInternerThreadLocalArena { + u8 *data; + u64 cursor; +}; +gb_thread_local gb_global StringInternerThreadLocalArena g_interner_arena; + +gb_internal void string_interner_thread_local_arena_init(StringInternerThreadLocalArena *tl_arena); +gb_internal void *string_interner_thread_local_arena_alloc(StringInternerThreadLocalArena *tl_arena, isize size, isize alignment); + +gb_internal void init_string_interner() { + StaticArena arena = {}; + static_arena_init(&arena, 1<<30, STATIC_ARENA_DEFAULT_COMMIT_BLOCK_SIZE); + + StringInterner *interner = cast(StringInterner *)static_arena_alloc(&arena, gb_size_of(StringInterner), STRING_INTERN_CACHE_LINE); + interner->arena = arena; + u64 cell_size = 1llu << 17llu; + u64 cell_mask = cell_size - 1; + interner->cell_mask = cell_mask; + interner->cells = cast(StringInternCell *)static_arena_alloc(&interner->arena, cell_size * gb_size_of(StringInternCell), STRING_INTERN_CACHE_LINE); + interner->track_count = false; + + g_string_interner = interner; + + g_interned_blank_ident = string_interner_insert(str_lit("_")); +} + +gb_internal String string_interner_load(InternedString interned) { + StringInterner* interner = g_string_interner; + if (interned.value == 0) { + return {}; + } + u8 *base = cast(u8 *)interner + interned.value; + u32 str_len = *cast(u32 *)base; + u8 *text = base + 4; + String str = { text, cast(isize)str_len }; + return str; +} + +gb_internal char const *string_interner_load_cstring(InternedString interned) { + StringInterner* interner = g_string_interner; + if (interned.value == 0) { + return ""; + } + u8 *base = cast(u8 *)interner + interned.value; + // u32 str_len = *cast(u32 *)base; + u8 *text = base + 4; + return cast(char const *)text; +} + +String InternedString::string() const { + return string_interner_load(*this); +} +char const *InternedString::cstring() const { + return string_interner_load_cstring(*this); +} +u32 InternedString::hash() const { + String s = string_interner_load(*this); + return string_hash(s); +} +bool InternedString::is_blank() const { + return this->value == g_interned_blank_ident.value; +} + +gb_internal InternedString string_interner_insert(String str, u32 hash, u32 *new_hash_) { + StringInterner* interner = g_string_interner; + if (str.len == 0) { + if (new_hash_) *new_hash_ = string_hash(String{}); + return {}; + } + + if (hash == 0) { + hash = string_hash(str); + } + if (new_hash_) *new_hash_ = hash; + + u64 cell_idx = hash & interner->cell_mask; + StringInternCell *cell = &interner->cells[cell_idx]; + while (true) { + StringInternCell *next = cell->next.load(std::memory_order_acquire); + + for (i32 i = 0; i < STRING_INTERNER_CELL_WIDTH; i += 1) { + if (cell->hashes[i].load(std::memory_order_acquire) == hash) { + String to_compare = string_interner_load(cell->offsets[i]); + if (to_compare == str) { + return cell->offsets[i]; + } + } + } + if (next == nullptr) { + break; + } + cell = next; + } + + u64 mutex_cell = cell_idx & STRING_INTERNER_MUTEX_STRIPE_MASK; + PaddedMutex* m = &interner->mutexes[mutex_cell]; + MUTEX_GUARD(&m->m); + + StringInternCell *load_cell = nullptr; + while (cell) { + for (i32 i = 0; i < STRING_INTERNER_CELL_WIDTH; i += 1) { + if (cell->hashes[i].load(std::memory_order_relaxed) == hash) { + // string check + String to_compare = string_interner_load(cell->offsets[i]); + if (to_compare == str) { + return cell->offsets[i]; + } + } + } + load_cell = cell; + cell = cell->next.load(std::memory_order_relaxed); + } + + u64 data_to_allocate = 4 + str.len + 1; + u8 *data = cast(u8 *)string_interner_thread_local_arena_alloc(&g_interner_arena, data_to_allocate, 8); + u32 str_len = cast(u32)str.len; + gb_memcopy(data, &str_len, 4); + gb_memcopy(&data[4], str.text, str_len); + data[4+str_len] = 0; + InternedString offset = { cast(u32)(cast(u8 *)data - cast(u8 *)interner) }; + + for (i32 i = 0; i < STRING_INTERNER_CELL_WIDTH; i += 1) { + if (load_cell->hashes[i].load(std::memory_order_relaxed) == 0) { + load_cell->offsets[i] = offset; + load_cell->hashes[i].store(hash, std::memory_order_release); + if (interner->track_count) { + interner->count.value.fetch_add(1, std::memory_order_relaxed); + } + return offset; + } + } + + StringInternCell *new_cell = cast(StringInternCell *)string_interner_thread_local_arena_alloc(&g_interner_arena, gb_size_of(StringInternCell), STRING_INTERN_CACHE_LINE); + new_cell->offsets[0] = offset; + new_cell->hashes[0].store(hash, std::memory_order_relaxed); + load_cell->next.store(new_cell, std::memory_order_release); + + if (interner->track_count) { + interner->count.value.fetch_add(1, std::memory_order_relaxed); + } + + return offset; +} + +gb_internal char const *string_intern_cstring(String str, u32 *hash_=nullptr) { + InternedString i = string_interner_insert(str, 0, hash_); + return string_interner_load_cstring(i); +} + + +gb_internal String string_intern_string(String str, u32 *hash_=nullptr) { + InternedString i = string_interner_insert(str, 0, hash_); + return string_interner_load(i); +} + + + + +gb_internal void string_interner_thread_local_arena_init(StringInternerThreadLocalArena *tl_arena) { + *tl_arena = { + nullptr, + STRING_INTERNER_THREAD_LOCAL_SIZE, + }; +} + +gb_internal void *string_interner_thread_local_arena_alloc(StringInternerThreadLocalArena *tl_arena, isize size, isize alignment) { + if (tl_arena->data == nullptr) { + tl_arena->cursor = STRING_INTERNER_THREAD_LOCAL_SIZE; + } + isize new_head = align_formula_isize(tl_arena->cursor, alignment); + isize cursor = new_head + size; + if (cursor > STRING_INTERNER_THREAD_LOCAL_SIZE) { + mutex_lock(&g_string_interner->arena_mutex.m); + tl_arena->data = cast(u8 *)static_arena_alloc(&g_string_interner->arena, STRING_INTERNER_THREAD_LOCAL_SIZE, 4096); + tl_arena->cursor = 0; + mutex_unlock(&g_string_interner->arena_mutex.m); + return string_interner_thread_local_arena_alloc(tl_arena, size, alignment); + } + u8 *return_head = tl_arena->data + new_head; + tl_arena->cursor = cursor; + return return_head; +} diff --git a/src/thread_pool.cpp b/src/thread_pool.cpp index 8363a4553..a0afbd269 100644 --- a/src/thread_pool.cpp +++ b/src/thread_pool.cpp @@ -1,5 +1,15 @@ // thread_pool.cpp +// TODO(bill): make work on MSVC +// #if defined(__SANITIZE_THREAD__) || (defined(__has_feature) && __has_feature(thread_sanitizer)) +// #include +// #define TSAN_RELEASE(addr) __tsan_release(addr) +// #define TSAN_ACQUIRE(addr) __tsan_acquire(addr) +// #else +#define TSAN_RELEASE(addr) +#define TSAN_ACQUIRE(addr) +// #endif + struct WorkerTask; struct ThreadPool; @@ -19,6 +29,11 @@ enum GrabState { Grab_Failed = 2, }; +enum BroadcastWaitState { + Nobody_Waiting = 0, + Someone_Waiting = 1, +}; + struct ThreadPool { gbAllocator threads_allocator; Slice threads; @@ -54,8 +69,8 @@ gb_internal void thread_pool_destroy(ThreadPool *pool) { for_array_off(i, 1, pool->threads) { Thread *t = &pool->threads[i]; - pool->tasks_available.fetch_add(1, std::memory_order_acquire); - futex_broadcast(&pool->tasks_available); + pool->tasks_available.store(Nobody_Waiting); + futex_broadcast(&t->pool->tasks_available); thread_join_and_destroy(t); } @@ -83,12 +98,15 @@ void thread_pool_queue_push(Thread *thread, WorkerTask task) { } cur_ring->buffer[bot % cur_ring->size] = task; + TSAN_RELEASE(cur_ring->buffer[bot % cur_ring->size]); std::atomic_thread_fence(std::memory_order_release); thread->queue.bottom.store(bot + 1, std::memory_order_relaxed); thread->pool->tasks_left.fetch_add(1, std::memory_order_release); - thread->pool->tasks_available.fetch_add(1, std::memory_order_relaxed); - futex_broadcast(&thread->pool->tasks_available); + i32 state = Someone_Waiting; + if (thread->pool->tasks_available.compare_exchange_strong(state, Nobody_Waiting)) { + futex_broadcast(&thread->pool->tasks_available); + } } GrabState thread_pool_queue_take(Thread *thread, WorkerTask *task) { @@ -101,6 +119,7 @@ GrabState thread_pool_queue_take(Thread *thread, WorkerTask *task) { if (top <= bot) { // Queue is not empty + TSAN_ACQUIRE(cur_ring->buffer[bot % cur_ring->size]); *task = cur_ring->buffer[bot % cur_ring->size]; if (top == bot) { // Only one entry left in queue @@ -132,6 +151,8 @@ GrabState thread_pool_queue_steal(Thread *thread, WorkerTask *task) { if (top < bot) { // Queue is not empty TaskRingBuffer *cur_ring = thread->queue.ring.load(std::memory_order_consume); + + TSAN_ACQUIRE(&cur_ring->buffer[top % cur_ring->size]); *task = cur_ring->buffer[top % cur_ring->size]; if (!thread->queue.top.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed)) { @@ -230,12 +251,13 @@ gb_internal THREAD_PROC(thread_pool_thread_proc) { } // if we've done all our work, and there's nothing to steal, go to sleep - state = pool->tasks_available.load(std::memory_order_acquire); + pool->tasks_available.store(Someone_Waiting); if (!pool->running) { break; } - futex_wait(&pool->tasks_available, state); + futex_wait(&pool->tasks_available, Someone_Waiting); main_loop_continue:; } return 0; } + diff --git a/src/threading.cpp b/src/threading.cpp index a0d1c4049..bc92ad3f2 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -195,7 +195,13 @@ gb_internal void mutex_lock(RecursiveMutex *m) { // inside the lock return; } - futex_wait(&m->owner, prev_owner); + + // NOTE(lucas): we are doing spin lock since futex signal is expensive on OSX. The recursive locks are + // very short lived so we don't hit this mega often and I see no perform regression on windows (with + // a performance uplift on OSX). + + //futex_wait(&m->owner, prev_owner); + yield_thread(); } } gb_internal bool mutex_try_lock(RecursiveMutex *m) { @@ -216,7 +222,9 @@ gb_internal void mutex_unlock(RecursiveMutex *m) { return; } m->owner.exchange(0, std::memory_order_release); - futex_signal(&m->owner); + // NOTE(lucas): see comment about spin lock in mutex_lock above + + // futex_signal(&m->owner); // outside the lock } @@ -367,8 +375,8 @@ gb_internal void semaphore_wait(Semaphore *s) { } gb_internal bool mutex_try_lock(BlockingMutex *m) { ANNOTATE_LOCK_PRE(m, 1); - i32 v = m->state().exchange(Internal_Mutex_State_Locked, std::memory_order_acquire); - if (v == Internal_Mutex_State_Unlocked) { + i32 expected = Internal_Mutex_State_Unlocked; + if (m->state().compare_exchange_strong(expected, Internal_Mutex_State_Locked, std::memory_order_acquire)) { ANNOTATE_LOCK_POST(m); return true; } @@ -448,6 +456,45 @@ gb_internal void semaphore_wait(Semaphore *s) { } #endif +static const int RWLOCK_WRITER = 1<<0; +static const int RWLOCK_UPGRADED = 1<<1; +static const int RWLOCK_READER = 1<<2; +struct RWSpinLock { + Futex bits; +}; + +void rwlock_release_write(RWSpinLock *l) { + l->bits.fetch_and(~(RWLOCK_WRITER | RWLOCK_UPGRADED), std::memory_order_release); + futex_signal(&l->bits); +} + +bool rwlock_try_acquire_upgrade(RWSpinLock *l) { + int value = l->bits.fetch_or(RWLOCK_UPGRADED, std::memory_order_acquire); + return (value & (RWLOCK_UPGRADED | RWLOCK_WRITER)) == 0; +} + +void rwlock_acquire_upgrade(RWSpinLock *l) { + while (!rwlock_try_acquire_upgrade(l)) { + futex_wait(&l->bits, RWLOCK_UPGRADED | RWLOCK_WRITER); + } +} +void rwlock_release_upgrade(RWSpinLock *l) { + l->bits.fetch_add(-RWLOCK_UPGRADED, std::memory_order_acq_rel); + futex_signal(&l->bits); +} + +bool rwlock_try_release_upgrade_and_acquire_write(RWSpinLock *l) { + int expect = RWLOCK_UPGRADED; + return l->bits.compare_exchange_strong(expect, RWLOCK_WRITER, std::memory_order_acq_rel); +} + +void rwlock_release_upgrade_and_acquire_write(RWSpinLock *l) { + while (!rwlock_try_release_upgrade_and_acquire_write(l)) { + futex_wait(&l->bits, RWLOCK_UPGRADED); + } +} + + struct Parker { Futex state; }; @@ -502,8 +549,6 @@ gb_internal u32 thread_current_id(void) { __asm__("mov %%fs:0x10,%0" : "=r"(thread_id)); #elif defined(GB_SYSTEM_LINUX) thread_id = gettid(); -#elif defined(GB_SYSTEM_HAIKU) - thread_id = find_thread(NULL); #elif defined(GB_SYSTEM_FREEBSD) thread_id = pthread_getthreadid_np(); #elif defined(GB_SYSTEM_NETBSD) @@ -980,177 +1025,46 @@ gb_internal void futex_wait(Futex *f, Footex val) { } while (f->load() == val); } -#elif defined(GB_SYSTEM_HAIKU) - -// Futex implementation taken from https://tavianator.com/2023/futex.html - -#include -#include - -struct _Spinlock { - std::atomic_flag state; - - void init() { - state.clear(); - } - - void lock() { - while (state.test_and_set(std::memory_order_acquire)) { - #if defined(GB_CPU_X86) - _mm_pause(); - #else - (void)0; // spin... - #endif - } - } - - void unlock() { - state.clear(std::memory_order_release); - } -}; - -struct Futex_Waitq; - -struct Futex_Waiter { - _Spinlock lock; - pthread_t thread; - Futex *futex; - Futex_Waitq *waitq; - Futex_Waiter *prev, *next; -}; - -struct Futex_Waitq { - _Spinlock lock; - Futex_Waiter list; - - void init() { - auto head = &list; - head->prev = head->next = head; - } -}; - -// FIXME: This approach may scale badly in the future, -// possible solution - hash map (leads to deadlocks now). - -Futex_Waitq g_waitq = { - .lock = ATOMIC_FLAG_INIT, - .list = { - .prev = &g_waitq.list, - .next = &g_waitq.list, - }, -}; - -Futex_Waitq *get_waitq(Futex *f) { - // Future hash map method... - return &g_waitq; -} - -void futex_signal(Futex *f) { - auto waitq = get_waitq(f); - - waitq->lock.lock(); - - auto head = &waitq->list; - for (auto waiter = head->next; waiter != head; waiter = waiter->next) { - if (waiter->futex != f) { - continue; - } - waitq->lock.unlock(); - pthread_kill(waiter->thread, SIGCONT); - return; - } - - waitq->lock.unlock(); -} - -void futex_broadcast(Futex *f) { - auto waitq = get_waitq(f); - - waitq->lock.lock(); - - auto head = &waitq->list; - for (auto waiter = head->next; waiter != head; waiter = waiter->next) { - if (waiter->futex != f) { - continue; - } - if (waiter->next == head) { - waitq->lock.unlock(); - pthread_kill(waiter->thread, SIGCONT); - return; - } else { - pthread_kill(waiter->thread, SIGCONT); - } - } - - waitq->lock.unlock(); -} - -void futex_wait(Futex *f, Footex val) { - Futex_Waiter waiter; - waiter.thread = pthread_self(); - waiter.futex = f; - - auto waitq = get_waitq(f); - while (waitq->lock.state.test_and_set(std::memory_order_acquire)) { - if (f->load(std::memory_order_relaxed) != val) { - return; - } - #if defined(GB_CPU_X86) - _mm_pause(); - #else - (void)0; // spin... - #endif - } - - waiter.waitq = waitq; - waiter.lock.init(); - waiter.lock.lock(); - - auto head = &waitq->list; - waiter.prev = head->prev; - waiter.next = head; - waiter.prev->next = &waiter; - waiter.next->prev = &waiter; - - waiter.prev->next = &waiter; - waiter.next->prev = &waiter; - - sigset_t old_mask, mask; - sigemptyset(&mask); - sigaddset(&mask, SIGCONT); - pthread_sigmask(SIG_BLOCK, &mask, &old_mask); - - if (f->load(std::memory_order_relaxed) == val) { - waiter.lock.unlock(); - waitq->lock.unlock(); - - int sig; - sigwait(&mask, &sig); - - waitq->lock.lock(); - waiter.lock.lock(); - - while (waitq != waiter.waitq) { - auto req = waiter.waitq; - waiter.lock.unlock(); - waitq->lock.unlock(); - waitq = req; - waitq->lock.lock(); - waiter.lock.lock(); - } - } - - waiter.prev->next = waiter.next; - waiter.next->prev = waiter.prev; - - pthread_sigmask(SIG_SETMASK, &old_mask, NULL); - - waiter.lock.unlock(); - waitq->lock.unlock(); -} - #endif #if defined(GB_SYSTEM_WINDOWS) #pragma warning(pop) #endif + + + +template +struct AtomicFreelist { + T value; + std::atomic *> next; +}; + +template +AtomicFreelist *atomic_freelist_get(std::atomic *> &head) { + AtomicFreelist *elem = nullptr; + + for (;;) { + elem = head.load(std::memory_order_acquire); + if (elem == nullptr) { + return nullptr; + } + + if (head.compare_exchange_weak(elem, elem->next.load(std::memory_order_acquire), std::memory_order_acquire, std::memory_order_relaxed)) { + elem->next.store(nullptr, std::memory_order_relaxed); + return elem; + } + + } +} + +template +void atomic_freelist_put(std::atomic *> &head_list, AtomicFreelist *elem) { + for (;;) { + auto *head = head_list.load(std::memory_order_relaxed); + elem->next.store(head, std::memory_order_relaxed); + if (head_list.compare_exchange_weak(head, elem, std::memory_order_release, std::memory_order_relaxed)) { + return; + } + + } +} \ No newline at end of file diff --git a/src/tilde.cpp b/src/tilde.cpp deleted file mode 100644 index f6fed0f9a..000000000 --- a/src/tilde.cpp +++ /dev/null @@ -1,842 +0,0 @@ -#include "tilde.hpp" - - -gb_global Slice global_tb_arenas; - -gb_internal TB_Arena *cg_arena(void) { - return &global_tb_arenas[current_thread_index()]; -} - -gb_internal void cg_global_arena_init(void) { - global_tb_arenas = slice_make(permanent_allocator(), global_thread_pool.threads.count); - for_array(i, global_tb_arenas) { - tb_arena_create(&global_tb_arenas[i], 2ull<<20); - } -} - -// returns TB_TYPE_VOID if not trivially possible -gb_internal TB_DataType cg_data_type(Type *t) { - GB_ASSERT(t != nullptr); - t = core_type(t); - i64 sz = type_size_of(t); - switch (t->kind) { - case Type_Basic: - switch (t->Basic.kind) { - case Basic_bool: - case Basic_b8: - case Basic_b16: - case Basic_b32: - case Basic_b64: - - case Basic_i8: - case Basic_u8: - case Basic_i16: - case Basic_u16: - case Basic_i32: - case Basic_u32: - case Basic_i64: - case Basic_u64: - case Basic_i128: - case Basic_u128: - - case Basic_rune: - - case Basic_int: - case Basic_uint: - case Basic_uintptr: - case Basic_typeid: - return TB_TYPE_INTN(cast(u16)gb_min(8*sz, 64)); - - case Basic_f16: return TB_TYPE_F16; - case Basic_f32: return TB_TYPE_F32; - case Basic_f64: return TB_TYPE_F64; - - case Basic_rawptr: return TB_TYPE_PTR; - case Basic_cstring: return TB_TYPE_PTR; - - - // Endian Specific Types - case Basic_i16le: - case Basic_u16le: - case Basic_i32le: - case Basic_u32le: - case Basic_i64le: - case Basic_u64le: - case Basic_i128le: - case Basic_u128le: - case Basic_i16be: - case Basic_u16be: - case Basic_i32be: - case Basic_u32be: - case Basic_i64be: - case Basic_u64be: - case Basic_i128be: - case Basic_u128be: - return TB_TYPE_INTN(cast(u16)gb_min(8*sz, 64)); - - case Basic_f16le: return TB_TYPE_F16; - case Basic_f32le: return TB_TYPE_F32; - case Basic_f64le: return TB_TYPE_F64; - - case Basic_f16be: return TB_TYPE_F16; - case Basic_f32be: return TB_TYPE_F32; - case Basic_f64be: return TB_TYPE_F64; - } - break; - - case Type_Pointer: - case Type_MultiPointer: - case Type_Proc: - return TB_TYPE_PTR; - - case Type_BitSet: - return cg_data_type(bit_set_to_int(t)); - - case Type_RelativePointer: - return cg_data_type(t->RelativePointer.base_integer); - } - - // unknown - return {}; -} - - -gb_internal cgValue cg_value(TB_Global *g, Type *type) { - return cg_value((TB_Symbol *)g, type); -} -gb_internal cgValue cg_value(TB_External *e, Type *type) { - return cg_value((TB_Symbol *)e, type); -} -gb_internal cgValue cg_value(TB_Function *f, Type *type) { - return cg_value((TB_Symbol *)f, type); -} -gb_internal cgValue cg_value(TB_Symbol *s, Type *type) { - cgValue v = {}; - v.kind = cgValue_Symbol; - v.type = type; - v.symbol = s; - return v; -} -gb_internal cgValue cg_value(TB_Node *node, Type *type) { - cgValue v = {}; - v.kind = cgValue_Value; - v.type = type; - v.node = node; - return v; -} -gb_internal cgValue cg_lvalue_addr(TB_Node *node, Type *type) { - GB_ASSERT(node->dt.type == TB_PTR); - cgValue v = {}; - v.kind = cgValue_Addr; - v.type = type; - v.node = node; - return v; -} - -gb_internal cgValue cg_lvalue_addr_to_value(cgValue v) { - if (v.kind == cgValue_Value) { - GB_ASSERT(is_type_pointer(v.type)); - GB_ASSERT(v.node->dt.type == TB_PTR); - } else { - GB_ASSERT(v.kind == cgValue_Addr); - GB_ASSERT(v.node->dt.type == TB_PTR); - v.kind = cgValue_Value; - v.type = alloc_type_pointer(v.type); - } - return v; -} - -gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) { - GB_ASSERT(type->kind == Type_Tuple); - GB_ASSERT(multi != nullptr); - GB_ASSERT(type->Tuple.variables.count > 1); - GB_ASSERT(multi->values.count == type->Tuple.variables.count); - cgValue v = {}; - v.kind = cgValue_Multi; - v.type = type; - v.multi = multi; - return v; -} - -gb_internal cgValue cg_value_multi(Slice const &values, Type *type) { - cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti); - multi->values = values; - return cg_value_multi(multi, type); -} - - -gb_internal cgValue cg_value_multi2(cgValue const &x, cgValue const &y, Type *type) { - GB_ASSERT(type->kind == Type_Tuple); - GB_ASSERT(type->Tuple.variables.count == 2); - cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti); - multi->values = slice_make(permanent_allocator(), 2); - multi->values[0] = x; - multi->values[1] = y; - return cg_value_multi(multi, type); -} - - -gb_internal cgAddr cg_addr(cgValue const &value) { - GB_ASSERT(value.kind != cgValue_Multi); - cgAddr addr = {}; - addr.kind = cgAddr_Default; - addr.addr = value; - if (addr.addr.kind == cgValue_Addr) { - GB_ASSERT(addr.addr.node != nullptr); - addr.addr.kind = cgValue_Value; - addr.addr.type = alloc_type_pointer(addr.addr.type); - } - return addr; -} - -gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Type *map_result) { - GB_ASSERT(is_type_pointer(addr.type)); - Type *mt = type_deref(addr.type); - GB_ASSERT(is_type_map(mt)); - - cgAddr v = {cgAddr_Map, addr}; - v.map.key = map_key; - v.map.type = map_type; - v.map.result = map_result; - return v; -} - -gb_internal cgAddr cg_addr_soa_variable(cgValue addr, cgValue index, Ast *index_expr) { - cgAddr v = {cgAddr_SoaVariable, addr}; - v.soa.index = index; - v.soa.index_expr = index_expr; - return v; -} - - - -gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) { - if (node) { - TokenPos pos = ast_token(node).pos; - TB_SourceFile **file = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id); - if (file) { - tb_inst_location(p->func, *file, pos.line, pos.column); - } - } -} - -gb_internal void cg_add_symbol(cgModule *m, Entity *e, TB_Symbol *symbol) { - if (e) { - rw_mutex_lock(&m->values_mutex); - map_set(&m->symbols, e, symbol); - rw_mutex_unlock(&m->values_mutex); - } -} - -gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) { - if (e) { - rw_mutex_lock(&m->values_mutex); - GB_ASSERT(val.node != nullptr); - map_set(&m->values, e, val); - rw_mutex_unlock(&m->values_mutex); - } -} - -gb_internal void cg_add_member(cgModule *m, String const &name, cgValue const &val) { - if (name.len > 0) { - rw_mutex_lock(&m->values_mutex); - string_map_set(&m->members, name, val); - rw_mutex_unlock(&m->values_mutex); - } -} - -gb_internal void cg_add_procedure_value(cgModule *m, cgProcedure *p) { - rw_mutex_lock(&m->values_mutex); - if (p->entity != nullptr) { - map_set(&m->procedure_values, p->func, p->entity); - if (p->symbol != nullptr) { - map_set(&m->symbols, p->entity, p->symbol); - } - } - string_map_set(&m->procedures, p->name, p); - rw_mutex_unlock(&m->values_mutex); - -} - -gb_internal TB_Symbol *cg_find_symbol_from_entity(cgModule *m, Entity *e) { - GB_ASSERT(e != nullptr); - - rw_mutex_lock(&m->values_mutex); - TB_Symbol **found = map_get(&m->symbols, e); - if (found) { - rw_mutex_unlock(&m->values_mutex); - return *found; - } - - String link_name = cg_get_entity_name(m, e); - cgProcedure **proc_found = string_map_get(&m->procedures, link_name); - if (proc_found) { - TB_Symbol *symbol = (*proc_found)->symbol; - map_set(&m->symbols, e, symbol); - rw_mutex_unlock(&m->values_mutex); - return symbol; - } - rw_mutex_unlock(&m->values_mutex); - - if (e->kind == Entity_Procedure) { - debugf("[Tilde] try to generate procedure %.*s as it was not in the minimum_dependency_set", LIT(e->token.string)); - // IMPORTANT TODO(bill): This is an utter bodge, try and fix this shit - cgProcedure *p = cg_procedure_create(m, e); - if (p != nullptr) { - GB_ASSERT(p->symbol != nullptr); - cg_add_procedure_to_queue(p); - return p->symbol; - } - } - - - GB_PANIC("could not find entity's symbol %.*s", LIT(e->token.string)); - return nullptr; -} - - -struct cgGlobalVariable { - cgValue var; - cgValue init; - DeclInfo *decl; - bool is_initialized; -}; - -// Returns already_has_entry_point -gb_internal bool cg_global_variables_create(cgModule *m, Array *global_variables) { - isize global_variable_max_count = 0; - bool already_has_entry_point = false; - - for (Entity *e : m->info->entities) { - String name = e->token.string; - - if (e->kind == Entity_Variable) { - global_variable_max_count++; - } else if (e->kind == Entity_Procedure) { - if ((e->scope->flags&ScopeFlag_Init) && name == "main") { - GB_ASSERT(e == m->info->entry_point); - } - if (build_context.command_kind == Command_test && - (e->Procedure.is_export || e->Procedure.link_name.len > 0)) { - String link_name = e->Procedure.link_name; - if (e->pkg->kind == Package_Runtime) { - if (link_name == "main" || - link_name == "DllMain" || - link_name == "WinMain" || - link_name == "wWinMain" || - link_name == "mainCRTStartup" || - link_name == "_start") { - already_has_entry_point = true; - } - } - } - } - } - *global_variables = array_make(permanent_allocator(), 0, global_variable_max_count); - - auto *min_dep_set = &m->info->minimum_dependency_set; - - for (DeclInfo *d : m->info->variable_init_order) { - Entity *e = d->entity; - - if ((e->scope->flags & ScopeFlag_File) == 0) { - continue; - } - - if (!ptr_set_exists(min_dep_set, e)) { - continue; - } - - DeclInfo *decl = decl_info_of_entity(e); - if (decl == nullptr) { - continue; - } - GB_ASSERT(e->kind == Entity_Variable); - - bool is_foreign = e->Variable.is_foreign; - bool is_export = e->Variable.is_export; - - String name = cg_get_entity_name(m, e); - - TB_Linkage linkage = TB_LINKAGE_PRIVATE; - - if (is_foreign) { - linkage = TB_LINKAGE_PUBLIC; - // lb_add_foreign_library_path(m, e->Variable.foreign_library); - } else if (is_export) { - linkage = TB_LINKAGE_PUBLIC; - } - // lb_set_linkage_from_entity_flags(m, g.value, e->flags); - - TB_DebugType *debug_type = cg_debug_type(m, e->type); - TB_Global *global = tb_global_create(m->mod, name.len, cast(char const *)name.text, debug_type, linkage); - cgValue g = cg_value(global, alloc_type_pointer(e->type)); - - TB_ModuleSectionHandle section = tb_module_get_data(m->mod); - - if (e->Variable.thread_local_model != "") { - section = tb_module_get_tls(m->mod); - } - if (e->Variable.link_section.len > 0) { - // TODO(bill): custom module sections - // LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section)); - } - - - cgGlobalVariable var = {}; - var.var = g; - var.decl = decl; - - if (decl->init_expr != nullptr) { - TypeAndValue tav = type_and_value_of_expr(decl->init_expr); - - isize max_regions = cg_global_const_calculate_region_count(tav.value, e->type); - tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), max_regions); - - if (tav.mode == Addressing_Constant && - tav.value.kind != ExactValue_Invalid) { - cg_global_const_add_region(m, tav.value, e->type, global, 0); - var.is_initialized = true; - } - if (!var.is_initialized && is_type_untyped_nil(tav.type)) { - var.is_initialized = true; - } - } else { - var.is_initialized = true; - // TODO(bill): is this even needed; - i64 max_regions = cg_global_const_calculate_region_count_from_basic_type(e->type); - tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), max_regions); - } - - array_add(global_variables, var); - - cg_add_symbol(m, e, cast(TB_Symbol *)global); - cg_add_entity(m, e, g); - cg_add_member(m, name, g); - } - - cg_setup_type_info_data(m); - - return already_has_entry_point; -} - -gb_internal void cg_global_variables_initialize(cgProcedure *p, Array *global_variables) { - for (cgGlobalVariable &var : *global_variables) { - if (var.is_initialized) { - continue; - } - cgValue src = cg_build_expr(p, var.decl->init_expr); - cgValue dst = cg_flatten_value(p, var.var); - cg_emit_store(p, dst, src); - } -} - - -gb_internal cgModule *cg_module_create(Checker *c) { - cgModule *m = gb_alloc_item(permanent_allocator(), cgModule); - - m->checker = c; - m->info = &c->info; - - - TB_FeatureSet feature_set = {}; - bool is_jit = false; - m->mod = tb_module_create(TB_ARCH_X86_64, TB_SYSTEM_WINDOWS, &feature_set, is_jit); - tb_module_set_tls_index(m->mod, 10, "_tls_index"); - - map_init(&m->values); - map_init(&m->symbols); - map_init(&m->file_id_map); - map_init(&m->debug_type_map); - map_init(&m->proc_debug_type_map); - map_init(&m->proc_proto_map); - map_init(&m->anonymous_proc_lits_map); - map_init(&m->equal_procs); - map_init(&m->hasher_procs); - map_init(&m->map_get_procs); - map_init(&m->map_set_procs); - map_init(&m->map_info_map); - map_init(&m->map_cell_info_map); - - array_init(&m->single_threaded_procedure_queue, heap_allocator()); - - - for_array(id, global_files) { - if (AstFile *f = global_files[id]) { - char const *path = alloc_cstring(temporary_allocator(), f->fullpath); - TB_SourceFile *file = tb_get_source_file(m->mod, path); - map_set(&m->file_id_map, cast(uintptr)id, file); - } - } - - return m; -} - -gb_internal void cg_module_destroy(cgModule *m) { - map_destroy(&m->values); - map_destroy(&m->symbols); - map_destroy(&m->file_id_map); - map_destroy(&m->debug_type_map); - map_destroy(&m->proc_debug_type_map); - map_destroy(&m->proc_proto_map); - map_destroy(&m->anonymous_proc_lits_map); - map_destroy(&m->equal_procs); - map_destroy(&m->hasher_procs); - map_destroy(&m->map_get_procs); - map_destroy(&m->map_set_procs); - map_destroy(&m->map_info_map); - map_destroy(&m->map_cell_info_map); - - array_free(&m->single_threaded_procedure_queue); - - tb_module_destroy(m->mod); -} - -gb_internal String cg_set_nested_type_name_ir_mangled_name(Entity *e, cgProcedure *p) { - // NOTE(bill, 2020-03-08): A polymorphic procedure may take a nested type declaration - // and as a result, the declaration does not have time to determine what it should be - - GB_ASSERT(e != nullptr && e->kind == Entity_TypeName); - if (e->TypeName.ir_mangled_name.len != 0) { - return e->TypeName.ir_mangled_name; - } - GB_ASSERT((e->scope->flags & ScopeFlag_File) == 0); - - if (p == nullptr) { - Entity *proc = nullptr; - if (e->parent_proc_decl != nullptr) { - proc = e->parent_proc_decl->entity; - } else { - Scope *scope = e->scope; - while (scope != nullptr && (scope->flags & ScopeFlag_Proc) == 0) { - scope = scope->parent; - } - GB_ASSERT(scope != nullptr); - GB_ASSERT(scope->flags & ScopeFlag_Proc); - proc = scope->procedure_entity; - } - GB_ASSERT(proc->kind == Entity_Procedure); - if (proc->cg_procedure != nullptr) { - p = proc->cg_procedure; - } - } - - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = e->token.string; - - if (p != nullptr) { - isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1); - name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - return name; - } else { - // NOTE(bill): a nested type be required before its parameter procedure exists. Just give it a temp name for now - isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - static std::atomic guid; - name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1)); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - return name; - } -} - -gb_internal String cg_mangle_name(cgModule *m, Entity *e) { - String name = e->token.string; - - AstPackage *pkg = e->pkg; - GB_ASSERT_MSG(pkg != nullptr, "Missing package for '%.*s'", LIT(name)); - String pkgn = pkg->name; - GB_ASSERT(!rune_is_digit(pkgn[0])); - if (pkgn == "llvm") { - GB_PANIC("llvm. entities are not allowed with the tilde backend"); - } - - isize max_len = pkgn.len + 1 + name.len + 1; - bool require_suffix_id = is_type_polymorphic(e->type, true); - - if ((e->scope->flags & (ScopeFlag_File | ScopeFlag_Pkg)) == 0) { - require_suffix_id = true; - } else if (is_blank_ident(e->token)) { - require_suffix_id = true; - }if (e->flags & EntityFlag_NotExported) { - require_suffix_id = true; - } - - if (require_suffix_id) { - max_len += 21; - } - - char *new_name = gb_alloc_array(permanent_allocator(), char, max_len); - isize new_name_len = gb_snprintf( - new_name, max_len, - "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name) - ); - if (require_suffix_id) { - char *str = new_name + new_name_len-1; - isize len = max_len-new_name_len; - isize extra = gb_snprintf(str, len, "-%llu", cast(unsigned long long)e->id); - new_name_len += extra-1; - } - - String mangled_name = make_string((u8 const *)new_name, new_name_len-1); - return mangled_name; -} - -gb_internal String cg_get_entity_name(cgModule *m, Entity *e) { - if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { - return e->TypeName.ir_mangled_name; - } - GB_ASSERT(e != nullptr); - - if (e->pkg == nullptr) { - return e->token.string; - } - - if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { - return cg_set_nested_type_name_ir_mangled_name(e, nullptr); - } - - String name = {}; - - bool no_name_mangle = false; - - if (e->kind == Entity_Variable) { - bool is_foreign = e->Variable.is_foreign; - bool is_export = e->Variable.is_export; - no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export; - if (e->Variable.link_name.len > 0) { - return e->Variable.link_name; - } - } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { - return e->Procedure.link_name; - } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { - no_name_mangle = true; - } - - if (!no_name_mangle) { - name = cg_mangle_name(m, e); - } - if (name.len == 0) { - name = e->token.string; - } - - if (e->kind == Entity_TypeName) { - e->TypeName.ir_mangled_name = name; - } else if (e->kind == Entity_Procedure) { - e->Procedure.link_name = name; - } - - return name; -} - -#include "tilde_const.cpp" -#include "tilde_debug.cpp" -#include "tilde_expr.cpp" -#include "tilde_builtin.cpp" -#include "tilde_type_info.cpp" -#include "tilde_proc.cpp" -#include "tilde_stmt.cpp" - - -gb_internal String cg_filepath_obj_for_module(cgModule *m, bool use_assembly) { - String path = concatenate3_strings(permanent_allocator(), - build_context.build_paths[BuildPath_Output].basename, - STR_LIT("/"), - build_context.build_paths[BuildPath_Output].name - ); - - // if (m->file) { - // char buf[32] = {}; - // isize n = gb_snprintf(buf, gb_size_of(buf), "-%u", m->file->id); - // String suffix = make_string((u8 *)buf, n-1); - // path = concatenate_strings(permanent_allocator(), path, suffix); - // } else if (m->pkg) { - // path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name); - // } - - String ext = {}; - - if (use_assembly) { - ext = STR_LIT(".S"); - } else { - if (is_arch_wasm()) { - ext = STR_LIT(".wasm.o"); - } else { - switch (build_context.metrics.os) { - case TargetOs_windows: - ext = STR_LIT(".obj"); - break; - default: - case TargetOs_darwin: - case TargetOs_linux: - case TargetOs_essence: - ext = STR_LIT(".o"); - break; - - case TargetOs_freestanding: - switch (build_context.metrics.abi) { - default: - case TargetABI_Default: - case TargetABI_SysV: - ext = STR_LIT(".o"); - break; - case TargetABI_Win64: - ext = STR_LIT(".obj"); - break; - } - break; - } - } - } - - return concatenate_strings(permanent_allocator(), path, ext); -} - - -gb_internal WORKER_TASK_PROC(cg_procedure_generate_worker_proc) { - cgProcedure *p = cast(cgProcedure *)data; - cg_procedure_generate(p); - return 0; -} - -gb_internal void cg_add_procedure_to_queue(cgProcedure *p) { - if (p == nullptr) { - return; - } - cgModule *m = p->module; - if (m->do_threading) { - thread_pool_add_task(cg_procedure_generate_worker_proc, p); - } else { - array_add(&m->single_threaded_procedure_queue, p); - } -} - -gb_internal bool cg_generate_code(Checker *c, LinkerData *linker_data) { - TIME_SECTION("Tilde Module Initializtion"); - - CheckerInfo *info = &c->info; - - linker_data_init(linker_data, info, c->parser->init_fullpath); - - #if defined(GB_SYSTEM_OSX) - linker_enable_system_library_linking(linker_data); - #endif - - cg_global_arena_init(); - - cgModule *m = cg_module_create(c); - defer (cg_module_destroy(m)); - - m->do_threading = false; - - TIME_SECTION("Tilde Global Variables"); - - Array global_variables = {}; - bool already_has_entry_point = cg_global_variables_create(m, &global_variables); - gb_unused(already_has_entry_point); - - if (true) { - Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); - cgProcedure *p = cg_procedure_create_dummy(m, str_lit(CG_STARTUP_RUNTIME_PROC_NAME), proc_type); - p->is_startup = true; - cg_startup_runtime_proc = p; - } - - if (true) { - Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin); - cgProcedure *p = cg_procedure_create_dummy(m, str_lit(CG_CLEANUP_RUNTIME_PROC_NAME), proc_type); - p->is_startup = true; - cg_cleanup_runtime_proc = p; - } - - auto *min_dep_set = &info->minimum_dependency_set; - - Array procedures_to_generate = {}; - array_init(&procedures_to_generate, heap_allocator()); - defer (array_free(&procedures_to_generate)); - - for (Entity *e : info->entities) { - String name = e->token.string; - Scope *scope = e->scope; - - if ((scope->flags & ScopeFlag_File) == 0) { - continue; - } - - Scope *package_scope = scope->parent; - GB_ASSERT(package_scope->flags & ScopeFlag_Pkg); - - if (e->kind != Entity_Procedure) { - continue; - } - - if (!ptr_set_exists(min_dep_set, e)) { - // NOTE(bill): Nothing depends upon it so doesn't need to be built - continue; - } - if (cgProcedure *p = cg_procedure_create(m, e)) { - array_add(&procedures_to_generate, p); - } - } - for (cgProcedure *p : procedures_to_generate) { - cg_add_procedure_to_queue(p); - } - - if (!m->do_threading) { - for (isize i = 0; i < m->single_threaded_procedure_queue.count; i++) { - cgProcedure *p = m->single_threaded_procedure_queue[i]; - cg_procedure_generate(p); - } - } - - thread_pool_wait(); - - { - cgProcedure *p = cg_startup_runtime_proc; - cg_procedure_begin(p); - cg_global_variables_initialize(p, &global_variables); - tb_inst_ret(p->func, 0, nullptr); - cg_procedure_end(p); - } - { - cgProcedure *p = cg_cleanup_runtime_proc; - cg_procedure_begin(p); - tb_inst_ret(p->func, 0, nullptr); - cg_procedure_end(p); - } - - - TB_DebugFormat debug_format = TB_DEBUGFMT_NONE; - if (build_context.ODIN_DEBUG) { - switch (build_context.metrics.os) { - case TargetOs_windows: - debug_format = TB_DEBUGFMT_CODEVIEW; - break; - case TargetOs_darwin: - case TargetOs_linux: - case TargetOs_essence: - case TargetOs_freebsd: - case TargetOs_openbsd: - case TargetOs_haiku: - debug_format = TB_DEBUGFMT_DWARF; - break; - } - } - TB_ExportBuffer export_buffer = tb_module_object_export(m->mod, debug_format); - defer (tb_export_buffer_free(export_buffer)); - - String filepath_obj = cg_filepath_obj_for_module(m, false); - array_add(&linker_data->output_object_paths, filepath_obj); - GB_ASSERT(tb_export_buffer_to_file(export_buffer, cast(char const *)filepath_obj.text)); - - return true; -} - -#undef ABI_PKG_NAME_SEPARATOR diff --git a/src/tilde.hpp b/src/tilde.hpp deleted file mode 100644 index d141b2330..000000000 --- a/src/tilde.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#if defined(GB_SYSTEM_WINDOWS) - #pragma warning(push) - #pragma warning(disable: 4200) - #pragma warning(disable: 4201) - #define restrict gb_restrict -#endif - -#include "tilde/tb.h" -#include "tilde/tb_arena.h" - -#define TB_TYPE_F16 TB_DataType{ { TB_INT, 16 } } -#define TB_TYPE_I128 TB_DataType{ { TB_INT, 128 } } -#define TB_TYPE_INT TB_TYPE_INTN(cast(u16)(8*build_context.int_size)) -#define TB_TYPE_INTPTR TB_TYPE_INTN(cast(u16)(8*build_context.ptr_size)) - -#if defined(GB_SYSTEM_WINDOWS) - #pragma warning(pop) -#endif - -#define CG_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" -#define CG_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime" -#define CG_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info" -#define CG_TYPE_INFO_DATA_NAME "__$type_info_data" -#define CG_TYPE_INFO_TYPES_NAME "__$type_info_types_data" -#define CG_TYPE_INFO_NAMES_NAME "__$type_info_names_data" -#define CG_TYPE_INFO_OFFSETS_NAME "__$type_info_offsets_data" -#define CG_TYPE_INFO_USINGS_NAME "__$type_info_usings_data" -#define CG_TYPE_INFO_TAGS_NAME "__$type_info_tags_data" -#define CG_TYPE_INFO_ENUM_VALUES_NAME "__$type_info_enum_values_data" - -struct cgModule; - - -enum cgValueKind : u32 { - cgValue_Value, // rvalue - cgValue_Addr, // lvalue - cgValue_Symbol, // global - cgValue_Multi, // multiple values -}; - -struct cgValueMulti; - -struct cgValue { - cgValueKind kind; - Type * type; - union { - // NOTE: any value in this union must be a pointer - TB_Symbol * symbol; - TB_Node * node; - cgValueMulti *multi; - }; -}; - -struct cgValueMulti { - Slice values; -}; - - -enum cgAddrKind { - cgAddr_Default, - cgAddr_Map, - cgAddr_Context, - cgAddr_SoaVariable, - - cgAddr_RelativePointer, - cgAddr_RelativeSlice, - - cgAddr_Swizzle, - cgAddr_SwizzleLarge, -}; - -struct cgAddr { - cgAddrKind kind; - cgValue addr; - union { - struct { - cgValue key; - Type *type; - Type *result; - } map; - struct { - Selection sel; - } ctx; - struct { - cgValue index; - Ast *index_expr; - } soa; - struct { - cgValue index; - Ast *node; - } index_set; - struct { - bool deref; - } relative; - struct { - Type *type; - u8 count; // 2, 3, or 4 components - u8 indices[4]; - } swizzle; - struct { - Type *type; - Slice indices; - } swizzle_large; - }; -}; - - -struct cgTargetList { - cgTargetList *prev; - bool is_block; - // control regions - TB_Node * break_; - TB_Node * continue_; - TB_Node * fallthrough_; -}; - -struct cgBranchRegions { - Ast * label; - TB_Node *break_; - TB_Node *continue_; -}; - -enum cgDeferExitKind { - cgDeferExit_Default, - cgDeferExit_Return, - cgDeferExit_Branch, -}; - -enum cgDeferKind { - cgDefer_Node, - cgDefer_Proc, -}; - -struct cgDefer { - cgDeferKind kind; - isize scope_index; - isize context_stack_count; - TB_Node * control_region; - union { - Ast *stmt; - struct { - cgValue deferred; - Slice result_as_args; - } proc; - }; -}; - - -struct cgContextData { - cgAddr ctx; - isize scope_index; - isize uses; -}; - -struct cgControlRegion { - TB_Node *control_region; - isize scope_index; -}; - -struct cgProcedure { - u32 flags; - u16 state_flags; - - cgProcedure *parent; - Array children; - - TB_Function *func; - TB_FunctionPrototype *proto; - TB_Symbol *symbol; - - Entity * entity; - cgModule *module; - String name; - Type * type; - Ast * type_expr; - Ast * body; - u64 tags; - ProcInlining inlining; - bool is_foreign; - bool is_export; - bool is_entry_point; - bool is_startup; - - TB_DebugType *debug_type; - - cgValue value; - - Ast *curr_stmt; - - cgTargetList * target_list; - Array defer_stack; - Array scope_stack; - Array context_stack; - - Array control_regions; - Array branch_regions; - - Scope *curr_scope; - i32 scope_index; - bool in_multi_assignment; - isize split_returns_index; - bool return_by_ptr; - - PtrMap variable_map; - PtrMap soa_values_map; -}; - - -struct cgModule { - TB_Module * mod; - Checker * checker; - CheckerInfo *info; - LinkerData * linker_data; - - bool do_threading; - Array single_threaded_procedure_queue; - - RwMutex values_mutex; - PtrMap values; - PtrMap symbols; - StringMap members; - StringMap procedures; - PtrMap procedure_values; - - RecursiveMutex debug_type_mutex; - PtrMap debug_type_map; - PtrMap proc_debug_type_map; // not pointer to - - RecursiveMutex proc_proto_mutex; - PtrMap proc_proto_map; - - BlockingMutex anonymous_proc_lits_mutex; - PtrMap anonymous_proc_lits_map; - - RecursiveMutex generated_procs_mutex; - PtrMap equal_procs; - PtrMap hasher_procs; - PtrMap map_get_procs; - PtrMap map_set_procs; - - RecursiveMutex map_info_mutex; - PtrMap map_info_map; - PtrMap map_cell_info_map; - - // NOTE(bill): no need to protect this with a mutex - PtrMap file_id_map; // Key: AstFile.id (i32 cast to uintptr) - - std::atomic nested_type_name_guid; - std::atomic const_nil_guid; -}; - -#ifndef ABI_PKG_NAME_SEPARATOR -#define ABI_PKG_NAME_SEPARATOR "@" -#endif - -struct GlobalTypeInfoData { - TB_Global *global; - Type * array_type; - Type * elem_type; - isize index; -}; - -gb_global Entity *cg_global_type_info_data_entity = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_types = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_names = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_offsets = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_usings = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_tags = {}; -gb_global GlobalTypeInfoData cg_global_type_info_member_enum_values = {}; - -gb_global cgProcedure *cg_startup_runtime_proc = nullptr; -gb_global cgProcedure *cg_cleanup_runtime_proc = nullptr; - - - -gb_internal TB_Arena *cg_arena(void); - -gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool ignore_body=false); -gb_internal void cg_add_procedure_to_queue(cgProcedure *p); -gb_internal void cg_setup_type_info_data(cgModule *m); -gb_internal cgProcedure *cg_procedure_generate_anonymous(cgModule *m, Ast *expr, cgProcedure *parent); - -gb_internal isize cg_global_const_calculate_region_count(ExactValue const &value, Type *type); -gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *type); -gb_internal bool cg_global_const_add_region(cgModule *m, ExactValue const &value, Type *type, TB_Global *global, i64 offset); - -gb_internal String cg_get_entity_name(cgModule *m, Entity *e); - -gb_internal cgValue cg_value(TB_Global * g, Type *type); -gb_internal cgValue cg_value(TB_External *e, Type *type); -gb_internal cgValue cg_value(TB_Function *f, Type *type); -gb_internal cgValue cg_value(TB_Symbol * s, Type *type); -gb_internal cgValue cg_value(TB_Node * node, Type *type); - -gb_internal cgAddr cg_addr(cgValue const &value); -gb_internal cgAddr cg_addr_map(cgValue addr, cgValue map_key, Type *map_type, Type *map_result); - -gb_internal u64 cg_typeid_as_u64(cgModule *m, Type *type); -gb_internal cgValue cg_type_info(cgProcedure *p, Type *type); -gb_internal isize cg_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=true); - -gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value); -gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type); - -gb_internal cgValue cg_flatten_value(cgProcedure *p, cgValue value); - -gb_internal void cg_build_stmt(cgProcedure *p, Ast *stmt); -gb_internal void cg_build_stmt_list(cgProcedure *p, Slice const &stmts); -gb_internal void cg_build_when_stmt(cgProcedure *p, AstWhenStmt *ws); - - -gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr); -gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr); -gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr); -gb_internal cgValue cg_build_cond(cgProcedure *p, Ast *cond, TB_Node *true_block, TB_Node *false_block); - -gb_internal Type * cg_addr_type(cgAddr const &addr); -gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr); -gb_internal void cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value); -gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr); - -gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false); -gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile=false); - -gb_internal cgAddr cg_add_local (cgProcedure *p, Type *type, Entity *e, bool zero_init); -gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e); -gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value); -gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment); - -gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr); - -gb_internal void cg_build_return_stmt(cgProcedure *p, Slice const &return_results); -gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice const &results); -gb_internal void cg_build_return_stmt_internal_single(cgProcedure *p, cgValue result); -gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node); - -gb_internal cgValue cg_find_value_from_entity(cgModule *m, Entity *e); -gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e); - -gb_internal TB_DebugType *cg_debug_type(cgModule *m, Type *type); - -gb_internal String cg_get_entity_name(cgModule *m, Entity *e); - -gb_internal cgValue cg_typeid(cgProcedure *m, Type *t); - -gb_internal cgValue cg_emit_ptr_offset(cgProcedure *p, cgValue ptr, cgValue index); -gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index); -gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index); -gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index); -gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel); -gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index); - -gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t); -gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind, cgValue x); -gb_internal cgValue cg_emit_comp(cgProcedure *p, TokenKind op_kind, cgValue left, cgValue right); -gb_internal cgValue cg_emit_arith(cgProcedure *p, TokenKind op, cgValue lhs, cgValue rhs, Type *type); -gb_internal cgValue cg_emit_unary_arith(cgProcedure *p, TokenKind op, cgValue x, Type *type); -gb_internal void cg_emit_increment(cgProcedure *p, cgValue addr); - -gb_internal cgProcedure *cg_equal_proc_for_type (cgModule *m, Type *type); -gb_internal cgProcedure *cg_hasher_proc_for_type(cgModule *m, Type *type); -gb_internal cgValue cg_hasher_proc_value_for_type(cgProcedure *p, Type *type); -gb_internal cgValue cg_equal_proc_value_for_type(cgProcedure *p, Type *type); - -gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice const &args); -gb_internal cgValue cg_emit_runtime_call(cgProcedure *p, char const *name, Slice const &args); - -gb_internal bool cg_emit_goto(cgProcedure *p, TB_Node *control_region); - -gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name); - -gb_internal isize cg_append_tuple_values(cgProcedure *p, Array *dst_values, cgValue src_value); - -gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos); - -gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value); -gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x); -gb_internal cgValue cg_builtin_map_info(cgProcedure *p, Type *map_type); -gb_internal cgValue cg_builtin_map_cell_info(cgProcedure *p, Type *type); -gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, String const &proc_name, TokenPos pos); -gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, Ast *node); - - -gb_internal cgValue cg_internal_dynamic_map_get_ptr(cgProcedure *p, cgValue const &map_ptr, cgValue const &key); -gb_internal void cg_internal_dynamic_map_set(cgProcedure *p, cgValue const &map_ptr, Type *map_type, - cgValue const &map_key, cgValue const &map_value, Ast *node); \ No newline at end of file diff --git a/src/tilde/tb.h b/src/tilde/tb.h deleted file mode 100644 index 4fe21c902..000000000 --- a/src/tilde/tb.h +++ /dev/null @@ -1,1309 +0,0 @@ -// Glossary (because i don't know where else to put it) -// IR - intermediate representation -// SoN - sea of nodes (https://www.oracle.com/technetwork/java/javase/tech/c2-ir95-150110.pdf) -// SSA - single static assignment -// GVN - global value numbering -// CSE - common subexpression elimination -// CFG - control flow graph -// DSE - dead store elimination -// GCM - global code motion -// SROA - scalar replacement of aggregates -// SCCP - sparse conditional constant propagation -// RPO - reverse postorder -// BB - basic block -// ZTC - zero trip count -// SCC - strongly connected components -#ifndef TB_CORE_H -#define TB_CORE_H - -#include -#include -#include -#include -#include -#include -#include -#include - -// https://semver.org/ -#define TB_VERSION_MAJOR 0 -#define TB_VERSION_MINOR 3 -#define TB_VERSION_PATCH 0 - -#ifndef TB_API -# ifdef __cplusplus -# define TB_EXTERN extern "C" -# else -# define TB_EXTERN -# endif -# ifdef TB_DLL -# ifdef TB_IMPORT_DLL -# define TB_API TB_EXTERN __declspec(dllimport) -# else -# define TB_API TB_EXTERN __declspec(dllexport) -# endif -# else -# define TB_API TB_EXTERN -# endif -#endif - -// These are flags -typedef enum TB_ArithmeticBehavior { - TB_ARITHMATIC_NONE = 0, - TB_ARITHMATIC_NSW = 1, - TB_ARITHMATIC_NUW = 2, -} TB_ArithmeticBehavior; - -typedef enum TB_DebugFormat { - TB_DEBUGFMT_NONE, - - TB_DEBUGFMT_DWARF, - TB_DEBUGFMT_CODEVIEW, - - TB_DEBUGFMT_COLINPILLED -} TB_DebugFormat; - -typedef enum TB_Arch { - TB_ARCH_UNKNOWN, - - TB_ARCH_X86_64, - TB_ARCH_AARCH64, // unsupported but planned - TB_ARCH_WASM32, -} TB_Arch; - -typedef enum TB_System { - TB_SYSTEM_WINDOWS, - TB_SYSTEM_LINUX, - TB_SYSTEM_MACOS, - TB_SYSTEM_ANDROID, // Not supported yet - TB_SYSTEM_WEB, - - TB_SYSTEM_MAX, -} TB_System; - -typedef enum TB_WindowsSubsystem { - TB_WIN_SUBSYSTEM_UNKNOWN, - - TB_WIN_SUBSYSTEM_WINDOWS, - TB_WIN_SUBSYSTEM_CONSOLE, - TB_WIN_SUBSYSTEM_EFI_APP, -} TB_WindowsSubsystem; - -typedef enum TB_ABI { - // Used on 64bit Windows platforms - TB_ABI_WIN64, - - // Used on Mac, BSD and Linux platforms - TB_ABI_SYSTEMV, -} TB_ABI; - -typedef enum TB_OutputFlavor { - TB_FLAVOR_OBJECT, // .o .obj - TB_FLAVOR_SHARED, // .so .dll - TB_FLAVOR_STATIC, // .a .lib - TB_FLAVOR_EXECUTABLE, // .exe -} TB_OutputFlavor; - -typedef enum TB_CallingConv { - TB_CDECL, - TB_STDCALL -} TB_CallingConv; - -typedef enum TB_FeatureSet_X64 { - TB_FEATURE_X64_SSE3 = (1u << 0u), - TB_FEATURE_X64_SSE41 = (1u << 1u), - TB_FEATURE_X64_SSE42 = (1u << 2u), - - TB_FEATURE_X64_POPCNT = (1u << 3u), - TB_FEATURE_X64_LZCNT = (1u << 4u), - - TB_FEATURE_X64_CLMUL = (1u << 5u), - TB_FEATURE_X64_F16C = (1u << 6u), - - TB_FEATURE_X64_BMI1 = (1u << 7u), - TB_FEATURE_X64_BMI2 = (1u << 8u), - - TB_FEATURE_X64_AVX = (1u << 9u), - TB_FEATURE_X64_AVX2 = (1u << 10u), -} TB_FeatureSet_X64; - -typedef struct TB_FeatureSet { - TB_FeatureSet_X64 x64; -} TB_FeatureSet; - -typedef enum TB_Linkage { - TB_LINKAGE_PUBLIC, - TB_LINKAGE_PRIVATE -} TB_Linkage; - -typedef enum { - TB_COMDAT_NONE, - - TB_COMDAT_MATCH_ANY, -} TB_ComdatType; - -typedef enum TB_MemoryOrder { - TB_MEM_ORDER_RELAXED, - TB_MEM_ORDER_CONSUME, - TB_MEM_ORDER_ACQUIRE, - TB_MEM_ORDER_RELEASE, - TB_MEM_ORDER_ACQ_REL, - TB_MEM_ORDER_SEQ_CST, -} TB_MemoryOrder; - -typedef enum TB_DataTypeEnum { - // Integers, note void is an i0 and bool is an i1 - // i(0-64) - TB_INT, - // Floating point numbers - // f{32,64} - TB_FLOAT, - // Pointers - TB_PTR, - // represents control flow for REGION, BRANCH - TB_CONTROL, - // represents memory (and I/O) - TB_MEMORY, - // continuation (usually just return addresses :p) - TB_CONT, - // Tuples, these cannot be used in memory ops, just accessed via projections - TB_TUPLE, -} TB_DataTypeEnum; - -typedef enum TB_FloatFormat { - // IEEE 754 floats - TB_FLT_32, TB_FLT_64 -} TB_FloatFormat; - -typedef union TB_DataType { - struct { - uint16_t type : 4; - // for integers it's the bitwidth - uint16_t data : 12; - }; - uint16_t raw; -} TB_DataType; -static_assert(sizeof(TB_DataType) == 2, "im expecting this to be a uint16_t"); - -// classify data types -#define TB_IS_VOID_TYPE(x) ((x).type == TB_INT && (x).data == 0) -#define TB_IS_BOOL_TYPE(x) ((x).type == TB_INT && (x).data == 1) -#define TB_IS_INTEGER_TYPE(x) ((x).type == TB_INT) -#define TB_IS_FLOAT_TYPE(x) ((x).type == TB_FLOAT) -#define TB_IS_POINTER_TYPE(x) ((x).type == TB_PTR) - -// accessors -#define TB_GET_INT_BITWIDTH(x) ((x).data) -#define TB_GET_FLOAT_FORMAT(x) ((x).data) -#define TB_GET_PTR_ADDRSPACE(x) ((x).data) - -//////////////////////////////// -// ANNOTATIONS -//////////////////////////////// -// -// (A, B) -> (C, D) -// -// node takes A and B, produces C, D. if there's multiple -// results we need to use projections and the indices are -// based on the order seen here, proj0 is C, proj1 is D. -// -// (A, B) & C -> Int -// -// nodes takes A and B along with C in it's extra data. this is -// where non-node inputs fit. -// -typedef enum TB_NodeTypeEnum { - TB_NULL = 0, - - //////////////////////////////// - // CONSTANTS - //////////////////////////////// - TB_INTEGER_CONST, - TB_FLOAT32_CONST, - TB_FLOAT64_CONST, - - //////////////////////////////// - // MISCELLANEOUS - //////////////////////////////// - // this is an unspecified value, usually generated by the optimizer - // when malformed input is folded into an operation. - TB_POISON, // () -> Any - // projections just extract a single field of a tuple - TB_PROJ, // Tuple & Int -> Any - // this is a simple way to embed machine code into the code - TB_MACHINE_OP, // (Control, Memory) & Buffer -> (Control, Memory) - // reads the TSC on x64 - TB_CYCLE_COUNTER, // (Control) -> Int64 - // prefetches data for reading. The number next to the - // - // 0 is temporal - // 1-3 are just cache levels - TB_PREFETCH, // (Memory, Ptr) & Int -> Memory - - //////////////////////////////// - // CONTROL - //////////////////////////////// - // there's only one START and STOP per function - TB_START, // () -> (Control, Memory, Data...) - TB_END, // (Control, Memory, Data?) -> () - // regions are used to represent paths which have multiple entries. - // each input is a predecessor. - TB_REGION, // (Control...) -> (Control) - // phi nodes work the same as in SSA CFG, the value is based on which predecessor was taken. - // each input lines up with the regions such that region.in[i] will use phi.in[i+1] as the - // subsequent data. - TB_PHI, // (Control, Data...) -> Data - // branch is used to implement most control flow, it acts like a switch - // statement in C usually. they take a key and match against some cases, - // if they match, it'll jump to that successor, if none match it'll take - // the default successor. - // - // if (cond) { A; } else { B; } is just switch (cond) { case 0: B; default: A; } - // - // it's possible to not pass a key and the default successor is always called, this is - // a GOTO. tb_inst_goto, tb_inst_if can handle common cases for you. - TB_BRANCH, // (Control, Data?) -> (Control...) - // debugbreak will trap in a continuable manner. - TB_DEBUGBREAK, // (Control, Memory) -> (Control) - // trap will not be continuable but will stop execution. - TB_TRAP, // (Control) -> (Control) - // unreachable means it won't trap or be continuable. - TB_UNREACHABLE, // (Control) -> () - // this is generated when a path becomes disconnected - // from the main IR, it'll be reduced by the monotonic - // rewrites. - TB_DEAD, // () -> (Control) - - //////////////////////////////// - // CONTROL + MEMORY - //////////////////////////////// - // nothing special, it's just a function call, 3rd argument here is the - // target pointer (or syscall number) and the rest are just data args. - TB_CALL, // (Control, Memory, Data, Data...) -> (Control, Memory, Data) - TB_SYSCALL, // (Control, Memory, Data, Data...) -> (Control, Memory, Data) - // performs call while recycling the stack frame somewhat - TB_TAILCALL, // (Control, Memory, RPC, Data, Data...) -> () - // safepoint polls are the same except they only trigger if the poll site - // says to (platform specific but almost always just the page being made - // unmapped/guard), 3rd argument is the poll site. - TB_SAFEPOINT_POLL, // (Control, Memory, Ptr?, Data...) -> (Control) - // this safepoint which doesn't emit any poll site, it's just - // an address, this is used by AOT compiles to encode line info. - TB_SAFEPOINT_NOP, // (Control, Memory, Ptr?, Data...) -> (Control) - - //////////////////////////////// - // MEMORY - //////////////////////////////// - // MERGEMEM will join multiple non-aliasing memory effects, because - // they don't alias there's no ordering guarentee. - TB_MERGEMEM, // (Memory...) -> Memory - // LOAD and STORE are standard memory accesses, they can be folded away. - TB_LOAD, // (Control?, Memory, Ptr) -> Data - TB_STORE, // (Control, Memory, Ptr, Data) -> Memory - // bulk memory ops. - TB_MEMCPY, // (Control, Memory, Ptr, Ptr, Size) -> Memory - TB_MEMSET, // (Control, Memory, Ptr, Int8, Size) -> Memory - // these memory accesses represent "volatile" which means - // they may produce side effects and thus cannot be eliminated. - TB_READ, // (Control, Memory, Ptr) -> (Memory, Data) - TB_WRITE, // (Control, Memory, Ptr, Data) -> (Memory, Data) - // atomics have multiple observers (if not they wouldn't need to - // be atomic) and thus produce side effects everywhere just like - // volatiles except they have synchronization guarentees. the atomic - // data ops will return the value before the operation is performed. - // Atomic CAS return the old value and a boolean for success (true if - // the value was changed) - TB_ATOMIC_LOAD, // (Control, Memory, Ptr) -> (Memory, Data) - TB_ATOMIC_XCHG, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_ADD, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_SUB, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_AND, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_XOR, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_OR, // (Control, Memory, Ptr, Data) -> (Memory, Data) - TB_ATOMIC_CAS, // (Control, Memory, Data, Data) -> (Memory, Data, Bool) - - // like a multi-way branch but without the control flow aspect, but for data. - TB_LOOKUP, - - //////////////////////////////// - // POINTERS - //////////////////////////////// - // LOCAL will statically allocate stack space - TB_LOCAL, // () & (Int, Int) -> Ptr - // SYMBOL will return a pointer to a TB_Symbol - TB_SYMBOL, // () & TB_Symbol* -> Ptr - // offsets pointer by constant value - TB_MEMBER_ACCESS, // Ptr & Int -> Ptr - // arguments represent base, index, and stride respectively - // and will perform `base + index*stride` - TB_ARRAY_ACCESS, // (Ptr, Int) & Int -> Ptr - // converts an integer to a pointer - TB_INT2PTR, // Int -> Ptr - // converts a pointer to an integer - TB_PTR2INT, // Ptr -> Int - - // Conversions - TB_TRUNCATE, - TB_FLOAT_EXT, - TB_SIGN_EXT, - TB_ZERO_EXT, - TB_UINT2FLOAT, - TB_FLOAT2UINT, - TB_INT2FLOAT, - TB_FLOAT2INT, - TB_BITCAST, - - // Select - TB_SELECT, - - // Bitmagic - TB_BSWAP, - TB_CLZ, - TB_CTZ, - TB_POPCNT, - - // Unary operations - TB_NOT, - TB_NEG, - - // Integer arithmatic - TB_AND, - TB_OR, - TB_XOR, - TB_ADD, - TB_SUB, - TB_MUL, - - TB_SHL, - TB_SHR, - TB_SAR, - TB_ROL, - TB_ROR, - TB_UDIV, - TB_SDIV, - TB_UMOD, - TB_SMOD, - - // Float arithmatic - TB_FADD, - TB_FSUB, - TB_FMUL, - TB_FDIV, - TB_FMAX, - TB_FMIN, - - // Comparisons - TB_CMP_EQ, - TB_CMP_NE, - TB_CMP_ULT, - TB_CMP_ULE, - TB_CMP_SLT, - TB_CMP_SLE, - TB_CMP_FLT, - TB_CMP_FLE, - - // Special ops - // adds two paired integers to two other paired integers and returns - // a low and high value - TB_ADDPAIR, - // does full multiplication (64x64=128 and so on) returning - // the low and high values in separate projections - TB_MULPAIR, - - // variadic - TB_VA_START, - - // x86 intrinsics - TB_X86INTRIN_LDMXCSR, - TB_X86INTRIN_STMXCSR, - TB_X86INTRIN_SQRT, - TB_X86INTRIN_RSQRT, -} TB_NodeTypeEnum; -typedef uint8_t TB_NodeType; - -// just represents some region of bytes, usually in file parsing crap -typedef struct { - size_t length; - const uint8_t* data; -} TB_Slice; - -// represents byte counts -typedef uint32_t TB_CharUnits; - -// will get interned so each TB_Module has a unique identifier for the source file -typedef struct { - // used by the debug info export - int id; - - size_t len; - uint8_t path[]; -} TB_SourceFile; - -typedef struct TB_Location { - TB_SourceFile* file; - int line, column; - uint32_t pos; -} TB_Location; - -// SO refers to shared objects which mean either shared libraries (.so or .dll) -// or executables (.exe or ELF executables) -typedef enum { - // exports to the rest of the shared object - TB_EXTERNAL_SO_LOCAL, - - // exports outside of the shared object - TB_EXTERNAL_SO_EXPORT, -} TB_ExternalType; - -typedef struct TB_Global TB_Global; -typedef struct TB_External TB_External; -typedef struct TB_Function TB_Function; - -typedef struct TB_Module TB_Module; -typedef struct TB_DebugType TB_DebugType; -typedef struct TB_ModuleSection TB_ModuleSection; -typedef struct TB_FunctionPrototype TB_FunctionPrototype; - -enum { TB_MODULE_SECTION_NONE = -1 }; -typedef int32_t TB_ModuleSectionHandle; -typedef struct TB_Attrib TB_Attrib; - -// target-specific, just a unique ID for the registers -typedef int TB_PhysicalReg; - -// Thread local module state -typedef struct TB_ThreadInfo TB_ThreadInfo; - -typedef enum { - TB_SYMBOL_NONE, - TB_SYMBOL_EXTERNAL, - TB_SYMBOL_GLOBAL, - TB_SYMBOL_FUNCTION, - TB_SYMBOL_MAX, -} TB_SymbolTag; - -// Refers generically to objects within a module -// -// TB_Function, TB_Global, and TB_External are all subtypes of TB_Symbol -// and thus are safely allowed to cast into a symbol for operations. -typedef struct TB_Symbol { - #ifdef __cplusplus - TB_SymbolTag tag; - #else - _Atomic TB_SymbolTag tag; - #endif - - // which thread info it's tied to (we may need to remove it, this - // is used for that) - TB_ThreadInfo* info; - char* name; - - // It's kinda a weird circular reference but yea - TB_Module* module; - - // helpful for sorting and getting consistent builds - uint64_t ordinal; - - union { - // if we're JITing then this maps to the address of the symbol - void* address; - size_t symbol_id; - }; - - // after this point it's tag-specific storage -} TB_Symbol; - -typedef struct TB_Node TB_Node; -typedef struct User User; -struct User { - User* next; - TB_Node* n; - int slot; -}; - -struct TB_Node { - TB_NodeType type; - uint16_t input_count; - TB_DataType dt; - - // makes it easier to track in graph walks - uint32_t gvn; - - // only value while inside of a TB_Passes, - // these are unordered and usually just - // help perform certain transformations or - // analysis (not necessarily semantics) - User* users; - - // ordered def-use edges, jolly ol' semantics - TB_Node** inputs; - - char extra[]; -}; - -// These are the extra data in specific nodes -#define TB_NODE_GET_EXTRA(n) ((void*) n->extra) -#define TB_NODE_GET_EXTRA_T(n, T) ((T*) (n)->extra) -#define TB_NODE_SET_EXTRA(n, T, ...) (*((T*) (n)->extra) = (T){ __VA_ARGS__ }) - -// this represents switch (many targets), if (one target) and goto (only default) logic. -typedef struct { // TB_BRANCH - size_t succ_count; - int64_t keys[]; -} TB_NodeBranch; - -typedef struct { // TB_PROJ - int index; -} TB_NodeProj; - -typedef struct { // TB_INTEGER_CONST - uint64_t value; -} TB_NodeInt; - -typedef struct { // any compare operator - TB_DataType cmp_dt; -} TB_NodeCompare; - -typedef struct { // any integer binary operator - TB_ArithmeticBehavior ab; -} TB_NodeBinopInt; - -typedef struct { - TB_CharUnits align; -} TB_NodeMemAccess; - -typedef struct { - int level; -} TB_NodePrefetch; - -typedef struct { - TB_CharUnits size, align; - int alias_index; // 0 if local is used beyond direct memops, 1...n as a unique alias name -} TB_NodeLocal; - -typedef struct { - // this is the raw buffer - size_t length; - const uint8_t* data; - - // represents the outputs, inputs and temporaries in that order - size_t outs, ins, tmps; - TB_PhysicalReg regs[]; -} TB_NodeMachineOp; - -typedef struct { - float value; -} TB_NodeFloat32; - -typedef struct { - double value; -} TB_NodeFloat64; - -typedef struct { - int64_t stride; -} TB_NodeArray; - -typedef struct { - int64_t offset; -} TB_NodeMember; - -typedef struct { - TB_Symbol* sym; -} TB_NodeSymbol; - -typedef struct { - TB_MemoryOrder order; - TB_MemoryOrder order2; - TB_Node* proj0; - TB_Node* proj1; -} TB_NodeAtomic; - -typedef struct { - // line info on safepoints - TB_SourceFile* file; - int line, column; -} TB_NodeSafepoint; - -typedef struct { - TB_FunctionPrototype* proto; - int proj_count; - TB_Node* projs[]; -} TB_NodeCall; - -typedef struct { - TB_FunctionPrototype* proto; -} TB_NodeTailcall; - -typedef struct { - const char* tag; - - // magic factor for hot-code, higher means run more often - float freq; - - // used for IR building only, stale after that. - TB_Node *mem_in, *mem_out; -} TB_NodeRegion; - -typedef struct { - int64_t key; - uint64_t val; -} TB_LookupEntry; - -typedef struct { - size_t entry_count; - TB_LookupEntry entries[]; -} TB_NodeLookup; - -typedef struct TB_MultiOutput { - size_t count; - union { - // count = 1 - TB_Node* single; - // count > 1 - TB_Node** multiple; - }; -} TB_MultiOutput; -#define TB_MULTI_OUTPUT(o) ((o).count > 1 ? (o).multiple : &(o).single) - -typedef struct { - int64_t key; - TB_Node* value; -} TB_SwitchEntry; - -typedef enum { - TB_EXECUTABLE_UNKNOWN, - TB_EXECUTABLE_PE, - TB_EXECUTABLE_ELF, -} TB_ExecutableType; - -typedef struct { - TB_Node* node; // type == TB_SAFEPOINT - void* userdata; - - uint32_t ip; // relative to the function body. - uint32_t count; // same as node->input_count - int32_t values[]; -} TB_Safepoint; - -typedef enum { - TB_MODULE_SECTION_WRITE = 1, - TB_MODULE_SECTION_EXEC = 2, - TB_MODULE_SECTION_TLS = 4, -} TB_ModuleSectionFlags; - -// ******************************* -// Public macros -// ******************************* -#ifdef __cplusplus - -#define TB_TYPE_TUPLE TB_DataType{ { TB_TUPLE } } -#define TB_TYPE_CONTROL TB_DataType{ { TB_CONTROL } } -#define TB_TYPE_VOID TB_DataType{ { TB_INT, 0 } } -#define TB_TYPE_I8 TB_DataType{ { TB_INT, 8 } } -#define TB_TYPE_I16 TB_DataType{ { TB_INT, 16 } } -#define TB_TYPE_I32 TB_DataType{ { TB_INT, 32 } } -#define TB_TYPE_I64 TB_DataType{ { TB_INT, 64 } } -#define TB_TYPE_F32 TB_DataType{ { TB_FLOAT, TB_FLT_32 } } -#define TB_TYPE_F64 TB_DataType{ { TB_FLOAT, TB_FLT_64 } } -#define TB_TYPE_BOOL TB_DataType{ { TB_INT, 1 } } -#define TB_TYPE_PTR TB_DataType{ { TB_PTR, 0 } } -#define TB_TYPE_MEMORY TB_DataType{ { TB_MEMORY,0 } } -#define TB_TYPE_CONT TB_DataType{ { TB_CONT, 0 } } -#define TB_TYPE_INTN(N) TB_DataType{ { TB_INT, (N) } } -#define TB_TYPE_PTRN(N) TB_DataType{ { TB_PTR, (N) } } - -#else - -#define TB_TYPE_TUPLE (TB_DataType){ { TB_TUPLE } } -#define TB_TYPE_CONTROL (TB_DataType){ { TB_CONTROL } } -#define TB_TYPE_VOID (TB_DataType){ { TB_INT, 0 } } -#define TB_TYPE_I8 (TB_DataType){ { TB_INT, 8 } } -#define TB_TYPE_I16 (TB_DataType){ { TB_INT, 16 } } -#define TB_TYPE_I32 (TB_DataType){ { TB_INT, 32 } } -#define TB_TYPE_I64 (TB_DataType){ { TB_INT, 64 } } -#define TB_TYPE_F32 (TB_DataType){ { TB_FLOAT, TB_FLT_32 } } -#define TB_TYPE_F64 (TB_DataType){ { TB_FLOAT, TB_FLT_64 } } -#define TB_TYPE_BOOL (TB_DataType){ { TB_INT, 1 } } -#define TB_TYPE_PTR (TB_DataType){ { TB_PTR, 0 } } -#define TB_TYPE_CONT (TB_DataType){ { TB_CONT, 0 } } -#define TB_TYPE_MEMORY (TB_DataType){ { TB_MEMORY,0 } } -#define TB_TYPE_INTN(N) (TB_DataType){ { TB_INT, (N) } } -#define TB_TYPE_PTRN(N) (TB_DataType){ { TB_PTR, (N) } } - -#endif - -typedef void (*TB_PrintCallback)(void* user_data, const char* fmt, ...); - -// defined in common/arena.h -typedef struct TB_Arena TB_Arena; - -// 0 for default -TB_API void tb_arena_create(TB_Arena* restrict arena, size_t chunk_size); -TB_API void tb_arena_destroy(TB_Arena* restrict arena); -TB_API bool tb_arena_is_empty(TB_Arena* restrict arena); -TB_API void tb_arena_clear(TB_Arena* restrict arena); - -//////////////////////////////// -// Module management -//////////////////////////////// -// Creates a module with the correct target and settings -TB_API TB_Module* tb_module_create(TB_Arch arch, TB_System sys, const TB_FeatureSet* features, bool is_jit); - -// Creates a module but defaults on the architecture and system based on the host machine -TB_API TB_Module* tb_module_create_for_host(const TB_FeatureSet* features, bool is_jit); - -// Frees all resources for the TB_Module and it's functions, globals and -// compiled code. -TB_API void tb_module_destroy(TB_Module* m); - -// When targetting windows & thread local storage, you'll need to bind a tls index -// which is usually just a global that the runtime support has initialized, if you -// dont and the tls_index is used, it'll crash -TB_API void tb_module_set_tls_index(TB_Module* m, ptrdiff_t len, const char* name); - -TB_API TB_ModuleSectionHandle tb_module_create_section(TB_Module* m, ptrdiff_t len, const char* name, TB_ModuleSectionFlags flags, TB_ComdatType comdat); - -typedef struct { - TB_ThreadInfo* info; - size_t i; -} TB_SymbolIter; - -// Lovely iterator for all the symbols... it's probably not "fast" -TB_SymbolIter tb_symbol_iter(TB_Module* mod); -TB_Symbol* tb_symbol_iter_next(TB_SymbolIter* iter); - -//////////////////////////////// -// Compiled code introspection -//////////////////////////////// -enum { TB_ASSEMBLY_CHUNK_CAP = 4*1024 - sizeof(size_t[2]) }; - -typedef struct TB_Assembly TB_Assembly; -struct TB_Assembly { - TB_Assembly* next; - - // nice chunk of text here - size_t length; - char data[]; -}; - -// this is where the machine code and other relevant pieces go. -typedef struct TB_FunctionOutput TB_FunctionOutput; - -TB_API void tb_output_print_asm(TB_FunctionOutput* out, FILE* fp); - -TB_API uint8_t* tb_output_get_code(TB_FunctionOutput* out, size_t* out_length); - -// returns NULL if there's no line info -TB_API TB_Location* tb_output_get_locations(TB_FunctionOutput* out, size_t* out_count); - -// returns NULL if no assembly was generated -TB_API TB_Assembly* tb_output_get_asm(TB_FunctionOutput* out); - -// this is relative to the start of the function (the start of the prologue) -TB_API TB_Safepoint* tb_safepoint_get(TB_Function* f, uint32_t relative_ip); - -//////////////////////////////// -// JIT compilation -//////////////////////////////// -typedef struct TB_JIT TB_JIT; -typedef struct TB_CPUContext TB_CPUContext; - -// passing 0 to jit_heap_capacity will default to 4MiB -TB_API TB_JIT* tb_jit_begin(TB_Module* m, size_t jit_heap_capacity); -TB_API void* tb_jit_place_function(TB_JIT* jit, TB_Function* f); -TB_API void* tb_jit_place_global(TB_JIT* jit, TB_Global* g); -TB_API void tb_jit_dump_heap(TB_JIT* jit); -TB_API void tb_jit_end(TB_JIT* jit); - -typedef struct { - TB_Symbol* base; - uint32_t offset; -} TB_ResolvedAddr; - -typedef struct { - TB_Function* f; - TB_Location* loc; - uint32_t start, end; -} TB_ResolvedLine; - -TB_API TB_ResolvedAddr tb_jit_addr2sym(TB_JIT* jit, void* ptr); -TB_API TB_ResolvedLine tb_jit_addr2line(TB_JIT* jit, void* ptr); -TB_API void* tb_jit_get_code_ptr(TB_Function* f); - -typedef enum { - // just keeps running - TB_DBG_NONE, - // stops after one instruction - TB_DBG_INST, - // stops once the line changes - TB_DBG_LINE, -} TB_DbgStep; - -// Debugger stuff -// creates a new context we can run JIT code in, you don't -// technically need this but it's a nice helper for writing -// JITs especially when it comes to breakpoints (and eventually -// safepoints) -TB_API TB_CPUContext* tb_jit_thread_create(void* entry, void* arg); -// runs until TB_DbgStep condition is met -TB_API bool tb_jit_thread_resume(TB_JIT* jit, TB_CPUContext* cpu, TB_DbgStep step); -TB_API void* tb_jit_thread_pc(TB_CPUContext* cpu); -TB_API void tb_jit_breakpoint(TB_JIT* jit, void* addr); -TB_API void tb_jit_thread_dump_stack(TB_JIT* jit, TB_CPUContext* cpu); - -//////////////////////////////// -// Disassembler -//////////////////////////////// -TB_API ptrdiff_t tb_print_disassembly_inst(TB_Arch arch, size_t length, const void* ptr); - -//////////////////////////////// -// Exporter -//////////////////////////////// -// Export buffers are generated in chunks because it's easier, usually the -// chunks are "massive" (representing some connected piece of the buffer) -// but they don't have to be. -typedef struct TB_ExportChunk TB_ExportChunk; -struct TB_ExportChunk { - TB_ExportChunk* next; - size_t pos, size; - uint8_t data[]; -}; - -typedef struct { - size_t total; - TB_ExportChunk *head, *tail; -} TB_ExportBuffer; - -TB_API TB_ExportBuffer tb_module_object_export(TB_Module* m, TB_DebugFormat debug_fmt); -TB_API bool tb_export_buffer_to_file(TB_ExportBuffer buffer, const char* path); -TB_API void tb_export_buffer_free(TB_ExportBuffer buffer); - -//////////////////////////////// -// Linker exporter -//////////////////////////////// -// This is used to export shared objects or executables -typedef struct TB_Linker TB_Linker; -typedef struct TB_LinkerSection TB_LinkerSection; -typedef struct TB_LinkerSectionPiece TB_LinkerSectionPiece; - -typedef struct { - enum { - TB_LINKER_MSG_NULL, - - // pragma comment(lib, "blah") - TB_LINKER_MSG_IMPORT, - } tag; - union { - // pragma lib request - TB_Slice import_path; - }; -} TB_LinkerMsg; - -TB_API TB_ExecutableType tb_system_executable_format(TB_System s); - -TB_API TB_Linker* tb_linker_create(TB_ExecutableType type, TB_Arch arch); -TB_API TB_ExportBuffer tb_linker_export(TB_Linker* l); -TB_API void tb_linker_destroy(TB_Linker* l); - -TB_API bool tb_linker_get_msg(TB_Linker* l, TB_LinkerMsg* msg); - -// windows only -TB_API void tb_linker_set_subsystem(TB_Linker* l, TB_WindowsSubsystem subsystem); - -TB_API void tb_linker_set_entrypoint(TB_Linker* l, const char* name); - -// Links compiled module into output -TB_API void tb_linker_append_module(TB_Linker* l, TB_Module* m); - -// Adds object file to output -TB_API void tb_linker_append_object(TB_Linker* l, TB_Slice obj_name, TB_Slice content); - -// Adds static library to output -// this can include imports (wrappers for DLL symbols) along with -// normal sections. -TB_API void tb_linker_append_library(TB_Linker* l, TB_Slice ar_name, TB_Slice content); - -//////////////////////////////// -// Symbols -//////////////////////////////// -TB_API TB_Global* tb_extern_transmute(TB_External* e, TB_DebugType* dbg_type, TB_Linkage linkage); -TB_API TB_External* tb_extern_create(TB_Module* m, ptrdiff_t len, const char* name, TB_ExternalType type); - -TB_API TB_SourceFile* tb_get_source_file(TB_Module* m, const char* path); - -// Called once you're done with TB operations on a thread (or i guess when it's -// about to be killed :p), not calling it can only result in leaks on that thread -// and calling it too early will result in TB potentially reallocating it but there's -// should be no crashes from this, just potential slowdown or higher than expected memory -// usage. -TB_API void tb_free_thread_resources(void); - -//////////////////////////////// -// Function Prototypes -//////////////////////////////// -typedef struct TB_PrototypeParam { - TB_DataType dt; - TB_DebugType* debug_type; - - // does not apply for returns - const char* name; -} TB_PrototypeParam; - -struct TB_FunctionPrototype { - // header - TB_CallingConv call_conv; - uint16_t return_count, param_count; - bool has_varargs; - - // params are directly followed by returns - TB_PrototypeParam params[]; -}; -#define TB_PROTOTYPE_RETURNS(p) ((p)->params + (p)->param_count) - -// creates a function prototype used to define a function's parameters and returns. -// -// function prototypes do not get freed individually and last for the entire run -// of the backend, they can also be reused for multiple functions which have -// matching signatures. -TB_API TB_FunctionPrototype* tb_prototype_create(TB_Module* m, TB_CallingConv cc, size_t param_count, const TB_PrototypeParam* params, size_t return_count, const TB_PrototypeParam* returns, bool has_varargs); - -// same as tb_function_set_prototype except it will handle lowering from types like the TB_DebugType -// into the correct ABI and exposing sane looking nodes to the parameters. -// -// returns the parameters -TB_API TB_Node** tb_function_set_prototype_from_dbg(TB_Function* f, TB_ModuleSectionHandle section, TB_DebugType* dbg, TB_Arena* arena, size_t* out_param_count); -TB_API TB_FunctionPrototype* tb_prototype_from_dbg(TB_Module* m, TB_DebugType* dbg); - -// used for ABI parameter passing -typedef enum { - // needs a direct value - TB_PASSING_DIRECT, - - // needs an address to the value - TB_PASSING_INDIRECT, - - // doesn't use this parameter - TB_PASSING_IGNORE, -} TB_PassingRule; - -TB_API TB_PassingRule tb_get_passing_rule_from_dbg(TB_Module* mod, TB_DebugType* param_type, bool is_return); - -//////////////////////////////// -// Globals -//////////////////////////////// -TB_API TB_Global* tb_global_create(TB_Module* m, ptrdiff_t len, const char* name, TB_DebugType* dbg_type, TB_Linkage linkage); - -// allocate space for the global -TB_API void tb_global_set_storage(TB_Module* m, TB_ModuleSectionHandle section, TB_Global* global, size_t size, size_t align, size_t max_objects); - -// returns a buffer which the user can fill to then have represented in the initializer -TB_API void* tb_global_add_region(TB_Module* m, TB_Global* global, size_t offset, size_t size); - -// places a relocation for a global at offset, the size of the relocation -// depends on the pointer size -TB_API void tb_global_add_symbol_reloc(TB_Module* m, TB_Global* global, size_t offset, const TB_Symbol* symbol); - -TB_API TB_ModuleSectionHandle tb_module_get_text(TB_Module* m); -TB_API TB_ModuleSectionHandle tb_module_get_rdata(TB_Module* m); -TB_API TB_ModuleSectionHandle tb_module_get_data(TB_Module* m); -TB_API TB_ModuleSectionHandle tb_module_get_tls(TB_Module* m); - -//////////////////////////////// -// Function Attributes -//////////////////////////////// -// These are parts of a function that describe metadata for instructions -TB_API void tb_function_attrib_variable(TB_Function* f, TB_Node* n, TB_Node* parent, ptrdiff_t len, const char* name, TB_DebugType* type); -TB_API void tb_function_attrib_scope(TB_Function* f, TB_Node* n, TB_Node* parent); - -//////////////////////////////// -// Debug info Generation -//////////////////////////////// -TB_API TB_DebugType* tb_debug_get_void(TB_Module* m); -TB_API TB_DebugType* tb_debug_get_bool(TB_Module* m); -TB_API TB_DebugType* tb_debug_get_integer(TB_Module* m, bool is_signed, int bits); -TB_API TB_DebugType* tb_debug_get_float(TB_Module* m, TB_FloatFormat fmt); -TB_API TB_DebugType* tb_debug_create_ptr(TB_Module* m, TB_DebugType* base); -TB_API TB_DebugType* tb_debug_create_array(TB_Module* m, TB_DebugType* base, size_t count); -TB_API TB_DebugType* tb_debug_create_alias(TB_Module* m, TB_DebugType* base, ptrdiff_t len, const char* tag); -TB_API TB_DebugType* tb_debug_create_struct(TB_Module* m, ptrdiff_t len, const char* tag); -TB_API TB_DebugType* tb_debug_create_union(TB_Module* m, ptrdiff_t len, const char* tag); -TB_API TB_DebugType* tb_debug_create_field(TB_Module* m, TB_DebugType* type, ptrdiff_t len, const char* name, TB_CharUnits offset); - -// returns the array you need to fill with fields -TB_API TB_DebugType** tb_debug_record_begin(TB_Module* m, TB_DebugType* type, size_t count); -TB_API void tb_debug_record_end(TB_DebugType* type, TB_CharUnits size, TB_CharUnits align); - -TB_API TB_DebugType* tb_debug_create_func(TB_Module* m, TB_CallingConv cc, size_t param_count, size_t return_count, bool has_varargs); - -TB_API TB_DebugType* tb_debug_field_type(TB_DebugType* type); - -TB_API size_t tb_debug_func_return_count(TB_DebugType* type); -TB_API size_t tb_debug_func_param_count(TB_DebugType* type); - -// you'll need to fill these if you make a function -TB_API TB_DebugType** tb_debug_func_params(TB_DebugType* type); -TB_API TB_DebugType** tb_debug_func_returns(TB_DebugType* type); - -//////////////////////////////// -// Symbols -//////////////////////////////// -// returns NULL if the tag doesn't match -TB_API TB_Function* tb_symbol_as_function(TB_Symbol* s); -TB_API TB_External* tb_symbol_as_external(TB_Symbol* s); -TB_API TB_Global* tb_symbol_as_global(TB_Symbol* s); - -//////////////////////////////// -// Function IR Generation -//////////////////////////////// -TB_API void tb_get_data_type_size(TB_Module* mod, TB_DataType dt, size_t* size, size_t* align); - -// the user_data is expected to be a valid FILE* -TB_API void tb_default_print_callback(void* user_data, const char* fmt, ...); - -TB_API void tb_inst_location(TB_Function* f, TB_SourceFile* file, int line, int column); - -// this is where the STOP will be -TB_API void tb_inst_set_exit_location(TB_Function* f, TB_SourceFile* file, int line, int column); - -// if section is NULL, default to .text -TB_API TB_Function* tb_function_create(TB_Module* m, ptrdiff_t len, const char* name, TB_Linkage linkage); - -TB_API TB_Arena* tb_function_get_arena(TB_Function* f); - -// if len is -1, it's null terminated -TB_API void tb_symbol_set_name(TB_Symbol* s, ptrdiff_t len, const char* name); - -TB_API void tb_symbol_bind_ptr(TB_Symbol* s, void* ptr); -TB_API const char* tb_symbol_get_name(TB_Symbol* s); - -// if arena is NULL, defaults to module arena which is freed on tb_free_thread_resources -TB_API void tb_function_set_prototype(TB_Function* f, TB_ModuleSectionHandle section, TB_FunctionPrototype* p, TB_Arena* arena); -TB_API TB_FunctionPrototype* tb_function_get_prototype(TB_Function* f); - -TB_API void tb_inst_set_control(TB_Function* f, TB_Node* control); -TB_API TB_Node* tb_inst_get_control(TB_Function* f); - -TB_API TB_Node* tb_inst_region(TB_Function* f); - -// if len is -1, it's null terminated -TB_API void tb_inst_set_region_name(TB_Function* f, TB_Node* n, ptrdiff_t len, const char* name); - -TB_API void tb_inst_unreachable(TB_Function* f); -TB_API void tb_inst_debugbreak(TB_Function* f); -TB_API void tb_inst_trap(TB_Function* f); -TB_API TB_Node* tb_inst_poison(TB_Function* f, TB_DataType dt); - -TB_API TB_Node* tb_inst_param(TB_Function* f, int param_id); - -TB_API TB_Node* tb_inst_fpxt(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_sxt(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_zxt(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_trunc(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_int2ptr(TB_Function* f, TB_Node* src); -TB_API TB_Node* tb_inst_ptr2int(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_int2float(TB_Function* f, TB_Node* src, TB_DataType dt, bool is_signed); -TB_API TB_Node* tb_inst_float2int(TB_Function* f, TB_Node* src, TB_DataType dt, bool is_signed); -TB_API TB_Node* tb_inst_bitcast(TB_Function* f, TB_Node* src, TB_DataType dt); - -TB_API TB_Node* tb_inst_local(TB_Function* f, TB_CharUnits size, TB_CharUnits align); - -TB_API TB_Node* tb_inst_load(TB_Function* f, TB_DataType dt, TB_Node* addr, TB_CharUnits align, bool is_volatile); -TB_API void tb_inst_store(TB_Function* f, TB_DataType dt, TB_Node* addr, TB_Node* val, TB_CharUnits align, bool is_volatile); - -TB_API void tb_inst_safepoint_poll(TB_Function* f, TB_Node* addr, int input_count, TB_Node** inputs); - -TB_API TB_Node* tb_inst_bool(TB_Function* f, bool imm); -TB_API TB_Node* tb_inst_sint(TB_Function* f, TB_DataType dt, int64_t imm); -TB_API TB_Node* tb_inst_uint(TB_Function* f, TB_DataType dt, uint64_t imm); -TB_API TB_Node* tb_inst_float32(TB_Function* f, float imm); -TB_API TB_Node* tb_inst_float64(TB_Function* f, double imm); -TB_API TB_Node* tb_inst_cstring(TB_Function* f, const char* str); -TB_API TB_Node* tb_inst_string(TB_Function* f, size_t len, const char* str); - -// write 'val' over 'count' bytes on 'dst' -TB_API void tb_inst_memset(TB_Function* f, TB_Node* dst, TB_Node* val, TB_Node* count, TB_CharUnits align); - -// zero 'count' bytes on 'dst' -TB_API void tb_inst_memzero(TB_Function* f, TB_Node* dst, TB_Node* count, TB_CharUnits align); - -// performs a copy of 'count' elements from one memory location to another -// both locations cannot overlap. -TB_API void tb_inst_memcpy(TB_Function* f, TB_Node* dst, TB_Node* src, TB_Node* count, TB_CharUnits align); - -// result = base + (index * stride) -TB_API TB_Node* tb_inst_array_access(TB_Function* f, TB_Node* base, TB_Node* index, int64_t stride); - -// result = base + offset -// where base is a pointer -TB_API TB_Node* tb_inst_member_access(TB_Function* f, TB_Node* base, int64_t offset); - -TB_API TB_Node* tb_inst_get_symbol_address(TB_Function* f, TB_Symbol* target); - -// Performs a conditional select between two values, if the operation is -// performed wide then the cond is expected to be the same type as a and b where -// the condition is resolved as true if the MSB (per component) is 1. -// -// result = cond ? a : b -// a, b must match in type -TB_API TB_Node* tb_inst_select(TB_Function* f, TB_Node* cond, TB_Node* a, TB_Node* b); - -// Integer arithmatic -TB_API TB_Node* tb_inst_add(TB_Function* f, TB_Node* a, TB_Node* b, TB_ArithmeticBehavior arith_behavior); -TB_API TB_Node* tb_inst_sub(TB_Function* f, TB_Node* a, TB_Node* b, TB_ArithmeticBehavior arith_behavior); -TB_API TB_Node* tb_inst_mul(TB_Function* f, TB_Node* a, TB_Node* b, TB_ArithmeticBehavior arith_behavior); -TB_API TB_Node* tb_inst_div(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); -TB_API TB_Node* tb_inst_mod(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); - -// Bitmagic operations -TB_API TB_Node* tb_inst_bswap(TB_Function* f, TB_Node* n); -TB_API TB_Node* tb_inst_clz(TB_Function* f, TB_Node* n); -TB_API TB_Node* tb_inst_ctz(TB_Function* f, TB_Node* n); -TB_API TB_Node* tb_inst_popcount(TB_Function* f, TB_Node* n); - -// Bitwise operations -TB_API TB_Node* tb_inst_not(TB_Function* f, TB_Node* n); -TB_API TB_Node* tb_inst_neg(TB_Function* f, TB_Node* n); -TB_API TB_Node* tb_inst_and(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_or(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_xor(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_sar(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_shl(TB_Function* f, TB_Node* a, TB_Node* b, TB_ArithmeticBehavior arith_behavior); -TB_API TB_Node* tb_inst_shr(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_rol(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_ror(TB_Function* f, TB_Node* a, TB_Node* b); - -// Atomics -// By default you can use TB_MEM_ORDER_SEQ_CST for the memory order to get -// correct but possibly slower results on certain platforms (those with relaxed -// memory models). - -// Must be aligned to the natural alignment of dt -TB_API TB_Node* tb_inst_atomic_load(TB_Function* f, TB_Node* addr, TB_DataType dt, TB_MemoryOrder order); - -// All atomic operations here return the old value and the operations are -// performed in the same data type as 'src' with alignment of 'addr' being -// the natural alignment of 'src' -TB_API TB_Node* tb_inst_atomic_xchg(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); -TB_API TB_Node* tb_inst_atomic_add(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); -TB_API TB_Node* tb_inst_atomic_sub(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); -TB_API TB_Node* tb_inst_atomic_and(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); -TB_API TB_Node* tb_inst_atomic_xor(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); -TB_API TB_Node* tb_inst_atomic_or(TB_Function* f, TB_Node* addr, TB_Node* src, TB_MemoryOrder order); - -// returns old_value from *addr -TB_API TB_Node* tb_inst_atomic_cmpxchg(TB_Function* f, TB_Node* addr, TB_Node* expected, TB_Node* desired, TB_MemoryOrder succ, TB_MemoryOrder fail); - -// Float math -TB_API TB_Node* tb_inst_fadd(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_fsub(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_fmul(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_fdiv(TB_Function* f, TB_Node* a, TB_Node* b); - -// Comparisons -TB_API TB_Node* tb_inst_cmp_eq(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_cmp_ne(TB_Function* f, TB_Node* a, TB_Node* b); - -TB_API TB_Node* tb_inst_cmp_ilt(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); -TB_API TB_Node* tb_inst_cmp_ile(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); -TB_API TB_Node* tb_inst_cmp_igt(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); -TB_API TB_Node* tb_inst_cmp_ige(TB_Function* f, TB_Node* a, TB_Node* b, bool signedness); - -TB_API TB_Node* tb_inst_cmp_flt(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_cmp_fle(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_cmp_fgt(TB_Function* f, TB_Node* a, TB_Node* b); -TB_API TB_Node* tb_inst_cmp_fge(TB_Function* f, TB_Node* a, TB_Node* b); - -// General intrinsics -TB_API TB_Node* tb_inst_va_start(TB_Function* f, TB_Node* a); -TB_API TB_Node* tb_inst_cycle_counter(TB_Function* f); -TB_API TB_Node* tb_inst_prefetch(TB_Function* f, TB_Node* addr, int level); - -// x86 Intrinsics -TB_API TB_Node* tb_inst_x86_ldmxcsr(TB_Function* f, TB_Node* a); -TB_API TB_Node* tb_inst_x86_stmxcsr(TB_Function* f); -TB_API TB_Node* tb_inst_x86_sqrt(TB_Function* f, TB_Node* a); -TB_API TB_Node* tb_inst_x86_rsqrt(TB_Function* f, TB_Node* a); - -// Control flow -TB_API TB_Node* tb_inst_syscall(TB_Function* f, TB_DataType dt, TB_Node* syscall_num, size_t param_count, TB_Node** params); -TB_API TB_MultiOutput tb_inst_call(TB_Function* f, TB_FunctionPrototype* proto, TB_Node* target, size_t param_count, TB_Node** params); -TB_API void tb_inst_tailcall(TB_Function* f, TB_FunctionPrototype* proto, TB_Node* target, size_t param_count, TB_Node** params); - -TB_API TB_Node* tb_inst_safepoint(TB_Function* f, TB_Node* poke_site, size_t param_count, TB_Node** params); - -TB_API TB_Node* tb_inst_incomplete_phi(TB_Function* f, TB_DataType dt, TB_Node* region, size_t preds); -TB_API bool tb_inst_add_phi_operand(TB_Function* f, TB_Node* phi, TB_Node* region, TB_Node* val); - -TB_API TB_Node* tb_inst_phi2(TB_Function* f, TB_Node* region, TB_Node* a, TB_Node* b); -TB_API void tb_inst_goto(TB_Function* f, TB_Node* target); -TB_API void tb_inst_if(TB_Function* f, TB_Node* cond, TB_Node* true_case, TB_Node* false_case); -TB_API void tb_inst_branch(TB_Function* f, TB_DataType dt, TB_Node* key, TB_Node* default_case, size_t entry_count, const TB_SwitchEntry* keys); - -TB_API void tb_inst_ret(TB_Function* f, size_t count, TB_Node** values); - -//////////////////////////////// -// Passes -//////////////////////////////// -typedef enum { - // allowed to remove PHIs nodes, this is - // helpful because the default IR building - // will produce tons of useless memory PHIs. - TB_PEEPHOLE_PHI = 1, - - // it's allowed to fold memory operations (store or load elimination) - TB_PEEPHOLE_MEMORY = 2, - - // just do every reduction rule i can provide you - TB_PEEPHOLE_ALL = 7, -} TB_PeepholeFlags; - -// Function analysis, optimizations, and codegen are all part of this -typedef struct TB_Passes TB_Passes; - -// the arena is used to allocate the nodes while passes are being done. -TB_API TB_Passes* tb_pass_enter(TB_Function* f, TB_Arena* arena); -TB_API void tb_pass_exit(TB_Passes* opt); - -// transformation passes: -// peephole: 99% of the optimizer, i'm sea of nodes pilled so i -// break down most optimizations into local rewrites, it's -// incremental and recommended to run after any non-peephole -// pass. -// -// mem2reg: lowers TB_LOCALs into SoN values, this makes more -// data flow analysis possible on the code and allows to codegen -// to place variables into registers. -// -// SROA: splits LOCALs into multiple to allow for more dataflow -// analysis later on. -TB_API void tb_pass_peephole(TB_Passes* opt, TB_PeepholeFlags flags); -TB_API void tb_pass_sroa(TB_Passes* opt); -TB_API bool tb_pass_mem2reg(TB_Passes* opt); -TB_API bool tb_pass_loop(TB_Passes* opt); - -// this just runs the optimizer in the default configuration -TB_API void tb_pass_optimize(TB_Passes* opt); - -// analysis -// print: prints IR in a flattened text form. -TB_API bool tb_pass_print(TB_Passes* opt); -// print-dot: prints IR as DOT -TB_API void tb_pass_print_dot(TB_Passes* opt, TB_PrintCallback callback, void* user_data); - -// codegen -TB_API TB_FunctionOutput* tb_pass_codegen(TB_Passes* opt, bool emit_asm); - -TB_API void tb_pass_kill_node(TB_Passes* opt, TB_Node* n); -TB_API void tb_pass_mark(TB_Passes* opt, TB_Node* n); -TB_API void tb_pass_mark_users(TB_Passes* opt, TB_Node* n); - -//////////////////////////////// -// IR access -//////////////////////////////// -TB_API const char* tb_node_get_name(TB_Node* n); - -TB_API TB_Node* tb_get_parent_region(TB_Node* n); -TB_API bool tb_node_is_constant_non_zero(TB_Node* n); -TB_API bool tb_node_is_constant_zero(TB_Node* n); - -#endif /* TB_CORE_H */ diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib deleted file mode 100644 index 510569b0e..000000000 Binary files a/src/tilde/tb.lib and /dev/null differ diff --git a/src/tilde/tb_arena.h b/src/tilde/tb_arena.h deleted file mode 100644 index 67ec0e181..000000000 --- a/src/tilde/tb_arena.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include -#include - -#ifndef TB_API -# ifdef __cplusplus -# define TB_EXTERN extern "C" -# else -# define TB_EXTERN -# endif -# ifdef TB_DLL -# ifdef TB_IMPORT_DLL -# define TB_API TB_EXTERN __declspec(dllimport) -# else -# define TB_API TB_EXTERN __declspec(dllexport) -# endif -# else -# define TB_API TB_EXTERN -# endif -#endif - -enum { - TB_ARENA_SMALL_CHUNK_SIZE = 4 * 1024, - TB_ARENA_MEDIUM_CHUNK_SIZE = 512 * 1024, - TB_ARENA_LARGE_CHUNK_SIZE = 16 * 1024 * 1024, - - TB_ARENA_ALIGNMENT = 16, -}; - -typedef struct TB_ArenaChunk TB_ArenaChunk; -struct TB_ArenaChunk { - TB_ArenaChunk* next; - size_t pad; - char data[]; -}; - -typedef struct TB_Arena { - size_t chunk_size; - TB_ArenaChunk* base; - TB_ArenaChunk* top; - - // top of the allocation space - char* watermark; - char* high_point; // &top->data[chunk_size] -} TB_Arena; - -typedef struct TB_ArenaSavepoint { - TB_ArenaChunk* top; - char* watermark; -} TB_ArenaSavepoint; - -#define TB_ARENA_FOR(it, arena) for (TB_ArenaChunk* it = (arena)->base; it != NULL; it = it->next) - -#define TB_ARENA_ALLOC(arena, T) tb_arena_alloc(arena, sizeof(T)) -#define TB_ARENA_ARR_ALLOC(arena, count, T) tb_arena_alloc(arena, (count) * sizeof(T)) - -TB_API void tb_arena_create(TB_Arena* restrict arena, size_t chunk_size); -TB_API void tb_arena_destroy(TB_Arena* restrict arena); - -TB_API void* tb_arena_unaligned_alloc(TB_Arena* restrict arena, size_t size); -TB_API void* tb_arena_alloc(TB_Arena* restrict arena, size_t size); - -// return false on failure -TB_API bool tb_arena_free(TB_Arena* restrict arena, void* ptr, size_t size); -TB_API void tb_arena_pop(TB_Arena* restrict arena, void* ptr, size_t size); - -// in case you wanna mix unaligned and aligned arenas -TB_API void tb_arena_realign(TB_Arena* restrict arena); - -TB_API bool tb_arena_is_empty(TB_Arena* arena); - -TB_API size_t tb_arena_current_size(TB_Arena* arena); - -// savepoints -TB_API TB_ArenaSavepoint tb_arena_save(TB_Arena* arena); -TB_API void tb_arena_restore(TB_Arena* arena, TB_ArenaSavepoint sp); - -// resets to only having one chunk -TB_API void tb_arena_clear(TB_Arena* arena); diff --git a/src/tilde/tb_coff.h b/src/tilde/tb_coff.h deleted file mode 100644 index ddedd6ffe..000000000 --- a/src/tilde/tb_coff.h +++ /dev/null @@ -1,334 +0,0 @@ -// PE/COFF is the executable/object format used by Microsoft. -#ifndef TB_COFF_H -#define TB_COFF_H - -#include "tb_formats.h" - -#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 - -#define IMAGE_SYM_CLASS_EXTERNAL 0x0002 -#define IMAGE_SYM_CLASS_STATIC 0x0003 -#define IMAGE_SYM_CLASS_LABEL 0x0006 -#define IMAGE_SYM_CLASS_FILE 0x0067 -#define IMAGE_SYM_CLASS_SECTION 0x0068 -#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069 - -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 - -#define IMAGE_REL_AMD64_ADDR64 0x0001 -#define IMAGE_REL_AMD64_ADDR32 0x0002 -#define IMAGE_REL_AMD64_ADDR32NB 0x0003 -#define IMAGE_REL_AMD64_REL32 0x0004 -#define IMAGE_REL_AMD64_REL32_1 0x0005 -#define IMAGE_REL_AMD64_REL32_2 0x0006 -#define IMAGE_REL_AMD64_REL32_3 0x0007 -#define IMAGE_REL_AMD64_REL32_4 0x0008 -#define IMAGE_REL_AMD64_REL32_5 0x0009 -#define IMAGE_REL_AMD64_SECTION 0x000A -#define IMAGE_REL_AMD64_SECREL 0x000B - -#define IMAGE_SCN_LNK_REMOVE 0x00000800 -#define IMAGE_SCN_LNK_COMDAT 0x00001000 -#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define IMAGE_SCN_MEM_READ 0x40000000 -#define IMAGE_SCN_MEM_WRITE 0x80000000 - -#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */ -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */ -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */ - -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory -#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory -#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory -#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory -#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory -#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table -#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory -#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data -#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP -#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory -#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory -#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers -#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table -#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors -#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor - -#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 -#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 -#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 - -typedef enum { - TB_COFF_SECTION_NO_PAD = 0x00000008, - TB_COFF_SECTION_CODE = 0x00000020, - TB_COFF_SECTION_INIT = 0x00000040, - TB_COFF_SECTION_UNINIT = 0x00000080, - TB_COFF_SECTION_OTHER = 0x00000100, - TB_COFF_SECTION_INFO = 0x00000200, - TB_COFF_SECTION_REMOVE = 0x00000800, - TB_COFF_SECTION_COMDAT = 0x00001000, - - // this is actually a 4bit field - TB_COFF_SECTION_ALIGN = 0x00F00000, - - // if we have more than 65535 relocations we do this - TB_COFF_SECTION_RELOC_OVR = 0x00F00000, - - // memory flags - TB_COFF_SECTION_DISCARDABLE = 0x02000000, - TB_COFF_SECTION_NOT_CACHED = 0x04000000, - TB_COFF_SECTION_NOT_PAGED = 0x08000000, - TB_COFF_SECTION_SHARED = 0x10000000, - TB_COFF_SECTION_EXECUTE = 0x20000000, - TB_COFF_SECTION_READ = 0x40000000, - TB_COFF_SECTION_WRITE = 0x80000000, -} TB_COFF_SectionFlags; - -typedef struct TB_COFF_Parser { - // inputs - TB_Slice name, file; - - // results - size_t section_count; - size_t symbol_table, symbol_count; - - // private - TB_Slice string_table; -} TB_COFF_Parser; - -// fills the parser with results from the COFF header -bool tb_coff_parse_init(TB_COFF_Parser* restrict parser); -bool tb_coff_parse_section(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSection* out_sec); - -// how many symbols does this one symbol take up (basically 1 + aux symbols). -// returns 0 if error. -size_t tb_coff_parse_symbol(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSymbol* restrict out_sym); - -#endif // TB_COFF_H - -#ifdef TB_COFF_IMPL -#include - -#pragma pack(push, 2) -typedef struct COFF_SectionHeader { - char name[8]; - union { - uint32_t physical_address; - uint32_t virtual_size; - } misc; - uint32_t virtual_address; - uint32_t raw_data_size; - uint32_t raw_data_pos; - uint32_t pointer_to_reloc; - uint32_t pointer_to_lineno; - uint16_t num_reloc; - uint16_t num_lineno; - uint32_t characteristics; -} COFF_SectionHeader; - -typedef struct COFF_FileHeader { - uint16_t machine; - uint16_t section_count; - uint32_t timestamp; - uint32_t symbol_table; - uint32_t symbol_count; - uint16_t optional_header_size; - uint16_t flags; -} COFF_FileHeader; - -typedef struct COFF_Symbol { - union { - uint8_t short_name[8]; - uint32_t long_name[2]; - }; - uint32_t value; - int16_t section_number; - uint16_t type; - uint8_t storage_class; - uint8_t aux_symbols_count; -} COFF_Symbol; - -typedef struct COFF_ImageReloc { - union { - uint32_t VirtualAddress; - uint32_t RelocCount; - }; - uint32_t SymbolTableIndex; - uint16_t Type; -} COFF_ImageReloc; -#pragma pack(pop) - -// sanity checks -static_assert(sizeof(COFF_SectionHeader) == 40, "COFF Section header size != 40 bytes"); -static_assert(sizeof(COFF_ImageReloc) == 10, "COFF Image Relocation size != 10 bytes"); -static_assert(sizeof(COFF_FileHeader) == 20, "COFF File header size != 20 bytes"); -static_assert(sizeof(COFF_Symbol) == 18, "COFF Symbol size != 18 bytes"); - -bool tb_coff_parse_init(TB_COFF_Parser* restrict parser) { - TB_Slice file = parser->file; - - if (file.length < sizeof(COFF_FileHeader)) return false; - COFF_FileHeader* header = (COFF_FileHeader*) &parser->file.data[0]; - - // locate string table (it spans until the end of the file) - size_t string_table_pos = header->symbol_table + (header->symbol_count * sizeof(COFF_Symbol)); - if (file.length < string_table_pos) return false; - - parser->symbol_count = header->symbol_count; - parser->symbol_table = header->symbol_table; - parser->section_count = header->section_count; - parser->string_table = (TB_Slice){ - .length = file.length - string_table_pos, - .data = &file.data[string_table_pos] - }; - - return true; -} - -static long long tb__parse_decimal_int(size_t n, const char* str) { - const char* end = &str[n]; - - int result = 0; - while (str != end) { - if (*str < '0' || *str > '9') break; - - result *= 10; - result += *str - '0'; - str++; - } - - return result; -} - -bool tb_coff_parse_section(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSection* restrict out_sec) { - TB_Slice file = parser->file; - size_t section_offset = sizeof(COFF_FileHeader) + (i * sizeof(COFF_SectionHeader)); - - if (file.length < section_offset + sizeof(COFF_SectionHeader)) { - return false; - } - - COFF_SectionHeader* sec = (COFF_SectionHeader*) &file.data[section_offset]; - *out_sec = (TB_ObjectSection) { .flags = sec->characteristics }; - - // Parse string table name stuff - if (sec->name[0] == '/') { - // string table access - int offset = tb__parse_decimal_int(7, &sec->name[1]); - if (file.length > offset) { - return false; - } - - const uint8_t* data = &parser->string_table.data[offset]; - out_sec->name = (TB_Slice){ strlen((const char*) data), data }; - } else { - // normal inplace string - size_t len = strlen(sec->name); - out_sec->name = (TB_Slice){ len, (uint8_t*) sec->name }; - } - - // Parse relocations - if (sec->num_reloc > 0) { - out_sec->relocation_count = sec->num_reloc; - COFF_ImageReloc* src_relocs = (COFF_ImageReloc*) &file.data[sec->pointer_to_reloc]; - - TB_ObjectReloc* dst_relocs = tb_platform_heap_alloc(sec->num_reloc * sizeof(TB_ObjectReloc)); - FOREACH_N(j, 0, sec->num_reloc) { - dst_relocs[j] = (TB_ObjectReloc){ 0 }; - switch (src_relocs[j].Type) { - case IMAGE_REL_AMD64_ADDR32NB: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR32NB; break; - case IMAGE_REL_AMD64_ADDR32: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR32; break; - case IMAGE_REL_AMD64_ADDR64: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR64; break; - case IMAGE_REL_AMD64_SECREL: dst_relocs[j].type = TB_OBJECT_RELOC_SECREL; break; - case IMAGE_REL_AMD64_SECTION: dst_relocs[j].type = TB_OBJECT_RELOC_SECTION; break; - - case IMAGE_REL_AMD64_REL32: - case IMAGE_REL_AMD64_REL32_1: - case IMAGE_REL_AMD64_REL32_2: - case IMAGE_REL_AMD64_REL32_3: - case IMAGE_REL_AMD64_REL32_4: - case IMAGE_REL_AMD64_REL32_5: - dst_relocs[j].type = TB_OBJECT_RELOC_REL32; - break; - - default: tb_todo(); - } - - if (src_relocs[j].Type >= IMAGE_REL_AMD64_REL32 && src_relocs[j].Type <= IMAGE_REL_AMD64_REL32_5) { - dst_relocs[j].addend = 4 + (src_relocs[j].Type - IMAGE_REL_AMD64_REL32); - } - - dst_relocs[j].symbol_index = src_relocs[j].SymbolTableIndex; - dst_relocs[j].virtual_address = src_relocs[j].VirtualAddress; - } - - out_sec->relocations = dst_relocs; - } - - // Parse virtual region - out_sec->virtual_address = sec->virtual_address; - out_sec->virtual_size = sec->misc.virtual_size; - - // Read raw data (if applies) - if (sec->raw_data_size) { - assert(sec->raw_data_pos + sec->raw_data_size < file.length); - out_sec->raw_data = (TB_Slice){ sec->raw_data_size, &file.data[sec->raw_data_pos] }; - } - - return true; -} - -TB_ObjectSymbolType classify_symbol_type(uint16_t st_class) { - switch (st_class) { - case 2: return TB_OBJECT_SYMBOL_EXTERN; - case 3: return TB_OBJECT_SYMBOL_STATIC; - case 6: return TB_OBJECT_SYMBOL_STATIC; - case 0x68: return TB_OBJECT_SYMBOL_SECTION; - case 0x69: return TB_OBJECT_SYMBOL_WEAK_EXTERN; - default: return TB_OBJECT_SYMBOL_UNKNOWN; - } -} - -size_t tb_coff_parse_symbol(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSymbol* restrict out_sym) { - TB_Slice file = parser->file; - size_t symbol_offset = parser->symbol_table + (i * sizeof(COFF_Symbol)); - - if (file.length < symbol_offset + sizeof(COFF_Symbol)) { - return 0; - } - - COFF_Symbol* sym = (COFF_Symbol*) &file.data[symbol_offset]; - *out_sym = (TB_ObjectSymbol) { - .ordinal = i, - .type = classify_symbol_type(sym->storage_class), - .section_num = sym->section_number, - .value = sym->value - }; - - // Parse string table name stuff - if (sym->long_name[0] == 0) { - // string table access (read a cstring) - // TODO(NeGate): bounds check this - const uint8_t* data = &parser->string_table.data[sym->long_name[1]]; - out_sym->name = (TB_Slice){ strlen((const char*) data), data }; - } else { - // normal inplace string - size_t len = 1; - const char* name = (const char*) sym->short_name; - while (len < 8 && name[len] != 0) { - len++; - } - out_sym->name = (TB_Slice){ len, sym->short_name }; - } - - // TODO(NeGate): Process aux symbols - if (sym->aux_symbols_count) { - out_sym->extra = &sym[1]; - - // FOREACH_N(j, 0, sym->aux_symbols_count) {} - } - - return sym->aux_symbols_count + 1; -} - -#endif // TB_COFF_IMPL diff --git a/src/tilde/tb_elf.h b/src/tilde/tb_elf.h deleted file mode 100644 index 5260d7372..000000000 --- a/src/tilde/tb_elf.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef TB_ELF_H -#define TB_ELF_H - -#include - -#define TB_EI_MAG0 0 -#define TB_EI_MAG1 1 -#define TB_EI_MAG2 2 -#define TB_EI_MAG3 3 -#define TB_EI_CLASS 4 /* Class of machine. */ -#define TB_EI_DATA 5 /* Data format. */ -#define TB_EI_VERSION 6 /* ELF format version. */ -#define TB_EI_OSABI 7 /* Operating system / ABI identification */ -#define TB_EI_ABIVERSION 8 /* ABI version */ -#define TB_OLD_EI_BRAND 8 /* Start of architecture identification. */ -#define TB_EI_PAD 9 /* Start of padding (per SVR4 ABI). */ -#define TB_EI_NIDENT 16 /* Size of e_ident array. */ - -/* Values for e_type. */ -#define TB_ET_NONE 0 /* Unknown type. */ -#define TB_ET_REL 1 /* Relocatable. */ -#define TB_ET_EXEC 2 /* Executable. */ -#define TB_ET_DYN 3 /* Shared object. */ -#define TB_ET_CORE 4 /* Core file. */ -#define TB_ET_LOOS 0xfe00 /* First operating system specific. */ -#define TB_ET_HIOS 0xfeff /* Last operating system-specific. */ -#define TB_ET_LOPROC 0xff00 /* First processor-specific. */ -#define TB_ET_HIPROC 0xffff /* Last processor-specific. */ - -/* Values for e_machine. */ -#define TB_EM_NONE 0 /* Unknown machine. */ -#define TB_EM_X86_64 62 /* Advanced Micro Devices x86-64 */ -#define TB_EM_AARCH64 183 /* AArch64 (64-bit ARM) */ - -/* sh_type */ -#define TB_SHT_NULL 0 /* inactive */ -#define TB_SHT_PROGBITS 1 /* program defined information */ -#define TB_SHT_SYMTAB 2 /* symbol table section */ -#define TB_SHT_STRTAB 3 /* string table section */ -#define TB_SHT_RELA 4 /* relocation section with addends */ -#define TB_SHT_NOBITS 8 /* no space section */ - -/* Flags for sh_flags. */ -#define TB_SHF_WRITE 0x1 /* Section contains writable data. */ -#define TB_SHF_ALLOC 0x2 /* Section occupies memory. */ -#define TB_SHF_EXECINSTR 0x4 /* Section contains instructions. */ -#define TB_SHF_MERGE 0x10 /* Section may be merged. */ -#define TB_SHF_STRINGS 0x20 /* Section contains strings. */ -#define TB_SHF_INFO_LINK 0x40 /* sh_info holds section index. */ -#define TB_SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ -#define TB_SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ -#define TB_SHF_GROUP 0x200 /* Member of section group. */ -#define TB_SHF_TLS 0x400 /* Section contains TLS data. */ -#define TB_SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ -#define TB_SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ - -/* Values for p_flags. */ -#define TB_PF_X 0x1 /* Executable. */ -#define TB_PF_W 0x2 /* Writable. */ -#define TB_PF_R 0x4 /* Readable. */ -#define TB_PF_MASKOS 0x0ff00000 /* Operating system-specific. */ -#define TB_PF_MASKPROC 0xf0000000 /* Processor-specific. */ - -/* Values for p_type. */ -#define TB_PT_NULL 0 /* Unused entry. */ -#define TB_PT_LOAD 1 /* Loadable segment. */ -#define TB_PT_DYNAMIC 2 /* Dynamic linking information segment. */ -#define TB_PT_INTERP 3 /* Pathname of interpreter. */ -#define TB_PT_NOTE 4 /* Auxiliary information. */ -#define TB_PT_SHLIB 5 /* Reserved (not used). */ -#define TB_PT_PHDR 6 /* Location of program header itself. */ -#define TB_PT_TLS 7 /* Thread local storage segment */ - -/* Values for relocation */ -typedef enum { - TB_ELF_X86_64_NONE = 0, - TB_ELF_X86_64_64 = 1, - TB_ELF_X86_64_PC32 = 2, - TB_ELF_X86_64_GOT32 = 3, - TB_ELF_X86_64_PLT32 = 4, - TB_ELF_X86_64_GOTPCREL = 9, -} TB_ELF_RelocType; - -// ST_TYPE -#define TB_ELF64_STT_NOTYPE 0 -#define TB_ELF64_STT_OBJECT 1 -#define TB_ELF64_STT_FUNC 2 -#define TB_ELF64_STT_SECTION 3 - -// ST_INFO -#define TB_ELF64_STB_LOCAL 0 -#define TB_ELF64_STB_GLOBAL 1 -#define TB_ELF64_STB_WEAK 2 - -/* Macros for accessing the fields of st_info. */ -#define TB_ELF64_ST_BIND(info) ((info) >> 4) -#define TB_ELF64_ST_TYPE(info) ((info) & 0xf) - -#define TB_ELF64_ST_INFO(b, t) (((b) << 4) | ((t) & 0xF)) - -#define TB_ELF64_R_SYM(i) ((i) >> 32u) -#define TB_ELF64_R_TYPE(i) ((i)&0xffffffffULL) -#define TB_ELF64_R_INFO(s, t) (((uint64_t)(s) << 32ULL) + ((uint64_t)(t) & 0xffffffffULL)) - -// http://web.mit.edu/freebsd/head/sys/sys/elf64.h -// https://cirosantilli.com/elf-hello-world#minimal-elf-file -// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format -typedef struct { - uint8_t ident[16]; - uint16_t type; - uint16_t machine; - uint32_t version; - uint64_t entry; - uint64_t phoff; - uint64_t shoff; - uint32_t flags; - uint16_t ehsize; - uint16_t phentsize; - uint16_t phnum; - uint16_t shentsize; - uint16_t shnum; - uint16_t shstrndx; -} TB_Elf64_Ehdr; - -typedef struct { - uint32_t name; - uint32_t type; - uint64_t flags; - uint64_t addr; - uint64_t offset; - uint64_t size; - uint32_t link; - uint32_t info; - uint64_t addralign; - uint64_t entsize; -} TB_Elf64_Shdr; - -// Segment header for ELF64. -typedef struct { - uint32_t type; // Type of segment - uint32_t flags; // Segment flags - uint64_t offset; // File offset where segment is located, in bytes - uint64_t vaddr; // Virtual address of beginning of segment - uint64_t paddr; // Physical addr of beginning of segment (OS-specific) - uint64_t filesz; // Num. of bytes in file image of segment (may be zero) - uint64_t memsz; // Num. of bytes in mem image of segment (may be zero) - uint64_t align; // Segment alignment constraint -} TB_Elf64_Phdr; - -typedef struct { - uint32_t name; - uint8_t info; - uint8_t other; - uint16_t shndx; - uint64_t value; - uint64_t size; -} TB_Elf64_Sym; - -typedef struct { - uint64_t offset; - uint64_t info; - int64_t addend; -} TB_Elf64_Rela; - -typedef struct { - uint64_t offset; - uint64_t info; -} TB_Elf64_Rel; - -#endif /* TB_ELF_H */ diff --git a/src/tilde/tb_formats.h b/src/tilde/tb_formats.h deleted file mode 100644 index 1975d5848..000000000 --- a/src/tilde/tb_formats.h +++ /dev/null @@ -1,132 +0,0 @@ -// This handles the generalized executable/object format parsing stuff -#ifndef TB_OBJECT_H -#define TB_OBJECT_H - -#include -#include - -typedef enum { - TB_OBJECT_RELOC_NONE, // how? - - // Target independent - TB_OBJECT_RELOC_ADDR32, - TB_OBJECT_RELOC_ADDR64, // unsupported on 32bit platforms - TB_OBJECT_RELOC_SECREL, - TB_OBJECT_RELOC_SECTION, - - // COFF only - TB_OBJECT_RELOC_ADDR32NB, // Relative virtual address - - // x64 only - TB_OBJECT_RELOC_REL32, // relative 32bit displacement - - // Aarch64 only - TB_OBJECT_RELOC_BRANCH26, // 26bit displacement for B and BL instructions - TB_OBJECT_RELOC_REL21, // for ADR instructions - - // TODO(NeGate): fill in the rest of this later -} TB_ObjectRelocType; - -typedef struct { - TB_ObjectRelocType type; - uint32_t symbol_index; - size_t virtual_address; - size_t addend; -} TB_ObjectReloc; - -typedef enum { - TB_OBJECT_SYMBOL_UNKNOWN, - TB_OBJECT_SYMBOL_EXTERN, // exported - TB_OBJECT_SYMBOL_WEAK_EXTERN, // weak - TB_OBJECT_SYMBOL_IMPORT, // forward decl - TB_OBJECT_SYMBOL_STATIC, // local - TB_OBJECT_SYMBOL_SECTION, // local -} TB_ObjectSymbolType; - -typedef struct { - TB_ObjectSymbolType type; - int section_num; - - uint32_t ordinal; - uint32_t value; - - TB_Slice name; - - // for COFF, this is the auxillary - void* extra; - - // this is zeroed out by the loader and left for the user to do crap with - void* user_data; -} TB_ObjectSymbol; - -typedef struct { - TB_Slice name; - uint32_t flags; - - size_t virtual_address; - size_t virtual_size; - - // You can have a virtual size without having a raw - // data size, that's how the BSS section works - TB_Slice raw_data; - - size_t relocation_count; - TB_ObjectReloc* relocations; - - // this is zeroed out by the loader and left for the user to do crap with - void* user_data; -} TB_ObjectSection; - -typedef enum { - TB_OBJECT_FILE_UNKNOWN, - - TB_OBJECT_FILE_COFF, - TB_OBJECT_FILE_ELF64 -} TB_ObjectFileType; - -typedef struct { - TB_ObjectFileType type; - TB_Arch arch; - - TB_Slice name; - TB_Slice ar_name; - - size_t symbol_count; - TB_ObjectSymbol* symbols; - - size_t section_count; - TB_ObjectSection sections[]; -} TB_ObjectFile; - -//////////////////////////////// -// Archive parser -//////////////////////////////// -typedef struct { - TB_Slice name; - - // if import_name is empty, we're dealing with an object file - TB_Slice import_name; - uint16_t ordinal; - - TB_Slice content; -} TB_ArchiveEntry; - -typedef struct { - TB_Slice file; - size_t pos; - - size_t member_count; - uint32_t* members; - - size_t symbol_count; - uint16_t* symbols; - - TB_Slice strtbl; -} TB_ArchiveFileParser; - -// We do this to parse the header -bool tb_archive_parse(TB_Slice file, TB_ArchiveFileParser* restrict out_parser); -// After that we can enumerate any symbol entries to resolve imports -size_t tb_archive_parse_entries(TB_ArchiveFileParser* restrict parser, size_t i, size_t count, TB_ArchiveEntry* out_entry); - -#endif // TB_OBJECT_H diff --git a/src/tilde/tb_x64.h b/src/tilde/tb_x64.h deleted file mode 100644 index 58b3d656c..000000000 --- a/src/tilde/tb_x64.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef TB_X64_H -#define TB_X64_H - -#include -#include - -typedef enum { - // uses xmm registers for the reg array - TB_X86_INSTR_XMMREG = (1u << 0u), - - // r/m is a memory operand - TB_X86_INSTR_USE_MEMOP = (1u << 1u), - - // r/m is a rip-relative address (TB_X86_INSTR_USE_MEMOP is always set when this is set) - TB_X86_INSTR_USE_RIPMEM = (1u << 2u), - - // LOCK prefix is present - TB_X86_INSTR_LOCK = (1u << 3u), - - // uses a signed immediate - TB_X86_INSTR_IMMEDIATE = (1u << 4u), - - // absolute means it's using the 64bit immediate (cannot be applied while a memory operand is active) - TB_X86_INSTR_ABSOLUTE = (1u << 5u), - - // set if the r/m can be found on the right hand side - TB_X86_INSTR_DIRECTION = (1u << 6u), - - // uses the second data type because the instruction is weird like MOVSX or MOVZX - TB_X86_INSTR_TWO_DATA_TYPES = (1u << 7u), - - // REP prefix is present - TB_X86_INSTR_REP = (1u << 8u), - - // REPNE prefix is present - TB_X86_INSTR_REPNE = (1u << 9u), -} TB_X86_InstFlags; - -typedef enum { - TB_X86_RAX, TB_X86_RCX, TB_X86_RDX, TB_X86_RBX, TB_X86_RSP, TB_X86_RBP, TB_X86_RSI, TB_X86_RDI, - TB_X86_R8, TB_X86_R9, TB_X86_R10, TB_X86_R11, TB_X86_R12, TB_X86_R13, TB_X86_R14, TB_X86_R15, -} TB_X86_GPR; - -typedef enum { - TB_X86_SEGMENT_DEFAULT = 0, - - TB_X86_SEGMENT_ES, TB_X86_SEGMENT_CS, - TB_X86_SEGMENT_SS, TB_X86_SEGMENT_DS, - TB_X86_SEGMENT_GS, TB_X86_SEGMENT_FS, -} TB_X86_Segment; - -typedef enum { - TB_X86_TYPE_NONE = 0, - - TB_X86_TYPE_BYTE, // 1 - TB_X86_TYPE_WORD, // 2 - TB_X86_TYPE_DWORD, // 4 - TB_X86_TYPE_QWORD, // 8 - - TB_X86_TYPE_PBYTE, // int8 x 16 = 16 - TB_X86_TYPE_PWORD, // int16 x 8 = 16 - TB_X86_TYPE_PDWORD, // int32 x 4 = 16 - TB_X86_TYPE_PQWORD, // int64 x 2 = 16 - - TB_X86_TYPE_SSE_SS, // float32 x 1 = 4 - TB_X86_TYPE_SSE_SD, // float64 x 1 = 8 - TB_X86_TYPE_SSE_PS, // float32 x 4 = 16 - TB_X86_TYPE_SSE_PD, // float64 x 2 = 16 - - TB_X86_TYPE_XMMWORD, // the generic idea of them -} TB_X86_DataType; - -typedef struct { - int32_t opcode; - - // registers (there's 4 max taking up 8bit slots each) - int8_t regs[4]; - uint16_t flags; - - // bitpacking amirite - TB_X86_DataType data_type : 8; - TB_X86_DataType data_type2 : 8; - TB_X86_Segment segment : 4; - uint8_t length : 4; - - // memory operand - // X86_INSTR_USE_MEMOP - uint8_t base, index, scale; - int32_t disp; - - // immediate operand - // imm for INSTR_IMMEDIATE - // abs for INSTR_ABSOLUTE - union { - int32_t imm; - uint64_t abs; - }; -} TB_X86_Inst; - -bool tb_x86_disasm(TB_X86_Inst* restrict inst, size_t length, const uint8_t* data); -const char* tb_x86_reg_name(int8_t reg, TB_X86_DataType dt); -const char* tb_x86_type_name(TB_X86_DataType dt); -const char* tb_x86_mnemonic(TB_X86_Inst* inst); - -#endif /* TB_X64_H */ diff --git a/src/tilde_builtin.cpp b/src/tilde_builtin.cpp deleted file mode 100644 index 3b4e4f900..000000000 --- a/src/tilde_builtin.cpp +++ /dev/null @@ -1,592 +0,0 @@ -gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value) { - Type *t = base_type(value.type); - - switch (t->kind) { - case Type_Basic: - switch (t->Basic.kind) { - case Basic_string: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_load(p, len_ptr); - } - case Basic_cstring: - GB_PANIC("TODO(bill): len(cstring)"); - break; - } - break; - case Type_Array: - return cg_const_int(p, t_int, t->Array.count); - case Type_EnumeratedArray: - return cg_const_int(p, t_int, t->EnumeratedArray.count); - case Type_Slice: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_load(p, len_ptr); - } - case Type_DynamicArray: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_load(p, len_ptr); - } - case Type_Map: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_conv(p, cg_emit_load(p, len_ptr), t_int); - } - case Type_Struct: - GB_ASSERT(is_type_soa_struct(t)); - { - if (t->Struct.soa_kind == StructSoa_Fixed) { - return cg_const_int(p, t_int, t->Struct.soa_count); - } - - GB_ASSERT(t->Struct.soa_kind == StructSoa_Slice || - t->Struct.soa_kind == StructSoa_Dynamic); - - isize n = 0; - Type *elem = base_type(t->Struct.soa_elem); - if (elem->kind == Type_Struct) { - n = cast(isize)elem->Struct.fields.count; - } else if (elem->kind == Type_Array) { - n = cast(isize)elem->Array.count; - } else { - GB_PANIC("Unreachable"); - } - - return cg_emit_struct_ev(p, value, n); - } - break; - } - - GB_PANIC("TODO(bill): cg_builtin_len %s", type_to_string(t)); - return {}; -} - -gb_internal cgValue cg_builtin_cap(cgProcedure *p, cgValue value) { - Type *t = base_type(value.type); - - switch (t->kind) { - case Type_Basic: - switch (t->Basic.kind) { - case Basic_string: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_load(p, len_ptr); - } - case Basic_cstring: - GB_PANIC("TODO(bill): cap(cstring)"); - break; - } - break; - case Type_Array: - return cg_const_int(p, t_int, t->Array.count); - case Type_EnumeratedArray: - return cg_const_int(p, t_int, t->EnumeratedArray.count); - case Type_Slice: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 1); - return cg_emit_load(p, len_ptr); - } - case Type_DynamicArray: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue len_ptr = cg_emit_struct_ep(p, ptr, 2); - return cg_emit_load(p, len_ptr); - } - case Type_Map: - { - TB_DataType dt_uintptr = cg_data_type(t_uintptr); - TB_Node *zero = tb_inst_uint(p->func, dt_uintptr, 0); - TB_Node *one = tb_inst_uint(p->func, dt_uintptr, 0); - TB_Node *mask = tb_inst_uint(p->func, dt_uintptr, MAP_CACHE_LINE_SIZE-1); - - TB_Node *data = cg_emit_struct_ev(p, value, 0).node; - TB_Node *log2_cap = tb_inst_and(p->func, data, mask); - TB_Node *cap = tb_inst_shl(p->func, one, log2_cap, cast(TB_ArithmeticBehavior)0); - TB_Node *cmp = tb_inst_cmp_eq(p->func, data, zero); - - cgValue res = cg_value(tb_inst_select(p->func, cmp, zero, cap), t_uintptr); - return cg_emit_conv(p, res, t_int); - } - case Type_Struct: - GB_ASSERT(is_type_soa_struct(t)); - break; - } - - GB_PANIC("TODO(bill): cg_builtin_cap %s", type_to_string(t)); - return {}; -} - - -gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) { - Type *t = base_type(value.type); - cgValue res = {}; - switch (t->kind) { - case Type_Slice: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0); - res = cg_emit_load(p, data_ptr); - GB_ASSERT(is_type_multi_pointer(res.type)); - } - break; - case Type_DynamicArray: - { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0); - res = cg_emit_load(p, data_ptr); - } - break; - case Type_Basic: - if (t->Basic.kind == Basic_string) { - GB_ASSERT(value.kind == cgValue_Addr); - cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type)); - cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0); - res = cg_emit_load(p, data_ptr); - } else if (t->Basic.kind == Basic_cstring) { - res = cg_emit_conv(p, value, t_u8_multi_ptr); - } - break; - case Type_Pointer: - GB_ASSERT(is_type_array_like(t->Pointer.elem)); - GB_ASSERT(value.kind == cgValue_Value); - res = cg_value(value.node, alloc_type_multi_pointer(base_array_type(t->Pointer.elem))); - break; - case Type_MultiPointer: - - GB_PANIC("TODO(bill) %s", type_to_string(value.type)); - // res = cg_emit_conv(p, value, tv.type); - break; - } - GB_ASSERT(res.node != nullptr); - return res; -} - -gb_internal cgValue cg_builtin_min(cgProcedure *p, Type *t, cgValue x, cgValue y) { - x = cg_emit_conv(p, x, t); - y = cg_emit_conv(p, y, t); - return cg_emit_select(p, cg_emit_comp(p, Token_Lt, x, y), x, y); -} -gb_internal cgValue cg_builtin_max(cgProcedure *p, Type *t, cgValue x, cgValue y) { - x = cg_emit_conv(p, x, t); - y = cg_emit_conv(p, y, t); - return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y); -} - -gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue const &x) { - if (is_type_unsigned(x.type)) { - return x; - } - - if (is_type_quaternion(x.type)) { - GB_PANIC("TODO(bill): abs quaternion"); - } else if (is_type_complex(x.type)) { - GB_PANIC("TODO(bill): abs complex"); - } - - TB_DataType dt = cg_data_type(x.type); - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - TB_Node *zero = nullptr; - if (dt.type == TB_FLOAT) { - if (dt.data == 32) { - zero = tb_inst_float32(p->func, 0); - } else if (dt.data == 64) { - zero = tb_inst_float64(p->func, 0); - } - } else { - zero = tb_inst_uint(p->func, dt, 0); - } - GB_ASSERT(zero != nullptr); - - cgValue cond = cg_emit_comp(p, Token_Lt, x, cg_value(zero, x.type)); - cgValue neg = cg_emit_unary_arith(p, Token_Sub, x, x.type); - return cg_emit_select(p, cond, neg, x); -} - -gb_internal cgValue cg_builtin_clamp(cgProcedure *p, Type *t, cgValue const &x, cgValue const &min, cgValue const &max) { - cgValue z = x; - z = cg_builtin_max(p, t, z, min); - z = cg_builtin_min(p, t, z, max); - return z; -} - - - -gb_internal cgValue cg_builtin_mem_zero(cgProcedure *p, cgValue const &ptr, cgValue const &len) { - GB_ASSERT(ptr.kind == cgValue_Value); - GB_ASSERT(len.kind == cgValue_Value); - tb_inst_memzero(p->func, ptr.node, len.node, 1); - return ptr; -} - -gb_internal cgValue cg_builtin_mem_copy(cgProcedure *p, cgValue const &dst, cgValue const &src, cgValue const &len) { - GB_ASSERT(dst.kind == cgValue_Value); - GB_ASSERT(src.kind == cgValue_Value); - GB_ASSERT(len.kind == cgValue_Value); - // TODO(bill): This needs to be memmove - tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1); - return dst; -} - -gb_internal cgValue cg_builtin_mem_copy_non_overlapping(cgProcedure *p, cgValue const &dst, cgValue const &src, cgValue const &len) { - GB_ASSERT(dst.kind == cgValue_Value); - GB_ASSERT(src.kind == cgValue_Value); - GB_ASSERT(len.kind == cgValue_Value); - tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1); - return dst; -} - -gb_internal TB_Symbol *cg_builtin_map_cell_info_symbol(cgModule *m, Type *type) { - MUTEX_GUARD(&m->map_info_mutex); - TB_Symbol **found = map_get(&m->map_cell_info_map, type); - if (found) { - return *found; - } - i64 size = 0, len = 0; - map_cell_size_and_len(type, &size, &len); - - TB_Global *global = tb_global_create(m->mod, 0, "", cg_debug_type(m, t_map_cell_info), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(t_map_cell_info), type_align_of(t_map_cell_info), 4); - - i64 ptr_size = build_context.ptr_size; - void *size_of_type = tb_global_add_region(m->mod, global, 0*ptr_size, ptr_size); - void *align_of_type = tb_global_add_region(m->mod, global, 1*ptr_size, ptr_size); - void *size_of_cell = tb_global_add_region(m->mod, global, 2*ptr_size, ptr_size); - void *elements_per_cell = tb_global_add_region(m->mod, global, 3*ptr_size, ptr_size); - - cg_write_uint_at_ptr(size_of_type, type_size_of(type), t_uintptr); - cg_write_uint_at_ptr(align_of_type, type_align_of(type), t_uintptr); - cg_write_uint_at_ptr(size_of_cell, size, t_uintptr); - cg_write_uint_at_ptr(elements_per_cell, len, t_uintptr); - - map_set(&m->map_cell_info_map, type, cast(TB_Symbol *)global); - - return cast(TB_Symbol *)global; -} - - -gb_internal cgValue cg_builtin_map_cell_info(cgProcedure *p, Type *type) { - type = core_type(type); - TB_Symbol *symbol = cg_builtin_map_cell_info_symbol(p->module, type); - TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); - return cg_value(node, t_map_cell_info_ptr); -} - -gb_internal cgValue cg_builtin_map_info(cgProcedure *p, Type *map_type) { - map_type = base_type(map_type); - GB_ASSERT(map_type->kind == Type_Map); - - cgModule *m = p->module; - MUTEX_GUARD(&m->map_info_mutex); - TB_Global *global = nullptr; - TB_Symbol **found = map_get(&m->map_info_map, map_type); - if (found) { - global = cast(TB_Global *)*found; - } else { - global = tb_global_create(m->mod, 0, "", cg_debug_type(m, t_map_info), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(t_map_info), type_align_of(t_map_info), 4); - - TB_Symbol *key_cell_info = cg_builtin_map_cell_info_symbol(m, map_type->Map.key); - TB_Symbol *value_cell_info = cg_builtin_map_cell_info_symbol(m, map_type->Map.value); - cgProcedure *key_hasher = cg_hasher_proc_for_type(p->module, map_type->Map.key); - cgProcedure *key_equal = cg_equal_proc_for_type (p->module, map_type->Map.key); - - tb_global_add_symbol_reloc(p->module->mod, global, 0*build_context.ptr_size, key_cell_info); - tb_global_add_symbol_reloc(p->module->mod, global, 1*build_context.ptr_size, value_cell_info); - tb_global_add_symbol_reloc(p->module->mod, global, 2*build_context.ptr_size, key_hasher->symbol); - tb_global_add_symbol_reloc(p->module->mod, global, 3*build_context.ptr_size, key_equal->symbol); - - map_set(&m->map_info_map, map_type, cast(TB_Symbol *)global); - } - - GB_ASSERT(global != nullptr); - TB_Node *node = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); - return cg_value(node, t_map_info_ptr); -} - - - - -gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) { - ast_node(ce, CallExpr, expr); - - if (BuiltinProc__simd_begin < id && id < BuiltinProc__simd_end) { - GB_PANIC("TODO(bill): cg_build_builtin_simd_proc"); - // return cg_build_builtin_simd_proc(p, expr, tv, id); - } - - String builtin_name = builtin_procs[id].name; - - switch (id) { - case BuiltinProc_DIRECTIVE: { - ast_node(bd, BasicDirective, ce->proc); - String name = bd->name.string; - GB_ASSERT(name == "location"); - String procedure = p->entity->token.string; - TokenPos pos = ast_token(ce->proc).pos; - if (ce->args.count > 0) { - Ast *ident = unselector_expr(ce->args[0]); - GB_ASSERT(ident->kind == Ast_Ident); - Entity *e = entity_of_node(ident); - GB_ASSERT(e != nullptr); - - if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity != nullptr) { - procedure = e->parent_proc_decl->entity->token.string; - } else { - procedure = str_lit(""); - } - pos = e->token.pos; - - } - return cg_emit_source_code_location_as_global(p, procedure, pos); - } break; - - case BuiltinProc_len: { - cgValue v = cg_build_expr(p, ce->args[0]); - Type *t = base_type(v.type); - if (is_type_pointer(t)) { - // IMPORTANT TODO(bill): Should there be a nil pointer check? - v = cg_emit_load(p, v); - t = type_deref(t); - } - return cg_builtin_len(p, v); - } - - case BuiltinProc_cap: { - cgValue v = cg_build_expr(p, ce->args[0]); - Type *t = base_type(v.type); - if (is_type_pointer(t)) { - // IMPORTANT TODO(bill): Should there be a nil pointer check? - v = cg_emit_load(p, v); - t = type_deref(t); - } - return cg_builtin_cap(p, v); - } - - case BuiltinProc_raw_data: - { - cgValue v = cg_build_expr(p, ce->args[0]); - return cg_builtin_raw_data(p, v); - } - - case BuiltinProc_min: - if (ce->args.count == 2) { - Type *t = type_of_expr(expr); - cgValue x = cg_build_expr(p, ce->args[0]); - cgValue y = cg_build_expr(p, ce->args[1]); - return cg_builtin_min(p, t, x, y); - } else { - Type *t = type_of_expr(expr); - cgValue x = cg_build_expr(p, ce->args[0]); - for (isize i = 1; i < ce->args.count; i++) { - cgValue y = cg_build_expr(p, ce->args[i]); - x = cg_builtin_min(p, t, x, y); - } - return x; - } - break; - case BuiltinProc_max: - if (ce->args.count == 2) { - Type *t = type_of_expr(expr); - cgValue x = cg_build_expr(p, ce->args[0]); - cgValue y = cg_build_expr(p, ce->args[1]); - return cg_builtin_max(p, t, x, y); - } else { - Type *t = type_of_expr(expr); - cgValue x = cg_build_expr(p, ce->args[0]); - for (isize i = 1; i < ce->args.count; i++) { - cgValue y = cg_build_expr(p, ce->args[i]); - x = cg_builtin_max(p, t, x, y); - } - return x; - } - break; - - case BuiltinProc_abs: - { - cgValue x = cg_build_expr(p, ce->args[0]); - return cg_builtin_abs(p, x); - } - - case BuiltinProc_clamp: - { - cgValue x = cg_build_expr(p, ce->args[0]); - cgValue min = cg_build_expr(p, ce->args[1]); - cgValue max = cg_build_expr(p, ce->args[2]); - return cg_builtin_clamp(p, type_of_expr(expr), x, min, max); - } - - case BuiltinProc_debug_trap: - tb_inst_debugbreak(p->func); - return {}; - case BuiltinProc_trap: - tb_inst_trap(p->func); - return {}; - - case BuiltinProc_mem_zero: - { - cgValue ptr = cg_build_expr(p, ce->args[0]); - cgValue len = cg_build_expr(p, ce->args[1]); - return cg_builtin_mem_zero(p, ptr, len); - } - - case BuiltinProc_mem_copy: - { - cgValue dst = cg_build_expr(p, ce->args[0]); - cgValue src = cg_build_expr(p, ce->args[1]); - cgValue len = cg_build_expr(p, ce->args[2]); - return cg_builtin_mem_copy(p, dst, src, len); - } - - case BuiltinProc_mem_copy_non_overlapping: - { - cgValue dst = cg_build_expr(p, ce->args[0]); - cgValue src = cg_build_expr(p, ce->args[1]); - cgValue len = cg_build_expr(p, ce->args[2]); - return cg_builtin_mem_copy_non_overlapping(p, dst, src, len); - } - - - case BuiltinProc_overflow_add: - { - Type *res_type = type_of_expr(expr); - GB_ASSERT(res_type->kind == Type_Tuple); - GB_ASSERT(res_type->Tuple.variables.count == 2); - // TODO(bill): do a proper overflow add - Type *type = res_type->Tuple.variables[0]->type; - Type *ok_type = res_type->Tuple.variables[1]->type; - cgValue x = cg_build_expr(p, ce->args[0]); - cgValue y = cg_build_expr(p, ce->args[1]); - x = cg_emit_conv(p, x, type); - y = cg_emit_conv(p, y, type); - cgValue res = cg_emit_arith(p, Token_Add, x, y, type); - cgValue ok = cg_const_int(p, ok_type, false); - - return cg_value_multi2(res, ok, res_type); - } - - - case BuiltinProc_ptr_offset: - { - cgValue ptr = cg_build_expr(p, ce->args[0]); - cgValue len = cg_build_expr(p, ce->args[1]); - len = cg_emit_conv(p, len, t_int); - return cg_emit_ptr_offset(p, ptr, len); - } - case BuiltinProc_ptr_sub: - { - Type *elem0 = type_deref(type_of_expr(ce->args[0])); - Type *elem1 = type_deref(type_of_expr(ce->args[1])); - GB_ASSERT(are_types_identical(elem0, elem1)); - Type *elem = elem0; - - cgValue ptr0 = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t_uintptr); - cgValue ptr1 = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t_uintptr); - - cgValue diff = cg_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr); - diff = cg_emit_conv(p, diff, t_int); - return cg_emit_arith(p, Token_Quo, diff, cg_const_int(p, t_int, type_size_of(elem)), t_int); - } - - case BuiltinProc_type_info_of: - { - Ast *arg = ce->args[0]; - TypeAndValue tav = type_and_value_of_expr(arg); - if (tav.mode == Addressing_Type) { - Type *t = default_type(type_of_expr(arg)); - return cg_type_info(p, t); - } - GB_ASSERT(is_type_typeid(tav.type)); - - auto args = slice_make(permanent_allocator(), 1); - args[0] = cg_build_expr(p, arg); - return cg_emit_runtime_call(p, "__type_info_of", args); - } - - - case BuiltinProc_type_equal_proc: - return cg_equal_proc_value_for_type(p, ce->args[0]->tav.type); - - case BuiltinProc_type_hasher_proc: - return cg_hasher_proc_value_for_type(p, ce->args[0]->tav.type); - - case BuiltinProc_type_map_cell_info: - return cg_builtin_map_cell_info(p, ce->args[0]->tav.type); - case BuiltinProc_type_map_info: - return cg_builtin_map_info(p, ce->args[0]->tav.type); - - case BuiltinProc_expect: - { - Type *t = default_type(expr->tav.type); - cgValue x = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t); - cgValue y = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t); - gb_unused(y); - return x; - } - - case BuiltinProc_count_leading_zeros: - { - cgValue n = cg_build_expr(p, ce->args[0]); - n = cg_emit_conv(p, n, default_type(expr->tav.type)); - GB_ASSERT(n.kind == cgValue_Value); - TB_Node *val = tb_inst_clz(p->func, n.node); - val = tb_inst_zxt(p->func, val, cg_data_type(n.type)); - return cg_value(val, n.type); - } - - - case BuiltinProc_count_trailing_zeros: - { - cgValue n = cg_build_expr(p, ce->args[0]); - n = cg_emit_conv(p, n, default_type(expr->tav.type)); - GB_ASSERT(n.kind == cgValue_Value); - TB_Node *val = tb_inst_ctz(p->func, n.node); - val = tb_inst_zxt(p->func, val, cg_data_type(n.type)); - return cg_value(val, n.type); - } - - case BuiltinProc_count_ones: - { - cgValue n = cg_build_expr(p, ce->args[0]); - n = cg_emit_conv(p, n, default_type(expr->tav.type)); - GB_ASSERT(n.kind == cgValue_Value); - TB_Node *val = tb_inst_popcount(p->func, n.node); - val = tb_inst_zxt(p->func, val, cg_data_type(n.type)); - return cg_value(val, n.type); - } - - case BuiltinProc_count_zeros: - { - cgValue n = cg_build_expr(p, ce->args[0]); - n = cg_emit_conv(p, n, default_type(expr->tav.type)); - GB_ASSERT(n.kind == cgValue_Value); - TB_DataType dt = cg_data_type(n.type); - TB_Node *ones = tb_inst_popcount(p->func, n.node); - ones = tb_inst_zxt(p->func, ones, dt); - - cgValue size = cg_const_int(p, n.type, 8*type_size_of(n.type)); - return cg_emit_arith(p, Token_Sub, size, cg_value(ones, n.type), n.type); - } - - } - - - GB_PANIC("TODO(bill): builtin procs %d %.*s", id, LIT(builtin_name)); - return {}; -} - diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp deleted file mode 100644 index 456b2cdc7..000000000 --- a/src/tilde_const.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -gb_internal bool cg_is_expr_constant_zero(Ast *expr) { - GB_ASSERT(expr != nullptr); - auto v = exact_value_to_integer(expr->tav.value); - if (v.kind == ExactValue_Integer) { - return big_int_cmp_zero(&v.value_integer) == 0; - } - return false; -} - -gb_internal cgValue cg_const_nil(cgModule *m, cgProcedure *p, Type *type) { - GB_ASSERT(m != nullptr); - Type *original_type = type; - type = core_type(type); - i64 size = type_size_of(type); - i64 align = type_align_of(type); - TB_DataType dt = cg_data_type(type); - if (TB_IS_VOID_TYPE(dt)) { - char name[32] = {}; - gb_snprintf(name, 31, "cnil$%u", 1+m->const_nil_guid.fetch_add(1)); - TB_Global *global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, size, align, 0); - - TB_Symbol *symbol = cast(TB_Symbol *)global; - if (p) { - TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); - return cg_lvalue_addr(node, type); - } else { - return cg_value(symbol, type); - } - } - - if (is_type_internally_pointer_like(type)) { - return cg_value(tb_inst_uint(p->func, dt, 0), type); - } else if (is_type_integer(type) || is_type_boolean(type) || is_type_bit_set(type) || is_type_typeid(type)) { - return cg_value(tb_inst_uint(p->func, dt, 0), type); - } else if (is_type_float(type)) { - switch (size) { - case 2: - return cg_value(tb_inst_uint(p->func, dt, 0), type); - case 4: - return cg_value(tb_inst_float32(p->func, 0), type); - case 8: - return cg_value(tb_inst_float64(p->func, 0), type); - } - } - GB_PANIC("TODO(bill): cg_const_nil %s", type_to_string(original_type)); - return {}; -} - -gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) { - return cg_const_nil(p->module, p, type); -} - -gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Type *type, TB_Global *global, i64 offset); -gb_internal void cg_write_int_at_ptr(void *dst, i64 i, Type *original_type); - -gb_internal void cg_global_source_code_location_const(cgModule *m, String const &proc_name, TokenPos pos, TB_Global *global, i64 offset) { - // Source_Code_Location :: struct { - // file_path: string, - // line, column: i32, - // procedure: string, - // } - - i64 file_path_offset = type_offset_of(t_source_code_location, 0); - i64 line_offset = type_offset_of(t_source_code_location, 1); - i64 column_offset = type_offset_of(t_source_code_location, 2); - i64 procedure_offset = type_offset_of(t_source_code_location, 3); - - String file_path = get_file_path_string(pos.file_id); - if (file_path.len != 0) { - cg_global_const_string(m, file_path, t_string, global, offset+file_path_offset); - } - - void *line_ptr = tb_global_add_region(m->mod, global, offset+line_offset, 4); - void *column_ptr = tb_global_add_region(m->mod, global, offset+column_offset, 4); - cg_write_int_at_ptr(line_ptr, pos.line, t_i32); - cg_write_int_at_ptr(column_ptr, pos.column, t_i32); - - if (proc_name.len != 0) { - cg_global_const_string(m, proc_name, t_string, global, offset+procedure_offset); - } -} - - -gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, String const &proc_name, TokenPos pos) { - cgModule *m = p->module; - char name[32] = {}; - gb_snprintf(name, 31, "scl$%u", 1+m->const_nil_guid.fetch_add(1)); - - TB_Global *global = tb_global_create(m->mod, -1, name, cg_debug_type(m, t_source_code_location), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(t_source_code_location), type_align_of(t_source_code_location), 6); - - cg_global_source_code_location_const(m, proc_name, pos, global, 0); - - TB_Node *ptr = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); - return cg_lvalue_addr(ptr, t_source_code_location); -} - -gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, Ast *node) { - String proc_name = p->name; - TokenPos pos = ast_token(node).pos; - return cg_emit_source_code_location_as_global(p, proc_name, pos); -} - -gb_internal void cg_write_big_int_at_ptr(void *dst, BigInt const *a, Type *original_type) { - GB_ASSERT(build_context.endian_kind == TargetEndian_Little); - size_t sz = cast(size_t)type_size_of(original_type); - if (big_int_is_zero(a)) { - gb_memset(dst, 0, sz); - return; - } - u64 rop64[4] = {}; // 2 u64 is the maximum we will ever need, so doubling it will be fine :P - u8 *rop = cast(u8 *)rop64; - - size_t max_count = 0; - size_t written = 0; - size_t size = 1; - size_t nails = 0; - mp_endian endian = MP_LITTLE_ENDIAN; - - max_count = mp_pack_count(a, nails, size); - if (sz < max_count) { - debug_print_big_int(a); - gb_printf_err("%s -> %tu\n", type_to_string(original_type), sz);; - } - GB_ASSERT_MSG(sz >= max_count, "max_count: %tu, sz: %tu, written: %tu, type %s", max_count, sz, written, type_to_string(original_type)); - GB_ASSERT(gb_size_of(rop64) >= sz); - - mp_err err = mp_pack(rop, sz, &written, - MP_LSB_FIRST, - size, endian, nails, - a); - GB_ASSERT(err == MP_OKAY); - - if (!is_type_endian_little(original_type)) { - for (size_t i = 0; i < sz/2; i++) { - u8 tmp = rop[i]; - rop[i] = rop[sz-1-i]; - rop[sz-1-i] = tmp; - } - } - - gb_memcopy(dst, rop, sz); - return; -} - - -gb_internal void cg_write_int_at_ptr(void *dst, i64 i, Type *original_type) { - ExactValue v = exact_value_i64(i); - cg_write_big_int_at_ptr(dst, &v.value_integer, original_type); -} -gb_internal void cg_write_uint_at_ptr(void *dst, u64 i, Type *original_type) { - ExactValue v = exact_value_u64(i); - cg_write_big_int_at_ptr(dst, &v.value_integer, original_type); -} - -gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Type *type, TB_Global *global, i64 offset) { - GB_ASSERT(is_type_string(type)); - - char name[32] = {}; - gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1)); - TB_Global *str_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - i64 size = str.len+1; - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, size, 1, 1); - u8 *data = cast(u8 *)tb_global_add_region(m->mod, str_global, 0, size); - gb_memcopy(data, str.text, str.len); - data[str.len] = 0; - - if (is_type_cstring(type)) { - if (global) { - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)str_global); - } - return str_global; - } - - if (global == nullptr) { - gb_snprintf(name, 31, "cstr$%u", 1+m->const_nil_guid.fetch_add(1)); - global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(type), type_align_of(type), 2); - } - - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)str_global); - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, str.len, t_int); - - return global; -} - -gb_internal bool cg_elem_type_can_be_constant(Type *t) { - t = base_type(t); - if (t == t_invalid) { - return false; - } - if (is_type_dynamic_array(t) || is_type_map(t)) { - return false; - } - return true; -} - - -gb_internal bool cg_is_elem_const(Ast *elem, Type *elem_type) { - if (!cg_elem_type_can_be_constant(elem_type)) { - return false; - } - if (elem->kind == Ast_FieldValue) { - elem = elem->FieldValue.value; - } - TypeAndValue tav = type_and_value_of_expr(elem); - GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s", expr_to_string(elem), type_to_string(tav.type)); - return tav.value.kind != ExactValue_Invalid; -} - -gb_internal bool cg_is_nested_possibly_constant(Type *ft, Selection const &sel, Ast *elem) { - GB_ASSERT(!sel.indirect); - for (i32 index : sel.index) { - Type *bt = base_type(ft); - switch (bt->kind) { - case Type_Struct: - // if (bt->Struct.is_raw_union) { - // return false; - // } - ft = bt->Struct.fields[index]->type; - break; - case Type_Array: - ft = bt->Array.elem; - break; - default: - return false; - } - } - return cg_is_elem_const(elem, ft); -} - -gb_internal i64 cg_global_const_calculate_region_count_from_basic_type(Type *type) { - type = core_type(type); - - switch (type->kind) { - case Type_Basic: - switch (type->Basic.kind) { - case Basic_string: // ^u8 + int - case Basic_any: // rawptr + typeid - return 2; - } - return 1; - case Type_Pointer: - case Type_MultiPointer: - return 2; // allows for offsets - case Type_Proc: - return 1; - case Type_Slice: - return 3; // alows for offsets - case Type_DynamicArray: - return 5; - case Type_Map: - return 4; - - case Type_Enum: - case Type_BitSet: - return 1; - - case Type_RelativePointer: - case Type_RelativeMultiPointer: - return 2; // allows for offsets - - case Type_Matrix: - return 1; - - case Type_Array: - { - Type *elem = type->Array.elem; - i64 count = cg_global_const_calculate_region_count_from_basic_type(elem); - return count*type->Array.count; - } - case Type_EnumeratedArray: - { - Type *elem = type->EnumeratedArray.elem; - i64 count = cg_global_const_calculate_region_count_from_basic_type(elem); - return count*type->EnumeratedArray.count; - } - - case Type_Struct: - if (type->Struct.is_raw_union) { - i64 max_count = 0; - for (Entity *f : type->Struct.fields) { - i64 count = cg_global_const_calculate_region_count_from_basic_type(f->type); - max_count = gb_max(count, max_count); - } - return max_count; - } else { - i64 max_count = 0; - for (Entity *f : type->Struct.fields) { - max_count += cg_global_const_calculate_region_count_from_basic_type(f->type); - } - return max_count; - } - break; - case Type_Union: - { - i64 max_count = 0; - for (Type *t : type->Union.variants) { - i64 count = cg_global_const_calculate_region_count_from_basic_type(t); - max_count = gb_max(count, max_count); - } - return max_count+1; - } - break; - - default: - GB_PANIC("TODO(bill): %s", type_to_string(type)); - break; - } - return -1; -} -gb_internal isize cg_global_const_calculate_region_count(ExactValue const &value, Type *type) { - Type *bt = base_type(type); - if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) { - if (is_type_rune_array(type)) { - return 1; - } - - Type *et = base_array_type(type); - i64 base_count = 2; - if (is_type_cstring(et)) { - base_count = 1; - } - return base_count * bt->Array.count; - } else if (is_type_u8_array(type) && value.kind == ExactValue_String) { - return 1; - } else if (is_type_array(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_String && - value.kind != ExactValue_Compound) { - Type *elem = type->Array.elem; - - i64 base_count = cg_global_const_calculate_region_count(value, elem); - return base_count * type->Array.count; - } else if (is_type_matrix(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_Compound) { - return 1; - } else if (is_type_simd_vector(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_Compound) { - return 1; - } - - isize count = 0; - switch (value.kind) { - case ExactValue_Invalid: - return 0; - case ExactValue_Bool: - case ExactValue_Integer: - case ExactValue_Float: - case ExactValue_Typeid: - case ExactValue_Complex: - case ExactValue_Quaternion: - return 1; - case ExactValue_Pointer: - return 2; - - case ExactValue_Procedure: - return 1; - - case ExactValue_String: - if (is_type_string(type)) { - return 3; - } else if (is_type_cstring(type) || is_type_array_like(type)) { - return 2; - } - return 3; - - case ExactValue_Compound: { - ast_node(cl, CompoundLit, value.value_compound); - Type *bt = base_type(type); - switch (bt->kind) { - case Type_Struct: - if (cl->elems[0]->kind == Ast_FieldValue) { - for (isize i = 0; i < cl->elems.count; i++) { - ast_node(fv, FieldValue, cl->elems[i]); - String name = fv->field->Ident.token.string; - - Selection sel = lookup_field(type, name, false); - GB_ASSERT(!sel.indirect); - - Entity *f = bt->Struct.fields[sel.index[0]]; - - if (!cg_elem_type_can_be_constant(f->type)) { - continue; - } - - if (sel.index.count == 1) { - count += cg_global_const_calculate_region_count(fv->value->tav.value, f->type); - } else { - count += 1; // just in case - if (cg_is_nested_possibly_constant(type, sel, fv->value)) { - Type *cv_type = sel.entity->type; - count += cg_global_const_calculate_region_count(fv->value->tav.value, cv_type); - } - } - } - } else { - for_array(i, cl->elems) { - i64 field_index = i; - Ast *elem = cl->elems[i]; - TypeAndValue tav = elem->tav; - Entity *f = bt->Struct.fields[field_index]; - if (!cg_elem_type_can_be_constant(f->type)) { - continue; - } - - ExactValue value = {}; - if (tav.mode != Addressing_Invalid) { - value = tav.value; - } - count += cg_global_const_calculate_region_count(value, type); - } - } - break; - case Type_Array: - case Type_EnumeratedArray: - case Type_SimdVector: { - Type *et = base_array_type(bt); - if (!cg_elem_type_can_be_constant(et)) { - break; - } - for (Ast *elem : cl->elems) { - if (elem->kind == Ast_FieldValue) { - ast_node(fv, FieldValue, elem); - ExactValue const &value = elem->FieldValue.value->tav.value; - if (is_ast_range(fv->field)) { - ast_node(ie, BinaryExpr, fv->field); - TypeAndValue lo_tav = ie->left->tav; - TypeAndValue hi_tav = ie->right->tav; - GB_ASSERT(lo_tav.mode == Addressing_Constant); - GB_ASSERT(hi_tav.mode == Addressing_Constant); - - TokenKind op = ie->op.kind; - i64 lo = exact_value_to_i64(lo_tav.value); - i64 hi = exact_value_to_i64(hi_tav.value); - if (op != Token_RangeHalf) { - hi += 1; - } - - for (i64 i = lo; i < hi; i++) { - count += cg_global_const_calculate_region_count(value, et); - } - } else { - count += cg_global_const_calculate_region_count(value, et); - } - } else { - ExactValue const &value = elem->tav.value; - count += cg_global_const_calculate_region_count(value, et); - } - } - } break; - - case Type_BitSet: - return 1; - case Type_Matrix: - return 1; - - case Type_Slice: - return 3; - - default: - GB_PANIC("TODO(bill): %s", type_to_string(type)); - break; - } - }break; - } - return count; -} - -gb_internal TB_Global *cg_global_const_comp_literal(cgModule *m, Type *type, ExactValue const &value, TB_Global *global, i64 base_offset); - -gb_internal bool cg_global_const_add_region(cgModule *m, ExactValue const &value, Type *type, TB_Global *global, i64 offset) { - GB_ASSERT(is_type_endian_little(type)); - GB_ASSERT(!is_type_different_to_arch_endianness(type)); - - GB_ASSERT(global != nullptr); - - Type *bt = base_type(type); - i64 size = type_size_of(type); - if (value.kind == ExactValue_Invalid) { - return false; - } - if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) { - if (is_type_rune_array(type)) { - i64 count = type->Array.count; - Rune rune; - isize rune_offset = 0; - isize width = 1; - String s = value.value_string; - - Rune *runes = cast(Rune *)tb_global_add_region(m->mod, global, offset, count*4); - - for (i64 i = 0; i < count && rune_offset < s.len; i++) { - width = utf8_decode(s.text+rune_offset, s.len-rune_offset, &rune); - runes[i] = rune; - rune_offset += width; - - } - GB_ASSERT(offset == s.len); - return true; - } - Type *et = bt->Array.elem; - i64 elem_size = type_size_of(et); - - for (i64 i = 0; i < bt->Array.count; i++) { - cg_global_const_add_region(m, value, et, global, offset+(i * elem_size)); - } - return true; - } else if (is_type_u8_array(type) && value.kind == ExactValue_String) { - u8 *dst = cast(u8 *)tb_global_add_region(m->mod, global, offset, size); - gb_memcopy(dst, value.value_string.text, gb_min(value.value_string.len, size)); - return true; - } else if (is_type_array(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_String && - value.kind != ExactValue_Compound) { - - Type *et = bt->Array.elem; - i64 elem_size = type_size_of(et); - - for (i64 i = 0; i < bt->Array.count; i++) { - cg_global_const_add_region(m, value, et, global, offset+(i * elem_size)); - } - - return true; - } else if (is_type_matrix(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_Compound) { - GB_PANIC("TODO(bill): matrices"); - - i64 row = bt->Matrix.row_count; - i64 column = bt->Matrix.column_count; - GB_ASSERT(row == column); - - Type *elem = bt->Matrix.elem; - - i64 elem_size = type_size_of(elem); - gb_unused(elem_size); - - // 1 region in memory, not many - - return true; - } else if (is_type_simd_vector(type) && - value.kind != ExactValue_Invalid && - value.kind != ExactValue_Compound) { - - GB_PANIC("TODO(bill): #simd vectors"); - - Type *et = type->SimdVector.elem; - i64 elem_size = type_size_of(et); - gb_unused(elem_size); - - // 1 region in memory, not many - - return true; - } - - - switch (value.kind) { - case ExactValue_Bool: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - bool *res = cast(bool *)tb_global_add_region(m->mod, global, offset, size); - *res = !!value.value_bool; - } - break; - - case ExactValue_Integer: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - void *res = tb_global_add_region(m->mod, global, offset, size); - cg_write_big_int_at_ptr(res, &value.value_integer, type); - } - break; - - case ExactValue_Float: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - f64 f = exact_value_to_f64(value); - void *res = tb_global_add_region(m->mod, global, offset, size); - switch (size) { - case 2: *(u16 *)res = f32_to_f16(cast(f32)f); break; - case 4: *(f32 *)res = cast(f32)f; break; - case 8: *(f64 *)res = cast(f64)f; break; - } - } - break; - - case ExactValue_Pointer: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - void *res = tb_global_add_region(m->mod, global, offset, size); - *(u64 *)res = exact_value_to_u64(value); - } - break; - - case ExactValue_String: - if (is_type_array_like(type)) { - GB_ASSERT(global != nullptr); - void *data = tb_global_add_region(m->mod, global, offset, size); - gb_memcopy(data, value.value_string.text, gb_min(value.value_string.len, size)); - } else { - cg_global_const_string(m, value.value_string, type, global, offset); - } - break; - - case ExactValue_Typeid: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - void *dst = tb_global_add_region(m->mod, global, offset, size); - u64 id = cg_typeid_as_u64(m, value.value_typeid); - cg_write_uint_at_ptr(dst, id, t_typeid); - } - break; - - case ExactValue_Compound: - { - TB_Global *out_global = cg_global_const_comp_literal(m, type, value, global, offset); - GB_ASSERT(out_global == global); - } - break; - - case ExactValue_Procedure: - GB_PANIC("TODO(bill): nested procedure values/literals\n"); - break; - case ExactValue_Complex: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - Complex128 c = {}; - if (value.value_complex) { - c = *value.value_complex; - } - void *res = tb_global_add_region(m->mod, global, offset, size); - switch (size) { - case 4: - ((u16 *)res)[0] = f32_to_f16(cast(f32)c.real); - ((u16 *)res)[1] = f32_to_f16(cast(f32)c.imag); - break; - case 8: - ((f32 *)res)[0] = cast(f32)c.real; - ((f32 *)res)[1] = cast(f32)c.imag; - break; - case 16: - ((f64 *)res)[0] = cast(f64)c.real; - ((f64 *)res)[1] = cast(f64)c.imag; - break; - } - } - break; - case ExactValue_Quaternion: - { - GB_ASSERT_MSG(!is_type_array_like(bt), "%s", type_to_string(type)); - // @QuaternionLayout - Quaternion256 q = {}; - if (value.value_quaternion) { - q = *value.value_quaternion; - } - void *res = tb_global_add_region(m->mod, global, offset, size); - switch (size) { - case 8: - ((u16 *)res)[0] = f32_to_f16(cast(f32)q.imag); - ((u16 *)res)[1] = f32_to_f16(cast(f32)q.jmag); - ((u16 *)res)[2] = f32_to_f16(cast(f32)q.kmag); - ((u16 *)res)[3] = f32_to_f16(cast(f32)q.real); - break; - case 16: - ((f32 *)res)[0] = cast(f32)q.imag; - ((f32 *)res)[1] = cast(f32)q.jmag; - ((f32 *)res)[2] = cast(f32)q.kmag; - ((f32 *)res)[3] = cast(f32)q.real; - break; - case 32: - ((f64 *)res)[0] = cast(f64)q.imag; - ((f64 *)res)[1] = cast(f64)q.jmag; - ((f64 *)res)[2] = cast(f64)q.kmag; - ((f64 *)res)[3] = cast(f64)q.real; - break; - } - } - break; - default: - GB_PANIC("%s", type_to_string(type)); - break; - } - return true; -} - - -gb_internal TB_Global *cg_global_const_comp_literal(cgModule *m, Type *original_type, ExactValue const &value, TB_Global *global, i64 base_offset) { - GB_ASSERT(value.kind == ExactValue_Compound); - Ast *value_compound = value.value_compound; - ast_node(cl, CompoundLit, value_compound); - - TEMPORARY_ALLOCATOR_GUARD(); - - if (global == nullptr) { - char name[32] = {}; - gb_snprintf(name, 31, "complit$%u", 1+m->const_nil_guid.fetch_add(1)); - global = tb_global_create(m->mod, -1, name, cg_debug_type(m, original_type), TB_LINKAGE_PRIVATE); - i64 size = type_size_of(original_type); - i64 align = type_align_of(original_type); - - // READ ONLY? - TB_ModuleSectionHandle section = 0; - if (is_type_string(original_type) || is_type_cstring(original_type)) { - section = tb_module_get_rdata(m->mod); - } else { - section = tb_module_get_data(m->mod); - } - - if (cl->elems.count == 0) { - tb_global_set_storage(m->mod, section, global, size, align, 0); - return global; - } - - - isize global_region_count = cg_global_const_calculate_region_count(value, original_type); - tb_global_set_storage(m->mod, section, global, size, align, global_region_count); - } - - if (cl->elems.count == 0) { - return global; - } - - - Type *bt = base_type(original_type); - i64 bt_size = type_size_of(bt); - - switch (bt->kind) { - case Type_Struct: - if (cl->elems[0]->kind == Ast_FieldValue) { - isize elem_count = cl->elems.count; - for (isize i = 0; i < elem_count; i++) { - ast_node(fv, FieldValue, cl->elems[i]); - String name = fv->field->Ident.token.string; - - TypeAndValue tav = fv->value->tav; - GB_ASSERT(tav.mode != Addressing_Invalid); - ExactValue value = tav.value; - - Selection sel = lookup_field(bt, name, false); - GB_ASSERT(!sel.indirect); - - if (!cg_is_nested_possibly_constant(bt, sel, fv->value)) { - continue; - } - - i64 offset = type_offset_of_from_selection(bt, sel); - cg_global_const_add_region(m, value, sel.entity->type, global, base_offset+offset); - } - } else { - for_array(i, cl->elems) { - i64 field_index = i; - Ast *elem = cl->elems[i]; - TypeAndValue tav = elem->tav; - Entity *f = bt->Struct.fields[field_index]; - if (!cg_elem_type_can_be_constant(f->type)) { - continue; - } - - i64 offset = bt->Struct.offsets[field_index]; - - ExactValue value = {}; - if (tav.mode != Addressing_Invalid) { - value = tav.value; - } - cg_global_const_add_region(m, value, f->type, global, base_offset+offset); - } - } - return global; - - case Type_Array: - case Type_EnumeratedArray: - case Type_SimdVector: - if (cl->elems[0]->kind == Ast_FieldValue) { - Type *et = base_array_type(bt); - i64 elem_size = type_size_of(et); - for (Ast *elem : cl->elems) { - ast_node(fv, FieldValue, elem); - - ExactValue const &value = fv->value->tav.value; - - if (is_ast_range(fv->field)) { - ast_node(ie, BinaryExpr, fv->field); - TypeAndValue lo_tav = ie->left->tav; - TypeAndValue hi_tav = ie->right->tav; - GB_ASSERT(lo_tav.mode == Addressing_Constant); - GB_ASSERT(hi_tav.mode == Addressing_Constant); - - TokenKind op = ie->op.kind; - i64 lo = exact_value_to_i64(lo_tav.value); - i64 hi = exact_value_to_i64(hi_tav.value); - if (op != Token_RangeHalf) { - hi += 1; - } - - for (i64 i = lo; i < hi; i++) { - i64 offset = i * elem_size; - cg_global_const_add_region(m, value, et, global, base_offset+offset); - } - } else { - TypeAndValue index_tav = fv->field->tav; - GB_ASSERT(index_tav.mode == Addressing_Constant); - i64 i = exact_value_to_i64(index_tav.value); - i64 offset = i * elem_size; - cg_global_const_add_region(m, value, et, global, base_offset+offset); - } - } - } else { - Type *et = base_array_type(bt); - i64 elem_size = type_size_of(et); - i64 offset = 0; - for (Ast *elem : cl->elems) { - ExactValue const &value = elem->tav.value; - cg_global_const_add_region(m, value, et, global, base_offset+offset); - offset += elem_size; - } - } - - return global; - - case Type_BitSet: - if (bt_size > 0) { - BigInt bits = {}; - BigInt one = {}; - big_int_from_u64(&one, 1); - - for_array(i, cl->elems) { - Ast *e = cl->elems[i]; - GB_ASSERT(e->kind != Ast_FieldValue); - - TypeAndValue tav = e->tav; - if (tav.mode != Addressing_Constant) { - continue; - } - GB_ASSERT(tav.value.kind == ExactValue_Integer); - i64 v = big_int_to_i64(&tav.value.value_integer); - i64 lower = bt->BitSet.lower; - u64 index = cast(u64)(v-lower); - BigInt bit = {}; - big_int_from_u64(&bit, index); - big_int_shl(&bit, &one, &bit); - big_int_or(&bits, &bits, &bit); - } - - void *dst = tb_global_add_region(m->mod, global, base_offset, bt_size); - cg_write_big_int_at_ptr(dst, &bits, original_type); - } - return global; - - case Type_Matrix: - GB_PANIC("TODO(bill): constant compound literal for %s", type_to_string(original_type)); - break; - - case Type_Slice: - { - i64 count = gb_max(cl->elems.count, cl->max_count); - Type *elem = bt->Slice.elem; - Type *t = alloc_type_array(elem, count); - TB_Global *backing_array = cg_global_const_comp_literal(m, t, value, nullptr, 0); - - tb_global_add_symbol_reloc(m->mod, global, base_offset+0, cast(TB_Symbol *)backing_array); - - void *len_ptr = tb_global_add_region(m->mod, global, base_offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); - } - return global; - } - - GB_PANIC("TODO(bill): constant compound literal for %s", type_to_string(original_type)); - return nullptr; -} - - -gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) { - GB_ASSERT(p != nullptr); - TB_Node *node = nullptr; - - if (is_type_untyped(type)) { - // TODO(bill): THIS IS A COMPLETE HACK, WHY DOES THIS NOT A TYPE? - GB_ASSERT(type->kind == Type_Basic); - switch (type->Basic.kind) { - case Basic_UntypedBool: - type = t_bool; - break; - case Basic_UntypedInteger: - type = t_i64; - break; - case Basic_UntypedFloat: - type = t_f64; - break; - case Basic_UntypedComplex: - type = t_complex128; - break; - case Basic_UntypedQuaternion: - type = t_quaternion256; - break; - case Basic_UntypedString: - type = t_string; - break; - case Basic_UntypedRune: - type = t_rune; - break; - case Basic_UntypedNil: - case Basic_UntypedUninit: - return cg_value(cast(TB_Node *)nullptr, type); - } - } - TB_DataType dt = cg_data_type(type); - - switch (value.kind) { - case ExactValue_Invalid: - return cg_const_nil(p, type); - - case ExactValue_Typeid: - return cg_typeid(p, value.value_typeid); - - case ExactValue_Procedure: - { - Ast *expr = unparen_expr(value.value_procedure); - if (expr->kind == Ast_ProcLit) { - cgProcedure *anon = cg_procedure_generate_anonymous(p->module, expr, p); - TB_Node *ptr = tb_inst_get_symbol_address(p->func, anon->symbol); - GB_ASSERT(are_types_identical(type, anon->type)); - return cg_value(ptr, type); - } - - Entity *e = entity_of_node(expr); - if (e != nullptr) { - TB_Symbol *found = cg_find_symbol_from_entity(p->module, e); - GB_ASSERT_MSG(found != nullptr, "could not find '%.*s'", LIT(e->token.string)); - TB_Node *ptr = tb_inst_get_symbol_address(p->func, found); - GB_ASSERT(type != nullptr); - GB_ASSERT(are_types_identical(type, e->type)); - return cg_value(ptr, type); - } - - GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure %s", expr_to_string(expr)); - } - break; - } - - switch (value.kind) { - case ExactValue_Bool: - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type); - - case ExactValue_Integer: - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - // GB_ASSERT(dt.raw != TB_TYPE_I128.raw); - if (is_type_unsigned(type)) { - u64 i = 0; - if (value.kind == ExactValue_Integer && value.value_integer.sign) { - i = exact_value_to_i64(value); - } else { - i = exact_value_to_u64(value); - } - return cg_value(tb_inst_uint(p->func, dt, i), type); - } else { - i64 i = exact_value_to_i64(value); - return cg_value(tb_inst_sint(p->func, dt, i), type); - } - break; - - case ExactValue_Float: - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - GB_ASSERT(dt.raw != TB_TYPE_F16.raw); - GB_ASSERT(!is_type_different_to_arch_endianness(type)); - { - f64 f = exact_value_to_f64(value); - if (type_size_of(type) == 8) { - return cg_value(tb_inst_float64(p->func, f), type); - } else { - return cg_value(tb_inst_float32(p->func, cast(f32)f), type); - } - } - break; - - case ExactValue_String: - { - GB_ASSERT(is_type_string(type)); - cgModule *m = p->module; - - String str = value.value_string; - - char name[32] = {}; - gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1)); - TB_Global *cstr_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - - i64 size = str.len+1; - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), cstr_global, size, 1, 1); - u8 *data = cast(u8 *)tb_global_add_region(m->mod, cstr_global, 0, size); - gb_memcopy(data, str.text, str.len); - data[str.len] = 0; - - if (is_type_cstring(type)) { - cgValue s = cg_value(cstr_global, type); - return cg_flatten_value(p, s); - } - - gb_snprintf(name, 31, "str$%u", 1+m->const_nil_guid.fetch_add(1)); - TB_Global *str_global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, type_size_of(type), type_align_of(type), 2); - - tb_global_add_symbol_reloc(m->mod, str_global, 0, cast(TB_Symbol *)cstr_global); - void *len_ptr = tb_global_add_region(m->mod, str_global, build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, str.len, t_int); - - TB_Node *s = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)str_global); - return cg_lvalue_addr(s, type); - - } - - case ExactValue_Pointer: - return cg_value(tb_inst_uint(p->func, dt, exact_value_to_u64(value)), type); - - case ExactValue_Compound: - { - TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_comp_literal(p->module, type, value, nullptr, 0); - TB_Node *node = tb_inst_get_symbol_address(p->func, symbol); - return cg_lvalue_addr(node, type); - } - break; - } - - - GB_ASSERT(node != nullptr); - return cg_value(node, type); -} - -gb_internal cgValue cg_const_int(cgProcedure *p, Type *type, i64 i) { - return cg_const_value(p, type, exact_value_i64(i)); -} -gb_internal cgValue cg_const_bool(cgProcedure *p, Type *type, bool v) { - return cg_value(tb_inst_bool(p->func, v), type); -} - -gb_internal cgValue cg_const_string(cgProcedure *p, Type *type, String const &str) { - return cg_const_value(p, type, exact_value_string(str)); -} - -gb_internal cgValue cg_const_union_tag(cgProcedure *p, Type *u, Type *v) { - return cg_const_value(p, union_tag_type(u), exact_value_i64(union_variant_index(u, v))); -} - diff --git a/src/tilde_debug.cpp b/src/tilde_debug.cpp deleted file mode 100644 index a4b82bf72..000000000 --- a/src/tilde_debug.cpp +++ /dev/null @@ -1,482 +0,0 @@ -gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type); -gb_internal TB_DebugType *cg_debug_type(cgModule *m, Type *type) { - type = reduce_tuple_to_single_type(type); - - mutex_lock(&m->debug_type_mutex); - defer (mutex_unlock(&m->debug_type_mutex)); - TB_DebugType **found = map_get(&m->debug_type_map, type); - if (found) { - return *found; - } - - TB_DebugType *res = cg_debug_type_internal(m, type); - map_set(&m->debug_type_map, type, res); - return res; -} - -gb_internal TB_DebugType *cg_debug_type_for_proc(cgModule *m, Type *type) { - GB_ASSERT(is_type_proc(type)); - TB_DebugType **func_found = nullptr; - TB_DebugType *func_ptr = cg_debug_type(m, type); - GB_ASSERT(func_ptr != nullptr); - - mutex_lock(&m->debug_type_mutex); - func_found = map_get(&m->proc_debug_type_map, type); - mutex_unlock(&m->debug_type_mutex); - GB_ASSERT(func_found != nullptr); - return *func_found; -} - - -gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, String const &record_name) { - Type *bt = base_type(type); - switch (bt->kind) { - case Type_Struct: - { - type_set_offsets(bt); - - TB_DebugType *record = nullptr; - if (bt->Struct.is_raw_union) { - record = tb_debug_create_union(m->mod, record_name.len, cast(char const *)record_name.text); - } else { - record = tb_debug_create_struct(m->mod, record_name.len, cast(char const *)record_name.text); - } - if (record_name.len != 0) { - map_set(&m->debug_type_map, type, record); - } - - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, bt->Struct.fields.count); - for_array(i, bt->Struct.fields) { - Entity *e = bt->Struct.fields[i]; - Type *type = e->type; - if (is_type_proc(type)) { - type = t_rawptr; - } - TB_DebugType *field_type = cg_debug_type(m, type); - String name = e->token.string; - TB_CharUnits offset = cast(TB_CharUnits)bt->Struct.offsets[i]; - if (name.len == 0) { - name = str_lit("_"); - } - - fields[i] = tb_debug_create_field(m->mod, field_type, name.len, cast(char const *)name.text, offset); - } - tb_debug_record_end( - record, - cast(TB_CharUnits)type_size_of(type), - cast(TB_CharUnits)type_align_of(type) - ); - return record; - } - break; - - case Type_Tuple: - { - GB_ASSERT(record_name.len == 0); - type_set_offsets(bt); - - TB_DebugType *record = tb_debug_create_struct(m->mod, 0, ""); - isize record_count = 0; - for (Entity *e : bt->Tuple.variables) { - if (e->kind == Entity_Variable) { - record_count += 1; - } - } - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, record_count); - for_array(i, bt->Tuple.variables) { - Entity *e = bt->Tuple.variables[i]; - if (e->kind != Entity_Variable) { - continue; - } - Type *type = e->type; - if (is_type_proc(type)) { - type = t_rawptr; - } - TB_DebugType *field_type = cg_debug_type(m, type); - String name = e->token.string; - TB_CharUnits offset = cast(TB_CharUnits)bt->Tuple.offsets[i]; - if (name.len == 0) { - name = str_lit("_"); - } - - fields[i] = tb_debug_create_field(m->mod, field_type, name.len, cast(char const *)name.text, offset); - } - tb_debug_record_end( - record, - cast(TB_CharUnits)type_size_of(type), - cast(TB_CharUnits)type_align_of(type) - ); - return record; - } - break; - case Type_Union: - { - TB_DebugType *record = tb_debug_create_struct(m->mod, record_name.len, cast(char const *)record_name.text); - if (record_name.len != 0) { - map_set(&m->debug_type_map, type, record); - } - - i64 variant_count = bt->Union.variants.count; - if (is_type_union_maybe_pointer(bt)) { - // NO TAG - GB_ASSERT(variant_count == 1); - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, variant_count); - TB_DebugType *variant_type = cg_debug_type(m, bt->Union.variants[0]); - fields[0] = tb_debug_create_field(m->mod, variant_type, -1, "v0", 0); - tb_debug_record_end( - record, - cast(TB_CharUnits)type_size_of(type), - cast(TB_CharUnits)type_align_of(type) - ); - } else { - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, variant_count+1); - for_array(i, bt->Union.variants) { - Type *v = bt->Union.variants[i]; - TB_DebugType *variant_type = cg_debug_type(m, v); - char name[32] = {}; - u32 v_index = cast(u32)i; - if (bt->Union.kind != UnionType_no_nil) { - v_index += 1; - } - gb_snprintf(name, 31, "v%u", v_index); - fields[i] = tb_debug_create_field(m->mod, variant_type, -1, name, 0); - } - - TB_DebugType *tag_type = cg_debug_type(m, union_tag_type(bt)); - fields[variant_count] = tb_debug_create_field(m->mod, tag_type, -1, "tag", cast(TB_CharUnits)bt->Union.variant_block_size); - - } - tb_debug_record_end( - record, - cast(TB_CharUnits)type_size_of(type), - cast(TB_CharUnits)type_align_of(type) - ); - return record; - } - break; - } - return nullptr; -} - - -gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { - if (type == nullptr) { - return tb_debug_get_void(m->mod); - } - Type *original_type = type; - if (type->kind == Type_Named) { - String name = type->Named.name; - TB_DebugType *res = cg_debug_type_internal_record(m, type, name); - if (res) { - return res; - } - type = base_type(type->Named.base); - } - - TB_CharUnits int_size = cast(TB_CharUnits)build_context.int_size; - TB_CharUnits ptr_size = cast(TB_CharUnits)build_context.ptr_size; - TB_CharUnits size = cast(TB_CharUnits)type_size_of(type); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(type); - int bits = cast(int)(8*size); - bool is_signed = is_type_integer(core_type(type)) && !is_type_unsigned(core_type(type)); - - switch (type->kind) { - case Type_Basic: - switch (type->Basic.kind) { - case Basic_bool: return tb_debug_get_bool(m->mod); - case Basic_b8: return tb_debug_get_bool(m->mod); - case Basic_b16: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_b32: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_b64: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i8: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u8: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i16: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u16: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i32: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u32: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i64: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u64: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i128: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u128: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_rune: return tb_debug_get_integer(m->mod, is_signed, bits); - - case Basic_f16: return tb_debug_get_integer(m->mod, false, bits); - case Basic_f32: return tb_debug_get_float(m->mod, TB_FLT_32); - case Basic_f64: return tb_debug_get_float(m->mod, TB_FLT_64); - - case Basic_complex32: - case Basic_complex64: - case Basic_complex128: - { - String name = basic_types[type->Basic.kind].Basic.name; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - Type *et = base_complex_elem_type(type); - TB_CharUnits elem_size = cast(TB_CharUnits)type_size_of(et); - TB_DebugType *elem = cg_debug_type(m, et); - - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); - fields[0] = tb_debug_create_field(m->mod, elem, -1, "real", 0*elem_size); - fields[1] = tb_debug_create_field(m->mod, elem, -1, "imag", 1*elem_size); - - tb_debug_record_end(record, size, align); - return record; - } - case Basic_quaternion64: - case Basic_quaternion128: - case Basic_quaternion256: - { - String name = basic_types[type->Basic.kind].Basic.name; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - Type *et = base_complex_elem_type(type); - TB_CharUnits elem_size = cast(TB_CharUnits)type_size_of(et); - TB_DebugType *elem = cg_debug_type(m, et); - - // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 4); - fields[0] = tb_debug_create_field(m->mod, elem, -1, "imag", 0*elem_size); - fields[1] = tb_debug_create_field(m->mod, elem, -1, "jmag", 1*elem_size); - fields[2] = tb_debug_create_field(m->mod, elem, -1, "kmag", 2*elem_size); - fields[3] = tb_debug_create_field(m->mod, elem, -1, "real", 3*elem_size); - - tb_debug_record_end(record, size, align); - return record; - } - - case Basic_int: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_uint: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_uintptr: return tb_debug_get_integer(m->mod, is_signed, bits); - - case Basic_rawptr: - return tb_debug_create_ptr(m->mod, tb_debug_get_void(m->mod)); - case Basic_string: - { - String name = basic_types[type->Basic.kind].Basic.name; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); - fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, t_u8_ptr), -1, "data", 0*int_size); - fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); - - tb_debug_record_end(record, size, align); - return record; - } - case Basic_cstring: - return tb_debug_create_ptr(m->mod, tb_debug_get_integer(m->mod, false, 8)); - - case Basic_any: - { - String name = basic_types[type->Basic.kind].Basic.name; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); - fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, t_rawptr), -1, "data", 0*ptr_size); - fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_typeid), -1, "id", 1*ptr_size); - - tb_debug_record_end(record, size, align); - return record; - } - case Basic_typeid: return tb_debug_get_integer(m->mod, false, bits); - - case Basic_i16le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u16le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i32le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u32le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i64le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u64le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i128le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u128le: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i16be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u16be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i32be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u32be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i64be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u64be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_i128be: return tb_debug_get_integer(m->mod, is_signed, bits); - case Basic_u128be: return tb_debug_get_integer(m->mod, is_signed, bits); - - case Basic_f16le: return tb_debug_get_integer(m->mod, false, bits); - case Basic_f32le: return tb_debug_get_float(m->mod, TB_FLT_32); - case Basic_f64le: return tb_debug_get_float(m->mod, TB_FLT_64); - case Basic_f16be: return tb_debug_get_integer(m->mod, false, bits); - case Basic_f32be: return tb_debug_get_float(m->mod, TB_FLT_32); - case Basic_f64be: return tb_debug_get_float(m->mod, TB_FLT_64); - } - break; - case Type_Generic: - GB_PANIC("SHOULD NEVER HIT"); - break; - case Type_Pointer: - return tb_debug_create_ptr(m->mod, cg_debug_type(m, type->Pointer.elem)); - case Type_MultiPointer: - return tb_debug_create_ptr(m->mod, cg_debug_type(m, type->MultiPointer.elem)); - case Type_Array: - return tb_debug_create_array(m->mod, cg_debug_type(m, type->Array.elem), type->Array.count); - case Type_EnumeratedArray: - return tb_debug_create_array(m->mod, cg_debug_type(m, type->EnumeratedArray.elem), type->EnumeratedArray.count); - case Type_Slice: - { - String name = {}; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); - fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->Slice.elem)), -1, "data", 0*int_size); - fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); - - tb_debug_record_end(record, size, align); - return record; - } - case Type_DynamicArray: - { - String name = {}; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 4); - fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->Slice.elem)), -1, "data", 0*int_size); - fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); - fields[2] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "cap", 2*int_size); - fields[3] = tb_debug_create_field(m->mod, cg_debug_type(m, t_allocator), -1, "allocator", 3*int_size); - - tb_debug_record_end(record, size, align); - return record; - } - case Type_Map: - return cg_debug_type(m, t_raw_map); - - case Type_Struct: - case Type_Tuple: - case Type_Union: - return cg_debug_type_internal_record(m, type, {}); - - case Type_Enum: - return tb_debug_get_integer(m->mod, is_signed, bits); - - case Type_Proc: - { - TypeProc *pt = &type->Proc; - isize param_count = 0; - isize return_count = 0; - - bool is_odin_cc = is_calling_convention_odin(pt->calling_convention); - - if (pt->params) for (Entity *e : pt->params->Tuple.variables) { - if (e->kind == Entity_Variable) { - param_count += 1; - } - } - - if (pt->result_count > 0) { - if (is_odin_cc) { - // Split returns - param_count += pt->result_count-1; - return_count = 1; - } else { - return_count = 1; - } - } - - if (pt->calling_convention == ProcCC_Odin) { - // `context` ptr - param_count += 1; - } - - TB_CallingConv tb_cc = TB_CDECL; - if (pt->calling_convention == ProcCC_StdCall) { - tb_cc = TB_STDCALL; - } - TB_DebugType *func = tb_debug_create_func(m->mod, tb_cc, param_count, return_count, pt->c_vararg); - - map_set(&m->proc_debug_type_map, original_type, func); - map_set(&m->proc_debug_type_map, type, func); - - TB_DebugType *func_ptr = tb_debug_create_ptr(m->mod, func); - map_set(&m->debug_type_map, original_type, func_ptr); - map_set(&m->debug_type_map, type, func_ptr); - - TB_DebugType **params = tb_debug_func_params(func); - TB_DebugType **returns = tb_debug_func_returns(func); - - isize param_index = 0; - isize return_index = 0; - if (pt->params) for (Entity *e : pt->params->Tuple.variables) { - if (e->kind == Entity_Variable) { - Type *type = e->type; - if (is_type_proc(type)) { - type = t_rawptr; - } - String name = e->token.string; - if (name.len == 0) { - name = str_lit("_"); - } - params[param_index++] = tb_debug_create_field(m->mod, cg_debug_type(m, type), name.len, cast(char const *)name.text, 0); - } - } - - if (pt->result_count) { - GB_ASSERT(pt->results); - if (is_odin_cc) { - // Split Returns - for (isize i = 0; i < pt->results->Tuple.variables.count-1; i++) { - Entity *e = pt->results->Tuple.variables[i]; - GB_ASSERT(e->kind == Entity_Variable); - Type *type = e->type; - if (is_type_proc(e->type)) { - type = t_rawptr; - } - type = alloc_type_pointer(type); - - String name = e->token.string; - if (name.len == 0) { - name = str_lit("_"); - } - params[param_index++] = tb_debug_create_field(m->mod, cg_debug_type(m, type), name.len, cast(char const *)name.text, 0); - } - - Type *last_type = pt->results->Tuple.variables[pt->results->Tuple.variables.count-1]->type; - if (is_type_proc(last_type)) { - last_type = t_rawptr; - } - returns[return_index++] = cg_debug_type(m, last_type); - } else { - returns[return_index++] = cg_debug_type(m, pt->results); - } - } - - if (pt->calling_convention == ProcCC_Odin) { - Type *type = t_context_ptr; - String name = str_lit("__.context_ptr"); - params[param_index++] = tb_debug_create_field(m->mod, cg_debug_type(m, type), name.len, cast(char const *)name.text, 0); - } - - GB_ASSERT_MSG(param_index == param_count, "%td vs %td for %s", param_index, param_count, type_to_string(type)); - GB_ASSERT_MSG(return_index == return_count, "%td vs %td for %s", return_index, return_count, type_to_string(type)); - - return func_ptr; - } - break; - case Type_BitSet: - return cg_debug_type(m, bit_set_to_int(type)); - case Type_SimdVector: - return tb_debug_create_array(m->mod, cg_debug_type(m, type->SimdVector.elem), type->SimdVector.count); - case Type_RelativePointer: - return cg_debug_type(m, type->RelativePointer.base_integer); - case Type_RelativeMultiPointer: - return cg_debug_type(m, type->RelativeMultiPointer.base_integer); - case Type_Matrix: - { - i64 count = matrix_type_total_internal_elems(type); - return tb_debug_create_array(m->mod, cg_debug_type(m, type->Matrix.elem), count); - } - case Type_SoaPointer: - { - String name = {}; - TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); - fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->SoaPointer.elem)), -1, "ptr", 0*int_size); - fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "offset", 1*int_size); - - tb_debug_record_end(record, size, align); - return record; - } - } - - // TODO(bill): cg_debug_type - return tb_debug_get_void(m->mod); -} diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp deleted file mode 100644 index 236d0cf7d..000000000 --- a/src/tilde_expr.cpp +++ /dev/null @@ -1,3961 +0,0 @@ -gb_internal cgValue cg_flatten_value(cgProcedure *p, cgValue value) { - GB_ASSERT(value.kind != cgValue_Multi); - if (value.kind == cgValue_Symbol) { - GB_ASSERT(is_type_internally_pointer_like(value.type)); - return cg_value(tb_inst_get_symbol_address(p->func, value.symbol), value.type); - } else if (value.kind == cgValue_Addr) { - // TODO(bill): Is this a good idea? - // this converts an lvalue to an rvalue if trivially possible - TB_DataType dt = cg_data_type(value.type); - if (!TB_IS_VOID_TYPE(dt)) { - TB_CharUnits align = cast(TB_CharUnits)type_align_of(value.type); - return cg_value(tb_inst_load(p->func, dt, value.node, align, false), value.type); - } - } - return value; -} - -gb_internal cgValue cg_emit_select(cgProcedure *p, cgValue const &cond, cgValue const &x, cgValue const &y) { - GB_ASSERT(x.kind == y.kind); - GB_ASSERT(cond.kind == cgValue_Value); - cgValue res = x; - res.node = tb_inst_select(p->func, cond.node, x.node, y.node); - return res; -} - - -gb_internal bool cg_is_expr_untyped_const(Ast *expr) { - auto const &tv = type_and_value_of_expr(expr); - if (is_type_untyped(tv.type)) { - return tv.value.kind != ExactValue_Invalid; - } - return false; -} -gb_internal cgValue cg_expr_untyped_const_to_typed(cgProcedure *p, Ast *expr, Type *t) { - GB_ASSERT(is_type_typed(t)); - auto const &tv = type_and_value_of_expr(expr); - return cg_const_value(p, t, tv.value); -} - -gb_internal cgContextData *cg_push_context_onto_stack(cgProcedure *p, cgAddr ctx) { - ctx.kind = cgAddr_Context; - cgContextData *cd = array_add_and_get(&p->context_stack); - cd->ctx = ctx; - cd->scope_index = p->scope_index; - return cd; -} - -gb_internal cgAddr cg_find_or_generate_context_ptr(cgProcedure *p) { - if (p->context_stack.count > 0) { - return p->context_stack[p->context_stack.count-1].ctx; - } - - Type *pt = base_type(p->type); - GB_ASSERT(pt->kind == Type_Proc); - GB_ASSERT(pt->Proc.calling_convention != ProcCC_Odin); - - cgAddr c = cg_add_local(p, t_context, nullptr, true); - tb_function_attrib_variable(p->func, c.addr.node, nullptr, -1, "context", cg_debug_type(p->module, t_context)); - c.kind = cgAddr_Context; - // lb_emit_init_context(p, c); - cg_push_context_onto_stack(p, c); - // lb_add_debug_context_variable(p, c); - - return c; -} - -gb_internal cgValue cg_find_value_from_entity(cgModule *m, Entity *e) { - e = strip_entity_wrapping(e); - GB_ASSERT(e != nullptr); - - GB_ASSERT(e->token.string != "_"); - - if (e->kind == Entity_Procedure) { - return cg_find_procedure_value_from_entity(m, e); - } - - cgValue *found = nullptr; - rw_mutex_shared_lock(&m->values_mutex); - found = map_get(&m->values, e); - rw_mutex_shared_unlock(&m->values_mutex); - if (found) { - return *found; - } - - GB_PANIC("\n\tError in: %s, missing value '%.*s'\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); - return {}; -} - -gb_internal cgValue cg_get_using_variable(cgProcedure *p, Entity *e) { - GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); - String name = e->token.string; - Entity *parent = e->using_parent; - Selection sel = lookup_field(parent->type, name, false); - GB_ASSERT(sel.entity != nullptr); - cgValue *pv = map_get(&p->module->values, parent); - - cgValue v = {}; - - if (pv == nullptr && parent->flags & EntityFlag_SoaPtrField) { - // NOTE(bill): using SOA value (probably from for-in statement) - GB_PANIC("TODO(bill): cg_get_soa_variable_addr"); - // cgAddr parent_addr = cg_get_soa_variable_addr(p, parent); - // v = cg_addr_get_ptr(p, parent_addr); - } else if (pv != nullptr) { - v = *pv; - } else { - GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s %.*s", LIT(e->token.string), LIT(name)); - v = cg_build_addr_ptr(p, e->using_expr); - } - GB_ASSERT(v.node != nullptr); - GB_ASSERT_MSG(parent->type == type_deref(v.type), "%s %s", type_to_string(parent->type), type_to_string(v.type)); - cgValue ptr = cg_emit_deep_field_gep(p, v, sel); - // if (parent->scope) { - // if ((parent->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { - // cg_add_debug_local_variable(p, ptr.value, e->type, e->token); - // } - // } else { - // cg_add_debug_local_variable(p, ptr.value, e->type, e->token); - // } - return ptr; -} -gb_internal cgAddr cg_build_addr_from_entity(cgProcedure *p, Entity *e, Ast *expr) { - GB_ASSERT(e != nullptr); - if (e->kind == Entity_Constant) { - Type *t = default_type(type_of_expr(expr)); - cgValue v = cg_const_value(p, t, e->Constant.value); - GB_PANIC("TODO(bill): cg_add_global_generated"); - // return cg_add_global_generated(p->module, t, v); - return {}; - } - - cgAddr *local_found = map_get(&p->variable_map, e); - if (local_found) { - return *local_found; - } - - cgValue v = {}; - - cgModule *m = p->module; - - rw_mutex_lock(&m->values_mutex); - cgValue *found = map_get(&m->values, e); - rw_mutex_unlock(&m->values_mutex); - if (found) { - v = *found; - } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { - // NOTE(bill): Calculate the using variable every time - v = cg_get_using_variable(p, e); - } else if (e->flags & EntityFlag_SoaPtrField) { - return map_must_get(&p->soa_values_map, e); - } - - - if (v.node == nullptr) { - cgValue v = cg_find_value_from_entity(m, e); - v = cg_flatten_value(p, v); - return cg_addr(v); - } - - return cg_addr(v); -} - -gb_internal cgValue cg_emit_union_tag_ptr(cgProcedure *p, cgValue const &parent_ptr) { - Type *t = parent_ptr.type; - Type *ut = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_pointer(t), "%s", type_to_string(t)); - GB_ASSERT_MSG(ut->kind == Type_Union, "%s", type_to_string(t)); - - GB_ASSERT(!is_type_union_maybe_pointer_original_alignment(ut)); - GB_ASSERT(!is_type_union_maybe_pointer(ut)); - GB_ASSERT(type_size_of(ut) > 0); - - Type *tag_type = union_tag_type(ut); - i64 tag_offset = ut->Union.variant_block_size; - - GB_ASSERT(parent_ptr.kind == cgValue_Value); - TB_Node *ptr = parent_ptr.node; - TB_Node *tag_ptr = tb_inst_member_access(p->func, ptr, tag_offset); - return cg_value(tag_ptr, alloc_type_pointer(tag_type)); -} - - - -gb_internal cgValue cg_correct_endianness(cgProcedure *p, cgValue value) { - Type *src = core_type(value.type); - GB_ASSERT(is_type_integer(src) || is_type_float(src)); - if (is_type_different_to_arch_endianness(src)) { - GB_PANIC("TODO(bill): cg_correct_endianness"); - // Type *platform_src_type = integer_endian_type_to_platform_type(src); - // value = cg_emit_byte_swap(p, value, platform_src_type); - } - return value; -} - -gb_internal cgValue cg_emit_transmute(cgProcedure *p, cgValue value, Type *type) { - GB_ASSERT(type_size_of(value.type) == type_size_of(type)); - - value = cg_flatten_value(p, value); - - if (are_types_identical(value.type, type)) { - return value; - } - if (are_types_identical(core_type(value.type), core_type(type))) { - value.type = type; - return value; - } - - i64 src_align = type_align_of(value.type); - i64 dst_align = type_align_of(type); - - if (dst_align > src_align) { - cgAddr local = cg_add_local(p, type, nullptr, false); - cgValue dst = local.addr; - dst.type = alloc_type_pointer(value.type); - cg_emit_store(p, dst, value); - return cg_addr_load(p, local); - } - - TB_DataType dt = cg_data_type(type); - switch (value.kind) { - case cgValue_Value: - GB_ASSERT_MSG(!TB_IS_VOID_TYPE(dt), "%d %s -> %s", dt.type, type_to_string(value.type), type_to_string(type)); - value.type = type; - if (value.node->dt.raw != dt.raw) { - switch (value.node->dt.type) { - case TB_INT: - switch (value.node->dt.type) { - case TB_INT: - break; - case TB_FLOAT: - value.node = tb_inst_bitcast(p->func, value.node, dt); - break; - case TB_PTR: - value.node = tb_inst_int2ptr(p->func, value.node); - break; - } - break; - case TB_FLOAT: - switch (value.node->dt.type) { - case TB_INT: - value.node = tb_inst_bitcast(p->func, value.node, dt); - break; - case TB_FLOAT: - break; - case TB_PTR: - value.node = tb_inst_bitcast(p->func, value.node, TB_TYPE_INTPTR); - value.node = tb_inst_int2ptr(p->func, value.node); - break; - } - break; - case TB_PTR: - switch (value.node->dt.type) { - case TB_INT: - value.node = tb_inst_ptr2int(p->func, value.node, dt); - break; - case TB_FLOAT: - value.node = tb_inst_ptr2int(p->func, value.node, TB_TYPE_INTPTR); - value.node = tb_inst_bitcast(p->func, value.node, dt); - break; - case TB_PTR: - break; - } - break; - } - } - return value; - case cgValue_Addr: - value.type = type; - return value; - case cgValue_Symbol: - GB_PANIC("should be handled above"); - break; - case cgValue_Multi: - GB_PANIC("cannot transmute multiple values at once"); - break; - } - return value; - -} -gb_internal cgValue cg_emit_byte_swap(cgProcedure *p, cgValue value, Type *end_type) { - GB_ASSERT(type_size_of(value.type) == type_size_of(end_type)); - - if (type_size_of(value.type) < 2) { - return value; - } - - if (is_type_float(value.type)) { - i64 sz = type_size_of(value.type); - Type *integer_type = nullptr; - switch (sz) { - case 2: integer_type = t_u16; break; - case 4: integer_type = t_u32; break; - case 8: integer_type = t_u64; break; - } - GB_ASSERT(integer_type != nullptr); - value = cg_emit_transmute(p, value, integer_type); - } - - GB_ASSERT(value.kind == cgValue_Value); - - // TODO(bill): bswap - // value.node = tb_inst_bswap(p->func, value.node); - return cg_emit_transmute(p, value, end_type); -} - -gb_internal cgValue cg_emit_comp_records(cgProcedure *p, TokenKind op_kind, cgValue left, cgValue right, Type *type) { - GB_ASSERT((is_type_struct(type) || is_type_union(type)) && is_type_comparable(type)); - cgValue left_ptr = cg_address_from_load_or_generate_local(p, left); - cgValue right_ptr = cg_address_from_load_or_generate_local(p, right); - cgValue res = {}; - if (type_size_of(type) == 0) { - switch (op_kind) { - case Token_CmpEq: - return cg_const_bool(p, t_bool, true); - case Token_NotEq: - return cg_const_bool(p, t_bool, false); - } - GB_PANIC("invalid operator"); - } - TEMPORARY_ALLOCATOR_GUARD(); - if (is_type_simple_compare(type)) { - // TODO(bill): Test to see if this is actually faster!!!! - auto args = slice_make(temporary_allocator(), 3); - args[0] = cg_emit_conv(p, left_ptr, t_rawptr); - args[1] = cg_emit_conv(p, right_ptr, t_rawptr); - args[2] = cg_const_int(p, t_int, type_size_of(type)); - res = cg_emit_runtime_call(p, "memory_equal", args); - } else { - cgProcedure *equal_proc = cg_equal_proc_for_type(p->module, type); - cgValue value = cg_value(tb_inst_get_symbol_address(p->func, equal_proc->symbol), equal_proc->type); - auto args = slice_make(temporary_allocator(), 2); - args[0] = cg_emit_conv(p, left_ptr, t_rawptr); - args[1] = cg_emit_conv(p, right_ptr, t_rawptr); - res = cg_emit_call(p, value, args); - } - if (op_kind == Token_NotEq) { - res = cg_emit_unary_arith(p, Token_Not, res, res.type); - } - return res; -} - -gb_internal cgValue cg_emit_comp(cgProcedure *p, TokenKind op_kind, cgValue left, cgValue right) { - GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)); - - Type *a = core_type(left.type); - Type *b = core_type(right.type); - - cgValue nil_check = {}; - if (is_type_array_like(left.type) || is_type_array_like(right.type)) { - // don't do `nil` check if it is array-like - } else if (is_type_untyped_nil(left.type)) { - nil_check = cg_emit_comp_against_nil(p, op_kind, right); - } else if (is_type_untyped_nil(right.type)) { - nil_check = cg_emit_comp_against_nil(p, op_kind, left); - } - if (nil_check.node != nullptr) { - return nil_check; - } - - if (are_types_identical(a, b)) { - // NOTE(bill): No need for a conversion - } /*else if (cg_is_const(left) || cg_is_const_nil(left)) { - left = cg_emit_conv(p, left, right.type); - } else if (cg_is_const(right) || cg_is_const_nil(right)) { - right = cg_emit_conv(p, right, left.type); - }*/ else { - Type *lt = left.type; - Type *rt = right.type; - - lt = left.type; - rt = right.type; - i64 ls = type_size_of(lt); - i64 rs = type_size_of(rt); - - // NOTE(bill): Quick heuristic, larger types are usually the target type - if (ls < rs) { - left = cg_emit_conv(p, left, rt); - } else if (ls > rs) { - right = cg_emit_conv(p, right, lt); - } else { - if (is_type_union(rt)) { - left = cg_emit_conv(p, left, rt); - } else { - right = cg_emit_conv(p, right, lt); - } - } - } - - a = core_type(left.type); - b = core_type(right.type); - left = cg_flatten_value(p, left); - right = cg_flatten_value(p, right); - - - if (is_type_matrix(a) && (op_kind == Token_CmpEq || op_kind == Token_NotEq)) { - GB_PANIC("TODO(bill): cg_emit_comp matrix"); - // Type *tl = base_type(a); - // lbValue lhs = lb_address_from_load_or_generate_local(p, left); - // lbValue rhs = lb_address_from_load_or_generate_local(p, right); - - - // // TODO(bill): Test to see if this is actually faster!!!! - // auto args = array_make(permanent_allocator(), 3); - // args[0] = lb_emit_conv(p, lhs, t_rawptr); - // args[1] = lb_emit_conv(p, rhs, t_rawptr); - // args[2] = lb_const_int(p->module, t_int, type_size_of(tl)); - // lbValue val = lb_emit_runtime_call(p, "memory_compare", args); - // lbValue res = lb_emit_comp(p, op_kind, val, lb_const_nil(p->module, val.type)); - // return lb_emit_conv(p, res, t_bool); - } - if (is_type_array_like(a)) { - GB_PANIC("TODO(bill): cg_emit_comp is_type_array_like"); - // Type *tl = base_type(a); - // lbValue lhs = lb_address_from_load_or_generate_local(p, left); - // lbValue rhs = lb_address_from_load_or_generate_local(p, right); - - - // TokenKind cmp_op = Token_And; - // lbValue res = lb_const_bool(p->module, t_bool, true); - // if (op_kind == Token_NotEq) { - // res = lb_const_bool(p->module, t_bool, false); - // cmp_op = Token_Or; - // } else if (op_kind == Token_CmpEq) { - // res = lb_const_bool(p->module, t_bool, true); - // cmp_op = Token_And; - // } - - // bool inline_array_arith = lb_can_try_to_inline_array_arith(tl); - // i32 count = 0; - // switch (tl->kind) { - // case Type_Array: count = cast(i32)tl->Array.count; break; - // case Type_EnumeratedArray: count = cast(i32)tl->EnumeratedArray.count; break; - // } - - // if (inline_array_arith) { - // // inline - // lbAddr val = lb_add_local_generated(p, t_bool, false); - // lb_addr_store(p, val, res); - // for (i32 i = 0; i < count; i++) { - // lbValue x = lb_emit_load(p, lb_emit_array_epi(p, lhs, i)); - // lbValue y = lb_emit_load(p, lb_emit_array_epi(p, rhs, i)); - // lbValue cmp = lb_emit_comp(p, op_kind, x, y); - // lbValue new_res = lb_emit_arith(p, cmp_op, lb_addr_load(p, val), cmp, t_bool); - // lb_addr_store(p, val, lb_emit_conv(p, new_res, t_bool)); - // } - - // return lb_addr_load(p, val); - // } else { - // if (is_type_simple_compare(tl) && (op_kind == Token_CmpEq || op_kind == Token_NotEq)) { - // // TODO(bill): Test to see if this is actually faster!!!! - // auto args = array_make(permanent_allocator(), 3); - // args[0] = lb_emit_conv(p, lhs, t_rawptr); - // args[1] = lb_emit_conv(p, rhs, t_rawptr); - // args[2] = lb_const_int(p->module, t_int, type_size_of(tl)); - // lbValue val = lb_emit_runtime_call(p, "memory_compare", args); - // lbValue res = lb_emit_comp(p, op_kind, val, lb_const_nil(p->module, val.type)); - // return lb_emit_conv(p, res, t_bool); - // } else { - // lbAddr val = lb_add_local_generated(p, t_bool, false); - // lb_addr_store(p, val, res); - // auto loop_data = lb_loop_start(p, count, t_i32); - // { - // lbValue i = loop_data.idx; - // lbValue x = lb_emit_load(p, lb_emit_array_ep(p, lhs, i)); - // lbValue y = lb_emit_load(p, lb_emit_array_ep(p, rhs, i)); - // lbValue cmp = lb_emit_comp(p, op_kind, x, y); - // lbValue new_res = lb_emit_arith(p, cmp_op, lb_addr_load(p, val), cmp, t_bool); - // lb_addr_store(p, val, lb_emit_conv(p, new_res, t_bool)); - // } - // lb_loop_end(p, loop_data); - - // return lb_addr_load(p, val); - // } - // } - } - - if ((is_type_struct(a) || is_type_union(a)) && is_type_comparable(a)) { - return cg_emit_comp_records(p, op_kind, left, right, a); - } - - if ((is_type_struct(b) || is_type_union(b)) && is_type_comparable(b)) { - return cg_emit_comp_records(p, op_kind, left, right, b); - } - - if (is_type_string(a)) { - if (is_type_cstring(a)) { - left = cg_emit_conv(p, left, t_string); - right = cg_emit_conv(p, right, t_string); - } - - char const *runtime_procedure = nullptr; - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "string_eq"; break; - case Token_NotEq: runtime_procedure = "string_ne"; break; - case Token_Lt: runtime_procedure = "string_lt"; break; - case Token_Gt: runtime_procedure = "string_gt"; break; - case Token_LtEq: runtime_procedure = "string_le"; break; - case Token_GtEq: runtime_procedure = "string_gt"; break; - } - GB_ASSERT(runtime_procedure != nullptr); - - auto args = slice_make(permanent_allocator(), 2); - args[0] = left; - args[1] = right; - return cg_emit_runtime_call(p, runtime_procedure, args); - } - - if (is_type_complex(a)) { - char const *runtime_procedure = ""; - i64 sz = 8*type_size_of(a); - switch (sz) { - case 32: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex32_eq"; break; - case Token_NotEq: runtime_procedure = "complex32_ne"; break; - } - break; - case 64: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex64_eq"; break; - case Token_NotEq: runtime_procedure = "complex64_ne"; break; - } - break; - case 128: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "complex128_eq"; break; - case Token_NotEq: runtime_procedure = "complex128_ne"; break; - } - break; - } - GB_ASSERT(runtime_procedure != nullptr); - - GB_PANIC("TODO(bill): cg_emit_runtime_call"); - // auto args = array_make(permanent_allocator(), 2); - // args[0] = left; - // args[1] = right; - // return lb_emit_runtime_call(p, runtime_procedure, args); - } - - if (is_type_quaternion(a)) { - char const *runtime_procedure = ""; - i64 sz = 8*type_size_of(a); - switch (sz) { - case 64: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion64_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion64_ne"; break; - } - break; - case 128: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion128_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion128_ne"; break; - } - break; - case 256: - switch (op_kind) { - case Token_CmpEq: runtime_procedure = "quaternion256_eq"; break; - case Token_NotEq: runtime_procedure = "quaternion256_ne"; break; - } - break; - } - GB_ASSERT(runtime_procedure != nullptr); - - GB_PANIC("TODO(bill): cg_emit_runtime_call"); - // auto args = array_make(permanent_allocator(), 2); - // args[0] = left; - // args[1] = right; - // return lb_emit_runtime_call(p, runtime_procedure, args); - } - - if (is_type_bit_set(a)) { - switch (op_kind) { - case Token_Lt: - case Token_LtEq: - case Token_Gt: - case Token_GtEq: - { - Type *it = bit_set_to_int(a); - cgValue lhs = cg_emit_transmute(p, left, it); - cgValue rhs = cg_emit_transmute(p, right, it); - cgValue res = cg_emit_arith(p, Token_And, lhs, rhs, it); - GB_ASSERT(lhs.kind == cgValue_Value); - GB_ASSERT(rhs.kind == cgValue_Value); - GB_ASSERT(res.kind == cgValue_Value); - - if (op_kind == Token_Lt || op_kind == Token_LtEq) { - // (lhs & rhs) == lhs - res = cg_value(tb_inst_cmp_eq(p->func, res.node, lhs.node), t_bool); - } else if (op_kind == Token_Gt || op_kind == Token_GtEq) { - // (lhs & rhs) == rhs - res = cg_value(tb_inst_cmp_eq(p->func, res.node, rhs.node), t_bool); - } - - // NOTE(bill): Strict subsets - if (op_kind == Token_Lt || op_kind == Token_Gt) { - // res &~ (lhs == rhs) - cgValue eq = cg_value(tb_inst_cmp_eq(p->func, lhs.node, rhs.node), t_bool); - res = cg_emit_arith(p, Token_AndNot, res, eq, t_bool); - } - return res; - } - - case Token_CmpEq: - GB_ASSERT(left.kind == cgValue_Value); - GB_ASSERT(right.kind == cgValue_Value); - return cg_value(tb_inst_cmp_eq(p->func, left.node, right.node), t_bool); - case Token_NotEq: - GB_ASSERT(left.kind == cgValue_Value); - GB_ASSERT(right.kind == cgValue_Value); - return cg_value(tb_inst_cmp_ne(p->func, left.node, right.node), t_bool); - } - } - - if (op_kind != Token_CmpEq && op_kind != Token_NotEq) { - Type *t = left.type; - if (is_type_integer(t) && is_type_different_to_arch_endianness(t)) { - Type *platform_type = integer_endian_type_to_platform_type(t); - cgValue x = cg_emit_byte_swap(p, left, platform_type); - cgValue y = cg_emit_byte_swap(p, right, platform_type); - left = x; - right = y; - } else if (is_type_float(t) && is_type_different_to_arch_endianness(t)) { - Type *platform_type = integer_endian_type_to_platform_type(t); - cgValue x = cg_emit_conv(p, left, platform_type); - cgValue y = cg_emit_conv(p, right, platform_type); - left = x; - right = y; - } - } - - a = core_type(left.type); - b = core_type(right.type); - - - if (is_type_integer(a) || - is_type_boolean(a) || - is_type_pointer(a) || - is_type_multi_pointer(a) || - is_type_proc(a) || - is_type_enum(a) || - is_type_typeid(a)) { - TB_Node *lhs = left.node; - TB_Node *rhs = right.node; - TB_Node *res = nullptr; - - bool is_signed = is_type_integer(left.type) && !is_type_unsigned(left.type); - switch (op_kind) { - case Token_CmpEq: res = tb_inst_cmp_eq(p->func, lhs, rhs); break; - case Token_NotEq: res = tb_inst_cmp_ne(p->func, lhs, rhs); break; - case Token_Gt: res = tb_inst_cmp_igt(p->func, lhs, rhs, is_signed); break; - case Token_GtEq: res = tb_inst_cmp_ige(p->func, lhs, rhs, is_signed); break; - case Token_Lt: res = tb_inst_cmp_ilt(p->func, lhs, rhs, is_signed); break; - case Token_LtEq: res = tb_inst_cmp_ile(p->func, lhs, rhs, is_signed); break; - } - - GB_ASSERT(res != nullptr); - return cg_value(res, t_bool); - } else if (is_type_float(a)) { - TB_Node *lhs = left.node; - TB_Node *rhs = right.node; - TB_Node *res = nullptr; - switch (op_kind) { - case Token_CmpEq: res = tb_inst_cmp_eq(p->func, lhs, rhs); break; - case Token_NotEq: res = tb_inst_cmp_ne(p->func, lhs, rhs); break; - case Token_Gt: res = tb_inst_cmp_fgt(p->func, lhs, rhs); break; - case Token_GtEq: res = tb_inst_cmp_fge(p->func, lhs, rhs); break; - case Token_Lt: res = tb_inst_cmp_flt(p->func, lhs, rhs); break; - case Token_LtEq: res = tb_inst_cmp_fle(p->func, lhs, rhs); break; - } - GB_ASSERT(res != nullptr); - return cg_value(res, t_bool); - } else if (is_type_simd_vector(a)) { - GB_PANIC("TODO(bill): #simd vector"); - // LLVMValueRef mask = nullptr; - // Type *elem = base_array_type(a); - // if (is_type_float(elem)) { - // LLVMRealPredicate pred = {}; - // switch (op_kind) { - // case Token_CmpEq: pred = LLVMRealOEQ; break; - // case Token_NotEq: pred = LLVMRealONE; break; - // } - // mask = LLVMBuildFCmp(p->builder, pred, left.value, right.value, ""); - // } else { - // LLVMIntPredicate pred = {}; - // switch (op_kind) { - // case Token_CmpEq: pred = LLVMIntEQ; break; - // case Token_NotEq: pred = LLVMIntNE; break; - // } - // mask = LLVMBuildICmp(p->builder, pred, left.value, right.value, ""); - // } - // GB_ASSERT_MSG(mask != nullptr, "Unhandled comparison kind %s (%s) %.*s %s (%s)", type_to_string(left.type), type_to_string(base_type(left.type)), LIT(token_strings[op_kind]), type_to_string(right.type), type_to_string(base_type(right.type))); - - // /* NOTE(bill, 2022-05-28): - // Thanks to Per Vognsen, sign extending to - // a vector of the same width as the input vector, bit casting to an integer, - // and then comparing against zero is the better option - // See: https://lists.llvm.org/pipermail/llvm-dev/2012-September/053046.html - - // // Example assuming 128-bit vector - - // %1 = <4 x float> ... - // %2 = <4 x float> ... - // %3 = fcmp oeq <4 x float> %1, %2 - // %4 = sext <4 x i1> %3 to <4 x i32> - // %5 = bitcast <4 x i32> %4 to i128 - // %6 = icmp ne i128 %5, 0 - // br i1 %6, label %true1, label %false2 - - // This will result in 1 cmpps + 1 ptest + 1 br - // (even without SSE4.1, contrary to what the mail list states, because of pmovmskb) - - // */ - - // unsigned count = cast(unsigned)get_array_type_count(a); - // unsigned elem_sz = cast(unsigned)(type_size_of(elem)*8); - // LLVMTypeRef mask_type = LLVMVectorType(LLVMIntTypeInContext(p->module->ctx, elem_sz), count); - // mask = LLVMBuildSExtOrBitCast(p->builder, mask, mask_type, ""); - - // LLVMTypeRef mask_int_type = LLVMIntTypeInContext(p->module->ctx, cast(unsigned)(8*type_size_of(a))); - // LLVMValueRef mask_int = LLVMBuildBitCast(p->builder, mask, mask_int_type, ""); - // res.value = LLVMBuildICmp(p->builder, LLVMIntNE, mask_int, LLVMConstNull(LLVMTypeOf(mask_int)), ""); - // return res; - } - - GB_PANIC("Unhandled comparison kind %s (%s) %.*s %s (%s)", type_to_string(left.type), type_to_string(base_type(left.type)), LIT(token_strings[op_kind]), type_to_string(right.type), type_to_string(base_type(right.type))); - return {}; -} - -gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind, cgValue x) { - GB_ASSERT(op_kind == Token_CmpEq || op_kind == Token_NotEq); - x = cg_flatten_value(p, x); - cgValue res = {}; - Type *t = x.type; - - TB_DataType dt = cg_data_type(t); - - Type *bt = base_type(t); - TypeKind type_kind = bt->kind; - - switch (type_kind) { - case Type_Basic: - switch (bt->Basic.kind) { - case Basic_rawptr: - case Basic_cstring: - GB_ASSERT(x.kind == cgValue_Value); - if (op_kind == Token_CmpEq) { - return cg_value(tb_inst_cmp_eq(p->func, x.node, tb_inst_uint(p->func, dt, 0)), t_bool); - } else if (op_kind == Token_NotEq) { - return cg_value(tb_inst_cmp_ne(p->func, x.node, tb_inst_uint(p->func, dt, 0)), t_bool); - } - break; - case Basic_any: - { - GB_ASSERT(x.kind == cgValue_Addr); - // // TODO(bill): is this correct behaviour for nil comparison for any? - cgValue data = cg_emit_struct_ev(p, x, 0); - cgValue id = cg_emit_struct_ev(p, x, 1); - - if (op_kind == Token_CmpEq) { - TB_Node *a = tb_inst_cmp_eq(p->func, data.node, tb_inst_uint(p->func, data.node->dt, 0)); - TB_Node *b = tb_inst_cmp_eq(p->func, id.node, tb_inst_uint(p->func, id.node->dt, 0)); - TB_Node *c = tb_inst_or(p->func, a, b); - return cg_value(c, t_bool); - } else if (op_kind == Token_NotEq) { - TB_Node *a = tb_inst_cmp_ne(p->func, data.node, tb_inst_uint(p->func, data.node->dt, 0)); - TB_Node *b = tb_inst_cmp_ne(p->func, id.node, tb_inst_uint(p->func, id.node->dt, 0)); - TB_Node *c = tb_inst_and(p->func, a, b); - return cg_value(c, t_bool); - } - } - break; - case Basic_typeid: - cgValue invalid_typeid = cg_const_value(p, t_typeid, exact_value_i64(0)); - return cg_emit_comp(p, op_kind, x, invalid_typeid); - } - break; - - case Type_Enum: - case Type_Pointer: - case Type_MultiPointer: - case Type_Proc: - case Type_BitSet: - GB_ASSERT(x.kind == cgValue_Value); - if (op_kind == Token_CmpEq) { - return cg_value(tb_inst_cmp_eq(p->func, x.node, tb_inst_uint(p->func, dt, 0)), t_bool); - } else if (op_kind == Token_NotEq) { - return cg_value(tb_inst_cmp_ne(p->func, x.node, tb_inst_uint(p->func, dt, 0)), t_bool); - } - break; - - case Type_Slice: - case Type_DynamicArray: - case Type_Map: - { - // NOTE(bill): all of their data "pointer-like" fields are at the 0-index - cgValue data = cg_emit_struct_ev(p, x, 0); - if (op_kind == Token_CmpEq) { - TB_Node *a = tb_inst_cmp_eq(p->func, data.node, tb_inst_uint(p->func, data.node->dt, 0)); - return cg_value(a, t_bool); - } else if (op_kind == Token_NotEq) { - TB_Node *a = tb_inst_cmp_ne(p->func, data.node, tb_inst_uint(p->func, data.node->dt, 0)); - return cg_value(a, t_bool); - } - } - break; - - case Type_Union: - { - if (type_size_of(t) == 0) { - return cg_const_bool(p, t_bool, op_kind == Token_CmpEq); - } else if (is_type_union_maybe_pointer(t)) { - cgValue tag = cg_emit_transmute(p, x, t_rawptr); - return cg_emit_comp_against_nil(p, op_kind, tag); - } else { - GB_ASSERT("TODO(bill): cg_emit_union_tag_value"); - // cgValue tag = cg_emit_union_tag_value(p, x); - // return cg_emit_comp(p, op_kind, tag, cg_zero(p->module, tag.type)); - } - } - break; - case Type_Struct: - GB_PANIC("TODO(bill): cg_emit_struct_ev"); - // if (is_type_soa_struct(t)) { - // Type *bt = base_type(t); - // if (bt->Struct.soa_kind == StructSoa_Slice) { - // LLVMValueRef the_value = {}; - // if (bt->Struct.fields.count == 0) { - // cgValue len = cg_soa_struct_len(p, x); - // the_value = len.value; - // } else { - // cgValue first_field = cg_emit_struct_ev(p, x, 0); - // the_value = first_field.value; - // } - // if (op_kind == Token_CmpEq) { - // res.value = LLVMBuildIsNull(p->builder, the_value, ""); - // return res; - // } else if (op_kind == Token_NotEq) { - // res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); - // return res; - // } - // } else if (bt->Struct.soa_kind == StructSoa_Dynamic) { - // LLVMValueRef the_value = {}; - // if (bt->Struct.fields.count == 0) { - // cgValue cap = cg_soa_struct_cap(p, x); - // the_value = cap.value; - // } else { - // cgValue first_field = cg_emit_struct_ev(p, x, 0); - // the_value = first_field.value; - // } - // if (op_kind == Token_CmpEq) { - // res.value = LLVMBuildIsNull(p->builder, the_value, ""); - // return res; - // } else if (op_kind == Token_NotEq) { - // res.value = LLVMBuildIsNotNull(p->builder, the_value, ""); - // return res; - // } - // } - // } else if (is_type_struct(t) && type_has_nil(t)) { - // auto args = array_make(permanent_allocator(), 2); - // cgValue lhs = cg_address_from_load_or_generate_local(p, x); - // args[0] = cg_emit_conv(p, lhs, t_rawptr); - // args[1] = cg_const_int(p->module, t_int, type_size_of(t)); - // cgValue val = cg_emit_runtime_call(p, "memory_compare_zero", args); - // cgValue res = cg_emit_comp(p, op_kind, val, cg_const_int(p->module, t_int, 0)); - // return res; - // } - break; - } - GB_PANIC("Unknown handled type: %s -> %s", type_to_string(t), type_to_string(bt)); - return {}; -} - -gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t) { - t = reduce_tuple_to_single_type(t); - - value = cg_flatten_value(p, value); - - Type *src_type = value.type; - if (are_types_identical(t, src_type)) { - return value; - } - - if (is_type_untyped_uninit(src_type)) { - // return cg_const_undef(m, t); - return cg_const_nil(p, t); - } - if (is_type_untyped_nil(src_type)) { - return cg_const_nil(p, t); - } - - Type *src = core_type(src_type); - Type *dst = core_type(t); - GB_ASSERT(src != nullptr); - GB_ASSERT(dst != nullptr); - - if (are_types_identical(src, dst)) { - return cg_emit_transmute(p, value, t); - } - - TB_DataType st = cg_data_type(src); - if (value.kind == cgValue_Value && !TB_IS_VOID_TYPE(value.node->dt)) { - st = value.node->dt; - } - TB_DataType dt = cg_data_type(t); - - if (is_type_integer(src) && is_type_integer(dst)) { - GB_ASSERT(src->kind == Type_Basic && - dst->kind == Type_Basic); - GB_ASSERT(value.kind == cgValue_Value); - - i64 sz = type_size_of(default_type(src)); - i64 dz = type_size_of(default_type(dst)); - - if (sz == dz) { - if (dz > 1 && !types_have_same_internal_endian(src, dst)) { - return cg_emit_byte_swap(p, value, t); - } - value.type = t; - return value; - } - - if (sz > 1 && is_type_different_to_arch_endianness(src)) { - Type *platform_src_type = integer_endian_type_to_platform_type(src); - value = cg_emit_byte_swap(p, value, platform_src_type); - } - - TB_Node* (*op)(TB_Function* f, TB_Node* src, TB_DataType dt) = tb_inst_trunc; - - if (dz < sz) { - op = tb_inst_trunc; - } else if (dz == sz) { - op = tb_inst_bitcast; - } else if (dz > sz) { - op = is_type_unsigned(src) ? tb_inst_zxt : tb_inst_sxt; // zero extent - } - - if (dz > 1 && is_type_different_to_arch_endianness(dst)) { - Type *platform_dst_type = integer_endian_type_to_platform_type(dst); - - cgValue res = cg_value(op(p->func, value.node, cg_data_type(platform_dst_type)), platform_dst_type); - return cg_emit_byte_swap(p, res, t); - } else { - return cg_value(op(p->func, value.node, dt), t); - } - } - - // boolean -> boolean/integer - if (is_type_boolean(src) && (is_type_boolean(dst) || is_type_integer(dst))) { - TB_Node *v = tb_inst_cmp_ne(p->func, value.node, tb_inst_uint(p->func, st, 0)); - return cg_value(tb_inst_zxt(p->func, v, dt), t); - } - - // integer -> boolean - if (is_type_integer(src) && is_type_boolean(dst)) { - TB_Node *v = tb_inst_cmp_ne(p->func, value.node, tb_inst_uint(p->func, st, 0)); - return cg_value(tb_inst_zxt(p->func, v, dt), t); - } - - if (is_type_cstring(src) && is_type_u8_ptr(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_u8_ptr(src) && is_type_cstring(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_cstring(src) && is_type_u8_multi_ptr(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_u8_multi_ptr(src) && is_type_cstring(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_cstring(src) && is_type_rawptr(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_rawptr(src) && is_type_cstring(dst)) { - return cg_emit_transmute(p, value, dst); - } - - - if (are_types_identical(src, t_cstring) && are_types_identical(dst, t_string)) { - TEMPORARY_ALLOCATOR_GUARD(); - cgValue c = cg_emit_conv(p, value, t_cstring); - auto args = slice_make(temporary_allocator(), 1); - args[0] = c; - cgValue s = cg_emit_runtime_call(p, "cstring_to_string", args); - return cg_emit_conv(p, s, dst); - } - - // float -> float - if (is_type_float(src) && is_type_float(dst)) { - i64 sz = type_size_of(src); - i64 dz = type_size_of(dst); - - if (sz == 2 || dz == 2) { - GB_PANIC("TODO(bill): f16 conversions"); - } - - - if (dz == sz) { - if (types_have_same_internal_endian(src, dst)) { - return cg_value(value.node, t); - } else { - return cg_emit_byte_swap(p, value, t); - } - } - - if (is_type_different_to_arch_endianness(src) || is_type_different_to_arch_endianness(dst)) { - Type *platform_src_type = integer_endian_type_to_platform_type(src); - Type *platform_dst_type = integer_endian_type_to_platform_type(dst); - cgValue res = {}; - res = cg_emit_conv(p, value, platform_src_type); - res = cg_emit_conv(p, res, platform_dst_type); - if (is_type_different_to_arch_endianness(dst)) { - res = cg_emit_byte_swap(p, res, t); - } - return cg_emit_conv(p, res, t); - } - - - if (dz >= sz) { - return cg_value(tb_inst_fpxt(p->func, value.node, dt), t); - } - return cg_value(tb_inst_trunc(p->func, value.node, dt), t); - } - - if (is_type_complex(src) && is_type_complex(dst)) { - GB_PANIC("TODO(bill): complex -> complex"); - } - - if (is_type_quaternion(src) && is_type_quaternion(dst)) { - // @QuaternionLayout - GB_PANIC("TODO(bill): quaternion -> quaternion"); - } - if (is_type_integer(src) && is_type_complex(dst)) { - GB_PANIC("TODO(bill): int -> complex"); - } - if (is_type_float(src) && is_type_complex(dst)) { - GB_PANIC("TODO(bill): float -> complex"); - } - if (is_type_integer(src) && is_type_quaternion(dst)) { - GB_PANIC("TODO(bill): int -> quaternion"); - } - if (is_type_float(src) && is_type_quaternion(dst)) { - GB_PANIC("TODO(bill): float -> quaternion"); - } - if (is_type_complex(src) && is_type_quaternion(dst)) { - GB_PANIC("TODO(bill): complex -> quaternion"); - } - - - // float <-> integer - if (is_type_float(src) && is_type_integer(dst)) { - if (is_type_different_to_arch_endianness(src) || is_type_different_to_arch_endianness(dst)) { - Type *platform_src_type = integer_endian_type_to_platform_type(src); - Type *platform_dst_type = integer_endian_type_to_platform_type(dst); - cgValue res = {}; - res = cg_emit_conv(p, value, platform_src_type); - res = cg_emit_conv(p, res, platform_dst_type); - return cg_emit_conv(p, res, t); - } - - // if (is_type_integer_128bit(dst)) { - // TEMPORARY_ALLOCATOR_GUARD(); - - // auto args = array_make(temporary_allocator(), 1); - // args[0] = value; - // char const *call = "fixunsdfdi"; - // if (is_type_unsigned(dst)) { - // call = "fixunsdfti"; - // } - // lbValue res_i128 = lb_emit_runtime_call(p, call, args); - // return lb_emit_conv(p, res_i128, t); - // } - - bool is_signed = !is_type_unsigned(dst); - return cg_value(tb_inst_float2int(p->func, value.node, dt, is_signed), t); - } - if (is_type_integer(src) && is_type_float(dst)) { - if (is_type_different_to_arch_endianness(src) || is_type_different_to_arch_endianness(dst)) { - Type *platform_src_type = integer_endian_type_to_platform_type(src); - Type *platform_dst_type = integer_endian_type_to_platform_type(dst); - cgValue res = {}; - res = cg_emit_conv(p, value, platform_src_type); - res = cg_emit_conv(p, res, platform_dst_type); - if (is_type_different_to_arch_endianness(dst)) { - res = cg_emit_byte_swap(p, res, t); - } - return cg_emit_conv(p, res, t); - } - - // if (is_type_integer_128bit(src)) { - // TEMPORARY_ALLOCATOR_GUARD(); - - // auto args = array_make(temporary_allocator(), 1); - // args[0] = value; - // char const *call = "floattidf"; - // if (is_type_unsigned(src)) { - // call = "floattidf_unsigned"; - // } - // lbValue res_f64 = lb_emit_runtime_call(p, call, args); - // return lb_emit_conv(p, res_f64, t); - // } - - bool is_signed = !is_type_unsigned(dst); - return cg_value(tb_inst_int2float(p->func, value.node, dt, is_signed), t); - } - - if (is_type_simd_vector(dst)) { - GB_PANIC("TODO(bill): ? -> #simd vector"); - } - - - // Pointer <-> uintptr - if (is_type_pointer(src) && is_type_uintptr(dst)) { - return cg_value(tb_inst_ptr2int(p->func, value.node, dt), t); - } - if (is_type_uintptr(src) && is_type_pointer(dst)) { - return cg_value(tb_inst_int2ptr(p->func, value.node), t); - } - if (is_type_multi_pointer(src) && is_type_uintptr(dst)) { - return cg_value(tb_inst_ptr2int(p->func, value.node, dt), t); - } - if (is_type_uintptr(src) && is_type_multi_pointer(dst)) { - return cg_value(tb_inst_int2ptr(p->func, value.node), t); - } - - if (is_type_union(dst)) { - GB_PANIC("TODO(bill): ? -> union"); - } - - // NOTE(bill): This has to be done before 'Pointer <-> Pointer' as it's - // subtype polymorphism casting - if (check_is_assignable_to_using_subtype(src_type, t)) { - GB_PANIC("TODO(bill): ? -> subtyping"); - } - - // Pointer <-> Pointer - if (is_type_pointer(src) && is_type_pointer(dst)) { - return cg_value(value.node, t); - } - if (is_type_multi_pointer(src) && is_type_pointer(dst)) { - return cg_value(value.node, t); - } - if (is_type_pointer(src) && is_type_multi_pointer(dst)) { - return cg_value(value.node, t); - } - if (is_type_multi_pointer(src) && is_type_multi_pointer(dst)) { - return cg_value(value.node, t); - } - - // proc <-> proc - if (is_type_proc(src) && is_type_proc(dst)) { - return cg_value(value.node, t); - } - - // pointer -> proc - if (is_type_pointer(src) && is_type_proc(dst)) { - return cg_value(value.node, t); - } - // proc -> pointer - if (is_type_proc(src) && is_type_pointer(dst)) { - return cg_value(value.node, t); - } - - // []byte/[]u8 <-> string - if (is_type_u8_slice(src) && is_type_string(dst)) { - return cg_emit_transmute(p, value, t); - } - if (is_type_string(src) && is_type_u8_slice(dst)) { - return cg_emit_transmute(p, value, t); - } - - if (is_type_matrix(dst) && !is_type_matrix(src)) { - GB_PANIC("TODO(bill): !matrix -> matrix"); - } - - if (is_type_matrix(dst) && is_type_matrix(src)) { - GB_PANIC("TODO(bill): matrix -> matrix"); - } - - if (is_type_any(dst)) { - if (is_type_untyped_nil(src) || - is_type_untyped_uninit(src)) { - return cg_const_nil(p, t); - } - - cgAddr result = cg_add_local(p, t, nullptr, false); - - Type *st = default_type(src_type); - - cgValue data = cg_address_from_load_or_generate_local(p, value); - GB_ASSERT(is_type_pointer(data.type)); - GB_ASSERT(is_type_typed(st)); - - data = cg_emit_conv(p, data, t_rawptr); - if (p->name == "main@main") { - GB_PANIC("HERE %s %llu", type_to_string(st), cg_typeid_as_u64(p->module, value.type)); - } - - cgValue id = cg_typeid(p, st); - cgValue data_ptr = cg_emit_struct_ep(p, result.addr, 0); - cgValue id_ptr = cg_emit_struct_ep(p, result.addr, 1); - - cg_emit_store(p, data_ptr, data); - cg_emit_store(p, id_ptr, id); - - return cg_addr_load(p, result); - } - - i64 src_sz = type_size_of(src); - i64 dst_sz = type_size_of(dst); - - if (src_sz == dst_sz) { - // bit_set <-> integer - if (is_type_integer(src) && is_type_bit_set(dst)) { - cgValue v = cg_emit_conv(p, value, bit_set_to_int(dst)); - return cg_emit_transmute(p, v, t); - } - if (is_type_bit_set(src) && is_type_integer(dst)) { - cgValue bs = cg_emit_transmute(p, value, bit_set_to_int(src)); - return cg_emit_conv(p, bs, dst); - } - - // typeid <-> integer - if (is_type_integer(src) && is_type_typeid(dst)) { - return cg_emit_transmute(p, value, dst); - } - if (is_type_typeid(src) && is_type_integer(dst)) { - return cg_emit_transmute(p, value, dst); - } - } - - - if (is_type_untyped(src)) { - if (is_type_string(src) && is_type_string(dst)) { - cgAddr result = cg_add_local(p, t, nullptr, false); - cg_addr_store(p, result, value); - return cg_addr_load(p, result); - } - } - - - gb_printf_err("%.*s\n", LIT(p->name)); - gb_printf_err("cg_emit_conv: src -> dst\n"); - gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t)); - gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst)); - gb_printf_err("Not Identical %p != %p\n", src_type, t); - gb_printf_err("Not Identical %p != %p\n", src, dst); - - - GB_PANIC("Invalid type conversion: '%s' to '%s' for procedure '%.*s'", - type_to_string(src_type), type_to_string(t), - LIT(p->name)); - - return {}; -} - -gb_internal cgValue cg_emit_arith(cgProcedure *p, TokenKind op, cgValue lhs, cgValue rhs, Type *type) { - if (is_type_array_like(lhs.type) || is_type_array_like(rhs.type)) { - GB_PANIC("TODO(bill): cg_emit_arith_array"); - } else if (is_type_matrix(lhs.type) || is_type_matrix(rhs.type)) { - GB_PANIC("TODO(bill): cg_emit_arith_matrix"); - } else if (is_type_complex(type)) { - GB_PANIC("TODO(bill): cg_emit_arith complex"); - } else if (is_type_quaternion(type)) { - GB_PANIC("TODO(bill): cg_emit_arith quaternion"); - } - - lhs = cg_flatten_value(p, cg_emit_conv(p, lhs, type)); - rhs = cg_flatten_value(p, cg_emit_conv(p, rhs, type)); - GB_ASSERT(lhs.kind == cgValue_Value); - GB_ASSERT(rhs.kind == cgValue_Value); - - if (is_type_integer(type) && is_type_different_to_arch_endianness(type)) { - switch (op) { - case Token_AndNot: - case Token_And: - case Token_Or: - case Token_Xor: - goto handle_op; - } - - Type *platform_type = integer_endian_type_to_platform_type(type); - cgValue x = cg_emit_byte_swap(p, lhs, integer_endian_type_to_platform_type(lhs.type)); - cgValue y = cg_emit_byte_swap(p, rhs, integer_endian_type_to_platform_type(rhs.type)); - - cgValue res = cg_emit_arith(p, op, x, y, platform_type); - - return cg_emit_byte_swap(p, res, type); - } - - if (is_type_float(type) && is_type_different_to_arch_endianness(type)) { - Type *platform_type = integer_endian_type_to_platform_type(type); - cgValue x = cg_emit_conv(p, lhs, integer_endian_type_to_platform_type(lhs.type)); - cgValue y = cg_emit_conv(p, rhs, integer_endian_type_to_platform_type(rhs.type)); - - cgValue res = cg_emit_arith(p, op, x, y, platform_type); - - return cg_emit_byte_swap(p, res, type); - } - -handle_op:; - - // NOTE(bill): Bit Set Aliases for + and - - if (is_type_bit_set(type)) { - switch (op) { - case Token_Add: op = Token_Or; break; - case Token_Sub: op = Token_AndNot; break; - } - } - - TB_ArithmeticBehavior arith_behavior = cast(TB_ArithmeticBehavior)0; - - Type *integral_type = type; - if (is_type_simd_vector(integral_type)) { - GB_PANIC("TODO(bill): cg_emit_arith #simd vector"); - // integral_type = core_array_type(integral_type); - } - - switch (op) { - case Token_Add: - if (is_type_float(integral_type)) { - return cg_value(tb_inst_fadd(p->func, lhs.node, rhs.node), type); - } - return cg_value(tb_inst_add(p->func, lhs.node, rhs.node, arith_behavior), type); - case Token_Sub: - if (is_type_float(integral_type)) { - return cg_value(tb_inst_fsub(p->func, lhs.node, rhs.node), type); - } - return cg_value(tb_inst_sub(p->func, lhs.node, rhs.node, arith_behavior), type); - case Token_Mul: - if (is_type_float(integral_type)) { - return cg_value(tb_inst_fmul(p->func, lhs.node, rhs.node), type); - } - return cg_value(tb_inst_mul(p->func, lhs.node, rhs.node, arith_behavior), type); - case Token_Quo: - if (is_type_float(integral_type)) { - return cg_value(tb_inst_fdiv(p->func, lhs.node, rhs.node), type); - } - return cg_value(tb_inst_div(p->func, lhs.node, rhs.node, !is_type_unsigned(integral_type)), type); - case Token_Mod: - if (is_type_float(integral_type)) { - GB_PANIC("TODO(bill): float %% float"); - } - return cg_value(tb_inst_mod(p->func, lhs.node, rhs.node, !is_type_unsigned(integral_type)), type); - case Token_ModMod: - if (is_type_unsigned(integral_type)) { - return cg_value(tb_inst_mod(p->func, lhs.node, rhs.node, false), type); - } else { - TB_Node *a = tb_inst_mod(p->func, lhs.node, rhs.node, true); - TB_Node *b = tb_inst_add(p->func, a, rhs.node, arith_behavior); - TB_Node *c = tb_inst_mod(p->func, b, rhs.node, true); - return cg_value(c, type); - } - - case Token_And: - return cg_value(tb_inst_and(p->func, lhs.node, rhs.node), type); - case Token_Or: - return cg_value(tb_inst_or(p->func, lhs.node, rhs.node), type); - case Token_Xor: - return cg_value(tb_inst_xor(p->func, lhs.node, rhs.node), type); - case Token_Shl: - { - rhs = cg_emit_conv(p, rhs, lhs.type); - TB_DataType dt = cg_data_type(lhs.type); - TB_Node *lhsval = lhs.node; - TB_Node *bits = rhs.node; - - TB_Node *bit_size = tb_inst_uint(p->func, dt, 8*type_size_of(lhs.type)); - TB_Node *zero = tb_inst_uint(p->func, dt, 0); - - TB_Node *width_test = tb_inst_cmp_ilt(p->func, bits, bit_size, false); - - TB_Node *res = tb_inst_shl(p->func, lhsval, bits, arith_behavior); - res = tb_inst_select(p->func, width_test, res, zero); - return cg_value(res, type); - } - case Token_Shr: - { - rhs = cg_emit_conv(p, rhs, lhs.type); - TB_DataType dt = cg_data_type(lhs.type); - TB_Node *lhsval = lhs.node; - TB_Node *bits = rhs.node; - - TB_Node *bit_size = tb_inst_uint(p->func, dt, 8*type_size_of(lhs.type)); - TB_Node *zero = tb_inst_uint(p->func, dt, 0); - - TB_Node *width_test = tb_inst_cmp_ilt(p->func, bits, bit_size, false); - - TB_Node *res = nullptr; - - if (is_type_unsigned(integral_type)) { - res = tb_inst_shr(p->func, lhsval, bits); - } else { - res = tb_inst_sar(p->func, lhsval, bits); - } - - - res = tb_inst_select(p->func, width_test, res, zero); - return cg_value(res, type); - } - case Token_AndNot: - return cg_value(tb_inst_and(p->func, lhs.node, tb_inst_not(p->func, rhs.node)), type); - } - - GB_PANIC("unhandled operator of cg_emit_arith"); - - return {}; -} - - -gb_internal void cg_fill_slice(cgProcedure *p, cgAddr const &slice, cgValue data, cgValue len) { - cgValue slice_ptr = cg_addr_get_ptr(p, slice); - cgValue data_ptr = cg_emit_struct_ep(p, slice_ptr, 0); - cgValue len_ptr = cg_emit_struct_ep(p, slice_ptr, 1); - - data = cg_emit_conv(p, data, type_deref(data_ptr.type)); - len = cg_emit_conv(p, len, t_int); - cg_emit_store(p, data_ptr, data); - cg_emit_store(p, len_ptr, len); -} - -gb_internal cgAddr cg_build_addr_slice_expr(cgProcedure *p, Ast *expr) { - ast_node(se, SliceExpr, expr); - - cgValue low = cg_const_int(p, t_int, 0); - cgValue high = {}; - - if (se->low != nullptr) { - low = cg_correct_endianness(p, cg_build_expr(p, se->low)); - } - if (se->high != nullptr) { - high = cg_correct_endianness(p, cg_build_expr(p, se->high)); - } - - bool no_indices = se->low == nullptr && se->high == nullptr; - gb_unused(no_indices); - - cgAddr addr = cg_build_addr(p, se->expr); - cgValue base = cg_addr_load(p, addr); - Type *type = base_type(base.type); - - if (is_type_pointer(type)) { - type = base_type(type_deref(type)); - addr = cg_addr(base); - base = cg_addr_load(p, addr); - } - - switch (type->kind) { - case Type_Basic: - case Type_Slice: { - if (type->kind == Type_Basic) { - GB_ASSERT(type->Basic.kind == Basic_string); - } - - Type *slice_type = type; - if (high.node == nullptr) { - cgValue len = cg_builtin_len(p, base); - high = len; - } - - if (!no_indices) { - // cg_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); - } - - cgValue elem = cg_emit_ptr_offset(p, cg_builtin_raw_data(p, base), low); - cgValue new_len = cg_emit_arith(p, Token_Sub, high, low, t_int); - - cgAddr slice = cg_add_local(p, slice_type, nullptr, true); - cg_fill_slice(p, slice, elem, new_len); - return slice; - } - - case Type_RelativeMultiPointer: - GB_PANIC("TODO(bill): Type_RelativeMultiPointer should be handled above already on the cg_addr_load"); - break; - - case Type_DynamicArray: { - // Type *elem_type = type->DynamicArray.elem; - // Type *slice_type = alloc_type_slice(elem_type); - - // lbValue len = lb_dynamic_array_len(p, base); - // if (high.value == nullptr) high = len; - - // if (!no_indices) { - // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); - // } - - // lbValue elem = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low); - // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); - - // lbAddr slice = lb_add_local_generated(p, slice_type, false); - // lb_fill_slice(p, slice, elem, new_len); - // return slice; - GB_PANIC("cg_build_addr_slice_expr Type_DynamicArray"); - break; - } - - case Type_MultiPointer: { - Type *res_type = type_of_expr(expr); - if (se->high == nullptr) { - cgAddr res = cg_add_local(p, res_type, nullptr, false); - GB_ASSERT(base.kind == cgValue_Value); - GB_ASSERT(low.kind == cgValue_Value); - - i64 stride = type_size_of(type->MultiPointer.elem); - cgValue offset = cg_value(tb_inst_array_access(p->func, base.node, low.node, stride), base.type); - cg_addr_store(p, res, offset); - return res; - } else { - cgAddr res = cg_add_local(p, res_type, nullptr, true); - low = cg_emit_conv(p, low, t_int); - high = cg_emit_conv(p, high, t_int); - - // cg_emit_multi_pointer_slice_bounds_check(p, se->open, low, high); - - i64 stride = type_size_of(type->MultiPointer.elem); - TB_Node *offset = tb_inst_array_access(p->func, base.node, low.node, stride); - TB_Node *len = tb_inst_sub(p->func, high.node, low.node, cast(TB_ArithmeticBehavior)0); - - TB_Node *data_ptr = tb_inst_member_access(p->func, res.addr.node, type_offset_of(res_type, 0)); - TB_Node *len_ptr = tb_inst_member_access(p->func, res.addr.node, type_offset_of(res_type, 1)); - - tb_inst_store(p->func, TB_TYPE_PTR, data_ptr, offset, cast(TB_CharUnits)build_context.ptr_size, false); - tb_inst_store(p->func, TB_TYPE_INT, len_ptr, len, cast(TB_CharUnits)build_context.int_size, false); - return res; - } - } - - case Type_Array: { - Type *slice_type = type_of_expr(expr); - GB_ASSERT(is_type_slice(slice_type)); - cgValue len = cg_const_int(p, t_int, type->Array.count); - if (high.node == nullptr) high = len; - - // bool low_const = type_and_value_of_expr(se->low).mode == Addressing_Constant; - // bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant; - // if (!low_const || !high_const) { - // if (!no_indices) { - // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); - // } - // } - cgValue elem = cg_emit_ptr_offset(p, cg_builtin_raw_data(p, cg_addr_get_ptr(p, addr)), low); - cgValue new_len = cg_emit_arith(p, Token_Sub, high, low, t_int); - - cgAddr slice = cg_add_local(p, slice_type, nullptr, true); - cg_fill_slice(p, slice, elem, new_len); - return slice; - } - - - case Type_Struct: - // if (is_type_soa_struct(type)) { - // lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr)); - // if (high.value == nullptr) high = len; - - // if (!no_indices) { - // lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); - // } - // #if 1 - - // lbAddr dst = lb_add_local_generated(p, type_of_expr(expr), true); - // if (type->Struct.soa_kind == StructSoa_Fixed) { - // i32 field_count = cast(i32)type->Struct.fields.count; - // for (i32 i = 0; i < field_count; i++) { - // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); - // lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i); - // field_src = lb_emit_array_ep(p, field_src, low); - // lb_emit_store(p, field_dst, field_src); - // } - - // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); - // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); - // lb_emit_store(p, len_dst, new_len); - // } else if (type->Struct.soa_kind == StructSoa_Slice) { - // if (no_indices) { - // lb_addr_store(p, dst, base); - // } else { - // i32 field_count = cast(i32)type->Struct.fields.count - 1; - // for (i32 i = 0; i < field_count; i++) { - // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); - // lbValue field_src = lb_emit_struct_ev(p, base, i); - // field_src = lb_emit_ptr_offset(p, field_src, low); - // lb_emit_store(p, field_dst, field_src); - // } - - - // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); - // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); - // lb_emit_store(p, len_dst, new_len); - // } - // } else if (type->Struct.soa_kind == StructSoa_Dynamic) { - // i32 field_count = cast(i32)type->Struct.fields.count - 3; - // for (i32 i = 0; i < field_count; i++) { - // lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); - // lbValue field_src = lb_emit_struct_ev(p, base, i); - // field_src = lb_emit_ptr_offset(p, field_src, low); - // lb_emit_store(p, field_dst, field_src); - // } - - - // lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count); - // lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); - // lb_emit_store(p, len_dst, new_len); - // } - - // return dst; - // #endif - // } - GB_PANIC("cg_build_addr_slice_expr Type_Struct"); - break; - - } - - GB_PANIC("Unknown slicable type"); - return {}; -} - -gb_internal cgValue cg_emit_unary_arith(cgProcedure *p, TokenKind op, cgValue x, Type *type) { - switch (op) { - case Token_Add: - return x; - case Token_Not: // Boolean not - case Token_Xor: // Bitwise not - case Token_Sub: // Number negation - break; - case Token_Pointer: - GB_PANIC("This should be handled elsewhere"); - break; - } - - x = cg_flatten_value(p, x); - - if (is_type_array_like(x.type)) { - GB_PANIC("TODO(bill): cg_emit_unary_arith is_type_array_like"); - // // IMPORTANT TODO(bill): This is very wasteful with regards to stack memory - // Type *tl = base_type(x.type); - // cgValue val = cg_address_from_load_or_generate_local(p, x); - // GB_ASSERT(is_type_array_like(type)); - // Type *elem_type = base_array_type(type); - - // // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops - // cgAddr res_addr = cg_add_local(p, type, nullptr, false); - // cgValue res = cg_addr_get_ptr(p, res_addr); - - // bool inline_array_arith = cg_can_try_to_inline_array_arith(type); - - // i32 count = cast(i32)get_array_type_count(tl); - - // LLVMTypeRef vector_type = nullptr; - // if (op != Token_Not && cg_try_vector_cast(p->module, val, &vector_type)) { - // LLVMValueRef vp = LLVMBuildPointerCast(p->builder, val.value, LLVMPointerType(vector_type, 0), ""); - // LLVMValueRef v = LLVMBuildLoad2(p->builder, vector_type, vp, ""); - - // LLVMValueRef opv = nullptr; - // switch (op) { - // case Token_Xor: - // opv = LLVMBuildNot(p->builder, v, ""); - // break; - // case Token_Sub: - // if (is_type_float(elem_type)) { - // opv = LLVMBuildFNeg(p->builder, v, ""); - // } else { - // opv = LLVMBuildNeg(p->builder, v, ""); - // } - // break; - // } - - // if (opv != nullptr) { - // LLVMSetAlignment(res.value, cast(unsigned)cg_alignof(vector_type)); - // LLVMValueRef res_ptr = LLVMBuildPointerCast(p->builder, res.value, LLVMPointerType(vector_type, 0), ""); - // LLVMBuildStore(p->builder, opv, res_ptr); - // return cg_emit_conv(p, cg_emit_load(p, res), type); - // } - // } - - // if (inline_array_arith) { - // // inline - // for (i32 i = 0; i < count; i++) { - // cgValue e = cg_emit_load(p, cg_emit_array_epi(p, val, i)); - // cgValue z = cg_emit_unary_arith(p, op, e, elem_type); - // cg_emit_store(p, cg_emit_array_epi(p, res, i), z); - // } - // } else { - // auto loop_data = cg_loop_start(p, count, t_i32); - - // cgValue e = cg_emit_load(p, cg_emit_array_ep(p, val, loop_data.idx)); - // cgValue z = cg_emit_unary_arith(p, op, e, elem_type); - // cg_emit_store(p, cg_emit_array_ep(p, res, loop_data.idx), z); - - // cg_loop_end(p, loop_data); - // } - // return cg_emit_load(p, res); - } - - if (op == Token_Xor) { - GB_ASSERT(x.kind == cgValue_Value); - cgValue cmp = cg_value(tb_inst_not(p->func, x.node), x.type); - return cg_emit_conv(p, cmp, type); - } - - if (op == Token_Not) { - TB_Node *zero = cg_const_nil(p, x.type).node; - cgValue cmp = cg_value(tb_inst_cmp_ne(p->func, x.node, zero), x.type); - return cg_emit_conv(p, cmp, type); - } - - if (op == Token_Sub && is_type_integer(type) && is_type_different_to_arch_endianness(type)) { - Type *platform_type = integer_endian_type_to_platform_type(type); - cgValue v = cg_emit_byte_swap(p, x, platform_type); - - cgValue res = cg_value(tb_inst_neg(p->func, v.node), platform_type); - return cg_emit_byte_swap(p, res, type); - } - - if (op == Token_Sub && is_type_float(type) && is_type_different_to_arch_endianness(type)) { - Type *platform_type = integer_endian_type_to_platform_type(type); - cgValue v = cg_emit_byte_swap(p, x, platform_type); - - cgValue res = cg_value(tb_inst_neg(p->func, v.node), platform_type); - return cg_emit_byte_swap(p, res, type); - } - - cgValue res = {}; - - if (op == Token_Sub) { // Number negation - if (is_type_integer(x.type)) { - res = cg_value(tb_inst_neg(p->func, x.node), x.type); - } else if (is_type_float(x.type)) { - res = cg_value(tb_inst_neg(p->func, x.node), x.type); - } else if (is_type_complex(x.type)) { - GB_PANIC("TODO(bill): neg complex"); - // LLVMValueRef v0 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 0, ""), ""); - // LLVMValueRef v1 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 1, ""), ""); - - // cgAddr addr = cg_add_local_generated(p, x.type, false); - // LLVMTypeRef type = llvm_addr_type(p->module, addr.addr); - // LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, "")); - // LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, "")); - // return cg_addr_load(p, addr); - - } else if (is_type_quaternion(x.type)) { - GB_PANIC("TODO(bill): neg quaternion"); - // LLVMValueRef v0 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 0, ""), ""); - // LLVMValueRef v1 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 1, ""), ""); - // LLVMValueRef v2 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 2, ""), ""); - // LLVMValueRef v3 = LLVMBuildFNeg(p->builder, LLVMBuildExtractValue(p->builder, x.value, 3, ""), ""); - - // cgAddr addr = cg_add_local_generated(p, x.type, false); - // LLVMTypeRef type = llvm_addr_type(p->module, addr.addr); - // LLVMBuildStore(p->builder, v0, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 0, "")); - // LLVMBuildStore(p->builder, v1, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 1, "")); - // LLVMBuildStore(p->builder, v2, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 2, "")); - // LLVMBuildStore(p->builder, v3, LLVMBuildStructGEP2(p->builder, type, addr.addr.value, 3, "")); - // return cg_addr_load(p, addr); - } else if (is_type_simd_vector(x.type)) { - GB_PANIC("TODO(bill): neg simd"); - // Type *elem = base_array_type(x.type); - // if (is_type_float(elem)) { - // res.value = LLVMBuildFNeg(p->builder, x.value, ""); - // } else { - // res.value = LLVMBuildNeg(p->builder, x.value, ""); - // } - } else if (is_type_matrix(x.type)) { - GB_PANIC("TODO(bill): neg matrix"); - // cgValue zero = {}; - // zero.value = LLVMConstNull(cg_type(p->module, type)); - // zero.type = type; - // return cg_emit_arith_matrix(p, Token_Sub, zero, x, type, true); - } else { - GB_PANIC("Unhandled type %s", type_to_string(x.type)); - } - res.type = x.type; - return res; - } - - return res; -} - -gb_internal void cg_emit_if(cgProcedure *p, cgValue const &cond, TB_Node *true_region, TB_Node *false_region) { - GB_ASSERT(cond.kind == cgValue_Value); - tb_inst_if(p->func, cond.node, true_region, false_region); -} - - -struct cgLoopData { - cgAddr index_addr; - cgValue index; - TB_Node *body; - TB_Node *done; - TB_Node *loop; -}; - -gb_internal cgLoopData cg_loop_start(cgProcedure *p, isize count, Type *index_type) { - cgLoopData data = {}; - - cgValue max = cg_const_int(p, index_type, count); - - data.index_addr = cg_add_local(p, index_type, nullptr, true); - - data.body = cg_control_region(p, "loop_body"); - data.done = cg_control_region(p, "loop_done"); - data.loop = cg_control_region(p, "loop_loop"); - - cg_emit_goto(p, data.loop); - tb_inst_set_control(p->func, data.loop); - - data.index = cg_addr_load(p, data.index_addr); - - cgValue cond = cg_emit_comp(p, Token_Lt, data.index, max); - cg_emit_if(p, cond, data.body, data.done); - tb_inst_set_control(p->func, data.body); - - return data; -} - -gb_internal void cg_loop_end(cgProcedure *p, cgLoopData const &data) { - if (data.index_addr.addr.node != nullptr) { - cg_emit_increment(p, data.index_addr.addr); - cg_emit_goto(p, data.loop); - tb_inst_set_control(p->func, data.done); - } -} - - - -gb_internal void cg_build_try_lhs_rhs(cgProcedure *p, Ast *arg, Type *final_type, cgValue *lhs_, cgValue *rhs_) { - cgValue lhs = {}; - cgValue rhs = {}; - - cgValue value = cg_build_expr(p, arg); - if (value.kind == cgValue_Multi) { - auto const &values = value.multi->values; - if (values.count == 2) { - lhs = values[0]; - rhs = values[1]; - } else { - rhs = values[values.count-1]; - if (values.count > 1) { - lhs = cg_value_multi(slice(values, 0, values.count-1), final_type); - } - } - } else { - rhs = value; - } - - GB_ASSERT(rhs.node != nullptr); - - if (lhs_) *lhs_ = lhs; - if (rhs_) *rhs_ = rhs; -} - -gb_internal cgValue cg_emit_try_has_value(cgProcedure *p, cgValue rhs) { - cgValue has_value = {}; - if (is_type_boolean(rhs.type)) { - has_value = rhs; - } else { - GB_ASSERT_MSG(type_has_nil(rhs.type), "%s", type_to_string(rhs.type)); - has_value = cg_emit_comp_against_nil(p, Token_CmpEq, rhs); - } - GB_ASSERT(has_value.node != nullptr); - return has_value; -} - -gb_internal cgValue cg_build_or_return(cgProcedure *p, Ast *arg, Type *final_type) { - cgValue lhs = {}; - cgValue rhs = {}; - cg_build_try_lhs_rhs(p, arg, final_type, &lhs, &rhs); - - TB_Node *return_region = cg_control_region(p, "or_return_return"); - TB_Node *continue_region = cg_control_region(p, "or_return_continue"); - - cgValue cond = cg_emit_try_has_value(p, rhs); - cg_emit_if(p, cond, continue_region, return_region); - tb_inst_set_control(p->func, return_region); - { - Type *proc_type = base_type(p->type); - Type *results = proc_type->Proc.results; - GB_ASSERT(results != nullptr && results->kind == Type_Tuple); - TypeTuple *tuple = &results->Tuple; - - GB_ASSERT(tuple->variables.count != 0); - - Entity *end_entity = tuple->variables[tuple->variables.count-1]; - rhs = cg_emit_conv(p, rhs, end_entity->type); - if (p->type->Proc.has_named_results) { - GB_ASSERT(end_entity->token.string.len != 0); - - // NOTE(bill): store the named values before returning - cgAddr found = map_must_get(&p->variable_map, end_entity); - cg_addr_store(p, found, rhs); - - cg_build_return_stmt(p, {}); - } else { - GB_ASSERT(tuple->variables.count == 1); - Slice results = {}; - results.data = &rhs; - results.count = 1;; - cg_build_return_stmt_internal(p, results); - } - } - tb_inst_set_control(p->func, continue_region); - if (final_type != nullptr && !is_type_tuple(final_type)) { - return cg_emit_conv(p, lhs, final_type); - } - return {}; -} - -gb_internal cgValue cg_build_or_else(cgProcedure *p, Ast *arg, Ast *else_expr, Type *final_type) { - if (arg->state_flags & StateFlag_DirectiveWasFalse) { - return cg_build_expr(p, else_expr); - } - - cgValue lhs = {}; - cgValue rhs = {}; - cg_build_try_lhs_rhs(p, arg, final_type, &lhs, &rhs); - - GB_ASSERT(else_expr != nullptr); - - if (is_diverging_expr(else_expr)) { - TB_Node *then = cg_control_region(p, "or_else_then"); - TB_Node *else_ = cg_control_region(p, "or_else_else"); - - cg_emit_if(p, cg_emit_try_has_value(p, rhs), then, else_); - // NOTE(bill): else block needs to be straight afterwards to make sure that the actual value is used - // from the then block - tb_inst_set_control(p->func, else_); - - cg_build_expr(p, else_expr); - - tb_inst_set_control(p->func, then); - return cg_emit_conv(p, lhs, final_type); - } else { - TB_Node *incoming_values[2] = {}; - TB_Node *incoming_regions[2] = {}; - - TB_Node *then = cg_control_region(p, "or_else_then"); - TB_Node *done = cg_control_region(p, "or_else_done"); // NOTE(bill): Append later - TB_Node *else_ = cg_control_region(p, "or_else_else"); - - cg_emit_if(p, cg_emit_try_has_value(p, rhs), then, else_); - tb_inst_set_control(p->func, then); - - cgValue x = cg_emit_conv(p, lhs, final_type); - incoming_values[0] = x.node; - incoming_regions[0] = tb_inst_get_control(p->func); - - tb_inst_goto(p->func, done); - tb_inst_set_control(p->func, else_); - - cgValue y = cg_emit_conv(p, cg_build_expr(p, else_expr), final_type); - incoming_values[1] = y.node; - incoming_regions[1] = tb_inst_get_control(p->func); - - tb_inst_goto(p->func, done); - tb_inst_set_control(p->func, done); - - GB_ASSERT(x.kind == y.kind); - GB_ASSERT(incoming_values[0]->dt.raw == incoming_values[1]->dt.raw); - cgValue res = {}; - res.kind = x.kind; - res.type = final_type; - - res.node = tb_inst_incomplete_phi(p->func, incoming_values[0]->dt, done, 2); - tb_inst_add_phi_operand(p->func, res.node, incoming_regions[0], incoming_values[0]); - tb_inst_add_phi_operand(p->func, res.node, incoming_regions[1], incoming_values[1]); - return res; - } -} - - -gb_internal isize cg_control_region_pred_count(TB_Node *region) { - GB_ASSERT(region->type == TB_REGION); - GB_ASSERT(region->input_count > 0); - return region->input_count; -} - -gb_internal cgValue cg_build_logical_binary_expr(cgProcedure *p, TokenKind op, Ast *left, Ast *right, Type *final_type) { - TB_Node *rhs = cg_control_region(p, "logical_cmp_rhs"); - TB_Node *done = cg_control_region(p, "logical_cmp_done"); - - cgValue short_circuit = {}; - if (op == Token_CmpAnd) { - cg_build_cond(p, left, rhs, done); - short_circuit = cg_const_bool(p, t_bool, false); - } else if (op == Token_CmpOr) { - cg_build_cond(p, left, done, rhs); - short_circuit = cg_const_bool(p, t_bool, true); - } - - if (rhs->input_count == 0) { - tb_inst_set_control(p->func, done); - return cg_emit_conv(p, short_circuit, final_type); - } - - if (done->input_count == 0) { - tb_inst_set_control(p->func, rhs); - return cg_build_expr(p, right); - } - - tb_inst_set_control(p->func, rhs); - cgValue edge = cg_build_expr(p, right); - TB_Node *edge_region = tb_inst_get_control(p->func); - - tb_inst_goto(p->func, done); - tb_inst_set_control(p->func, done); - - TB_DataType dt = edge.node->dt; - TB_Node *phi = tb_inst_incomplete_phi(p->func, dt, done, done->input_count); - for (size_t i = 0; i < done->input_count; i++) { - TB_Node *val = short_circuit.node; - TB_Node *region = done->inputs[i]; - if (region == edge_region) { - val = edge.node; - } - tb_inst_add_phi_operand(p->func, phi, region, val); - } - return cg_emit_conv(p, cg_value(phi, t_bool), final_type); -} - - - -gb_internal cgValue cg_build_binary_expr(cgProcedure *p, Ast *expr) { - ast_node(be, BinaryExpr, expr); - - TypeAndValue tv = type_and_value_of_expr(expr); - - if (is_type_matrix(be->left->tav.type) || is_type_matrix(be->right->tav.type)) { - cgValue left = cg_build_expr(p, be->left); - cgValue right = cg_build_expr(p, be->right); - GB_PANIC("TODO(bill): cg_emit_arith_matrix"); - // return cg_emit_arith_matrix(p, be->op.kind, left, right, default_type(tv.type), false); - } - - - switch (be->op.kind) { - case Token_Add: - case Token_Sub: - case Token_Mul: - case Token_Quo: - case Token_Mod: - case Token_ModMod: - case Token_And: - case Token_Or: - case Token_Xor: - case Token_AndNot: { - Type *type = default_type(tv.type); - cgValue left = cg_build_expr(p, be->left); - cgValue right = cg_build_expr(p, be->right); - return cg_emit_arith(p, be->op.kind, left, right, type); - } - - case Token_Shl: - case Token_Shr: { - cgValue left, right; - Type *type = default_type(tv.type); - left = cg_build_expr(p, be->left); - - if (cg_is_expr_untyped_const(be->right)) { - // NOTE(bill): RHS shift operands can still be untyped - // Just bypass the standard cg_build_expr - right = cg_expr_untyped_const_to_typed(p, be->right, type); - } else { - right = cg_build_expr(p, be->right); - } - return cg_emit_arith(p, be->op.kind, left, right, type); - } - - case Token_CmpEq: - case Token_NotEq: - if (is_type_untyped_nil(be->right->tav.type)) { - // `x == nil` or `x != nil` - cgValue left = cg_build_expr(p, be->left); - cgValue cmp = cg_emit_comp_against_nil(p, be->op.kind, left); - Type *type = default_type(tv.type); - return cg_emit_conv(p, cmp, type); - } else if (is_type_untyped_nil(be->left->tav.type)) { - // `nil == x` or `nil != x` - cgValue right = cg_build_expr(p, be->right); - cgValue cmp = cg_emit_comp_against_nil(p, be->op.kind, right); - Type *type = default_type(tv.type); - return cg_emit_conv(p, cmp, type); - }/* else if (cg_is_empty_string_constant(be->right)) { - // `x == ""` or `x != ""` - cgValue s = cg_build_expr(p, be->left); - s = cg_emit_conv(p, s, t_string); - cgValue len = cg_string_len(p, s); - cgValue cmp = cg_emit_comp(p, be->op.kind, len, cg_const_int(p->module, t_int, 0)); - Type *type = default_type(tv.type); - return cg_emit_conv(p, cmp, type); - } else if (cg_is_empty_string_constant(be->left)) { - // `"" == x` or `"" != x` - cgValue s = cg_build_expr(p, be->right); - s = cg_emit_conv(p, s, t_string); - cgValue len = cg_string_len(p, s); - cgValue cmp = cg_emit_comp(p, be->op.kind, len, cg_const_int(p->module, t_int, 0)); - Type *type = default_type(tv.type); - return cg_emit_conv(p, cmp, type); - }*/ - /*fallthrough*/ - case Token_Lt: - case Token_LtEq: - case Token_Gt: - case Token_GtEq: - { - cgValue left = {}; - cgValue right = {}; - - if (be->left->tav.mode == Addressing_Type) { - left = cg_typeid(p, be->left->tav.type); - } - if (be->right->tav.mode == Addressing_Type) { - right = cg_typeid(p, be->right->tav.type); - } - if (left.node == nullptr) left = cg_build_expr(p, be->left); - if (right.node == nullptr) right = cg_build_expr(p, be->right); - cgValue cmp = cg_emit_comp(p, be->op.kind, left, right); - Type *type = default_type(tv.type); - return cg_emit_conv(p, cmp, type); - } - - case Token_CmpAnd: - case Token_CmpOr: - return cg_build_logical_binary_expr(p, be->op.kind, be->left, be->right, tv.type); - - case Token_in: - case Token_not_in: - { - cgValue left = cg_build_expr(p, be->left); - cgValue right = cg_build_expr(p, be->right); - Type *rt = base_type(right.type); - if (is_type_pointer(rt)) { - right = cg_emit_load(p, right); - rt = base_type(type_deref(rt)); - } - - switch (rt->kind) { - case Type_Map: - { - cgValue map_ptr = cg_address_from_load_or_generate_local(p, right); - cgValue key = left; - cgValue ptr = cg_internal_dynamic_map_get_ptr(p, map_ptr, key); - if (be->op.kind == Token_in) { - return cg_emit_conv(p, cg_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); - } else { - return cg_emit_conv(p, cg_emit_comp_against_nil(p, Token_CmpEq, ptr), t_bool); - } - } - break; - case Type_BitSet: - { - Type *key_type = rt->BitSet.elem; - GB_ASSERT(are_types_identical(left.type, key_type)); - - Type *it = bit_set_to_int(rt); - left = cg_emit_conv(p, left, it); - if (is_type_different_to_arch_endianness(it)) { - left = cg_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it)); - } - - cgValue lower = cg_const_value(p, left.type, exact_value_i64(rt->BitSet.lower)); - cgValue key = cg_emit_arith(p, Token_Sub, left, lower, left.type); - cgValue bit = cg_emit_arith(p, Token_Shl, cg_const_int(p, left.type, 1), key, left.type); - bit = cg_emit_conv(p, bit, it); - - cgValue old_value = cg_emit_transmute(p, right, it); - cgValue new_value = cg_emit_arith(p, Token_And, old_value, bit, it); - - GB_PANIC("TODO(bill): cg_emit_comp"); - // TokenKind op = (be->op.kind == Token_in) ? Token_NotEq : Token_CmpEq; - // return cg_emit_conv(p, cg_emit_comp(p, op, new_value, cg_const_int(p, new_value.type, 0)), t_bool); - } - break; - default: - GB_PANIC("Invalid 'in' type"); - } - break; - } - break; - default: - GB_PANIC("Invalid binary expression"); - break; - } - return {}; -} - -gb_internal cgValue cg_build_cond(cgProcedure *p, Ast *cond, TB_Node *true_block, TB_Node *false_block) { - cond = unparen_expr(cond); - - GB_ASSERT(cond != nullptr); - GB_ASSERT(true_block != nullptr); - GB_ASSERT(false_block != nullptr); - - // Use to signal not to do compile time short circuit for consts - cgValue no_comptime_short_circuit = {}; - - switch (cond->kind) { - case_ast_node(ue, UnaryExpr, cond); - if (ue->op.kind == Token_Not) { - cgValue cond_val = cg_build_cond(p, ue->expr, false_block, true_block); - return cond_val; - // if (cond_val.value && LLVMIsConstant(cond_val.value)) { - // return cg_const_bool(p->module, cond_val.type, LLVMConstIntGetZExtValue(cond_val.value) == 0); - // } - // return no_comptime_short_circuit; - } - case_end; - - case_ast_node(be, BinaryExpr, cond); - if (be->op.kind == Token_CmpAnd) { - TB_Node *block = cg_control_region(p, "cmp_and"); - cg_build_cond(p, be->left, block, false_block); - tb_inst_set_control(p->func, block); - cg_build_cond(p, be->right, true_block, false_block); - return no_comptime_short_circuit; - } else if (be->op.kind == Token_CmpOr) { - TB_Node *block = cg_control_region(p, "cmp_or"); - cg_build_cond(p, be->left, true_block, block); - tb_inst_set_control(p->func, block); - cg_build_cond(p, be->right, true_block, false_block); - return no_comptime_short_circuit; - } - case_end; - } - - cgValue v = {}; - if (cg_is_expr_untyped_const(cond)) { - v = cg_expr_untyped_const_to_typed(p, cond, t_bool); - } else { - v = cg_build_expr(p, cond); - } - cg_emit_if(p, v, true_block, false_block); - return v; -} - -gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr); -gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) { - cg_set_debug_pos_from_node(p, expr); - - u16 prev_state_flags = p->state_flags; - defer (p->state_flags = prev_state_flags); - - if (expr->state_flags != 0) { - u16 in = expr->state_flags; - u16 out = p->state_flags; - - if (in & StateFlag_bounds_check) { - out |= StateFlag_bounds_check; - out &= ~StateFlag_no_bounds_check; - } else if (in & StateFlag_no_bounds_check) { - out |= StateFlag_no_bounds_check; - out &= ~StateFlag_bounds_check; - } - - if (in & StateFlag_type_assert) { - out |= StateFlag_type_assert; - out &= ~StateFlag_no_type_assert; - } else if (in & StateFlag_no_type_assert) { - out |= StateFlag_no_type_assert; - out &= ~StateFlag_type_assert; - } - - p->state_flags = out; - } - - - // IMPORTANT NOTE(bill): - // Selector Call Expressions (foo->bar(...)) - // must only evaluate `foo` once as it gets transformed into - // `foo.bar(foo, ...)` - // And if `foo` is a procedure call or something more complex, storing the value - // once is a very good idea - // If a stored value is found, it must be removed from the cache - if (expr->state_flags & StateFlag_SelectorCallExpr) { - // cgValue *pp = map_get(&p->selector_values, expr); - // if (pp != nullptr) { - // cgValue res = *pp; - // map_remove(&p->selector_values, expr); - // return res; - // } - // cgAddr *pa = map_get(&p->selector_addr, expr); - // if (pa != nullptr) { - // cgAddr res = *pa; - // map_remove(&p->selector_addr, expr); - // return cg_addr_load(p, res); - // } - } - - cgValue res = cg_build_expr_internal(p, expr); - if (res.kind == cgValue_Symbol) { - GB_ASSERT(is_type_internally_pointer_like(res.type)); - res = cg_value(tb_inst_get_symbol_address(p->func, res.symbol), res.type); - } - - if (expr->state_flags & StateFlag_SelectorCallExpr) { - // map_set(&p->selector_values, expr, res); - } - return res; -} - - -gb_internal cgValue cg_find_ident(cgProcedure *p, Entity *e, Ast *expr) { - cgAddr *found_addr = map_get(&p->variable_map, e); - if (found_addr) { - return cg_addr_load(p, *found_addr); - } - - cgValue *found = nullptr; - rw_mutex_shared_lock(&p->module->values_mutex); - found = map_get(&p->module->values, e); - rw_mutex_shared_unlock(&p->module->values_mutex); - - if (found) { - - auto v = *found; - // NOTE(bill): This is because pointers are already pointers in LLVM - if (is_type_proc(v.type)) { - return v; - } - return cg_emit_load(p, v); - } else if (e != nullptr && e->kind == Entity_Variable) { - return cg_addr_load(p, cg_build_addr(p, expr)); - } - - if (e->kind == Entity_Procedure) { - return cg_find_procedure_value_from_entity(p->module, e); - } - - String pkg = {}; - if (e->pkg) { - pkg = e->pkg->name; - } - gb_printf_err("Error in: %s\n", token_pos_to_string(ast_token(expr).pos)); - GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(pkg), LIT(e->token.string), e, type_to_string(e->type), expr); - return {}; -} - -cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) { - struct cgCompoundLitElemTempData { - Ast * expr; - cgValue value; - i64 elem_index; - i64 elem_length; - cgValue gep; - }; - - - auto const &populate = [](cgProcedure *p, Slice const &elems, Array *temp_data, Type *compound_type) { - Type *bt = base_type(compound_type); - Type *et = nullptr; - switch (bt->kind) { - case Type_Array: et = bt->Array.elem; break; - case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break; - case Type_Slice: et = bt->Slice.elem; break; - case Type_BitSet: et = bt->BitSet.elem; break; - case Type_DynamicArray: et = bt->DynamicArray.elem; break; - case Type_SimdVector: et = bt->SimdVector.elem; break; - case Type_Matrix: et = bt->Matrix.elem; break; - } - GB_ASSERT(et != nullptr); - - - // NOTE(bill): Separate value, gep, store into their own chunks - for_array(i, elems) { - Ast *elem = elems[i]; - if (elem->kind == Ast_FieldValue) { - ast_node(fv, FieldValue, elem); - if (is_ast_range(fv->field)) { - ast_node(ie, BinaryExpr, fv->field); - TypeAndValue lo_tav = ie->left->tav; - TypeAndValue hi_tav = ie->right->tav; - GB_ASSERT(lo_tav.mode == Addressing_Constant); - GB_ASSERT(hi_tav.mode == Addressing_Constant); - - TokenKind op = ie->op.kind; - i64 lo = exact_value_to_i64(lo_tav.value); - i64 hi = exact_value_to_i64(hi_tav.value); - if (op != Token_RangeHalf) { - hi += 1; - } - - cgValue value = cg_emit_conv(p, cg_build_expr(p, fv->value), et); - - GB_ASSERT((hi-lo) > 0); - - if (bt->kind == Type_Matrix) { - GB_PANIC("TODO(bill): Type_Matrix"); - // for (i64 k = lo; k < hi; k++) { - // cgCompoundLitElemTempData data = {}; - // data.value = value; - - // data.elem_index = matrix_row_major_index_to_offset(bt, k); - // array_add(temp_data, data); - // } - } else { - enum {MAX_ELEMENT_AMOUNT = 32}; - if ((hi-lo) <= MAX_ELEMENT_AMOUNT) { - for (i64 k = lo; k < hi; k++) { - cgCompoundLitElemTempData data = {}; - data.value = value; - data.elem_index = k; - array_add(temp_data, data); - } - } else { - cgCompoundLitElemTempData data = {}; - data.value = value; - data.elem_index = lo; - data.elem_length = hi-lo; - array_add(temp_data, data); - } - } - } else { - auto tav = fv->field->tav; - GB_ASSERT(tav.mode == Addressing_Constant); - i64 index = exact_value_to_i64(tav.value); - - cgValue value = cg_emit_conv(p, cg_build_expr(p, fv->value), et); - GB_ASSERT(!is_type_tuple(value.type)); - - cgCompoundLitElemTempData data = {}; - data.value = value; - data.expr = fv->value; - if (bt->kind == Type_Matrix) { - GB_PANIC("TODO(bill): Type_Matrix"); - // data.elem_index = matrix_row_major_index_to_offset(bt, index); - } else { - data.elem_index = index; - } - array_add(temp_data, data); - } - - } else { - // if (bt->kind != Type_DynamicArray && lb_is_elem_const(elem, et)) { - // continue; - // } - - cgValue field_expr = cg_build_expr(p, elem); - GB_ASSERT(!is_type_tuple(field_expr.type)); - - cgValue ev = cg_emit_conv(p, field_expr, et); - - cgCompoundLitElemTempData data = {}; - data.value = ev; - if (bt->kind == Type_Matrix) { - GB_PANIC("TODO(bill): Type_Matrix"); - // data.elem_index = matrix_row_major_index_to_offset(bt, i); - } else { - data.elem_index = i; - } - array_add(temp_data, data); - } - } - }; - - auto const &assign_array = [](cgProcedure *p, Array const &temp_data) { - for (auto const &td : temp_data) if (td.value.node != nullptr) { - if (td.elem_length > 0) { - GB_PANIC("TODO(bill): range"); - // auto loop_data = cg_loop_start(p, cast(isize)td.elem_length, t_i32); - // { - // cgValue dst = td.gep; - // dst = cg_emit_ptr_offset(p, dst, loop_data.idx); - // cg_emit_store(p, dst, td.value); - // } - // cg_loop_end(p, loop_data); - } else { - cg_emit_store(p, td.gep, td.value); - } - } - }; - - - - ast_node(cl, CompoundLit, expr); - - Type *type = type_of_expr(expr); - Type *bt = base_type(type); - - cgAddr v = {}; - if (p->is_startup) { - v = cg_add_global(p, type, nullptr); - } else { - v = cg_add_local(p, type, nullptr, true); - } - - if (cl->elems.count == 0) { - // No need to create it - return v; - } - - TEMPORARY_ALLOCATOR_GUARD(); - - Type *et = nullptr; - switch (bt->kind) { - case Type_Array: et = bt->Array.elem; break; - case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break; - case Type_Slice: et = bt->Slice.elem; break; - case Type_BitSet: et = bt->BitSet.elem; break; - case Type_SimdVector: et = bt->SimdVector.elem; break; - case Type_Matrix: et = bt->Matrix.elem; break; - } - - String proc_name = {}; - if (p->entity) { - proc_name = p->entity->token.string; - } - TokenPos pos = ast_token(expr).pos; - - - switch (bt->kind) { - default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; - - case Type_Struct: { - TypeStruct *st = &bt->Struct; - cgValue comp_lit_ptr = cg_addr_get_ptr(p, v); - - for_array(field_index, cl->elems) { - Ast *elem = cl->elems[field_index]; - - cgValue field_expr = {}; - Entity *field = nullptr; - isize index = field_index; - - if (elem->kind == Ast_FieldValue) { - ast_node(fv, FieldValue, elem); - String name = fv->field->Ident.token.string; - Selection sel = lookup_field(bt, name, false); - GB_ASSERT(!sel.indirect); - - elem = fv->value; - if (sel.index.count > 1) { - cgValue dst = cg_emit_deep_field_gep(p, comp_lit_ptr, sel); - field_expr = cg_build_expr(p, elem); - field_expr = cg_emit_conv(p, field_expr, sel.entity->type); - cg_emit_store(p, dst, field_expr); - continue; - } - - index = sel.index[0]; - } else { - Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index); - GB_ASSERT(sel.index.count == 1); - GB_ASSERT(!sel.indirect); - index = sel.index[0]; - } - - field = st->fields[index]; - Type *ft = field->type; - - field_expr = cg_build_expr(p, elem); - - cgValue gep = {}; - if (st->is_raw_union) { - gep = cg_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft)); - } else { - gep = cg_emit_struct_ep(p, comp_lit_ptr, cast(i32)index); - } - - Type *fet = field_expr.type; - GB_ASSERT(fet->kind != Type_Tuple); - - // HACK TODO(bill): THIS IS A MASSIVE HACK!!!! - if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) { - GB_ASSERT_MSG(union_variant_index(ft, fet) >= 0, "%s", type_to_string(fet)); - - GB_PANIC("TODO(bill): cg_emit_store_union_variant"); - // cg_emit_store_union_variant(p, gep, field_expr, fet); - } else { - cgValue fv = cg_emit_conv(p, field_expr, ft); - cg_emit_store(p, gep, fv); - } - } - return v; - } - - case Type_Map: { - GB_ASSERT(!build_context.no_dynamic_literals); - GB_PANIC("TODO(bill): map literals"); - - // cgValue err = cg_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); - // gb_unused(err); - - // for (Ast *elem : cl->elems) { - // ast_node(fv, FieldValue, elem); - - // cgValue key = cg_build_expr(p, fv->field); - // cgValue value = cg_build_expr(p, fv->value); - // cg_internal_dynamic_map_set(p, v.addr, type, key, value, elem); - // } - break; - } - - case Type_Array: { - auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - - populate(p, cl->elems, &temp_data, type); - - cgValue dst_ptr = cg_addr_get_ptr(p, v); - for_array(i, temp_data) { - i32 index = cast(i32)(temp_data[i].elem_index); - temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index); - } - - assign_array(p, temp_data); - break; - } - case Type_EnumeratedArray: { - auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - - populate(p, cl->elems, &temp_data, type); - - cgValue dst_ptr = cg_addr_get_ptr(p, v); - i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value); - for_array(i, temp_data) { - i32 index = cast(i32)(temp_data[i].elem_index - index_offset); - temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index); - } - - assign_array(p, temp_data); - break; - } - case Type_Slice: { - isize count = gb_max(cl->elems.count, cl->max_count); - - TB_CharUnits backing_size = cast(TB_CharUnits)(type_size_of(bt->Slice.elem) * count); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(bt->Slice.elem); - - TB_Node *backing = nullptr; - if (p->is_startup) { - TB_Global *global = tb_global_create(p->module->mod, 0, "", nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(p->module->mod, tb_module_get_data(p->module->mod), global, backing_size, align, 0); - backing = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); - } else { - backing = tb_inst_local(p->func, backing_size, align); - } - - cgValue data = cg_value(backing, alloc_type_multi_pointer(bt->Slice.elem)); - - auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - populate(p, cl->elems, &temp_data, type); - - - for_array(i, temp_data) { - temp_data[i].gep = cg_emit_ptr_offset(p, data, cg_const_int(p, t_int, temp_data[i].elem_index)); - } - - assign_array(p, temp_data); - cg_fill_slice(p, v, data, cg_const_int(p, t_int, count)); - return v; - } - - case Type_DynamicArray: { - GB_ASSERT(!build_context.no_dynamic_literals); - - Type *et = bt->DynamicArray.elem; - cgValue size = cg_const_int(p, t_int, type_size_of(et)); - cgValue align = cg_const_int(p, t_int, type_align_of(et)); - - i64 item_count = gb_max(cl->max_count, cl->elems.count); - { - - auto args = slice_make(temporary_allocator(), 5); - args[0] = cg_emit_conv(p, cg_addr_get_ptr(p, v), t_rawptr); - args[1] = size; - args[2] = align; - args[3] = cg_const_int(p, t_int, item_count); - args[4] = cg_emit_source_code_location_as_global(p, proc_name, pos); - cg_emit_runtime_call(p, "__dynamic_array_reserve", args); - } - - Type *array_type = alloc_type_array(et, item_count); - cgAddr items_addr = cg_add_local(p, array_type, nullptr, true); - cgValue items = cg_addr_get_ptr(p, items_addr); - - auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - populate(p, cl->elems, &temp_data, type); - - for_array(i, temp_data) { - temp_data[i].gep = cg_emit_array_epi(p, items, temp_data[i].elem_index); - } - assign_array(p, temp_data); - - { - auto args = slice_make(temporary_allocator(), 6); - args[0] = cg_emit_conv(p, v.addr, t_rawptr); - args[1] = size; - args[2] = align; - args[3] = cg_emit_conv(p, items, t_rawptr); - args[4] = cg_const_int(p, t_int, item_count); - args[5] = cg_emit_source_code_location_as_global(p, proc_name, pos); - cg_emit_runtime_call(p, "__dynamic_array_append", args); - } - break; - } - - case Type_Basic: { - GB_ASSERT(is_type_any(bt)); - String field_names[2] = { - str_lit("data"), - str_lit("id"), - }; - Type *field_types[2] = { - t_rawptr, - t_typeid, - }; - - for_array(field_index, cl->elems) { - Ast *elem = cl->elems[field_index]; - - cgValue field_expr = {}; - isize index = field_index; - - if (elem->kind == Ast_FieldValue) { - ast_node(fv, FieldValue, elem); - Selection sel = lookup_field(bt, fv->field->Ident.token.string, false); - index = sel.index[0]; - elem = fv->value; - } else { - TypeAndValue tav = type_and_value_of_expr(elem); - Selection sel = lookup_field(bt, field_names[field_index], false); - index = sel.index[0]; - } - - field_expr = cg_build_expr(p, elem); - - GB_ASSERT(field_expr.type->kind != Type_Tuple); - - Type *ft = field_types[index]; - cgValue fv = cg_emit_conv(p, field_expr, ft); - cgValue gep = cg_emit_struct_ep(p, cg_addr_get_ptr(p, v), index); - cg_emit_store(p, gep, fv); - } - break; - } - - case Type_BitSet: { - i64 sz = type_size_of(type); - if (sz == 0) { - return v; - } - cgValue lower = cg_const_value(p, t_int, exact_value_i64(bt->BitSet.lower)); - Type *it = bit_set_to_int(bt); - cgValue one = cg_const_value(p, it, exact_value_i64(1)); - for (Ast *elem : cl->elems) { - GB_ASSERT(elem->kind != Ast_FieldValue); - - cgValue expr = cg_build_expr(p, elem); - GB_ASSERT(expr.type->kind != Type_Tuple); - - cgValue e = cg_emit_conv(p, expr, it); - e = cg_emit_arith(p, Token_Sub, e, lower, it); - e = cg_emit_arith(p, Token_Shl, one, e, it); - - cgValue old_value = cg_emit_transmute(p, cg_addr_load(p, v), it); - cgValue new_value = cg_emit_arith(p, Token_Or, old_value, e, it); - new_value = cg_emit_transmute(p, new_value, type); - cg_addr_store(p, v, new_value); - } - return v; - } - - case Type_Matrix: { - auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - - populate(p, cl->elems, &temp_data, type); - - cgValue dst_ptr = cg_addr_get_ptr(p, v); - for_array(i, temp_data) { - temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, temp_data[i].elem_index); - } - - assign_array(p, temp_data); - break; - } - - case Type_SimdVector: { - // auto temp_data = array_make(temporary_allocator(), 0, cl->elems.count); - - // populate(p, cl->elems, &temp_data, type); - - // // TODO(bill): reduce the need for individual `insertelement` if a `shufflevector` - // // might be a better option - // for (auto const &td : temp_data) if (td.value.node != nullptr) { - // if (td.elem_length > 0) { - // for (i64 k = 0; k < td.elem_length; k++) { - // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index + k).value; - // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); - // } - // } else { - // LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index).value; - // vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, ""); - - // } - // } - break; - } - } - - return v; -} - -gb_internal cgValue cg_make_soa_pointer(cgProcedure *p, Type *type, cgValue const &addr, cgValue const &index) { - cgAddr v = cg_add_local(p, type, nullptr, true); - cgValue ptr = cg_emit_struct_ep(p, v.addr, 0); - cgValue idx = cg_emit_struct_ep(p, v.addr, 1); - cg_emit_store(p, ptr, addr); - cg_emit_store(p, idx, cg_emit_conv(p, index, t_int)); - - return cg_addr_load(p, v); -} - -gb_internal cgValue cg_build_unary_and(cgProcedure *p, Ast *expr) { - ast_node(ue, UnaryExpr, expr); - auto tv = type_and_value_of_expr(expr); - - - Ast *ue_expr = unparen_expr(ue->expr); - if (ue_expr->kind == Ast_IndexExpr && tv.mode == Addressing_OptionalOkPtr && is_type_tuple(tv.type)) { - GB_PANIC("TODO(bill): &m[k]"); - // Type *tuple = tv.type; - - // Type *map_type = type_of_expr(ue_expr->IndexExpr.expr); - // Type *ot = base_type(map_type); - // Type *t = base_type(type_deref(ot)); - // bool deref = t != ot; - // GB_ASSERT(t->kind == Type_Map); - // ast_node(ie, IndexExpr, ue_expr); - - // cgValue map_val = cg_build_addr_ptr(p, ie->expr); - // if (deref) { - // map_val = cg_emit_load(p, map_val); - // } - - // cgValue key = lb_build_expr(p, ie->index); - // key = lb_emit_conv(p, key, t->Map.key); - - // lbAddr addr = lb_addr_map(map_val, key, t, alloc_type_pointer(t->Map.value)); - // lbValue ptr = lb_addr_get_ptr(p, addr); - - // lbValue ok = lb_emit_comp_against_nil(p, Token_NotEq, ptr); - // ok = lb_emit_conv(p, ok, tuple->Tuple.variables[1]->type); - - // lbAddr res = lb_add_local_generated(p, tuple, false); - // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); - // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); - // lb_emit_store(p, gep0, ptr); - // lb_emit_store(p, gep1, ok); - // return lb_addr_load(p, res); - - } else if (is_type_soa_pointer(tv.type)) { - ast_node(ie, IndexExpr, ue_expr); - cgValue addr = cg_build_addr_ptr(p, ie->expr); - cgValue index = cg_build_expr(p, ie->index); - - if (!build_context.no_bounds_check) { - // TODO(bill): soa bounds checking - } - - return cg_make_soa_pointer(p, tv.type, addr, index); - } else if (ue_expr->kind == Ast_CompoundLit) { - cgAddr addr = cg_build_addr_compound_lit(p, expr); - return addr.addr; - } else if (ue_expr->kind == Ast_TypeAssertion) { - GB_PANIC("TODO(bill): &v.(T)"); - // if (is_type_tuple(tv.type)) { - // Type *tuple = tv.type; - // Type *ptr_type = tuple->Tuple.variables[0]->type; - // Type *ok_type = tuple->Tuple.variables[1]->type; - - // ast_node(ta, TypeAssertion, ue_expr); - // TokenPos pos = ast_token(expr).pos; - // Type *type = type_of_expr(ue_expr); - // GB_ASSERT(!is_type_tuple(type)); - - // lbValue e = lb_build_expr(p, ta->expr); - // Type *t = type_deref(e.type); - // if (is_type_union(t)) { - // lbValue v = e; - // if (!is_type_pointer(v.type)) { - // v = lb_address_from_load_or_generate_local(p, v); - // } - // Type *src_type = type_deref(v.type); - // Type *dst_type = type; - - // lbValue src_tag = {}; - // lbValue dst_tag = {}; - // if (is_type_union_maybe_pointer(src_type)) { - // src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); - // dst_tag = lb_const_bool(p->module, t_bool, true); - // } else { - // src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); - // dst_tag = lb_const_union_tag(p->module, src_type, dst_type); - // } - - // lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); - - // lbValue data_ptr = lb_emit_conv(p, v, ptr_type); - // lbAddr res = lb_add_local_generated(p, tuple, true); - // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); - // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); - // lb_emit_store(p, gep0, lb_emit_select(p, ok, data_ptr, lb_const_nil(p->module, ptr_type))); - // lb_emit_store(p, gep1, lb_emit_conv(p, ok, ok_type)); - // return lb_addr_load(p, res); - // } else if (is_type_any(t)) { - // lbValue v = e; - // if (is_type_pointer(v.type)) { - // v = lb_emit_load(p, v); - // } - - // lbValue data_ptr = lb_emit_conv(p, lb_emit_struct_ev(p, v, 0), ptr_type); - // lbValue any_id = lb_emit_struct_ev(p, v, 1); - // lbValue id = lb_typeid(p->module, type); - - // lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); - - // lbAddr res = lb_add_local_generated(p, tuple, false); - // lbValue gep0 = lb_emit_struct_ep(p, res.addr, 0); - // lbValue gep1 = lb_emit_struct_ep(p, res.addr, 1); - // lb_emit_store(p, gep0, lb_emit_select(p, ok, data_ptr, lb_const_nil(p->module, ptr_type))); - // lb_emit_store(p, gep1, lb_emit_conv(p, ok, ok_type)); - // return lb_addr_load(p, res); - // } else { - // GB_PANIC("TODO(bill): type assertion %s", type_to_string(type)); - // } - - // } else { - // GB_ASSERT(is_type_pointer(tv.type)); - - // ast_node(ta, TypeAssertion, ue_expr); - // TokenPos pos = ast_token(expr).pos; - // Type *type = type_of_expr(ue_expr); - // GB_ASSERT(!is_type_tuple(type)); - - // lbValue e = lb_build_expr(p, ta->expr); - // Type *t = type_deref(e.type); - // if (is_type_union(t)) { - // lbValue v = e; - // if (!is_type_pointer(v.type)) { - // v = lb_address_from_load_or_generate_local(p, v); - // } - // Type *src_type = type_deref(v.type); - // Type *dst_type = type; - - - // if ((p->state_flags & StateFlag_no_type_assert) == 0) { - // lbValue src_tag = {}; - // lbValue dst_tag = {}; - // if (is_type_union_maybe_pointer(src_type)) { - // src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); - // dst_tag = lb_const_bool(p->module, t_bool, true); - // } else { - // src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); - // dst_tag = lb_const_union_tag(p->module, src_type, dst_type); - // } - - - // isize arg_count = 6; - // if (build_context.no_rtti) { - // arg_count = 4; - // } - - // lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); - // auto args = array_make(permanent_allocator(), arg_count); - // args[0] = ok; - - // args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); - // args[2] = lb_const_int(p->module, t_i32, pos.line); - // args[3] = lb_const_int(p->module, t_i32, pos.column); - - // if (!build_context.no_rtti) { - // args[4] = lb_typeid(p->module, src_type); - // args[5] = lb_typeid(p->module, dst_type); - // } - // lb_emit_runtime_call(p, "type_assertion_check", args); - // } - - // lbValue data_ptr = v; - // return lb_emit_conv(p, data_ptr, tv.type); - // } else if (is_type_any(t)) { - // lbValue v = e; - // if (is_type_pointer(v.type)) { - // v = lb_emit_load(p, v); - // } - // lbValue data_ptr = lb_emit_struct_ev(p, v, 0); - // if ((p->state_flags & StateFlag_no_type_assert) == 0) { - // GB_ASSERT(!build_context.no_rtti); - - // lbValue any_id = lb_emit_struct_ev(p, v, 1); - - // lbValue id = lb_typeid(p->module, type); - // lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); - // auto args = array_make(permanent_allocator(), 6); - // args[0] = ok; - - // args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); - // args[2] = lb_const_int(p->module, t_i32, pos.line); - // args[3] = lb_const_int(p->module, t_i32, pos.column); - - // args[4] = any_id; - // args[5] = id; - // lb_emit_runtime_call(p, "type_assertion_check", args); - // } - - // return lb_emit_conv(p, data_ptr, tv.type); - // } else { - // GB_PANIC("TODO(bill): type assertion %s", type_to_string(type)); - // } - // } - } - - return cg_build_addr_ptr(p, ue->expr); -} - -gb_internal cgValue cg_emit_cast_union(cgProcedure *p, cgValue value, Type *type, TokenPos pos) { - Type *src_type = value.type; - bool is_ptr = is_type_pointer(src_type); - - bool is_tuple = true; - Type *tuple = type; - if (type->kind != Type_Tuple) { - is_tuple = false; - tuple = make_optional_ok_type(type); - } - - - if (is_ptr) { - value = cg_emit_load(p, value); - } - Type *src = base_type(type_deref(src_type)); - GB_ASSERT_MSG(is_type_union(src), "%s", type_to_string(src_type)); - Type *dst = tuple->Tuple.variables[0]->type; - - cgValue value_ = cg_address_from_load_or_generate_local(p, value); - - if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) { - // just do a bit cast of the data at the front - cgValue ptr = cg_emit_conv(p, value_, alloc_type_pointer(type)); - return cg_emit_load(p, ptr); - } - - - cgValue tag = {}; - cgValue dst_tag = {}; - cgValue cond = {}; - cgValue data = {}; - - cgValue gep0 = cg_add_local(p, tuple->Tuple.variables[0]->type, nullptr, true).addr; - cgValue gep1 = cg_add_local(p, tuple->Tuple.variables[1]->type, nullptr, true).addr; - - if (is_type_union_maybe_pointer(src)) { - data = cg_emit_load(p, cg_emit_conv(p, value_, gep0.type)); - } else { - tag = cg_emit_load(p, cg_emit_union_tag_ptr(p, value_)); - dst_tag = cg_const_union_tag(p, src, dst); - } - - TB_Node *ok_block = cg_control_region(p, "union_cast_ok"); - TB_Node *end_block = cg_control_region(p, "union_cast_end"); - - if (data.node != nullptr) { - GB_ASSERT(is_type_union_maybe_pointer(src)); - cond = cg_emit_comp_against_nil(p, Token_NotEq, data); - } else { - cond = cg_emit_comp(p, Token_CmpEq, tag, dst_tag); - } - - cg_emit_if(p, cond, ok_block, end_block); - tb_inst_set_control(p->func, ok_block); - - if (data.node == nullptr) { - data = cg_emit_load(p, cg_emit_conv(p, value_, gep0.type)); - } - cg_emit_store(p, gep0, data); - cg_emit_store(p, gep1, cg_const_bool(p, t_bool, true)); - - cg_emit_goto(p, end_block); - tb_inst_set_control(p->func, end_block); - - if (!is_tuple) { - GB_ASSERT((p->state_flags & StateFlag_no_type_assert) == 0); - // NOTE(bill): Panic on invalid conversion - Type *dst_type = tuple->Tuple.variables[0]->type; - - isize arg_count = 7; - if (build_context.no_rtti) { - arg_count = 4; - } - - cgValue ok = cg_emit_load(p, gep1); - auto args = slice_make(permanent_allocator(), arg_count); - args[0] = ok; - - args[1] = cg_const_string(p, t_string, get_file_path_string(pos.file_id)); - args[2] = cg_const_int(p, t_i32, pos.line); - args[3] = cg_const_int(p, t_i32, pos.column); - - if (!build_context.no_rtti) { - args[4] = cg_typeid(p, src_type); - args[5] = cg_typeid(p, dst_type); - args[6] = cg_emit_conv(p, value_, t_rawptr); - } - cg_emit_runtime_call(p, "type_assertion_check2", args); - - return cg_emit_load(p, gep0); - } - - return cg_value_multi2(cg_emit_load(p, gep0), cg_emit_load(p, gep1), tuple); -} - -gb_internal cgValue cg_emit_cast_any(cgProcedure *p, cgValue value, Type *type, TokenPos pos) { - Type *src_type = value.type; - - if (is_type_pointer(src_type)) { - value = cg_emit_load(p, value); - } - - bool is_tuple = true; - Type *tuple = type; - if (type->kind != Type_Tuple) { - is_tuple = false; - tuple = make_optional_ok_type(type); - } - Type *dst_type = tuple->Tuple.variables[0]->type; - - if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) { - // just do a bit cast of the data at the front - cgValue ptr = cg_emit_struct_ev(p, value, 0); - ptr = cg_emit_conv(p, ptr, alloc_type_pointer(type)); - return cg_emit_load(p, ptr); - } - - cgValue dst_typeid = cg_typeid(p, dst_type); - cgValue any_typeid = cg_emit_struct_ev(p, value, 1); - - - TB_Node *ok_block = cg_control_region(p, "any_cast_ok"); - TB_Node *end_block = cg_control_region(p, "any_cast_end"); - cgValue cond = cg_emit_comp(p, Token_CmpEq, any_typeid, dst_typeid); - cg_emit_if(p, cond, ok_block, end_block); - tb_inst_set_control(p->func, ok_block); - - cgValue gep0 = cg_add_local(p, tuple->Tuple.variables[0]->type, nullptr, true).addr; - cgValue gep1 = cg_add_local(p, tuple->Tuple.variables[1]->type, nullptr, true).addr; - - cgValue any_data = cg_emit_struct_ev(p, value, 0); - cgValue ptr = cg_emit_conv(p, any_data, alloc_type_pointer(dst_type)); - cg_emit_store(p, gep0, cg_emit_load(p, ptr)); - cg_emit_store(p, gep1, cg_const_bool(p, t_bool, true)); - - cg_emit_goto(p, end_block); - tb_inst_set_control(p->func, end_block); - - if (!is_tuple) { - // NOTE(bill): Panic on invalid conversion - cgValue ok = cg_emit_load(p, gep1); - - isize arg_count = 7; - if (build_context.no_rtti) { - arg_count = 4; - } - auto args = slice_make(permanent_allocator(), arg_count); - args[0] = ok; - - args[1] = cg_const_string(p, t_string, get_file_path_string(pos.file_id)); - args[2] = cg_const_int(p, t_i32, pos.line); - args[3] = cg_const_int(p, t_i32, pos.column); - - if (!build_context.no_rtti) { - args[4] = any_typeid; - args[5] = dst_typeid; - args[6] = cg_emit_struct_ev(p, value, 0); - } - cg_emit_runtime_call(p, "type_assertion_check2", args); - - return cg_emit_load(p, gep0); - } - - return cg_value_multi2(cg_emit_load(p, gep0), cg_emit_load(p, gep1), tuple); -} - - -gb_internal cgValue cg_build_type_assertion(cgProcedure *p, Ast *expr, Type *type) { - ast_node(ta, TypeAssertion, expr); - - TokenPos pos = ast_token(expr).pos; - cgValue e = cg_build_expr(p, ta->expr); - Type *t = type_deref(e.type); - - if (is_type_union(t)) { - return cg_emit_cast_union(p, e, type, pos); - } else if (is_type_any(t)) { - return cg_emit_cast_any(p, e, type, pos); - } - GB_PANIC("TODO(bill): type assertion %s", type_to_string(e.type)); - return {}; -} - - -gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { - expr = unparen_expr(expr); - - TokenPos expr_pos = ast_token(expr).pos; - TypeAndValue tv = type_and_value_of_expr(expr); - Type *type = type_of_expr(expr); - GB_ASSERT_MSG(tv.mode != Addressing_Invalid, "invalid expression '%s' (tv.mode = %d, tv.type = %s) @ %s\n Current Proc: %.*s : %s", expr_to_string(expr), tv.mode, type_to_string(tv.type), token_pos_to_string(expr_pos), LIT(p->name), type_to_string(p->type)); - - if (tv.value.kind != ExactValue_Invalid && - expr->kind != Ast_CompoundLit) { - // NOTE(bill): The commented out code below is just for debug purposes only - // if (is_type_untyped(type)) { - // gb_printf_err("%s %s : %s @ %p\n", token_pos_to_string(expr_pos), expr_to_string(expr), type_to_string(expr->tav.type), expr); - // GB_PANIC("%s\n", type_to_string(tv.type)); - // } - // NOTE(bill): Short on constant values - return cg_const_value(p, type, tv.value); - } else if (tv.mode == Addressing_Type) { - // NOTE(bill, 2023-01-16): is this correct? I hope so at least - return cg_typeid(p, tv.type); - } - - switch (expr->kind) { - case_ast_node(bl, BasicLit, expr); - TokenPos pos = bl->token.pos; - GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(token_strings[bl->token.kind])); - case_end; - - case_ast_node(bd, BasicDirective, expr); - TokenPos pos = bd->token.pos; - GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(bd->name.string)); - case_end; - - case_ast_node(i, Ident, expr); - Entity *e = entity_from_expr(expr); - e = strip_entity_wrapping(e); - - GB_ASSERT_MSG(e != nullptr, "%s in %.*s %p", expr_to_string(expr), LIT(p->name), expr); - - if (e->kind == Entity_Builtin) { - Token token = ast_token(expr); - GB_PANIC("TODO(bill): lb_build_expr Entity_Builtin '%.*s'\n" - "\t at %s", LIT(builtin_procs[e->Builtin.id].name), - token_pos_to_string(token.pos)); - return {}; - } else if (e->kind == Entity_Nil) { - // TODO(bill): is this correct? - return cg_value(cast(TB_Node *)nullptr, e->type); - } - GB_ASSERT(e->kind != Entity_ProcGroup); - - cgAddr *addr = map_get(&p->variable_map, e); - if (addr) { - return cg_addr_load(p, *addr); - } - return cg_find_ident(p, e, expr); - case_end; - - case_ast_node(i, Implicit, expr); - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - case_ast_node(u, Uninit, expr); - if (is_type_untyped(type)) { - return cg_value(cast(TB_Node *)nullptr, t_untyped_uninit); - } - return cg_value(tb_inst_poison(p->func, cg_data_type(type)), type); - case_end; - - case_ast_node(de, DerefExpr, expr); - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - - case_ast_node(se, SelectorExpr, expr); - TypeAndValue tav = type_and_value_of_expr(expr); - GB_ASSERT(tav.mode != Addressing_Invalid); - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - case_ast_node(ise, ImplicitSelectorExpr, expr); - TypeAndValue tav = type_and_value_of_expr(expr); - GB_ASSERT(tav.mode == Addressing_Constant); - - return cg_const_value(p, type, tv.value); - case_end; - - - case_ast_node(se, SelectorCallExpr, expr); - GB_ASSERT(se->modified_call); - return cg_build_call_expr(p, se->call); - case_end; - - case_ast_node(i, CallExpr, expr); - return cg_build_call_expr(p, expr); - case_end; - - case_ast_node(cl, CompoundLit, expr); - cgAddr addr = cg_build_addr_compound_lit(p, expr); - return cg_addr_load(p, addr); - case_end; - - - case_ast_node(te, TernaryIfExpr, expr); - cgValue incoming_values[2] = {}; - TB_Node *incoming_regions[2] = {}; - - TB_Node *then = cg_control_region(p, "if_then"); - TB_Node *done = cg_control_region(p, "if_done"); - TB_Node *else_ = cg_control_region(p, "if_else"); - - cg_build_cond(p, te->cond, then, else_); - tb_inst_set_control(p->func, then); - - Type *type = default_type(type_of_expr(expr)); - - incoming_values [0] = cg_emit_conv(p, cg_build_expr(p, te->x), type); - incoming_regions[0] = tb_inst_get_control(p->func); - - cg_emit_goto(p, done); - tb_inst_set_control(p->func, else_); - - incoming_values [1] = cg_emit_conv(p, cg_build_expr(p, te->y), type); - incoming_regions[1] = tb_inst_get_control(p->func); - - cg_emit_goto(p, done); - tb_inst_set_control(p->func, done); - - GB_ASSERT(incoming_values[0].kind == cgValue_Value || - incoming_values[0].kind == cgValue_Addr); - GB_ASSERT(incoming_values[0].kind == incoming_values[1].kind); - - cgValue res = {}; - res.kind = incoming_values[0].kind; - res.type = type; - TB_DataType dt = cg_data_type(type); - if (res.kind == cgValue_Addr) { - dt = TB_TYPE_PTR; - } - res.node = tb_inst_incomplete_phi(p->func, dt, done, 2); - tb_inst_add_phi_operand(p->func, res.node, incoming_regions[0], incoming_values[0].node); - tb_inst_add_phi_operand(p->func, res.node, incoming_regions[1], incoming_values[1].node); - return res; - case_end; - - case_ast_node(te, TernaryWhenExpr, expr); - TypeAndValue tav = type_and_value_of_expr(te->cond); - GB_ASSERT(tav.mode == Addressing_Constant); - GB_ASSERT(tav.value.kind == ExactValue_Bool); - if (tav.value.value_bool) { - return cg_build_expr(p, te->x); - } else { - return cg_build_expr(p, te->y); - } - case_end; - - case_ast_node(tc, TypeCast, expr); - cgValue e = cg_build_expr(p, tc->expr); - switch (tc->token.kind) { - case Token_cast: - return cg_emit_conv(p, e, type); - case Token_transmute: - return cg_emit_transmute(p, e, type); - } - GB_PANIC("Invalid AST TypeCast"); - case_end; - - case_ast_node(ac, AutoCast, expr); - cgValue value = cg_build_expr(p, ac->expr); - return cg_emit_conv(p, value, type); - case_end; - - case_ast_node(se, SliceExpr, expr); - if (is_type_slice(type_of_expr(se->expr))) { - // NOTE(bill): Quick optimization - if (se->high == nullptr && - (se->low == nullptr || cg_is_expr_constant_zero(se->low))) { - return cg_build_expr(p, se->expr); - } - } - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - case_ast_node(ie, IndexExpr, expr); - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - case_ast_node(ie, MatrixIndexExpr, expr); - return cg_addr_load(p, cg_build_addr(p, expr)); - case_end; - - case_ast_node(ue, UnaryExpr, expr); - if (ue->op.kind == Token_And) { - return cg_build_unary_and(p, expr); - } - cgValue v = cg_build_expr(p, ue->expr); - return cg_emit_unary_arith(p, ue->op.kind, v, type); - case_end; - case_ast_node(be, BinaryExpr, expr); - return cg_build_binary_expr(p, expr); - case_end; - - case_ast_node(oe, OrReturnExpr, expr); - return cg_build_or_return(p, oe->expr, tv.type); - case_end; - - case_ast_node(oe, OrElseExpr, expr); - return cg_build_or_else(p, oe->x, oe->y, tv.type); - case_end; - - case_ast_node(ta, TypeAssertion, expr); - return cg_build_type_assertion(p, expr, tv.type); - case_end; - - case_ast_node(pl, ProcLit, expr); - cgProcedure *anon = cg_procedure_generate_anonymous(p->module, expr, p); - GB_ASSERT(anon != nullptr); - GB_ASSERT(anon->symbol != nullptr); - return cg_value(tb_inst_get_symbol_address(p->func, anon->symbol), type); - case_end; - - } - TokenPos token_pos = ast_token(expr).pos; - GB_PANIC("Unexpected expression\n" - "\tAst: %.*s @ " - "%s\n", - LIT(ast_strings[expr->kind]), - token_pos_to_string(token_pos)); - - return {}; -} - - -gb_internal cgValue cg_map_data_uintptr(cgProcedure *p, cgValue value) { - GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map)); - cgValue data = cg_emit_struct_ev(p, value, 0); - u64 mask_value = 0; - if (build_context.ptr_size == 4) { - mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1); - } else { - mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1); - } - cgValue mask = cg_const_int(p, t_uintptr, mask_value); - return cg_emit_arith(p, Token_And, data, mask, t_uintptr); -} - -gb_internal cgValue cg_gen_map_key_hash(cgProcedure *p, cgValue const &map_ptr, cgValue key, cgValue *key_ptr_) { - TEMPORARY_ALLOCATOR_GUARD(); - - cgValue key_ptr = cg_address_from_load_or_generate_local(p, key); - key_ptr = cg_emit_conv(p, key_ptr, t_rawptr); - - if (key_ptr_) *key_ptr_ = key_ptr; - - Type* key_type = base_type(type_deref(map_ptr.type))->Map.key; - - cgValue hasher = cg_hasher_proc_value_for_type(p, key_type); - - Slice args = {}; - args = slice_make(temporary_allocator(), 1); - args[0] = cg_map_data_uintptr(p, cg_emit_load(p, map_ptr)); - cgValue seed = cg_emit_runtime_call(p, "map_seed_from_map_data", args); - - args = slice_make(temporary_allocator(), 2); - args[0] = key_ptr; - args[1] = seed; - return cg_emit_call(p, hasher, args); -} - -gb_internal cgValue cg_internal_dynamic_map_get_ptr(cgProcedure *p, cgValue const &map_ptr, cgValue const &key) { - TEMPORARY_ALLOCATOR_GUARD(); - - Type *map_type = base_type(type_deref(map_ptr.type)); - GB_ASSERT(map_type->kind == Type_Map); - - cgValue ptr = {}; - cgValue key_ptr = {}; - cgValue hash = cg_gen_map_key_hash(p, map_ptr, key, &key_ptr); - - auto args = slice_make(temporary_allocator(), 4); - args[0] = cg_emit_transmute(p, map_ptr, t_raw_map_ptr); - args[1] = cg_builtin_map_info(p, map_type); - args[2] = hash; - args[3] = key_ptr; - - ptr = cg_emit_runtime_call(p, "__dynamic_map_get", args); - - return cg_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); -} - - -gb_internal void cg_internal_dynamic_map_set(cgProcedure *p, cgValue const &map_ptr, Type *map_type, - cgValue const &map_key, cgValue const &map_value, Ast *node) { - TEMPORARY_ALLOCATOR_GUARD(); - - map_type = base_type(map_type); - GB_ASSERT(map_type->kind == Type_Map); - - cgValue key_ptr = {}; - cgValue hash = cg_gen_map_key_hash(p, map_ptr, map_key, &key_ptr); - - cgValue v = cg_emit_conv(p, map_value, map_type->Map.value); - cgValue value_ptr = cg_address_from_load_or_generate_local(p, v); - - auto args = slice_make(temporary_allocator(), 6); - args[0] = cg_emit_conv(p, map_ptr, t_raw_map_ptr); - args[1] = cg_builtin_map_info(p, map_type); - args[2] = hash; - args[3] = cg_emit_conv(p, key_ptr, t_rawptr); - args[4] = cg_emit_conv(p, value_ptr, t_rawptr); - args[5] = cg_emit_source_code_location_as_global(p, node); - cg_emit_runtime_call(p, "__dynamic_map_set", args); -} - - - - -gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr) { - cgAddr addr = cg_build_addr(p, expr); - return cg_addr_get_ptr(p, addr); -} - -gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr); -gb_internal cgAddr cg_build_addr(cgProcedure *p, Ast *expr) { - expr = unparen_expr(expr); - - // IMPORTANT NOTE(bill): - // Selector Call Expressions (foo->bar(...)) - // must only evaluate `foo` once as it gets transformed into - // `foo.bar(foo, ...)` - // And if `foo` is a procedure call or something more complex, storing the value - // once is a very good idea - // If a stored value is found, it must be removed from the cache - if (expr->state_flags & StateFlag_SelectorCallExpr) { - // lbAddr *pp = map_get(&p->selector_addr, expr); - // if (pp != nullptr) { - // lbAddr res = *pp; - // map_remove(&p->selector_addr, expr); - // return res; - // } - } - cgAddr addr = cg_build_addr_internal(p, expr); - if (expr->state_flags & StateFlag_SelectorCallExpr) { - // map_set(&p->selector_addr, expr, addr); - } - return addr; -} - -gb_internal cgAddr cg_build_addr_index_expr(cgProcedure *p, Ast *expr) { - ast_node(ie, IndexExpr, expr); - - Type *t = base_type(type_of_expr(ie->expr)); - - bool deref = is_type_pointer(t); - t = base_type(type_deref(t)); - if (is_type_soa_struct(t)) { - cgValue val = cg_build_addr_ptr(p, ie->expr); - if (deref) { - val = cg_emit_load(p, val); - } - - cgValue index = cg_build_expr(p, ie->index); - return cg_addr_soa_variable(val, index, ie->index); - } - - if (ie->expr->tav.mode == Addressing_SoaVariable) { - GB_PANIC("TODO(bill): #soa"); - // // SOA Structures for slices/dynamic arrays - // GB_ASSERT(is_type_pointer(type_of_expr(ie->expr))); - - // lbValue field = lb_build_expr(p, ie->expr); - // lbValue index = lb_build_expr(p, ie->index); - - - // if (!build_context.no_bounds_check) { - // // TODO HACK(bill): Clean up this hack to get the length for bounds checking - // // GB_ASSERT(LLVMIsALoadInst(field.value)); - - // // lbValue a = {}; - // // a.value = LLVMGetOperand(field.value, 0); - // // a.type = alloc_type_pointer(field.type); - - // // irInstr *b = &a->Instr; - // // GB_ASSERT(b->kind == irInstr_StructElementPtr); - // // lbValue base_struct = b->StructElementPtr.address; - - // // GB_ASSERT(is_type_soa_struct(type_deref(ir_type(base_struct)))); - // // lbValue len = ir_soa_struct_len(p, base_struct); - // // lb_emit_bounds_check(p, ast_token(ie->index), index, len); - // } - // lbValue val = lb_emit_ptr_offset(p, field, index); - // return lb_addr(val); - } - - GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr)); - - if (is_type_map(t)) { - cgAddr map_addr = cg_build_addr(p, ie->expr); - cgValue key = cg_build_expr(p, ie->index); - key = cg_emit_conv(p, key, t->Map.key); - - Type *result_type = type_of_expr(expr); - cgValue map_ptr = cg_addr_get_ptr(p, map_addr); - if (is_type_pointer(type_deref(map_ptr.type))) { - map_ptr = cg_emit_load(p, map_ptr); - } - return cg_addr_map(map_ptr, key, t, result_type); - } - - switch (t->kind) { - case Type_Array: { - cgValue array = {}; - array = cg_build_addr_ptr(p, ie->expr); - if (deref) { - array = cg_emit_load(p, array); - } - cgValue index = cg_build_expr(p, ie->index); - index = cg_emit_conv(p, index, t_int); - cgValue elem = cg_emit_array_ep(p, array, index); - - auto index_tv = type_and_value_of_expr(ie->index); - if (index_tv.mode != Addressing_Constant) { - // cgValue len = cg_const_int(p->module, t_int, t->Array.count); - // cg_emit_bounds_check(p, ast_token(ie->index), index, len); - } - return cg_addr(elem); - } - - case Type_EnumeratedArray: { - cgValue array = {}; - array = cg_build_addr_ptr(p, ie->expr); - if (deref) { - array = cg_emit_load(p, array); - } - - Type *index_type = t->EnumeratedArray.index; - - auto index_tv = type_and_value_of_expr(ie->index); - - cgValue index = {}; - if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) { - if (index_tv.mode == Addressing_Constant) { - ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value); - index = cg_const_value(p, index_type, idx); - } else { - index = cg_emit_arith(p, Token_Sub, - cg_build_expr(p, ie->index), - cg_const_value(p, index_type, *t->EnumeratedArray.min_value), - index_type); - index = cg_emit_conv(p, index, t_int); - } - } else { - index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); - } - - cgValue elem = cg_emit_array_ep(p, array, index); - - if (index_tv.mode != Addressing_Constant) { - // cgValue len = cg_const_int(p->module, t_int, t->EnumeratedArray.count); - // cg_emit_bounds_check(p, ast_token(ie->index), index, len); - } - return cg_addr(elem); - } - - case Type_Slice: { - cgValue slice = {}; - slice = cg_build_expr(p, ie->expr); - if (deref) { - slice = cg_emit_load(p, slice); - } - cgValue elem = cg_builtin_raw_data(p, slice); - cgValue index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); - // cgValue len = cg_builtin_len(p, slice); - // cg_emit_bounds_check(p, ast_token(ie->index), index, len); - cgValue v = cg_emit_ptr_offset(p, elem, index); - v.type = alloc_type_pointer(type_deref(v.type, true)); - return cg_addr(v); - } - - case Type_MultiPointer: { - cgValue multi_ptr = {}; - multi_ptr = cg_build_expr(p, ie->expr); - if (deref) { - multi_ptr = cg_emit_load(p, multi_ptr); - } - cgValue index = cg_build_expr(p, ie->index); - index = cg_emit_conv(p, index, t_int); - - cgValue v = cg_emit_ptr_offset(p, multi_ptr, index); - v.type = alloc_type_pointer(type_deref(v.type, true)); - return cg_addr(v); - } - - case Type_RelativeMultiPointer: { - cgValue multi_ptr = {}; - multi_ptr = cg_build_expr(p, ie->expr); - if (deref) { - multi_ptr = cg_emit_load(p, multi_ptr); - } - cgValue index = cg_build_expr(p, ie->index); - index = cg_emit_conv(p, index, t_int); - - cgValue v = cg_emit_ptr_offset(p, multi_ptr, index); - v.type = alloc_type_pointer(type_deref(v.type, true)); - return cg_addr(v); - } - - case Type_DynamicArray: { - cgValue dynamic_array = {}; - dynamic_array = cg_build_expr(p, ie->expr); - if (deref) { - dynamic_array = cg_emit_load(p, dynamic_array); - } - cgValue elem = cg_builtin_raw_data(p, dynamic_array); - cgValue index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); - // cgValue len = cg_dynamic_array_len(p, dynamic_array); - // cg_emit_bounds_check(p, ast_token(ie->index), index, len); - cgValue v = cg_emit_ptr_offset(p, elem, index); - v.type = alloc_type_pointer(type_deref(v.type, true)); - return cg_addr(v); - } - - case Type_Matrix: { - GB_PANIC("TODO(bill): matrix"); - // lbValue matrix = {}; - // matrix = lb_build_addr_ptr(p, ie->expr); - // if (deref) { - // matrix = lb_emit_load(p, matrix); - // } - // lbValue index = lb_build_expr(p, ie->index); - // index = lb_emit_conv(p, index, t_int); - // lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index); - // elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr))); - - // auto index_tv = type_and_value_of_expr(ie->index); - // if (index_tv.mode != Addressing_Constant) { - // lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count); - // lb_emit_bounds_check(p, ast_token(ie->index), index, len); - // } - // return lb_addr(elem); - } - - - case Type_Basic: { // Basic_string - cgValue str; - cgValue elem; - cgValue len; - cgValue index; - - str = cg_build_expr(p, ie->expr); - if (deref) { - str = cg_emit_load(p, str); - } - elem = cg_builtin_raw_data(p, str); - len = cg_builtin_len(p, str); - - index = cg_emit_conv(p, cg_build_expr(p, ie->index), t_int); - // cg_emit_bounds_check(p, ast_token(ie->index), index, len); - - cgValue v = cg_emit_ptr_offset(p, elem, index); - v.type = alloc_type_pointer(type_deref(v.type, true)); - return cg_addr(v); - } - } - return {}; -} - -gb_internal cgAddr cg_build_addr_internal(cgProcedure *p, Ast *expr) { - switch (expr->kind) { - case_ast_node(i, Implicit, expr); - cgAddr v = {}; - switch (i->kind) { - case Token_context: - v = cg_find_or_generate_context_ptr(p); - break; - } - - GB_ASSERT(v.addr.node != nullptr); - return v; - case_end; - - case_ast_node(i, Ident, expr); - if (is_blank_ident(expr)) { - cgAddr val = {}; - return val; - } - String name = i->token.string; - Entity *e = entity_of_node(expr); - return cg_build_addr_from_entity(p, e, expr); - case_end; - - case_ast_node(de, DerefExpr, expr); - Type *t = type_of_expr(de->expr); - if (is_type_relative_pointer(t)) { - cgAddr addr = cg_build_addr(p, de->expr); - addr.relative.deref = true; - return addr; - } else if (is_type_soa_pointer(t)) { - cgValue value = cg_build_expr(p, de->expr); - cgValue ptr = cg_emit_struct_ev(p, value, 0); - cgValue idx = cg_emit_struct_ev(p, value, 1); - return cg_addr_soa_variable(ptr, idx, nullptr); - } - cgValue addr = cg_build_expr(p, de->expr); - return cg_addr(addr); - case_end; - - case_ast_node(ie, IndexExpr, expr); - return cg_build_addr_index_expr(p, expr); - case_end; - - case_ast_node(se, SliceExpr, expr); - return cg_build_addr_slice_expr(p, expr); - case_end; - - case_ast_node(se, SelectorExpr, expr); - Ast *sel_node = unparen_expr(se->selector); - if (sel_node->kind != Ast_Ident) { - GB_PANIC("Unsupported selector expression"); - } - String selector = sel_node->Ident.token.string; - TypeAndValue tav = type_and_value_of_expr(se->expr); - - if (tav.mode == Addressing_Invalid) { - // NOTE(bill): Imports - Entity *imp = entity_of_node(se->expr); - if (imp != nullptr) { - GB_ASSERT(imp->kind == Entity_ImportName); - } - return cg_build_addr(p, unparen_expr(se->selector)); - } - - - Type *type = base_type(tav.type); - if (tav.mode == Addressing_Type) { // Addressing_Type - Selection sel = lookup_field(tav.type, selector, true); - if (sel.pseudo_field) { - GB_ASSERT(sel.entity->kind == Entity_Procedure); - return cg_addr(cg_find_value_from_entity(p->module, sel.entity)); - } - GB_PANIC("Unreachable %.*s", LIT(selector)); - } - - if (se->swizzle_count > 0) { - Type *array_type = base_type(type_deref(tav.type)); - GB_ASSERT(array_type->kind == Type_Array); - u8 swizzle_count = se->swizzle_count; - u8 swizzle_indices_raw = se->swizzle_indices; - u8 swizzle_indices[4] = {}; - for (u8 i = 0; i < swizzle_count; i++) { - u8 index = swizzle_indices_raw>>(i*2) & 3; - swizzle_indices[i] = index; - } - cgValue a = {}; - if (is_type_pointer(tav.type)) { - a = cg_build_expr(p, se->expr); - } else { - cgAddr addr = cg_build_addr(p, se->expr); - a = cg_addr_get_ptr(p, addr); - } - - GB_ASSERT(is_type_array(expr->tav.type)); - GB_PANIC("TODO(bill): cg_addr_swizzle"); - // return cg_addr_swizzle(a, expr->tav.type, swizzle_count, swizzle_indices); - } - - Selection sel = lookup_field(type, selector, false); - GB_ASSERT(sel.entity != nullptr); - if (sel.pseudo_field) { - GB_ASSERT(sel.entity->kind == Entity_Procedure); - Entity *e = entity_of_node(sel_node); - return cg_addr(cg_find_value_from_entity(p->module, e)); - } - - { - cgAddr addr = cg_build_addr(p, se->expr); - if (addr.kind == cgAddr_Map) { - cgValue v = cg_addr_load(p, addr); - cgValue a = cg_address_from_load_or_generate_local(p, v); - a = cg_emit_deep_field_gep(p, a, sel); - return cg_addr(a); - } else if (addr.kind == cgAddr_Context) { - GB_ASSERT(sel.index.count > 0); - if (addr.ctx.sel.index.count >= 0) { - sel = selection_combine(addr.ctx.sel, sel); - } - addr.ctx.sel = sel; - addr.kind = cgAddr_Context; - return addr; - } else if (addr.kind == cgAddr_SoaVariable) { - cgValue index = addr.soa.index; - i64 first_index = sel.index[0]; - Selection sub_sel = sel; - sub_sel.index.data += 1; - sub_sel.index.count -= 1; - - cgValue arr = cg_emit_struct_ep(p, addr.addr, first_index); - - Type *t = base_type(type_deref(addr.addr.type)); - GB_ASSERT(is_type_soa_struct(t)); - - // TODO(bill): bounds checking for soa variable - // if (addr.soa.index_expr != nullptr && (!cg_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) { - // cgValue len = cg_soa_struct_len(p, addr.addr); - // cg_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len); - // } - - cgValue item = {}; - - if (t->Struct.soa_kind == StructSoa_Fixed) { - item = cg_emit_array_ep(p, arr, index); - } else { - item = cg_emit_ptr_offset(p, cg_emit_load(p, arr), index); - } - if (sub_sel.index.count > 0) { - item = cg_emit_deep_field_gep(p, item, sub_sel); - } - item.type = alloc_type_pointer(type_deref(item.type, true)); - return cg_addr(item); - } else if (addr.kind == cgAddr_Swizzle) { - GB_ASSERT(sel.index.count > 0); - // NOTE(bill): just patch the index in place - sel.index[0] = addr.swizzle.indices[sel.index[0]]; - } else if (addr.kind == cgAddr_SwizzleLarge) { - GB_ASSERT(sel.index.count > 0); - // NOTE(bill): just patch the index in place - sel.index[0] = addr.swizzle.indices[sel.index[0]]; - } - - cgValue a = cg_addr_get_ptr(p, addr); - a = cg_emit_deep_field_gep(p, a, sel); - return cg_addr(a); - } - case_end; - - case_ast_node(ce, CallExpr, expr); - cgValue res = cg_build_expr(p, expr); - switch (res.kind) { - case cgValue_Value: - return cg_addr(cg_address_from_load_or_generate_local(p, res)); - case cgValue_Addr: - return cg_addr(res); - case cgValue_Multi: - GB_PANIC("cannot address a multi-valued expression"); - break; - } - case_end; - - case_ast_node(cl, CompoundLit, expr); - return cg_build_addr_compound_lit(p, expr); - case_end; - - } - - TokenPos token_pos = ast_token(expr).pos; - GB_PANIC("Unexpected address expression\n" - "\tAst: %.*s @ " - "%s\n", - LIT(ast_strings[expr->kind]), - token_pos_to_string(token_pos)); - - return {}; -} \ No newline at end of file diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp deleted file mode 100644 index 8e9b80144..000000000 --- a/src/tilde_proc.cpp +++ /dev/null @@ -1,1327 +0,0 @@ -gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Type *type) { - GB_ASSERT(is_type_proc(type)); - mutex_lock(&m->proc_proto_mutex); - defer (mutex_unlock(&m->proc_proto_mutex)); - - if (type->kind == Type_Named) { - type = base_type(type); - } - TB_FunctionPrototype **found = map_get(&m->proc_proto_map, type); - if (found) { - return *found; - } - - TB_DebugType *dbg = cg_debug_type_for_proc(m, type); - TB_FunctionPrototype *proto = tb_prototype_from_dbg(m->mod, dbg); - - map_set(&m->proc_proto_map, type, proto); - return proto; -} - -gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool ignore_body) { - GB_ASSERT(entity != nullptr); - GB_ASSERT(entity->kind == Entity_Procedure); - if (!entity->Procedure.is_foreign) { - if ((entity->flags & EntityFlag_ProcBodyChecked) == 0) { - GB_PANIC("%.*s :: %s (was parapoly: %d %d)", LIT(entity->token.string), type_to_string(entity->type), is_type_polymorphic(entity->type, true), is_type_polymorphic(entity->type, false)); - } - } - - String link_name = cg_get_entity_name(m, entity); - - cgProcedure *p = nullptr; - { - StringHashKey key = string_hash_string(link_name); - cgValue *found = string_map_get(&m->members, key); - if (found) { - cg_add_entity(m, entity, *found); - rw_mutex_lock(&m->values_mutex); - p = string_map_must_get(&m->procedures, key); - rw_mutex_unlock(&m->values_mutex); - if (!ignore_body && p->func != nullptr) { - return nullptr; - } - } - } - - if (p == nullptr) { - p = gb_alloc_item(permanent_allocator(), cgProcedure); - } - - p->module = m; - p->entity = entity; - p->name = link_name; - - DeclInfo *decl = entity->decl_info; - - ast_node(pl, ProcLit, decl->proc_lit); - Type *pt = base_type(entity->type); - GB_ASSERT(pt->kind == Type_Proc); - - p->type = entity->type; - p->type_expr = decl->type_expr; - p->body = pl->body; - p->inlining = pl->inlining; - p->is_foreign = entity->Procedure.is_foreign; - p->is_export = entity->Procedure.is_export; - p->is_entry_point = false; - p->split_returns_index = -1; - - gbAllocator a = heap_allocator(); - p->children.allocator = a; - - p->defer_stack.allocator = a; - p->scope_stack.allocator = a; - p->context_stack.allocator = a; - - p->control_regions.allocator = a; - p->branch_regions.allocator = a; - - map_init(&p->variable_map); - map_init(&p->soa_values_map); - - TB_Linkage linkage = TB_LINKAGE_PRIVATE; - if (p->is_export) { - linkage = TB_LINKAGE_PUBLIC; - } else if (p->is_foreign || ignore_body) { - if (ignore_body) { - linkage = TB_LINKAGE_PUBLIC; - } - p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL); - } - if (p->name == "main") { - // TODO(bill): figure out when this should be public or not - linkage = TB_LINKAGE_PUBLIC; - } - - if (p->symbol == nullptr) { - p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage); - - p->debug_type = cg_debug_type_for_proc(m, p->type); - p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); - - p->symbol = cast(TB_Symbol *)p->func; - } - - p->value = cg_value(p->symbol, p->type); - - cg_add_symbol(m, entity, p->symbol); - cg_add_entity(m, entity, p->value); - cg_add_member(m, p->name, p->value); - cg_add_procedure_value(m, p); - - - return p; -} - -gb_internal cgProcedure *cg_procedure_create_dummy(cgModule *m, String const &link_name, Type *type) { - auto *prev_found = string_map_get(&m->members, link_name); - GB_ASSERT_MSG(prev_found == nullptr, "failed to create dummy procedure for: %.*s", LIT(link_name)); - - cgProcedure *p = gb_alloc_item(permanent_allocator(), cgProcedure); - - p->module = m; - p->name = link_name; - - p->type = type; - p->type_expr = nullptr; - p->body = nullptr; - p->tags = 0; - p->inlining = ProcInlining_none; - p->is_foreign = false; - p->is_export = false; - p->is_entry_point = false; - p->split_returns_index = -1; - - gbAllocator a = heap_allocator(); - p->children.allocator = a; - - p->defer_stack.allocator = a; - p->scope_stack.allocator = a; - p->context_stack.allocator = a; - - p->control_regions.allocator = a; - p->branch_regions.allocator = a; - - map_init(&p->variable_map); - map_init(&p->soa_values_map); - - TB_Linkage linkage = TB_LINKAGE_PRIVATE; - - p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage); - - p->debug_type = cg_debug_type_for_proc(m, p->type); - p->proto = tb_prototype_from_dbg(m->mod, p->debug_type); - - p->symbol = cast(TB_Symbol *)p->func; - - cgValue proc_value = cg_value(p->symbol, p->type); - cg_add_member(m, p->name, proc_value); - cg_add_procedure_value(m, p); - - return p; -} - -gb_internal cgProcedure *cg_procedure_generate_anonymous(cgModule *m, Ast *expr, cgProcedure *parent) { - expr = unparen_expr(expr); - ast_node(pl, ProcLit, expr); - - mutex_lock(&m->anonymous_proc_lits_mutex); - defer (mutex_unlock(&m->anonymous_proc_lits_mutex)); - - cgProcedure **found = map_get(&m->anonymous_proc_lits_map, expr); - if (found) { - return *found; - } - - TokenPos pos = ast_token(expr).pos; - - // NOTE(bill): Generate a new name - // parent$count - - String prefix_name = str_lit("proc_lit"); - if (parent) { - prefix_name = parent->name; - } - - isize name_len = prefix_name.len + 6 + 11; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - - static std::atomic name_id; - name_len = gb_snprintf(name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), 1+name_id.fetch_add(1)); - String name = make_string((u8 *)name_text, name_len-1); - - Type *type = type_of_expr(expr); - - GB_ASSERT(pl->decl->entity == nullptr); - Token token = {}; - token.pos = ast_token(expr).pos; - token.kind = Token_Ident; - token.string = name; - Entity *e = alloc_entity_procedure(nullptr, token, type, pl->tags); - e->file = expr->file(); - - // NOTE(bill): this is to prevent a race condition since these procedure literals can be created anywhere at any time - e->decl_info = pl->decl; - pl->decl->entity = e; - e->flags |= EntityFlag_ProcBodyChecked; - - cgProcedure *p = cg_procedure_create(m, e); - - map_set(&m->anonymous_proc_lits_map, expr, p); - - if (parent != nullptr) { - array_add(&parent->children, p); - } - - cg_add_procedure_to_queue(p); - return p; - -} - -gb_internal void cg_procedure_begin(cgProcedure *p) { - if (p == nullptr || p->func == nullptr) { - return; - } - - TB_ModuleSectionHandle section = tb_module_get_text(p->module->mod); - tb_function_set_prototype(p->func, section, p->proto, cg_arena()); - - if (p->body == nullptr) { - return; - } - - - DeclInfo *decl = decl_info_of_entity(p->entity); - if (decl != nullptr) { - for_array(i, decl->labels) { - BlockLabel bl = decl->labels[i]; - cgBranchRegions bb = {bl.label, nullptr, nullptr}; - array_add(&p->branch_regions, bb); - } - } - - GB_ASSERT(p->type->kind == Type_Proc); - TypeProc *pt = &p->type->Proc; - bool is_odin_like_cc = is_calling_convention_odin(pt->calling_convention); - int param_index = 0; - int param_count = p->proto->param_count; - - if (pt->results) { - Type *result_type = nullptr; - if (is_odin_like_cc) { - result_type = pt->results->Tuple.variables[pt->results->Tuple.variables.count-1]->type; - } else { - result_type = pt->results; - } - TB_DebugType *debug_type = cg_debug_type(p->module, result_type); - TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, true); - if (rule == TB_PASSING_INDIRECT) { - p->return_by_ptr = true; - param_index++; - } - } - - if (pt->params != nullptr) for (Entity *e : pt->params->Tuple.variables) { - if (e->kind != Entity_Variable) { - continue; - } - - GB_ASSERT_MSG(param_index < param_count, "%d < %d %.*s :: %s", param_index, param_count, LIT(p->name), type_to_string(p->type)); - - TB_Node *param_ptr = nullptr; - - TB_CharUnits size = cast(TB_CharUnits)type_size_of(e->type); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(e->type); - TB_DebugType *debug_type = cg_debug_type(p->module, e->type); - TB_PassingRule rule = tb_get_passing_rule_from_dbg(p->module->mod, debug_type, false); - switch (rule) { - case TB_PASSING_DIRECT: { - TB_Node *param = tb_inst_param(p->func, param_index++); - param_ptr = tb_inst_local(p->func, size, align); - tb_inst_store(p->func, param->dt, param_ptr, param, align, false); - } break; - case TB_PASSING_INDIRECT: - // TODO(bill): does this need a copy? for non-odin calling convention stuff? - param_ptr = tb_inst_param(p->func, param_index++); - break; - case TB_PASSING_IGNORE: - continue; - } - - GB_ASSERT(param_ptr->dt.type == TB_PTR); - - cgValue local = cg_value(param_ptr, alloc_type_pointer(e->type)); - - if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { - // NOTE(bill): for debugging purposes only - String name = e->token.string; - TB_DebugType *param_debug_type = debug_type; - TB_Node * param_ptr_to_use = param_ptr; - if (rule == TB_PASSING_INDIRECT) { - // HACK TODO(bill): this is just to get the debug information - TB_CharUnits ptr_size = cast(TB_CharUnits)build_context.ptr_size; - TB_Node *dummy_param = tb_inst_local(p->func, ptr_size, ptr_size); - tb_inst_store(p->func, TB_TYPE_PTR, dummy_param, param_ptr, ptr_size, false); - param_ptr_to_use = dummy_param; - param_debug_type = tb_debug_create_ptr(p->module->mod, param_debug_type); - } - tb_function_attrib_variable( - p->func, - param_ptr_to_use, - nullptr, // parent - name.len, cast(char const *)name.text, - param_debug_type - ); - } - cgAddr addr = cg_addr(local); - if (e) { - map_set(&p->variable_map, e, addr); - } - } - - if (is_odin_like_cc) { - p->split_returns_index = param_index; - } - - if (pt->calling_convention == ProcCC_Odin) { - // NOTE(bill): Push context on to stack from implicit parameter - - String name = str_lit("__.context_ptr"); - - Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false); - e->flags |= EntityFlag_NoAlias; - - TB_Node *param_ptr = tb_inst_param(p->func, param_count-1); - cgValue local = cg_value(param_ptr, t_context_ptr); - cgAddr addr = cg_addr(local); - map_set(&p->variable_map, e, addr); - - - cgContextData *cd = array_add_and_get(&p->context_stack); - cd->ctx = addr; - cd->scope_index = -1; - cd->uses = +1; // make sure it has been used already - } - - if (pt->has_named_results) { - auto const &results = pt->results->Tuple.variables; - for_array(i, results) { - Entity *e = results[i]; - GB_ASSERT(e->kind == Entity_Variable); - - if (e->token.string == "") { - continue; - } - GB_ASSERT(!is_blank_ident(e->token)); - - cgAddr res = cg_add_local(p, e->type, e, true); - - if (e->Variable.param_value.kind != ParameterValue_Invalid) { - cgValue c = cg_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos); - cg_addr_store(p, res, c); - } - } - } -} - - -gb_internal WORKER_TASK_PROC(cg_procedure_compile_worker_proc) { - cgProcedure *p = cast(cgProcedure *)data; - - TB_Passes *opt = tb_pass_enter(p->func, cg_arena()); - defer (tb_pass_exit(opt)); - - // optimization passes - if (false) { - tb_pass_peephole(opt, TB_PEEPHOLE_ALL); - tb_pass_mem2reg(opt); - tb_pass_peephole(opt, TB_PEEPHOLE_ALL); - } - - bool emit_asm = false; - if ( - // string_starts_with(p->name, str_lit("runtime@_windows_default_alloc_or_resize")) || - false - ) { - emit_asm = true; - } - - // emit ir - if ( - // string_starts_with(p->name, str_lit("main@")) || - false - ) { // IR Printing - TB_Arena *arena = cg_arena(); - TB_Passes *passes = tb_pass_enter(p->func, arena); - defer (tb_pass_exit(passes)); - - tb_pass_print(passes); - fprintf(stdout, "\n"); - fflush(stdout); - } - if (false) { // GraphViz printing - tb_pass_print_dot(opt, tb_default_print_callback, stdout); - } - - // compile - TB_FunctionOutput *output = tb_pass_codegen(opt, emit_asm); - if (emit_asm) { - tb_output_print_asm(output, stdout); - fprintf(stdout, "\n"); - fflush(stdout); - } - - return 0; -} - -gb_internal void cg_procedure_end(cgProcedure *p) { - if (p == nullptr || p->func == nullptr) { - return; - } - if (tb_inst_get_control(p->func)) { - if (p->type->Proc.result_count == 0) { - tb_inst_ret(p->func, 0, nullptr); - } else { - tb_inst_unreachable(p->func); - } - } - - if (p->module->do_threading) { - thread_pool_add_task(cg_procedure_compile_worker_proc, p); - } else { - cg_procedure_compile_worker_proc(p); - } -} - -gb_internal void cg_procedure_generate(cgProcedure *p) { - if (p->body == nullptr) { - return; - } - - cg_procedure_begin(p); - cg_build_stmt(p, p->body); - cg_procedure_end(p); -} - -gb_internal void cg_build_nested_proc(cgProcedure *p, AstProcLit *pd, Entity *e) { - GB_ASSERT(pd->body != nullptr); - cgModule *m = p->module; - auto *min_dep_set = &m->info->minimum_dependency_set; - - if (ptr_set_exists(min_dep_set, e) == false) { - // NOTE(bill): Nothing depends upon it so doesn't need to be built - return; - } - - // NOTE(bill): Generate a new name - // parent.name-guid - String original_name = e->token.string; - String pd_name = original_name; - if (e->Procedure.link_name.len > 0) { - pd_name = e->Procedure.link_name; - } - - - isize name_len = p->name.len + 1 + pd_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - - i32 guid = cast(i32)p->children.count; - name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%d", LIT(p->name), LIT(pd_name), guid); - String name = make_string(cast(u8 *)name_text, name_len-1); - - e->Procedure.link_name = name; - - cgProcedure *nested_proc = cg_procedure_create(p->module, e); - e->cg_procedure = nested_proc; - - cgValue value = nested_proc->value; - - cg_add_entity(m, e, value); - array_add(&p->children, nested_proc); - cg_add_procedure_to_queue(nested_proc); -} - - - - - -gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) { - GB_ASSERT(is_type_proc(e->type)); - e = strip_entity_wrapping(e); - GB_ASSERT(e != nullptr); - GB_ASSERT(e->kind == Entity_Procedure); - - cgValue *found = nullptr; - rw_mutex_shared_lock(&m->values_mutex); - found = map_get(&m->values, e); - rw_mutex_shared_unlock(&m->values_mutex); - if (found) { - GB_ASSERT(found->node != nullptr); - return *found; - } - - GB_PANIC("Error in: %s, missing procedure %.*s\n", token_pos_to_string(e->token.pos), LIT(e->token.string)); - return {}; -} - - - -gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr); -gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr) { - expr = unparen_expr(expr); - ast_node(ce, CallExpr, expr); - - cgValue res = cg_build_call_expr_internal(p, expr); - - if (ce->optional_ok_one) { // TODO(bill): Minor hack for #optional_ok procedures - GB_ASSERT(res.kind == cgValue_Multi); - GB_ASSERT(res.multi->values.count == 2); - return res.multi->values[0]; - } - return res; -} - -gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice const &args) { - if (value.kind == cgValue_Symbol) { - value = cg_value(tb_inst_get_symbol_address(p->func, value.symbol), value.type); - } - GB_ASSERT(value.kind == cgValue_Value); - TEMPORARY_ALLOCATOR_GUARD(); - - TB_Module *m = p->module->mod; - - - Type *type = base_type(value.type); - GB_ASSERT(type->kind == Type_Proc); - TypeProc *pt = &type->Proc; - gb_unused(pt); - - TB_FunctionPrototype *proto = cg_procedure_type_as_prototype(p->module, type); - TB_Node *target = value.node; - auto params = slice_make(temporary_allocator(), proto->param_count); - - - GB_ASSERT(build_context.metrics.os == TargetOs_windows); - // TODO(bill): Support more than Win64 ABI - - bool is_odin_like_cc = is_calling_convention_odin(pt->calling_convention); - - bool return_is_indirect = false; - - Slice result_entities = {}; - Slice param_entities = {}; - if (pt->results) { - result_entities = pt->results->Tuple.variables; - } - if (pt->params) { - param_entities = pt->params->Tuple.variables; - } - - isize param_index = 0; - if (pt->result_count != 0) { - Type *return_type = nullptr; - if (is_odin_like_cc) { - return_type = result_entities[result_entities.count-1]->type; - } else { - return_type = pt->results; - } - TB_DebugType *dbg = cg_debug_type(p->module, return_type); - TB_PassingRule rule = tb_get_passing_rule_from_dbg(m, dbg, true); - if (rule == TB_PASSING_INDIRECT) { - return_is_indirect = true; - TB_CharUnits size = cast(TB_CharUnits)type_size_of(return_type); - TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(return_type), 16); - TB_Node *local = tb_inst_local(p->func, size, align); - tb_inst_memzero(p->func, local, tb_inst_uint(p->func, TB_TYPE_INT, size), align); - params[param_index++] = local; - } - } - isize param_entity_index = 0; - for_array(i, args) { - Entity *param_entity = nullptr; - do { - param_entity = param_entities[param_entity_index++]; - } while (param_entity->kind != Entity_Variable); - Type *param_type = param_entity->type; - cgValue arg = args[i]; - arg = cg_emit_conv(p, arg, param_type); - arg = cg_flatten_value(p, arg); - - TB_Node *param = nullptr; - - TB_DebugType *dbg = cg_debug_type(p->module, param_type); - TB_PassingRule rule = tb_get_passing_rule_from_dbg(m, dbg, false); - switch (rule) { - case TB_PASSING_DIRECT: - GB_ASSERT(arg.kind == cgValue_Value); - param = arg.node; - break; - case TB_PASSING_INDIRECT: - { - cgValue arg_ptr = {}; - // indirect - if (is_odin_like_cc) { - arg_ptr = cg_address_from_load_or_generate_local(p, arg); - } else { - arg_ptr = cg_copy_value_to_ptr(p, arg, param_type, 16); - } - GB_ASSERT(arg_ptr.kind == cgValue_Value); - param = arg_ptr.node; - } - break; - case TB_PASSING_IGNORE: - continue; - } - - params[param_index++] = param; - } - - // Split returns - isize split_offset = -1; - if (is_odin_like_cc) { - split_offset = param_index; - for (isize i = 0; i < pt->result_count-1; i++) { - Type *result = result_entities[i]->type; - TB_CharUnits size = cast(TB_CharUnits)type_size_of(result); - TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(result), 16); - TB_Node *local = tb_inst_local(p->func, size, align); - // TODO(bill): Should this need to be zeroed any way? - tb_inst_memzero(p->func, local, tb_inst_uint(p->func, TB_TYPE_INT, size), align); - params[param_index++] = local; - } - } - - if (pt->calling_convention == ProcCC_Odin) { - cgValue ctx_ptr = cg_find_or_generate_context_ptr(p).addr; - GB_ASSERT(ctx_ptr.kind == cgValue_Value); - params[param_index++] = ctx_ptr.node; - } - GB_ASSERT_MSG(param_index == params.count, "%td vs %td\n %s %u %u", - param_index, params.count, - type_to_string(type), - proto->return_count, - proto->param_count); - - for (TB_Node *param : params) { - GB_ASSERT(param != nullptr); - } - - GB_ASSERT(target != nullptr); - TB_MultiOutput multi_output = tb_inst_call(p->func, proto, target, params.count, params.data); - gb_unused(multi_output); - - switch (pt->result_count) { - case 0: - return {}; - case 1: - if (return_is_indirect) { - return cg_lvalue_addr(params[0], pt->results->Tuple.variables[0]->type); - } else { - GB_ASSERT(multi_output.count == 1); - TB_Node *node = multi_output.single; - return cg_value(node, pt->results->Tuple.variables[0]->type); - } - } - - cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti); - multi->values = slice_make(permanent_allocator(), pt->result_count); - - if (is_odin_like_cc) { - GB_ASSERT(split_offset >= 0); - for (isize i = 0; i < pt->result_count-1; i++) { - multi->values[i] = cg_lvalue_addr(params[split_offset+i], result_entities[i]->type); - } - - Type *end_type = result_entities[pt->result_count-1]->type; - if (return_is_indirect) { - multi->values[pt->result_count-1] = cg_lvalue_addr(params[0], end_type); - } else { - GB_ASSERT(multi_output.count == 1); - TB_DataType dt = cg_data_type(end_type); - TB_Node *res = multi_output.single; - if (res->dt.raw != dt.raw) { - // struct-like returns passed in registers - TB_CharUnits size = cast(TB_CharUnits)type_size_of(end_type); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(end_type); - TB_Node *addr = tb_inst_local(p->func, size, align); - tb_inst_store(p->func, res->dt, addr, res, align, false); - multi->values[pt->result_count-1] = cg_lvalue_addr(addr, end_type); - } else { - multi->values[pt->result_count-1] = cg_value(res, end_type); - } - } - } else { - TB_Node *the_tuple = {}; - if (return_is_indirect) { - the_tuple = params[0]; - } else { - GB_ASSERT(multi_output.count == 1); - TB_Node *res = multi_output.single; - - // struct-like returns passed in registers - TB_CharUnits size = cast(TB_CharUnits)type_size_of(pt->results); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(pt->results); - the_tuple = tb_inst_local(p->func, size, align); - tb_inst_store(p->func, res->dt, the_tuple, res, align, false); - } - for (isize i = 0; i < pt->result_count; i++) { - i64 offset = type_offset_of(pt->results, i, nullptr); - TB_Node *ptr = tb_inst_member_access(p->func, the_tuple, offset); - multi->values[i] = cg_lvalue_addr(ptr, result_entities[i]->type); - } - } - - return cg_value_multi(multi, pt->results); -} - -gb_internal cgValue cg_emit_runtime_call(cgProcedure *p, char const *name, Slice const &args) { - AstPackage *pkg = p->module->info->runtime_package; - Entity *e = scope_lookup_current(pkg->scope, make_string_c(name)); - cgValue value = cg_find_procedure_value_from_entity(p->module, e); - return cg_emit_call(p, value, args); -} - -gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos) { - switch (param_value.kind) { - case ParameterValue_Constant: - if (is_type_constant_type(parameter_type)) { - auto res = cg_const_value(p, parameter_type, param_value.value); - return res; - } else { - ExactValue ev = param_value.value; - cgValue arg = {}; - Type *type = type_of_expr(param_value.original_ast_expr); - if (type != nullptr) { - arg = cg_const_value(p, type, ev); - } else { - arg = cg_const_value(p, parameter_type, param_value.value); - } - return cg_emit_conv(p, arg, parameter_type); - } - - case ParameterValue_Nil: - return cg_const_nil(p, parameter_type); - case ParameterValue_Location: - { - String proc_name = {}; - if (p->entity != nullptr) { - proc_name = p->entity->token.string; - } - return cg_emit_source_code_location_as_global(p, proc_name, pos); - } - case ParameterValue_Value: - return cg_build_expr(p, param_value.ast_value); - } - return cg_const_nil(p, parameter_type); -} - -gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) { - ast_node(ce, CallExpr, expr); - - TypeAndValue tv = type_and_value_of_expr(expr); - - TypeAndValue proc_tv = type_and_value_of_expr(ce->proc); - AddressingMode proc_mode = proc_tv.mode; - if (proc_mode == Addressing_Type) { - GB_ASSERT(ce->args.count == 1); - cgValue x = cg_build_expr(p, ce->args[0]); - return cg_emit_conv(p, x, tv.type); - } - - Ast *proc_expr = unparen_expr(ce->proc); - if (proc_mode == Addressing_Builtin) { - Entity *e = entity_of_node(proc_expr); - BuiltinProcId id = BuiltinProc_Invalid; - if (e != nullptr) { - id = cast(BuiltinProcId)e->Builtin.id; - } else { - id = BuiltinProc_DIRECTIVE; - } - if (id == BuiltinProc___entry_point) { - if (p->module->info->entry_point) { - cgValue entry_point = cg_find_procedure_value_from_entity(p->module, p->module->info->entry_point); - GB_ASSERT(entry_point.node != nullptr); - cg_emit_call(p, entry_point, {}); - } - return {}; - } - - return cg_build_builtin(p, id, expr); - } - - // NOTE(bill): Regular call - cgValue value = {}; - - Entity *proc_entity = entity_of_node(proc_expr); - if (proc_entity != nullptr) { - if (proc_entity->flags & EntityFlag_Disabled) { - GB_ASSERT(tv.type == nullptr); - return {}; - } - } - - if (proc_expr->tav.mode == Addressing_Constant) { - ExactValue v = proc_expr->tav.value; - switch (v.kind) { - case ExactValue_Integer: - { - u64 u = big_int_to_u64(&v.value_integer); - cgValue x = cg_value(tb_inst_uint(p->func, TB_TYPE_PTR, u), t_rawptr); - value = cg_emit_conv(p, x, proc_expr->tav.type); - break; - } - case ExactValue_Pointer: - { - u64 u = cast(u64)v.value_pointer; - cgValue x = cg_value(tb_inst_uint(p->func, TB_TYPE_PTR, u), t_rawptr); - value = cg_emit_conv(p, x, proc_expr->tav.type); - break; - } - } - } - - if (value.node == nullptr) { - value = cg_build_expr(p, proc_expr); - } - if (value.kind == cgValue_Addr) { - value = cg_emit_load(p, value); - } - GB_ASSERT(value.kind == cgValue_Value); - GB_ASSERT(value.node != nullptr); - GB_ASSERT(is_type_proc(value.type)); - - TEMPORARY_ALLOCATOR_GUARD(); - - Type *proc_type_ = base_type(value.type); - GB_ASSERT(proc_type_->kind == Type_Proc); - TypeProc *pt = &proc_type_->Proc; - - GB_ASSERT(ce->split_args != nullptr); - - isize internal_param_count = 0; - if (pt->params) for (Entity *e : pt->params->Tuple.variables) { - if (e->kind == Entity_Variable) { - internal_param_count += 1; - } - } - GB_ASSERT(internal_param_count <= pt->param_count); - - auto args = array_make(temporary_allocator(), 0, internal_param_count); - - bool vari_expand = (ce->ellipsis.pos.line != 0); - bool is_c_vararg = pt->c_vararg; - - for_array(i, ce->split_args->positional) { - Entity *e = pt->params->Tuple.variables[i]; - if (e->kind == Entity_TypeName) { - continue; - } else if (e->kind == Entity_Constant) { - continue; - } - - GB_ASSERT(e->kind == Entity_Variable); - if (pt->variadic && pt->variadic_index == i) { - cgValue variadic_args = cg_const_nil(p, e->type); - auto variadic = slice(ce->split_args->positional, pt->variadic_index, ce->split_args->positional.count); - if (variadic.count != 0) { - // variadic call argument generation - Type *slice_type = e->type; - GB_ASSERT(slice_type->kind == Type_Slice); - - if (is_c_vararg) { - GB_ASSERT(!vari_expand); - - Type *elem_type = slice_type->Slice.elem; - - for (Ast *var_arg : variadic) { - cgValue arg = cg_build_expr(p, var_arg); - if (is_type_any(elem_type)) { - array_add(&args, cg_emit_conv(p, arg, default_type(arg.type))); - } else { - array_add(&args, cg_emit_conv(p, arg, elem_type)); - } - } - break; - } else if (vari_expand) { - GB_ASSERT(variadic.count == 1); - variadic_args = cg_build_expr(p, variadic[0]); - variadic_args = cg_emit_conv(p, variadic_args, slice_type); - } else { - Type *elem_type = slice_type->Slice.elem; - - auto var_args = array_make(temporary_allocator(), 0, variadic.count); - for (Ast *var_arg : variadic) { - cgValue v = cg_build_expr(p, var_arg); - cg_append_tuple_values(p, &var_args, v); - } - isize slice_len = var_args.count; - if (slice_len > 0) { - cgAddr slice = cg_add_local(p, slice_type, nullptr, true); - cgAddr base_array = cg_add_local(p, alloc_type_array(elem_type, slice_len), nullptr, true); - - for (isize i = 0; i < var_args.count; i++) { - cgValue addr = cg_emit_array_epi(p, base_array.addr, cast(i32)i); - cgValue var_arg = var_args[i]; - var_arg = cg_emit_conv(p, var_arg, elem_type); - cg_emit_store(p, addr, var_arg); - } - - cgValue base_elem = cg_emit_array_epi(p, base_array.addr, 0); - cgValue len = cg_const_int(p, t_int, slice_len); - cg_fill_slice(p, slice, base_elem, len); - - variadic_args = cg_addr_load(p, slice); - } - } - } - array_add(&args, variadic_args); - - break; - } else { - cgValue value = cg_build_expr(p, ce->split_args->positional[i]); - cg_append_tuple_values(p, &args, value); - } - } - - if (!is_c_vararg) { - array_resize(&args, internal_param_count); - } - - for (Ast *arg : ce->split_args->named) { - ast_node(fv, FieldValue, arg); - GB_ASSERT(fv->field->kind == Ast_Ident); - String name = fv->field->Ident.token.string; - gb_unused(name); - isize param_index = lookup_procedure_parameter(pt, name); - GB_ASSERT(param_index >= 0); - - cgValue value = cg_build_expr(p, fv->value); - GB_ASSERT(!is_type_tuple(value.type)); - args[param_index] = value; - } - - TokenPos pos = ast_token(ce->proc).pos; - - - if (pt->params != nullptr) { - isize min_count = internal_param_count; - if (is_c_vararg) { - min_count -= 1; - } - GB_ASSERT_MSG(args.count >= min_count, "in %.*s", LIT(p->name)); - isize arg_index = 0; - for_array(param_index, pt->params->Tuple.variables) { - Entity *e = pt->params->Tuple.variables[param_index]; - if (e->kind == Entity_TypeName) { - continue; - } else if (e->kind == Entity_Constant) { - continue; - } - GB_ASSERT(e->kind == Entity_Variable); - - if (pt->variadic && param_index == pt->variadic_index) { - if (!is_c_vararg && args[arg_index].node == nullptr) { - args[arg_index++] = cg_const_nil(p, e->type); - continue; - } - } - - cgValue arg = args[arg_index]; - if (arg.node == nullptr) { - GB_ASSERT(e->kind == Entity_Variable); - args[arg_index++] = cg_handle_param_value(p, e->type, e->Variable.param_value, pos); - } else { - args[arg_index++] = cg_emit_conv(p, arg, e->type); - } - } - } - - isize final_count = is_c_vararg ? args.count : internal_param_count; - auto call_args = slice(args, 0, final_count); - - return cg_emit_call(p, value, call_args); -} - - - -gb_internal cgValue cg_hasher_proc_value_for_type(cgProcedure *p, Type *type) { - cgProcedure *found = cg_hasher_proc_for_type(p->module, type); - return cg_value(tb_inst_get_symbol_address(p->func, found->symbol), found->type); -} - -gb_internal cgValue cg_equal_proc_value_for_type(cgProcedure *p, Type *type) { - cgProcedure *found = cg_equal_proc_for_type(p->module, type); - return cg_value(tb_inst_get_symbol_address(p->func, found->symbol), found->type); -} - - - -gb_internal cgProcedure *cg_equal_proc_for_type(cgModule *m, Type *type) { - type = base_type(type); - GB_ASSERT(is_type_comparable(type)); - - mutex_lock(&m->generated_procs_mutex); - defer (mutex_unlock(&m->generated_procs_mutex)); - - cgProcedure **found = map_get(&m->equal_procs, type); - if (found) { - return *found; - } - - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$equal%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); - - - cgProcedure *p = cg_procedure_create_dummy(m, proc_name, t_equal_proc); - map_set(&m->equal_procs, type, p); - p->split_returns_index = 2; - - cg_procedure_begin(p); - - TB_Node *x = tb_inst_param(p->func, 0); - TB_Node *y = tb_inst_param(p->func, 1); - GB_ASSERT(x->dt.type == TB_PTR); - GB_ASSERT(y->dt.type == TB_PTR); - - TB_DataType ret_dt = TB_PROTOTYPE_RETURNS(p->proto)->dt; - - TB_Node *node_true = tb_inst_uint(p->func, ret_dt, true); - TB_Node *node_false = tb_inst_uint(p->func, ret_dt, false); - - TB_Node *same_ptr_region = cg_control_region(p, "same_ptr"); - TB_Node *diff_ptr_region = cg_control_region(p, "diff_ptr"); - - TB_Node *is_same_ptr = tb_inst_cmp_eq(p->func, x, y); - tb_inst_if(p->func, is_same_ptr, same_ptr_region, diff_ptr_region); - - tb_inst_set_control(p->func, same_ptr_region); - tb_inst_ret(p->func, 1, &node_true); - - tb_inst_set_control(p->func, diff_ptr_region); - - Type *pt = alloc_type_pointer(type); - cgValue lhs = cg_value(x, pt); - cgValue rhs = cg_value(y, pt); - - if (type->kind == Type_Struct) { - type_set_offsets(type); - - TB_Node *false_region = cg_control_region(p, "bfalse"); - cgValue res = cg_const_bool(p, t_bool, true); - - for_array(i, type->Struct.fields) { - TB_Node *next_region = cg_control_region(p, "btrue"); - - cgValue plhs = cg_emit_struct_ep(p, lhs, i); - cgValue prhs = cg_emit_struct_ep(p, rhs, i); - cgValue left = cg_emit_load(p, plhs); - cgValue right = cg_emit_load(p, prhs); - cgValue ok = cg_emit_comp(p, Token_CmpEq, left, right); - - cg_emit_if(p, ok, next_region, false_region); - - cg_emit_goto(p, next_region); - tb_inst_set_control(p->func, next_region); - } - - tb_inst_ret(p->func, 1, &node_true); - tb_inst_set_control(p->func, false_region); - tb_inst_ret(p->func, 1, &node_false); - - } else if (type->kind == Type_Union) { - if (type_size_of(type) == 0) { - tb_inst_ret(p->func, 1, &node_true); - } else if (is_type_union_maybe_pointer(type)) { - Type *v = type->Union.variants[0]; - Type *pv = alloc_type_pointer(v); - - cgValue left = cg_emit_load(p, cg_emit_conv(p, lhs, pv)); - cgValue right = cg_emit_load(p, cg_emit_conv(p, rhs, pv)); - cgValue ok = cg_emit_comp(p, Token_CmpEq, left, right); - cg_build_return_stmt_internal_single(p, ok); - } else { - TB_Node *false_region = cg_control_region(p, "bfalse"); - TB_Node *switch_region = cg_control_region(p, "bswitch"); - - cgValue lhs_tag = cg_emit_load(p, cg_emit_union_tag_ptr(p, lhs)); - cgValue rhs_tag = cg_emit_load(p, cg_emit_union_tag_ptr(p, rhs)); - - cgValue tag_eq = cg_emit_comp(p, Token_CmpEq, lhs_tag, rhs_tag); - cg_emit_if(p, tag_eq, switch_region, false_region); - - size_t entry_count = type->Union.variants.count; - if (type->Union.kind != UnionType_no_nil) { - entry_count += 1; - } - - size_t entry_offset = 0; - - TB_SwitchEntry *keys = gb_alloc_array(temporary_allocator(), TB_SwitchEntry, entry_count); - if (type->Union.kind != UnionType_no_nil) { - TB_Node *region = cg_control_region(p, "bcase"); - keys[entry_offset].key = 0; - keys[entry_offset].value = region; - entry_offset += 1; - - tb_inst_set_control(p->func, region); - cgValue ok = cg_const_bool(p, t_bool, true); - cg_build_return_stmt_internal_single(p, ok); - } - - for (isize i = 0; i < type->Union.variants.count; i++) { - TB_Node *region = cg_control_region(p, "bcase"); - Type *variant = type->Union.variants[i]; - keys[entry_offset+i].key = union_variant_index(type, variant); - keys[entry_offset+i].value = region; - - tb_inst_set_control(p->func, region); - Type *vp = alloc_type_pointer(variant); - cgValue left = cg_emit_load(p, cg_emit_conv(p, lhs, vp)); - cgValue right = cg_emit_load(p, cg_emit_conv(p, rhs, vp)); - cgValue ok = cg_emit_comp(p, Token_CmpEq, left, right); - cg_build_return_stmt_internal_single(p, ok); - } - - - tb_inst_set_control(p->func, switch_region); - TB_DataType tag_dt = cg_data_type(lhs_tag.type); - GB_ASSERT(lhs_tag.kind == cgValue_Value); - tb_inst_branch(p->func, tag_dt, lhs_tag.node, false_region, entry_count, keys); - - tb_inst_set_control(p->func, false_region); - tb_inst_ret(p->func, 1, &node_false); - } - } else { - cgValue left = cg_lvalue_addr(x, type); - cgValue right = cg_lvalue_addr(y, type); - cgValue ok = cg_emit_comp(p, Token_CmpEq, left, right); - cg_build_return_stmt_internal_single(p, ok); - } - - cg_procedure_end(p); - - return p; -} - - -gb_internal cgValue cg_simple_compare_hash(cgProcedure *p, Type *type, cgValue data, cgValue seed) { - TEMPORARY_ALLOCATOR_GUARD(); - - GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type)); - - auto args = slice_make(temporary_allocator(), 3); - args[0] = data; - args[1] = seed; - args[2] = cg_const_int(p, t_int, type_size_of(type)); - return cg_emit_runtime_call(p, "default_hasher", args); -} - - - - - -gb_internal cgProcedure *cg_hasher_proc_for_type(cgModule *m, Type *type) { - type = base_type(type); - GB_ASSERT(is_type_valid_for_keys(type)); - - mutex_lock(&m->generated_procs_mutex); - defer (mutex_unlock(&m->generated_procs_mutex)); - - cgProcedure **found = map_get(&m->hasher_procs, type); - if (found) { - return *found; - } - - static std::atomic proc_index; - - char buf[32] = {}; - isize n = gb_snprintf(buf, 32, "__$hasher%u", 1+proc_index.fetch_add(1)); - char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1); - String proc_name = make_string_c(str); - - - cgProcedure *p = cg_procedure_create_dummy(m, proc_name, t_hasher_proc); - map_set(&m->hasher_procs, type, p); - p->split_returns_index = 2; - - cg_procedure_begin(p); - defer (cg_procedure_end(p)); - - TB_Node *x = tb_inst_param(p->func, 0); // data - TB_Node *y = tb_inst_param(p->func, 1); // seed - - cgValue data = cg_value(x, t_rawptr); - cgValue seed = cg_value(y, t_uintptr); - - if (is_type_simple_compare(type)) { - cgValue res = cg_simple_compare_hash(p, type, data, seed); - cg_build_return_stmt_internal_single(p, res); - return p; - } - - TEMPORARY_ALLOCATOR_GUARD(); - - auto args = slice_make(temporary_allocator(), 2); - - if (type->kind == Type_Struct) { - type_set_offsets(type); - for_array(i, type->Struct.fields) { - i64 offset = type->Struct.offsets[i]; - Entity *field = type->Struct.fields[i]; - cgValue field_hasher = cg_hasher_proc_value_for_type(p, field->type); - - TB_Node *ptr = tb_inst_member_access(p->func, data.node, offset); - - args[0] = cg_value(ptr, alloc_type_pointer(field->type)); - args[1] = seed; - seed = cg_emit_call(p, field_hasher, args); - } - - cg_build_return_stmt_internal_single(p, seed); - } else if (type->kind == Type_Union) { - if (type_size_of(type) == 0) { - cg_build_return_stmt_internal_single(p, seed); - } else if (is_type_union_maybe_pointer(type)) { - Type *v = type->Union.variants[0]; - cgValue variant_hasher = cg_hasher_proc_value_for_type(p, v); - - args[0] = data; - args[1] = seed; - cgValue res = cg_emit_call(p, variant_hasher, args); - cg_build_return_stmt_internal_single(p, seed); - } else { - TB_Node *end_region = cg_control_region(p, "bend"); - TB_Node *switch_region = cg_control_region(p, "bswitch"); - - cg_emit_goto(p, switch_region); - - size_t entry_count = type->Union.variants.count; - TB_SwitchEntry *keys = gb_alloc_array(temporary_allocator(), TB_SwitchEntry, entry_count); - for (size_t i = 0; i < entry_count; i++) { - TB_Node *region = cg_control_region(p, "bcase"); - Type *variant = type->Union.variants[i]; - keys[i].key = union_variant_index(type, variant); - keys[i].value = region; - - tb_inst_set_control(p->func, region); - - cgValue variant_hasher = cg_hasher_proc_value_for_type(p, variant); - - args[0] = data; - args[1] = seed; - cgValue res = cg_emit_call(p, variant_hasher, args); - cg_build_return_stmt_internal_single(p, res); - } - - tb_inst_set_control(p->func, switch_region); - - cgValue tag_ptr = cg_emit_union_tag_ptr(p, data); - cgValue tag = cg_emit_load(p, tag_ptr); - - TB_DataType tag_dt = cg_data_type(tag.type); - GB_ASSERT(tag.kind == cgValue_Value); - tb_inst_branch(p->func, tag_dt, tag.node, end_region, entry_count, keys); - - tb_inst_set_control(p->func, end_region); - cg_build_return_stmt_internal_single(p, seed); - } - } else if (type->kind == Type_Array) { - cgAddr pres = cg_add_local(p, t_uintptr, nullptr, false); - cg_addr_store(p, pres, seed); - - cgValue elem_hasher = cg_hasher_proc_value_for_type(p, type->Array.elem); - - auto loop_data = cg_loop_start(p, type->Array.count, t_int); - - i64 stride = type_size_of(type->Array.elem); - TB_Node *ptr = tb_inst_array_access(p->func, data.node, loop_data.index.node, stride); - args[0] = cg_value(ptr, alloc_type_pointer(type->Array.elem)); - args[1] = cg_addr_load(p, pres); - - cgValue new_seed = cg_emit_call(p, elem_hasher, args); - cg_addr_store(p, pres, new_seed); - - cg_loop_end(p, loop_data); - - cgValue res = cg_addr_load(p, pres); - cg_build_return_stmt_internal_single(p, res); - } else if (type->kind == Type_EnumeratedArray) { - cgAddr pres = cg_add_local(p, t_uintptr, nullptr, false); - cg_addr_store(p, pres, seed); - - cgValue elem_hasher = cg_hasher_proc_value_for_type(p, type->EnumeratedArray.elem); - - auto loop_data = cg_loop_start(p, type->EnumeratedArray.count, t_int); - - i64 stride = type_size_of(type->EnumeratedArray.elem); - TB_Node *ptr = tb_inst_array_access(p->func, data.node, loop_data.index.node, stride); - args[0] = cg_value(ptr, alloc_type_pointer(type->EnumeratedArray.elem)); - args[1] = cg_addr_load(p, pres); - - cgValue new_seed = cg_emit_call(p, elem_hasher, args); - cg_addr_store(p, pres, new_seed); - - cg_loop_end(p, loop_data); - - cgValue res = cg_addr_load(p, pres); - cg_build_return_stmt_internal_single(p, res); - } else if (is_type_cstring(type)) { - args[0] = data; - args[1] = seed; - cgValue res = cg_emit_runtime_call(p, "default_hasher_cstring", args); - cg_build_return_stmt_internal_single(p, seed); - } else if (is_type_string(type)) { - args[0] = data; - args[1] = seed; - cgValue res = cg_emit_runtime_call(p, "default_hasher_string", args); - cg_build_return_stmt_internal_single(p, seed); - } else { - GB_PANIC("Unhandled type for hasher: %s", type_to_string(type)); - } - return p; -} \ No newline at end of file diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp deleted file mode 100644 index 597a4262c..000000000 --- a/src/tilde_stmt.cpp +++ /dev/null @@ -1,2889 +0,0 @@ -gb_internal bool cg_emit_goto(cgProcedure *p, TB_Node *control_region) { - if (tb_inst_get_control(p->func)) { - tb_inst_goto(p->func, control_region); - return true; - } - return false; -} - -gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name) { - TEMPORARY_ALLOCATOR_GUARD(); - - isize n = gb_strlen(name); - - char *new_name = gb_alloc_array(temporary_allocator(), char, n+12); - n = -1 + gb_snprintf(new_name, n+11, "%.*s_%u", cast(int)n, name, p->control_regions.count); - - TB_Node *region = tb_inst_region(p->func); - tb_inst_set_region_name(p->func, region, n, new_name); - - GB_ASSERT(p->scope_index >= 0); - array_add(&p->control_regions, cgControlRegion{region, p->scope_index}); - - return region; -} - -gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile) { - GB_ASSERT_MSG(is_type_pointer(ptr.type), "%s", type_to_string(ptr.type)); - Type *type = type_deref(ptr.type); - TB_DataType dt = cg_data_type(type); - - if (TB_IS_VOID_TYPE(dt)) { - switch (ptr.kind) { - case cgValue_Value: - return cg_lvalue_addr(ptr.node, type); - case cgValue_Addr: - GB_PANIC("NOT POSSIBLE - Cannot load an lvalue to begin with"); - break; - case cgValue_Multi: - GB_PANIC("NOT POSSIBLE - Cannot load multiple values at once"); - break; - case cgValue_Symbol: - return cg_lvalue_addr(tb_inst_get_symbol_address(p->func, ptr.symbol), type); - } - } - GB_ASSERT(dt.type != TB_MEMORY); - GB_ASSERT(dt.type != TB_TUPLE); - - // use the natural alignment - // if people need a special alignment, they can use `intrinsics.unaligned_load` - TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(type); - - TB_Node *the_ptr = nullptr; - switch (ptr.kind) { - case cgValue_Value: - the_ptr = ptr.node; - break; - case cgValue_Addr: - the_ptr = tb_inst_load(p->func, TB_TYPE_PTR, ptr.node, alignment, is_volatile); - break; - case cgValue_Multi: - GB_PANIC("NOT POSSIBLE - Cannot load multiple values at once"); - break; - case cgValue_Symbol: - the_ptr = tb_inst_get_symbol_address(p->func, ptr.symbol); - break; - } - return cg_value(tb_inst_load(p->func, dt, the_ptr, alignment, is_volatile), type); -} - -gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile) { - GB_ASSERT_MSG(dst.kind != cgValue_Multi, "cannot store to multiple values at once"); - - if (dst.kind == cgValue_Addr) { - dst = cg_emit_load(p, dst, is_volatile); - } else if (dst.kind == cgValue_Symbol) { - dst = cg_value(tb_inst_get_symbol_address(p->func, dst.symbol), dst.type); - } - - GB_ASSERT(is_type_pointer(dst.type)); - Type *dst_type = type_deref(dst.type); - - GB_ASSERT_MSG(are_types_identical(core_type(dst_type), core_type(src.type)), "%s vs %s", type_to_string(dst_type), type_to_string(src.type)); - - TB_DataType dt = cg_data_type(dst_type); - TB_DataType st = cg_data_type(src.type); - GB_ASSERT(dt.raw == st.raw); - - // use the natural alignment - // if people need a special alignment, they can use `intrinsics.unaligned_store` - TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(dst_type); - - if (TB_IS_VOID_TYPE(dt)) { - TB_Node *dst_ptr = nullptr; - TB_Node *src_ptr = nullptr; - - switch (dst.kind) { - case cgValue_Value: - dst_ptr = dst.node; - break; - case cgValue_Addr: - GB_PANIC("DST cgValue_Addr should be handled above"); - break; - case cgValue_Symbol: - dst_ptr = tb_inst_get_symbol_address(p->func, dst.symbol); - break; - } - - switch (src.kind) { - case cgValue_Value: - GB_PANIC("SRC cgValue_Value should be handled above"); - break; - case cgValue_Symbol: - GB_PANIC("SRC cgValue_Symbol should be handled above"); - break; - case cgValue_Addr: - src_ptr = src.node; - break; - } - - // IMPORTANT TODO(bill): needs to be memmove - i64 sz = type_size_of(dst_type); - TB_Node *count = tb_inst_uint(p->func, TB_TYPE_INT, cast(u64)sz); - tb_inst_memcpy(p->func, dst_ptr, src_ptr, count, alignment/*, is_volatile*/); - return; - } - - - switch (dst.kind) { - case cgValue_Value: - switch (src.kind) { - case cgValue_Value: - if (src.node->dt.type == TB_INT && src.node->dt.data == 1) { - src.node = tb_inst_zxt(p->func, src.node, dt); - } - tb_inst_store(p->func, dt, dst.node, src.node, alignment, is_volatile); - return; - case cgValue_Addr: - tb_inst_store(p->func, dt, dst.node, - tb_inst_load(p->func, st, src.node, alignment, is_volatile), - alignment, is_volatile); - return; - case cgValue_Symbol: - tb_inst_store(p->func, dt, dst.node, - tb_inst_get_symbol_address(p->func, src.symbol), - alignment, is_volatile); - return; - } - case cgValue_Addr: - GB_PANIC("cgValue_Addr should be handled above"); - break; - case cgValue_Symbol: - GB_PANIC(" cgValue_Symbol should be handled above"); - break; - } -} - - -gb_internal cgValue cg_address_from_load(cgProcedure *p, cgValue value) { - switch (value.kind) { - case cgValue_Value: - { - TB_Node *load_inst = value.node; - GB_ASSERT_MSG(load_inst->type == TB_LOAD, "expected a load instruction"); - TB_Node *ptr = load_inst->inputs[2]; - return cg_value(ptr, alloc_type_pointer(value.type)); - } - case cgValue_Addr: - return cg_value(value.node, alloc_type_pointer(value.type)); - case cgValue_Symbol: - GB_PANIC("Symbol is an invalid use case for cg_address_from_load"); - return {}; - case cgValue_Multi: - GB_PANIC("Multi is an invalid use case for cg_address_from_load"); - break; - } - GB_PANIC("Invalid cgValue for cg_address_from_load"); - return {}; - -} - -gb_internal bool cg_addr_is_empty(cgAddr const &addr) { - switch (addr.kind) { - case cgValue_Value: - case cgValue_Addr: - return addr.addr.node == nullptr; - case cgValue_Symbol: - return addr.addr.symbol == nullptr; - case cgValue_Multi: - return addr.addr.multi == nullptr; - } - return true; -} - -gb_internal Type *cg_addr_type(cgAddr const &addr) { - if (cg_addr_is_empty(addr)) { - return nullptr; - } - switch (addr.kind) { - case cgAddr_Map: - { - Type *t = base_type(addr.map.type); - GB_ASSERT(is_type_map(t)); - return t->Map.value; - } - case cgAddr_Swizzle: - return addr.swizzle.type; - case cgAddr_SwizzleLarge: - return addr.swizzle_large.type; - case cgAddr_Context: - if (addr.ctx.sel.index.count > 0) { - Type *t = t_context; - for_array(i, addr.ctx.sel.index) { - GB_ASSERT(is_type_struct(t)); - t = base_type(t)->Struct.fields[addr.ctx.sel.index[i]]->type; - } - return t; - } - break; - } - return type_deref(addr.addr.type); -} - -gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr) { - if (addr.addr.node == nullptr) { - return {}; - } - switch (addr.kind) { - case cgAddr_Default: - return cg_emit_load(p, addr.addr); - - case cgAddr_Map: - { - Type *map_type = base_type(type_deref(addr.addr.type)); - GB_ASSERT(map_type->kind == Type_Map); - cgAddr v_addr = cg_add_local(p, map_type->Map.value, nullptr, true); - - cgValue ptr = cg_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key); - cgValue ok = cg_emit_conv(p, cg_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); - - TB_Node *then = cg_control_region(p, "map.get.then"); - TB_Node *done = cg_control_region(p, "map.get.done"); - cg_emit_if(p, ok, then, done); - tb_inst_set_control(p->func, then); - { - cgValue value = cg_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); - value = cg_emit_load(p, value); - cg_addr_store(p, v_addr, value); - } - cg_emit_goto(p, done); - tb_inst_set_control(p->func, done); - - cgValue v = cg_addr_load(p, v_addr); - if (is_type_tuple(addr.map.result)) { - return cg_value_multi2(v, ok, addr.map.result); - } else { - return v; - } - } - - case cgAddr_SoaVariable: - { - Type *t = type_deref(addr.addr.type); - t = base_type(t); - GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); - Type *elem = t->Struct.soa_elem; - - cgValue len = {}; - if (t->Struct.soa_kind == StructSoa_Fixed) { - len = cg_const_int(p, t_int, t->Struct.soa_count); - } else { - cgValue v = cg_emit_load(p, addr.addr); - len = cg_builtin_len(p, v); - } - - cgAddr res = cg_add_local(p, elem, nullptr, true); - - // if (addr.soa.index_expr != nullptr && (!cg_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) { - // cg_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len); - // } - - if (t->Struct.soa_kind == StructSoa_Fixed) { - for_array(i, t->Struct.fields) { - Entity *field = t->Struct.fields[i]; - Type *base_type = field->type; - GB_ASSERT(base_type->kind == Type_Array); - - cgValue dst = cg_emit_struct_ep(p, res.addr, cast(i32)i); - cgValue src_ptr = cg_emit_struct_ep(p, addr.addr, cast(i32)i); - src_ptr = cg_emit_array_ep(p, src_ptr, addr.soa.index); - cgValue src = cg_emit_load(p, src_ptr); - cg_emit_store(p, dst, src); - } - } else { - isize field_count = t->Struct.fields.count; - if (t->Struct.soa_kind == StructSoa_Slice) { - field_count -= 1; - } else if (t->Struct.soa_kind == StructSoa_Dynamic) { - field_count -= 3; - } - for (isize i = 0; i < field_count; i++) { - Entity *field = t->Struct.fields[i]; - Type *base_type = field->type; - GB_ASSERT(base_type->kind == Type_Pointer); - - cgValue dst = cg_emit_struct_ep(p, res.addr, cast(i32)i); - cgValue src_ptr = cg_emit_struct_ep(p, addr.addr, cast(i32)i); - cgValue src = cg_emit_load(p, src_ptr); - src = cg_emit_ptr_offset(p, src, addr.soa.index); - src = cg_emit_load(p, src); - cg_emit_store(p, dst, src); - } - } - - return cg_addr_load(p, res); - } - } - GB_PANIC("TODO(bill): cg_addr_load %p", addr.addr.node); - return {}; -} - - -gb_internal void cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value) { - if (cg_addr_is_empty(addr)) { - return; - } - GB_ASSERT(value.type != nullptr); - if (is_type_untyped_uninit(value.type)) { - Type *t = cg_addr_type(addr); - value = cg_value(tb_inst_poison(p->func, cg_data_type(t)), t); - // TODO(bill): IS THIS EVEN A GOOD IDEA? - } else if (is_type_untyped_nil(value.type)) { - Type *t = cg_addr_type(addr); - value = cg_const_nil(p, t); - } - - if (addr.kind == cgAddr_RelativePointer && addr.relative.deref) { - addr = cg_addr(cg_address_from_load(p, cg_addr_load(p, addr))); - } - - if (addr.kind == cgAddr_RelativePointer) { - GB_PANIC("TODO(bill): cgAddr_RelativePointer"); - } else if (addr.kind == cgAddr_RelativeSlice) { - GB_PANIC("TODO(bill): cgAddr_RelativeSlice"); - } else if (addr.kind == cgAddr_Map) { - cg_internal_dynamic_map_set(p, addr.addr, addr.map.type, addr.map.key, value, p->curr_stmt); - return; - } else if (addr.kind == cgAddr_Context) { - cgAddr old_addr = cg_find_or_generate_context_ptr(p); - - bool create_new = true; - for_array(i, p->context_stack) { - cgContextData *ctx_data = &p->context_stack[i]; - if (ctx_data->ctx.addr.node == old_addr.addr.node) { - if (ctx_data->uses > 0) { - create_new = true; - } else if (p->scope_index > ctx_data->scope_index) { - create_new = true; - } else { - // gb_printf_err("%.*s (curr:%td) (ctx:%td) (uses:%td)\n", LIT(p->name), p->scope_index, ctx_data->scope_index, ctx_data->uses); - create_new = false; - } - break; - } - } - - cgValue next = {}; - if (create_new) { - cgValue old = cg_addr_load(p, old_addr); - cgAddr next_addr = cg_add_local(p, t_context, nullptr, true); - cg_addr_store(p, next_addr, old); - cg_push_context_onto_stack(p, next_addr); - next = next_addr.addr; - } else { - next = old_addr.addr; - } - - if (addr.ctx.sel.index.count > 0) { - cgValue lhs = cg_emit_deep_field_gep(p, next, addr.ctx.sel); - cgValue rhs = cg_emit_conv(p, value, type_deref(lhs.type)); - cg_emit_store(p, lhs, rhs); - } else { - cgValue lhs = next; - cgValue rhs = cg_emit_conv(p, value, cg_addr_type(addr)); - cg_emit_store(p, lhs, rhs); - } - return; - } else if (addr.kind == cgAddr_SoaVariable) { - GB_PANIC("TODO(bill): cgAddr_SoaVariable"); - } else if (addr.kind == cgAddr_Swizzle) { - GB_ASSERT(addr.swizzle.count <= 4); - GB_PANIC("TODO(bill): cgAddr_Swizzle"); - } else if (addr.kind == cgAddr_SwizzleLarge) { - GB_PANIC("TODO(bill): cgAddr_SwizzleLarge"); - } - - value = cg_emit_conv(p, value, cg_addr_type(addr)); - cg_emit_store(p, addr.addr, value); -} - -gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr) { - if (cg_addr_is_empty(addr)) { - GB_PANIC("Illegal addr -> nullptr"); - return {}; - } - - switch (addr.kind) { - case cgAddr_Map: - GB_PANIC("TODO(bill): cg_addr_get_ptr cgAddr_Map"); - // return cg_internal_dynamic_map_get_ptr(p, addr.addr, addr.map.key); - break; - - case cgAddr_RelativePointer: { - Type *rel_ptr = base_type(cg_addr_type(addr)); - GB_ASSERT(rel_ptr->kind == Type_RelativePointer); - - cgValue ptr = cg_emit_conv(p, addr.addr, t_uintptr); - cgValue offset = cg_emit_conv(p, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); - offset = cg_emit_load(p, offset); - - if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { - offset = cg_emit_conv(p, offset, t_i64); - } - offset = cg_emit_conv(p, offset, t_uintptr); - - cgValue absolute_ptr = cg_emit_arith(p, Token_Add, ptr, offset, t_uintptr); - absolute_ptr = cg_emit_conv(p, absolute_ptr, rel_ptr->RelativePointer.pointer_type); - - GB_PANIC("TODO(bill): cg_addr_get_ptr cgAddr_RelativePointer"); - // cgValue cond = cg_emit_comp(p, Token_CmpEq, offset, cg_const_nil(p->module, rel_ptr->RelativePointer.base_integer)); - - // NOTE(bill): nil check - // cgValue nil_ptr = cg_const_nil(p->module, rel_ptr->RelativePointer.pointer_type); - // cgValue final_ptr = cg_emit_select(p, cond, nil_ptr, absolute_ptr); - // return final_ptr; - break; - } - - case cgAddr_SoaVariable: - // TODO(bill): FIX THIS HACK - return cg_address_from_load(p, cg_addr_load(p, addr)); - - case cgAddr_Context: - GB_PANIC("cgAddr_Context should be handled elsewhere"); - break; - - case cgAddr_Swizzle: - case cgAddr_SwizzleLarge: - // TOOD(bill): is this good enough logic? - break; - } - - return addr.addr; -} - -gb_internal cgValue cg_emit_ptr_offset(cgProcedure *p, cgValue ptr, cgValue index) { - GB_ASSERT(ptr.kind == cgValue_Value); - GB_ASSERT(index.kind == cgValue_Value); - GB_ASSERT(is_type_pointer(ptr.type) || is_type_multi_pointer(ptr.type)); - GB_ASSERT(is_type_integer(index.type)); - - Type *elem = type_deref(ptr.type, true); - i64 stride = type_size_of(elem); - return cg_value(tb_inst_array_access(p->func, ptr.node, index.node, stride), alloc_type_pointer(elem)); -} -gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) { - GB_ASSERT(s.kind == cgValue_Value); - GB_ASSERT(index.kind == cgValue_Value); - - Type *t = s.type; - GB_ASSERT_MSG(is_type_pointer(t), "%s", type_to_string(t)); - Type *st = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); - GB_ASSERT_MSG(is_type_integer(core_type(index.type)), "%s", type_to_string(index.type)); - - - Type *elem = base_array_type(st); - i64 stride = type_size_of(elem); - return cg_value(tb_inst_array_access(p->func, s.node, index.node, stride), alloc_type_pointer(elem)); -} -gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index) { - return cg_emit_array_ep(p, s, cg_const_int(p, t_int, index)); -} - - -gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) { - s = cg_flatten_value(p, s); - - GB_ASSERT(is_type_pointer(s.type)); - Type *t = base_type(type_deref(s.type)); - Type *result_type = nullptr; - - if (is_type_relative_pointer(t)) { - s = cg_addr_get_ptr(p, cg_addr(s)); - } - i64 offset = -1; - i64 int_size = build_context.int_size; - i64 ptr_size = build_context.ptr_size; - - switch (t->kind) { - case Type_Struct: - type_set_offsets(t); - result_type = t->Struct.fields[index]->type; - offset = t->Struct.offsets[index]; - break; - case Type_Union: - GB_ASSERT(index == -1); - GB_PANIC("TODO(bill): cg_emit_union_tag_ptr"); - break; - // return cg_emit_union_tag_ptr(p, s); - case Type_Tuple: - type_set_offsets(t); - result_type = t->Tuple.variables[index]->type; - offset = t->Tuple.offsets[index]; - GB_PANIC("TODO(bill): cg_emit_tuple_ep %d", s.kind); - break; - // return cg_emit_tuple_ep(p, s, index); - case Type_Slice: - switch (index) { - case 0: - result_type = alloc_type_multi_pointer(t->Slice.elem); - offset = 0; - break; - case 1: - result_type = t_int; - offset = int_size; - break; - } - break; - case Type_Basic: - switch (t->Basic.kind) { - case Basic_string: - switch (index) { - case 0: - result_type = t_u8_multi_ptr; - offset = 0; - break; - case 1: - result_type = t_int; - offset = int_size; - break; - } - break; - case Basic_any: - switch (index) { - case 0: - result_type = t_rawptr; - offset = 0; - break; - case 1: - result_type = t_typeid; - offset = ptr_size; - break; - } - break; - - case Basic_complex32: - case Basic_complex64: - case Basic_complex128: - { - Type *ft = base_complex_elem_type(t); - i64 sz = type_size_of(ft); - switch (index) { - case 0: case 1: - result_type = ft; offset = sz * index; break; - default: goto error_case; - } - break; - } - case Basic_quaternion64: - case Basic_quaternion128: - case Basic_quaternion256: - { - Type *ft = base_complex_elem_type(t); - i64 sz = type_size_of(ft); - switch (index) { - case 0: case 1: case 2: case 3: - result_type = ft; offset = sz * index; break; - default: goto error_case; - } - } - break; - default: - goto error_case; - } - break; - case Type_DynamicArray: - switch (index) { - case 0: - result_type = alloc_type_multi_pointer(t->DynamicArray.elem); - offset = index*int_size; - break; - case 1: case 2: - result_type = t_int; - offset = index*int_size; - break; - case 3: - result_type = t_allocator; - offset = index*int_size; - break; - default: goto error_case; - } - break; - case Type_Map: - { - init_map_internal_types(t); - Type *itp = alloc_type_pointer(t_raw_map); - s = cg_emit_transmute(p, s, itp); - - Type *rms = base_type(t_raw_map); - GB_ASSERT(rms->kind == Type_Struct); - - if (0 <= index && index < 3) { - result_type = rms->Struct.fields[index]->type; - offset = rms->Struct.offsets[index]; - } else { - goto error_case; - } - break; - } - case Type_Array: - return cg_emit_array_epi(p, s, index); - case Type_SoaPointer: - switch (index) { - case 0: - result_type = alloc_type_pointer(t->SoaPointer.elem); - offset = 0; - break; - case 1: - result_type = t_int; - offset = int_size; - break; - } - break; - default: - error_case:; - GB_PANIC("TODO(bill): struct_gep type: %s, %lld", type_to_string(s.type), cast(long long)index); - break; - } - - GB_ASSERT_MSG(result_type != nullptr, "%s %lld", type_to_string(t), cast(long long)index); - GB_ASSERT_MSG(offset >= 0, "%s %lld", type_to_string(t), cast(long long)offset); - - GB_ASSERT(s.kind == cgValue_Value); - return cg_value( - tb_inst_member_access(p->func, s.node, offset), - alloc_type_pointer(result_type) - ); -} - - -gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index) { - s = cg_address_from_load_or_generate_local(p, s); - cgValue ptr = cg_emit_struct_ep(p, s, index); - return cg_flatten_value(p, cg_emit_load(p, ptr)); -} - - -gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel) { - GB_ASSERT(sel.index.count > 0); - Type *type = type_deref(e.type); - - for_array(i, sel.index) { - i64 index = sel.index[i]; - if (is_type_pointer(type)) { - type = type_deref(type); - e = cg_emit_load(p, e); - } - type = core_type(type); - - switch (type->kind) { - case Type_SoaPointer: { - cgValue addr = cg_emit_struct_ep(p, e, 0); - cgValue index = cg_emit_struct_ep(p, e, 1); - addr = cg_emit_load(p, addr); - index = cg_emit_load(p, index); - - i64 first_index = sel.index[0]; - Selection sub_sel = sel; - sub_sel.index.data += 1; - sub_sel.index.count -= 1; - - cgValue arr = cg_emit_struct_ep(p, addr, first_index); - - Type *t = base_type(type_deref(addr.type)); - GB_ASSERT(is_type_soa_struct(t)); - - if (t->Struct.soa_kind == StructSoa_Fixed) { - e = cg_emit_array_ep(p, arr, index); - } else { - e = cg_emit_ptr_offset(p, cg_emit_load(p, arr), index); - } - break; - } - case Type_Basic: - switch (type->Basic.kind) { - case Basic_any: - if (index == 0) { - type = t_rawptr; - } else if (index == 1) { - type = t_type_info_ptr; - } - e = cg_emit_struct_ep(p, e, index); - break; - default: - e = cg_emit_struct_ep(p, e, index); - break; - } - break; - case Type_Struct: - if (type->Struct.is_raw_union) { - type = get_struct_field_type(type, index); - GB_ASSERT(is_type_pointer(e.type)); - e = cg_emit_transmute(p, e, alloc_type_pointer(type)); - } else { - type = get_struct_field_type(type, index); - e = cg_emit_struct_ep(p, e, index); - } - break; - case Type_Union: - GB_ASSERT(index == -1); - type = t_type_info_ptr; - e = cg_emit_struct_ep(p, e, index); - break; - case Type_Tuple: - type = type->Tuple.variables[index]->type; - e = cg_emit_struct_ep(p, e, index); - break; - case Type_Slice: - case Type_DynamicArray: - case Type_Map: - case Type_RelativePointer: - e = cg_emit_struct_ep(p, e, index); - break; - case Type_Array: - e = cg_emit_array_epi(p, e, index); - break; - default: - GB_PANIC("un-gep-able type %s", type_to_string(type)); - break; - } - } - - return e; -} - - - - - - - - -gb_internal cgBranchRegions cg_lookup_branch_regions(cgProcedure *p, Ast *ident) { - GB_ASSERT(ident->kind == Ast_Ident); - Entity *e = entity_of_node(ident); - GB_ASSERT(e->kind == Entity_Label); - for (cgBranchRegions const &b : p->branch_regions) { - if (b.label == e->Label.node) { - return b; - } - } - - GB_PANIC("Unreachable"); - cgBranchRegions empty = {}; - return empty; -} - -gb_internal cgTargetList *cg_push_target_list(cgProcedure *p, Ast *label, TB_Node *break_, TB_Node *continue_, TB_Node *fallthrough_) { - cgTargetList *tl = gb_alloc_item(permanent_allocator(), cgTargetList); - tl->prev = p->target_list; - tl->break_ = break_; - tl->continue_ = continue_; - tl->fallthrough_ = fallthrough_; - p->target_list = tl; - - if (label != nullptr) { // Set label blocks - GB_ASSERT(label->kind == Ast_Label); - - for (cgBranchRegions &b : p->branch_regions) { - GB_ASSERT(b.label != nullptr && label != nullptr); - GB_ASSERT(b.label->kind == Ast_Label); - if (b.label == label) { - b.break_ = break_; - b.continue_ = continue_; - return tl; - } - } - - GB_PANIC("Unreachable"); - } - - return tl; -} - -gb_internal void cg_pop_target_list(cgProcedure *p) { - p->target_list = p->target_list->prev; -} -gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init) { - GB_ASSERT(type != nullptr); - - isize size = type_size_of(type); - TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(type); - if (is_type_matrix(type)) { - alignment *= 2; // NOTE(bill): Just in case - } - - TB_Node *local = tb_inst_local(p->func, cast(u32)size, alignment); - - if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { - // NOTE(bill): for debugging purposes only - String name = e->token.string; - TB_DebugType *debug_type = cg_debug_type(p->module, type); - tb_function_attrib_variable(p->func, local, nullptr, name.len, cast(char const *)name.text, debug_type); - } - - if (zero_init) { - bool is_volatile = false; - gb_unused(is_volatile); - TB_Node *zero = tb_inst_uint(p->func, TB_TYPE_I8, 0); - TB_Node *count = tb_inst_uint(p->func, TB_TYPE_I32, cast(u64)size); - tb_inst_memset(p->func, local, zero, count, alignment/*, is_volatile*/); - } - - cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type))); - if (e) { - map_set(&p->variable_map, e, addr); - } - return addr; -} - -gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e) { - GB_ASSERT(type != nullptr); - - isize size = type_size_of(type); - TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(type); - if (is_type_matrix(type)) { - alignment *= 2; // NOTE(bill): Just in case - } - - TB_Global *global = tb_global_create(p->module->mod, 0, "", nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(p->module->mod, tb_module_get_data(p->module->mod), global, size, alignment, 0); - TB_Node *local = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); - - if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { - // NOTE(bill): for debugging purposes only - String name = e->token.string; - TB_DebugType *debug_type = cg_debug_type(p->module, type); - tb_function_attrib_variable(p->func, local, nullptr, name.len, cast(char const *)name.text, debug_type); - } - - cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type))); - if (e) { - map_set(&p->variable_map, e, addr); - } - return addr; -} - - -gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment) { - TB_CharUnits size = cast(TB_CharUnits)type_size_of(original_type); - TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(original_type), min_alignment); - TB_Node *copy = tb_inst_local(p->func, size, align); - if (value.kind == cgValue_Value) { - tb_inst_store(p->func, cg_data_type(original_type), copy, value.node, align, false); - } else { - GB_ASSERT(value.kind == cgValue_Addr); - tb_inst_memcpy(p->func, copy, value.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align); - } - - return cg_value(copy, alloc_type_pointer(original_type)); -} - -gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value) { - switch (value.kind) { - case cgValue_Value: - if (value.node->type == TB_LOAD) { - TB_Node *ptr = value.node->inputs[2]; - return cg_value(ptr, alloc_type_pointer(value.type)); - } - break; - case cgValue_Addr: - return cg_value(value.node, alloc_type_pointer(value.type)); - case cgValue_Multi: - GB_PANIC("cgValue_Multi not allowed"); - } - - cgAddr res = cg_add_local(p, value.type, nullptr, false); - cg_addr_store(p, res, value); - return res.addr; -} - - -gb_internal void cg_build_defer_stmt(cgProcedure *p, cgDefer const &d) { - TB_Node *curr_region = tb_inst_get_control(p->func); - if (curr_region == nullptr) { - return; - } - - // NOTE(bill): The prev block may defer injection before it's terminator - TB_Node *last_inst = nullptr; - // if (curr_region->input_count) { - // last_inst = *(curr_region->inputs + curr_region->input_count); - // } - // if (last_inst && TB_IS_NODE_TERMINATOR(last_inst->type)) { - // // NOTE(bill): ReturnStmt defer stuff will be handled previously - // return; - // } - - isize prev_context_stack_count = p->context_stack.count; - GB_ASSERT(prev_context_stack_count <= p->context_stack.capacity); - defer (p->context_stack.count = prev_context_stack_count); - p->context_stack.count = d.context_stack_count; - - TB_Node *b = cg_control_region(p, "defer"); - if (last_inst == nullptr) { - cg_emit_goto(p, b); - } - - tb_inst_set_control(p->func, b); - if (d.kind == cgDefer_Node) { - cg_build_stmt(p, d.stmt); - } else if (d.kind == cgDefer_Proc) { - cg_emit_call(p, d.proc.deferred, d.proc.result_as_args); - } -} - - -gb_internal void cg_emit_defer_stmts(cgProcedure *p, cgDeferExitKind kind, TB_Node *control_region) { - isize count = p->defer_stack.count; - isize i = count; - while (i --> 0) { - cgDefer const &d = p->defer_stack[i]; - - if (kind == cgDeferExit_Default) { - if (p->scope_index == d.scope_index && - d.scope_index > 0) { - cg_build_defer_stmt(p, d); - array_pop(&p->defer_stack); - continue; - } else { - break; - } - } else if (kind == cgDeferExit_Return) { - cg_build_defer_stmt(p, d); - } else if (kind == cgDeferExit_Branch) { - GB_ASSERT(control_region != nullptr); - isize lower_limit = -1; - for (auto const &cr : p->control_regions) { - if (cr.control_region == control_region) { - lower_limit = cr.scope_index; - break; - } - } - GB_ASSERT(lower_limit >= 0); - if (lower_limit < d.scope_index) { - cg_build_defer_stmt(p, d); - } - } - } -} - -gb_internal void cg_scope_open(cgProcedure *p, Scope *scope) { - // TODO(bill): debug scope information - p->scope_index += 1; - array_add(&p->scope_stack, scope); -} - -gb_internal void cg_scope_close(cgProcedure *p, cgDeferExitKind kind, TB_Node *control_region) { - cg_emit_defer_stmts(p, kind, control_region); - GB_ASSERT(p->scope_index > 0); - - while (p->context_stack.count > 0) { - auto *ctx = &p->context_stack[p->context_stack.count-1]; - if (ctx->scope_index < p->scope_index) { - break; - } - array_pop(&p->context_stack); - } - - p->scope_index -= 1; - array_pop(&p->scope_stack); -} - - -gb_internal isize cg_append_tuple_values(cgProcedure *p, Array *dst_values, cgValue src_value) { - isize init_count = dst_values->count; - Type *t = src_value.type; - if (t && t->kind == Type_Tuple) { - GB_ASSERT(src_value.kind == cgValue_Multi); - GB_ASSERT(src_value.multi != nullptr); - GB_ASSERT(src_value.multi->values.count == t->Tuple.variables.count); - for (cgValue const &value : src_value.multi->values) { - array_add(dst_values, value); - } - } else { - array_add(dst_values, src_value); - } - return dst_values->count - init_count; -} -gb_internal void cg_build_assignment(cgProcedure *p, Array const &lvals, Slice const &values) { - if (values.count == 0) { - return; - } - - auto inits = array_make(permanent_allocator(), 0, lvals.count); - - for (Ast *rhs : values) { - cgValue init = cg_build_expr(p, rhs); - cg_append_tuple_values(p, &inits, init); - } - - bool prev_in_assignment = p->in_multi_assignment; - - isize lval_count = 0; - for (cgAddr const &lval : lvals) { - if (!cg_addr_is_empty(lval)) { - // check if it is not a blank identifier - lval_count += 1; - } - } - p->in_multi_assignment = lval_count > 1; - - GB_ASSERT(lvals.count == inits.count); - - - if (inits.count > 1) for_array(i, inits) { - cgAddr lval = lvals[i]; - cgValue init = cg_flatten_value(p, inits[i]); - - GB_ASSERT(init.kind != cgValue_Multi); - if (init.type == nullptr) { - continue; - } - - Type *type = cg_addr_type(lval); - if (!cg_addr_is_empty(lval)) { - GB_ASSERT_MSG(are_types_identical(init.type, type), "%s = %s", type_to_string(init.type), type_to_string(type)); - } - - if (init.kind == cgValue_Addr && - !cg_addr_is_empty(lval)) { - // NOTE(bill): This is needed for certain constructs such as this: - // a, b = b, a - // NOTE(bill): This is a bodge and not necessarily a good way of doing things whatsoever - TB_CharUnits size = cast(TB_CharUnits)type_size_of(type); - TB_CharUnits align = cast(TB_CharUnits)type_align_of(type); - TB_Node *copy = tb_inst_local(p->func, size, align); - tb_inst_memcpy(p->func, copy, init.node, tb_inst_uint(p->func, TB_TYPE_INT, size), align); - // use the copy instead - init.node = copy; - } - inits[i] = init; - } - - for_array(i, inits) { - cgAddr lval = lvals[i]; - cgValue init = inits[i]; - GB_ASSERT(init.kind != cgValue_Multi); - if (init.type == nullptr) { - continue; - } - cg_addr_store(p, lval, init); - } - - p->in_multi_assignment = prev_in_assignment; -} - -gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) { - if (as->op.kind == Token_Eq) { - auto lvals = array_make(permanent_allocator(), 0, as->lhs.count); - - for (Ast *lhs : as->lhs) { - cgAddr lval = {}; - if (!is_blank_ident(lhs)) { - lval = cg_build_addr(p, lhs); - } - array_add(&lvals, lval); - } - cg_build_assignment(p, lvals, as->rhs); - return; - } - - GB_ASSERT(as->lhs.count == 1); - GB_ASSERT(as->rhs.count == 1); - // NOTE(bill): Only 1 += 1 is allowed, no tuples - // +=, -=, etc - - i32 op_ = cast(i32)as->op.kind; - op_ += Token_Add - Token_AddEq; // Convert += to + - TokenKind op = cast(TokenKind)op_; - - if (op == Token_CmpAnd || op == Token_CmpOr) { - GB_PANIC("TODO(bill): cg_emit_logical_binary_expr"); - // Type *type = as->lhs[0]->tav.type; - // cgValue new_value = cg_emit_logical_binary_expr(p, op, as->lhs[0], as->rhs[0], type); - - // cgAddr lhs = cg_build_addr(p, as->lhs[0]); - // cg_addr_store(p, lhs, new_value); - } else { - cgAddr lhs = cg_build_addr(p, as->lhs[0]); - cgValue value = cg_build_expr(p, as->rhs[0]); - Type *lhs_type = cg_addr_type(lhs); - - // NOTE(bill): Allow for the weird edge case of: - // array *= matrix - if (op == Token_Mul && is_type_matrix(value.type) && is_type_array(lhs_type)) { - GB_PANIC("TODO(bill): array *= matrix"); - // cgValue old_value = cg_addr_load(p, lhs); - // Type *type = old_value.type; - // cgValue new_value = cg_emit_vector_mul_matrix(p, old_value, value, type); - // cg_addr_store(p, lhs, new_value); - // return; - } - - if (is_type_array(lhs_type)) { - GB_PANIC("TODO(bill): cg_build_assign_stmt_array"); - // cg_build_assign_stmt_array(p, op, lhs, value); - // return; - } else { - cgValue old_value = cg_addr_load(p, lhs); - Type *type = old_value.type; - - cgValue change = cg_emit_conv(p, value, type); - cgValue new_value = cg_emit_arith(p, op, old_value, change, type); - cg_addr_store(p, lhs, new_value); - } - } -} - -gb_internal void cg_build_return_stmt_internal_single(cgProcedure *p, cgValue result) { - Slice results = {}; - results.data = &result; - results.count = 1; - cg_build_return_stmt_internal(p, results); -} - - -gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice const &results) { - TypeTuple *tuple = &p->type->Proc.results->Tuple; - isize return_count = p->type->Proc.result_count; - - if (return_count == 0) { - tb_inst_ret(p->func, 0, nullptr); - return; - } - - if (p->split_returns_index >= 0) { - GB_ASSERT(is_calling_convention_odin(p->type->Proc.calling_convention)); - - for (isize i = 0; i < return_count-1; i++) { - Entity *e = tuple->variables[i]; - TB_Node *ret_ptr = tb_inst_param(p->func, cast(int)(p->split_returns_index+i)); - cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type)); - cg_emit_store(p, ptr, results[i]); - } - - if (p->return_by_ptr) { - Entity *e = tuple->variables[return_count-1]; - TB_Node *ret_ptr = tb_inst_param(p->func, 0); - cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type)); - cg_emit_store(p, ptr, results[return_count-1]); - - tb_inst_ret(p->func, 0, nullptr); - return; - } else { - GB_ASSERT(p->proto->return_count == 1); - TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt; - - cgValue result = results[return_count-1]; - result = cg_flatten_value(p, result); - TB_Node *final_res = nullptr; - if (result.kind == cgValue_Addr) { - TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type); - final_res = tb_inst_load(p->func, dt, result.node, align, false); - } else { - GB_ASSERT(result.kind == cgValue_Value); - TB_DataType st = result.node->dt; - GB_ASSERT(st.type == dt.type); - if (st.raw == dt.raw) { - final_res = result.node; - } else if (st.type == TB_INT && st.data == 1) { - final_res = tb_inst_zxt(p->func, result.node, dt); - } else { - final_res = tb_inst_bitcast(p->func, result.node, dt); - } - } - GB_ASSERT(final_res != nullptr); - - tb_inst_ret(p->func, 1, &final_res); - return; - } - - } else { - GB_ASSERT_MSG(!is_calling_convention_odin(p->type->Proc.calling_convention), "missing %s", proc_calling_convention_strings[p->type->Proc.calling_convention]); - - if (p->return_by_ptr) { - Entity *e = tuple->variables[return_count-1]; - TB_Node *ret_ptr = tb_inst_param(p->func, 0); - cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type)); - cg_emit_store(p, ptr, results[return_count-1]); - - tb_inst_ret(p->func, 0, nullptr); - return; - } else { - GB_ASSERT(p->proto->return_count == 1); - TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt; - if (results.count == 1) { - cgValue result = results[0]; - result = cg_flatten_value(p, result); - - TB_Node *final_res = nullptr; - if (result.kind == cgValue_Addr) { - TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type); - final_res = tb_inst_load(p->func, dt, result.node, align, false); - } else { - GB_ASSERT(result.kind == cgValue_Value); - TB_DataType st = result.node->dt; - GB_ASSERT(st.type == dt.type); - if (st.raw == dt.raw) { - final_res = result.node; - } else if (st.type == TB_INT && st.data == 1) { - final_res = tb_inst_zxt(p->func, result.node, dt); - } else { - final_res = tb_inst_bitcast(p->func, result.node, dt); - } - } - - GB_ASSERT(final_res != nullptr); - - tb_inst_ret(p->func, 1, &final_res); - return; - } else { - GB_ASSERT_MSG(results.count == 1, "TODO(bill): multi-return values for the return"); - return; - } - } - - } -} - - -gb_internal void cg_build_return_stmt(cgProcedure *p, Slice const &return_results) { - TypeTuple *tuple = &p->type->Proc.results->Tuple; - isize return_count = p->type->Proc.result_count; - - if (return_count == 0) { - tb_inst_ret(p->func, 0, nullptr); - return; - } - TEMPORARY_ALLOCATOR_GUARD(); - - auto results = array_make(temporary_allocator(), 0, return_count); - - if (return_results.count != 0) { - for (isize i = 0; i < return_results.count; i++) { - cgValue res = cg_build_expr(p, return_results[i]); - cg_append_tuple_values(p, &results, res); - } - } else { - for_array(i, tuple->variables) { - Entity *e = tuple->variables[i]; - cgAddr addr = map_must_get(&p->variable_map, e); - cgValue res = cg_addr_load(p, addr); - array_add(&results, res); - } - } - GB_ASSERT(results.count == return_count); - - if (return_results.count != 0 && p->type->Proc.has_named_results) { - // NOTE(bill): store the named values before returning - for_array(i, tuple->variables) { - Entity *e = tuple->variables[i]; - cgAddr addr = map_must_get(&p->variable_map, e); - cg_addr_store(p, addr, results[i]); - } - } - for_array(i, tuple->variables) { - Entity *e = tuple->variables[i]; - results[i] = cg_emit_conv(p, results[i], e->type); - } - - cg_build_return_stmt_internal(p, slice_from_array(results)); -} - -gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) { - ast_node(is, IfStmt, node); - cg_scope_open(p, is->scope); // Scope #1 - defer (cg_scope_close(p, cgDeferExit_Default, nullptr)); - - if (is->init != nullptr) { - TB_Node *init = cg_control_region(p, "if_init"); - cg_emit_goto(p, init); - tb_inst_set_control(p->func, init); - cg_build_stmt(p, is->init); - } - - TB_Node *then = cg_control_region(p, "if_then"); - TB_Node *done = cg_control_region(p, "if_done"); - TB_Node *else_ = done; - if (is->else_stmt != nullptr) { - else_ = cg_control_region(p, "if_else"); - } - - cgValue cond = cg_build_cond(p, is->cond, then, else_); - gb_unused(cond); - - if (is->label != nullptr) { - cgTargetList *tl = cg_push_target_list(p, is->label, done, nullptr, nullptr); - tl->is_block = true; - } - - // TODO(bill): should we do a constant check? - // Which philosophy are we following? - // - IR represents what the code represents (probably this) - // - IR represents what the code executes - - tb_inst_set_control(p->func, then); - - cg_build_stmt(p, is->body); - - cg_emit_goto(p, done); - - if (is->else_stmt != nullptr) { - tb_inst_set_control(p->func, else_); - - cg_scope_open(p, scope_of_node(is->else_stmt)); - cg_build_stmt(p, is->else_stmt); - cg_scope_close(p, cgDeferExit_Default, nullptr); - - cg_emit_goto(p, done); - } - - tb_inst_set_control(p->func, done); -} - -gb_internal void cg_build_for_stmt(cgProcedure *p, Ast *node) { - ast_node(fs, ForStmt, node); - - cg_scope_open(p, fs->scope); - defer (cg_scope_close(p, cgDeferExit_Default, nullptr)); - - if (fs->init != nullptr) { - TB_Node *init = cg_control_region(p, "for_init"); - cg_emit_goto(p, init); - tb_inst_set_control(p->func, init); - cg_build_stmt(p, fs->init); - } - TB_Node *body = cg_control_region(p, "for_body"); - TB_Node *done = cg_control_region(p, "for_done"); - TB_Node *loop = body; - if (fs->cond != nullptr) { - loop = cg_control_region(p, "for_loop"); - } - TB_Node *post = loop; - if (fs->post != nullptr) { - post = cg_control_region(p, "for_post"); - } - - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - if (loop != body) { - cg_build_cond(p, fs->cond, body, done); - tb_inst_set_control(p->func, body); - } - - cg_push_target_list(p, fs->label, done, post, nullptr); - cg_build_stmt(p, fs->body); - cg_pop_target_list(p); - - cg_emit_goto(p, post); - - if (fs->post != nullptr) { - tb_inst_set_control(p->func, post); - cg_build_stmt(p, fs->post); - cg_emit_goto(p, loop); - } - tb_inst_set_control(p->func, done); -} - - -gb_internal Ast *cg_strip_and_prefix(Ast *ident) { - if (ident != nullptr) { - if (ident->kind == Ast_UnaryExpr && ident->UnaryExpr.op.kind == Token_And) { - ident = ident->UnaryExpr.expr; - } - GB_ASSERT(ident->kind == Ast_Ident); - } - return ident; -} - -gb_internal void cg_emit_increment(cgProcedure *p, cgValue addr) { - GB_ASSERT(is_type_pointer(addr.type)); - Type *type = type_deref(addr.type); - cgValue v_one = cg_const_value(p, type, exact_value_i64(1)); - cg_emit_store(p, addr, cg_emit_arith(p, Token_Add, cg_emit_load(p, addr), v_one, type)); - -} - -gb_internal void cg_range_stmt_store_val(cgProcedure *p, Ast *stmt_val, cgValue const &value) { - Entity *e = entity_of_node(stmt_val); - if (e == nullptr) { - return; - } - - if (e->flags & EntityFlag_Value) { - if (value.kind == cgValue_Addr) { - cgValue ptr = cg_address_from_load_or_generate_local(p, value); - cg_add_entity(p->module, e, ptr); - return; - } - } - - cgAddr addr = cg_add_local(p, e->type, e, false); - cg_addr_store(p, addr, value); - return; -} - -gb_internal void cg_build_range_stmt_interval(cgProcedure *p, AstBinaryExpr *node, - AstRangeStmt *rs, Scope *scope) { - bool ADD_EXTRA_WRAPPING_CHECK = true; - - cg_scope_open(p, scope); - - Ast *val0 = rs->vals.count > 0 ? cg_strip_and_prefix(rs->vals[0]) : nullptr; - Ast *val1 = rs->vals.count > 1 ? cg_strip_and_prefix(rs->vals[1]) : nullptr; - Type *val0_type = nullptr; - Type *val1_type = nullptr; - if (val0 != nullptr && !is_blank_ident(val0)) { - val0_type = type_of_expr(val0); - } - if (val1 != nullptr && !is_blank_ident(val1)) { - val1_type = type_of_expr(val1); - } - - TokenKind op = Token_Lt; - switch (node->op.kind) { - case Token_Ellipsis: op = Token_LtEq; break; - case Token_RangeFull: op = Token_LtEq; break; - case Token_RangeHalf: op = Token_Lt; break; - default: GB_PANIC("Invalid interval operator"); break; - } - - - cgValue lower = cg_build_expr(p, node->left); - cgValue upper = {}; // initialized each time in the loop - - cgAddr value; - if (val0_type != nullptr) { - value = cg_add_local(p, val0_type, entity_of_node(val0), false); - } else { - value = cg_add_local(p, lower.type, nullptr, false); - } - cg_addr_store(p, value, lower); - - cgAddr index; - if (val1_type != nullptr) { - index = cg_add_local(p, val1_type, entity_of_node(val1), false); - } else { - index = cg_add_local(p, t_int, nullptr, false); - } - cg_addr_store(p, index, cg_const_int(p, t_int, 0)); - - TB_Node *loop = cg_control_region(p, "for_interval_loop"); - TB_Node *body = cg_control_region(p, "for_interval_body"); - TB_Node *done = cg_control_region(p, "for_interval_done"); - - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - upper = cg_build_expr(p, node->right); - cgValue curr_value = cg_addr_load(p, value); - cgValue cond = cg_emit_comp(p, op, curr_value, upper); - cg_emit_if(p, cond, body, done); - tb_inst_set_control(p->func, body); - - cgValue val = cg_addr_load(p, value); - cgValue idx = cg_addr_load(p, index); - - if (val0_type) cg_range_stmt_store_val(p, val0, val); - if (val1_type) cg_range_stmt_store_val(p, val1, idx); - - - { - // NOTE: this check block will most likely be optimized out, and is here - // to make this code easier to read - TB_Node *check = nullptr; - TB_Node *post = cg_control_region(p, "for_interval_post"); - - TB_Node *continue_block = post; - - if (ADD_EXTRA_WRAPPING_CHECK && - op == Token_LtEq) { - check = cg_control_region(p, "for_interval_check"); - continue_block = check; - } - - cg_push_target_list(p, rs->label, done, continue_block, nullptr); - - cg_build_stmt(p, rs->body); - - cg_scope_close(p, cgDeferExit_Default, nullptr); - cg_pop_target_list(p); - - if (check != nullptr) { - cg_emit_goto(p, check); - tb_inst_set_control(p->func, check); - - cgValue check_cond = cg_emit_comp(p, Token_NotEq, curr_value, upper); - cg_emit_if(p, check_cond, post, done); - } else { - cg_emit_goto(p, post); - } - - tb_inst_set_control(p->func, post); - cg_emit_increment(p, value.addr); - cg_emit_increment(p, index.addr); - cg_emit_goto(p, loop); - } - - tb_inst_set_control(p->func, done); -} - -gb_internal void cg_build_range_stmt_indexed(cgProcedure *p, cgValue expr, Type *val_type, cgValue count_ptr, - cgValue *val_, cgValue *idx_, TB_Node **loop_, TB_Node **done_, - bool is_reverse) { - cgValue count = {}; - Type *expr_type = base_type(type_deref(expr.type)); - switch (expr_type->kind) { - case Type_Array: - count = cg_const_int(p, t_int, expr_type->Array.count); - break; - } - - cgValue val = {}; - cgValue idx = {}; - TB_Node *loop = nullptr; - TB_Node *done = nullptr; - TB_Node *body = nullptr; - - loop = cg_control_region(p, "for_index_loop"); - body = cg_control_region(p, "for_index_body"); - done = cg_control_region(p, "for_index_done"); - - cgAddr index = cg_add_local(p, t_int, nullptr, false); - - if (!is_reverse) { - /* - for x, i in array { - ... - } - - i := -1 - for { - i += 1 - if !(i < len(array)) { - break - } - #no_bounds_check x := array[i] - ... - } - */ - - cg_addr_store(p, index, cg_const_int(p, t_int, cast(u64)-1)); - - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - cgValue incr = cg_emit_arith(p, Token_Add, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); - cg_addr_store(p, index, incr); - - if (count.node == nullptr) { - GB_ASSERT(count_ptr.node != nullptr); - count = cg_emit_load(p, count_ptr); - } - cgValue cond = cg_emit_comp(p, Token_Lt, incr, count); - cg_emit_if(p, cond, body, done); - } else { - // NOTE(bill): REVERSED LOGIC - /* - #reverse for x, i in array { - ... - } - - i := len(array) - for { - i -= 1 - if i < 0 { - break - } - #no_bounds_check x := array[i] - ... - } - */ - - if (count.node == nullptr) { - GB_ASSERT(count_ptr.node != nullptr); - count = cg_emit_load(p, count_ptr); - } - count = cg_emit_conv(p, count, t_int); - cg_addr_store(p, index, count); - - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - cgValue incr = cg_emit_arith(p, Token_Sub, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); - cg_addr_store(p, index, incr); - - cgValue anti_cond = cg_emit_comp(p, Token_Lt, incr, cg_const_int(p, t_int, 0)); - cg_emit_if(p, anti_cond, done, body); - } - - tb_inst_set_control(p->func, body); - - idx = cg_addr_load(p, index); - switch (expr_type->kind) { - case Type_Array: { - if (val_type != nullptr) { - val = cg_emit_load(p, cg_emit_array_ep(p, expr, idx)); - } - break; - } - case Type_EnumeratedArray: { - if (val_type != nullptr) { - val = cg_emit_load(p, cg_emit_array_ep(p, expr, idx)); - // NOTE(bill): Override the idx value for the enumeration - Type *index_type = expr_type->EnumeratedArray.index; - if (compare_exact_values(Token_NotEq, *expr_type->EnumeratedArray.min_value, exact_value_u64(0))) { - idx = cg_emit_arith(p, Token_Add, idx, cg_const_value(p, index_type, *expr_type->EnumeratedArray.min_value), index_type); - } - } - break; - } - case Type_Slice: { - if (val_type != nullptr) { - cgValue elem = cg_builtin_raw_data(p, expr); - val = cg_emit_load(p, cg_emit_ptr_offset(p, elem, idx)); - } - break; - } - case Type_DynamicArray: { - if (val_type != nullptr) { - cgValue elem = cg_emit_struct_ep(p, expr, 0); - elem = cg_emit_load(p, elem); - val = cg_emit_load(p, cg_emit_ptr_offset(p, elem, idx)); - } - break; - } - case Type_Struct: { - GB_ASSERT(is_type_soa_struct(expr_type)); - break; - } - - default: - GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); - break; - } - - if (val_) *val_ = val; - if (idx_) *idx_ = idx; - if (loop_) *loop_ = loop; - if (done_) *done_ = done; - -} - -gb_internal void cg_build_range_stmt_enum(cgProcedure *p, Type *enum_type, Type *val_type, cgValue *val_, cgValue *idx_, TB_Node **loop_, TB_Node **done_) { - Type *t = enum_type; - GB_ASSERT(is_type_enum(t)); - t = base_type(t); - Type *core_elem = core_type(t); - GB_ASSERT(t->kind == Type_Enum); - i64 enum_count = t->Enum.fields.count; - cgValue max_count = cg_const_int(p, t_int, enum_count); - - cgValue ti = cg_type_info(p, t); - cgValue variant = cg_emit_struct_ep(p, ti, 4); - cgValue eti_ptr = cg_emit_conv(p, variant, t_type_info_enum_ptr); - cgValue values = cg_emit_load(p, cg_emit_struct_ep(p, eti_ptr, 2)); - cgValue values_data = cg_builtin_raw_data(p, values); - - cgAddr offset_ = cg_add_local(p, t_int, nullptr, false); - cg_addr_store(p, offset_, cg_const_int(p, t_int, 0)); - - TB_Node *loop = cg_control_region(p, "for_enum_loop"); - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - TB_Node *body = cg_control_region(p, "for_enum_body"); - TB_Node *done = cg_control_region(p, "for_enum_done"); - - cgValue offset = cg_addr_load(p, offset_); - cgValue cond = cg_emit_comp(p, Token_Lt, offset, max_count); - cg_emit_if(p, cond, body, done); - tb_inst_set_control(p->func, body); - - cgValue val_ptr = cg_emit_ptr_offset(p, values_data, offset); - cg_emit_increment(p, offset_.addr); - - cgValue val = {}; - if (val_type != nullptr) { - GB_ASSERT(are_types_identical(enum_type, val_type)); - - if (is_type_integer(core_elem)) { - cgValue i = cg_emit_load(p, cg_emit_conv(p, val_ptr, t_i64_ptr)); - val = cg_emit_conv(p, i, t); - } else { - GB_PANIC("TODO(bill): enum core type %s", type_to_string(core_elem)); - } - } - - if (val_) *val_ = val; - if (idx_) *idx_ = offset; - if (loop_) *loop_ = loop; - if (done_) *done_ = done; -} - -gb_internal void cg_build_range_stmt_struct_soa(cgProcedure *p, AstRangeStmt *rs, Scope *scope) { - Ast *expr = unparen_expr(rs->expr); - TypeAndValue tav = type_and_value_of_expr(expr); - - TB_Node *loop = nullptr; - TB_Node *body = nullptr; - TB_Node *done = nullptr; - - bool is_reverse = rs->reverse; - - cg_scope_open(p, scope); - - Ast *val0 = rs->vals.count > 0 ? cg_strip_and_prefix(rs->vals[0]) : nullptr; - Ast *val1 = rs->vals.count > 1 ? cg_strip_and_prefix(rs->vals[1]) : nullptr; - Type *val_types[2] = {}; - if (val0 != nullptr && !is_blank_ident(val0)) { - val_types[0] = type_of_expr(val0); - } - if (val1 != nullptr && !is_blank_ident(val1)) { - val_types[1] = type_of_expr(val1); - } - - cgAddr array = cg_build_addr(p, expr); - if (is_type_pointer(cg_addr_type(array))) { - array = cg_addr(cg_addr_load(p, array)); - } - cgValue count = cg_builtin_len(p, cg_addr_load(p, array)); - - - cgAddr index = cg_add_local(p, t_int, nullptr, false); - - if (!is_reverse) { - /* - for x, i in array { - ... - } - - i := -1 - for { - i += 1 - if !(i < len(array)) { - break - } - x := array[i] // but #soa-ified - ... - } - */ - - cg_addr_store(p, index, cg_const_int(p, t_int, cast(u64)-1)); - - loop = cg_control_region(p, "for_soa_loop"); - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - cgValue incr = cg_emit_arith(p, Token_Add, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); - cg_addr_store(p, index, incr); - - body = cg_control_region(p, "for_soa_body"); - done = cg_control_region(p, "for_soa_done"); - - cgValue cond = cg_emit_comp(p, Token_Lt, incr, count); - cg_emit_if(p, cond, body, done); - } else { - // NOTE(bill): REVERSED LOGIC - /* - #reverse for x, i in array { - ... - } - - i := len(array) - for { - i -= 1 - if i < 0 { - break - } - #no_bounds_check x := array[i] // but #soa-ified - ... - } - */ - cg_addr_store(p, index, count); - - loop = cg_control_region(p, "for_soa_loop"); - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, loop); - - cgValue incr = cg_emit_arith(p, Token_Sub, cg_addr_load(p, index), cg_const_int(p, t_int, 1), t_int); - cg_addr_store(p, index, incr); - - body = cg_control_region(p, "for_soa_body"); - done = cg_control_region(p, "for_soa_done"); - - cgValue cond = cg_emit_comp(p, Token_Lt, incr, cg_const_int(p, t_int, 0)); - cg_emit_if(p, cond, done, body); - } - tb_inst_set_control(p->func, body); - - - if (val_types[0]) { - Entity *e = entity_of_node(val0); - if (e != nullptr) { - cgAddr soa_val = cg_addr_soa_variable(array.addr, cg_addr_load(p, index), nullptr); - map_set(&p->soa_values_map, e, soa_val); - } - } - if (val_types[1]) { - cg_range_stmt_store_val(p, val1, cg_addr_load(p, index)); - } - - - cg_push_target_list(p, rs->label, done, loop, nullptr); - - cg_build_stmt(p, rs->body); - - cg_scope_close(p, cgDeferExit_Default, nullptr); - cg_pop_target_list(p); - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, done); - -} - - -gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) { - ast_node(rs, RangeStmt, node); - - Ast *expr = unparen_expr(rs->expr); - - if (is_ast_range(expr)) { - cg_build_range_stmt_interval(p, &expr->BinaryExpr, rs, rs->scope); - return; - } - - Type *expr_type = type_of_expr(expr); - if (expr_type != nullptr) { - Type *et = base_type(type_deref(expr_type)); - if (is_type_soa_struct(et)) { - cg_build_range_stmt_struct_soa(p, rs, rs->scope); - return; - } - } - - cg_scope_open(p, rs->scope); - - - Ast *val0 = rs->vals.count > 0 ? cg_strip_and_prefix(rs->vals[0]) : nullptr; - Ast *val1 = rs->vals.count > 1 ? cg_strip_and_prefix(rs->vals[1]) : nullptr; - Type *val0_type = nullptr; - Type *val1_type = nullptr; - if (val0 != nullptr && !is_blank_ident(val0)) { - val0_type = type_of_expr(val0); - } - if (val1 != nullptr && !is_blank_ident(val1)) { - val1_type = type_of_expr(val1); - } - - cgValue val = {}; - cgValue key = {}; - TB_Node *loop = nullptr; - TB_Node *done = nullptr; - bool is_map = false; - TypeAndValue tav = type_and_value_of_expr(expr); - - if (tav.mode == Addressing_Type) { - cg_build_range_stmt_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done); - } else { - Type *expr_type = type_of_expr(expr); - Type *et = base_type(type_deref(expr_type)); - switch (et->kind) { - case Type_Map: { - is_map = true; - cgValue map = cg_build_addr_ptr(p, expr); - if (is_type_pointer(type_deref(map.type))) { - map = cg_emit_load(p, map); - } - GB_PANIC("TODO(bill): cg_build_range_map"); - // cg_build_range_map(p, map, val1_type, &val, &key, &loop, &done); - break; - } - case Type_Array: { - cgValue array = cg_build_addr_ptr(p, expr); - if (is_type_pointer(type_deref(array.type))) { - array = cg_emit_load(p, array); - } - cgAddr count_ptr = cg_add_local(p, t_int, nullptr, false); - cg_addr_store(p, count_ptr, cg_const_int(p, t_int, et->Array.count)); - cg_build_range_stmt_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse); - break; - } - case Type_EnumeratedArray: { - cgValue array = cg_build_addr_ptr(p, expr); - if (is_type_pointer(type_deref(array.type))) { - array = cg_emit_load(p, array); - } - cgAddr count_ptr = cg_add_local(p, t_int, nullptr, false); - cg_addr_store(p, count_ptr, cg_const_int(p, t_int, et->EnumeratedArray.count)); - cg_build_range_stmt_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse); - break; - } - case Type_DynamicArray: { - cgValue count_ptr = {}; - cgValue array = cg_build_addr_ptr(p, expr); - if (is_type_pointer(type_deref(array.type))) { - array = cg_emit_load(p, array); - } - count_ptr = cg_emit_struct_ep(p, array, 1); - cg_build_range_stmt_indexed(p, array, val0_type, count_ptr, &val, &key, &loop, &done, rs->reverse); - break; - } - case Type_Slice: { - cgValue count_ptr = {}; - cgValue slice = cg_build_expr(p, expr); - if (is_type_pointer(slice.type)) { - count_ptr = cg_emit_struct_ep(p, slice, 1); - slice = cg_emit_load(p, slice); - } else { - count_ptr = cg_add_local(p, t_int, nullptr, false).addr; - cg_emit_store(p, count_ptr, cg_builtin_len(p, slice)); - } - cg_build_range_stmt_indexed(p, slice, val0_type, count_ptr, &val, &key, &loop, &done, rs->reverse); - break; - } - case Type_Basic: { - cgValue string = cg_build_expr(p, expr); - if (is_type_pointer(string.type)) { - string = cg_emit_load(p, string); - } - if (is_type_untyped(expr_type)) { - cgAddr s = cg_add_local(p, default_type(string.type), nullptr, false); - cg_addr_store(p, s, string); - string = cg_addr_load(p, s); - } - Type *t = base_type(string.type); - GB_ASSERT(!is_type_cstring(t)); - GB_PANIC("TODO(bill): cg_build_range_string"); - // cg_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); - break; - } - case Type_Tuple: - GB_PANIC("TODO(bill): cg_build_range_tuple"); - // cg_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done); - break; - default: - GB_PANIC("Cannot range over %s", type_to_string(expr_type)); - break; - } - } - - if (is_map) { - if (val0_type) cg_range_stmt_store_val(p, val0, key); - if (val1_type) cg_range_stmt_store_val(p, val1, val); - } else { - if (val0_type) cg_range_stmt_store_val(p, val0, val); - if (val1_type) cg_range_stmt_store_val(p, val1, key); - } - - cg_push_target_list(p, rs->label, done, loop, nullptr); - - cg_build_stmt(p, rs->body); - - cg_scope_close(p, cgDeferExit_Default, nullptr); - cg_pop_target_list(p); - cg_emit_goto(p, loop); - tb_inst_set_control(p->func, done); -} - -gb_internal bool cg_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss) { - if (ss->tag == nullptr) { - return false; - } - enum { DISALLOW_64_SWITCH = true }; - - bool is_typeid = false; - TypeAndValue tv = type_and_value_of_expr(ss->tag); - if (is_type_integer(core_type(tv.type))) { - i64 sz = type_size_of(tv.type); - if (sz > 8) { - return false; - } - if (DISALLOW_64_SWITCH && sz == 8) { - return false; - } - // okay - } else if (is_type_typeid(tv.type)) { - // okay - is_typeid = true; - if (DISALLOW_64_SWITCH && build_context.ptr_size == 8) { - return false; - } - } else { - return false; - } - - ast_node(body, BlockStmt, ss->body); - for (Ast *clause : body->stmts) { - ast_node(cc, CaseClause, clause); - - if (cc->list.count == 0) { - continue; - } - - for (Ast *expr : cc->list) { - expr = unparen_expr(expr); - if (is_ast_range(expr)) { - return false; - } - if (expr->tav.mode == Addressing_Type) { - GB_ASSERT(is_typeid); - continue; - } - tv = type_and_value_of_expr(expr); - if (tv.mode != Addressing_Constant) { - return false; - } - if (!is_type_integer(core_type(tv.type))) { - return false; - } - } - - } - - return true; -} - - -gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) { - ast_node(ss, SwitchStmt, node); - cg_scope_open(p, ss->scope); - - if (ss->init != nullptr) { - cg_build_stmt(p, ss->init); - } - cgValue tag = {}; - if (ss->tag != nullptr) { - tag = cg_build_expr(p, ss->tag); - } else { - tag = cg_const_bool(p, t_bool, true); - } - - TB_Node *done = cg_control_region(p, "switch_done"); - - ast_node(body, BlockStmt, ss->body); - - isize case_count = body->stmts.count; - Slice default_stmts = {}; - TB_Node *default_fall = nullptr; - TB_Node *default_block = nullptr; - Scope * default_scope = nullptr; - TB_Node *fall = nullptr; - - - auto body_regions = slice_make(permanent_allocator(), body->stmts.count); - auto body_scopes = slice_make(permanent_allocator(), body->stmts.count); - for_array(i, body->stmts) { - Ast *clause = body->stmts[i]; - ast_node(cc, CaseClause, clause); - - body_regions[i] = cg_control_region(p, cc->list.count == 0 ? "switch_default_body" : "switch_case_body"); - body_scopes[i] = cc->scope; - if (cc->list.count == 0) { - default_block = body_regions[i]; - default_scope = cc->scope; - } - } - - bool is_trivial = cg_switch_stmt_can_be_trivial_jump_table(ss); - if (is_trivial) { - isize key_count = 0; - for (Ast *clause : body->stmts) { - ast_node(cc, CaseClause, clause); - key_count += cc->list.count; - } - TB_SwitchEntry *keys = gb_alloc_array(temporary_allocator(), TB_SwitchEntry, key_count); - isize key_index = 0; - for_array(i, body->stmts) { - Ast *clause = body->stmts[i]; - ast_node(cc, CaseClause, clause); - - TB_Node *region = body_regions[i]; - for (Ast *expr : cc->list) { - i64 key = 0; - expr = unparen_expr(expr); - GB_ASSERT(!is_ast_range(expr)); - if (expr->tav.mode == Addressing_Type) { - Type *type = expr->tav.value.value_typeid; - if (type == nullptr || type == t_invalid) { - type = expr->tav.type; - } - key = cg_typeid_as_u64(p->module, type); - } else { - auto tv = type_and_value_of_expr(expr); - GB_ASSERT(tv.mode == Addressing_Constant); - key = exact_value_to_i64(tv.value); - } - keys[key_index++] = {key, region}; - } - } - GB_ASSERT(key_index == key_count); - - TB_Node *end_block = done; - if (default_block) { - end_block = default_block; - } - - TB_DataType dt = cg_data_type(tag.type); - GB_ASSERT(tag.kind == cgValue_Value); - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - - tb_inst_branch(p->func, dt, tag.node, end_block, key_count, keys); - } - - for_array(i, body->stmts) { - Ast *clause = body->stmts[i]; - ast_node(cc, CaseClause, clause); - - TB_Node *body_region = body_regions[i]; - Scope *body_scope = body_scopes[i]; - fall = done; - if (i+1 < case_count) { - fall = body_regions[i+1]; - } - - if (cc->list.count == 0) { - // default case - default_stmts = cc->stmts; - default_fall = fall; - GB_ASSERT(default_block == body_region); - continue; - } - - TB_Node *next_cond = nullptr; - if (!is_trivial) for (Ast *expr : cc->list) { - expr = unparen_expr(expr); - - next_cond = cg_control_region(p, "switch_case_next"); - - cgValue cond = {}; - if (is_ast_range(expr)) { - ast_node(ie, BinaryExpr, expr); - TokenKind op = Token_Invalid; - switch (ie->op.kind) { - case Token_Ellipsis: op = Token_LtEq; break; - case Token_RangeFull: op = Token_LtEq; break; - case Token_RangeHalf: op = Token_Lt; break; - default: GB_PANIC("Invalid interval operator"); break; - } - cgValue lhs = cg_build_expr(p, ie->left); - cgValue rhs = cg_build_expr(p, ie->right); - - cgValue cond_lhs = cg_emit_comp(p, Token_LtEq, lhs, tag); - cgValue cond_rhs = cg_emit_comp(p, op, tag, rhs); - cond = cg_emit_arith(p, Token_And, cond_lhs, cond_rhs, t_bool); - } else { - if (expr->tav.mode == Addressing_Type) { - GB_ASSERT(is_type_typeid(tag.type)); - cgValue e = cg_typeid(p, expr->tav.type); - e = cg_emit_conv(p, e, tag.type); - cond = cg_emit_comp(p, Token_CmpEq, tag, e); - } else { - cond = cg_emit_comp(p, Token_CmpEq, tag, cg_build_expr(p, expr)); - } - } - - GB_ASSERT(cond.kind == cgValue_Value); - tb_inst_if(p->func, cond.node, body_region, next_cond); - tb_inst_set_control(p->func, next_cond); - } - - tb_inst_set_control(p->func, body_region); - - cg_push_target_list(p, ss->label, done, nullptr, fall); - cg_scope_open(p, body_scope); - cg_build_stmt_list(p, cc->stmts); - cg_scope_close(p, cgDeferExit_Default, body_region); - cg_pop_target_list(p); - - cg_emit_goto(p, done); - tb_inst_set_control(p->func, next_cond); - } - - if (default_block != nullptr) { - if (!is_trivial) { - cg_emit_goto(p, default_block); - } - tb_inst_set_control(p->func, default_block); - - cg_push_target_list(p, ss->label, done, nullptr, default_fall); - cg_scope_open(p, default_scope); - cg_build_stmt_list(p, default_stmts); - cg_scope_close(p, cgDeferExit_Default, default_block); - cg_pop_target_list(p); - } - - - cg_emit_goto(p, done); - tb_inst_set_control(p->func, done); - - cg_scope_close(p, cgDeferExit_Default, done); -} - -gb_internal void cg_build_type_switch_stmt(cgProcedure *p, Ast *node) { - ast_node(ss, TypeSwitchStmt, node); - - TB_Node *done_region = cg_control_region(p, "typeswitch_done"); - TB_Node *else_region = done_region; - TB_Node *default_region = nullptr; - isize num_cases = 0; - - cg_scope_open(p, ss->scope); - defer (cg_scope_close(p, cgDeferExit_Default, done_region)); - - ast_node(as, AssignStmt, ss->tag); - GB_ASSERT(as->lhs.count == 1); - GB_ASSERT(as->rhs.count == 1); - - cgValue parent = cg_build_expr(p, as->rhs[0]); - bool is_parent_ptr = is_type_pointer(parent.type); - Type *parent_base_type = type_deref(parent.type); - gb_unused(parent_base_type); - - TypeSwitchKind switch_kind = check_valid_type_switch_type(parent.type); - GB_ASSERT(switch_kind != TypeSwitch_Invalid); - - - cgValue parent_value = parent; - - cgValue parent_ptr = parent; - if (!is_parent_ptr) { - parent_ptr = cg_address_from_load_or_generate_local(p, parent); - } - - cgValue tag = {}; - cgValue union_data = {}; - if (switch_kind == TypeSwitch_Union) { - union_data = cg_emit_conv(p, parent_ptr, t_rawptr); - Type *union_type = type_deref(parent_ptr.type); - if (is_type_union_maybe_pointer(union_type)) { - tag = cg_emit_conv(p, cg_emit_comp_against_nil(p, Token_NotEq, union_data), t_int); - } else if (union_tag_size(union_type) == 0) { - tag = {}; // there is no tag for a zero sized union - } else { - cgValue tag_ptr = cg_emit_union_tag_ptr(p, parent_ptr); - tag = cg_emit_load(p, tag_ptr); - } - } else if (switch_kind == TypeSwitch_Any) { - tag = cg_emit_load(p, cg_emit_struct_ep(p, parent_ptr, 1)); - } else { - GB_PANIC("Unknown switch kind"); - } - - ast_node(body, BlockStmt, ss->body); - - for (Ast *clause : body->stmts) { - ast_node(cc, CaseClause, clause); - num_cases += cc->list.count; - if (cc->list.count == 0) { - GB_ASSERT(default_region == nullptr); - default_region = cg_control_region(p, "typeswitch_default_body"); - else_region = default_region; - } - } - - bool all_by_reference = false; - for (Ast *clause : body->stmts) { - ast_node(cc, CaseClause, clause); - if (cc->list.count != 1) { - continue; - } - Entity *case_entity = implicit_entity_of_node(clause); - all_by_reference |= (case_entity->flags & EntityFlag_Value) == 0; - break; - } - - TB_Node *backing_ptr = nullptr; - if (!all_by_reference) { - bool variants_found = false; - i64 max_size = 0; - i64 max_align = 1; - for (Ast *clause : body->stmts) { - ast_node(cc, CaseClause, clause); - if (cc->list.count != 1) { - continue; - } - Entity *case_entity = implicit_entity_of_node(clause); - if (!is_type_untyped_nil(case_entity->type)) { - max_size = gb_max(max_size, type_size_of(case_entity->type)); - max_align = gb_max(max_align, type_align_of(case_entity->type)); - variants_found = true; - } - } - if (variants_found) { - backing_ptr = tb_inst_local(p->func, cast(TB_CharUnits)max_size, cast(TB_CharUnits)max_align); - } - } - - TEMPORARY_ALLOCATOR_GUARD(); - TB_Node **control_regions = gb_alloc_array(temporary_allocator(), TB_Node *, body->stmts.count); - TB_SwitchEntry *switch_entries = gb_alloc_array(temporary_allocator(), TB_SwitchEntry, num_cases); - - isize case_index = 0; - for_array(i, body->stmts) { - Ast *clause = body->stmts[i]; - ast_node(cc, CaseClause, clause); - if (cc->list.count == 0) { - control_regions[i] = default_region; - continue; - } - - TB_Node *region = cg_control_region(p, "typeswitch_body"); - control_regions[i] = region; - - for (Ast *type_expr : cc->list) { - Type *case_type = type_of_expr(type_expr); - i64 key = -1; - if (switch_kind == TypeSwitch_Union) { - Type *ut = base_type(type_deref(parent.type)); - if (is_type_untyped_nil(case_type)) { - key = 0; - } else { - key = union_variant_index(ut, case_type); - } - } else if (switch_kind == TypeSwitch_Any) { - if (is_type_untyped_nil(case_type)) { - key = 0; - } else { - key = cast(i64)cg_typeid_as_u64(p->module, case_type); - } - } - GB_ASSERT(key >= 0); - - switch_entries[case_index++] = TB_SwitchEntry{key, region}; - } - } - - GB_ASSERT(case_index == num_cases); - - { - TB_DataType dt = {}; - TB_Node *key = nullptr; - if (type_size_of(parent_base_type) == 0) { - GB_ASSERT(tag.node == nullptr); - key = tb_inst_bool(p->func, false); - dt = cg_data_type(t_bool); - } else { - GB_ASSERT(tag.kind == cgValue_Value && tag.node != nullptr); - dt = cg_data_type(tag.type); - key = tag.node; - } - - GB_ASSERT(!TB_IS_VOID_TYPE(dt)); - tb_inst_branch(p->func, dt, key, else_region, num_cases, switch_entries); - } - - - for_array(i, body->stmts) { - Ast *clause = body->stmts[i]; - ast_node(cc, CaseClause, clause); - - bool saw_nil = false; - for (Ast *type_expr : cc->list) { - Type *case_type = type_of_expr(type_expr); - if (is_type_untyped_nil(case_type)) { - saw_nil = true; - } - } - - Entity *case_entity = implicit_entity_of_node(clause); - bool by_reference = (case_entity->flags & EntityFlag_Value) == 0; - - cg_scope_open(p, cc->scope); - - TB_Node *body_region = control_regions[i]; - tb_inst_set_control(p->func, body_region); - - if (cc->list.count == 1 && !saw_nil) { - cgValue data = {}; - if (switch_kind == TypeSwitch_Union) { - data = union_data; - } else if (switch_kind == TypeSwitch_Any) { - data = cg_emit_load(p, cg_emit_struct_ep(p, parent_ptr, 0)); - } - GB_ASSERT(data.kind == cgValue_Value); - - Type *ct = case_entity->type; - Type *ct_ptr = alloc_type_pointer(ct); - - cgValue ptr = {}; - - if (backing_ptr) { // by value - GB_ASSERT(!by_reference); - - i64 size = type_size_of(case_entity->type); - i64 align = type_align_of(case_entity->type); - - // make a copy of the case value - tb_inst_memcpy(p->func, - backing_ptr, // dst - data.node, // src - tb_inst_uint(p->func, TB_TYPE_INT, size), - cast(TB_CharUnits)align - ); - - ptr = cg_value(backing_ptr, ct_ptr); - - } else { // by reference - GB_ASSERT(by_reference); - ptr = cg_emit_conv(p, data, ct_ptr); - } - GB_ASSERT(are_types_identical(case_entity->type, type_deref(ptr.type))); - - cg_add_entity(p->module, case_entity, ptr); - String name = case_entity->token.string; - tb_function_attrib_variable(p->func, ptr.node, nullptr, name.len, cast(char const *)name.text, cg_debug_type(p->module, ct)); - } else { - if (case_entity->flags & EntityFlag_Value) { - // by value - cgAddr x = cg_add_local(p, case_entity->type, case_entity, false); - cg_addr_store(p, x, parent_value); - } else { - // by reference - cg_add_entity(p->module, case_entity, parent_value); - } - } - - cg_push_target_list(p, ss->label, done_region, nullptr, nullptr); - cg_build_stmt_list(p, cc->stmts); - cg_scope_close(p, cgDeferExit_Default, body_region); - cg_pop_target_list(p); - - cg_emit_goto(p, done_region); - } - - cg_emit_goto(p, done_region); - tb_inst_set_control(p->func, done_region); -} - - -gb_internal void cg_build_mutable_value_decl(cgProcedure *p, Ast *node) { - ast_node(vd, ValueDecl, node); - if (!vd->is_mutable) { - return; - } - - bool is_static = false; - for (Ast *name : vd->names) if (!is_blank_ident(name)) { - // NOTE(bill): Sanity check to check for the existence of the variable's Entity - GB_ASSERT(name->kind == Ast_Ident); - Entity *e = entity_of_node(name); - TokenPos pos = ast_token(name).pos; - GB_ASSERT_MSG(e != nullptr, "\n%s missing entity for %.*s", token_pos_to_string(pos), LIT(name->Ident.token.string)); - if (e->flags & EntityFlag_Static) { - // NOTE(bill): If one of the entities is static, they all are - is_static = true; - } - } - - if (is_static) { - for_array(i, vd->names) { - Ast *ident = vd->names[i]; - GB_ASSERT(!is_blank_ident(ident)); - Entity *e = entity_of_node(ident); - GB_ASSERT(e->flags & EntityFlag_Static); - String name = e->token.string; - - String mangled_name = {}; - { - gbString str = gb_string_make_length(permanent_allocator(), p->name.text, p->name.len); - str = gb_string_appendc(str, "-"); - str = gb_string_append_fmt(str, ".%.*s-%llu", LIT(name), cast(long long)e->id); - mangled_name.text = cast(u8 *)str; - mangled_name.len = gb_string_length(str); - } - - cgModule *m = p->module; - - TB_DebugType *debug_type = cg_debug_type(m, e->type); - TB_Global *global = tb_global_create(m->mod, mangled_name.len, cast(char const *)mangled_name.text, debug_type, TB_LINKAGE_PRIVATE); - - TB_ModuleSectionHandle section = tb_module_get_data(m->mod); - if (e->Variable.thread_local_model != "") { - section = tb_module_get_tls(m->mod); - String model = e->Variable.thread_local_model; - if (model == "default") { - // TODO(bill): Thread Local Storage models - } else if (model == "localdynamic") { - // TODO(bill): Thread Local Storage models - } else if (model == "initialexec") { - // TODO(bill): Thread Local Storage models - } else if (model == "localexec") { - // TODO(bill): Thread Local Storage models - } else { - GB_PANIC("Unhandled thread local mode %.*s", LIT(model)); - } - } - - i64 max_objects = 0; - ExactValue value = {}; - - if (vd->values.count > 0) { - GB_ASSERT(vd->names.count == vd->values.count); - Ast *ast_value = vd->values[i]; - GB_ASSERT(ast_value->tav.mode == Addressing_Constant || - ast_value->tav.mode == Addressing_Invalid); - - value = ast_value->tav.value; - max_objects = cg_global_const_calculate_region_count(value, e->type); - } - tb_global_set_storage(m->mod, section, global, type_size_of(e->type), type_align_of(e->type), max_objects); - - cg_global_const_add_region(m, value, e->type, global, 0); - - TB_Node *node = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global); - cgValue global_val = cg_value(node, alloc_type_pointer(e->type)); - cg_add_entity(p->module, e, global_val); - cg_add_member(p->module, mangled_name, global_val); - } - return; - } - - TEMPORARY_ALLOCATOR_GUARD(); - - - - auto inits = array_make(temporary_allocator(), 0, vd->values.count != 0 ? vd->names.count : 0); - for (Ast *rhs : vd->values) { - cgValue init = cg_build_expr(p, rhs); - cg_append_tuple_values(p, &inits, init); - } - - - auto lvals = slice_make(temporary_allocator(), vd->names.count); - for_array(i, vd->names) { - Ast *name = vd->names[i]; - if (!is_blank_ident(name)) { - Entity *e = entity_of_node(name); - bool zero_init = vd->values.count == 0; - if (vd->names.count == vd->values.count) { - Ast *expr = unparen_expr(vd->values[i]); - if (expr->kind == Ast_CompoundLit && - inits[i].kind == cgValue_Addr) { - TB_Node *ptr = inits[i].node; - - if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { - // NOTE(bill): for debugging purposes only - String name = e->token.string; - TB_DebugType *debug_type = cg_debug_type(p->module, e->type); - tb_function_attrib_variable(p->func, ptr, nullptr, name.len, cast(char const *)name.text, debug_type); - } - - cgAddr addr = cg_addr(inits[i]); - map_set(&p->variable_map, e, addr); - continue; - } - } - - lvals[i] = cg_add_local(p, e->type, e, zero_init); - } - } - - - GB_ASSERT(vd->values.count == 0 || lvals.count == inits.count); - for_array(i, inits) { - cgAddr lval = lvals[i]; - cgValue init = inits[i]; - cg_addr_store(p, lval, init); - } -} - - -gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { - Ast *prev_stmt = p->curr_stmt; - defer (p->curr_stmt = prev_stmt); - p->curr_stmt = node; - - // TODO(bill): check if last instruction was a terminating one or not - - cg_set_debug_pos_from_node(p, node); - - u16 prev_state_flags = p->state_flags; - defer (p->state_flags = prev_state_flags); - - if (node->state_flags != 0) { - u16 in = node->state_flags; - u16 out = p->state_flags; - - if (in & StateFlag_bounds_check) { - out |= StateFlag_bounds_check; - out &= ~StateFlag_no_bounds_check; - } else if (in & StateFlag_no_bounds_check) { - out |= StateFlag_no_bounds_check; - out &= ~StateFlag_bounds_check; - } - if (in & StateFlag_no_type_assert) { - out |= StateFlag_no_type_assert; - out &= ~StateFlag_type_assert; - } else if (in & StateFlag_type_assert) { - out |= StateFlag_type_assert; - out &= ~StateFlag_no_type_assert; - } - - p->state_flags = out; - } - - switch (node->kind) { - case_ast_node(bs, EmptyStmt, node); - case_end; - - case_ast_node(us, UsingStmt, node); - case_end; - - case_ast_node(ws, WhenStmt, node); - cg_build_when_stmt(p, ws); - case_end; - - case_ast_node(bs, BlockStmt, node); - TB_Node *done = nullptr; - if (bs->label != nullptr) { - done = cg_control_region(p, "block_done"); - cgTargetList *tl = cg_push_target_list(p, bs->label, done, nullptr, nullptr); - tl->is_block = true; - } - - cg_scope_open(p, bs->scope); - cg_build_stmt_list(p, bs->stmts); - cg_scope_close(p, cgDeferExit_Default, nullptr); - - if (done != nullptr) { - cg_emit_goto(p, done); - tb_inst_set_control(p->func, done); - } - - if (bs->label != nullptr) { - cg_pop_target_list(p); - } - case_end; - - case_ast_node(vd, ValueDecl, node); - cg_build_mutable_value_decl(p, node); - case_end; - - case_ast_node(bs, BranchStmt, node); - TB_Node *block = nullptr; - - if (bs->label != nullptr) { - cgBranchRegions bb = cg_lookup_branch_regions(p, bs->label); - switch (bs->token.kind) { - case Token_break: block = bb.break_; break; - case Token_continue: block = bb.continue_; break; - case Token_fallthrough: - GB_PANIC("fallthrough cannot have a label"); - break; - } - } else { - for (cgTargetList *t = p->target_list; t != nullptr && block == nullptr; t = t->prev) { - if (t->is_block) { - continue; - } - - switch (bs->token.kind) { - case Token_break: block = t->break_; break; - case Token_continue: block = t->continue_; break; - case Token_fallthrough: block = t->fallthrough_; break; - } - } - } - GB_ASSERT(block != nullptr); - - cg_emit_defer_stmts(p, cgDeferExit_Branch, block); - cg_emit_goto(p, block); - case_end; - - case_ast_node(es, ExprStmt, node); - cg_build_expr(p, es->expr); - case_end; - - case_ast_node(as, AssignStmt, node); - cg_build_assign_stmt(p, as); - case_end; - - case_ast_node(rs, ReturnStmt, node); - cg_build_return_stmt(p, rs->results); - case_end; - - case_ast_node(is, IfStmt, node); - cg_build_if_stmt(p, node); - case_end; - - case_ast_node(fs, ForStmt, node); - cg_build_for_stmt(p, node); - case_end; - - case_ast_node(rs, RangeStmt, node); - cg_build_range_stmt(p, node); - case_end; - - case_ast_node(rs, UnrollRangeStmt, node); - GB_PANIC("TODO(bill): lb_build_unroll_range_stmt"); - // cg_build_range_stmt(p, rs, rs->scope); - case_end; - - case_ast_node(fs, SwitchStmt, node); - cg_build_switch_stmt(p, node); - case_end; - - case_ast_node(ts, TypeSwitchStmt, node); - cg_build_type_switch_stmt(p, node); - case_end; - - case_ast_node(ds, DeferStmt, node); - Type *pt = base_type(p->type); - GB_ASSERT(pt->kind == Type_Proc); - if (pt->Proc.calling_convention == ProcCC_Odin) { - GB_ASSERT(p->context_stack.count != 0); - } - - cgDefer *d = array_add_and_get(&p->defer_stack); - d->kind = cgDefer_Node; - d->scope_index = p->scope_index; - d->context_stack_count = p->context_stack.count; - d->control_region = tb_inst_get_control(p->func); - GB_ASSERT(d->control_region != nullptr); - d->stmt = ds->stmt; - case_end; - - - - default: - GB_PANIC("TODO cg_build_stmt %.*s", LIT(ast_strings[node->kind])); - break; - } -} - -gb_internal void cg_build_constant_value_decl(cgProcedure *p, AstValueDecl *vd) { - if (vd == nullptr || vd->is_mutable) { - return; - } - - auto *min_dep_set = &p->module->info->minimum_dependency_set; - - static i32 global_guid = 0; - - for (Ast *ident : vd->names) { - GB_ASSERT(ident->kind == Ast_Ident); - Entity *e = entity_of_node(ident); - GB_ASSERT(e != nullptr); - if (e->kind != Entity_TypeName) { - continue; - } - - bool polymorphic_struct = false; - if (e->type != nullptr && e->kind == Entity_TypeName) { - Type *bt = base_type(e->type); - if (bt->kind == Type_Struct) { - polymorphic_struct = bt->Struct.is_polymorphic; - } - } - - if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { - continue; - } - - if (e->TypeName.ir_mangled_name.len != 0) { - // NOTE(bill): Already set - continue; - } - - cg_set_nested_type_name_ir_mangled_name(e, p); - } - - for_array(i, vd->names) { - Ast *ident = vd->names[i]; - GB_ASSERT(ident->kind == Ast_Ident); - Entity *e = entity_of_node(ident); - GB_ASSERT(e != nullptr); - if (e->kind != Entity_Procedure) { - continue; - } - GB_ASSERT (vd->values[i] != nullptr); - - Ast *value = unparen_expr(vd->values[i]); - if (value->kind != Ast_ProcLit) { - continue; // It's an alias - } - - DeclInfo *decl = decl_info_of_entity(e); - ast_node(pl, ProcLit, decl->proc_lit); - if (pl->body != nullptr) { - GenProcsData *gpd = e->Procedure.gen_procs; - if (gpd) { - rw_mutex_shared_lock(&gpd->mutex); - for (Entity *e : gpd->procs) { - if (!ptr_set_exists(min_dep_set, e)) { - continue; - } - DeclInfo *d = decl_info_of_entity(e); - cg_build_nested_proc(p, &d->proc_lit->ProcLit, e); - } - rw_mutex_shared_unlock(&gpd->mutex); - } else { - cg_build_nested_proc(p, pl, e); - } - } else { - - // FFI - Foreign function interace - String original_name = e->token.string; - String name = original_name; - - if (e->Procedure.is_foreign) { - GB_PANIC("cg_add_foreign_library_path"); - // cg_add_foreign_library_path(p->module, e->Procedure.foreign_library); - } - - if (e->Procedure.link_name.len > 0) { - name = e->Procedure.link_name; - } - - cgValue *prev_value = string_map_get(&p->module->members, name); - if (prev_value != nullptr) { - // NOTE(bill): Don't do mutliple declarations in the IR - return; - } - - e->Procedure.link_name = name; - - cgProcedure *nested_proc = cg_procedure_create(p->module, e); - - cgValue value = p->value; - - array_add(&p->children, nested_proc); - string_map_set(&p->module->members, name, value); - cg_add_procedure_to_queue(nested_proc); - } - } -} - - -gb_internal void cg_build_stmt_list(cgProcedure *p, Slice const &stmts) { - for (Ast *stmt : stmts) { - switch (stmt->kind) { - case_ast_node(vd, ValueDecl, stmt); - cg_build_constant_value_decl(p, vd); - case_end; - case_ast_node(fb, ForeignBlockDecl, stmt); - ast_node(block, BlockStmt, fb->body); - cg_build_stmt_list(p, block->stmts); - case_end; - } - } - for (Ast *stmt : stmts) { - cg_build_stmt(p, stmt); - } -} - - -gb_internal void cg_build_when_stmt(cgProcedure *p, AstWhenStmt *ws) { - TypeAndValue tv = type_and_value_of_expr(ws->cond); - GB_ASSERT(is_type_boolean(tv.type)); - GB_ASSERT(tv.value.kind == ExactValue_Bool); - if (tv.value.value_bool) { - cg_build_stmt_list(p, ws->body->BlockStmt.stmts); - } else if (ws->else_stmt) { - switch (ws->else_stmt->kind) { - case Ast_BlockStmt: - cg_build_stmt_list(p, ws->else_stmt->BlockStmt.stmts); - break; - case Ast_WhenStmt: - cg_build_when_stmt(p, &ws->else_stmt->WhenStmt); - break; - default: - GB_PANIC("Invalid 'else' statement in 'when' statement"); - break; - } - } -} - diff --git a/src/tilde_type_info.cpp b/src/tilde_type_info.cpp deleted file mode 100644 index 58e8d3087..000000000 --- a/src/tilde_type_info.cpp +++ /dev/null @@ -1,987 +0,0 @@ -gb_internal void cg_global_const_type_info_ptr(cgModule *m, Type *type, TB_Global *global, i64 offset) { - GB_ASSERT(type != nullptr); - TB_Symbol *type_table_array = cg_find_symbol_from_entity(m, cg_global_type_info_data_entity); - - - i64 index_in_bytes = cast(i64)cg_type_info_index(m->info, type); - index_in_bytes *= type_size_of(t_type_info); - - void *ti_ptr_ptr = tb_global_add_region(m->mod, global, offset, build_context.ptr_size); - // NOTE(bill): define the byte offset for the pointer - cg_write_int_at_ptr(ti_ptr_ptr, index_in_bytes, t_uintptr); - - // NOTE(bill): this will add to the byte offset set previously - tb_global_add_symbol_reloc(m->mod, global, offset, type_table_array); -} - -gb_internal cgValue cg_global_type_info_data_ptr(cgProcedure *p) { - cgValue v = cg_find_value_from_entity(p->module, cg_global_type_info_data_entity); - return cg_flatten_value(p, v); -} - -gb_internal isize cg_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found) { - auto *set = &info->minimum_dependency_type_info_set; - isize index = type_info_index(info, type, err_on_not_found); - if (index >= 0) { - auto *found = map_get(set, index); - if (found) { - GB_ASSERT(*found >= 0); - return *found + 1; - } - } - if (err_on_not_found) { - GB_PANIC("NOT FOUND lb_type_info_index '%s' @ index %td", type_to_string(type), index); - } - return -1; -} - -gb_internal cgValue cg_type_info(cgProcedure *p, Type *type) { - GB_ASSERT(!build_context.no_rtti); - - type = default_type(type); - - isize index = cg_type_info_index(p->module->info, type); - GB_ASSERT(index >= 0); - - cgValue data = cg_global_type_info_data_ptr(p); - return cg_emit_array_epi(p, data, index); -} - - -gb_internal u64 cg_typeid_as_u64(cgModule *m, Type *type) { - GB_ASSERT(!build_context.no_rtti); - - type = default_type(type); - - u64 id = cast(u64)cg_type_info_index(m->info, type); - GB_ASSERT(id >= 0); - - u64 kind = Typeid_Invalid; - u64 named = is_type_named(type) && type->kind != Type_Basic; - u64 special = 0; - u64 reserved = 0; - - Type *bt = base_type(type); - TypeKind tk = bt->kind; - switch (tk) { - case Type_Basic: { - u32 flags = bt->Basic.flags; - if (flags & BasicFlag_Boolean) kind = Typeid_Boolean; - if (flags & BasicFlag_Integer) kind = Typeid_Integer; - if (flags & BasicFlag_Unsigned) kind = Typeid_Integer; - if (flags & BasicFlag_Float) kind = Typeid_Float; - if (flags & BasicFlag_Complex) kind = Typeid_Complex; - if (flags & BasicFlag_Pointer) kind = Typeid_Pointer; - if (flags & BasicFlag_String) kind = Typeid_String; - if (flags & BasicFlag_Rune) kind = Typeid_Rune; - } break; - case Type_Pointer: kind = Typeid_Pointer; break; - case Type_MultiPointer: kind = Typeid_Multi_Pointer; break; - case Type_Array: kind = Typeid_Array; break; - case Type_Matrix: kind = Typeid_Matrix; break; - case Type_EnumeratedArray: kind = Typeid_Enumerated_Array; break; - case Type_Slice: kind = Typeid_Slice; break; - case Type_DynamicArray: kind = Typeid_Dynamic_Array; break; - case Type_Map: kind = Typeid_Map; break; - case Type_Struct: kind = Typeid_Struct; break; - case Type_Enum: kind = Typeid_Enum; break; - case Type_Union: kind = Typeid_Union; break; - case Type_Tuple: kind = Typeid_Tuple; break; - case Type_Proc: kind = Typeid_Procedure; break; - case Type_BitSet: kind = Typeid_Bit_Set; break; - case Type_SimdVector: kind = Typeid_Simd_Vector; break; - case Type_RelativePointer: kind = Typeid_Relative_Pointer; break; - case Type_RelativeMultiPointer: kind = Typeid_Relative_Multi_Pointer; break; - case Type_SoaPointer: kind = Typeid_SoaPointer; break; - } - - if (is_type_cstring(type)) { - special = 1; - } else if (is_type_integer(type) && !is_type_unsigned(type)) { - special = 1; - } - - u64 data = 0; - if (build_context.ptr_size == 4) { - GB_ASSERT(id <= (1u<<24u)); - data |= (id &~ (1u<<24)) << 0u; // index - data |= (kind &~ (1u<<5)) << 24u; // kind - data |= (named &~ (1u<<1)) << 29u; // named - data |= (special &~ (1u<<1)) << 30u; // special - data |= (reserved &~ (1u<<1)) << 31u; // reserved - } else { - GB_ASSERT(build_context.ptr_size == 8); - GB_ASSERT(id <= (1ull<<56u)); - data |= (id &~ (1ull<<56)) << 0ul; // index - data |= (kind &~ (1ull<<5)) << 56ull; // kind - data |= (named &~ (1ull<<1)) << 61ull; // named - data |= (special &~ (1ull<<1)) << 62ull; // special - data |= (reserved &~ (1ull<<1)) << 63ull; // reserved - } - - return data; -} - -gb_internal cgValue cg_typeid(cgProcedure *p, Type *t) { - u64 x = cg_typeid_as_u64(p->module, t); - return cg_value(tb_inst_uint(p->func, cg_data_type(t_typeid), x), t_typeid); -} - - - - -gb_internal void cg_set_type_info_member_types(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, Type *(*type_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_types.index * type_size_of(cg_global_type_info_member_types.elem_type); - cg_global_type_info_member_types.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_types.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_types.elem_type); - Type *type = type_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - cg_global_const_type_info_ptr(m, type, cg_global_type_info_member_types.global, offset_for_elem); - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - - -gb_internal void cg_set_type_info_member_names(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, String (*name_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_names.index * type_size_of(cg_global_type_info_member_names.elem_type); - cg_global_type_info_member_names.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_names.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_names.elem_type); - String name = name_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - cg_global_const_string(m, name, cg_global_type_info_member_names.elem_type, cg_global_type_info_member_names.global, offset_for_elem); - - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - - -gb_internal void cg_set_type_info_member_offsets(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, i64 (*offset_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_offsets.index * type_size_of(cg_global_type_info_member_offsets.elem_type); - cg_global_type_info_member_offsets.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_offsets.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_offsets.elem_type); - i64 the_offset = offset_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - - void *offset_ptr = tb_global_add_region(m->mod, cg_global_type_info_member_offsets.global, offset_for_elem, elem_size); - cg_write_uint_at_ptr(offset_ptr, the_offset, t_uintptr); - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - -gb_internal void cg_set_type_info_member_usings(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, bool (*usings_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_usings.index * type_size_of(cg_global_type_info_member_usings.elem_type); - cg_global_type_info_member_usings.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_usings.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_usings.elem_type); - GB_ASSERT(elem_size == 1); - bool the_usings = usings_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - - bool *usings_ptr = cast(bool *)tb_global_add_region(m->mod, cg_global_type_info_member_usings.global, offset_for_elem, 1); - *usings_ptr = the_usings; - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - - - -gb_internal void cg_set_type_info_member_tags(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, String (*tag_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_tags.index * type_size_of(cg_global_type_info_member_tags.elem_type); - cg_global_type_info_member_tags.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_tags.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_tags.elem_type); - String tag = tag_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - cg_global_const_string(m, tag, cg_global_type_info_member_tags.elem_type, cg_global_type_info_member_tags.global, offset_for_elem); - - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - -gb_internal void cg_set_type_info_member_enum_values(cgModule *m, TB_Global *global, isize offset, isize count, void *userdata, i64 (*value_proc)(isize index, void *userdata)) { - if (count == 0) { - return; - } - void *data_ptr = tb_global_add_region(m->mod, global, offset+0, build_context.ptr_size); - i64 offset_in_bytes = cg_global_type_info_member_enum_values.index * type_size_of(cg_global_type_info_member_enum_values.elem_type); - cg_global_type_info_member_enum_values.index += count; - - cg_write_int_at_ptr(data_ptr, offset_in_bytes, t_uintptr); - tb_global_add_symbol_reloc(m->mod, global, offset+0, cast(TB_Symbol *)cg_global_type_info_member_enum_values.global); - - for (isize i = 0; i < count; i++) { - i64 elem_size = type_size_of(cg_global_type_info_member_enum_values.elem_type); - GB_ASSERT(elem_size == 8); - i64 the_value = value_proc(i, userdata); - i64 offset_for_elem = offset_in_bytes + i*elem_size; - - void *offset_ptr = tb_global_add_region(m->mod, cg_global_type_info_member_enum_values.global, offset_for_elem, elem_size); - cg_write_uint_at_ptr(offset_ptr, the_value, cg_global_type_info_member_enum_values.elem_type); - } - - void *len_ptr = tb_global_add_region(m->mod, global, offset+build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, count, t_int); -} - - - -gb_internal void cg_setup_type_info_data(cgModule *m) { - if (build_context.no_rtti) { - return; - } - - CheckerInfo *info = m->info; - { // Add type info data - isize max_type_info_count = info->minimum_dependency_type_info_set.count+1; - // gb_printf_err("max_type_info_count: %td\n", max_type_info_count); - Type *t = alloc_type_array(t_type_info, max_type_info_count); - - i64 max_objects = cast(i64)max_type_info_count * cg_global_const_calculate_region_count_from_basic_type(t_type_info); - - TB_Global *g = tb_global_create(m->mod, -1, CG_TYPE_INFO_DATA_NAME, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, max_objects); - - cgValue value = cg_value(g, alloc_type_pointer(t)); - cg_global_type_info_data_entity = alloc_entity_variable(nullptr, make_token_ident(CG_TYPE_INFO_DATA_NAME), t, EntityState_Resolved); - cg_add_symbol(m, cg_global_type_info_data_entity, cast(TB_Symbol *)g); - cg_add_entity(m, cg_global_type_info_data_entity, value); - } - - { // Type info member buffer - // NOTE(bill): Removes need for heap allocation by making it global memory - isize count = 0; - isize enum_count = 0; - - for (Type *t : m->info->type_info_types) { - isize index = cg_type_info_index(m->info, t, false); - if (index < 0) { - continue; - } - - switch (t->kind) { - case Type_Union: - count += t->Union.variants.count; - break; - case Type_Struct: - count += t->Struct.fields.count; - break; - case Type_Tuple: - count += t->Tuple.variables.count; - break; - case Type_Enum: - enum_count += t->Enum.fields.count; - break; - } - } - - if (count > 0) { - char const *name = CG_TYPE_INFO_TYPES_NAME; - Type *t = alloc_type_array(t_type_info_ptr, count); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*3); - cg_global_type_info_member_types = GlobalTypeInfoData{g, t, t_type_info_ptr, 0}; - } - if (count > 0 || enum_count > 0) { - char const *name = CG_TYPE_INFO_NAMES_NAME; - Type *t = alloc_type_array(t_string, (enum_count+count)); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, (enum_count+count)*3); - cg_global_type_info_member_names = GlobalTypeInfoData{g, t, t_string, 0}; - } - if (count > 0) { - char const *name = CG_TYPE_INFO_OFFSETS_NAME; - Type *t = alloc_type_array(t_uintptr, count); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); - cg_global_type_info_member_offsets = GlobalTypeInfoData{g, t, t_uintptr, 0}; - } - - if (count > 0) { - char const *name = CG_TYPE_INFO_USINGS_NAME; - Type *t = alloc_type_array(t_bool, count); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count); - cg_global_type_info_member_usings = GlobalTypeInfoData{g, t, t_bool, 0}; - } - - if (count > 0) { - char const *name = CG_TYPE_INFO_TAGS_NAME; - Type *t = alloc_type_array(t_string, count); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, count*3); - cg_global_type_info_member_tags = GlobalTypeInfoData{g, t, t_string, 0}; - } - - if (enum_count > 0) { - char const *name = CG_TYPE_INFO_ENUM_VALUES_NAME; - Type *t = alloc_type_array(t_i64, enum_count); - TB_Global *g = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE); - tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), g, type_size_of(t), 16, enum_count); - cg_global_type_info_member_enum_values = GlobalTypeInfoData{g, t, t_i64, 0}; - } - } - gb_unused(info); - - - i64 global_type_info_data_entity_count = 0; - - // NOTE(bill): Set the type_table slice with the global backing array - TB_Global *type_table_slice = cast(TB_Global *)cg_find_symbol_from_entity(m, scope_lookup_current(m->info->runtime_package->scope, str_lit("type_table"))); - GB_ASSERT(type_table_slice != nullptr); - - TB_Global *type_table_array = cast(TB_Global *)cg_find_symbol_from_entity(m, cg_global_type_info_data_entity); - GB_ASSERT(type_table_array != nullptr); - - Type *type = base_type(cg_global_type_info_data_entity->type); - GB_ASSERT(is_type_array(type)); - global_type_info_data_entity_count = type->Array.count; - - tb_global_add_symbol_reloc(m->mod, type_table_slice, 0, cast(TB_Symbol *)type_table_array); - - void *len_ptr = tb_global_add_region(m->mod, type_table_slice, build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(len_ptr, type->Array.count, t_int); - - // Useful types - Entity *type_info_flags_entity = find_core_entity(info->checker, str_lit("Type_Info_Flags")); - Type *t_type_info_flags = type_info_flags_entity->type; - GB_ASSERT(type_size_of(t_type_info_flags) == 4); - - auto entries_handled = slice_make(heap_allocator(), cast(isize)global_type_info_data_entity_count); - defer (gb_free(heap_allocator(), entries_handled.data)); - entries_handled[0] = true; - - - i64 type_info_size = type_size_of(t_type_info); - i64 size_offset = type_offset_of(t_type_info, 0); - i64 align_offset = type_offset_of(t_type_info, 1); - i64 flags_offset = type_offset_of(t_type_info, 2); - i64 id_offset = type_offset_of(t_type_info, 3); - i64 variant_offset = type_offset_of(t_type_info, 4); - - Type *type_info_union = base_type(t_type_info)->Struct.fields[4]->type; - GB_ASSERT(type_info_union->kind == Type_Union); - - i64 union_tag_offset = type_info_union->Union.variant_block_size; - Type *ti_union_tag_type = union_tag_type(type_info_union); - u64 union_tag_type_size = type_size_of(ti_union_tag_type); - - auto const &set_bool = [](cgModule *m, TB_Global *global, i64 offset, bool value) { - bool *ptr = cast(bool *)tb_global_add_region(m->mod, global, offset, 1); - *ptr = value; - }; - - - for_array(type_info_type_index, info->type_info_types) { - Type *t = info->type_info_types[type_info_type_index]; - if (t == nullptr || t == t_invalid) { - continue; - } - - isize entry_index = cg_type_info_index(info, t, false); - if (entry_index <= 0) { - continue; - } - - if (entries_handled[entry_index]) { - continue; - } - entries_handled[entry_index] = true; - - TB_Global *global = type_table_array; - - i64 offset = entry_index * type_info_size; - - i64 size = type_size_of(t); - i64 align = type_align_of(t); - u32 flags = type_info_flags_of_type(t); - u64 id = cg_typeid_as_u64(m, t); - - void *size_ptr = tb_global_add_region(m->mod, global, offset+size_offset, build_context.int_size); - void *align_ptr = tb_global_add_region(m->mod, global, offset+align_offset, build_context.int_size); - void *flags_ptr = tb_global_add_region(m->mod, global, offset+flags_offset, 4); - void *id_ptr = tb_global_add_region(m->mod, global, offset+id_offset, build_context.ptr_size); - cg_write_int_at_ptr (size_ptr, size, t_int); - cg_write_int_at_ptr (align_ptr, align, t_int); - cg_write_int_at_ptr (flags_ptr, flags, t_u32); - cg_write_uint_at_ptr(id_ptr, id, t_typeid); - - - // add data to the offset to make it easier to deal with later on - offset += variant_offset; - - Type *tag_type = nullptr; - - switch (t->kind) { - case Type_Named: { - // Type_Info_Named :: struct { - // name: string, - // base: ^Type_Info, - // pkg: string, - // loc: Source_Code_Location, - // } - tag_type = t_type_info_named; - - i64 name_offset = type_offset_of(tag_type, 0); - String name = t->Named.type_name->token.string; - cg_global_const_string(m, name, t_string, global, offset+name_offset); - - i64 base_offset = type_offset_of(tag_type, 1); - cg_global_const_type_info_ptr(m, t->Named.base, global, offset+base_offset); - - if (t->Named.type_name->pkg) { - i64 pkg_offset = type_offset_of(tag_type, 2); - String pkg_name = t->Named.type_name->pkg->name; - cg_global_const_string(m, pkg_name, t_string, global, offset+pkg_offset); - } - - String proc_name = {}; - if (t->Named.type_name->parent_proc_decl) { - DeclInfo *decl = t->Named.type_name->parent_proc_decl; - if (decl->entity && decl->entity->kind == Entity_Procedure) { - i64 name_offset = type_offset_of(tag_type, 0); - proc_name = decl->entity->token.string; - cg_global_const_string(m, proc_name, t_string, global, offset+name_offset); - } - } - - i64 loc_offset = type_offset_of(tag_type, 3); - TokenPos pos = t->Named.type_name->token.pos; - cg_global_source_code_location_const(m, proc_name, pos, global, offset+loc_offset); - - break; - } - - case Type_Basic: - switch (t->Basic.kind) { - case Basic_bool: - case Basic_b8: - case Basic_b16: - case Basic_b32: - case Basic_b64: - tag_type = t_type_info_boolean; - break; - - case Basic_i8: - case Basic_u8: - case Basic_i16: - case Basic_u16: - case Basic_i32: - case Basic_u32: - case Basic_i64: - case Basic_u64: - case Basic_i128: - case Basic_u128: - - case Basic_i16le: - case Basic_u16le: - case Basic_i32le: - case Basic_u32le: - case Basic_i64le: - case Basic_u64le: - case Basic_i128le: - case Basic_u128le: - case Basic_i16be: - case Basic_u16be: - case Basic_i32be: - case Basic_u32be: - case Basic_i64be: - case Basic_u64be: - case Basic_i128be: - case Basic_u128be: - - case Basic_int: - case Basic_uint: - case Basic_uintptr: { - tag_type = t_type_info_integer; - - bool is_signed = (t->Basic.flags & BasicFlag_Unsigned) == 0; - // NOTE(bill): This is matches the runtime layout - u8 endianness_value = 0; - if (t->Basic.flags & BasicFlag_EndianLittle) { - endianness_value = 1; - } else if (t->Basic.flags & BasicFlag_EndianBig) { - endianness_value = 2; - } - u8 *signed_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+0, 1); - u8 *endianness_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+1, 1); - *signed_ptr = is_signed; - *endianness_ptr = endianness_value; - break; - } - - case Basic_rune: - tag_type = t_type_info_rune; - break; - - case Basic_f16: - case Basic_f32: - case Basic_f64: - case Basic_f16le: - case Basic_f32le: - case Basic_f64le: - case Basic_f16be: - case Basic_f32be: - case Basic_f64be: - { - tag_type = t_type_info_float; - - // // NOTE(bill): This is matches the runtime layout - u8 endianness_value = 0; - if (t->Basic.flags & BasicFlag_EndianLittle) { - endianness_value = 1; - } else if (t->Basic.flags & BasicFlag_EndianBig) { - endianness_value = 2; - } - - u8 *ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+0, 1); - *ptr = endianness_value; - } - break; - - case Basic_complex32: - case Basic_complex64: - case Basic_complex128: - tag_type = t_type_info_complex; - break; - - case Basic_quaternion64: - case Basic_quaternion128: - case Basic_quaternion256: - tag_type = t_type_info_quaternion; - break; - - case Basic_rawptr: - tag_type = t_type_info_pointer; - break; - - case Basic_string: - tag_type = t_type_info_string; - break; - - case Basic_cstring: - tag_type = t_type_info_string; - set_bool(m, global, offset+0, true); - break; - - case Basic_any: - tag_type = t_type_info_any; - break; - - case Basic_typeid: - tag_type = t_type_info_typeid; - break; - } - break; - - case Type_Pointer: - tag_type = t_type_info_pointer; - cg_global_const_type_info_ptr(m, t->Pointer.elem, global, offset+0); - break; - case Type_MultiPointer: - tag_type = t_type_info_multi_pointer; - cg_global_const_type_info_ptr(m, t->MultiPointer.elem, global, offset+0); - break; - case Type_SoaPointer: - tag_type = t_type_info_soa_pointer; - cg_global_const_type_info_ptr(m, t->SoaPointer.elem, global, offset+0); - break; - - case Type_Array: - { - tag_type = t_type_info_array; - - cg_global_const_type_info_ptr(m, t->Array.elem, global, offset+0); - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+1*build_context.int_size, build_context.int_size); - void *count_ptr = tb_global_add_region(m->mod, global, offset+2*build_context.int_size, build_context.int_size); - - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->Array.elem), t_int); - cg_write_int_at_ptr(count_ptr, t->Array.count, t_int); - } - break; - - case Type_EnumeratedArray: - { - tag_type = t_type_info_enumerated_array; - - i64 elem_offset = type_offset_of(tag_type, 0); - i64 index_offset = type_offset_of(tag_type, 1); - i64 elem_size_offset = type_offset_of(tag_type, 2); - i64 count_offset = type_offset_of(tag_type, 3); - i64 min_value_offset = type_offset_of(tag_type, 4); - i64 max_value_offset = type_offset_of(tag_type, 5); - i64 is_sparse_offset = type_offset_of(tag_type, 6); - - cg_global_const_type_info_ptr(m, t->EnumeratedArray.elem, global, offset+elem_offset); - cg_global_const_type_info_ptr(m, t->EnumeratedArray.index, global, offset+index_offset); - - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+elem_size_offset, build_context.int_size); - void *count_ptr = tb_global_add_region(m->mod, global, offset+count_offset, build_context.int_size); - - void *min_value_ptr = tb_global_add_region(m->mod, global, offset+min_value_offset, type_size_of(t_type_info_enum_value)); - void *max_value_ptr = tb_global_add_region(m->mod, global, offset+max_value_offset, type_size_of(t_type_info_enum_value)); - - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->EnumeratedArray.elem), t_int); - cg_write_int_at_ptr(count_ptr, t->EnumeratedArray.count, t_int); - - cg_write_int_at_ptr(min_value_ptr, exact_value_to_i64(*t->EnumeratedArray.min_value), t_type_info_enum_value); - cg_write_int_at_ptr(max_value_ptr, exact_value_to_i64(*t->EnumeratedArray.max_value), t_type_info_enum_value); - set_bool(m, global, offset+is_sparse_offset, t->EnumeratedArray.is_sparse); - } - break; - - case Type_DynamicArray: - { - tag_type = t_type_info_dynamic_array; - - cg_global_const_type_info_ptr(m, t->DynamicArray.elem, global, offset+0); - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+1*build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->DynamicArray.elem), t_int); - } - break; - case Type_Slice: - { - tag_type = t_type_info_slice; - - cg_global_const_type_info_ptr(m, t->Slice.elem, global, offset+0); - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+1*build_context.int_size, build_context.int_size); - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->Slice.elem), t_int); - } - break; - - case Type_Proc: - { - tag_type = t_type_info_procedure; - - i64 params_offset = type_offset_of(tag_type, 0); - i64 results_offset = type_offset_of(tag_type, 1); - i64 variadic_offset = type_offset_of(tag_type, 2); - i64 convention_offset = type_offset_of(tag_type, 3); - - if (t->Proc.params) { - cg_global_const_type_info_ptr(m, t->Proc.params, global, offset+params_offset); - } - if (t->Proc.results) { - cg_global_const_type_info_ptr(m, t->Proc.results, global, offset+results_offset); - } - - set_bool(m, global, offset+variadic_offset, t->Proc.variadic); - - u8 *convention_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+convention_offset, 1); - *convention_ptr = cast(u8)t->Proc.calling_convention; - } - break; - - case Type_Tuple: - { - tag_type = t_type_info_parameters; - - i64 types_offset = type_offset_of(tag_type, 0); - i64 names_offset = type_offset_of(tag_type, 1); - - i64 count = t->Tuple.variables.count; - - cg_set_type_info_member_types(m, global, offset+types_offset, count, t, [](isize i, void *userdata) -> Type * { - Type *t = cast(Type *)userdata; - return t->Tuple.variables[i]->type; - }); - - cg_set_type_info_member_names(m, global, offset+names_offset, count, t, [](isize i, void *userdata) -> String { - Type *t = cast(Type *)userdata; - return t->Tuple.variables[i]->token.string; - }); - } - break; - - case Type_Enum: - { - tag_type = t_type_info_enum; - - i64 base_offset = type_offset_of(tag_type, 0); - i64 names_offset = type_offset_of(tag_type, 1); - i64 values_offset = type_offset_of(tag_type, 2); - - cg_global_const_type_info_ptr(m, t->Enum.base_type, global, offset+base_offset); - - i64 count = t->Enum.fields.count; - - cg_set_type_info_member_names(m, global, offset+names_offset, count, t, [](isize i, void *userdata) -> String { - Type *t = cast(Type *)userdata; - return t->Enum.fields[i]->token.string; - }); - - cg_set_type_info_member_enum_values(m, global, offset+values_offset, count, t, [](isize i, void *userdata) -> i64 { - Type *t = cast(Type *)userdata; - Entity *e = t->Enum.fields[i]; - GB_ASSERT(e->kind == Entity_Constant); - return exact_value_to_i64(e->Constant.value); - }); - } - break; - case Type_Struct: - { - tag_type = t_type_info_struct; - - i64 types_offset = type_offset_of(tag_type, 0); - i64 names_offset = type_offset_of(tag_type, 1); - i64 offsets_offset = type_offset_of(tag_type, 2); - i64 usings_offset = type_offset_of(tag_type, 3); - i64 tags_offset = type_offset_of(tag_type, 4); - - i64 is_packed_offset = type_offset_of(tag_type, 5); - i64 is_raw_union_offset = type_offset_of(tag_type, 6); - i64 is_no_copy_offset = type_offset_of(tag_type, 7); - i64 custom_align_offset = type_offset_of(tag_type, 8); - - i64 equal_offset = type_offset_of(tag_type, 9); - - i64 soa_kind_offset = type_offset_of(tag_type, 10); - i64 soa_base_type_offset = type_offset_of(tag_type, 11); - i64 soa_len_offset = type_offset_of(tag_type, 12); - - // TODO(bill): equal proc stuff - gb_unused(equal_offset); - - i64 count = t->Struct.fields.count; - - cg_set_type_info_member_types(m, global, offset+types_offset, count, t, [](isize i, void *userdata) -> Type * { - Type *t = cast(Type *)userdata; - return t->Struct.fields[i]->type; - }); - - cg_set_type_info_member_names(m, global, offset+names_offset, count, t, [](isize i, void *userdata) -> String { - Type *t = cast(Type *)userdata; - return t->Struct.fields[i]->token.string; - }); - - cg_set_type_info_member_offsets(m, global, offset+offsets_offset, count, t, [](isize i, void *userdata) -> i64 { - Type *t = cast(Type *)userdata; - return t->Struct.offsets[i]; - }); - - cg_set_type_info_member_usings(m, global, offset+usings_offset, count, t, [](isize i, void *userdata) -> bool { - Type *t = cast(Type *)userdata; - return (t->Struct.fields[i]->flags & EntityFlag_Using) != 0; - }); - - cg_set_type_info_member_tags(m, global, offset+tags_offset, count, t, [](isize i, void *userdata) -> String { - Type *t = cast(Type *)userdata; - return t->Struct.tags[i]; - }); - - - set_bool(m, global, offset+is_packed_offset, t->Struct.is_packed); - set_bool(m, global, offset+is_raw_union_offset, t->Struct.is_raw_union); - set_bool(m, global, offset+is_no_copy_offset, t->Struct.is_no_copy); - set_bool(m, global, offset+custom_align_offset, t->Struct.custom_align != 0); - - if (t->Struct.soa_kind != StructSoa_None) { - u8 *kind_ptr = cast(u8 *)tb_global_add_region(m->mod, global, offset+soa_kind_offset, 1); - *kind_ptr = cast(u8)t->Struct.soa_kind; - - cg_global_const_type_info_ptr(m, t->Struct.soa_elem, global, offset+soa_base_type_offset); - - void *soa_len_ptr = tb_global_add_region(m->mod, global, offset+soa_len_offset, build_context.int_size); - cg_write_int_at_ptr(soa_len_ptr, t->Struct.soa_count, t_int); - } - } - break; - case Type_Union: - { - tag_type = t_type_info_union; - - i64 variants_offset = type_offset_of(tag_type, 0); - i64 tag_offset_offset = type_offset_of(tag_type, 1); - i64 tag_type_offset = type_offset_of(tag_type, 2); - - i64 equal_offset = type_offset_of(tag_type, 3); - - i64 custom_align_offset = type_offset_of(tag_type, 4); - i64 no_nil_offset = type_offset_of(tag_type, 5); - i64 shared_nil_offset = type_offset_of(tag_type, 6); - - // TODO(bill): equal procs - gb_unused(equal_offset); - - i64 count = t->Union.variants.count; - - cg_set_type_info_member_types(m, global, offset+variants_offset, count, t, [](isize i, void *userdata) -> Type * { - Type *t = cast(Type *)userdata; - return t->Union.variants[i]; - }); - - void *tag_offset_ptr = tb_global_add_region(m->mod, global, offset+tag_offset_offset, build_context.ptr_size); - cg_write_uint_at_ptr(tag_offset_ptr, t->Union.variant_block_size, t_uintptr); - - cg_global_const_type_info_ptr(m, union_tag_type(t), global, offset+tag_type_offset); - - set_bool(m, global, offset+custom_align_offset, t->Union.custom_align != 0); - set_bool(m, global, offset+no_nil_offset, t->Union.kind == UnionType_no_nil); - set_bool(m, global, offset+shared_nil_offset, t->Union.kind == UnionType_shared_nil); - } - break; - case Type_Map: - { - tag_type = t_type_info_map; - - i64 key_offset = type_offset_of(tag_type, 0); - i64 value_offset = type_offset_of(tag_type, 1); - i64 map_info_offset = type_offset_of(tag_type, 2); - - // TODO(bill): map info - gb_unused(map_info_offset); - - cg_global_const_type_info_ptr(m, t->Map.key, global, offset+key_offset); - cg_global_const_type_info_ptr(m, t->Map.value, global, offset+value_offset); - - } - break; - case Type_BitSet: - { - tag_type = t_type_info_bit_set; - - i64 elem_offset = type_offset_of(tag_type, 0); - i64 underlying_offset = type_offset_of(tag_type, 1); - i64 lower_offset = type_offset_of(tag_type, 2); - i64 upper_offset = type_offset_of(tag_type, 3); - - cg_global_const_type_info_ptr(m, t->BitSet.elem, global, offset+elem_offset); - if (t->BitSet.underlying) { - cg_global_const_type_info_ptr(m, t->BitSet.underlying, global, offset+underlying_offset); - } - - void *lower_ptr = tb_global_add_region(m->mod, global, offset+lower_offset, 8); - void *upper_ptr = tb_global_add_region(m->mod, global, offset+upper_offset, 8); - - cg_write_int_at_ptr(lower_ptr, t->BitSet.lower, t_i64); - cg_write_int_at_ptr(upper_ptr, t->BitSet.upper, t_i64); - } - break; - case Type_SimdVector: - { - tag_type = t_type_info_simd_vector; - - i64 elem_offset = type_offset_of(tag_type, 0); - i64 elem_size_offset = type_offset_of(tag_type, 1); - i64 count_offset = type_offset_of(tag_type, 2); - - cg_global_const_type_info_ptr(m, t->SimdVector.elem, global, offset+elem_offset); - - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+elem_size_offset, build_context.int_size); - void *count_ptr = tb_global_add_region(m->mod, global, offset+count_offset, build_context.int_size); - - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->SimdVector.elem), t_int); - cg_write_int_at_ptr(count_ptr, t->SimdVector.count, t_int); - } - break; - - case Type_RelativePointer: - { - tag_type = t_type_info_relative_pointer; - - i64 pointer_offset = type_offset_of(tag_type, 0); - i64 base_integer_offset = type_offset_of(tag_type, 1); - - cg_global_const_type_info_ptr(m, t->RelativePointer.pointer_type, global, offset+pointer_offset); - cg_global_const_type_info_ptr(m, t->RelativePointer.base_integer, global, offset+base_integer_offset); - } - break; - case Type_RelativeMultiPointer: - { - tag_type = t_type_info_relative_multi_pointer; - - i64 pointer_offset = type_offset_of(tag_type, 0); - i64 base_integer_offset = type_offset_of(tag_type, 1); - - cg_global_const_type_info_ptr(m, t->RelativePointer.pointer_type, global, offset+pointer_offset); - cg_global_const_type_info_ptr(m, t->RelativePointer.base_integer, global, offset+base_integer_offset); - } - break; - case Type_Matrix: - { - tag_type = t_type_info_matrix; - - i64 elem_offset = type_offset_of(tag_type, 0); - i64 elem_size_offset = type_offset_of(tag_type, 1); - i64 elem_stride_offset = type_offset_of(tag_type, 2); - i64 row_count_offset = type_offset_of(tag_type, 3); - i64 column_count_offset = type_offset_of(tag_type, 4); - - cg_global_const_type_info_ptr(m, t->Matrix.elem, global, offset+elem_offset); - - void *elem_size_ptr = tb_global_add_region(m->mod, global, offset+elem_size_offset, build_context.int_size); - void *elem_stride_ptr = tb_global_add_region(m->mod, global, offset+elem_stride_offset, build_context.int_size); - void *row_count_ptr = tb_global_add_region(m->mod, global, offset+row_count_offset, build_context.int_size); - void *column_count_ptr = tb_global_add_region(m->mod, global, offset+column_count_offset, build_context.int_size); - - cg_write_int_at_ptr(elem_size_ptr, type_size_of(t->Matrix.elem), t_int); - cg_write_int_at_ptr(elem_stride_ptr, matrix_type_stride_in_elems(t), t_int); - cg_write_int_at_ptr(row_count_ptr, t->Matrix.row_count, t_int); - cg_write_int_at_ptr(column_count_ptr, t->Matrix.column_count, t_int); - - } - break; - } - - if (tag_type != nullptr) { - i64 union_index = union_variant_index(type_info_union, tag_type); - GB_ASSERT(union_index != 0); - void *tag_ptr = tb_global_add_region(m->mod, global, offset+union_tag_offset, union_tag_type_size); - cg_write_int_at_ptr(tag_ptr, union_index, ti_union_tag_type); - } - - } -} \ No newline at end of file diff --git a/src/timings.cpp b/src/timings.cpp index 3f8402b36..f6e86867f 100644 --- a/src/timings.cpp +++ b/src/timings.cpp @@ -197,7 +197,7 @@ gb_internal void timings_print_all(Timings *t, TimingUnit unit = TimingUnit_Mill f64 total_time = time_stamp(t->total, t->freq, unit); - gb_printf("%.*s%.*s - % 9.3f %s - %6.2f%%\n", + gb_printf_err("%.*s%.*s - % 9.3f %s - %6.2f%%\n", LIT(t->total.label), cast(int)(max_len-t->total.label.len), SPACES, total_time, @@ -207,7 +207,7 @@ gb_internal void timings_print_all(Timings *t, TimingUnit unit = TimingUnit_Mill for_array(i, t->sections) { TimeStamp ts = t->sections[i]; f64 section_time = time_stamp(ts, t->freq, unit); - gb_printf("%.*s%.*s - % 9.3f %s - %6.2f%%\n", + gb_printf_err("%.*s%.*s - % 9.3f %s - %6.2f%%\n", LIT(ts.label), cast(int)(max_len-ts.label.len), SPACES, section_time, diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 53f6135d0..f505b142e 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -35,6 +35,7 @@ TOKEN_KIND(Token__OperatorBegin, ""), \ TOKEN_KIND(Token_Shr, ">>"), \ TOKEN_KIND(Token_CmpAnd, "&&"), \ TOKEN_KIND(Token_CmpOr, "||"), \ + TOKEN_KIND(Token_MulMul, "**"), \ \ TOKEN_KIND(Token__AssignOpBegin, ""), \ TOKEN_KIND(Token_AddEq, "+="), \ @@ -379,6 +380,7 @@ gb_internal void advance_to_next_rune(Tokenizer *t) { gb_internal void init_tokenizer_with_data(Tokenizer *t, String const &fullpath, void const *data, isize size) { t->fullpath = fullpath; + t->column_minus_one = -1; t->line_count = 1; t->start = cast(u8 *)data; @@ -878,6 +880,9 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) { if (t->curr_rune == '=') { advance_to_next_rune(t); token->kind = Token_MulEq; + } else if (t->curr_rune == '*') { + advance_to_next_rune(t); + token->kind = Token_MulMul; } break; case '=': @@ -968,6 +973,7 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) { advance_to_next_rune(t); for (isize comment_scope = 1; comment_scope > 0; /**/) { if (t->curr_rune == GB_RUNE_EOF) { + tokenizer_err(t, "Multi-line comment not terminated"); break; } else if (t->curr_rune == '/') { advance_to_next_rune(t); @@ -1113,6 +1119,7 @@ semicolon_check:; /*fallthrough*/ case Token_Increment: case Token_Decrement: + case Token_Not: /*fallthrough*/ t->insert_semicolon = true; break; diff --git a/src/types.cpp b/src/types.cpp index 32becc446..d85f01c41 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2,6 +2,9 @@ struct Ast; struct Scope; struct Entity; +// NOTE(Jeroen): Minimum alignment for #load(file, ) slices +#define MINIMUM_SLICE_ALIGNMENT 16 + enum BasicKind { Basic_Invalid, @@ -41,8 +44,13 @@ enum BasicKind { Basic_uint, Basic_uintptr, Basic_rawptr, - Basic_string, // ^u8 + int - Basic_cstring, // ^u8 + + Basic_string, // [^]u8 + int + Basic_cstring, // [^]u8 + + Basic_string16, // [^]u16 + int + Basic_cstring16, // [^]u16 + int + Basic_any, // rawptr + ^Type_Info Basic_typeid, @@ -152,29 +160,31 @@ struct TypeStruct { bool is_polymorphic; bool are_offsets_set : 1; - bool are_offsets_being_processed : 1; bool is_packed : 1; bool is_raw_union : 1; - bool is_no_copy : 1; + bool is_all_or_none : 1; + bool is_simple : 1; bool is_poly_specialized : 1; + + std::atomic are_offsets_being_processed; }; struct TypeUnion { - Slice variants; + Slice variants; - Ast * node; - Scope * scope; + Ast * node; + Scope * scope; - i64 variant_block_size; - i64 custom_align; - Type * polymorphic_params; // Type_Tuple - Type * polymorphic_parent; - Wait_Signal polymorphic_wait_signal; + std::atomic variant_block_size; + i64 custom_align; + Type * polymorphic_params; // Type_Tuple + Type * polymorphic_parent; + Wait_Signal polymorphic_wait_signal; - i16 tag_size; - bool is_polymorphic; - bool is_poly_specialized; - UnionTypeKind kind; + std::atomic tag_size; + bool is_polymorphic; + bool is_poly_specialized; + UnionTypeKind kind; }; struct TypeProc { @@ -201,16 +211,22 @@ struct TypeProc { bool optional_ok; }; +struct TypeNamed { + String name; + Type * base; + Entity *type_name; /* Entity_TypeName */ + + BlockingMutex gen_types_data_mutex; + GenTypesData *gen_types_data; +}; + #define TYPE_KINDS \ TYPE_KIND(Basic, BasicType) \ - TYPE_KIND(Named, struct { \ - String name; \ - Type * base; \ - Entity *type_name; /* Entity_TypeName */ \ - }) \ + TYPE_KIND(Named, TypeNamed) \ TYPE_KIND(Generic, struct { \ i64 id; \ String name; \ + InternedString interned_name; \ Type * specialized; \ Scope * scope; \ Entity *entity; \ @@ -233,6 +249,12 @@ struct TypeProc { }) \ TYPE_KIND(Slice, struct { Type *elem; }) \ TYPE_KIND(DynamicArray, struct { Type *elem; }) \ + TYPE_KIND(FixedCapacityDynamicArray, struct { \ + i64 capacity; \ + Type *generic_capacity; \ + Type *elem; \ + i64 padding_needed; /*-1 if unknown*/ \ + }) \ TYPE_KIND(Map, struct { \ Type *key; \ Type *value; \ @@ -255,7 +277,7 @@ struct TypeProc { Slice variables; /* Entity_Variable */ \ i64 * offsets; \ BlockingMutex mutex; /* for settings offsets */ \ - bool are_offsets_being_processed; \ + std::atomic are_offsets_being_processed; \ bool are_offsets_set; \ bool is_packed; \ }) \ @@ -329,6 +351,7 @@ struct Type { // NOTE(bill): These need to be at the end to not affect the unionized data std::atomic cached_size; std::atomic cached_align; + std::atomic canonical_hash; std::atomic flags; // TypeFlag bool failure; }; @@ -362,6 +385,7 @@ enum Typeid_Kind : u8 { Typeid_Matrix, Typeid_SoaPointer, Typeid_Bit_Field, + Typeid_Fixed_Capacity_Dynamic_Array, Typeid__COUNT @@ -376,7 +400,7 @@ enum TypeInfoFlag : u32 { enum : int { MATRIX_ELEMENT_COUNT_MIN = 1, - MATRIX_ELEMENT_COUNT_MAX = 16, + MATRIX_ELEMENT_COUNT_MAX = 64, MATRIX_ELEMENT_MAX_SIZE = MATRIX_ELEMENT_COUNT_MAX * (2 * 8), // complex128 SIMD_ELEMENT_COUNT_MIN = 1, @@ -399,7 +423,7 @@ gb_internal u32 type_info_flags_of_type(Type *type) { flags |= TypeInfoFlag_Comparable; } if (is_type_simple_compare(type)) { - flags |= TypeInfoFlag_Comparable; + flags |= TypeInfoFlag_Comparable|TypeInfoFlag_Simple_Compare; } return flags; } @@ -424,11 +448,8 @@ gb_internal Selection make_selection(Entity *entity, Array index, bool indi } gb_internal void selection_add_index(Selection *s, isize index) { - // IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form - // of heap allocation - // TODO(bill): Find a way to use a backing buffer for initial use as the general case is probably .count<3 if (s->index.data == nullptr) { - array_init(&s->index, heap_allocator()); + array_init(&s->index, permanent_allocator()); } array_add(&s->index, cast(i32)index); } @@ -436,7 +457,7 @@ gb_internal void selection_add_index(Selection *s, isize index) { gb_internal Selection selection_combine(Selection const &lhs, Selection const &rhs) { Selection new_sel = lhs; new_sel.indirect = lhs.indirect || rhs.indirect; - new_sel.index = array_make(heap_allocator(), lhs.index.count+rhs.index.count); + new_sel.index = array_make(permanent_allocator(), lhs.index.count+rhs.index.count); array_copy(&new_sel.index, lhs.index, 0); array_copy(&new_sel.index, rhs.index, lhs.index.count); return new_sel; @@ -501,8 +522,14 @@ gb_global Type basic_types[] = { {Type_Basic, {Basic_uintptr, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uintptr")}}, {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}}, + {Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}}, {Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}}, + + {Type_Basic, {Basic_string16, BasicFlag_String, -1, STR_LIT("string16")}}, + {Type_Basic, {Basic_cstring16, BasicFlag_String, -1, STR_LIT("cstring16")}}, + + {Type_Basic, {Basic_any, 0, 16, STR_LIT("any")}}, {Type_Basic, {Basic_typeid, 0, 8, STR_LIT("typeid")}}, @@ -592,8 +619,12 @@ gb_global Type *t_uint = &basic_types[Basic_uint]; gb_global Type *t_uintptr = &basic_types[Basic_uintptr]; gb_global Type *t_rawptr = &basic_types[Basic_rawptr]; + gb_global Type *t_string = &basic_types[Basic_string]; gb_global Type *t_cstring = &basic_types[Basic_cstring]; +gb_global Type *t_string16 = &basic_types[Basic_string16]; +gb_global Type *t_cstring16 = &basic_types[Basic_cstring16]; + gb_global Type *t_any = &basic_types[Basic_any]; gb_global Type *t_typeid = &basic_types[Basic_typeid]; @@ -631,6 +662,8 @@ gb_global Type *t_untyped_uninit = &basic_types[Basic_UntypedUninit]; gb_global Type *t_u8_ptr = nullptr; gb_global Type *t_u8_multi_ptr = nullptr; +gb_global Type *t_u16_ptr = nullptr; +gb_global Type *t_u16_multi_ptr = nullptr; gb_global Type *t_int_ptr = nullptr; gb_global Type *t_i64_ptr = nullptr; gb_global Type *t_f64_ptr = nullptr; @@ -644,6 +677,8 @@ gb_global Type *t_type_info_enum_value = nullptr; gb_global Type *t_type_info_ptr = nullptr; gb_global Type *t_type_info_enum_value_ptr = nullptr; +gb_global Type *t_type_info_string_encoding_kind = nullptr; + gb_global Type *t_type_info_named = nullptr; gb_global Type *t_type_info_integer = nullptr; gb_global Type *t_type_info_rune = nullptr; @@ -671,6 +706,7 @@ gb_global Type *t_type_info_simd_vector = nullptr; gb_global Type *t_type_info_matrix = nullptr; gb_global Type *t_type_info_soa_pointer = nullptr; gb_global Type *t_type_info_bit_field = nullptr; +gb_global Type *t_type_info_fixed_capacity_dynamic_array = nullptr; gb_global Type *t_type_info_named_ptr = nullptr; gb_global Type *t_type_info_integer_ptr = nullptr; @@ -699,6 +735,7 @@ gb_global Type *t_type_info_simd_vector_ptr = nullptr; gb_global Type *t_type_info_matrix_ptr = nullptr; gb_global Type *t_type_info_soa_pointer_ptr = nullptr; gb_global Type *t_type_info_bit_field_ptr = nullptr; +gb_global Type *t_type_info_fixed_capacity_dynamic_array_ptr = nullptr; gb_global Type *t_allocator = nullptr; gb_global Type *t_allocator_ptr = nullptr; @@ -730,11 +767,22 @@ gb_global Type *t_objc_object = nullptr; gb_global Type *t_objc_selector = nullptr; gb_global Type *t_objc_class = nullptr; gb_global Type *t_objc_ivar = nullptr; +gb_global Type *t_objc_super = nullptr; // Struct used in lieu of the 'self' instance when calling objc_msgSendSuper. +gb_global Type *t_objc_super_ptr = nullptr; gb_global Type *t_objc_id = nullptr; gb_global Type *t_objc_SEL = nullptr; gb_global Type *t_objc_Class = nullptr; gb_global Type *t_objc_Ivar = nullptr; +gb_global Type *t_objc_instancetype = nullptr; // Special distinct variant of t_objc_id used mimic auto-typing of instancetype* in Objective-C + + +gb_global Type *t_c_va_list = nullptr; +gb_global Type *t_c_va_list_ptr = nullptr; + + +gb_global Type *t_odin_calling_convention = nullptr; + enum OdinAtomicMemoryOrder : i32 { OdinAtomicMemoryOrder_relaxed = 0, // unordered @@ -760,6 +808,34 @@ gb_global Type *t_atomic_memory_order = nullptr; +enum OdinFastMathFlag : u8 { + OdinFastMath_Allow_Reassoc = 0, + OdinFastMath_No_NaNs = 1, + OdinFastMath_No_Infs = 2, + OdinFastMath_No_Signed_Zeros = 3, + OdinFastMath_Allow_Reciprocal = 4, + OdinFastMath_Allow_Contract = 5, + OdinFastMath_Approx_Func = 6, + + OdinFastMath_COUNT, +}; + +char const *OdinFastMathFlag_strings[OdinFastMath_COUNT] = { + "Allow_Reassoc", + "No_NaNs", + "No_Infs", + "No_Signed_Zeros", + "Allow_Reciprocal", + "Allow_Contract", + "Approx_Func", +}; + +gb_global Type *t_fast_math_flag = nullptr; // named enum +gb_global Type *t_fast_math_flags = nullptr; // named bit_set + + + + gb_global RecursiveMutex g_type_mutex; struct TypePath; @@ -939,10 +1015,7 @@ gb_internal void set_base_type(Type *t, Type *base) { gb_internal Type *alloc_type(TypeKind kind) { - // gbAllocator a = heap_allocator(); - gbAllocator a = permanent_allocator(); - Type *t = gb_alloc_item(a, Type); - gb_zero_item(t); + Type *t = permanent_alloc_item(); t->kind = kind; t->cached_size = -1; t->cached_align = -1; @@ -950,10 +1023,11 @@ gb_internal Type *alloc_type(TypeKind kind) { } -gb_internal Type *alloc_type_generic(Scope *scope, i64 id, String name, Type *specialized) { +gb_internal Type *alloc_type_generic(Scope *scope, i64 id, InternedString interned_name, Type *specialized) { Type *t = alloc_type(Type_Generic); t->Generic.id = id; - t->Generic.name = name; + t->Generic.name = interned_name.string(); + t->Generic.interned_name = interned_name; t->Generic.specialized = specialized; t->Generic.scope = scope; return t; @@ -1037,8 +1111,8 @@ gb_internal Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValu Type *t = alloc_type(Type_EnumeratedArray); t->EnumeratedArray.elem = elem; t->EnumeratedArray.index = index; - t->EnumeratedArray.min_value = gb_alloc_item(permanent_allocator(), ExactValue); - t->EnumeratedArray.max_value = gb_alloc_item(permanent_allocator(), ExactValue); + t->EnumeratedArray.min_value = permanent_alloc_item(); + t->EnumeratedArray.max_value = permanent_alloc_item(); gb_memmove(t->EnumeratedArray.min_value, min_value, gb_size_of(ExactValue)); gb_memmove(t->EnumeratedArray.max_value, max_value, gb_size_of(ExactValue)); t->EnumeratedArray.op = op; @@ -1064,6 +1138,23 @@ gb_internal Type *alloc_type_dynamic_array(Type *elem) { return t; } +gb_internal Type *alloc_type_fixed_capacity_dynamic_array(Type *elem, i64 capacity, Type *generic_capacity = nullptr) { + if (generic_capacity != nullptr) { + Type *t = alloc_type(Type_FixedCapacityDynamicArray); + t->FixedCapacityDynamicArray.elem = elem; + t->FixedCapacityDynamicArray.capacity = capacity; + t->FixedCapacityDynamicArray.generic_capacity = generic_capacity; + t->FixedCapacityDynamicArray.padding_needed = -1; + return t; + } + Type *t = alloc_type(Type_FixedCapacityDynamicArray); + t->FixedCapacityDynamicArray.elem = elem; + t->FixedCapacityDynamicArray.capacity = capacity; + t->FixedCapacityDynamicArray.padding_needed = -1; + return t; +} + + gb_internal Type *alloc_type_struct() { Type *t = alloc_type(Type_Struct); @@ -1085,8 +1176,8 @@ gb_internal Type *alloc_type_union() { gb_internal Type *alloc_type_enum() { Type *t = alloc_type(Type_Enum); - t->Enum.min_value = gb_alloc_item(permanent_allocator(), ExactValue); - t->Enum.max_value = gb_alloc_item(permanent_allocator(), ExactValue); + t->Enum.min_value = permanent_alloc_item(); + t->Enum.max_value = permanent_alloc_item(); return t; } @@ -1203,6 +1294,7 @@ gb_internal Type *type_deref(Type *t, bool allow_multi_pointer) { } gb_internal bool is_type_named(Type *t) { + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return true; } @@ -1210,16 +1302,16 @@ gb_internal bool is_type_named(Type *t) { } gb_internal bool is_type_boolean(Type *t) { - // t = core_type(t); t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Boolean) != 0; } return false; } gb_internal bool is_type_integer(Type *t) { - // t = core_type(t); t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Integer) != 0; } @@ -1227,6 +1319,7 @@ gb_internal bool is_type_integer(Type *t) { } gb_internal bool is_type_integer_like(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & (BasicFlag_Integer|BasicFlag_Boolean)) != 0; } @@ -1241,31 +1334,45 @@ gb_internal bool is_type_integer_like(Type *t) { gb_internal bool is_type_unsigned(Type *t) { t = base_type(t); - // t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Unsigned) != 0; } + if (t->kind == Type_Enum) { + return (t->Enum.base_type->Basic.flags & BasicFlag_Unsigned) != 0; + } return false; } gb_internal bool is_type_integer_128bit(Type *t) { - // t = core_type(t); t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Integer) != 0 && t->Basic.size == 16; } return false; } gb_internal bool is_type_rune(Type *t) { - // t = core_type(t); t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Rune) != 0; } return false; } -gb_internal bool is_type_numeric(Type *t) { - // t = core_type(t); +gb_internal bool is_type_integer_or_float(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return (t->Basic.flags & (BasicFlag_Integer|BasicFlag_Float)) != 0; + } + return false; +} + + + +gb_internal bool is_type_numeric(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Numeric) != 0; } else if (t->kind == Type_Enum) { @@ -1279,23 +1386,39 @@ gb_internal bool is_type_numeric(Type *t) { } gb_internal bool is_type_string(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_String) != 0; } return false; } +gb_internal bool is_type_string16(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_string16; + } + return false; +} gb_internal bool is_type_cstring(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return t->Basic.kind == Basic_cstring; } return false; } +gb_internal bool is_type_cstring16(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_cstring16; + } + return false; +} gb_internal bool is_type_typed(Type *t) { t = base_type(t); - if (t == nullptr) { - return false; - } + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Untyped) == 0; } @@ -1303,9 +1426,7 @@ gb_internal bool is_type_typed(Type *t) { } gb_internal bool is_type_untyped(Type *t) { t = base_type(t); - if (t == nullptr) { - return false; - } + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Untyped) != 0; } @@ -1313,6 +1434,7 @@ gb_internal bool is_type_untyped(Type *t) { } gb_internal bool is_type_ordered(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } switch (t->kind) { case Type_Basic: return (t->Basic.flags & BasicFlag_Ordered) != 0; @@ -1325,6 +1447,7 @@ gb_internal bool is_type_ordered(Type *t) { } gb_internal bool is_type_ordered_numeric(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } switch (t->kind) { case Type_Basic: return (t->Basic.flags & BasicFlag_OrderedNumeric) != 0; @@ -1333,19 +1456,27 @@ gb_internal bool is_type_ordered_numeric(Type *t) { } gb_internal bool is_type_constant_type(Type *t) { t = core_type(t); - if (t->kind == Type_Basic) { + if (t == nullptr) { return false; } + switch (t->kind) { + case Type_Basic: + if (t->Basic.kind == Basic_typeid) { + return true; + } return (t->Basic.flags & BasicFlag_ConstantType) != 0; - } - if (t->kind == Type_BitSet) { + case Type_BitSet: return true; - } - if (t->kind == Type_Proc) { + case Type_Proc: return true; + case Type_Array: + return is_type_constant_type(t->Array.elem); + case Type_EnumeratedArray: + return is_type_constant_type(t->EnumeratedArray.elem); } return false; } gb_internal bool is_type_float(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Float) != 0; } @@ -1353,6 +1484,7 @@ gb_internal bool is_type_float(Type *t) { } gb_internal bool is_type_complex(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Complex) != 0; } @@ -1360,6 +1492,7 @@ gb_internal bool is_type_complex(Type *t) { } gb_internal bool is_type_quaternion(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Quaternion) != 0; } @@ -1367,6 +1500,7 @@ gb_internal bool is_type_quaternion(Type *t) { } gb_internal bool is_type_complex_or_quaternion(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & (BasicFlag_Complex|BasicFlag_Quaternion)) != 0; } @@ -1374,6 +1508,7 @@ gb_internal bool is_type_complex_or_quaternion(Type *t) { } gb_internal bool is_type_pointer(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Pointer) != 0; } @@ -1381,10 +1516,12 @@ gb_internal bool is_type_pointer(Type *t) { } gb_internal bool is_type_soa_pointer(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_SoaPointer; } gb_internal bool is_type_multi_pointer(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_MultiPointer; } gb_internal bool is_type_internally_pointer_like(Type *t) { @@ -1393,36 +1530,50 @@ gb_internal bool is_type_internally_pointer_like(Type *t) { gb_internal bool is_type_tuple(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Tuple; } gb_internal bool is_type_uintptr(Type *t) { + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.kind == Basic_uintptr); } return false; } gb_internal bool is_type_rawptr(Type *t) { + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return t->Basic.kind == Basic_rawptr; } return false; } gb_internal bool is_type_u8(Type *t) { + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return t->Basic.kind == Basic_u8; } return false; } +gb_internal bool is_type_u16(Type *t) { + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_u16; + } + return false; +} gb_internal bool is_type_array(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Array; } gb_internal bool is_type_enumerated_array(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_EnumeratedArray; } gb_internal bool is_type_matrix(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Matrix; } @@ -1551,6 +1702,7 @@ gb_internal bool is_matrix_square(Type *t) { gb_internal bool is_type_valid_for_matrix_elems(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (is_type_integer(t)) { return true; } else if (is_type_float(t)) { @@ -1566,25 +1718,80 @@ gb_internal bool is_type_valid_for_matrix_elems(Type *t) { gb_internal bool is_type_dynamic_array(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_DynamicArray; } +gb_internal bool is_type_fixed_capacity_dynamic_array(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + return t->kind == Type_FixedCapacityDynamicArray; +} gb_internal bool is_type_slice(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Slice; } gb_internal bool is_type_proc(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Proc; } gb_internal bool is_type_asm_proc(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Proc && t->Proc.calling_convention == ProcCC_InlineAsm; } gb_internal bool is_type_simd_vector(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_SimdVector; } + +gb_internal Type *type_unsigned_equivalent(Type *t) { + Type *original_type = t; + t = base_type(t); + if (is_type_simd_vector(t)) { + if (is_type_unsigned(t->SimdVector.elem)) { + return original_type; + } + return alloc_type_simd_vector(t->SimdVector.count, type_unsigned_equivalent(t->SimdVector.elem)); + } + + i64 sz = type_size_of(t); + switch (sz) { + case 1: return t_u8; + case 2: return t_u16; + case 4: return t_u32; + case 8: return t_u64; + case 16: return t_u128; + } + GB_PANIC("No known equivalent unsigned integer sized for %s", type_to_string(t)); + return nullptr; +} + +gb_internal Type *type_signed_equivalent(Type *t) { + Type *original_type = t; + t = base_type(t); + if (is_type_simd_vector(t)) { + if (!is_type_unsigned(t->SimdVector.elem)) { + return original_type; + } + return alloc_type_simd_vector(t->SimdVector.count, type_signed_equivalent(t->SimdVector.elem)); + } + ; + i64 sz = type_size_of(t); + switch (sz) { + case 1: return t_i8; + case 2: return t_i16; + case 4: return t_i32; + case 8: return t_i64; + case 16: return t_i128; + } + GB_PANIC("No known equivalent signed integer sized for %s", type_to_string(t)); + return nullptr; +} + gb_internal Type *base_array_type(Type *t) { Type *bt = base_type(t); if (is_type_array(bt)) { @@ -1593,6 +1800,8 @@ gb_internal Type *base_array_type(Type *t) { return bt->EnumeratedArray.elem; } else if (is_type_simd_vector(bt)) { return bt->SimdVector.elem; + } else if (is_type_fixed_capacity_dynamic_array(bt)) { + return bt->FixedCapacityDynamicArray.elem; } else if (is_type_matrix(bt)) { return bt->Matrix.elem; } @@ -1608,6 +1817,8 @@ gb_internal Type *base_any_array_type(Type *t) { return bt->Slice.elem; } else if (is_type_dynamic_array(bt)) { return bt->DynamicArray.elem; + } else if (is_type_fixed_capacity_dynamic_array(bt)) { + return bt->FixedCapacityDynamicArray.elem; } else if (is_type_enumerated_array(bt)) { return bt->EnumeratedArray.elem; } else if (is_type_simd_vector(bt)) { @@ -1621,11 +1832,13 @@ gb_internal Type *base_any_array_type(Type *t) { gb_internal bool is_type_generic(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Generic; } gb_internal bool is_type_u8_slice(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Slice) { return is_type_u8(t->Slice.elem); } @@ -1633,6 +1846,7 @@ gb_internal bool is_type_u8_slice(Type *t) { } gb_internal bool is_type_u8_array(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Array) { return is_type_u8(t->Array.elem); } @@ -1640,13 +1854,15 @@ gb_internal bool is_type_u8_array(Type *t) { } gb_internal bool is_type_u8_ptr(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Pointer) { - return is_type_u8(t->Slice.elem); + return is_type_u8(t->Pointer.elem); } return false; } gb_internal bool is_type_u8_multi_ptr(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_MultiPointer) { return is_type_u8(t->Slice.elem); } @@ -1654,12 +1870,46 @@ gb_internal bool is_type_u8_multi_ptr(Type *t) { } gb_internal bool is_type_rune_array(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Array) { return is_type_rune(t->Array.elem); } return false; } +gb_internal bool is_type_u16_slice(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Slice) { + return is_type_u16(t->Slice.elem); + } + return false; +} +gb_internal bool is_type_u16_array(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Array) { + return is_type_u16(t->Array.elem); + } + return false; +} +gb_internal bool is_type_u16_ptr(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Pointer) { + return is_type_u16(t->Pointer.elem); + } + return false; +} +gb_internal bool is_type_u16_multi_ptr(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_MultiPointer) { + return is_type_u16(t->Slice.elem); + } + return false; +} + gb_internal bool is_type_array_like(Type *t) { return is_type_array(t) || is_type_enumerated_array(t); @@ -1734,44 +1984,49 @@ gb_internal Type *base_complex_elem_type(Type *t) { gb_internal bool is_type_struct(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Struct; } gb_internal bool is_type_union(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Union; } gb_internal bool is_type_soa_struct(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None; } gb_internal bool is_type_raw_union(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_Struct && t->Struct.is_raw_union); } -gb_internal bool is_type_no_copy(Type *t) { - t = base_type(t); - return (t->kind == Type_Struct && t->Struct.is_no_copy); -} gb_internal bool is_type_enum(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_Enum); } gb_internal bool is_type_bit_set(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_BitSet); } gb_internal bool is_type_bit_field(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_BitField); } gb_internal bool is_type_map(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return t->kind == Type_Map; } gb_internal bool is_type_union_maybe_pointer(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Union && t->Union.variants.count == 1) { Type *v = t->Union.variants[0]; return is_type_internally_pointer_like(v); @@ -1782,6 +2037,7 @@ gb_internal bool is_type_union_maybe_pointer(Type *t) { gb_internal bool is_type_union_maybe_pointer_original_alignment(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Union && t->Union.variants.count == 1) { Type *v = t->Union.variants[0]; if (is_type_internally_pointer_like(v)) { @@ -1816,6 +2072,7 @@ gb_internal TypeEndianKind type_endian_kind_of(Type *t) { gb_internal bool is_type_endian_big(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { if (t->Basic.flags & BasicFlag_EndianBig) { return true; @@ -1832,6 +2089,7 @@ gb_internal bool is_type_endian_big(Type *t) { } gb_internal bool is_type_endian_little(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { if (t->Basic.flags & BasicFlag_EndianLittle) { return true; @@ -1849,6 +2107,7 @@ gb_internal bool is_type_endian_little(Type *t) { gb_internal bool is_type_endian_platform(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_Basic) { return (t->Basic.flags & (BasicFlag_EndianLittle|BasicFlag_EndianBig)) == 0; } else if (t->kind == Type_BitSet) { @@ -1864,6 +2123,7 @@ gb_internal bool types_have_same_internal_endian(Type *a, Type *b) { } gb_internal bool is_type_endian_specific(Type *t) { t = core_type(t); + if (t == nullptr) { return false; } if (t->kind == Type_BitSet) { t = bit_set_to_int(t); } @@ -1961,25 +2221,35 @@ gb_internal Type *integer_endian_type_to_platform_type(Type *t) { gb_internal bool is_type_any(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_Basic && t->Basic.kind == Basic_any); } gb_internal bool is_type_typeid(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } return (t->kind == Type_Basic && t->Basic.kind == Basic_typeid); } gb_internal bool is_type_untyped_nil(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } // NOTE(bill): checking for `nil` or `---` at once is just to improve the error handling return (t->kind == Type_Basic && (t->Basic.kind == Basic_UntypedNil || t->Basic.kind == Basic_UntypedUninit)); } gb_internal bool is_type_untyped_uninit(Type *t) { t = base_type(t); + if (t == nullptr) { return false; } // NOTE(bill): checking for `nil` or `---` at once is just to improve the error handling return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedUninit); } gb_internal bool is_type_empty_union(Type *t) { + if (t == nullptr) { + return false; + } t = base_type(t); + if (t == nullptr) { + return false; + } return t->kind == Type_Union && t->Union.variants.count == 0; } @@ -2077,10 +2347,11 @@ gb_internal bool is_type_indexable(Type *t) { Type *bt = base_type(t); switch (bt->kind) { case Type_Basic: - return bt->Basic.kind == Basic_string; + return bt->Basic.kind == Basic_string || bt->Basic.kind == Basic_string16; case Type_Array: case Type_Slice: case Type_DynamicArray: + case Type_FixedCapacityDynamicArray: case Type_Map: return true; case Type_MultiPointer: @@ -2097,10 +2368,11 @@ gb_internal bool is_type_sliceable(Type *t) { Type *bt = base_type(t); switch (bt->kind) { case Type_Basic: - return bt->Basic.kind == Basic_string; + return bt->Basic.kind == Basic_string || bt->Basic.kind == Basic_string16; case Type_Array: case Type_Slice: case Type_DynamicArray: + case Type_FixedCapacityDynamicArray: return true; case Type_EnumeratedArray: return false; @@ -2241,6 +2513,11 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) { return is_type_polymorphic(t->SimdVector.elem, or_specialized); case Type_DynamicArray: return is_type_polymorphic(t->DynamicArray.elem, or_specialized); + case Type_FixedCapacityDynamicArray: + if (t->FixedCapacityDynamicArray.generic_capacity != nullptr) { + return true; + } + return is_type_polymorphic(t->FixedCapacityDynamicArray.elem, or_specialized); case Type_Slice: return is_type_polymorphic(t->Slice.elem, or_specialized); @@ -2344,6 +2621,7 @@ gb_internal bool type_has_nil(Type *t) { case Basic_any: return true; case Basic_cstring: + case Basic_cstring16: return true; case Basic_typeid: return true; @@ -2361,6 +2639,11 @@ gb_internal bool type_has_nil(Type *t) { case Type_DynamicArray: case Type_Map: return true; + + case Type_FixedCapacityDynamicArray: + // it's like a normal array, so no, similar to `#soa[N]T + return false; + case Type_Union: return t->Union.kind != UnionType_no_nil; case Type_Struct: @@ -2376,18 +2659,102 @@ gb_internal bool type_has_nil(Type *t) { return false; } +gb_internal bool is_type_union_constantable(Type *type); + +gb_internal bool is_type_constant_type_for_unions(Type *t) { + t = core_type(t); + if (t == nullptr) { return false; } + switch (t->kind) { + case Type_Basic: + if (t->Basic.kind == Basic_typeid) { + return true; + } + return (t->Basic.flags & BasicFlag_ConstantType) != 0; + case Type_BitSet: + return true; + case Type_Proc: + return true; + case Type_Array: + return is_type_constant_type(t->Array.elem); + case Type_EnumeratedArray: + return is_type_constant_type(t->EnumeratedArray.elem); + case Type_Struct: + { + for (Entity *field : t->Struct.fields) { + if (!is_type_constant_type_for_unions(field->type)) { + return false; + } + } + return true; + } + case Type_Union: + return is_type_union_constantable(t); + } + return false; +} + +gb_internal bool is_type_union_constantable(Type *type) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Union); + + if (bt->Union.variants.count == 0) { + return true; + } + + for (Type *v : bt->Union.variants) { + if (!is_type_constant_type_for_unions(v)) { + return false; + } + } + return true; +} + +gb_internal bool is_type_raw_union_constantable(Type *type) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Struct); + GB_ASSERT(bt->Struct.is_raw_union); + + for (Entity *f : bt->Struct.fields) { + if (!is_type_constant_type_for_unions(f->type)) { + return false; + } + } + // return true; + return false; // Disable raw union constants for the time being +} + gb_internal bool elem_type_can_be_constant(Type *t) { t = base_type(t); if (t == t_invalid) { return false; } - if (is_type_any(t) || is_type_union(t) || is_type_raw_union(t)) { + if (is_type_any(t)) { return false; } + if (is_type_raw_union(t)) { + return is_type_raw_union_constantable(t); + } + if (is_type_union(t)) { + return is_type_union_constantable(t); + } return true; } +gb_internal bool elem_cannot_be_constant(Type *t) { + if (is_type_any(t)) { + return true; + } + if (is_type_union(t)) { + return !is_type_union_constantable(t); + } + if (is_type_raw_union(t)) { + return !is_type_raw_union_constantable(t); + } + return false; +} + + gb_internal bool is_type_lock_free(Type *t) { t = core_type(t); if (t == t_invalid) { @@ -2411,8 +2778,9 @@ gb_internal bool is_type_comparable(Type *t) { case Basic_rune: return true; case Basic_string: - return true; case Basic_cstring: + case Basic_string16: + case Basic_cstring16: return true; case Basic_typeid: return true; @@ -2435,6 +2803,9 @@ gb_internal bool is_type_comparable(Type *t) { case Type_Matrix: return is_type_comparable(t->Matrix.elem); + case Type_FixedCapacityDynamicArray: + return false; + case Type_BitSet: return true; @@ -2481,6 +2852,10 @@ gb_internal bool is_type_simple_compare(Type *t) { case Type_EnumeratedArray: return is_type_simple_compare(t->EnumeratedArray.elem); + case Type_FixedCapacityDynamicArray: + return false; + // return is_type_simple_compare(t->FixedCapacityDynamicArray.elem); + case Type_Basic: if (t->Basic.flags & BasicFlag_SimpleCompare) { return true; @@ -2495,12 +2870,16 @@ gb_internal bool is_type_simple_compare(Type *t) { case Type_SoaPointer: case Type_Proc: case Type_BitSet: + case Type_BitField: return true; case Type_Matrix: return is_type_simple_compare(t->Matrix.elem); case Type_Struct: + if (t->Struct.is_simple) { + return true; + } for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields[i]; if (!is_type_simple_compare(f->type)) { @@ -2522,6 +2901,91 @@ gb_internal bool is_type_simple_compare(Type *t) { case Type_SimdVector: return is_type_simple_compare(t->SimdVector.elem); + case Type_Tuple: + if (t->Tuple.variables.count == 1) { + return is_type_simple_compare(t->Tuple.variables[0]->type); + } + break; + + case Type_Slice: + case Type_DynamicArray: + case Type_Map: + return false; + } + + return false; +} + +// NOTE(bill): type can be easily compared using memcmp or contains a float +gb_internal bool is_type_nearly_simple_compare(Type *t) { + t = core_type(t); + switch (t->kind) { + case Type_Array: + return is_type_nearly_simple_compare(t->Array.elem); + + case Type_EnumeratedArray: + return is_type_nearly_simple_compare(t->EnumeratedArray.elem); + + case Type_FixedCapacityDynamicArray: + return false; + // return is_type_nearly_simple_compare(t->FixedCapacityDynamicArray.elem); + + case Type_Basic: + if (t->Basic.flags & (BasicFlag_SimpleCompare|BasicFlag_Numeric)) { + return true; + } + if (t->Basic.kind == Basic_typeid) { + return true; + } + return false; + + case Type_Pointer: + case Type_MultiPointer: + case Type_SoaPointer: + case Type_Proc: + case Type_BitSet: + case Type_BitField: + return true; + + case Type_Matrix: + return is_type_nearly_simple_compare(t->Matrix.elem); + + case Type_Struct: + if (t->Struct.is_simple) { + return true; + } + for_array(i, t->Struct.fields) { + Entity *f = t->Struct.fields[i]; + if (!is_type_nearly_simple_compare(f->type)) { + return false; + } + } + return true; + + case Type_Union: + for_array(i, t->Union.variants) { + Type *v = t->Union.variants[i]; + if (!is_type_nearly_simple_compare(v)) { + return false; + } + } + // make it dumb on purpose + return t->Union.variants.count == 1; + + case Type_SimdVector: + return is_type_nearly_simple_compare(t->SimdVector.elem); + + case Type_Tuple: + if (t->Tuple.variables.count == 1) { + return is_type_nearly_simple_compare(t->Tuple.variables[0]->type); + } + break; + + case Type_Slice: + case Type_DynamicArray: + case Type_Map: + return false; + } return false; @@ -2546,6 +3010,7 @@ gb_internal bool is_type_load_safe(Type *type) { case Type_DynamicArray: case Type_Proc: case Type_SoaPointer: + case Type_FixedCapacityDynamicArray: return false; case Type_Enum: @@ -2630,7 +3095,7 @@ gb_internal bool lookup_subtype_polymorphic_selection(Type *dst, Type *src, Sele return true; } } - if ((f->flags & EntityFlag_Using) != 0 && is_type_struct(f->type)) { + if ((f->flags & EntityFlags_IsSubtype) != 0 && is_type_struct(f->type)) { String name = lookup_subtype_polymorphic_field(dst, f->type); if (name.len > 0) { array_add(&sel->index, cast(i32)i); @@ -2668,10 +3133,11 @@ gb_internal bool are_types_identical(Type *x, Type *y) { y = y->Named.base; } } - if (x->kind != y->kind) { + if (x == nullptr || y == nullptr || x->kind != y->kind) { return false; } + // MUTEX_GUARD(&g_type_mutex); return are_types_identical_internal(x, y, false); } gb_internal bool are_types_identical_unique_tuples(Type *x, Type *y) { @@ -2699,9 +3165,21 @@ gb_internal bool are_types_identical_unique_tuples(Type *x, Type *y) { return false; } + // if (x->canonical_hash && y->canonical_hash && x->canonical_hash != y->canonical_hash) { + // return false; + // } + + // MUTEX_GUARD(&g_type_mutex); return are_types_identical_internal(x, y, true); } +gb_internal bool are_proc_properties_identical(Type *x, Type *y) { + return x->Proc.calling_convention == y->Proc.calling_convention && + x->Proc.c_vararg == y->Proc.c_vararg && + x->Proc.variadic == y->Proc.variadic && + x->Proc.diverging == y->Proc.diverging && + x->Proc.optional_ok == y->Proc.optional_ok; +} gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple_names) { if (x == y) { @@ -2712,6 +3190,10 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple return false; } + // if (x->canonical_hash && y->canonical_hash && x->canonical_hash != y->canonical_hash) { + // return false; + // } + #if 0 if (x->kind == Type_Named) { Entity *e = x->Named.type_name; @@ -2753,6 +3235,10 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple case Type_DynamicArray: return are_types_identical(x->DynamicArray.elem, y->DynamicArray.elem); + case Type_FixedCapacityDynamicArray: + return (x->FixedCapacityDynamicArray.capacity == y->FixedCapacityDynamicArray.capacity) && + are_types_identical(x->FixedCapacityDynamicArray.elem, y->FixedCapacityDynamicArray.elem); + case Type_Slice: return are_types_identical(x->Slice.elem, y->Slice.elem); @@ -2821,10 +3307,10 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple break; case Type_Struct: - if (x->Struct.is_raw_union == y->Struct.is_raw_union && - x->Struct.is_no_copy == y->Struct.is_no_copy && - x->Struct.fields.count == y->Struct.fields.count && - x->Struct.is_packed == y->Struct.is_packed && + if (x->Struct.is_raw_union == y->Struct.is_raw_union && + x->Struct.fields.count == y->Struct.fields.count && + x->Struct.is_packed == y->Struct.is_packed && + x->Struct.is_all_or_none == y->Struct.is_all_or_none && x->Struct.soa_kind == y->Struct.soa_kind && x->Struct.soa_count == y->Struct.soa_count && are_types_identical(x->Struct.soa_elem, y->Struct.soa_elem)) { @@ -2898,11 +3384,7 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple break; case Type_Proc: - return x->Proc.calling_convention == y->Proc.calling_convention && - x->Proc.c_vararg == y->Proc.c_vararg && - x->Proc.variadic == y->Proc.variadic && - x->Proc.diverging == y->Proc.diverging && - x->Proc.optional_ok == y->Proc.optional_ok && + return are_proc_properties_identical(x, y) && are_types_identical_internal(x->Proc.params, y->Proc.params, check_tuple_names) && are_types_identical_internal(x->Proc.results, y->Proc.results, check_tuple_names); @@ -2957,6 +3439,10 @@ gb_internal Type *default_type(Type *type) { case Basic_UntypedString: return t_string; case Basic_UntypedRune: return t_rune; } + } else if (type->kind == Type_Generic) { + if (type->Generic.specialized) { + return default_type(type->Generic.specialized); + } } return type; } @@ -3014,7 +3500,7 @@ gb_internal bool union_variant_index_types_equal(Type *v, Type *vt) { return false; } -gb_internal i64 union_variant_index(Type *u, Type *v) { +gb_internal i64 union_variant_index_checked(Type *u, Type *v) { u = base_type(u); GB_ASSERT(u->kind == Type_Union); @@ -3028,9 +3514,24 @@ gb_internal i64 union_variant_index(Type *u, Type *v) { } } } - return 0; + GB_PANIC("unfound variant -> %s %s", type_to_string(u), type_to_string(v)); + return -1; } +gb_internal bool union_is_variant_of(Type *u, Type *v) { + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + for_array(i, u->Union.variants) { + Type *vt = u->Union.variants[i]; + if (union_variant_index_types_equal(v, vt)) { + return true; + } + } + return false; +} + + gb_internal i64 union_tag_size(Type *u) { u = base_type(u); GB_ASSERT(u->kind == Type_Union); @@ -3055,11 +3556,15 @@ gb_internal i64 union_tag_size(Type *u) { compiler_error("how many variants do you have?! %lld", cast(long long)u->Union.variants.count); } - for_array(i, u->Union.variants) { - Type *variant_type = u->Union.variants[i]; - i64 align = type_align_of(variant_type); - if (max_align < align) { - max_align = align; + if (u->Union.custom_align > 0) { + max_align = gb_max(max_align, u->Union.custom_align); + } else { + for_array(i, u->Union.variants) { + Type *variant_type = u->Union.variants[i]; + i64 align = type_align_of(variant_type); + if (max_align < align) { + max_align = align; + } } } @@ -3184,9 +3689,9 @@ gb_internal ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) -gb_internal Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident=false); +gb_internal Selection lookup_field_with_selection(Type *type_, InternedString field_name, bool is_type, Selection sel, bool allow_blank_ident=false); -gb_internal Selection lookup_field(Type *type_, String field_name, bool is_type, bool allow_blank_ident=false) { +gb_internal Selection lookup_field(Type *type_, InternedString field_name, bool is_type, bool allow_blank_ident=false) { return lookup_field_with_selection(type_, field_name, is_type, empty_selection, allow_blank_ident); } @@ -3239,13 +3744,13 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) { return empty_selection; } -gb_internal Entity *scope_lookup_current(Scope *s, String const &name); +gb_internal Entity *scope_lookup_current(Scope *s, InternedString name, u32 hash=0); gb_internal bool has_type_got_objc_class_attribute(Type *t); -gb_internal Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) { +gb_internal Selection lookup_field_with_selection(Type *type_, InternedString field_name, bool is_type, Selection sel, bool allow_blank_ident) { GB_ASSERT(type_ != nullptr); - if (!allow_blank_ident && is_blank_ident(field_name)) { + if (!allow_blank_ident && field_name.is_blank()) { return empty_selection; } @@ -3267,7 +3772,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name defer (mutex_unlock(md->mutex)); for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup); - if (entry.name == field_name) { + if (entry.interned == field_name) { sel.entity = entry.entity; sel.pseudo_field = true; return sel; @@ -3294,7 +3799,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name for_array(i, type->Enum.fields) { Entity *f = type->Enum.fields[i]; GB_ASSERT(f->kind == Entity_Constant); - String str = f->token.string; + auto str = entity_interned_name(f); if (field_name == str) { sel.entity = f; @@ -3325,8 +3830,22 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name } } else if (type->kind == Type_BitSet) { return lookup_field_with_selection(type->BitSet.elem, field_name, true, sel, allow_blank_ident); - } + } else if (type->kind == Type_BitField) { + for_array(i, type->BitField.fields) { + Entity *f = type->BitField.fields[i]; + if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { + continue; + } + auto str = entity_interned_name(f); + if (field_name == str) { + selection_add_index(&sel, i); // HACK(bill): Leaky memory + sel.entity = f; + sel.is_bit_field = true; + return sel; + } + } + } if (type->kind == Type_Generic && type->Generic.specialized != nullptr) { Type *specialized = type->Generic.specialized; @@ -3345,7 +3864,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name defer (mutex_unlock(md->mutex)); for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup); - if (entry.name == field_name) { + if (entry.interned == field_name) { sel.entity = entry.entity; sel.pseudo_field = true; return sel; @@ -3374,7 +3893,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { continue; } - String str = f->token.string; + auto str = entity_interned_name(f); if (field_name == str) { selection_add_index(&sel, i); // HACK(bill): Leaky memory sel.entity = f; @@ -3403,11 +3922,12 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name bool is_soa_of_array = is_soa && is_type_array(type->Struct.soa_elem); if (is_soa_of_array) { - String mapped_field_name = {}; - if (field_name == "r") mapped_field_name = str_lit("x"); - else if (field_name == "g") mapped_field_name = str_lit("y"); - else if (field_name == "b") mapped_field_name = str_lit("z"); - else if (field_name == "a") mapped_field_name = str_lit("w"); + InternedString mapped_field_name = {}; + String n = field_name.string(); + if (n == "r") mapped_field_name = string_interner_insert(str_lit("x")); + else if (n == "g") mapped_field_name = string_interner_insert(str_lit("y")); + else if (n == "b") mapped_field_name = string_interner_insert(str_lit("z")); + else if (n == "a") mapped_field_name = string_interner_insert(str_lit("w")); return lookup_field_with_selection(type, mapped_field_name, is_type, sel, allow_blank_ident); } } else if (type->kind == Type_BitField) { @@ -3416,7 +3936,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { continue; } - String str = f->token.string; + auto str = entity_interned_name(f); if (field_name == str) { selection_add_index(&sel, i); // HACK(bill): Leaky memory sel.entity = f; @@ -3424,7 +3944,6 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name return sel; } } - } else if (type->kind == Type_Basic) { switch (type->Basic.kind) { case Basic_any: { @@ -3434,11 +3953,12 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name gb_local_persist Entity *entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0); gb_local_persist Entity *entity__any_id = alloc_entity_field(nullptr, make_token_ident(id_str), t_typeid, false, 1); - if (field_name == data_str) { + String n = field_name.string(); + if (n == data_str) { selection_add_index(&sel, 0); sel.entity = entity__any_data; return sel; - } else if (field_name == id_str) { + } else if (n == id_str) { selection_add_index(&sel, 1); sel.entity = entity__any_id; return sel; @@ -3456,19 +3976,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f16, false, 0); gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f16, false, 1); gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f16, false, 2); - if (field_name == w) { + + String n = field_name.string(); + if (n == w) { selection_add_index(&sel, 3); sel.entity = entity__w; return sel; - } else if (field_name == x) { + } else if (n == x) { selection_add_index(&sel, 0); sel.entity = entity__x; return sel; - } else if (field_name == y) { + } else if (n == y) { selection_add_index(&sel, 1); sel.entity = entity__y; return sel; - } else if (field_name == z) { + } else if (n == z) { selection_add_index(&sel, 2); sel.entity = entity__z; return sel; @@ -3485,19 +4007,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f32, false, 0); gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f32, false, 1); gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f32, false, 2); - if (field_name == w) { + + String n = field_name.string(); + if (n == w) { selection_add_index(&sel, 3); sel.entity = entity__w; return sel; - } else if (field_name == x) { + } else if (n == x) { selection_add_index(&sel, 0); sel.entity = entity__x; return sel; - } else if (field_name == y) { + } else if (n == y) { selection_add_index(&sel, 1); sel.entity = entity__y; return sel; - } else if (field_name == z) { + } else if (n == z) { selection_add_index(&sel, 2); sel.entity = entity__z; return sel; @@ -3514,19 +4038,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f64, false, 0); gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f64, false, 1); gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f64, false, 2); - if (field_name == w) { + + String n = field_name.string(); + if (n == w) { selection_add_index(&sel, 3); sel.entity = entity__w; return sel; - } else if (field_name == x) { + } else if (n == x) { selection_add_index(&sel, 0); sel.entity = entity__x; return sel; - } else if (field_name == y) { + } else if (n == y) { selection_add_index(&sel, 1); sel.entity = entity__y; return sel; - } else if (field_name == z) { + } else if (n == z) { selection_add_index(&sel, 2); sel.entity = entity__z; return sel; @@ -3543,19 +4069,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_untyped_float, false, 0); gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_untyped_float, false, 1); gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_untyped_float, false, 2); - if (field_name == w) { + + String n = field_name.string(); + if (n == w) { selection_add_index(&sel, 3); sel.entity = entity__w; return sel; - } else if (field_name == x) { + } else if (n == x) { selection_add_index(&sel, 0); sel.entity = entity__x; return sel; - } else if (field_name == y) { + } else if (n == y) { selection_add_index(&sel, 1); sel.entity = entity__y; return sel; - } else if (field_name == z) { + } else if (n == z) { selection_add_index(&sel, 2); sel.entity = entity__z; return sel; @@ -3570,7 +4098,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name String allocator_str = str_lit("allocator"); gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3); - if (field_name == allocator_str) { + String n = field_name.string(); + if (n == allocator_str) { selection_add_index(&sel, 3); sel.entity = entity__allocator; return sel; @@ -3580,7 +4109,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name String allocator_str = str_lit("allocator"); gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 2); - if (field_name == allocator_str) { + String n = field_name.string(); + if (n == allocator_str) { selection_add_index(&sel, 2); sel.entity = entity__allocator; return sel; @@ -3588,7 +4118,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name #define _ARRAY_FIELD_CASE_IF(_length, _name) \ - if (field_name == (_name)) { \ + if (n == (_name)) { \ selection_add_index(&sel, (_length)-1); \ sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), elem, (_length)-1); \ return sel; \ @@ -3601,7 +4131,7 @@ case (_length): \ } else if (type->kind == Type_Array) { - + String n = field_name.string(); Type *elem = type->Array.elem; if (type->Array.count <= 4) { @@ -3616,8 +4146,9 @@ case (_length): \ } } } else if (type->kind == Type_SimdVector) { - + String n = field_name.string(); Type *elem = type->SimdVector.elem; + if (type->SimdVector.count <= 4) { // HACK(bill): Memory leak switch (type->SimdVector.count) { @@ -3735,10 +4266,12 @@ gb_internal i64 type_size_of(Type *t) { if (t->kind == Type_Basic) { GB_ASSERT_MSG(is_type_typed(t), "%s", type_to_string(t)); switch (t->Basic.kind) { - case Basic_string: size = 2*build_context.int_size; break; - case Basic_cstring: size = build_context.ptr_size; break; - case Basic_any: size = 16; break; - case Basic_typeid: size = 8; break; + case Basic_string: size = 2*build_context.int_size; break; + case Basic_cstring: size = build_context.ptr_size; break; + case Basic_string16: size = 2*build_context.int_size; break; + case Basic_cstring16: size = build_context.ptr_size; break; + case Basic_any: size = 16; break; + case Basic_typeid: size = 8; break; case Basic_int: case Basic_uint: size = build_context.int_size; @@ -3758,7 +4291,7 @@ gb_internal i64 type_size_of(Type *t) { TypePath path{}; type_path_init(&path); { - MUTEX_GUARD(&g_type_mutex); + // MUTEX_GUARD(&g_type_mutex); size = type_size_of_internal(t, &path); t->cached_size.store(size); } @@ -3778,7 +4311,7 @@ gb_internal i64 type_align_of(Type *t) { TypePath path{}; type_path_init(&path); { - MUTEX_GUARD(&g_type_mutex); + // MUTEX_GUARD(&g_type_mutex); t->cached_align.store(type_align_of_internal(t, &path)); } type_path_free(&path); @@ -3798,10 +4331,12 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { case Type_Basic: { GB_ASSERT(is_type_typed(t)); switch (t->Basic.kind) { - case Basic_string: return build_context.int_size; - case Basic_cstring: return build_context.ptr_size; - case Basic_any: return 8; - case Basic_typeid: return 8; + case Basic_string: return build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_string16: return build_context.int_size; + case Basic_cstring16: return build_context.ptr_size; + case Basic_any: return 8; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -3838,9 +4373,22 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { } case Type_DynamicArray: - // data, count, capacity, allocator + // data, len, cap, allocator return build_context.int_size; + case Type_FixedCapacityDynamicArray: + // data, len + { + Type *elem = t->FixedCapacityDynamicArray.elem; + bool pop = type_path_push(path, elem); + if (path->failure) { + return FAILURE_ALIGNMENT; + } + i64 align = type_align_of_internal(elem, path); + if (pop) type_path_pop(path); + return gb_max(build_context.int_size, align); + } + case Type_Slice: return build_context.int_size; @@ -3895,8 +4443,9 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { if (t->Struct.is_packed) { return 1; } - - type_set_offsets(t); + // Avoid forcing offset computation here. The caller's type-path state must + // be able to detect recursive field cycles before any nested struct tries to + // re-enter this struct's offset mutex. i64 max = 1; for_array(i, t->Struct.fields) { @@ -4002,23 +4551,26 @@ gb_internal i64 *type_set_offsets_of(Slice const &fields, bool is_pack gb_internal bool type_set_offsets(Type *t) { t = base_type(t); if (t->kind == Type_Struct) { + // if (t->Struct.are_offsets_being_processed.load()) { + // return true; + // } MUTEX_GUARD(&t->Struct.offset_mutex); if (!t->Struct.are_offsets_set) { - t->Struct.are_offsets_being_processed = true; + t->Struct.are_offsets_being_processed.store(true); t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union, t->Struct.custom_min_field_align, t->Struct.custom_max_field_align); - t->Struct.are_offsets_being_processed = false; + t->Struct.are_offsets_being_processed.store(false); t->Struct.are_offsets_set = true; - return true; } + return true; } else if (is_type_tuple(t)) { MUTEX_GUARD(&t->Tuple.mutex); if (!t->Tuple.are_offsets_set) { - t->Tuple.are_offsets_being_processed = true; + t->Tuple.are_offsets_being_processed.store(true); t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false, 1, 0); - t->Tuple.are_offsets_being_processed = false; + t->Tuple.are_offsets_being_processed.store(false); t->Tuple.are_offsets_set = true; - return true; } + return true; } else { GB_PANIC("Invalid type for setting offsets"); } @@ -4049,10 +4601,12 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { return size; } switch (kind) { - case Basic_string: return 2*build_context.int_size; - case Basic_cstring: return build_context.ptr_size; - case Basic_any: return 16; - case Basic_typeid: return 8; + case Basic_string: return 2*build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_string16: return 2*build_context.int_size; + case Basic_cstring16: return build_context.ptr_size; + case Basic_any: return 16; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -4107,6 +4661,31 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { // data + len + cap + allocator(procedure+data) return 3*build_context.int_size + 2*build_context.ptr_size; + case Type_FixedCapacityDynamicArray: + { + // data + len + i64 capacity = t->FixedCapacityDynamicArray.capacity; + Type *elem = t->FixedCapacityDynamicArray.elem; + i64 align = type_align_of_internal(elem, path); + if (path->failure) { + return FAILURE_SIZE; + } + align = gb_max(build_context.int_size, align); + + i64 size = type_size_of(elem); + size *= capacity; + + i64 old_size = size; + size = align_formula(size, build_context.int_size); + + i64 padding = size - old_size; + t->FixedCapacityDynamicArray.padding_needed = padding; + + size += 1*build_context.int_size; + size = align_formula(size, align); + return size; + } + case Type_Map: /* struct { @@ -4198,9 +4777,12 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { if (path->failure) { return FAILURE_SIZE; } - if (t->Struct.are_offsets_being_processed && t->Struct.offsets == nullptr) { - type_path_print_illegal_cycle(path, path->path.count-1); - return FAILURE_SIZE; + { + MUTEX_GUARD(&t->Struct.offset_mutex); + if (t->Struct.are_offsets_being_processed.load() && t->Struct.offsets == nullptr) { + type_path_print_illegal_cycle(path, path->path.count-1); + return FAILURE_SIZE; + } } type_set_offsets(t); GB_ASSERT(t->Struct.fields.count == 0 || t->Struct.offsets != nullptr); @@ -4281,6 +4863,15 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { if (field_type_) *field_type_ = t_int; return build_context.int_size; // len } + } else if (t->Basic.kind == Basic_string16) { + switch (index) { + case 0: + if (field_type_) *field_type_ = t_u16_ptr; + return 0; // data + case 1: + if (field_type_) *field_type_ = t_int; + return build_context.int_size; // len + } } else if (t->Basic.kind == Basic_any) { switch (index) { case 0: @@ -4289,6 +4880,8 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { case 1: if (field_type_) *field_type_ = t_typeid; return 8; // id + default: + GB_PANIC("index > 1"); } } break; @@ -4318,6 +4911,24 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { return 3*build_context.int_size; // allocator } break; + + case Type_FixedCapacityDynamicArray: + switch (index) { + case 0: + if (field_type_) *field_type_ = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); + return 0; // data + + case 1: // len + if (field_type_) *field_type_ = t_int; + { + i64 elem_size = type_size_of(t->FixedCapacityDynamicArray.elem); + i64 offset = 0; + offset = elem_size * t->FixedCapacityDynamicArray.capacity; + offset = align_formula(offset, build_context.int_size); + return offset; + } + } + break; case Type_Union: if (!is_type_union_maybe_pointer(t)) { /* i64 s = */ type_size_of(t); @@ -4357,10 +4968,16 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) { case 0: t = t_rawptr; break; case 1: t = t_int; break; } + } else if (t->Basic.kind == Basic_string16) { + switch (index) { + case 0: t = t_rawptr; break; + case 1: t = t_int; break; + } } else if (t->Basic.kind == Basic_any) { switch (index) { case 0: t = t_rawptr; break; case 1: t = t_typeid; break; + default: GB_PANIC("index > 1"); } } break; @@ -4379,6 +4996,12 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) { case 3: t = t_allocator; break; } break; + case Type_FixedCapacityDynamicArray: + switch (index) { + case 0: t = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break; + case 1: t = t_int; break; + } + break; } } } @@ -4421,15 +5044,53 @@ gb_internal isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isi return level+1; } } - isize nested_level = check_is_assignable_to_using_subtype(f->type, dst, level+1, src_is_ptr, allow_polymorphic); - if (nested_level > 0) { - return nested_level; + if (f->flags & EntityFlags_IsSubtype) { + isize nested_level = check_is_assignable_to_using_subtype(f->type, dst, level+1, src_is_ptr, allow_polymorphic); + if (nested_level > 0) { + return nested_level; + } } } return 0; } +gb_internal bool check_is_assignable_to_using_offset_zero_subtype(Type *src, Type *dst) { + + Type *src_struct = base_type(src); + if (!is_type_struct(src_struct)) { + return false; + } + + // We check multiple fields in case of #raw_union, + // but exit on the first field that is not at offset 0. + for_array(i, src_struct->Struct.fields) { + Entity *f = src_struct->Struct.fields[i]; + if (f->kind != Entity_Variable || (f->flags&EntityFlags_IsSubtype) == 0) { + continue; + } + + Type *field_type = nullptr; + i64 offset = type_offset_of(src_struct, i, &field_type); + + // Only allowed if the subtype field shared the same address as its container + if (offset != 0) { + return false; + } + + if (are_types_identical(field_type, dst)) { + return true; + } + + // Check parent if the field type is a struct + if (check_is_assignable_to_using_offset_zero_subtype(field_type, dst)) { + return true; + } + } + + return false; +} + gb_internal bool is_type_subtype_of(Type *src, Type *dst) { if (are_types_identical(src, dst)) { return true; @@ -4457,6 +5118,14 @@ gb_internal bool is_type_objc_object(Type *t) { return internal_check_is_assignable_to(t, t_objc_object); } +gb_internal bool is_type_objc_ptr_to_object(Type *t) { + // NOTE (harold): is_type_objc_object() returns true if it's a pointer to an object or the object itself. + // This returns true ONLY if Type is a shallow pointer to an Objective-C object. + + Type *elem = type_deref(t); + return elem != t && elem->kind == Type_Named && is_type_objc_object(elem); +} + gb_internal Type *get_struct_field_type(Type *t, isize index) { t = base_type(type_deref(t)); GB_ASSERT(t->kind == Type_Struct); @@ -4483,7 +5152,7 @@ gb_internal Type *alloc_type_tuple_from_field_types(Type **field_types, isize fi } Type *t = alloc_type_tuple(); - t->Tuple.variables = slice_make(heap_allocator(), field_count); + t->Tuple.variables = slice_make(permanent_allocator(), field_count); Scope *scope = nullptr; for_array(i, t->Tuple.variables) { @@ -4576,6 +5245,97 @@ gb_internal Type *alloc_type_proc_from_types(Type **param_types, unsigned param_ // return type; // } +// Index a type that is internally a struct or array. +gb_internal Type *type_internal_index(Type *t, isize index) { + Type *bt = base_type(t); + if (bt == nullptr) { + return nullptr; + } + + switch (bt->kind) { + case Type_Basic: + { + switch (bt->Basic.kind) { + case Basic_complex32: return t_f16; + case Basic_complex64: return t_f32; + case Basic_complex128: return t_f64; + case Basic_quaternion64: return t_f16; + case Basic_quaternion128: return t_f32; + case Basic_quaternion256: return t_f64; + case Basic_string: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_u8_ptr : t_int; + } + case Basic_string16: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_u16_ptr : t_int; + } + case Basic_any: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_rawptr : t_typeid; + } + } + } + break; + + case Type_Array: return bt->Array.elem; + case Type_EnumeratedArray: return bt->EnumeratedArray.elem; + case Type_SimdVector: return bt->SimdVector.elem; + case Type_Slice: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_rawptr : t_int; + } + case Type_DynamicArray: + { + switch (index) { + case 0: return t_rawptr; + case 1: return t_int; + case 2: return t_int; + case 3: return t_allocator; + default: GB_PANIC("invalid raw dynamic array index"); + }; + } + + case Type_FixedCapacityDynamicArray: + { + switch (index) { + case 0: t = alloc_type_array(t->FixedCapacityDynamicArray.elem, t->FixedCapacityDynamicArray.capacity); break; + case 1: return t_int; + default: GB_PANIC("invalid raw fixed capacity dynamic array index"); + }; + } + case Type_Struct: + return get_struct_field_type(bt, index); + case Type_Union: + if (index < bt->Union.variants.count) { + return bt->Union.variants[index]; + } + return union_tag_type(bt); + case Type_Tuple: + return bt->Tuple.variables[index]->type; + case Type_Matrix: + return bt->Matrix.elem; + case Type_SoaPointer: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_rawptr : t_int; + } + case Type_Map: + return type_internal_index(bt->Map.debug_metadata_type, index); + case Type_BitField: + return type_internal_index(bt->BitField.backing_type, index); + case Type_Generic: + return type_internal_index(bt->Generic.specialized, index); + }; + + GB_PANIC("Unhandled type %s", type_to_string(bt)); + return nullptr; +}; + gb_internal gbString write_type_to_string(gbString str, Type *type, bool shorthand=false, bool allow_polymorphic=false) { if (type == nullptr) { return gb_string_appendc(str, ""); @@ -4646,6 +5406,13 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = write_type_to_string(str, type->DynamicArray.elem, shorthand, allow_polymorphic); break; + case Type_FixedCapacityDynamicArray: + str = gb_string_appendc(str, "[dynamic; "); + str = gb_string_appendc(str, gb_bprintf("%lld", cast(long long)type->FixedCapacityDynamicArray.capacity)); + str = gb_string_appendc(str, "]"); + str = write_type_to_string(str, type->FixedCapacityDynamicArray.elem, shorthand, allow_polymorphic); + break; + case Type_Enum: str = gb_string_appendc(str, "enum"); if (type->Enum.base_type != nullptr) { @@ -4708,10 +5475,11 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_appendc(str, ")"); } - if (type->Struct.is_packed) str = gb_string_appendc(str, " #packed"); - if (type->Struct.is_raw_union) str = gb_string_appendc(str, " #raw_union"); - if (type->Struct.is_no_copy) str = gb_string_appendc(str, " #no_copy"); + if (type->Struct.is_packed) str = gb_string_appendc(str, " #packed"); + if (type->Struct.is_raw_union) str = gb_string_appendc(str, " #raw_union"); if (type->Struct.custom_align != 0) str = gb_string_append_fmt(str, " #align %d", cast(int)type->Struct.custom_align); + if (type->Struct.is_all_or_none) str = gb_string_appendc(str, " #all_or_none"); + if (type->Struct.is_simple) str = gb_string_appendc(str, " #simple"); str = gb_string_appendc(str, " {"); @@ -4820,40 +5588,12 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha case Type_Proc: str = gb_string_appendc(str, "proc"); - switch (type->Proc.calling_convention) { - case ProcCC_Odin: - if (default_calling_convention() != ProcCC_Odin) { - str = gb_string_appendc(str, " \"odin\" "); - } - break; - case ProcCC_Contextless: - if (default_calling_convention() != ProcCC_Contextless) { - str = gb_string_appendc(str, " \"contextless\" "); - } - break; - case ProcCC_CDecl: - str = gb_string_appendc(str, " \"c\" "); - break; - case ProcCC_StdCall: - str = gb_string_appendc(str, " \"std\" "); - break; - case ProcCC_FastCall: - str = gb_string_appendc(str, " \"fastcall\" "); - break; - break; - case ProcCC_None: - str = gb_string_appendc(str, " \"none\" "); - break; - case ProcCC_Naked: - str = gb_string_appendc(str, " \"naked\" "); - break; - // case ProcCC_VectorCall: - // str = gb_string_appendc(str, " \"vectorcall\" "); - // break; - // case ProcCC_ClrCall: - // str = gb_string_appendc(str, " \"clrcall\" "); - // break; + if (type->Proc.calling_convention != default_calling_convention()) { + str = gb_string_appendc(str, " \""); + str = gb_string_appendc(str, proc_calling_convention_strings[type->Proc.calling_convention]); + str = gb_string_appendc(str, "\" "); } + str = gb_string_appendc(str, "("); if (type->Proc.params) { str = write_type_to_string(str, type->Proc.params, shorthand, allow_polymorphic); diff --git a/src/ucg/ucg.c b/src/ucg/ucg.c index c3e270e1a..119f88805 100644 --- a/src/ucg/ucg.c +++ b/src/ucg/ucg.c @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: (c) 2024 Feoramund - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: zlib */ diff --git a/src/ucg/ucg_tables.h b/src/ucg/ucg_tables.h index a33f9f898..f31e51773 100644 --- a/src/ucg/ucg_tables.h +++ b/src/ucg/ucg_tables.h @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: (c) 2024 Feoramund - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: zlib */ #ifndef _UCG_TABLES_INCLUDED #define _UCG_TABLES_INCLUDED diff --git a/tests/benchmark/all.odin b/tests/benchmark/all.odin index a48872cc6..042b2fa63 100644 --- a/tests/benchmark/all.odin +++ b/tests/benchmark/all.odin @@ -3,4 +3,6 @@ package benchmarks @(require) import "bytes" @(require) import "crypto" @(require) import "hash" +@(require) import "math" @(require) import "text/regex" +@(require) import "strings" \ No newline at end of file diff --git a/tests/benchmark/bytes/benchmark_bytes.odin b/tests/benchmark/bytes/benchmark_bytes.odin index 13ef8f9a5..ee3a91d64 100644 --- a/tests/benchmark/bytes/benchmark_bytes.odin +++ b/tests/benchmark/bytes/benchmark_bytes.odin @@ -54,14 +54,15 @@ run_trial_size :: proc(p: proc "contextless" ([]u8, byte) -> int, size: int, idx accumulator: int - for _ in 0.. (bp, sc: time.Duration) { - point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" - scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - - point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) - scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) - out: [x25519.POINT_SIZE]byte = --- - - start := time.tick_now() - for _ in 0 ..< ECDH_ITERS { - x25519.scalarmult_basepoint(out[:], scalar[:]) - } - bp = time.tick_since(start) / ECDH_ITERS - - start = time.tick_now() - for _ in 0 ..< ECDH_ITERS { - x25519.scalarmult(out[:], scalar[:], point[:]) - } - sc = time.tick_since(start) / ECDH_ITERS - - return -} - -@(private = "file") -bench_x448 :: proc() -> (bp, sc: time.Duration) { - point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" - scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - - point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) - scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) - out: [x448.POINT_SIZE]byte = --- - - start := time.tick_now() - for _ in 0 ..< ECDH_ITERS { - x448.scalarmult_basepoint(out[:], scalar[:]) - } - bp = time.tick_since(start) / ECDH_ITERS - - start = time.tick_now() - for _ in 0 ..< ECDH_ITERS { - x448.scalarmult(out[:], scalar[:], point[:]) - } - sc = time.tick_since(start) / ECDH_ITERS - - return -} - -@(private = "file") +@(private="file") bench_dsa :: proc() { tbl: table.Table table.init(&tbl) @@ -123,13 +107,27 @@ bench_dsa :: proc() { append_tbl(&tbl, "ed25519", "sign", sig) append_tbl(&tbl, "ed25519", "verify", verif) + table.row(&tbl) + + sk, sig, verif = bench_ecdsa(.SECP256R1, .SHA256) + append_tbl(&tbl, "secp256r1/SHA256/RFC6979", "private_key_set_bytes", sk) + append_tbl(&tbl, "secp256r1/SHA256/RFC6979", "sign", sig) + append_tbl(&tbl, "secp256r1/SHA256/RFC6979", "verify", verif) + + table.row(&tbl) + + sk, sig, verif = bench_ecdsa(.SECP384R1, .SHA384) + append_tbl(&tbl, "secp384r1/SHA384/RFC6979", "private_key_set_bytes", sk) + append_tbl(&tbl, "secp384r1/SHA384/RFC6979", "sign", sig) + append_tbl(&tbl, "secp384r1/SHA384/RFC6979", "verify", verif) + log_table(&tbl) } @(private = "file") bench_ed25519 :: proc() -> (sk, sig, verif: time.Duration) { - priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator) + SEED : string : "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" + priv_bytes, _ := hex.decode(transmute([]byte)(SEED), context.temp_allocator) priv_key: ed25519.Private_Key start := time.tick_now() for _ in 0 ..< DSA_ITERS { @@ -138,14 +136,11 @@ bench_ed25519 :: proc() -> (sk, sig, verif: time.Duration) { } sk = time.tick_since(start) / DSA_ITERS - pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing" pub_key: ed25519.Public_Key - ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:]) - assert(ok, "public key should deserialize") + ed25519.public_key_set_priv(&pub_key, &priv_key) - msg := "Got a job for you, 621." sig_bytes: [ed25519.SIGNATURE_SIZE]byte - msg_bytes := transmute([]byte)(msg) + msg_bytes := transmute([]byte)(SIG_MSG) start = time.tick_now() for _ in 0 ..< DSA_ITERS { ed25519.sign(&priv_key, msg_bytes, sig_bytes[:]) @@ -154,7 +149,41 @@ bench_ed25519 :: proc() -> (sk, sig, verif: time.Duration) { start = time.tick_now() for _ in 0 ..< DSA_ITERS { - ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes[:]) + ok := ed25519.verify(&pub_key, msg_bytes, sig_bytes[:]) + assert(ok, "signature should validate") + } + verif = time.tick_since(start) / DSA_ITERS + + return +} + +@(private="file") +bench_ecdsa :: proc(curve: ecdsa.Curve, hash: hash.Algorithm) -> (sk, sig, verif: time.Duration) { + priv_bytes := make([]byte, ecdsa.PRIVATE_KEY_SIZES[curve], context.temp_allocator) + mem.set(raw_data(priv_bytes), 0x69, len(priv_bytes)) + priv_key: ecdsa.Private_Key + start := time.tick_now() + for _ in 0 ..< DSA_ITERS { + ok := ecdsa.private_key_set_bytes(&priv_key, curve, priv_bytes) + assert(ok, "private key should deserialize") + } + sk = time.tick_since(start) / DSA_ITERS + + pub_key: ecdsa.Public_Key + ecdsa.public_key_set_priv(&pub_key, &priv_key) + + sig_bytes := make([]byte, ecdsa.RAW_SIGNATURE_SIZES[curve], context.temp_allocator) + msg_bytes := transmute([]byte)(SIG_MSG) + start = time.tick_now() + for _ in 0 ..< DSA_ITERS { + ok := ecdsa.sign_raw(&priv_key, hash, msg_bytes, sig_bytes, true) + assert(ok, "signing should succeed") + } + sig = time.tick_since(start) / DSA_ITERS + + start = time.tick_now() + for _ in 0 ..< DSA_ITERS { + ok := ecdsa.verify_raw(&pub_key, hash, msg_bytes, sig_bytes) assert(ok, "signature should validate") } verif = time.tick_since(start) / DSA_ITERS diff --git a/tests/benchmark/crypto/benchmark_pqc.odin b/tests/benchmark/crypto/benchmark_pqc.odin new file mode 100644 index 000000000..20b2827fb --- /dev/null +++ b/tests/benchmark/crypto/benchmark_pqc.odin @@ -0,0 +1,176 @@ +package benchmark_core_crypto + +import "core:log" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto" +import "core:crypto/mldsa" +import "core:crypto/mlkem" + +@(private = "file") +MLKEM_ITERS :: 50000 +@(private = "file") +MLDSA_ITERS :: 10000 + +@(test) +benchmark_crypto_mlkem :: proc(t: ^testing.T) { + if !crypto.HAS_RAND_BYTES { + log.warnf("ML-KEM benchmarks skipped, no system entropy source") + return + } + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "ML-KEM") + table.aligned_header_of_values(&tbl, .Right, "Parameters", "Keygen", "Encaps", "Decaps") + + append_tbl := proc(tbl: ^table.Table, algo_name: string, keygen, encaps, decaps: time.Duration) { + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + table.format(tbl, "%8M", keygen), + table.format(tbl, "%8M", encaps), + table.format(tbl, "%8M", decaps), + ) + } + + for params in mlkem.Parameters { + if params == .Invalid { + continue + } + param_name := MLKEM_PARAMS_NAMES[params] + + decaps_key: mlkem.Decapsulation_Key + start := time.tick_now() + for _ in 0 ..< MLKEM_ITERS { + _ = mlkem.decapsulation_key_generate(&decaps_key, params) + } + keygen := time.tick_since(start) / MLKEM_ITERS + + encaps_key := make([]byte, mlkem.ENCAPSULATION_KEY_SIZES[params]) + defer delete(encaps_key) + ciphertext := make([]byte, mlkem.CIPHERTEXT_SIZES[params]) + defer delete(ciphertext) + + mlkem.decapsulation_key_encaps_bytes(&decaps_key, encaps_key) + + bob_shared: [mlkem.SHARED_SECRET_SIZE]byte + start = time.tick_now() + for _ in 0 ..< MLKEM_ITERS { + _ = mlkem.encaps(params, encaps_key, bob_shared[:], ciphertext) + } + encaps := time.tick_since(start) / MLKEM_ITERS + + alice_shared: [mlkem.SHARED_SECRET_SIZE]byte + start = time.tick_now() + for _ in 0 ..< MLKEM_ITERS { + _ = mlkem.decaps(&decaps_key, ciphertext, alice_shared[:]) + } + decaps := time.tick_since(start) / MLKEM_ITERS + + append_tbl(&tbl, param_name, keygen, encaps, decaps) + } + + log_table(&tbl) +} + +@(test) +bench_mldsa :: proc(t: ^testing.T) { + if !crypto.HAS_RAND_BYTES { + log.warnf("ML-DSA benchmarks skipped, no system entropy source") + return + } + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "ML-DSA") + table.aligned_header_of_values(&tbl, .Right, "Parameters", "Op", "Time") + + append_tbl := proc(tbl: ^table.Table, algo_name, op: string, t: time.Duration) { + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + op, + table.format(tbl, "%8M", t), + ) + } + + do_bench := proc(params: mldsa.Parameters) -> (sk, sig, verif: time.Duration) { + // The time taken is highly seed dependent due to rejection + // sampling using SHAKE, so we hit up the system entropy source + // and crank up the iteration count. + priv_key: mldsa.Private_Key + start := time.tick_now() + for _ in 0 ..< MLDSA_ITERS*2 { + ok := mldsa.private_key_generate(&priv_key, params) + assert(ok, "private key should generate") + } + sk = time.tick_since(start) / (MLDSA_ITERS*2) + + pub_key: mldsa.Public_Key + mldsa.public_key_set_priv(&pub_key, &priv_key) + + msg_bytes := transmute([]byte)(SIG_MSG) + sig_bytes := make([]byte, mldsa.SIGNATURE_SIZES[params]) + defer delete(sig_bytes) + + // FIPS defaults to hedged mode with non-deterministic signatures. + start = time.tick_now() + for _ in 0 ..< MLDSA_ITERS { + ok := mldsa.sign(&priv_key, nil, msg_bytes, sig_bytes) + assert(ok, "signature should succeed") + } + sig = time.tick_since(start) / MLDSA_ITERS + + start = time.tick_now() + for _ in 0 ..< MLDSA_ITERS { + ok := mldsa.verify(&pub_key, nil, msg_bytes, sig_bytes) + assert(ok, "signature should validate") + } + verif = time.tick_since(start) / MLDSA_ITERS + + return + } + + for params in mldsa.Parameters { + if params == .Invalid { + continue + } + param_name := MLDSA_PARAMS_NAMES[params] + + sig, sk, verif := do_bench(params) + append_tbl(&tbl, param_name, "private_key_generate", sk) + append_tbl(&tbl, param_name, "sign", sig) + append_tbl(&tbl, param_name, "verify", verif) + + if params != .ML_DSA_87 { + table.row(&tbl) + } + } + + log_table(&tbl) +} + +@(private="file") +MLKEM_PARAMS_NAMES := [mlkem.Parameters]string { + .Invalid = "invalid", + .ML_KEM_512 = "ML-KEM-512", + .ML_KEM_768 = "ML-KEM-768", + .ML_KEM_1024 = "ML-KEM-1024", +} + +@(private="file") +MLDSA_PARAMS_NAMES := [mldsa.Parameters]string { + .Invalid = "invalid", + .ML_DSA_44 = "ML-DSA-44", + .ML_DSA_65 = "ML-DSA-65", + .ML_DSA_87 = "ML-DSA-87", +} diff --git a/tests/benchmark/math/benchmark_rand.odin b/tests/benchmark/math/benchmark_rand.odin new file mode 100644 index 000000000..742c90599 --- /dev/null +++ b/tests/benchmark/math/benchmark_rand.odin @@ -0,0 +1,130 @@ +package benchmark_core_math + +import "base:runtime" + +import "core:fmt" +import "core:math/rand" +import "core:log" +import "core:strings" +import "core:testing" +import "core:text/table" +import "core:time" + +@(private = "file") +ITERS :: 10000000 +@(private = "file") +ITERS_BULK :: 1000 + +@(private = "file") +SAMPLE_SEED : string : "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456" + +@(test) +benchmark_rng :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "RNG") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput") + + context.random_generator = rand.default_random_generator() + rand.reset_bytes(transmute([]byte)(SAMPLE_SEED)) + _benchmark_u64(t, &tbl, "chacha8rand") + _benchmark_large(t, &tbl, "chacha8rand") + + table.row(&tbl) + + context.random_generator = rand.pcg_random_generator() + _benchmark_u64(t, &tbl, "pcg64") + _benchmark_large(t, &tbl, "pcg64") + + table.row(&tbl) + + context.random_generator = rand.xoshiro256_random_generator() + _benchmark_u64(t, &tbl, "xorshiro256**") + _benchmark_large(t, &tbl, "xorshiro256**") + + log_table(&tbl) +} + +@(private = "file") +_benchmark_u64 :: proc(t: ^testing.T, tbl: ^table.Table, algo_name: string) { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = 8, + setup = nil, + bench = proc(options: ^time.Benchmark_Options, allocator: runtime.Allocator) -> (err: time.Benchmark_Error){ + sum: u64 + for _ in 0 ..= options.rounds { + sum += rand.uint64() + } + options.hash = u128(sum) + options.count = options.rounds + options.processed = options.rounds * options.bytes + return + }, + teardown = nil, + } + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + table.format(tbl, "uint64"), + table.format(tbl, "%8M", time_per_iter), + table.format(tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) +} + +@(private = "file") +_benchmark_large :: proc(t: ^testing.T, tbl: ^table.Table, algo_name: string) { + options := &time.Benchmark_Options{ + rounds = ITERS_BULK, + bytes = 1024768, + setup = nil, + bench = proc(options: ^time.Benchmark_Options, allocator: runtime.Allocator) -> (err: time.Benchmark_Error){ + n: int + for _ in 0 ..= options.rounds { + n += rand.read(options.output) + } + options.hash = u128(n) + options.count = options.rounds + options.processed = options.rounds * options.bytes + return + }, + output = make([]byte, 1024768, context.temp_allocator), + teardown = nil, + } + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS_BULK + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + table.format(tbl, "1 MiB"), + table.format(tbl, "%8M", time_per_iter), + table.format(tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) +} + +@(private) +log_table :: proc(tbl: ^table.Table) { + sb := strings.builder_make() + defer strings.builder_destroy(&sb) + + wr := strings.to_writer(&sb) + + fmt.sbprintln(&sb) + table.write_plain_table(wr, tbl) + + log.info(strings.to_string(sb)) +} diff --git a/tests/benchmark/runtime/benchmark_runtime.odin b/tests/benchmark/runtime/benchmark_runtime.odin new file mode 100644 index 000000000..871fb05e6 --- /dev/null +++ b/tests/benchmark/runtime/benchmark_runtime.odin @@ -0,0 +1,227 @@ +package benchmark_runtime + +import "base:runtime" +import "core:fmt" +import "core:log" +import "core:testing" +import "core:strings" +import "core:text/table" +import "core:time" + +RUNS_PER_SIZE :: 2500 + +sizes := [?]int { + 7, 8, 9, + 15, 16, 17, + 31, 32, 33, + 63, 64, 65, + 95, 96, 97, + 128, + 256, + 512, + 1024, + 4096, + 1024 * 1024, +} + +// These are the normal, unoptimized algorithms. + +plain_memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { + switch { + case n == 0: return true + case x == y: return true + } + a, b := ([^]byte)(x), ([^]byte)(y) + length := uint(n) + + for i := uint(0); i < length; i += 1 { + if a[i] != b[i] { + return false + } + } + return true +} + +plain_memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check { + switch { + case a == b: return 0 + case a == nil: return -1 + case b == nil: return +1 + } + + x := uintptr(a) + y := uintptr(b) + n := uintptr(n) + + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) + if n < SU { + fast = 0 + } + + for /**/; curr_block < fast; curr_block += 1 { + va := (^uintptr)(x + curr_block * size_of(uintptr))^ + vb := (^uintptr)(y + curr_block * size_of(uintptr))^ + if va ~ vb != 0 { + for pos := curr_block*SU; pos < n; pos += 1 { + a := (^byte)(x+pos)^ + b := (^byte)(y+pos)^ + if a ~ b != 0 { + return -1 if (int(a) - int(b)) < 0 else +1 + } + } + } + } + + for /**/; offset < n; offset += 1 { + a := (^byte)(x+offset)^ + b := (^byte)(y+offset)^ + if a ~ b != 0 { + return -1 if (int(a) - int(b)) < 0 else +1 + } + } + + return 0 +} + +plain_memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check { + x := uintptr(a) + n := uintptr(n) + + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) + if n < SU { + fast = 0 + } + + for /**/; curr_block < fast; curr_block += 1 { + va := (^uintptr)(x + curr_block * size_of(uintptr))^ + if va ~ 0 != 0 { + for pos := curr_block*SU; pos < n; pos += 1 { + a := (^byte)(x+pos)^ + if a ~ 0 != 0 { + return -1 if int(a) < 0 else +1 + } + } + } + } + + for /**/; offset < n; offset += 1 { + a := (^byte)(x+offset)^ + if a ~ 0 != 0 { + return -1 if int(a) < 0 else +1 + } + } + + return 0 +} + +run_trial_size_cmp :: proc(p: proc "contextless" (rawptr, rawptr, int) -> $R, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + left := make([]u8, size) + right := make([]u8, size) + defer { + delete(left) + delete(right) + } + + right[idx] = 0x01 + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.. int, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + data := make([]u8, size) + defer delete(data) + + data[idx] = 0x01 + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.. (n: int) { + _len := min(len(a), len(b)) + + // Scan for matches including partial codepoints. + #no_bounds_check for n < _len && a[n] == b[n] { + n += 1 + } + + // Now scan to ignore partial codepoints. + if n > 0 { + s := a[:n] + n = 0 + for { + r0, w := utf8.decode_rune(s[n:]) + if r0 != utf8.RUNE_ERROR { + n += w + } else { + break + } + } + } + return +} + +run_trial_size_prefix :: proc(p: proc "contextless" (string, string) -> $R, suffix: string, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + left := make([]u8, size) + right := make([]u8, size) + defer { + delete(left) + delete(right) + } + + if len(suffix) > 0 { + copy(left [idx:], suffix) + copy(right[idx:], suffix) + + } else { + right[idx] = 'A' + } + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.... +0020 ; White_Space # Zs SPACE +0085 ; White_Space # Cc +00A0 ; White_Space # Zs NO-BREAK SPACE +1680 ; White_Space # Zs OGHAM SPACE MARK +2000..200A ; White_Space # Zs [11] EN QUAD..HAIR SPACE +2028 ; White_Space # Zl LINE SEPARATOR +2029 ; White_Space # Zp PARAGRAPH SEPARATOR +202F ; White_Space # Zs NARROW NO-BREAK SPACE +205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE +3000 ; White_Space # Zs IDEOGRAPHIC SPACE + +# Total code points: 25 + +# ================================================ + +061C ; Bidi_Control # Cf ARABIC LETTER MARK +200E..200F ; Bidi_Control # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK +202A..202E ; Bidi_Control # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE +2066..2069 ; Bidi_Control # Cf [4] LEFT-TO-RIGHT ISOLATE..POP DIRECTIONAL ISOLATE + +# Total code points: 12 + +# ================================================ + +200C..200D ; Join_Control # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER + +# Total code points: 2 + +# ================================================ + +002D ; Dash # Pd HYPHEN-MINUS +058A ; Dash # Pd ARMENIAN HYPHEN +05BE ; Dash # Pd HEBREW PUNCTUATION MAQAF +1400 ; Dash # Pd CANADIAN SYLLABICS HYPHEN +1806 ; Dash # Pd MONGOLIAN TODO SOFT HYPHEN +2010..2015 ; Dash # Pd [6] HYPHEN..HORIZONTAL BAR +2053 ; Dash # Po SWUNG DASH +207B ; Dash # Sm SUPERSCRIPT MINUS +208B ; Dash # Sm SUBSCRIPT MINUS +2212 ; Dash # Sm MINUS SIGN +2E17 ; Dash # Pd DOUBLE OBLIQUE HYPHEN +2E1A ; Dash # Pd HYPHEN WITH DIAERESIS +2E3A..2E3B ; Dash # Pd [2] TWO-EM DASH..THREE-EM DASH +2E40 ; Dash # Pd DOUBLE HYPHEN +2E5D ; Dash # Pd OBLIQUE HYPHEN +301C ; Dash # Pd WAVE DASH +3030 ; Dash # Pd WAVY DASH +30A0 ; Dash # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN +FE31..FE32 ; Dash # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH +FE58 ; Dash # Pd SMALL EM DASH +FE63 ; Dash # Pd SMALL HYPHEN-MINUS +FF0D ; Dash # Pd FULLWIDTH HYPHEN-MINUS +10D6E ; Dash # Pd GARAY HYPHEN +10EAD ; Dash # Pd YEZIDI HYPHENATION MARK + +# Total code points: 31 + +# ================================================ + +002D ; Hyphen # Pd HYPHEN-MINUS +00AD ; Hyphen # Cf SOFT HYPHEN +058A ; Hyphen # Pd ARMENIAN HYPHEN +1806 ; Hyphen # Pd MONGOLIAN TODO SOFT HYPHEN +2010..2011 ; Hyphen # Pd [2] HYPHEN..NON-BREAKING HYPHEN +2E17 ; Hyphen # Pd DOUBLE OBLIQUE HYPHEN +30FB ; Hyphen # Po KATAKANA MIDDLE DOT +FE63 ; Hyphen # Pd SMALL HYPHEN-MINUS +FF0D ; Hyphen # Pd FULLWIDTH HYPHEN-MINUS +FF65 ; Hyphen # Po HALFWIDTH KATAKANA MIDDLE DOT + +# Total code points: 11 + +# ================================================ + +0022 ; Quotation_Mark # Po QUOTATION MARK +0027 ; Quotation_Mark # Po APOSTROPHE +00AB ; Quotation_Mark # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00BB ; Quotation_Mark # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +2018 ; Quotation_Mark # Pi LEFT SINGLE QUOTATION MARK +2019 ; Quotation_Mark # Pf RIGHT SINGLE QUOTATION MARK +201A ; Quotation_Mark # Ps SINGLE LOW-9 QUOTATION MARK +201B..201C ; Quotation_Mark # Pi [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK +201D ; Quotation_Mark # Pf RIGHT DOUBLE QUOTATION MARK +201E ; Quotation_Mark # Ps DOUBLE LOW-9 QUOTATION MARK +201F ; Quotation_Mark # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK +2039 ; Quotation_Mark # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A ; Quotation_Mark # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +2E42 ; Quotation_Mark # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK +300C ; Quotation_Mark # Ps LEFT CORNER BRACKET +300D ; Quotation_Mark # Pe RIGHT CORNER BRACKET +300E ; Quotation_Mark # Ps LEFT WHITE CORNER BRACKET +300F ; Quotation_Mark # Pe RIGHT WHITE CORNER BRACKET +301D ; Quotation_Mark # Ps REVERSED DOUBLE PRIME QUOTATION MARK +301E..301F ; Quotation_Mark # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK +FE41 ; Quotation_Mark # Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET +FE42 ; Quotation_Mark # Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET +FE43 ; Quotation_Mark # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET +FE44 ; Quotation_Mark # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET +FF02 ; Quotation_Mark # Po FULLWIDTH QUOTATION MARK +FF07 ; Quotation_Mark # Po FULLWIDTH APOSTROPHE +FF62 ; Quotation_Mark # Ps HALFWIDTH LEFT CORNER BRACKET +FF63 ; Quotation_Mark # Pe HALFWIDTH RIGHT CORNER BRACKET + +# Total code points: 30 + +# ================================================ + +0021 ; Terminal_Punctuation # Po EXCLAMATION MARK +002C ; Terminal_Punctuation # Po COMMA +002E ; Terminal_Punctuation # Po FULL STOP +003A..003B ; Terminal_Punctuation # Po [2] COLON..SEMICOLON +003F ; Terminal_Punctuation # Po QUESTION MARK +037E ; Terminal_Punctuation # Po GREEK QUESTION MARK +0387 ; Terminal_Punctuation # Po GREEK ANO TELEIA +0589 ; Terminal_Punctuation # Po ARMENIAN FULL STOP +05C3 ; Terminal_Punctuation # Po HEBREW PUNCTUATION SOF PASUQ +060C ; Terminal_Punctuation # Po ARABIC COMMA +061B ; Terminal_Punctuation # Po ARABIC SEMICOLON +061D..061F ; Terminal_Punctuation # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK +06D4 ; Terminal_Punctuation # Po ARABIC FULL STOP +0700..070A ; Terminal_Punctuation # Po [11] SYRIAC END OF PARAGRAPH..SYRIAC CONTRACTION +070C ; Terminal_Punctuation # Po SYRIAC HARKLEAN METOBELUS +07F8..07F9 ; Terminal_Punctuation # Po [2] NKO COMMA..NKO EXCLAMATION MARK +0830..0835 ; Terminal_Punctuation # Po [6] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION SHIYYAALAA +0837..083E ; Terminal_Punctuation # Po [8] SAMARITAN PUNCTUATION MELODIC QITSA..SAMARITAN PUNCTUATION ANNAAU +085E ; Terminal_Punctuation # Po MANDAIC PUNCTUATION +0964..0965 ; Terminal_Punctuation # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA +0E5A..0E5B ; Terminal_Punctuation # Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT +0F08 ; Terminal_Punctuation # Po TIBETAN MARK SBRUL SHAD +0F0D..0F12 ; Terminal_Punctuation # Po [6] TIBETAN MARK SHAD..TIBETAN MARK RGYA GRAM SHAD +104A..104B ; Terminal_Punctuation # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION +1361..1368 ; Terminal_Punctuation # Po [8] ETHIOPIC WORDSPACE..ETHIOPIC PARAGRAPH SEPARATOR +166E ; Terminal_Punctuation # Po CANADIAN SYLLABICS FULL STOP +16EB..16ED ; Terminal_Punctuation # Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION +1735..1736 ; Terminal_Punctuation # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION +17D4..17D6 ; Terminal_Punctuation # Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH +17DA ; Terminal_Punctuation # Po KHMER SIGN KOOMUUT +1802..1805 ; Terminal_Punctuation # Po [4] MONGOLIAN COMMA..MONGOLIAN FOUR DOTS +1808..1809 ; Terminal_Punctuation # Po [2] MONGOLIAN MANCHU COMMA..MONGOLIAN MANCHU FULL STOP +1944..1945 ; Terminal_Punctuation # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK +1AA8..1AAB ; Terminal_Punctuation # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU +1B4E..1B4F ; Terminal_Punctuation # Po [2] BALINESE INVERTED CARIK SIKI..BALINESE INVERTED CARIK PAREREN +1B5A..1B5B ; Terminal_Punctuation # Po [2] BALINESE PANTI..BALINESE PAMADA +1B5D..1B5F ; Terminal_Punctuation # Po [3] BALINESE CARIK PAMUNGKAH..BALINESE CARIK PAREREN +1B7D..1B7F ; Terminal_Punctuation # Po [3] BALINESE PANTI LANTANG..BALINESE PANTI BAWAK +1C3B..1C3F ; Terminal_Punctuation # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK +1C7E..1C7F ; Terminal_Punctuation # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD +2024 ; Terminal_Punctuation # Po ONE DOT LEADER +203C..203D ; Terminal_Punctuation # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG +2047..2049 ; Terminal_Punctuation # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK +2CF9..2CFB ; Terminal_Punctuation # Po [3] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN INDIRECT QUESTION MARK +2E2E ; Terminal_Punctuation # Po REVERSED QUESTION MARK +2E3C ; Terminal_Punctuation # Po STENOGRAPHIC FULL STOP +2E41 ; Terminal_Punctuation # Po REVERSED COMMA +2E4C ; Terminal_Punctuation # Po MEDIEVAL COMMA +2E4E..2E4F ; Terminal_Punctuation # Po [2] PUNCTUS ELEVATUS MARK..CORNISH VERSE DIVIDER +2E53..2E54 ; Terminal_Punctuation # Po [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK +3001..3002 ; Terminal_Punctuation # Po [2] IDEOGRAPHIC COMMA..IDEOGRAPHIC FULL STOP +A4FE..A4FF ; Terminal_Punctuation # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP +A60D..A60F ; Terminal_Punctuation # Po [3] VAI COMMA..VAI QUESTION MARK +A6F3..A6F7 ; Terminal_Punctuation # Po [5] BAMUM FULL STOP..BAMUM QUESTION MARK +A876..A877 ; Terminal_Punctuation # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD +A8CE..A8CF ; Terminal_Punctuation # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA +A92F ; Terminal_Punctuation # Po KAYAH LI SIGN SHYA +A9C7..A9C9 ; Terminal_Punctuation # Po [3] JAVANESE PADA PANGKAT..JAVANESE PADA LUNGSI +AA5D..AA5F ; Terminal_Punctuation # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA +AADF ; Terminal_Punctuation # Po TAI VIET SYMBOL KOI KOI +AAF0..AAF1 ; Terminal_Punctuation # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM +ABEB ; Terminal_Punctuation # Po MEETEI MAYEK CHEIKHEI +FE12 ; Terminal_Punctuation # Po PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP +FE15..FE16 ; Terminal_Punctuation # Po [2] PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK..PRESENTATION FORM FOR VERTICAL QUESTION MARK +FE50..FE52 ; Terminal_Punctuation # Po [3] SMALL COMMA..SMALL FULL STOP +FE54..FE57 ; Terminal_Punctuation # Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK +FF01 ; Terminal_Punctuation # Po FULLWIDTH EXCLAMATION MARK +FF0C ; Terminal_Punctuation # Po FULLWIDTH COMMA +FF0E ; Terminal_Punctuation # Po FULLWIDTH FULL STOP +FF1A..FF1B ; Terminal_Punctuation # Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON +FF1F ; Terminal_Punctuation # Po FULLWIDTH QUESTION MARK +FF61 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC FULL STOP +FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA +1039F ; Terminal_Punctuation # Po UGARITIC WORD DIVIDER +103D0 ; Terminal_Punctuation # Po OLD PERSIAN WORD DIVIDER +10857 ; Terminal_Punctuation # Po IMPERIAL ARAMAIC SECTION SIGN +1091F ; Terminal_Punctuation # Po PHOENICIAN WORD SEPARATOR +10A56..10A57 ; Terminal_Punctuation # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA +10AF0..10AF5 ; Terminal_Punctuation # Po [6] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION TWO DOTS +10B3A..10B3F ; Terminal_Punctuation # Po [6] TINY TWO DOTS OVER ONE DOT PUNCTUATION..LARGE ONE RING OVER TWO RINGS PUNCTUATION +10B99..10B9C ; Terminal_Punctuation # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT +10F55..10F59 ; Terminal_Punctuation # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT +10F86..10F89 ; Terminal_Punctuation # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS +11047..1104D ; Terminal_Punctuation # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS +110BE..110C1 ; Terminal_Punctuation # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA +11141..11143 ; Terminal_Punctuation # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK +111C5..111C6 ; Terminal_Punctuation # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA +111CD ; Terminal_Punctuation # Po SHARADA SUTRA MARK +111DE..111DF ; Terminal_Punctuation # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 +11238..1123C ; Terminal_Punctuation # Po [5] KHOJKI DANDA..KHOJKI DOUBLE SECTION MARK +112A9 ; Terminal_Punctuation # Po MULTANI SECTION MARK +113D4..113D5 ; Terminal_Punctuation # Po [2] TULU-TIGALARI DANDA..TULU-TIGALARI DOUBLE DANDA +1144B..1144D ; Terminal_Punctuation # Po [3] NEWA DANDA..NEWA COMMA +1145A..1145B ; Terminal_Punctuation # Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK +115C2..115C5 ; Terminal_Punctuation # Po [4] SIDDHAM DANDA..SIDDHAM SEPARATOR BAR +115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES +11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA +1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +11944 ; Terminal_Punctuation # Po DIVES AKURU DOUBLE DANDA +11946 ; Terminal_Punctuation # Po DIVES AKURU END OF TEXT MARK +11A42..11A43 ; Terminal_Punctuation # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD +11A9B..11A9C ; Terminal_Punctuation # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD +11AA1..11AA2 ; Terminal_Punctuation # Po [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2 +11C41..11C43 ; Terminal_Punctuation # Po [3] BHAIKSUKI DANDA..BHAIKSUKI WORD SEPARATOR +11C71 ; Terminal_Punctuation # Po MARCHEN MARK SHAD +11EF7..11EF8 ; Terminal_Punctuation # Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION +11F43..11F44 ; Terminal_Punctuation # Po [2] KAWI DANDA..KAWI DOUBLE DANDA +12470..12474 ; Terminal_Punctuation # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON +16A6E..16A6F ; Terminal_Punctuation # Po [2] MRO DANDA..MRO DOUBLE DANDA +16AF5 ; Terminal_Punctuation # Po BASSA VAH FULL STOP +16B37..16B39 ; Terminal_Punctuation # Po [3] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN CIM CHEEM +16B44 ; Terminal_Punctuation # Po PAHAWH HMONG SIGN XAUS +16D6E..16D6F ; Terminal_Punctuation # Po [2] KIRAT RAI DANDA..KIRAT RAI DOUBLE DANDA +16E97..16E98 ; Terminal_Punctuation # Po [2] MEDEFAIDRIN COMMA..MEDEFAIDRIN FULL STOP +1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP +1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON + +# Total code points: 291 + +# ================================================ + +005E ; Other_Math # Sk CIRCUMFLEX ACCENT +03D0..03D2 ; Other_Math # L& [3] GREEK BETA SYMBOL..GREEK UPSILON WITH HOOK SYMBOL +03D5 ; Other_Math # L& GREEK PHI SYMBOL +03F0..03F1 ; Other_Math # L& [2] GREEK KAPPA SYMBOL..GREEK RHO SYMBOL +03F4..03F5 ; Other_Math # L& [2] GREEK CAPITAL THETA SYMBOL..GREEK LUNATE EPSILON SYMBOL +2016 ; Other_Math # Po DOUBLE VERTICAL LINE +2032..2034 ; Other_Math # Po [3] PRIME..TRIPLE PRIME +2040 ; Other_Math # Pc CHARACTER TIE +2061..2064 ; Other_Math # Cf [4] FUNCTION APPLICATION..INVISIBLE PLUS +207D ; Other_Math # Ps SUPERSCRIPT LEFT PARENTHESIS +207E ; Other_Math # Pe SUPERSCRIPT RIGHT PARENTHESIS +208D ; Other_Math # Ps SUBSCRIPT LEFT PARENTHESIS +208E ; Other_Math # Pe SUBSCRIPT RIGHT PARENTHESIS +20D0..20DC ; Other_Math # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE +20E1 ; Other_Math # Mn COMBINING LEFT RIGHT ARROW ABOVE +20E5..20E6 ; Other_Math # Mn [2] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING DOUBLE VERTICAL STROKE OVERLAY +20EB..20EF ; Other_Math # Mn [5] COMBINING LONG DOUBLE SOLIDUS OVERLAY..COMBINING RIGHT ARROW BELOW +2102 ; Other_Math # L& DOUBLE-STRUCK CAPITAL C +2107 ; Other_Math # L& EULER CONSTANT +210A..2113 ; Other_Math # L& [10] SCRIPT SMALL G..SCRIPT SMALL L +2115 ; Other_Math # L& DOUBLE-STRUCK CAPITAL N +2119..211D ; Other_Math # L& [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R +2124 ; Other_Math # L& DOUBLE-STRUCK CAPITAL Z +2128 ; Other_Math # L& BLACK-LETTER CAPITAL Z +2129 ; Other_Math # So TURNED GREEK SMALL LETTER IOTA +212C..212D ; Other_Math # L& [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C +212F..2131 ; Other_Math # L& [3] SCRIPT SMALL E..SCRIPT CAPITAL F +2133..2134 ; Other_Math # L& [2] SCRIPT CAPITAL M..SCRIPT SMALL O +2135..2138 ; Other_Math # Lo [4] ALEF SYMBOL..DALET SYMBOL +213C..213F ; Other_Math # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI +2145..2149 ; Other_Math # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J +2195..2199 ; Other_Math # So [5] UP DOWN ARROW..SOUTH WEST ARROW +219C..219F ; Other_Math # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW +21A1..21A2 ; Other_Math # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL +21A4..21A5 ; Other_Math # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR +21A7 ; Other_Math # So DOWNWARDS ARROW FROM BAR +21A9..21AD ; Other_Math # So [5] LEFTWARDS ARROW WITH HOOK..LEFT RIGHT WAVE ARROW +21B0..21B1 ; Other_Math # So [2] UPWARDS ARROW WITH TIP LEFTWARDS..UPWARDS ARROW WITH TIP RIGHTWARDS +21B6..21B7 ; Other_Math # So [2] ANTICLOCKWISE TOP SEMICIRCLE ARROW..CLOCKWISE TOP SEMICIRCLE ARROW +21BC..21CD ; Other_Math # So [18] LEFTWARDS HARPOON WITH BARB UPWARDS..LEFTWARDS DOUBLE ARROW WITH STROKE +21D0..21D1 ; Other_Math # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW +21D3 ; Other_Math # So DOWNWARDS DOUBLE ARROW +21D5..21DB ; Other_Math # So [7] UP DOWN DOUBLE ARROW..RIGHTWARDS TRIPLE ARROW +21DD ; Other_Math # So RIGHTWARDS SQUIGGLE ARROW +21E4..21E5 ; Other_Math # So [2] LEFTWARDS ARROW TO BAR..RIGHTWARDS ARROW TO BAR +2308 ; Other_Math # Ps LEFT CEILING +2309 ; Other_Math # Pe RIGHT CEILING +230A ; Other_Math # Ps LEFT FLOOR +230B ; Other_Math # Pe RIGHT FLOOR +23B4..23B5 ; Other_Math # So [2] TOP SQUARE BRACKET..BOTTOM SQUARE BRACKET +23B7 ; Other_Math # So RADICAL SYMBOL BOTTOM +23D0 ; Other_Math # So VERTICAL LINE EXTENSION +23E2 ; Other_Math # So WHITE TRAPEZIUM +25A0..25A1 ; Other_Math # So [2] BLACK SQUARE..WHITE SQUARE +25AE..25B6 ; Other_Math # So [9] BLACK VERTICAL RECTANGLE..BLACK RIGHT-POINTING TRIANGLE +25BC..25C0 ; Other_Math # So [5] BLACK DOWN-POINTING TRIANGLE..BLACK LEFT-POINTING TRIANGLE +25C6..25C7 ; Other_Math # So [2] BLACK DIAMOND..WHITE DIAMOND +25CA..25CB ; Other_Math # So [2] LOZENGE..WHITE CIRCLE +25CF..25D3 ; Other_Math # So [5] BLACK CIRCLE..CIRCLE WITH UPPER HALF BLACK +25E2 ; Other_Math # So BLACK LOWER RIGHT TRIANGLE +25E4 ; Other_Math # So BLACK UPPER LEFT TRIANGLE +25E7..25EC ; Other_Math # So [6] SQUARE WITH LEFT HALF BLACK..WHITE UP-POINTING TRIANGLE WITH DOT +2605..2606 ; Other_Math # So [2] BLACK STAR..WHITE STAR +2640 ; Other_Math # So FEMALE SIGN +2642 ; Other_Math # So MALE SIGN +2660..2663 ; Other_Math # So [4] BLACK SPADE SUIT..BLACK CLUB SUIT +266D..266E ; Other_Math # So [2] MUSIC FLAT SIGN..MUSIC NATURAL SIGN +27C5 ; Other_Math # Ps LEFT S-SHAPED BAG DELIMITER +27C6 ; Other_Math # Pe RIGHT S-SHAPED BAG DELIMITER +27E6 ; Other_Math # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET +27E7 ; Other_Math # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET +27E8 ; Other_Math # Ps MATHEMATICAL LEFT ANGLE BRACKET +27E9 ; Other_Math # Pe MATHEMATICAL RIGHT ANGLE BRACKET +27EA ; Other_Math # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET +27EB ; Other_Math # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET +27EC ; Other_Math # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET +27ED ; Other_Math # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET +27EE ; Other_Math # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS +27EF ; Other_Math # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS +2983 ; Other_Math # Ps LEFT WHITE CURLY BRACKET +2984 ; Other_Math # Pe RIGHT WHITE CURLY BRACKET +2985 ; Other_Math # Ps LEFT WHITE PARENTHESIS +2986 ; Other_Math # Pe RIGHT WHITE PARENTHESIS +2987 ; Other_Math # Ps Z NOTATION LEFT IMAGE BRACKET +2988 ; Other_Math # Pe Z NOTATION RIGHT IMAGE BRACKET +2989 ; Other_Math # Ps Z NOTATION LEFT BINDING BRACKET +298A ; Other_Math # Pe Z NOTATION RIGHT BINDING BRACKET +298B ; Other_Math # Ps LEFT SQUARE BRACKET WITH UNDERBAR +298C ; Other_Math # Pe RIGHT SQUARE BRACKET WITH UNDERBAR +298D ; Other_Math # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER +298E ; Other_Math # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +298F ; Other_Math # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +2990 ; Other_Math # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER +2991 ; Other_Math # Ps LEFT ANGLE BRACKET WITH DOT +2992 ; Other_Math # Pe RIGHT ANGLE BRACKET WITH DOT +2993 ; Other_Math # Ps LEFT ARC LESS-THAN BRACKET +2994 ; Other_Math # Pe RIGHT ARC GREATER-THAN BRACKET +2995 ; Other_Math # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET +2996 ; Other_Math # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET +2997 ; Other_Math # Ps LEFT BLACK TORTOISE SHELL BRACKET +2998 ; Other_Math # Pe RIGHT BLACK TORTOISE SHELL BRACKET +29D8 ; Other_Math # Ps LEFT WIGGLY FENCE +29D9 ; Other_Math # Pe RIGHT WIGGLY FENCE +29DA ; Other_Math # Ps LEFT DOUBLE WIGGLY FENCE +29DB ; Other_Math # Pe RIGHT DOUBLE WIGGLY FENCE +29FC ; Other_Math # Ps LEFT-POINTING CURVED ANGLE BRACKET +29FD ; Other_Math # Pe RIGHT-POINTING CURVED ANGLE BRACKET +FE61 ; Other_Math # Po SMALL ASTERISK +FE63 ; Other_Math # Pd SMALL HYPHEN-MINUS +FE68 ; Other_Math # Po SMALL REVERSE SOLIDUS +FF3C ; Other_Math # Po FULLWIDTH REVERSE SOLIDUS +FF3E ; Other_Math # Sk FULLWIDTH CIRCUMFLEX ACCENT +1D400..1D454 ; Other_Math # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G +1D456..1D49C ; Other_Math # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A +1D49E..1D49F ; Other_Math # L& [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D +1D4A2 ; Other_Math # L& MATHEMATICAL SCRIPT CAPITAL G +1D4A5..1D4A6 ; Other_Math # L& [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K +1D4A9..1D4AC ; Other_Math # L& [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q +1D4AE..1D4B9 ; Other_Math # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D +1D4BB ; Other_Math # L& MATHEMATICAL SCRIPT SMALL F +1D4BD..1D4C3 ; Other_Math # L& [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N +1D4C5..1D505 ; Other_Math # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B +1D507..1D50A ; Other_Math # L& [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G +1D50D..1D514 ; Other_Math # L& [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q +1D516..1D51C ; Other_Math # L& [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y +1D51E..1D539 ; Other_Math # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B +1D53B..1D53E ; Other_Math # L& [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G +1D540..1D544 ; Other_Math # L& [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M +1D546 ; Other_Math # L& MATHEMATICAL DOUBLE-STRUCK CAPITAL O +1D54A..1D550 ; Other_Math # L& [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y +1D552..1D6A5 ; Other_Math # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J +1D6A8..1D6C0 ; Other_Math # L& [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA +1D6C2..1D6DA ; Other_Math # L& [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA +1D6DC..1D6FA ; Other_Math # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA +1D6FC..1D714 ; Other_Math # L& [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA +1D716..1D734 ; Other_Math # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA +1D736..1D74E ; Other_Math # L& [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA +1D750..1D76E ; Other_Math # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA +1D770..1D788 ; Other_Math # L& [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA +1D78A..1D7A8 ; Other_Math # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA +1D7AA..1D7C2 ; Other_Math # L& [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA +1D7C4..1D7CB ; Other_Math # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA +1D7CE..1D7FF ; Other_Math # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE +1EE00..1EE03 ; Other_Math # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL +1EE05..1EE1F ; Other_Math # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF +1EE21..1EE22 ; Other_Math # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM +1EE24 ; Other_Math # Lo ARABIC MATHEMATICAL INITIAL HEH +1EE27 ; Other_Math # Lo ARABIC MATHEMATICAL INITIAL HAH +1EE29..1EE32 ; Other_Math # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF +1EE34..1EE37 ; Other_Math # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH +1EE39 ; Other_Math # Lo ARABIC MATHEMATICAL INITIAL DAD +1EE3B ; Other_Math # Lo ARABIC MATHEMATICAL INITIAL GHAIN +1EE42 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED JEEM +1EE47 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED HAH +1EE49 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED YEH +1EE4B ; Other_Math # Lo ARABIC MATHEMATICAL TAILED LAM +1EE4D..1EE4F ; Other_Math # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN +1EE51..1EE52 ; Other_Math # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF +1EE54 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED SHEEN +1EE57 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED KHAH +1EE59 ; Other_Math # Lo ARABIC MATHEMATICAL TAILED DAD +1EE5B ; Other_Math # Lo ARABIC MATHEMATICAL TAILED GHAIN +1EE5D ; Other_Math # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON +1EE5F ; Other_Math # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF +1EE61..1EE62 ; Other_Math # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM +1EE64 ; Other_Math # Lo ARABIC MATHEMATICAL STRETCHED HEH +1EE67..1EE6A ; Other_Math # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF +1EE6C..1EE72 ; Other_Math # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF +1EE74..1EE77 ; Other_Math # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH +1EE79..1EE7C ; Other_Math # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH +1EE7E ; Other_Math # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH +1EE80..1EE89 ; Other_Math # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH +1EE8B..1EE9B ; Other_Math # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN +1EEA1..1EEA3 ; Other_Math # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL +1EEA5..1EEA9 ; Other_Math # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH +1EEAB..1EEBB ; Other_Math # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN + +# Total code points: 1362 + +# ================================================ + +0030..0039 ; Hex_Digit # Nd [10] DIGIT ZERO..DIGIT NINE +0041..0046 ; Hex_Digit # L& [6] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER F +0061..0066 ; Hex_Digit # L& [6] LATIN SMALL LETTER A..LATIN SMALL LETTER F +FF10..FF19 ; Hex_Digit # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE +FF21..FF26 ; Hex_Digit # L& [6] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER F +FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER F + +# Total code points: 44 + +# ================================================ + +0030..0039 ; ASCII_Hex_Digit # Nd [10] DIGIT ZERO..DIGIT NINE +0041..0046 ; ASCII_Hex_Digit # L& [6] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER F +0061..0066 ; ASCII_Hex_Digit # L& [6] LATIN SMALL LETTER A..LATIN SMALL LETTER F + +# Total code points: 22 + +# ================================================ + +0345 ; Other_Alphabetic # Mn COMBINING GREEK YPOGEGRAMMENI +0363..036F ; Other_Alphabetic # Mn [13] COMBINING LATIN SMALL LETTER A..COMBINING LATIN SMALL LETTER X +05B0..05BD ; Other_Alphabetic # Mn [14] HEBREW POINT SHEVA..HEBREW POINT METEG +05BF ; Other_Alphabetic # Mn HEBREW POINT RAFE +05C1..05C2 ; Other_Alphabetic # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT +05C4..05C5 ; Other_Alphabetic # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT +05C7 ; Other_Alphabetic # Mn HEBREW POINT QAMATS QATAN +0610..061A ; Other_Alphabetic # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA +064B..0657 ; Other_Alphabetic # Mn [13] ARABIC FATHATAN..ARABIC INVERTED DAMMA +0659..065F ; Other_Alphabetic # Mn [7] ARABIC ZWARAKAY..ARABIC WAVY HAMZA BELOW +0670 ; Other_Alphabetic # Mn ARABIC LETTER SUPERSCRIPT ALEF +06D6..06DC ; Other_Alphabetic # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN +06E1..06E4 ; Other_Alphabetic # Mn [4] ARABIC SMALL HIGH DOTLESS HEAD OF KHAH..ARABIC SMALL HIGH MADDA +06E7..06E8 ; Other_Alphabetic # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON +06ED ; Other_Alphabetic # Mn ARABIC SMALL LOW MEEM +0711 ; Other_Alphabetic # Mn SYRIAC LETTER SUPERSCRIPT ALAPH +0730..073F ; Other_Alphabetic # Mn [16] SYRIAC PTHAHA ABOVE..SYRIAC RWAHA +07A6..07B0 ; Other_Alphabetic # Mn [11] THAANA ABAFILI..THAANA SUKUN +0816..0817 ; Other_Alphabetic # Mn [2] SAMARITAN MARK IN..SAMARITAN MARK IN-ALAF +081B..0823 ; Other_Alphabetic # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A +0825..0827 ; Other_Alphabetic # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U +0829..082C ; Other_Alphabetic # Mn [4] SAMARITAN VOWEL SIGN LONG I..SAMARITAN VOWEL SIGN SUKUN +0897 ; Other_Alphabetic # Mn ARABIC PEPET +08D4..08DF ; Other_Alphabetic # Mn [12] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH WORD WAQFA +08E3..08E9 ; Other_Alphabetic # Mn [7] ARABIC TURNED DAMMA BELOW..ARABIC CURLY KASRATAN +08F0..0902 ; Other_Alphabetic # Mn [19] ARABIC OPEN FATHATAN..DEVANAGARI SIGN ANUSVARA +0903 ; Other_Alphabetic # Mc DEVANAGARI SIGN VISARGA +093A ; Other_Alphabetic # Mn DEVANAGARI VOWEL SIGN OE +093B ; Other_Alphabetic # Mc DEVANAGARI VOWEL SIGN OOE +093E..0940 ; Other_Alphabetic # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II +0941..0948 ; Other_Alphabetic # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI +0949..094C ; Other_Alphabetic # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU +094E..094F ; Other_Alphabetic # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW +0955..0957 ; Other_Alphabetic # Mn [3] DEVANAGARI VOWEL SIGN CANDRA LONG E..DEVANAGARI VOWEL SIGN UUE +0962..0963 ; Other_Alphabetic # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL +0981 ; Other_Alphabetic # Mn BENGALI SIGN CANDRABINDU +0982..0983 ; Other_Alphabetic # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA +09BE..09C0 ; Other_Alphabetic # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II +09C1..09C4 ; Other_Alphabetic # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR +09C7..09C8 ; Other_Alphabetic # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI +09CB..09CC ; Other_Alphabetic # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU +09D7 ; Other_Alphabetic # Mc BENGALI AU LENGTH MARK +09E2..09E3 ; Other_Alphabetic # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL +0A01..0A02 ; Other_Alphabetic # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI +0A03 ; Other_Alphabetic # Mc GURMUKHI SIGN VISARGA +0A3E..0A40 ; Other_Alphabetic # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II +0A41..0A42 ; Other_Alphabetic # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU +0A47..0A48 ; Other_Alphabetic # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI +0A4B..0A4C ; Other_Alphabetic # Mn [2] GURMUKHI VOWEL SIGN OO..GURMUKHI VOWEL SIGN AU +0A51 ; Other_Alphabetic # Mn GURMUKHI SIGN UDAAT +0A70..0A71 ; Other_Alphabetic # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK +0A75 ; Other_Alphabetic # Mn GURMUKHI SIGN YAKASH +0A81..0A82 ; Other_Alphabetic # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA +0A83 ; Other_Alphabetic # Mc GUJARATI SIGN VISARGA +0ABE..0AC0 ; Other_Alphabetic # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II +0AC1..0AC5 ; Other_Alphabetic # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E +0AC7..0AC8 ; Other_Alphabetic # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI +0AC9 ; Other_Alphabetic # Mc GUJARATI VOWEL SIGN CANDRA O +0ACB..0ACC ; Other_Alphabetic # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU +0AE2..0AE3 ; Other_Alphabetic # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL +0AFA..0AFC ; Other_Alphabetic # Mn [3] GUJARATI SIGN SUKUN..GUJARATI SIGN MADDAH +0B01 ; Other_Alphabetic # Mn ORIYA SIGN CANDRABINDU +0B02..0B03 ; Other_Alphabetic # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA +0B3E ; Other_Alphabetic # Mc ORIYA VOWEL SIGN AA +0B3F ; Other_Alphabetic # Mn ORIYA VOWEL SIGN I +0B40 ; Other_Alphabetic # Mc ORIYA VOWEL SIGN II +0B41..0B44 ; Other_Alphabetic # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR +0B47..0B48 ; Other_Alphabetic # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI +0B4B..0B4C ; Other_Alphabetic # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU +0B56 ; Other_Alphabetic # Mn ORIYA AI LENGTH MARK +0B57 ; Other_Alphabetic # Mc ORIYA AU LENGTH MARK +0B62..0B63 ; Other_Alphabetic # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL +0B82 ; Other_Alphabetic # Mn TAMIL SIGN ANUSVARA +0BBE..0BBF ; Other_Alphabetic # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I +0BC0 ; Other_Alphabetic # Mn TAMIL VOWEL SIGN II +0BC1..0BC2 ; Other_Alphabetic # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU +0BC6..0BC8 ; Other_Alphabetic # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI +0BCA..0BCC ; Other_Alphabetic # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU +0BD7 ; Other_Alphabetic # Mc TAMIL AU LENGTH MARK +0C00 ; Other_Alphabetic # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE +0C01..0C03 ; Other_Alphabetic # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA +0C04 ; Other_Alphabetic # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE +0C3E..0C40 ; Other_Alphabetic # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II +0C41..0C44 ; Other_Alphabetic # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR +0C46..0C48 ; Other_Alphabetic # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI +0C4A..0C4C ; Other_Alphabetic # Mn [3] TELUGU VOWEL SIGN O..TELUGU VOWEL SIGN AU +0C55..0C56 ; Other_Alphabetic # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK +0C62..0C63 ; Other_Alphabetic # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL +0C81 ; Other_Alphabetic # Mn KANNADA SIGN CANDRABINDU +0C82..0C83 ; Other_Alphabetic # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA +0CBE ; Other_Alphabetic # Mc KANNADA VOWEL SIGN AA +0CBF ; Other_Alphabetic # Mn KANNADA VOWEL SIGN I +0CC0..0CC4 ; Other_Alphabetic # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR +0CC6 ; Other_Alphabetic # Mn KANNADA VOWEL SIGN E +0CC7..0CC8 ; Other_Alphabetic # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI +0CCA..0CCB ; Other_Alphabetic # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO +0CCC ; Other_Alphabetic # Mn KANNADA VOWEL SIGN AU +0CD5..0CD6 ; Other_Alphabetic # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK +0CE2..0CE3 ; Other_Alphabetic # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL +0CF3 ; Other_Alphabetic # Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT +0D00..0D01 ; Other_Alphabetic # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU +0D02..0D03 ; Other_Alphabetic # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA +0D3E..0D40 ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II +0D41..0D44 ; Other_Alphabetic # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR +0D46..0D48 ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI +0D4A..0D4C ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU +0D57 ; Other_Alphabetic # Mc MALAYALAM AU LENGTH MARK +0D62..0D63 ; Other_Alphabetic # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL +0D81 ; Other_Alphabetic # Mn SINHALA SIGN CANDRABINDU +0D82..0D83 ; Other_Alphabetic # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA +0DCF..0DD1 ; Other_Alphabetic # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA +0DD2..0DD4 ; Other_Alphabetic # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA +0DD6 ; Other_Alphabetic # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA +0DD8..0DDF ; Other_Alphabetic # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA +0DF2..0DF3 ; Other_Alphabetic # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA +0E31 ; Other_Alphabetic # Mn THAI CHARACTER MAI HAN-AKAT +0E34..0E3A ; Other_Alphabetic # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU +0E4D ; Other_Alphabetic # Mn THAI CHARACTER NIKHAHIT +0EB1 ; Other_Alphabetic # Mn LAO VOWEL SIGN MAI KAN +0EB4..0EB9 ; Other_Alphabetic # Mn [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU +0EBB..0EBC ; Other_Alphabetic # Mn [2] LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN LO +0ECD ; Other_Alphabetic # Mn LAO NIGGAHITA +0F71..0F7E ; Other_Alphabetic # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO +0F7F ; Other_Alphabetic # Mc TIBETAN SIGN RNAM BCAD +0F80..0F83 ; Other_Alphabetic # Mn [4] TIBETAN VOWEL SIGN REVERSED I..TIBETAN SIGN SNA LDAN +0F8D..0F97 ; Other_Alphabetic # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA +0F99..0FBC ; Other_Alphabetic # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA +102B..102C ; Other_Alphabetic # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA +102D..1030 ; Other_Alphabetic # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU +1031 ; Other_Alphabetic # Mc MYANMAR VOWEL SIGN E +1032..1036 ; Other_Alphabetic # Mn [5] MYANMAR VOWEL SIGN AI..MYANMAR SIGN ANUSVARA +1038 ; Other_Alphabetic # Mc MYANMAR SIGN VISARGA +103B..103C ; Other_Alphabetic # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA +103D..103E ; Other_Alphabetic # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA +1056..1057 ; Other_Alphabetic # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR +1058..1059 ; Other_Alphabetic # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL +105E..1060 ; Other_Alphabetic # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA +1062..1064 ; Other_Alphabetic # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO +1067..106D ; Other_Alphabetic # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5 +1071..1074 ; Other_Alphabetic # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE +1082 ; Other_Alphabetic # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA +1083..1084 ; Other_Alphabetic # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E +1085..1086 ; Other_Alphabetic # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y +1087..108C ; Other_Alphabetic # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 +108D ; Other_Alphabetic # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE +108F ; Other_Alphabetic # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 +109A..109C ; Other_Alphabetic # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A +109D ; Other_Alphabetic # Mn MYANMAR VOWEL SIGN AITON AI +1712..1713 ; Other_Alphabetic # Mn [2] TAGALOG VOWEL SIGN I..TAGALOG VOWEL SIGN U +1732..1733 ; Other_Alphabetic # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U +1752..1753 ; Other_Alphabetic # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U +1772..1773 ; Other_Alphabetic # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U +17B6 ; Other_Alphabetic # Mc KHMER VOWEL SIGN AA +17B7..17BD ; Other_Alphabetic # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA +17BE..17C5 ; Other_Alphabetic # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU +17C6 ; Other_Alphabetic # Mn KHMER SIGN NIKAHIT +17C7..17C8 ; Other_Alphabetic # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU +1885..1886 ; Other_Alphabetic # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +18A9 ; Other_Alphabetic # Mn MONGOLIAN LETTER ALI GALI DAGALGA +1920..1922 ; Other_Alphabetic # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U +1923..1926 ; Other_Alphabetic # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU +1927..1928 ; Other_Alphabetic # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O +1929..192B ; Other_Alphabetic # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA +1930..1931 ; Other_Alphabetic # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA +1932 ; Other_Alphabetic # Mn LIMBU SMALL LETTER ANUSVARA +1933..1938 ; Other_Alphabetic # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA +1A17..1A18 ; Other_Alphabetic # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U +1A19..1A1A ; Other_Alphabetic # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O +1A1B ; Other_Alphabetic # Mn BUGINESE VOWEL SIGN AE +1A55 ; Other_Alphabetic # Mc TAI THAM CONSONANT SIGN MEDIAL RA +1A56 ; Other_Alphabetic # Mn TAI THAM CONSONANT SIGN MEDIAL LA +1A57 ; Other_Alphabetic # Mc TAI THAM CONSONANT SIGN LA TANG LAI +1A58..1A5E ; Other_Alphabetic # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA +1A61 ; Other_Alphabetic # Mc TAI THAM VOWEL SIGN A +1A62 ; Other_Alphabetic # Mn TAI THAM VOWEL SIGN MAI SAT +1A63..1A64 ; Other_Alphabetic # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA +1A65..1A6C ; Other_Alphabetic # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW +1A6D..1A72 ; Other_Alphabetic # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI +1A73..1A74 ; Other_Alphabetic # Mn [2] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN MAI KANG +1ABF..1AC0 ; Other_Alphabetic # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW +1ACC..1ACE ; Other_Alphabetic # Mn [3] COMBINING LATIN SMALL LETTER INSULAR G..COMBINING LATIN SMALL LETTER INSULAR T +1B00..1B03 ; Other_Alphabetic # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG +1B04 ; Other_Alphabetic # Mc BALINESE SIGN BISAH +1B35 ; Other_Alphabetic # Mc BALINESE VOWEL SIGN TEDUNG +1B36..1B3A ; Other_Alphabetic # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA +1B3B ; Other_Alphabetic # Mc BALINESE VOWEL SIGN RA REPA TEDUNG +1B3C ; Other_Alphabetic # Mn BALINESE VOWEL SIGN LA LENGA +1B3D..1B41 ; Other_Alphabetic # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG +1B42 ; Other_Alphabetic # Mn BALINESE VOWEL SIGN PEPET +1B43 ; Other_Alphabetic # Mc BALINESE VOWEL SIGN PEPET TEDUNG +1B80..1B81 ; Other_Alphabetic # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR +1B82 ; Other_Alphabetic # Mc SUNDANESE SIGN PANGWISAD +1BA1 ; Other_Alphabetic # Mc SUNDANESE CONSONANT SIGN PAMINGKAL +1BA2..1BA5 ; Other_Alphabetic # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU +1BA6..1BA7 ; Other_Alphabetic # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG +1BA8..1BA9 ; Other_Alphabetic # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG +1BAC..1BAD ; Other_Alphabetic # Mn [2] SUNDANESE CONSONANT SIGN PASANGAN MA..SUNDANESE CONSONANT SIGN PASANGAN WA +1BE7 ; Other_Alphabetic # Mc BATAK VOWEL SIGN E +1BE8..1BE9 ; Other_Alphabetic # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE +1BEA..1BEC ; Other_Alphabetic # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O +1BED ; Other_Alphabetic # Mn BATAK VOWEL SIGN KARO O +1BEE ; Other_Alphabetic # Mc BATAK VOWEL SIGN U +1BEF..1BF1 ; Other_Alphabetic # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H +1C24..1C2B ; Other_Alphabetic # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU +1C2C..1C33 ; Other_Alphabetic # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T +1C34..1C35 ; Other_Alphabetic # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG +1C36 ; Other_Alphabetic # Mn LEPCHA SIGN RAN +1DD3..1DF4 ; Other_Alphabetic # Mn [34] COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE..COMBINING LATIN SMALL LETTER U WITH DIAERESIS +24B6..24E9 ; Other_Alphabetic # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z +2DE0..2DFF ; Other_Alphabetic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS +A674..A67B ; Other_Alphabetic # Mn [8] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC LETTER OMEGA +A69E..A69F ; Other_Alphabetic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E +A802 ; Other_Alphabetic # Mn SYLOTI NAGRI SIGN DVISVARA +A80B ; Other_Alphabetic # Mn SYLOTI NAGRI SIGN ANUSVARA +A823..A824 ; Other_Alphabetic # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I +A825..A826 ; Other_Alphabetic # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E +A827 ; Other_Alphabetic # Mc SYLOTI NAGRI VOWEL SIGN OO +A880..A881 ; Other_Alphabetic # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA +A8B4..A8C3 ; Other_Alphabetic # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU +A8C5 ; Other_Alphabetic # Mn SAURASHTRA SIGN CANDRABINDU +A8FF ; Other_Alphabetic # Mn DEVANAGARI VOWEL SIGN AY +A926..A92A ; Other_Alphabetic # Mn [5] KAYAH LI VOWEL UE..KAYAH LI VOWEL O +A947..A951 ; Other_Alphabetic # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R +A952 ; Other_Alphabetic # Mc REJANG CONSONANT SIGN H +A980..A982 ; Other_Alphabetic # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR +A983 ; Other_Alphabetic # Mc JAVANESE SIGN WIGNYAN +A9B4..A9B5 ; Other_Alphabetic # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG +A9B6..A9B9 ; Other_Alphabetic # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT +A9BA..A9BB ; Other_Alphabetic # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE +A9BC..A9BD ; Other_Alphabetic # Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET +A9BE..A9BF ; Other_Alphabetic # Mc [2] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE CONSONANT SIGN CAKRA +A9E5 ; Other_Alphabetic # Mn MYANMAR SIGN SHAN SAW +AA29..AA2E ; Other_Alphabetic # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE +AA2F..AA30 ; Other_Alphabetic # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI +AA31..AA32 ; Other_Alphabetic # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE +AA33..AA34 ; Other_Alphabetic # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA +AA35..AA36 ; Other_Alphabetic # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA +AA43 ; Other_Alphabetic # Mn CHAM CONSONANT SIGN FINAL NG +AA4C ; Other_Alphabetic # Mn CHAM CONSONANT SIGN FINAL M +AA4D ; Other_Alphabetic # Mc CHAM CONSONANT SIGN FINAL H +AA7B ; Other_Alphabetic # Mc MYANMAR SIGN PAO KAREN TONE +AA7C ; Other_Alphabetic # Mn MYANMAR SIGN TAI LAING TONE-2 +AA7D ; Other_Alphabetic # Mc MYANMAR SIGN TAI LAING TONE-5 +AAB0 ; Other_Alphabetic # Mn TAI VIET MAI KANG +AAB2..AAB4 ; Other_Alphabetic # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U +AAB7..AAB8 ; Other_Alphabetic # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA +AABE ; Other_Alphabetic # Mn TAI VIET VOWEL AM +AAEB ; Other_Alphabetic # Mc MEETEI MAYEK VOWEL SIGN II +AAEC..AAED ; Other_Alphabetic # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI +AAEE..AAEF ; Other_Alphabetic # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU +AAF5 ; Other_Alphabetic # Mc MEETEI MAYEK VOWEL SIGN VISARGA +ABE3..ABE4 ; Other_Alphabetic # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP +ABE5 ; Other_Alphabetic # Mn MEETEI MAYEK VOWEL SIGN ANAP +ABE6..ABE7 ; Other_Alphabetic # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP +ABE8 ; Other_Alphabetic # Mn MEETEI MAYEK VOWEL SIGN UNAP +ABE9..ABEA ; Other_Alphabetic # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG +FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA +10376..1037A ; Other_Alphabetic # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII +10A01..10A03 ; Other_Alphabetic # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R +10A05..10A06 ; Other_Alphabetic # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O +10A0C..10A0F ; Other_Alphabetic # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA +10D24..10D27 ; Other_Alphabetic # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI +10D69 ; Other_Alphabetic # Mn GARAY VOWEL SIGN E +10EAB..10EAC ; Other_Alphabetic # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK +10EFA..10EFC ; Other_Alphabetic # Mn [3] ARABIC DOUBLE VERTICAL BAR BELOW..ARABIC COMBINING ALEF OVERLAY +11000 ; Other_Alphabetic # Mc BRAHMI SIGN CANDRABINDU +11001 ; Other_Alphabetic # Mn BRAHMI SIGN ANUSVARA +11002 ; Other_Alphabetic # Mc BRAHMI SIGN VISARGA +11038..11045 ; Other_Alphabetic # Mn [14] BRAHMI VOWEL SIGN AA..BRAHMI VOWEL SIGN AU +11073..11074 ; Other_Alphabetic # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O +11080..11081 ; Other_Alphabetic # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA +11082 ; Other_Alphabetic # Mc KAITHI SIGN VISARGA +110B0..110B2 ; Other_Alphabetic # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II +110B3..110B6 ; Other_Alphabetic # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI +110B7..110B8 ; Other_Alphabetic # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU +110C2 ; Other_Alphabetic # Mn KAITHI VOWEL SIGN VOCALIC R +11100..11102 ; Other_Alphabetic # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA +11127..1112B ; Other_Alphabetic # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU +1112C ; Other_Alphabetic # Mc CHAKMA VOWEL SIGN E +1112D..11132 ; Other_Alphabetic # Mn [6] CHAKMA VOWEL SIGN AI..CHAKMA AU MARK +11145..11146 ; Other_Alphabetic # Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI +11180..11181 ; Other_Alphabetic # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA +11182 ; Other_Alphabetic # Mc SHARADA SIGN VISARGA +111B3..111B5 ; Other_Alphabetic # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II +111B6..111BE ; Other_Alphabetic # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O +111BF ; Other_Alphabetic # Mc SHARADA VOWEL SIGN AU +111CE ; Other_Alphabetic # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E +111CF ; Other_Alphabetic # Mn SHARADA SIGN INVERTED CANDRABINDU +1122C..1122E ; Other_Alphabetic # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II +1122F..11231 ; Other_Alphabetic # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI +11232..11233 ; Other_Alphabetic # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU +11234 ; Other_Alphabetic # Mn KHOJKI SIGN ANUSVARA +11237 ; Other_Alphabetic # Mn KHOJKI SIGN SHADDA +1123E ; Other_Alphabetic # Mn KHOJKI SIGN SUKUN +11241 ; Other_Alphabetic # Mn KHOJKI VOWEL SIGN VOCALIC R +112DF ; Other_Alphabetic # Mn KHUDAWADI SIGN ANUSVARA +112E0..112E2 ; Other_Alphabetic # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II +112E3..112E8 ; Other_Alphabetic # Mn [6] KHUDAWADI VOWEL SIGN U..KHUDAWADI VOWEL SIGN AU +11300..11301 ; Other_Alphabetic # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU +11302..11303 ; Other_Alphabetic # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA +1133E..1133F ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I +11340 ; Other_Alphabetic # Mn GRANTHA VOWEL SIGN II +11341..11344 ; Other_Alphabetic # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR +11347..11348 ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI +1134B..1134C ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN OO..GRANTHA VOWEL SIGN AU +11357 ; Other_Alphabetic # Mc GRANTHA AU LENGTH MARK +11362..11363 ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL +113B8..113BA ; Other_Alphabetic # Mc [3] TULU-TIGALARI VOWEL SIGN AA..TULU-TIGALARI VOWEL SIGN II +113BB..113C0 ; Other_Alphabetic # Mn [6] TULU-TIGALARI VOWEL SIGN U..TULU-TIGALARI VOWEL SIGN VOCALIC LL +113C2 ; Other_Alphabetic # Mc TULU-TIGALARI VOWEL SIGN EE +113C5 ; Other_Alphabetic # Mc TULU-TIGALARI VOWEL SIGN AI +113C7..113CA ; Other_Alphabetic # Mc [4] TULU-TIGALARI VOWEL SIGN OO..TULU-TIGALARI SIGN CANDRA ANUNASIKA +113CC..113CD ; Other_Alphabetic # Mc [2] TULU-TIGALARI SIGN ANUSVARA..TULU-TIGALARI SIGN VISARGA +11435..11437 ; Other_Alphabetic # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II +11438..1143F ; Other_Alphabetic # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI +11440..11441 ; Other_Alphabetic # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU +11443..11444 ; Other_Alphabetic # Mn [2] NEWA SIGN CANDRABINDU..NEWA SIGN ANUSVARA +11445 ; Other_Alphabetic # Mc NEWA SIGN VISARGA +114B0..114B2 ; Other_Alphabetic # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II +114B3..114B8 ; Other_Alphabetic # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL +114B9 ; Other_Alphabetic # Mc TIRHUTA VOWEL SIGN E +114BA ; Other_Alphabetic # Mn TIRHUTA VOWEL SIGN SHORT E +114BB..114BE ; Other_Alphabetic # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU +114BF..114C0 ; Other_Alphabetic # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA +114C1 ; Other_Alphabetic # Mc TIRHUTA SIGN VISARGA +115AF..115B1 ; Other_Alphabetic # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II +115B2..115B5 ; Other_Alphabetic # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR +115B8..115BB ; Other_Alphabetic # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU +115BC..115BD ; Other_Alphabetic # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA +115BE ; Other_Alphabetic # Mc SIDDHAM SIGN VISARGA +115DC..115DD ; Other_Alphabetic # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU +11630..11632 ; Other_Alphabetic # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II +11633..1163A ; Other_Alphabetic # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI +1163B..1163C ; Other_Alphabetic # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU +1163D ; Other_Alphabetic # Mn MODI SIGN ANUSVARA +1163E ; Other_Alphabetic # Mc MODI SIGN VISARGA +11640 ; Other_Alphabetic # Mn MODI SIGN ARDHACANDRA +116AB ; Other_Alphabetic # Mn TAKRI SIGN ANUSVARA +116AC ; Other_Alphabetic # Mc TAKRI SIGN VISARGA +116AD ; Other_Alphabetic # Mn TAKRI VOWEL SIGN AA +116AE..116AF ; Other_Alphabetic # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II +116B0..116B5 ; Other_Alphabetic # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU +1171D ; Other_Alphabetic # Mn AHOM CONSONANT SIGN MEDIAL LA +1171E ; Other_Alphabetic # Mc AHOM CONSONANT SIGN MEDIAL RA +1171F ; Other_Alphabetic # Mn AHOM CONSONANT SIGN MEDIAL LIGATING RA +11720..11721 ; Other_Alphabetic # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA +11722..11725 ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU +11726 ; Other_Alphabetic # Mc AHOM VOWEL SIGN E +11727..1172A ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM +1182C..1182E ; Other_Alphabetic # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II +1182F..11837 ; Other_Alphabetic # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA +11838 ; Other_Alphabetic # Mc DOGRA SIGN VISARGA +11930..11935 ; Other_Alphabetic # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E +11937..11938 ; Other_Alphabetic # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O +1193B..1193C ; Other_Alphabetic # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU +11940 ; Other_Alphabetic # Mc DIVES AKURU MEDIAL YA +11942 ; Other_Alphabetic # Mc DIVES AKURU MEDIAL RA +119D1..119D3 ; Other_Alphabetic # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II +119D4..119D7 ; Other_Alphabetic # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR +119DA..119DB ; Other_Alphabetic # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI +119DC..119DF ; Other_Alphabetic # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA +119E4 ; Other_Alphabetic # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E +11A01..11A0A ; Other_Alphabetic # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK +11A35..11A38 ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE SIGN CANDRABINDU..ZANABAZAR SQUARE SIGN ANUSVARA +11A39 ; Other_Alphabetic # Mc ZANABAZAR SQUARE SIGN VISARGA +11A3B..11A3E ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA +11A51..11A56 ; Other_Alphabetic # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE +11A57..11A58 ; Other_Alphabetic # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU +11A59..11A5B ; Other_Alphabetic # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK +11A8A..11A96 ; Other_Alphabetic # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA +11A97 ; Other_Alphabetic # Mc SOYOMBO SIGN VISARGA +11B60 ; Other_Alphabetic # Mn SHARADA VOWEL SIGN OE +11B61 ; Other_Alphabetic # Mc SHARADA VOWEL SIGN OOE +11B62..11B64 ; Other_Alphabetic # Mn [3] SHARADA VOWEL SIGN UE..SHARADA VOWEL SIGN SHORT E +11B65 ; Other_Alphabetic # Mc SHARADA VOWEL SIGN SHORT O +11B66 ; Other_Alphabetic # Mn SHARADA VOWEL SIGN CANDRA E +11B67 ; Other_Alphabetic # Mc SHARADA VOWEL SIGN CANDRA O +11C2F ; Other_Alphabetic # Mc BHAIKSUKI VOWEL SIGN AA +11C30..11C36 ; Other_Alphabetic # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L +11C38..11C3D ; Other_Alphabetic # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA +11C3E ; Other_Alphabetic # Mc BHAIKSUKI SIGN VISARGA +11C92..11CA7 ; Other_Alphabetic # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA +11CA9 ; Other_Alphabetic # Mc MARCHEN SUBJOINED LETTER YA +11CAA..11CB0 ; Other_Alphabetic # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA +11CB1 ; Other_Alphabetic # Mc MARCHEN VOWEL SIGN I +11CB2..11CB3 ; Other_Alphabetic # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E +11CB4 ; Other_Alphabetic # Mc MARCHEN VOWEL SIGN O +11CB5..11CB6 ; Other_Alphabetic # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU +11D31..11D36 ; Other_Alphabetic # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R +11D3A ; Other_Alphabetic # Mn MASARAM GONDI VOWEL SIGN E +11D3C..11D3D ; Other_Alphabetic # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O +11D3F..11D41 ; Other_Alphabetic # Mn [3] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI SIGN VISARGA +11D43 ; Other_Alphabetic # Mn MASARAM GONDI SIGN CANDRA +11D47 ; Other_Alphabetic # Mn MASARAM GONDI RA-KARA +11D8A..11D8E ; Other_Alphabetic # Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU +11D90..11D91 ; Other_Alphabetic # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI +11D93..11D94 ; Other_Alphabetic # Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU +11D95 ; Other_Alphabetic # Mn GUNJALA GONDI SIGN ANUSVARA +11D96 ; Other_Alphabetic # Mc GUNJALA GONDI SIGN VISARGA +11EF3..11EF4 ; Other_Alphabetic # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U +11EF5..11EF6 ; Other_Alphabetic # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O +11F00..11F01 ; Other_Alphabetic # Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA +11F03 ; Other_Alphabetic # Mc KAWI SIGN VISARGA +11F34..11F35 ; Other_Alphabetic # Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA +11F36..11F3A ; Other_Alphabetic # Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R +11F3E..11F3F ; Other_Alphabetic # Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI +11F40 ; Other_Alphabetic # Mn KAWI VOWEL SIGN EU +1611E..16129 ; Other_Alphabetic # Mn [12] GURUNG KHEMA VOWEL SIGN AA..GURUNG KHEMA VOWEL LENGTH MARK +1612A..1612C ; Other_Alphabetic # Mc [3] GURUNG KHEMA CONSONANT SIGN MEDIAL YA..GURUNG KHEMA CONSONANT SIGN MEDIAL HA +1612D..1612E ; Other_Alphabetic # Mn [2] GURUNG KHEMA SIGN ANUSVARA..GURUNG KHEMA CONSONANT SIGN MEDIAL RA +16F4F ; Other_Alphabetic # Mn MIAO SIGN CONSONANT MODIFIER BAR +16F51..16F87 ; Other_Alphabetic # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI +16F8F..16F92 ; Other_Alphabetic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW +16FF0..16FF1 ; Other_Alphabetic # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY +1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK +1E000..1E006 ; Other_Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE +1E008..1E018 ; Other_Alphabetic # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU +1E01B..1E021 ; Other_Alphabetic # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI +1E023..1E024 ; Other_Alphabetic # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS +1E026..1E02A ; Other_Alphabetic # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA +1E08F ; Other_Alphabetic # Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +1E6E3 ; Other_Alphabetic # Mn TAI YO SIGN UE +1E6E6 ; Other_Alphabetic # Mn TAI YO SIGN AU +1E6EE..1E6EF ; Other_Alphabetic # Mn [2] TAI YO SIGN AY..TAI YO SIGN ANG +1E6F5 ; Other_Alphabetic # Mn TAI YO SIGN OM +1E947 ; Other_Alphabetic # Mn ADLAM HAMZA +1F130..1F149 ; Other_Alphabetic # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z +1F150..1F169 ; Other_Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z +1F170..1F189 ; Other_Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z + +# Total code points: 1510 + +# ================================================ + +3006 ; Ideographic # Lo IDEOGRAPHIC CLOSING MARK +3007 ; Ideographic # Nl IDEOGRAPHIC NUMBER ZERO +3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE +3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY +3400..4DBF ; Ideographic # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF +4E00..9FFF ; Ideographic # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF +F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D +FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 +16FE4 ; Ideographic # Mn KHITAN SMALL SCRIPT FILLER +16FF2..16FF3 ; Ideographic # Lm [2] CHINESE SMALL SIMPLIFIED ER..CHINESE SMALL TRADITIONAL ER +16FF4..16FF6 ; Ideographic # Nl [3] YANGQIN SIGN SLOW ONE BEAT..YANGQIN SIGN SLOW TWO BEATS +17000..18CD5 ; Ideographic # Lo [7382] TANGUT IDEOGRAPH-17000..KHITAN SMALL SCRIPT CHARACTER-18CD5 +18CFF..18D1E ; Ideographic # Lo [32] KHITAN SMALL SCRIPT CHARACTER-18CFF..TANGUT IDEOGRAPH-18D1E +18D80..18DF2 ; Ideographic # Lo [115] TANGUT COMPONENT-769..TANGUT COMPONENT-883 +1B170..1B2FB ; Ideographic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB +20000..2A6DF ; Ideographic # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B81D ; Ideographic # Lo [4382] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B81D +2B820..2CEAD ; Ideographic # Lo [5774] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEAD +2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 +2EBF0..2EE5D ; Ideographic # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D +2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D +30000..3134A ; Ideographic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A +31350..33479 ; Ideographic # Lo [8490] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-33479 + +# Total code points: 110943 + +# ================================================ + +005E ; Diacritic # Sk CIRCUMFLEX ACCENT +0060 ; Diacritic # Sk GRAVE ACCENT +00A8 ; Diacritic # Sk DIAERESIS +00AF ; Diacritic # Sk MACRON +00B4 ; Diacritic # Sk ACUTE ACCENT +00B7 ; Diacritic # Po MIDDLE DOT +00B8 ; Diacritic # Sk CEDILLA +02B0..02C1 ; Diacritic # Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP +02C2..02C5 ; Diacritic # Sk [4] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD +02C6..02D1 ; Diacritic # Lm [12] MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON +02D2..02DF ; Diacritic # Sk [14] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER CROSS ACCENT +02E0..02E4 ; Diacritic # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP +02E5..02EB ; Diacritic # Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK +02EC ; Diacritic # Lm MODIFIER LETTER VOICING +02ED ; Diacritic # Sk MODIFIER LETTER UNASPIRATED +02EE ; Diacritic # Lm MODIFIER LETTER DOUBLE APOSTROPHE +02EF..02FF ; Diacritic # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW +0300..034E ; Diacritic # Mn [79] COMBINING GRAVE ACCENT..COMBINING UPWARDS ARROW BELOW +0350..0357 ; Diacritic # Mn [8] COMBINING RIGHT ARROWHEAD ABOVE..COMBINING RIGHT HALF RING ABOVE +035D..0362 ; Diacritic # Mn [6] COMBINING DOUBLE BREVE..COMBINING DOUBLE RIGHTWARDS ARROW BELOW +0374 ; Diacritic # Lm GREEK NUMERAL SIGN +0375 ; Diacritic # Sk GREEK LOWER NUMERAL SIGN +037A ; Diacritic # Lm GREEK YPOGEGRAMMENI +0384..0385 ; Diacritic # Sk [2] GREEK TONOS..GREEK DIALYTIKA TONOS +0483..0487 ; Diacritic # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE +0559 ; Diacritic # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING +0591..05BD ; Diacritic # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG +05BF ; Diacritic # Mn HEBREW POINT RAFE +05C1..05C2 ; Diacritic # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT +05C4..05C5 ; Diacritic # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT +05C7 ; Diacritic # Mn HEBREW POINT QAMATS QATAN +064B..0652 ; Diacritic # Mn [8] ARABIC FATHATAN..ARABIC SUKUN +0657..0658 ; Diacritic # Mn [2] ARABIC INVERTED DAMMA..ARABIC MARK NOON GHUNNA +06DF..06E0 ; Diacritic # Mn [2] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO +06E5..06E6 ; Diacritic # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH +06EA..06EC ; Diacritic # Mn [3] ARABIC EMPTY CENTRE LOW STOP..ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE +0730..074A ; Diacritic # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH +07A6..07B0 ; Diacritic # Mn [11] THAANA ABAFILI..THAANA SUKUN +07EB..07F3 ; Diacritic # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE +07F4..07F5 ; Diacritic # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE +0818..0819 ; Diacritic # Mn [2] SAMARITAN MARK OCCLUSION..SAMARITAN MARK DAGESH +0898..089F ; Diacritic # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA +08C9 ; Diacritic # Lm ARABIC SMALL FARSI YEH +08CA..08D2 ; Diacritic # Mn [9] ARABIC SMALL HIGH FARSI YEH..ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW +08E3..08FE ; Diacritic # Mn [28] ARABIC TURNED DAMMA BELOW..ARABIC DAMMA WITH DOT +093C ; Diacritic # Mn DEVANAGARI SIGN NUKTA +094D ; Diacritic # Mn DEVANAGARI SIGN VIRAMA +0951..0954 ; Diacritic # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT +0971 ; Diacritic # Lm DEVANAGARI SIGN HIGH SPACING DOT +09BC ; Diacritic # Mn BENGALI SIGN NUKTA +09CD ; Diacritic # Mn BENGALI SIGN VIRAMA +0A3C ; Diacritic # Mn GURMUKHI SIGN NUKTA +0A4D ; Diacritic # Mn GURMUKHI SIGN VIRAMA +0ABC ; Diacritic # Mn GUJARATI SIGN NUKTA +0ACD ; Diacritic # Mn GUJARATI SIGN VIRAMA +0AFD..0AFF ; Diacritic # Mn [3] GUJARATI SIGN THREE-DOT NUKTA ABOVE..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE +0B3C ; Diacritic # Mn ORIYA SIGN NUKTA +0B4D ; Diacritic # Mn ORIYA SIGN VIRAMA +0B55 ; Diacritic # Mn ORIYA SIGN OVERLINE +0BCD ; Diacritic # Mn TAMIL SIGN VIRAMA +0C3C ; Diacritic # Mn TELUGU SIGN NUKTA +0C4D ; Diacritic # Mn TELUGU SIGN VIRAMA +0CBC ; Diacritic # Mn KANNADA SIGN NUKTA +0CCD ; Diacritic # Mn KANNADA SIGN VIRAMA +0D3B..0D3C ; Diacritic # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA +0D4D ; Diacritic # Mn MALAYALAM SIGN VIRAMA +0DCA ; Diacritic # Mn SINHALA SIGN AL-LAKUNA +0E3A ; Diacritic # Mn THAI CHARACTER PHINTHU +0E47..0E4C ; Diacritic # Mn [6] THAI CHARACTER MAITAIKHU..THAI CHARACTER THANTHAKHAT +0E4E ; Diacritic # Mn THAI CHARACTER YAMAKKAN +0EBA ; Diacritic # Mn LAO SIGN PALI VIRAMA +0EC8..0ECC ; Diacritic # Mn [5] LAO TONE MAI EK..LAO CANCELLATION MARK +0F18..0F19 ; Diacritic # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS +0F35 ; Diacritic # Mn TIBETAN MARK NGAS BZUNG NYI ZLA +0F37 ; Diacritic # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS +0F39 ; Diacritic # Mn TIBETAN MARK TSA -PHRU +0F3E..0F3F ; Diacritic # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES +0F82..0F84 ; Diacritic # Mn [3] TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HALANTA +0F86..0F87 ; Diacritic # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS +0FC6 ; Diacritic # Mn TIBETAN SYMBOL PADMA GDAN +1037 ; Diacritic # Mn MYANMAR SIGN DOT BELOW +1039..103A ; Diacritic # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT +1063..1064 ; Diacritic # Mc [2] MYANMAR TONE MARK SGAW KAREN HATHI..MYANMAR TONE MARK SGAW KAREN KE PHO +1069..106D ; Diacritic # Mc [5] MYANMAR SIGN WESTERN PWO KAREN TONE-1..MYANMAR SIGN WESTERN PWO KAREN TONE-5 +1087..108C ; Diacritic # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3 +108D ; Diacritic # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE +108F ; Diacritic # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5 +109A..109B ; Diacritic # Mc [2] MYANMAR SIGN KHAMTI TONE-1..MYANMAR SIGN KHAMTI TONE-3 +135D..135F ; Diacritic # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK +1714 ; Diacritic # Mn TAGALOG SIGN VIRAMA +1715 ; Diacritic # Mc TAGALOG SIGN PAMUDPOD +1734 ; Diacritic # Mc HANUNOO SIGN PAMUDPOD +17C9..17D3 ; Diacritic # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT +17DD ; Diacritic # Mn KHMER SIGN ATTHACAN +1939..193B ; Diacritic # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I +1A60 ; Diacritic # Mn TAI THAM SIGN SAKOT +1A75..1A7C ; Diacritic # Mn [8] TAI THAM SIGN TONE-1..TAI THAM SIGN KHUEN-LUE KARAN +1A7F ; Diacritic # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT +1AB0..1ABD ; Diacritic # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW +1ABE ; Diacritic # Me COMBINING PARENTHESES OVERLAY +1AC1..1ACB ; Diacritic # Mn [11] COMBINING LEFT PARENTHESIS ABOVE LEFT..COMBINING TRIPLE ACUTE ACCENT +1ACF..1ADD ; Diacritic # Mn [15] COMBINING DOUBLE CARON..COMBINING DOT-AND-RING BELOW +1AE0..1AEB ; Diacritic # Mn [12] COMBINING LEFT TACK ABOVE..COMBINING DOUBLE RIGHTWARDS ARROW ABOVE +1B34 ; Diacritic # Mn BALINESE SIGN REREKAN +1B44 ; Diacritic # Mc BALINESE ADEG ADEG +1B6B..1B73 ; Diacritic # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG +1BAA ; Diacritic # Mc SUNDANESE SIGN PAMAAEH +1BAB ; Diacritic # Mn SUNDANESE SIGN VIRAMA +1BE6 ; Diacritic # Mn BATAK SIGN TOMPI +1BF2..1BF3 ; Diacritic # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN +1C36..1C37 ; Diacritic # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA +1C78..1C7D ; Diacritic # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD +1CD0..1CD2 ; Diacritic # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA +1CD3 ; Diacritic # Po VEDIC SIGN NIHSHVASA +1CD4..1CE0 ; Diacritic # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA +1CE1 ; Diacritic # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA +1CE2..1CE8 ; Diacritic # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL +1CED ; Diacritic # Mn VEDIC SIGN TIRYAK +1CF4 ; Diacritic # Mn VEDIC TONE CANDRA ABOVE +1CF7 ; Diacritic # Mc VEDIC SIGN ATIKRAMA +1CF8..1CF9 ; Diacritic # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE +1D2C..1D6A ; Diacritic # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI +1D9B..1DBE ; Diacritic # Lm [36] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL EZH +1DC4..1DCF ; Diacritic # Mn [12] COMBINING MACRON-ACUTE..COMBINING ZIGZAG BELOW +1DF5..1DFF ; Diacritic # Mn [11] COMBINING UP TACK ABOVE..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW +1FBD ; Diacritic # Sk GREEK KORONIS +1FBF..1FC1 ; Diacritic # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI +1FCD..1FCF ; Diacritic # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI +1FDD..1FDF ; Diacritic # Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI +1FED..1FEF ; Diacritic # Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA +1FFD..1FFE ; Diacritic # Sk [2] GREEK OXIA..GREEK DASIA +2CEF..2CF1 ; Diacritic # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS +2E2F ; Diacritic # Lm VERTICAL TILDE +302A..302D ; Diacritic # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK +302E..302F ; Diacritic # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK +3099..309A ; Diacritic # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +309B..309C ; Diacritic # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +30FC ; Diacritic # Lm KATAKANA-HIRAGANA PROLONGED SOUND MARK +A66F ; Diacritic # Mn COMBINING CYRILLIC VZMET +A67C..A67D ; Diacritic # Mn [2] COMBINING CYRILLIC KAVYKA..COMBINING CYRILLIC PAYEROK +A67F ; Diacritic # Lm CYRILLIC PAYEROK +A69C..A69D ; Diacritic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN +A6F0..A6F1 ; Diacritic # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS +A700..A716 ; Diacritic # Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR +A717..A71F ; Diacritic # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK +A720..A721 ; Diacritic # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE +A788 ; Diacritic # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT +A789..A78A ; Diacritic # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN +A7F1 ; Diacritic # Lm MODIFIER LETTER CAPITAL S +A7F8..A7F9 ; Diacritic # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE +A806 ; Diacritic # Mn SYLOTI NAGRI SIGN HASANTA +A82C ; Diacritic # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA +A8C4 ; Diacritic # Mn SAURASHTRA SIGN VIRAMA +A8E0..A8F1 ; Diacritic # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA +A92B..A92D ; Diacritic # Mn [3] KAYAH LI TONE PLOPHU..KAYAH LI TONE CALYA PLOPHU +A92E ; Diacritic # Po KAYAH LI SIGN CWI +A953 ; Diacritic # Mc REJANG VIRAMA +A9B3 ; Diacritic # Mn JAVANESE SIGN CECAK TELU +A9C0 ; Diacritic # Mc JAVANESE PANGKON +A9E5 ; Diacritic # Mn MYANMAR SIGN SHAN SAW +AA7B ; Diacritic # Mc MYANMAR SIGN PAO KAREN TONE +AA7C ; Diacritic # Mn MYANMAR SIGN TAI LAING TONE-2 +AA7D ; Diacritic # Mc MYANMAR SIGN TAI LAING TONE-5 +AABF ; Diacritic # Mn TAI VIET TONE MAI EK +AAC0 ; Diacritic # Lo TAI VIET TONE MAI NUENG +AAC1 ; Diacritic # Mn TAI VIET TONE MAI THO +AAC2 ; Diacritic # Lo TAI VIET TONE MAI SONG +AAF6 ; Diacritic # Mn MEETEI MAYEK VIRAMA +AB5B ; Diacritic # Sk MODIFIER BREVE WITH INVERTED BREVE +AB5C..AB5F ; Diacritic # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK +AB69 ; Diacritic # Lm MODIFIER LETTER SMALL TURNED W +AB6A..AB6B ; Diacritic # Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK +ABEC ; Diacritic # Mc MEETEI MAYEK LUM IYEK +ABED ; Diacritic # Mn MEETEI MAYEK APUN IYEK +FB1E ; Diacritic # Mn HEBREW POINT JUDEO-SPANISH VARIKA +FE20..FE2F ; Diacritic # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF +FF3E ; Diacritic # Sk FULLWIDTH CIRCUMFLEX ACCENT +FF40 ; Diacritic # Sk FULLWIDTH GRAVE ACCENT +FF70 ; Diacritic # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK +FF9E..FF9F ; Diacritic # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +FFE3 ; Diacritic # Sk FULLWIDTH MACRON +102E0 ; Diacritic # Mn COPTIC EPACT THOUSANDS MARK +10780..10785 ; Diacritic # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Diacritic # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Diacritic # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL +10A38..10A3A ; Diacritic # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW +10A3F ; Diacritic # Mn KHAROSHTHI VIRAMA +10AE5..10AE6 ; Diacritic # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW +10D22..10D23 ; Diacritic # Lo [2] HANIFI ROHINGYA MARK SAKIN..HANIFI ROHINGYA MARK NA KHONNA +10D24..10D27 ; Diacritic # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI +10D4E ; Diacritic # Lm GARAY VOWEL LENGTH MARK +10D69..10D6D ; Diacritic # Mn [5] GARAY VOWEL SIGN E..GARAY CONSONANT NASALIZATION MARK +10EFA ; Diacritic # Mn ARABIC DOUBLE VERTICAL BAR BELOW +10EFD..10EFF ; Diacritic # Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA +10F46..10F50 ; Diacritic # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW +10F82..10F85 ; Diacritic # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW +11046 ; Diacritic # Mn BRAHMI VIRAMA +11070 ; Diacritic # Mn BRAHMI SIGN OLD TAMIL VIRAMA +110B9..110BA ; Diacritic # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA +11133..11134 ; Diacritic # Mn [2] CHAKMA VIRAMA..CHAKMA MAAYYAA +11173 ; Diacritic # Mn MAHAJANI SIGN NUKTA +111C0 ; Diacritic # Mc SHARADA SIGN VIRAMA +111CA..111CC ; Diacritic # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK +11235 ; Diacritic # Mc KHOJKI SIGN VIRAMA +11236 ; Diacritic # Mn KHOJKI SIGN NUKTA +112E9..112EA ; Diacritic # Mn [2] KHUDAWADI SIGN NUKTA..KHUDAWADI SIGN VIRAMA +1133B..1133C ; Diacritic # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA +1134D ; Diacritic # Mc GRANTHA SIGN VIRAMA +11366..1136C ; Diacritic # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX +11370..11374 ; Diacritic # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA +113CE ; Diacritic # Mn TULU-TIGALARI SIGN VIRAMA +113CF ; Diacritic # Mc TULU-TIGALARI SIGN LOOPED VIRAMA +113D0 ; Diacritic # Mn TULU-TIGALARI CONJOINER +113D2 ; Diacritic # Mn TULU-TIGALARI GEMINATION MARK +113D3 ; Diacritic # Lo TULU-TIGALARI SIGN PLUTA +113E1..113E2 ; Diacritic # Mn [2] TULU-TIGALARI VEDIC TONE SVARITA..TULU-TIGALARI VEDIC TONE ANUDATTA +11442 ; Diacritic # Mn NEWA SIGN VIRAMA +11446 ; Diacritic # Mn NEWA SIGN NUKTA +114C2..114C3 ; Diacritic # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA +115BF..115C0 ; Diacritic # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA +1163F ; Diacritic # Mn MODI SIGN VIRAMA +116B6 ; Diacritic # Mc TAKRI SIGN VIRAMA +116B7 ; Diacritic # Mn TAKRI SIGN NUKTA +1172B ; Diacritic # Mn AHOM SIGN KILLER +11839..1183A ; Diacritic # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA +1193D ; Diacritic # Mc DIVES AKURU SIGN HALANTA +1193E ; Diacritic # Mn DIVES AKURU VIRAMA +11943 ; Diacritic # Mn DIVES AKURU SIGN NUKTA +119E0 ; Diacritic # Mn NANDINAGARI SIGN VIRAMA +11A34 ; Diacritic # Mn ZANABAZAR SQUARE SIGN VIRAMA +11A47 ; Diacritic # Mn ZANABAZAR SQUARE SUBJOINER +11A99 ; Diacritic # Mn SOYOMBO SUBJOINER +11C3F ; Diacritic # Mn BHAIKSUKI SIGN VIRAMA +11D42 ; Diacritic # Mn MASARAM GONDI SIGN NUKTA +11D44..11D45 ; Diacritic # Mn [2] MASARAM GONDI SIGN HALANTA..MASARAM GONDI VIRAMA +11D97 ; Diacritic # Mn GUNJALA GONDI VIRAMA +11DD9 ; Diacritic # Lm TOLONG SIKI SIGN SELA +11F41 ; Diacritic # Mc KAWI SIGN KILLER +11F42 ; Diacritic # Mn KAWI CONJOINER +11F5A ; Diacritic # Mn KAWI SIGN NUKTA +13447..13455 ; Diacritic # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED +1612F ; Diacritic # Mn GURUNG KHEMA SIGN THOLHOMA +16AF0..16AF4 ; Diacritic # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE +16B30..16B36 ; Diacritic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM +16D6B..16D6C ; Diacritic # Lm [2] KIRAT RAI SIGN VIRAMA..KIRAT RAI SIGN SAAT +16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW +16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8 +16FF0..16FF1 ; Diacritic # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY +1AFF0..1AFF3 ; Diacritic # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5 +1AFF5..1AFFB ; Diacritic # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 +1AFFD..1AFFE ; Diacritic # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 +1CF00..1CF2D ; Diacritic # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT +1CF30..1CF46 ; Diacritic # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG +1D167..1D169 ; Diacritic # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3 +1D16D..1D172 ; Diacritic # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 +1D17B..1D182 ; Diacritic # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE +1D185..1D18B ; Diacritic # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE +1D1AA..1D1AD ; Diacritic # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO +1E030..1E06D ; Diacritic # Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE +1E130..1E136 ; Diacritic # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D +1E2AE ; Diacritic # Mn TOTO SIGN RISING TONE +1E2EC..1E2EF ; Diacritic # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI +1E5EE..1E5EF ; Diacritic # Mn [2] OL ONAL SIGN MU..OL ONAL SIGN IKIR +1E8D0..1E8D6 ; Diacritic # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS +1E944..1E946 ; Diacritic # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK +1E948..1E94A ; Diacritic # Mn [3] ADLAM CONSONANT MODIFIER..ADLAM NUKTA + +# Total code points: 1247 + +# ================================================ + +00B7 ; Extender # Po MIDDLE DOT +02D0..02D1 ; Extender # Lm [2] MODIFIER LETTER TRIANGULAR COLON..MODIFIER LETTER HALF TRIANGULAR COLON +0640 ; Extender # Lm ARABIC TATWEEL +07FA ; Extender # Lm NKO LAJANYALAN +0A71 ; Extender # Mn GURMUKHI ADDAK +0AFB ; Extender # Mn GUJARATI SIGN SHADDA +0B55 ; Extender # Mn ORIYA SIGN OVERLINE +0E46 ; Extender # Lm THAI CHARACTER MAIYAMOK +0EC6 ; Extender # Lm LAO KO LA +180A ; Extender # Po MONGOLIAN NIRUGU +1843 ; Extender # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN +1AA7 ; Extender # Lm TAI THAM SIGN MAI YAMOK +1C36 ; Extender # Mn LEPCHA SIGN RAN +1C7B ; Extender # Lm OL CHIKI RELAA +3005 ; Extender # Lm IDEOGRAPHIC ITERATION MARK +3031..3035 ; Extender # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF +309D..309E ; Extender # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK +30FC..30FE ; Extender # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK +A015 ; Extender # Lm YI SYLLABLE WU +A60C ; Extender # Lm VAI SYLLABLE LENGTHENER +A9CF ; Extender # Lm JAVANESE PANGRANGKEP +A9E6 ; Extender # Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION +AA70 ; Extender # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION +AADD ; Extender # Lm TAI VIET SYMBOL SAM +AAF3..AAF4 ; Extender # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK +FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK +10781..10782 ; Extender # Lm [2] MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON..MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON +10D4E ; Extender # Lm GARAY VOWEL LENGTH MARK +10D6A ; Extender # Mn GARAY CONSONANT GEMINATION MARK +10D6F ; Extender # Lm GARAY REDUPLICATION MARK +11237 ; Extender # Mn KHOJKI SIGN SHADDA +1135D ; Extender # Lo GRANTHA SIGN PLUTA +113D2 ; Extender # Mn TULU-TIGALARI GEMINATION MARK +113D3 ; Extender # Lo TULU-TIGALARI SIGN PLUTA +115C6..115C8 ; Extender # Po [3] SIDDHAM REPETITION MARK-1..SIDDHAM REPETITION MARK-3 +11A98 ; Extender # Mn SOYOMBO GEMINATION MARK +11DD9 ; Extender # Lm TOLONG SIKI SIGN SELA +16B42..16B43 ; Extender # Lm [2] PAHAWH HMONG SIGN VOS NRUA..PAHAWH HMONG SIGN IB YAM +16FE0..16FE1 ; Extender # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK +16FE3 ; Extender # Lm OLD CHINESE ITERATION MARK +16FF2..16FF3 ; Extender # Lm [2] CHINESE SMALL SIMPLIFIED ER..CHINESE SMALL TRADITIONAL ER +1E13C..1E13D ; Extender # Lm [2] NYIAKENG PUACHUE HMONG SIGN XW XW..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER +1E5EF ; Extender # Mn OL ONAL SIGN IKIR +1E944..1E946 ; Extender # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK + +# Total code points: 62 + +# ================================================ + +00AA ; Other_Lowercase # Lo FEMININE ORDINAL INDICATOR +00BA ; Other_Lowercase # Lo MASCULINE ORDINAL INDICATOR +02B0..02B8 ; Other_Lowercase # Lm [9] MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y +02C0..02C1 ; Other_Lowercase # Lm [2] MODIFIER LETTER GLOTTAL STOP..MODIFIER LETTER REVERSED GLOTTAL STOP +02E0..02E4 ; Other_Lowercase # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP +0345 ; Other_Lowercase # Mn COMBINING GREEK YPOGEGRAMMENI +037A ; Other_Lowercase # Lm GREEK YPOGEGRAMMENI +10FC ; Other_Lowercase # Lm MODIFIER LETTER GEORGIAN NAR +1D2C..1D6A ; Other_Lowercase # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI +1D78 ; Other_Lowercase # Lm MODIFIER LETTER CYRILLIC EN +1D9B..1DBF ; Other_Lowercase # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA +2071 ; Other_Lowercase # Lm SUPERSCRIPT LATIN SMALL LETTER I +207F ; Other_Lowercase # Lm SUPERSCRIPT LATIN SMALL LETTER N +2090..209C ; Other_Lowercase # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T +2170..217F ; Other_Lowercase # Nl [16] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL ONE THOUSAND +24D0..24E9 ; Other_Lowercase # So [26] CIRCLED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z +2C7C..2C7D ; Other_Lowercase # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V +A69C..A69D ; Other_Lowercase # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN +A770 ; Other_Lowercase # Lm MODIFIER LETTER US +A7F1..A7F4 ; Other_Lowercase # Lm [4] MODIFIER LETTER CAPITAL S..MODIFIER LETTER CAPITAL Q +A7F8..A7F9 ; Other_Lowercase # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE +AB5C..AB5F ; Other_Lowercase # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK +AB69 ; Other_Lowercase # Lm MODIFIER LETTER SMALL TURNED W +10780 ; Other_Lowercase # Lm MODIFIER LETTER SMALL CAPITAL AA +10783..10785 ; Other_Lowercase # Lm [3] MODIFIER LETTER SMALL AE..MODIFIER LETTER SMALL B WITH HOOK +10787..107B0 ; Other_Lowercase # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK +107B2..107BA ; Other_Lowercase # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL +1E030..1E06D ; Other_Lowercase # Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + +# Total code points: 312 + +# ================================================ + +2160..216F ; Other_Uppercase # Nl [16] ROMAN NUMERAL ONE..ROMAN NUMERAL ONE THOUSAND +24B6..24CF ; Other_Uppercase # So [26] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN CAPITAL LETTER Z +1F130..1F149 ; Other_Uppercase # So [26] SQUARED LATIN CAPITAL LETTER A..SQUARED LATIN CAPITAL LETTER Z +1F150..1F169 ; Other_Uppercase # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z +1F170..1F189 ; Other_Uppercase # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z + +# Total code points: 120 + +# ================================================ + +FDD0..FDEF ; Noncharacter_Code_Point # Cn [32] .. +FFFE..FFFF ; Noncharacter_Code_Point # Cn [2] .. +1FFFE..1FFFF ; Noncharacter_Code_Point # Cn [2] .. +2FFFE..2FFFF ; Noncharacter_Code_Point # Cn [2] .. +3FFFE..3FFFF ; Noncharacter_Code_Point # Cn [2] .. +4FFFE..4FFFF ; Noncharacter_Code_Point # Cn [2] .. +5FFFE..5FFFF ; Noncharacter_Code_Point # Cn [2] .. +6FFFE..6FFFF ; Noncharacter_Code_Point # Cn [2] .. +7FFFE..7FFFF ; Noncharacter_Code_Point # Cn [2] .. +8FFFE..8FFFF ; Noncharacter_Code_Point # Cn [2] .. +9FFFE..9FFFF ; Noncharacter_Code_Point # Cn [2] .. +AFFFE..AFFFF ; Noncharacter_Code_Point # Cn [2] .. +BFFFE..BFFFF ; Noncharacter_Code_Point # Cn [2] .. +CFFFE..CFFFF ; Noncharacter_Code_Point # Cn [2] .. +DFFFE..DFFFF ; Noncharacter_Code_Point # Cn [2] .. +EFFFE..EFFFF ; Noncharacter_Code_Point # Cn [2] .. +FFFFE..FFFFF ; Noncharacter_Code_Point # Cn [2] .. +10FFFE..10FFFF; Noncharacter_Code_Point # Cn [2] .. + +# Total code points: 66 + +# ================================================ + +09BE ; Other_Grapheme_Extend # Mc BENGALI VOWEL SIGN AA +09D7 ; Other_Grapheme_Extend # Mc BENGALI AU LENGTH MARK +0B3E ; Other_Grapheme_Extend # Mc ORIYA VOWEL SIGN AA +0B57 ; Other_Grapheme_Extend # Mc ORIYA AU LENGTH MARK +0BBE ; Other_Grapheme_Extend # Mc TAMIL VOWEL SIGN AA +0BD7 ; Other_Grapheme_Extend # Mc TAMIL AU LENGTH MARK +0CC0 ; Other_Grapheme_Extend # Mc KANNADA VOWEL SIGN II +0CC2 ; Other_Grapheme_Extend # Mc KANNADA VOWEL SIGN UU +0CC7..0CC8 ; Other_Grapheme_Extend # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI +0CCA..0CCB ; Other_Grapheme_Extend # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO +0CD5..0CD6 ; Other_Grapheme_Extend # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK +0D3E ; Other_Grapheme_Extend # Mc MALAYALAM VOWEL SIGN AA +0D57 ; Other_Grapheme_Extend # Mc MALAYALAM AU LENGTH MARK +0DCF ; Other_Grapheme_Extend # Mc SINHALA VOWEL SIGN AELA-PILLA +0DDF ; Other_Grapheme_Extend # Mc SINHALA VOWEL SIGN GAYANUKITTA +1715 ; Other_Grapheme_Extend # Mc TAGALOG SIGN PAMUDPOD +1734 ; Other_Grapheme_Extend # Mc HANUNOO SIGN PAMUDPOD +1B35 ; Other_Grapheme_Extend # Mc BALINESE VOWEL SIGN TEDUNG +1B3B ; Other_Grapheme_Extend # Mc BALINESE VOWEL SIGN RA REPA TEDUNG +1B3D ; Other_Grapheme_Extend # Mc BALINESE VOWEL SIGN LA LENGA TEDUNG +1B43..1B44 ; Other_Grapheme_Extend # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG +1BAA ; Other_Grapheme_Extend # Mc SUNDANESE SIGN PAMAAEH +1BF2..1BF3 ; Other_Grapheme_Extend # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN +200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER +302E..302F ; Other_Grapheme_Extend # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK +A953 ; Other_Grapheme_Extend # Mc REJANG VIRAMA +A9C0 ; Other_Grapheme_Extend # Mc JAVANESE PANGKON +FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +111C0 ; Other_Grapheme_Extend # Mc SHARADA SIGN VIRAMA +11235 ; Other_Grapheme_Extend # Mc KHOJKI SIGN VIRAMA +1133E ; Other_Grapheme_Extend # Mc GRANTHA VOWEL SIGN AA +1134D ; Other_Grapheme_Extend # Mc GRANTHA SIGN VIRAMA +11357 ; Other_Grapheme_Extend # Mc GRANTHA AU LENGTH MARK +113B8 ; Other_Grapheme_Extend # Mc TULU-TIGALARI VOWEL SIGN AA +113C2 ; Other_Grapheme_Extend # Mc TULU-TIGALARI VOWEL SIGN EE +113C5 ; Other_Grapheme_Extend # Mc TULU-TIGALARI VOWEL SIGN AI +113C7..113C9 ; Other_Grapheme_Extend # Mc [3] TULU-TIGALARI VOWEL SIGN OO..TULU-TIGALARI AU LENGTH MARK +113CF ; Other_Grapheme_Extend # Mc TULU-TIGALARI SIGN LOOPED VIRAMA +114B0 ; Other_Grapheme_Extend # Mc TIRHUTA VOWEL SIGN AA +114BD ; Other_Grapheme_Extend # Mc TIRHUTA VOWEL SIGN SHORT O +115AF ; Other_Grapheme_Extend # Mc SIDDHAM VOWEL SIGN AA +116B6 ; Other_Grapheme_Extend # Mc TAKRI SIGN VIRAMA +11930 ; Other_Grapheme_Extend # Mc DIVES AKURU VOWEL SIGN AA +1193D ; Other_Grapheme_Extend # Mc DIVES AKURU SIGN HALANTA +11F41 ; Other_Grapheme_Extend # Mc KAWI SIGN KILLER +16FF0..16FF1 ; Other_Grapheme_Extend # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY +1D165..1D166 ; Other_Grapheme_Extend # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM +1D16D..1D172 ; Other_Grapheme_Extend # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5 +E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG + +# Total code points: 160 + +# ================================================ + +2FF0..2FF1 ; IDS_Binary_Operator # So [2] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW +2FF4..2FFD ; IDS_Binary_Operator # So [10] IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND..IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT +31EF ; IDS_Binary_Operator # So IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION + +# Total code points: 13 + +# ================================================ + +2FF2..2FF3 ; IDS_Trinary_Operator # So [2] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW + +# Total code points: 2 + +# ================================================ + +2FFE..2FFF ; IDS_Unary_Operator # So [2] IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION + +# Total code points: 2 + +# ================================================ + +2E80..2E99 ; Radical # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP +2E9B..2EF3 ; Radical # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE +2F00..2FD5 ; Radical # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE + +# Total code points: 329 + +# ================================================ + +3400..4DBF ; Unified_Ideograph # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF +4E00..9FFF ; Unified_Ideograph # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF +FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F +FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11 +FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14 +FA1F ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA1F +FA21 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA21 +FA23..FA24 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24 +FA27..FA29 ; Unified_Ideograph # Lo [3] CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29 +20000..2A6DF ; Unified_Ideograph # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF +2A700..2B81D ; Unified_Ideograph # Lo [4382] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B81D +2B820..2CEAD ; Unified_Ideograph # Lo [5774] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEAD +2CEB0..2EBE0 ; Unified_Ideograph # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 +2EBF0..2EE5D ; Unified_Ideograph # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D +30000..3134A ; Unified_Ideograph # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A +31350..33479 ; Unified_Ideograph # Lo [8490] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-33479 + +# Total code points: 101996 + +# ================================================ + +034F ; Other_Default_Ignorable_Code_Point # Mn COMBINING GRAPHEME JOINER +115F..1160 ; Other_Default_Ignorable_Code_Point # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER +17B4..17B5 ; Other_Default_Ignorable_Code_Point # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA +2065 ; Other_Default_Ignorable_Code_Point # Cn +3164 ; Other_Default_Ignorable_Code_Point # Lo HANGUL FILLER +FFA0 ; Other_Default_Ignorable_Code_Point # Lo HALFWIDTH HANGUL FILLER +FFF0..FFF8 ; Other_Default_Ignorable_Code_Point # Cn [9] .. +E0000 ; Other_Default_Ignorable_Code_Point # Cn +E0002..E001F ; Other_Default_Ignorable_Code_Point # Cn [30] .. +E0080..E00FF ; Other_Default_Ignorable_Code_Point # Cn [128] .. +E01F0..E0FFF ; Other_Default_Ignorable_Code_Point # Cn [3600] .. + +# Total code points: 3776 + +# ================================================ + +0149 ; Deprecated # L& LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0673 ; Deprecated # Lo ARABIC LETTER ALEF WITH WAVY HAMZA BELOW +0F77 ; Deprecated # Mn TIBETAN VOWEL SIGN VOCALIC RR +0F79 ; Deprecated # Mn TIBETAN VOWEL SIGN VOCALIC LL +17A3..17A4 ; Deprecated # Lo [2] KHMER INDEPENDENT VOWEL QAQ..KHMER INDEPENDENT VOWEL QAA +206A..206F ; Deprecated # Cf [6] INHIBIT SYMMETRIC SWAPPING..NOMINAL DIGIT SHAPES +2329 ; Deprecated # Ps LEFT-POINTING ANGLE BRACKET +232A ; Deprecated # Pe RIGHT-POINTING ANGLE BRACKET +E0001 ; Deprecated # Cf LANGUAGE TAG + +# Total code points: 15 + +# ================================================ + +0069..006A ; Soft_Dotted # L& [2] LATIN SMALL LETTER I..LATIN SMALL LETTER J +012F ; Soft_Dotted # L& LATIN SMALL LETTER I WITH OGONEK +0249 ; Soft_Dotted # L& LATIN SMALL LETTER J WITH STROKE +0268 ; Soft_Dotted # L& LATIN SMALL LETTER I WITH STROKE +029D ; Soft_Dotted # L& LATIN SMALL LETTER J WITH CROSSED-TAIL +02B2 ; Soft_Dotted # Lm MODIFIER LETTER SMALL J +03F3 ; Soft_Dotted # L& GREEK LETTER YOT +0456 ; Soft_Dotted # L& CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +0458 ; Soft_Dotted # L& CYRILLIC SMALL LETTER JE +1D62 ; Soft_Dotted # Lm LATIN SUBSCRIPT SMALL LETTER I +1D96 ; Soft_Dotted # L& LATIN SMALL LETTER I WITH RETROFLEX HOOK +1DA4 ; Soft_Dotted # Lm MODIFIER LETTER SMALL I WITH STROKE +1DA8 ; Soft_Dotted # Lm MODIFIER LETTER SMALL J WITH CROSSED-TAIL +1E2D ; Soft_Dotted # L& LATIN SMALL LETTER I WITH TILDE BELOW +1ECB ; Soft_Dotted # L& LATIN SMALL LETTER I WITH DOT BELOW +2071 ; Soft_Dotted # Lm SUPERSCRIPT LATIN SMALL LETTER I +2148..2149 ; Soft_Dotted # L& [2] DOUBLE-STRUCK ITALIC SMALL I..DOUBLE-STRUCK ITALIC SMALL J +2C7C ; Soft_Dotted # Lm LATIN SUBSCRIPT SMALL LETTER J +1D422..1D423 ; Soft_Dotted # L& [2] MATHEMATICAL BOLD SMALL I..MATHEMATICAL BOLD SMALL J +1D456..1D457 ; Soft_Dotted # L& [2] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL J +1D48A..1D48B ; Soft_Dotted # L& [2] MATHEMATICAL BOLD ITALIC SMALL I..MATHEMATICAL BOLD ITALIC SMALL J +1D4BE..1D4BF ; Soft_Dotted # L& [2] MATHEMATICAL SCRIPT SMALL I..MATHEMATICAL SCRIPT SMALL J +1D4F2..1D4F3 ; Soft_Dotted # L& [2] MATHEMATICAL BOLD SCRIPT SMALL I..MATHEMATICAL BOLD SCRIPT SMALL J +1D526..1D527 ; Soft_Dotted # L& [2] MATHEMATICAL FRAKTUR SMALL I..MATHEMATICAL FRAKTUR SMALL J +1D55A..1D55B ; Soft_Dotted # L& [2] MATHEMATICAL DOUBLE-STRUCK SMALL I..MATHEMATICAL DOUBLE-STRUCK SMALL J +1D58E..1D58F ; Soft_Dotted # L& [2] MATHEMATICAL BOLD FRAKTUR SMALL I..MATHEMATICAL BOLD FRAKTUR SMALL J +1D5C2..1D5C3 ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF SMALL I..MATHEMATICAL SANS-SERIF SMALL J +1D5F6..1D5F7 ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF BOLD SMALL I..MATHEMATICAL SANS-SERIF BOLD SMALL J +1D62A..1D62B ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J +1D65E..1D65F ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J +1D692..1D693 ; Soft_Dotted # L& [2] MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J +1DF1A ; Soft_Dotted # L& LATIN SMALL LETTER I WITH STROKE AND RETROFLEX HOOK +1E04C..1E04D ; Soft_Dotted # Lm [2] MODIFIER LETTER CYRILLIC SMALL BYELORUSSIAN-UKRAINIAN I..MODIFIER LETTER CYRILLIC SMALL JE +1E068 ; Soft_Dotted # Lm CYRILLIC SUBSCRIPT SMALL LETTER BYELORUSSIAN-UKRAINIAN I + +# Total code points: 50 + +# ================================================ + +0E40..0E44 ; Logical_Order_Exception # Lo [5] THAI CHARACTER SARA E..THAI CHARACTER SARA AI MAIMALAI +0EC0..0EC4 ; Logical_Order_Exception # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI +19B5..19B7 ; Logical_Order_Exception # Lo [3] NEW TAI LUE VOWEL SIGN E..NEW TAI LUE VOWEL SIGN O +19BA ; Logical_Order_Exception # Lo NEW TAI LUE VOWEL SIGN AY +AAB5..AAB6 ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O +AAB9 ; Logical_Order_Exception # Lo TAI VIET VOWEL UEA +AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET VOWEL AY + +# Total code points: 19 + +# ================================================ + +1885..1886 ; Other_ID_Start # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA +2118 ; Other_ID_Start # Sm SCRIPT CAPITAL P +212E ; Other_ID_Start # So ESTIMATED SYMBOL +309B..309C ; Other_ID_Start # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + +# Total code points: 6 + +# ================================================ + +00B7 ; Other_ID_Continue # Po MIDDLE DOT +0387 ; Other_ID_Continue # Po GREEK ANO TELEIA +1369..1371 ; Other_ID_Continue # No [9] ETHIOPIC DIGIT ONE..ETHIOPIC DIGIT NINE +19DA ; Other_ID_Continue # No NEW TAI LUE THAM DIGIT ONE +200C..200D ; Other_ID_Continue # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER +30FB ; Other_ID_Continue # Po KATAKANA MIDDLE DOT +FF65 ; Other_ID_Continue # Po HALFWIDTH KATAKANA MIDDLE DOT + +# Total code points: 16 + +# ================================================ + +00B2..00B3 ; ID_Compat_Math_Continue # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE +00B9 ; ID_Compat_Math_Continue # No SUPERSCRIPT ONE +2070 ; ID_Compat_Math_Continue # No SUPERSCRIPT ZERO +2074..2079 ; ID_Compat_Math_Continue # No [6] SUPERSCRIPT FOUR..SUPERSCRIPT NINE +207A..207C ; ID_Compat_Math_Continue # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN +207D ; ID_Compat_Math_Continue # Ps SUPERSCRIPT LEFT PARENTHESIS +207E ; ID_Compat_Math_Continue # Pe SUPERSCRIPT RIGHT PARENTHESIS +2080..2089 ; ID_Compat_Math_Continue # No [10] SUBSCRIPT ZERO..SUBSCRIPT NINE +208A..208C ; ID_Compat_Math_Continue # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN +208D ; ID_Compat_Math_Continue # Ps SUBSCRIPT LEFT PARENTHESIS +208E ; ID_Compat_Math_Continue # Pe SUBSCRIPT RIGHT PARENTHESIS +2202 ; ID_Compat_Math_Continue # Sm PARTIAL DIFFERENTIAL +2207 ; ID_Compat_Math_Continue # Sm NABLA +221E ; ID_Compat_Math_Continue # Sm INFINITY +1D6C1 ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD NABLA +1D6DB ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL +1D6FB ; ID_Compat_Math_Continue # Sm MATHEMATICAL ITALIC NABLA +1D715 ; ID_Compat_Math_Continue # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL +1D735 ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD ITALIC NABLA +1D74F ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL +1D76F ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD NABLA +1D789 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL +1D7A9 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA +1D7C3 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL + +# Total code points: 43 + +# ================================================ + +2202 ; ID_Compat_Math_Start # Sm PARTIAL DIFFERENTIAL +2207 ; ID_Compat_Math_Start # Sm NABLA +221E ; ID_Compat_Math_Start # Sm INFINITY +1D6C1 ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD NABLA +1D6DB ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL +1D6FB ; ID_Compat_Math_Start # Sm MATHEMATICAL ITALIC NABLA +1D715 ; ID_Compat_Math_Start # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL +1D735 ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD ITALIC NABLA +1D74F ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL +1D76F ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD NABLA +1D789 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL +1D7A9 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA +1D7C3 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL + +# Total code points: 13 + +# ================================================ + +0021 ; Sentence_Terminal # Po EXCLAMATION MARK +002E ; Sentence_Terminal # Po FULL STOP +003F ; Sentence_Terminal # Po QUESTION MARK +0589 ; Sentence_Terminal # Po ARMENIAN FULL STOP +061D..061F ; Sentence_Terminal # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK +06D4 ; Sentence_Terminal # Po ARABIC FULL STOP +0700..0702 ; Sentence_Terminal # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP +07F9 ; Sentence_Terminal # Po NKO EXCLAMATION MARK +0837 ; Sentence_Terminal # Po SAMARITAN PUNCTUATION MELODIC QITSA +0839 ; Sentence_Terminal # Po SAMARITAN PUNCTUATION QITSA +083D..083E ; Sentence_Terminal # Po [2] SAMARITAN PUNCTUATION SOF MASHFAAT..SAMARITAN PUNCTUATION ANNAAU +0964..0965 ; Sentence_Terminal # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA +104A..104B ; Sentence_Terminal # Po [2] MYANMAR SIGN LITTLE SECTION..MYANMAR SIGN SECTION +1362 ; Sentence_Terminal # Po ETHIOPIC FULL STOP +1367..1368 ; Sentence_Terminal # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR +166E ; Sentence_Terminal # Po CANADIAN SYLLABICS FULL STOP +1735..1736 ; Sentence_Terminal # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION +17D4..17D5 ; Sentence_Terminal # Po [2] KHMER SIGN KHAN..KHMER SIGN BARIYOOSAN +1803 ; Sentence_Terminal # Po MONGOLIAN FULL STOP +1809 ; Sentence_Terminal # Po MONGOLIAN MANCHU FULL STOP +1944..1945 ; Sentence_Terminal # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK +1AA8..1AAB ; Sentence_Terminal # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU +1B4E..1B4F ; Sentence_Terminal # Po [2] BALINESE INVERTED CARIK SIKI..BALINESE INVERTED CARIK PAREREN +1B5A..1B5B ; Sentence_Terminal # Po [2] BALINESE PANTI..BALINESE PAMADA +1B5E..1B5F ; Sentence_Terminal # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN +1B7D..1B7F ; Sentence_Terminal # Po [3] BALINESE PANTI LANTANG..BALINESE PANTI BAWAK +1C3B..1C3C ; Sentence_Terminal # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL +1C7E..1C7F ; Sentence_Terminal # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD +2024 ; Sentence_Terminal # Po ONE DOT LEADER +203C..203D ; Sentence_Terminal # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG +2047..2049 ; Sentence_Terminal # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK +2CF9..2CFB ; Sentence_Terminal # Po [3] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN INDIRECT QUESTION MARK +2E2E ; Sentence_Terminal # Po REVERSED QUESTION MARK +2E3C ; Sentence_Terminal # Po STENOGRAPHIC FULL STOP +2E53..2E54 ; Sentence_Terminal # Po [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK +3002 ; Sentence_Terminal # Po IDEOGRAPHIC FULL STOP +A4FF ; Sentence_Terminal # Po LISU PUNCTUATION FULL STOP +A60E..A60F ; Sentence_Terminal # Po [2] VAI FULL STOP..VAI QUESTION MARK +A6F3 ; Sentence_Terminal # Po BAMUM FULL STOP +A6F7 ; Sentence_Terminal # Po BAMUM QUESTION MARK +A876..A877 ; Sentence_Terminal # Po [2] PHAGS-PA MARK SHAD..PHAGS-PA MARK DOUBLE SHAD +A8CE..A8CF ; Sentence_Terminal # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA +A92F ; Sentence_Terminal # Po KAYAH LI SIGN SHYA +A9C8..A9C9 ; Sentence_Terminal # Po [2] JAVANESE PADA LINGSA..JAVANESE PADA LUNGSI +AA5D..AA5F ; Sentence_Terminal # Po [3] CHAM PUNCTUATION DANDA..CHAM PUNCTUATION TRIPLE DANDA +AAF0..AAF1 ; Sentence_Terminal # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM +ABEB ; Sentence_Terminal # Po MEETEI MAYEK CHEIKHEI +FE12 ; Sentence_Terminal # Po PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP +FE15..FE16 ; Sentence_Terminal # Po [2] PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK..PRESENTATION FORM FOR VERTICAL QUESTION MARK +FE52 ; Sentence_Terminal # Po SMALL FULL STOP +FE56..FE57 ; Sentence_Terminal # Po [2] SMALL QUESTION MARK..SMALL EXCLAMATION MARK +FF01 ; Sentence_Terminal # Po FULLWIDTH EXCLAMATION MARK +FF0E ; Sentence_Terminal # Po FULLWIDTH FULL STOP +FF1F ; Sentence_Terminal # Po FULLWIDTH QUESTION MARK +FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP +10A56..10A57 ; Sentence_Terminal # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA +10F55..10F59 ; Sentence_Terminal # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT +10F86..10F89 ; Sentence_Terminal # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS +11047..11048 ; Sentence_Terminal # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA +110BE..110C1 ; Sentence_Terminal # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA +11141..11143 ; Sentence_Terminal # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK +111C5..111C6 ; Sentence_Terminal # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA +111CD ; Sentence_Terminal # Po SHARADA SUTRA MARK +111DE..111DF ; Sentence_Terminal # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2 +11238..11239 ; Sentence_Terminal # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA +1123B..1123C ; Sentence_Terminal # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK +112A9 ; Sentence_Terminal # Po MULTANI SECTION MARK +113D4..113D5 ; Sentence_Terminal # Po [2] TULU-TIGALARI DANDA..TULU-TIGALARI DOUBLE DANDA +1144B..1144C ; Sentence_Terminal # Po [2] NEWA DANDA..NEWA DOUBLE DANDA +115C2..115C3 ; Sentence_Terminal # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA +115C9..115D7 ; Sentence_Terminal # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES +11641..11642 ; Sentence_Terminal # Po [2] MODI DANDA..MODI DOUBLE DANDA +1173C..1173E ; Sentence_Terminal # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI +11944 ; Sentence_Terminal # Po DIVES AKURU DOUBLE DANDA +11946 ; Sentence_Terminal # Po DIVES AKURU END OF TEXT MARK +11A42..11A43 ; Sentence_Terminal # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD +11A9B..11A9C ; Sentence_Terminal # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD +11C41..11C42 ; Sentence_Terminal # Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA +11EF7..11EF8 ; Sentence_Terminal # Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION +11F43..11F44 ; Sentence_Terminal # Po [2] KAWI DANDA..KAWI DOUBLE DANDA +16A6E..16A6F ; Sentence_Terminal # Po [2] MRO DANDA..MRO DOUBLE DANDA +16AF5 ; Sentence_Terminal # Po BASSA VAH FULL STOP +16B37..16B38 ; Sentence_Terminal # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB +16B44 ; Sentence_Terminal # Po PAHAWH HMONG SIGN XAUS +16D6E..16D6F ; Sentence_Terminal # Po [2] KIRAT RAI DANDA..KIRAT RAI DOUBLE DANDA +16E98 ; Sentence_Terminal # Po MEDEFAIDRIN FULL STOP +1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP +1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP + +# Total code points: 170 + +# ================================================ + +180B..180D ; Variation_Selector # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE +180F ; Variation_Selector # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR +FE00..FE0F ; Variation_Selector # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16 +E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 + +# Total code points: 260 + +# ================================================ + +0009..000D ; Pattern_White_Space # Cc [5] .. +0020 ; Pattern_White_Space # Zs SPACE +0085 ; Pattern_White_Space # Cc +200E..200F ; Pattern_White_Space # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK +2028 ; Pattern_White_Space # Zl LINE SEPARATOR +2029 ; Pattern_White_Space # Zp PARAGRAPH SEPARATOR + +# Total code points: 11 + +# ================================================ + +0021..0023 ; Pattern_Syntax # Po [3] EXCLAMATION MARK..NUMBER SIGN +0024 ; Pattern_Syntax # Sc DOLLAR SIGN +0025..0027 ; Pattern_Syntax # Po [3] PERCENT SIGN..APOSTROPHE +0028 ; Pattern_Syntax # Ps LEFT PARENTHESIS +0029 ; Pattern_Syntax # Pe RIGHT PARENTHESIS +002A ; Pattern_Syntax # Po ASTERISK +002B ; Pattern_Syntax # Sm PLUS SIGN +002C ; Pattern_Syntax # Po COMMA +002D ; Pattern_Syntax # Pd HYPHEN-MINUS +002E..002F ; Pattern_Syntax # Po [2] FULL STOP..SOLIDUS +003A..003B ; Pattern_Syntax # Po [2] COLON..SEMICOLON +003C..003E ; Pattern_Syntax # Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN +003F..0040 ; Pattern_Syntax # Po [2] QUESTION MARK..COMMERCIAL AT +005B ; Pattern_Syntax # Ps LEFT SQUARE BRACKET +005C ; Pattern_Syntax # Po REVERSE SOLIDUS +005D ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET +005E ; Pattern_Syntax # Sk CIRCUMFLEX ACCENT +0060 ; Pattern_Syntax # Sk GRAVE ACCENT +007B ; Pattern_Syntax # Ps LEFT CURLY BRACKET +007C ; Pattern_Syntax # Sm VERTICAL LINE +007D ; Pattern_Syntax # Pe RIGHT CURLY BRACKET +007E ; Pattern_Syntax # Sm TILDE +00A1 ; Pattern_Syntax # Po INVERTED EXCLAMATION MARK +00A2..00A5 ; Pattern_Syntax # Sc [4] CENT SIGN..YEN SIGN +00A6 ; Pattern_Syntax # So BROKEN BAR +00A7 ; Pattern_Syntax # Po SECTION SIGN +00A9 ; Pattern_Syntax # So COPYRIGHT SIGN +00AB ; Pattern_Syntax # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00AC ; Pattern_Syntax # Sm NOT SIGN +00AE ; Pattern_Syntax # So REGISTERED SIGN +00B0 ; Pattern_Syntax # So DEGREE SIGN +00B1 ; Pattern_Syntax # Sm PLUS-MINUS SIGN +00B6 ; Pattern_Syntax # Po PILCROW SIGN +00BB ; Pattern_Syntax # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +00BF ; Pattern_Syntax # Po INVERTED QUESTION MARK +00D7 ; Pattern_Syntax # Sm MULTIPLICATION SIGN +00F7 ; Pattern_Syntax # Sm DIVISION SIGN +2010..2015 ; Pattern_Syntax # Pd [6] HYPHEN..HORIZONTAL BAR +2016..2017 ; Pattern_Syntax # Po [2] DOUBLE VERTICAL LINE..DOUBLE LOW LINE +2018 ; Pattern_Syntax # Pi LEFT SINGLE QUOTATION MARK +2019 ; Pattern_Syntax # Pf RIGHT SINGLE QUOTATION MARK +201A ; Pattern_Syntax # Ps SINGLE LOW-9 QUOTATION MARK +201B..201C ; Pattern_Syntax # Pi [2] SINGLE HIGH-REVERSED-9 QUOTATION MARK..LEFT DOUBLE QUOTATION MARK +201D ; Pattern_Syntax # Pf RIGHT DOUBLE QUOTATION MARK +201E ; Pattern_Syntax # Ps DOUBLE LOW-9 QUOTATION MARK +201F ; Pattern_Syntax # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK +2020..2027 ; Pattern_Syntax # Po [8] DAGGER..HYPHENATION POINT +2030..2038 ; Pattern_Syntax # Po [9] PER MILLE SIGN..CARET +2039 ; Pattern_Syntax # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A ; Pattern_Syntax # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +203B..203E ; Pattern_Syntax # Po [4] REFERENCE MARK..OVERLINE +2041..2043 ; Pattern_Syntax # Po [3] CARET INSERTION POINT..HYPHEN BULLET +2044 ; Pattern_Syntax # Sm FRACTION SLASH +2045 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH QUILL +2046 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH QUILL +2047..2051 ; Pattern_Syntax # Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY +2052 ; Pattern_Syntax # Sm COMMERCIAL MINUS SIGN +2053 ; Pattern_Syntax # Po SWUNG DASH +2055..205E ; Pattern_Syntax # Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS +2190..2194 ; Pattern_Syntax # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW +2195..2199 ; Pattern_Syntax # So [5] UP DOWN ARROW..SOUTH WEST ARROW +219A..219B ; Pattern_Syntax # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE +219C..219F ; Pattern_Syntax # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW +21A0 ; Pattern_Syntax # Sm RIGHTWARDS TWO HEADED ARROW +21A1..21A2 ; Pattern_Syntax # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL +21A3 ; Pattern_Syntax # Sm RIGHTWARDS ARROW WITH TAIL +21A4..21A5 ; Pattern_Syntax # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR +21A6 ; Pattern_Syntax # Sm RIGHTWARDS ARROW FROM BAR +21A7..21AD ; Pattern_Syntax # So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW +21AE ; Pattern_Syntax # Sm LEFT RIGHT ARROW WITH STROKE +21AF..21CD ; Pattern_Syntax # So [31] DOWNWARDS ZIGZAG ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE +21CE..21CF ; Pattern_Syntax # Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE +21D0..21D1 ; Pattern_Syntax # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW +21D2 ; Pattern_Syntax # Sm RIGHTWARDS DOUBLE ARROW +21D3 ; Pattern_Syntax # So DOWNWARDS DOUBLE ARROW +21D4 ; Pattern_Syntax # Sm LEFT RIGHT DOUBLE ARROW +21D5..21F3 ; Pattern_Syntax # So [31] UP DOWN DOUBLE ARROW..UP DOWN WHITE ARROW +21F4..22FF ; Pattern_Syntax # Sm [268] RIGHT ARROW WITH SMALL CIRCLE..Z NOTATION BAG MEMBERSHIP +2300..2307 ; Pattern_Syntax # So [8] DIAMETER SIGN..WAVY LINE +2308 ; Pattern_Syntax # Ps LEFT CEILING +2309 ; Pattern_Syntax # Pe RIGHT CEILING +230A ; Pattern_Syntax # Ps LEFT FLOOR +230B ; Pattern_Syntax # Pe RIGHT FLOOR +230C..231F ; Pattern_Syntax # So [20] BOTTOM RIGHT CROP..BOTTOM RIGHT CORNER +2320..2321 ; Pattern_Syntax # Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL +2322..2328 ; Pattern_Syntax # So [7] FROWN..KEYBOARD +2329 ; Pattern_Syntax # Ps LEFT-POINTING ANGLE BRACKET +232A ; Pattern_Syntax # Pe RIGHT-POINTING ANGLE BRACKET +232B..237B ; Pattern_Syntax # So [81] ERASE TO THE LEFT..NOT CHECK MARK +237C ; Pattern_Syntax # Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW +237D..239A ; Pattern_Syntax # So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL +239B..23B3 ; Pattern_Syntax # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM +23B4..23DB ; Pattern_Syntax # So [40] TOP SQUARE BRACKET..FUSE +23DC..23E1 ; Pattern_Syntax # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET +23E2..2429 ; Pattern_Syntax # So [72] WHITE TRAPEZIUM..SYMBOL FOR DELETE MEDIUM SHADE FORM +242A..243F ; Pattern_Syntax # Cn [22] .. +2440..244A ; Pattern_Syntax # So [11] OCR HOOK..OCR DOUBLE BACKSLASH +244B..245F ; Pattern_Syntax # Cn [21] .. +2500..25B6 ; Pattern_Syntax # So [183] BOX DRAWINGS LIGHT HORIZONTAL..BLACK RIGHT-POINTING TRIANGLE +25B7 ; Pattern_Syntax # Sm WHITE RIGHT-POINTING TRIANGLE +25B8..25C0 ; Pattern_Syntax # So [9] BLACK RIGHT-POINTING SMALL TRIANGLE..BLACK LEFT-POINTING TRIANGLE +25C1 ; Pattern_Syntax # Sm WHITE LEFT-POINTING TRIANGLE +25C2..25F7 ; Pattern_Syntax # So [54] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE CIRCLE WITH UPPER RIGHT QUADRANT +25F8..25FF ; Pattern_Syntax # Sm [8] UPPER LEFT TRIANGLE..LOWER RIGHT TRIANGLE +2600..266E ; Pattern_Syntax # So [111] BLACK SUN WITH RAYS..MUSIC NATURAL SIGN +266F ; Pattern_Syntax # Sm MUSIC SHARP SIGN +2670..2767 ; Pattern_Syntax # So [248] WEST SYRIAC CROSS..ROTATED FLORAL HEART BULLET +2768 ; Pattern_Syntax # Ps MEDIUM LEFT PARENTHESIS ORNAMENT +2769 ; Pattern_Syntax # Pe MEDIUM RIGHT PARENTHESIS ORNAMENT +276A ; Pattern_Syntax # Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT +276B ; Pattern_Syntax # Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT +276C ; Pattern_Syntax # Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT +276D ; Pattern_Syntax # Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT +276E ; Pattern_Syntax # Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT +276F ; Pattern_Syntax # Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT +2770 ; Pattern_Syntax # Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT +2771 ; Pattern_Syntax # Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT +2772 ; Pattern_Syntax # Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT +2773 ; Pattern_Syntax # Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT +2774 ; Pattern_Syntax # Ps MEDIUM LEFT CURLY BRACKET ORNAMENT +2775 ; Pattern_Syntax # Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT +2794..27BF ; Pattern_Syntax # So [44] HEAVY WIDE-HEADED RIGHTWARDS ARROW..DOUBLE CURLY LOOP +27C0..27C4 ; Pattern_Syntax # Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET +27C5 ; Pattern_Syntax # Ps LEFT S-SHAPED BAG DELIMITER +27C6 ; Pattern_Syntax # Pe RIGHT S-SHAPED BAG DELIMITER +27C7..27E5 ; Pattern_Syntax # Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK +27E6 ; Pattern_Syntax # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET +27E7 ; Pattern_Syntax # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET +27E8 ; Pattern_Syntax # Ps MATHEMATICAL LEFT ANGLE BRACKET +27E9 ; Pattern_Syntax # Pe MATHEMATICAL RIGHT ANGLE BRACKET +27EA ; Pattern_Syntax # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET +27EB ; Pattern_Syntax # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET +27EC ; Pattern_Syntax # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET +27ED ; Pattern_Syntax # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET +27EE ; Pattern_Syntax # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS +27EF ; Pattern_Syntax # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS +27F0..27FF ; Pattern_Syntax # Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW +2800..28FF ; Pattern_Syntax # So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678 +2900..2982 ; Pattern_Syntax # Sm [131] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..Z NOTATION TYPE COLON +2983 ; Pattern_Syntax # Ps LEFT WHITE CURLY BRACKET +2984 ; Pattern_Syntax # Pe RIGHT WHITE CURLY BRACKET +2985 ; Pattern_Syntax # Ps LEFT WHITE PARENTHESIS +2986 ; Pattern_Syntax # Pe RIGHT WHITE PARENTHESIS +2987 ; Pattern_Syntax # Ps Z NOTATION LEFT IMAGE BRACKET +2988 ; Pattern_Syntax # Pe Z NOTATION RIGHT IMAGE BRACKET +2989 ; Pattern_Syntax # Ps Z NOTATION LEFT BINDING BRACKET +298A ; Pattern_Syntax # Pe Z NOTATION RIGHT BINDING BRACKET +298B ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH UNDERBAR +298C ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH UNDERBAR +298D ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER +298E ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +298F ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER +2990 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER +2991 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET WITH DOT +2992 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET WITH DOT +2993 ; Pattern_Syntax # Ps LEFT ARC LESS-THAN BRACKET +2994 ; Pattern_Syntax # Pe RIGHT ARC GREATER-THAN BRACKET +2995 ; Pattern_Syntax # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET +2996 ; Pattern_Syntax # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET +2997 ; Pattern_Syntax # Ps LEFT BLACK TORTOISE SHELL BRACKET +2998 ; Pattern_Syntax # Pe RIGHT BLACK TORTOISE SHELL BRACKET +2999..29D7 ; Pattern_Syntax # Sm [63] DOTTED FENCE..BLACK HOURGLASS +29D8 ; Pattern_Syntax # Ps LEFT WIGGLY FENCE +29D9 ; Pattern_Syntax # Pe RIGHT WIGGLY FENCE +29DA ; Pattern_Syntax # Ps LEFT DOUBLE WIGGLY FENCE +29DB ; Pattern_Syntax # Pe RIGHT DOUBLE WIGGLY FENCE +29DC..29FB ; Pattern_Syntax # Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS +29FC ; Pattern_Syntax # Ps LEFT-POINTING CURVED ANGLE BRACKET +29FD ; Pattern_Syntax # Pe RIGHT-POINTING CURVED ANGLE BRACKET +29FE..2AFF ; Pattern_Syntax # Sm [258] TINY..N-ARY WHITE VERTICAL BAR +2B00..2B2F ; Pattern_Syntax # So [48] NORTH EAST WHITE ARROW..WHITE VERTICAL ELLIPSE +2B30..2B44 ; Pattern_Syntax # Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET +2B45..2B46 ; Pattern_Syntax # So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW +2B47..2B4C ; Pattern_Syntax # Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR +2B4D..2B73 ; Pattern_Syntax # So [39] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR +2B74..2B75 ; Pattern_Syntax # Cn [2] .. +2B76..2BFF ; Pattern_Syntax # So [138] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..HELLSCHREIBER PAUSE SYMBOL +2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER +2E02 ; Pattern_Syntax # Pi LEFT SUBSTITUTION BRACKET +2E03 ; Pattern_Syntax # Pf RIGHT SUBSTITUTION BRACKET +2E04 ; Pattern_Syntax # Pi LEFT DOTTED SUBSTITUTION BRACKET +2E05 ; Pattern_Syntax # Pf RIGHT DOTTED SUBSTITUTION BRACKET +2E06..2E08 ; Pattern_Syntax # Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER +2E09 ; Pattern_Syntax # Pi LEFT TRANSPOSITION BRACKET +2E0A ; Pattern_Syntax # Pf RIGHT TRANSPOSITION BRACKET +2E0B ; Pattern_Syntax # Po RAISED SQUARE +2E0C ; Pattern_Syntax # Pi LEFT RAISED OMISSION BRACKET +2E0D ; Pattern_Syntax # Pf RIGHT RAISED OMISSION BRACKET +2E0E..2E16 ; Pattern_Syntax # Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE +2E17 ; Pattern_Syntax # Pd DOUBLE OBLIQUE HYPHEN +2E18..2E19 ; Pattern_Syntax # Po [2] INVERTED INTERROBANG..PALM BRANCH +2E1A ; Pattern_Syntax # Pd HYPHEN WITH DIAERESIS +2E1B ; Pattern_Syntax # Po TILDE WITH RING ABOVE +2E1C ; Pattern_Syntax # Pi LEFT LOW PARAPHRASE BRACKET +2E1D ; Pattern_Syntax # Pf RIGHT LOW PARAPHRASE BRACKET +2E1E..2E1F ; Pattern_Syntax # Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW +2E20 ; Pattern_Syntax # Pi LEFT VERTICAL BAR WITH QUILL +2E21 ; Pattern_Syntax # Pf RIGHT VERTICAL BAR WITH QUILL +2E22 ; Pattern_Syntax # Ps TOP LEFT HALF BRACKET +2E23 ; Pattern_Syntax # Pe TOP RIGHT HALF BRACKET +2E24 ; Pattern_Syntax # Ps BOTTOM LEFT HALF BRACKET +2E25 ; Pattern_Syntax # Pe BOTTOM RIGHT HALF BRACKET +2E26 ; Pattern_Syntax # Ps LEFT SIDEWAYS U BRACKET +2E27 ; Pattern_Syntax # Pe RIGHT SIDEWAYS U BRACKET +2E28 ; Pattern_Syntax # Ps LEFT DOUBLE PARENTHESIS +2E29 ; Pattern_Syntax # Pe RIGHT DOUBLE PARENTHESIS +2E2A..2E2E ; Pattern_Syntax # Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK +2E2F ; Pattern_Syntax # Lm VERTICAL TILDE +2E30..2E39 ; Pattern_Syntax # Po [10] RING POINT..TOP HALF SECTION SIGN +2E3A..2E3B ; Pattern_Syntax # Pd [2] TWO-EM DASH..THREE-EM DASH +2E3C..2E3F ; Pattern_Syntax # Po [4] STENOGRAPHIC FULL STOP..CAPITULUM +2E40 ; Pattern_Syntax # Pd DOUBLE HYPHEN +2E41 ; Pattern_Syntax # Po REVERSED COMMA +2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK +2E43..2E4F ; Pattern_Syntax # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER +2E50..2E51 ; Pattern_Syntax # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR +2E52..2E54 ; Pattern_Syntax # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK +2E55 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH STROKE +2E56 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH STROKE +2E57 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE +2E58 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE +2E59 ; Pattern_Syntax # Ps TOP HALF LEFT PARENTHESIS +2E5A ; Pattern_Syntax # Pe TOP HALF RIGHT PARENTHESIS +2E5B ; Pattern_Syntax # Ps BOTTOM HALF LEFT PARENTHESIS +2E5C ; Pattern_Syntax # Pe BOTTOM HALF RIGHT PARENTHESIS +2E5D ; Pattern_Syntax # Pd OBLIQUE HYPHEN +2E5E..2E7F ; Pattern_Syntax # Cn [34] .. +3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK +3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET +3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET +300A ; Pattern_Syntax # Ps LEFT DOUBLE ANGLE BRACKET +300B ; Pattern_Syntax # Pe RIGHT DOUBLE ANGLE BRACKET +300C ; Pattern_Syntax # Ps LEFT CORNER BRACKET +300D ; Pattern_Syntax # Pe RIGHT CORNER BRACKET +300E ; Pattern_Syntax # Ps LEFT WHITE CORNER BRACKET +300F ; Pattern_Syntax # Pe RIGHT WHITE CORNER BRACKET +3010 ; Pattern_Syntax # Ps LEFT BLACK LENTICULAR BRACKET +3011 ; Pattern_Syntax # Pe RIGHT BLACK LENTICULAR BRACKET +3012..3013 ; Pattern_Syntax # So [2] POSTAL MARK..GETA MARK +3014 ; Pattern_Syntax # Ps LEFT TORTOISE SHELL BRACKET +3015 ; Pattern_Syntax # Pe RIGHT TORTOISE SHELL BRACKET +3016 ; Pattern_Syntax # Ps LEFT WHITE LENTICULAR BRACKET +3017 ; Pattern_Syntax # Pe RIGHT WHITE LENTICULAR BRACKET +3018 ; Pattern_Syntax # Ps LEFT WHITE TORTOISE SHELL BRACKET +3019 ; Pattern_Syntax # Pe RIGHT WHITE TORTOISE SHELL BRACKET +301A ; Pattern_Syntax # Ps LEFT WHITE SQUARE BRACKET +301B ; Pattern_Syntax # Pe RIGHT WHITE SQUARE BRACKET +301C ; Pattern_Syntax # Pd WAVE DASH +301D ; Pattern_Syntax # Ps REVERSED DOUBLE PRIME QUOTATION MARK +301E..301F ; Pattern_Syntax # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK +3020 ; Pattern_Syntax # So POSTAL MARK FACE +3030 ; Pattern_Syntax # Pd WAVY DASH +FD3E ; Pattern_Syntax # Pe ORNATE LEFT PARENTHESIS +FD3F ; Pattern_Syntax # Ps ORNATE RIGHT PARENTHESIS +FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT + +# Total code points: 2760 + +# ================================================ + +0600..0605 ; Prepended_Concatenation_Mark # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE +06DD ; Prepended_Concatenation_Mark # Cf ARABIC END OF AYAH +070F ; Prepended_Concatenation_Mark # Cf SYRIAC ABBREVIATION MARK +0890..0891 ; Prepended_Concatenation_Mark # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE +08E2 ; Prepended_Concatenation_Mark # Cf ARABIC DISPUTED END OF AYAH +110BD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN +110CD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN ABOVE + +# Total code points: 13 + +# ================================================ + +1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z + +# Total code points: 26 + +# ================================================ + +0654..0655 ; Modifier_Combining_Mark # Mn [2] ARABIC HAMZA ABOVE..ARABIC HAMZA BELOW +0658 ; Modifier_Combining_Mark # Mn ARABIC MARK NOON GHUNNA +06DC ; Modifier_Combining_Mark # Mn ARABIC SMALL HIGH SEEN +06E3 ; Modifier_Combining_Mark # Mn ARABIC SMALL LOW SEEN +06E7..06E8 ; Modifier_Combining_Mark # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON +08CA..08CB ; Modifier_Combining_Mark # Mn [2] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW +08CD..08CF ; Modifier_Combining_Mark # Mn [3] ARABIC SMALL HIGH ZAH..ARABIC LARGE ROUND DOT BELOW +08D3 ; Modifier_Combining_Mark # Mn ARABIC SMALL LOW WAW +08F3 ; Modifier_Combining_Mark # Mn ARABIC SMALL HIGH WAW + +# Total code points: 14 + +# EOF diff --git a/tests/core/assets/UCD/UnicodeData.txt b/tests/core/assets/UCD/UnicodeData.txt new file mode 100644 index 000000000..fca68e3e1 --- /dev/null +++ b/tests/core/assets/UCD/UnicodeData.txt @@ -0,0 +1,40575 @@ +0000;;Cc;0;BN;;;;;N;NULL;;;; +0001;;Cc;0;BN;;;;;N;START OF HEADING;;;; +0002;;Cc;0;BN;;;;;N;START OF TEXT;;;; +0003;;Cc;0;BN;;;;;N;END OF TEXT;;;; +0004;;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;; +0005;;Cc;0;BN;;;;;N;ENQUIRY;;;; +0006;;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; +0007;;Cc;0;BN;;;;;N;BELL;;;; +0008;;Cc;0;BN;;;;;N;BACKSPACE;;;; +0009;;Cc;0;S;;;;;N;CHARACTER TABULATION;;;; +000A;;Cc;0;B;;;;;N;LINE FEED (LF);;;; +000B;;Cc;0;S;;;;;N;LINE TABULATION;;;; +000C;;Cc;0;WS;;;;;N;FORM FEED (FF);;;; +000D;;Cc;0;B;;;;;N;CARRIAGE RETURN (CR);;;; +000E;;Cc;0;BN;;;;;N;SHIFT OUT;;;; +000F;;Cc;0;BN;;;;;N;SHIFT IN;;;; +0010;;Cc;0;BN;;;;;N;DATA LINK ESCAPE;;;; +0011;;Cc;0;BN;;;;;N;DEVICE CONTROL ONE;;;; +0012;;Cc;0;BN;;;;;N;DEVICE CONTROL TWO;;;; +0013;;Cc;0;BN;;;;;N;DEVICE CONTROL THREE;;;; +0014;;Cc;0;BN;;;;;N;DEVICE CONTROL FOUR;;;; +0015;;Cc;0;BN;;;;;N;NEGATIVE ACKNOWLEDGE;;;; +0016;;Cc;0;BN;;;;;N;SYNCHRONOUS IDLE;;;; +0017;;Cc;0;BN;;;;;N;END OF TRANSMISSION BLOCK;;;; +0018;;Cc;0;BN;;;;;N;CANCEL;;;; +0019;;Cc;0;BN;;;;;N;END OF MEDIUM;;;; +001A;;Cc;0;BN;;;;;N;SUBSTITUTE;;;; +001B;;Cc;0;BN;;;;;N;ESCAPE;;;; +001C;;Cc;0;B;;;;;N;INFORMATION SEPARATOR FOUR;;;; +001D;;Cc;0;B;;;;;N;INFORMATION SEPARATOR THREE;;;; +001E;;Cc;0;B;;;;;N;INFORMATION SEPARATOR TWO;;;; +001F;;Cc;0;S;;;;;N;INFORMATION SEPARATOR ONE;;;; +0020;SPACE;Zs;0;WS;;;;;N;;;;; +0021;EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +0022;QUOTATION MARK;Po;0;ON;;;;;N;;;;; +0023;NUMBER SIGN;Po;0;ET;;;;;N;;;;; +0024;DOLLAR SIGN;Sc;0;ET;;;;;N;;;;; +0025;PERCENT SIGN;Po;0;ET;;;;;N;;;;; +0026;AMPERSAND;Po;0;ON;;;;;N;;;;; +0027;APOSTROPHE;Po;0;ON;;;;;N;APOSTROPHE-QUOTE;;;; +0028;LEFT PARENTHESIS;Ps;0;ON;;;;;Y;OPENING PARENTHESIS;;;; +0029;RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;CLOSING PARENTHESIS;;;; +002A;ASTERISK;Po;0;ON;;;;;N;;;;; +002B;PLUS SIGN;Sm;0;ES;;;;;N;;;;; +002C;COMMA;Po;0;CS;;;;;N;;;;; +002D;HYPHEN-MINUS;Pd;0;ES;;;;;N;;;;; +002E;FULL STOP;Po;0;CS;;;;;N;PERIOD;;;; +002F;SOLIDUS;Po;0;CS;;;;;N;SLASH;;;; +0030;DIGIT ZERO;Nd;0;EN;;0;0;0;N;;;;; +0031;DIGIT ONE;Nd;0;EN;;1;1;1;N;;;;; +0032;DIGIT TWO;Nd;0;EN;;2;2;2;N;;;;; +0033;DIGIT THREE;Nd;0;EN;;3;3;3;N;;;;; +0034;DIGIT FOUR;Nd;0;EN;;4;4;4;N;;;;; +0035;DIGIT FIVE;Nd;0;EN;;5;5;5;N;;;;; +0036;DIGIT SIX;Nd;0;EN;;6;6;6;N;;;;; +0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;; +0038;DIGIT EIGHT;Nd;0;EN;;8;8;8;N;;;;; +0039;DIGIT NINE;Nd;0;EN;;9;9;9;N;;;;; +003A;COLON;Po;0;CS;;;;;N;;;;; +003B;SEMICOLON;Po;0;ON;;;;;N;;;;; +003C;LESS-THAN SIGN;Sm;0;ON;;;;;Y;;;;; +003D;EQUALS SIGN;Sm;0;ON;;;;;N;;;;; +003E;GREATER-THAN SIGN;Sm;0;ON;;;;;Y;;;;; +003F;QUESTION MARK;Po;0;ON;;;;;N;;;;; +0040;COMMERCIAL AT;Po;0;ON;;;;;N;;;;; +0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061; +0042;LATIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;0062; +0043;LATIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;0063; +0044;LATIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;0064; +0045;LATIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;0065; +0046;LATIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;0066; +0047;LATIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;0067; +0048;LATIN CAPITAL LETTER H;Lu;0;L;;;;;N;;;;0068; +0049;LATIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;0069; +004A;LATIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;006A; +004B;LATIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;006B; +004C;LATIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;006C; +004D;LATIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;006D; +004E;LATIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;006E; +004F;LATIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;006F; +0050;LATIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;0070; +0051;LATIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;0071; +0052;LATIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;0072; +0053;LATIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;0073; +0054;LATIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;0074; +0055;LATIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0075; +0056;LATIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;0076; +0057;LATIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;0077; +0058;LATIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;0078; +0059;LATIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;0079; +005A;LATIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;007A; +005B;LEFT SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING SQUARE BRACKET;;;; +005C;REVERSE SOLIDUS;Po;0;ON;;;;;N;BACKSLASH;;;; +005D;RIGHT SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING SQUARE BRACKET;;;; +005E;CIRCUMFLEX ACCENT;Sk;0;ON;;;;;N;SPACING CIRCUMFLEX;;;; +005F;LOW LINE;Pc;0;ON;;;;;N;SPACING UNDERSCORE;;;; +0060;GRAVE ACCENT;Sk;0;ON;;;;;N;SPACING GRAVE;;;; +0061;LATIN SMALL LETTER A;Ll;0;L;;;;;N;;;0041;;0041 +0062;LATIN SMALL LETTER B;Ll;0;L;;;;;N;;;0042;;0042 +0063;LATIN SMALL LETTER C;Ll;0;L;;;;;N;;;0043;;0043 +0064;LATIN SMALL LETTER D;Ll;0;L;;;;;N;;;0044;;0044 +0065;LATIN SMALL LETTER E;Ll;0;L;;;;;N;;;0045;;0045 +0066;LATIN SMALL LETTER F;Ll;0;L;;;;;N;;;0046;;0046 +0067;LATIN SMALL LETTER G;Ll;0;L;;;;;N;;;0047;;0047 +0068;LATIN SMALL LETTER H;Ll;0;L;;;;;N;;;0048;;0048 +0069;LATIN SMALL LETTER I;Ll;0;L;;;;;N;;;0049;;0049 +006A;LATIN SMALL LETTER J;Ll;0;L;;;;;N;;;004A;;004A +006B;LATIN SMALL LETTER K;Ll;0;L;;;;;N;;;004B;;004B +006C;LATIN SMALL LETTER L;Ll;0;L;;;;;N;;;004C;;004C +006D;LATIN SMALL LETTER M;Ll;0;L;;;;;N;;;004D;;004D +006E;LATIN SMALL LETTER N;Ll;0;L;;;;;N;;;004E;;004E +006F;LATIN SMALL LETTER O;Ll;0;L;;;;;N;;;004F;;004F +0070;LATIN SMALL LETTER P;Ll;0;L;;;;;N;;;0050;;0050 +0071;LATIN SMALL LETTER Q;Ll;0;L;;;;;N;;;0051;;0051 +0072;LATIN SMALL LETTER R;Ll;0;L;;;;;N;;;0052;;0052 +0073;LATIN SMALL LETTER S;Ll;0;L;;;;;N;;;0053;;0053 +0074;LATIN SMALL LETTER T;Ll;0;L;;;;;N;;;0054;;0054 +0075;LATIN SMALL LETTER U;Ll;0;L;;;;;N;;;0055;;0055 +0076;LATIN SMALL LETTER V;Ll;0;L;;;;;N;;;0056;;0056 +0077;LATIN SMALL LETTER W;Ll;0;L;;;;;N;;;0057;;0057 +0078;LATIN SMALL LETTER X;Ll;0;L;;;;;N;;;0058;;0058 +0079;LATIN SMALL LETTER Y;Ll;0;L;;;;;N;;;0059;;0059 +007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A +007B;LEFT CURLY BRACKET;Ps;0;ON;;;;;Y;OPENING CURLY BRACKET;;;; +007C;VERTICAL LINE;Sm;0;ON;;;;;N;VERTICAL BAR;;;; +007D;RIGHT CURLY BRACKET;Pe;0;ON;;;;;Y;CLOSING CURLY BRACKET;;;; +007E;TILDE;Sm;0;ON;;;;;N;;;;; +007F;;Cc;0;BN;;;;;N;DELETE;;;; +0080;;Cc;0;BN;;;;;N;;;;; +0081;;Cc;0;BN;;;;;N;;;;; +0082;;Cc;0;BN;;;;;N;BREAK PERMITTED HERE;;;; +0083;;Cc;0;BN;;;;;N;NO BREAK HERE;;;; +0084;;Cc;0;BN;;;;;N;;;;; +0085;;Cc;0;B;;;;;N;NEXT LINE (NEL);;;; +0086;;Cc;0;BN;;;;;N;START OF SELECTED AREA;;;; +0087;;Cc;0;BN;;;;;N;END OF SELECTED AREA;;;; +0088;;Cc;0;BN;;;;;N;CHARACTER TABULATION SET;;;; +0089;;Cc;0;BN;;;;;N;CHARACTER TABULATION WITH JUSTIFICATION;;;; +008A;;Cc;0;BN;;;;;N;LINE TABULATION SET;;;; +008B;;Cc;0;BN;;;;;N;PARTIAL LINE FORWARD;;;; +008C;;Cc;0;BN;;;;;N;PARTIAL LINE BACKWARD;;;; +008D;;Cc;0;BN;;;;;N;REVERSE LINE FEED;;;; +008E;;Cc;0;BN;;;;;N;SINGLE SHIFT TWO;;;; +008F;;Cc;0;BN;;;;;N;SINGLE SHIFT THREE;;;; +0090;;Cc;0;BN;;;;;N;DEVICE CONTROL STRING;;;; +0091;;Cc;0;BN;;;;;N;PRIVATE USE ONE;;;; +0092;;Cc;0;BN;;;;;N;PRIVATE USE TWO;;;; +0093;;Cc;0;BN;;;;;N;SET TRANSMIT STATE;;;; +0094;;Cc;0;BN;;;;;N;CANCEL CHARACTER;;;; +0095;;Cc;0;BN;;;;;N;MESSAGE WAITING;;;; +0096;;Cc;0;BN;;;;;N;START OF GUARDED AREA;;;; +0097;;Cc;0;BN;;;;;N;END OF GUARDED AREA;;;; +0098;;Cc;0;BN;;;;;N;START OF STRING;;;; +0099;;Cc;0;BN;;;;;N;;;;; +009A;;Cc;0;BN;;;;;N;SINGLE CHARACTER INTRODUCER;;;; +009B;;Cc;0;BN;;;;;N;CONTROL SEQUENCE INTRODUCER;;;; +009C;;Cc;0;BN;;;;;N;STRING TERMINATOR;;;; +009D;;Cc;0;BN;;;;;N;OPERATING SYSTEM COMMAND;;;; +009E;;Cc;0;BN;;;;;N;PRIVACY MESSAGE;;;; +009F;;Cc;0;BN;;;;;N;APPLICATION PROGRAM COMMAND;;;; +00A0;NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;NON-BREAKING SPACE;;;; +00A1;INVERTED EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +00A2;CENT SIGN;Sc;0;ET;;;;;N;;;;; +00A3;POUND SIGN;Sc;0;ET;;;;;N;;;;; +00A4;CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; +00A5;YEN SIGN;Sc;0;ET;;;;;N;;;;; +00A6;BROKEN BAR;So;0;ON;;;;;N;BROKEN VERTICAL BAR;;;; +00A7;SECTION SIGN;Po;0;ON;;;;;N;;;;; +00A8;DIAERESIS;Sk;0;ON; 0020 0308;;;;N;SPACING DIAERESIS;;;; +00A9;COPYRIGHT SIGN;So;0;ON;;;;;N;;;;; +00AA;FEMININE ORDINAL INDICATOR;Lo;0;L; 0061;;;;N;;;;; +00AB;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING GUILLEMET;;;; +00AC;NOT SIGN;Sm;0;ON;;;;;N;;;;; +00AD;SOFT HYPHEN;Cf;0;BN;;;;;N;;;;; +00AE;REGISTERED SIGN;So;0;ON;;;;;N;REGISTERED TRADE MARK SIGN;;;; +00AF;MACRON;Sk;0;ON; 0020 0304;;;;N;SPACING MACRON;;;; +00B0;DEGREE SIGN;So;0;ET;;;;;N;;;;; +00B1;PLUS-MINUS SIGN;Sm;0;ET;;;;;N;PLUS-OR-MINUS SIGN;;;; +00B2;SUPERSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUPERSCRIPT DIGIT TWO;;;; +00B3;SUPERSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUPERSCRIPT DIGIT THREE;;;; +00B4;ACUTE ACCENT;Sk;0;ON; 0020 0301;;;;N;SPACING ACUTE;;;; +00B5;MICRO SIGN;Ll;0;L; 03BC;;;;N;;;039C;;039C +00B6;PILCROW SIGN;Po;0;ON;;;;;N;PARAGRAPH SIGN;;;; +00B7;MIDDLE DOT;Po;0;ON;;;;;N;;;;; +00B8;CEDILLA;Sk;0;ON; 0020 0327;;;;N;SPACING CEDILLA;;;; +00B9;SUPERSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;; +00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L; 006F;;;;N;;;;; +00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;; +00BC;VULGAR FRACTION ONE QUARTER;No;0;ON; 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;; +00BD;VULGAR FRACTION ONE HALF;No;0;ON; 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;; +00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON; 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;; +00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;; +00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0; +00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1; +00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2; +00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3; +00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4; +00C5;LATIN CAPITAL LETTER A WITH RING ABOVE;Lu;0;L;0041 030A;;;;N;LATIN CAPITAL LETTER A RING;;;00E5; +00C6;LATIN CAPITAL LETTER AE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER A E;;;00E6; +00C7;LATIN CAPITAL LETTER C WITH CEDILLA;Lu;0;L;0043 0327;;;;N;LATIN CAPITAL LETTER C CEDILLA;;;00E7; +00C8;LATIN CAPITAL LETTER E WITH GRAVE;Lu;0;L;0045 0300;;;;N;LATIN CAPITAL LETTER E GRAVE;;;00E8; +00C9;LATIN CAPITAL LETTER E WITH ACUTE;Lu;0;L;0045 0301;;;;N;LATIN CAPITAL LETTER E ACUTE;;;00E9; +00CA;LATIN CAPITAL LETTER E WITH CIRCUMFLEX;Lu;0;L;0045 0302;;;;N;LATIN CAPITAL LETTER E CIRCUMFLEX;;;00EA; +00CB;LATIN CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;0045 0308;;;;N;LATIN CAPITAL LETTER E DIAERESIS;;;00EB; +00CC;LATIN CAPITAL LETTER I WITH GRAVE;Lu;0;L;0049 0300;;;;N;LATIN CAPITAL LETTER I GRAVE;;;00EC; +00CD;LATIN CAPITAL LETTER I WITH ACUTE;Lu;0;L;0049 0301;;;;N;LATIN CAPITAL LETTER I ACUTE;;;00ED; +00CE;LATIN CAPITAL LETTER I WITH CIRCUMFLEX;Lu;0;L;0049 0302;;;;N;LATIN CAPITAL LETTER I CIRCUMFLEX;;;00EE; +00CF;LATIN CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0049 0308;;;;N;LATIN CAPITAL LETTER I DIAERESIS;;;00EF; +00D0;LATIN CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;00F0; +00D1;LATIN CAPITAL LETTER N WITH TILDE;Lu;0;L;004E 0303;;;;N;LATIN CAPITAL LETTER N TILDE;;;00F1; +00D2;LATIN CAPITAL LETTER O WITH GRAVE;Lu;0;L;004F 0300;;;;N;LATIN CAPITAL LETTER O GRAVE;;;00F2; +00D3;LATIN CAPITAL LETTER O WITH ACUTE;Lu;0;L;004F 0301;;;;N;LATIN CAPITAL LETTER O ACUTE;;;00F3; +00D4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX;Lu;0;L;004F 0302;;;;N;LATIN CAPITAL LETTER O CIRCUMFLEX;;;00F4; +00D5;LATIN CAPITAL LETTER O WITH TILDE;Lu;0;L;004F 0303;;;;N;LATIN CAPITAL LETTER O TILDE;;;00F5; +00D6;LATIN CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;004F 0308;;;;N;LATIN CAPITAL LETTER O DIAERESIS;;;00F6; +00D7;MULTIPLICATION SIGN;Sm;0;ON;;;;;N;;;;; +00D8;LATIN CAPITAL LETTER O WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O SLASH;;;00F8; +00D9;LATIN CAPITAL LETTER U WITH GRAVE;Lu;0;L;0055 0300;;;;N;LATIN CAPITAL LETTER U GRAVE;;;00F9; +00DA;LATIN CAPITAL LETTER U WITH ACUTE;Lu;0;L;0055 0301;;;;N;LATIN CAPITAL LETTER U ACUTE;;;00FA; +00DB;LATIN CAPITAL LETTER U WITH CIRCUMFLEX;Lu;0;L;0055 0302;;;;N;LATIN CAPITAL LETTER U CIRCUMFLEX;;;00FB; +00DC;LATIN CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0055 0308;;;;N;LATIN CAPITAL LETTER U DIAERESIS;;;00FC; +00DD;LATIN CAPITAL LETTER Y WITH ACUTE;Lu;0;L;0059 0301;;;;N;LATIN CAPITAL LETTER Y ACUTE;;;00FD; +00DE;LATIN CAPITAL LETTER THORN;Lu;0;L;;;;;N;;;;00FE; +00DF;LATIN SMALL LETTER SHARP S;Ll;0;L;;;;;N;;;;; +00E0;LATIN SMALL LETTER A WITH GRAVE;Ll;0;L;0061 0300;;;;N;LATIN SMALL LETTER A GRAVE;;00C0;;00C0 +00E1;LATIN SMALL LETTER A WITH ACUTE;Ll;0;L;0061 0301;;;;N;LATIN SMALL LETTER A ACUTE;;00C1;;00C1 +00E2;LATIN SMALL LETTER A WITH CIRCUMFLEX;Ll;0;L;0061 0302;;;;N;LATIN SMALL LETTER A CIRCUMFLEX;;00C2;;00C2 +00E3;LATIN SMALL LETTER A WITH TILDE;Ll;0;L;0061 0303;;;;N;LATIN SMALL LETTER A TILDE;;00C3;;00C3 +00E4;LATIN SMALL LETTER A WITH DIAERESIS;Ll;0;L;0061 0308;;;;N;LATIN SMALL LETTER A DIAERESIS;;00C4;;00C4 +00E5;LATIN SMALL LETTER A WITH RING ABOVE;Ll;0;L;0061 030A;;;;N;LATIN SMALL LETTER A RING;;00C5;;00C5 +00E6;LATIN SMALL LETTER AE;Ll;0;L;;;;;N;LATIN SMALL LETTER A E;;00C6;;00C6 +00E7;LATIN SMALL LETTER C WITH CEDILLA;Ll;0;L;0063 0327;;;;N;LATIN SMALL LETTER C CEDILLA;;00C7;;00C7 +00E8;LATIN SMALL LETTER E WITH GRAVE;Ll;0;L;0065 0300;;;;N;LATIN SMALL LETTER E GRAVE;;00C8;;00C8 +00E9;LATIN SMALL LETTER E WITH ACUTE;Ll;0;L;0065 0301;;;;N;LATIN SMALL LETTER E ACUTE;;00C9;;00C9 +00EA;LATIN SMALL LETTER E WITH CIRCUMFLEX;Ll;0;L;0065 0302;;;;N;LATIN SMALL LETTER E CIRCUMFLEX;;00CA;;00CA +00EB;LATIN SMALL LETTER E WITH DIAERESIS;Ll;0;L;0065 0308;;;;N;LATIN SMALL LETTER E DIAERESIS;;00CB;;00CB +00EC;LATIN SMALL LETTER I WITH GRAVE;Ll;0;L;0069 0300;;;;N;LATIN SMALL LETTER I GRAVE;;00CC;;00CC +00ED;LATIN SMALL LETTER I WITH ACUTE;Ll;0;L;0069 0301;;;;N;LATIN SMALL LETTER I ACUTE;;00CD;;00CD +00EE;LATIN SMALL LETTER I WITH CIRCUMFLEX;Ll;0;L;0069 0302;;;;N;LATIN SMALL LETTER I CIRCUMFLEX;;00CE;;00CE +00EF;LATIN SMALL LETTER I WITH DIAERESIS;Ll;0;L;0069 0308;;;;N;LATIN SMALL LETTER I DIAERESIS;;00CF;;00CF +00F0;LATIN SMALL LETTER ETH;Ll;0;L;;;;;N;;;00D0;;00D0 +00F1;LATIN SMALL LETTER N WITH TILDE;Ll;0;L;006E 0303;;;;N;LATIN SMALL LETTER N TILDE;;00D1;;00D1 +00F2;LATIN SMALL LETTER O WITH GRAVE;Ll;0;L;006F 0300;;;;N;LATIN SMALL LETTER O GRAVE;;00D2;;00D2 +00F3;LATIN SMALL LETTER O WITH ACUTE;Ll;0;L;006F 0301;;;;N;LATIN SMALL LETTER O ACUTE;;00D3;;00D3 +00F4;LATIN SMALL LETTER O WITH CIRCUMFLEX;Ll;0;L;006F 0302;;;;N;LATIN SMALL LETTER O CIRCUMFLEX;;00D4;;00D4 +00F5;LATIN SMALL LETTER O WITH TILDE;Ll;0;L;006F 0303;;;;N;LATIN SMALL LETTER O TILDE;;00D5;;00D5 +00F6;LATIN SMALL LETTER O WITH DIAERESIS;Ll;0;L;006F 0308;;;;N;LATIN SMALL LETTER O DIAERESIS;;00D6;;00D6 +00F7;DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +00F8;LATIN SMALL LETTER O WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER O SLASH;;00D8;;00D8 +00F9;LATIN SMALL LETTER U WITH GRAVE;Ll;0;L;0075 0300;;;;N;LATIN SMALL LETTER U GRAVE;;00D9;;00D9 +00FA;LATIN SMALL LETTER U WITH ACUTE;Ll;0;L;0075 0301;;;;N;LATIN SMALL LETTER U ACUTE;;00DA;;00DA +00FB;LATIN SMALL LETTER U WITH CIRCUMFLEX;Ll;0;L;0075 0302;;;;N;LATIN SMALL LETTER U CIRCUMFLEX;;00DB;;00DB +00FC;LATIN SMALL LETTER U WITH DIAERESIS;Ll;0;L;0075 0308;;;;N;LATIN SMALL LETTER U DIAERESIS;;00DC;;00DC +00FD;LATIN SMALL LETTER Y WITH ACUTE;Ll;0;L;0079 0301;;;;N;LATIN SMALL LETTER Y ACUTE;;00DD;;00DD +00FE;LATIN SMALL LETTER THORN;Ll;0;L;;;;;N;;;00DE;;00DE +00FF;LATIN SMALL LETTER Y WITH DIAERESIS;Ll;0;L;0079 0308;;;;N;LATIN SMALL LETTER Y DIAERESIS;;0178;;0178 +0100;LATIN CAPITAL LETTER A WITH MACRON;Lu;0;L;0041 0304;;;;N;LATIN CAPITAL LETTER A MACRON;;;0101; +0101;LATIN SMALL LETTER A WITH MACRON;Ll;0;L;0061 0304;;;;N;LATIN SMALL LETTER A MACRON;;0100;;0100 +0102;LATIN CAPITAL LETTER A WITH BREVE;Lu;0;L;0041 0306;;;;N;LATIN CAPITAL LETTER A BREVE;;;0103; +0103;LATIN SMALL LETTER A WITH BREVE;Ll;0;L;0061 0306;;;;N;LATIN SMALL LETTER A BREVE;;0102;;0102 +0104;LATIN CAPITAL LETTER A WITH OGONEK;Lu;0;L;0041 0328;;;;N;LATIN CAPITAL LETTER A OGONEK;;;0105; +0105;LATIN SMALL LETTER A WITH OGONEK;Ll;0;L;0061 0328;;;;N;LATIN SMALL LETTER A OGONEK;;0104;;0104 +0106;LATIN CAPITAL LETTER C WITH ACUTE;Lu;0;L;0043 0301;;;;N;LATIN CAPITAL LETTER C ACUTE;;;0107; +0107;LATIN SMALL LETTER C WITH ACUTE;Ll;0;L;0063 0301;;;;N;LATIN SMALL LETTER C ACUTE;;0106;;0106 +0108;LATIN CAPITAL LETTER C WITH CIRCUMFLEX;Lu;0;L;0043 0302;;;;N;LATIN CAPITAL LETTER C CIRCUMFLEX;;;0109; +0109;LATIN SMALL LETTER C WITH CIRCUMFLEX;Ll;0;L;0063 0302;;;;N;LATIN SMALL LETTER C CIRCUMFLEX;;0108;;0108 +010A;LATIN CAPITAL LETTER C WITH DOT ABOVE;Lu;0;L;0043 0307;;;;N;LATIN CAPITAL LETTER C DOT;;;010B; +010B;LATIN SMALL LETTER C WITH DOT ABOVE;Ll;0;L;0063 0307;;;;N;LATIN SMALL LETTER C DOT;;010A;;010A +010C;LATIN CAPITAL LETTER C WITH CARON;Lu;0;L;0043 030C;;;;N;LATIN CAPITAL LETTER C HACEK;;;010D; +010D;LATIN SMALL LETTER C WITH CARON;Ll;0;L;0063 030C;;;;N;LATIN SMALL LETTER C HACEK;;010C;;010C +010E;LATIN CAPITAL LETTER D WITH CARON;Lu;0;L;0044 030C;;;;N;LATIN CAPITAL LETTER D HACEK;;;010F; +010F;LATIN SMALL LETTER D WITH CARON;Ll;0;L;0064 030C;;;;N;LATIN SMALL LETTER D HACEK;;010E;;010E +0110;LATIN CAPITAL LETTER D WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D BAR;;;0111; +0111;LATIN SMALL LETTER D WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER D BAR;;0110;;0110 +0112;LATIN CAPITAL LETTER E WITH MACRON;Lu;0;L;0045 0304;;;;N;LATIN CAPITAL LETTER E MACRON;;;0113; +0113;LATIN SMALL LETTER E WITH MACRON;Ll;0;L;0065 0304;;;;N;LATIN SMALL LETTER E MACRON;;0112;;0112 +0114;LATIN CAPITAL LETTER E WITH BREVE;Lu;0;L;0045 0306;;;;N;LATIN CAPITAL LETTER E BREVE;;;0115; +0115;LATIN SMALL LETTER E WITH BREVE;Ll;0;L;0065 0306;;;;N;LATIN SMALL LETTER E BREVE;;0114;;0114 +0116;LATIN CAPITAL LETTER E WITH DOT ABOVE;Lu;0;L;0045 0307;;;;N;LATIN CAPITAL LETTER E DOT;;;0117; +0117;LATIN SMALL LETTER E WITH DOT ABOVE;Ll;0;L;0065 0307;;;;N;LATIN SMALL LETTER E DOT;;0116;;0116 +0118;LATIN CAPITAL LETTER E WITH OGONEK;Lu;0;L;0045 0328;;;;N;LATIN CAPITAL LETTER E OGONEK;;;0119; +0119;LATIN SMALL LETTER E WITH OGONEK;Ll;0;L;0065 0328;;;;N;LATIN SMALL LETTER E OGONEK;;0118;;0118 +011A;LATIN CAPITAL LETTER E WITH CARON;Lu;0;L;0045 030C;;;;N;LATIN CAPITAL LETTER E HACEK;;;011B; +011B;LATIN SMALL LETTER E WITH CARON;Ll;0;L;0065 030C;;;;N;LATIN SMALL LETTER E HACEK;;011A;;011A +011C;LATIN CAPITAL LETTER G WITH CIRCUMFLEX;Lu;0;L;0047 0302;;;;N;LATIN CAPITAL LETTER G CIRCUMFLEX;;;011D; +011D;LATIN SMALL LETTER G WITH CIRCUMFLEX;Ll;0;L;0067 0302;;;;N;LATIN SMALL LETTER G CIRCUMFLEX;;011C;;011C +011E;LATIN CAPITAL LETTER G WITH BREVE;Lu;0;L;0047 0306;;;;N;LATIN CAPITAL LETTER G BREVE;;;011F; +011F;LATIN SMALL LETTER G WITH BREVE;Ll;0;L;0067 0306;;;;N;LATIN SMALL LETTER G BREVE;;011E;;011E +0120;LATIN CAPITAL LETTER G WITH DOT ABOVE;Lu;0;L;0047 0307;;;;N;LATIN CAPITAL LETTER G DOT;;;0121; +0121;LATIN SMALL LETTER G WITH DOT ABOVE;Ll;0;L;0067 0307;;;;N;LATIN SMALL LETTER G DOT;;0120;;0120 +0122;LATIN CAPITAL LETTER G WITH CEDILLA;Lu;0;L;0047 0327;;;;N;LATIN CAPITAL LETTER G CEDILLA;;;0123; +0123;LATIN SMALL LETTER G WITH CEDILLA;Ll;0;L;0067 0327;;;;N;LATIN SMALL LETTER G CEDILLA;;0122;;0122 +0124;LATIN CAPITAL LETTER H WITH CIRCUMFLEX;Lu;0;L;0048 0302;;;;N;LATIN CAPITAL LETTER H CIRCUMFLEX;;;0125; +0125;LATIN SMALL LETTER H WITH CIRCUMFLEX;Ll;0;L;0068 0302;;;;N;LATIN SMALL LETTER H CIRCUMFLEX;;0124;;0124 +0126;LATIN CAPITAL LETTER H WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER H BAR;;;0127; +0127;LATIN SMALL LETTER H WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER H BAR;;0126;;0126 +0128;LATIN CAPITAL LETTER I WITH TILDE;Lu;0;L;0049 0303;;;;N;LATIN CAPITAL LETTER I TILDE;;;0129; +0129;LATIN SMALL LETTER I WITH TILDE;Ll;0;L;0069 0303;;;;N;LATIN SMALL LETTER I TILDE;;0128;;0128 +012A;LATIN CAPITAL LETTER I WITH MACRON;Lu;0;L;0049 0304;;;;N;LATIN CAPITAL LETTER I MACRON;;;012B; +012B;LATIN SMALL LETTER I WITH MACRON;Ll;0;L;0069 0304;;;;N;LATIN SMALL LETTER I MACRON;;012A;;012A +012C;LATIN CAPITAL LETTER I WITH BREVE;Lu;0;L;0049 0306;;;;N;LATIN CAPITAL LETTER I BREVE;;;012D; +012D;LATIN SMALL LETTER I WITH BREVE;Ll;0;L;0069 0306;;;;N;LATIN SMALL LETTER I BREVE;;012C;;012C +012E;LATIN CAPITAL LETTER I WITH OGONEK;Lu;0;L;0049 0328;;;;N;LATIN CAPITAL LETTER I OGONEK;;;012F; +012F;LATIN SMALL LETTER I WITH OGONEK;Ll;0;L;0069 0328;;;;N;LATIN SMALL LETTER I OGONEK;;012E;;012E +0130;LATIN CAPITAL LETTER I WITH DOT ABOVE;Lu;0;L;0049 0307;;;;N;LATIN CAPITAL LETTER I DOT;;;0069; +0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 +0132;LATIN CAPITAL LIGATURE IJ;Lu;0;L; 0049 004A;;;;N;LATIN CAPITAL LETTER I J;;;0133; +0133;LATIN SMALL LIGATURE IJ;Ll;0;L; 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 +0134;LATIN CAPITAL LETTER J WITH CIRCUMFLEX;Lu;0;L;004A 0302;;;;N;LATIN CAPITAL LETTER J CIRCUMFLEX;;;0135; +0135;LATIN SMALL LETTER J WITH CIRCUMFLEX;Ll;0;L;006A 0302;;;;N;LATIN SMALL LETTER J CIRCUMFLEX;;0134;;0134 +0136;LATIN CAPITAL LETTER K WITH CEDILLA;Lu;0;L;004B 0327;;;;N;LATIN CAPITAL LETTER K CEDILLA;;;0137; +0137;LATIN SMALL LETTER K WITH CEDILLA;Ll;0;L;006B 0327;;;;N;LATIN SMALL LETTER K CEDILLA;;0136;;0136 +0138;LATIN SMALL LETTER KRA;Ll;0;L;;;;;N;;;;; +0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; +013A;LATIN SMALL LETTER L WITH ACUTE;Ll;0;L;006C 0301;;;;N;LATIN SMALL LETTER L ACUTE;;0139;;0139 +013B;LATIN CAPITAL LETTER L WITH CEDILLA;Lu;0;L;004C 0327;;;;N;LATIN CAPITAL LETTER L CEDILLA;;;013C; +013C;LATIN SMALL LETTER L WITH CEDILLA;Ll;0;L;006C 0327;;;;N;LATIN SMALL LETTER L CEDILLA;;013B;;013B +013D;LATIN CAPITAL LETTER L WITH CARON;Lu;0;L;004C 030C;;;;N;LATIN CAPITAL LETTER L HACEK;;;013E; +013E;LATIN SMALL LETTER L WITH CARON;Ll;0;L;006C 030C;;;;N;LATIN SMALL LETTER L HACEK;;013D;;013D +013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L; 004C 00B7;;;;N;;;;0140; +0140;LATIN SMALL LETTER L WITH MIDDLE DOT;Ll;0;L; 006C 00B7;;;;N;;;013F;;013F +0141;LATIN CAPITAL LETTER L WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER L SLASH;;;0142; +0142;LATIN SMALL LETTER L WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER L SLASH;;0141;;0141 +0143;LATIN CAPITAL LETTER N WITH ACUTE;Lu;0;L;004E 0301;;;;N;LATIN CAPITAL LETTER N ACUTE;;;0144; +0144;LATIN SMALL LETTER N WITH ACUTE;Ll;0;L;006E 0301;;;;N;LATIN SMALL LETTER N ACUTE;;0143;;0143 +0145;LATIN CAPITAL LETTER N WITH CEDILLA;Lu;0;L;004E 0327;;;;N;LATIN CAPITAL LETTER N CEDILLA;;;0146; +0146;LATIN SMALL LETTER N WITH CEDILLA;Ll;0;L;006E 0327;;;;N;LATIN SMALL LETTER N CEDILLA;;0145;;0145 +0147;LATIN CAPITAL LETTER N WITH CARON;Lu;0;L;004E 030C;;;;N;LATIN CAPITAL LETTER N HACEK;;;0148; +0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 +0149;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE;Ll;0;L; 02BC 006E;;;;N;LATIN SMALL LETTER APOSTROPHE N;;;; +014A;LATIN CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;014B; +014B;LATIN SMALL LETTER ENG;Ll;0;L;;;;;N;;;014A;;014A +014C;LATIN CAPITAL LETTER O WITH MACRON;Lu;0;L;004F 0304;;;;N;LATIN CAPITAL LETTER O MACRON;;;014D; +014D;LATIN SMALL LETTER O WITH MACRON;Ll;0;L;006F 0304;;;;N;LATIN SMALL LETTER O MACRON;;014C;;014C +014E;LATIN CAPITAL LETTER O WITH BREVE;Lu;0;L;004F 0306;;;;N;LATIN CAPITAL LETTER O BREVE;;;014F; +014F;LATIN SMALL LETTER O WITH BREVE;Ll;0;L;006F 0306;;;;N;LATIN SMALL LETTER O BREVE;;014E;;014E +0150;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE;Lu;0;L;004F 030B;;;;N;LATIN CAPITAL LETTER O DOUBLE ACUTE;;;0151; +0151;LATIN SMALL LETTER O WITH DOUBLE ACUTE;Ll;0;L;006F 030B;;;;N;LATIN SMALL LETTER O DOUBLE ACUTE;;0150;;0150 +0152;LATIN CAPITAL LIGATURE OE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O E;;;0153; +0153;LATIN SMALL LIGATURE OE;Ll;0;L;;;;;N;LATIN SMALL LETTER O E;;0152;;0152 +0154;LATIN CAPITAL LETTER R WITH ACUTE;Lu;0;L;0052 0301;;;;N;LATIN CAPITAL LETTER R ACUTE;;;0155; +0155;LATIN SMALL LETTER R WITH ACUTE;Ll;0;L;0072 0301;;;;N;LATIN SMALL LETTER R ACUTE;;0154;;0154 +0156;LATIN CAPITAL LETTER R WITH CEDILLA;Lu;0;L;0052 0327;;;;N;LATIN CAPITAL LETTER R CEDILLA;;;0157; +0157;LATIN SMALL LETTER R WITH CEDILLA;Ll;0;L;0072 0327;;;;N;LATIN SMALL LETTER R CEDILLA;;0156;;0156 +0158;LATIN CAPITAL LETTER R WITH CARON;Lu;0;L;0052 030C;;;;N;LATIN CAPITAL LETTER R HACEK;;;0159; +0159;LATIN SMALL LETTER R WITH CARON;Ll;0;L;0072 030C;;;;N;LATIN SMALL LETTER R HACEK;;0158;;0158 +015A;LATIN CAPITAL LETTER S WITH ACUTE;Lu;0;L;0053 0301;;;;N;LATIN CAPITAL LETTER S ACUTE;;;015B; +015B;LATIN SMALL LETTER S WITH ACUTE;Ll;0;L;0073 0301;;;;N;LATIN SMALL LETTER S ACUTE;;015A;;015A +015C;LATIN CAPITAL LETTER S WITH CIRCUMFLEX;Lu;0;L;0053 0302;;;;N;LATIN CAPITAL LETTER S CIRCUMFLEX;;;015D; +015D;LATIN SMALL LETTER S WITH CIRCUMFLEX;Ll;0;L;0073 0302;;;;N;LATIN SMALL LETTER S CIRCUMFLEX;;015C;;015C +015E;LATIN CAPITAL LETTER S WITH CEDILLA;Lu;0;L;0053 0327;;;;N;LATIN CAPITAL LETTER S CEDILLA;;;015F; +015F;LATIN SMALL LETTER S WITH CEDILLA;Ll;0;L;0073 0327;;;;N;LATIN SMALL LETTER S CEDILLA;;015E;;015E +0160;LATIN CAPITAL LETTER S WITH CARON;Lu;0;L;0053 030C;;;;N;LATIN CAPITAL LETTER S HACEK;;;0161; +0161;LATIN SMALL LETTER S WITH CARON;Ll;0;L;0073 030C;;;;N;LATIN SMALL LETTER S HACEK;;0160;;0160 +0162;LATIN CAPITAL LETTER T WITH CEDILLA;Lu;0;L;0054 0327;;;;N;LATIN CAPITAL LETTER T CEDILLA;;;0163; +0163;LATIN SMALL LETTER T WITH CEDILLA;Ll;0;L;0074 0327;;;;N;LATIN SMALL LETTER T CEDILLA;;0162;;0162 +0164;LATIN CAPITAL LETTER T WITH CARON;Lu;0;L;0054 030C;;;;N;LATIN CAPITAL LETTER T HACEK;;;0165; +0165;LATIN SMALL LETTER T WITH CARON;Ll;0;L;0074 030C;;;;N;LATIN SMALL LETTER T HACEK;;0164;;0164 +0166;LATIN CAPITAL LETTER T WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T BAR;;;0167; +0167;LATIN SMALL LETTER T WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER T BAR;;0166;;0166 +0168;LATIN CAPITAL LETTER U WITH TILDE;Lu;0;L;0055 0303;;;;N;LATIN CAPITAL LETTER U TILDE;;;0169; +0169;LATIN SMALL LETTER U WITH TILDE;Ll;0;L;0075 0303;;;;N;LATIN SMALL LETTER U TILDE;;0168;;0168 +016A;LATIN CAPITAL LETTER U WITH MACRON;Lu;0;L;0055 0304;;;;N;LATIN CAPITAL LETTER U MACRON;;;016B; +016B;LATIN SMALL LETTER U WITH MACRON;Ll;0;L;0075 0304;;;;N;LATIN SMALL LETTER U MACRON;;016A;;016A +016C;LATIN CAPITAL LETTER U WITH BREVE;Lu;0;L;0055 0306;;;;N;LATIN CAPITAL LETTER U BREVE;;;016D; +016D;LATIN SMALL LETTER U WITH BREVE;Ll;0;L;0075 0306;;;;N;LATIN SMALL LETTER U BREVE;;016C;;016C +016E;LATIN CAPITAL LETTER U WITH RING ABOVE;Lu;0;L;0055 030A;;;;N;LATIN CAPITAL LETTER U RING;;;016F; +016F;LATIN SMALL LETTER U WITH RING ABOVE;Ll;0;L;0075 030A;;;;N;LATIN SMALL LETTER U RING;;016E;;016E +0170;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0055 030B;;;;N;LATIN CAPITAL LETTER U DOUBLE ACUTE;;;0171; +0171;LATIN SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0075 030B;;;;N;LATIN SMALL LETTER U DOUBLE ACUTE;;0170;;0170 +0172;LATIN CAPITAL LETTER U WITH OGONEK;Lu;0;L;0055 0328;;;;N;LATIN CAPITAL LETTER U OGONEK;;;0173; +0173;LATIN SMALL LETTER U WITH OGONEK;Ll;0;L;0075 0328;;;;N;LATIN SMALL LETTER U OGONEK;;0172;;0172 +0174;LATIN CAPITAL LETTER W WITH CIRCUMFLEX;Lu;0;L;0057 0302;;;;N;LATIN CAPITAL LETTER W CIRCUMFLEX;;;0175; +0175;LATIN SMALL LETTER W WITH CIRCUMFLEX;Ll;0;L;0077 0302;;;;N;LATIN SMALL LETTER W CIRCUMFLEX;;0174;;0174 +0176;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX;Lu;0;L;0059 0302;;;;N;LATIN CAPITAL LETTER Y CIRCUMFLEX;;;0177; +0177;LATIN SMALL LETTER Y WITH CIRCUMFLEX;Ll;0;L;0079 0302;;;;N;LATIN SMALL LETTER Y CIRCUMFLEX;;0176;;0176 +0178;LATIN CAPITAL LETTER Y WITH DIAERESIS;Lu;0;L;0059 0308;;;;N;LATIN CAPITAL LETTER Y DIAERESIS;;;00FF; +0179;LATIN CAPITAL LETTER Z WITH ACUTE;Lu;0;L;005A 0301;;;;N;LATIN CAPITAL LETTER Z ACUTE;;;017A; +017A;LATIN SMALL LETTER Z WITH ACUTE;Ll;0;L;007A 0301;;;;N;LATIN SMALL LETTER Z ACUTE;;0179;;0179 +017B;LATIN CAPITAL LETTER Z WITH DOT ABOVE;Lu;0;L;005A 0307;;;;N;LATIN CAPITAL LETTER Z DOT;;;017C; +017C;LATIN SMALL LETTER Z WITH DOT ABOVE;Ll;0;L;007A 0307;;;;N;LATIN SMALL LETTER Z DOT;;017B;;017B +017D;LATIN CAPITAL LETTER Z WITH CARON;Lu;0;L;005A 030C;;;;N;LATIN CAPITAL LETTER Z HACEK;;;017E; +017E;LATIN SMALL LETTER Z WITH CARON;Ll;0;L;007A 030C;;;;N;LATIN SMALL LETTER Z HACEK;;017D;;017D +017F;LATIN SMALL LETTER LONG S;Ll;0;L; 0073;;;;N;;;0053;;0053 +0180;LATIN SMALL LETTER B WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER B BAR;;0243;;0243 +0181;LATIN CAPITAL LETTER B WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B HOOK;;;0253; +0182;LATIN CAPITAL LETTER B WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER B TOPBAR;;;0183; +0183;LATIN SMALL LETTER B WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER B TOPBAR;;0182;;0182 +0184;LATIN CAPITAL LETTER TONE SIX;Lu;0;L;;;;;N;;;;0185; +0185;LATIN SMALL LETTER TONE SIX;Ll;0;L;;;;;N;;;0184;;0184 +0186;LATIN CAPITAL LETTER OPEN O;Lu;0;L;;;;;N;;;;0254; +0187;LATIN CAPITAL LETTER C WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER C HOOK;;;0188; +0188;LATIN SMALL LETTER C WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER C HOOK;;0187;;0187 +0189;LATIN CAPITAL LETTER AFRICAN D;Lu;0;L;;;;;N;;;;0256; +018A;LATIN CAPITAL LETTER D WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D HOOK;;;0257; +018B;LATIN CAPITAL LETTER D WITH TOPBAR;Lu;0;L;;;;;N;LATIN CAPITAL LETTER D TOPBAR;;;018C; +018C;LATIN SMALL LETTER D WITH TOPBAR;Ll;0;L;;;;;N;LATIN SMALL LETTER D TOPBAR;;018B;;018B +018D;LATIN SMALL LETTER TURNED DELTA;Ll;0;L;;;;;N;;;;; +018E;LATIN CAPITAL LETTER REVERSED E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER TURNED E;;;01DD; +018F;LATIN CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;0259; +0190;LATIN CAPITAL LETTER OPEN E;Lu;0;L;;;;;N;LATIN CAPITAL LETTER EPSILON;;;025B; +0191;LATIN CAPITAL LETTER F WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER F HOOK;;;0192; +0192;LATIN SMALL LETTER F WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT F;;0191;;0191 +0193;LATIN CAPITAL LETTER G WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G HOOK;;;0260; +0194;LATIN CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;0263; +0195;LATIN SMALL LETTER HV;Ll;0;L;;;;;N;LATIN SMALL LETTER H V;;01F6;;01F6 +0196;LATIN CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;0269; +0197;LATIN CAPITAL LETTER I WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED I;;;0268; +0198;LATIN CAPITAL LETTER K WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER K HOOK;;;0199; +0199;LATIN SMALL LETTER K WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER K HOOK;;0198;;0198 +019A;LATIN SMALL LETTER L WITH BAR;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED L;;023D;;023D +019B;LATIN SMALL LETTER LAMBDA WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED LAMBDA;;A7DC;;A7DC +019C;LATIN CAPITAL LETTER TURNED M;Lu;0;L;;;;;N;;;;026F; +019D;LATIN CAPITAL LETTER N WITH LEFT HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER N HOOK;;;0272; +019E;LATIN SMALL LETTER N WITH LONG RIGHT LEG;Ll;0;L;;;;;N;;;0220;;0220 +019F;LATIN CAPITAL LETTER O WITH MIDDLE TILDE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER BARRED O;;;0275; +01A0;LATIN CAPITAL LETTER O WITH HORN;Lu;0;L;004F 031B;;;;N;LATIN CAPITAL LETTER O HORN;;;01A1; +01A1;LATIN SMALL LETTER O WITH HORN;Ll;0;L;006F 031B;;;;N;LATIN SMALL LETTER O HORN;;01A0;;01A0 +01A2;LATIN CAPITAL LETTER OI;Lu;0;L;;;;;N;LATIN CAPITAL LETTER O I;;;01A3; +01A3;LATIN SMALL LETTER OI;Ll;0;L;;;;;N;LATIN SMALL LETTER O I;;01A2;;01A2 +01A4;LATIN CAPITAL LETTER P WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER P HOOK;;;01A5; +01A5;LATIN SMALL LETTER P WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER P HOOK;;01A4;;01A4 +01A6;LATIN LETTER YR;Lu;0;L;;;;;N;LATIN LETTER Y R;;;0280; +01A7;LATIN CAPITAL LETTER TONE TWO;Lu;0;L;;;;;N;;;;01A8; +01A8;LATIN SMALL LETTER TONE TWO;Ll;0;L;;;;;N;;;01A7;;01A7 +01A9;LATIN CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;0283; +01AA;LATIN LETTER REVERSED ESH LOOP;Ll;0;L;;;;;N;;;;; +01AB;LATIN SMALL LETTER T WITH PALATAL HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T PALATAL HOOK;;;; +01AC;LATIN CAPITAL LETTER T WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T HOOK;;;01AD; +01AD;LATIN SMALL LETTER T WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T HOOK;;01AC;;01AC +01AE;LATIN CAPITAL LETTER T WITH RETROFLEX HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER T RETROFLEX HOOK;;;0288; +01AF;LATIN CAPITAL LETTER U WITH HORN;Lu;0;L;0055 031B;;;;N;LATIN CAPITAL LETTER U HORN;;;01B0; +01B0;LATIN SMALL LETTER U WITH HORN;Ll;0;L;0075 031B;;;;N;LATIN SMALL LETTER U HORN;;01AF;;01AF +01B1;LATIN CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;028A; +01B2;LATIN CAPITAL LETTER V WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER SCRIPT V;;;028B; +01B3;LATIN CAPITAL LETTER Y WITH HOOK;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Y HOOK;;;01B4; +01B4;LATIN SMALL LETTER Y WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Y HOOK;;01B3;;01B3 +01B5;LATIN CAPITAL LETTER Z WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER Z BAR;;;01B6; +01B6;LATIN SMALL LETTER Z WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER Z BAR;;01B5;;01B5 +01B7;LATIN CAPITAL LETTER EZH;Lu;0;L;;;;;N;LATIN CAPITAL LETTER YOGH;;;0292; +01B8;LATIN CAPITAL LETTER EZH REVERSED;Lu;0;L;;;;;N;LATIN CAPITAL LETTER REVERSED YOGH;;;01B9; +01B9;LATIN SMALL LETTER EZH REVERSED;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED YOGH;;01B8;;01B8 +01BA;LATIN SMALL LETTER EZH WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH WITH TAIL;;;; +01BB;LATIN LETTER TWO WITH STROKE;Lo;0;L;;;;;N;LATIN LETTER TWO BAR;;;; +01BC;LATIN CAPITAL LETTER TONE FIVE;Lu;0;L;;;;;N;;;;01BD; +01BD;LATIN SMALL LETTER TONE FIVE;Ll;0;L;;;;;N;;;01BC;;01BC +01BE;LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER INVERTED GLOTTAL STOP BAR;;;; +01BF;LATIN LETTER WYNN;Ll;0;L;;;;;N;;;01F7;;01F7 +01C0;LATIN LETTER DENTAL CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE;;;; +01C1;LATIN LETTER LATERAL CLICK;Lo;0;L;;;;;N;LATIN LETTER DOUBLE PIPE;;;; +01C2;LATIN LETTER ALVEOLAR CLICK;Lo;0;L;;;;;N;LATIN LETTER PIPE DOUBLE BAR;;;; +01C3;LATIN LETTER RETROFLEX CLICK;Lo;0;L;;;;;N;LATIN LETTER EXCLAMATION MARK;;;; +01C4;LATIN CAPITAL LETTER DZ WITH CARON;Lu;0;L; 0044 017D;;;;N;LATIN CAPITAL LETTER D Z HACEK;;;01C6;01C5 +01C5;LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON;Lt;0;L; 0044 017E;;;;N;LATIN LETTER CAPITAL D SMALL Z HACEK;;01C4;01C6;01C5 +01C6;LATIN SMALL LETTER DZ WITH CARON;Ll;0;L; 0064 017E;;;;N;LATIN SMALL LETTER D Z HACEK;;01C4;;01C5 +01C7;LATIN CAPITAL LETTER LJ;Lu;0;L; 004C 004A;;;;N;LATIN CAPITAL LETTER L J;;;01C9;01C8 +01C8;LATIN CAPITAL LETTER L WITH SMALL LETTER J;Lt;0;L; 004C 006A;;;;N;LATIN LETTER CAPITAL L SMALL J;;01C7;01C9;01C8 +01C9;LATIN SMALL LETTER LJ;Ll;0;L; 006C 006A;;;;N;LATIN SMALL LETTER L J;;01C7;;01C8 +01CA;LATIN CAPITAL LETTER NJ;Lu;0;L; 004E 004A;;;;N;LATIN CAPITAL LETTER N J;;;01CC;01CB +01CB;LATIN CAPITAL LETTER N WITH SMALL LETTER J;Lt;0;L; 004E 006A;;;;N;LATIN LETTER CAPITAL N SMALL J;;01CA;01CC;01CB +01CC;LATIN SMALL LETTER NJ;Ll;0;L; 006E 006A;;;;N;LATIN SMALL LETTER N J;;01CA;;01CB +01CD;LATIN CAPITAL LETTER A WITH CARON;Lu;0;L;0041 030C;;;;N;LATIN CAPITAL LETTER A HACEK;;;01CE; +01CE;LATIN SMALL LETTER A WITH CARON;Ll;0;L;0061 030C;;;;N;LATIN SMALL LETTER A HACEK;;01CD;;01CD +01CF;LATIN CAPITAL LETTER I WITH CARON;Lu;0;L;0049 030C;;;;N;LATIN CAPITAL LETTER I HACEK;;;01D0; +01D0;LATIN SMALL LETTER I WITH CARON;Ll;0;L;0069 030C;;;;N;LATIN SMALL LETTER I HACEK;;01CF;;01CF +01D1;LATIN CAPITAL LETTER O WITH CARON;Lu;0;L;004F 030C;;;;N;LATIN CAPITAL LETTER O HACEK;;;01D2; +01D2;LATIN SMALL LETTER O WITH CARON;Ll;0;L;006F 030C;;;;N;LATIN SMALL LETTER O HACEK;;01D1;;01D1 +01D3;LATIN CAPITAL LETTER U WITH CARON;Lu;0;L;0055 030C;;;;N;LATIN CAPITAL LETTER U HACEK;;;01D4; +01D4;LATIN SMALL LETTER U WITH CARON;Ll;0;L;0075 030C;;;;N;LATIN SMALL LETTER U HACEK;;01D3;;01D3 +01D5;LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON;Lu;0;L;00DC 0304;;;;N;LATIN CAPITAL LETTER U DIAERESIS MACRON;;;01D6; +01D6;LATIN SMALL LETTER U WITH DIAERESIS AND MACRON;Ll;0;L;00FC 0304;;;;N;LATIN SMALL LETTER U DIAERESIS MACRON;;01D5;;01D5 +01D7;LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE;Lu;0;L;00DC 0301;;;;N;LATIN CAPITAL LETTER U DIAERESIS ACUTE;;;01D8; +01D8;LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE;Ll;0;L;00FC 0301;;;;N;LATIN SMALL LETTER U DIAERESIS ACUTE;;01D7;;01D7 +01D9;LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON;Lu;0;L;00DC 030C;;;;N;LATIN CAPITAL LETTER U DIAERESIS HACEK;;;01DA; +01DA;LATIN SMALL LETTER U WITH DIAERESIS AND CARON;Ll;0;L;00FC 030C;;;;N;LATIN SMALL LETTER U DIAERESIS HACEK;;01D9;;01D9 +01DB;LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE;Lu;0;L;00DC 0300;;;;N;LATIN CAPITAL LETTER U DIAERESIS GRAVE;;;01DC; +01DC;LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE;Ll;0;L;00FC 0300;;;;N;LATIN SMALL LETTER U DIAERESIS GRAVE;;01DB;;01DB +01DD;LATIN SMALL LETTER TURNED E;Ll;0;L;;;;;N;;;018E;;018E +01DE;LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON;Lu;0;L;00C4 0304;;;;N;LATIN CAPITAL LETTER A DIAERESIS MACRON;;;01DF; +01DF;LATIN SMALL LETTER A WITH DIAERESIS AND MACRON;Ll;0;L;00E4 0304;;;;N;LATIN SMALL LETTER A DIAERESIS MACRON;;01DE;;01DE +01E0;LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON;Lu;0;L;0226 0304;;;;N;LATIN CAPITAL LETTER A DOT MACRON;;;01E1; +01E1;LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON;Ll;0;L;0227 0304;;;;N;LATIN SMALL LETTER A DOT MACRON;;01E0;;01E0 +01E2;LATIN CAPITAL LETTER AE WITH MACRON;Lu;0;L;00C6 0304;;;;N;LATIN CAPITAL LETTER A E MACRON;;;01E3; +01E3;LATIN SMALL LETTER AE WITH MACRON;Ll;0;L;00E6 0304;;;;N;LATIN SMALL LETTER A E MACRON;;01E2;;01E2 +01E4;LATIN CAPITAL LETTER G WITH STROKE;Lu;0;L;;;;;N;LATIN CAPITAL LETTER G BAR;;;01E5; +01E5;LATIN SMALL LETTER G WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER G BAR;;01E4;;01E4 +01E6;LATIN CAPITAL LETTER G WITH CARON;Lu;0;L;0047 030C;;;;N;LATIN CAPITAL LETTER G HACEK;;;01E7; +01E7;LATIN SMALL LETTER G WITH CARON;Ll;0;L;0067 030C;;;;N;LATIN SMALL LETTER G HACEK;;01E6;;01E6 +01E8;LATIN CAPITAL LETTER K WITH CARON;Lu;0;L;004B 030C;;;;N;LATIN CAPITAL LETTER K HACEK;;;01E9; +01E9;LATIN SMALL LETTER K WITH CARON;Ll;0;L;006B 030C;;;;N;LATIN SMALL LETTER K HACEK;;01E8;;01E8 +01EA;LATIN CAPITAL LETTER O WITH OGONEK;Lu;0;L;004F 0328;;;;N;LATIN CAPITAL LETTER O OGONEK;;;01EB; +01EB;LATIN SMALL LETTER O WITH OGONEK;Ll;0;L;006F 0328;;;;N;LATIN SMALL LETTER O OGONEK;;01EA;;01EA +01EC;LATIN CAPITAL LETTER O WITH OGONEK AND MACRON;Lu;0;L;01EA 0304;;;;N;LATIN CAPITAL LETTER O OGONEK MACRON;;;01ED; +01ED;LATIN SMALL LETTER O WITH OGONEK AND MACRON;Ll;0;L;01EB 0304;;;;N;LATIN SMALL LETTER O OGONEK MACRON;;01EC;;01EC +01EE;LATIN CAPITAL LETTER EZH WITH CARON;Lu;0;L;01B7 030C;;;;N;LATIN CAPITAL LETTER YOGH HACEK;;;01EF; +01EF;LATIN SMALL LETTER EZH WITH CARON;Ll;0;L;0292 030C;;;;N;LATIN SMALL LETTER YOGH HACEK;;01EE;;01EE +01F0;LATIN SMALL LETTER J WITH CARON;Ll;0;L;006A 030C;;;;N;LATIN SMALL LETTER J HACEK;;;; +01F1;LATIN CAPITAL LETTER DZ;Lu;0;L; 0044 005A;;;;N;;;;01F3;01F2 +01F2;LATIN CAPITAL LETTER D WITH SMALL LETTER Z;Lt;0;L; 0044 007A;;;;N;;;01F1;01F3;01F2 +01F3;LATIN SMALL LETTER DZ;Ll;0;L; 0064 007A;;;;N;;;01F1;;01F2 +01F4;LATIN CAPITAL LETTER G WITH ACUTE;Lu;0;L;0047 0301;;;;N;;;;01F5; +01F5;LATIN SMALL LETTER G WITH ACUTE;Ll;0;L;0067 0301;;;;N;;;01F4;;01F4 +01F6;LATIN CAPITAL LETTER HWAIR;Lu;0;L;;;;;N;;;;0195; +01F7;LATIN CAPITAL LETTER WYNN;Lu;0;L;;;;;N;;;;01BF; +01F8;LATIN CAPITAL LETTER N WITH GRAVE;Lu;0;L;004E 0300;;;;N;;;;01F9; +01F9;LATIN SMALL LETTER N WITH GRAVE;Ll;0;L;006E 0300;;;;N;;;01F8;;01F8 +01FA;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE;Lu;0;L;00C5 0301;;;;N;;;;01FB; +01FB;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE;Ll;0;L;00E5 0301;;;;N;;;01FA;;01FA +01FC;LATIN CAPITAL LETTER AE WITH ACUTE;Lu;0;L;00C6 0301;;;;N;;;;01FD; +01FD;LATIN SMALL LETTER AE WITH ACUTE;Ll;0;L;00E6 0301;;;;N;;;01FC;;01FC +01FE;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE;Lu;0;L;00D8 0301;;;;N;;;;01FF; +01FF;LATIN SMALL LETTER O WITH STROKE AND ACUTE;Ll;0;L;00F8 0301;;;;N;;;01FE;;01FE +0200;LATIN CAPITAL LETTER A WITH DOUBLE GRAVE;Lu;0;L;0041 030F;;;;N;;;;0201; +0201;LATIN SMALL LETTER A WITH DOUBLE GRAVE;Ll;0;L;0061 030F;;;;N;;;0200;;0200 +0202;LATIN CAPITAL LETTER A WITH INVERTED BREVE;Lu;0;L;0041 0311;;;;N;;;;0203; +0203;LATIN SMALL LETTER A WITH INVERTED BREVE;Ll;0;L;0061 0311;;;;N;;;0202;;0202 +0204;LATIN CAPITAL LETTER E WITH DOUBLE GRAVE;Lu;0;L;0045 030F;;;;N;;;;0205; +0205;LATIN SMALL LETTER E WITH DOUBLE GRAVE;Ll;0;L;0065 030F;;;;N;;;0204;;0204 +0206;LATIN CAPITAL LETTER E WITH INVERTED BREVE;Lu;0;L;0045 0311;;;;N;;;;0207; +0207;LATIN SMALL LETTER E WITH INVERTED BREVE;Ll;0;L;0065 0311;;;;N;;;0206;;0206 +0208;LATIN CAPITAL LETTER I WITH DOUBLE GRAVE;Lu;0;L;0049 030F;;;;N;;;;0209; +0209;LATIN SMALL LETTER I WITH DOUBLE GRAVE;Ll;0;L;0069 030F;;;;N;;;0208;;0208 +020A;LATIN CAPITAL LETTER I WITH INVERTED BREVE;Lu;0;L;0049 0311;;;;N;;;;020B; +020B;LATIN SMALL LETTER I WITH INVERTED BREVE;Ll;0;L;0069 0311;;;;N;;;020A;;020A +020C;LATIN CAPITAL LETTER O WITH DOUBLE GRAVE;Lu;0;L;004F 030F;;;;N;;;;020D; +020D;LATIN SMALL LETTER O WITH DOUBLE GRAVE;Ll;0;L;006F 030F;;;;N;;;020C;;020C +020E;LATIN CAPITAL LETTER O WITH INVERTED BREVE;Lu;0;L;004F 0311;;;;N;;;;020F; +020F;LATIN SMALL LETTER O WITH INVERTED BREVE;Ll;0;L;006F 0311;;;;N;;;020E;;020E +0210;LATIN CAPITAL LETTER R WITH DOUBLE GRAVE;Lu;0;L;0052 030F;;;;N;;;;0211; +0211;LATIN SMALL LETTER R WITH DOUBLE GRAVE;Ll;0;L;0072 030F;;;;N;;;0210;;0210 +0212;LATIN CAPITAL LETTER R WITH INVERTED BREVE;Lu;0;L;0052 0311;;;;N;;;;0213; +0213;LATIN SMALL LETTER R WITH INVERTED BREVE;Ll;0;L;0072 0311;;;;N;;;0212;;0212 +0214;LATIN CAPITAL LETTER U WITH DOUBLE GRAVE;Lu;0;L;0055 030F;;;;N;;;;0215; +0215;LATIN SMALL LETTER U WITH DOUBLE GRAVE;Ll;0;L;0075 030F;;;;N;;;0214;;0214 +0216;LATIN CAPITAL LETTER U WITH INVERTED BREVE;Lu;0;L;0055 0311;;;;N;;;;0217; +0217;LATIN SMALL LETTER U WITH INVERTED BREVE;Ll;0;L;0075 0311;;;;N;;;0216;;0216 +0218;LATIN CAPITAL LETTER S WITH COMMA BELOW;Lu;0;L;0053 0326;;;;N;;;;0219; +0219;LATIN SMALL LETTER S WITH COMMA BELOW;Ll;0;L;0073 0326;;;;N;;;0218;;0218 +021A;LATIN CAPITAL LETTER T WITH COMMA BELOW;Lu;0;L;0054 0326;;;;N;;;;021B; +021B;LATIN SMALL LETTER T WITH COMMA BELOW;Ll;0;L;0074 0326;;;;N;;;021A;;021A +021C;LATIN CAPITAL LETTER YOGH;Lu;0;L;;;;;N;;;;021D; +021D;LATIN SMALL LETTER YOGH;Ll;0;L;;;;;N;;;021C;;021C +021E;LATIN CAPITAL LETTER H WITH CARON;Lu;0;L;0048 030C;;;;N;;;;021F; +021F;LATIN SMALL LETTER H WITH CARON;Ll;0;L;0068 030C;;;;N;;;021E;;021E +0220;LATIN CAPITAL LETTER N WITH LONG RIGHT LEG;Lu;0;L;;;;;N;;;;019E; +0221;LATIN SMALL LETTER D WITH CURL;Ll;0;L;;;;;N;;;;; +0222;LATIN CAPITAL LETTER OU;Lu;0;L;;;;;N;;;;0223; +0223;LATIN SMALL LETTER OU;Ll;0;L;;;;;N;;;0222;;0222 +0224;LATIN CAPITAL LETTER Z WITH HOOK;Lu;0;L;;;;;N;;;;0225; +0225;LATIN SMALL LETTER Z WITH HOOK;Ll;0;L;;;;;N;;;0224;;0224 +0226;LATIN CAPITAL LETTER A WITH DOT ABOVE;Lu;0;L;0041 0307;;;;N;;;;0227; +0227;LATIN SMALL LETTER A WITH DOT ABOVE;Ll;0;L;0061 0307;;;;N;;;0226;;0226 +0228;LATIN CAPITAL LETTER E WITH CEDILLA;Lu;0;L;0045 0327;;;;N;;;;0229; +0229;LATIN SMALL LETTER E WITH CEDILLA;Ll;0;L;0065 0327;;;;N;;;0228;;0228 +022A;LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON;Lu;0;L;00D6 0304;;;;N;;;;022B; +022B;LATIN SMALL LETTER O WITH DIAERESIS AND MACRON;Ll;0;L;00F6 0304;;;;N;;;022A;;022A +022C;LATIN CAPITAL LETTER O WITH TILDE AND MACRON;Lu;0;L;00D5 0304;;;;N;;;;022D; +022D;LATIN SMALL LETTER O WITH TILDE AND MACRON;Ll;0;L;00F5 0304;;;;N;;;022C;;022C +022E;LATIN CAPITAL LETTER O WITH DOT ABOVE;Lu;0;L;004F 0307;;;;N;;;;022F; +022F;LATIN SMALL LETTER O WITH DOT ABOVE;Ll;0;L;006F 0307;;;;N;;;022E;;022E +0230;LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON;Lu;0;L;022E 0304;;;;N;;;;0231; +0231;LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON;Ll;0;L;022F 0304;;;;N;;;0230;;0230 +0232;LATIN CAPITAL LETTER Y WITH MACRON;Lu;0;L;0059 0304;;;;N;;;;0233; +0233;LATIN SMALL LETTER Y WITH MACRON;Ll;0;L;0079 0304;;;;N;;;0232;;0232 +0234;LATIN SMALL LETTER L WITH CURL;Ll;0;L;;;;;N;;;;; +0235;LATIN SMALL LETTER N WITH CURL;Ll;0;L;;;;;N;;;;; +0236;LATIN SMALL LETTER T WITH CURL;Ll;0;L;;;;;N;;;;; +0237;LATIN SMALL LETTER DOTLESS J;Ll;0;L;;;;;N;;;;; +0238;LATIN SMALL LETTER DB DIGRAPH;Ll;0;L;;;;;N;;;;; +0239;LATIN SMALL LETTER QP DIGRAPH;Ll;0;L;;;;;N;;;;; +023A;LATIN CAPITAL LETTER A WITH STROKE;Lu;0;L;;;;;N;;;;2C65; +023B;LATIN CAPITAL LETTER C WITH STROKE;Lu;0;L;;;;;N;;;;023C; +023C;LATIN SMALL LETTER C WITH STROKE;Ll;0;L;;;;;N;;;023B;;023B +023D;LATIN CAPITAL LETTER L WITH BAR;Lu;0;L;;;;;N;;;;019A; +023E;LATIN CAPITAL LETTER T WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;2C66; +023F;LATIN SMALL LETTER S WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7E;;2C7E +0240;LATIN SMALL LETTER Z WITH SWASH TAIL;Ll;0;L;;;;;N;;;2C7F;;2C7F +0241;LATIN CAPITAL LETTER GLOTTAL STOP;Lu;0;L;;;;;N;;;;0242; +0242;LATIN SMALL LETTER GLOTTAL STOP;Ll;0;L;;;;;N;;;0241;;0241 +0243;LATIN CAPITAL LETTER B WITH STROKE;Lu;0;L;;;;;N;;;;0180; +0244;LATIN CAPITAL LETTER U BAR;Lu;0;L;;;;;N;;;;0289; +0245;LATIN CAPITAL LETTER TURNED V;Lu;0;L;;;;;N;;;;028C; +0246;LATIN CAPITAL LETTER E WITH STROKE;Lu;0;L;;;;;N;;;;0247; +0247;LATIN SMALL LETTER E WITH STROKE;Ll;0;L;;;;;N;;;0246;;0246 +0248;LATIN CAPITAL LETTER J WITH STROKE;Lu;0;L;;;;;N;;;;0249; +0249;LATIN SMALL LETTER J WITH STROKE;Ll;0;L;;;;;N;;;0248;;0248 +024A;LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL;Lu;0;L;;;;;N;;;;024B; +024B;LATIN SMALL LETTER Q WITH HOOK TAIL;Ll;0;L;;;;;N;;;024A;;024A +024C;LATIN CAPITAL LETTER R WITH STROKE;Lu;0;L;;;;;N;;;;024D; +024D;LATIN SMALL LETTER R WITH STROKE;Ll;0;L;;;;;N;;;024C;;024C +024E;LATIN CAPITAL LETTER Y WITH STROKE;Lu;0;L;;;;;N;;;;024F; +024F;LATIN SMALL LETTER Y WITH STROKE;Ll;0;L;;;;;N;;;024E;;024E +0250;LATIN SMALL LETTER TURNED A;Ll;0;L;;;;;N;;;2C6F;;2C6F +0251;LATIN SMALL LETTER ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT A;;2C6D;;2C6D +0252;LATIN SMALL LETTER TURNED ALPHA;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED SCRIPT A;;2C70;;2C70 +0253;LATIN SMALL LETTER B WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER B HOOK;;0181;;0181 +0254;LATIN SMALL LETTER OPEN O;Ll;0;L;;;;;N;;;0186;;0186 +0255;LATIN SMALL LETTER C WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER C CURL;;;; +0256;LATIN SMALL LETTER D WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER D RETROFLEX HOOK;;0189;;0189 +0257;LATIN SMALL LETTER D WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER D HOOK;;018A;;018A +0258;LATIN SMALL LETTER REVERSED E;Ll;0;L;;;;;N;;;;; +0259;LATIN SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;018F;;018F +025A;LATIN SMALL LETTER SCHWA WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCHWA HOOK;;;; +025B;LATIN SMALL LETTER OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER EPSILON;;0190;;0190 +025C;LATIN SMALL LETTER REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON;;A7AB;;A7AB +025D;LATIN SMALL LETTER REVERSED OPEN E WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED EPSILON HOOK;;;; +025E;LATIN SMALL LETTER CLOSED REVERSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED REVERSED EPSILON;;;; +025F;LATIN SMALL LETTER DOTLESS J WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR;;;; +0260;LATIN SMALL LETTER G WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER G HOOK;;0193;;0193 +0261;LATIN SMALL LETTER SCRIPT G;Ll;0;L;;;;;N;;;A7AC;;A7AC +0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; +0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 +0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;A7CB;;A7CB +0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D +0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;A7AA;;A7AA +0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; +0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 +0269;LATIN SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0196;;0196 +026A;LATIN LETTER SMALL CAPITAL I;Ll;0;L;;;;;N;;;A7AE;;A7AE +026B;LATIN SMALL LETTER L WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;2C62;;2C62 +026C;LATIN SMALL LETTER L WITH BELT;Ll;0;L;;;;;N;LATIN SMALL LETTER L BELT;;A7AD;;A7AD +026D;LATIN SMALL LETTER L WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER L RETROFLEX HOOK;;;; +026E;LATIN SMALL LETTER LEZH;Ll;0;L;;;;;N;LATIN SMALL LETTER L YOGH;;;; +026F;LATIN SMALL LETTER TURNED M;Ll;0;L;;;;;N;;;019C;;019C +0270;LATIN SMALL LETTER TURNED M WITH LONG LEG;Ll;0;L;;;;;N;;;;; +0271;LATIN SMALL LETTER M WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER M HOOK;;2C6E;;2C6E +0272;LATIN SMALL LETTER N WITH LEFT HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N HOOK;;019D;;019D +0273;LATIN SMALL LETTER N WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER N RETROFLEX HOOK;;;; +0274;LATIN LETTER SMALL CAPITAL N;Ll;0;L;;;;;N;;;;; +0275;LATIN SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;019F;;019F +0276;LATIN LETTER SMALL CAPITAL OE;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL O E;;;; +0277;LATIN SMALL LETTER CLOSED OMEGA;Ll;0;L;;;;;N;;;;; +0278;LATIN SMALL LETTER PHI;Ll;0;L;;;;;N;;;;; +0279;LATIN SMALL LETTER TURNED R;Ll;0;L;;;;;N;;;;; +027A;LATIN SMALL LETTER TURNED R WITH LONG LEG;Ll;0;L;;;;;N;;;;; +027B;LATIN SMALL LETTER TURNED R WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER TURNED R HOOK;;;; +027C;LATIN SMALL LETTER R WITH LONG LEG;Ll;0;L;;;;;N;;;;; +027D;LATIN SMALL LETTER R WITH TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER R HOOK;;2C64;;2C64 +027E;LATIN SMALL LETTER R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER FISHHOOK R;;;; +027F;LATIN SMALL LETTER REVERSED R WITH FISHHOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER REVERSED FISHHOOK R;;;; +0280;LATIN LETTER SMALL CAPITAL R;Ll;0;L;;;;;N;;;01A6;;01A6 +0281;LATIN LETTER SMALL CAPITAL INVERTED R;Ll;0;L;;;;;N;;;;; +0282;LATIN SMALL LETTER S WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER S HOOK;;A7C5;;A7C5 +0283;LATIN SMALL LETTER ESH;Ll;0;L;;;;;N;;;01A9;;01A9 +0284;LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER DOTLESS J BAR HOOK;;;; +0285;LATIN SMALL LETTER SQUAT REVERSED ESH;Ll;0;L;;;;;N;;;;; +0286;LATIN SMALL LETTER ESH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER ESH CURL;;;; +0287;LATIN SMALL LETTER TURNED T;Ll;0;L;;;;;N;;;A7B1;;A7B1 +0288;LATIN SMALL LETTER T WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER T RETROFLEX HOOK;;01AE;;01AE +0289;LATIN SMALL LETTER U BAR;Ll;0;L;;;;;N;;;0244;;0244 +028A;LATIN SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;01B1;;01B1 +028B;LATIN SMALL LETTER V WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER SCRIPT V;;01B2;;01B2 +028C;LATIN SMALL LETTER TURNED V;Ll;0;L;;;;;N;;;0245;;0245 +028D;LATIN SMALL LETTER TURNED W;Ll;0;L;;;;;N;;;;; +028E;LATIN SMALL LETTER TURNED Y;Ll;0;L;;;;;N;;;;; +028F;LATIN LETTER SMALL CAPITAL Y;Ll;0;L;;;;;N;;;;; +0290;LATIN SMALL LETTER Z WITH RETROFLEX HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Z RETROFLEX HOOK;;;; +0291;LATIN SMALL LETTER Z WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER Z CURL;;;; +0292;LATIN SMALL LETTER EZH;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH;;01B7;;01B7 +0293;LATIN SMALL LETTER EZH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER YOGH CURL;;;; +0294;LATIN LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +0295;LATIN LETTER PHARYNGEAL VOICED FRICATIVE;Lo;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP;;;; +0296;LATIN LETTER INVERTED GLOTTAL STOP;Ll;0;L;;;;;N;;;;; +0297;LATIN LETTER STRETCHED C;Ll;0;L;;;;;N;;;;; +0298;LATIN LETTER BILABIAL CLICK;Ll;0;L;;;;;N;LATIN LETTER BULLSEYE;;;; +0299;LATIN LETTER SMALL CAPITAL B;Ll;0;L;;;;;N;;;;; +029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;; +029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;; +029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;; +029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;A7B2;;A7B2 +029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;A7B0;;A7B0 +029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;; +02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;; +02A1;LATIN LETTER GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER GLOTTAL STOP BAR;;;; +02A2;LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE;Ll;0;L;;;;;N;LATIN LETTER REVERSED GLOTTAL STOP BAR;;;; +02A3;LATIN SMALL LETTER DZ DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z;;;; +02A4;LATIN SMALL LETTER DEZH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER D YOGH;;;; +02A5;LATIN SMALL LETTER DZ DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER D Z CURL;;;; +02A6;LATIN SMALL LETTER TS DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T S;;;; +02A7;LATIN SMALL LETTER TESH DIGRAPH;Ll;0;L;;;;;N;LATIN SMALL LETTER T ESH;;;; +02A8;LATIN SMALL LETTER TC DIGRAPH WITH CURL;Ll;0;L;;;;;N;LATIN SMALL LETTER T C CURL;;;; +02A9;LATIN SMALL LETTER FENG DIGRAPH;Ll;0;L;;;;;N;;;;; +02AA;LATIN SMALL LETTER LS DIGRAPH;Ll;0;L;;;;;N;;;;; +02AB;LATIN SMALL LETTER LZ DIGRAPH;Ll;0;L;;;;;N;;;;; +02AC;LATIN LETTER BILABIAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; +02AD;LATIN LETTER BIDENTAL PERCUSSIVE;Ll;0;L;;;;;N;;;;; +02AE;LATIN SMALL LETTER TURNED H WITH FISHHOOK;Ll;0;L;;;;;N;;;;; +02AF;LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL;Ll;0;L;;;;;N;;;;; +02B0;MODIFIER LETTER SMALL H;Lm;0;L; 0068;;;;N;;;;; +02B1;MODIFIER LETTER SMALL H WITH HOOK;Lm;0;L; 0266;;;;N;MODIFIER LETTER SMALL H HOOK;;;; +02B2;MODIFIER LETTER SMALL J;Lm;0;L; 006A;;;;N;;;;; +02B3;MODIFIER LETTER SMALL R;Lm;0;L; 0072;;;;N;;;;; +02B4;MODIFIER LETTER SMALL TURNED R;Lm;0;L; 0279;;;;N;;;;; +02B5;MODIFIER LETTER SMALL TURNED R WITH HOOK;Lm;0;L; 027B;;;;N;MODIFIER LETTER SMALL TURNED R HOOK;;;; +02B6;MODIFIER LETTER SMALL CAPITAL INVERTED R;Lm;0;L; 0281;;;;N;;;;; +02B7;MODIFIER LETTER SMALL W;Lm;0;L; 0077;;;;N;;;;; +02B8;MODIFIER LETTER SMALL Y;Lm;0;L; 0079;;;;N;;;;; +02B9;MODIFIER LETTER PRIME;Lm;0;ON;;;;;N;;;;; +02BA;MODIFIER LETTER DOUBLE PRIME;Lm;0;ON;;;;;N;;;;; +02BB;MODIFIER LETTER TURNED COMMA;Lm;0;L;;;;;N;;;;; +02BC;MODIFIER LETTER APOSTROPHE;Lm;0;L;;;;;N;;;;; +02BD;MODIFIER LETTER REVERSED COMMA;Lm;0;L;;;;;N;;;;; +02BE;MODIFIER LETTER RIGHT HALF RING;Lm;0;L;;;;;N;;;;; +02BF;MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; +02C0;MODIFIER LETTER GLOTTAL STOP;Lm;0;L;;;;;N;;;;; +02C1;MODIFIER LETTER REVERSED GLOTTAL STOP;Lm;0;L;;;;;N;;;;; +02C2;MODIFIER LETTER LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C3;MODIFIER LETTER RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C4;MODIFIER LETTER UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C5;MODIFIER LETTER DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02C6;MODIFIER LETTER CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER CIRCUMFLEX;;;; +02C7;CARON;Lm;0;ON;;;;;N;MODIFIER LETTER HACEK;;;; +02C8;MODIFIER LETTER VERTICAL LINE;Lm;0;ON;;;;;N;;;;; +02C9;MODIFIER LETTER MACRON;Lm;0;ON;;;;;N;;;;; +02CA;MODIFIER LETTER ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER ACUTE;;;; +02CB;MODIFIER LETTER GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER GRAVE;;;; +02CC;MODIFIER LETTER LOW VERTICAL LINE;Lm;0;ON;;;;;N;;;;; +02CD;MODIFIER LETTER LOW MACRON;Lm;0;ON;;;;;N;;;;; +02CE;MODIFIER LETTER LOW GRAVE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW GRAVE;;;; +02CF;MODIFIER LETTER LOW ACUTE ACCENT;Lm;0;ON;;;;;N;MODIFIER LETTER LOW ACUTE;;;; +02D0;MODIFIER LETTER TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; +02D1;MODIFIER LETTER HALF TRIANGULAR COLON;Lm;0;L;;;;;N;;;;; +02D2;MODIFIER LETTER CENTRED RIGHT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED RIGHT HALF RING;;;; +02D3;MODIFIER LETTER CENTRED LEFT HALF RING;Sk;0;ON;;;;;N;MODIFIER LETTER CENTERED LEFT HALF RING;;;; +02D4;MODIFIER LETTER UP TACK;Sk;0;ON;;;;;N;;;;; +02D5;MODIFIER LETTER DOWN TACK;Sk;0;ON;;;;;N;;;;; +02D6;MODIFIER LETTER PLUS SIGN;Sk;0;ON;;;;;N;;;;; +02D7;MODIFIER LETTER MINUS SIGN;Sk;0;ON;;;;;N;;;;; +02D8;BREVE;Sk;0;ON; 0020 0306;;;;N;SPACING BREVE;;;; +02D9;DOT ABOVE;Sk;0;ON; 0020 0307;;;;N;SPACING DOT ABOVE;;;; +02DA;RING ABOVE;Sk;0;ON; 0020 030A;;;;N;SPACING RING ABOVE;;;; +02DB;OGONEK;Sk;0;ON; 0020 0328;;;;N;SPACING OGONEK;;;; +02DC;SMALL TILDE;Sk;0;ON; 0020 0303;;;;N;SPACING TILDE;;;; +02DD;DOUBLE ACUTE ACCENT;Sk;0;ON; 0020 030B;;;;N;SPACING DOUBLE ACUTE;;;; +02DE;MODIFIER LETTER RHOTIC HOOK;Sk;0;ON;;;;;N;;;;; +02DF;MODIFIER LETTER CROSS ACCENT;Sk;0;ON;;;;;N;;;;; +02E0;MODIFIER LETTER SMALL GAMMA;Lm;0;L; 0263;;;;N;;;;; +02E1;MODIFIER LETTER SMALL L;Lm;0;L; 006C;;;;N;;;;; +02E2;MODIFIER LETTER SMALL S;Lm;0;L; 0073;;;;N;;;;; +02E3;MODIFIER LETTER SMALL X;Lm;0;L; 0078;;;;N;;;;; +02E4;MODIFIER LETTER SMALL REVERSED GLOTTAL STOP;Lm;0;L; 0295;;;;N;;;;; +02E5;MODIFIER LETTER EXTRA-HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; +02E6;MODIFIER LETTER HIGH TONE BAR;Sk;0;ON;;;;;N;;;;; +02E7;MODIFIER LETTER MID TONE BAR;Sk;0;ON;;;;;N;;;;; +02E8;MODIFIER LETTER LOW TONE BAR;Sk;0;ON;;;;;N;;;;; +02E9;MODIFIER LETTER EXTRA-LOW TONE BAR;Sk;0;ON;;;;;N;;;;; +02EA;MODIFIER LETTER YIN DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; +02EB;MODIFIER LETTER YANG DEPARTING TONE MARK;Sk;0;ON;;;;;N;;;;; +02EC;MODIFIER LETTER VOICING;Lm;0;ON;;;;;N;;;;; +02ED;MODIFIER LETTER UNASPIRATED;Sk;0;ON;;;;;N;;;;; +02EE;MODIFIER LETTER DOUBLE APOSTROPHE;Lm;0;L;;;;;N;;;;; +02EF;MODIFIER LETTER LOW DOWN ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F0;MODIFIER LETTER LOW UP ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F1;MODIFIER LETTER LOW LEFT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F2;MODIFIER LETTER LOW RIGHT ARROWHEAD;Sk;0;ON;;;;;N;;;;; +02F3;MODIFIER LETTER LOW RING;Sk;0;ON;;;;;N;;;;; +02F4;MODIFIER LETTER MIDDLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; +02F5;MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT;Sk;0;ON;;;;;N;;;;; +02F6;MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT;Sk;0;ON;;;;;N;;;;; +02F7;MODIFIER LETTER LOW TILDE;Sk;0;ON;;;;;N;;;;; +02F8;MODIFIER LETTER RAISED COLON;Sk;0;ON;;;;;N;;;;; +02F9;MODIFIER LETTER BEGIN HIGH TONE;Sk;0;ON;;;;;N;;;;; +02FA;MODIFIER LETTER END HIGH TONE;Sk;0;ON;;;;;N;;;;; +02FB;MODIFIER LETTER BEGIN LOW TONE;Sk;0;ON;;;;;N;;;;; +02FC;MODIFIER LETTER END LOW TONE;Sk;0;ON;;;;;N;;;;; +02FD;MODIFIER LETTER SHELF;Sk;0;ON;;;;;N;;;;; +02FE;MODIFIER LETTER OPEN SHELF;Sk;0;ON;;;;;N;;;;; +02FF;MODIFIER LETTER LOW LEFT ARROW;Sk;0;ON;;;;;N;;;;; +0300;COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;; +0301;COMBINING ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING ACUTE;;;; +0302;COMBINING CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;NON-SPACING CIRCUMFLEX;;;; +0303;COMBINING TILDE;Mn;230;NSM;;;;;N;NON-SPACING TILDE;;;; +0304;COMBINING MACRON;Mn;230;NSM;;;;;N;NON-SPACING MACRON;;;; +0305;COMBINING OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING OVERSCORE;;;; +0306;COMBINING BREVE;Mn;230;NSM;;;;;N;NON-SPACING BREVE;;;; +0307;COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOT ABOVE;;;; +0308;COMBINING DIAERESIS;Mn;230;NSM;;;;;N;NON-SPACING DIAERESIS;;;; +0309;COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;NON-SPACING HOOK ABOVE;;;; +030A;COMBINING RING ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RING ABOVE;;;; +030B;COMBINING DOUBLE ACUTE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE ACUTE;;;; +030C;COMBINING CARON;Mn;230;NSM;;;;;N;NON-SPACING HACEK;;;; +030D;COMBINING VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL LINE ABOVE;;;; +030E;COMBINING DOUBLE VERTICAL LINE ABOVE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE VERTICAL LINE ABOVE;;;; +030F;COMBINING DOUBLE GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE GRAVE;;;; +0310;COMBINING CANDRABINDU;Mn;230;NSM;;;;;N;NON-SPACING CANDRABINDU;;;; +0311;COMBINING INVERTED BREVE;Mn;230;NSM;;;;;N;NON-SPACING INVERTED BREVE;;;; +0312;COMBINING TURNED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING TURNED COMMA ABOVE;;;; +0313;COMBINING COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING COMMA ABOVE;;;; +0314;COMBINING REVERSED COMMA ABOVE;Mn;230;NSM;;;;;N;NON-SPACING REVERSED COMMA ABOVE;;;; +0315;COMBINING COMMA ABOVE RIGHT;Mn;232;NSM;;;;;N;NON-SPACING COMMA ABOVE RIGHT;;;; +0316;COMBINING GRAVE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING GRAVE BELOW;;;; +0317;COMBINING ACUTE ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING ACUTE BELOW;;;; +0318;COMBINING LEFT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT TACK BELOW;;;; +0319;COMBINING RIGHT TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT TACK BELOW;;;; +031A;COMBINING LEFT ANGLE ABOVE;Mn;232;NSM;;;;;N;NON-SPACING LEFT ANGLE ABOVE;;;; +031B;COMBINING HORN;Mn;216;NSM;;;;;N;NON-SPACING HORN;;;; +031C;COMBINING LEFT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING LEFT HALF RING BELOW;;;; +031D;COMBINING UP TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING UP TACK BELOW;;;; +031E;COMBINING DOWN TACK BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOWN TACK BELOW;;;; +031F;COMBINING PLUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING PLUS SIGN BELOW;;;; +0320;COMBINING MINUS SIGN BELOW;Mn;220;NSM;;;;;N;NON-SPACING MINUS SIGN BELOW;;;; +0321;COMBINING PALATALIZED HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING PALATALIZED HOOK BELOW;;;; +0322;COMBINING RETROFLEX HOOK BELOW;Mn;202;NSM;;;;;N;NON-SPACING RETROFLEX HOOK BELOW;;;; +0323;COMBINING DOT BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOT BELOW;;;; +0324;COMBINING DIAERESIS BELOW;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE DOT BELOW;;;; +0325;COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;; +0326;COMBINING COMMA BELOW;Mn;220;NSM;;;;;N;NON-SPACING COMMA BELOW;;;; +0327;COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;; +0328;COMBINING OGONEK;Mn;202;NSM;;;;;N;NON-SPACING OGONEK;;;; +0329;COMBINING VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;NON-SPACING VERTICAL LINE BELOW;;;; +032A;COMBINING BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BRIDGE BELOW;;;; +032B;COMBINING INVERTED DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED DOUBLE ARCH BELOW;;;; +032C;COMBINING CARON BELOW;Mn;220;NSM;;;;;N;NON-SPACING HACEK BELOW;;;; +032D;COMBINING CIRCUMFLEX ACCENT BELOW;Mn;220;NSM;;;;;N;NON-SPACING CIRCUMFLEX BELOW;;;; +032E;COMBINING BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING BREVE BELOW;;;; +032F;COMBINING INVERTED BREVE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BREVE BELOW;;;; +0330;COMBINING TILDE BELOW;Mn;220;NSM;;;;;N;NON-SPACING TILDE BELOW;;;; +0331;COMBINING MACRON BELOW;Mn;220;NSM;;;;;N;NON-SPACING MACRON BELOW;;;; +0332;COMBINING LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING UNDERSCORE;;;; +0333;COMBINING DOUBLE LOW LINE;Mn;220;NSM;;;;;N;NON-SPACING DOUBLE UNDERSCORE;;;; +0334;COMBINING TILDE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING TILDE OVERLAY;;;; +0335;COMBINING SHORT STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT BAR OVERLAY;;;; +0336;COMBINING LONG STROKE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG BAR OVERLAY;;;; +0337;COMBINING SHORT SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT SLASH OVERLAY;;;; +0338;COMBINING LONG SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG SLASH OVERLAY;;;; +0339;COMBINING RIGHT HALF RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RIGHT HALF RING BELOW;;;; +033A;COMBINING INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;NON-SPACING INVERTED BRIDGE BELOW;;;; +033B;COMBINING SQUARE BELOW;Mn;220;NSM;;;;;N;NON-SPACING SQUARE BELOW;;;; +033C;COMBINING SEAGULL BELOW;Mn;220;NSM;;;;;N;NON-SPACING SEAGULL BELOW;;;; +033D;COMBINING X ABOVE;Mn;230;NSM;;;;;N;NON-SPACING X ABOVE;;;; +033E;COMBINING VERTICAL TILDE;Mn;230;NSM;;;;;N;NON-SPACING VERTICAL TILDE;;;; +033F;COMBINING DOUBLE OVERLINE;Mn;230;NSM;;;;;N;NON-SPACING DOUBLE OVERSCORE;;;; +0340;COMBINING GRAVE TONE MARK;Mn;230;NSM;0300;;;;N;NON-SPACING GRAVE TONE MARK;;;; +0341;COMBINING ACUTE TONE MARK;Mn;230;NSM;0301;;;;N;NON-SPACING ACUTE TONE MARK;;;; +0342;COMBINING GREEK PERISPOMENI;Mn;230;NSM;;;;;N;;;;; +0343;COMBINING GREEK KORONIS;Mn;230;NSM;0313;;;;N;;;;; +0344;COMBINING GREEK DIALYTIKA TONOS;Mn;230;NSM;0308 0301;;;;N;GREEK NON-SPACING DIAERESIS TONOS;;;; +0345;COMBINING GREEK YPOGEGRAMMENI;Mn;240;NSM;;;;;N;GREEK NON-SPACING IOTA BELOW;;0399;;0399 +0346;COMBINING BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; +0347;COMBINING EQUALS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; +0348;COMBINING DOUBLE VERTICAL LINE BELOW;Mn;220;NSM;;;;;N;;;;; +0349;COMBINING LEFT ANGLE BELOW;Mn;220;NSM;;;;;N;;;;; +034A;COMBINING NOT TILDE ABOVE;Mn;230;NSM;;;;;N;;;;; +034B;COMBINING HOMOTHETIC ABOVE;Mn;230;NSM;;;;;N;;;;; +034C;COMBINING ALMOST EQUAL TO ABOVE;Mn;230;NSM;;;;;N;;;;; +034D;COMBINING LEFT RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +034E;COMBINING UPWARDS ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +034F;COMBINING GRAPHEME JOINER;Mn;0;NSM;;;;;N;;;;; +0350;COMBINING RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +0351;COMBINING LEFT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; +0352;COMBINING FERMATA;Mn;230;NSM;;;;;N;;;;; +0353;COMBINING X BELOW;Mn;220;NSM;;;;;N;;;;; +0354;COMBINING LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0355;COMBINING RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0356;COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +0357;COMBINING RIGHT HALF RING ABOVE;Mn;230;NSM;;;;;N;;;;; +0358;COMBINING DOT ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +0359;COMBINING ASTERISK BELOW;Mn;220;NSM;;;;;N;;;;; +035A;COMBINING DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; +035B;COMBINING ZIGZAG ABOVE;Mn;230;NSM;;;;;N;;;;; +035C;COMBINING DOUBLE BREVE BELOW;Mn;233;NSM;;;;;N;;;;; +035D;COMBINING DOUBLE BREVE;Mn;234;NSM;;;;;N;;;;; +035E;COMBINING DOUBLE MACRON;Mn;234;NSM;;;;;N;;;;; +035F;COMBINING DOUBLE MACRON BELOW;Mn;233;NSM;;;;;N;;;;; +0360;COMBINING DOUBLE TILDE;Mn;234;NSM;;;;;N;;;;; +0361;COMBINING DOUBLE INVERTED BREVE;Mn;234;NSM;;;;;N;;;;; +0362;COMBINING DOUBLE RIGHTWARDS ARROW BELOW;Mn;233;NSM;;;;;N;;;;; +0363;COMBINING LATIN SMALL LETTER A;Mn;230;NSM;;;;;N;;;;; +0364;COMBINING LATIN SMALL LETTER E;Mn;230;NSM;;;;;N;;;;; +0365;COMBINING LATIN SMALL LETTER I;Mn;230;NSM;;;;;N;;;;; +0366;COMBINING LATIN SMALL LETTER O;Mn;230;NSM;;;;;N;;;;; +0367;COMBINING LATIN SMALL LETTER U;Mn;230;NSM;;;;;N;;;;; +0368;COMBINING LATIN SMALL LETTER C;Mn;230;NSM;;;;;N;;;;; +0369;COMBINING LATIN SMALL LETTER D;Mn;230;NSM;;;;;N;;;;; +036A;COMBINING LATIN SMALL LETTER H;Mn;230;NSM;;;;;N;;;;; +036B;COMBINING LATIN SMALL LETTER M;Mn;230;NSM;;;;;N;;;;; +036C;COMBINING LATIN SMALL LETTER R;Mn;230;NSM;;;;;N;;;;; +036D;COMBINING LATIN SMALL LETTER T;Mn;230;NSM;;;;;N;;;;; +036E;COMBINING LATIN SMALL LETTER V;Mn;230;NSM;;;;;N;;;;; +036F;COMBINING LATIN SMALL LETTER X;Mn;230;NSM;;;;;N;;;;; +0370;GREEK CAPITAL LETTER HETA;Lu;0;L;;;;;N;;;;0371; +0371;GREEK SMALL LETTER HETA;Ll;0;L;;;;;N;;;0370;;0370 +0372;GREEK CAPITAL LETTER ARCHAIC SAMPI;Lu;0;L;;;;;N;;;;0373; +0373;GREEK SMALL LETTER ARCHAIC SAMPI;Ll;0;L;;;;;N;;;0372;;0372 +0374;GREEK NUMERAL SIGN;Lm;0;ON;02B9;;;;N;GREEK UPPER NUMERAL SIGN;;;; +0375;GREEK LOWER NUMERAL SIGN;Sk;0;ON;;;;;N;;;;; +0376;GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA;Lu;0;L;;;;;N;;;;0377; +0377;GREEK SMALL LETTER PAMPHYLIAN DIGAMMA;Ll;0;L;;;;;N;;;0376;;0376 +037A;GREEK YPOGEGRAMMENI;Lm;0;L; 0020 0345;;;;N;GREEK SPACING IOTA BELOW;;;; +037B;GREEK SMALL REVERSED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FD;;03FD +037C;GREEK SMALL DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FE;;03FE +037D;GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL;Ll;0;L;;;;;N;;;03FF;;03FF +037E;GREEK QUESTION MARK;Po;0;ON;003B;;;;N;;;;; +037F;GREEK CAPITAL LETTER YOT;Lu;0;L;;;;;N;;;;03F3; +0384;GREEK TONOS;Sk;0;ON; 0020 0301;;;;N;GREEK SPACING TONOS;;;; +0385;GREEK DIALYTIKA TONOS;Sk;0;ON;00A8 0301;;;;N;GREEK SPACING DIAERESIS TONOS;;;; +0386;GREEK CAPITAL LETTER ALPHA WITH TONOS;Lu;0;L;0391 0301;;;;N;GREEK CAPITAL LETTER ALPHA TONOS;;;03AC; +0387;GREEK ANO TELEIA;Po;0;ON;00B7;;;;N;;;;; +0388;GREEK CAPITAL LETTER EPSILON WITH TONOS;Lu;0;L;0395 0301;;;;N;GREEK CAPITAL LETTER EPSILON TONOS;;;03AD; +0389;GREEK CAPITAL LETTER ETA WITH TONOS;Lu;0;L;0397 0301;;;;N;GREEK CAPITAL LETTER ETA TONOS;;;03AE; +038A;GREEK CAPITAL LETTER IOTA WITH TONOS;Lu;0;L;0399 0301;;;;N;GREEK CAPITAL LETTER IOTA TONOS;;;03AF; +038C;GREEK CAPITAL LETTER OMICRON WITH TONOS;Lu;0;L;039F 0301;;;;N;GREEK CAPITAL LETTER OMICRON TONOS;;;03CC; +038E;GREEK CAPITAL LETTER UPSILON WITH TONOS;Lu;0;L;03A5 0301;;;;N;GREEK CAPITAL LETTER UPSILON TONOS;;;03CD; +038F;GREEK CAPITAL LETTER OMEGA WITH TONOS;Lu;0;L;03A9 0301;;;;N;GREEK CAPITAL LETTER OMEGA TONOS;;;03CE; +0390;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS;Ll;0;L;03CA 0301;;;;N;GREEK SMALL LETTER IOTA DIAERESIS TONOS;;;; +0391;GREEK CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;03B1; +0392;GREEK CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;03B2; +0393;GREEK CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;03B3; +0394;GREEK CAPITAL LETTER DELTA;Lu;0;L;;;;;N;;;;03B4; +0395;GREEK CAPITAL LETTER EPSILON;Lu;0;L;;;;;N;;;;03B5; +0396;GREEK CAPITAL LETTER ZETA;Lu;0;L;;;;;N;;;;03B6; +0397;GREEK CAPITAL LETTER ETA;Lu;0;L;;;;;N;;;;03B7; +0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8; +0399;GREEK CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;03B9; +039A;GREEK CAPITAL LETTER KAPPA;Lu;0;L;;;;;N;;;;03BA; +039B;GREEK CAPITAL LETTER LAMDA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER LAMBDA;;;03BB; +039C;GREEK CAPITAL LETTER MU;Lu;0;L;;;;;N;;;;03BC; +039D;GREEK CAPITAL LETTER NU;Lu;0;L;;;;;N;;;;03BD; +039E;GREEK CAPITAL LETTER XI;Lu;0;L;;;;;N;;;;03BE; +039F;GREEK CAPITAL LETTER OMICRON;Lu;0;L;;;;;N;;;;03BF; +03A0;GREEK CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;03C0; +03A1;GREEK CAPITAL LETTER RHO;Lu;0;L;;;;;N;;;;03C1; +03A3;GREEK CAPITAL LETTER SIGMA;Lu;0;L;;;;;N;;;;03C3; +03A4;GREEK CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;03C4; +03A5;GREEK CAPITAL LETTER UPSILON;Lu;0;L;;;;;N;;;;03C5; +03A6;GREEK CAPITAL LETTER PHI;Lu;0;L;;;;;N;;;;03C6; +03A7;GREEK CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;03C7; +03A8;GREEK CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;03C8; +03A9;GREEK CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;03C9; +03AA;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA;Lu;0;L;0399 0308;;;;N;GREEK CAPITAL LETTER IOTA DIAERESIS;;;03CA; +03AB;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA;Lu;0;L;03A5 0308;;;;N;GREEK CAPITAL LETTER UPSILON DIAERESIS;;;03CB; +03AC;GREEK SMALL LETTER ALPHA WITH TONOS;Ll;0;L;03B1 0301;;;;N;GREEK SMALL LETTER ALPHA TONOS;;0386;;0386 +03AD;GREEK SMALL LETTER EPSILON WITH TONOS;Ll;0;L;03B5 0301;;;;N;GREEK SMALL LETTER EPSILON TONOS;;0388;;0388 +03AE;GREEK SMALL LETTER ETA WITH TONOS;Ll;0;L;03B7 0301;;;;N;GREEK SMALL LETTER ETA TONOS;;0389;;0389 +03AF;GREEK SMALL LETTER IOTA WITH TONOS;Ll;0;L;03B9 0301;;;;N;GREEK SMALL LETTER IOTA TONOS;;038A;;038A +03B0;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS;Ll;0;L;03CB 0301;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS TONOS;;;; +03B1;GREEK SMALL LETTER ALPHA;Ll;0;L;;;;;N;;;0391;;0391 +03B2;GREEK SMALL LETTER BETA;Ll;0;L;;;;;N;;;0392;;0392 +03B3;GREEK SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0393;;0393 +03B4;GREEK SMALL LETTER DELTA;Ll;0;L;;;;;N;;;0394;;0394 +03B5;GREEK SMALL LETTER EPSILON;Ll;0;L;;;;;N;;;0395;;0395 +03B6;GREEK SMALL LETTER ZETA;Ll;0;L;;;;;N;;;0396;;0396 +03B7;GREEK SMALL LETTER ETA;Ll;0;L;;;;;N;;;0397;;0397 +03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398 +03B9;GREEK SMALL LETTER IOTA;Ll;0;L;;;;;N;;;0399;;0399 +03BA;GREEK SMALL LETTER KAPPA;Ll;0;L;;;;;N;;;039A;;039A +03BB;GREEK SMALL LETTER LAMDA;Ll;0;L;;;;;N;GREEK SMALL LETTER LAMBDA;;039B;;039B +03BC;GREEK SMALL LETTER MU;Ll;0;L;;;;;N;;;039C;;039C +03BD;GREEK SMALL LETTER NU;Ll;0;L;;;;;N;;;039D;;039D +03BE;GREEK SMALL LETTER XI;Ll;0;L;;;;;N;;;039E;;039E +03BF;GREEK SMALL LETTER OMICRON;Ll;0;L;;;;;N;;;039F;;039F +03C0;GREEK SMALL LETTER PI;Ll;0;L;;;;;N;;;03A0;;03A0 +03C1;GREEK SMALL LETTER RHO;Ll;0;L;;;;;N;;;03A1;;03A1 +03C2;GREEK SMALL LETTER FINAL SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 +03C3;GREEK SMALL LETTER SIGMA;Ll;0;L;;;;;N;;;03A3;;03A3 +03C4;GREEK SMALL LETTER TAU;Ll;0;L;;;;;N;;;03A4;;03A4 +03C5;GREEK SMALL LETTER UPSILON;Ll;0;L;;;;;N;;;03A5;;03A5 +03C6;GREEK SMALL LETTER PHI;Ll;0;L;;;;;N;;;03A6;;03A6 +03C7;GREEK SMALL LETTER CHI;Ll;0;L;;;;;N;;;03A7;;03A7 +03C8;GREEK SMALL LETTER PSI;Ll;0;L;;;;;N;;;03A8;;03A8 +03C9;GREEK SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;03A9;;03A9 +03CA;GREEK SMALL LETTER IOTA WITH DIALYTIKA;Ll;0;L;03B9 0308;;;;N;GREEK SMALL LETTER IOTA DIAERESIS;;03AA;;03AA +03CB;GREEK SMALL LETTER UPSILON WITH DIALYTIKA;Ll;0;L;03C5 0308;;;;N;GREEK SMALL LETTER UPSILON DIAERESIS;;03AB;;03AB +03CC;GREEK SMALL LETTER OMICRON WITH TONOS;Ll;0;L;03BF 0301;;;;N;GREEK SMALL LETTER OMICRON TONOS;;038C;;038C +03CD;GREEK SMALL LETTER UPSILON WITH TONOS;Ll;0;L;03C5 0301;;;;N;GREEK SMALL LETTER UPSILON TONOS;;038E;;038E +03CE;GREEK SMALL LETTER OMEGA WITH TONOS;Ll;0;L;03C9 0301;;;;N;GREEK SMALL LETTER OMEGA TONOS;;038F;;038F +03CF;GREEK CAPITAL KAI SYMBOL;Lu;0;L;;;;;N;;;;03D7; +03D0;GREEK BETA SYMBOL;Ll;0;L; 03B2;;;;N;GREEK SMALL LETTER CURLED BETA;;0392;;0392 +03D1;GREEK THETA SYMBOL;Ll;0;L; 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398 +03D2;GREEK UPSILON WITH HOOK SYMBOL;Lu;0;L; 03A5;;;;N;GREEK CAPITAL LETTER UPSILON HOOK;;;; +03D3;GREEK UPSILON WITH ACUTE AND HOOK SYMBOL;Lu;0;L;03D2 0301;;;;N;GREEK CAPITAL LETTER UPSILON HOOK TONOS;;;; +03D4;GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL;Lu;0;L;03D2 0308;;;;N;GREEK CAPITAL LETTER UPSILON HOOK DIAERESIS;;;; +03D5;GREEK PHI SYMBOL;Ll;0;L; 03C6;;;;N;GREEK SMALL LETTER SCRIPT PHI;;03A6;;03A6 +03D6;GREEK PI SYMBOL;Ll;0;L; 03C0;;;;N;GREEK SMALL LETTER OMEGA PI;;03A0;;03A0 +03D7;GREEK KAI SYMBOL;Ll;0;L;;;;;N;;;03CF;;03CF +03D8;GREEK LETTER ARCHAIC KOPPA;Lu;0;L;;;;;N;;;;03D9; +03D9;GREEK SMALL LETTER ARCHAIC KOPPA;Ll;0;L;;;;;N;;;03D8;;03D8 +03DA;GREEK LETTER STIGMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER STIGMA;;;03DB; +03DB;GREEK SMALL LETTER STIGMA;Ll;0;L;;;;;N;;;03DA;;03DA +03DC;GREEK LETTER DIGAMMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DIGAMMA;;;03DD; +03DD;GREEK SMALL LETTER DIGAMMA;Ll;0;L;;;;;N;;;03DC;;03DC +03DE;GREEK LETTER KOPPA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KOPPA;;;03DF; +03DF;GREEK SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;03DE;;03DE +03E0;GREEK LETTER SAMPI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SAMPI;;;03E1; +03E1;GREEK SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;03E0;;03E0 +03E2;COPTIC CAPITAL LETTER SHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHEI;;;03E3; +03E3;COPTIC SMALL LETTER SHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER SHEI;;03E2;;03E2 +03E4;COPTIC CAPITAL LETTER FEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER FEI;;;03E5; +03E5;COPTIC SMALL LETTER FEI;Ll;0;L;;;;;N;GREEK SMALL LETTER FEI;;03E4;;03E4 +03E6;COPTIC CAPITAL LETTER KHEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER KHEI;;;03E7; +03E7;COPTIC SMALL LETTER KHEI;Ll;0;L;;;;;N;GREEK SMALL LETTER KHEI;;03E6;;03E6 +03E8;COPTIC CAPITAL LETTER HORI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER HORI;;;03E9; +03E9;COPTIC SMALL LETTER HORI;Ll;0;L;;;;;N;GREEK SMALL LETTER HORI;;03E8;;03E8 +03EA;COPTIC CAPITAL LETTER GANGIA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER GANGIA;;;03EB; +03EB;COPTIC SMALL LETTER GANGIA;Ll;0;L;;;;;N;GREEK SMALL LETTER GANGIA;;03EA;;03EA +03EC;COPTIC CAPITAL LETTER SHIMA;Lu;0;L;;;;;N;GREEK CAPITAL LETTER SHIMA;;;03ED; +03ED;COPTIC SMALL LETTER SHIMA;Ll;0;L;;;;;N;GREEK SMALL LETTER SHIMA;;03EC;;03EC +03EE;COPTIC CAPITAL LETTER DEI;Lu;0;L;;;;;N;GREEK CAPITAL LETTER DEI;;;03EF; +03EF;COPTIC SMALL LETTER DEI;Ll;0;L;;;;;N;GREEK SMALL LETTER DEI;;03EE;;03EE +03F0;GREEK KAPPA SYMBOL;Ll;0;L; 03BA;;;;N;GREEK SMALL LETTER SCRIPT KAPPA;;039A;;039A +03F1;GREEK RHO SYMBOL;Ll;0;L; 03C1;;;;N;GREEK SMALL LETTER TAILED RHO;;03A1;;03A1 +03F2;GREEK LUNATE SIGMA SYMBOL;Ll;0;L; 03C2;;;;N;GREEK SMALL LETTER LUNATE SIGMA;;03F9;;03F9 +03F3;GREEK LETTER YOT;Ll;0;L;;;;;N;;;037F;;037F +03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L; 0398;;;;N;;;;03B8; +03F5;GREEK LUNATE EPSILON SYMBOL;Ll;0;L; 03B5;;;;N;;;0395;;0395 +03F6;GREEK REVERSED LUNATE EPSILON SYMBOL;Sm;0;ON;;;;;N;;;;; +03F7;GREEK CAPITAL LETTER SHO;Lu;0;L;;;;;N;;;;03F8; +03F8;GREEK SMALL LETTER SHO;Ll;0;L;;;;;N;;;03F7;;03F7 +03F9;GREEK CAPITAL LUNATE SIGMA SYMBOL;Lu;0;L; 03A3;;;;N;;;;03F2; +03FA;GREEK CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;03FB; +03FB;GREEK SMALL LETTER SAN;Ll;0;L;;;;;N;;;03FA;;03FA +03FC;GREEK RHO WITH STROKE SYMBOL;Ll;0;L;;;;;N;;;;; +03FD;GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037B; +03FE;GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037C; +03FF;GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL;Lu;0;L;;;;;N;;;;037D; +0400;CYRILLIC CAPITAL LETTER IE WITH GRAVE;Lu;0;L;0415 0300;;;;N;;;;0450; +0401;CYRILLIC CAPITAL LETTER IO;Lu;0;L;0415 0308;;;;N;;;;0451; +0402;CYRILLIC CAPITAL LETTER DJE;Lu;0;L;;;;;N;;;;0452; +0403;CYRILLIC CAPITAL LETTER GJE;Lu;0;L;0413 0301;;;;N;;;;0453; +0404;CYRILLIC CAPITAL LETTER UKRAINIAN IE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER E;;;0454; +0405;CYRILLIC CAPITAL LETTER DZE;Lu;0;L;;;;;N;;;;0455; +0406;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER I;;;0456; +0407;CYRILLIC CAPITAL LETTER YI;Lu;0;L;0406 0308;;;;N;;;;0457; +0408;CYRILLIC CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;0458; +0409;CYRILLIC CAPITAL LETTER LJE;Lu;0;L;;;;;N;;;;0459; +040A;CYRILLIC CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;045A; +040B;CYRILLIC CAPITAL LETTER TSHE;Lu;0;L;;;;;N;;;;045B; +040C;CYRILLIC CAPITAL LETTER KJE;Lu;0;L;041A 0301;;;;N;;;;045C; +040D;CYRILLIC CAPITAL LETTER I WITH GRAVE;Lu;0;L;0418 0300;;;;N;;;;045D; +040E;CYRILLIC CAPITAL LETTER SHORT U;Lu;0;L;0423 0306;;;;N;;;;045E; +040F;CYRILLIC CAPITAL LETTER DZHE;Lu;0;L;;;;;N;;;;045F; +0410;CYRILLIC CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0430; +0411;CYRILLIC CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;0431; +0412;CYRILLIC CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;0432; +0413;CYRILLIC CAPITAL LETTER GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE;;;0433; +0414;CYRILLIC CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;0434; +0415;CYRILLIC CAPITAL LETTER IE;Lu;0;L;;;;;N;;;;0435; +0416;CYRILLIC CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;0436; +0417;CYRILLIC CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;0437; +0418;CYRILLIC CAPITAL LETTER I;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER II;;;0438; +0419;CYRILLIC CAPITAL LETTER SHORT I;Lu;0;L;0418 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT II;;;0439; +041A;CYRILLIC CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;043A; +041B;CYRILLIC CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;043B; +041C;CYRILLIC CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;043C; +041D;CYRILLIC CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;043D; +041E;CYRILLIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;043E; +041F;CYRILLIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;043F; +0420;CYRILLIC CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;0440; +0421;CYRILLIC CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;0441; +0422;CYRILLIC CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;0442; +0423;CYRILLIC CAPITAL LETTER U;Lu;0;L;;;;;N;;;;0443; +0424;CYRILLIC CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;0444; +0425;CYRILLIC CAPITAL LETTER HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA;;;0445; +0426;CYRILLIC CAPITAL LETTER TSE;Lu;0;L;;;;;N;;;;0446; +0427;CYRILLIC CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;0447; +0428;CYRILLIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0448; +0429;CYRILLIC CAPITAL LETTER SHCHA;Lu;0;L;;;;;N;;;;0449; +042A;CYRILLIC CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;044A; +042B;CYRILLIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER YERI;;;044B; +042C;CYRILLIC CAPITAL LETTER SOFT SIGN;Lu;0;L;;;;;N;;;;044C; +042D;CYRILLIC CAPITAL LETTER E;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED E;;;044D; +042E;CYRILLIC CAPITAL LETTER YU;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IU;;;044E; +042F;CYRILLIC CAPITAL LETTER YA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IA;;;044F; +0430;CYRILLIC SMALL LETTER A;Ll;0;L;;;;;N;;;0410;;0410 +0431;CYRILLIC SMALL LETTER BE;Ll;0;L;;;;;N;;;0411;;0411 +0432;CYRILLIC SMALL LETTER VE;Ll;0;L;;;;;N;;;0412;;0412 +0433;CYRILLIC SMALL LETTER GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE;;0413;;0413 +0434;CYRILLIC SMALL LETTER DE;Ll;0;L;;;;;N;;;0414;;0414 +0435;CYRILLIC SMALL LETTER IE;Ll;0;L;;;;;N;;;0415;;0415 +0436;CYRILLIC SMALL LETTER ZHE;Ll;0;L;;;;;N;;;0416;;0416 +0437;CYRILLIC SMALL LETTER ZE;Ll;0;L;;;;;N;;;0417;;0417 +0438;CYRILLIC SMALL LETTER I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER II;;0418;;0418 +0439;CYRILLIC SMALL LETTER SHORT I;Ll;0;L;0438 0306;;;;N;CYRILLIC SMALL LETTER SHORT II;;0419;;0419 +043A;CYRILLIC SMALL LETTER KA;Ll;0;L;;;;;N;;;041A;;041A +043B;CYRILLIC SMALL LETTER EL;Ll;0;L;;;;;N;;;041B;;041B +043C;CYRILLIC SMALL LETTER EM;Ll;0;L;;;;;N;;;041C;;041C +043D;CYRILLIC SMALL LETTER EN;Ll;0;L;;;;;N;;;041D;;041D +043E;CYRILLIC SMALL LETTER O;Ll;0;L;;;;;N;;;041E;;041E +043F;CYRILLIC SMALL LETTER PE;Ll;0;L;;;;;N;;;041F;;041F +0440;CYRILLIC SMALL LETTER ER;Ll;0;L;;;;;N;;;0420;;0420 +0441;CYRILLIC SMALL LETTER ES;Ll;0;L;;;;;N;;;0421;;0421 +0442;CYRILLIC SMALL LETTER TE;Ll;0;L;;;;;N;;;0422;;0422 +0443;CYRILLIC SMALL LETTER U;Ll;0;L;;;;;N;;;0423;;0423 +0444;CYRILLIC SMALL LETTER EF;Ll;0;L;;;;;N;;;0424;;0424 +0445;CYRILLIC SMALL LETTER HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA;;0425;;0425 +0446;CYRILLIC SMALL LETTER TSE;Ll;0;L;;;;;N;;;0426;;0426 +0447;CYRILLIC SMALL LETTER CHE;Ll;0;L;;;;;N;;;0427;;0427 +0448;CYRILLIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;0428;;0428 +0449;CYRILLIC SMALL LETTER SHCHA;Ll;0;L;;;;;N;;;0429;;0429 +044A;CYRILLIC SMALL LETTER HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A +044B;CYRILLIC SMALL LETTER YERU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER YERI;;042B;;042B +044C;CYRILLIC SMALL LETTER SOFT SIGN;Ll;0;L;;;;;N;;;042C;;042C +044D;CYRILLIC SMALL LETTER E;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED E;;042D;;042D +044E;CYRILLIC SMALL LETTER YU;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IU;;042E;;042E +044F;CYRILLIC SMALL LETTER YA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IA;;042F;;042F +0450;CYRILLIC SMALL LETTER IE WITH GRAVE;Ll;0;L;0435 0300;;;;N;;;0400;;0400 +0451;CYRILLIC SMALL LETTER IO;Ll;0;L;0435 0308;;;;N;;;0401;;0401 +0452;CYRILLIC SMALL LETTER DJE;Ll;0;L;;;;;N;;;0402;;0402 +0453;CYRILLIC SMALL LETTER GJE;Ll;0;L;0433 0301;;;;N;;;0403;;0403 +0454;CYRILLIC SMALL LETTER UKRAINIAN IE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER E;;0404;;0404 +0455;CYRILLIC SMALL LETTER DZE;Ll;0;L;;;;;N;;;0405;;0405 +0456;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER I;;0406;;0406 +0457;CYRILLIC SMALL LETTER YI;Ll;0;L;0456 0308;;;;N;;;0407;;0407 +0458;CYRILLIC SMALL LETTER JE;Ll;0;L;;;;;N;;;0408;;0408 +0459;CYRILLIC SMALL LETTER LJE;Ll;0;L;;;;;N;;;0409;;0409 +045A;CYRILLIC SMALL LETTER NJE;Ll;0;L;;;;;N;;;040A;;040A +045B;CYRILLIC SMALL LETTER TSHE;Ll;0;L;;;;;N;;;040B;;040B +045C;CYRILLIC SMALL LETTER KJE;Ll;0;L;043A 0301;;;;N;;;040C;;040C +045D;CYRILLIC SMALL LETTER I WITH GRAVE;Ll;0;L;0438 0300;;;;N;;;040D;;040D +045E;CYRILLIC SMALL LETTER SHORT U;Ll;0;L;0443 0306;;;;N;;;040E;;040E +045F;CYRILLIC SMALL LETTER DZHE;Ll;0;L;;;;;N;;;040F;;040F +0460;CYRILLIC CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;0461; +0461;CYRILLIC SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;0460;;0460 +0462;CYRILLIC CAPITAL LETTER YAT;Lu;0;L;;;;;N;;;;0463; +0463;CYRILLIC SMALL LETTER YAT;Ll;0;L;;;;;N;;;0462;;0462 +0464;CYRILLIC CAPITAL LETTER IOTIFIED E;Lu;0;L;;;;;N;;;;0465; +0465;CYRILLIC SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;0464;;0464 +0466;CYRILLIC CAPITAL LETTER LITTLE YUS;Lu;0;L;;;;;N;;;;0467; +0467;CYRILLIC SMALL LETTER LITTLE YUS;Ll;0;L;;;;;N;;;0466;;0466 +0468;CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS;Lu;0;L;;;;;N;;;;0469; +0469;CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS;Ll;0;L;;;;;N;;;0468;;0468 +046A;CYRILLIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;046B; +046B;CYRILLIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;046A;;046A +046C;CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS;Lu;0;L;;;;;N;;;;046D; +046D;CYRILLIC SMALL LETTER IOTIFIED BIG YUS;Ll;0;L;;;;;N;;;046C;;046C +046E;CYRILLIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;046F; +046F;CYRILLIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;046E;;046E +0470;CYRILLIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;0471; +0471;CYRILLIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;0470;;0470 +0472;CYRILLIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;0473; +0473;CYRILLIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;0472;;0472 +0474;CYRILLIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;0475; +0475;CYRILLIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;0474;;0474 +0476;CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Lu;0;L;0474 030F;;;;N;CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE;;;0477; +0477;CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT;Ll;0;L;0475 030F;;;;N;CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE;;0476;;0476 +0478;CYRILLIC CAPITAL LETTER UK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER UK DIGRAPH;;;0479; +0479;CYRILLIC SMALL LETTER UK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER UK DIGRAPH;;0478;;0478 +047A;CYRILLIC CAPITAL LETTER ROUND OMEGA;Lu;0;L;;;;;N;;;;047B; +047B;CYRILLIC SMALL LETTER ROUND OMEGA;Ll;0;L;;;;;N;;;047A;;047A +047C;CYRILLIC CAPITAL LETTER OMEGA WITH TITLO;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER OMEGA TITLO;;;047D; +047D;CYRILLIC SMALL LETTER OMEGA WITH TITLO;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER OMEGA TITLO;;047C;;047C +047E;CYRILLIC CAPITAL LETTER OT;Lu;0;L;;;;;N;;;;047F; +047F;CYRILLIC SMALL LETTER OT;Ll;0;L;;;;;N;;;047E;;047E +0480;CYRILLIC CAPITAL LETTER KOPPA;Lu;0;L;;;;;N;;;;0481; +0481;CYRILLIC SMALL LETTER KOPPA;Ll;0;L;;;;;N;;;0480;;0480 +0482;CYRILLIC THOUSANDS SIGN;So;0;L;;;;;N;;;;; +0483;COMBINING CYRILLIC TITLO;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING TITLO;;;; +0484;COMBINING CYRILLIC PALATALIZATION;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PALATALIZATION;;;; +0485;COMBINING CYRILLIC DASIA PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING DASIA PNEUMATA;;;; +0486;COMBINING CYRILLIC PSILI PNEUMATA;Mn;230;NSM;;;;;N;CYRILLIC NON-SPACING PSILI PNEUMATA;;;; +0487;COMBINING CYRILLIC POKRYTIE;Mn;230;NSM;;;;;N;;;;; +0488;COMBINING CYRILLIC HUNDRED THOUSANDS SIGN;Me;0;NSM;;;;;N;;;;; +0489;COMBINING CYRILLIC MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +048A;CYRILLIC CAPITAL LETTER SHORT I WITH TAIL;Lu;0;L;;;;;N;;;;048B; +048B;CYRILLIC SMALL LETTER SHORT I WITH TAIL;Ll;0;L;;;;;N;;;048A;;048A +048C;CYRILLIC CAPITAL LETTER SEMISOFT SIGN;Lu;0;L;;;;;N;;;;048D; +048D;CYRILLIC SMALL LETTER SEMISOFT SIGN;Ll;0;L;;;;;N;;;048C;;048C +048E;CYRILLIC CAPITAL LETTER ER WITH TICK;Lu;0;L;;;;;N;;;;048F; +048F;CYRILLIC SMALL LETTER ER WITH TICK;Ll;0;L;;;;;N;;;048E;;048E +0490;CYRILLIC CAPITAL LETTER GHE WITH UPTURN;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE WITH UPTURN;;;0491; +0491;CYRILLIC SMALL LETTER GHE WITH UPTURN;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE WITH UPTURN;;0490;;0490 +0492;CYRILLIC CAPITAL LETTER GHE WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE BAR;;;0493; +0493;CYRILLIC SMALL LETTER GHE WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE BAR;;0492;;0492 +0494;CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER GE HOOK;;;0495; +0495;CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER GE HOOK;;0494;;0494 +0496;CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER;;;0497; +0497;CYRILLIC SMALL LETTER ZHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER;;0496;;0496 +0498;CYRILLIC CAPITAL LETTER ZE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ZE CEDILLA;;;0499; +0499;CYRILLIC SMALL LETTER ZE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ZE CEDILLA;;0498;;0498 +049A;CYRILLIC CAPITAL LETTER KA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER;;;049B; +049B;CYRILLIC SMALL LETTER KA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER;;049A;;049A +049C;CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA VERTICAL BAR;;;049D; +049D;CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA VERTICAL BAR;;049C;;049C +049E;CYRILLIC CAPITAL LETTER KA WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA BAR;;;049F; +049F;CYRILLIC SMALL LETTER KA WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA BAR;;049E;;049E +04A0;CYRILLIC CAPITAL LETTER BASHKIR KA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER REVERSED GE KA;;;04A1; +04A1;CYRILLIC SMALL LETTER BASHKIR KA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER REVERSED GE KA;;04A0;;04A0 +04A2;CYRILLIC CAPITAL LETTER EN WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER;;;04A3; +04A3;CYRILLIC SMALL LETTER EN WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER;;04A2;;04A2 +04A4;CYRILLIC CAPITAL LIGATURE EN GHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN GE;;;04A5; +04A5;CYRILLIC SMALL LIGATURE EN GHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN GE;;04A4;;04A4 +04A6;CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER PE HOOK;;;04A7; +04A7;CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER PE HOOK;;04A6;;04A6 +04A8;CYRILLIC CAPITAL LETTER ABKHASIAN HA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER O HOOK;;;04A9; +04A9;CYRILLIC SMALL LETTER ABKHASIAN HA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER O HOOK;;04A8;;04A8 +04AA;CYRILLIC CAPITAL LETTER ES WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER ES CEDILLA;;;04AB; +04AB;CYRILLIC SMALL LETTER ES WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER ES CEDILLA;;04AA;;04AA +04AC;CYRILLIC CAPITAL LETTER TE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER;;;04AD; +04AD;CYRILLIC SMALL LETTER TE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER;;04AC;;04AC +04AE;CYRILLIC CAPITAL LETTER STRAIGHT U;Lu;0;L;;;;;N;;;;04AF; +04AF;CYRILLIC SMALL LETTER STRAIGHT U;Ll;0;L;;;;;N;;;04AE;;04AE +04B0;CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER STRAIGHT U BAR;;;04B1; +04B1;CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER STRAIGHT U BAR;;04B0;;04B0 +04B2;CYRILLIC CAPITAL LETTER HA WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER;;;04B3; +04B3;CYRILLIC SMALL LETTER HA WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER;;04B2;;04B2 +04B4;CYRILLIC CAPITAL LIGATURE TE TSE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER TE TSE;;;04B5; +04B5;CYRILLIC SMALL LIGATURE TE TSE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER TE TSE;;04B4;;04B4 +04B6;CYRILLIC CAPITAL LETTER CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER;;;04B7; +04B7;CYRILLIC SMALL LETTER CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER;;04B6;;04B6 +04B8;CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE VERTICAL BAR;;;04B9; +04B9;CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE VERTICAL BAR;;04B8;;04B8 +04BA;CYRILLIC CAPITAL LETTER SHHA;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER H;;;04BB; +04BB;CYRILLIC SMALL LETTER SHHA;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER H;;04BA;;04BA +04BC;CYRILLIC CAPITAL LETTER ABKHASIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK;;;04BD; +04BD;CYRILLIC SMALL LETTER ABKHASIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK;;04BC;;04BC +04BE;CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER IE HOOK OGONEK;;;04BF; +04BF;CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER IE HOOK OGONEK;;04BE;;04BE +04C0;CYRILLIC LETTER PALOCHKA;Lu;0;L;;;;;N;CYRILLIC LETTER I;;;04CF; +04C1;CYRILLIC CAPITAL LETTER ZHE WITH BREVE;Lu;0;L;0416 0306;;;;N;CYRILLIC CAPITAL LETTER SHORT ZHE;;;04C2; +04C2;CYRILLIC SMALL LETTER ZHE WITH BREVE;Ll;0;L;0436 0306;;;;N;CYRILLIC SMALL LETTER SHORT ZHE;;04C1;;04C1 +04C3;CYRILLIC CAPITAL LETTER KA WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER KA HOOK;;;04C4; +04C4;CYRILLIC SMALL LETTER KA WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER KA HOOK;;04C3;;04C3 +04C5;CYRILLIC CAPITAL LETTER EL WITH TAIL;Lu;0;L;;;;;N;;;;04C6; +04C6;CYRILLIC SMALL LETTER EL WITH TAIL;Ll;0;L;;;;;N;;;04C5;;04C5 +04C7;CYRILLIC CAPITAL LETTER EN WITH HOOK;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER EN HOOK;;;04C8; +04C8;CYRILLIC SMALL LETTER EN WITH HOOK;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER EN HOOK;;04C7;;04C7 +04C9;CYRILLIC CAPITAL LETTER EN WITH TAIL;Lu;0;L;;;;;N;;;;04CA; +04CA;CYRILLIC SMALL LETTER EN WITH TAIL;Ll;0;L;;;;;N;;;04C9;;04C9 +04CB;CYRILLIC CAPITAL LETTER KHAKASSIAN CHE;Lu;0;L;;;;;N;CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER;;;04CC; +04CC;CYRILLIC SMALL LETTER KHAKASSIAN CHE;Ll;0;L;;;;;N;CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER;;04CB;;04CB +04CD;CYRILLIC CAPITAL LETTER EM WITH TAIL;Lu;0;L;;;;;N;;;;04CE; +04CE;CYRILLIC SMALL LETTER EM WITH TAIL;Ll;0;L;;;;;N;;;04CD;;04CD +04CF;CYRILLIC SMALL LETTER PALOCHKA;Ll;0;L;;;;;N;;;04C0;;04C0 +04D0;CYRILLIC CAPITAL LETTER A WITH BREVE;Lu;0;L;0410 0306;;;;N;;;;04D1; +04D1;CYRILLIC SMALL LETTER A WITH BREVE;Ll;0;L;0430 0306;;;;N;;;04D0;;04D0 +04D2;CYRILLIC CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0410 0308;;;;N;;;;04D3; +04D3;CYRILLIC SMALL LETTER A WITH DIAERESIS;Ll;0;L;0430 0308;;;;N;;;04D2;;04D2 +04D4;CYRILLIC CAPITAL LIGATURE A IE;Lu;0;L;;;;;N;;;;04D5; +04D5;CYRILLIC SMALL LIGATURE A IE;Ll;0;L;;;;;N;;;04D4;;04D4 +04D6;CYRILLIC CAPITAL LETTER IE WITH BREVE;Lu;0;L;0415 0306;;;;N;;;;04D7; +04D7;CYRILLIC SMALL LETTER IE WITH BREVE;Ll;0;L;0435 0306;;;;N;;;04D6;;04D6 +04D8;CYRILLIC CAPITAL LETTER SCHWA;Lu;0;L;;;;;N;;;;04D9; +04D9;CYRILLIC SMALL LETTER SCHWA;Ll;0;L;;;;;N;;;04D8;;04D8 +04DA;CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS;Lu;0;L;04D8 0308;;;;N;;;;04DB; +04DB;CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS;Ll;0;L;04D9 0308;;;;N;;;04DA;;04DA +04DC;CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS;Lu;0;L;0416 0308;;;;N;;;;04DD; +04DD;CYRILLIC SMALL LETTER ZHE WITH DIAERESIS;Ll;0;L;0436 0308;;;;N;;;04DC;;04DC +04DE;CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS;Lu;0;L;0417 0308;;;;N;;;;04DF; +04DF;CYRILLIC SMALL LETTER ZE WITH DIAERESIS;Ll;0;L;0437 0308;;;;N;;;04DE;;04DE +04E0;CYRILLIC CAPITAL LETTER ABKHASIAN DZE;Lu;0;L;;;;;N;;;;04E1; +04E1;CYRILLIC SMALL LETTER ABKHASIAN DZE;Ll;0;L;;;;;N;;;04E0;;04E0 +04E2;CYRILLIC CAPITAL LETTER I WITH MACRON;Lu;0;L;0418 0304;;;;N;;;;04E3; +04E3;CYRILLIC SMALL LETTER I WITH MACRON;Ll;0;L;0438 0304;;;;N;;;04E2;;04E2 +04E4;CYRILLIC CAPITAL LETTER I WITH DIAERESIS;Lu;0;L;0418 0308;;;;N;;;;04E5; +04E5;CYRILLIC SMALL LETTER I WITH DIAERESIS;Ll;0;L;0438 0308;;;;N;;;04E4;;04E4 +04E6;CYRILLIC CAPITAL LETTER O WITH DIAERESIS;Lu;0;L;041E 0308;;;;N;;;;04E7; +04E7;CYRILLIC SMALL LETTER O WITH DIAERESIS;Ll;0;L;043E 0308;;;;N;;;04E6;;04E6 +04E8;CYRILLIC CAPITAL LETTER BARRED O;Lu;0;L;;;;;N;;;;04E9; +04E9;CYRILLIC SMALL LETTER BARRED O;Ll;0;L;;;;;N;;;04E8;;04E8 +04EA;CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS;Lu;0;L;04E8 0308;;;;N;;;;04EB; +04EB;CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS;Ll;0;L;04E9 0308;;;;N;;;04EA;;04EA +04EC;CYRILLIC CAPITAL LETTER E WITH DIAERESIS;Lu;0;L;042D 0308;;;;N;;;;04ED; +04ED;CYRILLIC SMALL LETTER E WITH DIAERESIS;Ll;0;L;044D 0308;;;;N;;;04EC;;04EC +04EE;CYRILLIC CAPITAL LETTER U WITH MACRON;Lu;0;L;0423 0304;;;;N;;;;04EF; +04EF;CYRILLIC SMALL LETTER U WITH MACRON;Ll;0;L;0443 0304;;;;N;;;04EE;;04EE +04F0;CYRILLIC CAPITAL LETTER U WITH DIAERESIS;Lu;0;L;0423 0308;;;;N;;;;04F1; +04F1;CYRILLIC SMALL LETTER U WITH DIAERESIS;Ll;0;L;0443 0308;;;;N;;;04F0;;04F0 +04F2;CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE;Lu;0;L;0423 030B;;;;N;;;;04F3; +04F3;CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE;Ll;0;L;0443 030B;;;;N;;;04F2;;04F2 +04F4;CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS;Lu;0;L;0427 0308;;;;N;;;;04F5; +04F5;CYRILLIC SMALL LETTER CHE WITH DIAERESIS;Ll;0;L;0447 0308;;;;N;;;04F4;;04F4 +04F6;CYRILLIC CAPITAL LETTER GHE WITH DESCENDER;Lu;0;L;;;;;N;;;;04F7; +04F7;CYRILLIC SMALL LETTER GHE WITH DESCENDER;Ll;0;L;;;;;N;;;04F6;;04F6 +04F8;CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS;Lu;0;L;042B 0308;;;;N;;;;04F9; +04F9;CYRILLIC SMALL LETTER YERU WITH DIAERESIS;Ll;0;L;044B 0308;;;;N;;;04F8;;04F8 +04FA;CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK;Lu;0;L;;;;;N;;;;04FB; +04FB;CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK;Ll;0;L;;;;;N;;;04FA;;04FA +04FC;CYRILLIC CAPITAL LETTER HA WITH HOOK;Lu;0;L;;;;;N;;;;04FD; +04FD;CYRILLIC SMALL LETTER HA WITH HOOK;Ll;0;L;;;;;N;;;04FC;;04FC +04FE;CYRILLIC CAPITAL LETTER HA WITH STROKE;Lu;0;L;;;;;N;;;;04FF; +04FF;CYRILLIC SMALL LETTER HA WITH STROKE;Ll;0;L;;;;;N;;;04FE;;04FE +0500;CYRILLIC CAPITAL LETTER KOMI DE;Lu;0;L;;;;;N;;;;0501; +0501;CYRILLIC SMALL LETTER KOMI DE;Ll;0;L;;;;;N;;;0500;;0500 +0502;CYRILLIC CAPITAL LETTER KOMI DJE;Lu;0;L;;;;;N;;;;0503; +0503;CYRILLIC SMALL LETTER KOMI DJE;Ll;0;L;;;;;N;;;0502;;0502 +0504;CYRILLIC CAPITAL LETTER KOMI ZJE;Lu;0;L;;;;;N;;;;0505; +0505;CYRILLIC SMALL LETTER KOMI ZJE;Ll;0;L;;;;;N;;;0504;;0504 +0506;CYRILLIC CAPITAL LETTER KOMI DZJE;Lu;0;L;;;;;N;;;;0507; +0507;CYRILLIC SMALL LETTER KOMI DZJE;Ll;0;L;;;;;N;;;0506;;0506 +0508;CYRILLIC CAPITAL LETTER KOMI LJE;Lu;0;L;;;;;N;;;;0509; +0509;CYRILLIC SMALL LETTER KOMI LJE;Ll;0;L;;;;;N;;;0508;;0508 +050A;CYRILLIC CAPITAL LETTER KOMI NJE;Lu;0;L;;;;;N;;;;050B; +050B;CYRILLIC SMALL LETTER KOMI NJE;Ll;0;L;;;;;N;;;050A;;050A +050C;CYRILLIC CAPITAL LETTER KOMI SJE;Lu;0;L;;;;;N;;;;050D; +050D;CYRILLIC SMALL LETTER KOMI SJE;Ll;0;L;;;;;N;;;050C;;050C +050E;CYRILLIC CAPITAL LETTER KOMI TJE;Lu;0;L;;;;;N;;;;050F; +050F;CYRILLIC SMALL LETTER KOMI TJE;Ll;0;L;;;;;N;;;050E;;050E +0510;CYRILLIC CAPITAL LETTER REVERSED ZE;Lu;0;L;;;;;N;;;;0511; +0511;CYRILLIC SMALL LETTER REVERSED ZE;Ll;0;L;;;;;N;;;0510;;0510 +0512;CYRILLIC CAPITAL LETTER EL WITH HOOK;Lu;0;L;;;;;N;;;;0513; +0513;CYRILLIC SMALL LETTER EL WITH HOOK;Ll;0;L;;;;;N;;;0512;;0512 +0514;CYRILLIC CAPITAL LETTER LHA;Lu;0;L;;;;;N;;;;0515; +0515;CYRILLIC SMALL LETTER LHA;Ll;0;L;;;;;N;;;0514;;0514 +0516;CYRILLIC CAPITAL LETTER RHA;Lu;0;L;;;;;N;;;;0517; +0517;CYRILLIC SMALL LETTER RHA;Ll;0;L;;;;;N;;;0516;;0516 +0518;CYRILLIC CAPITAL LETTER YAE;Lu;0;L;;;;;N;;;;0519; +0519;CYRILLIC SMALL LETTER YAE;Ll;0;L;;;;;N;;;0518;;0518 +051A;CYRILLIC CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;051B; +051B;CYRILLIC SMALL LETTER QA;Ll;0;L;;;;;N;;;051A;;051A +051C;CYRILLIC CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;051D; +051D;CYRILLIC SMALL LETTER WE;Ll;0;L;;;;;N;;;051C;;051C +051E;CYRILLIC CAPITAL LETTER ALEUT KA;Lu;0;L;;;;;N;;;;051F; +051F;CYRILLIC SMALL LETTER ALEUT KA;Ll;0;L;;;;;N;;;051E;;051E +0520;CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0521; +0521;CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0520;;0520 +0522;CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;0523; +0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 +0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; +0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 +0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527; +0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526 +0528;CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK;Lu;0;L;;;;;N;;;;0529; +0529;CYRILLIC SMALL LETTER EN WITH LEFT HOOK;Ll;0;L;;;;;N;;;0528;;0528 +052A;CYRILLIC CAPITAL LETTER DZZHE;Lu;0;L;;;;;N;;;;052B; +052B;CYRILLIC SMALL LETTER DZZHE;Ll;0;L;;;;;N;;;052A;;052A +052C;CYRILLIC CAPITAL LETTER DCHE;Lu;0;L;;;;;N;;;;052D; +052D;CYRILLIC SMALL LETTER DCHE;Ll;0;L;;;;;N;;;052C;;052C +052E;CYRILLIC CAPITAL LETTER EL WITH DESCENDER;Lu;0;L;;;;;N;;;;052F; +052F;CYRILLIC SMALL LETTER EL WITH DESCENDER;Ll;0;L;;;;;N;;;052E;;052E +0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; +0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; +0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; +0534;ARMENIAN CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;0564; +0535;ARMENIAN CAPITAL LETTER ECH;Lu;0;L;;;;;N;;;;0565; +0536;ARMENIAN CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;0566; +0537;ARMENIAN CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;0567; +0538;ARMENIAN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;0568; +0539;ARMENIAN CAPITAL LETTER TO;Lu;0;L;;;;;N;;;;0569; +053A;ARMENIAN CAPITAL LETTER ZHE;Lu;0;L;;;;;N;;;;056A; +053B;ARMENIAN CAPITAL LETTER INI;Lu;0;L;;;;;N;;;;056B; +053C;ARMENIAN CAPITAL LETTER LIWN;Lu;0;L;;;;;N;;;;056C; +053D;ARMENIAN CAPITAL LETTER XEH;Lu;0;L;;;;;N;;;;056D; +053E;ARMENIAN CAPITAL LETTER CA;Lu;0;L;;;;;N;;;;056E; +053F;ARMENIAN CAPITAL LETTER KEN;Lu;0;L;;;;;N;;;;056F; +0540;ARMENIAN CAPITAL LETTER HO;Lu;0;L;;;;;N;;;;0570; +0541;ARMENIAN CAPITAL LETTER JA;Lu;0;L;;;;;N;;;;0571; +0542;ARMENIAN CAPITAL LETTER GHAD;Lu;0;L;;;;;N;ARMENIAN CAPITAL LETTER LAD;;;0572; +0543;ARMENIAN CAPITAL LETTER CHEH;Lu;0;L;;;;;N;;;;0573; +0544;ARMENIAN CAPITAL LETTER MEN;Lu;0;L;;;;;N;;;;0574; +0545;ARMENIAN CAPITAL LETTER YI;Lu;0;L;;;;;N;;;;0575; +0546;ARMENIAN CAPITAL LETTER NOW;Lu;0;L;;;;;N;;;;0576; +0547;ARMENIAN CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;0577; +0548;ARMENIAN CAPITAL LETTER VO;Lu;0;L;;;;;N;;;;0578; +0549;ARMENIAN CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;0579; +054A;ARMENIAN CAPITAL LETTER PEH;Lu;0;L;;;;;N;;;;057A; +054B;ARMENIAN CAPITAL LETTER JHEH;Lu;0;L;;;;;N;;;;057B; +054C;ARMENIAN CAPITAL LETTER RA;Lu;0;L;;;;;N;;;;057C; +054D;ARMENIAN CAPITAL LETTER SEH;Lu;0;L;;;;;N;;;;057D; +054E;ARMENIAN CAPITAL LETTER VEW;Lu;0;L;;;;;N;;;;057E; +054F;ARMENIAN CAPITAL LETTER TIWN;Lu;0;L;;;;;N;;;;057F; +0550;ARMENIAN CAPITAL LETTER REH;Lu;0;L;;;;;N;;;;0580; +0551;ARMENIAN CAPITAL LETTER CO;Lu;0;L;;;;;N;;;;0581; +0552;ARMENIAN CAPITAL LETTER YIWN;Lu;0;L;;;;;N;;;;0582; +0553;ARMENIAN CAPITAL LETTER PIWR;Lu;0;L;;;;;N;;;;0583; +0554;ARMENIAN CAPITAL LETTER KEH;Lu;0;L;;;;;N;;;;0584; +0555;ARMENIAN CAPITAL LETTER OH;Lu;0;L;;;;;N;;;;0585; +0556;ARMENIAN CAPITAL LETTER FEH;Lu;0;L;;;;;N;;;;0586; +0559;ARMENIAN MODIFIER LETTER LEFT HALF RING;Lm;0;L;;;;;N;;;;; +055A;ARMENIAN APOSTROPHE;Po;0;L;;;;;N;ARMENIAN MODIFIER LETTER RIGHT HALF RING;;;; +055B;ARMENIAN EMPHASIS MARK;Po;0;L;;;;;N;;;;; +055C;ARMENIAN EXCLAMATION MARK;Po;0;L;;;;;N;;;;; +055D;ARMENIAN COMMA;Po;0;L;;;;;N;;;;; +055E;ARMENIAN QUESTION MARK;Po;0;L;;;;;N;;;;; +055F;ARMENIAN ABBREVIATION MARK;Po;0;L;;;;;N;;;;; +0560;ARMENIAN SMALL LETTER TURNED AYB;Ll;0;L;;;;;N;;;;; +0561;ARMENIAN SMALL LETTER AYB;Ll;0;L;;;;;N;;;0531;;0531 +0562;ARMENIAN SMALL LETTER BEN;Ll;0;L;;;;;N;;;0532;;0532 +0563;ARMENIAN SMALL LETTER GIM;Ll;0;L;;;;;N;;;0533;;0533 +0564;ARMENIAN SMALL LETTER DA;Ll;0;L;;;;;N;;;0534;;0534 +0565;ARMENIAN SMALL LETTER ECH;Ll;0;L;;;;;N;;;0535;;0535 +0566;ARMENIAN SMALL LETTER ZA;Ll;0;L;;;;;N;;;0536;;0536 +0567;ARMENIAN SMALL LETTER EH;Ll;0;L;;;;;N;;;0537;;0537 +0568;ARMENIAN SMALL LETTER ET;Ll;0;L;;;;;N;;;0538;;0538 +0569;ARMENIAN SMALL LETTER TO;Ll;0;L;;;;;N;;;0539;;0539 +056A;ARMENIAN SMALL LETTER ZHE;Ll;0;L;;;;;N;;;053A;;053A +056B;ARMENIAN SMALL LETTER INI;Ll;0;L;;;;;N;;;053B;;053B +056C;ARMENIAN SMALL LETTER LIWN;Ll;0;L;;;;;N;;;053C;;053C +056D;ARMENIAN SMALL LETTER XEH;Ll;0;L;;;;;N;;;053D;;053D +056E;ARMENIAN SMALL LETTER CA;Ll;0;L;;;;;N;;;053E;;053E +056F;ARMENIAN SMALL LETTER KEN;Ll;0;L;;;;;N;;;053F;;053F +0570;ARMENIAN SMALL LETTER HO;Ll;0;L;;;;;N;;;0540;;0540 +0571;ARMENIAN SMALL LETTER JA;Ll;0;L;;;;;N;;;0541;;0541 +0572;ARMENIAN SMALL LETTER GHAD;Ll;0;L;;;;;N;ARMENIAN SMALL LETTER LAD;;0542;;0542 +0573;ARMENIAN SMALL LETTER CHEH;Ll;0;L;;;;;N;;;0543;;0543 +0574;ARMENIAN SMALL LETTER MEN;Ll;0;L;;;;;N;;;0544;;0544 +0575;ARMENIAN SMALL LETTER YI;Ll;0;L;;;;;N;;;0545;;0545 +0576;ARMENIAN SMALL LETTER NOW;Ll;0;L;;;;;N;;;0546;;0546 +0577;ARMENIAN SMALL LETTER SHA;Ll;0;L;;;;;N;;;0547;;0547 +0578;ARMENIAN SMALL LETTER VO;Ll;0;L;;;;;N;;;0548;;0548 +0579;ARMENIAN SMALL LETTER CHA;Ll;0;L;;;;;N;;;0549;;0549 +057A;ARMENIAN SMALL LETTER PEH;Ll;0;L;;;;;N;;;054A;;054A +057B;ARMENIAN SMALL LETTER JHEH;Ll;0;L;;;;;N;;;054B;;054B +057C;ARMENIAN SMALL LETTER RA;Ll;0;L;;;;;N;;;054C;;054C +057D;ARMENIAN SMALL LETTER SEH;Ll;0;L;;;;;N;;;054D;;054D +057E;ARMENIAN SMALL LETTER VEW;Ll;0;L;;;;;N;;;054E;;054E +057F;ARMENIAN SMALL LETTER TIWN;Ll;0;L;;;;;N;;;054F;;054F +0580;ARMENIAN SMALL LETTER REH;Ll;0;L;;;;;N;;;0550;;0550 +0581;ARMENIAN SMALL LETTER CO;Ll;0;L;;;;;N;;;0551;;0551 +0582;ARMENIAN SMALL LETTER YIWN;Ll;0;L;;;;;N;;;0552;;0552 +0583;ARMENIAN SMALL LETTER PIWR;Ll;0;L;;;;;N;;;0553;;0553 +0584;ARMENIAN SMALL LETTER KEH;Ll;0;L;;;;;N;;;0554;;0554 +0585;ARMENIAN SMALL LETTER OH;Ll;0;L;;;;;N;;;0555;;0555 +0586;ARMENIAN SMALL LETTER FEH;Ll;0;L;;;;;N;;;0556;;0556 +0587;ARMENIAN SMALL LIGATURE ECH YIWN;Ll;0;L; 0565 0582;;;;N;;;;; +0588;ARMENIAN SMALL LETTER YI WITH STROKE;Ll;0;L;;;;;N;;;;; +0589;ARMENIAN FULL STOP;Po;0;L;;;;;N;ARMENIAN PERIOD;;;; +058A;ARMENIAN HYPHEN;Pd;0;ON;;;;;N;;;;; +058D;RIGHT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; +058E;LEFT-FACING ARMENIAN ETERNITY SIGN;So;0;ON;;;;;N;;;;; +058F;ARMENIAN DRAM SIGN;Sc;0;ET;;;;;N;;;;; +0591;HEBREW ACCENT ETNAHTA;Mn;220;NSM;;;;;N;;;;; +0592;HEBREW ACCENT SEGOL;Mn;230;NSM;;;;;N;;;;; +0593;HEBREW ACCENT SHALSHELET;Mn;230;NSM;;;;;N;;;;; +0594;HEBREW ACCENT ZAQEF QATAN;Mn;230;NSM;;;;;N;;;;; +0595;HEBREW ACCENT ZAQEF GADOL;Mn;230;NSM;;;;;N;;;;; +0596;HEBREW ACCENT TIPEHA;Mn;220;NSM;;;;;N;;;;; +0597;HEBREW ACCENT REVIA;Mn;230;NSM;;;;;N;;;;; +0598;HEBREW ACCENT ZARQA;Mn;230;NSM;;;;;N;;;;; +0599;HEBREW ACCENT PASHTA;Mn;230;NSM;;;;;N;;;;; +059A;HEBREW ACCENT YETIV;Mn;222;NSM;;;;;N;;;;; +059B;HEBREW ACCENT TEVIR;Mn;220;NSM;;;;;N;;;;; +059C;HEBREW ACCENT GERESH;Mn;230;NSM;;;;;N;;;;; +059D;HEBREW ACCENT GERESH MUQDAM;Mn;230;NSM;;;;;N;;;;; +059E;HEBREW ACCENT GERSHAYIM;Mn;230;NSM;;;;;N;;;;; +059F;HEBREW ACCENT QARNEY PARA;Mn;230;NSM;;;;;N;;;;; +05A0;HEBREW ACCENT TELISHA GEDOLA;Mn;230;NSM;;;;;N;;;;; +05A1;HEBREW ACCENT PAZER;Mn;230;NSM;;;;;N;;;;; +05A2;HEBREW ACCENT ATNAH HAFUKH;Mn;220;NSM;;;;;N;;;;; +05A3;HEBREW ACCENT MUNAH;Mn;220;NSM;;;;;N;;;;; +05A4;HEBREW ACCENT MAHAPAKH;Mn;220;NSM;;;;;N;;;;; +05A5;HEBREW ACCENT MERKHA;Mn;220;NSM;;;;;N;;;;; +05A6;HEBREW ACCENT MERKHA KEFULA;Mn;220;NSM;;;;;N;;;;; +05A7;HEBREW ACCENT DARGA;Mn;220;NSM;;;;;N;;;;; +05A8;HEBREW ACCENT QADMA;Mn;230;NSM;;;;;N;;;;; +05A9;HEBREW ACCENT TELISHA QETANA;Mn;230;NSM;;;;;N;;;;; +05AA;HEBREW ACCENT YERAH BEN YOMO;Mn;220;NSM;;;;;N;;;;; +05AB;HEBREW ACCENT OLE;Mn;230;NSM;;;;;N;;;;; +05AC;HEBREW ACCENT ILUY;Mn;230;NSM;;;;;N;;;;; +05AD;HEBREW ACCENT DEHI;Mn;222;NSM;;;;;N;;;;; +05AE;HEBREW ACCENT ZINOR;Mn;228;NSM;;;;;N;;;;; +05AF;HEBREW MARK MASORA CIRCLE;Mn;230;NSM;;;;;N;;;;; +05B0;HEBREW POINT SHEVA;Mn;10;NSM;;;;;N;;;;; +05B1;HEBREW POINT HATAF SEGOL;Mn;11;NSM;;;;;N;;;;; +05B2;HEBREW POINT HATAF PATAH;Mn;12;NSM;;;;;N;;;;; +05B3;HEBREW POINT HATAF QAMATS;Mn;13;NSM;;;;;N;;;;; +05B4;HEBREW POINT HIRIQ;Mn;14;NSM;;;;;N;;;;; +05B5;HEBREW POINT TSERE;Mn;15;NSM;;;;;N;;;;; +05B6;HEBREW POINT SEGOL;Mn;16;NSM;;;;;N;;;;; +05B7;HEBREW POINT PATAH;Mn;17;NSM;;;;;N;;;;; +05B8;HEBREW POINT QAMATS;Mn;18;NSM;;;;;N;;;;; +05B9;HEBREW POINT HOLAM;Mn;19;NSM;;;;;N;;;;; +05BA;HEBREW POINT HOLAM HASER FOR VAV;Mn;19;NSM;;;;;N;;;;; +05BB;HEBREW POINT QUBUTS;Mn;20;NSM;;;;;N;;;;; +05BC;HEBREW POINT DAGESH OR MAPIQ;Mn;21;NSM;;;;;N;HEBREW POINT DAGESH;;;; +05BD;HEBREW POINT METEG;Mn;22;NSM;;;;;N;;;;; +05BE;HEBREW PUNCTUATION MAQAF;Pd;0;R;;;;;N;;;;; +05BF;HEBREW POINT RAFE;Mn;23;NSM;;;;;N;;;;; +05C0;HEBREW PUNCTUATION PASEQ;Po;0;R;;;;;N;HEBREW POINT PASEQ;;;; +05C1;HEBREW POINT SHIN DOT;Mn;24;NSM;;;;;N;;;;; +05C2;HEBREW POINT SIN DOT;Mn;25;NSM;;;;;N;;;;; +05C3;HEBREW PUNCTUATION SOF PASUQ;Po;0;R;;;;;N;;;;; +05C4;HEBREW MARK UPPER DOT;Mn;230;NSM;;;;;N;;;;; +05C5;HEBREW MARK LOWER DOT;Mn;220;NSM;;;;;N;;;;; +05C6;HEBREW PUNCTUATION NUN HAFUKHA;Po;0;R;;;;;N;;;;; +05C7;HEBREW POINT QAMATS QATAN;Mn;18;NSM;;;;;N;;;;; +05D0;HEBREW LETTER ALEF;Lo;0;R;;;;;N;;;;; +05D1;HEBREW LETTER BET;Lo;0;R;;;;;N;;;;; +05D2;HEBREW LETTER GIMEL;Lo;0;R;;;;;N;;;;; +05D3;HEBREW LETTER DALET;Lo;0;R;;;;;N;;;;; +05D4;HEBREW LETTER HE;Lo;0;R;;;;;N;;;;; +05D5;HEBREW LETTER VAV;Lo;0;R;;;;;N;;;;; +05D6;HEBREW LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +05D7;HEBREW LETTER HET;Lo;0;R;;;;;N;;;;; +05D8;HEBREW LETTER TET;Lo;0;R;;;;;N;;;;; +05D9;HEBREW LETTER YOD;Lo;0;R;;;;;N;;;;; +05DA;HEBREW LETTER FINAL KAF;Lo;0;R;;;;;N;;;;; +05DB;HEBREW LETTER KAF;Lo;0;R;;;;;N;;;;; +05DC;HEBREW LETTER LAMED;Lo;0;R;;;;;N;;;;; +05DD;HEBREW LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; +05DE;HEBREW LETTER MEM;Lo;0;R;;;;;N;;;;; +05DF;HEBREW LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +05E0;HEBREW LETTER NUN;Lo;0;R;;;;;N;;;;; +05E1;HEBREW LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +05E2;HEBREW LETTER AYIN;Lo;0;R;;;;;N;;;;; +05E3;HEBREW LETTER FINAL PE;Lo;0;R;;;;;N;;;;; +05E4;HEBREW LETTER PE;Lo;0;R;;;;;N;;;;; +05E5;HEBREW LETTER FINAL TSADI;Lo;0;R;;;;;N;;;;; +05E6;HEBREW LETTER TSADI;Lo;0;R;;;;;N;;;;; +05E7;HEBREW LETTER QOF;Lo;0;R;;;;;N;;;;; +05E8;HEBREW LETTER RESH;Lo;0;R;;;;;N;;;;; +05E9;HEBREW LETTER SHIN;Lo;0;R;;;;;N;;;;; +05EA;HEBREW LETTER TAV;Lo;0;R;;;;;N;;;;; +05EF;HEBREW YOD TRIANGLE;Lo;0;R;;;;;N;;;;; +05F0;HEBREW LIGATURE YIDDISH DOUBLE VAV;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE VAV;;;; +05F1;HEBREW LIGATURE YIDDISH VAV YOD;Lo;0;R;;;;;N;HEBREW LETTER VAV YOD;;;; +05F2;HEBREW LIGATURE YIDDISH DOUBLE YOD;Lo;0;R;;;;;N;HEBREW LETTER DOUBLE YOD;;;; +05F3;HEBREW PUNCTUATION GERESH;Po;0;R;;;;;N;;;;; +05F4;HEBREW PUNCTUATION GERSHAYIM;Po;0;R;;;;;N;;;;; +0600;ARABIC NUMBER SIGN;Cf;0;AN;;;;;N;;;;; +0601;ARABIC SIGN SANAH;Cf;0;AN;;;;;N;;;;; +0602;ARABIC FOOTNOTE MARKER;Cf;0;AN;;;;;N;;;;; +0603;ARABIC SIGN SAFHA;Cf;0;AN;;;;;N;;;;; +0604;ARABIC SIGN SAMVAT;Cf;0;AN;;;;;N;;;;; +0605;ARABIC NUMBER MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0606;ARABIC-INDIC CUBE ROOT;Sm;0;ON;;;;;N;;;;; +0607;ARABIC-INDIC FOURTH ROOT;Sm;0;ON;;;;;N;;;;; +0608;ARABIC RAY;Sm;0;AL;;;;;N;;;;; +0609;ARABIC-INDIC PER MILLE SIGN;Po;0;ET;;;;;N;;;;; +060A;ARABIC-INDIC PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; +060B;AFGHANI SIGN;Sc;0;AL;;;;;N;;;;; +060C;ARABIC COMMA;Po;0;CS;;;;;N;;;;; +060D;ARABIC DATE SEPARATOR;Po;0;AL;;;;;N;;;;; +060E;ARABIC POETIC VERSE SIGN;So;0;ON;;;;;N;;;;; +060F;ARABIC SIGN MISRA;So;0;ON;;;;;N;;;;; +0610;ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM;Mn;230;NSM;;;;;N;;;;; +0611;ARABIC SIGN ALAYHE ASSALLAM;Mn;230;NSM;;;;;N;;;;; +0612;ARABIC SIGN RAHMATULLAH ALAYHE;Mn;230;NSM;;;;;N;;;;; +0613;ARABIC SIGN RADI ALLAHOU ANHU;Mn;230;NSM;;;;;N;;;;; +0614;ARABIC SIGN TAKHALLUS;Mn;230;NSM;;;;;N;;;;; +0615;ARABIC SMALL HIGH TAH;Mn;230;NSM;;;;;N;;;;; +0616;ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH;Mn;230;NSM;;;;;N;;;;; +0617;ARABIC SMALL HIGH ZAIN;Mn;230;NSM;;;;;N;;;;; +0618;ARABIC SMALL FATHA;Mn;30;NSM;;;;;N;;;;; +0619;ARABIC SMALL DAMMA;Mn;31;NSM;;;;;N;;;;; +061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;; +061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; +061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;; +061D;ARABIC END OF TEXT MARK;Po;0;AL;;;;;N;;;;; +061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; +061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; +0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; +0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; +0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; +0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; +0624;ARABIC LETTER WAW WITH HAMZA ABOVE;Lo;0;AL;0648 0654;;;;N;ARABIC LETTER HAMZAH ON WAW;;;; +0625;ARABIC LETTER ALEF WITH HAMZA BELOW;Lo;0;AL;0627 0655;;;;N;ARABIC LETTER HAMZAH UNDER ALEF;;;; +0626;ARABIC LETTER YEH WITH HAMZA ABOVE;Lo;0;AL;064A 0654;;;;N;ARABIC LETTER HAMZAH ON YA;;;; +0627;ARABIC LETTER ALEF;Lo;0;AL;;;;;N;;;;; +0628;ARABIC LETTER BEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA;;;; +0629;ARABIC LETTER TEH MARBUTA;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH;;;; +062A;ARABIC LETTER TEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA;;;; +062B;ARABIC LETTER THEH;Lo;0;AL;;;;;N;ARABIC LETTER THAA;;;; +062C;ARABIC LETTER JEEM;Lo;0;AL;;;;;N;;;;; +062D;ARABIC LETTER HAH;Lo;0;AL;;;;;N;ARABIC LETTER HAA;;;; +062E;ARABIC LETTER KHAH;Lo;0;AL;;;;;N;ARABIC LETTER KHAA;;;; +062F;ARABIC LETTER DAL;Lo;0;AL;;;;;N;;;;; +0630;ARABIC LETTER THAL;Lo;0;AL;;;;;N;;;;; +0631;ARABIC LETTER REH;Lo;0;AL;;;;;N;ARABIC LETTER RA;;;; +0632;ARABIC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; +0633;ARABIC LETTER SEEN;Lo;0;AL;;;;;N;;;;; +0634;ARABIC LETTER SHEEN;Lo;0;AL;;;;;N;;;;; +0635;ARABIC LETTER SAD;Lo;0;AL;;;;;N;;;;; +0636;ARABIC LETTER DAD;Lo;0;AL;;;;;N;;;;; +0637;ARABIC LETTER TAH;Lo;0;AL;;;;;N;;;;; +0638;ARABIC LETTER ZAH;Lo;0;AL;;;;;N;ARABIC LETTER DHAH;;;; +0639;ARABIC LETTER AIN;Lo;0;AL;;;;;N;;;;; +063A;ARABIC LETTER GHAIN;Lo;0;AL;;;;;N;;;;; +063B;ARABIC LETTER KEHEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +063C;ARABIC LETTER KEHEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +063D;ARABIC LETTER FARSI YEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +063E;ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +063F;ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0640;ARABIC TATWEEL;Lm;0;AL;;;;;N;;;;; +0641;ARABIC LETTER FEH;Lo;0;AL;;;;;N;ARABIC LETTER FA;;;; +0642;ARABIC LETTER QAF;Lo;0;AL;;;;;N;;;;; +0643;ARABIC LETTER KAF;Lo;0;AL;;;;;N;ARABIC LETTER CAF;;;; +0644;ARABIC LETTER LAM;Lo;0;AL;;;;;N;;;;; +0645;ARABIC LETTER MEEM;Lo;0;AL;;;;;N;;;;; +0646;ARABIC LETTER NOON;Lo;0;AL;;;;;N;;;;; +0647;ARABIC LETTER HEH;Lo;0;AL;;;;;N;ARABIC LETTER HA;;;; +0648;ARABIC LETTER WAW;Lo;0;AL;;;;;N;;;;; +0649;ARABIC LETTER ALEF MAKSURA;Lo;0;AL;;;;;N;ARABIC LETTER ALEF MAQSURAH;;;; +064A;ARABIC LETTER YEH;Lo;0;AL;;;;;N;ARABIC LETTER YA;;;; +064B;ARABIC FATHATAN;Mn;27;NSM;;;;;N;;;;; +064C;ARABIC DAMMATAN;Mn;28;NSM;;;;;N;;;;; +064D;ARABIC KASRATAN;Mn;29;NSM;;;;;N;;;;; +064E;ARABIC FATHA;Mn;30;NSM;;;;;N;ARABIC FATHAH;;;; +064F;ARABIC DAMMA;Mn;31;NSM;;;;;N;ARABIC DAMMAH;;;; +0650;ARABIC KASRA;Mn;32;NSM;;;;;N;ARABIC KASRAH;;;; +0651;ARABIC SHADDA;Mn;33;NSM;;;;;N;ARABIC SHADDAH;;;; +0652;ARABIC SUKUN;Mn;34;NSM;;;;;N;;;;; +0653;ARABIC MADDAH ABOVE;Mn;230;NSM;;;;;N;;;;; +0654;ARABIC HAMZA ABOVE;Mn;230;NSM;;;;;N;;;;; +0655;ARABIC HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; +0656;ARABIC SUBSCRIPT ALEF;Mn;220;NSM;;;;;N;;;;; +0657;ARABIC INVERTED DAMMA;Mn;230;NSM;;;;;N;;;;; +0658;ARABIC MARK NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; +0659;ARABIC ZWARAKAY;Mn;230;NSM;;;;;N;;;;; +065A;ARABIC VOWEL SIGN SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; +065B;ARABIC VOWEL SIGN INVERTED SMALL V ABOVE;Mn;230;NSM;;;;;N;;;;; +065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; +065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; +065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; +065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; +0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; +0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; +0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; +0663;ARABIC-INDIC DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; +0664;ARABIC-INDIC DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; +0665;ARABIC-INDIC DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; +0666;ARABIC-INDIC DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; +0667;ARABIC-INDIC DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; +0668;ARABIC-INDIC DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; +0669;ARABIC-INDIC DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; +066A;ARABIC PERCENT SIGN;Po;0;ET;;;;;N;;;;; +066B;ARABIC DECIMAL SEPARATOR;Po;0;AN;;;;;N;;;;; +066C;ARABIC THOUSANDS SEPARATOR;Po;0;AN;;;;;N;;;;; +066D;ARABIC FIVE POINTED STAR;Po;0;AL;;;;;N;;;;; +066E;ARABIC LETTER DOTLESS BEH;Lo;0;AL;;;;;N;;;;; +066F;ARABIC LETTER DOTLESS QAF;Lo;0;AL;;;;;N;;;;; +0670;ARABIC LETTER SUPERSCRIPT ALEF;Mn;35;NSM;;;;;N;ARABIC ALEF ABOVE;;;; +0671;ARABIC LETTER ALEF WASLA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAT WASL ON ALEF;;;; +0672;ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH ON ALEF;;;; +0673;ARABIC LETTER ALEF WITH WAVY HAMZA BELOW;Lo;0;AL;;;;;N;ARABIC LETTER WAVY HAMZAH UNDER ALEF;;;; +0674;ARABIC LETTER HIGH HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HIGH HAMZAH;;;; +0675;ARABIC LETTER HIGH HAMZA ALEF;Lo;0;AL; 0627 0674;;;;N;ARABIC LETTER HIGH HAMZAH ALEF;;;; +0676;ARABIC LETTER HIGH HAMZA WAW;Lo;0;AL; 0648 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW;;;; +0677;ARABIC LETTER U WITH HAMZA ABOVE;Lo;0;AL; 06C7 0674;;;;N;ARABIC LETTER HIGH HAMZAH WAW WITH DAMMAH;;;; +0678;ARABIC LETTER HIGH HAMZA YEH;Lo;0;AL; 064A 0674;;;;N;ARABIC LETTER HIGH HAMZAH YA;;;; +0679;ARABIC LETTER TTEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH SMALL TAH;;;; +067A;ARABIC LETTER TTEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH TWO DOTS VERTICAL ABOVE;;;; +067B;ARABIC LETTER BEEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH TWO DOTS VERTICAL BELOW;;;; +067C;ARABIC LETTER TEH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH RING;;;; +067D;ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS ABOVE DOWNWARD;;;; +067E;ARABIC LETTER PEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH THREE DOTS BELOW;;;; +067F;ARABIC LETTER TEHEH;Lo;0;AL;;;;;N;ARABIC LETTER TAA WITH FOUR DOTS ABOVE;;;; +0680;ARABIC LETTER BEHEH;Lo;0;AL;;;;;N;ARABIC LETTER BAA WITH FOUR DOTS BELOW;;;; +0681;ARABIC LETTER HAH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH ON HAA;;;; +0682;ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH TWO DOTS VERTICAL ABOVE;;;; +0683;ARABIC LETTER NYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS;;;; +0684;ARABIC LETTER DYEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE TWO DOTS VERTICAL;;;; +0685;ARABIC LETTER HAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH THREE DOTS ABOVE;;;; +0686;ARABIC LETTER TCHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE THREE DOTS DOWNWARD;;;; +0687;ARABIC LETTER TCHEHEH;Lo;0;AL;;;;;N;ARABIC LETTER HAA WITH MIDDLE FOUR DOTS;;;; +0688;ARABIC LETTER DDAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH SMALL TAH;;;; +0689;ARABIC LETTER DAL WITH RING;Lo;0;AL;;;;;N;;;;; +068A;ARABIC LETTER DAL WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +068B;ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; +068C;ARABIC LETTER DAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS ABOVE;;;; +068D;ARABIC LETTER DDAHAL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH TWO DOTS BELOW;;;; +068E;ARABIC LETTER DUL;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE;;;; +068F;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS;Lo;0;AL;;;;;N;ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARD;;;; +0690;ARABIC LETTER DAL WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0691;ARABIC LETTER RREH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL TAH;;;; +0692;ARABIC LETTER REH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V;;;; +0693;ARABIC LETTER REH WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH RING;;;; +0694;ARABIC LETTER REH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW;;;; +0695;ARABIC LETTER REH WITH SMALL V BELOW;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH SMALL V BELOW;;;; +0696;ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH DOT BELOW AND DOT ABOVE;;;; +0697;ARABIC LETTER REH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH TWO DOTS ABOVE;;;; +0698;ARABIC LETTER JEH;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH THREE DOTS ABOVE;;;; +0699;ARABIC LETTER REH WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER RA WITH FOUR DOTS ABOVE;;;; +069A;ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +069B;ARABIC LETTER SEEN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +069C;ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +069D;ARABIC LETTER SAD WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +069E;ARABIC LETTER SAD WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +069F;ARABIC LETTER TAH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A0;ARABIC LETTER AIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A1;ARABIC LETTER DOTLESS FEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS FA;;;; +06A2;ARABIC LETTER FEH WITH DOT MOVED BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT MOVED BELOW;;;; +06A3;ARABIC LETTER FEH WITH DOT BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH DOT BELOW;;;; +06A4;ARABIC LETTER VEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS ABOVE;;;; +06A5;ARABIC LETTER FEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH THREE DOTS BELOW;;;; +06A6;ARABIC LETTER PEHEH;Lo;0;AL;;;;;N;ARABIC LETTER FA WITH FOUR DOTS ABOVE;;;; +06A7;ARABIC LETTER QAF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06A8;ARABIC LETTER QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06A9;ARABIC LETTER KEHEH;Lo;0;AL;;;;;N;ARABIC LETTER OPEN CAF;;;; +06AA;ARABIC LETTER SWASH KAF;Lo;0;AL;;;;;N;ARABIC LETTER SWASH CAF;;;; +06AB;ARABIC LETTER KAF WITH RING;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH RING;;;; +06AC;ARABIC LETTER KAF WITH DOT ABOVE;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH DOT ABOVE;;;; +06AD;ARABIC LETTER NG;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS ABOVE;;;; +06AE;ARABIC LETTER KAF WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER CAF WITH THREE DOTS BELOW;;;; +06AF;ARABIC LETTER GAF;Lo;0;AL;;;;;N;;;;; +06B0;ARABIC LETTER GAF WITH RING;Lo;0;AL;;;;;N;;;;; +06B1;ARABIC LETTER NGOEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS ABOVE;;;; +06B2;ARABIC LETTER GAF WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +06B3;ARABIC LETTER GUEH;Lo;0;AL;;;;;N;ARABIC LETTER GAF WITH TWO DOTS VERTICAL BELOW;;;; +06B4;ARABIC LETTER GAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06B5;ARABIC LETTER LAM WITH SMALL V;Lo;0;AL;;;;;N;;;;; +06B6;ARABIC LETTER LAM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06B7;ARABIC LETTER LAM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06B8;ARABIC LETTER LAM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +06B9;ARABIC LETTER NOON WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06BA;ARABIC LETTER NOON GHUNNA;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON;;;; +06BB;ARABIC LETTER RNOON;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS NOON WITH SMALL TAH;;;; +06BC;ARABIC LETTER NOON WITH RING;Lo;0;AL;;;;;N;;;;; +06BD;ARABIC LETTER NOON WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06BE;ARABIC LETTER HEH DOACHASHMEE;Lo;0;AL;;;;;N;ARABIC LETTER KNOTTED HA;;;; +06BF;ARABIC LETTER TCHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06C0;ARABIC LETTER HEH WITH YEH ABOVE;Lo;0;AL;06D5 0654;;;;N;ARABIC LETTER HAMZAH ON HA;;;; +06C1;ARABIC LETTER HEH GOAL;Lo;0;AL;;;;;N;ARABIC LETTER HA GOAL;;;; +06C2;ARABIC LETTER HEH GOAL WITH HAMZA ABOVE;Lo;0;AL;06C1 0654;;;;N;ARABIC LETTER HAMZAH ON HA GOAL;;;; +06C3;ARABIC LETTER TEH MARBUTA GOAL;Lo;0;AL;;;;;N;ARABIC LETTER TAA MARBUTAH GOAL;;;; +06C4;ARABIC LETTER WAW WITH RING;Lo;0;AL;;;;;N;;;;; +06C5;ARABIC LETTER KIRGHIZ OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH BAR;;;; +06C6;ARABIC LETTER OE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH SMALL V;;;; +06C7;ARABIC LETTER U;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH DAMMAH;;;; +06C8;ARABIC LETTER YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH ALEF ABOVE;;;; +06C9;ARABIC LETTER KIRGHIZ YU;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH INVERTED SMALL V;;;; +06CA;ARABIC LETTER WAW WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +06CB;ARABIC LETTER VE;Lo;0;AL;;;;;N;ARABIC LETTER WAW WITH THREE DOTS ABOVE;;;; +06CC;ARABIC LETTER FARSI YEH;Lo;0;AL;;;;;N;ARABIC LETTER DOTLESS YA;;;; +06CD;ARABIC LETTER YEH WITH TAIL;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TAIL;;;; +06CE;ARABIC LETTER YEH WITH SMALL V;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH SMALL V;;;; +06CF;ARABIC LETTER WAW WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +06D0;ARABIC LETTER E;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH TWO DOTS VERTICAL BELOW;;;; +06D1;ARABIC LETTER YEH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;ARABIC LETTER YA WITH THREE DOTS BELOW;;;; +06D2;ARABIC LETTER YEH BARREE;Lo;0;AL;;;;;N;ARABIC LETTER YA BARREE;;;; +06D3;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE;Lo;0;AL;06D2 0654;;;;N;ARABIC LETTER HAMZAH ON YA BARREE;;;; +06D4;ARABIC FULL STOP;Po;0;AL;;;;;N;ARABIC PERIOD;;;; +06D5;ARABIC LETTER AE;Lo;0;AL;;;;;N;;;;; +06D6;ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; +06D7;ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA;Mn;230;NSM;;;;;N;;;;; +06D8;ARABIC SMALL HIGH MEEM INITIAL FORM;Mn;230;NSM;;;;;N;;;;; +06D9;ARABIC SMALL HIGH LAM ALEF;Mn;230;NSM;;;;;N;;;;; +06DA;ARABIC SMALL HIGH JEEM;Mn;230;NSM;;;;;N;;;;; +06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; +06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; +06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; +06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;; +06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; +06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; +06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; +06E2;ARABIC SMALL HIGH MEEM ISOLATED FORM;Mn;230;NSM;;;;;N;;;;; +06E3;ARABIC SMALL LOW SEEN;Mn;220;NSM;;;;;N;;;;; +06E4;ARABIC SMALL HIGH MADDA;Mn;230;NSM;;;;;N;;;;; +06E5;ARABIC SMALL WAW;Lm;0;AL;;;;;N;;;;; +06E6;ARABIC SMALL YEH;Lm;0;AL;;;;;N;;;;; +06E7;ARABIC SMALL HIGH YEH;Mn;230;NSM;;;;;N;;;;; +06E8;ARABIC SMALL HIGH NOON;Mn;230;NSM;;;;;N;;;;; +06E9;ARABIC PLACE OF SAJDAH;So;0;ON;;;;;N;;;;; +06EA;ARABIC EMPTY CENTRE LOW STOP;Mn;220;NSM;;;;;N;;;;; +06EB;ARABIC EMPTY CENTRE HIGH STOP;Mn;230;NSM;;;;;N;;;;; +06EC;ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE;Mn;230;NSM;;;;;N;;;;; +06ED;ARABIC SMALL LOW MEEM;Mn;220;NSM;;;;;N;;;;; +06EE;ARABIC LETTER DAL WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +06EF;ARABIC LETTER REH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +06F0;EXTENDED ARABIC-INDIC DIGIT ZERO;Nd;0;EN;;0;0;0;N;EASTERN ARABIC-INDIC DIGIT ZERO;;;; +06F1;EXTENDED ARABIC-INDIC DIGIT ONE;Nd;0;EN;;1;1;1;N;EASTERN ARABIC-INDIC DIGIT ONE;;;; +06F2;EXTENDED ARABIC-INDIC DIGIT TWO;Nd;0;EN;;2;2;2;N;EASTERN ARABIC-INDIC DIGIT TWO;;;; +06F3;EXTENDED ARABIC-INDIC DIGIT THREE;Nd;0;EN;;3;3;3;N;EASTERN ARABIC-INDIC DIGIT THREE;;;; +06F4;EXTENDED ARABIC-INDIC DIGIT FOUR;Nd;0;EN;;4;4;4;N;EASTERN ARABIC-INDIC DIGIT FOUR;;;; +06F5;EXTENDED ARABIC-INDIC DIGIT FIVE;Nd;0;EN;;5;5;5;N;EASTERN ARABIC-INDIC DIGIT FIVE;;;; +06F6;EXTENDED ARABIC-INDIC DIGIT SIX;Nd;0;EN;;6;6;6;N;EASTERN ARABIC-INDIC DIGIT SIX;;;; +06F7;EXTENDED ARABIC-INDIC DIGIT SEVEN;Nd;0;EN;;7;7;7;N;EASTERN ARABIC-INDIC DIGIT SEVEN;;;; +06F8;EXTENDED ARABIC-INDIC DIGIT EIGHT;Nd;0;EN;;8;8;8;N;EASTERN ARABIC-INDIC DIGIT EIGHT;;;; +06F9;EXTENDED ARABIC-INDIC DIGIT NINE;Nd;0;EN;;9;9;9;N;EASTERN ARABIC-INDIC DIGIT NINE;;;; +06FA;ARABIC LETTER SHEEN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FB;ARABIC LETTER DAD WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FC;ARABIC LETTER GHAIN WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +06FD;ARABIC SIGN SINDHI AMPERSAND;So;0;AL;;;;;N;;;;; +06FE;ARABIC SIGN SINDHI POSTPOSITION MEN;So;0;AL;;;;;N;;;;; +06FF;ARABIC LETTER HEH WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +0700;SYRIAC END OF PARAGRAPH;Po;0;AL;;;;;N;;;;; +0701;SYRIAC SUPRALINEAR FULL STOP;Po;0;AL;;;;;N;;;;; +0702;SYRIAC SUBLINEAR FULL STOP;Po;0;AL;;;;;N;;;;; +0703;SYRIAC SUPRALINEAR COLON;Po;0;AL;;;;;N;;;;; +0704;SYRIAC SUBLINEAR COLON;Po;0;AL;;;;;N;;;;; +0705;SYRIAC HORIZONTAL COLON;Po;0;AL;;;;;N;;;;; +0706;SYRIAC COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; +0707;SYRIAC COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; +0708;SYRIAC SUPRALINEAR COLON SKEWED LEFT;Po;0;AL;;;;;N;;;;; +0709;SYRIAC SUBLINEAR COLON SKEWED RIGHT;Po;0;AL;;;;;N;;;;; +070A;SYRIAC CONTRACTION;Po;0;AL;;;;;N;;;;; +070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; +070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; +070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; +070F;SYRIAC ABBREVIATION MARK;Cf;0;AL;;;;;N;;;;; +0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; +0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; +0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; +0713;SYRIAC LETTER GAMAL;Lo;0;AL;;;;;N;;;;; +0714;SYRIAC LETTER GAMAL GARSHUNI;Lo;0;AL;;;;;N;;;;; +0715;SYRIAC LETTER DALATH;Lo;0;AL;;;;;N;;;;; +0716;SYRIAC LETTER DOTLESS DALATH RISH;Lo;0;AL;;;;;N;;;;; +0717;SYRIAC LETTER HE;Lo;0;AL;;;;;N;;;;; +0718;SYRIAC LETTER WAW;Lo;0;AL;;;;;N;;;;; +0719;SYRIAC LETTER ZAIN;Lo;0;AL;;;;;N;;;;; +071A;SYRIAC LETTER HETH;Lo;0;AL;;;;;N;;;;; +071B;SYRIAC LETTER TETH;Lo;0;AL;;;;;N;;;;; +071C;SYRIAC LETTER TETH GARSHUNI;Lo;0;AL;;;;;N;;;;; +071D;SYRIAC LETTER YUDH;Lo;0;AL;;;;;N;;;;; +071E;SYRIAC LETTER YUDH HE;Lo;0;AL;;;;;N;;;;; +071F;SYRIAC LETTER KAPH;Lo;0;AL;;;;;N;;;;; +0720;SYRIAC LETTER LAMADH;Lo;0;AL;;;;;N;;;;; +0721;SYRIAC LETTER MIM;Lo;0;AL;;;;;N;;;;; +0722;SYRIAC LETTER NUN;Lo;0;AL;;;;;N;;;;; +0723;SYRIAC LETTER SEMKATH;Lo;0;AL;;;;;N;;;;; +0724;SYRIAC LETTER FINAL SEMKATH;Lo;0;AL;;;;;N;;;;; +0725;SYRIAC LETTER E;Lo;0;AL;;;;;N;;;;; +0726;SYRIAC LETTER PE;Lo;0;AL;;;;;N;;;;; +0727;SYRIAC LETTER REVERSED PE;Lo;0;AL;;;;;N;;;;; +0728;SYRIAC LETTER SADHE;Lo;0;AL;;;;;N;;;;; +0729;SYRIAC LETTER QAPH;Lo;0;AL;;;;;N;;;;; +072A;SYRIAC LETTER RISH;Lo;0;AL;;;;;N;;;;; +072B;SYRIAC LETTER SHIN;Lo;0;AL;;;;;N;;;;; +072C;SYRIAC LETTER TAW;Lo;0;AL;;;;;N;;;;; +072D;SYRIAC LETTER PERSIAN BHETH;Lo;0;AL;;;;;N;;;;; +072E;SYRIAC LETTER PERSIAN GHAMAL;Lo;0;AL;;;;;N;;;;; +072F;SYRIAC LETTER PERSIAN DHALATH;Lo;0;AL;;;;;N;;;;; +0730;SYRIAC PTHAHA ABOVE;Mn;230;NSM;;;;;N;;;;; +0731;SYRIAC PTHAHA BELOW;Mn;220;NSM;;;;;N;;;;; +0732;SYRIAC PTHAHA DOTTED;Mn;230;NSM;;;;;N;;;;; +0733;SYRIAC ZQAPHA ABOVE;Mn;230;NSM;;;;;N;;;;; +0734;SYRIAC ZQAPHA BELOW;Mn;220;NSM;;;;;N;;;;; +0735;SYRIAC ZQAPHA DOTTED;Mn;230;NSM;;;;;N;;;;; +0736;SYRIAC RBASA ABOVE;Mn;230;NSM;;;;;N;;;;; +0737;SYRIAC RBASA BELOW;Mn;220;NSM;;;;;N;;;;; +0738;SYRIAC DOTTED ZLAMA HORIZONTAL;Mn;220;NSM;;;;;N;;;;; +0739;SYRIAC DOTTED ZLAMA ANGULAR;Mn;220;NSM;;;;;N;;;;; +073A;SYRIAC HBASA ABOVE;Mn;230;NSM;;;;;N;;;;; +073B;SYRIAC HBASA BELOW;Mn;220;NSM;;;;;N;;;;; +073C;SYRIAC HBASA-ESASA DOTTED;Mn;220;NSM;;;;;N;;;;; +073D;SYRIAC ESASA ABOVE;Mn;230;NSM;;;;;N;;;;; +073E;SYRIAC ESASA BELOW;Mn;220;NSM;;;;;N;;;;; +073F;SYRIAC RWAHA;Mn;230;NSM;;;;;N;;;;; +0740;SYRIAC FEMININE DOT;Mn;230;NSM;;;;;N;;;;; +0741;SYRIAC QUSHSHAYA;Mn;230;NSM;;;;;N;;;;; +0742;SYRIAC RUKKAKHA;Mn;220;NSM;;;;;N;;;;; +0743;SYRIAC TWO VERTICAL DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +0744;SYRIAC TWO VERTICAL DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +0745;SYRIAC THREE DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +0746;SYRIAC THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +0747;SYRIAC OBLIQUE LINE ABOVE;Mn;230;NSM;;;;;N;;;;; +0748;SYRIAC OBLIQUE LINE BELOW;Mn;220;NSM;;;;;N;;;;; +0749;SYRIAC MUSIC;Mn;230;NSM;;;;;N;;;;; +074A;SYRIAC BARREKH;Mn;230;NSM;;;;;N;;;;; +074D;SYRIAC LETTER SOGDIAN ZHAIN;Lo;0;AL;;;;;N;;;;; +074E;SYRIAC LETTER SOGDIAN KHAPH;Lo;0;AL;;;;;N;;;;; +074F;SYRIAC LETTER SOGDIAN FE;Lo;0;AL;;;;;N;;;;; +0750;ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW;Lo;0;AL;;;;;N;;;;; +0751;ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0752;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0753;ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0754;ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0755;ARABIC LETTER BEH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +0756;ARABIC LETTER BEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +0757;ARABIC LETTER HAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0758;ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0759;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH;Lo;0;AL;;;;;N;;;;; +075A;ARABIC LETTER DAL WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +075B;ARABIC LETTER REH WITH STROKE;Lo;0;AL;;;;;N;;;;; +075C;ARABIC LETTER SEEN WITH FOUR DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +075D;ARABIC LETTER AIN WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +075E;ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE;Lo;0;AL;;;;;N;;;;; +075F;ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +0760;ARABIC LETTER FEH WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0761;ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0762;ARABIC LETTER KEHEH WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0763;ARABIC LETTER KEHEH WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0764;ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW;Lo;0;AL;;;;;N;;;;; +0765;ARABIC LETTER MEEM WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0766;ARABIC LETTER MEEM WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +0767;ARABIC LETTER NOON WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0768;ARABIC LETTER NOON WITH SMALL TAH;Lo;0;AL;;;;;N;;;;; +0769;ARABIC LETTER NOON WITH SMALL V;Lo;0;AL;;;;;N;;;;; +076A;ARABIC LETTER LAM WITH BAR;Lo;0;AL;;;;;N;;;;; +076B;ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +076C;ARABIC LETTER REH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +076D;ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE;Lo;0;AL;;;;;N;;;;; +076E;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW;Lo;0;AL;;;;;N;;;;; +076F;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0770;ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0771;ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS;Lo;0;AL;;;;;N;;;;; +0772;ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; +0773;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0774;ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +0775;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0776;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +0777;ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; +0778;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +0779;ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +077A;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE;Lo;0;AL;;;;;N;;;;; +077B;ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE;Lo;0;AL;;;;;N;;;;; +077C;ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW;Lo;0;AL;;;;;N;;;;; +077D;ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE;Lo;0;AL;;;;;N;;;;; +077E;ARABIC LETTER SEEN WITH INVERTED V;Lo;0;AL;;;;;N;;;;; +077F;ARABIC LETTER KAF WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +0780;THAANA LETTER HAA;Lo;0;AL;;;;;N;;;;; +0781;THAANA LETTER SHAVIYANI;Lo;0;AL;;;;;N;;;;; +0782;THAANA LETTER NOONU;Lo;0;AL;;;;;N;;;;; +0783;THAANA LETTER RAA;Lo;0;AL;;;;;N;;;;; +0784;THAANA LETTER BAA;Lo;0;AL;;;;;N;;;;; +0785;THAANA LETTER LHAVIYANI;Lo;0;AL;;;;;N;;;;; +0786;THAANA LETTER KAAFU;Lo;0;AL;;;;;N;;;;; +0787;THAANA LETTER ALIFU;Lo;0;AL;;;;;N;;;;; +0788;THAANA LETTER VAAVU;Lo;0;AL;;;;;N;;;;; +0789;THAANA LETTER MEEMU;Lo;0;AL;;;;;N;;;;; +078A;THAANA LETTER FAAFU;Lo;0;AL;;;;;N;;;;; +078B;THAANA LETTER DHAALU;Lo;0;AL;;;;;N;;;;; +078C;THAANA LETTER THAA;Lo;0;AL;;;;;N;;;;; +078D;THAANA LETTER LAAMU;Lo;0;AL;;;;;N;;;;; +078E;THAANA LETTER GAAFU;Lo;0;AL;;;;;N;;;;; +078F;THAANA LETTER GNAVIYANI;Lo;0;AL;;;;;N;;;;; +0790;THAANA LETTER SEENU;Lo;0;AL;;;;;N;;;;; +0791;THAANA LETTER DAVIYANI;Lo;0;AL;;;;;N;;;;; +0792;THAANA LETTER ZAVIYANI;Lo;0;AL;;;;;N;;;;; +0793;THAANA LETTER TAVIYANI;Lo;0;AL;;;;;N;;;;; +0794;THAANA LETTER YAA;Lo;0;AL;;;;;N;;;;; +0795;THAANA LETTER PAVIYANI;Lo;0;AL;;;;;N;;;;; +0796;THAANA LETTER JAVIYANI;Lo;0;AL;;;;;N;;;;; +0797;THAANA LETTER CHAVIYANI;Lo;0;AL;;;;;N;;;;; +0798;THAANA LETTER TTAA;Lo;0;AL;;;;;N;;;;; +0799;THAANA LETTER HHAA;Lo;0;AL;;;;;N;;;;; +079A;THAANA LETTER KHAA;Lo;0;AL;;;;;N;;;;; +079B;THAANA LETTER THAALU;Lo;0;AL;;;;;N;;;;; +079C;THAANA LETTER ZAA;Lo;0;AL;;;;;N;;;;; +079D;THAANA LETTER SHEENU;Lo;0;AL;;;;;N;;;;; +079E;THAANA LETTER SAADHU;Lo;0;AL;;;;;N;;;;; +079F;THAANA LETTER DAADHU;Lo;0;AL;;;;;N;;;;; +07A0;THAANA LETTER TO;Lo;0;AL;;;;;N;;;;; +07A1;THAANA LETTER ZO;Lo;0;AL;;;;;N;;;;; +07A2;THAANA LETTER AINU;Lo;0;AL;;;;;N;;;;; +07A3;THAANA LETTER GHAINU;Lo;0;AL;;;;;N;;;;; +07A4;THAANA LETTER QAAFU;Lo;0;AL;;;;;N;;;;; +07A5;THAANA LETTER WAAVU;Lo;0;AL;;;;;N;;;;; +07A6;THAANA ABAFILI;Mn;0;NSM;;;;;N;;;;; +07A7;THAANA AABAAFILI;Mn;0;NSM;;;;;N;;;;; +07A8;THAANA IBIFILI;Mn;0;NSM;;;;;N;;;;; +07A9;THAANA EEBEEFILI;Mn;0;NSM;;;;;N;;;;; +07AA;THAANA UBUFILI;Mn;0;NSM;;;;;N;;;;; +07AB;THAANA OOBOOFILI;Mn;0;NSM;;;;;N;;;;; +07AC;THAANA EBEFILI;Mn;0;NSM;;;;;N;;;;; +07AD;THAANA EYBEYFILI;Mn;0;NSM;;;;;N;;;;; +07AE;THAANA OBOFILI;Mn;0;NSM;;;;;N;;;;; +07AF;THAANA OABOAFILI;Mn;0;NSM;;;;;N;;;;; +07B0;THAANA SUKUN;Mn;0;NSM;;;;;N;;;;; +07B1;THAANA LETTER NAA;Lo;0;AL;;;;;N;;;;; +07C0;NKO DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; +07C1;NKO DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; +07C2;NKO DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; +07C3;NKO DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; +07C4;NKO DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; +07C5;NKO DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; +07C6;NKO DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; +07C7;NKO DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; +07C8;NKO DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; +07C9;NKO DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; +07CA;NKO LETTER A;Lo;0;R;;;;;N;;;;; +07CB;NKO LETTER EE;Lo;0;R;;;;;N;;;;; +07CC;NKO LETTER I;Lo;0;R;;;;;N;;;;; +07CD;NKO LETTER E;Lo;0;R;;;;;N;;;;; +07CE;NKO LETTER U;Lo;0;R;;;;;N;;;;; +07CF;NKO LETTER OO;Lo;0;R;;;;;N;;;;; +07D0;NKO LETTER O;Lo;0;R;;;;;N;;;;; +07D1;NKO LETTER DAGBASINNA;Lo;0;R;;;;;N;;;;; +07D2;NKO LETTER N;Lo;0;R;;;;;N;;;;; +07D3;NKO LETTER BA;Lo;0;R;;;;;N;;;;; +07D4;NKO LETTER PA;Lo;0;R;;;;;N;;;;; +07D5;NKO LETTER TA;Lo;0;R;;;;;N;;;;; +07D6;NKO LETTER JA;Lo;0;R;;;;;N;;;;; +07D7;NKO LETTER CHA;Lo;0;R;;;;;N;;;;; +07D8;NKO LETTER DA;Lo;0;R;;;;;N;;;;; +07D9;NKO LETTER RA;Lo;0;R;;;;;N;;;;; +07DA;NKO LETTER RRA;Lo;0;R;;;;;N;;;;; +07DB;NKO LETTER SA;Lo;0;R;;;;;N;;;;; +07DC;NKO LETTER GBA;Lo;0;R;;;;;N;;;;; +07DD;NKO LETTER FA;Lo;0;R;;;;;N;;;;; +07DE;NKO LETTER KA;Lo;0;R;;;;;N;;;;; +07DF;NKO LETTER LA;Lo;0;R;;;;;N;;;;; +07E0;NKO LETTER NA WOLOSO;Lo;0;R;;;;;N;;;;; +07E1;NKO LETTER MA;Lo;0;R;;;;;N;;;;; +07E2;NKO LETTER NYA;Lo;0;R;;;;;N;;;;; +07E3;NKO LETTER NA;Lo;0;R;;;;;N;;;;; +07E4;NKO LETTER HA;Lo;0;R;;;;;N;;;;; +07E5;NKO LETTER WA;Lo;0;R;;;;;N;;;;; +07E6;NKO LETTER YA;Lo;0;R;;;;;N;;;;; +07E7;NKO LETTER NYA WOLOSO;Lo;0;R;;;;;N;;;;; +07E8;NKO LETTER JONA JA;Lo;0;R;;;;;N;;;;; +07E9;NKO LETTER JONA CHA;Lo;0;R;;;;;N;;;;; +07EA;NKO LETTER JONA RA;Lo;0;R;;;;;N;;;;; +07EB;NKO COMBINING SHORT HIGH TONE;Mn;230;NSM;;;;;N;;;;; +07EC;NKO COMBINING SHORT LOW TONE;Mn;230;NSM;;;;;N;;;;; +07ED;NKO COMBINING SHORT RISING TONE;Mn;230;NSM;;;;;N;;;;; +07EE;NKO COMBINING LONG DESCENDING TONE;Mn;230;NSM;;;;;N;;;;; +07EF;NKO COMBINING LONG HIGH TONE;Mn;230;NSM;;;;;N;;;;; +07F0;NKO COMBINING LONG LOW TONE;Mn;230;NSM;;;;;N;;;;; +07F1;NKO COMBINING LONG RISING TONE;Mn;230;NSM;;;;;N;;;;; +07F2;NKO COMBINING NASALIZATION MARK;Mn;220;NSM;;;;;N;;;;; +07F3;NKO COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +07F4;NKO HIGH TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; +07F5;NKO LOW TONE APOSTROPHE;Lm;0;R;;;;;N;;;;; +07F6;NKO SYMBOL OO DENNEN;So;0;ON;;;;;N;;;;; +07F7;NKO SYMBOL GBAKURUNEN;Po;0;ON;;;;;N;;;;; +07F8;NKO COMMA;Po;0;ON;;;;;N;;;;; +07F9;NKO EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +07FA;NKO LAJANYALAN;Lm;0;R;;;;;N;;;;; +07FD;NKO DANTAYALAN;Mn;220;NSM;;;;;N;;;;; +07FE;NKO DOROME SIGN;Sc;0;R;;;;;N;;;;; +07FF;NKO TAMAN SIGN;Sc;0;R;;;;;N;;;;; +0800;SAMARITAN LETTER ALAF;Lo;0;R;;;;;N;;;;; +0801;SAMARITAN LETTER BIT;Lo;0;R;;;;;N;;;;; +0802;SAMARITAN LETTER GAMAN;Lo;0;R;;;;;N;;;;; +0803;SAMARITAN LETTER DALAT;Lo;0;R;;;;;N;;;;; +0804;SAMARITAN LETTER IY;Lo;0;R;;;;;N;;;;; +0805;SAMARITAN LETTER BAA;Lo;0;R;;;;;N;;;;; +0806;SAMARITAN LETTER ZEN;Lo;0;R;;;;;N;;;;; +0807;SAMARITAN LETTER IT;Lo;0;R;;;;;N;;;;; +0808;SAMARITAN LETTER TIT;Lo;0;R;;;;;N;;;;; +0809;SAMARITAN LETTER YUT;Lo;0;R;;;;;N;;;;; +080A;SAMARITAN LETTER KAAF;Lo;0;R;;;;;N;;;;; +080B;SAMARITAN LETTER LABAT;Lo;0;R;;;;;N;;;;; +080C;SAMARITAN LETTER MIM;Lo;0;R;;;;;N;;;;; +080D;SAMARITAN LETTER NUN;Lo;0;R;;;;;N;;;;; +080E;SAMARITAN LETTER SINGAAT;Lo;0;R;;;;;N;;;;; +080F;SAMARITAN LETTER IN;Lo;0;R;;;;;N;;;;; +0810;SAMARITAN LETTER FI;Lo;0;R;;;;;N;;;;; +0811;SAMARITAN LETTER TSAADIY;Lo;0;R;;;;;N;;;;; +0812;SAMARITAN LETTER QUF;Lo;0;R;;;;;N;;;;; +0813;SAMARITAN LETTER RISH;Lo;0;R;;;;;N;;;;; +0814;SAMARITAN LETTER SHAN;Lo;0;R;;;;;N;;;;; +0815;SAMARITAN LETTER TAAF;Lo;0;R;;;;;N;;;;; +0816;SAMARITAN MARK IN;Mn;230;NSM;;;;;N;;;;; +0817;SAMARITAN MARK IN-ALAF;Mn;230;NSM;;;;;N;;;;; +0818;SAMARITAN MARK OCCLUSION;Mn;230;NSM;;;;;N;;;;; +0819;SAMARITAN MARK DAGESH;Mn;230;NSM;;;;;N;;;;; +081A;SAMARITAN MODIFIER LETTER EPENTHETIC YUT;Lm;0;R;;;;;N;;;;; +081B;SAMARITAN MARK EPENTHETIC YUT;Mn;230;NSM;;;;;N;;;;; +081C;SAMARITAN VOWEL SIGN LONG E;Mn;230;NSM;;;;;N;;;;; +081D;SAMARITAN VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; +081E;SAMARITAN VOWEL SIGN OVERLONG AA;Mn;230;NSM;;;;;N;;;;; +081F;SAMARITAN VOWEL SIGN LONG AA;Mn;230;NSM;;;;;N;;;;; +0820;SAMARITAN VOWEL SIGN AA;Mn;230;NSM;;;;;N;;;;; +0821;SAMARITAN VOWEL SIGN OVERLONG A;Mn;230;NSM;;;;;N;;;;; +0822;SAMARITAN VOWEL SIGN LONG A;Mn;230;NSM;;;;;N;;;;; +0823;SAMARITAN VOWEL SIGN A;Mn;230;NSM;;;;;N;;;;; +0824;SAMARITAN MODIFIER LETTER SHORT A;Lm;0;R;;;;;N;;;;; +0825;SAMARITAN VOWEL SIGN SHORT A;Mn;230;NSM;;;;;N;;;;; +0826;SAMARITAN VOWEL SIGN LONG U;Mn;230;NSM;;;;;N;;;;; +0827;SAMARITAN VOWEL SIGN U;Mn;230;NSM;;;;;N;;;;; +0828;SAMARITAN MODIFIER LETTER I;Lm;0;R;;;;;N;;;;; +0829;SAMARITAN VOWEL SIGN LONG I;Mn;230;NSM;;;;;N;;;;; +082A;SAMARITAN VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; +082B;SAMARITAN VOWEL SIGN O;Mn;230;NSM;;;;;N;;;;; +082C;SAMARITAN VOWEL SIGN SUKUN;Mn;230;NSM;;;;;N;;;;; +082D;SAMARITAN MARK NEQUDAA;Mn;230;NSM;;;;;N;;;;; +0830;SAMARITAN PUNCTUATION NEQUDAA;Po;0;R;;;;;N;;;;; +0831;SAMARITAN PUNCTUATION AFSAAQ;Po;0;R;;;;;N;;;;; +0832;SAMARITAN PUNCTUATION ANGED;Po;0;R;;;;;N;;;;; +0833;SAMARITAN PUNCTUATION BAU;Po;0;R;;;;;N;;;;; +0834;SAMARITAN PUNCTUATION ATMAAU;Po;0;R;;;;;N;;;;; +0835;SAMARITAN PUNCTUATION SHIYYAALAA;Po;0;R;;;;;N;;;;; +0836;SAMARITAN ABBREVIATION MARK;Po;0;R;;;;;N;;;;; +0837;SAMARITAN PUNCTUATION MELODIC QITSA;Po;0;R;;;;;N;;;;; +0838;SAMARITAN PUNCTUATION ZIQAA;Po;0;R;;;;;N;;;;; +0839;SAMARITAN PUNCTUATION QITSA;Po;0;R;;;;;N;;;;; +083A;SAMARITAN PUNCTUATION ZAEF;Po;0;R;;;;;N;;;;; +083B;SAMARITAN PUNCTUATION TURU;Po;0;R;;;;;N;;;;; +083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; +083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; +083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; +0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;; +0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;; +0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;; +0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;; +0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;; +0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;; +0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;; +0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;; +0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;; +0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;; +084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;; +084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;; +084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;; +084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;; +084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;; +084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;; +0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;; +0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;; +0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;; +0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;; +0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;; +0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;; +0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;; +0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;; +0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;; +0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;; +085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; +085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; +085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; +0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;; +0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;; +0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;; +0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;; +0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;; +0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;; +0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;; +0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;; +0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;; +0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;; +086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;; +0870;ARABIC LETTER ALEF WITH ATTACHED FATHA;Lo;0;AL;;;;;N;;;;; +0871;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA;Lo;0;AL;;;;;N;;;;; +0872;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;; +0873;ARABIC LETTER ALEF WITH LEFT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;; +0874;ARABIC LETTER ALEF WITH ATTACHED KASRA;Lo;0;AL;;;;;N;;;;; +0875;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA;Lo;0;AL;;;;;N;;;;; +0876;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +0877;ARABIC LETTER ALEF WITH ATTACHED RIGHT ROUND DOT;Lo;0;AL;;;;;N;;;;; +0878;ARABIC LETTER ALEF WITH ATTACHED LEFT ROUND DOT;Lo;0;AL;;;;;N;;;;; +0879;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT BELOW;Lo;0;AL;;;;;N;;;;; +087A;ARABIC LETTER ALEF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087B;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087C;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087D;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +087E;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND LEFT RING;Lo;0;AL;;;;;N;;;;; +087F;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND LEFT RING;Lo;0;AL;;;;;N;;;;; +0880;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND LEFT RING;Lo;0;AL;;;;;N;;;;; +0881;ARABIC LETTER ALEF WITH ATTACHED RIGHT HAMZA;Lo;0;AL;;;;;N;;;;; +0882;ARABIC LETTER ALEF WITH ATTACHED LEFT HAMZA;Lo;0;AL;;;;;N;;;;; +0883;ARABIC TATWEEL WITH OVERSTRUCK HAMZA;Lo;0;AL;;;;;N;;;;; +0884;ARABIC TATWEEL WITH OVERSTRUCK WAW;Lo;0;AL;;;;;N;;;;; +0885;ARABIC TATWEEL WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;; +0886;ARABIC LETTER THIN YEH;Lo;0;AL;;;;;N;;;;; +0887;ARABIC BASELINE ROUND DOT;Lo;0;AL;;;;;N;;;;; +0888;ARABIC RAISED ROUND DOT;Sk;0;AL;;;;;N;;;;; +0889;ARABIC LETTER NOON WITH INVERTED SMALL V;Lo;0;AL;;;;;N;;;;; +088A;ARABIC LETTER HAH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +088B;ARABIC LETTER TAH WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +088C;ARABIC LETTER TAH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +088D;ARABIC LETTER KEHEH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;; +088E;ARABIC VERTICAL TAIL;Lo;0;AL;;;;;N;;;;; +088F;ARABIC LETTER NOON WITH RING ABOVE;Lo;0;AL;;;;;N;;;;; +0890;ARABIC POUND MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0891;ARABIC PIASTRE MARK ABOVE;Cf;0;AN;;;;;N;;;;; +0897;ARABIC PEPET;Mn;230;NSM;;;;;N;;;;; +0898;ARABIC SMALL HIGH WORD AL-JUZ;Mn;230;NSM;;;;;N;;;;; +0899;ARABIC SMALL LOW WORD ISHMAAM;Mn;220;NSM;;;;;N;;;;; +089A;ARABIC SMALL LOW WORD IMAALA;Mn;220;NSM;;;;;N;;;;; +089B;ARABIC SMALL LOW WORD TASHEEL;Mn;220;NSM;;;;;N;;;;; +089C;ARABIC MADDA WAAJIB;Mn;230;NSM;;;;;N;;;;; +089D;ARABIC SUPERSCRIPT ALEF MOKHASSAS;Mn;230;NSM;;;;;N;;;;; +089E;ARABIC DOUBLED MADDA;Mn;230;NSM;;;;;N;;;;; +089F;ARABIC HALF MADDA OVER MADDA;Mn;230;NSM;;;;;N;;;;; +08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;; +08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A3;ARABIC LETTER TAH WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A4;ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A5;ARABIC LETTER QAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08A6;ARABIC LETTER LAM WITH DOUBLE BAR;Lo;0;AL;;;;;N;;;;; +08A7;ARABIC LETTER MEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08A8;ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE;Lo;0;AL;;;;;N;;;;; +08A9;ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE;Lo;0;AL;;;;;N;;;;; +08AA;ARABIC LETTER REH WITH LOOP;Lo;0;AL;;;;;N;;;;; +08AB;ARABIC LETTER WAW WITH DOT WITHIN;Lo;0;AL;;;;;N;;;;; +08AC;ARABIC LETTER ROHINGYA YEH;Lo;0;AL;;;;;N;;;;; +08AD;ARABIC LETTER LOW ALEF;Lo;0;AL;;;;;N;;;;; +08AE;ARABIC LETTER DAL WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08AF;ARABIC LETTER SAD WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08B0;ARABIC LETTER GAF WITH INVERTED STROKE;Lo;0;AL;;;;;N;;;;; +08B1;ARABIC LETTER STRAIGHT WAW;Lo;0;AL;;;;;N;;;;; +08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;; +08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;; +08B5;ARABIC LETTER QAF WITH DOT BELOW AND NO DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;; +08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;; +08B9;ARABIC LETTER REH WITH SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BA;ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE;Lo;0;AL;;;;;N;;;;; +08BB;ARABIC LETTER AFRICAN FEH;Lo;0;AL;;;;;N;;;;; +08BC;ARABIC LETTER AFRICAN QAF;Lo;0;AL;;;;;N;;;;; +08BD;ARABIC LETTER AFRICAN NOON;Lo;0;AL;;;;;N;;;;; +08BE;ARABIC LETTER PEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +08BF;ARABIC LETTER TEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +08C0;ARABIC LETTER TTEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +08C1;ARABIC LETTER TCHEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +08C2;ARABIC LETTER KEHEH WITH SMALL V;Lo;0;AL;;;;;N;;;;; +08C3;ARABIC LETTER GHAIN WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08C4;ARABIC LETTER AFRICAN QAF WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08C5;ARABIC LETTER JEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;; +08C6;ARABIC LETTER JEEM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;; +08C7;ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;; +08C8;ARABIC LETTER GRAF;Lo;0;AL;;;;;N;;;;; +08C9;ARABIC SMALL FARSI YEH;Lm;0;AL;;;;;N;;;;; +08CA;ARABIC SMALL HIGH FARSI YEH;Mn;230;NSM;;;;;N;;;;; +08CB;ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW;Mn;230;NSM;;;;;N;;;;; +08CC;ARABIC SMALL HIGH WORD SAH;Mn;230;NSM;;;;;N;;;;; +08CD;ARABIC SMALL HIGH ZAH;Mn;230;NSM;;;;;N;;;;; +08CE;ARABIC LARGE ROUND DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08CF;ARABIC LARGE ROUND DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08D0;ARABIC SUKUN BELOW;Mn;220;NSM;;;;;N;;;;; +08D1;ARABIC LARGE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;; +08D2;ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;; +08D3;ARABIC SMALL LOW WAW;Mn;220;NSM;;;;;N;;;;; +08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;; +08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;; +08D6;ARABIC SMALL HIGH AIN;Mn;230;NSM;;;;;N;;;;; +08D7;ARABIC SMALL HIGH QAF;Mn;230;NSM;;;;;N;;;;; +08D8;ARABIC SMALL HIGH NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08D9;ARABIC SMALL LOW NOON WITH KASRA;Mn;230;NSM;;;;;N;;;;; +08DA;ARABIC SMALL HIGH WORD ATH-THALATHA;Mn;230;NSM;;;;;N;;;;; +08DB;ARABIC SMALL HIGH WORD AS-SAJDA;Mn;230;NSM;;;;;N;;;;; +08DC;ARABIC SMALL HIGH WORD AN-NISF;Mn;230;NSM;;;;;N;;;;; +08DD;ARABIC SMALL HIGH WORD SAKTA;Mn;230;NSM;;;;;N;;;;; +08DE;ARABIC SMALL HIGH WORD QIF;Mn;230;NSM;;;;;N;;;;; +08DF;ARABIC SMALL HIGH WORD WAQFA;Mn;230;NSM;;;;;N;;;;; +08E0;ARABIC SMALL HIGH FOOTNOTE MARKER;Mn;230;NSM;;;;;N;;;;; +08E1;ARABIC SMALL HIGH SIGN SAFHA;Mn;230;NSM;;;;;N;;;;; +08E2;ARABIC DISPUTED END OF AYAH;Cf;0;AN;;;;;N;;;;; +08E3;ARABIC TURNED DAMMA BELOW;Mn;220;NSM;;;;;N;;;;; +08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;; +08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;; +08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;; +08E7;ARABIC CURLY FATHATAN;Mn;230;NSM;;;;;N;;;;; +08E8;ARABIC CURLY DAMMATAN;Mn;230;NSM;;;;;N;;;;; +08E9;ARABIC CURLY KASRATAN;Mn;220;NSM;;;;;N;;;;; +08EA;ARABIC TONE ONE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08EB;ARABIC TONE TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +08EC;ARABIC TONE LOOP ABOVE;Mn;230;NSM;;;;;N;;;;; +08ED;ARABIC TONE ONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08EE;ARABIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +08EF;ARABIC TONE LOOP BELOW;Mn;220;NSM;;;;;N;;;;; +08F0;ARABIC OPEN FATHATAN;Mn;27;NSM;;;;;N;;;;; +08F1;ARABIC OPEN DAMMATAN;Mn;28;NSM;;;;;N;;;;; +08F2;ARABIC OPEN KASRATAN;Mn;29;NSM;;;;;N;;;;; +08F3;ARABIC SMALL HIGH WAW;Mn;230;NSM;;;;;N;;;;; +08F4;ARABIC FATHA WITH RING;Mn;230;NSM;;;;;N;;;;; +08F5;ARABIC FATHA WITH DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +08F6;ARABIC KASRA WITH DOT BELOW;Mn;220;NSM;;;;;N;;;;; +08F7;ARABIC LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08F8;ARABIC RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08F9;ARABIC LEFT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +08FA;ARABIC RIGHT ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +08FB;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +08FC;ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FD;ARABIC RIGHT ARROWHEAD ABOVE WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FE;ARABIC DAMMA WITH DOT;Mn;230;NSM;;;;;N;;;;; +08FF;ARABIC MARK SIDEWAYS NOON GHUNNA;Mn;230;NSM;;;;;N;;;;; +0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0903;DEVANAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0904;DEVANAGARI LETTER SHORT A;Lo;0;L;;;;;N;;;;; +0905;DEVANAGARI LETTER A;Lo;0;L;;;;;N;;;;; +0906;DEVANAGARI LETTER AA;Lo;0;L;;;;;N;;;;; +0907;DEVANAGARI LETTER I;Lo;0;L;;;;;N;;;;; +0908;DEVANAGARI LETTER II;Lo;0;L;;;;;N;;;;; +0909;DEVANAGARI LETTER U;Lo;0;L;;;;;N;;;;; +090A;DEVANAGARI LETTER UU;Lo;0;L;;;;;N;;;;; +090B;DEVANAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +090C;DEVANAGARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +090D;DEVANAGARI LETTER CANDRA E;Lo;0;L;;;;;N;;;;; +090E;DEVANAGARI LETTER SHORT E;Lo;0;L;;;;;N;;;;; +090F;DEVANAGARI LETTER E;Lo;0;L;;;;;N;;;;; +0910;DEVANAGARI LETTER AI;Lo;0;L;;;;;N;;;;; +0911;DEVANAGARI LETTER CANDRA O;Lo;0;L;;;;;N;;;;; +0912;DEVANAGARI LETTER SHORT O;Lo;0;L;;;;;N;;;;; +0913;DEVANAGARI LETTER O;Lo;0;L;;;;;N;;;;; +0914;DEVANAGARI LETTER AU;Lo;0;L;;;;;N;;;;; +0915;DEVANAGARI LETTER KA;Lo;0;L;;;;;N;;;;; +0916;DEVANAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; +0917;DEVANAGARI LETTER GA;Lo;0;L;;;;;N;;;;; +0918;DEVANAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; +0919;DEVANAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; +091A;DEVANAGARI LETTER CA;Lo;0;L;;;;;N;;;;; +091B;DEVANAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; +091C;DEVANAGARI LETTER JA;Lo;0;L;;;;;N;;;;; +091D;DEVANAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; +091E;DEVANAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; +091F;DEVANAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; +0920;DEVANAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0921;DEVANAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; +0922;DEVANAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0923;DEVANAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; +0924;DEVANAGARI LETTER TA;Lo;0;L;;;;;N;;;;; +0925;DEVANAGARI LETTER THA;Lo;0;L;;;;;N;;;;; +0926;DEVANAGARI LETTER DA;Lo;0;L;;;;;N;;;;; +0927;DEVANAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; +0928;DEVANAGARI LETTER NA;Lo;0;L;;;;;N;;;;; +0929;DEVANAGARI LETTER NNNA;Lo;0;L;0928 093C;;;;N;;;;; +092A;DEVANAGARI LETTER PA;Lo;0;L;;;;;N;;;;; +092B;DEVANAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; +092C;DEVANAGARI LETTER BA;Lo;0;L;;;;;N;;;;; +092D;DEVANAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; +092E;DEVANAGARI LETTER MA;Lo;0;L;;;;;N;;;;; +092F;DEVANAGARI LETTER YA;Lo;0;L;;;;;N;;;;; +0930;DEVANAGARI LETTER RA;Lo;0;L;;;;;N;;;;; +0931;DEVANAGARI LETTER RRA;Lo;0;L;0930 093C;;;;N;;;;; +0932;DEVANAGARI LETTER LA;Lo;0;L;;;;;N;;;;; +0933;DEVANAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; +0934;DEVANAGARI LETTER LLLA;Lo;0;L;0933 093C;;;;N;;;;; +0935;DEVANAGARI LETTER VA;Lo;0;L;;;;;N;;;;; +0936;DEVANAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; +0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; +0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; +0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; +093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; +093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +093F;DEVANAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0940;DEVANAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0941;DEVANAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0942;DEVANAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0943;DEVANAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0944;DEVANAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0945;DEVANAGARI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; +0946;DEVANAGARI VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; +0947;DEVANAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0948;DEVANAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0949;DEVANAGARI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; +094A;DEVANAGARI VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; +094B;DEVANAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; +094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;; +0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; +0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; +0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; +0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; +0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; +0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; +0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; +0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; +095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; +095B;DEVANAGARI LETTER ZA;Lo;0;L;091C 093C;;;;N;;;;; +095C;DEVANAGARI LETTER DDDHA;Lo;0;L;0921 093C;;;;N;;;;; +095D;DEVANAGARI LETTER RHA;Lo;0;L;0922 093C;;;;N;;;;; +095E;DEVANAGARI LETTER FA;Lo;0;L;092B 093C;;;;N;;;;; +095F;DEVANAGARI LETTER YYA;Lo;0;L;092F 093C;;;;N;;;;; +0960;DEVANAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0961;DEVANAGARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0962;DEVANAGARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0963;DEVANAGARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0964;DEVANAGARI DANDA;Po;0;L;;;;;N;;;;; +0965;DEVANAGARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +0966;DEVANAGARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0967;DEVANAGARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0968;DEVANAGARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0969;DEVANAGARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +096A;DEVANAGARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +096B;DEVANAGARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +096C;DEVANAGARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +096D;DEVANAGARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +096E;DEVANAGARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +096F;DEVANAGARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; +0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; +0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;; +0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;; +0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;; +0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;; +0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;; +0978;DEVANAGARI LETTER MARWARI DDA;Lo;0;L;;;;;N;;;;; +0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; +097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; +097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; +097C;DEVANAGARI LETTER JJA;Lo;0;L;;;;;N;;;;; +097D;DEVANAGARI LETTER GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +097E;DEVANAGARI LETTER DDDA;Lo;0;L;;;;;N;;;;; +097F;DEVANAGARI LETTER BBA;Lo;0;L;;;;;N;;;;; +0980;BENGALI ANJI;Lo;0;L;;;;;N;;;;; +0981;BENGALI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0982;BENGALI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0983;BENGALI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0985;BENGALI LETTER A;Lo;0;L;;;;;N;;;;; +0986;BENGALI LETTER AA;Lo;0;L;;;;;N;;;;; +0987;BENGALI LETTER I;Lo;0;L;;;;;N;;;;; +0988;BENGALI LETTER II;Lo;0;L;;;;;N;;;;; +0989;BENGALI LETTER U;Lo;0;L;;;;;N;;;;; +098A;BENGALI LETTER UU;Lo;0;L;;;;;N;;;;; +098B;BENGALI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +098C;BENGALI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +098F;BENGALI LETTER E;Lo;0;L;;;;;N;;;;; +0990;BENGALI LETTER AI;Lo;0;L;;;;;N;;;;; +0993;BENGALI LETTER O;Lo;0;L;;;;;N;;;;; +0994;BENGALI LETTER AU;Lo;0;L;;;;;N;;;;; +0995;BENGALI LETTER KA;Lo;0;L;;;;;N;;;;; +0996;BENGALI LETTER KHA;Lo;0;L;;;;;N;;;;; +0997;BENGALI LETTER GA;Lo;0;L;;;;;N;;;;; +0998;BENGALI LETTER GHA;Lo;0;L;;;;;N;;;;; +0999;BENGALI LETTER NGA;Lo;0;L;;;;;N;;;;; +099A;BENGALI LETTER CA;Lo;0;L;;;;;N;;;;; +099B;BENGALI LETTER CHA;Lo;0;L;;;;;N;;;;; +099C;BENGALI LETTER JA;Lo;0;L;;;;;N;;;;; +099D;BENGALI LETTER JHA;Lo;0;L;;;;;N;;;;; +099E;BENGALI LETTER NYA;Lo;0;L;;;;;N;;;;; +099F;BENGALI LETTER TTA;Lo;0;L;;;;;N;;;;; +09A0;BENGALI LETTER TTHA;Lo;0;L;;;;;N;;;;; +09A1;BENGALI LETTER DDA;Lo;0;L;;;;;N;;;;; +09A2;BENGALI LETTER DDHA;Lo;0;L;;;;;N;;;;; +09A3;BENGALI LETTER NNA;Lo;0;L;;;;;N;;;;; +09A4;BENGALI LETTER TA;Lo;0;L;;;;;N;;;;; +09A5;BENGALI LETTER THA;Lo;0;L;;;;;N;;;;; +09A6;BENGALI LETTER DA;Lo;0;L;;;;;N;;;;; +09A7;BENGALI LETTER DHA;Lo;0;L;;;;;N;;;;; +09A8;BENGALI LETTER NA;Lo;0;L;;;;;N;;;;; +09AA;BENGALI LETTER PA;Lo;0;L;;;;;N;;;;; +09AB;BENGALI LETTER PHA;Lo;0;L;;;;;N;;;;; +09AC;BENGALI LETTER BA;Lo;0;L;;;;;N;;;;; +09AD;BENGALI LETTER BHA;Lo;0;L;;;;;N;;;;; +09AE;BENGALI LETTER MA;Lo;0;L;;;;;N;;;;; +09AF;BENGALI LETTER YA;Lo;0;L;;;;;N;;;;; +09B0;BENGALI LETTER RA;Lo;0;L;;;;;N;;;;; +09B2;BENGALI LETTER LA;Lo;0;L;;;;;N;;;;; +09B6;BENGALI LETTER SHA;Lo;0;L;;;;;N;;;;; +09B7;BENGALI LETTER SSA;Lo;0;L;;;;;N;;;;; +09B8;BENGALI LETTER SA;Lo;0;L;;;;;N;;;;; +09B9;BENGALI LETTER HA;Lo;0;L;;;;;N;;;;; +09BC;BENGALI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +09BD;BENGALI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +09BE;BENGALI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +09BF;BENGALI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +09C0;BENGALI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +09C1;BENGALI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +09C2;BENGALI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +09C3;BENGALI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +09C4;BENGALI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +09C7;BENGALI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +09C8;BENGALI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +09CB;BENGALI VOWEL SIGN O;Mc;0;L;09C7 09BE;;;;N;;;;; +09CC;BENGALI VOWEL SIGN AU;Mc;0;L;09C7 09D7;;;;N;;;;; +09CD;BENGALI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +09CE;BENGALI LETTER KHANDA TA;Lo;0;L;;;;;N;;;;; +09D7;BENGALI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +09DC;BENGALI LETTER RRA;Lo;0;L;09A1 09BC;;;;N;;;;; +09DD;BENGALI LETTER RHA;Lo;0;L;09A2 09BC;;;;N;;;;; +09DF;BENGALI LETTER YYA;Lo;0;L;09AF 09BC;;;;N;;;;; +09E0;BENGALI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +09E1;BENGALI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +09E2;BENGALI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +09E3;BENGALI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +09E6;BENGALI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +09E7;BENGALI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +09E8;BENGALI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +09E9;BENGALI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +09EA;BENGALI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +09EB;BENGALI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +09EC;BENGALI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +09ED;BENGALI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +09EE;BENGALI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +09EF;BENGALI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +09F0;BENGALI LETTER RA WITH MIDDLE DIAGONAL;Lo;0;L;;;;;N;;;;; +09F1;BENGALI LETTER RA WITH LOWER DIAGONAL;Lo;0;L;;;;;N;BENGALI LETTER VA WITH LOWER DIAGONAL;;;; +09F2;BENGALI RUPEE MARK;Sc;0;ET;;;;;N;;;;; +09F3;BENGALI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +09F4;BENGALI CURRENCY NUMERATOR ONE;No;0;L;;;;1/16;N;;;;; +09F5;BENGALI CURRENCY NUMERATOR TWO;No;0;L;;;;1/8;N;;;;; +09F6;BENGALI CURRENCY NUMERATOR THREE;No;0;L;;;;3/16;N;;;;; +09F7;BENGALI CURRENCY NUMERATOR FOUR;No;0;L;;;;1/4;N;;;;; +09F8;BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR;No;0;L;;;;3/4;N;;;;; +09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;; +09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;; +09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;; +09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +09FE;BENGALI SANDHI MARK;Mn;230;NSM;;;;;N;;;;; +0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;; +0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;; +0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0A05;GURMUKHI LETTER A;Lo;0;L;;;;;N;;;;; +0A06;GURMUKHI LETTER AA;Lo;0;L;;;;;N;;;;; +0A07;GURMUKHI LETTER I;Lo;0;L;;;;;N;;;;; +0A08;GURMUKHI LETTER II;Lo;0;L;;;;;N;;;;; +0A09;GURMUKHI LETTER U;Lo;0;L;;;;;N;;;;; +0A0A;GURMUKHI LETTER UU;Lo;0;L;;;;;N;;;;; +0A0F;GURMUKHI LETTER EE;Lo;0;L;;;;;N;;;;; +0A10;GURMUKHI LETTER AI;Lo;0;L;;;;;N;;;;; +0A13;GURMUKHI LETTER OO;Lo;0;L;;;;;N;;;;; +0A14;GURMUKHI LETTER AU;Lo;0;L;;;;;N;;;;; +0A15;GURMUKHI LETTER KA;Lo;0;L;;;;;N;;;;; +0A16;GURMUKHI LETTER KHA;Lo;0;L;;;;;N;;;;; +0A17;GURMUKHI LETTER GA;Lo;0;L;;;;;N;;;;; +0A18;GURMUKHI LETTER GHA;Lo;0;L;;;;;N;;;;; +0A19;GURMUKHI LETTER NGA;Lo;0;L;;;;;N;;;;; +0A1A;GURMUKHI LETTER CA;Lo;0;L;;;;;N;;;;; +0A1B;GURMUKHI LETTER CHA;Lo;0;L;;;;;N;;;;; +0A1C;GURMUKHI LETTER JA;Lo;0;L;;;;;N;;;;; +0A1D;GURMUKHI LETTER JHA;Lo;0;L;;;;;N;;;;; +0A1E;GURMUKHI LETTER NYA;Lo;0;L;;;;;N;;;;; +0A1F;GURMUKHI LETTER TTA;Lo;0;L;;;;;N;;;;; +0A20;GURMUKHI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0A21;GURMUKHI LETTER DDA;Lo;0;L;;;;;N;;;;; +0A22;GURMUKHI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0A23;GURMUKHI LETTER NNA;Lo;0;L;;;;;N;;;;; +0A24;GURMUKHI LETTER TA;Lo;0;L;;;;;N;;;;; +0A25;GURMUKHI LETTER THA;Lo;0;L;;;;;N;;;;; +0A26;GURMUKHI LETTER DA;Lo;0;L;;;;;N;;;;; +0A27;GURMUKHI LETTER DHA;Lo;0;L;;;;;N;;;;; +0A28;GURMUKHI LETTER NA;Lo;0;L;;;;;N;;;;; +0A2A;GURMUKHI LETTER PA;Lo;0;L;;;;;N;;;;; +0A2B;GURMUKHI LETTER PHA;Lo;0;L;;;;;N;;;;; +0A2C;GURMUKHI LETTER BA;Lo;0;L;;;;;N;;;;; +0A2D;GURMUKHI LETTER BHA;Lo;0;L;;;;;N;;;;; +0A2E;GURMUKHI LETTER MA;Lo;0;L;;;;;N;;;;; +0A2F;GURMUKHI LETTER YA;Lo;0;L;;;;;N;;;;; +0A30;GURMUKHI LETTER RA;Lo;0;L;;;;;N;;;;; +0A32;GURMUKHI LETTER LA;Lo;0;L;;;;;N;;;;; +0A33;GURMUKHI LETTER LLA;Lo;0;L;0A32 0A3C;;;;N;;;;; +0A35;GURMUKHI LETTER VA;Lo;0;L;;;;;N;;;;; +0A36;GURMUKHI LETTER SHA;Lo;0;L;0A38 0A3C;;;;N;;;;; +0A38;GURMUKHI LETTER SA;Lo;0;L;;;;;N;;;;; +0A39;GURMUKHI LETTER HA;Lo;0;L;;;;;N;;;;; +0A3C;GURMUKHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0A3E;GURMUKHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0A3F;GURMUKHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0A40;GURMUKHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0A41;GURMUKHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0A42;GURMUKHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0A47;GURMUKHI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +0A48;GURMUKHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0A4B;GURMUKHI VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; +0A4C;GURMUKHI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0A4D;GURMUKHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0A51;GURMUKHI SIGN UDAAT;Mn;0;NSM;;;;;N;;;;; +0A59;GURMUKHI LETTER KHHA;Lo;0;L;0A16 0A3C;;;;N;;;;; +0A5A;GURMUKHI LETTER GHHA;Lo;0;L;0A17 0A3C;;;;N;;;;; +0A5B;GURMUKHI LETTER ZA;Lo;0;L;0A1C 0A3C;;;;N;;;;; +0A5C;GURMUKHI LETTER RRA;Lo;0;L;;;;;N;;;;; +0A5E;GURMUKHI LETTER FA;Lo;0;L;0A2B 0A3C;;;;N;;;;; +0A66;GURMUKHI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0A67;GURMUKHI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0A68;GURMUKHI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0A69;GURMUKHI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0A6A;GURMUKHI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0A6B;GURMUKHI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0A6C;GURMUKHI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0A6D;GURMUKHI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0A6E;GURMUKHI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0A6F;GURMUKHI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0A70;GURMUKHI TIPPI;Mn;0;NSM;;;;;N;;;;; +0A71;GURMUKHI ADDAK;Mn;0;NSM;;;;;N;;;;; +0A72;GURMUKHI IRI;Lo;0;L;;;;;N;;;;; +0A73;GURMUKHI URA;Lo;0;L;;;;;N;;;;; +0A74;GURMUKHI EK ONKAR;Lo;0;L;;;;;N;;;;; +0A75;GURMUKHI SIGN YAKASH;Mn;0;NSM;;;;;N;;;;; +0A76;GURMUKHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0A81;GUJARATI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0A82;GUJARATI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0A83;GUJARATI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0A85;GUJARATI LETTER A;Lo;0;L;;;;;N;;;;; +0A86;GUJARATI LETTER AA;Lo;0;L;;;;;N;;;;; +0A87;GUJARATI LETTER I;Lo;0;L;;;;;N;;;;; +0A88;GUJARATI LETTER II;Lo;0;L;;;;;N;;;;; +0A89;GUJARATI LETTER U;Lo;0;L;;;;;N;;;;; +0A8A;GUJARATI LETTER UU;Lo;0;L;;;;;N;;;;; +0A8B;GUJARATI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0A8C;GUJARATI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0A8D;GUJARATI VOWEL CANDRA E;Lo;0;L;;;;;N;;;;; +0A8F;GUJARATI LETTER E;Lo;0;L;;;;;N;;;;; +0A90;GUJARATI LETTER AI;Lo;0;L;;;;;N;;;;; +0A91;GUJARATI VOWEL CANDRA O;Lo;0;L;;;;;N;;;;; +0A93;GUJARATI LETTER O;Lo;0;L;;;;;N;;;;; +0A94;GUJARATI LETTER AU;Lo;0;L;;;;;N;;;;; +0A95;GUJARATI LETTER KA;Lo;0;L;;;;;N;;;;; +0A96;GUJARATI LETTER KHA;Lo;0;L;;;;;N;;;;; +0A97;GUJARATI LETTER GA;Lo;0;L;;;;;N;;;;; +0A98;GUJARATI LETTER GHA;Lo;0;L;;;;;N;;;;; +0A99;GUJARATI LETTER NGA;Lo;0;L;;;;;N;;;;; +0A9A;GUJARATI LETTER CA;Lo;0;L;;;;;N;;;;; +0A9B;GUJARATI LETTER CHA;Lo;0;L;;;;;N;;;;; +0A9C;GUJARATI LETTER JA;Lo;0;L;;;;;N;;;;; +0A9D;GUJARATI LETTER JHA;Lo;0;L;;;;;N;;;;; +0A9E;GUJARATI LETTER NYA;Lo;0;L;;;;;N;;;;; +0A9F;GUJARATI LETTER TTA;Lo;0;L;;;;;N;;;;; +0AA0;GUJARATI LETTER TTHA;Lo;0;L;;;;;N;;;;; +0AA1;GUJARATI LETTER DDA;Lo;0;L;;;;;N;;;;; +0AA2;GUJARATI LETTER DDHA;Lo;0;L;;;;;N;;;;; +0AA3;GUJARATI LETTER NNA;Lo;0;L;;;;;N;;;;; +0AA4;GUJARATI LETTER TA;Lo;0;L;;;;;N;;;;; +0AA5;GUJARATI LETTER THA;Lo;0;L;;;;;N;;;;; +0AA6;GUJARATI LETTER DA;Lo;0;L;;;;;N;;;;; +0AA7;GUJARATI LETTER DHA;Lo;0;L;;;;;N;;;;; +0AA8;GUJARATI LETTER NA;Lo;0;L;;;;;N;;;;; +0AAA;GUJARATI LETTER PA;Lo;0;L;;;;;N;;;;; +0AAB;GUJARATI LETTER PHA;Lo;0;L;;;;;N;;;;; +0AAC;GUJARATI LETTER BA;Lo;0;L;;;;;N;;;;; +0AAD;GUJARATI LETTER BHA;Lo;0;L;;;;;N;;;;; +0AAE;GUJARATI LETTER MA;Lo;0;L;;;;;N;;;;; +0AAF;GUJARATI LETTER YA;Lo;0;L;;;;;N;;;;; +0AB0;GUJARATI LETTER RA;Lo;0;L;;;;;N;;;;; +0AB2;GUJARATI LETTER LA;Lo;0;L;;;;;N;;;;; +0AB3;GUJARATI LETTER LLA;Lo;0;L;;;;;N;;;;; +0AB5;GUJARATI LETTER VA;Lo;0;L;;;;;N;;;;; +0AB6;GUJARATI LETTER SHA;Lo;0;L;;;;;N;;;;; +0AB7;GUJARATI LETTER SSA;Lo;0;L;;;;;N;;;;; +0AB8;GUJARATI LETTER SA;Lo;0;L;;;;;N;;;;; +0AB9;GUJARATI LETTER HA;Lo;0;L;;;;;N;;;;; +0ABC;GUJARATI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0ABD;GUJARATI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0ABE;GUJARATI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0ABF;GUJARATI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0AC0;GUJARATI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0AC1;GUJARATI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0AC2;GUJARATI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0AC3;GUJARATI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0AC4;GUJARATI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0AC5;GUJARATI VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; +0AC7;GUJARATI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0AC8;GUJARATI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +0AC9;GUJARATI VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; +0ACB;GUJARATI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +0ACC;GUJARATI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +0ACD;GUJARATI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0AD0;GUJARATI OM;Lo;0;L;;;;;N;;;;; +0AE0;GUJARATI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0AE1;GUJARATI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0AE2;GUJARATI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0AE3;GUJARATI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0AE6;GUJARATI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0AE7;GUJARATI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0AE8;GUJARATI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0AE9;GUJARATI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0AEA;GUJARATI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0AEB;GUJARATI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0AEC;GUJARATI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0AED;GUJARATI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0AEE;GUJARATI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;; +0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;; +0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;; +0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0B05;ORIYA LETTER A;Lo;0;L;;;;;N;;;;; +0B06;ORIYA LETTER AA;Lo;0;L;;;;;N;;;;; +0B07;ORIYA LETTER I;Lo;0;L;;;;;N;;;;; +0B08;ORIYA LETTER II;Lo;0;L;;;;;N;;;;; +0B09;ORIYA LETTER U;Lo;0;L;;;;;N;;;;; +0B0A;ORIYA LETTER UU;Lo;0;L;;;;;N;;;;; +0B0B;ORIYA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0B0C;ORIYA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0B0F;ORIYA LETTER E;Lo;0;L;;;;;N;;;;; +0B10;ORIYA LETTER AI;Lo;0;L;;;;;N;;;;; +0B13;ORIYA LETTER O;Lo;0;L;;;;;N;;;;; +0B14;ORIYA LETTER AU;Lo;0;L;;;;;N;;;;; +0B15;ORIYA LETTER KA;Lo;0;L;;;;;N;;;;; +0B16;ORIYA LETTER KHA;Lo;0;L;;;;;N;;;;; +0B17;ORIYA LETTER GA;Lo;0;L;;;;;N;;;;; +0B18;ORIYA LETTER GHA;Lo;0;L;;;;;N;;;;; +0B19;ORIYA LETTER NGA;Lo;0;L;;;;;N;;;;; +0B1A;ORIYA LETTER CA;Lo;0;L;;;;;N;;;;; +0B1B;ORIYA LETTER CHA;Lo;0;L;;;;;N;;;;; +0B1C;ORIYA LETTER JA;Lo;0;L;;;;;N;;;;; +0B1D;ORIYA LETTER JHA;Lo;0;L;;;;;N;;;;; +0B1E;ORIYA LETTER NYA;Lo;0;L;;;;;N;;;;; +0B1F;ORIYA LETTER TTA;Lo;0;L;;;;;N;;;;; +0B20;ORIYA LETTER TTHA;Lo;0;L;;;;;N;;;;; +0B21;ORIYA LETTER DDA;Lo;0;L;;;;;N;;;;; +0B22;ORIYA LETTER DDHA;Lo;0;L;;;;;N;;;;; +0B23;ORIYA LETTER NNA;Lo;0;L;;;;;N;;;;; +0B24;ORIYA LETTER TA;Lo;0;L;;;;;N;;;;; +0B25;ORIYA LETTER THA;Lo;0;L;;;;;N;;;;; +0B26;ORIYA LETTER DA;Lo;0;L;;;;;N;;;;; +0B27;ORIYA LETTER DHA;Lo;0;L;;;;;N;;;;; +0B28;ORIYA LETTER NA;Lo;0;L;;;;;N;;;;; +0B2A;ORIYA LETTER PA;Lo;0;L;;;;;N;;;;; +0B2B;ORIYA LETTER PHA;Lo;0;L;;;;;N;;;;; +0B2C;ORIYA LETTER BA;Lo;0;L;;;;;N;;;;; +0B2D;ORIYA LETTER BHA;Lo;0;L;;;;;N;;;;; +0B2E;ORIYA LETTER MA;Lo;0;L;;;;;N;;;;; +0B2F;ORIYA LETTER YA;Lo;0;L;;;;;N;;;;; +0B30;ORIYA LETTER RA;Lo;0;L;;;;;N;;;;; +0B32;ORIYA LETTER LA;Lo;0;L;;;;;N;;;;; +0B33;ORIYA LETTER LLA;Lo;0;L;;;;;N;;;;; +0B35;ORIYA LETTER VA;Lo;0;L;;;;;N;;;;; +0B36;ORIYA LETTER SHA;Lo;0;L;;;;;N;;;;; +0B37;ORIYA LETTER SSA;Lo;0;L;;;;;N;;;;; +0B38;ORIYA LETTER SA;Lo;0;L;;;;;N;;;;; +0B39;ORIYA LETTER HA;Lo;0;L;;;;;N;;;;; +0B3C;ORIYA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0B3D;ORIYA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0B3E;ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0B3F;ORIYA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0B40;ORIYA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0B41;ORIYA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0B42;ORIYA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0B43;ORIYA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0B44;ORIYA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0B47;ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0B48;ORIYA VOWEL SIGN AI;Mc;0;L;0B47 0B56;;;;N;;;;; +0B4B;ORIYA VOWEL SIGN O;Mc;0;L;0B47 0B3E;;;;N;;;;; +0B4C;ORIYA VOWEL SIGN AU;Mc;0;L;0B47 0B57;;;;N;;;;; +0B4D;ORIYA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0B55;ORIYA SIGN OVERLINE;Mn;0;NSM;;;;;N;;;;; +0B56;ORIYA AI LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +0B57;ORIYA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0B5C;ORIYA LETTER RRA;Lo;0;L;0B21 0B3C;;;;N;;;;; +0B5D;ORIYA LETTER RHA;Lo;0;L;0B22 0B3C;;;;N;;;;; +0B5F;ORIYA LETTER YYA;Lo;0;L;;;;;N;;;;; +0B60;ORIYA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0B61;ORIYA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0B62;ORIYA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0B63;ORIYA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0B66;ORIYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0B67;ORIYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0B68;ORIYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0B69;ORIYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0B6A;ORIYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0B6B;ORIYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0B6C;ORIYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0B6D;ORIYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0B6E;ORIYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; +0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; +0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; +0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; +0B86;TAMIL LETTER AA;Lo;0;L;;;;;N;;;;; +0B87;TAMIL LETTER I;Lo;0;L;;;;;N;;;;; +0B88;TAMIL LETTER II;Lo;0;L;;;;;N;;;;; +0B89;TAMIL LETTER U;Lo;0;L;;;;;N;;;;; +0B8A;TAMIL LETTER UU;Lo;0;L;;;;;N;;;;; +0B8E;TAMIL LETTER E;Lo;0;L;;;;;N;;;;; +0B8F;TAMIL LETTER EE;Lo;0;L;;;;;N;;;;; +0B90;TAMIL LETTER AI;Lo;0;L;;;;;N;;;;; +0B92;TAMIL LETTER O;Lo;0;L;;;;;N;;;;; +0B93;TAMIL LETTER OO;Lo;0;L;;;;;N;;;;; +0B94;TAMIL LETTER AU;Lo;0;L;0B92 0BD7;;;;N;;;;; +0B95;TAMIL LETTER KA;Lo;0;L;;;;;N;;;;; +0B99;TAMIL LETTER NGA;Lo;0;L;;;;;N;;;;; +0B9A;TAMIL LETTER CA;Lo;0;L;;;;;N;;;;; +0B9C;TAMIL LETTER JA;Lo;0;L;;;;;N;;;;; +0B9E;TAMIL LETTER NYA;Lo;0;L;;;;;N;;;;; +0B9F;TAMIL LETTER TTA;Lo;0;L;;;;;N;;;;; +0BA3;TAMIL LETTER NNA;Lo;0;L;;;;;N;;;;; +0BA4;TAMIL LETTER TA;Lo;0;L;;;;;N;;;;; +0BA8;TAMIL LETTER NA;Lo;0;L;;;;;N;;;;; +0BA9;TAMIL LETTER NNNA;Lo;0;L;;;;;N;;;;; +0BAA;TAMIL LETTER PA;Lo;0;L;;;;;N;;;;; +0BAE;TAMIL LETTER MA;Lo;0;L;;;;;N;;;;; +0BAF;TAMIL LETTER YA;Lo;0;L;;;;;N;;;;; +0BB0;TAMIL LETTER RA;Lo;0;L;;;;;N;;;;; +0BB1;TAMIL LETTER RRA;Lo;0;L;;;;;N;;;;; +0BB2;TAMIL LETTER LA;Lo;0;L;;;;;N;;;;; +0BB3;TAMIL LETTER LLA;Lo;0;L;;;;;N;;;;; +0BB4;TAMIL LETTER LLLA;Lo;0;L;;;;;N;;;;; +0BB5;TAMIL LETTER VA;Lo;0;L;;;;;N;;;;; +0BB6;TAMIL LETTER SHA;Lo;0;L;;;;;N;;;;; +0BB7;TAMIL LETTER SSA;Lo;0;L;;;;;N;;;;; +0BB8;TAMIL LETTER SA;Lo;0;L;;;;;N;;;;; +0BB9;TAMIL LETTER HA;Lo;0;L;;;;;N;;;;; +0BBE;TAMIL VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0BBF;TAMIL VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0BC0;TAMIL VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0BC1;TAMIL VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0BC2;TAMIL VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0BC6;TAMIL VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0BC7;TAMIL VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +0BC8;TAMIL VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +0BCA;TAMIL VOWEL SIGN O;Mc;0;L;0BC6 0BBE;;;;N;;;;; +0BCB;TAMIL VOWEL SIGN OO;Mc;0;L;0BC7 0BBE;;;;N;;;;; +0BCC;TAMIL VOWEL SIGN AU;Mc;0;L;0BC6 0BD7;;;;N;;;;; +0BCD;TAMIL SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0BD0;TAMIL OM;Lo;0;L;;;;;N;;;;; +0BD7;TAMIL AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0BE6;TAMIL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0BE7;TAMIL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0BE8;TAMIL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0BE9;TAMIL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0BEA;TAMIL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0BEB;TAMIL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0BEC;TAMIL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0BED;TAMIL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0BEE;TAMIL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0BEF;TAMIL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0BF0;TAMIL NUMBER TEN;No;0;L;;;;10;N;;;;; +0BF1;TAMIL NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +0BF2;TAMIL NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +0BF3;TAMIL DAY SIGN;So;0;ON;;;;;N;;;;; +0BF4;TAMIL MONTH SIGN;So;0;ON;;;;;N;;;;; +0BF5;TAMIL YEAR SIGN;So;0;ON;;;;;N;;;;; +0BF6;TAMIL DEBIT SIGN;So;0;ON;;;;;N;;;;; +0BF7;TAMIL CREDIT SIGN;So;0;ON;;;;;N;;;;; +0BF8;TAMIL AS ABOVE SIGN;So;0;ON;;;;;N;;;;; +0BF9;TAMIL RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +0BFA;TAMIL NUMBER SIGN;So;0;ON;;;;;N;;;;; +0C00;TELUGU SIGN COMBINING CANDRABINDU ABOVE;Mn;0;NSM;;;;;N;;;;; +0C01;TELUGU SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; +0C02;TELUGU SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0C03;TELUGU SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0C04;TELUGU SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; +0C05;TELUGU LETTER A;Lo;0;L;;;;;N;;;;; +0C06;TELUGU LETTER AA;Lo;0;L;;;;;N;;;;; +0C07;TELUGU LETTER I;Lo;0;L;;;;;N;;;;; +0C08;TELUGU LETTER II;Lo;0;L;;;;;N;;;;; +0C09;TELUGU LETTER U;Lo;0;L;;;;;N;;;;; +0C0A;TELUGU LETTER UU;Lo;0;L;;;;;N;;;;; +0C0B;TELUGU LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0C0C;TELUGU LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0C0E;TELUGU LETTER E;Lo;0;L;;;;;N;;;;; +0C0F;TELUGU LETTER EE;Lo;0;L;;;;;N;;;;; +0C10;TELUGU LETTER AI;Lo;0;L;;;;;N;;;;; +0C12;TELUGU LETTER O;Lo;0;L;;;;;N;;;;; +0C13;TELUGU LETTER OO;Lo;0;L;;;;;N;;;;; +0C14;TELUGU LETTER AU;Lo;0;L;;;;;N;;;;; +0C15;TELUGU LETTER KA;Lo;0;L;;;;;N;;;;; +0C16;TELUGU LETTER KHA;Lo;0;L;;;;;N;;;;; +0C17;TELUGU LETTER GA;Lo;0;L;;;;;N;;;;; +0C18;TELUGU LETTER GHA;Lo;0;L;;;;;N;;;;; +0C19;TELUGU LETTER NGA;Lo;0;L;;;;;N;;;;; +0C1A;TELUGU LETTER CA;Lo;0;L;;;;;N;;;;; +0C1B;TELUGU LETTER CHA;Lo;0;L;;;;;N;;;;; +0C1C;TELUGU LETTER JA;Lo;0;L;;;;;N;;;;; +0C1D;TELUGU LETTER JHA;Lo;0;L;;;;;N;;;;; +0C1E;TELUGU LETTER NYA;Lo;0;L;;;;;N;;;;; +0C1F;TELUGU LETTER TTA;Lo;0;L;;;;;N;;;;; +0C20;TELUGU LETTER TTHA;Lo;0;L;;;;;N;;;;; +0C21;TELUGU LETTER DDA;Lo;0;L;;;;;N;;;;; +0C22;TELUGU LETTER DDHA;Lo;0;L;;;;;N;;;;; +0C23;TELUGU LETTER NNA;Lo;0;L;;;;;N;;;;; +0C24;TELUGU LETTER TA;Lo;0;L;;;;;N;;;;; +0C25;TELUGU LETTER THA;Lo;0;L;;;;;N;;;;; +0C26;TELUGU LETTER DA;Lo;0;L;;;;;N;;;;; +0C27;TELUGU LETTER DHA;Lo;0;L;;;;;N;;;;; +0C28;TELUGU LETTER NA;Lo;0;L;;;;;N;;;;; +0C2A;TELUGU LETTER PA;Lo;0;L;;;;;N;;;;; +0C2B;TELUGU LETTER PHA;Lo;0;L;;;;;N;;;;; +0C2C;TELUGU LETTER BA;Lo;0;L;;;;;N;;;;; +0C2D;TELUGU LETTER BHA;Lo;0;L;;;;;N;;;;; +0C2E;TELUGU LETTER MA;Lo;0;L;;;;;N;;;;; +0C2F;TELUGU LETTER YA;Lo;0;L;;;;;N;;;;; +0C30;TELUGU LETTER RA;Lo;0;L;;;;;N;;;;; +0C31;TELUGU LETTER RRA;Lo;0;L;;;;;N;;;;; +0C32;TELUGU LETTER LA;Lo;0;L;;;;;N;;;;; +0C33;TELUGU LETTER LLA;Lo;0;L;;;;;N;;;;; +0C34;TELUGU LETTER LLLA;Lo;0;L;;;;;N;;;;; +0C35;TELUGU LETTER VA;Lo;0;L;;;;;N;;;;; +0C36;TELUGU LETTER SHA;Lo;0;L;;;;;N;;;;; +0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;; +0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;; +0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;; +0C3C;TELUGU SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0C40;TELUGU VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0C41;TELUGU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0C42;TELUGU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0C43;TELUGU VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +0C44;TELUGU VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +0C46;TELUGU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +0C47;TELUGU VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +0C48;TELUGU VOWEL SIGN AI;Mn;0;NSM;0C46 0C56;;;;N;;;;; +0C4A;TELUGU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +0C4B;TELUGU VOWEL SIGN OO;Mn;0;NSM;;;;;N;;;;; +0C4C;TELUGU VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0C4D;TELUGU SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0C55;TELUGU LENGTH MARK;Mn;84;NSM;;;;;N;;;;; +0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;; +0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;; +0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;; +0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;; +0C5C;TELUGU ARCHAIC SHRII;Lo;0;L;;;;;N;;;;; +0C5D;TELUGU LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;; +0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0C63;TELUGU VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0C66;TELUGU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0C67;TELUGU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0C68;TELUGU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0C69;TELUGU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0C6A;TELUGU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0C6B;TELUGU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0C6C;TELUGU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0C6D;TELUGU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0C6E;TELUGU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0C6F;TELUGU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0C77;TELUGU SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +0C78;TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR;No;0;ON;;;;0;N;;;;; +0C79;TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR;No;0;ON;;;;1;N;;;;; +0C7A;TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR;No;0;ON;;;;2;N;;;;; +0C7B;TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR;No;0;ON;;;;3;N;;;;; +0C7C;TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR;No;0;ON;;;;1;N;;;;; +0C7D;TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR;No;0;ON;;;;2;N;;;;; +0C7E;TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR;No;0;ON;;;;3;N;;;;; +0C7F;TELUGU SIGN TUUMU;So;0;L;;;;;N;;;;; +0C80;KANNADA SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; +0C81;KANNADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0C82;KANNADA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0C83;KANNADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0C84;KANNADA SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +0C85;KANNADA LETTER A;Lo;0;L;;;;;N;;;;; +0C86;KANNADA LETTER AA;Lo;0;L;;;;;N;;;;; +0C87;KANNADA LETTER I;Lo;0;L;;;;;N;;;;; +0C88;KANNADA LETTER II;Lo;0;L;;;;;N;;;;; +0C89;KANNADA LETTER U;Lo;0;L;;;;;N;;;;; +0C8A;KANNADA LETTER UU;Lo;0;L;;;;;N;;;;; +0C8B;KANNADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0C8C;KANNADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0C8E;KANNADA LETTER E;Lo;0;L;;;;;N;;;;; +0C8F;KANNADA LETTER EE;Lo;0;L;;;;;N;;;;; +0C90;KANNADA LETTER AI;Lo;0;L;;;;;N;;;;; +0C92;KANNADA LETTER O;Lo;0;L;;;;;N;;;;; +0C93;KANNADA LETTER OO;Lo;0;L;;;;;N;;;;; +0C94;KANNADA LETTER AU;Lo;0;L;;;;;N;;;;; +0C95;KANNADA LETTER KA;Lo;0;L;;;;;N;;;;; +0C96;KANNADA LETTER KHA;Lo;0;L;;;;;N;;;;; +0C97;KANNADA LETTER GA;Lo;0;L;;;;;N;;;;; +0C98;KANNADA LETTER GHA;Lo;0;L;;;;;N;;;;; +0C99;KANNADA LETTER NGA;Lo;0;L;;;;;N;;;;; +0C9A;KANNADA LETTER CA;Lo;0;L;;;;;N;;;;; +0C9B;KANNADA LETTER CHA;Lo;0;L;;;;;N;;;;; +0C9C;KANNADA LETTER JA;Lo;0;L;;;;;N;;;;; +0C9D;KANNADA LETTER JHA;Lo;0;L;;;;;N;;;;; +0C9E;KANNADA LETTER NYA;Lo;0;L;;;;;N;;;;; +0C9F;KANNADA LETTER TTA;Lo;0;L;;;;;N;;;;; +0CA0;KANNADA LETTER TTHA;Lo;0;L;;;;;N;;;;; +0CA1;KANNADA LETTER DDA;Lo;0;L;;;;;N;;;;; +0CA2;KANNADA LETTER DDHA;Lo;0;L;;;;;N;;;;; +0CA3;KANNADA LETTER NNA;Lo;0;L;;;;;N;;;;; +0CA4;KANNADA LETTER TA;Lo;0;L;;;;;N;;;;; +0CA5;KANNADA LETTER THA;Lo;0;L;;;;;N;;;;; +0CA6;KANNADA LETTER DA;Lo;0;L;;;;;N;;;;; +0CA7;KANNADA LETTER DHA;Lo;0;L;;;;;N;;;;; +0CA8;KANNADA LETTER NA;Lo;0;L;;;;;N;;;;; +0CAA;KANNADA LETTER PA;Lo;0;L;;;;;N;;;;; +0CAB;KANNADA LETTER PHA;Lo;0;L;;;;;N;;;;; +0CAC;KANNADA LETTER BA;Lo;0;L;;;;;N;;;;; +0CAD;KANNADA LETTER BHA;Lo;0;L;;;;;N;;;;; +0CAE;KANNADA LETTER MA;Lo;0;L;;;;;N;;;;; +0CAF;KANNADA LETTER YA;Lo;0;L;;;;;N;;;;; +0CB0;KANNADA LETTER RA;Lo;0;L;;;;;N;;;;; +0CB1;KANNADA LETTER RRA;Lo;0;L;;;;;N;;;;; +0CB2;KANNADA LETTER LA;Lo;0;L;;;;;N;;;;; +0CB3;KANNADA LETTER LLA;Lo;0;L;;;;;N;;;;; +0CB5;KANNADA LETTER VA;Lo;0;L;;;;;N;;;;; +0CB6;KANNADA LETTER SHA;Lo;0;L;;;;;N;;;;; +0CB7;KANNADA LETTER SSA;Lo;0;L;;;;;N;;;;; +0CB8;KANNADA LETTER SA;Lo;0;L;;;;;N;;;;; +0CB9;KANNADA LETTER HA;Lo;0;L;;;;;N;;;;; +0CBC;KANNADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +0CBD;KANNADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0CBE;KANNADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0CBF;KANNADA VOWEL SIGN I;Mn;0;L;;;;;N;;;;; +0CC0;KANNADA VOWEL SIGN II;Mc;0;L;0CBF 0CD5;;;;N;;;;; +0CC1;KANNADA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +0CC2;KANNADA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +0CC3;KANNADA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +0CC4;KANNADA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +0CC6;KANNADA VOWEL SIGN E;Mn;0;L;;;;;N;;;;; +0CC7;KANNADA VOWEL SIGN EE;Mc;0;L;0CC6 0CD5;;;;N;;;;; +0CC8;KANNADA VOWEL SIGN AI;Mc;0;L;0CC6 0CD6;;;;N;;;;; +0CCA;KANNADA VOWEL SIGN O;Mc;0;L;0CC6 0CC2;;;;N;;;;; +0CCB;KANNADA VOWEL SIGN OO;Mc;0;L;0CCA 0CD5;;;;N;;;;; +0CCC;KANNADA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;; +0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;; +0CDC;KANNADA ARCHAIC SHRII;Lo;0;L;;;;;N;;;;; +0CDD;KANNADA LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;; +0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;; +0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0CE2;KANNADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0CE3;KANNADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0CE6;KANNADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0CE7;KANNADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0CE8;KANNADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0CE9;KANNADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0CEA;KANNADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0CEB;KANNADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0CEC;KANNADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +0CF3;KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT;Mc;0;L;;;;;N;;;;; +0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; +0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; +0D04;MALAYALAM LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; +0D06;MALAYALAM LETTER AA;Lo;0;L;;;;;N;;;;; +0D07;MALAYALAM LETTER I;Lo;0;L;;;;;N;;;;; +0D08;MALAYALAM LETTER II;Lo;0;L;;;;;N;;;;; +0D09;MALAYALAM LETTER U;Lo;0;L;;;;;N;;;;; +0D0A;MALAYALAM LETTER UU;Lo;0;L;;;;;N;;;;; +0D0B;MALAYALAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +0D0C;MALAYALAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +0D0E;MALAYALAM LETTER E;Lo;0;L;;;;;N;;;;; +0D0F;MALAYALAM LETTER EE;Lo;0;L;;;;;N;;;;; +0D10;MALAYALAM LETTER AI;Lo;0;L;;;;;N;;;;; +0D12;MALAYALAM LETTER O;Lo;0;L;;;;;N;;;;; +0D13;MALAYALAM LETTER OO;Lo;0;L;;;;;N;;;;; +0D14;MALAYALAM LETTER AU;Lo;0;L;;;;;N;;;;; +0D15;MALAYALAM LETTER KA;Lo;0;L;;;;;N;;;;; +0D16;MALAYALAM LETTER KHA;Lo;0;L;;;;;N;;;;; +0D17;MALAYALAM LETTER GA;Lo;0;L;;;;;N;;;;; +0D18;MALAYALAM LETTER GHA;Lo;0;L;;;;;N;;;;; +0D19;MALAYALAM LETTER NGA;Lo;0;L;;;;;N;;;;; +0D1A;MALAYALAM LETTER CA;Lo;0;L;;;;;N;;;;; +0D1B;MALAYALAM LETTER CHA;Lo;0;L;;;;;N;;;;; +0D1C;MALAYALAM LETTER JA;Lo;0;L;;;;;N;;;;; +0D1D;MALAYALAM LETTER JHA;Lo;0;L;;;;;N;;;;; +0D1E;MALAYALAM LETTER NYA;Lo;0;L;;;;;N;;;;; +0D1F;MALAYALAM LETTER TTA;Lo;0;L;;;;;N;;;;; +0D20;MALAYALAM LETTER TTHA;Lo;0;L;;;;;N;;;;; +0D21;MALAYALAM LETTER DDA;Lo;0;L;;;;;N;;;;; +0D22;MALAYALAM LETTER DDHA;Lo;0;L;;;;;N;;;;; +0D23;MALAYALAM LETTER NNA;Lo;0;L;;;;;N;;;;; +0D24;MALAYALAM LETTER TA;Lo;0;L;;;;;N;;;;; +0D25;MALAYALAM LETTER THA;Lo;0;L;;;;;N;;;;; +0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; +0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; +0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; +0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;; +0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; +0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; +0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; +0D2D;MALAYALAM LETTER BHA;Lo;0;L;;;;;N;;;;; +0D2E;MALAYALAM LETTER MA;Lo;0;L;;;;;N;;;;; +0D2F;MALAYALAM LETTER YA;Lo;0;L;;;;;N;;;;; +0D30;MALAYALAM LETTER RA;Lo;0;L;;;;;N;;;;; +0D31;MALAYALAM LETTER RRA;Lo;0;L;;;;;N;;;;; +0D32;MALAYALAM LETTER LA;Lo;0;L;;;;;N;;;;; +0D33;MALAYALAM LETTER LLA;Lo;0;L;;;;;N;;;;; +0D34;MALAYALAM LETTER LLLA;Lo;0;L;;;;;N;;;;; +0D35;MALAYALAM LETTER VA;Lo;0;L;;;;;N;;;;; +0D36;MALAYALAM LETTER SHA;Lo;0;L;;;;;N;;;;; +0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; +0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; +0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; +0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; +0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +0D40;MALAYALAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +0D41;MALAYALAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +0D42;MALAYALAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +0D43;MALAYALAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +0D44;MALAYALAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +0D46;MALAYALAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +0D47;MALAYALAM VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +0D48;MALAYALAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +0D4A;MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;; +0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; +0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; +0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; +0D4F;MALAYALAM SIGN PARA;So;0;L;;;;;N;;;;; +0D54;MALAYALAM LETTER CHILLU M;Lo;0;L;;;;;N;;;;; +0D55;MALAYALAM LETTER CHILLU Y;Lo;0;L;;;;;N;;;;; +0D56;MALAYALAM LETTER CHILLU LLL;Lo;0;L;;;;;N;;;;; +0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +0D58;MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH;No;0;L;;;;1/160;N;;;;; +0D59;MALAYALAM FRACTION ONE FORTIETH;No;0;L;;;;1/40;N;;;;; +0D5A;MALAYALAM FRACTION THREE EIGHTIETHS;No;0;L;;;;3/80;N;;;;; +0D5B;MALAYALAM FRACTION ONE TWENTIETH;No;0;L;;;;1/20;N;;;;; +0D5C;MALAYALAM FRACTION ONE TENTH;No;0;L;;;;1/10;N;;;;; +0D5D;MALAYALAM FRACTION THREE TWENTIETHS;No;0;L;;;;3/20;N;;;;; +0D5E;MALAYALAM FRACTION ONE FIFTH;No;0;L;;;;1/5;N;;;;; +0D5F;MALAYALAM LETTER ARCHAIC II;Lo;0;L;;;;;N;;;;; +0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +0D63;MALAYALAM VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +0D66;MALAYALAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0D67;MALAYALAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0D68;MALAYALAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0D69;MALAYALAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0D6A;MALAYALAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0D6B;MALAYALAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0D6C;MALAYALAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0D6D;MALAYALAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0D6E;MALAYALAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0D6F;MALAYALAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0D70;MALAYALAM NUMBER TEN;No;0;L;;;;10;N;;;;; +0D71;MALAYALAM NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +0D72;MALAYALAM NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +0D73;MALAYALAM FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +0D74;MALAYALAM FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +0D75;MALAYALAM FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0D76;MALAYALAM FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0D77;MALAYALAM FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0D78;MALAYALAM FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +0D79;MALAYALAM DATE MARK;So;0;L;;;;;N;;;;; +0D7A;MALAYALAM LETTER CHILLU NN;Lo;0;L;;;;;N;;;;; +0D7B;MALAYALAM LETTER CHILLU N;Lo;0;L;;;;;N;;;;; +0D7C;MALAYALAM LETTER CHILLU RR;Lo;0;L;;;;;N;;;;; +0D7D;MALAYALAM LETTER CHILLU L;Lo;0;L;;;;;N;;;;; +0D7E;MALAYALAM LETTER CHILLU LL;Lo;0;L;;;;;N;;;;; +0D7F;MALAYALAM LETTER CHILLU K;Lo;0;L;;;;;N;;;;; +0D81;SINHALA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +0D82;SINHALA SIGN ANUSVARAYA;Mc;0;L;;;;;N;;;;; +0D83;SINHALA SIGN VISARGAYA;Mc;0;L;;;;;N;;;;; +0D85;SINHALA LETTER AYANNA;Lo;0;L;;;;;N;;;;; +0D86;SINHALA LETTER AAYANNA;Lo;0;L;;;;;N;;;;; +0D87;SINHALA LETTER AEYANNA;Lo;0;L;;;;;N;;;;; +0D88;SINHALA LETTER AEEYANNA;Lo;0;L;;;;;N;;;;; +0D89;SINHALA LETTER IYANNA;Lo;0;L;;;;;N;;;;; +0D8A;SINHALA LETTER IIYANNA;Lo;0;L;;;;;N;;;;; +0D8B;SINHALA LETTER UYANNA;Lo;0;L;;;;;N;;;;; +0D8C;SINHALA LETTER UUYANNA;Lo;0;L;;;;;N;;;;; +0D8D;SINHALA LETTER IRUYANNA;Lo;0;L;;;;;N;;;;; +0D8E;SINHALA LETTER IRUUYANNA;Lo;0;L;;;;;N;;;;; +0D8F;SINHALA LETTER ILUYANNA;Lo;0;L;;;;;N;;;;; +0D90;SINHALA LETTER ILUUYANNA;Lo;0;L;;;;;N;;;;; +0D91;SINHALA LETTER EYANNA;Lo;0;L;;;;;N;;;;; +0D92;SINHALA LETTER EEYANNA;Lo;0;L;;;;;N;;;;; +0D93;SINHALA LETTER AIYANNA;Lo;0;L;;;;;N;;;;; +0D94;SINHALA LETTER OYANNA;Lo;0;L;;;;;N;;;;; +0D95;SINHALA LETTER OOYANNA;Lo;0;L;;;;;N;;;;; +0D96;SINHALA LETTER AUYANNA;Lo;0;L;;;;;N;;;;; +0D9A;SINHALA LETTER ALPAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; +0D9B;SINHALA LETTER MAHAAPRAANA KAYANNA;Lo;0;L;;;;;N;;;;; +0D9C;SINHALA LETTER ALPAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; +0D9D;SINHALA LETTER MAHAAPRAANA GAYANNA;Lo;0;L;;;;;N;;;;; +0D9E;SINHALA LETTER KANTAJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; +0D9F;SINHALA LETTER SANYAKA GAYANNA;Lo;0;L;;;;;N;;;;; +0DA0;SINHALA LETTER ALPAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; +0DA1;SINHALA LETTER MAHAAPRAANA CAYANNA;Lo;0;L;;;;;N;;;;; +0DA2;SINHALA LETTER ALPAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA3;SINHALA LETTER MAHAAPRAANA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA4;SINHALA LETTER TAALUJA NAASIKYAYA;Lo;0;L;;;;;N;;;;; +0DA5;SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA;Lo;0;L;;;;;N;;;;; +0DA6;SINHALA LETTER SANYAKA JAYANNA;Lo;0;L;;;;;N;;;;; +0DA7;SINHALA LETTER ALPAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; +0DA8;SINHALA LETTER MAHAAPRAANA TTAYANNA;Lo;0;L;;;;;N;;;;; +0DA9;SINHALA LETTER ALPAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAA;SINHALA LETTER MAHAAPRAANA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAB;SINHALA LETTER MUURDHAJA NAYANNA;Lo;0;L;;;;;N;;;;; +0DAC;SINHALA LETTER SANYAKA DDAYANNA;Lo;0;L;;;;;N;;;;; +0DAD;SINHALA LETTER ALPAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; +0DAE;SINHALA LETTER MAHAAPRAANA TAYANNA;Lo;0;L;;;;;N;;;;; +0DAF;SINHALA LETTER ALPAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB0;SINHALA LETTER MAHAAPRAANA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB1;SINHALA LETTER DANTAJA NAYANNA;Lo;0;L;;;;;N;;;;; +0DB3;SINHALA LETTER SANYAKA DAYANNA;Lo;0;L;;;;;N;;;;; +0DB4;SINHALA LETTER ALPAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; +0DB5;SINHALA LETTER MAHAAPRAANA PAYANNA;Lo;0;L;;;;;N;;;;; +0DB6;SINHALA LETTER ALPAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; +0DB7;SINHALA LETTER MAHAAPRAANA BAYANNA;Lo;0;L;;;;;N;;;;; +0DB8;SINHALA LETTER MAYANNA;Lo;0;L;;;;;N;;;;; +0DB9;SINHALA LETTER AMBA BAYANNA;Lo;0;L;;;;;N;;;;; +0DBA;SINHALA LETTER YAYANNA;Lo;0;L;;;;;N;;;;; +0DBB;SINHALA LETTER RAYANNA;Lo;0;L;;;;;N;;;;; +0DBD;SINHALA LETTER DANTAJA LAYANNA;Lo;0;L;;;;;N;;;;; +0DC0;SINHALA LETTER VAYANNA;Lo;0;L;;;;;N;;;;; +0DC1;SINHALA LETTER TAALUJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC2;SINHALA LETTER MUURDHAJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC3;SINHALA LETTER DANTAJA SAYANNA;Lo;0;L;;;;;N;;;;; +0DC4;SINHALA LETTER HAYANNA;Lo;0;L;;;;;N;;;;; +0DC5;SINHALA LETTER MUURDHAJA LAYANNA;Lo;0;L;;;;;N;;;;; +0DC6;SINHALA LETTER FAYANNA;Lo;0;L;;;;;N;;;;; +0DCA;SINHALA SIGN AL-LAKUNA;Mn;9;NSM;;;;;N;;;;; +0DCF;SINHALA VOWEL SIGN AELA-PILLA;Mc;0;L;;;;;N;;;;; +0DD0;SINHALA VOWEL SIGN KETTI AEDA-PILLA;Mc;0;L;;;;;N;;;;; +0DD1;SINHALA VOWEL SIGN DIGA AEDA-PILLA;Mc;0;L;;;;;N;;;;; +0DD2;SINHALA VOWEL SIGN KETTI IS-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD3;SINHALA VOWEL SIGN DIGA IS-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD4;SINHALA VOWEL SIGN KETTI PAA-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD6;SINHALA VOWEL SIGN DIGA PAA-PILLA;Mn;0;NSM;;;;;N;;;;; +0DD8;SINHALA VOWEL SIGN GAETTA-PILLA;Mc;0;L;;;;;N;;;;; +0DD9;SINHALA VOWEL SIGN KOMBUVA;Mc;0;L;;;;;N;;;;; +0DDA;SINHALA VOWEL SIGN DIGA KOMBUVA;Mc;0;L;0DD9 0DCA;;;;N;;;;; +0DDB;SINHALA VOWEL SIGN KOMBU DEKA;Mc;0;L;;;;;N;;;;; +0DDC;SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA;Mc;0;L;0DD9 0DCF;;;;N;;;;; +0DDD;SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA;Mc;0;L;0DDC 0DCA;;;;N;;;;; +0DDE;SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA;Mc;0;L;0DD9 0DDF;;;;N;;;;; +0DDF;SINHALA VOWEL SIGN GAYANUKITTA;Mc;0;L;;;;;N;;;;; +0DE6;SINHALA LITH DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0DE7;SINHALA LITH DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0DE8;SINHALA LITH DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0DE9;SINHALA LITH DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0DEA;SINHALA LITH DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0DEB;SINHALA LITH DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0DEC;SINHALA LITH DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0DED;SINHALA LITH DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0DEE;SINHALA LITH DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0DEF;SINHALA LITH DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0DF2;SINHALA VOWEL SIGN DIGA GAETTA-PILLA;Mc;0;L;;;;;N;;;;; +0DF3;SINHALA VOWEL SIGN DIGA GAYANUKITTA;Mc;0;L;;;;;N;;;;; +0DF4;SINHALA PUNCTUATION KUNDDALIYA;Po;0;L;;;;;N;;;;; +0E01;THAI CHARACTER KO KAI;Lo;0;L;;;;;N;THAI LETTER KO KAI;;;; +0E02;THAI CHARACTER KHO KHAI;Lo;0;L;;;;;N;THAI LETTER KHO KHAI;;;; +0E03;THAI CHARACTER KHO KHUAT;Lo;0;L;;;;;N;THAI LETTER KHO KHUAT;;;; +0E04;THAI CHARACTER KHO KHWAI;Lo;0;L;;;;;N;THAI LETTER KHO KHWAI;;;; +0E05;THAI CHARACTER KHO KHON;Lo;0;L;;;;;N;THAI LETTER KHO KHON;;;; +0E06;THAI CHARACTER KHO RAKHANG;Lo;0;L;;;;;N;THAI LETTER KHO RAKHANG;;;; +0E07;THAI CHARACTER NGO NGU;Lo;0;L;;;;;N;THAI LETTER NGO NGU;;;; +0E08;THAI CHARACTER CHO CHAN;Lo;0;L;;;;;N;THAI LETTER CHO CHAN;;;; +0E09;THAI CHARACTER CHO CHING;Lo;0;L;;;;;N;THAI LETTER CHO CHING;;;; +0E0A;THAI CHARACTER CHO CHANG;Lo;0;L;;;;;N;THAI LETTER CHO CHANG;;;; +0E0B;THAI CHARACTER SO SO;Lo;0;L;;;;;N;THAI LETTER SO SO;;;; +0E0C;THAI CHARACTER CHO CHOE;Lo;0;L;;;;;N;THAI LETTER CHO CHOE;;;; +0E0D;THAI CHARACTER YO YING;Lo;0;L;;;;;N;THAI LETTER YO YING;;;; +0E0E;THAI CHARACTER DO CHADA;Lo;0;L;;;;;N;THAI LETTER DO CHADA;;;; +0E0F;THAI CHARACTER TO PATAK;Lo;0;L;;;;;N;THAI LETTER TO PATAK;;;; +0E10;THAI CHARACTER THO THAN;Lo;0;L;;;;;N;THAI LETTER THO THAN;;;; +0E11;THAI CHARACTER THO NANGMONTHO;Lo;0;L;;;;;N;THAI LETTER THO NANGMONTHO;;;; +0E12;THAI CHARACTER THO PHUTHAO;Lo;0;L;;;;;N;THAI LETTER THO PHUTHAO;;;; +0E13;THAI CHARACTER NO NEN;Lo;0;L;;;;;N;THAI LETTER NO NEN;;;; +0E14;THAI CHARACTER DO DEK;Lo;0;L;;;;;N;THAI LETTER DO DEK;;;; +0E15;THAI CHARACTER TO TAO;Lo;0;L;;;;;N;THAI LETTER TO TAO;;;; +0E16;THAI CHARACTER THO THUNG;Lo;0;L;;;;;N;THAI LETTER THO THUNG;;;; +0E17;THAI CHARACTER THO THAHAN;Lo;0;L;;;;;N;THAI LETTER THO THAHAN;;;; +0E18;THAI CHARACTER THO THONG;Lo;0;L;;;;;N;THAI LETTER THO THONG;;;; +0E19;THAI CHARACTER NO NU;Lo;0;L;;;;;N;THAI LETTER NO NU;;;; +0E1A;THAI CHARACTER BO BAIMAI;Lo;0;L;;;;;N;THAI LETTER BO BAIMAI;;;; +0E1B;THAI CHARACTER PO PLA;Lo;0;L;;;;;N;THAI LETTER PO PLA;;;; +0E1C;THAI CHARACTER PHO PHUNG;Lo;0;L;;;;;N;THAI LETTER PHO PHUNG;;;; +0E1D;THAI CHARACTER FO FA;Lo;0;L;;;;;N;THAI LETTER FO FA;;;; +0E1E;THAI CHARACTER PHO PHAN;Lo;0;L;;;;;N;THAI LETTER PHO PHAN;;;; +0E1F;THAI CHARACTER FO FAN;Lo;0;L;;;;;N;THAI LETTER FO FAN;;;; +0E20;THAI CHARACTER PHO SAMPHAO;Lo;0;L;;;;;N;THAI LETTER PHO SAMPHAO;;;; +0E21;THAI CHARACTER MO MA;Lo;0;L;;;;;N;THAI LETTER MO MA;;;; +0E22;THAI CHARACTER YO YAK;Lo;0;L;;;;;N;THAI LETTER YO YAK;;;; +0E23;THAI CHARACTER RO RUA;Lo;0;L;;;;;N;THAI LETTER RO RUA;;;; +0E24;THAI CHARACTER RU;Lo;0;L;;;;;N;THAI LETTER RU;;;; +0E25;THAI CHARACTER LO LING;Lo;0;L;;;;;N;THAI LETTER LO LING;;;; +0E26;THAI CHARACTER LU;Lo;0;L;;;;;N;THAI LETTER LU;;;; +0E27;THAI CHARACTER WO WAEN;Lo;0;L;;;;;N;THAI LETTER WO WAEN;;;; +0E28;THAI CHARACTER SO SALA;Lo;0;L;;;;;N;THAI LETTER SO SALA;;;; +0E29;THAI CHARACTER SO RUSI;Lo;0;L;;;;;N;THAI LETTER SO RUSI;;;; +0E2A;THAI CHARACTER SO SUA;Lo;0;L;;;;;N;THAI LETTER SO SUA;;;; +0E2B;THAI CHARACTER HO HIP;Lo;0;L;;;;;N;THAI LETTER HO HIP;;;; +0E2C;THAI CHARACTER LO CHULA;Lo;0;L;;;;;N;THAI LETTER LO CHULA;;;; +0E2D;THAI CHARACTER O ANG;Lo;0;L;;;;;N;THAI LETTER O ANG;;;; +0E2E;THAI CHARACTER HO NOKHUK;Lo;0;L;;;;;N;THAI LETTER HO NOK HUK;;;; +0E2F;THAI CHARACTER PAIYANNOI;Lo;0;L;;;;;N;THAI PAI YAN NOI;;;; +0E30;THAI CHARACTER SARA A;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA A;;;; +0E31;THAI CHARACTER MAI HAN-AKAT;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI HAN-AKAT;;;; +0E32;THAI CHARACTER SARA AA;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AA;;;; +0E33;THAI CHARACTER SARA AM;Lo;0;L; 0E4D 0E32;;;;N;THAI VOWEL SIGN SARA AM;;;; +0E34;THAI CHARACTER SARA I;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA I;;;; +0E35;THAI CHARACTER SARA II;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA II;;;; +0E36;THAI CHARACTER SARA UE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UE;;;; +0E37;THAI CHARACTER SARA UEE;Mn;0;NSM;;;;;N;THAI VOWEL SIGN SARA UEE;;;; +0E38;THAI CHARACTER SARA U;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA U;;;; +0E39;THAI CHARACTER SARA UU;Mn;103;NSM;;;;;N;THAI VOWEL SIGN SARA UU;;;; +0E3A;THAI CHARACTER PHINTHU;Mn;9;NSM;;;;;N;THAI VOWEL SIGN PHINTHU;;;; +0E3F;THAI CURRENCY SYMBOL BAHT;Sc;0;ET;;;;;N;THAI BAHT SIGN;;;; +0E40;THAI CHARACTER SARA E;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA E;;;; +0E41;THAI CHARACTER SARA AE;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA AE;;;; +0E42;THAI CHARACTER SARA O;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA O;;;; +0E43;THAI CHARACTER SARA AI MAIMUAN;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MUAN;;;; +0E44;THAI CHARACTER SARA AI MAIMALAI;Lo;0;L;;;;;N;THAI VOWEL SIGN SARA MAI MALAI;;;; +0E45;THAI CHARACTER LAKKHANGYAO;Lo;0;L;;;;;N;THAI LAK KHANG YAO;;;; +0E46;THAI CHARACTER MAIYAMOK;Lm;0;L;;;;;N;THAI MAI YAMOK;;;; +0E47;THAI CHARACTER MAITAIKHU;Mn;0;NSM;;;;;N;THAI VOWEL SIGN MAI TAI KHU;;;; +0E48;THAI CHARACTER MAI EK;Mn;107;NSM;;;;;N;THAI TONE MAI EK;;;; +0E49;THAI CHARACTER MAI THO;Mn;107;NSM;;;;;N;THAI TONE MAI THO;;;; +0E4A;THAI CHARACTER MAI TRI;Mn;107;NSM;;;;;N;THAI TONE MAI TRI;;;; +0E4B;THAI CHARACTER MAI CHATTAWA;Mn;107;NSM;;;;;N;THAI TONE MAI CHATTAWA;;;; +0E4C;THAI CHARACTER THANTHAKHAT;Mn;0;NSM;;;;;N;THAI THANTHAKHAT;;;; +0E4D;THAI CHARACTER NIKHAHIT;Mn;0;NSM;;;;;N;THAI NIKKHAHIT;;;; +0E4E;THAI CHARACTER YAMAKKAN;Mn;0;NSM;;;;;N;THAI YAMAKKAN;;;; +0E4F;THAI CHARACTER FONGMAN;Po;0;L;;;;;N;THAI FONGMAN;;;; +0E50;THAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0E51;THAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0E52;THAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0E53;THAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0E54;THAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0E55;THAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0E56;THAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0E57;THAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0E58;THAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0E59;THAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0E5A;THAI CHARACTER ANGKHANKHU;Po;0;L;;;;;N;THAI ANGKHANKHU;;;; +0E5B;THAI CHARACTER KHOMUT;Po;0;L;;;;;N;THAI KHOMUT;;;; +0E81;LAO LETTER KO;Lo;0;L;;;;;N;;;;; +0E82;LAO LETTER KHO SUNG;Lo;0;L;;;;;N;;;;; +0E84;LAO LETTER KHO TAM;Lo;0;L;;;;;N;;;;; +0E86;LAO LETTER PALI GHA;Lo;0;L;;;;;N;;;;; +0E87;LAO LETTER NGO;Lo;0;L;;;;;N;;;;; +0E88;LAO LETTER CO;Lo;0;L;;;;;N;;;;; +0E89;LAO LETTER PALI CHA;Lo;0;L;;;;;N;;;;; +0E8A;LAO LETTER SO TAM;Lo;0;L;;;;;N;;;;; +0E8C;LAO LETTER PALI JHA;Lo;0;L;;;;;N;;;;; +0E8D;LAO LETTER NYO;Lo;0;L;;;;;N;;;;; +0E8E;LAO LETTER PALI NYA;Lo;0;L;;;;;N;;;;; +0E8F;LAO LETTER PALI TTA;Lo;0;L;;;;;N;;;;; +0E90;LAO LETTER PALI TTHA;Lo;0;L;;;;;N;;;;; +0E91;LAO LETTER PALI DDA;Lo;0;L;;;;;N;;;;; +0E92;LAO LETTER PALI DDHA;Lo;0;L;;;;;N;;;;; +0E93;LAO LETTER PALI NNA;Lo;0;L;;;;;N;;;;; +0E94;LAO LETTER DO;Lo;0;L;;;;;N;;;;; +0E95;LAO LETTER TO;Lo;0;L;;;;;N;;;;; +0E96;LAO LETTER THO SUNG;Lo;0;L;;;;;N;;;;; +0E97;LAO LETTER THO TAM;Lo;0;L;;;;;N;;;;; +0E98;LAO LETTER PALI DHA;Lo;0;L;;;;;N;;;;; +0E99;LAO LETTER NO;Lo;0;L;;;;;N;;;;; +0E9A;LAO LETTER BO;Lo;0;L;;;;;N;;;;; +0E9B;LAO LETTER PO;Lo;0;L;;;;;N;;;;; +0E9C;LAO LETTER PHO SUNG;Lo;0;L;;;;;N;;;;; +0E9D;LAO LETTER FO TAM;Lo;0;L;;;;;N;;;;; +0E9E;LAO LETTER PHO TAM;Lo;0;L;;;;;N;;;;; +0E9F;LAO LETTER FO SUNG;Lo;0;L;;;;;N;;;;; +0EA0;LAO LETTER PALI BHA;Lo;0;L;;;;;N;;;;; +0EA1;LAO LETTER MO;Lo;0;L;;;;;N;;;;; +0EA2;LAO LETTER YO;Lo;0;L;;;;;N;;;;; +0EA3;LAO LETTER LO LING;Lo;0;L;;;;;N;;;;; +0EA5;LAO LETTER LO LOOT;Lo;0;L;;;;;N;;;;; +0EA7;LAO LETTER WO;Lo;0;L;;;;;N;;;;; +0EA8;LAO LETTER SANSKRIT SHA;Lo;0;L;;;;;N;;;;; +0EA9;LAO LETTER SANSKRIT SSA;Lo;0;L;;;;;N;;;;; +0EAA;LAO LETTER SO SUNG;Lo;0;L;;;;;N;;;;; +0EAB;LAO LETTER HO SUNG;Lo;0;L;;;;;N;;;;; +0EAC;LAO LETTER PALI LLA;Lo;0;L;;;;;N;;;;; +0EAD;LAO LETTER O;Lo;0;L;;;;;N;;;;; +0EAE;LAO LETTER HO TAM;Lo;0;L;;;;;N;;;;; +0EAF;LAO ELLIPSIS;Lo;0;L;;;;;N;;;;; +0EB0;LAO VOWEL SIGN A;Lo;0;L;;;;;N;;;;; +0EB1;LAO VOWEL SIGN MAI KAN;Mn;0;NSM;;;;;N;;;;; +0EB2;LAO VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; +0EB3;LAO VOWEL SIGN AM;Lo;0;L; 0ECD 0EB2;;;;N;;;;; +0EB4;LAO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +0EB5;LAO VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +0EB6;LAO VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; +0EB7;LAO VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; +0EB8;LAO VOWEL SIGN U;Mn;118;NSM;;;;;N;;;;; +0EB9;LAO VOWEL SIGN UU;Mn;118;NSM;;;;;N;;;;; +0EBA;LAO SIGN PALI VIRAMA;Mn;9;NSM;;;;;N;;;;; +0EBB;LAO VOWEL SIGN MAI KON;Mn;0;NSM;;;;;N;;;;; +0EBC;LAO SEMIVOWEL SIGN LO;Mn;0;NSM;;;;;N;;;;; +0EBD;LAO SEMIVOWEL SIGN NYO;Lo;0;L;;;;;N;;;;; +0EC0;LAO VOWEL SIGN E;Lo;0;L;;;;;N;;;;; +0EC1;LAO VOWEL SIGN EI;Lo;0;L;;;;;N;;;;; +0EC2;LAO VOWEL SIGN O;Lo;0;L;;;;;N;;;;; +0EC3;LAO VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; +0EC4;LAO VOWEL SIGN AI;Lo;0;L;;;;;N;;;;; +0EC6;LAO KO LA;Lm;0;L;;;;;N;;;;; +0EC8;LAO TONE MAI EK;Mn;122;NSM;;;;;N;;;;; +0EC9;LAO TONE MAI THO;Mn;122;NSM;;;;;N;;;;; +0ECA;LAO TONE MAI TI;Mn;122;NSM;;;;;N;;;;; +0ECB;LAO TONE MAI CATAWA;Mn;122;NSM;;;;;N;;;;; +0ECC;LAO CANCELLATION MARK;Mn;0;NSM;;;;;N;;;;; +0ECD;LAO NIGGAHITA;Mn;0;NSM;;;;;N;;;;; +0ECE;LAO YAMAKKAN;Mn;0;NSM;;;;;N;;;;; +0ED0;LAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0ED1;LAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0ED2;LAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0ED3;LAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0ED4;LAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0ED5;LAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0ED6;LAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0ED7;LAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0ED8;LAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0ED9;LAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0EDC;LAO HO NO;Lo;0;L; 0EAB 0E99;;;;N;;;;; +0EDD;LAO HO MO;Lo;0;L; 0EAB 0EA1;;;;N;;;;; +0EDE;LAO LETTER KHMU GO;Lo;0;L;;;;;N;;;;; +0EDF;LAO LETTER KHMU NYO;Lo;0;L;;;;;N;;;;; +0F00;TIBETAN SYLLABLE OM;Lo;0;L;;;;;N;;;;; +0F01;TIBETAN MARK GTER YIG MGO TRUNCATED A;So;0;L;;;;;N;;;;; +0F02;TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA;So;0;L;;;;;N;;;;; +0F03;TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA;So;0;L;;;;;N;;;;; +0F04;TIBETAN MARK INITIAL YIG MGO MDUN MA;Po;0;L;;;;;N;TIBETAN SINGLE ORNAMENT;;;; +0F05;TIBETAN MARK CLOSING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; +0F06;TIBETAN MARK CARET YIG MGO PHUR SHAD MA;Po;0;L;;;;;N;;;;; +0F07;TIBETAN MARK YIG MGO TSHEG SHAD MA;Po;0;L;;;;;N;;;;; +0F08;TIBETAN MARK SBRUL SHAD;Po;0;L;;;;;N;TIBETAN RGYANSHAD;;;; +0F09;TIBETAN MARK BSKUR YIG MGO;Po;0;L;;;;;N;;;;; +0F0A;TIBETAN MARK BKA- SHOG YIG MGO;Po;0;L;;;;;N;;;;; +0F0B;TIBETAN MARK INTERSYLLABIC TSHEG;Po;0;L;;;;;N;TIBETAN TSEG;;;; +0F0C;TIBETAN MARK DELIMITER TSHEG BSTAR;Po;0;L; 0F0B;;;;N;;;;; +0F0D;TIBETAN MARK SHAD;Po;0;L;;;;;N;TIBETAN SHAD;;;; +0F0E;TIBETAN MARK NYIS SHAD;Po;0;L;;;;;N;TIBETAN DOUBLE SHAD;;;; +0F0F;TIBETAN MARK TSHEG SHAD;Po;0;L;;;;;N;;;;; +0F10;TIBETAN MARK NYIS TSHEG SHAD;Po;0;L;;;;;N;;;;; +0F11;TIBETAN MARK RIN CHEN SPUNGS SHAD;Po;0;L;;;;;N;TIBETAN RINCHANPHUNGSHAD;;;; +0F12;TIBETAN MARK RGYA GRAM SHAD;Po;0;L;;;;;N;;;;; +0F13;TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN;So;0;L;;;;;N;;;;; +0F14;TIBETAN MARK GTER TSHEG;Po;0;L;;;;;N;TIBETAN COMMA;;;; +0F15;TIBETAN LOGOTYPE SIGN CHAD RTAGS;So;0;L;;;;;N;;;;; +0F16;TIBETAN LOGOTYPE SIGN LHAG RTAGS;So;0;L;;;;;N;;;;; +0F17;TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS;So;0;L;;;;;N;;;;; +0F18;TIBETAN ASTROLOGICAL SIGN -KHYUD PA;Mn;220;NSM;;;;;N;;;;; +0F19;TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS;Mn;220;NSM;;;;;N;;;;; +0F1A;TIBETAN SIGN RDEL DKAR GCIG;So;0;L;;;;;N;;;;; +0F1B;TIBETAN SIGN RDEL DKAR GNYIS;So;0;L;;;;;N;;;;; +0F1C;TIBETAN SIGN RDEL DKAR GSUM;So;0;L;;;;;N;;;;; +0F1D;TIBETAN SIGN RDEL NAG GCIG;So;0;L;;;;;N;;;;; +0F1E;TIBETAN SIGN RDEL NAG GNYIS;So;0;L;;;;;N;;;;; +0F1F;TIBETAN SIGN RDEL DKAR RDEL NAG;So;0;L;;;;;N;;;;; +0F20;TIBETAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +0F21;TIBETAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +0F22;TIBETAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +0F23;TIBETAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +0F24;TIBETAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +0F25;TIBETAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +0F26;TIBETAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +0F27;TIBETAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +0F28;TIBETAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +0F29;TIBETAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +0F2A;TIBETAN DIGIT HALF ONE;No;0;L;;;;1/2;N;;;;; +0F2B;TIBETAN DIGIT HALF TWO;No;0;L;;;;3/2;N;;;;; +0F2C;TIBETAN DIGIT HALF THREE;No;0;L;;;;5/2;N;;;;; +0F2D;TIBETAN DIGIT HALF FOUR;No;0;L;;;;7/2;N;;;;; +0F2E;TIBETAN DIGIT HALF FIVE;No;0;L;;;;9/2;N;;;;; +0F2F;TIBETAN DIGIT HALF SIX;No;0;L;;;;11/2;N;;;;; +0F30;TIBETAN DIGIT HALF SEVEN;No;0;L;;;;13/2;N;;;;; +0F31;TIBETAN DIGIT HALF EIGHT;No;0;L;;;;15/2;N;;;;; +0F32;TIBETAN DIGIT HALF NINE;No;0;L;;;;17/2;N;;;;; +0F33;TIBETAN DIGIT HALF ZERO;No;0;L;;;;-1/2;N;;;;; +0F34;TIBETAN MARK BSDUS RTAGS;So;0;L;;;;;N;;;;; +0F35;TIBETAN MARK NGAS BZUNG NYI ZLA;Mn;220;NSM;;;;;N;TIBETAN HONORIFIC UNDER RING;;;; +0F36;TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN;So;0;L;;;;;N;;;;; +0F37;TIBETAN MARK NGAS BZUNG SGOR RTAGS;Mn;220;NSM;;;;;N;TIBETAN UNDER RING;;;; +0F38;TIBETAN MARK CHE MGO;So;0;L;;;;;N;;;;; +0F39;TIBETAN MARK TSA -PHRU;Mn;216;NSM;;;;;N;TIBETAN LENITION MARK;;;; +0F3A;TIBETAN MARK GUG RTAGS GYON;Ps;0;ON;;;;;Y;;;;; +0F3B;TIBETAN MARK GUG RTAGS GYAS;Pe;0;ON;;;;;Y;;;;; +0F3C;TIBETAN MARK ANG KHANG GYON;Ps;0;ON;;;;;Y;TIBETAN LEFT BRACE;;;; +0F3D;TIBETAN MARK ANG KHANG GYAS;Pe;0;ON;;;;;Y;TIBETAN RIGHT BRACE;;;; +0F3E;TIBETAN SIGN YAR TSHES;Mc;0;L;;;;;N;;;;; +0F3F;TIBETAN SIGN MAR TSHES;Mc;0;L;;;;;N;;;;; +0F40;TIBETAN LETTER KA;Lo;0;L;;;;;N;;;;; +0F41;TIBETAN LETTER KHA;Lo;0;L;;;;;N;;;;; +0F42;TIBETAN LETTER GA;Lo;0;L;;;;;N;;;;; +0F43;TIBETAN LETTER GHA;Lo;0;L;0F42 0FB7;;;;N;;;;; +0F44;TIBETAN LETTER NGA;Lo;0;L;;;;;N;;;;; +0F45;TIBETAN LETTER CA;Lo;0;L;;;;;N;;;;; +0F46;TIBETAN LETTER CHA;Lo;0;L;;;;;N;;;;; +0F47;TIBETAN LETTER JA;Lo;0;L;;;;;N;;;;; +0F49;TIBETAN LETTER NYA;Lo;0;L;;;;;N;;;;; +0F4A;TIBETAN LETTER TTA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED TA;;;; +0F4B;TIBETAN LETTER TTHA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED THA;;;; +0F4C;TIBETAN LETTER DDA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED DA;;;; +0F4D;TIBETAN LETTER DDHA;Lo;0;L;0F4C 0FB7;;;;N;;;;; +0F4E;TIBETAN LETTER NNA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED NA;;;; +0F4F;TIBETAN LETTER TA;Lo;0;L;;;;;N;;;;; +0F50;TIBETAN LETTER THA;Lo;0;L;;;;;N;;;;; +0F51;TIBETAN LETTER DA;Lo;0;L;;;;;N;;;;; +0F52;TIBETAN LETTER DHA;Lo;0;L;0F51 0FB7;;;;N;;;;; +0F53;TIBETAN LETTER NA;Lo;0;L;;;;;N;;;;; +0F54;TIBETAN LETTER PA;Lo;0;L;;;;;N;;;;; +0F55;TIBETAN LETTER PHA;Lo;0;L;;;;;N;;;;; +0F56;TIBETAN LETTER BA;Lo;0;L;;;;;N;;;;; +0F57;TIBETAN LETTER BHA;Lo;0;L;0F56 0FB7;;;;N;;;;; +0F58;TIBETAN LETTER MA;Lo;0;L;;;;;N;;;;; +0F59;TIBETAN LETTER TSA;Lo;0;L;;;;;N;;;;; +0F5A;TIBETAN LETTER TSHA;Lo;0;L;;;;;N;;;;; +0F5B;TIBETAN LETTER DZA;Lo;0;L;;;;;N;;;;; +0F5C;TIBETAN LETTER DZHA;Lo;0;L;0F5B 0FB7;;;;N;;;;; +0F5D;TIBETAN LETTER WA;Lo;0;L;;;;;N;;;;; +0F5E;TIBETAN LETTER ZHA;Lo;0;L;;;;;N;;;;; +0F5F;TIBETAN LETTER ZA;Lo;0;L;;;;;N;;;;; +0F60;TIBETAN LETTER -A;Lo;0;L;;;;;N;TIBETAN LETTER AA;;;; +0F61;TIBETAN LETTER YA;Lo;0;L;;;;;N;;;;; +0F62;TIBETAN LETTER RA;Lo;0;L;;;;;N;;;;; +0F63;TIBETAN LETTER LA;Lo;0;L;;;;;N;;;;; +0F64;TIBETAN LETTER SHA;Lo;0;L;;;;;N;;;;; +0F65;TIBETAN LETTER SSA;Lo;0;L;;;;;N;TIBETAN LETTER REVERSED SHA;;;; +0F66;TIBETAN LETTER SA;Lo;0;L;;;;;N;;;;; +0F67;TIBETAN LETTER HA;Lo;0;L;;;;;N;;;;; +0F68;TIBETAN LETTER A;Lo;0;L;;;;;N;;;;; +0F69;TIBETAN LETTER KSSA;Lo;0;L;0F40 0FB5;;;;N;;;;; +0F6A;TIBETAN LETTER FIXED-FORM RA;Lo;0;L;;;;;N;;;;; +0F6B;TIBETAN LETTER KKA;Lo;0;L;;;;;N;;;;; +0F6C;TIBETAN LETTER RRA;Lo;0;L;;;;;N;;;;; +0F71;TIBETAN VOWEL SIGN AA;Mn;129;NSM;;;;;N;;;;; +0F72;TIBETAN VOWEL SIGN I;Mn;130;NSM;;;;;N;;;;; +0F73;TIBETAN VOWEL SIGN II;Mn;0;NSM;0F71 0F72;;;;N;;;;; +0F74;TIBETAN VOWEL SIGN U;Mn;132;NSM;;;;;N;;;;; +0F75;TIBETAN VOWEL SIGN UU;Mn;0;NSM;0F71 0F74;;;;N;;;;; +0F76;TIBETAN VOWEL SIGN VOCALIC R;Mn;0;NSM;0FB2 0F80;;;;N;;;;; +0F77;TIBETAN VOWEL SIGN VOCALIC RR;Mn;0;NSM; 0FB2 0F81;;;;N;;;;; +0F78;TIBETAN VOWEL SIGN VOCALIC L;Mn;0;NSM;0FB3 0F80;;;;N;;;;; +0F79;TIBETAN VOWEL SIGN VOCALIC LL;Mn;0;NSM; 0FB3 0F81;;;;N;;;;; +0F7A;TIBETAN VOWEL SIGN E;Mn;130;NSM;;;;;N;;;;; +0F7B;TIBETAN VOWEL SIGN EE;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AI;;;; +0F7C;TIBETAN VOWEL SIGN O;Mn;130;NSM;;;;;N;;;;; +0F7D;TIBETAN VOWEL SIGN OO;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN AU;;;; +0F7E;TIBETAN SIGN RJES SU NGA RO;Mn;0;NSM;;;;;N;TIBETAN ANUSVARA;;;; +0F7F;TIBETAN SIGN RNAM BCAD;Mc;0;L;;;;;N;TIBETAN VISARGA;;;; +0F80;TIBETAN VOWEL SIGN REVERSED I;Mn;130;NSM;;;;;N;TIBETAN VOWEL SIGN SHORT I;;;; +0F81;TIBETAN VOWEL SIGN REVERSED II;Mn;0;NSM;0F71 0F80;;;;N;;;;; +0F82;TIBETAN SIGN NYI ZLA NAA DA;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU WITH ORNAMENT;;;; +0F83;TIBETAN SIGN SNA LDAN;Mn;230;NSM;;;;;N;TIBETAN CANDRABINDU;;;; +0F84;TIBETAN MARK HALANTA;Mn;9;NSM;;;;;N;TIBETAN VIRAMA;;;; +0F85;TIBETAN MARK PALUTA;Po;0;L;;;;;N;TIBETAN CHUCHENYIGE;;;; +0F86;TIBETAN SIGN LCI RTAGS;Mn;230;NSM;;;;;N;;;;; +0F87;TIBETAN SIGN YANG RTAGS;Mn;230;NSM;;;;;N;;;;; +0F88;TIBETAN SIGN LCE TSA CAN;Lo;0;L;;;;;N;;;;; +0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; +0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; +0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; +0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;; +0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;; +0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;; +0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;; +0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; +0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; +0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; +0F93;TIBETAN SUBJOINED LETTER GHA;Mn;0;NSM;0F92 0FB7;;;;N;;;;; +0F94;TIBETAN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; +0F95;TIBETAN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; +0F96;TIBETAN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; +0F97;TIBETAN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; +0F99;TIBETAN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; +0F9A;TIBETAN SUBJOINED LETTER TTA;Mn;0;NSM;;;;;N;;;;; +0F9B;TIBETAN SUBJOINED LETTER TTHA;Mn;0;NSM;;;;;N;;;;; +0F9C;TIBETAN SUBJOINED LETTER DDA;Mn;0;NSM;;;;;N;;;;; +0F9D;TIBETAN SUBJOINED LETTER DDHA;Mn;0;NSM;0F9C 0FB7;;;;N;;;;; +0F9E;TIBETAN SUBJOINED LETTER NNA;Mn;0;NSM;;;;;N;;;;; +0F9F;TIBETAN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; +0FA0;TIBETAN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; +0FA1;TIBETAN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; +0FA2;TIBETAN SUBJOINED LETTER DHA;Mn;0;NSM;0FA1 0FB7;;;;N;;;;; +0FA3;TIBETAN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; +0FA4;TIBETAN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; +0FA5;TIBETAN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; +0FA6;TIBETAN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; +0FA7;TIBETAN SUBJOINED LETTER BHA;Mn;0;NSM;0FA6 0FB7;;;;N;;;;; +0FA8;TIBETAN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; +0FA9;TIBETAN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; +0FAA;TIBETAN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; +0FAB;TIBETAN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; +0FAC;TIBETAN SUBJOINED LETTER DZHA;Mn;0;NSM;0FAB 0FB7;;;;N;;;;; +0FAD;TIBETAN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; +0FAE;TIBETAN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; +0FAF;TIBETAN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; +0FB0;TIBETAN SUBJOINED LETTER -A;Mn;0;NSM;;;;;N;;;;; +0FB1;TIBETAN SUBJOINED LETTER YA;Mn;0;NSM;;;;;N;;;;; +0FB2;TIBETAN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; +0FB3;TIBETAN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; +0FB4;TIBETAN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; +0FB5;TIBETAN SUBJOINED LETTER SSA;Mn;0;NSM;;;;;N;;;;; +0FB6;TIBETAN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; +0FB7;TIBETAN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; +0FB8;TIBETAN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; +0FB9;TIBETAN SUBJOINED LETTER KSSA;Mn;0;NSM;0F90 0FB5;;;;N;;;;; +0FBA;TIBETAN SUBJOINED LETTER FIXED-FORM WA;Mn;0;NSM;;;;;N;;;;; +0FBB;TIBETAN SUBJOINED LETTER FIXED-FORM YA;Mn;0;NSM;;;;;N;;;;; +0FBC;TIBETAN SUBJOINED LETTER FIXED-FORM RA;Mn;0;NSM;;;;;N;;;;; +0FBE;TIBETAN KU RU KHA;So;0;L;;;;;N;;;;; +0FBF;TIBETAN KU RU KHA BZHI MIG CAN;So;0;L;;;;;N;;;;; +0FC0;TIBETAN CANTILLATION SIGN HEAVY BEAT;So;0;L;;;;;N;;;;; +0FC1;TIBETAN CANTILLATION SIGN LIGHT BEAT;So;0;L;;;;;N;;;;; +0FC2;TIBETAN CANTILLATION SIGN CANG TE-U;So;0;L;;;;;N;;;;; +0FC3;TIBETAN CANTILLATION SIGN SBUB -CHAL;So;0;L;;;;;N;;;;; +0FC4;TIBETAN SYMBOL DRIL BU;So;0;L;;;;;N;;;;; +0FC5;TIBETAN SYMBOL RDO RJE;So;0;L;;;;;N;;;;; +0FC6;TIBETAN SYMBOL PADMA GDAN;Mn;220;NSM;;;;;N;;;;; +0FC7;TIBETAN SYMBOL RDO RJE RGYA GRAM;So;0;L;;;;;N;;;;; +0FC8;TIBETAN SYMBOL PHUR PA;So;0;L;;;;;N;;;;; +0FC9;TIBETAN SYMBOL NOR BU;So;0;L;;;;;N;;;;; +0FCA;TIBETAN SYMBOL NOR BU NYIS -KHYIL;So;0;L;;;;;N;;;;; +0FCB;TIBETAN SYMBOL NOR BU GSUM -KHYIL;So;0;L;;;;;N;;;;; +0FCC;TIBETAN SYMBOL NOR BU BZHI -KHYIL;So;0;L;;;;;N;;;;; +0FCE;TIBETAN SIGN RDEL NAG RDEL DKAR;So;0;L;;;;;N;;;;; +0FCF;TIBETAN SIGN RDEL NAG GSUM;So;0;L;;;;;N;;;;; +0FD0;TIBETAN MARK BSKA- SHOG GI MGO RGYAN;Po;0;L;;;;;N;;;;; +0FD1;TIBETAN MARK MNYAM YIG GI MGO RGYAN;Po;0;L;;;;;N;;;;; +0FD2;TIBETAN MARK NYIS TSHEG;Po;0;L;;;;;N;;;;; +0FD3;TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA;Po;0;L;;;;;N;;;;; +0FD4;TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA;Po;0;L;;;;;N;;;;; +0FD5;RIGHT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; +0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; +0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; +0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; +0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;; +0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;; +1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; +1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; +1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; +1003;MYANMAR LETTER GHA;Lo;0;L;;;;;N;;;;; +1004;MYANMAR LETTER NGA;Lo;0;L;;;;;N;;;;; +1005;MYANMAR LETTER CA;Lo;0;L;;;;;N;;;;; +1006;MYANMAR LETTER CHA;Lo;0;L;;;;;N;;;;; +1007;MYANMAR LETTER JA;Lo;0;L;;;;;N;;;;; +1008;MYANMAR LETTER JHA;Lo;0;L;;;;;N;;;;; +1009;MYANMAR LETTER NYA;Lo;0;L;;;;;N;;;;; +100A;MYANMAR LETTER NNYA;Lo;0;L;;;;;N;;;;; +100B;MYANMAR LETTER TTA;Lo;0;L;;;;;N;;;;; +100C;MYANMAR LETTER TTHA;Lo;0;L;;;;;N;;;;; +100D;MYANMAR LETTER DDA;Lo;0;L;;;;;N;;;;; +100E;MYANMAR LETTER DDHA;Lo;0;L;;;;;N;;;;; +100F;MYANMAR LETTER NNA;Lo;0;L;;;;;N;;;;; +1010;MYANMAR LETTER TA;Lo;0;L;;;;;N;;;;; +1011;MYANMAR LETTER THA;Lo;0;L;;;;;N;;;;; +1012;MYANMAR LETTER DA;Lo;0;L;;;;;N;;;;; +1013;MYANMAR LETTER DHA;Lo;0;L;;;;;N;;;;; +1014;MYANMAR LETTER NA;Lo;0;L;;;;;N;;;;; +1015;MYANMAR LETTER PA;Lo;0;L;;;;;N;;;;; +1016;MYANMAR LETTER PHA;Lo;0;L;;;;;N;;;;; +1017;MYANMAR LETTER BA;Lo;0;L;;;;;N;;;;; +1018;MYANMAR LETTER BHA;Lo;0;L;;;;;N;;;;; +1019;MYANMAR LETTER MA;Lo;0;L;;;;;N;;;;; +101A;MYANMAR LETTER YA;Lo;0;L;;;;;N;;;;; +101B;MYANMAR LETTER RA;Lo;0;L;;;;;N;;;;; +101C;MYANMAR LETTER LA;Lo;0;L;;;;;N;;;;; +101D;MYANMAR LETTER WA;Lo;0;L;;;;;N;;;;; +101E;MYANMAR LETTER SA;Lo;0;L;;;;;N;;;;; +101F;MYANMAR LETTER HA;Lo;0;L;;;;;N;;;;; +1020;MYANMAR LETTER LLA;Lo;0;L;;;;;N;;;;; +1021;MYANMAR LETTER A;Lo;0;L;;;;;N;;;;; +1022;MYANMAR LETTER SHAN A;Lo;0;L;;;;;N;;;;; +1023;MYANMAR LETTER I;Lo;0;L;;;;;N;;;;; +1024;MYANMAR LETTER II;Lo;0;L;;;;;N;;;;; +1025;MYANMAR LETTER U;Lo;0;L;;;;;N;;;;; +1026;MYANMAR LETTER UU;Lo;0;L;1025 102E;;;;N;;;;; +1027;MYANMAR LETTER E;Lo;0;L;;;;;N;;;;; +1028;MYANMAR LETTER MON E;Lo;0;L;;;;;N;;;;; +1029;MYANMAR LETTER O;Lo;0;L;;;;;N;;;;; +102A;MYANMAR LETTER AU;Lo;0;L;;;;;N;;;;; +102B;MYANMAR VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; +102C;MYANMAR VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +102D;MYANMAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +102E;MYANMAR VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +102F;MYANMAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1030;MYANMAR VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1031;MYANMAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1032;MYANMAR VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1033;MYANMAR VOWEL SIGN MON II;Mn;0;NSM;;;;;N;;;;; +1034;MYANMAR VOWEL SIGN MON O;Mn;0;NSM;;;;;N;;;;; +1035;MYANMAR VOWEL SIGN E ABOVE;Mn;0;NSM;;;;;N;;;;; +1036;MYANMAR SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1037;MYANMAR SIGN DOT BELOW;Mn;7;NSM;;;;;N;;;;; +1038;MYANMAR SIGN VISARGA;Mc;0;L;;;;;N;;;;; +1039;MYANMAR SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +103A;MYANMAR SIGN ASAT;Mn;9;NSM;;;;;N;;;;; +103B;MYANMAR CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; +103C;MYANMAR CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; +103D;MYANMAR CONSONANT SIGN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; +103E;MYANMAR CONSONANT SIGN MEDIAL HA;Mn;0;NSM;;;;;N;;;;; +103F;MYANMAR LETTER GREAT SA;Lo;0;L;;;;;N;;;;; +1040;MYANMAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1041;MYANMAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1042;MYANMAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1043;MYANMAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1044;MYANMAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1045;MYANMAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1046;MYANMAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1047;MYANMAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1048;MYANMAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1049;MYANMAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +104A;MYANMAR SIGN LITTLE SECTION;Po;0;L;;;;;N;;;;; +104B;MYANMAR SIGN SECTION;Po;0;L;;;;;N;;;;; +104C;MYANMAR SYMBOL LOCATIVE;Po;0;L;;;;;N;;;;; +104D;MYANMAR SYMBOL COMPLETED;Po;0;L;;;;;N;;;;; +104E;MYANMAR SYMBOL AFOREMENTIONED;Po;0;L;;;;;N;;;;; +104F;MYANMAR SYMBOL GENITIVE;Po;0;L;;;;;N;;;;; +1050;MYANMAR LETTER SHA;Lo;0;L;;;;;N;;;;; +1051;MYANMAR LETTER SSA;Lo;0;L;;;;;N;;;;; +1052;MYANMAR LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1053;MYANMAR LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1054;MYANMAR LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1055;MYANMAR LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1056;MYANMAR VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +1057;MYANMAR VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +1058;MYANMAR VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +1059;MYANMAR VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +105A;MYANMAR LETTER MON NGA;Lo;0;L;;;;;N;;;;; +105B;MYANMAR LETTER MON JHA;Lo;0;L;;;;;N;;;;; +105C;MYANMAR LETTER MON BBA;Lo;0;L;;;;;N;;;;; +105D;MYANMAR LETTER MON BBE;Lo;0;L;;;;;N;;;;; +105E;MYANMAR CONSONANT SIGN MON MEDIAL NA;Mn;0;NSM;;;;;N;;;;; +105F;MYANMAR CONSONANT SIGN MON MEDIAL MA;Mn;0;NSM;;;;;N;;;;; +1060;MYANMAR CONSONANT SIGN MON MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1061;MYANMAR LETTER SGAW KAREN SHA;Lo;0;L;;;;;N;;;;; +1062;MYANMAR VOWEL SIGN SGAW KAREN EU;Mc;0;L;;;;;N;;;;; +1063;MYANMAR TONE MARK SGAW KAREN HATHI;Mc;0;L;;;;;N;;;;; +1064;MYANMAR TONE MARK SGAW KAREN KE PHO;Mc;0;L;;;;;N;;;;; +1065;MYANMAR LETTER WESTERN PWO KAREN THA;Lo;0;L;;;;;N;;;;; +1066;MYANMAR LETTER WESTERN PWO KAREN PWA;Lo;0;L;;;;;N;;;;; +1067;MYANMAR VOWEL SIGN WESTERN PWO KAREN EU;Mc;0;L;;;;;N;;;;; +1068;MYANMAR VOWEL SIGN WESTERN PWO KAREN UE;Mc;0;L;;;;;N;;;;; +1069;MYANMAR SIGN WESTERN PWO KAREN TONE-1;Mc;0;L;;;;;N;;;;; +106A;MYANMAR SIGN WESTERN PWO KAREN TONE-2;Mc;0;L;;;;;N;;;;; +106B;MYANMAR SIGN WESTERN PWO KAREN TONE-3;Mc;0;L;;;;;N;;;;; +106C;MYANMAR SIGN WESTERN PWO KAREN TONE-4;Mc;0;L;;;;;N;;;;; +106D;MYANMAR SIGN WESTERN PWO KAREN TONE-5;Mc;0;L;;;;;N;;;;; +106E;MYANMAR LETTER EASTERN PWO KAREN NNA;Lo;0;L;;;;;N;;;;; +106F;MYANMAR LETTER EASTERN PWO KAREN YWA;Lo;0;L;;;;;N;;;;; +1070;MYANMAR LETTER EASTERN PWO KAREN GHWA;Lo;0;L;;;;;N;;;;; +1071;MYANMAR VOWEL SIGN GEBA KAREN I;Mn;0;NSM;;;;;N;;;;; +1072;MYANMAR VOWEL SIGN KAYAH OE;Mn;0;NSM;;;;;N;;;;; +1073;MYANMAR VOWEL SIGN KAYAH U;Mn;0;NSM;;;;;N;;;;; +1074;MYANMAR VOWEL SIGN KAYAH EE;Mn;0;NSM;;;;;N;;;;; +1075;MYANMAR LETTER SHAN KA;Lo;0;L;;;;;N;;;;; +1076;MYANMAR LETTER SHAN KHA;Lo;0;L;;;;;N;;;;; +1077;MYANMAR LETTER SHAN GA;Lo;0;L;;;;;N;;;;; +1078;MYANMAR LETTER SHAN CA;Lo;0;L;;;;;N;;;;; +1079;MYANMAR LETTER SHAN ZA;Lo;0;L;;;;;N;;;;; +107A;MYANMAR LETTER SHAN NYA;Lo;0;L;;;;;N;;;;; +107B;MYANMAR LETTER SHAN DA;Lo;0;L;;;;;N;;;;; +107C;MYANMAR LETTER SHAN NA;Lo;0;L;;;;;N;;;;; +107D;MYANMAR LETTER SHAN PHA;Lo;0;L;;;;;N;;;;; +107E;MYANMAR LETTER SHAN FA;Lo;0;L;;;;;N;;;;; +107F;MYANMAR LETTER SHAN BA;Lo;0;L;;;;;N;;;;; +1080;MYANMAR LETTER SHAN THA;Lo;0;L;;;;;N;;;;; +1081;MYANMAR LETTER SHAN HA;Lo;0;L;;;;;N;;;;; +1082;MYANMAR CONSONANT SIGN SHAN MEDIAL WA;Mn;0;NSM;;;;;N;;;;; +1083;MYANMAR VOWEL SIGN SHAN AA;Mc;0;L;;;;;N;;;;; +1084;MYANMAR VOWEL SIGN SHAN E;Mc;0;L;;;;;N;;;;; +1085;MYANMAR VOWEL SIGN SHAN E ABOVE;Mn;0;NSM;;;;;N;;;;; +1086;MYANMAR VOWEL SIGN SHAN FINAL Y;Mn;0;NSM;;;;;N;;;;; +1087;MYANMAR SIGN SHAN TONE-2;Mc;0;L;;;;;N;;;;; +1088;MYANMAR SIGN SHAN TONE-3;Mc;0;L;;;;;N;;;;; +1089;MYANMAR SIGN SHAN TONE-5;Mc;0;L;;;;;N;;;;; +108A;MYANMAR SIGN SHAN TONE-6;Mc;0;L;;;;;N;;;;; +108B;MYANMAR SIGN SHAN COUNCIL TONE-2;Mc;0;L;;;;;N;;;;; +108C;MYANMAR SIGN SHAN COUNCIL TONE-3;Mc;0;L;;;;;N;;;;; +108D;MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE;Mn;220;NSM;;;;;N;;;;; +108E;MYANMAR LETTER RUMAI PALAUNG FA;Lo;0;L;;;;;N;;;;; +108F;MYANMAR SIGN RUMAI PALAUNG TONE-5;Mc;0;L;;;;;N;;;;; +1090;MYANMAR SHAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1091;MYANMAR SHAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1092;MYANMAR SHAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1093;MYANMAR SHAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1094;MYANMAR SHAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1095;MYANMAR SHAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1096;MYANMAR SHAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1097;MYANMAR SHAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1098;MYANMAR SHAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1099;MYANMAR SHAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +109A;MYANMAR SIGN KHAMTI TONE-1;Mc;0;L;;;;;N;;;;; +109B;MYANMAR SIGN KHAMTI TONE-3;Mc;0;L;;;;;N;;;;; +109C;MYANMAR VOWEL SIGN AITON A;Mc;0;L;;;;;N;;;;; +109D;MYANMAR VOWEL SIGN AITON AI;Mn;0;NSM;;;;;N;;;;; +109E;MYANMAR SYMBOL SHAN ONE;So;0;L;;;;;N;;;;; +109F;MYANMAR SYMBOL SHAN EXCLAMATION;So;0;L;;;;;N;;;;; +10A0;GEORGIAN CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;2D00; +10A1;GEORGIAN CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;2D01; +10A2;GEORGIAN CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;2D02; +10A3;GEORGIAN CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;2D03; +10A4;GEORGIAN CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;2D04; +10A5;GEORGIAN CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;2D05; +10A6;GEORGIAN CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;2D06; +10A7;GEORGIAN CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;2D07; +10A8;GEORGIAN CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;2D08; +10A9;GEORGIAN CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;2D09; +10AA;GEORGIAN CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;2D0A; +10AB;GEORGIAN CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;2D0B; +10AC;GEORGIAN CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;2D0C; +10AD;GEORGIAN CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;2D0D; +10AE;GEORGIAN CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;2D0E; +10AF;GEORGIAN CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;2D0F; +10B0;GEORGIAN CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;2D10; +10B1;GEORGIAN CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;2D11; +10B2;GEORGIAN CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;2D12; +10B3;GEORGIAN CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;2D13; +10B4;GEORGIAN CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;2D14; +10B5;GEORGIAN CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;2D15; +10B6;GEORGIAN CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;2D16; +10B7;GEORGIAN CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;2D17; +10B8;GEORGIAN CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;2D18; +10B9;GEORGIAN CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;2D19; +10BA;GEORGIAN CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;2D1A; +10BB;GEORGIAN CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;2D1B; +10BC;GEORGIAN CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;2D1C; +10BD;GEORGIAN CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;2D1D; +10BE;GEORGIAN CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;2D1E; +10BF;GEORGIAN CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;2D1F; +10C0;GEORGIAN CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;2D20; +10C1;GEORGIAN CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;2D21; +10C2;GEORGIAN CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;2D22; +10C3;GEORGIAN CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;2D23; +10C4;GEORGIAN CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;2D24; +10C5;GEORGIAN CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;2D25; +10C7;GEORGIAN CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;2D27; +10CD;GEORGIAN CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;2D2D; +10D0;GEORGIAN LETTER AN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER AN;;1C90;;10D0 +10D1;GEORGIAN LETTER BAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER BAN;;1C91;;10D1 +10D2;GEORGIAN LETTER GAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER GAN;;1C92;;10D2 +10D3;GEORGIAN LETTER DON;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER DON;;1C93;;10D3 +10D4;GEORGIAN LETTER EN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER EN;;1C94;;10D4 +10D5;GEORGIAN LETTER VIN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER VIN;;1C95;;10D5 +10D6;GEORGIAN LETTER ZEN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER ZEN;;1C96;;10D6 +10D7;GEORGIAN LETTER TAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER TAN;;1C97;;10D7 +10D8;GEORGIAN LETTER IN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER IN;;1C98;;10D8 +10D9;GEORGIAN LETTER KAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER KAN;;1C99;;10D9 +10DA;GEORGIAN LETTER LAS;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER LAS;;1C9A;;10DA +10DB;GEORGIAN LETTER MAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER MAN;;1C9B;;10DB +10DC;GEORGIAN LETTER NAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER NAR;;1C9C;;10DC +10DD;GEORGIAN LETTER ON;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER ON;;1C9D;;10DD +10DE;GEORGIAN LETTER PAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER PAR;;1C9E;;10DE +10DF;GEORGIAN LETTER ZHAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER ZHAR;;1C9F;;10DF +10E0;GEORGIAN LETTER RAE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER RAE;;1CA0;;10E0 +10E1;GEORGIAN LETTER SAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER SAN;;1CA1;;10E1 +10E2;GEORGIAN LETTER TAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER TAR;;1CA2;;10E2 +10E3;GEORGIAN LETTER UN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER UN;;1CA3;;10E3 +10E4;GEORGIAN LETTER PHAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER PHAR;;1CA4;;10E4 +10E5;GEORGIAN LETTER KHAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER KHAR;;1CA5;;10E5 +10E6;GEORGIAN LETTER GHAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER GHAN;;1CA6;;10E6 +10E7;GEORGIAN LETTER QAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER QAR;;1CA7;;10E7 +10E8;GEORGIAN LETTER SHIN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER SHIN;;1CA8;;10E8 +10E9;GEORGIAN LETTER CHIN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER CHIN;;1CA9;;10E9 +10EA;GEORGIAN LETTER CAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER CAN;;1CAA;;10EA +10EB;GEORGIAN LETTER JIL;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER JIL;;1CAB;;10EB +10EC;GEORGIAN LETTER CIL;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER CIL;;1CAC;;10EC +10ED;GEORGIAN LETTER CHAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER CHAR;;1CAD;;10ED +10EE;GEORGIAN LETTER XAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER XAN;;1CAE;;10EE +10EF;GEORGIAN LETTER JHAN;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER JHAN;;1CAF;;10EF +10F0;GEORGIAN LETTER HAE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER HAE;;1CB0;;10F0 +10F1;GEORGIAN LETTER HE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER HE;;1CB1;;10F1 +10F2;GEORGIAN LETTER HIE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER HIE;;1CB2;;10F2 +10F3;GEORGIAN LETTER WE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER WE;;1CB3;;10F3 +10F4;GEORGIAN LETTER HAR;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER HAR;;1CB4;;10F4 +10F5;GEORGIAN LETTER HOE;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER HOE;;1CB5;;10F5 +10F6;GEORGIAN LETTER FI;Ll;0;L;;;;;N;GEORGIAN SMALL LETTER FI;;1CB6;;10F6 +10F7;GEORGIAN LETTER YN;Ll;0;L;;;;;N;;;1CB7;;10F7 +10F8;GEORGIAN LETTER ELIFI;Ll;0;L;;;;;N;;;1CB8;;10F8 +10F9;GEORGIAN LETTER TURNED GAN;Ll;0;L;;;;;N;;;1CB9;;10F9 +10FA;GEORGIAN LETTER AIN;Ll;0;L;;;;;N;;;1CBA;;10FA +10FB;GEORGIAN PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; +10FC;MODIFIER LETTER GEORGIAN NAR;Lm;0;L; 10DC;;;;N;;;;; +10FD;GEORGIAN LETTER AEN;Ll;0;L;;;;;N;;;1CBD;;10FD +10FE;GEORGIAN LETTER HARD SIGN;Ll;0;L;;;;;N;;;1CBE;;10FE +10FF;GEORGIAN LETTER LABIAL SIGN;Ll;0;L;;;;;N;;;1CBF;;10FF +1100;HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;; +1101;HANGUL CHOSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +1102;HANGUL CHOSEONG NIEUN;Lo;0;L;;;;;N;;;;; +1103;HANGUL CHOSEONG TIKEUT;Lo;0;L;;;;;N;;;;; +1104;HANGUL CHOSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +1105;HANGUL CHOSEONG RIEUL;Lo;0;L;;;;;N;;;;; +1106;HANGUL CHOSEONG MIEUM;Lo;0;L;;;;;N;;;;; +1107;HANGUL CHOSEONG PIEUP;Lo;0;L;;;;;N;;;;; +1108;HANGUL CHOSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; +1109;HANGUL CHOSEONG SIOS;Lo;0;L;;;;;N;;;;; +110A;HANGUL CHOSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; +110B;HANGUL CHOSEONG IEUNG;Lo;0;L;;;;;N;;;;; +110C;HANGUL CHOSEONG CIEUC;Lo;0;L;;;;;N;;;;; +110D;HANGUL CHOSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; +110E;HANGUL CHOSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; +110F;HANGUL CHOSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; +1110;HANGUL CHOSEONG THIEUTH;Lo;0;L;;;;;N;;;;; +1111;HANGUL CHOSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; +1112;HANGUL CHOSEONG HIEUH;Lo;0;L;;;;;N;;;;; +1113;HANGUL CHOSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; +1114;HANGUL CHOSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; +1115;HANGUL CHOSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; +1116;HANGUL CHOSEONG NIEUN-PIEUP;Lo;0;L;;;;;N;;;;; +1117;HANGUL CHOSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; +1118;HANGUL CHOSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; +1119;HANGUL CHOSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; +111A;HANGUL CHOSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; +111B;HANGUL CHOSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; +111C;HANGUL CHOSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; +111D;HANGUL CHOSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; +111E;HANGUL CHOSEONG PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; +111F;HANGUL CHOSEONG PIEUP-NIEUN;Lo;0;L;;;;;N;;;;; +1120;HANGUL CHOSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +1121;HANGUL CHOSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +1122;HANGUL CHOSEONG PIEUP-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +1123;HANGUL CHOSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +1124;HANGUL CHOSEONG PIEUP-SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +1125;HANGUL CHOSEONG PIEUP-SSANGSIOS;Lo;0;L;;;;;N;;;;; +1126;HANGUL CHOSEONG PIEUP-SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +1127;HANGUL CHOSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; +1128;HANGUL CHOSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; +1129;HANGUL CHOSEONG PIEUP-THIEUTH;Lo;0;L;;;;;N;;;;; +112A;HANGUL CHOSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +112B;HANGUL CHOSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +112C;HANGUL CHOSEONG KAPYEOUNSSANGPIEUP;Lo;0;L;;;;;N;;;;; +112D;HANGUL CHOSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +112E;HANGUL CHOSEONG SIOS-NIEUN;Lo;0;L;;;;;N;;;;; +112F;HANGUL CHOSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +1130;HANGUL CHOSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; +1131;HANGUL CHOSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; +1132;HANGUL CHOSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +1133;HANGUL CHOSEONG SIOS-PIEUP-KIYEOK;Lo;0;L;;;;;N;;;;; +1134;HANGUL CHOSEONG SIOS-SSANGSIOS;Lo;0;L;;;;;N;;;;; +1135;HANGUL CHOSEONG SIOS-IEUNG;Lo;0;L;;;;;N;;;;; +1136;HANGUL CHOSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +1137;HANGUL CHOSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; +1138;HANGUL CHOSEONG SIOS-KHIEUKH;Lo;0;L;;;;;N;;;;; +1139;HANGUL CHOSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +113A;HANGUL CHOSEONG SIOS-PHIEUPH;Lo;0;L;;;;;N;;;;; +113B;HANGUL CHOSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; +113C;HANGUL CHOSEONG CHITUEUMSIOS;Lo;0;L;;;;;N;;;;; +113D;HANGUL CHOSEONG CHITUEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; +113E;HANGUL CHOSEONG CEONGCHIEUMSIOS;Lo;0;L;;;;;N;;;;; +113F;HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS;Lo;0;L;;;;;N;;;;; +1140;HANGUL CHOSEONG PANSIOS;Lo;0;L;;;;;N;;;;; +1141;HANGUL CHOSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; +1142;HANGUL CHOSEONG IEUNG-TIKEUT;Lo;0;L;;;;;N;;;;; +1143;HANGUL CHOSEONG IEUNG-MIEUM;Lo;0;L;;;;;N;;;;; +1144;HANGUL CHOSEONG IEUNG-PIEUP;Lo;0;L;;;;;N;;;;; +1145;HANGUL CHOSEONG IEUNG-SIOS;Lo;0;L;;;;;N;;;;; +1146;HANGUL CHOSEONG IEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; +1147;HANGUL CHOSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; +1148;HANGUL CHOSEONG IEUNG-CIEUC;Lo;0;L;;;;;N;;;;; +1149;HANGUL CHOSEONG IEUNG-CHIEUCH;Lo;0;L;;;;;N;;;;; +114A;HANGUL CHOSEONG IEUNG-THIEUTH;Lo;0;L;;;;;N;;;;; +114B;HANGUL CHOSEONG IEUNG-PHIEUPH;Lo;0;L;;;;;N;;;;; +114C;HANGUL CHOSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; +114D;HANGUL CHOSEONG CIEUC-IEUNG;Lo;0;L;;;;;N;;;;; +114E;HANGUL CHOSEONG CHITUEUMCIEUC;Lo;0;L;;;;;N;;;;; +114F;HANGUL CHOSEONG CHITUEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; +1150;HANGUL CHOSEONG CEONGCHIEUMCIEUC;Lo;0;L;;;;;N;;;;; +1151;HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC;Lo;0;L;;;;;N;;;;; +1152;HANGUL CHOSEONG CHIEUCH-KHIEUKH;Lo;0;L;;;;;N;;;;; +1153;HANGUL CHOSEONG CHIEUCH-HIEUH;Lo;0;L;;;;;N;;;;; +1154;HANGUL CHOSEONG CHITUEUMCHIEUCH;Lo;0;L;;;;;N;;;;; +1155;HANGUL CHOSEONG CEONGCHIEUMCHIEUCH;Lo;0;L;;;;;N;;;;; +1156;HANGUL CHOSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; +1157;HANGUL CHOSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; +1158;HANGUL CHOSEONG SSANGHIEUH;Lo;0;L;;;;;N;;;;; +1159;HANGUL CHOSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; +115A;HANGUL CHOSEONG KIYEOK-TIKEUT;Lo;0;L;;;;;N;;;;; +115B;HANGUL CHOSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; +115C;HANGUL CHOSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; +115D;HANGUL CHOSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; +115E;HANGUL CHOSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; +115F;HANGUL CHOSEONG FILLER;Lo;0;L;;;;;N;;;;; +1160;HANGUL JUNGSEONG FILLER;Lo;0;L;;;;;N;;;;; +1161;HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;; +1162;HANGUL JUNGSEONG AE;Lo;0;L;;;;;N;;;;; +1163;HANGUL JUNGSEONG YA;Lo;0;L;;;;;N;;;;; +1164;HANGUL JUNGSEONG YAE;Lo;0;L;;;;;N;;;;; +1165;HANGUL JUNGSEONG EO;Lo;0;L;;;;;N;;;;; +1166;HANGUL JUNGSEONG E;Lo;0;L;;;;;N;;;;; +1167;HANGUL JUNGSEONG YEO;Lo;0;L;;;;;N;;;;; +1168;HANGUL JUNGSEONG YE;Lo;0;L;;;;;N;;;;; +1169;HANGUL JUNGSEONG O;Lo;0;L;;;;;N;;;;; +116A;HANGUL JUNGSEONG WA;Lo;0;L;;;;;N;;;;; +116B;HANGUL JUNGSEONG WAE;Lo;0;L;;;;;N;;;;; +116C;HANGUL JUNGSEONG OE;Lo;0;L;;;;;N;;;;; +116D;HANGUL JUNGSEONG YO;Lo;0;L;;;;;N;;;;; +116E;HANGUL JUNGSEONG U;Lo;0;L;;;;;N;;;;; +116F;HANGUL JUNGSEONG WEO;Lo;0;L;;;;;N;;;;; +1170;HANGUL JUNGSEONG WE;Lo;0;L;;;;;N;;;;; +1171;HANGUL JUNGSEONG WI;Lo;0;L;;;;;N;;;;; +1172;HANGUL JUNGSEONG YU;Lo;0;L;;;;;N;;;;; +1173;HANGUL JUNGSEONG EU;Lo;0;L;;;;;N;;;;; +1174;HANGUL JUNGSEONG YI;Lo;0;L;;;;;N;;;;; +1175;HANGUL JUNGSEONG I;Lo;0;L;;;;;N;;;;; +1176;HANGUL JUNGSEONG A-O;Lo;0;L;;;;;N;;;;; +1177;HANGUL JUNGSEONG A-U;Lo;0;L;;;;;N;;;;; +1178;HANGUL JUNGSEONG YA-O;Lo;0;L;;;;;N;;;;; +1179;HANGUL JUNGSEONG YA-YO;Lo;0;L;;;;;N;;;;; +117A;HANGUL JUNGSEONG EO-O;Lo;0;L;;;;;N;;;;; +117B;HANGUL JUNGSEONG EO-U;Lo;0;L;;;;;N;;;;; +117C;HANGUL JUNGSEONG EO-EU;Lo;0;L;;;;;N;;;;; +117D;HANGUL JUNGSEONG YEO-O;Lo;0;L;;;;;N;;;;; +117E;HANGUL JUNGSEONG YEO-U;Lo;0;L;;;;;N;;;;; +117F;HANGUL JUNGSEONG O-EO;Lo;0;L;;;;;N;;;;; +1180;HANGUL JUNGSEONG O-E;Lo;0;L;;;;;N;;;;; +1181;HANGUL JUNGSEONG O-YE;Lo;0;L;;;;;N;;;;; +1182;HANGUL JUNGSEONG O-O;Lo;0;L;;;;;N;;;;; +1183;HANGUL JUNGSEONG O-U;Lo;0;L;;;;;N;;;;; +1184;HANGUL JUNGSEONG YO-YA;Lo;0;L;;;;;N;;;;; +1185;HANGUL JUNGSEONG YO-YAE;Lo;0;L;;;;;N;;;;; +1186;HANGUL JUNGSEONG YO-YEO;Lo;0;L;;;;;N;;;;; +1187;HANGUL JUNGSEONG YO-O;Lo;0;L;;;;;N;;;;; +1188;HANGUL JUNGSEONG YO-I;Lo;0;L;;;;;N;;;;; +1189;HANGUL JUNGSEONG U-A;Lo;0;L;;;;;N;;;;; +118A;HANGUL JUNGSEONG U-AE;Lo;0;L;;;;;N;;;;; +118B;HANGUL JUNGSEONG U-EO-EU;Lo;0;L;;;;;N;;;;; +118C;HANGUL JUNGSEONG U-YE;Lo;0;L;;;;;N;;;;; +118D;HANGUL JUNGSEONG U-U;Lo;0;L;;;;;N;;;;; +118E;HANGUL JUNGSEONG YU-A;Lo;0;L;;;;;N;;;;; +118F;HANGUL JUNGSEONG YU-EO;Lo;0;L;;;;;N;;;;; +1190;HANGUL JUNGSEONG YU-E;Lo;0;L;;;;;N;;;;; +1191;HANGUL JUNGSEONG YU-YEO;Lo;0;L;;;;;N;;;;; +1192;HANGUL JUNGSEONG YU-YE;Lo;0;L;;;;;N;;;;; +1193;HANGUL JUNGSEONG YU-U;Lo;0;L;;;;;N;;;;; +1194;HANGUL JUNGSEONG YU-I;Lo;0;L;;;;;N;;;;; +1195;HANGUL JUNGSEONG EU-U;Lo;0;L;;;;;N;;;;; +1196;HANGUL JUNGSEONG EU-EU;Lo;0;L;;;;;N;;;;; +1197;HANGUL JUNGSEONG YI-U;Lo;0;L;;;;;N;;;;; +1198;HANGUL JUNGSEONG I-A;Lo;0;L;;;;;N;;;;; +1199;HANGUL JUNGSEONG I-YA;Lo;0;L;;;;;N;;;;; +119A;HANGUL JUNGSEONG I-O;Lo;0;L;;;;;N;;;;; +119B;HANGUL JUNGSEONG I-U;Lo;0;L;;;;;N;;;;; +119C;HANGUL JUNGSEONG I-EU;Lo;0;L;;;;;N;;;;; +119D;HANGUL JUNGSEONG I-ARAEA;Lo;0;L;;;;;N;;;;; +119E;HANGUL JUNGSEONG ARAEA;Lo;0;L;;;;;N;;;;; +119F;HANGUL JUNGSEONG ARAEA-EO;Lo;0;L;;;;;N;;;;; +11A0;HANGUL JUNGSEONG ARAEA-U;Lo;0;L;;;;;N;;;;; +11A1;HANGUL JUNGSEONG ARAEA-I;Lo;0;L;;;;;N;;;;; +11A2;HANGUL JUNGSEONG SSANGARAEA;Lo;0;L;;;;;N;;;;; +11A3;HANGUL JUNGSEONG A-EU;Lo;0;L;;;;;N;;;;; +11A4;HANGUL JUNGSEONG YA-U;Lo;0;L;;;;;N;;;;; +11A5;HANGUL JUNGSEONG YEO-YA;Lo;0;L;;;;;N;;;;; +11A6;HANGUL JUNGSEONG O-YA;Lo;0;L;;;;;N;;;;; +11A7;HANGUL JUNGSEONG O-YAE;Lo;0;L;;;;;N;;;;; +11A8;HANGUL JONGSEONG KIYEOK;Lo;0;L;;;;;N;;;;; +11A9;HANGUL JONGSEONG SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +11AA;HANGUL JONGSEONG KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; +11AB;HANGUL JONGSEONG NIEUN;Lo;0;L;;;;;N;;;;; +11AC;HANGUL JONGSEONG NIEUN-CIEUC;Lo;0;L;;;;;N;;;;; +11AD;HANGUL JONGSEONG NIEUN-HIEUH;Lo;0;L;;;;;N;;;;; +11AE;HANGUL JONGSEONG TIKEUT;Lo;0;L;;;;;N;;;;; +11AF;HANGUL JONGSEONG RIEUL;Lo;0;L;;;;;N;;;;; +11B0;HANGUL JONGSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; +11B1;HANGUL JONGSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; +11B2;HANGUL JONGSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; +11B3;HANGUL JONGSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; +11B4;HANGUL JONGSEONG RIEUL-THIEUTH;Lo;0;L;;;;;N;;;;; +11B5;HANGUL JONGSEONG RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; +11B6;HANGUL JONGSEONG RIEUL-HIEUH;Lo;0;L;;;;;N;;;;; +11B7;HANGUL JONGSEONG MIEUM;Lo;0;L;;;;;N;;;;; +11B8;HANGUL JONGSEONG PIEUP;Lo;0;L;;;;;N;;;;; +11B9;HANGUL JONGSEONG PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +11BA;HANGUL JONGSEONG SIOS;Lo;0;L;;;;;N;;;;; +11BB;HANGUL JONGSEONG SSANGSIOS;Lo;0;L;;;;;N;;;;; +11BC;HANGUL JONGSEONG IEUNG;Lo;0;L;;;;;N;;;;; +11BD;HANGUL JONGSEONG CIEUC;Lo;0;L;;;;;N;;;;; +11BE;HANGUL JONGSEONG CHIEUCH;Lo;0;L;;;;;N;;;;; +11BF;HANGUL JONGSEONG KHIEUKH;Lo;0;L;;;;;N;;;;; +11C0;HANGUL JONGSEONG THIEUTH;Lo;0;L;;;;;N;;;;; +11C1;HANGUL JONGSEONG PHIEUPH;Lo;0;L;;;;;N;;;;; +11C2;HANGUL JONGSEONG HIEUH;Lo;0;L;;;;;N;;;;; +11C3;HANGUL JONGSEONG KIYEOK-RIEUL;Lo;0;L;;;;;N;;;;; +11C4;HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +11C5;HANGUL JONGSEONG NIEUN-KIYEOK;Lo;0;L;;;;;N;;;;; +11C6;HANGUL JONGSEONG NIEUN-TIKEUT;Lo;0;L;;;;;N;;;;; +11C7;HANGUL JONGSEONG NIEUN-SIOS;Lo;0;L;;;;;N;;;;; +11C8;HANGUL JONGSEONG NIEUN-PANSIOS;Lo;0;L;;;;;N;;;;; +11C9;HANGUL JONGSEONG NIEUN-THIEUTH;Lo;0;L;;;;;N;;;;; +11CA;HANGUL JONGSEONG TIKEUT-KIYEOK;Lo;0;L;;;;;N;;;;; +11CB;HANGUL JONGSEONG TIKEUT-RIEUL;Lo;0;L;;;;;N;;;;; +11CC;HANGUL JONGSEONG RIEUL-KIYEOK-SIOS;Lo;0;L;;;;;N;;;;; +11CD;HANGUL JONGSEONG RIEUL-NIEUN;Lo;0;L;;;;;N;;;;; +11CE;HANGUL JONGSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; +11CF;HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH;Lo;0;L;;;;;N;;;;; +11D0;HANGUL JONGSEONG SSANGRIEUL;Lo;0;L;;;;;N;;;;; +11D1;HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +11D2;HANGUL JONGSEONG RIEUL-MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +11D3;HANGUL JONGSEONG RIEUL-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +11D4;HANGUL JONGSEONG RIEUL-PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +11D5;HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +11D6;HANGUL JONGSEONG RIEUL-SSANGSIOS;Lo;0;L;;;;;N;;;;; +11D7;HANGUL JONGSEONG RIEUL-PANSIOS;Lo;0;L;;;;;N;;;;; +11D8;HANGUL JONGSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +11D9;HANGUL JONGSEONG RIEUL-YEORINHIEUH;Lo;0;L;;;;;N;;;;; +11DA;HANGUL JONGSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +11DB;HANGUL JONGSEONG MIEUM-RIEUL;Lo;0;L;;;;;N;;;;; +11DC;HANGUL JONGSEONG MIEUM-PIEUP;Lo;0;L;;;;;N;;;;; +11DD;HANGUL JONGSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +11DE;HANGUL JONGSEONG MIEUM-SSANGSIOS;Lo;0;L;;;;;N;;;;; +11DF;HANGUL JONGSEONG MIEUM-PANSIOS;Lo;0;L;;;;;N;;;;; +11E0;HANGUL JONGSEONG MIEUM-CHIEUCH;Lo;0;L;;;;;N;;;;; +11E1;HANGUL JONGSEONG MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; +11E2;HANGUL JONGSEONG KAPYEOUNMIEUM;Lo;0;L;;;;;N;;;;; +11E3;HANGUL JONGSEONG PIEUP-RIEUL;Lo;0;L;;;;;N;;;;; +11E4;HANGUL JONGSEONG PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +11E5;HANGUL JONGSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +11E6;HANGUL JONGSEONG KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +11E7;HANGUL JONGSEONG SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +11E8;HANGUL JONGSEONG SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +11E9;HANGUL JONGSEONG SIOS-RIEUL;Lo;0;L;;;;;N;;;;; +11EA;HANGUL JONGSEONG SIOS-PIEUP;Lo;0;L;;;;;N;;;;; +11EB;HANGUL JONGSEONG PANSIOS;Lo;0;L;;;;;N;;;;; +11EC;HANGUL JONGSEONG IEUNG-KIYEOK;Lo;0;L;;;;;N;;;;; +11ED;HANGUL JONGSEONG IEUNG-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +11EE;HANGUL JONGSEONG SSANGIEUNG;Lo;0;L;;;;;N;;;;; +11EF;HANGUL JONGSEONG IEUNG-KHIEUKH;Lo;0;L;;;;;N;;;;; +11F0;HANGUL JONGSEONG YESIEUNG;Lo;0;L;;;;;N;;;;; +11F1;HANGUL JONGSEONG YESIEUNG-SIOS;Lo;0;L;;;;;N;;;;; +11F2;HANGUL JONGSEONG YESIEUNG-PANSIOS;Lo;0;L;;;;;N;;;;; +11F3;HANGUL JONGSEONG PHIEUPH-PIEUP;Lo;0;L;;;;;N;;;;; +11F4;HANGUL JONGSEONG KAPYEOUNPHIEUPH;Lo;0;L;;;;;N;;;;; +11F5;HANGUL JONGSEONG HIEUH-NIEUN;Lo;0;L;;;;;N;;;;; +11F6;HANGUL JONGSEONG HIEUH-RIEUL;Lo;0;L;;;;;N;;;;; +11F7;HANGUL JONGSEONG HIEUH-MIEUM;Lo;0;L;;;;;N;;;;; +11F8;HANGUL JONGSEONG HIEUH-PIEUP;Lo;0;L;;;;;N;;;;; +11F9;HANGUL JONGSEONG YEORINHIEUH;Lo;0;L;;;;;N;;;;; +11FA;HANGUL JONGSEONG KIYEOK-NIEUN;Lo;0;L;;;;;N;;;;; +11FB;HANGUL JONGSEONG KIYEOK-PIEUP;Lo;0;L;;;;;N;;;;; +11FC;HANGUL JONGSEONG KIYEOK-CHIEUCH;Lo;0;L;;;;;N;;;;; +11FD;HANGUL JONGSEONG KIYEOK-KHIEUKH;Lo;0;L;;;;;N;;;;; +11FE;HANGUL JONGSEONG KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; +11FF;HANGUL JONGSEONG SSANGNIEUN;Lo;0;L;;;;;N;;;;; +1200;ETHIOPIC SYLLABLE HA;Lo;0;L;;;;;N;;;;; +1201;ETHIOPIC SYLLABLE HU;Lo;0;L;;;;;N;;;;; +1202;ETHIOPIC SYLLABLE HI;Lo;0;L;;;;;N;;;;; +1203;ETHIOPIC SYLLABLE HAA;Lo;0;L;;;;;N;;;;; +1204;ETHIOPIC SYLLABLE HEE;Lo;0;L;;;;;N;;;;; +1205;ETHIOPIC SYLLABLE HE;Lo;0;L;;;;;N;;;;; +1206;ETHIOPIC SYLLABLE HO;Lo;0;L;;;;;N;;;;; +1207;ETHIOPIC SYLLABLE HOA;Lo;0;L;;;;;N;;;;; +1208;ETHIOPIC SYLLABLE LA;Lo;0;L;;;;;N;;;;; +1209;ETHIOPIC SYLLABLE LU;Lo;0;L;;;;;N;;;;; +120A;ETHIOPIC SYLLABLE LI;Lo;0;L;;;;;N;;;;; +120B;ETHIOPIC SYLLABLE LAA;Lo;0;L;;;;;N;;;;; +120C;ETHIOPIC SYLLABLE LEE;Lo;0;L;;;;;N;;;;; +120D;ETHIOPIC SYLLABLE LE;Lo;0;L;;;;;N;;;;; +120E;ETHIOPIC SYLLABLE LO;Lo;0;L;;;;;N;;;;; +120F;ETHIOPIC SYLLABLE LWA;Lo;0;L;;;;;N;;;;; +1210;ETHIOPIC SYLLABLE HHA;Lo;0;L;;;;;N;;;;; +1211;ETHIOPIC SYLLABLE HHU;Lo;0;L;;;;;N;;;;; +1212;ETHIOPIC SYLLABLE HHI;Lo;0;L;;;;;N;;;;; +1213;ETHIOPIC SYLLABLE HHAA;Lo;0;L;;;;;N;;;;; +1214;ETHIOPIC SYLLABLE HHEE;Lo;0;L;;;;;N;;;;; +1215;ETHIOPIC SYLLABLE HHE;Lo;0;L;;;;;N;;;;; +1216;ETHIOPIC SYLLABLE HHO;Lo;0;L;;;;;N;;;;; +1217;ETHIOPIC SYLLABLE HHWA;Lo;0;L;;;;;N;;;;; +1218;ETHIOPIC SYLLABLE MA;Lo;0;L;;;;;N;;;;; +1219;ETHIOPIC SYLLABLE MU;Lo;0;L;;;;;N;;;;; +121A;ETHIOPIC SYLLABLE MI;Lo;0;L;;;;;N;;;;; +121B;ETHIOPIC SYLLABLE MAA;Lo;0;L;;;;;N;;;;; +121C;ETHIOPIC SYLLABLE MEE;Lo;0;L;;;;;N;;;;; +121D;ETHIOPIC SYLLABLE ME;Lo;0;L;;;;;N;;;;; +121E;ETHIOPIC SYLLABLE MO;Lo;0;L;;;;;N;;;;; +121F;ETHIOPIC SYLLABLE MWA;Lo;0;L;;;;;N;;;;; +1220;ETHIOPIC SYLLABLE SZA;Lo;0;L;;;;;N;;;;; +1221;ETHIOPIC SYLLABLE SZU;Lo;0;L;;;;;N;;;;; +1222;ETHIOPIC SYLLABLE SZI;Lo;0;L;;;;;N;;;;; +1223;ETHIOPIC SYLLABLE SZAA;Lo;0;L;;;;;N;;;;; +1224;ETHIOPIC SYLLABLE SZEE;Lo;0;L;;;;;N;;;;; +1225;ETHIOPIC SYLLABLE SZE;Lo;0;L;;;;;N;;;;; +1226;ETHIOPIC SYLLABLE SZO;Lo;0;L;;;;;N;;;;; +1227;ETHIOPIC SYLLABLE SZWA;Lo;0;L;;;;;N;;;;; +1228;ETHIOPIC SYLLABLE RA;Lo;0;L;;;;;N;;;;; +1229;ETHIOPIC SYLLABLE RU;Lo;0;L;;;;;N;;;;; +122A;ETHIOPIC SYLLABLE RI;Lo;0;L;;;;;N;;;;; +122B;ETHIOPIC SYLLABLE RAA;Lo;0;L;;;;;N;;;;; +122C;ETHIOPIC SYLLABLE REE;Lo;0;L;;;;;N;;;;; +122D;ETHIOPIC SYLLABLE RE;Lo;0;L;;;;;N;;;;; +122E;ETHIOPIC SYLLABLE RO;Lo;0;L;;;;;N;;;;; +122F;ETHIOPIC SYLLABLE RWA;Lo;0;L;;;;;N;;;;; +1230;ETHIOPIC SYLLABLE SA;Lo;0;L;;;;;N;;;;; +1231;ETHIOPIC SYLLABLE SU;Lo;0;L;;;;;N;;;;; +1232;ETHIOPIC SYLLABLE SI;Lo;0;L;;;;;N;;;;; +1233;ETHIOPIC SYLLABLE SAA;Lo;0;L;;;;;N;;;;; +1234;ETHIOPIC SYLLABLE SEE;Lo;0;L;;;;;N;;;;; +1235;ETHIOPIC SYLLABLE SE;Lo;0;L;;;;;N;;;;; +1236;ETHIOPIC SYLLABLE SO;Lo;0;L;;;;;N;;;;; +1237;ETHIOPIC SYLLABLE SWA;Lo;0;L;;;;;N;;;;; +1238;ETHIOPIC SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +1239;ETHIOPIC SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +123A;ETHIOPIC SYLLABLE SHI;Lo;0;L;;;;;N;;;;; +123B;ETHIOPIC SYLLABLE SHAA;Lo;0;L;;;;;N;;;;; +123C;ETHIOPIC SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; +123D;ETHIOPIC SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +123E;ETHIOPIC SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +123F;ETHIOPIC SYLLABLE SHWA;Lo;0;L;;;;;N;;;;; +1240;ETHIOPIC SYLLABLE QA;Lo;0;L;;;;;N;;;;; +1241;ETHIOPIC SYLLABLE QU;Lo;0;L;;;;;N;;;;; +1242;ETHIOPIC SYLLABLE QI;Lo;0;L;;;;;N;;;;; +1243;ETHIOPIC SYLLABLE QAA;Lo;0;L;;;;;N;;;;; +1244;ETHIOPIC SYLLABLE QEE;Lo;0;L;;;;;N;;;;; +1245;ETHIOPIC SYLLABLE QE;Lo;0;L;;;;;N;;;;; +1246;ETHIOPIC SYLLABLE QO;Lo;0;L;;;;;N;;;;; +1247;ETHIOPIC SYLLABLE QOA;Lo;0;L;;;;;N;;;;; +1248;ETHIOPIC SYLLABLE QWA;Lo;0;L;;;;;N;;;;; +124A;ETHIOPIC SYLLABLE QWI;Lo;0;L;;;;;N;;;;; +124B;ETHIOPIC SYLLABLE QWAA;Lo;0;L;;;;;N;;;;; +124C;ETHIOPIC SYLLABLE QWEE;Lo;0;L;;;;;N;;;;; +124D;ETHIOPIC SYLLABLE QWE;Lo;0;L;;;;;N;;;;; +1250;ETHIOPIC SYLLABLE QHA;Lo;0;L;;;;;N;;;;; +1251;ETHIOPIC SYLLABLE QHU;Lo;0;L;;;;;N;;;;; +1252;ETHIOPIC SYLLABLE QHI;Lo;0;L;;;;;N;;;;; +1253;ETHIOPIC SYLLABLE QHAA;Lo;0;L;;;;;N;;;;; +1254;ETHIOPIC SYLLABLE QHEE;Lo;0;L;;;;;N;;;;; +1255;ETHIOPIC SYLLABLE QHE;Lo;0;L;;;;;N;;;;; +1256;ETHIOPIC SYLLABLE QHO;Lo;0;L;;;;;N;;;;; +1258;ETHIOPIC SYLLABLE QHWA;Lo;0;L;;;;;N;;;;; +125A;ETHIOPIC SYLLABLE QHWI;Lo;0;L;;;;;N;;;;; +125B;ETHIOPIC SYLLABLE QHWAA;Lo;0;L;;;;;N;;;;; +125C;ETHIOPIC SYLLABLE QHWEE;Lo;0;L;;;;;N;;;;; +125D;ETHIOPIC SYLLABLE QHWE;Lo;0;L;;;;;N;;;;; +1260;ETHIOPIC SYLLABLE BA;Lo;0;L;;;;;N;;;;; +1261;ETHIOPIC SYLLABLE BU;Lo;0;L;;;;;N;;;;; +1262;ETHIOPIC SYLLABLE BI;Lo;0;L;;;;;N;;;;; +1263;ETHIOPIC SYLLABLE BAA;Lo;0;L;;;;;N;;;;; +1264;ETHIOPIC SYLLABLE BEE;Lo;0;L;;;;;N;;;;; +1265;ETHIOPIC SYLLABLE BE;Lo;0;L;;;;;N;;;;; +1266;ETHIOPIC SYLLABLE BO;Lo;0;L;;;;;N;;;;; +1267;ETHIOPIC SYLLABLE BWA;Lo;0;L;;;;;N;;;;; +1268;ETHIOPIC SYLLABLE VA;Lo;0;L;;;;;N;;;;; +1269;ETHIOPIC SYLLABLE VU;Lo;0;L;;;;;N;;;;; +126A;ETHIOPIC SYLLABLE VI;Lo;0;L;;;;;N;;;;; +126B;ETHIOPIC SYLLABLE VAA;Lo;0;L;;;;;N;;;;; +126C;ETHIOPIC SYLLABLE VEE;Lo;0;L;;;;;N;;;;; +126D;ETHIOPIC SYLLABLE VE;Lo;0;L;;;;;N;;;;; +126E;ETHIOPIC SYLLABLE VO;Lo;0;L;;;;;N;;;;; +126F;ETHIOPIC SYLLABLE VWA;Lo;0;L;;;;;N;;;;; +1270;ETHIOPIC SYLLABLE TA;Lo;0;L;;;;;N;;;;; +1271;ETHIOPIC SYLLABLE TU;Lo;0;L;;;;;N;;;;; +1272;ETHIOPIC SYLLABLE TI;Lo;0;L;;;;;N;;;;; +1273;ETHIOPIC SYLLABLE TAA;Lo;0;L;;;;;N;;;;; +1274;ETHIOPIC SYLLABLE TEE;Lo;0;L;;;;;N;;;;; +1275;ETHIOPIC SYLLABLE TE;Lo;0;L;;;;;N;;;;; +1276;ETHIOPIC SYLLABLE TO;Lo;0;L;;;;;N;;;;; +1277;ETHIOPIC SYLLABLE TWA;Lo;0;L;;;;;N;;;;; +1278;ETHIOPIC SYLLABLE CA;Lo;0;L;;;;;N;;;;; +1279;ETHIOPIC SYLLABLE CU;Lo;0;L;;;;;N;;;;; +127A;ETHIOPIC SYLLABLE CI;Lo;0;L;;;;;N;;;;; +127B;ETHIOPIC SYLLABLE CAA;Lo;0;L;;;;;N;;;;; +127C;ETHIOPIC SYLLABLE CEE;Lo;0;L;;;;;N;;;;; +127D;ETHIOPIC SYLLABLE CE;Lo;0;L;;;;;N;;;;; +127E;ETHIOPIC SYLLABLE CO;Lo;0;L;;;;;N;;;;; +127F;ETHIOPIC SYLLABLE CWA;Lo;0;L;;;;;N;;;;; +1280;ETHIOPIC SYLLABLE XA;Lo;0;L;;;;;N;;;;; +1281;ETHIOPIC SYLLABLE XU;Lo;0;L;;;;;N;;;;; +1282;ETHIOPIC SYLLABLE XI;Lo;0;L;;;;;N;;;;; +1283;ETHIOPIC SYLLABLE XAA;Lo;0;L;;;;;N;;;;; +1284;ETHIOPIC SYLLABLE XEE;Lo;0;L;;;;;N;;;;; +1285;ETHIOPIC SYLLABLE XE;Lo;0;L;;;;;N;;;;; +1286;ETHIOPIC SYLLABLE XO;Lo;0;L;;;;;N;;;;; +1287;ETHIOPIC SYLLABLE XOA;Lo;0;L;;;;;N;;;;; +1288;ETHIOPIC SYLLABLE XWA;Lo;0;L;;;;;N;;;;; +128A;ETHIOPIC SYLLABLE XWI;Lo;0;L;;;;;N;;;;; +128B;ETHIOPIC SYLLABLE XWAA;Lo;0;L;;;;;N;;;;; +128C;ETHIOPIC SYLLABLE XWEE;Lo;0;L;;;;;N;;;;; +128D;ETHIOPIC SYLLABLE XWE;Lo;0;L;;;;;N;;;;; +1290;ETHIOPIC SYLLABLE NA;Lo;0;L;;;;;N;;;;; +1291;ETHIOPIC SYLLABLE NU;Lo;0;L;;;;;N;;;;; +1292;ETHIOPIC SYLLABLE NI;Lo;0;L;;;;;N;;;;; +1293;ETHIOPIC SYLLABLE NAA;Lo;0;L;;;;;N;;;;; +1294;ETHIOPIC SYLLABLE NEE;Lo;0;L;;;;;N;;;;; +1295;ETHIOPIC SYLLABLE NE;Lo;0;L;;;;;N;;;;; +1296;ETHIOPIC SYLLABLE NO;Lo;0;L;;;;;N;;;;; +1297;ETHIOPIC SYLLABLE NWA;Lo;0;L;;;;;N;;;;; +1298;ETHIOPIC SYLLABLE NYA;Lo;0;L;;;;;N;;;;; +1299;ETHIOPIC SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +129A;ETHIOPIC SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +129B;ETHIOPIC SYLLABLE NYAA;Lo;0;L;;;;;N;;;;; +129C;ETHIOPIC SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; +129D;ETHIOPIC SYLLABLE NYE;Lo;0;L;;;;;N;;;;; +129E;ETHIOPIC SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +129F;ETHIOPIC SYLLABLE NYWA;Lo;0;L;;;;;N;;;;; +12A0;ETHIOPIC SYLLABLE GLOTTAL A;Lo;0;L;;;;;N;;;;; +12A1;ETHIOPIC SYLLABLE GLOTTAL U;Lo;0;L;;;;;N;;;;; +12A2;ETHIOPIC SYLLABLE GLOTTAL I;Lo;0;L;;;;;N;;;;; +12A3;ETHIOPIC SYLLABLE GLOTTAL AA;Lo;0;L;;;;;N;;;;; +12A4;ETHIOPIC SYLLABLE GLOTTAL EE;Lo;0;L;;;;;N;;;;; +12A5;ETHIOPIC SYLLABLE GLOTTAL E;Lo;0;L;;;;;N;;;;; +12A6;ETHIOPIC SYLLABLE GLOTTAL O;Lo;0;L;;;;;N;;;;; +12A7;ETHIOPIC SYLLABLE GLOTTAL WA;Lo;0;L;;;;;N;;;;; +12A8;ETHIOPIC SYLLABLE KA;Lo;0;L;;;;;N;;;;; +12A9;ETHIOPIC SYLLABLE KU;Lo;0;L;;;;;N;;;;; +12AA;ETHIOPIC SYLLABLE KI;Lo;0;L;;;;;N;;;;; +12AB;ETHIOPIC SYLLABLE KAA;Lo;0;L;;;;;N;;;;; +12AC;ETHIOPIC SYLLABLE KEE;Lo;0;L;;;;;N;;;;; +12AD;ETHIOPIC SYLLABLE KE;Lo;0;L;;;;;N;;;;; +12AE;ETHIOPIC SYLLABLE KO;Lo;0;L;;;;;N;;;;; +12AF;ETHIOPIC SYLLABLE KOA;Lo;0;L;;;;;N;;;;; +12B0;ETHIOPIC SYLLABLE KWA;Lo;0;L;;;;;N;;;;; +12B2;ETHIOPIC SYLLABLE KWI;Lo;0;L;;;;;N;;;;; +12B3;ETHIOPIC SYLLABLE KWAA;Lo;0;L;;;;;N;;;;; +12B4;ETHIOPIC SYLLABLE KWEE;Lo;0;L;;;;;N;;;;; +12B5;ETHIOPIC SYLLABLE KWE;Lo;0;L;;;;;N;;;;; +12B8;ETHIOPIC SYLLABLE KXA;Lo;0;L;;;;;N;;;;; +12B9;ETHIOPIC SYLLABLE KXU;Lo;0;L;;;;;N;;;;; +12BA;ETHIOPIC SYLLABLE KXI;Lo;0;L;;;;;N;;;;; +12BB;ETHIOPIC SYLLABLE KXAA;Lo;0;L;;;;;N;;;;; +12BC;ETHIOPIC SYLLABLE KXEE;Lo;0;L;;;;;N;;;;; +12BD;ETHIOPIC SYLLABLE KXE;Lo;0;L;;;;;N;;;;; +12BE;ETHIOPIC SYLLABLE KXO;Lo;0;L;;;;;N;;;;; +12C0;ETHIOPIC SYLLABLE KXWA;Lo;0;L;;;;;N;;;;; +12C2;ETHIOPIC SYLLABLE KXWI;Lo;0;L;;;;;N;;;;; +12C3;ETHIOPIC SYLLABLE KXWAA;Lo;0;L;;;;;N;;;;; +12C4;ETHIOPIC SYLLABLE KXWEE;Lo;0;L;;;;;N;;;;; +12C5;ETHIOPIC SYLLABLE KXWE;Lo;0;L;;;;;N;;;;; +12C8;ETHIOPIC SYLLABLE WA;Lo;0;L;;;;;N;;;;; +12C9;ETHIOPIC SYLLABLE WU;Lo;0;L;;;;;N;;;;; +12CA;ETHIOPIC SYLLABLE WI;Lo;0;L;;;;;N;;;;; +12CB;ETHIOPIC SYLLABLE WAA;Lo;0;L;;;;;N;;;;; +12CC;ETHIOPIC SYLLABLE WEE;Lo;0;L;;;;;N;;;;; +12CD;ETHIOPIC SYLLABLE WE;Lo;0;L;;;;;N;;;;; +12CE;ETHIOPIC SYLLABLE WO;Lo;0;L;;;;;N;;;;; +12CF;ETHIOPIC SYLLABLE WOA;Lo;0;L;;;;;N;;;;; +12D0;ETHIOPIC SYLLABLE PHARYNGEAL A;Lo;0;L;;;;;N;;;;; +12D1;ETHIOPIC SYLLABLE PHARYNGEAL U;Lo;0;L;;;;;N;;;;; +12D2;ETHIOPIC SYLLABLE PHARYNGEAL I;Lo;0;L;;;;;N;;;;; +12D3;ETHIOPIC SYLLABLE PHARYNGEAL AA;Lo;0;L;;;;;N;;;;; +12D4;ETHIOPIC SYLLABLE PHARYNGEAL EE;Lo;0;L;;;;;N;;;;; +12D5;ETHIOPIC SYLLABLE PHARYNGEAL E;Lo;0;L;;;;;N;;;;; +12D6;ETHIOPIC SYLLABLE PHARYNGEAL O;Lo;0;L;;;;;N;;;;; +12D8;ETHIOPIC SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +12D9;ETHIOPIC SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +12DA;ETHIOPIC SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +12DB;ETHIOPIC SYLLABLE ZAA;Lo;0;L;;;;;N;;;;; +12DC;ETHIOPIC SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; +12DD;ETHIOPIC SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +12DE;ETHIOPIC SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +12DF;ETHIOPIC SYLLABLE ZWA;Lo;0;L;;;;;N;;;;; +12E0;ETHIOPIC SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +12E1;ETHIOPIC SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +12E2;ETHIOPIC SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; +12E3;ETHIOPIC SYLLABLE ZHAA;Lo;0;L;;;;;N;;;;; +12E4;ETHIOPIC SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; +12E5;ETHIOPIC SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +12E6;ETHIOPIC SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +12E7;ETHIOPIC SYLLABLE ZHWA;Lo;0;L;;;;;N;;;;; +12E8;ETHIOPIC SYLLABLE YA;Lo;0;L;;;;;N;;;;; +12E9;ETHIOPIC SYLLABLE YU;Lo;0;L;;;;;N;;;;; +12EA;ETHIOPIC SYLLABLE YI;Lo;0;L;;;;;N;;;;; +12EB;ETHIOPIC SYLLABLE YAA;Lo;0;L;;;;;N;;;;; +12EC;ETHIOPIC SYLLABLE YEE;Lo;0;L;;;;;N;;;;; +12ED;ETHIOPIC SYLLABLE YE;Lo;0;L;;;;;N;;;;; +12EE;ETHIOPIC SYLLABLE YO;Lo;0;L;;;;;N;;;;; +12EF;ETHIOPIC SYLLABLE YOA;Lo;0;L;;;;;N;;;;; +12F0;ETHIOPIC SYLLABLE DA;Lo;0;L;;;;;N;;;;; +12F1;ETHIOPIC SYLLABLE DU;Lo;0;L;;;;;N;;;;; +12F2;ETHIOPIC SYLLABLE DI;Lo;0;L;;;;;N;;;;; +12F3;ETHIOPIC SYLLABLE DAA;Lo;0;L;;;;;N;;;;; +12F4;ETHIOPIC SYLLABLE DEE;Lo;0;L;;;;;N;;;;; +12F5;ETHIOPIC SYLLABLE DE;Lo;0;L;;;;;N;;;;; +12F6;ETHIOPIC SYLLABLE DO;Lo;0;L;;;;;N;;;;; +12F7;ETHIOPIC SYLLABLE DWA;Lo;0;L;;;;;N;;;;; +12F8;ETHIOPIC SYLLABLE DDA;Lo;0;L;;;;;N;;;;; +12F9;ETHIOPIC SYLLABLE DDU;Lo;0;L;;;;;N;;;;; +12FA;ETHIOPIC SYLLABLE DDI;Lo;0;L;;;;;N;;;;; +12FB;ETHIOPIC SYLLABLE DDAA;Lo;0;L;;;;;N;;;;; +12FC;ETHIOPIC SYLLABLE DDEE;Lo;0;L;;;;;N;;;;; +12FD;ETHIOPIC SYLLABLE DDE;Lo;0;L;;;;;N;;;;; +12FE;ETHIOPIC SYLLABLE DDO;Lo;0;L;;;;;N;;;;; +12FF;ETHIOPIC SYLLABLE DDWA;Lo;0;L;;;;;N;;;;; +1300;ETHIOPIC SYLLABLE JA;Lo;0;L;;;;;N;;;;; +1301;ETHIOPIC SYLLABLE JU;Lo;0;L;;;;;N;;;;; +1302;ETHIOPIC SYLLABLE JI;Lo;0;L;;;;;N;;;;; +1303;ETHIOPIC SYLLABLE JAA;Lo;0;L;;;;;N;;;;; +1304;ETHIOPIC SYLLABLE JEE;Lo;0;L;;;;;N;;;;; +1305;ETHIOPIC SYLLABLE JE;Lo;0;L;;;;;N;;;;; +1306;ETHIOPIC SYLLABLE JO;Lo;0;L;;;;;N;;;;; +1307;ETHIOPIC SYLLABLE JWA;Lo;0;L;;;;;N;;;;; +1308;ETHIOPIC SYLLABLE GA;Lo;0;L;;;;;N;;;;; +1309;ETHIOPIC SYLLABLE GU;Lo;0;L;;;;;N;;;;; +130A;ETHIOPIC SYLLABLE GI;Lo;0;L;;;;;N;;;;; +130B;ETHIOPIC SYLLABLE GAA;Lo;0;L;;;;;N;;;;; +130C;ETHIOPIC SYLLABLE GEE;Lo;0;L;;;;;N;;;;; +130D;ETHIOPIC SYLLABLE GE;Lo;0;L;;;;;N;;;;; +130E;ETHIOPIC SYLLABLE GO;Lo;0;L;;;;;N;;;;; +130F;ETHIOPIC SYLLABLE GOA;Lo;0;L;;;;;N;;;;; +1310;ETHIOPIC SYLLABLE GWA;Lo;0;L;;;;;N;;;;; +1312;ETHIOPIC SYLLABLE GWI;Lo;0;L;;;;;N;;;;; +1313;ETHIOPIC SYLLABLE GWAA;Lo;0;L;;;;;N;;;;; +1314;ETHIOPIC SYLLABLE GWEE;Lo;0;L;;;;;N;;;;; +1315;ETHIOPIC SYLLABLE GWE;Lo;0;L;;;;;N;;;;; +1318;ETHIOPIC SYLLABLE GGA;Lo;0;L;;;;;N;;;;; +1319;ETHIOPIC SYLLABLE GGU;Lo;0;L;;;;;N;;;;; +131A;ETHIOPIC SYLLABLE GGI;Lo;0;L;;;;;N;;;;; +131B;ETHIOPIC SYLLABLE GGAA;Lo;0;L;;;;;N;;;;; +131C;ETHIOPIC SYLLABLE GGEE;Lo;0;L;;;;;N;;;;; +131D;ETHIOPIC SYLLABLE GGE;Lo;0;L;;;;;N;;;;; +131E;ETHIOPIC SYLLABLE GGO;Lo;0;L;;;;;N;;;;; +131F;ETHIOPIC SYLLABLE GGWAA;Lo;0;L;;;;;N;;;;; +1320;ETHIOPIC SYLLABLE THA;Lo;0;L;;;;;N;;;;; +1321;ETHIOPIC SYLLABLE THU;Lo;0;L;;;;;N;;;;; +1322;ETHIOPIC SYLLABLE THI;Lo;0;L;;;;;N;;;;; +1323;ETHIOPIC SYLLABLE THAA;Lo;0;L;;;;;N;;;;; +1324;ETHIOPIC SYLLABLE THEE;Lo;0;L;;;;;N;;;;; +1325;ETHIOPIC SYLLABLE THE;Lo;0;L;;;;;N;;;;; +1326;ETHIOPIC SYLLABLE THO;Lo;0;L;;;;;N;;;;; +1327;ETHIOPIC SYLLABLE THWA;Lo;0;L;;;;;N;;;;; +1328;ETHIOPIC SYLLABLE CHA;Lo;0;L;;;;;N;;;;; +1329;ETHIOPIC SYLLABLE CHU;Lo;0;L;;;;;N;;;;; +132A;ETHIOPIC SYLLABLE CHI;Lo;0;L;;;;;N;;;;; +132B;ETHIOPIC SYLLABLE CHAA;Lo;0;L;;;;;N;;;;; +132C;ETHIOPIC SYLLABLE CHEE;Lo;0;L;;;;;N;;;;; +132D;ETHIOPIC SYLLABLE CHE;Lo;0;L;;;;;N;;;;; +132E;ETHIOPIC SYLLABLE CHO;Lo;0;L;;;;;N;;;;; +132F;ETHIOPIC SYLLABLE CHWA;Lo;0;L;;;;;N;;;;; +1330;ETHIOPIC SYLLABLE PHA;Lo;0;L;;;;;N;;;;; +1331;ETHIOPIC SYLLABLE PHU;Lo;0;L;;;;;N;;;;; +1332;ETHIOPIC SYLLABLE PHI;Lo;0;L;;;;;N;;;;; +1333;ETHIOPIC SYLLABLE PHAA;Lo;0;L;;;;;N;;;;; +1334;ETHIOPIC SYLLABLE PHEE;Lo;0;L;;;;;N;;;;; +1335;ETHIOPIC SYLLABLE PHE;Lo;0;L;;;;;N;;;;; +1336;ETHIOPIC SYLLABLE PHO;Lo;0;L;;;;;N;;;;; +1337;ETHIOPIC SYLLABLE PHWA;Lo;0;L;;;;;N;;;;; +1338;ETHIOPIC SYLLABLE TSA;Lo;0;L;;;;;N;;;;; +1339;ETHIOPIC SYLLABLE TSU;Lo;0;L;;;;;N;;;;; +133A;ETHIOPIC SYLLABLE TSI;Lo;0;L;;;;;N;;;;; +133B;ETHIOPIC SYLLABLE TSAA;Lo;0;L;;;;;N;;;;; +133C;ETHIOPIC SYLLABLE TSEE;Lo;0;L;;;;;N;;;;; +133D;ETHIOPIC SYLLABLE TSE;Lo;0;L;;;;;N;;;;; +133E;ETHIOPIC SYLLABLE TSO;Lo;0;L;;;;;N;;;;; +133F;ETHIOPIC SYLLABLE TSWA;Lo;0;L;;;;;N;;;;; +1340;ETHIOPIC SYLLABLE TZA;Lo;0;L;;;;;N;;;;; +1341;ETHIOPIC SYLLABLE TZU;Lo;0;L;;;;;N;;;;; +1342;ETHIOPIC SYLLABLE TZI;Lo;0;L;;;;;N;;;;; +1343;ETHIOPIC SYLLABLE TZAA;Lo;0;L;;;;;N;;;;; +1344;ETHIOPIC SYLLABLE TZEE;Lo;0;L;;;;;N;;;;; +1345;ETHIOPIC SYLLABLE TZE;Lo;0;L;;;;;N;;;;; +1346;ETHIOPIC SYLLABLE TZO;Lo;0;L;;;;;N;;;;; +1347;ETHIOPIC SYLLABLE TZOA;Lo;0;L;;;;;N;;;;; +1348;ETHIOPIC SYLLABLE FA;Lo;0;L;;;;;N;;;;; +1349;ETHIOPIC SYLLABLE FU;Lo;0;L;;;;;N;;;;; +134A;ETHIOPIC SYLLABLE FI;Lo;0;L;;;;;N;;;;; +134B;ETHIOPIC SYLLABLE FAA;Lo;0;L;;;;;N;;;;; +134C;ETHIOPIC SYLLABLE FEE;Lo;0;L;;;;;N;;;;; +134D;ETHIOPIC SYLLABLE FE;Lo;0;L;;;;;N;;;;; +134E;ETHIOPIC SYLLABLE FO;Lo;0;L;;;;;N;;;;; +134F;ETHIOPIC SYLLABLE FWA;Lo;0;L;;;;;N;;;;; +1350;ETHIOPIC SYLLABLE PA;Lo;0;L;;;;;N;;;;; +1351;ETHIOPIC SYLLABLE PU;Lo;0;L;;;;;N;;;;; +1352;ETHIOPIC SYLLABLE PI;Lo;0;L;;;;;N;;;;; +1353;ETHIOPIC SYLLABLE PAA;Lo;0;L;;;;;N;;;;; +1354;ETHIOPIC SYLLABLE PEE;Lo;0;L;;;;;N;;;;; +1355;ETHIOPIC SYLLABLE PE;Lo;0;L;;;;;N;;;;; +1356;ETHIOPIC SYLLABLE PO;Lo;0;L;;;;;N;;;;; +1357;ETHIOPIC SYLLABLE PWA;Lo;0;L;;;;;N;;;;; +1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; +1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; +135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; +135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; +135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; +135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +1360;ETHIOPIC SECTION MARK;Po;0;L;;;;;N;;;;; +1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; +1362;ETHIOPIC FULL STOP;Po;0;L;;;;;N;;;;; +1363;ETHIOPIC COMMA;Po;0;L;;;;;N;;;;; +1364;ETHIOPIC SEMICOLON;Po;0;L;;;;;N;;;;; +1365;ETHIOPIC COLON;Po;0;L;;;;;N;;;;; +1366;ETHIOPIC PREFACE COLON;Po;0;L;;;;;N;;;;; +1367;ETHIOPIC QUESTION MARK;Po;0;L;;;;;N;;;;; +1368;ETHIOPIC PARAGRAPH SEPARATOR;Po;0;L;;;;;N;;;;; +1369;ETHIOPIC DIGIT ONE;No;0;L;;;1;1;N;;;;; +136A;ETHIOPIC DIGIT TWO;No;0;L;;;2;2;N;;;;; +136B;ETHIOPIC DIGIT THREE;No;0;L;;;3;3;N;;;;; +136C;ETHIOPIC DIGIT FOUR;No;0;L;;;4;4;N;;;;; +136D;ETHIOPIC DIGIT FIVE;No;0;L;;;5;5;N;;;;; +136E;ETHIOPIC DIGIT SIX;No;0;L;;;6;6;N;;;;; +136F;ETHIOPIC DIGIT SEVEN;No;0;L;;;7;7;N;;;;; +1370;ETHIOPIC DIGIT EIGHT;No;0;L;;;8;8;N;;;;; +1371;ETHIOPIC DIGIT NINE;No;0;L;;;9;9;N;;;;; +1372;ETHIOPIC NUMBER TEN;No;0;L;;;;10;N;;;;; +1373;ETHIOPIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; +1374;ETHIOPIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; +1375;ETHIOPIC NUMBER FORTY;No;0;L;;;;40;N;;;;; +1376;ETHIOPIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; +1377;ETHIOPIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; +1378;ETHIOPIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +1379;ETHIOPIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +137A;ETHIOPIC NUMBER NINETY;No;0;L;;;;90;N;;;;; +137B;ETHIOPIC NUMBER HUNDRED;No;0;L;;;;100;N;;;;; +137C;ETHIOPIC NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; +1380;ETHIOPIC SYLLABLE SEBATBEIT MWA;Lo;0;L;;;;;N;;;;; +1381;ETHIOPIC SYLLABLE MWI;Lo;0;L;;;;;N;;;;; +1382;ETHIOPIC SYLLABLE MWEE;Lo;0;L;;;;;N;;;;; +1383;ETHIOPIC SYLLABLE MWE;Lo;0;L;;;;;N;;;;; +1384;ETHIOPIC SYLLABLE SEBATBEIT BWA;Lo;0;L;;;;;N;;;;; +1385;ETHIOPIC SYLLABLE BWI;Lo;0;L;;;;;N;;;;; +1386;ETHIOPIC SYLLABLE BWEE;Lo;0;L;;;;;N;;;;; +1387;ETHIOPIC SYLLABLE BWE;Lo;0;L;;;;;N;;;;; +1388;ETHIOPIC SYLLABLE SEBATBEIT FWA;Lo;0;L;;;;;N;;;;; +1389;ETHIOPIC SYLLABLE FWI;Lo;0;L;;;;;N;;;;; +138A;ETHIOPIC SYLLABLE FWEE;Lo;0;L;;;;;N;;;;; +138B;ETHIOPIC SYLLABLE FWE;Lo;0;L;;;;;N;;;;; +138C;ETHIOPIC SYLLABLE SEBATBEIT PWA;Lo;0;L;;;;;N;;;;; +138D;ETHIOPIC SYLLABLE PWI;Lo;0;L;;;;;N;;;;; +138E;ETHIOPIC SYLLABLE PWEE;Lo;0;L;;;;;N;;;;; +138F;ETHIOPIC SYLLABLE PWE;Lo;0;L;;;;;N;;;;; +1390;ETHIOPIC TONAL MARK YIZET;So;0;ON;;;;;N;;;;; +1391;ETHIOPIC TONAL MARK DERET;So;0;ON;;;;;N;;;;; +1392;ETHIOPIC TONAL MARK RIKRIK;So;0;ON;;;;;N;;;;; +1393;ETHIOPIC TONAL MARK SHORT RIKRIK;So;0;ON;;;;;N;;;;; +1394;ETHIOPIC TONAL MARK DIFAT;So;0;ON;;;;;N;;;;; +1395;ETHIOPIC TONAL MARK KENAT;So;0;ON;;;;;N;;;;; +1396;ETHIOPIC TONAL MARK CHIRET;So;0;ON;;;;;N;;;;; +1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;; +1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;; +1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;; +13A0;CHEROKEE LETTER A;Lu;0;L;;;;;N;;;;AB70; +13A1;CHEROKEE LETTER E;Lu;0;L;;;;;N;;;;AB71; +13A2;CHEROKEE LETTER I;Lu;0;L;;;;;N;;;;AB72; +13A3;CHEROKEE LETTER O;Lu;0;L;;;;;N;;;;AB73; +13A4;CHEROKEE LETTER U;Lu;0;L;;;;;N;;;;AB74; +13A5;CHEROKEE LETTER V;Lu;0;L;;;;;N;;;;AB75; +13A6;CHEROKEE LETTER GA;Lu;0;L;;;;;N;;;;AB76; +13A7;CHEROKEE LETTER KA;Lu;0;L;;;;;N;;;;AB77; +13A8;CHEROKEE LETTER GE;Lu;0;L;;;;;N;;;;AB78; +13A9;CHEROKEE LETTER GI;Lu;0;L;;;;;N;;;;AB79; +13AA;CHEROKEE LETTER GO;Lu;0;L;;;;;N;;;;AB7A; +13AB;CHEROKEE LETTER GU;Lu;0;L;;;;;N;;;;AB7B; +13AC;CHEROKEE LETTER GV;Lu;0;L;;;;;N;;;;AB7C; +13AD;CHEROKEE LETTER HA;Lu;0;L;;;;;N;;;;AB7D; +13AE;CHEROKEE LETTER HE;Lu;0;L;;;;;N;;;;AB7E; +13AF;CHEROKEE LETTER HI;Lu;0;L;;;;;N;;;;AB7F; +13B0;CHEROKEE LETTER HO;Lu;0;L;;;;;N;;;;AB80; +13B1;CHEROKEE LETTER HU;Lu;0;L;;;;;N;;;;AB81; +13B2;CHEROKEE LETTER HV;Lu;0;L;;;;;N;;;;AB82; +13B3;CHEROKEE LETTER LA;Lu;0;L;;;;;N;;;;AB83; +13B4;CHEROKEE LETTER LE;Lu;0;L;;;;;N;;;;AB84; +13B5;CHEROKEE LETTER LI;Lu;0;L;;;;;N;;;;AB85; +13B6;CHEROKEE LETTER LO;Lu;0;L;;;;;N;;;;AB86; +13B7;CHEROKEE LETTER LU;Lu;0;L;;;;;N;;;;AB87; +13B8;CHEROKEE LETTER LV;Lu;0;L;;;;;N;;;;AB88; +13B9;CHEROKEE LETTER MA;Lu;0;L;;;;;N;;;;AB89; +13BA;CHEROKEE LETTER ME;Lu;0;L;;;;;N;;;;AB8A; +13BB;CHEROKEE LETTER MI;Lu;0;L;;;;;N;;;;AB8B; +13BC;CHEROKEE LETTER MO;Lu;0;L;;;;;N;;;;AB8C; +13BD;CHEROKEE LETTER MU;Lu;0;L;;;;;N;;;;AB8D; +13BE;CHEROKEE LETTER NA;Lu;0;L;;;;;N;;;;AB8E; +13BF;CHEROKEE LETTER HNA;Lu;0;L;;;;;N;;;;AB8F; +13C0;CHEROKEE LETTER NAH;Lu;0;L;;;;;N;;;;AB90; +13C1;CHEROKEE LETTER NE;Lu;0;L;;;;;N;;;;AB91; +13C2;CHEROKEE LETTER NI;Lu;0;L;;;;;N;;;;AB92; +13C3;CHEROKEE LETTER NO;Lu;0;L;;;;;N;;;;AB93; +13C4;CHEROKEE LETTER NU;Lu;0;L;;;;;N;;;;AB94; +13C5;CHEROKEE LETTER NV;Lu;0;L;;;;;N;;;;AB95; +13C6;CHEROKEE LETTER QUA;Lu;0;L;;;;;N;;;;AB96; +13C7;CHEROKEE LETTER QUE;Lu;0;L;;;;;N;;;;AB97; +13C8;CHEROKEE LETTER QUI;Lu;0;L;;;;;N;;;;AB98; +13C9;CHEROKEE LETTER QUO;Lu;0;L;;;;;N;;;;AB99; +13CA;CHEROKEE LETTER QUU;Lu;0;L;;;;;N;;;;AB9A; +13CB;CHEROKEE LETTER QUV;Lu;0;L;;;;;N;;;;AB9B; +13CC;CHEROKEE LETTER SA;Lu;0;L;;;;;N;;;;AB9C; +13CD;CHEROKEE LETTER S;Lu;0;L;;;;;N;;;;AB9D; +13CE;CHEROKEE LETTER SE;Lu;0;L;;;;;N;;;;AB9E; +13CF;CHEROKEE LETTER SI;Lu;0;L;;;;;N;;;;AB9F; +13D0;CHEROKEE LETTER SO;Lu;0;L;;;;;N;;;;ABA0; +13D1;CHEROKEE LETTER SU;Lu;0;L;;;;;N;;;;ABA1; +13D2;CHEROKEE LETTER SV;Lu;0;L;;;;;N;;;;ABA2; +13D3;CHEROKEE LETTER DA;Lu;0;L;;;;;N;;;;ABA3; +13D4;CHEROKEE LETTER TA;Lu;0;L;;;;;N;;;;ABA4; +13D5;CHEROKEE LETTER DE;Lu;0;L;;;;;N;;;;ABA5; +13D6;CHEROKEE LETTER TE;Lu;0;L;;;;;N;;;;ABA6; +13D7;CHEROKEE LETTER DI;Lu;0;L;;;;;N;;;;ABA7; +13D8;CHEROKEE LETTER TI;Lu;0;L;;;;;N;;;;ABA8; +13D9;CHEROKEE LETTER DO;Lu;0;L;;;;;N;;;;ABA9; +13DA;CHEROKEE LETTER DU;Lu;0;L;;;;;N;;;;ABAA; +13DB;CHEROKEE LETTER DV;Lu;0;L;;;;;N;;;;ABAB; +13DC;CHEROKEE LETTER DLA;Lu;0;L;;;;;N;;;;ABAC; +13DD;CHEROKEE LETTER TLA;Lu;0;L;;;;;N;;;;ABAD; +13DE;CHEROKEE LETTER TLE;Lu;0;L;;;;;N;;;;ABAE; +13DF;CHEROKEE LETTER TLI;Lu;0;L;;;;;N;;;;ABAF; +13E0;CHEROKEE LETTER TLO;Lu;0;L;;;;;N;;;;ABB0; +13E1;CHEROKEE LETTER TLU;Lu;0;L;;;;;N;;;;ABB1; +13E2;CHEROKEE LETTER TLV;Lu;0;L;;;;;N;;;;ABB2; +13E3;CHEROKEE LETTER TSA;Lu;0;L;;;;;N;;;;ABB3; +13E4;CHEROKEE LETTER TSE;Lu;0;L;;;;;N;;;;ABB4; +13E5;CHEROKEE LETTER TSI;Lu;0;L;;;;;N;;;;ABB5; +13E6;CHEROKEE LETTER TSO;Lu;0;L;;;;;N;;;;ABB6; +13E7;CHEROKEE LETTER TSU;Lu;0;L;;;;;N;;;;ABB7; +13E8;CHEROKEE LETTER TSV;Lu;0;L;;;;;N;;;;ABB8; +13E9;CHEROKEE LETTER WA;Lu;0;L;;;;;N;;;;ABB9; +13EA;CHEROKEE LETTER WE;Lu;0;L;;;;;N;;;;ABBA; +13EB;CHEROKEE LETTER WI;Lu;0;L;;;;;N;;;;ABBB; +13EC;CHEROKEE LETTER WO;Lu;0;L;;;;;N;;;;ABBC; +13ED;CHEROKEE LETTER WU;Lu;0;L;;;;;N;;;;ABBD; +13EE;CHEROKEE LETTER WV;Lu;0;L;;;;;N;;;;ABBE; +13EF;CHEROKEE LETTER YA;Lu;0;L;;;;;N;;;;ABBF; +13F0;CHEROKEE LETTER YE;Lu;0;L;;;;;N;;;;13F8; +13F1;CHEROKEE LETTER YI;Lu;0;L;;;;;N;;;;13F9; +13F2;CHEROKEE LETTER YO;Lu;0;L;;;;;N;;;;13FA; +13F3;CHEROKEE LETTER YU;Lu;0;L;;;;;N;;;;13FB; +13F4;CHEROKEE LETTER YV;Lu;0;L;;;;;N;;;;13FC; +13F5;CHEROKEE LETTER MV;Lu;0;L;;;;;N;;;;13FD; +13F8;CHEROKEE SMALL LETTER YE;Ll;0;L;;;;;N;;;13F0;;13F0 +13F9;CHEROKEE SMALL LETTER YI;Ll;0;L;;;;;N;;;13F1;;13F1 +13FA;CHEROKEE SMALL LETTER YO;Ll;0;L;;;;;N;;;13F2;;13F2 +13FB;CHEROKEE SMALL LETTER YU;Ll;0;L;;;;;N;;;13F3;;13F3 +13FC;CHEROKEE SMALL LETTER YV;Ll;0;L;;;;;N;;;13F4;;13F4 +13FD;CHEROKEE SMALL LETTER MV;Ll;0;L;;;;;N;;;13F5;;13F5 +1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;; +1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;; +1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;; +1403;CANADIAN SYLLABICS I;Lo;0;L;;;;;N;;;;; +1404;CANADIAN SYLLABICS II;Lo;0;L;;;;;N;;;;; +1405;CANADIAN SYLLABICS O;Lo;0;L;;;;;N;;;;; +1406;CANADIAN SYLLABICS OO;Lo;0;L;;;;;N;;;;; +1407;CANADIAN SYLLABICS Y-CREE OO;Lo;0;L;;;;;N;;;;; +1408;CANADIAN SYLLABICS CARRIER EE;Lo;0;L;;;;;N;;;;; +1409;CANADIAN SYLLABICS CARRIER I;Lo;0;L;;;;;N;;;;; +140A;CANADIAN SYLLABICS A;Lo;0;L;;;;;N;;;;; +140B;CANADIAN SYLLABICS AA;Lo;0;L;;;;;N;;;;; +140C;CANADIAN SYLLABICS WE;Lo;0;L;;;;;N;;;;; +140D;CANADIAN SYLLABICS WEST-CREE WE;Lo;0;L;;;;;N;;;;; +140E;CANADIAN SYLLABICS WI;Lo;0;L;;;;;N;;;;; +140F;CANADIAN SYLLABICS WEST-CREE WI;Lo;0;L;;;;;N;;;;; +1410;CANADIAN SYLLABICS WII;Lo;0;L;;;;;N;;;;; +1411;CANADIAN SYLLABICS WEST-CREE WII;Lo;0;L;;;;;N;;;;; +1412;CANADIAN SYLLABICS WO;Lo;0;L;;;;;N;;;;; +1413;CANADIAN SYLLABICS WEST-CREE WO;Lo;0;L;;;;;N;;;;; +1414;CANADIAN SYLLABICS WOO;Lo;0;L;;;;;N;;;;; +1415;CANADIAN SYLLABICS WEST-CREE WOO;Lo;0;L;;;;;N;;;;; +1416;CANADIAN SYLLABICS NASKAPI WOO;Lo;0;L;;;;;N;;;;; +1417;CANADIAN SYLLABICS WA;Lo;0;L;;;;;N;;;;; +1418;CANADIAN SYLLABICS WEST-CREE WA;Lo;0;L;;;;;N;;;;; +1419;CANADIAN SYLLABICS WAA;Lo;0;L;;;;;N;;;;; +141A;CANADIAN SYLLABICS WEST-CREE WAA;Lo;0;L;;;;;N;;;;; +141B;CANADIAN SYLLABICS NASKAPI WAA;Lo;0;L;;;;;N;;;;; +141C;CANADIAN SYLLABICS AI;Lo;0;L;;;;;N;;;;; +141D;CANADIAN SYLLABICS Y-CREE W;Lo;0;L;;;;;N;;;;; +141E;CANADIAN SYLLABICS GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +141F;CANADIAN SYLLABICS FINAL ACUTE;Lo;0;L;;;;;N;;;;; +1420;CANADIAN SYLLABICS FINAL GRAVE;Lo;0;L;;;;;N;;;;; +1421;CANADIAN SYLLABICS FINAL BOTTOM HALF RING;Lo;0;L;;;;;N;;;;; +1422;CANADIAN SYLLABICS FINAL TOP HALF RING;Lo;0;L;;;;;N;;;;; +1423;CANADIAN SYLLABICS FINAL RIGHT HALF RING;Lo;0;L;;;;;N;;;;; +1424;CANADIAN SYLLABICS FINAL RING;Lo;0;L;;;;;N;;;;; +1425;CANADIAN SYLLABICS FINAL DOUBLE ACUTE;Lo;0;L;;;;;N;;;;; +1426;CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES;Lo;0;L;;;;;N;;;;; +1427;CANADIAN SYLLABICS FINAL MIDDLE DOT;Lo;0;L;;;;;N;;;;; +1428;CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE;Lo;0;L;;;;;N;;;;; +1429;CANADIAN SYLLABICS FINAL PLUS;Lo;0;L;;;;;N;;;;; +142A;CANADIAN SYLLABICS FINAL DOWN TACK;Lo;0;L;;;;;N;;;;; +142B;CANADIAN SYLLABICS EN;Lo;0;L;;;;;N;;;;; +142C;CANADIAN SYLLABICS IN;Lo;0;L;;;;;N;;;;; +142D;CANADIAN SYLLABICS ON;Lo;0;L;;;;;N;;;;; +142E;CANADIAN SYLLABICS AN;Lo;0;L;;;;;N;;;;; +142F;CANADIAN SYLLABICS PE;Lo;0;L;;;;;N;;;;; +1430;CANADIAN SYLLABICS PAAI;Lo;0;L;;;;;N;;;;; +1431;CANADIAN SYLLABICS PI;Lo;0;L;;;;;N;;;;; +1432;CANADIAN SYLLABICS PII;Lo;0;L;;;;;N;;;;; +1433;CANADIAN SYLLABICS PO;Lo;0;L;;;;;N;;;;; +1434;CANADIAN SYLLABICS POO;Lo;0;L;;;;;N;;;;; +1435;CANADIAN SYLLABICS Y-CREE POO;Lo;0;L;;;;;N;;;;; +1436;CANADIAN SYLLABICS CARRIER HEE;Lo;0;L;;;;;N;;;;; +1437;CANADIAN SYLLABICS CARRIER HI;Lo;0;L;;;;;N;;;;; +1438;CANADIAN SYLLABICS PA;Lo;0;L;;;;;N;;;;; +1439;CANADIAN SYLLABICS PAA;Lo;0;L;;;;;N;;;;; +143A;CANADIAN SYLLABICS PWE;Lo;0;L;;;;;N;;;;; +143B;CANADIAN SYLLABICS WEST-CREE PWE;Lo;0;L;;;;;N;;;;; +143C;CANADIAN SYLLABICS PWI;Lo;0;L;;;;;N;;;;; +143D;CANADIAN SYLLABICS WEST-CREE PWI;Lo;0;L;;;;;N;;;;; +143E;CANADIAN SYLLABICS PWII;Lo;0;L;;;;;N;;;;; +143F;CANADIAN SYLLABICS WEST-CREE PWII;Lo;0;L;;;;;N;;;;; +1440;CANADIAN SYLLABICS PWO;Lo;0;L;;;;;N;;;;; +1441;CANADIAN SYLLABICS WEST-CREE PWO;Lo;0;L;;;;;N;;;;; +1442;CANADIAN SYLLABICS PWOO;Lo;0;L;;;;;N;;;;; +1443;CANADIAN SYLLABICS WEST-CREE PWOO;Lo;0;L;;;;;N;;;;; +1444;CANADIAN SYLLABICS PWA;Lo;0;L;;;;;N;;;;; +1445;CANADIAN SYLLABICS WEST-CREE PWA;Lo;0;L;;;;;N;;;;; +1446;CANADIAN SYLLABICS PWAA;Lo;0;L;;;;;N;;;;; +1447;CANADIAN SYLLABICS WEST-CREE PWAA;Lo;0;L;;;;;N;;;;; +1448;CANADIAN SYLLABICS Y-CREE PWAA;Lo;0;L;;;;;N;;;;; +1449;CANADIAN SYLLABICS P;Lo;0;L;;;;;N;;;;; +144A;CANADIAN SYLLABICS WEST-CREE P;Lo;0;L;;;;;N;;;;; +144B;CANADIAN SYLLABICS CARRIER H;Lo;0;L;;;;;N;;;;; +144C;CANADIAN SYLLABICS TE;Lo;0;L;;;;;N;;;;; +144D;CANADIAN SYLLABICS TAAI;Lo;0;L;;;;;N;;;;; +144E;CANADIAN SYLLABICS TI;Lo;0;L;;;;;N;;;;; +144F;CANADIAN SYLLABICS TII;Lo;0;L;;;;;N;;;;; +1450;CANADIAN SYLLABICS TO;Lo;0;L;;;;;N;;;;; +1451;CANADIAN SYLLABICS TOO;Lo;0;L;;;;;N;;;;; +1452;CANADIAN SYLLABICS Y-CREE TOO;Lo;0;L;;;;;N;;;;; +1453;CANADIAN SYLLABICS CARRIER DEE;Lo;0;L;;;;;N;;;;; +1454;CANADIAN SYLLABICS CARRIER DI;Lo;0;L;;;;;N;;;;; +1455;CANADIAN SYLLABICS TA;Lo;0;L;;;;;N;;;;; +1456;CANADIAN SYLLABICS TAA;Lo;0;L;;;;;N;;;;; +1457;CANADIAN SYLLABICS TWE;Lo;0;L;;;;;N;;;;; +1458;CANADIAN SYLLABICS WEST-CREE TWE;Lo;0;L;;;;;N;;;;; +1459;CANADIAN SYLLABICS TWI;Lo;0;L;;;;;N;;;;; +145A;CANADIAN SYLLABICS WEST-CREE TWI;Lo;0;L;;;;;N;;;;; +145B;CANADIAN SYLLABICS TWII;Lo;0;L;;;;;N;;;;; +145C;CANADIAN SYLLABICS WEST-CREE TWII;Lo;0;L;;;;;N;;;;; +145D;CANADIAN SYLLABICS TWO;Lo;0;L;;;;;N;;;;; +145E;CANADIAN SYLLABICS WEST-CREE TWO;Lo;0;L;;;;;N;;;;; +145F;CANADIAN SYLLABICS TWOO;Lo;0;L;;;;;N;;;;; +1460;CANADIAN SYLLABICS WEST-CREE TWOO;Lo;0;L;;;;;N;;;;; +1461;CANADIAN SYLLABICS TWA;Lo;0;L;;;;;N;;;;; +1462;CANADIAN SYLLABICS WEST-CREE TWA;Lo;0;L;;;;;N;;;;; +1463;CANADIAN SYLLABICS TWAA;Lo;0;L;;;;;N;;;;; +1464;CANADIAN SYLLABICS WEST-CREE TWAA;Lo;0;L;;;;;N;;;;; +1465;CANADIAN SYLLABICS NASKAPI TWAA;Lo;0;L;;;;;N;;;;; +1466;CANADIAN SYLLABICS T;Lo;0;L;;;;;N;;;;; +1467;CANADIAN SYLLABICS TTE;Lo;0;L;;;;;N;;;;; +1468;CANADIAN SYLLABICS TTI;Lo;0;L;;;;;N;;;;; +1469;CANADIAN SYLLABICS TTO;Lo;0;L;;;;;N;;;;; +146A;CANADIAN SYLLABICS TTA;Lo;0;L;;;;;N;;;;; +146B;CANADIAN SYLLABICS KE;Lo;0;L;;;;;N;;;;; +146C;CANADIAN SYLLABICS KAAI;Lo;0;L;;;;;N;;;;; +146D;CANADIAN SYLLABICS KI;Lo;0;L;;;;;N;;;;; +146E;CANADIAN SYLLABICS KII;Lo;0;L;;;;;N;;;;; +146F;CANADIAN SYLLABICS KO;Lo;0;L;;;;;N;;;;; +1470;CANADIAN SYLLABICS KOO;Lo;0;L;;;;;N;;;;; +1471;CANADIAN SYLLABICS Y-CREE KOO;Lo;0;L;;;;;N;;;;; +1472;CANADIAN SYLLABICS KA;Lo;0;L;;;;;N;;;;; +1473;CANADIAN SYLLABICS KAA;Lo;0;L;;;;;N;;;;; +1474;CANADIAN SYLLABICS KWE;Lo;0;L;;;;;N;;;;; +1475;CANADIAN SYLLABICS WEST-CREE KWE;Lo;0;L;;;;;N;;;;; +1476;CANADIAN SYLLABICS KWI;Lo;0;L;;;;;N;;;;; +1477;CANADIAN SYLLABICS WEST-CREE KWI;Lo;0;L;;;;;N;;;;; +1478;CANADIAN SYLLABICS KWII;Lo;0;L;;;;;N;;;;; +1479;CANADIAN SYLLABICS WEST-CREE KWII;Lo;0;L;;;;;N;;;;; +147A;CANADIAN SYLLABICS KWO;Lo;0;L;;;;;N;;;;; +147B;CANADIAN SYLLABICS WEST-CREE KWO;Lo;0;L;;;;;N;;;;; +147C;CANADIAN SYLLABICS KWOO;Lo;0;L;;;;;N;;;;; +147D;CANADIAN SYLLABICS WEST-CREE KWOO;Lo;0;L;;;;;N;;;;; +147E;CANADIAN SYLLABICS KWA;Lo;0;L;;;;;N;;;;; +147F;CANADIAN SYLLABICS WEST-CREE KWA;Lo;0;L;;;;;N;;;;; +1480;CANADIAN SYLLABICS KWAA;Lo;0;L;;;;;N;;;;; +1481;CANADIAN SYLLABICS WEST-CREE KWAA;Lo;0;L;;;;;N;;;;; +1482;CANADIAN SYLLABICS NASKAPI KWAA;Lo;0;L;;;;;N;;;;; +1483;CANADIAN SYLLABICS K;Lo;0;L;;;;;N;;;;; +1484;CANADIAN SYLLABICS KW;Lo;0;L;;;;;N;;;;; +1485;CANADIAN SYLLABICS SOUTH-SLAVEY KEH;Lo;0;L;;;;;N;;;;; +1486;CANADIAN SYLLABICS SOUTH-SLAVEY KIH;Lo;0;L;;;;;N;;;;; +1487;CANADIAN SYLLABICS SOUTH-SLAVEY KOH;Lo;0;L;;;;;N;;;;; +1488;CANADIAN SYLLABICS SOUTH-SLAVEY KAH;Lo;0;L;;;;;N;;;;; +1489;CANADIAN SYLLABICS CE;Lo;0;L;;;;;N;;;;; +148A;CANADIAN SYLLABICS CAAI;Lo;0;L;;;;;N;;;;; +148B;CANADIAN SYLLABICS CI;Lo;0;L;;;;;N;;;;; +148C;CANADIAN SYLLABICS CII;Lo;0;L;;;;;N;;;;; +148D;CANADIAN SYLLABICS CO;Lo;0;L;;;;;N;;;;; +148E;CANADIAN SYLLABICS COO;Lo;0;L;;;;;N;;;;; +148F;CANADIAN SYLLABICS Y-CREE COO;Lo;0;L;;;;;N;;;;; +1490;CANADIAN SYLLABICS CA;Lo;0;L;;;;;N;;;;; +1491;CANADIAN SYLLABICS CAA;Lo;0;L;;;;;N;;;;; +1492;CANADIAN SYLLABICS CWE;Lo;0;L;;;;;N;;;;; +1493;CANADIAN SYLLABICS WEST-CREE CWE;Lo;0;L;;;;;N;;;;; +1494;CANADIAN SYLLABICS CWI;Lo;0;L;;;;;N;;;;; +1495;CANADIAN SYLLABICS WEST-CREE CWI;Lo;0;L;;;;;N;;;;; +1496;CANADIAN SYLLABICS CWII;Lo;0;L;;;;;N;;;;; +1497;CANADIAN SYLLABICS WEST-CREE CWII;Lo;0;L;;;;;N;;;;; +1498;CANADIAN SYLLABICS CWO;Lo;0;L;;;;;N;;;;; +1499;CANADIAN SYLLABICS WEST-CREE CWO;Lo;0;L;;;;;N;;;;; +149A;CANADIAN SYLLABICS CWOO;Lo;0;L;;;;;N;;;;; +149B;CANADIAN SYLLABICS WEST-CREE CWOO;Lo;0;L;;;;;N;;;;; +149C;CANADIAN SYLLABICS CWA;Lo;0;L;;;;;N;;;;; +149D;CANADIAN SYLLABICS WEST-CREE CWA;Lo;0;L;;;;;N;;;;; +149E;CANADIAN SYLLABICS CWAA;Lo;0;L;;;;;N;;;;; +149F;CANADIAN SYLLABICS WEST-CREE CWAA;Lo;0;L;;;;;N;;;;; +14A0;CANADIAN SYLLABICS NASKAPI CWAA;Lo;0;L;;;;;N;;;;; +14A1;CANADIAN SYLLABICS C;Lo;0;L;;;;;N;;;;; +14A2;CANADIAN SYLLABICS SAYISI TH;Lo;0;L;;;;;N;;;;; +14A3;CANADIAN SYLLABICS ME;Lo;0;L;;;;;N;;;;; +14A4;CANADIAN SYLLABICS MAAI;Lo;0;L;;;;;N;;;;; +14A5;CANADIAN SYLLABICS MI;Lo;0;L;;;;;N;;;;; +14A6;CANADIAN SYLLABICS MII;Lo;0;L;;;;;N;;;;; +14A7;CANADIAN SYLLABICS MO;Lo;0;L;;;;;N;;;;; +14A8;CANADIAN SYLLABICS MOO;Lo;0;L;;;;;N;;;;; +14A9;CANADIAN SYLLABICS Y-CREE MOO;Lo;0;L;;;;;N;;;;; +14AA;CANADIAN SYLLABICS MA;Lo;0;L;;;;;N;;;;; +14AB;CANADIAN SYLLABICS MAA;Lo;0;L;;;;;N;;;;; +14AC;CANADIAN SYLLABICS MWE;Lo;0;L;;;;;N;;;;; +14AD;CANADIAN SYLLABICS WEST-CREE MWE;Lo;0;L;;;;;N;;;;; +14AE;CANADIAN SYLLABICS MWI;Lo;0;L;;;;;N;;;;; +14AF;CANADIAN SYLLABICS WEST-CREE MWI;Lo;0;L;;;;;N;;;;; +14B0;CANADIAN SYLLABICS MWII;Lo;0;L;;;;;N;;;;; +14B1;CANADIAN SYLLABICS WEST-CREE MWII;Lo;0;L;;;;;N;;;;; +14B2;CANADIAN SYLLABICS MWO;Lo;0;L;;;;;N;;;;; +14B3;CANADIAN SYLLABICS WEST-CREE MWO;Lo;0;L;;;;;N;;;;; +14B4;CANADIAN SYLLABICS MWOO;Lo;0;L;;;;;N;;;;; +14B5;CANADIAN SYLLABICS WEST-CREE MWOO;Lo;0;L;;;;;N;;;;; +14B6;CANADIAN SYLLABICS MWA;Lo;0;L;;;;;N;;;;; +14B7;CANADIAN SYLLABICS WEST-CREE MWA;Lo;0;L;;;;;N;;;;; +14B8;CANADIAN SYLLABICS MWAA;Lo;0;L;;;;;N;;;;; +14B9;CANADIAN SYLLABICS WEST-CREE MWAA;Lo;0;L;;;;;N;;;;; +14BA;CANADIAN SYLLABICS NASKAPI MWAA;Lo;0;L;;;;;N;;;;; +14BB;CANADIAN SYLLABICS M;Lo;0;L;;;;;N;;;;; +14BC;CANADIAN SYLLABICS WEST-CREE M;Lo;0;L;;;;;N;;;;; +14BD;CANADIAN SYLLABICS MH;Lo;0;L;;;;;N;;;;; +14BE;CANADIAN SYLLABICS ATHAPASCAN M;Lo;0;L;;;;;N;;;;; +14BF;CANADIAN SYLLABICS SAYISI M;Lo;0;L;;;;;N;;;;; +14C0;CANADIAN SYLLABICS NE;Lo;0;L;;;;;N;;;;; +14C1;CANADIAN SYLLABICS NAAI;Lo;0;L;;;;;N;;;;; +14C2;CANADIAN SYLLABICS NI;Lo;0;L;;;;;N;;;;; +14C3;CANADIAN SYLLABICS NII;Lo;0;L;;;;;N;;;;; +14C4;CANADIAN SYLLABICS NO;Lo;0;L;;;;;N;;;;; +14C5;CANADIAN SYLLABICS NOO;Lo;0;L;;;;;N;;;;; +14C6;CANADIAN SYLLABICS Y-CREE NOO;Lo;0;L;;;;;N;;;;; +14C7;CANADIAN SYLLABICS NA;Lo;0;L;;;;;N;;;;; +14C8;CANADIAN SYLLABICS NAA;Lo;0;L;;;;;N;;;;; +14C9;CANADIAN SYLLABICS NWE;Lo;0;L;;;;;N;;;;; +14CA;CANADIAN SYLLABICS WEST-CREE NWE;Lo;0;L;;;;;N;;;;; +14CB;CANADIAN SYLLABICS NWA;Lo;0;L;;;;;N;;;;; +14CC;CANADIAN SYLLABICS WEST-CREE NWA;Lo;0;L;;;;;N;;;;; +14CD;CANADIAN SYLLABICS NWAA;Lo;0;L;;;;;N;;;;; +14CE;CANADIAN SYLLABICS WEST-CREE NWAA;Lo;0;L;;;;;N;;;;; +14CF;CANADIAN SYLLABICS NASKAPI NWAA;Lo;0;L;;;;;N;;;;; +14D0;CANADIAN SYLLABICS N;Lo;0;L;;;;;N;;;;; +14D1;CANADIAN SYLLABICS CARRIER NG;Lo;0;L;;;;;N;;;;; +14D2;CANADIAN SYLLABICS NH;Lo;0;L;;;;;N;;;;; +14D3;CANADIAN SYLLABICS LE;Lo;0;L;;;;;N;;;;; +14D4;CANADIAN SYLLABICS LAAI;Lo;0;L;;;;;N;;;;; +14D5;CANADIAN SYLLABICS LI;Lo;0;L;;;;;N;;;;; +14D6;CANADIAN SYLLABICS LII;Lo;0;L;;;;;N;;;;; +14D7;CANADIAN SYLLABICS LO;Lo;0;L;;;;;N;;;;; +14D8;CANADIAN SYLLABICS LOO;Lo;0;L;;;;;N;;;;; +14D9;CANADIAN SYLLABICS Y-CREE LOO;Lo;0;L;;;;;N;;;;; +14DA;CANADIAN SYLLABICS LA;Lo;0;L;;;;;N;;;;; +14DB;CANADIAN SYLLABICS LAA;Lo;0;L;;;;;N;;;;; +14DC;CANADIAN SYLLABICS LWE;Lo;0;L;;;;;N;;;;; +14DD;CANADIAN SYLLABICS WEST-CREE LWE;Lo;0;L;;;;;N;;;;; +14DE;CANADIAN SYLLABICS LWI;Lo;0;L;;;;;N;;;;; +14DF;CANADIAN SYLLABICS WEST-CREE LWI;Lo;0;L;;;;;N;;;;; +14E0;CANADIAN SYLLABICS LWII;Lo;0;L;;;;;N;;;;; +14E1;CANADIAN SYLLABICS WEST-CREE LWII;Lo;0;L;;;;;N;;;;; +14E2;CANADIAN SYLLABICS LWO;Lo;0;L;;;;;N;;;;; +14E3;CANADIAN SYLLABICS WEST-CREE LWO;Lo;0;L;;;;;N;;;;; +14E4;CANADIAN SYLLABICS LWOO;Lo;0;L;;;;;N;;;;; +14E5;CANADIAN SYLLABICS WEST-CREE LWOO;Lo;0;L;;;;;N;;;;; +14E6;CANADIAN SYLLABICS LWA;Lo;0;L;;;;;N;;;;; +14E7;CANADIAN SYLLABICS WEST-CREE LWA;Lo;0;L;;;;;N;;;;; +14E8;CANADIAN SYLLABICS LWAA;Lo;0;L;;;;;N;;;;; +14E9;CANADIAN SYLLABICS WEST-CREE LWAA;Lo;0;L;;;;;N;;;;; +14EA;CANADIAN SYLLABICS L;Lo;0;L;;;;;N;;;;; +14EB;CANADIAN SYLLABICS WEST-CREE L;Lo;0;L;;;;;N;;;;; +14EC;CANADIAN SYLLABICS MEDIAL L;Lo;0;L;;;;;N;;;;; +14ED;CANADIAN SYLLABICS SE;Lo;0;L;;;;;N;;;;; +14EE;CANADIAN SYLLABICS SAAI;Lo;0;L;;;;;N;;;;; +14EF;CANADIAN SYLLABICS SI;Lo;0;L;;;;;N;;;;; +14F0;CANADIAN SYLLABICS SII;Lo;0;L;;;;;N;;;;; +14F1;CANADIAN SYLLABICS SO;Lo;0;L;;;;;N;;;;; +14F2;CANADIAN SYLLABICS SOO;Lo;0;L;;;;;N;;;;; +14F3;CANADIAN SYLLABICS Y-CREE SOO;Lo;0;L;;;;;N;;;;; +14F4;CANADIAN SYLLABICS SA;Lo;0;L;;;;;N;;;;; +14F5;CANADIAN SYLLABICS SAA;Lo;0;L;;;;;N;;;;; +14F6;CANADIAN SYLLABICS SWE;Lo;0;L;;;;;N;;;;; +14F7;CANADIAN SYLLABICS WEST-CREE SWE;Lo;0;L;;;;;N;;;;; +14F8;CANADIAN SYLLABICS SWI;Lo;0;L;;;;;N;;;;; +14F9;CANADIAN SYLLABICS WEST-CREE SWI;Lo;0;L;;;;;N;;;;; +14FA;CANADIAN SYLLABICS SWII;Lo;0;L;;;;;N;;;;; +14FB;CANADIAN SYLLABICS WEST-CREE SWII;Lo;0;L;;;;;N;;;;; +14FC;CANADIAN SYLLABICS SWO;Lo;0;L;;;;;N;;;;; +14FD;CANADIAN SYLLABICS WEST-CREE SWO;Lo;0;L;;;;;N;;;;; +14FE;CANADIAN SYLLABICS SWOO;Lo;0;L;;;;;N;;;;; +14FF;CANADIAN SYLLABICS WEST-CREE SWOO;Lo;0;L;;;;;N;;;;; +1500;CANADIAN SYLLABICS SWA;Lo;0;L;;;;;N;;;;; +1501;CANADIAN SYLLABICS WEST-CREE SWA;Lo;0;L;;;;;N;;;;; +1502;CANADIAN SYLLABICS SWAA;Lo;0;L;;;;;N;;;;; +1503;CANADIAN SYLLABICS WEST-CREE SWAA;Lo;0;L;;;;;N;;;;; +1504;CANADIAN SYLLABICS NASKAPI SWAA;Lo;0;L;;;;;N;;;;; +1505;CANADIAN SYLLABICS S;Lo;0;L;;;;;N;;;;; +1506;CANADIAN SYLLABICS ATHAPASCAN S;Lo;0;L;;;;;N;;;;; +1507;CANADIAN SYLLABICS SW;Lo;0;L;;;;;N;;;;; +1508;CANADIAN SYLLABICS BLACKFOOT S;Lo;0;L;;;;;N;;;;; +1509;CANADIAN SYLLABICS MOOSE-CREE SK;Lo;0;L;;;;;N;;;;; +150A;CANADIAN SYLLABICS NASKAPI SKW;Lo;0;L;;;;;N;;;;; +150B;CANADIAN SYLLABICS NASKAPI S-W;Lo;0;L;;;;;N;;;;; +150C;CANADIAN SYLLABICS NASKAPI SPWA;Lo;0;L;;;;;N;;;;; +150D;CANADIAN SYLLABICS NASKAPI STWA;Lo;0;L;;;;;N;;;;; +150E;CANADIAN SYLLABICS NASKAPI SKWA;Lo;0;L;;;;;N;;;;; +150F;CANADIAN SYLLABICS NASKAPI SCWA;Lo;0;L;;;;;N;;;;; +1510;CANADIAN SYLLABICS SHE;Lo;0;L;;;;;N;;;;; +1511;CANADIAN SYLLABICS SHI;Lo;0;L;;;;;N;;;;; +1512;CANADIAN SYLLABICS SHII;Lo;0;L;;;;;N;;;;; +1513;CANADIAN SYLLABICS SHO;Lo;0;L;;;;;N;;;;; +1514;CANADIAN SYLLABICS SHOO;Lo;0;L;;;;;N;;;;; +1515;CANADIAN SYLLABICS SHA;Lo;0;L;;;;;N;;;;; +1516;CANADIAN SYLLABICS SHAA;Lo;0;L;;;;;N;;;;; +1517;CANADIAN SYLLABICS SHWE;Lo;0;L;;;;;N;;;;; +1518;CANADIAN SYLLABICS WEST-CREE SHWE;Lo;0;L;;;;;N;;;;; +1519;CANADIAN SYLLABICS SHWI;Lo;0;L;;;;;N;;;;; +151A;CANADIAN SYLLABICS WEST-CREE SHWI;Lo;0;L;;;;;N;;;;; +151B;CANADIAN SYLLABICS SHWII;Lo;0;L;;;;;N;;;;; +151C;CANADIAN SYLLABICS WEST-CREE SHWII;Lo;0;L;;;;;N;;;;; +151D;CANADIAN SYLLABICS SHWO;Lo;0;L;;;;;N;;;;; +151E;CANADIAN SYLLABICS WEST-CREE SHWO;Lo;0;L;;;;;N;;;;; +151F;CANADIAN SYLLABICS SHWOO;Lo;0;L;;;;;N;;;;; +1520;CANADIAN SYLLABICS WEST-CREE SHWOO;Lo;0;L;;;;;N;;;;; +1521;CANADIAN SYLLABICS SHWA;Lo;0;L;;;;;N;;;;; +1522;CANADIAN SYLLABICS WEST-CREE SHWA;Lo;0;L;;;;;N;;;;; +1523;CANADIAN SYLLABICS SHWAA;Lo;0;L;;;;;N;;;;; +1524;CANADIAN SYLLABICS WEST-CREE SHWAA;Lo;0;L;;;;;N;;;;; +1525;CANADIAN SYLLABICS SH;Lo;0;L;;;;;N;;;;; +1526;CANADIAN SYLLABICS YE;Lo;0;L;;;;;N;;;;; +1527;CANADIAN SYLLABICS YAAI;Lo;0;L;;;;;N;;;;; +1528;CANADIAN SYLLABICS YI;Lo;0;L;;;;;N;;;;; +1529;CANADIAN SYLLABICS YII;Lo;0;L;;;;;N;;;;; +152A;CANADIAN SYLLABICS YO;Lo;0;L;;;;;N;;;;; +152B;CANADIAN SYLLABICS YOO;Lo;0;L;;;;;N;;;;; +152C;CANADIAN SYLLABICS Y-CREE YOO;Lo;0;L;;;;;N;;;;; +152D;CANADIAN SYLLABICS YA;Lo;0;L;;;;;N;;;;; +152E;CANADIAN SYLLABICS YAA;Lo;0;L;;;;;N;;;;; +152F;CANADIAN SYLLABICS YWE;Lo;0;L;;;;;N;;;;; +1530;CANADIAN SYLLABICS WEST-CREE YWE;Lo;0;L;;;;;N;;;;; +1531;CANADIAN SYLLABICS YWI;Lo;0;L;;;;;N;;;;; +1532;CANADIAN SYLLABICS WEST-CREE YWI;Lo;0;L;;;;;N;;;;; +1533;CANADIAN SYLLABICS YWII;Lo;0;L;;;;;N;;;;; +1534;CANADIAN SYLLABICS WEST-CREE YWII;Lo;0;L;;;;;N;;;;; +1535;CANADIAN SYLLABICS YWO;Lo;0;L;;;;;N;;;;; +1536;CANADIAN SYLLABICS WEST-CREE YWO;Lo;0;L;;;;;N;;;;; +1537;CANADIAN SYLLABICS YWOO;Lo;0;L;;;;;N;;;;; +1538;CANADIAN SYLLABICS WEST-CREE YWOO;Lo;0;L;;;;;N;;;;; +1539;CANADIAN SYLLABICS YWA;Lo;0;L;;;;;N;;;;; +153A;CANADIAN SYLLABICS WEST-CREE YWA;Lo;0;L;;;;;N;;;;; +153B;CANADIAN SYLLABICS YWAA;Lo;0;L;;;;;N;;;;; +153C;CANADIAN SYLLABICS WEST-CREE YWAA;Lo;0;L;;;;;N;;;;; +153D;CANADIAN SYLLABICS NASKAPI YWAA;Lo;0;L;;;;;N;;;;; +153E;CANADIAN SYLLABICS Y;Lo;0;L;;;;;N;;;;; +153F;CANADIAN SYLLABICS BIBLE-CREE Y;Lo;0;L;;;;;N;;;;; +1540;CANADIAN SYLLABICS WEST-CREE Y;Lo;0;L;;;;;N;;;;; +1541;CANADIAN SYLLABICS SAYISI YI;Lo;0;L;;;;;N;;;;; +1542;CANADIAN SYLLABICS RE;Lo;0;L;;;;;N;;;;; +1543;CANADIAN SYLLABICS R-CREE RE;Lo;0;L;;;;;N;;;;; +1544;CANADIAN SYLLABICS WEST-CREE LE;Lo;0;L;;;;;N;;;;; +1545;CANADIAN SYLLABICS RAAI;Lo;0;L;;;;;N;;;;; +1546;CANADIAN SYLLABICS RI;Lo;0;L;;;;;N;;;;; +1547;CANADIAN SYLLABICS RII;Lo;0;L;;;;;N;;;;; +1548;CANADIAN SYLLABICS RO;Lo;0;L;;;;;N;;;;; +1549;CANADIAN SYLLABICS ROO;Lo;0;L;;;;;N;;;;; +154A;CANADIAN SYLLABICS WEST-CREE LO;Lo;0;L;;;;;N;;;;; +154B;CANADIAN SYLLABICS RA;Lo;0;L;;;;;N;;;;; +154C;CANADIAN SYLLABICS RAA;Lo;0;L;;;;;N;;;;; +154D;CANADIAN SYLLABICS WEST-CREE LA;Lo;0;L;;;;;N;;;;; +154E;CANADIAN SYLLABICS RWAA;Lo;0;L;;;;;N;;;;; +154F;CANADIAN SYLLABICS WEST-CREE RWAA;Lo;0;L;;;;;N;;;;; +1550;CANADIAN SYLLABICS R;Lo;0;L;;;;;N;;;;; +1551;CANADIAN SYLLABICS WEST-CREE R;Lo;0;L;;;;;N;;;;; +1552;CANADIAN SYLLABICS MEDIAL R;Lo;0;L;;;;;N;;;;; +1553;CANADIAN SYLLABICS FE;Lo;0;L;;;;;N;;;;; +1554;CANADIAN SYLLABICS FAAI;Lo;0;L;;;;;N;;;;; +1555;CANADIAN SYLLABICS FI;Lo;0;L;;;;;N;;;;; +1556;CANADIAN SYLLABICS FII;Lo;0;L;;;;;N;;;;; +1557;CANADIAN SYLLABICS FO;Lo;0;L;;;;;N;;;;; +1558;CANADIAN SYLLABICS FOO;Lo;0;L;;;;;N;;;;; +1559;CANADIAN SYLLABICS FA;Lo;0;L;;;;;N;;;;; +155A;CANADIAN SYLLABICS FAA;Lo;0;L;;;;;N;;;;; +155B;CANADIAN SYLLABICS FWAA;Lo;0;L;;;;;N;;;;; +155C;CANADIAN SYLLABICS WEST-CREE FWAA;Lo;0;L;;;;;N;;;;; +155D;CANADIAN SYLLABICS F;Lo;0;L;;;;;N;;;;; +155E;CANADIAN SYLLABICS THE;Lo;0;L;;;;;N;;;;; +155F;CANADIAN SYLLABICS N-CREE THE;Lo;0;L;;;;;N;;;;; +1560;CANADIAN SYLLABICS THI;Lo;0;L;;;;;N;;;;; +1561;CANADIAN SYLLABICS N-CREE THI;Lo;0;L;;;;;N;;;;; +1562;CANADIAN SYLLABICS THII;Lo;0;L;;;;;N;;;;; +1563;CANADIAN SYLLABICS N-CREE THII;Lo;0;L;;;;;N;;;;; +1564;CANADIAN SYLLABICS THO;Lo;0;L;;;;;N;;;;; +1565;CANADIAN SYLLABICS THOO;Lo;0;L;;;;;N;;;;; +1566;CANADIAN SYLLABICS THA;Lo;0;L;;;;;N;;;;; +1567;CANADIAN SYLLABICS THAA;Lo;0;L;;;;;N;;;;; +1568;CANADIAN SYLLABICS THWAA;Lo;0;L;;;;;N;;;;; +1569;CANADIAN SYLLABICS WEST-CREE THWAA;Lo;0;L;;;;;N;;;;; +156A;CANADIAN SYLLABICS TH;Lo;0;L;;;;;N;;;;; +156B;CANADIAN SYLLABICS TTHE;Lo;0;L;;;;;N;;;;; +156C;CANADIAN SYLLABICS TTHI;Lo;0;L;;;;;N;;;;; +156D;CANADIAN SYLLABICS TTHO;Lo;0;L;;;;;N;;;;; +156E;CANADIAN SYLLABICS TTHA;Lo;0;L;;;;;N;;;;; +156F;CANADIAN SYLLABICS TTH;Lo;0;L;;;;;N;;;;; +1570;CANADIAN SYLLABICS TYE;Lo;0;L;;;;;N;;;;; +1571;CANADIAN SYLLABICS TYI;Lo;0;L;;;;;N;;;;; +1572;CANADIAN SYLLABICS TYO;Lo;0;L;;;;;N;;;;; +1573;CANADIAN SYLLABICS TYA;Lo;0;L;;;;;N;;;;; +1574;CANADIAN SYLLABICS NUNAVIK HE;Lo;0;L;;;;;N;;;;; +1575;CANADIAN SYLLABICS NUNAVIK HI;Lo;0;L;;;;;N;;;;; +1576;CANADIAN SYLLABICS NUNAVIK HII;Lo;0;L;;;;;N;;;;; +1577;CANADIAN SYLLABICS NUNAVIK HO;Lo;0;L;;;;;N;;;;; +1578;CANADIAN SYLLABICS NUNAVIK HOO;Lo;0;L;;;;;N;;;;; +1579;CANADIAN SYLLABICS NUNAVIK HA;Lo;0;L;;;;;N;;;;; +157A;CANADIAN SYLLABICS NUNAVIK HAA;Lo;0;L;;;;;N;;;;; +157B;CANADIAN SYLLABICS NUNAVIK H;Lo;0;L;;;;;N;;;;; +157C;CANADIAN SYLLABICS NUNAVUT H;Lo;0;L;;;;;N;;;;; +157D;CANADIAN SYLLABICS HK;Lo;0;L;;;;;N;;;;; +157E;CANADIAN SYLLABICS QAAI;Lo;0;L;;;;;N;;;;; +157F;CANADIAN SYLLABICS QI;Lo;0;L;;;;;N;;;;; +1580;CANADIAN SYLLABICS QII;Lo;0;L;;;;;N;;;;; +1581;CANADIAN SYLLABICS QO;Lo;0;L;;;;;N;;;;; +1582;CANADIAN SYLLABICS QOO;Lo;0;L;;;;;N;;;;; +1583;CANADIAN SYLLABICS QA;Lo;0;L;;;;;N;;;;; +1584;CANADIAN SYLLABICS QAA;Lo;0;L;;;;;N;;;;; +1585;CANADIAN SYLLABICS Q;Lo;0;L;;;;;N;;;;; +1586;CANADIAN SYLLABICS TLHE;Lo;0;L;;;;;N;;;;; +1587;CANADIAN SYLLABICS TLHI;Lo;0;L;;;;;N;;;;; +1588;CANADIAN SYLLABICS TLHO;Lo;0;L;;;;;N;;;;; +1589;CANADIAN SYLLABICS TLHA;Lo;0;L;;;;;N;;;;; +158A;CANADIAN SYLLABICS WEST-CREE RE;Lo;0;L;;;;;N;;;;; +158B;CANADIAN SYLLABICS WEST-CREE RI;Lo;0;L;;;;;N;;;;; +158C;CANADIAN SYLLABICS WEST-CREE RO;Lo;0;L;;;;;N;;;;; +158D;CANADIAN SYLLABICS WEST-CREE RA;Lo;0;L;;;;;N;;;;; +158E;CANADIAN SYLLABICS NGAAI;Lo;0;L;;;;;N;;;;; +158F;CANADIAN SYLLABICS NGI;Lo;0;L;;;;;N;;;;; +1590;CANADIAN SYLLABICS NGII;Lo;0;L;;;;;N;;;;; +1591;CANADIAN SYLLABICS NGO;Lo;0;L;;;;;N;;;;; +1592;CANADIAN SYLLABICS NGOO;Lo;0;L;;;;;N;;;;; +1593;CANADIAN SYLLABICS NGA;Lo;0;L;;;;;N;;;;; +1594;CANADIAN SYLLABICS NGAA;Lo;0;L;;;;;N;;;;; +1595;CANADIAN SYLLABICS NG;Lo;0;L;;;;;N;;;;; +1596;CANADIAN SYLLABICS NNG;Lo;0;L;;;;;N;;;;; +1597;CANADIAN SYLLABICS SAYISI SHE;Lo;0;L;;;;;N;;;;; +1598;CANADIAN SYLLABICS SAYISI SHI;Lo;0;L;;;;;N;;;;; +1599;CANADIAN SYLLABICS SAYISI SHO;Lo;0;L;;;;;N;;;;; +159A;CANADIAN SYLLABICS SAYISI SHA;Lo;0;L;;;;;N;;;;; +159B;CANADIAN SYLLABICS WOODS-CREE THE;Lo;0;L;;;;;N;;;;; +159C;CANADIAN SYLLABICS WOODS-CREE THI;Lo;0;L;;;;;N;;;;; +159D;CANADIAN SYLLABICS WOODS-CREE THO;Lo;0;L;;;;;N;;;;; +159E;CANADIAN SYLLABICS WOODS-CREE THA;Lo;0;L;;;;;N;;;;; +159F;CANADIAN SYLLABICS WOODS-CREE TH;Lo;0;L;;;;;N;;;;; +15A0;CANADIAN SYLLABICS LHI;Lo;0;L;;;;;N;;;;; +15A1;CANADIAN SYLLABICS LHII;Lo;0;L;;;;;N;;;;; +15A2;CANADIAN SYLLABICS LHO;Lo;0;L;;;;;N;;;;; +15A3;CANADIAN SYLLABICS LHOO;Lo;0;L;;;;;N;;;;; +15A4;CANADIAN SYLLABICS LHA;Lo;0;L;;;;;N;;;;; +15A5;CANADIAN SYLLABICS LHAA;Lo;0;L;;;;;N;;;;; +15A6;CANADIAN SYLLABICS LH;Lo;0;L;;;;;N;;;;; +15A7;CANADIAN SYLLABICS TH-CREE THE;Lo;0;L;;;;;N;;;;; +15A8;CANADIAN SYLLABICS TH-CREE THI;Lo;0;L;;;;;N;;;;; +15A9;CANADIAN SYLLABICS TH-CREE THII;Lo;0;L;;;;;N;;;;; +15AA;CANADIAN SYLLABICS TH-CREE THO;Lo;0;L;;;;;N;;;;; +15AB;CANADIAN SYLLABICS TH-CREE THOO;Lo;0;L;;;;;N;;;;; +15AC;CANADIAN SYLLABICS TH-CREE THA;Lo;0;L;;;;;N;;;;; +15AD;CANADIAN SYLLABICS TH-CREE THAA;Lo;0;L;;;;;N;;;;; +15AE;CANADIAN SYLLABICS TH-CREE TH;Lo;0;L;;;;;N;;;;; +15AF;CANADIAN SYLLABICS AIVILIK B;Lo;0;L;;;;;N;;;;; +15B0;CANADIAN SYLLABICS BLACKFOOT E;Lo;0;L;;;;;N;;;;; +15B1;CANADIAN SYLLABICS BLACKFOOT I;Lo;0;L;;;;;N;;;;; +15B2;CANADIAN SYLLABICS BLACKFOOT O;Lo;0;L;;;;;N;;;;; +15B3;CANADIAN SYLLABICS BLACKFOOT A;Lo;0;L;;;;;N;;;;; +15B4;CANADIAN SYLLABICS BLACKFOOT WE;Lo;0;L;;;;;N;;;;; +15B5;CANADIAN SYLLABICS BLACKFOOT WI;Lo;0;L;;;;;N;;;;; +15B6;CANADIAN SYLLABICS BLACKFOOT WO;Lo;0;L;;;;;N;;;;; +15B7;CANADIAN SYLLABICS BLACKFOOT WA;Lo;0;L;;;;;N;;;;; +15B8;CANADIAN SYLLABICS BLACKFOOT NE;Lo;0;L;;;;;N;;;;; +15B9;CANADIAN SYLLABICS BLACKFOOT NI;Lo;0;L;;;;;N;;;;; +15BA;CANADIAN SYLLABICS BLACKFOOT NO;Lo;0;L;;;;;N;;;;; +15BB;CANADIAN SYLLABICS BLACKFOOT NA;Lo;0;L;;;;;N;;;;; +15BC;CANADIAN SYLLABICS BLACKFOOT KE;Lo;0;L;;;;;N;;;;; +15BD;CANADIAN SYLLABICS BLACKFOOT KI;Lo;0;L;;;;;N;;;;; +15BE;CANADIAN SYLLABICS BLACKFOOT KO;Lo;0;L;;;;;N;;;;; +15BF;CANADIAN SYLLABICS BLACKFOOT KA;Lo;0;L;;;;;N;;;;; +15C0;CANADIAN SYLLABICS SAYISI HE;Lo;0;L;;;;;N;;;;; +15C1;CANADIAN SYLLABICS SAYISI HI;Lo;0;L;;;;;N;;;;; +15C2;CANADIAN SYLLABICS SAYISI HO;Lo;0;L;;;;;N;;;;; +15C3;CANADIAN SYLLABICS SAYISI HA;Lo;0;L;;;;;N;;;;; +15C4;CANADIAN SYLLABICS CARRIER GHU;Lo;0;L;;;;;N;;;;; +15C5;CANADIAN SYLLABICS CARRIER GHO;Lo;0;L;;;;;N;;;;; +15C6;CANADIAN SYLLABICS CARRIER GHE;Lo;0;L;;;;;N;;;;; +15C7;CANADIAN SYLLABICS CARRIER GHEE;Lo;0;L;;;;;N;;;;; +15C8;CANADIAN SYLLABICS CARRIER GHI;Lo;0;L;;;;;N;;;;; +15C9;CANADIAN SYLLABICS CARRIER GHA;Lo;0;L;;;;;N;;;;; +15CA;CANADIAN SYLLABICS CARRIER RU;Lo;0;L;;;;;N;;;;; +15CB;CANADIAN SYLLABICS CARRIER RO;Lo;0;L;;;;;N;;;;; +15CC;CANADIAN SYLLABICS CARRIER RE;Lo;0;L;;;;;N;;;;; +15CD;CANADIAN SYLLABICS CARRIER REE;Lo;0;L;;;;;N;;;;; +15CE;CANADIAN SYLLABICS CARRIER RI;Lo;0;L;;;;;N;;;;; +15CF;CANADIAN SYLLABICS CARRIER RA;Lo;0;L;;;;;N;;;;; +15D0;CANADIAN SYLLABICS CARRIER WU;Lo;0;L;;;;;N;;;;; +15D1;CANADIAN SYLLABICS CARRIER WO;Lo;0;L;;;;;N;;;;; +15D2;CANADIAN SYLLABICS CARRIER WE;Lo;0;L;;;;;N;;;;; +15D3;CANADIAN SYLLABICS CARRIER WEE;Lo;0;L;;;;;N;;;;; +15D4;CANADIAN SYLLABICS CARRIER WI;Lo;0;L;;;;;N;;;;; +15D5;CANADIAN SYLLABICS CARRIER WA;Lo;0;L;;;;;N;;;;; +15D6;CANADIAN SYLLABICS CARRIER HWU;Lo;0;L;;;;;N;;;;; +15D7;CANADIAN SYLLABICS CARRIER HWO;Lo;0;L;;;;;N;;;;; +15D8;CANADIAN SYLLABICS CARRIER HWE;Lo;0;L;;;;;N;;;;; +15D9;CANADIAN SYLLABICS CARRIER HWEE;Lo;0;L;;;;;N;;;;; +15DA;CANADIAN SYLLABICS CARRIER HWI;Lo;0;L;;;;;N;;;;; +15DB;CANADIAN SYLLABICS CARRIER HWA;Lo;0;L;;;;;N;;;;; +15DC;CANADIAN SYLLABICS CARRIER THU;Lo;0;L;;;;;N;;;;; +15DD;CANADIAN SYLLABICS CARRIER THO;Lo;0;L;;;;;N;;;;; +15DE;CANADIAN SYLLABICS CARRIER THE;Lo;0;L;;;;;N;;;;; +15DF;CANADIAN SYLLABICS CARRIER THEE;Lo;0;L;;;;;N;;;;; +15E0;CANADIAN SYLLABICS CARRIER THI;Lo;0;L;;;;;N;;;;; +15E1;CANADIAN SYLLABICS CARRIER THA;Lo;0;L;;;;;N;;;;; +15E2;CANADIAN SYLLABICS CARRIER TTU;Lo;0;L;;;;;N;;;;; +15E3;CANADIAN SYLLABICS CARRIER TTO;Lo;0;L;;;;;N;;;;; +15E4;CANADIAN SYLLABICS CARRIER TTE;Lo;0;L;;;;;N;;;;; +15E5;CANADIAN SYLLABICS CARRIER TTEE;Lo;0;L;;;;;N;;;;; +15E6;CANADIAN SYLLABICS CARRIER TTI;Lo;0;L;;;;;N;;;;; +15E7;CANADIAN SYLLABICS CARRIER TTA;Lo;0;L;;;;;N;;;;; +15E8;CANADIAN SYLLABICS CARRIER PU;Lo;0;L;;;;;N;;;;; +15E9;CANADIAN SYLLABICS CARRIER PO;Lo;0;L;;;;;N;;;;; +15EA;CANADIAN SYLLABICS CARRIER PE;Lo;0;L;;;;;N;;;;; +15EB;CANADIAN SYLLABICS CARRIER PEE;Lo;0;L;;;;;N;;;;; +15EC;CANADIAN SYLLABICS CARRIER PI;Lo;0;L;;;;;N;;;;; +15ED;CANADIAN SYLLABICS CARRIER PA;Lo;0;L;;;;;N;;;;; +15EE;CANADIAN SYLLABICS CARRIER P;Lo;0;L;;;;;N;;;;; +15EF;CANADIAN SYLLABICS CARRIER GU;Lo;0;L;;;;;N;;;;; +15F0;CANADIAN SYLLABICS CARRIER GO;Lo;0;L;;;;;N;;;;; +15F1;CANADIAN SYLLABICS CARRIER GE;Lo;0;L;;;;;N;;;;; +15F2;CANADIAN SYLLABICS CARRIER GEE;Lo;0;L;;;;;N;;;;; +15F3;CANADIAN SYLLABICS CARRIER GI;Lo;0;L;;;;;N;;;;; +15F4;CANADIAN SYLLABICS CARRIER GA;Lo;0;L;;;;;N;;;;; +15F5;CANADIAN SYLLABICS CARRIER KHU;Lo;0;L;;;;;N;;;;; +15F6;CANADIAN SYLLABICS CARRIER KHO;Lo;0;L;;;;;N;;;;; +15F7;CANADIAN SYLLABICS CARRIER KHE;Lo;0;L;;;;;N;;;;; +15F8;CANADIAN SYLLABICS CARRIER KHEE;Lo;0;L;;;;;N;;;;; +15F9;CANADIAN SYLLABICS CARRIER KHI;Lo;0;L;;;;;N;;;;; +15FA;CANADIAN SYLLABICS CARRIER KHA;Lo;0;L;;;;;N;;;;; +15FB;CANADIAN SYLLABICS CARRIER KKU;Lo;0;L;;;;;N;;;;; +15FC;CANADIAN SYLLABICS CARRIER KKO;Lo;0;L;;;;;N;;;;; +15FD;CANADIAN SYLLABICS CARRIER KKE;Lo;0;L;;;;;N;;;;; +15FE;CANADIAN SYLLABICS CARRIER KKEE;Lo;0;L;;;;;N;;;;; +15FF;CANADIAN SYLLABICS CARRIER KKI;Lo;0;L;;;;;N;;;;; +1600;CANADIAN SYLLABICS CARRIER KKA;Lo;0;L;;;;;N;;;;; +1601;CANADIAN SYLLABICS CARRIER KK;Lo;0;L;;;;;N;;;;; +1602;CANADIAN SYLLABICS CARRIER NU;Lo;0;L;;;;;N;;;;; +1603;CANADIAN SYLLABICS CARRIER NO;Lo;0;L;;;;;N;;;;; +1604;CANADIAN SYLLABICS CARRIER NE;Lo;0;L;;;;;N;;;;; +1605;CANADIAN SYLLABICS CARRIER NEE;Lo;0;L;;;;;N;;;;; +1606;CANADIAN SYLLABICS CARRIER NI;Lo;0;L;;;;;N;;;;; +1607;CANADIAN SYLLABICS CARRIER NA;Lo;0;L;;;;;N;;;;; +1608;CANADIAN SYLLABICS CARRIER MU;Lo;0;L;;;;;N;;;;; +1609;CANADIAN SYLLABICS CARRIER MO;Lo;0;L;;;;;N;;;;; +160A;CANADIAN SYLLABICS CARRIER ME;Lo;0;L;;;;;N;;;;; +160B;CANADIAN SYLLABICS CARRIER MEE;Lo;0;L;;;;;N;;;;; +160C;CANADIAN SYLLABICS CARRIER MI;Lo;0;L;;;;;N;;;;; +160D;CANADIAN SYLLABICS CARRIER MA;Lo;0;L;;;;;N;;;;; +160E;CANADIAN SYLLABICS CARRIER YU;Lo;0;L;;;;;N;;;;; +160F;CANADIAN SYLLABICS CARRIER YO;Lo;0;L;;;;;N;;;;; +1610;CANADIAN SYLLABICS CARRIER YE;Lo;0;L;;;;;N;;;;; +1611;CANADIAN SYLLABICS CARRIER YEE;Lo;0;L;;;;;N;;;;; +1612;CANADIAN SYLLABICS CARRIER YI;Lo;0;L;;;;;N;;;;; +1613;CANADIAN SYLLABICS CARRIER YA;Lo;0;L;;;;;N;;;;; +1614;CANADIAN SYLLABICS CARRIER JU;Lo;0;L;;;;;N;;;;; +1615;CANADIAN SYLLABICS SAYISI JU;Lo;0;L;;;;;N;;;;; +1616;CANADIAN SYLLABICS CARRIER JO;Lo;0;L;;;;;N;;;;; +1617;CANADIAN SYLLABICS CARRIER JE;Lo;0;L;;;;;N;;;;; +1618;CANADIAN SYLLABICS CARRIER JEE;Lo;0;L;;;;;N;;;;; +1619;CANADIAN SYLLABICS CARRIER JI;Lo;0;L;;;;;N;;;;; +161A;CANADIAN SYLLABICS SAYISI JI;Lo;0;L;;;;;N;;;;; +161B;CANADIAN SYLLABICS CARRIER JA;Lo;0;L;;;;;N;;;;; +161C;CANADIAN SYLLABICS CARRIER JJU;Lo;0;L;;;;;N;;;;; +161D;CANADIAN SYLLABICS CARRIER JJO;Lo;0;L;;;;;N;;;;; +161E;CANADIAN SYLLABICS CARRIER JJE;Lo;0;L;;;;;N;;;;; +161F;CANADIAN SYLLABICS CARRIER JJEE;Lo;0;L;;;;;N;;;;; +1620;CANADIAN SYLLABICS CARRIER JJI;Lo;0;L;;;;;N;;;;; +1621;CANADIAN SYLLABICS CARRIER JJA;Lo;0;L;;;;;N;;;;; +1622;CANADIAN SYLLABICS CARRIER LU;Lo;0;L;;;;;N;;;;; +1623;CANADIAN SYLLABICS CARRIER LO;Lo;0;L;;;;;N;;;;; +1624;CANADIAN SYLLABICS CARRIER LE;Lo;0;L;;;;;N;;;;; +1625;CANADIAN SYLLABICS CARRIER LEE;Lo;0;L;;;;;N;;;;; +1626;CANADIAN SYLLABICS CARRIER LI;Lo;0;L;;;;;N;;;;; +1627;CANADIAN SYLLABICS CARRIER LA;Lo;0;L;;;;;N;;;;; +1628;CANADIAN SYLLABICS CARRIER DLU;Lo;0;L;;;;;N;;;;; +1629;CANADIAN SYLLABICS CARRIER DLO;Lo;0;L;;;;;N;;;;; +162A;CANADIAN SYLLABICS CARRIER DLE;Lo;0;L;;;;;N;;;;; +162B;CANADIAN SYLLABICS CARRIER DLEE;Lo;0;L;;;;;N;;;;; +162C;CANADIAN SYLLABICS CARRIER DLI;Lo;0;L;;;;;N;;;;; +162D;CANADIAN SYLLABICS CARRIER DLA;Lo;0;L;;;;;N;;;;; +162E;CANADIAN SYLLABICS CARRIER LHU;Lo;0;L;;;;;N;;;;; +162F;CANADIAN SYLLABICS CARRIER LHO;Lo;0;L;;;;;N;;;;; +1630;CANADIAN SYLLABICS CARRIER LHE;Lo;0;L;;;;;N;;;;; +1631;CANADIAN SYLLABICS CARRIER LHEE;Lo;0;L;;;;;N;;;;; +1632;CANADIAN SYLLABICS CARRIER LHI;Lo;0;L;;;;;N;;;;; +1633;CANADIAN SYLLABICS CARRIER LHA;Lo;0;L;;;;;N;;;;; +1634;CANADIAN SYLLABICS CARRIER TLHU;Lo;0;L;;;;;N;;;;; +1635;CANADIAN SYLLABICS CARRIER TLHO;Lo;0;L;;;;;N;;;;; +1636;CANADIAN SYLLABICS CARRIER TLHE;Lo;0;L;;;;;N;;;;; +1637;CANADIAN SYLLABICS CARRIER TLHEE;Lo;0;L;;;;;N;;;;; +1638;CANADIAN SYLLABICS CARRIER TLHI;Lo;0;L;;;;;N;;;;; +1639;CANADIAN SYLLABICS CARRIER TLHA;Lo;0;L;;;;;N;;;;; +163A;CANADIAN SYLLABICS CARRIER TLU;Lo;0;L;;;;;N;;;;; +163B;CANADIAN SYLLABICS CARRIER TLO;Lo;0;L;;;;;N;;;;; +163C;CANADIAN SYLLABICS CARRIER TLE;Lo;0;L;;;;;N;;;;; +163D;CANADIAN SYLLABICS CARRIER TLEE;Lo;0;L;;;;;N;;;;; +163E;CANADIAN SYLLABICS CARRIER TLI;Lo;0;L;;;;;N;;;;; +163F;CANADIAN SYLLABICS CARRIER TLA;Lo;0;L;;;;;N;;;;; +1640;CANADIAN SYLLABICS CARRIER ZU;Lo;0;L;;;;;N;;;;; +1641;CANADIAN SYLLABICS CARRIER ZO;Lo;0;L;;;;;N;;;;; +1642;CANADIAN SYLLABICS CARRIER ZE;Lo;0;L;;;;;N;;;;; +1643;CANADIAN SYLLABICS CARRIER ZEE;Lo;0;L;;;;;N;;;;; +1644;CANADIAN SYLLABICS CARRIER ZI;Lo;0;L;;;;;N;;;;; +1645;CANADIAN SYLLABICS CARRIER ZA;Lo;0;L;;;;;N;;;;; +1646;CANADIAN SYLLABICS CARRIER Z;Lo;0;L;;;;;N;;;;; +1647;CANADIAN SYLLABICS CARRIER INITIAL Z;Lo;0;L;;;;;N;;;;; +1648;CANADIAN SYLLABICS CARRIER DZU;Lo;0;L;;;;;N;;;;; +1649;CANADIAN SYLLABICS CARRIER DZO;Lo;0;L;;;;;N;;;;; +164A;CANADIAN SYLLABICS CARRIER DZE;Lo;0;L;;;;;N;;;;; +164B;CANADIAN SYLLABICS CARRIER DZEE;Lo;0;L;;;;;N;;;;; +164C;CANADIAN SYLLABICS CARRIER DZI;Lo;0;L;;;;;N;;;;; +164D;CANADIAN SYLLABICS CARRIER DZA;Lo;0;L;;;;;N;;;;; +164E;CANADIAN SYLLABICS CARRIER SU;Lo;0;L;;;;;N;;;;; +164F;CANADIAN SYLLABICS CARRIER SO;Lo;0;L;;;;;N;;;;; +1650;CANADIAN SYLLABICS CARRIER SE;Lo;0;L;;;;;N;;;;; +1651;CANADIAN SYLLABICS CARRIER SEE;Lo;0;L;;;;;N;;;;; +1652;CANADIAN SYLLABICS CARRIER SI;Lo;0;L;;;;;N;;;;; +1653;CANADIAN SYLLABICS CARRIER SA;Lo;0;L;;;;;N;;;;; +1654;CANADIAN SYLLABICS CARRIER SHU;Lo;0;L;;;;;N;;;;; +1655;CANADIAN SYLLABICS CARRIER SHO;Lo;0;L;;;;;N;;;;; +1656;CANADIAN SYLLABICS CARRIER SHE;Lo;0;L;;;;;N;;;;; +1657;CANADIAN SYLLABICS CARRIER SHEE;Lo;0;L;;;;;N;;;;; +1658;CANADIAN SYLLABICS CARRIER SHI;Lo;0;L;;;;;N;;;;; +1659;CANADIAN SYLLABICS CARRIER SHA;Lo;0;L;;;;;N;;;;; +165A;CANADIAN SYLLABICS CARRIER SH;Lo;0;L;;;;;N;;;;; +165B;CANADIAN SYLLABICS CARRIER TSU;Lo;0;L;;;;;N;;;;; +165C;CANADIAN SYLLABICS CARRIER TSO;Lo;0;L;;;;;N;;;;; +165D;CANADIAN SYLLABICS CARRIER TSE;Lo;0;L;;;;;N;;;;; +165E;CANADIAN SYLLABICS CARRIER TSEE;Lo;0;L;;;;;N;;;;; +165F;CANADIAN SYLLABICS CARRIER TSI;Lo;0;L;;;;;N;;;;; +1660;CANADIAN SYLLABICS CARRIER TSA;Lo;0;L;;;;;N;;;;; +1661;CANADIAN SYLLABICS CARRIER CHU;Lo;0;L;;;;;N;;;;; +1662;CANADIAN SYLLABICS CARRIER CHO;Lo;0;L;;;;;N;;;;; +1663;CANADIAN SYLLABICS CARRIER CHE;Lo;0;L;;;;;N;;;;; +1664;CANADIAN SYLLABICS CARRIER CHEE;Lo;0;L;;;;;N;;;;; +1665;CANADIAN SYLLABICS CARRIER CHI;Lo;0;L;;;;;N;;;;; +1666;CANADIAN SYLLABICS CARRIER CHA;Lo;0;L;;;;;N;;;;; +1667;CANADIAN SYLLABICS CARRIER TTSU;Lo;0;L;;;;;N;;;;; +1668;CANADIAN SYLLABICS CARRIER TTSO;Lo;0;L;;;;;N;;;;; +1669;CANADIAN SYLLABICS CARRIER TTSE;Lo;0;L;;;;;N;;;;; +166A;CANADIAN SYLLABICS CARRIER TTSEE;Lo;0;L;;;;;N;;;;; +166B;CANADIAN SYLLABICS CARRIER TTSI;Lo;0;L;;;;;N;;;;; +166C;CANADIAN SYLLABICS CARRIER TTSA;Lo;0;L;;;;;N;;;;; +166D;CANADIAN SYLLABICS CHI SIGN;So;0;L;;;;;N;;;;; +166E;CANADIAN SYLLABICS FULL STOP;Po;0;L;;;;;N;;;;; +166F;CANADIAN SYLLABICS QAI;Lo;0;L;;;;;N;;;;; +1670;CANADIAN SYLLABICS NGAI;Lo;0;L;;;;;N;;;;; +1671;CANADIAN SYLLABICS NNGI;Lo;0;L;;;;;N;;;;; +1672;CANADIAN SYLLABICS NNGII;Lo;0;L;;;;;N;;;;; +1673;CANADIAN SYLLABICS NNGO;Lo;0;L;;;;;N;;;;; +1674;CANADIAN SYLLABICS NNGOO;Lo;0;L;;;;;N;;;;; +1675;CANADIAN SYLLABICS NNGA;Lo;0;L;;;;;N;;;;; +1676;CANADIAN SYLLABICS NNGAA;Lo;0;L;;;;;N;;;;; +1677;CANADIAN SYLLABICS WOODS-CREE THWEE;Lo;0;L;;;;;N;;;;; +1678;CANADIAN SYLLABICS WOODS-CREE THWI;Lo;0;L;;;;;N;;;;; +1679;CANADIAN SYLLABICS WOODS-CREE THWII;Lo;0;L;;;;;N;;;;; +167A;CANADIAN SYLLABICS WOODS-CREE THWO;Lo;0;L;;;;;N;;;;; +167B;CANADIAN SYLLABICS WOODS-CREE THWOO;Lo;0;L;;;;;N;;;;; +167C;CANADIAN SYLLABICS WOODS-CREE THWA;Lo;0;L;;;;;N;;;;; +167D;CANADIAN SYLLABICS WOODS-CREE THWAA;Lo;0;L;;;;;N;;;;; +167E;CANADIAN SYLLABICS WOODS-CREE FINAL TH;Lo;0;L;;;;;N;;;;; +167F;CANADIAN SYLLABICS BLACKFOOT W;Lo;0;L;;;;;N;;;;; +1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;; +1681;OGHAM LETTER BEITH;Lo;0;L;;;;;N;;;;; +1682;OGHAM LETTER LUIS;Lo;0;L;;;;;N;;;;; +1683;OGHAM LETTER FEARN;Lo;0;L;;;;;N;;;;; +1684;OGHAM LETTER SAIL;Lo;0;L;;;;;N;;;;; +1685;OGHAM LETTER NION;Lo;0;L;;;;;N;;;;; +1686;OGHAM LETTER UATH;Lo;0;L;;;;;N;;;;; +1687;OGHAM LETTER DAIR;Lo;0;L;;;;;N;;;;; +1688;OGHAM LETTER TINNE;Lo;0;L;;;;;N;;;;; +1689;OGHAM LETTER COLL;Lo;0;L;;;;;N;;;;; +168A;OGHAM LETTER CEIRT;Lo;0;L;;;;;N;;;;; +168B;OGHAM LETTER MUIN;Lo;0;L;;;;;N;;;;; +168C;OGHAM LETTER GORT;Lo;0;L;;;;;N;;;;; +168D;OGHAM LETTER NGEADAL;Lo;0;L;;;;;N;;;;; +168E;OGHAM LETTER STRAIF;Lo;0;L;;;;;N;;;;; +168F;OGHAM LETTER RUIS;Lo;0;L;;;;;N;;;;; +1690;OGHAM LETTER AILM;Lo;0;L;;;;;N;;;;; +1691;OGHAM LETTER ONN;Lo;0;L;;;;;N;;;;; +1692;OGHAM LETTER UR;Lo;0;L;;;;;N;;;;; +1693;OGHAM LETTER EADHADH;Lo;0;L;;;;;N;;;;; +1694;OGHAM LETTER IODHADH;Lo;0;L;;;;;N;;;;; +1695;OGHAM LETTER EABHADH;Lo;0;L;;;;;N;;;;; +1696;OGHAM LETTER OR;Lo;0;L;;;;;N;;;;; +1697;OGHAM LETTER UILLEANN;Lo;0;L;;;;;N;;;;; +1698;OGHAM LETTER IFIN;Lo;0;L;;;;;N;;;;; +1699;OGHAM LETTER EAMHANCHOLL;Lo;0;L;;;;;N;;;;; +169A;OGHAM LETTER PEITH;Lo;0;L;;;;;N;;;;; +169B;OGHAM FEATHER MARK;Ps;0;ON;;;;;Y;;;;; +169C;OGHAM REVERSED FEATHER MARK;Pe;0;ON;;;;;Y;;;;; +16A0;RUNIC LETTER FEHU FEOH FE F;Lo;0;L;;;;;N;;;;; +16A1;RUNIC LETTER V;Lo;0;L;;;;;N;;;;; +16A2;RUNIC LETTER URUZ UR U;Lo;0;L;;;;;N;;;;; +16A3;RUNIC LETTER YR;Lo;0;L;;;;;N;;;;; +16A4;RUNIC LETTER Y;Lo;0;L;;;;;N;;;;; +16A5;RUNIC LETTER W;Lo;0;L;;;;;N;;;;; +16A6;RUNIC LETTER THURISAZ THURS THORN;Lo;0;L;;;;;N;;;;; +16A7;RUNIC LETTER ETH;Lo;0;L;;;;;N;;;;; +16A8;RUNIC LETTER ANSUZ A;Lo;0;L;;;;;N;;;;; +16A9;RUNIC LETTER OS O;Lo;0;L;;;;;N;;;;; +16AA;RUNIC LETTER AC A;Lo;0;L;;;;;N;;;;; +16AB;RUNIC LETTER AESC;Lo;0;L;;;;;N;;;;; +16AC;RUNIC LETTER LONG-BRANCH-OSS O;Lo;0;L;;;;;N;;;;; +16AD;RUNIC LETTER SHORT-TWIG-OSS O;Lo;0;L;;;;;N;;;;; +16AE;RUNIC LETTER O;Lo;0;L;;;;;N;;;;; +16AF;RUNIC LETTER OE;Lo;0;L;;;;;N;;;;; +16B0;RUNIC LETTER ON;Lo;0;L;;;;;N;;;;; +16B1;RUNIC LETTER RAIDO RAD REID R;Lo;0;L;;;;;N;;;;; +16B2;RUNIC LETTER KAUNA;Lo;0;L;;;;;N;;;;; +16B3;RUNIC LETTER CEN;Lo;0;L;;;;;N;;;;; +16B4;RUNIC LETTER KAUN K;Lo;0;L;;;;;N;;;;; +16B5;RUNIC LETTER G;Lo;0;L;;;;;N;;;;; +16B6;RUNIC LETTER ENG;Lo;0;L;;;;;N;;;;; +16B7;RUNIC LETTER GEBO GYFU G;Lo;0;L;;;;;N;;;;; +16B8;RUNIC LETTER GAR;Lo;0;L;;;;;N;;;;; +16B9;RUNIC LETTER WUNJO WYNN W;Lo;0;L;;;;;N;;;;; +16BA;RUNIC LETTER HAGLAZ H;Lo;0;L;;;;;N;;;;; +16BB;RUNIC LETTER HAEGL H;Lo;0;L;;;;;N;;;;; +16BC;RUNIC LETTER LONG-BRANCH-HAGALL H;Lo;0;L;;;;;N;;;;; +16BD;RUNIC LETTER SHORT-TWIG-HAGALL H;Lo;0;L;;;;;N;;;;; +16BE;RUNIC LETTER NAUDIZ NYD NAUD N;Lo;0;L;;;;;N;;;;; +16BF;RUNIC LETTER SHORT-TWIG-NAUD N;Lo;0;L;;;;;N;;;;; +16C0;RUNIC LETTER DOTTED-N;Lo;0;L;;;;;N;;;;; +16C1;RUNIC LETTER ISAZ IS ISS I;Lo;0;L;;;;;N;;;;; +16C2;RUNIC LETTER E;Lo;0;L;;;;;N;;;;; +16C3;RUNIC LETTER JERAN J;Lo;0;L;;;;;N;;;;; +16C4;RUNIC LETTER GER;Lo;0;L;;;;;N;;;;; +16C5;RUNIC LETTER LONG-BRANCH-AR AE;Lo;0;L;;;;;N;;;;; +16C6;RUNIC LETTER SHORT-TWIG-AR A;Lo;0;L;;;;;N;;;;; +16C7;RUNIC LETTER IWAZ EOH;Lo;0;L;;;;;N;;;;; +16C8;RUNIC LETTER PERTHO PEORTH P;Lo;0;L;;;;;N;;;;; +16C9;RUNIC LETTER ALGIZ EOLHX;Lo;0;L;;;;;N;;;;; +16CA;RUNIC LETTER SOWILO S;Lo;0;L;;;;;N;;;;; +16CB;RUNIC LETTER SIGEL LONG-BRANCH-SOL S;Lo;0;L;;;;;N;;;;; +16CC;RUNIC LETTER SHORT-TWIG-SOL S;Lo;0;L;;;;;N;;;;; +16CD;RUNIC LETTER C;Lo;0;L;;;;;N;;;;; +16CE;RUNIC LETTER Z;Lo;0;L;;;;;N;;;;; +16CF;RUNIC LETTER TIWAZ TIR TYR T;Lo;0;L;;;;;N;;;;; +16D0;RUNIC LETTER SHORT-TWIG-TYR T;Lo;0;L;;;;;N;;;;; +16D1;RUNIC LETTER D;Lo;0;L;;;;;N;;;;; +16D2;RUNIC LETTER BERKANAN BEORC BJARKAN B;Lo;0;L;;;;;N;;;;; +16D3;RUNIC LETTER SHORT-TWIG-BJARKAN B;Lo;0;L;;;;;N;;;;; +16D4;RUNIC LETTER DOTTED-P;Lo;0;L;;;;;N;;;;; +16D5;RUNIC LETTER OPEN-P;Lo;0;L;;;;;N;;;;; +16D6;RUNIC LETTER EHWAZ EH E;Lo;0;L;;;;;N;;;;; +16D7;RUNIC LETTER MANNAZ MAN M;Lo;0;L;;;;;N;;;;; +16D8;RUNIC LETTER LONG-BRANCH-MADR M;Lo;0;L;;;;;N;;;;; +16D9;RUNIC LETTER SHORT-TWIG-MADR M;Lo;0;L;;;;;N;;;;; +16DA;RUNIC LETTER LAUKAZ LAGU LOGR L;Lo;0;L;;;;;N;;;;; +16DB;RUNIC LETTER DOTTED-L;Lo;0;L;;;;;N;;;;; +16DC;RUNIC LETTER INGWAZ;Lo;0;L;;;;;N;;;;; +16DD;RUNIC LETTER ING;Lo;0;L;;;;;N;;;;; +16DE;RUNIC LETTER DAGAZ DAEG D;Lo;0;L;;;;;N;;;;; +16DF;RUNIC LETTER OTHALAN ETHEL O;Lo;0;L;;;;;N;;;;; +16E0;RUNIC LETTER EAR;Lo;0;L;;;;;N;;;;; +16E1;RUNIC LETTER IOR;Lo;0;L;;;;;N;;;;; +16E2;RUNIC LETTER CWEORTH;Lo;0;L;;;;;N;;;;; +16E3;RUNIC LETTER CALC;Lo;0;L;;;;;N;;;;; +16E4;RUNIC LETTER CEALC;Lo;0;L;;;;;N;;;;; +16E5;RUNIC LETTER STAN;Lo;0;L;;;;;N;;;;; +16E6;RUNIC LETTER LONG-BRANCH-YR;Lo;0;L;;;;;N;;;;; +16E7;RUNIC LETTER SHORT-TWIG-YR;Lo;0;L;;;;;N;;;;; +16E8;RUNIC LETTER ICELANDIC-YR;Lo;0;L;;;;;N;;;;; +16E9;RUNIC LETTER Q;Lo;0;L;;;;;N;;;;; +16EA;RUNIC LETTER X;Lo;0;L;;;;;N;;;;; +16EB;RUNIC SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; +16EC;RUNIC MULTIPLE PUNCTUATION;Po;0;L;;;;;N;;;;; +16ED;RUNIC CROSS PUNCTUATION;Po;0;L;;;;;N;;;;; +16EE;RUNIC ARLAUG SYMBOL;Nl;0;L;;;;17;N;;;;; +16EF;RUNIC TVIMADUR SYMBOL;Nl;0;L;;;;18;N;;;;; +16F0;RUNIC BELGTHOR SYMBOL;Nl;0;L;;;;19;N;;;;; +16F1;RUNIC LETTER K;Lo;0;L;;;;;N;;;;; +16F2;RUNIC LETTER SH;Lo;0;L;;;;;N;;;;; +16F3;RUNIC LETTER OO;Lo;0;L;;;;;N;;;;; +16F4;RUNIC LETTER FRANKS CASKET OS;Lo;0;L;;;;;N;;;;; +16F5;RUNIC LETTER FRANKS CASKET IS;Lo;0;L;;;;;N;;;;; +16F6;RUNIC LETTER FRANKS CASKET EH;Lo;0;L;;;;;N;;;;; +16F7;RUNIC LETTER FRANKS CASKET AC;Lo;0;L;;;;;N;;;;; +16F8;RUNIC LETTER FRANKS CASKET AESC;Lo;0;L;;;;;N;;;;; +1700;TAGALOG LETTER A;Lo;0;L;;;;;N;;;;; +1701;TAGALOG LETTER I;Lo;0;L;;;;;N;;;;; +1702;TAGALOG LETTER U;Lo;0;L;;;;;N;;;;; +1703;TAGALOG LETTER KA;Lo;0;L;;;;;N;;;;; +1704;TAGALOG LETTER GA;Lo;0;L;;;;;N;;;;; +1705;TAGALOG LETTER NGA;Lo;0;L;;;;;N;;;;; +1706;TAGALOG LETTER TA;Lo;0;L;;;;;N;;;;; +1707;TAGALOG LETTER DA;Lo;0;L;;;;;N;;;;; +1708;TAGALOG LETTER NA;Lo;0;L;;;;;N;;;;; +1709;TAGALOG LETTER PA;Lo;0;L;;;;;N;;;;; +170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;; +170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;; +170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;; +170D;TAGALOG LETTER RA;Lo;0;L;;;;;N;;;;; +170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;; +170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;; +1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;; +1711;TAGALOG LETTER HA;Lo;0;L;;;;;N;;;;; +1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1715;TAGALOG SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;; +171F;TAGALOG LETTER ARCHAIC RA;Lo;0;L;;;;;N;;;;; +1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;; +1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;; +1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;; +1723;HANUNOO LETTER KA;Lo;0;L;;;;;N;;;;; +1724;HANUNOO LETTER GA;Lo;0;L;;;;;N;;;;; +1725;HANUNOO LETTER NGA;Lo;0;L;;;;;N;;;;; +1726;HANUNOO LETTER TA;Lo;0;L;;;;;N;;;;; +1727;HANUNOO LETTER DA;Lo;0;L;;;;;N;;;;; +1728;HANUNOO LETTER NA;Lo;0;L;;;;;N;;;;; +1729;HANUNOO LETTER PA;Lo;0;L;;;;;N;;;;; +172A;HANUNOO LETTER BA;Lo;0;L;;;;;N;;;;; +172B;HANUNOO LETTER MA;Lo;0;L;;;;;N;;;;; +172C;HANUNOO LETTER YA;Lo;0;L;;;;;N;;;;; +172D;HANUNOO LETTER RA;Lo;0;L;;;;;N;;;;; +172E;HANUNOO LETTER LA;Lo;0;L;;;;;N;;;;; +172F;HANUNOO LETTER WA;Lo;0;L;;;;;N;;;;; +1730;HANUNOO LETTER SA;Lo;0;L;;;;;N;;;;; +1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;; +1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1734;HANUNOO SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;; +1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;; +1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;; +1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;; +1741;BUHID LETTER I;Lo;0;L;;;;;N;;;;; +1742;BUHID LETTER U;Lo;0;L;;;;;N;;;;; +1743;BUHID LETTER KA;Lo;0;L;;;;;N;;;;; +1744;BUHID LETTER GA;Lo;0;L;;;;;N;;;;; +1745;BUHID LETTER NGA;Lo;0;L;;;;;N;;;;; +1746;BUHID LETTER TA;Lo;0;L;;;;;N;;;;; +1747;BUHID LETTER DA;Lo;0;L;;;;;N;;;;; +1748;BUHID LETTER NA;Lo;0;L;;;;;N;;;;; +1749;BUHID LETTER PA;Lo;0;L;;;;;N;;;;; +174A;BUHID LETTER BA;Lo;0;L;;;;;N;;;;; +174B;BUHID LETTER MA;Lo;0;L;;;;;N;;;;; +174C;BUHID LETTER YA;Lo;0;L;;;;;N;;;;; +174D;BUHID LETTER RA;Lo;0;L;;;;;N;;;;; +174E;BUHID LETTER LA;Lo;0;L;;;;;N;;;;; +174F;BUHID LETTER WA;Lo;0;L;;;;;N;;;;; +1750;BUHID LETTER SA;Lo;0;L;;;;;N;;;;; +1751;BUHID LETTER HA;Lo;0;L;;;;;N;;;;; +1752;BUHID VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1753;BUHID VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1760;TAGBANWA LETTER A;Lo;0;L;;;;;N;;;;; +1761;TAGBANWA LETTER I;Lo;0;L;;;;;N;;;;; +1762;TAGBANWA LETTER U;Lo;0;L;;;;;N;;;;; +1763;TAGBANWA LETTER KA;Lo;0;L;;;;;N;;;;; +1764;TAGBANWA LETTER GA;Lo;0;L;;;;;N;;;;; +1765;TAGBANWA LETTER NGA;Lo;0;L;;;;;N;;;;; +1766;TAGBANWA LETTER TA;Lo;0;L;;;;;N;;;;; +1767;TAGBANWA LETTER DA;Lo;0;L;;;;;N;;;;; +1768;TAGBANWA LETTER NA;Lo;0;L;;;;;N;;;;; +1769;TAGBANWA LETTER PA;Lo;0;L;;;;;N;;;;; +176A;TAGBANWA LETTER BA;Lo;0;L;;;;;N;;;;; +176B;TAGBANWA LETTER MA;Lo;0;L;;;;;N;;;;; +176C;TAGBANWA LETTER YA;Lo;0;L;;;;;N;;;;; +176E;TAGBANWA LETTER LA;Lo;0;L;;;;;N;;;;; +176F;TAGBANWA LETTER WA;Lo;0;L;;;;;N;;;;; +1770;TAGBANWA LETTER SA;Lo;0;L;;;;;N;;;;; +1772;TAGBANWA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1773;TAGBANWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1780;KHMER LETTER KA;Lo;0;L;;;;;N;;;;; +1781;KHMER LETTER KHA;Lo;0;L;;;;;N;;;;; +1782;KHMER LETTER KO;Lo;0;L;;;;;N;;;;; +1783;KHMER LETTER KHO;Lo;0;L;;;;;N;;;;; +1784;KHMER LETTER NGO;Lo;0;L;;;;;N;;;;; +1785;KHMER LETTER CA;Lo;0;L;;;;;N;;;;; +1786;KHMER LETTER CHA;Lo;0;L;;;;;N;;;;; +1787;KHMER LETTER CO;Lo;0;L;;;;;N;;;;; +1788;KHMER LETTER CHO;Lo;0;L;;;;;N;;;;; +1789;KHMER LETTER NYO;Lo;0;L;;;;;N;;;;; +178A;KHMER LETTER DA;Lo;0;L;;;;;N;;;;; +178B;KHMER LETTER TTHA;Lo;0;L;;;;;N;;;;; +178C;KHMER LETTER DO;Lo;0;L;;;;;N;;;;; +178D;KHMER LETTER TTHO;Lo;0;L;;;;;N;;;;; +178E;KHMER LETTER NNO;Lo;0;L;;;;;N;;;;; +178F;KHMER LETTER TA;Lo;0;L;;;;;N;;;;; +1790;KHMER LETTER THA;Lo;0;L;;;;;N;;;;; +1791;KHMER LETTER TO;Lo;0;L;;;;;N;;;;; +1792;KHMER LETTER THO;Lo;0;L;;;;;N;;;;; +1793;KHMER LETTER NO;Lo;0;L;;;;;N;;;;; +1794;KHMER LETTER BA;Lo;0;L;;;;;N;;;;; +1795;KHMER LETTER PHA;Lo;0;L;;;;;N;;;;; +1796;KHMER LETTER PO;Lo;0;L;;;;;N;;;;; +1797;KHMER LETTER PHO;Lo;0;L;;;;;N;;;;; +1798;KHMER LETTER MO;Lo;0;L;;;;;N;;;;; +1799;KHMER LETTER YO;Lo;0;L;;;;;N;;;;; +179A;KHMER LETTER RO;Lo;0;L;;;;;N;;;;; +179B;KHMER LETTER LO;Lo;0;L;;;;;N;;;;; +179C;KHMER LETTER VO;Lo;0;L;;;;;N;;;;; +179D;KHMER LETTER SHA;Lo;0;L;;;;;N;;;;; +179E;KHMER LETTER SSO;Lo;0;L;;;;;N;;;;; +179F;KHMER LETTER SA;Lo;0;L;;;;;N;;;;; +17A0;KHMER LETTER HA;Lo;0;L;;;;;N;;;;; +17A1;KHMER LETTER LA;Lo;0;L;;;;;N;;;;; +17A2;KHMER LETTER QA;Lo;0;L;;;;;N;;;;; +17A3;KHMER INDEPENDENT VOWEL QAQ;Lo;0;L;;;;;N;;;;; +17A4;KHMER INDEPENDENT VOWEL QAA;Lo;0;L;;;;;N;;;;; +17A5;KHMER INDEPENDENT VOWEL QI;Lo;0;L;;;;;N;;;;; +17A6;KHMER INDEPENDENT VOWEL QII;Lo;0;L;;;;;N;;;;; +17A7;KHMER INDEPENDENT VOWEL QU;Lo;0;L;;;;;N;;;;; +17A8;KHMER INDEPENDENT VOWEL QUK;Lo;0;L;;;;;N;;;;; +17A9;KHMER INDEPENDENT VOWEL QUU;Lo;0;L;;;;;N;;;;; +17AA;KHMER INDEPENDENT VOWEL QUUV;Lo;0;L;;;;;N;;;;; +17AB;KHMER INDEPENDENT VOWEL RY;Lo;0;L;;;;;N;;;;; +17AC;KHMER INDEPENDENT VOWEL RYY;Lo;0;L;;;;;N;;;;; +17AD;KHMER INDEPENDENT VOWEL LY;Lo;0;L;;;;;N;;;;; +17AE;KHMER INDEPENDENT VOWEL LYY;Lo;0;L;;;;;N;;;;; +17AF;KHMER INDEPENDENT VOWEL QE;Lo;0;L;;;;;N;;;;; +17B0;KHMER INDEPENDENT VOWEL QAI;Lo;0;L;;;;;N;;;;; +17B1;KHMER INDEPENDENT VOWEL QOO TYPE ONE;Lo;0;L;;;;;N;;;;; +17B2;KHMER INDEPENDENT VOWEL QOO TYPE TWO;Lo;0;L;;;;;N;;;;; +17B3;KHMER INDEPENDENT VOWEL QAU;Lo;0;L;;;;;N;;;;; +17B4;KHMER VOWEL INHERENT AQ;Mn;0;NSM;;;;;N;;;;; +17B5;KHMER VOWEL INHERENT AA;Mn;0;NSM;;;;;N;;;;; +17B6;KHMER VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +17B7;KHMER VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +17B8;KHMER VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +17B9;KHMER VOWEL SIGN Y;Mn;0;NSM;;;;;N;;;;; +17BA;KHMER VOWEL SIGN YY;Mn;0;NSM;;;;;N;;;;; +17BB;KHMER VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +17BC;KHMER VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +17BD;KHMER VOWEL SIGN UA;Mn;0;NSM;;;;;N;;;;; +17BE;KHMER VOWEL SIGN OE;Mc;0;L;;;;;N;;;;; +17BF;KHMER VOWEL SIGN YA;Mc;0;L;;;;;N;;;;; +17C0;KHMER VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; +17C1;KHMER VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +17C2;KHMER VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +17C3;KHMER VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +17C4;KHMER VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +17C5;KHMER VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +17C6;KHMER SIGN NIKAHIT;Mn;0;NSM;;;;;N;;;;; +17C7;KHMER SIGN REAHMUK;Mc;0;L;;;;;N;;;;; +17C8;KHMER SIGN YUUKALEAPINTU;Mc;0;L;;;;;N;;;;; +17C9;KHMER SIGN MUUSIKATOAN;Mn;0;NSM;;;;;N;;;;; +17CA;KHMER SIGN TRIISAP;Mn;0;NSM;;;;;N;;;;; +17CB;KHMER SIGN BANTOC;Mn;0;NSM;;;;;N;;;;; +17CC;KHMER SIGN ROBAT;Mn;0;NSM;;;;;N;;;;; +17CD;KHMER SIGN TOANDAKHIAT;Mn;0;NSM;;;;;N;;;;; +17CE;KHMER SIGN KAKABAT;Mn;0;NSM;;;;;N;;;;; +17CF;KHMER SIGN AHSDA;Mn;0;NSM;;;;;N;;;;; +17D0;KHMER SIGN SAMYOK SANNYA;Mn;0;NSM;;;;;N;;;;; +17D1;KHMER SIGN VIRIAM;Mn;0;NSM;;;;;N;;;;; +17D2;KHMER SIGN COENG;Mn;9;NSM;;;;;N;;;;; +17D3;KHMER SIGN BATHAMASAT;Mn;0;NSM;;;;;N;;;;; +17D4;KHMER SIGN KHAN;Po;0;L;;;;;N;;;;; +17D5;KHMER SIGN BARIYOOSAN;Po;0;L;;;;;N;;;;; +17D6;KHMER SIGN CAMNUC PII KUUH;Po;0;L;;;;;N;;;;; +17D7;KHMER SIGN LEK TOO;Lm;0;L;;;;;N;;;;; +17D8;KHMER SIGN BEYYAL;Po;0;L;;;;;N;;;;; +17D9;KHMER SIGN PHNAEK MUAN;Po;0;L;;;;;N;;;;; +17DA;KHMER SIGN KOOMUUT;Po;0;L;;;;;N;;;;; +17DB;KHMER CURRENCY SYMBOL RIEL;Sc;0;ET;;;;;N;;;;; +17DC;KHMER SIGN AVAKRAHASANYA;Lo;0;L;;;;;N;;;;; +17DD;KHMER SIGN ATTHACAN;Mn;230;NSM;;;;;N;;;;; +17E0;KHMER DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +17E1;KHMER DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +17E2;KHMER DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +17E3;KHMER DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +17E4;KHMER DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +17E5;KHMER DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +17E6;KHMER DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +17E7;KHMER DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +17E8;KHMER DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +17E9;KHMER DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +17F0;KHMER SYMBOL LEK ATTAK SON;No;0;ON;;;;0;N;;;;; +17F1;KHMER SYMBOL LEK ATTAK MUOY;No;0;ON;;;;1;N;;;;; +17F2;KHMER SYMBOL LEK ATTAK PII;No;0;ON;;;;2;N;;;;; +17F3;KHMER SYMBOL LEK ATTAK BEI;No;0;ON;;;;3;N;;;;; +17F4;KHMER SYMBOL LEK ATTAK BUON;No;0;ON;;;;4;N;;;;; +17F5;KHMER SYMBOL LEK ATTAK PRAM;No;0;ON;;;;5;N;;;;; +17F6;KHMER SYMBOL LEK ATTAK PRAM-MUOY;No;0;ON;;;;6;N;;;;; +17F7;KHMER SYMBOL LEK ATTAK PRAM-PII;No;0;ON;;;;7;N;;;;; +17F8;KHMER SYMBOL LEK ATTAK PRAM-BEI;No;0;ON;;;;8;N;;;;; +17F9;KHMER SYMBOL LEK ATTAK PRAM-BUON;No;0;ON;;;;9;N;;;;; +1800;MONGOLIAN BIRGA;Po;0;ON;;;;;N;;;;; +1801;MONGOLIAN ELLIPSIS;Po;0;ON;;;;;N;;;;; +1802;MONGOLIAN COMMA;Po;0;ON;;;;;N;;;;; +1803;MONGOLIAN FULL STOP;Po;0;ON;;;;;N;;;;; +1804;MONGOLIAN COLON;Po;0;ON;;;;;N;;;;; +1805;MONGOLIAN FOUR DOTS;Po;0;ON;;;;;N;;;;; +1806;MONGOLIAN TODO SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; +1807;MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER;Po;0;ON;;;;;N;;;;; +1808;MONGOLIAN MANCHU COMMA;Po;0;ON;;;;;N;;;;; +1809;MONGOLIAN MANCHU FULL STOP;Po;0;ON;;;;;N;;;;; +180A;MONGOLIAN NIRUGU;Po;0;ON;;;;;N;;;;; +180B;MONGOLIAN FREE VARIATION SELECTOR ONE;Mn;0;NSM;;;;;N;;;;; +180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;; +180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;; +180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;; +180F;MONGOLIAN FREE VARIATION SELECTOR FOUR;Mn;0;NSM;;;;;N;;;;; +1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1813;MONGOLIAN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1814;MONGOLIAN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1815;MONGOLIAN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1816;MONGOLIAN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1817;MONGOLIAN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1818;MONGOLIAN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1819;MONGOLIAN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1820;MONGOLIAN LETTER A;Lo;0;L;;;;;N;;;;; +1821;MONGOLIAN LETTER E;Lo;0;L;;;;;N;;;;; +1822;MONGOLIAN LETTER I;Lo;0;L;;;;;N;;;;; +1823;MONGOLIAN LETTER O;Lo;0;L;;;;;N;;;;; +1824;MONGOLIAN LETTER U;Lo;0;L;;;;;N;;;;; +1825;MONGOLIAN LETTER OE;Lo;0;L;;;;;N;;;;; +1826;MONGOLIAN LETTER UE;Lo;0;L;;;;;N;;;;; +1827;MONGOLIAN LETTER EE;Lo;0;L;;;;;N;;;;; +1828;MONGOLIAN LETTER NA;Lo;0;L;;;;;N;;;;; +1829;MONGOLIAN LETTER ANG;Lo;0;L;;;;;N;;;;; +182A;MONGOLIAN LETTER BA;Lo;0;L;;;;;N;;;;; +182B;MONGOLIAN LETTER PA;Lo;0;L;;;;;N;;;;; +182C;MONGOLIAN LETTER QA;Lo;0;L;;;;;N;;;;; +182D;MONGOLIAN LETTER GA;Lo;0;L;;;;;N;;;;; +182E;MONGOLIAN LETTER MA;Lo;0;L;;;;;N;;;;; +182F;MONGOLIAN LETTER LA;Lo;0;L;;;;;N;;;;; +1830;MONGOLIAN LETTER SA;Lo;0;L;;;;;N;;;;; +1831;MONGOLIAN LETTER SHA;Lo;0;L;;;;;N;;;;; +1832;MONGOLIAN LETTER TA;Lo;0;L;;;;;N;;;;; +1833;MONGOLIAN LETTER DA;Lo;0;L;;;;;N;;;;; +1834;MONGOLIAN LETTER CHA;Lo;0;L;;;;;N;;;;; +1835;MONGOLIAN LETTER JA;Lo;0;L;;;;;N;;;;; +1836;MONGOLIAN LETTER YA;Lo;0;L;;;;;N;;;;; +1837;MONGOLIAN LETTER RA;Lo;0;L;;;;;N;;;;; +1838;MONGOLIAN LETTER WA;Lo;0;L;;;;;N;;;;; +1839;MONGOLIAN LETTER FA;Lo;0;L;;;;;N;;;;; +183A;MONGOLIAN LETTER KA;Lo;0;L;;;;;N;;;;; +183B;MONGOLIAN LETTER KHA;Lo;0;L;;;;;N;;;;; +183C;MONGOLIAN LETTER TSA;Lo;0;L;;;;;N;;;;; +183D;MONGOLIAN LETTER ZA;Lo;0;L;;;;;N;;;;; +183E;MONGOLIAN LETTER HAA;Lo;0;L;;;;;N;;;;; +183F;MONGOLIAN LETTER ZRA;Lo;0;L;;;;;N;;;;; +1840;MONGOLIAN LETTER LHA;Lo;0;L;;;;;N;;;;; +1841;MONGOLIAN LETTER ZHI;Lo;0;L;;;;;N;;;;; +1842;MONGOLIAN LETTER CHI;Lo;0;L;;;;;N;;;;; +1843;MONGOLIAN LETTER TODO LONG VOWEL SIGN;Lm;0;L;;;;;N;;;;; +1844;MONGOLIAN LETTER TODO E;Lo;0;L;;;;;N;;;;; +1845;MONGOLIAN LETTER TODO I;Lo;0;L;;;;;N;;;;; +1846;MONGOLIAN LETTER TODO O;Lo;0;L;;;;;N;;;;; +1847;MONGOLIAN LETTER TODO U;Lo;0;L;;;;;N;;;;; +1848;MONGOLIAN LETTER TODO OE;Lo;0;L;;;;;N;;;;; +1849;MONGOLIAN LETTER TODO UE;Lo;0;L;;;;;N;;;;; +184A;MONGOLIAN LETTER TODO ANG;Lo;0;L;;;;;N;;;;; +184B;MONGOLIAN LETTER TODO BA;Lo;0;L;;;;;N;;;;; +184C;MONGOLIAN LETTER TODO PA;Lo;0;L;;;;;N;;;;; +184D;MONGOLIAN LETTER TODO QA;Lo;0;L;;;;;N;;;;; +184E;MONGOLIAN LETTER TODO GA;Lo;0;L;;;;;N;;;;; +184F;MONGOLIAN LETTER TODO MA;Lo;0;L;;;;;N;;;;; +1850;MONGOLIAN LETTER TODO TA;Lo;0;L;;;;;N;;;;; +1851;MONGOLIAN LETTER TODO DA;Lo;0;L;;;;;N;;;;; +1852;MONGOLIAN LETTER TODO CHA;Lo;0;L;;;;;N;;;;; +1853;MONGOLIAN LETTER TODO JA;Lo;0;L;;;;;N;;;;; +1854;MONGOLIAN LETTER TODO TSA;Lo;0;L;;;;;N;;;;; +1855;MONGOLIAN LETTER TODO YA;Lo;0;L;;;;;N;;;;; +1856;MONGOLIAN LETTER TODO WA;Lo;0;L;;;;;N;;;;; +1857;MONGOLIAN LETTER TODO KA;Lo;0;L;;;;;N;;;;; +1858;MONGOLIAN LETTER TODO GAA;Lo;0;L;;;;;N;;;;; +1859;MONGOLIAN LETTER TODO HAA;Lo;0;L;;;;;N;;;;; +185A;MONGOLIAN LETTER TODO JIA;Lo;0;L;;;;;N;;;;; +185B;MONGOLIAN LETTER TODO NIA;Lo;0;L;;;;;N;;;;; +185C;MONGOLIAN LETTER TODO DZA;Lo;0;L;;;;;N;;;;; +185D;MONGOLIAN LETTER SIBE E;Lo;0;L;;;;;N;;;;; +185E;MONGOLIAN LETTER SIBE I;Lo;0;L;;;;;N;;;;; +185F;MONGOLIAN LETTER SIBE IY;Lo;0;L;;;;;N;;;;; +1860;MONGOLIAN LETTER SIBE UE;Lo;0;L;;;;;N;;;;; +1861;MONGOLIAN LETTER SIBE U;Lo;0;L;;;;;N;;;;; +1862;MONGOLIAN LETTER SIBE ANG;Lo;0;L;;;;;N;;;;; +1863;MONGOLIAN LETTER SIBE KA;Lo;0;L;;;;;N;;;;; +1864;MONGOLIAN LETTER SIBE GA;Lo;0;L;;;;;N;;;;; +1865;MONGOLIAN LETTER SIBE HA;Lo;0;L;;;;;N;;;;; +1866;MONGOLIAN LETTER SIBE PA;Lo;0;L;;;;;N;;;;; +1867;MONGOLIAN LETTER SIBE SHA;Lo;0;L;;;;;N;;;;; +1868;MONGOLIAN LETTER SIBE TA;Lo;0;L;;;;;N;;;;; +1869;MONGOLIAN LETTER SIBE DA;Lo;0;L;;;;;N;;;;; +186A;MONGOLIAN LETTER SIBE JA;Lo;0;L;;;;;N;;;;; +186B;MONGOLIAN LETTER SIBE FA;Lo;0;L;;;;;N;;;;; +186C;MONGOLIAN LETTER SIBE GAA;Lo;0;L;;;;;N;;;;; +186D;MONGOLIAN LETTER SIBE HAA;Lo;0;L;;;;;N;;;;; +186E;MONGOLIAN LETTER SIBE TSA;Lo;0;L;;;;;N;;;;; +186F;MONGOLIAN LETTER SIBE ZA;Lo;0;L;;;;;N;;;;; +1870;MONGOLIAN LETTER SIBE RAA;Lo;0;L;;;;;N;;;;; +1871;MONGOLIAN LETTER SIBE CHA;Lo;0;L;;;;;N;;;;; +1872;MONGOLIAN LETTER SIBE ZHA;Lo;0;L;;;;;N;;;;; +1873;MONGOLIAN LETTER MANCHU I;Lo;0;L;;;;;N;;;;; +1874;MONGOLIAN LETTER MANCHU KA;Lo;0;L;;;;;N;;;;; +1875;MONGOLIAN LETTER MANCHU RA;Lo;0;L;;;;;N;;;;; +1876;MONGOLIAN LETTER MANCHU FA;Lo;0;L;;;;;N;;;;; +1877;MONGOLIAN LETTER MANCHU ZHA;Lo;0;L;;;;;N;;;;; +1878;MONGOLIAN LETTER CHA WITH TWO DOTS;Lo;0;L;;;;;N;;;;; +1880;MONGOLIAN LETTER ALI GALI ANUSVARA ONE;Lo;0;L;;;;;N;;;;; +1881;MONGOLIAN LETTER ALI GALI VISARGA ONE;Lo;0;L;;;;;N;;;;; +1882;MONGOLIAN LETTER ALI GALI DAMARU;Lo;0;L;;;;;N;;;;; +1883;MONGOLIAN LETTER ALI GALI UBADAMA;Lo;0;L;;;;;N;;;;; +1884;MONGOLIAN LETTER ALI GALI INVERTED UBADAMA;Lo;0;L;;;;;N;;;;; +1885;MONGOLIAN LETTER ALI GALI BALUDA;Mn;0;NSM;;;;;N;;;;; +1886;MONGOLIAN LETTER ALI GALI THREE BALUDA;Mn;0;NSM;;;;;N;;;;; +1887;MONGOLIAN LETTER ALI GALI A;Lo;0;L;;;;;N;;;;; +1888;MONGOLIAN LETTER ALI GALI I;Lo;0;L;;;;;N;;;;; +1889;MONGOLIAN LETTER ALI GALI KA;Lo;0;L;;;;;N;;;;; +188A;MONGOLIAN LETTER ALI GALI NGA;Lo;0;L;;;;;N;;;;; +188B;MONGOLIAN LETTER ALI GALI CA;Lo;0;L;;;;;N;;;;; +188C;MONGOLIAN LETTER ALI GALI TTA;Lo;0;L;;;;;N;;;;; +188D;MONGOLIAN LETTER ALI GALI TTHA;Lo;0;L;;;;;N;;;;; +188E;MONGOLIAN LETTER ALI GALI DDA;Lo;0;L;;;;;N;;;;; +188F;MONGOLIAN LETTER ALI GALI NNA;Lo;0;L;;;;;N;;;;; +1890;MONGOLIAN LETTER ALI GALI TA;Lo;0;L;;;;;N;;;;; +1891;MONGOLIAN LETTER ALI GALI DA;Lo;0;L;;;;;N;;;;; +1892;MONGOLIAN LETTER ALI GALI PA;Lo;0;L;;;;;N;;;;; +1893;MONGOLIAN LETTER ALI GALI PHA;Lo;0;L;;;;;N;;;;; +1894;MONGOLIAN LETTER ALI GALI SSA;Lo;0;L;;;;;N;;;;; +1895;MONGOLIAN LETTER ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +1896;MONGOLIAN LETTER ALI GALI ZA;Lo;0;L;;;;;N;;;;; +1897;MONGOLIAN LETTER ALI GALI AH;Lo;0;L;;;;;N;;;;; +1898;MONGOLIAN LETTER TODO ALI GALI TA;Lo;0;L;;;;;N;;;;; +1899;MONGOLIAN LETTER TODO ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +189A;MONGOLIAN LETTER MANCHU ALI GALI GHA;Lo;0;L;;;;;N;;;;; +189B;MONGOLIAN LETTER MANCHU ALI GALI NGA;Lo;0;L;;;;;N;;;;; +189C;MONGOLIAN LETTER MANCHU ALI GALI CA;Lo;0;L;;;;;N;;;;; +189D;MONGOLIAN LETTER MANCHU ALI GALI JHA;Lo;0;L;;;;;N;;;;; +189E;MONGOLIAN LETTER MANCHU ALI GALI TTA;Lo;0;L;;;;;N;;;;; +189F;MONGOLIAN LETTER MANCHU ALI GALI DDHA;Lo;0;L;;;;;N;;;;; +18A0;MONGOLIAN LETTER MANCHU ALI GALI TA;Lo;0;L;;;;;N;;;;; +18A1;MONGOLIAN LETTER MANCHU ALI GALI DHA;Lo;0;L;;;;;N;;;;; +18A2;MONGOLIAN LETTER MANCHU ALI GALI SSA;Lo;0;L;;;;;N;;;;; +18A3;MONGOLIAN LETTER MANCHU ALI GALI CYA;Lo;0;L;;;;;N;;;;; +18A4;MONGOLIAN LETTER MANCHU ALI GALI ZHA;Lo;0;L;;;;;N;;;;; +18A5;MONGOLIAN LETTER MANCHU ALI GALI ZA;Lo;0;L;;;;;N;;;;; +18A6;MONGOLIAN LETTER ALI GALI HALF U;Lo;0;L;;;;;N;;;;; +18A7;MONGOLIAN LETTER ALI GALI HALF YA;Lo;0;L;;;;;N;;;;; +18A8;MONGOLIAN LETTER MANCHU ALI GALI BHA;Lo;0;L;;;;;N;;;;; +18A9;MONGOLIAN LETTER ALI GALI DAGALGA;Mn;228;NSM;;;;;N;;;;; +18AA;MONGOLIAN LETTER MANCHU ALI GALI LHA;Lo;0;L;;;;;N;;;;; +18B0;CANADIAN SYLLABICS OY;Lo;0;L;;;;;N;;;;; +18B1;CANADIAN SYLLABICS AY;Lo;0;L;;;;;N;;;;; +18B2;CANADIAN SYLLABICS AAY;Lo;0;L;;;;;N;;;;; +18B3;CANADIAN SYLLABICS WAY;Lo;0;L;;;;;N;;;;; +18B4;CANADIAN SYLLABICS POY;Lo;0;L;;;;;N;;;;; +18B5;CANADIAN SYLLABICS PAY;Lo;0;L;;;;;N;;;;; +18B6;CANADIAN SYLLABICS PWOY;Lo;0;L;;;;;N;;;;; +18B7;CANADIAN SYLLABICS TAY;Lo;0;L;;;;;N;;;;; +18B8;CANADIAN SYLLABICS KAY;Lo;0;L;;;;;N;;;;; +18B9;CANADIAN SYLLABICS KWAY;Lo;0;L;;;;;N;;;;; +18BA;CANADIAN SYLLABICS MAY;Lo;0;L;;;;;N;;;;; +18BB;CANADIAN SYLLABICS NOY;Lo;0;L;;;;;N;;;;; +18BC;CANADIAN SYLLABICS NAY;Lo;0;L;;;;;N;;;;; +18BD;CANADIAN SYLLABICS LAY;Lo;0;L;;;;;N;;;;; +18BE;CANADIAN SYLLABICS SOY;Lo;0;L;;;;;N;;;;; +18BF;CANADIAN SYLLABICS SAY;Lo;0;L;;;;;N;;;;; +18C0;CANADIAN SYLLABICS SHOY;Lo;0;L;;;;;N;;;;; +18C1;CANADIAN SYLLABICS SHAY;Lo;0;L;;;;;N;;;;; +18C2;CANADIAN SYLLABICS SHWOY;Lo;0;L;;;;;N;;;;; +18C3;CANADIAN SYLLABICS YOY;Lo;0;L;;;;;N;;;;; +18C4;CANADIAN SYLLABICS YAY;Lo;0;L;;;;;N;;;;; +18C5;CANADIAN SYLLABICS RAY;Lo;0;L;;;;;N;;;;; +18C6;CANADIAN SYLLABICS NWI;Lo;0;L;;;;;N;;;;; +18C7;CANADIAN SYLLABICS OJIBWAY NWI;Lo;0;L;;;;;N;;;;; +18C8;CANADIAN SYLLABICS NWII;Lo;0;L;;;;;N;;;;; +18C9;CANADIAN SYLLABICS OJIBWAY NWII;Lo;0;L;;;;;N;;;;; +18CA;CANADIAN SYLLABICS NWO;Lo;0;L;;;;;N;;;;; +18CB;CANADIAN SYLLABICS OJIBWAY NWO;Lo;0;L;;;;;N;;;;; +18CC;CANADIAN SYLLABICS NWOO;Lo;0;L;;;;;N;;;;; +18CD;CANADIAN SYLLABICS OJIBWAY NWOO;Lo;0;L;;;;;N;;;;; +18CE;CANADIAN SYLLABICS RWEE;Lo;0;L;;;;;N;;;;; +18CF;CANADIAN SYLLABICS RWI;Lo;0;L;;;;;N;;;;; +18D0;CANADIAN SYLLABICS RWII;Lo;0;L;;;;;N;;;;; +18D1;CANADIAN SYLLABICS RWO;Lo;0;L;;;;;N;;;;; +18D2;CANADIAN SYLLABICS RWOO;Lo;0;L;;;;;N;;;;; +18D3;CANADIAN SYLLABICS RWA;Lo;0;L;;;;;N;;;;; +18D4;CANADIAN SYLLABICS OJIBWAY P;Lo;0;L;;;;;N;;;;; +18D5;CANADIAN SYLLABICS OJIBWAY T;Lo;0;L;;;;;N;;;;; +18D6;CANADIAN SYLLABICS OJIBWAY K;Lo;0;L;;;;;N;;;;; +18D7;CANADIAN SYLLABICS OJIBWAY C;Lo;0;L;;;;;N;;;;; +18D8;CANADIAN SYLLABICS OJIBWAY M;Lo;0;L;;;;;N;;;;; +18D9;CANADIAN SYLLABICS OJIBWAY N;Lo;0;L;;;;;N;;;;; +18DA;CANADIAN SYLLABICS OJIBWAY S;Lo;0;L;;;;;N;;;;; +18DB;CANADIAN SYLLABICS OJIBWAY SH;Lo;0;L;;;;;N;;;;; +18DC;CANADIAN SYLLABICS EASTERN W;Lo;0;L;;;;;N;;;;; +18DD;CANADIAN SYLLABICS WESTERN W;Lo;0;L;;;;;N;;;;; +18DE;CANADIAN SYLLABICS FINAL SMALL RING;Lo;0;L;;;;;N;;;;; +18DF;CANADIAN SYLLABICS FINAL RAISED DOT;Lo;0;L;;;;;N;;;;; +18E0;CANADIAN SYLLABICS R-CREE RWE;Lo;0;L;;;;;N;;;;; +18E1;CANADIAN SYLLABICS WEST-CREE LOO;Lo;0;L;;;;;N;;;;; +18E2;CANADIAN SYLLABICS WEST-CREE LAA;Lo;0;L;;;;;N;;;;; +18E3;CANADIAN SYLLABICS THWE;Lo;0;L;;;;;N;;;;; +18E4;CANADIAN SYLLABICS THWA;Lo;0;L;;;;;N;;;;; +18E5;CANADIAN SYLLABICS TTHWE;Lo;0;L;;;;;N;;;;; +18E6;CANADIAN SYLLABICS TTHOO;Lo;0;L;;;;;N;;;;; +18E7;CANADIAN SYLLABICS TTHAA;Lo;0;L;;;;;N;;;;; +18E8;CANADIAN SYLLABICS TLHWE;Lo;0;L;;;;;N;;;;; +18E9;CANADIAN SYLLABICS TLHOO;Lo;0;L;;;;;N;;;;; +18EA;CANADIAN SYLLABICS SAYISI SHWE;Lo;0;L;;;;;N;;;;; +18EB;CANADIAN SYLLABICS SAYISI SHOO;Lo;0;L;;;;;N;;;;; +18EC;CANADIAN SYLLABICS SAYISI HOO;Lo;0;L;;;;;N;;;;; +18ED;CANADIAN SYLLABICS CARRIER GWU;Lo;0;L;;;;;N;;;;; +18EE;CANADIAN SYLLABICS CARRIER DENE GEE;Lo;0;L;;;;;N;;;;; +18EF;CANADIAN SYLLABICS CARRIER GAA;Lo;0;L;;;;;N;;;;; +18F0;CANADIAN SYLLABICS CARRIER GWA;Lo;0;L;;;;;N;;;;; +18F1;CANADIAN SYLLABICS SAYISI JUU;Lo;0;L;;;;;N;;;;; +18F2;CANADIAN SYLLABICS CARRIER JWA;Lo;0;L;;;;;N;;;;; +18F3;CANADIAN SYLLABICS BEAVER DENE L;Lo;0;L;;;;;N;;;;; +18F4;CANADIAN SYLLABICS BEAVER DENE R;Lo;0;L;;;;;N;;;;; +18F5;CANADIAN SYLLABICS CARRIER DENTAL S;Lo;0;L;;;;;N;;;;; +1900;LIMBU VOWEL-CARRIER LETTER;Lo;0;L;;;;;N;;;;; +1901;LIMBU LETTER KA;Lo;0;L;;;;;N;;;;; +1902;LIMBU LETTER KHA;Lo;0;L;;;;;N;;;;; +1903;LIMBU LETTER GA;Lo;0;L;;;;;N;;;;; +1904;LIMBU LETTER GHA;Lo;0;L;;;;;N;;;;; +1905;LIMBU LETTER NGA;Lo;0;L;;;;;N;;;;; +1906;LIMBU LETTER CA;Lo;0;L;;;;;N;;;;; +1907;LIMBU LETTER CHA;Lo;0;L;;;;;N;;;;; +1908;LIMBU LETTER JA;Lo;0;L;;;;;N;;;;; +1909;LIMBU LETTER JHA;Lo;0;L;;;;;N;;;;; +190A;LIMBU LETTER YAN;Lo;0;L;;;;;N;;;;; +190B;LIMBU LETTER TA;Lo;0;L;;;;;N;;;;; +190C;LIMBU LETTER THA;Lo;0;L;;;;;N;;;;; +190D;LIMBU LETTER DA;Lo;0;L;;;;;N;;;;; +190E;LIMBU LETTER DHA;Lo;0;L;;;;;N;;;;; +190F;LIMBU LETTER NA;Lo;0;L;;;;;N;;;;; +1910;LIMBU LETTER PA;Lo;0;L;;;;;N;;;;; +1911;LIMBU LETTER PHA;Lo;0;L;;;;;N;;;;; +1912;LIMBU LETTER BA;Lo;0;L;;;;;N;;;;; +1913;LIMBU LETTER BHA;Lo;0;L;;;;;N;;;;; +1914;LIMBU LETTER MA;Lo;0;L;;;;;N;;;;; +1915;LIMBU LETTER YA;Lo;0;L;;;;;N;;;;; +1916;LIMBU LETTER RA;Lo;0;L;;;;;N;;;;; +1917;LIMBU LETTER LA;Lo;0;L;;;;;N;;;;; +1918;LIMBU LETTER WA;Lo;0;L;;;;;N;;;;; +1919;LIMBU LETTER SHA;Lo;0;L;;;;;N;;;;; +191A;LIMBU LETTER SSA;Lo;0;L;;;;;N;;;;; +191B;LIMBU LETTER SA;Lo;0;L;;;;;N;;;;; +191C;LIMBU LETTER HA;Lo;0;L;;;;;N;;;;; +191D;LIMBU LETTER GYAN;Lo;0;L;;;;;N;;;;; +191E;LIMBU LETTER TRA;Lo;0;L;;;;;N;;;;; +1920;LIMBU VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; +1921;LIMBU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1922;LIMBU VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1923;LIMBU VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +1924;LIMBU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1925;LIMBU VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1926;LIMBU VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +1927;LIMBU VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1928;LIMBU VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +1929;LIMBU SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +192A;LIMBU SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; +192B;LIMBU SUBJOINED LETTER WA;Mc;0;L;;;;;N;;;;; +1930;LIMBU SMALL LETTER KA;Mc;0;L;;;;;N;;;;; +1931;LIMBU SMALL LETTER NGA;Mc;0;L;;;;;N;;;;; +1932;LIMBU SMALL LETTER ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1933;LIMBU SMALL LETTER TA;Mc;0;L;;;;;N;;;;; +1934;LIMBU SMALL LETTER NA;Mc;0;L;;;;;N;;;;; +1935;LIMBU SMALL LETTER PA;Mc;0;L;;;;;N;;;;; +1936;LIMBU SMALL LETTER MA;Mc;0;L;;;;;N;;;;; +1937;LIMBU SMALL LETTER RA;Mc;0;L;;;;;N;;;;; +1938;LIMBU SMALL LETTER LA;Mc;0;L;;;;;N;;;;; +1939;LIMBU SIGN MUKPHRENG;Mn;222;NSM;;;;;N;;;;; +193A;LIMBU SIGN KEMPHRENG;Mn;230;NSM;;;;;N;;;;; +193B;LIMBU SIGN SA-I;Mn;220;NSM;;;;;N;;;;; +1940;LIMBU SIGN LOO;So;0;ON;;;;;N;;;;; +1944;LIMBU EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +1945;LIMBU QUESTION MARK;Po;0;ON;;;;;N;;;;; +1946;LIMBU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1947;LIMBU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1948;LIMBU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1949;LIMBU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +194A;LIMBU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +194B;LIMBU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +194C;LIMBU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +194D;LIMBU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +194E;LIMBU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +194F;LIMBU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1950;TAI LE LETTER KA;Lo;0;L;;;;;N;;;;; +1951;TAI LE LETTER XA;Lo;0;L;;;;;N;;;;; +1952;TAI LE LETTER NGA;Lo;0;L;;;;;N;;;;; +1953;TAI LE LETTER TSA;Lo;0;L;;;;;N;;;;; +1954;TAI LE LETTER SA;Lo;0;L;;;;;N;;;;; +1955;TAI LE LETTER YA;Lo;0;L;;;;;N;;;;; +1956;TAI LE LETTER TA;Lo;0;L;;;;;N;;;;; +1957;TAI LE LETTER THA;Lo;0;L;;;;;N;;;;; +1958;TAI LE LETTER LA;Lo;0;L;;;;;N;;;;; +1959;TAI LE LETTER PA;Lo;0;L;;;;;N;;;;; +195A;TAI LE LETTER PHA;Lo;0;L;;;;;N;;;;; +195B;TAI LE LETTER MA;Lo;0;L;;;;;N;;;;; +195C;TAI LE LETTER FA;Lo;0;L;;;;;N;;;;; +195D;TAI LE LETTER VA;Lo;0;L;;;;;N;;;;; +195E;TAI LE LETTER HA;Lo;0;L;;;;;N;;;;; +195F;TAI LE LETTER QA;Lo;0;L;;;;;N;;;;; +1960;TAI LE LETTER KHA;Lo;0;L;;;;;N;;;;; +1961;TAI LE LETTER TSHA;Lo;0;L;;;;;N;;;;; +1962;TAI LE LETTER NA;Lo;0;L;;;;;N;;;;; +1963;TAI LE LETTER A;Lo;0;L;;;;;N;;;;; +1964;TAI LE LETTER I;Lo;0;L;;;;;N;;;;; +1965;TAI LE LETTER EE;Lo;0;L;;;;;N;;;;; +1966;TAI LE LETTER EH;Lo;0;L;;;;;N;;;;; +1967;TAI LE LETTER U;Lo;0;L;;;;;N;;;;; +1968;TAI LE LETTER OO;Lo;0;L;;;;;N;;;;; +1969;TAI LE LETTER O;Lo;0;L;;;;;N;;;;; +196A;TAI LE LETTER UE;Lo;0;L;;;;;N;;;;; +196B;TAI LE LETTER E;Lo;0;L;;;;;N;;;;; +196C;TAI LE LETTER AUE;Lo;0;L;;;;;N;;;;; +196D;TAI LE LETTER AI;Lo;0;L;;;;;N;;;;; +1970;TAI LE LETTER TONE-2;Lo;0;L;;;;;N;;;;; +1971;TAI LE LETTER TONE-3;Lo;0;L;;;;;N;;;;; +1972;TAI LE LETTER TONE-4;Lo;0;L;;;;;N;;;;; +1973;TAI LE LETTER TONE-5;Lo;0;L;;;;;N;;;;; +1974;TAI LE LETTER TONE-6;Lo;0;L;;;;;N;;;;; +1980;NEW TAI LUE LETTER HIGH QA;Lo;0;L;;;;;N;;;;; +1981;NEW TAI LUE LETTER LOW QA;Lo;0;L;;;;;N;;;;; +1982;NEW TAI LUE LETTER HIGH KA;Lo;0;L;;;;;N;;;;; +1983;NEW TAI LUE LETTER HIGH XA;Lo;0;L;;;;;N;;;;; +1984;NEW TAI LUE LETTER HIGH NGA;Lo;0;L;;;;;N;;;;; +1985;NEW TAI LUE LETTER LOW KA;Lo;0;L;;;;;N;;;;; +1986;NEW TAI LUE LETTER LOW XA;Lo;0;L;;;;;N;;;;; +1987;NEW TAI LUE LETTER LOW NGA;Lo;0;L;;;;;N;;;;; +1988;NEW TAI LUE LETTER HIGH TSA;Lo;0;L;;;;;N;;;;; +1989;NEW TAI LUE LETTER HIGH SA;Lo;0;L;;;;;N;;;;; +198A;NEW TAI LUE LETTER HIGH YA;Lo;0;L;;;;;N;;;;; +198B;NEW TAI LUE LETTER LOW TSA;Lo;0;L;;;;;N;;;;; +198C;NEW TAI LUE LETTER LOW SA;Lo;0;L;;;;;N;;;;; +198D;NEW TAI LUE LETTER LOW YA;Lo;0;L;;;;;N;;;;; +198E;NEW TAI LUE LETTER HIGH TA;Lo;0;L;;;;;N;;;;; +198F;NEW TAI LUE LETTER HIGH THA;Lo;0;L;;;;;N;;;;; +1990;NEW TAI LUE LETTER HIGH NA;Lo;0;L;;;;;N;;;;; +1991;NEW TAI LUE LETTER LOW TA;Lo;0;L;;;;;N;;;;; +1992;NEW TAI LUE LETTER LOW THA;Lo;0;L;;;;;N;;;;; +1993;NEW TAI LUE LETTER LOW NA;Lo;0;L;;;;;N;;;;; +1994;NEW TAI LUE LETTER HIGH PA;Lo;0;L;;;;;N;;;;; +1995;NEW TAI LUE LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; +1996;NEW TAI LUE LETTER HIGH MA;Lo;0;L;;;;;N;;;;; +1997;NEW TAI LUE LETTER LOW PA;Lo;0;L;;;;;N;;;;; +1998;NEW TAI LUE LETTER LOW PHA;Lo;0;L;;;;;N;;;;; +1999;NEW TAI LUE LETTER LOW MA;Lo;0;L;;;;;N;;;;; +199A;NEW TAI LUE LETTER HIGH FA;Lo;0;L;;;;;N;;;;; +199B;NEW TAI LUE LETTER HIGH VA;Lo;0;L;;;;;N;;;;; +199C;NEW TAI LUE LETTER HIGH LA;Lo;0;L;;;;;N;;;;; +199D;NEW TAI LUE LETTER LOW FA;Lo;0;L;;;;;N;;;;; +199E;NEW TAI LUE LETTER LOW VA;Lo;0;L;;;;;N;;;;; +199F;NEW TAI LUE LETTER LOW LA;Lo;0;L;;;;;N;;;;; +19A0;NEW TAI LUE LETTER HIGH HA;Lo;0;L;;;;;N;;;;; +19A1;NEW TAI LUE LETTER HIGH DA;Lo;0;L;;;;;N;;;;; +19A2;NEW TAI LUE LETTER HIGH BA;Lo;0;L;;;;;N;;;;; +19A3;NEW TAI LUE LETTER LOW HA;Lo;0;L;;;;;N;;;;; +19A4;NEW TAI LUE LETTER LOW DA;Lo;0;L;;;;;N;;;;; +19A5;NEW TAI LUE LETTER LOW BA;Lo;0;L;;;;;N;;;;; +19A6;NEW TAI LUE LETTER HIGH KVA;Lo;0;L;;;;;N;;;;; +19A7;NEW TAI LUE LETTER HIGH XVA;Lo;0;L;;;;;N;;;;; +19A8;NEW TAI LUE LETTER LOW KVA;Lo;0;L;;;;;N;;;;; +19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;; +19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;; +19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;; +19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Lo;0;L;;;;;N;;;;; +19B1;NEW TAI LUE VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; +19B2;NEW TAI LUE VOWEL SIGN II;Lo;0;L;;;;;N;;;;; +19B3;NEW TAI LUE VOWEL SIGN U;Lo;0;L;;;;;N;;;;; +19B4;NEW TAI LUE VOWEL SIGN UU;Lo;0;L;;;;;N;;;;; +19B5;NEW TAI LUE VOWEL SIGN E;Lo;0;L;;;;;N;;;;; +19B6;NEW TAI LUE VOWEL SIGN AE;Lo;0;L;;;;;N;;;;; +19B7;NEW TAI LUE VOWEL SIGN O;Lo;0;L;;;;;N;;;;; +19B8;NEW TAI LUE VOWEL SIGN OA;Lo;0;L;;;;;N;;;;; +19B9;NEW TAI LUE VOWEL SIGN UE;Lo;0;L;;;;;N;;;;; +19BA;NEW TAI LUE VOWEL SIGN AY;Lo;0;L;;;;;N;;;;; +19BB;NEW TAI LUE VOWEL SIGN AAY;Lo;0;L;;;;;N;;;;; +19BC;NEW TAI LUE VOWEL SIGN UY;Lo;0;L;;;;;N;;;;; +19BD;NEW TAI LUE VOWEL SIGN OY;Lo;0;L;;;;;N;;;;; +19BE;NEW TAI LUE VOWEL SIGN OAY;Lo;0;L;;;;;N;;;;; +19BF;NEW TAI LUE VOWEL SIGN UEY;Lo;0;L;;;;;N;;;;; +19C0;NEW TAI LUE VOWEL SIGN IY;Lo;0;L;;;;;N;;;;; +19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;; +19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;; +19C4;NEW TAI LUE LETTER FINAL M;Lo;0;L;;;;;N;;;;; +19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;; +19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;; +19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;; +19C8;NEW TAI LUE TONE MARK-1;Lo;0;L;;;;;N;;;;; +19C9;NEW TAI LUE TONE MARK-2;Lo;0;L;;;;;N;;;;; +19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +19D3;NEW TAI LUE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +19D4;NEW TAI LUE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +19D5;NEW TAI LUE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +19D6;NEW TAI LUE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;; +19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;; +19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;; +19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; +19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; +19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; +19E3;KHMER SYMBOL BEI KOET;So;0;ON;;;;;N;;;;; +19E4;KHMER SYMBOL BUON KOET;So;0;ON;;;;;N;;;;; +19E5;KHMER SYMBOL PRAM KOET;So;0;ON;;;;;N;;;;; +19E6;KHMER SYMBOL PRAM-MUOY KOET;So;0;ON;;;;;N;;;;; +19E7;KHMER SYMBOL PRAM-PII KOET;So;0;ON;;;;;N;;;;; +19E8;KHMER SYMBOL PRAM-BEI KOET;So;0;ON;;;;;N;;;;; +19E9;KHMER SYMBOL PRAM-BUON KOET;So;0;ON;;;;;N;;;;; +19EA;KHMER SYMBOL DAP KOET;So;0;ON;;;;;N;;;;; +19EB;KHMER SYMBOL DAP-MUOY KOET;So;0;ON;;;;;N;;;;; +19EC;KHMER SYMBOL DAP-PII KOET;So;0;ON;;;;;N;;;;; +19ED;KHMER SYMBOL DAP-BEI KOET;So;0;ON;;;;;N;;;;; +19EE;KHMER SYMBOL DAP-BUON KOET;So;0;ON;;;;;N;;;;; +19EF;KHMER SYMBOL DAP-PRAM KOET;So;0;ON;;;;;N;;;;; +19F0;KHMER SYMBOL TUTEYASAT;So;0;ON;;;;;N;;;;; +19F1;KHMER SYMBOL MUOY ROC;So;0;ON;;;;;N;;;;; +19F2;KHMER SYMBOL PII ROC;So;0;ON;;;;;N;;;;; +19F3;KHMER SYMBOL BEI ROC;So;0;ON;;;;;N;;;;; +19F4;KHMER SYMBOL BUON ROC;So;0;ON;;;;;N;;;;; +19F5;KHMER SYMBOL PRAM ROC;So;0;ON;;;;;N;;;;; +19F6;KHMER SYMBOL PRAM-MUOY ROC;So;0;ON;;;;;N;;;;; +19F7;KHMER SYMBOL PRAM-PII ROC;So;0;ON;;;;;N;;;;; +19F8;KHMER SYMBOL PRAM-BEI ROC;So;0;ON;;;;;N;;;;; +19F9;KHMER SYMBOL PRAM-BUON ROC;So;0;ON;;;;;N;;;;; +19FA;KHMER SYMBOL DAP ROC;So;0;ON;;;;;N;;;;; +19FB;KHMER SYMBOL DAP-MUOY ROC;So;0;ON;;;;;N;;;;; +19FC;KHMER SYMBOL DAP-PII ROC;So;0;ON;;;;;N;;;;; +19FD;KHMER SYMBOL DAP-BEI ROC;So;0;ON;;;;;N;;;;; +19FE;KHMER SYMBOL DAP-BUON ROC;So;0;ON;;;;;N;;;;; +19FF;KHMER SYMBOL DAP-PRAM ROC;So;0;ON;;;;;N;;;;; +1A00;BUGINESE LETTER KA;Lo;0;L;;;;;N;;;;; +1A01;BUGINESE LETTER GA;Lo;0;L;;;;;N;;;;; +1A02;BUGINESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1A03;BUGINESE LETTER NGKA;Lo;0;L;;;;;N;;;;; +1A04;BUGINESE LETTER PA;Lo;0;L;;;;;N;;;;; +1A05;BUGINESE LETTER BA;Lo;0;L;;;;;N;;;;; +1A06;BUGINESE LETTER MA;Lo;0;L;;;;;N;;;;; +1A07;BUGINESE LETTER MPA;Lo;0;L;;;;;N;;;;; +1A08;BUGINESE LETTER TA;Lo;0;L;;;;;N;;;;; +1A09;BUGINESE LETTER DA;Lo;0;L;;;;;N;;;;; +1A0A;BUGINESE LETTER NA;Lo;0;L;;;;;N;;;;; +1A0B;BUGINESE LETTER NRA;Lo;0;L;;;;;N;;;;; +1A0C;BUGINESE LETTER CA;Lo;0;L;;;;;N;;;;; +1A0D;BUGINESE LETTER JA;Lo;0;L;;;;;N;;;;; +1A0E;BUGINESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1A0F;BUGINESE LETTER NYCA;Lo;0;L;;;;;N;;;;; +1A10;BUGINESE LETTER YA;Lo;0;L;;;;;N;;;;; +1A11;BUGINESE LETTER RA;Lo;0;L;;;;;N;;;;; +1A12;BUGINESE LETTER LA;Lo;0;L;;;;;N;;;;; +1A13;BUGINESE LETTER VA;Lo;0;L;;;;;N;;;;; +1A14;BUGINESE LETTER SA;Lo;0;L;;;;;N;;;;; +1A15;BUGINESE LETTER A;Lo;0;L;;;;;N;;;;; +1A16;BUGINESE LETTER HA;Lo;0;L;;;;;N;;;;; +1A17;BUGINESE VOWEL SIGN I;Mn;230;NSM;;;;;N;;;;; +1A18;BUGINESE VOWEL SIGN U;Mn;220;NSM;;;;;N;;;;; +1A19;BUGINESE VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1A1A;BUGINESE VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1A1B;BUGINESE VOWEL SIGN AE;Mn;0;NSM;;;;;N;;;;; +1A1E;BUGINESE PALLAWA;Po;0;L;;;;;N;;;;; +1A1F;BUGINESE END OF SECTION;Po;0;L;;;;;N;;;;; +1A20;TAI THAM LETTER HIGH KA;Lo;0;L;;;;;N;;;;; +1A21;TAI THAM LETTER HIGH KHA;Lo;0;L;;;;;N;;;;; +1A22;TAI THAM LETTER HIGH KXA;Lo;0;L;;;;;N;;;;; +1A23;TAI THAM LETTER LOW KA;Lo;0;L;;;;;N;;;;; +1A24;TAI THAM LETTER LOW KXA;Lo;0;L;;;;;N;;;;; +1A25;TAI THAM LETTER LOW KHA;Lo;0;L;;;;;N;;;;; +1A26;TAI THAM LETTER NGA;Lo;0;L;;;;;N;;;;; +1A27;TAI THAM LETTER HIGH CA;Lo;0;L;;;;;N;;;;; +1A28;TAI THAM LETTER HIGH CHA;Lo;0;L;;;;;N;;;;; +1A29;TAI THAM LETTER LOW CA;Lo;0;L;;;;;N;;;;; +1A2A;TAI THAM LETTER LOW SA;Lo;0;L;;;;;N;;;;; +1A2B;TAI THAM LETTER LOW CHA;Lo;0;L;;;;;N;;;;; +1A2C;TAI THAM LETTER NYA;Lo;0;L;;;;;N;;;;; +1A2D;TAI THAM LETTER RATA;Lo;0;L;;;;;N;;;;; +1A2E;TAI THAM LETTER HIGH RATHA;Lo;0;L;;;;;N;;;;; +1A2F;TAI THAM LETTER DA;Lo;0;L;;;;;N;;;;; +1A30;TAI THAM LETTER LOW RATHA;Lo;0;L;;;;;N;;;;; +1A31;TAI THAM LETTER RANA;Lo;0;L;;;;;N;;;;; +1A32;TAI THAM LETTER HIGH TA;Lo;0;L;;;;;N;;;;; +1A33;TAI THAM LETTER HIGH THA;Lo;0;L;;;;;N;;;;; +1A34;TAI THAM LETTER LOW TA;Lo;0;L;;;;;N;;;;; +1A35;TAI THAM LETTER LOW THA;Lo;0;L;;;;;N;;;;; +1A36;TAI THAM LETTER NA;Lo;0;L;;;;;N;;;;; +1A37;TAI THAM LETTER BA;Lo;0;L;;;;;N;;;;; +1A38;TAI THAM LETTER HIGH PA;Lo;0;L;;;;;N;;;;; +1A39;TAI THAM LETTER HIGH PHA;Lo;0;L;;;;;N;;;;; +1A3A;TAI THAM LETTER HIGH FA;Lo;0;L;;;;;N;;;;; +1A3B;TAI THAM LETTER LOW PA;Lo;0;L;;;;;N;;;;; +1A3C;TAI THAM LETTER LOW FA;Lo;0;L;;;;;N;;;;; +1A3D;TAI THAM LETTER LOW PHA;Lo;0;L;;;;;N;;;;; +1A3E;TAI THAM LETTER MA;Lo;0;L;;;;;N;;;;; +1A3F;TAI THAM LETTER LOW YA;Lo;0;L;;;;;N;;;;; +1A40;TAI THAM LETTER HIGH YA;Lo;0;L;;;;;N;;;;; +1A41;TAI THAM LETTER RA;Lo;0;L;;;;;N;;;;; +1A42;TAI THAM LETTER RUE;Lo;0;L;;;;;N;;;;; +1A43;TAI THAM LETTER LA;Lo;0;L;;;;;N;;;;; +1A44;TAI THAM LETTER LUE;Lo;0;L;;;;;N;;;;; +1A45;TAI THAM LETTER WA;Lo;0;L;;;;;N;;;;; +1A46;TAI THAM LETTER HIGH SHA;Lo;0;L;;;;;N;;;;; +1A47;TAI THAM LETTER HIGH SSA;Lo;0;L;;;;;N;;;;; +1A48;TAI THAM LETTER HIGH SA;Lo;0;L;;;;;N;;;;; +1A49;TAI THAM LETTER HIGH HA;Lo;0;L;;;;;N;;;;; +1A4A;TAI THAM LETTER LLA;Lo;0;L;;;;;N;;;;; +1A4B;TAI THAM LETTER A;Lo;0;L;;;;;N;;;;; +1A4C;TAI THAM LETTER LOW HA;Lo;0;L;;;;;N;;;;; +1A4D;TAI THAM LETTER I;Lo;0;L;;;;;N;;;;; +1A4E;TAI THAM LETTER II;Lo;0;L;;;;;N;;;;; +1A4F;TAI THAM LETTER U;Lo;0;L;;;;;N;;;;; +1A50;TAI THAM LETTER UU;Lo;0;L;;;;;N;;;;; +1A51;TAI THAM LETTER EE;Lo;0;L;;;;;N;;;;; +1A52;TAI THAM LETTER OO;Lo;0;L;;;;;N;;;;; +1A53;TAI THAM LETTER LAE;Lo;0;L;;;;;N;;;;; +1A54;TAI THAM LETTER GREAT SA;Lo;0;L;;;;;N;;;;; +1A55;TAI THAM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; +1A56;TAI THAM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1A57;TAI THAM CONSONANT SIGN LA TANG LAI;Mc;0;L;;;;;N;;;;; +1A58;TAI THAM SIGN MAI KANG LAI;Mn;0;NSM;;;;;N;;;;; +1A59;TAI THAM CONSONANT SIGN FINAL NGA;Mn;0;NSM;;;;;N;;;;; +1A5A;TAI THAM CONSONANT SIGN LOW PA;Mn;0;NSM;;;;;N;;;;; +1A5B;TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA;Mn;0;NSM;;;;;N;;;;; +1A5C;TAI THAM CONSONANT SIGN MA;Mn;0;NSM;;;;;N;;;;; +1A5D;TAI THAM CONSONANT SIGN BA;Mn;0;NSM;;;;;N;;;;; +1A5E;TAI THAM CONSONANT SIGN SA;Mn;0;NSM;;;;;N;;;;; +1A60;TAI THAM SIGN SAKOT;Mn;9;NSM;;;;;N;;;;; +1A61;TAI THAM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +1A62;TAI THAM VOWEL SIGN MAI SAT;Mn;0;NSM;;;;;N;;;;; +1A63;TAI THAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1A64;TAI THAM VOWEL SIGN TALL AA;Mc;0;L;;;;;N;;;;; +1A65;TAI THAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1A66;TAI THAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1A67;TAI THAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +1A68;TAI THAM VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; +1A69;TAI THAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1A6A;TAI THAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1A6B;TAI THAM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +1A6C;TAI THAM VOWEL SIGN OA BELOW;Mn;0;NSM;;;;;N;;;;; +1A6D;TAI THAM VOWEL SIGN OY;Mc;0;L;;;;;N;;;;; +1A6E;TAI THAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1A6F;TAI THAM VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +1A70;TAI THAM VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1A71;TAI THAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1A72;TAI THAM VOWEL SIGN THAM AI;Mc;0;L;;;;;N;;;;; +1A73;TAI THAM VOWEL SIGN OA ABOVE;Mn;0;NSM;;;;;N;;;;; +1A74;TAI THAM SIGN MAI KANG;Mn;0;NSM;;;;;N;;;;; +1A75;TAI THAM SIGN TONE-1;Mn;230;NSM;;;;;N;;;;; +1A76;TAI THAM SIGN TONE-2;Mn;230;NSM;;;;;N;;;;; +1A77;TAI THAM SIGN KHUEN TONE-3;Mn;230;NSM;;;;;N;;;;; +1A78;TAI THAM SIGN KHUEN TONE-4;Mn;230;NSM;;;;;N;;;;; +1A79;TAI THAM SIGN KHUEN TONE-5;Mn;230;NSM;;;;;N;;;;; +1A7A;TAI THAM SIGN RA HAAM;Mn;230;NSM;;;;;N;;;;; +1A7B;TAI THAM SIGN MAI SAM;Mn;230;NSM;;;;;N;;;;; +1A7C;TAI THAM SIGN KHUEN-LUE KARAN;Mn;230;NSM;;;;;N;;;;; +1A7F;TAI THAM COMBINING CRYPTOGRAMMIC DOT;Mn;220;NSM;;;;;N;;;;; +1A80;TAI THAM HORA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1A81;TAI THAM HORA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1A82;TAI THAM HORA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1A83;TAI THAM HORA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1A84;TAI THAM HORA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1A85;TAI THAM HORA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1A86;TAI THAM HORA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1A87;TAI THAM HORA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1A88;TAI THAM HORA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1A89;TAI THAM HORA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1A90;TAI THAM THAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1A91;TAI THAM THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1A92;TAI THAM THAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1A93;TAI THAM THAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1A94;TAI THAM THAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1A95;TAI THAM THAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1A96;TAI THAM THAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1A97;TAI THAM THAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1A98;TAI THAM THAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1A99;TAI THAM THAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1AA0;TAI THAM SIGN WIANG;Po;0;L;;;;;N;;;;; +1AA1;TAI THAM SIGN WIANGWAAK;Po;0;L;;;;;N;;;;; +1AA2;TAI THAM SIGN SAWAN;Po;0;L;;;;;N;;;;; +1AA3;TAI THAM SIGN KEOW;Po;0;L;;;;;N;;;;; +1AA4;TAI THAM SIGN HOY;Po;0;L;;;;;N;;;;; +1AA5;TAI THAM SIGN DOKMAI;Po;0;L;;;;;N;;;;; +1AA6;TAI THAM SIGN REVERSED ROTATED RANA;Po;0;L;;;;;N;;;;; +1AA7;TAI THAM SIGN MAI YAMOK;Lm;0;L;;;;;N;;;;; +1AA8;TAI THAM SIGN KAAN;Po;0;L;;;;;N;;;;; +1AA9;TAI THAM SIGN KAANKUU;Po;0;L;;;;;N;;;;; +1AAA;TAI THAM SIGN SATKAAN;Po;0;L;;;;;N;;;;; +1AAB;TAI THAM SIGN SATKAANKUU;Po;0;L;;;;;N;;;;; +1AAC;TAI THAM SIGN HANG;Po;0;L;;;;;N;;;;; +1AAD;TAI THAM SIGN CAANG;Po;0;L;;;;;N;;;;; +1AB0;COMBINING DOUBLED CIRCUMFLEX ACCENT;Mn;230;NSM;;;;;N;;;;; +1AB1;COMBINING DIAERESIS-RING;Mn;230;NSM;;;;;N;;;;; +1AB2;COMBINING INFINITY;Mn;230;NSM;;;;;N;;;;; +1AB3;COMBINING DOWNWARDS ARROW;Mn;230;NSM;;;;;N;;;;; +1AB4;COMBINING TRIPLE DOT;Mn;230;NSM;;;;;N;;;;; +1AB5;COMBINING X-X BELOW;Mn;220;NSM;;;;;N;;;;; +1AB6;COMBINING WIGGLY LINE BELOW;Mn;220;NSM;;;;;N;;;;; +1AB7;COMBINING OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; +1AB8;COMBINING DOUBLE OPEN MARK BELOW;Mn;220;NSM;;;;;N;;;;; +1AB9;COMBINING LIGHT CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; +1ABA;COMBINING STRONG CENTRALIZATION STROKE BELOW;Mn;220;NSM;;;;;N;;;;; +1ABB;COMBINING PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; +1ABC;COMBINING DOUBLE PARENTHESES ABOVE;Mn;230;NSM;;;;;N;;;;; +1ABD;COMBINING PARENTHESES BELOW;Mn;220;NSM;;;;;N;;;;; +1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;; +1ABF;COMBINING LATIN SMALL LETTER W BELOW;Mn;220;NSM;;;;;N;;;;; +1AC0;COMBINING LATIN SMALL LETTER TURNED W BELOW;Mn;220;NSM;;;;;N;;;;; +1AC1;COMBINING LEFT PARENTHESIS ABOVE LEFT;Mn;230;NSM;;;;;N;;;;; +1AC2;COMBINING RIGHT PARENTHESIS ABOVE RIGHT;Mn;230;NSM;;;;;N;;;;; +1AC3;COMBINING LEFT PARENTHESIS BELOW LEFT;Mn;220;NSM;;;;;N;;;;; +1AC4;COMBINING RIGHT PARENTHESIS BELOW RIGHT;Mn;220;NSM;;;;;N;;;;; +1AC5;COMBINING SQUARE BRACKETS ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC6;COMBINING NUMBER SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC7;COMBINING INVERTED DOUBLE ARCH ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC8;COMBINING PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AC9;COMBINING DOUBLE PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1ACA;COMBINING DOUBLE PLUS SIGN BELOW;Mn;220;NSM;;;;;N;;;;; +1ACB;COMBINING TRIPLE ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +1ACC;COMBINING LATIN SMALL LETTER INSULAR G;Mn;230;NSM;;;;;N;;;;; +1ACD;COMBINING LATIN SMALL LETTER INSULAR R;Mn;230;NSM;;;;;N;;;;; +1ACE;COMBINING LATIN SMALL LETTER INSULAR T;Mn;230;NSM;;;;;N;;;;; +1ACF;COMBINING DOUBLE CARON;Mn;230;NSM;;;;;N;;;;; +1AD0;COMBINING VERTICAL-LINE-ACUTE;Mn;230;NSM;;;;;N;;;;; +1AD1;COMBINING GRAVE-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;; +1AD2;COMBINING VERTICAL-LINE-GRAVE;Mn;230;NSM;;;;;N;;;;; +1AD3;COMBINING ACUTE-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;; +1AD4;COMBINING VERTICAL-LINE-MACRON;Mn;230;NSM;;;;;N;;;;; +1AD5;COMBINING MACRON-VERTICAL-LINE;Mn;230;NSM;;;;;N;;;;; +1AD6;COMBINING VERTICAL-LINE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; +1AD7;COMBINING VERTICAL-LINE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; +1AD8;COMBINING MACRON-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; +1AD9;COMBINING SHARP SIGN;Mn;230;NSM;;;;;N;;;;; +1ADA;COMBINING FLAT SIGN;Mn;230;NSM;;;;;N;;;;; +1ADB;COMBINING DOWN TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1ADC;COMBINING DIAERESIS WITH RAISED LEFT DOT;Mn;230;NSM;;;;;N;;;;; +1ADD;COMBINING DOT-AND-RING BELOW;Mn;220;NSM;;;;;N;;;;; +1AE0;COMBINING LEFT TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE1;COMBINING RIGHT TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE2;COMBINING MINUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE3;COMBINING INVERTED BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE4;COMBINING SQUARE ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE5;COMBINING SEAGULL ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE6;COMBINING DOUBLE ARCH BELOW;Mn;220;NSM;;;;;N;;;;; +1AE7;COMBINING DOUBLE ARCH ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE8;COMBINING EQUALS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;; +1AE9;COMBINING LEFT ANGLE CENTRED ABOVE;Mn;230;NSM;;;;;N;;;;; +1AEA;COMBINING UPWARDS ARROW ABOVE;Mn;230;NSM;;;;;N;;;;; +1AEB;COMBINING DOUBLE RIGHTWARDS ARROW ABOVE;Mn;234;NSM;;;;;N;;;;; +1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;; +1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;; +1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;; +1B03;BALINESE SIGN SURANG;Mn;0;NSM;;;;;N;;;;; +1B04;BALINESE SIGN BISAH;Mc;0;L;;;;;N;;;;; +1B05;BALINESE LETTER AKARA;Lo;0;L;;;;;N;;;;; +1B06;BALINESE LETTER AKARA TEDUNG;Lo;0;L;1B05 1B35;;;;N;;;;; +1B07;BALINESE LETTER IKARA;Lo;0;L;;;;;N;;;;; +1B08;BALINESE LETTER IKARA TEDUNG;Lo;0;L;1B07 1B35;;;;N;;;;; +1B09;BALINESE LETTER UKARA;Lo;0;L;;;;;N;;;;; +1B0A;BALINESE LETTER UKARA TEDUNG;Lo;0;L;1B09 1B35;;;;N;;;;; +1B0B;BALINESE LETTER RA REPA;Lo;0;L;;;;;N;;;;; +1B0C;BALINESE LETTER RA REPA TEDUNG;Lo;0;L;1B0B 1B35;;;;N;;;;; +1B0D;BALINESE LETTER LA LENGA;Lo;0;L;;;;;N;;;;; +1B0E;BALINESE LETTER LA LENGA TEDUNG;Lo;0;L;1B0D 1B35;;;;N;;;;; +1B0F;BALINESE LETTER EKARA;Lo;0;L;;;;;N;;;;; +1B10;BALINESE LETTER AIKARA;Lo;0;L;;;;;N;;;;; +1B11;BALINESE LETTER OKARA;Lo;0;L;;;;;N;;;;; +1B12;BALINESE LETTER OKARA TEDUNG;Lo;0;L;1B11 1B35;;;;N;;;;; +1B13;BALINESE LETTER KA;Lo;0;L;;;;;N;;;;; +1B14;BALINESE LETTER KA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B15;BALINESE LETTER GA;Lo;0;L;;;;;N;;;;; +1B16;BALINESE LETTER GA GORA;Lo;0;L;;;;;N;;;;; +1B17;BALINESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1B18;BALINESE LETTER CA;Lo;0;L;;;;;N;;;;; +1B19;BALINESE LETTER CA LACA;Lo;0;L;;;;;N;;;;; +1B1A;BALINESE LETTER JA;Lo;0;L;;;;;N;;;;; +1B1B;BALINESE LETTER JA JERA;Lo;0;L;;;;;N;;;;; +1B1C;BALINESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1B1D;BALINESE LETTER TA LATIK;Lo;0;L;;;;;N;;;;; +1B1E;BALINESE LETTER TA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B1F;BALINESE LETTER DA MURDA ALPAPRANA;Lo;0;L;;;;;N;;;;; +1B20;BALINESE LETTER DA MURDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +1B21;BALINESE LETTER NA RAMBAT;Lo;0;L;;;;;N;;;;; +1B22;BALINESE LETTER TA;Lo;0;L;;;;;N;;;;; +1B23;BALINESE LETTER TA TAWA;Lo;0;L;;;;;N;;;;; +1B24;BALINESE LETTER DA;Lo;0;L;;;;;N;;;;; +1B25;BALINESE LETTER DA MADU;Lo;0;L;;;;;N;;;;; +1B26;BALINESE LETTER NA;Lo;0;L;;;;;N;;;;; +1B27;BALINESE LETTER PA;Lo;0;L;;;;;N;;;;; +1B28;BALINESE LETTER PA KAPAL;Lo;0;L;;;;;N;;;;; +1B29;BALINESE LETTER BA;Lo;0;L;;;;;N;;;;; +1B2A;BALINESE LETTER BA KEMBANG;Lo;0;L;;;;;N;;;;; +1B2B;BALINESE LETTER MA;Lo;0;L;;;;;N;;;;; +1B2C;BALINESE LETTER YA;Lo;0;L;;;;;N;;;;; +1B2D;BALINESE LETTER RA;Lo;0;L;;;;;N;;;;; +1B2E;BALINESE LETTER LA;Lo;0;L;;;;;N;;;;; +1B2F;BALINESE LETTER WA;Lo;0;L;;;;;N;;;;; +1B30;BALINESE LETTER SA SAGA;Lo;0;L;;;;;N;;;;; +1B31;BALINESE LETTER SA SAPA;Lo;0;L;;;;;N;;;;; +1B32;BALINESE LETTER SA;Lo;0;L;;;;;N;;;;; +1B33;BALINESE LETTER HA;Lo;0;L;;;;;N;;;;; +1B34;BALINESE SIGN REREKAN;Mn;7;NSM;;;;;N;;;;; +1B35;BALINESE VOWEL SIGN TEDUNG;Mc;0;L;;;;;N;;;;; +1B36;BALINESE VOWEL SIGN ULU;Mn;0;NSM;;;;;N;;;;; +1B37;BALINESE VOWEL SIGN ULU SARI;Mn;0;NSM;;;;;N;;;;; +1B38;BALINESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; +1B39;BALINESE VOWEL SIGN SUKU ILUT;Mn;0;NSM;;;;;N;;;;; +1B3A;BALINESE VOWEL SIGN RA REPA;Mn;0;NSM;;;;;N;;;;; +1B3B;BALINESE VOWEL SIGN RA REPA TEDUNG;Mc;0;L;1B3A 1B35;;;;N;;;;; +1B3C;BALINESE VOWEL SIGN LA LENGA;Mn;0;NSM;;;;;N;;;;; +1B3D;BALINESE VOWEL SIGN LA LENGA TEDUNG;Mc;0;L;1B3C 1B35;;;;N;;;;; +1B3E;BALINESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; +1B3F;BALINESE VOWEL SIGN TALING REPA;Mc;0;L;;;;;N;;;;; +1B40;BALINESE VOWEL SIGN TALING TEDUNG;Mc;0;L;1B3E 1B35;;;;N;;;;; +1B41;BALINESE VOWEL SIGN TALING REPA TEDUNG;Mc;0;L;1B3F 1B35;;;;N;;;;; +1B42;BALINESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; +1B43;BALINESE VOWEL SIGN PEPET TEDUNG;Mc;0;L;1B42 1B35;;;;N;;;;; +1B44;BALINESE ADEG ADEG;Mc;9;L;;;;;N;;;;; +1B45;BALINESE LETTER KAF SASAK;Lo;0;L;;;;;N;;;;; +1B46;BALINESE LETTER KHOT SASAK;Lo;0;L;;;;;N;;;;; +1B47;BALINESE LETTER TZIR SASAK;Lo;0;L;;;;;N;;;;; +1B48;BALINESE LETTER EF SASAK;Lo;0;L;;;;;N;;;;; +1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;; +1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;; +1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;; +1B4C;BALINESE LETTER ARCHAIC JNYA;Lo;0;L;;;;;N;;;;; +1B4E;BALINESE INVERTED CARIK SIKI;Po;0;L;;;;;N;;;;; +1B4F;BALINESE INVERTED CARIK PAREREN;Po;0;L;;;;;N;;;;; +1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1B53;BALINESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1B54;BALINESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1B55;BALINESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1B56;BALINESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1B57;BALINESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1B58;BALINESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1B59;BALINESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1B5A;BALINESE PANTI;Po;0;L;;;;;N;;;;; +1B5B;BALINESE PAMADA;Po;0;L;;;;;N;;;;; +1B5C;BALINESE WINDU;Po;0;L;;;;;N;;;;; +1B5D;BALINESE CARIK PAMUNGKAH;Po;0;L;;;;;N;;;;; +1B5E;BALINESE CARIK SIKI;Po;0;L;;;;;N;;;;; +1B5F;BALINESE CARIK PAREREN;Po;0;L;;;;;N;;;;; +1B60;BALINESE PAMENENG;Po;0;L;;;;;N;;;;; +1B61;BALINESE MUSICAL SYMBOL DONG;So;0;L;;;;;N;;;;; +1B62;BALINESE MUSICAL SYMBOL DENG;So;0;L;;;;;N;;;;; +1B63;BALINESE MUSICAL SYMBOL DUNG;So;0;L;;;;;N;;;;; +1B64;BALINESE MUSICAL SYMBOL DANG;So;0;L;;;;;N;;;;; +1B65;BALINESE MUSICAL SYMBOL DANG SURANG;So;0;L;;;;;N;;;;; +1B66;BALINESE MUSICAL SYMBOL DING;So;0;L;;;;;N;;;;; +1B67;BALINESE MUSICAL SYMBOL DAENG;So;0;L;;;;;N;;;;; +1B68;BALINESE MUSICAL SYMBOL DEUNG;So;0;L;;;;;N;;;;; +1B69;BALINESE MUSICAL SYMBOL DAING;So;0;L;;;;;N;;;;; +1B6A;BALINESE MUSICAL SYMBOL DANG GEDE;So;0;L;;;;;N;;;;; +1B6B;BALINESE MUSICAL SYMBOL COMBINING TEGEH;Mn;230;NSM;;;;;N;;;;; +1B6C;BALINESE MUSICAL SYMBOL COMBINING ENDEP;Mn;220;NSM;;;;;N;;;;; +1B6D;BALINESE MUSICAL SYMBOL COMBINING KEMPUL;Mn;230;NSM;;;;;N;;;;; +1B6E;BALINESE MUSICAL SYMBOL COMBINING KEMPLI;Mn;230;NSM;;;;;N;;;;; +1B6F;BALINESE MUSICAL SYMBOL COMBINING JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B70;BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B71;BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN;Mn;230;NSM;;;;;N;;;;; +1B72;BALINESE MUSICAL SYMBOL COMBINING BENDE;Mn;230;NSM;;;;;N;;;;; +1B73;BALINESE MUSICAL SYMBOL COMBINING GONG;Mn;230;NSM;;;;;N;;;;; +1B74;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG;So;0;L;;;;;N;;;;; +1B75;BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG;So;0;L;;;;;N;;;;; +1B76;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK;So;0;L;;;;;N;;;;; +1B77;BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK;So;0;L;;;;;N;;;;; +1B78;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG;So;0;L;;;;;N;;;;; +1B79;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG;So;0;L;;;;;N;;;;; +1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;; +1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;; +1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;; +1B7D;BALINESE PANTI LANTANG;Po;0;L;;;;;N;;;;; +1B7E;BALINESE PAMADA LANTANG;Po;0;L;;;;;N;;;;; +1B7F;BALINESE PANTI BAWAK;Po;0;L;;;;;N;;;;; +1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;; +1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;; +1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;; +1B83;SUNDANESE LETTER A;Lo;0;L;;;;;N;;;;; +1B84;SUNDANESE LETTER I;Lo;0;L;;;;;N;;;;; +1B85;SUNDANESE LETTER U;Lo;0;L;;;;;N;;;;; +1B86;SUNDANESE LETTER AE;Lo;0;L;;;;;N;;;;; +1B87;SUNDANESE LETTER O;Lo;0;L;;;;;N;;;;; +1B88;SUNDANESE LETTER E;Lo;0;L;;;;;N;;;;; +1B89;SUNDANESE LETTER EU;Lo;0;L;;;;;N;;;;; +1B8A;SUNDANESE LETTER KA;Lo;0;L;;;;;N;;;;; +1B8B;SUNDANESE LETTER QA;Lo;0;L;;;;;N;;;;; +1B8C;SUNDANESE LETTER GA;Lo;0;L;;;;;N;;;;; +1B8D;SUNDANESE LETTER NGA;Lo;0;L;;;;;N;;;;; +1B8E;SUNDANESE LETTER CA;Lo;0;L;;;;;N;;;;; +1B8F;SUNDANESE LETTER JA;Lo;0;L;;;;;N;;;;; +1B90;SUNDANESE LETTER ZA;Lo;0;L;;;;;N;;;;; +1B91;SUNDANESE LETTER NYA;Lo;0;L;;;;;N;;;;; +1B92;SUNDANESE LETTER TA;Lo;0;L;;;;;N;;;;; +1B93;SUNDANESE LETTER DA;Lo;0;L;;;;;N;;;;; +1B94;SUNDANESE LETTER NA;Lo;0;L;;;;;N;;;;; +1B95;SUNDANESE LETTER PA;Lo;0;L;;;;;N;;;;; +1B96;SUNDANESE LETTER FA;Lo;0;L;;;;;N;;;;; +1B97;SUNDANESE LETTER VA;Lo;0;L;;;;;N;;;;; +1B98;SUNDANESE LETTER BA;Lo;0;L;;;;;N;;;;; +1B99;SUNDANESE LETTER MA;Lo;0;L;;;;;N;;;;; +1B9A;SUNDANESE LETTER YA;Lo;0;L;;;;;N;;;;; +1B9B;SUNDANESE LETTER RA;Lo;0;L;;;;;N;;;;; +1B9C;SUNDANESE LETTER LA;Lo;0;L;;;;;N;;;;; +1B9D;SUNDANESE LETTER WA;Lo;0;L;;;;;N;;;;; +1B9E;SUNDANESE LETTER SA;Lo;0;L;;;;;N;;;;; +1B9F;SUNDANESE LETTER XA;Lo;0;L;;;;;N;;;;; +1BA0;SUNDANESE LETTER HA;Lo;0;L;;;;;N;;;;; +1BA1;SUNDANESE CONSONANT SIGN PAMINGKAL;Mc;0;L;;;;;N;;;;; +1BA2;SUNDANESE CONSONANT SIGN PANYAKRA;Mn;0;NSM;;;;;N;;;;; +1BA3;SUNDANESE CONSONANT SIGN PANYIKU;Mn;0;NSM;;;;;N;;;;; +1BA4;SUNDANESE VOWEL SIGN PANGHULU;Mn;0;NSM;;;;;N;;;;; +1BA5;SUNDANESE VOWEL SIGN PANYUKU;Mn;0;NSM;;;;;N;;;;; +1BA6;SUNDANESE VOWEL SIGN PANAELAENG;Mc;0;L;;;;;N;;;;; +1BA7;SUNDANESE VOWEL SIGN PANOLONG;Mc;0;L;;;;;N;;;;; +1BA8;SUNDANESE VOWEL SIGN PAMEPET;Mn;0;NSM;;;;;N;;;;; +1BA9;SUNDANESE VOWEL SIGN PANEULEUNG;Mn;0;NSM;;;;;N;;;;; +1BAA;SUNDANESE SIGN PAMAAEH;Mc;9;L;;;;;N;;;;; +1BAB;SUNDANESE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1BAC;SUNDANESE CONSONANT SIGN PASANGAN MA;Mn;0;NSM;;;;;N;;;;; +1BAD;SUNDANESE CONSONANT SIGN PASANGAN WA;Mn;0;NSM;;;;;N;;;;; +1BAE;SUNDANESE LETTER KHA;Lo;0;L;;;;;N;;;;; +1BAF;SUNDANESE LETTER SYA;Lo;0;L;;;;;N;;;;; +1BB0;SUNDANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1BB1;SUNDANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1BB2;SUNDANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1BB3;SUNDANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1BB4;SUNDANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1BB5;SUNDANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1BB6;SUNDANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1BBA;SUNDANESE AVAGRAHA;Lo;0;L;;;;;N;;;;; +1BBB;SUNDANESE LETTER REU;Lo;0;L;;;;;N;;;;; +1BBC;SUNDANESE LETTER LEU;Lo;0;L;;;;;N;;;;; +1BBD;SUNDANESE LETTER BHA;Lo;0;L;;;;;N;;;;; +1BBE;SUNDANESE LETTER FINAL K;Lo;0;L;;;;;N;;;;; +1BBF;SUNDANESE LETTER FINAL M;Lo;0;L;;;;;N;;;;; +1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;; +1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;; +1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;; +1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;; +1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;; +1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;; +1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;; +1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;; +1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;; +1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;; +1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;; +1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;; +1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;; +1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;; +1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;; +1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;; +1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;; +1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;; +1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;; +1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;; +1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;; +1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;; +1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;; +1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;; +1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;; +1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;; +1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;; +1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;; +1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;; +1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;; +1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;; +1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;; +1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;; +1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;; +1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;; +1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;; +1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;; +1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;; +1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;; +1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;; +1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;; +1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;; +1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;; +1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;; +1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;; +1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;; +1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;; +1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;; +1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;; +1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;; +1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; +1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; +1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; +1C03;LEPCHA LETTER GA;Lo;0;L;;;;;N;;;;; +1C04;LEPCHA LETTER GLA;Lo;0;L;;;;;N;;;;; +1C05;LEPCHA LETTER NGA;Lo;0;L;;;;;N;;;;; +1C06;LEPCHA LETTER CA;Lo;0;L;;;;;N;;;;; +1C07;LEPCHA LETTER CHA;Lo;0;L;;;;;N;;;;; +1C08;LEPCHA LETTER JA;Lo;0;L;;;;;N;;;;; +1C09;LEPCHA LETTER NYA;Lo;0;L;;;;;N;;;;; +1C0A;LEPCHA LETTER TA;Lo;0;L;;;;;N;;;;; +1C0B;LEPCHA LETTER THA;Lo;0;L;;;;;N;;;;; +1C0C;LEPCHA LETTER DA;Lo;0;L;;;;;N;;;;; +1C0D;LEPCHA LETTER NA;Lo;0;L;;;;;N;;;;; +1C0E;LEPCHA LETTER PA;Lo;0;L;;;;;N;;;;; +1C0F;LEPCHA LETTER PLA;Lo;0;L;;;;;N;;;;; +1C10;LEPCHA LETTER PHA;Lo;0;L;;;;;N;;;;; +1C11;LEPCHA LETTER FA;Lo;0;L;;;;;N;;;;; +1C12;LEPCHA LETTER FLA;Lo;0;L;;;;;N;;;;; +1C13;LEPCHA LETTER BA;Lo;0;L;;;;;N;;;;; +1C14;LEPCHA LETTER BLA;Lo;0;L;;;;;N;;;;; +1C15;LEPCHA LETTER MA;Lo;0;L;;;;;N;;;;; +1C16;LEPCHA LETTER MLA;Lo;0;L;;;;;N;;;;; +1C17;LEPCHA LETTER TSA;Lo;0;L;;;;;N;;;;; +1C18;LEPCHA LETTER TSHA;Lo;0;L;;;;;N;;;;; +1C19;LEPCHA LETTER DZA;Lo;0;L;;;;;N;;;;; +1C1A;LEPCHA LETTER YA;Lo;0;L;;;;;N;;;;; +1C1B;LEPCHA LETTER RA;Lo;0;L;;;;;N;;;;; +1C1C;LEPCHA LETTER LA;Lo;0;L;;;;;N;;;;; +1C1D;LEPCHA LETTER HA;Lo;0;L;;;;;N;;;;; +1C1E;LEPCHA LETTER HLA;Lo;0;L;;;;;N;;;;; +1C1F;LEPCHA LETTER VA;Lo;0;L;;;;;N;;;;; +1C20;LEPCHA LETTER SA;Lo;0;L;;;;;N;;;;; +1C21;LEPCHA LETTER SHA;Lo;0;L;;;;;N;;;;; +1C22;LEPCHA LETTER WA;Lo;0;L;;;;;N;;;;; +1C23;LEPCHA LETTER A;Lo;0;L;;;;;N;;;;; +1C24;LEPCHA SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +1C25;LEPCHA SUBJOINED LETTER RA;Mc;0;L;;;;;N;;;;; +1C26;LEPCHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1C27;LEPCHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1C28;LEPCHA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1C29;LEPCHA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +1C2A;LEPCHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +1C2B;LEPCHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +1C2C;LEPCHA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1C2D;LEPCHA CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +1C2E;LEPCHA CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +1C2F;LEPCHA CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +1C30;LEPCHA CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +1C31;LEPCHA CONSONANT SIGN P;Mn;0;NSM;;;;;N;;;;; +1C32;LEPCHA CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +1C33;LEPCHA CONSONANT SIGN T;Mn;0;NSM;;;;;N;;;;; +1C34;LEPCHA CONSONANT SIGN NYIN-DO;Mc;0;L;;;;;N;;;;; +1C35;LEPCHA CONSONANT SIGN KANG;Mc;0;L;;;;;N;;;;; +1C36;LEPCHA SIGN RAN;Mn;0;NSM;;;;;N;;;;; +1C37;LEPCHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +1C3B;LEPCHA PUNCTUATION TA-ROL;Po;0;L;;;;;N;;;;; +1C3C;LEPCHA PUNCTUATION NYET THYOOM TA-ROL;Po;0;L;;;;;N;;;;; +1C3D;LEPCHA PUNCTUATION CER-WA;Po;0;L;;;;;N;;;;; +1C3E;LEPCHA PUNCTUATION TSHOOK CER-WA;Po;0;L;;;;;N;;;;; +1C3F;LEPCHA PUNCTUATION TSHOOK;Po;0;L;;;;;N;;;;; +1C40;LEPCHA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1C41;LEPCHA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1C42;LEPCHA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1C43;LEPCHA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1C44;LEPCHA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1C45;LEPCHA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1C46;LEPCHA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1C47;LEPCHA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1C48;LEPCHA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1C49;LEPCHA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1C4D;LEPCHA LETTER TTA;Lo;0;L;;;;;N;;;;; +1C4E;LEPCHA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1C4F;LEPCHA LETTER DDA;Lo;0;L;;;;;N;;;;; +1C50;OL CHIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1C51;OL CHIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1C52;OL CHIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1C53;OL CHIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1C54;OL CHIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1C55;OL CHIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1C56;OL CHIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1C57;OL CHIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1C58;OL CHIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1C59;OL CHIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1C5A;OL CHIKI LETTER LA;Lo;0;L;;;;;N;;;;; +1C5B;OL CHIKI LETTER AT;Lo;0;L;;;;;N;;;;; +1C5C;OL CHIKI LETTER AG;Lo;0;L;;;;;N;;;;; +1C5D;OL CHIKI LETTER ANG;Lo;0;L;;;;;N;;;;; +1C5E;OL CHIKI LETTER AL;Lo;0;L;;;;;N;;;;; +1C5F;OL CHIKI LETTER LAA;Lo;0;L;;;;;N;;;;; +1C60;OL CHIKI LETTER AAK;Lo;0;L;;;;;N;;;;; +1C61;OL CHIKI LETTER AAJ;Lo;0;L;;;;;N;;;;; +1C62;OL CHIKI LETTER AAM;Lo;0;L;;;;;N;;;;; +1C63;OL CHIKI LETTER AAW;Lo;0;L;;;;;N;;;;; +1C64;OL CHIKI LETTER LI;Lo;0;L;;;;;N;;;;; +1C65;OL CHIKI LETTER IS;Lo;0;L;;;;;N;;;;; +1C66;OL CHIKI LETTER IH;Lo;0;L;;;;;N;;;;; +1C67;OL CHIKI LETTER INY;Lo;0;L;;;;;N;;;;; +1C68;OL CHIKI LETTER IR;Lo;0;L;;;;;N;;;;; +1C69;OL CHIKI LETTER LU;Lo;0;L;;;;;N;;;;; +1C6A;OL CHIKI LETTER UC;Lo;0;L;;;;;N;;;;; +1C6B;OL CHIKI LETTER UD;Lo;0;L;;;;;N;;;;; +1C6C;OL CHIKI LETTER UNN;Lo;0;L;;;;;N;;;;; +1C6D;OL CHIKI LETTER UY;Lo;0;L;;;;;N;;;;; +1C6E;OL CHIKI LETTER LE;Lo;0;L;;;;;N;;;;; +1C6F;OL CHIKI LETTER EP;Lo;0;L;;;;;N;;;;; +1C70;OL CHIKI LETTER EDD;Lo;0;L;;;;;N;;;;; +1C71;OL CHIKI LETTER EN;Lo;0;L;;;;;N;;;;; +1C72;OL CHIKI LETTER ERR;Lo;0;L;;;;;N;;;;; +1C73;OL CHIKI LETTER LO;Lo;0;L;;;;;N;;;;; +1C74;OL CHIKI LETTER OTT;Lo;0;L;;;;;N;;;;; +1C75;OL CHIKI LETTER OB;Lo;0;L;;;;;N;;;;; +1C76;OL CHIKI LETTER OV;Lo;0;L;;;;;N;;;;; +1C77;OL CHIKI LETTER OH;Lo;0;L;;;;;N;;;;; +1C78;OL CHIKI MU TTUDDAG;Lm;0;L;;;;;N;;;;; +1C79;OL CHIKI GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; +1C7A;OL CHIKI MU-GAAHLAA TTUDDAAG;Lm;0;L;;;;;N;;;;; +1C7B;OL CHIKI RELAA;Lm;0;L;;;;;N;;;;; +1C7C;OL CHIKI PHAARKAA;Lm;0;L;;;;;N;;;;; +1C7D;OL CHIKI AHAD;Lm;0;L;;;;;N;;;;; +1C7E;OL CHIKI PUNCTUATION MUCAAD;Po;0;L;;;;;N;;;;; +1C7F;OL CHIKI PUNCTUATION DOUBLE MUCAAD;Po;0;L;;;;;N;;;;; +1C80;CYRILLIC SMALL LETTER ROUNDED VE;Ll;0;L;;;;;N;;;0412;;0412 +1C81;CYRILLIC SMALL LETTER LONG-LEGGED DE;Ll;0;L;;;;;N;;;0414;;0414 +1C82;CYRILLIC SMALL LETTER NARROW O;Ll;0;L;;;;;N;;;041E;;041E +1C83;CYRILLIC SMALL LETTER WIDE ES;Ll;0;L;;;;;N;;;0421;;0421 +1C84;CYRILLIC SMALL LETTER TALL TE;Ll;0;L;;;;;N;;;0422;;0422 +1C85;CYRILLIC SMALL LETTER THREE-LEGGED TE;Ll;0;L;;;;;N;;;0422;;0422 +1C86;CYRILLIC SMALL LETTER TALL HARD SIGN;Ll;0;L;;;;;N;;;042A;;042A +1C87;CYRILLIC SMALL LETTER TALL YAT;Ll;0;L;;;;;N;;;0462;;0462 +1C88;CYRILLIC SMALL LETTER UNBLENDED UK;Ll;0;L;;;;;N;;;A64A;;A64A +1C89;CYRILLIC CAPITAL LETTER TJE;Lu;0;L;;;;;N;;;;1C8A; +1C8A;CYRILLIC SMALL LETTER TJE;Ll;0;L;;;;;N;;;1C89;;1C89 +1C90;GEORGIAN MTAVRULI CAPITAL LETTER AN;Lu;0;L;;;;;N;;;;10D0; +1C91;GEORGIAN MTAVRULI CAPITAL LETTER BAN;Lu;0;L;;;;;N;;;;10D1; +1C92;GEORGIAN MTAVRULI CAPITAL LETTER GAN;Lu;0;L;;;;;N;;;;10D2; +1C93;GEORGIAN MTAVRULI CAPITAL LETTER DON;Lu;0;L;;;;;N;;;;10D3; +1C94;GEORGIAN MTAVRULI CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;10D4; +1C95;GEORGIAN MTAVRULI CAPITAL LETTER VIN;Lu;0;L;;;;;N;;;;10D5; +1C96;GEORGIAN MTAVRULI CAPITAL LETTER ZEN;Lu;0;L;;;;;N;;;;10D6; +1C97;GEORGIAN MTAVRULI CAPITAL LETTER TAN;Lu;0;L;;;;;N;;;;10D7; +1C98;GEORGIAN MTAVRULI CAPITAL LETTER IN;Lu;0;L;;;;;N;;;;10D8; +1C99;GEORGIAN MTAVRULI CAPITAL LETTER KAN;Lu;0;L;;;;;N;;;;10D9; +1C9A;GEORGIAN MTAVRULI CAPITAL LETTER LAS;Lu;0;L;;;;;N;;;;10DA; +1C9B;GEORGIAN MTAVRULI CAPITAL LETTER MAN;Lu;0;L;;;;;N;;;;10DB; +1C9C;GEORGIAN MTAVRULI CAPITAL LETTER NAR;Lu;0;L;;;;;N;;;;10DC; +1C9D;GEORGIAN MTAVRULI CAPITAL LETTER ON;Lu;0;L;;;;;N;;;;10DD; +1C9E;GEORGIAN MTAVRULI CAPITAL LETTER PAR;Lu;0;L;;;;;N;;;;10DE; +1C9F;GEORGIAN MTAVRULI CAPITAL LETTER ZHAR;Lu;0;L;;;;;N;;;;10DF; +1CA0;GEORGIAN MTAVRULI CAPITAL LETTER RAE;Lu;0;L;;;;;N;;;;10E0; +1CA1;GEORGIAN MTAVRULI CAPITAL LETTER SAN;Lu;0;L;;;;;N;;;;10E1; +1CA2;GEORGIAN MTAVRULI CAPITAL LETTER TAR;Lu;0;L;;;;;N;;;;10E2; +1CA3;GEORGIAN MTAVRULI CAPITAL LETTER UN;Lu;0;L;;;;;N;;;;10E3; +1CA4;GEORGIAN MTAVRULI CAPITAL LETTER PHAR;Lu;0;L;;;;;N;;;;10E4; +1CA5;GEORGIAN MTAVRULI CAPITAL LETTER KHAR;Lu;0;L;;;;;N;;;;10E5; +1CA6;GEORGIAN MTAVRULI CAPITAL LETTER GHAN;Lu;0;L;;;;;N;;;;10E6; +1CA7;GEORGIAN MTAVRULI CAPITAL LETTER QAR;Lu;0;L;;;;;N;;;;10E7; +1CA8;GEORGIAN MTAVRULI CAPITAL LETTER SHIN;Lu;0;L;;;;;N;;;;10E8; +1CA9;GEORGIAN MTAVRULI CAPITAL LETTER CHIN;Lu;0;L;;;;;N;;;;10E9; +1CAA;GEORGIAN MTAVRULI CAPITAL LETTER CAN;Lu;0;L;;;;;N;;;;10EA; +1CAB;GEORGIAN MTAVRULI CAPITAL LETTER JIL;Lu;0;L;;;;;N;;;;10EB; +1CAC;GEORGIAN MTAVRULI CAPITAL LETTER CIL;Lu;0;L;;;;;N;;;;10EC; +1CAD;GEORGIAN MTAVRULI CAPITAL LETTER CHAR;Lu;0;L;;;;;N;;;;10ED; +1CAE;GEORGIAN MTAVRULI CAPITAL LETTER XAN;Lu;0;L;;;;;N;;;;10EE; +1CAF;GEORGIAN MTAVRULI CAPITAL LETTER JHAN;Lu;0;L;;;;;N;;;;10EF; +1CB0;GEORGIAN MTAVRULI CAPITAL LETTER HAE;Lu;0;L;;;;;N;;;;10F0; +1CB1;GEORGIAN MTAVRULI CAPITAL LETTER HE;Lu;0;L;;;;;N;;;;10F1; +1CB2;GEORGIAN MTAVRULI CAPITAL LETTER HIE;Lu;0;L;;;;;N;;;;10F2; +1CB3;GEORGIAN MTAVRULI CAPITAL LETTER WE;Lu;0;L;;;;;N;;;;10F3; +1CB4;GEORGIAN MTAVRULI CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;10F4; +1CB5;GEORGIAN MTAVRULI CAPITAL LETTER HOE;Lu;0;L;;;;;N;;;;10F5; +1CB6;GEORGIAN MTAVRULI CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;10F6; +1CB7;GEORGIAN MTAVRULI CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;10F7; +1CB8;GEORGIAN MTAVRULI CAPITAL LETTER ELIFI;Lu;0;L;;;;;N;;;;10F8; +1CB9;GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN;Lu;0;L;;;;;N;;;;10F9; +1CBA;GEORGIAN MTAVRULI CAPITAL LETTER AIN;Lu;0;L;;;;;N;;;;10FA; +1CBD;GEORGIAN MTAVRULI CAPITAL LETTER AEN;Lu;0;L;;;;;N;;;;10FD; +1CBE;GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN;Lu;0;L;;;;;N;;;;10FE; +1CBF;GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN;Lu;0;L;;;;;N;;;;10FF; +1CC0;SUNDANESE PUNCTUATION BINDU SURYA;Po;0;L;;;;;N;;;;; +1CC1;SUNDANESE PUNCTUATION BINDU PANGLONG;Po;0;L;;;;;N;;;;; +1CC2;SUNDANESE PUNCTUATION BINDU PURNAMA;Po;0;L;;;;;N;;;;; +1CC3;SUNDANESE PUNCTUATION BINDU CAKRA;Po;0;L;;;;;N;;;;; +1CC4;SUNDANESE PUNCTUATION BINDU LEU SATANGA;Po;0;L;;;;;N;;;;; +1CC5;SUNDANESE PUNCTUATION BINDU KA SATANGA;Po;0;L;;;;;N;;;;; +1CC6;SUNDANESE PUNCTUATION BINDU DA SATANGA;Po;0;L;;;;;N;;;;; +1CC7;SUNDANESE PUNCTUATION BINDU BA SATANGA;Po;0;L;;;;;N;;;;; +1CD0;VEDIC TONE KARSHANA;Mn;230;NSM;;;;;N;;;;; +1CD1;VEDIC TONE SHARA;Mn;230;NSM;;;;;N;;;;; +1CD2;VEDIC TONE PRENKHA;Mn;230;NSM;;;;;N;;;;; +1CD3;VEDIC SIGN NIHSHVASA;Po;0;L;;;;;N;;;;; +1CD4;VEDIC SIGN YAJURVEDIC MIDLINE SVARITA;Mn;1;NSM;;;;;N;;;;; +1CD5;VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD6;VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD7;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA;Mn;220;NSM;;;;;N;;;;; +1CD8;VEDIC TONE CANDRA BELOW;Mn;220;NSM;;;;;N;;;;; +1CD9;VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER;Mn;220;NSM;;;;;N;;;;; +1CDA;VEDIC TONE DOUBLE SVARITA;Mn;230;NSM;;;;;N;;;;; +1CDB;VEDIC TONE TRIPLE SVARITA;Mn;230;NSM;;;;;N;;;;; +1CDC;VEDIC TONE KATHAKA ANUDATTA;Mn;220;NSM;;;;;N;;;;; +1CDD;VEDIC TONE DOT BELOW;Mn;220;NSM;;;;;N;;;;; +1CDE;VEDIC TONE TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +1CDF;VEDIC TONE THREE DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +1CE0;VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA;Mn;230;NSM;;;;;N;;;;; +1CE1;VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA;Mc;0;L;;;;;N;;;;; +1CE2;VEDIC SIGN VISARGA SVARITA;Mn;1;NSM;;;;;N;;;;; +1CE3;VEDIC SIGN VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; +1CE4;VEDIC SIGN REVERSED VISARGA UDATTA;Mn;1;NSM;;;;;N;;;;; +1CE5;VEDIC SIGN VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; +1CE6;VEDIC SIGN REVERSED VISARGA ANUDATTA;Mn;1;NSM;;;;;N;;;;; +1CE7;VEDIC SIGN VISARGA UDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; +1CE8;VEDIC SIGN VISARGA ANUDATTA WITH TAIL;Mn;1;NSM;;;;;N;;;;; +1CE9;VEDIC SIGN ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEA;VEDIC SIGN ANUSVARA BAHIRGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEB;VEDIC SIGN ANUSVARA VAMAGOMUKHA;Lo;0;L;;;;;N;;;;; +1CEC;VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL;Lo;0;L;;;;;N;;;;; +1CED;VEDIC SIGN TIRYAK;Mn;220;NSM;;;;;N;;;;; +1CEE;VEDIC SIGN HEXIFORM LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CEF;VEDIC SIGN LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CF0;VEDIC SIGN RTHANG LONG ANUSVARA;Lo;0;L;;;;;N;;;;; +1CF1;VEDIC SIGN ANUSVARA UBHAYATO MUKHA;Lo;0;L;;;;;N;;;;; +1CF2;VEDIC SIGN ARDHAVISARGA;Lo;0;L;;;;;N;;;;; +1CF3;VEDIC SIGN ROTATED ARDHAVISARGA;Lo;0;L;;;;;N;;;;; +1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;; +1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;; +1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;; +1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;; +1CFA;VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA;Lo;0;L;;;;;N;;;;; +1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;; +1D01;LATIN LETTER SMALL CAPITAL AE;Ll;0;L;;;;;N;;;;; +1D02;LATIN SMALL LETTER TURNED AE;Ll;0;L;;;;;N;;;;; +1D03;LATIN LETTER SMALL CAPITAL BARRED B;Ll;0;L;;;;;N;;;;; +1D04;LATIN LETTER SMALL CAPITAL C;Ll;0;L;;;;;N;;;;; +1D05;LATIN LETTER SMALL CAPITAL D;Ll;0;L;;;;;N;;;;; +1D06;LATIN LETTER SMALL CAPITAL ETH;Ll;0;L;;;;;N;;;;; +1D07;LATIN LETTER SMALL CAPITAL E;Ll;0;L;;;;;N;;;;; +1D08;LATIN SMALL LETTER TURNED OPEN E;Ll;0;L;;;;;N;;;;; +1D09;LATIN SMALL LETTER TURNED I;Ll;0;L;;;;;N;;;;; +1D0A;LATIN LETTER SMALL CAPITAL J;Ll;0;L;;;;;N;;;;; +1D0B;LATIN LETTER SMALL CAPITAL K;Ll;0;L;;;;;N;;;;; +1D0C;LATIN LETTER SMALL CAPITAL L WITH STROKE;Ll;0;L;;;;;N;;;;; +1D0D;LATIN LETTER SMALL CAPITAL M;Ll;0;L;;;;;N;;;;; +1D0E;LATIN LETTER SMALL CAPITAL REVERSED N;Ll;0;L;;;;;N;;;;; +1D0F;LATIN LETTER SMALL CAPITAL O;Ll;0;L;;;;;N;;;;; +1D10;LATIN LETTER SMALL CAPITAL OPEN O;Ll;0;L;;;;;N;;;;; +1D11;LATIN SMALL LETTER SIDEWAYS O;Ll;0;L;;;;;N;;;;; +1D12;LATIN SMALL LETTER SIDEWAYS OPEN O;Ll;0;L;;;;;N;;;;; +1D13;LATIN SMALL LETTER SIDEWAYS O WITH STROKE;Ll;0;L;;;;;N;;;;; +1D14;LATIN SMALL LETTER TURNED OE;Ll;0;L;;;;;N;;;;; +1D15;LATIN LETTER SMALL CAPITAL OU;Ll;0;L;;;;;N;;;;; +1D16;LATIN SMALL LETTER TOP HALF O;Ll;0;L;;;;;N;;;;; +1D17;LATIN SMALL LETTER BOTTOM HALF O;Ll;0;L;;;;;N;;;;; +1D18;LATIN LETTER SMALL CAPITAL P;Ll;0;L;;;;;N;;;;; +1D19;LATIN LETTER SMALL CAPITAL REVERSED R;Ll;0;L;;;;;N;;;;; +1D1A;LATIN LETTER SMALL CAPITAL TURNED R;Ll;0;L;;;;;N;;;;; +1D1B;LATIN LETTER SMALL CAPITAL T;Ll;0;L;;;;;N;;;;; +1D1C;LATIN LETTER SMALL CAPITAL U;Ll;0;L;;;;;N;;;;; +1D1D;LATIN SMALL LETTER SIDEWAYS U;Ll;0;L;;;;;N;;;;; +1D1E;LATIN SMALL LETTER SIDEWAYS DIAERESIZED U;Ll;0;L;;;;;N;;;;; +1D1F;LATIN SMALL LETTER SIDEWAYS TURNED M;Ll;0;L;;;;;N;;;;; +1D20;LATIN LETTER SMALL CAPITAL V;Ll;0;L;;;;;N;;;;; +1D21;LATIN LETTER SMALL CAPITAL W;Ll;0;L;;;;;N;;;;; +1D22;LATIN LETTER SMALL CAPITAL Z;Ll;0;L;;;;;N;;;;; +1D23;LATIN LETTER SMALL CAPITAL EZH;Ll;0;L;;;;;N;;;;; +1D24;LATIN LETTER VOICED LARYNGEAL SPIRANT;Ll;0;L;;;;;N;;;;; +1D25;LATIN LETTER AIN;Ll;0;L;;;;;N;;;;; +1D26;GREEK LETTER SMALL CAPITAL GAMMA;Ll;0;L;;;;;N;;;;; +1D27;GREEK LETTER SMALL CAPITAL LAMDA;Ll;0;L;;;;;N;;;;; +1D28;GREEK LETTER SMALL CAPITAL PI;Ll;0;L;;;;;N;;;;; +1D29;GREEK LETTER SMALL CAPITAL RHO;Ll;0;L;;;;;N;;;;; +1D2A;GREEK LETTER SMALL CAPITAL PSI;Ll;0;L;;;;;N;;;;; +1D2B;CYRILLIC LETTER SMALL CAPITAL EL;Ll;0;L;;;;;N;;;;; +1D2C;MODIFIER LETTER CAPITAL A;Lm;0;L; 0041;;;;N;;;;; +1D2D;MODIFIER LETTER CAPITAL AE;Lm;0;L; 00C6;;;;N;;;;; +1D2E;MODIFIER LETTER CAPITAL B;Lm;0;L; 0042;;;;N;;;;; +1D2F;MODIFIER LETTER CAPITAL BARRED B;Lm;0;L;;;;;N;;;;; +1D30;MODIFIER LETTER CAPITAL D;Lm;0;L; 0044;;;;N;;;;; +1D31;MODIFIER LETTER CAPITAL E;Lm;0;L; 0045;;;;N;;;;; +1D32;MODIFIER LETTER CAPITAL REVERSED E;Lm;0;L; 018E;;;;N;;;;; +1D33;MODIFIER LETTER CAPITAL G;Lm;0;L; 0047;;;;N;;;;; +1D34;MODIFIER LETTER CAPITAL H;Lm;0;L; 0048;;;;N;;;;; +1D35;MODIFIER LETTER CAPITAL I;Lm;0;L; 0049;;;;N;;;;; +1D36;MODIFIER LETTER CAPITAL J;Lm;0;L; 004A;;;;N;;;;; +1D37;MODIFIER LETTER CAPITAL K;Lm;0;L; 004B;;;;N;;;;; +1D38;MODIFIER LETTER CAPITAL L;Lm;0;L; 004C;;;;N;;;;; +1D39;MODIFIER LETTER CAPITAL M;Lm;0;L; 004D;;;;N;;;;; +1D3A;MODIFIER LETTER CAPITAL N;Lm;0;L; 004E;;;;N;;;;; +1D3B;MODIFIER LETTER CAPITAL REVERSED N;Lm;0;L;;;;;N;;;;; +1D3C;MODIFIER LETTER CAPITAL O;Lm;0;L; 004F;;;;N;;;;; +1D3D;MODIFIER LETTER CAPITAL OU;Lm;0;L; 0222;;;;N;;;;; +1D3E;MODIFIER LETTER CAPITAL P;Lm;0;L; 0050;;;;N;;;;; +1D3F;MODIFIER LETTER CAPITAL R;Lm;0;L; 0052;;;;N;;;;; +1D40;MODIFIER LETTER CAPITAL T;Lm;0;L; 0054;;;;N;;;;; +1D41;MODIFIER LETTER CAPITAL U;Lm;0;L; 0055;;;;N;;;;; +1D42;MODIFIER LETTER CAPITAL W;Lm;0;L; 0057;;;;N;;;;; +1D43;MODIFIER LETTER SMALL A;Lm;0;L; 0061;;;;N;;;;; +1D44;MODIFIER LETTER SMALL TURNED A;Lm;0;L; 0250;;;;N;;;;; +1D45;MODIFIER LETTER SMALL ALPHA;Lm;0;L; 0251;;;;N;;;;; +1D46;MODIFIER LETTER SMALL TURNED AE;Lm;0;L; 1D02;;;;N;;;;; +1D47;MODIFIER LETTER SMALL B;Lm;0;L; 0062;;;;N;;;;; +1D48;MODIFIER LETTER SMALL D;Lm;0;L; 0064;;;;N;;;;; +1D49;MODIFIER LETTER SMALL E;Lm;0;L; 0065;;;;N;;;;; +1D4A;MODIFIER LETTER SMALL SCHWA;Lm;0;L; 0259;;;;N;;;;; +1D4B;MODIFIER LETTER SMALL OPEN E;Lm;0;L; 025B;;;;N;;;;; +1D4C;MODIFIER LETTER SMALL TURNED OPEN E;Lm;0;L; 025C;;;;N;;;;; +1D4D;MODIFIER LETTER SMALL G;Lm;0;L; 0067;;;;N;;;;; +1D4E;MODIFIER LETTER SMALL TURNED I;Lm;0;L;;;;;N;;;;; +1D4F;MODIFIER LETTER SMALL K;Lm;0;L; 006B;;;;N;;;;; +1D50;MODIFIER LETTER SMALL M;Lm;0;L; 006D;;;;N;;;;; +1D51;MODIFIER LETTER SMALL ENG;Lm;0;L; 014B;;;;N;;;;; +1D52;MODIFIER LETTER SMALL O;Lm;0;L; 006F;;;;N;;;;; +1D53;MODIFIER LETTER SMALL OPEN O;Lm;0;L; 0254;;;;N;;;;; +1D54;MODIFIER LETTER SMALL TOP HALF O;Lm;0;L; 1D16;;;;N;;;;; +1D55;MODIFIER LETTER SMALL BOTTOM HALF O;Lm;0;L; 1D17;;;;N;;;;; +1D56;MODIFIER LETTER SMALL P;Lm;0;L; 0070;;;;N;;;;; +1D57;MODIFIER LETTER SMALL T;Lm;0;L; 0074;;;;N;;;;; +1D58;MODIFIER LETTER SMALL U;Lm;0;L; 0075;;;;N;;;;; +1D59;MODIFIER LETTER SMALL SIDEWAYS U;Lm;0;L; 1D1D;;;;N;;;;; +1D5A;MODIFIER LETTER SMALL TURNED M;Lm;0;L; 026F;;;;N;;;;; +1D5B;MODIFIER LETTER SMALL V;Lm;0;L; 0076;;;;N;;;;; +1D5C;MODIFIER LETTER SMALL AIN;Lm;0;L; 1D25;;;;N;;;;; +1D5D;MODIFIER LETTER SMALL BETA;Lm;0;L; 03B2;;;;N;;;;; +1D5E;MODIFIER LETTER SMALL GREEK GAMMA;Lm;0;L; 03B3;;;;N;;;;; +1D5F;MODIFIER LETTER SMALL DELTA;Lm;0;L; 03B4;;;;N;;;;; +1D60;MODIFIER LETTER SMALL GREEK PHI;Lm;0;L; 03C6;;;;N;;;;; +1D61;MODIFIER LETTER SMALL CHI;Lm;0;L; 03C7;;;;N;;;;; +1D62;LATIN SUBSCRIPT SMALL LETTER I;Lm;0;L; 0069;;;;N;;;;; +1D63;LATIN SUBSCRIPT SMALL LETTER R;Lm;0;L; 0072;;;;N;;;;; +1D64;LATIN SUBSCRIPT SMALL LETTER U;Lm;0;L; 0075;;;;N;;;;; +1D65;LATIN SUBSCRIPT SMALL LETTER V;Lm;0;L; 0076;;;;N;;;;; +1D66;GREEK SUBSCRIPT SMALL LETTER BETA;Lm;0;L; 03B2;;;;N;;;;; +1D67;GREEK SUBSCRIPT SMALL LETTER GAMMA;Lm;0;L; 03B3;;;;N;;;;; +1D68;GREEK SUBSCRIPT SMALL LETTER RHO;Lm;0;L; 03C1;;;;N;;;;; +1D69;GREEK SUBSCRIPT SMALL LETTER PHI;Lm;0;L; 03C6;;;;N;;;;; +1D6A;GREEK SUBSCRIPT SMALL LETTER CHI;Lm;0;L; 03C7;;;;N;;;;; +1D6B;LATIN SMALL LETTER UE;Ll;0;L;;;;;N;;;;; +1D6C;LATIN SMALL LETTER B WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6D;LATIN SMALL LETTER D WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6E;LATIN SMALL LETTER F WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D6F;LATIN SMALL LETTER M WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D70;LATIN SMALL LETTER N WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D71;LATIN SMALL LETTER P WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D72;LATIN SMALL LETTER R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D73;LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D74;LATIN SMALL LETTER S WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D75;LATIN SMALL LETTER T WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D76;LATIN SMALL LETTER Z WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +1D77;LATIN SMALL LETTER TURNED G;Ll;0;L;;;;;N;;;;; +1D78;MODIFIER LETTER CYRILLIC EN;Lm;0;L; 043D;;;;N;;;;; +1D79;LATIN SMALL LETTER INSULAR G;Ll;0;L;;;;;N;;;A77D;;A77D +1D7A;LATIN SMALL LETTER TH WITH STRIKETHROUGH;Ll;0;L;;;;;N;;;;; +1D7B;LATIN SMALL CAPITAL LETTER I WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7C;LATIN SMALL LETTER IOTA WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7D;LATIN SMALL LETTER P WITH STROKE;Ll;0;L;;;;;N;;;2C63;;2C63 +1D7E;LATIN SMALL CAPITAL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;;; +1D7F;LATIN SMALL LETTER UPSILON WITH STROKE;Ll;0;L;;;;;N;;;;; +1D80;LATIN SMALL LETTER B WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D81;LATIN SMALL LETTER D WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D82;LATIN SMALL LETTER F WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D83;LATIN SMALL LETTER G WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D84;LATIN SMALL LETTER K WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D85;LATIN SMALL LETTER L WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D86;LATIN SMALL LETTER M WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D87;LATIN SMALL LETTER N WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D88;LATIN SMALL LETTER P WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D89;LATIN SMALL LETTER R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8A;LATIN SMALL LETTER S WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8B;LATIN SMALL LETTER ESH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8C;LATIN SMALL LETTER V WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8D;LATIN SMALL LETTER X WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1D8E;LATIN SMALL LETTER Z WITH PALATAL HOOK;Ll;0;L;;;;;N;;;A7C6;;A7C6 +1D8F;LATIN SMALL LETTER A WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D90;LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D91;LATIN SMALL LETTER D WITH HOOK AND TAIL;Ll;0;L;;;;;N;;;;; +1D92;LATIN SMALL LETTER E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D93;LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D94;LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D95;LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D96;LATIN SMALL LETTER I WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D97;LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D98;LATIN SMALL LETTER ESH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D99;LATIN SMALL LETTER U WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D9A;LATIN SMALL LETTER EZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1D9B;MODIFIER LETTER SMALL TURNED ALPHA;Lm;0;L; 0252;;;;N;;;;; +1D9C;MODIFIER LETTER SMALL C;Lm;0;L; 0063;;;;N;;;;; +1D9D;MODIFIER LETTER SMALL C WITH CURL;Lm;0;L; 0255;;;;N;;;;; +1D9E;MODIFIER LETTER SMALL ETH;Lm;0;L; 00F0;;;;N;;;;; +1D9F;MODIFIER LETTER SMALL REVERSED OPEN E;Lm;0;L; 025C;;;;N;;;;; +1DA0;MODIFIER LETTER SMALL F;Lm;0;L; 0066;;;;N;;;;; +1DA1;MODIFIER LETTER SMALL DOTLESS J WITH STROKE;Lm;0;L; 025F;;;;N;;;;; +1DA2;MODIFIER LETTER SMALL SCRIPT G;Lm;0;L; 0261;;;;N;;;;; +1DA3;MODIFIER LETTER SMALL TURNED H;Lm;0;L; 0265;;;;N;;;;; +1DA4;MODIFIER LETTER SMALL I WITH STROKE;Lm;0;L; 0268;;;;N;;;;; +1DA5;MODIFIER LETTER SMALL IOTA;Lm;0;L; 0269;;;;N;;;;; +1DA6;MODIFIER LETTER SMALL CAPITAL I;Lm;0;L; 026A;;;;N;;;;; +1DA7;MODIFIER LETTER SMALL CAPITAL I WITH STROKE;Lm;0;L; 1D7B;;;;N;;;;; +1DA8;MODIFIER LETTER SMALL J WITH CROSSED-TAIL;Lm;0;L; 029D;;;;N;;;;; +1DA9;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK;Lm;0;L; 026D;;;;N;;;;; +1DAA;MODIFIER LETTER SMALL L WITH PALATAL HOOK;Lm;0;L; 1D85;;;;N;;;;; +1DAB;MODIFIER LETTER SMALL CAPITAL L;Lm;0;L; 029F;;;;N;;;;; +1DAC;MODIFIER LETTER SMALL M WITH HOOK;Lm;0;L; 0271;;;;N;;;;; +1DAD;MODIFIER LETTER SMALL TURNED M WITH LONG LEG;Lm;0;L; 0270;;;;N;;;;; +1DAE;MODIFIER LETTER SMALL N WITH LEFT HOOK;Lm;0;L; 0272;;;;N;;;;; +1DAF;MODIFIER LETTER SMALL N WITH RETROFLEX HOOK;Lm;0;L; 0273;;;;N;;;;; +1DB0;MODIFIER LETTER SMALL CAPITAL N;Lm;0;L; 0274;;;;N;;;;; +1DB1;MODIFIER LETTER SMALL BARRED O;Lm;0;L; 0275;;;;N;;;;; +1DB2;MODIFIER LETTER SMALL PHI;Lm;0;L; 0278;;;;N;;;;; +1DB3;MODIFIER LETTER SMALL S WITH HOOK;Lm;0;L; 0282;;;;N;;;;; +1DB4;MODIFIER LETTER SMALL ESH;Lm;0;L; 0283;;;;N;;;;; +1DB5;MODIFIER LETTER SMALL T WITH PALATAL HOOK;Lm;0;L; 01AB;;;;N;;;;; +1DB6;MODIFIER LETTER SMALL U BAR;Lm;0;L; 0289;;;;N;;;;; +1DB7;MODIFIER LETTER SMALL UPSILON;Lm;0;L; 028A;;;;N;;;;; +1DB8;MODIFIER LETTER SMALL CAPITAL U;Lm;0;L; 1D1C;;;;N;;;;; +1DB9;MODIFIER LETTER SMALL V WITH HOOK;Lm;0;L; 028B;;;;N;;;;; +1DBA;MODIFIER LETTER SMALL TURNED V;Lm;0;L; 028C;;;;N;;;;; +1DBB;MODIFIER LETTER SMALL Z;Lm;0;L; 007A;;;;N;;;;; +1DBC;MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK;Lm;0;L; 0290;;;;N;;;;; +1DBD;MODIFIER LETTER SMALL Z WITH CURL;Lm;0;L; 0291;;;;N;;;;; +1DBE;MODIFIER LETTER SMALL EZH;Lm;0;L; 0292;;;;N;;;;; +1DBF;MODIFIER LETTER SMALL THETA;Lm;0;L; 03B8;;;;N;;;;; +1DC0;COMBINING DOTTED GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; +1DC1;COMBINING DOTTED ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; +1DC2;COMBINING SNAKE BELOW;Mn;220;NSM;;;;;N;;;;; +1DC3;COMBINING SUSPENSION MARK;Mn;230;NSM;;;;;N;;;;; +1DC4;COMBINING MACRON-ACUTE;Mn;230;NSM;;;;;N;;;;; +1DC5;COMBINING GRAVE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DC6;COMBINING MACRON-GRAVE;Mn;230;NSM;;;;;N;;;;; +1DC7;COMBINING ACUTE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DC8;COMBINING GRAVE-ACUTE-GRAVE;Mn;230;NSM;;;;;N;;;;; +1DC9;COMBINING ACUTE-GRAVE-ACUTE;Mn;230;NSM;;;;;N;;;;; +1DCA;COMBINING LATIN SMALL LETTER R BELOW;Mn;220;NSM;;;;;N;;;;; +1DCB;COMBINING BREVE-MACRON;Mn;230;NSM;;;;;N;;;;; +1DCC;COMBINING MACRON-BREVE;Mn;230;NSM;;;;;N;;;;; +1DCD;COMBINING DOUBLE CIRCUMFLEX ABOVE;Mn;234;NSM;;;;;N;;;;; +1DCE;COMBINING OGONEK ABOVE;Mn;214;NSM;;;;;N;;;;; +1DCF;COMBINING ZIGZAG BELOW;Mn;220;NSM;;;;;N;;;;; +1DD0;COMBINING IS BELOW;Mn;202;NSM;;;;;N;;;;; +1DD1;COMBINING UR ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD2;COMBINING US ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD3;COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE;Mn;230;NSM;;;;;N;;;;; +1DD4;COMBINING LATIN SMALL LETTER AE;Mn;230;NSM;;;;;N;;;;; +1DD5;COMBINING LATIN SMALL LETTER AO;Mn;230;NSM;;;;;N;;;;; +1DD6;COMBINING LATIN SMALL LETTER AV;Mn;230;NSM;;;;;N;;;;; +1DD7;COMBINING LATIN SMALL LETTER C CEDILLA;Mn;230;NSM;;;;;N;;;;; +1DD8;COMBINING LATIN SMALL LETTER INSULAR D;Mn;230;NSM;;;;;N;;;;; +1DD9;COMBINING LATIN SMALL LETTER ETH;Mn;230;NSM;;;;;N;;;;; +1DDA;COMBINING LATIN SMALL LETTER G;Mn;230;NSM;;;;;N;;;;; +1DDB;COMBINING LATIN LETTER SMALL CAPITAL G;Mn;230;NSM;;;;;N;;;;; +1DDC;COMBINING LATIN SMALL LETTER K;Mn;230;NSM;;;;;N;;;;; +1DDD;COMBINING LATIN SMALL LETTER L;Mn;230;NSM;;;;;N;;;;; +1DDE;COMBINING LATIN LETTER SMALL CAPITAL L;Mn;230;NSM;;;;;N;;;;; +1DDF;COMBINING LATIN LETTER SMALL CAPITAL M;Mn;230;NSM;;;;;N;;;;; +1DE0;COMBINING LATIN SMALL LETTER N;Mn;230;NSM;;;;;N;;;;; +1DE1;COMBINING LATIN LETTER SMALL CAPITAL N;Mn;230;NSM;;;;;N;;;;; +1DE2;COMBINING LATIN LETTER SMALL CAPITAL R;Mn;230;NSM;;;;;N;;;;; +1DE3;COMBINING LATIN SMALL LETTER R ROTUNDA;Mn;230;NSM;;;;;N;;;;; +1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; +1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; +1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; +1DE7;COMBINING LATIN SMALL LETTER ALPHA;Mn;230;NSM;;;;;N;;;;; +1DE8;COMBINING LATIN SMALL LETTER B;Mn;230;NSM;;;;;N;;;;; +1DE9;COMBINING LATIN SMALL LETTER BETA;Mn;230;NSM;;;;;N;;;;; +1DEA;COMBINING LATIN SMALL LETTER SCHWA;Mn;230;NSM;;;;;N;;;;; +1DEB;COMBINING LATIN SMALL LETTER F;Mn;230;NSM;;;;;N;;;;; +1DEC;COMBINING LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Mn;230;NSM;;;;;N;;;;; +1DED;COMBINING LATIN SMALL LETTER O WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; +1DEE;COMBINING LATIN SMALL LETTER P;Mn;230;NSM;;;;;N;;;;; +1DEF;COMBINING LATIN SMALL LETTER ESH;Mn;230;NSM;;;;;N;;;;; +1DF0;COMBINING LATIN SMALL LETTER U WITH LIGHT CENTRALIZATION STROKE;Mn;230;NSM;;;;;N;;;;; +1DF1;COMBINING LATIN SMALL LETTER W;Mn;230;NSM;;;;;N;;;;; +1DF2;COMBINING LATIN SMALL LETTER A WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;; +1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;; +1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;; +1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;; +1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;; +1DFA;COMBINING DOT BELOW LEFT;Mn;218;NSM;;;;;N;;;;; +1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;; +1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; +1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; +1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; +1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; +1E00;LATIN CAPITAL LETTER A WITH RING BELOW;Lu;0;L;0041 0325;;;;N;;;;1E01; +1E01;LATIN SMALL LETTER A WITH RING BELOW;Ll;0;L;0061 0325;;;;N;;;1E00;;1E00 +1E02;LATIN CAPITAL LETTER B WITH DOT ABOVE;Lu;0;L;0042 0307;;;;N;;;;1E03; +1E03;LATIN SMALL LETTER B WITH DOT ABOVE;Ll;0;L;0062 0307;;;;N;;;1E02;;1E02 +1E04;LATIN CAPITAL LETTER B WITH DOT BELOW;Lu;0;L;0042 0323;;;;N;;;;1E05; +1E05;LATIN SMALL LETTER B WITH DOT BELOW;Ll;0;L;0062 0323;;;;N;;;1E04;;1E04 +1E06;LATIN CAPITAL LETTER B WITH LINE BELOW;Lu;0;L;0042 0331;;;;N;;;;1E07; +1E07;LATIN SMALL LETTER B WITH LINE BELOW;Ll;0;L;0062 0331;;;;N;;;1E06;;1E06 +1E08;LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE;Lu;0;L;00C7 0301;;;;N;;;;1E09; +1E09;LATIN SMALL LETTER C WITH CEDILLA AND ACUTE;Ll;0;L;00E7 0301;;;;N;;;1E08;;1E08 +1E0A;LATIN CAPITAL LETTER D WITH DOT ABOVE;Lu;0;L;0044 0307;;;;N;;;;1E0B; +1E0B;LATIN SMALL LETTER D WITH DOT ABOVE;Ll;0;L;0064 0307;;;;N;;;1E0A;;1E0A +1E0C;LATIN CAPITAL LETTER D WITH DOT BELOW;Lu;0;L;0044 0323;;;;N;;;;1E0D; +1E0D;LATIN SMALL LETTER D WITH DOT BELOW;Ll;0;L;0064 0323;;;;N;;;1E0C;;1E0C +1E0E;LATIN CAPITAL LETTER D WITH LINE BELOW;Lu;0;L;0044 0331;;;;N;;;;1E0F; +1E0F;LATIN SMALL LETTER D WITH LINE BELOW;Ll;0;L;0064 0331;;;;N;;;1E0E;;1E0E +1E10;LATIN CAPITAL LETTER D WITH CEDILLA;Lu;0;L;0044 0327;;;;N;;;;1E11; +1E11;LATIN SMALL LETTER D WITH CEDILLA;Ll;0;L;0064 0327;;;;N;;;1E10;;1E10 +1E12;LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW;Lu;0;L;0044 032D;;;;N;;;;1E13; +1E13;LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW;Ll;0;L;0064 032D;;;;N;;;1E12;;1E12 +1E14;LATIN CAPITAL LETTER E WITH MACRON AND GRAVE;Lu;0;L;0112 0300;;;;N;;;;1E15; +1E15;LATIN SMALL LETTER E WITH MACRON AND GRAVE;Ll;0;L;0113 0300;;;;N;;;1E14;;1E14 +1E16;LATIN CAPITAL LETTER E WITH MACRON AND ACUTE;Lu;0;L;0112 0301;;;;N;;;;1E17; +1E17;LATIN SMALL LETTER E WITH MACRON AND ACUTE;Ll;0;L;0113 0301;;;;N;;;1E16;;1E16 +1E18;LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW;Lu;0;L;0045 032D;;;;N;;;;1E19; +1E19;LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW;Ll;0;L;0065 032D;;;;N;;;1E18;;1E18 +1E1A;LATIN CAPITAL LETTER E WITH TILDE BELOW;Lu;0;L;0045 0330;;;;N;;;;1E1B; +1E1B;LATIN SMALL LETTER E WITH TILDE BELOW;Ll;0;L;0065 0330;;;;N;;;1E1A;;1E1A +1E1C;LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE;Lu;0;L;0228 0306;;;;N;;;;1E1D; +1E1D;LATIN SMALL LETTER E WITH CEDILLA AND BREVE;Ll;0;L;0229 0306;;;;N;;;1E1C;;1E1C +1E1E;LATIN CAPITAL LETTER F WITH DOT ABOVE;Lu;0;L;0046 0307;;;;N;;;;1E1F; +1E1F;LATIN SMALL LETTER F WITH DOT ABOVE;Ll;0;L;0066 0307;;;;N;;;1E1E;;1E1E +1E20;LATIN CAPITAL LETTER G WITH MACRON;Lu;0;L;0047 0304;;;;N;;;;1E21; +1E21;LATIN SMALL LETTER G WITH MACRON;Ll;0;L;0067 0304;;;;N;;;1E20;;1E20 +1E22;LATIN CAPITAL LETTER H WITH DOT ABOVE;Lu;0;L;0048 0307;;;;N;;;;1E23; +1E23;LATIN SMALL LETTER H WITH DOT ABOVE;Ll;0;L;0068 0307;;;;N;;;1E22;;1E22 +1E24;LATIN CAPITAL LETTER H WITH DOT BELOW;Lu;0;L;0048 0323;;;;N;;;;1E25; +1E25;LATIN SMALL LETTER H WITH DOT BELOW;Ll;0;L;0068 0323;;;;N;;;1E24;;1E24 +1E26;LATIN CAPITAL LETTER H WITH DIAERESIS;Lu;0;L;0048 0308;;;;N;;;;1E27; +1E27;LATIN SMALL LETTER H WITH DIAERESIS;Ll;0;L;0068 0308;;;;N;;;1E26;;1E26 +1E28;LATIN CAPITAL LETTER H WITH CEDILLA;Lu;0;L;0048 0327;;;;N;;;;1E29; +1E29;LATIN SMALL LETTER H WITH CEDILLA;Ll;0;L;0068 0327;;;;N;;;1E28;;1E28 +1E2A;LATIN CAPITAL LETTER H WITH BREVE BELOW;Lu;0;L;0048 032E;;;;N;;;;1E2B; +1E2B;LATIN SMALL LETTER H WITH BREVE BELOW;Ll;0;L;0068 032E;;;;N;;;1E2A;;1E2A +1E2C;LATIN CAPITAL LETTER I WITH TILDE BELOW;Lu;0;L;0049 0330;;;;N;;;;1E2D; +1E2D;LATIN SMALL LETTER I WITH TILDE BELOW;Ll;0;L;0069 0330;;;;N;;;1E2C;;1E2C +1E2E;LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE;Lu;0;L;00CF 0301;;;;N;;;;1E2F; +1E2F;LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE;Ll;0;L;00EF 0301;;;;N;;;1E2E;;1E2E +1E30;LATIN CAPITAL LETTER K WITH ACUTE;Lu;0;L;004B 0301;;;;N;;;;1E31; +1E31;LATIN SMALL LETTER K WITH ACUTE;Ll;0;L;006B 0301;;;;N;;;1E30;;1E30 +1E32;LATIN CAPITAL LETTER K WITH DOT BELOW;Lu;0;L;004B 0323;;;;N;;;;1E33; +1E33;LATIN SMALL LETTER K WITH DOT BELOW;Ll;0;L;006B 0323;;;;N;;;1E32;;1E32 +1E34;LATIN CAPITAL LETTER K WITH LINE BELOW;Lu;0;L;004B 0331;;;;N;;;;1E35; +1E35;LATIN SMALL LETTER K WITH LINE BELOW;Ll;0;L;006B 0331;;;;N;;;1E34;;1E34 +1E36;LATIN CAPITAL LETTER L WITH DOT BELOW;Lu;0;L;004C 0323;;;;N;;;;1E37; +1E37;LATIN SMALL LETTER L WITH DOT BELOW;Ll;0;L;006C 0323;;;;N;;;1E36;;1E36 +1E38;LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON;Lu;0;L;1E36 0304;;;;N;;;;1E39; +1E39;LATIN SMALL LETTER L WITH DOT BELOW AND MACRON;Ll;0;L;1E37 0304;;;;N;;;1E38;;1E38 +1E3A;LATIN CAPITAL LETTER L WITH LINE BELOW;Lu;0;L;004C 0331;;;;N;;;;1E3B; +1E3B;LATIN SMALL LETTER L WITH LINE BELOW;Ll;0;L;006C 0331;;;;N;;;1E3A;;1E3A +1E3C;LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW;Lu;0;L;004C 032D;;;;N;;;;1E3D; +1E3D;LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW;Ll;0;L;006C 032D;;;;N;;;1E3C;;1E3C +1E3E;LATIN CAPITAL LETTER M WITH ACUTE;Lu;0;L;004D 0301;;;;N;;;;1E3F; +1E3F;LATIN SMALL LETTER M WITH ACUTE;Ll;0;L;006D 0301;;;;N;;;1E3E;;1E3E +1E40;LATIN CAPITAL LETTER M WITH DOT ABOVE;Lu;0;L;004D 0307;;;;N;;;;1E41; +1E41;LATIN SMALL LETTER M WITH DOT ABOVE;Ll;0;L;006D 0307;;;;N;;;1E40;;1E40 +1E42;LATIN CAPITAL LETTER M WITH DOT BELOW;Lu;0;L;004D 0323;;;;N;;;;1E43; +1E43;LATIN SMALL LETTER M WITH DOT BELOW;Ll;0;L;006D 0323;;;;N;;;1E42;;1E42 +1E44;LATIN CAPITAL LETTER N WITH DOT ABOVE;Lu;0;L;004E 0307;;;;N;;;;1E45; +1E45;LATIN SMALL LETTER N WITH DOT ABOVE;Ll;0;L;006E 0307;;;;N;;;1E44;;1E44 +1E46;LATIN CAPITAL LETTER N WITH DOT BELOW;Lu;0;L;004E 0323;;;;N;;;;1E47; +1E47;LATIN SMALL LETTER N WITH DOT BELOW;Ll;0;L;006E 0323;;;;N;;;1E46;;1E46 +1E48;LATIN CAPITAL LETTER N WITH LINE BELOW;Lu;0;L;004E 0331;;;;N;;;;1E49; +1E49;LATIN SMALL LETTER N WITH LINE BELOW;Ll;0;L;006E 0331;;;;N;;;1E48;;1E48 +1E4A;LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW;Lu;0;L;004E 032D;;;;N;;;;1E4B; +1E4B;LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW;Ll;0;L;006E 032D;;;;N;;;1E4A;;1E4A +1E4C;LATIN CAPITAL LETTER O WITH TILDE AND ACUTE;Lu;0;L;00D5 0301;;;;N;;;;1E4D; +1E4D;LATIN SMALL LETTER O WITH TILDE AND ACUTE;Ll;0;L;00F5 0301;;;;N;;;1E4C;;1E4C +1E4E;LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS;Lu;0;L;00D5 0308;;;;N;;;;1E4F; +1E4F;LATIN SMALL LETTER O WITH TILDE AND DIAERESIS;Ll;0;L;00F5 0308;;;;N;;;1E4E;;1E4E +1E50;LATIN CAPITAL LETTER O WITH MACRON AND GRAVE;Lu;0;L;014C 0300;;;;N;;;;1E51; +1E51;LATIN SMALL LETTER O WITH MACRON AND GRAVE;Ll;0;L;014D 0300;;;;N;;;1E50;;1E50 +1E52;LATIN CAPITAL LETTER O WITH MACRON AND ACUTE;Lu;0;L;014C 0301;;;;N;;;;1E53; +1E53;LATIN SMALL LETTER O WITH MACRON AND ACUTE;Ll;0;L;014D 0301;;;;N;;;1E52;;1E52 +1E54;LATIN CAPITAL LETTER P WITH ACUTE;Lu;0;L;0050 0301;;;;N;;;;1E55; +1E55;LATIN SMALL LETTER P WITH ACUTE;Ll;0;L;0070 0301;;;;N;;;1E54;;1E54 +1E56;LATIN CAPITAL LETTER P WITH DOT ABOVE;Lu;0;L;0050 0307;;;;N;;;;1E57; +1E57;LATIN SMALL LETTER P WITH DOT ABOVE;Ll;0;L;0070 0307;;;;N;;;1E56;;1E56 +1E58;LATIN CAPITAL LETTER R WITH DOT ABOVE;Lu;0;L;0052 0307;;;;N;;;;1E59; +1E59;LATIN SMALL LETTER R WITH DOT ABOVE;Ll;0;L;0072 0307;;;;N;;;1E58;;1E58 +1E5A;LATIN CAPITAL LETTER R WITH DOT BELOW;Lu;0;L;0052 0323;;;;N;;;;1E5B; +1E5B;LATIN SMALL LETTER R WITH DOT BELOW;Ll;0;L;0072 0323;;;;N;;;1E5A;;1E5A +1E5C;LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON;Lu;0;L;1E5A 0304;;;;N;;;;1E5D; +1E5D;LATIN SMALL LETTER R WITH DOT BELOW AND MACRON;Ll;0;L;1E5B 0304;;;;N;;;1E5C;;1E5C +1E5E;LATIN CAPITAL LETTER R WITH LINE BELOW;Lu;0;L;0052 0331;;;;N;;;;1E5F; +1E5F;LATIN SMALL LETTER R WITH LINE BELOW;Ll;0;L;0072 0331;;;;N;;;1E5E;;1E5E +1E60;LATIN CAPITAL LETTER S WITH DOT ABOVE;Lu;0;L;0053 0307;;;;N;;;;1E61; +1E61;LATIN SMALL LETTER S WITH DOT ABOVE;Ll;0;L;0073 0307;;;;N;;;1E60;;1E60 +1E62;LATIN CAPITAL LETTER S WITH DOT BELOW;Lu;0;L;0053 0323;;;;N;;;;1E63; +1E63;LATIN SMALL LETTER S WITH DOT BELOW;Ll;0;L;0073 0323;;;;N;;;1E62;;1E62 +1E64;LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE;Lu;0;L;015A 0307;;;;N;;;;1E65; +1E65;LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE;Ll;0;L;015B 0307;;;;N;;;1E64;;1E64 +1E66;LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE;Lu;0;L;0160 0307;;;;N;;;;1E67; +1E67;LATIN SMALL LETTER S WITH CARON AND DOT ABOVE;Ll;0;L;0161 0307;;;;N;;;1E66;;1E66 +1E68;LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE;Lu;0;L;1E62 0307;;;;N;;;;1E69; +1E69;LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE;Ll;0;L;1E63 0307;;;;N;;;1E68;;1E68 +1E6A;LATIN CAPITAL LETTER T WITH DOT ABOVE;Lu;0;L;0054 0307;;;;N;;;;1E6B; +1E6B;LATIN SMALL LETTER T WITH DOT ABOVE;Ll;0;L;0074 0307;;;;N;;;1E6A;;1E6A +1E6C;LATIN CAPITAL LETTER T WITH DOT BELOW;Lu;0;L;0054 0323;;;;N;;;;1E6D; +1E6D;LATIN SMALL LETTER T WITH DOT BELOW;Ll;0;L;0074 0323;;;;N;;;1E6C;;1E6C +1E6E;LATIN CAPITAL LETTER T WITH LINE BELOW;Lu;0;L;0054 0331;;;;N;;;;1E6F; +1E6F;LATIN SMALL LETTER T WITH LINE BELOW;Ll;0;L;0074 0331;;;;N;;;1E6E;;1E6E +1E70;LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW;Lu;0;L;0054 032D;;;;N;;;;1E71; +1E71;LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW;Ll;0;L;0074 032D;;;;N;;;1E70;;1E70 +1E72;LATIN CAPITAL LETTER U WITH DIAERESIS BELOW;Lu;0;L;0055 0324;;;;N;;;;1E73; +1E73;LATIN SMALL LETTER U WITH DIAERESIS BELOW;Ll;0;L;0075 0324;;;;N;;;1E72;;1E72 +1E74;LATIN CAPITAL LETTER U WITH TILDE BELOW;Lu;0;L;0055 0330;;;;N;;;;1E75; +1E75;LATIN SMALL LETTER U WITH TILDE BELOW;Ll;0;L;0075 0330;;;;N;;;1E74;;1E74 +1E76;LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW;Lu;0;L;0055 032D;;;;N;;;;1E77; +1E77;LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW;Ll;0;L;0075 032D;;;;N;;;1E76;;1E76 +1E78;LATIN CAPITAL LETTER U WITH TILDE AND ACUTE;Lu;0;L;0168 0301;;;;N;;;;1E79; +1E79;LATIN SMALL LETTER U WITH TILDE AND ACUTE;Ll;0;L;0169 0301;;;;N;;;1E78;;1E78 +1E7A;LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS;Lu;0;L;016A 0308;;;;N;;;;1E7B; +1E7B;LATIN SMALL LETTER U WITH MACRON AND DIAERESIS;Ll;0;L;016B 0308;;;;N;;;1E7A;;1E7A +1E7C;LATIN CAPITAL LETTER V WITH TILDE;Lu;0;L;0056 0303;;;;N;;;;1E7D; +1E7D;LATIN SMALL LETTER V WITH TILDE;Ll;0;L;0076 0303;;;;N;;;1E7C;;1E7C +1E7E;LATIN CAPITAL LETTER V WITH DOT BELOW;Lu;0;L;0056 0323;;;;N;;;;1E7F; +1E7F;LATIN SMALL LETTER V WITH DOT BELOW;Ll;0;L;0076 0323;;;;N;;;1E7E;;1E7E +1E80;LATIN CAPITAL LETTER W WITH GRAVE;Lu;0;L;0057 0300;;;;N;;;;1E81; +1E81;LATIN SMALL LETTER W WITH GRAVE;Ll;0;L;0077 0300;;;;N;;;1E80;;1E80 +1E82;LATIN CAPITAL LETTER W WITH ACUTE;Lu;0;L;0057 0301;;;;N;;;;1E83; +1E83;LATIN SMALL LETTER W WITH ACUTE;Ll;0;L;0077 0301;;;;N;;;1E82;;1E82 +1E84;LATIN CAPITAL LETTER W WITH DIAERESIS;Lu;0;L;0057 0308;;;;N;;;;1E85; +1E85;LATIN SMALL LETTER W WITH DIAERESIS;Ll;0;L;0077 0308;;;;N;;;1E84;;1E84 +1E86;LATIN CAPITAL LETTER W WITH DOT ABOVE;Lu;0;L;0057 0307;;;;N;;;;1E87; +1E87;LATIN SMALL LETTER W WITH DOT ABOVE;Ll;0;L;0077 0307;;;;N;;;1E86;;1E86 +1E88;LATIN CAPITAL LETTER W WITH DOT BELOW;Lu;0;L;0057 0323;;;;N;;;;1E89; +1E89;LATIN SMALL LETTER W WITH DOT BELOW;Ll;0;L;0077 0323;;;;N;;;1E88;;1E88 +1E8A;LATIN CAPITAL LETTER X WITH DOT ABOVE;Lu;0;L;0058 0307;;;;N;;;;1E8B; +1E8B;LATIN SMALL LETTER X WITH DOT ABOVE;Ll;0;L;0078 0307;;;;N;;;1E8A;;1E8A +1E8C;LATIN CAPITAL LETTER X WITH DIAERESIS;Lu;0;L;0058 0308;;;;N;;;;1E8D; +1E8D;LATIN SMALL LETTER X WITH DIAERESIS;Ll;0;L;0078 0308;;;;N;;;1E8C;;1E8C +1E8E;LATIN CAPITAL LETTER Y WITH DOT ABOVE;Lu;0;L;0059 0307;;;;N;;;;1E8F; +1E8F;LATIN SMALL LETTER Y WITH DOT ABOVE;Ll;0;L;0079 0307;;;;N;;;1E8E;;1E8E +1E90;LATIN CAPITAL LETTER Z WITH CIRCUMFLEX;Lu;0;L;005A 0302;;;;N;;;;1E91; +1E91;LATIN SMALL LETTER Z WITH CIRCUMFLEX;Ll;0;L;007A 0302;;;;N;;;1E90;;1E90 +1E92;LATIN CAPITAL LETTER Z WITH DOT BELOW;Lu;0;L;005A 0323;;;;N;;;;1E93; +1E93;LATIN SMALL LETTER Z WITH DOT BELOW;Ll;0;L;007A 0323;;;;N;;;1E92;;1E92 +1E94;LATIN CAPITAL LETTER Z WITH LINE BELOW;Lu;0;L;005A 0331;;;;N;;;;1E95; +1E95;LATIN SMALL LETTER Z WITH LINE BELOW;Ll;0;L;007A 0331;;;;N;;;1E94;;1E94 +1E96;LATIN SMALL LETTER H WITH LINE BELOW;Ll;0;L;0068 0331;;;;N;;;;; +1E97;LATIN SMALL LETTER T WITH DIAERESIS;Ll;0;L;0074 0308;;;;N;;;;; +1E98;LATIN SMALL LETTER W WITH RING ABOVE;Ll;0;L;0077 030A;;;;N;;;;; +1E99;LATIN SMALL LETTER Y WITH RING ABOVE;Ll;0;L;0079 030A;;;;N;;;;; +1E9A;LATIN SMALL LETTER A WITH RIGHT HALF RING;Ll;0;L; 0061 02BE;;;;N;;;;; +1E9B;LATIN SMALL LETTER LONG S WITH DOT ABOVE;Ll;0;L;017F 0307;;;;N;;;1E60;;1E60 +1E9C;LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;;; +1E9D;LATIN SMALL LETTER LONG S WITH HIGH STROKE;Ll;0;L;;;;;N;;;;; +1E9E;LATIN CAPITAL LETTER SHARP S;Lu;0;L;;;;;N;;;;00DF; +1E9F;LATIN SMALL LETTER DELTA;Ll;0;L;;;;;N;;;;; +1EA0;LATIN CAPITAL LETTER A WITH DOT BELOW;Lu;0;L;0041 0323;;;;N;;;;1EA1; +1EA1;LATIN SMALL LETTER A WITH DOT BELOW;Ll;0;L;0061 0323;;;;N;;;1EA0;;1EA0 +1EA2;LATIN CAPITAL LETTER A WITH HOOK ABOVE;Lu;0;L;0041 0309;;;;N;;;;1EA3; +1EA3;LATIN SMALL LETTER A WITH HOOK ABOVE;Ll;0;L;0061 0309;;;;N;;;1EA2;;1EA2 +1EA4;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00C2 0301;;;;N;;;;1EA5; +1EA5;LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00E2 0301;;;;N;;;1EA4;;1EA4 +1EA6;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00C2 0300;;;;N;;;;1EA7; +1EA7;LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00E2 0300;;;;N;;;1EA6;;1EA6 +1EA8;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00C2 0309;;;;N;;;;1EA9; +1EA9;LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00E2 0309;;;;N;;;1EA8;;1EA8 +1EAA;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE;Lu;0;L;00C2 0303;;;;N;;;;1EAB; +1EAB;LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE;Ll;0;L;00E2 0303;;;;N;;;1EAA;;1EAA +1EAC;LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EA0 0302;;;;N;;;;1EAD; +1EAD;LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EA1 0302;;;;N;;;1EAC;;1EAC +1EAE;LATIN CAPITAL LETTER A WITH BREVE AND ACUTE;Lu;0;L;0102 0301;;;;N;;;;1EAF; +1EAF;LATIN SMALL LETTER A WITH BREVE AND ACUTE;Ll;0;L;0103 0301;;;;N;;;1EAE;;1EAE +1EB0;LATIN CAPITAL LETTER A WITH BREVE AND GRAVE;Lu;0;L;0102 0300;;;;N;;;;1EB1; +1EB1;LATIN SMALL LETTER A WITH BREVE AND GRAVE;Ll;0;L;0103 0300;;;;N;;;1EB0;;1EB0 +1EB2;LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE;Lu;0;L;0102 0309;;;;N;;;;1EB3; +1EB3;LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE;Ll;0;L;0103 0309;;;;N;;;1EB2;;1EB2 +1EB4;LATIN CAPITAL LETTER A WITH BREVE AND TILDE;Lu;0;L;0102 0303;;;;N;;;;1EB5; +1EB5;LATIN SMALL LETTER A WITH BREVE AND TILDE;Ll;0;L;0103 0303;;;;N;;;1EB4;;1EB4 +1EB6;LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW;Lu;0;L;1EA0 0306;;;;N;;;;1EB7; +1EB7;LATIN SMALL LETTER A WITH BREVE AND DOT BELOW;Ll;0;L;1EA1 0306;;;;N;;;1EB6;;1EB6 +1EB8;LATIN CAPITAL LETTER E WITH DOT BELOW;Lu;0;L;0045 0323;;;;N;;;;1EB9; +1EB9;LATIN SMALL LETTER E WITH DOT BELOW;Ll;0;L;0065 0323;;;;N;;;1EB8;;1EB8 +1EBA;LATIN CAPITAL LETTER E WITH HOOK ABOVE;Lu;0;L;0045 0309;;;;N;;;;1EBB; +1EBB;LATIN SMALL LETTER E WITH HOOK ABOVE;Ll;0;L;0065 0309;;;;N;;;1EBA;;1EBA +1EBC;LATIN CAPITAL LETTER E WITH TILDE;Lu;0;L;0045 0303;;;;N;;;;1EBD; +1EBD;LATIN SMALL LETTER E WITH TILDE;Ll;0;L;0065 0303;;;;N;;;1EBC;;1EBC +1EBE;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00CA 0301;;;;N;;;;1EBF; +1EBF;LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00EA 0301;;;;N;;;1EBE;;1EBE +1EC0;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00CA 0300;;;;N;;;;1EC1; +1EC1;LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00EA 0300;;;;N;;;1EC0;;1EC0 +1EC2;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00CA 0309;;;;N;;;;1EC3; +1EC3;LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00EA 0309;;;;N;;;1EC2;;1EC2 +1EC4;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE;Lu;0;L;00CA 0303;;;;N;;;;1EC5; +1EC5;LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE;Ll;0;L;00EA 0303;;;;N;;;1EC4;;1EC4 +1EC6;LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1EB8 0302;;;;N;;;;1EC7; +1EC7;LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1EB9 0302;;;;N;;;1EC6;;1EC6 +1EC8;LATIN CAPITAL LETTER I WITH HOOK ABOVE;Lu;0;L;0049 0309;;;;N;;;;1EC9; +1EC9;LATIN SMALL LETTER I WITH HOOK ABOVE;Ll;0;L;0069 0309;;;;N;;;1EC8;;1EC8 +1ECA;LATIN CAPITAL LETTER I WITH DOT BELOW;Lu;0;L;0049 0323;;;;N;;;;1ECB; +1ECB;LATIN SMALL LETTER I WITH DOT BELOW;Ll;0;L;0069 0323;;;;N;;;1ECA;;1ECA +1ECC;LATIN CAPITAL LETTER O WITH DOT BELOW;Lu;0;L;004F 0323;;;;N;;;;1ECD; +1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC +1ECE;LATIN CAPITAL LETTER O WITH HOOK ABOVE;Lu;0;L;004F 0309;;;;N;;;;1ECF; +1ECF;LATIN SMALL LETTER O WITH HOOK ABOVE;Ll;0;L;006F 0309;;;;N;;;1ECE;;1ECE +1ED0;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE;Lu;0;L;00D4 0301;;;;N;;;;1ED1; +1ED1;LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE;Ll;0;L;00F4 0301;;;;N;;;1ED0;;1ED0 +1ED2;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE;Lu;0;L;00D4 0300;;;;N;;;;1ED3; +1ED3;LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE;Ll;0;L;00F4 0300;;;;N;;;1ED2;;1ED2 +1ED4;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Lu;0;L;00D4 0309;;;;N;;;;1ED5; +1ED5;LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE;Ll;0;L;00F4 0309;;;;N;;;1ED4;;1ED4 +1ED6;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE;Lu;0;L;00D4 0303;;;;N;;;;1ED7; +1ED7;LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE;Ll;0;L;00F4 0303;;;;N;;;1ED6;;1ED6 +1ED8;LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Lu;0;L;1ECC 0302;;;;N;;;;1ED9; +1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8 +1EDA;LATIN CAPITAL LETTER O WITH HORN AND ACUTE;Lu;0;L;01A0 0301;;;;N;;;;1EDB; +1EDB;LATIN SMALL LETTER O WITH HORN AND ACUTE;Ll;0;L;01A1 0301;;;;N;;;1EDA;;1EDA +1EDC;LATIN CAPITAL LETTER O WITH HORN AND GRAVE;Lu;0;L;01A0 0300;;;;N;;;;1EDD; +1EDD;LATIN SMALL LETTER O WITH HORN AND GRAVE;Ll;0;L;01A1 0300;;;;N;;;1EDC;;1EDC +1EDE;LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE;Lu;0;L;01A0 0309;;;;N;;;;1EDF; +1EDF;LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE;Ll;0;L;01A1 0309;;;;N;;;1EDE;;1EDE +1EE0;LATIN CAPITAL LETTER O WITH HORN AND TILDE;Lu;0;L;01A0 0303;;;;N;;;;1EE1; +1EE1;LATIN SMALL LETTER O WITH HORN AND TILDE;Ll;0;L;01A1 0303;;;;N;;;1EE0;;1EE0 +1EE2;LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW;Lu;0;L;01A0 0323;;;;N;;;;1EE3; +1EE3;LATIN SMALL LETTER O WITH HORN AND DOT BELOW;Ll;0;L;01A1 0323;;;;N;;;1EE2;;1EE2 +1EE4;LATIN CAPITAL LETTER U WITH DOT BELOW;Lu;0;L;0055 0323;;;;N;;;;1EE5; +1EE5;LATIN SMALL LETTER U WITH DOT BELOW;Ll;0;L;0075 0323;;;;N;;;1EE4;;1EE4 +1EE6;LATIN CAPITAL LETTER U WITH HOOK ABOVE;Lu;0;L;0055 0309;;;;N;;;;1EE7; +1EE7;LATIN SMALL LETTER U WITH HOOK ABOVE;Ll;0;L;0075 0309;;;;N;;;1EE6;;1EE6 +1EE8;LATIN CAPITAL LETTER U WITH HORN AND ACUTE;Lu;0;L;01AF 0301;;;;N;;;;1EE9; +1EE9;LATIN SMALL LETTER U WITH HORN AND ACUTE;Ll;0;L;01B0 0301;;;;N;;;1EE8;;1EE8 +1EEA;LATIN CAPITAL LETTER U WITH HORN AND GRAVE;Lu;0;L;01AF 0300;;;;N;;;;1EEB; +1EEB;LATIN SMALL LETTER U WITH HORN AND GRAVE;Ll;0;L;01B0 0300;;;;N;;;1EEA;;1EEA +1EEC;LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE;Lu;0;L;01AF 0309;;;;N;;;;1EED; +1EED;LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE;Ll;0;L;01B0 0309;;;;N;;;1EEC;;1EEC +1EEE;LATIN CAPITAL LETTER U WITH HORN AND TILDE;Lu;0;L;01AF 0303;;;;N;;;;1EEF; +1EEF;LATIN SMALL LETTER U WITH HORN AND TILDE;Ll;0;L;01B0 0303;;;;N;;;1EEE;;1EEE +1EF0;LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW;Lu;0;L;01AF 0323;;;;N;;;;1EF1; +1EF1;LATIN SMALL LETTER U WITH HORN AND DOT BELOW;Ll;0;L;01B0 0323;;;;N;;;1EF0;;1EF0 +1EF2;LATIN CAPITAL LETTER Y WITH GRAVE;Lu;0;L;0059 0300;;;;N;;;;1EF3; +1EF3;LATIN SMALL LETTER Y WITH GRAVE;Ll;0;L;0079 0300;;;;N;;;1EF2;;1EF2 +1EF4;LATIN CAPITAL LETTER Y WITH DOT BELOW;Lu;0;L;0059 0323;;;;N;;;;1EF5; +1EF5;LATIN SMALL LETTER Y WITH DOT BELOW;Ll;0;L;0079 0323;;;;N;;;1EF4;;1EF4 +1EF6;LATIN CAPITAL LETTER Y WITH HOOK ABOVE;Lu;0;L;0059 0309;;;;N;;;;1EF7; +1EF7;LATIN SMALL LETTER Y WITH HOOK ABOVE;Ll;0;L;0079 0309;;;;N;;;1EF6;;1EF6 +1EF8;LATIN CAPITAL LETTER Y WITH TILDE;Lu;0;L;0059 0303;;;;N;;;;1EF9; +1EF9;LATIN SMALL LETTER Y WITH TILDE;Ll;0;L;0079 0303;;;;N;;;1EF8;;1EF8 +1EFA;LATIN CAPITAL LETTER MIDDLE-WELSH LL;Lu;0;L;;;;;N;;;;1EFB; +1EFB;LATIN SMALL LETTER MIDDLE-WELSH LL;Ll;0;L;;;;;N;;;1EFA;;1EFA +1EFC;LATIN CAPITAL LETTER MIDDLE-WELSH V;Lu;0;L;;;;;N;;;;1EFD; +1EFD;LATIN SMALL LETTER MIDDLE-WELSH V;Ll;0;L;;;;;N;;;1EFC;;1EFC +1EFE;LATIN CAPITAL LETTER Y WITH LOOP;Lu;0;L;;;;;N;;;;1EFF; +1EFF;LATIN SMALL LETTER Y WITH LOOP;Ll;0;L;;;;;N;;;1EFE;;1EFE +1F00;GREEK SMALL LETTER ALPHA WITH PSILI;Ll;0;L;03B1 0313;;;;N;;;1F08;;1F08 +1F01;GREEK SMALL LETTER ALPHA WITH DASIA;Ll;0;L;03B1 0314;;;;N;;;1F09;;1F09 +1F02;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA;Ll;0;L;1F00 0300;;;;N;;;1F0A;;1F0A +1F03;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA;Ll;0;L;1F01 0300;;;;N;;;1F0B;;1F0B +1F04;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA;Ll;0;L;1F00 0301;;;;N;;;1F0C;;1F0C +1F05;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA;Ll;0;L;1F01 0301;;;;N;;;1F0D;;1F0D +1F06;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI;Ll;0;L;1F00 0342;;;;N;;;1F0E;;1F0E +1F07;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI;Ll;0;L;1F01 0342;;;;N;;;1F0F;;1F0F +1F08;GREEK CAPITAL LETTER ALPHA WITH PSILI;Lu;0;L;0391 0313;;;;N;;;;1F00; +1F09;GREEK CAPITAL LETTER ALPHA WITH DASIA;Lu;0;L;0391 0314;;;;N;;;;1F01; +1F0A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA;Lu;0;L;1F08 0300;;;;N;;;;1F02; +1F0B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA;Lu;0;L;1F09 0300;;;;N;;;;1F03; +1F0C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA;Lu;0;L;1F08 0301;;;;N;;;;1F04; +1F0D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA;Lu;0;L;1F09 0301;;;;N;;;;1F05; +1F0E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI;Lu;0;L;1F08 0342;;;;N;;;;1F06; +1F0F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI;Lu;0;L;1F09 0342;;;;N;;;;1F07; +1F10;GREEK SMALL LETTER EPSILON WITH PSILI;Ll;0;L;03B5 0313;;;;N;;;1F18;;1F18 +1F11;GREEK SMALL LETTER EPSILON WITH DASIA;Ll;0;L;03B5 0314;;;;N;;;1F19;;1F19 +1F12;GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA;Ll;0;L;1F10 0300;;;;N;;;1F1A;;1F1A +1F13;GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA;Ll;0;L;1F11 0300;;;;N;;;1F1B;;1F1B +1F14;GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA;Ll;0;L;1F10 0301;;;;N;;;1F1C;;1F1C +1F15;GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA;Ll;0;L;1F11 0301;;;;N;;;1F1D;;1F1D +1F18;GREEK CAPITAL LETTER EPSILON WITH PSILI;Lu;0;L;0395 0313;;;;N;;;;1F10; +1F19;GREEK CAPITAL LETTER EPSILON WITH DASIA;Lu;0;L;0395 0314;;;;N;;;;1F11; +1F1A;GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA;Lu;0;L;1F18 0300;;;;N;;;;1F12; +1F1B;GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA;Lu;0;L;1F19 0300;;;;N;;;;1F13; +1F1C;GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA;Lu;0;L;1F18 0301;;;;N;;;;1F14; +1F1D;GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA;Lu;0;L;1F19 0301;;;;N;;;;1F15; +1F20;GREEK SMALL LETTER ETA WITH PSILI;Ll;0;L;03B7 0313;;;;N;;;1F28;;1F28 +1F21;GREEK SMALL LETTER ETA WITH DASIA;Ll;0;L;03B7 0314;;;;N;;;1F29;;1F29 +1F22;GREEK SMALL LETTER ETA WITH PSILI AND VARIA;Ll;0;L;1F20 0300;;;;N;;;1F2A;;1F2A +1F23;GREEK SMALL LETTER ETA WITH DASIA AND VARIA;Ll;0;L;1F21 0300;;;;N;;;1F2B;;1F2B +1F24;GREEK SMALL LETTER ETA WITH PSILI AND OXIA;Ll;0;L;1F20 0301;;;;N;;;1F2C;;1F2C +1F25;GREEK SMALL LETTER ETA WITH DASIA AND OXIA;Ll;0;L;1F21 0301;;;;N;;;1F2D;;1F2D +1F26;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI;Ll;0;L;1F20 0342;;;;N;;;1F2E;;1F2E +1F27;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI;Ll;0;L;1F21 0342;;;;N;;;1F2F;;1F2F +1F28;GREEK CAPITAL LETTER ETA WITH PSILI;Lu;0;L;0397 0313;;;;N;;;;1F20; +1F29;GREEK CAPITAL LETTER ETA WITH DASIA;Lu;0;L;0397 0314;;;;N;;;;1F21; +1F2A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA;Lu;0;L;1F28 0300;;;;N;;;;1F22; +1F2B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA;Lu;0;L;1F29 0300;;;;N;;;;1F23; +1F2C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA;Lu;0;L;1F28 0301;;;;N;;;;1F24; +1F2D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA;Lu;0;L;1F29 0301;;;;N;;;;1F25; +1F2E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI;Lu;0;L;1F28 0342;;;;N;;;;1F26; +1F2F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI;Lu;0;L;1F29 0342;;;;N;;;;1F27; +1F30;GREEK SMALL LETTER IOTA WITH PSILI;Ll;0;L;03B9 0313;;;;N;;;1F38;;1F38 +1F31;GREEK SMALL LETTER IOTA WITH DASIA;Ll;0;L;03B9 0314;;;;N;;;1F39;;1F39 +1F32;GREEK SMALL LETTER IOTA WITH PSILI AND VARIA;Ll;0;L;1F30 0300;;;;N;;;1F3A;;1F3A +1F33;GREEK SMALL LETTER IOTA WITH DASIA AND VARIA;Ll;0;L;1F31 0300;;;;N;;;1F3B;;1F3B +1F34;GREEK SMALL LETTER IOTA WITH PSILI AND OXIA;Ll;0;L;1F30 0301;;;;N;;;1F3C;;1F3C +1F35;GREEK SMALL LETTER IOTA WITH DASIA AND OXIA;Ll;0;L;1F31 0301;;;;N;;;1F3D;;1F3D +1F36;GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI;Ll;0;L;1F30 0342;;;;N;;;1F3E;;1F3E +1F37;GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI;Ll;0;L;1F31 0342;;;;N;;;1F3F;;1F3F +1F38;GREEK CAPITAL LETTER IOTA WITH PSILI;Lu;0;L;0399 0313;;;;N;;;;1F30; +1F39;GREEK CAPITAL LETTER IOTA WITH DASIA;Lu;0;L;0399 0314;;;;N;;;;1F31; +1F3A;GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA;Lu;0;L;1F38 0300;;;;N;;;;1F32; +1F3B;GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA;Lu;0;L;1F39 0300;;;;N;;;;1F33; +1F3C;GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA;Lu;0;L;1F38 0301;;;;N;;;;1F34; +1F3D;GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA;Lu;0;L;1F39 0301;;;;N;;;;1F35; +1F3E;GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI;Lu;0;L;1F38 0342;;;;N;;;;1F36; +1F3F;GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI;Lu;0;L;1F39 0342;;;;N;;;;1F37; +1F40;GREEK SMALL LETTER OMICRON WITH PSILI;Ll;0;L;03BF 0313;;;;N;;;1F48;;1F48 +1F41;GREEK SMALL LETTER OMICRON WITH DASIA;Ll;0;L;03BF 0314;;;;N;;;1F49;;1F49 +1F42;GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA;Ll;0;L;1F40 0300;;;;N;;;1F4A;;1F4A +1F43;GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA;Ll;0;L;1F41 0300;;;;N;;;1F4B;;1F4B +1F44;GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA;Ll;0;L;1F40 0301;;;;N;;;1F4C;;1F4C +1F45;GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA;Ll;0;L;1F41 0301;;;;N;;;1F4D;;1F4D +1F48;GREEK CAPITAL LETTER OMICRON WITH PSILI;Lu;0;L;039F 0313;;;;N;;;;1F40; +1F49;GREEK CAPITAL LETTER OMICRON WITH DASIA;Lu;0;L;039F 0314;;;;N;;;;1F41; +1F4A;GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA;Lu;0;L;1F48 0300;;;;N;;;;1F42; +1F4B;GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA;Lu;0;L;1F49 0300;;;;N;;;;1F43; +1F4C;GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA;Lu;0;L;1F48 0301;;;;N;;;;1F44; +1F4D;GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA;Lu;0;L;1F49 0301;;;;N;;;;1F45; +1F50;GREEK SMALL LETTER UPSILON WITH PSILI;Ll;0;L;03C5 0313;;;;N;;;;; +1F51;GREEK SMALL LETTER UPSILON WITH DASIA;Ll;0;L;03C5 0314;;;;N;;;1F59;;1F59 +1F52;GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA;Ll;0;L;1F50 0300;;;;N;;;;; +1F53;GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA;Ll;0;L;1F51 0300;;;;N;;;1F5B;;1F5B +1F54;GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA;Ll;0;L;1F50 0301;;;;N;;;;; +1F55;GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA;Ll;0;L;1F51 0301;;;;N;;;1F5D;;1F5D +1F56;GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI;Ll;0;L;1F50 0342;;;;N;;;;; +1F57;GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI;Ll;0;L;1F51 0342;;;;N;;;1F5F;;1F5F +1F59;GREEK CAPITAL LETTER UPSILON WITH DASIA;Lu;0;L;03A5 0314;;;;N;;;;1F51; +1F5B;GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA;Lu;0;L;1F59 0300;;;;N;;;;1F53; +1F5D;GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA;Lu;0;L;1F59 0301;;;;N;;;;1F55; +1F5F;GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI;Lu;0;L;1F59 0342;;;;N;;;;1F57; +1F60;GREEK SMALL LETTER OMEGA WITH PSILI;Ll;0;L;03C9 0313;;;;N;;;1F68;;1F68 +1F61;GREEK SMALL LETTER OMEGA WITH DASIA;Ll;0;L;03C9 0314;;;;N;;;1F69;;1F69 +1F62;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA;Ll;0;L;1F60 0300;;;;N;;;1F6A;;1F6A +1F63;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA;Ll;0;L;1F61 0300;;;;N;;;1F6B;;1F6B +1F64;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA;Ll;0;L;1F60 0301;;;;N;;;1F6C;;1F6C +1F65;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA;Ll;0;L;1F61 0301;;;;N;;;1F6D;;1F6D +1F66;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI;Ll;0;L;1F60 0342;;;;N;;;1F6E;;1F6E +1F67;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI;Ll;0;L;1F61 0342;;;;N;;;1F6F;;1F6F +1F68;GREEK CAPITAL LETTER OMEGA WITH PSILI;Lu;0;L;03A9 0313;;;;N;;;;1F60; +1F69;GREEK CAPITAL LETTER OMEGA WITH DASIA;Lu;0;L;03A9 0314;;;;N;;;;1F61; +1F6A;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA;Lu;0;L;1F68 0300;;;;N;;;;1F62; +1F6B;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA;Lu;0;L;1F69 0300;;;;N;;;;1F63; +1F6C;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA;Lu;0;L;1F68 0301;;;;N;;;;1F64; +1F6D;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA;Lu;0;L;1F69 0301;;;;N;;;;1F65; +1F6E;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI;Lu;0;L;1F68 0342;;;;N;;;;1F66; +1F6F;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI;Lu;0;L;1F69 0342;;;;N;;;;1F67; +1F70;GREEK SMALL LETTER ALPHA WITH VARIA;Ll;0;L;03B1 0300;;;;N;;;1FBA;;1FBA +1F71;GREEK SMALL LETTER ALPHA WITH OXIA;Ll;0;L;03AC;;;;N;;;1FBB;;1FBB +1F72;GREEK SMALL LETTER EPSILON WITH VARIA;Ll;0;L;03B5 0300;;;;N;;;1FC8;;1FC8 +1F73;GREEK SMALL LETTER EPSILON WITH OXIA;Ll;0;L;03AD;;;;N;;;1FC9;;1FC9 +1F74;GREEK SMALL LETTER ETA WITH VARIA;Ll;0;L;03B7 0300;;;;N;;;1FCA;;1FCA +1F75;GREEK SMALL LETTER ETA WITH OXIA;Ll;0;L;03AE;;;;N;;;1FCB;;1FCB +1F76;GREEK SMALL LETTER IOTA WITH VARIA;Ll;0;L;03B9 0300;;;;N;;;1FDA;;1FDA +1F77;GREEK SMALL LETTER IOTA WITH OXIA;Ll;0;L;03AF;;;;N;;;1FDB;;1FDB +1F78;GREEK SMALL LETTER OMICRON WITH VARIA;Ll;0;L;03BF 0300;;;;N;;;1FF8;;1FF8 +1F79;GREEK SMALL LETTER OMICRON WITH OXIA;Ll;0;L;03CC;;;;N;;;1FF9;;1FF9 +1F7A;GREEK SMALL LETTER UPSILON WITH VARIA;Ll;0;L;03C5 0300;;;;N;;;1FEA;;1FEA +1F7B;GREEK SMALL LETTER UPSILON WITH OXIA;Ll;0;L;03CD;;;;N;;;1FEB;;1FEB +1F7C;GREEK SMALL LETTER OMEGA WITH VARIA;Ll;0;L;03C9 0300;;;;N;;;1FFA;;1FFA +1F7D;GREEK SMALL LETTER OMEGA WITH OXIA;Ll;0;L;03CE;;;;N;;;1FFB;;1FFB +1F80;GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F00 0345;;;;N;;;1F88;;1F88 +1F81;GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F01 0345;;;;N;;;1F89;;1F89 +1F82;GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F02 0345;;;;N;;;1F8A;;1F8A +1F83;GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F03 0345;;;;N;;;1F8B;;1F8B +1F84;GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F04 0345;;;;N;;;1F8C;;1F8C +1F85;GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F05 0345;;;;N;;;1F8D;;1F8D +1F86;GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F06 0345;;;;N;;;1F8E;;1F8E +1F87;GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F07 0345;;;;N;;;1F8F;;1F8F +1F88;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F08 0345;;;;N;;;;1F80; +1F89;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F09 0345;;;;N;;;;1F81; +1F8A;GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0A 0345;;;;N;;;;1F82; +1F8B;GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F0B 0345;;;;N;;;;1F83; +1F8C;GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0C 0345;;;;N;;;;1F84; +1F8D;GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F0D 0345;;;;N;;;;1F85; +1F8E;GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0E 0345;;;;N;;;;1F86; +1F8F;GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F0F 0345;;;;N;;;;1F87; +1F90;GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F20 0345;;;;N;;;1F98;;1F98 +1F91;GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F21 0345;;;;N;;;1F99;;1F99 +1F92;GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F22 0345;;;;N;;;1F9A;;1F9A +1F93;GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F23 0345;;;;N;;;1F9B;;1F9B +1F94;GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F24 0345;;;;N;;;1F9C;;1F9C +1F95;GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F25 0345;;;;N;;;1F9D;;1F9D +1F96;GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F26 0345;;;;N;;;1F9E;;1F9E +1F97;GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F27 0345;;;;N;;;1F9F;;1F9F +1F98;GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F28 0345;;;;N;;;;1F90; +1F99;GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F29 0345;;;;N;;;;1F91; +1F9A;GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2A 0345;;;;N;;;;1F92; +1F9B;GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F2B 0345;;;;N;;;;1F93; +1F9C;GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2C 0345;;;;N;;;;1F94; +1F9D;GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F2D 0345;;;;N;;;;1F95; +1F9E;GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2E 0345;;;;N;;;;1F96; +1F9F;GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F2F 0345;;;;N;;;;1F97; +1FA0;GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI;Ll;0;L;1F60 0345;;;;N;;;1FA8;;1FA8 +1FA1;GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI;Ll;0;L;1F61 0345;;;;N;;;1FA9;;1FA9 +1FA2;GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F62 0345;;;;N;;;1FAA;;1FAA +1FA3;GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI;Ll;0;L;1F63 0345;;;;N;;;1FAB;;1FAB +1FA4;GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F64 0345;;;;N;;;1FAC;;1FAC +1FA5;GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI;Ll;0;L;1F65 0345;;;;N;;;1FAD;;1FAD +1FA6;GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F66 0345;;;;N;;;1FAE;;1FAE +1FA7;GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1F67 0345;;;;N;;;1FAF;;1FAF +1FA8;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI;Lt;0;L;1F68 0345;;;;N;;;;1FA0; +1FA9;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI;Lt;0;L;1F69 0345;;;;N;;;;1FA1; +1FAA;GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6A 0345;;;;N;;;;1FA2; +1FAB;GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI;Lt;0;L;1F6B 0345;;;;N;;;;1FA3; +1FAC;GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6C 0345;;;;N;;;;1FA4; +1FAD;GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI;Lt;0;L;1F6D 0345;;;;N;;;;1FA5; +1FAE;GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6E 0345;;;;N;;;;1FA6; +1FAF;GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI;Lt;0;L;1F6F 0345;;;;N;;;;1FA7; +1FB0;GREEK SMALL LETTER ALPHA WITH VRACHY;Ll;0;L;03B1 0306;;;;N;;;1FB8;;1FB8 +1FB1;GREEK SMALL LETTER ALPHA WITH MACRON;Ll;0;L;03B1 0304;;;;N;;;1FB9;;1FB9 +1FB2;GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F70 0345;;;;N;;;;; +1FB3;GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI;Ll;0;L;03B1 0345;;;;N;;;1FBC;;1FBC +1FB4;GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AC 0345;;;;N;;;;; +1FB6;GREEK SMALL LETTER ALPHA WITH PERISPOMENI;Ll;0;L;03B1 0342;;;;N;;;;; +1FB7;GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FB6 0345;;;;N;;;;; +1FB8;GREEK CAPITAL LETTER ALPHA WITH VRACHY;Lu;0;L;0391 0306;;;;N;;;;1FB0; +1FB9;GREEK CAPITAL LETTER ALPHA WITH MACRON;Lu;0;L;0391 0304;;;;N;;;;1FB1; +1FBA;GREEK CAPITAL LETTER ALPHA WITH VARIA;Lu;0;L;0391 0300;;;;N;;;;1F70; +1FBB;GREEK CAPITAL LETTER ALPHA WITH OXIA;Lu;0;L;0386;;;;N;;;;1F71; +1FBC;GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI;Lt;0;L;0391 0345;;;;N;;;;1FB3; +1FBD;GREEK KORONIS;Sk;0;ON; 0020 0313;;;;N;;;;; +1FBE;GREEK PROSGEGRAMMENI;Ll;0;L;03B9;;;;N;;;0399;;0399 +1FBF;GREEK PSILI;Sk;0;ON; 0020 0313;;;;N;;;;; +1FC0;GREEK PERISPOMENI;Sk;0;ON; 0020 0342;;;;N;;;;; +1FC1;GREEK DIALYTIKA AND PERISPOMENI;Sk;0;ON;00A8 0342;;;;N;;;;; +1FC2;GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F74 0345;;;;N;;;;; +1FC3;GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI;Ll;0;L;03B7 0345;;;;N;;;1FCC;;1FCC +1FC4;GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03AE 0345;;;;N;;;;; +1FC6;GREEK SMALL LETTER ETA WITH PERISPOMENI;Ll;0;L;03B7 0342;;;;N;;;;; +1FC7;GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FC6 0345;;;;N;;;;; +1FC8;GREEK CAPITAL LETTER EPSILON WITH VARIA;Lu;0;L;0395 0300;;;;N;;;;1F72; +1FC9;GREEK CAPITAL LETTER EPSILON WITH OXIA;Lu;0;L;0388;;;;N;;;;1F73; +1FCA;GREEK CAPITAL LETTER ETA WITH VARIA;Lu;0;L;0397 0300;;;;N;;;;1F74; +1FCB;GREEK CAPITAL LETTER ETA WITH OXIA;Lu;0;L;0389;;;;N;;;;1F75; +1FCC;GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI;Lt;0;L;0397 0345;;;;N;;;;1FC3; +1FCD;GREEK PSILI AND VARIA;Sk;0;ON;1FBF 0300;;;;N;;;;; +1FCE;GREEK PSILI AND OXIA;Sk;0;ON;1FBF 0301;;;;N;;;;; +1FCF;GREEK PSILI AND PERISPOMENI;Sk;0;ON;1FBF 0342;;;;N;;;;; +1FD0;GREEK SMALL LETTER IOTA WITH VRACHY;Ll;0;L;03B9 0306;;;;N;;;1FD8;;1FD8 +1FD1;GREEK SMALL LETTER IOTA WITH MACRON;Ll;0;L;03B9 0304;;;;N;;;1FD9;;1FD9 +1FD2;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA;Ll;0;L;03CA 0300;;;;N;;;;; +1FD3;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA;Ll;0;L;0390;;;;N;;;;; +1FD6;GREEK SMALL LETTER IOTA WITH PERISPOMENI;Ll;0;L;03B9 0342;;;;N;;;;; +1FD7;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CA 0342;;;;N;;;;; +1FD8;GREEK CAPITAL LETTER IOTA WITH VRACHY;Lu;0;L;0399 0306;;;;N;;;;1FD0; +1FD9;GREEK CAPITAL LETTER IOTA WITH MACRON;Lu;0;L;0399 0304;;;;N;;;;1FD1; +1FDA;GREEK CAPITAL LETTER IOTA WITH VARIA;Lu;0;L;0399 0300;;;;N;;;;1F76; +1FDB;GREEK CAPITAL LETTER IOTA WITH OXIA;Lu;0;L;038A;;;;N;;;;1F77; +1FDD;GREEK DASIA AND VARIA;Sk;0;ON;1FFE 0300;;;;N;;;;; +1FDE;GREEK DASIA AND OXIA;Sk;0;ON;1FFE 0301;;;;N;;;;; +1FDF;GREEK DASIA AND PERISPOMENI;Sk;0;ON;1FFE 0342;;;;N;;;;; +1FE0;GREEK SMALL LETTER UPSILON WITH VRACHY;Ll;0;L;03C5 0306;;;;N;;;1FE8;;1FE8 +1FE1;GREEK SMALL LETTER UPSILON WITH MACRON;Ll;0;L;03C5 0304;;;;N;;;1FE9;;1FE9 +1FE2;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA;Ll;0;L;03CB 0300;;;;N;;;;; +1FE3;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA;Ll;0;L;03B0;;;;N;;;;; +1FE4;GREEK SMALL LETTER RHO WITH PSILI;Ll;0;L;03C1 0313;;;;N;;;;; +1FE5;GREEK SMALL LETTER RHO WITH DASIA;Ll;0;L;03C1 0314;;;;N;;;1FEC;;1FEC +1FE6;GREEK SMALL LETTER UPSILON WITH PERISPOMENI;Ll;0;L;03C5 0342;;;;N;;;;; +1FE7;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI;Ll;0;L;03CB 0342;;;;N;;;;; +1FE8;GREEK CAPITAL LETTER UPSILON WITH VRACHY;Lu;0;L;03A5 0306;;;;N;;;;1FE0; +1FE9;GREEK CAPITAL LETTER UPSILON WITH MACRON;Lu;0;L;03A5 0304;;;;N;;;;1FE1; +1FEA;GREEK CAPITAL LETTER UPSILON WITH VARIA;Lu;0;L;03A5 0300;;;;N;;;;1F7A; +1FEB;GREEK CAPITAL LETTER UPSILON WITH OXIA;Lu;0;L;038E;;;;N;;;;1F7B; +1FEC;GREEK CAPITAL LETTER RHO WITH DASIA;Lu;0;L;03A1 0314;;;;N;;;;1FE5; +1FED;GREEK DIALYTIKA AND VARIA;Sk;0;ON;00A8 0300;;;;N;;;;; +1FEE;GREEK DIALYTIKA AND OXIA;Sk;0;ON;0385;;;;N;;;;; +1FEF;GREEK VARIA;Sk;0;ON;0060;;;;N;;;;; +1FF2;GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI;Ll;0;L;1F7C 0345;;;;N;;;;; +1FF3;GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI;Ll;0;L;03C9 0345;;;;N;;;1FFC;;1FFC +1FF4;GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI;Ll;0;L;03CE 0345;;;;N;;;;; +1FF6;GREEK SMALL LETTER OMEGA WITH PERISPOMENI;Ll;0;L;03C9 0342;;;;N;;;;; +1FF7;GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI;Ll;0;L;1FF6 0345;;;;N;;;;; +1FF8;GREEK CAPITAL LETTER OMICRON WITH VARIA;Lu;0;L;039F 0300;;;;N;;;;1F78; +1FF9;GREEK CAPITAL LETTER OMICRON WITH OXIA;Lu;0;L;038C;;;;N;;;;1F79; +1FFA;GREEK CAPITAL LETTER OMEGA WITH VARIA;Lu;0;L;03A9 0300;;;;N;;;;1F7C; +1FFB;GREEK CAPITAL LETTER OMEGA WITH OXIA;Lu;0;L;038F;;;;N;;;;1F7D; +1FFC;GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI;Lt;0;L;03A9 0345;;;;N;;;;1FF3; +1FFD;GREEK OXIA;Sk;0;ON;00B4;;;;N;;;;; +1FFE;GREEK DASIA;Sk;0;ON; 0020 0314;;;;N;;;;; +2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;; +2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;; +2002;EN SPACE;Zs;0;WS; 0020;;;;N;;;;; +2003;EM SPACE;Zs;0;WS; 0020;;;;N;;;;; +2004;THREE-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; +2005;FOUR-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; +2006;SIX-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; +2007;FIGURE SPACE;Zs;0;WS; 0020;;;;N;;;;; +2008;PUNCTUATION SPACE;Zs;0;WS; 0020;;;;N;;;;; +2009;THIN SPACE;Zs;0;WS; 0020;;;;N;;;;; +200A;HAIR SPACE;Zs;0;WS; 0020;;;;N;;;;; +200B;ZERO WIDTH SPACE;Cf;0;BN;;;;;N;;;;; +200C;ZERO WIDTH NON-JOINER;Cf;0;BN;;;;;N;;;;; +200D;ZERO WIDTH JOINER;Cf;0;BN;;;;;N;;;;; +200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;; +200F;RIGHT-TO-LEFT MARK;Cf;0;R;;;;;N;;;;; +2010;HYPHEN;Pd;0;ON;;;;;N;;;;; +2011;NON-BREAKING HYPHEN;Pd;0;ON; 2010;;;;N;;;;; +2012;FIGURE DASH;Pd;0;ON;;;;;N;;;;; +2013;EN DASH;Pd;0;ON;;;;;N;;;;; +2014;EM DASH;Pd;0;ON;;;;;N;;;;; +2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; +2016;DOUBLE VERTICAL LINE;Po;0;ON;;;;;N;DOUBLE VERTICAL BAR;;;; +2017;DOUBLE LOW LINE;Po;0;ON; 0020 0333;;;;N;SPACING DOUBLE UNDERSCORE;;;; +2018;LEFT SINGLE QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE TURNED COMMA QUOTATION MARK;;;; +2019;RIGHT SINGLE QUOTATION MARK;Pf;0;ON;;;;;N;SINGLE COMMA QUOTATION MARK;;;; +201A;SINGLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW SINGLE COMMA QUOTATION MARK;;;; +201B;SINGLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;SINGLE REVERSED COMMA QUOTATION MARK;;;; +201C;LEFT DOUBLE QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE TURNED COMMA QUOTATION MARK;;;; +201D;RIGHT DOUBLE QUOTATION MARK;Pf;0;ON;;;;;N;DOUBLE COMMA QUOTATION MARK;;;; +201E;DOUBLE LOW-9 QUOTATION MARK;Ps;0;ON;;;;;N;LOW DOUBLE COMMA QUOTATION MARK;;;; +201F;DOUBLE HIGH-REVERSED-9 QUOTATION MARK;Pi;0;ON;;;;;N;DOUBLE REVERSED COMMA QUOTATION MARK;;;; +2020;DAGGER;Po;0;ON;;;;;N;;;;; +2021;DOUBLE DAGGER;Po;0;ON;;;;;N;;;;; +2022;BULLET;Po;0;ON;;;;;N;;;;; +2023;TRIANGULAR BULLET;Po;0;ON;;;;;N;;;;; +2024;ONE DOT LEADER;Po;0;ON; 002E;;;;N;;;;; +2025;TWO DOT LEADER;Po;0;ON; 002E 002E;;;;N;;;;; +2026;HORIZONTAL ELLIPSIS;Po;0;ON; 002E 002E 002E;;;;N;;;;; +2027;HYPHENATION POINT;Po;0;ON;;;;;N;;;;; +2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; +2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; +202A;LEFT-TO-RIGHT EMBEDDING;Cf;0;LRE;;;;;N;;;;; +202B;RIGHT-TO-LEFT EMBEDDING;Cf;0;RLE;;;;;N;;;;; +202C;POP DIRECTIONAL FORMATTING;Cf;0;PDF;;;;;N;;;;; +202D;LEFT-TO-RIGHT OVERRIDE;Cf;0;LRO;;;;;N;;;;; +202E;RIGHT-TO-LEFT OVERRIDE;Cf;0;RLO;;;;;N;;;;; +202F;NARROW NO-BREAK SPACE;Zs;0;CS; 0020;;;;N;;;;; +2030;PER MILLE SIGN;Po;0;ET;;;;;N;;;;; +2031;PER TEN THOUSAND SIGN;Po;0;ET;;;;;N;;;;; +2032;PRIME;Po;0;ET;;;;;N;;;;; +2033;DOUBLE PRIME;Po;0;ET; 2032 2032;;;;N;;;;; +2034;TRIPLE PRIME;Po;0;ET; 2032 2032 2032;;;;N;;;;; +2035;REVERSED PRIME;Po;0;ON;;;;;N;;;;; +2036;REVERSED DOUBLE PRIME;Po;0;ON; 2035 2035;;;;N;;;;; +2037;REVERSED TRIPLE PRIME;Po;0;ON; 2035 2035 2035;;;;N;;;;; +2038;CARET;Po;0;ON;;;;;N;;;;; +2039;SINGLE LEFT-POINTING ANGLE QUOTATION MARK;Pi;0;ON;;;;;Y;LEFT POINTING SINGLE GUILLEMET;;;; +203A;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING SINGLE GUILLEMET;;;; +203B;REFERENCE MARK;Po;0;ON;;;;;N;;;;; +203C;DOUBLE EXCLAMATION MARK;Po;0;ON; 0021 0021;;;;N;;;;; +203D;INTERROBANG;Po;0;ON;;;;;N;;;;; +203E;OVERLINE;Po;0;ON; 0020 0305;;;;N;SPACING OVERSCORE;;;; +203F;UNDERTIE;Pc;0;ON;;;;;N;;;;; +2040;CHARACTER TIE;Pc;0;ON;;;;;N;;;;; +2041;CARET INSERTION POINT;Po;0;ON;;;;;N;;;;; +2042;ASTERISM;Po;0;ON;;;;;N;;;;; +2043;HYPHEN BULLET;Po;0;ON;;;;;N;;;;; +2044;FRACTION SLASH;Sm;0;CS;;;;;N;;;;; +2045;LEFT SQUARE BRACKET WITH QUILL;Ps;0;ON;;;;;Y;;;;; +2046;RIGHT SQUARE BRACKET WITH QUILL;Pe;0;ON;;;;;Y;;;;; +2047;DOUBLE QUESTION MARK;Po;0;ON; 003F 003F;;;;N;;;;; +2048;QUESTION EXCLAMATION MARK;Po;0;ON; 003F 0021;;;;N;;;;; +2049;EXCLAMATION QUESTION MARK;Po;0;ON; 0021 003F;;;;N;;;;; +204A;TIRONIAN SIGN ET;Po;0;ON;;;;;N;;;;; +204B;REVERSED PILCROW SIGN;Po;0;ON;;;;;N;;;;; +204C;BLACK LEFTWARDS BULLET;Po;0;ON;;;;;N;;;;; +204D;BLACK RIGHTWARDS BULLET;Po;0;ON;;;;;N;;;;; +204E;LOW ASTERISK;Po;0;ON;;;;;N;;;;; +204F;REVERSED SEMICOLON;Po;0;ON;;;;;N;;;;; +2050;CLOSE UP;Po;0;ON;;;;;N;;;;; +2051;TWO ASTERISKS ALIGNED VERTICALLY;Po;0;ON;;;;;N;;;;; +2052;COMMERCIAL MINUS SIGN;Sm;0;ON;;;;;N;;;;; +2053;SWUNG DASH;Po;0;ON;;;;;N;;;;; +2054;INVERTED UNDERTIE;Pc;0;ON;;;;;N;;;;; +2055;FLOWER PUNCTUATION MARK;Po;0;ON;;;;;N;;;;; +2056;THREE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2057;QUADRUPLE PRIME;Po;0;ON; 2032 2032 2032 2032;;;;N;;;;; +2058;FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2059;FIVE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +205A;TWO DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +205B;FOUR DOT MARK;Po;0;ON;;;;;N;;;;; +205C;DOTTED CROSS;Po;0;ON;;;;;N;;;;; +205D;TRICOLON;Po;0;ON;;;;;N;;;;; +205E;VERTICAL FOUR DOTS;Po;0;ON;;;;;N;;;;; +205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS; 0020;;;;N;;;;; +2060;WORD JOINER;Cf;0;BN;;;;;N;;;;; +2061;FUNCTION APPLICATION;Cf;0;BN;;;;;N;;;;; +2062;INVISIBLE TIMES;Cf;0;BN;;;;;N;;;;; +2063;INVISIBLE SEPARATOR;Cf;0;BN;;;;;N;;;;; +2064;INVISIBLE PLUS;Cf;0;BN;;;;;N;;;;; +2066;LEFT-TO-RIGHT ISOLATE;Cf;0;LRI;;;;;N;;;;; +2067;RIGHT-TO-LEFT ISOLATE;Cf;0;RLI;;;;;N;;;;; +2068;FIRST STRONG ISOLATE;Cf;0;FSI;;;;;N;;;;; +2069;POP DIRECTIONAL ISOLATE;Cf;0;PDI;;;;;N;;;;; +206A;INHIBIT SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; +206B;ACTIVATE SYMMETRIC SWAPPING;Cf;0;BN;;;;;N;;;;; +206C;INHIBIT ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; +206D;ACTIVATE ARABIC FORM SHAPING;Cf;0;BN;;;;;N;;;;; +206E;NATIONAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; +206F;NOMINAL DIGIT SHAPES;Cf;0;BN;;;;;N;;;;; +2070;SUPERSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUPERSCRIPT DIGIT ZERO;;;; +2071;SUPERSCRIPT LATIN SMALL LETTER I;Lm;0;L; 0069;;;;N;;;;; +2074;SUPERSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUPERSCRIPT DIGIT FOUR;;;; +2075;SUPERSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUPERSCRIPT DIGIT FIVE;;;; +2076;SUPERSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUPERSCRIPT DIGIT SIX;;;; +2077;SUPERSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUPERSCRIPT DIGIT SEVEN;;;; +2078;SUPERSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUPERSCRIPT DIGIT EIGHT;;;; +2079;SUPERSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUPERSCRIPT DIGIT NINE;;;; +207A;SUPERSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; +207B;SUPERSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUPERSCRIPT HYPHEN-MINUS;;;; +207C;SUPERSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; +207D;SUPERSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUPERSCRIPT OPENING PARENTHESIS;;;; +207E;SUPERSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUPERSCRIPT CLOSING PARENTHESIS;;;; +207F;SUPERSCRIPT LATIN SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; +2080;SUBSCRIPT ZERO;No;0;EN; 0030;;0;0;N;SUBSCRIPT DIGIT ZERO;;;; +2081;SUBSCRIPT ONE;No;0;EN; 0031;;1;1;N;SUBSCRIPT DIGIT ONE;;;; +2082;SUBSCRIPT TWO;No;0;EN; 0032;;2;2;N;SUBSCRIPT DIGIT TWO;;;; +2083;SUBSCRIPT THREE;No;0;EN; 0033;;3;3;N;SUBSCRIPT DIGIT THREE;;;; +2084;SUBSCRIPT FOUR;No;0;EN; 0034;;4;4;N;SUBSCRIPT DIGIT FOUR;;;; +2085;SUBSCRIPT FIVE;No;0;EN; 0035;;5;5;N;SUBSCRIPT DIGIT FIVE;;;; +2086;SUBSCRIPT SIX;No;0;EN; 0036;;6;6;N;SUBSCRIPT DIGIT SIX;;;; +2087;SUBSCRIPT SEVEN;No;0;EN; 0037;;7;7;N;SUBSCRIPT DIGIT SEVEN;;;; +2088;SUBSCRIPT EIGHT;No;0;EN; 0038;;8;8;N;SUBSCRIPT DIGIT EIGHT;;;; +2089;SUBSCRIPT NINE;No;0;EN; 0039;;9;9;N;SUBSCRIPT DIGIT NINE;;;; +208A;SUBSCRIPT PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; +208B;SUBSCRIPT MINUS;Sm;0;ES; 2212;;;;N;SUBSCRIPT HYPHEN-MINUS;;;; +208C;SUBSCRIPT EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; +208D;SUBSCRIPT LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SUBSCRIPT OPENING PARENTHESIS;;;; +208E;SUBSCRIPT RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SUBSCRIPT CLOSING PARENTHESIS;;;; +2090;LATIN SUBSCRIPT SMALL LETTER A;Lm;0;L; 0061;;;;N;;;;; +2091;LATIN SUBSCRIPT SMALL LETTER E;Lm;0;L; 0065;;;;N;;;;; +2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L; 006F;;;;N;;;;; +2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L; 0078;;;;N;;;;; +2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L; 0259;;;;N;;;;; +2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L; 0068;;;;N;;;;; +2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L; 006B;;;;N;;;;; +2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L; 006C;;;;N;;;;; +2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L; 006D;;;;N;;;;; +2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; +209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L; 0070;;;;N;;;;; +209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L; 0073;;;;N;;;;; +209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L; 0074;;;;N;;;;; +20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; +20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; +20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; +20A3;FRENCH FRANC SIGN;Sc;0;ET;;;;;N;;;;; +20A4;LIRA SIGN;Sc;0;ET;;;;;N;;;;; +20A5;MILL SIGN;Sc;0;ET;;;;;N;;;;; +20A6;NAIRA SIGN;Sc;0;ET;;;;;N;;;;; +20A7;PESETA SIGN;Sc;0;ET;;;;;N;;;;; +20A8;RUPEE SIGN;Sc;0;ET; 0052 0073;;;;N;;;;; +20A9;WON SIGN;Sc;0;ET;;;;;N;;;;; +20AA;NEW SHEQEL SIGN;Sc;0;ET;;;;;N;;;;; +20AB;DONG SIGN;Sc;0;ET;;;;;N;;;;; +20AC;EURO SIGN;Sc;0;ET;;;;;N;;;;; +20AD;KIP SIGN;Sc;0;ET;;;;;N;;;;; +20AE;TUGRIK SIGN;Sc;0;ET;;;;;N;;;;; +20AF;DRACHMA SIGN;Sc;0;ET;;;;;N;;;;; +20B0;GERMAN PENNY SIGN;Sc;0;ET;;;;;N;;;;; +20B1;PESO SIGN;Sc;0;ET;;;;;N;;;;; +20B2;GUARANI SIGN;Sc;0;ET;;;;;N;;;;; +20B3;AUSTRAL SIGN;Sc;0;ET;;;;;N;;;;; +20B4;HRYVNIA SIGN;Sc;0;ET;;;;;N;;;;; +20B5;CEDI SIGN;Sc;0;ET;;;;;N;;;;; +20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; +20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; +20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; +20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;; +20BA;TURKISH LIRA SIGN;Sc;0;ET;;;;;N;;;;; +20BB;NORDIC MARK SIGN;Sc;0;ET;;;;;N;;;;; +20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;; +20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;; +20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;; +20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;; +20C0;SOM SIGN;Sc;0;ET;;;;;N;;;;; +20C1;SAUDI RIYAL SIGN;Sc;0;ET;;;;;N;;;;; +20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; +20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; +20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; +20D3;COMBINING SHORT VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING SHORT VERTICAL BAR OVERLAY;;;; +20D4;COMBINING ANTICLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING ANTICLOCKWISE ARROW ABOVE;;;; +20D5;COMBINING CLOCKWISE ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING CLOCKWISE ARROW ABOVE;;;; +20D6;COMBINING LEFT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT ARROW ABOVE;;;; +20D7;COMBINING RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT ARROW ABOVE;;;; +20D8;COMBINING RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING RING OVERLAY;;;; +20D9;COMBINING CLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING CLOCKWISE RING OVERLAY;;;; +20DA;COMBINING ANTICLOCKWISE RING OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING ANTICLOCKWISE RING OVERLAY;;;; +20DB;COMBINING THREE DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING THREE DOTS ABOVE;;;; +20DC;COMBINING FOUR DOTS ABOVE;Mn;230;NSM;;;;;N;NON-SPACING FOUR DOTS ABOVE;;;; +20DD;COMBINING ENCLOSING CIRCLE;Me;0;NSM;;;;;N;ENCLOSING CIRCLE;;;; +20DE;COMBINING ENCLOSING SQUARE;Me;0;NSM;;;;;N;ENCLOSING SQUARE;;;; +20DF;COMBINING ENCLOSING DIAMOND;Me;0;NSM;;;;;N;ENCLOSING DIAMOND;;;; +20E0;COMBINING ENCLOSING CIRCLE BACKSLASH;Me;0;NSM;;;;;N;ENCLOSING CIRCLE SLASH;;;; +20E1;COMBINING LEFT RIGHT ARROW ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT RIGHT ARROW ABOVE;;;; +20E2;COMBINING ENCLOSING SCREEN;Me;0;NSM;;;;;N;;;;; +20E3;COMBINING ENCLOSING KEYCAP;Me;0;NSM;;;;;N;;;;; +20E4;COMBINING ENCLOSING UPWARD POINTING TRIANGLE;Me;0;NSM;;;;;N;;;;; +20E5;COMBINING REVERSE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; +20E6;COMBINING DOUBLE VERTICAL STROKE OVERLAY;Mn;1;NSM;;;;;N;;;;; +20E7;COMBINING ANNUITY SYMBOL;Mn;230;NSM;;;;;N;;;;; +20E8;COMBINING TRIPLE UNDERDOT;Mn;220;NSM;;;;;N;;;;; +20E9;COMBINING WIDE BRIDGE ABOVE;Mn;230;NSM;;;;;N;;;;; +20EA;COMBINING LEFTWARDS ARROW OVERLAY;Mn;1;NSM;;;;;N;;;;; +20EB;COMBINING LONG DOUBLE SOLIDUS OVERLAY;Mn;1;NSM;;;;;N;;;;; +20EC;COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; +20ED;COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS;Mn;220;NSM;;;;;N;;;;; +20EE;COMBINING LEFT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +20EF;COMBINING RIGHT ARROW BELOW;Mn;220;NSM;;;;;N;;;;; +20F0;COMBINING ASTERISK ABOVE;Mn;230;NSM;;;;;N;;;;; +2100;ACCOUNT OF;So;0;ON; 0061 002F 0063;;;;N;;;;; +2101;ADDRESSED TO THE SUBJECT;So;0;ON; 0061 002F 0073;;;;N;;;;; +2102;DOUBLE-STRUCK CAPITAL C;Lu;0;L; 0043;;;;N;DOUBLE-STRUCK C;;;; +2103;DEGREE CELSIUS;So;0;ON; 00B0 0043;;;;N;DEGREES CENTIGRADE;;;; +2104;CENTRE LINE SYMBOL;So;0;ON;;;;;N;C L SYMBOL;;;; +2105;CARE OF;So;0;ON; 0063 002F 006F;;;;N;;;;; +2106;CADA UNA;So;0;ON; 0063 002F 0075;;;;N;;;;; +2107;EULER CONSTANT;Lu;0;L; 0190;;;;N;EULERS;;;; +2108;SCRUPLE;So;0;ON;;;;;N;;;;; +2109;DEGREE FAHRENHEIT;So;0;ON; 00B0 0046;;;;N;DEGREES FAHRENHEIT;;;; +210A;SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; +210B;SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;SCRIPT H;;;; +210C;BLACK-LETTER CAPITAL H;Lu;0;L; 0048;;;;N;BLACK-LETTER H;;;; +210D;DOUBLE-STRUCK CAPITAL H;Lu;0;L; 0048;;;;N;DOUBLE-STRUCK H;;;; +210E;PLANCK CONSTANT;Ll;0;L; 0068;;;;N;;;;; +210F;PLANCK CONSTANT OVER TWO PI;Ll;0;L; 0127;;;;N;PLANCK CONSTANT OVER 2 PI;;;; +2110;SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;SCRIPT I;;;; +2111;BLACK-LETTER CAPITAL I;Lu;0;L; 0049;;;;N;BLACK-LETTER I;;;; +2112;SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;SCRIPT L;;;; +2113;SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; +2114;L B BAR SYMBOL;So;0;ON;;;;;N;;;;; +2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L; 004E;;;;N;DOUBLE-STRUCK N;;;; +2116;NUMERO SIGN;So;0;ON; 004E 006F;;;;N;NUMERO;;;; +2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; +2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;; +2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L; 0050;;;;N;DOUBLE-STRUCK P;;;; +211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L; 0051;;;;N;DOUBLE-STRUCK Q;;;; +211B;SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;SCRIPT R;;;; +211C;BLACK-LETTER CAPITAL R;Lu;0;L; 0052;;;;N;BLACK-LETTER R;;;; +211D;DOUBLE-STRUCK CAPITAL R;Lu;0;L; 0052;;;;N;DOUBLE-STRUCK R;;;; +211E;PRESCRIPTION TAKE;So;0;ON;;;;;N;;;;; +211F;RESPONSE;So;0;ON;;;;;N;;;;; +2120;SERVICE MARK;So;0;ON; 0053 004D;;;;N;;;;; +2121;TELEPHONE SIGN;So;0;ON; 0054 0045 004C;;;;N;T E L SYMBOL;;;; +2122;TRADE MARK SIGN;So;0;ON; 0054 004D;;;;N;TRADEMARK;;;; +2123;VERSICLE;So;0;ON;;;;;N;;;;; +2124;DOUBLE-STRUCK CAPITAL Z;Lu;0;L; 005A;;;;N;DOUBLE-STRUCK Z;;;; +2125;OUNCE SIGN;So;0;ON;;;;;N;OUNCE;;;; +2126;OHM SIGN;Lu;0;L;03A9;;;;N;OHM;;;03C9; +2127;INVERTED OHM SIGN;So;0;ON;;;;;N;MHO;;;; +2128;BLACK-LETTER CAPITAL Z;Lu;0;L; 005A;;;;N;BLACK-LETTER Z;;;; +2129;TURNED GREEK SMALL LETTER IOTA;So;0;ON;;;;;N;;;;; +212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; +212B;ANGSTROM SIGN;Lu;0;L;00C5;;;;N;ANGSTROM UNIT;;;00E5; +212C;SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;SCRIPT B;;;; +212D;BLACK-LETTER CAPITAL C;Lu;0;L; 0043;;;;N;BLACK-LETTER C;;;; +212E;ESTIMATED SYMBOL;So;0;ET;;;;;N;;;;; +212F;SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; +2130;SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;SCRIPT E;;;; +2131;SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;SCRIPT F;;;; +2132;TURNED CAPITAL F;Lu;0;L;;;;;N;TURNED F;;;214E; +2133;SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;SCRIPT M;;;; +2134;SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; +2135;ALEF SYMBOL;Lo;0;L; 05D0;;;;N;FIRST TRANSFINITE CARDINAL;;;; +2136;BET SYMBOL;Lo;0;L; 05D1;;;;N;SECOND TRANSFINITE CARDINAL;;;; +2137;GIMEL SYMBOL;Lo;0;L; 05D2;;;;N;THIRD TRANSFINITE CARDINAL;;;; +2138;DALET SYMBOL;Lo;0;L; 05D3;;;;N;FOURTH TRANSFINITE CARDINAL;;;; +2139;INFORMATION SOURCE;Ll;0;L; 0069;;;;N;;;;; +213A;ROTATED CAPITAL Q;So;0;ON;;;;;N;;;;; +213B;FACSIMILE SIGN;So;0;ON; 0046 0041 0058;;;;N;;;;; +213C;DOUBLE-STRUCK SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +213D;DOUBLE-STRUCK SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +213E;DOUBLE-STRUCK CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +213F;DOUBLE-STRUCK CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +2140;DOUBLE-STRUCK N-ARY SUMMATION;Sm;0;ON; 2211;;;;Y;;;;; +2141;TURNED SANS-SERIF CAPITAL G;Sm;0;ON;;;;;N;;;;; +2142;TURNED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; +2143;REVERSED SANS-SERIF CAPITAL L;Sm;0;ON;;;;;N;;;;; +2144;TURNED SANS-SERIF CAPITAL Y;Sm;0;ON;;;;;N;;;;; +2145;DOUBLE-STRUCK ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +2146;DOUBLE-STRUCK ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; +2147;DOUBLE-STRUCK ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; +2148;DOUBLE-STRUCK ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; +2149;DOUBLE-STRUCK ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; +214A;PROPERTY LINE;So;0;ON;;;;;N;;;;; +214B;TURNED AMPERSAND;Sm;0;ON;;;;;N;;;;; +214C;PER SIGN;So;0;ON;;;;;N;;;;; +214D;AKTIESELSKAB;So;0;ON;;;;;N;;;;; +214E;TURNED SMALL F;Ll;0;L;;;;;N;;;2132;;2132 +214F;SYMBOL FOR SAMARITAN SOURCE;So;0;L;;;;;N;;;;; +2150;VULGAR FRACTION ONE SEVENTH;No;0;ON; 0031 2044 0037;;;1/7;N;;;;; +2151;VULGAR FRACTION ONE NINTH;No;0;ON; 0031 2044 0039;;;1/9;N;;;;; +2152;VULGAR FRACTION ONE TENTH;No;0;ON; 0031 2044 0031 0030;;;1/10;N;;;;; +2153;VULGAR FRACTION ONE THIRD;No;0;ON; 0031 2044 0033;;;1/3;N;FRACTION ONE THIRD;;;; +2154;VULGAR FRACTION TWO THIRDS;No;0;ON; 0032 2044 0033;;;2/3;N;FRACTION TWO THIRDS;;;; +2155;VULGAR FRACTION ONE FIFTH;No;0;ON; 0031 2044 0035;;;1/5;N;FRACTION ONE FIFTH;;;; +2156;VULGAR FRACTION TWO FIFTHS;No;0;ON; 0032 2044 0035;;;2/5;N;FRACTION TWO FIFTHS;;;; +2157;VULGAR FRACTION THREE FIFTHS;No;0;ON; 0033 2044 0035;;;3/5;N;FRACTION THREE FIFTHS;;;; +2158;VULGAR FRACTION FOUR FIFTHS;No;0;ON; 0034 2044 0035;;;4/5;N;FRACTION FOUR FIFTHS;;;; +2159;VULGAR FRACTION ONE SIXTH;No;0;ON; 0031 2044 0036;;;1/6;N;FRACTION ONE SIXTH;;;; +215A;VULGAR FRACTION FIVE SIXTHS;No;0;ON; 0035 2044 0036;;;5/6;N;FRACTION FIVE SIXTHS;;;; +215B;VULGAR FRACTION ONE EIGHTH;No;0;ON; 0031 2044 0038;;;1/8;N;FRACTION ONE EIGHTH;;;; +215C;VULGAR FRACTION THREE EIGHTHS;No;0;ON; 0033 2044 0038;;;3/8;N;FRACTION THREE EIGHTHS;;;; +215D;VULGAR FRACTION FIVE EIGHTHS;No;0;ON; 0035 2044 0038;;;5/8;N;FRACTION FIVE EIGHTHS;;;; +215E;VULGAR FRACTION SEVEN EIGHTHS;No;0;ON; 0037 2044 0038;;;7/8;N;FRACTION SEVEN EIGHTHS;;;; +215F;FRACTION NUMERATOR ONE;No;0;ON; 0031 2044;;;1;N;;;;; +2160;ROMAN NUMERAL ONE;Nl;0;L; 0049;;;1;N;;;;2170; +2161;ROMAN NUMERAL TWO;Nl;0;L; 0049 0049;;;2;N;;;;2171; +2162;ROMAN NUMERAL THREE;Nl;0;L; 0049 0049 0049;;;3;N;;;;2172; +2163;ROMAN NUMERAL FOUR;Nl;0;L; 0049 0056;;;4;N;;;;2173; +2164;ROMAN NUMERAL FIVE;Nl;0;L; 0056;;;5;N;;;;2174; +2165;ROMAN NUMERAL SIX;Nl;0;L; 0056 0049;;;6;N;;;;2175; +2166;ROMAN NUMERAL SEVEN;Nl;0;L; 0056 0049 0049;;;7;N;;;;2176; +2167;ROMAN NUMERAL EIGHT;Nl;0;L; 0056 0049 0049 0049;;;8;N;;;;2177; +2168;ROMAN NUMERAL NINE;Nl;0;L; 0049 0058;;;9;N;;;;2178; +2169;ROMAN NUMERAL TEN;Nl;0;L; 0058;;;10;N;;;;2179; +216A;ROMAN NUMERAL ELEVEN;Nl;0;L; 0058 0049;;;11;N;;;;217A; +216B;ROMAN NUMERAL TWELVE;Nl;0;L; 0058 0049 0049;;;12;N;;;;217B; +216C;ROMAN NUMERAL FIFTY;Nl;0;L; 004C;;;50;N;;;;217C; +216D;ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0043;;;100;N;;;;217D; +216E;ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0044;;;500;N;;;;217E; +216F;ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 004D;;;1000;N;;;;217F; +2170;SMALL ROMAN NUMERAL ONE;Nl;0;L; 0069;;;1;N;;;2160;;2160 +2171;SMALL ROMAN NUMERAL TWO;Nl;0;L; 0069 0069;;;2;N;;;2161;;2161 +2172;SMALL ROMAN NUMERAL THREE;Nl;0;L; 0069 0069 0069;;;3;N;;;2162;;2162 +2173;SMALL ROMAN NUMERAL FOUR;Nl;0;L; 0069 0076;;;4;N;;;2163;;2163 +2174;SMALL ROMAN NUMERAL FIVE;Nl;0;L; 0076;;;5;N;;;2164;;2164 +2175;SMALL ROMAN NUMERAL SIX;Nl;0;L; 0076 0069;;;6;N;;;2165;;2165 +2176;SMALL ROMAN NUMERAL SEVEN;Nl;0;L; 0076 0069 0069;;;7;N;;;2166;;2166 +2177;SMALL ROMAN NUMERAL EIGHT;Nl;0;L; 0076 0069 0069 0069;;;8;N;;;2167;;2167 +2178;SMALL ROMAN NUMERAL NINE;Nl;0;L; 0069 0078;;;9;N;;;2168;;2168 +2179;SMALL ROMAN NUMERAL TEN;Nl;0;L; 0078;;;10;N;;;2169;;2169 +217A;SMALL ROMAN NUMERAL ELEVEN;Nl;0;L; 0078 0069;;;11;N;;;216A;;216A +217B;SMALL ROMAN NUMERAL TWELVE;Nl;0;L; 0078 0069 0069;;;12;N;;;216B;;216B +217C;SMALL ROMAN NUMERAL FIFTY;Nl;0;L; 006C;;;50;N;;;216C;;216C +217D;SMALL ROMAN NUMERAL ONE HUNDRED;Nl;0;L; 0063;;;100;N;;;216D;;216D +217E;SMALL ROMAN NUMERAL FIVE HUNDRED;Nl;0;L; 0064;;;500;N;;;216E;;216E +217F;SMALL ROMAN NUMERAL ONE THOUSAND;Nl;0;L; 006D;;;1000;N;;;216F;;216F +2180;ROMAN NUMERAL ONE THOUSAND C D;Nl;0;L;;;;1000;N;;;;; +2181;ROMAN NUMERAL FIVE THOUSAND;Nl;0;L;;;;5000;N;;;;; +2182;ROMAN NUMERAL TEN THOUSAND;Nl;0;L;;;;10000;N;;;;; +2183;ROMAN NUMERAL REVERSED ONE HUNDRED;Lu;0;L;;;;;N;;;;2184; +2184;LATIN SMALL LETTER REVERSED C;Ll;0;L;;;;;N;;;2183;;2183 +2185;ROMAN NUMERAL SIX LATE FORM;Nl;0;L;;;;6;N;;;;; +2186;ROMAN NUMERAL FIFTY EARLY FORM;Nl;0;L;;;;50;N;;;;; +2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;; +2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;; +2189;VULGAR FRACTION ZERO THIRDS;No;0;ON; 0030 2044 0033;;;0;N;;;;; +218A;TURNED DIGIT TWO;So;0;ON;;;;;N;;;;; +218B;TURNED DIGIT THREE;So;0;ON;;;;;N;;;;; +2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;; +2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;; +2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;; +2193;DOWNWARDS ARROW;Sm;0;ON;;;;;N;DOWN ARROW;;;; +2194;LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; +2195;UP DOWN ARROW;So;0;ON;;;;;N;;;;; +2196;NORTH WEST ARROW;So;0;ON;;;;;N;UPPER LEFT ARROW;;;; +2197;NORTH EAST ARROW;So;0;ON;;;;;N;UPPER RIGHT ARROW;;;; +2198;SOUTH EAST ARROW;So;0;ON;;;;;N;LOWER RIGHT ARROW;;;; +2199;SOUTH WEST ARROW;So;0;ON;;;;;N;LOWER LEFT ARROW;;;; +219A;LEFTWARDS ARROW WITH STROKE;Sm;0;ON;2190 0338;;;;N;LEFT ARROW WITH STROKE;;;; +219B;RIGHTWARDS ARROW WITH STROKE;Sm;0;ON;2192 0338;;;;N;RIGHT ARROW WITH STROKE;;;; +219C;LEFTWARDS WAVE ARROW;So;0;ON;;;;;N;LEFT WAVE ARROW;;;; +219D;RIGHTWARDS WAVE ARROW;So;0;ON;;;;;N;RIGHT WAVE ARROW;;;; +219E;LEFTWARDS TWO HEADED ARROW;So;0;ON;;;;;N;LEFT TWO HEADED ARROW;;;; +219F;UPWARDS TWO HEADED ARROW;So;0;ON;;;;;N;UP TWO HEADED ARROW;;;; +21A0;RIGHTWARDS TWO HEADED ARROW;Sm;0;ON;;;;;N;RIGHT TWO HEADED ARROW;;;; +21A1;DOWNWARDS TWO HEADED ARROW;So;0;ON;;;;;N;DOWN TWO HEADED ARROW;;;; +21A2;LEFTWARDS ARROW WITH TAIL;So;0;ON;;;;;N;LEFT ARROW WITH TAIL;;;; +21A3;RIGHTWARDS ARROW WITH TAIL;Sm;0;ON;;;;;N;RIGHT ARROW WITH TAIL;;;; +21A4;LEFTWARDS ARROW FROM BAR;So;0;ON;;;;;N;LEFT ARROW FROM BAR;;;; +21A5;UPWARDS ARROW FROM BAR;So;0;ON;;;;;N;UP ARROW FROM BAR;;;; +21A6;RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;RIGHT ARROW FROM BAR;;;; +21A7;DOWNWARDS ARROW FROM BAR;So;0;ON;;;;;N;DOWN ARROW FROM BAR;;;; +21A8;UP DOWN ARROW WITH BASE;So;0;ON;;;;;N;;;;; +21A9;LEFTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;LEFT ARROW WITH HOOK;;;; +21AA;RIGHTWARDS ARROW WITH HOOK;So;0;ON;;;;;N;RIGHT ARROW WITH HOOK;;;; +21AB;LEFTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;LEFT ARROW WITH LOOP;;;; +21AC;RIGHTWARDS ARROW WITH LOOP;So;0;ON;;;;;N;RIGHT ARROW WITH LOOP;;;; +21AD;LEFT RIGHT WAVE ARROW;So;0;ON;;;;;N;;;;; +21AE;LEFT RIGHT ARROW WITH STROKE;Sm;0;ON;2194 0338;;;;N;;;;; +21AF;DOWNWARDS ZIGZAG ARROW;So;0;ON;;;;;N;DOWN ZIGZAG ARROW;;;; +21B0;UPWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP LEFT;;;; +21B1;UPWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;UP ARROW WITH TIP RIGHT;;;; +21B2;DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP LEFT;;;; +21B3;DOWNWARDS ARROW WITH TIP RIGHTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH TIP RIGHT;;;; +21B4;RIGHTWARDS ARROW WITH CORNER DOWNWARDS;So;0;ON;;;;;N;RIGHT ARROW WITH CORNER DOWN;;;; +21B5;DOWNWARDS ARROW WITH CORNER LEFTWARDS;So;0;ON;;;;;N;DOWN ARROW WITH CORNER LEFT;;;; +21B6;ANTICLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; +21B7;CLOCKWISE TOP SEMICIRCLE ARROW;So;0;ON;;;;;N;;;;; +21B8;NORTH WEST ARROW TO LONG BAR;So;0;ON;;;;;N;UPPER LEFT ARROW TO LONG BAR;;;; +21B9;LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR;;;; +21BA;ANTICLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +21BB;CLOCKWISE OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +21BC;LEFTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB UP;;;; +21BD;LEFTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;LEFT HARPOON WITH BARB DOWN;;;; +21BE;UPWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB RIGHT;;;; +21BF;UPWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;UP HARPOON WITH BARB LEFT;;;; +21C0;RIGHTWARDS HARPOON WITH BARB UPWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB UP;;;; +21C1;RIGHTWARDS HARPOON WITH BARB DOWNWARDS;So;0;ON;;;;;N;RIGHT HARPOON WITH BARB DOWN;;;; +21C2;DOWNWARDS HARPOON WITH BARB RIGHTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB RIGHT;;;; +21C3;DOWNWARDS HARPOON WITH BARB LEFTWARDS;So;0;ON;;;;;N;DOWN HARPOON WITH BARB LEFT;;;; +21C4;RIGHTWARDS ARROW OVER LEFTWARDS ARROW;So;0;ON;;;;;N;RIGHT ARROW OVER LEFT ARROW;;;; +21C5;UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW;So;0;ON;;;;;N;UP ARROW LEFT OF DOWN ARROW;;;; +21C6;LEFTWARDS ARROW OVER RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT ARROW OVER RIGHT ARROW;;;; +21C7;LEFTWARDS PAIRED ARROWS;So;0;ON;;;;;N;LEFT PAIRED ARROWS;;;; +21C8;UPWARDS PAIRED ARROWS;So;0;ON;;;;;N;UP PAIRED ARROWS;;;; +21C9;RIGHTWARDS PAIRED ARROWS;So;0;ON;;;;;N;RIGHT PAIRED ARROWS;;;; +21CA;DOWNWARDS PAIRED ARROWS;So;0;ON;;;;;N;DOWN PAIRED ARROWS;;;; +21CB;LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON;So;0;ON;;;;;N;LEFT HARPOON OVER RIGHT HARPOON;;;; +21CC;RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON;So;0;ON;;;;;N;RIGHT HARPOON OVER LEFT HARPOON;;;; +21CD;LEFTWARDS DOUBLE ARROW WITH STROKE;So;0;ON;21D0 0338;;;;N;LEFT DOUBLE ARROW WITH STROKE;;;; +21CE;LEFT RIGHT DOUBLE ARROW WITH STROKE;Sm;0;ON;21D4 0338;;;;N;;;;; +21CF;RIGHTWARDS DOUBLE ARROW WITH STROKE;Sm;0;ON;21D2 0338;;;;N;RIGHT DOUBLE ARROW WITH STROKE;;;; +21D0;LEFTWARDS DOUBLE ARROW;So;0;ON;;;;;N;LEFT DOUBLE ARROW;;;; +21D1;UPWARDS DOUBLE ARROW;So;0;ON;;;;;N;UP DOUBLE ARROW;;;; +21D2;RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;RIGHT DOUBLE ARROW;;;; +21D3;DOWNWARDS DOUBLE ARROW;So;0;ON;;;;;N;DOWN DOUBLE ARROW;;;; +21D4;LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +21D5;UP DOWN DOUBLE ARROW;So;0;ON;;;;;N;;;;; +21D6;NORTH WEST DOUBLE ARROW;So;0;ON;;;;;N;UPPER LEFT DOUBLE ARROW;;;; +21D7;NORTH EAST DOUBLE ARROW;So;0;ON;;;;;N;UPPER RIGHT DOUBLE ARROW;;;; +21D8;SOUTH EAST DOUBLE ARROW;So;0;ON;;;;;N;LOWER RIGHT DOUBLE ARROW;;;; +21D9;SOUTH WEST DOUBLE ARROW;So;0;ON;;;;;N;LOWER LEFT DOUBLE ARROW;;;; +21DA;LEFTWARDS TRIPLE ARROW;So;0;ON;;;;;N;LEFT TRIPLE ARROW;;;; +21DB;RIGHTWARDS TRIPLE ARROW;So;0;ON;;;;;N;RIGHT TRIPLE ARROW;;;; +21DC;LEFTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;LEFT SQUIGGLE ARROW;;;; +21DD;RIGHTWARDS SQUIGGLE ARROW;So;0;ON;;;;;N;RIGHT SQUIGGLE ARROW;;;; +21DE;UPWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;UP ARROW WITH DOUBLE STROKE;;;; +21DF;DOWNWARDS ARROW WITH DOUBLE STROKE;So;0;ON;;;;;N;DOWN ARROW WITH DOUBLE STROKE;;;; +21E0;LEFTWARDS DASHED ARROW;So;0;ON;;;;;N;LEFT DASHED ARROW;;;; +21E1;UPWARDS DASHED ARROW;So;0;ON;;;;;N;UP DASHED ARROW;;;; +21E2;RIGHTWARDS DASHED ARROW;So;0;ON;;;;;N;RIGHT DASHED ARROW;;;; +21E3;DOWNWARDS DASHED ARROW;So;0;ON;;;;;N;DOWN DASHED ARROW;;;; +21E4;LEFTWARDS ARROW TO BAR;So;0;ON;;;;;N;LEFT ARROW TO BAR;;;; +21E5;RIGHTWARDS ARROW TO BAR;So;0;ON;;;;;N;RIGHT ARROW TO BAR;;;; +21E6;LEFTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE LEFT ARROW;;;; +21E7;UPWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE UP ARROW;;;; +21E8;RIGHTWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE RIGHT ARROW;;;; +21E9;DOWNWARDS WHITE ARROW;So;0;ON;;;;;N;WHITE DOWN ARROW;;;; +21EA;UPWARDS WHITE ARROW FROM BAR;So;0;ON;;;;;N;WHITE UP ARROW FROM BAR;;;; +21EB;UPWARDS WHITE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; +21EC;UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; +21ED;UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +21EE;UPWARDS WHITE DOUBLE ARROW;So;0;ON;;;;;N;;;;; +21EF;UPWARDS WHITE DOUBLE ARROW ON PEDESTAL;So;0;ON;;;;;N;;;;; +21F0;RIGHTWARDS WHITE ARROW FROM WALL;So;0;ON;;;;;N;;;;; +21F1;NORTH WEST ARROW TO CORNER;So;0;ON;;;;;N;;;;; +21F2;SOUTH EAST ARROW TO CORNER;So;0;ON;;;;;N;;;;; +21F3;UP DOWN WHITE ARROW;So;0;ON;;;;;N;;;;; +21F4;RIGHT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +21F5;DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW;Sm;0;ON;;;;;N;;;;; +21F6;THREE RIGHTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; +21F7;LEFTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21F8;RIGHTWARDS ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21F9;LEFT RIGHT ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FA;LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FB;RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FC;LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +21FD;LEFTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +21FE;RIGHTWARDS OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +21FF;LEFT RIGHT OPEN-HEADED ARROW;Sm;0;ON;;;;;N;;;;; +2200;FOR ALL;Sm;0;ON;;;;;N;;;;; +2201;COMPLEMENT;Sm;0;ON;;;;;Y;;;;; +2202;PARTIAL DIFFERENTIAL;Sm;0;ON;;;;;Y;;;;; +2203;THERE EXISTS;Sm;0;ON;;;;;Y;;;;; +2204;THERE DOES NOT EXIST;Sm;0;ON;2203 0338;;;;Y;;;;; +2205;EMPTY SET;Sm;0;ON;;;;;N;;;;; +2206;INCREMENT;Sm;0;ON;;;;;N;;;;; +2207;NABLA;Sm;0;ON;;;;;N;;;;; +2208;ELEMENT OF;Sm;0;ON;;;;;Y;;;;; +2209;NOT AN ELEMENT OF;Sm;0;ON;2208 0338;;;;Y;;;;; +220A;SMALL ELEMENT OF;Sm;0;ON;;;;;Y;;;;; +220B;CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; +220C;DOES NOT CONTAIN AS MEMBER;Sm;0;ON;220B 0338;;;;Y;;;;; +220D;SMALL CONTAINS AS MEMBER;Sm;0;ON;;;;;Y;;;;; +220E;END OF PROOF;Sm;0;ON;;;;;N;;;;; +220F;N-ARY PRODUCT;Sm;0;ON;;;;;N;;;;; +2210;N-ARY COPRODUCT;Sm;0;ON;;;;;N;;;;; +2211;N-ARY SUMMATION;Sm;0;ON;;;;;Y;;;;; +2212;MINUS SIGN;Sm;0;ES;;;;;N;;;;; +2213;MINUS-OR-PLUS SIGN;Sm;0;ET;;;;;N;;;;; +2214;DOT PLUS;Sm;0;ON;;;;;N;;;;; +2215;DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; +2216;SET MINUS;Sm;0;ON;;;;;Y;;;;; +2217;ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; +2218;RING OPERATOR;Sm;0;ON;;;;;N;;;;; +2219;BULLET OPERATOR;Sm;0;ON;;;;;N;;;;; +221A;SQUARE ROOT;Sm;0;ON;;;;;Y;;;;; +221B;CUBE ROOT;Sm;0;ON;;;;;Y;;;;; +221C;FOURTH ROOT;Sm;0;ON;;;;;Y;;;;; +221D;PROPORTIONAL TO;Sm;0;ON;;;;;Y;;;;; +221E;INFINITY;Sm;0;ON;;;;;N;;;;; +221F;RIGHT ANGLE;Sm;0;ON;;;;;Y;;;;; +2220;ANGLE;Sm;0;ON;;;;;Y;;;;; +2221;MEASURED ANGLE;Sm;0;ON;;;;;Y;;;;; +2222;SPHERICAL ANGLE;Sm;0;ON;;;;;Y;;;;; +2223;DIVIDES;Sm;0;ON;;;;;N;;;;; +2224;DOES NOT DIVIDE;Sm;0;ON;2223 0338;;;;Y;;;;; +2225;PARALLEL TO;Sm;0;ON;;;;;N;;;;; +2226;NOT PARALLEL TO;Sm;0;ON;2225 0338;;;;Y;;;;; +2227;LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2228;LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2229;INTERSECTION;Sm;0;ON;;;;;N;;;;; +222A;UNION;Sm;0;ON;;;;;N;;;;; +222B;INTEGRAL;Sm;0;ON;;;;;Y;;;;; +222C;DOUBLE INTEGRAL;Sm;0;ON; 222B 222B;;;;Y;;;;; +222D;TRIPLE INTEGRAL;Sm;0;ON; 222B 222B 222B;;;;Y;;;;; +222E;CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +222F;SURFACE INTEGRAL;Sm;0;ON; 222E 222E;;;;Y;;;;; +2230;VOLUME INTEGRAL;Sm;0;ON; 222E 222E 222E;;;;Y;;;;; +2231;CLOCKWISE INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2232;CLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2233;ANTICLOCKWISE CONTOUR INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2234;THEREFORE;Sm;0;ON;;;;;N;;;;; +2235;BECAUSE;Sm;0;ON;;;;;N;;;;; +2236;RATIO;Sm;0;ON;;;;;N;;;;; +2237;PROPORTION;Sm;0;ON;;;;;N;;;;; +2238;DOT MINUS;Sm;0;ON;;;;;N;;;;; +2239;EXCESS;Sm;0;ON;;;;;Y;;;;; +223A;GEOMETRIC PROPORTION;Sm;0;ON;;;;;N;;;;; +223B;HOMOTHETIC;Sm;0;ON;;;;;Y;;;;; +223C;TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +223D;REVERSED TILDE;Sm;0;ON;;;;;Y;;;;; +223E;INVERTED LAZY S;Sm;0;ON;;;;;Y;;;;; +223F;SINE WAVE;Sm;0;ON;;;;;Y;;;;; +2240;WREATH PRODUCT;Sm;0;ON;;;;;Y;;;;; +2241;NOT TILDE;Sm;0;ON;223C 0338;;;;Y;;;;; +2242;MINUS TILDE;Sm;0;ON;;;;;Y;;;;; +2243;ASYMPTOTICALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2244;NOT ASYMPTOTICALLY EQUAL TO;Sm;0;ON;2243 0338;;;;Y;;;;; +2245;APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2246;APPROXIMATELY BUT NOT ACTUALLY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2247;NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO;Sm;0;ON;2245 0338;;;;Y;;;;; +2248;ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2249;NOT ALMOST EQUAL TO;Sm;0;ON;2248 0338;;;;Y;;;;; +224A;ALMOST EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +224B;TRIPLE TILDE;Sm;0;ON;;;;;Y;;;;; +224C;ALL EQUAL TO;Sm;0;ON;;;;;Y;;;;; +224D;EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +224E;GEOMETRICALLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +224F;DIFFERENCE BETWEEN;Sm;0;ON;;;;;N;;;;; +2250;APPROACHES THE LIMIT;Sm;0;ON;;;;;N;;;;; +2251;GEOMETRICALLY EQUAL TO;Sm;0;ON;;;;;N;;;;; +2252;APPROXIMATELY EQUAL TO OR THE IMAGE OF;Sm;0;ON;;;;;Y;;;;; +2253;IMAGE OF OR APPROXIMATELY EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2254;COLON EQUALS;Sm;0;ON;;;;;Y;COLON EQUAL;;;; +2255;EQUALS COLON;Sm;0;ON;;;;;Y;EQUAL COLON;;;; +2256;RING IN EQUAL TO;Sm;0;ON;;;;;N;;;;; +2257;RING EQUAL TO;Sm;0;ON;;;;;N;;;;; +2258;CORRESPONDS TO;Sm;0;ON;;;;;N;;;;; +2259;ESTIMATES;Sm;0;ON;;;;;N;;;;; +225A;EQUIANGULAR TO;Sm;0;ON;;;;;N;;;;; +225B;STAR EQUALS;Sm;0;ON;;;;;N;;;;; +225C;DELTA EQUAL TO;Sm;0;ON;;;;;N;;;;; +225D;EQUAL TO BY DEFINITION;Sm;0;ON;;;;;N;;;;; +225E;MEASURED BY;Sm;0;ON;;;;;N;;;;; +225F;QUESTIONED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2260;NOT EQUAL TO;Sm;0;ON;003D 0338;;;;Y;;;;; +2261;IDENTICAL TO;Sm;0;ON;;;;;N;;;;; +2262;NOT IDENTICAL TO;Sm;0;ON;2261 0338;;;;Y;;;;; +2263;STRICTLY EQUIVALENT TO;Sm;0;ON;;;;;N;;;;; +2264;LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUAL TO;;;; +2265;GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUAL TO;;;; +2266;LESS-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN OVER EQUAL TO;;;; +2267;GREATER-THAN OVER EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN OVER EQUAL TO;;;; +2268;LESS-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUAL TO;;;; +2269;GREATER-THAN BUT NOT EQUAL TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUAL TO;;;; +226A;MUCH LESS-THAN;Sm;0;ON;;;;;Y;MUCH LESS THAN;;;; +226B;MUCH GREATER-THAN;Sm;0;ON;;;;;Y;MUCH GREATER THAN;;;; +226C;BETWEEN;Sm;0;ON;;;;;N;;;;; +226D;NOT EQUIVALENT TO;Sm;0;ON;224D 0338;;;;Y;;;;; +226E;NOT LESS-THAN;Sm;0;ON;003C 0338;;;;Y;NOT LESS THAN;;;; +226F;NOT GREATER-THAN;Sm;0;ON;003E 0338;;;;Y;NOT GREATER THAN;;;; +2270;NEITHER LESS-THAN NOR EQUAL TO;Sm;0;ON;2264 0338;;;;Y;NEITHER LESS THAN NOR EQUAL TO;;;; +2271;NEITHER GREATER-THAN NOR EQUAL TO;Sm;0;ON;2265 0338;;;;Y;NEITHER GREATER THAN NOR EQUAL TO;;;; +2272;LESS-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN OR EQUIVALENT TO;;;; +2273;GREATER-THAN OR EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN OR EQUIVALENT TO;;;; +2274;NEITHER LESS-THAN NOR EQUIVALENT TO;Sm;0;ON;2272 0338;;;;Y;NEITHER LESS THAN NOR EQUIVALENT TO;;;; +2275;NEITHER GREATER-THAN NOR EQUIVALENT TO;Sm;0;ON;2273 0338;;;;Y;NEITHER GREATER THAN NOR EQUIVALENT TO;;;; +2276;LESS-THAN OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN OR GREATER THAN;;;; +2277;GREATER-THAN OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN OR LESS THAN;;;; +2278;NEITHER LESS-THAN NOR GREATER-THAN;Sm;0;ON;2276 0338;;;;Y;NEITHER LESS THAN NOR GREATER THAN;;;; +2279;NEITHER GREATER-THAN NOR LESS-THAN;Sm;0;ON;2277 0338;;;;Y;NEITHER GREATER THAN NOR LESS THAN;;;; +227A;PRECEDES;Sm;0;ON;;;;;Y;;;;; +227B;SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +227C;PRECEDES OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +227D;SUCCEEDS OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +227E;PRECEDES OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +227F;SUCCEEDS OR EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +2280;DOES NOT PRECEDE;Sm;0;ON;227A 0338;;;;Y;;;;; +2281;DOES NOT SUCCEED;Sm;0;ON;227B 0338;;;;Y;;;;; +2282;SUBSET OF;Sm;0;ON;;;;;Y;;;;; +2283;SUPERSET OF;Sm;0;ON;;;;;Y;;;;; +2284;NOT A SUBSET OF;Sm;0;ON;2282 0338;;;;Y;;;;; +2285;NOT A SUPERSET OF;Sm;0;ON;2283 0338;;;;Y;;;;; +2286;SUBSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2287;SUPERSET OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2288;NEITHER A SUBSET OF NOR EQUAL TO;Sm;0;ON;2286 0338;;;;Y;;;;; +2289;NEITHER A SUPERSET OF NOR EQUAL TO;Sm;0;ON;2287 0338;;;;Y;;;;; +228A;SUBSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUBSET OF OR NOT EQUAL TO;;;; +228B;SUPERSET OF WITH NOT EQUAL TO;Sm;0;ON;;;;;Y;SUPERSET OF OR NOT EQUAL TO;;;; +228C;MULTISET;Sm;0;ON;;;;;Y;;;;; +228D;MULTISET MULTIPLICATION;Sm;0;ON;;;;;N;;;;; +228E;MULTISET UNION;Sm;0;ON;;;;;N;;;;; +228F;SQUARE IMAGE OF;Sm;0;ON;;;;;Y;;;;; +2290;SQUARE ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; +2291;SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2292;SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2293;SQUARE CAP;Sm;0;ON;;;;;N;;;;; +2294;SQUARE CUP;Sm;0;ON;;;;;N;;;;; +2295;CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +2296;CIRCLED MINUS;Sm;0;ON;;;;;N;;;;; +2297;CIRCLED TIMES;Sm;0;ON;;;;;N;;;;; +2298;CIRCLED DIVISION SLASH;Sm;0;ON;;;;;Y;;;;; +2299;CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +229A;CIRCLED RING OPERATOR;Sm;0;ON;;;;;N;;;;; +229B;CIRCLED ASTERISK OPERATOR;Sm;0;ON;;;;;N;;;;; +229C;CIRCLED EQUALS;Sm;0;ON;;;;;N;;;;; +229D;CIRCLED DASH;Sm;0;ON;;;;;N;;;;; +229E;SQUARED PLUS;Sm;0;ON;;;;;N;;;;; +229F;SQUARED MINUS;Sm;0;ON;;;;;N;;;;; +22A0;SQUARED TIMES;Sm;0;ON;;;;;N;;;;; +22A1;SQUARED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +22A2;RIGHT TACK;Sm;0;ON;;;;;Y;;;;; +22A3;LEFT TACK;Sm;0;ON;;;;;Y;;;;; +22A4;DOWN TACK;Sm;0;ON;;;;;N;;;;; +22A5;UP TACK;Sm;0;ON;;;;;N;;;;; +22A6;ASSERTION;Sm;0;ON;;;;;Y;;;;; +22A7;MODELS;Sm;0;ON;;;;;Y;;;;; +22A8;TRUE;Sm;0;ON;;;;;Y;;;;; +22A9;FORCES;Sm;0;ON;;;;;Y;;;;; +22AA;TRIPLE VERTICAL BAR RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +22AB;DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +22AC;DOES NOT PROVE;Sm;0;ON;22A2 0338;;;;Y;;;;; +22AD;NOT TRUE;Sm;0;ON;22A8 0338;;;;Y;;;;; +22AE;DOES NOT FORCE;Sm;0;ON;22A9 0338;;;;Y;;;;; +22AF;NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE;Sm;0;ON;22AB 0338;;;;Y;;;;; +22B0;PRECEDES UNDER RELATION;Sm;0;ON;;;;;Y;;;;; +22B1;SUCCEEDS UNDER RELATION;Sm;0;ON;;;;;Y;;;;; +22B2;NORMAL SUBGROUP OF;Sm;0;ON;;;;;Y;;;;; +22B3;CONTAINS AS NORMAL SUBGROUP;Sm;0;ON;;;;;Y;;;;; +22B4;NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22B5;CONTAINS AS NORMAL SUBGROUP OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22B6;ORIGINAL OF;Sm;0;ON;;;;;Y;;;;; +22B7;IMAGE OF;Sm;0;ON;;;;;Y;;;;; +22B8;MULTIMAP;Sm;0;ON;;;;;Y;;;;; +22B9;HERMITIAN CONJUGATE MATRIX;Sm;0;ON;;;;;N;;;;; +22BA;INTERCALATE;Sm;0;ON;;;;;N;;;;; +22BB;XOR;Sm;0;ON;;;;;N;;;;; +22BC;NAND;Sm;0;ON;;;;;N;;;;; +22BD;NOR;Sm;0;ON;;;;;N;;;;; +22BE;RIGHT ANGLE WITH ARC;Sm;0;ON;;;;;Y;;;;; +22BF;RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +22C0;N-ARY LOGICAL AND;Sm;0;ON;;;;;N;;;;; +22C1;N-ARY LOGICAL OR;Sm;0;ON;;;;;N;;;;; +22C2;N-ARY INTERSECTION;Sm;0;ON;;;;;N;;;;; +22C3;N-ARY UNION;Sm;0;ON;;;;;N;;;;; +22C4;DIAMOND OPERATOR;Sm;0;ON;;;;;N;;;;; +22C5;DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +22C6;STAR OPERATOR;Sm;0;ON;;;;;N;;;;; +22C7;DIVISION TIMES;Sm;0;ON;;;;;N;;;;; +22C8;BOWTIE;Sm;0;ON;;;;;N;;;;; +22C9;LEFT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CA;RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CB;LEFT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CC;RIGHT SEMIDIRECT PRODUCT;Sm;0;ON;;;;;Y;;;;; +22CD;REVERSED TILDE EQUALS;Sm;0;ON;;;;;Y;;;;; +22CE;CURLY LOGICAL OR;Sm;0;ON;;;;;N;;;;; +22CF;CURLY LOGICAL AND;Sm;0;ON;;;;;N;;;;; +22D0;DOUBLE SUBSET;Sm;0;ON;;;;;Y;;;;; +22D1;DOUBLE SUPERSET;Sm;0;ON;;;;;Y;;;;; +22D2;DOUBLE INTERSECTION;Sm;0;ON;;;;;N;;;;; +22D3;DOUBLE UNION;Sm;0;ON;;;;;N;;;;; +22D4;PITCHFORK;Sm;0;ON;;;;;N;;;;; +22D5;EQUAL AND PARALLEL TO;Sm;0;ON;;;;;N;;;;; +22D6;LESS-THAN WITH DOT;Sm;0;ON;;;;;Y;LESS THAN WITH DOT;;;; +22D7;GREATER-THAN WITH DOT;Sm;0;ON;;;;;Y;GREATER THAN WITH DOT;;;; +22D8;VERY MUCH LESS-THAN;Sm;0;ON;;;;;Y;VERY MUCH LESS THAN;;;; +22D9;VERY MUCH GREATER-THAN;Sm;0;ON;;;;;Y;VERY MUCH GREATER THAN;;;; +22DA;LESS-THAN EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;LESS THAN EQUAL TO OR GREATER THAN;;;; +22DB;GREATER-THAN EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;GREATER THAN EQUAL TO OR LESS THAN;;;; +22DC;EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR LESS THAN;;;; +22DD;EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;EQUAL TO OR GREATER THAN;;;; +22DE;EQUAL TO OR PRECEDES;Sm;0;ON;;;;;Y;;;;; +22DF;EQUAL TO OR SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +22E0;DOES NOT PRECEDE OR EQUAL;Sm;0;ON;227C 0338;;;;Y;;;;; +22E1;DOES NOT SUCCEED OR EQUAL;Sm;0;ON;227D 0338;;;;Y;;;;; +22E2;NOT SQUARE IMAGE OF OR EQUAL TO;Sm;0;ON;2291 0338;;;;Y;;;;; +22E3;NOT SQUARE ORIGINAL OF OR EQUAL TO;Sm;0;ON;2292 0338;;;;Y;;;;; +22E4;SQUARE IMAGE OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22E5;SQUARE ORIGINAL OF OR NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +22E6;LESS-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;LESS THAN BUT NOT EQUIVALENT TO;;;; +22E7;GREATER-THAN BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;GREATER THAN BUT NOT EQUIVALENT TO;;;; +22E8;PRECEDES BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +22E9;SUCCEEDS BUT NOT EQUIVALENT TO;Sm;0;ON;;;;;Y;;;;; +22EA;NOT NORMAL SUBGROUP OF;Sm;0;ON;22B2 0338;;;;Y;;;;; +22EB;DOES NOT CONTAIN AS NORMAL SUBGROUP;Sm;0;ON;22B3 0338;;;;Y;;;;; +22EC;NOT NORMAL SUBGROUP OF OR EQUAL TO;Sm;0;ON;22B4 0338;;;;Y;;;;; +22ED;DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL;Sm;0;ON;22B5 0338;;;;Y;;;;; +22EE;VERTICAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; +22EF;MIDLINE HORIZONTAL ELLIPSIS;Sm;0;ON;;;;;N;;;;; +22F0;UP RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; +22F1;DOWN RIGHT DIAGONAL ELLIPSIS;Sm;0;ON;;;;;Y;;;;; +22F2;ELEMENT OF WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F3;ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F4;SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22F5;ELEMENT OF WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +22F6;ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22F7;SMALL ELEMENT OF WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22F8;ELEMENT OF WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +22F9;ELEMENT OF WITH TWO HORIZONTAL STROKES;Sm;0;ON;;;;;Y;;;;; +22FA;CONTAINS WITH LONG HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FB;CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FC;SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +22FD;CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22FE;SMALL CONTAINS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +22FF;Z NOTATION BAG MEMBERSHIP;Sm;0;ON;;;;;Y;;;;; +2300;DIAMETER SIGN;So;0;ON;;;;;N;;;;; +2301;ELECTRIC ARROW;So;0;ON;;;;;N;;;;; +2302;HOUSE;So;0;ON;;;;;N;;;;; +2303;UP ARROWHEAD;So;0;ON;;;;;N;;;;; +2304;DOWN ARROWHEAD;So;0;ON;;;;;N;;;;; +2305;PROJECTIVE;So;0;ON;;;;;N;;;;; +2306;PERSPECTIVE;So;0;ON;;;;;N;;;;; +2307;WAVY LINE;So;0;ON;;;;;N;;;;; +2308;LEFT CEILING;Ps;0;ON;;;;;Y;;;;; +2309;RIGHT CEILING;Pe;0;ON;;;;;Y;;;;; +230A;LEFT FLOOR;Ps;0;ON;;;;;Y;;;;; +230B;RIGHT FLOOR;Pe;0;ON;;;;;Y;;;;; +230C;BOTTOM RIGHT CROP;So;0;ON;;;;;N;;;;; +230D;BOTTOM LEFT CROP;So;0;ON;;;;;N;;;;; +230E;TOP RIGHT CROP;So;0;ON;;;;;N;;;;; +230F;TOP LEFT CROP;So;0;ON;;;;;N;;;;; +2310;REVERSED NOT SIGN;So;0;ON;;;;;N;;;;; +2311;SQUARE LOZENGE;So;0;ON;;;;;N;;;;; +2312;ARC;So;0;ON;;;;;N;;;;; +2313;SEGMENT;So;0;ON;;;;;N;;;;; +2314;SECTOR;So;0;ON;;;;;N;;;;; +2315;TELEPHONE RECORDER;So;0;ON;;;;;N;;;;; +2316;POSITION INDICATOR;So;0;ON;;;;;N;;;;; +2317;VIEWDATA SQUARE;So;0;ON;;;;;N;;;;; +2318;PLACE OF INTEREST SIGN;So;0;ON;;;;;N;COMMAND KEY;;;; +2319;TURNED NOT SIGN;So;0;ON;;;;;N;;;;; +231A;WATCH;So;0;ON;;;;;N;;;;; +231B;HOURGLASS;So;0;ON;;;;;N;;;;; +231C;TOP LEFT CORNER;So;0;ON;;;;;N;;;;; +231D;TOP RIGHT CORNER;So;0;ON;;;;;N;;;;; +231E;BOTTOM LEFT CORNER;So;0;ON;;;;;N;;;;; +231F;BOTTOM RIGHT CORNER;So;0;ON;;;;;N;;;;; +2320;TOP HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2321;BOTTOM HALF INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2322;FROWN;So;0;ON;;;;;N;;;;; +2323;SMILE;So;0;ON;;;;;N;;;;; +2324;UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS;So;0;ON;;;;;N;ENTER KEY;;;; +2325;OPTION KEY;So;0;ON;;;;;N;;;;; +2326;ERASE TO THE RIGHT;So;0;ON;;;;;N;DELETE TO THE RIGHT KEY;;;; +2327;X IN A RECTANGLE BOX;So;0;ON;;;;;N;CLEAR KEY;;;; +2328;KEYBOARD;So;0;ON;;;;;N;;;;; +2329;LEFT-POINTING ANGLE BRACKET;Ps;0;ON;3008;;;;Y;BRA;;;; +232A;RIGHT-POINTING ANGLE BRACKET;Pe;0;ON;3009;;;;Y;KET;;;; +232B;ERASE TO THE LEFT;So;0;ON;;;;;N;DELETE TO THE LEFT KEY;;;; +232C;BENZENE RING;So;0;ON;;;;;N;;;;; +232D;CYLINDRICITY;So;0;ON;;;;;N;;;;; +232E;ALL AROUND-PROFILE;So;0;ON;;;;;N;;;;; +232F;SYMMETRY;So;0;ON;;;;;N;;;;; +2330;TOTAL RUNOUT;So;0;ON;;;;;N;;;;; +2331;DIMENSION ORIGIN;So;0;ON;;;;;N;;;;; +2332;CONICAL TAPER;So;0;ON;;;;;N;;;;; +2333;SLOPE;So;0;ON;;;;;N;;;;; +2334;COUNTERBORE;So;0;ON;;;;;N;;;;; +2335;COUNTERSINK;So;0;ON;;;;;N;;;;; +2336;APL FUNCTIONAL SYMBOL I-BEAM;So;0;L;;;;;N;;;;; +2337;APL FUNCTIONAL SYMBOL SQUISH QUAD;So;0;L;;;;;N;;;;; +2338;APL FUNCTIONAL SYMBOL QUAD EQUAL;So;0;L;;;;;N;;;;; +2339;APL FUNCTIONAL SYMBOL QUAD DIVIDE;So;0;L;;;;;N;;;;; +233A;APL FUNCTIONAL SYMBOL QUAD DIAMOND;So;0;L;;;;;N;;;;; +233B;APL FUNCTIONAL SYMBOL QUAD JOT;So;0;L;;;;;N;;;;; +233C;APL FUNCTIONAL SYMBOL QUAD CIRCLE;So;0;L;;;;;N;;;;; +233D;APL FUNCTIONAL SYMBOL CIRCLE STILE;So;0;L;;;;;N;;;;; +233E;APL FUNCTIONAL SYMBOL CIRCLE JOT;So;0;L;;;;;N;;;;; +233F;APL FUNCTIONAL SYMBOL SLASH BAR;So;0;L;;;;;N;;;;; +2340;APL FUNCTIONAL SYMBOL BACKSLASH BAR;So;0;L;;;;;N;;;;; +2341;APL FUNCTIONAL SYMBOL QUAD SLASH;So;0;L;;;;;N;;;;; +2342;APL FUNCTIONAL SYMBOL QUAD BACKSLASH;So;0;L;;;;;N;;;;; +2343;APL FUNCTIONAL SYMBOL QUAD LESS-THAN;So;0;L;;;;;N;;;;; +2344;APL FUNCTIONAL SYMBOL QUAD GREATER-THAN;So;0;L;;;;;N;;;;; +2345;APL FUNCTIONAL SYMBOL LEFTWARDS VANE;So;0;L;;;;;N;;;;; +2346;APL FUNCTIONAL SYMBOL RIGHTWARDS VANE;So;0;L;;;;;N;;;;; +2347;APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW;So;0;L;;;;;N;;;;; +2348;APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW;So;0;L;;;;;N;;;;; +2349;APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH;So;0;L;;;;;N;;;;; +234A;APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR;So;0;L;;;;;N;;;;; +234B;APL FUNCTIONAL SYMBOL DELTA STILE;So;0;L;;;;;N;;;;; +234C;APL FUNCTIONAL SYMBOL QUAD DOWN CARET;So;0;L;;;;;N;;;;; +234D;APL FUNCTIONAL SYMBOL QUAD DELTA;So;0;L;;;;;N;;;;; +234E;APL FUNCTIONAL SYMBOL DOWN TACK JOT;So;0;L;;;;;N;;;;; +234F;APL FUNCTIONAL SYMBOL UPWARDS VANE;So;0;L;;;;;N;;;;; +2350;APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW;So;0;L;;;;;N;;;;; +2351;APL FUNCTIONAL SYMBOL UP TACK OVERBAR;So;0;L;;;;;N;;;;; +2352;APL FUNCTIONAL SYMBOL DEL STILE;So;0;L;;;;;N;;;;; +2353;APL FUNCTIONAL SYMBOL QUAD UP CARET;So;0;L;;;;;N;;;;; +2354;APL FUNCTIONAL SYMBOL QUAD DEL;So;0;L;;;;;N;;;;; +2355;APL FUNCTIONAL SYMBOL UP TACK JOT;So;0;L;;;;;N;;;;; +2356;APL FUNCTIONAL SYMBOL DOWNWARDS VANE;So;0;L;;;;;N;;;;; +2357;APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW;So;0;L;;;;;N;;;;; +2358;APL FUNCTIONAL SYMBOL QUOTE UNDERBAR;So;0;L;;;;;N;;;;; +2359;APL FUNCTIONAL SYMBOL DELTA UNDERBAR;So;0;L;;;;;N;;;;; +235A;APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR;So;0;L;;;;;N;;;;; +235B;APL FUNCTIONAL SYMBOL JOT UNDERBAR;So;0;L;;;;;N;;;;; +235C;APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR;So;0;L;;;;;N;;;;; +235D;APL FUNCTIONAL SYMBOL UP SHOE JOT;So;0;L;;;;;N;;;;; +235E;APL FUNCTIONAL SYMBOL QUOTE QUAD;So;0;L;;;;;N;;;;; +235F;APL FUNCTIONAL SYMBOL CIRCLE STAR;So;0;L;;;;;N;;;;; +2360;APL FUNCTIONAL SYMBOL QUAD COLON;So;0;L;;;;;N;;;;; +2361;APL FUNCTIONAL SYMBOL UP TACK DIAERESIS;So;0;L;;;;;N;;;;; +2362;APL FUNCTIONAL SYMBOL DEL DIAERESIS;So;0;L;;;;;N;;;;; +2363;APL FUNCTIONAL SYMBOL STAR DIAERESIS;So;0;L;;;;;N;;;;; +2364;APL FUNCTIONAL SYMBOL JOT DIAERESIS;So;0;L;;;;;N;;;;; +2365;APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS;So;0;L;;;;;N;;;;; +2366;APL FUNCTIONAL SYMBOL DOWN SHOE STILE;So;0;L;;;;;N;;;;; +2367;APL FUNCTIONAL SYMBOL LEFT SHOE STILE;So;0;L;;;;;N;;;;; +2368;APL FUNCTIONAL SYMBOL TILDE DIAERESIS;So;0;L;;;;;N;;;;; +2369;APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS;So;0;L;;;;;N;;;;; +236A;APL FUNCTIONAL SYMBOL COMMA BAR;So;0;L;;;;;N;;;;; +236B;APL FUNCTIONAL SYMBOL DEL TILDE;So;0;L;;;;;N;;;;; +236C;APL FUNCTIONAL SYMBOL ZILDE;So;0;L;;;;;N;;;;; +236D;APL FUNCTIONAL SYMBOL STILE TILDE;So;0;L;;;;;N;;;;; +236E;APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR;So;0;L;;;;;N;;;;; +236F;APL FUNCTIONAL SYMBOL QUAD NOT EQUAL;So;0;L;;;;;N;;;;; +2370;APL FUNCTIONAL SYMBOL QUAD QUESTION;So;0;L;;;;;N;;;;; +2371;APL FUNCTIONAL SYMBOL DOWN CARET TILDE;So;0;L;;;;;N;;;;; +2372;APL FUNCTIONAL SYMBOL UP CARET TILDE;So;0;L;;;;;N;;;;; +2373;APL FUNCTIONAL SYMBOL IOTA;So;0;L;;;;;N;;;;; +2374;APL FUNCTIONAL SYMBOL RHO;So;0;L;;;;;N;;;;; +2375;APL FUNCTIONAL SYMBOL OMEGA;So;0;L;;;;;N;;;;; +2376;APL FUNCTIONAL SYMBOL ALPHA UNDERBAR;So;0;L;;;;;N;;;;; +2377;APL FUNCTIONAL SYMBOL EPSILON UNDERBAR;So;0;L;;;;;N;;;;; +2378;APL FUNCTIONAL SYMBOL IOTA UNDERBAR;So;0;L;;;;;N;;;;; +2379;APL FUNCTIONAL SYMBOL OMEGA UNDERBAR;So;0;L;;;;;N;;;;; +237A;APL FUNCTIONAL SYMBOL ALPHA;So;0;L;;;;;N;;;;; +237B;NOT CHECK MARK;So;0;ON;;;;;N;;;;; +237C;RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW;Sm;0;ON;;;;;N;;;;; +237D;SHOULDERED OPEN BOX;So;0;ON;;;;;N;;;;; +237E;BELL SYMBOL;So;0;ON;;;;;N;;;;; +237F;VERTICAL LINE WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; +2380;INSERTION SYMBOL;So;0;ON;;;;;N;;;;; +2381;CONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; +2382;DISCONTINUOUS UNDERLINE SYMBOL;So;0;ON;;;;;N;;;;; +2383;EMPHASIS SYMBOL;So;0;ON;;;;;N;;;;; +2384;COMPOSITION SYMBOL;So;0;ON;;;;;N;;;;; +2385;WHITE SQUARE WITH CENTRE VERTICAL LINE;So;0;ON;;;;;N;;;;; +2386;ENTER SYMBOL;So;0;ON;;;;;N;;;;; +2387;ALTERNATIVE KEY SYMBOL;So;0;ON;;;;;N;;;;; +2388;HELM SYMBOL;So;0;ON;;;;;N;;;;; +2389;CIRCLED HORIZONTAL BAR WITH NOTCH;So;0;ON;;;;;N;;;;; +238A;CIRCLED TRIANGLE DOWN;So;0;ON;;;;;N;;;;; +238B;BROKEN CIRCLE WITH NORTHWEST ARROW;So;0;ON;;;;;N;;;;; +238C;UNDO SYMBOL;So;0;ON;;;;;N;;;;; +238D;MONOSTABLE SYMBOL;So;0;ON;;;;;N;;;;; +238E;HYSTERESIS SYMBOL;So;0;ON;;;;;N;;;;; +238F;OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL;So;0;ON;;;;;N;;;;; +2390;OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL;So;0;ON;;;;;N;;;;; +2391;PASSIVE-PULL-DOWN-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; +2392;PASSIVE-PULL-UP-OUTPUT SYMBOL;So;0;ON;;;;;N;;;;; +2393;DIRECT CURRENT SYMBOL FORM TWO;So;0;ON;;;;;N;;;;; +2394;SOFTWARE-FUNCTION SYMBOL;So;0;ON;;;;;N;;;;; +2395;APL FUNCTIONAL SYMBOL QUAD;So;0;L;;;;;N;;;;; +2396;DECIMAL SEPARATOR KEY SYMBOL;So;0;ON;;;;;N;;;;; +2397;PREVIOUS PAGE;So;0;ON;;;;;N;;;;; +2398;NEXT PAGE;So;0;ON;;;;;N;;;;; +2399;PRINT SCREEN SYMBOL;So;0;ON;;;;;N;;;;; +239A;CLEAR SCREEN SYMBOL;So;0;ON;;;;;N;;;;; +239B;LEFT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; +239C;LEFT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; +239D;LEFT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; +239E;RIGHT PARENTHESIS UPPER HOOK;Sm;0;ON;;;;;N;;;;; +239F;RIGHT PARENTHESIS EXTENSION;Sm;0;ON;;;;;N;;;;; +23A0;RIGHT PARENTHESIS LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23A1;LEFT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; +23A2;LEFT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23A3;LEFT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; +23A4;RIGHT SQUARE BRACKET UPPER CORNER;Sm;0;ON;;;;;N;;;;; +23A5;RIGHT SQUARE BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23A6;RIGHT SQUARE BRACKET LOWER CORNER;Sm;0;ON;;;;;N;;;;; +23A7;LEFT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; +23A8;LEFT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; +23A9;LEFT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23AA;CURLY BRACKET EXTENSION;Sm;0;ON;;;;;N;;;;; +23AB;RIGHT CURLY BRACKET UPPER HOOK;Sm;0;ON;;;;;N;;;;; +23AC;RIGHT CURLY BRACKET MIDDLE PIECE;Sm;0;ON;;;;;N;;;;; +23AD;RIGHT CURLY BRACKET LOWER HOOK;Sm;0;ON;;;;;N;;;;; +23AE;INTEGRAL EXTENSION;Sm;0;ON;;;;;N;;;;; +23AF;HORIZONTAL LINE EXTENSION;Sm;0;ON;;;;;N;;;;; +23B0;UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; +23B1;UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION;Sm;0;ON;;;;;N;;;;; +23B2;SUMMATION TOP;Sm;0;ON;;;;;N;;;;; +23B3;SUMMATION BOTTOM;Sm;0;ON;;;;;N;;;;; +23B4;TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B5;BOTTOM SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B6;BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET;So;0;ON;;;;;N;;;;; +23B7;RADICAL SYMBOL BOTTOM;So;0;ON;;;;;N;;;;; +23B8;LEFT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; +23B9;RIGHT VERTICAL BOX LINE;So;0;ON;;;;;N;;;;; +23BA;HORIZONTAL SCAN LINE-1;So;0;ON;;;;;N;;;;; +23BB;HORIZONTAL SCAN LINE-3;So;0;ON;;;;;N;;;;; +23BC;HORIZONTAL SCAN LINE-7;So;0;ON;;;;;N;;;;; +23BD;HORIZONTAL SCAN LINE-9;So;0;ON;;;;;N;;;;; +23BE;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; +23BF;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; +23C0;DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C1;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C2;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE;So;0;ON;;;;;N;;;;; +23C3;DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C4;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C5;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE;So;0;ON;;;;;N;;;;; +23C6;DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE;So;0;ON;;;;;N;;;;; +23C7;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; +23C8;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE;So;0;ON;;;;;N;;;;; +23C9;DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;;;;; +23CA;DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;;;;; +23CB;DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; +23CC;DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; +23CD;SQUARE FOOT;So;0;ON;;;;;N;;;;; +23CE;RETURN SYMBOL;So;0;ON;;;;;N;;;;; +23CF;EJECT SYMBOL;So;0;ON;;;;;N;;;;; +23D0;VERTICAL LINE EXTENSION;So;0;ON;;;;;N;;;;; +23D1;METRICAL BREVE;So;0;ON;;;;;N;;;;; +23D2;METRICAL LONG OVER SHORT;So;0;ON;;;;;N;;;;; +23D3;METRICAL SHORT OVER LONG;So;0;ON;;;;;N;;;;; +23D4;METRICAL LONG OVER TWO SHORTS;So;0;ON;;;;;N;;;;; +23D5;METRICAL TWO SHORTS OVER LONG;So;0;ON;;;;;N;;;;; +23D6;METRICAL TWO SHORTS JOINED;So;0;ON;;;;;N;;;;; +23D7;METRICAL TRISEME;So;0;ON;;;;;N;;;;; +23D8;METRICAL TETRASEME;So;0;ON;;;;;N;;;;; +23D9;METRICAL PENTASEME;So;0;ON;;;;;N;;;;; +23DA;EARTH GROUND;So;0;ON;;;;;N;;;;; +23DB;FUSE;So;0;ON;;;;;N;;;;; +23DC;TOP PARENTHESIS;Sm;0;ON;;;;;N;;;;; +23DD;BOTTOM PARENTHESIS;Sm;0;ON;;;;;N;;;;; +23DE;TOP CURLY BRACKET;Sm;0;ON;;;;;N;;;;; +23DF;BOTTOM CURLY BRACKET;Sm;0;ON;;;;;N;;;;; +23E0;TOP TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; +23E1;BOTTOM TORTOISE SHELL BRACKET;Sm;0;ON;;;;;N;;;;; +23E2;WHITE TRAPEZIUM;So;0;ON;;;;;N;;;;; +23E3;BENZENE RING WITH CIRCLE;So;0;ON;;;;;N;;;;; +23E4;STRAIGHTNESS;So;0;ON;;;;;N;;;;; +23E5;FLATNESS;So;0;ON;;;;;N;;;;; +23E6;AC CURRENT;So;0;ON;;;;;N;;;;; +23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; +23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; +23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; +23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;; +23F1;STOPWATCH;So;0;ON;;;;;N;;;;; +23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;; +23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;; +23F4;BLACK MEDIUM LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F5;BLACK MEDIUM RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F6;BLACK MEDIUM UP-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F7;BLACK MEDIUM DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +23F8;DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; +23F9;BLACK SQUARE FOR STOP;So;0;ON;;;;;N;;;;; +23FA;BLACK CIRCLE FOR RECORD;So;0;ON;;;;;N;;;;; +23FB;POWER SYMBOL;So;0;ON;;;;;N;;;;; +23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;; +23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;; +23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;; +23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;; +2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; +2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; +2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; +2403;SYMBOL FOR END OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR END OF TEXT;;;; +2404;SYMBOL FOR END OF TRANSMISSION;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION;;;; +2405;SYMBOL FOR ENQUIRY;So;0;ON;;;;;N;GRAPHIC FOR ENQUIRY;;;; +2406;SYMBOL FOR ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR ACKNOWLEDGE;;;; +2407;SYMBOL FOR BELL;So;0;ON;;;;;N;GRAPHIC FOR BELL;;;; +2408;SYMBOL FOR BACKSPACE;So;0;ON;;;;;N;GRAPHIC FOR BACKSPACE;;;; +2409;SYMBOL FOR HORIZONTAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR HORIZONTAL TABULATION;;;; +240A;SYMBOL FOR LINE FEED;So;0;ON;;;;;N;GRAPHIC FOR LINE FEED;;;; +240B;SYMBOL FOR VERTICAL TABULATION;So;0;ON;;;;;N;GRAPHIC FOR VERTICAL TABULATION;;;; +240C;SYMBOL FOR FORM FEED;So;0;ON;;;;;N;GRAPHIC FOR FORM FEED;;;; +240D;SYMBOL FOR CARRIAGE RETURN;So;0;ON;;;;;N;GRAPHIC FOR CARRIAGE RETURN;;;; +240E;SYMBOL FOR SHIFT OUT;So;0;ON;;;;;N;GRAPHIC FOR SHIFT OUT;;;; +240F;SYMBOL FOR SHIFT IN;So;0;ON;;;;;N;GRAPHIC FOR SHIFT IN;;;; +2410;SYMBOL FOR DATA LINK ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR DATA LINK ESCAPE;;;; +2411;SYMBOL FOR DEVICE CONTROL ONE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL ONE;;;; +2412;SYMBOL FOR DEVICE CONTROL TWO;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL TWO;;;; +2413;SYMBOL FOR DEVICE CONTROL THREE;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL THREE;;;; +2414;SYMBOL FOR DEVICE CONTROL FOUR;So;0;ON;;;;;N;GRAPHIC FOR DEVICE CONTROL FOUR;;;; +2415;SYMBOL FOR NEGATIVE ACKNOWLEDGE;So;0;ON;;;;;N;GRAPHIC FOR NEGATIVE ACKNOWLEDGE;;;; +2416;SYMBOL FOR SYNCHRONOUS IDLE;So;0;ON;;;;;N;GRAPHIC FOR SYNCHRONOUS IDLE;;;; +2417;SYMBOL FOR END OF TRANSMISSION BLOCK;So;0;ON;;;;;N;GRAPHIC FOR END OF TRANSMISSION BLOCK;;;; +2418;SYMBOL FOR CANCEL;So;0;ON;;;;;N;GRAPHIC FOR CANCEL;;;; +2419;SYMBOL FOR END OF MEDIUM;So;0;ON;;;;;N;GRAPHIC FOR END OF MEDIUM;;;; +241A;SYMBOL FOR SUBSTITUTE;So;0;ON;;;;;N;GRAPHIC FOR SUBSTITUTE;;;; +241B;SYMBOL FOR ESCAPE;So;0;ON;;;;;N;GRAPHIC FOR ESCAPE;;;; +241C;SYMBOL FOR FILE SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR FILE SEPARATOR;;;; +241D;SYMBOL FOR GROUP SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR GROUP SEPARATOR;;;; +241E;SYMBOL FOR RECORD SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR RECORD SEPARATOR;;;; +241F;SYMBOL FOR UNIT SEPARATOR;So;0;ON;;;;;N;GRAPHIC FOR UNIT SEPARATOR;;;; +2420;SYMBOL FOR SPACE;So;0;ON;;;;;N;GRAPHIC FOR SPACE;;;; +2421;SYMBOL FOR DELETE;So;0;ON;;;;;N;GRAPHIC FOR DELETE;;;; +2422;BLANK SYMBOL;So;0;ON;;;;;N;BLANK;;;; +2423;OPEN BOX;So;0;ON;;;;;N;;;;; +2424;SYMBOL FOR NEWLINE;So;0;ON;;;;;N;GRAPHIC FOR NEWLINE;;;; +2425;SYMBOL FOR DELETE FORM TWO;So;0;ON;;;;;N;;;;; +2426;SYMBOL FOR SUBSTITUTE FORM TWO;So;0;ON;;;;;N;;;;; +2427;SYMBOL FOR DELETE SQUARE CHECKER BOARD FORM;So;0;ON;;;;;N;;;;; +2428;SYMBOL FOR DELETE RECTANGULAR CHECKER BOARD FORM;So;0;ON;;;;;N;;;;; +2429;SYMBOL FOR DELETE MEDIUM SHADE FORM;So;0;ON;;;;;N;;;;; +2440;OCR HOOK;So;0;ON;;;;;N;;;;; +2441;OCR CHAIR;So;0;ON;;;;;N;;;;; +2442;OCR FORK;So;0;ON;;;;;N;;;;; +2443;OCR INVERTED FORK;So;0;ON;;;;;N;;;;; +2444;OCR BELT BUCKLE;So;0;ON;;;;;N;;;;; +2445;OCR BOW TIE;So;0;ON;;;;;N;;;;; +2446;OCR BRANCH BANK IDENTIFICATION;So;0;ON;;;;;N;;;;; +2447;OCR AMOUNT OF CHECK;So;0;ON;;;;;N;;;;; +2448;OCR DASH;So;0;ON;;;;;N;;;;; +2449;OCR CUSTOMER ACCOUNT NUMBER;So;0;ON;;;;;N;;;;; +244A;OCR DOUBLE BACKSLASH;So;0;ON;;;;;N;;;;; +2460;CIRCLED DIGIT ONE;No;0;ON; 0031;;1;1;N;;;;; +2461;CIRCLED DIGIT TWO;No;0;ON; 0032;;2;2;N;;;;; +2462;CIRCLED DIGIT THREE;No;0;ON; 0033;;3;3;N;;;;; +2463;CIRCLED DIGIT FOUR;No;0;ON; 0034;;4;4;N;;;;; +2464;CIRCLED DIGIT FIVE;No;0;ON; 0035;;5;5;N;;;;; +2465;CIRCLED DIGIT SIX;No;0;ON; 0036;;6;6;N;;;;; +2466;CIRCLED DIGIT SEVEN;No;0;ON; 0037;;7;7;N;;;;; +2467;CIRCLED DIGIT EIGHT;No;0;ON; 0038;;8;8;N;;;;; +2468;CIRCLED DIGIT NINE;No;0;ON; 0039;;9;9;N;;;;; +2469;CIRCLED NUMBER TEN;No;0;ON; 0031 0030;;;10;N;;;;; +246A;CIRCLED NUMBER ELEVEN;No;0;ON; 0031 0031;;;11;N;;;;; +246B;CIRCLED NUMBER TWELVE;No;0;ON; 0031 0032;;;12;N;;;;; +246C;CIRCLED NUMBER THIRTEEN;No;0;ON; 0031 0033;;;13;N;;;;; +246D;CIRCLED NUMBER FOURTEEN;No;0;ON; 0031 0034;;;14;N;;;;; +246E;CIRCLED NUMBER FIFTEEN;No;0;ON; 0031 0035;;;15;N;;;;; +246F;CIRCLED NUMBER SIXTEEN;No;0;ON; 0031 0036;;;16;N;;;;; +2470;CIRCLED NUMBER SEVENTEEN;No;0;ON; 0031 0037;;;17;N;;;;; +2471;CIRCLED NUMBER EIGHTEEN;No;0;ON; 0031 0038;;;18;N;;;;; +2472;CIRCLED NUMBER NINETEEN;No;0;ON; 0031 0039;;;19;N;;;;; +2473;CIRCLED NUMBER TWENTY;No;0;ON; 0032 0030;;;20;N;;;;; +2474;PARENTHESIZED DIGIT ONE;No;0;ON; 0028 0031 0029;;1;1;N;;;;; +2475;PARENTHESIZED DIGIT TWO;No;0;ON; 0028 0032 0029;;2;2;N;;;;; +2476;PARENTHESIZED DIGIT THREE;No;0;ON; 0028 0033 0029;;3;3;N;;;;; +2477;PARENTHESIZED DIGIT FOUR;No;0;ON; 0028 0034 0029;;4;4;N;;;;; +2478;PARENTHESIZED DIGIT FIVE;No;0;ON; 0028 0035 0029;;5;5;N;;;;; +2479;PARENTHESIZED DIGIT SIX;No;0;ON; 0028 0036 0029;;6;6;N;;;;; +247A;PARENTHESIZED DIGIT SEVEN;No;0;ON; 0028 0037 0029;;7;7;N;;;;; +247B;PARENTHESIZED DIGIT EIGHT;No;0;ON; 0028 0038 0029;;8;8;N;;;;; +247C;PARENTHESIZED DIGIT NINE;No;0;ON; 0028 0039 0029;;9;9;N;;;;; +247D;PARENTHESIZED NUMBER TEN;No;0;ON; 0028 0031 0030 0029;;;10;N;;;;; +247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON; 0028 0031 0031 0029;;;11;N;;;;; +247F;PARENTHESIZED NUMBER TWELVE;No;0;ON; 0028 0031 0032 0029;;;12;N;;;;; +2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON; 0028 0031 0033 0029;;;13;N;;;;; +2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON; 0028 0031 0034 0029;;;14;N;;;;; +2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON; 0028 0031 0035 0029;;;15;N;;;;; +2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON; 0028 0031 0036 0029;;;16;N;;;;; +2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON; 0028 0031 0037 0029;;;17;N;;;;; +2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON; 0028 0031 0038 0029;;;18;N;;;;; +2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON; 0028 0031 0039 0029;;;19;N;;;;; +2487;PARENTHESIZED NUMBER TWENTY;No;0;ON; 0028 0032 0030 0029;;;20;N;;;;; +2488;DIGIT ONE FULL STOP;No;0;EN; 0031 002E;;1;1;N;DIGIT ONE PERIOD;;;; +2489;DIGIT TWO FULL STOP;No;0;EN; 0032 002E;;2;2;N;DIGIT TWO PERIOD;;;; +248A;DIGIT THREE FULL STOP;No;0;EN; 0033 002E;;3;3;N;DIGIT THREE PERIOD;;;; +248B;DIGIT FOUR FULL STOP;No;0;EN; 0034 002E;;4;4;N;DIGIT FOUR PERIOD;;;; +248C;DIGIT FIVE FULL STOP;No;0;EN; 0035 002E;;5;5;N;DIGIT FIVE PERIOD;;;; +248D;DIGIT SIX FULL STOP;No;0;EN; 0036 002E;;6;6;N;DIGIT SIX PERIOD;;;; +248E;DIGIT SEVEN FULL STOP;No;0;EN; 0037 002E;;7;7;N;DIGIT SEVEN PERIOD;;;; +248F;DIGIT EIGHT FULL STOP;No;0;EN; 0038 002E;;8;8;N;DIGIT EIGHT PERIOD;;;; +2490;DIGIT NINE FULL STOP;No;0;EN; 0039 002E;;9;9;N;DIGIT NINE PERIOD;;;; +2491;NUMBER TEN FULL STOP;No;0;EN; 0031 0030 002E;;;10;N;NUMBER TEN PERIOD;;;; +2492;NUMBER ELEVEN FULL STOP;No;0;EN; 0031 0031 002E;;;11;N;NUMBER ELEVEN PERIOD;;;; +2493;NUMBER TWELVE FULL STOP;No;0;EN; 0031 0032 002E;;;12;N;NUMBER TWELVE PERIOD;;;; +2494;NUMBER THIRTEEN FULL STOP;No;0;EN; 0031 0033 002E;;;13;N;NUMBER THIRTEEN PERIOD;;;; +2495;NUMBER FOURTEEN FULL STOP;No;0;EN; 0031 0034 002E;;;14;N;NUMBER FOURTEEN PERIOD;;;; +2496;NUMBER FIFTEEN FULL STOP;No;0;EN; 0031 0035 002E;;;15;N;NUMBER FIFTEEN PERIOD;;;; +2497;NUMBER SIXTEEN FULL STOP;No;0;EN; 0031 0036 002E;;;16;N;NUMBER SIXTEEN PERIOD;;;; +2498;NUMBER SEVENTEEN FULL STOP;No;0;EN; 0031 0037 002E;;;17;N;NUMBER SEVENTEEN PERIOD;;;; +2499;NUMBER EIGHTEEN FULL STOP;No;0;EN; 0031 0038 002E;;;18;N;NUMBER EIGHTEEN PERIOD;;;; +249A;NUMBER NINETEEN FULL STOP;No;0;EN; 0031 0039 002E;;;19;N;NUMBER NINETEEN PERIOD;;;; +249B;NUMBER TWENTY FULL STOP;No;0;EN; 0032 0030 002E;;;20;N;NUMBER TWENTY PERIOD;;;; +249C;PARENTHESIZED LATIN SMALL LETTER A;So;0;L; 0028 0061 0029;;;;N;;;;; +249D;PARENTHESIZED LATIN SMALL LETTER B;So;0;L; 0028 0062 0029;;;;N;;;;; +249E;PARENTHESIZED LATIN SMALL LETTER C;So;0;L; 0028 0063 0029;;;;N;;;;; +249F;PARENTHESIZED LATIN SMALL LETTER D;So;0;L; 0028 0064 0029;;;;N;;;;; +24A0;PARENTHESIZED LATIN SMALL LETTER E;So;0;L; 0028 0065 0029;;;;N;;;;; +24A1;PARENTHESIZED LATIN SMALL LETTER F;So;0;L; 0028 0066 0029;;;;N;;;;; +24A2;PARENTHESIZED LATIN SMALL LETTER G;So;0;L; 0028 0067 0029;;;;N;;;;; +24A3;PARENTHESIZED LATIN SMALL LETTER H;So;0;L; 0028 0068 0029;;;;N;;;;; +24A4;PARENTHESIZED LATIN SMALL LETTER I;So;0;L; 0028 0069 0029;;;;N;;;;; +24A5;PARENTHESIZED LATIN SMALL LETTER J;So;0;L; 0028 006A 0029;;;;N;;;;; +24A6;PARENTHESIZED LATIN SMALL LETTER K;So;0;L; 0028 006B 0029;;;;N;;;;; +24A7;PARENTHESIZED LATIN SMALL LETTER L;So;0;L; 0028 006C 0029;;;;N;;;;; +24A8;PARENTHESIZED LATIN SMALL LETTER M;So;0;L; 0028 006D 0029;;;;N;;;;; +24A9;PARENTHESIZED LATIN SMALL LETTER N;So;0;L; 0028 006E 0029;;;;N;;;;; +24AA;PARENTHESIZED LATIN SMALL LETTER O;So;0;L; 0028 006F 0029;;;;N;;;;; +24AB;PARENTHESIZED LATIN SMALL LETTER P;So;0;L; 0028 0070 0029;;;;N;;;;; +24AC;PARENTHESIZED LATIN SMALL LETTER Q;So;0;L; 0028 0071 0029;;;;N;;;;; +24AD;PARENTHESIZED LATIN SMALL LETTER R;So;0;L; 0028 0072 0029;;;;N;;;;; +24AE;PARENTHESIZED LATIN SMALL LETTER S;So;0;L; 0028 0073 0029;;;;N;;;;; +24AF;PARENTHESIZED LATIN SMALL LETTER T;So;0;L; 0028 0074 0029;;;;N;;;;; +24B0;PARENTHESIZED LATIN SMALL LETTER U;So;0;L; 0028 0075 0029;;;;N;;;;; +24B1;PARENTHESIZED LATIN SMALL LETTER V;So;0;L; 0028 0076 0029;;;;N;;;;; +24B2;PARENTHESIZED LATIN SMALL LETTER W;So;0;L; 0028 0077 0029;;;;N;;;;; +24B3;PARENTHESIZED LATIN SMALL LETTER X;So;0;L; 0028 0078 0029;;;;N;;;;; +24B4;PARENTHESIZED LATIN SMALL LETTER Y;So;0;L; 0028 0079 0029;;;;N;;;;; +24B5;PARENTHESIZED LATIN SMALL LETTER Z;So;0;L; 0028 007A 0029;;;;N;;;;; +24B6;CIRCLED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;24D0; +24B7;CIRCLED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;24D1; +24B8;CIRCLED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;24D2; +24B9;CIRCLED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;24D3; +24BA;CIRCLED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;24D4; +24BB;CIRCLED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;24D5; +24BC;CIRCLED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;24D6; +24BD;CIRCLED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;24D7; +24BE;CIRCLED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;24D8; +24BF;CIRCLED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;24D9; +24C0;CIRCLED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;24DA; +24C1;CIRCLED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;24DB; +24C2;CIRCLED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;24DC; +24C3;CIRCLED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;24DD; +24C4;CIRCLED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;24DE; +24C5;CIRCLED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;24DF; +24C6;CIRCLED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;24E0; +24C7;CIRCLED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;24E1; +24C8;CIRCLED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;24E2; +24C9;CIRCLED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;24E3; +24CA;CIRCLED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;24E4; +24CB;CIRCLED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;24E5; +24CC;CIRCLED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;24E6; +24CD;CIRCLED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;24E7; +24CE;CIRCLED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;24E8; +24CF;CIRCLED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;24E9; +24D0;CIRCLED LATIN SMALL LETTER A;So;0;L; 0061;;;;N;;;24B6;;24B6 +24D1;CIRCLED LATIN SMALL LETTER B;So;0;L; 0062;;;;N;;;24B7;;24B7 +24D2;CIRCLED LATIN SMALL LETTER C;So;0;L; 0063;;;;N;;;24B8;;24B8 +24D3;CIRCLED LATIN SMALL LETTER D;So;0;L; 0064;;;;N;;;24B9;;24B9 +24D4;CIRCLED LATIN SMALL LETTER E;So;0;L; 0065;;;;N;;;24BA;;24BA +24D5;CIRCLED LATIN SMALL LETTER F;So;0;L; 0066;;;;N;;;24BB;;24BB +24D6;CIRCLED LATIN SMALL LETTER G;So;0;L; 0067;;;;N;;;24BC;;24BC +24D7;CIRCLED LATIN SMALL LETTER H;So;0;L; 0068;;;;N;;;24BD;;24BD +24D8;CIRCLED LATIN SMALL LETTER I;So;0;L; 0069;;;;N;;;24BE;;24BE +24D9;CIRCLED LATIN SMALL LETTER J;So;0;L; 006A;;;;N;;;24BF;;24BF +24DA;CIRCLED LATIN SMALL LETTER K;So;0;L; 006B;;;;N;;;24C0;;24C0 +24DB;CIRCLED LATIN SMALL LETTER L;So;0;L; 006C;;;;N;;;24C1;;24C1 +24DC;CIRCLED LATIN SMALL LETTER M;So;0;L; 006D;;;;N;;;24C2;;24C2 +24DD;CIRCLED LATIN SMALL LETTER N;So;0;L; 006E;;;;N;;;24C3;;24C3 +24DE;CIRCLED LATIN SMALL LETTER O;So;0;L; 006F;;;;N;;;24C4;;24C4 +24DF;CIRCLED LATIN SMALL LETTER P;So;0;L; 0070;;;;N;;;24C5;;24C5 +24E0;CIRCLED LATIN SMALL LETTER Q;So;0;L; 0071;;;;N;;;24C6;;24C6 +24E1;CIRCLED LATIN SMALL LETTER R;So;0;L; 0072;;;;N;;;24C7;;24C7 +24E2;CIRCLED LATIN SMALL LETTER S;So;0;L; 0073;;;;N;;;24C8;;24C8 +24E3;CIRCLED LATIN SMALL LETTER T;So;0;L; 0074;;;;N;;;24C9;;24C9 +24E4;CIRCLED LATIN SMALL LETTER U;So;0;L; 0075;;;;N;;;24CA;;24CA +24E5;CIRCLED LATIN SMALL LETTER V;So;0;L; 0076;;;;N;;;24CB;;24CB +24E6;CIRCLED LATIN SMALL LETTER W;So;0;L; 0077;;;;N;;;24CC;;24CC +24E7;CIRCLED LATIN SMALL LETTER X;So;0;L; 0078;;;;N;;;24CD;;24CD +24E8;CIRCLED LATIN SMALL LETTER Y;So;0;L; 0079;;;;N;;;24CE;;24CE +24E9;CIRCLED LATIN SMALL LETTER Z;So;0;L; 007A;;;;N;;;24CF;;24CF +24EA;CIRCLED DIGIT ZERO;No;0;ON; 0030;;0;0;N;;;;; +24EB;NEGATIVE CIRCLED NUMBER ELEVEN;No;0;ON;;;;11;N;;;;; +24EC;NEGATIVE CIRCLED NUMBER TWELVE;No;0;ON;;;;12;N;;;;; +24ED;NEGATIVE CIRCLED NUMBER THIRTEEN;No;0;ON;;;;13;N;;;;; +24EE;NEGATIVE CIRCLED NUMBER FOURTEEN;No;0;ON;;;;14;N;;;;; +24EF;NEGATIVE CIRCLED NUMBER FIFTEEN;No;0;ON;;;;15;N;;;;; +24F0;NEGATIVE CIRCLED NUMBER SIXTEEN;No;0;ON;;;;16;N;;;;; +24F1;NEGATIVE CIRCLED NUMBER SEVENTEEN;No;0;ON;;;;17;N;;;;; +24F2;NEGATIVE CIRCLED NUMBER EIGHTEEN;No;0;ON;;;;18;N;;;;; +24F3;NEGATIVE CIRCLED NUMBER NINETEEN;No;0;ON;;;;19;N;;;;; +24F4;NEGATIVE CIRCLED NUMBER TWENTY;No;0;ON;;;;20;N;;;;; +24F5;DOUBLE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;;;;; +24F6;DOUBLE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;;;;; +24F7;DOUBLE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;;;;; +24F8;DOUBLE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;;;;; +24F9;DOUBLE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;;;;; +24FA;DOUBLE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;;;;; +24FB;DOUBLE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;;;;; +24FC;DOUBLE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;;;;; +24FD;DOUBLE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;;;;; +24FE;DOUBLE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;;;;; +24FF;NEGATIVE CIRCLED DIGIT ZERO;No;0;ON;;;0;0;N;;;;; +2500;BOX DRAWINGS LIGHT HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT HORIZONTAL;;;; +2501;BOX DRAWINGS HEAVY HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY HORIZONTAL;;;; +2502;BOX DRAWINGS LIGHT VERTICAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL;;;; +2503;BOX DRAWINGS HEAVY VERTICAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL;;;; +2504;BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH HORIZONTAL;;;; +2505;BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH HORIZONTAL;;;; +2506;BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT TRIPLE DASH VERTICAL;;;; +2507;BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY TRIPLE DASH VERTICAL;;;; +2508;BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH HORIZONTAL;;;; +2509;BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH HORIZONTAL;;;; +250A;BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT QUADRUPLE DASH VERTICAL;;;; +250B;BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY QUADRUPLE DASH VERTICAL;;;; +250C;BOX DRAWINGS LIGHT DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND RIGHT;;;; +250D;BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT HEAVY;;;; +250E;BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT LIGHT;;;; +250F;BOX DRAWINGS HEAVY DOWN AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND RIGHT;;;; +2510;BOX DRAWINGS LIGHT DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT DOWN AND LEFT;;;; +2511;BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT HEAVY;;;; +2512;BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT LIGHT;;;; +2513;BOX DRAWINGS HEAVY DOWN AND LEFT;So;0;ON;;;;;N;FORMS HEAVY DOWN AND LEFT;;;; +2514;BOX DRAWINGS LIGHT UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT UP AND RIGHT;;;; +2515;BOX DRAWINGS UP LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT HEAVY;;;; +2516;BOX DRAWINGS UP HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT LIGHT;;;; +2517;BOX DRAWINGS HEAVY UP AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY UP AND RIGHT;;;; +2518;BOX DRAWINGS LIGHT UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT UP AND LEFT;;;; +2519;BOX DRAWINGS UP LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT HEAVY;;;; +251A;BOX DRAWINGS UP HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT LIGHT;;;; +251B;BOX DRAWINGS HEAVY UP AND LEFT;So;0;ON;;;;;N;FORMS HEAVY UP AND LEFT;;;; +251C;BOX DRAWINGS LIGHT VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND RIGHT;;;; +251D;BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND RIGHT HEAVY;;;; +251E;BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND RIGHT DOWN LIGHT;;;; +251F;BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND RIGHT UP LIGHT;;;; +2520;BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND RIGHT LIGHT;;;; +2521;BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND RIGHT UP HEAVY;;;; +2522;BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND RIGHT DOWN HEAVY;;;; +2523;BOX DRAWINGS HEAVY VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND RIGHT;;;; +2524;BOX DRAWINGS LIGHT VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND LEFT;;;; +2525;BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND LEFT HEAVY;;;; +2526;BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND LEFT DOWN LIGHT;;;; +2527;BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND LEFT UP LIGHT;;;; +2528;BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND LEFT LIGHT;;;; +2529;BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND LEFT UP HEAVY;;;; +252A;BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND LEFT DOWN HEAVY;;;; +252B;BOX DRAWINGS HEAVY VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND LEFT;;;; +252C;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOWN AND HORIZONTAL;;;; +252D;BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT DOWN LIGHT;;;; +252E;BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT DOWN LIGHT;;;; +252F;BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND HORIZONTAL HEAVY;;;; +2530;BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND HORIZONTAL LIGHT;;;; +2531;BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT DOWN HEAVY;;;; +2532;BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT DOWN HEAVY;;;; +2533;BOX DRAWINGS HEAVY DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOWN AND HORIZONTAL;;;; +2534;BOX DRAWINGS LIGHT UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT UP AND HORIZONTAL;;;; +2535;BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT UP LIGHT;;;; +2536;BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT UP LIGHT;;;; +2537;BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND HORIZONTAL HEAVY;;;; +2538;BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND HORIZONTAL LIGHT;;;; +2539;BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT UP HEAVY;;;; +253A;BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT UP HEAVY;;;; +253B;BOX DRAWINGS HEAVY UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY UP AND HORIZONTAL;;;; +253C;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT VERTICAL AND HORIZONTAL;;;; +253D;BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT;;;; +253E;BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT;So;0;ON;;;;;N;FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT;;;; +253F;BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY;;;; +2540;BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT;;;; +2541;BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT;;;; +2542;BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT;So;0;ON;;;;;N;FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT;;;; +2543;BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT;So;0;ON;;;;;N;FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT;;;; +2544;BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT;So;0;ON;;;;;N;FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT;;;; +2545;BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT;So;0;ON;;;;;N;FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT;;;; +2546;BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT;So;0;ON;;;;;N;FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT;;;; +2547;BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY;;;; +2548;BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY;So;0;ON;;;;;N;FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY;;;; +2549;BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY;;;; +254A;BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY;So;0;ON;;;;;N;FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY;;;; +254B;BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY VERTICAL AND HORIZONTAL;;;; +254C;BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH HORIZONTAL;;;; +254D;BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH HORIZONTAL;;;; +254E;BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS LIGHT DOUBLE DASH VERTICAL;;;; +254F;BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL;So;0;ON;;;;;N;FORMS HEAVY DOUBLE DASH VERTICAL;;;; +2550;BOX DRAWINGS DOUBLE HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE HORIZONTAL;;;; +2551;BOX DRAWINGS DOUBLE VERTICAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL;;;; +2552;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND RIGHT DOUBLE;;;; +2553;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND RIGHT SINGLE;;;; +2554;BOX DRAWINGS DOUBLE DOWN AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND RIGHT;;;; +2555;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND LEFT DOUBLE;;;; +2556;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND LEFT SINGLE;;;; +2557;BOX DRAWINGS DOUBLE DOWN AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND LEFT;;;; +2558;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND RIGHT DOUBLE;;;; +2559;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND RIGHT SINGLE;;;; +255A;BOX DRAWINGS DOUBLE UP AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE UP AND RIGHT;;;; +255B;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND LEFT DOUBLE;;;; +255C;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND LEFT SINGLE;;;; +255D;BOX DRAWINGS DOUBLE UP AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE UP AND LEFT;;;; +255E;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND RIGHT DOUBLE;;;; +255F;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND RIGHT SINGLE;;;; +2560;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND RIGHT;;;; +2561;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND LEFT DOUBLE;;;; +2562;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND LEFT SINGLE;;;; +2563;BOX DRAWINGS DOUBLE VERTICAL AND LEFT;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND LEFT;;;; +2564;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS DOWN SINGLE AND HORIZONTAL DOUBLE;;;; +2565;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS DOWN DOUBLE AND HORIZONTAL SINGLE;;;; +2566;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE DOWN AND HORIZONTAL;;;; +2567;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS UP SINGLE AND HORIZONTAL DOUBLE;;;; +2568;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS UP DOUBLE AND HORIZONTAL SINGLE;;;; +2569;BOX DRAWINGS DOUBLE UP AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE UP AND HORIZONTAL;;;; +256A;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE;So;0;ON;;;;;N;FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE;;;; +256B;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE;So;0;ON;;;;;N;FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE;;;; +256C;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL;So;0;ON;;;;;N;FORMS DOUBLE VERTICAL AND HORIZONTAL;;;; +256D;BOX DRAWINGS LIGHT ARC DOWN AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND RIGHT;;;; +256E;BOX DRAWINGS LIGHT ARC DOWN AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC DOWN AND LEFT;;;; +256F;BOX DRAWINGS LIGHT ARC UP AND LEFT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND LEFT;;;; +2570;BOX DRAWINGS LIGHT ARC UP AND RIGHT;So;0;ON;;;;;N;FORMS LIGHT ARC UP AND RIGHT;;;; +2571;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT;;;; +2572;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT;;;; +2573;BOX DRAWINGS LIGHT DIAGONAL CROSS;So;0;ON;;;;;N;FORMS LIGHT DIAGONAL CROSS;;;; +2574;BOX DRAWINGS LIGHT LEFT;So;0;ON;;;;;N;FORMS LIGHT LEFT;;;; +2575;BOX DRAWINGS LIGHT UP;So;0;ON;;;;;N;FORMS LIGHT UP;;;; +2576;BOX DRAWINGS LIGHT RIGHT;So;0;ON;;;;;N;FORMS LIGHT RIGHT;;;; +2577;BOX DRAWINGS LIGHT DOWN;So;0;ON;;;;;N;FORMS LIGHT DOWN;;;; +2578;BOX DRAWINGS HEAVY LEFT;So;0;ON;;;;;N;FORMS HEAVY LEFT;;;; +2579;BOX DRAWINGS HEAVY UP;So;0;ON;;;;;N;FORMS HEAVY UP;;;; +257A;BOX DRAWINGS HEAVY RIGHT;So;0;ON;;;;;N;FORMS HEAVY RIGHT;;;; +257B;BOX DRAWINGS HEAVY DOWN;So;0;ON;;;;;N;FORMS HEAVY DOWN;;;; +257C;BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT;So;0;ON;;;;;N;FORMS LIGHT LEFT AND HEAVY RIGHT;;;; +257D;BOX DRAWINGS LIGHT UP AND HEAVY DOWN;So;0;ON;;;;;N;FORMS LIGHT UP AND HEAVY DOWN;;;; +257E;BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT;So;0;ON;;;;;N;FORMS HEAVY LEFT AND LIGHT RIGHT;;;; +257F;BOX DRAWINGS HEAVY UP AND LIGHT DOWN;So;0;ON;;;;;N;FORMS HEAVY UP AND LIGHT DOWN;;;; +2580;UPPER HALF BLOCK;So;0;ON;;;;;N;;;;; +2581;LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2582;LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +2583;LOWER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2584;LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; +2585;LOWER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2586;LOWER THREE QUARTERS BLOCK;So;0;ON;;;;;N;LOWER THREE QUARTER BLOCK;;;; +2587;LOWER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +2588;FULL BLOCK;So;0;ON;;;;;N;;;;; +2589;LEFT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258A;LEFT THREE QUARTERS BLOCK;So;0;ON;;;;;N;LEFT THREE QUARTER BLOCK;;;; +258B;LEFT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258C;LEFT HALF BLOCK;So;0;ON;;;;;N;;;;; +258D;LEFT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +258E;LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +258F;LEFT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2590;RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; +2591;LIGHT SHADE;So;0;ON;;;;;N;;;;; +2592;MEDIUM SHADE;So;0;ON;;;;;N;;;;; +2593;DARK SHADE;So;0;ON;;;;;N;;;;; +2594;UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2595;RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +2596;QUADRANT LOWER LEFT;So;0;ON;;;;;N;;;;; +2597;QUADRANT LOWER RIGHT;So;0;ON;;;;;N;;;;; +2598;QUADRANT UPPER LEFT;So;0;ON;;;;;N;;;;; +2599;QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259A;QUADRANT UPPER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259B;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; +259C;QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +259D;QUADRANT UPPER RIGHT;So;0;ON;;;;;N;;;;; +259E;QUADRANT UPPER RIGHT AND LOWER LEFT;So;0;ON;;;;;N;;;;; +259F;QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +25A0;BLACK SQUARE;So;0;ON;;;;;N;;;;; +25A1;WHITE SQUARE;So;0;ON;;;;;N;;;;; +25A2;WHITE SQUARE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; +25A3;WHITE SQUARE CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +25A4;SQUARE WITH HORIZONTAL FILL;So;0;ON;;;;;N;;;;; +25A5;SQUARE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; +25A6;SQUARE WITH ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +25A7;SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; +25A8;SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; +25A9;SQUARE WITH DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +25AA;BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +25AB;WHITE SMALL SQUARE;So;0;ON;;;;;N;;;;; +25AC;BLACK RECTANGLE;So;0;ON;;;;;N;;;;; +25AD;WHITE RECTANGLE;So;0;ON;;;;;N;;;;; +25AE;BLACK VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; +25AF;WHITE VERTICAL RECTANGLE;So;0;ON;;;;;N;;;;; +25B0;BLACK PARALLELOGRAM;So;0;ON;;;;;N;;;;; +25B1;WHITE PARALLELOGRAM;So;0;ON;;;;;N;;;;; +25B2;BLACK UP-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING TRIANGLE;;;; +25B3;WHITE UP-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE;;;; +25B4;BLACK UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK UP POINTING SMALL TRIANGLE;;;; +25B5;WHITE UP-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE UP POINTING SMALL TRIANGLE;;;; +25B6;BLACK RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING TRIANGLE;;;; +25B7;WHITE RIGHT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE RIGHT POINTING TRIANGLE;;;; +25B8;BLACK RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK RIGHT POINTING SMALL TRIANGLE;;;; +25B9;WHITE RIGHT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE RIGHT POINTING SMALL TRIANGLE;;;; +25BA;BLACK RIGHT-POINTING POINTER;So;0;ON;;;;;N;BLACK RIGHT POINTING POINTER;;;; +25BB;WHITE RIGHT-POINTING POINTER;So;0;ON;;;;;N;WHITE RIGHT POINTING POINTER;;;; +25BC;BLACK DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING TRIANGLE;;;; +25BD;WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING TRIANGLE;;;; +25BE;BLACK DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK DOWN POINTING SMALL TRIANGLE;;;; +25BF;WHITE DOWN-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE DOWN POINTING SMALL TRIANGLE;;;; +25C0;BLACK LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING TRIANGLE;;;; +25C1;WHITE LEFT-POINTING TRIANGLE;Sm;0;ON;;;;;N;WHITE LEFT POINTING TRIANGLE;;;; +25C2;BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;BLACK LEFT POINTING SMALL TRIANGLE;;;; +25C3;WHITE LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;WHITE LEFT POINTING SMALL TRIANGLE;;;; +25C4;BLACK LEFT-POINTING POINTER;So;0;ON;;;;;N;BLACK LEFT POINTING POINTER;;;; +25C5;WHITE LEFT-POINTING POINTER;So;0;ON;;;;;N;WHITE LEFT POINTING POINTER;;;; +25C6;BLACK DIAMOND;So;0;ON;;;;;N;;;;; +25C7;WHITE DIAMOND;So;0;ON;;;;;N;;;;; +25C8;WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; +25C9;FISHEYE;So;0;ON;;;;;N;;;;; +25CA;LOZENGE;So;0;ON;;;;;N;;;;; +25CB;WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25CC;DOTTED CIRCLE;So;0;ON;;;;;N;;;;; +25CD;CIRCLE WITH VERTICAL FILL;So;0;ON;;;;;N;;;;; +25CE;BULLSEYE;So;0;ON;;;;;N;;;;; +25CF;BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D0;CIRCLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +25D1;CIRCLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +25D2;CIRCLE WITH LOWER HALF BLACK;So;0;ON;;;;;N;;;;; +25D3;CIRCLE WITH UPPER HALF BLACK;So;0;ON;;;;;N;;;;; +25D4;CIRCLE WITH UPPER RIGHT QUADRANT BLACK;So;0;ON;;;;;N;;;;; +25D5;CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK;So;0;ON;;;;;N;;;;; +25D6;LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D7;RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +25D8;INVERSE BULLET;So;0;ON;;;;;N;;;;; +25D9;INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DA;UPPER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DB;LOWER HALF INVERSE WHITE CIRCLE;So;0;ON;;;;;N;;;;; +25DC;UPPER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DD;UPPER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DE;LOWER RIGHT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25DF;LOWER LEFT QUADRANT CIRCULAR ARC;So;0;ON;;;;;N;;;;; +25E0;UPPER HALF CIRCLE;So;0;ON;;;;;N;;;;; +25E1;LOWER HALF CIRCLE;So;0;ON;;;;;N;;;;; +25E2;BLACK LOWER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +25E3;BLACK LOWER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; +25E4;BLACK UPPER LEFT TRIANGLE;So;0;ON;;;;;N;;;;; +25E5;BLACK UPPER RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +25E6;WHITE BULLET;So;0;ON;;;;;N;;;;; +25E7;SQUARE WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +25E8;SQUARE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +25E9;SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +25EA;SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +25EB;WHITE SQUARE WITH VERTICAL BISECTING LINE;So;0;ON;;;;;N;;;;; +25EC;WHITE UP-POINTING TRIANGLE WITH DOT;So;0;ON;;;;;N;WHITE UP POINTING TRIANGLE WITH DOT;;;; +25ED;UP-POINTING TRIANGLE WITH LEFT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH LEFT HALF BLACK;;;; +25EE;UP-POINTING TRIANGLE WITH RIGHT HALF BLACK;So;0;ON;;;;;N;UP POINTING TRIANGLE WITH RIGHT HALF BLACK;;;; +25EF;LARGE CIRCLE;So;0;ON;;;;;N;;;;; +25F0;WHITE SQUARE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F1;WHITE SQUARE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F2;WHITE SQUARE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F3;WHITE SQUARE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F4;WHITE CIRCLE WITH UPPER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F5;WHITE CIRCLE WITH LOWER LEFT QUADRANT;So;0;ON;;;;;N;;;;; +25F6;WHITE CIRCLE WITH LOWER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F7;WHITE CIRCLE WITH UPPER RIGHT QUADRANT;So;0;ON;;;;;N;;;;; +25F8;UPPER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25F9;UPPER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25FA;LOWER LEFT TRIANGLE;Sm;0;ON;;;;;N;;;;; +25FB;WHITE MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; +25FC;BLACK MEDIUM SQUARE;Sm;0;ON;;;;;N;;;;; +25FD;WHITE MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; +25FE;BLACK MEDIUM SMALL SQUARE;Sm;0;ON;;;;;N;;;;; +25FF;LOWER RIGHT TRIANGLE;Sm;0;ON;;;;;N;;;;; +2600;BLACK SUN WITH RAYS;So;0;ON;;;;;N;;;;; +2601;CLOUD;So;0;ON;;;;;N;;;;; +2602;UMBRELLA;So;0;ON;;;;;N;;;;; +2603;SNOWMAN;So;0;ON;;;;;N;;;;; +2604;COMET;So;0;ON;;;;;N;;;;; +2605;BLACK STAR;So;0;ON;;;;;N;;;;; +2606;WHITE STAR;So;0;ON;;;;;N;;;;; +2607;LIGHTNING;So;0;ON;;;;;N;;;;; +2608;THUNDERSTORM;So;0;ON;;;;;N;;;;; +2609;SUN;So;0;ON;;;;;N;;;;; +260A;ASCENDING NODE;So;0;ON;;;;;N;;;;; +260B;DESCENDING NODE;So;0;ON;;;;;N;;;;; +260C;CONJUNCTION;So;0;ON;;;;;N;;;;; +260D;OPPOSITION;So;0;ON;;;;;N;;;;; +260E;BLACK TELEPHONE;So;0;ON;;;;;N;;;;; +260F;WHITE TELEPHONE;So;0;ON;;;;;N;;;;; +2610;BALLOT BOX;So;0;ON;;;;;N;;;;; +2611;BALLOT BOX WITH CHECK;So;0;ON;;;;;N;;;;; +2612;BALLOT BOX WITH X;So;0;ON;;;;;N;;;;; +2613;SALTIRE;So;0;ON;;;;;N;;;;; +2614;UMBRELLA WITH RAIN DROPS;So;0;ON;;;;;N;;;;; +2615;HOT BEVERAGE;So;0;ON;;;;;N;;;;; +2616;WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; +2617;BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; +2618;SHAMROCK;So;0;ON;;;;;N;;;;; +2619;REVERSED ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; +261A;BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +261B;BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +261C;WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +261D;WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; +261E;WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +261F;WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +2620;SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; +2621;CAUTION SIGN;So;0;ON;;;;;N;;;;; +2622;RADIOACTIVE SIGN;So;0;ON;;;;;N;;;;; +2623;BIOHAZARD SIGN;So;0;ON;;;;;N;;;;; +2624;CADUCEUS;So;0;ON;;;;;N;;;;; +2625;ANKH;So;0;ON;;;;;N;;;;; +2626;ORTHODOX CROSS;So;0;ON;;;;;N;;;;; +2627;CHI RHO;So;0;ON;;;;;N;;;;; +2628;CROSS OF LORRAINE;So;0;ON;;;;;N;;;;; +2629;CROSS OF JERUSALEM;So;0;ON;;;;;N;;;;; +262A;STAR AND CRESCENT;So;0;ON;;;;;N;;;;; +262B;FARSI SYMBOL;So;0;ON;;;;;N;SYMBOL OF IRAN;;;; +262C;ADI SHAKTI;So;0;ON;;;;;N;;;;; +262D;HAMMER AND SICKLE;So;0;ON;;;;;N;;;;; +262E;PEACE SYMBOL;So;0;ON;;;;;N;;;;; +262F;YIN YANG;So;0;ON;;;;;N;;;;; +2630;TRIGRAM FOR HEAVEN;So;0;ON;;;;;N;;;;; +2631;TRIGRAM FOR LAKE;So;0;ON;;;;;N;;;;; +2632;TRIGRAM FOR FIRE;So;0;ON;;;;;N;;;;; +2633;TRIGRAM FOR THUNDER;So;0;ON;;;;;N;;;;; +2634;TRIGRAM FOR WIND;So;0;ON;;;;;N;;;;; +2635;TRIGRAM FOR WATER;So;0;ON;;;;;N;;;;; +2636;TRIGRAM FOR MOUNTAIN;So;0;ON;;;;;N;;;;; +2637;TRIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +2638;WHEEL OF DHARMA;So;0;ON;;;;;N;;;;; +2639;WHITE FROWNING FACE;So;0;ON;;;;;N;;;;; +263A;WHITE SMILING FACE;So;0;ON;;;;;N;;;;; +263B;BLACK SMILING FACE;So;0;ON;;;;;N;;;;; +263C;WHITE SUN WITH RAYS;So;0;ON;;;;;N;;;;; +263D;FIRST QUARTER MOON;So;0;ON;;;;;N;;;;; +263E;LAST QUARTER MOON;So;0;ON;;;;;N;;;;; +263F;MERCURY;So;0;ON;;;;;N;;;;; +2640;FEMALE SIGN;So;0;ON;;;;;N;;;;; +2641;EARTH;So;0;ON;;;;;N;;;;; +2642;MALE SIGN;So;0;ON;;;;;N;;;;; +2643;JUPITER;So;0;ON;;;;;N;;;;; +2644;SATURN;So;0;ON;;;;;N;;;;; +2645;URANUS;So;0;ON;;;;;N;;;;; +2646;NEPTUNE;So;0;ON;;;;;N;;;;; +2647;PLUTO;So;0;ON;;;;;N;;;;; +2648;ARIES;So;0;ON;;;;;N;;;;; +2649;TAURUS;So;0;ON;;;;;N;;;;; +264A;GEMINI;So;0;ON;;;;;N;;;;; +264B;CANCER;So;0;ON;;;;;N;;;;; +264C;LEO;So;0;ON;;;;;N;;;;; +264D;VIRGO;So;0;ON;;;;;N;;;;; +264E;LIBRA;So;0;ON;;;;;N;;;;; +264F;SCORPIUS;So;0;ON;;;;;N;;;;; +2650;SAGITTARIUS;So;0;ON;;;;;N;;;;; +2651;CAPRICORN;So;0;ON;;;;;N;;;;; +2652;AQUARIUS;So;0;ON;;;;;N;;;;; +2653;PISCES;So;0;ON;;;;;N;;;;; +2654;WHITE CHESS KING;So;0;ON;;;;;N;;;;; +2655;WHITE CHESS QUEEN;So;0;ON;;;;;N;;;;; +2656;WHITE CHESS ROOK;So;0;ON;;;;;N;;;;; +2657;WHITE CHESS BISHOP;So;0;ON;;;;;N;;;;; +2658;WHITE CHESS KNIGHT;So;0;ON;;;;;N;;;;; +2659;WHITE CHESS PAWN;So;0;ON;;;;;N;;;;; +265A;BLACK CHESS KING;So;0;ON;;;;;N;;;;; +265B;BLACK CHESS QUEEN;So;0;ON;;;;;N;;;;; +265C;BLACK CHESS ROOK;So;0;ON;;;;;N;;;;; +265D;BLACK CHESS BISHOP;So;0;ON;;;;;N;;;;; +265E;BLACK CHESS KNIGHT;So;0;ON;;;;;N;;;;; +265F;BLACK CHESS PAWN;So;0;ON;;;;;N;;;;; +2660;BLACK SPADE SUIT;So;0;ON;;;;;N;;;;; +2661;WHITE HEART SUIT;So;0;ON;;;;;N;;;;; +2662;WHITE DIAMOND SUIT;So;0;ON;;;;;N;;;;; +2663;BLACK CLUB SUIT;So;0;ON;;;;;N;;;;; +2664;WHITE SPADE SUIT;So;0;ON;;;;;N;;;;; +2665;BLACK HEART SUIT;So;0;ON;;;;;N;;;;; +2666;BLACK DIAMOND SUIT;So;0;ON;;;;;N;;;;; +2667;WHITE CLUB SUIT;So;0;ON;;;;;N;;;;; +2668;HOT SPRINGS;So;0;ON;;;;;N;;;;; +2669;QUARTER NOTE;So;0;ON;;;;;N;;;;; +266A;EIGHTH NOTE;So;0;ON;;;;;N;;;;; +266B;BEAMED EIGHTH NOTES;So;0;ON;;;;;N;BARRED EIGHTH NOTES;;;; +266C;BEAMED SIXTEENTH NOTES;So;0;ON;;;;;N;BARRED SIXTEENTH NOTES;;;; +266D;MUSIC FLAT SIGN;So;0;ON;;;;;N;FLAT;;;; +266E;MUSIC NATURAL SIGN;So;0;ON;;;;;N;NATURAL;;;; +266F;MUSIC SHARP SIGN;Sm;0;ON;;;;;N;SHARP;;;; +2670;WEST SYRIAC CROSS;So;0;ON;;;;;N;;;;; +2671;EAST SYRIAC CROSS;So;0;ON;;;;;N;;;;; +2672;UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; +2673;RECYCLING SYMBOL FOR TYPE-1 PLASTICS;So;0;ON;;;;;N;;;;; +2674;RECYCLING SYMBOL FOR TYPE-2 PLASTICS;So;0;ON;;;;;N;;;;; +2675;RECYCLING SYMBOL FOR TYPE-3 PLASTICS;So;0;ON;;;;;N;;;;; +2676;RECYCLING SYMBOL FOR TYPE-4 PLASTICS;So;0;ON;;;;;N;;;;; +2677;RECYCLING SYMBOL FOR TYPE-5 PLASTICS;So;0;ON;;;;;N;;;;; +2678;RECYCLING SYMBOL FOR TYPE-6 PLASTICS;So;0;ON;;;;;N;;;;; +2679;RECYCLING SYMBOL FOR TYPE-7 PLASTICS;So;0;ON;;;;;N;;;;; +267A;RECYCLING SYMBOL FOR GENERIC MATERIALS;So;0;ON;;;;;N;;;;; +267B;BLACK UNIVERSAL RECYCLING SYMBOL;So;0;ON;;;;;N;;;;; +267C;RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; +267D;PARTIALLY-RECYCLED PAPER SYMBOL;So;0;ON;;;;;N;;;;; +267E;PERMANENT PAPER SIGN;So;0;ON;;;;;N;;;;; +267F;WHEELCHAIR SYMBOL;So;0;ON;;;;;N;;;;; +2680;DIE FACE-1;So;0;ON;;;;;N;;;;; +2681;DIE FACE-2;So;0;ON;;;;;N;;;;; +2682;DIE FACE-3;So;0;ON;;;;;N;;;;; +2683;DIE FACE-4;So;0;ON;;;;;N;;;;; +2684;DIE FACE-5;So;0;ON;;;;;N;;;;; +2685;DIE FACE-6;So;0;ON;;;;;N;;;;; +2686;WHITE CIRCLE WITH DOT RIGHT;So;0;ON;;;;;N;;;;; +2687;WHITE CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +2688;BLACK CIRCLE WITH WHITE DOT RIGHT;So;0;ON;;;;;N;;;;; +2689;BLACK CIRCLE WITH TWO WHITE DOTS;So;0;ON;;;;;N;;;;; +268A;MONOGRAM FOR YANG;So;0;ON;;;;;N;;;;; +268B;MONOGRAM FOR YIN;So;0;ON;;;;;N;;;;; +268C;DIGRAM FOR GREATER YANG;So;0;ON;;;;;N;;;;; +268D;DIGRAM FOR LESSER YIN;So;0;ON;;;;;N;;;;; +268E;DIGRAM FOR LESSER YANG;So;0;ON;;;;;N;;;;; +268F;DIGRAM FOR GREATER YIN;So;0;ON;;;;;N;;;;; +2690;WHITE FLAG;So;0;ON;;;;;N;;;;; +2691;BLACK FLAG;So;0;ON;;;;;N;;;;; +2692;HAMMER AND PICK;So;0;ON;;;;;N;;;;; +2693;ANCHOR;So;0;ON;;;;;N;;;;; +2694;CROSSED SWORDS;So;0;ON;;;;;N;;;;; +2695;STAFF OF AESCULAPIUS;So;0;ON;;;;;N;;;;; +2696;SCALES;So;0;ON;;;;;N;;;;; +2697;ALEMBIC;So;0;ON;;;;;N;;;;; +2698;FLOWER;So;0;ON;;;;;N;;;;; +2699;GEAR;So;0;ON;;;;;N;;;;; +269A;STAFF OF HERMES;So;0;ON;;;;;N;;;;; +269B;ATOM SYMBOL;So;0;ON;;;;;N;;;;; +269C;FLEUR-DE-LIS;So;0;ON;;;;;N;;;;; +269D;OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; +269E;THREE LINES CONVERGING RIGHT;So;0;ON;;;;;N;;;;; +269F;THREE LINES CONVERGING LEFT;So;0;ON;;;;;N;;;;; +26A0;WARNING SIGN;So;0;ON;;;;;N;;;;; +26A1;HIGH VOLTAGE SIGN;So;0;ON;;;;;N;;;;; +26A2;DOUBLED FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A3;DOUBLED MALE SIGN;So;0;ON;;;;;N;;;;; +26A4;INTERLOCKED FEMALE AND MALE SIGN;So;0;ON;;;;;N;;;;; +26A5;MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A6;MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26A7;MALE WITH STROKE AND MALE AND FEMALE SIGN;So;0;ON;;;;;N;;;;; +26A8;VERTICAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26A9;HORIZONTAL MALE WITH STROKE SIGN;So;0;ON;;;;;N;;;;; +26AA;MEDIUM WHITE CIRCLE;So;0;ON;;;;;N;;;;; +26AB;MEDIUM BLACK CIRCLE;So;0;ON;;;;;N;;;;; +26AC;MEDIUM SMALL WHITE CIRCLE;So;0;L;;;;;N;;;;; +26AD;MARRIAGE SYMBOL;So;0;ON;;;;;N;;;;; +26AE;DIVORCE SYMBOL;So;0;ON;;;;;N;;;;; +26AF;UNMARRIED PARTNERSHIP SYMBOL;So;0;ON;;;;;N;;;;; +26B0;COFFIN;So;0;ON;;;;;N;;;;; +26B1;FUNERAL URN;So;0;ON;;;;;N;;;;; +26B2;NEUTER;So;0;ON;;;;;N;;;;; +26B3;CERES;So;0;ON;;;;;N;;;;; +26B4;PALLAS;So;0;ON;;;;;N;;;;; +26B5;JUNO;So;0;ON;;;;;N;;;;; +26B6;VESTA;So;0;ON;;;;;N;;;;; +26B7;CHIRON;So;0;ON;;;;;N;;;;; +26B8;BLACK MOON LILITH;So;0;ON;;;;;N;;;;; +26B9;SEXTILE;So;0;ON;;;;;N;;;;; +26BA;SEMISEXTILE;So;0;ON;;;;;N;;;;; +26BB;QUINCUNX;So;0;ON;;;;;N;;;;; +26BC;SESQUIQUADRATE;So;0;ON;;;;;N;;;;; +26BD;SOCCER BALL;So;0;ON;;;;;N;;;;; +26BE;BASEBALL;So;0;ON;;;;;N;;;;; +26BF;SQUARED KEY;So;0;ON;;;;;N;;;;; +26C0;WHITE DRAUGHTS MAN;So;0;ON;;;;;N;;;;; +26C1;WHITE DRAUGHTS KING;So;0;ON;;;;;N;;;;; +26C2;BLACK DRAUGHTS MAN;So;0;ON;;;;;N;;;;; +26C3;BLACK DRAUGHTS KING;So;0;ON;;;;;N;;;;; +26C4;SNOWMAN WITHOUT SNOW;So;0;ON;;;;;N;;;;; +26C5;SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; +26C6;RAIN;So;0;ON;;;;;N;;;;; +26C7;BLACK SNOWMAN;So;0;ON;;;;;N;;;;; +26C8;THUNDER CLOUD AND RAIN;So;0;ON;;;;;N;;;;; +26C9;TURNED WHITE SHOGI PIECE;So;0;ON;;;;;N;;;;; +26CA;TURNED BLACK SHOGI PIECE;So;0;ON;;;;;N;;;;; +26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; +26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; +26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; +26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;; +26CF;PICK;So;0;ON;;;;;N;;;;; +26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; +26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; +26D2;CIRCLED CROSSING LANES;So;0;ON;;;;;N;;;;; +26D3;CHAINS;So;0;ON;;;;;N;;;;; +26D4;NO ENTRY;So;0;ON;;;;;N;;;;; +26D5;ALTERNATE ONE-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D6;BLACK TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D7;WHITE TWO-WAY LEFT WAY TRAFFIC;So;0;ON;;;;;N;;;;; +26D8;BLACK LEFT LANE MERGE;So;0;ON;;;;;N;;;;; +26D9;WHITE LEFT LANE MERGE;So;0;ON;;;;;N;;;;; +26DA;DRIVE SLOW SIGN;So;0;ON;;;;;N;;;;; +26DB;HEAVY WHITE DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +26DC;LEFT CLOSED ENTRY;So;0;ON;;;;;N;;;;; +26DD;SQUARED SALTIRE;So;0;ON;;;;;N;;;;; +26DE;FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; +26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; +26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; +26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;; +26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; +26E4;PENTAGRAM;So;0;ON;;;;;N;;;;; +26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; +26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; +26EA;CHURCH;So;0;ON;;;;;N;;;;; +26EB;CASTLE;So;0;ON;;;;;N;;;;; +26EC;HISTORIC SITE;So;0;ON;;;;;N;;;;; +26ED;GEAR WITHOUT HUB;So;0;ON;;;;;N;;;;; +26EE;GEAR WITH HANDLES;So;0;ON;;;;;N;;;;; +26EF;MAP SYMBOL FOR LIGHTHOUSE;So;0;ON;;;;;N;;;;; +26F0;MOUNTAIN;So;0;ON;;;;;N;;;;; +26F1;UMBRELLA ON GROUND;So;0;ON;;;;;N;;;;; +26F2;FOUNTAIN;So;0;ON;;;;;N;;;;; +26F3;FLAG IN HOLE;So;0;ON;;;;;N;;;;; +26F4;FERRY;So;0;ON;;;;;N;;;;; +26F5;SAILBOAT;So;0;ON;;;;;N;;;;; +26F6;SQUARE FOUR CORNERS;So;0;ON;;;;;N;;;;; +26F7;SKIER;So;0;ON;;;;;N;;;;; +26F8;ICE SKATE;So;0;ON;;;;;N;;;;; +26F9;PERSON WITH BALL;So;0;ON;;;;;N;;;;; +26FA;TENT;So;0;ON;;;;;N;;;;; +26FB;JAPANESE BANK SYMBOL;So;0;ON;;;;;N;;;;; +26FC;HEADSTONE GRAVEYARD SYMBOL;So;0;ON;;;;;N;;;;; +26FD;FUEL PUMP;So;0;ON;;;;;N;;;;; +26FE;CUP ON BLACK SQUARE;So;0;ON;;;;;N;;;;; +26FF;WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE;So;0;ON;;;;;N;;;;; +2700;BLACK SAFETY SCISSORS;So;0;ON;;;;;N;;;;; +2701;UPPER BLADE SCISSORS;So;0;ON;;;;;N;;;;; +2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; +2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; +2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; +2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; +2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; +2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; +2708;AIRPLANE;So;0;ON;;;;;N;;;;; +2709;ENVELOPE;So;0;ON;;;;;N;;;;; +270A;RAISED FIST;So;0;ON;;;;;N;;;;; +270B;RAISED HAND;So;0;ON;;;;;N;;;;; +270C;VICTORY HAND;So;0;ON;;;;;N;;;;; +270D;WRITING HAND;So;0;ON;;;;;N;;;;; +270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; +270F;PENCIL;So;0;ON;;;;;N;;;;; +2710;UPPER RIGHT PENCIL;So;0;ON;;;;;N;;;;; +2711;WHITE NIB;So;0;ON;;;;;N;;;;; +2712;BLACK NIB;So;0;ON;;;;;N;;;;; +2713;CHECK MARK;So;0;ON;;;;;N;;;;; +2714;HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; +2715;MULTIPLICATION X;So;0;ON;;;;;N;;;;; +2716;HEAVY MULTIPLICATION X;So;0;ON;;;;;N;;;;; +2717;BALLOT X;So;0;ON;;;;;N;;;;; +2718;HEAVY BALLOT X;So;0;ON;;;;;N;;;;; +2719;OUTLINED GREEK CROSS;So;0;ON;;;;;N;;;;; +271A;HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +271B;OPEN CENTRE CROSS;So;0;ON;;;;;N;OPEN CENTER CROSS;;;; +271C;HEAVY OPEN CENTRE CROSS;So;0;ON;;;;;N;HEAVY OPEN CENTER CROSS;;;; +271D;LATIN CROSS;So;0;ON;;;;;N;;;;; +271E;SHADOWED WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; +271F;OUTLINED LATIN CROSS;So;0;ON;;;;;N;;;;; +2720;MALTESE CROSS;So;0;ON;;;;;N;;;;; +2721;STAR OF DAVID;So;0;ON;;;;;N;;;;; +2722;FOUR TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2723;FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2724;HEAVY FOUR BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; +2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; +2728;SPARKLES;So;0;ON;;;;;N;;;;; +2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; +272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; +272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; +272C;BLACK CENTRE WHITE STAR;So;0;ON;;;;;N;BLACK CENTER WHITE STAR;;;; +272D;OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; +272E;HEAVY OUTLINED BLACK STAR;So;0;ON;;;;;N;;;;; +272F;PINWHEEL STAR;So;0;ON;;;;;N;;;;; +2730;SHADOWED WHITE STAR;So;0;ON;;;;;N;;;;; +2731;HEAVY ASTERISK;So;0;ON;;;;;N;;;;; +2732;OPEN CENTRE ASTERISK;So;0;ON;;;;;N;OPEN CENTER ASTERISK;;;; +2733;EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +2734;EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +2735;EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +2736;SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +2737;EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; +2738;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR;So;0;ON;;;;;N;;;;; +2739;TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +273A;SIXTEEN POINTED ASTERISK;So;0;ON;;;;;N;;;;; +273B;TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +273C;OPEN CENTRE TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;OPEN CENTER TEARDROP-SPOKED ASTERISK;;;; +273D;HEAVY TEARDROP-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +273E;SIX PETALLED BLACK AND WHITE FLORETTE;So;0;ON;;;;;N;;;;; +273F;BLACK FLORETTE;So;0;ON;;;;;N;;;;; +2740;WHITE FLORETTE;So;0;ON;;;;;N;;;;; +2741;EIGHT PETALLED OUTLINED BLACK FLORETTE;So;0;ON;;;;;N;;;;; +2742;CIRCLED OPEN CENTRE EIGHT POINTED STAR;So;0;ON;;;;;N;CIRCLED OPEN CENTER EIGHT POINTED STAR;;;; +2743;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK;So;0;ON;;;;;N;;;;; +2744;SNOWFLAKE;So;0;ON;;;;;N;;;;; +2745;TIGHT TRIFOLIATE SNOWFLAKE;So;0;ON;;;;;N;;;;; +2746;HEAVY CHEVRON SNOWFLAKE;So;0;ON;;;;;N;;;;; +2747;SPARKLE;So;0;ON;;;;;N;;;;; +2748;HEAVY SPARKLE;So;0;ON;;;;;N;;;;; +2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; +274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; +274C;CROSS MARK;So;0;ON;;;;;N;;;;; +274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;; +274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; +2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; +2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; +2759;MEDIUM VERTICAL BAR;So;0;ON;;;;;N;;;;; +275A;HEAVY VERTICAL BAR;So;0;ON;;;;;N;;;;; +275B;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; +2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2764;HEAVY BLACK HEART;So;0;ON;;;;;N;;;;; +2765;ROTATED HEAVY BLACK HEART BULLET;So;0;ON;;;;;N;;;;; +2766;FLORAL HEART;So;0;ON;;;;;N;;;;; +2767;ROTATED FLORAL HEART BULLET;So;0;ON;;;;;N;;;;; +2768;MEDIUM LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2769;MEDIUM RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276A;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276B;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276C;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276D;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +276E;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT;Ps;0;ON;;;;;Y;;;;; +276F;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2770;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2771;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2772;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2773;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2774;MEDIUM LEFT CURLY BRACKET ORNAMENT;Ps;0;ON;;;;;Y;;;;; +2775;MEDIUM RIGHT CURLY BRACKET ORNAMENT;Pe;0;ON;;;;;Y;;;;; +2776;DINGBAT NEGATIVE CIRCLED DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED DIGIT ONE;;;; +2777;DINGBAT NEGATIVE CIRCLED DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED DIGIT TWO;;;; +2778;DINGBAT NEGATIVE CIRCLED DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED DIGIT THREE;;;; +2779;DINGBAT NEGATIVE CIRCLED DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED DIGIT FOUR;;;; +277A;DINGBAT NEGATIVE CIRCLED DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED DIGIT FIVE;;;; +277B;DINGBAT NEGATIVE CIRCLED DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED DIGIT SIX;;;; +277C;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED DIGIT SEVEN;;;; +277D;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED DIGIT EIGHT;;;; +277E;DINGBAT NEGATIVE CIRCLED DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED DIGIT NINE;;;; +277F;DINGBAT NEGATIVE CIRCLED NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED NUMBER TEN;;;; +2780;DINGBAT CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;CIRCLED SANS-SERIF DIGIT ONE;;;; +2781;DINGBAT CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;CIRCLED SANS-SERIF DIGIT TWO;;;; +2782;DINGBAT CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;CIRCLED SANS-SERIF DIGIT THREE;;;; +2783;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;CIRCLED SANS-SERIF DIGIT FOUR;;;; +2784;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;CIRCLED SANS-SERIF DIGIT FIVE;;;; +2785;DINGBAT CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;CIRCLED SANS-SERIF DIGIT SIX;;;; +2786;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;CIRCLED SANS-SERIF DIGIT SEVEN;;;; +2787;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;CIRCLED SANS-SERIF DIGIT EIGHT;;;; +2788;DINGBAT CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;CIRCLED SANS-SERIF DIGIT NINE;;;; +2789;DINGBAT CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;CIRCLED SANS-SERIF NUMBER TEN;;;; +278A;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE;No;0;ON;;;1;1;N;INVERSE CIRCLED SANS-SERIF DIGIT ONE;;;; +278B;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO;No;0;ON;;;2;2;N;INVERSE CIRCLED SANS-SERIF DIGIT TWO;;;; +278C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE;No;0;ON;;;3;3;N;INVERSE CIRCLED SANS-SERIF DIGIT THREE;;;; +278D;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR;No;0;ON;;;4;4;N;INVERSE CIRCLED SANS-SERIF DIGIT FOUR;;;; +278E;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE;No;0;ON;;;5;5;N;INVERSE CIRCLED SANS-SERIF DIGIT FIVE;;;; +278F;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX;No;0;ON;;;6;6;N;INVERSE CIRCLED SANS-SERIF DIGIT SIX;;;; +2790;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN;No;0;ON;;;7;7;N;INVERSE CIRCLED SANS-SERIF DIGIT SEVEN;;;; +2791;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT;No;0;ON;;;8;8;N;INVERSE CIRCLED SANS-SERIF DIGIT EIGHT;;;; +2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; +2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; +2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; +2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;; +2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;; +2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;; +2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; +2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; +279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; +279B;DRAFTING POINT RIGHTWARDS ARROW;So;0;ON;;;;;N;DRAFTING POINT RIGHT ARROW;;;; +279C;HEAVY ROUND-TIPPED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY ROUND-TIPPED RIGHT ARROW;;;; +279D;TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;TRIANGLE-HEADED RIGHT ARROW;;;; +279E;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TRIANGLE-HEADED RIGHT ARROW;;;; +279F;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;DASHED TRIANGLE-HEADED RIGHT ARROW;;;; +27A0;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW;;;; +27A1;BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK RIGHT ARROW;;;; +27A2;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D TOP-LIGHTED RIGHT ARROWHEAD;;;; +27A3;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD;;;; +27A4;BLACK RIGHTWARDS ARROWHEAD;So;0;ON;;;;;N;BLACK RIGHT ARROWHEAD;;;; +27A5;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED DOWN AND RIGHT ARROW;;;; +27A6;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK CURVED UP AND RIGHT ARROW;;;; +27A7;SQUAT BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;SQUAT BLACK RIGHT ARROW;;;; +27A8;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY CONCAVE-POINTED BLACK RIGHT ARROW;;;; +27A9;RIGHT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;RIGHT-SHADED WHITE RIGHT ARROW;;;; +27AA;LEFT-SHADED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;LEFT-SHADED WHITE RIGHT ARROW;;;; +27AB;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;BACK-TILTED SHADOWED WHITE RIGHT ARROW;;;; +27AC;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;FRONT-TILTED SHADOWED WHITE RIGHT ARROW;;;; +27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27B0;CURLY LOOP;So;0;ON;;;;;N;;;;; +27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; +27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; +27B4;BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED LOWER RIGHT ARROW;;;; +27B5;BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;BLACK-FEATHERED RIGHT ARROW;;;; +27B6;BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;BLACK-FEATHERED UPPER RIGHT ARROW;;;; +27B7;HEAVY BLACK-FEATHERED SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED LOWER RIGHT ARROW;;;; +27B8;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED RIGHT ARROW;;;; +27B9;HEAVY BLACK-FEATHERED NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY BLACK-FEATHERED UPPER RIGHT ARROW;;;; +27BA;TEARDROP-BARBED RIGHTWARDS ARROW;So;0;ON;;;;;N;TEARDROP-BARBED RIGHT ARROW;;;; +27BB;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY TEARDROP-SHANKED RIGHT ARROW;;;; +27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; +27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; +27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; +27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;; +27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; +27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; +27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; +27C3;OPEN SUBSET;Sm;0;ON;;;;;Y;;;;; +27C4;OPEN SUPERSET;Sm;0;ON;;;;;Y;;;;; +27C5;LEFT S-SHAPED BAG DELIMITER;Ps;0;ON;;;;;Y;;;;; +27C6;RIGHT S-SHAPED BAG DELIMITER;Pe;0;ON;;;;;Y;;;;; +27C7;OR WITH DOT INSIDE;Sm;0;ON;;;;;N;;;;; +27C8;REVERSE SOLIDUS PRECEDING SUBSET;Sm;0;ON;;;;;Y;;;;; +27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; +27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +27CB;MATHEMATICAL RISING DIAGONAL;Sm;0;ON;;;;;Y;;;;; +27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; +27CD;MATHEMATICAL FALLING DIAGONAL;Sm;0;ON;;;;;Y;;;;; +27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;; +27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;; +27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; +27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; +27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; +27D3;LOWER RIGHT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; +27D4;UPPER LEFT CORNER WITH DOT;Sm;0;ON;;;;;Y;;;;; +27D5;LEFT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; +27D6;RIGHT OUTER JOIN;Sm;0;ON;;;;;Y;;;;; +27D7;FULL OUTER JOIN;Sm;0;ON;;;;;N;;;;; +27D8;LARGE UP TACK;Sm;0;ON;;;;;N;;;;; +27D9;LARGE DOWN TACK;Sm;0;ON;;;;;N;;;;; +27DA;LEFT AND RIGHT DOUBLE TURNSTILE;Sm;0;ON;;;;;N;;;;; +27DB;LEFT AND RIGHT TACK;Sm;0;ON;;;;;N;;;;; +27DC;LEFT MULTIMAP;Sm;0;ON;;;;;Y;;;;; +27DD;LONG RIGHT TACK;Sm;0;ON;;;;;Y;;;;; +27DE;LONG LEFT TACK;Sm;0;ON;;;;;Y;;;;; +27DF;UP TACK WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +27E0;LOZENGE DIVIDED BY HORIZONTAL RULE;Sm;0;ON;;;;;N;;;;; +27E1;WHITE CONCAVE-SIDED DIAMOND;Sm;0;ON;;;;;N;;;;; +27E2;WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E3;WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E4;WHITE SQUARE WITH LEFTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E5;WHITE SQUARE WITH RIGHTWARDS TICK;Sm;0;ON;;;;;Y;;;;; +27E6;MATHEMATICAL LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;;;;; +27E7;MATHEMATICAL RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;;;;; +27E8;MATHEMATICAL LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +27E9;MATHEMATICAL RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +27EA;MATHEMATICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +27EB;MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +27EC;MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; +27ED;MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; +27EE;MATHEMATICAL LEFT FLATTENED PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +27EF;MATHEMATICAL RIGHT FLATTENED PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +27F0;UPWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; +27F1;DOWNWARDS QUADRUPLE ARROW;Sm;0;ON;;;;;N;;;;; +27F2;ANTICLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +27F3;CLOCKWISE GAPPED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +27F4;RIGHT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +27F5;LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +27F6;LONG RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +27F7;LONG LEFT RIGHT ARROW;Sm;0;ON;;;;;N;;;;; +27F8;LONG LEFTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27F9;LONG RIGHTWARDS DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27FA;LONG LEFT RIGHT DOUBLE ARROW;Sm;0;ON;;;;;N;;;;; +27FB;LONG LEFTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FC;LONG RIGHTWARDS ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FD;LONG LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FE;LONG RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +27FF;LONG RIGHTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; +2800;BRAILLE PATTERN BLANK;So;0;L;;;;;N;;;;; +2801;BRAILLE PATTERN DOTS-1;So;0;L;;;;;N;;;;; +2802;BRAILLE PATTERN DOTS-2;So;0;L;;;;;N;;;;; +2803;BRAILLE PATTERN DOTS-12;So;0;L;;;;;N;;;;; +2804;BRAILLE PATTERN DOTS-3;So;0;L;;;;;N;;;;; +2805;BRAILLE PATTERN DOTS-13;So;0;L;;;;;N;;;;; +2806;BRAILLE PATTERN DOTS-23;So;0;L;;;;;N;;;;; +2807;BRAILLE PATTERN DOTS-123;So;0;L;;;;;N;;;;; +2808;BRAILLE PATTERN DOTS-4;So;0;L;;;;;N;;;;; +2809;BRAILLE PATTERN DOTS-14;So;0;L;;;;;N;;;;; +280A;BRAILLE PATTERN DOTS-24;So;0;L;;;;;N;;;;; +280B;BRAILLE PATTERN DOTS-124;So;0;L;;;;;N;;;;; +280C;BRAILLE PATTERN DOTS-34;So;0;L;;;;;N;;;;; +280D;BRAILLE PATTERN DOTS-134;So;0;L;;;;;N;;;;; +280E;BRAILLE PATTERN DOTS-234;So;0;L;;;;;N;;;;; +280F;BRAILLE PATTERN DOTS-1234;So;0;L;;;;;N;;;;; +2810;BRAILLE PATTERN DOTS-5;So;0;L;;;;;N;;;;; +2811;BRAILLE PATTERN DOTS-15;So;0;L;;;;;N;;;;; +2812;BRAILLE PATTERN DOTS-25;So;0;L;;;;;N;;;;; +2813;BRAILLE PATTERN DOTS-125;So;0;L;;;;;N;;;;; +2814;BRAILLE PATTERN DOTS-35;So;0;L;;;;;N;;;;; +2815;BRAILLE PATTERN DOTS-135;So;0;L;;;;;N;;;;; +2816;BRAILLE PATTERN DOTS-235;So;0;L;;;;;N;;;;; +2817;BRAILLE PATTERN DOTS-1235;So;0;L;;;;;N;;;;; +2818;BRAILLE PATTERN DOTS-45;So;0;L;;;;;N;;;;; +2819;BRAILLE PATTERN DOTS-145;So;0;L;;;;;N;;;;; +281A;BRAILLE PATTERN DOTS-245;So;0;L;;;;;N;;;;; +281B;BRAILLE PATTERN DOTS-1245;So;0;L;;;;;N;;;;; +281C;BRAILLE PATTERN DOTS-345;So;0;L;;;;;N;;;;; +281D;BRAILLE PATTERN DOTS-1345;So;0;L;;;;;N;;;;; +281E;BRAILLE PATTERN DOTS-2345;So;0;L;;;;;N;;;;; +281F;BRAILLE PATTERN DOTS-12345;So;0;L;;;;;N;;;;; +2820;BRAILLE PATTERN DOTS-6;So;0;L;;;;;N;;;;; +2821;BRAILLE PATTERN DOTS-16;So;0;L;;;;;N;;;;; +2822;BRAILLE PATTERN DOTS-26;So;0;L;;;;;N;;;;; +2823;BRAILLE PATTERN DOTS-126;So;0;L;;;;;N;;;;; +2824;BRAILLE PATTERN DOTS-36;So;0;L;;;;;N;;;;; +2825;BRAILLE PATTERN DOTS-136;So;0;L;;;;;N;;;;; +2826;BRAILLE PATTERN DOTS-236;So;0;L;;;;;N;;;;; +2827;BRAILLE PATTERN DOTS-1236;So;0;L;;;;;N;;;;; +2828;BRAILLE PATTERN DOTS-46;So;0;L;;;;;N;;;;; +2829;BRAILLE PATTERN DOTS-146;So;0;L;;;;;N;;;;; +282A;BRAILLE PATTERN DOTS-246;So;0;L;;;;;N;;;;; +282B;BRAILLE PATTERN DOTS-1246;So;0;L;;;;;N;;;;; +282C;BRAILLE PATTERN DOTS-346;So;0;L;;;;;N;;;;; +282D;BRAILLE PATTERN DOTS-1346;So;0;L;;;;;N;;;;; +282E;BRAILLE PATTERN DOTS-2346;So;0;L;;;;;N;;;;; +282F;BRAILLE PATTERN DOTS-12346;So;0;L;;;;;N;;;;; +2830;BRAILLE PATTERN DOTS-56;So;0;L;;;;;N;;;;; +2831;BRAILLE PATTERN DOTS-156;So;0;L;;;;;N;;;;; +2832;BRAILLE PATTERN DOTS-256;So;0;L;;;;;N;;;;; +2833;BRAILLE PATTERN DOTS-1256;So;0;L;;;;;N;;;;; +2834;BRAILLE PATTERN DOTS-356;So;0;L;;;;;N;;;;; +2835;BRAILLE PATTERN DOTS-1356;So;0;L;;;;;N;;;;; +2836;BRAILLE PATTERN DOTS-2356;So;0;L;;;;;N;;;;; +2837;BRAILLE PATTERN DOTS-12356;So;0;L;;;;;N;;;;; +2838;BRAILLE PATTERN DOTS-456;So;0;L;;;;;N;;;;; +2839;BRAILLE PATTERN DOTS-1456;So;0;L;;;;;N;;;;; +283A;BRAILLE PATTERN DOTS-2456;So;0;L;;;;;N;;;;; +283B;BRAILLE PATTERN DOTS-12456;So;0;L;;;;;N;;;;; +283C;BRAILLE PATTERN DOTS-3456;So;0;L;;;;;N;;;;; +283D;BRAILLE PATTERN DOTS-13456;So;0;L;;;;;N;;;;; +283E;BRAILLE PATTERN DOTS-23456;So;0;L;;;;;N;;;;; +283F;BRAILLE PATTERN DOTS-123456;So;0;L;;;;;N;;;;; +2840;BRAILLE PATTERN DOTS-7;So;0;L;;;;;N;;;;; +2841;BRAILLE PATTERN DOTS-17;So;0;L;;;;;N;;;;; +2842;BRAILLE PATTERN DOTS-27;So;0;L;;;;;N;;;;; +2843;BRAILLE PATTERN DOTS-127;So;0;L;;;;;N;;;;; +2844;BRAILLE PATTERN DOTS-37;So;0;L;;;;;N;;;;; +2845;BRAILLE PATTERN DOTS-137;So;0;L;;;;;N;;;;; +2846;BRAILLE PATTERN DOTS-237;So;0;L;;;;;N;;;;; +2847;BRAILLE PATTERN DOTS-1237;So;0;L;;;;;N;;;;; +2848;BRAILLE PATTERN DOTS-47;So;0;L;;;;;N;;;;; +2849;BRAILLE PATTERN DOTS-147;So;0;L;;;;;N;;;;; +284A;BRAILLE PATTERN DOTS-247;So;0;L;;;;;N;;;;; +284B;BRAILLE PATTERN DOTS-1247;So;0;L;;;;;N;;;;; +284C;BRAILLE PATTERN DOTS-347;So;0;L;;;;;N;;;;; +284D;BRAILLE PATTERN DOTS-1347;So;0;L;;;;;N;;;;; +284E;BRAILLE PATTERN DOTS-2347;So;0;L;;;;;N;;;;; +284F;BRAILLE PATTERN DOTS-12347;So;0;L;;;;;N;;;;; +2850;BRAILLE PATTERN DOTS-57;So;0;L;;;;;N;;;;; +2851;BRAILLE PATTERN DOTS-157;So;0;L;;;;;N;;;;; +2852;BRAILLE PATTERN DOTS-257;So;0;L;;;;;N;;;;; +2853;BRAILLE PATTERN DOTS-1257;So;0;L;;;;;N;;;;; +2854;BRAILLE PATTERN DOTS-357;So;0;L;;;;;N;;;;; +2855;BRAILLE PATTERN DOTS-1357;So;0;L;;;;;N;;;;; +2856;BRAILLE PATTERN DOTS-2357;So;0;L;;;;;N;;;;; +2857;BRAILLE PATTERN DOTS-12357;So;0;L;;;;;N;;;;; +2858;BRAILLE PATTERN DOTS-457;So;0;L;;;;;N;;;;; +2859;BRAILLE PATTERN DOTS-1457;So;0;L;;;;;N;;;;; +285A;BRAILLE PATTERN DOTS-2457;So;0;L;;;;;N;;;;; +285B;BRAILLE PATTERN DOTS-12457;So;0;L;;;;;N;;;;; +285C;BRAILLE PATTERN DOTS-3457;So;0;L;;;;;N;;;;; +285D;BRAILLE PATTERN DOTS-13457;So;0;L;;;;;N;;;;; +285E;BRAILLE PATTERN DOTS-23457;So;0;L;;;;;N;;;;; +285F;BRAILLE PATTERN DOTS-123457;So;0;L;;;;;N;;;;; +2860;BRAILLE PATTERN DOTS-67;So;0;L;;;;;N;;;;; +2861;BRAILLE PATTERN DOTS-167;So;0;L;;;;;N;;;;; +2862;BRAILLE PATTERN DOTS-267;So;0;L;;;;;N;;;;; +2863;BRAILLE PATTERN DOTS-1267;So;0;L;;;;;N;;;;; +2864;BRAILLE PATTERN DOTS-367;So;0;L;;;;;N;;;;; +2865;BRAILLE PATTERN DOTS-1367;So;0;L;;;;;N;;;;; +2866;BRAILLE PATTERN DOTS-2367;So;0;L;;;;;N;;;;; +2867;BRAILLE PATTERN DOTS-12367;So;0;L;;;;;N;;;;; +2868;BRAILLE PATTERN DOTS-467;So;0;L;;;;;N;;;;; +2869;BRAILLE PATTERN DOTS-1467;So;0;L;;;;;N;;;;; +286A;BRAILLE PATTERN DOTS-2467;So;0;L;;;;;N;;;;; +286B;BRAILLE PATTERN DOTS-12467;So;0;L;;;;;N;;;;; +286C;BRAILLE PATTERN DOTS-3467;So;0;L;;;;;N;;;;; +286D;BRAILLE PATTERN DOTS-13467;So;0;L;;;;;N;;;;; +286E;BRAILLE PATTERN DOTS-23467;So;0;L;;;;;N;;;;; +286F;BRAILLE PATTERN DOTS-123467;So;0;L;;;;;N;;;;; +2870;BRAILLE PATTERN DOTS-567;So;0;L;;;;;N;;;;; +2871;BRAILLE PATTERN DOTS-1567;So;0;L;;;;;N;;;;; +2872;BRAILLE PATTERN DOTS-2567;So;0;L;;;;;N;;;;; +2873;BRAILLE PATTERN DOTS-12567;So;0;L;;;;;N;;;;; +2874;BRAILLE PATTERN DOTS-3567;So;0;L;;;;;N;;;;; +2875;BRAILLE PATTERN DOTS-13567;So;0;L;;;;;N;;;;; +2876;BRAILLE PATTERN DOTS-23567;So;0;L;;;;;N;;;;; +2877;BRAILLE PATTERN DOTS-123567;So;0;L;;;;;N;;;;; +2878;BRAILLE PATTERN DOTS-4567;So;0;L;;;;;N;;;;; +2879;BRAILLE PATTERN DOTS-14567;So;0;L;;;;;N;;;;; +287A;BRAILLE PATTERN DOTS-24567;So;0;L;;;;;N;;;;; +287B;BRAILLE PATTERN DOTS-124567;So;0;L;;;;;N;;;;; +287C;BRAILLE PATTERN DOTS-34567;So;0;L;;;;;N;;;;; +287D;BRAILLE PATTERN DOTS-134567;So;0;L;;;;;N;;;;; +287E;BRAILLE PATTERN DOTS-234567;So;0;L;;;;;N;;;;; +287F;BRAILLE PATTERN DOTS-1234567;So;0;L;;;;;N;;;;; +2880;BRAILLE PATTERN DOTS-8;So;0;L;;;;;N;;;;; +2881;BRAILLE PATTERN DOTS-18;So;0;L;;;;;N;;;;; +2882;BRAILLE PATTERN DOTS-28;So;0;L;;;;;N;;;;; +2883;BRAILLE PATTERN DOTS-128;So;0;L;;;;;N;;;;; +2884;BRAILLE PATTERN DOTS-38;So;0;L;;;;;N;;;;; +2885;BRAILLE PATTERN DOTS-138;So;0;L;;;;;N;;;;; +2886;BRAILLE PATTERN DOTS-238;So;0;L;;;;;N;;;;; +2887;BRAILLE PATTERN DOTS-1238;So;0;L;;;;;N;;;;; +2888;BRAILLE PATTERN DOTS-48;So;0;L;;;;;N;;;;; +2889;BRAILLE PATTERN DOTS-148;So;0;L;;;;;N;;;;; +288A;BRAILLE PATTERN DOTS-248;So;0;L;;;;;N;;;;; +288B;BRAILLE PATTERN DOTS-1248;So;0;L;;;;;N;;;;; +288C;BRAILLE PATTERN DOTS-348;So;0;L;;;;;N;;;;; +288D;BRAILLE PATTERN DOTS-1348;So;0;L;;;;;N;;;;; +288E;BRAILLE PATTERN DOTS-2348;So;0;L;;;;;N;;;;; +288F;BRAILLE PATTERN DOTS-12348;So;0;L;;;;;N;;;;; +2890;BRAILLE PATTERN DOTS-58;So;0;L;;;;;N;;;;; +2891;BRAILLE PATTERN DOTS-158;So;0;L;;;;;N;;;;; +2892;BRAILLE PATTERN DOTS-258;So;0;L;;;;;N;;;;; +2893;BRAILLE PATTERN DOTS-1258;So;0;L;;;;;N;;;;; +2894;BRAILLE PATTERN DOTS-358;So;0;L;;;;;N;;;;; +2895;BRAILLE PATTERN DOTS-1358;So;0;L;;;;;N;;;;; +2896;BRAILLE PATTERN DOTS-2358;So;0;L;;;;;N;;;;; +2897;BRAILLE PATTERN DOTS-12358;So;0;L;;;;;N;;;;; +2898;BRAILLE PATTERN DOTS-458;So;0;L;;;;;N;;;;; +2899;BRAILLE PATTERN DOTS-1458;So;0;L;;;;;N;;;;; +289A;BRAILLE PATTERN DOTS-2458;So;0;L;;;;;N;;;;; +289B;BRAILLE PATTERN DOTS-12458;So;0;L;;;;;N;;;;; +289C;BRAILLE PATTERN DOTS-3458;So;0;L;;;;;N;;;;; +289D;BRAILLE PATTERN DOTS-13458;So;0;L;;;;;N;;;;; +289E;BRAILLE PATTERN DOTS-23458;So;0;L;;;;;N;;;;; +289F;BRAILLE PATTERN DOTS-123458;So;0;L;;;;;N;;;;; +28A0;BRAILLE PATTERN DOTS-68;So;0;L;;;;;N;;;;; +28A1;BRAILLE PATTERN DOTS-168;So;0;L;;;;;N;;;;; +28A2;BRAILLE PATTERN DOTS-268;So;0;L;;;;;N;;;;; +28A3;BRAILLE PATTERN DOTS-1268;So;0;L;;;;;N;;;;; +28A4;BRAILLE PATTERN DOTS-368;So;0;L;;;;;N;;;;; +28A5;BRAILLE PATTERN DOTS-1368;So;0;L;;;;;N;;;;; +28A6;BRAILLE PATTERN DOTS-2368;So;0;L;;;;;N;;;;; +28A7;BRAILLE PATTERN DOTS-12368;So;0;L;;;;;N;;;;; +28A8;BRAILLE PATTERN DOTS-468;So;0;L;;;;;N;;;;; +28A9;BRAILLE PATTERN DOTS-1468;So;0;L;;;;;N;;;;; +28AA;BRAILLE PATTERN DOTS-2468;So;0;L;;;;;N;;;;; +28AB;BRAILLE PATTERN DOTS-12468;So;0;L;;;;;N;;;;; +28AC;BRAILLE PATTERN DOTS-3468;So;0;L;;;;;N;;;;; +28AD;BRAILLE PATTERN DOTS-13468;So;0;L;;;;;N;;;;; +28AE;BRAILLE PATTERN DOTS-23468;So;0;L;;;;;N;;;;; +28AF;BRAILLE PATTERN DOTS-123468;So;0;L;;;;;N;;;;; +28B0;BRAILLE PATTERN DOTS-568;So;0;L;;;;;N;;;;; +28B1;BRAILLE PATTERN DOTS-1568;So;0;L;;;;;N;;;;; +28B2;BRAILLE PATTERN DOTS-2568;So;0;L;;;;;N;;;;; +28B3;BRAILLE PATTERN DOTS-12568;So;0;L;;;;;N;;;;; +28B4;BRAILLE PATTERN DOTS-3568;So;0;L;;;;;N;;;;; +28B5;BRAILLE PATTERN DOTS-13568;So;0;L;;;;;N;;;;; +28B6;BRAILLE PATTERN DOTS-23568;So;0;L;;;;;N;;;;; +28B7;BRAILLE PATTERN DOTS-123568;So;0;L;;;;;N;;;;; +28B8;BRAILLE PATTERN DOTS-4568;So;0;L;;;;;N;;;;; +28B9;BRAILLE PATTERN DOTS-14568;So;0;L;;;;;N;;;;; +28BA;BRAILLE PATTERN DOTS-24568;So;0;L;;;;;N;;;;; +28BB;BRAILLE PATTERN DOTS-124568;So;0;L;;;;;N;;;;; +28BC;BRAILLE PATTERN DOTS-34568;So;0;L;;;;;N;;;;; +28BD;BRAILLE PATTERN DOTS-134568;So;0;L;;;;;N;;;;; +28BE;BRAILLE PATTERN DOTS-234568;So;0;L;;;;;N;;;;; +28BF;BRAILLE PATTERN DOTS-1234568;So;0;L;;;;;N;;;;; +28C0;BRAILLE PATTERN DOTS-78;So;0;L;;;;;N;;;;; +28C1;BRAILLE PATTERN DOTS-178;So;0;L;;;;;N;;;;; +28C2;BRAILLE PATTERN DOTS-278;So;0;L;;;;;N;;;;; +28C3;BRAILLE PATTERN DOTS-1278;So;0;L;;;;;N;;;;; +28C4;BRAILLE PATTERN DOTS-378;So;0;L;;;;;N;;;;; +28C5;BRAILLE PATTERN DOTS-1378;So;0;L;;;;;N;;;;; +28C6;BRAILLE PATTERN DOTS-2378;So;0;L;;;;;N;;;;; +28C7;BRAILLE PATTERN DOTS-12378;So;0;L;;;;;N;;;;; +28C8;BRAILLE PATTERN DOTS-478;So;0;L;;;;;N;;;;; +28C9;BRAILLE PATTERN DOTS-1478;So;0;L;;;;;N;;;;; +28CA;BRAILLE PATTERN DOTS-2478;So;0;L;;;;;N;;;;; +28CB;BRAILLE PATTERN DOTS-12478;So;0;L;;;;;N;;;;; +28CC;BRAILLE PATTERN DOTS-3478;So;0;L;;;;;N;;;;; +28CD;BRAILLE PATTERN DOTS-13478;So;0;L;;;;;N;;;;; +28CE;BRAILLE PATTERN DOTS-23478;So;0;L;;;;;N;;;;; +28CF;BRAILLE PATTERN DOTS-123478;So;0;L;;;;;N;;;;; +28D0;BRAILLE PATTERN DOTS-578;So;0;L;;;;;N;;;;; +28D1;BRAILLE PATTERN DOTS-1578;So;0;L;;;;;N;;;;; +28D2;BRAILLE PATTERN DOTS-2578;So;0;L;;;;;N;;;;; +28D3;BRAILLE PATTERN DOTS-12578;So;0;L;;;;;N;;;;; +28D4;BRAILLE PATTERN DOTS-3578;So;0;L;;;;;N;;;;; +28D5;BRAILLE PATTERN DOTS-13578;So;0;L;;;;;N;;;;; +28D6;BRAILLE PATTERN DOTS-23578;So;0;L;;;;;N;;;;; +28D7;BRAILLE PATTERN DOTS-123578;So;0;L;;;;;N;;;;; +28D8;BRAILLE PATTERN DOTS-4578;So;0;L;;;;;N;;;;; +28D9;BRAILLE PATTERN DOTS-14578;So;0;L;;;;;N;;;;; +28DA;BRAILLE PATTERN DOTS-24578;So;0;L;;;;;N;;;;; +28DB;BRAILLE PATTERN DOTS-124578;So;0;L;;;;;N;;;;; +28DC;BRAILLE PATTERN DOTS-34578;So;0;L;;;;;N;;;;; +28DD;BRAILLE PATTERN DOTS-134578;So;0;L;;;;;N;;;;; +28DE;BRAILLE PATTERN DOTS-234578;So;0;L;;;;;N;;;;; +28DF;BRAILLE PATTERN DOTS-1234578;So;0;L;;;;;N;;;;; +28E0;BRAILLE PATTERN DOTS-678;So;0;L;;;;;N;;;;; +28E1;BRAILLE PATTERN DOTS-1678;So;0;L;;;;;N;;;;; +28E2;BRAILLE PATTERN DOTS-2678;So;0;L;;;;;N;;;;; +28E3;BRAILLE PATTERN DOTS-12678;So;0;L;;;;;N;;;;; +28E4;BRAILLE PATTERN DOTS-3678;So;0;L;;;;;N;;;;; +28E5;BRAILLE PATTERN DOTS-13678;So;0;L;;;;;N;;;;; +28E6;BRAILLE PATTERN DOTS-23678;So;0;L;;;;;N;;;;; +28E7;BRAILLE PATTERN DOTS-123678;So;0;L;;;;;N;;;;; +28E8;BRAILLE PATTERN DOTS-4678;So;0;L;;;;;N;;;;; +28E9;BRAILLE PATTERN DOTS-14678;So;0;L;;;;;N;;;;; +28EA;BRAILLE PATTERN DOTS-24678;So;0;L;;;;;N;;;;; +28EB;BRAILLE PATTERN DOTS-124678;So;0;L;;;;;N;;;;; +28EC;BRAILLE PATTERN DOTS-34678;So;0;L;;;;;N;;;;; +28ED;BRAILLE PATTERN DOTS-134678;So;0;L;;;;;N;;;;; +28EE;BRAILLE PATTERN DOTS-234678;So;0;L;;;;;N;;;;; +28EF;BRAILLE PATTERN DOTS-1234678;So;0;L;;;;;N;;;;; +28F0;BRAILLE PATTERN DOTS-5678;So;0;L;;;;;N;;;;; +28F1;BRAILLE PATTERN DOTS-15678;So;0;L;;;;;N;;;;; +28F2;BRAILLE PATTERN DOTS-25678;So;0;L;;;;;N;;;;; +28F3;BRAILLE PATTERN DOTS-125678;So;0;L;;;;;N;;;;; +28F4;BRAILLE PATTERN DOTS-35678;So;0;L;;;;;N;;;;; +28F5;BRAILLE PATTERN DOTS-135678;So;0;L;;;;;N;;;;; +28F6;BRAILLE PATTERN DOTS-235678;So;0;L;;;;;N;;;;; +28F7;BRAILLE PATTERN DOTS-1235678;So;0;L;;;;;N;;;;; +28F8;BRAILLE PATTERN DOTS-45678;So;0;L;;;;;N;;;;; +28F9;BRAILLE PATTERN DOTS-145678;So;0;L;;;;;N;;;;; +28FA;BRAILLE PATTERN DOTS-245678;So;0;L;;;;;N;;;;; +28FB;BRAILLE PATTERN DOTS-1245678;So;0;L;;;;;N;;;;; +28FC;BRAILLE PATTERN DOTS-345678;So;0;L;;;;;N;;;;; +28FD;BRAILLE PATTERN DOTS-1345678;So;0;L;;;;;N;;;;; +28FE;BRAILLE PATTERN DOTS-2345678;So;0;L;;;;;N;;;;; +28FF;BRAILLE PATTERN DOTS-12345678;So;0;L;;;;;N;;;;; +2900;RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2901;RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2902;LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2903;RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2904;LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2905;RIGHTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2906;LEFTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2907;RIGHTWARDS DOUBLE ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2908;DOWNWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2909;UPWARDS ARROW WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +290A;UPWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; +290B;DOWNWARDS TRIPLE ARROW;Sm;0;ON;;;;;N;;;;; +290C;LEFTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290D;RIGHTWARDS DOUBLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290E;LEFTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +290F;RIGHTWARDS TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2910;RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2911;RIGHTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; +2912;UPWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; +2913;DOWNWARDS ARROW TO BAR;Sm;0;ON;;;;;N;;;;; +2914;RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2915;RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2916;RIGHTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; +2917;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2918;RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2919;LEFTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291A;RIGHTWARDS ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291B;LEFTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291C;RIGHTWARDS DOUBLE ARROW-TAIL;Sm;0;ON;;;;;N;;;;; +291D;LEFTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +291E;RIGHTWARDS ARROW TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +291F;LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +2920;RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +2921;NORTH WEST AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2922;NORTH EAST AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +2923;NORTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2924;NORTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2925;SOUTH EAST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2926;SOUTH WEST ARROW WITH HOOK;Sm;0;ON;;;;;N;;;;; +2927;NORTH WEST ARROW AND NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2928;NORTH EAST ARROW AND SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2929;SOUTH EAST ARROW AND SOUTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +292A;SOUTH WEST ARROW AND NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +292B;RISING DIAGONAL CROSSING FALLING DIAGONAL;Sm;0;ON;;;;;N;;;;; +292C;FALLING DIAGONAL CROSSING RISING DIAGONAL;Sm;0;ON;;;;;N;;;;; +292D;SOUTH EAST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +292E;NORTH EAST ARROW CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +292F;FALLING DIAGONAL CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2930;RISING DIAGONAL CROSSING SOUTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2931;NORTH EAST ARROW CROSSING NORTH WEST ARROW;Sm;0;ON;;;;;N;;;;; +2932;NORTH WEST ARROW CROSSING NORTH EAST ARROW;Sm;0;ON;;;;;N;;;;; +2933;WAVE ARROW POINTING DIRECTLY RIGHT;Sm;0;ON;;;;;N;;;;; +2934;ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS;Sm;0;ON;;;;;N;;;;; +2935;ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS;Sm;0;ON;;;;;N;;;;; +2936;ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS;Sm;0;ON;;;;;N;;;;; +2937;ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS;Sm;0;ON;;;;;N;;;;; +2938;RIGHT-SIDE ARC CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +2939;LEFT-SIDE ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293A;TOP ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293B;BOTTOM ARC ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293C;TOP ARC CLOCKWISE ARROW WITH MINUS;Sm;0;ON;;;;;N;;;;; +293D;TOP ARC ANTICLOCKWISE ARROW WITH PLUS;Sm;0;ON;;;;;N;;;;; +293E;LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +293F;LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW;Sm;0;ON;;;;;N;;;;; +2940;ANTICLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +2941;CLOCKWISE CLOSED CIRCLE ARROW;Sm;0;ON;;;;;N;;;;; +2942;RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2943;LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2944;SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2945;RIGHTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; +2946;LEFTWARDS ARROW WITH PLUS BELOW;Sm;0;ON;;;;;N;;;;; +2947;RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; +2948;LEFT RIGHT ARROW THROUGH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +2949;UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +294A;LEFT BARB UP RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; +294B;LEFT BARB DOWN RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; +294C;UP BARB RIGHT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; +294D;UP BARB LEFT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; +294E;LEFT BARB UP RIGHT BARB UP HARPOON;Sm;0;ON;;;;;N;;;;; +294F;UP BARB RIGHT DOWN BARB RIGHT HARPOON;Sm;0;ON;;;;;N;;;;; +2950;LEFT BARB DOWN RIGHT BARB DOWN HARPOON;Sm;0;ON;;;;;N;;;;; +2951;UP BARB LEFT DOWN BARB LEFT HARPOON;Sm;0;ON;;;;;N;;;;; +2952;LEFTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; +2953;RIGHTWARDS HARPOON WITH BARB UP TO BAR;Sm;0;ON;;;;;N;;;;; +2954;UPWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; +2955;DOWNWARDS HARPOON WITH BARB RIGHT TO BAR;Sm;0;ON;;;;;N;;;;; +2956;LEFTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; +2957;RIGHTWARDS HARPOON WITH BARB DOWN TO BAR;Sm;0;ON;;;;;N;;;;; +2958;UPWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; +2959;DOWNWARDS HARPOON WITH BARB LEFT TO BAR;Sm;0;ON;;;;;N;;;;; +295A;LEFTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; +295B;RIGHTWARDS HARPOON WITH BARB UP FROM BAR;Sm;0;ON;;;;;N;;;;; +295C;UPWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; +295D;DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR;Sm;0;ON;;;;;N;;;;; +295E;LEFTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; +295F;RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR;Sm;0;ON;;;;;N;;;;; +2960;UPWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; +2961;DOWNWARDS HARPOON WITH BARB LEFT FROM BAR;Sm;0;ON;;;;;N;;;;; +2962;LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2963;UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2964;RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2965;DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2966;LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; +2967;LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +2968;RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP;Sm;0;ON;;;;;N;;;;; +2969;RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN;Sm;0;ON;;;;;N;;;;; +296A;LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; +296B;LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; +296C;RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH;Sm;0;ON;;;;;N;;;;; +296D;RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH;Sm;0;ON;;;;;N;;;;; +296E;UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +296F;DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT;Sm;0;ON;;;;;N;;;;; +2970;RIGHT DOUBLE ARROW WITH ROUNDED HEAD;Sm;0;ON;;;;;N;;;;; +2971;EQUALS SIGN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2972;TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2973;LEFTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2974;RIGHTWARDS ARROW ABOVE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2975;RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2976;LESS-THAN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2977;LEFTWARDS ARROW THROUGH LESS-THAN;Sm;0;ON;;;;;N;;;;; +2978;GREATER-THAN ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2979;SUBSET ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +297A;LEFTWARDS ARROW THROUGH SUBSET;Sm;0;ON;;;;;N;;;;; +297B;SUPERSET ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +297C;LEFT FISH TAIL;Sm;0;ON;;;;;N;;;;; +297D;RIGHT FISH TAIL;Sm;0;ON;;;;;N;;;;; +297E;UP FISH TAIL;Sm;0;ON;;;;;N;;;;; +297F;DOWN FISH TAIL;Sm;0;ON;;;;;N;;;;; +2980;TRIPLE VERTICAL BAR DELIMITER;Sm;0;ON;;;;;N;;;;; +2981;Z NOTATION SPOT;Sm;0;ON;;;;;N;;;;; +2982;Z NOTATION TYPE COLON;Sm;0;ON;;;;;N;;;;; +2983;LEFT WHITE CURLY BRACKET;Ps;0;ON;;;;;Y;;;;; +2984;RIGHT WHITE CURLY BRACKET;Pe;0;ON;;;;;Y;;;;; +2985;LEFT WHITE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2986;RIGHT WHITE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2987;Z NOTATION LEFT IMAGE BRACKET;Ps;0;ON;;;;;Y;;;;; +2988;Z NOTATION RIGHT IMAGE BRACKET;Pe;0;ON;;;;;Y;;;;; +2989;Z NOTATION LEFT BINDING BRACKET;Ps;0;ON;;;;;Y;;;;; +298A;Z NOTATION RIGHT BINDING BRACKET;Pe;0;ON;;;;;Y;;;;; +298B;LEFT SQUARE BRACKET WITH UNDERBAR;Ps;0;ON;;;;;Y;;;;; +298C;RIGHT SQUARE BRACKET WITH UNDERBAR;Pe;0;ON;;;;;Y;;;;; +298D;LEFT SQUARE BRACKET WITH TICK IN TOP CORNER;Ps;0;ON;;;;;Y;;;;; +298E;RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Pe;0;ON;;;;;Y;;;;; +298F;LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER;Ps;0;ON;;;;;Y;;;;; +2990;RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER;Pe;0;ON;;;;;Y;;;;; +2991;LEFT ANGLE BRACKET WITH DOT;Ps;0;ON;;;;;Y;;;;; +2992;RIGHT ANGLE BRACKET WITH DOT;Pe;0;ON;;;;;Y;;;;; +2993;LEFT ARC LESS-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; +2994;RIGHT ARC GREATER-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; +2995;DOUBLE LEFT ARC GREATER-THAN BRACKET;Ps;0;ON;;;;;Y;;;;; +2996;DOUBLE RIGHT ARC LESS-THAN BRACKET;Pe;0;ON;;;;;Y;;;;; +2997;LEFT BLACK TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;;;;; +2998;RIGHT BLACK TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;;;;; +2999;DOTTED FENCE;Sm;0;ON;;;;;N;;;;; +299A;VERTICAL ZIGZAG LINE;Sm;0;ON;;;;;N;;;;; +299B;MEASURED ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; +299C;RIGHT ANGLE VARIANT WITH SQUARE;Sm;0;ON;;;;;Y;;;;; +299D;MEASURED RIGHT ANGLE WITH DOT;Sm;0;ON;;;;;Y;;;;; +299E;ANGLE WITH S INSIDE;Sm;0;ON;;;;;Y;;;;; +299F;ACUTE ANGLE;Sm;0;ON;;;;;Y;;;;; +29A0;SPHERICAL ANGLE OPENING LEFT;Sm;0;ON;;;;;Y;;;;; +29A1;SPHERICAL ANGLE OPENING UP;Sm;0;ON;;;;;N;;;;; +29A2;TURNED ANGLE;Sm;0;ON;;;;;Y;;;;; +29A3;REVERSED ANGLE;Sm;0;ON;;;;;Y;;;;; +29A4;ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +29A5;REVERSED ANGLE WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +29A6;OBLIQUE ANGLE OPENING UP;Sm;0;ON;;;;;Y;;;;; +29A7;OBLIQUE ANGLE OPENING DOWN;Sm;0;ON;;;;;Y;;;;; +29A8;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT;Sm;0;ON;;;;;Y;;;;; +29A9;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT;Sm;0;ON;;;;;Y;;;;; +29AA;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT;Sm;0;ON;;;;;Y;;;;; +29AB;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT;Sm;0;ON;;;;;Y;;;;; +29AC;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP;Sm;0;ON;;;;;Y;;;;; +29AD;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP;Sm;0;ON;;;;;Y;;;;; +29AE;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN;Sm;0;ON;;;;;Y;;;;; +29AF;MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN;Sm;0;ON;;;;;Y;;;;; +29B0;REVERSED EMPTY SET;Sm;0;ON;;;;;N;;;;; +29B1;EMPTY SET WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +29B2;EMPTY SET WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +29B3;EMPTY SET WITH RIGHT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; +29B4;EMPTY SET WITH LEFT ARROW ABOVE;Sm;0;ON;;;;;N;;;;; +29B5;CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; +29B6;CIRCLED VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29B7;CIRCLED PARALLEL;Sm;0;ON;;;;;N;;;;; +29B8;CIRCLED REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29B9;CIRCLED PERPENDICULAR;Sm;0;ON;;;;;N;;;;; +29BA;CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29BB;CIRCLE WITH SUPERIMPOSED X;Sm;0;ON;;;;;N;;;;; +29BC;CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +29BD;UP ARROW THROUGH CIRCLE;Sm;0;ON;;;;;N;;;;; +29BE;CIRCLED WHITE BULLET;Sm;0;ON;;;;;N;;;;; +29BF;CIRCLED BULLET;Sm;0;ON;;;;;N;;;;; +29C0;CIRCLED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +29C1;CIRCLED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +29C2;CIRCLE WITH SMALL CIRCLE TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; +29C3;CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT;Sm;0;ON;;;;;Y;;;;; +29C4;SQUARED RISING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; +29C5;SQUARED FALLING DIAGONAL SLASH;Sm;0;ON;;;;;Y;;;;; +29C6;SQUARED ASTERISK;Sm;0;ON;;;;;N;;;;; +29C7;SQUARED SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +29C8;SQUARED SQUARE;Sm;0;ON;;;;;N;;;;; +29C9;TWO JOINED SQUARES;Sm;0;ON;;;;;Y;;;;; +29CA;TRIANGLE WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +29CB;TRIANGLE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +29CC;S IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +29CD;TRIANGLE WITH SERIFS AT BOTTOM;Sm;0;ON;;;;;N;;;;; +29CE;RIGHT TRIANGLE ABOVE LEFT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +29CF;LEFT TRIANGLE BESIDE VERTICAL BAR;Sm;0;ON;;;;;Y;;;;; +29D0;VERTICAL BAR BESIDE RIGHT TRIANGLE;Sm;0;ON;;;;;Y;;;;; +29D1;BOWTIE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D2;BOWTIE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D3;BLACK BOWTIE;Sm;0;ON;;;;;N;;;;; +29D4;TIMES WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D5;TIMES WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29D6;WHITE HOURGLASS;Sm;0;ON;;;;;N;;;;; +29D7;BLACK HOURGLASS;Sm;0;ON;;;;;N;;;;; +29D8;LEFT WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; +29D9;RIGHT WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; +29DA;LEFT DOUBLE WIGGLY FENCE;Ps;0;ON;;;;;Y;;;;; +29DB;RIGHT DOUBLE WIGGLY FENCE;Pe;0;ON;;;;;Y;;;;; +29DC;INCOMPLETE INFINITY;Sm;0;ON;;;;;Y;;;;; +29DD;TIE OVER INFINITY;Sm;0;ON;;;;;N;;;;; +29DE;INFINITY NEGATED WITH VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +29DF;DOUBLE-ENDED MULTIMAP;Sm;0;ON;;;;;N;;;;; +29E0;SQUARE WITH CONTOURED OUTLINE;Sm;0;ON;;;;;N;;;;; +29E1;INCREASES AS;Sm;0;ON;;;;;Y;;;;; +29E2;SHUFFLE PRODUCT;Sm;0;ON;;;;;N;;;;; +29E3;EQUALS SIGN AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; +29E4;EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; +29E5;IDENTICAL TO AND SLANTED PARALLEL;Sm;0;ON;;;;;Y;;;;; +29E6;GLEICH STARK;Sm;0;ON;;;;;N;;;;; +29E7;THERMODYNAMIC;Sm;0;ON;;;;;N;;;;; +29E8;DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29E9;DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK;Sm;0;ON;;;;;Y;;;;; +29EA;BLACK DIAMOND WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29EB;BLACK LOZENGE;Sm;0;ON;;;;;N;;;;; +29EC;WHITE CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29ED;BLACK CIRCLE WITH DOWN ARROW;Sm;0;ON;;;;;N;;;;; +29EE;ERROR-BARRED WHITE SQUARE;Sm;0;ON;;;;;N;;;;; +29EF;ERROR-BARRED BLACK SQUARE;Sm;0;ON;;;;;N;;;;; +29F0;ERROR-BARRED WHITE DIAMOND;Sm;0;ON;;;;;N;;;;; +29F1;ERROR-BARRED BLACK DIAMOND;Sm;0;ON;;;;;N;;;;; +29F2;ERROR-BARRED WHITE CIRCLE;Sm;0;ON;;;;;N;;;;; +29F3;ERROR-BARRED BLACK CIRCLE;Sm;0;ON;;;;;N;;;;; +29F4;RULE-DELAYED;Sm;0;ON;;;;;Y;;;;; +29F5;REVERSE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; +29F6;SOLIDUS WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +29F7;REVERSE SOLIDUS WITH HORIZONTAL STROKE;Sm;0;ON;;;;;Y;;;;; +29F8;BIG SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29F9;BIG REVERSE SOLIDUS;Sm;0;ON;;;;;Y;;;;; +29FA;DOUBLE PLUS;Sm;0;ON;;;;;N;;;;; +29FB;TRIPLE PLUS;Sm;0;ON;;;;;N;;;;; +29FC;LEFT-POINTING CURVED ANGLE BRACKET;Ps;0;ON;;;;;Y;;;;; +29FD;RIGHT-POINTING CURVED ANGLE BRACKET;Pe;0;ON;;;;;Y;;;;; +29FE;TINY;Sm;0;ON;;;;;N;;;;; +29FF;MINY;Sm;0;ON;;;;;N;;;;; +2A00;N-ARY CIRCLED DOT OPERATOR;Sm;0;ON;;;;;N;;;;; +2A01;N-ARY CIRCLED PLUS OPERATOR;Sm;0;ON;;;;;N;;;;; +2A02;N-ARY CIRCLED TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; +2A03;N-ARY UNION OPERATOR WITH DOT;Sm;0;ON;;;;;N;;;;; +2A04;N-ARY UNION OPERATOR WITH PLUS;Sm;0;ON;;;;;N;;;;; +2A05;N-ARY SQUARE INTERSECTION OPERATOR;Sm;0;ON;;;;;N;;;;; +2A06;N-ARY SQUARE UNION OPERATOR;Sm;0;ON;;;;;N;;;;; +2A07;TWO LOGICAL AND OPERATOR;Sm;0;ON;;;;;N;;;;; +2A08;TWO LOGICAL OR OPERATOR;Sm;0;ON;;;;;N;;;;; +2A09;N-ARY TIMES OPERATOR;Sm;0;ON;;;;;N;;;;; +2A0A;MODULO TWO SUM;Sm;0;ON;;;;;Y;;;;; +2A0B;SUMMATION WITH INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2A0C;QUADRUPLE INTEGRAL OPERATOR;Sm;0;ON; 222B 222B 222B 222B;;;;Y;;;;; +2A0D;FINITE PART INTEGRAL;Sm;0;ON;;;;;Y;;;;; +2A0E;INTEGRAL WITH DOUBLE STROKE;Sm;0;ON;;;;;Y;;;;; +2A0F;INTEGRAL AVERAGE WITH SLASH;Sm;0;ON;;;;;Y;;;;; +2A10;CIRCULATION FUNCTION;Sm;0;ON;;;;;Y;;;;; +2A11;ANTICLOCKWISE INTEGRATION;Sm;0;ON;;;;;Y;;;;; +2A12;LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; +2A13;LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE;Sm;0;ON;;;;;Y;;;;; +2A14;LINE INTEGRATION NOT INCLUDING THE POLE;Sm;0;ON;;;;;Y;;;;; +2A15;INTEGRAL AROUND A POINT OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A16;QUATERNION INTEGRAL OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A17;INTEGRAL WITH LEFTWARDS ARROW WITH HOOK;Sm;0;ON;;;;;Y;;;;; +2A18;INTEGRAL WITH TIMES SIGN;Sm;0;ON;;;;;Y;;;;; +2A19;INTEGRAL WITH INTERSECTION;Sm;0;ON;;;;;Y;;;;; +2A1A;INTEGRAL WITH UNION;Sm;0;ON;;;;;Y;;;;; +2A1B;INTEGRAL WITH OVERBAR;Sm;0;ON;;;;;Y;;;;; +2A1C;INTEGRAL WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +2A1D;JOIN;Sm;0;ON;;;;;N;;;;; +2A1E;LARGE LEFT TRIANGLE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A1F;Z NOTATION SCHEMA COMPOSITION;Sm;0;ON;;;;;Y;;;;; +2A20;Z NOTATION SCHEMA PIPING;Sm;0;ON;;;;;Y;;;;; +2A21;Z NOTATION SCHEMA PROJECTION;Sm;0;ON;;;;;Y;;;;; +2A22;PLUS SIGN WITH SMALL CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +2A23;PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE;Sm;0;ON;;;;;N;;;;; +2A24;PLUS SIGN WITH TILDE ABOVE;Sm;0;ON;;;;;Y;;;;; +2A25;PLUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A26;PLUS SIGN WITH TILDE BELOW;Sm;0;ON;;;;;Y;;;;; +2A27;PLUS SIGN WITH SUBSCRIPT TWO;Sm;0;ON;;;;;N;;;;; +2A28;PLUS SIGN WITH BLACK TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A29;MINUS SIGN WITH COMMA ABOVE;Sm;0;ON;;;;;Y;;;;; +2A2A;MINUS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A2B;MINUS SIGN WITH FALLING DOTS;Sm;0;ON;;;;;Y;;;;; +2A2C;MINUS SIGN WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; +2A2D;PLUS SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A2E;PLUS SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A2F;VECTOR OR CROSS PRODUCT;Sm;0;ON;;;;;N;;;;; +2A30;MULTIPLICATION SIGN WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A31;MULTIPLICATION SIGN WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A32;SEMIDIRECT PRODUCT WITH BOTTOM CLOSED;Sm;0;ON;;;;;N;;;;; +2A33;SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; +2A34;MULTIPLICATION SIGN IN LEFT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A35;MULTIPLICATION SIGN IN RIGHT HALF CIRCLE;Sm;0;ON;;;;;Y;;;;; +2A36;CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;N;;;;; +2A37;MULTIPLICATION SIGN IN DOUBLE CIRCLE;Sm;0;ON;;;;;N;;;;; +2A38;CIRCLED DIVISION SIGN;Sm;0;ON;;;;;N;;;;; +2A39;PLUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3A;MINUS SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3B;MULTIPLICATION SIGN IN TRIANGLE;Sm;0;ON;;;;;N;;;;; +2A3C;INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; +2A3D;RIGHTHAND INTERIOR PRODUCT;Sm;0;ON;;;;;Y;;;;; +2A3E;Z NOTATION RELATIONAL COMPOSITION;Sm;0;ON;;;;;Y;;;;; +2A3F;AMALGAMATION OR COPRODUCT;Sm;0;ON;;;;;N;;;;; +2A40;INTERSECTION WITH DOT;Sm;0;ON;;;;;N;;;;; +2A41;UNION WITH MINUS SIGN;Sm;0;ON;;;;;N;;;;; +2A42;UNION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2A43;INTERSECTION WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2A44;INTERSECTION WITH LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A45;UNION WITH LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A46;UNION ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A47;INTERSECTION ABOVE UNION;Sm;0;ON;;;;;N;;;;; +2A48;UNION ABOVE BAR ABOVE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A49;INTERSECTION ABOVE BAR ABOVE UNION;Sm;0;ON;;;;;N;;;;; +2A4A;UNION BESIDE AND JOINED WITH UNION;Sm;0;ON;;;;;N;;;;; +2A4B;INTERSECTION BESIDE AND JOINED WITH INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A4C;CLOSED UNION WITH SERIFS;Sm;0;ON;;;;;N;;;;; +2A4D;CLOSED INTERSECTION WITH SERIFS;Sm;0;ON;;;;;N;;;;; +2A4E;DOUBLE SQUARE INTERSECTION;Sm;0;ON;;;;;N;;;;; +2A4F;DOUBLE SQUARE UNION;Sm;0;ON;;;;;N;;;;; +2A50;CLOSED UNION WITH SERIFS AND SMASH PRODUCT;Sm;0;ON;;;;;N;;;;; +2A51;LOGICAL AND WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A52;LOGICAL OR WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A53;DOUBLE LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A54;DOUBLE LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A55;TWO INTERSECTING LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A56;TWO INTERSECTING LOGICAL OR;Sm;0;ON;;;;;N;;;;; +2A57;SLOPING LARGE OR;Sm;0;ON;;;;;Y;;;;; +2A58;SLOPING LARGE AND;Sm;0;ON;;;;;Y;;;;; +2A59;LOGICAL OR OVERLAPPING LOGICAL AND;Sm;0;ON;;;;;N;;;;; +2A5A;LOGICAL AND WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; +2A5B;LOGICAL OR WITH MIDDLE STEM;Sm;0;ON;;;;;N;;;;; +2A5C;LOGICAL AND WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; +2A5D;LOGICAL OR WITH HORIZONTAL DASH;Sm;0;ON;;;;;N;;;;; +2A5E;LOGICAL AND WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; +2A5F;LOGICAL AND WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A60;LOGICAL AND WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A61;SMALL VEE WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A62;LOGICAL OR WITH DOUBLE OVERBAR;Sm;0;ON;;;;;N;;;;; +2A63;LOGICAL OR WITH DOUBLE UNDERBAR;Sm;0;ON;;;;;N;;;;; +2A64;Z NOTATION DOMAIN ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; +2A65;Z NOTATION RANGE ANTIRESTRICTION;Sm;0;ON;;;;;Y;;;;; +2A66;EQUALS SIGN WITH DOT BELOW;Sm;0;ON;;;;;N;;;;; +2A67;IDENTICAL WITH DOT ABOVE;Sm;0;ON;;;;;N;;;;; +2A68;TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2A69;TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2A6A;TILDE OPERATOR WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A6B;TILDE OPERATOR WITH RISING DOTS;Sm;0;ON;;;;;Y;;;;; +2A6C;SIMILAR MINUS SIMILAR;Sm;0;ON;;;;;Y;;;;; +2A6D;CONGRUENT WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A6E;EQUALS WITH ASTERISK;Sm;0;ON;;;;;N;;;;; +2A6F;ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT;Sm;0;ON;;;;;Y;;;;; +2A70;APPROXIMATELY EQUAL OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A71;EQUALS SIGN ABOVE PLUS SIGN;Sm;0;ON;;;;;N;;;;; +2A72;PLUS SIGN ABOVE EQUALS SIGN;Sm;0;ON;;;;;N;;;;; +2A73;EQUALS SIGN ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2A74;DOUBLE COLON EQUAL;Sm;0;ON; 003A 003A 003D;;;;Y;;;;; +2A75;TWO CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D;;;;N;;;;; +2A76;THREE CONSECUTIVE EQUALS SIGNS;Sm;0;ON; 003D 003D 003D;;;;N;;;;; +2A77;EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW;Sm;0;ON;;;;;N;;;;; +2A78;EQUIVALENT WITH FOUR DOTS ABOVE;Sm;0;ON;;;;;N;;;;; +2A79;LESS-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; +2A7A;GREATER-THAN WITH CIRCLE INSIDE;Sm;0;ON;;;;;Y;;;;; +2A7B;LESS-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; +2A7C;GREATER-THAN WITH QUESTION MARK ABOVE;Sm;0;ON;;;;;Y;;;;; +2A7D;LESS-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A7E;GREATER-THAN OR SLANTED EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A7F;LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A80;GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A81;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A82;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2A83;LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT;Sm;0;ON;;;;;Y;;;;; +2A84;GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT;Sm;0;ON;;;;;Y;;;;; +2A85;LESS-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A86;GREATER-THAN OR APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A87;LESS-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A88;GREATER-THAN AND SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2A89;LESS-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A8A;GREATER-THAN AND NOT APPROXIMATE;Sm;0;ON;;;;;Y;;;;; +2A8B;LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A8C;GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A8D;LESS-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; +2A8E;GREATER-THAN ABOVE SIMILAR OR EQUAL;Sm;0;ON;;;;;Y;;;;; +2A8F;LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A90;GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A91;LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; +2A92;GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL;Sm;0;ON;;;;;Y;;;;; +2A93;LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2A94;GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2A95;SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A96;SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A97;SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A98;SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE;Sm;0;ON;;;;;Y;;;;; +2A99;DOUBLE-LINE EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9A;DOUBLE-LINE EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9B;DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9C;DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9D;SIMILAR OR LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2A9E;SIMILAR OR GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2A9F;SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AA0;SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AA1;DOUBLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2AA2;DOUBLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2AA3;DOUBLE NESTED LESS-THAN WITH UNDERBAR;Sm;0;ON;;;;;Y;;;;; +2AA4;GREATER-THAN OVERLAPPING LESS-THAN;Sm;0;ON;;;;;N;;;;; +2AA5;GREATER-THAN BESIDE LESS-THAN;Sm;0;ON;;;;;N;;;;; +2AA6;LESS-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; +2AA7;GREATER-THAN CLOSED BY CURVE;Sm;0;ON;;;;;Y;;;;; +2AA8;LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2AA9;GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL;Sm;0;ON;;;;;Y;;;;; +2AAA;SMALLER THAN;Sm;0;ON;;;;;Y;;;;; +2AAB;LARGER THAN;Sm;0;ON;;;;;Y;;;;; +2AAC;SMALLER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AAD;LARGER THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AAE;EQUALS SIGN WITH BUMPY ABOVE;Sm;0;ON;;;;;N;;;;; +2AAF;PRECEDES ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB0;SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB1;PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB2;SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB3;PRECEDES ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB4;SUCCEEDS ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AB5;PRECEDES ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB6;SUCCEEDS ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB7;PRECEDES ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB8;SUCCEEDS ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AB9;PRECEDES ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ABA;SUCCEEDS ABOVE NOT ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ABB;DOUBLE PRECEDES;Sm;0;ON;;;;;Y;;;;; +2ABC;DOUBLE SUCCEEDS;Sm;0;ON;;;;;Y;;;;; +2ABD;SUBSET WITH DOT;Sm;0;ON;;;;;Y;;;;; +2ABE;SUPERSET WITH DOT;Sm;0;ON;;;;;Y;;;;; +2ABF;SUBSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC0;SUPERSET WITH PLUS SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC1;SUBSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC2;SUPERSET WITH MULTIPLICATION SIGN BELOW;Sm;0;ON;;;;;Y;;;;; +2AC3;SUBSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2AC4;SUPERSET OF OR EQUAL TO WITH DOT ABOVE;Sm;0;ON;;;;;Y;;;;; +2AC5;SUBSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AC6;SUPERSET OF ABOVE EQUALS SIGN;Sm;0;ON;;;;;Y;;;;; +2AC7;SUBSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AC8;SUPERSET OF ABOVE TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AC9;SUBSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACA;SUPERSET OF ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACB;SUBSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACC;SUPERSET OF ABOVE NOT EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2ACD;SQUARE LEFT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; +2ACE;SQUARE RIGHT OPEN BOX OPERATOR;Sm;0;ON;;;;;Y;;;;; +2ACF;CLOSED SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD0;CLOSED SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD1;CLOSED SUBSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AD2;CLOSED SUPERSET OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AD3;SUBSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD4;SUPERSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD5;SUBSET ABOVE SUBSET;Sm;0;ON;;;;;Y;;;;; +2AD6;SUPERSET ABOVE SUPERSET;Sm;0;ON;;;;;Y;;;;; +2AD7;SUPERSET BESIDE SUBSET;Sm;0;ON;;;;;N;;;;; +2AD8;SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET;Sm;0;ON;;;;;N;;;;; +2AD9;ELEMENT OF OPENING DOWNWARDS;Sm;0;ON;;;;;N;;;;; +2ADA;PITCHFORK WITH TEE TOP;Sm;0;ON;;;;;N;;;;; +2ADB;TRANSVERSAL INTERSECTION;Sm;0;ON;;;;;N;;;;; +2ADC;FORKING;Sm;0;ON;2ADD 0338;;;;Y;;;;; +2ADD;NONFORKING;Sm;0;ON;;;;;N;;;;; +2ADE;SHORT LEFT TACK;Sm;0;ON;;;;;Y;;;;; +2ADF;SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AE0;SHORT UP TACK;Sm;0;ON;;;;;N;;;;; +2AE1;PERPENDICULAR WITH S;Sm;0;ON;;;;;N;;;;; +2AE2;VERTICAL BAR TRIPLE RIGHT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE3;DOUBLE VERTICAL BAR LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE4;VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE5;DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE;Sm;0;ON;;;;;Y;;;;; +2AE6;LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL;Sm;0;ON;;;;;Y;;;;; +2AE7;SHORT DOWN TACK WITH OVERBAR;Sm;0;ON;;;;;N;;;;; +2AE8;SHORT UP TACK WITH UNDERBAR;Sm;0;ON;;;;;N;;;;; +2AE9;SHORT UP TACK ABOVE SHORT DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AEA;DOUBLE DOWN TACK;Sm;0;ON;;;;;N;;;;; +2AEB;DOUBLE UP TACK;Sm;0;ON;;;;;N;;;;; +2AEC;DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; +2AED;REVERSED DOUBLE STROKE NOT SIGN;Sm;0;ON;;;;;Y;;;;; +2AEE;DOES NOT DIVIDE WITH REVERSED NEGATION SLASH;Sm;0;ON;;;;;Y;;;;; +2AEF;VERTICAL LINE WITH CIRCLE ABOVE;Sm;0;ON;;;;;N;;;;; +2AF0;VERTICAL LINE WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; +2AF1;DOWN TACK WITH CIRCLE BELOW;Sm;0;ON;;;;;N;;;;; +2AF2;PARALLEL WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2AF3;PARALLEL WITH TILDE OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AF4;TRIPLE VERTICAL BAR BINARY RELATION;Sm;0;ON;;;;;N;;;;; +2AF5;TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; +2AF6;TRIPLE COLON OPERATOR;Sm;0;ON;;;;;N;;;;; +2AF7;TRIPLE NESTED LESS-THAN;Sm;0;ON;;;;;Y;;;;; +2AF8;TRIPLE NESTED GREATER-THAN;Sm;0;ON;;;;;Y;;;;; +2AF9;DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AFA;DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO;Sm;0;ON;;;;;Y;;;;; +2AFB;TRIPLE SOLIDUS BINARY RELATION;Sm;0;ON;;;;;Y;;;;; +2AFC;LARGE TRIPLE VERTICAL BAR OPERATOR;Sm;0;ON;;;;;N;;;;; +2AFD;DOUBLE SOLIDUS OPERATOR;Sm;0;ON;;;;;Y;;;;; +2AFE;WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +2AFF;N-ARY WHITE VERTICAL BAR;Sm;0;ON;;;;;N;;;;; +2B00;NORTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B01;NORTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B02;SOUTH EAST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B03;SOUTH WEST WHITE ARROW;So;0;ON;;;;;N;;;;; +2B04;LEFT RIGHT WHITE ARROW;So;0;ON;;;;;N;;;;; +2B05;LEFTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B06;UPWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B07;DOWNWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B08;NORTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B09;NORTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0A;SOUTH EAST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0B;SOUTH WEST BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0C;LEFT RIGHT BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0D;UP DOWN BLACK ARROW;So;0;ON;;;;;N;;;;; +2B0E;RIGHTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2B0F;RIGHTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; +2B10;LEFTWARDS ARROW WITH TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2B11;LEFTWARDS ARROW WITH TIP UPWARDS;So;0;ON;;;;;N;;;;; +2B12;SQUARE WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; +2B13;SQUARE WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; +2B14;SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +2B15;SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK;So;0;ON;;;;;N;;;;; +2B16;DIAMOND WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +2B17;DIAMOND WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +2B18;DIAMOND WITH TOP HALF BLACK;So;0;ON;;;;;N;;;;; +2B19;DIAMOND WITH BOTTOM HALF BLACK;So;0;ON;;;;;N;;;;; +2B1A;DOTTED SQUARE;So;0;ON;;;;;N;;;;; +2B1B;BLACK LARGE SQUARE;So;0;ON;;;;;N;;;;; +2B1C;WHITE LARGE SQUARE;So;0;ON;;;;;N;;;;; +2B1D;BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +2B1E;WHITE VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +2B1F;BLACK PENTAGON;So;0;ON;;;;;N;;;;; +2B20;WHITE PENTAGON;So;0;ON;;;;;N;;;;; +2B21;WHITE HEXAGON;So;0;ON;;;;;N;;;;; +2B22;BLACK HEXAGON;So;0;ON;;;;;N;;;;; +2B23;HORIZONTAL BLACK HEXAGON;So;0;ON;;;;;N;;;;; +2B24;BLACK LARGE CIRCLE;So;0;ON;;;;;N;;;;; +2B25;BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +2B26;WHITE MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +2B27;BLACK MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; +2B28;WHITE MEDIUM LOZENGE;So;0;ON;;;;;N;;;;; +2B29;BLACK SMALL DIAMOND;So;0;ON;;;;;N;;;;; +2B2A;BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; +2B2B;WHITE SMALL LOZENGE;So;0;ON;;;;;N;;;;; +2B2C;BLACK HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2D;WHITE HORIZONTAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2E;BLACK VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B2F;WHITE VERTICAL ELLIPSE;So;0;ON;;;;;N;;;;; +2B30;LEFT ARROW WITH SMALL CIRCLE;Sm;0;ON;;;;;N;;;;; +2B31;THREE LEFTWARDS ARROWS;Sm;0;ON;;;;;N;;;;; +2B32;LEFT ARROW WITH CIRCLED PLUS;Sm;0;ON;;;;;N;;;;; +2B33;LONG LEFTWARDS SQUIGGLE ARROW;Sm;0;ON;;;;;N;;;;; +2B34;LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B35;LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B36;LEFTWARDS TWO-HEADED ARROW FROM BAR;Sm;0;ON;;;;;N;;;;; +2B37;LEFTWARDS TWO-HEADED TRIPLE DASH ARROW;Sm;0;ON;;;;;N;;;;; +2B38;LEFTWARDS ARROW WITH DOTTED STEM;Sm;0;ON;;;;;N;;;;; +2B39;LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3A;LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3B;LEFTWARDS TWO-HEADED ARROW WITH TAIL;Sm;0;ON;;;;;N;;;;; +2B3C;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3D;LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE;Sm;0;ON;;;;;N;;;;; +2B3E;LEFTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; +2B3F;WAVE ARROW POINTING DIRECTLY LEFT;Sm;0;ON;;;;;N;;;;; +2B40;EQUALS SIGN ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B41;REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B42;LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B43;RIGHTWARDS ARROW THROUGH GREATER-THAN;Sm;0;ON;;;;;N;;;;; +2B44;RIGHTWARDS ARROW THROUGH SUPERSET;Sm;0;ON;;;;;N;;;;; +2B45;LEFTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; +2B46;RIGHTWARDS QUADRUPLE ARROW;So;0;ON;;;;;N;;;;; +2B47;REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B48;RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B49;TILDE OPERATOR ABOVE LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +2B4A;LEFTWARDS ARROW ABOVE ALMOST EQUAL TO;Sm;0;ON;;;;;N;;;;; +2B4B;LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2B4C;RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR;Sm;0;ON;;;;;N;;;;; +2B4D;DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW;So;0;ON;;;;;N;;;;; +2B4E;SHORT SLANTED NORTH ARROW;So;0;ON;;;;;N;;;;; +2B4F;SHORT BACKSLANTED SOUTH ARROW;So;0;ON;;;;;N;;;;; +2B50;WHITE MEDIUM STAR;So;0;ON;;;;;N;;;;; +2B51;BLACK SMALL STAR;So;0;ON;;;;;N;;;;; +2B52;WHITE SMALL STAR;So;0;ON;;;;;N;;;;; +2B53;BLACK RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; +2B54;WHITE RIGHT-POINTING PENTAGON;So;0;ON;;;;;N;;;;; +2B55;HEAVY LARGE CIRCLE;So;0;ON;;;;;N;;;;; +2B56;HEAVY OVAL WITH OVAL INSIDE;So;0;ON;;;;;N;;;;; +2B57;HEAVY CIRCLE WITH CIRCLE INSIDE;So;0;ON;;;;;N;;;;; +2B58;HEAVY CIRCLE;So;0;ON;;;;;N;;;;; +2B59;HEAVY CIRCLED SALTIRE;So;0;ON;;;;;N;;;;; +2B5A;SLANTED NORTH ARROW WITH HOOKED HEAD;So;0;ON;;;;;N;;;;; +2B5B;BACKSLANTED SOUTH ARROW WITH HOOKED TAIL;So;0;ON;;;;;N;;;;; +2B5C;SLANTED NORTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; +2B5D;BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL;So;0;ON;;;;;N;;;;; +2B5E;BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; +2B5F;SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST;So;0;ON;;;;;N;;;;; +2B60;LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B61;UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B62;RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B63;DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B64;LEFT RIGHT TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B65;UP DOWN TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B66;NORTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B67;NORTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B68;SOUTH EAST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B69;SOUTH WEST TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B6A;LEFTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6B;UPWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6C;RIGHTWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6D;DOWNWARDS TRIANGLE-HEADED DASHED ARROW;So;0;ON;;;;;N;;;;; +2B6E;CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +2B6F;ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW;So;0;ON;;;;;N;;;;; +2B70;LEFTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B71;UPWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B72;RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B73;DOWNWARDS TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B76;NORTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B77;NORTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B78;SOUTH EAST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B79;SOUTH WEST TRIANGLE-HEADED ARROW TO BAR;So;0;ON;;;;;N;;;;; +2B7A;LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7B;UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7C;RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7D;DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE;So;0;ON;;;;;N;;;;; +2B7E;HORIZONTAL TAB KEY;So;0;ON;;;;;N;;;;; +2B7F;VERTICAL TAB KEY;So;0;ON;;;;;N;;;;; +2B80;LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B81;UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B82;RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B83;DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW;So;0;ON;;;;;N;;;;; +2B84;LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B85;UPWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B86;RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B87;DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS;So;0;ON;;;;;N;;;;; +2B88;LEFTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B89;UPWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8A;RIGHTWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8B;DOWNWARDS BLACK CIRCLED WHITE ARROW;So;0;ON;;;;;N;;;;; +2B8C;ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8D;ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8E;ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B8F;ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW;So;0;ON;;;;;N;;;;; +2B90;RETURN LEFT;So;0;ON;;;;;N;;;;; +2B91;RETURN RIGHT;So;0;ON;;;;;N;;;;; +2B92;NEWLINE LEFT;So;0;ON;;;;;N;;;;; +2B93;NEWLINE RIGHT;So;0;ON;;;;;N;;;;; +2B94;FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE;So;0;ON;;;;;N;;;;; +2B95;RIGHTWARDS BLACK ARROW;So;0;ON;;;;;N;;;;; +2B96;EQUALS SIGN WITH INFINITY ABOVE;So;0;ON;;;;;N;;;;; +2B97;SYMBOL FOR TYPE A ELECTRONICS;So;0;ON;;;;;N;;;;; +2B98;THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B99;THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9A;THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9B;THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9C;BLACK LEFTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9D;BLACK UPWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9E;BLACK RIGHTWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2B9F;BLACK DOWNWARDS EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +2BA0;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; +2BA1;DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; +2BA2;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS;So;0;ON;;;;;N;;;;; +2BA3;UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS;So;0;ON;;;;;N;;;;; +2BA4;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; +2BA5;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS;So;0;ON;;;;;N;;;;; +2BA6;LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2BA7;RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS;So;0;ON;;;;;N;;;;; +2BA8;BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BA9;BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAA;BLACK CURVED UPWARDS AND LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAB;BLACK CURVED UPWARDS AND RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAC;BLACK CURVED LEFTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAD;BLACK CURVED RIGHTWARDS AND UPWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAE;BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +2BAF;BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +2BB0;RIBBON ARROW DOWN LEFT;So;0;ON;;;;;N;;;;; +2BB1;RIBBON ARROW DOWN RIGHT;So;0;ON;;;;;N;;;;; +2BB2;RIBBON ARROW UP LEFT;So;0;ON;;;;;N;;;;; +2BB3;RIBBON ARROW UP RIGHT;So;0;ON;;;;;N;;;;; +2BB4;RIBBON ARROW LEFT UP;So;0;ON;;;;;N;;;;; +2BB5;RIBBON ARROW RIGHT UP;So;0;ON;;;;;N;;;;; +2BB6;RIBBON ARROW LEFT DOWN;So;0;ON;;;;;N;;;;; +2BB7;RIBBON ARROW RIGHT DOWN;So;0;ON;;;;;N;;;;; +2BB8;UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; +2BB9;UP ARROWHEAD IN A RECTANGLE BOX;So;0;ON;;;;;N;;;;; +2BBA;OVERLAPPING WHITE SQUARES;So;0;ON;;;;;N;;;;; +2BBB;OVERLAPPING WHITE AND BLACK SQUARES;So;0;ON;;;;;N;;;;; +2BBC;OVERLAPPING BLACK SQUARES;So;0;ON;;;;;N;;;;; +2BBD;BALLOT BOX WITH LIGHT X;So;0;ON;;;;;N;;;;; +2BBE;CIRCLED X;So;0;ON;;;;;N;;;;; +2BBF;CIRCLED BOLD X;So;0;ON;;;;;N;;;;; +2BC0;BLACK SQUARE CENTRED;So;0;ON;;;;;N;;;;; +2BC1;BLACK DIAMOND CENTRED;So;0;ON;;;;;N;;;;; +2BC2;TURNED BLACK PENTAGON;So;0;ON;;;;;N;;;;; +2BC3;HORIZONTAL BLACK OCTAGON;So;0;ON;;;;;N;;;;; +2BC4;BLACK OCTAGON;So;0;ON;;;;;N;;;;; +2BC5;BLACK MEDIUM UP-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC6;BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC7;BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC8;BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED;So;0;ON;;;;;N;;;;; +2BC9;NEPTUNE FORM TWO;So;0;ON;;;;;N;;;;; +2BCA;TOP HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +2BCB;BOTTOM HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +2BCC;LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; +2BCD;ROTATED LIGHT FOUR POINTED BLACK CUSP;So;0;ON;;;;;N;;;;; +2BCE;WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; +2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;; +2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;; +2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;; +2BD2;GROUP MARK;So;0;ON;;;;;N;;;;; +2BD3;PLUTO FORM TWO;So;0;ON;;;;;N;;;;; +2BD4;PLUTO FORM THREE;So;0;ON;;;;;N;;;;; +2BD5;PLUTO FORM FOUR;So;0;ON;;;;;N;;;;; +2BD6;PLUTO FORM FIVE;So;0;ON;;;;;N;;;;; +2BD7;TRANSPLUTO;So;0;ON;;;;;N;;;;; +2BD8;PROSERPINA;So;0;ON;;;;;N;;;;; +2BD9;ASTRAEA;So;0;ON;;;;;N;;;;; +2BDA;HYGIEA;So;0;ON;;;;;N;;;;; +2BDB;PHOLUS;So;0;ON;;;;;N;;;;; +2BDC;NESSUS;So;0;ON;;;;;N;;;;; +2BDD;WHITE MOON SELENA;So;0;ON;;;;;N;;;;; +2BDE;BLACK DIAMOND ON CROSS;So;0;ON;;;;;N;;;;; +2BDF;TRUE LIGHT MOON ARTA;So;0;ON;;;;;N;;;;; +2BE0;CUPIDO;So;0;ON;;;;;N;;;;; +2BE1;HADES;So;0;ON;;;;;N;;;;; +2BE2;ZEUS;So;0;ON;;;;;N;;;;; +2BE3;KRONOS;So;0;ON;;;;;N;;;;; +2BE4;APOLLON;So;0;ON;;;;;N;;;;; +2BE5;ADMETOS;So;0;ON;;;;;N;;;;; +2BE6;VULCANUS;So;0;ON;;;;;N;;;;; +2BE7;POSEIDON;So;0;ON;;;;;N;;;;; +2BE8;LEFT HALF BLACK STAR;So;0;ON;;;;;N;;;;; +2BE9;RIGHT HALF BLACK STAR;So;0;ON;;;;;N;;;;; +2BEA;STAR WITH LEFT HALF BLACK;So;0;ON;;;;;N;;;;; +2BEB;STAR WITH RIGHT HALF BLACK;So;0;ON;;;;;N;;;;; +2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BEF;DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;; +2BF0;ERIS FORM ONE;So;0;ON;;;;;N;;;;; +2BF1;ERIS FORM TWO;So;0;ON;;;;;N;;;;; +2BF2;SEDNA;So;0;ON;;;;;N;;;;; +2BF3;RUSSIAN ASTROLOGICAL SYMBOL VIGINTILE;So;0;ON;;;;;N;;;;; +2BF4;RUSSIAN ASTROLOGICAL SYMBOL NOVILE;So;0;ON;;;;;N;;;;; +2BF5;RUSSIAN ASTROLOGICAL SYMBOL QUINTILE;So;0;ON;;;;;N;;;;; +2BF6;RUSSIAN ASTROLOGICAL SYMBOL BINOVILE;So;0;ON;;;;;N;;;;; +2BF7;RUSSIAN ASTROLOGICAL SYMBOL SENTAGON;So;0;ON;;;;;N;;;;; +2BF8;RUSSIAN ASTROLOGICAL SYMBOL TREDECILE;So;0;ON;;;;;N;;;;; +2BF9;EQUALS SIGN WITH INFINITY BELOW;So;0;ON;;;;;N;;;;; +2BFA;UNITED SYMBOL;So;0;ON;;;;;N;;;;; +2BFB;SEPARATED SYMBOL;So;0;ON;;;;;N;;;;; +2BFC;DOUBLED SYMBOL;So;0;ON;;;;;N;;;;; +2BFD;PASSED SYMBOL;So;0;ON;;;;;N;;;;; +2BFE;REVERSED RIGHT ANGLE;So;0;ON;;;;;Y;;;;; +2BFF;HELLSCHREIBER PAUSE SYMBOL;So;0;ON;;;;;N;;;;; +2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30; +2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31; +2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32; +2C03;GLAGOLITIC CAPITAL LETTER GLAGOLI;Lu;0;L;;;;;N;;;;2C33; +2C04;GLAGOLITIC CAPITAL LETTER DOBRO;Lu;0;L;;;;;N;;;;2C34; +2C05;GLAGOLITIC CAPITAL LETTER YESTU;Lu;0;L;;;;;N;;;;2C35; +2C06;GLAGOLITIC CAPITAL LETTER ZHIVETE;Lu;0;L;;;;;N;;;;2C36; +2C07;GLAGOLITIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;2C37; +2C08;GLAGOLITIC CAPITAL LETTER ZEMLJA;Lu;0;L;;;;;N;;;;2C38; +2C09;GLAGOLITIC CAPITAL LETTER IZHE;Lu;0;L;;;;;N;;;;2C39; +2C0A;GLAGOLITIC CAPITAL LETTER INITIAL IZHE;Lu;0;L;;;;;N;;;;2C3A; +2C0B;GLAGOLITIC CAPITAL LETTER I;Lu;0;L;;;;;N;;;;2C3B; +2C0C;GLAGOLITIC CAPITAL LETTER DJERVI;Lu;0;L;;;;;N;;;;2C3C; +2C0D;GLAGOLITIC CAPITAL LETTER KAKO;Lu;0;L;;;;;N;;;;2C3D; +2C0E;GLAGOLITIC CAPITAL LETTER LJUDIJE;Lu;0;L;;;;;N;;;;2C3E; +2C0F;GLAGOLITIC CAPITAL LETTER MYSLITE;Lu;0;L;;;;;N;;;;2C3F; +2C10;GLAGOLITIC CAPITAL LETTER NASHI;Lu;0;L;;;;;N;;;;2C40; +2C11;GLAGOLITIC CAPITAL LETTER ONU;Lu;0;L;;;;;N;;;;2C41; +2C12;GLAGOLITIC CAPITAL LETTER POKOJI;Lu;0;L;;;;;N;;;;2C42; +2C13;GLAGOLITIC CAPITAL LETTER RITSI;Lu;0;L;;;;;N;;;;2C43; +2C14;GLAGOLITIC CAPITAL LETTER SLOVO;Lu;0;L;;;;;N;;;;2C44; +2C15;GLAGOLITIC CAPITAL LETTER TVRIDO;Lu;0;L;;;;;N;;;;2C45; +2C16;GLAGOLITIC CAPITAL LETTER UKU;Lu;0;L;;;;;N;;;;2C46; +2C17;GLAGOLITIC CAPITAL LETTER FRITU;Lu;0;L;;;;;N;;;;2C47; +2C18;GLAGOLITIC CAPITAL LETTER HERU;Lu;0;L;;;;;N;;;;2C48; +2C19;GLAGOLITIC CAPITAL LETTER OTU;Lu;0;L;;;;;N;;;;2C49; +2C1A;GLAGOLITIC CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;2C4A; +2C1B;GLAGOLITIC CAPITAL LETTER SHTA;Lu;0;L;;;;;N;;;;2C4B; +2C1C;GLAGOLITIC CAPITAL LETTER TSI;Lu;0;L;;;;;N;;;;2C4C; +2C1D;GLAGOLITIC CAPITAL LETTER CHRIVI;Lu;0;L;;;;;N;;;;2C4D; +2C1E;GLAGOLITIC CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;2C4E; +2C1F;GLAGOLITIC CAPITAL LETTER YERU;Lu;0;L;;;;;N;;;;2C4F; +2C20;GLAGOLITIC CAPITAL LETTER YERI;Lu;0;L;;;;;N;;;;2C50; +2C21;GLAGOLITIC CAPITAL LETTER YATI;Lu;0;L;;;;;N;;;;2C51; +2C22;GLAGOLITIC CAPITAL LETTER SPIDERY HA;Lu;0;L;;;;;N;;;;2C52; +2C23;GLAGOLITIC CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;2C53; +2C24;GLAGOLITIC CAPITAL LETTER SMALL YUS;Lu;0;L;;;;;N;;;;2C54; +2C25;GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL;Lu;0;L;;;;;N;;;;2C55; +2C26;GLAGOLITIC CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;2C56; +2C27;GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS;Lu;0;L;;;;;N;;;;2C57; +2C28;GLAGOLITIC CAPITAL LETTER BIG YUS;Lu;0;L;;;;;N;;;;2C58; +2C29;GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS;Lu;0;L;;;;;N;;;;2C59; +2C2A;GLAGOLITIC CAPITAL LETTER FITA;Lu;0;L;;;;;N;;;;2C5A; +2C2B;GLAGOLITIC CAPITAL LETTER IZHITSA;Lu;0;L;;;;;N;;;;2C5B; +2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C; +2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D; +2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E; +2C2F;GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI;Lu;0;L;;;;;N;;;;2C5F; +2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00 +2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01 +2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02 +2C33;GLAGOLITIC SMALL LETTER GLAGOLI;Ll;0;L;;;;;N;;;2C03;;2C03 +2C34;GLAGOLITIC SMALL LETTER DOBRO;Ll;0;L;;;;;N;;;2C04;;2C04 +2C35;GLAGOLITIC SMALL LETTER YESTU;Ll;0;L;;;;;N;;;2C05;;2C05 +2C36;GLAGOLITIC SMALL LETTER ZHIVETE;Ll;0;L;;;;;N;;;2C06;;2C06 +2C37;GLAGOLITIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;2C07;;2C07 +2C38;GLAGOLITIC SMALL LETTER ZEMLJA;Ll;0;L;;;;;N;;;2C08;;2C08 +2C39;GLAGOLITIC SMALL LETTER IZHE;Ll;0;L;;;;;N;;;2C09;;2C09 +2C3A;GLAGOLITIC SMALL LETTER INITIAL IZHE;Ll;0;L;;;;;N;;;2C0A;;2C0A +2C3B;GLAGOLITIC SMALL LETTER I;Ll;0;L;;;;;N;;;2C0B;;2C0B +2C3C;GLAGOLITIC SMALL LETTER DJERVI;Ll;0;L;;;;;N;;;2C0C;;2C0C +2C3D;GLAGOLITIC SMALL LETTER KAKO;Ll;0;L;;;;;N;;;2C0D;;2C0D +2C3E;GLAGOLITIC SMALL LETTER LJUDIJE;Ll;0;L;;;;;N;;;2C0E;;2C0E +2C3F;GLAGOLITIC SMALL LETTER MYSLITE;Ll;0;L;;;;;N;;;2C0F;;2C0F +2C40;GLAGOLITIC SMALL LETTER NASHI;Ll;0;L;;;;;N;;;2C10;;2C10 +2C41;GLAGOLITIC SMALL LETTER ONU;Ll;0;L;;;;;N;;;2C11;;2C11 +2C42;GLAGOLITIC SMALL LETTER POKOJI;Ll;0;L;;;;;N;;;2C12;;2C12 +2C43;GLAGOLITIC SMALL LETTER RITSI;Ll;0;L;;;;;N;;;2C13;;2C13 +2C44;GLAGOLITIC SMALL LETTER SLOVO;Ll;0;L;;;;;N;;;2C14;;2C14 +2C45;GLAGOLITIC SMALL LETTER TVRIDO;Ll;0;L;;;;;N;;;2C15;;2C15 +2C46;GLAGOLITIC SMALL LETTER UKU;Ll;0;L;;;;;N;;;2C16;;2C16 +2C47;GLAGOLITIC SMALL LETTER FRITU;Ll;0;L;;;;;N;;;2C17;;2C17 +2C48;GLAGOLITIC SMALL LETTER HERU;Ll;0;L;;;;;N;;;2C18;;2C18 +2C49;GLAGOLITIC SMALL LETTER OTU;Ll;0;L;;;;;N;;;2C19;;2C19 +2C4A;GLAGOLITIC SMALL LETTER PE;Ll;0;L;;;;;N;;;2C1A;;2C1A +2C4B;GLAGOLITIC SMALL LETTER SHTA;Ll;0;L;;;;;N;;;2C1B;;2C1B +2C4C;GLAGOLITIC SMALL LETTER TSI;Ll;0;L;;;;;N;;;2C1C;;2C1C +2C4D;GLAGOLITIC SMALL LETTER CHRIVI;Ll;0;L;;;;;N;;;2C1D;;2C1D +2C4E;GLAGOLITIC SMALL LETTER SHA;Ll;0;L;;;;;N;;;2C1E;;2C1E +2C4F;GLAGOLITIC SMALL LETTER YERU;Ll;0;L;;;;;N;;;2C1F;;2C1F +2C50;GLAGOLITIC SMALL LETTER YERI;Ll;0;L;;;;;N;;;2C20;;2C20 +2C51;GLAGOLITIC SMALL LETTER YATI;Ll;0;L;;;;;N;;;2C21;;2C21 +2C52;GLAGOLITIC SMALL LETTER SPIDERY HA;Ll;0;L;;;;;N;;;2C22;;2C22 +2C53;GLAGOLITIC SMALL LETTER YU;Ll;0;L;;;;;N;;;2C23;;2C23 +2C54;GLAGOLITIC SMALL LETTER SMALL YUS;Ll;0;L;;;;;N;;;2C24;;2C24 +2C55;GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL;Ll;0;L;;;;;N;;;2C25;;2C25 +2C56;GLAGOLITIC SMALL LETTER YO;Ll;0;L;;;;;N;;;2C26;;2C26 +2C57;GLAGOLITIC SMALL LETTER IOTATED SMALL YUS;Ll;0;L;;;;;N;;;2C27;;2C27 +2C58;GLAGOLITIC SMALL LETTER BIG YUS;Ll;0;L;;;;;N;;;2C28;;2C28 +2C59;GLAGOLITIC SMALL LETTER IOTATED BIG YUS;Ll;0;L;;;;;N;;;2C29;;2C29 +2C5A;GLAGOLITIC SMALL LETTER FITA;Ll;0;L;;;;;N;;;2C2A;;2C2A +2C5B;GLAGOLITIC SMALL LETTER IZHITSA;Ll;0;L;;;;;N;;;2C2B;;2C2B +2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C +2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D +2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E +2C5F;GLAGOLITIC SMALL LETTER CAUDATE CHRIVI;Ll;0;L;;;;;N;;;2C2F;;2C2F +2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61; +2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60 +2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B; +2C63;LATIN CAPITAL LETTER P WITH STROKE;Lu;0;L;;;;;N;;;;1D7D; +2C64;LATIN CAPITAL LETTER R WITH TAIL;Lu;0;L;;;;;N;;;;027D; +2C65;LATIN SMALL LETTER A WITH STROKE;Ll;0;L;;;;;N;;;023A;;023A +2C66;LATIN SMALL LETTER T WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;023E;;023E +2C67;LATIN CAPITAL LETTER H WITH DESCENDER;Lu;0;L;;;;;N;;;;2C68; +2C68;LATIN SMALL LETTER H WITH DESCENDER;Ll;0;L;;;;;N;;;2C67;;2C67 +2C69;LATIN CAPITAL LETTER K WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6A; +2C6A;LATIN SMALL LETTER K WITH DESCENDER;Ll;0;L;;;;;N;;;2C69;;2C69 +2C6B;LATIN CAPITAL LETTER Z WITH DESCENDER;Lu;0;L;;;;;N;;;;2C6C; +2C6C;LATIN SMALL LETTER Z WITH DESCENDER;Ll;0;L;;;;;N;;;2C6B;;2C6B +2C6D;LATIN CAPITAL LETTER ALPHA;Lu;0;L;;;;;N;;;;0251; +2C6E;LATIN CAPITAL LETTER M WITH HOOK;Lu;0;L;;;;;N;;;;0271; +2C6F;LATIN CAPITAL LETTER TURNED A;Lu;0;L;;;;;N;;;;0250; +2C70;LATIN CAPITAL LETTER TURNED ALPHA;Lu;0;L;;;;;N;;;;0252; +2C71;LATIN SMALL LETTER V WITH RIGHT HOOK;Ll;0;L;;;;;N;;;;; +2C72;LATIN CAPITAL LETTER W WITH HOOK;Lu;0;L;;;;;N;;;;2C73; +2C73;LATIN SMALL LETTER W WITH HOOK;Ll;0;L;;;;;N;;;2C72;;2C72 +2C74;LATIN SMALL LETTER V WITH CURL;Ll;0;L;;;;;N;;;;; +2C75;LATIN CAPITAL LETTER HALF H;Lu;0;L;;;;;N;;;;2C76; +2C76;LATIN SMALL LETTER HALF H;Ll;0;L;;;;;N;;;2C75;;2C75 +2C77;LATIN SMALL LETTER TAILLESS PHI;Ll;0;L;;;;;N;;;;; +2C78;LATIN SMALL LETTER E WITH NOTCH;Ll;0;L;;;;;N;;;;; +2C79;LATIN SMALL LETTER TURNED R WITH TAIL;Ll;0;L;;;;;N;;;;; +2C7A;LATIN SMALL LETTER O WITH LOW RING INSIDE;Ll;0;L;;;;;N;;;;; +2C7B;LATIN LETTER SMALL CAPITAL TURNED E;Ll;0;L;;;;;N;;;;; +2C7C;LATIN SUBSCRIPT SMALL LETTER J;Lm;0;L; 006A;;;;N;;;;; +2C7D;MODIFIER LETTER CAPITAL V;Lm;0;L; 0056;;;;N;;;;; +2C7E;LATIN CAPITAL LETTER S WITH SWASH TAIL;Lu;0;L;;;;;N;;;;023F; +2C7F;LATIN CAPITAL LETTER Z WITH SWASH TAIL;Lu;0;L;;;;;N;;;;0240; +2C80;COPTIC CAPITAL LETTER ALFA;Lu;0;L;;;;;N;;;;2C81; +2C81;COPTIC SMALL LETTER ALFA;Ll;0;L;;;;;N;;;2C80;;2C80 +2C82;COPTIC CAPITAL LETTER VIDA;Lu;0;L;;;;;N;;;;2C83; +2C83;COPTIC SMALL LETTER VIDA;Ll;0;L;;;;;N;;;2C82;;2C82 +2C84;COPTIC CAPITAL LETTER GAMMA;Lu;0;L;;;;;N;;;;2C85; +2C85;COPTIC SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;2C84;;2C84 +2C86;COPTIC CAPITAL LETTER DALDA;Lu;0;L;;;;;N;;;;2C87; +2C87;COPTIC SMALL LETTER DALDA;Ll;0;L;;;;;N;;;2C86;;2C86 +2C88;COPTIC CAPITAL LETTER EIE;Lu;0;L;;;;;N;;;;2C89; +2C89;COPTIC SMALL LETTER EIE;Ll;0;L;;;;;N;;;2C88;;2C88 +2C8A;COPTIC CAPITAL LETTER SOU;Lu;0;L;;;;;N;;;;2C8B; +2C8B;COPTIC SMALL LETTER SOU;Ll;0;L;;;;;N;;;2C8A;;2C8A +2C8C;COPTIC CAPITAL LETTER ZATA;Lu;0;L;;;;;N;;;;2C8D; +2C8D;COPTIC SMALL LETTER ZATA;Ll;0;L;;;;;N;;;2C8C;;2C8C +2C8E;COPTIC CAPITAL LETTER HATE;Lu;0;L;;;;;N;;;;2C8F; +2C8F;COPTIC SMALL LETTER HATE;Ll;0;L;;;;;N;;;2C8E;;2C8E +2C90;COPTIC CAPITAL LETTER THETHE;Lu;0;L;;;;;N;;;;2C91; +2C91;COPTIC SMALL LETTER THETHE;Ll;0;L;;;;;N;;;2C90;;2C90 +2C92;COPTIC CAPITAL LETTER IAUDA;Lu;0;L;;;;;N;;;;2C93; +2C93;COPTIC SMALL LETTER IAUDA;Ll;0;L;;;;;N;;;2C92;;2C92 +2C94;COPTIC CAPITAL LETTER KAPA;Lu;0;L;;;;;N;;;;2C95; +2C95;COPTIC SMALL LETTER KAPA;Ll;0;L;;;;;N;;;2C94;;2C94 +2C96;COPTIC CAPITAL LETTER LAULA;Lu;0;L;;;;;N;;;;2C97; +2C97;COPTIC SMALL LETTER LAULA;Ll;0;L;;;;;N;;;2C96;;2C96 +2C98;COPTIC CAPITAL LETTER MI;Lu;0;L;;;;;N;;;;2C99; +2C99;COPTIC SMALL LETTER MI;Ll;0;L;;;;;N;;;2C98;;2C98 +2C9A;COPTIC CAPITAL LETTER NI;Lu;0;L;;;;;N;;;;2C9B; +2C9B;COPTIC SMALL LETTER NI;Ll;0;L;;;;;N;;;2C9A;;2C9A +2C9C;COPTIC CAPITAL LETTER KSI;Lu;0;L;;;;;N;;;;2C9D; +2C9D;COPTIC SMALL LETTER KSI;Ll;0;L;;;;;N;;;2C9C;;2C9C +2C9E;COPTIC CAPITAL LETTER O;Lu;0;L;;;;;N;;;;2C9F; +2C9F;COPTIC SMALL LETTER O;Ll;0;L;;;;;N;;;2C9E;;2C9E +2CA0;COPTIC CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;2CA1; +2CA1;COPTIC SMALL LETTER PI;Ll;0;L;;;;;N;;;2CA0;;2CA0 +2CA2;COPTIC CAPITAL LETTER RO;Lu;0;L;;;;;N;;;;2CA3; +2CA3;COPTIC SMALL LETTER RO;Ll;0;L;;;;;N;;;2CA2;;2CA2 +2CA4;COPTIC CAPITAL LETTER SIMA;Lu;0;L;;;;;N;;;;2CA5; +2CA5;COPTIC SMALL LETTER SIMA;Ll;0;L;;;;;N;;;2CA4;;2CA4 +2CA6;COPTIC CAPITAL LETTER TAU;Lu;0;L;;;;;N;;;;2CA7; +2CA7;COPTIC SMALL LETTER TAU;Ll;0;L;;;;;N;;;2CA6;;2CA6 +2CA8;COPTIC CAPITAL LETTER UA;Lu;0;L;;;;;N;;;;2CA9; +2CA9;COPTIC SMALL LETTER UA;Ll;0;L;;;;;N;;;2CA8;;2CA8 +2CAA;COPTIC CAPITAL LETTER FI;Lu;0;L;;;;;N;;;;2CAB; +2CAB;COPTIC SMALL LETTER FI;Ll;0;L;;;;;N;;;2CAA;;2CAA +2CAC;COPTIC CAPITAL LETTER KHI;Lu;0;L;;;;;N;;;;2CAD; +2CAD;COPTIC SMALL LETTER KHI;Ll;0;L;;;;;N;;;2CAC;;2CAC +2CAE;COPTIC CAPITAL LETTER PSI;Lu;0;L;;;;;N;;;;2CAF; +2CAF;COPTIC SMALL LETTER PSI;Ll;0;L;;;;;N;;;2CAE;;2CAE +2CB0;COPTIC CAPITAL LETTER OOU;Lu;0;L;;;;;N;;;;2CB1; +2CB1;COPTIC SMALL LETTER OOU;Ll;0;L;;;;;N;;;2CB0;;2CB0 +2CB2;COPTIC CAPITAL LETTER DIALECT-P ALEF;Lu;0;L;;;;;N;;;;2CB3; +2CB3;COPTIC SMALL LETTER DIALECT-P ALEF;Ll;0;L;;;;;N;;;2CB2;;2CB2 +2CB4;COPTIC CAPITAL LETTER OLD COPTIC AIN;Lu;0;L;;;;;N;;;;2CB5; +2CB5;COPTIC SMALL LETTER OLD COPTIC AIN;Ll;0;L;;;;;N;;;2CB4;;2CB4 +2CB6;COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE;Lu;0;L;;;;;N;;;;2CB7; +2CB7;COPTIC SMALL LETTER CRYPTOGRAMMIC EIE;Ll;0;L;;;;;N;;;2CB6;;2CB6 +2CB8;COPTIC CAPITAL LETTER DIALECT-P KAPA;Lu;0;L;;;;;N;;;;2CB9; +2CB9;COPTIC SMALL LETTER DIALECT-P KAPA;Ll;0;L;;;;;N;;;2CB8;;2CB8 +2CBA;COPTIC CAPITAL LETTER DIALECT-P NI;Lu;0;L;;;;;N;;;;2CBB; +2CBB;COPTIC SMALL LETTER DIALECT-P NI;Ll;0;L;;;;;N;;;2CBA;;2CBA +2CBC;COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI;Lu;0;L;;;;;N;;;;2CBD; +2CBD;COPTIC SMALL LETTER CRYPTOGRAMMIC NI;Ll;0;L;;;;;N;;;2CBC;;2CBC +2CBE;COPTIC CAPITAL LETTER OLD COPTIC OOU;Lu;0;L;;;;;N;;;;2CBF; +2CBF;COPTIC SMALL LETTER OLD COPTIC OOU;Ll;0;L;;;;;N;;;2CBE;;2CBE +2CC0;COPTIC CAPITAL LETTER SAMPI;Lu;0;L;;;;;N;;;;2CC1; +2CC1;COPTIC SMALL LETTER SAMPI;Ll;0;L;;;;;N;;;2CC0;;2CC0 +2CC2;COPTIC CAPITAL LETTER CROSSED SHEI;Lu;0;L;;;;;N;;;;2CC3; +2CC3;COPTIC SMALL LETTER CROSSED SHEI;Ll;0;L;;;;;N;;;2CC2;;2CC2 +2CC4;COPTIC CAPITAL LETTER OLD COPTIC SHEI;Lu;0;L;;;;;N;;;;2CC5; +2CC5;COPTIC SMALL LETTER OLD COPTIC SHEI;Ll;0;L;;;;;N;;;2CC4;;2CC4 +2CC6;COPTIC CAPITAL LETTER OLD COPTIC ESH;Lu;0;L;;;;;N;;;;2CC7; +2CC7;COPTIC SMALL LETTER OLD COPTIC ESH;Ll;0;L;;;;;N;;;2CC6;;2CC6 +2CC8;COPTIC CAPITAL LETTER AKHMIMIC KHEI;Lu;0;L;;;;;N;;;;2CC9; +2CC9;COPTIC SMALL LETTER AKHMIMIC KHEI;Ll;0;L;;;;;N;;;2CC8;;2CC8 +2CCA;COPTIC CAPITAL LETTER DIALECT-P HORI;Lu;0;L;;;;;N;;;;2CCB; +2CCB;COPTIC SMALL LETTER DIALECT-P HORI;Ll;0;L;;;;;N;;;2CCA;;2CCA +2CCC;COPTIC CAPITAL LETTER OLD COPTIC HORI;Lu;0;L;;;;;N;;;;2CCD; +2CCD;COPTIC SMALL LETTER OLD COPTIC HORI;Ll;0;L;;;;;N;;;2CCC;;2CCC +2CCE;COPTIC CAPITAL LETTER OLD COPTIC HA;Lu;0;L;;;;;N;;;;2CCF; +2CCF;COPTIC SMALL LETTER OLD COPTIC HA;Ll;0;L;;;;;N;;;2CCE;;2CCE +2CD0;COPTIC CAPITAL LETTER L-SHAPED HA;Lu;0;L;;;;;N;;;;2CD1; +2CD1;COPTIC SMALL LETTER L-SHAPED HA;Ll;0;L;;;;;N;;;2CD0;;2CD0 +2CD2;COPTIC CAPITAL LETTER OLD COPTIC HEI;Lu;0;L;;;;;N;;;;2CD3; +2CD3;COPTIC SMALL LETTER OLD COPTIC HEI;Ll;0;L;;;;;N;;;2CD2;;2CD2 +2CD4;COPTIC CAPITAL LETTER OLD COPTIC HAT;Lu;0;L;;;;;N;;;;2CD5; +2CD5;COPTIC SMALL LETTER OLD COPTIC HAT;Ll;0;L;;;;;N;;;2CD4;;2CD4 +2CD6;COPTIC CAPITAL LETTER OLD COPTIC GANGIA;Lu;0;L;;;;;N;;;;2CD7; +2CD7;COPTIC SMALL LETTER OLD COPTIC GANGIA;Ll;0;L;;;;;N;;;2CD6;;2CD6 +2CD8;COPTIC CAPITAL LETTER OLD COPTIC DJA;Lu;0;L;;;;;N;;;;2CD9; +2CD9;COPTIC SMALL LETTER OLD COPTIC DJA;Ll;0;L;;;;;N;;;2CD8;;2CD8 +2CDA;COPTIC CAPITAL LETTER OLD COPTIC SHIMA;Lu;0;L;;;;;N;;;;2CDB; +2CDB;COPTIC SMALL LETTER OLD COPTIC SHIMA;Ll;0;L;;;;;N;;;2CDA;;2CDA +2CDC;COPTIC CAPITAL LETTER OLD NUBIAN SHIMA;Lu;0;L;;;;;N;;;;2CDD; +2CDD;COPTIC SMALL LETTER OLD NUBIAN SHIMA;Ll;0;L;;;;;N;;;2CDC;;2CDC +2CDE;COPTIC CAPITAL LETTER OLD NUBIAN NGI;Lu;0;L;;;;;N;;;;2CDF; +2CDF;COPTIC SMALL LETTER OLD NUBIAN NGI;Ll;0;L;;;;;N;;;2CDE;;2CDE +2CE0;COPTIC CAPITAL LETTER OLD NUBIAN NYI;Lu;0;L;;;;;N;;;;2CE1; +2CE1;COPTIC SMALL LETTER OLD NUBIAN NYI;Ll;0;L;;;;;N;;;2CE0;;2CE0 +2CE2;COPTIC CAPITAL LETTER OLD NUBIAN WAU;Lu;0;L;;;;;N;;;;2CE3; +2CE3;COPTIC SMALL LETTER OLD NUBIAN WAU;Ll;0;L;;;;;N;;;2CE2;;2CE2 +2CE4;COPTIC SYMBOL KAI;Ll;0;L;;;;;N;;;;; +2CE5;COPTIC SYMBOL MI RO;So;0;ON;;;;;N;;;;; +2CE6;COPTIC SYMBOL PI RO;So;0;ON;;;;;N;;;;; +2CE7;COPTIC SYMBOL STAUROS;So;0;ON;;;;;N;;;;; +2CE8;COPTIC SYMBOL TAU RO;So;0;ON;;;;;N;;;;; +2CE9;COPTIC SYMBOL KHI RO;So;0;ON;;;;;N;;;;; +2CEA;COPTIC SYMBOL SHIMA SIMA;So;0;ON;;;;;N;;;;; +2CEB;COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI;Lu;0;L;;;;;N;;;;2CEC; +2CEC;COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI;Ll;0;L;;;;;N;;;2CEB;;2CEB +2CED;COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA;Lu;0;L;;;;;N;;;;2CEE; +2CEE;COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA;Ll;0;L;;;;;N;;;2CED;;2CED +2CEF;COPTIC COMBINING NI ABOVE;Mn;230;NSM;;;;;N;;;;; +2CF0;COPTIC COMBINING SPIRITUS ASPER;Mn;230;NSM;;;;;N;;;;; +2CF1;COPTIC COMBINING SPIRITUS LENIS;Mn;230;NSM;;;;;N;;;;; +2CF2;COPTIC CAPITAL LETTER BOHAIRIC KHEI;Lu;0;L;;;;;N;;;;2CF3; +2CF3;COPTIC SMALL LETTER BOHAIRIC KHEI;Ll;0;L;;;;;N;;;2CF2;;2CF2 +2CF9;COPTIC OLD NUBIAN FULL STOP;Po;0;ON;;;;;N;;;;; +2CFA;COPTIC OLD NUBIAN DIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; +2CFB;COPTIC OLD NUBIAN INDIRECT QUESTION MARK;Po;0;ON;;;;;N;;;;; +2CFC;COPTIC OLD NUBIAN VERSE DIVIDER;Po;0;ON;;;;;N;;;;; +2CFD;COPTIC FRACTION ONE HALF;No;0;ON;;;;1/2;N;;;;; +2CFE;COPTIC FULL STOP;Po;0;ON;;;;;N;;;;; +2CFF;COPTIC MORPHOLOGICAL DIVIDER;Po;0;ON;;;;;N;;;;; +2D00;GEORGIAN SMALL LETTER AN;Ll;0;L;;;;;N;;;10A0;;10A0 +2D01;GEORGIAN SMALL LETTER BAN;Ll;0;L;;;;;N;;;10A1;;10A1 +2D02;GEORGIAN SMALL LETTER GAN;Ll;0;L;;;;;N;;;10A2;;10A2 +2D03;GEORGIAN SMALL LETTER DON;Ll;0;L;;;;;N;;;10A3;;10A3 +2D04;GEORGIAN SMALL LETTER EN;Ll;0;L;;;;;N;;;10A4;;10A4 +2D05;GEORGIAN SMALL LETTER VIN;Ll;0;L;;;;;N;;;10A5;;10A5 +2D06;GEORGIAN SMALL LETTER ZEN;Ll;0;L;;;;;N;;;10A6;;10A6 +2D07;GEORGIAN SMALL LETTER TAN;Ll;0;L;;;;;N;;;10A7;;10A7 +2D08;GEORGIAN SMALL LETTER IN;Ll;0;L;;;;;N;;;10A8;;10A8 +2D09;GEORGIAN SMALL LETTER KAN;Ll;0;L;;;;;N;;;10A9;;10A9 +2D0A;GEORGIAN SMALL LETTER LAS;Ll;0;L;;;;;N;;;10AA;;10AA +2D0B;GEORGIAN SMALL LETTER MAN;Ll;0;L;;;;;N;;;10AB;;10AB +2D0C;GEORGIAN SMALL LETTER NAR;Ll;0;L;;;;;N;;;10AC;;10AC +2D0D;GEORGIAN SMALL LETTER ON;Ll;0;L;;;;;N;;;10AD;;10AD +2D0E;GEORGIAN SMALL LETTER PAR;Ll;0;L;;;;;N;;;10AE;;10AE +2D0F;GEORGIAN SMALL LETTER ZHAR;Ll;0;L;;;;;N;;;10AF;;10AF +2D10;GEORGIAN SMALL LETTER RAE;Ll;0;L;;;;;N;;;10B0;;10B0 +2D11;GEORGIAN SMALL LETTER SAN;Ll;0;L;;;;;N;;;10B1;;10B1 +2D12;GEORGIAN SMALL LETTER TAR;Ll;0;L;;;;;N;;;10B2;;10B2 +2D13;GEORGIAN SMALL LETTER UN;Ll;0;L;;;;;N;;;10B3;;10B3 +2D14;GEORGIAN SMALL LETTER PHAR;Ll;0;L;;;;;N;;;10B4;;10B4 +2D15;GEORGIAN SMALL LETTER KHAR;Ll;0;L;;;;;N;;;10B5;;10B5 +2D16;GEORGIAN SMALL LETTER GHAN;Ll;0;L;;;;;N;;;10B6;;10B6 +2D17;GEORGIAN SMALL LETTER QAR;Ll;0;L;;;;;N;;;10B7;;10B7 +2D18;GEORGIAN SMALL LETTER SHIN;Ll;0;L;;;;;N;;;10B8;;10B8 +2D19;GEORGIAN SMALL LETTER CHIN;Ll;0;L;;;;;N;;;10B9;;10B9 +2D1A;GEORGIAN SMALL LETTER CAN;Ll;0;L;;;;;N;;;10BA;;10BA +2D1B;GEORGIAN SMALL LETTER JIL;Ll;0;L;;;;;N;;;10BB;;10BB +2D1C;GEORGIAN SMALL LETTER CIL;Ll;0;L;;;;;N;;;10BC;;10BC +2D1D;GEORGIAN SMALL LETTER CHAR;Ll;0;L;;;;;N;;;10BD;;10BD +2D1E;GEORGIAN SMALL LETTER XAN;Ll;0;L;;;;;N;;;10BE;;10BE +2D1F;GEORGIAN SMALL LETTER JHAN;Ll;0;L;;;;;N;;;10BF;;10BF +2D20;GEORGIAN SMALL LETTER HAE;Ll;0;L;;;;;N;;;10C0;;10C0 +2D21;GEORGIAN SMALL LETTER HE;Ll;0;L;;;;;N;;;10C1;;10C1 +2D22;GEORGIAN SMALL LETTER HIE;Ll;0;L;;;;;N;;;10C2;;10C2 +2D23;GEORGIAN SMALL LETTER WE;Ll;0;L;;;;;N;;;10C3;;10C3 +2D24;GEORGIAN SMALL LETTER HAR;Ll;0;L;;;;;N;;;10C4;;10C4 +2D25;GEORGIAN SMALL LETTER HOE;Ll;0;L;;;;;N;;;10C5;;10C5 +2D27;GEORGIAN SMALL LETTER YN;Ll;0;L;;;;;N;;;10C7;;10C7 +2D2D;GEORGIAN SMALL LETTER AEN;Ll;0;L;;;;;N;;;10CD;;10CD +2D30;TIFINAGH LETTER YA;Lo;0;L;;;;;N;;;;; +2D31;TIFINAGH LETTER YAB;Lo;0;L;;;;;N;;;;; +2D32;TIFINAGH LETTER YABH;Lo;0;L;;;;;N;;;;; +2D33;TIFINAGH LETTER YAG;Lo;0;L;;;;;N;;;;; +2D34;TIFINAGH LETTER YAGHH;Lo;0;L;;;;;N;;;;; +2D35;TIFINAGH LETTER BERBER ACADEMY YAJ;Lo;0;L;;;;;N;;;;; +2D36;TIFINAGH LETTER YAJ;Lo;0;L;;;;;N;;;;; +2D37;TIFINAGH LETTER YAD;Lo;0;L;;;;;N;;;;; +2D38;TIFINAGH LETTER YADH;Lo;0;L;;;;;N;;;;; +2D39;TIFINAGH LETTER YADD;Lo;0;L;;;;;N;;;;; +2D3A;TIFINAGH LETTER YADDH;Lo;0;L;;;;;N;;;;; +2D3B;TIFINAGH LETTER YEY;Lo;0;L;;;;;N;;;;; +2D3C;TIFINAGH LETTER YAF;Lo;0;L;;;;;N;;;;; +2D3D;TIFINAGH LETTER YAK;Lo;0;L;;;;;N;;;;; +2D3E;TIFINAGH LETTER TUAREG YAK;Lo;0;L;;;;;N;;;;; +2D3F;TIFINAGH LETTER YAKHH;Lo;0;L;;;;;N;;;;; +2D40;TIFINAGH LETTER YAH;Lo;0;L;;;;;N;;;;; +2D41;TIFINAGH LETTER BERBER ACADEMY YAH;Lo;0;L;;;;;N;;;;; +2D42;TIFINAGH LETTER TUAREG YAH;Lo;0;L;;;;;N;;;;; +2D43;TIFINAGH LETTER YAHH;Lo;0;L;;;;;N;;;;; +2D44;TIFINAGH LETTER YAA;Lo;0;L;;;;;N;;;;; +2D45;TIFINAGH LETTER YAKH;Lo;0;L;;;;;N;;;;; +2D46;TIFINAGH LETTER TUAREG YAKH;Lo;0;L;;;;;N;;;;; +2D47;TIFINAGH LETTER YAQ;Lo;0;L;;;;;N;;;;; +2D48;TIFINAGH LETTER TUAREG YAQ;Lo;0;L;;;;;N;;;;; +2D49;TIFINAGH LETTER YI;Lo;0;L;;;;;N;;;;; +2D4A;TIFINAGH LETTER YAZH;Lo;0;L;;;;;N;;;;; +2D4B;TIFINAGH LETTER AHAGGAR YAZH;Lo;0;L;;;;;N;;;;; +2D4C;TIFINAGH LETTER TUAREG YAZH;Lo;0;L;;;;;N;;;;; +2D4D;TIFINAGH LETTER YAL;Lo;0;L;;;;;N;;;;; +2D4E;TIFINAGH LETTER YAM;Lo;0;L;;;;;N;;;;; +2D4F;TIFINAGH LETTER YAN;Lo;0;L;;;;;N;;;;; +2D50;TIFINAGH LETTER TUAREG YAGN;Lo;0;L;;;;;N;;;;; +2D51;TIFINAGH LETTER TUAREG YANG;Lo;0;L;;;;;N;;;;; +2D52;TIFINAGH LETTER YAP;Lo;0;L;;;;;N;;;;; +2D53;TIFINAGH LETTER YU;Lo;0;L;;;;;N;;;;; +2D54;TIFINAGH LETTER YAR;Lo;0;L;;;;;N;;;;; +2D55;TIFINAGH LETTER YARR;Lo;0;L;;;;;N;;;;; +2D56;TIFINAGH LETTER YAGH;Lo;0;L;;;;;N;;;;; +2D57;TIFINAGH LETTER TUAREG YAGH;Lo;0;L;;;;;N;;;;; +2D58;TIFINAGH LETTER AYER YAGH;Lo;0;L;;;;;N;;;;; +2D59;TIFINAGH LETTER YAS;Lo;0;L;;;;;N;;;;; +2D5A;TIFINAGH LETTER YASS;Lo;0;L;;;;;N;;;;; +2D5B;TIFINAGH LETTER YASH;Lo;0;L;;;;;N;;;;; +2D5C;TIFINAGH LETTER YAT;Lo;0;L;;;;;N;;;;; +2D5D;TIFINAGH LETTER YATH;Lo;0;L;;;;;N;;;;; +2D5E;TIFINAGH LETTER YACH;Lo;0;L;;;;;N;;;;; +2D5F;TIFINAGH LETTER YATT;Lo;0;L;;;;;N;;;;; +2D60;TIFINAGH LETTER YAV;Lo;0;L;;;;;N;;;;; +2D61;TIFINAGH LETTER YAW;Lo;0;L;;;;;N;;;;; +2D62;TIFINAGH LETTER YAY;Lo;0;L;;;;;N;;;;; +2D63;TIFINAGH LETTER YAZ;Lo;0;L;;;;;N;;;;; +2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; +2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; +2D66;TIFINAGH LETTER YE;Lo;0;L;;;;;N;;;;; +2D67;TIFINAGH LETTER YO;Lo;0;L;;;;;N;;;;; +2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L; 2D61;;;;N;;;;; +2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;; +2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;; +2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; +2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; +2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; +2D83;ETHIOPIC SYLLABLE SOA;Lo;0;L;;;;;N;;;;; +2D84;ETHIOPIC SYLLABLE SHOA;Lo;0;L;;;;;N;;;;; +2D85;ETHIOPIC SYLLABLE BOA;Lo;0;L;;;;;N;;;;; +2D86;ETHIOPIC SYLLABLE TOA;Lo;0;L;;;;;N;;;;; +2D87;ETHIOPIC SYLLABLE COA;Lo;0;L;;;;;N;;;;; +2D88;ETHIOPIC SYLLABLE NOA;Lo;0;L;;;;;N;;;;; +2D89;ETHIOPIC SYLLABLE NYOA;Lo;0;L;;;;;N;;;;; +2D8A;ETHIOPIC SYLLABLE GLOTTAL OA;Lo;0;L;;;;;N;;;;; +2D8B;ETHIOPIC SYLLABLE ZOA;Lo;0;L;;;;;N;;;;; +2D8C;ETHIOPIC SYLLABLE DOA;Lo;0;L;;;;;N;;;;; +2D8D;ETHIOPIC SYLLABLE DDOA;Lo;0;L;;;;;N;;;;; +2D8E;ETHIOPIC SYLLABLE JOA;Lo;0;L;;;;;N;;;;; +2D8F;ETHIOPIC SYLLABLE THOA;Lo;0;L;;;;;N;;;;; +2D90;ETHIOPIC SYLLABLE CHOA;Lo;0;L;;;;;N;;;;; +2D91;ETHIOPIC SYLLABLE PHOA;Lo;0;L;;;;;N;;;;; +2D92;ETHIOPIC SYLLABLE POA;Lo;0;L;;;;;N;;;;; +2D93;ETHIOPIC SYLLABLE GGWA;Lo;0;L;;;;;N;;;;; +2D94;ETHIOPIC SYLLABLE GGWI;Lo;0;L;;;;;N;;;;; +2D95;ETHIOPIC SYLLABLE GGWEE;Lo;0;L;;;;;N;;;;; +2D96;ETHIOPIC SYLLABLE GGWE;Lo;0;L;;;;;N;;;;; +2DA0;ETHIOPIC SYLLABLE SSA;Lo;0;L;;;;;N;;;;; +2DA1;ETHIOPIC SYLLABLE SSU;Lo;0;L;;;;;N;;;;; +2DA2;ETHIOPIC SYLLABLE SSI;Lo;0;L;;;;;N;;;;; +2DA3;ETHIOPIC SYLLABLE SSAA;Lo;0;L;;;;;N;;;;; +2DA4;ETHIOPIC SYLLABLE SSEE;Lo;0;L;;;;;N;;;;; +2DA5;ETHIOPIC SYLLABLE SSE;Lo;0;L;;;;;N;;;;; +2DA6;ETHIOPIC SYLLABLE SSO;Lo;0;L;;;;;N;;;;; +2DA8;ETHIOPIC SYLLABLE CCA;Lo;0;L;;;;;N;;;;; +2DA9;ETHIOPIC SYLLABLE CCU;Lo;0;L;;;;;N;;;;; +2DAA;ETHIOPIC SYLLABLE CCI;Lo;0;L;;;;;N;;;;; +2DAB;ETHIOPIC SYLLABLE CCAA;Lo;0;L;;;;;N;;;;; +2DAC;ETHIOPIC SYLLABLE CCEE;Lo;0;L;;;;;N;;;;; +2DAD;ETHIOPIC SYLLABLE CCE;Lo;0;L;;;;;N;;;;; +2DAE;ETHIOPIC SYLLABLE CCO;Lo;0;L;;;;;N;;;;; +2DB0;ETHIOPIC SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; +2DB1;ETHIOPIC SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; +2DB2;ETHIOPIC SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; +2DB3;ETHIOPIC SYLLABLE ZZAA;Lo;0;L;;;;;N;;;;; +2DB4;ETHIOPIC SYLLABLE ZZEE;Lo;0;L;;;;;N;;;;; +2DB5;ETHIOPIC SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; +2DB6;ETHIOPIC SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; +2DB8;ETHIOPIC SYLLABLE CCHA;Lo;0;L;;;;;N;;;;; +2DB9;ETHIOPIC SYLLABLE CCHU;Lo;0;L;;;;;N;;;;; +2DBA;ETHIOPIC SYLLABLE CCHI;Lo;0;L;;;;;N;;;;; +2DBB;ETHIOPIC SYLLABLE CCHAA;Lo;0;L;;;;;N;;;;; +2DBC;ETHIOPIC SYLLABLE CCHEE;Lo;0;L;;;;;N;;;;; +2DBD;ETHIOPIC SYLLABLE CCHE;Lo;0;L;;;;;N;;;;; +2DBE;ETHIOPIC SYLLABLE CCHO;Lo;0;L;;;;;N;;;;; +2DC0;ETHIOPIC SYLLABLE QYA;Lo;0;L;;;;;N;;;;; +2DC1;ETHIOPIC SYLLABLE QYU;Lo;0;L;;;;;N;;;;; +2DC2;ETHIOPIC SYLLABLE QYI;Lo;0;L;;;;;N;;;;; +2DC3;ETHIOPIC SYLLABLE QYAA;Lo;0;L;;;;;N;;;;; +2DC4;ETHIOPIC SYLLABLE QYEE;Lo;0;L;;;;;N;;;;; +2DC5;ETHIOPIC SYLLABLE QYE;Lo;0;L;;;;;N;;;;; +2DC6;ETHIOPIC SYLLABLE QYO;Lo;0;L;;;;;N;;;;; +2DC8;ETHIOPIC SYLLABLE KYA;Lo;0;L;;;;;N;;;;; +2DC9;ETHIOPIC SYLLABLE KYU;Lo;0;L;;;;;N;;;;; +2DCA;ETHIOPIC SYLLABLE KYI;Lo;0;L;;;;;N;;;;; +2DCB;ETHIOPIC SYLLABLE KYAA;Lo;0;L;;;;;N;;;;; +2DCC;ETHIOPIC SYLLABLE KYEE;Lo;0;L;;;;;N;;;;; +2DCD;ETHIOPIC SYLLABLE KYE;Lo;0;L;;;;;N;;;;; +2DCE;ETHIOPIC SYLLABLE KYO;Lo;0;L;;;;;N;;;;; +2DD0;ETHIOPIC SYLLABLE XYA;Lo;0;L;;;;;N;;;;; +2DD1;ETHIOPIC SYLLABLE XYU;Lo;0;L;;;;;N;;;;; +2DD2;ETHIOPIC SYLLABLE XYI;Lo;0;L;;;;;N;;;;; +2DD3;ETHIOPIC SYLLABLE XYAA;Lo;0;L;;;;;N;;;;; +2DD4;ETHIOPIC SYLLABLE XYEE;Lo;0;L;;;;;N;;;;; +2DD5;ETHIOPIC SYLLABLE XYE;Lo;0;L;;;;;N;;;;; +2DD6;ETHIOPIC SYLLABLE XYO;Lo;0;L;;;;;N;;;;; +2DD8;ETHIOPIC SYLLABLE GYA;Lo;0;L;;;;;N;;;;; +2DD9;ETHIOPIC SYLLABLE GYU;Lo;0;L;;;;;N;;;;; +2DDA;ETHIOPIC SYLLABLE GYI;Lo;0;L;;;;;N;;;;; +2DDB;ETHIOPIC SYLLABLE GYAA;Lo;0;L;;;;;N;;;;; +2DDC;ETHIOPIC SYLLABLE GYEE;Lo;0;L;;;;;N;;;;; +2DDD;ETHIOPIC SYLLABLE GYE;Lo;0;L;;;;;N;;;;; +2DDE;ETHIOPIC SYLLABLE GYO;Lo;0;L;;;;;N;;;;; +2DE0;COMBINING CYRILLIC LETTER BE;Mn;230;NSM;;;;;N;;;;; +2DE1;COMBINING CYRILLIC LETTER VE;Mn;230;NSM;;;;;N;;;;; +2DE2;COMBINING CYRILLIC LETTER GHE;Mn;230;NSM;;;;;N;;;;; +2DE3;COMBINING CYRILLIC LETTER DE;Mn;230;NSM;;;;;N;;;;; +2DE4;COMBINING CYRILLIC LETTER ZHE;Mn;230;NSM;;;;;N;;;;; +2DE5;COMBINING CYRILLIC LETTER ZE;Mn;230;NSM;;;;;N;;;;; +2DE6;COMBINING CYRILLIC LETTER KA;Mn;230;NSM;;;;;N;;;;; +2DE7;COMBINING CYRILLIC LETTER EL;Mn;230;NSM;;;;;N;;;;; +2DE8;COMBINING CYRILLIC LETTER EM;Mn;230;NSM;;;;;N;;;;; +2DE9;COMBINING CYRILLIC LETTER EN;Mn;230;NSM;;;;;N;;;;; +2DEA;COMBINING CYRILLIC LETTER O;Mn;230;NSM;;;;;N;;;;; +2DEB;COMBINING CYRILLIC LETTER PE;Mn;230;NSM;;;;;N;;;;; +2DEC;COMBINING CYRILLIC LETTER ER;Mn;230;NSM;;;;;N;;;;; +2DED;COMBINING CYRILLIC LETTER ES;Mn;230;NSM;;;;;N;;;;; +2DEE;COMBINING CYRILLIC LETTER TE;Mn;230;NSM;;;;;N;;;;; +2DEF;COMBINING CYRILLIC LETTER HA;Mn;230;NSM;;;;;N;;;;; +2DF0;COMBINING CYRILLIC LETTER TSE;Mn;230;NSM;;;;;N;;;;; +2DF1;COMBINING CYRILLIC LETTER CHE;Mn;230;NSM;;;;;N;;;;; +2DF2;COMBINING CYRILLIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; +2DF3;COMBINING CYRILLIC LETTER SHCHA;Mn;230;NSM;;;;;N;;;;; +2DF4;COMBINING CYRILLIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; +2DF5;COMBINING CYRILLIC LETTER ES-TE;Mn;230;NSM;;;;;N;;;;; +2DF6;COMBINING CYRILLIC LETTER A;Mn;230;NSM;;;;;N;;;;; +2DF7;COMBINING CYRILLIC LETTER IE;Mn;230;NSM;;;;;N;;;;; +2DF8;COMBINING CYRILLIC LETTER DJERV;Mn;230;NSM;;;;;N;;;;; +2DF9;COMBINING CYRILLIC LETTER MONOGRAPH UK;Mn;230;NSM;;;;;N;;;;; +2DFA;COMBINING CYRILLIC LETTER YAT;Mn;230;NSM;;;;;N;;;;; +2DFB;COMBINING CYRILLIC LETTER YU;Mn;230;NSM;;;;;N;;;;; +2DFC;COMBINING CYRILLIC LETTER IOTIFIED A;Mn;230;NSM;;;;;N;;;;; +2DFD;COMBINING CYRILLIC LETTER LITTLE YUS;Mn;230;NSM;;;;;N;;;;; +2DFE;COMBINING CYRILLIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; +2DFF;COMBINING CYRILLIC LETTER IOTIFIED BIG YUS;Mn;230;NSM;;;;;N;;;;; +2E00;RIGHT ANGLE SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; +2E01;RIGHT ANGLE DOTTED SUBSTITUTION MARKER;Po;0;ON;;;;;N;;;;; +2E02;LEFT SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E03;RIGHT SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E04;LEFT DOTTED SUBSTITUTION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E05;RIGHT DOTTED SUBSTITUTION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E06;RAISED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; +2E07;RAISED DOTTED INTERPOLATION MARKER;Po;0;ON;;;;;N;;;;; +2E08;DOTTED TRANSPOSITION MARKER;Po;0;ON;;;;;N;;;;; +2E09;LEFT TRANSPOSITION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E0A;RIGHT TRANSPOSITION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E0B;RAISED SQUARE;Po;0;ON;;;;;N;;;;; +2E0C;LEFT RAISED OMISSION BRACKET;Pi;0;ON;;;;;Y;;;;; +2E0D;RIGHT RAISED OMISSION BRACKET;Pf;0;ON;;;;;Y;;;;; +2E0E;EDITORIAL CORONIS;Po;0;ON;;;;;N;;;;; +2E0F;PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E10;FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E11;REVERSED FORKED PARAGRAPHOS;Po;0;ON;;;;;N;;;;; +2E12;HYPODIASTOLE;Po;0;ON;;;;;N;;;;; +2E13;DOTTED OBELOS;Po;0;ON;;;;;N;;;;; +2E14;DOWNWARDS ANCORA;Po;0;ON;;;;;N;;;;; +2E15;UPWARDS ANCORA;Po;0;ON;;;;;N;;;;; +2E16;DOTTED RIGHT-POINTING ANGLE;Po;0;ON;;;;;N;;;;; +2E17;DOUBLE OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; +2E18;INVERTED INTERROBANG;Po;0;ON;;;;;N;;;;; +2E19;PALM BRANCH;Po;0;ON;;;;;N;;;;; +2E1A;HYPHEN WITH DIAERESIS;Pd;0;ON;;;;;N;;;;; +2E1B;TILDE WITH RING ABOVE;Po;0;ON;;;;;N;;;;; +2E1C;LEFT LOW PARAPHRASE BRACKET;Pi;0;ON;;;;;Y;;;;; +2E1D;RIGHT LOW PARAPHRASE BRACKET;Pf;0;ON;;;;;Y;;;;; +2E1E;TILDE WITH DOT ABOVE;Po;0;ON;;;;;N;;;;; +2E1F;TILDE WITH DOT BELOW;Po;0;ON;;;;;N;;;;; +2E20;LEFT VERTICAL BAR WITH QUILL;Pi;0;ON;;;;;Y;;;;; +2E21;RIGHT VERTICAL BAR WITH QUILL;Pf;0;ON;;;;;Y;;;;; +2E22;TOP LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; +2E23;TOP RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; +2E24;BOTTOM LEFT HALF BRACKET;Ps;0;ON;;;;;Y;;;;; +2E25;BOTTOM RIGHT HALF BRACKET;Pe;0;ON;;;;;Y;;;;; +2E26;LEFT SIDEWAYS U BRACKET;Ps;0;ON;;;;;Y;;;;; +2E27;RIGHT SIDEWAYS U BRACKET;Pe;0;ON;;;;;Y;;;;; +2E28;LEFT DOUBLE PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E29;RIGHT DOUBLE PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E2A;TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2B;ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2C;SQUARED FOUR DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +2E2D;FIVE DOT MARK;Po;0;ON;;;;;N;;;;; +2E2E;REVERSED QUESTION MARK;Po;0;ON;;;;;N;;;;; +2E2F;VERTICAL TILDE;Lm;0;ON;;;;;N;;;;; +2E30;RING POINT;Po;0;ON;;;;;N;;;;; +2E31;WORD SEPARATOR MIDDLE DOT;Po;0;ON;;;;;N;;;;; +2E32;TURNED COMMA;Po;0;ON;;;;;N;;;;; +2E33;RAISED DOT;Po;0;ON;;;;;N;;;;; +2E34;RAISED COMMA;Po;0;ON;;;;;N;;;;; +2E35;TURNED SEMICOLON;Po;0;ON;;;;;N;;;;; +2E36;DAGGER WITH LEFT GUARD;Po;0;ON;;;;;N;;;;; +2E37;DAGGER WITH RIGHT GUARD;Po;0;ON;;;;;N;;;;; +2E38;TURNED DAGGER;Po;0;ON;;;;;N;;;;; +2E39;TOP HALF SECTION SIGN;Po;0;ON;;;;;N;;;;; +2E3A;TWO-EM DASH;Pd;0;ON;;;;;N;;;;; +2E3B;THREE-EM DASH;Pd;0;ON;;;;;N;;;;; +2E3C;STENOGRAPHIC FULL STOP;Po;0;ON;;;;;N;;;;; +2E3D;VERTICAL SIX DOTS;Po;0;ON;;;;;N;;;;; +2E3E;WIGGLY VERTICAL LINE;Po;0;ON;;;;;N;;;;; +2E3F;CAPITULUM;Po;0;ON;;;;;N;;;;; +2E40;DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; +2E41;REVERSED COMMA;Po;0;ON;;;;;N;;;;; +2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;; +2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;; +2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;; +2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;; +2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;; +2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;; +2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;; +2E4A;DOTTED SOLIDUS;Po;0;ON;;;;;N;;;;; +2E4B;TRIPLE DAGGER;Po;0;ON;;;;;N;;;;; +2E4C;MEDIEVAL COMMA;Po;0;ON;;;;;N;;;;; +2E4D;PARAGRAPHUS MARK;Po;0;ON;;;;;N;;;;; +2E4E;PUNCTUS ELEVATUS MARK;Po;0;ON;;;;;N;;;;; +2E4F;CORNISH VERSE DIVIDER;Po;0;ON;;;;;N;;;;; +2E50;CROSS PATTY WITH RIGHT CROSSBAR;So;0;ON;;;;;N;;;;; +2E51;CROSS PATTY WITH LEFT CROSSBAR;So;0;ON;;;;;N;;;;; +2E52;TIRONIAN SIGN CAPITAL ET;Po;0;ON;;;;;N;;;;; +2E53;MEDIEVAL EXCLAMATION MARK;Po;0;ON;;;;;N;;;;; +2E54;MEDIEVAL QUESTION MARK;Po;0;ON;;;;;N;;;;; +2E55;LEFT SQUARE BRACKET WITH STROKE;Ps;0;ON;;;;;Y;;;;; +2E56;RIGHT SQUARE BRACKET WITH STROKE;Pe;0;ON;;;;;Y;;;;; +2E57;LEFT SQUARE BRACKET WITH DOUBLE STROKE;Ps;0;ON;;;;;Y;;;;; +2E58;RIGHT SQUARE BRACKET WITH DOUBLE STROKE;Pe;0;ON;;;;;Y;;;;; +2E59;TOP HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E5A;TOP HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E5B;BOTTOM HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;; +2E5C;BOTTOM HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;; +2E5D;OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;; +2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;; +2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;; +2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;; +2E83;CJK RADICAL SECOND TWO;So;0;ON;;;;;N;;;;; +2E84;CJK RADICAL SECOND THREE;So;0;ON;;;;;N;;;;; +2E85;CJK RADICAL PERSON;So;0;ON;;;;;N;;;;; +2E86;CJK RADICAL BOX;So;0;ON;;;;;N;;;;; +2E87;CJK RADICAL TABLE;So;0;ON;;;;;N;;;;; +2E88;CJK RADICAL KNIFE ONE;So;0;ON;;;;;N;;;;; +2E89;CJK RADICAL KNIFE TWO;So;0;ON;;;;;N;;;;; +2E8A;CJK RADICAL DIVINATION;So;0;ON;;;;;N;;;;; +2E8B;CJK RADICAL SEAL;So;0;ON;;;;;N;;;;; +2E8C;CJK RADICAL SMALL ONE;So;0;ON;;;;;N;;;;; +2E8D;CJK RADICAL SMALL TWO;So;0;ON;;;;;N;;;;; +2E8E;CJK RADICAL LAME ONE;So;0;ON;;;;;N;;;;; +2E8F;CJK RADICAL LAME TWO;So;0;ON;;;;;N;;;;; +2E90;CJK RADICAL LAME THREE;So;0;ON;;;;;N;;;;; +2E91;CJK RADICAL LAME FOUR;So;0;ON;;;;;N;;;;; +2E92;CJK RADICAL SNAKE;So;0;ON;;;;;N;;;;; +2E93;CJK RADICAL THREAD;So;0;ON;;;;;N;;;;; +2E94;CJK RADICAL SNOUT ONE;So;0;ON;;;;;N;;;;; +2E95;CJK RADICAL SNOUT TWO;So;0;ON;;;;;N;;;;; +2E96;CJK RADICAL HEART ONE;So;0;ON;;;;;N;;;;; +2E97;CJK RADICAL HEART TWO;So;0;ON;;;;;N;;;;; +2E98;CJK RADICAL HAND;So;0;ON;;;;;N;;;;; +2E99;CJK RADICAL RAP;So;0;ON;;;;;N;;;;; +2E9B;CJK RADICAL CHOKE;So;0;ON;;;;;N;;;;; +2E9C;CJK RADICAL SUN;So;0;ON;;;;;N;;;;; +2E9D;CJK RADICAL MOON;So;0;ON;;;;;N;;;;; +2E9E;CJK RADICAL DEATH;So;0;ON;;;;;N;;;;; +2E9F;CJK RADICAL MOTHER;So;0;ON; 6BCD;;;;N;;;;; +2EA0;CJK RADICAL CIVILIAN;So;0;ON;;;;;N;;;;; +2EA1;CJK RADICAL WATER ONE;So;0;ON;;;;;N;;;;; +2EA2;CJK RADICAL WATER TWO;So;0;ON;;;;;N;;;;; +2EA3;CJK RADICAL FIRE;So;0;ON;;;;;N;;;;; +2EA4;CJK RADICAL PAW ONE;So;0;ON;;;;;N;;;;; +2EA5;CJK RADICAL PAW TWO;So;0;ON;;;;;N;;;;; +2EA6;CJK RADICAL SIMPLIFIED HALF TREE TRUNK;So;0;ON;;;;;N;;;;; +2EA7;CJK RADICAL COW;So;0;ON;;;;;N;;;;; +2EA8;CJK RADICAL DOG;So;0;ON;;;;;N;;;;; +2EA9;CJK RADICAL JADE;So;0;ON;;;;;N;;;;; +2EAA;CJK RADICAL BOLT OF CLOTH;So;0;ON;;;;;N;;;;; +2EAB;CJK RADICAL EYE;So;0;ON;;;;;N;;;;; +2EAC;CJK RADICAL SPIRIT ONE;So;0;ON;;;;;N;;;;; +2EAD;CJK RADICAL SPIRIT TWO;So;0;ON;;;;;N;;;;; +2EAE;CJK RADICAL BAMBOO;So;0;ON;;;;;N;;;;; +2EAF;CJK RADICAL SILK;So;0;ON;;;;;N;;;;; +2EB0;CJK RADICAL C-SIMPLIFIED SILK;So;0;ON;;;;;N;;;;; +2EB1;CJK RADICAL NET ONE;So;0;ON;;;;;N;;;;; +2EB2;CJK RADICAL NET TWO;So;0;ON;;;;;N;;;;; +2EB3;CJK RADICAL NET THREE;So;0;ON;;;;;N;;;;; +2EB4;CJK RADICAL NET FOUR;So;0;ON;;;;;N;;;;; +2EB5;CJK RADICAL MESH;So;0;ON;;;;;N;;;;; +2EB6;CJK RADICAL SHEEP;So;0;ON;;;;;N;;;;; +2EB7;CJK RADICAL RAM;So;0;ON;;;;;N;;;;; +2EB8;CJK RADICAL EWE;So;0;ON;;;;;N;;;;; +2EB9;CJK RADICAL OLD;So;0;ON;;;;;N;;;;; +2EBA;CJK RADICAL BRUSH ONE;So;0;ON;;;;;N;;;;; +2EBB;CJK RADICAL BRUSH TWO;So;0;ON;;;;;N;;;;; +2EBC;CJK RADICAL MEAT;So;0;ON;;;;;N;;;;; +2EBD;CJK RADICAL MORTAR;So;0;ON;;;;;N;;;;; +2EBE;CJK RADICAL GRASS ONE;So;0;ON;;;;;N;;;;; +2EBF;CJK RADICAL GRASS TWO;So;0;ON;;;;;N;;;;; +2EC0;CJK RADICAL GRASS THREE;So;0;ON;;;;;N;;;;; +2EC1;CJK RADICAL TIGER;So;0;ON;;;;;N;;;;; +2EC2;CJK RADICAL CLOTHES;So;0;ON;;;;;N;;;;; +2EC3;CJK RADICAL WEST ONE;So;0;ON;;;;;N;;;;; +2EC4;CJK RADICAL WEST TWO;So;0;ON;;;;;N;;;;; +2EC5;CJK RADICAL C-SIMPLIFIED SEE;So;0;ON;;;;;N;;;;; +2EC6;CJK RADICAL SIMPLIFIED HORN;So;0;ON;;;;;N;;;;; +2EC7;CJK RADICAL HORN;So;0;ON;;;;;N;;;;; +2EC8;CJK RADICAL C-SIMPLIFIED SPEECH;So;0;ON;;;;;N;;;;; +2EC9;CJK RADICAL C-SIMPLIFIED SHELL;So;0;ON;;;;;N;;;;; +2ECA;CJK RADICAL FOOT;So;0;ON;;;;;N;;;;; +2ECB;CJK RADICAL C-SIMPLIFIED CART;So;0;ON;;;;;N;;;;; +2ECC;CJK RADICAL SIMPLIFIED WALK;So;0;ON;;;;;N;;;;; +2ECD;CJK RADICAL WALK ONE;So;0;ON;;;;;N;;;;; +2ECE;CJK RADICAL WALK TWO;So;0;ON;;;;;N;;;;; +2ECF;CJK RADICAL CITY;So;0;ON;;;;;N;;;;; +2ED0;CJK RADICAL C-SIMPLIFIED GOLD;So;0;ON;;;;;N;;;;; +2ED1;CJK RADICAL LONG ONE;So;0;ON;;;;;N;;;;; +2ED2;CJK RADICAL LONG TWO;So;0;ON;;;;;N;;;;; +2ED3;CJK RADICAL C-SIMPLIFIED LONG;So;0;ON;;;;;N;;;;; +2ED4;CJK RADICAL C-SIMPLIFIED GATE;So;0;ON;;;;;N;;;;; +2ED5;CJK RADICAL MOUND ONE;So;0;ON;;;;;N;;;;; +2ED6;CJK RADICAL MOUND TWO;So;0;ON;;;;;N;;;;; +2ED7;CJK RADICAL RAIN;So;0;ON;;;;;N;;;;; +2ED8;CJK RADICAL BLUE;So;0;ON;;;;;N;;;;; +2ED9;CJK RADICAL C-SIMPLIFIED TANNED LEATHER;So;0;ON;;;;;N;;;;; +2EDA;CJK RADICAL C-SIMPLIFIED LEAF;So;0;ON;;;;;N;;;;; +2EDB;CJK RADICAL C-SIMPLIFIED WIND;So;0;ON;;;;;N;;;;; +2EDC;CJK RADICAL C-SIMPLIFIED FLY;So;0;ON;;;;;N;;;;; +2EDD;CJK RADICAL EAT ONE;So;0;ON;;;;;N;;;;; +2EDE;CJK RADICAL EAT TWO;So;0;ON;;;;;N;;;;; +2EDF;CJK RADICAL EAT THREE;So;0;ON;;;;;N;;;;; +2EE0;CJK RADICAL C-SIMPLIFIED EAT;So;0;ON;;;;;N;;;;; +2EE1;CJK RADICAL HEAD;So;0;ON;;;;;N;;;;; +2EE2;CJK RADICAL C-SIMPLIFIED HORSE;So;0;ON;;;;;N;;;;; +2EE3;CJK RADICAL BONE;So;0;ON;;;;;N;;;;; +2EE4;CJK RADICAL GHOST;So;0;ON;;;;;N;;;;; +2EE5;CJK RADICAL C-SIMPLIFIED FISH;So;0;ON;;;;;N;;;;; +2EE6;CJK RADICAL C-SIMPLIFIED BIRD;So;0;ON;;;;;N;;;;; +2EE7;CJK RADICAL C-SIMPLIFIED SALT;So;0;ON;;;;;N;;;;; +2EE8;CJK RADICAL SIMPLIFIED WHEAT;So;0;ON;;;;;N;;;;; +2EE9;CJK RADICAL SIMPLIFIED YELLOW;So;0;ON;;;;;N;;;;; +2EEA;CJK RADICAL C-SIMPLIFIED FROG;So;0;ON;;;;;N;;;;; +2EEB;CJK RADICAL J-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; +2EEC;CJK RADICAL C-SIMPLIFIED EVEN;So;0;ON;;;;;N;;;;; +2EED;CJK RADICAL J-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; +2EEE;CJK RADICAL C-SIMPLIFIED TOOTH;So;0;ON;;;;;N;;;;; +2EEF;CJK RADICAL J-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; +2EF0;CJK RADICAL C-SIMPLIFIED DRAGON;So;0;ON;;;;;N;;;;; +2EF1;CJK RADICAL TURTLE;So;0;ON;;;;;N;;;;; +2EF2;CJK RADICAL J-SIMPLIFIED TURTLE;So;0;ON;;;;;N;;;;; +2EF3;CJK RADICAL C-SIMPLIFIED TURTLE;So;0;ON; 9F9F;;;;N;;;;; +2F00;KANGXI RADICAL ONE;So;0;ON; 4E00;;;;N;;;;; +2F01;KANGXI RADICAL LINE;So;0;ON; 4E28;;;;N;;;;; +2F02;KANGXI RADICAL DOT;So;0;ON; 4E36;;;;N;;;;; +2F03;KANGXI RADICAL SLASH;So;0;ON; 4E3F;;;;N;;;;; +2F04;KANGXI RADICAL SECOND;So;0;ON; 4E59;;;;N;;;;; +2F05;KANGXI RADICAL HOOK;So;0;ON; 4E85;;;;N;;;;; +2F06;KANGXI RADICAL TWO;So;0;ON; 4E8C;;;;N;;;;; +2F07;KANGXI RADICAL LID;So;0;ON; 4EA0;;;;N;;;;; +2F08;KANGXI RADICAL MAN;So;0;ON; 4EBA;;;;N;;;;; +2F09;KANGXI RADICAL LEGS;So;0;ON; 513F;;;;N;;;;; +2F0A;KANGXI RADICAL ENTER;So;0;ON; 5165;;;;N;;;;; +2F0B;KANGXI RADICAL EIGHT;So;0;ON; 516B;;;;N;;;;; +2F0C;KANGXI RADICAL DOWN BOX;So;0;ON; 5182;;;;N;;;;; +2F0D;KANGXI RADICAL COVER;So;0;ON; 5196;;;;N;;;;; +2F0E;KANGXI RADICAL ICE;So;0;ON; 51AB;;;;N;;;;; +2F0F;KANGXI RADICAL TABLE;So;0;ON; 51E0;;;;N;;;;; +2F10;KANGXI RADICAL OPEN BOX;So;0;ON; 51F5;;;;N;;;;; +2F11;KANGXI RADICAL KNIFE;So;0;ON; 5200;;;;N;;;;; +2F12;KANGXI RADICAL POWER;So;0;ON; 529B;;;;N;;;;; +2F13;KANGXI RADICAL WRAP;So;0;ON; 52F9;;;;N;;;;; +2F14;KANGXI RADICAL SPOON;So;0;ON; 5315;;;;N;;;;; +2F15;KANGXI RADICAL RIGHT OPEN BOX;So;0;ON; 531A;;;;N;;;;; +2F16;KANGXI RADICAL HIDING ENCLOSURE;So;0;ON; 5338;;;;N;;;;; +2F17;KANGXI RADICAL TEN;So;0;ON; 5341;;;;N;;;;; +2F18;KANGXI RADICAL DIVINATION;So;0;ON; 535C;;;;N;;;;; +2F19;KANGXI RADICAL SEAL;So;0;ON; 5369;;;;N;;;;; +2F1A;KANGXI RADICAL CLIFF;So;0;ON; 5382;;;;N;;;;; +2F1B;KANGXI RADICAL PRIVATE;So;0;ON; 53B6;;;;N;;;;; +2F1C;KANGXI RADICAL AGAIN;So;0;ON; 53C8;;;;N;;;;; +2F1D;KANGXI RADICAL MOUTH;So;0;ON; 53E3;;;;N;;;;; +2F1E;KANGXI RADICAL ENCLOSURE;So;0;ON; 56D7;;;;N;;;;; +2F1F;KANGXI RADICAL EARTH;So;0;ON; 571F;;;;N;;;;; +2F20;KANGXI RADICAL SCHOLAR;So;0;ON; 58EB;;;;N;;;;; +2F21;KANGXI RADICAL GO;So;0;ON; 5902;;;;N;;;;; +2F22;KANGXI RADICAL GO SLOWLY;So;0;ON; 590A;;;;N;;;;; +2F23;KANGXI RADICAL EVENING;So;0;ON; 5915;;;;N;;;;; +2F24;KANGXI RADICAL BIG;So;0;ON; 5927;;;;N;;;;; +2F25;KANGXI RADICAL WOMAN;So;0;ON; 5973;;;;N;;;;; +2F26;KANGXI RADICAL CHILD;So;0;ON; 5B50;;;;N;;;;; +2F27;KANGXI RADICAL ROOF;So;0;ON; 5B80;;;;N;;;;; +2F28;KANGXI RADICAL INCH;So;0;ON; 5BF8;;;;N;;;;; +2F29;KANGXI RADICAL SMALL;So;0;ON; 5C0F;;;;N;;;;; +2F2A;KANGXI RADICAL LAME;So;0;ON; 5C22;;;;N;;;;; +2F2B;KANGXI RADICAL CORPSE;So;0;ON; 5C38;;;;N;;;;; +2F2C;KANGXI RADICAL SPROUT;So;0;ON; 5C6E;;;;N;;;;; +2F2D;KANGXI RADICAL MOUNTAIN;So;0;ON; 5C71;;;;N;;;;; +2F2E;KANGXI RADICAL RIVER;So;0;ON; 5DDB;;;;N;;;;; +2F2F;KANGXI RADICAL WORK;So;0;ON; 5DE5;;;;N;;;;; +2F30;KANGXI RADICAL ONESELF;So;0;ON; 5DF1;;;;N;;;;; +2F31;KANGXI RADICAL TURBAN;So;0;ON; 5DFE;;;;N;;;;; +2F32;KANGXI RADICAL DRY;So;0;ON; 5E72;;;;N;;;;; +2F33;KANGXI RADICAL SHORT THREAD;So;0;ON; 5E7A;;;;N;;;;; +2F34;KANGXI RADICAL DOTTED CLIFF;So;0;ON; 5E7F;;;;N;;;;; +2F35;KANGXI RADICAL LONG STRIDE;So;0;ON; 5EF4;;;;N;;;;; +2F36;KANGXI RADICAL TWO HANDS;So;0;ON; 5EFE;;;;N;;;;; +2F37;KANGXI RADICAL SHOOT;So;0;ON; 5F0B;;;;N;;;;; +2F38;KANGXI RADICAL BOW;So;0;ON; 5F13;;;;N;;;;; +2F39;KANGXI RADICAL SNOUT;So;0;ON; 5F50;;;;N;;;;; +2F3A;KANGXI RADICAL BRISTLE;So;0;ON; 5F61;;;;N;;;;; +2F3B;KANGXI RADICAL STEP;So;0;ON; 5F73;;;;N;;;;; +2F3C;KANGXI RADICAL HEART;So;0;ON; 5FC3;;;;N;;;;; +2F3D;KANGXI RADICAL HALBERD;So;0;ON; 6208;;;;N;;;;; +2F3E;KANGXI RADICAL DOOR;So;0;ON; 6236;;;;N;;;;; +2F3F;KANGXI RADICAL HAND;So;0;ON; 624B;;;;N;;;;; +2F40;KANGXI RADICAL BRANCH;So;0;ON; 652F;;;;N;;;;; +2F41;KANGXI RADICAL RAP;So;0;ON; 6534;;;;N;;;;; +2F42;KANGXI RADICAL SCRIPT;So;0;ON; 6587;;;;N;;;;; +2F43;KANGXI RADICAL DIPPER;So;0;ON; 6597;;;;N;;;;; +2F44;KANGXI RADICAL AXE;So;0;ON; 65A4;;;;N;;;;; +2F45;KANGXI RADICAL SQUARE;So;0;ON; 65B9;;;;N;;;;; +2F46;KANGXI RADICAL NOT;So;0;ON; 65E0;;;;N;;;;; +2F47;KANGXI RADICAL SUN;So;0;ON; 65E5;;;;N;;;;; +2F48;KANGXI RADICAL SAY;So;0;ON; 66F0;;;;N;;;;; +2F49;KANGXI RADICAL MOON;So;0;ON; 6708;;;;N;;;;; +2F4A;KANGXI RADICAL TREE;So;0;ON; 6728;;;;N;;;;; +2F4B;KANGXI RADICAL LACK;So;0;ON; 6B20;;;;N;;;;; +2F4C;KANGXI RADICAL STOP;So;0;ON; 6B62;;;;N;;;;; +2F4D;KANGXI RADICAL DEATH;So;0;ON; 6B79;;;;N;;;;; +2F4E;KANGXI RADICAL WEAPON;So;0;ON; 6BB3;;;;N;;;;; +2F4F;KANGXI RADICAL DO NOT;So;0;ON; 6BCB;;;;N;;;;; +2F50;KANGXI RADICAL COMPARE;So;0;ON; 6BD4;;;;N;;;;; +2F51;KANGXI RADICAL FUR;So;0;ON; 6BDB;;;;N;;;;; +2F52;KANGXI RADICAL CLAN;So;0;ON; 6C0F;;;;N;;;;; +2F53;KANGXI RADICAL STEAM;So;0;ON; 6C14;;;;N;;;;; +2F54;KANGXI RADICAL WATER;So;0;ON; 6C34;;;;N;;;;; +2F55;KANGXI RADICAL FIRE;So;0;ON; 706B;;;;N;;;;; +2F56;KANGXI RADICAL CLAW;So;0;ON; 722A;;;;N;;;;; +2F57;KANGXI RADICAL FATHER;So;0;ON; 7236;;;;N;;;;; +2F58;KANGXI RADICAL DOUBLE X;So;0;ON; 723B;;;;N;;;;; +2F59;KANGXI RADICAL HALF TREE TRUNK;So;0;ON; 723F;;;;N;;;;; +2F5A;KANGXI RADICAL SLICE;So;0;ON; 7247;;;;N;;;;; +2F5B;KANGXI RADICAL FANG;So;0;ON; 7259;;;;N;;;;; +2F5C;KANGXI RADICAL COW;So;0;ON; 725B;;;;N;;;;; +2F5D;KANGXI RADICAL DOG;So;0;ON; 72AC;;;;N;;;;; +2F5E;KANGXI RADICAL PROFOUND;So;0;ON; 7384;;;;N;;;;; +2F5F;KANGXI RADICAL JADE;So;0;ON; 7389;;;;N;;;;; +2F60;KANGXI RADICAL MELON;So;0;ON; 74DC;;;;N;;;;; +2F61;KANGXI RADICAL TILE;So;0;ON; 74E6;;;;N;;;;; +2F62;KANGXI RADICAL SWEET;So;0;ON; 7518;;;;N;;;;; +2F63;KANGXI RADICAL LIFE;So;0;ON; 751F;;;;N;;;;; +2F64;KANGXI RADICAL USE;So;0;ON; 7528;;;;N;;;;; +2F65;KANGXI RADICAL FIELD;So;0;ON; 7530;;;;N;;;;; +2F66;KANGXI RADICAL BOLT OF CLOTH;So;0;ON; 758B;;;;N;;;;; +2F67;KANGXI RADICAL SICKNESS;So;0;ON; 7592;;;;N;;;;; +2F68;KANGXI RADICAL DOTTED TENT;So;0;ON; 7676;;;;N;;;;; +2F69;KANGXI RADICAL WHITE;So;0;ON; 767D;;;;N;;;;; +2F6A;KANGXI RADICAL SKIN;So;0;ON; 76AE;;;;N;;;;; +2F6B;KANGXI RADICAL DISH;So;0;ON; 76BF;;;;N;;;;; +2F6C;KANGXI RADICAL EYE;So;0;ON; 76EE;;;;N;;;;; +2F6D;KANGXI RADICAL SPEAR;So;0;ON; 77DB;;;;N;;;;; +2F6E;KANGXI RADICAL ARROW;So;0;ON; 77E2;;;;N;;;;; +2F6F;KANGXI RADICAL STONE;So;0;ON; 77F3;;;;N;;;;; +2F70;KANGXI RADICAL SPIRIT;So;0;ON; 793A;;;;N;;;;; +2F71;KANGXI RADICAL TRACK;So;0;ON; 79B8;;;;N;;;;; +2F72;KANGXI RADICAL GRAIN;So;0;ON; 79BE;;;;N;;;;; +2F73;KANGXI RADICAL CAVE;So;0;ON; 7A74;;;;N;;;;; +2F74;KANGXI RADICAL STAND;So;0;ON; 7ACB;;;;N;;;;; +2F75;KANGXI RADICAL BAMBOO;So;0;ON; 7AF9;;;;N;;;;; +2F76;KANGXI RADICAL RICE;So;0;ON; 7C73;;;;N;;;;; +2F77;KANGXI RADICAL SILK;So;0;ON; 7CF8;;;;N;;;;; +2F78;KANGXI RADICAL JAR;So;0;ON; 7F36;;;;N;;;;; +2F79;KANGXI RADICAL NET;So;0;ON; 7F51;;;;N;;;;; +2F7A;KANGXI RADICAL SHEEP;So;0;ON; 7F8A;;;;N;;;;; +2F7B;KANGXI RADICAL FEATHER;So;0;ON; 7FBD;;;;N;;;;; +2F7C;KANGXI RADICAL OLD;So;0;ON; 8001;;;;N;;;;; +2F7D;KANGXI RADICAL AND;So;0;ON; 800C;;;;N;;;;; +2F7E;KANGXI RADICAL PLOW;So;0;ON; 8012;;;;N;;;;; +2F7F;KANGXI RADICAL EAR;So;0;ON; 8033;;;;N;;;;; +2F80;KANGXI RADICAL BRUSH;So;0;ON; 807F;;;;N;;;;; +2F81;KANGXI RADICAL MEAT;So;0;ON; 8089;;;;N;;;;; +2F82;KANGXI RADICAL MINISTER;So;0;ON; 81E3;;;;N;;;;; +2F83;KANGXI RADICAL SELF;So;0;ON; 81EA;;;;N;;;;; +2F84;KANGXI RADICAL ARRIVE;So;0;ON; 81F3;;;;N;;;;; +2F85;KANGXI RADICAL MORTAR;So;0;ON; 81FC;;;;N;;;;; +2F86;KANGXI RADICAL TONGUE;So;0;ON; 820C;;;;N;;;;; +2F87;KANGXI RADICAL OPPOSE;So;0;ON; 821B;;;;N;;;;; +2F88;KANGXI RADICAL BOAT;So;0;ON; 821F;;;;N;;;;; +2F89;KANGXI RADICAL STOPPING;So;0;ON; 826E;;;;N;;;;; +2F8A;KANGXI RADICAL COLOR;So;0;ON; 8272;;;;N;;;;; +2F8B;KANGXI RADICAL GRASS;So;0;ON; 8278;;;;N;;;;; +2F8C;KANGXI RADICAL TIGER;So;0;ON; 864D;;;;N;;;;; +2F8D;KANGXI RADICAL INSECT;So;0;ON; 866B;;;;N;;;;; +2F8E;KANGXI RADICAL BLOOD;So;0;ON; 8840;;;;N;;;;; +2F8F;KANGXI RADICAL WALK ENCLOSURE;So;0;ON; 884C;;;;N;;;;; +2F90;KANGXI RADICAL CLOTHES;So;0;ON; 8863;;;;N;;;;; +2F91;KANGXI RADICAL WEST;So;0;ON; 897E;;;;N;;;;; +2F92;KANGXI RADICAL SEE;So;0;ON; 898B;;;;N;;;;; +2F93;KANGXI RADICAL HORN;So;0;ON; 89D2;;;;N;;;;; +2F94;KANGXI RADICAL SPEECH;So;0;ON; 8A00;;;;N;;;;; +2F95;KANGXI RADICAL VALLEY;So;0;ON; 8C37;;;;N;;;;; +2F96;KANGXI RADICAL BEAN;So;0;ON; 8C46;;;;N;;;;; +2F97;KANGXI RADICAL PIG;So;0;ON; 8C55;;;;N;;;;; +2F98;KANGXI RADICAL BADGER;So;0;ON; 8C78;;;;N;;;;; +2F99;KANGXI RADICAL SHELL;So;0;ON; 8C9D;;;;N;;;;; +2F9A;KANGXI RADICAL RED;So;0;ON; 8D64;;;;N;;;;; +2F9B;KANGXI RADICAL RUN;So;0;ON; 8D70;;;;N;;;;; +2F9C;KANGXI RADICAL FOOT;So;0;ON; 8DB3;;;;N;;;;; +2F9D;KANGXI RADICAL BODY;So;0;ON; 8EAB;;;;N;;;;; +2F9E;KANGXI RADICAL CART;So;0;ON; 8ECA;;;;N;;;;; +2F9F;KANGXI RADICAL BITTER;So;0;ON; 8F9B;;;;N;;;;; +2FA0;KANGXI RADICAL MORNING;So;0;ON; 8FB0;;;;N;;;;; +2FA1;KANGXI RADICAL WALK;So;0;ON; 8FB5;;;;N;;;;; +2FA2;KANGXI RADICAL CITY;So;0;ON; 9091;;;;N;;;;; +2FA3;KANGXI RADICAL WINE;So;0;ON; 9149;;;;N;;;;; +2FA4;KANGXI RADICAL DISTINGUISH;So;0;ON; 91C6;;;;N;;;;; +2FA5;KANGXI RADICAL VILLAGE;So;0;ON; 91CC;;;;N;;;;; +2FA6;KANGXI RADICAL GOLD;So;0;ON; 91D1;;;;N;;;;; +2FA7;KANGXI RADICAL LONG;So;0;ON; 9577;;;;N;;;;; +2FA8;KANGXI RADICAL GATE;So;0;ON; 9580;;;;N;;;;; +2FA9;KANGXI RADICAL MOUND;So;0;ON; 961C;;;;N;;;;; +2FAA;KANGXI RADICAL SLAVE;So;0;ON; 96B6;;;;N;;;;; +2FAB;KANGXI RADICAL SHORT TAILED BIRD;So;0;ON; 96B9;;;;N;;;;; +2FAC;KANGXI RADICAL RAIN;So;0;ON; 96E8;;;;N;;;;; +2FAD;KANGXI RADICAL BLUE;So;0;ON; 9751;;;;N;;;;; +2FAE;KANGXI RADICAL WRONG;So;0;ON; 975E;;;;N;;;;; +2FAF;KANGXI RADICAL FACE;So;0;ON; 9762;;;;N;;;;; +2FB0;KANGXI RADICAL LEATHER;So;0;ON; 9769;;;;N;;;;; +2FB1;KANGXI RADICAL TANNED LEATHER;So;0;ON; 97CB;;;;N;;;;; +2FB2;KANGXI RADICAL LEEK;So;0;ON; 97ED;;;;N;;;;; +2FB3;KANGXI RADICAL SOUND;So;0;ON; 97F3;;;;N;;;;; +2FB4;KANGXI RADICAL LEAF;So;0;ON; 9801;;;;N;;;;; +2FB5;KANGXI RADICAL WIND;So;0;ON; 98A8;;;;N;;;;; +2FB6;KANGXI RADICAL FLY;So;0;ON; 98DB;;;;N;;;;; +2FB7;KANGXI RADICAL EAT;So;0;ON; 98DF;;;;N;;;;; +2FB8;KANGXI RADICAL HEAD;So;0;ON; 9996;;;;N;;;;; +2FB9;KANGXI RADICAL FRAGRANT;So;0;ON; 9999;;;;N;;;;; +2FBA;KANGXI RADICAL HORSE;So;0;ON; 99AC;;;;N;;;;; +2FBB;KANGXI RADICAL BONE;So;0;ON; 9AA8;;;;N;;;;; +2FBC;KANGXI RADICAL TALL;So;0;ON; 9AD8;;;;N;;;;; +2FBD;KANGXI RADICAL HAIR;So;0;ON; 9ADF;;;;N;;;;; +2FBE;KANGXI RADICAL FIGHT;So;0;ON; 9B25;;;;N;;;;; +2FBF;KANGXI RADICAL SACRIFICIAL WINE;So;0;ON; 9B2F;;;;N;;;;; +2FC0;KANGXI RADICAL CAULDRON;So;0;ON; 9B32;;;;N;;;;; +2FC1;KANGXI RADICAL GHOST;So;0;ON; 9B3C;;;;N;;;;; +2FC2;KANGXI RADICAL FISH;So;0;ON; 9B5A;;;;N;;;;; +2FC3;KANGXI RADICAL BIRD;So;0;ON; 9CE5;;;;N;;;;; +2FC4;KANGXI RADICAL SALT;So;0;ON; 9E75;;;;N;;;;; +2FC5;KANGXI RADICAL DEER;So;0;ON; 9E7F;;;;N;;;;; +2FC6;KANGXI RADICAL WHEAT;So;0;ON; 9EA5;;;;N;;;;; +2FC7;KANGXI RADICAL HEMP;So;0;ON; 9EBB;;;;N;;;;; +2FC8;KANGXI RADICAL YELLOW;So;0;ON; 9EC3;;;;N;;;;; +2FC9;KANGXI RADICAL MILLET;So;0;ON; 9ECD;;;;N;;;;; +2FCA;KANGXI RADICAL BLACK;So;0;ON; 9ED1;;;;N;;;;; +2FCB;KANGXI RADICAL EMBROIDERY;So;0;ON; 9EF9;;;;N;;;;; +2FCC;KANGXI RADICAL FROG;So;0;ON; 9EFD;;;;N;;;;; +2FCD;KANGXI RADICAL TRIPOD;So;0;ON; 9F0E;;;;N;;;;; +2FCE;KANGXI RADICAL DRUM;So;0;ON; 9F13;;;;N;;;;; +2FCF;KANGXI RADICAL RAT;So;0;ON; 9F20;;;;N;;;;; +2FD0;KANGXI RADICAL NOSE;So;0;ON; 9F3B;;;;N;;;;; +2FD1;KANGXI RADICAL EVEN;So;0;ON; 9F4A;;;;N;;;;; +2FD2;KANGXI RADICAL TOOTH;So;0;ON; 9F52;;;;N;;;;; +2FD3;KANGXI RADICAL DRAGON;So;0;ON; 9F8D;;;;N;;;;; +2FD4;KANGXI RADICAL TURTLE;So;0;ON; 9F9C;;;;N;;;;; +2FD5;KANGXI RADICAL FLUTE;So;0;ON; 9FA0;;;;N;;;;; +2FF0;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT;So;0;ON;;;;;N;;;;; +2FF1;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW;So;0;ON;;;;;N;;;;; +2FF2;IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT;So;0;ON;;;;;N;;;;; +2FF3;IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW;So;0;ON;;;;;N;;;;; +2FF4;IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND;So;0;ON;;;;;N;;;;; +2FF5;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE;So;0;ON;;;;;N;;;;; +2FF6;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW;So;0;ON;;;;;N;;;;; +2FF7;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT;So;0;ON;;;;;N;;;;; +2FF8;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT;So;0;ON;;;;;N;;;;; +2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;; +2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;; +2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;; +2FFC;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM RIGHT;So;0;ON;;;;;N;;;;; +2FFD;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT;So;0;ON;;;;;N;;;;; +2FFE;IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION;So;0;ON;;;;;N;;;;; +2FFF;IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION;So;0;ON;;;;;N;;;;; +3000;IDEOGRAPHIC SPACE;Zs;0;WS; 0020;;;;N;;;;; +3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;; +3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;; +3003;DITTO MARK;Po;0;ON;;;;;N;;;;; +3004;JAPANESE INDUSTRIAL STANDARD SYMBOL;So;0;ON;;;;;N;;;;; +3005;IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; +3006;IDEOGRAPHIC CLOSING MARK;Lo;0;L;;;;;N;;;;; +3007;IDEOGRAPHIC NUMBER ZERO;Nl;0;L;;;;0;N;;;;; +3008;LEFT ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING ANGLE BRACKET;;;; +3009;RIGHT ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING ANGLE BRACKET;;;; +300A;LEFT DOUBLE ANGLE BRACKET;Ps;0;ON;;;;;Y;OPENING DOUBLE ANGLE BRACKET;;;; +300B;RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON;;;;;Y;CLOSING DOUBLE ANGLE BRACKET;;;; +300C;LEFT CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING CORNER BRACKET;;;; +300D;RIGHT CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING CORNER BRACKET;;;; +300E;LEFT WHITE CORNER BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE CORNER BRACKET;;;; +300F;RIGHT WHITE CORNER BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE CORNER BRACKET;;;; +3010;LEFT BLACK LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING BLACK LENTICULAR BRACKET;;;; +3011;RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING BLACK LENTICULAR BRACKET;;;; +3012;POSTAL MARK;So;0;ON;;;;;N;;;;; +3013;GETA MARK;So;0;ON;;;;;N;;;;; +3014;LEFT TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING TORTOISE SHELL BRACKET;;;; +3015;RIGHT TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING TORTOISE SHELL BRACKET;;;; +3016;LEFT WHITE LENTICULAR BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE LENTICULAR BRACKET;;;; +3017;RIGHT WHITE LENTICULAR BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE LENTICULAR BRACKET;;;; +3018;LEFT WHITE TORTOISE SHELL BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE TORTOISE SHELL BRACKET;;;; +3019;RIGHT WHITE TORTOISE SHELL BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE TORTOISE SHELL BRACKET;;;; +301A;LEFT WHITE SQUARE BRACKET;Ps;0;ON;;;;;Y;OPENING WHITE SQUARE BRACKET;;;; +301B;RIGHT WHITE SQUARE BRACKET;Pe;0;ON;;;;;Y;CLOSING WHITE SQUARE BRACKET;;;; +301C;WAVE DASH;Pd;0;ON;;;;;N;;;;; +301D;REVERSED DOUBLE PRIME QUOTATION MARK;Ps;0;ON;;;;;N;;;;; +301E;DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; +301F;LOW DOUBLE PRIME QUOTATION MARK;Pe;0;ON;;;;;N;;;;; +3020;POSTAL MARK FACE;So;0;ON;;;;;N;;;;; +3021;HANGZHOU NUMERAL ONE;Nl;0;L;;;;1;N;;;;; +3022;HANGZHOU NUMERAL TWO;Nl;0;L;;;;2;N;;;;; +3023;HANGZHOU NUMERAL THREE;Nl;0;L;;;;3;N;;;;; +3024;HANGZHOU NUMERAL FOUR;Nl;0;L;;;;4;N;;;;; +3025;HANGZHOU NUMERAL FIVE;Nl;0;L;;;;5;N;;;;; +3026;HANGZHOU NUMERAL SIX;Nl;0;L;;;;6;N;;;;; +3027;HANGZHOU NUMERAL SEVEN;Nl;0;L;;;;7;N;;;;; +3028;HANGZHOU NUMERAL EIGHT;Nl;0;L;;;;8;N;;;;; +3029;HANGZHOU NUMERAL NINE;Nl;0;L;;;;9;N;;;;; +302A;IDEOGRAPHIC LEVEL TONE MARK;Mn;218;NSM;;;;;N;;;;; +302B;IDEOGRAPHIC RISING TONE MARK;Mn;228;NSM;;;;;N;;;;; +302C;IDEOGRAPHIC DEPARTING TONE MARK;Mn;232;NSM;;;;;N;;;;; +302D;IDEOGRAPHIC ENTERING TONE MARK;Mn;222;NSM;;;;;N;;;;; +302E;HANGUL SINGLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; +302F;HANGUL DOUBLE DOT TONE MARK;Mc;224;L;;;;;N;;;;; +3030;WAVY DASH;Pd;0;ON;;;;;N;;;;; +3031;VERTICAL KANA REPEAT MARK;Lm;0;L;;;;;N;;;;; +3032;VERTICAL KANA REPEAT WITH VOICED SOUND MARK;Lm;0;L;;;;;N;;;;; +3033;VERTICAL KANA REPEAT MARK UPPER HALF;Lm;0;L;;;;;N;;;;; +3034;VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF;Lm;0;L;;;;;N;;;;; +3035;VERTICAL KANA REPEAT MARK LOWER HALF;Lm;0;L;;;;;N;;;;; +3036;CIRCLED POSTAL MARK;So;0;ON; 3012;;;;N;;;;; +3037;IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL;So;0;ON;;;;;N;;;;; +3038;HANGZHOU NUMERAL TEN;Nl;0;L; 5341;;;10;N;;;;; +3039;HANGZHOU NUMERAL TWENTY;Nl;0;L; 5344;;;20;N;;;;; +303A;HANGZHOU NUMERAL THIRTY;Nl;0;L; 5345;;;30;N;;;;; +303B;VERTICAL IDEOGRAPHIC ITERATION MARK;Lm;0;L;;;;;N;;;;; +303C;MASU MARK;Lo;0;L;;;;;N;;;;; +303D;PART ALTERNATION MARK;Po;0;ON;;;;;N;;;;; +303E;IDEOGRAPHIC VARIATION INDICATOR;So;0;ON;;;;;N;;;;; +303F;IDEOGRAPHIC HALF FILL SPACE;So;0;ON;;;;;N;;;;; +3041;HIRAGANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +3042;HIRAGANA LETTER A;Lo;0;L;;;;;N;;;;; +3043;HIRAGANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; +3044;HIRAGANA LETTER I;Lo;0;L;;;;;N;;;;; +3045;HIRAGANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; +3046;HIRAGANA LETTER U;Lo;0;L;;;;;N;;;;; +3047;HIRAGANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; +3048;HIRAGANA LETTER E;Lo;0;L;;;;;N;;;;; +3049;HIRAGANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; +304A;HIRAGANA LETTER O;Lo;0;L;;;;;N;;;;; +304B;HIRAGANA LETTER KA;Lo;0;L;;;;;N;;;;; +304C;HIRAGANA LETTER GA;Lo;0;L;304B 3099;;;;N;;;;; +304D;HIRAGANA LETTER KI;Lo;0;L;;;;;N;;;;; +304E;HIRAGANA LETTER GI;Lo;0;L;304D 3099;;;;N;;;;; +304F;HIRAGANA LETTER KU;Lo;0;L;;;;;N;;;;; +3050;HIRAGANA LETTER GU;Lo;0;L;304F 3099;;;;N;;;;; +3051;HIRAGANA LETTER KE;Lo;0;L;;;;;N;;;;; +3052;HIRAGANA LETTER GE;Lo;0;L;3051 3099;;;;N;;;;; +3053;HIRAGANA LETTER KO;Lo;0;L;;;;;N;;;;; +3054;HIRAGANA LETTER GO;Lo;0;L;3053 3099;;;;N;;;;; +3055;HIRAGANA LETTER SA;Lo;0;L;;;;;N;;;;; +3056;HIRAGANA LETTER ZA;Lo;0;L;3055 3099;;;;N;;;;; +3057;HIRAGANA LETTER SI;Lo;0;L;;;;;N;;;;; +3058;HIRAGANA LETTER ZI;Lo;0;L;3057 3099;;;;N;;;;; +3059;HIRAGANA LETTER SU;Lo;0;L;;;;;N;;;;; +305A;HIRAGANA LETTER ZU;Lo;0;L;3059 3099;;;;N;;;;; +305B;HIRAGANA LETTER SE;Lo;0;L;;;;;N;;;;; +305C;HIRAGANA LETTER ZE;Lo;0;L;305B 3099;;;;N;;;;; +305D;HIRAGANA LETTER SO;Lo;0;L;;;;;N;;;;; +305E;HIRAGANA LETTER ZO;Lo;0;L;305D 3099;;;;N;;;;; +305F;HIRAGANA LETTER TA;Lo;0;L;;;;;N;;;;; +3060;HIRAGANA LETTER DA;Lo;0;L;305F 3099;;;;N;;;;; +3061;HIRAGANA LETTER TI;Lo;0;L;;;;;N;;;;; +3062;HIRAGANA LETTER DI;Lo;0;L;3061 3099;;;;N;;;;; +3063;HIRAGANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; +3064;HIRAGANA LETTER TU;Lo;0;L;;;;;N;;;;; +3065;HIRAGANA LETTER DU;Lo;0;L;3064 3099;;;;N;;;;; +3066;HIRAGANA LETTER TE;Lo;0;L;;;;;N;;;;; +3067;HIRAGANA LETTER DE;Lo;0;L;3066 3099;;;;N;;;;; +3068;HIRAGANA LETTER TO;Lo;0;L;;;;;N;;;;; +3069;HIRAGANA LETTER DO;Lo;0;L;3068 3099;;;;N;;;;; +306A;HIRAGANA LETTER NA;Lo;0;L;;;;;N;;;;; +306B;HIRAGANA LETTER NI;Lo;0;L;;;;;N;;;;; +306C;HIRAGANA LETTER NU;Lo;0;L;;;;;N;;;;; +306D;HIRAGANA LETTER NE;Lo;0;L;;;;;N;;;;; +306E;HIRAGANA LETTER NO;Lo;0;L;;;;;N;;;;; +306F;HIRAGANA LETTER HA;Lo;0;L;;;;;N;;;;; +3070;HIRAGANA LETTER BA;Lo;0;L;306F 3099;;;;N;;;;; +3071;HIRAGANA LETTER PA;Lo;0;L;306F 309A;;;;N;;;;; +3072;HIRAGANA LETTER HI;Lo;0;L;;;;;N;;;;; +3073;HIRAGANA LETTER BI;Lo;0;L;3072 3099;;;;N;;;;; +3074;HIRAGANA LETTER PI;Lo;0;L;3072 309A;;;;N;;;;; +3075;HIRAGANA LETTER HU;Lo;0;L;;;;;N;;;;; +3076;HIRAGANA LETTER BU;Lo;0;L;3075 3099;;;;N;;;;; +3077;HIRAGANA LETTER PU;Lo;0;L;3075 309A;;;;N;;;;; +3078;HIRAGANA LETTER HE;Lo;0;L;;;;;N;;;;; +3079;HIRAGANA LETTER BE;Lo;0;L;3078 3099;;;;N;;;;; +307A;HIRAGANA LETTER PE;Lo;0;L;3078 309A;;;;N;;;;; +307B;HIRAGANA LETTER HO;Lo;0;L;;;;;N;;;;; +307C;HIRAGANA LETTER BO;Lo;0;L;307B 3099;;;;N;;;;; +307D;HIRAGANA LETTER PO;Lo;0;L;307B 309A;;;;N;;;;; +307E;HIRAGANA LETTER MA;Lo;0;L;;;;;N;;;;; +307F;HIRAGANA LETTER MI;Lo;0;L;;;;;N;;;;; +3080;HIRAGANA LETTER MU;Lo;0;L;;;;;N;;;;; +3081;HIRAGANA LETTER ME;Lo;0;L;;;;;N;;;;; +3082;HIRAGANA LETTER MO;Lo;0;L;;;;;N;;;;; +3083;HIRAGANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; +3084;HIRAGANA LETTER YA;Lo;0;L;;;;;N;;;;; +3085;HIRAGANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; +3086;HIRAGANA LETTER YU;Lo;0;L;;;;;N;;;;; +3087;HIRAGANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; +3088;HIRAGANA LETTER YO;Lo;0;L;;;;;N;;;;; +3089;HIRAGANA LETTER RA;Lo;0;L;;;;;N;;;;; +308A;HIRAGANA LETTER RI;Lo;0;L;;;;;N;;;;; +308B;HIRAGANA LETTER RU;Lo;0;L;;;;;N;;;;; +308C;HIRAGANA LETTER RE;Lo;0;L;;;;;N;;;;; +308D;HIRAGANA LETTER RO;Lo;0;L;;;;;N;;;;; +308E;HIRAGANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; +308F;HIRAGANA LETTER WA;Lo;0;L;;;;;N;;;;; +3090;HIRAGANA LETTER WI;Lo;0;L;;;;;N;;;;; +3091;HIRAGANA LETTER WE;Lo;0;L;;;;;N;;;;; +3092;HIRAGANA LETTER WO;Lo;0;L;;;;;N;;;;; +3093;HIRAGANA LETTER N;Lo;0;L;;;;;N;;;;; +3094;HIRAGANA LETTER VU;Lo;0;L;3046 3099;;;;N;;;;; +3095;HIRAGANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; +3096;HIRAGANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; +3099;COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA VOICED SOUND MARK;;;; +309A;COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Mn;8;NSM;;;;;N;NON-SPACING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;;;; +309B;KATAKANA-HIRAGANA VOICED SOUND MARK;Sk;0;ON; 0020 3099;;;;N;;;;; +309C;KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK;Sk;0;ON; 0020 309A;;;;N;;;;; +309D;HIRAGANA ITERATION MARK;Lm;0;L;;;;;N;;;;; +309E;HIRAGANA VOICED ITERATION MARK;Lm;0;L;309D 3099;;;;N;;;;; +309F;HIRAGANA DIGRAPH YORI;Lo;0;L; 3088 308A;;;;N;;;;; +30A0;KATAKANA-HIRAGANA DOUBLE HYPHEN;Pd;0;ON;;;;;N;;;;; +30A1;KATAKANA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +30A2;KATAKANA LETTER A;Lo;0;L;;;;;N;;;;; +30A3;KATAKANA LETTER SMALL I;Lo;0;L;;;;;N;;;;; +30A4;KATAKANA LETTER I;Lo;0;L;;;;;N;;;;; +30A5;KATAKANA LETTER SMALL U;Lo;0;L;;;;;N;;;;; +30A6;KATAKANA LETTER U;Lo;0;L;;;;;N;;;;; +30A7;KATAKANA LETTER SMALL E;Lo;0;L;;;;;N;;;;; +30A8;KATAKANA LETTER E;Lo;0;L;;;;;N;;;;; +30A9;KATAKANA LETTER SMALL O;Lo;0;L;;;;;N;;;;; +30AA;KATAKANA LETTER O;Lo;0;L;;;;;N;;;;; +30AB;KATAKANA LETTER KA;Lo;0;L;;;;;N;;;;; +30AC;KATAKANA LETTER GA;Lo;0;L;30AB 3099;;;;N;;;;; +30AD;KATAKANA LETTER KI;Lo;0;L;;;;;N;;;;; +30AE;KATAKANA LETTER GI;Lo;0;L;30AD 3099;;;;N;;;;; +30AF;KATAKANA LETTER KU;Lo;0;L;;;;;N;;;;; +30B0;KATAKANA LETTER GU;Lo;0;L;30AF 3099;;;;N;;;;; +30B1;KATAKANA LETTER KE;Lo;0;L;;;;;N;;;;; +30B2;KATAKANA LETTER GE;Lo;0;L;30B1 3099;;;;N;;;;; +30B3;KATAKANA LETTER KO;Lo;0;L;;;;;N;;;;; +30B4;KATAKANA LETTER GO;Lo;0;L;30B3 3099;;;;N;;;;; +30B5;KATAKANA LETTER SA;Lo;0;L;;;;;N;;;;; +30B6;KATAKANA LETTER ZA;Lo;0;L;30B5 3099;;;;N;;;;; +30B7;KATAKANA LETTER SI;Lo;0;L;;;;;N;;;;; +30B8;KATAKANA LETTER ZI;Lo;0;L;30B7 3099;;;;N;;;;; +30B9;KATAKANA LETTER SU;Lo;0;L;;;;;N;;;;; +30BA;KATAKANA LETTER ZU;Lo;0;L;30B9 3099;;;;N;;;;; +30BB;KATAKANA LETTER SE;Lo;0;L;;;;;N;;;;; +30BC;KATAKANA LETTER ZE;Lo;0;L;30BB 3099;;;;N;;;;; +30BD;KATAKANA LETTER SO;Lo;0;L;;;;;N;;;;; +30BE;KATAKANA LETTER ZO;Lo;0;L;30BD 3099;;;;N;;;;; +30BF;KATAKANA LETTER TA;Lo;0;L;;;;;N;;;;; +30C0;KATAKANA LETTER DA;Lo;0;L;30BF 3099;;;;N;;;;; +30C1;KATAKANA LETTER TI;Lo;0;L;;;;;N;;;;; +30C2;KATAKANA LETTER DI;Lo;0;L;30C1 3099;;;;N;;;;; +30C3;KATAKANA LETTER SMALL TU;Lo;0;L;;;;;N;;;;; +30C4;KATAKANA LETTER TU;Lo;0;L;;;;;N;;;;; +30C5;KATAKANA LETTER DU;Lo;0;L;30C4 3099;;;;N;;;;; +30C6;KATAKANA LETTER TE;Lo;0;L;;;;;N;;;;; +30C7;KATAKANA LETTER DE;Lo;0;L;30C6 3099;;;;N;;;;; +30C8;KATAKANA LETTER TO;Lo;0;L;;;;;N;;;;; +30C9;KATAKANA LETTER DO;Lo;0;L;30C8 3099;;;;N;;;;; +30CA;KATAKANA LETTER NA;Lo;0;L;;;;;N;;;;; +30CB;KATAKANA LETTER NI;Lo;0;L;;;;;N;;;;; +30CC;KATAKANA LETTER NU;Lo;0;L;;;;;N;;;;; +30CD;KATAKANA LETTER NE;Lo;0;L;;;;;N;;;;; +30CE;KATAKANA LETTER NO;Lo;0;L;;;;;N;;;;; +30CF;KATAKANA LETTER HA;Lo;0;L;;;;;N;;;;; +30D0;KATAKANA LETTER BA;Lo;0;L;30CF 3099;;;;N;;;;; +30D1;KATAKANA LETTER PA;Lo;0;L;30CF 309A;;;;N;;;;; +30D2;KATAKANA LETTER HI;Lo;0;L;;;;;N;;;;; +30D3;KATAKANA LETTER BI;Lo;0;L;30D2 3099;;;;N;;;;; +30D4;KATAKANA LETTER PI;Lo;0;L;30D2 309A;;;;N;;;;; +30D5;KATAKANA LETTER HU;Lo;0;L;;;;;N;;;;; +30D6;KATAKANA LETTER BU;Lo;0;L;30D5 3099;;;;N;;;;; +30D7;KATAKANA LETTER PU;Lo;0;L;30D5 309A;;;;N;;;;; +30D8;KATAKANA LETTER HE;Lo;0;L;;;;;N;;;;; +30D9;KATAKANA LETTER BE;Lo;0;L;30D8 3099;;;;N;;;;; +30DA;KATAKANA LETTER PE;Lo;0;L;30D8 309A;;;;N;;;;; +30DB;KATAKANA LETTER HO;Lo;0;L;;;;;N;;;;; +30DC;KATAKANA LETTER BO;Lo;0;L;30DB 3099;;;;N;;;;; +30DD;KATAKANA LETTER PO;Lo;0;L;30DB 309A;;;;N;;;;; +30DE;KATAKANA LETTER MA;Lo;0;L;;;;;N;;;;; +30DF;KATAKANA LETTER MI;Lo;0;L;;;;;N;;;;; +30E0;KATAKANA LETTER MU;Lo;0;L;;;;;N;;;;; +30E1;KATAKANA LETTER ME;Lo;0;L;;;;;N;;;;; +30E2;KATAKANA LETTER MO;Lo;0;L;;;;;N;;;;; +30E3;KATAKANA LETTER SMALL YA;Lo;0;L;;;;;N;;;;; +30E4;KATAKANA LETTER YA;Lo;0;L;;;;;N;;;;; +30E5;KATAKANA LETTER SMALL YU;Lo;0;L;;;;;N;;;;; +30E6;KATAKANA LETTER YU;Lo;0;L;;;;;N;;;;; +30E7;KATAKANA LETTER SMALL YO;Lo;0;L;;;;;N;;;;; +30E8;KATAKANA LETTER YO;Lo;0;L;;;;;N;;;;; +30E9;KATAKANA LETTER RA;Lo;0;L;;;;;N;;;;; +30EA;KATAKANA LETTER RI;Lo;0;L;;;;;N;;;;; +30EB;KATAKANA LETTER RU;Lo;0;L;;;;;N;;;;; +30EC;KATAKANA LETTER RE;Lo;0;L;;;;;N;;;;; +30ED;KATAKANA LETTER RO;Lo;0;L;;;;;N;;;;; +30EE;KATAKANA LETTER SMALL WA;Lo;0;L;;;;;N;;;;; +30EF;KATAKANA LETTER WA;Lo;0;L;;;;;N;;;;; +30F0;KATAKANA LETTER WI;Lo;0;L;;;;;N;;;;; +30F1;KATAKANA LETTER WE;Lo;0;L;;;;;N;;;;; +30F2;KATAKANA LETTER WO;Lo;0;L;;;;;N;;;;; +30F3;KATAKANA LETTER N;Lo;0;L;;;;;N;;;;; +30F4;KATAKANA LETTER VU;Lo;0;L;30A6 3099;;;;N;;;;; +30F5;KATAKANA LETTER SMALL KA;Lo;0;L;;;;;N;;;;; +30F6;KATAKANA LETTER SMALL KE;Lo;0;L;;;;;N;;;;; +30F7;KATAKANA LETTER VA;Lo;0;L;30EF 3099;;;;N;;;;; +30F8;KATAKANA LETTER VI;Lo;0;L;30F0 3099;;;;N;;;;; +30F9;KATAKANA LETTER VE;Lo;0;L;30F1 3099;;;;N;;;;; +30FA;KATAKANA LETTER VO;Lo;0;L;30F2 3099;;;;N;;;;; +30FB;KATAKANA MIDDLE DOT;Po;0;ON;;;;;N;;;;; +30FC;KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L;;;;;N;;;;; +30FD;KATAKANA ITERATION MARK;Lm;0;L;;;;;N;;;;; +30FE;KATAKANA VOICED ITERATION MARK;Lm;0;L;30FD 3099;;;;N;;;;; +30FF;KATAKANA DIGRAPH KOTO;Lo;0;L; 30B3 30C8;;;;N;;;;; +3105;BOPOMOFO LETTER B;Lo;0;L;;;;;N;;;;; +3106;BOPOMOFO LETTER P;Lo;0;L;;;;;N;;;;; +3107;BOPOMOFO LETTER M;Lo;0;L;;;;;N;;;;; +3108;BOPOMOFO LETTER F;Lo;0;L;;;;;N;;;;; +3109;BOPOMOFO LETTER D;Lo;0;L;;;;;N;;;;; +310A;BOPOMOFO LETTER T;Lo;0;L;;;;;N;;;;; +310B;BOPOMOFO LETTER N;Lo;0;L;;;;;N;;;;; +310C;BOPOMOFO LETTER L;Lo;0;L;;;;;N;;;;; +310D;BOPOMOFO LETTER G;Lo;0;L;;;;;N;;;;; +310E;BOPOMOFO LETTER K;Lo;0;L;;;;;N;;;;; +310F;BOPOMOFO LETTER H;Lo;0;L;;;;;N;;;;; +3110;BOPOMOFO LETTER J;Lo;0;L;;;;;N;;;;; +3111;BOPOMOFO LETTER Q;Lo;0;L;;;;;N;;;;; +3112;BOPOMOFO LETTER X;Lo;0;L;;;;;N;;;;; +3113;BOPOMOFO LETTER ZH;Lo;0;L;;;;;N;;;;; +3114;BOPOMOFO LETTER CH;Lo;0;L;;;;;N;;;;; +3115;BOPOMOFO LETTER SH;Lo;0;L;;;;;N;;;;; +3116;BOPOMOFO LETTER R;Lo;0;L;;;;;N;;;;; +3117;BOPOMOFO LETTER Z;Lo;0;L;;;;;N;;;;; +3118;BOPOMOFO LETTER C;Lo;0;L;;;;;N;;;;; +3119;BOPOMOFO LETTER S;Lo;0;L;;;;;N;;;;; +311A;BOPOMOFO LETTER A;Lo;0;L;;;;;N;;;;; +311B;BOPOMOFO LETTER O;Lo;0;L;;;;;N;;;;; +311C;BOPOMOFO LETTER E;Lo;0;L;;;;;N;;;;; +311D;BOPOMOFO LETTER EH;Lo;0;L;;;;;N;;;;; +311E;BOPOMOFO LETTER AI;Lo;0;L;;;;;N;;;;; +311F;BOPOMOFO LETTER EI;Lo;0;L;;;;;N;;;;; +3120;BOPOMOFO LETTER AU;Lo;0;L;;;;;N;;;;; +3121;BOPOMOFO LETTER OU;Lo;0;L;;;;;N;;;;; +3122;BOPOMOFO LETTER AN;Lo;0;L;;;;;N;;;;; +3123;BOPOMOFO LETTER EN;Lo;0;L;;;;;N;;;;; +3124;BOPOMOFO LETTER ANG;Lo;0;L;;;;;N;;;;; +3125;BOPOMOFO LETTER ENG;Lo;0;L;;;;;N;;;;; +3126;BOPOMOFO LETTER ER;Lo;0;L;;;;;N;;;;; +3127;BOPOMOFO LETTER I;Lo;0;L;;;;;N;;;;; +3128;BOPOMOFO LETTER U;Lo;0;L;;;;;N;;;;; +3129;BOPOMOFO LETTER IU;Lo;0;L;;;;;N;;;;; +312A;BOPOMOFO LETTER V;Lo;0;L;;;;;N;;;;; +312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;; +312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;; +312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;; +312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;; +312F;BOPOMOFO LETTER NN;Lo;0;L;;;;;N;;;;; +3131;HANGUL LETTER KIYEOK;Lo;0;L; 1100;;;;N;HANGUL LETTER GIYEOG;;;; +3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L; 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;; +3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;; +3134;HANGUL LETTER NIEUN;Lo;0;L; 1102;;;;N;;;;; +3135;HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 11AC;;;;N;HANGUL LETTER NIEUN JIEUJ;;;; +3136;HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 11AD;;;;N;HANGUL LETTER NIEUN HIEUH;;;; +3137;HANGUL LETTER TIKEUT;Lo;0;L; 1103;;;;N;HANGUL LETTER DIGEUD;;;; +3138;HANGUL LETTER SSANGTIKEUT;Lo;0;L; 1104;;;;N;HANGUL LETTER SSANG DIGEUD;;;; +3139;HANGUL LETTER RIEUL;Lo;0;L; 1105;;;;N;HANGUL LETTER LIEUL;;;; +313A;HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 11B0;;;;N;HANGUL LETTER LIEUL GIYEOG;;;; +313B;HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 11B1;;;;N;HANGUL LETTER LIEUL MIEUM;;;; +313C;HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 11B2;;;;N;HANGUL LETTER LIEUL BIEUB;;;; +313D;HANGUL LETTER RIEUL-SIOS;Lo;0;L; 11B3;;;;N;HANGUL LETTER LIEUL SIOS;;;; +313E;HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 11B4;;;;N;HANGUL LETTER LIEUL TIEUT;;;; +313F;HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 11B5;;;;N;HANGUL LETTER LIEUL PIEUP;;;; +3140;HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 111A;;;;N;HANGUL LETTER LIEUL HIEUH;;;; +3141;HANGUL LETTER MIEUM;Lo;0;L; 1106;;;;N;;;;; +3142;HANGUL LETTER PIEUP;Lo;0;L; 1107;;;;N;HANGUL LETTER BIEUB;;;; +3143;HANGUL LETTER SSANGPIEUP;Lo;0;L; 1108;;;;N;HANGUL LETTER SSANG BIEUB;;;; +3144;HANGUL LETTER PIEUP-SIOS;Lo;0;L; 1121;;;;N;HANGUL LETTER BIEUB SIOS;;;; +3145;HANGUL LETTER SIOS;Lo;0;L; 1109;;;;N;;;;; +3146;HANGUL LETTER SSANGSIOS;Lo;0;L; 110A;;;;N;HANGUL LETTER SSANG SIOS;;;; +3147;HANGUL LETTER IEUNG;Lo;0;L; 110B;;;;N;;;;; +3148;HANGUL LETTER CIEUC;Lo;0;L; 110C;;;;N;HANGUL LETTER JIEUJ;;;; +3149;HANGUL LETTER SSANGCIEUC;Lo;0;L; 110D;;;;N;HANGUL LETTER SSANG JIEUJ;;;; +314A;HANGUL LETTER CHIEUCH;Lo;0;L; 110E;;;;N;HANGUL LETTER CIEUC;;;; +314B;HANGUL LETTER KHIEUKH;Lo;0;L; 110F;;;;N;HANGUL LETTER KIYEOK;;;; +314C;HANGUL LETTER THIEUTH;Lo;0;L; 1110;;;;N;HANGUL LETTER TIEUT;;;; +314D;HANGUL LETTER PHIEUPH;Lo;0;L; 1111;;;;N;HANGUL LETTER PIEUP;;;; +314E;HANGUL LETTER HIEUH;Lo;0;L; 1112;;;;N;;;;; +314F;HANGUL LETTER A;Lo;0;L; 1161;;;;N;;;;; +3150;HANGUL LETTER AE;Lo;0;L; 1162;;;;N;;;;; +3151;HANGUL LETTER YA;Lo;0;L; 1163;;;;N;;;;; +3152;HANGUL LETTER YAE;Lo;0;L; 1164;;;;N;;;;; +3153;HANGUL LETTER EO;Lo;0;L; 1165;;;;N;;;;; +3154;HANGUL LETTER E;Lo;0;L; 1166;;;;N;;;;; +3155;HANGUL LETTER YEO;Lo;0;L; 1167;;;;N;;;;; +3156;HANGUL LETTER YE;Lo;0;L; 1168;;;;N;;;;; +3157;HANGUL LETTER O;Lo;0;L; 1169;;;;N;;;;; +3158;HANGUL LETTER WA;Lo;0;L; 116A;;;;N;;;;; +3159;HANGUL LETTER WAE;Lo;0;L; 116B;;;;N;;;;; +315A;HANGUL LETTER OE;Lo;0;L; 116C;;;;N;;;;; +315B;HANGUL LETTER YO;Lo;0;L; 116D;;;;N;;;;; +315C;HANGUL LETTER U;Lo;0;L; 116E;;;;N;;;;; +315D;HANGUL LETTER WEO;Lo;0;L; 116F;;;;N;;;;; +315E;HANGUL LETTER WE;Lo;0;L; 1170;;;;N;;;;; +315F;HANGUL LETTER WI;Lo;0;L; 1171;;;;N;;;;; +3160;HANGUL LETTER YU;Lo;0;L; 1172;;;;N;;;;; +3161;HANGUL LETTER EU;Lo;0;L; 1173;;;;N;;;;; +3162;HANGUL LETTER YI;Lo;0;L; 1174;;;;N;;;;; +3163;HANGUL LETTER I;Lo;0;L; 1175;;;;N;;;;; +3164;HANGUL FILLER;Lo;0;L; 1160;;;;N;HANGUL CAE OM;;;; +3165;HANGUL LETTER SSANGNIEUN;Lo;0;L; 1114;;;;N;HANGUL LETTER SSANG NIEUN;;;; +3166;HANGUL LETTER NIEUN-TIKEUT;Lo;0;L; 1115;;;;N;HANGUL LETTER NIEUN DIGEUD;;;; +3167;HANGUL LETTER NIEUN-SIOS;Lo;0;L; 11C7;;;;N;HANGUL LETTER NIEUN SIOS;;;; +3168;HANGUL LETTER NIEUN-PANSIOS;Lo;0;L; 11C8;;;;N;HANGUL LETTER NIEUN BAN CHI EUM;;;; +3169;HANGUL LETTER RIEUL-KIYEOK-SIOS;Lo;0;L; 11CC;;;;N;HANGUL LETTER LIEUL GIYEOG SIOS;;;; +316A;HANGUL LETTER RIEUL-TIKEUT;Lo;0;L; 11CE;;;;N;HANGUL LETTER LIEUL DIGEUD;;;; +316B;HANGUL LETTER RIEUL-PIEUP-SIOS;Lo;0;L; 11D3;;;;N;HANGUL LETTER LIEUL BIEUB SIOS;;;; +316C;HANGUL LETTER RIEUL-PANSIOS;Lo;0;L; 11D7;;;;N;HANGUL LETTER LIEUL BAN CHI EUM;;;; +316D;HANGUL LETTER RIEUL-YEORINHIEUH;Lo;0;L; 11D9;;;;N;HANGUL LETTER LIEUL YEOLIN HIEUH;;;; +316E;HANGUL LETTER MIEUM-PIEUP;Lo;0;L; 111C;;;;N;HANGUL LETTER MIEUM BIEUB;;;; +316F;HANGUL LETTER MIEUM-SIOS;Lo;0;L; 11DD;;;;N;HANGUL LETTER MIEUM SIOS;;;; +3170;HANGUL LETTER MIEUM-PANSIOS;Lo;0;L; 11DF;;;;N;HANGUL LETTER BIEUB BAN CHI EUM;;;; +3171;HANGUL LETTER KAPYEOUNMIEUM;Lo;0;L; 111D;;;;N;HANGUL LETTER MIEUM SUN GYEONG EUM;;;; +3172;HANGUL LETTER PIEUP-KIYEOK;Lo;0;L; 111E;;;;N;HANGUL LETTER BIEUB GIYEOG;;;; +3173;HANGUL LETTER PIEUP-TIKEUT;Lo;0;L; 1120;;;;N;HANGUL LETTER BIEUB DIGEUD;;;; +3174;HANGUL LETTER PIEUP-SIOS-KIYEOK;Lo;0;L; 1122;;;;N;HANGUL LETTER BIEUB SIOS GIYEOG;;;; +3175;HANGUL LETTER PIEUP-SIOS-TIKEUT;Lo;0;L; 1123;;;;N;HANGUL LETTER BIEUB SIOS DIGEUD;;;; +3176;HANGUL LETTER PIEUP-CIEUC;Lo;0;L; 1127;;;;N;HANGUL LETTER BIEUB JIEUJ;;;; +3177;HANGUL LETTER PIEUP-THIEUTH;Lo;0;L; 1129;;;;N;HANGUL LETTER BIEUB TIEUT;;;; +3178;HANGUL LETTER KAPYEOUNPIEUP;Lo;0;L; 112B;;;;N;HANGUL LETTER BIEUB SUN GYEONG EUM;;;; +3179;HANGUL LETTER KAPYEOUNSSANGPIEUP;Lo;0;L; 112C;;;;N;HANGUL LETTER SSANG BIEUB SUN GYEONG EUM;;;; +317A;HANGUL LETTER SIOS-KIYEOK;Lo;0;L; 112D;;;;N;HANGUL LETTER SIOS GIYEOG;;;; +317B;HANGUL LETTER SIOS-NIEUN;Lo;0;L; 112E;;;;N;HANGUL LETTER SIOS NIEUN;;;; +317C;HANGUL LETTER SIOS-TIKEUT;Lo;0;L; 112F;;;;N;HANGUL LETTER SIOS DIGEUD;;;; +317D;HANGUL LETTER SIOS-PIEUP;Lo;0;L; 1132;;;;N;HANGUL LETTER SIOS BIEUB;;;; +317E;HANGUL LETTER SIOS-CIEUC;Lo;0;L; 1136;;;;N;HANGUL LETTER SIOS JIEUJ;;;; +317F;HANGUL LETTER PANSIOS;Lo;0;L; 1140;;;;N;HANGUL LETTER BAN CHI EUM;;;; +3180;HANGUL LETTER SSANGIEUNG;Lo;0;L; 1147;;;;N;HANGUL LETTER SSANG IEUNG;;;; +3181;HANGUL LETTER YESIEUNG;Lo;0;L; 114C;;;;N;HANGUL LETTER NGIEUNG;;;; +3182;HANGUL LETTER YESIEUNG-SIOS;Lo;0;L; 11F1;;;;N;HANGUL LETTER NGIEUNG SIOS;;;; +3183;HANGUL LETTER YESIEUNG-PANSIOS;Lo;0;L; 11F2;;;;N;HANGUL LETTER NGIEUNG BAN CHI EUM;;;; +3184;HANGUL LETTER KAPYEOUNPHIEUPH;Lo;0;L; 1157;;;;N;HANGUL LETTER PIEUP SUN GYEONG EUM;;;; +3185;HANGUL LETTER SSANGHIEUH;Lo;0;L; 1158;;;;N;HANGUL LETTER SSANG HIEUH;;;; +3186;HANGUL LETTER YEORINHIEUH;Lo;0;L; 1159;;;;N;HANGUL LETTER YEOLIN HIEUH;;;; +3187;HANGUL LETTER YO-YA;Lo;0;L; 1184;;;;N;HANGUL LETTER YOYA;;;; +3188;HANGUL LETTER YO-YAE;Lo;0;L; 1185;;;;N;HANGUL LETTER YOYAE;;;; +3189;HANGUL LETTER YO-I;Lo;0;L; 1188;;;;N;HANGUL LETTER YOI;;;; +318A;HANGUL LETTER YU-YEO;Lo;0;L; 1191;;;;N;HANGUL LETTER YUYEO;;;; +318B;HANGUL LETTER YU-YE;Lo;0;L; 1192;;;;N;HANGUL LETTER YUYE;;;; +318C;HANGUL LETTER YU-I;Lo;0;L; 1194;;;;N;HANGUL LETTER YUI;;;; +318D;HANGUL LETTER ARAEA;Lo;0;L; 119E;;;;N;HANGUL LETTER ALAE A;;;; +318E;HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;; +3190;IDEOGRAPHIC ANNOTATION LINKING MARK;So;0;L;;;;;N;KANBUN TATETEN;;;; +3191;IDEOGRAPHIC ANNOTATION REVERSE MARK;So;0;L;;;;;N;KAERITEN RE;;;; +3192;IDEOGRAPHIC ANNOTATION ONE MARK;No;0;L; 4E00;;;1;N;KAERITEN ITI;;;; +3193;IDEOGRAPHIC ANNOTATION TWO MARK;No;0;L; 4E8C;;;2;N;KAERITEN NI;;;; +3194;IDEOGRAPHIC ANNOTATION THREE MARK;No;0;L; 4E09;;;3;N;KAERITEN SAN;;;; +3195;IDEOGRAPHIC ANNOTATION FOUR MARK;No;0;L; 56DB;;;4;N;KAERITEN SI;;;; +3196;IDEOGRAPHIC ANNOTATION TOP MARK;So;0;L; 4E0A;;;;N;KAERITEN ZYOU;;;; +3197;IDEOGRAPHIC ANNOTATION MIDDLE MARK;So;0;L; 4E2D;;;;N;KAERITEN TYUU;;;; +3198;IDEOGRAPHIC ANNOTATION BOTTOM MARK;So;0;L; 4E0B;;;;N;KAERITEN GE;;;; +3199;IDEOGRAPHIC ANNOTATION FIRST MARK;So;0;L; 7532;;;;N;KAERITEN KOU;;;; +319A;IDEOGRAPHIC ANNOTATION SECOND MARK;So;0;L; 4E59;;;;N;KAERITEN OTU;;;; +319B;IDEOGRAPHIC ANNOTATION THIRD MARK;So;0;L; 4E19;;;;N;KAERITEN HEI;;;; +319C;IDEOGRAPHIC ANNOTATION FOURTH MARK;So;0;L; 4E01;;;;N;KAERITEN TEI;;;; +319D;IDEOGRAPHIC ANNOTATION HEAVEN MARK;So;0;L; 5929;;;;N;KAERITEN TEN;;;; +319E;IDEOGRAPHIC ANNOTATION EARTH MARK;So;0;L; 5730;;;;N;KAERITEN TI;;;; +319F;IDEOGRAPHIC ANNOTATION MAN MARK;So;0;L; 4EBA;;;;N;KAERITEN ZIN;;;; +31A0;BOPOMOFO LETTER BU;Lo;0;L;;;;;N;;;;; +31A1;BOPOMOFO LETTER ZI;Lo;0;L;;;;;N;;;;; +31A2;BOPOMOFO LETTER JI;Lo;0;L;;;;;N;;;;; +31A3;BOPOMOFO LETTER GU;Lo;0;L;;;;;N;;;;; +31A4;BOPOMOFO LETTER EE;Lo;0;L;;;;;N;;;;; +31A5;BOPOMOFO LETTER ENN;Lo;0;L;;;;;N;;;;; +31A6;BOPOMOFO LETTER OO;Lo;0;L;;;;;N;;;;; +31A7;BOPOMOFO LETTER ONN;Lo;0;L;;;;;N;;;;; +31A8;BOPOMOFO LETTER IR;Lo;0;L;;;;;N;;;;; +31A9;BOPOMOFO LETTER ANN;Lo;0;L;;;;;N;;;;; +31AA;BOPOMOFO LETTER INN;Lo;0;L;;;;;N;;;;; +31AB;BOPOMOFO LETTER UNN;Lo;0;L;;;;;N;;;;; +31AC;BOPOMOFO LETTER IM;Lo;0;L;;;;;N;;;;; +31AD;BOPOMOFO LETTER NGG;Lo;0;L;;;;;N;;;;; +31AE;BOPOMOFO LETTER AINN;Lo;0;L;;;;;N;;;;; +31AF;BOPOMOFO LETTER AUNN;Lo;0;L;;;;;N;;;;; +31B0;BOPOMOFO LETTER AM;Lo;0;L;;;;;N;;;;; +31B1;BOPOMOFO LETTER OM;Lo;0;L;;;;;N;;;;; +31B2;BOPOMOFO LETTER ONG;Lo;0;L;;;;;N;;;;; +31B3;BOPOMOFO LETTER INNN;Lo;0;L;;;;;N;;;;; +31B4;BOPOMOFO FINAL LETTER P;Lo;0;L;;;;;N;;;;; +31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; +31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; +31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; +31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;; +31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;; +31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;; +31BB;BOPOMOFO FINAL LETTER G;Lo;0;L;;;;;N;;;;; +31BC;BOPOMOFO LETTER GW;Lo;0;L;;;;;N;;;;; +31BD;BOPOMOFO LETTER KW;Lo;0;L;;;;;N;;;;; +31BE;BOPOMOFO LETTER OE;Lo;0;L;;;;;N;;;;; +31BF;BOPOMOFO LETTER AH;Lo;0;L;;;;;N;;;;; +31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; +31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; +31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; +31C3;CJK STROKE BXG;So;0;ON;;;;;N;;;;; +31C4;CJK STROKE SW;So;0;ON;;;;;N;;;;; +31C5;CJK STROKE HZZ;So;0;ON;;;;;N;;;;; +31C6;CJK STROKE HZG;So;0;ON;;;;;N;;;;; +31C7;CJK STROKE HP;So;0;ON;;;;;N;;;;; +31C8;CJK STROKE HZWG;So;0;ON;;;;;N;;;;; +31C9;CJK STROKE SZWG;So;0;ON;;;;;N;;;;; +31CA;CJK STROKE HZT;So;0;ON;;;;;N;;;;; +31CB;CJK STROKE HZZP;So;0;ON;;;;;N;;;;; +31CC;CJK STROKE HPWG;So;0;ON;;;;;N;;;;; +31CD;CJK STROKE HZW;So;0;ON;;;;;N;;;;; +31CE;CJK STROKE HZZZ;So;0;ON;;;;;N;;;;; +31CF;CJK STROKE N;So;0;ON;;;;;N;;;;; +31D0;CJK STROKE H;So;0;ON;;;;;N;;;;; +31D1;CJK STROKE S;So;0;ON;;;;;N;;;;; +31D2;CJK STROKE P;So;0;ON;;;;;N;;;;; +31D3;CJK STROKE SP;So;0;ON;;;;;N;;;;; +31D4;CJK STROKE D;So;0;ON;;;;;N;;;;; +31D5;CJK STROKE HZ;So;0;ON;;;;;N;;;;; +31D6;CJK STROKE HG;So;0;ON;;;;;N;;;;; +31D7;CJK STROKE SZ;So;0;ON;;;;;N;;;;; +31D8;CJK STROKE SWZ;So;0;ON;;;;;N;;;;; +31D9;CJK STROKE ST;So;0;ON;;;;;N;;;;; +31DA;CJK STROKE SG;So;0;ON;;;;;N;;;;; +31DB;CJK STROKE PD;So;0;ON;;;;;N;;;;; +31DC;CJK STROKE PZ;So;0;ON;;;;;N;;;;; +31DD;CJK STROKE TN;So;0;ON;;;;;N;;;;; +31DE;CJK STROKE SZZ;So;0;ON;;;;;N;;;;; +31DF;CJK STROKE SWG;So;0;ON;;;;;N;;;;; +31E0;CJK STROKE HXWG;So;0;ON;;;;;N;;;;; +31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;; +31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;; +31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;; +31E4;CJK STROKE HXG;So;0;ON;;;;;N;;;;; +31E5;CJK STROKE SZP;So;0;ON;;;;;N;;;;; +31EF;IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION;So;0;ON;;;;;N;;;;; +31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;; +31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;; +31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;; +31F3;KATAKANA LETTER SMALL TO;Lo;0;L;;;;;N;;;;; +31F4;KATAKANA LETTER SMALL NU;Lo;0;L;;;;;N;;;;; +31F5;KATAKANA LETTER SMALL HA;Lo;0;L;;;;;N;;;;; +31F6;KATAKANA LETTER SMALL HI;Lo;0;L;;;;;N;;;;; +31F7;KATAKANA LETTER SMALL HU;Lo;0;L;;;;;N;;;;; +31F8;KATAKANA LETTER SMALL HE;Lo;0;L;;;;;N;;;;; +31F9;KATAKANA LETTER SMALL HO;Lo;0;L;;;;;N;;;;; +31FA;KATAKANA LETTER SMALL MU;Lo;0;L;;;;;N;;;;; +31FB;KATAKANA LETTER SMALL RA;Lo;0;L;;;;;N;;;;; +31FC;KATAKANA LETTER SMALL RI;Lo;0;L;;;;;N;;;;; +31FD;KATAKANA LETTER SMALL RU;Lo;0;L;;;;;N;;;;; +31FE;KATAKANA LETTER SMALL RE;Lo;0;L;;;;;N;;;;; +31FF;KATAKANA LETTER SMALL RO;Lo;0;L;;;;;N;;;;; +3200;PARENTHESIZED HANGUL KIYEOK;So;0;L; 0028 1100 0029;;;;N;PARENTHESIZED HANGUL GIYEOG;;;; +3201;PARENTHESIZED HANGUL NIEUN;So;0;L; 0028 1102 0029;;;;N;;;;; +3202;PARENTHESIZED HANGUL TIKEUT;So;0;L; 0028 1103 0029;;;;N;PARENTHESIZED HANGUL DIGEUD;;;; +3203;PARENTHESIZED HANGUL RIEUL;So;0;L; 0028 1105 0029;;;;N;PARENTHESIZED HANGUL LIEUL;;;; +3204;PARENTHESIZED HANGUL MIEUM;So;0;L; 0028 1106 0029;;;;N;;;;; +3205;PARENTHESIZED HANGUL PIEUP;So;0;L; 0028 1107 0029;;;;N;PARENTHESIZED HANGUL BIEUB;;;; +3206;PARENTHESIZED HANGUL SIOS;So;0;L; 0028 1109 0029;;;;N;;;;; +3207;PARENTHESIZED HANGUL IEUNG;So;0;L; 0028 110B 0029;;;;N;;;;; +3208;PARENTHESIZED HANGUL CIEUC;So;0;L; 0028 110C 0029;;;;N;PARENTHESIZED HANGUL JIEUJ;;;; +3209;PARENTHESIZED HANGUL CHIEUCH;So;0;L; 0028 110E 0029;;;;N;PARENTHESIZED HANGUL CIEUC;;;; +320A;PARENTHESIZED HANGUL KHIEUKH;So;0;L; 0028 110F 0029;;;;N;PARENTHESIZED HANGUL KIYEOK;;;; +320B;PARENTHESIZED HANGUL THIEUTH;So;0;L; 0028 1110 0029;;;;N;PARENTHESIZED HANGUL TIEUT;;;; +320C;PARENTHESIZED HANGUL PHIEUPH;So;0;L; 0028 1111 0029;;;;N;PARENTHESIZED HANGUL PIEUP;;;; +320D;PARENTHESIZED HANGUL HIEUH;So;0;L; 0028 1112 0029;;;;N;;;;; +320E;PARENTHESIZED HANGUL KIYEOK A;So;0;L; 0028 1100 1161 0029;;;;N;PARENTHESIZED HANGUL GA;;;; +320F;PARENTHESIZED HANGUL NIEUN A;So;0;L; 0028 1102 1161 0029;;;;N;PARENTHESIZED HANGUL NA;;;; +3210;PARENTHESIZED HANGUL TIKEUT A;So;0;L; 0028 1103 1161 0029;;;;N;PARENTHESIZED HANGUL DA;;;; +3211;PARENTHESIZED HANGUL RIEUL A;So;0;L; 0028 1105 1161 0029;;;;N;PARENTHESIZED HANGUL LA;;;; +3212;PARENTHESIZED HANGUL MIEUM A;So;0;L; 0028 1106 1161 0029;;;;N;PARENTHESIZED HANGUL MA;;;; +3213;PARENTHESIZED HANGUL PIEUP A;So;0;L; 0028 1107 1161 0029;;;;N;PARENTHESIZED HANGUL BA;;;; +3214;PARENTHESIZED HANGUL SIOS A;So;0;L; 0028 1109 1161 0029;;;;N;PARENTHESIZED HANGUL SA;;;; +3215;PARENTHESIZED HANGUL IEUNG A;So;0;L; 0028 110B 1161 0029;;;;N;PARENTHESIZED HANGUL A;;;; +3216;PARENTHESIZED HANGUL CIEUC A;So;0;L; 0028 110C 1161 0029;;;;N;PARENTHESIZED HANGUL JA;;;; +3217;PARENTHESIZED HANGUL CHIEUCH A;So;0;L; 0028 110E 1161 0029;;;;N;PARENTHESIZED HANGUL CA;;;; +3218;PARENTHESIZED HANGUL KHIEUKH A;So;0;L; 0028 110F 1161 0029;;;;N;PARENTHESIZED HANGUL KA;;;; +3219;PARENTHESIZED HANGUL THIEUTH A;So;0;L; 0028 1110 1161 0029;;;;N;PARENTHESIZED HANGUL TA;;;; +321A;PARENTHESIZED HANGUL PHIEUPH A;So;0;L; 0028 1111 1161 0029;;;;N;PARENTHESIZED HANGUL PA;;;; +321B;PARENTHESIZED HANGUL HIEUH A;So;0;L; 0028 1112 1161 0029;;;;N;PARENTHESIZED HANGUL HA;;;; +321C;PARENTHESIZED HANGUL CIEUC U;So;0;L; 0028 110C 116E 0029;;;;N;PARENTHESIZED HANGUL JU;;;; +321D;PARENTHESIZED KOREAN CHARACTER OJEON;So;0;ON; 0028 110B 1169 110C 1165 11AB 0029;;;;N;;;;; +321E;PARENTHESIZED KOREAN CHARACTER O HU;So;0;ON; 0028 110B 1169 1112 116E 0029;;;;N;;;;; +3220;PARENTHESIZED IDEOGRAPH ONE;No;0;L; 0028 4E00 0029;;;1;N;;;;; +3221;PARENTHESIZED IDEOGRAPH TWO;No;0;L; 0028 4E8C 0029;;;2;N;;;;; +3222;PARENTHESIZED IDEOGRAPH THREE;No;0;L; 0028 4E09 0029;;;3;N;;;;; +3223;PARENTHESIZED IDEOGRAPH FOUR;No;0;L; 0028 56DB 0029;;;4;N;;;;; +3224;PARENTHESIZED IDEOGRAPH FIVE;No;0;L; 0028 4E94 0029;;;5;N;;;;; +3225;PARENTHESIZED IDEOGRAPH SIX;No;0;L; 0028 516D 0029;;;6;N;;;;; +3226;PARENTHESIZED IDEOGRAPH SEVEN;No;0;L; 0028 4E03 0029;;;7;N;;;;; +3227;PARENTHESIZED IDEOGRAPH EIGHT;No;0;L; 0028 516B 0029;;;8;N;;;;; +3228;PARENTHESIZED IDEOGRAPH NINE;No;0;L; 0028 4E5D 0029;;;9;N;;;;; +3229;PARENTHESIZED IDEOGRAPH TEN;No;0;L; 0028 5341 0029;;;10;N;;;;; +322A;PARENTHESIZED IDEOGRAPH MOON;So;0;L; 0028 6708 0029;;;;N;;;;; +322B;PARENTHESIZED IDEOGRAPH FIRE;So;0;L; 0028 706B 0029;;;;N;;;;; +322C;PARENTHESIZED IDEOGRAPH WATER;So;0;L; 0028 6C34 0029;;;;N;;;;; +322D;PARENTHESIZED IDEOGRAPH WOOD;So;0;L; 0028 6728 0029;;;;N;;;;; +322E;PARENTHESIZED IDEOGRAPH METAL;So;0;L; 0028 91D1 0029;;;;N;;;;; +322F;PARENTHESIZED IDEOGRAPH EARTH;So;0;L; 0028 571F 0029;;;;N;;;;; +3230;PARENTHESIZED IDEOGRAPH SUN;So;0;L; 0028 65E5 0029;;;;N;;;;; +3231;PARENTHESIZED IDEOGRAPH STOCK;So;0;L; 0028 682A 0029;;;;N;;;;; +3232;PARENTHESIZED IDEOGRAPH HAVE;So;0;L; 0028 6709 0029;;;;N;;;;; +3233;PARENTHESIZED IDEOGRAPH SOCIETY;So;0;L; 0028 793E 0029;;;;N;;;;; +3234;PARENTHESIZED IDEOGRAPH NAME;So;0;L; 0028 540D 0029;;;;N;;;;; +3235;PARENTHESIZED IDEOGRAPH SPECIAL;So;0;L; 0028 7279 0029;;;;N;;;;; +3236;PARENTHESIZED IDEOGRAPH FINANCIAL;So;0;L; 0028 8CA1 0029;;;;N;;;;; +3237;PARENTHESIZED IDEOGRAPH CONGRATULATION;So;0;L; 0028 795D 0029;;;;N;;;;; +3238;PARENTHESIZED IDEOGRAPH LABOR;So;0;L; 0028 52B4 0029;;;;N;;;;; +3239;PARENTHESIZED IDEOGRAPH REPRESENT;So;0;L; 0028 4EE3 0029;;;;N;;;;; +323A;PARENTHESIZED IDEOGRAPH CALL;So;0;L; 0028 547C 0029;;;;N;;;;; +323B;PARENTHESIZED IDEOGRAPH STUDY;So;0;L; 0028 5B66 0029;;;;N;;;;; +323C;PARENTHESIZED IDEOGRAPH SUPERVISE;So;0;L; 0028 76E3 0029;;;;N;;;;; +323D;PARENTHESIZED IDEOGRAPH ENTERPRISE;So;0;L; 0028 4F01 0029;;;;N;;;;; +323E;PARENTHESIZED IDEOGRAPH RESOURCE;So;0;L; 0028 8CC7 0029;;;;N;;;;; +323F;PARENTHESIZED IDEOGRAPH ALLIANCE;So;0;L; 0028 5354 0029;;;;N;;;;; +3240;PARENTHESIZED IDEOGRAPH FESTIVAL;So;0;L; 0028 796D 0029;;;;N;;;;; +3241;PARENTHESIZED IDEOGRAPH REST;So;0;L; 0028 4F11 0029;;;;N;;;;; +3242;PARENTHESIZED IDEOGRAPH SELF;So;0;L; 0028 81EA 0029;;;;N;;;;; +3243;PARENTHESIZED IDEOGRAPH REACH;So;0;L; 0028 81F3 0029;;;;N;;;;; +3244;CIRCLED IDEOGRAPH QUESTION;So;0;L; 554F;;;;N;;;;; +3245;CIRCLED IDEOGRAPH KINDERGARTEN;So;0;L; 5E7C;;;;N;;;;; +3246;CIRCLED IDEOGRAPH SCHOOL;So;0;L; 6587;;;;N;;;;; +3247;CIRCLED IDEOGRAPH KOTO;So;0;L; 7B8F;;;;N;;;;; +3248;CIRCLED NUMBER TEN ON BLACK SQUARE;No;0;L;;;;10;N;;;;; +3249;CIRCLED NUMBER TWENTY ON BLACK SQUARE;No;0;L;;;;20;N;;;;; +324A;CIRCLED NUMBER THIRTY ON BLACK SQUARE;No;0;L;;;;30;N;;;;; +324B;CIRCLED NUMBER FORTY ON BLACK SQUARE;No;0;L;;;;40;N;;;;; +324C;CIRCLED NUMBER FIFTY ON BLACK SQUARE;No;0;L;;;;50;N;;;;; +324D;CIRCLED NUMBER SIXTY ON BLACK SQUARE;No;0;L;;;;60;N;;;;; +324E;CIRCLED NUMBER SEVENTY ON BLACK SQUARE;No;0;L;;;;70;N;;;;; +324F;CIRCLED NUMBER EIGHTY ON BLACK SQUARE;No;0;L;;;;80;N;;;;; +3250;PARTNERSHIP SIGN;So;0;ON; 0050 0054 0045;;;;N;;;;; +3251;CIRCLED NUMBER TWENTY ONE;No;0;ON; 0032 0031;;;21;N;;;;; +3252;CIRCLED NUMBER TWENTY TWO;No;0;ON; 0032 0032;;;22;N;;;;; +3253;CIRCLED NUMBER TWENTY THREE;No;0;ON; 0032 0033;;;23;N;;;;; +3254;CIRCLED NUMBER TWENTY FOUR;No;0;ON; 0032 0034;;;24;N;;;;; +3255;CIRCLED NUMBER TWENTY FIVE;No;0;ON; 0032 0035;;;25;N;;;;; +3256;CIRCLED NUMBER TWENTY SIX;No;0;ON; 0032 0036;;;26;N;;;;; +3257;CIRCLED NUMBER TWENTY SEVEN;No;0;ON; 0032 0037;;;27;N;;;;; +3258;CIRCLED NUMBER TWENTY EIGHT;No;0;ON; 0032 0038;;;28;N;;;;; +3259;CIRCLED NUMBER TWENTY NINE;No;0;ON; 0032 0039;;;29;N;;;;; +325A;CIRCLED NUMBER THIRTY;No;0;ON; 0033 0030;;;30;N;;;;; +325B;CIRCLED NUMBER THIRTY ONE;No;0;ON; 0033 0031;;;31;N;;;;; +325C;CIRCLED NUMBER THIRTY TWO;No;0;ON; 0033 0032;;;32;N;;;;; +325D;CIRCLED NUMBER THIRTY THREE;No;0;ON; 0033 0033;;;33;N;;;;; +325E;CIRCLED NUMBER THIRTY FOUR;No;0;ON; 0033 0034;;;34;N;;;;; +325F;CIRCLED NUMBER THIRTY FIVE;No;0;ON; 0033 0035;;;35;N;;;;; +3260;CIRCLED HANGUL KIYEOK;So;0;L; 1100;;;;N;CIRCLED HANGUL GIYEOG;;;; +3261;CIRCLED HANGUL NIEUN;So;0;L; 1102;;;;N;;;;; +3262;CIRCLED HANGUL TIKEUT;So;0;L; 1103;;;;N;CIRCLED HANGUL DIGEUD;;;; +3263;CIRCLED HANGUL RIEUL;So;0;L; 1105;;;;N;CIRCLED HANGUL LIEUL;;;; +3264;CIRCLED HANGUL MIEUM;So;0;L; 1106;;;;N;;;;; +3265;CIRCLED HANGUL PIEUP;So;0;L; 1107;;;;N;CIRCLED HANGUL BIEUB;;;; +3266;CIRCLED HANGUL SIOS;So;0;L; 1109;;;;N;;;;; +3267;CIRCLED HANGUL IEUNG;So;0;L; 110B;;;;N;;;;; +3268;CIRCLED HANGUL CIEUC;So;0;L; 110C;;;;N;CIRCLED HANGUL JIEUJ;;;; +3269;CIRCLED HANGUL CHIEUCH;So;0;L; 110E;;;;N;CIRCLED HANGUL CIEUC;;;; +326A;CIRCLED HANGUL KHIEUKH;So;0;L; 110F;;;;N;CIRCLED HANGUL KIYEOK;;;; +326B;CIRCLED HANGUL THIEUTH;So;0;L; 1110;;;;N;CIRCLED HANGUL TIEUT;;;; +326C;CIRCLED HANGUL PHIEUPH;So;0;L; 1111;;;;N;CIRCLED HANGUL PIEUP;;;; +326D;CIRCLED HANGUL HIEUH;So;0;L; 1112;;;;N;;;;; +326E;CIRCLED HANGUL KIYEOK A;So;0;L; 1100 1161;;;;N;CIRCLED HANGUL GA;;;; +326F;CIRCLED HANGUL NIEUN A;So;0;L; 1102 1161;;;;N;CIRCLED HANGUL NA;;;; +3270;CIRCLED HANGUL TIKEUT A;So;0;L; 1103 1161;;;;N;CIRCLED HANGUL DA;;;; +3271;CIRCLED HANGUL RIEUL A;So;0;L; 1105 1161;;;;N;CIRCLED HANGUL LA;;;; +3272;CIRCLED HANGUL MIEUM A;So;0;L; 1106 1161;;;;N;CIRCLED HANGUL MA;;;; +3273;CIRCLED HANGUL PIEUP A;So;0;L; 1107 1161;;;;N;CIRCLED HANGUL BA;;;; +3274;CIRCLED HANGUL SIOS A;So;0;L; 1109 1161;;;;N;CIRCLED HANGUL SA;;;; +3275;CIRCLED HANGUL IEUNG A;So;0;L; 110B 1161;;;;N;CIRCLED HANGUL A;;;; +3276;CIRCLED HANGUL CIEUC A;So;0;L; 110C 1161;;;;N;CIRCLED HANGUL JA;;;; +3277;CIRCLED HANGUL CHIEUCH A;So;0;L; 110E 1161;;;;N;CIRCLED HANGUL CA;;;; +3278;CIRCLED HANGUL KHIEUKH A;So;0;L; 110F 1161;;;;N;CIRCLED HANGUL KA;;;; +3279;CIRCLED HANGUL THIEUTH A;So;0;L; 1110 1161;;;;N;CIRCLED HANGUL TA;;;; +327A;CIRCLED HANGUL PHIEUPH A;So;0;L; 1111 1161;;;;N;CIRCLED HANGUL PA;;;; +327B;CIRCLED HANGUL HIEUH A;So;0;L; 1112 1161;;;;N;CIRCLED HANGUL HA;;;; +327C;CIRCLED KOREAN CHARACTER CHAMKO;So;0;ON; 110E 1161 11B7 1100 1169;;;;N;;;;; +327D;CIRCLED KOREAN CHARACTER JUEUI;So;0;ON; 110C 116E 110B 1174;;;;N;;;;; +327E;CIRCLED HANGUL IEUNG U;So;0;ON; 110B 116E;;;;N;;;;; +327F;KOREAN STANDARD SYMBOL;So;0;L;;;;;N;;;;; +3280;CIRCLED IDEOGRAPH ONE;No;0;L; 4E00;;;1;N;;;;; +3281;CIRCLED IDEOGRAPH TWO;No;0;L; 4E8C;;;2;N;;;;; +3282;CIRCLED IDEOGRAPH THREE;No;0;L; 4E09;;;3;N;;;;; +3283;CIRCLED IDEOGRAPH FOUR;No;0;L; 56DB;;;4;N;;;;; +3284;CIRCLED IDEOGRAPH FIVE;No;0;L; 4E94;;;5;N;;;;; +3285;CIRCLED IDEOGRAPH SIX;No;0;L; 516D;;;6;N;;;;; +3286;CIRCLED IDEOGRAPH SEVEN;No;0;L; 4E03;;;7;N;;;;; +3287;CIRCLED IDEOGRAPH EIGHT;No;0;L; 516B;;;8;N;;;;; +3288;CIRCLED IDEOGRAPH NINE;No;0;L; 4E5D;;;9;N;;;;; +3289;CIRCLED IDEOGRAPH TEN;No;0;L; 5341;;;10;N;;;;; +328A;CIRCLED IDEOGRAPH MOON;So;0;L; 6708;;;;N;;;;; +328B;CIRCLED IDEOGRAPH FIRE;So;0;L; 706B;;;;N;;;;; +328C;CIRCLED IDEOGRAPH WATER;So;0;L; 6C34;;;;N;;;;; +328D;CIRCLED IDEOGRAPH WOOD;So;0;L; 6728;;;;N;;;;; +328E;CIRCLED IDEOGRAPH METAL;So;0;L; 91D1;;;;N;;;;; +328F;CIRCLED IDEOGRAPH EARTH;So;0;L; 571F;;;;N;;;;; +3290;CIRCLED IDEOGRAPH SUN;So;0;L; 65E5;;;;N;;;;; +3291;CIRCLED IDEOGRAPH STOCK;So;0;L; 682A;;;;N;;;;; +3292;CIRCLED IDEOGRAPH HAVE;So;0;L; 6709;;;;N;;;;; +3293;CIRCLED IDEOGRAPH SOCIETY;So;0;L; 793E;;;;N;;;;; +3294;CIRCLED IDEOGRAPH NAME;So;0;L; 540D;;;;N;;;;; +3295;CIRCLED IDEOGRAPH SPECIAL;So;0;L; 7279;;;;N;;;;; +3296;CIRCLED IDEOGRAPH FINANCIAL;So;0;L; 8CA1;;;;N;;;;; +3297;CIRCLED IDEOGRAPH CONGRATULATION;So;0;L; 795D;;;;N;;;;; +3298;CIRCLED IDEOGRAPH LABOR;So;0;L; 52B4;;;;N;;;;; +3299;CIRCLED IDEOGRAPH SECRET;So;0;L; 79D8;;;;N;;;;; +329A;CIRCLED IDEOGRAPH MALE;So;0;L; 7537;;;;N;;;;; +329B;CIRCLED IDEOGRAPH FEMALE;So;0;L; 5973;;;;N;;;;; +329C;CIRCLED IDEOGRAPH SUITABLE;So;0;L; 9069;;;;N;;;;; +329D;CIRCLED IDEOGRAPH EXCELLENT;So;0;L; 512A;;;;N;;;;; +329E;CIRCLED IDEOGRAPH PRINT;So;0;L; 5370;;;;N;;;;; +329F;CIRCLED IDEOGRAPH ATTENTION;So;0;L; 6CE8;;;;N;;;;; +32A0;CIRCLED IDEOGRAPH ITEM;So;0;L; 9805;;;;N;;;;; +32A1;CIRCLED IDEOGRAPH REST;So;0;L; 4F11;;;;N;;;;; +32A2;CIRCLED IDEOGRAPH COPY;So;0;L; 5199;;;;N;;;;; +32A3;CIRCLED IDEOGRAPH CORRECT;So;0;L; 6B63;;;;N;;;;; +32A4;CIRCLED IDEOGRAPH HIGH;So;0;L; 4E0A;;;;N;;;;; +32A5;CIRCLED IDEOGRAPH CENTRE;So;0;L; 4E2D;;;;N;CIRCLED IDEOGRAPH CENTER;;;; +32A6;CIRCLED IDEOGRAPH LOW;So;0;L; 4E0B;;;;N;;;;; +32A7;CIRCLED IDEOGRAPH LEFT;So;0;L; 5DE6;;;;N;;;;; +32A8;CIRCLED IDEOGRAPH RIGHT;So;0;L; 53F3;;;;N;;;;; +32A9;CIRCLED IDEOGRAPH MEDICINE;So;0;L; 533B;;;;N;;;;; +32AA;CIRCLED IDEOGRAPH RELIGION;So;0;L; 5B97;;;;N;;;;; +32AB;CIRCLED IDEOGRAPH STUDY;So;0;L; 5B66;;;;N;;;;; +32AC;CIRCLED IDEOGRAPH SUPERVISE;So;0;L; 76E3;;;;N;;;;; +32AD;CIRCLED IDEOGRAPH ENTERPRISE;So;0;L; 4F01;;;;N;;;;; +32AE;CIRCLED IDEOGRAPH RESOURCE;So;0;L; 8CC7;;;;N;;;;; +32AF;CIRCLED IDEOGRAPH ALLIANCE;So;0;L; 5354;;;;N;;;;; +32B0;CIRCLED IDEOGRAPH NIGHT;So;0;L; 591C;;;;N;;;;; +32B1;CIRCLED NUMBER THIRTY SIX;No;0;ON; 0033 0036;;;36;N;;;;; +32B2;CIRCLED NUMBER THIRTY SEVEN;No;0;ON; 0033 0037;;;37;N;;;;; +32B3;CIRCLED NUMBER THIRTY EIGHT;No;0;ON; 0033 0038;;;38;N;;;;; +32B4;CIRCLED NUMBER THIRTY NINE;No;0;ON; 0033 0039;;;39;N;;;;; +32B5;CIRCLED NUMBER FORTY;No;0;ON; 0034 0030;;;40;N;;;;; +32B6;CIRCLED NUMBER FORTY ONE;No;0;ON; 0034 0031;;;41;N;;;;; +32B7;CIRCLED NUMBER FORTY TWO;No;0;ON; 0034 0032;;;42;N;;;;; +32B8;CIRCLED NUMBER FORTY THREE;No;0;ON; 0034 0033;;;43;N;;;;; +32B9;CIRCLED NUMBER FORTY FOUR;No;0;ON; 0034 0034;;;44;N;;;;; +32BA;CIRCLED NUMBER FORTY FIVE;No;0;ON; 0034 0035;;;45;N;;;;; +32BB;CIRCLED NUMBER FORTY SIX;No;0;ON; 0034 0036;;;46;N;;;;; +32BC;CIRCLED NUMBER FORTY SEVEN;No;0;ON; 0034 0037;;;47;N;;;;; +32BD;CIRCLED NUMBER FORTY EIGHT;No;0;ON; 0034 0038;;;48;N;;;;; +32BE;CIRCLED NUMBER FORTY NINE;No;0;ON; 0034 0039;;;49;N;;;;; +32BF;CIRCLED NUMBER FIFTY;No;0;ON; 0035 0030;;;50;N;;;;; +32C0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY;So;0;L; 0031 6708;;;;N;;;;; +32C1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY;So;0;L; 0032 6708;;;;N;;;;; +32C2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH;So;0;L; 0033 6708;;;;N;;;;; +32C3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL;So;0;L; 0034 6708;;;;N;;;;; +32C4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY;So;0;L; 0035 6708;;;;N;;;;; +32C5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE;So;0;L; 0036 6708;;;;N;;;;; +32C6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY;So;0;L; 0037 6708;;;;N;;;;; +32C7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST;So;0;L; 0038 6708;;;;N;;;;; +32C8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER;So;0;L; 0039 6708;;;;N;;;;; +32C9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER;So;0;L; 0031 0030 6708;;;;N;;;;; +32CA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER;So;0;L; 0031 0031 6708;;;;N;;;;; +32CB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER;So;0;L; 0031 0032 6708;;;;N;;;;; +32CC;SQUARE HG;So;0;ON; 0048 0067;;;;N;;;;; +32CD;SQUARE ERG;So;0;ON; 0065 0072 0067;;;;N;;;;; +32CE;SQUARE EV;So;0;ON; 0065 0056;;;;N;;;;; +32CF;LIMITED LIABILITY SIGN;So;0;ON; 004C 0054 0044;;;;N;;;;; +32D0;CIRCLED KATAKANA A;So;0;L; 30A2;;;;N;;;;; +32D1;CIRCLED KATAKANA I;So;0;L; 30A4;;;;N;;;;; +32D2;CIRCLED KATAKANA U;So;0;L; 30A6;;;;N;;;;; +32D3;CIRCLED KATAKANA E;So;0;L; 30A8;;;;N;;;;; +32D4;CIRCLED KATAKANA O;So;0;L; 30AA;;;;N;;;;; +32D5;CIRCLED KATAKANA KA;So;0;L; 30AB;;;;N;;;;; +32D6;CIRCLED KATAKANA KI;So;0;L; 30AD;;;;N;;;;; +32D7;CIRCLED KATAKANA KU;So;0;L; 30AF;;;;N;;;;; +32D8;CIRCLED KATAKANA KE;So;0;L; 30B1;;;;N;;;;; +32D9;CIRCLED KATAKANA KO;So;0;L; 30B3;;;;N;;;;; +32DA;CIRCLED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; +32DB;CIRCLED KATAKANA SI;So;0;L; 30B7;;;;N;;;;; +32DC;CIRCLED KATAKANA SU;So;0;L; 30B9;;;;N;;;;; +32DD;CIRCLED KATAKANA SE;So;0;L; 30BB;;;;N;;;;; +32DE;CIRCLED KATAKANA SO;So;0;L; 30BD;;;;N;;;;; +32DF;CIRCLED KATAKANA TA;So;0;L; 30BF;;;;N;;;;; +32E0;CIRCLED KATAKANA TI;So;0;L; 30C1;;;;N;;;;; +32E1;CIRCLED KATAKANA TU;So;0;L; 30C4;;;;N;;;;; +32E2;CIRCLED KATAKANA TE;So;0;L; 30C6;;;;N;;;;; +32E3;CIRCLED KATAKANA TO;So;0;L; 30C8;;;;N;;;;; +32E4;CIRCLED KATAKANA NA;So;0;L; 30CA;;;;N;;;;; +32E5;CIRCLED KATAKANA NI;So;0;L; 30CB;;;;N;;;;; +32E6;CIRCLED KATAKANA NU;So;0;L; 30CC;;;;N;;;;; +32E7;CIRCLED KATAKANA NE;So;0;L; 30CD;;;;N;;;;; +32E8;CIRCLED KATAKANA NO;So;0;L; 30CE;;;;N;;;;; +32E9;CIRCLED KATAKANA HA;So;0;L; 30CF;;;;N;;;;; +32EA;CIRCLED KATAKANA HI;So;0;L; 30D2;;;;N;;;;; +32EB;CIRCLED KATAKANA HU;So;0;L; 30D5;;;;N;;;;; +32EC;CIRCLED KATAKANA HE;So;0;L; 30D8;;;;N;;;;; +32ED;CIRCLED KATAKANA HO;So;0;L; 30DB;;;;N;;;;; +32EE;CIRCLED KATAKANA MA;So;0;L; 30DE;;;;N;;;;; +32EF;CIRCLED KATAKANA MI;So;0;L; 30DF;;;;N;;;;; +32F0;CIRCLED KATAKANA MU;So;0;L; 30E0;;;;N;;;;; +32F1;CIRCLED KATAKANA ME;So;0;L; 30E1;;;;N;;;;; +32F2;CIRCLED KATAKANA MO;So;0;L; 30E2;;;;N;;;;; +32F3;CIRCLED KATAKANA YA;So;0;L; 30E4;;;;N;;;;; +32F4;CIRCLED KATAKANA YU;So;0;L; 30E6;;;;N;;;;; +32F5;CIRCLED KATAKANA YO;So;0;L; 30E8;;;;N;;;;; +32F6;CIRCLED KATAKANA RA;So;0;L; 30E9;;;;N;;;;; +32F7;CIRCLED KATAKANA RI;So;0;L; 30EA;;;;N;;;;; +32F8;CIRCLED KATAKANA RU;So;0;L; 30EB;;;;N;;;;; +32F9;CIRCLED KATAKANA RE;So;0;L; 30EC;;;;N;;;;; +32FA;CIRCLED KATAKANA RO;So;0;L; 30ED;;;;N;;;;; +32FB;CIRCLED KATAKANA WA;So;0;L; 30EF;;;;N;;;;; +32FC;CIRCLED KATAKANA WI;So;0;L; 30F0;;;;N;;;;; +32FD;CIRCLED KATAKANA WE;So;0;L; 30F1;;;;N;;;;; +32FE;CIRCLED KATAKANA WO;So;0;L; 30F2;;;;N;;;;; +32FF;SQUARE ERA NAME REIWA;So;0;L; 4EE4 548C;;;;N;;;;; +3300;SQUARE APAATO;So;0;L; 30A2 30D1 30FC 30C8;;;;N;SQUARED APAATO;;;; +3301;SQUARE ARUHUA;So;0;L; 30A2 30EB 30D5 30A1;;;;N;SQUARED ARUHUA;;;; +3302;SQUARE ANPEA;So;0;L; 30A2 30F3 30DA 30A2;;;;N;SQUARED ANPEA;;;; +3303;SQUARE AARU;So;0;L; 30A2 30FC 30EB;;;;N;SQUARED AARU;;;; +3304;SQUARE ININGU;So;0;L; 30A4 30CB 30F3 30B0;;;;N;SQUARED ININGU;;;; +3305;SQUARE INTI;So;0;L; 30A4 30F3 30C1;;;;N;SQUARED INTI;;;; +3306;SQUARE UON;So;0;L; 30A6 30A9 30F3;;;;N;SQUARED UON;;;; +3307;SQUARE ESUKUUDO;So;0;L; 30A8 30B9 30AF 30FC 30C9;;;;N;SQUARED ESUKUUDO;;;; +3308;SQUARE EEKAA;So;0;L; 30A8 30FC 30AB 30FC;;;;N;SQUARED EEKAA;;;; +3309;SQUARE ONSU;So;0;L; 30AA 30F3 30B9;;;;N;SQUARED ONSU;;;; +330A;SQUARE OOMU;So;0;L; 30AA 30FC 30E0;;;;N;SQUARED OOMU;;;; +330B;SQUARE KAIRI;So;0;L; 30AB 30A4 30EA;;;;N;SQUARED KAIRI;;;; +330C;SQUARE KARATTO;So;0;L; 30AB 30E9 30C3 30C8;;;;N;SQUARED KARATTO;;;; +330D;SQUARE KARORII;So;0;L; 30AB 30ED 30EA 30FC;;;;N;SQUARED KARORII;;;; +330E;SQUARE GARON;So;0;L; 30AC 30ED 30F3;;;;N;SQUARED GARON;;;; +330F;SQUARE GANMA;So;0;L; 30AC 30F3 30DE;;;;N;SQUARED GANMA;;;; +3310;SQUARE GIGA;So;0;L; 30AE 30AC;;;;N;SQUARED GIGA;;;; +3311;SQUARE GINII;So;0;L; 30AE 30CB 30FC;;;;N;SQUARED GINII;;;; +3312;SQUARE KYURII;So;0;L; 30AD 30E5 30EA 30FC;;;;N;SQUARED KYURII;;;; +3313;SQUARE GIRUDAA;So;0;L; 30AE 30EB 30C0 30FC;;;;N;SQUARED GIRUDAA;;;; +3314;SQUARE KIRO;So;0;L; 30AD 30ED;;;;N;SQUARED KIRO;;;; +3315;SQUARE KIROGURAMU;So;0;L; 30AD 30ED 30B0 30E9 30E0;;;;N;SQUARED KIROGURAMU;;;; +3316;SQUARE KIROMEETORU;So;0;L; 30AD 30ED 30E1 30FC 30C8 30EB;;;;N;SQUARED KIROMEETORU;;;; +3317;SQUARE KIROWATTO;So;0;L; 30AD 30ED 30EF 30C3 30C8;;;;N;SQUARED KIROWATTO;;;; +3318;SQUARE GURAMU;So;0;L; 30B0 30E9 30E0;;;;N;SQUARED GURAMU;;;; +3319;SQUARE GURAMUTON;So;0;L; 30B0 30E9 30E0 30C8 30F3;;;;N;SQUARED GURAMUTON;;;; +331A;SQUARE KURUZEIRO;So;0;L; 30AF 30EB 30BC 30A4 30ED;;;;N;SQUARED KURUZEIRO;;;; +331B;SQUARE KUROONE;So;0;L; 30AF 30ED 30FC 30CD;;;;N;SQUARED KUROONE;;;; +331C;SQUARE KEESU;So;0;L; 30B1 30FC 30B9;;;;N;SQUARED KEESU;;;; +331D;SQUARE KORUNA;So;0;L; 30B3 30EB 30CA;;;;N;SQUARED KORUNA;;;; +331E;SQUARE KOOPO;So;0;L; 30B3 30FC 30DD;;;;N;SQUARED KOOPO;;;; +331F;SQUARE SAIKURU;So;0;L; 30B5 30A4 30AF 30EB;;;;N;SQUARED SAIKURU;;;; +3320;SQUARE SANTIIMU;So;0;L; 30B5 30F3 30C1 30FC 30E0;;;;N;SQUARED SANTIIMU;;;; +3321;SQUARE SIRINGU;So;0;L; 30B7 30EA 30F3 30B0;;;;N;SQUARED SIRINGU;;;; +3322;SQUARE SENTI;So;0;L; 30BB 30F3 30C1;;;;N;SQUARED SENTI;;;; +3323;SQUARE SENTO;So;0;L; 30BB 30F3 30C8;;;;N;SQUARED SENTO;;;; +3324;SQUARE DAASU;So;0;L; 30C0 30FC 30B9;;;;N;SQUARED DAASU;;;; +3325;SQUARE DESI;So;0;L; 30C7 30B7;;;;N;SQUARED DESI;;;; +3326;SQUARE DORU;So;0;L; 30C9 30EB;;;;N;SQUARED DORU;;;; +3327;SQUARE TON;So;0;L; 30C8 30F3;;;;N;SQUARED TON;;;; +3328;SQUARE NANO;So;0;L; 30CA 30CE;;;;N;SQUARED NANO;;;; +3329;SQUARE NOTTO;So;0;L; 30CE 30C3 30C8;;;;N;SQUARED NOTTO;;;; +332A;SQUARE HAITU;So;0;L; 30CF 30A4 30C4;;;;N;SQUARED HAITU;;;; +332B;SQUARE PAASENTO;So;0;L; 30D1 30FC 30BB 30F3 30C8;;;;N;SQUARED PAASENTO;;;; +332C;SQUARE PAATU;So;0;L; 30D1 30FC 30C4;;;;N;SQUARED PAATU;;;; +332D;SQUARE BAARERU;So;0;L; 30D0 30FC 30EC 30EB;;;;N;SQUARED BAARERU;;;; +332E;SQUARE PIASUTORU;So;0;L; 30D4 30A2 30B9 30C8 30EB;;;;N;SQUARED PIASUTORU;;;; +332F;SQUARE PIKURU;So;0;L; 30D4 30AF 30EB;;;;N;SQUARED PIKURU;;;; +3330;SQUARE PIKO;So;0;L; 30D4 30B3;;;;N;SQUARED PIKO;;;; +3331;SQUARE BIRU;So;0;L; 30D3 30EB;;;;N;SQUARED BIRU;;;; +3332;SQUARE HUARADDO;So;0;L; 30D5 30A1 30E9 30C3 30C9;;;;N;SQUARED HUARADDO;;;; +3333;SQUARE HUIITO;So;0;L; 30D5 30A3 30FC 30C8;;;;N;SQUARED HUIITO;;;; +3334;SQUARE BUSSYERU;So;0;L; 30D6 30C3 30B7 30A7 30EB;;;;N;SQUARED BUSSYERU;;;; +3335;SQUARE HURAN;So;0;L; 30D5 30E9 30F3;;;;N;SQUARED HURAN;;;; +3336;SQUARE HEKUTAARU;So;0;L; 30D8 30AF 30BF 30FC 30EB;;;;N;SQUARED HEKUTAARU;;;; +3337;SQUARE PESO;So;0;L; 30DA 30BD;;;;N;SQUARED PESO;;;; +3338;SQUARE PENIHI;So;0;L; 30DA 30CB 30D2;;;;N;SQUARED PENIHI;;;; +3339;SQUARE HERUTU;So;0;L; 30D8 30EB 30C4;;;;N;SQUARED HERUTU;;;; +333A;SQUARE PENSU;So;0;L; 30DA 30F3 30B9;;;;N;SQUARED PENSU;;;; +333B;SQUARE PEEZI;So;0;L; 30DA 30FC 30B8;;;;N;SQUARED PEEZI;;;; +333C;SQUARE BEETA;So;0;L; 30D9 30FC 30BF;;;;N;SQUARED BEETA;;;; +333D;SQUARE POINTO;So;0;L; 30DD 30A4 30F3 30C8;;;;N;SQUARED POINTO;;;; +333E;SQUARE BORUTO;So;0;L; 30DC 30EB 30C8;;;;N;SQUARED BORUTO;;;; +333F;SQUARE HON;So;0;L; 30DB 30F3;;;;N;SQUARED HON;;;; +3340;SQUARE PONDO;So;0;L; 30DD 30F3 30C9;;;;N;SQUARED PONDO;;;; +3341;SQUARE HOORU;So;0;L; 30DB 30FC 30EB;;;;N;SQUARED HOORU;;;; +3342;SQUARE HOON;So;0;L; 30DB 30FC 30F3;;;;N;SQUARED HOON;;;; +3343;SQUARE MAIKURO;So;0;L; 30DE 30A4 30AF 30ED;;;;N;SQUARED MAIKURO;;;; +3344;SQUARE MAIRU;So;0;L; 30DE 30A4 30EB;;;;N;SQUARED MAIRU;;;; +3345;SQUARE MAHHA;So;0;L; 30DE 30C3 30CF;;;;N;SQUARED MAHHA;;;; +3346;SQUARE MARUKU;So;0;L; 30DE 30EB 30AF;;;;N;SQUARED MARUKU;;;; +3347;SQUARE MANSYON;So;0;L; 30DE 30F3 30B7 30E7 30F3;;;;N;SQUARED MANSYON;;;; +3348;SQUARE MIKURON;So;0;L; 30DF 30AF 30ED 30F3;;;;N;SQUARED MIKURON;;;; +3349;SQUARE MIRI;So;0;L; 30DF 30EA;;;;N;SQUARED MIRI;;;; +334A;SQUARE MIRIBAARU;So;0;L; 30DF 30EA 30D0 30FC 30EB;;;;N;SQUARED MIRIBAARU;;;; +334B;SQUARE MEGA;So;0;L; 30E1 30AC;;;;N;SQUARED MEGA;;;; +334C;SQUARE MEGATON;So;0;L; 30E1 30AC 30C8 30F3;;;;N;SQUARED MEGATON;;;; +334D;SQUARE MEETORU;So;0;L; 30E1 30FC 30C8 30EB;;;;N;SQUARED MEETORU;;;; +334E;SQUARE YAADO;So;0;L; 30E4 30FC 30C9;;;;N;SQUARED YAADO;;;; +334F;SQUARE YAARU;So;0;L; 30E4 30FC 30EB;;;;N;SQUARED YAARU;;;; +3350;SQUARE YUAN;So;0;L; 30E6 30A2 30F3;;;;N;SQUARED YUAN;;;; +3351;SQUARE RITTORU;So;0;L; 30EA 30C3 30C8 30EB;;;;N;SQUARED RITTORU;;;; +3352;SQUARE RIRA;So;0;L; 30EA 30E9;;;;N;SQUARED RIRA;;;; +3353;SQUARE RUPII;So;0;L; 30EB 30D4 30FC;;;;N;SQUARED RUPII;;;; +3354;SQUARE RUUBURU;So;0;L; 30EB 30FC 30D6 30EB;;;;N;SQUARED RUUBURU;;;; +3355;SQUARE REMU;So;0;L; 30EC 30E0;;;;N;SQUARED REMU;;;; +3356;SQUARE RENTOGEN;So;0;L; 30EC 30F3 30C8 30B2 30F3;;;;N;SQUARED RENTOGEN;;;; +3357;SQUARE WATTO;So;0;L; 30EF 30C3 30C8;;;;N;SQUARED WATTO;;;; +3358;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO;So;0;L; 0030 70B9;;;;N;;;;; +3359;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE;So;0;L; 0031 70B9;;;;N;;;;; +335A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO;So;0;L; 0032 70B9;;;;N;;;;; +335B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE;So;0;L; 0033 70B9;;;;N;;;;; +335C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR;So;0;L; 0034 70B9;;;;N;;;;; +335D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE;So;0;L; 0035 70B9;;;;N;;;;; +335E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX;So;0;L; 0036 70B9;;;;N;;;;; +335F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN;So;0;L; 0037 70B9;;;;N;;;;; +3360;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT;So;0;L; 0038 70B9;;;;N;;;;; +3361;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE;So;0;L; 0039 70B9;;;;N;;;;; +3362;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN;So;0;L; 0031 0030 70B9;;;;N;;;;; +3363;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN;So;0;L; 0031 0031 70B9;;;;N;;;;; +3364;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE;So;0;L; 0031 0032 70B9;;;;N;;;;; +3365;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN;So;0;L; 0031 0033 70B9;;;;N;;;;; +3366;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN;So;0;L; 0031 0034 70B9;;;;N;;;;; +3367;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN;So;0;L; 0031 0035 70B9;;;;N;;;;; +3368;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN;So;0;L; 0031 0036 70B9;;;;N;;;;; +3369;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN;So;0;L; 0031 0037 70B9;;;;N;;;;; +336A;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN;So;0;L; 0031 0038 70B9;;;;N;;;;; +336B;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN;So;0;L; 0031 0039 70B9;;;;N;;;;; +336C;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY;So;0;L; 0032 0030 70B9;;;;N;;;;; +336D;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE;So;0;L; 0032 0031 70B9;;;;N;;;;; +336E;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO;So;0;L; 0032 0032 70B9;;;;N;;;;; +336F;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE;So;0;L; 0032 0033 70B9;;;;N;;;;; +3370;IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR;So;0;L; 0032 0034 70B9;;;;N;;;;; +3371;SQUARE HPA;So;0;L; 0068 0050 0061;;;;N;;;;; +3372;SQUARE DA;So;0;L; 0064 0061;;;;N;;;;; +3373;SQUARE AU;So;0;L; 0041 0055;;;;N;;;;; +3374;SQUARE BAR;So;0;L; 0062 0061 0072;;;;N;;;;; +3375;SQUARE OV;So;0;L; 006F 0056;;;;N;;;;; +3376;SQUARE PC;So;0;L; 0070 0063;;;;N;;;;; +3377;SQUARE DM;So;0;ON; 0064 006D;;;;N;;;;; +3378;SQUARE DM SQUARED;So;0;ON; 0064 006D 00B2;;;;N;;;;; +3379;SQUARE DM CUBED;So;0;ON; 0064 006D 00B3;;;;N;;;;; +337A;SQUARE IU;So;0;ON; 0049 0055;;;;N;;;;; +337B;SQUARE ERA NAME HEISEI;So;0;L; 5E73 6210;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME HEISEI;;;; +337C;SQUARE ERA NAME SYOUWA;So;0;L; 662D 548C;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME SYOUWA;;;; +337D;SQUARE ERA NAME TAISYOU;So;0;L; 5927 6B63;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME TAISYOU;;;; +337E;SQUARE ERA NAME MEIZI;So;0;L; 660E 6CBB;;;;N;SQUARED TWO IDEOGRAPHS ERA NAME MEIZI;;;; +337F;SQUARE CORPORATION;So;0;L; 682A 5F0F 4F1A 793E;;;;N;SQUARED FOUR IDEOGRAPHS CORPORATION;;;; +3380;SQUARE PA AMPS;So;0;L; 0070 0041;;;;N;SQUARED PA AMPS;;;; +3381;SQUARE NA;So;0;L; 006E 0041;;;;N;SQUARED NA;;;; +3382;SQUARE MU A;So;0;L; 03BC 0041;;;;N;SQUARED MU A;;;; +3383;SQUARE MA;So;0;L; 006D 0041;;;;N;SQUARED MA;;;; +3384;SQUARE KA;So;0;L; 006B 0041;;;;N;SQUARED KA;;;; +3385;SQUARE KB;So;0;L; 004B 0042;;;;N;SQUARED KB;;;; +3386;SQUARE MB;So;0;L; 004D 0042;;;;N;SQUARED MB;;;; +3387;SQUARE GB;So;0;L; 0047 0042;;;;N;SQUARED GB;;;; +3388;SQUARE CAL;So;0;L; 0063 0061 006C;;;;N;SQUARED CAL;;;; +3389;SQUARE KCAL;So;0;L; 006B 0063 0061 006C;;;;N;SQUARED KCAL;;;; +338A;SQUARE PF;So;0;L; 0070 0046;;;;N;SQUARED PF;;;; +338B;SQUARE NF;So;0;L; 006E 0046;;;;N;SQUARED NF;;;; +338C;SQUARE MU F;So;0;L; 03BC 0046;;;;N;SQUARED MU F;;;; +338D;SQUARE MU G;So;0;L; 03BC 0067;;;;N;SQUARED MU G;;;; +338E;SQUARE MG;So;0;L; 006D 0067;;;;N;SQUARED MG;;;; +338F;SQUARE KG;So;0;L; 006B 0067;;;;N;SQUARED KG;;;; +3390;SQUARE HZ;So;0;L; 0048 007A;;;;N;SQUARED HZ;;;; +3391;SQUARE KHZ;So;0;L; 006B 0048 007A;;;;N;SQUARED KHZ;;;; +3392;SQUARE MHZ;So;0;L; 004D 0048 007A;;;;N;SQUARED MHZ;;;; +3393;SQUARE GHZ;So;0;L; 0047 0048 007A;;;;N;SQUARED GHZ;;;; +3394;SQUARE THZ;So;0;L; 0054 0048 007A;;;;N;SQUARED THZ;;;; +3395;SQUARE MU L;So;0;L; 03BC 2113;;;;N;SQUARED MU L;;;; +3396;SQUARE ML;So;0;L; 006D 2113;;;;N;SQUARED ML;;;; +3397;SQUARE DL;So;0;L; 0064 2113;;;;N;SQUARED DL;;;; +3398;SQUARE KL;So;0;L; 006B 2113;;;;N;SQUARED KL;;;; +3399;SQUARE FM;So;0;L; 0066 006D;;;;N;SQUARED FM;;;; +339A;SQUARE NM;So;0;L; 006E 006D;;;;N;SQUARED NM;;;; +339B;SQUARE MU M;So;0;L; 03BC 006D;;;;N;SQUARED MU M;;;; +339C;SQUARE MM;So;0;L; 006D 006D;;;;N;SQUARED MM;;;; +339D;SQUARE CM;So;0;L; 0063 006D;;;;N;SQUARED CM;;;; +339E;SQUARE KM;So;0;L; 006B 006D;;;;N;SQUARED KM;;;; +339F;SQUARE MM SQUARED;So;0;L; 006D 006D 00B2;;;;N;SQUARED MM SQUARED;;;; +33A0;SQUARE CM SQUARED;So;0;L; 0063 006D 00B2;;;;N;SQUARED CM SQUARED;;;; +33A1;SQUARE M SQUARED;So;0;L; 006D 00B2;;;;N;SQUARED M SQUARED;;;; +33A2;SQUARE KM SQUARED;So;0;L; 006B 006D 00B2;;;;N;SQUARED KM SQUARED;;;; +33A3;SQUARE MM CUBED;So;0;L; 006D 006D 00B3;;;;N;SQUARED MM CUBED;;;; +33A4;SQUARE CM CUBED;So;0;L; 0063 006D 00B3;;;;N;SQUARED CM CUBED;;;; +33A5;SQUARE M CUBED;So;0;L; 006D 00B3;;;;N;SQUARED M CUBED;;;; +33A6;SQUARE KM CUBED;So;0;L; 006B 006D 00B3;;;;N;SQUARED KM CUBED;;;; +33A7;SQUARE M OVER S;So;0;L; 006D 2215 0073;;;;N;SQUARED M OVER S;;;; +33A8;SQUARE M OVER S SQUARED;So;0;L; 006D 2215 0073 00B2;;;;N;SQUARED M OVER S SQUARED;;;; +33A9;SQUARE PA;So;0;L; 0050 0061;;;;N;SQUARED PA;;;; +33AA;SQUARE KPA;So;0;L; 006B 0050 0061;;;;N;SQUARED KPA;;;; +33AB;SQUARE MPA;So;0;L; 004D 0050 0061;;;;N;SQUARED MPA;;;; +33AC;SQUARE GPA;So;0;L; 0047 0050 0061;;;;N;SQUARED GPA;;;; +33AD;SQUARE RAD;So;0;L; 0072 0061 0064;;;;N;SQUARED RAD;;;; +33AE;SQUARE RAD OVER S;So;0;L; 0072 0061 0064 2215 0073;;;;N;SQUARED RAD OVER S;;;; +33AF;SQUARE RAD OVER S SQUARED;So;0;L; 0072 0061 0064 2215 0073 00B2;;;;N;SQUARED RAD OVER S SQUARED;;;; +33B0;SQUARE PS;So;0;L; 0070 0073;;;;N;SQUARED PS;;;; +33B1;SQUARE NS;So;0;L; 006E 0073;;;;N;SQUARED NS;;;; +33B2;SQUARE MU S;So;0;L; 03BC 0073;;;;N;SQUARED MU S;;;; +33B3;SQUARE MS;So;0;L; 006D 0073;;;;N;SQUARED MS;;;; +33B4;SQUARE PV;So;0;L; 0070 0056;;;;N;SQUARED PV;;;; +33B5;SQUARE NV;So;0;L; 006E 0056;;;;N;SQUARED NV;;;; +33B6;SQUARE MU V;So;0;L; 03BC 0056;;;;N;SQUARED MU V;;;; +33B7;SQUARE MV;So;0;L; 006D 0056;;;;N;SQUARED MV;;;; +33B8;SQUARE KV;So;0;L; 006B 0056;;;;N;SQUARED KV;;;; +33B9;SQUARE MV MEGA;So;0;L; 004D 0056;;;;N;SQUARED MV MEGA;;;; +33BA;SQUARE PW;So;0;L; 0070 0057;;;;N;SQUARED PW;;;; +33BB;SQUARE NW;So;0;L; 006E 0057;;;;N;SQUARED NW;;;; +33BC;SQUARE MU W;So;0;L; 03BC 0057;;;;N;SQUARED MU W;;;; +33BD;SQUARE MW;So;0;L; 006D 0057;;;;N;SQUARED MW;;;; +33BE;SQUARE KW;So;0;L; 006B 0057;;;;N;SQUARED KW;;;; +33BF;SQUARE MW MEGA;So;0;L; 004D 0057;;;;N;SQUARED MW MEGA;;;; +33C0;SQUARE K OHM;So;0;L; 006B 03A9;;;;N;SQUARED K OHM;;;; +33C1;SQUARE M OHM;So;0;L; 004D 03A9;;;;N;SQUARED M OHM;;;; +33C2;SQUARE AM;So;0;L; 0061 002E 006D 002E;;;;N;SQUARED AM;;;; +33C3;SQUARE BQ;So;0;L; 0042 0071;;;;N;SQUARED BQ;;;; +33C4;SQUARE CC;So;0;L; 0063 0063;;;;N;SQUARED CC;;;; +33C5;SQUARE CD;So;0;L; 0063 0064;;;;N;SQUARED CD;;;; +33C6;SQUARE C OVER KG;So;0;L; 0043 2215 006B 0067;;;;N;SQUARED C OVER KG;;;; +33C7;SQUARE CO;So;0;L; 0043 006F 002E;;;;N;SQUARED CO;;;; +33C8;SQUARE DB;So;0;L; 0064 0042;;;;N;SQUARED DB;;;; +33C9;SQUARE GY;So;0;L; 0047 0079;;;;N;SQUARED GY;;;; +33CA;SQUARE HA;So;0;L; 0068 0061;;;;N;SQUARED HA;;;; +33CB;SQUARE HP;So;0;L; 0048 0050;;;;N;SQUARED HP;;;; +33CC;SQUARE IN;So;0;L; 0069 006E;;;;N;SQUARED IN;;;; +33CD;SQUARE KK;So;0;L; 004B 004B;;;;N;SQUARED KK;;;; +33CE;SQUARE KM CAPITAL;So;0;L; 004B 004D;;;;N;SQUARED KM CAPITAL;;;; +33CF;SQUARE KT;So;0;L; 006B 0074;;;;N;SQUARED KT;;;; +33D0;SQUARE LM;So;0;L; 006C 006D;;;;N;SQUARED LM;;;; +33D1;SQUARE LN;So;0;L; 006C 006E;;;;N;SQUARED LN;;;; +33D2;SQUARE LOG;So;0;L; 006C 006F 0067;;;;N;SQUARED LOG;;;; +33D3;SQUARE LX;So;0;L; 006C 0078;;;;N;SQUARED LX;;;; +33D4;SQUARE MB SMALL;So;0;L; 006D 0062;;;;N;SQUARED MB SMALL;;;; +33D5;SQUARE MIL;So;0;L; 006D 0069 006C;;;;N;SQUARED MIL;;;; +33D6;SQUARE MOL;So;0;L; 006D 006F 006C;;;;N;SQUARED MOL;;;; +33D7;SQUARE PH;So;0;L; 0050 0048;;;;N;SQUARED PH;;;; +33D8;SQUARE PM;So;0;L; 0070 002E 006D 002E;;;;N;SQUARED PM;;;; +33D9;SQUARE PPM;So;0;L; 0050 0050 004D;;;;N;SQUARED PPM;;;; +33DA;SQUARE PR;So;0;L; 0050 0052;;;;N;SQUARED PR;;;; +33DB;SQUARE SR;So;0;L; 0073 0072;;;;N;SQUARED SR;;;; +33DC;SQUARE SV;So;0;L; 0053 0076;;;;N;SQUARED SV;;;; +33DD;SQUARE WB;So;0;L; 0057 0062;;;;N;SQUARED WB;;;; +33DE;SQUARE V OVER M;So;0;ON; 0056 2215 006D;;;;N;;;;; +33DF;SQUARE A OVER M;So;0;ON; 0041 2215 006D;;;;N;;;;; +33E0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE;So;0;L; 0031 65E5;;;;N;;;;; +33E1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO;So;0;L; 0032 65E5;;;;N;;;;; +33E2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE;So;0;L; 0033 65E5;;;;N;;;;; +33E3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR;So;0;L; 0034 65E5;;;;N;;;;; +33E4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE;So;0;L; 0035 65E5;;;;N;;;;; +33E5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX;So;0;L; 0036 65E5;;;;N;;;;; +33E6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN;So;0;L; 0037 65E5;;;;N;;;;; +33E7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT;So;0;L; 0038 65E5;;;;N;;;;; +33E8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE;So;0;L; 0039 65E5;;;;N;;;;; +33E9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN;So;0;L; 0031 0030 65E5;;;;N;;;;; +33EA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN;So;0;L; 0031 0031 65E5;;;;N;;;;; +33EB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE;So;0;L; 0031 0032 65E5;;;;N;;;;; +33EC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN;So;0;L; 0031 0033 65E5;;;;N;;;;; +33ED;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN;So;0;L; 0031 0034 65E5;;;;N;;;;; +33EE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN;So;0;L; 0031 0035 65E5;;;;N;;;;; +33EF;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN;So;0;L; 0031 0036 65E5;;;;N;;;;; +33F0;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN;So;0;L; 0031 0037 65E5;;;;N;;;;; +33F1;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN;So;0;L; 0031 0038 65E5;;;;N;;;;; +33F2;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN;So;0;L; 0031 0039 65E5;;;;N;;;;; +33F3;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY;So;0;L; 0032 0030 65E5;;;;N;;;;; +33F4;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE;So;0;L; 0032 0031 65E5;;;;N;;;;; +33F5;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO;So;0;L; 0032 0032 65E5;;;;N;;;;; +33F6;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE;So;0;L; 0032 0033 65E5;;;;N;;;;; +33F7;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR;So;0;L; 0032 0034 65E5;;;;N;;;;; +33F8;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE;So;0;L; 0032 0035 65E5;;;;N;;;;; +33F9;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX;So;0;L; 0032 0036 65E5;;;;N;;;;; +33FA;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN;So;0;L; 0032 0037 65E5;;;;N;;;;; +33FB;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT;So;0;L; 0032 0038 65E5;;;;N;;;;; +33FC;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE;So;0;L; 0032 0039 65E5;;;;N;;;;; +33FD;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY;So;0;L; 0033 0030 65E5;;;;N;;;;; +33FE;IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE;So;0;L; 0033 0031 65E5;;;;N;;;;; +33FF;SQUARE GAL;So;0;ON; 0067 0061 006C;;;;N;;;;; +3400;;Lo;0;L;;;;;N;;;;; +4DBF;;Lo;0;L;;;;;N;;;;; +4DC0;HEXAGRAM FOR THE CREATIVE HEAVEN;So;0;ON;;;;;N;;;;; +4DC1;HEXAGRAM FOR THE RECEPTIVE EARTH;So;0;ON;;;;;N;;;;; +4DC2;HEXAGRAM FOR DIFFICULTY AT THE BEGINNING;So;0;ON;;;;;N;;;;; +4DC3;HEXAGRAM FOR YOUTHFUL FOLLY;So;0;ON;;;;;N;;;;; +4DC4;HEXAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; +4DC5;HEXAGRAM FOR CONFLICT;So;0;ON;;;;;N;;;;; +4DC6;HEXAGRAM FOR THE ARMY;So;0;ON;;;;;N;;;;; +4DC7;HEXAGRAM FOR HOLDING TOGETHER;So;0;ON;;;;;N;;;;; +4DC8;HEXAGRAM FOR SMALL TAMING;So;0;ON;;;;;N;;;;; +4DC9;HEXAGRAM FOR TREADING;So;0;ON;;;;;N;;;;; +4DCA;HEXAGRAM FOR PEACE;So;0;ON;;;;;N;;;;; +4DCB;HEXAGRAM FOR STANDSTILL;So;0;ON;;;;;N;;;;; +4DCC;HEXAGRAM FOR FELLOWSHIP;So;0;ON;;;;;N;;;;; +4DCD;HEXAGRAM FOR GREAT POSSESSION;So;0;ON;;;;;N;;;;; +4DCE;HEXAGRAM FOR MODESTY;So;0;ON;;;;;N;;;;; +4DCF;HEXAGRAM FOR ENTHUSIASM;So;0;ON;;;;;N;;;;; +4DD0;HEXAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; +4DD1;HEXAGRAM FOR WORK ON THE DECAYED;So;0;ON;;;;;N;;;;; +4DD2;HEXAGRAM FOR APPROACH;So;0;ON;;;;;N;;;;; +4DD3;HEXAGRAM FOR CONTEMPLATION;So;0;ON;;;;;N;;;;; +4DD4;HEXAGRAM FOR BITING THROUGH;So;0;ON;;;;;N;;;;; +4DD5;HEXAGRAM FOR GRACE;So;0;ON;;;;;N;;;;; +4DD6;HEXAGRAM FOR SPLITTING APART;So;0;ON;;;;;N;;;;; +4DD7;HEXAGRAM FOR RETURN;So;0;ON;;;;;N;;;;; +4DD8;HEXAGRAM FOR INNOCENCE;So;0;ON;;;;;N;;;;; +4DD9;HEXAGRAM FOR GREAT TAMING;So;0;ON;;;;;N;;;;; +4DDA;HEXAGRAM FOR MOUTH CORNERS;So;0;ON;;;;;N;;;;; +4DDB;HEXAGRAM FOR GREAT PREPONDERANCE;So;0;ON;;;;;N;;;;; +4DDC;HEXAGRAM FOR THE ABYSMAL WATER;So;0;ON;;;;;N;;;;; +4DDD;HEXAGRAM FOR THE CLINGING FIRE;So;0;ON;;;;;N;;;;; +4DDE;HEXAGRAM FOR INFLUENCE;So;0;ON;;;;;N;;;;; +4DDF;HEXAGRAM FOR DURATION;So;0;ON;;;;;N;;;;; +4DE0;HEXAGRAM FOR RETREAT;So;0;ON;;;;;N;;;;; +4DE1;HEXAGRAM FOR GREAT POWER;So;0;ON;;;;;N;;;;; +4DE2;HEXAGRAM FOR PROGRESS;So;0;ON;;;;;N;;;;; +4DE3;HEXAGRAM FOR DARKENING OF THE LIGHT;So;0;ON;;;;;N;;;;; +4DE4;HEXAGRAM FOR THE FAMILY;So;0;ON;;;;;N;;;;; +4DE5;HEXAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; +4DE6;HEXAGRAM FOR OBSTRUCTION;So;0;ON;;;;;N;;;;; +4DE7;HEXAGRAM FOR DELIVERANCE;So;0;ON;;;;;N;;;;; +4DE8;HEXAGRAM FOR DECREASE;So;0;ON;;;;;N;;;;; +4DE9;HEXAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; +4DEA;HEXAGRAM FOR BREAKTHROUGH;So;0;ON;;;;;N;;;;; +4DEB;HEXAGRAM FOR COMING TO MEET;So;0;ON;;;;;N;;;;; +4DEC;HEXAGRAM FOR GATHERING TOGETHER;So;0;ON;;;;;N;;;;; +4DED;HEXAGRAM FOR PUSHING UPWARD;So;0;ON;;;;;N;;;;; +4DEE;HEXAGRAM FOR OPPRESSION;So;0;ON;;;;;N;;;;; +4DEF;HEXAGRAM FOR THE WELL;So;0;ON;;;;;N;;;;; +4DF0;HEXAGRAM FOR REVOLUTION;So;0;ON;;;;;N;;;;; +4DF1;HEXAGRAM FOR THE CAULDRON;So;0;ON;;;;;N;;;;; +4DF2;HEXAGRAM FOR THE AROUSING THUNDER;So;0;ON;;;;;N;;;;; +4DF3;HEXAGRAM FOR THE KEEPING STILL MOUNTAIN;So;0;ON;;;;;N;;;;; +4DF4;HEXAGRAM FOR DEVELOPMENT;So;0;ON;;;;;N;;;;; +4DF5;HEXAGRAM FOR THE MARRYING MAIDEN;So;0;ON;;;;;N;;;;; +4DF6;HEXAGRAM FOR ABUNDANCE;So;0;ON;;;;;N;;;;; +4DF7;HEXAGRAM FOR THE WANDERER;So;0;ON;;;;;N;;;;; +4DF8;HEXAGRAM FOR THE GENTLE WIND;So;0;ON;;;;;N;;;;; +4DF9;HEXAGRAM FOR THE JOYOUS LAKE;So;0;ON;;;;;N;;;;; +4DFA;HEXAGRAM FOR DISPERSION;So;0;ON;;;;;N;;;;; +4DFB;HEXAGRAM FOR LIMITATION;So;0;ON;;;;;N;;;;; +4DFC;HEXAGRAM FOR INNER TRUTH;So;0;ON;;;;;N;;;;; +4DFD;HEXAGRAM FOR SMALL PREPONDERANCE;So;0;ON;;;;;N;;;;; +4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;; +4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;; +4E00;;Lo;0;L;;;;;N;;;;; +9FFF;;Lo;0;L;;;;;N;;;;; +A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;; +A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;; +A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;; +A003;YI SYLLABLE IP;Lo;0;L;;;;;N;;;;; +A004;YI SYLLABLE IET;Lo;0;L;;;;;N;;;;; +A005;YI SYLLABLE IEX;Lo;0;L;;;;;N;;;;; +A006;YI SYLLABLE IE;Lo;0;L;;;;;N;;;;; +A007;YI SYLLABLE IEP;Lo;0;L;;;;;N;;;;; +A008;YI SYLLABLE AT;Lo;0;L;;;;;N;;;;; +A009;YI SYLLABLE AX;Lo;0;L;;;;;N;;;;; +A00A;YI SYLLABLE A;Lo;0;L;;;;;N;;;;; +A00B;YI SYLLABLE AP;Lo;0;L;;;;;N;;;;; +A00C;YI SYLLABLE UOX;Lo;0;L;;;;;N;;;;; +A00D;YI SYLLABLE UO;Lo;0;L;;;;;N;;;;; +A00E;YI SYLLABLE UOP;Lo;0;L;;;;;N;;;;; +A00F;YI SYLLABLE OT;Lo;0;L;;;;;N;;;;; +A010;YI SYLLABLE OX;Lo;0;L;;;;;N;;;;; +A011;YI SYLLABLE O;Lo;0;L;;;;;N;;;;; +A012;YI SYLLABLE OP;Lo;0;L;;;;;N;;;;; +A013;YI SYLLABLE EX;Lo;0;L;;;;;N;;;;; +A014;YI SYLLABLE E;Lo;0;L;;;;;N;;;;; +A015;YI SYLLABLE WU;Lm;0;L;;;;;N;;;;; +A016;YI SYLLABLE BIT;Lo;0;L;;;;;N;;;;; +A017;YI SYLLABLE BIX;Lo;0;L;;;;;N;;;;; +A018;YI SYLLABLE BI;Lo;0;L;;;;;N;;;;; +A019;YI SYLLABLE BIP;Lo;0;L;;;;;N;;;;; +A01A;YI SYLLABLE BIET;Lo;0;L;;;;;N;;;;; +A01B;YI SYLLABLE BIEX;Lo;0;L;;;;;N;;;;; +A01C;YI SYLLABLE BIE;Lo;0;L;;;;;N;;;;; +A01D;YI SYLLABLE BIEP;Lo;0;L;;;;;N;;;;; +A01E;YI SYLLABLE BAT;Lo;0;L;;;;;N;;;;; +A01F;YI SYLLABLE BAX;Lo;0;L;;;;;N;;;;; +A020;YI SYLLABLE BA;Lo;0;L;;;;;N;;;;; +A021;YI SYLLABLE BAP;Lo;0;L;;;;;N;;;;; +A022;YI SYLLABLE BUOX;Lo;0;L;;;;;N;;;;; +A023;YI SYLLABLE BUO;Lo;0;L;;;;;N;;;;; +A024;YI SYLLABLE BUOP;Lo;0;L;;;;;N;;;;; +A025;YI SYLLABLE BOT;Lo;0;L;;;;;N;;;;; +A026;YI SYLLABLE BOX;Lo;0;L;;;;;N;;;;; +A027;YI SYLLABLE BO;Lo;0;L;;;;;N;;;;; +A028;YI SYLLABLE BOP;Lo;0;L;;;;;N;;;;; +A029;YI SYLLABLE BEX;Lo;0;L;;;;;N;;;;; +A02A;YI SYLLABLE BE;Lo;0;L;;;;;N;;;;; +A02B;YI SYLLABLE BEP;Lo;0;L;;;;;N;;;;; +A02C;YI SYLLABLE BUT;Lo;0;L;;;;;N;;;;; +A02D;YI SYLLABLE BUX;Lo;0;L;;;;;N;;;;; +A02E;YI SYLLABLE BU;Lo;0;L;;;;;N;;;;; +A02F;YI SYLLABLE BUP;Lo;0;L;;;;;N;;;;; +A030;YI SYLLABLE BURX;Lo;0;L;;;;;N;;;;; +A031;YI SYLLABLE BUR;Lo;0;L;;;;;N;;;;; +A032;YI SYLLABLE BYT;Lo;0;L;;;;;N;;;;; +A033;YI SYLLABLE BYX;Lo;0;L;;;;;N;;;;; +A034;YI SYLLABLE BY;Lo;0;L;;;;;N;;;;; +A035;YI SYLLABLE BYP;Lo;0;L;;;;;N;;;;; +A036;YI SYLLABLE BYRX;Lo;0;L;;;;;N;;;;; +A037;YI SYLLABLE BYR;Lo;0;L;;;;;N;;;;; +A038;YI SYLLABLE PIT;Lo;0;L;;;;;N;;;;; +A039;YI SYLLABLE PIX;Lo;0;L;;;;;N;;;;; +A03A;YI SYLLABLE PI;Lo;0;L;;;;;N;;;;; +A03B;YI SYLLABLE PIP;Lo;0;L;;;;;N;;;;; +A03C;YI SYLLABLE PIEX;Lo;0;L;;;;;N;;;;; +A03D;YI SYLLABLE PIE;Lo;0;L;;;;;N;;;;; +A03E;YI SYLLABLE PIEP;Lo;0;L;;;;;N;;;;; +A03F;YI SYLLABLE PAT;Lo;0;L;;;;;N;;;;; +A040;YI SYLLABLE PAX;Lo;0;L;;;;;N;;;;; +A041;YI SYLLABLE PA;Lo;0;L;;;;;N;;;;; +A042;YI SYLLABLE PAP;Lo;0;L;;;;;N;;;;; +A043;YI SYLLABLE PUOX;Lo;0;L;;;;;N;;;;; +A044;YI SYLLABLE PUO;Lo;0;L;;;;;N;;;;; +A045;YI SYLLABLE PUOP;Lo;0;L;;;;;N;;;;; +A046;YI SYLLABLE POT;Lo;0;L;;;;;N;;;;; +A047;YI SYLLABLE POX;Lo;0;L;;;;;N;;;;; +A048;YI SYLLABLE PO;Lo;0;L;;;;;N;;;;; +A049;YI SYLLABLE POP;Lo;0;L;;;;;N;;;;; +A04A;YI SYLLABLE PUT;Lo;0;L;;;;;N;;;;; +A04B;YI SYLLABLE PUX;Lo;0;L;;;;;N;;;;; +A04C;YI SYLLABLE PU;Lo;0;L;;;;;N;;;;; +A04D;YI SYLLABLE PUP;Lo;0;L;;;;;N;;;;; +A04E;YI SYLLABLE PURX;Lo;0;L;;;;;N;;;;; +A04F;YI SYLLABLE PUR;Lo;0;L;;;;;N;;;;; +A050;YI SYLLABLE PYT;Lo;0;L;;;;;N;;;;; +A051;YI SYLLABLE PYX;Lo;0;L;;;;;N;;;;; +A052;YI SYLLABLE PY;Lo;0;L;;;;;N;;;;; +A053;YI SYLLABLE PYP;Lo;0;L;;;;;N;;;;; +A054;YI SYLLABLE PYRX;Lo;0;L;;;;;N;;;;; +A055;YI SYLLABLE PYR;Lo;0;L;;;;;N;;;;; +A056;YI SYLLABLE BBIT;Lo;0;L;;;;;N;;;;; +A057;YI SYLLABLE BBIX;Lo;0;L;;;;;N;;;;; +A058;YI SYLLABLE BBI;Lo;0;L;;;;;N;;;;; +A059;YI SYLLABLE BBIP;Lo;0;L;;;;;N;;;;; +A05A;YI SYLLABLE BBIET;Lo;0;L;;;;;N;;;;; +A05B;YI SYLLABLE BBIEX;Lo;0;L;;;;;N;;;;; +A05C;YI SYLLABLE BBIE;Lo;0;L;;;;;N;;;;; +A05D;YI SYLLABLE BBIEP;Lo;0;L;;;;;N;;;;; +A05E;YI SYLLABLE BBAT;Lo;0;L;;;;;N;;;;; +A05F;YI SYLLABLE BBAX;Lo;0;L;;;;;N;;;;; +A060;YI SYLLABLE BBA;Lo;0;L;;;;;N;;;;; +A061;YI SYLLABLE BBAP;Lo;0;L;;;;;N;;;;; +A062;YI SYLLABLE BBUOX;Lo;0;L;;;;;N;;;;; +A063;YI SYLLABLE BBUO;Lo;0;L;;;;;N;;;;; +A064;YI SYLLABLE BBUOP;Lo;0;L;;;;;N;;;;; +A065;YI SYLLABLE BBOT;Lo;0;L;;;;;N;;;;; +A066;YI SYLLABLE BBOX;Lo;0;L;;;;;N;;;;; +A067;YI SYLLABLE BBO;Lo;0;L;;;;;N;;;;; +A068;YI SYLLABLE BBOP;Lo;0;L;;;;;N;;;;; +A069;YI SYLLABLE BBEX;Lo;0;L;;;;;N;;;;; +A06A;YI SYLLABLE BBE;Lo;0;L;;;;;N;;;;; +A06B;YI SYLLABLE BBEP;Lo;0;L;;;;;N;;;;; +A06C;YI SYLLABLE BBUT;Lo;0;L;;;;;N;;;;; +A06D;YI SYLLABLE BBUX;Lo;0;L;;;;;N;;;;; +A06E;YI SYLLABLE BBU;Lo;0;L;;;;;N;;;;; +A06F;YI SYLLABLE BBUP;Lo;0;L;;;;;N;;;;; +A070;YI SYLLABLE BBURX;Lo;0;L;;;;;N;;;;; +A071;YI SYLLABLE BBUR;Lo;0;L;;;;;N;;;;; +A072;YI SYLLABLE BBYT;Lo;0;L;;;;;N;;;;; +A073;YI SYLLABLE BBYX;Lo;0;L;;;;;N;;;;; +A074;YI SYLLABLE BBY;Lo;0;L;;;;;N;;;;; +A075;YI SYLLABLE BBYP;Lo;0;L;;;;;N;;;;; +A076;YI SYLLABLE NBIT;Lo;0;L;;;;;N;;;;; +A077;YI SYLLABLE NBIX;Lo;0;L;;;;;N;;;;; +A078;YI SYLLABLE NBI;Lo;0;L;;;;;N;;;;; +A079;YI SYLLABLE NBIP;Lo;0;L;;;;;N;;;;; +A07A;YI SYLLABLE NBIEX;Lo;0;L;;;;;N;;;;; +A07B;YI SYLLABLE NBIE;Lo;0;L;;;;;N;;;;; +A07C;YI SYLLABLE NBIEP;Lo;0;L;;;;;N;;;;; +A07D;YI SYLLABLE NBAT;Lo;0;L;;;;;N;;;;; +A07E;YI SYLLABLE NBAX;Lo;0;L;;;;;N;;;;; +A07F;YI SYLLABLE NBA;Lo;0;L;;;;;N;;;;; +A080;YI SYLLABLE NBAP;Lo;0;L;;;;;N;;;;; +A081;YI SYLLABLE NBOT;Lo;0;L;;;;;N;;;;; +A082;YI SYLLABLE NBOX;Lo;0;L;;;;;N;;;;; +A083;YI SYLLABLE NBO;Lo;0;L;;;;;N;;;;; +A084;YI SYLLABLE NBOP;Lo;0;L;;;;;N;;;;; +A085;YI SYLLABLE NBUT;Lo;0;L;;;;;N;;;;; +A086;YI SYLLABLE NBUX;Lo;0;L;;;;;N;;;;; +A087;YI SYLLABLE NBU;Lo;0;L;;;;;N;;;;; +A088;YI SYLLABLE NBUP;Lo;0;L;;;;;N;;;;; +A089;YI SYLLABLE NBURX;Lo;0;L;;;;;N;;;;; +A08A;YI SYLLABLE NBUR;Lo;0;L;;;;;N;;;;; +A08B;YI SYLLABLE NBYT;Lo;0;L;;;;;N;;;;; +A08C;YI SYLLABLE NBYX;Lo;0;L;;;;;N;;;;; +A08D;YI SYLLABLE NBY;Lo;0;L;;;;;N;;;;; +A08E;YI SYLLABLE NBYP;Lo;0;L;;;;;N;;;;; +A08F;YI SYLLABLE NBYRX;Lo;0;L;;;;;N;;;;; +A090;YI SYLLABLE NBYR;Lo;0;L;;;;;N;;;;; +A091;YI SYLLABLE HMIT;Lo;0;L;;;;;N;;;;; +A092;YI SYLLABLE HMIX;Lo;0;L;;;;;N;;;;; +A093;YI SYLLABLE HMI;Lo;0;L;;;;;N;;;;; +A094;YI SYLLABLE HMIP;Lo;0;L;;;;;N;;;;; +A095;YI SYLLABLE HMIEX;Lo;0;L;;;;;N;;;;; +A096;YI SYLLABLE HMIE;Lo;0;L;;;;;N;;;;; +A097;YI SYLLABLE HMIEP;Lo;0;L;;;;;N;;;;; +A098;YI SYLLABLE HMAT;Lo;0;L;;;;;N;;;;; +A099;YI SYLLABLE HMAX;Lo;0;L;;;;;N;;;;; +A09A;YI SYLLABLE HMA;Lo;0;L;;;;;N;;;;; +A09B;YI SYLLABLE HMAP;Lo;0;L;;;;;N;;;;; +A09C;YI SYLLABLE HMUOX;Lo;0;L;;;;;N;;;;; +A09D;YI SYLLABLE HMUO;Lo;0;L;;;;;N;;;;; +A09E;YI SYLLABLE HMUOP;Lo;0;L;;;;;N;;;;; +A09F;YI SYLLABLE HMOT;Lo;0;L;;;;;N;;;;; +A0A0;YI SYLLABLE HMOX;Lo;0;L;;;;;N;;;;; +A0A1;YI SYLLABLE HMO;Lo;0;L;;;;;N;;;;; +A0A2;YI SYLLABLE HMOP;Lo;0;L;;;;;N;;;;; +A0A3;YI SYLLABLE HMUT;Lo;0;L;;;;;N;;;;; +A0A4;YI SYLLABLE HMUX;Lo;0;L;;;;;N;;;;; +A0A5;YI SYLLABLE HMU;Lo;0;L;;;;;N;;;;; +A0A6;YI SYLLABLE HMUP;Lo;0;L;;;;;N;;;;; +A0A7;YI SYLLABLE HMURX;Lo;0;L;;;;;N;;;;; +A0A8;YI SYLLABLE HMUR;Lo;0;L;;;;;N;;;;; +A0A9;YI SYLLABLE HMYX;Lo;0;L;;;;;N;;;;; +A0AA;YI SYLLABLE HMY;Lo;0;L;;;;;N;;;;; +A0AB;YI SYLLABLE HMYP;Lo;0;L;;;;;N;;;;; +A0AC;YI SYLLABLE HMYRX;Lo;0;L;;;;;N;;;;; +A0AD;YI SYLLABLE HMYR;Lo;0;L;;;;;N;;;;; +A0AE;YI SYLLABLE MIT;Lo;0;L;;;;;N;;;;; +A0AF;YI SYLLABLE MIX;Lo;0;L;;;;;N;;;;; +A0B0;YI SYLLABLE MI;Lo;0;L;;;;;N;;;;; +A0B1;YI SYLLABLE MIP;Lo;0;L;;;;;N;;;;; +A0B2;YI SYLLABLE MIEX;Lo;0;L;;;;;N;;;;; +A0B3;YI SYLLABLE MIE;Lo;0;L;;;;;N;;;;; +A0B4;YI SYLLABLE MIEP;Lo;0;L;;;;;N;;;;; +A0B5;YI SYLLABLE MAT;Lo;0;L;;;;;N;;;;; +A0B6;YI SYLLABLE MAX;Lo;0;L;;;;;N;;;;; +A0B7;YI SYLLABLE MA;Lo;0;L;;;;;N;;;;; +A0B8;YI SYLLABLE MAP;Lo;0;L;;;;;N;;;;; +A0B9;YI SYLLABLE MUOT;Lo;0;L;;;;;N;;;;; +A0BA;YI SYLLABLE MUOX;Lo;0;L;;;;;N;;;;; +A0BB;YI SYLLABLE MUO;Lo;0;L;;;;;N;;;;; +A0BC;YI SYLLABLE MUOP;Lo;0;L;;;;;N;;;;; +A0BD;YI SYLLABLE MOT;Lo;0;L;;;;;N;;;;; +A0BE;YI SYLLABLE MOX;Lo;0;L;;;;;N;;;;; +A0BF;YI SYLLABLE MO;Lo;0;L;;;;;N;;;;; +A0C0;YI SYLLABLE MOP;Lo;0;L;;;;;N;;;;; +A0C1;YI SYLLABLE MEX;Lo;0;L;;;;;N;;;;; +A0C2;YI SYLLABLE ME;Lo;0;L;;;;;N;;;;; +A0C3;YI SYLLABLE MUT;Lo;0;L;;;;;N;;;;; +A0C4;YI SYLLABLE MUX;Lo;0;L;;;;;N;;;;; +A0C5;YI SYLLABLE MU;Lo;0;L;;;;;N;;;;; +A0C6;YI SYLLABLE MUP;Lo;0;L;;;;;N;;;;; +A0C7;YI SYLLABLE MURX;Lo;0;L;;;;;N;;;;; +A0C8;YI SYLLABLE MUR;Lo;0;L;;;;;N;;;;; +A0C9;YI SYLLABLE MYT;Lo;0;L;;;;;N;;;;; +A0CA;YI SYLLABLE MYX;Lo;0;L;;;;;N;;;;; +A0CB;YI SYLLABLE MY;Lo;0;L;;;;;N;;;;; +A0CC;YI SYLLABLE MYP;Lo;0;L;;;;;N;;;;; +A0CD;YI SYLLABLE FIT;Lo;0;L;;;;;N;;;;; +A0CE;YI SYLLABLE FIX;Lo;0;L;;;;;N;;;;; +A0CF;YI SYLLABLE FI;Lo;0;L;;;;;N;;;;; +A0D0;YI SYLLABLE FIP;Lo;0;L;;;;;N;;;;; +A0D1;YI SYLLABLE FAT;Lo;0;L;;;;;N;;;;; +A0D2;YI SYLLABLE FAX;Lo;0;L;;;;;N;;;;; +A0D3;YI SYLLABLE FA;Lo;0;L;;;;;N;;;;; +A0D4;YI SYLLABLE FAP;Lo;0;L;;;;;N;;;;; +A0D5;YI SYLLABLE FOX;Lo;0;L;;;;;N;;;;; +A0D6;YI SYLLABLE FO;Lo;0;L;;;;;N;;;;; +A0D7;YI SYLLABLE FOP;Lo;0;L;;;;;N;;;;; +A0D8;YI SYLLABLE FUT;Lo;0;L;;;;;N;;;;; +A0D9;YI SYLLABLE FUX;Lo;0;L;;;;;N;;;;; +A0DA;YI SYLLABLE FU;Lo;0;L;;;;;N;;;;; +A0DB;YI SYLLABLE FUP;Lo;0;L;;;;;N;;;;; +A0DC;YI SYLLABLE FURX;Lo;0;L;;;;;N;;;;; +A0DD;YI SYLLABLE FUR;Lo;0;L;;;;;N;;;;; +A0DE;YI SYLLABLE FYT;Lo;0;L;;;;;N;;;;; +A0DF;YI SYLLABLE FYX;Lo;0;L;;;;;N;;;;; +A0E0;YI SYLLABLE FY;Lo;0;L;;;;;N;;;;; +A0E1;YI SYLLABLE FYP;Lo;0;L;;;;;N;;;;; +A0E2;YI SYLLABLE VIT;Lo;0;L;;;;;N;;;;; +A0E3;YI SYLLABLE VIX;Lo;0;L;;;;;N;;;;; +A0E4;YI SYLLABLE VI;Lo;0;L;;;;;N;;;;; +A0E5;YI SYLLABLE VIP;Lo;0;L;;;;;N;;;;; +A0E6;YI SYLLABLE VIET;Lo;0;L;;;;;N;;;;; +A0E7;YI SYLLABLE VIEX;Lo;0;L;;;;;N;;;;; +A0E8;YI SYLLABLE VIE;Lo;0;L;;;;;N;;;;; +A0E9;YI SYLLABLE VIEP;Lo;0;L;;;;;N;;;;; +A0EA;YI SYLLABLE VAT;Lo;0;L;;;;;N;;;;; +A0EB;YI SYLLABLE VAX;Lo;0;L;;;;;N;;;;; +A0EC;YI SYLLABLE VA;Lo;0;L;;;;;N;;;;; +A0ED;YI SYLLABLE VAP;Lo;0;L;;;;;N;;;;; +A0EE;YI SYLLABLE VOT;Lo;0;L;;;;;N;;;;; +A0EF;YI SYLLABLE VOX;Lo;0;L;;;;;N;;;;; +A0F0;YI SYLLABLE VO;Lo;0;L;;;;;N;;;;; +A0F1;YI SYLLABLE VOP;Lo;0;L;;;;;N;;;;; +A0F2;YI SYLLABLE VEX;Lo;0;L;;;;;N;;;;; +A0F3;YI SYLLABLE VEP;Lo;0;L;;;;;N;;;;; +A0F4;YI SYLLABLE VUT;Lo;0;L;;;;;N;;;;; +A0F5;YI SYLLABLE VUX;Lo;0;L;;;;;N;;;;; +A0F6;YI SYLLABLE VU;Lo;0;L;;;;;N;;;;; +A0F7;YI SYLLABLE VUP;Lo;0;L;;;;;N;;;;; +A0F8;YI SYLLABLE VURX;Lo;0;L;;;;;N;;;;; +A0F9;YI SYLLABLE VUR;Lo;0;L;;;;;N;;;;; +A0FA;YI SYLLABLE VYT;Lo;0;L;;;;;N;;;;; +A0FB;YI SYLLABLE VYX;Lo;0;L;;;;;N;;;;; +A0FC;YI SYLLABLE VY;Lo;0;L;;;;;N;;;;; +A0FD;YI SYLLABLE VYP;Lo;0;L;;;;;N;;;;; +A0FE;YI SYLLABLE VYRX;Lo;0;L;;;;;N;;;;; +A0FF;YI SYLLABLE VYR;Lo;0;L;;;;;N;;;;; +A100;YI SYLLABLE DIT;Lo;0;L;;;;;N;;;;; +A101;YI SYLLABLE DIX;Lo;0;L;;;;;N;;;;; +A102;YI SYLLABLE DI;Lo;0;L;;;;;N;;;;; +A103;YI SYLLABLE DIP;Lo;0;L;;;;;N;;;;; +A104;YI SYLLABLE DIEX;Lo;0;L;;;;;N;;;;; +A105;YI SYLLABLE DIE;Lo;0;L;;;;;N;;;;; +A106;YI SYLLABLE DIEP;Lo;0;L;;;;;N;;;;; +A107;YI SYLLABLE DAT;Lo;0;L;;;;;N;;;;; +A108;YI SYLLABLE DAX;Lo;0;L;;;;;N;;;;; +A109;YI SYLLABLE DA;Lo;0;L;;;;;N;;;;; +A10A;YI SYLLABLE DAP;Lo;0;L;;;;;N;;;;; +A10B;YI SYLLABLE DUOX;Lo;0;L;;;;;N;;;;; +A10C;YI SYLLABLE DUO;Lo;0;L;;;;;N;;;;; +A10D;YI SYLLABLE DOT;Lo;0;L;;;;;N;;;;; +A10E;YI SYLLABLE DOX;Lo;0;L;;;;;N;;;;; +A10F;YI SYLLABLE DO;Lo;0;L;;;;;N;;;;; +A110;YI SYLLABLE DOP;Lo;0;L;;;;;N;;;;; +A111;YI SYLLABLE DEX;Lo;0;L;;;;;N;;;;; +A112;YI SYLLABLE DE;Lo;0;L;;;;;N;;;;; +A113;YI SYLLABLE DEP;Lo;0;L;;;;;N;;;;; +A114;YI SYLLABLE DUT;Lo;0;L;;;;;N;;;;; +A115;YI SYLLABLE DUX;Lo;0;L;;;;;N;;;;; +A116;YI SYLLABLE DU;Lo;0;L;;;;;N;;;;; +A117;YI SYLLABLE DUP;Lo;0;L;;;;;N;;;;; +A118;YI SYLLABLE DURX;Lo;0;L;;;;;N;;;;; +A119;YI SYLLABLE DUR;Lo;0;L;;;;;N;;;;; +A11A;YI SYLLABLE TIT;Lo;0;L;;;;;N;;;;; +A11B;YI SYLLABLE TIX;Lo;0;L;;;;;N;;;;; +A11C;YI SYLLABLE TI;Lo;0;L;;;;;N;;;;; +A11D;YI SYLLABLE TIP;Lo;0;L;;;;;N;;;;; +A11E;YI SYLLABLE TIEX;Lo;0;L;;;;;N;;;;; +A11F;YI SYLLABLE TIE;Lo;0;L;;;;;N;;;;; +A120;YI SYLLABLE TIEP;Lo;0;L;;;;;N;;;;; +A121;YI SYLLABLE TAT;Lo;0;L;;;;;N;;;;; +A122;YI SYLLABLE TAX;Lo;0;L;;;;;N;;;;; +A123;YI SYLLABLE TA;Lo;0;L;;;;;N;;;;; +A124;YI SYLLABLE TAP;Lo;0;L;;;;;N;;;;; +A125;YI SYLLABLE TUOT;Lo;0;L;;;;;N;;;;; +A126;YI SYLLABLE TUOX;Lo;0;L;;;;;N;;;;; +A127;YI SYLLABLE TUO;Lo;0;L;;;;;N;;;;; +A128;YI SYLLABLE TUOP;Lo;0;L;;;;;N;;;;; +A129;YI SYLLABLE TOT;Lo;0;L;;;;;N;;;;; +A12A;YI SYLLABLE TOX;Lo;0;L;;;;;N;;;;; +A12B;YI SYLLABLE TO;Lo;0;L;;;;;N;;;;; +A12C;YI SYLLABLE TOP;Lo;0;L;;;;;N;;;;; +A12D;YI SYLLABLE TEX;Lo;0;L;;;;;N;;;;; +A12E;YI SYLLABLE TE;Lo;0;L;;;;;N;;;;; +A12F;YI SYLLABLE TEP;Lo;0;L;;;;;N;;;;; +A130;YI SYLLABLE TUT;Lo;0;L;;;;;N;;;;; +A131;YI SYLLABLE TUX;Lo;0;L;;;;;N;;;;; +A132;YI SYLLABLE TU;Lo;0;L;;;;;N;;;;; +A133;YI SYLLABLE TUP;Lo;0;L;;;;;N;;;;; +A134;YI SYLLABLE TURX;Lo;0;L;;;;;N;;;;; +A135;YI SYLLABLE TUR;Lo;0;L;;;;;N;;;;; +A136;YI SYLLABLE DDIT;Lo;0;L;;;;;N;;;;; +A137;YI SYLLABLE DDIX;Lo;0;L;;;;;N;;;;; +A138;YI SYLLABLE DDI;Lo;0;L;;;;;N;;;;; +A139;YI SYLLABLE DDIP;Lo;0;L;;;;;N;;;;; +A13A;YI SYLLABLE DDIEX;Lo;0;L;;;;;N;;;;; +A13B;YI SYLLABLE DDIE;Lo;0;L;;;;;N;;;;; +A13C;YI SYLLABLE DDIEP;Lo;0;L;;;;;N;;;;; +A13D;YI SYLLABLE DDAT;Lo;0;L;;;;;N;;;;; +A13E;YI SYLLABLE DDAX;Lo;0;L;;;;;N;;;;; +A13F;YI SYLLABLE DDA;Lo;0;L;;;;;N;;;;; +A140;YI SYLLABLE DDAP;Lo;0;L;;;;;N;;;;; +A141;YI SYLLABLE DDUOX;Lo;0;L;;;;;N;;;;; +A142;YI SYLLABLE DDUO;Lo;0;L;;;;;N;;;;; +A143;YI SYLLABLE DDUOP;Lo;0;L;;;;;N;;;;; +A144;YI SYLLABLE DDOT;Lo;0;L;;;;;N;;;;; +A145;YI SYLLABLE DDOX;Lo;0;L;;;;;N;;;;; +A146;YI SYLLABLE DDO;Lo;0;L;;;;;N;;;;; +A147;YI SYLLABLE DDOP;Lo;0;L;;;;;N;;;;; +A148;YI SYLLABLE DDEX;Lo;0;L;;;;;N;;;;; +A149;YI SYLLABLE DDE;Lo;0;L;;;;;N;;;;; +A14A;YI SYLLABLE DDEP;Lo;0;L;;;;;N;;;;; +A14B;YI SYLLABLE DDUT;Lo;0;L;;;;;N;;;;; +A14C;YI SYLLABLE DDUX;Lo;0;L;;;;;N;;;;; +A14D;YI SYLLABLE DDU;Lo;0;L;;;;;N;;;;; +A14E;YI SYLLABLE DDUP;Lo;0;L;;;;;N;;;;; +A14F;YI SYLLABLE DDURX;Lo;0;L;;;;;N;;;;; +A150;YI SYLLABLE DDUR;Lo;0;L;;;;;N;;;;; +A151;YI SYLLABLE NDIT;Lo;0;L;;;;;N;;;;; +A152;YI SYLLABLE NDIX;Lo;0;L;;;;;N;;;;; +A153;YI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; +A154;YI SYLLABLE NDIP;Lo;0;L;;;;;N;;;;; +A155;YI SYLLABLE NDIEX;Lo;0;L;;;;;N;;;;; +A156;YI SYLLABLE NDIE;Lo;0;L;;;;;N;;;;; +A157;YI SYLLABLE NDAT;Lo;0;L;;;;;N;;;;; +A158;YI SYLLABLE NDAX;Lo;0;L;;;;;N;;;;; +A159;YI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; +A15A;YI SYLLABLE NDAP;Lo;0;L;;;;;N;;;;; +A15B;YI SYLLABLE NDOT;Lo;0;L;;;;;N;;;;; +A15C;YI SYLLABLE NDOX;Lo;0;L;;;;;N;;;;; +A15D;YI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; +A15E;YI SYLLABLE NDOP;Lo;0;L;;;;;N;;;;; +A15F;YI SYLLABLE NDEX;Lo;0;L;;;;;N;;;;; +A160;YI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; +A161;YI SYLLABLE NDEP;Lo;0;L;;;;;N;;;;; +A162;YI SYLLABLE NDUT;Lo;0;L;;;;;N;;;;; +A163;YI SYLLABLE NDUX;Lo;0;L;;;;;N;;;;; +A164;YI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; +A165;YI SYLLABLE NDUP;Lo;0;L;;;;;N;;;;; +A166;YI SYLLABLE NDURX;Lo;0;L;;;;;N;;;;; +A167;YI SYLLABLE NDUR;Lo;0;L;;;;;N;;;;; +A168;YI SYLLABLE HNIT;Lo;0;L;;;;;N;;;;; +A169;YI SYLLABLE HNIX;Lo;0;L;;;;;N;;;;; +A16A;YI SYLLABLE HNI;Lo;0;L;;;;;N;;;;; +A16B;YI SYLLABLE HNIP;Lo;0;L;;;;;N;;;;; +A16C;YI SYLLABLE HNIET;Lo;0;L;;;;;N;;;;; +A16D;YI SYLLABLE HNIEX;Lo;0;L;;;;;N;;;;; +A16E;YI SYLLABLE HNIE;Lo;0;L;;;;;N;;;;; +A16F;YI SYLLABLE HNIEP;Lo;0;L;;;;;N;;;;; +A170;YI SYLLABLE HNAT;Lo;0;L;;;;;N;;;;; +A171;YI SYLLABLE HNAX;Lo;0;L;;;;;N;;;;; +A172;YI SYLLABLE HNA;Lo;0;L;;;;;N;;;;; +A173;YI SYLLABLE HNAP;Lo;0;L;;;;;N;;;;; +A174;YI SYLLABLE HNUOX;Lo;0;L;;;;;N;;;;; +A175;YI SYLLABLE HNUO;Lo;0;L;;;;;N;;;;; +A176;YI SYLLABLE HNOT;Lo;0;L;;;;;N;;;;; +A177;YI SYLLABLE HNOX;Lo;0;L;;;;;N;;;;; +A178;YI SYLLABLE HNOP;Lo;0;L;;;;;N;;;;; +A179;YI SYLLABLE HNEX;Lo;0;L;;;;;N;;;;; +A17A;YI SYLLABLE HNE;Lo;0;L;;;;;N;;;;; +A17B;YI SYLLABLE HNEP;Lo;0;L;;;;;N;;;;; +A17C;YI SYLLABLE HNUT;Lo;0;L;;;;;N;;;;; +A17D;YI SYLLABLE NIT;Lo;0;L;;;;;N;;;;; +A17E;YI SYLLABLE NIX;Lo;0;L;;;;;N;;;;; +A17F;YI SYLLABLE NI;Lo;0;L;;;;;N;;;;; +A180;YI SYLLABLE NIP;Lo;0;L;;;;;N;;;;; +A181;YI SYLLABLE NIEX;Lo;0;L;;;;;N;;;;; +A182;YI SYLLABLE NIE;Lo;0;L;;;;;N;;;;; +A183;YI SYLLABLE NIEP;Lo;0;L;;;;;N;;;;; +A184;YI SYLLABLE NAX;Lo;0;L;;;;;N;;;;; +A185;YI SYLLABLE NA;Lo;0;L;;;;;N;;;;; +A186;YI SYLLABLE NAP;Lo;0;L;;;;;N;;;;; +A187;YI SYLLABLE NUOX;Lo;0;L;;;;;N;;;;; +A188;YI SYLLABLE NUO;Lo;0;L;;;;;N;;;;; +A189;YI SYLLABLE NUOP;Lo;0;L;;;;;N;;;;; +A18A;YI SYLLABLE NOT;Lo;0;L;;;;;N;;;;; +A18B;YI SYLLABLE NOX;Lo;0;L;;;;;N;;;;; +A18C;YI SYLLABLE NO;Lo;0;L;;;;;N;;;;; +A18D;YI SYLLABLE NOP;Lo;0;L;;;;;N;;;;; +A18E;YI SYLLABLE NEX;Lo;0;L;;;;;N;;;;; +A18F;YI SYLLABLE NE;Lo;0;L;;;;;N;;;;; +A190;YI SYLLABLE NEP;Lo;0;L;;;;;N;;;;; +A191;YI SYLLABLE NUT;Lo;0;L;;;;;N;;;;; +A192;YI SYLLABLE NUX;Lo;0;L;;;;;N;;;;; +A193;YI SYLLABLE NU;Lo;0;L;;;;;N;;;;; +A194;YI SYLLABLE NUP;Lo;0;L;;;;;N;;;;; +A195;YI SYLLABLE NURX;Lo;0;L;;;;;N;;;;; +A196;YI SYLLABLE NUR;Lo;0;L;;;;;N;;;;; +A197;YI SYLLABLE HLIT;Lo;0;L;;;;;N;;;;; +A198;YI SYLLABLE HLIX;Lo;0;L;;;;;N;;;;; +A199;YI SYLLABLE HLI;Lo;0;L;;;;;N;;;;; +A19A;YI SYLLABLE HLIP;Lo;0;L;;;;;N;;;;; +A19B;YI SYLLABLE HLIEX;Lo;0;L;;;;;N;;;;; +A19C;YI SYLLABLE HLIE;Lo;0;L;;;;;N;;;;; +A19D;YI SYLLABLE HLIEP;Lo;0;L;;;;;N;;;;; +A19E;YI SYLLABLE HLAT;Lo;0;L;;;;;N;;;;; +A19F;YI SYLLABLE HLAX;Lo;0;L;;;;;N;;;;; +A1A0;YI SYLLABLE HLA;Lo;0;L;;;;;N;;;;; +A1A1;YI SYLLABLE HLAP;Lo;0;L;;;;;N;;;;; +A1A2;YI SYLLABLE HLUOX;Lo;0;L;;;;;N;;;;; +A1A3;YI SYLLABLE HLUO;Lo;0;L;;;;;N;;;;; +A1A4;YI SYLLABLE HLUOP;Lo;0;L;;;;;N;;;;; +A1A5;YI SYLLABLE HLOX;Lo;0;L;;;;;N;;;;; +A1A6;YI SYLLABLE HLO;Lo;0;L;;;;;N;;;;; +A1A7;YI SYLLABLE HLOP;Lo;0;L;;;;;N;;;;; +A1A8;YI SYLLABLE HLEX;Lo;0;L;;;;;N;;;;; +A1A9;YI SYLLABLE HLE;Lo;0;L;;;;;N;;;;; +A1AA;YI SYLLABLE HLEP;Lo;0;L;;;;;N;;;;; +A1AB;YI SYLLABLE HLUT;Lo;0;L;;;;;N;;;;; +A1AC;YI SYLLABLE HLUX;Lo;0;L;;;;;N;;;;; +A1AD;YI SYLLABLE HLU;Lo;0;L;;;;;N;;;;; +A1AE;YI SYLLABLE HLUP;Lo;0;L;;;;;N;;;;; +A1AF;YI SYLLABLE HLURX;Lo;0;L;;;;;N;;;;; +A1B0;YI SYLLABLE HLUR;Lo;0;L;;;;;N;;;;; +A1B1;YI SYLLABLE HLYT;Lo;0;L;;;;;N;;;;; +A1B2;YI SYLLABLE HLYX;Lo;0;L;;;;;N;;;;; +A1B3;YI SYLLABLE HLY;Lo;0;L;;;;;N;;;;; +A1B4;YI SYLLABLE HLYP;Lo;0;L;;;;;N;;;;; +A1B5;YI SYLLABLE HLYRX;Lo;0;L;;;;;N;;;;; +A1B6;YI SYLLABLE HLYR;Lo;0;L;;;;;N;;;;; +A1B7;YI SYLLABLE LIT;Lo;0;L;;;;;N;;;;; +A1B8;YI SYLLABLE LIX;Lo;0;L;;;;;N;;;;; +A1B9;YI SYLLABLE LI;Lo;0;L;;;;;N;;;;; +A1BA;YI SYLLABLE LIP;Lo;0;L;;;;;N;;;;; +A1BB;YI SYLLABLE LIET;Lo;0;L;;;;;N;;;;; +A1BC;YI SYLLABLE LIEX;Lo;0;L;;;;;N;;;;; +A1BD;YI SYLLABLE LIE;Lo;0;L;;;;;N;;;;; +A1BE;YI SYLLABLE LIEP;Lo;0;L;;;;;N;;;;; +A1BF;YI SYLLABLE LAT;Lo;0;L;;;;;N;;;;; +A1C0;YI SYLLABLE LAX;Lo;0;L;;;;;N;;;;; +A1C1;YI SYLLABLE LA;Lo;0;L;;;;;N;;;;; +A1C2;YI SYLLABLE LAP;Lo;0;L;;;;;N;;;;; +A1C3;YI SYLLABLE LUOT;Lo;0;L;;;;;N;;;;; +A1C4;YI SYLLABLE LUOX;Lo;0;L;;;;;N;;;;; +A1C5;YI SYLLABLE LUO;Lo;0;L;;;;;N;;;;; +A1C6;YI SYLLABLE LUOP;Lo;0;L;;;;;N;;;;; +A1C7;YI SYLLABLE LOT;Lo;0;L;;;;;N;;;;; +A1C8;YI SYLLABLE LOX;Lo;0;L;;;;;N;;;;; +A1C9;YI SYLLABLE LO;Lo;0;L;;;;;N;;;;; +A1CA;YI SYLLABLE LOP;Lo;0;L;;;;;N;;;;; +A1CB;YI SYLLABLE LEX;Lo;0;L;;;;;N;;;;; +A1CC;YI SYLLABLE LE;Lo;0;L;;;;;N;;;;; +A1CD;YI SYLLABLE LEP;Lo;0;L;;;;;N;;;;; +A1CE;YI SYLLABLE LUT;Lo;0;L;;;;;N;;;;; +A1CF;YI SYLLABLE LUX;Lo;0;L;;;;;N;;;;; +A1D0;YI SYLLABLE LU;Lo;0;L;;;;;N;;;;; +A1D1;YI SYLLABLE LUP;Lo;0;L;;;;;N;;;;; +A1D2;YI SYLLABLE LURX;Lo;0;L;;;;;N;;;;; +A1D3;YI SYLLABLE LUR;Lo;0;L;;;;;N;;;;; +A1D4;YI SYLLABLE LYT;Lo;0;L;;;;;N;;;;; +A1D5;YI SYLLABLE LYX;Lo;0;L;;;;;N;;;;; +A1D6;YI SYLLABLE LY;Lo;0;L;;;;;N;;;;; +A1D7;YI SYLLABLE LYP;Lo;0;L;;;;;N;;;;; +A1D8;YI SYLLABLE LYRX;Lo;0;L;;;;;N;;;;; +A1D9;YI SYLLABLE LYR;Lo;0;L;;;;;N;;;;; +A1DA;YI SYLLABLE GIT;Lo;0;L;;;;;N;;;;; +A1DB;YI SYLLABLE GIX;Lo;0;L;;;;;N;;;;; +A1DC;YI SYLLABLE GI;Lo;0;L;;;;;N;;;;; +A1DD;YI SYLLABLE GIP;Lo;0;L;;;;;N;;;;; +A1DE;YI SYLLABLE GIET;Lo;0;L;;;;;N;;;;; +A1DF;YI SYLLABLE GIEX;Lo;0;L;;;;;N;;;;; +A1E0;YI SYLLABLE GIE;Lo;0;L;;;;;N;;;;; +A1E1;YI SYLLABLE GIEP;Lo;0;L;;;;;N;;;;; +A1E2;YI SYLLABLE GAT;Lo;0;L;;;;;N;;;;; +A1E3;YI SYLLABLE GAX;Lo;0;L;;;;;N;;;;; +A1E4;YI SYLLABLE GA;Lo;0;L;;;;;N;;;;; +A1E5;YI SYLLABLE GAP;Lo;0;L;;;;;N;;;;; +A1E6;YI SYLLABLE GUOT;Lo;0;L;;;;;N;;;;; +A1E7;YI SYLLABLE GUOX;Lo;0;L;;;;;N;;;;; +A1E8;YI SYLLABLE GUO;Lo;0;L;;;;;N;;;;; +A1E9;YI SYLLABLE GUOP;Lo;0;L;;;;;N;;;;; +A1EA;YI SYLLABLE GOT;Lo;0;L;;;;;N;;;;; +A1EB;YI SYLLABLE GOX;Lo;0;L;;;;;N;;;;; +A1EC;YI SYLLABLE GO;Lo;0;L;;;;;N;;;;; +A1ED;YI SYLLABLE GOP;Lo;0;L;;;;;N;;;;; +A1EE;YI SYLLABLE GET;Lo;0;L;;;;;N;;;;; +A1EF;YI SYLLABLE GEX;Lo;0;L;;;;;N;;;;; +A1F0;YI SYLLABLE GE;Lo;0;L;;;;;N;;;;; +A1F1;YI SYLLABLE GEP;Lo;0;L;;;;;N;;;;; +A1F2;YI SYLLABLE GUT;Lo;0;L;;;;;N;;;;; +A1F3;YI SYLLABLE GUX;Lo;0;L;;;;;N;;;;; +A1F4;YI SYLLABLE GU;Lo;0;L;;;;;N;;;;; +A1F5;YI SYLLABLE GUP;Lo;0;L;;;;;N;;;;; +A1F6;YI SYLLABLE GURX;Lo;0;L;;;;;N;;;;; +A1F7;YI SYLLABLE GUR;Lo;0;L;;;;;N;;;;; +A1F8;YI SYLLABLE KIT;Lo;0;L;;;;;N;;;;; +A1F9;YI SYLLABLE KIX;Lo;0;L;;;;;N;;;;; +A1FA;YI SYLLABLE KI;Lo;0;L;;;;;N;;;;; +A1FB;YI SYLLABLE KIP;Lo;0;L;;;;;N;;;;; +A1FC;YI SYLLABLE KIEX;Lo;0;L;;;;;N;;;;; +A1FD;YI SYLLABLE KIE;Lo;0;L;;;;;N;;;;; +A1FE;YI SYLLABLE KIEP;Lo;0;L;;;;;N;;;;; +A1FF;YI SYLLABLE KAT;Lo;0;L;;;;;N;;;;; +A200;YI SYLLABLE KAX;Lo;0;L;;;;;N;;;;; +A201;YI SYLLABLE KA;Lo;0;L;;;;;N;;;;; +A202;YI SYLLABLE KAP;Lo;0;L;;;;;N;;;;; +A203;YI SYLLABLE KUOX;Lo;0;L;;;;;N;;;;; +A204;YI SYLLABLE KUO;Lo;0;L;;;;;N;;;;; +A205;YI SYLLABLE KUOP;Lo;0;L;;;;;N;;;;; +A206;YI SYLLABLE KOT;Lo;0;L;;;;;N;;;;; +A207;YI SYLLABLE KOX;Lo;0;L;;;;;N;;;;; +A208;YI SYLLABLE KO;Lo;0;L;;;;;N;;;;; +A209;YI SYLLABLE KOP;Lo;0;L;;;;;N;;;;; +A20A;YI SYLLABLE KET;Lo;0;L;;;;;N;;;;; +A20B;YI SYLLABLE KEX;Lo;0;L;;;;;N;;;;; +A20C;YI SYLLABLE KE;Lo;0;L;;;;;N;;;;; +A20D;YI SYLLABLE KEP;Lo;0;L;;;;;N;;;;; +A20E;YI SYLLABLE KUT;Lo;0;L;;;;;N;;;;; +A20F;YI SYLLABLE KUX;Lo;0;L;;;;;N;;;;; +A210;YI SYLLABLE KU;Lo;0;L;;;;;N;;;;; +A211;YI SYLLABLE KUP;Lo;0;L;;;;;N;;;;; +A212;YI SYLLABLE KURX;Lo;0;L;;;;;N;;;;; +A213;YI SYLLABLE KUR;Lo;0;L;;;;;N;;;;; +A214;YI SYLLABLE GGIT;Lo;0;L;;;;;N;;;;; +A215;YI SYLLABLE GGIX;Lo;0;L;;;;;N;;;;; +A216;YI SYLLABLE GGI;Lo;0;L;;;;;N;;;;; +A217;YI SYLLABLE GGIEX;Lo;0;L;;;;;N;;;;; +A218;YI SYLLABLE GGIE;Lo;0;L;;;;;N;;;;; +A219;YI SYLLABLE GGIEP;Lo;0;L;;;;;N;;;;; +A21A;YI SYLLABLE GGAT;Lo;0;L;;;;;N;;;;; +A21B;YI SYLLABLE GGAX;Lo;0;L;;;;;N;;;;; +A21C;YI SYLLABLE GGA;Lo;0;L;;;;;N;;;;; +A21D;YI SYLLABLE GGAP;Lo;0;L;;;;;N;;;;; +A21E;YI SYLLABLE GGUOT;Lo;0;L;;;;;N;;;;; +A21F;YI SYLLABLE GGUOX;Lo;0;L;;;;;N;;;;; +A220;YI SYLLABLE GGUO;Lo;0;L;;;;;N;;;;; +A221;YI SYLLABLE GGUOP;Lo;0;L;;;;;N;;;;; +A222;YI SYLLABLE GGOT;Lo;0;L;;;;;N;;;;; +A223;YI SYLLABLE GGOX;Lo;0;L;;;;;N;;;;; +A224;YI SYLLABLE GGO;Lo;0;L;;;;;N;;;;; +A225;YI SYLLABLE GGOP;Lo;0;L;;;;;N;;;;; +A226;YI SYLLABLE GGET;Lo;0;L;;;;;N;;;;; +A227;YI SYLLABLE GGEX;Lo;0;L;;;;;N;;;;; +A228;YI SYLLABLE GGE;Lo;0;L;;;;;N;;;;; +A229;YI SYLLABLE GGEP;Lo;0;L;;;;;N;;;;; +A22A;YI SYLLABLE GGUT;Lo;0;L;;;;;N;;;;; +A22B;YI SYLLABLE GGUX;Lo;0;L;;;;;N;;;;; +A22C;YI SYLLABLE GGU;Lo;0;L;;;;;N;;;;; +A22D;YI SYLLABLE GGUP;Lo;0;L;;;;;N;;;;; +A22E;YI SYLLABLE GGURX;Lo;0;L;;;;;N;;;;; +A22F;YI SYLLABLE GGUR;Lo;0;L;;;;;N;;;;; +A230;YI SYLLABLE MGIEX;Lo;0;L;;;;;N;;;;; +A231;YI SYLLABLE MGIE;Lo;0;L;;;;;N;;;;; +A232;YI SYLLABLE MGAT;Lo;0;L;;;;;N;;;;; +A233;YI SYLLABLE MGAX;Lo;0;L;;;;;N;;;;; +A234;YI SYLLABLE MGA;Lo;0;L;;;;;N;;;;; +A235;YI SYLLABLE MGAP;Lo;0;L;;;;;N;;;;; +A236;YI SYLLABLE MGUOX;Lo;0;L;;;;;N;;;;; +A237;YI SYLLABLE MGUO;Lo;0;L;;;;;N;;;;; +A238;YI SYLLABLE MGUOP;Lo;0;L;;;;;N;;;;; +A239;YI SYLLABLE MGOT;Lo;0;L;;;;;N;;;;; +A23A;YI SYLLABLE MGOX;Lo;0;L;;;;;N;;;;; +A23B;YI SYLLABLE MGO;Lo;0;L;;;;;N;;;;; +A23C;YI SYLLABLE MGOP;Lo;0;L;;;;;N;;;;; +A23D;YI SYLLABLE MGEX;Lo;0;L;;;;;N;;;;; +A23E;YI SYLLABLE MGE;Lo;0;L;;;;;N;;;;; +A23F;YI SYLLABLE MGEP;Lo;0;L;;;;;N;;;;; +A240;YI SYLLABLE MGUT;Lo;0;L;;;;;N;;;;; +A241;YI SYLLABLE MGUX;Lo;0;L;;;;;N;;;;; +A242;YI SYLLABLE MGU;Lo;0;L;;;;;N;;;;; +A243;YI SYLLABLE MGUP;Lo;0;L;;;;;N;;;;; +A244;YI SYLLABLE MGURX;Lo;0;L;;;;;N;;;;; +A245;YI SYLLABLE MGUR;Lo;0;L;;;;;N;;;;; +A246;YI SYLLABLE HXIT;Lo;0;L;;;;;N;;;;; +A247;YI SYLLABLE HXIX;Lo;0;L;;;;;N;;;;; +A248;YI SYLLABLE HXI;Lo;0;L;;;;;N;;;;; +A249;YI SYLLABLE HXIP;Lo;0;L;;;;;N;;;;; +A24A;YI SYLLABLE HXIET;Lo;0;L;;;;;N;;;;; +A24B;YI SYLLABLE HXIEX;Lo;0;L;;;;;N;;;;; +A24C;YI SYLLABLE HXIE;Lo;0;L;;;;;N;;;;; +A24D;YI SYLLABLE HXIEP;Lo;0;L;;;;;N;;;;; +A24E;YI SYLLABLE HXAT;Lo;0;L;;;;;N;;;;; +A24F;YI SYLLABLE HXAX;Lo;0;L;;;;;N;;;;; +A250;YI SYLLABLE HXA;Lo;0;L;;;;;N;;;;; +A251;YI SYLLABLE HXAP;Lo;0;L;;;;;N;;;;; +A252;YI SYLLABLE HXUOT;Lo;0;L;;;;;N;;;;; +A253;YI SYLLABLE HXUOX;Lo;0;L;;;;;N;;;;; +A254;YI SYLLABLE HXUO;Lo;0;L;;;;;N;;;;; +A255;YI SYLLABLE HXUOP;Lo;0;L;;;;;N;;;;; +A256;YI SYLLABLE HXOT;Lo;0;L;;;;;N;;;;; +A257;YI SYLLABLE HXOX;Lo;0;L;;;;;N;;;;; +A258;YI SYLLABLE HXO;Lo;0;L;;;;;N;;;;; +A259;YI SYLLABLE HXOP;Lo;0;L;;;;;N;;;;; +A25A;YI SYLLABLE HXEX;Lo;0;L;;;;;N;;;;; +A25B;YI SYLLABLE HXE;Lo;0;L;;;;;N;;;;; +A25C;YI SYLLABLE HXEP;Lo;0;L;;;;;N;;;;; +A25D;YI SYLLABLE NGIEX;Lo;0;L;;;;;N;;;;; +A25E;YI SYLLABLE NGIE;Lo;0;L;;;;;N;;;;; +A25F;YI SYLLABLE NGIEP;Lo;0;L;;;;;N;;;;; +A260;YI SYLLABLE NGAT;Lo;0;L;;;;;N;;;;; +A261;YI SYLLABLE NGAX;Lo;0;L;;;;;N;;;;; +A262;YI SYLLABLE NGA;Lo;0;L;;;;;N;;;;; +A263;YI SYLLABLE NGAP;Lo;0;L;;;;;N;;;;; +A264;YI SYLLABLE NGUOT;Lo;0;L;;;;;N;;;;; +A265;YI SYLLABLE NGUOX;Lo;0;L;;;;;N;;;;; +A266;YI SYLLABLE NGUO;Lo;0;L;;;;;N;;;;; +A267;YI SYLLABLE NGOT;Lo;0;L;;;;;N;;;;; +A268;YI SYLLABLE NGOX;Lo;0;L;;;;;N;;;;; +A269;YI SYLLABLE NGO;Lo;0;L;;;;;N;;;;; +A26A;YI SYLLABLE NGOP;Lo;0;L;;;;;N;;;;; +A26B;YI SYLLABLE NGEX;Lo;0;L;;;;;N;;;;; +A26C;YI SYLLABLE NGE;Lo;0;L;;;;;N;;;;; +A26D;YI SYLLABLE NGEP;Lo;0;L;;;;;N;;;;; +A26E;YI SYLLABLE HIT;Lo;0;L;;;;;N;;;;; +A26F;YI SYLLABLE HIEX;Lo;0;L;;;;;N;;;;; +A270;YI SYLLABLE HIE;Lo;0;L;;;;;N;;;;; +A271;YI SYLLABLE HAT;Lo;0;L;;;;;N;;;;; +A272;YI SYLLABLE HAX;Lo;0;L;;;;;N;;;;; +A273;YI SYLLABLE HA;Lo;0;L;;;;;N;;;;; +A274;YI SYLLABLE HAP;Lo;0;L;;;;;N;;;;; +A275;YI SYLLABLE HUOT;Lo;0;L;;;;;N;;;;; +A276;YI SYLLABLE HUOX;Lo;0;L;;;;;N;;;;; +A277;YI SYLLABLE HUO;Lo;0;L;;;;;N;;;;; +A278;YI SYLLABLE HUOP;Lo;0;L;;;;;N;;;;; +A279;YI SYLLABLE HOT;Lo;0;L;;;;;N;;;;; +A27A;YI SYLLABLE HOX;Lo;0;L;;;;;N;;;;; +A27B;YI SYLLABLE HO;Lo;0;L;;;;;N;;;;; +A27C;YI SYLLABLE HOP;Lo;0;L;;;;;N;;;;; +A27D;YI SYLLABLE HEX;Lo;0;L;;;;;N;;;;; +A27E;YI SYLLABLE HE;Lo;0;L;;;;;N;;;;; +A27F;YI SYLLABLE HEP;Lo;0;L;;;;;N;;;;; +A280;YI SYLLABLE WAT;Lo;0;L;;;;;N;;;;; +A281;YI SYLLABLE WAX;Lo;0;L;;;;;N;;;;; +A282;YI SYLLABLE WA;Lo;0;L;;;;;N;;;;; +A283;YI SYLLABLE WAP;Lo;0;L;;;;;N;;;;; +A284;YI SYLLABLE WUOX;Lo;0;L;;;;;N;;;;; +A285;YI SYLLABLE WUO;Lo;0;L;;;;;N;;;;; +A286;YI SYLLABLE WUOP;Lo;0;L;;;;;N;;;;; +A287;YI SYLLABLE WOX;Lo;0;L;;;;;N;;;;; +A288;YI SYLLABLE WO;Lo;0;L;;;;;N;;;;; +A289;YI SYLLABLE WOP;Lo;0;L;;;;;N;;;;; +A28A;YI SYLLABLE WEX;Lo;0;L;;;;;N;;;;; +A28B;YI SYLLABLE WE;Lo;0;L;;;;;N;;;;; +A28C;YI SYLLABLE WEP;Lo;0;L;;;;;N;;;;; +A28D;YI SYLLABLE ZIT;Lo;0;L;;;;;N;;;;; +A28E;YI SYLLABLE ZIX;Lo;0;L;;;;;N;;;;; +A28F;YI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +A290;YI SYLLABLE ZIP;Lo;0;L;;;;;N;;;;; +A291;YI SYLLABLE ZIEX;Lo;0;L;;;;;N;;;;; +A292;YI SYLLABLE ZIE;Lo;0;L;;;;;N;;;;; +A293;YI SYLLABLE ZIEP;Lo;0;L;;;;;N;;;;; +A294;YI SYLLABLE ZAT;Lo;0;L;;;;;N;;;;; +A295;YI SYLLABLE ZAX;Lo;0;L;;;;;N;;;;; +A296;YI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +A297;YI SYLLABLE ZAP;Lo;0;L;;;;;N;;;;; +A298;YI SYLLABLE ZUOX;Lo;0;L;;;;;N;;;;; +A299;YI SYLLABLE ZUO;Lo;0;L;;;;;N;;;;; +A29A;YI SYLLABLE ZUOP;Lo;0;L;;;;;N;;;;; +A29B;YI SYLLABLE ZOT;Lo;0;L;;;;;N;;;;; +A29C;YI SYLLABLE ZOX;Lo;0;L;;;;;N;;;;; +A29D;YI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +A29E;YI SYLLABLE ZOP;Lo;0;L;;;;;N;;;;; +A29F;YI SYLLABLE ZEX;Lo;0;L;;;;;N;;;;; +A2A0;YI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +A2A1;YI SYLLABLE ZEP;Lo;0;L;;;;;N;;;;; +A2A2;YI SYLLABLE ZUT;Lo;0;L;;;;;N;;;;; +A2A3;YI SYLLABLE ZUX;Lo;0;L;;;;;N;;;;; +A2A4;YI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +A2A5;YI SYLLABLE ZUP;Lo;0;L;;;;;N;;;;; +A2A6;YI SYLLABLE ZURX;Lo;0;L;;;;;N;;;;; +A2A7;YI SYLLABLE ZUR;Lo;0;L;;;;;N;;;;; +A2A8;YI SYLLABLE ZYT;Lo;0;L;;;;;N;;;;; +A2A9;YI SYLLABLE ZYX;Lo;0;L;;;;;N;;;;; +A2AA;YI SYLLABLE ZY;Lo;0;L;;;;;N;;;;; +A2AB;YI SYLLABLE ZYP;Lo;0;L;;;;;N;;;;; +A2AC;YI SYLLABLE ZYRX;Lo;0;L;;;;;N;;;;; +A2AD;YI SYLLABLE ZYR;Lo;0;L;;;;;N;;;;; +A2AE;YI SYLLABLE CIT;Lo;0;L;;;;;N;;;;; +A2AF;YI SYLLABLE CIX;Lo;0;L;;;;;N;;;;; +A2B0;YI SYLLABLE CI;Lo;0;L;;;;;N;;;;; +A2B1;YI SYLLABLE CIP;Lo;0;L;;;;;N;;;;; +A2B2;YI SYLLABLE CIET;Lo;0;L;;;;;N;;;;; +A2B3;YI SYLLABLE CIEX;Lo;0;L;;;;;N;;;;; +A2B4;YI SYLLABLE CIE;Lo;0;L;;;;;N;;;;; +A2B5;YI SYLLABLE CIEP;Lo;0;L;;;;;N;;;;; +A2B6;YI SYLLABLE CAT;Lo;0;L;;;;;N;;;;; +A2B7;YI SYLLABLE CAX;Lo;0;L;;;;;N;;;;; +A2B8;YI SYLLABLE CA;Lo;0;L;;;;;N;;;;; +A2B9;YI SYLLABLE CAP;Lo;0;L;;;;;N;;;;; +A2BA;YI SYLLABLE CUOX;Lo;0;L;;;;;N;;;;; +A2BB;YI SYLLABLE CUO;Lo;0;L;;;;;N;;;;; +A2BC;YI SYLLABLE CUOP;Lo;0;L;;;;;N;;;;; +A2BD;YI SYLLABLE COT;Lo;0;L;;;;;N;;;;; +A2BE;YI SYLLABLE COX;Lo;0;L;;;;;N;;;;; +A2BF;YI SYLLABLE CO;Lo;0;L;;;;;N;;;;; +A2C0;YI SYLLABLE COP;Lo;0;L;;;;;N;;;;; +A2C1;YI SYLLABLE CEX;Lo;0;L;;;;;N;;;;; +A2C2;YI SYLLABLE CE;Lo;0;L;;;;;N;;;;; +A2C3;YI SYLLABLE CEP;Lo;0;L;;;;;N;;;;; +A2C4;YI SYLLABLE CUT;Lo;0;L;;;;;N;;;;; +A2C5;YI SYLLABLE CUX;Lo;0;L;;;;;N;;;;; +A2C6;YI SYLLABLE CU;Lo;0;L;;;;;N;;;;; +A2C7;YI SYLLABLE CUP;Lo;0;L;;;;;N;;;;; +A2C8;YI SYLLABLE CURX;Lo;0;L;;;;;N;;;;; +A2C9;YI SYLLABLE CUR;Lo;0;L;;;;;N;;;;; +A2CA;YI SYLLABLE CYT;Lo;0;L;;;;;N;;;;; +A2CB;YI SYLLABLE CYX;Lo;0;L;;;;;N;;;;; +A2CC;YI SYLLABLE CY;Lo;0;L;;;;;N;;;;; +A2CD;YI SYLLABLE CYP;Lo;0;L;;;;;N;;;;; +A2CE;YI SYLLABLE CYRX;Lo;0;L;;;;;N;;;;; +A2CF;YI SYLLABLE CYR;Lo;0;L;;;;;N;;;;; +A2D0;YI SYLLABLE ZZIT;Lo;0;L;;;;;N;;;;; +A2D1;YI SYLLABLE ZZIX;Lo;0;L;;;;;N;;;;; +A2D2;YI SYLLABLE ZZI;Lo;0;L;;;;;N;;;;; +A2D3;YI SYLLABLE ZZIP;Lo;0;L;;;;;N;;;;; +A2D4;YI SYLLABLE ZZIET;Lo;0;L;;;;;N;;;;; +A2D5;YI SYLLABLE ZZIEX;Lo;0;L;;;;;N;;;;; +A2D6;YI SYLLABLE ZZIE;Lo;0;L;;;;;N;;;;; +A2D7;YI SYLLABLE ZZIEP;Lo;0;L;;;;;N;;;;; +A2D8;YI SYLLABLE ZZAT;Lo;0;L;;;;;N;;;;; +A2D9;YI SYLLABLE ZZAX;Lo;0;L;;;;;N;;;;; +A2DA;YI SYLLABLE ZZA;Lo;0;L;;;;;N;;;;; +A2DB;YI SYLLABLE ZZAP;Lo;0;L;;;;;N;;;;; +A2DC;YI SYLLABLE ZZOX;Lo;0;L;;;;;N;;;;; +A2DD;YI SYLLABLE ZZO;Lo;0;L;;;;;N;;;;; +A2DE;YI SYLLABLE ZZOP;Lo;0;L;;;;;N;;;;; +A2DF;YI SYLLABLE ZZEX;Lo;0;L;;;;;N;;;;; +A2E0;YI SYLLABLE ZZE;Lo;0;L;;;;;N;;;;; +A2E1;YI SYLLABLE ZZEP;Lo;0;L;;;;;N;;;;; +A2E2;YI SYLLABLE ZZUX;Lo;0;L;;;;;N;;;;; +A2E3;YI SYLLABLE ZZU;Lo;0;L;;;;;N;;;;; +A2E4;YI SYLLABLE ZZUP;Lo;0;L;;;;;N;;;;; +A2E5;YI SYLLABLE ZZURX;Lo;0;L;;;;;N;;;;; +A2E6;YI SYLLABLE ZZUR;Lo;0;L;;;;;N;;;;; +A2E7;YI SYLLABLE ZZYT;Lo;0;L;;;;;N;;;;; +A2E8;YI SYLLABLE ZZYX;Lo;0;L;;;;;N;;;;; +A2E9;YI SYLLABLE ZZY;Lo;0;L;;;;;N;;;;; +A2EA;YI SYLLABLE ZZYP;Lo;0;L;;;;;N;;;;; +A2EB;YI SYLLABLE ZZYRX;Lo;0;L;;;;;N;;;;; +A2EC;YI SYLLABLE ZZYR;Lo;0;L;;;;;N;;;;; +A2ED;YI SYLLABLE NZIT;Lo;0;L;;;;;N;;;;; +A2EE;YI SYLLABLE NZIX;Lo;0;L;;;;;N;;;;; +A2EF;YI SYLLABLE NZI;Lo;0;L;;;;;N;;;;; +A2F0;YI SYLLABLE NZIP;Lo;0;L;;;;;N;;;;; +A2F1;YI SYLLABLE NZIEX;Lo;0;L;;;;;N;;;;; +A2F2;YI SYLLABLE NZIE;Lo;0;L;;;;;N;;;;; +A2F3;YI SYLLABLE NZIEP;Lo;0;L;;;;;N;;;;; +A2F4;YI SYLLABLE NZAT;Lo;0;L;;;;;N;;;;; +A2F5;YI SYLLABLE NZAX;Lo;0;L;;;;;N;;;;; +A2F6;YI SYLLABLE NZA;Lo;0;L;;;;;N;;;;; +A2F7;YI SYLLABLE NZAP;Lo;0;L;;;;;N;;;;; +A2F8;YI SYLLABLE NZUOX;Lo;0;L;;;;;N;;;;; +A2F9;YI SYLLABLE NZUO;Lo;0;L;;;;;N;;;;; +A2FA;YI SYLLABLE NZOX;Lo;0;L;;;;;N;;;;; +A2FB;YI SYLLABLE NZOP;Lo;0;L;;;;;N;;;;; +A2FC;YI SYLLABLE NZEX;Lo;0;L;;;;;N;;;;; +A2FD;YI SYLLABLE NZE;Lo;0;L;;;;;N;;;;; +A2FE;YI SYLLABLE NZUX;Lo;0;L;;;;;N;;;;; +A2FF;YI SYLLABLE NZU;Lo;0;L;;;;;N;;;;; +A300;YI SYLLABLE NZUP;Lo;0;L;;;;;N;;;;; +A301;YI SYLLABLE NZURX;Lo;0;L;;;;;N;;;;; +A302;YI SYLLABLE NZUR;Lo;0;L;;;;;N;;;;; +A303;YI SYLLABLE NZYT;Lo;0;L;;;;;N;;;;; +A304;YI SYLLABLE NZYX;Lo;0;L;;;;;N;;;;; +A305;YI SYLLABLE NZY;Lo;0;L;;;;;N;;;;; +A306;YI SYLLABLE NZYP;Lo;0;L;;;;;N;;;;; +A307;YI SYLLABLE NZYRX;Lo;0;L;;;;;N;;;;; +A308;YI SYLLABLE NZYR;Lo;0;L;;;;;N;;;;; +A309;YI SYLLABLE SIT;Lo;0;L;;;;;N;;;;; +A30A;YI SYLLABLE SIX;Lo;0;L;;;;;N;;;;; +A30B;YI SYLLABLE SI;Lo;0;L;;;;;N;;;;; +A30C;YI SYLLABLE SIP;Lo;0;L;;;;;N;;;;; +A30D;YI SYLLABLE SIEX;Lo;0;L;;;;;N;;;;; +A30E;YI SYLLABLE SIE;Lo;0;L;;;;;N;;;;; +A30F;YI SYLLABLE SIEP;Lo;0;L;;;;;N;;;;; +A310;YI SYLLABLE SAT;Lo;0;L;;;;;N;;;;; +A311;YI SYLLABLE SAX;Lo;0;L;;;;;N;;;;; +A312;YI SYLLABLE SA;Lo;0;L;;;;;N;;;;; +A313;YI SYLLABLE SAP;Lo;0;L;;;;;N;;;;; +A314;YI SYLLABLE SUOX;Lo;0;L;;;;;N;;;;; +A315;YI SYLLABLE SUO;Lo;0;L;;;;;N;;;;; +A316;YI SYLLABLE SUOP;Lo;0;L;;;;;N;;;;; +A317;YI SYLLABLE SOT;Lo;0;L;;;;;N;;;;; +A318;YI SYLLABLE SOX;Lo;0;L;;;;;N;;;;; +A319;YI SYLLABLE SO;Lo;0;L;;;;;N;;;;; +A31A;YI SYLLABLE SOP;Lo;0;L;;;;;N;;;;; +A31B;YI SYLLABLE SEX;Lo;0;L;;;;;N;;;;; +A31C;YI SYLLABLE SE;Lo;0;L;;;;;N;;;;; +A31D;YI SYLLABLE SEP;Lo;0;L;;;;;N;;;;; +A31E;YI SYLLABLE SUT;Lo;0;L;;;;;N;;;;; +A31F;YI SYLLABLE SUX;Lo;0;L;;;;;N;;;;; +A320;YI SYLLABLE SU;Lo;0;L;;;;;N;;;;; +A321;YI SYLLABLE SUP;Lo;0;L;;;;;N;;;;; +A322;YI SYLLABLE SURX;Lo;0;L;;;;;N;;;;; +A323;YI SYLLABLE SUR;Lo;0;L;;;;;N;;;;; +A324;YI SYLLABLE SYT;Lo;0;L;;;;;N;;;;; +A325;YI SYLLABLE SYX;Lo;0;L;;;;;N;;;;; +A326;YI SYLLABLE SY;Lo;0;L;;;;;N;;;;; +A327;YI SYLLABLE SYP;Lo;0;L;;;;;N;;;;; +A328;YI SYLLABLE SYRX;Lo;0;L;;;;;N;;;;; +A329;YI SYLLABLE SYR;Lo;0;L;;;;;N;;;;; +A32A;YI SYLLABLE SSIT;Lo;0;L;;;;;N;;;;; +A32B;YI SYLLABLE SSIX;Lo;0;L;;;;;N;;;;; +A32C;YI SYLLABLE SSI;Lo;0;L;;;;;N;;;;; +A32D;YI SYLLABLE SSIP;Lo;0;L;;;;;N;;;;; +A32E;YI SYLLABLE SSIEX;Lo;0;L;;;;;N;;;;; +A32F;YI SYLLABLE SSIE;Lo;0;L;;;;;N;;;;; +A330;YI SYLLABLE SSIEP;Lo;0;L;;;;;N;;;;; +A331;YI SYLLABLE SSAT;Lo;0;L;;;;;N;;;;; +A332;YI SYLLABLE SSAX;Lo;0;L;;;;;N;;;;; +A333;YI SYLLABLE SSA;Lo;0;L;;;;;N;;;;; +A334;YI SYLLABLE SSAP;Lo;0;L;;;;;N;;;;; +A335;YI SYLLABLE SSOT;Lo;0;L;;;;;N;;;;; +A336;YI SYLLABLE SSOX;Lo;0;L;;;;;N;;;;; +A337;YI SYLLABLE SSO;Lo;0;L;;;;;N;;;;; +A338;YI SYLLABLE SSOP;Lo;0;L;;;;;N;;;;; +A339;YI SYLLABLE SSEX;Lo;0;L;;;;;N;;;;; +A33A;YI SYLLABLE SSE;Lo;0;L;;;;;N;;;;; +A33B;YI SYLLABLE SSEP;Lo;0;L;;;;;N;;;;; +A33C;YI SYLLABLE SSUT;Lo;0;L;;;;;N;;;;; +A33D;YI SYLLABLE SSUX;Lo;0;L;;;;;N;;;;; +A33E;YI SYLLABLE SSU;Lo;0;L;;;;;N;;;;; +A33F;YI SYLLABLE SSUP;Lo;0;L;;;;;N;;;;; +A340;YI SYLLABLE SSYT;Lo;0;L;;;;;N;;;;; +A341;YI SYLLABLE SSYX;Lo;0;L;;;;;N;;;;; +A342;YI SYLLABLE SSY;Lo;0;L;;;;;N;;;;; +A343;YI SYLLABLE SSYP;Lo;0;L;;;;;N;;;;; +A344;YI SYLLABLE SSYRX;Lo;0;L;;;;;N;;;;; +A345;YI SYLLABLE SSYR;Lo;0;L;;;;;N;;;;; +A346;YI SYLLABLE ZHAT;Lo;0;L;;;;;N;;;;; +A347;YI SYLLABLE ZHAX;Lo;0;L;;;;;N;;;;; +A348;YI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +A349;YI SYLLABLE ZHAP;Lo;0;L;;;;;N;;;;; +A34A;YI SYLLABLE ZHUOX;Lo;0;L;;;;;N;;;;; +A34B;YI SYLLABLE ZHUO;Lo;0;L;;;;;N;;;;; +A34C;YI SYLLABLE ZHUOP;Lo;0;L;;;;;N;;;;; +A34D;YI SYLLABLE ZHOT;Lo;0;L;;;;;N;;;;; +A34E;YI SYLLABLE ZHOX;Lo;0;L;;;;;N;;;;; +A34F;YI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +A350;YI SYLLABLE ZHOP;Lo;0;L;;;;;N;;;;; +A351;YI SYLLABLE ZHET;Lo;0;L;;;;;N;;;;; +A352;YI SYLLABLE ZHEX;Lo;0;L;;;;;N;;;;; +A353;YI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +A354;YI SYLLABLE ZHEP;Lo;0;L;;;;;N;;;;; +A355;YI SYLLABLE ZHUT;Lo;0;L;;;;;N;;;;; +A356;YI SYLLABLE ZHUX;Lo;0;L;;;;;N;;;;; +A357;YI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +A358;YI SYLLABLE ZHUP;Lo;0;L;;;;;N;;;;; +A359;YI SYLLABLE ZHURX;Lo;0;L;;;;;N;;;;; +A35A;YI SYLLABLE ZHUR;Lo;0;L;;;;;N;;;;; +A35B;YI SYLLABLE ZHYT;Lo;0;L;;;;;N;;;;; +A35C;YI SYLLABLE ZHYX;Lo;0;L;;;;;N;;;;; +A35D;YI SYLLABLE ZHY;Lo;0;L;;;;;N;;;;; +A35E;YI SYLLABLE ZHYP;Lo;0;L;;;;;N;;;;; +A35F;YI SYLLABLE ZHYRX;Lo;0;L;;;;;N;;;;; +A360;YI SYLLABLE ZHYR;Lo;0;L;;;;;N;;;;; +A361;YI SYLLABLE CHAT;Lo;0;L;;;;;N;;;;; +A362;YI SYLLABLE CHAX;Lo;0;L;;;;;N;;;;; +A363;YI SYLLABLE CHA;Lo;0;L;;;;;N;;;;; +A364;YI SYLLABLE CHAP;Lo;0;L;;;;;N;;;;; +A365;YI SYLLABLE CHUOT;Lo;0;L;;;;;N;;;;; +A366;YI SYLLABLE CHUOX;Lo;0;L;;;;;N;;;;; +A367;YI SYLLABLE CHUO;Lo;0;L;;;;;N;;;;; +A368;YI SYLLABLE CHUOP;Lo;0;L;;;;;N;;;;; +A369;YI SYLLABLE CHOT;Lo;0;L;;;;;N;;;;; +A36A;YI SYLLABLE CHOX;Lo;0;L;;;;;N;;;;; +A36B;YI SYLLABLE CHO;Lo;0;L;;;;;N;;;;; +A36C;YI SYLLABLE CHOP;Lo;0;L;;;;;N;;;;; +A36D;YI SYLLABLE CHET;Lo;0;L;;;;;N;;;;; +A36E;YI SYLLABLE CHEX;Lo;0;L;;;;;N;;;;; +A36F;YI SYLLABLE CHE;Lo;0;L;;;;;N;;;;; +A370;YI SYLLABLE CHEP;Lo;0;L;;;;;N;;;;; +A371;YI SYLLABLE CHUX;Lo;0;L;;;;;N;;;;; +A372;YI SYLLABLE CHU;Lo;0;L;;;;;N;;;;; +A373;YI SYLLABLE CHUP;Lo;0;L;;;;;N;;;;; +A374;YI SYLLABLE CHURX;Lo;0;L;;;;;N;;;;; +A375;YI SYLLABLE CHUR;Lo;0;L;;;;;N;;;;; +A376;YI SYLLABLE CHYT;Lo;0;L;;;;;N;;;;; +A377;YI SYLLABLE CHYX;Lo;0;L;;;;;N;;;;; +A378;YI SYLLABLE CHY;Lo;0;L;;;;;N;;;;; +A379;YI SYLLABLE CHYP;Lo;0;L;;;;;N;;;;; +A37A;YI SYLLABLE CHYRX;Lo;0;L;;;;;N;;;;; +A37B;YI SYLLABLE CHYR;Lo;0;L;;;;;N;;;;; +A37C;YI SYLLABLE RRAX;Lo;0;L;;;;;N;;;;; +A37D;YI SYLLABLE RRA;Lo;0;L;;;;;N;;;;; +A37E;YI SYLLABLE RRUOX;Lo;0;L;;;;;N;;;;; +A37F;YI SYLLABLE RRUO;Lo;0;L;;;;;N;;;;; +A380;YI SYLLABLE RROT;Lo;0;L;;;;;N;;;;; +A381;YI SYLLABLE RROX;Lo;0;L;;;;;N;;;;; +A382;YI SYLLABLE RRO;Lo;0;L;;;;;N;;;;; +A383;YI SYLLABLE RROP;Lo;0;L;;;;;N;;;;; +A384;YI SYLLABLE RRET;Lo;0;L;;;;;N;;;;; +A385;YI SYLLABLE RREX;Lo;0;L;;;;;N;;;;; +A386;YI SYLLABLE RRE;Lo;0;L;;;;;N;;;;; +A387;YI SYLLABLE RREP;Lo;0;L;;;;;N;;;;; +A388;YI SYLLABLE RRUT;Lo;0;L;;;;;N;;;;; +A389;YI SYLLABLE RRUX;Lo;0;L;;;;;N;;;;; +A38A;YI SYLLABLE RRU;Lo;0;L;;;;;N;;;;; +A38B;YI SYLLABLE RRUP;Lo;0;L;;;;;N;;;;; +A38C;YI SYLLABLE RRURX;Lo;0;L;;;;;N;;;;; +A38D;YI SYLLABLE RRUR;Lo;0;L;;;;;N;;;;; +A38E;YI SYLLABLE RRYT;Lo;0;L;;;;;N;;;;; +A38F;YI SYLLABLE RRYX;Lo;0;L;;;;;N;;;;; +A390;YI SYLLABLE RRY;Lo;0;L;;;;;N;;;;; +A391;YI SYLLABLE RRYP;Lo;0;L;;;;;N;;;;; +A392;YI SYLLABLE RRYRX;Lo;0;L;;;;;N;;;;; +A393;YI SYLLABLE RRYR;Lo;0;L;;;;;N;;;;; +A394;YI SYLLABLE NRAT;Lo;0;L;;;;;N;;;;; +A395;YI SYLLABLE NRAX;Lo;0;L;;;;;N;;;;; +A396;YI SYLLABLE NRA;Lo;0;L;;;;;N;;;;; +A397;YI SYLLABLE NRAP;Lo;0;L;;;;;N;;;;; +A398;YI SYLLABLE NROX;Lo;0;L;;;;;N;;;;; +A399;YI SYLLABLE NRO;Lo;0;L;;;;;N;;;;; +A39A;YI SYLLABLE NROP;Lo;0;L;;;;;N;;;;; +A39B;YI SYLLABLE NRET;Lo;0;L;;;;;N;;;;; +A39C;YI SYLLABLE NREX;Lo;0;L;;;;;N;;;;; +A39D;YI SYLLABLE NRE;Lo;0;L;;;;;N;;;;; +A39E;YI SYLLABLE NREP;Lo;0;L;;;;;N;;;;; +A39F;YI SYLLABLE NRUT;Lo;0;L;;;;;N;;;;; +A3A0;YI SYLLABLE NRUX;Lo;0;L;;;;;N;;;;; +A3A1;YI SYLLABLE NRU;Lo;0;L;;;;;N;;;;; +A3A2;YI SYLLABLE NRUP;Lo;0;L;;;;;N;;;;; +A3A3;YI SYLLABLE NRURX;Lo;0;L;;;;;N;;;;; +A3A4;YI SYLLABLE NRUR;Lo;0;L;;;;;N;;;;; +A3A5;YI SYLLABLE NRYT;Lo;0;L;;;;;N;;;;; +A3A6;YI SYLLABLE NRYX;Lo;0;L;;;;;N;;;;; +A3A7;YI SYLLABLE NRY;Lo;0;L;;;;;N;;;;; +A3A8;YI SYLLABLE NRYP;Lo;0;L;;;;;N;;;;; +A3A9;YI SYLLABLE NRYRX;Lo;0;L;;;;;N;;;;; +A3AA;YI SYLLABLE NRYR;Lo;0;L;;;;;N;;;;; +A3AB;YI SYLLABLE SHAT;Lo;0;L;;;;;N;;;;; +A3AC;YI SYLLABLE SHAX;Lo;0;L;;;;;N;;;;; +A3AD;YI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +A3AE;YI SYLLABLE SHAP;Lo;0;L;;;;;N;;;;; +A3AF;YI SYLLABLE SHUOX;Lo;0;L;;;;;N;;;;; +A3B0;YI SYLLABLE SHUO;Lo;0;L;;;;;N;;;;; +A3B1;YI SYLLABLE SHUOP;Lo;0;L;;;;;N;;;;; +A3B2;YI SYLLABLE SHOT;Lo;0;L;;;;;N;;;;; +A3B3;YI SYLLABLE SHOX;Lo;0;L;;;;;N;;;;; +A3B4;YI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +A3B5;YI SYLLABLE SHOP;Lo;0;L;;;;;N;;;;; +A3B6;YI SYLLABLE SHET;Lo;0;L;;;;;N;;;;; +A3B7;YI SYLLABLE SHEX;Lo;0;L;;;;;N;;;;; +A3B8;YI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +A3B9;YI SYLLABLE SHEP;Lo;0;L;;;;;N;;;;; +A3BA;YI SYLLABLE SHUT;Lo;0;L;;;;;N;;;;; +A3BB;YI SYLLABLE SHUX;Lo;0;L;;;;;N;;;;; +A3BC;YI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +A3BD;YI SYLLABLE SHUP;Lo;0;L;;;;;N;;;;; +A3BE;YI SYLLABLE SHURX;Lo;0;L;;;;;N;;;;; +A3BF;YI SYLLABLE SHUR;Lo;0;L;;;;;N;;;;; +A3C0;YI SYLLABLE SHYT;Lo;0;L;;;;;N;;;;; +A3C1;YI SYLLABLE SHYX;Lo;0;L;;;;;N;;;;; +A3C2;YI SYLLABLE SHY;Lo;0;L;;;;;N;;;;; +A3C3;YI SYLLABLE SHYP;Lo;0;L;;;;;N;;;;; +A3C4;YI SYLLABLE SHYRX;Lo;0;L;;;;;N;;;;; +A3C5;YI SYLLABLE SHYR;Lo;0;L;;;;;N;;;;; +A3C6;YI SYLLABLE RAT;Lo;0;L;;;;;N;;;;; +A3C7;YI SYLLABLE RAX;Lo;0;L;;;;;N;;;;; +A3C8;YI SYLLABLE RA;Lo;0;L;;;;;N;;;;; +A3C9;YI SYLLABLE RAP;Lo;0;L;;;;;N;;;;; +A3CA;YI SYLLABLE RUOX;Lo;0;L;;;;;N;;;;; +A3CB;YI SYLLABLE RUO;Lo;0;L;;;;;N;;;;; +A3CC;YI SYLLABLE RUOP;Lo;0;L;;;;;N;;;;; +A3CD;YI SYLLABLE ROT;Lo;0;L;;;;;N;;;;; +A3CE;YI SYLLABLE ROX;Lo;0;L;;;;;N;;;;; +A3CF;YI SYLLABLE RO;Lo;0;L;;;;;N;;;;; +A3D0;YI SYLLABLE ROP;Lo;0;L;;;;;N;;;;; +A3D1;YI SYLLABLE REX;Lo;0;L;;;;;N;;;;; +A3D2;YI SYLLABLE RE;Lo;0;L;;;;;N;;;;; +A3D3;YI SYLLABLE REP;Lo;0;L;;;;;N;;;;; +A3D4;YI SYLLABLE RUT;Lo;0;L;;;;;N;;;;; +A3D5;YI SYLLABLE RUX;Lo;0;L;;;;;N;;;;; +A3D6;YI SYLLABLE RU;Lo;0;L;;;;;N;;;;; +A3D7;YI SYLLABLE RUP;Lo;0;L;;;;;N;;;;; +A3D8;YI SYLLABLE RURX;Lo;0;L;;;;;N;;;;; +A3D9;YI SYLLABLE RUR;Lo;0;L;;;;;N;;;;; +A3DA;YI SYLLABLE RYT;Lo;0;L;;;;;N;;;;; +A3DB;YI SYLLABLE RYX;Lo;0;L;;;;;N;;;;; +A3DC;YI SYLLABLE RY;Lo;0;L;;;;;N;;;;; +A3DD;YI SYLLABLE RYP;Lo;0;L;;;;;N;;;;; +A3DE;YI SYLLABLE RYRX;Lo;0;L;;;;;N;;;;; +A3DF;YI SYLLABLE RYR;Lo;0;L;;;;;N;;;;; +A3E0;YI SYLLABLE JIT;Lo;0;L;;;;;N;;;;; +A3E1;YI SYLLABLE JIX;Lo;0;L;;;;;N;;;;; +A3E2;YI SYLLABLE JI;Lo;0;L;;;;;N;;;;; +A3E3;YI SYLLABLE JIP;Lo;0;L;;;;;N;;;;; +A3E4;YI SYLLABLE JIET;Lo;0;L;;;;;N;;;;; +A3E5;YI SYLLABLE JIEX;Lo;0;L;;;;;N;;;;; +A3E6;YI SYLLABLE JIE;Lo;0;L;;;;;N;;;;; +A3E7;YI SYLLABLE JIEP;Lo;0;L;;;;;N;;;;; +A3E8;YI SYLLABLE JUOT;Lo;0;L;;;;;N;;;;; +A3E9;YI SYLLABLE JUOX;Lo;0;L;;;;;N;;;;; +A3EA;YI SYLLABLE JUO;Lo;0;L;;;;;N;;;;; +A3EB;YI SYLLABLE JUOP;Lo;0;L;;;;;N;;;;; +A3EC;YI SYLLABLE JOT;Lo;0;L;;;;;N;;;;; +A3ED;YI SYLLABLE JOX;Lo;0;L;;;;;N;;;;; +A3EE;YI SYLLABLE JO;Lo;0;L;;;;;N;;;;; +A3EF;YI SYLLABLE JOP;Lo;0;L;;;;;N;;;;; +A3F0;YI SYLLABLE JUT;Lo;0;L;;;;;N;;;;; +A3F1;YI SYLLABLE JUX;Lo;0;L;;;;;N;;;;; +A3F2;YI SYLLABLE JU;Lo;0;L;;;;;N;;;;; +A3F3;YI SYLLABLE JUP;Lo;0;L;;;;;N;;;;; +A3F4;YI SYLLABLE JURX;Lo;0;L;;;;;N;;;;; +A3F5;YI SYLLABLE JUR;Lo;0;L;;;;;N;;;;; +A3F6;YI SYLLABLE JYT;Lo;0;L;;;;;N;;;;; +A3F7;YI SYLLABLE JYX;Lo;0;L;;;;;N;;;;; +A3F8;YI SYLLABLE JY;Lo;0;L;;;;;N;;;;; +A3F9;YI SYLLABLE JYP;Lo;0;L;;;;;N;;;;; +A3FA;YI SYLLABLE JYRX;Lo;0;L;;;;;N;;;;; +A3FB;YI SYLLABLE JYR;Lo;0;L;;;;;N;;;;; +A3FC;YI SYLLABLE QIT;Lo;0;L;;;;;N;;;;; +A3FD;YI SYLLABLE QIX;Lo;0;L;;;;;N;;;;; +A3FE;YI SYLLABLE QI;Lo;0;L;;;;;N;;;;; +A3FF;YI SYLLABLE QIP;Lo;0;L;;;;;N;;;;; +A400;YI SYLLABLE QIET;Lo;0;L;;;;;N;;;;; +A401;YI SYLLABLE QIEX;Lo;0;L;;;;;N;;;;; +A402;YI SYLLABLE QIE;Lo;0;L;;;;;N;;;;; +A403;YI SYLLABLE QIEP;Lo;0;L;;;;;N;;;;; +A404;YI SYLLABLE QUOT;Lo;0;L;;;;;N;;;;; +A405;YI SYLLABLE QUOX;Lo;0;L;;;;;N;;;;; +A406;YI SYLLABLE QUO;Lo;0;L;;;;;N;;;;; +A407;YI SYLLABLE QUOP;Lo;0;L;;;;;N;;;;; +A408;YI SYLLABLE QOT;Lo;0;L;;;;;N;;;;; +A409;YI SYLLABLE QOX;Lo;0;L;;;;;N;;;;; +A40A;YI SYLLABLE QO;Lo;0;L;;;;;N;;;;; +A40B;YI SYLLABLE QOP;Lo;0;L;;;;;N;;;;; +A40C;YI SYLLABLE QUT;Lo;0;L;;;;;N;;;;; +A40D;YI SYLLABLE QUX;Lo;0;L;;;;;N;;;;; +A40E;YI SYLLABLE QU;Lo;0;L;;;;;N;;;;; +A40F;YI SYLLABLE QUP;Lo;0;L;;;;;N;;;;; +A410;YI SYLLABLE QURX;Lo;0;L;;;;;N;;;;; +A411;YI SYLLABLE QUR;Lo;0;L;;;;;N;;;;; +A412;YI SYLLABLE QYT;Lo;0;L;;;;;N;;;;; +A413;YI SYLLABLE QYX;Lo;0;L;;;;;N;;;;; +A414;YI SYLLABLE QY;Lo;0;L;;;;;N;;;;; +A415;YI SYLLABLE QYP;Lo;0;L;;;;;N;;;;; +A416;YI SYLLABLE QYRX;Lo;0;L;;;;;N;;;;; +A417;YI SYLLABLE QYR;Lo;0;L;;;;;N;;;;; +A418;YI SYLLABLE JJIT;Lo;0;L;;;;;N;;;;; +A419;YI SYLLABLE JJIX;Lo;0;L;;;;;N;;;;; +A41A;YI SYLLABLE JJI;Lo;0;L;;;;;N;;;;; +A41B;YI SYLLABLE JJIP;Lo;0;L;;;;;N;;;;; +A41C;YI SYLLABLE JJIET;Lo;0;L;;;;;N;;;;; +A41D;YI SYLLABLE JJIEX;Lo;0;L;;;;;N;;;;; +A41E;YI SYLLABLE JJIE;Lo;0;L;;;;;N;;;;; +A41F;YI SYLLABLE JJIEP;Lo;0;L;;;;;N;;;;; +A420;YI SYLLABLE JJUOX;Lo;0;L;;;;;N;;;;; +A421;YI SYLLABLE JJUO;Lo;0;L;;;;;N;;;;; +A422;YI SYLLABLE JJUOP;Lo;0;L;;;;;N;;;;; +A423;YI SYLLABLE JJOT;Lo;0;L;;;;;N;;;;; +A424;YI SYLLABLE JJOX;Lo;0;L;;;;;N;;;;; +A425;YI SYLLABLE JJO;Lo;0;L;;;;;N;;;;; +A426;YI SYLLABLE JJOP;Lo;0;L;;;;;N;;;;; +A427;YI SYLLABLE JJUT;Lo;0;L;;;;;N;;;;; +A428;YI SYLLABLE JJUX;Lo;0;L;;;;;N;;;;; +A429;YI SYLLABLE JJU;Lo;0;L;;;;;N;;;;; +A42A;YI SYLLABLE JJUP;Lo;0;L;;;;;N;;;;; +A42B;YI SYLLABLE JJURX;Lo;0;L;;;;;N;;;;; +A42C;YI SYLLABLE JJUR;Lo;0;L;;;;;N;;;;; +A42D;YI SYLLABLE JJYT;Lo;0;L;;;;;N;;;;; +A42E;YI SYLLABLE JJYX;Lo;0;L;;;;;N;;;;; +A42F;YI SYLLABLE JJY;Lo;0;L;;;;;N;;;;; +A430;YI SYLLABLE JJYP;Lo;0;L;;;;;N;;;;; +A431;YI SYLLABLE NJIT;Lo;0;L;;;;;N;;;;; +A432;YI SYLLABLE NJIX;Lo;0;L;;;;;N;;;;; +A433;YI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; +A434;YI SYLLABLE NJIP;Lo;0;L;;;;;N;;;;; +A435;YI SYLLABLE NJIET;Lo;0;L;;;;;N;;;;; +A436;YI SYLLABLE NJIEX;Lo;0;L;;;;;N;;;;; +A437;YI SYLLABLE NJIE;Lo;0;L;;;;;N;;;;; +A438;YI SYLLABLE NJIEP;Lo;0;L;;;;;N;;;;; +A439;YI SYLLABLE NJUOX;Lo;0;L;;;;;N;;;;; +A43A;YI SYLLABLE NJUO;Lo;0;L;;;;;N;;;;; +A43B;YI SYLLABLE NJOT;Lo;0;L;;;;;N;;;;; +A43C;YI SYLLABLE NJOX;Lo;0;L;;;;;N;;;;; +A43D;YI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; +A43E;YI SYLLABLE NJOP;Lo;0;L;;;;;N;;;;; +A43F;YI SYLLABLE NJUX;Lo;0;L;;;;;N;;;;; +A440;YI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; +A441;YI SYLLABLE NJUP;Lo;0;L;;;;;N;;;;; +A442;YI SYLLABLE NJURX;Lo;0;L;;;;;N;;;;; +A443;YI SYLLABLE NJUR;Lo;0;L;;;;;N;;;;; +A444;YI SYLLABLE NJYT;Lo;0;L;;;;;N;;;;; +A445;YI SYLLABLE NJYX;Lo;0;L;;;;;N;;;;; +A446;YI SYLLABLE NJY;Lo;0;L;;;;;N;;;;; +A447;YI SYLLABLE NJYP;Lo;0;L;;;;;N;;;;; +A448;YI SYLLABLE NJYRX;Lo;0;L;;;;;N;;;;; +A449;YI SYLLABLE NJYR;Lo;0;L;;;;;N;;;;; +A44A;YI SYLLABLE NYIT;Lo;0;L;;;;;N;;;;; +A44B;YI SYLLABLE NYIX;Lo;0;L;;;;;N;;;;; +A44C;YI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +A44D;YI SYLLABLE NYIP;Lo;0;L;;;;;N;;;;; +A44E;YI SYLLABLE NYIET;Lo;0;L;;;;;N;;;;; +A44F;YI SYLLABLE NYIEX;Lo;0;L;;;;;N;;;;; +A450;YI SYLLABLE NYIE;Lo;0;L;;;;;N;;;;; +A451;YI SYLLABLE NYIEP;Lo;0;L;;;;;N;;;;; +A452;YI SYLLABLE NYUOX;Lo;0;L;;;;;N;;;;; +A453;YI SYLLABLE NYUO;Lo;0;L;;;;;N;;;;; +A454;YI SYLLABLE NYUOP;Lo;0;L;;;;;N;;;;; +A455;YI SYLLABLE NYOT;Lo;0;L;;;;;N;;;;; +A456;YI SYLLABLE NYOX;Lo;0;L;;;;;N;;;;; +A457;YI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +A458;YI SYLLABLE NYOP;Lo;0;L;;;;;N;;;;; +A459;YI SYLLABLE NYUT;Lo;0;L;;;;;N;;;;; +A45A;YI SYLLABLE NYUX;Lo;0;L;;;;;N;;;;; +A45B;YI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +A45C;YI SYLLABLE NYUP;Lo;0;L;;;;;N;;;;; +A45D;YI SYLLABLE XIT;Lo;0;L;;;;;N;;;;; +A45E;YI SYLLABLE XIX;Lo;0;L;;;;;N;;;;; +A45F;YI SYLLABLE XI;Lo;0;L;;;;;N;;;;; +A460;YI SYLLABLE XIP;Lo;0;L;;;;;N;;;;; +A461;YI SYLLABLE XIET;Lo;0;L;;;;;N;;;;; +A462;YI SYLLABLE XIEX;Lo;0;L;;;;;N;;;;; +A463;YI SYLLABLE XIE;Lo;0;L;;;;;N;;;;; +A464;YI SYLLABLE XIEP;Lo;0;L;;;;;N;;;;; +A465;YI SYLLABLE XUOX;Lo;0;L;;;;;N;;;;; +A466;YI SYLLABLE XUO;Lo;0;L;;;;;N;;;;; +A467;YI SYLLABLE XOT;Lo;0;L;;;;;N;;;;; +A468;YI SYLLABLE XOX;Lo;0;L;;;;;N;;;;; +A469;YI SYLLABLE XO;Lo;0;L;;;;;N;;;;; +A46A;YI SYLLABLE XOP;Lo;0;L;;;;;N;;;;; +A46B;YI SYLLABLE XYT;Lo;0;L;;;;;N;;;;; +A46C;YI SYLLABLE XYX;Lo;0;L;;;;;N;;;;; +A46D;YI SYLLABLE XY;Lo;0;L;;;;;N;;;;; +A46E;YI SYLLABLE XYP;Lo;0;L;;;;;N;;;;; +A46F;YI SYLLABLE XYRX;Lo;0;L;;;;;N;;;;; +A470;YI SYLLABLE XYR;Lo;0;L;;;;;N;;;;; +A471;YI SYLLABLE YIT;Lo;0;L;;;;;N;;;;; +A472;YI SYLLABLE YIX;Lo;0;L;;;;;N;;;;; +A473;YI SYLLABLE YI;Lo;0;L;;;;;N;;;;; +A474;YI SYLLABLE YIP;Lo;0;L;;;;;N;;;;; +A475;YI SYLLABLE YIET;Lo;0;L;;;;;N;;;;; +A476;YI SYLLABLE YIEX;Lo;0;L;;;;;N;;;;; +A477;YI SYLLABLE YIE;Lo;0;L;;;;;N;;;;; +A478;YI SYLLABLE YIEP;Lo;0;L;;;;;N;;;;; +A479;YI SYLLABLE YUOT;Lo;0;L;;;;;N;;;;; +A47A;YI SYLLABLE YUOX;Lo;0;L;;;;;N;;;;; +A47B;YI SYLLABLE YUO;Lo;0;L;;;;;N;;;;; +A47C;YI SYLLABLE YUOP;Lo;0;L;;;;;N;;;;; +A47D;YI SYLLABLE YOT;Lo;0;L;;;;;N;;;;; +A47E;YI SYLLABLE YOX;Lo;0;L;;;;;N;;;;; +A47F;YI SYLLABLE YO;Lo;0;L;;;;;N;;;;; +A480;YI SYLLABLE YOP;Lo;0;L;;;;;N;;;;; +A481;YI SYLLABLE YUT;Lo;0;L;;;;;N;;;;; +A482;YI SYLLABLE YUX;Lo;0;L;;;;;N;;;;; +A483;YI SYLLABLE YU;Lo;0;L;;;;;N;;;;; +A484;YI SYLLABLE YUP;Lo;0;L;;;;;N;;;;; +A485;YI SYLLABLE YURX;Lo;0;L;;;;;N;;;;; +A486;YI SYLLABLE YUR;Lo;0;L;;;;;N;;;;; +A487;YI SYLLABLE YYT;Lo;0;L;;;;;N;;;;; +A488;YI SYLLABLE YYX;Lo;0;L;;;;;N;;;;; +A489;YI SYLLABLE YY;Lo;0;L;;;;;N;;;;; +A48A;YI SYLLABLE YYP;Lo;0;L;;;;;N;;;;; +A48B;YI SYLLABLE YYRX;Lo;0;L;;;;;N;;;;; +A48C;YI SYLLABLE YYR;Lo;0;L;;;;;N;;;;; +A490;YI RADICAL QOT;So;0;ON;;;;;N;;;;; +A491;YI RADICAL LI;So;0;ON;;;;;N;;;;; +A492;YI RADICAL KIT;So;0;ON;;;;;N;;;;; +A493;YI RADICAL NYIP;So;0;ON;;;;;N;;;;; +A494;YI RADICAL CYP;So;0;ON;;;;;N;;;;; +A495;YI RADICAL SSI;So;0;ON;;;;;N;;;;; +A496;YI RADICAL GGOP;So;0;ON;;;;;N;;;;; +A497;YI RADICAL GEP;So;0;ON;;;;;N;;;;; +A498;YI RADICAL MI;So;0;ON;;;;;N;;;;; +A499;YI RADICAL HXIT;So;0;ON;;;;;N;;;;; +A49A;YI RADICAL LYR;So;0;ON;;;;;N;;;;; +A49B;YI RADICAL BBUT;So;0;ON;;;;;N;;;;; +A49C;YI RADICAL MOP;So;0;ON;;;;;N;;;;; +A49D;YI RADICAL YO;So;0;ON;;;;;N;;;;; +A49E;YI RADICAL PUT;So;0;ON;;;;;N;;;;; +A49F;YI RADICAL HXUO;So;0;ON;;;;;N;;;;; +A4A0;YI RADICAL TAT;So;0;ON;;;;;N;;;;; +A4A1;YI RADICAL GA;So;0;ON;;;;;N;;;;; +A4A2;YI RADICAL ZUP;So;0;ON;;;;;N;;;;; +A4A3;YI RADICAL CYT;So;0;ON;;;;;N;;;;; +A4A4;YI RADICAL DDUR;So;0;ON;;;;;N;;;;; +A4A5;YI RADICAL BUR;So;0;ON;;;;;N;;;;; +A4A6;YI RADICAL GGUO;So;0;ON;;;;;N;;;;; +A4A7;YI RADICAL NYOP;So;0;ON;;;;;N;;;;; +A4A8;YI RADICAL TU;So;0;ON;;;;;N;;;;; +A4A9;YI RADICAL OP;So;0;ON;;;;;N;;;;; +A4AA;YI RADICAL JJUT;So;0;ON;;;;;N;;;;; +A4AB;YI RADICAL ZOT;So;0;ON;;;;;N;;;;; +A4AC;YI RADICAL PYT;So;0;ON;;;;;N;;;;; +A4AD;YI RADICAL HMO;So;0;ON;;;;;N;;;;; +A4AE;YI RADICAL YIT;So;0;ON;;;;;N;;;;; +A4AF;YI RADICAL VUR;So;0;ON;;;;;N;;;;; +A4B0;YI RADICAL SHY;So;0;ON;;;;;N;;;;; +A4B1;YI RADICAL VEP;So;0;ON;;;;;N;;;;; +A4B2;YI RADICAL ZA;So;0;ON;;;;;N;;;;; +A4B3;YI RADICAL JO;So;0;ON;;;;;N;;;;; +A4B4;YI RADICAL NZUP;So;0;ON;;;;;N;;;;; +A4B5;YI RADICAL JJY;So;0;ON;;;;;N;;;;; +A4B6;YI RADICAL GOT;So;0;ON;;;;;N;;;;; +A4B7;YI RADICAL JJIE;So;0;ON;;;;;N;;;;; +A4B8;YI RADICAL WO;So;0;ON;;;;;N;;;;; +A4B9;YI RADICAL DU;So;0;ON;;;;;N;;;;; +A4BA;YI RADICAL SHUR;So;0;ON;;;;;N;;;;; +A4BB;YI RADICAL LIE;So;0;ON;;;;;N;;;;; +A4BC;YI RADICAL CY;So;0;ON;;;;;N;;;;; +A4BD;YI RADICAL CUOP;So;0;ON;;;;;N;;;;; +A4BE;YI RADICAL CIP;So;0;ON;;;;;N;;;;; +A4BF;YI RADICAL HXOP;So;0;ON;;;;;N;;;;; +A4C0;YI RADICAL SHAT;So;0;ON;;;;;N;;;;; +A4C1;YI RADICAL ZUR;So;0;ON;;;;;N;;;;; +A4C2;YI RADICAL SHOP;So;0;ON;;;;;N;;;;; +A4C3;YI RADICAL CHE;So;0;ON;;;;;N;;;;; +A4C4;YI RADICAL ZZIET;So;0;ON;;;;;N;;;;; +A4C5;YI RADICAL NBIE;So;0;ON;;;;;N;;;;; +A4C6;YI RADICAL KE;So;0;ON;;;;;N;;;;; +A4D0;LISU LETTER BA;Lo;0;L;;;;;N;;;;; +A4D1;LISU LETTER PA;Lo;0;L;;;;;N;;;;; +A4D2;LISU LETTER PHA;Lo;0;L;;;;;N;;;;; +A4D3;LISU LETTER DA;Lo;0;L;;;;;N;;;;; +A4D4;LISU LETTER TA;Lo;0;L;;;;;N;;;;; +A4D5;LISU LETTER THA;Lo;0;L;;;;;N;;;;; +A4D6;LISU LETTER GA;Lo;0;L;;;;;N;;;;; +A4D7;LISU LETTER KA;Lo;0;L;;;;;N;;;;; +A4D8;LISU LETTER KHA;Lo;0;L;;;;;N;;;;; +A4D9;LISU LETTER JA;Lo;0;L;;;;;N;;;;; +A4DA;LISU LETTER CA;Lo;0;L;;;;;N;;;;; +A4DB;LISU LETTER CHA;Lo;0;L;;;;;N;;;;; +A4DC;LISU LETTER DZA;Lo;0;L;;;;;N;;;;; +A4DD;LISU LETTER TSA;Lo;0;L;;;;;N;;;;; +A4DE;LISU LETTER TSHA;Lo;0;L;;;;;N;;;;; +A4DF;LISU LETTER MA;Lo;0;L;;;;;N;;;;; +A4E0;LISU LETTER NA;Lo;0;L;;;;;N;;;;; +A4E1;LISU LETTER LA;Lo;0;L;;;;;N;;;;; +A4E2;LISU LETTER SA;Lo;0;L;;;;;N;;;;; +A4E3;LISU LETTER ZHA;Lo;0;L;;;;;N;;;;; +A4E4;LISU LETTER ZA;Lo;0;L;;;;;N;;;;; +A4E5;LISU LETTER NGA;Lo;0;L;;;;;N;;;;; +A4E6;LISU LETTER HA;Lo;0;L;;;;;N;;;;; +A4E7;LISU LETTER XA;Lo;0;L;;;;;N;;;;; +A4E8;LISU LETTER HHA;Lo;0;L;;;;;N;;;;; +A4E9;LISU LETTER FA;Lo;0;L;;;;;N;;;;; +A4EA;LISU LETTER WA;Lo;0;L;;;;;N;;;;; +A4EB;LISU LETTER SHA;Lo;0;L;;;;;N;;;;; +A4EC;LISU LETTER YA;Lo;0;L;;;;;N;;;;; +A4ED;LISU LETTER GHA;Lo;0;L;;;;;N;;;;; +A4EE;LISU LETTER A;Lo;0;L;;;;;N;;;;; +A4EF;LISU LETTER AE;Lo;0;L;;;;;N;;;;; +A4F0;LISU LETTER E;Lo;0;L;;;;;N;;;;; +A4F1;LISU LETTER EU;Lo;0;L;;;;;N;;;;; +A4F2;LISU LETTER I;Lo;0;L;;;;;N;;;;; +A4F3;LISU LETTER O;Lo;0;L;;;;;N;;;;; +A4F4;LISU LETTER U;Lo;0;L;;;;;N;;;;; +A4F5;LISU LETTER UE;Lo;0;L;;;;;N;;;;; +A4F6;LISU LETTER UH;Lo;0;L;;;;;N;;;;; +A4F7;LISU LETTER OE;Lo;0;L;;;;;N;;;;; +A4F8;LISU LETTER TONE MYA TI;Lm;0;L;;;;;N;;;;; +A4F9;LISU LETTER TONE NA PO;Lm;0;L;;;;;N;;;;; +A4FA;LISU LETTER TONE MYA CYA;Lm;0;L;;;;;N;;;;; +A4FB;LISU LETTER TONE MYA BO;Lm;0;L;;;;;N;;;;; +A4FC;LISU LETTER TONE MYA NA;Lm;0;L;;;;;N;;;;; +A4FD;LISU LETTER TONE MYA JEU;Lm;0;L;;;;;N;;;;; +A4FE;LISU PUNCTUATION COMMA;Po;0;L;;;;;N;;;;; +A4FF;LISU PUNCTUATION FULL STOP;Po;0;L;;;;;N;;;;; +A500;VAI SYLLABLE EE;Lo;0;L;;;;;N;;;;; +A501;VAI SYLLABLE EEN;Lo;0;L;;;;;N;;;;; +A502;VAI SYLLABLE HEE;Lo;0;L;;;;;N;;;;; +A503;VAI SYLLABLE WEE;Lo;0;L;;;;;N;;;;; +A504;VAI SYLLABLE WEEN;Lo;0;L;;;;;N;;;;; +A505;VAI SYLLABLE PEE;Lo;0;L;;;;;N;;;;; +A506;VAI SYLLABLE BHEE;Lo;0;L;;;;;N;;;;; +A507;VAI SYLLABLE BEE;Lo;0;L;;;;;N;;;;; +A508;VAI SYLLABLE MBEE;Lo;0;L;;;;;N;;;;; +A509;VAI SYLLABLE KPEE;Lo;0;L;;;;;N;;;;; +A50A;VAI SYLLABLE MGBEE;Lo;0;L;;;;;N;;;;; +A50B;VAI SYLLABLE GBEE;Lo;0;L;;;;;N;;;;; +A50C;VAI SYLLABLE FEE;Lo;0;L;;;;;N;;;;; +A50D;VAI SYLLABLE VEE;Lo;0;L;;;;;N;;;;; +A50E;VAI SYLLABLE TEE;Lo;0;L;;;;;N;;;;; +A50F;VAI SYLLABLE THEE;Lo;0;L;;;;;N;;;;; +A510;VAI SYLLABLE DHEE;Lo;0;L;;;;;N;;;;; +A511;VAI SYLLABLE DHHEE;Lo;0;L;;;;;N;;;;; +A512;VAI SYLLABLE LEE;Lo;0;L;;;;;N;;;;; +A513;VAI SYLLABLE REE;Lo;0;L;;;;;N;;;;; +A514;VAI SYLLABLE DEE;Lo;0;L;;;;;N;;;;; +A515;VAI SYLLABLE NDEE;Lo;0;L;;;;;N;;;;; +A516;VAI SYLLABLE SEE;Lo;0;L;;;;;N;;;;; +A517;VAI SYLLABLE SHEE;Lo;0;L;;;;;N;;;;; +A518;VAI SYLLABLE ZEE;Lo;0;L;;;;;N;;;;; +A519;VAI SYLLABLE ZHEE;Lo;0;L;;;;;N;;;;; +A51A;VAI SYLLABLE CEE;Lo;0;L;;;;;N;;;;; +A51B;VAI SYLLABLE JEE;Lo;0;L;;;;;N;;;;; +A51C;VAI SYLLABLE NJEE;Lo;0;L;;;;;N;;;;; +A51D;VAI SYLLABLE YEE;Lo;0;L;;;;;N;;;;; +A51E;VAI SYLLABLE KEE;Lo;0;L;;;;;N;;;;; +A51F;VAI SYLLABLE NGGEE;Lo;0;L;;;;;N;;;;; +A520;VAI SYLLABLE GEE;Lo;0;L;;;;;N;;;;; +A521;VAI SYLLABLE MEE;Lo;0;L;;;;;N;;;;; +A522;VAI SYLLABLE NEE;Lo;0;L;;;;;N;;;;; +A523;VAI SYLLABLE NYEE;Lo;0;L;;;;;N;;;;; +A524;VAI SYLLABLE I;Lo;0;L;;;;;N;;;;; +A525;VAI SYLLABLE IN;Lo;0;L;;;;;N;;;;; +A526;VAI SYLLABLE HI;Lo;0;L;;;;;N;;;;; +A527;VAI SYLLABLE HIN;Lo;0;L;;;;;N;;;;; +A528;VAI SYLLABLE WI;Lo;0;L;;;;;N;;;;; +A529;VAI SYLLABLE WIN;Lo;0;L;;;;;N;;;;; +A52A;VAI SYLLABLE PI;Lo;0;L;;;;;N;;;;; +A52B;VAI SYLLABLE BHI;Lo;0;L;;;;;N;;;;; +A52C;VAI SYLLABLE BI;Lo;0;L;;;;;N;;;;; +A52D;VAI SYLLABLE MBI;Lo;0;L;;;;;N;;;;; +A52E;VAI SYLLABLE KPI;Lo;0;L;;;;;N;;;;; +A52F;VAI SYLLABLE MGBI;Lo;0;L;;;;;N;;;;; +A530;VAI SYLLABLE GBI;Lo;0;L;;;;;N;;;;; +A531;VAI SYLLABLE FI;Lo;0;L;;;;;N;;;;; +A532;VAI SYLLABLE VI;Lo;0;L;;;;;N;;;;; +A533;VAI SYLLABLE TI;Lo;0;L;;;;;N;;;;; +A534;VAI SYLLABLE THI;Lo;0;L;;;;;N;;;;; +A535;VAI SYLLABLE DHI;Lo;0;L;;;;;N;;;;; +A536;VAI SYLLABLE DHHI;Lo;0;L;;;;;N;;;;; +A537;VAI SYLLABLE LI;Lo;0;L;;;;;N;;;;; +A538;VAI SYLLABLE RI;Lo;0;L;;;;;N;;;;; +A539;VAI SYLLABLE DI;Lo;0;L;;;;;N;;;;; +A53A;VAI SYLLABLE NDI;Lo;0;L;;;;;N;;;;; +A53B;VAI SYLLABLE SI;Lo;0;L;;;;;N;;;;; +A53C;VAI SYLLABLE SHI;Lo;0;L;;;;;N;;;;; +A53D;VAI SYLLABLE ZI;Lo;0;L;;;;;N;;;;; +A53E;VAI SYLLABLE ZHI;Lo;0;L;;;;;N;;;;; +A53F;VAI SYLLABLE CI;Lo;0;L;;;;;N;;;;; +A540;VAI SYLLABLE JI;Lo;0;L;;;;;N;;;;; +A541;VAI SYLLABLE NJI;Lo;0;L;;;;;N;;;;; +A542;VAI SYLLABLE YI;Lo;0;L;;;;;N;;;;; +A543;VAI SYLLABLE KI;Lo;0;L;;;;;N;;;;; +A544;VAI SYLLABLE NGGI;Lo;0;L;;;;;N;;;;; +A545;VAI SYLLABLE GI;Lo;0;L;;;;;N;;;;; +A546;VAI SYLLABLE MI;Lo;0;L;;;;;N;;;;; +A547;VAI SYLLABLE NI;Lo;0;L;;;;;N;;;;; +A548;VAI SYLLABLE NYI;Lo;0;L;;;;;N;;;;; +A549;VAI SYLLABLE A;Lo;0;L;;;;;N;;;;; +A54A;VAI SYLLABLE AN;Lo;0;L;;;;;N;;;;; +A54B;VAI SYLLABLE NGAN;Lo;0;L;;;;;N;;;;; +A54C;VAI SYLLABLE HA;Lo;0;L;;;;;N;;;;; +A54D;VAI SYLLABLE HAN;Lo;0;L;;;;;N;;;;; +A54E;VAI SYLLABLE WA;Lo;0;L;;;;;N;;;;; +A54F;VAI SYLLABLE WAN;Lo;0;L;;;;;N;;;;; +A550;VAI SYLLABLE PA;Lo;0;L;;;;;N;;;;; +A551;VAI SYLLABLE BHA;Lo;0;L;;;;;N;;;;; +A552;VAI SYLLABLE BA;Lo;0;L;;;;;N;;;;; +A553;VAI SYLLABLE MBA;Lo;0;L;;;;;N;;;;; +A554;VAI SYLLABLE KPA;Lo;0;L;;;;;N;;;;; +A555;VAI SYLLABLE KPAN;Lo;0;L;;;;;N;;;;; +A556;VAI SYLLABLE MGBA;Lo;0;L;;;;;N;;;;; +A557;VAI SYLLABLE GBA;Lo;0;L;;;;;N;;;;; +A558;VAI SYLLABLE FA;Lo;0;L;;;;;N;;;;; +A559;VAI SYLLABLE VA;Lo;0;L;;;;;N;;;;; +A55A;VAI SYLLABLE TA;Lo;0;L;;;;;N;;;;; +A55B;VAI SYLLABLE THA;Lo;0;L;;;;;N;;;;; +A55C;VAI SYLLABLE DHA;Lo;0;L;;;;;N;;;;; +A55D;VAI SYLLABLE DHHA;Lo;0;L;;;;;N;;;;; +A55E;VAI SYLLABLE LA;Lo;0;L;;;;;N;;;;; +A55F;VAI SYLLABLE RA;Lo;0;L;;;;;N;;;;; +A560;VAI SYLLABLE DA;Lo;0;L;;;;;N;;;;; +A561;VAI SYLLABLE NDA;Lo;0;L;;;;;N;;;;; +A562;VAI SYLLABLE SA;Lo;0;L;;;;;N;;;;; +A563;VAI SYLLABLE SHA;Lo;0;L;;;;;N;;;;; +A564;VAI SYLLABLE ZA;Lo;0;L;;;;;N;;;;; +A565;VAI SYLLABLE ZHA;Lo;0;L;;;;;N;;;;; +A566;VAI SYLLABLE CA;Lo;0;L;;;;;N;;;;; +A567;VAI SYLLABLE JA;Lo;0;L;;;;;N;;;;; +A568;VAI SYLLABLE NJA;Lo;0;L;;;;;N;;;;; +A569;VAI SYLLABLE YA;Lo;0;L;;;;;N;;;;; +A56A;VAI SYLLABLE KA;Lo;0;L;;;;;N;;;;; +A56B;VAI SYLLABLE KAN;Lo;0;L;;;;;N;;;;; +A56C;VAI SYLLABLE NGGA;Lo;0;L;;;;;N;;;;; +A56D;VAI SYLLABLE GA;Lo;0;L;;;;;N;;;;; +A56E;VAI SYLLABLE MA;Lo;0;L;;;;;N;;;;; +A56F;VAI SYLLABLE NA;Lo;0;L;;;;;N;;;;; +A570;VAI SYLLABLE NYA;Lo;0;L;;;;;N;;;;; +A571;VAI SYLLABLE OO;Lo;0;L;;;;;N;;;;; +A572;VAI SYLLABLE OON;Lo;0;L;;;;;N;;;;; +A573;VAI SYLLABLE HOO;Lo;0;L;;;;;N;;;;; +A574;VAI SYLLABLE WOO;Lo;0;L;;;;;N;;;;; +A575;VAI SYLLABLE WOON;Lo;0;L;;;;;N;;;;; +A576;VAI SYLLABLE POO;Lo;0;L;;;;;N;;;;; +A577;VAI SYLLABLE BHOO;Lo;0;L;;;;;N;;;;; +A578;VAI SYLLABLE BOO;Lo;0;L;;;;;N;;;;; +A579;VAI SYLLABLE MBOO;Lo;0;L;;;;;N;;;;; +A57A;VAI SYLLABLE KPOO;Lo;0;L;;;;;N;;;;; +A57B;VAI SYLLABLE MGBOO;Lo;0;L;;;;;N;;;;; +A57C;VAI SYLLABLE GBOO;Lo;0;L;;;;;N;;;;; +A57D;VAI SYLLABLE FOO;Lo;0;L;;;;;N;;;;; +A57E;VAI SYLLABLE VOO;Lo;0;L;;;;;N;;;;; +A57F;VAI SYLLABLE TOO;Lo;0;L;;;;;N;;;;; +A580;VAI SYLLABLE THOO;Lo;0;L;;;;;N;;;;; +A581;VAI SYLLABLE DHOO;Lo;0;L;;;;;N;;;;; +A582;VAI SYLLABLE DHHOO;Lo;0;L;;;;;N;;;;; +A583;VAI SYLLABLE LOO;Lo;0;L;;;;;N;;;;; +A584;VAI SYLLABLE ROO;Lo;0;L;;;;;N;;;;; +A585;VAI SYLLABLE DOO;Lo;0;L;;;;;N;;;;; +A586;VAI SYLLABLE NDOO;Lo;0;L;;;;;N;;;;; +A587;VAI SYLLABLE SOO;Lo;0;L;;;;;N;;;;; +A588;VAI SYLLABLE SHOO;Lo;0;L;;;;;N;;;;; +A589;VAI SYLLABLE ZOO;Lo;0;L;;;;;N;;;;; +A58A;VAI SYLLABLE ZHOO;Lo;0;L;;;;;N;;;;; +A58B;VAI SYLLABLE COO;Lo;0;L;;;;;N;;;;; +A58C;VAI SYLLABLE JOO;Lo;0;L;;;;;N;;;;; +A58D;VAI SYLLABLE NJOO;Lo;0;L;;;;;N;;;;; +A58E;VAI SYLLABLE YOO;Lo;0;L;;;;;N;;;;; +A58F;VAI SYLLABLE KOO;Lo;0;L;;;;;N;;;;; +A590;VAI SYLLABLE NGGOO;Lo;0;L;;;;;N;;;;; +A591;VAI SYLLABLE GOO;Lo;0;L;;;;;N;;;;; +A592;VAI SYLLABLE MOO;Lo;0;L;;;;;N;;;;; +A593;VAI SYLLABLE NOO;Lo;0;L;;;;;N;;;;; +A594;VAI SYLLABLE NYOO;Lo;0;L;;;;;N;;;;; +A595;VAI SYLLABLE U;Lo;0;L;;;;;N;;;;; +A596;VAI SYLLABLE UN;Lo;0;L;;;;;N;;;;; +A597;VAI SYLLABLE HU;Lo;0;L;;;;;N;;;;; +A598;VAI SYLLABLE HUN;Lo;0;L;;;;;N;;;;; +A599;VAI SYLLABLE WU;Lo;0;L;;;;;N;;;;; +A59A;VAI SYLLABLE WUN;Lo;0;L;;;;;N;;;;; +A59B;VAI SYLLABLE PU;Lo;0;L;;;;;N;;;;; +A59C;VAI SYLLABLE BHU;Lo;0;L;;;;;N;;;;; +A59D;VAI SYLLABLE BU;Lo;0;L;;;;;N;;;;; +A59E;VAI SYLLABLE MBU;Lo;0;L;;;;;N;;;;; +A59F;VAI SYLLABLE KPU;Lo;0;L;;;;;N;;;;; +A5A0;VAI SYLLABLE MGBU;Lo;0;L;;;;;N;;;;; +A5A1;VAI SYLLABLE GBU;Lo;0;L;;;;;N;;;;; +A5A2;VAI SYLLABLE FU;Lo;0;L;;;;;N;;;;; +A5A3;VAI SYLLABLE VU;Lo;0;L;;;;;N;;;;; +A5A4;VAI SYLLABLE TU;Lo;0;L;;;;;N;;;;; +A5A5;VAI SYLLABLE THU;Lo;0;L;;;;;N;;;;; +A5A6;VAI SYLLABLE DHU;Lo;0;L;;;;;N;;;;; +A5A7;VAI SYLLABLE DHHU;Lo;0;L;;;;;N;;;;; +A5A8;VAI SYLLABLE LU;Lo;0;L;;;;;N;;;;; +A5A9;VAI SYLLABLE RU;Lo;0;L;;;;;N;;;;; +A5AA;VAI SYLLABLE DU;Lo;0;L;;;;;N;;;;; +A5AB;VAI SYLLABLE NDU;Lo;0;L;;;;;N;;;;; +A5AC;VAI SYLLABLE SU;Lo;0;L;;;;;N;;;;; +A5AD;VAI SYLLABLE SHU;Lo;0;L;;;;;N;;;;; +A5AE;VAI SYLLABLE ZU;Lo;0;L;;;;;N;;;;; +A5AF;VAI SYLLABLE ZHU;Lo;0;L;;;;;N;;;;; +A5B0;VAI SYLLABLE CU;Lo;0;L;;;;;N;;;;; +A5B1;VAI SYLLABLE JU;Lo;0;L;;;;;N;;;;; +A5B2;VAI SYLLABLE NJU;Lo;0;L;;;;;N;;;;; +A5B3;VAI SYLLABLE YU;Lo;0;L;;;;;N;;;;; +A5B4;VAI SYLLABLE KU;Lo;0;L;;;;;N;;;;; +A5B5;VAI SYLLABLE NGGU;Lo;0;L;;;;;N;;;;; +A5B6;VAI SYLLABLE GU;Lo;0;L;;;;;N;;;;; +A5B7;VAI SYLLABLE MU;Lo;0;L;;;;;N;;;;; +A5B8;VAI SYLLABLE NU;Lo;0;L;;;;;N;;;;; +A5B9;VAI SYLLABLE NYU;Lo;0;L;;;;;N;;;;; +A5BA;VAI SYLLABLE O;Lo;0;L;;;;;N;;;;; +A5BB;VAI SYLLABLE ON;Lo;0;L;;;;;N;;;;; +A5BC;VAI SYLLABLE NGON;Lo;0;L;;;;;N;;;;; +A5BD;VAI SYLLABLE HO;Lo;0;L;;;;;N;;;;; +A5BE;VAI SYLLABLE HON;Lo;0;L;;;;;N;;;;; +A5BF;VAI SYLLABLE WO;Lo;0;L;;;;;N;;;;; +A5C0;VAI SYLLABLE WON;Lo;0;L;;;;;N;;;;; +A5C1;VAI SYLLABLE PO;Lo;0;L;;;;;N;;;;; +A5C2;VAI SYLLABLE BHO;Lo;0;L;;;;;N;;;;; +A5C3;VAI SYLLABLE BO;Lo;0;L;;;;;N;;;;; +A5C4;VAI SYLLABLE MBO;Lo;0;L;;;;;N;;;;; +A5C5;VAI SYLLABLE KPO;Lo;0;L;;;;;N;;;;; +A5C6;VAI SYLLABLE MGBO;Lo;0;L;;;;;N;;;;; +A5C7;VAI SYLLABLE GBO;Lo;0;L;;;;;N;;;;; +A5C8;VAI SYLLABLE GBON;Lo;0;L;;;;;N;;;;; +A5C9;VAI SYLLABLE FO;Lo;0;L;;;;;N;;;;; +A5CA;VAI SYLLABLE VO;Lo;0;L;;;;;N;;;;; +A5CB;VAI SYLLABLE TO;Lo;0;L;;;;;N;;;;; +A5CC;VAI SYLLABLE THO;Lo;0;L;;;;;N;;;;; +A5CD;VAI SYLLABLE DHO;Lo;0;L;;;;;N;;;;; +A5CE;VAI SYLLABLE DHHO;Lo;0;L;;;;;N;;;;; +A5CF;VAI SYLLABLE LO;Lo;0;L;;;;;N;;;;; +A5D0;VAI SYLLABLE RO;Lo;0;L;;;;;N;;;;; +A5D1;VAI SYLLABLE DO;Lo;0;L;;;;;N;;;;; +A5D2;VAI SYLLABLE NDO;Lo;0;L;;;;;N;;;;; +A5D3;VAI SYLLABLE SO;Lo;0;L;;;;;N;;;;; +A5D4;VAI SYLLABLE SHO;Lo;0;L;;;;;N;;;;; +A5D5;VAI SYLLABLE ZO;Lo;0;L;;;;;N;;;;; +A5D6;VAI SYLLABLE ZHO;Lo;0;L;;;;;N;;;;; +A5D7;VAI SYLLABLE CO;Lo;0;L;;;;;N;;;;; +A5D8;VAI SYLLABLE JO;Lo;0;L;;;;;N;;;;; +A5D9;VAI SYLLABLE NJO;Lo;0;L;;;;;N;;;;; +A5DA;VAI SYLLABLE YO;Lo;0;L;;;;;N;;;;; +A5DB;VAI SYLLABLE KO;Lo;0;L;;;;;N;;;;; +A5DC;VAI SYLLABLE NGGO;Lo;0;L;;;;;N;;;;; +A5DD;VAI SYLLABLE GO;Lo;0;L;;;;;N;;;;; +A5DE;VAI SYLLABLE MO;Lo;0;L;;;;;N;;;;; +A5DF;VAI SYLLABLE NO;Lo;0;L;;;;;N;;;;; +A5E0;VAI SYLLABLE NYO;Lo;0;L;;;;;N;;;;; +A5E1;VAI SYLLABLE E;Lo;0;L;;;;;N;;;;; +A5E2;VAI SYLLABLE EN;Lo;0;L;;;;;N;;;;; +A5E3;VAI SYLLABLE NGEN;Lo;0;L;;;;;N;;;;; +A5E4;VAI SYLLABLE HE;Lo;0;L;;;;;N;;;;; +A5E5;VAI SYLLABLE HEN;Lo;0;L;;;;;N;;;;; +A5E6;VAI SYLLABLE WE;Lo;0;L;;;;;N;;;;; +A5E7;VAI SYLLABLE WEN;Lo;0;L;;;;;N;;;;; +A5E8;VAI SYLLABLE PE;Lo;0;L;;;;;N;;;;; +A5E9;VAI SYLLABLE BHE;Lo;0;L;;;;;N;;;;; +A5EA;VAI SYLLABLE BE;Lo;0;L;;;;;N;;;;; +A5EB;VAI SYLLABLE MBE;Lo;0;L;;;;;N;;;;; +A5EC;VAI SYLLABLE KPE;Lo;0;L;;;;;N;;;;; +A5ED;VAI SYLLABLE KPEN;Lo;0;L;;;;;N;;;;; +A5EE;VAI SYLLABLE MGBE;Lo;0;L;;;;;N;;;;; +A5EF;VAI SYLLABLE GBE;Lo;0;L;;;;;N;;;;; +A5F0;VAI SYLLABLE GBEN;Lo;0;L;;;;;N;;;;; +A5F1;VAI SYLLABLE FE;Lo;0;L;;;;;N;;;;; +A5F2;VAI SYLLABLE VE;Lo;0;L;;;;;N;;;;; +A5F3;VAI SYLLABLE TE;Lo;0;L;;;;;N;;;;; +A5F4;VAI SYLLABLE THE;Lo;0;L;;;;;N;;;;; +A5F5;VAI SYLLABLE DHE;Lo;0;L;;;;;N;;;;; +A5F6;VAI SYLLABLE DHHE;Lo;0;L;;;;;N;;;;; +A5F7;VAI SYLLABLE LE;Lo;0;L;;;;;N;;;;; +A5F8;VAI SYLLABLE RE;Lo;0;L;;;;;N;;;;; +A5F9;VAI SYLLABLE DE;Lo;0;L;;;;;N;;;;; +A5FA;VAI SYLLABLE NDE;Lo;0;L;;;;;N;;;;; +A5FB;VAI SYLLABLE SE;Lo;0;L;;;;;N;;;;; +A5FC;VAI SYLLABLE SHE;Lo;0;L;;;;;N;;;;; +A5FD;VAI SYLLABLE ZE;Lo;0;L;;;;;N;;;;; +A5FE;VAI SYLLABLE ZHE;Lo;0;L;;;;;N;;;;; +A5FF;VAI SYLLABLE CE;Lo;0;L;;;;;N;;;;; +A600;VAI SYLLABLE JE;Lo;0;L;;;;;N;;;;; +A601;VAI SYLLABLE NJE;Lo;0;L;;;;;N;;;;; +A602;VAI SYLLABLE YE;Lo;0;L;;;;;N;;;;; +A603;VAI SYLLABLE KE;Lo;0;L;;;;;N;;;;; +A604;VAI SYLLABLE NGGE;Lo;0;L;;;;;N;;;;; +A605;VAI SYLLABLE NGGEN;Lo;0;L;;;;;N;;;;; +A606;VAI SYLLABLE GE;Lo;0;L;;;;;N;;;;; +A607;VAI SYLLABLE GEN;Lo;0;L;;;;;N;;;;; +A608;VAI SYLLABLE ME;Lo;0;L;;;;;N;;;;; +A609;VAI SYLLABLE NE;Lo;0;L;;;;;N;;;;; +A60A;VAI SYLLABLE NYE;Lo;0;L;;;;;N;;;;; +A60B;VAI SYLLABLE NG;Lo;0;L;;;;;N;;;;; +A60C;VAI SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; +A60D;VAI COMMA;Po;0;ON;;;;;N;;;;; +A60E;VAI FULL STOP;Po;0;ON;;;;;N;;;;; +A60F;VAI QUESTION MARK;Po;0;ON;;;;;N;;;;; +A610;VAI SYLLABLE NDOLE FA;Lo;0;L;;;;;N;;;;; +A611;VAI SYLLABLE NDOLE KA;Lo;0;L;;;;;N;;;;; +A612;VAI SYLLABLE NDOLE SOO;Lo;0;L;;;;;N;;;;; +A613;VAI SYMBOL FEENG;Lo;0;L;;;;;N;;;;; +A614;VAI SYMBOL KEENG;Lo;0;L;;;;;N;;;;; +A615;VAI SYMBOL TING;Lo;0;L;;;;;N;;;;; +A616;VAI SYMBOL NII;Lo;0;L;;;;;N;;;;; +A617;VAI SYMBOL BANG;Lo;0;L;;;;;N;;;;; +A618;VAI SYMBOL FAA;Lo;0;L;;;;;N;;;;; +A619;VAI SYMBOL TAA;Lo;0;L;;;;;N;;;;; +A61A;VAI SYMBOL DANG;Lo;0;L;;;;;N;;;;; +A61B;VAI SYMBOL DOONG;Lo;0;L;;;;;N;;;;; +A61C;VAI SYMBOL KUNG;Lo;0;L;;;;;N;;;;; +A61D;VAI SYMBOL TONG;Lo;0;L;;;;;N;;;;; +A61E;VAI SYMBOL DO-O;Lo;0;L;;;;;N;;;;; +A61F;VAI SYMBOL JONG;Lo;0;L;;;;;N;;;;; +A620;VAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A621;VAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A622;VAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A623;VAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A624;VAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A625;VAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A626;VAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A627;VAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A628;VAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A629;VAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A62A;VAI SYLLABLE NDOLE MA;Lo;0;L;;;;;N;;;;; +A62B;VAI SYLLABLE NDOLE DO;Lo;0;L;;;;;N;;;;; +A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; +A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 +A642;CYRILLIC CAPITAL LETTER DZELO;Lu;0;L;;;;;N;;;;A643; +A643;CYRILLIC SMALL LETTER DZELO;Ll;0;L;;;;;N;;;A642;;A642 +A644;CYRILLIC CAPITAL LETTER REVERSED DZE;Lu;0;L;;;;;N;;;;A645; +A645;CYRILLIC SMALL LETTER REVERSED DZE;Ll;0;L;;;;;N;;;A644;;A644 +A646;CYRILLIC CAPITAL LETTER IOTA;Lu;0;L;;;;;N;;;;A647; +A647;CYRILLIC SMALL LETTER IOTA;Ll;0;L;;;;;N;;;A646;;A646 +A648;CYRILLIC CAPITAL LETTER DJERV;Lu;0;L;;;;;N;;;;A649; +A649;CYRILLIC SMALL LETTER DJERV;Ll;0;L;;;;;N;;;A648;;A648 +A64A;CYRILLIC CAPITAL LETTER MONOGRAPH UK;Lu;0;L;;;;;N;;;;A64B; +A64B;CYRILLIC SMALL LETTER MONOGRAPH UK;Ll;0;L;;;;;N;;;A64A;;A64A +A64C;CYRILLIC CAPITAL LETTER BROAD OMEGA;Lu;0;L;;;;;N;;;;A64D; +A64D;CYRILLIC SMALL LETTER BROAD OMEGA;Ll;0;L;;;;;N;;;A64C;;A64C +A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; +A64F;CYRILLIC SMALL LETTER NEUTRAL YER;Ll;0;L;;;;;N;;;A64E;;A64E +A650;CYRILLIC CAPITAL LETTER YERU WITH BACK YER;Lu;0;L;;;;;N;;;;A651; +A651;CYRILLIC SMALL LETTER YERU WITH BACK YER;Ll;0;L;;;;;N;;;A650;;A650 +A652;CYRILLIC CAPITAL LETTER IOTIFIED YAT;Lu;0;L;;;;;N;;;;A653; +A653;CYRILLIC SMALL LETTER IOTIFIED YAT;Ll;0;L;;;;;N;;;A652;;A652 +A654;CYRILLIC CAPITAL LETTER REVERSED YU;Lu;0;L;;;;;N;;;;A655; +A655;CYRILLIC SMALL LETTER REVERSED YU;Ll;0;L;;;;;N;;;A654;;A654 +A656;CYRILLIC CAPITAL LETTER IOTIFIED A;Lu;0;L;;;;;N;;;;A657; +A657;CYRILLIC SMALL LETTER IOTIFIED A;Ll;0;L;;;;;N;;;A656;;A656 +A658;CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A659; +A659;CYRILLIC SMALL LETTER CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A658;;A658 +A65A;CYRILLIC CAPITAL LETTER BLENDED YUS;Lu;0;L;;;;;N;;;;A65B; +A65B;CYRILLIC SMALL LETTER BLENDED YUS;Ll;0;L;;;;;N;;;A65A;;A65A +A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; +A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C +A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; +A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E +A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661; +A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660 +A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; +A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 +A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; +A665;CYRILLIC SMALL LETTER SOFT EL;Ll;0;L;;;;;N;;;A664;;A664 +A666;CYRILLIC CAPITAL LETTER SOFT EM;Lu;0;L;;;;;N;;;;A667; +A667;CYRILLIC SMALL LETTER SOFT EM;Ll;0;L;;;;;N;;;A666;;A666 +A668;CYRILLIC CAPITAL LETTER MONOCULAR O;Lu;0;L;;;;;N;;;;A669; +A669;CYRILLIC SMALL LETTER MONOCULAR O;Ll;0;L;;;;;N;;;A668;;A668 +A66A;CYRILLIC CAPITAL LETTER BINOCULAR O;Lu;0;L;;;;;N;;;;A66B; +A66B;CYRILLIC SMALL LETTER BINOCULAR O;Ll;0;L;;;;;N;;;A66A;;A66A +A66C;CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O;Lu;0;L;;;;;N;;;;A66D; +A66D;CYRILLIC SMALL LETTER DOUBLE MONOCULAR O;Ll;0;L;;;;;N;;;A66C;;A66C +A66E;CYRILLIC LETTER MULTIOCULAR O;Lo;0;L;;;;;N;;;;; +A66F;COMBINING CYRILLIC VZMET;Mn;230;NSM;;;;;N;;;;; +A670;COMBINING CYRILLIC TEN MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A671;COMBINING CYRILLIC HUNDRED MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A672;COMBINING CYRILLIC THOUSAND MILLIONS SIGN;Me;0;NSM;;;;;N;;;;; +A673;SLAVONIC ASTERISK;Po;0;ON;;;;;N;;;;; +A674;COMBINING CYRILLIC LETTER UKRAINIAN IE;Mn;230;NSM;;;;;N;;;;; +A675;COMBINING CYRILLIC LETTER I;Mn;230;NSM;;;;;N;;;;; +A676;COMBINING CYRILLIC LETTER YI;Mn;230;NSM;;;;;N;;;;; +A677;COMBINING CYRILLIC LETTER U;Mn;230;NSM;;;;;N;;;;; +A678;COMBINING CYRILLIC LETTER HARD SIGN;Mn;230;NSM;;;;;N;;;;; +A679;COMBINING CYRILLIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; +A67A;COMBINING CYRILLIC LETTER SOFT SIGN;Mn;230;NSM;;;;;N;;;;; +A67B;COMBINING CYRILLIC LETTER OMEGA;Mn;230;NSM;;;;;N;;;;; +A67C;COMBINING CYRILLIC KAVYKA;Mn;230;NSM;;;;;N;;;;; +A67D;COMBINING CYRILLIC PAYEROK;Mn;230;NSM;;;;;N;;;;; +A67E;CYRILLIC KAVYKA;Po;0;ON;;;;;N;;;;; +A67F;CYRILLIC PAYEROK;Lm;0;ON;;;;;N;;;;; +A680;CYRILLIC CAPITAL LETTER DWE;Lu;0;L;;;;;N;;;;A681; +A681;CYRILLIC SMALL LETTER DWE;Ll;0;L;;;;;N;;;A680;;A680 +A682;CYRILLIC CAPITAL LETTER DZWE;Lu;0;L;;;;;N;;;;A683; +A683;CYRILLIC SMALL LETTER DZWE;Ll;0;L;;;;;N;;;A682;;A682 +A684;CYRILLIC CAPITAL LETTER ZHWE;Lu;0;L;;;;;N;;;;A685; +A685;CYRILLIC SMALL LETTER ZHWE;Ll;0;L;;;;;N;;;A684;;A684 +A686;CYRILLIC CAPITAL LETTER CCHE;Lu;0;L;;;;;N;;;;A687; +A687;CYRILLIC SMALL LETTER CCHE;Ll;0;L;;;;;N;;;A686;;A686 +A688;CYRILLIC CAPITAL LETTER DZZE;Lu;0;L;;;;;N;;;;A689; +A689;CYRILLIC SMALL LETTER DZZE;Ll;0;L;;;;;N;;;A688;;A688 +A68A;CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK;Lu;0;L;;;;;N;;;;A68B; +A68B;CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;A68A;;A68A +A68C;CYRILLIC CAPITAL LETTER TWE;Lu;0;L;;;;;N;;;;A68D; +A68D;CYRILLIC SMALL LETTER TWE;Ll;0;L;;;;;N;;;A68C;;A68C +A68E;CYRILLIC CAPITAL LETTER TSWE;Lu;0;L;;;;;N;;;;A68F; +A68F;CYRILLIC SMALL LETTER TSWE;Ll;0;L;;;;;N;;;A68E;;A68E +A690;CYRILLIC CAPITAL LETTER TSSE;Lu;0;L;;;;;N;;;;A691; +A691;CYRILLIC SMALL LETTER TSSE;Ll;0;L;;;;;N;;;A690;;A690 +A692;CYRILLIC CAPITAL LETTER TCHE;Lu;0;L;;;;;N;;;;A693; +A693;CYRILLIC SMALL LETTER TCHE;Ll;0;L;;;;;N;;;A692;;A692 +A694;CYRILLIC CAPITAL LETTER HWE;Lu;0;L;;;;;N;;;;A695; +A695;CYRILLIC SMALL LETTER HWE;Ll;0;L;;;;;N;;;A694;;A694 +A696;CYRILLIC CAPITAL LETTER SHWE;Lu;0;L;;;;;N;;;;A697; +A697;CYRILLIC SMALL LETTER SHWE;Ll;0;L;;;;;N;;;A696;;A696 +A698;CYRILLIC CAPITAL LETTER DOUBLE O;Lu;0;L;;;;;N;;;;A699; +A699;CYRILLIC SMALL LETTER DOUBLE O;Ll;0;L;;;;;N;;;A698;;A698 +A69A;CYRILLIC CAPITAL LETTER CROSSED O;Lu;0;L;;;;;N;;;;A69B; +A69B;CYRILLIC SMALL LETTER CROSSED O;Ll;0;L;;;;;N;;;A69A;;A69A +A69C;MODIFIER LETTER CYRILLIC HARD SIGN;Lm;0;L; 044A;;;;N;;;;; +A69D;MODIFIER LETTER CYRILLIC SOFT SIGN;Lm;0;L; 044C;;;;N;;;;; +A69E;COMBINING CYRILLIC LETTER EF;Mn;230;NSM;;;;;N;;;;; +A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;; +A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;; +A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;; +A6A2;BAMUM LETTER U;Lo;0;L;;;;;N;;;;; +A6A3;BAMUM LETTER KU;Lo;0;L;;;;;N;;;;; +A6A4;BAMUM LETTER EE;Lo;0;L;;;;;N;;;;; +A6A5;BAMUM LETTER REE;Lo;0;L;;;;;N;;;;; +A6A6;BAMUM LETTER TAE;Lo;0;L;;;;;N;;;;; +A6A7;BAMUM LETTER O;Lo;0;L;;;;;N;;;;; +A6A8;BAMUM LETTER NYI;Lo;0;L;;;;;N;;;;; +A6A9;BAMUM LETTER I;Lo;0;L;;;;;N;;;;; +A6AA;BAMUM LETTER LA;Lo;0;L;;;;;N;;;;; +A6AB;BAMUM LETTER PA;Lo;0;L;;;;;N;;;;; +A6AC;BAMUM LETTER RII;Lo;0;L;;;;;N;;;;; +A6AD;BAMUM LETTER RIEE;Lo;0;L;;;;;N;;;;; +A6AE;BAMUM LETTER LEEEE;Lo;0;L;;;;;N;;;;; +A6AF;BAMUM LETTER MEEEE;Lo;0;L;;;;;N;;;;; +A6B0;BAMUM LETTER TAA;Lo;0;L;;;;;N;;;;; +A6B1;BAMUM LETTER NDAA;Lo;0;L;;;;;N;;;;; +A6B2;BAMUM LETTER NJAEM;Lo;0;L;;;;;N;;;;; +A6B3;BAMUM LETTER M;Lo;0;L;;;;;N;;;;; +A6B4;BAMUM LETTER SUU;Lo;0;L;;;;;N;;;;; +A6B5;BAMUM LETTER MU;Lo;0;L;;;;;N;;;;; +A6B6;BAMUM LETTER SHII;Lo;0;L;;;;;N;;;;; +A6B7;BAMUM LETTER SI;Lo;0;L;;;;;N;;;;; +A6B8;BAMUM LETTER SHEUX;Lo;0;L;;;;;N;;;;; +A6B9;BAMUM LETTER SEUX;Lo;0;L;;;;;N;;;;; +A6BA;BAMUM LETTER KYEE;Lo;0;L;;;;;N;;;;; +A6BB;BAMUM LETTER KET;Lo;0;L;;;;;N;;;;; +A6BC;BAMUM LETTER NUAE;Lo;0;L;;;;;N;;;;; +A6BD;BAMUM LETTER NU;Lo;0;L;;;;;N;;;;; +A6BE;BAMUM LETTER NJUAE;Lo;0;L;;;;;N;;;;; +A6BF;BAMUM LETTER YOQ;Lo;0;L;;;;;N;;;;; +A6C0;BAMUM LETTER SHU;Lo;0;L;;;;;N;;;;; +A6C1;BAMUM LETTER YUQ;Lo;0;L;;;;;N;;;;; +A6C2;BAMUM LETTER YA;Lo;0;L;;;;;N;;;;; +A6C3;BAMUM LETTER NSHA;Lo;0;L;;;;;N;;;;; +A6C4;BAMUM LETTER KEUX;Lo;0;L;;;;;N;;;;; +A6C5;BAMUM LETTER PEUX;Lo;0;L;;;;;N;;;;; +A6C6;BAMUM LETTER NJEE;Lo;0;L;;;;;N;;;;; +A6C7;BAMUM LETTER NTEE;Lo;0;L;;;;;N;;;;; +A6C8;BAMUM LETTER PUE;Lo;0;L;;;;;N;;;;; +A6C9;BAMUM LETTER WUE;Lo;0;L;;;;;N;;;;; +A6CA;BAMUM LETTER PEE;Lo;0;L;;;;;N;;;;; +A6CB;BAMUM LETTER FEE;Lo;0;L;;;;;N;;;;; +A6CC;BAMUM LETTER RU;Lo;0;L;;;;;N;;;;; +A6CD;BAMUM LETTER LU;Lo;0;L;;;;;N;;;;; +A6CE;BAMUM LETTER MI;Lo;0;L;;;;;N;;;;; +A6CF;BAMUM LETTER NI;Lo;0;L;;;;;N;;;;; +A6D0;BAMUM LETTER REUX;Lo;0;L;;;;;N;;;;; +A6D1;BAMUM LETTER RAE;Lo;0;L;;;;;N;;;;; +A6D2;BAMUM LETTER KEN;Lo;0;L;;;;;N;;;;; +A6D3;BAMUM LETTER NGKWAEN;Lo;0;L;;;;;N;;;;; +A6D4;BAMUM LETTER NGGA;Lo;0;L;;;;;N;;;;; +A6D5;BAMUM LETTER NGA;Lo;0;L;;;;;N;;;;; +A6D6;BAMUM LETTER SHO;Lo;0;L;;;;;N;;;;; +A6D7;BAMUM LETTER PUAE;Lo;0;L;;;;;N;;;;; +A6D8;BAMUM LETTER FU;Lo;0;L;;;;;N;;;;; +A6D9;BAMUM LETTER FOM;Lo;0;L;;;;;N;;;;; +A6DA;BAMUM LETTER WA;Lo;0;L;;;;;N;;;;; +A6DB;BAMUM LETTER NA;Lo;0;L;;;;;N;;;;; +A6DC;BAMUM LETTER LI;Lo;0;L;;;;;N;;;;; +A6DD;BAMUM LETTER PI;Lo;0;L;;;;;N;;;;; +A6DE;BAMUM LETTER LOQ;Lo;0;L;;;;;N;;;;; +A6DF;BAMUM LETTER KO;Lo;0;L;;;;;N;;;;; +A6E0;BAMUM LETTER MBEN;Lo;0;L;;;;;N;;;;; +A6E1;BAMUM LETTER REN;Lo;0;L;;;;;N;;;;; +A6E2;BAMUM LETTER MEN;Lo;0;L;;;;;N;;;;; +A6E3;BAMUM LETTER MA;Lo;0;L;;;;;N;;;;; +A6E4;BAMUM LETTER TI;Lo;0;L;;;;;N;;;;; +A6E5;BAMUM LETTER KI;Lo;0;L;;;;;N;;;;; +A6E6;BAMUM LETTER MO;Nl;0;L;;;;1;N;;;;; +A6E7;BAMUM LETTER MBAA;Nl;0;L;;;;2;N;;;;; +A6E8;BAMUM LETTER TET;Nl;0;L;;;;3;N;;;;; +A6E9;BAMUM LETTER KPA;Nl;0;L;;;;4;N;;;;; +A6EA;BAMUM LETTER TEN;Nl;0;L;;;;5;N;;;;; +A6EB;BAMUM LETTER NTUU;Nl;0;L;;;;6;N;;;;; +A6EC;BAMUM LETTER SAMBA;Nl;0;L;;;;7;N;;;;; +A6ED;BAMUM LETTER FAAMAE;Nl;0;L;;;;8;N;;;;; +A6EE;BAMUM LETTER KOVUU;Nl;0;L;;;;9;N;;;;; +A6EF;BAMUM LETTER KOGHOM;Nl;0;L;;;;0;N;;;;; +A6F0;BAMUM COMBINING MARK KOQNDON;Mn;230;NSM;;;;;N;;;;; +A6F1;BAMUM COMBINING MARK TUKWENTIS;Mn;230;NSM;;;;;N;;;;; +A6F2;BAMUM NJAEMLI;Po;0;L;;;;;N;;;;; +A6F3;BAMUM FULL STOP;Po;0;L;;;;;N;;;;; +A6F4;BAMUM COLON;Po;0;L;;;;;N;;;;; +A6F5;BAMUM COMMA;Po;0;L;;;;;N;;;;; +A6F6;BAMUM SEMICOLON;Po;0;L;;;;;N;;;;; +A6F7;BAMUM QUESTION MARK;Po;0;L;;;;;N;;;;; +A700;MODIFIER LETTER CHINESE TONE YIN PING;Sk;0;ON;;;;;N;;;;; +A701;MODIFIER LETTER CHINESE TONE YANG PING;Sk;0;ON;;;;;N;;;;; +A702;MODIFIER LETTER CHINESE TONE YIN SHANG;Sk;0;ON;;;;;N;;;;; +A703;MODIFIER LETTER CHINESE TONE YANG SHANG;Sk;0;ON;;;;;N;;;;; +A704;MODIFIER LETTER CHINESE TONE YIN QU;Sk;0;ON;;;;;N;;;;; +A705;MODIFIER LETTER CHINESE TONE YANG QU;Sk;0;ON;;;;;N;;;;; +A706;MODIFIER LETTER CHINESE TONE YIN RU;Sk;0;ON;;;;;N;;;;; +A707;MODIFIER LETTER CHINESE TONE YANG RU;Sk;0;ON;;;;;N;;;;; +A708;MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A709;MODIFIER LETTER HIGH DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70A;MODIFIER LETTER MID DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70B;MODIFIER LETTER LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70C;MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR;Sk;0;ON;;;;;N;;;;; +A70D;MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A70E;MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A70F;MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A710;MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A711;MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A712;MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A713;MODIFIER LETTER HIGH LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A714;MODIFIER LETTER MID LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A715;MODIFIER LETTER LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A716;MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR;Sk;0;ON;;;;;N;;;;; +A717;MODIFIER LETTER DOT VERTICAL BAR;Lm;0;ON;;;;;N;;;;; +A718;MODIFIER LETTER DOT SLASH;Lm;0;ON;;;;;N;;;;; +A719;MODIFIER LETTER DOT HORIZONTAL BAR;Lm;0;ON;;;;;N;;;;; +A71A;MODIFIER LETTER LOWER RIGHT CORNER ANGLE;Lm;0;ON;;;;;N;;;;; +A71B;MODIFIER LETTER RAISED UP ARROW;Lm;0;ON;;;;;N;;;;; +A71C;MODIFIER LETTER RAISED DOWN ARROW;Lm;0;ON;;;;;N;;;;; +A71D;MODIFIER LETTER RAISED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A71E;MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A71F;MODIFIER LETTER LOW INVERTED EXCLAMATION MARK;Lm;0;ON;;;;;N;;;;; +A720;MODIFIER LETTER STRESS AND HIGH TONE;Sk;0;ON;;;;;N;;;;; +A721;MODIFIER LETTER STRESS AND LOW TONE;Sk;0;ON;;;;;N;;;;; +A722;LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF;Lu;0;L;;;;;N;;;;A723; +A723;LATIN SMALL LETTER EGYPTOLOGICAL ALEF;Ll;0;L;;;;;N;;;A722;;A722 +A724;LATIN CAPITAL LETTER EGYPTOLOGICAL AIN;Lu;0;L;;;;;N;;;;A725; +A725;LATIN SMALL LETTER EGYPTOLOGICAL AIN;Ll;0;L;;;;;N;;;A724;;A724 +A726;LATIN CAPITAL LETTER HENG;Lu;0;L;;;;;N;;;;A727; +A727;LATIN SMALL LETTER HENG;Ll;0;L;;;;;N;;;A726;;A726 +A728;LATIN CAPITAL LETTER TZ;Lu;0;L;;;;;N;;;;A729; +A729;LATIN SMALL LETTER TZ;Ll;0;L;;;;;N;;;A728;;A728 +A72A;LATIN CAPITAL LETTER TRESILLO;Lu;0;L;;;;;N;;;;A72B; +A72B;LATIN SMALL LETTER TRESILLO;Ll;0;L;;;;;N;;;A72A;;A72A +A72C;LATIN CAPITAL LETTER CUATRILLO;Lu;0;L;;;;;N;;;;A72D; +A72D;LATIN SMALL LETTER CUATRILLO;Ll;0;L;;;;;N;;;A72C;;A72C +A72E;LATIN CAPITAL LETTER CUATRILLO WITH COMMA;Lu;0;L;;;;;N;;;;A72F; +A72F;LATIN SMALL LETTER CUATRILLO WITH COMMA;Ll;0;L;;;;;N;;;A72E;;A72E +A730;LATIN LETTER SMALL CAPITAL F;Ll;0;L;;;;;N;;;;; +A731;LATIN LETTER SMALL CAPITAL S;Ll;0;L;;;;;N;;;;; +A732;LATIN CAPITAL LETTER AA;Lu;0;L;;;;;N;;;;A733; +A733;LATIN SMALL LETTER AA;Ll;0;L;;;;;N;;;A732;;A732 +A734;LATIN CAPITAL LETTER AO;Lu;0;L;;;;;N;;;;A735; +A735;LATIN SMALL LETTER AO;Ll;0;L;;;;;N;;;A734;;A734 +A736;LATIN CAPITAL LETTER AU;Lu;0;L;;;;;N;;;;A737; +A737;LATIN SMALL LETTER AU;Ll;0;L;;;;;N;;;A736;;A736 +A738;LATIN CAPITAL LETTER AV;Lu;0;L;;;;;N;;;;A739; +A739;LATIN SMALL LETTER AV;Ll;0;L;;;;;N;;;A738;;A738 +A73A;LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR;Lu;0;L;;;;;N;;;;A73B; +A73B;LATIN SMALL LETTER AV WITH HORIZONTAL BAR;Ll;0;L;;;;;N;;;A73A;;A73A +A73C;LATIN CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;A73D; +A73D;LATIN SMALL LETTER AY;Ll;0;L;;;;;N;;;A73C;;A73C +A73E;LATIN CAPITAL LETTER REVERSED C WITH DOT;Lu;0;L;;;;;N;;;;A73F; +A73F;LATIN SMALL LETTER REVERSED C WITH DOT;Ll;0;L;;;;;N;;;A73E;;A73E +A740;LATIN CAPITAL LETTER K WITH STROKE;Lu;0;L;;;;;N;;;;A741; +A741;LATIN SMALL LETTER K WITH STROKE;Ll;0;L;;;;;N;;;A740;;A740 +A742;LATIN CAPITAL LETTER K WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A743; +A743;LATIN SMALL LETTER K WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A742;;A742 +A744;LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A745; +A745;LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE;Ll;0;L;;;;;N;;;A744;;A744 +A746;LATIN CAPITAL LETTER BROKEN L;Lu;0;L;;;;;N;;;;A747; +A747;LATIN SMALL LETTER BROKEN L;Ll;0;L;;;;;N;;;A746;;A746 +A748;LATIN CAPITAL LETTER L WITH HIGH STROKE;Lu;0;L;;;;;N;;;;A749; +A749;LATIN SMALL LETTER L WITH HIGH STROKE;Ll;0;L;;;;;N;;;A748;;A748 +A74A;LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY;Lu;0;L;;;;;N;;;;A74B; +A74B;LATIN SMALL LETTER O WITH LONG STROKE OVERLAY;Ll;0;L;;;;;N;;;A74A;;A74A +A74C;LATIN CAPITAL LETTER O WITH LOOP;Lu;0;L;;;;;N;;;;A74D; +A74D;LATIN SMALL LETTER O WITH LOOP;Ll;0;L;;;;;N;;;A74C;;A74C +A74E;LATIN CAPITAL LETTER OO;Lu;0;L;;;;;N;;;;A74F; +A74F;LATIN SMALL LETTER OO;Ll;0;L;;;;;N;;;A74E;;A74E +A750;LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A751; +A751;LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A750;;A750 +A752;LATIN CAPITAL LETTER P WITH FLOURISH;Lu;0;L;;;;;N;;;;A753; +A753;LATIN SMALL LETTER P WITH FLOURISH;Ll;0;L;;;;;N;;;A752;;A752 +A754;LATIN CAPITAL LETTER P WITH SQUIRREL TAIL;Lu;0;L;;;;;N;;;;A755; +A755;LATIN SMALL LETTER P WITH SQUIRREL TAIL;Ll;0;L;;;;;N;;;A754;;A754 +A756;LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A757; +A757;LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A756;;A756 +A758;LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A759; +A759;LATIN SMALL LETTER Q WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A758;;A758 +A75A;LATIN CAPITAL LETTER R ROTUNDA;Lu;0;L;;;;;N;;;;A75B; +A75B;LATIN SMALL LETTER R ROTUNDA;Ll;0;L;;;;;N;;;A75A;;A75A +A75C;LATIN CAPITAL LETTER RUM ROTUNDA;Lu;0;L;;;;;N;;;;A75D; +A75D;LATIN SMALL LETTER RUM ROTUNDA;Ll;0;L;;;;;N;;;A75C;;A75C +A75E;LATIN CAPITAL LETTER V WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A75F; +A75F;LATIN SMALL LETTER V WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A75E;;A75E +A760;LATIN CAPITAL LETTER VY;Lu;0;L;;;;;N;;;;A761; +A761;LATIN SMALL LETTER VY;Ll;0;L;;;;;N;;;A760;;A760 +A762;LATIN CAPITAL LETTER VISIGOTHIC Z;Lu;0;L;;;;;N;;;;A763; +A763;LATIN SMALL LETTER VISIGOTHIC Z;Ll;0;L;;;;;N;;;A762;;A762 +A764;LATIN CAPITAL LETTER THORN WITH STROKE;Lu;0;L;;;;;N;;;;A765; +A765;LATIN SMALL LETTER THORN WITH STROKE;Ll;0;L;;;;;N;;;A764;;A764 +A766;LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER;Lu;0;L;;;;;N;;;;A767; +A767;LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER;Ll;0;L;;;;;N;;;A766;;A766 +A768;LATIN CAPITAL LETTER VEND;Lu;0;L;;;;;N;;;;A769; +A769;LATIN SMALL LETTER VEND;Ll;0;L;;;;;N;;;A768;;A768 +A76A;LATIN CAPITAL LETTER ET;Lu;0;L;;;;;N;;;;A76B; +A76B;LATIN SMALL LETTER ET;Ll;0;L;;;;;N;;;A76A;;A76A +A76C;LATIN CAPITAL LETTER IS;Lu;0;L;;;;;N;;;;A76D; +A76D;LATIN SMALL LETTER IS;Ll;0;L;;;;;N;;;A76C;;A76C +A76E;LATIN CAPITAL LETTER CON;Lu;0;L;;;;;N;;;;A76F; +A76F;LATIN SMALL LETTER CON;Ll;0;L;;;;;N;;;A76E;;A76E +A770;MODIFIER LETTER US;Lm;0;L; A76F;;;;N;;;;; +A771;LATIN SMALL LETTER DUM;Ll;0;L;;;;;N;;;;; +A772;LATIN SMALL LETTER LUM;Ll;0;L;;;;;N;;;;; +A773;LATIN SMALL LETTER MUM;Ll;0;L;;;;;N;;;;; +A774;LATIN SMALL LETTER NUM;Ll;0;L;;;;;N;;;;; +A775;LATIN SMALL LETTER RUM;Ll;0;L;;;;;N;;;;; +A776;LATIN LETTER SMALL CAPITAL RUM;Ll;0;L;;;;;N;;;;; +A777;LATIN SMALL LETTER TUM;Ll;0;L;;;;;N;;;;; +A778;LATIN SMALL LETTER UM;Ll;0;L;;;;;N;;;;; +A779;LATIN CAPITAL LETTER INSULAR D;Lu;0;L;;;;;N;;;;A77A; +A77A;LATIN SMALL LETTER INSULAR D;Ll;0;L;;;;;N;;;A779;;A779 +A77B;LATIN CAPITAL LETTER INSULAR F;Lu;0;L;;;;;N;;;;A77C; +A77C;LATIN SMALL LETTER INSULAR F;Ll;0;L;;;;;N;;;A77B;;A77B +A77D;LATIN CAPITAL LETTER INSULAR G;Lu;0;L;;;;;N;;;;1D79; +A77E;LATIN CAPITAL LETTER TURNED INSULAR G;Lu;0;L;;;;;N;;;;A77F; +A77F;LATIN SMALL LETTER TURNED INSULAR G;Ll;0;L;;;;;N;;;A77E;;A77E +A780;LATIN CAPITAL LETTER TURNED L;Lu;0;L;;;;;N;;;;A781; +A781;LATIN SMALL LETTER TURNED L;Ll;0;L;;;;;N;;;A780;;A780 +A782;LATIN CAPITAL LETTER INSULAR R;Lu;0;L;;;;;N;;;;A783; +A783;LATIN SMALL LETTER INSULAR R;Ll;0;L;;;;;N;;;A782;;A782 +A784;LATIN CAPITAL LETTER INSULAR S;Lu;0;L;;;;;N;;;;A785; +A785;LATIN SMALL LETTER INSULAR S;Ll;0;L;;;;;N;;;A784;;A784 +A786;LATIN CAPITAL LETTER INSULAR T;Lu;0;L;;;;;N;;;;A787; +A787;LATIN SMALL LETTER INSULAR T;Ll;0;L;;;;;N;;;A786;;A786 +A788;MODIFIER LETTER LOW CIRCUMFLEX ACCENT;Lm;0;ON;;;;;N;;;;; +A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; +A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; +A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; +A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B +A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265; +A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;; +A78F;LATIN LETTER SINOLOGICAL DOT;Lo;0;L;;;;;N;;;;; +A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791; +A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790 +A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793; +A793;LATIN SMALL LETTER C WITH BAR;Ll;0;L;;;;;N;;;A792;;A792 +A794;LATIN SMALL LETTER C WITH PALATAL HOOK;Ll;0;L;;;;;N;;;A7C4;;A7C4 +A795;LATIN SMALL LETTER H WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +A796;LATIN CAPITAL LETTER B WITH FLOURISH;Lu;0;L;;;;;N;;;;A797; +A797;LATIN SMALL LETTER B WITH FLOURISH;Ll;0;L;;;;;N;;;A796;;A796 +A798;LATIN CAPITAL LETTER F WITH STROKE;Lu;0;L;;;;;N;;;;A799; +A799;LATIN SMALL LETTER F WITH STROKE;Ll;0;L;;;;;N;;;A798;;A798 +A79A;LATIN CAPITAL LETTER VOLAPUK AE;Lu;0;L;;;;;N;;;;A79B; +A79B;LATIN SMALL LETTER VOLAPUK AE;Ll;0;L;;;;;N;;;A79A;;A79A +A79C;LATIN CAPITAL LETTER VOLAPUK OE;Lu;0;L;;;;;N;;;;A79D; +A79D;LATIN SMALL LETTER VOLAPUK OE;Ll;0;L;;;;;N;;;A79C;;A79C +A79E;LATIN CAPITAL LETTER VOLAPUK UE;Lu;0;L;;;;;N;;;;A79F; +A79F;LATIN SMALL LETTER VOLAPUK UE;Ll;0;L;;;;;N;;;A79E;;A79E +A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1; +A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0 +A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3; +A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2 +A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5; +A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4 +A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7; +A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6 +A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9; +A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8 +A7AA;LATIN CAPITAL LETTER H WITH HOOK;Lu;0;L;;;;;N;;;;0266; +A7AB;LATIN CAPITAL LETTER REVERSED OPEN E;Lu;0;L;;;;;N;;;;025C; +A7AC;LATIN CAPITAL LETTER SCRIPT G;Lu;0;L;;;;;N;;;;0261; +A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C; +A7AE;LATIN CAPITAL LETTER SMALL CAPITAL I;Lu;0;L;;;;;N;;;;026A; +A7AF;LATIN LETTER SMALL CAPITAL Q;Ll;0;L;;;;;N;;;;; +A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E; +A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287; +A7B2;LATIN CAPITAL LETTER J WITH CROSSED-TAIL;Lu;0;L;;;;;N;;;;029D; +A7B3;LATIN CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;AB53; +A7B4;LATIN CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;A7B5; +A7B5;LATIN SMALL LETTER BETA;Ll;0;L;;;;;N;;;A7B4;;A7B4 +A7B6;LATIN CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;A7B7; +A7B7;LATIN SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;A7B6;;A7B6 +A7B8;LATIN CAPITAL LETTER U WITH STROKE;Lu;0;L;;;;;N;;;;A7B9; +A7B9;LATIN SMALL LETTER U WITH STROKE;Ll;0;L;;;;;N;;;A7B8;;A7B8 +A7BA;LATIN CAPITAL LETTER GLOTTAL A;Lu;0;L;;;;;N;;;;A7BB; +A7BB;LATIN SMALL LETTER GLOTTAL A;Ll;0;L;;;;;N;;;A7BA;;A7BA +A7BC;LATIN CAPITAL LETTER GLOTTAL I;Lu;0;L;;;;;N;;;;A7BD; +A7BD;LATIN SMALL LETTER GLOTTAL I;Ll;0;L;;;;;N;;;A7BC;;A7BC +A7BE;LATIN CAPITAL LETTER GLOTTAL U;Lu;0;L;;;;;N;;;;A7BF; +A7BF;LATIN SMALL LETTER GLOTTAL U;Ll;0;L;;;;;N;;;A7BE;;A7BE +A7C0;LATIN CAPITAL LETTER OLD POLISH O;Lu;0;L;;;;;N;;;;A7C1; +A7C1;LATIN SMALL LETTER OLD POLISH O;Ll;0;L;;;;;N;;;A7C0;;A7C0 +A7C2;LATIN CAPITAL LETTER ANGLICANA W;Lu;0;L;;;;;N;;;;A7C3; +A7C3;LATIN SMALL LETTER ANGLICANA W;Ll;0;L;;;;;N;;;A7C2;;A7C2 +A7C4;LATIN CAPITAL LETTER C WITH PALATAL HOOK;Lu;0;L;;;;;N;;;;A794; +A7C5;LATIN CAPITAL LETTER S WITH HOOK;Lu;0;L;;;;;N;;;;0282; +A7C6;LATIN CAPITAL LETTER Z WITH PALATAL HOOK;Lu;0;L;;;;;N;;;;1D8E; +A7C7;LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7C8; +A7C8;LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C7;;A7C7 +A7C9;LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7CA; +A7CA;LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C9;;A7C9 +A7CB;LATIN CAPITAL LETTER RAMS HORN;Lu;0;L;;;;;N;;;;0264; +A7CC;LATIN CAPITAL LETTER S WITH DIAGONAL STROKE;Lu;0;L;;;;;N;;;;A7CD; +A7CD;LATIN SMALL LETTER S WITH DIAGONAL STROKE;Ll;0;L;;;;;N;;;A7CC;;A7CC +A7CE;LATIN CAPITAL LETTER PHARYNGEAL VOICED FRICATIVE;Lu;0;L;;;;;N;;;;A7CF; +A7CF;LATIN SMALL LETTER PHARYNGEAL VOICED FRICATIVE;Ll;0;L;;;;;N;;;A7CE;;A7CE +A7D0;LATIN CAPITAL LETTER CLOSED INSULAR G;Lu;0;L;;;;;N;;;;A7D1; +A7D1;LATIN SMALL LETTER CLOSED INSULAR G;Ll;0;L;;;;;N;;;A7D0;;A7D0 +A7D2;LATIN CAPITAL LETTER DOUBLE THORN;Lu;0;L;;;;;N;;;;A7D3; +A7D3;LATIN SMALL LETTER DOUBLE THORN;Ll;0;L;;;;;N;;;A7D2;;A7D2 +A7D4;LATIN CAPITAL LETTER DOUBLE WYNN;Lu;0;L;;;;;N;;;;A7D5; +A7D5;LATIN SMALL LETTER DOUBLE WYNN;Ll;0;L;;;;;N;;;A7D4;;A7D4 +A7D6;LATIN CAPITAL LETTER MIDDLE SCOTS S;Lu;0;L;;;;;N;;;;A7D7; +A7D7;LATIN SMALL LETTER MIDDLE SCOTS S;Ll;0;L;;;;;N;;;A7D6;;A7D6 +A7D8;LATIN CAPITAL LETTER SIGMOID S;Lu;0;L;;;;;N;;;;A7D9; +A7D9;LATIN SMALL LETTER SIGMOID S;Ll;0;L;;;;;N;;;A7D8;;A7D8 +A7DA;LATIN CAPITAL LETTER LAMBDA;Lu;0;L;;;;;N;;;;A7DB; +A7DB;LATIN SMALL LETTER LAMBDA;Ll;0;L;;;;;N;;;A7DA;;A7DA +A7DC;LATIN CAPITAL LETTER LAMBDA WITH STROKE;Lu;0;L;;;;;N;;;;019B; +A7F1;MODIFIER LETTER CAPITAL S;Lm;0;L; 0053;;;;N;;;;; +A7F2;MODIFIER LETTER CAPITAL C;Lm;0;L; 0043;;;;N;;;;; +A7F3;MODIFIER LETTER CAPITAL F;Lm;0;L; 0046;;;;N;;;;; +A7F4;MODIFIER LETTER CAPITAL Q;Lm;0;L; 0051;;;;N;;;;; +A7F5;LATIN CAPITAL LETTER REVERSED HALF H;Lu;0;L;;;;;N;;;;A7F6; +A7F6;LATIN SMALL LETTER REVERSED HALF H;Ll;0;L;;;;;N;;;A7F5;;A7F5 +A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;; +A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L; 0126;;;;N;;;;; +A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L; 0153;;;;N;;;;; +A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;; +A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; +A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; +A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; +A7FE;LATIN EPIGRAPHIC LETTER I LONGA;Lo;0;L;;;;;N;;;;; +A7FF;LATIN EPIGRAPHIC LETTER ARCHAIC M;Lo;0;L;;;;;N;;;;; +A800;SYLOTI NAGRI LETTER A;Lo;0;L;;;;;N;;;;; +A801;SYLOTI NAGRI LETTER I;Lo;0;L;;;;;N;;;;; +A802;SYLOTI NAGRI SIGN DVISVARA;Mn;0;NSM;;;;;N;;;;; +A803;SYLOTI NAGRI LETTER U;Lo;0;L;;;;;N;;;;; +A804;SYLOTI NAGRI LETTER E;Lo;0;L;;;;;N;;;;; +A805;SYLOTI NAGRI LETTER O;Lo;0;L;;;;;N;;;;; +A806;SYLOTI NAGRI SIGN HASANTA;Mn;9;NSM;;;;;N;;;;; +A807;SYLOTI NAGRI LETTER KO;Lo;0;L;;;;;N;;;;; +A808;SYLOTI NAGRI LETTER KHO;Lo;0;L;;;;;N;;;;; +A809;SYLOTI NAGRI LETTER GO;Lo;0;L;;;;;N;;;;; +A80A;SYLOTI NAGRI LETTER GHO;Lo;0;L;;;;;N;;;;; +A80B;SYLOTI NAGRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +A80C;SYLOTI NAGRI LETTER CO;Lo;0;L;;;;;N;;;;; +A80D;SYLOTI NAGRI LETTER CHO;Lo;0;L;;;;;N;;;;; +A80E;SYLOTI NAGRI LETTER JO;Lo;0;L;;;;;N;;;;; +A80F;SYLOTI NAGRI LETTER JHO;Lo;0;L;;;;;N;;;;; +A810;SYLOTI NAGRI LETTER TTO;Lo;0;L;;;;;N;;;;; +A811;SYLOTI NAGRI LETTER TTHO;Lo;0;L;;;;;N;;;;; +A812;SYLOTI NAGRI LETTER DDO;Lo;0;L;;;;;N;;;;; +A813;SYLOTI NAGRI LETTER DDHO;Lo;0;L;;;;;N;;;;; +A814;SYLOTI NAGRI LETTER TO;Lo;0;L;;;;;N;;;;; +A815;SYLOTI NAGRI LETTER THO;Lo;0;L;;;;;N;;;;; +A816;SYLOTI NAGRI LETTER DO;Lo;0;L;;;;;N;;;;; +A817;SYLOTI NAGRI LETTER DHO;Lo;0;L;;;;;N;;;;; +A818;SYLOTI NAGRI LETTER NO;Lo;0;L;;;;;N;;;;; +A819;SYLOTI NAGRI LETTER PO;Lo;0;L;;;;;N;;;;; +A81A;SYLOTI NAGRI LETTER PHO;Lo;0;L;;;;;N;;;;; +A81B;SYLOTI NAGRI LETTER BO;Lo;0;L;;;;;N;;;;; +A81C;SYLOTI NAGRI LETTER BHO;Lo;0;L;;;;;N;;;;; +A81D;SYLOTI NAGRI LETTER MO;Lo;0;L;;;;;N;;;;; +A81E;SYLOTI NAGRI LETTER RO;Lo;0;L;;;;;N;;;;; +A81F;SYLOTI NAGRI LETTER LO;Lo;0;L;;;;;N;;;;; +A820;SYLOTI NAGRI LETTER RRO;Lo;0;L;;;;;N;;;;; +A821;SYLOTI NAGRI LETTER SO;Lo;0;L;;;;;N;;;;; +A822;SYLOTI NAGRI LETTER HO;Lo;0;L;;;;;N;;;;; +A823;SYLOTI NAGRI VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +A824;SYLOTI NAGRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +A825;SYLOTI NAGRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +A826;SYLOTI NAGRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +A827;SYLOTI NAGRI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +A828;SYLOTI NAGRI POETRY MARK-1;So;0;ON;;;;;N;;;;; +A829;SYLOTI NAGRI POETRY MARK-2;So;0;ON;;;;;N;;;;; +A82A;SYLOTI NAGRI POETRY MARK-3;So;0;ON;;;;;N;;;;; +A82B;SYLOTI NAGRI POETRY MARK-4;So;0;ON;;;;;N;;;;; +A82C;SYLOTI NAGRI SIGN ALTERNATE HASANTA;Mn;9;NSM;;;;;N;;;;; +A830;NORTH INDIC FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +A831;NORTH INDIC FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +A832;NORTH INDIC FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +A833;NORTH INDIC FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +A834;NORTH INDIC FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +A835;NORTH INDIC FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +A836;NORTH INDIC QUARTER MARK;So;0;L;;;;;N;;;;; +A837;NORTH INDIC PLACEHOLDER MARK;So;0;L;;;;;N;;;;; +A838;NORTH INDIC RUPEE MARK;Sc;0;ET;;;;;N;;;;; +A839;NORTH INDIC QUANTITY MARK;So;0;ET;;;;;N;;;;; +A840;PHAGS-PA LETTER KA;Lo;0;L;;;;;N;;;;; +A841;PHAGS-PA LETTER KHA;Lo;0;L;;;;;N;;;;; +A842;PHAGS-PA LETTER GA;Lo;0;L;;;;;N;;;;; +A843;PHAGS-PA LETTER NGA;Lo;0;L;;;;;N;;;;; +A844;PHAGS-PA LETTER CA;Lo;0;L;;;;;N;;;;; +A845;PHAGS-PA LETTER CHA;Lo;0;L;;;;;N;;;;; +A846;PHAGS-PA LETTER JA;Lo;0;L;;;;;N;;;;; +A847;PHAGS-PA LETTER NYA;Lo;0;L;;;;;N;;;;; +A848;PHAGS-PA LETTER TA;Lo;0;L;;;;;N;;;;; +A849;PHAGS-PA LETTER THA;Lo;0;L;;;;;N;;;;; +A84A;PHAGS-PA LETTER DA;Lo;0;L;;;;;N;;;;; +A84B;PHAGS-PA LETTER NA;Lo;0;L;;;;;N;;;;; +A84C;PHAGS-PA LETTER PA;Lo;0;L;;;;;N;;;;; +A84D;PHAGS-PA LETTER PHA;Lo;0;L;;;;;N;;;;; +A84E;PHAGS-PA LETTER BA;Lo;0;L;;;;;N;;;;; +A84F;PHAGS-PA LETTER MA;Lo;0;L;;;;;N;;;;; +A850;PHAGS-PA LETTER TSA;Lo;0;L;;;;;N;;;;; +A851;PHAGS-PA LETTER TSHA;Lo;0;L;;;;;N;;;;; +A852;PHAGS-PA LETTER DZA;Lo;0;L;;;;;N;;;;; +A853;PHAGS-PA LETTER WA;Lo;0;L;;;;;N;;;;; +A854;PHAGS-PA LETTER ZHA;Lo;0;L;;;;;N;;;;; +A855;PHAGS-PA LETTER ZA;Lo;0;L;;;;;N;;;;; +A856;PHAGS-PA LETTER SMALL A;Lo;0;L;;;;;N;;;;; +A857;PHAGS-PA LETTER YA;Lo;0;L;;;;;N;;;;; +A858;PHAGS-PA LETTER RA;Lo;0;L;;;;;N;;;;; +A859;PHAGS-PA LETTER LA;Lo;0;L;;;;;N;;;;; +A85A;PHAGS-PA LETTER SHA;Lo;0;L;;;;;N;;;;; +A85B;PHAGS-PA LETTER SA;Lo;0;L;;;;;N;;;;; +A85C;PHAGS-PA LETTER HA;Lo;0;L;;;;;N;;;;; +A85D;PHAGS-PA LETTER A;Lo;0;L;;;;;N;;;;; +A85E;PHAGS-PA LETTER I;Lo;0;L;;;;;N;;;;; +A85F;PHAGS-PA LETTER U;Lo;0;L;;;;;N;;;;; +A860;PHAGS-PA LETTER E;Lo;0;L;;;;;N;;;;; +A861;PHAGS-PA LETTER O;Lo;0;L;;;;;N;;;;; +A862;PHAGS-PA LETTER QA;Lo;0;L;;;;;N;;;;; +A863;PHAGS-PA LETTER XA;Lo;0;L;;;;;N;;;;; +A864;PHAGS-PA LETTER FA;Lo;0;L;;;;;N;;;;; +A865;PHAGS-PA LETTER GGA;Lo;0;L;;;;;N;;;;; +A866;PHAGS-PA LETTER EE;Lo;0;L;;;;;N;;;;; +A867;PHAGS-PA SUBJOINED LETTER WA;Lo;0;L;;;;;N;;;;; +A868;PHAGS-PA SUBJOINED LETTER YA;Lo;0;L;;;;;N;;;;; +A869;PHAGS-PA LETTER TTA;Lo;0;L;;;;;N;;;;; +A86A;PHAGS-PA LETTER TTHA;Lo;0;L;;;;;N;;;;; +A86B;PHAGS-PA LETTER DDA;Lo;0;L;;;;;N;;;;; +A86C;PHAGS-PA LETTER NNA;Lo;0;L;;;;;N;;;;; +A86D;PHAGS-PA LETTER ALTERNATE YA;Lo;0;L;;;;;N;;;;; +A86E;PHAGS-PA LETTER VOICELESS SHA;Lo;0;L;;;;;N;;;;; +A86F;PHAGS-PA LETTER VOICED HA;Lo;0;L;;;;;N;;;;; +A870;PHAGS-PA LETTER ASPIRATED FA;Lo;0;L;;;;;N;;;;; +A871;PHAGS-PA SUBJOINED LETTER RA;Lo;0;L;;;;;N;;;;; +A872;PHAGS-PA SUPERFIXED LETTER RA;Lo;0;L;;;;;N;;;;; +A873;PHAGS-PA LETTER CANDRABINDU;Lo;0;L;;;;;N;;;;; +A874;PHAGS-PA SINGLE HEAD MARK;Po;0;ON;;;;;N;;;;; +A875;PHAGS-PA DOUBLE HEAD MARK;Po;0;ON;;;;;N;;;;; +A876;PHAGS-PA MARK SHAD;Po;0;ON;;;;;N;;;;; +A877;PHAGS-PA MARK DOUBLE SHAD;Po;0;ON;;;;;N;;;;; +A880;SAURASHTRA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +A881;SAURASHTRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +A882;SAURASHTRA LETTER A;Lo;0;L;;;;;N;;;;; +A883;SAURASHTRA LETTER AA;Lo;0;L;;;;;N;;;;; +A884;SAURASHTRA LETTER I;Lo;0;L;;;;;N;;;;; +A885;SAURASHTRA LETTER II;Lo;0;L;;;;;N;;;;; +A886;SAURASHTRA LETTER U;Lo;0;L;;;;;N;;;;; +A887;SAURASHTRA LETTER UU;Lo;0;L;;;;;N;;;;; +A888;SAURASHTRA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +A889;SAURASHTRA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +A88A;SAURASHTRA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +A88B;SAURASHTRA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +A88C;SAURASHTRA LETTER E;Lo;0;L;;;;;N;;;;; +A88D;SAURASHTRA LETTER EE;Lo;0;L;;;;;N;;;;; +A88E;SAURASHTRA LETTER AI;Lo;0;L;;;;;N;;;;; +A88F;SAURASHTRA LETTER O;Lo;0;L;;;;;N;;;;; +A890;SAURASHTRA LETTER OO;Lo;0;L;;;;;N;;;;; +A891;SAURASHTRA LETTER AU;Lo;0;L;;;;;N;;;;; +A892;SAURASHTRA LETTER KA;Lo;0;L;;;;;N;;;;; +A893;SAURASHTRA LETTER KHA;Lo;0;L;;;;;N;;;;; +A894;SAURASHTRA LETTER GA;Lo;0;L;;;;;N;;;;; +A895;SAURASHTRA LETTER GHA;Lo;0;L;;;;;N;;;;; +A896;SAURASHTRA LETTER NGA;Lo;0;L;;;;;N;;;;; +A897;SAURASHTRA LETTER CA;Lo;0;L;;;;;N;;;;; +A898;SAURASHTRA LETTER CHA;Lo;0;L;;;;;N;;;;; +A899;SAURASHTRA LETTER JA;Lo;0;L;;;;;N;;;;; +A89A;SAURASHTRA LETTER JHA;Lo;0;L;;;;;N;;;;; +A89B;SAURASHTRA LETTER NYA;Lo;0;L;;;;;N;;;;; +A89C;SAURASHTRA LETTER TTA;Lo;0;L;;;;;N;;;;; +A89D;SAURASHTRA LETTER TTHA;Lo;0;L;;;;;N;;;;; +A89E;SAURASHTRA LETTER DDA;Lo;0;L;;;;;N;;;;; +A89F;SAURASHTRA LETTER DDHA;Lo;0;L;;;;;N;;;;; +A8A0;SAURASHTRA LETTER NNA;Lo;0;L;;;;;N;;;;; +A8A1;SAURASHTRA LETTER TA;Lo;0;L;;;;;N;;;;; +A8A2;SAURASHTRA LETTER THA;Lo;0;L;;;;;N;;;;; +A8A3;SAURASHTRA LETTER DA;Lo;0;L;;;;;N;;;;; +A8A4;SAURASHTRA LETTER DHA;Lo;0;L;;;;;N;;;;; +A8A5;SAURASHTRA LETTER NA;Lo;0;L;;;;;N;;;;; +A8A6;SAURASHTRA LETTER PA;Lo;0;L;;;;;N;;;;; +A8A7;SAURASHTRA LETTER PHA;Lo;0;L;;;;;N;;;;; +A8A8;SAURASHTRA LETTER BA;Lo;0;L;;;;;N;;;;; +A8A9;SAURASHTRA LETTER BHA;Lo;0;L;;;;;N;;;;; +A8AA;SAURASHTRA LETTER MA;Lo;0;L;;;;;N;;;;; +A8AB;SAURASHTRA LETTER YA;Lo;0;L;;;;;N;;;;; +A8AC;SAURASHTRA LETTER RA;Lo;0;L;;;;;N;;;;; +A8AD;SAURASHTRA LETTER LA;Lo;0;L;;;;;N;;;;; +A8AE;SAURASHTRA LETTER VA;Lo;0;L;;;;;N;;;;; +A8AF;SAURASHTRA LETTER SHA;Lo;0;L;;;;;N;;;;; +A8B0;SAURASHTRA LETTER SSA;Lo;0;L;;;;;N;;;;; +A8B1;SAURASHTRA LETTER SA;Lo;0;L;;;;;N;;;;; +A8B2;SAURASHTRA LETTER HA;Lo;0;L;;;;;N;;;;; +A8B3;SAURASHTRA LETTER LLA;Lo;0;L;;;;;N;;;;; +A8B4;SAURASHTRA CONSONANT SIGN HAARU;Mc;0;L;;;;;N;;;;; +A8B5;SAURASHTRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +A8B6;SAURASHTRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +A8B7;SAURASHTRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +A8B8;SAURASHTRA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +A8B9;SAURASHTRA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +A8BA;SAURASHTRA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +A8BB;SAURASHTRA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +A8BC;SAURASHTRA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; +A8BD;SAURASHTRA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; +A8BE;SAURASHTRA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +A8BF;SAURASHTRA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +A8C0;SAURASHTRA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +A8C1;SAURASHTRA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +A8C2;SAURASHTRA VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +A8C3;SAURASHTRA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +A8C4;SAURASHTRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +A8C5;SAURASHTRA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +A8CE;SAURASHTRA DANDA;Po;0;L;;;;;N;;;;; +A8CF;SAURASHTRA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +A8D0;SAURASHTRA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A8D1;SAURASHTRA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A8D2;SAURASHTRA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A8D3;SAURASHTRA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A8D4;SAURASHTRA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A8D5;SAURASHTRA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A8D6;SAURASHTRA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A8D7;SAURASHTRA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A8D8;SAURASHTRA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A8D9;SAURASHTRA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A8E0;COMBINING DEVANAGARI DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; +A8E1;COMBINING DEVANAGARI DIGIT ONE;Mn;230;NSM;;;;;N;;;;; +A8E2;COMBINING DEVANAGARI DIGIT TWO;Mn;230;NSM;;;;;N;;;;; +A8E3;COMBINING DEVANAGARI DIGIT THREE;Mn;230;NSM;;;;;N;;;;; +A8E4;COMBINING DEVANAGARI DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; +A8E5;COMBINING DEVANAGARI DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; +A8E6;COMBINING DEVANAGARI DIGIT SIX;Mn;230;NSM;;;;;N;;;;; +A8E7;COMBINING DEVANAGARI DIGIT SEVEN;Mn;230;NSM;;;;;N;;;;; +A8E8;COMBINING DEVANAGARI DIGIT EIGHT;Mn;230;NSM;;;;;N;;;;; +A8E9;COMBINING DEVANAGARI DIGIT NINE;Mn;230;NSM;;;;;N;;;;; +A8EA;COMBINING DEVANAGARI LETTER A;Mn;230;NSM;;;;;N;;;;; +A8EB;COMBINING DEVANAGARI LETTER U;Mn;230;NSM;;;;;N;;;;; +A8EC;COMBINING DEVANAGARI LETTER KA;Mn;230;NSM;;;;;N;;;;; +A8ED;COMBINING DEVANAGARI LETTER NA;Mn;230;NSM;;;;;N;;;;; +A8EE;COMBINING DEVANAGARI LETTER PA;Mn;230;NSM;;;;;N;;;;; +A8EF;COMBINING DEVANAGARI LETTER RA;Mn;230;NSM;;;;;N;;;;; +A8F0;COMBINING DEVANAGARI LETTER VI;Mn;230;NSM;;;;;N;;;;; +A8F1;COMBINING DEVANAGARI SIGN AVAGRAHA;Mn;230;NSM;;;;;N;;;;; +A8F2;DEVANAGARI SIGN SPACING CANDRABINDU;Lo;0;L;;;;;N;;;;; +A8F3;DEVANAGARI SIGN CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; +A8F4;DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA;Lo;0;L;;;;;N;;;;; +A8F5;DEVANAGARI SIGN CANDRABINDU TWO;Lo;0;L;;;;;N;;;;; +A8F6;DEVANAGARI SIGN CANDRABINDU THREE;Lo;0;L;;;;;N;;;;; +A8F7;DEVANAGARI SIGN CANDRABINDU AVAGRAHA;Lo;0;L;;;;;N;;;;; +A8F8;DEVANAGARI SIGN PUSHPIKA;Po;0;L;;;;;N;;;;; +A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;; +A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;; +A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; +A8FC;DEVANAGARI SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +A8FD;DEVANAGARI JAIN OM;Lo;0;L;;;;;N;;;;; +A8FE;DEVANAGARI LETTER AY;Lo;0;L;;;;;N;;;;; +A8FF;DEVANAGARI VOWEL SIGN AY;Mn;0;NSM;;;;;N;;;;; +A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A903;KAYAH LI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A904;KAYAH LI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A905;KAYAH LI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A906;KAYAH LI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A907;KAYAH LI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A908;KAYAH LI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A909;KAYAH LI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A90A;KAYAH LI LETTER KA;Lo;0;L;;;;;N;;;;; +A90B;KAYAH LI LETTER KHA;Lo;0;L;;;;;N;;;;; +A90C;KAYAH LI LETTER GA;Lo;0;L;;;;;N;;;;; +A90D;KAYAH LI LETTER NGA;Lo;0;L;;;;;N;;;;; +A90E;KAYAH LI LETTER SA;Lo;0;L;;;;;N;;;;; +A90F;KAYAH LI LETTER SHA;Lo;0;L;;;;;N;;;;; +A910;KAYAH LI LETTER ZA;Lo;0;L;;;;;N;;;;; +A911;KAYAH LI LETTER NYA;Lo;0;L;;;;;N;;;;; +A912;KAYAH LI LETTER TA;Lo;0;L;;;;;N;;;;; +A913;KAYAH LI LETTER HTA;Lo;0;L;;;;;N;;;;; +A914;KAYAH LI LETTER NA;Lo;0;L;;;;;N;;;;; +A915;KAYAH LI LETTER PA;Lo;0;L;;;;;N;;;;; +A916;KAYAH LI LETTER PHA;Lo;0;L;;;;;N;;;;; +A917;KAYAH LI LETTER MA;Lo;0;L;;;;;N;;;;; +A918;KAYAH LI LETTER DA;Lo;0;L;;;;;N;;;;; +A919;KAYAH LI LETTER BA;Lo;0;L;;;;;N;;;;; +A91A;KAYAH LI LETTER RA;Lo;0;L;;;;;N;;;;; +A91B;KAYAH LI LETTER YA;Lo;0;L;;;;;N;;;;; +A91C;KAYAH LI LETTER LA;Lo;0;L;;;;;N;;;;; +A91D;KAYAH LI LETTER WA;Lo;0;L;;;;;N;;;;; +A91E;KAYAH LI LETTER THA;Lo;0;L;;;;;N;;;;; +A91F;KAYAH LI LETTER HA;Lo;0;L;;;;;N;;;;; +A920;KAYAH LI LETTER VA;Lo;0;L;;;;;N;;;;; +A921;KAYAH LI LETTER CA;Lo;0;L;;;;;N;;;;; +A922;KAYAH LI LETTER A;Lo;0;L;;;;;N;;;;; +A923;KAYAH LI LETTER OE;Lo;0;L;;;;;N;;;;; +A924;KAYAH LI LETTER I;Lo;0;L;;;;;N;;;;; +A925;KAYAH LI LETTER OO;Lo;0;L;;;;;N;;;;; +A926;KAYAH LI VOWEL UE;Mn;0;NSM;;;;;N;;;;; +A927;KAYAH LI VOWEL E;Mn;0;NSM;;;;;N;;;;; +A928;KAYAH LI VOWEL U;Mn;0;NSM;;;;;N;;;;; +A929;KAYAH LI VOWEL EE;Mn;0;NSM;;;;;N;;;;; +A92A;KAYAH LI VOWEL O;Mn;0;NSM;;;;;N;;;;; +A92B;KAYAH LI TONE PLOPHU;Mn;220;NSM;;;;;N;;;;; +A92C;KAYAH LI TONE CALYA;Mn;220;NSM;;;;;N;;;;; +A92D;KAYAH LI TONE CALYA PLOPHU;Mn;220;NSM;;;;;N;;;;; +A92E;KAYAH LI SIGN CWI;Po;0;L;;;;;N;;;;; +A92F;KAYAH LI SIGN SHYA;Po;0;L;;;;;N;;;;; +A930;REJANG LETTER KA;Lo;0;L;;;;;N;;;;; +A931;REJANG LETTER GA;Lo;0;L;;;;;N;;;;; +A932;REJANG LETTER NGA;Lo;0;L;;;;;N;;;;; +A933;REJANG LETTER TA;Lo;0;L;;;;;N;;;;; +A934;REJANG LETTER DA;Lo;0;L;;;;;N;;;;; +A935;REJANG LETTER NA;Lo;0;L;;;;;N;;;;; +A936;REJANG LETTER PA;Lo;0;L;;;;;N;;;;; +A937;REJANG LETTER BA;Lo;0;L;;;;;N;;;;; +A938;REJANG LETTER MA;Lo;0;L;;;;;N;;;;; +A939;REJANG LETTER CA;Lo;0;L;;;;;N;;;;; +A93A;REJANG LETTER JA;Lo;0;L;;;;;N;;;;; +A93B;REJANG LETTER NYA;Lo;0;L;;;;;N;;;;; +A93C;REJANG LETTER SA;Lo;0;L;;;;;N;;;;; +A93D;REJANG LETTER RA;Lo;0;L;;;;;N;;;;; +A93E;REJANG LETTER LA;Lo;0;L;;;;;N;;;;; +A93F;REJANG LETTER YA;Lo;0;L;;;;;N;;;;; +A940;REJANG LETTER WA;Lo;0;L;;;;;N;;;;; +A941;REJANG LETTER HA;Lo;0;L;;;;;N;;;;; +A942;REJANG LETTER MBA;Lo;0;L;;;;;N;;;;; +A943;REJANG LETTER NGGA;Lo;0;L;;;;;N;;;;; +A944;REJANG LETTER NDA;Lo;0;L;;;;;N;;;;; +A945;REJANG LETTER NYJA;Lo;0;L;;;;;N;;;;; +A946;REJANG LETTER A;Lo;0;L;;;;;N;;;;; +A947;REJANG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +A948;REJANG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +A949;REJANG VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +A94A;REJANG VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +A94B;REJANG VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +A94C;REJANG VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +A94D;REJANG VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; +A94E;REJANG VOWEL SIGN EA;Mn;0;NSM;;;;;N;;;;; +A94F;REJANG CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +A950;REJANG CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +A951;REJANG CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +A952;REJANG CONSONANT SIGN H;Mc;0;L;;;;;N;;;;; +A953;REJANG VIRAMA;Mc;9;L;;;;;N;;;;; +A95F;REJANG SECTION MARK;Po;0;L;;;;;N;;;;; +A960;HANGUL CHOSEONG TIKEUT-MIEUM;Lo;0;L;;;;;N;;;;; +A961;HANGUL CHOSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +A962;HANGUL CHOSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; +A963;HANGUL CHOSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; +A964;HANGUL CHOSEONG RIEUL-KIYEOK;Lo;0;L;;;;;N;;;;; +A965;HANGUL CHOSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +A966;HANGUL CHOSEONG RIEUL-TIKEUT;Lo;0;L;;;;;N;;;;; +A967;HANGUL CHOSEONG RIEUL-SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +A968;HANGUL CHOSEONG RIEUL-MIEUM;Lo;0;L;;;;;N;;;;; +A969;HANGUL CHOSEONG RIEUL-PIEUP;Lo;0;L;;;;;N;;;;; +A96A;HANGUL CHOSEONG RIEUL-SSANGPIEUP;Lo;0;L;;;;;N;;;;; +A96B;HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +A96C;HANGUL CHOSEONG RIEUL-SIOS;Lo;0;L;;;;;N;;;;; +A96D;HANGUL CHOSEONG RIEUL-CIEUC;Lo;0;L;;;;;N;;;;; +A96E;HANGUL CHOSEONG RIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +A96F;HANGUL CHOSEONG MIEUM-KIYEOK;Lo;0;L;;;;;N;;;;; +A970;HANGUL CHOSEONG MIEUM-TIKEUT;Lo;0;L;;;;;N;;;;; +A971;HANGUL CHOSEONG MIEUM-SIOS;Lo;0;L;;;;;N;;;;; +A972;HANGUL CHOSEONG PIEUP-SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +A973;HANGUL CHOSEONG PIEUP-KHIEUKH;Lo;0;L;;;;;N;;;;; +A974;HANGUL CHOSEONG PIEUP-HIEUH;Lo;0;L;;;;;N;;;;; +A975;HANGUL CHOSEONG SSANGSIOS-PIEUP;Lo;0;L;;;;;N;;;;; +A976;HANGUL CHOSEONG IEUNG-RIEUL;Lo;0;L;;;;;N;;;;; +A977;HANGUL CHOSEONG IEUNG-HIEUH;Lo;0;L;;;;;N;;;;; +A978;HANGUL CHOSEONG SSANGCIEUC-HIEUH;Lo;0;L;;;;;N;;;;; +A979;HANGUL CHOSEONG SSANGTHIEUTH;Lo;0;L;;;;;N;;;;; +A97A;HANGUL CHOSEONG PHIEUPH-HIEUH;Lo;0;L;;;;;N;;;;; +A97B;HANGUL CHOSEONG HIEUH-SIOS;Lo;0;L;;;;;N;;;;; +A97C;HANGUL CHOSEONG SSANGYEORINHIEUH;Lo;0;L;;;;;N;;;;; +A980;JAVANESE SIGN PANYANGGA;Mn;0;NSM;;;;;N;;;;; +A981;JAVANESE SIGN CECAK;Mn;0;NSM;;;;;N;;;;; +A982;JAVANESE SIGN LAYAR;Mn;0;NSM;;;;;N;;;;; +A983;JAVANESE SIGN WIGNYAN;Mc;0;L;;;;;N;;;;; +A984;JAVANESE LETTER A;Lo;0;L;;;;;N;;;;; +A985;JAVANESE LETTER I KAWI;Lo;0;L;;;;;N;;;;; +A986;JAVANESE LETTER I;Lo;0;L;;;;;N;;;;; +A987;JAVANESE LETTER II;Lo;0;L;;;;;N;;;;; +A988;JAVANESE LETTER U;Lo;0;L;;;;;N;;;;; +A989;JAVANESE LETTER PA CEREK;Lo;0;L;;;;;N;;;;; +A98A;JAVANESE LETTER NGA LELET;Lo;0;L;;;;;N;;;;; +A98B;JAVANESE LETTER NGA LELET RASWADI;Lo;0;L;;;;;N;;;;; +A98C;JAVANESE LETTER E;Lo;0;L;;;;;N;;;;; +A98D;JAVANESE LETTER AI;Lo;0;L;;;;;N;;;;; +A98E;JAVANESE LETTER O;Lo;0;L;;;;;N;;;;; +A98F;JAVANESE LETTER KA;Lo;0;L;;;;;N;;;;; +A990;JAVANESE LETTER KA SASAK;Lo;0;L;;;;;N;;;;; +A991;JAVANESE LETTER KA MURDA;Lo;0;L;;;;;N;;;;; +A992;JAVANESE LETTER GA;Lo;0;L;;;;;N;;;;; +A993;JAVANESE LETTER GA MURDA;Lo;0;L;;;;;N;;;;; +A994;JAVANESE LETTER NGA;Lo;0;L;;;;;N;;;;; +A995;JAVANESE LETTER CA;Lo;0;L;;;;;N;;;;; +A996;JAVANESE LETTER CA MURDA;Lo;0;L;;;;;N;;;;; +A997;JAVANESE LETTER JA;Lo;0;L;;;;;N;;;;; +A998;JAVANESE LETTER NYA MURDA;Lo;0;L;;;;;N;;;;; +A999;JAVANESE LETTER JA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99A;JAVANESE LETTER NYA;Lo;0;L;;;;;N;;;;; +A99B;JAVANESE LETTER TTA;Lo;0;L;;;;;N;;;;; +A99C;JAVANESE LETTER TTA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99D;JAVANESE LETTER DDA;Lo;0;L;;;;;N;;;;; +A99E;JAVANESE LETTER DDA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A99F;JAVANESE LETTER NA MURDA;Lo;0;L;;;;;N;;;;; +A9A0;JAVANESE LETTER TA;Lo;0;L;;;;;N;;;;; +A9A1;JAVANESE LETTER TA MURDA;Lo;0;L;;;;;N;;;;; +A9A2;JAVANESE LETTER DA;Lo;0;L;;;;;N;;;;; +A9A3;JAVANESE LETTER DA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A9A4;JAVANESE LETTER NA;Lo;0;L;;;;;N;;;;; +A9A5;JAVANESE LETTER PA;Lo;0;L;;;;;N;;;;; +A9A6;JAVANESE LETTER PA MURDA;Lo;0;L;;;;;N;;;;; +A9A7;JAVANESE LETTER BA;Lo;0;L;;;;;N;;;;; +A9A8;JAVANESE LETTER BA MURDA;Lo;0;L;;;;;N;;;;; +A9A9;JAVANESE LETTER MA;Lo;0;L;;;;;N;;;;; +A9AA;JAVANESE LETTER YA;Lo;0;L;;;;;N;;;;; +A9AB;JAVANESE LETTER RA;Lo;0;L;;;;;N;;;;; +A9AC;JAVANESE LETTER RA AGUNG;Lo;0;L;;;;;N;;;;; +A9AD;JAVANESE LETTER LA;Lo;0;L;;;;;N;;;;; +A9AE;JAVANESE LETTER WA;Lo;0;L;;;;;N;;;;; +A9AF;JAVANESE LETTER SA MURDA;Lo;0;L;;;;;N;;;;; +A9B0;JAVANESE LETTER SA MAHAPRANA;Lo;0;L;;;;;N;;;;; +A9B1;JAVANESE LETTER SA;Lo;0;L;;;;;N;;;;; +A9B2;JAVANESE LETTER HA;Lo;0;L;;;;;N;;;;; +A9B3;JAVANESE SIGN CECAK TELU;Mn;7;NSM;;;;;N;;;;; +A9B4;JAVANESE VOWEL SIGN TARUNG;Mc;0;L;;;;;N;;;;; +A9B5;JAVANESE VOWEL SIGN TOLONG;Mc;0;L;;;;;N;;;;; +A9B6;JAVANESE VOWEL SIGN WULU;Mn;0;NSM;;;;;N;;;;; +A9B7;JAVANESE VOWEL SIGN WULU MELIK;Mn;0;NSM;;;;;N;;;;; +A9B8;JAVANESE VOWEL SIGN SUKU;Mn;0;NSM;;;;;N;;;;; +A9B9;JAVANESE VOWEL SIGN SUKU MENDUT;Mn;0;NSM;;;;;N;;;;; +A9BA;JAVANESE VOWEL SIGN TALING;Mc;0;L;;;;;N;;;;; +A9BB;JAVANESE VOWEL SIGN DIRGA MURE;Mc;0;L;;;;;N;;;;; +A9BC;JAVANESE VOWEL SIGN PEPET;Mn;0;NSM;;;;;N;;;;; +A9BD;JAVANESE CONSONANT SIGN KERET;Mn;0;NSM;;;;;N;;;;; +A9BE;JAVANESE CONSONANT SIGN PENGKAL;Mc;0;L;;;;;N;;;;; +A9BF;JAVANESE CONSONANT SIGN CAKRA;Mc;0;L;;;;;N;;;;; +A9C0;JAVANESE PANGKON;Mc;9;L;;;;;N;;;;; +A9C1;JAVANESE LEFT RERENGGAN;Po;0;L;;;;;N;;;;; +A9C2;JAVANESE RIGHT RERENGGAN;Po;0;L;;;;;N;;;;; +A9C3;JAVANESE PADA ANDAP;Po;0;L;;;;;N;;;;; +A9C4;JAVANESE PADA MADYA;Po;0;L;;;;;N;;;;; +A9C5;JAVANESE PADA LUHUR;Po;0;L;;;;;N;;;;; +A9C6;JAVANESE PADA WINDU;Po;0;L;;;;;N;;;;; +A9C7;JAVANESE PADA PANGKAT;Po;0;L;;;;;N;;;;; +A9C8;JAVANESE PADA LINGSA;Po;0;L;;;;;N;;;;; +A9C9;JAVANESE PADA LUNGSI;Po;0;L;;;;;N;;;;; +A9CA;JAVANESE PADA ADEG;Po;0;L;;;;;N;;;;; +A9CB;JAVANESE PADA ADEG ADEG;Po;0;L;;;;;N;;;;; +A9CC;JAVANESE PADA PISELEH;Po;0;L;;;;;N;;;;; +A9CD;JAVANESE TURNED PADA PISELEH;Po;0;L;;;;;N;;;;; +A9CF;JAVANESE PANGRANGKEP;Lm;0;L;;;;;N;;;;; +A9D0;JAVANESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A9D1;JAVANESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A9D2;JAVANESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A9D3;JAVANESE DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A9D4;JAVANESE DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A9D5;JAVANESE DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A9D6;JAVANESE DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A9D7;JAVANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A9D8;JAVANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A9D9;JAVANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A9DE;JAVANESE PADA TIRTA TUMETES;Po;0;L;;;;;N;;;;; +A9DF;JAVANESE PADA ISEN-ISEN;Po;0;L;;;;;N;;;;; +A9E0;MYANMAR LETTER SHAN GHA;Lo;0;L;;;;;N;;;;; +A9E1;MYANMAR LETTER SHAN CHA;Lo;0;L;;;;;N;;;;; +A9E2;MYANMAR LETTER SHAN JHA;Lo;0;L;;;;;N;;;;; +A9E3;MYANMAR LETTER SHAN NNA;Lo;0;L;;;;;N;;;;; +A9E4;MYANMAR LETTER SHAN BHA;Lo;0;L;;;;;N;;;;; +A9E5;MYANMAR SIGN SHAN SAW;Mn;0;NSM;;;;;N;;;;; +A9E6;MYANMAR MODIFIER LETTER SHAN REDUPLICATION;Lm;0;L;;;;;N;;;;; +A9E7;MYANMAR LETTER TAI LAING NYA;Lo;0;L;;;;;N;;;;; +A9E8;MYANMAR LETTER TAI LAING FA;Lo;0;L;;;;;N;;;;; +A9E9;MYANMAR LETTER TAI LAING GA;Lo;0;L;;;;;N;;;;; +A9EA;MYANMAR LETTER TAI LAING GHA;Lo;0;L;;;;;N;;;;; +A9EB;MYANMAR LETTER TAI LAING JA;Lo;0;L;;;;;N;;;;; +A9EC;MYANMAR LETTER TAI LAING JHA;Lo;0;L;;;;;N;;;;; +A9ED;MYANMAR LETTER TAI LAING DDA;Lo;0;L;;;;;N;;;;; +A9EE;MYANMAR LETTER TAI LAING DDHA;Lo;0;L;;;;;N;;;;; +A9EF;MYANMAR LETTER TAI LAING NNA;Lo;0;L;;;;;N;;;;; +A9F0;MYANMAR TAI LAING DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +A9F1;MYANMAR TAI LAING DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +A9F2;MYANMAR TAI LAING DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +A9F3;MYANMAR TAI LAING DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +A9F4;MYANMAR TAI LAING DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +A9F5;MYANMAR TAI LAING DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +A9F6;MYANMAR TAI LAING DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +A9F7;MYANMAR TAI LAING DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +A9F8;MYANMAR TAI LAING DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +A9F9;MYANMAR TAI LAING DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +A9FA;MYANMAR LETTER TAI LAING LLA;Lo;0;L;;;;;N;;;;; +A9FB;MYANMAR LETTER TAI LAING DA;Lo;0;L;;;;;N;;;;; +A9FC;MYANMAR LETTER TAI LAING DHA;Lo;0;L;;;;;N;;;;; +A9FD;MYANMAR LETTER TAI LAING BA;Lo;0;L;;;;;N;;;;; +A9FE;MYANMAR LETTER TAI LAING BHA;Lo;0;L;;;;;N;;;;; +AA00;CHAM LETTER A;Lo;0;L;;;;;N;;;;; +AA01;CHAM LETTER I;Lo;0;L;;;;;N;;;;; +AA02;CHAM LETTER U;Lo;0;L;;;;;N;;;;; +AA03;CHAM LETTER E;Lo;0;L;;;;;N;;;;; +AA04;CHAM LETTER AI;Lo;0;L;;;;;N;;;;; +AA05;CHAM LETTER O;Lo;0;L;;;;;N;;;;; +AA06;CHAM LETTER KA;Lo;0;L;;;;;N;;;;; +AA07;CHAM LETTER KHA;Lo;0;L;;;;;N;;;;; +AA08;CHAM LETTER GA;Lo;0;L;;;;;N;;;;; +AA09;CHAM LETTER GHA;Lo;0;L;;;;;N;;;;; +AA0A;CHAM LETTER NGUE;Lo;0;L;;;;;N;;;;; +AA0B;CHAM LETTER NGA;Lo;0;L;;;;;N;;;;; +AA0C;CHAM LETTER CHA;Lo;0;L;;;;;N;;;;; +AA0D;CHAM LETTER CHHA;Lo;0;L;;;;;N;;;;; +AA0E;CHAM LETTER JA;Lo;0;L;;;;;N;;;;; +AA0F;CHAM LETTER JHA;Lo;0;L;;;;;N;;;;; +AA10;CHAM LETTER NHUE;Lo;0;L;;;;;N;;;;; +AA11;CHAM LETTER NHA;Lo;0;L;;;;;N;;;;; +AA12;CHAM LETTER NHJA;Lo;0;L;;;;;N;;;;; +AA13;CHAM LETTER TA;Lo;0;L;;;;;N;;;;; +AA14;CHAM LETTER THA;Lo;0;L;;;;;N;;;;; +AA15;CHAM LETTER DA;Lo;0;L;;;;;N;;;;; +AA16;CHAM LETTER DHA;Lo;0;L;;;;;N;;;;; +AA17;CHAM LETTER NUE;Lo;0;L;;;;;N;;;;; +AA18;CHAM LETTER NA;Lo;0;L;;;;;N;;;;; +AA19;CHAM LETTER DDA;Lo;0;L;;;;;N;;;;; +AA1A;CHAM LETTER PA;Lo;0;L;;;;;N;;;;; +AA1B;CHAM LETTER PPA;Lo;0;L;;;;;N;;;;; +AA1C;CHAM LETTER PHA;Lo;0;L;;;;;N;;;;; +AA1D;CHAM LETTER BA;Lo;0;L;;;;;N;;;;; +AA1E;CHAM LETTER BHA;Lo;0;L;;;;;N;;;;; +AA1F;CHAM LETTER MUE;Lo;0;L;;;;;N;;;;; +AA20;CHAM LETTER MA;Lo;0;L;;;;;N;;;;; +AA21;CHAM LETTER BBA;Lo;0;L;;;;;N;;;;; +AA22;CHAM LETTER YA;Lo;0;L;;;;;N;;;;; +AA23;CHAM LETTER RA;Lo;0;L;;;;;N;;;;; +AA24;CHAM LETTER LA;Lo;0;L;;;;;N;;;;; +AA25;CHAM LETTER VA;Lo;0;L;;;;;N;;;;; +AA26;CHAM LETTER SSA;Lo;0;L;;;;;N;;;;; +AA27;CHAM LETTER SA;Lo;0;L;;;;;N;;;;; +AA28;CHAM LETTER HA;Lo;0;L;;;;;N;;;;; +AA29;CHAM VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +AA2A;CHAM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +AA2B;CHAM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +AA2C;CHAM VOWEL SIGN EI;Mn;0;NSM;;;;;N;;;;; +AA2D;CHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +AA2E;CHAM VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +AA2F;CHAM VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +AA30;CHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +AA31;CHAM VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +AA32;CHAM VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +AA33;CHAM CONSONANT SIGN YA;Mc;0;L;;;;;N;;;;; +AA34;CHAM CONSONANT SIGN RA;Mc;0;L;;;;;N;;;;; +AA35;CHAM CONSONANT SIGN LA;Mn;0;NSM;;;;;N;;;;; +AA36;CHAM CONSONANT SIGN WA;Mn;0;NSM;;;;;N;;;;; +AA40;CHAM LETTER FINAL K;Lo;0;L;;;;;N;;;;; +AA41;CHAM LETTER FINAL G;Lo;0;L;;;;;N;;;;; +AA42;CHAM LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +AA43;CHAM CONSONANT SIGN FINAL NG;Mn;0;NSM;;;;;N;;;;; +AA44;CHAM LETTER FINAL CH;Lo;0;L;;;;;N;;;;; +AA45;CHAM LETTER FINAL T;Lo;0;L;;;;;N;;;;; +AA46;CHAM LETTER FINAL N;Lo;0;L;;;;;N;;;;; +AA47;CHAM LETTER FINAL P;Lo;0;L;;;;;N;;;;; +AA48;CHAM LETTER FINAL Y;Lo;0;L;;;;;N;;;;; +AA49;CHAM LETTER FINAL R;Lo;0;L;;;;;N;;;;; +AA4A;CHAM LETTER FINAL L;Lo;0;L;;;;;N;;;;; +AA4B;CHAM LETTER FINAL SS;Lo;0;L;;;;;N;;;;; +AA4C;CHAM CONSONANT SIGN FINAL M;Mn;0;NSM;;;;;N;;;;; +AA4D;CHAM CONSONANT SIGN FINAL H;Mc;0;L;;;;;N;;;;; +AA50;CHAM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +AA51;CHAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +AA52;CHAM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +AA53;CHAM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +AA54;CHAM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +AA55;CHAM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +AA56;CHAM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +AA57;CHAM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +AA58;CHAM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +AA59;CHAM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +AA5C;CHAM PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; +AA5D;CHAM PUNCTUATION DANDA;Po;0;L;;;;;N;;;;; +AA5E;CHAM PUNCTUATION DOUBLE DANDA;Po;0;L;;;;;N;;;;; +AA5F;CHAM PUNCTUATION TRIPLE DANDA;Po;0;L;;;;;N;;;;; +AA60;MYANMAR LETTER KHAMTI GA;Lo;0;L;;;;;N;;;;; +AA61;MYANMAR LETTER KHAMTI CA;Lo;0;L;;;;;N;;;;; +AA62;MYANMAR LETTER KHAMTI CHA;Lo;0;L;;;;;N;;;;; +AA63;MYANMAR LETTER KHAMTI JA;Lo;0;L;;;;;N;;;;; +AA64;MYANMAR LETTER KHAMTI JHA;Lo;0;L;;;;;N;;;;; +AA65;MYANMAR LETTER KHAMTI NYA;Lo;0;L;;;;;N;;;;; +AA66;MYANMAR LETTER KHAMTI TTA;Lo;0;L;;;;;N;;;;; +AA67;MYANMAR LETTER KHAMTI TTHA;Lo;0;L;;;;;N;;;;; +AA68;MYANMAR LETTER KHAMTI DDA;Lo;0;L;;;;;N;;;;; +AA69;MYANMAR LETTER KHAMTI DDHA;Lo;0;L;;;;;N;;;;; +AA6A;MYANMAR LETTER KHAMTI DHA;Lo;0;L;;;;;N;;;;; +AA6B;MYANMAR LETTER KHAMTI NA;Lo;0;L;;;;;N;;;;; +AA6C;MYANMAR LETTER KHAMTI SA;Lo;0;L;;;;;N;;;;; +AA6D;MYANMAR LETTER KHAMTI HA;Lo;0;L;;;;;N;;;;; +AA6E;MYANMAR LETTER KHAMTI HHA;Lo;0;L;;;;;N;;;;; +AA6F;MYANMAR LETTER KHAMTI FA;Lo;0;L;;;;;N;;;;; +AA70;MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION;Lm;0;L;;;;;N;;;;; +AA71;MYANMAR LETTER KHAMTI XA;Lo;0;L;;;;;N;;;;; +AA72;MYANMAR LETTER KHAMTI ZA;Lo;0;L;;;;;N;;;;; +AA73;MYANMAR LETTER KHAMTI RA;Lo;0;L;;;;;N;;;;; +AA74;MYANMAR LOGOGRAM KHAMTI OAY;Lo;0;L;;;;;N;;;;; +AA75;MYANMAR LOGOGRAM KHAMTI QN;Lo;0;L;;;;;N;;;;; +AA76;MYANMAR LOGOGRAM KHAMTI HM;Lo;0;L;;;;;N;;;;; +AA77;MYANMAR SYMBOL AITON EXCLAMATION;So;0;L;;;;;N;;;;; +AA78;MYANMAR SYMBOL AITON ONE;So;0;L;;;;;N;;;;; +AA79;MYANMAR SYMBOL AITON TWO;So;0;L;;;;;N;;;;; +AA7A;MYANMAR LETTER AITON RA;Lo;0;L;;;;;N;;;;; +AA7B;MYANMAR SIGN PAO KAREN TONE;Mc;0;L;;;;;N;;;;; +AA7C;MYANMAR SIGN TAI LAING TONE-2;Mn;0;NSM;;;;;N;;;;; +AA7D;MYANMAR SIGN TAI LAING TONE-5;Mc;0;L;;;;;N;;;;; +AA7E;MYANMAR LETTER SHWE PALAUNG CHA;Lo;0;L;;;;;N;;;;; +AA7F;MYANMAR LETTER SHWE PALAUNG SHA;Lo;0;L;;;;;N;;;;; +AA80;TAI VIET LETTER LOW KO;Lo;0;L;;;;;N;;;;; +AA81;TAI VIET LETTER HIGH KO;Lo;0;L;;;;;N;;;;; +AA82;TAI VIET LETTER LOW KHO;Lo;0;L;;;;;N;;;;; +AA83;TAI VIET LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; +AA84;TAI VIET LETTER LOW KHHO;Lo;0;L;;;;;N;;;;; +AA85;TAI VIET LETTER HIGH KHHO;Lo;0;L;;;;;N;;;;; +AA86;TAI VIET LETTER LOW GO;Lo;0;L;;;;;N;;;;; +AA87;TAI VIET LETTER HIGH GO;Lo;0;L;;;;;N;;;;; +AA88;TAI VIET LETTER LOW NGO;Lo;0;L;;;;;N;;;;; +AA89;TAI VIET LETTER HIGH NGO;Lo;0;L;;;;;N;;;;; +AA8A;TAI VIET LETTER LOW CO;Lo;0;L;;;;;N;;;;; +AA8B;TAI VIET LETTER HIGH CO;Lo;0;L;;;;;N;;;;; +AA8C;TAI VIET LETTER LOW CHO;Lo;0;L;;;;;N;;;;; +AA8D;TAI VIET LETTER HIGH CHO;Lo;0;L;;;;;N;;;;; +AA8E;TAI VIET LETTER LOW SO;Lo;0;L;;;;;N;;;;; +AA8F;TAI VIET LETTER HIGH SO;Lo;0;L;;;;;N;;;;; +AA90;TAI VIET LETTER LOW NYO;Lo;0;L;;;;;N;;;;; +AA91;TAI VIET LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; +AA92;TAI VIET LETTER LOW DO;Lo;0;L;;;;;N;;;;; +AA93;TAI VIET LETTER HIGH DO;Lo;0;L;;;;;N;;;;; +AA94;TAI VIET LETTER LOW TO;Lo;0;L;;;;;N;;;;; +AA95;TAI VIET LETTER HIGH TO;Lo;0;L;;;;;N;;;;; +AA96;TAI VIET LETTER LOW THO;Lo;0;L;;;;;N;;;;; +AA97;TAI VIET LETTER HIGH THO;Lo;0;L;;;;;N;;;;; +AA98;TAI VIET LETTER LOW NO;Lo;0;L;;;;;N;;;;; +AA99;TAI VIET LETTER HIGH NO;Lo;0;L;;;;;N;;;;; +AA9A;TAI VIET LETTER LOW BO;Lo;0;L;;;;;N;;;;; +AA9B;TAI VIET LETTER HIGH BO;Lo;0;L;;;;;N;;;;; +AA9C;TAI VIET LETTER LOW PO;Lo;0;L;;;;;N;;;;; +AA9D;TAI VIET LETTER HIGH PO;Lo;0;L;;;;;N;;;;; +AA9E;TAI VIET LETTER LOW PHO;Lo;0;L;;;;;N;;;;; +AA9F;TAI VIET LETTER HIGH PHO;Lo;0;L;;;;;N;;;;; +AAA0;TAI VIET LETTER LOW FO;Lo;0;L;;;;;N;;;;; +AAA1;TAI VIET LETTER HIGH FO;Lo;0;L;;;;;N;;;;; +AAA2;TAI VIET LETTER LOW MO;Lo;0;L;;;;;N;;;;; +AAA3;TAI VIET LETTER HIGH MO;Lo;0;L;;;;;N;;;;; +AAA4;TAI VIET LETTER LOW YO;Lo;0;L;;;;;N;;;;; +AAA5;TAI VIET LETTER HIGH YO;Lo;0;L;;;;;N;;;;; +AAA6;TAI VIET LETTER LOW RO;Lo;0;L;;;;;N;;;;; +AAA7;TAI VIET LETTER HIGH RO;Lo;0;L;;;;;N;;;;; +AAA8;TAI VIET LETTER LOW LO;Lo;0;L;;;;;N;;;;; +AAA9;TAI VIET LETTER HIGH LO;Lo;0;L;;;;;N;;;;; +AAAA;TAI VIET LETTER LOW VO;Lo;0;L;;;;;N;;;;; +AAAB;TAI VIET LETTER HIGH VO;Lo;0;L;;;;;N;;;;; +AAAC;TAI VIET LETTER LOW HO;Lo;0;L;;;;;N;;;;; +AAAD;TAI VIET LETTER HIGH HO;Lo;0;L;;;;;N;;;;; +AAAE;TAI VIET LETTER LOW O;Lo;0;L;;;;;N;;;;; +AAAF;TAI VIET LETTER HIGH O;Lo;0;L;;;;;N;;;;; +AAB0;TAI VIET MAI KANG;Mn;230;NSM;;;;;N;;;;; +AAB1;TAI VIET VOWEL AA;Lo;0;L;;;;;N;;;;; +AAB2;TAI VIET VOWEL I;Mn;230;NSM;;;;;N;;;;; +AAB3;TAI VIET VOWEL UE;Mn;230;NSM;;;;;N;;;;; +AAB4;TAI VIET VOWEL U;Mn;220;NSM;;;;;N;;;;; +AAB5;TAI VIET VOWEL E;Lo;0;L;;;;;N;;;;; +AAB6;TAI VIET VOWEL O;Lo;0;L;;;;;N;;;;; +AAB7;TAI VIET MAI KHIT;Mn;230;NSM;;;;;N;;;;; +AAB8;TAI VIET VOWEL IA;Mn;230;NSM;;;;;N;;;;; +AAB9;TAI VIET VOWEL UEA;Lo;0;L;;;;;N;;;;; +AABA;TAI VIET VOWEL UA;Lo;0;L;;;;;N;;;;; +AABB;TAI VIET VOWEL AUE;Lo;0;L;;;;;N;;;;; +AABC;TAI VIET VOWEL AY;Lo;0;L;;;;;N;;;;; +AABD;TAI VIET VOWEL AN;Lo;0;L;;;;;N;;;;; +AABE;TAI VIET VOWEL AM;Mn;230;NSM;;;;;N;;;;; +AABF;TAI VIET TONE MAI EK;Mn;230;NSM;;;;;N;;;;; +AAC0;TAI VIET TONE MAI NUENG;Lo;0;L;;;;;N;;;;; +AAC1;TAI VIET TONE MAI THO;Mn;230;NSM;;;;;N;;;;; +AAC2;TAI VIET TONE MAI SONG;Lo;0;L;;;;;N;;;;; +AADB;TAI VIET SYMBOL KON;Lo;0;L;;;;;N;;;;; +AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; +AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; +AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; +AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; +AAE0;MEETEI MAYEK LETTER E;Lo;0;L;;;;;N;;;;; +AAE1;MEETEI MAYEK LETTER O;Lo;0;L;;;;;N;;;;; +AAE2;MEETEI MAYEK LETTER CHA;Lo;0;L;;;;;N;;;;; +AAE3;MEETEI MAYEK LETTER NYA;Lo;0;L;;;;;N;;;;; +AAE4;MEETEI MAYEK LETTER TTA;Lo;0;L;;;;;N;;;;; +AAE5;MEETEI MAYEK LETTER TTHA;Lo;0;L;;;;;N;;;;; +AAE6;MEETEI MAYEK LETTER DDA;Lo;0;L;;;;;N;;;;; +AAE7;MEETEI MAYEK LETTER DDHA;Lo;0;L;;;;;N;;;;; +AAE8;MEETEI MAYEK LETTER NNA;Lo;0;L;;;;;N;;;;; +AAE9;MEETEI MAYEK LETTER SHA;Lo;0;L;;;;;N;;;;; +AAEA;MEETEI MAYEK LETTER SSA;Lo;0;L;;;;;N;;;;; +AAEB;MEETEI MAYEK VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +AAEC;MEETEI MAYEK VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +AAED;MEETEI MAYEK VOWEL SIGN AAI;Mn;0;NSM;;;;;N;;;;; +AAEE;MEETEI MAYEK VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +AAEF;MEETEI MAYEK VOWEL SIGN AAU;Mc;0;L;;;;;N;;;;; +AAF0;MEETEI MAYEK CHEIKHAN;Po;0;L;;;;;N;;;;; +AAF1;MEETEI MAYEK AHANG KHUDAM;Po;0;L;;;;;N;;;;; +AAF2;MEETEI MAYEK ANJI;Lo;0;L;;;;;N;;;;; +AAF3;MEETEI MAYEK SYLLABLE REPETITION MARK;Lm;0;L;;;;;N;;;;; +AAF4;MEETEI MAYEK WORD REPETITION MARK;Lm;0;L;;;;;N;;;;; +AAF5;MEETEI MAYEK VOWEL SIGN VISARGA;Mc;0;L;;;;;N;;;;; +AAF6;MEETEI MAYEK VIRAMA;Mn;9;NSM;;;;;N;;;;; +AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;; +AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;; +AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;; +AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;; +AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;; +AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;; +AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;; +AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;; +AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;; +AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;; +AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;; +AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;; +AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;; +AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;; +AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;; +AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;; +AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;; +AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;; +AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;; +AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;; +AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;; +AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;; +AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;; +AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;; +AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;; +AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;; +AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;; +AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;; +AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;; +AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;; +AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;; +AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;; +AB30;LATIN SMALL LETTER BARRED ALPHA;Ll;0;L;;;;;N;;;;; +AB31;LATIN SMALL LETTER A REVERSED-SCHWA;Ll;0;L;;;;;N;;;;; +AB32;LATIN SMALL LETTER BLACKLETTER E;Ll;0;L;;;;;N;;;;; +AB33;LATIN SMALL LETTER BARRED E;Ll;0;L;;;;;N;;;;; +AB34;LATIN SMALL LETTER E WITH FLOURISH;Ll;0;L;;;;;N;;;;; +AB35;LATIN SMALL LETTER LENIS F;Ll;0;L;;;;;N;;;;; +AB36;LATIN SMALL LETTER SCRIPT G WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB37;LATIN SMALL LETTER L WITH INVERTED LAZY S;Ll;0;L;;;;;N;;;;; +AB38;LATIN SMALL LETTER L WITH DOUBLE MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +AB39;LATIN SMALL LETTER L WITH MIDDLE RING;Ll;0;L;;;;;N;;;;; +AB3A;LATIN SMALL LETTER M WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3B;LATIN SMALL LETTER N WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3C;LATIN SMALL LETTER ENG WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB3D;LATIN SMALL LETTER BLACKLETTER O;Ll;0;L;;;;;N;;;;; +AB3E;LATIN SMALL LETTER BLACKLETTER O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB3F;LATIN SMALL LETTER OPEN O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB40;LATIN SMALL LETTER INVERTED OE;Ll;0;L;;;;;N;;;;; +AB41;LATIN SMALL LETTER TURNED OE WITH STROKE;Ll;0;L;;;;;N;;;;; +AB42;LATIN SMALL LETTER TURNED OE WITH HORIZONTAL STROKE;Ll;0;L;;;;;N;;;;; +AB43;LATIN SMALL LETTER TURNED O OPEN-O;Ll;0;L;;;;;N;;;;; +AB44;LATIN SMALL LETTER TURNED O OPEN-O WITH STROKE;Ll;0;L;;;;;N;;;;; +AB45;LATIN SMALL LETTER STIRRUP R;Ll;0;L;;;;;N;;;;; +AB46;LATIN LETTER SMALL CAPITAL R WITH RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB47;LATIN SMALL LETTER R WITHOUT HANDLE;Ll;0;L;;;;;N;;;;; +AB48;LATIN SMALL LETTER DOUBLE R;Ll;0;L;;;;;N;;;;; +AB49;LATIN SMALL LETTER R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB4A;LATIN SMALL LETTER DOUBLE R WITH CROSSED-TAIL;Ll;0;L;;;;;N;;;;; +AB4B;LATIN SMALL LETTER SCRIPT R;Ll;0;L;;;;;N;;;;; +AB4C;LATIN SMALL LETTER SCRIPT R WITH RING;Ll;0;L;;;;;N;;;;; +AB4D;LATIN SMALL LETTER BASELINE ESH;Ll;0;L;;;;;N;;;;; +AB4E;LATIN SMALL LETTER U WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB4F;LATIN SMALL LETTER U BAR WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB50;LATIN SMALL LETTER UI;Ll;0;L;;;;;N;;;;; +AB51;LATIN SMALL LETTER TURNED UI;Ll;0;L;;;;;N;;;;; +AB52;LATIN SMALL LETTER U WITH LEFT HOOK;Ll;0;L;;;;;N;;;;; +AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;A7B3;;A7B3 +AB54;LATIN SMALL LETTER CHI WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB55;LATIN SMALL LETTER CHI WITH LOW LEFT SERIF;Ll;0;L;;;;;N;;;;; +AB56;LATIN SMALL LETTER X WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB57;LATIN SMALL LETTER X WITH LONG LEFT LEG;Ll;0;L;;;;;N;;;;; +AB58;LATIN SMALL LETTER X WITH LONG LEFT LEG AND LOW RIGHT RING;Ll;0;L;;;;;N;;;;; +AB59;LATIN SMALL LETTER X WITH LONG LEFT LEG WITH SERIF;Ll;0;L;;;;;N;;;;; +AB5A;LATIN SMALL LETTER Y WITH SHORT RIGHT LEG;Ll;0;L;;;;;N;;;;; +AB5B;MODIFIER BREVE WITH INVERTED BREVE;Sk;0;L;;;;;N;;;;; +AB5C;MODIFIER LETTER SMALL HENG;Lm;0;L; A727;;;;N;;;;; +AB5D;MODIFIER LETTER SMALL L WITH INVERTED LAZY S;Lm;0;L; AB37;;;;N;;;;; +AB5E;MODIFIER LETTER SMALL L WITH MIDDLE TILDE;Lm;0;L; 026B;;;;N;;;;; +AB5F;MODIFIER LETTER SMALL U WITH LEFT HOOK;Lm;0;L; AB52;;;;N;;;;; +AB60;LATIN SMALL LETTER SAKHA YAT;Ll;0;L;;;;;N;;;;; +AB61;LATIN SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;;; +AB62;LATIN SMALL LETTER OPEN OE;Ll;0;L;;;;;N;;;;; +AB63;LATIN SMALL LETTER UO;Ll;0;L;;;;;N;;;;; +AB64;LATIN SMALL LETTER INVERTED ALPHA;Ll;0;L;;;;;N;;;;; +AB65;GREEK LETTER SMALL CAPITAL OMEGA;Ll;0;L;;;;;N;;;;; +AB66;LATIN SMALL LETTER DZ DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +AB67;LATIN SMALL LETTER TS DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +AB68;LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE;Ll;0;L;;;;;N;;;;; +AB69;MODIFIER LETTER SMALL TURNED W;Lm;0;L; 028D;;;;N;;;;; +AB6A;MODIFIER LETTER LEFT TACK;Sk;0;ON;;;;;N;;;;; +AB6B;MODIFIER LETTER RIGHT TACK;Sk;0;ON;;;;;N;;;;; +AB70;CHEROKEE SMALL LETTER A;Ll;0;L;;;;;N;;;13A0;;13A0 +AB71;CHEROKEE SMALL LETTER E;Ll;0;L;;;;;N;;;13A1;;13A1 +AB72;CHEROKEE SMALL LETTER I;Ll;0;L;;;;;N;;;13A2;;13A2 +AB73;CHEROKEE SMALL LETTER O;Ll;0;L;;;;;N;;;13A3;;13A3 +AB74;CHEROKEE SMALL LETTER U;Ll;0;L;;;;;N;;;13A4;;13A4 +AB75;CHEROKEE SMALL LETTER V;Ll;0;L;;;;;N;;;13A5;;13A5 +AB76;CHEROKEE SMALL LETTER GA;Ll;0;L;;;;;N;;;13A6;;13A6 +AB77;CHEROKEE SMALL LETTER KA;Ll;0;L;;;;;N;;;13A7;;13A7 +AB78;CHEROKEE SMALL LETTER GE;Ll;0;L;;;;;N;;;13A8;;13A8 +AB79;CHEROKEE SMALL LETTER GI;Ll;0;L;;;;;N;;;13A9;;13A9 +AB7A;CHEROKEE SMALL LETTER GO;Ll;0;L;;;;;N;;;13AA;;13AA +AB7B;CHEROKEE SMALL LETTER GU;Ll;0;L;;;;;N;;;13AB;;13AB +AB7C;CHEROKEE SMALL LETTER GV;Ll;0;L;;;;;N;;;13AC;;13AC +AB7D;CHEROKEE SMALL LETTER HA;Ll;0;L;;;;;N;;;13AD;;13AD +AB7E;CHEROKEE SMALL LETTER HE;Ll;0;L;;;;;N;;;13AE;;13AE +AB7F;CHEROKEE SMALL LETTER HI;Ll;0;L;;;;;N;;;13AF;;13AF +AB80;CHEROKEE SMALL LETTER HO;Ll;0;L;;;;;N;;;13B0;;13B0 +AB81;CHEROKEE SMALL LETTER HU;Ll;0;L;;;;;N;;;13B1;;13B1 +AB82;CHEROKEE SMALL LETTER HV;Ll;0;L;;;;;N;;;13B2;;13B2 +AB83;CHEROKEE SMALL LETTER LA;Ll;0;L;;;;;N;;;13B3;;13B3 +AB84;CHEROKEE SMALL LETTER LE;Ll;0;L;;;;;N;;;13B4;;13B4 +AB85;CHEROKEE SMALL LETTER LI;Ll;0;L;;;;;N;;;13B5;;13B5 +AB86;CHEROKEE SMALL LETTER LO;Ll;0;L;;;;;N;;;13B6;;13B6 +AB87;CHEROKEE SMALL LETTER LU;Ll;0;L;;;;;N;;;13B7;;13B7 +AB88;CHEROKEE SMALL LETTER LV;Ll;0;L;;;;;N;;;13B8;;13B8 +AB89;CHEROKEE SMALL LETTER MA;Ll;0;L;;;;;N;;;13B9;;13B9 +AB8A;CHEROKEE SMALL LETTER ME;Ll;0;L;;;;;N;;;13BA;;13BA +AB8B;CHEROKEE SMALL LETTER MI;Ll;0;L;;;;;N;;;13BB;;13BB +AB8C;CHEROKEE SMALL LETTER MO;Ll;0;L;;;;;N;;;13BC;;13BC +AB8D;CHEROKEE SMALL LETTER MU;Ll;0;L;;;;;N;;;13BD;;13BD +AB8E;CHEROKEE SMALL LETTER NA;Ll;0;L;;;;;N;;;13BE;;13BE +AB8F;CHEROKEE SMALL LETTER HNA;Ll;0;L;;;;;N;;;13BF;;13BF +AB90;CHEROKEE SMALL LETTER NAH;Ll;0;L;;;;;N;;;13C0;;13C0 +AB91;CHEROKEE SMALL LETTER NE;Ll;0;L;;;;;N;;;13C1;;13C1 +AB92;CHEROKEE SMALL LETTER NI;Ll;0;L;;;;;N;;;13C2;;13C2 +AB93;CHEROKEE SMALL LETTER NO;Ll;0;L;;;;;N;;;13C3;;13C3 +AB94;CHEROKEE SMALL LETTER NU;Ll;0;L;;;;;N;;;13C4;;13C4 +AB95;CHEROKEE SMALL LETTER NV;Ll;0;L;;;;;N;;;13C5;;13C5 +AB96;CHEROKEE SMALL LETTER QUA;Ll;0;L;;;;;N;;;13C6;;13C6 +AB97;CHEROKEE SMALL LETTER QUE;Ll;0;L;;;;;N;;;13C7;;13C7 +AB98;CHEROKEE SMALL LETTER QUI;Ll;0;L;;;;;N;;;13C8;;13C8 +AB99;CHEROKEE SMALL LETTER QUO;Ll;0;L;;;;;N;;;13C9;;13C9 +AB9A;CHEROKEE SMALL LETTER QUU;Ll;0;L;;;;;N;;;13CA;;13CA +AB9B;CHEROKEE SMALL LETTER QUV;Ll;0;L;;;;;N;;;13CB;;13CB +AB9C;CHEROKEE SMALL LETTER SA;Ll;0;L;;;;;N;;;13CC;;13CC +AB9D;CHEROKEE SMALL LETTER S;Ll;0;L;;;;;N;;;13CD;;13CD +AB9E;CHEROKEE SMALL LETTER SE;Ll;0;L;;;;;N;;;13CE;;13CE +AB9F;CHEROKEE SMALL LETTER SI;Ll;0;L;;;;;N;;;13CF;;13CF +ABA0;CHEROKEE SMALL LETTER SO;Ll;0;L;;;;;N;;;13D0;;13D0 +ABA1;CHEROKEE SMALL LETTER SU;Ll;0;L;;;;;N;;;13D1;;13D1 +ABA2;CHEROKEE SMALL LETTER SV;Ll;0;L;;;;;N;;;13D2;;13D2 +ABA3;CHEROKEE SMALL LETTER DA;Ll;0;L;;;;;N;;;13D3;;13D3 +ABA4;CHEROKEE SMALL LETTER TA;Ll;0;L;;;;;N;;;13D4;;13D4 +ABA5;CHEROKEE SMALL LETTER DE;Ll;0;L;;;;;N;;;13D5;;13D5 +ABA6;CHEROKEE SMALL LETTER TE;Ll;0;L;;;;;N;;;13D6;;13D6 +ABA7;CHEROKEE SMALL LETTER DI;Ll;0;L;;;;;N;;;13D7;;13D7 +ABA8;CHEROKEE SMALL LETTER TI;Ll;0;L;;;;;N;;;13D8;;13D8 +ABA9;CHEROKEE SMALL LETTER DO;Ll;0;L;;;;;N;;;13D9;;13D9 +ABAA;CHEROKEE SMALL LETTER DU;Ll;0;L;;;;;N;;;13DA;;13DA +ABAB;CHEROKEE SMALL LETTER DV;Ll;0;L;;;;;N;;;13DB;;13DB +ABAC;CHEROKEE SMALL LETTER DLA;Ll;0;L;;;;;N;;;13DC;;13DC +ABAD;CHEROKEE SMALL LETTER TLA;Ll;0;L;;;;;N;;;13DD;;13DD +ABAE;CHEROKEE SMALL LETTER TLE;Ll;0;L;;;;;N;;;13DE;;13DE +ABAF;CHEROKEE SMALL LETTER TLI;Ll;0;L;;;;;N;;;13DF;;13DF +ABB0;CHEROKEE SMALL LETTER TLO;Ll;0;L;;;;;N;;;13E0;;13E0 +ABB1;CHEROKEE SMALL LETTER TLU;Ll;0;L;;;;;N;;;13E1;;13E1 +ABB2;CHEROKEE SMALL LETTER TLV;Ll;0;L;;;;;N;;;13E2;;13E2 +ABB3;CHEROKEE SMALL LETTER TSA;Ll;0;L;;;;;N;;;13E3;;13E3 +ABB4;CHEROKEE SMALL LETTER TSE;Ll;0;L;;;;;N;;;13E4;;13E4 +ABB5;CHEROKEE SMALL LETTER TSI;Ll;0;L;;;;;N;;;13E5;;13E5 +ABB6;CHEROKEE SMALL LETTER TSO;Ll;0;L;;;;;N;;;13E6;;13E6 +ABB7;CHEROKEE SMALL LETTER TSU;Ll;0;L;;;;;N;;;13E7;;13E7 +ABB8;CHEROKEE SMALL LETTER TSV;Ll;0;L;;;;;N;;;13E8;;13E8 +ABB9;CHEROKEE SMALL LETTER WA;Ll;0;L;;;;;N;;;13E9;;13E9 +ABBA;CHEROKEE SMALL LETTER WE;Ll;0;L;;;;;N;;;13EA;;13EA +ABBB;CHEROKEE SMALL LETTER WI;Ll;0;L;;;;;N;;;13EB;;13EB +ABBC;CHEROKEE SMALL LETTER WO;Ll;0;L;;;;;N;;;13EC;;13EC +ABBD;CHEROKEE SMALL LETTER WU;Ll;0;L;;;;;N;;;13ED;;13ED +ABBE;CHEROKEE SMALL LETTER WV;Ll;0;L;;;;;N;;;13EE;;13EE +ABBF;CHEROKEE SMALL LETTER YA;Ll;0;L;;;;;N;;;13EF;;13EF +ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; +ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; +ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; +ABC3;MEETEI MAYEK LETTER MIT;Lo;0;L;;;;;N;;;;; +ABC4;MEETEI MAYEK LETTER PA;Lo;0;L;;;;;N;;;;; +ABC5;MEETEI MAYEK LETTER NA;Lo;0;L;;;;;N;;;;; +ABC6;MEETEI MAYEK LETTER CHIL;Lo;0;L;;;;;N;;;;; +ABC7;MEETEI MAYEK LETTER TIL;Lo;0;L;;;;;N;;;;; +ABC8;MEETEI MAYEK LETTER KHOU;Lo;0;L;;;;;N;;;;; +ABC9;MEETEI MAYEK LETTER NGOU;Lo;0;L;;;;;N;;;;; +ABCA;MEETEI MAYEK LETTER THOU;Lo;0;L;;;;;N;;;;; +ABCB;MEETEI MAYEK LETTER WAI;Lo;0;L;;;;;N;;;;; +ABCC;MEETEI MAYEK LETTER YANG;Lo;0;L;;;;;N;;;;; +ABCD;MEETEI MAYEK LETTER HUK;Lo;0;L;;;;;N;;;;; +ABCE;MEETEI MAYEK LETTER UN;Lo;0;L;;;;;N;;;;; +ABCF;MEETEI MAYEK LETTER I;Lo;0;L;;;;;N;;;;; +ABD0;MEETEI MAYEK LETTER PHAM;Lo;0;L;;;;;N;;;;; +ABD1;MEETEI MAYEK LETTER ATIYA;Lo;0;L;;;;;N;;;;; +ABD2;MEETEI MAYEK LETTER GOK;Lo;0;L;;;;;N;;;;; +ABD3;MEETEI MAYEK LETTER JHAM;Lo;0;L;;;;;N;;;;; +ABD4;MEETEI MAYEK LETTER RAI;Lo;0;L;;;;;N;;;;; +ABD5;MEETEI MAYEK LETTER BA;Lo;0;L;;;;;N;;;;; +ABD6;MEETEI MAYEK LETTER JIL;Lo;0;L;;;;;N;;;;; +ABD7;MEETEI MAYEK LETTER DIL;Lo;0;L;;;;;N;;;;; +ABD8;MEETEI MAYEK LETTER GHOU;Lo;0;L;;;;;N;;;;; +ABD9;MEETEI MAYEK LETTER DHOU;Lo;0;L;;;;;N;;;;; +ABDA;MEETEI MAYEK LETTER BHAM;Lo;0;L;;;;;N;;;;; +ABDB;MEETEI MAYEK LETTER KOK LONSUM;Lo;0;L;;;;;N;;;;; +ABDC;MEETEI MAYEK LETTER LAI LONSUM;Lo;0;L;;;;;N;;;;; +ABDD;MEETEI MAYEK LETTER MIT LONSUM;Lo;0;L;;;;;N;;;;; +ABDE;MEETEI MAYEK LETTER PA LONSUM;Lo;0;L;;;;;N;;;;; +ABDF;MEETEI MAYEK LETTER NA LONSUM;Lo;0;L;;;;;N;;;;; +ABE0;MEETEI MAYEK LETTER TIL LONSUM;Lo;0;L;;;;;N;;;;; +ABE1;MEETEI MAYEK LETTER NGOU LONSUM;Lo;0;L;;;;;N;;;;; +ABE2;MEETEI MAYEK LETTER I LONSUM;Lo;0;L;;;;;N;;;;; +ABE3;MEETEI MAYEK VOWEL SIGN ONAP;Mc;0;L;;;;;N;;;;; +ABE4;MEETEI MAYEK VOWEL SIGN INAP;Mc;0;L;;;;;N;;;;; +ABE5;MEETEI MAYEK VOWEL SIGN ANAP;Mn;0;NSM;;;;;N;;;;; +ABE6;MEETEI MAYEK VOWEL SIGN YENAP;Mc;0;L;;;;;N;;;;; +ABE7;MEETEI MAYEK VOWEL SIGN SOUNAP;Mc;0;L;;;;;N;;;;; +ABE8;MEETEI MAYEK VOWEL SIGN UNAP;Mn;0;NSM;;;;;N;;;;; +ABE9;MEETEI MAYEK VOWEL SIGN CHEINAP;Mc;0;L;;;;;N;;;;; +ABEA;MEETEI MAYEK VOWEL SIGN NUNG;Mc;0;L;;;;;N;;;;; +ABEB;MEETEI MAYEK CHEIKHEI;Po;0;L;;;;;N;;;;; +ABEC;MEETEI MAYEK LUM IYEK;Mc;0;L;;;;;N;;;;; +ABED;MEETEI MAYEK APUN IYEK;Mn;9;NSM;;;;;N;;;;; +ABF0;MEETEI MAYEK DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +ABF1;MEETEI MAYEK DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +ABF2;MEETEI MAYEK DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +ABF3;MEETEI MAYEK DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +ABF4;MEETEI MAYEK DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +ABF5;MEETEI MAYEK DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +ABF6;MEETEI MAYEK DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +ABF7;MEETEI MAYEK DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +ABF8;MEETEI MAYEK DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +ABF9;MEETEI MAYEK DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +AC00;;Lo;0;L;;;;;N;;;;; +D7A3;;Lo;0;L;;;;;N;;;;; +D7B0;HANGUL JUNGSEONG O-YEO;Lo;0;L;;;;;N;;;;; +D7B1;HANGUL JUNGSEONG O-O-I;Lo;0;L;;;;;N;;;;; +D7B2;HANGUL JUNGSEONG YO-A;Lo;0;L;;;;;N;;;;; +D7B3;HANGUL JUNGSEONG YO-AE;Lo;0;L;;;;;N;;;;; +D7B4;HANGUL JUNGSEONG YO-EO;Lo;0;L;;;;;N;;;;; +D7B5;HANGUL JUNGSEONG U-YEO;Lo;0;L;;;;;N;;;;; +D7B6;HANGUL JUNGSEONG U-I-I;Lo;0;L;;;;;N;;;;; +D7B7;HANGUL JUNGSEONG YU-AE;Lo;0;L;;;;;N;;;;; +D7B8;HANGUL JUNGSEONG YU-O;Lo;0;L;;;;;N;;;;; +D7B9;HANGUL JUNGSEONG EU-A;Lo;0;L;;;;;N;;;;; +D7BA;HANGUL JUNGSEONG EU-EO;Lo;0;L;;;;;N;;;;; +D7BB;HANGUL JUNGSEONG EU-E;Lo;0;L;;;;;N;;;;; +D7BC;HANGUL JUNGSEONG EU-O;Lo;0;L;;;;;N;;;;; +D7BD;HANGUL JUNGSEONG I-YA-O;Lo;0;L;;;;;N;;;;; +D7BE;HANGUL JUNGSEONG I-YAE;Lo;0;L;;;;;N;;;;; +D7BF;HANGUL JUNGSEONG I-YEO;Lo;0;L;;;;;N;;;;; +D7C0;HANGUL JUNGSEONG I-YE;Lo;0;L;;;;;N;;;;; +D7C1;HANGUL JUNGSEONG I-O-I;Lo;0;L;;;;;N;;;;; +D7C2;HANGUL JUNGSEONG I-YO;Lo;0;L;;;;;N;;;;; +D7C3;HANGUL JUNGSEONG I-YU;Lo;0;L;;;;;N;;;;; +D7C4;HANGUL JUNGSEONG I-I;Lo;0;L;;;;;N;;;;; +D7C5;HANGUL JUNGSEONG ARAEA-A;Lo;0;L;;;;;N;;;;; +D7C6;HANGUL JUNGSEONG ARAEA-E;Lo;0;L;;;;;N;;;;; +D7CB;HANGUL JONGSEONG NIEUN-RIEUL;Lo;0;L;;;;;N;;;;; +D7CC;HANGUL JONGSEONG NIEUN-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7CD;HANGUL JONGSEONG SSANGTIKEUT;Lo;0;L;;;;;N;;;;; +D7CE;HANGUL JONGSEONG SSANGTIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +D7CF;HANGUL JONGSEONG TIKEUT-PIEUP;Lo;0;L;;;;;N;;;;; +D7D0;HANGUL JONGSEONG TIKEUT-SIOS;Lo;0;L;;;;;N;;;;; +D7D1;HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +D7D2;HANGUL JONGSEONG TIKEUT-CIEUC;Lo;0;L;;;;;N;;;;; +D7D3;HANGUL JONGSEONG TIKEUT-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7D4;HANGUL JONGSEONG TIKEUT-THIEUTH;Lo;0;L;;;;;N;;;;; +D7D5;HANGUL JONGSEONG RIEUL-SSANGKIYEOK;Lo;0;L;;;;;N;;;;; +D7D6;HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH;Lo;0;L;;;;;N;;;;; +D7D7;HANGUL JONGSEONG SSANGRIEUL-KHIEUKH;Lo;0;L;;;;;N;;;;; +D7D8;HANGUL JONGSEONG RIEUL-MIEUM-HIEUH;Lo;0;L;;;;;N;;;;; +D7D9;HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +D7DA;HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH;Lo;0;L;;;;;N;;;;; +D7DB;HANGUL JONGSEONG RIEUL-YESIEUNG;Lo;0;L;;;;;N;;;;; +D7DC;HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH;Lo;0;L;;;;;N;;;;; +D7DD;HANGUL JONGSEONG KAPYEOUNRIEUL;Lo;0;L;;;;;N;;;;; +D7DE;HANGUL JONGSEONG MIEUM-NIEUN;Lo;0;L;;;;;N;;;;; +D7DF;HANGUL JONGSEONG MIEUM-SSANGNIEUN;Lo;0;L;;;;;N;;;;; +D7E0;HANGUL JONGSEONG SSANGMIEUM;Lo;0;L;;;;;N;;;;; +D7E1;HANGUL JONGSEONG MIEUM-PIEUP-SIOS;Lo;0;L;;;;;N;;;;; +D7E2;HANGUL JONGSEONG MIEUM-CIEUC;Lo;0;L;;;;;N;;;;; +D7E3;HANGUL JONGSEONG PIEUP-TIKEUT;Lo;0;L;;;;;N;;;;; +D7E4;HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH;Lo;0;L;;;;;N;;;;; +D7E5;HANGUL JONGSEONG PIEUP-MIEUM;Lo;0;L;;;;;N;;;;; +D7E6;HANGUL JONGSEONG SSANGPIEUP;Lo;0;L;;;;;N;;;;; +D7E7;HANGUL JONGSEONG PIEUP-SIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +D7E8;HANGUL JONGSEONG PIEUP-CIEUC;Lo;0;L;;;;;N;;;;; +D7E9;HANGUL JONGSEONG PIEUP-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7EA;HANGUL JONGSEONG SIOS-MIEUM;Lo;0;L;;;;;N;;;;; +D7EB;HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +D7EC;HANGUL JONGSEONG SSANGSIOS-KIYEOK;Lo;0;L;;;;;N;;;;; +D7ED;HANGUL JONGSEONG SSANGSIOS-TIKEUT;Lo;0;L;;;;;N;;;;; +D7EE;HANGUL JONGSEONG SIOS-PANSIOS;Lo;0;L;;;;;N;;;;; +D7EF;HANGUL JONGSEONG SIOS-CIEUC;Lo;0;L;;;;;N;;;;; +D7F0;HANGUL JONGSEONG SIOS-CHIEUCH;Lo;0;L;;;;;N;;;;; +D7F1;HANGUL JONGSEONG SIOS-THIEUTH;Lo;0;L;;;;;N;;;;; +D7F2;HANGUL JONGSEONG SIOS-HIEUH;Lo;0;L;;;;;N;;;;; +D7F3;HANGUL JONGSEONG PANSIOS-PIEUP;Lo;0;L;;;;;N;;;;; +D7F4;HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP;Lo;0;L;;;;;N;;;;; +D7F5;HANGUL JONGSEONG YESIEUNG-MIEUM;Lo;0;L;;;;;N;;;;; +D7F6;HANGUL JONGSEONG YESIEUNG-HIEUH;Lo;0;L;;;;;N;;;;; +D7F7;HANGUL JONGSEONG CIEUC-PIEUP;Lo;0;L;;;;;N;;;;; +D7F8;HANGUL JONGSEONG CIEUC-SSANGPIEUP;Lo;0;L;;;;;N;;;;; +D7F9;HANGUL JONGSEONG SSANGCIEUC;Lo;0;L;;;;;N;;;;; +D7FA;HANGUL JONGSEONG PHIEUPH-SIOS;Lo;0;L;;;;;N;;;;; +D7FB;HANGUL JONGSEONG PHIEUPH-THIEUTH;Lo;0;L;;;;;N;;;;; +D800;;Cs;0;L;;;;;N;;;;; +DB7F;;Cs;0;L;;;;;N;;;;; +DB80;;Cs;0;L;;;;;N;;;;; +DBFF;;Cs;0;L;;;;;N;;;;; +DC00;;Cs;0;L;;;;;N;;;;; +DFFF;;Cs;0;L;;;;;N;;;;; +E000;;Co;0;L;;;;;N;;;;; +F8FF;;Co;0;L;;;;;N;;;;; +F900;CJK COMPATIBILITY IDEOGRAPH-F900;Lo;0;L;8C48;;;;N;;;;; +F901;CJK COMPATIBILITY IDEOGRAPH-F901;Lo;0;L;66F4;;;;N;;;;; +F902;CJK COMPATIBILITY IDEOGRAPH-F902;Lo;0;L;8ECA;;;;N;;;;; +F903;CJK COMPATIBILITY IDEOGRAPH-F903;Lo;0;L;8CC8;;;;N;;;;; +F904;CJK COMPATIBILITY IDEOGRAPH-F904;Lo;0;L;6ED1;;;;N;;;;; +F905;CJK COMPATIBILITY IDEOGRAPH-F905;Lo;0;L;4E32;;;;N;;;;; +F906;CJK COMPATIBILITY IDEOGRAPH-F906;Lo;0;L;53E5;;;;N;;;;; +F907;CJK COMPATIBILITY IDEOGRAPH-F907;Lo;0;L;9F9C;;;;N;;;;; +F908;CJK COMPATIBILITY IDEOGRAPH-F908;Lo;0;L;9F9C;;;;N;;;;; +F909;CJK COMPATIBILITY IDEOGRAPH-F909;Lo;0;L;5951;;;;N;;;;; +F90A;CJK COMPATIBILITY IDEOGRAPH-F90A;Lo;0;L;91D1;;;;N;;;;; +F90B;CJK COMPATIBILITY IDEOGRAPH-F90B;Lo;0;L;5587;;;;N;;;;; +F90C;CJK COMPATIBILITY IDEOGRAPH-F90C;Lo;0;L;5948;;;;N;;;;; +F90D;CJK COMPATIBILITY IDEOGRAPH-F90D;Lo;0;L;61F6;;;;N;;;;; +F90E;CJK COMPATIBILITY IDEOGRAPH-F90E;Lo;0;L;7669;;;;N;;;;; +F90F;CJK COMPATIBILITY IDEOGRAPH-F90F;Lo;0;L;7F85;;;;N;;;;; +F910;CJK COMPATIBILITY IDEOGRAPH-F910;Lo;0;L;863F;;;;N;;;;; +F911;CJK COMPATIBILITY IDEOGRAPH-F911;Lo;0;L;87BA;;;;N;;;;; +F912;CJK COMPATIBILITY IDEOGRAPH-F912;Lo;0;L;88F8;;;;N;;;;; +F913;CJK COMPATIBILITY IDEOGRAPH-F913;Lo;0;L;908F;;;;N;;;;; +F914;CJK COMPATIBILITY IDEOGRAPH-F914;Lo;0;L;6A02;;;;N;;;;; +F915;CJK COMPATIBILITY IDEOGRAPH-F915;Lo;0;L;6D1B;;;;N;;;;; +F916;CJK COMPATIBILITY IDEOGRAPH-F916;Lo;0;L;70D9;;;;N;;;;; +F917;CJK COMPATIBILITY IDEOGRAPH-F917;Lo;0;L;73DE;;;;N;;;;; +F918;CJK COMPATIBILITY IDEOGRAPH-F918;Lo;0;L;843D;;;;N;;;;; +F919;CJK COMPATIBILITY IDEOGRAPH-F919;Lo;0;L;916A;;;;N;;;;; +F91A;CJK COMPATIBILITY IDEOGRAPH-F91A;Lo;0;L;99F1;;;;N;;;;; +F91B;CJK COMPATIBILITY IDEOGRAPH-F91B;Lo;0;L;4E82;;;;N;;;;; +F91C;CJK COMPATIBILITY IDEOGRAPH-F91C;Lo;0;L;5375;;;;N;;;;; +F91D;CJK COMPATIBILITY IDEOGRAPH-F91D;Lo;0;L;6B04;;;;N;;;;; +F91E;CJK COMPATIBILITY IDEOGRAPH-F91E;Lo;0;L;721B;;;;N;;;;; +F91F;CJK COMPATIBILITY IDEOGRAPH-F91F;Lo;0;L;862D;;;;N;;;;; +F920;CJK COMPATIBILITY IDEOGRAPH-F920;Lo;0;L;9E1E;;;;N;;;;; +F921;CJK COMPATIBILITY IDEOGRAPH-F921;Lo;0;L;5D50;;;;N;;;;; +F922;CJK COMPATIBILITY IDEOGRAPH-F922;Lo;0;L;6FEB;;;;N;;;;; +F923;CJK COMPATIBILITY IDEOGRAPH-F923;Lo;0;L;85CD;;;;N;;;;; +F924;CJK COMPATIBILITY IDEOGRAPH-F924;Lo;0;L;8964;;;;N;;;;; +F925;CJK COMPATIBILITY IDEOGRAPH-F925;Lo;0;L;62C9;;;;N;;;;; +F926;CJK COMPATIBILITY IDEOGRAPH-F926;Lo;0;L;81D8;;;;N;;;;; +F927;CJK COMPATIBILITY IDEOGRAPH-F927;Lo;0;L;881F;;;;N;;;;; +F928;CJK COMPATIBILITY IDEOGRAPH-F928;Lo;0;L;5ECA;;;;N;;;;; +F929;CJK COMPATIBILITY IDEOGRAPH-F929;Lo;0;L;6717;;;;N;;;;; +F92A;CJK COMPATIBILITY IDEOGRAPH-F92A;Lo;0;L;6D6A;;;;N;;;;; +F92B;CJK COMPATIBILITY IDEOGRAPH-F92B;Lo;0;L;72FC;;;;N;;;;; +F92C;CJK COMPATIBILITY IDEOGRAPH-F92C;Lo;0;L;90CE;;;;N;;;;; +F92D;CJK COMPATIBILITY IDEOGRAPH-F92D;Lo;0;L;4F86;;;;N;;;;; +F92E;CJK COMPATIBILITY IDEOGRAPH-F92E;Lo;0;L;51B7;;;;N;;;;; +F92F;CJK COMPATIBILITY IDEOGRAPH-F92F;Lo;0;L;52DE;;;;N;;;;; +F930;CJK COMPATIBILITY IDEOGRAPH-F930;Lo;0;L;64C4;;;;N;;;;; +F931;CJK COMPATIBILITY IDEOGRAPH-F931;Lo;0;L;6AD3;;;;N;;;;; +F932;CJK COMPATIBILITY IDEOGRAPH-F932;Lo;0;L;7210;;;;N;;;;; +F933;CJK COMPATIBILITY IDEOGRAPH-F933;Lo;0;L;76E7;;;;N;;;;; +F934;CJK COMPATIBILITY IDEOGRAPH-F934;Lo;0;L;8001;;;;N;;;;; +F935;CJK COMPATIBILITY IDEOGRAPH-F935;Lo;0;L;8606;;;;N;;;;; +F936;CJK COMPATIBILITY IDEOGRAPH-F936;Lo;0;L;865C;;;;N;;;;; +F937;CJK COMPATIBILITY IDEOGRAPH-F937;Lo;0;L;8DEF;;;;N;;;;; +F938;CJK COMPATIBILITY IDEOGRAPH-F938;Lo;0;L;9732;;;;N;;;;; +F939;CJK COMPATIBILITY IDEOGRAPH-F939;Lo;0;L;9B6F;;;;N;;;;; +F93A;CJK COMPATIBILITY IDEOGRAPH-F93A;Lo;0;L;9DFA;;;;N;;;;; +F93B;CJK COMPATIBILITY IDEOGRAPH-F93B;Lo;0;L;788C;;;;N;;;;; +F93C;CJK COMPATIBILITY IDEOGRAPH-F93C;Lo;0;L;797F;;;;N;;;;; +F93D;CJK COMPATIBILITY IDEOGRAPH-F93D;Lo;0;L;7DA0;;;;N;;;;; +F93E;CJK COMPATIBILITY IDEOGRAPH-F93E;Lo;0;L;83C9;;;;N;;;;; +F93F;CJK COMPATIBILITY IDEOGRAPH-F93F;Lo;0;L;9304;;;;N;;;;; +F940;CJK COMPATIBILITY IDEOGRAPH-F940;Lo;0;L;9E7F;;;;N;;;;; +F941;CJK COMPATIBILITY IDEOGRAPH-F941;Lo;0;L;8AD6;;;;N;;;;; +F942;CJK COMPATIBILITY IDEOGRAPH-F942;Lo;0;L;58DF;;;;N;;;;; +F943;CJK COMPATIBILITY IDEOGRAPH-F943;Lo;0;L;5F04;;;;N;;;;; +F944;CJK COMPATIBILITY IDEOGRAPH-F944;Lo;0;L;7C60;;;;N;;;;; +F945;CJK COMPATIBILITY IDEOGRAPH-F945;Lo;0;L;807E;;;;N;;;;; +F946;CJK COMPATIBILITY IDEOGRAPH-F946;Lo;0;L;7262;;;;N;;;;; +F947;CJK COMPATIBILITY IDEOGRAPH-F947;Lo;0;L;78CA;;;;N;;;;; +F948;CJK COMPATIBILITY IDEOGRAPH-F948;Lo;0;L;8CC2;;;;N;;;;; +F949;CJK COMPATIBILITY IDEOGRAPH-F949;Lo;0;L;96F7;;;;N;;;;; +F94A;CJK COMPATIBILITY IDEOGRAPH-F94A;Lo;0;L;58D8;;;;N;;;;; +F94B;CJK COMPATIBILITY IDEOGRAPH-F94B;Lo;0;L;5C62;;;;N;;;;; +F94C;CJK COMPATIBILITY IDEOGRAPH-F94C;Lo;0;L;6A13;;;;N;;;;; +F94D;CJK COMPATIBILITY IDEOGRAPH-F94D;Lo;0;L;6DDA;;;;N;;;;; +F94E;CJK COMPATIBILITY IDEOGRAPH-F94E;Lo;0;L;6F0F;;;;N;;;;; +F94F;CJK COMPATIBILITY IDEOGRAPH-F94F;Lo;0;L;7D2F;;;;N;;;;; +F950;CJK COMPATIBILITY IDEOGRAPH-F950;Lo;0;L;7E37;;;;N;;;;; +F951;CJK COMPATIBILITY IDEOGRAPH-F951;Lo;0;L;964B;;;;N;;;;; +F952;CJK COMPATIBILITY IDEOGRAPH-F952;Lo;0;L;52D2;;;;N;;;;; +F953;CJK COMPATIBILITY IDEOGRAPH-F953;Lo;0;L;808B;;;;N;;;;; +F954;CJK COMPATIBILITY IDEOGRAPH-F954;Lo;0;L;51DC;;;;N;;;;; +F955;CJK COMPATIBILITY IDEOGRAPH-F955;Lo;0;L;51CC;;;;N;;;;; +F956;CJK COMPATIBILITY IDEOGRAPH-F956;Lo;0;L;7A1C;;;;N;;;;; +F957;CJK COMPATIBILITY IDEOGRAPH-F957;Lo;0;L;7DBE;;;;N;;;;; +F958;CJK COMPATIBILITY IDEOGRAPH-F958;Lo;0;L;83F1;;;;N;;;;; +F959;CJK COMPATIBILITY IDEOGRAPH-F959;Lo;0;L;9675;;;;N;;;;; +F95A;CJK COMPATIBILITY IDEOGRAPH-F95A;Lo;0;L;8B80;;;;N;;;;; +F95B;CJK COMPATIBILITY IDEOGRAPH-F95B;Lo;0;L;62CF;;;;N;;;;; +F95C;CJK COMPATIBILITY IDEOGRAPH-F95C;Lo;0;L;6A02;;;;N;;;;; +F95D;CJK COMPATIBILITY IDEOGRAPH-F95D;Lo;0;L;8AFE;;;;N;;;;; +F95E;CJK COMPATIBILITY IDEOGRAPH-F95E;Lo;0;L;4E39;;;;N;;;;; +F95F;CJK COMPATIBILITY IDEOGRAPH-F95F;Lo;0;L;5BE7;;;;N;;;;; +F960;CJK COMPATIBILITY IDEOGRAPH-F960;Lo;0;L;6012;;;;N;;;;; +F961;CJK COMPATIBILITY IDEOGRAPH-F961;Lo;0;L;7387;;;;N;;;;; +F962;CJK COMPATIBILITY IDEOGRAPH-F962;Lo;0;L;7570;;;;N;;;;; +F963;CJK COMPATIBILITY IDEOGRAPH-F963;Lo;0;L;5317;;;;N;;;;; +F964;CJK COMPATIBILITY IDEOGRAPH-F964;Lo;0;L;78FB;;;;N;;;;; +F965;CJK COMPATIBILITY IDEOGRAPH-F965;Lo;0;L;4FBF;;;;N;;;;; +F966;CJK COMPATIBILITY IDEOGRAPH-F966;Lo;0;L;5FA9;;;;N;;;;; +F967;CJK COMPATIBILITY IDEOGRAPH-F967;Lo;0;L;4E0D;;;;N;;;;; +F968;CJK COMPATIBILITY IDEOGRAPH-F968;Lo;0;L;6CCC;;;;N;;;;; +F969;CJK COMPATIBILITY IDEOGRAPH-F969;Lo;0;L;6578;;;;N;;;;; +F96A;CJK COMPATIBILITY IDEOGRAPH-F96A;Lo;0;L;7D22;;;;N;;;;; +F96B;CJK COMPATIBILITY IDEOGRAPH-F96B;Lo;0;L;53C3;;;3;N;;;;; +F96C;CJK COMPATIBILITY IDEOGRAPH-F96C;Lo;0;L;585E;;;;N;;;;; +F96D;CJK COMPATIBILITY IDEOGRAPH-F96D;Lo;0;L;7701;;;;N;;;;; +F96E;CJK COMPATIBILITY IDEOGRAPH-F96E;Lo;0;L;8449;;;;N;;;;; +F96F;CJK COMPATIBILITY IDEOGRAPH-F96F;Lo;0;L;8AAA;;;;N;;;;; +F970;CJK COMPATIBILITY IDEOGRAPH-F970;Lo;0;L;6BBA;;;;N;;;;; +F971;CJK COMPATIBILITY IDEOGRAPH-F971;Lo;0;L;8FB0;;;;N;;;;; +F972;CJK COMPATIBILITY IDEOGRAPH-F972;Lo;0;L;6C88;;;;N;;;;; +F973;CJK COMPATIBILITY IDEOGRAPH-F973;Lo;0;L;62FE;;;10;N;;;;; +F974;CJK COMPATIBILITY IDEOGRAPH-F974;Lo;0;L;82E5;;;;N;;;;; +F975;CJK COMPATIBILITY IDEOGRAPH-F975;Lo;0;L;63A0;;;;N;;;;; +F976;CJK COMPATIBILITY IDEOGRAPH-F976;Lo;0;L;7565;;;;N;;;;; +F977;CJK COMPATIBILITY IDEOGRAPH-F977;Lo;0;L;4EAE;;;;N;;;;; +F978;CJK COMPATIBILITY IDEOGRAPH-F978;Lo;0;L;5169;;;2;N;;;;; +F979;CJK COMPATIBILITY IDEOGRAPH-F979;Lo;0;L;51C9;;;;N;;;;; +F97A;CJK COMPATIBILITY IDEOGRAPH-F97A;Lo;0;L;6881;;;;N;;;;; +F97B;CJK COMPATIBILITY IDEOGRAPH-F97B;Lo;0;L;7CE7;;;;N;;;;; +F97C;CJK COMPATIBILITY IDEOGRAPH-F97C;Lo;0;L;826F;;;;N;;;;; +F97D;CJK COMPATIBILITY IDEOGRAPH-F97D;Lo;0;L;8AD2;;;;N;;;;; +F97E;CJK COMPATIBILITY IDEOGRAPH-F97E;Lo;0;L;91CF;;;;N;;;;; +F97F;CJK COMPATIBILITY IDEOGRAPH-F97F;Lo;0;L;52F5;;;;N;;;;; +F980;CJK COMPATIBILITY IDEOGRAPH-F980;Lo;0;L;5442;;;;N;;;;; +F981;CJK COMPATIBILITY IDEOGRAPH-F981;Lo;0;L;5973;;;;N;;;;; +F982;CJK COMPATIBILITY IDEOGRAPH-F982;Lo;0;L;5EEC;;;;N;;;;; +F983;CJK COMPATIBILITY IDEOGRAPH-F983;Lo;0;L;65C5;;;;N;;;;; +F984;CJK COMPATIBILITY IDEOGRAPH-F984;Lo;0;L;6FFE;;;;N;;;;; +F985;CJK COMPATIBILITY IDEOGRAPH-F985;Lo;0;L;792A;;;;N;;;;; +F986;CJK COMPATIBILITY IDEOGRAPH-F986;Lo;0;L;95AD;;;;N;;;;; +F987;CJK COMPATIBILITY IDEOGRAPH-F987;Lo;0;L;9A6A;;;;N;;;;; +F988;CJK COMPATIBILITY IDEOGRAPH-F988;Lo;0;L;9E97;;;;N;;;;; +F989;CJK COMPATIBILITY IDEOGRAPH-F989;Lo;0;L;9ECE;;;;N;;;;; +F98A;CJK COMPATIBILITY IDEOGRAPH-F98A;Lo;0;L;529B;;;;N;;;;; +F98B;CJK COMPATIBILITY IDEOGRAPH-F98B;Lo;0;L;66C6;;;;N;;;;; +F98C;CJK COMPATIBILITY IDEOGRAPH-F98C;Lo;0;L;6B77;;;;N;;;;; +F98D;CJK COMPATIBILITY IDEOGRAPH-F98D;Lo;0;L;8F62;;;;N;;;;; +F98E;CJK COMPATIBILITY IDEOGRAPH-F98E;Lo;0;L;5E74;;;;N;;;;; +F98F;CJK COMPATIBILITY IDEOGRAPH-F98F;Lo;0;L;6190;;;;N;;;;; +F990;CJK COMPATIBILITY IDEOGRAPH-F990;Lo;0;L;6200;;;;N;;;;; +F991;CJK COMPATIBILITY IDEOGRAPH-F991;Lo;0;L;649A;;;;N;;;;; +F992;CJK COMPATIBILITY IDEOGRAPH-F992;Lo;0;L;6F23;;;;N;;;;; +F993;CJK COMPATIBILITY IDEOGRAPH-F993;Lo;0;L;7149;;;;N;;;;; +F994;CJK COMPATIBILITY IDEOGRAPH-F994;Lo;0;L;7489;;;;N;;;;; +F995;CJK COMPATIBILITY IDEOGRAPH-F995;Lo;0;L;79CA;;;;N;;;;; +F996;CJK COMPATIBILITY IDEOGRAPH-F996;Lo;0;L;7DF4;;;;N;;;;; +F997;CJK COMPATIBILITY IDEOGRAPH-F997;Lo;0;L;806F;;;;N;;;;; +F998;CJK COMPATIBILITY IDEOGRAPH-F998;Lo;0;L;8F26;;;;N;;;;; +F999;CJK COMPATIBILITY IDEOGRAPH-F999;Lo;0;L;84EE;;;;N;;;;; +F99A;CJK COMPATIBILITY IDEOGRAPH-F99A;Lo;0;L;9023;;;;N;;;;; +F99B;CJK COMPATIBILITY IDEOGRAPH-F99B;Lo;0;L;934A;;;;N;;;;; +F99C;CJK COMPATIBILITY IDEOGRAPH-F99C;Lo;0;L;5217;;;;N;;;;; +F99D;CJK COMPATIBILITY IDEOGRAPH-F99D;Lo;0;L;52A3;;;;N;;;;; +F99E;CJK COMPATIBILITY IDEOGRAPH-F99E;Lo;0;L;54BD;;;;N;;;;; +F99F;CJK COMPATIBILITY IDEOGRAPH-F99F;Lo;0;L;70C8;;;;N;;;;; +F9A0;CJK COMPATIBILITY IDEOGRAPH-F9A0;Lo;0;L;88C2;;;;N;;;;; +F9A1;CJK COMPATIBILITY IDEOGRAPH-F9A1;Lo;0;L;8AAA;;;;N;;;;; +F9A2;CJK COMPATIBILITY IDEOGRAPH-F9A2;Lo;0;L;5EC9;;;;N;;;;; +F9A3;CJK COMPATIBILITY IDEOGRAPH-F9A3;Lo;0;L;5FF5;;;;N;;;;; +F9A4;CJK COMPATIBILITY IDEOGRAPH-F9A4;Lo;0;L;637B;;;;N;;;;; +F9A5;CJK COMPATIBILITY IDEOGRAPH-F9A5;Lo;0;L;6BAE;;;;N;;;;; +F9A6;CJK COMPATIBILITY IDEOGRAPH-F9A6;Lo;0;L;7C3E;;;;N;;;;; +F9A7;CJK COMPATIBILITY IDEOGRAPH-F9A7;Lo;0;L;7375;;;;N;;;;; +F9A8;CJK COMPATIBILITY IDEOGRAPH-F9A8;Lo;0;L;4EE4;;;;N;;;;; +F9A9;CJK COMPATIBILITY IDEOGRAPH-F9A9;Lo;0;L;56F9;;;;N;;;;; +F9AA;CJK COMPATIBILITY IDEOGRAPH-F9AA;Lo;0;L;5BE7;;;;N;;;;; +F9AB;CJK COMPATIBILITY IDEOGRAPH-F9AB;Lo;0;L;5DBA;;;;N;;;;; +F9AC;CJK COMPATIBILITY IDEOGRAPH-F9AC;Lo;0;L;601C;;;;N;;;;; +F9AD;CJK COMPATIBILITY IDEOGRAPH-F9AD;Lo;0;L;73B2;;;;N;;;;; +F9AE;CJK COMPATIBILITY IDEOGRAPH-F9AE;Lo;0;L;7469;;;;N;;;;; +F9AF;CJK COMPATIBILITY IDEOGRAPH-F9AF;Lo;0;L;7F9A;;;;N;;;;; +F9B0;CJK COMPATIBILITY IDEOGRAPH-F9B0;Lo;0;L;8046;;;;N;;;;; +F9B1;CJK COMPATIBILITY IDEOGRAPH-F9B1;Lo;0;L;9234;;;;N;;;;; +F9B2;CJK COMPATIBILITY IDEOGRAPH-F9B2;Lo;0;L;96F6;;;0;N;;;;; +F9B3;CJK COMPATIBILITY IDEOGRAPH-F9B3;Lo;0;L;9748;;;;N;;;;; +F9B4;CJK COMPATIBILITY IDEOGRAPH-F9B4;Lo;0;L;9818;;;;N;;;;; +F9B5;CJK COMPATIBILITY IDEOGRAPH-F9B5;Lo;0;L;4F8B;;;;N;;;;; +F9B6;CJK COMPATIBILITY IDEOGRAPH-F9B6;Lo;0;L;79AE;;;;N;;;;; +F9B7;CJK COMPATIBILITY IDEOGRAPH-F9B7;Lo;0;L;91B4;;;;N;;;;; +F9B8;CJK COMPATIBILITY IDEOGRAPH-F9B8;Lo;0;L;96B8;;;;N;;;;; +F9B9;CJK COMPATIBILITY IDEOGRAPH-F9B9;Lo;0;L;60E1;;;;N;;;;; +F9BA;CJK COMPATIBILITY IDEOGRAPH-F9BA;Lo;0;L;4E86;;;;N;;;;; +F9BB;CJK COMPATIBILITY IDEOGRAPH-F9BB;Lo;0;L;50DA;;;;N;;;;; +F9BC;CJK COMPATIBILITY IDEOGRAPH-F9BC;Lo;0;L;5BEE;;;;N;;;;; +F9BD;CJK COMPATIBILITY IDEOGRAPH-F9BD;Lo;0;L;5C3F;;;;N;;;;; +F9BE;CJK COMPATIBILITY IDEOGRAPH-F9BE;Lo;0;L;6599;;;;N;;;;; +F9BF;CJK COMPATIBILITY IDEOGRAPH-F9BF;Lo;0;L;6A02;;;;N;;;;; +F9C0;CJK COMPATIBILITY IDEOGRAPH-F9C0;Lo;0;L;71CE;;;;N;;;;; +F9C1;CJK COMPATIBILITY IDEOGRAPH-F9C1;Lo;0;L;7642;;;;N;;;;; +F9C2;CJK COMPATIBILITY IDEOGRAPH-F9C2;Lo;0;L;84FC;;;;N;;;;; +F9C3;CJK COMPATIBILITY IDEOGRAPH-F9C3;Lo;0;L;907C;;;;N;;;;; +F9C4;CJK COMPATIBILITY IDEOGRAPH-F9C4;Lo;0;L;9F8D;;;;N;;;;; +F9C5;CJK COMPATIBILITY IDEOGRAPH-F9C5;Lo;0;L;6688;;;;N;;;;; +F9C6;CJK COMPATIBILITY IDEOGRAPH-F9C6;Lo;0;L;962E;;;;N;;;;; +F9C7;CJK COMPATIBILITY IDEOGRAPH-F9C7;Lo;0;L;5289;;;;N;;;;; +F9C8;CJK COMPATIBILITY IDEOGRAPH-F9C8;Lo;0;L;677B;;;;N;;;;; +F9C9;CJK COMPATIBILITY IDEOGRAPH-F9C9;Lo;0;L;67F3;;;;N;;;;; +F9CA;CJK COMPATIBILITY IDEOGRAPH-F9CA;Lo;0;L;6D41;;;;N;;;;; +F9CB;CJK COMPATIBILITY IDEOGRAPH-F9CB;Lo;0;L;6E9C;;;;N;;;;; +F9CC;CJK COMPATIBILITY IDEOGRAPH-F9CC;Lo;0;L;7409;;;;N;;;;; +F9CD;CJK COMPATIBILITY IDEOGRAPH-F9CD;Lo;0;L;7559;;;;N;;;;; +F9CE;CJK COMPATIBILITY IDEOGRAPH-F9CE;Lo;0;L;786B;;;;N;;;;; +F9CF;CJK COMPATIBILITY IDEOGRAPH-F9CF;Lo;0;L;7D10;;;;N;;;;; +F9D0;CJK COMPATIBILITY IDEOGRAPH-F9D0;Lo;0;L;985E;;;;N;;;;; +F9D1;CJK COMPATIBILITY IDEOGRAPH-F9D1;Lo;0;L;516D;;;6;N;;;;; +F9D2;CJK COMPATIBILITY IDEOGRAPH-F9D2;Lo;0;L;622E;;;;N;;;;; +F9D3;CJK COMPATIBILITY IDEOGRAPH-F9D3;Lo;0;L;9678;;;6;N;;;;; +F9D4;CJK COMPATIBILITY IDEOGRAPH-F9D4;Lo;0;L;502B;;;;N;;;;; +F9D5;CJK COMPATIBILITY IDEOGRAPH-F9D5;Lo;0;L;5D19;;;;N;;;;; +F9D6;CJK COMPATIBILITY IDEOGRAPH-F9D6;Lo;0;L;6DEA;;;;N;;;;; +F9D7;CJK COMPATIBILITY IDEOGRAPH-F9D7;Lo;0;L;8F2A;;;;N;;;;; +F9D8;CJK COMPATIBILITY IDEOGRAPH-F9D8;Lo;0;L;5F8B;;;;N;;;;; +F9D9;CJK COMPATIBILITY IDEOGRAPH-F9D9;Lo;0;L;6144;;;;N;;;;; +F9DA;CJK COMPATIBILITY IDEOGRAPH-F9DA;Lo;0;L;6817;;;;N;;;;; +F9DB;CJK COMPATIBILITY IDEOGRAPH-F9DB;Lo;0;L;7387;;;;N;;;;; +F9DC;CJK COMPATIBILITY IDEOGRAPH-F9DC;Lo;0;L;9686;;;;N;;;;; +F9DD;CJK COMPATIBILITY IDEOGRAPH-F9DD;Lo;0;L;5229;;;;N;;;;; +F9DE;CJK COMPATIBILITY IDEOGRAPH-F9DE;Lo;0;L;540F;;;;N;;;;; +F9DF;CJK COMPATIBILITY IDEOGRAPH-F9DF;Lo;0;L;5C65;;;;N;;;;; +F9E0;CJK COMPATIBILITY IDEOGRAPH-F9E0;Lo;0;L;6613;;;;N;;;;; +F9E1;CJK COMPATIBILITY IDEOGRAPH-F9E1;Lo;0;L;674E;;;;N;;;;; +F9E2;CJK COMPATIBILITY IDEOGRAPH-F9E2;Lo;0;L;68A8;;;;N;;;;; +F9E3;CJK COMPATIBILITY IDEOGRAPH-F9E3;Lo;0;L;6CE5;;;;N;;;;; +F9E4;CJK COMPATIBILITY IDEOGRAPH-F9E4;Lo;0;L;7406;;;;N;;;;; +F9E5;CJK COMPATIBILITY IDEOGRAPH-F9E5;Lo;0;L;75E2;;;;N;;;;; +F9E6;CJK COMPATIBILITY IDEOGRAPH-F9E6;Lo;0;L;7F79;;;;N;;;;; +F9E7;CJK COMPATIBILITY IDEOGRAPH-F9E7;Lo;0;L;88CF;;;;N;;;;; +F9E8;CJK COMPATIBILITY IDEOGRAPH-F9E8;Lo;0;L;88E1;;;;N;;;;; +F9E9;CJK COMPATIBILITY IDEOGRAPH-F9E9;Lo;0;L;91CC;;;;N;;;;; +F9EA;CJK COMPATIBILITY IDEOGRAPH-F9EA;Lo;0;L;96E2;;;;N;;;;; +F9EB;CJK COMPATIBILITY IDEOGRAPH-F9EB;Lo;0;L;533F;;;;N;;;;; +F9EC;CJK COMPATIBILITY IDEOGRAPH-F9EC;Lo;0;L;6EBA;;;;N;;;;; +F9ED;CJK COMPATIBILITY IDEOGRAPH-F9ED;Lo;0;L;541D;;;;N;;;;; +F9EE;CJK COMPATIBILITY IDEOGRAPH-F9EE;Lo;0;L;71D0;;;;N;;;;; +F9EF;CJK COMPATIBILITY IDEOGRAPH-F9EF;Lo;0;L;7498;;;;N;;;;; +F9F0;CJK COMPATIBILITY IDEOGRAPH-F9F0;Lo;0;L;85FA;;;;N;;;;; +F9F1;CJK COMPATIBILITY IDEOGRAPH-F9F1;Lo;0;L;96A3;;;;N;;;;; +F9F2;CJK COMPATIBILITY IDEOGRAPH-F9F2;Lo;0;L;9C57;;;;N;;;;; +F9F3;CJK COMPATIBILITY IDEOGRAPH-F9F3;Lo;0;L;9E9F;;;;N;;;;; +F9F4;CJK COMPATIBILITY IDEOGRAPH-F9F4;Lo;0;L;6797;;;;N;;;;; +F9F5;CJK COMPATIBILITY IDEOGRAPH-F9F5;Lo;0;L;6DCB;;;;N;;;;; +F9F6;CJK COMPATIBILITY IDEOGRAPH-F9F6;Lo;0;L;81E8;;;;N;;;;; +F9F7;CJK COMPATIBILITY IDEOGRAPH-F9F7;Lo;0;L;7ACB;;;;N;;;;; +F9F8;CJK COMPATIBILITY IDEOGRAPH-F9F8;Lo;0;L;7B20;;;;N;;;;; +F9F9;CJK COMPATIBILITY IDEOGRAPH-F9F9;Lo;0;L;7C92;;;;N;;;;; +F9FA;CJK COMPATIBILITY IDEOGRAPH-F9FA;Lo;0;L;72C0;;;;N;;;;; +F9FB;CJK COMPATIBILITY IDEOGRAPH-F9FB;Lo;0;L;7099;;;;N;;;;; +F9FC;CJK COMPATIBILITY IDEOGRAPH-F9FC;Lo;0;L;8B58;;;;N;;;;; +F9FD;CJK COMPATIBILITY IDEOGRAPH-F9FD;Lo;0;L;4EC0;;;10;N;;;;; +F9FE;CJK COMPATIBILITY IDEOGRAPH-F9FE;Lo;0;L;8336;;;;N;;;;; +F9FF;CJK COMPATIBILITY IDEOGRAPH-F9FF;Lo;0;L;523A;;;;N;;;;; +FA00;CJK COMPATIBILITY IDEOGRAPH-FA00;Lo;0;L;5207;;;;N;;;;; +FA01;CJK COMPATIBILITY IDEOGRAPH-FA01;Lo;0;L;5EA6;;;;N;;;;; +FA02;CJK COMPATIBILITY IDEOGRAPH-FA02;Lo;0;L;62D3;;;;N;;;;; +FA03;CJK COMPATIBILITY IDEOGRAPH-FA03;Lo;0;L;7CD6;;;;N;;;;; +FA04;CJK COMPATIBILITY IDEOGRAPH-FA04;Lo;0;L;5B85;;;;N;;;;; +FA05;CJK COMPATIBILITY IDEOGRAPH-FA05;Lo;0;L;6D1E;;;;N;;;;; +FA06;CJK COMPATIBILITY IDEOGRAPH-FA06;Lo;0;L;66B4;;;;N;;;;; +FA07;CJK COMPATIBILITY IDEOGRAPH-FA07;Lo;0;L;8F3B;;;;N;;;;; +FA08;CJK COMPATIBILITY IDEOGRAPH-FA08;Lo;0;L;884C;;;;N;;;;; +FA09;CJK COMPATIBILITY IDEOGRAPH-FA09;Lo;0;L;964D;;;;N;;;;; +FA0A;CJK COMPATIBILITY IDEOGRAPH-FA0A;Lo;0;L;898B;;;;N;;;;; +FA0B;CJK COMPATIBILITY IDEOGRAPH-FA0B;Lo;0;L;5ED3;;;;N;;;;; +FA0C;CJK COMPATIBILITY IDEOGRAPH-FA0C;Lo;0;L;5140;;;;N;;;;; +FA0D;CJK COMPATIBILITY IDEOGRAPH-FA0D;Lo;0;L;55C0;;;;N;;;;; +FA0E;CJK COMPATIBILITY IDEOGRAPH-FA0E;Lo;0;L;;;;;N;;;;; +FA0F;CJK COMPATIBILITY IDEOGRAPH-FA0F;Lo;0;L;;;;;N;;;;; +FA10;CJK COMPATIBILITY IDEOGRAPH-FA10;Lo;0;L;585A;;;;N;;;;; +FA11;CJK COMPATIBILITY IDEOGRAPH-FA11;Lo;0;L;;;;;N;;;;; +FA12;CJK COMPATIBILITY IDEOGRAPH-FA12;Lo;0;L;6674;;;;N;;;;; +FA13;CJK COMPATIBILITY IDEOGRAPH-FA13;Lo;0;L;;;;;N;;;;; +FA14;CJK COMPATIBILITY IDEOGRAPH-FA14;Lo;0;L;;;;;N;;;;; +FA15;CJK COMPATIBILITY IDEOGRAPH-FA15;Lo;0;L;51DE;;;;N;;;;; +FA16;CJK COMPATIBILITY IDEOGRAPH-FA16;Lo;0;L;732A;;;;N;;;;; +FA17;CJK COMPATIBILITY IDEOGRAPH-FA17;Lo;0;L;76CA;;;;N;;;;; +FA18;CJK COMPATIBILITY IDEOGRAPH-FA18;Lo;0;L;793C;;;;N;;;;; +FA19;CJK COMPATIBILITY IDEOGRAPH-FA19;Lo;0;L;795E;;;;N;;;;; +FA1A;CJK COMPATIBILITY IDEOGRAPH-FA1A;Lo;0;L;7965;;;;N;;;;; +FA1B;CJK COMPATIBILITY IDEOGRAPH-FA1B;Lo;0;L;798F;;;;N;;;;; +FA1C;CJK COMPATIBILITY IDEOGRAPH-FA1C;Lo;0;L;9756;;;;N;;;;; +FA1D;CJK COMPATIBILITY IDEOGRAPH-FA1D;Lo;0;L;7CBE;;;;N;;;;; +FA1E;CJK COMPATIBILITY IDEOGRAPH-FA1E;Lo;0;L;7FBD;;;;N;;;;; +FA1F;CJK COMPATIBILITY IDEOGRAPH-FA1F;Lo;0;L;;;;;N;;;;; +FA20;CJK COMPATIBILITY IDEOGRAPH-FA20;Lo;0;L;8612;;;;N;;;;; +FA21;CJK COMPATIBILITY IDEOGRAPH-FA21;Lo;0;L;;;;;N;;;;; +FA22;CJK COMPATIBILITY IDEOGRAPH-FA22;Lo;0;L;8AF8;;;;N;;;;; +FA23;CJK COMPATIBILITY IDEOGRAPH-FA23;Lo;0;L;;;;;N;;;;; +FA24;CJK COMPATIBILITY IDEOGRAPH-FA24;Lo;0;L;;;;;N;;;;; +FA25;CJK COMPATIBILITY IDEOGRAPH-FA25;Lo;0;L;9038;;;;N;;;;; +FA26;CJK COMPATIBILITY IDEOGRAPH-FA26;Lo;0;L;90FD;;;;N;;;;; +FA27;CJK COMPATIBILITY IDEOGRAPH-FA27;Lo;0;L;;;;;N;;;;; +FA28;CJK COMPATIBILITY IDEOGRAPH-FA28;Lo;0;L;;;;;N;;;;; +FA29;CJK COMPATIBILITY IDEOGRAPH-FA29;Lo;0;L;;;;;N;;;;; +FA2A;CJK COMPATIBILITY IDEOGRAPH-FA2A;Lo;0;L;98EF;;;;N;;;;; +FA2B;CJK COMPATIBILITY IDEOGRAPH-FA2B;Lo;0;L;98FC;;;;N;;;;; +FA2C;CJK COMPATIBILITY IDEOGRAPH-FA2C;Lo;0;L;9928;;;;N;;;;; +FA2D;CJK COMPATIBILITY IDEOGRAPH-FA2D;Lo;0;L;9DB4;;;;N;;;;; +FA2E;CJK COMPATIBILITY IDEOGRAPH-FA2E;Lo;0;L;90DE;;;;N;;;;; +FA2F;CJK COMPATIBILITY IDEOGRAPH-FA2F;Lo;0;L;96B7;;;;N;;;;; +FA30;CJK COMPATIBILITY IDEOGRAPH-FA30;Lo;0;L;4FAE;;;;N;;;;; +FA31;CJK COMPATIBILITY IDEOGRAPH-FA31;Lo;0;L;50E7;;;;N;;;;; +FA32;CJK COMPATIBILITY IDEOGRAPH-FA32;Lo;0;L;514D;;;;N;;;;; +FA33;CJK COMPATIBILITY IDEOGRAPH-FA33;Lo;0;L;52C9;;;;N;;;;; +FA34;CJK COMPATIBILITY IDEOGRAPH-FA34;Lo;0;L;52E4;;;;N;;;;; +FA35;CJK COMPATIBILITY IDEOGRAPH-FA35;Lo;0;L;5351;;;;N;;;;; +FA36;CJK COMPATIBILITY IDEOGRAPH-FA36;Lo;0;L;559D;;;;N;;;;; +FA37;CJK COMPATIBILITY IDEOGRAPH-FA37;Lo;0;L;5606;;;;N;;;;; +FA38;CJK COMPATIBILITY IDEOGRAPH-FA38;Lo;0;L;5668;;;;N;;;;; +FA39;CJK COMPATIBILITY IDEOGRAPH-FA39;Lo;0;L;5840;;;;N;;;;; +FA3A;CJK COMPATIBILITY IDEOGRAPH-FA3A;Lo;0;L;58A8;;;;N;;;;; +FA3B;CJK COMPATIBILITY IDEOGRAPH-FA3B;Lo;0;L;5C64;;;;N;;;;; +FA3C;CJK COMPATIBILITY IDEOGRAPH-FA3C;Lo;0;L;5C6E;;;;N;;;;; +FA3D;CJK COMPATIBILITY IDEOGRAPH-FA3D;Lo;0;L;6094;;;;N;;;;; +FA3E;CJK COMPATIBILITY IDEOGRAPH-FA3E;Lo;0;L;6168;;;;N;;;;; +FA3F;CJK COMPATIBILITY IDEOGRAPH-FA3F;Lo;0;L;618E;;;;N;;;;; +FA40;CJK COMPATIBILITY IDEOGRAPH-FA40;Lo;0;L;61F2;;;;N;;;;; +FA41;CJK COMPATIBILITY IDEOGRAPH-FA41;Lo;0;L;654F;;;;N;;;;; +FA42;CJK COMPATIBILITY IDEOGRAPH-FA42;Lo;0;L;65E2;;;;N;;;;; +FA43;CJK COMPATIBILITY IDEOGRAPH-FA43;Lo;0;L;6691;;;;N;;;;; +FA44;CJK COMPATIBILITY IDEOGRAPH-FA44;Lo;0;L;6885;;;;N;;;;; +FA45;CJK COMPATIBILITY IDEOGRAPH-FA45;Lo;0;L;6D77;;;;N;;;;; +FA46;CJK COMPATIBILITY IDEOGRAPH-FA46;Lo;0;L;6E1A;;;;N;;;;; +FA47;CJK COMPATIBILITY IDEOGRAPH-FA47;Lo;0;L;6F22;;;;N;;;;; +FA48;CJK COMPATIBILITY IDEOGRAPH-FA48;Lo;0;L;716E;;;;N;;;;; +FA49;CJK COMPATIBILITY IDEOGRAPH-FA49;Lo;0;L;722B;;;;N;;;;; +FA4A;CJK COMPATIBILITY IDEOGRAPH-FA4A;Lo;0;L;7422;;;;N;;;;; +FA4B;CJK COMPATIBILITY IDEOGRAPH-FA4B;Lo;0;L;7891;;;;N;;;;; +FA4C;CJK COMPATIBILITY IDEOGRAPH-FA4C;Lo;0;L;793E;;;;N;;;;; +FA4D;CJK COMPATIBILITY IDEOGRAPH-FA4D;Lo;0;L;7949;;;;N;;;;; +FA4E;CJK COMPATIBILITY IDEOGRAPH-FA4E;Lo;0;L;7948;;;;N;;;;; +FA4F;CJK COMPATIBILITY IDEOGRAPH-FA4F;Lo;0;L;7950;;;;N;;;;; +FA50;CJK COMPATIBILITY IDEOGRAPH-FA50;Lo;0;L;7956;;;;N;;;;; +FA51;CJK COMPATIBILITY IDEOGRAPH-FA51;Lo;0;L;795D;;;;N;;;;; +FA52;CJK COMPATIBILITY IDEOGRAPH-FA52;Lo;0;L;798D;;;;N;;;;; +FA53;CJK COMPATIBILITY IDEOGRAPH-FA53;Lo;0;L;798E;;;;N;;;;; +FA54;CJK COMPATIBILITY IDEOGRAPH-FA54;Lo;0;L;7A40;;;;N;;;;; +FA55;CJK COMPATIBILITY IDEOGRAPH-FA55;Lo;0;L;7A81;;;;N;;;;; +FA56;CJK COMPATIBILITY IDEOGRAPH-FA56;Lo;0;L;7BC0;;;;N;;;;; +FA57;CJK COMPATIBILITY IDEOGRAPH-FA57;Lo;0;L;7DF4;;;;N;;;;; +FA58;CJK COMPATIBILITY IDEOGRAPH-FA58;Lo;0;L;7E09;;;;N;;;;; +FA59;CJK COMPATIBILITY IDEOGRAPH-FA59;Lo;0;L;7E41;;;;N;;;;; +FA5A;CJK COMPATIBILITY IDEOGRAPH-FA5A;Lo;0;L;7F72;;;;N;;;;; +FA5B;CJK COMPATIBILITY IDEOGRAPH-FA5B;Lo;0;L;8005;;;;N;;;;; +FA5C;CJK COMPATIBILITY IDEOGRAPH-FA5C;Lo;0;L;81ED;;;;N;;;;; +FA5D;CJK COMPATIBILITY IDEOGRAPH-FA5D;Lo;0;L;8279;;;;N;;;;; +FA5E;CJK COMPATIBILITY IDEOGRAPH-FA5E;Lo;0;L;8279;;;;N;;;;; +FA5F;CJK COMPATIBILITY IDEOGRAPH-FA5F;Lo;0;L;8457;;;;N;;;;; +FA60;CJK COMPATIBILITY IDEOGRAPH-FA60;Lo;0;L;8910;;;;N;;;;; +FA61;CJK COMPATIBILITY IDEOGRAPH-FA61;Lo;0;L;8996;;;;N;;;;; +FA62;CJK COMPATIBILITY IDEOGRAPH-FA62;Lo;0;L;8B01;;;;N;;;;; +FA63;CJK COMPATIBILITY IDEOGRAPH-FA63;Lo;0;L;8B39;;;;N;;;;; +FA64;CJK COMPATIBILITY IDEOGRAPH-FA64;Lo;0;L;8CD3;;;;N;;;;; +FA65;CJK COMPATIBILITY IDEOGRAPH-FA65;Lo;0;L;8D08;;;;N;;;;; +FA66;CJK COMPATIBILITY IDEOGRAPH-FA66;Lo;0;L;8FB6;;;;N;;;;; +FA67;CJK COMPATIBILITY IDEOGRAPH-FA67;Lo;0;L;9038;;;;N;;;;; +FA68;CJK COMPATIBILITY IDEOGRAPH-FA68;Lo;0;L;96E3;;;;N;;;;; +FA69;CJK COMPATIBILITY IDEOGRAPH-FA69;Lo;0;L;97FF;;;;N;;;;; +FA6A;CJK COMPATIBILITY IDEOGRAPH-FA6A;Lo;0;L;983B;;;;N;;;;; +FA6B;CJK COMPATIBILITY IDEOGRAPH-FA6B;Lo;0;L;6075;;;;N;;;;; +FA6C;CJK COMPATIBILITY IDEOGRAPH-FA6C;Lo;0;L;242EE;;;;N;;;;; +FA6D;CJK COMPATIBILITY IDEOGRAPH-FA6D;Lo;0;L;8218;;;;N;;;;; +FA70;CJK COMPATIBILITY IDEOGRAPH-FA70;Lo;0;L;4E26;;;;N;;;;; +FA71;CJK COMPATIBILITY IDEOGRAPH-FA71;Lo;0;L;51B5;;;;N;;;;; +FA72;CJK COMPATIBILITY IDEOGRAPH-FA72;Lo;0;L;5168;;;;N;;;;; +FA73;CJK COMPATIBILITY IDEOGRAPH-FA73;Lo;0;L;4F80;;;;N;;;;; +FA74;CJK COMPATIBILITY IDEOGRAPH-FA74;Lo;0;L;5145;;;;N;;;;; +FA75;CJK COMPATIBILITY IDEOGRAPH-FA75;Lo;0;L;5180;;;;N;;;;; +FA76;CJK COMPATIBILITY IDEOGRAPH-FA76;Lo;0;L;52C7;;;;N;;;;; +FA77;CJK COMPATIBILITY IDEOGRAPH-FA77;Lo;0;L;52FA;;;;N;;;;; +FA78;CJK COMPATIBILITY IDEOGRAPH-FA78;Lo;0;L;559D;;;;N;;;;; +FA79;CJK COMPATIBILITY IDEOGRAPH-FA79;Lo;0;L;5555;;;;N;;;;; +FA7A;CJK COMPATIBILITY IDEOGRAPH-FA7A;Lo;0;L;5599;;;;N;;;;; +FA7B;CJK COMPATIBILITY IDEOGRAPH-FA7B;Lo;0;L;55E2;;;;N;;;;; +FA7C;CJK COMPATIBILITY IDEOGRAPH-FA7C;Lo;0;L;585A;;;;N;;;;; +FA7D;CJK COMPATIBILITY IDEOGRAPH-FA7D;Lo;0;L;58B3;;;;N;;;;; +FA7E;CJK COMPATIBILITY IDEOGRAPH-FA7E;Lo;0;L;5944;;;;N;;;;; +FA7F;CJK COMPATIBILITY IDEOGRAPH-FA7F;Lo;0;L;5954;;;;N;;;;; +FA80;CJK COMPATIBILITY IDEOGRAPH-FA80;Lo;0;L;5A62;;;;N;;;;; +FA81;CJK COMPATIBILITY IDEOGRAPH-FA81;Lo;0;L;5B28;;;;N;;;;; +FA82;CJK COMPATIBILITY IDEOGRAPH-FA82;Lo;0;L;5ED2;;;;N;;;;; +FA83;CJK COMPATIBILITY IDEOGRAPH-FA83;Lo;0;L;5ED9;;;;N;;;;; +FA84;CJK COMPATIBILITY IDEOGRAPH-FA84;Lo;0;L;5F69;;;;N;;;;; +FA85;CJK COMPATIBILITY IDEOGRAPH-FA85;Lo;0;L;5FAD;;;;N;;;;; +FA86;CJK COMPATIBILITY IDEOGRAPH-FA86;Lo;0;L;60D8;;;;N;;;;; +FA87;CJK COMPATIBILITY IDEOGRAPH-FA87;Lo;0;L;614E;;;;N;;;;; +FA88;CJK COMPATIBILITY IDEOGRAPH-FA88;Lo;0;L;6108;;;;N;;;;; +FA89;CJK COMPATIBILITY IDEOGRAPH-FA89;Lo;0;L;618E;;;;N;;;;; +FA8A;CJK COMPATIBILITY IDEOGRAPH-FA8A;Lo;0;L;6160;;;;N;;;;; +FA8B;CJK COMPATIBILITY IDEOGRAPH-FA8B;Lo;0;L;61F2;;;;N;;;;; +FA8C;CJK COMPATIBILITY IDEOGRAPH-FA8C;Lo;0;L;6234;;;;N;;;;; +FA8D;CJK COMPATIBILITY IDEOGRAPH-FA8D;Lo;0;L;63C4;;;;N;;;;; +FA8E;CJK COMPATIBILITY IDEOGRAPH-FA8E;Lo;0;L;641C;;;;N;;;;; +FA8F;CJK COMPATIBILITY IDEOGRAPH-FA8F;Lo;0;L;6452;;;;N;;;;; +FA90;CJK COMPATIBILITY IDEOGRAPH-FA90;Lo;0;L;6556;;;;N;;;;; +FA91;CJK COMPATIBILITY IDEOGRAPH-FA91;Lo;0;L;6674;;;;N;;;;; +FA92;CJK COMPATIBILITY IDEOGRAPH-FA92;Lo;0;L;6717;;;;N;;;;; +FA93;CJK COMPATIBILITY IDEOGRAPH-FA93;Lo;0;L;671B;;;;N;;;;; +FA94;CJK COMPATIBILITY IDEOGRAPH-FA94;Lo;0;L;6756;;;;N;;;;; +FA95;CJK COMPATIBILITY IDEOGRAPH-FA95;Lo;0;L;6B79;;;;N;;;;; +FA96;CJK COMPATIBILITY IDEOGRAPH-FA96;Lo;0;L;6BBA;;;;N;;;;; +FA97;CJK COMPATIBILITY IDEOGRAPH-FA97;Lo;0;L;6D41;;;;N;;;;; +FA98;CJK COMPATIBILITY IDEOGRAPH-FA98;Lo;0;L;6EDB;;;;N;;;;; +FA99;CJK COMPATIBILITY IDEOGRAPH-FA99;Lo;0;L;6ECB;;;;N;;;;; +FA9A;CJK COMPATIBILITY IDEOGRAPH-FA9A;Lo;0;L;6F22;;;;N;;;;; +FA9B;CJK COMPATIBILITY IDEOGRAPH-FA9B;Lo;0;L;701E;;;;N;;;;; +FA9C;CJK COMPATIBILITY IDEOGRAPH-FA9C;Lo;0;L;716E;;;;N;;;;; +FA9D;CJK COMPATIBILITY IDEOGRAPH-FA9D;Lo;0;L;77A7;;;;N;;;;; +FA9E;CJK COMPATIBILITY IDEOGRAPH-FA9E;Lo;0;L;7235;;;;N;;;;; +FA9F;CJK COMPATIBILITY IDEOGRAPH-FA9F;Lo;0;L;72AF;;;;N;;;;; +FAA0;CJK COMPATIBILITY IDEOGRAPH-FAA0;Lo;0;L;732A;;;;N;;;;; +FAA1;CJK COMPATIBILITY IDEOGRAPH-FAA1;Lo;0;L;7471;;;;N;;;;; +FAA2;CJK COMPATIBILITY IDEOGRAPH-FAA2;Lo;0;L;7506;;;;N;;;;; +FAA3;CJK COMPATIBILITY IDEOGRAPH-FAA3;Lo;0;L;753B;;;;N;;;;; +FAA4;CJK COMPATIBILITY IDEOGRAPH-FAA4;Lo;0;L;761D;;;;N;;;;; +FAA5;CJK COMPATIBILITY IDEOGRAPH-FAA5;Lo;0;L;761F;;;;N;;;;; +FAA6;CJK COMPATIBILITY IDEOGRAPH-FAA6;Lo;0;L;76CA;;;;N;;;;; +FAA7;CJK COMPATIBILITY IDEOGRAPH-FAA7;Lo;0;L;76DB;;;;N;;;;; +FAA8;CJK COMPATIBILITY IDEOGRAPH-FAA8;Lo;0;L;76F4;;;;N;;;;; +FAA9;CJK COMPATIBILITY IDEOGRAPH-FAA9;Lo;0;L;774A;;;;N;;;;; +FAAA;CJK COMPATIBILITY IDEOGRAPH-FAAA;Lo;0;L;7740;;;;N;;;;; +FAAB;CJK COMPATIBILITY IDEOGRAPH-FAAB;Lo;0;L;78CC;;;;N;;;;; +FAAC;CJK COMPATIBILITY IDEOGRAPH-FAAC;Lo;0;L;7AB1;;;;N;;;;; +FAAD;CJK COMPATIBILITY IDEOGRAPH-FAAD;Lo;0;L;7BC0;;;;N;;;;; +FAAE;CJK COMPATIBILITY IDEOGRAPH-FAAE;Lo;0;L;7C7B;;;;N;;;;; +FAAF;CJK COMPATIBILITY IDEOGRAPH-FAAF;Lo;0;L;7D5B;;;;N;;;;; +FAB0;CJK COMPATIBILITY IDEOGRAPH-FAB0;Lo;0;L;7DF4;;;;N;;;;; +FAB1;CJK COMPATIBILITY IDEOGRAPH-FAB1;Lo;0;L;7F3E;;;;N;;;;; +FAB2;CJK COMPATIBILITY IDEOGRAPH-FAB2;Lo;0;L;8005;;;;N;;;;; +FAB3;CJK COMPATIBILITY IDEOGRAPH-FAB3;Lo;0;L;8352;;;;N;;;;; +FAB4;CJK COMPATIBILITY IDEOGRAPH-FAB4;Lo;0;L;83EF;;;;N;;;;; +FAB5;CJK COMPATIBILITY IDEOGRAPH-FAB5;Lo;0;L;8779;;;;N;;;;; +FAB6;CJK COMPATIBILITY IDEOGRAPH-FAB6;Lo;0;L;8941;;;;N;;;;; +FAB7;CJK COMPATIBILITY IDEOGRAPH-FAB7;Lo;0;L;8986;;;;N;;;;; +FAB8;CJK COMPATIBILITY IDEOGRAPH-FAB8;Lo;0;L;8996;;;;N;;;;; +FAB9;CJK COMPATIBILITY IDEOGRAPH-FAB9;Lo;0;L;8ABF;;;;N;;;;; +FABA;CJK COMPATIBILITY IDEOGRAPH-FABA;Lo;0;L;8AF8;;;;N;;;;; +FABB;CJK COMPATIBILITY IDEOGRAPH-FABB;Lo;0;L;8ACB;;;;N;;;;; +FABC;CJK COMPATIBILITY IDEOGRAPH-FABC;Lo;0;L;8B01;;;;N;;;;; +FABD;CJK COMPATIBILITY IDEOGRAPH-FABD;Lo;0;L;8AFE;;;;N;;;;; +FABE;CJK COMPATIBILITY IDEOGRAPH-FABE;Lo;0;L;8AED;;;;N;;;;; +FABF;CJK COMPATIBILITY IDEOGRAPH-FABF;Lo;0;L;8B39;;;;N;;;;; +FAC0;CJK COMPATIBILITY IDEOGRAPH-FAC0;Lo;0;L;8B8A;;;;N;;;;; +FAC1;CJK COMPATIBILITY IDEOGRAPH-FAC1;Lo;0;L;8D08;;;;N;;;;; +FAC2;CJK COMPATIBILITY IDEOGRAPH-FAC2;Lo;0;L;8F38;;;;N;;;;; +FAC3;CJK COMPATIBILITY IDEOGRAPH-FAC3;Lo;0;L;9072;;;;N;;;;; +FAC4;CJK COMPATIBILITY IDEOGRAPH-FAC4;Lo;0;L;9199;;;;N;;;;; +FAC5;CJK COMPATIBILITY IDEOGRAPH-FAC5;Lo;0;L;9276;;;;N;;;;; +FAC6;CJK COMPATIBILITY IDEOGRAPH-FAC6;Lo;0;L;967C;;;;N;;;;; +FAC7;CJK COMPATIBILITY IDEOGRAPH-FAC7;Lo;0;L;96E3;;;;N;;;;; +FAC8;CJK COMPATIBILITY IDEOGRAPH-FAC8;Lo;0;L;9756;;;;N;;;;; +FAC9;CJK COMPATIBILITY IDEOGRAPH-FAC9;Lo;0;L;97DB;;;;N;;;;; +FACA;CJK COMPATIBILITY IDEOGRAPH-FACA;Lo;0;L;97FF;;;;N;;;;; +FACB;CJK COMPATIBILITY IDEOGRAPH-FACB;Lo;0;L;980B;;;;N;;;;; +FACC;CJK COMPATIBILITY IDEOGRAPH-FACC;Lo;0;L;983B;;;;N;;;;; +FACD;CJK COMPATIBILITY IDEOGRAPH-FACD;Lo;0;L;9B12;;;;N;;;;; +FACE;CJK COMPATIBILITY IDEOGRAPH-FACE;Lo;0;L;9F9C;;;;N;;;;; +FACF;CJK COMPATIBILITY IDEOGRAPH-FACF;Lo;0;L;2284A;;;;N;;;;; +FAD0;CJK COMPATIBILITY IDEOGRAPH-FAD0;Lo;0;L;22844;;;;N;;;;; +FAD1;CJK COMPATIBILITY IDEOGRAPH-FAD1;Lo;0;L;233D5;;;;N;;;;; +FAD2;CJK COMPATIBILITY IDEOGRAPH-FAD2;Lo;0;L;3B9D;;;;N;;;;; +FAD3;CJK COMPATIBILITY IDEOGRAPH-FAD3;Lo;0;L;4018;;;;N;;;;; +FAD4;CJK COMPATIBILITY IDEOGRAPH-FAD4;Lo;0;L;4039;;;;N;;;;; +FAD5;CJK COMPATIBILITY IDEOGRAPH-FAD5;Lo;0;L;25249;;;;N;;;;; +FAD6;CJK COMPATIBILITY IDEOGRAPH-FAD6;Lo;0;L;25CD0;;;;N;;;;; +FAD7;CJK COMPATIBILITY IDEOGRAPH-FAD7;Lo;0;L;27ED3;;;;N;;;;; +FAD8;CJK COMPATIBILITY IDEOGRAPH-FAD8;Lo;0;L;9F43;;;;N;;;;; +FAD9;CJK COMPATIBILITY IDEOGRAPH-FAD9;Lo;0;L;9F8E;;;;N;;;;; +FB00;LATIN SMALL LIGATURE FF;Ll;0;L; 0066 0066;;;;N;;;;; +FB01;LATIN SMALL LIGATURE FI;Ll;0;L; 0066 0069;;;;N;;;;; +FB02;LATIN SMALL LIGATURE FL;Ll;0;L; 0066 006C;;;;N;;;;; +FB03;LATIN SMALL LIGATURE FFI;Ll;0;L; 0066 0066 0069;;;;N;;;;; +FB04;LATIN SMALL LIGATURE FFL;Ll;0;L; 0066 0066 006C;;;;N;;;;; +FB05;LATIN SMALL LIGATURE LONG S T;Ll;0;L; 017F 0074;;;;N;;;;; +FB06;LATIN SMALL LIGATURE ST;Ll;0;L; 0073 0074;;;;N;;;;; +FB13;ARMENIAN SMALL LIGATURE MEN NOW;Ll;0;L; 0574 0576;;;;N;;;;; +FB14;ARMENIAN SMALL LIGATURE MEN ECH;Ll;0;L; 0574 0565;;;;N;;;;; +FB15;ARMENIAN SMALL LIGATURE MEN INI;Ll;0;L; 0574 056B;;;;N;;;;; +FB16;ARMENIAN SMALL LIGATURE VEW NOW;Ll;0;L; 057E 0576;;;;N;;;;; +FB17;ARMENIAN SMALL LIGATURE MEN XEH;Ll;0;L; 0574 056D;;;;N;;;;; +FB1D;HEBREW LETTER YOD WITH HIRIQ;Lo;0;R;05D9 05B4;;;;N;;;;; +FB1E;HEBREW POINT JUDEO-SPANISH VARIKA;Mn;26;NSM;;;;;N;HEBREW POINT VARIKA;;;; +FB1F;HEBREW LIGATURE YIDDISH YOD YOD PATAH;Lo;0;R;05F2 05B7;;;;N;;;;; +FB20;HEBREW LETTER ALTERNATIVE AYIN;Lo;0;R; 05E2;;;;N;;;;; +FB21;HEBREW LETTER WIDE ALEF;Lo;0;R; 05D0;;;;N;;;;; +FB22;HEBREW LETTER WIDE DALET;Lo;0;R; 05D3;;;;N;;;;; +FB23;HEBREW LETTER WIDE HE;Lo;0;R; 05D4;;;;N;;;;; +FB24;HEBREW LETTER WIDE KAF;Lo;0;R; 05DB;;;;N;;;;; +FB25;HEBREW LETTER WIDE LAMED;Lo;0;R; 05DC;;;;N;;;;; +FB26;HEBREW LETTER WIDE FINAL MEM;Lo;0;R; 05DD;;;;N;;;;; +FB27;HEBREW LETTER WIDE RESH;Lo;0;R; 05E8;;;;N;;;;; +FB28;HEBREW LETTER WIDE TAV;Lo;0;R; 05EA;;;;N;;;;; +FB29;HEBREW LETTER ALTERNATIVE PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; +FB2A;HEBREW LETTER SHIN WITH SHIN DOT;Lo;0;R;05E9 05C1;;;;N;;;;; +FB2B;HEBREW LETTER SHIN WITH SIN DOT;Lo;0;R;05E9 05C2;;;;N;;;;; +FB2C;HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT;Lo;0;R;FB49 05C1;;;;N;;;;; +FB2D;HEBREW LETTER SHIN WITH DAGESH AND SIN DOT;Lo;0;R;FB49 05C2;;;;N;;;;; +FB2E;HEBREW LETTER ALEF WITH PATAH;Lo;0;R;05D0 05B7;;;;N;;;;; +FB2F;HEBREW LETTER ALEF WITH QAMATS;Lo;0;R;05D0 05B8;;;;N;;;;; +FB30;HEBREW LETTER ALEF WITH MAPIQ;Lo;0;R;05D0 05BC;;;;N;;;;; +FB31;HEBREW LETTER BET WITH DAGESH;Lo;0;R;05D1 05BC;;;;N;;;;; +FB32;HEBREW LETTER GIMEL WITH DAGESH;Lo;0;R;05D2 05BC;;;;N;;;;; +FB33;HEBREW LETTER DALET WITH DAGESH;Lo;0;R;05D3 05BC;;;;N;;;;; +FB34;HEBREW LETTER HE WITH MAPIQ;Lo;0;R;05D4 05BC;;;;N;;;;; +FB35;HEBREW LETTER VAV WITH DAGESH;Lo;0;R;05D5 05BC;;;;N;;;;; +FB36;HEBREW LETTER ZAYIN WITH DAGESH;Lo;0;R;05D6 05BC;;;;N;;;;; +FB38;HEBREW LETTER TET WITH DAGESH;Lo;0;R;05D8 05BC;;;;N;;;;; +FB39;HEBREW LETTER YOD WITH DAGESH;Lo;0;R;05D9 05BC;;;;N;;;;; +FB3A;HEBREW LETTER FINAL KAF WITH DAGESH;Lo;0;R;05DA 05BC;;;;N;;;;; +FB3B;HEBREW LETTER KAF WITH DAGESH;Lo;0;R;05DB 05BC;;;;N;;;;; +FB3C;HEBREW LETTER LAMED WITH DAGESH;Lo;0;R;05DC 05BC;;;;N;;;;; +FB3E;HEBREW LETTER MEM WITH DAGESH;Lo;0;R;05DE 05BC;;;;N;;;;; +FB40;HEBREW LETTER NUN WITH DAGESH;Lo;0;R;05E0 05BC;;;;N;;;;; +FB41;HEBREW LETTER SAMEKH WITH DAGESH;Lo;0;R;05E1 05BC;;;;N;;;;; +FB43;HEBREW LETTER FINAL PE WITH DAGESH;Lo;0;R;05E3 05BC;;;;N;;;;; +FB44;HEBREW LETTER PE WITH DAGESH;Lo;0;R;05E4 05BC;;;;N;;;;; +FB46;HEBREW LETTER TSADI WITH DAGESH;Lo;0;R;05E6 05BC;;;;N;;;;; +FB47;HEBREW LETTER QOF WITH DAGESH;Lo;0;R;05E7 05BC;;;;N;;;;; +FB48;HEBREW LETTER RESH WITH DAGESH;Lo;0;R;05E8 05BC;;;;N;;;;; +FB49;HEBREW LETTER SHIN WITH DAGESH;Lo;0;R;05E9 05BC;;;;N;;;;; +FB4A;HEBREW LETTER TAV WITH DAGESH;Lo;0;R;05EA 05BC;;;;N;;;;; +FB4B;HEBREW LETTER VAV WITH HOLAM;Lo;0;R;05D5 05B9;;;;N;;;;; +FB4C;HEBREW LETTER BET WITH RAFE;Lo;0;R;05D1 05BF;;;;N;;;;; +FB4D;HEBREW LETTER KAF WITH RAFE;Lo;0;R;05DB 05BF;;;;N;;;;; +FB4E;HEBREW LETTER PE WITH RAFE;Lo;0;R;05E4 05BF;;;;N;;;;; +FB4F;HEBREW LIGATURE ALEF LAMED;Lo;0;R; 05D0 05DC;;;;N;;;;; +FB50;ARABIC LETTER ALEF WASLA ISOLATED FORM;Lo;0;AL; 0671;;;;N;;;;; +FB51;ARABIC LETTER ALEF WASLA FINAL FORM;Lo;0;AL; 0671;;;;N;;;;; +FB52;ARABIC LETTER BEEH ISOLATED FORM;Lo;0;AL; 067B;;;;N;;;;; +FB53;ARABIC LETTER BEEH FINAL FORM;Lo;0;AL; 067B;;;;N;;;;; +FB54;ARABIC LETTER BEEH INITIAL FORM;Lo;0;AL; 067B;;;;N;;;;; +FB55;ARABIC LETTER BEEH MEDIAL FORM;Lo;0;AL; 067B;;;;N;;;;; +FB56;ARABIC LETTER PEH ISOLATED FORM;Lo;0;AL; 067E;;;;N;;;;; +FB57;ARABIC LETTER PEH FINAL FORM;Lo;0;AL; 067E;;;;N;;;;; +FB58;ARABIC LETTER PEH INITIAL FORM;Lo;0;AL; 067E;;;;N;;;;; +FB59;ARABIC LETTER PEH MEDIAL FORM;Lo;0;AL; 067E;;;;N;;;;; +FB5A;ARABIC LETTER BEHEH ISOLATED FORM;Lo;0;AL; 0680;;;;N;;;;; +FB5B;ARABIC LETTER BEHEH FINAL FORM;Lo;0;AL; 0680;;;;N;;;;; +FB5C;ARABIC LETTER BEHEH INITIAL FORM;Lo;0;AL; 0680;;;;N;;;;; +FB5D;ARABIC LETTER BEHEH MEDIAL FORM;Lo;0;AL; 0680;;;;N;;;;; +FB5E;ARABIC LETTER TTEHEH ISOLATED FORM;Lo;0;AL; 067A;;;;N;;;;; +FB5F;ARABIC LETTER TTEHEH FINAL FORM;Lo;0;AL; 067A;;;;N;;;;; +FB60;ARABIC LETTER TTEHEH INITIAL FORM;Lo;0;AL; 067A;;;;N;;;;; +FB61;ARABIC LETTER TTEHEH MEDIAL FORM;Lo;0;AL; 067A;;;;N;;;;; +FB62;ARABIC LETTER TEHEH ISOLATED FORM;Lo;0;AL; 067F;;;;N;;;;; +FB63;ARABIC LETTER TEHEH FINAL FORM;Lo;0;AL; 067F;;;;N;;;;; +FB64;ARABIC LETTER TEHEH INITIAL FORM;Lo;0;AL; 067F;;;;N;;;;; +FB65;ARABIC LETTER TEHEH MEDIAL FORM;Lo;0;AL; 067F;;;;N;;;;; +FB66;ARABIC LETTER TTEH ISOLATED FORM;Lo;0;AL; 0679;;;;N;;;;; +FB67;ARABIC LETTER TTEH FINAL FORM;Lo;0;AL; 0679;;;;N;;;;; +FB68;ARABIC LETTER TTEH INITIAL FORM;Lo;0;AL; 0679;;;;N;;;;; +FB69;ARABIC LETTER TTEH MEDIAL FORM;Lo;0;AL; 0679;;;;N;;;;; +FB6A;ARABIC LETTER VEH ISOLATED FORM;Lo;0;AL; 06A4;;;;N;;;;; +FB6B;ARABIC LETTER VEH FINAL FORM;Lo;0;AL; 06A4;;;;N;;;;; +FB6C;ARABIC LETTER VEH INITIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; +FB6D;ARABIC LETTER VEH MEDIAL FORM;Lo;0;AL; 06A4;;;;N;;;;; +FB6E;ARABIC LETTER PEHEH ISOLATED FORM;Lo;0;AL; 06A6;;;;N;;;;; +FB6F;ARABIC LETTER PEHEH FINAL FORM;Lo;0;AL; 06A6;;;;N;;;;; +FB70;ARABIC LETTER PEHEH INITIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; +FB71;ARABIC LETTER PEHEH MEDIAL FORM;Lo;0;AL; 06A6;;;;N;;;;; +FB72;ARABIC LETTER DYEH ISOLATED FORM;Lo;0;AL; 0684;;;;N;;;;; +FB73;ARABIC LETTER DYEH FINAL FORM;Lo;0;AL; 0684;;;;N;;;;; +FB74;ARABIC LETTER DYEH INITIAL FORM;Lo;0;AL; 0684;;;;N;;;;; +FB75;ARABIC LETTER DYEH MEDIAL FORM;Lo;0;AL; 0684;;;;N;;;;; +FB76;ARABIC LETTER NYEH ISOLATED FORM;Lo;0;AL; 0683;;;;N;;;;; +FB77;ARABIC LETTER NYEH FINAL FORM;Lo;0;AL; 0683;;;;N;;;;; +FB78;ARABIC LETTER NYEH INITIAL FORM;Lo;0;AL; 0683;;;;N;;;;; +FB79;ARABIC LETTER NYEH MEDIAL FORM;Lo;0;AL; 0683;;;;N;;;;; +FB7A;ARABIC LETTER TCHEH ISOLATED FORM;Lo;0;AL; 0686;;;;N;;;;; +FB7B;ARABIC LETTER TCHEH FINAL FORM;Lo;0;AL; 0686;;;;N;;;;; +FB7C;ARABIC LETTER TCHEH INITIAL FORM;Lo;0;AL; 0686;;;;N;;;;; +FB7D;ARABIC LETTER TCHEH MEDIAL FORM;Lo;0;AL; 0686;;;;N;;;;; +FB7E;ARABIC LETTER TCHEHEH ISOLATED FORM;Lo;0;AL; 0687;;;;N;;;;; +FB7F;ARABIC LETTER TCHEHEH FINAL FORM;Lo;0;AL; 0687;;;;N;;;;; +FB80;ARABIC LETTER TCHEHEH INITIAL FORM;Lo;0;AL; 0687;;;;N;;;;; +FB81;ARABIC LETTER TCHEHEH MEDIAL FORM;Lo;0;AL; 0687;;;;N;;;;; +FB82;ARABIC LETTER DDAHAL ISOLATED FORM;Lo;0;AL; 068D;;;;N;;;;; +FB83;ARABIC LETTER DDAHAL FINAL FORM;Lo;0;AL; 068D;;;;N;;;;; +FB84;ARABIC LETTER DAHAL ISOLATED FORM;Lo;0;AL; 068C;;;;N;;;;; +FB85;ARABIC LETTER DAHAL FINAL FORM;Lo;0;AL; 068C;;;;N;;;;; +FB86;ARABIC LETTER DUL ISOLATED FORM;Lo;0;AL; 068E;;;;N;;;;; +FB87;ARABIC LETTER DUL FINAL FORM;Lo;0;AL; 068E;;;;N;;;;; +FB88;ARABIC LETTER DDAL ISOLATED FORM;Lo;0;AL; 0688;;;;N;;;;; +FB89;ARABIC LETTER DDAL FINAL FORM;Lo;0;AL; 0688;;;;N;;;;; +FB8A;ARABIC LETTER JEH ISOLATED FORM;Lo;0;AL; 0698;;;;N;;;;; +FB8B;ARABIC LETTER JEH FINAL FORM;Lo;0;AL; 0698;;;;N;;;;; +FB8C;ARABIC LETTER RREH ISOLATED FORM;Lo;0;AL; 0691;;;;N;;;;; +FB8D;ARABIC LETTER RREH FINAL FORM;Lo;0;AL; 0691;;;;N;;;;; +FB8E;ARABIC LETTER KEHEH ISOLATED FORM;Lo;0;AL; 06A9;;;;N;;;;; +FB8F;ARABIC LETTER KEHEH FINAL FORM;Lo;0;AL; 06A9;;;;N;;;;; +FB90;ARABIC LETTER KEHEH INITIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; +FB91;ARABIC LETTER KEHEH MEDIAL FORM;Lo;0;AL; 06A9;;;;N;;;;; +FB92;ARABIC LETTER GAF ISOLATED FORM;Lo;0;AL; 06AF;;;;N;;;;; +FB93;ARABIC LETTER GAF FINAL FORM;Lo;0;AL; 06AF;;;;N;;;;; +FB94;ARABIC LETTER GAF INITIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; +FB95;ARABIC LETTER GAF MEDIAL FORM;Lo;0;AL; 06AF;;;;N;;;;; +FB96;ARABIC LETTER GUEH ISOLATED FORM;Lo;0;AL; 06B3;;;;N;;;;; +FB97;ARABIC LETTER GUEH FINAL FORM;Lo;0;AL; 06B3;;;;N;;;;; +FB98;ARABIC LETTER GUEH INITIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; +FB99;ARABIC LETTER GUEH MEDIAL FORM;Lo;0;AL; 06B3;;;;N;;;;; +FB9A;ARABIC LETTER NGOEH ISOLATED FORM;Lo;0;AL; 06B1;;;;N;;;;; +FB9B;ARABIC LETTER NGOEH FINAL FORM;Lo;0;AL; 06B1;;;;N;;;;; +FB9C;ARABIC LETTER NGOEH INITIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; +FB9D;ARABIC LETTER NGOEH MEDIAL FORM;Lo;0;AL; 06B1;;;;N;;;;; +FB9E;ARABIC LETTER NOON GHUNNA ISOLATED FORM;Lo;0;AL; 06BA;;;;N;;;;; +FB9F;ARABIC LETTER NOON GHUNNA FINAL FORM;Lo;0;AL; 06BA;;;;N;;;;; +FBA0;ARABIC LETTER RNOON ISOLATED FORM;Lo;0;AL; 06BB;;;;N;;;;; +FBA1;ARABIC LETTER RNOON FINAL FORM;Lo;0;AL; 06BB;;;;N;;;;; +FBA2;ARABIC LETTER RNOON INITIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; +FBA3;ARABIC LETTER RNOON MEDIAL FORM;Lo;0;AL; 06BB;;;;N;;;;; +FBA4;ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM;Lo;0;AL; 06C0;;;;N;;;;; +FBA5;ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM;Lo;0;AL; 06C0;;;;N;;;;; +FBA6;ARABIC LETTER HEH GOAL ISOLATED FORM;Lo;0;AL; 06C1;;;;N;;;;; +FBA7;ARABIC LETTER HEH GOAL FINAL FORM;Lo;0;AL; 06C1;;;;N;;;;; +FBA8;ARABIC LETTER HEH GOAL INITIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; +FBA9;ARABIC LETTER HEH GOAL MEDIAL FORM;Lo;0;AL; 06C1;;;;N;;;;; +FBAA;ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM;Lo;0;AL; 06BE;;;;N;;;;; +FBAB;ARABIC LETTER HEH DOACHASHMEE FINAL FORM;Lo;0;AL; 06BE;;;;N;;;;; +FBAC;ARABIC LETTER HEH DOACHASHMEE INITIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; +FBAD;ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM;Lo;0;AL; 06BE;;;;N;;;;; +FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL; 06D2;;;;N;;;;; +FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL; 06D2;;;;N;;;;; +FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 06D3;;;;N;;;;; +FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 06D3;;;;N;;;;; +FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;; +FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;; +FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;; +FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;; +FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;; +FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; +FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; +FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; +FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; +FBC2;ARABIC SYMBOL WASLA ABOVE;Sk;0;AL;;;;;N;;;;; +FBC3;ARABIC LIGATURE JALLA WA-ALAA;So;0;ON;;;;;N;;;;; +FBC4;ARABIC LIGATURE DAAMAT BARAKAATUHUM;So;0;ON;;;;;N;;;;; +FBC5;ARABIC LIGATURE RAHMATU ALLAAHI TAAALAA ALAYH;So;0;ON;;;;;N;;;;; +FBC6;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHIM;So;0;ON;;;;;N;;;;; +FBC7;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHIMAA;So;0;ON;;;;;N;;;;; +FBC8;ARABIC LIGATURE RAHIMAHUM ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;; +FBC9;ARABIC LIGATURE RAHIMAHUMAA ALLAAH;So;0;ON;;;;;N;;;;; +FBCA;ARABIC LIGATURE RAHIMAHUMAA ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;; +FBCB;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHUM;So;0;ON;;;;;N;;;;; +FBCC;ARABIC LIGATURE HAFIZAHU ALLAAH;So;0;ON;;;;;N;;;;; +FBCD;ARABIC LIGATURE HAFIZAHU ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;; +FBCE;ARABIC LIGATURE HAFIZAHUM ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;; +FBCF;ARABIC LIGATURE HAFIZAHUMAA ALLAAHU TAAALAA;So;0;ON;;;;;N;;;;; +FBD0;ARABIC LIGATURE SALLALLAAHU TAAALAA ALAYHI WA-SALLAM;So;0;ON;;;;;N;;;;; +FBD1;ARABIC LIGATURE AJJAL ALLAAHU FARAJAHU ASH-SHAREEF;So;0;ON;;;;;N;;;;; +FBD2;ARABIC LIGATURE ALAYHI AR-RAHMAH;So;0;ON;;;;;N;;;;; +FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; +FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; +FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; +FBD6;ARABIC LETTER NG MEDIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; +FBD7;ARABIC LETTER U ISOLATED FORM;Lo;0;AL; 06C7;;;;N;;;;; +FBD8;ARABIC LETTER U FINAL FORM;Lo;0;AL; 06C7;;;;N;;;;; +FBD9;ARABIC LETTER OE ISOLATED FORM;Lo;0;AL; 06C6;;;;N;;;;; +FBDA;ARABIC LETTER OE FINAL FORM;Lo;0;AL; 06C6;;;;N;;;;; +FBDB;ARABIC LETTER YU ISOLATED FORM;Lo;0;AL; 06C8;;;;N;;;;; +FBDC;ARABIC LETTER YU FINAL FORM;Lo;0;AL; 06C8;;;;N;;;;; +FBDD;ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0677;;;;N;;;;; +FBDE;ARABIC LETTER VE ISOLATED FORM;Lo;0;AL; 06CB;;;;N;;;;; +FBDF;ARABIC LETTER VE FINAL FORM;Lo;0;AL; 06CB;;;;N;;;;; +FBE0;ARABIC LETTER KIRGHIZ OE ISOLATED FORM;Lo;0;AL; 06C5;;;;N;;;;; +FBE1;ARABIC LETTER KIRGHIZ OE FINAL FORM;Lo;0;AL; 06C5;;;;N;;;;; +FBE2;ARABIC LETTER KIRGHIZ YU ISOLATED FORM;Lo;0;AL; 06C9;;;;N;;;;; +FBE3;ARABIC LETTER KIRGHIZ YU FINAL FORM;Lo;0;AL; 06C9;;;;N;;;;; +FBE4;ARABIC LETTER E ISOLATED FORM;Lo;0;AL; 06D0;;;;N;;;;; +FBE5;ARABIC LETTER E FINAL FORM;Lo;0;AL; 06D0;;;;N;;;;; +FBE6;ARABIC LETTER E INITIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; +FBE7;ARABIC LETTER E MEDIAL FORM;Lo;0;AL; 06D0;;;;N;;;;; +FBE8;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0649;;;;N;;;;; +FBE9;ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM;Lo;0;AL; 0649;;;;N;;;;; +FBEA;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM;Lo;0;AL; 0626 0627;;;;N;;;;; +FBEB;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM;Lo;0;AL; 0626 0627;;;;N;;;;; +FBEC;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; +FBED;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM;Lo;0;AL; 0626 06D5;;;;N;;;;; +FBEE;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM;Lo;0;AL; 0626 0648;;;;N;;;;; +FBEF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM;Lo;0;AL; 0626 0648;;;;N;;;;; +FBF0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; +FBF1;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM;Lo;0;AL; 0626 06C7;;;;N;;;;; +FBF2;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; +FBF3;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM;Lo;0;AL; 0626 06C6;;;;N;;;;; +FBF4;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; +FBF5;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM;Lo;0;AL; 0626 06C8;;;;N;;;;; +FBF6;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; +FBF7;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; +FBF8;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM;Lo;0;AL; 0626 06D0;;;;N;;;;; +FBF9;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; +FBFA;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; +FBFB;ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; +FBFC;ARABIC LETTER FARSI YEH ISOLATED FORM;Lo;0;AL; 06CC;;;;N;;;;; +FBFD;ARABIC LETTER FARSI YEH FINAL FORM;Lo;0;AL; 06CC;;;;N;;;;; +FBFE;ARABIC LETTER FARSI YEH INITIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; +FBFF;ARABIC LETTER FARSI YEH MEDIAL FORM;Lo;0;AL; 06CC;;;;N;;;;; +FC00;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM;Lo;0;AL; 0626 062C;;;;N;;;;; +FC01;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM;Lo;0;AL; 0626 062D;;;;N;;;;; +FC02;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM;Lo;0;AL; 0626 0645;;;;N;;;;; +FC03;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0626 0649;;;;N;;;;; +FC04;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM;Lo;0;AL; 0626 064A;;;;N;;;;; +FC05;ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0628 062C;;;;N;;;;; +FC06;ARABIC LIGATURE BEH WITH HAH ISOLATED FORM;Lo;0;AL; 0628 062D;;;;N;;;;; +FC07;ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0628 062E;;;;N;;;;; +FC08;ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0628 0645;;;;N;;;;; +FC09;ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0628 0649;;;;N;;;;; +FC0A;ARABIC LIGATURE BEH WITH YEH ISOLATED FORM;Lo;0;AL; 0628 064A;;;;N;;;;; +FC0B;ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062A 062C;;;;N;;;;; +FC0C;ARABIC LIGATURE TEH WITH HAH ISOLATED FORM;Lo;0;AL; 062A 062D;;;;N;;;;; +FC0D;ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM;Lo;0;AL; 062A 062E;;;;N;;;;; +FC0E;ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062A 0645;;;;N;;;;; +FC0F;ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062A 0649;;;;N;;;;; +FC10;ARABIC LIGATURE TEH WITH YEH ISOLATED FORM;Lo;0;AL; 062A 064A;;;;N;;;;; +FC11;ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM;Lo;0;AL; 062B 062C;;;;N;;;;; +FC12;ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM;Lo;0;AL; 062B 0645;;;;N;;;;; +FC13;ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062B 0649;;;;N;;;;; +FC14;ARABIC LIGATURE THEH WITH YEH ISOLATED FORM;Lo;0;AL; 062B 064A;;;;N;;;;; +FC15;ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM;Lo;0;AL; 062C 062D;;;;N;;;;; +FC16;ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 062C 0645;;;;N;;;;; +FC17;ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062D 062C;;;;N;;;;; +FC18;ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062D 0645;;;;N;;;;; +FC19;ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM;Lo;0;AL; 062E 062C;;;;N;;;;; +FC1A;ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM;Lo;0;AL; 062E 062D;;;;N;;;;; +FC1B;ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM;Lo;0;AL; 062E 0645;;;;N;;;;; +FC1C;ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0633 062C;;;;N;;;;; +FC1D;ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0633 062D;;;;N;;;;; +FC1E;ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0633 062E;;;;N;;;;; +FC1F;ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0633 0645;;;;N;;;;; +FC20;ARABIC LIGATURE SAD WITH HAH ISOLATED FORM;Lo;0;AL; 0635 062D;;;;N;;;;; +FC21;ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0635 0645;;;;N;;;;; +FC22;ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM;Lo;0;AL; 0636 062C;;;;N;;;;; +FC23;ARABIC LIGATURE DAD WITH HAH ISOLATED FORM;Lo;0;AL; 0636 062D;;;;N;;;;; +FC24;ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM;Lo;0;AL; 0636 062E;;;;N;;;;; +FC25;ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM;Lo;0;AL; 0636 0645;;;;N;;;;; +FC26;ARABIC LIGATURE TAH WITH HAH ISOLATED FORM;Lo;0;AL; 0637 062D;;;;N;;;;; +FC27;ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0637 0645;;;;N;;;;; +FC28;ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM;Lo;0;AL; 0638 0645;;;;N;;;;; +FC29;ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM;Lo;0;AL; 0639 062C;;;;N;;;;; +FC2A;ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM;Lo;0;AL; 0639 0645;;;;N;;;;; +FC2B;ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM;Lo;0;AL; 063A 062C;;;;N;;;;; +FC2C;ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM;Lo;0;AL; 063A 0645;;;;N;;;;; +FC2D;ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0641 062C;;;;N;;;;; +FC2E;ARABIC LIGATURE FEH WITH HAH ISOLATED FORM;Lo;0;AL; 0641 062D;;;;N;;;;; +FC2F;ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM;Lo;0;AL; 0641 062E;;;;N;;;;; +FC30;ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0641 0645;;;;N;;;;; +FC31;ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0641 0649;;;;N;;;;; +FC32;ARABIC LIGATURE FEH WITH YEH ISOLATED FORM;Lo;0;AL; 0641 064A;;;;N;;;;; +FC33;ARABIC LIGATURE QAF WITH HAH ISOLATED FORM;Lo;0;AL; 0642 062D;;;;N;;;;; +FC34;ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0642 0645;;;;N;;;;; +FC35;ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0642 0649;;;;N;;;;; +FC36;ARABIC LIGATURE QAF WITH YEH ISOLATED FORM;Lo;0;AL; 0642 064A;;;;N;;;;; +FC37;ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM;Lo;0;AL; 0643 0627;;;;N;;;;; +FC38;ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM;Lo;0;AL; 0643 062C;;;;N;;;;; +FC39;ARABIC LIGATURE KAF WITH HAH ISOLATED FORM;Lo;0;AL; 0643 062D;;;;N;;;;; +FC3A;ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM;Lo;0;AL; 0643 062E;;;;N;;;;; +FC3B;ARABIC LIGATURE KAF WITH LAM ISOLATED FORM;Lo;0;AL; 0643 0644;;;;N;;;;; +FC3C;ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM;Lo;0;AL; 0643 0645;;;;N;;;;; +FC3D;ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0643 0649;;;;N;;;;; +FC3E;ARABIC LIGATURE KAF WITH YEH ISOLATED FORM;Lo;0;AL; 0643 064A;;;;N;;;;; +FC3F;ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM;Lo;0;AL; 0644 062C;;;;N;;;;; +FC40;ARABIC LIGATURE LAM WITH HAH ISOLATED FORM;Lo;0;AL; 0644 062D;;;;N;;;;; +FC41;ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM;Lo;0;AL; 0644 062E;;;;N;;;;; +FC42;ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM;Lo;0;AL; 0644 0645;;;;N;;;;; +FC43;ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0644 0649;;;;N;;;;; +FC44;ARABIC LIGATURE LAM WITH YEH ISOLATED FORM;Lo;0;AL; 0644 064A;;;;N;;;;; +FC45;ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM;Lo;0;AL; 0645 062C;;;;N;;;;; +FC46;ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM;Lo;0;AL; 0645 062D;;;;N;;;;; +FC47;ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM;Lo;0;AL; 0645 062E;;;;N;;;;; +FC48;ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM;Lo;0;AL; 0645 0645;;;;N;;;;; +FC49;ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0645 0649;;;;N;;;;; +FC4A;ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM;Lo;0;AL; 0645 064A;;;;N;;;;; +FC4B;ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM;Lo;0;AL; 0646 062C;;;;N;;;;; +FC4C;ARABIC LIGATURE NOON WITH HAH ISOLATED FORM;Lo;0;AL; 0646 062D;;;;N;;;;; +FC4D;ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM;Lo;0;AL; 0646 062E;;;;N;;;;; +FC4E;ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM;Lo;0;AL; 0646 0645;;;;N;;;;; +FC4F;ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0646 0649;;;;N;;;;; +FC50;ARABIC LIGATURE NOON WITH YEH ISOLATED FORM;Lo;0;AL; 0646 064A;;;;N;;;;; +FC51;ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM;Lo;0;AL; 0647 062C;;;;N;;;;; +FC52;ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM;Lo;0;AL; 0647 0645;;;;N;;;;; +FC53;ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0647 0649;;;;N;;;;; +FC54;ARABIC LIGATURE HEH WITH YEH ISOLATED FORM;Lo;0;AL; 0647 064A;;;;N;;;;; +FC55;ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM;Lo;0;AL; 064A 062C;;;;N;;;;; +FC56;ARABIC LIGATURE YEH WITH HAH ISOLATED FORM;Lo;0;AL; 064A 062D;;;;N;;;;; +FC57;ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM;Lo;0;AL; 064A 062E;;;;N;;;;; +FC58;ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM;Lo;0;AL; 064A 0645;;;;N;;;;; +FC59;ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 064A 0649;;;;N;;;;; +FC5A;ARABIC LIGATURE YEH WITH YEH ISOLATED FORM;Lo;0;AL; 064A 064A;;;;N;;;;; +FC5B;ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0630 0670;;;;N;;;;; +FC5C;ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0631 0670;;;;N;;;;; +FC5D;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0649 0670;;;;N;;;;; +FC5E;ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C 0651;;;;N;;;;; +FC5F;ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D 0651;;;;N;;;;; +FC60;ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM;Lo;0;AL; 0020 064E 0651;;;;N;;;;; +FC61;ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F 0651;;;;N;;;;; +FC62;ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM;Lo;0;AL; 0020 0650 0651;;;;N;;;;; +FC63;ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM;Lo;0;AL; 0020 0651 0670;;;;N;;;;; +FC64;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM;Lo;0;AL; 0626 0631;;;;N;;;;; +FC65;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM;Lo;0;AL; 0626 0632;;;;N;;;;; +FC66;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; +FC67;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM;Lo;0;AL; 0626 0646;;;;N;;;;; +FC68;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0626 0649;;;;N;;;;; +FC69;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM;Lo;0;AL; 0626 064A;;;;N;;;;; +FC6A;ARABIC LIGATURE BEH WITH REH FINAL FORM;Lo;0;AL; 0628 0631;;;;N;;;;; +FC6B;ARABIC LIGATURE BEH WITH ZAIN FINAL FORM;Lo;0;AL; 0628 0632;;;;N;;;;; +FC6C;ARABIC LIGATURE BEH WITH MEEM FINAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; +FC6D;ARABIC LIGATURE BEH WITH NOON FINAL FORM;Lo;0;AL; 0628 0646;;;;N;;;;; +FC6E;ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0628 0649;;;;N;;;;; +FC6F;ARABIC LIGATURE BEH WITH YEH FINAL FORM;Lo;0;AL; 0628 064A;;;;N;;;;; +FC70;ARABIC LIGATURE TEH WITH REH FINAL FORM;Lo;0;AL; 062A 0631;;;;N;;;;; +FC71;ARABIC LIGATURE TEH WITH ZAIN FINAL FORM;Lo;0;AL; 062A 0632;;;;N;;;;; +FC72;ARABIC LIGATURE TEH WITH MEEM FINAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; +FC73;ARABIC LIGATURE TEH WITH NOON FINAL FORM;Lo;0;AL; 062A 0646;;;;N;;;;; +FC74;ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0649;;;;N;;;;; +FC75;ARABIC LIGATURE TEH WITH YEH FINAL FORM;Lo;0;AL; 062A 064A;;;;N;;;;; +FC76;ARABIC LIGATURE THEH WITH REH FINAL FORM;Lo;0;AL; 062B 0631;;;;N;;;;; +FC77;ARABIC LIGATURE THEH WITH ZAIN FINAL FORM;Lo;0;AL; 062B 0632;;;;N;;;;; +FC78;ARABIC LIGATURE THEH WITH MEEM FINAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; +FC79;ARABIC LIGATURE THEH WITH NOON FINAL FORM;Lo;0;AL; 062B 0646;;;;N;;;;; +FC7A;ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062B 0649;;;;N;;;;; +FC7B;ARABIC LIGATURE THEH WITH YEH FINAL FORM;Lo;0;AL; 062B 064A;;;;N;;;;; +FC7C;ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0641 0649;;;;N;;;;; +FC7D;ARABIC LIGATURE FEH WITH YEH FINAL FORM;Lo;0;AL; 0641 064A;;;;N;;;;; +FC7E;ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0642 0649;;;;N;;;;; +FC7F;ARABIC LIGATURE QAF WITH YEH FINAL FORM;Lo;0;AL; 0642 064A;;;;N;;;;; +FC80;ARABIC LIGATURE KAF WITH ALEF FINAL FORM;Lo;0;AL; 0643 0627;;;;N;;;;; +FC81;ARABIC LIGATURE KAF WITH LAM FINAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; +FC82;ARABIC LIGATURE KAF WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; +FC83;ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0643 0649;;;;N;;;;; +FC84;ARABIC LIGATURE KAF WITH YEH FINAL FORM;Lo;0;AL; 0643 064A;;;;N;;;;; +FC85;ARABIC LIGATURE LAM WITH MEEM FINAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; +FC86;ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 0649;;;;N;;;;; +FC87;ARABIC LIGATURE LAM WITH YEH FINAL FORM;Lo;0;AL; 0644 064A;;;;N;;;;; +FC88;ARABIC LIGATURE MEEM WITH ALEF FINAL FORM;Lo;0;AL; 0645 0627;;;;N;;;;; +FC89;ARABIC LIGATURE MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; +FC8A;ARABIC LIGATURE NOON WITH REH FINAL FORM;Lo;0;AL; 0646 0631;;;;N;;;;; +FC8B;ARABIC LIGATURE NOON WITH ZAIN FINAL FORM;Lo;0;AL; 0646 0632;;;;N;;;;; +FC8C;ARABIC LIGATURE NOON WITH MEEM FINAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; +FC8D;ARABIC LIGATURE NOON WITH NOON FINAL FORM;Lo;0;AL; 0646 0646;;;;N;;;;; +FC8E;ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0649;;;;N;;;;; +FC8F;ARABIC LIGATURE NOON WITH YEH FINAL FORM;Lo;0;AL; 0646 064A;;;;N;;;;; +FC90;ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM;Lo;0;AL; 0649 0670;;;;N;;;;; +FC91;ARABIC LIGATURE YEH WITH REH FINAL FORM;Lo;0;AL; 064A 0631;;;;N;;;;; +FC92;ARABIC LIGATURE YEH WITH ZAIN FINAL FORM;Lo;0;AL; 064A 0632;;;;N;;;;; +FC93;ARABIC LIGATURE YEH WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; +FC94;ARABIC LIGATURE YEH WITH NOON FINAL FORM;Lo;0;AL; 064A 0646;;;;N;;;;; +FC95;ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 064A 0649;;;;N;;;;; +FC96;ARABIC LIGATURE YEH WITH YEH FINAL FORM;Lo;0;AL; 064A 064A;;;;N;;;;; +FC97;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM;Lo;0;AL; 0626 062C;;;;N;;;;; +FC98;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM;Lo;0;AL; 0626 062D;;;;N;;;;; +FC99;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM;Lo;0;AL; 0626 062E;;;;N;;;;; +FC9A;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; +FC9B;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; +FC9C;ARABIC LIGATURE BEH WITH JEEM INITIAL FORM;Lo;0;AL; 0628 062C;;;;N;;;;; +FC9D;ARABIC LIGATURE BEH WITH HAH INITIAL FORM;Lo;0;AL; 0628 062D;;;;N;;;;; +FC9E;ARABIC LIGATURE BEH WITH KHAH INITIAL FORM;Lo;0;AL; 0628 062E;;;;N;;;;; +FC9F;ARABIC LIGATURE BEH WITH MEEM INITIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; +FCA0;ARABIC LIGATURE BEH WITH HEH INITIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; +FCA1;ARABIC LIGATURE TEH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062C;;;;N;;;;; +FCA2;ARABIC LIGATURE TEH WITH HAH INITIAL FORM;Lo;0;AL; 062A 062D;;;;N;;;;; +FCA3;ARABIC LIGATURE TEH WITH KHAH INITIAL FORM;Lo;0;AL; 062A 062E;;;;N;;;;; +FCA4;ARABIC LIGATURE TEH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; +FCA5;ARABIC LIGATURE TEH WITH HEH INITIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; +FCA6;ARABIC LIGATURE THEH WITH MEEM INITIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; +FCA7;ARABIC LIGATURE JEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 062D;;;;N;;;;; +FCA8;ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062C 0645;;;;N;;;;; +FCA9;ARABIC LIGATURE HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062D 062C;;;;N;;;;; +FCAA;ARABIC LIGATURE HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062D 0645;;;;N;;;;; +FCAB;ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 062E 062C;;;;N;;;;; +FCAC;ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062E 0645;;;;N;;;;; +FCAD;ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; +FCAE;ARABIC LIGATURE SEEN WITH HAH INITIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; +FCAF;ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; +FCB0;ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; +FCB1;ARABIC LIGATURE SAD WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D;;;;N;;;;; +FCB2;ARABIC LIGATURE SAD WITH KHAH INITIAL FORM;Lo;0;AL; 0635 062E;;;;N;;;;; +FCB3;ARABIC LIGATURE SAD WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645;;;;N;;;;; +FCB4;ARABIC LIGATURE DAD WITH JEEM INITIAL FORM;Lo;0;AL; 0636 062C;;;;N;;;;; +FCB5;ARABIC LIGATURE DAD WITH HAH INITIAL FORM;Lo;0;AL; 0636 062D;;;;N;;;;; +FCB6;ARABIC LIGATURE DAD WITH KHAH INITIAL FORM;Lo;0;AL; 0636 062E;;;;N;;;;; +FCB7;ARABIC LIGATURE DAD WITH MEEM INITIAL FORM;Lo;0;AL; 0636 0645;;;;N;;;;; +FCB8;ARABIC LIGATURE TAH WITH HAH INITIAL FORM;Lo;0;AL; 0637 062D;;;;N;;;;; +FCB9;ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; +FCBA;ARABIC LIGATURE AIN WITH JEEM INITIAL FORM;Lo;0;AL; 0639 062C;;;;N;;;;; +FCBB;ARABIC LIGATURE AIN WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645;;;;N;;;;; +FCBC;ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM;Lo;0;AL; 063A 062C;;;;N;;;;; +FCBD;ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM;Lo;0;AL; 063A 0645;;;;N;;;;; +FCBE;ARABIC LIGATURE FEH WITH JEEM INITIAL FORM;Lo;0;AL; 0641 062C;;;;N;;;;; +FCBF;ARABIC LIGATURE FEH WITH HAH INITIAL FORM;Lo;0;AL; 0641 062D;;;;N;;;;; +FCC0;ARABIC LIGATURE FEH WITH KHAH INITIAL FORM;Lo;0;AL; 0641 062E;;;;N;;;;; +FCC1;ARABIC LIGATURE FEH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 0645;;;;N;;;;; +FCC2;ARABIC LIGATURE QAF WITH HAH INITIAL FORM;Lo;0;AL; 0642 062D;;;;N;;;;; +FCC3;ARABIC LIGATURE QAF WITH MEEM INITIAL FORM;Lo;0;AL; 0642 0645;;;;N;;;;; +FCC4;ARABIC LIGATURE KAF WITH JEEM INITIAL FORM;Lo;0;AL; 0643 062C;;;;N;;;;; +FCC5;ARABIC LIGATURE KAF WITH HAH INITIAL FORM;Lo;0;AL; 0643 062D;;;;N;;;;; +FCC6;ARABIC LIGATURE KAF WITH KHAH INITIAL FORM;Lo;0;AL; 0643 062E;;;;N;;;;; +FCC7;ARABIC LIGATURE KAF WITH LAM INITIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; +FCC8;ARABIC LIGATURE KAF WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; +FCC9;ARABIC LIGATURE LAM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C;;;;N;;;;; +FCCA;ARABIC LIGATURE LAM WITH HAH INITIAL FORM;Lo;0;AL; 0644 062D;;;;N;;;;; +FCCB;ARABIC LIGATURE LAM WITH KHAH INITIAL FORM;Lo;0;AL; 0644 062E;;;;N;;;;; +FCCC;ARABIC LIGATURE LAM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; +FCCD;ARABIC LIGATURE LAM WITH HEH INITIAL FORM;Lo;0;AL; 0644 0647;;;;N;;;;; +FCCE;ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062C;;;;N;;;;; +FCCF;ARABIC LIGATURE MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062D;;;;N;;;;; +FCD0;ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062E;;;;N;;;;; +FCD1;ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 0645;;;;N;;;;; +FCD2;ARABIC LIGATURE NOON WITH JEEM INITIAL FORM;Lo;0;AL; 0646 062C;;;;N;;;;; +FCD3;ARABIC LIGATURE NOON WITH HAH INITIAL FORM;Lo;0;AL; 0646 062D;;;;N;;;;; +FCD4;ARABIC LIGATURE NOON WITH KHAH INITIAL FORM;Lo;0;AL; 0646 062E;;;;N;;;;; +FCD5;ARABIC LIGATURE NOON WITH MEEM INITIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; +FCD6;ARABIC LIGATURE NOON WITH HEH INITIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; +FCD7;ARABIC LIGATURE HEH WITH JEEM INITIAL FORM;Lo;0;AL; 0647 062C;;;;N;;;;; +FCD8;ARABIC LIGATURE HEH WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645;;;;N;;;;; +FCD9;ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM;Lo;0;AL; 0647 0670;;;;N;;;;; +FCDA;ARABIC LIGATURE YEH WITH JEEM INITIAL FORM;Lo;0;AL; 064A 062C;;;;N;;;;; +FCDB;ARABIC LIGATURE YEH WITH HAH INITIAL FORM;Lo;0;AL; 064A 062D;;;;N;;;;; +FCDC;ARABIC LIGATURE YEH WITH KHAH INITIAL FORM;Lo;0;AL; 064A 062E;;;;N;;;;; +FCDD;ARABIC LIGATURE YEH WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; +FCDE;ARABIC LIGATURE YEH WITH HEH INITIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; +FCDF;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM;Lo;0;AL; 0626 0645;;;;N;;;;; +FCE0;ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM;Lo;0;AL; 0626 0647;;;;N;;;;; +FCE1;ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM;Lo;0;AL; 0628 0645;;;;N;;;;; +FCE2;ARABIC LIGATURE BEH WITH HEH MEDIAL FORM;Lo;0;AL; 0628 0647;;;;N;;;;; +FCE3;ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062A 0645;;;;N;;;;; +FCE4;ARABIC LIGATURE TEH WITH HEH MEDIAL FORM;Lo;0;AL; 062A 0647;;;;N;;;;; +FCE5;ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM;Lo;0;AL; 062B 0645;;;;N;;;;; +FCE6;ARABIC LIGATURE THEH WITH HEH MEDIAL FORM;Lo;0;AL; 062B 0647;;;;N;;;;; +FCE7;ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0633 0645;;;;N;;;;; +FCE8;ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; +FCE9;ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; +FCEA;ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; +FCEB;ARABIC LIGATURE KAF WITH LAM MEDIAL FORM;Lo;0;AL; 0643 0644;;;;N;;;;; +FCEC;ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM;Lo;0;AL; 0643 0645;;;;N;;;;; +FCED;ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM;Lo;0;AL; 0644 0645;;;;N;;;;; +FCEE;ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM;Lo;0;AL; 0646 0645;;;;N;;;;; +FCEF;ARABIC LIGATURE NOON WITH HEH MEDIAL FORM;Lo;0;AL; 0646 0647;;;;N;;;;; +FCF0;ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM;Lo;0;AL; 064A 0645;;;;N;;;;; +FCF1;ARABIC LIGATURE YEH WITH HEH MEDIAL FORM;Lo;0;AL; 064A 0647;;;;N;;;;; +FCF2;ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM;Lo;0;AL; 0640 064E 0651;;;;N;;;;; +FCF3;ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F 0651;;;;N;;;;; +FCF4;ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM;Lo;0;AL; 0640 0650 0651;;;;N;;;;; +FCF5;ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0637 0649;;;;N;;;;; +FCF6;ARABIC LIGATURE TAH WITH YEH ISOLATED FORM;Lo;0;AL; 0637 064A;;;;N;;;;; +FCF7;ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0639 0649;;;;N;;;;; +FCF8;ARABIC LIGATURE AIN WITH YEH ISOLATED FORM;Lo;0;AL; 0639 064A;;;;N;;;;; +FCF9;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 063A 0649;;;;N;;;;; +FCFA;ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM;Lo;0;AL; 063A 064A;;;;N;;;;; +FCFB;ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0633 0649;;;;N;;;;; +FCFC;ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0633 064A;;;;N;;;;; +FCFD;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0634 0649;;;;N;;;;; +FCFE;ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM;Lo;0;AL; 0634 064A;;;;N;;;;; +FCFF;ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062D 0649;;;;N;;;;; +FD00;ARABIC LIGATURE HAH WITH YEH ISOLATED FORM;Lo;0;AL; 062D 064A;;;;N;;;;; +FD01;ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062C 0649;;;;N;;;;; +FD02;ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM;Lo;0;AL; 062C 064A;;;;N;;;;; +FD03;ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 062E 0649;;;;N;;;;; +FD04;ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM;Lo;0;AL; 062E 064A;;;;N;;;;; +FD05;ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0635 0649;;;;N;;;;; +FD06;ARABIC LIGATURE SAD WITH YEH ISOLATED FORM;Lo;0;AL; 0635 064A;;;;N;;;;; +FD07;ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0636 0649;;;;N;;;;; +FD08;ARABIC LIGATURE DAD WITH YEH ISOLATED FORM;Lo;0;AL; 0636 064A;;;;N;;;;; +FD09;ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM;Lo;0;AL; 0634 062C;;;;N;;;;; +FD0A;ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM;Lo;0;AL; 0634 062D;;;;N;;;;; +FD0B;ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM;Lo;0;AL; 0634 062E;;;;N;;;;; +FD0C;ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM;Lo;0;AL; 0634 0645;;;;N;;;;; +FD0D;ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM;Lo;0;AL; 0634 0631;;;;N;;;;; +FD0E;ARABIC LIGATURE SEEN WITH REH ISOLATED FORM;Lo;0;AL; 0633 0631;;;;N;;;;; +FD0F;ARABIC LIGATURE SAD WITH REH ISOLATED FORM;Lo;0;AL; 0635 0631;;;;N;;;;; +FD10;ARABIC LIGATURE DAD WITH REH ISOLATED FORM;Lo;0;AL; 0636 0631;;;;N;;;;; +FD11;ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0637 0649;;;;N;;;;; +FD12;ARABIC LIGATURE TAH WITH YEH FINAL FORM;Lo;0;AL; 0637 064A;;;;N;;;;; +FD13;ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0649;;;;N;;;;; +FD14;ARABIC LIGATURE AIN WITH YEH FINAL FORM;Lo;0;AL; 0639 064A;;;;N;;;;; +FD15;ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0649;;;;N;;;;; +FD16;ARABIC LIGATURE GHAIN WITH YEH FINAL FORM;Lo;0;AL; 063A 064A;;;;N;;;;; +FD17;ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 0649;;;;N;;;;; +FD18;ARABIC LIGATURE SEEN WITH YEH FINAL FORM;Lo;0;AL; 0633 064A;;;;N;;;;; +FD19;ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0634 0649;;;;N;;;;; +FD1A;ARABIC LIGATURE SHEEN WITH YEH FINAL FORM;Lo;0;AL; 0634 064A;;;;N;;;;; +FD1B;ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0649;;;;N;;;;; +FD1C;ARABIC LIGATURE HAH WITH YEH FINAL FORM;Lo;0;AL; 062D 064A;;;;N;;;;; +FD1D;ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0649;;;;N;;;;; +FD1E;ARABIC LIGATURE JEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 064A;;;;N;;;;; +FD1F;ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062E 0649;;;;N;;;;; +FD20;ARABIC LIGATURE KHAH WITH YEH FINAL FORM;Lo;0;AL; 062E 064A;;;;N;;;;; +FD21;ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0635 0649;;;;N;;;;; +FD22;ARABIC LIGATURE SAD WITH YEH FINAL FORM;Lo;0;AL; 0635 064A;;;;N;;;;; +FD23;ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 0649;;;;N;;;;; +FD24;ARABIC LIGATURE DAD WITH YEH FINAL FORM;Lo;0;AL; 0636 064A;;;;N;;;;; +FD25;ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; +FD26;ARABIC LIGATURE SHEEN WITH HAH FINAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; +FD27;ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; +FD28;ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; +FD29;ARABIC LIGATURE SHEEN WITH REH FINAL FORM;Lo;0;AL; 0634 0631;;;;N;;;;; +FD2A;ARABIC LIGATURE SEEN WITH REH FINAL FORM;Lo;0;AL; 0633 0631;;;;N;;;;; +FD2B;ARABIC LIGATURE SAD WITH REH FINAL FORM;Lo;0;AL; 0635 0631;;;;N;;;;; +FD2C;ARABIC LIGATURE DAD WITH REH FINAL FORM;Lo;0;AL; 0636 0631;;;;N;;;;; +FD2D;ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; +FD2E;ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; +FD2F;ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; +FD30;ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645;;;;N;;;;; +FD31;ARABIC LIGATURE SEEN WITH HEH INITIAL FORM;Lo;0;AL; 0633 0647;;;;N;;;;; +FD32;ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM;Lo;0;AL; 0634 0647;;;;N;;;;; +FD33;ARABIC LIGATURE TAH WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; +FD34;ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0633 062C;;;;N;;;;; +FD35;ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0633 062D;;;;N;;;;; +FD36;ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0633 062E;;;;N;;;;; +FD37;ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM;Lo;0;AL; 0634 062C;;;;N;;;;; +FD38;ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM;Lo;0;AL; 0634 062D;;;;N;;;;; +FD39;ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM;Lo;0;AL; 0634 062E;;;;N;;;;; +FD3A;ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0637 0645;;;;N;;;;; +FD3B;ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM;Lo;0;AL; 0638 0645;;;;N;;;;; +FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL; 0627 064B;;;;N;;;;; +FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0627 064B;;;;N;;;;; +FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;; +FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;; +FD40;ARABIC LIGATURE RAHIMAHU ALLAAH;So;0;ON;;;;;N;;;;; +FD41;ARABIC LIGATURE RADI ALLAAHU ANH;So;0;ON;;;;;N;;;;; +FD42;ARABIC LIGATURE RADI ALLAAHU ANHAA;So;0;ON;;;;;N;;;;; +FD43;ARABIC LIGATURE RADI ALLAAHU ANHUM;So;0;ON;;;;;N;;;;; +FD44;ARABIC LIGATURE RADI ALLAAHU ANHUMAA;So;0;ON;;;;;N;;;;; +FD45;ARABIC LIGATURE RADI ALLAAHU ANHUNNA;So;0;ON;;;;;N;;;;; +FD46;ARABIC LIGATURE SALLALLAAHU ALAYHI WA-AALIH;So;0;ON;;;;;N;;;;; +FD47;ARABIC LIGATURE ALAYHI AS-SALAAM;So;0;ON;;;;;N;;;;; +FD48;ARABIC LIGATURE ALAYHIM AS-SALAAM;So;0;ON;;;;;N;;;;; +FD49;ARABIC LIGATURE ALAYHIMAA AS-SALAAM;So;0;ON;;;;;N;;;;; +FD4A;ARABIC LIGATURE ALAYHI AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;; +FD4B;ARABIC LIGATURE QUDDISA SIRRAH;So;0;ON;;;;;N;;;;; +FD4C;ARABIC LIGATURE SALLALLAHU ALAYHI WAAALIHEE WA-SALLAM;So;0;ON;;;;;N;;;;; +FD4D;ARABIC LIGATURE ALAYHAA AS-SALAAM;So;0;ON;;;;;N;;;;; +FD4E;ARABIC LIGATURE TABAARAKA WA-TAAALAA;So;0;ON;;;;;N;;;;; +FD4F;ARABIC LIGATURE RAHIMAHUM ALLAAH;So;0;ON;;;;;N;;;;; +FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062C 0645;;;;N;;;;; +FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; +FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 062A 062D 062C;;;;N;;;;; +FD53;ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062D 0645;;;;N;;;;; +FD54;ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 062A 062E 0645;;;;N;;;;; +FD55;ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 062A 0645 062C;;;;N;;;;; +FD56;ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062A 0645 062D;;;;N;;;;; +FD57;ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 062A 0645 062E;;;;N;;;;; +FD58;ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; +FD59;ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 062C 0645 062D;;;;N;;;;; +FD5A;ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 0645 064A;;;;N;;;;; +FD5B;ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062D 0645 0649;;;;N;;;;; +FD5C;ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0633 062D 062C;;;;N;;;;; +FD5D;ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 062C 062D;;;;N;;;;; +FD5E;ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062C 0649;;;;N;;;;; +FD5F;ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; +FD60;ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0633 0645 062D;;;;N;;;;; +FD61;ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0633 0645 062C;;;;N;;;;; +FD62;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; +FD63;ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0633 0645 0645;;;;N;;;;; +FD64;ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; +FD65;ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM;Lo;0;AL; 0635 062D 062D;;;;N;;;;; +FD66;ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; +FD67;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; +FD68;ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0634 062D 0645;;;;N;;;;; +FD69;ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0634 062C 064A;;;;N;;;;; +FD6A;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; +FD6B;ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0634 0645 062E;;;;N;;;;; +FD6C;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; +FD6D;ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0634 0645 0645;;;;N;;;;; +FD6E;ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0636 062D 0649;;;;N;;;;; +FD6F;ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; +FD70;ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0636 062E 0645;;;;N;;;;; +FD71;ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; +FD72;ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0637 0645 062D;;;;N;;;;; +FD73;ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0637 0645 0645;;;;N;;;;; +FD74;ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0637 0645 064A;;;;N;;;;; +FD75;ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; +FD76;ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; +FD77;ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 0645 0645;;;;N;;;;; +FD78;ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0639 0645 0649;;;;N;;;;; +FD79;ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 063A 0645 0645;;;;N;;;;; +FD7A;ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 063A 0645 064A;;;;N;;;;; +FD7B;ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 063A 0645 0649;;;;N;;;;; +FD7C;ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; +FD7D;ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0641 062E 0645;;;;N;;;;; +FD7E;ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; +FD7F;ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0642 0645 0645;;;;N;;;;; +FD80;ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; +FD81;ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0644 062D 064A;;;;N;;;;; +FD82;ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0644 062D 0649;;;;N;;;;; +FD83;ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; +FD84;ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM;Lo;0;AL; 0644 062C 062C;;;;N;;;;; +FD85;ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; +FD86;ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062E 0645;;;;N;;;;; +FD87;ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; +FD88;ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0644 0645 062D;;;;N;;;;; +FD89;ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062D 062C;;;;N;;;;; +FD8A;ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062D 0645;;;;N;;;;; +FD8B;ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062D 064A;;;;N;;;;; +FD8C;ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0645 062C 062D;;;;N;;;;; +FD8D;ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062C 0645;;;;N;;;;; +FD8E;ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM;Lo;0;AL; 0645 062E 062C;;;;N;;;;; +FD8F;ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM;Lo;0;AL; 0645 062E 0645;;;;N;;;;; +FD90;ARABIC LIGATURE RAHMATU ALLAAHI ALAYH;So;0;ON;;;;;N;;;;; +FD91;ARABIC LIGATURE RAHMATU ALLAAHI ALAYHAA;So;0;ON;;;;;N;;;;; +FD92;ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM;Lo;0;AL; 0645 062C 062E;;;;N;;;;; +FD93;ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0647 0645 062C;;;;N;;;;; +FD94;ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0647 0645 0645;;;;N;;;;; +FD95;ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062D 0645;;;;N;;;;; +FD96;ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062D 0649;;;;N;;;;; +FD97;ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; +FD98;ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0646 062C 0645;;;;N;;;;; +FD99;ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 062C 0649;;;;N;;;;; +FD9A;ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 0645 064A;;;;N;;;;; +FD9B;ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0646 0645 0649;;;;N;;;;; +FD9C;ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; +FD9D;ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 064A 0645 0645;;;;N;;;;; +FD9E;ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062E 064A;;;;N;;;;; +FD9F;ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 062C 064A;;;;N;;;;; +FDA0;ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062C 0649;;;;N;;;;; +FDA1;ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 062A 062E 064A;;;;N;;;;; +FDA2;ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 062E 0649;;;;N;;;;; +FDA3;ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062A 0645 064A;;;;N;;;;; +FDA4;ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062A 0645 0649;;;;N;;;;; +FDA5;ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 062C 0645 064A;;;;N;;;;; +FDA6;ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 062D 0649;;;;N;;;;; +FDA7;ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 062C 0645 0649;;;;N;;;;; +FDA8;ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM;Lo;0;AL; 0633 062E 0649;;;;N;;;;; +FDA9;ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0635 062D 064A;;;;N;;;;; +FDAA;ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0634 062D 064A;;;;N;;;;; +FDAB;ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0636 062D 064A;;;;N;;;;; +FDAC;ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 062C 064A;;;;N;;;;; +FDAD;ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0644 0645 064A;;;;N;;;;; +FDAE;ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 064A 062D 064A;;;;N;;;;; +FDAF;ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 062C 064A;;;;N;;;;; +FDB0;ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 064A 0645 064A;;;;N;;;;; +FDB1;ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 0645 064A;;;;N;;;;; +FDB2;ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0642 0645 064A;;;;N;;;;; +FDB3;ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0646 062D 064A;;;;N;;;;; +FDB4;ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM;Lo;0;AL; 0642 0645 062D;;;;N;;;;; +FDB5;ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062D 0645;;;;N;;;;; +FDB6;ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0639 0645 064A;;;;N;;;;; +FDB7;ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0643 0645 064A;;;;N;;;;; +FDB8;ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; +FDB9;ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0645 062E 064A;;;;N;;;;; +FDBA;ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; +FDBB;ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; +FDBC;ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM;Lo;0;AL; 0644 062C 0645;;;;N;;;;; +FDBD;ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM;Lo;0;AL; 0646 062C 062D;;;;N;;;;; +FDBE;ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 062C 062D 064A;;;;N;;;;; +FDBF;ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 062D 062C 064A;;;;N;;;;; +FDC0;ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0645 062C 064A;;;;N;;;;; +FDC1;ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM;Lo;0;AL; 0641 0645 064A;;;;N;;;;; +FDC2;ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM;Lo;0;AL; 0628 062D 064A;;;;N;;;;; +FDC3;ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0643 0645 0645;;;;N;;;;; +FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0639 062C 0645;;;;N;;;;; +FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL; 0635 0645 0645;;;;N;;;;; +FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL; 0633 062E 064A;;;;N;;;;; +FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL; 0646 062C 064A;;;;N;;;;; +FDC8;ARABIC LIGATURE RAHIMAHU ALLAAH TAAALAA;So;0;ON;;;;;N;;;;; +FDC9;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANH;So;0;ON;;;;;N;;;;; +FDCA;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHAA;So;0;ON;;;;;N;;;;; +FDCB;ARABIC LIGATURE RADI ALLAAHU TAAALAA ANHUMAA;So;0;ON;;;;;N;;;;; +FDCC;ARABIC LIGATURE SALLALLAHU ALAYHI WA-ALAA AALIHEE WA-SALLAM;So;0;ON;;;;;N;;;;; +FDCD;ARABIC LIGATURE AJJAL ALLAAHU TAAALAA FARAJAHU ASH-SHAREEF;So;0;ON;;;;;N;;;;; +FDCE;ARABIC LIGATURE KARRAMA ALLAAHU WAJHAH;So;0;ON;;;;;N;;;;; +FDCF;ARABIC LIGATURE SALAAMUHU ALAYNAA;So;0;ON;;;;;N;;;;; +FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0635 0644 06D2;;;;N;;;;; +FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL; 0642 0644 06D2;;;;N;;;;; +FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL; 0627 0644 0644 0647;;;;N;;;;; +FDF3;ARABIC LIGATURE AKBAR ISOLATED FORM;Lo;0;AL; 0627 0643 0628 0631;;;;N;;;;; +FDF4;ARABIC LIGATURE MOHAMMAD ISOLATED FORM;Lo;0;AL; 0645 062D 0645 062F;;;;N;;;;; +FDF5;ARABIC LIGATURE SALAM ISOLATED FORM;Lo;0;AL; 0635 0644 0639 0645;;;;N;;;;; +FDF6;ARABIC LIGATURE RASOUL ISOLATED FORM;Lo;0;AL; 0631 0633 0648 0644;;;;N;;;;; +FDF7;ARABIC LIGATURE ALAYHE ISOLATED FORM;Lo;0;AL; 0639 0644 064A 0647;;;;N;;;;; +FDF8;ARABIC LIGATURE WASALLAM ISOLATED FORM;Lo;0;AL; 0648 0633 0644 0645;;;;N;;;;; +FDF9;ARABIC LIGATURE SALLA ISOLATED FORM;Lo;0;AL; 0635 0644 0649;;;;N;;;;; +FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL; 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645;;;;N;ARABIC LETTER SALLALLAHOU ALAYHE WASALLAM;;;; +FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL; 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;; +FDFC;RIAL SIGN;Sc;0;AL; 0631 06CC 0627 0644;;;;N;;;;; +FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;; +FDFE;ARABIC LIGATURE SUBHAANAHU WA TAAALAA;So;0;ON;;;;;N;;;;; +FDFF;ARABIC LIGATURE AZZA WA JALL;So;0;ON;;;;;N;;;;; +FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;; +FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;; +FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;; +FE03;VARIATION SELECTOR-4;Mn;0;NSM;;;;;N;;;;; +FE04;VARIATION SELECTOR-5;Mn;0;NSM;;;;;N;;;;; +FE05;VARIATION SELECTOR-6;Mn;0;NSM;;;;;N;;;;; +FE06;VARIATION SELECTOR-7;Mn;0;NSM;;;;;N;;;;; +FE07;VARIATION SELECTOR-8;Mn;0;NSM;;;;;N;;;;; +FE08;VARIATION SELECTOR-9;Mn;0;NSM;;;;;N;;;;; +FE09;VARIATION SELECTOR-10;Mn;0;NSM;;;;;N;;;;; +FE0A;VARIATION SELECTOR-11;Mn;0;NSM;;;;;N;;;;; +FE0B;VARIATION SELECTOR-12;Mn;0;NSM;;;;;N;;;;; +FE0C;VARIATION SELECTOR-13;Mn;0;NSM;;;;;N;;;;; +FE0D;VARIATION SELECTOR-14;Mn;0;NSM;;;;;N;;;;; +FE0E;VARIATION SELECTOR-15;Mn;0;NSM;;;;;N;;;;; +FE0F;VARIATION SELECTOR-16;Mn;0;NSM;;;;;N;;;;; +FE10;PRESENTATION FORM FOR VERTICAL COMMA;Po;0;ON; 002C;;;;N;;;;; +FE11;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; +FE12;PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;;;;; +FE13;PRESENTATION FORM FOR VERTICAL COLON;Po;0;ON; 003A;;;;N;;;;; +FE14;PRESENTATION FORM FOR VERTICAL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; +FE15;PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; +FE16;PRESENTATION FORM FOR VERTICAL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; +FE17;PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET;Ps;0;ON; 3016;;;;N;;;;; +FE18;PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET;Pe;0;ON; 3017;;;;N;;;;; +FE19;PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS;Po;0;ON; 2026;;;;N;;;;; +FE20;COMBINING LIGATURE LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE21;COMBINING LIGATURE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE22;COMBINING DOUBLE TILDE LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE23;COMBINING DOUBLE TILDE RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE24;COMBINING MACRON LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE25;COMBINING MACRON RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE26;COMBINING CONJOINING MACRON;Mn;230;NSM;;;;;N;;;;; +FE27;COMBINING LIGATURE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE28;COMBINING LIGATURE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE29;COMBINING TILDE LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2A;COMBINING TILDE RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2B;COMBINING MACRON LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2C;COMBINING MACRON RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;; +FE2D;COMBINING CONJOINING MACRON BELOW;Mn;220;NSM;;;;;N;;;;; +FE2E;COMBINING CYRILLIC TITLO LEFT HALF;Mn;230;NSM;;;;;N;;;;; +FE2F;COMBINING CYRILLIC TITLO RIGHT HALF;Mn;230;NSM;;;;;N;;;;; +FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON; 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;; +FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON; 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;; +FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON; 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;; +FE33;PRESENTATION FORM FOR VERTICAL LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING UNDERSCORE;;;; +FE34;PRESENTATION FORM FOR VERTICAL WAVY LOW LINE;Pc;0;ON; 005F;;;;N;GLYPH FOR VERTICAL SPACING WAVY UNDERSCORE;;;; +FE35;PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;N;GLYPH FOR VERTICAL OPENING PARENTHESIS;;;; +FE36;PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;N;GLYPH FOR VERTICAL CLOSING PARENTHESIS;;;; +FE37;PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;N;GLYPH FOR VERTICAL OPENING CURLY BRACKET;;;; +FE38;PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;N;GLYPH FOR VERTICAL CLOSING CURLY BRACKET;;;; +FE39;PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;N;GLYPH FOR VERTICAL OPENING TORTOISE SHELL BRACKET;;;; +FE3A;PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;N;GLYPH FOR VERTICAL CLOSING TORTOISE SHELL BRACKET;;;; +FE3B;PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET;Ps;0;ON; 3010;;;;N;GLYPH FOR VERTICAL OPENING BLACK LENTICULAR BRACKET;;;; +FE3C;PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET;Pe;0;ON; 3011;;;;N;GLYPH FOR VERTICAL CLOSING BLACK LENTICULAR BRACKET;;;; +FE3D;PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET;Ps;0;ON; 300A;;;;N;GLYPH FOR VERTICAL OPENING DOUBLE ANGLE BRACKET;;;; +FE3E;PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET;Pe;0;ON; 300B;;;;N;GLYPH FOR VERTICAL CLOSING DOUBLE ANGLE BRACKET;;;; +FE3F;PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET;Ps;0;ON; 3008;;;;N;GLYPH FOR VERTICAL OPENING ANGLE BRACKET;;;; +FE40;PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET;Pe;0;ON; 3009;;;;N;GLYPH FOR VERTICAL CLOSING ANGLE BRACKET;;;; +FE41;PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;N;GLYPH FOR VERTICAL OPENING CORNER BRACKET;;;; +FE42;PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;N;GLYPH FOR VERTICAL CLOSING CORNER BRACKET;;;; +FE43;PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET;Ps;0;ON; 300E;;;;N;GLYPH FOR VERTICAL OPENING WHITE CORNER BRACKET;;;; +FE44;PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET;Pe;0;ON; 300F;;;;N;GLYPH FOR VERTICAL CLOSING WHITE CORNER BRACKET;;;; +FE45;SESAME DOT;Po;0;ON;;;;;N;;;;; +FE46;WHITE SESAME DOT;Po;0;ON;;;;;N;;;;; +FE47;PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;N;;;;; +FE48;PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;N;;;;; +FE49;DASHED OVERLINE;Po;0;ON; 203E;;;;N;SPACING DASHED OVERSCORE;;;; +FE4A;CENTRELINE OVERLINE;Po;0;ON; 203E;;;;N;SPACING CENTERLINE OVERSCORE;;;; +FE4B;WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING WAVY OVERSCORE;;;; +FE4C;DOUBLE WAVY OVERLINE;Po;0;ON; 203E;;;;N;SPACING DOUBLE WAVY OVERSCORE;;;; +FE4D;DASHED LOW LINE;Pc;0;ON; 005F;;;;N;SPACING DASHED UNDERSCORE;;;; +FE4E;CENTRELINE LOW LINE;Pc;0;ON; 005F;;;;N;SPACING CENTERLINE UNDERSCORE;;;; +FE4F;WAVY LOW LINE;Pc;0;ON; 005F;;;;N;SPACING WAVY UNDERSCORE;;;; +FE50;SMALL COMMA;Po;0;CS; 002C;;;;N;;;;; +FE51;SMALL IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; +FE52;SMALL FULL STOP;Po;0;CS; 002E;;;;N;SMALL PERIOD;;;; +FE54;SMALL SEMICOLON;Po;0;ON; 003B;;;;N;;;;; +FE55;SMALL COLON;Po;0;CS; 003A;;;;N;;;;; +FE56;SMALL QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; +FE57;SMALL EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; +FE58;SMALL EM DASH;Pd;0;ON; 2014;;;;N;;;;; +FE59;SMALL LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;SMALL OPENING PARENTHESIS;;;; +FE5A;SMALL RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;SMALL CLOSING PARENTHESIS;;;; +FE5B;SMALL LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;SMALL OPENING CURLY BRACKET;;;; +FE5C;SMALL RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;SMALL CLOSING CURLY BRACKET;;;; +FE5D;SMALL LEFT TORTOISE SHELL BRACKET;Ps;0;ON; 3014;;;;Y;SMALL OPENING TORTOISE SHELL BRACKET;;;; +FE5E;SMALL RIGHT TORTOISE SHELL BRACKET;Pe;0;ON; 3015;;;;Y;SMALL CLOSING TORTOISE SHELL BRACKET;;;; +FE5F;SMALL NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; +FE60;SMALL AMPERSAND;Po;0;ON; 0026;;;;N;;;;; +FE61;SMALL ASTERISK;Po;0;ON; 002A;;;;N;;;;; +FE62;SMALL PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; +FE63;SMALL HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; +FE64;SMALL LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; +FE65;SMALL GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; +FE66;SMALL EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; +FE68;SMALL REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;SMALL BACKSLASH;;;; +FE69;SMALL DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; +FE6A;SMALL PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; +FE6B;SMALL COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; +FE70;ARABIC FATHATAN ISOLATED FORM;Lo;0;AL; 0020 064B;;;;N;ARABIC SPACING FATHATAN;;;; +FE71;ARABIC TATWEEL WITH FATHATAN ABOVE;Lo;0;AL; 0640 064B;;;;N;ARABIC FATHATAN ON TATWEEL;;;; +FE72;ARABIC DAMMATAN ISOLATED FORM;Lo;0;AL; 0020 064C;;;;N;ARABIC SPACING DAMMATAN;;;; +FE73;ARABIC TAIL FRAGMENT;Lo;0;AL;;;;;N;;;;; +FE74;ARABIC KASRATAN ISOLATED FORM;Lo;0;AL; 0020 064D;;;;N;ARABIC SPACING KASRATAN;;;; +FE76;ARABIC FATHA ISOLATED FORM;Lo;0;AL; 0020 064E;;;;N;ARABIC SPACING FATHAH;;;; +FE77;ARABIC FATHA MEDIAL FORM;Lo;0;AL; 0640 064E;;;;N;ARABIC FATHAH ON TATWEEL;;;; +FE78;ARABIC DAMMA ISOLATED FORM;Lo;0;AL; 0020 064F;;;;N;ARABIC SPACING DAMMAH;;;; +FE79;ARABIC DAMMA MEDIAL FORM;Lo;0;AL; 0640 064F;;;;N;ARABIC DAMMAH ON TATWEEL;;;; +FE7A;ARABIC KASRA ISOLATED FORM;Lo;0;AL; 0020 0650;;;;N;ARABIC SPACING KASRAH;;;; +FE7B;ARABIC KASRA MEDIAL FORM;Lo;0;AL; 0640 0650;;;;N;ARABIC KASRAH ON TATWEEL;;;; +FE7C;ARABIC SHADDA ISOLATED FORM;Lo;0;AL; 0020 0651;;;;N;ARABIC SPACING SHADDAH;;;; +FE7D;ARABIC SHADDA MEDIAL FORM;Lo;0;AL; 0640 0651;;;;N;ARABIC SHADDAH ON TATWEEL;;;; +FE7E;ARABIC SUKUN ISOLATED FORM;Lo;0;AL; 0020 0652;;;;N;ARABIC SPACING SUKUN;;;; +FE7F;ARABIC SUKUN MEDIAL FORM;Lo;0;AL; 0640 0652;;;;N;ARABIC SUKUN ON TATWEEL;;;; +FE80;ARABIC LETTER HAMZA ISOLATED FORM;Lo;0;AL; 0621;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH;;;; +FE81;ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON ALEF;;;; +FE82;ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON ALEF;;;; +FE83;ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON ALEF;;;; +FE84;ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON ALEF;;;; +FE85;ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON WAW;;;; +FE86;ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0624;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON WAW;;;; +FE87;ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER ALEF;;;; +FE88;ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER ALEF;;;; +FE89;ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON YA;;;; +FE8A;ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON YA;;;; +FE8B;ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR INITIAL ARABIC HAMZAH ON YA;;;; +FE8C;ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM;Lo;0;AL; 0626;;;;N;GLYPH FOR MEDIAL ARABIC HAMZAH ON YA;;;; +FE8D;ARABIC LETTER ALEF ISOLATED FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR ISOLATE ARABIC ALEF;;;; +FE8E;ARABIC LETTER ALEF FINAL FORM;Lo;0;AL; 0627;;;;N;GLYPH FOR FINAL ARABIC ALEF;;;; +FE8F;ARABIC LETTER BEH ISOLATED FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR ISOLATE ARABIC BAA;;;; +FE90;ARABIC LETTER BEH FINAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR FINAL ARABIC BAA;;;; +FE91;ARABIC LETTER BEH INITIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR INITIAL ARABIC BAA;;;; +FE92;ARABIC LETTER BEH MEDIAL FORM;Lo;0;AL; 0628;;;;N;GLYPH FOR MEDIAL ARABIC BAA;;;; +FE93;ARABIC LETTER TEH MARBUTA ISOLATED FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR ISOLATE ARABIC TAA MARBUTAH;;;; +FE94;ARABIC LETTER TEH MARBUTA FINAL FORM;Lo;0;AL; 0629;;;;N;GLYPH FOR FINAL ARABIC TAA MARBUTAH;;;; +FE95;ARABIC LETTER TEH ISOLATED FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR ISOLATE ARABIC TAA;;;; +FE96;ARABIC LETTER TEH FINAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR FINAL ARABIC TAA;;;; +FE97;ARABIC LETTER TEH INITIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR INITIAL ARABIC TAA;;;; +FE98;ARABIC LETTER TEH MEDIAL FORM;Lo;0;AL; 062A;;;;N;GLYPH FOR MEDIAL ARABIC TAA;;;; +FE99;ARABIC LETTER THEH ISOLATED FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR ISOLATE ARABIC THAA;;;; +FE9A;ARABIC LETTER THEH FINAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR FINAL ARABIC THAA;;;; +FE9B;ARABIC LETTER THEH INITIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR INITIAL ARABIC THAA;;;; +FE9C;ARABIC LETTER THEH MEDIAL FORM;Lo;0;AL; 062B;;;;N;GLYPH FOR MEDIAL ARABIC THAA;;;; +FE9D;ARABIC LETTER JEEM ISOLATED FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR ISOLATE ARABIC JEEM;;;; +FE9E;ARABIC LETTER JEEM FINAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR FINAL ARABIC JEEM;;;; +FE9F;ARABIC LETTER JEEM INITIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR INITIAL ARABIC JEEM;;;; +FEA0;ARABIC LETTER JEEM MEDIAL FORM;Lo;0;AL; 062C;;;;N;GLYPH FOR MEDIAL ARABIC JEEM;;;; +FEA1;ARABIC LETTER HAH ISOLATED FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR ISOLATE ARABIC HAA;;;; +FEA2;ARABIC LETTER HAH FINAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR FINAL ARABIC HAA;;;; +FEA3;ARABIC LETTER HAH INITIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR INITIAL ARABIC HAA;;;; +FEA4;ARABIC LETTER HAH MEDIAL FORM;Lo;0;AL; 062D;;;;N;GLYPH FOR MEDIAL ARABIC HAA;;;; +FEA5;ARABIC LETTER KHAH ISOLATED FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR ISOLATE ARABIC KHAA;;;; +FEA6;ARABIC LETTER KHAH FINAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR FINAL ARABIC KHAA;;;; +FEA7;ARABIC LETTER KHAH INITIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR INITIAL ARABIC KHAA;;;; +FEA8;ARABIC LETTER KHAH MEDIAL FORM;Lo;0;AL; 062E;;;;N;GLYPH FOR MEDIAL ARABIC KHAA;;;; +FEA9;ARABIC LETTER DAL ISOLATED FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR ISOLATE ARABIC DAL;;;; +FEAA;ARABIC LETTER DAL FINAL FORM;Lo;0;AL; 062F;;;;N;GLYPH FOR FINAL ARABIC DAL;;;; +FEAB;ARABIC LETTER THAL ISOLATED FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR ISOLATE ARABIC THAL;;;; +FEAC;ARABIC LETTER THAL FINAL FORM;Lo;0;AL; 0630;;;;N;GLYPH FOR FINAL ARABIC THAL;;;; +FEAD;ARABIC LETTER REH ISOLATED FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR ISOLATE ARABIC RA;;;; +FEAE;ARABIC LETTER REH FINAL FORM;Lo;0;AL; 0631;;;;N;GLYPH FOR FINAL ARABIC RA;;;; +FEAF;ARABIC LETTER ZAIN ISOLATED FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR ISOLATE ARABIC ZAIN;;;; +FEB0;ARABIC LETTER ZAIN FINAL FORM;Lo;0;AL; 0632;;;;N;GLYPH FOR FINAL ARABIC ZAIN;;;; +FEB1;ARABIC LETTER SEEN ISOLATED FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR ISOLATE ARABIC SEEN;;;; +FEB2;ARABIC LETTER SEEN FINAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR FINAL ARABIC SEEN;;;; +FEB3;ARABIC LETTER SEEN INITIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR INITIAL ARABIC SEEN;;;; +FEB4;ARABIC LETTER SEEN MEDIAL FORM;Lo;0;AL; 0633;;;;N;GLYPH FOR MEDIAL ARABIC SEEN;;;; +FEB5;ARABIC LETTER SHEEN ISOLATED FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR ISOLATE ARABIC SHEEN;;;; +FEB6;ARABIC LETTER SHEEN FINAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR FINAL ARABIC SHEEN;;;; +FEB7;ARABIC LETTER SHEEN INITIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR INITIAL ARABIC SHEEN;;;; +FEB8;ARABIC LETTER SHEEN MEDIAL FORM;Lo;0;AL; 0634;;;;N;GLYPH FOR MEDIAL ARABIC SHEEN;;;; +FEB9;ARABIC LETTER SAD ISOLATED FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR ISOLATE ARABIC SAD;;;; +FEBA;ARABIC LETTER SAD FINAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR FINAL ARABIC SAD;;;; +FEBB;ARABIC LETTER SAD INITIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR INITIAL ARABIC SAD;;;; +FEBC;ARABIC LETTER SAD MEDIAL FORM;Lo;0;AL; 0635;;;;N;GLYPH FOR MEDIAL ARABIC SAD;;;; +FEBD;ARABIC LETTER DAD ISOLATED FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR ISOLATE ARABIC DAD;;;; +FEBE;ARABIC LETTER DAD FINAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR FINAL ARABIC DAD;;;; +FEBF;ARABIC LETTER DAD INITIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR INITIAL ARABIC DAD;;;; +FEC0;ARABIC LETTER DAD MEDIAL FORM;Lo;0;AL; 0636;;;;N;GLYPH FOR MEDIAL ARABIC DAD;;;; +FEC1;ARABIC LETTER TAH ISOLATED FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR ISOLATE ARABIC TAH;;;; +FEC2;ARABIC LETTER TAH FINAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR FINAL ARABIC TAH;;;; +FEC3;ARABIC LETTER TAH INITIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR INITIAL ARABIC TAH;;;; +FEC4;ARABIC LETTER TAH MEDIAL FORM;Lo;0;AL; 0637;;;;N;GLYPH FOR MEDIAL ARABIC TAH;;;; +FEC5;ARABIC LETTER ZAH ISOLATED FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR ISOLATE ARABIC DHAH;;;; +FEC6;ARABIC LETTER ZAH FINAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR FINAL ARABIC DHAH;;;; +FEC7;ARABIC LETTER ZAH INITIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR INITIAL ARABIC DHAH;;;; +FEC8;ARABIC LETTER ZAH MEDIAL FORM;Lo;0;AL; 0638;;;;N;GLYPH FOR MEDIAL ARABIC DHAH;;;; +FEC9;ARABIC LETTER AIN ISOLATED FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR ISOLATE ARABIC AIN;;;; +FECA;ARABIC LETTER AIN FINAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR FINAL ARABIC AIN;;;; +FECB;ARABIC LETTER AIN INITIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR INITIAL ARABIC AIN;;;; +FECC;ARABIC LETTER AIN MEDIAL FORM;Lo;0;AL; 0639;;;;N;GLYPH FOR MEDIAL ARABIC AIN;;;; +FECD;ARABIC LETTER GHAIN ISOLATED FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR ISOLATE ARABIC GHAIN;;;; +FECE;ARABIC LETTER GHAIN FINAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR FINAL ARABIC GHAIN;;;; +FECF;ARABIC LETTER GHAIN INITIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR INITIAL ARABIC GHAIN;;;; +FED0;ARABIC LETTER GHAIN MEDIAL FORM;Lo;0;AL; 063A;;;;N;GLYPH FOR MEDIAL ARABIC GHAIN;;;; +FED1;ARABIC LETTER FEH ISOLATED FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR ISOLATE ARABIC FA;;;; +FED2;ARABIC LETTER FEH FINAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR FINAL ARABIC FA;;;; +FED3;ARABIC LETTER FEH INITIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR INITIAL ARABIC FA;;;; +FED4;ARABIC LETTER FEH MEDIAL FORM;Lo;0;AL; 0641;;;;N;GLYPH FOR MEDIAL ARABIC FA;;;; +FED5;ARABIC LETTER QAF ISOLATED FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR ISOLATE ARABIC QAF;;;; +FED6;ARABIC LETTER QAF FINAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR FINAL ARABIC QAF;;;; +FED7;ARABIC LETTER QAF INITIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR INITIAL ARABIC QAF;;;; +FED8;ARABIC LETTER QAF MEDIAL FORM;Lo;0;AL; 0642;;;;N;GLYPH FOR MEDIAL ARABIC QAF;;;; +FED9;ARABIC LETTER KAF ISOLATED FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR ISOLATE ARABIC CAF;;;; +FEDA;ARABIC LETTER KAF FINAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR FINAL ARABIC CAF;;;; +FEDB;ARABIC LETTER KAF INITIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR INITIAL ARABIC CAF;;;; +FEDC;ARABIC LETTER KAF MEDIAL FORM;Lo;0;AL; 0643;;;;N;GLYPH FOR MEDIAL ARABIC CAF;;;; +FEDD;ARABIC LETTER LAM ISOLATED FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR ISOLATE ARABIC LAM;;;; +FEDE;ARABIC LETTER LAM FINAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR FINAL ARABIC LAM;;;; +FEDF;ARABIC LETTER LAM INITIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR INITIAL ARABIC LAM;;;; +FEE0;ARABIC LETTER LAM MEDIAL FORM;Lo;0;AL; 0644;;;;N;GLYPH FOR MEDIAL ARABIC LAM;;;; +FEE1;ARABIC LETTER MEEM ISOLATED FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR ISOLATE ARABIC MEEM;;;; +FEE2;ARABIC LETTER MEEM FINAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR FINAL ARABIC MEEM;;;; +FEE3;ARABIC LETTER MEEM INITIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR INITIAL ARABIC MEEM;;;; +FEE4;ARABIC LETTER MEEM MEDIAL FORM;Lo;0;AL; 0645;;;;N;GLYPH FOR MEDIAL ARABIC MEEM;;;; +FEE5;ARABIC LETTER NOON ISOLATED FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR ISOLATE ARABIC NOON;;;; +FEE6;ARABIC LETTER NOON FINAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR FINAL ARABIC NOON;;;; +FEE7;ARABIC LETTER NOON INITIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR INITIAL ARABIC NOON;;;; +FEE8;ARABIC LETTER NOON MEDIAL FORM;Lo;0;AL; 0646;;;;N;GLYPH FOR MEDIAL ARABIC NOON;;;; +FEE9;ARABIC LETTER HEH ISOLATED FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR ISOLATE ARABIC HA;;;; +FEEA;ARABIC LETTER HEH FINAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR FINAL ARABIC HA;;;; +FEEB;ARABIC LETTER HEH INITIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR INITIAL ARABIC HA;;;; +FEEC;ARABIC LETTER HEH MEDIAL FORM;Lo;0;AL; 0647;;;;N;GLYPH FOR MEDIAL ARABIC HA;;;; +FEED;ARABIC LETTER WAW ISOLATED FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR ISOLATE ARABIC WAW;;;; +FEEE;ARABIC LETTER WAW FINAL FORM;Lo;0;AL; 0648;;;;N;GLYPH FOR FINAL ARABIC WAW;;;; +FEEF;ARABIC LETTER ALEF MAKSURA ISOLATED FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR ISOLATE ARABIC ALEF MAQSURAH;;;; +FEF0;ARABIC LETTER ALEF MAKSURA FINAL FORM;Lo;0;AL; 0649;;;;N;GLYPH FOR FINAL ARABIC ALEF MAQSURAH;;;; +FEF1;ARABIC LETTER YEH ISOLATED FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR ISOLATE ARABIC YA;;;; +FEF2;ARABIC LETTER YEH FINAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR FINAL ARABIC YA;;;; +FEF3;ARABIC LETTER YEH INITIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR INITIAL ARABIC YA;;;; +FEF4;ARABIC LETTER YEH MEDIAL FORM;Lo;0;AL; 064A;;;;N;GLYPH FOR MEDIAL ARABIC YA;;;; +FEF5;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR ISOLATE ARABIC MADDAH ON LIGATURE LAM ALEF;;;; +FEF6;ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM;Lo;0;AL; 0644 0622;;;;N;GLYPH FOR FINAL ARABIC MADDAH ON LIGATURE LAM ALEF;;;; +FEF7;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; +FEF8;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 0644 0623;;;;N;GLYPH FOR FINAL ARABIC HAMZAH ON LIGATURE LAM ALEF;;;; +FEF9;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR ISOLATE ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; +FEFA;ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM;Lo;0;AL; 0644 0625;;;;N;GLYPH FOR FINAL ARABIC HAMZAH UNDER LIGATURE LAM ALEF;;;; +FEFB;ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR ISOLATE ARABIC LIGATURE LAM ALEF;;;; +FEFC;ARABIC LIGATURE LAM WITH ALEF FINAL FORM;Lo;0;AL; 0644 0627;;;;N;GLYPH FOR FINAL ARABIC LIGATURE LAM ALEF;;;; +FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; +FF01;FULLWIDTH EXCLAMATION MARK;Po;0;ON; 0021;;;;N;;;;; +FF02;FULLWIDTH QUOTATION MARK;Po;0;ON; 0022;;;;N;;;;; +FF03;FULLWIDTH NUMBER SIGN;Po;0;ET; 0023;;;;N;;;;; +FF04;FULLWIDTH DOLLAR SIGN;Sc;0;ET; 0024;;;;N;;;;; +FF05;FULLWIDTH PERCENT SIGN;Po;0;ET; 0025;;;;N;;;;; +FF06;FULLWIDTH AMPERSAND;Po;0;ON; 0026;;;;N;;;;; +FF07;FULLWIDTH APOSTROPHE;Po;0;ON; 0027;;;;N;;;;; +FF08;FULLWIDTH LEFT PARENTHESIS;Ps;0;ON; 0028;;;;Y;FULLWIDTH OPENING PARENTHESIS;;;; +FF09;FULLWIDTH RIGHT PARENTHESIS;Pe;0;ON; 0029;;;;Y;FULLWIDTH CLOSING PARENTHESIS;;;; +FF0A;FULLWIDTH ASTERISK;Po;0;ON; 002A;;;;N;;;;; +FF0B;FULLWIDTH PLUS SIGN;Sm;0;ES; 002B;;;;N;;;;; +FF0C;FULLWIDTH COMMA;Po;0;CS; 002C;;;;N;;;;; +FF0D;FULLWIDTH HYPHEN-MINUS;Pd;0;ES; 002D;;;;N;;;;; +FF0E;FULLWIDTH FULL STOP;Po;0;CS; 002E;;;;N;FULLWIDTH PERIOD;;;; +FF0F;FULLWIDTH SOLIDUS;Po;0;CS; 002F;;;;N;FULLWIDTH SLASH;;;; +FF10;FULLWIDTH DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +FF11;FULLWIDTH DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +FF12;FULLWIDTH DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +FF13;FULLWIDTH DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +FF14;FULLWIDTH DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +FF15;FULLWIDTH DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +FF16;FULLWIDTH DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +FF17;FULLWIDTH DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +FF18;FULLWIDTH DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +FF19;FULLWIDTH DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +FF1A;FULLWIDTH COLON;Po;0;CS; 003A;;;;N;;;;; +FF1B;FULLWIDTH SEMICOLON;Po;0;ON; 003B;;;;N;;;;; +FF1C;FULLWIDTH LESS-THAN SIGN;Sm;0;ON; 003C;;;;Y;;;;; +FF1D;FULLWIDTH EQUALS SIGN;Sm;0;ON; 003D;;;;N;;;;; +FF1E;FULLWIDTH GREATER-THAN SIGN;Sm;0;ON; 003E;;;;Y;;;;; +FF1F;FULLWIDTH QUESTION MARK;Po;0;ON; 003F;;;;N;;;;; +FF20;FULLWIDTH COMMERCIAL AT;Po;0;ON; 0040;;;;N;;;;; +FF21;FULLWIDTH LATIN CAPITAL LETTER A;Lu;0;L; 0041;;;;N;;;;FF41; +FF22;FULLWIDTH LATIN CAPITAL LETTER B;Lu;0;L; 0042;;;;N;;;;FF42; +FF23;FULLWIDTH LATIN CAPITAL LETTER C;Lu;0;L; 0043;;;;N;;;;FF43; +FF24;FULLWIDTH LATIN CAPITAL LETTER D;Lu;0;L; 0044;;;;N;;;;FF44; +FF25;FULLWIDTH LATIN CAPITAL LETTER E;Lu;0;L; 0045;;;;N;;;;FF45; +FF26;FULLWIDTH LATIN CAPITAL LETTER F;Lu;0;L; 0046;;;;N;;;;FF46; +FF27;FULLWIDTH LATIN CAPITAL LETTER G;Lu;0;L; 0047;;;;N;;;;FF47; +FF28;FULLWIDTH LATIN CAPITAL LETTER H;Lu;0;L; 0048;;;;N;;;;FF48; +FF29;FULLWIDTH LATIN CAPITAL LETTER I;Lu;0;L; 0049;;;;N;;;;FF49; +FF2A;FULLWIDTH LATIN CAPITAL LETTER J;Lu;0;L; 004A;;;;N;;;;FF4A; +FF2B;FULLWIDTH LATIN CAPITAL LETTER K;Lu;0;L; 004B;;;;N;;;;FF4B; +FF2C;FULLWIDTH LATIN CAPITAL LETTER L;Lu;0;L; 004C;;;;N;;;;FF4C; +FF2D;FULLWIDTH LATIN CAPITAL LETTER M;Lu;0;L; 004D;;;;N;;;;FF4D; +FF2E;FULLWIDTH LATIN CAPITAL LETTER N;Lu;0;L; 004E;;;;N;;;;FF4E; +FF2F;FULLWIDTH LATIN CAPITAL LETTER O;Lu;0;L; 004F;;;;N;;;;FF4F; +FF30;FULLWIDTH LATIN CAPITAL LETTER P;Lu;0;L; 0050;;;;N;;;;FF50; +FF31;FULLWIDTH LATIN CAPITAL LETTER Q;Lu;0;L; 0051;;;;N;;;;FF51; +FF32;FULLWIDTH LATIN CAPITAL LETTER R;Lu;0;L; 0052;;;;N;;;;FF52; +FF33;FULLWIDTH LATIN CAPITAL LETTER S;Lu;0;L; 0053;;;;N;;;;FF53; +FF34;FULLWIDTH LATIN CAPITAL LETTER T;Lu;0;L; 0054;;;;N;;;;FF54; +FF35;FULLWIDTH LATIN CAPITAL LETTER U;Lu;0;L; 0055;;;;N;;;;FF55; +FF36;FULLWIDTH LATIN CAPITAL LETTER V;Lu;0;L; 0056;;;;N;;;;FF56; +FF37;FULLWIDTH LATIN CAPITAL LETTER W;Lu;0;L; 0057;;;;N;;;;FF57; +FF38;FULLWIDTH LATIN CAPITAL LETTER X;Lu;0;L; 0058;;;;N;;;;FF58; +FF39;FULLWIDTH LATIN CAPITAL LETTER Y;Lu;0;L; 0059;;;;N;;;;FF59; +FF3A;FULLWIDTH LATIN CAPITAL LETTER Z;Lu;0;L; 005A;;;;N;;;;FF5A; +FF3B;FULLWIDTH LEFT SQUARE BRACKET;Ps;0;ON; 005B;;;;Y;FULLWIDTH OPENING SQUARE BRACKET;;;; +FF3C;FULLWIDTH REVERSE SOLIDUS;Po;0;ON; 005C;;;;N;FULLWIDTH BACKSLASH;;;; +FF3D;FULLWIDTH RIGHT SQUARE BRACKET;Pe;0;ON; 005D;;;;Y;FULLWIDTH CLOSING SQUARE BRACKET;;;; +FF3E;FULLWIDTH CIRCUMFLEX ACCENT;Sk;0;ON; 005E;;;;N;FULLWIDTH SPACING CIRCUMFLEX;;;; +FF3F;FULLWIDTH LOW LINE;Pc;0;ON; 005F;;;;N;FULLWIDTH SPACING UNDERSCORE;;;; +FF40;FULLWIDTH GRAVE ACCENT;Sk;0;ON; 0060;;;;N;FULLWIDTH SPACING GRAVE;;;; +FF41;FULLWIDTH LATIN SMALL LETTER A;Ll;0;L; 0061;;;;N;;;FF21;;FF21 +FF42;FULLWIDTH LATIN SMALL LETTER B;Ll;0;L; 0062;;;;N;;;FF22;;FF22 +FF43;FULLWIDTH LATIN SMALL LETTER C;Ll;0;L; 0063;;;;N;;;FF23;;FF23 +FF44;FULLWIDTH LATIN SMALL LETTER D;Ll;0;L; 0064;;;;N;;;FF24;;FF24 +FF45;FULLWIDTH LATIN SMALL LETTER E;Ll;0;L; 0065;;;;N;;;FF25;;FF25 +FF46;FULLWIDTH LATIN SMALL LETTER F;Ll;0;L; 0066;;;;N;;;FF26;;FF26 +FF47;FULLWIDTH LATIN SMALL LETTER G;Ll;0;L; 0067;;;;N;;;FF27;;FF27 +FF48;FULLWIDTH LATIN SMALL LETTER H;Ll;0;L; 0068;;;;N;;;FF28;;FF28 +FF49;FULLWIDTH LATIN SMALL LETTER I;Ll;0;L; 0069;;;;N;;;FF29;;FF29 +FF4A;FULLWIDTH LATIN SMALL LETTER J;Ll;0;L; 006A;;;;N;;;FF2A;;FF2A +FF4B;FULLWIDTH LATIN SMALL LETTER K;Ll;0;L; 006B;;;;N;;;FF2B;;FF2B +FF4C;FULLWIDTH LATIN SMALL LETTER L;Ll;0;L; 006C;;;;N;;;FF2C;;FF2C +FF4D;FULLWIDTH LATIN SMALL LETTER M;Ll;0;L; 006D;;;;N;;;FF2D;;FF2D +FF4E;FULLWIDTH LATIN SMALL LETTER N;Ll;0;L; 006E;;;;N;;;FF2E;;FF2E +FF4F;FULLWIDTH LATIN SMALL LETTER O;Ll;0;L; 006F;;;;N;;;FF2F;;FF2F +FF50;FULLWIDTH LATIN SMALL LETTER P;Ll;0;L; 0070;;;;N;;;FF30;;FF30 +FF51;FULLWIDTH LATIN SMALL LETTER Q;Ll;0;L; 0071;;;;N;;;FF31;;FF31 +FF52;FULLWIDTH LATIN SMALL LETTER R;Ll;0;L; 0072;;;;N;;;FF32;;FF32 +FF53;FULLWIDTH LATIN SMALL LETTER S;Ll;0;L; 0073;;;;N;;;FF33;;FF33 +FF54;FULLWIDTH LATIN SMALL LETTER T;Ll;0;L; 0074;;;;N;;;FF34;;FF34 +FF55;FULLWIDTH LATIN SMALL LETTER U;Ll;0;L; 0075;;;;N;;;FF35;;FF35 +FF56;FULLWIDTH LATIN SMALL LETTER V;Ll;0;L; 0076;;;;N;;;FF36;;FF36 +FF57;FULLWIDTH LATIN SMALL LETTER W;Ll;0;L; 0077;;;;N;;;FF37;;FF37 +FF58;FULLWIDTH LATIN SMALL LETTER X;Ll;0;L; 0078;;;;N;;;FF38;;FF38 +FF59;FULLWIDTH LATIN SMALL LETTER Y;Ll;0;L; 0079;;;;N;;;FF39;;FF39 +FF5A;FULLWIDTH LATIN SMALL LETTER Z;Ll;0;L; 007A;;;;N;;;FF3A;;FF3A +FF5B;FULLWIDTH LEFT CURLY BRACKET;Ps;0;ON; 007B;;;;Y;FULLWIDTH OPENING CURLY BRACKET;;;; +FF5C;FULLWIDTH VERTICAL LINE;Sm;0;ON; 007C;;;;N;FULLWIDTH VERTICAL BAR;;;; +FF5D;FULLWIDTH RIGHT CURLY BRACKET;Pe;0;ON; 007D;;;;Y;FULLWIDTH CLOSING CURLY BRACKET;;;; +FF5E;FULLWIDTH TILDE;Sm;0;ON; 007E;;;;N;FULLWIDTH SPACING TILDE;;;; +FF5F;FULLWIDTH LEFT WHITE PARENTHESIS;Ps;0;ON; 2985;;;;Y;;;;; +FF60;FULLWIDTH RIGHT WHITE PARENTHESIS;Pe;0;ON; 2986;;;;Y;;;;; +FF61;HALFWIDTH IDEOGRAPHIC FULL STOP;Po;0;ON; 3002;;;;N;HALFWIDTH IDEOGRAPHIC PERIOD;;;; +FF62;HALFWIDTH LEFT CORNER BRACKET;Ps;0;ON; 300C;;;;Y;HALFWIDTH OPENING CORNER BRACKET;;;; +FF63;HALFWIDTH RIGHT CORNER BRACKET;Pe;0;ON; 300D;;;;Y;HALFWIDTH CLOSING CORNER BRACKET;;;; +FF64;HALFWIDTH IDEOGRAPHIC COMMA;Po;0;ON; 3001;;;;N;;;;; +FF65;HALFWIDTH KATAKANA MIDDLE DOT;Po;0;ON; 30FB;;;;N;;;;; +FF66;HALFWIDTH KATAKANA LETTER WO;Lo;0;L; 30F2;;;;N;;;;; +FF67;HALFWIDTH KATAKANA LETTER SMALL A;Lo;0;L; 30A1;;;;N;;;;; +FF68;HALFWIDTH KATAKANA LETTER SMALL I;Lo;0;L; 30A3;;;;N;;;;; +FF69;HALFWIDTH KATAKANA LETTER SMALL U;Lo;0;L; 30A5;;;;N;;;;; +FF6A;HALFWIDTH KATAKANA LETTER SMALL E;Lo;0;L; 30A7;;;;N;;;;; +FF6B;HALFWIDTH KATAKANA LETTER SMALL O;Lo;0;L; 30A9;;;;N;;;;; +FF6C;HALFWIDTH KATAKANA LETTER SMALL YA;Lo;0;L; 30E3;;;;N;;;;; +FF6D;HALFWIDTH KATAKANA LETTER SMALL YU;Lo;0;L; 30E5;;;;N;;;;; +FF6E;HALFWIDTH KATAKANA LETTER SMALL YO;Lo;0;L; 30E7;;;;N;;;;; +FF6F;HALFWIDTH KATAKANA LETTER SMALL TU;Lo;0;L; 30C3;;;;N;;;;; +FF70;HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK;Lm;0;L; 30FC;;;;N;;;;; +FF71;HALFWIDTH KATAKANA LETTER A;Lo;0;L; 30A2;;;;N;;;;; +FF72;HALFWIDTH KATAKANA LETTER I;Lo;0;L; 30A4;;;;N;;;;; +FF73;HALFWIDTH KATAKANA LETTER U;Lo;0;L; 30A6;;;;N;;;;; +FF74;HALFWIDTH KATAKANA LETTER E;Lo;0;L; 30A8;;;;N;;;;; +FF75;HALFWIDTH KATAKANA LETTER O;Lo;0;L; 30AA;;;;N;;;;; +FF76;HALFWIDTH KATAKANA LETTER KA;Lo;0;L; 30AB;;;;N;;;;; +FF77;HALFWIDTH KATAKANA LETTER KI;Lo;0;L; 30AD;;;;N;;;;; +FF78;HALFWIDTH KATAKANA LETTER KU;Lo;0;L; 30AF;;;;N;;;;; +FF79;HALFWIDTH KATAKANA LETTER KE;Lo;0;L; 30B1;;;;N;;;;; +FF7A;HALFWIDTH KATAKANA LETTER KO;Lo;0;L; 30B3;;;;N;;;;; +FF7B;HALFWIDTH KATAKANA LETTER SA;Lo;0;L; 30B5;;;;N;;;;; +FF7C;HALFWIDTH KATAKANA LETTER SI;Lo;0;L; 30B7;;;;N;;;;; +FF7D;HALFWIDTH KATAKANA LETTER SU;Lo;0;L; 30B9;;;;N;;;;; +FF7E;HALFWIDTH KATAKANA LETTER SE;Lo;0;L; 30BB;;;;N;;;;; +FF7F;HALFWIDTH KATAKANA LETTER SO;Lo;0;L; 30BD;;;;N;;;;; +FF80;HALFWIDTH KATAKANA LETTER TA;Lo;0;L; 30BF;;;;N;;;;; +FF81;HALFWIDTH KATAKANA LETTER TI;Lo;0;L; 30C1;;;;N;;;;; +FF82;HALFWIDTH KATAKANA LETTER TU;Lo;0;L; 30C4;;;;N;;;;; +FF83;HALFWIDTH KATAKANA LETTER TE;Lo;0;L; 30C6;;;;N;;;;; +FF84;HALFWIDTH KATAKANA LETTER TO;Lo;0;L; 30C8;;;;N;;;;; +FF85;HALFWIDTH KATAKANA LETTER NA;Lo;0;L; 30CA;;;;N;;;;; +FF86;HALFWIDTH KATAKANA LETTER NI;Lo;0;L; 30CB;;;;N;;;;; +FF87;HALFWIDTH KATAKANA LETTER NU;Lo;0;L; 30CC;;;;N;;;;; +FF88;HALFWIDTH KATAKANA LETTER NE;Lo;0;L; 30CD;;;;N;;;;; +FF89;HALFWIDTH KATAKANA LETTER NO;Lo;0;L; 30CE;;;;N;;;;; +FF8A;HALFWIDTH KATAKANA LETTER HA;Lo;0;L; 30CF;;;;N;;;;; +FF8B;HALFWIDTH KATAKANA LETTER HI;Lo;0;L; 30D2;;;;N;;;;; +FF8C;HALFWIDTH KATAKANA LETTER HU;Lo;0;L; 30D5;;;;N;;;;; +FF8D;HALFWIDTH KATAKANA LETTER HE;Lo;0;L; 30D8;;;;N;;;;; +FF8E;HALFWIDTH KATAKANA LETTER HO;Lo;0;L; 30DB;;;;N;;;;; +FF8F;HALFWIDTH KATAKANA LETTER MA;Lo;0;L; 30DE;;;;N;;;;; +FF90;HALFWIDTH KATAKANA LETTER MI;Lo;0;L; 30DF;;;;N;;;;; +FF91;HALFWIDTH KATAKANA LETTER MU;Lo;0;L; 30E0;;;;N;;;;; +FF92;HALFWIDTH KATAKANA LETTER ME;Lo;0;L; 30E1;;;;N;;;;; +FF93;HALFWIDTH KATAKANA LETTER MO;Lo;0;L; 30E2;;;;N;;;;; +FF94;HALFWIDTH KATAKANA LETTER YA;Lo;0;L; 30E4;;;;N;;;;; +FF95;HALFWIDTH KATAKANA LETTER YU;Lo;0;L; 30E6;;;;N;;;;; +FF96;HALFWIDTH KATAKANA LETTER YO;Lo;0;L; 30E8;;;;N;;;;; +FF97;HALFWIDTH KATAKANA LETTER RA;Lo;0;L; 30E9;;;;N;;;;; +FF98;HALFWIDTH KATAKANA LETTER RI;Lo;0;L; 30EA;;;;N;;;;; +FF99;HALFWIDTH KATAKANA LETTER RU;Lo;0;L; 30EB;;;;N;;;;; +FF9A;HALFWIDTH KATAKANA LETTER RE;Lo;0;L; 30EC;;;;N;;;;; +FF9B;HALFWIDTH KATAKANA LETTER RO;Lo;0;L; 30ED;;;;N;;;;; +FF9C;HALFWIDTH KATAKANA LETTER WA;Lo;0;L; 30EF;;;;N;;;;; +FF9D;HALFWIDTH KATAKANA LETTER N;Lo;0;L; 30F3;;;;N;;;;; +FF9E;HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;; +FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;; +FFA0;HALFWIDTH HANGUL FILLER;Lo;0;L; 3164;;;;N;HALFWIDTH HANGUL CAE OM;;;; +FFA1;HALFWIDTH HANGUL LETTER KIYEOK;Lo;0;L; 3131;;;;N;HALFWIDTH HANGUL LETTER GIYEOG;;;; +FFA2;HALFWIDTH HANGUL LETTER SSANGKIYEOK;Lo;0;L; 3132;;;;N;HALFWIDTH HANGUL LETTER SSANG GIYEOG;;;; +FFA3;HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;; +FFA4;HALFWIDTH HANGUL LETTER NIEUN;Lo;0;L; 3134;;;;N;;;;; +FFA5;HALFWIDTH HANGUL LETTER NIEUN-CIEUC;Lo;0;L; 3135;;;;N;HALFWIDTH HANGUL LETTER NIEUN JIEUJ;;;; +FFA6;HALFWIDTH HANGUL LETTER NIEUN-HIEUH;Lo;0;L; 3136;;;;N;HALFWIDTH HANGUL LETTER NIEUN HIEUH;;;; +FFA7;HALFWIDTH HANGUL LETTER TIKEUT;Lo;0;L; 3137;;;;N;HALFWIDTH HANGUL LETTER DIGEUD;;;; +FFA8;HALFWIDTH HANGUL LETTER SSANGTIKEUT;Lo;0;L; 3138;;;;N;HALFWIDTH HANGUL LETTER SSANG DIGEUD;;;; +FFA9;HALFWIDTH HANGUL LETTER RIEUL;Lo;0;L; 3139;;;;N;HALFWIDTH HANGUL LETTER LIEUL;;;; +FFAA;HALFWIDTH HANGUL LETTER RIEUL-KIYEOK;Lo;0;L; 313A;;;;N;HALFWIDTH HANGUL LETTER LIEUL GIYEOG;;;; +FFAB;HALFWIDTH HANGUL LETTER RIEUL-MIEUM;Lo;0;L; 313B;;;;N;HALFWIDTH HANGUL LETTER LIEUL MIEUM;;;; +FFAC;HALFWIDTH HANGUL LETTER RIEUL-PIEUP;Lo;0;L; 313C;;;;N;HALFWIDTH HANGUL LETTER LIEUL BIEUB;;;; +FFAD;HALFWIDTH HANGUL LETTER RIEUL-SIOS;Lo;0;L; 313D;;;;N;HALFWIDTH HANGUL LETTER LIEUL SIOS;;;; +FFAE;HALFWIDTH HANGUL LETTER RIEUL-THIEUTH;Lo;0;L; 313E;;;;N;HALFWIDTH HANGUL LETTER LIEUL TIEUT;;;; +FFAF;HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH;Lo;0;L; 313F;;;;N;HALFWIDTH HANGUL LETTER LIEUL PIEUP;;;; +FFB0;HALFWIDTH HANGUL LETTER RIEUL-HIEUH;Lo;0;L; 3140;;;;N;HALFWIDTH HANGUL LETTER LIEUL HIEUH;;;; +FFB1;HALFWIDTH HANGUL LETTER MIEUM;Lo;0;L; 3141;;;;N;;;;; +FFB2;HALFWIDTH HANGUL LETTER PIEUP;Lo;0;L; 3142;;;;N;HALFWIDTH HANGUL LETTER BIEUB;;;; +FFB3;HALFWIDTH HANGUL LETTER SSANGPIEUP;Lo;0;L; 3143;;;;N;HALFWIDTH HANGUL LETTER SSANG BIEUB;;;; +FFB4;HALFWIDTH HANGUL LETTER PIEUP-SIOS;Lo;0;L; 3144;;;;N;HALFWIDTH HANGUL LETTER BIEUB SIOS;;;; +FFB5;HALFWIDTH HANGUL LETTER SIOS;Lo;0;L; 3145;;;;N;;;;; +FFB6;HALFWIDTH HANGUL LETTER SSANGSIOS;Lo;0;L; 3146;;;;N;HALFWIDTH HANGUL LETTER SSANG SIOS;;;; +FFB7;HALFWIDTH HANGUL LETTER IEUNG;Lo;0;L; 3147;;;;N;;;;; +FFB8;HALFWIDTH HANGUL LETTER CIEUC;Lo;0;L; 3148;;;;N;HALFWIDTH HANGUL LETTER JIEUJ;;;; +FFB9;HALFWIDTH HANGUL LETTER SSANGCIEUC;Lo;0;L; 3149;;;;N;HALFWIDTH HANGUL LETTER SSANG JIEUJ;;;; +FFBA;HALFWIDTH HANGUL LETTER CHIEUCH;Lo;0;L; 314A;;;;N;HALFWIDTH HANGUL LETTER CIEUC;;;; +FFBB;HALFWIDTH HANGUL LETTER KHIEUKH;Lo;0;L; 314B;;;;N;HALFWIDTH HANGUL LETTER KIYEOK;;;; +FFBC;HALFWIDTH HANGUL LETTER THIEUTH;Lo;0;L; 314C;;;;N;HALFWIDTH HANGUL LETTER TIEUT;;;; +FFBD;HALFWIDTH HANGUL LETTER PHIEUPH;Lo;0;L; 314D;;;;N;HALFWIDTH HANGUL LETTER PIEUP;;;; +FFBE;HALFWIDTH HANGUL LETTER HIEUH;Lo;0;L; 314E;;;;N;;;;; +FFC2;HALFWIDTH HANGUL LETTER A;Lo;0;L; 314F;;;;N;;;;; +FFC3;HALFWIDTH HANGUL LETTER AE;Lo;0;L; 3150;;;;N;;;;; +FFC4;HALFWIDTH HANGUL LETTER YA;Lo;0;L; 3151;;;;N;;;;; +FFC5;HALFWIDTH HANGUL LETTER YAE;Lo;0;L; 3152;;;;N;;;;; +FFC6;HALFWIDTH HANGUL LETTER EO;Lo;0;L; 3153;;;;N;;;;; +FFC7;HALFWIDTH HANGUL LETTER E;Lo;0;L; 3154;;;;N;;;;; +FFCA;HALFWIDTH HANGUL LETTER YEO;Lo;0;L; 3155;;;;N;;;;; +FFCB;HALFWIDTH HANGUL LETTER YE;Lo;0;L; 3156;;;;N;;;;; +FFCC;HALFWIDTH HANGUL LETTER O;Lo;0;L; 3157;;;;N;;;;; +FFCD;HALFWIDTH HANGUL LETTER WA;Lo;0;L; 3158;;;;N;;;;; +FFCE;HALFWIDTH HANGUL LETTER WAE;Lo;0;L; 3159;;;;N;;;;; +FFCF;HALFWIDTH HANGUL LETTER OE;Lo;0;L; 315A;;;;N;;;;; +FFD2;HALFWIDTH HANGUL LETTER YO;Lo;0;L; 315B;;;;N;;;;; +FFD3;HALFWIDTH HANGUL LETTER U;Lo;0;L; 315C;;;;N;;;;; +FFD4;HALFWIDTH HANGUL LETTER WEO;Lo;0;L; 315D;;;;N;;;;; +FFD5;HALFWIDTH HANGUL LETTER WE;Lo;0;L; 315E;;;;N;;;;; +FFD6;HALFWIDTH HANGUL LETTER WI;Lo;0;L; 315F;;;;N;;;;; +FFD7;HALFWIDTH HANGUL LETTER YU;Lo;0;L; 3160;;;;N;;;;; +FFDA;HALFWIDTH HANGUL LETTER EU;Lo;0;L; 3161;;;;N;;;;; +FFDB;HALFWIDTH HANGUL LETTER YI;Lo;0;L; 3162;;;;N;;;;; +FFDC;HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;; +FFE0;FULLWIDTH CENT SIGN;Sc;0;ET; 00A2;;;;N;;;;; +FFE1;FULLWIDTH POUND SIGN;Sc;0;ET; 00A3;;;;N;;;;; +FFE2;FULLWIDTH NOT SIGN;Sm;0;ON; 00AC;;;;N;;;;; +FFE3;FULLWIDTH MACRON;Sk;0;ON; 00AF;;;;N;FULLWIDTH SPACING MACRON;;;; +FFE4;FULLWIDTH BROKEN BAR;So;0;ON; 00A6;;;;N;FULLWIDTH BROKEN VERTICAL BAR;;;; +FFE5;FULLWIDTH YEN SIGN;Sc;0;ET; 00A5;;;;N;;;;; +FFE6;FULLWIDTH WON SIGN;Sc;0;ET; 20A9;;;;N;;;;; +FFE8;HALFWIDTH FORMS LIGHT VERTICAL;So;0;ON; 2502;;;;N;;;;; +FFE9;HALFWIDTH LEFTWARDS ARROW;Sm;0;ON; 2190;;;;N;;;;; +FFEA;HALFWIDTH UPWARDS ARROW;Sm;0;ON; 2191;;;;N;;;;; +FFEB;HALFWIDTH RIGHTWARDS ARROW;Sm;0;ON; 2192;;;;N;;;;; +FFEC;HALFWIDTH DOWNWARDS ARROW;Sm;0;ON; 2193;;;;N;;;;; +FFED;HALFWIDTH BLACK SQUARE;So;0;ON; 25A0;;;;N;;;;; +FFEE;HALFWIDTH WHITE CIRCLE;So;0;ON; 25CB;;;;N;;;;; +FFF9;INTERLINEAR ANNOTATION ANCHOR;Cf;0;ON;;;;;N;;;;; +FFFA;INTERLINEAR ANNOTATION SEPARATOR;Cf;0;ON;;;;;N;;;;; +FFFB;INTERLINEAR ANNOTATION TERMINATOR;Cf;0;ON;;;;;N;;;;; +FFFC;OBJECT REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; +FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; +10000;LINEAR B SYLLABLE B008 A;Lo;0;L;;;;;N;;;;; +10001;LINEAR B SYLLABLE B038 E;Lo;0;L;;;;;N;;;;; +10002;LINEAR B SYLLABLE B028 I;Lo;0;L;;;;;N;;;;; +10003;LINEAR B SYLLABLE B061 O;Lo;0;L;;;;;N;;;;; +10004;LINEAR B SYLLABLE B010 U;Lo;0;L;;;;;N;;;;; +10005;LINEAR B SYLLABLE B001 DA;Lo;0;L;;;;;N;;;;; +10006;LINEAR B SYLLABLE B045 DE;Lo;0;L;;;;;N;;;;; +10007;LINEAR B SYLLABLE B007 DI;Lo;0;L;;;;;N;;;;; +10008;LINEAR B SYLLABLE B014 DO;Lo;0;L;;;;;N;;;;; +10009;LINEAR B SYLLABLE B051 DU;Lo;0;L;;;;;N;;;;; +1000A;LINEAR B SYLLABLE B057 JA;Lo;0;L;;;;;N;;;;; +1000B;LINEAR B SYLLABLE B046 JE;Lo;0;L;;;;;N;;;;; +1000D;LINEAR B SYLLABLE B036 JO;Lo;0;L;;;;;N;;;;; +1000E;LINEAR B SYLLABLE B065 JU;Lo;0;L;;;;;N;;;;; +1000F;LINEAR B SYLLABLE B077 KA;Lo;0;L;;;;;N;;;;; +10010;LINEAR B SYLLABLE B044 KE;Lo;0;L;;;;;N;;;;; +10011;LINEAR B SYLLABLE B067 KI;Lo;0;L;;;;;N;;;;; +10012;LINEAR B SYLLABLE B070 KO;Lo;0;L;;;;;N;;;;; +10013;LINEAR B SYLLABLE B081 KU;Lo;0;L;;;;;N;;;;; +10014;LINEAR B SYLLABLE B080 MA;Lo;0;L;;;;;N;;;;; +10015;LINEAR B SYLLABLE B013 ME;Lo;0;L;;;;;N;;;;; +10016;LINEAR B SYLLABLE B073 MI;Lo;0;L;;;;;N;;;;; +10017;LINEAR B SYLLABLE B015 MO;Lo;0;L;;;;;N;;;;; +10018;LINEAR B SYLLABLE B023 MU;Lo;0;L;;;;;N;;;;; +10019;LINEAR B SYLLABLE B006 NA;Lo;0;L;;;;;N;;;;; +1001A;LINEAR B SYLLABLE B024 NE;Lo;0;L;;;;;N;;;;; +1001B;LINEAR B SYLLABLE B030 NI;Lo;0;L;;;;;N;;;;; +1001C;LINEAR B SYLLABLE B052 NO;Lo;0;L;;;;;N;;;;; +1001D;LINEAR B SYLLABLE B055 NU;Lo;0;L;;;;;N;;;;; +1001E;LINEAR B SYLLABLE B003 PA;Lo;0;L;;;;;N;;;;; +1001F;LINEAR B SYLLABLE B072 PE;Lo;0;L;;;;;N;;;;; +10020;LINEAR B SYLLABLE B039 PI;Lo;0;L;;;;;N;;;;; +10021;LINEAR B SYLLABLE B011 PO;Lo;0;L;;;;;N;;;;; +10022;LINEAR B SYLLABLE B050 PU;Lo;0;L;;;;;N;;;;; +10023;LINEAR B SYLLABLE B016 QA;Lo;0;L;;;;;N;;;;; +10024;LINEAR B SYLLABLE B078 QE;Lo;0;L;;;;;N;;;;; +10025;LINEAR B SYLLABLE B021 QI;Lo;0;L;;;;;N;;;;; +10026;LINEAR B SYLLABLE B032 QO;Lo;0;L;;;;;N;;;;; +10028;LINEAR B SYLLABLE B060 RA;Lo;0;L;;;;;N;;;;; +10029;LINEAR B SYLLABLE B027 RE;Lo;0;L;;;;;N;;;;; +1002A;LINEAR B SYLLABLE B053 RI;Lo;0;L;;;;;N;;;;; +1002B;LINEAR B SYLLABLE B002 RO;Lo;0;L;;;;;N;;;;; +1002C;LINEAR B SYLLABLE B026 RU;Lo;0;L;;;;;N;;;;; +1002D;LINEAR B SYLLABLE B031 SA;Lo;0;L;;;;;N;;;;; +1002E;LINEAR B SYLLABLE B009 SE;Lo;0;L;;;;;N;;;;; +1002F;LINEAR B SYLLABLE B041 SI;Lo;0;L;;;;;N;;;;; +10030;LINEAR B SYLLABLE B012 SO;Lo;0;L;;;;;N;;;;; +10031;LINEAR B SYLLABLE B058 SU;Lo;0;L;;;;;N;;;;; +10032;LINEAR B SYLLABLE B059 TA;Lo;0;L;;;;;N;;;;; +10033;LINEAR B SYLLABLE B004 TE;Lo;0;L;;;;;N;;;;; +10034;LINEAR B SYLLABLE B037 TI;Lo;0;L;;;;;N;;;;; +10035;LINEAR B SYLLABLE B005 TO;Lo;0;L;;;;;N;;;;; +10036;LINEAR B SYLLABLE B069 TU;Lo;0;L;;;;;N;;;;; +10037;LINEAR B SYLLABLE B054 WA;Lo;0;L;;;;;N;;;;; +10038;LINEAR B SYLLABLE B075 WE;Lo;0;L;;;;;N;;;;; +10039;LINEAR B SYLLABLE B040 WI;Lo;0;L;;;;;N;;;;; +1003A;LINEAR B SYLLABLE B042 WO;Lo;0;L;;;;;N;;;;; +1003C;LINEAR B SYLLABLE B017 ZA;Lo;0;L;;;;;N;;;;; +1003D;LINEAR B SYLLABLE B074 ZE;Lo;0;L;;;;;N;;;;; +1003F;LINEAR B SYLLABLE B020 ZO;Lo;0;L;;;;;N;;;;; +10040;LINEAR B SYLLABLE B025 A2;Lo;0;L;;;;;N;;;;; +10041;LINEAR B SYLLABLE B043 A3;Lo;0;L;;;;;N;;;;; +10042;LINEAR B SYLLABLE B085 AU;Lo;0;L;;;;;N;;;;; +10043;LINEAR B SYLLABLE B071 DWE;Lo;0;L;;;;;N;;;;; +10044;LINEAR B SYLLABLE B090 DWO;Lo;0;L;;;;;N;;;;; +10045;LINEAR B SYLLABLE B048 NWA;Lo;0;L;;;;;N;;;;; +10046;LINEAR B SYLLABLE B029 PU2;Lo;0;L;;;;;N;;;;; +10047;LINEAR B SYLLABLE B062 PTE;Lo;0;L;;;;;N;;;;; +10048;LINEAR B SYLLABLE B076 RA2;Lo;0;L;;;;;N;;;;; +10049;LINEAR B SYLLABLE B033 RA3;Lo;0;L;;;;;N;;;;; +1004A;LINEAR B SYLLABLE B068 RO2;Lo;0;L;;;;;N;;;;; +1004B;LINEAR B SYLLABLE B066 TA2;Lo;0;L;;;;;N;;;;; +1004C;LINEAR B SYLLABLE B087 TWE;Lo;0;L;;;;;N;;;;; +1004D;LINEAR B SYLLABLE B091 TWO;Lo;0;L;;;;;N;;;;; +10050;LINEAR B SYMBOL B018;Lo;0;L;;;;;N;;;;; +10051;LINEAR B SYMBOL B019;Lo;0;L;;;;;N;;;;; +10052;LINEAR B SYMBOL B022;Lo;0;L;;;;;N;;;;; +10053;LINEAR B SYMBOL B034;Lo;0;L;;;;;N;;;;; +10054;LINEAR B SYMBOL B047;Lo;0;L;;;;;N;;;;; +10055;LINEAR B SYMBOL B049;Lo;0;L;;;;;N;;;;; +10056;LINEAR B SYMBOL B056;Lo;0;L;;;;;N;;;;; +10057;LINEAR B SYMBOL B063;Lo;0;L;;;;;N;;;;; +10058;LINEAR B SYMBOL B064;Lo;0;L;;;;;N;;;;; +10059;LINEAR B SYMBOL B079;Lo;0;L;;;;;N;;;;; +1005A;LINEAR B SYMBOL B082;Lo;0;L;;;;;N;;;;; +1005B;LINEAR B SYMBOL B083;Lo;0;L;;;;;N;;;;; +1005C;LINEAR B SYMBOL B086;Lo;0;L;;;;;N;;;;; +1005D;LINEAR B SYMBOL B089;Lo;0;L;;;;;N;;;;; +10080;LINEAR B IDEOGRAM B100 MAN;Lo;0;L;;;;;N;;;;; +10081;LINEAR B IDEOGRAM B102 WOMAN;Lo;0;L;;;;;N;;;;; +10082;LINEAR B IDEOGRAM B104 DEER;Lo;0;L;;;;;N;;;;; +10083;LINEAR B IDEOGRAM B105 EQUID;Lo;0;L;;;;;N;;;;; +10084;LINEAR B IDEOGRAM B105F MARE;Lo;0;L;;;;;N;;;;; +10085;LINEAR B IDEOGRAM B105M STALLION;Lo;0;L;;;;;N;;;;; +10086;LINEAR B IDEOGRAM B106F EWE;Lo;0;L;;;;;N;;;;; +10087;LINEAR B IDEOGRAM B106M RAM;Lo;0;L;;;;;N;;;;; +10088;LINEAR B IDEOGRAM B107F SHE-GOAT;Lo;0;L;;;;;N;;;;; +10089;LINEAR B IDEOGRAM B107M HE-GOAT;Lo;0;L;;;;;N;;;;; +1008A;LINEAR B IDEOGRAM B108F SOW;Lo;0;L;;;;;N;;;;; +1008B;LINEAR B IDEOGRAM B108M BOAR;Lo;0;L;;;;;N;;;;; +1008C;LINEAR B IDEOGRAM B109F COW;Lo;0;L;;;;;N;;;;; +1008D;LINEAR B IDEOGRAM B109M BULL;Lo;0;L;;;;;N;;;;; +1008E;LINEAR B IDEOGRAM B120 WHEAT;Lo;0;L;;;;;N;;;;; +1008F;LINEAR B IDEOGRAM B121 BARLEY;Lo;0;L;;;;;N;;;;; +10090;LINEAR B IDEOGRAM B122 OLIVE;Lo;0;L;;;;;N;;;;; +10091;LINEAR B IDEOGRAM B123 SPICE;Lo;0;L;;;;;N;;;;; +10092;LINEAR B IDEOGRAM B125 CYPERUS;Lo;0;L;;;;;N;;;;; +10093;LINEAR B MONOGRAM B127 KAPO;Lo;0;L;;;;;N;;;;; +10094;LINEAR B MONOGRAM B128 KANAKO;Lo;0;L;;;;;N;;;;; +10095;LINEAR B IDEOGRAM B130 OIL;Lo;0;L;;;;;N;;;;; +10096;LINEAR B IDEOGRAM B131 WINE;Lo;0;L;;;;;N;;;;; +10097;LINEAR B IDEOGRAM B132;Lo;0;L;;;;;N;;;;; +10098;LINEAR B MONOGRAM B133 AREPA;Lo;0;L;;;;;N;;;;; +10099;LINEAR B MONOGRAM B135 MERI;Lo;0;L;;;;;N;;;;; +1009A;LINEAR B IDEOGRAM B140 BRONZE;Lo;0;L;;;;;N;;;;; +1009B;LINEAR B IDEOGRAM B141 GOLD;Lo;0;L;;;;;N;;;;; +1009C;LINEAR B IDEOGRAM B142;Lo;0;L;;;;;N;;;;; +1009D;LINEAR B IDEOGRAM B145 WOOL;Lo;0;L;;;;;N;;;;; +1009E;LINEAR B IDEOGRAM B146;Lo;0;L;;;;;N;;;;; +1009F;LINEAR B IDEOGRAM B150;Lo;0;L;;;;;N;;;;; +100A0;LINEAR B IDEOGRAM B151 HORN;Lo;0;L;;;;;N;;;;; +100A1;LINEAR B IDEOGRAM B152;Lo;0;L;;;;;N;;;;; +100A2;LINEAR B IDEOGRAM B153;Lo;0;L;;;;;N;;;;; +100A3;LINEAR B IDEOGRAM B154;Lo;0;L;;;;;N;;;;; +100A4;LINEAR B MONOGRAM B156 TURO2;Lo;0;L;;;;;N;;;;; +100A5;LINEAR B IDEOGRAM B157;Lo;0;L;;;;;N;;;;; +100A6;LINEAR B IDEOGRAM B158;Lo;0;L;;;;;N;;;;; +100A7;LINEAR B IDEOGRAM B159 CLOTH;Lo;0;L;;;;;N;;;;; +100A8;LINEAR B IDEOGRAM B160;Lo;0;L;;;;;N;;;;; +100A9;LINEAR B IDEOGRAM B161;Lo;0;L;;;;;N;;;;; +100AA;LINEAR B IDEOGRAM B162 GARMENT;Lo;0;L;;;;;N;;;;; +100AB;LINEAR B IDEOGRAM B163 ARMOUR;Lo;0;L;;;;;N;;;;; +100AC;LINEAR B IDEOGRAM B164;Lo;0;L;;;;;N;;;;; +100AD;LINEAR B IDEOGRAM B165;Lo;0;L;;;;;N;;;;; +100AE;LINEAR B IDEOGRAM B166;Lo;0;L;;;;;N;;;;; +100AF;LINEAR B IDEOGRAM B167;Lo;0;L;;;;;N;;;;; +100B0;LINEAR B IDEOGRAM B168;Lo;0;L;;;;;N;;;;; +100B1;LINEAR B IDEOGRAM B169;Lo;0;L;;;;;N;;;;; +100B2;LINEAR B IDEOGRAM B170;Lo;0;L;;;;;N;;;;; +100B3;LINEAR B IDEOGRAM B171;Lo;0;L;;;;;N;;;;; +100B4;LINEAR B IDEOGRAM B172;Lo;0;L;;;;;N;;;;; +100B5;LINEAR B IDEOGRAM B173 MONTH;Lo;0;L;;;;;N;;;;; +100B6;LINEAR B IDEOGRAM B174;Lo;0;L;;;;;N;;;;; +100B7;LINEAR B IDEOGRAM B176 TREE;Lo;0;L;;;;;N;;;;; +100B8;LINEAR B IDEOGRAM B177;Lo;0;L;;;;;N;;;;; +100B9;LINEAR B IDEOGRAM B178;Lo;0;L;;;;;N;;;;; +100BA;LINEAR B IDEOGRAM B179;Lo;0;L;;;;;N;;;;; +100BB;LINEAR B IDEOGRAM B180;Lo;0;L;;;;;N;;;;; +100BC;LINEAR B IDEOGRAM B181;Lo;0;L;;;;;N;;;;; +100BD;LINEAR B IDEOGRAM B182;Lo;0;L;;;;;N;;;;; +100BE;LINEAR B IDEOGRAM B183;Lo;0;L;;;;;N;;;;; +100BF;LINEAR B IDEOGRAM B184;Lo;0;L;;;;;N;;;;; +100C0;LINEAR B IDEOGRAM B185;Lo;0;L;;;;;N;;;;; +100C1;LINEAR B IDEOGRAM B189;Lo;0;L;;;;;N;;;;; +100C2;LINEAR B IDEOGRAM B190;Lo;0;L;;;;;N;;;;; +100C3;LINEAR B IDEOGRAM B191 HELMET;Lo;0;L;;;;;N;;;;; +100C4;LINEAR B IDEOGRAM B220 FOOTSTOOL;Lo;0;L;;;;;N;;;;; +100C5;LINEAR B IDEOGRAM B225 BATHTUB;Lo;0;L;;;;;N;;;;; +100C6;LINEAR B IDEOGRAM B230 SPEAR;Lo;0;L;;;;;N;;;;; +100C7;LINEAR B IDEOGRAM B231 ARROW;Lo;0;L;;;;;N;;;;; +100C8;LINEAR B IDEOGRAM B232;Lo;0;L;;;;;N;;;;; +100C9;LINEAR B IDEOGRAM B233 SWORD;Lo;0;L;;;;;N;;;;; +100CA;LINEAR B IDEOGRAM B234;Lo;0;L;;;;;N;;;;; +100CB;LINEAR B IDEOGRAM B236;Lo;0;L;;;;;N;;;;; +100CC;LINEAR B IDEOGRAM B240 WHEELED CHARIOT;Lo;0;L;;;;;N;;;;; +100CD;LINEAR B IDEOGRAM B241 CHARIOT;Lo;0;L;;;;;N;;;;; +100CE;LINEAR B IDEOGRAM B242 CHARIOT FRAME;Lo;0;L;;;;;N;;;;; +100CF;LINEAR B IDEOGRAM B243 WHEEL;Lo;0;L;;;;;N;;;;; +100D0;LINEAR B IDEOGRAM B245;Lo;0;L;;;;;N;;;;; +100D1;LINEAR B IDEOGRAM B246;Lo;0;L;;;;;N;;;;; +100D2;LINEAR B MONOGRAM B247 DIPTE;Lo;0;L;;;;;N;;;;; +100D3;LINEAR B IDEOGRAM B248;Lo;0;L;;;;;N;;;;; +100D4;LINEAR B IDEOGRAM B249;Lo;0;L;;;;;N;;;;; +100D5;LINEAR B IDEOGRAM B251;Lo;0;L;;;;;N;;;;; +100D6;LINEAR B IDEOGRAM B252;Lo;0;L;;;;;N;;;;; +100D7;LINEAR B IDEOGRAM B253;Lo;0;L;;;;;N;;;;; +100D8;LINEAR B IDEOGRAM B254 DART;Lo;0;L;;;;;N;;;;; +100D9;LINEAR B IDEOGRAM B255;Lo;0;L;;;;;N;;;;; +100DA;LINEAR B IDEOGRAM B256;Lo;0;L;;;;;N;;;;; +100DB;LINEAR B IDEOGRAM B257;Lo;0;L;;;;;N;;;;; +100DC;LINEAR B IDEOGRAM B258;Lo;0;L;;;;;N;;;;; +100DD;LINEAR B IDEOGRAM B259;Lo;0;L;;;;;N;;;;; +100DE;LINEAR B IDEOGRAM VESSEL B155;Lo;0;L;;;;;N;;;;; +100DF;LINEAR B IDEOGRAM VESSEL B200;Lo;0;L;;;;;N;;;;; +100E0;LINEAR B IDEOGRAM VESSEL B201;Lo;0;L;;;;;N;;;;; +100E1;LINEAR B IDEOGRAM VESSEL B202;Lo;0;L;;;;;N;;;;; +100E2;LINEAR B IDEOGRAM VESSEL B203;Lo;0;L;;;;;N;;;;; +100E3;LINEAR B IDEOGRAM VESSEL B204;Lo;0;L;;;;;N;;;;; +100E4;LINEAR B IDEOGRAM VESSEL B205;Lo;0;L;;;;;N;;;;; +100E5;LINEAR B IDEOGRAM VESSEL B206;Lo;0;L;;;;;N;;;;; +100E6;LINEAR B IDEOGRAM VESSEL B207;Lo;0;L;;;;;N;;;;; +100E7;LINEAR B IDEOGRAM VESSEL B208;Lo;0;L;;;;;N;;;;; +100E8;LINEAR B IDEOGRAM VESSEL B209;Lo;0;L;;;;;N;;;;; +100E9;LINEAR B IDEOGRAM VESSEL B210;Lo;0;L;;;;;N;;;;; +100EA;LINEAR B IDEOGRAM VESSEL B211;Lo;0;L;;;;;N;;;;; +100EB;LINEAR B IDEOGRAM VESSEL B212;Lo;0;L;;;;;N;;;;; +100EC;LINEAR B IDEOGRAM VESSEL B213;Lo;0;L;;;;;N;;;;; +100ED;LINEAR B IDEOGRAM VESSEL B214;Lo;0;L;;;;;N;;;;; +100EE;LINEAR B IDEOGRAM VESSEL B215;Lo;0;L;;;;;N;;;;; +100EF;LINEAR B IDEOGRAM VESSEL B216;Lo;0;L;;;;;N;;;;; +100F0;LINEAR B IDEOGRAM VESSEL B217;Lo;0;L;;;;;N;;;;; +100F1;LINEAR B IDEOGRAM VESSEL B218;Lo;0;L;;;;;N;;;;; +100F2;LINEAR B IDEOGRAM VESSEL B219;Lo;0;L;;;;;N;;;;; +100F3;LINEAR B IDEOGRAM VESSEL B221;Lo;0;L;;;;;N;;;;; +100F4;LINEAR B IDEOGRAM VESSEL B222;Lo;0;L;;;;;N;;;;; +100F5;LINEAR B IDEOGRAM VESSEL B226;Lo;0;L;;;;;N;;;;; +100F6;LINEAR B IDEOGRAM VESSEL B227;Lo;0;L;;;;;N;;;;; +100F7;LINEAR B IDEOGRAM VESSEL B228;Lo;0;L;;;;;N;;;;; +100F8;LINEAR B IDEOGRAM VESSEL B229;Lo;0;L;;;;;N;;;;; +100F9;LINEAR B IDEOGRAM VESSEL B250;Lo;0;L;;;;;N;;;;; +100FA;LINEAR B IDEOGRAM VESSEL B305;Lo;0;L;;;;;N;;;;; +10100;AEGEAN WORD SEPARATOR LINE;Po;0;L;;;;;N;;;;; +10101;AEGEAN WORD SEPARATOR DOT;Po;0;ON;;;;;N;;;;; +10102;AEGEAN CHECK MARK;Po;0;L;;;;;N;;;;; +10107;AEGEAN NUMBER ONE;No;0;L;;;;1;N;;;;; +10108;AEGEAN NUMBER TWO;No;0;L;;;;2;N;;;;; +10109;AEGEAN NUMBER THREE;No;0;L;;;;3;N;;;;; +1010A;AEGEAN NUMBER FOUR;No;0;L;;;;4;N;;;;; +1010B;AEGEAN NUMBER FIVE;No;0;L;;;;5;N;;;;; +1010C;AEGEAN NUMBER SIX;No;0;L;;;;6;N;;;;; +1010D;AEGEAN NUMBER SEVEN;No;0;L;;;;7;N;;;;; +1010E;AEGEAN NUMBER EIGHT;No;0;L;;;;8;N;;;;; +1010F;AEGEAN NUMBER NINE;No;0;L;;;;9;N;;;;; +10110;AEGEAN NUMBER TEN;No;0;L;;;;10;N;;;;; +10111;AEGEAN NUMBER TWENTY;No;0;L;;;;20;N;;;;; +10112;AEGEAN NUMBER THIRTY;No;0;L;;;;30;N;;;;; +10113;AEGEAN NUMBER FORTY;No;0;L;;;;40;N;;;;; +10114;AEGEAN NUMBER FIFTY;No;0;L;;;;50;N;;;;; +10115;AEGEAN NUMBER SIXTY;No;0;L;;;;60;N;;;;; +10116;AEGEAN NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +10117;AEGEAN NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +10118;AEGEAN NUMBER NINETY;No;0;L;;;;90;N;;;;; +10119;AEGEAN NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +1011A;AEGEAN NUMBER TWO HUNDRED;No;0;L;;;;200;N;;;;; +1011B;AEGEAN NUMBER THREE HUNDRED;No;0;L;;;;300;N;;;;; +1011C;AEGEAN NUMBER FOUR HUNDRED;No;0;L;;;;400;N;;;;; +1011D;AEGEAN NUMBER FIVE HUNDRED;No;0;L;;;;500;N;;;;; +1011E;AEGEAN NUMBER SIX HUNDRED;No;0;L;;;;600;N;;;;; +1011F;AEGEAN NUMBER SEVEN HUNDRED;No;0;L;;;;700;N;;;;; +10120;AEGEAN NUMBER EIGHT HUNDRED;No;0;L;;;;800;N;;;;; +10121;AEGEAN NUMBER NINE HUNDRED;No;0;L;;;;900;N;;;;; +10122;AEGEAN NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +10123;AEGEAN NUMBER TWO THOUSAND;No;0;L;;;;2000;N;;;;; +10124;AEGEAN NUMBER THREE THOUSAND;No;0;L;;;;3000;N;;;;; +10125;AEGEAN NUMBER FOUR THOUSAND;No;0;L;;;;4000;N;;;;; +10126;AEGEAN NUMBER FIVE THOUSAND;No;0;L;;;;5000;N;;;;; +10127;AEGEAN NUMBER SIX THOUSAND;No;0;L;;;;6000;N;;;;; +10128;AEGEAN NUMBER SEVEN THOUSAND;No;0;L;;;;7000;N;;;;; +10129;AEGEAN NUMBER EIGHT THOUSAND;No;0;L;;;;8000;N;;;;; +1012A;AEGEAN NUMBER NINE THOUSAND;No;0;L;;;;9000;N;;;;; +1012B;AEGEAN NUMBER TEN THOUSAND;No;0;L;;;;10000;N;;;;; +1012C;AEGEAN NUMBER TWENTY THOUSAND;No;0;L;;;;20000;N;;;;; +1012D;AEGEAN NUMBER THIRTY THOUSAND;No;0;L;;;;30000;N;;;;; +1012E;AEGEAN NUMBER FORTY THOUSAND;No;0;L;;;;40000;N;;;;; +1012F;AEGEAN NUMBER FIFTY THOUSAND;No;0;L;;;;50000;N;;;;; +10130;AEGEAN NUMBER SIXTY THOUSAND;No;0;L;;;;60000;N;;;;; +10131;AEGEAN NUMBER SEVENTY THOUSAND;No;0;L;;;;70000;N;;;;; +10132;AEGEAN NUMBER EIGHTY THOUSAND;No;0;L;;;;80000;N;;;;; +10133;AEGEAN NUMBER NINETY THOUSAND;No;0;L;;;;90000;N;;;;; +10137;AEGEAN WEIGHT BASE UNIT;So;0;L;;;;;N;;;;; +10138;AEGEAN WEIGHT FIRST SUBUNIT;So;0;L;;;;;N;;;;; +10139;AEGEAN WEIGHT SECOND SUBUNIT;So;0;L;;;;;N;;;;; +1013A;AEGEAN WEIGHT THIRD SUBUNIT;So;0;L;;;;;N;;;;; +1013B;AEGEAN WEIGHT FOURTH SUBUNIT;So;0;L;;;;;N;;;;; +1013C;AEGEAN DRY MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; +1013D;AEGEAN LIQUID MEASURE FIRST SUBUNIT;So;0;L;;;;;N;;;;; +1013E;AEGEAN MEASURE SECOND SUBUNIT;So;0;L;;;;;N;;;;; +1013F;AEGEAN MEASURE THIRD SUBUNIT;So;0;L;;;;;N;;;;; +10140;GREEK ACROPHONIC ATTIC ONE QUARTER;Nl;0;ON;;;;1/4;N;;;;; +10141;GREEK ACROPHONIC ATTIC ONE HALF;Nl;0;ON;;;;1/2;N;;;;; +10142;GREEK ACROPHONIC ATTIC ONE DRACHMA;Nl;0;ON;;;;1;N;;;;; +10143;GREEK ACROPHONIC ATTIC FIVE;Nl;0;ON;;;;5;N;;;;; +10144;GREEK ACROPHONIC ATTIC FIFTY;Nl;0;ON;;;;50;N;;;;; +10145;GREEK ACROPHONIC ATTIC FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10146;GREEK ACROPHONIC ATTIC FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; +10147;GREEK ACROPHONIC ATTIC FIFTY THOUSAND;Nl;0;ON;;;;50000;N;;;;; +10148;GREEK ACROPHONIC ATTIC FIVE TALENTS;Nl;0;ON;;;;5;N;;;;; +10149;GREEK ACROPHONIC ATTIC TEN TALENTS;Nl;0;ON;;;;10;N;;;;; +1014A;GREEK ACROPHONIC ATTIC FIFTY TALENTS;Nl;0;ON;;;;50;N;;;;; +1014B;GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS;Nl;0;ON;;;;100;N;;;;; +1014C;GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS;Nl;0;ON;;;;500;N;;;;; +1014D;GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS;Nl;0;ON;;;;1000;N;;;;; +1014E;GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS;Nl;0;ON;;;;5000;N;;;;; +1014F;GREEK ACROPHONIC ATTIC FIVE STATERS;Nl;0;ON;;;;5;N;;;;; +10150;GREEK ACROPHONIC ATTIC TEN STATERS;Nl;0;ON;;;;10;N;;;;; +10151;GREEK ACROPHONIC ATTIC FIFTY STATERS;Nl;0;ON;;;;50;N;;;;; +10152;GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS;Nl;0;ON;;;;100;N;;;;; +10153;GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS;Nl;0;ON;;;;500;N;;;;; +10154;GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS;Nl;0;ON;;;;1000;N;;;;; +10155;GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS;Nl;0;ON;;;;10000;N;;;;; +10156;GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS;Nl;0;ON;;;;50000;N;;;;; +10157;GREEK ACROPHONIC ATTIC TEN MNAS;Nl;0;ON;;;;10;N;;;;; +10158;GREEK ACROPHONIC HERAEUM ONE PLETHRON;Nl;0;ON;;;;1;N;;;;; +10159;GREEK ACROPHONIC THESPIAN ONE;Nl;0;ON;;;;1;N;;;;; +1015A;GREEK ACROPHONIC HERMIONIAN ONE;Nl;0;ON;;;;1;N;;;;; +1015B;GREEK ACROPHONIC EPIDAUREAN TWO;Nl;0;ON;;;;2;N;;;;; +1015C;GREEK ACROPHONIC THESPIAN TWO;Nl;0;ON;;;;2;N;;;;; +1015D;GREEK ACROPHONIC CYRENAIC TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; +1015E;GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS;Nl;0;ON;;;;2;N;;;;; +1015F;GREEK ACROPHONIC TROEZENIAN FIVE;Nl;0;ON;;;;5;N;;;;; +10160;GREEK ACROPHONIC TROEZENIAN TEN;Nl;0;ON;;;;10;N;;;;; +10161;GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM;Nl;0;ON;;;;10;N;;;;; +10162;GREEK ACROPHONIC HERMIONIAN TEN;Nl;0;ON;;;;10;N;;;;; +10163;GREEK ACROPHONIC MESSENIAN TEN;Nl;0;ON;;;;10;N;;;;; +10164;GREEK ACROPHONIC THESPIAN TEN;Nl;0;ON;;;;10;N;;;;; +10165;GREEK ACROPHONIC THESPIAN THIRTY;Nl;0;ON;;;;30;N;;;;; +10166;GREEK ACROPHONIC TROEZENIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +10167;GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM;Nl;0;ON;;;;50;N;;;;; +10168;GREEK ACROPHONIC HERMIONIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +10169;GREEK ACROPHONIC THESPIAN FIFTY;Nl;0;ON;;;;50;N;;;;; +1016A;GREEK ACROPHONIC THESPIAN ONE HUNDRED;Nl;0;ON;;;;100;N;;;;; +1016B;GREEK ACROPHONIC THESPIAN THREE HUNDRED;Nl;0;ON;;;;300;N;;;;; +1016C;GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016D;GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016E;GREEK ACROPHONIC THESPIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +1016F;GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10170;GREEK ACROPHONIC NAXIAN FIVE HUNDRED;Nl;0;ON;;;;500;N;;;;; +10171;GREEK ACROPHONIC THESPIAN ONE THOUSAND;Nl;0;ON;;;;1000;N;;;;; +10172;GREEK ACROPHONIC THESPIAN FIVE THOUSAND;Nl;0;ON;;;;5000;N;;;;; +10173;GREEK ACROPHONIC DELPHIC FIVE MNAS;Nl;0;ON;;;;5;N;;;;; +10174;GREEK ACROPHONIC STRATIAN FIFTY MNAS;Nl;0;ON;;;;50;N;;;;; +10175;GREEK ONE HALF SIGN;No;0;ON;;;;1/2;N;;;;; +10176;GREEK ONE HALF SIGN ALTERNATE FORM;No;0;ON;;;;1/2;N;;;;; +10177;GREEK TWO THIRDS SIGN;No;0;ON;;;;2/3;N;;;;; +10178;GREEK THREE QUARTERS SIGN;No;0;ON;;;;3/4;N;;;;; +10179;GREEK YEAR SIGN;So;0;ON;;;;;N;;;;; +1017A;GREEK TALENT SIGN;So;0;ON;;;;;N;;;;; +1017B;GREEK DRACHMA SIGN;So;0;ON;;;;;N;;;;; +1017C;GREEK OBOL SIGN;So;0;ON;;;;;N;;;;; +1017D;GREEK TWO OBOLS SIGN;So;0;ON;;;;;N;;;;; +1017E;GREEK THREE OBOLS SIGN;So;0;ON;;;;;N;;;;; +1017F;GREEK FOUR OBOLS SIGN;So;0;ON;;;;;N;;;;; +10180;GREEK FIVE OBOLS SIGN;So;0;ON;;;;;N;;;;; +10181;GREEK METRETES SIGN;So;0;ON;;;;;N;;;;; +10182;GREEK KYATHOS BASE SIGN;So;0;ON;;;;;N;;;;; +10183;GREEK LITRA SIGN;So;0;ON;;;;;N;;;;; +10184;GREEK OUNKIA SIGN;So;0;ON;;;;;N;;;;; +10185;GREEK XESTES SIGN;So;0;ON;;;;;N;;;;; +10186;GREEK ARTABE SIGN;So;0;ON;;;;;N;;;;; +10187;GREEK AROURA SIGN;So;0;ON;;;;;N;;;;; +10188;GREEK GRAMMA SIGN;So;0;ON;;;;;N;;;;; +10189;GREEK TRYBLION BASE SIGN;So;0;ON;;;;;N;;;;; +1018A;GREEK ZERO SIGN;No;0;ON;;;;0;N;;;;; +1018B;GREEK ONE QUARTER SIGN;No;0;ON;;;;1/4;N;;;;; +1018C;GREEK SINUSOID SIGN;So;0;ON;;;;;N;;;;; +1018D;GREEK INDICTION SIGN;So;0;L;;;;;N;;;;; +1018E;NOMISMA SIGN;So;0;L;;;;;N;;;;; +10190;ROMAN SEXTANS SIGN;So;0;ON;;;;;N;;;;; +10191;ROMAN UNCIA SIGN;So;0;ON;;;;;N;;;;; +10192;ROMAN SEMUNCIA SIGN;So;0;ON;;;;;N;;;;; +10193;ROMAN SEXTULA SIGN;So;0;ON;;;;;N;;;;; +10194;ROMAN DIMIDIA SEXTULA SIGN;So;0;ON;;;;;N;;;;; +10195;ROMAN SILIQUA SIGN;So;0;ON;;;;;N;;;;; +10196;ROMAN DENARIUS SIGN;So;0;ON;;;;;N;;;;; +10197;ROMAN QUINARIUS SIGN;So;0;ON;;;;;N;;;;; +10198;ROMAN SESTERTIUS SIGN;So;0;ON;;;;;N;;;;; +10199;ROMAN DUPONDIUS SIGN;So;0;ON;;;;;N;;;;; +1019A;ROMAN AS SIGN;So;0;ON;;;;;N;;;;; +1019B;ROMAN CENTURIAL SIGN;So;0;ON;;;;;N;;;;; +1019C;ASCIA SYMBOL;So;0;ON;;;;;N;;;;; +101A0;GREEK SYMBOL TAU RHO;So;0;ON;;;;;N;;;;; +101D0;PHAISTOS DISC SIGN PEDESTRIAN;So;0;L;;;;;N;;;;; +101D1;PHAISTOS DISC SIGN PLUMED HEAD;So;0;L;;;;;N;;;;; +101D2;PHAISTOS DISC SIGN TATTOOED HEAD;So;0;L;;;;;N;;;;; +101D3;PHAISTOS DISC SIGN CAPTIVE;So;0;L;;;;;N;;;;; +101D4;PHAISTOS DISC SIGN CHILD;So;0;L;;;;;N;;;;; +101D5;PHAISTOS DISC SIGN WOMAN;So;0;L;;;;;N;;;;; +101D6;PHAISTOS DISC SIGN HELMET;So;0;L;;;;;N;;;;; +101D7;PHAISTOS DISC SIGN GAUNTLET;So;0;L;;;;;N;;;;; +101D8;PHAISTOS DISC SIGN TIARA;So;0;L;;;;;N;;;;; +101D9;PHAISTOS DISC SIGN ARROW;So;0;L;;;;;N;;;;; +101DA;PHAISTOS DISC SIGN BOW;So;0;L;;;;;N;;;;; +101DB;PHAISTOS DISC SIGN SHIELD;So;0;L;;;;;N;;;;; +101DC;PHAISTOS DISC SIGN CLUB;So;0;L;;;;;N;;;;; +101DD;PHAISTOS DISC SIGN MANACLES;So;0;L;;;;;N;;;;; +101DE;PHAISTOS DISC SIGN MATTOCK;So;0;L;;;;;N;;;;; +101DF;PHAISTOS DISC SIGN SAW;So;0;L;;;;;N;;;;; +101E0;PHAISTOS DISC SIGN LID;So;0;L;;;;;N;;;;; +101E1;PHAISTOS DISC SIGN BOOMERANG;So;0;L;;;;;N;;;;; +101E2;PHAISTOS DISC SIGN CARPENTRY PLANE;So;0;L;;;;;N;;;;; +101E3;PHAISTOS DISC SIGN DOLIUM;So;0;L;;;;;N;;;;; +101E4;PHAISTOS DISC SIGN COMB;So;0;L;;;;;N;;;;; +101E5;PHAISTOS DISC SIGN SLING;So;0;L;;;;;N;;;;; +101E6;PHAISTOS DISC SIGN COLUMN;So;0;L;;;;;N;;;;; +101E7;PHAISTOS DISC SIGN BEEHIVE;So;0;L;;;;;N;;;;; +101E8;PHAISTOS DISC SIGN SHIP;So;0;L;;;;;N;;;;; +101E9;PHAISTOS DISC SIGN HORN;So;0;L;;;;;N;;;;; +101EA;PHAISTOS DISC SIGN HIDE;So;0;L;;;;;N;;;;; +101EB;PHAISTOS DISC SIGN BULLS LEG;So;0;L;;;;;N;;;;; +101EC;PHAISTOS DISC SIGN CAT;So;0;L;;;;;N;;;;; +101ED;PHAISTOS DISC SIGN RAM;So;0;L;;;;;N;;;;; +101EE;PHAISTOS DISC SIGN EAGLE;So;0;L;;;;;N;;;;; +101EF;PHAISTOS DISC SIGN DOVE;So;0;L;;;;;N;;;;; +101F0;PHAISTOS DISC SIGN TUNNY;So;0;L;;;;;N;;;;; +101F1;PHAISTOS DISC SIGN BEE;So;0;L;;;;;N;;;;; +101F2;PHAISTOS DISC SIGN PLANE TREE;So;0;L;;;;;N;;;;; +101F3;PHAISTOS DISC SIGN VINE;So;0;L;;;;;N;;;;; +101F4;PHAISTOS DISC SIGN PAPYRUS;So;0;L;;;;;N;;;;; +101F5;PHAISTOS DISC SIGN ROSETTE;So;0;L;;;;;N;;;;; +101F6;PHAISTOS DISC SIGN LILY;So;0;L;;;;;N;;;;; +101F7;PHAISTOS DISC SIGN OX BACK;So;0;L;;;;;N;;;;; +101F8;PHAISTOS DISC SIGN FLUTE;So;0;L;;;;;N;;;;; +101F9;PHAISTOS DISC SIGN GRATER;So;0;L;;;;;N;;;;; +101FA;PHAISTOS DISC SIGN STRAINER;So;0;L;;;;;N;;;;; +101FB;PHAISTOS DISC SIGN SMALL AXE;So;0;L;;;;;N;;;;; +101FC;PHAISTOS DISC SIGN WAVY BAND;So;0;L;;;;;N;;;;; +101FD;PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE;Mn;220;NSM;;;;;N;;;;; +10280;LYCIAN LETTER A;Lo;0;L;;;;;N;;;;; +10281;LYCIAN LETTER E;Lo;0;L;;;;;N;;;;; +10282;LYCIAN LETTER B;Lo;0;L;;;;;N;;;;; +10283;LYCIAN LETTER BH;Lo;0;L;;;;;N;;;;; +10284;LYCIAN LETTER G;Lo;0;L;;;;;N;;;;; +10285;LYCIAN LETTER D;Lo;0;L;;;;;N;;;;; +10286;LYCIAN LETTER I;Lo;0;L;;;;;N;;;;; +10287;LYCIAN LETTER W;Lo;0;L;;;;;N;;;;; +10288;LYCIAN LETTER Z;Lo;0;L;;;;;N;;;;; +10289;LYCIAN LETTER TH;Lo;0;L;;;;;N;;;;; +1028A;LYCIAN LETTER J;Lo;0;L;;;;;N;;;;; +1028B;LYCIAN LETTER K;Lo;0;L;;;;;N;;;;; +1028C;LYCIAN LETTER Q;Lo;0;L;;;;;N;;;;; +1028D;LYCIAN LETTER L;Lo;0;L;;;;;N;;;;; +1028E;LYCIAN LETTER M;Lo;0;L;;;;;N;;;;; +1028F;LYCIAN LETTER N;Lo;0;L;;;;;N;;;;; +10290;LYCIAN LETTER MM;Lo;0;L;;;;;N;;;;; +10291;LYCIAN LETTER NN;Lo;0;L;;;;;N;;;;; +10292;LYCIAN LETTER U;Lo;0;L;;;;;N;;;;; +10293;LYCIAN LETTER P;Lo;0;L;;;;;N;;;;; +10294;LYCIAN LETTER KK;Lo;0;L;;;;;N;;;;; +10295;LYCIAN LETTER R;Lo;0;L;;;;;N;;;;; +10296;LYCIAN LETTER S;Lo;0;L;;;;;N;;;;; +10297;LYCIAN LETTER T;Lo;0;L;;;;;N;;;;; +10298;LYCIAN LETTER TT;Lo;0;L;;;;;N;;;;; +10299;LYCIAN LETTER AN;Lo;0;L;;;;;N;;;;; +1029A;LYCIAN LETTER EN;Lo;0;L;;;;;N;;;;; +1029B;LYCIAN LETTER H;Lo;0;L;;;;;N;;;;; +1029C;LYCIAN LETTER X;Lo;0;L;;;;;N;;;;; +102A0;CARIAN LETTER A;Lo;0;L;;;;;N;;;;; +102A1;CARIAN LETTER P2;Lo;0;L;;;;;N;;;;; +102A2;CARIAN LETTER D;Lo;0;L;;;;;N;;;;; +102A3;CARIAN LETTER L;Lo;0;L;;;;;N;;;;; +102A4;CARIAN LETTER UUU;Lo;0;L;;;;;N;;;;; +102A5;CARIAN LETTER R;Lo;0;L;;;;;N;;;;; +102A6;CARIAN LETTER LD;Lo;0;L;;;;;N;;;;; +102A7;CARIAN LETTER A2;Lo;0;L;;;;;N;;;;; +102A8;CARIAN LETTER Q;Lo;0;L;;;;;N;;;;; +102A9;CARIAN LETTER B;Lo;0;L;;;;;N;;;;; +102AA;CARIAN LETTER M;Lo;0;L;;;;;N;;;;; +102AB;CARIAN LETTER O;Lo;0;L;;;;;N;;;;; +102AC;CARIAN LETTER D2;Lo;0;L;;;;;N;;;;; +102AD;CARIAN LETTER T;Lo;0;L;;;;;N;;;;; +102AE;CARIAN LETTER SH;Lo;0;L;;;;;N;;;;; +102AF;CARIAN LETTER SH2;Lo;0;L;;;;;N;;;;; +102B0;CARIAN LETTER S;Lo;0;L;;;;;N;;;;; +102B1;CARIAN LETTER C-18;Lo;0;L;;;;;N;;;;; +102B2;CARIAN LETTER U;Lo;0;L;;;;;N;;;;; +102B3;CARIAN LETTER NN;Lo;0;L;;;;;N;;;;; +102B4;CARIAN LETTER X;Lo;0;L;;;;;N;;;;; +102B5;CARIAN LETTER N;Lo;0;L;;;;;N;;;;; +102B6;CARIAN LETTER TT2;Lo;0;L;;;;;N;;;;; +102B7;CARIAN LETTER P;Lo;0;L;;;;;N;;;;; +102B8;CARIAN LETTER SS;Lo;0;L;;;;;N;;;;; +102B9;CARIAN LETTER I;Lo;0;L;;;;;N;;;;; +102BA;CARIAN LETTER E;Lo;0;L;;;;;N;;;;; +102BB;CARIAN LETTER UUUU;Lo;0;L;;;;;N;;;;; +102BC;CARIAN LETTER K;Lo;0;L;;;;;N;;;;; +102BD;CARIAN LETTER K2;Lo;0;L;;;;;N;;;;; +102BE;CARIAN LETTER ND;Lo;0;L;;;;;N;;;;; +102BF;CARIAN LETTER UU;Lo;0;L;;;;;N;;;;; +102C0;CARIAN LETTER G;Lo;0;L;;;;;N;;;;; +102C1;CARIAN LETTER G2;Lo;0;L;;;;;N;;;;; +102C2;CARIAN LETTER ST;Lo;0;L;;;;;N;;;;; +102C3;CARIAN LETTER ST2;Lo;0;L;;;;;N;;;;; +102C4;CARIAN LETTER NG;Lo;0;L;;;;;N;;;;; +102C5;CARIAN LETTER II;Lo;0;L;;;;;N;;;;; +102C6;CARIAN LETTER C-39;Lo;0;L;;;;;N;;;;; +102C7;CARIAN LETTER TT;Lo;0;L;;;;;N;;;;; +102C8;CARIAN LETTER UUU2;Lo;0;L;;;;;N;;;;; +102C9;CARIAN LETTER RR;Lo;0;L;;;;;N;;;;; +102CA;CARIAN LETTER MB;Lo;0;L;;;;;N;;;;; +102CB;CARIAN LETTER MB2;Lo;0;L;;;;;N;;;;; +102CC;CARIAN LETTER MB3;Lo;0;L;;;;;N;;;;; +102CD;CARIAN LETTER MB4;Lo;0;L;;;;;N;;;;; +102CE;CARIAN LETTER LD2;Lo;0;L;;;;;N;;;;; +102CF;CARIAN LETTER E2;Lo;0;L;;;;;N;;;;; +102D0;CARIAN LETTER UUU3;Lo;0;L;;;;;N;;;;; +102E0;COPTIC EPACT THOUSANDS MARK;Mn;220;NSM;;;;;N;;;;; +102E1;COPTIC EPACT DIGIT ONE;No;0;EN;;;;1;N;;;;; +102E2;COPTIC EPACT DIGIT TWO;No;0;EN;;;;2;N;;;;; +102E3;COPTIC EPACT DIGIT THREE;No;0;EN;;;;3;N;;;;; +102E4;COPTIC EPACT DIGIT FOUR;No;0;EN;;;;4;N;;;;; +102E5;COPTIC EPACT DIGIT FIVE;No;0;EN;;;;5;N;;;;; +102E6;COPTIC EPACT DIGIT SIX;No;0;EN;;;;6;N;;;;; +102E7;COPTIC EPACT DIGIT SEVEN;No;0;EN;;;;7;N;;;;; +102E8;COPTIC EPACT DIGIT EIGHT;No;0;EN;;;;8;N;;;;; +102E9;COPTIC EPACT DIGIT NINE;No;0;EN;;;;9;N;;;;; +102EA;COPTIC EPACT NUMBER TEN;No;0;EN;;;;10;N;;;;; +102EB;COPTIC EPACT NUMBER TWENTY;No;0;EN;;;;20;N;;;;; +102EC;COPTIC EPACT NUMBER THIRTY;No;0;EN;;;;30;N;;;;; +102ED;COPTIC EPACT NUMBER FORTY;No;0;EN;;;;40;N;;;;; +102EE;COPTIC EPACT NUMBER FIFTY;No;0;EN;;;;50;N;;;;; +102EF;COPTIC EPACT NUMBER SIXTY;No;0;EN;;;;60;N;;;;; +102F0;COPTIC EPACT NUMBER SEVENTY;No;0;EN;;;;70;N;;;;; +102F1;COPTIC EPACT NUMBER EIGHTY;No;0;EN;;;;80;N;;;;; +102F2;COPTIC EPACT NUMBER NINETY;No;0;EN;;;;90;N;;;;; +102F3;COPTIC EPACT NUMBER ONE HUNDRED;No;0;EN;;;;100;N;;;;; +102F4;COPTIC EPACT NUMBER TWO HUNDRED;No;0;EN;;;;200;N;;;;; +102F5;COPTIC EPACT NUMBER THREE HUNDRED;No;0;EN;;;;300;N;;;;; +102F6;COPTIC EPACT NUMBER FOUR HUNDRED;No;0;EN;;;;400;N;;;;; +102F7;COPTIC EPACT NUMBER FIVE HUNDRED;No;0;EN;;;;500;N;;;;; +102F8;COPTIC EPACT NUMBER SIX HUNDRED;No;0;EN;;;;600;N;;;;; +102F9;COPTIC EPACT NUMBER SEVEN HUNDRED;No;0;EN;;;;700;N;;;;; +102FA;COPTIC EPACT NUMBER EIGHT HUNDRED;No;0;EN;;;;800;N;;;;; +102FB;COPTIC EPACT NUMBER NINE HUNDRED;No;0;EN;;;;900;N;;;;; +10300;OLD ITALIC LETTER A;Lo;0;L;;;;;N;;;;; +10301;OLD ITALIC LETTER BE;Lo;0;L;;;;;N;;;;; +10302;OLD ITALIC LETTER KE;Lo;0;L;;;;;N;;;;; +10303;OLD ITALIC LETTER DE;Lo;0;L;;;;;N;;;;; +10304;OLD ITALIC LETTER E;Lo;0;L;;;;;N;;;;; +10305;OLD ITALIC LETTER VE;Lo;0;L;;;;;N;;;;; +10306;OLD ITALIC LETTER ZE;Lo;0;L;;;;;N;;;;; +10307;OLD ITALIC LETTER HE;Lo;0;L;;;;;N;;;;; +10308;OLD ITALIC LETTER THE;Lo;0;L;;;;;N;;;;; +10309;OLD ITALIC LETTER I;Lo;0;L;;;;;N;;;;; +1030A;OLD ITALIC LETTER KA;Lo;0;L;;;;;N;;;;; +1030B;OLD ITALIC LETTER EL;Lo;0;L;;;;;N;;;;; +1030C;OLD ITALIC LETTER EM;Lo;0;L;;;;;N;;;;; +1030D;OLD ITALIC LETTER EN;Lo;0;L;;;;;N;;;;; +1030E;OLD ITALIC LETTER ESH;Lo;0;L;;;;;N;;;;; +1030F;OLD ITALIC LETTER O;Lo;0;L;;;;;N;;;;; +10310;OLD ITALIC LETTER PE;Lo;0;L;;;;;N;;;;; +10311;OLD ITALIC LETTER SHE;Lo;0;L;;;;;N;;;;; +10312;OLD ITALIC LETTER KU;Lo;0;L;;;;;N;;;;; +10313;OLD ITALIC LETTER ER;Lo;0;L;;;;;N;;;;; +10314;OLD ITALIC LETTER ES;Lo;0;L;;;;;N;;;;; +10315;OLD ITALIC LETTER TE;Lo;0;L;;;;;N;;;;; +10316;OLD ITALIC LETTER U;Lo;0;L;;;;;N;;;;; +10317;OLD ITALIC LETTER EKS;Lo;0;L;;;;;N;;;;; +10318;OLD ITALIC LETTER PHE;Lo;0;L;;;;;N;;;;; +10319;OLD ITALIC LETTER KHE;Lo;0;L;;;;;N;;;;; +1031A;OLD ITALIC LETTER EF;Lo;0;L;;;;;N;;;;; +1031B;OLD ITALIC LETTER ERS;Lo;0;L;;;;;N;;;;; +1031C;OLD ITALIC LETTER CHE;Lo;0;L;;;;;N;;;;; +1031D;OLD ITALIC LETTER II;Lo;0;L;;;;;N;;;;; +1031E;OLD ITALIC LETTER UU;Lo;0;L;;;;;N;;;;; +1031F;OLD ITALIC LETTER ESS;Lo;0;L;;;;;N;;;;; +10320;OLD ITALIC NUMERAL ONE;No;0;L;;;;1;N;;;;; +10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;; +10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;; +10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;; +1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;; +1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;; +1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;; +10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;; +10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;; +10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;; +10333;GOTHIC LETTER DAGS;Lo;0;L;;;;;N;;;;; +10334;GOTHIC LETTER AIHVUS;Lo;0;L;;;;;N;;;;; +10335;GOTHIC LETTER QAIRTHRA;Lo;0;L;;;;;N;;;;; +10336;GOTHIC LETTER IUJA;Lo;0;L;;;;;N;;;;; +10337;GOTHIC LETTER HAGL;Lo;0;L;;;;;N;;;;; +10338;GOTHIC LETTER THIUTH;Lo;0;L;;;;;N;;;;; +10339;GOTHIC LETTER EIS;Lo;0;L;;;;;N;;;;; +1033A;GOTHIC LETTER KUSMA;Lo;0;L;;;;;N;;;;; +1033B;GOTHIC LETTER LAGUS;Lo;0;L;;;;;N;;;;; +1033C;GOTHIC LETTER MANNA;Lo;0;L;;;;;N;;;;; +1033D;GOTHIC LETTER NAUTHS;Lo;0;L;;;;;N;;;;; +1033E;GOTHIC LETTER JER;Lo;0;L;;;;;N;;;;; +1033F;GOTHIC LETTER URUS;Lo;0;L;;;;;N;;;;; +10340;GOTHIC LETTER PAIRTHRA;Lo;0;L;;;;;N;;;;; +10341;GOTHIC LETTER NINETY;Nl;0;L;;;;90;N;;;;; +10342;GOTHIC LETTER RAIDA;Lo;0;L;;;;;N;;;;; +10343;GOTHIC LETTER SAUIL;Lo;0;L;;;;;N;;;;; +10344;GOTHIC LETTER TEIWS;Lo;0;L;;;;;N;;;;; +10345;GOTHIC LETTER WINJA;Lo;0;L;;;;;N;;;;; +10346;GOTHIC LETTER FAIHU;Lo;0;L;;;;;N;;;;; +10347;GOTHIC LETTER IGGWS;Lo;0;L;;;;;N;;;;; +10348;GOTHIC LETTER HWAIR;Lo;0;L;;;;;N;;;;; +10349;GOTHIC LETTER OTHAL;Lo;0;L;;;;;N;;;;; +1034A;GOTHIC LETTER NINE HUNDRED;Nl;0;L;;;;900;N;;;;; +10350;OLD PERMIC LETTER AN;Lo;0;L;;;;;N;;;;; +10351;OLD PERMIC LETTER BUR;Lo;0;L;;;;;N;;;;; +10352;OLD PERMIC LETTER GAI;Lo;0;L;;;;;N;;;;; +10353;OLD PERMIC LETTER DOI;Lo;0;L;;;;;N;;;;; +10354;OLD PERMIC LETTER E;Lo;0;L;;;;;N;;;;; +10355;OLD PERMIC LETTER ZHOI;Lo;0;L;;;;;N;;;;; +10356;OLD PERMIC LETTER DZHOI;Lo;0;L;;;;;N;;;;; +10357;OLD PERMIC LETTER ZATA;Lo;0;L;;;;;N;;;;; +10358;OLD PERMIC LETTER DZITA;Lo;0;L;;;;;N;;;;; +10359;OLD PERMIC LETTER I;Lo;0;L;;;;;N;;;;; +1035A;OLD PERMIC LETTER KOKE;Lo;0;L;;;;;N;;;;; +1035B;OLD PERMIC LETTER LEI;Lo;0;L;;;;;N;;;;; +1035C;OLD PERMIC LETTER MENOE;Lo;0;L;;;;;N;;;;; +1035D;OLD PERMIC LETTER NENOE;Lo;0;L;;;;;N;;;;; +1035E;OLD PERMIC LETTER VOOI;Lo;0;L;;;;;N;;;;; +1035F;OLD PERMIC LETTER PEEI;Lo;0;L;;;;;N;;;;; +10360;OLD PERMIC LETTER REI;Lo;0;L;;;;;N;;;;; +10361;OLD PERMIC LETTER SII;Lo;0;L;;;;;N;;;;; +10362;OLD PERMIC LETTER TAI;Lo;0;L;;;;;N;;;;; +10363;OLD PERMIC LETTER U;Lo;0;L;;;;;N;;;;; +10364;OLD PERMIC LETTER CHERY;Lo;0;L;;;;;N;;;;; +10365;OLD PERMIC LETTER SHOOI;Lo;0;L;;;;;N;;;;; +10366;OLD PERMIC LETTER SHCHOOI;Lo;0;L;;;;;N;;;;; +10367;OLD PERMIC LETTER YRY;Lo;0;L;;;;;N;;;;; +10368;OLD PERMIC LETTER YERU;Lo;0;L;;;;;N;;;;; +10369;OLD PERMIC LETTER O;Lo;0;L;;;;;N;;;;; +1036A;OLD PERMIC LETTER OO;Lo;0;L;;;;;N;;;;; +1036B;OLD PERMIC LETTER EF;Lo;0;L;;;;;N;;;;; +1036C;OLD PERMIC LETTER HA;Lo;0;L;;;;;N;;;;; +1036D;OLD PERMIC LETTER TSIU;Lo;0;L;;;;;N;;;;; +1036E;OLD PERMIC LETTER VER;Lo;0;L;;;;;N;;;;; +1036F;OLD PERMIC LETTER YER;Lo;0;L;;;;;N;;;;; +10370;OLD PERMIC LETTER YERI;Lo;0;L;;;;;N;;;;; +10371;OLD PERMIC LETTER YAT;Lo;0;L;;;;;N;;;;; +10372;OLD PERMIC LETTER IE;Lo;0;L;;;;;N;;;;; +10373;OLD PERMIC LETTER YU;Lo;0;L;;;;;N;;;;; +10374;OLD PERMIC LETTER YA;Lo;0;L;;;;;N;;;;; +10375;OLD PERMIC LETTER IA;Lo;0;L;;;;;N;;;;; +10376;COMBINING OLD PERMIC LETTER AN;Mn;230;NSM;;;;;N;;;;; +10377;COMBINING OLD PERMIC LETTER DOI;Mn;230;NSM;;;;;N;;;;; +10378;COMBINING OLD PERMIC LETTER ZATA;Mn;230;NSM;;;;;N;;;;; +10379;COMBINING OLD PERMIC LETTER NENOE;Mn;230;NSM;;;;;N;;;;; +1037A;COMBINING OLD PERMIC LETTER SII;Mn;230;NSM;;;;;N;;;;; +10380;UGARITIC LETTER ALPA;Lo;0;L;;;;;N;;;;; +10381;UGARITIC LETTER BETA;Lo;0;L;;;;;N;;;;; +10382;UGARITIC LETTER GAMLA;Lo;0;L;;;;;N;;;;; +10383;UGARITIC LETTER KHA;Lo;0;L;;;;;N;;;;; +10384;UGARITIC LETTER DELTA;Lo;0;L;;;;;N;;;;; +10385;UGARITIC LETTER HO;Lo;0;L;;;;;N;;;;; +10386;UGARITIC LETTER WO;Lo;0;L;;;;;N;;;;; +10387;UGARITIC LETTER ZETA;Lo;0;L;;;;;N;;;;; +10388;UGARITIC LETTER HOTA;Lo;0;L;;;;;N;;;;; +10389;UGARITIC LETTER TET;Lo;0;L;;;;;N;;;;; +1038A;UGARITIC LETTER YOD;Lo;0;L;;;;;N;;;;; +1038B;UGARITIC LETTER KAF;Lo;0;L;;;;;N;;;;; +1038C;UGARITIC LETTER SHIN;Lo;0;L;;;;;N;;;;; +1038D;UGARITIC LETTER LAMDA;Lo;0;L;;;;;N;;;;; +1038E;UGARITIC LETTER MEM;Lo;0;L;;;;;N;;;;; +1038F;UGARITIC LETTER DHAL;Lo;0;L;;;;;N;;;;; +10390;UGARITIC LETTER NUN;Lo;0;L;;;;;N;;;;; +10391;UGARITIC LETTER ZU;Lo;0;L;;;;;N;;;;; +10392;UGARITIC LETTER SAMKA;Lo;0;L;;;;;N;;;;; +10393;UGARITIC LETTER AIN;Lo;0;L;;;;;N;;;;; +10394;UGARITIC LETTER PU;Lo;0;L;;;;;N;;;;; +10395;UGARITIC LETTER SADE;Lo;0;L;;;;;N;;;;; +10396;UGARITIC LETTER QOPA;Lo;0;L;;;;;N;;;;; +10397;UGARITIC LETTER RASHA;Lo;0;L;;;;;N;;;;; +10398;UGARITIC LETTER THANNA;Lo;0;L;;;;;N;;;;; +10399;UGARITIC LETTER GHAIN;Lo;0;L;;;;;N;;;;; +1039A;UGARITIC LETTER TO;Lo;0;L;;;;;N;;;;; +1039B;UGARITIC LETTER I;Lo;0;L;;;;;N;;;;; +1039C;UGARITIC LETTER U;Lo;0;L;;;;;N;;;;; +1039D;UGARITIC LETTER SSU;Lo;0;L;;;;;N;;;;; +1039F;UGARITIC WORD DIVIDER;Po;0;L;;;;;N;;;;; +103A0;OLD PERSIAN SIGN A;Lo;0;L;;;;;N;;;;; +103A1;OLD PERSIAN SIGN I;Lo;0;L;;;;;N;;;;; +103A2;OLD PERSIAN SIGN U;Lo;0;L;;;;;N;;;;; +103A3;OLD PERSIAN SIGN KA;Lo;0;L;;;;;N;;;;; +103A4;OLD PERSIAN SIGN KU;Lo;0;L;;;;;N;;;;; +103A5;OLD PERSIAN SIGN GA;Lo;0;L;;;;;N;;;;; +103A6;OLD PERSIAN SIGN GU;Lo;0;L;;;;;N;;;;; +103A7;OLD PERSIAN SIGN XA;Lo;0;L;;;;;N;;;;; +103A8;OLD PERSIAN SIGN CA;Lo;0;L;;;;;N;;;;; +103A9;OLD PERSIAN SIGN JA;Lo;0;L;;;;;N;;;;; +103AA;OLD PERSIAN SIGN JI;Lo;0;L;;;;;N;;;;; +103AB;OLD PERSIAN SIGN TA;Lo;0;L;;;;;N;;;;; +103AC;OLD PERSIAN SIGN TU;Lo;0;L;;;;;N;;;;; +103AD;OLD PERSIAN SIGN DA;Lo;0;L;;;;;N;;;;; +103AE;OLD PERSIAN SIGN DI;Lo;0;L;;;;;N;;;;; +103AF;OLD PERSIAN SIGN DU;Lo;0;L;;;;;N;;;;; +103B0;OLD PERSIAN SIGN THA;Lo;0;L;;;;;N;;;;; +103B1;OLD PERSIAN SIGN PA;Lo;0;L;;;;;N;;;;; +103B2;OLD PERSIAN SIGN BA;Lo;0;L;;;;;N;;;;; +103B3;OLD PERSIAN SIGN FA;Lo;0;L;;;;;N;;;;; +103B4;OLD PERSIAN SIGN NA;Lo;0;L;;;;;N;;;;; +103B5;OLD PERSIAN SIGN NU;Lo;0;L;;;;;N;;;;; +103B6;OLD PERSIAN SIGN MA;Lo;0;L;;;;;N;;;;; +103B7;OLD PERSIAN SIGN MI;Lo;0;L;;;;;N;;;;; +103B8;OLD PERSIAN SIGN MU;Lo;0;L;;;;;N;;;;; +103B9;OLD PERSIAN SIGN YA;Lo;0;L;;;;;N;;;;; +103BA;OLD PERSIAN SIGN VA;Lo;0;L;;;;;N;;;;; +103BB;OLD PERSIAN SIGN VI;Lo;0;L;;;;;N;;;;; +103BC;OLD PERSIAN SIGN RA;Lo;0;L;;;;;N;;;;; +103BD;OLD PERSIAN SIGN RU;Lo;0;L;;;;;N;;;;; +103BE;OLD PERSIAN SIGN LA;Lo;0;L;;;;;N;;;;; +103BF;OLD PERSIAN SIGN SA;Lo;0;L;;;;;N;;;;; +103C0;OLD PERSIAN SIGN ZA;Lo;0;L;;;;;N;;;;; +103C1;OLD PERSIAN SIGN SHA;Lo;0;L;;;;;N;;;;; +103C2;OLD PERSIAN SIGN SSA;Lo;0;L;;;;;N;;;;; +103C3;OLD PERSIAN SIGN HA;Lo;0;L;;;;;N;;;;; +103C8;OLD PERSIAN SIGN AURAMAZDAA;Lo;0;L;;;;;N;;;;; +103C9;OLD PERSIAN SIGN AURAMAZDAA-2;Lo;0;L;;;;;N;;;;; +103CA;OLD PERSIAN SIGN AURAMAZDAAHA;Lo;0;L;;;;;N;;;;; +103CB;OLD PERSIAN SIGN XSHAAYATHIYA;Lo;0;L;;;;;N;;;;; +103CC;OLD PERSIAN SIGN DAHYAAUSH;Lo;0;L;;;;;N;;;;; +103CD;OLD PERSIAN SIGN DAHYAAUSH-2;Lo;0;L;;;;;N;;;;; +103CE;OLD PERSIAN SIGN BAGA;Lo;0;L;;;;;N;;;;; +103CF;OLD PERSIAN SIGN BUUMISH;Lo;0;L;;;;;N;;;;; +103D0;OLD PERSIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; +103D1;OLD PERSIAN NUMBER ONE;Nl;0;L;;;;1;N;;;;; +103D2;OLD PERSIAN NUMBER TWO;Nl;0;L;;;;2;N;;;;; +103D3;OLD PERSIAN NUMBER TEN;Nl;0;L;;;;10;N;;;;; +103D4;OLD PERSIAN NUMBER TWENTY;Nl;0;L;;;;20;N;;;;; +103D5;OLD PERSIAN NUMBER HUNDRED;Nl;0;L;;;;100;N;;;;; +10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; +10401;DESERET CAPITAL LETTER LONG E;Lu;0;L;;;;;N;;;;10429; +10402;DESERET CAPITAL LETTER LONG A;Lu;0;L;;;;;N;;;;1042A; +10403;DESERET CAPITAL LETTER LONG AH;Lu;0;L;;;;;N;;;;1042B; +10404;DESERET CAPITAL LETTER LONG O;Lu;0;L;;;;;N;;;;1042C; +10405;DESERET CAPITAL LETTER LONG OO;Lu;0;L;;;;;N;;;;1042D; +10406;DESERET CAPITAL LETTER SHORT I;Lu;0;L;;;;;N;;;;1042E; +10407;DESERET CAPITAL LETTER SHORT E;Lu;0;L;;;;;N;;;;1042F; +10408;DESERET CAPITAL LETTER SHORT A;Lu;0;L;;;;;N;;;;10430; +10409;DESERET CAPITAL LETTER SHORT AH;Lu;0;L;;;;;N;;;;10431; +1040A;DESERET CAPITAL LETTER SHORT O;Lu;0;L;;;;;N;;;;10432; +1040B;DESERET CAPITAL LETTER SHORT OO;Lu;0;L;;;;;N;;;;10433; +1040C;DESERET CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;10434; +1040D;DESERET CAPITAL LETTER OW;Lu;0;L;;;;;N;;;;10435; +1040E;DESERET CAPITAL LETTER WU;Lu;0;L;;;;;N;;;;10436; +1040F;DESERET CAPITAL LETTER YEE;Lu;0;L;;;;;N;;;;10437; +10410;DESERET CAPITAL LETTER H;Lu;0;L;;;;;N;;;;10438; +10411;DESERET CAPITAL LETTER PEE;Lu;0;L;;;;;N;;;;10439; +10412;DESERET CAPITAL LETTER BEE;Lu;0;L;;;;;N;;;;1043A; +10413;DESERET CAPITAL LETTER TEE;Lu;0;L;;;;;N;;;;1043B; +10414;DESERET CAPITAL LETTER DEE;Lu;0;L;;;;;N;;;;1043C; +10415;DESERET CAPITAL LETTER CHEE;Lu;0;L;;;;;N;;;;1043D; +10416;DESERET CAPITAL LETTER JEE;Lu;0;L;;;;;N;;;;1043E; +10417;DESERET CAPITAL LETTER KAY;Lu;0;L;;;;;N;;;;1043F; +10418;DESERET CAPITAL LETTER GAY;Lu;0;L;;;;;N;;;;10440; +10419;DESERET CAPITAL LETTER EF;Lu;0;L;;;;;N;;;;10441; +1041A;DESERET CAPITAL LETTER VEE;Lu;0;L;;;;;N;;;;10442; +1041B;DESERET CAPITAL LETTER ETH;Lu;0;L;;;;;N;;;;10443; +1041C;DESERET CAPITAL LETTER THEE;Lu;0;L;;;;;N;;;;10444; +1041D;DESERET CAPITAL LETTER ES;Lu;0;L;;;;;N;;;;10445; +1041E;DESERET CAPITAL LETTER ZEE;Lu;0;L;;;;;N;;;;10446; +1041F;DESERET CAPITAL LETTER ESH;Lu;0;L;;;;;N;;;;10447; +10420;DESERET CAPITAL LETTER ZHEE;Lu;0;L;;;;;N;;;;10448; +10421;DESERET CAPITAL LETTER ER;Lu;0;L;;;;;N;;;;10449; +10422;DESERET CAPITAL LETTER EL;Lu;0;L;;;;;N;;;;1044A; +10423;DESERET CAPITAL LETTER EM;Lu;0;L;;;;;N;;;;1044B; +10424;DESERET CAPITAL LETTER EN;Lu;0;L;;;;;N;;;;1044C; +10425;DESERET CAPITAL LETTER ENG;Lu;0;L;;;;;N;;;;1044D; +10426;DESERET CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;1044E; +10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; +10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 +10429;DESERET SMALL LETTER LONG E;Ll;0;L;;;;;N;;;10401;;10401 +1042A;DESERET SMALL LETTER LONG A;Ll;0;L;;;;;N;;;10402;;10402 +1042B;DESERET SMALL LETTER LONG AH;Ll;0;L;;;;;N;;;10403;;10403 +1042C;DESERET SMALL LETTER LONG O;Ll;0;L;;;;;N;;;10404;;10404 +1042D;DESERET SMALL LETTER LONG OO;Ll;0;L;;;;;N;;;10405;;10405 +1042E;DESERET SMALL LETTER SHORT I;Ll;0;L;;;;;N;;;10406;;10406 +1042F;DESERET SMALL LETTER SHORT E;Ll;0;L;;;;;N;;;10407;;10407 +10430;DESERET SMALL LETTER SHORT A;Ll;0;L;;;;;N;;;10408;;10408 +10431;DESERET SMALL LETTER SHORT AH;Ll;0;L;;;;;N;;;10409;;10409 +10432;DESERET SMALL LETTER SHORT O;Ll;0;L;;;;;N;;;1040A;;1040A +10433;DESERET SMALL LETTER SHORT OO;Ll;0;L;;;;;N;;;1040B;;1040B +10434;DESERET SMALL LETTER AY;Ll;0;L;;;;;N;;;1040C;;1040C +10435;DESERET SMALL LETTER OW;Ll;0;L;;;;;N;;;1040D;;1040D +10436;DESERET SMALL LETTER WU;Ll;0;L;;;;;N;;;1040E;;1040E +10437;DESERET SMALL LETTER YEE;Ll;0;L;;;;;N;;;1040F;;1040F +10438;DESERET SMALL LETTER H;Ll;0;L;;;;;N;;;10410;;10410 +10439;DESERET SMALL LETTER PEE;Ll;0;L;;;;;N;;;10411;;10411 +1043A;DESERET SMALL LETTER BEE;Ll;0;L;;;;;N;;;10412;;10412 +1043B;DESERET SMALL LETTER TEE;Ll;0;L;;;;;N;;;10413;;10413 +1043C;DESERET SMALL LETTER DEE;Ll;0;L;;;;;N;;;10414;;10414 +1043D;DESERET SMALL LETTER CHEE;Ll;0;L;;;;;N;;;10415;;10415 +1043E;DESERET SMALL LETTER JEE;Ll;0;L;;;;;N;;;10416;;10416 +1043F;DESERET SMALL LETTER KAY;Ll;0;L;;;;;N;;;10417;;10417 +10440;DESERET SMALL LETTER GAY;Ll;0;L;;;;;N;;;10418;;10418 +10441;DESERET SMALL LETTER EF;Ll;0;L;;;;;N;;;10419;;10419 +10442;DESERET SMALL LETTER VEE;Ll;0;L;;;;;N;;;1041A;;1041A +10443;DESERET SMALL LETTER ETH;Ll;0;L;;;;;N;;;1041B;;1041B +10444;DESERET SMALL LETTER THEE;Ll;0;L;;;;;N;;;1041C;;1041C +10445;DESERET SMALL LETTER ES;Ll;0;L;;;;;N;;;1041D;;1041D +10446;DESERET SMALL LETTER ZEE;Ll;0;L;;;;;N;;;1041E;;1041E +10447;DESERET SMALL LETTER ESH;Ll;0;L;;;;;N;;;1041F;;1041F +10448;DESERET SMALL LETTER ZHEE;Ll;0;L;;;;;N;;;10420;;10420 +10449;DESERET SMALL LETTER ER;Ll;0;L;;;;;N;;;10421;;10421 +1044A;DESERET SMALL LETTER EL;Ll;0;L;;;;;N;;;10422;;10422 +1044B;DESERET SMALL LETTER EM;Ll;0;L;;;;;N;;;10423;;10423 +1044C;DESERET SMALL LETTER EN;Ll;0;L;;;;;N;;;10424;;10424 +1044D;DESERET SMALL LETTER ENG;Ll;0;L;;;;;N;;;10425;;10425 +1044E;DESERET SMALL LETTER OI;Ll;0;L;;;;;N;;;10426;;10426 +1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 +10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; +10451;SHAVIAN LETTER TOT;Lo;0;L;;;;;N;;;;; +10452;SHAVIAN LETTER KICK;Lo;0;L;;;;;N;;;;; +10453;SHAVIAN LETTER FEE;Lo;0;L;;;;;N;;;;; +10454;SHAVIAN LETTER THIGH;Lo;0;L;;;;;N;;;;; +10455;SHAVIAN LETTER SO;Lo;0;L;;;;;N;;;;; +10456;SHAVIAN LETTER SURE;Lo;0;L;;;;;N;;;;; +10457;SHAVIAN LETTER CHURCH;Lo;0;L;;;;;N;;;;; +10458;SHAVIAN LETTER YEA;Lo;0;L;;;;;N;;;;; +10459;SHAVIAN LETTER HUNG;Lo;0;L;;;;;N;;;;; +1045A;SHAVIAN LETTER BIB;Lo;0;L;;;;;N;;;;; +1045B;SHAVIAN LETTER DEAD;Lo;0;L;;;;;N;;;;; +1045C;SHAVIAN LETTER GAG;Lo;0;L;;;;;N;;;;; +1045D;SHAVIAN LETTER VOW;Lo;0;L;;;;;N;;;;; +1045E;SHAVIAN LETTER THEY;Lo;0;L;;;;;N;;;;; +1045F;SHAVIAN LETTER ZOO;Lo;0;L;;;;;N;;;;; +10460;SHAVIAN LETTER MEASURE;Lo;0;L;;;;;N;;;;; +10461;SHAVIAN LETTER JUDGE;Lo;0;L;;;;;N;;;;; +10462;SHAVIAN LETTER WOE;Lo;0;L;;;;;N;;;;; +10463;SHAVIAN LETTER HA-HA;Lo;0;L;;;;;N;;;;; +10464;SHAVIAN LETTER LOLL;Lo;0;L;;;;;N;;;;; +10465;SHAVIAN LETTER MIME;Lo;0;L;;;;;N;;;;; +10466;SHAVIAN LETTER IF;Lo;0;L;;;;;N;;;;; +10467;SHAVIAN LETTER EGG;Lo;0;L;;;;;N;;;;; +10468;SHAVIAN LETTER ASH;Lo;0;L;;;;;N;;;;; +10469;SHAVIAN LETTER ADO;Lo;0;L;;;;;N;;;;; +1046A;SHAVIAN LETTER ON;Lo;0;L;;;;;N;;;;; +1046B;SHAVIAN LETTER WOOL;Lo;0;L;;;;;N;;;;; +1046C;SHAVIAN LETTER OUT;Lo;0;L;;;;;N;;;;; +1046D;SHAVIAN LETTER AH;Lo;0;L;;;;;N;;;;; +1046E;SHAVIAN LETTER ROAR;Lo;0;L;;;;;N;;;;; +1046F;SHAVIAN LETTER NUN;Lo;0;L;;;;;N;;;;; +10470;SHAVIAN LETTER EAT;Lo;0;L;;;;;N;;;;; +10471;SHAVIAN LETTER AGE;Lo;0;L;;;;;N;;;;; +10472;SHAVIAN LETTER ICE;Lo;0;L;;;;;N;;;;; +10473;SHAVIAN LETTER UP;Lo;0;L;;;;;N;;;;; +10474;SHAVIAN LETTER OAK;Lo;0;L;;;;;N;;;;; +10475;SHAVIAN LETTER OOZE;Lo;0;L;;;;;N;;;;; +10476;SHAVIAN LETTER OIL;Lo;0;L;;;;;N;;;;; +10477;SHAVIAN LETTER AWE;Lo;0;L;;;;;N;;;;; +10478;SHAVIAN LETTER ARE;Lo;0;L;;;;;N;;;;; +10479;SHAVIAN LETTER OR;Lo;0;L;;;;;N;;;;; +1047A;SHAVIAN LETTER AIR;Lo;0;L;;;;;N;;;;; +1047B;SHAVIAN LETTER ERR;Lo;0;L;;;;;N;;;;; +1047C;SHAVIAN LETTER ARRAY;Lo;0;L;;;;;N;;;;; +1047D;SHAVIAN LETTER EAR;Lo;0;L;;;;;N;;;;; +1047E;SHAVIAN LETTER IAN;Lo;0;L;;;;;N;;;;; +1047F;SHAVIAN LETTER YEW;Lo;0;L;;;;;N;;;;; +10480;OSMANYA LETTER ALEF;Lo;0;L;;;;;N;;;;; +10481;OSMANYA LETTER BA;Lo;0;L;;;;;N;;;;; +10482;OSMANYA LETTER TA;Lo;0;L;;;;;N;;;;; +10483;OSMANYA LETTER JA;Lo;0;L;;;;;N;;;;; +10484;OSMANYA LETTER XA;Lo;0;L;;;;;N;;;;; +10485;OSMANYA LETTER KHA;Lo;0;L;;;;;N;;;;; +10486;OSMANYA LETTER DEEL;Lo;0;L;;;;;N;;;;; +10487;OSMANYA LETTER RA;Lo;0;L;;;;;N;;;;; +10488;OSMANYA LETTER SA;Lo;0;L;;;;;N;;;;; +10489;OSMANYA LETTER SHIIN;Lo;0;L;;;;;N;;;;; +1048A;OSMANYA LETTER DHA;Lo;0;L;;;;;N;;;;; +1048B;OSMANYA LETTER CAYN;Lo;0;L;;;;;N;;;;; +1048C;OSMANYA LETTER GA;Lo;0;L;;;;;N;;;;; +1048D;OSMANYA LETTER FA;Lo;0;L;;;;;N;;;;; +1048E;OSMANYA LETTER QAAF;Lo;0;L;;;;;N;;;;; +1048F;OSMANYA LETTER KAAF;Lo;0;L;;;;;N;;;;; +10490;OSMANYA LETTER LAAN;Lo;0;L;;;;;N;;;;; +10491;OSMANYA LETTER MIIN;Lo;0;L;;;;;N;;;;; +10492;OSMANYA LETTER NUUN;Lo;0;L;;;;;N;;;;; +10493;OSMANYA LETTER WAW;Lo;0;L;;;;;N;;;;; +10494;OSMANYA LETTER HA;Lo;0;L;;;;;N;;;;; +10495;OSMANYA LETTER YA;Lo;0;L;;;;;N;;;;; +10496;OSMANYA LETTER A;Lo;0;L;;;;;N;;;;; +10497;OSMANYA LETTER E;Lo;0;L;;;;;N;;;;; +10498;OSMANYA LETTER I;Lo;0;L;;;;;N;;;;; +10499;OSMANYA LETTER O;Lo;0;L;;;;;N;;;;; +1049A;OSMANYA LETTER U;Lo;0;L;;;;;N;;;;; +1049B;OSMANYA LETTER AA;Lo;0;L;;;;;N;;;;; +1049C;OSMANYA LETTER EE;Lo;0;L;;;;;N;;;;; +1049D;OSMANYA LETTER OO;Lo;0;L;;;;;N;;;;; +104A0;OSMANYA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +104A1;OSMANYA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +104A2;OSMANYA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +104A3;OSMANYA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +104A4;OSMANYA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +104A5;OSMANYA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +104A6;OSMANYA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +104A7;OSMANYA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +104A8;OSMANYA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +104A9;OSMANYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +104B0;OSAGE CAPITAL LETTER A;Lu;0;L;;;;;N;;;;104D8; +104B1;OSAGE CAPITAL LETTER AI;Lu;0;L;;;;;N;;;;104D9; +104B2;OSAGE CAPITAL LETTER AIN;Lu;0;L;;;;;N;;;;104DA; +104B3;OSAGE CAPITAL LETTER AH;Lu;0;L;;;;;N;;;;104DB; +104B4;OSAGE CAPITAL LETTER BRA;Lu;0;L;;;;;N;;;;104DC; +104B5;OSAGE CAPITAL LETTER CHA;Lu;0;L;;;;;N;;;;104DD; +104B6;OSAGE CAPITAL LETTER EHCHA;Lu;0;L;;;;;N;;;;104DE; +104B7;OSAGE CAPITAL LETTER E;Lu;0;L;;;;;N;;;;104DF; +104B8;OSAGE CAPITAL LETTER EIN;Lu;0;L;;;;;N;;;;104E0; +104B9;OSAGE CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;104E1; +104BA;OSAGE CAPITAL LETTER HYA;Lu;0;L;;;;;N;;;;104E2; +104BB;OSAGE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;104E3; +104BC;OSAGE CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;104E4; +104BD;OSAGE CAPITAL LETTER EHKA;Lu;0;L;;;;;N;;;;104E5; +104BE;OSAGE CAPITAL LETTER KYA;Lu;0;L;;;;;N;;;;104E6; +104BF;OSAGE CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;104E7; +104C0;OSAGE CAPITAL LETTER MA;Lu;0;L;;;;;N;;;;104E8; +104C1;OSAGE CAPITAL LETTER NA;Lu;0;L;;;;;N;;;;104E9; +104C2;OSAGE CAPITAL LETTER O;Lu;0;L;;;;;N;;;;104EA; +104C3;OSAGE CAPITAL LETTER OIN;Lu;0;L;;;;;N;;;;104EB; +104C4;OSAGE CAPITAL LETTER PA;Lu;0;L;;;;;N;;;;104EC; +104C5;OSAGE CAPITAL LETTER EHPA;Lu;0;L;;;;;N;;;;104ED; +104C6;OSAGE CAPITAL LETTER SA;Lu;0;L;;;;;N;;;;104EE; +104C7;OSAGE CAPITAL LETTER SHA;Lu;0;L;;;;;N;;;;104EF; +104C8;OSAGE CAPITAL LETTER TA;Lu;0;L;;;;;N;;;;104F0; +104C9;OSAGE CAPITAL LETTER EHTA;Lu;0;L;;;;;N;;;;104F1; +104CA;OSAGE CAPITAL LETTER TSA;Lu;0;L;;;;;N;;;;104F2; +104CB;OSAGE CAPITAL LETTER EHTSA;Lu;0;L;;;;;N;;;;104F3; +104CC;OSAGE CAPITAL LETTER TSHA;Lu;0;L;;;;;N;;;;104F4; +104CD;OSAGE CAPITAL LETTER DHA;Lu;0;L;;;;;N;;;;104F5; +104CE;OSAGE CAPITAL LETTER U;Lu;0;L;;;;;N;;;;104F6; +104CF;OSAGE CAPITAL LETTER WA;Lu;0;L;;;;;N;;;;104F7; +104D0;OSAGE CAPITAL LETTER KHA;Lu;0;L;;;;;N;;;;104F8; +104D1;OSAGE CAPITAL LETTER GHA;Lu;0;L;;;;;N;;;;104F9; +104D2;OSAGE CAPITAL LETTER ZA;Lu;0;L;;;;;N;;;;104FA; +104D3;OSAGE CAPITAL LETTER ZHA;Lu;0;L;;;;;N;;;;104FB; +104D8;OSAGE SMALL LETTER A;Ll;0;L;;;;;N;;;104B0;;104B0 +104D9;OSAGE SMALL LETTER AI;Ll;0;L;;;;;N;;;104B1;;104B1 +104DA;OSAGE SMALL LETTER AIN;Ll;0;L;;;;;N;;;104B2;;104B2 +104DB;OSAGE SMALL LETTER AH;Ll;0;L;;;;;N;;;104B3;;104B3 +104DC;OSAGE SMALL LETTER BRA;Ll;0;L;;;;;N;;;104B4;;104B4 +104DD;OSAGE SMALL LETTER CHA;Ll;0;L;;;;;N;;;104B5;;104B5 +104DE;OSAGE SMALL LETTER EHCHA;Ll;0;L;;;;;N;;;104B6;;104B6 +104DF;OSAGE SMALL LETTER E;Ll;0;L;;;;;N;;;104B7;;104B7 +104E0;OSAGE SMALL LETTER EIN;Ll;0;L;;;;;N;;;104B8;;104B8 +104E1;OSAGE SMALL LETTER HA;Ll;0;L;;;;;N;;;104B9;;104B9 +104E2;OSAGE SMALL LETTER HYA;Ll;0;L;;;;;N;;;104BA;;104BA +104E3;OSAGE SMALL LETTER I;Ll;0;L;;;;;N;;;104BB;;104BB +104E4;OSAGE SMALL LETTER KA;Ll;0;L;;;;;N;;;104BC;;104BC +104E5;OSAGE SMALL LETTER EHKA;Ll;0;L;;;;;N;;;104BD;;104BD +104E6;OSAGE SMALL LETTER KYA;Ll;0;L;;;;;N;;;104BE;;104BE +104E7;OSAGE SMALL LETTER LA;Ll;0;L;;;;;N;;;104BF;;104BF +104E8;OSAGE SMALL LETTER MA;Ll;0;L;;;;;N;;;104C0;;104C0 +104E9;OSAGE SMALL LETTER NA;Ll;0;L;;;;;N;;;104C1;;104C1 +104EA;OSAGE SMALL LETTER O;Ll;0;L;;;;;N;;;104C2;;104C2 +104EB;OSAGE SMALL LETTER OIN;Ll;0;L;;;;;N;;;104C3;;104C3 +104EC;OSAGE SMALL LETTER PA;Ll;0;L;;;;;N;;;104C4;;104C4 +104ED;OSAGE SMALL LETTER EHPA;Ll;0;L;;;;;N;;;104C5;;104C5 +104EE;OSAGE SMALL LETTER SA;Ll;0;L;;;;;N;;;104C6;;104C6 +104EF;OSAGE SMALL LETTER SHA;Ll;0;L;;;;;N;;;104C7;;104C7 +104F0;OSAGE SMALL LETTER TA;Ll;0;L;;;;;N;;;104C8;;104C8 +104F1;OSAGE SMALL LETTER EHTA;Ll;0;L;;;;;N;;;104C9;;104C9 +104F2;OSAGE SMALL LETTER TSA;Ll;0;L;;;;;N;;;104CA;;104CA +104F3;OSAGE SMALL LETTER EHTSA;Ll;0;L;;;;;N;;;104CB;;104CB +104F4;OSAGE SMALL LETTER TSHA;Ll;0;L;;;;;N;;;104CC;;104CC +104F5;OSAGE SMALL LETTER DHA;Ll;0;L;;;;;N;;;104CD;;104CD +104F6;OSAGE SMALL LETTER U;Ll;0;L;;;;;N;;;104CE;;104CE +104F7;OSAGE SMALL LETTER WA;Ll;0;L;;;;;N;;;104CF;;104CF +104F8;OSAGE SMALL LETTER KHA;Ll;0;L;;;;;N;;;104D0;;104D0 +104F9;OSAGE SMALL LETTER GHA;Ll;0;L;;;;;N;;;104D1;;104D1 +104FA;OSAGE SMALL LETTER ZA;Ll;0;L;;;;;N;;;104D2;;104D2 +104FB;OSAGE SMALL LETTER ZHA;Ll;0;L;;;;;N;;;104D3;;104D3 +10500;ELBASAN LETTER A;Lo;0;L;;;;;N;;;;; +10501;ELBASAN LETTER BE;Lo;0;L;;;;;N;;;;; +10502;ELBASAN LETTER CE;Lo;0;L;;;;;N;;;;; +10503;ELBASAN LETTER CHE;Lo;0;L;;;;;N;;;;; +10504;ELBASAN LETTER DE;Lo;0;L;;;;;N;;;;; +10505;ELBASAN LETTER NDE;Lo;0;L;;;;;N;;;;; +10506;ELBASAN LETTER DHE;Lo;0;L;;;;;N;;;;; +10507;ELBASAN LETTER EI;Lo;0;L;;;;;N;;;;; +10508;ELBASAN LETTER E;Lo;0;L;;;;;N;;;;; +10509;ELBASAN LETTER FE;Lo;0;L;;;;;N;;;;; +1050A;ELBASAN LETTER GE;Lo;0;L;;;;;N;;;;; +1050B;ELBASAN LETTER GJE;Lo;0;L;;;;;N;;;;; +1050C;ELBASAN LETTER HE;Lo;0;L;;;;;N;;;;; +1050D;ELBASAN LETTER I;Lo;0;L;;;;;N;;;;; +1050E;ELBASAN LETTER JE;Lo;0;L;;;;;N;;;;; +1050F;ELBASAN LETTER KE;Lo;0;L;;;;;N;;;;; +10510;ELBASAN LETTER LE;Lo;0;L;;;;;N;;;;; +10511;ELBASAN LETTER LLE;Lo;0;L;;;;;N;;;;; +10512;ELBASAN LETTER ME;Lo;0;L;;;;;N;;;;; +10513;ELBASAN LETTER NE;Lo;0;L;;;;;N;;;;; +10514;ELBASAN LETTER NA;Lo;0;L;;;;;N;;;;; +10515;ELBASAN LETTER NJE;Lo;0;L;;;;;N;;;;; +10516;ELBASAN LETTER O;Lo;0;L;;;;;N;;;;; +10517;ELBASAN LETTER PE;Lo;0;L;;;;;N;;;;; +10518;ELBASAN LETTER QE;Lo;0;L;;;;;N;;;;; +10519;ELBASAN LETTER RE;Lo;0;L;;;;;N;;;;; +1051A;ELBASAN LETTER RRE;Lo;0;L;;;;;N;;;;; +1051B;ELBASAN LETTER SE;Lo;0;L;;;;;N;;;;; +1051C;ELBASAN LETTER SHE;Lo;0;L;;;;;N;;;;; +1051D;ELBASAN LETTER TE;Lo;0;L;;;;;N;;;;; +1051E;ELBASAN LETTER THE;Lo;0;L;;;;;N;;;;; +1051F;ELBASAN LETTER U;Lo;0;L;;;;;N;;;;; +10520;ELBASAN LETTER VE;Lo;0;L;;;;;N;;;;; +10521;ELBASAN LETTER XE;Lo;0;L;;;;;N;;;;; +10522;ELBASAN LETTER Y;Lo;0;L;;;;;N;;;;; +10523;ELBASAN LETTER ZE;Lo;0;L;;;;;N;;;;; +10524;ELBASAN LETTER ZHE;Lo;0;L;;;;;N;;;;; +10525;ELBASAN LETTER GHE;Lo;0;L;;;;;N;;;;; +10526;ELBASAN LETTER GHAMMA;Lo;0;L;;;;;N;;;;; +10527;ELBASAN LETTER KHE;Lo;0;L;;;;;N;;;;; +10530;CAUCASIAN ALBANIAN LETTER ALT;Lo;0;L;;;;;N;;;;; +10531;CAUCASIAN ALBANIAN LETTER BET;Lo;0;L;;;;;N;;;;; +10532;CAUCASIAN ALBANIAN LETTER GIM;Lo;0;L;;;;;N;;;;; +10533;CAUCASIAN ALBANIAN LETTER DAT;Lo;0;L;;;;;N;;;;; +10534;CAUCASIAN ALBANIAN LETTER EB;Lo;0;L;;;;;N;;;;; +10535;CAUCASIAN ALBANIAN LETTER ZARL;Lo;0;L;;;;;N;;;;; +10536;CAUCASIAN ALBANIAN LETTER EYN;Lo;0;L;;;;;N;;;;; +10537;CAUCASIAN ALBANIAN LETTER ZHIL;Lo;0;L;;;;;N;;;;; +10538;CAUCASIAN ALBANIAN LETTER TAS;Lo;0;L;;;;;N;;;;; +10539;CAUCASIAN ALBANIAN LETTER CHA;Lo;0;L;;;;;N;;;;; +1053A;CAUCASIAN ALBANIAN LETTER YOWD;Lo;0;L;;;;;N;;;;; +1053B;CAUCASIAN ALBANIAN LETTER ZHA;Lo;0;L;;;;;N;;;;; +1053C;CAUCASIAN ALBANIAN LETTER IRB;Lo;0;L;;;;;N;;;;; +1053D;CAUCASIAN ALBANIAN LETTER SHA;Lo;0;L;;;;;N;;;;; +1053E;CAUCASIAN ALBANIAN LETTER LAN;Lo;0;L;;;;;N;;;;; +1053F;CAUCASIAN ALBANIAN LETTER INYA;Lo;0;L;;;;;N;;;;; +10540;CAUCASIAN ALBANIAN LETTER XEYN;Lo;0;L;;;;;N;;;;; +10541;CAUCASIAN ALBANIAN LETTER DYAN;Lo;0;L;;;;;N;;;;; +10542;CAUCASIAN ALBANIAN LETTER CAR;Lo;0;L;;;;;N;;;;; +10543;CAUCASIAN ALBANIAN LETTER JHOX;Lo;0;L;;;;;N;;;;; +10544;CAUCASIAN ALBANIAN LETTER KAR;Lo;0;L;;;;;N;;;;; +10545;CAUCASIAN ALBANIAN LETTER LYIT;Lo;0;L;;;;;N;;;;; +10546;CAUCASIAN ALBANIAN LETTER HEYT;Lo;0;L;;;;;N;;;;; +10547;CAUCASIAN ALBANIAN LETTER QAY;Lo;0;L;;;;;N;;;;; +10548;CAUCASIAN ALBANIAN LETTER AOR;Lo;0;L;;;;;N;;;;; +10549;CAUCASIAN ALBANIAN LETTER CHOY;Lo;0;L;;;;;N;;;;; +1054A;CAUCASIAN ALBANIAN LETTER CHI;Lo;0;L;;;;;N;;;;; +1054B;CAUCASIAN ALBANIAN LETTER CYAY;Lo;0;L;;;;;N;;;;; +1054C;CAUCASIAN ALBANIAN LETTER MAQ;Lo;0;L;;;;;N;;;;; +1054D;CAUCASIAN ALBANIAN LETTER QAR;Lo;0;L;;;;;N;;;;; +1054E;CAUCASIAN ALBANIAN LETTER NOWC;Lo;0;L;;;;;N;;;;; +1054F;CAUCASIAN ALBANIAN LETTER DZYAY;Lo;0;L;;;;;N;;;;; +10550;CAUCASIAN ALBANIAN LETTER SHAK;Lo;0;L;;;;;N;;;;; +10551;CAUCASIAN ALBANIAN LETTER JAYN;Lo;0;L;;;;;N;;;;; +10552;CAUCASIAN ALBANIAN LETTER ON;Lo;0;L;;;;;N;;;;; +10553;CAUCASIAN ALBANIAN LETTER TYAY;Lo;0;L;;;;;N;;;;; +10554;CAUCASIAN ALBANIAN LETTER FAM;Lo;0;L;;;;;N;;;;; +10555;CAUCASIAN ALBANIAN LETTER DZAY;Lo;0;L;;;;;N;;;;; +10556;CAUCASIAN ALBANIAN LETTER CHAT;Lo;0;L;;;;;N;;;;; +10557;CAUCASIAN ALBANIAN LETTER PEN;Lo;0;L;;;;;N;;;;; +10558;CAUCASIAN ALBANIAN LETTER GHEYS;Lo;0;L;;;;;N;;;;; +10559;CAUCASIAN ALBANIAN LETTER RAT;Lo;0;L;;;;;N;;;;; +1055A;CAUCASIAN ALBANIAN LETTER SEYK;Lo;0;L;;;;;N;;;;; +1055B;CAUCASIAN ALBANIAN LETTER VEYZ;Lo;0;L;;;;;N;;;;; +1055C;CAUCASIAN ALBANIAN LETTER TIWR;Lo;0;L;;;;;N;;;;; +1055D;CAUCASIAN ALBANIAN LETTER SHOY;Lo;0;L;;;;;N;;;;; +1055E;CAUCASIAN ALBANIAN LETTER IWN;Lo;0;L;;;;;N;;;;; +1055F;CAUCASIAN ALBANIAN LETTER CYAW;Lo;0;L;;;;;N;;;;; +10560;CAUCASIAN ALBANIAN LETTER CAYN;Lo;0;L;;;;;N;;;;; +10561;CAUCASIAN ALBANIAN LETTER YAYD;Lo;0;L;;;;;N;;;;; +10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;; +10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;; +1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;; +10570;VITHKUQI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;10597; +10571;VITHKUQI CAPITAL LETTER BBE;Lu;0;L;;;;;N;;;;10598; +10572;VITHKUQI CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;10599; +10573;VITHKUQI CAPITAL LETTER CE;Lu;0;L;;;;;N;;;;1059A; +10574;VITHKUQI CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;1059B; +10575;VITHKUQI CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;1059C; +10576;VITHKUQI CAPITAL LETTER DHE;Lu;0;L;;;;;N;;;;1059D; +10577;VITHKUQI CAPITAL LETTER EI;Lu;0;L;;;;;N;;;;1059E; +10578;VITHKUQI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;1059F; +10579;VITHKUQI CAPITAL LETTER FE;Lu;0;L;;;;;N;;;;105A0; +1057A;VITHKUQI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;105A1; +1057C;VITHKUQI CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;105A3; +1057D;VITHKUQI CAPITAL LETTER HHA;Lu;0;L;;;;;N;;;;105A4; +1057E;VITHKUQI CAPITAL LETTER I;Lu;0;L;;;;;N;;;;105A5; +1057F;VITHKUQI CAPITAL LETTER IJE;Lu;0;L;;;;;N;;;;105A6; +10580;VITHKUQI CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;105A7; +10581;VITHKUQI CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;105A8; +10582;VITHKUQI CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;105A9; +10583;VITHKUQI CAPITAL LETTER LLA;Lu;0;L;;;;;N;;;;105AA; +10584;VITHKUQI CAPITAL LETTER ME;Lu;0;L;;;;;N;;;;105AB; +10585;VITHKUQI CAPITAL LETTER NE;Lu;0;L;;;;;N;;;;105AC; +10586;VITHKUQI CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;105AD; +10587;VITHKUQI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;105AE; +10588;VITHKUQI CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;105AF; +10589;VITHKUQI CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;105B0; +1058A;VITHKUQI CAPITAL LETTER RE;Lu;0;L;;;;;N;;;;105B1; +1058C;VITHKUQI CAPITAL LETTER SE;Lu;0;L;;;;;N;;;;105B3; +1058D;VITHKUQI CAPITAL LETTER SHE;Lu;0;L;;;;;N;;;;105B4; +1058E;VITHKUQI CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;105B5; +1058F;VITHKUQI CAPITAL LETTER THE;Lu;0;L;;;;;N;;;;105B6; +10590;VITHKUQI CAPITAL LETTER U;Lu;0;L;;;;;N;;;;105B7; +10591;VITHKUQI CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;105B8; +10592;VITHKUQI CAPITAL LETTER XE;Lu;0;L;;;;;N;;;;105B9; +10594;VITHKUQI CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;105BB; +10595;VITHKUQI CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;105BC; +10597;VITHKUQI SMALL LETTER A;Ll;0;L;;;;;N;;;10570;;10570 +10598;VITHKUQI SMALL LETTER BBE;Ll;0;L;;;;;N;;;10571;;10571 +10599;VITHKUQI SMALL LETTER BE;Ll;0;L;;;;;N;;;10572;;10572 +1059A;VITHKUQI SMALL LETTER CE;Ll;0;L;;;;;N;;;10573;;10573 +1059B;VITHKUQI SMALL LETTER CHE;Ll;0;L;;;;;N;;;10574;;10574 +1059C;VITHKUQI SMALL LETTER DE;Ll;0;L;;;;;N;;;10575;;10575 +1059D;VITHKUQI SMALL LETTER DHE;Ll;0;L;;;;;N;;;10576;;10576 +1059E;VITHKUQI SMALL LETTER EI;Ll;0;L;;;;;N;;;10577;;10577 +1059F;VITHKUQI SMALL LETTER E;Ll;0;L;;;;;N;;;10578;;10578 +105A0;VITHKUQI SMALL LETTER FE;Ll;0;L;;;;;N;;;10579;;10579 +105A1;VITHKUQI SMALL LETTER GA;Ll;0;L;;;;;N;;;1057A;;1057A +105A3;VITHKUQI SMALL LETTER HA;Ll;0;L;;;;;N;;;1057C;;1057C +105A4;VITHKUQI SMALL LETTER HHA;Ll;0;L;;;;;N;;;1057D;;1057D +105A5;VITHKUQI SMALL LETTER I;Ll;0;L;;;;;N;;;1057E;;1057E +105A6;VITHKUQI SMALL LETTER IJE;Ll;0;L;;;;;N;;;1057F;;1057F +105A7;VITHKUQI SMALL LETTER JE;Ll;0;L;;;;;N;;;10580;;10580 +105A8;VITHKUQI SMALL LETTER KA;Ll;0;L;;;;;N;;;10581;;10581 +105A9;VITHKUQI SMALL LETTER LA;Ll;0;L;;;;;N;;;10582;;10582 +105AA;VITHKUQI SMALL LETTER LLA;Ll;0;L;;;;;N;;;10583;;10583 +105AB;VITHKUQI SMALL LETTER ME;Ll;0;L;;;;;N;;;10584;;10584 +105AC;VITHKUQI SMALL LETTER NE;Ll;0;L;;;;;N;;;10585;;10585 +105AD;VITHKUQI SMALL LETTER NJE;Ll;0;L;;;;;N;;;10586;;10586 +105AE;VITHKUQI SMALL LETTER O;Ll;0;L;;;;;N;;;10587;;10587 +105AF;VITHKUQI SMALL LETTER PE;Ll;0;L;;;;;N;;;10588;;10588 +105B0;VITHKUQI SMALL LETTER QA;Ll;0;L;;;;;N;;;10589;;10589 +105B1;VITHKUQI SMALL LETTER RE;Ll;0;L;;;;;N;;;1058A;;1058A +105B3;VITHKUQI SMALL LETTER SE;Ll;0;L;;;;;N;;;1058C;;1058C +105B4;VITHKUQI SMALL LETTER SHE;Ll;0;L;;;;;N;;;1058D;;1058D +105B5;VITHKUQI SMALL LETTER TE;Ll;0;L;;;;;N;;;1058E;;1058E +105B6;VITHKUQI SMALL LETTER THE;Ll;0;L;;;;;N;;;1058F;;1058F +105B7;VITHKUQI SMALL LETTER U;Ll;0;L;;;;;N;;;10590;;10590 +105B8;VITHKUQI SMALL LETTER VE;Ll;0;L;;;;;N;;;10591;;10591 +105B9;VITHKUQI SMALL LETTER XE;Ll;0;L;;;;;N;;;10592;;10592 +105BB;VITHKUQI SMALL LETTER Y;Ll;0;L;;;;;N;;;10594;;10594 +105BC;VITHKUQI SMALL LETTER ZE;Ll;0;L;;;;;N;;;10595;;10595 +105C0;TODHRI LETTER A;Lo;0;L;;;;;N;;;;; +105C1;TODHRI LETTER AS;Lo;0;L;;;;;N;;;;; +105C2;TODHRI LETTER BA;Lo;0;L;;;;;N;;;;; +105C3;TODHRI LETTER MBA;Lo;0;L;;;;;N;;;;; +105C4;TODHRI LETTER CA;Lo;0;L;;;;;N;;;;; +105C5;TODHRI LETTER CHA;Lo;0;L;;;;;N;;;;; +105C6;TODHRI LETTER DA;Lo;0;L;;;;;N;;;;; +105C7;TODHRI LETTER NDA;Lo;0;L;;;;;N;;;;; +105C8;TODHRI LETTER DHA;Lo;0;L;;;;;N;;;;; +105C9;TODHRI LETTER EI;Lo;0;L;105D2 0307;;;;N;;;;; +105CA;TODHRI LETTER E;Lo;0;L;;;;;N;;;;; +105CB;TODHRI LETTER FA;Lo;0;L;;;;;N;;;;; +105CC;TODHRI LETTER GA;Lo;0;L;;;;;N;;;;; +105CD;TODHRI LETTER NGA;Lo;0;L;;;;;N;;;;; +105CE;TODHRI LETTER GJA;Lo;0;L;;;;;N;;;;; +105CF;TODHRI LETTER NGJA;Lo;0;L;;;;;N;;;;; +105D0;TODHRI LETTER HA;Lo;0;L;;;;;N;;;;; +105D1;TODHRI LETTER HJA;Lo;0;L;;;;;N;;;;; +105D2;TODHRI LETTER I;Lo;0;L;;;;;N;;;;; +105D3;TODHRI LETTER JA;Lo;0;L;;;;;N;;;;; +105D4;TODHRI LETTER KA;Lo;0;L;;;;;N;;;;; +105D5;TODHRI LETTER LA;Lo;0;L;;;;;N;;;;; +105D6;TODHRI LETTER LLA;Lo;0;L;;;;;N;;;;; +105D7;TODHRI LETTER MA;Lo;0;L;;;;;N;;;;; +105D8;TODHRI LETTER NA;Lo;0;L;;;;;N;;;;; +105D9;TODHRI LETTER NJAN;Lo;0;L;;;;;N;;;;; +105DA;TODHRI LETTER O;Lo;0;L;;;;;N;;;;; +105DB;TODHRI LETTER PA;Lo;0;L;;;;;N;;;;; +105DC;TODHRI LETTER QA;Lo;0;L;;;;;N;;;;; +105DD;TODHRI LETTER RA;Lo;0;L;;;;;N;;;;; +105DE;TODHRI LETTER RRA;Lo;0;L;;;;;N;;;;; +105DF;TODHRI LETTER SA;Lo;0;L;;;;;N;;;;; +105E0;TODHRI LETTER SHA;Lo;0;L;;;;;N;;;;; +105E1;TODHRI LETTER SHTA;Lo;0;L;;;;;N;;;;; +105E2;TODHRI LETTER TA;Lo;0;L;;;;;N;;;;; +105E3;TODHRI LETTER THA;Lo;0;L;;;;;N;;;;; +105E4;TODHRI LETTER U;Lo;0;L;105DA 0307;;;;N;;;;; +105E5;TODHRI LETTER VA;Lo;0;L;;;;;N;;;;; +105E6;TODHRI LETTER XA;Lo;0;L;;;;;N;;;;; +105E7;TODHRI LETTER NXA;Lo;0;L;;;;;N;;;;; +105E8;TODHRI LETTER XHA;Lo;0;L;;;;;N;;;;; +105E9;TODHRI LETTER NXHA;Lo;0;L;;;;;N;;;;; +105EA;TODHRI LETTER Y;Lo;0;L;;;;;N;;;;; +105EB;TODHRI LETTER JY;Lo;0;L;;;;;N;;;;; +105EC;TODHRI LETTER ZA;Lo;0;L;;;;;N;;;;; +105ED;TODHRI LETTER ZHA;Lo;0;L;;;;;N;;;;; +105EE;TODHRI LETTER GHA;Lo;0;L;;;;;N;;;;; +105EF;TODHRI LETTER STA;Lo;0;L;;;;;N;;;;; +105F0;TODHRI LETTER SKAN;Lo;0;L;;;;;N;;;;; +105F1;TODHRI LETTER KHA;Lo;0;L;;;;;N;;;;; +105F2;TODHRI LETTER PSA;Lo;0;L;;;;;N;;;;; +105F3;TODHRI LETTER OO;Lo;0;L;;;;;N;;;;; +10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;; +10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;; +10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;; +10603;LINEAR A SIGN AB004;Lo;0;L;;;;;N;;;;; +10604;LINEAR A SIGN AB005;Lo;0;L;;;;;N;;;;; +10605;LINEAR A SIGN AB006;Lo;0;L;;;;;N;;;;; +10606;LINEAR A SIGN AB007;Lo;0;L;;;;;N;;;;; +10607;LINEAR A SIGN AB008;Lo;0;L;;;;;N;;;;; +10608;LINEAR A SIGN AB009;Lo;0;L;;;;;N;;;;; +10609;LINEAR A SIGN AB010;Lo;0;L;;;;;N;;;;; +1060A;LINEAR A SIGN AB011;Lo;0;L;;;;;N;;;;; +1060B;LINEAR A SIGN AB013;Lo;0;L;;;;;N;;;;; +1060C;LINEAR A SIGN AB016;Lo;0;L;;;;;N;;;;; +1060D;LINEAR A SIGN AB017;Lo;0;L;;;;;N;;;;; +1060E;LINEAR A SIGN AB020;Lo;0;L;;;;;N;;;;; +1060F;LINEAR A SIGN AB021;Lo;0;L;;;;;N;;;;; +10610;LINEAR A SIGN AB021F;Lo;0;L;;;;;N;;;;; +10611;LINEAR A SIGN AB021M;Lo;0;L;;;;;N;;;;; +10612;LINEAR A SIGN AB022;Lo;0;L;;;;;N;;;;; +10613;LINEAR A SIGN AB022F;Lo;0;L;;;;;N;;;;; +10614;LINEAR A SIGN AB022M;Lo;0;L;;;;;N;;;;; +10615;LINEAR A SIGN AB023;Lo;0;L;;;;;N;;;;; +10616;LINEAR A SIGN AB023M;Lo;0;L;;;;;N;;;;; +10617;LINEAR A SIGN AB024;Lo;0;L;;;;;N;;;;; +10618;LINEAR A SIGN AB026;Lo;0;L;;;;;N;;;;; +10619;LINEAR A SIGN AB027;Lo;0;L;;;;;N;;;;; +1061A;LINEAR A SIGN AB028;Lo;0;L;;;;;N;;;;; +1061B;LINEAR A SIGN A028B;Lo;0;L;;;;;N;;;;; +1061C;LINEAR A SIGN AB029;Lo;0;L;;;;;N;;;;; +1061D;LINEAR A SIGN AB030;Lo;0;L;;;;;N;;;;; +1061E;LINEAR A SIGN AB031;Lo;0;L;;;;;N;;;;; +1061F;LINEAR A SIGN AB034;Lo;0;L;;;;;N;;;;; +10620;LINEAR A SIGN AB037;Lo;0;L;;;;;N;;;;; +10621;LINEAR A SIGN AB038;Lo;0;L;;;;;N;;;;; +10622;LINEAR A SIGN AB039;Lo;0;L;;;;;N;;;;; +10623;LINEAR A SIGN AB040;Lo;0;L;;;;;N;;;;; +10624;LINEAR A SIGN AB041;Lo;0;L;;;;;N;;;;; +10625;LINEAR A SIGN AB044;Lo;0;L;;;;;N;;;;; +10626;LINEAR A SIGN AB045;Lo;0;L;;;;;N;;;;; +10627;LINEAR A SIGN AB046;Lo;0;L;;;;;N;;;;; +10628;LINEAR A SIGN AB047;Lo;0;L;;;;;N;;;;; +10629;LINEAR A SIGN AB048;Lo;0;L;;;;;N;;;;; +1062A;LINEAR A SIGN AB049;Lo;0;L;;;;;N;;;;; +1062B;LINEAR A SIGN AB050;Lo;0;L;;;;;N;;;;; +1062C;LINEAR A SIGN AB051;Lo;0;L;;;;;N;;;;; +1062D;LINEAR A SIGN AB053;Lo;0;L;;;;;N;;;;; +1062E;LINEAR A SIGN AB054;Lo;0;L;;;;;N;;;;; +1062F;LINEAR A SIGN AB055;Lo;0;L;;;;;N;;;;; +10630;LINEAR A SIGN AB056;Lo;0;L;;;;;N;;;;; +10631;LINEAR A SIGN AB057;Lo;0;L;;;;;N;;;;; +10632;LINEAR A SIGN AB058;Lo;0;L;;;;;N;;;;; +10633;LINEAR A SIGN AB059;Lo;0;L;;;;;N;;;;; +10634;LINEAR A SIGN AB060;Lo;0;L;;;;;N;;;;; +10635;LINEAR A SIGN AB061;Lo;0;L;;;;;N;;;;; +10636;LINEAR A SIGN AB065;Lo;0;L;;;;;N;;;;; +10637;LINEAR A SIGN AB066;Lo;0;L;;;;;N;;;;; +10638;LINEAR A SIGN AB067;Lo;0;L;;;;;N;;;;; +10639;LINEAR A SIGN AB069;Lo;0;L;;;;;N;;;;; +1063A;LINEAR A SIGN AB070;Lo;0;L;;;;;N;;;;; +1063B;LINEAR A SIGN AB073;Lo;0;L;;;;;N;;;;; +1063C;LINEAR A SIGN AB074;Lo;0;L;;;;;N;;;;; +1063D;LINEAR A SIGN AB076;Lo;0;L;;;;;N;;;;; +1063E;LINEAR A SIGN AB077;Lo;0;L;;;;;N;;;;; +1063F;LINEAR A SIGN AB078;Lo;0;L;;;;;N;;;;; +10640;LINEAR A SIGN AB079;Lo;0;L;;;;;N;;;;; +10641;LINEAR A SIGN AB080;Lo;0;L;;;;;N;;;;; +10642;LINEAR A SIGN AB081;Lo;0;L;;;;;N;;;;; +10643;LINEAR A SIGN AB082;Lo;0;L;;;;;N;;;;; +10644;LINEAR A SIGN AB085;Lo;0;L;;;;;N;;;;; +10645;LINEAR A SIGN AB086;Lo;0;L;;;;;N;;;;; +10646;LINEAR A SIGN AB087;Lo;0;L;;;;;N;;;;; +10647;LINEAR A SIGN A100-102;Lo;0;L;;;;;N;;;;; +10648;LINEAR A SIGN AB118;Lo;0;L;;;;;N;;;;; +10649;LINEAR A SIGN AB120;Lo;0;L;;;;;N;;;;; +1064A;LINEAR A SIGN A120B;Lo;0;L;;;;;N;;;;; +1064B;LINEAR A SIGN AB122;Lo;0;L;;;;;N;;;;; +1064C;LINEAR A SIGN AB123;Lo;0;L;;;;;N;;;;; +1064D;LINEAR A SIGN AB131A;Lo;0;L;;;;;N;;;;; +1064E;LINEAR A SIGN AB131B;Lo;0;L;;;;;N;;;;; +1064F;LINEAR A SIGN A131C;Lo;0;L;;;;;N;;;;; +10650;LINEAR A SIGN AB164;Lo;0;L;;;;;N;;;;; +10651;LINEAR A SIGN AB171;Lo;0;L;;;;;N;;;;; +10652;LINEAR A SIGN AB180;Lo;0;L;;;;;N;;;;; +10653;LINEAR A SIGN AB188;Lo;0;L;;;;;N;;;;; +10654;LINEAR A SIGN AB191;Lo;0;L;;;;;N;;;;; +10655;LINEAR A SIGN A301;Lo;0;L;;;;;N;;;;; +10656;LINEAR A SIGN A302;Lo;0;L;;;;;N;;;;; +10657;LINEAR A SIGN A303;Lo;0;L;;;;;N;;;;; +10658;LINEAR A SIGN A304;Lo;0;L;;;;;N;;;;; +10659;LINEAR A SIGN A305;Lo;0;L;;;;;N;;;;; +1065A;LINEAR A SIGN A306;Lo;0;L;;;;;N;;;;; +1065B;LINEAR A SIGN A307;Lo;0;L;;;;;N;;;;; +1065C;LINEAR A SIGN A308;Lo;0;L;;;;;N;;;;; +1065D;LINEAR A SIGN A309A;Lo;0;L;;;;;N;;;;; +1065E;LINEAR A SIGN A309B;Lo;0;L;;;;;N;;;;; +1065F;LINEAR A SIGN A309C;Lo;0;L;;;;;N;;;;; +10660;LINEAR A SIGN A310;Lo;0;L;;;;;N;;;;; +10661;LINEAR A SIGN A311;Lo;0;L;;;;;N;;;;; +10662;LINEAR A SIGN A312;Lo;0;L;;;;;N;;;;; +10663;LINEAR A SIGN A313A;Lo;0;L;;;;;N;;;;; +10664;LINEAR A SIGN A313B;Lo;0;L;;;;;N;;;;; +10665;LINEAR A SIGN A313C;Lo;0;L;;;;;N;;;;; +10666;LINEAR A SIGN A314;Lo;0;L;;;;;N;;;;; +10667;LINEAR A SIGN A315;Lo;0;L;;;;;N;;;;; +10668;LINEAR A SIGN A316;Lo;0;L;;;;;N;;;;; +10669;LINEAR A SIGN A317;Lo;0;L;;;;;N;;;;; +1066A;LINEAR A SIGN A318;Lo;0;L;;;;;N;;;;; +1066B;LINEAR A SIGN A319;Lo;0;L;;;;;N;;;;; +1066C;LINEAR A SIGN A320;Lo;0;L;;;;;N;;;;; +1066D;LINEAR A SIGN A321;Lo;0;L;;;;;N;;;;; +1066E;LINEAR A SIGN A322;Lo;0;L;;;;;N;;;;; +1066F;LINEAR A SIGN A323;Lo;0;L;;;;;N;;;;; +10670;LINEAR A SIGN A324;Lo;0;L;;;;;N;;;;; +10671;LINEAR A SIGN A325;Lo;0;L;;;;;N;;;;; +10672;LINEAR A SIGN A326;Lo;0;L;;;;;N;;;;; +10673;LINEAR A SIGN A327;Lo;0;L;;;;;N;;;;; +10674;LINEAR A SIGN A328;Lo;0;L;;;;;N;;;;; +10675;LINEAR A SIGN A329;Lo;0;L;;;;;N;;;;; +10676;LINEAR A SIGN A330;Lo;0;L;;;;;N;;;;; +10677;LINEAR A SIGN A331;Lo;0;L;;;;;N;;;;; +10678;LINEAR A SIGN A332;Lo;0;L;;;;;N;;;;; +10679;LINEAR A SIGN A333;Lo;0;L;;;;;N;;;;; +1067A;LINEAR A SIGN A334;Lo;0;L;;;;;N;;;;; +1067B;LINEAR A SIGN A335;Lo;0;L;;;;;N;;;;; +1067C;LINEAR A SIGN A336;Lo;0;L;;;;;N;;;;; +1067D;LINEAR A SIGN A337;Lo;0;L;;;;;N;;;;; +1067E;LINEAR A SIGN A338;Lo;0;L;;;;;N;;;;; +1067F;LINEAR A SIGN A339;Lo;0;L;;;;;N;;;;; +10680;LINEAR A SIGN A340;Lo;0;L;;;;;N;;;;; +10681;LINEAR A SIGN A341;Lo;0;L;;;;;N;;;;; +10682;LINEAR A SIGN A342;Lo;0;L;;;;;N;;;;; +10683;LINEAR A SIGN A343;Lo;0;L;;;;;N;;;;; +10684;LINEAR A SIGN A344;Lo;0;L;;;;;N;;;;; +10685;LINEAR A SIGN A345;Lo;0;L;;;;;N;;;;; +10686;LINEAR A SIGN A346;Lo;0;L;;;;;N;;;;; +10687;LINEAR A SIGN A347;Lo;0;L;;;;;N;;;;; +10688;LINEAR A SIGN A348;Lo;0;L;;;;;N;;;;; +10689;LINEAR A SIGN A349;Lo;0;L;;;;;N;;;;; +1068A;LINEAR A SIGN A350;Lo;0;L;;;;;N;;;;; +1068B;LINEAR A SIGN A351;Lo;0;L;;;;;N;;;;; +1068C;LINEAR A SIGN A352;Lo;0;L;;;;;N;;;;; +1068D;LINEAR A SIGN A353;Lo;0;L;;;;;N;;;;; +1068E;LINEAR A SIGN A354;Lo;0;L;;;;;N;;;;; +1068F;LINEAR A SIGN A355;Lo;0;L;;;;;N;;;;; +10690;LINEAR A SIGN A356;Lo;0;L;;;;;N;;;;; +10691;LINEAR A SIGN A357;Lo;0;L;;;;;N;;;;; +10692;LINEAR A SIGN A358;Lo;0;L;;;;;N;;;;; +10693;LINEAR A SIGN A359;Lo;0;L;;;;;N;;;;; +10694;LINEAR A SIGN A360;Lo;0;L;;;;;N;;;;; +10695;LINEAR A SIGN A361;Lo;0;L;;;;;N;;;;; +10696;LINEAR A SIGN A362;Lo;0;L;;;;;N;;;;; +10697;LINEAR A SIGN A363;Lo;0;L;;;;;N;;;;; +10698;LINEAR A SIGN A364;Lo;0;L;;;;;N;;;;; +10699;LINEAR A SIGN A365;Lo;0;L;;;;;N;;;;; +1069A;LINEAR A SIGN A366;Lo;0;L;;;;;N;;;;; +1069B;LINEAR A SIGN A367;Lo;0;L;;;;;N;;;;; +1069C;LINEAR A SIGN A368;Lo;0;L;;;;;N;;;;; +1069D;LINEAR A SIGN A369;Lo;0;L;;;;;N;;;;; +1069E;LINEAR A SIGN A370;Lo;0;L;;;;;N;;;;; +1069F;LINEAR A SIGN A371;Lo;0;L;;;;;N;;;;; +106A0;LINEAR A SIGN A400-VAS;Lo;0;L;;;;;N;;;;; +106A1;LINEAR A SIGN A401-VAS;Lo;0;L;;;;;N;;;;; +106A2;LINEAR A SIGN A402-VAS;Lo;0;L;;;;;N;;;;; +106A3;LINEAR A SIGN A403-VAS;Lo;0;L;;;;;N;;;;; +106A4;LINEAR A SIGN A404-VAS;Lo;0;L;;;;;N;;;;; +106A5;LINEAR A SIGN A405-VAS;Lo;0;L;;;;;N;;;;; +106A6;LINEAR A SIGN A406-VAS;Lo;0;L;;;;;N;;;;; +106A7;LINEAR A SIGN A407-VAS;Lo;0;L;;;;;N;;;;; +106A8;LINEAR A SIGN A408-VAS;Lo;0;L;;;;;N;;;;; +106A9;LINEAR A SIGN A409-VAS;Lo;0;L;;;;;N;;;;; +106AA;LINEAR A SIGN A410-VAS;Lo;0;L;;;;;N;;;;; +106AB;LINEAR A SIGN A411-VAS;Lo;0;L;;;;;N;;;;; +106AC;LINEAR A SIGN A412-VAS;Lo;0;L;;;;;N;;;;; +106AD;LINEAR A SIGN A413-VAS;Lo;0;L;;;;;N;;;;; +106AE;LINEAR A SIGN A414-VAS;Lo;0;L;;;;;N;;;;; +106AF;LINEAR A SIGN A415-VAS;Lo;0;L;;;;;N;;;;; +106B0;LINEAR A SIGN A416-VAS;Lo;0;L;;;;;N;;;;; +106B1;LINEAR A SIGN A417-VAS;Lo;0;L;;;;;N;;;;; +106B2;LINEAR A SIGN A418-VAS;Lo;0;L;;;;;N;;;;; +106B3;LINEAR A SIGN A501;Lo;0;L;;;;;N;;;;; +106B4;LINEAR A SIGN A502;Lo;0;L;;;;;N;;;;; +106B5;LINEAR A SIGN A503;Lo;0;L;;;;;N;;;;; +106B6;LINEAR A SIGN A504;Lo;0;L;;;;;N;;;;; +106B7;LINEAR A SIGN A505;Lo;0;L;;;;;N;;;;; +106B8;LINEAR A SIGN A506;Lo;0;L;;;;;N;;;;; +106B9;LINEAR A SIGN A508;Lo;0;L;;;;;N;;;;; +106BA;LINEAR A SIGN A509;Lo;0;L;;;;;N;;;;; +106BB;LINEAR A SIGN A510;Lo;0;L;;;;;N;;;;; +106BC;LINEAR A SIGN A511;Lo;0;L;;;;;N;;;;; +106BD;LINEAR A SIGN A512;Lo;0;L;;;;;N;;;;; +106BE;LINEAR A SIGN A513;Lo;0;L;;;;;N;;;;; +106BF;LINEAR A SIGN A515;Lo;0;L;;;;;N;;;;; +106C0;LINEAR A SIGN A516;Lo;0;L;;;;;N;;;;; +106C1;LINEAR A SIGN A520;Lo;0;L;;;;;N;;;;; +106C2;LINEAR A SIGN A521;Lo;0;L;;;;;N;;;;; +106C3;LINEAR A SIGN A523;Lo;0;L;;;;;N;;;;; +106C4;LINEAR A SIGN A524;Lo;0;L;;;;;N;;;;; +106C5;LINEAR A SIGN A525;Lo;0;L;;;;;N;;;;; +106C6;LINEAR A SIGN A526;Lo;0;L;;;;;N;;;;; +106C7;LINEAR A SIGN A527;Lo;0;L;;;;;N;;;;; +106C8;LINEAR A SIGN A528;Lo;0;L;;;;;N;;;;; +106C9;LINEAR A SIGN A529;Lo;0;L;;;;;N;;;;; +106CA;LINEAR A SIGN A530;Lo;0;L;;;;;N;;;;; +106CB;LINEAR A SIGN A531;Lo;0;L;;;;;N;;;;; +106CC;LINEAR A SIGN A532;Lo;0;L;;;;;N;;;;; +106CD;LINEAR A SIGN A534;Lo;0;L;;;;;N;;;;; +106CE;LINEAR A SIGN A535;Lo;0;L;;;;;N;;;;; +106CF;LINEAR A SIGN A536;Lo;0;L;;;;;N;;;;; +106D0;LINEAR A SIGN A537;Lo;0;L;;;;;N;;;;; +106D1;LINEAR A SIGN A538;Lo;0;L;;;;;N;;;;; +106D2;LINEAR A SIGN A539;Lo;0;L;;;;;N;;;;; +106D3;LINEAR A SIGN A540;Lo;0;L;;;;;N;;;;; +106D4;LINEAR A SIGN A541;Lo;0;L;;;;;N;;;;; +106D5;LINEAR A SIGN A542;Lo;0;L;;;;;N;;;;; +106D6;LINEAR A SIGN A545;Lo;0;L;;;;;N;;;;; +106D7;LINEAR A SIGN A547;Lo;0;L;;;;;N;;;;; +106D8;LINEAR A SIGN A548;Lo;0;L;;;;;N;;;;; +106D9;LINEAR A SIGN A549;Lo;0;L;;;;;N;;;;; +106DA;LINEAR A SIGN A550;Lo;0;L;;;;;N;;;;; +106DB;LINEAR A SIGN A551;Lo;0;L;;;;;N;;;;; +106DC;LINEAR A SIGN A552;Lo;0;L;;;;;N;;;;; +106DD;LINEAR A SIGN A553;Lo;0;L;;;;;N;;;;; +106DE;LINEAR A SIGN A554;Lo;0;L;;;;;N;;;;; +106DF;LINEAR A SIGN A555;Lo;0;L;;;;;N;;;;; +106E0;LINEAR A SIGN A556;Lo;0;L;;;;;N;;;;; +106E1;LINEAR A SIGN A557;Lo;0;L;;;;;N;;;;; +106E2;LINEAR A SIGN A559;Lo;0;L;;;;;N;;;;; +106E3;LINEAR A SIGN A563;Lo;0;L;;;;;N;;;;; +106E4;LINEAR A SIGN A564;Lo;0;L;;;;;N;;;;; +106E5;LINEAR A SIGN A565;Lo;0;L;;;;;N;;;;; +106E6;LINEAR A SIGN A566;Lo;0;L;;;;;N;;;;; +106E7;LINEAR A SIGN A568;Lo;0;L;;;;;N;;;;; +106E8;LINEAR A SIGN A569;Lo;0;L;;;;;N;;;;; +106E9;LINEAR A SIGN A570;Lo;0;L;;;;;N;;;;; +106EA;LINEAR A SIGN A571;Lo;0;L;;;;;N;;;;; +106EB;LINEAR A SIGN A572;Lo;0;L;;;;;N;;;;; +106EC;LINEAR A SIGN A573;Lo;0;L;;;;;N;;;;; +106ED;LINEAR A SIGN A574;Lo;0;L;;;;;N;;;;; +106EE;LINEAR A SIGN A575;Lo;0;L;;;;;N;;;;; +106EF;LINEAR A SIGN A576;Lo;0;L;;;;;N;;;;; +106F0;LINEAR A SIGN A577;Lo;0;L;;;;;N;;;;; +106F1;LINEAR A SIGN A578;Lo;0;L;;;;;N;;;;; +106F2;LINEAR A SIGN A579;Lo;0;L;;;;;N;;;;; +106F3;LINEAR A SIGN A580;Lo;0;L;;;;;N;;;;; +106F4;LINEAR A SIGN A581;Lo;0;L;;;;;N;;;;; +106F5;LINEAR A SIGN A582;Lo;0;L;;;;;N;;;;; +106F6;LINEAR A SIGN A583;Lo;0;L;;;;;N;;;;; +106F7;LINEAR A SIGN A584;Lo;0;L;;;;;N;;;;; +106F8;LINEAR A SIGN A585;Lo;0;L;;;;;N;;;;; +106F9;LINEAR A SIGN A586;Lo;0;L;;;;;N;;;;; +106FA;LINEAR A SIGN A587;Lo;0;L;;;;;N;;;;; +106FB;LINEAR A SIGN A588;Lo;0;L;;;;;N;;;;; +106FC;LINEAR A SIGN A589;Lo;0;L;;;;;N;;;;; +106FD;LINEAR A SIGN A591;Lo;0;L;;;;;N;;;;; +106FE;LINEAR A SIGN A592;Lo;0;L;;;;;N;;;;; +106FF;LINEAR A SIGN A594;Lo;0;L;;;;;N;;;;; +10700;LINEAR A SIGN A595;Lo;0;L;;;;;N;;;;; +10701;LINEAR A SIGN A596;Lo;0;L;;;;;N;;;;; +10702;LINEAR A SIGN A598;Lo;0;L;;;;;N;;;;; +10703;LINEAR A SIGN A600;Lo;0;L;;;;;N;;;;; +10704;LINEAR A SIGN A601;Lo;0;L;;;;;N;;;;; +10705;LINEAR A SIGN A602;Lo;0;L;;;;;N;;;;; +10706;LINEAR A SIGN A603;Lo;0;L;;;;;N;;;;; +10707;LINEAR A SIGN A604;Lo;0;L;;;;;N;;;;; +10708;LINEAR A SIGN A606;Lo;0;L;;;;;N;;;;; +10709;LINEAR A SIGN A608;Lo;0;L;;;;;N;;;;; +1070A;LINEAR A SIGN A609;Lo;0;L;;;;;N;;;;; +1070B;LINEAR A SIGN A610;Lo;0;L;;;;;N;;;;; +1070C;LINEAR A SIGN A611;Lo;0;L;;;;;N;;;;; +1070D;LINEAR A SIGN A612;Lo;0;L;;;;;N;;;;; +1070E;LINEAR A SIGN A613;Lo;0;L;;;;;N;;;;; +1070F;LINEAR A SIGN A614;Lo;0;L;;;;;N;;;;; +10710;LINEAR A SIGN A615;Lo;0;L;;;;;N;;;;; +10711;LINEAR A SIGN A616;Lo;0;L;;;;;N;;;;; +10712;LINEAR A SIGN A617;Lo;0;L;;;;;N;;;;; +10713;LINEAR A SIGN A618;Lo;0;L;;;;;N;;;;; +10714;LINEAR A SIGN A619;Lo;0;L;;;;;N;;;;; +10715;LINEAR A SIGN A620;Lo;0;L;;;;;N;;;;; +10716;LINEAR A SIGN A621;Lo;0;L;;;;;N;;;;; +10717;LINEAR A SIGN A622;Lo;0;L;;;;;N;;;;; +10718;LINEAR A SIGN A623;Lo;0;L;;;;;N;;;;; +10719;LINEAR A SIGN A624;Lo;0;L;;;;;N;;;;; +1071A;LINEAR A SIGN A626;Lo;0;L;;;;;N;;;;; +1071B;LINEAR A SIGN A627;Lo;0;L;;;;;N;;;;; +1071C;LINEAR A SIGN A628;Lo;0;L;;;;;N;;;;; +1071D;LINEAR A SIGN A629;Lo;0;L;;;;;N;;;;; +1071E;LINEAR A SIGN A634;Lo;0;L;;;;;N;;;;; +1071F;LINEAR A SIGN A637;Lo;0;L;;;;;N;;;;; +10720;LINEAR A SIGN A638;Lo;0;L;;;;;N;;;;; +10721;LINEAR A SIGN A640;Lo;0;L;;;;;N;;;;; +10722;LINEAR A SIGN A642;Lo;0;L;;;;;N;;;;; +10723;LINEAR A SIGN A643;Lo;0;L;;;;;N;;;;; +10724;LINEAR A SIGN A644;Lo;0;L;;;;;N;;;;; +10725;LINEAR A SIGN A645;Lo;0;L;;;;;N;;;;; +10726;LINEAR A SIGN A646;Lo;0;L;;;;;N;;;;; +10727;LINEAR A SIGN A648;Lo;0;L;;;;;N;;;;; +10728;LINEAR A SIGN A649;Lo;0;L;;;;;N;;;;; +10729;LINEAR A SIGN A651;Lo;0;L;;;;;N;;;;; +1072A;LINEAR A SIGN A652;Lo;0;L;;;;;N;;;;; +1072B;LINEAR A SIGN A653;Lo;0;L;;;;;N;;;;; +1072C;LINEAR A SIGN A654;Lo;0;L;;;;;N;;;;; +1072D;LINEAR A SIGN A655;Lo;0;L;;;;;N;;;;; +1072E;LINEAR A SIGN A656;Lo;0;L;;;;;N;;;;; +1072F;LINEAR A SIGN A657;Lo;0;L;;;;;N;;;;; +10730;LINEAR A SIGN A658;Lo;0;L;;;;;N;;;;; +10731;LINEAR A SIGN A659;Lo;0;L;;;;;N;;;;; +10732;LINEAR A SIGN A660;Lo;0;L;;;;;N;;;;; +10733;LINEAR A SIGN A661;Lo;0;L;;;;;N;;;;; +10734;LINEAR A SIGN A662;Lo;0;L;;;;;N;;;;; +10735;LINEAR A SIGN A663;Lo;0;L;;;;;N;;;;; +10736;LINEAR A SIGN A664;Lo;0;L;;;;;N;;;;; +10740;LINEAR A SIGN A701 A;Lo;0;L;;;;;N;;;;; +10741;LINEAR A SIGN A702 B;Lo;0;L;;;;;N;;;;; +10742;LINEAR A SIGN A703 D;Lo;0;L;;;;;N;;;;; +10743;LINEAR A SIGN A704 E;Lo;0;L;;;;;N;;;;; +10744;LINEAR A SIGN A705 F;Lo;0;L;;;;;N;;;;; +10745;LINEAR A SIGN A706 H;Lo;0;L;;;;;N;;;;; +10746;LINEAR A SIGN A707 J;Lo;0;L;;;;;N;;;;; +10747;LINEAR A SIGN A708 K;Lo;0;L;;;;;N;;;;; +10748;LINEAR A SIGN A709 L;Lo;0;L;;;;;N;;;;; +10749;LINEAR A SIGN A709-2 L2;Lo;0;L;;;;;N;;;;; +1074A;LINEAR A SIGN A709-3 L3;Lo;0;L;;;;;N;;;;; +1074B;LINEAR A SIGN A709-4 L4;Lo;0;L;;;;;N;;;;; +1074C;LINEAR A SIGN A709-6 L6;Lo;0;L;;;;;N;;;;; +1074D;LINEAR A SIGN A710 W;Lo;0;L;;;;;N;;;;; +1074E;LINEAR A SIGN A711 X;Lo;0;L;;;;;N;;;;; +1074F;LINEAR A SIGN A712 Y;Lo;0;L;;;;;N;;;;; +10750;LINEAR A SIGN A713 OMEGA;Lo;0;L;;;;;N;;;;; +10751;LINEAR A SIGN A714 ABB;Lo;0;L;;;;;N;;;;; +10752;LINEAR A SIGN A715 BB;Lo;0;L;;;;;N;;;;; +10753;LINEAR A SIGN A717 DD;Lo;0;L;;;;;N;;;;; +10754;LINEAR A SIGN A726 EYYY;Lo;0;L;;;;;N;;;;; +10755;LINEAR A SIGN A732 JE;Lo;0;L;;;;;N;;;;; +10760;LINEAR A SIGN A800;Lo;0;L;;;;;N;;;;; +10761;LINEAR A SIGN A801;Lo;0;L;;;;;N;;;;; +10762;LINEAR A SIGN A802;Lo;0;L;;;;;N;;;;; +10763;LINEAR A SIGN A803;Lo;0;L;;;;;N;;;;; +10764;LINEAR A SIGN A804;Lo;0;L;;;;;N;;;;; +10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;; +10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;; +10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;; +10780;MODIFIER LETTER SMALL CAPITAL AA;Lm;0;L;;;;;N;;;;; +10781;MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON;Lm;0;L; 02D0;;;;N;;;;; +10782;MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON;Lm;0;L; 02D1;;;;N;;;;; +10783;MODIFIER LETTER SMALL AE;Lm;0;L; 00E6;;;;N;;;;; +10784;MODIFIER LETTER SMALL CAPITAL B;Lm;0;L; 0299;;;;N;;;;; +10785;MODIFIER LETTER SMALL B WITH HOOK;Lm;0;L; 0253;;;;N;;;;; +10787;MODIFIER LETTER SMALL DZ DIGRAPH;Lm;0;L; 02A3;;;;N;;;;; +10788;MODIFIER LETTER SMALL DZ DIGRAPH WITH RETROFLEX HOOK;Lm;0;L; AB66;;;;N;;;;; +10789;MODIFIER LETTER SMALL DZ DIGRAPH WITH CURL;Lm;0;L; 02A5;;;;N;;;;; +1078A;MODIFIER LETTER SMALL DEZH DIGRAPH;Lm;0;L; 02A4;;;;N;;;;; +1078B;MODIFIER LETTER SMALL D WITH TAIL;Lm;0;L; 0256;;;;N;;;;; +1078C;MODIFIER LETTER SMALL D WITH HOOK;Lm;0;L; 0257;;;;N;;;;; +1078D;MODIFIER LETTER SMALL D WITH HOOK AND TAIL;Lm;0;L; 1D91;;;;N;;;;; +1078E;MODIFIER LETTER SMALL REVERSED E;Lm;0;L; 0258;;;;N;;;;; +1078F;MODIFIER LETTER SMALL CLOSED REVERSED OPEN E;Lm;0;L; 025E;;;;N;;;;; +10790;MODIFIER LETTER SMALL FENG DIGRAPH;Lm;0;L; 02A9;;;;N;;;;; +10791;MODIFIER LETTER SMALL RAMS HORN;Lm;0;L; 0264;;;;N;;;;; +10792;MODIFIER LETTER SMALL CAPITAL G;Lm;0;L; 0262;;;;N;;;;; +10793;MODIFIER LETTER SMALL G WITH HOOK;Lm;0;L; 0260;;;;N;;;;; +10794;MODIFIER LETTER SMALL CAPITAL G WITH HOOK;Lm;0;L; 029B;;;;N;;;;; +10795;MODIFIER LETTER SMALL H WITH STROKE;Lm;0;L; 0127;;;;N;;;;; +10796;MODIFIER LETTER SMALL CAPITAL H;Lm;0;L; 029C;;;;N;;;;; +10797;MODIFIER LETTER SMALL HENG WITH HOOK;Lm;0;L; 0267;;;;N;;;;; +10798;MODIFIER LETTER SMALL DOTLESS J WITH STROKE AND HOOK;Lm;0;L; 0284;;;;N;;;;; +10799;MODIFIER LETTER SMALL LS DIGRAPH;Lm;0;L; 02AA;;;;N;;;;; +1079A;MODIFIER LETTER SMALL LZ DIGRAPH;Lm;0;L; 02AB;;;;N;;;;; +1079B;MODIFIER LETTER SMALL L WITH BELT;Lm;0;L; 026C;;;;N;;;;; +1079C;MODIFIER LETTER SMALL CAPITAL L WITH BELT;Lm;0;L; 1DF04;;;;N;;;;; +1079D;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK AND BELT;Lm;0;L; A78E;;;;N;;;;; +1079E;MODIFIER LETTER SMALL LEZH;Lm;0;L; 026E;;;;N;;;;; +1079F;MODIFIER LETTER SMALL LEZH WITH RETROFLEX HOOK;Lm;0;L; 1DF05;;;;N;;;;; +107A0;MODIFIER LETTER SMALL TURNED Y;Lm;0;L; 028E;;;;N;;;;; +107A1;MODIFIER LETTER SMALL TURNED Y WITH BELT;Lm;0;L; 1DF06;;;;N;;;;; +107A2;MODIFIER LETTER SMALL O WITH STROKE;Lm;0;L; 00F8;;;;N;;;;; +107A3;MODIFIER LETTER SMALL CAPITAL OE;Lm;0;L; 0276;;;;N;;;;; +107A4;MODIFIER LETTER SMALL CLOSED OMEGA;Lm;0;L; 0277;;;;N;;;;; +107A5;MODIFIER LETTER SMALL Q;Lm;0;L; 0071;;;;N;;;;; +107A6;MODIFIER LETTER SMALL TURNED R WITH LONG LEG;Lm;0;L; 027A;;;;N;;;;; +107A7;MODIFIER LETTER SMALL TURNED R WITH LONG LEG AND RETROFLEX HOOK;Lm;0;L; 1DF08;;;;N;;;;; +107A8;MODIFIER LETTER SMALL R WITH TAIL;Lm;0;L; 027D;;;;N;;;;; +107A9;MODIFIER LETTER SMALL R WITH FISHHOOK;Lm;0;L; 027E;;;;N;;;;; +107AA;MODIFIER LETTER SMALL CAPITAL R;Lm;0;L; 0280;;;;N;;;;; +107AB;MODIFIER LETTER SMALL TC DIGRAPH WITH CURL;Lm;0;L; 02A8;;;;N;;;;; +107AC;MODIFIER LETTER SMALL TS DIGRAPH;Lm;0;L; 02A6;;;;N;;;;; +107AD;MODIFIER LETTER SMALL TS DIGRAPH WITH RETROFLEX HOOK;Lm;0;L; AB67;;;;N;;;;; +107AE;MODIFIER LETTER SMALL TESH DIGRAPH;Lm;0;L; 02A7;;;;N;;;;; +107AF;MODIFIER LETTER SMALL T WITH RETROFLEX HOOK;Lm;0;L; 0288;;;;N;;;;; +107B0;MODIFIER LETTER SMALL V WITH RIGHT HOOK;Lm;0;L; 2C71;;;;N;;;;; +107B2;MODIFIER LETTER SMALL CAPITAL Y;Lm;0;L; 028F;;;;N;;;;; +107B3;MODIFIER LETTER GLOTTAL STOP WITH STROKE;Lm;0;L; 02A1;;;;N;;;;; +107B4;MODIFIER LETTER REVERSED GLOTTAL STOP WITH STROKE;Lm;0;L; 02A2;;;;N;;;;; +107B5;MODIFIER LETTER BILABIAL CLICK;Lm;0;L; 0298;;;;N;;;;; +107B6;MODIFIER LETTER DENTAL CLICK;Lm;0;L; 01C0;;;;N;;;;; +107B7;MODIFIER LETTER LATERAL CLICK;Lm;0;L; 01C1;;;;N;;;;; +107B8;MODIFIER LETTER ALVEOLAR CLICK;Lm;0;L; 01C2;;;;N;;;;; +107B9;MODIFIER LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lm;0;L; 1DF0A;;;;N;;;;; +107BA;MODIFIER LETTER SMALL S WITH CURL;Lm;0;L; 1DF1E;;;;N;;;;; +10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;; +10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;; +10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;; +10803;CYPRIOT SYLLABLE O;Lo;0;R;;;;;N;;;;; +10804;CYPRIOT SYLLABLE U;Lo;0;R;;;;;N;;;;; +10805;CYPRIOT SYLLABLE JA;Lo;0;R;;;;;N;;;;; +10808;CYPRIOT SYLLABLE JO;Lo;0;R;;;;;N;;;;; +1080A;CYPRIOT SYLLABLE KA;Lo;0;R;;;;;N;;;;; +1080B;CYPRIOT SYLLABLE KE;Lo;0;R;;;;;N;;;;; +1080C;CYPRIOT SYLLABLE KI;Lo;0;R;;;;;N;;;;; +1080D;CYPRIOT SYLLABLE KO;Lo;0;R;;;;;N;;;;; +1080E;CYPRIOT SYLLABLE KU;Lo;0;R;;;;;N;;;;; +1080F;CYPRIOT SYLLABLE LA;Lo;0;R;;;;;N;;;;; +10810;CYPRIOT SYLLABLE LE;Lo;0;R;;;;;N;;;;; +10811;CYPRIOT SYLLABLE LI;Lo;0;R;;;;;N;;;;; +10812;CYPRIOT SYLLABLE LO;Lo;0;R;;;;;N;;;;; +10813;CYPRIOT SYLLABLE LU;Lo;0;R;;;;;N;;;;; +10814;CYPRIOT SYLLABLE MA;Lo;0;R;;;;;N;;;;; +10815;CYPRIOT SYLLABLE ME;Lo;0;R;;;;;N;;;;; +10816;CYPRIOT SYLLABLE MI;Lo;0;R;;;;;N;;;;; +10817;CYPRIOT SYLLABLE MO;Lo;0;R;;;;;N;;;;; +10818;CYPRIOT SYLLABLE MU;Lo;0;R;;;;;N;;;;; +10819;CYPRIOT SYLLABLE NA;Lo;0;R;;;;;N;;;;; +1081A;CYPRIOT SYLLABLE NE;Lo;0;R;;;;;N;;;;; +1081B;CYPRIOT SYLLABLE NI;Lo;0;R;;;;;N;;;;; +1081C;CYPRIOT SYLLABLE NO;Lo;0;R;;;;;N;;;;; +1081D;CYPRIOT SYLLABLE NU;Lo;0;R;;;;;N;;;;; +1081E;CYPRIOT SYLLABLE PA;Lo;0;R;;;;;N;;;;; +1081F;CYPRIOT SYLLABLE PE;Lo;0;R;;;;;N;;;;; +10820;CYPRIOT SYLLABLE PI;Lo;0;R;;;;;N;;;;; +10821;CYPRIOT SYLLABLE PO;Lo;0;R;;;;;N;;;;; +10822;CYPRIOT SYLLABLE PU;Lo;0;R;;;;;N;;;;; +10823;CYPRIOT SYLLABLE RA;Lo;0;R;;;;;N;;;;; +10824;CYPRIOT SYLLABLE RE;Lo;0;R;;;;;N;;;;; +10825;CYPRIOT SYLLABLE RI;Lo;0;R;;;;;N;;;;; +10826;CYPRIOT SYLLABLE RO;Lo;0;R;;;;;N;;;;; +10827;CYPRIOT SYLLABLE RU;Lo;0;R;;;;;N;;;;; +10828;CYPRIOT SYLLABLE SA;Lo;0;R;;;;;N;;;;; +10829;CYPRIOT SYLLABLE SE;Lo;0;R;;;;;N;;;;; +1082A;CYPRIOT SYLLABLE SI;Lo;0;R;;;;;N;;;;; +1082B;CYPRIOT SYLLABLE SO;Lo;0;R;;;;;N;;;;; +1082C;CYPRIOT SYLLABLE SU;Lo;0;R;;;;;N;;;;; +1082D;CYPRIOT SYLLABLE TA;Lo;0;R;;;;;N;;;;; +1082E;CYPRIOT SYLLABLE TE;Lo;0;R;;;;;N;;;;; +1082F;CYPRIOT SYLLABLE TI;Lo;0;R;;;;;N;;;;; +10830;CYPRIOT SYLLABLE TO;Lo;0;R;;;;;N;;;;; +10831;CYPRIOT SYLLABLE TU;Lo;0;R;;;;;N;;;;; +10832;CYPRIOT SYLLABLE WA;Lo;0;R;;;;;N;;;;; +10833;CYPRIOT SYLLABLE WE;Lo;0;R;;;;;N;;;;; +10834;CYPRIOT SYLLABLE WI;Lo;0;R;;;;;N;;;;; +10835;CYPRIOT SYLLABLE WO;Lo;0;R;;;;;N;;;;; +10837;CYPRIOT SYLLABLE XA;Lo;0;R;;;;;N;;;;; +10838;CYPRIOT SYLLABLE XE;Lo;0;R;;;;;N;;;;; +1083C;CYPRIOT SYLLABLE ZA;Lo;0;R;;;;;N;;;;; +1083F;CYPRIOT SYLLABLE ZO;Lo;0;R;;;;;N;;;;; +10840;IMPERIAL ARAMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10841;IMPERIAL ARAMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; +10842;IMPERIAL ARAMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10843;IMPERIAL ARAMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; +10844;IMPERIAL ARAMAIC LETTER HE;Lo;0;R;;;;;N;;;;; +10845;IMPERIAL ARAMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; +10846;IMPERIAL ARAMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10847;IMPERIAL ARAMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; +10848;IMPERIAL ARAMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; +10849;IMPERIAL ARAMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; +1084A;IMPERIAL ARAMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; +1084B;IMPERIAL ARAMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +1084C;IMPERIAL ARAMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; +1084D;IMPERIAL ARAMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; +1084E;IMPERIAL ARAMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +1084F;IMPERIAL ARAMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; +10850;IMPERIAL ARAMAIC LETTER PE;Lo;0;R;;;;;N;;;;; +10851;IMPERIAL ARAMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; +10852;IMPERIAL ARAMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; +10853;IMPERIAL ARAMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; +10854;IMPERIAL ARAMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; +10855;IMPERIAL ARAMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; +10857;IMPERIAL ARAMAIC SECTION SIGN;Po;0;R;;;;;N;;;;; +10858;IMPERIAL ARAMAIC NUMBER ONE;No;0;R;;;;1;N;;;;; +10859;IMPERIAL ARAMAIC NUMBER TWO;No;0;R;;;;2;N;;;;; +1085A;IMPERIAL ARAMAIC NUMBER THREE;No;0;R;;;;3;N;;;;; +1085B;IMPERIAL ARAMAIC NUMBER TEN;No;0;R;;;;10;N;;;;; +1085C;IMPERIAL ARAMAIC NUMBER TWENTY;No;0;R;;;;20;N;;;;; +1085D;IMPERIAL ARAMAIC NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +1085E;IMPERIAL ARAMAIC NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +1085F;IMPERIAL ARAMAIC NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; +10860;PALMYRENE LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10861;PALMYRENE LETTER BETH;Lo;0;R;;;;;N;;;;; +10862;PALMYRENE LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10863;PALMYRENE LETTER DALETH;Lo;0;R;;;;;N;;;;; +10864;PALMYRENE LETTER HE;Lo;0;R;;;;;N;;;;; +10865;PALMYRENE LETTER WAW;Lo;0;R;;;;;N;;;;; +10866;PALMYRENE LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10867;PALMYRENE LETTER HETH;Lo;0;R;;;;;N;;;;; +10868;PALMYRENE LETTER TETH;Lo;0;R;;;;;N;;;;; +10869;PALMYRENE LETTER YODH;Lo;0;R;;;;;N;;;;; +1086A;PALMYRENE LETTER KAPH;Lo;0;R;;;;;N;;;;; +1086B;PALMYRENE LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +1086C;PALMYRENE LETTER MEM;Lo;0;R;;;;;N;;;;; +1086D;PALMYRENE LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +1086E;PALMYRENE LETTER NUN;Lo;0;R;;;;;N;;;;; +1086F;PALMYRENE LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10870;PALMYRENE LETTER AYIN;Lo;0;R;;;;;N;;;;; +10871;PALMYRENE LETTER PE;Lo;0;R;;;;;N;;;;; +10872;PALMYRENE LETTER SADHE;Lo;0;R;;;;;N;;;;; +10873;PALMYRENE LETTER QOPH;Lo;0;R;;;;;N;;;;; +10874;PALMYRENE LETTER RESH;Lo;0;R;;;;;N;;;;; +10875;PALMYRENE LETTER SHIN;Lo;0;R;;;;;N;;;;; +10876;PALMYRENE LETTER TAW;Lo;0;R;;;;;N;;;;; +10877;PALMYRENE LEFT-POINTING FLEURON;So;0;R;;;;;N;;;;; +10878;PALMYRENE RIGHT-POINTING FLEURON;So;0;R;;;;;N;;;;; +10879;PALMYRENE NUMBER ONE;No;0;R;;;;1;N;;;;; +1087A;PALMYRENE NUMBER TWO;No;0;R;;;;2;N;;;;; +1087B;PALMYRENE NUMBER THREE;No;0;R;;;;3;N;;;;; +1087C;PALMYRENE NUMBER FOUR;No;0;R;;;;4;N;;;;; +1087D;PALMYRENE NUMBER FIVE;No;0;R;;;;5;N;;;;; +1087E;PALMYRENE NUMBER TEN;No;0;R;;;;10;N;;;;; +1087F;PALMYRENE NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10880;NABATAEAN LETTER FINAL ALEPH;Lo;0;R;;;;;N;;;;; +10881;NABATAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10882;NABATAEAN LETTER FINAL BETH;Lo;0;R;;;;;N;;;;; +10883;NABATAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10884;NABATAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10885;NABATAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10886;NABATAEAN LETTER FINAL HE;Lo;0;R;;;;;N;;;;; +10887;NABATAEAN LETTER HE;Lo;0;R;;;;;N;;;;; +10888;NABATAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10889;NABATAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +1088A;NABATAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; +1088B;NABATAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; +1088C;NABATAEAN LETTER FINAL YODH;Lo;0;R;;;;;N;;;;; +1088D;NABATAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; +1088E;NABATAEAN LETTER FINAL KAPH;Lo;0;R;;;;;N;;;;; +1088F;NABATAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10890;NABATAEAN LETTER FINAL LAMEDH;Lo;0;R;;;;;N;;;;; +10891;NABATAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10892;NABATAEAN LETTER FINAL MEM;Lo;0;R;;;;;N;;;;; +10893;NABATAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10894;NABATAEAN LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +10895;NABATAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10896;NABATAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10897;NABATAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10898;NABATAEAN LETTER PE;Lo;0;R;;;;;N;;;;; +10899;NABATAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +1089A;NABATAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +1089B;NABATAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; +1089C;NABATAEAN LETTER FINAL SHIN;Lo;0;R;;;;;N;;;;; +1089D;NABATAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +1089E;NABATAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; +108A7;NABATAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; +108A8;NABATAEAN NUMBER TWO;No;0;R;;;;2;N;;;;; +108A9;NABATAEAN NUMBER THREE;No;0;R;;;;3;N;;;;; +108AA;NABATAEAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +108AB;NABATAEAN CRUCIFORM NUMBER FOUR;No;0;R;;;;4;N;;;;; +108AC;NABATAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +108AD;NABATAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; +108AE;NABATAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +108AF;NABATAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +108E0;HATRAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +108E1;HATRAN LETTER BETH;Lo;0;R;;;;;N;;;;; +108E2;HATRAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +108E3;HATRAN LETTER DALETH-RESH;Lo;0;R;;;;;N;;;;; +108E4;HATRAN LETTER HE;Lo;0;R;;;;;N;;;;; +108E5;HATRAN LETTER WAW;Lo;0;R;;;;;N;;;;; +108E6;HATRAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; +108E7;HATRAN LETTER HETH;Lo;0;R;;;;;N;;;;; +108E8;HATRAN LETTER TETH;Lo;0;R;;;;;N;;;;; +108E9;HATRAN LETTER YODH;Lo;0;R;;;;;N;;;;; +108EA;HATRAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +108EB;HATRAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +108EC;HATRAN LETTER MEM;Lo;0;R;;;;;N;;;;; +108ED;HATRAN LETTER NUN;Lo;0;R;;;;;N;;;;; +108EE;HATRAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +108EF;HATRAN LETTER AYN;Lo;0;R;;;;;N;;;;; +108F0;HATRAN LETTER PE;Lo;0;R;;;;;N;;;;; +108F1;HATRAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +108F2;HATRAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +108F4;HATRAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +108F5;HATRAN LETTER TAW;Lo;0;R;;;;;N;;;;; +108FB;HATRAN NUMBER ONE;No;0;R;;;;1;N;;;;; +108FC;HATRAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +108FD;HATRAN NUMBER TEN;No;0;R;;;;10;N;;;;; +108FE;HATRAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +108FF;HATRAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;; +10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;; +10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;; +10903;PHOENICIAN LETTER DELT;Lo;0;R;;;;;N;;;;; +10904;PHOENICIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10905;PHOENICIAN LETTER WAU;Lo;0;R;;;;;N;;;;; +10906;PHOENICIAN LETTER ZAI;Lo;0;R;;;;;N;;;;; +10907;PHOENICIAN LETTER HET;Lo;0;R;;;;;N;;;;; +10908;PHOENICIAN LETTER TET;Lo;0;R;;;;;N;;;;; +10909;PHOENICIAN LETTER YOD;Lo;0;R;;;;;N;;;;; +1090A;PHOENICIAN LETTER KAF;Lo;0;R;;;;;N;;;;; +1090B;PHOENICIAN LETTER LAMD;Lo;0;R;;;;;N;;;;; +1090C;PHOENICIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +1090D;PHOENICIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +1090E;PHOENICIAN LETTER SEMK;Lo;0;R;;;;;N;;;;; +1090F;PHOENICIAN LETTER AIN;Lo;0;R;;;;;N;;;;; +10910;PHOENICIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10911;PHOENICIAN LETTER SADE;Lo;0;R;;;;;N;;;;; +10912;PHOENICIAN LETTER QOF;Lo;0;R;;;;;N;;;;; +10913;PHOENICIAN LETTER ROSH;Lo;0;R;;;;;N;;;;; +10914;PHOENICIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10915;PHOENICIAN LETTER TAU;Lo;0;R;;;;;N;;;;; +10916;PHOENICIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10917;PHOENICIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10918;PHOENICIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10919;PHOENICIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +1091A;PHOENICIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +1091B;PHOENICIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +1091F;PHOENICIAN WORD SEPARATOR;Po;0;ON;;;;;N;;;;; +10920;LYDIAN LETTER A;Lo;0;R;;;;;N;;;;; +10921;LYDIAN LETTER B;Lo;0;R;;;;;N;;;;; +10922;LYDIAN LETTER G;Lo;0;R;;;;;N;;;;; +10923;LYDIAN LETTER D;Lo;0;R;;;;;N;;;;; +10924;LYDIAN LETTER E;Lo;0;R;;;;;N;;;;; +10925;LYDIAN LETTER V;Lo;0;R;;;;;N;;;;; +10926;LYDIAN LETTER I;Lo;0;R;;;;;N;;;;; +10927;LYDIAN LETTER Y;Lo;0;R;;;;;N;;;;; +10928;LYDIAN LETTER K;Lo;0;R;;;;;N;;;;; +10929;LYDIAN LETTER L;Lo;0;R;;;;;N;;;;; +1092A;LYDIAN LETTER M;Lo;0;R;;;;;N;;;;; +1092B;LYDIAN LETTER N;Lo;0;R;;;;;N;;;;; +1092C;LYDIAN LETTER O;Lo;0;R;;;;;N;;;;; +1092D;LYDIAN LETTER R;Lo;0;R;;;;;N;;;;; +1092E;LYDIAN LETTER SS;Lo;0;R;;;;;N;;;;; +1092F;LYDIAN LETTER T;Lo;0;R;;;;;N;;;;; +10930;LYDIAN LETTER U;Lo;0;R;;;;;N;;;;; +10931;LYDIAN LETTER F;Lo;0;R;;;;;N;;;;; +10932;LYDIAN LETTER Q;Lo;0;R;;;;;N;;;;; +10933;LYDIAN LETTER S;Lo;0;R;;;;;N;;;;; +10934;LYDIAN LETTER TT;Lo;0;R;;;;;N;;;;; +10935;LYDIAN LETTER AN;Lo;0;R;;;;;N;;;;; +10936;LYDIAN LETTER EN;Lo;0;R;;;;;N;;;;; +10937;LYDIAN LETTER LY;Lo;0;R;;;;;N;;;;; +10938;LYDIAN LETTER NN;Lo;0;R;;;;;N;;;;; +10939;LYDIAN LETTER C;Lo;0;R;;;;;N;;;;; +1093F;LYDIAN TRIANGULAR MARK;Po;0;R;;;;;N;;;;; +10940;SIDETIC LETTER N01;Lo;0;R;;;;;N;;;;; +10941;SIDETIC LETTER N02;Lo;0;R;;;;;N;;;;; +10942;SIDETIC LETTER N03;Lo;0;R;;;;;N;;;;; +10943;SIDETIC LETTER N04;Lo;0;R;;;;;N;;;;; +10944;SIDETIC LETTER N05;Lo;0;R;;;;;N;;;;; +10945;SIDETIC LETTER N06;Lo;0;R;;;;;N;;;;; +10946;SIDETIC LETTER N07;Lo;0;R;;;;;N;;;;; +10947;SIDETIC LETTER N08;Lo;0;R;;;;;N;;;;; +10948;SIDETIC LETTER N09;Lo;0;R;;;;;N;;;;; +10949;SIDETIC LETTER N10;Lo;0;R;;;;;N;;;;; +1094A;SIDETIC LETTER N11;Lo;0;R;;;;;N;;;;; +1094B;SIDETIC LETTER N12;Lo;0;R;;;;;N;;;;; +1094C;SIDETIC LETTER N13;Lo;0;R;;;;;N;;;;; +1094D;SIDETIC LETTER N14;Lo;0;R;;;;;N;;;;; +1094E;SIDETIC LETTER N15;Lo;0;R;;;;;N;;;;; +1094F;SIDETIC LETTER N16;Lo;0;R;;;;;N;;;;; +10950;SIDETIC LETTER N17;Lo;0;R;;;;;N;;;;; +10951;SIDETIC LETTER N18;Lo;0;R;;;;;N;;;;; +10952;SIDETIC LETTER N19;Lo;0;R;;;;;N;;;;; +10953;SIDETIC LETTER N20;Lo;0;R;;;;;N;;;;; +10954;SIDETIC LETTER N21;Lo;0;R;;;;;N;;;;; +10955;SIDETIC LETTER N22;Lo;0;R;;;;;N;;;;; +10956;SIDETIC LETTER N23;Lo;0;R;;;;;N;;;;; +10957;SIDETIC LETTER N24;Lo;0;R;;;;;N;;;;; +10958;SIDETIC LETTER N25;Lo;0;R;;;;;N;;;;; +10959;SIDETIC LETTER N26;Lo;0;R;;;;;N;;;;; +10980;MEROITIC HIEROGLYPHIC LETTER A;Lo;0;R;;;;;N;;;;; +10981;MEROITIC HIEROGLYPHIC LETTER E;Lo;0;R;;;;;N;;;;; +10982;MEROITIC HIEROGLYPHIC LETTER I;Lo;0;R;;;;;N;;;;; +10983;MEROITIC HIEROGLYPHIC LETTER O;Lo;0;R;;;;;N;;;;; +10984;MEROITIC HIEROGLYPHIC LETTER YA;Lo;0;R;;;;;N;;;;; +10985;MEROITIC HIEROGLYPHIC LETTER WA;Lo;0;R;;;;;N;;;;; +10986;MEROITIC HIEROGLYPHIC LETTER BA;Lo;0;R;;;;;N;;;;; +10987;MEROITIC HIEROGLYPHIC LETTER BA-2;Lo;0;R;;;;;N;;;;; +10988;MEROITIC HIEROGLYPHIC LETTER PA;Lo;0;R;;;;;N;;;;; +10989;MEROITIC HIEROGLYPHIC LETTER MA;Lo;0;R;;;;;N;;;;; +1098A;MEROITIC HIEROGLYPHIC LETTER NA;Lo;0;R;;;;;N;;;;; +1098B;MEROITIC HIEROGLYPHIC LETTER NA-2;Lo;0;R;;;;;N;;;;; +1098C;MEROITIC HIEROGLYPHIC LETTER NE;Lo;0;R;;;;;N;;;;; +1098D;MEROITIC HIEROGLYPHIC LETTER NE-2;Lo;0;R;;;;;N;;;;; +1098E;MEROITIC HIEROGLYPHIC LETTER RA;Lo;0;R;;;;;N;;;;; +1098F;MEROITIC HIEROGLYPHIC LETTER RA-2;Lo;0;R;;;;;N;;;;; +10990;MEROITIC HIEROGLYPHIC LETTER LA;Lo;0;R;;;;;N;;;;; +10991;MEROITIC HIEROGLYPHIC LETTER KHA;Lo;0;R;;;;;N;;;;; +10992;MEROITIC HIEROGLYPHIC LETTER HHA;Lo;0;R;;;;;N;;;;; +10993;MEROITIC HIEROGLYPHIC LETTER SA;Lo;0;R;;;;;N;;;;; +10994;MEROITIC HIEROGLYPHIC LETTER SA-2;Lo;0;R;;;;;N;;;;; +10995;MEROITIC HIEROGLYPHIC LETTER SE;Lo;0;R;;;;;N;;;;; +10996;MEROITIC HIEROGLYPHIC LETTER KA;Lo;0;R;;;;;N;;;;; +10997;MEROITIC HIEROGLYPHIC LETTER QA;Lo;0;R;;;;;N;;;;; +10998;MEROITIC HIEROGLYPHIC LETTER TA;Lo;0;R;;;;;N;;;;; +10999;MEROITIC HIEROGLYPHIC LETTER TA-2;Lo;0;R;;;;;N;;;;; +1099A;MEROITIC HIEROGLYPHIC LETTER TE;Lo;0;R;;;;;N;;;;; +1099B;MEROITIC HIEROGLYPHIC LETTER TE-2;Lo;0;R;;;;;N;;;;; +1099C;MEROITIC HIEROGLYPHIC LETTER TO;Lo;0;R;;;;;N;;;;; +1099D;MEROITIC HIEROGLYPHIC LETTER DA;Lo;0;R;;;;;N;;;;; +1099E;MEROITIC HIEROGLYPHIC SYMBOL VIDJ;Lo;0;R;;;;;N;;;;; +1099F;MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2;Lo;0;R;;;;;N;;;;; +109A0;MEROITIC CURSIVE LETTER A;Lo;0;R;;;;;N;;;;; +109A1;MEROITIC CURSIVE LETTER E;Lo;0;R;;;;;N;;;;; +109A2;MEROITIC CURSIVE LETTER I;Lo;0;R;;;;;N;;;;; +109A3;MEROITIC CURSIVE LETTER O;Lo;0;R;;;;;N;;;;; +109A4;MEROITIC CURSIVE LETTER YA;Lo;0;R;;;;;N;;;;; +109A5;MEROITIC CURSIVE LETTER WA;Lo;0;R;;;;;N;;;;; +109A6;MEROITIC CURSIVE LETTER BA;Lo;0;R;;;;;N;;;;; +109A7;MEROITIC CURSIVE LETTER PA;Lo;0;R;;;;;N;;;;; +109A8;MEROITIC CURSIVE LETTER MA;Lo;0;R;;;;;N;;;;; +109A9;MEROITIC CURSIVE LETTER NA;Lo;0;R;;;;;N;;;;; +109AA;MEROITIC CURSIVE LETTER NE;Lo;0;R;;;;;N;;;;; +109AB;MEROITIC CURSIVE LETTER RA;Lo;0;R;;;;;N;;;;; +109AC;MEROITIC CURSIVE LETTER LA;Lo;0;R;;;;;N;;;;; +109AD;MEROITIC CURSIVE LETTER KHA;Lo;0;R;;;;;N;;;;; +109AE;MEROITIC CURSIVE LETTER HHA;Lo;0;R;;;;;N;;;;; +109AF;MEROITIC CURSIVE LETTER SA;Lo;0;R;;;;;N;;;;; +109B0;MEROITIC CURSIVE LETTER ARCHAIC SA;Lo;0;R;;;;;N;;;;; +109B1;MEROITIC CURSIVE LETTER SE;Lo;0;R;;;;;N;;;;; +109B2;MEROITIC CURSIVE LETTER KA;Lo;0;R;;;;;N;;;;; +109B3;MEROITIC CURSIVE LETTER QA;Lo;0;R;;;;;N;;;;; +109B4;MEROITIC CURSIVE LETTER TA;Lo;0;R;;;;;N;;;;; +109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;; +109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;; +109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;; +109BC;MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS;No;0;R;;;;11/12;N;;;;; +109BD;MEROITIC CURSIVE FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;; +109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;; +109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;; +109C0;MEROITIC CURSIVE NUMBER ONE;No;0;R;;;;1;N;;;;; +109C1;MEROITIC CURSIVE NUMBER TWO;No;0;R;;;;2;N;;;;; +109C2;MEROITIC CURSIVE NUMBER THREE;No;0;R;;;;3;N;;;;; +109C3;MEROITIC CURSIVE NUMBER FOUR;No;0;R;;;;4;N;;;;; +109C4;MEROITIC CURSIVE NUMBER FIVE;No;0;R;;;;5;N;;;;; +109C5;MEROITIC CURSIVE NUMBER SIX;No;0;R;;;;6;N;;;;; +109C6;MEROITIC CURSIVE NUMBER SEVEN;No;0;R;;;;7;N;;;;; +109C7;MEROITIC CURSIVE NUMBER EIGHT;No;0;R;;;;8;N;;;;; +109C8;MEROITIC CURSIVE NUMBER NINE;No;0;R;;;;9;N;;;;; +109C9;MEROITIC CURSIVE NUMBER TEN;No;0;R;;;;10;N;;;;; +109CA;MEROITIC CURSIVE NUMBER TWENTY;No;0;R;;;;20;N;;;;; +109CB;MEROITIC CURSIVE NUMBER THIRTY;No;0;R;;;;30;N;;;;; +109CC;MEROITIC CURSIVE NUMBER FORTY;No;0;R;;;;40;N;;;;; +109CD;MEROITIC CURSIVE NUMBER FIFTY;No;0;R;;;;50;N;;;;; +109CE;MEROITIC CURSIVE NUMBER SIXTY;No;0;R;;;;60;N;;;;; +109CF;MEROITIC CURSIVE NUMBER SEVENTY;No;0;R;;;;70;N;;;;; +109D2;MEROITIC CURSIVE NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +109D3;MEROITIC CURSIVE NUMBER TWO HUNDRED;No;0;R;;;;200;N;;;;; +109D4;MEROITIC CURSIVE NUMBER THREE HUNDRED;No;0;R;;;;300;N;;;;; +109D5;MEROITIC CURSIVE NUMBER FOUR HUNDRED;No;0;R;;;;400;N;;;;; +109D6;MEROITIC CURSIVE NUMBER FIVE HUNDRED;No;0;R;;;;500;N;;;;; +109D7;MEROITIC CURSIVE NUMBER SIX HUNDRED;No;0;R;;;;600;N;;;;; +109D8;MEROITIC CURSIVE NUMBER SEVEN HUNDRED;No;0;R;;;;700;N;;;;; +109D9;MEROITIC CURSIVE NUMBER EIGHT HUNDRED;No;0;R;;;;800;N;;;;; +109DA;MEROITIC CURSIVE NUMBER NINE HUNDRED;No;0;R;;;;900;N;;;;; +109DB;MEROITIC CURSIVE NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +109DC;MEROITIC CURSIVE NUMBER TWO THOUSAND;No;0;R;;;;2000;N;;;;; +109DD;MEROITIC CURSIVE NUMBER THREE THOUSAND;No;0;R;;;;3000;N;;;;; +109DE;MEROITIC CURSIVE NUMBER FOUR THOUSAND;No;0;R;;;;4000;N;;;;; +109DF;MEROITIC CURSIVE NUMBER FIVE THOUSAND;No;0;R;;;;5000;N;;;;; +109E0;MEROITIC CURSIVE NUMBER SIX THOUSAND;No;0;R;;;;6000;N;;;;; +109E1;MEROITIC CURSIVE NUMBER SEVEN THOUSAND;No;0;R;;;;7000;N;;;;; +109E2;MEROITIC CURSIVE NUMBER EIGHT THOUSAND;No;0;R;;;;8000;N;;;;; +109E3;MEROITIC CURSIVE NUMBER NINE THOUSAND;No;0;R;;;;9000;N;;;;; +109E4;MEROITIC CURSIVE NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;; +109E5;MEROITIC CURSIVE NUMBER TWENTY THOUSAND;No;0;R;;;;20000;N;;;;; +109E6;MEROITIC CURSIVE NUMBER THIRTY THOUSAND;No;0;R;;;;30000;N;;;;; +109E7;MEROITIC CURSIVE NUMBER FORTY THOUSAND;No;0;R;;;;40000;N;;;;; +109E8;MEROITIC CURSIVE NUMBER FIFTY THOUSAND;No;0;R;;;;50000;N;;;;; +109E9;MEROITIC CURSIVE NUMBER SIXTY THOUSAND;No;0;R;;;;60000;N;;;;; +109EA;MEROITIC CURSIVE NUMBER SEVENTY THOUSAND;No;0;R;;;;70000;N;;;;; +109EB;MEROITIC CURSIVE NUMBER EIGHTY THOUSAND;No;0;R;;;;80000;N;;;;; +109EC;MEROITIC CURSIVE NUMBER NINETY THOUSAND;No;0;R;;;;90000;N;;;;; +109ED;MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND;No;0;R;;;;100000;N;;;;; +109EE;MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND;No;0;R;;;;200000;N;;;;; +109EF;MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND;No;0;R;;;;300000;N;;;;; +109F0;MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND;No;0;R;;;;400000;N;;;;; +109F1;MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND;No;0;R;;;;500000;N;;;;; +109F2;MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND;No;0;R;;;;600000;N;;;;; +109F3;MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND;No;0;R;;;;700000;N;;;;; +109F4;MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND;No;0;R;;;;800000;N;;;;; +109F5;MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND;No;0;R;;;;900000;N;;;;; +109F6;MEROITIC CURSIVE FRACTION ONE TWELFTH;No;0;R;;;;1/12;N;;;;; +109F7;MEROITIC CURSIVE FRACTION TWO TWELFTHS;No;0;R;;;;2/12;N;;;;; +109F8;MEROITIC CURSIVE FRACTION THREE TWELFTHS;No;0;R;;;;3/12;N;;;;; +109F9;MEROITIC CURSIVE FRACTION FOUR TWELFTHS;No;0;R;;;;4/12;N;;;;; +109FA;MEROITIC CURSIVE FRACTION FIVE TWELFTHS;No;0;R;;;;5/12;N;;;;; +109FB;MEROITIC CURSIVE FRACTION SIX TWELFTHS;No;0;R;;;;6/12;N;;;;; +109FC;MEROITIC CURSIVE FRACTION SEVEN TWELFTHS;No;0;R;;;;7/12;N;;;;; +109FD;MEROITIC CURSIVE FRACTION EIGHT TWELFTHS;No;0;R;;;;8/12;N;;;;; +109FE;MEROITIC CURSIVE FRACTION NINE TWELFTHS;No;0;R;;;;9/12;N;;;;; +109FF;MEROITIC CURSIVE FRACTION TEN TWELFTHS;No;0;R;;;;10/12;N;;;;; +10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;; +10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +10A03;KHAROSHTHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +10A05;KHAROSHTHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +10A06;KHAROSHTHI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +10A0C;KHAROSHTHI VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +10A0D;KHAROSHTHI SIGN DOUBLE RING BELOW;Mn;220;NSM;;;;;N;;;;; +10A0E;KHAROSHTHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +10A0F;KHAROSHTHI SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; +10A10;KHAROSHTHI LETTER KA;Lo;0;R;;;;;N;;;;; +10A11;KHAROSHTHI LETTER KHA;Lo;0;R;;;;;N;;;;; +10A12;KHAROSHTHI LETTER GA;Lo;0;R;;;;;N;;;;; +10A13;KHAROSHTHI LETTER GHA;Lo;0;R;;;;;N;;;;; +10A15;KHAROSHTHI LETTER CA;Lo;0;R;;;;;N;;;;; +10A16;KHAROSHTHI LETTER CHA;Lo;0;R;;;;;N;;;;; +10A17;KHAROSHTHI LETTER JA;Lo;0;R;;;;;N;;;;; +10A19;KHAROSHTHI LETTER NYA;Lo;0;R;;;;;N;;;;; +10A1A;KHAROSHTHI LETTER TTA;Lo;0;R;;;;;N;;;;; +10A1B;KHAROSHTHI LETTER TTHA;Lo;0;R;;;;;N;;;;; +10A1C;KHAROSHTHI LETTER DDA;Lo;0;R;;;;;N;;;;; +10A1D;KHAROSHTHI LETTER DDHA;Lo;0;R;;;;;N;;;;; +10A1E;KHAROSHTHI LETTER NNA;Lo;0;R;;;;;N;;;;; +10A1F;KHAROSHTHI LETTER TA;Lo;0;R;;;;;N;;;;; +10A20;KHAROSHTHI LETTER THA;Lo;0;R;;;;;N;;;;; +10A21;KHAROSHTHI LETTER DA;Lo;0;R;;;;;N;;;;; +10A22;KHAROSHTHI LETTER DHA;Lo;0;R;;;;;N;;;;; +10A23;KHAROSHTHI LETTER NA;Lo;0;R;;;;;N;;;;; +10A24;KHAROSHTHI LETTER PA;Lo;0;R;;;;;N;;;;; +10A25;KHAROSHTHI LETTER PHA;Lo;0;R;;;;;N;;;;; +10A26;KHAROSHTHI LETTER BA;Lo;0;R;;;;;N;;;;; +10A27;KHAROSHTHI LETTER BHA;Lo;0;R;;;;;N;;;;; +10A28;KHAROSHTHI LETTER MA;Lo;0;R;;;;;N;;;;; +10A29;KHAROSHTHI LETTER YA;Lo;0;R;;;;;N;;;;; +10A2A;KHAROSHTHI LETTER RA;Lo;0;R;;;;;N;;;;; +10A2B;KHAROSHTHI LETTER LA;Lo;0;R;;;;;N;;;;; +10A2C;KHAROSHTHI LETTER VA;Lo;0;R;;;;;N;;;;; +10A2D;KHAROSHTHI LETTER SHA;Lo;0;R;;;;;N;;;;; +10A2E;KHAROSHTHI LETTER SSA;Lo;0;R;;;;;N;;;;; +10A2F;KHAROSHTHI LETTER SA;Lo;0;R;;;;;N;;;;; +10A30;KHAROSHTHI LETTER ZA;Lo;0;R;;;;;N;;;;; +10A31;KHAROSHTHI LETTER HA;Lo;0;R;;;;;N;;;;; +10A32;KHAROSHTHI LETTER KKA;Lo;0;R;;;;;N;;;;; +10A33;KHAROSHTHI LETTER TTTHA;Lo;0;R;;;;;N;;;;; +10A34;KHAROSHTHI LETTER TTTA;Lo;0;R;;;;;N;;;;; +10A35;KHAROSHTHI LETTER VHA;Lo;0;R;;;;;N;;;;; +10A38;KHAROSHTHI SIGN BAR ABOVE;Mn;230;NSM;;;;;N;;;;; +10A39;KHAROSHTHI SIGN CAUDA;Mn;1;NSM;;;;;N;;;;; +10A3A;KHAROSHTHI SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; +10A3F;KHAROSHTHI VIRAMA;Mn;9;NSM;;;;;N;;;;; +10A40;KHAROSHTHI DIGIT ONE;No;0;R;;;1;1;N;;;;; +10A41;KHAROSHTHI DIGIT TWO;No;0;R;;;2;2;N;;;;; +10A42;KHAROSHTHI DIGIT THREE;No;0;R;;;3;3;N;;;;; +10A43;KHAROSHTHI DIGIT FOUR;No;0;R;;;4;4;N;;;;; +10A44;KHAROSHTHI NUMBER TEN;No;0;R;;;;10;N;;;;; +10A45;KHAROSHTHI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10A46;KHAROSHTHI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10A47;KHAROSHTHI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10A48;KHAROSHTHI FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;; +10A50;KHAROSHTHI PUNCTUATION DOT;Po;0;R;;;;;N;;;;; +10A51;KHAROSHTHI PUNCTUATION SMALL CIRCLE;Po;0;R;;;;;N;;;;; +10A52;KHAROSHTHI PUNCTUATION CIRCLE;Po;0;R;;;;;N;;;;; +10A53;KHAROSHTHI PUNCTUATION CRESCENT BAR;Po;0;R;;;;;N;;;;; +10A54;KHAROSHTHI PUNCTUATION MANGALAM;Po;0;R;;;;;N;;;;; +10A55;KHAROSHTHI PUNCTUATION LOTUS;Po;0;R;;;;;N;;;;; +10A56;KHAROSHTHI PUNCTUATION DANDA;Po;0;R;;;;;N;;;;; +10A57;KHAROSHTHI PUNCTUATION DOUBLE DANDA;Po;0;R;;;;;N;;;;; +10A58;KHAROSHTHI PUNCTUATION LINES;Po;0;R;;;;;N;;;;; +10A60;OLD SOUTH ARABIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10A61;OLD SOUTH ARABIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10A62;OLD SOUTH ARABIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10A63;OLD SOUTH ARABIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10A64;OLD SOUTH ARABIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10A65;OLD SOUTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10A66;OLD SOUTH ARABIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10A67;OLD SOUTH ARABIAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10A68;OLD SOUTH ARABIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10A69;OLD SOUTH ARABIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10A6A;OLD SOUTH ARABIAN LETTER SAT;Lo;0;R;;;;;N;;;;; +10A6B;OLD SOUTH ARABIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10A6C;OLD SOUTH ARABIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10A6D;OLD SOUTH ARABIAN LETTER KHETH;Lo;0;R;;;;;N;;;;; +10A6E;OLD SOUTH ARABIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10A6F;OLD SOUTH ARABIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10A70;OLD SOUTH ARABIAN LETTER FE;Lo;0;R;;;;;N;;;;; +10A71;OLD SOUTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; +10A72;OLD SOUTH ARABIAN LETTER AYN;Lo;0;R;;;;;N;;;;; +10A73;OLD SOUTH ARABIAN LETTER DHADHE;Lo;0;R;;;;;N;;;;; +10A74;OLD SOUTH ARABIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10A75;OLD SOUTH ARABIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10A76;OLD SOUTH ARABIAN LETTER GHAYN;Lo;0;R;;;;;N;;;;; +10A77;OLD SOUTH ARABIAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10A78;OLD SOUTH ARABIAN LETTER ZAYN;Lo;0;R;;;;;N;;;;; +10A79;OLD SOUTH ARABIAN LETTER DHALETH;Lo;0;R;;;;;N;;;;; +10A7A;OLD SOUTH ARABIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10A7B;OLD SOUTH ARABIAN LETTER THAW;Lo;0;R;;;;;N;;;;; +10A7C;OLD SOUTH ARABIAN LETTER THETH;Lo;0;R;;;;;N;;;;; +10A7D;OLD SOUTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10A7E;OLD SOUTH ARABIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; +10A7F;OLD SOUTH ARABIAN NUMERIC INDICATOR;Po;0;R;;;;;N;;;;; +10A80;OLD NORTH ARABIAN LETTER HEH;Lo;0;R;;;;;N;;;;; +10A81;OLD NORTH ARABIAN LETTER LAM;Lo;0;R;;;;;N;;;;; +10A82;OLD NORTH ARABIAN LETTER HAH;Lo;0;R;;;;;N;;;;; +10A83;OLD NORTH ARABIAN LETTER MEEM;Lo;0;R;;;;;N;;;;; +10A84;OLD NORTH ARABIAN LETTER QAF;Lo;0;R;;;;;N;;;;; +10A85;OLD NORTH ARABIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10A86;OLD NORTH ARABIAN LETTER ES-2;Lo;0;R;;;;;N;;;;; +10A87;OLD NORTH ARABIAN LETTER REH;Lo;0;R;;;;;N;;;;; +10A88;OLD NORTH ARABIAN LETTER BEH;Lo;0;R;;;;;N;;;;; +10A89;OLD NORTH ARABIAN LETTER TEH;Lo;0;R;;;;;N;;;;; +10A8A;OLD NORTH ARABIAN LETTER ES-1;Lo;0;R;;;;;N;;;;; +10A8B;OLD NORTH ARABIAN LETTER KAF;Lo;0;R;;;;;N;;;;; +10A8C;OLD NORTH ARABIAN LETTER NOON;Lo;0;R;;;;;N;;;;; +10A8D;OLD NORTH ARABIAN LETTER KHAH;Lo;0;R;;;;;N;;;;; +10A8E;OLD NORTH ARABIAN LETTER SAD;Lo;0;R;;;;;N;;;;; +10A8F;OLD NORTH ARABIAN LETTER ES-3;Lo;0;R;;;;;N;;;;; +10A90;OLD NORTH ARABIAN LETTER FEH;Lo;0;R;;;;;N;;;;; +10A91;OLD NORTH ARABIAN LETTER ALEF;Lo;0;R;;;;;N;;;;; +10A92;OLD NORTH ARABIAN LETTER AIN;Lo;0;R;;;;;N;;;;; +10A93;OLD NORTH ARABIAN LETTER DAD;Lo;0;R;;;;;N;;;;; +10A94;OLD NORTH ARABIAN LETTER GEEM;Lo;0;R;;;;;N;;;;; +10A95;OLD NORTH ARABIAN LETTER DAL;Lo;0;R;;;;;N;;;;; +10A96;OLD NORTH ARABIAN LETTER GHAIN;Lo;0;R;;;;;N;;;;; +10A97;OLD NORTH ARABIAN LETTER TAH;Lo;0;R;;;;;N;;;;; +10A98;OLD NORTH ARABIAN LETTER ZAIN;Lo;0;R;;;;;N;;;;; +10A99;OLD NORTH ARABIAN LETTER THAL;Lo;0;R;;;;;N;;;;; +10A9A;OLD NORTH ARABIAN LETTER YEH;Lo;0;R;;;;;N;;;;; +10A9B;OLD NORTH ARABIAN LETTER THEH;Lo;0;R;;;;;N;;;;; +10A9C;OLD NORTH ARABIAN LETTER ZAH;Lo;0;R;;;;;N;;;;; +10A9D;OLD NORTH ARABIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10A9E;OLD NORTH ARABIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10A9F;OLD NORTH ARABIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10AC0;MANICHAEAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10AC1;MANICHAEAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10AC2;MANICHAEAN LETTER BHETH;Lo;0;R;;;;;N;;;;; +10AC3;MANICHAEAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10AC4;MANICHAEAN LETTER GHIMEL;Lo;0;R;;;;;N;;;;; +10AC5;MANICHAEAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10AC6;MANICHAEAN LETTER HE;Lo;0;R;;;;;N;;;;; +10AC7;MANICHAEAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10AC8;MANICHAEAN SIGN UD;So;0;R;;;;;N;;;;; +10AC9;MANICHAEAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10ACA;MANICHAEAN LETTER ZHAYIN;Lo;0;R;;;;;N;;;;; +10ACB;MANICHAEAN LETTER JAYIN;Lo;0;R;;;;;N;;;;; +10ACC;MANICHAEAN LETTER JHAYIN;Lo;0;R;;;;;N;;;;; +10ACD;MANICHAEAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10ACE;MANICHAEAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10ACF;MANICHAEAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10AD0;MANICHAEAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10AD1;MANICHAEAN LETTER XAPH;Lo;0;R;;;;;N;;;;; +10AD2;MANICHAEAN LETTER KHAPH;Lo;0;R;;;;;N;;;;; +10AD3;MANICHAEAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10AD4;MANICHAEAN LETTER DHAMEDH;Lo;0;R;;;;;N;;;;; +10AD5;MANICHAEAN LETTER THAMEDH;Lo;0;R;;;;;N;;;;; +10AD6;MANICHAEAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10AD7;MANICHAEAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10AD8;MANICHAEAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10AD9;MANICHAEAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10ADA;MANICHAEAN LETTER AAYIN;Lo;0;R;;;;;N;;;;; +10ADB;MANICHAEAN LETTER PE;Lo;0;R;;;;;N;;;;; +10ADC;MANICHAEAN LETTER FE;Lo;0;R;;;;;N;;;;; +10ADD;MANICHAEAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10ADE;MANICHAEAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10ADF;MANICHAEAN LETTER XOPH;Lo;0;R;;;;;N;;;;; +10AE0;MANICHAEAN LETTER QHOPH;Lo;0;R;;;;;N;;;;; +10AE1;MANICHAEAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10AE2;MANICHAEAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10AE3;MANICHAEAN LETTER SSHIN;Lo;0;R;;;;;N;;;;; +10AE4;MANICHAEAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10AE5;MANICHAEAN ABBREVIATION MARK ABOVE;Mn;230;NSM;;;;;N;;;;; +10AE6;MANICHAEAN ABBREVIATION MARK BELOW;Mn;220;NSM;;;;;N;;;;; +10AEB;MANICHAEAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10AEC;MANICHAEAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +10AED;MANICHAEAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10AEE;MANICHAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10AEF;MANICHAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10AF0;MANICHAEAN PUNCTUATION STAR;Po;0;R;;;;;N;;;;; +10AF1;MANICHAEAN PUNCTUATION FLEURON;Po;0;R;;;;;N;;;;; +10AF2;MANICHAEAN PUNCTUATION DOUBLE DOT WITHIN DOT;Po;0;R;;;;;N;;;;; +10AF3;MANICHAEAN PUNCTUATION DOT WITHIN DOT;Po;0;R;;;;;N;;;;; +10AF4;MANICHAEAN PUNCTUATION DOT;Po;0;R;;;;;N;;;;; +10AF5;MANICHAEAN PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; +10AF6;MANICHAEAN PUNCTUATION LINE FILLER;Po;0;R;;;;;N;;;;; +10B00;AVESTAN LETTER A;Lo;0;R;;;;;N;;;;; +10B01;AVESTAN LETTER AA;Lo;0;R;;;;;N;;;;; +10B02;AVESTAN LETTER AO;Lo;0;R;;;;;N;;;;; +10B03;AVESTAN LETTER AAO;Lo;0;R;;;;;N;;;;; +10B04;AVESTAN LETTER AN;Lo;0;R;;;;;N;;;;; +10B05;AVESTAN LETTER AAN;Lo;0;R;;;;;N;;;;; +10B06;AVESTAN LETTER AE;Lo;0;R;;;;;N;;;;; +10B07;AVESTAN LETTER AEE;Lo;0;R;;;;;N;;;;; +10B08;AVESTAN LETTER E;Lo;0;R;;;;;N;;;;; +10B09;AVESTAN LETTER EE;Lo;0;R;;;;;N;;;;; +10B0A;AVESTAN LETTER O;Lo;0;R;;;;;N;;;;; +10B0B;AVESTAN LETTER OO;Lo;0;R;;;;;N;;;;; +10B0C;AVESTAN LETTER I;Lo;0;R;;;;;N;;;;; +10B0D;AVESTAN LETTER II;Lo;0;R;;;;;N;;;;; +10B0E;AVESTAN LETTER U;Lo;0;R;;;;;N;;;;; +10B0F;AVESTAN LETTER UU;Lo;0;R;;;;;N;;;;; +10B10;AVESTAN LETTER KE;Lo;0;R;;;;;N;;;;; +10B11;AVESTAN LETTER XE;Lo;0;R;;;;;N;;;;; +10B12;AVESTAN LETTER XYE;Lo;0;R;;;;;N;;;;; +10B13;AVESTAN LETTER XVE;Lo;0;R;;;;;N;;;;; +10B14;AVESTAN LETTER GE;Lo;0;R;;;;;N;;;;; +10B15;AVESTAN LETTER GGE;Lo;0;R;;;;;N;;;;; +10B16;AVESTAN LETTER GHE;Lo;0;R;;;;;N;;;;; +10B17;AVESTAN LETTER CE;Lo;0;R;;;;;N;;;;; +10B18;AVESTAN LETTER JE;Lo;0;R;;;;;N;;;;; +10B19;AVESTAN LETTER TE;Lo;0;R;;;;;N;;;;; +10B1A;AVESTAN LETTER THE;Lo;0;R;;;;;N;;;;; +10B1B;AVESTAN LETTER DE;Lo;0;R;;;;;N;;;;; +10B1C;AVESTAN LETTER DHE;Lo;0;R;;;;;N;;;;; +10B1D;AVESTAN LETTER TTE;Lo;0;R;;;;;N;;;;; +10B1E;AVESTAN LETTER PE;Lo;0;R;;;;;N;;;;; +10B1F;AVESTAN LETTER FE;Lo;0;R;;;;;N;;;;; +10B20;AVESTAN LETTER BE;Lo;0;R;;;;;N;;;;; +10B21;AVESTAN LETTER BHE;Lo;0;R;;;;;N;;;;; +10B22;AVESTAN LETTER NGE;Lo;0;R;;;;;N;;;;; +10B23;AVESTAN LETTER NGYE;Lo;0;R;;;;;N;;;;; +10B24;AVESTAN LETTER NGVE;Lo;0;R;;;;;N;;;;; +10B25;AVESTAN LETTER NE;Lo;0;R;;;;;N;;;;; +10B26;AVESTAN LETTER NYE;Lo;0;R;;;;;N;;;;; +10B27;AVESTAN LETTER NNE;Lo;0;R;;;;;N;;;;; +10B28;AVESTAN LETTER ME;Lo;0;R;;;;;N;;;;; +10B29;AVESTAN LETTER HME;Lo;0;R;;;;;N;;;;; +10B2A;AVESTAN LETTER YYE;Lo;0;R;;;;;N;;;;; +10B2B;AVESTAN LETTER YE;Lo;0;R;;;;;N;;;;; +10B2C;AVESTAN LETTER VE;Lo;0;R;;;;;N;;;;; +10B2D;AVESTAN LETTER RE;Lo;0;R;;;;;N;;;;; +10B2E;AVESTAN LETTER LE;Lo;0;R;;;;;N;;;;; +10B2F;AVESTAN LETTER SE;Lo;0;R;;;;;N;;;;; +10B30;AVESTAN LETTER ZE;Lo;0;R;;;;;N;;;;; +10B31;AVESTAN LETTER SHE;Lo;0;R;;;;;N;;;;; +10B32;AVESTAN LETTER ZHE;Lo;0;R;;;;;N;;;;; +10B33;AVESTAN LETTER SHYE;Lo;0;R;;;;;N;;;;; +10B34;AVESTAN LETTER SSHE;Lo;0;R;;;;;N;;;;; +10B35;AVESTAN LETTER HE;Lo;0;R;;;;;N;;;;; +10B39;AVESTAN ABBREVIATION MARK;Po;0;ON;;;;;N;;;;; +10B3A;TINY TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3B;SMALL TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3C;LARGE TWO DOTS OVER ONE DOT PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3D;LARGE ONE DOT OVER TWO DOTS PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3E;LARGE TWO RINGS OVER ONE RING PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B3F;LARGE ONE RING OVER TWO RINGS PUNCTUATION;Po;0;ON;;;;;N;;;;; +10B40;INSCRIPTIONAL PARTHIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B41;INSCRIPTIONAL PARTHIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10B42;INSCRIPTIONAL PARTHIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B43;INSCRIPTIONAL PARTHIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B44;INSCRIPTIONAL PARTHIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10B45;INSCRIPTIONAL PARTHIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10B46;INSCRIPTIONAL PARTHIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B47;INSCRIPTIONAL PARTHIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10B48;INSCRIPTIONAL PARTHIAN LETTER TETH;Lo;0;R;;;;;N;;;;; +10B49;INSCRIPTIONAL PARTHIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10B4A;INSCRIPTIONAL PARTHIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B4B;INSCRIPTIONAL PARTHIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B4C;INSCRIPTIONAL PARTHIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10B4D;INSCRIPTIONAL PARTHIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10B4E;INSCRIPTIONAL PARTHIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B4F;INSCRIPTIONAL PARTHIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10B50;INSCRIPTIONAL PARTHIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10B51;INSCRIPTIONAL PARTHIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B52;INSCRIPTIONAL PARTHIAN LETTER QOPH;Lo;0;R;;;;;N;;;;; +10B53;INSCRIPTIONAL PARTHIAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10B54;INSCRIPTIONAL PARTHIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B55;INSCRIPTIONAL PARTHIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10B58;INSCRIPTIONAL PARTHIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10B59;INSCRIPTIONAL PARTHIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +10B5A;INSCRIPTIONAL PARTHIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +10B5B;INSCRIPTIONAL PARTHIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +10B5C;INSCRIPTIONAL PARTHIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10B5D;INSCRIPTIONAL PARTHIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10B5E;INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10B5F;INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10B60;INSCRIPTIONAL PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B61;INSCRIPTIONAL PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; +10B62;INSCRIPTIONAL PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B63;INSCRIPTIONAL PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B64;INSCRIPTIONAL PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; +10B65;INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; +10B66;INSCRIPTIONAL PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B67;INSCRIPTIONAL PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; +10B68;INSCRIPTIONAL PAHLAVI LETTER TETH;Lo;0;R;;;;;N;;;;; +10B69;INSCRIPTIONAL PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; +10B6A;INSCRIPTIONAL PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B6B;INSCRIPTIONAL PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B6C;INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; +10B6D;INSCRIPTIONAL PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; +10B6E;INSCRIPTIONAL PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B6F;INSCRIPTIONAL PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; +10B70;INSCRIPTIONAL PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B71;INSCRIPTIONAL PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B72;INSCRIPTIONAL PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; +10B78;INSCRIPTIONAL PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; +10B79;INSCRIPTIONAL PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; +10B7A;INSCRIPTIONAL PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; +10B7B;INSCRIPTIONAL PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; +10B7C;INSCRIPTIONAL PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; +10B7D;INSCRIPTIONAL PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10B7E;INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10B7F;INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10B80;PSALTER PAHLAVI LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10B81;PSALTER PAHLAVI LETTER BETH;Lo;0;R;;;;;N;;;;; +10B82;PSALTER PAHLAVI LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10B83;PSALTER PAHLAVI LETTER DALETH;Lo;0;R;;;;;N;;;;; +10B84;PSALTER PAHLAVI LETTER HE;Lo;0;R;;;;;N;;;;; +10B85;PSALTER PAHLAVI LETTER WAW-AYIN-RESH;Lo;0;R;;;;;N;;;;; +10B86;PSALTER PAHLAVI LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10B87;PSALTER PAHLAVI LETTER HETH;Lo;0;R;;;;;N;;;;; +10B88;PSALTER PAHLAVI LETTER YODH;Lo;0;R;;;;;N;;;;; +10B89;PSALTER PAHLAVI LETTER KAPH;Lo;0;R;;;;;N;;;;; +10B8A;PSALTER PAHLAVI LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10B8B;PSALTER PAHLAVI LETTER MEM-QOPH;Lo;0;R;;;;;N;;;;; +10B8C;PSALTER PAHLAVI LETTER NUN;Lo;0;R;;;;;N;;;;; +10B8D;PSALTER PAHLAVI LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10B8E;PSALTER PAHLAVI LETTER PE;Lo;0;R;;;;;N;;;;; +10B8F;PSALTER PAHLAVI LETTER SADHE;Lo;0;R;;;;;N;;;;; +10B90;PSALTER PAHLAVI LETTER SHIN;Lo;0;R;;;;;N;;;;; +10B91;PSALTER PAHLAVI LETTER TAW;Lo;0;R;;;;;N;;;;; +10B99;PSALTER PAHLAVI SECTION MARK;Po;0;R;;;;;N;;;;; +10B9A;PSALTER PAHLAVI TURNED SECTION MARK;Po;0;R;;;;;N;;;;; +10B9B;PSALTER PAHLAVI FOUR DOTS WITH CROSS;Po;0;R;;;;;N;;;;; +10B9C;PSALTER PAHLAVI FOUR DOTS WITH DOT;Po;0;R;;;;;N;;;;; +10BA9;PSALTER PAHLAVI NUMBER ONE;No;0;R;;;;1;N;;;;; +10BAA;PSALTER PAHLAVI NUMBER TWO;No;0;R;;;;2;N;;;;; +10BAB;PSALTER PAHLAVI NUMBER THREE;No;0;R;;;;3;N;;;;; +10BAC;PSALTER PAHLAVI NUMBER FOUR;No;0;R;;;;4;N;;;;; +10BAD;PSALTER PAHLAVI NUMBER TEN;No;0;R;;;;10;N;;;;; +10BAE;PSALTER PAHLAVI NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10BAF;PSALTER PAHLAVI NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10C00;OLD TURKIC LETTER ORKHON A;Lo;0;R;;;;;N;;;;; +10C01;OLD TURKIC LETTER YENISEI A;Lo;0;R;;;;;N;;;;; +10C02;OLD TURKIC LETTER YENISEI AE;Lo;0;R;;;;;N;;;;; +10C03;OLD TURKIC LETTER ORKHON I;Lo;0;R;;;;;N;;;;; +10C04;OLD TURKIC LETTER YENISEI I;Lo;0;R;;;;;N;;;;; +10C05;OLD TURKIC LETTER YENISEI E;Lo;0;R;;;;;N;;;;; +10C06;OLD TURKIC LETTER ORKHON O;Lo;0;R;;;;;N;;;;; +10C07;OLD TURKIC LETTER ORKHON OE;Lo;0;R;;;;;N;;;;; +10C08;OLD TURKIC LETTER YENISEI OE;Lo;0;R;;;;;N;;;;; +10C09;OLD TURKIC LETTER ORKHON AB;Lo;0;R;;;;;N;;;;; +10C0A;OLD TURKIC LETTER YENISEI AB;Lo;0;R;;;;;N;;;;; +10C0B;OLD TURKIC LETTER ORKHON AEB;Lo;0;R;;;;;N;;;;; +10C0C;OLD TURKIC LETTER YENISEI AEB;Lo;0;R;;;;;N;;;;; +10C0D;OLD TURKIC LETTER ORKHON AG;Lo;0;R;;;;;N;;;;; +10C0E;OLD TURKIC LETTER YENISEI AG;Lo;0;R;;;;;N;;;;; +10C0F;OLD TURKIC LETTER ORKHON AEG;Lo;0;R;;;;;N;;;;; +10C10;OLD TURKIC LETTER YENISEI AEG;Lo;0;R;;;;;N;;;;; +10C11;OLD TURKIC LETTER ORKHON AD;Lo;0;R;;;;;N;;;;; +10C12;OLD TURKIC LETTER YENISEI AD;Lo;0;R;;;;;N;;;;; +10C13;OLD TURKIC LETTER ORKHON AED;Lo;0;R;;;;;N;;;;; +10C14;OLD TURKIC LETTER ORKHON EZ;Lo;0;R;;;;;N;;;;; +10C15;OLD TURKIC LETTER YENISEI EZ;Lo;0;R;;;;;N;;;;; +10C16;OLD TURKIC LETTER ORKHON AY;Lo;0;R;;;;;N;;;;; +10C17;OLD TURKIC LETTER YENISEI AY;Lo;0;R;;;;;N;;;;; +10C18;OLD TURKIC LETTER ORKHON AEY;Lo;0;R;;;;;N;;;;; +10C19;OLD TURKIC LETTER YENISEI AEY;Lo;0;R;;;;;N;;;;; +10C1A;OLD TURKIC LETTER ORKHON AEK;Lo;0;R;;;;;N;;;;; +10C1B;OLD TURKIC LETTER YENISEI AEK;Lo;0;R;;;;;N;;;;; +10C1C;OLD TURKIC LETTER ORKHON OEK;Lo;0;R;;;;;N;;;;; +10C1D;OLD TURKIC LETTER YENISEI OEK;Lo;0;R;;;;;N;;;;; +10C1E;OLD TURKIC LETTER ORKHON AL;Lo;0;R;;;;;N;;;;; +10C1F;OLD TURKIC LETTER YENISEI AL;Lo;0;R;;;;;N;;;;; +10C20;OLD TURKIC LETTER ORKHON AEL;Lo;0;R;;;;;N;;;;; +10C21;OLD TURKIC LETTER ORKHON ELT;Lo;0;R;;;;;N;;;;; +10C22;OLD TURKIC LETTER ORKHON EM;Lo;0;R;;;;;N;;;;; +10C23;OLD TURKIC LETTER ORKHON AN;Lo;0;R;;;;;N;;;;; +10C24;OLD TURKIC LETTER ORKHON AEN;Lo;0;R;;;;;N;;;;; +10C25;OLD TURKIC LETTER YENISEI AEN;Lo;0;R;;;;;N;;;;; +10C26;OLD TURKIC LETTER ORKHON ENT;Lo;0;R;;;;;N;;;;; +10C27;OLD TURKIC LETTER YENISEI ENT;Lo;0;R;;;;;N;;;;; +10C28;OLD TURKIC LETTER ORKHON ENC;Lo;0;R;;;;;N;;;;; +10C29;OLD TURKIC LETTER YENISEI ENC;Lo;0;R;;;;;N;;;;; +10C2A;OLD TURKIC LETTER ORKHON ENY;Lo;0;R;;;;;N;;;;; +10C2B;OLD TURKIC LETTER YENISEI ENY;Lo;0;R;;;;;N;;;;; +10C2C;OLD TURKIC LETTER YENISEI ANG;Lo;0;R;;;;;N;;;;; +10C2D;OLD TURKIC LETTER ORKHON ENG;Lo;0;R;;;;;N;;;;; +10C2E;OLD TURKIC LETTER YENISEI AENG;Lo;0;R;;;;;N;;;;; +10C2F;OLD TURKIC LETTER ORKHON EP;Lo;0;R;;;;;N;;;;; +10C30;OLD TURKIC LETTER ORKHON OP;Lo;0;R;;;;;N;;;;; +10C31;OLD TURKIC LETTER ORKHON IC;Lo;0;R;;;;;N;;;;; +10C32;OLD TURKIC LETTER ORKHON EC;Lo;0;R;;;;;N;;;;; +10C33;OLD TURKIC LETTER YENISEI EC;Lo;0;R;;;;;N;;;;; +10C34;OLD TURKIC LETTER ORKHON AQ;Lo;0;R;;;;;N;;;;; +10C35;OLD TURKIC LETTER YENISEI AQ;Lo;0;R;;;;;N;;;;; +10C36;OLD TURKIC LETTER ORKHON IQ;Lo;0;R;;;;;N;;;;; +10C37;OLD TURKIC LETTER YENISEI IQ;Lo;0;R;;;;;N;;;;; +10C38;OLD TURKIC LETTER ORKHON OQ;Lo;0;R;;;;;N;;;;; +10C39;OLD TURKIC LETTER YENISEI OQ;Lo;0;R;;;;;N;;;;; +10C3A;OLD TURKIC LETTER ORKHON AR;Lo;0;R;;;;;N;;;;; +10C3B;OLD TURKIC LETTER YENISEI AR;Lo;0;R;;;;;N;;;;; +10C3C;OLD TURKIC LETTER ORKHON AER;Lo;0;R;;;;;N;;;;; +10C3D;OLD TURKIC LETTER ORKHON AS;Lo;0;R;;;;;N;;;;; +10C3E;OLD TURKIC LETTER ORKHON AES;Lo;0;R;;;;;N;;;;; +10C3F;OLD TURKIC LETTER ORKHON ASH;Lo;0;R;;;;;N;;;;; +10C40;OLD TURKIC LETTER YENISEI ASH;Lo;0;R;;;;;N;;;;; +10C41;OLD TURKIC LETTER ORKHON ESH;Lo;0;R;;;;;N;;;;; +10C42;OLD TURKIC LETTER YENISEI ESH;Lo;0;R;;;;;N;;;;; +10C43;OLD TURKIC LETTER ORKHON AT;Lo;0;R;;;;;N;;;;; +10C44;OLD TURKIC LETTER YENISEI AT;Lo;0;R;;;;;N;;;;; +10C45;OLD TURKIC LETTER ORKHON AET;Lo;0;R;;;;;N;;;;; +10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;; +10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;; +10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;; +10C80;OLD HUNGARIAN CAPITAL LETTER A;Lu;0;R;;;;;N;;;;10CC0; +10C81;OLD HUNGARIAN CAPITAL LETTER AA;Lu;0;R;;;;;N;;;;10CC1; +10C82;OLD HUNGARIAN CAPITAL LETTER EB;Lu;0;R;;;;;N;;;;10CC2; +10C83;OLD HUNGARIAN CAPITAL LETTER AMB;Lu;0;R;;;;;N;;;;10CC3; +10C84;OLD HUNGARIAN CAPITAL LETTER EC;Lu;0;R;;;;;N;;;;10CC4; +10C85;OLD HUNGARIAN CAPITAL LETTER ENC;Lu;0;R;;;;;N;;;;10CC5; +10C86;OLD HUNGARIAN CAPITAL LETTER ECS;Lu;0;R;;;;;N;;;;10CC6; +10C87;OLD HUNGARIAN CAPITAL LETTER ED;Lu;0;R;;;;;N;;;;10CC7; +10C88;OLD HUNGARIAN CAPITAL LETTER AND;Lu;0;R;;;;;N;;;;10CC8; +10C89;OLD HUNGARIAN CAPITAL LETTER E;Lu;0;R;;;;;N;;;;10CC9; +10C8A;OLD HUNGARIAN CAPITAL LETTER CLOSE E;Lu;0;R;;;;;N;;;;10CCA; +10C8B;OLD HUNGARIAN CAPITAL LETTER EE;Lu;0;R;;;;;N;;;;10CCB; +10C8C;OLD HUNGARIAN CAPITAL LETTER EF;Lu;0;R;;;;;N;;;;10CCC; +10C8D;OLD HUNGARIAN CAPITAL LETTER EG;Lu;0;R;;;;;N;;;;10CCD; +10C8E;OLD HUNGARIAN CAPITAL LETTER EGY;Lu;0;R;;;;;N;;;;10CCE; +10C8F;OLD HUNGARIAN CAPITAL LETTER EH;Lu;0;R;;;;;N;;;;10CCF; +10C90;OLD HUNGARIAN CAPITAL LETTER I;Lu;0;R;;;;;N;;;;10CD0; +10C91;OLD HUNGARIAN CAPITAL LETTER II;Lu;0;R;;;;;N;;;;10CD1; +10C92;OLD HUNGARIAN CAPITAL LETTER EJ;Lu;0;R;;;;;N;;;;10CD2; +10C93;OLD HUNGARIAN CAPITAL LETTER EK;Lu;0;R;;;;;N;;;;10CD3; +10C94;OLD HUNGARIAN CAPITAL LETTER AK;Lu;0;R;;;;;N;;;;10CD4; +10C95;OLD HUNGARIAN CAPITAL LETTER UNK;Lu;0;R;;;;;N;;;;10CD5; +10C96;OLD HUNGARIAN CAPITAL LETTER EL;Lu;0;R;;;;;N;;;;10CD6; +10C97;OLD HUNGARIAN CAPITAL LETTER ELY;Lu;0;R;;;;;N;;;;10CD7; +10C98;OLD HUNGARIAN CAPITAL LETTER EM;Lu;0;R;;;;;N;;;;10CD8; +10C99;OLD HUNGARIAN CAPITAL LETTER EN;Lu;0;R;;;;;N;;;;10CD9; +10C9A;OLD HUNGARIAN CAPITAL LETTER ENY;Lu;0;R;;;;;N;;;;10CDA; +10C9B;OLD HUNGARIAN CAPITAL LETTER O;Lu;0;R;;;;;N;;;;10CDB; +10C9C;OLD HUNGARIAN CAPITAL LETTER OO;Lu;0;R;;;;;N;;;;10CDC; +10C9D;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE;Lu;0;R;;;;;N;;;;10CDD; +10C9E;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE;Lu;0;R;;;;;N;;;;10CDE; +10C9F;OLD HUNGARIAN CAPITAL LETTER OEE;Lu;0;R;;;;;N;;;;10CDF; +10CA0;OLD HUNGARIAN CAPITAL LETTER EP;Lu;0;R;;;;;N;;;;10CE0; +10CA1;OLD HUNGARIAN CAPITAL LETTER EMP;Lu;0;R;;;;;N;;;;10CE1; +10CA2;OLD HUNGARIAN CAPITAL LETTER ER;Lu;0;R;;;;;N;;;;10CE2; +10CA3;OLD HUNGARIAN CAPITAL LETTER SHORT ER;Lu;0;R;;;;;N;;;;10CE3; +10CA4;OLD HUNGARIAN CAPITAL LETTER ES;Lu;0;R;;;;;N;;;;10CE4; +10CA5;OLD HUNGARIAN CAPITAL LETTER ESZ;Lu;0;R;;;;;N;;;;10CE5; +10CA6;OLD HUNGARIAN CAPITAL LETTER ET;Lu;0;R;;;;;N;;;;10CE6; +10CA7;OLD HUNGARIAN CAPITAL LETTER ENT;Lu;0;R;;;;;N;;;;10CE7; +10CA8;OLD HUNGARIAN CAPITAL LETTER ETY;Lu;0;R;;;;;N;;;;10CE8; +10CA9;OLD HUNGARIAN CAPITAL LETTER ECH;Lu;0;R;;;;;N;;;;10CE9; +10CAA;OLD HUNGARIAN CAPITAL LETTER U;Lu;0;R;;;;;N;;;;10CEA; +10CAB;OLD HUNGARIAN CAPITAL LETTER UU;Lu;0;R;;;;;N;;;;10CEB; +10CAC;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE;Lu;0;R;;;;;N;;;;10CEC; +10CAD;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE;Lu;0;R;;;;;N;;;;10CED; +10CAE;OLD HUNGARIAN CAPITAL LETTER EV;Lu;0;R;;;;;N;;;;10CEE; +10CAF;OLD HUNGARIAN CAPITAL LETTER EZ;Lu;0;R;;;;;N;;;;10CEF; +10CB0;OLD HUNGARIAN CAPITAL LETTER EZS;Lu;0;R;;;;;N;;;;10CF0; +10CB1;OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN;Lu;0;R;;;;;N;;;;10CF1; +10CB2;OLD HUNGARIAN CAPITAL LETTER US;Lu;0;R;;;;;N;;;;10CF2; +10CC0;OLD HUNGARIAN SMALL LETTER A;Ll;0;R;;;;;N;;;10C80;;10C80 +10CC1;OLD HUNGARIAN SMALL LETTER AA;Ll;0;R;;;;;N;;;10C81;;10C81 +10CC2;OLD HUNGARIAN SMALL LETTER EB;Ll;0;R;;;;;N;;;10C82;;10C82 +10CC3;OLD HUNGARIAN SMALL LETTER AMB;Ll;0;R;;;;;N;;;10C83;;10C83 +10CC4;OLD HUNGARIAN SMALL LETTER EC;Ll;0;R;;;;;N;;;10C84;;10C84 +10CC5;OLD HUNGARIAN SMALL LETTER ENC;Ll;0;R;;;;;N;;;10C85;;10C85 +10CC6;OLD HUNGARIAN SMALL LETTER ECS;Ll;0;R;;;;;N;;;10C86;;10C86 +10CC7;OLD HUNGARIAN SMALL LETTER ED;Ll;0;R;;;;;N;;;10C87;;10C87 +10CC8;OLD HUNGARIAN SMALL LETTER AND;Ll;0;R;;;;;N;;;10C88;;10C88 +10CC9;OLD HUNGARIAN SMALL LETTER E;Ll;0;R;;;;;N;;;10C89;;10C89 +10CCA;OLD HUNGARIAN SMALL LETTER CLOSE E;Ll;0;R;;;;;N;;;10C8A;;10C8A +10CCB;OLD HUNGARIAN SMALL LETTER EE;Ll;0;R;;;;;N;;;10C8B;;10C8B +10CCC;OLD HUNGARIAN SMALL LETTER EF;Ll;0;R;;;;;N;;;10C8C;;10C8C +10CCD;OLD HUNGARIAN SMALL LETTER EG;Ll;0;R;;;;;N;;;10C8D;;10C8D +10CCE;OLD HUNGARIAN SMALL LETTER EGY;Ll;0;R;;;;;N;;;10C8E;;10C8E +10CCF;OLD HUNGARIAN SMALL LETTER EH;Ll;0;R;;;;;N;;;10C8F;;10C8F +10CD0;OLD HUNGARIAN SMALL LETTER I;Ll;0;R;;;;;N;;;10C90;;10C90 +10CD1;OLD HUNGARIAN SMALL LETTER II;Ll;0;R;;;;;N;;;10C91;;10C91 +10CD2;OLD HUNGARIAN SMALL LETTER EJ;Ll;0;R;;;;;N;;;10C92;;10C92 +10CD3;OLD HUNGARIAN SMALL LETTER EK;Ll;0;R;;;;;N;;;10C93;;10C93 +10CD4;OLD HUNGARIAN SMALL LETTER AK;Ll;0;R;;;;;N;;;10C94;;10C94 +10CD5;OLD HUNGARIAN SMALL LETTER UNK;Ll;0;R;;;;;N;;;10C95;;10C95 +10CD6;OLD HUNGARIAN SMALL LETTER EL;Ll;0;R;;;;;N;;;10C96;;10C96 +10CD7;OLD HUNGARIAN SMALL LETTER ELY;Ll;0;R;;;;;N;;;10C97;;10C97 +10CD8;OLD HUNGARIAN SMALL LETTER EM;Ll;0;R;;;;;N;;;10C98;;10C98 +10CD9;OLD HUNGARIAN SMALL LETTER EN;Ll;0;R;;;;;N;;;10C99;;10C99 +10CDA;OLD HUNGARIAN SMALL LETTER ENY;Ll;0;R;;;;;N;;;10C9A;;10C9A +10CDB;OLD HUNGARIAN SMALL LETTER O;Ll;0;R;;;;;N;;;10C9B;;10C9B +10CDC;OLD HUNGARIAN SMALL LETTER OO;Ll;0;R;;;;;N;;;10C9C;;10C9C +10CDD;OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE;Ll;0;R;;;;;N;;;10C9D;;10C9D +10CDE;OLD HUNGARIAN SMALL LETTER RUDIMENTA OE;Ll;0;R;;;;;N;;;10C9E;;10C9E +10CDF;OLD HUNGARIAN SMALL LETTER OEE;Ll;0;R;;;;;N;;;10C9F;;10C9F +10CE0;OLD HUNGARIAN SMALL LETTER EP;Ll;0;R;;;;;N;;;10CA0;;10CA0 +10CE1;OLD HUNGARIAN SMALL LETTER EMP;Ll;0;R;;;;;N;;;10CA1;;10CA1 +10CE2;OLD HUNGARIAN SMALL LETTER ER;Ll;0;R;;;;;N;;;10CA2;;10CA2 +10CE3;OLD HUNGARIAN SMALL LETTER SHORT ER;Ll;0;R;;;;;N;;;10CA3;;10CA3 +10CE4;OLD HUNGARIAN SMALL LETTER ES;Ll;0;R;;;;;N;;;10CA4;;10CA4 +10CE5;OLD HUNGARIAN SMALL LETTER ESZ;Ll;0;R;;;;;N;;;10CA5;;10CA5 +10CE6;OLD HUNGARIAN SMALL LETTER ET;Ll;0;R;;;;;N;;;10CA6;;10CA6 +10CE7;OLD HUNGARIAN SMALL LETTER ENT;Ll;0;R;;;;;N;;;10CA7;;10CA7 +10CE8;OLD HUNGARIAN SMALL LETTER ETY;Ll;0;R;;;;;N;;;10CA8;;10CA8 +10CE9;OLD HUNGARIAN SMALL LETTER ECH;Ll;0;R;;;;;N;;;10CA9;;10CA9 +10CEA;OLD HUNGARIAN SMALL LETTER U;Ll;0;R;;;;;N;;;10CAA;;10CAA +10CEB;OLD HUNGARIAN SMALL LETTER UU;Ll;0;R;;;;;N;;;10CAB;;10CAB +10CEC;OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE;Ll;0;R;;;;;N;;;10CAC;;10CAC +10CED;OLD HUNGARIAN SMALL LETTER RUDIMENTA UE;Ll;0;R;;;;;N;;;10CAD;;10CAD +10CEE;OLD HUNGARIAN SMALL LETTER EV;Ll;0;R;;;;;N;;;10CAE;;10CAE +10CEF;OLD HUNGARIAN SMALL LETTER EZ;Ll;0;R;;;;;N;;;10CAF;;10CAF +10CF0;OLD HUNGARIAN SMALL LETTER EZS;Ll;0;R;;;;;N;;;10CB0;;10CB0 +10CF1;OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN;Ll;0;R;;;;;N;;;10CB1;;10CB1 +10CF2;OLD HUNGARIAN SMALL LETTER US;Ll;0;R;;;;;N;;;10CB2;;10CB2 +10CFA;OLD HUNGARIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10CFB;OLD HUNGARIAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +10CFC;OLD HUNGARIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10CFD;OLD HUNGARIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;; +10CFE;OLD HUNGARIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10CFF;OLD HUNGARIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;; +10D00;HANIFI ROHINGYA LETTER A;Lo;0;AL;;;;;N;;;;; +10D01;HANIFI ROHINGYA LETTER BA;Lo;0;AL;;;;;N;;;;; +10D02;HANIFI ROHINGYA LETTER PA;Lo;0;AL;;;;;N;;;;; +10D03;HANIFI ROHINGYA LETTER TA;Lo;0;AL;;;;;N;;;;; +10D04;HANIFI ROHINGYA LETTER TTA;Lo;0;AL;;;;;N;;;;; +10D05;HANIFI ROHINGYA LETTER JA;Lo;0;AL;;;;;N;;;;; +10D06;HANIFI ROHINGYA LETTER CA;Lo;0;AL;;;;;N;;;;; +10D07;HANIFI ROHINGYA LETTER HA;Lo;0;AL;;;;;N;;;;; +10D08;HANIFI ROHINGYA LETTER KHA;Lo;0;AL;;;;;N;;;;; +10D09;HANIFI ROHINGYA LETTER FA;Lo;0;AL;;;;;N;;;;; +10D0A;HANIFI ROHINGYA LETTER DA;Lo;0;AL;;;;;N;;;;; +10D0B;HANIFI ROHINGYA LETTER DDA;Lo;0;AL;;;;;N;;;;; +10D0C;HANIFI ROHINGYA LETTER RA;Lo;0;AL;;;;;N;;;;; +10D0D;HANIFI ROHINGYA LETTER RRA;Lo;0;AL;;;;;N;;;;; +10D0E;HANIFI ROHINGYA LETTER ZA;Lo;0;AL;;;;;N;;;;; +10D0F;HANIFI ROHINGYA LETTER SA;Lo;0;AL;;;;;N;;;;; +10D10;HANIFI ROHINGYA LETTER SHA;Lo;0;AL;;;;;N;;;;; +10D11;HANIFI ROHINGYA LETTER KA;Lo;0;AL;;;;;N;;;;; +10D12;HANIFI ROHINGYA LETTER GA;Lo;0;AL;;;;;N;;;;; +10D13;HANIFI ROHINGYA LETTER LA;Lo;0;AL;;;;;N;;;;; +10D14;HANIFI ROHINGYA LETTER MA;Lo;0;AL;;;;;N;;;;; +10D15;HANIFI ROHINGYA LETTER NA;Lo;0;AL;;;;;N;;;;; +10D16;HANIFI ROHINGYA LETTER WA;Lo;0;AL;;;;;N;;;;; +10D17;HANIFI ROHINGYA LETTER KINNA WA;Lo;0;AL;;;;;N;;;;; +10D18;HANIFI ROHINGYA LETTER YA;Lo;0;AL;;;;;N;;;;; +10D19;HANIFI ROHINGYA LETTER KINNA YA;Lo;0;AL;;;;;N;;;;; +10D1A;HANIFI ROHINGYA LETTER NGA;Lo;0;AL;;;;;N;;;;; +10D1B;HANIFI ROHINGYA LETTER NYA;Lo;0;AL;;;;;N;;;;; +10D1C;HANIFI ROHINGYA LETTER VA;Lo;0;AL;;;;;N;;;;; +10D1D;HANIFI ROHINGYA VOWEL A;Lo;0;AL;;;;;N;;;;; +10D1E;HANIFI ROHINGYA VOWEL I;Lo;0;AL;;;;;N;;;;; +10D1F;HANIFI ROHINGYA VOWEL U;Lo;0;AL;;;;;N;;;;; +10D20;HANIFI ROHINGYA VOWEL E;Lo;0;AL;;;;;N;;;;; +10D21;HANIFI ROHINGYA VOWEL O;Lo;0;AL;;;;;N;;;;; +10D22;HANIFI ROHINGYA MARK SAKIN;Lo;0;AL;;;;;N;;;;; +10D23;HANIFI ROHINGYA MARK NA KHONNA;Lo;0;AL;;;;;N;;;;; +10D24;HANIFI ROHINGYA SIGN HARBAHAY;Mn;230;NSM;;;;;N;;;;; +10D25;HANIFI ROHINGYA SIGN TAHALA;Mn;230;NSM;;;;;N;;;;; +10D26;HANIFI ROHINGYA SIGN TANA;Mn;230;NSM;;;;;N;;;;; +10D27;HANIFI ROHINGYA SIGN TASSI;Mn;230;NSM;;;;;N;;;;; +10D30;HANIFI ROHINGYA DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; +10D31;HANIFI ROHINGYA DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; +10D32;HANIFI ROHINGYA DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; +10D33;HANIFI ROHINGYA DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; +10D34;HANIFI ROHINGYA DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; +10D35;HANIFI ROHINGYA DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; +10D36;HANIFI ROHINGYA DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; +10D37;HANIFI ROHINGYA DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; +10D38;HANIFI ROHINGYA DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; +10D39;HANIFI ROHINGYA DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; +10D40;GARAY DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; +10D41;GARAY DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; +10D42;GARAY DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; +10D43;GARAY DIGIT THREE;Nd;0;AN;;3;3;3;N;;;;; +10D44;GARAY DIGIT FOUR;Nd;0;AN;;4;4;4;N;;;;; +10D45;GARAY DIGIT FIVE;Nd;0;AN;;5;5;5;N;;;;; +10D46;GARAY DIGIT SIX;Nd;0;AN;;6;6;6;N;;;;; +10D47;GARAY DIGIT SEVEN;Nd;0;AN;;7;7;7;N;;;;; +10D48;GARAY DIGIT EIGHT;Nd;0;AN;;8;8;8;N;;;;; +10D49;GARAY DIGIT NINE;Nd;0;AN;;9;9;9;N;;;;; +10D4A;GARAY VOWEL SIGN A;Lo;0;R;;;;;N;;;;; +10D4B;GARAY VOWEL SIGN I;Lo;0;R;;;;;N;;;;; +10D4C;GARAY VOWEL SIGN O;Lo;0;R;;;;;N;;;;; +10D4D;GARAY VOWEL SIGN EE;Lo;0;R;;;;;N;;;;; +10D4E;GARAY VOWEL LENGTH MARK;Lm;0;R;;;;;N;;;;; +10D4F;GARAY SUKUN;Lo;0;R;;;;;N;;;;; +10D50;GARAY CAPITAL LETTER A;Lu;0;R;;;;;N;;;;10D70; +10D51;GARAY CAPITAL LETTER CA;Lu;0;R;;;;;N;;;;10D71; +10D52;GARAY CAPITAL LETTER MA;Lu;0;R;;;;;N;;;;10D72; +10D53;GARAY CAPITAL LETTER KA;Lu;0;R;;;;;N;;;;10D73; +10D54;GARAY CAPITAL LETTER BA;Lu;0;R;;;;;N;;;;10D74; +10D55;GARAY CAPITAL LETTER JA;Lu;0;R;;;;;N;;;;10D75; +10D56;GARAY CAPITAL LETTER SA;Lu;0;R;;;;;N;;;;10D76; +10D57;GARAY CAPITAL LETTER WA;Lu;0;R;;;;;N;;;;10D77; +10D58;GARAY CAPITAL LETTER LA;Lu;0;R;;;;;N;;;;10D78; +10D59;GARAY CAPITAL LETTER GA;Lu;0;R;;;;;N;;;;10D79; +10D5A;GARAY CAPITAL LETTER DA;Lu;0;R;;;;;N;;;;10D7A; +10D5B;GARAY CAPITAL LETTER XA;Lu;0;R;;;;;N;;;;10D7B; +10D5C;GARAY CAPITAL LETTER YA;Lu;0;R;;;;;N;;;;10D7C; +10D5D;GARAY CAPITAL LETTER TA;Lu;0;R;;;;;N;;;;10D7D; +10D5E;GARAY CAPITAL LETTER RA;Lu;0;R;;;;;N;;;;10D7E; +10D5F;GARAY CAPITAL LETTER NYA;Lu;0;R;;;;;N;;;;10D7F; +10D60;GARAY CAPITAL LETTER FA;Lu;0;R;;;;;N;;;;10D80; +10D61;GARAY CAPITAL LETTER NA;Lu;0;R;;;;;N;;;;10D81; +10D62;GARAY CAPITAL LETTER PA;Lu;0;R;;;;;N;;;;10D82; +10D63;GARAY CAPITAL LETTER HA;Lu;0;R;;;;;N;;;;10D83; +10D64;GARAY CAPITAL LETTER OLD KA;Lu;0;R;;;;;N;;;;10D84; +10D65;GARAY CAPITAL LETTER OLD NA;Lu;0;R;;;;;N;;;;10D85; +10D69;GARAY VOWEL SIGN E;Mn;230;NSM;;;;;N;;;;; +10D6A;GARAY CONSONANT GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +10D6B;GARAY COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +10D6C;GARAY COMBINING DOUBLE DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +10D6D;GARAY CONSONANT NASALIZATION MARK;Mn;230;NSM;;;;;N;;;;; +10D6E;GARAY HYPHEN;Pd;0;ON;;;;;N;;;;; +10D6F;GARAY REDUPLICATION MARK;Lm;0;R;;;;;N;;;;; +10D70;GARAY SMALL LETTER A;Ll;0;R;;;;;N;;;10D50;;10D50 +10D71;GARAY SMALL LETTER CA;Ll;0;R;;;;;N;;;10D51;;10D51 +10D72;GARAY SMALL LETTER MA;Ll;0;R;;;;;N;;;10D52;;10D52 +10D73;GARAY SMALL LETTER KA;Ll;0;R;;;;;N;;;10D53;;10D53 +10D74;GARAY SMALL LETTER BA;Ll;0;R;;;;;N;;;10D54;;10D54 +10D75;GARAY SMALL LETTER JA;Ll;0;R;;;;;N;;;10D55;;10D55 +10D76;GARAY SMALL LETTER SA;Ll;0;R;;;;;N;;;10D56;;10D56 +10D77;GARAY SMALL LETTER WA;Ll;0;R;;;;;N;;;10D57;;10D57 +10D78;GARAY SMALL LETTER LA;Ll;0;R;;;;;N;;;10D58;;10D58 +10D79;GARAY SMALL LETTER GA;Ll;0;R;;;;;N;;;10D59;;10D59 +10D7A;GARAY SMALL LETTER DA;Ll;0;R;;;;;N;;;10D5A;;10D5A +10D7B;GARAY SMALL LETTER XA;Ll;0;R;;;;;N;;;10D5B;;10D5B +10D7C;GARAY SMALL LETTER YA;Ll;0;R;;;;;N;;;10D5C;;10D5C +10D7D;GARAY SMALL LETTER TA;Ll;0;R;;;;;N;;;10D5D;;10D5D +10D7E;GARAY SMALL LETTER RA;Ll;0;R;;;;;N;;;10D5E;;10D5E +10D7F;GARAY SMALL LETTER NYA;Ll;0;R;;;;;N;;;10D5F;;10D5F +10D80;GARAY SMALL LETTER FA;Ll;0;R;;;;;N;;;10D60;;10D60 +10D81;GARAY SMALL LETTER NA;Ll;0;R;;;;;N;;;10D61;;10D61 +10D82;GARAY SMALL LETTER PA;Ll;0;R;;;;;N;;;10D62;;10D62 +10D83;GARAY SMALL LETTER HA;Ll;0;R;;;;;N;;;10D63;;10D63 +10D84;GARAY SMALL LETTER OLD KA;Ll;0;R;;;;;N;;;10D64;;10D64 +10D85;GARAY SMALL LETTER OLD NA;Ll;0;R;;;;;N;;;10D65;;10D65 +10D8E;GARAY PLUS SIGN;Sm;0;R;;;;;N;;;;; +10D8F;GARAY MINUS SIGN;Sm;0;R;;;;;N;;;;; +10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;; +10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;; +10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;; +10E63;RUMI DIGIT FOUR;No;0;AN;;;4;4;N;;;;; +10E64;RUMI DIGIT FIVE;No;0;AN;;;5;5;N;;;;; +10E65;RUMI DIGIT SIX;No;0;AN;;;6;6;N;;;;; +10E66;RUMI DIGIT SEVEN;No;0;AN;;;7;7;N;;;;; +10E67;RUMI DIGIT EIGHT;No;0;AN;;;8;8;N;;;;; +10E68;RUMI DIGIT NINE;No;0;AN;;;9;9;N;;;;; +10E69;RUMI NUMBER TEN;No;0;AN;;;;10;N;;;;; +10E6A;RUMI NUMBER TWENTY;No;0;AN;;;;20;N;;;;; +10E6B;RUMI NUMBER THIRTY;No;0;AN;;;;30;N;;;;; +10E6C;RUMI NUMBER FORTY;No;0;AN;;;;40;N;;;;; +10E6D;RUMI NUMBER FIFTY;No;0;AN;;;;50;N;;;;; +10E6E;RUMI NUMBER SIXTY;No;0;AN;;;;60;N;;;;; +10E6F;RUMI NUMBER SEVENTY;No;0;AN;;;;70;N;;;;; +10E70;RUMI NUMBER EIGHTY;No;0;AN;;;;80;N;;;;; +10E71;RUMI NUMBER NINETY;No;0;AN;;;;90;N;;;;; +10E72;RUMI NUMBER ONE HUNDRED;No;0;AN;;;;100;N;;;;; +10E73;RUMI NUMBER TWO HUNDRED;No;0;AN;;;;200;N;;;;; +10E74;RUMI NUMBER THREE HUNDRED;No;0;AN;;;;300;N;;;;; +10E75;RUMI NUMBER FOUR HUNDRED;No;0;AN;;;;400;N;;;;; +10E76;RUMI NUMBER FIVE HUNDRED;No;0;AN;;;;500;N;;;;; +10E77;RUMI NUMBER SIX HUNDRED;No;0;AN;;;;600;N;;;;; +10E78;RUMI NUMBER SEVEN HUNDRED;No;0;AN;;;;700;N;;;;; +10E79;RUMI NUMBER EIGHT HUNDRED;No;0;AN;;;;800;N;;;;; +10E7A;RUMI NUMBER NINE HUNDRED;No;0;AN;;;;900;N;;;;; +10E7B;RUMI FRACTION ONE HALF;No;0;AN;;;;1/2;N;;;;; +10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; +10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; +10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; +10E80;YEZIDI LETTER ELIF;Lo;0;R;;;;;N;;;;; +10E81;YEZIDI LETTER BE;Lo;0;R;;;;;N;;;;; +10E82;YEZIDI LETTER PE;Lo;0;R;;;;;N;;;;; +10E83;YEZIDI LETTER PHE;Lo;0;R;;;;;N;;;;; +10E84;YEZIDI LETTER THE;Lo;0;R;;;;;N;;;;; +10E85;YEZIDI LETTER SE;Lo;0;R;;;;;N;;;;; +10E86;YEZIDI LETTER CIM;Lo;0;R;;;;;N;;;;; +10E87;YEZIDI LETTER CHIM;Lo;0;R;;;;;N;;;;; +10E88;YEZIDI LETTER CHHIM;Lo;0;R;;;;;N;;;;; +10E89;YEZIDI LETTER HHA;Lo;0;R;;;;;N;;;;; +10E8A;YEZIDI LETTER XA;Lo;0;R;;;;;N;;;;; +10E8B;YEZIDI LETTER DAL;Lo;0;R;;;;;N;;;;; +10E8C;YEZIDI LETTER ZAL;Lo;0;R;;;;;N;;;;; +10E8D;YEZIDI LETTER RA;Lo;0;R;;;;;N;;;;; +10E8E;YEZIDI LETTER RHA;Lo;0;R;;;;;N;;;;; +10E8F;YEZIDI LETTER ZA;Lo;0;R;;;;;N;;;;; +10E90;YEZIDI LETTER JA;Lo;0;R;;;;;N;;;;; +10E91;YEZIDI LETTER SIN;Lo;0;R;;;;;N;;;;; +10E92;YEZIDI LETTER SHIN;Lo;0;R;;;;;N;;;;; +10E93;YEZIDI LETTER SAD;Lo;0;R;;;;;N;;;;; +10E94;YEZIDI LETTER DAD;Lo;0;R;;;;;N;;;;; +10E95;YEZIDI LETTER TA;Lo;0;R;;;;;N;;;;; +10E96;YEZIDI LETTER ZE;Lo;0;R;;;;;N;;;;; +10E97;YEZIDI LETTER EYN;Lo;0;R;;;;;N;;;;; +10E98;YEZIDI LETTER XHEYN;Lo;0;R;;;;;N;;;;; +10E99;YEZIDI LETTER FA;Lo;0;R;;;;;N;;;;; +10E9A;YEZIDI LETTER VA;Lo;0;R;;;;;N;;;;; +10E9B;YEZIDI LETTER VA ALTERNATE FORM;Lo;0;R;;;;;N;;;;; +10E9C;YEZIDI LETTER QAF;Lo;0;R;;;;;N;;;;; +10E9D;YEZIDI LETTER KAF;Lo;0;R;;;;;N;;;;; +10E9E;YEZIDI LETTER KHAF;Lo;0;R;;;;;N;;;;; +10E9F;YEZIDI LETTER GAF;Lo;0;R;;;;;N;;;;; +10EA0;YEZIDI LETTER LAM;Lo;0;R;;;;;N;;;;; +10EA1;YEZIDI LETTER MIM;Lo;0;R;;;;;N;;;;; +10EA2;YEZIDI LETTER NUN;Lo;0;R;;;;;N;;;;; +10EA3;YEZIDI LETTER UM;Lo;0;R;;;;;N;;;;; +10EA4;YEZIDI LETTER WAW;Lo;0;R;;;;;N;;;;; +10EA5;YEZIDI LETTER OW;Lo;0;R;;;;;N;;;;; +10EA6;YEZIDI LETTER EW;Lo;0;R;;;;;N;;;;; +10EA7;YEZIDI LETTER HAY;Lo;0;R;;;;;N;;;;; +10EA8;YEZIDI LETTER YOT;Lo;0;R;;;;;N;;;;; +10EA9;YEZIDI LETTER ET;Lo;0;R;;;;;N;;;;; +10EAB;YEZIDI COMBINING HAMZA MARK;Mn;230;NSM;;;;;N;;;;; +10EAC;YEZIDI COMBINING MADDA MARK;Mn;230;NSM;;;;;N;;;;; +10EAD;YEZIDI HYPHENATION MARK;Pd;0;R;;;;;N;;;;; +10EB0;YEZIDI LETTER LAM WITH DOT ABOVE;Lo;0;R;;;;;N;;;;; +10EB1;YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE;Lo;0;R;;;;;N;;;;; +10EC2;ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;; +10EC3;ARABIC LETTER TAH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;; +10EC4;ARABIC LETTER KAF WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;; +10EC5;ARABIC SMALL YEH BARREE WITH TWO DOTS BELOW;Lm;0;AL;;;;;N;;;;; +10EC6;ARABIC LETTER THIN NOON;Lo;0;AL;;;;;N;;;;; +10EC7;ARABIC LETTER YEH WITH FOUR DOTS BELOW;Lo;0;AL;;;;;N;;;;; +10ED0;ARABIC BIBLICAL END OF VERSE;Po;0;ON;;;;;N;;;;; +10ED1;ARABIC LIGATURE ALAYHAA AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;; +10ED2;ARABIC LIGATURE ALAYHIM AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;; +10ED3;ARABIC LIGATURE ALAYHIMAA AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;; +10ED4;ARABIC LIGATURE QADDASA ALLAAHU SIRRAH;So;0;ON;;;;;N;;;;; +10ED5;ARABIC LIGATURE QUDDISA SIRRUHUM;So;0;ON;;;;;N;;;;; +10ED6;ARABIC LIGATURE QUDDISA SIRRUHUMAA;So;0;ON;;;;;N;;;;; +10ED7;ARABIC LIGATURE QUDDISAT ASRAARUHUM;So;0;ON;;;;;N;;;;; +10ED8;ARABIC LIGATURE NAWWARA ALLAAHU MARQADAH;So;0;ON;;;;;N;;;;; +10EFA;ARABIC DOUBLE VERTICAL BAR BELOW;Mn;220;NSM;;;;;N;;;;; +10EFB;ARABIC SMALL LOW NOON;Mn;220;NSM;;;;;N;;;;; +10EFC;ARABIC COMBINING ALEF OVERLAY;Mn;0;NSM;;;;;N;;;;; +10EFD;ARABIC SMALL LOW WORD SAKTA;Mn;220;NSM;;;;;N;;;;; +10EFE;ARABIC SMALL LOW WORD QASR;Mn;220;NSM;;;;;N;;;;; +10EFF;ARABIC SMALL LOW WORD MADDA;Mn;220;NSM;;;;;N;;;;; +10F00;OLD SOGDIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10F01;OLD SOGDIAN LETTER FINAL ALEPH;Lo;0;R;;;;;N;;;;; +10F02;OLD SOGDIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10F03;OLD SOGDIAN LETTER FINAL BETH;Lo;0;R;;;;;N;;;;; +10F04;OLD SOGDIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10F05;OLD SOGDIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10F06;OLD SOGDIAN LETTER FINAL HE;Lo;0;R;;;;;N;;;;; +10F07;OLD SOGDIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10F08;OLD SOGDIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10F09;OLD SOGDIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10F0A;OLD SOGDIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10F0B;OLD SOGDIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10F0C;OLD SOGDIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10F0D;OLD SOGDIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10F0E;OLD SOGDIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10F0F;OLD SOGDIAN LETTER FINAL NUN;Lo;0;R;;;;;N;;;;; +10F10;OLD SOGDIAN LETTER FINAL NUN WITH VERTICAL TAIL;Lo;0;R;;;;;N;;;;; +10F11;OLD SOGDIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10F12;OLD SOGDIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10F13;OLD SOGDIAN LETTER ALTERNATE AYIN;Lo;0;R;;;;;N;;;;; +10F14;OLD SOGDIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10F15;OLD SOGDIAN LETTER SADHE;Lo;0;R;;;;;N;;;;; +10F16;OLD SOGDIAN LETTER FINAL SADHE;Lo;0;R;;;;;N;;;;; +10F17;OLD SOGDIAN LETTER FINAL SADHE WITH VERTICAL TAIL;Lo;0;R;;;;;N;;;;; +10F18;OLD SOGDIAN LETTER RESH-AYIN-DALETH;Lo;0;R;;;;;N;;;;; +10F19;OLD SOGDIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10F1A;OLD SOGDIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10F1B;OLD SOGDIAN LETTER FINAL TAW;Lo;0;R;;;;;N;;;;; +10F1C;OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL;Lo;0;R;;;;;N;;;;; +10F1D;OLD SOGDIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10F1E;OLD SOGDIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +10F1F;OLD SOGDIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +10F20;OLD SOGDIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +10F21;OLD SOGDIAN NUMBER FIVE;No;0;R;;;;5;N;;;;; +10F22;OLD SOGDIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10F23;OLD SOGDIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10F24;OLD SOGDIAN NUMBER THIRTY;No;0;R;;;;30;N;;;;; +10F25;OLD SOGDIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10F26;OLD SOGDIAN FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;; +10F27;OLD SOGDIAN LIGATURE AYIN-DALETH;Lo;0;R;;;;;N;;;;; +10F30;SOGDIAN LETTER ALEPH;Lo;0;AL;;;;;N;;;;; +10F31;SOGDIAN LETTER BETH;Lo;0;AL;;;;;N;;;;; +10F32;SOGDIAN LETTER GIMEL;Lo;0;AL;;;;;N;;;;; +10F33;SOGDIAN LETTER HE;Lo;0;AL;;;;;N;;;;; +10F34;SOGDIAN LETTER WAW;Lo;0;AL;;;;;N;;;;; +10F35;SOGDIAN LETTER ZAYIN;Lo;0;AL;;;;;N;;;;; +10F36;SOGDIAN LETTER HETH;Lo;0;AL;;;;;N;;;;; +10F37;SOGDIAN LETTER YODH;Lo;0;AL;;;;;N;;;;; +10F38;SOGDIAN LETTER KAPH;Lo;0;AL;;;;;N;;;;; +10F39;SOGDIAN LETTER LAMEDH;Lo;0;AL;;;;;N;;;;; +10F3A;SOGDIAN LETTER MEM;Lo;0;AL;;;;;N;;;;; +10F3B;SOGDIAN LETTER NUN;Lo;0;AL;;;;;N;;;;; +10F3C;SOGDIAN LETTER SAMEKH;Lo;0;AL;;;;;N;;;;; +10F3D;SOGDIAN LETTER AYIN;Lo;0;AL;;;;;N;;;;; +10F3E;SOGDIAN LETTER PE;Lo;0;AL;;;;;N;;;;; +10F3F;SOGDIAN LETTER SADHE;Lo;0;AL;;;;;N;;;;; +10F40;SOGDIAN LETTER RESH-AYIN;Lo;0;AL;;;;;N;;;;; +10F41;SOGDIAN LETTER SHIN;Lo;0;AL;;;;;N;;;;; +10F42;SOGDIAN LETTER TAW;Lo;0;AL;;;;;N;;;;; +10F43;SOGDIAN LETTER FETH;Lo;0;AL;;;;;N;;;;; +10F44;SOGDIAN LETTER LESH;Lo;0;AL;;;;;N;;;;; +10F45;SOGDIAN INDEPENDENT SHIN;Lo;0;AL;;;;;N;;;;; +10F46;SOGDIAN COMBINING DOT BELOW;Mn;220;NSM;;;;;N;;;;; +10F47;SOGDIAN COMBINING TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +10F48;SOGDIAN COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +10F49;SOGDIAN COMBINING TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +10F4A;SOGDIAN COMBINING CURVE ABOVE;Mn;230;NSM;;;;;N;;;;; +10F4B;SOGDIAN COMBINING CURVE BELOW;Mn;220;NSM;;;;;N;;;;; +10F4C;SOGDIAN COMBINING HOOK ABOVE;Mn;230;NSM;;;;;N;;;;; +10F4D;SOGDIAN COMBINING HOOK BELOW;Mn;220;NSM;;;;;N;;;;; +10F4E;SOGDIAN COMBINING LONG HOOK BELOW;Mn;220;NSM;;;;;N;;;;; +10F4F;SOGDIAN COMBINING RESH BELOW;Mn;220;NSM;;;;;N;;;;; +10F50;SOGDIAN COMBINING STROKE BELOW;Mn;220;NSM;;;;;N;;;;; +10F51;SOGDIAN NUMBER ONE;No;0;AL;;;;1;N;;;;; +10F52;SOGDIAN NUMBER TEN;No;0;AL;;;;10;N;;;;; +10F53;SOGDIAN NUMBER TWENTY;No;0;AL;;;;20;N;;;;; +10F54;SOGDIAN NUMBER ONE HUNDRED;No;0;AL;;;;100;N;;;;; +10F55;SOGDIAN PUNCTUATION TWO VERTICAL BARS;Po;0;AL;;;;;N;;;;; +10F56;SOGDIAN PUNCTUATION TWO VERTICAL BARS WITH DOTS;Po;0;AL;;;;;N;;;;; +10F57;SOGDIAN PUNCTUATION CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;; +10F58;SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS;Po;0;AL;;;;;N;;;;; +10F59;SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;; +10F70;OLD UYGHUR LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10F71;OLD UYGHUR LETTER BETH;Lo;0;R;;;;;N;;;;; +10F72;OLD UYGHUR LETTER GIMEL-HETH;Lo;0;R;;;;;N;;;;; +10F73;OLD UYGHUR LETTER WAW;Lo;0;R;;;;;N;;;;; +10F74;OLD UYGHUR LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10F75;OLD UYGHUR LETTER FINAL HETH;Lo;0;R;;;;;N;;;;; +10F76;OLD UYGHUR LETTER YODH;Lo;0;R;;;;;N;;;;; +10F77;OLD UYGHUR LETTER KAPH;Lo;0;R;;;;;N;;;;; +10F78;OLD UYGHUR LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10F79;OLD UYGHUR LETTER MEM;Lo;0;R;;;;;N;;;;; +10F7A;OLD UYGHUR LETTER NUN;Lo;0;R;;;;;N;;;;; +10F7B;OLD UYGHUR LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10F7C;OLD UYGHUR LETTER PE;Lo;0;R;;;;;N;;;;; +10F7D;OLD UYGHUR LETTER SADHE;Lo;0;R;;;;;N;;;;; +10F7E;OLD UYGHUR LETTER RESH;Lo;0;R;;;;;N;;;;; +10F7F;OLD UYGHUR LETTER SHIN;Lo;0;R;;;;;N;;;;; +10F80;OLD UYGHUR LETTER TAW;Lo;0;R;;;;;N;;;;; +10F81;OLD UYGHUR LETTER LESH;Lo;0;R;;;;;N;;;;; +10F82;OLD UYGHUR COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;;;;; +10F83;OLD UYGHUR COMBINING DOT BELOW;Mn;220;NSM;;;;;N;;;;; +10F84;OLD UYGHUR COMBINING TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;; +10F85;OLD UYGHUR COMBINING TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;; +10F86;OLD UYGHUR PUNCTUATION BAR;Po;0;R;;;;;N;;;;; +10F87;OLD UYGHUR PUNCTUATION TWO BARS;Po;0;R;;;;;N;;;;; +10F88;OLD UYGHUR PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;; +10F89;OLD UYGHUR PUNCTUATION FOUR DOTS;Po;0;R;;;;;N;;;;; +10FB0;CHORASMIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10FB1;CHORASMIAN LETTER SMALL ALEPH;Lo;0;R;;;;;N;;;;; +10FB2;CHORASMIAN LETTER BETH;Lo;0;R;;;;;N;;;;; +10FB3;CHORASMIAN LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10FB4;CHORASMIAN LETTER DALETH;Lo;0;R;;;;;N;;;;; +10FB5;CHORASMIAN LETTER HE;Lo;0;R;;;;;N;;;;; +10FB6;CHORASMIAN LETTER WAW;Lo;0;R;;;;;N;;;;; +10FB7;CHORASMIAN LETTER CURLED WAW;Lo;0;R;;;;;N;;;;; +10FB8;CHORASMIAN LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10FB9;CHORASMIAN LETTER HETH;Lo;0;R;;;;;N;;;;; +10FBA;CHORASMIAN LETTER YODH;Lo;0;R;;;;;N;;;;; +10FBB;CHORASMIAN LETTER KAPH;Lo;0;R;;;;;N;;;;; +10FBC;CHORASMIAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10FBD;CHORASMIAN LETTER MEM;Lo;0;R;;;;;N;;;;; +10FBE;CHORASMIAN LETTER NUN;Lo;0;R;;;;;N;;;;; +10FBF;CHORASMIAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10FC0;CHORASMIAN LETTER AYIN;Lo;0;R;;;;;N;;;;; +10FC1;CHORASMIAN LETTER PE;Lo;0;R;;;;;N;;;;; +10FC2;CHORASMIAN LETTER RESH;Lo;0;R;;;;;N;;;;; +10FC3;CHORASMIAN LETTER SHIN;Lo;0;R;;;;;N;;;;; +10FC4;CHORASMIAN LETTER TAW;Lo;0;R;;;;;N;;;;; +10FC5;CHORASMIAN NUMBER ONE;No;0;R;;;;1;N;;;;; +10FC6;CHORASMIAN NUMBER TWO;No;0;R;;;;2;N;;;;; +10FC7;CHORASMIAN NUMBER THREE;No;0;R;;;;3;N;;;;; +10FC8;CHORASMIAN NUMBER FOUR;No;0;R;;;;4;N;;;;; +10FC9;CHORASMIAN NUMBER TEN;No;0;R;;;;10;N;;;;; +10FCA;CHORASMIAN NUMBER TWENTY;No;0;R;;;;20;N;;;;; +10FCB;CHORASMIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;; +10FE0;ELYMAIC LETTER ALEPH;Lo;0;R;;;;;N;;;;; +10FE1;ELYMAIC LETTER BETH;Lo;0;R;;;;;N;;;;; +10FE2;ELYMAIC LETTER GIMEL;Lo;0;R;;;;;N;;;;; +10FE3;ELYMAIC LETTER DALETH;Lo;0;R;;;;;N;;;;; +10FE4;ELYMAIC LETTER HE;Lo;0;R;;;;;N;;;;; +10FE5;ELYMAIC LETTER WAW;Lo;0;R;;;;;N;;;;; +10FE6;ELYMAIC LETTER ZAYIN;Lo;0;R;;;;;N;;;;; +10FE7;ELYMAIC LETTER HETH;Lo;0;R;;;;;N;;;;; +10FE8;ELYMAIC LETTER TETH;Lo;0;R;;;;;N;;;;; +10FE9;ELYMAIC LETTER YODH;Lo;0;R;;;;;N;;;;; +10FEA;ELYMAIC LETTER KAPH;Lo;0;R;;;;;N;;;;; +10FEB;ELYMAIC LETTER LAMEDH;Lo;0;R;;;;;N;;;;; +10FEC;ELYMAIC LETTER MEM;Lo;0;R;;;;;N;;;;; +10FED;ELYMAIC LETTER NUN;Lo;0;R;;;;;N;;;;; +10FEE;ELYMAIC LETTER SAMEKH;Lo;0;R;;;;;N;;;;; +10FEF;ELYMAIC LETTER AYIN;Lo;0;R;;;;;N;;;;; +10FF0;ELYMAIC LETTER PE;Lo;0;R;;;;;N;;;;; +10FF1;ELYMAIC LETTER SADHE;Lo;0;R;;;;;N;;;;; +10FF2;ELYMAIC LETTER QOPH;Lo;0;R;;;;;N;;;;; +10FF3;ELYMAIC LETTER RESH;Lo;0;R;;;;;N;;;;; +10FF4;ELYMAIC LETTER SHIN;Lo;0;R;;;;;N;;;;; +10FF5;ELYMAIC LETTER TAW;Lo;0;R;;;;;N;;;;; +10FF6;ELYMAIC LIGATURE ZAYIN-YODH;Lo;0;R;;;;;N;;;;; +11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; +11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;; +11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;; +11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;; +11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;; +11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;; +1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;; +1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;; +11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;; +11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;; +11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;; +11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;; +11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;; +11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;; +11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;; +11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;; +11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;; +11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;; +1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;; +1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;; +1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;; +1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;; +1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;; +11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;; +11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;; +11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;; +11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;; +11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;; +11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;; +11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;; +11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;; +11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;; +1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;; +1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;; +1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;; +1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;; +1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;; +1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;; +11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;; +11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;; +11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;; +11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;; +11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;; +11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;; +11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;; +11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;; +11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;; +1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;; +11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; +1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; +1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;; +1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;; +1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;; +11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;; +11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;; +11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;; +11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;; +11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;; +11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;; +11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;; +11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;; +1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;; +1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;; +1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;; +1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;; +1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;; +1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;; +11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;; +11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;; +11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;; +11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;; +11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;; +11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;; +11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11070;BRAHMI SIGN OLD TAMIL VIRAMA;Mn;9;NSM;;;;;N;;;;; +11071;BRAHMI LETTER OLD TAMIL SHORT E;Lo;0;L;;;;;N;;;;; +11072;BRAHMI LETTER OLD TAMIL SHORT O;Lo;0;L;;;;;N;;;;; +11073;BRAHMI VOWEL SIGN OLD TAMIL SHORT E;Mn;0;NSM;;;;;N;;;;; +11074;BRAHMI VOWEL SIGN OLD TAMIL SHORT O;Mn;0;NSM;;;;;N;;;;; +11075;BRAHMI LETTER OLD TAMIL LLA;Lo;0;L;;;;;N;;;;; +1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;; +11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11083;KAITHI LETTER A;Lo;0;L;;;;;N;;;;; +11084;KAITHI LETTER AA;Lo;0;L;;;;;N;;;;; +11085;KAITHI LETTER I;Lo;0;L;;;;;N;;;;; +11086;KAITHI LETTER II;Lo;0;L;;;;;N;;;;; +11087;KAITHI LETTER U;Lo;0;L;;;;;N;;;;; +11088;KAITHI LETTER UU;Lo;0;L;;;;;N;;;;; +11089;KAITHI LETTER E;Lo;0;L;;;;;N;;;;; +1108A;KAITHI LETTER AI;Lo;0;L;;;;;N;;;;; +1108B;KAITHI LETTER O;Lo;0;L;;;;;N;;;;; +1108C;KAITHI LETTER AU;Lo;0;L;;;;;N;;;;; +1108D;KAITHI LETTER KA;Lo;0;L;;;;;N;;;;; +1108E;KAITHI LETTER KHA;Lo;0;L;;;;;N;;;;; +1108F;KAITHI LETTER GA;Lo;0;L;;;;;N;;;;; +11090;KAITHI LETTER GHA;Lo;0;L;;;;;N;;;;; +11091;KAITHI LETTER NGA;Lo;0;L;;;;;N;;;;; +11092;KAITHI LETTER CA;Lo;0;L;;;;;N;;;;; +11093;KAITHI LETTER CHA;Lo;0;L;;;;;N;;;;; +11094;KAITHI LETTER JA;Lo;0;L;;;;;N;;;;; +11095;KAITHI LETTER JHA;Lo;0;L;;;;;N;;;;; +11096;KAITHI LETTER NYA;Lo;0;L;;;;;N;;;;; +11097;KAITHI LETTER TTA;Lo;0;L;;;;;N;;;;; +11098;KAITHI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11099;KAITHI LETTER DDA;Lo;0;L;;;;;N;;;;; +1109A;KAITHI LETTER DDDHA;Lo;0;L;11099 110BA;;;;N;;;;; +1109B;KAITHI LETTER DDHA;Lo;0;L;;;;;N;;;;; +1109C;KAITHI LETTER RHA;Lo;0;L;1109B 110BA;;;;N;;;;; +1109D;KAITHI LETTER NNA;Lo;0;L;;;;;N;;;;; +1109E;KAITHI LETTER TA;Lo;0;L;;;;;N;;;;; +1109F;KAITHI LETTER THA;Lo;0;L;;;;;N;;;;; +110A0;KAITHI LETTER DA;Lo;0;L;;;;;N;;;;; +110A1;KAITHI LETTER DHA;Lo;0;L;;;;;N;;;;; +110A2;KAITHI LETTER NA;Lo;0;L;;;;;N;;;;; +110A3;KAITHI LETTER PA;Lo;0;L;;;;;N;;;;; +110A4;KAITHI LETTER PHA;Lo;0;L;;;;;N;;;;; +110A5;KAITHI LETTER BA;Lo;0;L;;;;;N;;;;; +110A6;KAITHI LETTER BHA;Lo;0;L;;;;;N;;;;; +110A7;KAITHI LETTER MA;Lo;0;L;;;;;N;;;;; +110A8;KAITHI LETTER YA;Lo;0;L;;;;;N;;;;; +110A9;KAITHI LETTER RA;Lo;0;L;;;;;N;;;;; +110AA;KAITHI LETTER LA;Lo;0;L;;;;;N;;;;; +110AB;KAITHI LETTER VA;Lo;0;L;110A5 110BA;;;;N;;;;; +110AC;KAITHI LETTER SHA;Lo;0;L;;;;;N;;;;; +110AD;KAITHI LETTER SSA;Lo;0;L;;;;;N;;;;; +110AE;KAITHI LETTER SA;Lo;0;L;;;;;N;;;;; +110AF;KAITHI LETTER HA;Lo;0;L;;;;;N;;;;; +110B0;KAITHI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +110B1;KAITHI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +110B2;KAITHI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +110B3;KAITHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +110B4;KAITHI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +110B5;KAITHI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +110B6;KAITHI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +110B7;KAITHI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +110B8;KAITHI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +110B9;KAITHI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +110BA;KAITHI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +110BB;KAITHI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +110BC;KAITHI ENUMERATION SIGN;Po;0;L;;;;;N;;;;; +110BD;KAITHI NUMBER SIGN;Cf;0;L;;;;;N;;;;; +110BE;KAITHI SECTION MARK;Po;0;L;;;;;N;;;;; +110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; +110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;; +110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +110C2;KAITHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +110CD;KAITHI NUMBER SIGN ABOVE;Cf;0;L;;;;;N;;;;; +110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;; +110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;; +110D2;SORA SOMPENG LETTER BAH;Lo;0;L;;;;;N;;;;; +110D3;SORA SOMPENG LETTER CAH;Lo;0;L;;;;;N;;;;; +110D4;SORA SOMPENG LETTER DAH;Lo;0;L;;;;;N;;;;; +110D5;SORA SOMPENG LETTER GAH;Lo;0;L;;;;;N;;;;; +110D6;SORA SOMPENG LETTER MAH;Lo;0;L;;;;;N;;;;; +110D7;SORA SOMPENG LETTER NGAH;Lo;0;L;;;;;N;;;;; +110D8;SORA SOMPENG LETTER LAH;Lo;0;L;;;;;N;;;;; +110D9;SORA SOMPENG LETTER NAH;Lo;0;L;;;;;N;;;;; +110DA;SORA SOMPENG LETTER VAH;Lo;0;L;;;;;N;;;;; +110DB;SORA SOMPENG LETTER PAH;Lo;0;L;;;;;N;;;;; +110DC;SORA SOMPENG LETTER YAH;Lo;0;L;;;;;N;;;;; +110DD;SORA SOMPENG LETTER RAH;Lo;0;L;;;;;N;;;;; +110DE;SORA SOMPENG LETTER HAH;Lo;0;L;;;;;N;;;;; +110DF;SORA SOMPENG LETTER KAH;Lo;0;L;;;;;N;;;;; +110E0;SORA SOMPENG LETTER JAH;Lo;0;L;;;;;N;;;;; +110E1;SORA SOMPENG LETTER NYAH;Lo;0;L;;;;;N;;;;; +110E2;SORA SOMPENG LETTER AH;Lo;0;L;;;;;N;;;;; +110E3;SORA SOMPENG LETTER EEH;Lo;0;L;;;;;N;;;;; +110E4;SORA SOMPENG LETTER IH;Lo;0;L;;;;;N;;;;; +110E5;SORA SOMPENG LETTER UH;Lo;0;L;;;;;N;;;;; +110E6;SORA SOMPENG LETTER OH;Lo;0;L;;;;;N;;;;; +110E7;SORA SOMPENG LETTER EH;Lo;0;L;;;;;N;;;;; +110E8;SORA SOMPENG LETTER MAE;Lo;0;L;;;;;N;;;;; +110F0;SORA SOMPENG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +110F1;SORA SOMPENG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +110F2;SORA SOMPENG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +110F3;SORA SOMPENG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +110F4;SORA SOMPENG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +110F5;SORA SOMPENG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +110F6;SORA SOMPENG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +110F7;SORA SOMPENG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +110F8;SORA SOMPENG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +110F9;SORA SOMPENG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11100;CHAKMA SIGN CANDRABINDU;Mn;230;NSM;;;;;N;;;;; +11101;CHAKMA SIGN ANUSVARA;Mn;230;NSM;;;;;N;;;;; +11102;CHAKMA SIGN VISARGA;Mn;230;NSM;;;;;N;;;;; +11103;CHAKMA LETTER AA;Lo;0;L;;;;;N;;;;; +11104;CHAKMA LETTER I;Lo;0;L;;;;;N;;;;; +11105;CHAKMA LETTER U;Lo;0;L;;;;;N;;;;; +11106;CHAKMA LETTER E;Lo;0;L;;;;;N;;;;; +11107;CHAKMA LETTER KAA;Lo;0;L;;;;;N;;;;; +11108;CHAKMA LETTER KHAA;Lo;0;L;;;;;N;;;;; +11109;CHAKMA LETTER GAA;Lo;0;L;;;;;N;;;;; +1110A;CHAKMA LETTER GHAA;Lo;0;L;;;;;N;;;;; +1110B;CHAKMA LETTER NGAA;Lo;0;L;;;;;N;;;;; +1110C;CHAKMA LETTER CAA;Lo;0;L;;;;;N;;;;; +1110D;CHAKMA LETTER CHAA;Lo;0;L;;;;;N;;;;; +1110E;CHAKMA LETTER JAA;Lo;0;L;;;;;N;;;;; +1110F;CHAKMA LETTER JHAA;Lo;0;L;;;;;N;;;;; +11110;CHAKMA LETTER NYAA;Lo;0;L;;;;;N;;;;; +11111;CHAKMA LETTER TTAA;Lo;0;L;;;;;N;;;;; +11112;CHAKMA LETTER TTHAA;Lo;0;L;;;;;N;;;;; +11113;CHAKMA LETTER DDAA;Lo;0;L;;;;;N;;;;; +11114;CHAKMA LETTER DDHAA;Lo;0;L;;;;;N;;;;; +11115;CHAKMA LETTER NNAA;Lo;0;L;;;;;N;;;;; +11116;CHAKMA LETTER TAA;Lo;0;L;;;;;N;;;;; +11117;CHAKMA LETTER THAA;Lo;0;L;;;;;N;;;;; +11118;CHAKMA LETTER DAA;Lo;0;L;;;;;N;;;;; +11119;CHAKMA LETTER DHAA;Lo;0;L;;;;;N;;;;; +1111A;CHAKMA LETTER NAA;Lo;0;L;;;;;N;;;;; +1111B;CHAKMA LETTER PAA;Lo;0;L;;;;;N;;;;; +1111C;CHAKMA LETTER PHAA;Lo;0;L;;;;;N;;;;; +1111D;CHAKMA LETTER BAA;Lo;0;L;;;;;N;;;;; +1111E;CHAKMA LETTER BHAA;Lo;0;L;;;;;N;;;;; +1111F;CHAKMA LETTER MAA;Lo;0;L;;;;;N;;;;; +11120;CHAKMA LETTER YYAA;Lo;0;L;;;;;N;;;;; +11121;CHAKMA LETTER YAA;Lo;0;L;;;;;N;;;;; +11122;CHAKMA LETTER RAA;Lo;0;L;;;;;N;;;;; +11123;CHAKMA LETTER LAA;Lo;0;L;;;;;N;;;;; +11124;CHAKMA LETTER WAA;Lo;0;L;;;;;N;;;;; +11125;CHAKMA LETTER SAA;Lo;0;L;;;;;N;;;;; +11126;CHAKMA LETTER HAA;Lo;0;L;;;;;N;;;;; +11127;CHAKMA VOWEL SIGN A;Mn;0;NSM;;;;;N;;;;; +11128;CHAKMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11129;CHAKMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1112A;CHAKMA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1112B;CHAKMA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1112C;CHAKMA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1112D;CHAKMA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1112E;CHAKMA VOWEL SIGN O;Mn;0;NSM;11131 11127;;;;N;;;;; +1112F;CHAKMA VOWEL SIGN AU;Mn;0;NSM;11132 11127;;;;N;;;;; +11130;CHAKMA VOWEL SIGN OI;Mn;0;NSM;;;;;N;;;;; +11131;CHAKMA O MARK;Mn;0;NSM;;;;;N;;;;; +11132;CHAKMA AU MARK;Mn;0;NSM;;;;;N;;;;; +11133;CHAKMA VIRAMA;Mn;9;NSM;;;;;N;;;;; +11134;CHAKMA MAAYYAA;Mn;9;NSM;;;;;N;;;;; +11136;CHAKMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11137;CHAKMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11138;CHAKMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11139;CHAKMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1113A;CHAKMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1113B;CHAKMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1113C;CHAKMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1113D;CHAKMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1113E;CHAKMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1113F;CHAKMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11140;CHAKMA SECTION MARK;Po;0;L;;;;;N;;;;; +11141;CHAKMA DANDA;Po;0;L;;;;;N;;;;; +11142;CHAKMA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11143;CHAKMA QUESTION MARK;Po;0;L;;;;;N;;;;; +11144;CHAKMA LETTER LHAA;Lo;0;L;;;;;N;;;;; +11145;CHAKMA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11146;CHAKMA VOWEL SIGN EI;Mc;0;L;;;;;N;;;;; +11147;CHAKMA LETTER VAA;Lo;0;L;;;;;N;;;;; +11150;MAHAJANI LETTER A;Lo;0;L;;;;;N;;;;; +11151;MAHAJANI LETTER I;Lo;0;L;;;;;N;;;;; +11152;MAHAJANI LETTER U;Lo;0;L;;;;;N;;;;; +11153;MAHAJANI LETTER E;Lo;0;L;;;;;N;;;;; +11154;MAHAJANI LETTER O;Lo;0;L;;;;;N;;;;; +11155;MAHAJANI LETTER KA;Lo;0;L;;;;;N;;;;; +11156;MAHAJANI LETTER KHA;Lo;0;L;;;;;N;;;;; +11157;MAHAJANI LETTER GA;Lo;0;L;;;;;N;;;;; +11158;MAHAJANI LETTER GHA;Lo;0;L;;;;;N;;;;; +11159;MAHAJANI LETTER CA;Lo;0;L;;;;;N;;;;; +1115A;MAHAJANI LETTER CHA;Lo;0;L;;;;;N;;;;; +1115B;MAHAJANI LETTER JA;Lo;0;L;;;;;N;;;;; +1115C;MAHAJANI LETTER JHA;Lo;0;L;;;;;N;;;;; +1115D;MAHAJANI LETTER NYA;Lo;0;L;;;;;N;;;;; +1115E;MAHAJANI LETTER TTA;Lo;0;L;;;;;N;;;;; +1115F;MAHAJANI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11160;MAHAJANI LETTER DDA;Lo;0;L;;;;;N;;;;; +11161;MAHAJANI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11162;MAHAJANI LETTER NNA;Lo;0;L;;;;;N;;;;; +11163;MAHAJANI LETTER TA;Lo;0;L;;;;;N;;;;; +11164;MAHAJANI LETTER THA;Lo;0;L;;;;;N;;;;; +11165;MAHAJANI LETTER DA;Lo;0;L;;;;;N;;;;; +11166;MAHAJANI LETTER DHA;Lo;0;L;;;;;N;;;;; +11167;MAHAJANI LETTER NA;Lo;0;L;;;;;N;;;;; +11168;MAHAJANI LETTER PA;Lo;0;L;;;;;N;;;;; +11169;MAHAJANI LETTER PHA;Lo;0;L;;;;;N;;;;; +1116A;MAHAJANI LETTER BA;Lo;0;L;;;;;N;;;;; +1116B;MAHAJANI LETTER BHA;Lo;0;L;;;;;N;;;;; +1116C;MAHAJANI LETTER MA;Lo;0;L;;;;;N;;;;; +1116D;MAHAJANI LETTER RA;Lo;0;L;;;;;N;;;;; +1116E;MAHAJANI LETTER LA;Lo;0;L;;;;;N;;;;; +1116F;MAHAJANI LETTER VA;Lo;0;L;;;;;N;;;;; +11170;MAHAJANI LETTER SA;Lo;0;L;;;;;N;;;;; +11171;MAHAJANI LETTER HA;Lo;0;L;;;;;N;;;;; +11172;MAHAJANI LETTER RRA;Lo;0;L;;;;;N;;;;; +11173;MAHAJANI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11174;MAHAJANI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11175;MAHAJANI SECTION MARK;Po;0;L;;;;;N;;;;; +11176;MAHAJANI LIGATURE SHRI;Lo;0;L;;;;;N;;;;; +11180;SHARADA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11181;SHARADA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11182;SHARADA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11183;SHARADA LETTER A;Lo;0;L;;;;;N;;;;; +11184;SHARADA LETTER AA;Lo;0;L;;;;;N;;;;; +11185;SHARADA LETTER I;Lo;0;L;;;;;N;;;;; +11186;SHARADA LETTER II;Lo;0;L;;;;;N;;;;; +11187;SHARADA LETTER U;Lo;0;L;;;;;N;;;;; +11188;SHARADA LETTER UU;Lo;0;L;;;;;N;;;;; +11189;SHARADA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1118A;SHARADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1118B;SHARADA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1118C;SHARADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1118D;SHARADA LETTER E;Lo;0;L;;;;;N;;;;; +1118E;SHARADA LETTER AI;Lo;0;L;;;;;N;;;;; +1118F;SHARADA LETTER O;Lo;0;L;;;;;N;;;;; +11190;SHARADA LETTER AU;Lo;0;L;;;;;N;;;;; +11191;SHARADA LETTER KA;Lo;0;L;;;;;N;;;;; +11192;SHARADA LETTER KHA;Lo;0;L;;;;;N;;;;; +11193;SHARADA LETTER GA;Lo;0;L;;;;;N;;;;; +11194;SHARADA LETTER GHA;Lo;0;L;;;;;N;;;;; +11195;SHARADA LETTER NGA;Lo;0;L;;;;;N;;;;; +11196;SHARADA LETTER CA;Lo;0;L;;;;;N;;;;; +11197;SHARADA LETTER CHA;Lo;0;L;;;;;N;;;;; +11198;SHARADA LETTER JA;Lo;0;L;;;;;N;;;;; +11199;SHARADA LETTER JHA;Lo;0;L;;;;;N;;;;; +1119A;SHARADA LETTER NYA;Lo;0;L;;;;;N;;;;; +1119B;SHARADA LETTER TTA;Lo;0;L;;;;;N;;;;; +1119C;SHARADA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1119D;SHARADA LETTER DDA;Lo;0;L;;;;;N;;;;; +1119E;SHARADA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1119F;SHARADA LETTER NNA;Lo;0;L;;;;;N;;;;; +111A0;SHARADA LETTER TA;Lo;0;L;;;;;N;;;;; +111A1;SHARADA LETTER THA;Lo;0;L;;;;;N;;;;; +111A2;SHARADA LETTER DA;Lo;0;L;;;;;N;;;;; +111A3;SHARADA LETTER DHA;Lo;0;L;;;;;N;;;;; +111A4;SHARADA LETTER NA;Lo;0;L;;;;;N;;;;; +111A5;SHARADA LETTER PA;Lo;0;L;;;;;N;;;;; +111A6;SHARADA LETTER PHA;Lo;0;L;;;;;N;;;;; +111A7;SHARADA LETTER BA;Lo;0;L;;;;;N;;;;; +111A8;SHARADA LETTER BHA;Lo;0;L;;;;;N;;;;; +111A9;SHARADA LETTER MA;Lo;0;L;;;;;N;;;;; +111AA;SHARADA LETTER YA;Lo;0;L;;;;;N;;;;; +111AB;SHARADA LETTER RA;Lo;0;L;;;;;N;;;;; +111AC;SHARADA LETTER LA;Lo;0;L;;;;;N;;;;; +111AD;SHARADA LETTER LLA;Lo;0;L;;;;;N;;;;; +111AE;SHARADA LETTER VA;Lo;0;L;;;;;N;;;;; +111AF;SHARADA LETTER SHA;Lo;0;L;;;;;N;;;;; +111B0;SHARADA LETTER SSA;Lo;0;L;;;;;N;;;;; +111B1;SHARADA LETTER SA;Lo;0;L;;;;;N;;;;; +111B2;SHARADA LETTER HA;Lo;0;L;;;;;N;;;;; +111B3;SHARADA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +111B4;SHARADA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +111B5;SHARADA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +111B6;SHARADA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +111B7;SHARADA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +111B8;SHARADA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +111B9;SHARADA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +111BA;SHARADA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +111BB;SHARADA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +111BC;SHARADA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +111BD;SHARADA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +111BE;SHARADA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +111BF;SHARADA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +111C0;SHARADA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +111C1;SHARADA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +111C2;SHARADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +111C3;SHARADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +111C4;SHARADA OM;Lo;0;L;;;;;N;;;;; +111C5;SHARADA DANDA;Po;0;L;;;;;N;;;;; +111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;; +111C9;SHARADA SANDHI MARK;Mn;0;NSM;;;;;N;;;;; +111CA;SHARADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +111CB;SHARADA VOWEL MODIFIER MARK;Mn;0;NSM;;;;;N;;;;; +111CC;SHARADA EXTRA SHORT VOWEL MARK;Mn;0;NSM;;;;;N;;;;; +111CD;SHARADA SUTRA MARK;Po;0;L;;;;;N;;;;; +111CE;SHARADA VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; +111CF;SHARADA SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +111D2;SHARADA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +111D3;SHARADA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +111D4;SHARADA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +111D5;SHARADA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +111D6;SHARADA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +111D7;SHARADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +111DA;SHARADA EKAM;Lo;0;L;;;;;N;;;;; +111DB;SHARADA SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +111DC;SHARADA HEADSTROKE;Lo;0;L;;;;;N;;;;; +111DD;SHARADA CONTINUATION SIGN;Po;0;L;;;;;N;;;;; +111DE;SHARADA SECTION MARK-1;Po;0;L;;;;;N;;;;; +111DF;SHARADA SECTION MARK-2;Po;0;L;;;;;N;;;;; +111E1;SINHALA ARCHAIC DIGIT ONE;No;0;L;;;;1;N;;;;; +111E2;SINHALA ARCHAIC DIGIT TWO;No;0;L;;;;2;N;;;;; +111E3;SINHALA ARCHAIC DIGIT THREE;No;0;L;;;;3;N;;;;; +111E4;SINHALA ARCHAIC DIGIT FOUR;No;0;L;;;;4;N;;;;; +111E5;SINHALA ARCHAIC DIGIT FIVE;No;0;L;;;;5;N;;;;; +111E6;SINHALA ARCHAIC DIGIT SIX;No;0;L;;;;6;N;;;;; +111E7;SINHALA ARCHAIC DIGIT SEVEN;No;0;L;;;;7;N;;;;; +111E8;SINHALA ARCHAIC DIGIT EIGHT;No;0;L;;;;8;N;;;;; +111E9;SINHALA ARCHAIC DIGIT NINE;No;0;L;;;;9;N;;;;; +111EA;SINHALA ARCHAIC NUMBER TEN;No;0;L;;;;10;N;;;;; +111EB;SINHALA ARCHAIC NUMBER TWENTY;No;0;L;;;;20;N;;;;; +111EC;SINHALA ARCHAIC NUMBER THIRTY;No;0;L;;;;30;N;;;;; +111ED;SINHALA ARCHAIC NUMBER FORTY;No;0;L;;;;40;N;;;;; +111EE;SINHALA ARCHAIC NUMBER FIFTY;No;0;L;;;;50;N;;;;; +111EF;SINHALA ARCHAIC NUMBER SIXTY;No;0;L;;;;60;N;;;;; +111F0;SINHALA ARCHAIC NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +111F1;SINHALA ARCHAIC NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +111F2;SINHALA ARCHAIC NUMBER NINETY;No;0;L;;;;90;N;;;;; +111F3;SINHALA ARCHAIC NUMBER ONE HUNDRED;No;0;L;;;;100;N;;;;; +111F4;SINHALA ARCHAIC NUMBER ONE THOUSAND;No;0;L;;;;1000;N;;;;; +11200;KHOJKI LETTER A;Lo;0;L;;;;;N;;;;; +11201;KHOJKI LETTER AA;Lo;0;L;;;;;N;;;;; +11202;KHOJKI LETTER I;Lo;0;L;;;;;N;;;;; +11203;KHOJKI LETTER U;Lo;0;L;;;;;N;;;;; +11204;KHOJKI LETTER E;Lo;0;L;;;;;N;;;;; +11205;KHOJKI LETTER AI;Lo;0;L;;;;;N;;;;; +11206;KHOJKI LETTER O;Lo;0;L;;;;;N;;;;; +11207;KHOJKI LETTER AU;Lo;0;L;;;;;N;;;;; +11208;KHOJKI LETTER KA;Lo;0;L;;;;;N;;;;; +11209;KHOJKI LETTER KHA;Lo;0;L;;;;;N;;;;; +1120A;KHOJKI LETTER GA;Lo;0;L;;;;;N;;;;; +1120B;KHOJKI LETTER GGA;Lo;0;L;;;;;N;;;;; +1120C;KHOJKI LETTER GHA;Lo;0;L;;;;;N;;;;; +1120D;KHOJKI LETTER NGA;Lo;0;L;;;;;N;;;;; +1120E;KHOJKI LETTER CA;Lo;0;L;;;;;N;;;;; +1120F;KHOJKI LETTER CHA;Lo;0;L;;;;;N;;;;; +11210;KHOJKI LETTER JA;Lo;0;L;;;;;N;;;;; +11211;KHOJKI LETTER JJA;Lo;0;L;;;;;N;;;;; +11213;KHOJKI LETTER NYA;Lo;0;L;;;;;N;;;;; +11214;KHOJKI LETTER TTA;Lo;0;L;;;;;N;;;;; +11215;KHOJKI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11216;KHOJKI LETTER DDA;Lo;0;L;;;;;N;;;;; +11217;KHOJKI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11218;KHOJKI LETTER NNA;Lo;0;L;;;;;N;;;;; +11219;KHOJKI LETTER TA;Lo;0;L;;;;;N;;;;; +1121A;KHOJKI LETTER THA;Lo;0;L;;;;;N;;;;; +1121B;KHOJKI LETTER DA;Lo;0;L;;;;;N;;;;; +1121C;KHOJKI LETTER DDDA;Lo;0;L;;;;;N;;;;; +1121D;KHOJKI LETTER DHA;Lo;0;L;;;;;N;;;;; +1121E;KHOJKI LETTER NA;Lo;0;L;;;;;N;;;;; +1121F;KHOJKI LETTER PA;Lo;0;L;;;;;N;;;;; +11220;KHOJKI LETTER PHA;Lo;0;L;;;;;N;;;;; +11221;KHOJKI LETTER BA;Lo;0;L;;;;;N;;;;; +11222;KHOJKI LETTER BBA;Lo;0;L;;;;;N;;;;; +11223;KHOJKI LETTER BHA;Lo;0;L;;;;;N;;;;; +11224;KHOJKI LETTER MA;Lo;0;L;;;;;N;;;;; +11225;KHOJKI LETTER YA;Lo;0;L;;;;;N;;;;; +11226;KHOJKI LETTER RA;Lo;0;L;;;;;N;;;;; +11227;KHOJKI LETTER LA;Lo;0;L;;;;;N;;;;; +11228;KHOJKI LETTER VA;Lo;0;L;;;;;N;;;;; +11229;KHOJKI LETTER SA;Lo;0;L;;;;;N;;;;; +1122A;KHOJKI LETTER HA;Lo;0;L;;;;;N;;;;; +1122B;KHOJKI LETTER LLA;Lo;0;L;;;;;N;;;;; +1122C;KHOJKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1122D;KHOJKI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1122E;KHOJKI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +1122F;KHOJKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11230;KHOJKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11231;KHOJKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11232;KHOJKI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11233;KHOJKI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11234;KHOJKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11235;KHOJKI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +11236;KHOJKI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11237;KHOJKI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;; +11238;KHOJKI DANDA;Po;0;L;;;;;N;;;;; +11239;KHOJKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +1123A;KHOJKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; +1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;; +1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;; +1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +1123E;KHOJKI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;; +1123F;KHOJKI LETTER QA;Lo;0;L;;;;;N;;;;; +11240;KHOJKI LETTER SHORT I;Lo;0;L;;;;;N;;;;; +11241;KHOJKI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11280;MULTANI LETTER A;Lo;0;L;;;;;N;;;;; +11281;MULTANI LETTER I;Lo;0;L;;;;;N;;;;; +11282;MULTANI LETTER U;Lo;0;L;;;;;N;;;;; +11283;MULTANI LETTER E;Lo;0;L;;;;;N;;;;; +11284;MULTANI LETTER KA;Lo;0;L;;;;;N;;;;; +11285;MULTANI LETTER KHA;Lo;0;L;;;;;N;;;;; +11286;MULTANI LETTER GA;Lo;0;L;;;;;N;;;;; +11288;MULTANI LETTER GHA;Lo;0;L;;;;;N;;;;; +1128A;MULTANI LETTER CA;Lo;0;L;;;;;N;;;;; +1128B;MULTANI LETTER CHA;Lo;0;L;;;;;N;;;;; +1128C;MULTANI LETTER JA;Lo;0;L;;;;;N;;;;; +1128D;MULTANI LETTER JJA;Lo;0;L;;;;;N;;;;; +1128F;MULTANI LETTER NYA;Lo;0;L;;;;;N;;;;; +11290;MULTANI LETTER TTA;Lo;0;L;;;;;N;;;;; +11291;MULTANI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11292;MULTANI LETTER DDA;Lo;0;L;;;;;N;;;;; +11293;MULTANI LETTER DDDA;Lo;0;L;;;;;N;;;;; +11294;MULTANI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11295;MULTANI LETTER NNA;Lo;0;L;;;;;N;;;;; +11296;MULTANI LETTER TA;Lo;0;L;;;;;N;;;;; +11297;MULTANI LETTER THA;Lo;0;L;;;;;N;;;;; +11298;MULTANI LETTER DA;Lo;0;L;;;;;N;;;;; +11299;MULTANI LETTER DHA;Lo;0;L;;;;;N;;;;; +1129A;MULTANI LETTER NA;Lo;0;L;;;;;N;;;;; +1129B;MULTANI LETTER PA;Lo;0;L;;;;;N;;;;; +1129C;MULTANI LETTER PHA;Lo;0;L;;;;;N;;;;; +1129D;MULTANI LETTER BA;Lo;0;L;;;;;N;;;;; +1129F;MULTANI LETTER BHA;Lo;0;L;;;;;N;;;;; +112A0;MULTANI LETTER MA;Lo;0;L;;;;;N;;;;; +112A1;MULTANI LETTER YA;Lo;0;L;;;;;N;;;;; +112A2;MULTANI LETTER RA;Lo;0;L;;;;;N;;;;; +112A3;MULTANI LETTER LA;Lo;0;L;;;;;N;;;;; +112A4;MULTANI LETTER VA;Lo;0;L;;;;;N;;;;; +112A5;MULTANI LETTER SA;Lo;0;L;;;;;N;;;;; +112A6;MULTANI LETTER HA;Lo;0;L;;;;;N;;;;; +112A7;MULTANI LETTER RRA;Lo;0;L;;;;;N;;;;; +112A8;MULTANI LETTER RHA;Lo;0;L;;;;;N;;;;; +112A9;MULTANI SECTION MARK;Po;0;L;;;;;N;;;;; +112B0;KHUDAWADI LETTER A;Lo;0;L;;;;;N;;;;; +112B1;KHUDAWADI LETTER AA;Lo;0;L;;;;;N;;;;; +112B2;KHUDAWADI LETTER I;Lo;0;L;;;;;N;;;;; +112B3;KHUDAWADI LETTER II;Lo;0;L;;;;;N;;;;; +112B4;KHUDAWADI LETTER U;Lo;0;L;;;;;N;;;;; +112B5;KHUDAWADI LETTER UU;Lo;0;L;;;;;N;;;;; +112B6;KHUDAWADI LETTER E;Lo;0;L;;;;;N;;;;; +112B7;KHUDAWADI LETTER AI;Lo;0;L;;;;;N;;;;; +112B8;KHUDAWADI LETTER O;Lo;0;L;;;;;N;;;;; +112B9;KHUDAWADI LETTER AU;Lo;0;L;;;;;N;;;;; +112BA;KHUDAWADI LETTER KA;Lo;0;L;;;;;N;;;;; +112BB;KHUDAWADI LETTER KHA;Lo;0;L;;;;;N;;;;; +112BC;KHUDAWADI LETTER GA;Lo;0;L;;;;;N;;;;; +112BD;KHUDAWADI LETTER GGA;Lo;0;L;;;;;N;;;;; +112BE;KHUDAWADI LETTER GHA;Lo;0;L;;;;;N;;;;; +112BF;KHUDAWADI LETTER NGA;Lo;0;L;;;;;N;;;;; +112C0;KHUDAWADI LETTER CA;Lo;0;L;;;;;N;;;;; +112C1;KHUDAWADI LETTER CHA;Lo;0;L;;;;;N;;;;; +112C2;KHUDAWADI LETTER JA;Lo;0;L;;;;;N;;;;; +112C3;KHUDAWADI LETTER JJA;Lo;0;L;;;;;N;;;;; +112C4;KHUDAWADI LETTER JHA;Lo;0;L;;;;;N;;;;; +112C5;KHUDAWADI LETTER NYA;Lo;0;L;;;;;N;;;;; +112C6;KHUDAWADI LETTER TTA;Lo;0;L;;;;;N;;;;; +112C7;KHUDAWADI LETTER TTHA;Lo;0;L;;;;;N;;;;; +112C8;KHUDAWADI LETTER DDA;Lo;0;L;;;;;N;;;;; +112C9;KHUDAWADI LETTER DDDA;Lo;0;L;;;;;N;;;;; +112CA;KHUDAWADI LETTER RRA;Lo;0;L;;;;;N;;;;; +112CB;KHUDAWADI LETTER DDHA;Lo;0;L;;;;;N;;;;; +112CC;KHUDAWADI LETTER NNA;Lo;0;L;;;;;N;;;;; +112CD;KHUDAWADI LETTER TA;Lo;0;L;;;;;N;;;;; +112CE;KHUDAWADI LETTER THA;Lo;0;L;;;;;N;;;;; +112CF;KHUDAWADI LETTER DA;Lo;0;L;;;;;N;;;;; +112D0;KHUDAWADI LETTER DHA;Lo;0;L;;;;;N;;;;; +112D1;KHUDAWADI LETTER NA;Lo;0;L;;;;;N;;;;; +112D2;KHUDAWADI LETTER PA;Lo;0;L;;;;;N;;;;; +112D3;KHUDAWADI LETTER PHA;Lo;0;L;;;;;N;;;;; +112D4;KHUDAWADI LETTER BA;Lo;0;L;;;;;N;;;;; +112D5;KHUDAWADI LETTER BBA;Lo;0;L;;;;;N;;;;; +112D6;KHUDAWADI LETTER BHA;Lo;0;L;;;;;N;;;;; +112D7;KHUDAWADI LETTER MA;Lo;0;L;;;;;N;;;;; +112D8;KHUDAWADI LETTER YA;Lo;0;L;;;;;N;;;;; +112D9;KHUDAWADI LETTER RA;Lo;0;L;;;;;N;;;;; +112DA;KHUDAWADI LETTER LA;Lo;0;L;;;;;N;;;;; +112DB;KHUDAWADI LETTER VA;Lo;0;L;;;;;N;;;;; +112DC;KHUDAWADI LETTER SHA;Lo;0;L;;;;;N;;;;; +112DD;KHUDAWADI LETTER SA;Lo;0;L;;;;;N;;;;; +112DE;KHUDAWADI LETTER HA;Lo;0;L;;;;;N;;;;; +112DF;KHUDAWADI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +112E0;KHUDAWADI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +112E1;KHUDAWADI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +112E2;KHUDAWADI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +112E3;KHUDAWADI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +112E4;KHUDAWADI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +112E5;KHUDAWADI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +112E6;KHUDAWADI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +112E7;KHUDAWADI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +112E8;KHUDAWADI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +112E9;KHUDAWADI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +112EA;KHUDAWADI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +112F0;KHUDAWADI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +112F1;KHUDAWADI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +112F2;KHUDAWADI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +112F3;KHUDAWADI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +112F4;KHUDAWADI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +112F5;KHUDAWADI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +112F6;KHUDAWADI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +112F7;KHUDAWADI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +112F8;KHUDAWADI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +112F9;KHUDAWADI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11300;GRANTHA SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;; +11301;GRANTHA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11302;GRANTHA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +11303;GRANTHA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11305;GRANTHA LETTER A;Lo;0;L;;;;;N;;;;; +11306;GRANTHA LETTER AA;Lo;0;L;;;;;N;;;;; +11307;GRANTHA LETTER I;Lo;0;L;;;;;N;;;;; +11308;GRANTHA LETTER II;Lo;0;L;;;;;N;;;;; +11309;GRANTHA LETTER U;Lo;0;L;;;;;N;;;;; +1130A;GRANTHA LETTER UU;Lo;0;L;;;;;N;;;;; +1130B;GRANTHA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1130C;GRANTHA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1130F;GRANTHA LETTER EE;Lo;0;L;;;;;N;;;;; +11310;GRANTHA LETTER AI;Lo;0;L;;;;;N;;;;; +11313;GRANTHA LETTER OO;Lo;0;L;;;;;N;;;;; +11314;GRANTHA LETTER AU;Lo;0;L;;;;;N;;;;; +11315;GRANTHA LETTER KA;Lo;0;L;;;;;N;;;;; +11316;GRANTHA LETTER KHA;Lo;0;L;;;;;N;;;;; +11317;GRANTHA LETTER GA;Lo;0;L;;;;;N;;;;; +11318;GRANTHA LETTER GHA;Lo;0;L;;;;;N;;;;; +11319;GRANTHA LETTER NGA;Lo;0;L;;;;;N;;;;; +1131A;GRANTHA LETTER CA;Lo;0;L;;;;;N;;;;; +1131B;GRANTHA LETTER CHA;Lo;0;L;;;;;N;;;;; +1131C;GRANTHA LETTER JA;Lo;0;L;;;;;N;;;;; +1131D;GRANTHA LETTER JHA;Lo;0;L;;;;;N;;;;; +1131E;GRANTHA LETTER NYA;Lo;0;L;;;;;N;;;;; +1131F;GRANTHA LETTER TTA;Lo;0;L;;;;;N;;;;; +11320;GRANTHA LETTER TTHA;Lo;0;L;;;;;N;;;;; +11321;GRANTHA LETTER DDA;Lo;0;L;;;;;N;;;;; +11322;GRANTHA LETTER DDHA;Lo;0;L;;;;;N;;;;; +11323;GRANTHA LETTER NNA;Lo;0;L;;;;;N;;;;; +11324;GRANTHA LETTER TA;Lo;0;L;;;;;N;;;;; +11325;GRANTHA LETTER THA;Lo;0;L;;;;;N;;;;; +11326;GRANTHA LETTER DA;Lo;0;L;;;;;N;;;;; +11327;GRANTHA LETTER DHA;Lo;0;L;;;;;N;;;;; +11328;GRANTHA LETTER NA;Lo;0;L;;;;;N;;;;; +1132A;GRANTHA LETTER PA;Lo;0;L;;;;;N;;;;; +1132B;GRANTHA LETTER PHA;Lo;0;L;;;;;N;;;;; +1132C;GRANTHA LETTER BA;Lo;0;L;;;;;N;;;;; +1132D;GRANTHA LETTER BHA;Lo;0;L;;;;;N;;;;; +1132E;GRANTHA LETTER MA;Lo;0;L;;;;;N;;;;; +1132F;GRANTHA LETTER YA;Lo;0;L;;;;;N;;;;; +11330;GRANTHA LETTER RA;Lo;0;L;;;;;N;;;;; +11332;GRANTHA LETTER LA;Lo;0;L;;;;;N;;;;; +11333;GRANTHA LETTER LLA;Lo;0;L;;;;;N;;;;; +11335;GRANTHA LETTER VA;Lo;0;L;;;;;N;;;;; +11336;GRANTHA LETTER SHA;Lo;0;L;;;;;N;;;;; +11337;GRANTHA LETTER SSA;Lo;0;L;;;;;N;;;;; +11338;GRANTHA LETTER SA;Lo;0;L;;;;;N;;;;; +11339;GRANTHA LETTER HA;Lo;0;L;;;;;N;;;;; +1133B;COMBINING BINDU BELOW;Mn;7;NSM;;;;;N;;;;; +1133C;GRANTHA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +1133D;GRANTHA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +1133E;GRANTHA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1133F;GRANTHA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11340;GRANTHA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11341;GRANTHA VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +11342;GRANTHA VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +11343;GRANTHA VOWEL SIGN VOCALIC R;Mc;0;L;;;;;N;;;;; +11344;GRANTHA VOWEL SIGN VOCALIC RR;Mc;0;L;;;;;N;;;;; +11347;GRANTHA VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +11348;GRANTHA VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +1134B;GRANTHA VOWEL SIGN OO;Mc;0;L;11347 1133E;;;;N;;;;; +1134C;GRANTHA VOWEL SIGN AU;Mc;0;L;11347 11357;;;;N;;;;; +1134D;GRANTHA SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +11350;GRANTHA OM;Lo;0;L;;;;;N;;;;; +11357;GRANTHA AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +1135D;GRANTHA SIGN PLUTA;Lo;0;L;;;;;N;;;;; +1135E;GRANTHA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +1135F;GRANTHA LETTER VEDIC DOUBLE ANUSVARA;Lo;0;L;;;;;N;;;;; +11360;GRANTHA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11361;GRANTHA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +11362;GRANTHA VOWEL SIGN VOCALIC L;Mc;0;L;;;;;N;;;;; +11363;GRANTHA VOWEL SIGN VOCALIC LL;Mc;0;L;;;;;N;;;;; +11366;COMBINING GRANTHA DIGIT ZERO;Mn;230;NSM;;;;;N;;;;; +11367;COMBINING GRANTHA DIGIT ONE;Mn;230;NSM;;;;;N;;;;; +11368;COMBINING GRANTHA DIGIT TWO;Mn;230;NSM;;;;;N;;;;; +11369;COMBINING GRANTHA DIGIT THREE;Mn;230;NSM;;;;;N;;;;; +1136A;COMBINING GRANTHA DIGIT FOUR;Mn;230;NSM;;;;;N;;;;; +1136B;COMBINING GRANTHA DIGIT FIVE;Mn;230;NSM;;;;;N;;;;; +1136C;COMBINING GRANTHA DIGIT SIX;Mn;230;NSM;;;;;N;;;;; +11370;COMBINING GRANTHA LETTER A;Mn;230;NSM;;;;;N;;;;; +11371;COMBINING GRANTHA LETTER KA;Mn;230;NSM;;;;;N;;;;; +11372;COMBINING GRANTHA LETTER NA;Mn;230;NSM;;;;;N;;;;; +11373;COMBINING GRANTHA LETTER VI;Mn;230;NSM;;;;;N;;;;; +11374;COMBINING GRANTHA LETTER PA;Mn;230;NSM;;;;;N;;;;; +11380;TULU-TIGALARI LETTER A;Lo;0;L;;;;;N;;;;; +11381;TULU-TIGALARI LETTER AA;Lo;0;L;;;;;N;;;;; +11382;TULU-TIGALARI LETTER I;Lo;0;L;;;;;N;;;;; +11383;TULU-TIGALARI LETTER II;Lo;0;L;11382 113C9;;;;N;;;;; +11384;TULU-TIGALARI LETTER U;Lo;0;L;;;;;N;;;;; +11385;TULU-TIGALARI LETTER UU;Lo;0;L;11384 113BB;;;;N;;;;; +11386;TULU-TIGALARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11387;TULU-TIGALARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11388;TULU-TIGALARI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11389;TULU-TIGALARI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1138B;TULU-TIGALARI LETTER EE;Lo;0;L;;;;;N;;;;; +1138E;TULU-TIGALARI LETTER AI;Lo;0;L;1138B 113C2;;;;N;;;;; +11390;TULU-TIGALARI LETTER OO;Lo;0;L;;;;;N;;;;; +11391;TULU-TIGALARI LETTER AU;Lo;0;L;11390 113C9;;;;N;;;;; +11392;TULU-TIGALARI LETTER KA;Lo;0;L;;;;;N;;;;; +11393;TULU-TIGALARI LETTER KHA;Lo;0;L;;;;;N;;;;; +11394;TULU-TIGALARI LETTER GA;Lo;0;L;;;;;N;;;;; +11395;TULU-TIGALARI LETTER GHA;Lo;0;L;;;;;N;;;;; +11396;TULU-TIGALARI LETTER NGA;Lo;0;L;;;;;N;;;;; +11397;TULU-TIGALARI LETTER CA;Lo;0;L;;;;;N;;;;; +11398;TULU-TIGALARI LETTER CHA;Lo;0;L;;;;;N;;;;; +11399;TULU-TIGALARI LETTER JA;Lo;0;L;;;;;N;;;;; +1139A;TULU-TIGALARI LETTER JHA;Lo;0;L;;;;;N;;;;; +1139B;TULU-TIGALARI LETTER NYA;Lo;0;L;;;;;N;;;;; +1139C;TULU-TIGALARI LETTER TTA;Lo;0;L;;;;;N;;;;; +1139D;TULU-TIGALARI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1139E;TULU-TIGALARI LETTER DDA;Lo;0;L;;;;;N;;;;; +1139F;TULU-TIGALARI LETTER DDHA;Lo;0;L;;;;;N;;;;; +113A0;TULU-TIGALARI LETTER NNA;Lo;0;L;;;;;N;;;;; +113A1;TULU-TIGALARI LETTER TA;Lo;0;L;;;;;N;;;;; +113A2;TULU-TIGALARI LETTER THA;Lo;0;L;;;;;N;;;;; +113A3;TULU-TIGALARI LETTER DA;Lo;0;L;;;;;N;;;;; +113A4;TULU-TIGALARI LETTER DHA;Lo;0;L;;;;;N;;;;; +113A5;TULU-TIGALARI LETTER NA;Lo;0;L;;;;;N;;;;; +113A6;TULU-TIGALARI LETTER PA;Lo;0;L;;;;;N;;;;; +113A7;TULU-TIGALARI LETTER PHA;Lo;0;L;;;;;N;;;;; +113A8;TULU-TIGALARI LETTER BA;Lo;0;L;;;;;N;;;;; +113A9;TULU-TIGALARI LETTER BHA;Lo;0;L;;;;;N;;;;; +113AA;TULU-TIGALARI LETTER MA;Lo;0;L;;;;;N;;;;; +113AB;TULU-TIGALARI LETTER YA;Lo;0;L;;;;;N;;;;; +113AC;TULU-TIGALARI LETTER RA;Lo;0;L;;;;;N;;;;; +113AD;TULU-TIGALARI LETTER LA;Lo;0;L;;;;;N;;;;; +113AE;TULU-TIGALARI LETTER VA;Lo;0;L;;;;;N;;;;; +113AF;TULU-TIGALARI LETTER SHA;Lo;0;L;;;;;N;;;;; +113B0;TULU-TIGALARI LETTER SSA;Lo;0;L;;;;;N;;;;; +113B1;TULU-TIGALARI LETTER SA;Lo;0;L;;;;;N;;;;; +113B2;TULU-TIGALARI LETTER HA;Lo;0;L;;;;;N;;;;; +113B3;TULU-TIGALARI LETTER LLA;Lo;0;L;;;;;N;;;;; +113B4;TULU-TIGALARI LETTER RRA;Lo;0;L;;;;;N;;;;; +113B5;TULU-TIGALARI LETTER LLLA;Lo;0;L;;;;;N;;;;; +113B7;TULU-TIGALARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +113B8;TULU-TIGALARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +113B9;TULU-TIGALARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +113BA;TULU-TIGALARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +113BB;TULU-TIGALARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +113BC;TULU-TIGALARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +113BD;TULU-TIGALARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +113BE;TULU-TIGALARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +113BF;TULU-TIGALARI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +113C0;TULU-TIGALARI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +113C2;TULU-TIGALARI VOWEL SIGN EE;Mc;0;L;;;;;N;;;;; +113C5;TULU-TIGALARI VOWEL SIGN AI;Mc;0;L;113C2 113C2;;;;N;;;;; +113C7;TULU-TIGALARI VOWEL SIGN OO;Mc;0;L;113C2 113B8;;;;N;;;;; +113C8;TULU-TIGALARI VOWEL SIGN AU;Mc;0;L;113C2 113C9;;;;N;;;;; +113C9;TULU-TIGALARI AU LENGTH MARK;Mc;0;L;;;;;N;;;;; +113CA;TULU-TIGALARI SIGN CANDRA ANUNASIKA;Mc;0;L;;;;;N;;;;; +113CC;TULU-TIGALARI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +113CD;TULU-TIGALARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +113CE;TULU-TIGALARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +113CF;TULU-TIGALARI SIGN LOOPED VIRAMA;Mc;9;L;;;;;N;;;;; +113D0;TULU-TIGALARI CONJOINER;Mn;9;NSM;;;;;N;;;;; +113D1;TULU-TIGALARI REPHA;Lo;0;L;;;;;N;;;;; +113D2;TULU-TIGALARI GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +113D3;TULU-TIGALARI SIGN PLUTA;Lo;0;L;;;;;N;;;;; +113D4;TULU-TIGALARI DANDA;Po;0;L;;;;;N;;;;; +113D5;TULU-TIGALARI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +113D7;TULU-TIGALARI SIGN OM PUSHPIKA;Po;0;L;;;;;N;;;;; +113D8;TULU-TIGALARI SIGN SHRII PUSHPIKA;Po;0;L;;;;;N;;;;; +113E1;TULU-TIGALARI VEDIC TONE SVARITA;Mn;0;NSM;;;;;N;;;;; +113E2;TULU-TIGALARI VEDIC TONE ANUDATTA;Mn;0;NSM;;;;;N;;;;; +11400;NEWA LETTER A;Lo;0;L;;;;;N;;;;; +11401;NEWA LETTER AA;Lo;0;L;;;;;N;;;;; +11402;NEWA LETTER I;Lo;0;L;;;;;N;;;;; +11403;NEWA LETTER II;Lo;0;L;;;;;N;;;;; +11404;NEWA LETTER U;Lo;0;L;;;;;N;;;;; +11405;NEWA LETTER UU;Lo;0;L;;;;;N;;;;; +11406;NEWA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11407;NEWA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11408;NEWA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11409;NEWA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1140A;NEWA LETTER E;Lo;0;L;;;;;N;;;;; +1140B;NEWA LETTER AI;Lo;0;L;;;;;N;;;;; +1140C;NEWA LETTER O;Lo;0;L;;;;;N;;;;; +1140D;NEWA LETTER AU;Lo;0;L;;;;;N;;;;; +1140E;NEWA LETTER KA;Lo;0;L;;;;;N;;;;; +1140F;NEWA LETTER KHA;Lo;0;L;;;;;N;;;;; +11410;NEWA LETTER GA;Lo;0;L;;;;;N;;;;; +11411;NEWA LETTER GHA;Lo;0;L;;;;;N;;;;; +11412;NEWA LETTER NGA;Lo;0;L;;;;;N;;;;; +11413;NEWA LETTER NGHA;Lo;0;L;;;;;N;;;;; +11414;NEWA LETTER CA;Lo;0;L;;;;;N;;;;; +11415;NEWA LETTER CHA;Lo;0;L;;;;;N;;;;; +11416;NEWA LETTER JA;Lo;0;L;;;;;N;;;;; +11417;NEWA LETTER JHA;Lo;0;L;;;;;N;;;;; +11418;NEWA LETTER NYA;Lo;0;L;;;;;N;;;;; +11419;NEWA LETTER NYHA;Lo;0;L;;;;;N;;;;; +1141A;NEWA LETTER TTA;Lo;0;L;;;;;N;;;;; +1141B;NEWA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1141C;NEWA LETTER DDA;Lo;0;L;;;;;N;;;;; +1141D;NEWA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1141E;NEWA LETTER NNA;Lo;0;L;;;;;N;;;;; +1141F;NEWA LETTER TA;Lo;0;L;;;;;N;;;;; +11420;NEWA LETTER THA;Lo;0;L;;;;;N;;;;; +11421;NEWA LETTER DA;Lo;0;L;;;;;N;;;;; +11422;NEWA LETTER DHA;Lo;0;L;;;;;N;;;;; +11423;NEWA LETTER NA;Lo;0;L;;;;;N;;;;; +11424;NEWA LETTER NHA;Lo;0;L;;;;;N;;;;; +11425;NEWA LETTER PA;Lo;0;L;;;;;N;;;;; +11426;NEWA LETTER PHA;Lo;0;L;;;;;N;;;;; +11427;NEWA LETTER BA;Lo;0;L;;;;;N;;;;; +11428;NEWA LETTER BHA;Lo;0;L;;;;;N;;;;; +11429;NEWA LETTER MA;Lo;0;L;;;;;N;;;;; +1142A;NEWA LETTER MHA;Lo;0;L;;;;;N;;;;; +1142B;NEWA LETTER YA;Lo;0;L;;;;;N;;;;; +1142C;NEWA LETTER RA;Lo;0;L;;;;;N;;;;; +1142D;NEWA LETTER RHA;Lo;0;L;;;;;N;;;;; +1142E;NEWA LETTER LA;Lo;0;L;;;;;N;;;;; +1142F;NEWA LETTER LHA;Lo;0;L;;;;;N;;;;; +11430;NEWA LETTER WA;Lo;0;L;;;;;N;;;;; +11431;NEWA LETTER SHA;Lo;0;L;;;;;N;;;;; +11432;NEWA LETTER SSA;Lo;0;L;;;;;N;;;;; +11433;NEWA LETTER SA;Lo;0;L;;;;;N;;;;; +11434;NEWA LETTER HA;Lo;0;L;;;;;N;;;;; +11435;NEWA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11436;NEWA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11437;NEWA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11438;NEWA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11439;NEWA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1143A;NEWA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1143B;NEWA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +1143C;NEWA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +1143D;NEWA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +1143E;NEWA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1143F;NEWA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11440;NEWA VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11441;NEWA VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11442;NEWA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11443;NEWA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11444;NEWA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11445;NEWA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11446;NEWA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11447;NEWA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11448;NEWA SIGN FINAL ANUSVARA;Lo;0;L;;;;;N;;;;; +11449;NEWA OM;Lo;0;L;;;;;N;;;;; +1144A;NEWA SIDDHI;Lo;0;L;;;;;N;;;;; +1144B;NEWA DANDA;Po;0;L;;;;;N;;;;; +1144C;NEWA DOUBLE DANDA;Po;0;L;;;;;N;;;;; +1144D;NEWA COMMA;Po;0;L;;;;;N;;;;; +1144E;NEWA GAP FILLER;Po;0;L;;;;;N;;;;; +1144F;NEWA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11450;NEWA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11451;NEWA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11452;NEWA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11453;NEWA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11454;NEWA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11455;NEWA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11456;NEWA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11457;NEWA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11458;NEWA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11459;NEWA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1145A;NEWA DOUBLE COMMA;Po;0;L;;;;;N;;;;; +1145B;NEWA PLACEHOLDER MARK;Po;0;L;;;;;N;;;;; +1145D;NEWA INSERTION SIGN;Po;0;L;;;;;N;;;;; +1145E;NEWA SANDHI MARK;Mn;230;NSM;;;;;N;;;;; +1145F;NEWA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;; +11460;NEWA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +11461;NEWA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +11480;TIRHUTA ANJI;Lo;0;L;;;;;N;;;;; +11481;TIRHUTA LETTER A;Lo;0;L;;;;;N;;;;; +11482;TIRHUTA LETTER AA;Lo;0;L;;;;;N;;;;; +11483;TIRHUTA LETTER I;Lo;0;L;;;;;N;;;;; +11484;TIRHUTA LETTER II;Lo;0;L;;;;;N;;;;; +11485;TIRHUTA LETTER U;Lo;0;L;;;;;N;;;;; +11486;TIRHUTA LETTER UU;Lo;0;L;;;;;N;;;;; +11487;TIRHUTA LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11488;TIRHUTA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11489;TIRHUTA LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1148A;TIRHUTA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1148B;TIRHUTA LETTER E;Lo;0;L;;;;;N;;;;; +1148C;TIRHUTA LETTER AI;Lo;0;L;;;;;N;;;;; +1148D;TIRHUTA LETTER O;Lo;0;L;;;;;N;;;;; +1148E;TIRHUTA LETTER AU;Lo;0;L;;;;;N;;;;; +1148F;TIRHUTA LETTER KA;Lo;0;L;;;;;N;;;;; +11490;TIRHUTA LETTER KHA;Lo;0;L;;;;;N;;;;; +11491;TIRHUTA LETTER GA;Lo;0;L;;;;;N;;;;; +11492;TIRHUTA LETTER GHA;Lo;0;L;;;;;N;;;;; +11493;TIRHUTA LETTER NGA;Lo;0;L;;;;;N;;;;; +11494;TIRHUTA LETTER CA;Lo;0;L;;;;;N;;;;; +11495;TIRHUTA LETTER CHA;Lo;0;L;;;;;N;;;;; +11496;TIRHUTA LETTER JA;Lo;0;L;;;;;N;;;;; +11497;TIRHUTA LETTER JHA;Lo;0;L;;;;;N;;;;; +11498;TIRHUTA LETTER NYA;Lo;0;L;;;;;N;;;;; +11499;TIRHUTA LETTER TTA;Lo;0;L;;;;;N;;;;; +1149A;TIRHUTA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1149B;TIRHUTA LETTER DDA;Lo;0;L;;;;;N;;;;; +1149C;TIRHUTA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1149D;TIRHUTA LETTER NNA;Lo;0;L;;;;;N;;;;; +1149E;TIRHUTA LETTER TA;Lo;0;L;;;;;N;;;;; +1149F;TIRHUTA LETTER THA;Lo;0;L;;;;;N;;;;; +114A0;TIRHUTA LETTER DA;Lo;0;L;;;;;N;;;;; +114A1;TIRHUTA LETTER DHA;Lo;0;L;;;;;N;;;;; +114A2;TIRHUTA LETTER NA;Lo;0;L;;;;;N;;;;; +114A3;TIRHUTA LETTER PA;Lo;0;L;;;;;N;;;;; +114A4;TIRHUTA LETTER PHA;Lo;0;L;;;;;N;;;;; +114A5;TIRHUTA LETTER BA;Lo;0;L;;;;;N;;;;; +114A6;TIRHUTA LETTER BHA;Lo;0;L;;;;;N;;;;; +114A7;TIRHUTA LETTER MA;Lo;0;L;;;;;N;;;;; +114A8;TIRHUTA LETTER YA;Lo;0;L;;;;;N;;;;; +114A9;TIRHUTA LETTER RA;Lo;0;L;;;;;N;;;;; +114AA;TIRHUTA LETTER LA;Lo;0;L;;;;;N;;;;; +114AB;TIRHUTA LETTER VA;Lo;0;L;;;;;N;;;;; +114AC;TIRHUTA LETTER SHA;Lo;0;L;;;;;N;;;;; +114AD;TIRHUTA LETTER SSA;Lo;0;L;;;;;N;;;;; +114AE;TIRHUTA LETTER SA;Lo;0;L;;;;;N;;;;; +114AF;TIRHUTA LETTER HA;Lo;0;L;;;;;N;;;;; +114B0;TIRHUTA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +114B1;TIRHUTA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +114B2;TIRHUTA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +114B3;TIRHUTA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +114B4;TIRHUTA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +114B5;TIRHUTA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +114B6;TIRHUTA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +114B7;TIRHUTA VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +114B8;TIRHUTA VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +114B9;TIRHUTA VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +114BA;TIRHUTA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; +114BB;TIRHUTA VOWEL SIGN AI;Mc;0;L;114B9 114BA;;;;N;;;;; +114BC;TIRHUTA VOWEL SIGN O;Mc;0;L;114B9 114B0;;;;N;;;;; +114BD;TIRHUTA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; +114BE;TIRHUTA VOWEL SIGN AU;Mc;0;L;114B9 114BD;;;;N;;;;; +114BF;TIRHUTA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +114C0;TIRHUTA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +114C1;TIRHUTA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +114C2;TIRHUTA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +114C3;TIRHUTA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +114C4;TIRHUTA SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +114C5;TIRHUTA GVANG;Lo;0;L;;;;;N;;;;; +114C6;TIRHUTA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +114C7;TIRHUTA OM;Lo;0;L;;;;;N;;;;; +114D0;TIRHUTA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +114D1;TIRHUTA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +114D2;TIRHUTA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +114D3;TIRHUTA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +114D4;TIRHUTA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +114D5;TIRHUTA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +114D6;TIRHUTA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +114D7;TIRHUTA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +114D8;TIRHUTA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +114D9;TIRHUTA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11580;SIDDHAM LETTER A;Lo;0;L;;;;;N;;;;; +11581;SIDDHAM LETTER AA;Lo;0;L;;;;;N;;;;; +11582;SIDDHAM LETTER I;Lo;0;L;;;;;N;;;;; +11583;SIDDHAM LETTER II;Lo;0;L;;;;;N;;;;; +11584;SIDDHAM LETTER U;Lo;0;L;;;;;N;;;;; +11585;SIDDHAM LETTER UU;Lo;0;L;;;;;N;;;;; +11586;SIDDHAM LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11587;SIDDHAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11588;SIDDHAM LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11589;SIDDHAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1158A;SIDDHAM LETTER E;Lo;0;L;;;;;N;;;;; +1158B;SIDDHAM LETTER AI;Lo;0;L;;;;;N;;;;; +1158C;SIDDHAM LETTER O;Lo;0;L;;;;;N;;;;; +1158D;SIDDHAM LETTER AU;Lo;0;L;;;;;N;;;;; +1158E;SIDDHAM LETTER KA;Lo;0;L;;;;;N;;;;; +1158F;SIDDHAM LETTER KHA;Lo;0;L;;;;;N;;;;; +11590;SIDDHAM LETTER GA;Lo;0;L;;;;;N;;;;; +11591;SIDDHAM LETTER GHA;Lo;0;L;;;;;N;;;;; +11592;SIDDHAM LETTER NGA;Lo;0;L;;;;;N;;;;; +11593;SIDDHAM LETTER CA;Lo;0;L;;;;;N;;;;; +11594;SIDDHAM LETTER CHA;Lo;0;L;;;;;N;;;;; +11595;SIDDHAM LETTER JA;Lo;0;L;;;;;N;;;;; +11596;SIDDHAM LETTER JHA;Lo;0;L;;;;;N;;;;; +11597;SIDDHAM LETTER NYA;Lo;0;L;;;;;N;;;;; +11598;SIDDHAM LETTER TTA;Lo;0;L;;;;;N;;;;; +11599;SIDDHAM LETTER TTHA;Lo;0;L;;;;;N;;;;; +1159A;SIDDHAM LETTER DDA;Lo;0;L;;;;;N;;;;; +1159B;SIDDHAM LETTER DDHA;Lo;0;L;;;;;N;;;;; +1159C;SIDDHAM LETTER NNA;Lo;0;L;;;;;N;;;;; +1159D;SIDDHAM LETTER TA;Lo;0;L;;;;;N;;;;; +1159E;SIDDHAM LETTER THA;Lo;0;L;;;;;N;;;;; +1159F;SIDDHAM LETTER DA;Lo;0;L;;;;;N;;;;; +115A0;SIDDHAM LETTER DHA;Lo;0;L;;;;;N;;;;; +115A1;SIDDHAM LETTER NA;Lo;0;L;;;;;N;;;;; +115A2;SIDDHAM LETTER PA;Lo;0;L;;;;;N;;;;; +115A3;SIDDHAM LETTER PHA;Lo;0;L;;;;;N;;;;; +115A4;SIDDHAM LETTER BA;Lo;0;L;;;;;N;;;;; +115A5;SIDDHAM LETTER BHA;Lo;0;L;;;;;N;;;;; +115A6;SIDDHAM LETTER MA;Lo;0;L;;;;;N;;;;; +115A7;SIDDHAM LETTER YA;Lo;0;L;;;;;N;;;;; +115A8;SIDDHAM LETTER RA;Lo;0;L;;;;;N;;;;; +115A9;SIDDHAM LETTER LA;Lo;0;L;;;;;N;;;;; +115AA;SIDDHAM LETTER VA;Lo;0;L;;;;;N;;;;; +115AB;SIDDHAM LETTER SHA;Lo;0;L;;;;;N;;;;; +115AC;SIDDHAM LETTER SSA;Lo;0;L;;;;;N;;;;; +115AD;SIDDHAM LETTER SA;Lo;0;L;;;;;N;;;;; +115AE;SIDDHAM LETTER HA;Lo;0;L;;;;;N;;;;; +115AF;SIDDHAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +115B0;SIDDHAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +115B1;SIDDHAM VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +115B2;SIDDHAM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +115B3;SIDDHAM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +115B4;SIDDHAM VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +115B5;SIDDHAM VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +115B8;SIDDHAM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +115B9;SIDDHAM VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +115BA;SIDDHAM VOWEL SIGN O;Mc;0;L;115B8 115AF;;;;N;;;;; +115BB;SIDDHAM VOWEL SIGN AU;Mc;0;L;115B9 115AF;;;;N;;;;; +115BC;SIDDHAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +115BD;SIDDHAM SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +115BE;SIDDHAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; +115BF;SIDDHAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +115C0;SIDDHAM SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +115C1;SIDDHAM SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +115C2;SIDDHAM DANDA;Po;0;L;;;;;N;;;;; +115C3;SIDDHAM DOUBLE DANDA;Po;0;L;;;;;N;;;;; +115C4;SIDDHAM SEPARATOR DOT;Po;0;L;;;;;N;;;;; +115C5;SIDDHAM SEPARATOR BAR;Po;0;L;;;;;N;;;;; +115C6;SIDDHAM REPETITION MARK-1;Po;0;L;;;;;N;;;;; +115C7;SIDDHAM REPETITION MARK-2;Po;0;L;;;;;N;;;;; +115C8;SIDDHAM REPETITION MARK-3;Po;0;L;;;;;N;;;;; +115C9;SIDDHAM END OF TEXT MARK;Po;0;L;;;;;N;;;;; +115CA;SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS;Po;0;L;;;;;N;;;;; +115CB;SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; +115CC;SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;; +115CD;SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; +115CE;SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115CF;SIDDHAM SECTION MARK DOUBLE RING;Po;0;L;;;;;N;;;;; +115D0;SIDDHAM SECTION MARK DOUBLE RING WITH RAYS;Po;0;L;;;;;N;;;;; +115D1;SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D2;SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D3;SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D4;SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS;Po;0;L;;;;;N;;;;; +115D5;SIDDHAM SECTION MARK WITH CIRCLES AND RAYS;Po;0;L;;;;;N;;;;; +115D6;SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES;Po;0;L;;;;;N;;;;; +115D7;SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES;Po;0;L;;;;;N;;;;; +115D8;SIDDHAM LETTER THREE-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; +115D9;SIDDHAM LETTER TWO-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;; +115DA;SIDDHAM LETTER TWO-CIRCLE ALTERNATE II;Lo;0;L;;;;;N;;;;; +115DB;SIDDHAM LETTER ALTERNATE U;Lo;0;L;;;;;N;;;;; +115DC;SIDDHAM VOWEL SIGN ALTERNATE U;Mn;0;NSM;;;;;N;;;;; +115DD;SIDDHAM VOWEL SIGN ALTERNATE UU;Mn;0;NSM;;;;;N;;;;; +11600;MODI LETTER A;Lo;0;L;;;;;N;;;;; +11601;MODI LETTER AA;Lo;0;L;;;;;N;;;;; +11602;MODI LETTER I;Lo;0;L;;;;;N;;;;; +11603;MODI LETTER II;Lo;0;L;;;;;N;;;;; +11604;MODI LETTER U;Lo;0;L;;;;;N;;;;; +11605;MODI LETTER UU;Lo;0;L;;;;;N;;;;; +11606;MODI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11607;MODI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11608;MODI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11609;MODI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1160A;MODI LETTER E;Lo;0;L;;;;;N;;;;; +1160B;MODI LETTER AI;Lo;0;L;;;;;N;;;;; +1160C;MODI LETTER O;Lo;0;L;;;;;N;;;;; +1160D;MODI LETTER AU;Lo;0;L;;;;;N;;;;; +1160E;MODI LETTER KA;Lo;0;L;;;;;N;;;;; +1160F;MODI LETTER KHA;Lo;0;L;;;;;N;;;;; +11610;MODI LETTER GA;Lo;0;L;;;;;N;;;;; +11611;MODI LETTER GHA;Lo;0;L;;;;;N;;;;; +11612;MODI LETTER NGA;Lo;0;L;;;;;N;;;;; +11613;MODI LETTER CA;Lo;0;L;;;;;N;;;;; +11614;MODI LETTER CHA;Lo;0;L;;;;;N;;;;; +11615;MODI LETTER JA;Lo;0;L;;;;;N;;;;; +11616;MODI LETTER JHA;Lo;0;L;;;;;N;;;;; +11617;MODI LETTER NYA;Lo;0;L;;;;;N;;;;; +11618;MODI LETTER TTA;Lo;0;L;;;;;N;;;;; +11619;MODI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1161A;MODI LETTER DDA;Lo;0;L;;;;;N;;;;; +1161B;MODI LETTER DDHA;Lo;0;L;;;;;N;;;;; +1161C;MODI LETTER NNA;Lo;0;L;;;;;N;;;;; +1161D;MODI LETTER TA;Lo;0;L;;;;;N;;;;; +1161E;MODI LETTER THA;Lo;0;L;;;;;N;;;;; +1161F;MODI LETTER DA;Lo;0;L;;;;;N;;;;; +11620;MODI LETTER DHA;Lo;0;L;;;;;N;;;;; +11621;MODI LETTER NA;Lo;0;L;;;;;N;;;;; +11622;MODI LETTER PA;Lo;0;L;;;;;N;;;;; +11623;MODI LETTER PHA;Lo;0;L;;;;;N;;;;; +11624;MODI LETTER BA;Lo;0;L;;;;;N;;;;; +11625;MODI LETTER BHA;Lo;0;L;;;;;N;;;;; +11626;MODI LETTER MA;Lo;0;L;;;;;N;;;;; +11627;MODI LETTER YA;Lo;0;L;;;;;N;;;;; +11628;MODI LETTER RA;Lo;0;L;;;;;N;;;;; +11629;MODI LETTER LA;Lo;0;L;;;;;N;;;;; +1162A;MODI LETTER VA;Lo;0;L;;;;;N;;;;; +1162B;MODI LETTER SHA;Lo;0;L;;;;;N;;;;; +1162C;MODI LETTER SSA;Lo;0;L;;;;;N;;;;; +1162D;MODI LETTER SA;Lo;0;L;;;;;N;;;;; +1162E;MODI LETTER HA;Lo;0;L;;;;;N;;;;; +1162F;MODI LETTER LLA;Lo;0;L;;;;;N;;;;; +11630;MODI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11631;MODI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11632;MODI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11633;MODI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11634;MODI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11635;MODI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11636;MODI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11637;MODI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11638;MODI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +11639;MODI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +1163A;MODI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1163B;MODI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1163C;MODI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +1163D;MODI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1163E;MODI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +1163F;MODI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11640;MODI SIGN ARDHACANDRA;Mn;0;NSM;;;;;N;;;;; +11641;MODI DANDA;Po;0;L;;;;;N;;;;; +11642;MODI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11643;MODI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +11644;MODI SIGN HUVA;Lo;0;L;;;;;N;;;;; +11650;MODI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11651;MODI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11652;MODI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11653;MODI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11654;MODI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11655;MODI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11656;MODI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11657;MODI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11658;MODI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11659;MODI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11660;MONGOLIAN BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11661;MONGOLIAN ROTATED BIRGA;Po;0;ON;;;;;N;;;;; +11662;MONGOLIAN DOUBLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11663;MONGOLIAN TRIPLE BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11664;MONGOLIAN BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11665;MONGOLIAN ROTATED BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +11666;MONGOLIAN ROTATED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11667;MONGOLIAN INVERTED BIRGA;Po;0;ON;;;;;N;;;;; +11668;MONGOLIAN INVERTED BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11669;MONGOLIAN SWIRL BIRGA;Po;0;ON;;;;;N;;;;; +1166A;MONGOLIAN SWIRL BIRGA WITH ORNAMENT;Po;0;ON;;;;;N;;;;; +1166B;MONGOLIAN SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +1166C;MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT;Po;0;ON;;;;;N;;;;; +11680;TAKRI LETTER A;Lo;0;L;;;;;N;;;;; +11681;TAKRI LETTER AA;Lo;0;L;;;;;N;;;;; +11682;TAKRI LETTER I;Lo;0;L;;;;;N;;;;; +11683;TAKRI LETTER II;Lo;0;L;;;;;N;;;;; +11684;TAKRI LETTER U;Lo;0;L;;;;;N;;;;; +11685;TAKRI LETTER UU;Lo;0;L;;;;;N;;;;; +11686;TAKRI LETTER E;Lo;0;L;;;;;N;;;;; +11687;TAKRI LETTER AI;Lo;0;L;;;;;N;;;;; +11688;TAKRI LETTER O;Lo;0;L;;;;;N;;;;; +11689;TAKRI LETTER AU;Lo;0;L;;;;;N;;;;; +1168A;TAKRI LETTER KA;Lo;0;L;;;;;N;;;;; +1168B;TAKRI LETTER KHA;Lo;0;L;;;;;N;;;;; +1168C;TAKRI LETTER GA;Lo;0;L;;;;;N;;;;; +1168D;TAKRI LETTER GHA;Lo;0;L;;;;;N;;;;; +1168E;TAKRI LETTER NGA;Lo;0;L;;;;;N;;;;; +1168F;TAKRI LETTER CA;Lo;0;L;;;;;N;;;;; +11690;TAKRI LETTER CHA;Lo;0;L;;;;;N;;;;; +11691;TAKRI LETTER JA;Lo;0;L;;;;;N;;;;; +11692;TAKRI LETTER JHA;Lo;0;L;;;;;N;;;;; +11693;TAKRI LETTER NYA;Lo;0;L;;;;;N;;;;; +11694;TAKRI LETTER TTA;Lo;0;L;;;;;N;;;;; +11695;TAKRI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11696;TAKRI LETTER DDA;Lo;0;L;;;;;N;;;;; +11697;TAKRI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11698;TAKRI LETTER NNA;Lo;0;L;;;;;N;;;;; +11699;TAKRI LETTER TA;Lo;0;L;;;;;N;;;;; +1169A;TAKRI LETTER THA;Lo;0;L;;;;;N;;;;; +1169B;TAKRI LETTER DA;Lo;0;L;;;;;N;;;;; +1169C;TAKRI LETTER DHA;Lo;0;L;;;;;N;;;;; +1169D;TAKRI LETTER NA;Lo;0;L;;;;;N;;;;; +1169E;TAKRI LETTER PA;Lo;0;L;;;;;N;;;;; +1169F;TAKRI LETTER PHA;Lo;0;L;;;;;N;;;;; +116A0;TAKRI LETTER BA;Lo;0;L;;;;;N;;;;; +116A1;TAKRI LETTER BHA;Lo;0;L;;;;;N;;;;; +116A2;TAKRI LETTER MA;Lo;0;L;;;;;N;;;;; +116A3;TAKRI LETTER YA;Lo;0;L;;;;;N;;;;; +116A4;TAKRI LETTER RA;Lo;0;L;;;;;N;;;;; +116A5;TAKRI LETTER LA;Lo;0;L;;;;;N;;;;; +116A6;TAKRI LETTER VA;Lo;0;L;;;;;N;;;;; +116A7;TAKRI LETTER SHA;Lo;0;L;;;;;N;;;;; +116A8;TAKRI LETTER SA;Lo;0;L;;;;;N;;;;; +116A9;TAKRI LETTER HA;Lo;0;L;;;;;N;;;;; +116AA;TAKRI LETTER RRA;Lo;0;L;;;;;N;;;;; +116AB;TAKRI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +116AC;TAKRI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +116AD;TAKRI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +116AE;TAKRI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +116AF;TAKRI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +116B0;TAKRI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +116B1;TAKRI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +116B2;TAKRI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +116B3;TAKRI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +116B4;TAKRI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +116B5;TAKRI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;; +116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +116B8;TAKRI LETTER ARCHAIC KHA;Lo;0;L;;;;;N;;;;; +116B9;TAKRI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +116C3;TAKRI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +116C4;TAKRI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +116C5;TAKRI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +116C6;TAKRI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +116D0;MYANMAR PAO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +116D1;MYANMAR PAO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +116D2;MYANMAR PAO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +116D3;MYANMAR PAO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +116D4;MYANMAR PAO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +116D5;MYANMAR PAO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +116D6;MYANMAR PAO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +116D7;MYANMAR PAO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +116D8;MYANMAR PAO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +116D9;MYANMAR PAO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +116DA;MYANMAR EASTERN PWO KAREN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +116DB;MYANMAR EASTERN PWO KAREN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +116DC;MYANMAR EASTERN PWO KAREN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +116DD;MYANMAR EASTERN PWO KAREN DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +116DE;MYANMAR EASTERN PWO KAREN DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +116DF;MYANMAR EASTERN PWO KAREN DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +116E0;MYANMAR EASTERN PWO KAREN DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +116E1;MYANMAR EASTERN PWO KAREN DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +116E2;MYANMAR EASTERN PWO KAREN DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +116E3;MYANMAR EASTERN PWO KAREN DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11700;AHOM LETTER KA;Lo;0;L;;;;;N;;;;; +11701;AHOM LETTER KHA;Lo;0;L;;;;;N;;;;; +11702;AHOM LETTER NGA;Lo;0;L;;;;;N;;;;; +11703;AHOM LETTER NA;Lo;0;L;;;;;N;;;;; +11704;AHOM LETTER TA;Lo;0;L;;;;;N;;;;; +11705;AHOM LETTER ALTERNATE TA;Lo;0;L;;;;;N;;;;; +11706;AHOM LETTER PA;Lo;0;L;;;;;N;;;;; +11707;AHOM LETTER PHA;Lo;0;L;;;;;N;;;;; +11708;AHOM LETTER BA;Lo;0;L;;;;;N;;;;; +11709;AHOM LETTER MA;Lo;0;L;;;;;N;;;;; +1170A;AHOM LETTER JA;Lo;0;L;;;;;N;;;;; +1170B;AHOM LETTER CHA;Lo;0;L;;;;;N;;;;; +1170C;AHOM LETTER THA;Lo;0;L;;;;;N;;;;; +1170D;AHOM LETTER RA;Lo;0;L;;;;;N;;;;; +1170E;AHOM LETTER LA;Lo;0;L;;;;;N;;;;; +1170F;AHOM LETTER SA;Lo;0;L;;;;;N;;;;; +11710;AHOM LETTER NYA;Lo;0;L;;;;;N;;;;; +11711;AHOM LETTER HA;Lo;0;L;;;;;N;;;;; +11712;AHOM LETTER A;Lo;0;L;;;;;N;;;;; +11713;AHOM LETTER DA;Lo;0;L;;;;;N;;;;; +11714;AHOM LETTER DHA;Lo;0;L;;;;;N;;;;; +11715;AHOM LETTER GA;Lo;0;L;;;;;N;;;;; +11716;AHOM LETTER ALTERNATE GA;Lo;0;L;;;;;N;;;;; +11717;AHOM LETTER GHA;Lo;0;L;;;;;N;;;;; +11718;AHOM LETTER BHA;Lo;0;L;;;;;N;;;;; +11719;AHOM LETTER JHA;Lo;0;L;;;;;N;;;;; +1171A;AHOM LETTER ALTERNATE BA;Lo;0;L;;;;;N;;;;; +1171D;AHOM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;; +1171E;AHOM CONSONANT SIGN MEDIAL RA;Mc;0;L;;;;;N;;;;; +1171F;AHOM CONSONANT SIGN MEDIAL LIGATING RA;Mn;0;NSM;;;;;N;;;;; +11720;AHOM VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +11721;AHOM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11722;AHOM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11723;AHOM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11724;AHOM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11725;AHOM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11726;AHOM VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +11727;AHOM VOWEL SIGN AW;Mn;0;NSM;;;;;N;;;;; +11728;AHOM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11729;AHOM VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +1172A;AHOM VOWEL SIGN AM;Mn;0;NSM;;;;;N;;;;; +1172B;AHOM SIGN KILLER;Mn;9;NSM;;;;;N;;;;; +11730;AHOM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11731;AHOM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11732;AHOM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11733;AHOM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11734;AHOM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11735;AHOM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11736;AHOM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11737;AHOM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11738;AHOM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11739;AHOM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1173A;AHOM NUMBER TEN;No;0;L;;;;10;N;;;;; +1173B;AHOM NUMBER TWENTY;No;0;L;;;;20;N;;;;; +1173C;AHOM SIGN SMALL SECTION;Po;0;L;;;;;N;;;;; +1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;; +1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;; +1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;; +11740;AHOM LETTER CA;Lo;0;L;;;;;N;;;;; +11741;AHOM LETTER TTA;Lo;0;L;;;;;N;;;;; +11742;AHOM LETTER TTHA;Lo;0;L;;;;;N;;;;; +11743;AHOM LETTER DDA;Lo;0;L;;;;;N;;;;; +11744;AHOM LETTER DDHA;Lo;0;L;;;;;N;;;;; +11745;AHOM LETTER NNA;Lo;0;L;;;;;N;;;;; +11746;AHOM LETTER LLA;Lo;0;L;;;;;N;;;;; +11800;DOGRA LETTER A;Lo;0;L;;;;;N;;;;; +11801;DOGRA LETTER AA;Lo;0;L;;;;;N;;;;; +11802;DOGRA LETTER I;Lo;0;L;;;;;N;;;;; +11803;DOGRA LETTER II;Lo;0;L;;;;;N;;;;; +11804;DOGRA LETTER U;Lo;0;L;;;;;N;;;;; +11805;DOGRA LETTER UU;Lo;0;L;;;;;N;;;;; +11806;DOGRA LETTER E;Lo;0;L;;;;;N;;;;; +11807;DOGRA LETTER AI;Lo;0;L;;;;;N;;;;; +11808;DOGRA LETTER O;Lo;0;L;;;;;N;;;;; +11809;DOGRA LETTER AU;Lo;0;L;;;;;N;;;;; +1180A;DOGRA LETTER KA;Lo;0;L;;;;;N;;;;; +1180B;DOGRA LETTER KHA;Lo;0;L;;;;;N;;;;; +1180C;DOGRA LETTER GA;Lo;0;L;;;;;N;;;;; +1180D;DOGRA LETTER GHA;Lo;0;L;;;;;N;;;;; +1180E;DOGRA LETTER NGA;Lo;0;L;;;;;N;;;;; +1180F;DOGRA LETTER CA;Lo;0;L;;;;;N;;;;; +11810;DOGRA LETTER CHA;Lo;0;L;;;;;N;;;;; +11811;DOGRA LETTER JA;Lo;0;L;;;;;N;;;;; +11812;DOGRA LETTER JHA;Lo;0;L;;;;;N;;;;; +11813;DOGRA LETTER NYA;Lo;0;L;;;;;N;;;;; +11814;DOGRA LETTER TTA;Lo;0;L;;;;;N;;;;; +11815;DOGRA LETTER TTHA;Lo;0;L;;;;;N;;;;; +11816;DOGRA LETTER DDA;Lo;0;L;;;;;N;;;;; +11817;DOGRA LETTER DDHA;Lo;0;L;;;;;N;;;;; +11818;DOGRA LETTER NNA;Lo;0;L;;;;;N;;;;; +11819;DOGRA LETTER TA;Lo;0;L;;;;;N;;;;; +1181A;DOGRA LETTER THA;Lo;0;L;;;;;N;;;;; +1181B;DOGRA LETTER DA;Lo;0;L;;;;;N;;;;; +1181C;DOGRA LETTER DHA;Lo;0;L;;;;;N;;;;; +1181D;DOGRA LETTER NA;Lo;0;L;;;;;N;;;;; +1181E;DOGRA LETTER PA;Lo;0;L;;;;;N;;;;; +1181F;DOGRA LETTER PHA;Lo;0;L;;;;;N;;;;; +11820;DOGRA LETTER BA;Lo;0;L;;;;;N;;;;; +11821;DOGRA LETTER BHA;Lo;0;L;;;;;N;;;;; +11822;DOGRA LETTER MA;Lo;0;L;;;;;N;;;;; +11823;DOGRA LETTER YA;Lo;0;L;;;;;N;;;;; +11824;DOGRA LETTER RA;Lo;0;L;;;;;N;;;;; +11825;DOGRA LETTER LA;Lo;0;L;;;;;N;;;;; +11826;DOGRA LETTER VA;Lo;0;L;;;;;N;;;;; +11827;DOGRA LETTER SHA;Lo;0;L;;;;;N;;;;; +11828;DOGRA LETTER SSA;Lo;0;L;;;;;N;;;;; +11829;DOGRA LETTER SA;Lo;0;L;;;;;N;;;;; +1182A;DOGRA LETTER HA;Lo;0;L;;;;;N;;;;; +1182B;DOGRA LETTER RRA;Lo;0;L;;;;;N;;;;; +1182C;DOGRA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +1182D;DOGRA VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1182E;DOGRA VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +1182F;DOGRA VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11830;DOGRA VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11831;DOGRA VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11832;DOGRA VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11833;DOGRA VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11834;DOGRA VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11835;DOGRA VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11836;DOGRA VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11837;DOGRA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11838;DOGRA SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11839;DOGRA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +1183A;DOGRA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +1183B;DOGRA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +118A0;WARANG CITI CAPITAL LETTER NGAA;Lu;0;L;;;;;N;;;;118C0; +118A1;WARANG CITI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;118C1; +118A2;WARANG CITI CAPITAL LETTER WI;Lu;0;L;;;;;N;;;;118C2; +118A3;WARANG CITI CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;118C3; +118A4;WARANG CITI CAPITAL LETTER YA;Lu;0;L;;;;;N;;;;118C4; +118A5;WARANG CITI CAPITAL LETTER YO;Lu;0;L;;;;;N;;;;118C5; +118A6;WARANG CITI CAPITAL LETTER II;Lu;0;L;;;;;N;;;;118C6; +118A7;WARANG CITI CAPITAL LETTER UU;Lu;0;L;;;;;N;;;;118C7; +118A8;WARANG CITI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;118C8; +118A9;WARANG CITI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;118C9; +118AA;WARANG CITI CAPITAL LETTER ANG;Lu;0;L;;;;;N;;;;118CA; +118AB;WARANG CITI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;118CB; +118AC;WARANG CITI CAPITAL LETTER KO;Lu;0;L;;;;;N;;;;118CC; +118AD;WARANG CITI CAPITAL LETTER ENY;Lu;0;L;;;;;N;;;;118CD; +118AE;WARANG CITI CAPITAL LETTER YUJ;Lu;0;L;;;;;N;;;;118CE; +118AF;WARANG CITI CAPITAL LETTER UC;Lu;0;L;;;;;N;;;;118CF; +118B0;WARANG CITI CAPITAL LETTER ENN;Lu;0;L;;;;;N;;;;118D0; +118B1;WARANG CITI CAPITAL LETTER ODD;Lu;0;L;;;;;N;;;;118D1; +118B2;WARANG CITI CAPITAL LETTER TTE;Lu;0;L;;;;;N;;;;118D2; +118B3;WARANG CITI CAPITAL LETTER NUNG;Lu;0;L;;;;;N;;;;118D3; +118B4;WARANG CITI CAPITAL LETTER DA;Lu;0;L;;;;;N;;;;118D4; +118B5;WARANG CITI CAPITAL LETTER AT;Lu;0;L;;;;;N;;;;118D5; +118B6;WARANG CITI CAPITAL LETTER AM;Lu;0;L;;;;;N;;;;118D6; +118B7;WARANG CITI CAPITAL LETTER BU;Lu;0;L;;;;;N;;;;118D7; +118B8;WARANG CITI CAPITAL LETTER PU;Lu;0;L;;;;;N;;;;118D8; +118B9;WARANG CITI CAPITAL LETTER HIYO;Lu;0;L;;;;;N;;;;118D9; +118BA;WARANG CITI CAPITAL LETTER HOLO;Lu;0;L;;;;;N;;;;118DA; +118BB;WARANG CITI CAPITAL LETTER HORR;Lu;0;L;;;;;N;;;;118DB; +118BC;WARANG CITI CAPITAL LETTER HAR;Lu;0;L;;;;;N;;;;118DC; +118BD;WARANG CITI CAPITAL LETTER SSUU;Lu;0;L;;;;;N;;;;118DD; +118BE;WARANG CITI CAPITAL LETTER SII;Lu;0;L;;;;;N;;;;118DE; +118BF;WARANG CITI CAPITAL LETTER VIYO;Lu;0;L;;;;;N;;;;118DF; +118C0;WARANG CITI SMALL LETTER NGAA;Ll;0;L;;;;;N;;;118A0;;118A0 +118C1;WARANG CITI SMALL LETTER A;Ll;0;L;;;;;N;;;118A1;;118A1 +118C2;WARANG CITI SMALL LETTER WI;Ll;0;L;;;;;N;;;118A2;;118A2 +118C3;WARANG CITI SMALL LETTER YU;Ll;0;L;;;;;N;;;118A3;;118A3 +118C4;WARANG CITI SMALL LETTER YA;Ll;0;L;;;;;N;;;118A4;;118A4 +118C5;WARANG CITI SMALL LETTER YO;Ll;0;L;;;;;N;;;118A5;;118A5 +118C6;WARANG CITI SMALL LETTER II;Ll;0;L;;;;;N;;;118A6;;118A6 +118C7;WARANG CITI SMALL LETTER UU;Ll;0;L;;;;;N;;;118A7;;118A7 +118C8;WARANG CITI SMALL LETTER E;Ll;0;L;;;;;N;;;118A8;;118A8 +118C9;WARANG CITI SMALL LETTER O;Ll;0;L;;;;;N;;;118A9;;118A9 +118CA;WARANG CITI SMALL LETTER ANG;Ll;0;L;;;;;N;;;118AA;;118AA +118CB;WARANG CITI SMALL LETTER GA;Ll;0;L;;;;;N;;;118AB;;118AB +118CC;WARANG CITI SMALL LETTER KO;Ll;0;L;;;;;N;;;118AC;;118AC +118CD;WARANG CITI SMALL LETTER ENY;Ll;0;L;;;;;N;;;118AD;;118AD +118CE;WARANG CITI SMALL LETTER YUJ;Ll;0;L;;;;;N;;;118AE;;118AE +118CF;WARANG CITI SMALL LETTER UC;Ll;0;L;;;;;N;;;118AF;;118AF +118D0;WARANG CITI SMALL LETTER ENN;Ll;0;L;;;;;N;;;118B0;;118B0 +118D1;WARANG CITI SMALL LETTER ODD;Ll;0;L;;;;;N;;;118B1;;118B1 +118D2;WARANG CITI SMALL LETTER TTE;Ll;0;L;;;;;N;;;118B2;;118B2 +118D3;WARANG CITI SMALL LETTER NUNG;Ll;0;L;;;;;N;;;118B3;;118B3 +118D4;WARANG CITI SMALL LETTER DA;Ll;0;L;;;;;N;;;118B4;;118B4 +118D5;WARANG CITI SMALL LETTER AT;Ll;0;L;;;;;N;;;118B5;;118B5 +118D6;WARANG CITI SMALL LETTER AM;Ll;0;L;;;;;N;;;118B6;;118B6 +118D7;WARANG CITI SMALL LETTER BU;Ll;0;L;;;;;N;;;118B7;;118B7 +118D8;WARANG CITI SMALL LETTER PU;Ll;0;L;;;;;N;;;118B8;;118B8 +118D9;WARANG CITI SMALL LETTER HIYO;Ll;0;L;;;;;N;;;118B9;;118B9 +118DA;WARANG CITI SMALL LETTER HOLO;Ll;0;L;;;;;N;;;118BA;;118BA +118DB;WARANG CITI SMALL LETTER HORR;Ll;0;L;;;;;N;;;118BB;;118BB +118DC;WARANG CITI SMALL LETTER HAR;Ll;0;L;;;;;N;;;118BC;;118BC +118DD;WARANG CITI SMALL LETTER SSUU;Ll;0;L;;;;;N;;;118BD;;118BD +118DE;WARANG CITI SMALL LETTER SII;Ll;0;L;;;;;N;;;118BE;;118BE +118DF;WARANG CITI SMALL LETTER VIYO;Ll;0;L;;;;;N;;;118BF;;118BF +118E0;WARANG CITI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +118E1;WARANG CITI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +118E2;WARANG CITI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +118E3;WARANG CITI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +118E4;WARANG CITI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +118E5;WARANG CITI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +118E6;WARANG CITI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +118E7;WARANG CITI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +118E8;WARANG CITI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +118E9;WARANG CITI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +118EA;WARANG CITI NUMBER TEN;No;0;L;;;;10;N;;;;; +118EB;WARANG CITI NUMBER TWENTY;No;0;L;;;;20;N;;;;; +118EC;WARANG CITI NUMBER THIRTY;No;0;L;;;;30;N;;;;; +118ED;WARANG CITI NUMBER FORTY;No;0;L;;;;40;N;;;;; +118EE;WARANG CITI NUMBER FIFTY;No;0;L;;;;50;N;;;;; +118EF;WARANG CITI NUMBER SIXTY;No;0;L;;;;60;N;;;;; +118F0;WARANG CITI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;; +118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;; +11900;DIVES AKURU LETTER A;Lo;0;L;;;;;N;;;;; +11901;DIVES AKURU LETTER AA;Lo;0;L;;;;;N;;;;; +11902;DIVES AKURU LETTER I;Lo;0;L;;;;;N;;;;; +11903;DIVES AKURU LETTER II;Lo;0;L;;;;;N;;;;; +11904;DIVES AKURU LETTER U;Lo;0;L;;;;;N;;;;; +11905;DIVES AKURU LETTER UU;Lo;0;L;;;;;N;;;;; +11906;DIVES AKURU LETTER E;Lo;0;L;;;;;N;;;;; +11909;DIVES AKURU LETTER O;Lo;0;L;;;;;N;;;;; +1190C;DIVES AKURU LETTER KA;Lo;0;L;;;;;N;;;;; +1190D;DIVES AKURU LETTER KHA;Lo;0;L;;;;;N;;;;; +1190E;DIVES AKURU LETTER GA;Lo;0;L;;;;;N;;;;; +1190F;DIVES AKURU LETTER GHA;Lo;0;L;;;;;N;;;;; +11910;DIVES AKURU LETTER NGA;Lo;0;L;;;;;N;;;;; +11911;DIVES AKURU LETTER CA;Lo;0;L;;;;;N;;;;; +11912;DIVES AKURU LETTER CHA;Lo;0;L;;;;;N;;;;; +11913;DIVES AKURU LETTER JA;Lo;0;L;;;;;N;;;;; +11915;DIVES AKURU LETTER NYA;Lo;0;L;;;;;N;;;;; +11916;DIVES AKURU LETTER TTA;Lo;0;L;;;;;N;;;;; +11918;DIVES AKURU LETTER DDA;Lo;0;L;;;;;N;;;;; +11919;DIVES AKURU LETTER DDHA;Lo;0;L;;;;;N;;;;; +1191A;DIVES AKURU LETTER NNA;Lo;0;L;;;;;N;;;;; +1191B;DIVES AKURU LETTER TA;Lo;0;L;;;;;N;;;;; +1191C;DIVES AKURU LETTER THA;Lo;0;L;;;;;N;;;;; +1191D;DIVES AKURU LETTER DA;Lo;0;L;;;;;N;;;;; +1191E;DIVES AKURU LETTER DHA;Lo;0;L;;;;;N;;;;; +1191F;DIVES AKURU LETTER NA;Lo;0;L;;;;;N;;;;; +11920;DIVES AKURU LETTER PA;Lo;0;L;;;;;N;;;;; +11921;DIVES AKURU LETTER PHA;Lo;0;L;;;;;N;;;;; +11922;DIVES AKURU LETTER BA;Lo;0;L;;;;;N;;;;; +11923;DIVES AKURU LETTER BHA;Lo;0;L;;;;;N;;;;; +11924;DIVES AKURU LETTER MA;Lo;0;L;;;;;N;;;;; +11925;DIVES AKURU LETTER YA;Lo;0;L;;;;;N;;;;; +11926;DIVES AKURU LETTER YYA;Lo;0;L;;;;;N;;;;; +11927;DIVES AKURU LETTER RA;Lo;0;L;;;;;N;;;;; +11928;DIVES AKURU LETTER LA;Lo;0;L;;;;;N;;;;; +11929;DIVES AKURU LETTER VA;Lo;0;L;;;;;N;;;;; +1192A;DIVES AKURU LETTER SHA;Lo;0;L;;;;;N;;;;; +1192B;DIVES AKURU LETTER SSA;Lo;0;L;;;;;N;;;;; +1192C;DIVES AKURU LETTER SA;Lo;0;L;;;;;N;;;;; +1192D;DIVES AKURU LETTER HA;Lo;0;L;;;;;N;;;;; +1192E;DIVES AKURU LETTER LLA;Lo;0;L;;;;;N;;;;; +1192F;DIVES AKURU LETTER ZA;Lo;0;L;;;;;N;;;;; +11930;DIVES AKURU VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11931;DIVES AKURU VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11932;DIVES AKURU VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11933;DIVES AKURU VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +11934;DIVES AKURU VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +11935;DIVES AKURU VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +11937;DIVES AKURU VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11938;DIVES AKURU VOWEL SIGN O;Mc;0;L;11935 11930;;;;N;;;;; +1193B;DIVES AKURU SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1193C;DIVES AKURU SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +1193D;DIVES AKURU SIGN HALANTA;Mc;9;L;;;;;N;;;;; +1193E;DIVES AKURU VIRAMA;Mn;9;NSM;;;;;N;;;;; +1193F;DIVES AKURU PREFIXED NASAL SIGN;Lo;0;L;;;;;N;;;;; +11940;DIVES AKURU MEDIAL YA;Mc;0;L;;;;;N;;;;; +11941;DIVES AKURU INITIAL RA;Lo;0;L;;;;;N;;;;; +11942;DIVES AKURU MEDIAL RA;Mc;0;L;;;;;N;;;;; +11943;DIVES AKURU SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11944;DIVES AKURU DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11945;DIVES AKURU GAP FILLER;Po;0;L;;;;;N;;;;; +11946;DIVES AKURU END OF TEXT MARK;Po;0;L;;;;;N;;;;; +11950;DIVES AKURU DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11951;DIVES AKURU DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11952;DIVES AKURU DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11953;DIVES AKURU DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11954;DIVES AKURU DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11955;DIVES AKURU DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11956;DIVES AKURU DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11957;DIVES AKURU DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11958;DIVES AKURU DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11959;DIVES AKURU DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +119A0;NANDINAGARI LETTER A;Lo;0;L;;;;;N;;;;; +119A1;NANDINAGARI LETTER AA;Lo;0;L;;;;;N;;;;; +119A2;NANDINAGARI LETTER I;Lo;0;L;;;;;N;;;;; +119A3;NANDINAGARI LETTER II;Lo;0;L;;;;;N;;;;; +119A4;NANDINAGARI LETTER U;Lo;0;L;;;;;N;;;;; +119A5;NANDINAGARI LETTER UU;Lo;0;L;;;;;N;;;;; +119A6;NANDINAGARI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +119A7;NANDINAGARI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +119AA;NANDINAGARI LETTER E;Lo;0;L;;;;;N;;;;; +119AB;NANDINAGARI LETTER AI;Lo;0;L;;;;;N;;;;; +119AC;NANDINAGARI LETTER O;Lo;0;L;;;;;N;;;;; +119AD;NANDINAGARI LETTER AU;Lo;0;L;;;;;N;;;;; +119AE;NANDINAGARI LETTER KA;Lo;0;L;;;;;N;;;;; +119AF;NANDINAGARI LETTER KHA;Lo;0;L;;;;;N;;;;; +119B0;NANDINAGARI LETTER GA;Lo;0;L;;;;;N;;;;; +119B1;NANDINAGARI LETTER GHA;Lo;0;L;;;;;N;;;;; +119B2;NANDINAGARI LETTER NGA;Lo;0;L;;;;;N;;;;; +119B3;NANDINAGARI LETTER CA;Lo;0;L;;;;;N;;;;; +119B4;NANDINAGARI LETTER CHA;Lo;0;L;;;;;N;;;;; +119B5;NANDINAGARI LETTER JA;Lo;0;L;;;;;N;;;;; +119B6;NANDINAGARI LETTER JHA;Lo;0;L;;;;;N;;;;; +119B7;NANDINAGARI LETTER NYA;Lo;0;L;;;;;N;;;;; +119B8;NANDINAGARI LETTER TTA;Lo;0;L;;;;;N;;;;; +119B9;NANDINAGARI LETTER TTHA;Lo;0;L;;;;;N;;;;; +119BA;NANDINAGARI LETTER DDA;Lo;0;L;;;;;N;;;;; +119BB;NANDINAGARI LETTER DDHA;Lo;0;L;;;;;N;;;;; +119BC;NANDINAGARI LETTER NNA;Lo;0;L;;;;;N;;;;; +119BD;NANDINAGARI LETTER TA;Lo;0;L;;;;;N;;;;; +119BE;NANDINAGARI LETTER THA;Lo;0;L;;;;;N;;;;; +119BF;NANDINAGARI LETTER DA;Lo;0;L;;;;;N;;;;; +119C0;NANDINAGARI LETTER DHA;Lo;0;L;;;;;N;;;;; +119C1;NANDINAGARI LETTER NA;Lo;0;L;;;;;N;;;;; +119C2;NANDINAGARI LETTER PA;Lo;0;L;;;;;N;;;;; +119C3;NANDINAGARI LETTER PHA;Lo;0;L;;;;;N;;;;; +119C4;NANDINAGARI LETTER BA;Lo;0;L;;;;;N;;;;; +119C5;NANDINAGARI LETTER BHA;Lo;0;L;;;;;N;;;;; +119C6;NANDINAGARI LETTER MA;Lo;0;L;;;;;N;;;;; +119C7;NANDINAGARI LETTER YA;Lo;0;L;;;;;N;;;;; +119C8;NANDINAGARI LETTER RA;Lo;0;L;;;;;N;;;;; +119C9;NANDINAGARI LETTER LA;Lo;0;L;;;;;N;;;;; +119CA;NANDINAGARI LETTER VA;Lo;0;L;;;;;N;;;;; +119CB;NANDINAGARI LETTER SHA;Lo;0;L;;;;;N;;;;; +119CC;NANDINAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; +119CD;NANDINAGARI LETTER SA;Lo;0;L;;;;;N;;;;; +119CE;NANDINAGARI LETTER HA;Lo;0;L;;;;;N;;;;; +119CF;NANDINAGARI LETTER LLA;Lo;0;L;;;;;N;;;;; +119D0;NANDINAGARI LETTER RRA;Lo;0;L;;;;;N;;;;; +119D1;NANDINAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +119D2;NANDINAGARI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +119D3;NANDINAGARI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +119D4;NANDINAGARI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +119D5;NANDINAGARI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +119D6;NANDINAGARI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +119D7;NANDINAGARI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +119DA;NANDINAGARI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +119DB;NANDINAGARI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +119DC;NANDINAGARI VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +119DD;NANDINAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +119DE;NANDINAGARI SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; +119DF;NANDINAGARI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +119E0;NANDINAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +119E1;NANDINAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +119E2;NANDINAGARI SIGN SIDDHAM;Po;0;L;;;;;N;;;;; +119E3;NANDINAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;; +119E4;NANDINAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; +11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;; +11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mn;0;L;;;;;N;;;;; +11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mn;0;L;;;;;N;;;;; +11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;; +11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;; +11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;; +11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;; +11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;; +11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;; +11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;; +11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;; +11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;; +11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;; +11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;; +11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;; +11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;; +11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;; +11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;; +11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;; +11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;; +11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;; +11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;; +11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;; +11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;; +11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;; +11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;; +11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;; +11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;; +11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;; +11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;; +11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;; +11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;; +11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;; +11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;; +11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;; +11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;; +11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;; +11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;; +11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;; +11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;; +11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;; +11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;; +11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;; +11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;; +11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;; +11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;; +11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;; +11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;; +11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;; +11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;; +11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;; +11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;; +11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;; +11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;; +11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;; +11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;; +11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;; +11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;; +11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;; +11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;; +11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;; +11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;; +11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;; +11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;; +11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;; +11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;; +11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;; +11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;; +11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;; +11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;; +11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;; +11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;; +11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;; +11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;; +11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;; +11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;; +11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;; +11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;; +11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;; +11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;; +11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;; +11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;; +11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;; +11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;; +11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;; +11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;; +11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;; +11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;; +11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;; +11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;; +11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;; +11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;; +11A84;SOYOMBO SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +11A85;SOYOMBO SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;; +11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;; +11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;; +11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;; +11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;; +11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;; +11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;; +11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;; +11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;; +11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;; +11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;; +11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;; +11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;; +11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;; +11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;; +11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;; +11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;; +11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;; +11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;; +11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;; +11A9D;SOYOMBO MARK PLUTA;Lo;0;L;;;;;N;;;;; +11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;; +11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;; +11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;; +11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;; +11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;; +11AB0;CANADIAN SYLLABICS NATTILIK HI;Lo;0;L;;;;;N;;;;; +11AB1;CANADIAN SYLLABICS NATTILIK HII;Lo;0;L;;;;;N;;;;; +11AB2;CANADIAN SYLLABICS NATTILIK HO;Lo;0;L;;;;;N;;;;; +11AB3;CANADIAN SYLLABICS NATTILIK HOO;Lo;0;L;;;;;N;;;;; +11AB4;CANADIAN SYLLABICS NATTILIK HA;Lo;0;L;;;;;N;;;;; +11AB5;CANADIAN SYLLABICS NATTILIK HAA;Lo;0;L;;;;;N;;;;; +11AB6;CANADIAN SYLLABICS NATTILIK SHRI;Lo;0;L;;;;;N;;;;; +11AB7;CANADIAN SYLLABICS NATTILIK SHRII;Lo;0;L;;;;;N;;;;; +11AB8;CANADIAN SYLLABICS NATTILIK SHRO;Lo;0;L;;;;;N;;;;; +11AB9;CANADIAN SYLLABICS NATTILIK SHROO;Lo;0;L;;;;;N;;;;; +11ABA;CANADIAN SYLLABICS NATTILIK SHRA;Lo;0;L;;;;;N;;;;; +11ABB;CANADIAN SYLLABICS NATTILIK SHRAA;Lo;0;L;;;;;N;;;;; +11ABC;CANADIAN SYLLABICS SPE;Lo;0;L;;;;;N;;;;; +11ABD;CANADIAN SYLLABICS SPI;Lo;0;L;;;;;N;;;;; +11ABE;CANADIAN SYLLABICS SPO;Lo;0;L;;;;;N;;;;; +11ABF;CANADIAN SYLLABICS SPA;Lo;0;L;;;;;N;;;;; +11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;; +11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;; +11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;; +11AC3;PAU CIN HAU LETTER MA;Lo;0;L;;;;;N;;;;; +11AC4;PAU CIN HAU LETTER DA;Lo;0;L;;;;;N;;;;; +11AC5;PAU CIN HAU LETTER ZA;Lo;0;L;;;;;N;;;;; +11AC6;PAU CIN HAU LETTER VA;Lo;0;L;;;;;N;;;;; +11AC7;PAU CIN HAU LETTER NGA;Lo;0;L;;;;;N;;;;; +11AC8;PAU CIN HAU LETTER HA;Lo;0;L;;;;;N;;;;; +11AC9;PAU CIN HAU LETTER GA;Lo;0;L;;;;;N;;;;; +11ACA;PAU CIN HAU LETTER KHA;Lo;0;L;;;;;N;;;;; +11ACB;PAU CIN HAU LETTER SA;Lo;0;L;;;;;N;;;;; +11ACC;PAU CIN HAU LETTER BA;Lo;0;L;;;;;N;;;;; +11ACD;PAU CIN HAU LETTER CA;Lo;0;L;;;;;N;;;;; +11ACE;PAU CIN HAU LETTER TA;Lo;0;L;;;;;N;;;;; +11ACF;PAU CIN HAU LETTER THA;Lo;0;L;;;;;N;;;;; +11AD0;PAU CIN HAU LETTER NA;Lo;0;L;;;;;N;;;;; +11AD1;PAU CIN HAU LETTER PHA;Lo;0;L;;;;;N;;;;; +11AD2;PAU CIN HAU LETTER RA;Lo;0;L;;;;;N;;;;; +11AD3;PAU CIN HAU LETTER FA;Lo;0;L;;;;;N;;;;; +11AD4;PAU CIN HAU LETTER CHA;Lo;0;L;;;;;N;;;;; +11AD5;PAU CIN HAU LETTER A;Lo;0;L;;;;;N;;;;; +11AD6;PAU CIN HAU LETTER E;Lo;0;L;;;;;N;;;;; +11AD7;PAU CIN HAU LETTER I;Lo;0;L;;;;;N;;;;; +11AD8;PAU CIN HAU LETTER O;Lo;0;L;;;;;N;;;;; +11AD9;PAU CIN HAU LETTER U;Lo;0;L;;;;;N;;;;; +11ADA;PAU CIN HAU LETTER UA;Lo;0;L;;;;;N;;;;; +11ADB;PAU CIN HAU LETTER IA;Lo;0;L;;;;;N;;;;; +11ADC;PAU CIN HAU LETTER FINAL P;Lo;0;L;;;;;N;;;;; +11ADD;PAU CIN HAU LETTER FINAL K;Lo;0;L;;;;;N;;;;; +11ADE;PAU CIN HAU LETTER FINAL T;Lo;0;L;;;;;N;;;;; +11ADF;PAU CIN HAU LETTER FINAL M;Lo;0;L;;;;;N;;;;; +11AE0;PAU CIN HAU LETTER FINAL N;Lo;0;L;;;;;N;;;;; +11AE1;PAU CIN HAU LETTER FINAL L;Lo;0;L;;;;;N;;;;; +11AE2;PAU CIN HAU LETTER FINAL W;Lo;0;L;;;;;N;;;;; +11AE3;PAU CIN HAU LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +11AE4;PAU CIN HAU LETTER FINAL Y;Lo;0;L;;;;;N;;;;; +11AE5;PAU CIN HAU RISING TONE LONG;Lo;0;L;;;;;N;;;;; +11AE6;PAU CIN HAU RISING TONE;Lo;0;L;;;;;N;;;;; +11AE7;PAU CIN HAU SANDHI GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +11AE8;PAU CIN HAU RISING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AE9;PAU CIN HAU RISING TONE FINAL;Lo;0;L;;;;;N;;;;; +11AEA;PAU CIN HAU SANDHI GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; +11AEB;PAU CIN HAU SANDHI TONE LONG;Lo;0;L;;;;;N;;;;; +11AEC;PAU CIN HAU SANDHI TONE;Lo;0;L;;;;;N;;;;; +11AED;PAU CIN HAU SANDHI TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AEE;PAU CIN HAU SANDHI TONE FINAL;Lo;0;L;;;;;N;;;;; +11AEF;PAU CIN HAU MID-LEVEL TONE;Lo;0;L;;;;;N;;;;; +11AF0;PAU CIN HAU GLOTTAL STOP VARIANT;Lo;0;L;;;;;N;;;;; +11AF1;PAU CIN HAU MID-LEVEL TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AF2;PAU CIN HAU MID-LEVEL TONE FINAL;Lo;0;L;;;;;N;;;;; +11AF3;PAU CIN HAU LOW-FALLING TONE LONG;Lo;0;L;;;;;N;;;;; +11AF4;PAU CIN HAU LOW-FALLING TONE;Lo;0;L;;;;;N;;;;; +11AF5;PAU CIN HAU GLOTTAL STOP;Lo;0;L;;;;;N;;;;; +11AF6;PAU CIN HAU LOW-FALLING TONE LONG FINAL;Lo;0;L;;;;;N;;;;; +11AF7;PAU CIN HAU LOW-FALLING TONE FINAL;Lo;0;L;;;;;N;;;;; +11AF8;PAU CIN HAU GLOTTAL STOP FINAL;Lo;0;L;;;;;N;;;;; +11B00;DEVANAGARI HEAD MARK;Po;0;L;;;;;N;;;;; +11B01;DEVANAGARI HEAD MARK WITH HEADSTROKE;Po;0;L;;;;;N;;;;; +11B02;DEVANAGARI SIGN BHALE;Po;0;L;;;;;N;;;;; +11B03;DEVANAGARI SIGN BHALE WITH HOOK;Po;0;L;;;;;N;;;;; +11B04;DEVANAGARI SIGN EXTENDED BHALE;Po;0;L;;;;;N;;;;; +11B05;DEVANAGARI SIGN EXTENDED BHALE WITH HOOK;Po;0;L;;;;;N;;;;; +11B06;DEVANAGARI SIGN WESTERN FIVE-LIKE BHALE;Po;0;L;;;;;N;;;;; +11B07;DEVANAGARI SIGN WESTERN NINE-LIKE BHALE;Po;0;L;;;;;N;;;;; +11B08;DEVANAGARI SIGN REVERSED NINE-LIKE BHALE;Po;0;L;;;;;N;;;;; +11B09;DEVANAGARI SIGN MINDU;Po;0;L;;;;;N;;;;; +11B60;SHARADA VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +11B61;SHARADA VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; +11B62;SHARADA VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +11B63;SHARADA VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; +11B64;SHARADA VOWEL SIGN SHORT E;Mn;0;NSM;;;;;N;;;;; +11B65;SHARADA VOWEL SIGN SHORT O;Mc;0;L;;;;;N;;;;; +11B66;SHARADA VOWEL SIGN CANDRA E;Mn;0;NSM;;;;;N;;;;; +11B67;SHARADA VOWEL SIGN CANDRA O;Mc;0;L;;;;;N;;;;; +11BC0;SUNUWAR LETTER DEVI;Lo;0;L;;;;;N;;;;; +11BC1;SUNUWAR LETTER TASLA;Lo;0;L;;;;;N;;;;; +11BC2;SUNUWAR LETTER EKO;Lo;0;L;;;;;N;;;;; +11BC3;SUNUWAR LETTER IMAR;Lo;0;L;;;;;N;;;;; +11BC4;SUNUWAR LETTER REU;Lo;0;L;;;;;N;;;;; +11BC5;SUNUWAR LETTER UTTHI;Lo;0;L;;;;;N;;;;; +11BC6;SUNUWAR LETTER KIK;Lo;0;L;;;;;N;;;;; +11BC7;SUNUWAR LETTER MA;Lo;0;L;;;;;N;;;;; +11BC8;SUNUWAR LETTER APPHO;Lo;0;L;;;;;N;;;;; +11BC9;SUNUWAR LETTER PIP;Lo;0;L;;;;;N;;;;; +11BCA;SUNUWAR LETTER GIL;Lo;0;L;;;;;N;;;;; +11BCB;SUNUWAR LETTER HAMSO;Lo;0;L;;;;;N;;;;; +11BCC;SUNUWAR LETTER CARMI;Lo;0;L;;;;;N;;;;; +11BCD;SUNUWAR LETTER NAH;Lo;0;L;;;;;N;;;;; +11BCE;SUNUWAR LETTER BUR;Lo;0;L;;;;;N;;;;; +11BCF;SUNUWAR LETTER JYAH;Lo;0;L;;;;;N;;;;; +11BD0;SUNUWAR LETTER LOACHA;Lo;0;L;;;;;N;;;;; +11BD1;SUNUWAR LETTER OTTHI;Lo;0;L;;;;;N;;;;; +11BD2;SUNUWAR LETTER SHYELE;Lo;0;L;;;;;N;;;;; +11BD3;SUNUWAR LETTER VARCA;Lo;0;L;;;;;N;;;;; +11BD4;SUNUWAR LETTER YAT;Lo;0;L;;;;;N;;;;; +11BD5;SUNUWAR LETTER AVA;Lo;0;L;;;;;N;;;;; +11BD6;SUNUWAR LETTER AAL;Lo;0;L;;;;;N;;;;; +11BD7;SUNUWAR LETTER DONGA;Lo;0;L;;;;;N;;;;; +11BD8;SUNUWAR LETTER THARI;Lo;0;L;;;;;N;;;;; +11BD9;SUNUWAR LETTER PHAR;Lo;0;L;;;;;N;;;;; +11BDA;SUNUWAR LETTER NGAR;Lo;0;L;;;;;N;;;;; +11BDB;SUNUWAR LETTER KHA;Lo;0;L;;;;;N;;;;; +11BDC;SUNUWAR LETTER SHYER;Lo;0;L;;;;;N;;;;; +11BDD;SUNUWAR LETTER CHELAP;Lo;0;L;;;;;N;;;;; +11BDE;SUNUWAR LETTER TENTU;Lo;0;L;;;;;N;;;;; +11BDF;SUNUWAR LETTER THELE;Lo;0;L;;;;;N;;;;; +11BE0;SUNUWAR LETTER KLOKO;Lo;0;L;;;;;N;;;;; +11BE1;SUNUWAR SIGN PVO;Po;0;L;;;;;N;;;;; +11BF0;SUNUWAR DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11BF1;SUNUWAR DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11BF2;SUNUWAR DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11BF3;SUNUWAR DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11BF4;SUNUWAR DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11BF5;SUNUWAR DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11BF6;SUNUWAR DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11BF7;SUNUWAR DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11BF8;SUNUWAR DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11BF9;SUNUWAR DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11C00;BHAIKSUKI LETTER A;Lo;0;L;;;;;N;;;;; +11C01;BHAIKSUKI LETTER AA;Lo;0;L;;;;;N;;;;; +11C02;BHAIKSUKI LETTER I;Lo;0;L;;;;;N;;;;; +11C03;BHAIKSUKI LETTER II;Lo;0;L;;;;;N;;;;; +11C04;BHAIKSUKI LETTER U;Lo;0;L;;;;;N;;;;; +11C05;BHAIKSUKI LETTER UU;Lo;0;L;;;;;N;;;;; +11C06;BHAIKSUKI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11C07;BHAIKSUKI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11C08;BHAIKSUKI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11C0A;BHAIKSUKI LETTER E;Lo;0;L;;;;;N;;;;; +11C0B;BHAIKSUKI LETTER AI;Lo;0;L;;;;;N;;;;; +11C0C;BHAIKSUKI LETTER O;Lo;0;L;;;;;N;;;;; +11C0D;BHAIKSUKI LETTER AU;Lo;0;L;;;;;N;;;;; +11C0E;BHAIKSUKI LETTER KA;Lo;0;L;;;;;N;;;;; +11C0F;BHAIKSUKI LETTER KHA;Lo;0;L;;;;;N;;;;; +11C10;BHAIKSUKI LETTER GA;Lo;0;L;;;;;N;;;;; +11C11;BHAIKSUKI LETTER GHA;Lo;0;L;;;;;N;;;;; +11C12;BHAIKSUKI LETTER NGA;Lo;0;L;;;;;N;;;;; +11C13;BHAIKSUKI LETTER CA;Lo;0;L;;;;;N;;;;; +11C14;BHAIKSUKI LETTER CHA;Lo;0;L;;;;;N;;;;; +11C15;BHAIKSUKI LETTER JA;Lo;0;L;;;;;N;;;;; +11C16;BHAIKSUKI LETTER JHA;Lo;0;L;;;;;N;;;;; +11C17;BHAIKSUKI LETTER NYA;Lo;0;L;;;;;N;;;;; +11C18;BHAIKSUKI LETTER TTA;Lo;0;L;;;;;N;;;;; +11C19;BHAIKSUKI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11C1A;BHAIKSUKI LETTER DDA;Lo;0;L;;;;;N;;;;; +11C1B;BHAIKSUKI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11C1C;BHAIKSUKI LETTER NNA;Lo;0;L;;;;;N;;;;; +11C1D;BHAIKSUKI LETTER TA;Lo;0;L;;;;;N;;;;; +11C1E;BHAIKSUKI LETTER THA;Lo;0;L;;;;;N;;;;; +11C1F;BHAIKSUKI LETTER DA;Lo;0;L;;;;;N;;;;; +11C20;BHAIKSUKI LETTER DHA;Lo;0;L;;;;;N;;;;; +11C21;BHAIKSUKI LETTER NA;Lo;0;L;;;;;N;;;;; +11C22;BHAIKSUKI LETTER PA;Lo;0;L;;;;;N;;;;; +11C23;BHAIKSUKI LETTER PHA;Lo;0;L;;;;;N;;;;; +11C24;BHAIKSUKI LETTER BA;Lo;0;L;;;;;N;;;;; +11C25;BHAIKSUKI LETTER BHA;Lo;0;L;;;;;N;;;;; +11C26;BHAIKSUKI LETTER MA;Lo;0;L;;;;;N;;;;; +11C27;BHAIKSUKI LETTER YA;Lo;0;L;;;;;N;;;;; +11C28;BHAIKSUKI LETTER RA;Lo;0;L;;;;;N;;;;; +11C29;BHAIKSUKI LETTER LA;Lo;0;L;;;;;N;;;;; +11C2A;BHAIKSUKI LETTER VA;Lo;0;L;;;;;N;;;;; +11C2B;BHAIKSUKI LETTER SHA;Lo;0;L;;;;;N;;;;; +11C2C;BHAIKSUKI LETTER SSA;Lo;0;L;;;;;N;;;;; +11C2D;BHAIKSUKI LETTER SA;Lo;0;L;;;;;N;;;;; +11C2E;BHAIKSUKI LETTER HA;Lo;0;L;;;;;N;;;;; +11C2F;BHAIKSUKI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11C30;BHAIKSUKI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11C31;BHAIKSUKI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11C32;BHAIKSUKI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11C33;BHAIKSUKI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11C34;BHAIKSUKI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11C35;BHAIKSUKI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11C36;BHAIKSUKI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11C38;BHAIKSUKI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11C39;BHAIKSUKI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11C3A;BHAIKSUKI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11C3B;BHAIKSUKI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11C3C;BHAIKSUKI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11C3D;BHAIKSUKI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11C3E;BHAIKSUKI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11C3F;BHAIKSUKI SIGN VIRAMA;Mn;9;L;;;;;N;;;;; +11C40;BHAIKSUKI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; +11C41;BHAIKSUKI DANDA;Po;0;L;;;;;N;;;;; +11C42;BHAIKSUKI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11C43;BHAIKSUKI WORD SEPARATOR;Po;0;L;;;;;N;;;;; +11C44;BHAIKSUKI GAP FILLER-1;Po;0;L;;;;;N;;;;; +11C45;BHAIKSUKI GAP FILLER-2;Po;0;L;;;;;N;;;;; +11C50;BHAIKSUKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11C51;BHAIKSUKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11C52;BHAIKSUKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11C53;BHAIKSUKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11C54;BHAIKSUKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11C55;BHAIKSUKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11C56;BHAIKSUKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11C57;BHAIKSUKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11C58;BHAIKSUKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11C59;BHAIKSUKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11C5A;BHAIKSUKI NUMBER ONE;No;0;L;;;;1;N;;;;; +11C5B;BHAIKSUKI NUMBER TWO;No;0;L;;;;2;N;;;;; +11C5C;BHAIKSUKI NUMBER THREE;No;0;L;;;;3;N;;;;; +11C5D;BHAIKSUKI NUMBER FOUR;No;0;L;;;;4;N;;;;; +11C5E;BHAIKSUKI NUMBER FIVE;No;0;L;;;;5;N;;;;; +11C5F;BHAIKSUKI NUMBER SIX;No;0;L;;;;6;N;;;;; +11C60;BHAIKSUKI NUMBER SEVEN;No;0;L;;;;7;N;;;;; +11C61;BHAIKSUKI NUMBER EIGHT;No;0;L;;;;8;N;;;;; +11C62;BHAIKSUKI NUMBER NINE;No;0;L;;;;9;N;;;;; +11C63;BHAIKSUKI NUMBER TEN;No;0;L;;;;10;N;;;;; +11C64;BHAIKSUKI NUMBER TWENTY;No;0;L;;;;20;N;;;;; +11C65;BHAIKSUKI NUMBER THIRTY;No;0;L;;;;30;N;;;;; +11C66;BHAIKSUKI NUMBER FORTY;No;0;L;;;;40;N;;;;; +11C67;BHAIKSUKI NUMBER FIFTY;No;0;L;;;;50;N;;;;; +11C68;BHAIKSUKI NUMBER SIXTY;No;0;L;;;;60;N;;;;; +11C69;BHAIKSUKI NUMBER SEVENTY;No;0;L;;;;70;N;;;;; +11C6A;BHAIKSUKI NUMBER EIGHTY;No;0;L;;;;80;N;;;;; +11C6B;BHAIKSUKI NUMBER NINETY;No;0;L;;;;90;N;;;;; +11C6C;BHAIKSUKI HUNDREDS UNIT MARK;No;0;L;;;;100;N;;;;; +11C70;MARCHEN HEAD MARK;Po;0;L;;;;;N;;;;; +11C71;MARCHEN MARK SHAD;Po;0;L;;;;;N;;;;; +11C72;MARCHEN LETTER KA;Lo;0;L;;;;;N;;;;; +11C73;MARCHEN LETTER KHA;Lo;0;L;;;;;N;;;;; +11C74;MARCHEN LETTER GA;Lo;0;L;;;;;N;;;;; +11C75;MARCHEN LETTER NGA;Lo;0;L;;;;;N;;;;; +11C76;MARCHEN LETTER CA;Lo;0;L;;;;;N;;;;; +11C77;MARCHEN LETTER CHA;Lo;0;L;;;;;N;;;;; +11C78;MARCHEN LETTER JA;Lo;0;L;;;;;N;;;;; +11C79;MARCHEN LETTER NYA;Lo;0;L;;;;;N;;;;; +11C7A;MARCHEN LETTER TA;Lo;0;L;;;;;N;;;;; +11C7B;MARCHEN LETTER THA;Lo;0;L;;;;;N;;;;; +11C7C;MARCHEN LETTER DA;Lo;0;L;;;;;N;;;;; +11C7D;MARCHEN LETTER NA;Lo;0;L;;;;;N;;;;; +11C7E;MARCHEN LETTER PA;Lo;0;L;;;;;N;;;;; +11C7F;MARCHEN LETTER PHA;Lo;0;L;;;;;N;;;;; +11C80;MARCHEN LETTER BA;Lo;0;L;;;;;N;;;;; +11C81;MARCHEN LETTER MA;Lo;0;L;;;;;N;;;;; +11C82;MARCHEN LETTER TSA;Lo;0;L;;;;;N;;;;; +11C83;MARCHEN LETTER TSHA;Lo;0;L;;;;;N;;;;; +11C84;MARCHEN LETTER DZA;Lo;0;L;;;;;N;;;;; +11C85;MARCHEN LETTER WA;Lo;0;L;;;;;N;;;;; +11C86;MARCHEN LETTER ZHA;Lo;0;L;;;;;N;;;;; +11C87;MARCHEN LETTER ZA;Lo;0;L;;;;;N;;;;; +11C88;MARCHEN LETTER -A;Lo;0;L;;;;;N;;;;; +11C89;MARCHEN LETTER YA;Lo;0;L;;;;;N;;;;; +11C8A;MARCHEN LETTER RA;Lo;0;L;;;;;N;;;;; +11C8B;MARCHEN LETTER LA;Lo;0;L;;;;;N;;;;; +11C8C;MARCHEN LETTER SHA;Lo;0;L;;;;;N;;;;; +11C8D;MARCHEN LETTER SA;Lo;0;L;;;;;N;;;;; +11C8E;MARCHEN LETTER HA;Lo;0;L;;;;;N;;;;; +11C8F;MARCHEN LETTER A;Lo;0;L;;;;;N;;;;; +11C92;MARCHEN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; +11C93;MARCHEN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; +11C94;MARCHEN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; +11C95;MARCHEN SUBJOINED LETTER NGA;Mn;0;NSM;;;;;N;;;;; +11C96;MARCHEN SUBJOINED LETTER CA;Mn;0;NSM;;;;;N;;;;; +11C97;MARCHEN SUBJOINED LETTER CHA;Mn;0;NSM;;;;;N;;;;; +11C98;MARCHEN SUBJOINED LETTER JA;Mn;0;NSM;;;;;N;;;;; +11C99;MARCHEN SUBJOINED LETTER NYA;Mn;0;NSM;;;;;N;;;;; +11C9A;MARCHEN SUBJOINED LETTER TA;Mn;0;NSM;;;;;N;;;;; +11C9B;MARCHEN SUBJOINED LETTER THA;Mn;0;NSM;;;;;N;;;;; +11C9C;MARCHEN SUBJOINED LETTER DA;Mn;0;NSM;;;;;N;;;;; +11C9D;MARCHEN SUBJOINED LETTER NA;Mn;0;NSM;;;;;N;;;;; +11C9E;MARCHEN SUBJOINED LETTER PA;Mn;0;NSM;;;;;N;;;;; +11C9F;MARCHEN SUBJOINED LETTER PHA;Mn;0;NSM;;;;;N;;;;; +11CA0;MARCHEN SUBJOINED LETTER BA;Mn;0;NSM;;;;;N;;;;; +11CA1;MARCHEN SUBJOINED LETTER MA;Mn;0;NSM;;;;;N;;;;; +11CA2;MARCHEN SUBJOINED LETTER TSA;Mn;0;NSM;;;;;N;;;;; +11CA3;MARCHEN SUBJOINED LETTER TSHA;Mn;0;NSM;;;;;N;;;;; +11CA4;MARCHEN SUBJOINED LETTER DZA;Mn;0;NSM;;;;;N;;;;; +11CA5;MARCHEN SUBJOINED LETTER WA;Mn;0;NSM;;;;;N;;;;; +11CA6;MARCHEN SUBJOINED LETTER ZHA;Mn;0;NSM;;;;;N;;;;; +11CA7;MARCHEN SUBJOINED LETTER ZA;Mn;0;NSM;;;;;N;;;;; +11CA9;MARCHEN SUBJOINED LETTER YA;Mc;0;L;;;;;N;;;;; +11CAA;MARCHEN SUBJOINED LETTER RA;Mn;0;NSM;;;;;N;;;;; +11CAB;MARCHEN SUBJOINED LETTER LA;Mn;0;NSM;;;;;N;;;;; +11CAC;MARCHEN SUBJOINED LETTER SHA;Mn;0;NSM;;;;;N;;;;; +11CAD;MARCHEN SUBJOINED LETTER SA;Mn;0;NSM;;;;;N;;;;; +11CAE;MARCHEN SUBJOINED LETTER HA;Mn;0;NSM;;;;;N;;;;; +11CAF;MARCHEN SUBJOINED LETTER A;Mn;0;NSM;;;;;N;;;;; +11CB0;MARCHEN VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11CB1;MARCHEN VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11CB2;MARCHEN VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11CB3;MARCHEN VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;; +11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;; +11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;; +11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;; +11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;; +11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;; +11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;; +11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;; +11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;; +11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; +11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;; +11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;; +11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;; +11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;; +11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11D60;GUNJALA GONDI LETTER A;Lo;0;L;;;;;N;;;;; +11D61;GUNJALA GONDI LETTER AA;Lo;0;L;;;;;N;;;;; +11D62;GUNJALA GONDI LETTER I;Lo;0;L;;;;;N;;;;; +11D63;GUNJALA GONDI LETTER II;Lo;0;L;;;;;N;;;;; +11D64;GUNJALA GONDI LETTER U;Lo;0;L;;;;;N;;;;; +11D65;GUNJALA GONDI LETTER UU;Lo;0;L;;;;;N;;;;; +11D67;GUNJALA GONDI LETTER EE;Lo;0;L;;;;;N;;;;; +11D68;GUNJALA GONDI LETTER AI;Lo;0;L;;;;;N;;;;; +11D6A;GUNJALA GONDI LETTER OO;Lo;0;L;;;;;N;;;;; +11D6B;GUNJALA GONDI LETTER AU;Lo;0;L;;;;;N;;;;; +11D6C;GUNJALA GONDI LETTER YA;Lo;0;L;;;;;N;;;;; +11D6D;GUNJALA GONDI LETTER VA;Lo;0;L;;;;;N;;;;; +11D6E;GUNJALA GONDI LETTER BA;Lo;0;L;;;;;N;;;;; +11D6F;GUNJALA GONDI LETTER BHA;Lo;0;L;;;;;N;;;;; +11D70;GUNJALA GONDI LETTER MA;Lo;0;L;;;;;N;;;;; +11D71;GUNJALA GONDI LETTER KA;Lo;0;L;;;;;N;;;;; +11D72;GUNJALA GONDI LETTER KHA;Lo;0;L;;;;;N;;;;; +11D73;GUNJALA GONDI LETTER TA;Lo;0;L;;;;;N;;;;; +11D74;GUNJALA GONDI LETTER THA;Lo;0;L;;;;;N;;;;; +11D75;GUNJALA GONDI LETTER LA;Lo;0;L;;;;;N;;;;; +11D76;GUNJALA GONDI LETTER GA;Lo;0;L;;;;;N;;;;; +11D77;GUNJALA GONDI LETTER GHA;Lo;0;L;;;;;N;;;;; +11D78;GUNJALA GONDI LETTER DA;Lo;0;L;;;;;N;;;;; +11D79;GUNJALA GONDI LETTER DHA;Lo;0;L;;;;;N;;;;; +11D7A;GUNJALA GONDI LETTER NA;Lo;0;L;;;;;N;;;;; +11D7B;GUNJALA GONDI LETTER CA;Lo;0;L;;;;;N;;;;; +11D7C;GUNJALA GONDI LETTER CHA;Lo;0;L;;;;;N;;;;; +11D7D;GUNJALA GONDI LETTER TTA;Lo;0;L;;;;;N;;;;; +11D7E;GUNJALA GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11D7F;GUNJALA GONDI LETTER LLA;Lo;0;L;;;;;N;;;;; +11D80;GUNJALA GONDI LETTER JA;Lo;0;L;;;;;N;;;;; +11D81;GUNJALA GONDI LETTER JHA;Lo;0;L;;;;;N;;;;; +11D82;GUNJALA GONDI LETTER DDA;Lo;0;L;;;;;N;;;;; +11D83;GUNJALA GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11D84;GUNJALA GONDI LETTER NGA;Lo;0;L;;;;;N;;;;; +11D85;GUNJALA GONDI LETTER PA;Lo;0;L;;;;;N;;;;; +11D86;GUNJALA GONDI LETTER PHA;Lo;0;L;;;;;N;;;;; +11D87;GUNJALA GONDI LETTER HA;Lo;0;L;;;;;N;;;;; +11D88;GUNJALA GONDI LETTER RA;Lo;0;L;;;;;N;;;;; +11D89;GUNJALA GONDI LETTER SA;Lo;0;L;;;;;N;;;;; +11D8A;GUNJALA GONDI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11D8B;GUNJALA GONDI VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +11D8C;GUNJALA GONDI VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +11D8D;GUNJALA GONDI VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +11D8E;GUNJALA GONDI VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +11D90;GUNJALA GONDI VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +11D91;GUNJALA GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11D93;GUNJALA GONDI VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +11D94;GUNJALA GONDI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +11D95;GUNJALA GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11D96;GUNJALA GONDI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11D97;GUNJALA GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11D98;GUNJALA GONDI OM;Lo;0;L;;;;;N;;;;; +11DA0;GUNJALA GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11DA1;GUNJALA GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11DA2;GUNJALA GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11DA3;GUNJALA GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11DA4;GUNJALA GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11DA5;GUNJALA GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11DA6;GUNJALA GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11DA7;GUNJALA GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11DA8;GUNJALA GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11DA9;GUNJALA GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11DB0;TOLONG SIKI LETTER I;Lo;0;L;;;;;N;;;;; +11DB1;TOLONG SIKI LETTER E;Lo;0;L;;;;;N;;;;; +11DB2;TOLONG SIKI LETTER U;Lo;0;L;;;;;N;;;;; +11DB3;TOLONG SIKI LETTER O;Lo;0;L;;;;;N;;;;; +11DB4;TOLONG SIKI LETTER A;Lo;0;L;;;;;N;;;;; +11DB5;TOLONG SIKI LETTER AA;Lo;0;L;;;;;N;;;;; +11DB6;TOLONG SIKI LETTER P;Lo;0;L;;;;;N;;;;; +11DB7;TOLONG SIKI LETTER PH;Lo;0;L;;;;;N;;;;; +11DB8;TOLONG SIKI LETTER B;Lo;0;L;;;;;N;;;;; +11DB9;TOLONG SIKI LETTER BH;Lo;0;L;;;;;N;;;;; +11DBA;TOLONG SIKI LETTER M;Lo;0;L;;;;;N;;;;; +11DBB;TOLONG SIKI LETTER T;Lo;0;L;;;;;N;;;;; +11DBC;TOLONG SIKI LETTER TH;Lo;0;L;;;;;N;;;;; +11DBD;TOLONG SIKI LETTER D;Lo;0;L;;;;;N;;;;; +11DBE;TOLONG SIKI LETTER DH;Lo;0;L;;;;;N;;;;; +11DBF;TOLONG SIKI LETTER N;Lo;0;L;;;;;N;;;;; +11DC0;TOLONG SIKI LETTER TT;Lo;0;L;;;;;N;;;;; +11DC1;TOLONG SIKI LETTER TTH;Lo;0;L;;;;;N;;;;; +11DC2;TOLONG SIKI LETTER DD;Lo;0;L;;;;;N;;;;; +11DC3;TOLONG SIKI LETTER DDH;Lo;0;L;;;;;N;;;;; +11DC4;TOLONG SIKI LETTER NN;Lo;0;L;;;;;N;;;;; +11DC5;TOLONG SIKI LETTER C;Lo;0;L;;;;;N;;;;; +11DC6;TOLONG SIKI LETTER CH;Lo;0;L;;;;;N;;;;; +11DC7;TOLONG SIKI LETTER J;Lo;0;L;;;;;N;;;;; +11DC8;TOLONG SIKI LETTER JH;Lo;0;L;;;;;N;;;;; +11DC9;TOLONG SIKI LETTER NY;Lo;0;L;;;;;N;;;;; +11DCA;TOLONG SIKI LETTER K;Lo;0;L;;;;;N;;;;; +11DCB;TOLONG SIKI LETTER KH;Lo;0;L;;;;;N;;;;; +11DCC;TOLONG SIKI LETTER G;Lo;0;L;;;;;N;;;;; +11DCD;TOLONG SIKI LETTER GH;Lo;0;L;;;;;N;;;;; +11DCE;TOLONG SIKI LETTER NG;Lo;0;L;;;;;N;;;;; +11DCF;TOLONG SIKI LETTER Y;Lo;0;L;;;;;N;;;;; +11DD0;TOLONG SIKI LETTER R;Lo;0;L;;;;;N;;;;; +11DD1;TOLONG SIKI LETTER L;Lo;0;L;;;;;N;;;;; +11DD2;TOLONG SIKI LETTER V;Lo;0;L;;;;;N;;;;; +11DD3;TOLONG SIKI LETTER NNY;Lo;0;L;;;;;N;;;;; +11DD4;TOLONG SIKI LETTER S;Lo;0;L;;;;;N;;;;; +11DD5;TOLONG SIKI LETTER H;Lo;0;L;;;;;N;;;;; +11DD6;TOLONG SIKI LETTER X;Lo;0;L;;;;;N;;;;; +11DD7;TOLONG SIKI LETTER RR;Lo;0;L;;;;;N;;;;; +11DD8;TOLONG SIKI LETTER RRH;Lo;0;L;;;;;N;;;;; +11DD9;TOLONG SIKI SIGN SELA;Lm;0;L;;;;;N;;;;; +11DDA;TOLONG SIKI SIGN HECAKA;Lo;0;L;;;;;N;;;;; +11DDB;TOLONG SIKI UNGGA;Lo;0;L;;;;;N;;;;; +11DE0;TOLONG SIKI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11DE1;TOLONG SIKI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11DE2;TOLONG SIKI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11DE3;TOLONG SIKI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11DE4;TOLONG SIKI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11DE5;TOLONG SIKI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11DE6;TOLONG SIKI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11DE7;TOLONG SIKI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11DE8;TOLONG SIKI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11DE9;TOLONG SIKI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11EE0;MAKASAR LETTER KA;Lo;0;L;;;;;N;;;;; +11EE1;MAKASAR LETTER GA;Lo;0;L;;;;;N;;;;; +11EE2;MAKASAR LETTER NGA;Lo;0;L;;;;;N;;;;; +11EE3;MAKASAR LETTER PA;Lo;0;L;;;;;N;;;;; +11EE4;MAKASAR LETTER BA;Lo;0;L;;;;;N;;;;; +11EE5;MAKASAR LETTER MA;Lo;0;L;;;;;N;;;;; +11EE6;MAKASAR LETTER TA;Lo;0;L;;;;;N;;;;; +11EE7;MAKASAR LETTER DA;Lo;0;L;;;;;N;;;;; +11EE8;MAKASAR LETTER NA;Lo;0;L;;;;;N;;;;; +11EE9;MAKASAR LETTER CA;Lo;0;L;;;;;N;;;;; +11EEA;MAKASAR LETTER JA;Lo;0;L;;;;;N;;;;; +11EEB;MAKASAR LETTER NYA;Lo;0;L;;;;;N;;;;; +11EEC;MAKASAR LETTER YA;Lo;0;L;;;;;N;;;;; +11EED;MAKASAR LETTER RA;Lo;0;L;;;;;N;;;;; +11EEE;MAKASAR LETTER LA;Lo;0;L;;;;;N;;;;; +11EEF;MAKASAR LETTER VA;Lo;0;L;;;;;N;;;;; +11EF0;MAKASAR LETTER SA;Lo;0;L;;;;;N;;;;; +11EF1;MAKASAR LETTER A;Lo;0;L;;;;;N;;;;; +11EF2;MAKASAR ANGKA;Lo;0;L;;;;;N;;;;; +11EF3;MAKASAR VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11EF4;MAKASAR VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11EF5;MAKASAR VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +11EF6;MAKASAR VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +11EF7;MAKASAR PASSIMBANG;Po;0;L;;;;;N;;;;; +11EF8;MAKASAR END OF SECTION;Po;0;L;;;;;N;;;;; +11F00;KAWI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; +11F01;KAWI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11F02;KAWI SIGN REPHA;Lo;0;L;;;;;N;;;;; +11F03;KAWI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11F04;KAWI LETTER A;Lo;0;L;;;;;N;;;;; +11F05;KAWI LETTER AA;Lo;0;L;;;;;N;;;;; +11F06;KAWI LETTER I;Lo;0;L;;;;;N;;;;; +11F07;KAWI LETTER II;Lo;0;L;;;;;N;;;;; +11F08;KAWI LETTER U;Lo;0;L;;;;;N;;;;; +11F09;KAWI LETTER UU;Lo;0;L;;;;;N;;;;; +11F0A;KAWI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +11F0B;KAWI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +11F0C;KAWI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +11F0D;KAWI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +11F0E;KAWI LETTER E;Lo;0;L;;;;;N;;;;; +11F0F;KAWI LETTER AI;Lo;0;L;;;;;N;;;;; +11F10;KAWI LETTER O;Lo;0;L;;;;;N;;;;; +11F12;KAWI LETTER KA;Lo;0;L;;;;;N;;;;; +11F13;KAWI LETTER KHA;Lo;0;L;;;;;N;;;;; +11F14;KAWI LETTER GA;Lo;0;L;;;;;N;;;;; +11F15;KAWI LETTER GHA;Lo;0;L;;;;;N;;;;; +11F16;KAWI LETTER NGA;Lo;0;L;;;;;N;;;;; +11F17;KAWI LETTER CA;Lo;0;L;;;;;N;;;;; +11F18;KAWI LETTER CHA;Lo;0;L;;;;;N;;;;; +11F19;KAWI LETTER JA;Lo;0;L;;;;;N;;;;; +11F1A;KAWI LETTER JHA;Lo;0;L;;;;;N;;;;; +11F1B;KAWI LETTER NYA;Lo;0;L;;;;;N;;;;; +11F1C;KAWI LETTER TTA;Lo;0;L;;;;;N;;;;; +11F1D;KAWI LETTER TTHA;Lo;0;L;;;;;N;;;;; +11F1E;KAWI LETTER DDA;Lo;0;L;;;;;N;;;;; +11F1F;KAWI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11F20;KAWI LETTER NNA;Lo;0;L;;;;;N;;;;; +11F21;KAWI LETTER TA;Lo;0;L;;;;;N;;;;; +11F22;KAWI LETTER THA;Lo;0;L;;;;;N;;;;; +11F23;KAWI LETTER DA;Lo;0;L;;;;;N;;;;; +11F24;KAWI LETTER DHA;Lo;0;L;;;;;N;;;;; +11F25;KAWI LETTER NA;Lo;0;L;;;;;N;;;;; +11F26;KAWI LETTER PA;Lo;0;L;;;;;N;;;;; +11F27;KAWI LETTER PHA;Lo;0;L;;;;;N;;;;; +11F28;KAWI LETTER BA;Lo;0;L;;;;;N;;;;; +11F29;KAWI LETTER BHA;Lo;0;L;;;;;N;;;;; +11F2A;KAWI LETTER MA;Lo;0;L;;;;;N;;;;; +11F2B;KAWI LETTER YA;Lo;0;L;;;;;N;;;;; +11F2C;KAWI LETTER RA;Lo;0;L;;;;;N;;;;; +11F2D;KAWI LETTER LA;Lo;0;L;;;;;N;;;;; +11F2E;KAWI LETTER WA;Lo;0;L;;;;;N;;;;; +11F2F;KAWI LETTER SHA;Lo;0;L;;;;;N;;;;; +11F30;KAWI LETTER SSA;Lo;0;L;;;;;N;;;;; +11F31;KAWI LETTER SA;Lo;0;L;;;;;N;;;;; +11F32;KAWI LETTER HA;Lo;0;L;;;;;N;;;;; +11F33;KAWI LETTER JNYA;Lo;0;L;;;;;N;;;;; +11F34;KAWI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +11F35;KAWI VOWEL SIGN ALTERNATE AA;Mc;0;L;;;;;N;;;;; +11F36;KAWI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +11F37;KAWI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +11F38;KAWI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +11F39;KAWI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +11F3A;KAWI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +11F3E;KAWI VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +11F3F;KAWI VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +11F40;KAWI VOWEL SIGN EU;Mn;0;NSM;;;;;N;;;;; +11F41;KAWI SIGN KILLER;Mc;9;L;;;;;N;;;;; +11F42;KAWI CONJOINER;Mn;9;NSM;;;;;N;;;;; +11F43;KAWI DANDA;Po;0;L;;;;;N;;;;; +11F44;KAWI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11F45;KAWI PUNCTUATION SECTION MARKER;Po;0;L;;;;;N;;;;; +11F46;KAWI PUNCTUATION ALTERNATE SECTION MARKER;Po;0;L;;;;;N;;;;; +11F47;KAWI PUNCTUATION FLOWER;Po;0;L;;;;;N;;;;; +11F48;KAWI PUNCTUATION SPACE FILLER;Po;0;L;;;;;N;;;;; +11F49;KAWI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; +11F4A;KAWI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; +11F4B;KAWI PUNCTUATION TRIPLE DOT;Po;0;L;;;;;N;;;;; +11F4C;KAWI PUNCTUATION CIRCLE;Po;0;L;;;;;N;;;;; +11F4D;KAWI PUNCTUATION FILLED CIRCLE;Po;0;L;;;;;N;;;;; +11F4E;KAWI PUNCTUATION SPIRAL;Po;0;L;;;;;N;;;;; +11F4F;KAWI PUNCTUATION CLOSING SPIRAL;Po;0;L;;;;;N;;;;; +11F50;KAWI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11F51;KAWI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11F52;KAWI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11F53;KAWI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +11F54;KAWI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +11F55;KAWI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +11F56;KAWI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +11F57;KAWI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +11F58;KAWI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +11F59;KAWI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +11F5A;KAWI SIGN NUKTA;Mn;0;NSM;;;;;N;;;;; +11FB0;LISU LETTER YHA;Lo;0;L;;;;;N;;;;; +11FC0;TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH;No;0;L;;;;1/320;N;;;;; +11FC1;TAMIL FRACTION ONE ONE-HUNDRED-AND-SIXTIETH;No;0;L;;;;1/160;N;;;;; +11FC2;TAMIL FRACTION ONE EIGHTIETH;No;0;L;;;;1/80;N;;;;; +11FC3;TAMIL FRACTION ONE SIXTY-FOURTH;No;0;L;;;;1/64;N;;;;; +11FC4;TAMIL FRACTION ONE FORTIETH;No;0;L;;;;1/40;N;;;;; +11FC5;TAMIL FRACTION ONE THIRTY-SECOND;No;0;L;;;;1/32;N;;;;; +11FC6;TAMIL FRACTION THREE EIGHTIETHS;No;0;L;;;;3/80;N;;;;; +11FC7;TAMIL FRACTION THREE SIXTY-FOURTHS;No;0;L;;;;3/64;N;;;;; +11FC8;TAMIL FRACTION ONE TWENTIETH;No;0;L;;;;1/20;N;;;;; +11FC9;TAMIL FRACTION ONE SIXTEENTH-1;No;0;L;;;;1/16;N;;;;; +11FCA;TAMIL FRACTION ONE SIXTEENTH-2;No;0;L;;;;1/16;N;;;;; +11FCB;TAMIL FRACTION ONE TENTH;No;0;L;;;;1/10;N;;;;; +11FCC;TAMIL FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +11FCD;TAMIL FRACTION THREE TWENTIETHS;No;0;L;;;;3/20;N;;;;; +11FCE;TAMIL FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; +11FCF;TAMIL FRACTION ONE FIFTH;No;0;L;;;;1/5;N;;;;; +11FD0;TAMIL FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +11FD1;TAMIL FRACTION ONE HALF-1;No;0;L;;;;1/2;N;;;;; +11FD2;TAMIL FRACTION ONE HALF-2;No;0;L;;;;1/2;N;;;;; +11FD3;TAMIL FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +11FD4;TAMIL FRACTION DOWNSCALING FACTOR KIIZH;No;0;L;;;;1/320;N;;;;; +11FD5;TAMIL SIGN NEL;So;0;ON;;;;;N;;;;; +11FD6;TAMIL SIGN CEVITU;So;0;ON;;;;;N;;;;; +11FD7;TAMIL SIGN AAZHAAKKU;So;0;ON;;;;;N;;;;; +11FD8;TAMIL SIGN UZHAKKU;So;0;ON;;;;;N;;;;; +11FD9;TAMIL SIGN MUUVUZHAKKU;So;0;ON;;;;;N;;;;; +11FDA;TAMIL SIGN KURUNI;So;0;ON;;;;;N;;;;; +11FDB;TAMIL SIGN PATHAKKU;So;0;ON;;;;;N;;;;; +11FDC;TAMIL SIGN MUKKURUNI;So;0;ON;;;;;N;;;;; +11FDD;TAMIL SIGN KAACU;Sc;0;ET;;;;;N;;;;; +11FDE;TAMIL SIGN PANAM;Sc;0;ET;;;;;N;;;;; +11FDF;TAMIL SIGN PON;Sc;0;ET;;;;;N;;;;; +11FE0;TAMIL SIGN VARAAKAN;Sc;0;ET;;;;;N;;;;; +11FE1;TAMIL SIGN PAARAM;So;0;ON;;;;;N;;;;; +11FE2;TAMIL SIGN KUZHI;So;0;ON;;;;;N;;;;; +11FE3;TAMIL SIGN VELI;So;0;ON;;;;;N;;;;; +11FE4;TAMIL WET CULTIVATION SIGN;So;0;ON;;;;;N;;;;; +11FE5;TAMIL DRY CULTIVATION SIGN;So;0;ON;;;;;N;;;;; +11FE6;TAMIL LAND SIGN;So;0;ON;;;;;N;;;;; +11FE7;TAMIL SALT PAN SIGN;So;0;ON;;;;;N;;;;; +11FE8;TAMIL TRADITIONAL CREDIT SIGN;So;0;ON;;;;;N;;;;; +11FE9;TAMIL TRADITIONAL NUMBER SIGN;So;0;ON;;;;;N;;;;; +11FEA;TAMIL CURRENT SIGN;So;0;ON;;;;;N;;;;; +11FEB;TAMIL AND ODD SIGN;So;0;ON;;;;;N;;;;; +11FEC;TAMIL SPENT SIGN;So;0;ON;;;;;N;;;;; +11FED;TAMIL TOTAL SIGN;So;0;ON;;;;;N;;;;; +11FEE;TAMIL IN POSSESSION SIGN;So;0;ON;;;;;N;;;;; +11FEF;TAMIL STARTING FROM SIGN;So;0;ON;;;;;N;;;;; +11FF0;TAMIL SIGN MUTHALIYA;So;0;ON;;;;;N;;;;; +11FF1;TAMIL SIGN VAKAIYARAA;So;0;ON;;;;;N;;;;; +11FFF;TAMIL PUNCTUATION END OF TEXT;Po;0;L;;;;;N;;;;; +12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;; +12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;; +12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;; +12003;CUNEIFORM SIGN A TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12004;CUNEIFORM SIGN A TIMES HA;Lo;0;L;;;;;N;;;;; +12005;CUNEIFORM SIGN A TIMES IGI;Lo;0;L;;;;;N;;;;; +12006;CUNEIFORM SIGN A TIMES LAGAR GUNU;Lo;0;L;;;;;N;;;;; +12007;CUNEIFORM SIGN A TIMES MUSH;Lo;0;L;;;;;N;;;;; +12008;CUNEIFORM SIGN A TIMES SAG;Lo;0;L;;;;;N;;;;; +12009;CUNEIFORM SIGN A2;Lo;0;L;;;;;N;;;;; +1200A;CUNEIFORM SIGN AB;Lo;0;L;;;;;N;;;;; +1200B;CUNEIFORM SIGN AB TIMES ASH2;Lo;0;L;;;;;N;;;;; +1200C;CUNEIFORM SIGN AB TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; +1200D;CUNEIFORM SIGN AB TIMES GAL;Lo;0;L;;;;;N;;;;; +1200E;CUNEIFORM SIGN AB TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1200F;CUNEIFORM SIGN AB TIMES HA;Lo;0;L;;;;;N;;;;; +12010;CUNEIFORM SIGN AB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12011;CUNEIFORM SIGN AB TIMES IMIN;Lo;0;L;;;;;N;;;;; +12012;CUNEIFORM SIGN AB TIMES LAGAB;Lo;0;L;;;;;N;;;;; +12013;CUNEIFORM SIGN AB TIMES SHESH;Lo;0;L;;;;;N;;;;; +12014;CUNEIFORM SIGN AB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +12015;CUNEIFORM SIGN AB GUNU;Lo;0;L;;;;;N;;;;; +12016;CUNEIFORM SIGN AB2;Lo;0;L;;;;;N;;;;; +12017;CUNEIFORM SIGN AB2 TIMES BALAG;Lo;0;L;;;;;N;;;;; +12018;CUNEIFORM SIGN AB2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12019;CUNEIFORM SIGN AB2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +1201A;CUNEIFORM SIGN AB2 TIMES SHA3;Lo;0;L;;;;;N;;;;; +1201B;CUNEIFORM SIGN AB2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1201C;CUNEIFORM SIGN AD;Lo;0;L;;;;;N;;;;; +1201D;CUNEIFORM SIGN AK;Lo;0;L;;;;;N;;;;; +1201E;CUNEIFORM SIGN AK TIMES ERIN2;Lo;0;L;;;;;N;;;;; +1201F;CUNEIFORM SIGN AK TIMES SHITA PLUS GISH;Lo;0;L;;;;;N;;;;; +12020;CUNEIFORM SIGN AL;Lo;0;L;;;;;N;;;;; +12021;CUNEIFORM SIGN AL TIMES AL;Lo;0;L;;;;;N;;;;; +12022;CUNEIFORM SIGN AL TIMES DIM2;Lo;0;L;;;;;N;;;;; +12023;CUNEIFORM SIGN AL TIMES GISH;Lo;0;L;;;;;N;;;;; +12024;CUNEIFORM SIGN AL TIMES HA;Lo;0;L;;;;;N;;;;; +12025;CUNEIFORM SIGN AL TIMES KAD3;Lo;0;L;;;;;N;;;;; +12026;CUNEIFORM SIGN AL TIMES KI;Lo;0;L;;;;;N;;;;; +12027;CUNEIFORM SIGN AL TIMES SHE;Lo;0;L;;;;;N;;;;; +12028;CUNEIFORM SIGN AL TIMES USH;Lo;0;L;;;;;N;;;;; +12029;CUNEIFORM SIGN ALAN;Lo;0;L;;;;;N;;;;; +1202A;CUNEIFORM SIGN ALEPH;Lo;0;L;;;;;N;;;;; +1202B;CUNEIFORM SIGN AMAR;Lo;0;L;;;;;N;;;;; +1202C;CUNEIFORM SIGN AMAR TIMES SHE;Lo;0;L;;;;;N;;;;; +1202D;CUNEIFORM SIGN AN;Lo;0;L;;;;;N;;;;; +1202E;CUNEIFORM SIGN AN OVER AN;Lo;0;L;;;;;N;;;;; +1202F;CUNEIFORM SIGN AN THREE TIMES;Lo;0;L;;;;;N;;;;; +12030;CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA;Lo;0;L;;;;;N;;;;; +12031;CUNEIFORM SIGN AN PLUS NAGA SQUARED;Lo;0;L;;;;;N;;;;; +12032;CUNEIFORM SIGN ANSHE;Lo;0;L;;;;;N;;;;; +12033;CUNEIFORM SIGN APIN;Lo;0;L;;;;;N;;;;; +12034;CUNEIFORM SIGN ARAD;Lo;0;L;;;;;N;;;;; +12035;CUNEIFORM SIGN ARAD TIMES KUR;Lo;0;L;;;;;N;;;;; +12036;CUNEIFORM SIGN ARKAB;Lo;0;L;;;;;N;;;;; +12037;CUNEIFORM SIGN ASAL2;Lo;0;L;;;;;N;;;;; +12038;CUNEIFORM SIGN ASH;Lo;0;L;;;;1;N;;;;; +12039;CUNEIFORM SIGN ASH ZIDA TENU;Lo;0;L;;;;1;N;;;;; +1203A;CUNEIFORM SIGN ASH KABA TENU;Lo;0;L;;;;;N;;;;; +1203B;CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP;Lo;0;L;;;;;N;;;;; +1203C;CUNEIFORM SIGN ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; +1203D;CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH;Lo;0;L;;;;;N;;;;; +1203E;CUNEIFORM SIGN ASH2;Lo;0;L;;;;;N;;;;; +1203F;CUNEIFORM SIGN ASHGAB;Lo;0;L;;;;;N;;;;; +12040;CUNEIFORM SIGN BA;Lo;0;L;;;;;N;;;;; +12041;CUNEIFORM SIGN BAD;Lo;0;L;;;;;N;;;;; +12042;CUNEIFORM SIGN BAG3;Lo;0;L;;;;;N;;;;; +12043;CUNEIFORM SIGN BAHAR2;Lo;0;L;;;;;N;;;;; +12044;CUNEIFORM SIGN BAL;Lo;0;L;;;;;N;;;;; +12045;CUNEIFORM SIGN BAL OVER BAL;Lo;0;L;;;;;N;;;;; +12046;CUNEIFORM SIGN BALAG;Lo;0;L;;;;;N;;;;; +12047;CUNEIFORM SIGN BAR;Lo;0;L;;;;;N;;;;; +12048;CUNEIFORM SIGN BARA2;Lo;0;L;;;;;N;;;;; +12049;CUNEIFORM SIGN BI;Lo;0;L;;;;;N;;;;; +1204A;CUNEIFORM SIGN BI TIMES A;Lo;0;L;;;;;N;;;;; +1204B;CUNEIFORM SIGN BI TIMES GAR;Lo;0;L;;;;;N;;;;; +1204C;CUNEIFORM SIGN BI TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1204D;CUNEIFORM SIGN BU;Lo;0;L;;;;;N;;;;; +1204E;CUNEIFORM SIGN BU OVER BU AB;Lo;0;L;;;;;N;;;;; +1204F;CUNEIFORM SIGN BU OVER BU UN;Lo;0;L;;;;;N;;;;; +12050;CUNEIFORM SIGN BU CROSSING BU;Lo;0;L;;;;;N;;;;; +12051;CUNEIFORM SIGN BULUG;Lo;0;L;;;;;N;;;;; +12052;CUNEIFORM SIGN BULUG OVER BULUG;Lo;0;L;;;;;N;;;;; +12053;CUNEIFORM SIGN BUR;Lo;0;L;;;;;N;;;;; +12054;CUNEIFORM SIGN BUR2;Lo;0;L;;;;;N;;;;; +12055;CUNEIFORM SIGN DA;Lo;0;L;;;;;N;;;;; +12056;CUNEIFORM SIGN DAG;Lo;0;L;;;;;N;;;;; +12057;CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH;Lo;0;L;;;;;N;;;;; +12058;CUNEIFORM SIGN DAG KISIM5 TIMES AMAR;Lo;0;L;;;;;N;;;;; +12059;CUNEIFORM SIGN DAG KISIM5 TIMES BALAG;Lo;0;L;;;;;N;;;;; +1205A;CUNEIFORM SIGN DAG KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; +1205B;CUNEIFORM SIGN DAG KISIM5 TIMES GA;Lo;0;L;;;;;N;;;;; +1205C;CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH;Lo;0;L;;;;;N;;;;; +1205D;CUNEIFORM SIGN DAG KISIM5 TIMES GI;Lo;0;L;;;;;N;;;;; +1205E;CUNEIFORM SIGN DAG KISIM5 TIMES GIR2;Lo;0;L;;;;;N;;;;; +1205F;CUNEIFORM SIGN DAG KISIM5 TIMES GUD;Lo;0;L;;;;;N;;;;; +12060;CUNEIFORM SIGN DAG KISIM5 TIMES HA;Lo;0;L;;;;;N;;;;; +12061;CUNEIFORM SIGN DAG KISIM5 TIMES IR;Lo;0;L;;;;;N;;;;; +12062;CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU;Lo;0;L;;;;;N;;;;; +12063;CUNEIFORM SIGN DAG KISIM5 TIMES KAK;Lo;0;L;;;;;N;;;;; +12064;CUNEIFORM SIGN DAG KISIM5 TIMES LA;Lo;0;L;;;;;N;;;;; +12065;CUNEIFORM SIGN DAG KISIM5 TIMES LU;Lo;0;L;;;;;N;;;;; +12066;CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2;Lo;0;L;;;;;N;;;;; +12067;CUNEIFORM SIGN DAG KISIM5 TIMES LUM;Lo;0;L;;;;;N;;;;; +12068;CUNEIFORM SIGN DAG KISIM5 TIMES NE;Lo;0;L;;;;;N;;;;; +12069;CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; +1206A;CUNEIFORM SIGN DAG KISIM5 TIMES SI;Lo;0;L;;;;;N;;;;; +1206B;CUNEIFORM SIGN DAG KISIM5 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1206C;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2;Lo;0;L;;;;;N;;;;; +1206D;CUNEIFORM SIGN DAG KISIM5 TIMES USH;Lo;0;L;;;;;N;;;;; +1206E;CUNEIFORM SIGN DAM;Lo;0;L;;;;;N;;;;; +1206F;CUNEIFORM SIGN DAR;Lo;0;L;;;;;N;;;;; +12070;CUNEIFORM SIGN DARA3;Lo;0;L;;;;;N;;;;; +12071;CUNEIFORM SIGN DARA4;Lo;0;L;;;;;N;;;;; +12072;CUNEIFORM SIGN DI;Lo;0;L;;;;;N;;;;; +12073;CUNEIFORM SIGN DIB;Lo;0;L;;;;;N;;;;; +12074;CUNEIFORM SIGN DIM;Lo;0;L;;;;;N;;;;; +12075;CUNEIFORM SIGN DIM TIMES SHE;Lo;0;L;;;;;N;;;;; +12076;CUNEIFORM SIGN DIM2;Lo;0;L;;;;;N;;;;; +12077;CUNEIFORM SIGN DIN;Lo;0;L;;;;;N;;;;; +12078;CUNEIFORM SIGN DIN KASKAL U GUNU DISH;Lo;0;L;;;;;N;;;;; +12079;CUNEIFORM SIGN DISH;Lo;0;L;;;;1;N;;;;; +1207A;CUNEIFORM SIGN DU;Lo;0;L;;;;;N;;;;; +1207B;CUNEIFORM SIGN DU OVER DU;Lo;0;L;;;;;N;;;;; +1207C;CUNEIFORM SIGN DU GUNU;Lo;0;L;;;;;N;;;;; +1207D;CUNEIFORM SIGN DU SHESHIG;Lo;0;L;;;;;N;;;;; +1207E;CUNEIFORM SIGN DUB;Lo;0;L;;;;;N;;;;; +1207F;CUNEIFORM SIGN DUB TIMES ESH2;Lo;0;L;;;;;N;;;;; +12080;CUNEIFORM SIGN DUB2;Lo;0;L;;;;;N;;;;; +12081;CUNEIFORM SIGN DUG;Lo;0;L;;;;;N;;;;; +12082;CUNEIFORM SIGN DUGUD;Lo;0;L;;;;;N;;;;; +12083;CUNEIFORM SIGN DUH;Lo;0;L;;;;;N;;;;; +12084;CUNEIFORM SIGN DUN;Lo;0;L;;;;;N;;;;; +12085;CUNEIFORM SIGN DUN3;Lo;0;L;;;;;N;;;;; +12086;CUNEIFORM SIGN DUN3 GUNU;Lo;0;L;;;;;N;;;;; +12087;CUNEIFORM SIGN DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +12088;CUNEIFORM SIGN DUN4;Lo;0;L;;;;;N;;;;; +12089;CUNEIFORM SIGN DUR2;Lo;0;L;;;;;N;;;;; +1208A;CUNEIFORM SIGN E;Lo;0;L;;;;;N;;;;; +1208B;CUNEIFORM SIGN E TIMES PAP;Lo;0;L;;;;;N;;;;; +1208C;CUNEIFORM SIGN E OVER E NUN OVER NUN;Lo;0;L;;;;;N;;;;; +1208D;CUNEIFORM SIGN E2;Lo;0;L;;;;;N;;;;; +1208E;CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA;Lo;0;L;;;;;N;;;;; +1208F;CUNEIFORM SIGN E2 TIMES GAR;Lo;0;L;;;;;N;;;;; +12090;CUNEIFORM SIGN E2 TIMES MI;Lo;0;L;;;;;N;;;;; +12091;CUNEIFORM SIGN E2 TIMES SAL;Lo;0;L;;;;;N;;;;; +12092;CUNEIFORM SIGN E2 TIMES SHE;Lo;0;L;;;;;N;;;;; +12093;CUNEIFORM SIGN E2 TIMES U;Lo;0;L;;;;;N;;;;; +12094;CUNEIFORM SIGN EDIN;Lo;0;L;;;;;N;;;;; +12095;CUNEIFORM SIGN EGIR;Lo;0;L;;;;;N;;;;; +12096;CUNEIFORM SIGN EL;Lo;0;L;;;;;N;;;;; +12097;CUNEIFORM SIGN EN;Lo;0;L;;;;;N;;;;; +12098;CUNEIFORM SIGN EN TIMES GAN2;Lo;0;L;;;;;N;;;;; +12099;CUNEIFORM SIGN EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1209A;CUNEIFORM SIGN EN TIMES ME;Lo;0;L;;;;;N;;;;; +1209B;CUNEIFORM SIGN EN CROSSING EN;Lo;0;L;;;;;N;;;;; +1209C;CUNEIFORM SIGN EN OPPOSING EN;Lo;0;L;;;;;N;;;;; +1209D;CUNEIFORM SIGN EN SQUARED;Lo;0;L;;;;;N;;;;; +1209E;CUNEIFORM SIGN EREN;Lo;0;L;;;;;N;;;;; +1209F;CUNEIFORM SIGN ERIN2;Lo;0;L;;;;;N;;;;; +120A0;CUNEIFORM SIGN ESH2;Lo;0;L;;;;;N;;;;; +120A1;CUNEIFORM SIGN EZEN;Lo;0;L;;;;;N;;;;; +120A2;CUNEIFORM SIGN EZEN TIMES A;Lo;0;L;;;;;N;;;;; +120A3;CUNEIFORM SIGN EZEN TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; +120A4;CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +120A5;CUNEIFORM SIGN EZEN TIMES AN;Lo;0;L;;;;;N;;;;; +120A6;CUNEIFORM SIGN EZEN TIMES BAD;Lo;0;L;;;;;N;;;;; +120A7;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU;Lo;0;L;;;;;N;;;;; +120A8;CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +120A9;CUNEIFORM SIGN EZEN TIMES HA;Lo;0;L;;;;;N;;;;; +120AA;CUNEIFORM SIGN EZEN TIMES HA GUNU;Lo;0;L;;;;;N;;;;; +120AB;CUNEIFORM SIGN EZEN TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +120AC;CUNEIFORM SIGN EZEN TIMES KASKAL;Lo;0;L;;;;;N;;;;; +120AD;CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED;Lo;0;L;;;;;N;;;;; +120AE;CUNEIFORM SIGN EZEN TIMES KU3;Lo;0;L;;;;;N;;;;; +120AF;CUNEIFORM SIGN EZEN TIMES LA;Lo;0;L;;;;;N;;;;; +120B0;CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +120B1;CUNEIFORM SIGN EZEN TIMES LI;Lo;0;L;;;;;N;;;;; +120B2;CUNEIFORM SIGN EZEN TIMES LU;Lo;0;L;;;;;N;;;;; +120B3;CUNEIFORM SIGN EZEN TIMES U2;Lo;0;L;;;;;N;;;;; +120B4;CUNEIFORM SIGN EZEN TIMES UD;Lo;0;L;;;;;N;;;;; +120B5;CUNEIFORM SIGN GA;Lo;0;L;;;;;N;;;;; +120B6;CUNEIFORM SIGN GA GUNU;Lo;0;L;;;;;N;;;;; +120B7;CUNEIFORM SIGN GA2;Lo;0;L;;;;;N;;;;; +120B8;CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; +120B9;CUNEIFORM SIGN GA2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; +120BA;CUNEIFORM SIGN GA2 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; +120BB;CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB;Lo;0;L;;;;;N;;;;; +120BC;CUNEIFORM SIGN GA2 TIMES AN;Lo;0;L;;;;;N;;;;; +120BD;CUNEIFORM SIGN GA2 TIMES ASH;Lo;0;L;;;;;N;;;;; +120BE;CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL;Lo;0;L;;;;;N;;;;; +120BF;CUNEIFORM SIGN GA2 TIMES BAD;Lo;0;L;;;;;N;;;;; +120C0;CUNEIFORM SIGN GA2 TIMES BAR PLUS RA;Lo;0;L;;;;;N;;;;; +120C1;CUNEIFORM SIGN GA2 TIMES BUR;Lo;0;L;;;;;N;;;;; +120C2;CUNEIFORM SIGN GA2 TIMES BUR PLUS RA;Lo;0;L;;;;;N;;;;; +120C3;CUNEIFORM SIGN GA2 TIMES DA;Lo;0;L;;;;;N;;;;; +120C4;CUNEIFORM SIGN GA2 TIMES DI;Lo;0;L;;;;;N;;;;; +120C5;CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE;Lo;0;L;;;;;N;;;;; +120C6;CUNEIFORM SIGN GA2 TIMES DUB;Lo;0;L;;;;;N;;;;; +120C7;CUNEIFORM SIGN GA2 TIMES EL;Lo;0;L;;;;;N;;;;; +120C8;CUNEIFORM SIGN GA2 TIMES EL PLUS LA;Lo;0;L;;;;;N;;;;; +120C9;CUNEIFORM SIGN GA2 TIMES EN;Lo;0;L;;;;;N;;;;; +120CA;CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +120CB;CUNEIFORM SIGN GA2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +120CC;CUNEIFORM SIGN GA2 TIMES GAR;Lo;0;L;;;;;N;;;;; +120CD;CUNEIFORM SIGN GA2 TIMES GI;Lo;0;L;;;;;N;;;;; +120CE;CUNEIFORM SIGN GA2 TIMES GI4;Lo;0;L;;;;;N;;;;; +120CF;CUNEIFORM SIGN GA2 TIMES GI4 PLUS A;Lo;0;L;;;;;N;;;;; +120D0;CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU;Lo;0;L;;;;;N;;;;; +120D1;CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2;Lo;0;L;;;;;N;;;;; +120D2;CUNEIFORM SIGN GA2 TIMES HAL;Lo;0;L;;;;;N;;;;; +120D3;CUNEIFORM SIGN GA2 TIMES HAL PLUS LA;Lo;0;L;;;;;N;;;;; +120D4;CUNEIFORM SIGN GA2 TIMES HI PLUS LI;Lo;0;L;;;;;N;;;;; +120D5;CUNEIFORM SIGN GA2 TIMES HUB2;Lo;0;L;;;;;N;;;;; +120D6;CUNEIFORM SIGN GA2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +120D7;CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH;Lo;0;L;;;;;N;;;;; +120D8;CUNEIFORM SIGN GA2 TIMES KAK;Lo;0;L;;;;;N;;;;; +120D9;CUNEIFORM SIGN GA2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +120DA;CUNEIFORM SIGN GA2 TIMES KID;Lo;0;L;;;;;N;;;;; +120DB;CUNEIFORM SIGN GA2 TIMES KID PLUS LAL;Lo;0;L;;;;;N;;;;; +120DC;CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN;Lo;0;L;;;;;N;;;;; +120DD;CUNEIFORM SIGN GA2 TIMES LA;Lo;0;L;;;;;N;;;;; +120DE;CUNEIFORM SIGN GA2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +120DF;CUNEIFORM SIGN GA2 TIMES MI;Lo;0;L;;;;;N;;;;; +120E0;CUNEIFORM SIGN GA2 TIMES NUN;Lo;0;L;;;;;N;;;;; +120E1;CUNEIFORM SIGN GA2 TIMES NUN OVER NUN;Lo;0;L;;;;;N;;;;; +120E2;CUNEIFORM SIGN GA2 TIMES PA;Lo;0;L;;;;;N;;;;; +120E3;CUNEIFORM SIGN GA2 TIMES SAL;Lo;0;L;;;;;N;;;;; +120E4;CUNEIFORM SIGN GA2 TIMES SAR;Lo;0;L;;;;;N;;;;; +120E5;CUNEIFORM SIGN GA2 TIMES SHE;Lo;0;L;;;;;N;;;;; +120E6;CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR;Lo;0;L;;;;;N;;;;; +120E7;CUNEIFORM SIGN GA2 TIMES SHID;Lo;0;L;;;;;N;;;;; +120E8;CUNEIFORM SIGN GA2 TIMES SUM;Lo;0;L;;;;;N;;;;; +120E9;CUNEIFORM SIGN GA2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +120EA;CUNEIFORM SIGN GA2 TIMES U;Lo;0;L;;;;;N;;;;; +120EB;CUNEIFORM SIGN GA2 TIMES UD;Lo;0;L;;;;;N;;;;; +120EC;CUNEIFORM SIGN GA2 TIMES UD PLUS DU;Lo;0;L;;;;;N;;;;; +120ED;CUNEIFORM SIGN GA2 OVER GA2;Lo;0;L;;;;;N;;;;; +120EE;CUNEIFORM SIGN GABA;Lo;0;L;;;;;N;;;;; +120EF;CUNEIFORM SIGN GABA CROSSING GABA;Lo;0;L;;;;;N;;;;; +120F0;CUNEIFORM SIGN GAD;Lo;0;L;;;;;N;;;;; +120F1;CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +120F2;CUNEIFORM SIGN GAL;Lo;0;L;;;;;N;;;;; +120F3;CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +120F4;CUNEIFORM SIGN GALAM;Lo;0;L;;;;;N;;;;; +120F5;CUNEIFORM SIGN GAM;Lo;0;L;;;;;N;;;;; +120F6;CUNEIFORM SIGN GAN;Lo;0;L;;;;;N;;;;; +120F7;CUNEIFORM SIGN GAN2;Lo;0;L;;;;;N;;;;; +120F8;CUNEIFORM SIGN GAN2 TENU;Lo;0;L;;;;;N;;;;; +120F9;CUNEIFORM SIGN GAN2 OVER GAN2;Lo;0;L;;;;;N;;;;; +120FA;CUNEIFORM SIGN GAN2 CROSSING GAN2;Lo;0;L;;;;;N;;;;; +120FB;CUNEIFORM SIGN GAR;Lo;0;L;;;;;N;;;;; +120FC;CUNEIFORM SIGN GAR3;Lo;0;L;;;;;N;;;;; +120FD;CUNEIFORM SIGN GASHAN;Lo;0;L;;;;;N;;;;; +120FE;CUNEIFORM SIGN GESHTIN;Lo;0;L;;;;;N;;;;; +120FF;CUNEIFORM SIGN GESHTIN TIMES KUR;Lo;0;L;;;;;N;;;;; +12100;CUNEIFORM SIGN GI;Lo;0;L;;;;;N;;;;; +12101;CUNEIFORM SIGN GI TIMES E;Lo;0;L;;;;;N;;;;; +12102;CUNEIFORM SIGN GI TIMES U;Lo;0;L;;;;;N;;;;; +12103;CUNEIFORM SIGN GI CROSSING GI;Lo;0;L;;;;;N;;;;; +12104;CUNEIFORM SIGN GI4;Lo;0;L;;;;;N;;;;; +12105;CUNEIFORM SIGN GI4 OVER GI4;Lo;0;L;;;;;N;;;;; +12106;CUNEIFORM SIGN GI4 CROSSING GI4;Lo;0;L;;;;;N;;;;; +12107;CUNEIFORM SIGN GIDIM;Lo;0;L;;;;;N;;;;; +12108;CUNEIFORM SIGN GIR2;Lo;0;L;;;;;N;;;;; +12109;CUNEIFORM SIGN GIR2 GUNU;Lo;0;L;;;;;N;;;;; +1210A;CUNEIFORM SIGN GIR3;Lo;0;L;;;;;N;;;;; +1210B;CUNEIFORM SIGN GIR3 TIMES A PLUS IGI;Lo;0;L;;;;;N;;;;; +1210C;CUNEIFORM SIGN GIR3 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1210D;CUNEIFORM SIGN GIR3 TIMES IGI;Lo;0;L;;;;;N;;;;; +1210E;CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI;Lo;0;L;;;;;N;;;;; +1210F;CUNEIFORM SIGN GIR3 TIMES PA;Lo;0;L;;;;;N;;;;; +12110;CUNEIFORM SIGN GISAL;Lo;0;L;;;;;N;;;;; +12111;CUNEIFORM SIGN GISH;Lo;0;L;;;;;N;;;;; +12112;CUNEIFORM SIGN GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +12113;CUNEIFORM SIGN GISH TIMES BAD;Lo;0;L;;;;;N;;;;; +12114;CUNEIFORM SIGN GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; +12115;CUNEIFORM SIGN GISH TENU;Lo;0;L;;;;;N;;;;; +12116;CUNEIFORM SIGN GU;Lo;0;L;;;;;N;;;;; +12117;CUNEIFORM SIGN GU CROSSING GU;Lo;0;L;;;;;N;;;;; +12118;CUNEIFORM SIGN GU2;Lo;0;L;;;;;N;;;;; +12119;CUNEIFORM SIGN GU2 TIMES KAK;Lo;0;L;;;;;N;;;;; +1211A;CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1211B;CUNEIFORM SIGN GU2 TIMES NUN;Lo;0;L;;;;;N;;;;; +1211C;CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2;Lo;0;L;;;;;N;;;;; +1211D;CUNEIFORM SIGN GU2 GUNU;Lo;0;L;;;;;N;;;;; +1211E;CUNEIFORM SIGN GUD;Lo;0;L;;;;;N;;;;; +1211F;CUNEIFORM SIGN GUD TIMES A PLUS KUR;Lo;0;L;;;;;N;;;;; +12120;CUNEIFORM SIGN GUD TIMES KUR;Lo;0;L;;;;;N;;;;; +12121;CUNEIFORM SIGN GUD OVER GUD LUGAL;Lo;0;L;;;;;N;;;;; +12122;CUNEIFORM SIGN GUL;Lo;0;L;;;;;N;;;;; +12123;CUNEIFORM SIGN GUM;Lo;0;L;;;;;N;;;;; +12124;CUNEIFORM SIGN GUM TIMES SHE;Lo;0;L;;;;;N;;;;; +12125;CUNEIFORM SIGN GUR;Lo;0;L;;;;;N;;;;; +12126;CUNEIFORM SIGN GUR7;Lo;0;L;;;;;N;;;;; +12127;CUNEIFORM SIGN GURUN;Lo;0;L;;;;;N;;;;; +12128;CUNEIFORM SIGN GURUSH;Lo;0;L;;;;;N;;;;; +12129;CUNEIFORM SIGN HA;Lo;0;L;;;;;N;;;;; +1212A;CUNEIFORM SIGN HA TENU;Lo;0;L;;;;;N;;;;; +1212B;CUNEIFORM SIGN HA GUNU;Lo;0;L;;;;;N;;;;; +1212C;CUNEIFORM SIGN HAL;Lo;0;L;;;;;N;;;;; +1212D;CUNEIFORM SIGN HI;Lo;0;L;;;;;N;;;;; +1212E;CUNEIFORM SIGN HI TIMES ASH;Lo;0;L;;;;;N;;;;; +1212F;CUNEIFORM SIGN HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +12130;CUNEIFORM SIGN HI TIMES BAD;Lo;0;L;;;;;N;;;;; +12131;CUNEIFORM SIGN HI TIMES DISH;Lo;0;L;;;;;N;;;;; +12132;CUNEIFORM SIGN HI TIMES GAD;Lo;0;L;;;;;N;;;;; +12133;CUNEIFORM SIGN HI TIMES KIN;Lo;0;L;;;;;N;;;;; +12134;CUNEIFORM SIGN HI TIMES NUN;Lo;0;L;;;;;N;;;;; +12135;CUNEIFORM SIGN HI TIMES SHE;Lo;0;L;;;;;N;;;;; +12136;CUNEIFORM SIGN HI TIMES U;Lo;0;L;;;;;N;;;;; +12137;CUNEIFORM SIGN HU;Lo;0;L;;;;;N;;;;; +12138;CUNEIFORM SIGN HUB2;Lo;0;L;;;;;N;;;;; +12139;CUNEIFORM SIGN HUB2 TIMES AN;Lo;0;L;;;;;N;;;;; +1213A;CUNEIFORM SIGN HUB2 TIMES HAL;Lo;0;L;;;;;N;;;;; +1213B;CUNEIFORM SIGN HUB2 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1213C;CUNEIFORM SIGN HUB2 TIMES LISH;Lo;0;L;;;;;N;;;;; +1213D;CUNEIFORM SIGN HUB2 TIMES UD;Lo;0;L;;;;;N;;;;; +1213E;CUNEIFORM SIGN HUL2;Lo;0;L;;;;;N;;;;; +1213F;CUNEIFORM SIGN I;Lo;0;L;;;;;N;;;;; +12140;CUNEIFORM SIGN I A;Lo;0;L;;;;;N;;;;; +12141;CUNEIFORM SIGN IB;Lo;0;L;;;;;N;;;;; +12142;CUNEIFORM SIGN IDIM;Lo;0;L;;;;;N;;;;; +12143;CUNEIFORM SIGN IDIM OVER IDIM BUR;Lo;0;L;;;;;N;;;;; +12144;CUNEIFORM SIGN IDIM OVER IDIM SQUARED;Lo;0;L;;;;;N;;;;; +12145;CUNEIFORM SIGN IG;Lo;0;L;;;;;N;;;;; +12146;CUNEIFORM SIGN IGI;Lo;0;L;;;;;N;;;;; +12147;CUNEIFORM SIGN IGI DIB;Lo;0;L;;;;;N;;;;; +12148;CUNEIFORM SIGN IGI RI;Lo;0;L;;;;;N;;;;; +12149;CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD;Lo;0;L;;;;;N;;;;; +1214A;CUNEIFORM SIGN IGI GUNU;Lo;0;L;;;;;N;;;;; +1214B;CUNEIFORM SIGN IL;Lo;0;L;;;;;N;;;;; +1214C;CUNEIFORM SIGN IL TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1214D;CUNEIFORM SIGN IL2;Lo;0;L;;;;;N;;;;; +1214E;CUNEIFORM SIGN IM;Lo;0;L;;;;;N;;;;; +1214F;CUNEIFORM SIGN IM TIMES TAK4;Lo;0;L;;;;;N;;;;; +12150;CUNEIFORM SIGN IM CROSSING IM;Lo;0;L;;;;;N;;;;; +12151;CUNEIFORM SIGN IM OPPOSING IM;Lo;0;L;;;;;N;;;;; +12152;CUNEIFORM SIGN IM SQUARED;Lo;0;L;;;;;N;;;;; +12153;CUNEIFORM SIGN IMIN;Lo;0;L;;;;;N;;;;; +12154;CUNEIFORM SIGN IN;Lo;0;L;;;;;N;;;;; +12155;CUNEIFORM SIGN IR;Lo;0;L;;;;;N;;;;; +12156;CUNEIFORM SIGN ISH;Lo;0;L;;;;;N;;;;; +12157;CUNEIFORM SIGN KA;Lo;0;L;;;;;N;;;;; +12158;CUNEIFORM SIGN KA TIMES A;Lo;0;L;;;;;N;;;;; +12159;CUNEIFORM SIGN KA TIMES AD;Lo;0;L;;;;;N;;;;; +1215A;CUNEIFORM SIGN KA TIMES AD PLUS KU3;Lo;0;L;;;;;N;;;;; +1215B;CUNEIFORM SIGN KA TIMES ASH2;Lo;0;L;;;;;N;;;;; +1215C;CUNEIFORM SIGN KA TIMES BAD;Lo;0;L;;;;;N;;;;; +1215D;CUNEIFORM SIGN KA TIMES BALAG;Lo;0;L;;;;;N;;;;; +1215E;CUNEIFORM SIGN KA TIMES BAR;Lo;0;L;;;;;N;;;;; +1215F;CUNEIFORM SIGN KA TIMES BI;Lo;0;L;;;;;N;;;;; +12160;CUNEIFORM SIGN KA TIMES ERIN2;Lo;0;L;;;;;N;;;;; +12161;CUNEIFORM SIGN KA TIMES ESH2;Lo;0;L;;;;;N;;;;; +12162;CUNEIFORM SIGN KA TIMES GA;Lo;0;L;;;;;N;;;;; +12163;CUNEIFORM SIGN KA TIMES GAL;Lo;0;L;;;;;N;;;;; +12164;CUNEIFORM SIGN KA TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12165;CUNEIFORM SIGN KA TIMES GAR;Lo;0;L;;;;;N;;;;; +12166;CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A;Lo;0;L;;;;;N;;;;; +12167;CUNEIFORM SIGN KA TIMES GI;Lo;0;L;;;;;N;;;;; +12168;CUNEIFORM SIGN KA TIMES GIR2;Lo;0;L;;;;;N;;;;; +12169;CUNEIFORM SIGN KA TIMES GISH PLUS SAR;Lo;0;L;;;;;N;;;;; +1216A;CUNEIFORM SIGN KA TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +1216B;CUNEIFORM SIGN KA TIMES GU;Lo;0;L;;;;;N;;;;; +1216C;CUNEIFORM SIGN KA TIMES GUR7;Lo;0;L;;;;;N;;;;; +1216D;CUNEIFORM SIGN KA TIMES IGI;Lo;0;L;;;;;N;;;;; +1216E;CUNEIFORM SIGN KA TIMES IM;Lo;0;L;;;;;N;;;;; +1216F;CUNEIFORM SIGN KA TIMES KAK;Lo;0;L;;;;;N;;;;; +12170;CUNEIFORM SIGN KA TIMES KI;Lo;0;L;;;;;N;;;;; +12171;CUNEIFORM SIGN KA TIMES KID;Lo;0;L;;;;;N;;;;; +12172;CUNEIFORM SIGN KA TIMES LI;Lo;0;L;;;;;N;;;;; +12173;CUNEIFORM SIGN KA TIMES LU;Lo;0;L;;;;;N;;;;; +12174;CUNEIFORM SIGN KA TIMES ME;Lo;0;L;;;;;N;;;;; +12175;CUNEIFORM SIGN KA TIMES ME PLUS DU;Lo;0;L;;;;;N;;;;; +12176;CUNEIFORM SIGN KA TIMES ME PLUS GI;Lo;0;L;;;;;N;;;;; +12177;CUNEIFORM SIGN KA TIMES ME PLUS TE;Lo;0;L;;;;;N;;;;; +12178;CUNEIFORM SIGN KA TIMES MI;Lo;0;L;;;;;N;;;;; +12179;CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ;Lo;0;L;;;;;N;;;;; +1217A;CUNEIFORM SIGN KA TIMES NE;Lo;0;L;;;;;N;;;;; +1217B;CUNEIFORM SIGN KA TIMES NUN;Lo;0;L;;;;;N;;;;; +1217C;CUNEIFORM SIGN KA TIMES PI;Lo;0;L;;;;;N;;;;; +1217D;CUNEIFORM SIGN KA TIMES RU;Lo;0;L;;;;;N;;;;; +1217E;CUNEIFORM SIGN KA TIMES SA;Lo;0;L;;;;;N;;;;; +1217F;CUNEIFORM SIGN KA TIMES SAR;Lo;0;L;;;;;N;;;;; +12180;CUNEIFORM SIGN KA TIMES SHA;Lo;0;L;;;;;N;;;;; +12181;CUNEIFORM SIGN KA TIMES SHE;Lo;0;L;;;;;N;;;;; +12182;CUNEIFORM SIGN KA TIMES SHID;Lo;0;L;;;;;N;;;;; +12183;CUNEIFORM SIGN KA TIMES SHU;Lo;0;L;;;;;N;;;;; +12184;CUNEIFORM SIGN KA TIMES SIG;Lo;0;L;;;;;N;;;;; +12185;CUNEIFORM SIGN KA TIMES SUHUR;Lo;0;L;;;;;N;;;;; +12186;CUNEIFORM SIGN KA TIMES TAR;Lo;0;L;;;;;N;;;;; +12187;CUNEIFORM SIGN KA TIMES U;Lo;0;L;;;;;N;;;;; +12188;CUNEIFORM SIGN KA TIMES U2;Lo;0;L;;;;;N;;;;; +12189;CUNEIFORM SIGN KA TIMES UD;Lo;0;L;;;;;N;;;;; +1218A;CUNEIFORM SIGN KA TIMES UMUM TIMES PA;Lo;0;L;;;;;N;;;;; +1218B;CUNEIFORM SIGN KA TIMES USH;Lo;0;L;;;;;N;;;;; +1218C;CUNEIFORM SIGN KA TIMES ZI;Lo;0;L;;;;;N;;;;; +1218D;CUNEIFORM SIGN KA2;Lo;0;L;;;;;N;;;;; +1218E;CUNEIFORM SIGN KA2 CROSSING KA2;Lo;0;L;;;;;N;;;;; +1218F;CUNEIFORM SIGN KAB;Lo;0;L;;;;;N;;;;; +12190;CUNEIFORM SIGN KAD2;Lo;0;L;;;;;N;;;;; +12191;CUNEIFORM SIGN KAD3;Lo;0;L;;;;;N;;;;; +12192;CUNEIFORM SIGN KAD4;Lo;0;L;;;;;N;;;;; +12193;CUNEIFORM SIGN KAD5;Lo;0;L;;;;;N;;;;; +12194;CUNEIFORM SIGN KAD5 OVER KAD5;Lo;0;L;;;;;N;;;;; +12195;CUNEIFORM SIGN KAK;Lo;0;L;;;;;N;;;;; +12196;CUNEIFORM SIGN KAK TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12197;CUNEIFORM SIGN KAL;Lo;0;L;;;;;N;;;;; +12198;CUNEIFORM SIGN KAL TIMES BAD;Lo;0;L;;;;;N;;;;; +12199;CUNEIFORM SIGN KAL CROSSING KAL;Lo;0;L;;;;;N;;;;; +1219A;CUNEIFORM SIGN KAM2;Lo;0;L;;;;;N;;;;; +1219B;CUNEIFORM SIGN KAM4;Lo;0;L;;;;;N;;;;; +1219C;CUNEIFORM SIGN KASKAL;Lo;0;L;;;;;N;;;;; +1219D;CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +1219E;CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +1219F;CUNEIFORM SIGN KESH2;Lo;0;L;;;;;N;;;;; +121A0;CUNEIFORM SIGN KI;Lo;0;L;;;;;N;;;;; +121A1;CUNEIFORM SIGN KI TIMES BAD;Lo;0;L;;;;;N;;;;; +121A2;CUNEIFORM SIGN KI TIMES U;Lo;0;L;;;;;N;;;;; +121A3;CUNEIFORM SIGN KI TIMES UD;Lo;0;L;;;;;N;;;;; +121A4;CUNEIFORM SIGN KID;Lo;0;L;;;;;N;;;;; +121A5;CUNEIFORM SIGN KIN;Lo;0;L;;;;;N;;;;; +121A6;CUNEIFORM SIGN KISAL;Lo;0;L;;;;;N;;;;; +121A7;CUNEIFORM SIGN KISH;Lo;0;L;;;;;N;;;;; +121A8;CUNEIFORM SIGN KISIM5;Lo;0;L;;;;;N;;;;; +121A9;CUNEIFORM SIGN KISIM5 OVER KISIM5;Lo;0;L;;;;;N;;;;; +121AA;CUNEIFORM SIGN KU;Lo;0;L;;;;;N;;;;; +121AB;CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +121AC;CUNEIFORM SIGN KU3;Lo;0;L;;;;;N;;;;; +121AD;CUNEIFORM SIGN KU4;Lo;0;L;;;;;N;;;;; +121AE;CUNEIFORM SIGN KU4 VARIANT FORM;Lo;0;L;;;;;N;;;;; +121AF;CUNEIFORM SIGN KU7;Lo;0;L;;;;;N;;;;; +121B0;CUNEIFORM SIGN KUL;Lo;0;L;;;;;N;;;;; +121B1;CUNEIFORM SIGN KUL GUNU;Lo;0;L;;;;;N;;;;; +121B2;CUNEIFORM SIGN KUN;Lo;0;L;;;;;N;;;;; +121B3;CUNEIFORM SIGN KUR;Lo;0;L;;;;;N;;;;; +121B4;CUNEIFORM SIGN KUR OPPOSING KUR;Lo;0;L;;;;;N;;;;; +121B5;CUNEIFORM SIGN KUSHU2;Lo;0;L;;;;;N;;;;; +121B6;CUNEIFORM SIGN KWU318;Lo;0;L;;;;;N;;;;; +121B7;CUNEIFORM SIGN LA;Lo;0;L;;;;;N;;;;; +121B8;CUNEIFORM SIGN LAGAB;Lo;0;L;;;;;N;;;;; +121B9;CUNEIFORM SIGN LAGAB TIMES A;Lo;0;L;;;;;N;;;;; +121BA;CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA;Lo;0;L;;;;;N;;;;; +121BB;CUNEIFORM SIGN LAGAB TIMES A PLUS GAR;Lo;0;L;;;;;N;;;;; +121BC;CUNEIFORM SIGN LAGAB TIMES A PLUS LAL;Lo;0;L;;;;;N;;;;; +121BD;CUNEIFORM SIGN LAGAB TIMES AL;Lo;0;L;;;;;N;;;;; +121BE;CUNEIFORM SIGN LAGAB TIMES AN;Lo;0;L;;;;;N;;;;; +121BF;CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU;Lo;0;L;;;;;N;;;;; +121C0;CUNEIFORM SIGN LAGAB TIMES BAD;Lo;0;L;;;;;N;;;;; +121C1;CUNEIFORM SIGN LAGAB TIMES BI;Lo;0;L;;;;;N;;;;; +121C2;CUNEIFORM SIGN LAGAB TIMES DAR;Lo;0;L;;;;;N;;;;; +121C3;CUNEIFORM SIGN LAGAB TIMES EN;Lo;0;L;;;;;N;;;;; +121C4;CUNEIFORM SIGN LAGAB TIMES GA;Lo;0;L;;;;;N;;;;; +121C5;CUNEIFORM SIGN LAGAB TIMES GAR;Lo;0;L;;;;;N;;;;; +121C6;CUNEIFORM SIGN LAGAB TIMES GUD;Lo;0;L;;;;;N;;;;; +121C7;CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD;Lo;0;L;;;;;N;;;;; +121C8;CUNEIFORM SIGN LAGAB TIMES HA;Lo;0;L;;;;;N;;;;; +121C9;CUNEIFORM SIGN LAGAB TIMES HAL;Lo;0;L;;;;;N;;;;; +121CA;CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN;Lo;0;L;;;;;N;;;;; +121CB;CUNEIFORM SIGN LAGAB TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +121CC;CUNEIFORM SIGN LAGAB TIMES IM;Lo;0;L;;;;;N;;;;; +121CD;CUNEIFORM SIGN LAGAB TIMES IM PLUS HA;Lo;0;L;;;;;N;;;;; +121CE;CUNEIFORM SIGN LAGAB TIMES IM PLUS LU;Lo;0;L;;;;;N;;;;; +121CF;CUNEIFORM SIGN LAGAB TIMES KI;Lo;0;L;;;;;N;;;;; +121D0;CUNEIFORM SIGN LAGAB TIMES KIN;Lo;0;L;;;;;N;;;;; +121D1;CUNEIFORM SIGN LAGAB TIMES KU3;Lo;0;L;;;;;N;;;;; +121D2;CUNEIFORM SIGN LAGAB TIMES KUL;Lo;0;L;;;;;N;;;;; +121D3;CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A;Lo;0;L;;;;;N;;;;; +121D4;CUNEIFORM SIGN LAGAB TIMES LAGAB;Lo;0;L;;;;;N;;;;; +121D5;CUNEIFORM SIGN LAGAB TIMES LISH;Lo;0;L;;;;;N;;;;; +121D6;CUNEIFORM SIGN LAGAB TIMES LU;Lo;0;L;;;;;N;;;;; +121D7;CUNEIFORM SIGN LAGAB TIMES LUL;Lo;0;L;;;;;N;;;;; +121D8;CUNEIFORM SIGN LAGAB TIMES ME;Lo;0;L;;;;;N;;;;; +121D9;CUNEIFORM SIGN LAGAB TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +121DA;CUNEIFORM SIGN LAGAB TIMES MUSH;Lo;0;L;;;;;N;;;;; +121DB;CUNEIFORM SIGN LAGAB TIMES NE;Lo;0;L;;;;;N;;;;; +121DC;CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; +121DD;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2;Lo;0;L;;;;;N;;;;; +121DE;CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU;Lo;0;L;;;;;N;;;;; +121DF;CUNEIFORM SIGN LAGAB TIMES SHU2;Lo;0;L;;;;;N;;;;; +121E0;CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2;Lo;0;L;;;;;N;;;;; +121E1;CUNEIFORM SIGN LAGAB TIMES SUM;Lo;0;L;;;;;N;;;;; +121E2;CUNEIFORM SIGN LAGAB TIMES TAG;Lo;0;L;;;;;N;;;;; +121E3;CUNEIFORM SIGN LAGAB TIMES TAK4;Lo;0;L;;;;;N;;;;; +121E4;CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA;Lo;0;L;;;;;N;;;;; +121E5;CUNEIFORM SIGN LAGAB TIMES U;Lo;0;L;;;;;N;;;;; +121E6;CUNEIFORM SIGN LAGAB TIMES U PLUS A;Lo;0;L;;;;;N;;;;; +121E7;CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +121E8;CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +121E9;CUNEIFORM SIGN LAGAB TIMES UD;Lo;0;L;;;;;N;;;;; +121EA;CUNEIFORM SIGN LAGAB TIMES USH;Lo;0;L;;;;;N;;;;; +121EB;CUNEIFORM SIGN LAGAB SQUARED;Lo;0;L;;;;;N;;;;; +121EC;CUNEIFORM SIGN LAGAR;Lo;0;L;;;;;N;;;;; +121ED;CUNEIFORM SIGN LAGAR TIMES SHE;Lo;0;L;;;;;N;;;;; +121EE;CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM;Lo;0;L;;;;;N;;;;; +121EF;CUNEIFORM SIGN LAGAR GUNU;Lo;0;L;;;;;N;;;;; +121F0;CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE;Lo;0;L;;;;;N;;;;; +121F1;CUNEIFORM SIGN LAHSHU;Lo;0;L;;;;;N;;;;; +121F2;CUNEIFORM SIGN LAL;Lo;0;L;;;;;N;;;;; +121F3;CUNEIFORM SIGN LAL TIMES LAL;Lo;0;L;;;;;N;;;;; +121F4;CUNEIFORM SIGN LAM;Lo;0;L;;;;;N;;;;; +121F5;CUNEIFORM SIGN LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +121F6;CUNEIFORM SIGN LAM TIMES KUR PLUS RU;Lo;0;L;;;;;N;;;;; +121F7;CUNEIFORM SIGN LI;Lo;0;L;;;;;N;;;;; +121F8;CUNEIFORM SIGN LIL;Lo;0;L;;;;;N;;;;; +121F9;CUNEIFORM SIGN LIMMU2;Lo;0;L;;;;;N;;;;; +121FA;CUNEIFORM SIGN LISH;Lo;0;L;;;;;N;;;;; +121FB;CUNEIFORM SIGN LU;Lo;0;L;;;;;N;;;;; +121FC;CUNEIFORM SIGN LU TIMES BAD;Lo;0;L;;;;;N;;;;; +121FD;CUNEIFORM SIGN LU2;Lo;0;L;;;;;N;;;;; +121FE;CUNEIFORM SIGN LU2 TIMES AL;Lo;0;L;;;;;N;;;;; +121FF;CUNEIFORM SIGN LU2 TIMES BAD;Lo;0;L;;;;;N;;;;; +12200;CUNEIFORM SIGN LU2 TIMES ESH2;Lo;0;L;;;;;N;;;;; +12201;CUNEIFORM SIGN LU2 TIMES ESH2 TENU;Lo;0;L;;;;;N;;;;; +12202;CUNEIFORM SIGN LU2 TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12203;CUNEIFORM SIGN LU2 TIMES HI TIMES BAD;Lo;0;L;;;;;N;;;;; +12204;CUNEIFORM SIGN LU2 TIMES IM;Lo;0;L;;;;;N;;;;; +12205;CUNEIFORM SIGN LU2 TIMES KAD2;Lo;0;L;;;;;N;;;;; +12206;CUNEIFORM SIGN LU2 TIMES KAD3;Lo;0;L;;;;;N;;;;; +12207;CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH;Lo;0;L;;;;;N;;;;; +12208;CUNEIFORM SIGN LU2 TIMES KI;Lo;0;L;;;;;N;;;;; +12209;CUNEIFORM SIGN LU2 TIMES LA PLUS ASH;Lo;0;L;;;;;N;;;;; +1220A;CUNEIFORM SIGN LU2 TIMES LAGAB;Lo;0;L;;;;;N;;;;; +1220B;CUNEIFORM SIGN LU2 TIMES ME PLUS EN;Lo;0;L;;;;;N;;;;; +1220C;CUNEIFORM SIGN LU2 TIMES NE;Lo;0;L;;;;;N;;;;; +1220D;CUNEIFORM SIGN LU2 TIMES NU;Lo;0;L;;;;;N;;;;; +1220E;CUNEIFORM SIGN LU2 TIMES SI PLUS ASH;Lo;0;L;;;;;N;;;;; +1220F;CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU;Lo;0;L;;;;;N;;;;; +12210;CUNEIFORM SIGN LU2 TIMES TUG2;Lo;0;L;;;;;N;;;;; +12211;CUNEIFORM SIGN LU2 TENU;Lo;0;L;;;;;N;;;;; +12212;CUNEIFORM SIGN LU2 CROSSING LU2;Lo;0;L;;;;;N;;;;; +12213;CUNEIFORM SIGN LU2 OPPOSING LU2;Lo;0;L;;;;;N;;;;; +12214;CUNEIFORM SIGN LU2 SQUARED;Lo;0;L;;;;;N;;;;; +12215;CUNEIFORM SIGN LU2 SHESHIG;Lo;0;L;;;;;N;;;;; +12216;CUNEIFORM SIGN LU3;Lo;0;L;;;;;N;;;;; +12217;CUNEIFORM SIGN LUGAL;Lo;0;L;;;;;N;;;;; +12218;CUNEIFORM SIGN LUGAL OVER LUGAL;Lo;0;L;;;;;N;;;;; +12219;CUNEIFORM SIGN LUGAL OPPOSING LUGAL;Lo;0;L;;;;;N;;;;; +1221A;CUNEIFORM SIGN LUGAL SHESHIG;Lo;0;L;;;;;N;;;;; +1221B;CUNEIFORM SIGN LUH;Lo;0;L;;;;;N;;;;; +1221C;CUNEIFORM SIGN LUL;Lo;0;L;;;;;N;;;;; +1221D;CUNEIFORM SIGN LUM;Lo;0;L;;;;;N;;;;; +1221E;CUNEIFORM SIGN LUM OVER LUM;Lo;0;L;;;;;N;;;;; +1221F;CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR;Lo;0;L;;;;;N;;;;; +12220;CUNEIFORM SIGN MA;Lo;0;L;;;;;N;;;;; +12221;CUNEIFORM SIGN MA TIMES TAK4;Lo;0;L;;;;;N;;;;; +12222;CUNEIFORM SIGN MA GUNU;Lo;0;L;;;;;N;;;;; +12223;CUNEIFORM SIGN MA2;Lo;0;L;;;;;N;;;;; +12224;CUNEIFORM SIGN MAH;Lo;0;L;;;;;N;;;;; +12225;CUNEIFORM SIGN MAR;Lo;0;L;;;;;N;;;;; +12226;CUNEIFORM SIGN MASH;Lo;0;L;;;;1/2;N;;;;; +12227;CUNEIFORM SIGN MASH2;Lo;0;L;;;;;N;;;;; +12228;CUNEIFORM SIGN ME;Lo;0;L;;;;;N;;;;; +12229;CUNEIFORM SIGN MES;Lo;0;L;;;;;N;;;;; +1222A;CUNEIFORM SIGN MI;Lo;0;L;;;;;N;;;;; +1222B;CUNEIFORM SIGN MIN;Lo;0;L;;;;2;N;;;;; +1222C;CUNEIFORM SIGN MU;Lo;0;L;;;;;N;;;;; +1222D;CUNEIFORM SIGN MU OVER MU;Lo;0;L;;;;;N;;;;; +1222E;CUNEIFORM SIGN MUG;Lo;0;L;;;;;N;;;;; +1222F;CUNEIFORM SIGN MUG GUNU;Lo;0;L;;;;;N;;;;; +12230;CUNEIFORM SIGN MUNSUB;Lo;0;L;;;;;N;;;;; +12231;CUNEIFORM SIGN MURGU2;Lo;0;L;;;;;N;;;;; +12232;CUNEIFORM SIGN MUSH;Lo;0;L;;;;;N;;;;; +12233;CUNEIFORM SIGN MUSH TIMES A;Lo;0;L;;;;;N;;;;; +12234;CUNEIFORM SIGN MUSH TIMES KUR;Lo;0;L;;;;;N;;;;; +12235;CUNEIFORM SIGN MUSH TIMES ZA;Lo;0;L;;;;;N;;;;; +12236;CUNEIFORM SIGN MUSH OVER MUSH;Lo;0;L;;;;;N;;;;; +12237;CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; +12238;CUNEIFORM SIGN MUSH CROSSING MUSH;Lo;0;L;;;;;N;;;;; +12239;CUNEIFORM SIGN MUSH3;Lo;0;L;;;;;N;;;;; +1223A;CUNEIFORM SIGN MUSH3 TIMES A;Lo;0;L;;;;;N;;;;; +1223B;CUNEIFORM SIGN MUSH3 TIMES A PLUS DI;Lo;0;L;;;;;N;;;;; +1223C;CUNEIFORM SIGN MUSH3 TIMES DI;Lo;0;L;;;;;N;;;;; +1223D;CUNEIFORM SIGN MUSH3 GUNU;Lo;0;L;;;;;N;;;;; +1223E;CUNEIFORM SIGN NA;Lo;0;L;;;;;N;;;;; +1223F;CUNEIFORM SIGN NA2;Lo;0;L;;;;;N;;;;; +12240;CUNEIFORM SIGN NAGA;Lo;0;L;;;;;N;;;;; +12241;CUNEIFORM SIGN NAGA INVERTED;Lo;0;L;;;;;N;;;;; +12242;CUNEIFORM SIGN NAGA TIMES SHU TENU;Lo;0;L;;;;;N;;;;; +12243;CUNEIFORM SIGN NAGA OPPOSING NAGA;Lo;0;L;;;;;N;;;;; +12244;CUNEIFORM SIGN NAGAR;Lo;0;L;;;;;N;;;;; +12245;CUNEIFORM SIGN NAM NUTILLU;Lo;0;L;;;;;N;;;;; +12246;CUNEIFORM SIGN NAM;Lo;0;L;;;;;N;;;;; +12247;CUNEIFORM SIGN NAM2;Lo;0;L;;;;;N;;;;; +12248;CUNEIFORM SIGN NE;Lo;0;L;;;;;N;;;;; +12249;CUNEIFORM SIGN NE TIMES A;Lo;0;L;;;;;N;;;;; +1224A;CUNEIFORM SIGN NE TIMES UD;Lo;0;L;;;;;N;;;;; +1224B;CUNEIFORM SIGN NE SHESHIG;Lo;0;L;;;;;N;;;;; +1224C;CUNEIFORM SIGN NI;Lo;0;L;;;;;N;;;;; +1224D;CUNEIFORM SIGN NI TIMES E;Lo;0;L;;;;;N;;;;; +1224E;CUNEIFORM SIGN NI2;Lo;0;L;;;;;N;;;;; +1224F;CUNEIFORM SIGN NIM;Lo;0;L;;;;;N;;;;; +12250;CUNEIFORM SIGN NIM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +12251;CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; +12252;CUNEIFORM SIGN NINDA2;Lo;0;L;;;;;N;;;;; +12253;CUNEIFORM SIGN NINDA2 TIMES AN;Lo;0;L;;;;;N;;;;; +12254;CUNEIFORM SIGN NINDA2 TIMES ASH;Lo;0;L;;;;;N;;;;; +12255;CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH;Lo;0;L;;;;;N;;;;; +12256;CUNEIFORM SIGN NINDA2 TIMES GUD;Lo;0;L;;;;;N;;;;; +12257;CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU;Lo;0;L;;;;;N;;;;; +12258;CUNEIFORM SIGN NINDA2 TIMES NE;Lo;0;L;;;;;N;;;;; +12259;CUNEIFORM SIGN NINDA2 TIMES NUN;Lo;0;L;;;;;N;;;;; +1225A;CUNEIFORM SIGN NINDA2 TIMES SHE;Lo;0;L;;;;;N;;;;; +1225B;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN;Lo;0;L;;;;;N;;;;; +1225C;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH;Lo;0;L;;;;;N;;;;; +1225D;CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH;Lo;0;L;;;;;N;;;;; +1225E;CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +1225F;CUNEIFORM SIGN NINDA2 TIMES USH;Lo;0;L;;;;;N;;;;; +12260;CUNEIFORM SIGN NISAG;Lo;0;L;;;;;N;;;;; +12261;CUNEIFORM SIGN NU;Lo;0;L;;;;;N;;;;; +12262;CUNEIFORM SIGN NU11;Lo;0;L;;;;;N;;;;; +12263;CUNEIFORM SIGN NUN;Lo;0;L;;;;;N;;;;; +12264;CUNEIFORM SIGN NUN LAGAR TIMES GAR;Lo;0;L;;;;;N;;;;; +12265;CUNEIFORM SIGN NUN LAGAR TIMES MASH;Lo;0;L;;;;;N;;;;; +12266;CUNEIFORM SIGN NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; +12267;CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL;Lo;0;L;;;;;N;;;;; +12268;CUNEIFORM SIGN NUN LAGAR TIMES USH;Lo;0;L;;;;;N;;;;; +12269;CUNEIFORM SIGN NUN TENU;Lo;0;L;;;;;N;;;;; +1226A;CUNEIFORM SIGN NUN OVER NUN;Lo;0;L;;;;;N;;;;; +1226B;CUNEIFORM SIGN NUN CROSSING NUN;Lo;0;L;;;;;N;;;;; +1226C;CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR;Lo;0;L;;;;;N;;;;; +1226D;CUNEIFORM SIGN NUNUZ;Lo;0;L;;;;;N;;;;; +1226E;CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB;Lo;0;L;;;;;N;;;;; +1226F;CUNEIFORM SIGN NUNUZ AB2 TIMES BI;Lo;0;L;;;;;N;;;;; +12270;CUNEIFORM SIGN NUNUZ AB2 TIMES DUG;Lo;0;L;;;;;N;;;;; +12271;CUNEIFORM SIGN NUNUZ AB2 TIMES GUD;Lo;0;L;;;;;N;;;;; +12272;CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12273;CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3;Lo;0;L;;;;;N;;;;; +12274;CUNEIFORM SIGN NUNUZ AB2 TIMES LA;Lo;0;L;;;;;N;;;;; +12275;CUNEIFORM SIGN NUNUZ AB2 TIMES NE;Lo;0;L;;;;;N;;;;; +12276;CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3;Lo;0;L;;;;;N;;;;; +12277;CUNEIFORM SIGN NUNUZ AB2 TIMES U2;Lo;0;L;;;;;N;;;;; +12278;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI;Lo;0;L;;;;;N;;;;; +12279;CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U;Lo;0;L;;;;;N;;;;; +1227A;CUNEIFORM SIGN PA;Lo;0;L;;;;;N;;;;; +1227B;CUNEIFORM SIGN PAD;Lo;0;L;;;;;N;;;;; +1227C;CUNEIFORM SIGN PAN;Lo;0;L;;;;;N;;;;; +1227D;CUNEIFORM SIGN PAP;Lo;0;L;;;;;N;;;;; +1227E;CUNEIFORM SIGN PESH2;Lo;0;L;;;;;N;;;;; +1227F;CUNEIFORM SIGN PI;Lo;0;L;;;;;N;;;;; +12280;CUNEIFORM SIGN PI TIMES A;Lo;0;L;;;;;N;;;;; +12281;CUNEIFORM SIGN PI TIMES AB;Lo;0;L;;;;;N;;;;; +12282;CUNEIFORM SIGN PI TIMES BI;Lo;0;L;;;;;N;;;;; +12283;CUNEIFORM SIGN PI TIMES BU;Lo;0;L;;;;;N;;;;; +12284;CUNEIFORM SIGN PI TIMES E;Lo;0;L;;;;;N;;;;; +12285;CUNEIFORM SIGN PI TIMES I;Lo;0;L;;;;;N;;;;; +12286;CUNEIFORM SIGN PI TIMES IB;Lo;0;L;;;;;N;;;;; +12287;CUNEIFORM SIGN PI TIMES U;Lo;0;L;;;;;N;;;;; +12288;CUNEIFORM SIGN PI TIMES U2;Lo;0;L;;;;;N;;;;; +12289;CUNEIFORM SIGN PI CROSSING PI;Lo;0;L;;;;;N;;;;; +1228A;CUNEIFORM SIGN PIRIG;Lo;0;L;;;;;N;;;;; +1228B;CUNEIFORM SIGN PIRIG TIMES KAL;Lo;0;L;;;;;N;;;;; +1228C;CUNEIFORM SIGN PIRIG TIMES UD;Lo;0;L;;;;;N;;;;; +1228D;CUNEIFORM SIGN PIRIG TIMES ZA;Lo;0;L;;;;;N;;;;; +1228E;CUNEIFORM SIGN PIRIG OPPOSING PIRIG;Lo;0;L;;;;;N;;;;; +1228F;CUNEIFORM SIGN RA;Lo;0;L;;;;;N;;;;; +12290;CUNEIFORM SIGN RAB;Lo;0;L;;;;;N;;;;; +12291;CUNEIFORM SIGN RI;Lo;0;L;;;;;N;;;;; +12292;CUNEIFORM SIGN RU;Lo;0;L;;;;;N;;;;; +12293;CUNEIFORM SIGN SA;Lo;0;L;;;;;N;;;;; +12294;CUNEIFORM SIGN SAG NUTILLU;Lo;0;L;;;;;N;;;;; +12295;CUNEIFORM SIGN SAG;Lo;0;L;;;;;N;;;;; +12296;CUNEIFORM SIGN SAG TIMES A;Lo;0;L;;;;;N;;;;; +12297;CUNEIFORM SIGN SAG TIMES DU;Lo;0;L;;;;;N;;;;; +12298;CUNEIFORM SIGN SAG TIMES DUB;Lo;0;L;;;;;N;;;;; +12299;CUNEIFORM SIGN SAG TIMES HA;Lo;0;L;;;;;N;;;;; +1229A;CUNEIFORM SIGN SAG TIMES KAK;Lo;0;L;;;;;N;;;;; +1229B;CUNEIFORM SIGN SAG TIMES KUR;Lo;0;L;;;;;N;;;;; +1229C;CUNEIFORM SIGN SAG TIMES LUM;Lo;0;L;;;;;N;;;;; +1229D;CUNEIFORM SIGN SAG TIMES MI;Lo;0;L;;;;;N;;;;; +1229E;CUNEIFORM SIGN SAG TIMES NUN;Lo;0;L;;;;;N;;;;; +1229F;CUNEIFORM SIGN SAG TIMES SAL;Lo;0;L;;;;;N;;;;; +122A0;CUNEIFORM SIGN SAG TIMES SHID;Lo;0;L;;;;;N;;;;; +122A1;CUNEIFORM SIGN SAG TIMES TAB;Lo;0;L;;;;;N;;;;; +122A2;CUNEIFORM SIGN SAG TIMES U2;Lo;0;L;;;;;N;;;;; +122A3;CUNEIFORM SIGN SAG TIMES UB;Lo;0;L;;;;;N;;;;; +122A4;CUNEIFORM SIGN SAG TIMES UM;Lo;0;L;;;;;N;;;;; +122A5;CUNEIFORM SIGN SAG TIMES UR;Lo;0;L;;;;;N;;;;; +122A6;CUNEIFORM SIGN SAG TIMES USH;Lo;0;L;;;;;N;;;;; +122A7;CUNEIFORM SIGN SAG OVER SAG;Lo;0;L;;;;;N;;;;; +122A8;CUNEIFORM SIGN SAG GUNU;Lo;0;L;;;;;N;;;;; +122A9;CUNEIFORM SIGN SAL;Lo;0;L;;;;;N;;;;; +122AA;CUNEIFORM SIGN SAL LAGAB TIMES ASH2;Lo;0;L;;;;;N;;;;; +122AB;CUNEIFORM SIGN SANGA2;Lo;0;L;;;;;N;;;;; +122AC;CUNEIFORM SIGN SAR;Lo;0;L;;;;;N;;;;; +122AD;CUNEIFORM SIGN SHA;Lo;0;L;;;;;N;;;;; +122AE;CUNEIFORM SIGN SHA3;Lo;0;L;;;;;N;;;;; +122AF;CUNEIFORM SIGN SHA3 TIMES A;Lo;0;L;;;;;N;;;;; +122B0;CUNEIFORM SIGN SHA3 TIMES BAD;Lo;0;L;;;;;N;;;;; +122B1;CUNEIFORM SIGN SHA3 TIMES GISH;Lo;0;L;;;;;N;;;;; +122B2;CUNEIFORM SIGN SHA3 TIMES NE;Lo;0;L;;;;;N;;;;; +122B3;CUNEIFORM SIGN SHA3 TIMES SHU2;Lo;0;L;;;;;N;;;;; +122B4;CUNEIFORM SIGN SHA3 TIMES TUR;Lo;0;L;;;;;N;;;;; +122B5;CUNEIFORM SIGN SHA3 TIMES U;Lo;0;L;;;;;N;;;;; +122B6;CUNEIFORM SIGN SHA3 TIMES U PLUS A;Lo;0;L;;;;;N;;;;; +122B7;CUNEIFORM SIGN SHA6;Lo;0;L;;;;;N;;;;; +122B8;CUNEIFORM SIGN SHAB6;Lo;0;L;;;;;N;;;;; +122B9;CUNEIFORM SIGN SHAR2;Lo;0;L;;;;;N;;;;; +122BA;CUNEIFORM SIGN SHE;Lo;0;L;;;;;N;;;;; +122BB;CUNEIFORM SIGN SHE HU;Lo;0;L;;;;;N;;;;; +122BC;CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +122BD;CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR;Lo;0;L;;;;;N;;;;; +122BE;CUNEIFORM SIGN SHEG9;Lo;0;L;;;;;N;;;;; +122BF;CUNEIFORM SIGN SHEN;Lo;0;L;;;;;N;;;;; +122C0;CUNEIFORM SIGN SHESH;Lo;0;L;;;;;N;;;;; +122C1;CUNEIFORM SIGN SHESH2;Lo;0;L;;;;;N;;;;; +122C2;CUNEIFORM SIGN SHESHLAM;Lo;0;L;;;;;N;;;;; +122C3;CUNEIFORM SIGN SHID;Lo;0;L;;;;;N;;;;; +122C4;CUNEIFORM SIGN SHID TIMES A;Lo;0;L;;;;;N;;;;; +122C5;CUNEIFORM SIGN SHID TIMES IM;Lo;0;L;;;;;N;;;;; +122C6;CUNEIFORM SIGN SHIM;Lo;0;L;;;;;N;;;;; +122C7;CUNEIFORM SIGN SHIM TIMES A;Lo;0;L;;;;;N;;;;; +122C8;CUNEIFORM SIGN SHIM TIMES BAL;Lo;0;L;;;;;N;;;;; +122C9;CUNEIFORM SIGN SHIM TIMES BULUG;Lo;0;L;;;;;N;;;;; +122CA;CUNEIFORM SIGN SHIM TIMES DIN;Lo;0;L;;;;;N;;;;; +122CB;CUNEIFORM SIGN SHIM TIMES GAR;Lo;0;L;;;;;N;;;;; +122CC;CUNEIFORM SIGN SHIM TIMES IGI;Lo;0;L;;;;;N;;;;; +122CD;CUNEIFORM SIGN SHIM TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +122CE;CUNEIFORM SIGN SHIM TIMES KUSHU2;Lo;0;L;;;;;N;;;;; +122CF;CUNEIFORM SIGN SHIM TIMES LUL;Lo;0;L;;;;;N;;;;; +122D0;CUNEIFORM SIGN SHIM TIMES MUG;Lo;0;L;;;;;N;;;;; +122D1;CUNEIFORM SIGN SHIM TIMES SAL;Lo;0;L;;;;;N;;;;; +122D2;CUNEIFORM SIGN SHINIG;Lo;0;L;;;;;N;;;;; +122D3;CUNEIFORM SIGN SHIR;Lo;0;L;;;;;N;;;;; +122D4;CUNEIFORM SIGN SHIR TENU;Lo;0;L;;;;;N;;;;; +122D5;CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR;Lo;0;L;;;;;N;;;;; +122D6;CUNEIFORM SIGN SHITA;Lo;0;L;;;;;N;;;;; +122D7;CUNEIFORM SIGN SHU;Lo;0;L;;;;;N;;;;; +122D8;CUNEIFORM SIGN SHU OVER INVERTED SHU;Lo;0;L;;;;;N;;;;; +122D9;CUNEIFORM SIGN SHU2;Lo;0;L;;;;;N;;;;; +122DA;CUNEIFORM SIGN SHUBUR;Lo;0;L;;;;;N;;;;; +122DB;CUNEIFORM SIGN SI;Lo;0;L;;;;;N;;;;; +122DC;CUNEIFORM SIGN SI GUNU;Lo;0;L;;;;;N;;;;; +122DD;CUNEIFORM SIGN SIG;Lo;0;L;;;;;N;;;;; +122DE;CUNEIFORM SIGN SIG4;Lo;0;L;;;;;N;;;;; +122DF;CUNEIFORM SIGN SIG4 OVER SIG4 SHU2;Lo;0;L;;;;;N;;;;; +122E0;CUNEIFORM SIGN SIK2;Lo;0;L;;;;;N;;;;; +122E1;CUNEIFORM SIGN SILA3;Lo;0;L;;;;;N;;;;; +122E2;CUNEIFORM SIGN SU;Lo;0;L;;;;;N;;;;; +122E3;CUNEIFORM SIGN SU OVER SU;Lo;0;L;;;;;N;;;;; +122E4;CUNEIFORM SIGN SUD;Lo;0;L;;;;;N;;;;; +122E5;CUNEIFORM SIGN SUD2;Lo;0;L;;;;;N;;;;; +122E6;CUNEIFORM SIGN SUHUR;Lo;0;L;;;;;N;;;;; +122E7;CUNEIFORM SIGN SUM;Lo;0;L;;;;;N;;;;; +122E8;CUNEIFORM SIGN SUMASH;Lo;0;L;;;;;N;;;;; +122E9;CUNEIFORM SIGN SUR;Lo;0;L;;;;;N;;;;; +122EA;CUNEIFORM SIGN SUR9;Lo;0;L;;;;;N;;;;; +122EB;CUNEIFORM SIGN TA;Lo;0;L;;;;;N;;;;; +122EC;CUNEIFORM SIGN TA ASTERISK;Lo;0;L;;;;;N;;;;; +122ED;CUNEIFORM SIGN TA TIMES HI;Lo;0;L;;;;;N;;;;; +122EE;CUNEIFORM SIGN TA TIMES MI;Lo;0;L;;;;;N;;;;; +122EF;CUNEIFORM SIGN TA GUNU;Lo;0;L;;;;;N;;;;; +122F0;CUNEIFORM SIGN TAB;Lo;0;L;;;;;N;;;;; +122F1;CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH;Lo;0;L;;;;;N;;;;; +122F2;CUNEIFORM SIGN TAB SQUARED;Lo;0;L;;;;;N;;;;; +122F3;CUNEIFORM SIGN TAG;Lo;0;L;;;;;N;;;;; +122F4;CUNEIFORM SIGN TAG TIMES BI;Lo;0;L;;;;;N;;;;; +122F5;CUNEIFORM SIGN TAG TIMES GUD;Lo;0;L;;;;;N;;;;; +122F6;CUNEIFORM SIGN TAG TIMES SHE;Lo;0;L;;;;;N;;;;; +122F7;CUNEIFORM SIGN TAG TIMES SHU;Lo;0;L;;;;;N;;;;; +122F8;CUNEIFORM SIGN TAG TIMES TUG2;Lo;0;L;;;;;N;;;;; +122F9;CUNEIFORM SIGN TAG TIMES UD;Lo;0;L;;;;;N;;;;; +122FA;CUNEIFORM SIGN TAK4;Lo;0;L;;;;;N;;;;; +122FB;CUNEIFORM SIGN TAR;Lo;0;L;;;;;N;;;;; +122FC;CUNEIFORM SIGN TE;Lo;0;L;;;;;N;;;;; +122FD;CUNEIFORM SIGN TE GUNU;Lo;0;L;;;;;N;;;;; +122FE;CUNEIFORM SIGN TI;Lo;0;L;;;;;N;;;;; +122FF;CUNEIFORM SIGN TI TENU;Lo;0;L;;;;;N;;;;; +12300;CUNEIFORM SIGN TIL;Lo;0;L;;;;;N;;;;; +12301;CUNEIFORM SIGN TIR;Lo;0;L;;;;;N;;;;; +12302;CUNEIFORM SIGN TIR TIMES TAK4;Lo;0;L;;;;;N;;;;; +12303;CUNEIFORM SIGN TIR OVER TIR;Lo;0;L;;;;;N;;;;; +12304;CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR;Lo;0;L;;;;;N;;;;; +12305;CUNEIFORM SIGN TU;Lo;0;L;;;;;N;;;;; +12306;CUNEIFORM SIGN TUG2;Lo;0;L;;;;;N;;;;; +12307;CUNEIFORM SIGN TUK;Lo;0;L;;;;;N;;;;; +12308;CUNEIFORM SIGN TUM;Lo;0;L;;;;;N;;;;; +12309;CUNEIFORM SIGN TUR;Lo;0;L;;;;;N;;;;; +1230A;CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA;Lo;0;L;;;;;N;;;;; +1230B;CUNEIFORM SIGN U;Lo;0;L;;;;1;N;;;;; +1230C;CUNEIFORM SIGN U GUD;Lo;0;L;;;;;N;;;;; +1230D;CUNEIFORM SIGN U U U;Lo;0;L;;;;3;N;;;;; +1230E;CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR;Lo;0;L;;;;;N;;;;; +1230F;CUNEIFORM SIGN U OVER U SUR OVER SUR;Lo;0;L;;;;;N;;;;; +12310;CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED;Lo;0;L;;;;;N;;;;; +12311;CUNEIFORM SIGN U2;Lo;0;L;;;;;N;;;;; +12312;CUNEIFORM SIGN UB;Lo;0;L;;;;;N;;;;; +12313;CUNEIFORM SIGN UD;Lo;0;L;;;;;N;;;;; +12314;CUNEIFORM SIGN UD KUSHU2;Lo;0;L;;;;;N;;;;; +12315;CUNEIFORM SIGN UD TIMES BAD;Lo;0;L;;;;;N;;;;; +12316;CUNEIFORM SIGN UD TIMES MI;Lo;0;L;;;;;N;;;;; +12317;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U;Lo;0;L;;;;;N;;;;; +12318;CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU;Lo;0;L;;;;;N;;;;; +12319;CUNEIFORM SIGN UD GUNU;Lo;0;L;;;;;N;;;;; +1231A;CUNEIFORM SIGN UD SHESHIG;Lo;0;L;;;;;N;;;;; +1231B;CUNEIFORM SIGN UD SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; +1231C;CUNEIFORM SIGN UDUG;Lo;0;L;;;;;N;;;;; +1231D;CUNEIFORM SIGN UM;Lo;0;L;;;;;N;;;;; +1231E;CUNEIFORM SIGN UM TIMES LAGAB;Lo;0;L;;;;;N;;;;; +1231F;CUNEIFORM SIGN UM TIMES ME PLUS DA;Lo;0;L;;;;;N;;;;; +12320;CUNEIFORM SIGN UM TIMES SHA3;Lo;0;L;;;;;N;;;;; +12321;CUNEIFORM SIGN UM TIMES U;Lo;0;L;;;;;N;;;;; +12322;CUNEIFORM SIGN UMBIN;Lo;0;L;;;;;N;;;;; +12323;CUNEIFORM SIGN UMUM;Lo;0;L;;;;;N;;;;; +12324;CUNEIFORM SIGN UMUM TIMES KASKAL;Lo;0;L;;;;;N;;;;; +12325;CUNEIFORM SIGN UMUM TIMES PA;Lo;0;L;;;;;N;;;;; +12326;CUNEIFORM SIGN UN;Lo;0;L;;;;;N;;;;; +12327;CUNEIFORM SIGN UN GUNU;Lo;0;L;;;;;N;;;;; +12328;CUNEIFORM SIGN UR;Lo;0;L;;;;;N;;;;; +12329;CUNEIFORM SIGN UR CROSSING UR;Lo;0;L;;;;;N;;;;; +1232A;CUNEIFORM SIGN UR SHESHIG;Lo;0;L;;;;;N;;;;; +1232B;CUNEIFORM SIGN UR2;Lo;0;L;;;;;N;;;;; +1232C;CUNEIFORM SIGN UR2 TIMES A PLUS HA;Lo;0;L;;;;;N;;;;; +1232D;CUNEIFORM SIGN UR2 TIMES A PLUS NA;Lo;0;L;;;;;N;;;;; +1232E;CUNEIFORM SIGN UR2 TIMES AL;Lo;0;L;;;;;N;;;;; +1232F;CUNEIFORM SIGN UR2 TIMES HA;Lo;0;L;;;;;N;;;;; +12330;CUNEIFORM SIGN UR2 TIMES NUN;Lo;0;L;;;;;N;;;;; +12331;CUNEIFORM SIGN UR2 TIMES U2;Lo;0;L;;;;;N;;;;; +12332;CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH;Lo;0;L;;;;;N;;;;; +12333;CUNEIFORM SIGN UR2 TIMES U2 PLUS BI;Lo;0;L;;;;;N;;;;; +12334;CUNEIFORM SIGN UR4;Lo;0;L;;;;;N;;;;; +12335;CUNEIFORM SIGN URI;Lo;0;L;;;;;N;;;;; +12336;CUNEIFORM SIGN URI3;Lo;0;L;;;;;N;;;;; +12337;CUNEIFORM SIGN URU;Lo;0;L;;;;;N;;;;; +12338;CUNEIFORM SIGN URU TIMES A;Lo;0;L;;;;;N;;;;; +12339;CUNEIFORM SIGN URU TIMES ASHGAB;Lo;0;L;;;;;N;;;;; +1233A;CUNEIFORM SIGN URU TIMES BAR;Lo;0;L;;;;;N;;;;; +1233B;CUNEIFORM SIGN URU TIMES DUN;Lo;0;L;;;;;N;;;;; +1233C;CUNEIFORM SIGN URU TIMES GA;Lo;0;L;;;;;N;;;;; +1233D;CUNEIFORM SIGN URU TIMES GAL;Lo;0;L;;;;;N;;;;; +1233E;CUNEIFORM SIGN URU TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1233F;CUNEIFORM SIGN URU TIMES GAR;Lo;0;L;;;;;N;;;;; +12340;CUNEIFORM SIGN URU TIMES GU;Lo;0;L;;;;;N;;;;; +12341;CUNEIFORM SIGN URU TIMES HA;Lo;0;L;;;;;N;;;;; +12342;CUNEIFORM SIGN URU TIMES IGI;Lo;0;L;;;;;N;;;;; +12343;CUNEIFORM SIGN URU TIMES IM;Lo;0;L;;;;;N;;;;; +12344;CUNEIFORM SIGN URU TIMES ISH;Lo;0;L;;;;;N;;;;; +12345;CUNEIFORM SIGN URU TIMES KI;Lo;0;L;;;;;N;;;;; +12346;CUNEIFORM SIGN URU TIMES LUM;Lo;0;L;;;;;N;;;;; +12347;CUNEIFORM SIGN URU TIMES MIN;Lo;0;L;;;;;N;;;;; +12348;CUNEIFORM SIGN URU TIMES PA;Lo;0;L;;;;;N;;;;; +12349;CUNEIFORM SIGN URU TIMES SHE;Lo;0;L;;;;;N;;;;; +1234A;CUNEIFORM SIGN URU TIMES SIG4;Lo;0;L;;;;;N;;;;; +1234B;CUNEIFORM SIGN URU TIMES TU;Lo;0;L;;;;;N;;;;; +1234C;CUNEIFORM SIGN URU TIMES U PLUS GUD;Lo;0;L;;;;;N;;;;; +1234D;CUNEIFORM SIGN URU TIMES UD;Lo;0;L;;;;;N;;;;; +1234E;CUNEIFORM SIGN URU TIMES URUDA;Lo;0;L;;;;;N;;;;; +1234F;CUNEIFORM SIGN URUDA;Lo;0;L;;;;;N;;;;; +12350;CUNEIFORM SIGN URUDA TIMES U;Lo;0;L;;;;;N;;;;; +12351;CUNEIFORM SIGN USH;Lo;0;L;;;;;N;;;;; +12352;CUNEIFORM SIGN USH TIMES A;Lo;0;L;;;;;N;;;;; +12353;CUNEIFORM SIGN USH TIMES KU;Lo;0;L;;;;;N;;;;; +12354;CUNEIFORM SIGN USH TIMES KUR;Lo;0;L;;;;;N;;;;; +12355;CUNEIFORM SIGN USH TIMES TAK4;Lo;0;L;;;;;N;;;;; +12356;CUNEIFORM SIGN USHX;Lo;0;L;;;;;N;;;;; +12357;CUNEIFORM SIGN USH2;Lo;0;L;;;;;N;;;;; +12358;CUNEIFORM SIGN USHUMX;Lo;0;L;;;;;N;;;;; +12359;CUNEIFORM SIGN UTUKI;Lo;0;L;;;;;N;;;;; +1235A;CUNEIFORM SIGN UZ3;Lo;0;L;;;;;N;;;;; +1235B;CUNEIFORM SIGN UZ3 TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1235C;CUNEIFORM SIGN UZU;Lo;0;L;;;;;N;;;;; +1235D;CUNEIFORM SIGN ZA;Lo;0;L;;;;;N;;;;; +1235E;CUNEIFORM SIGN ZA TENU;Lo;0;L;;;;;N;;;;; +1235F;CUNEIFORM SIGN ZA SQUARED TIMES KUR;Lo;0;L;;;;;N;;;;; +12360;CUNEIFORM SIGN ZAG;Lo;0;L;;;;;N;;;;; +12361;CUNEIFORM SIGN ZAMX;Lo;0;L;;;;;N;;;;; +12362;CUNEIFORM SIGN ZE2;Lo;0;L;;;;;N;;;;; +12363;CUNEIFORM SIGN ZI;Lo;0;L;;;;;N;;;;; +12364;CUNEIFORM SIGN ZI OVER ZI;Lo;0;L;;;;;N;;;;; +12365;CUNEIFORM SIGN ZI3;Lo;0;L;;;;;N;;;;; +12366;CUNEIFORM SIGN ZIB;Lo;0;L;;;;;N;;;;; +12367;CUNEIFORM SIGN ZIB KABA TENU;Lo;0;L;;;;;N;;;;; +12368;CUNEIFORM SIGN ZIG;Lo;0;L;;;;;N;;;;; +12369;CUNEIFORM SIGN ZIZ2;Lo;0;L;;;;;N;;;;; +1236A;CUNEIFORM SIGN ZU;Lo;0;L;;;;;N;;;;; +1236B;CUNEIFORM SIGN ZU5;Lo;0;L;;;;;N;;;;; +1236C;CUNEIFORM SIGN ZU5 TIMES A;Lo;0;L;;;;;N;;;;; +1236D;CUNEIFORM SIGN ZUBUR;Lo;0;L;;;;;N;;;;; +1236E;CUNEIFORM SIGN ZUM;Lo;0;L;;;;;N;;;;; +1236F;CUNEIFORM SIGN KAP ELAMITE;Lo;0;L;;;;;N;;;;; +12370;CUNEIFORM SIGN AB TIMES NUN;Lo;0;L;;;;;N;;;;; +12371;CUNEIFORM SIGN AB2 TIMES A;Lo;0;L;;;;;N;;;;; +12372;CUNEIFORM SIGN AMAR TIMES KUG;Lo;0;L;;;;;N;;;;; +12373;CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS MASH;Lo;0;L;;;;;N;;;;; +12374;CUNEIFORM SIGN DAG3;Lo;0;L;;;;;N;;;;; +12375;CUNEIFORM SIGN DISH PLUS SHU;Lo;0;L;;;;;N;;;;; +12376;CUNEIFORM SIGN DUB TIMES SHE;Lo;0;L;;;;;N;;;;; +12377;CUNEIFORM SIGN EZEN TIMES GUD;Lo;0;L;;;;;N;;;;; +12378;CUNEIFORM SIGN EZEN TIMES SHE;Lo;0;L;;;;;N;;;;; +12379;CUNEIFORM SIGN GA2 TIMES AN PLUS KAK PLUS A;Lo;0;L;;;;;N;;;;; +1237A;CUNEIFORM SIGN GA2 TIMES ASH2;Lo;0;L;;;;;N;;;;; +1237B;CUNEIFORM SIGN GE22;Lo;0;L;;;;;N;;;;; +1237C;CUNEIFORM SIGN GIG;Lo;0;L;;;;;N;;;;; +1237D;CUNEIFORM SIGN HUSH;Lo;0;L;;;;;N;;;;; +1237E;CUNEIFORM SIGN KA TIMES ANSHE;Lo;0;L;;;;;N;;;;; +1237F;CUNEIFORM SIGN KA TIMES ASH3;Lo;0;L;;;;;N;;;;; +12380;CUNEIFORM SIGN KA TIMES GISH;Lo;0;L;;;;;N;;;;; +12381;CUNEIFORM SIGN KA TIMES GUD;Lo;0;L;;;;;N;;;;; +12382;CUNEIFORM SIGN KA TIMES HI TIMES ASH2;Lo;0;L;;;;;N;;;;; +12383;CUNEIFORM SIGN KA TIMES LUM;Lo;0;L;;;;;N;;;;; +12384;CUNEIFORM SIGN KA TIMES PA;Lo;0;L;;;;;N;;;;; +12385;CUNEIFORM SIGN KA TIMES SHUL;Lo;0;L;;;;;N;;;;; +12386;CUNEIFORM SIGN KA TIMES TU;Lo;0;L;;;;;N;;;;; +12387;CUNEIFORM SIGN KA TIMES UR2;Lo;0;L;;;;;N;;;;; +12388;CUNEIFORM SIGN LAGAB TIMES GI;Lo;0;L;;;;;N;;;;; +12389;CUNEIFORM SIGN LU2 SHESHIG TIMES BAD;Lo;0;L;;;;;N;;;;; +1238A;CUNEIFORM SIGN LU2 TIMES ESH2 PLUS LAL;Lo;0;L;;;;;N;;;;; +1238B;CUNEIFORM SIGN LU2 TIMES SHU;Lo;0;L;;;;;N;;;;; +1238C;CUNEIFORM SIGN MESH;Lo;0;L;;;;;N;;;;; +1238D;CUNEIFORM SIGN MUSH3 TIMES ZA;Lo;0;L;;;;;N;;;;; +1238E;CUNEIFORM SIGN NA4;Lo;0;L;;;;;N;;;;; +1238F;CUNEIFORM SIGN NIN;Lo;0;L;;;;;N;;;;; +12390;CUNEIFORM SIGN NIN9;Lo;0;L;;;;;N;;;;; +12391;CUNEIFORM SIGN NINDA2 TIMES BAL;Lo;0;L;;;;;N;;;;; +12392;CUNEIFORM SIGN NINDA2 TIMES GI;Lo;0;L;;;;;N;;;;; +12393;CUNEIFORM SIGN NU11 ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; +12394;CUNEIFORM SIGN PESH2 ASTERISK;Lo;0;L;;;;;N;;;;; +12395;CUNEIFORM SIGN PIR2;Lo;0;L;;;;;N;;;;; +12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;; +12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;; +12399;CUNEIFORM SIGN U U;Lo;0;L;;;;2;N;;;;; +12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;; +12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;; +12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;; +12403;CUNEIFORM NUMERIC SIGN FIVE ASH;Nl;0;L;;;;5;N;;;;; +12404;CUNEIFORM NUMERIC SIGN SIX ASH;Nl;0;L;;;;6;N;;;;; +12405;CUNEIFORM NUMERIC SIGN SEVEN ASH;Nl;0;L;;;;7;N;;;;; +12406;CUNEIFORM NUMERIC SIGN EIGHT ASH;Nl;0;L;;;;8;N;;;;; +12407;CUNEIFORM NUMERIC SIGN NINE ASH;Nl;0;L;;;;9;N;;;;; +12408;CUNEIFORM NUMERIC SIGN THREE DISH;Nl;0;L;;;;3;N;;;;; +12409;CUNEIFORM NUMERIC SIGN FOUR DISH;Nl;0;L;;;;4;N;;;;; +1240A;CUNEIFORM NUMERIC SIGN FIVE DISH;Nl;0;L;;;;5;N;;;;; +1240B;CUNEIFORM NUMERIC SIGN SIX DISH;Nl;0;L;;;;6;N;;;;; +1240C;CUNEIFORM NUMERIC SIGN SEVEN DISH;Nl;0;L;;;;7;N;;;;; +1240D;CUNEIFORM NUMERIC SIGN EIGHT DISH;Nl;0;L;;;;8;N;;;;; +1240E;CUNEIFORM NUMERIC SIGN NINE DISH;Nl;0;L;;;;9;N;;;;; +1240F;CUNEIFORM NUMERIC SIGN FOUR U;Nl;0;L;;;;4;N;;;;; +12410;CUNEIFORM NUMERIC SIGN FIVE U;Nl;0;L;;;;5;N;;;;; +12411;CUNEIFORM NUMERIC SIGN SIX U;Nl;0;L;;;;6;N;;;;; +12412;CUNEIFORM NUMERIC SIGN SEVEN U;Nl;0;L;;;;7;N;;;;; +12413;CUNEIFORM NUMERIC SIGN EIGHT U;Nl;0;L;;;;8;N;;;;; +12414;CUNEIFORM NUMERIC SIGN NINE U;Nl;0;L;;;;9;N;;;;; +12415;CUNEIFORM NUMERIC SIGN ONE GESH2;Nl;0;L;;;;1;N;;;;; +12416;CUNEIFORM NUMERIC SIGN TWO GESH2;Nl;0;L;;;;2;N;;;;; +12417;CUNEIFORM NUMERIC SIGN THREE GESH2;Nl;0;L;;;;3;N;;;;; +12418;CUNEIFORM NUMERIC SIGN FOUR GESH2;Nl;0;L;;;;4;N;;;;; +12419;CUNEIFORM NUMERIC SIGN FIVE GESH2;Nl;0;L;;;;5;N;;;;; +1241A;CUNEIFORM NUMERIC SIGN SIX GESH2;Nl;0;L;;;;6;N;;;;; +1241B;CUNEIFORM NUMERIC SIGN SEVEN GESH2;Nl;0;L;;;;7;N;;;;; +1241C;CUNEIFORM NUMERIC SIGN EIGHT GESH2;Nl;0;L;;;;8;N;;;;; +1241D;CUNEIFORM NUMERIC SIGN NINE GESH2;Nl;0;L;;;;9;N;;;;; +1241E;CUNEIFORM NUMERIC SIGN ONE GESHU;Nl;0;L;;;;1;N;;;;; +1241F;CUNEIFORM NUMERIC SIGN TWO GESHU;Nl;0;L;;;;2;N;;;;; +12420;CUNEIFORM NUMERIC SIGN THREE GESHU;Nl;0;L;;;;3;N;;;;; +12421;CUNEIFORM NUMERIC SIGN FOUR GESHU;Nl;0;L;;;;4;N;;;;; +12422;CUNEIFORM NUMERIC SIGN FIVE GESHU;Nl;0;L;;;;5;N;;;;; +12423;CUNEIFORM NUMERIC SIGN TWO SHAR2;Nl;0;L;;;;2;N;;;;; +12424;CUNEIFORM NUMERIC SIGN THREE SHAR2;Nl;0;L;;;;3;N;;;;; +12425;CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12426;CUNEIFORM NUMERIC SIGN FOUR SHAR2;Nl;0;L;;;;4;N;;;;; +12427;CUNEIFORM NUMERIC SIGN FIVE SHAR2;Nl;0;L;;;;5;N;;;;; +12428;CUNEIFORM NUMERIC SIGN SIX SHAR2;Nl;0;L;;;;6;N;;;;; +12429;CUNEIFORM NUMERIC SIGN SEVEN SHAR2;Nl;0;L;;;;7;N;;;;; +1242A;CUNEIFORM NUMERIC SIGN EIGHT SHAR2;Nl;0;L;;;;8;N;;;;; +1242B;CUNEIFORM NUMERIC SIGN NINE SHAR2;Nl;0;L;;;;9;N;;;;; +1242C;CUNEIFORM NUMERIC SIGN ONE SHARU;Nl;0;L;;;;1;N;;;;; +1242D;CUNEIFORM NUMERIC SIGN TWO SHARU;Nl;0;L;;;;2;N;;;;; +1242E;CUNEIFORM NUMERIC SIGN THREE SHARU;Nl;0;L;;;;3;N;;;;; +1242F;CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12430;CUNEIFORM NUMERIC SIGN FOUR SHARU;Nl;0;L;;;;4;N;;;;; +12431;CUNEIFORM NUMERIC SIGN FIVE SHARU;Nl;0;L;;;;5;N;;;;; +12432;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH;Nl;0;L;;;;216000;N;;;;; +12433;CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN;Nl;0;L;;;;432000;N;;;;; +12434;CUNEIFORM NUMERIC SIGN ONE BURU;Nl;0;L;;;;1;N;;;;; +12435;CUNEIFORM NUMERIC SIGN TWO BURU;Nl;0;L;;;;2;N;;;;; +12436;CUNEIFORM NUMERIC SIGN THREE BURU;Nl;0;L;;;;3;N;;;;; +12437;CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM;Nl;0;L;;;;3;N;;;;; +12438;CUNEIFORM NUMERIC SIGN FOUR BURU;Nl;0;L;;;;4;N;;;;; +12439;CUNEIFORM NUMERIC SIGN FIVE BURU;Nl;0;L;;;;5;N;;;;; +1243A;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16;Nl;0;L;;;;3;N;;;;; +1243B;CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21;Nl;0;L;;;;3;N;;;;; +1243C;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU;Nl;0;L;;;;4;N;;;;; +1243D;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4;Nl;0;L;;;;4;N;;;;; +1243E;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A;Nl;0;L;;;;4;N;;;;; +1243F;CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B;Nl;0;L;;;;4;N;;;;; +12440;CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9;Nl;0;L;;;;6;N;;;;; +12441;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3;Nl;0;L;;;;7;N;;;;; +12442;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A;Nl;0;L;;;;7;N;;;;; +12443;CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B;Nl;0;L;;;;7;N;;;;; +12444;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU;Nl;0;L;;;;8;N;;;;; +12445;CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3;Nl;0;L;;;;8;N;;;;; +12446;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU;Nl;0;L;;;;9;N;;;;; +12447;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3;Nl;0;L;;;;9;N;;;;; +12448;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4;Nl;0;L;;;;9;N;;;;; +12449;CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A;Nl;0;L;;;;9;N;;;;; +1244A;CUNEIFORM NUMERIC SIGN TWO ASH TENU;Nl;0;L;;;;2;N;;;;; +1244B;CUNEIFORM NUMERIC SIGN THREE ASH TENU;Nl;0;L;;;;3;N;;;;; +1244C;CUNEIFORM NUMERIC SIGN FOUR ASH TENU;Nl;0;L;;;;4;N;;;;; +1244D;CUNEIFORM NUMERIC SIGN FIVE ASH TENU;Nl;0;L;;;;5;N;;;;; +1244E;CUNEIFORM NUMERIC SIGN SIX ASH TENU;Nl;0;L;;;;6;N;;;;; +1244F;CUNEIFORM NUMERIC SIGN ONE BAN2;Nl;0;L;;;;1;N;;;;; +12450;CUNEIFORM NUMERIC SIGN TWO BAN2;Nl;0;L;;;;2;N;;;;; +12451;CUNEIFORM NUMERIC SIGN THREE BAN2;Nl;0;L;;;;3;N;;;;; +12452;CUNEIFORM NUMERIC SIGN FOUR BAN2;Nl;0;L;;;;4;N;;;;; +12453;CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM;Nl;0;L;;;;4;N;;;;; +12454;CUNEIFORM NUMERIC SIGN FIVE BAN2;Nl;0;L;;;;5;N;;;;; +12455;CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM;Nl;0;L;;;;5;N;;;;; +12456;CUNEIFORM NUMERIC SIGN NIGIDAMIN;Nl;0;L;;;;2;N;;;;; +12457;CUNEIFORM NUMERIC SIGN NIGIDAESH;Nl;0;L;;;;3;N;;;;; +12458;CUNEIFORM NUMERIC SIGN ONE ESHE3;Nl;0;L;;;;1;N;;;;; +12459;CUNEIFORM NUMERIC SIGN TWO ESHE3;Nl;0;L;;;;2;N;;;;; +1245A;CUNEIFORM NUMERIC SIGN ONE THIRD DISH;Nl;0;L;;;;1/3;N;;;;; +1245B;CUNEIFORM NUMERIC SIGN TWO THIRDS DISH;Nl;0;L;;;;2/3;N;;;;; +1245C;CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH;Nl;0;L;;;;5/6;N;;;;; +1245D;CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A;Nl;0;L;;;;1/3;N;;;;; +1245E;CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A;Nl;0;L;;;;2/3;N;;;;; +1245F;CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH;Nl;0;L;;;;1/8;N;;;;; +12460;CUNEIFORM NUMERIC SIGN ONE QUARTER ASH;Nl;0;L;;;;1/4;N;;;;; +12461;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH;Nl;0;L;;;;1/6;N;;;;; +12462;CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER;Nl;0;L;;;;1/4;N;;;;; +12463;CUNEIFORM NUMERIC SIGN ONE QUARTER GUR;Nl;0;L;;;;1/4;N;;;;; +12464;CUNEIFORM NUMERIC SIGN ONE HALF GUR;Nl;0;L;;;;1/2;N;;;;; +12465;CUNEIFORM NUMERIC SIGN ELAMITE ONE THIRD;Nl;0;L;;;;1/3;N;;;;; +12466;CUNEIFORM NUMERIC SIGN ELAMITE TWO THIRDS;Nl;0;L;;;;2/3;N;;;;; +12467;CUNEIFORM NUMERIC SIGN ELAMITE FORTY;Nl;0;L;;;;40;N;;;;; +12468;CUNEIFORM NUMERIC SIGN ELAMITE FIFTY;Nl;0;L;;;;50;N;;;;; +12469;CUNEIFORM NUMERIC SIGN FOUR U VARIANT FORM;Nl;0;L;;;;4;N;;;;; +1246A;CUNEIFORM NUMERIC SIGN FIVE U VARIANT FORM;Nl;0;L;;;;5;N;;;;; +1246B;CUNEIFORM NUMERIC SIGN SIX U VARIANT FORM;Nl;0;L;;;;6;N;;;;; +1246C;CUNEIFORM NUMERIC SIGN SEVEN U VARIANT FORM;Nl;0;L;;;;7;N;;;;; +1246D;CUNEIFORM NUMERIC SIGN EIGHT U VARIANT FORM;Nl;0;L;;;;8;N;;;;; +1246E;CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM;Nl;0;L;;;;9;N;;;;; +12470;CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER;Po;0;L;;;;;N;;;;; +12471;CUNEIFORM PUNCTUATION SIGN VERTICAL COLON;Po;0;L;;;;;N;;;;; +12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;; +12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;; +12474;CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON;Po;0;L;;;;;N;;;;; +12480;CUNEIFORM SIGN AB TIMES NUN TENU;Lo;0;L;;;;;N;;;;; +12481;CUNEIFORM SIGN AB TIMES SHU2;Lo;0;L;;;;;N;;;;; +12482;CUNEIFORM SIGN AD TIMES ESH2;Lo;0;L;;;;;N;;;;; +12483;CUNEIFORM SIGN BAD TIMES DISH TENU;Lo;0;L;;;;;N;;;;; +12484;CUNEIFORM SIGN BAHAR2 TIMES AB2;Lo;0;L;;;;;N;;;;; +12485;CUNEIFORM SIGN BAHAR2 TIMES NI;Lo;0;L;;;;;N;;;;; +12486;CUNEIFORM SIGN BAHAR2 TIMES ZA;Lo;0;L;;;;;N;;;;; +12487;CUNEIFORM SIGN BU OVER BU TIMES NA2;Lo;0;L;;;;;N;;;;; +12488;CUNEIFORM SIGN DA TIMES TAK4;Lo;0;L;;;;;N;;;;; +12489;CUNEIFORM SIGN DAG TIMES KUR;Lo;0;L;;;;;N;;;;; +1248A;CUNEIFORM SIGN DIM TIMES IGI;Lo;0;L;;;;;N;;;;; +1248B;CUNEIFORM SIGN DIM TIMES U U U;Lo;0;L;;;;;N;;;;; +1248C;CUNEIFORM SIGN DIM2 TIMES UD;Lo;0;L;;;;;N;;;;; +1248D;CUNEIFORM SIGN DUG TIMES ANSHE;Lo;0;L;;;;;N;;;;; +1248E;CUNEIFORM SIGN DUG TIMES ASH;Lo;0;L;;;;;N;;;;; +1248F;CUNEIFORM SIGN DUG TIMES ASH AT LEFT;Lo;0;L;;;;;N;;;;; +12490;CUNEIFORM SIGN DUG TIMES DIN;Lo;0;L;;;;;N;;;;; +12491;CUNEIFORM SIGN DUG TIMES DUN;Lo;0;L;;;;;N;;;;; +12492;CUNEIFORM SIGN DUG TIMES ERIN2;Lo;0;L;;;;;N;;;;; +12493;CUNEIFORM SIGN DUG TIMES GA;Lo;0;L;;;;;N;;;;; +12494;CUNEIFORM SIGN DUG TIMES GI;Lo;0;L;;;;;N;;;;; +12495;CUNEIFORM SIGN DUG TIMES GIR2 GUNU;Lo;0;L;;;;;N;;;;; +12496;CUNEIFORM SIGN DUG TIMES GISH;Lo;0;L;;;;;N;;;;; +12497;CUNEIFORM SIGN DUG TIMES HA;Lo;0;L;;;;;N;;;;; +12498;CUNEIFORM SIGN DUG TIMES HI;Lo;0;L;;;;;N;;;;; +12499;CUNEIFORM SIGN DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +1249A;CUNEIFORM SIGN DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; +1249B;CUNEIFORM SIGN DUG TIMES KUR;Lo;0;L;;;;;N;;;;; +1249C;CUNEIFORM SIGN DUG TIMES KUSHU2;Lo;0;L;;;;;N;;;;; +1249D;CUNEIFORM SIGN DUG TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; +1249E;CUNEIFORM SIGN DUG TIMES LAK-020;Lo;0;L;;;;;N;;;;; +1249F;CUNEIFORM SIGN DUG TIMES LAM;Lo;0;L;;;;;N;;;;; +124A0;CUNEIFORM SIGN DUG TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +124A1;CUNEIFORM SIGN DUG TIMES LUH PLUS GISH;Lo;0;L;;;;;N;;;;; +124A2;CUNEIFORM SIGN DUG TIMES MASH;Lo;0;L;;;;;N;;;;; +124A3;CUNEIFORM SIGN DUG TIMES MES;Lo;0;L;;;;;N;;;;; +124A4;CUNEIFORM SIGN DUG TIMES MI;Lo;0;L;;;;;N;;;;; +124A5;CUNEIFORM SIGN DUG TIMES NI;Lo;0;L;;;;;N;;;;; +124A6;CUNEIFORM SIGN DUG TIMES PI;Lo;0;L;;;;;N;;;;; +124A7;CUNEIFORM SIGN DUG TIMES SHE;Lo;0;L;;;;;N;;;;; +124A8;CUNEIFORM SIGN DUG TIMES SI GUNU;Lo;0;L;;;;;N;;;;; +124A9;CUNEIFORM SIGN E2 TIMES KUR;Lo;0;L;;;;;N;;;;; +124AA;CUNEIFORM SIGN E2 TIMES PAP;Lo;0;L;;;;;N;;;;; +124AB;CUNEIFORM SIGN ERIN2 X;Lo;0;L;;;;;N;;;;; +124AC;CUNEIFORM SIGN ESH2 CROSSING ESH2;Lo;0;L;;;;;N;;;;; +124AD;CUNEIFORM SIGN EZEN SHESHIG TIMES ASH;Lo;0;L;;;;;N;;;;; +124AE;CUNEIFORM SIGN EZEN SHESHIG TIMES HI;Lo;0;L;;;;;N;;;;; +124AF;CUNEIFORM SIGN EZEN SHESHIG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124B0;CUNEIFORM SIGN EZEN SHESHIG TIMES LA;Lo;0;L;;;;;N;;;;; +124B1;CUNEIFORM SIGN EZEN SHESHIG TIMES LAL;Lo;0;L;;;;;N;;;;; +124B2;CUNEIFORM SIGN EZEN SHESHIG TIMES ME;Lo;0;L;;;;;N;;;;; +124B3;CUNEIFORM SIGN EZEN SHESHIG TIMES MES;Lo;0;L;;;;;N;;;;; +124B4;CUNEIFORM SIGN EZEN SHESHIG TIMES SU;Lo;0;L;;;;;N;;;;; +124B5;CUNEIFORM SIGN EZEN TIMES SU;Lo;0;L;;;;;N;;;;; +124B6;CUNEIFORM SIGN GA2 TIMES BAHAR2;Lo;0;L;;;;;N;;;;; +124B7;CUNEIFORM SIGN GA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; +124B8;CUNEIFORM SIGN GA2 TIMES DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124B9;CUNEIFORM SIGN GA2 TIMES DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;; +124BA;CUNEIFORM SIGN GA2 TIMES EREN;Lo;0;L;;;;;N;;;;; +124BB;CUNEIFORM SIGN GA2 TIMES GA;Lo;0;L;;;;;N;;;;; +124BC;CUNEIFORM SIGN GA2 TIMES GAR PLUS DI;Lo;0;L;;;;;N;;;;; +124BD;CUNEIFORM SIGN GA2 TIMES GAR PLUS NE;Lo;0;L;;;;;N;;;;; +124BE;CUNEIFORM SIGN GA2 TIMES HA PLUS A;Lo;0;L;;;;;N;;;;; +124BF;CUNEIFORM SIGN GA2 TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;; +124C0;CUNEIFORM SIGN GA2 TIMES LAM;Lo;0;L;;;;;N;;;;; +124C1;CUNEIFORM SIGN GA2 TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;; +124C2;CUNEIFORM SIGN GA2 TIMES LUH;Lo;0;L;;;;;N;;;;; +124C3;CUNEIFORM SIGN GA2 TIMES MUSH;Lo;0;L;;;;;N;;;;; +124C4;CUNEIFORM SIGN GA2 TIMES NE;Lo;0;L;;;;;N;;;;; +124C5;CUNEIFORM SIGN GA2 TIMES NE PLUS E2;Lo;0;L;;;;;N;;;;; +124C6;CUNEIFORM SIGN GA2 TIMES NE PLUS GI;Lo;0;L;;;;;N;;;;; +124C7;CUNEIFORM SIGN GA2 TIMES SHIM;Lo;0;L;;;;;N;;;;; +124C8;CUNEIFORM SIGN GA2 TIMES ZIZ2;Lo;0;L;;;;;N;;;;; +124C9;CUNEIFORM SIGN GABA ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;; +124CA;CUNEIFORM SIGN GESHTIN TIMES U;Lo;0;L;;;;;N;;;;; +124CB;CUNEIFORM SIGN GISH TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;; +124CC;CUNEIFORM SIGN GU2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +124CD;CUNEIFORM SIGN GUD PLUS GISH TIMES TAK4;Lo;0;L;;;;;N;;;;; +124CE;CUNEIFORM SIGN HA TENU GUNU;Lo;0;L;;;;;N;;;;; +124CF;CUNEIFORM SIGN HI TIMES ASH OVER HI TIMES ASH;Lo;0;L;;;;;N;;;;; +124D0;CUNEIFORM SIGN KA TIMES BU;Lo;0;L;;;;;N;;;;; +124D1;CUNEIFORM SIGN KA TIMES KA;Lo;0;L;;;;;N;;;;; +124D2;CUNEIFORM SIGN KA TIMES U U U;Lo;0;L;;;;;N;;;;; +124D3;CUNEIFORM SIGN KA TIMES UR;Lo;0;L;;;;;N;;;;; +124D4;CUNEIFORM SIGN LAGAB TIMES ZU OVER ZU;Lo;0;L;;;;;N;;;;; +124D5;CUNEIFORM SIGN LAK-003;Lo;0;L;;;;;N;;;;; +124D6;CUNEIFORM SIGN LAK-021;Lo;0;L;;;;;N;;;;; +124D7;CUNEIFORM SIGN LAK-025;Lo;0;L;;;;;N;;;;; +124D8;CUNEIFORM SIGN LAK-030;Lo;0;L;;;;;N;;;;; +124D9;CUNEIFORM SIGN LAK-050;Lo;0;L;;;;;N;;;;; +124DA;CUNEIFORM SIGN LAK-051;Lo;0;L;;;;;N;;;;; +124DB;CUNEIFORM SIGN LAK-062;Lo;0;L;;;;;N;;;;; +124DC;CUNEIFORM SIGN LAK-079 OVER LAK-079 GUNU;Lo;0;L;;;;;N;;;;; +124DD;CUNEIFORM SIGN LAK-080;Lo;0;L;;;;;N;;;;; +124DE;CUNEIFORM SIGN LAK-081 OVER LAK-081;Lo;0;L;;;;;N;;;;; +124DF;CUNEIFORM SIGN LAK-092;Lo;0;L;;;;;N;;;;; +124E0;CUNEIFORM SIGN LAK-130;Lo;0;L;;;;;N;;;;; +124E1;CUNEIFORM SIGN LAK-142;Lo;0;L;;;;;N;;;;; +124E2;CUNEIFORM SIGN LAK-210;Lo;0;L;;;;;N;;;;; +124E3;CUNEIFORM SIGN LAK-219;Lo;0;L;;;;;N;;;;; +124E4;CUNEIFORM SIGN LAK-220;Lo;0;L;;;;;N;;;;; +124E5;CUNEIFORM SIGN LAK-225;Lo;0;L;;;;;N;;;;; +124E6;CUNEIFORM SIGN LAK-228;Lo;0;L;;;;;N;;;;; +124E7;CUNEIFORM SIGN LAK-238;Lo;0;L;;;;;N;;;;; +124E8;CUNEIFORM SIGN LAK-265;Lo;0;L;;;;;N;;;;; +124E9;CUNEIFORM SIGN LAK-266;Lo;0;L;;;;;N;;;;; +124EA;CUNEIFORM SIGN LAK-343;Lo;0;L;;;;;N;;;;; +124EB;CUNEIFORM SIGN LAK-347;Lo;0;L;;;;;N;;;;; +124EC;CUNEIFORM SIGN LAK-348;Lo;0;L;;;;;N;;;;; +124ED;CUNEIFORM SIGN LAK-383;Lo;0;L;;;;;N;;;;; +124EE;CUNEIFORM SIGN LAK-384;Lo;0;L;;;;;N;;;;; +124EF;CUNEIFORM SIGN LAK-390;Lo;0;L;;;;;N;;;;; +124F0;CUNEIFORM SIGN LAK-441;Lo;0;L;;;;;N;;;;; +124F1;CUNEIFORM SIGN LAK-449;Lo;0;L;;;;;N;;;;; +124F2;CUNEIFORM SIGN LAK-449 TIMES GU;Lo;0;L;;;;;N;;;;; +124F3;CUNEIFORM SIGN LAK-449 TIMES IGI;Lo;0;L;;;;;N;;;;; +124F4;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +124F5;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +124F6;CUNEIFORM SIGN LAK-449 TIMES U2 PLUS BA;Lo;0;L;;;;;N;;;;; +124F7;CUNEIFORM SIGN LAK-450;Lo;0;L;;;;;N;;;;; +124F8;CUNEIFORM SIGN LAK-457;Lo;0;L;;;;;N;;;;; +124F9;CUNEIFORM SIGN LAK-470;Lo;0;L;;;;;N;;;;; +124FA;CUNEIFORM SIGN LAK-483;Lo;0;L;;;;;N;;;;; +124FB;CUNEIFORM SIGN LAK-490;Lo;0;L;;;;;N;;;;; +124FC;CUNEIFORM SIGN LAK-492;Lo;0;L;;;;;N;;;;; +124FD;CUNEIFORM SIGN LAK-493;Lo;0;L;;;;;N;;;;; +124FE;CUNEIFORM SIGN LAK-495;Lo;0;L;;;;;N;;;;; +124FF;CUNEIFORM SIGN LAK-550;Lo;0;L;;;;;N;;;;; +12500;CUNEIFORM SIGN LAK-608;Lo;0;L;;;;;N;;;;; +12501;CUNEIFORM SIGN LAK-617;Lo;0;L;;;;;N;;;;; +12502;CUNEIFORM SIGN LAK-617 TIMES ASH;Lo;0;L;;;;;N;;;;; +12503;CUNEIFORM SIGN LAK-617 TIMES BAD;Lo;0;L;;;;;N;;;;; +12504;CUNEIFORM SIGN LAK-617 TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;; +12505;CUNEIFORM SIGN LAK-617 TIMES KU3;Lo;0;L;;;;;N;;;;; +12506;CUNEIFORM SIGN LAK-617 TIMES LA;Lo;0;L;;;;;N;;;;; +12507;CUNEIFORM SIGN LAK-617 TIMES TAR;Lo;0;L;;;;;N;;;;; +12508;CUNEIFORM SIGN LAK-617 TIMES TE;Lo;0;L;;;;;N;;;;; +12509;CUNEIFORM SIGN LAK-617 TIMES U2;Lo;0;L;;;;;N;;;;; +1250A;CUNEIFORM SIGN LAK-617 TIMES UD;Lo;0;L;;;;;N;;;;; +1250B;CUNEIFORM SIGN LAK-617 TIMES URUDA;Lo;0;L;;;;;N;;;;; +1250C;CUNEIFORM SIGN LAK-636;Lo;0;L;;;;;N;;;;; +1250D;CUNEIFORM SIGN LAK-648;Lo;0;L;;;;;N;;;;; +1250E;CUNEIFORM SIGN LAK-648 TIMES DUB;Lo;0;L;;;;;N;;;;; +1250F;CUNEIFORM SIGN LAK-648 TIMES GA;Lo;0;L;;;;;N;;;;; +12510;CUNEIFORM SIGN LAK-648 TIMES IGI;Lo;0;L;;;;;N;;;;; +12511;CUNEIFORM SIGN LAK-648 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;; +12512;CUNEIFORM SIGN LAK-648 TIMES NI;Lo;0;L;;;;;N;;;;; +12513;CUNEIFORM SIGN LAK-648 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +12514;CUNEIFORM SIGN LAK-648 TIMES SHESH PLUS KI;Lo;0;L;;;;;N;;;;; +12515;CUNEIFORM SIGN LAK-648 TIMES UD;Lo;0;L;;;;;N;;;;; +12516;CUNEIFORM SIGN LAK-648 TIMES URUDA;Lo;0;L;;;;;N;;;;; +12517;CUNEIFORM SIGN LAK-724;Lo;0;L;;;;;N;;;;; +12518;CUNEIFORM SIGN LAK-749;Lo;0;L;;;;;N;;;;; +12519;CUNEIFORM SIGN LU2 GUNU TIMES ASH;Lo;0;L;;;;;N;;;;; +1251A;CUNEIFORM SIGN LU2 TIMES DISH;Lo;0;L;;;;;N;;;;; +1251B;CUNEIFORM SIGN LU2 TIMES HAL;Lo;0;L;;;;;N;;;;; +1251C;CUNEIFORM SIGN LU2 TIMES PAP;Lo;0;L;;;;;N;;;;; +1251D;CUNEIFORM SIGN LU2 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;; +1251E;CUNEIFORM SIGN LU2 TIMES TAK4;Lo;0;L;;;;;N;;;;; +1251F;CUNEIFORM SIGN MI PLUS ZA7;Lo;0;L;;;;;N;;;;; +12520;CUNEIFORM SIGN MUSH OVER MUSH TIMES GA;Lo;0;L;;;;;N;;;;; +12521;CUNEIFORM SIGN MUSH OVER MUSH TIMES KAK;Lo;0;L;;;;;N;;;;; +12522;CUNEIFORM SIGN NINDA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;; +12523;CUNEIFORM SIGN NINDA2 TIMES GISH;Lo;0;L;;;;;N;;;;; +12524;CUNEIFORM SIGN NINDA2 TIMES GUL;Lo;0;L;;;;;N;;;;; +12525;CUNEIFORM SIGN NINDA2 TIMES HI;Lo;0;L;;;;;N;;;;; +12526;CUNEIFORM SIGN NINDA2 TIMES KESH2;Lo;0;L;;;;;N;;;;; +12527;CUNEIFORM SIGN NINDA2 TIMES LAK-050;Lo;0;L;;;;;N;;;;; +12528;CUNEIFORM SIGN NINDA2 TIMES MASH;Lo;0;L;;;;;N;;;;; +12529;CUNEIFORM SIGN NINDA2 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;; +1252A;CUNEIFORM SIGN NINDA2 TIMES U;Lo;0;L;;;;;N;;;;; +1252B;CUNEIFORM SIGN NINDA2 TIMES U PLUS U;Lo;0;L;;;;;N;;;;; +1252C;CUNEIFORM SIGN NINDA2 TIMES URUDA;Lo;0;L;;;;;N;;;;; +1252D;CUNEIFORM SIGN SAG GUNU TIMES HA;Lo;0;L;;;;;N;;;;; +1252E;CUNEIFORM SIGN SAG TIMES EN;Lo;0;L;;;;;N;;;;; +1252F;CUNEIFORM SIGN SAG TIMES SHE AT LEFT;Lo;0;L;;;;;N;;;;; +12530;CUNEIFORM SIGN SAG TIMES TAK4;Lo;0;L;;;;;N;;;;; +12531;CUNEIFORM SIGN SHA6 TENU;Lo;0;L;;;;;N;;;;; +12532;CUNEIFORM SIGN SHE OVER SHE;Lo;0;L;;;;;N;;;;; +12533;CUNEIFORM SIGN SHE PLUS HUB2;Lo;0;L;;;;;N;;;;; +12534;CUNEIFORM SIGN SHE PLUS NAM2;Lo;0;L;;;;;N;;;;; +12535;CUNEIFORM SIGN SHE PLUS SAR;Lo;0;L;;;;;N;;;;; +12536;CUNEIFORM SIGN SHU2 PLUS DUG TIMES NI;Lo;0;L;;;;;N;;;;; +12537;CUNEIFORM SIGN SHU2 PLUS E2 TIMES AN;Lo;0;L;;;;;N;;;;; +12538;CUNEIFORM SIGN SI TIMES TAK4;Lo;0;L;;;;;N;;;;; +12539;CUNEIFORM SIGN TAK4 PLUS SAG;Lo;0;L;;;;;N;;;;; +1253A;CUNEIFORM SIGN TUM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;; +1253B;CUNEIFORM SIGN TUM TIMES THREE DISH;Lo;0;L;;;;;N;;;;; +1253C;CUNEIFORM SIGN UR2 INVERTED;Lo;0;L;;;;;N;;;;; +1253D;CUNEIFORM SIGN UR2 TIMES UD;Lo;0;L;;;;;N;;;;; +1253E;CUNEIFORM SIGN URU TIMES DARA3;Lo;0;L;;;;;N;;;;; +1253F;CUNEIFORM SIGN URU TIMES LAK-668;Lo;0;L;;;;;N;;;;; +12540;CUNEIFORM SIGN URU TIMES LU3;Lo;0;L;;;;;N;;;;; +12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;; +12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;; +12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;; +12F90;CYPRO-MINOAN SIGN CM001;Lo;0;L;;;;;N;;;;; +12F91;CYPRO-MINOAN SIGN CM002;Lo;0;L;;;;;N;;;;; +12F92;CYPRO-MINOAN SIGN CM004;Lo;0;L;;;;;N;;;;; +12F93;CYPRO-MINOAN SIGN CM005;Lo;0;L;;;;;N;;;;; +12F94;CYPRO-MINOAN SIGN CM006;Lo;0;L;;;;;N;;;;; +12F95;CYPRO-MINOAN SIGN CM007;Lo;0;L;;;;;N;;;;; +12F96;CYPRO-MINOAN SIGN CM008;Lo;0;L;;;;;N;;;;; +12F97;CYPRO-MINOAN SIGN CM009;Lo;0;L;;;;;N;;;;; +12F98;CYPRO-MINOAN SIGN CM010;Lo;0;L;;;;;N;;;;; +12F99;CYPRO-MINOAN SIGN CM011;Lo;0;L;;;;;N;;;;; +12F9A;CYPRO-MINOAN SIGN CM012;Lo;0;L;;;;;N;;;;; +12F9B;CYPRO-MINOAN SIGN CM012B;Lo;0;L;;;;;N;;;;; +12F9C;CYPRO-MINOAN SIGN CM013;Lo;0;L;;;;;N;;;;; +12F9D;CYPRO-MINOAN SIGN CM015;Lo;0;L;;;;;N;;;;; +12F9E;CYPRO-MINOAN SIGN CM017;Lo;0;L;;;;;N;;;;; +12F9F;CYPRO-MINOAN SIGN CM019;Lo;0;L;;;;;N;;;;; +12FA0;CYPRO-MINOAN SIGN CM021;Lo;0;L;;;;;N;;;;; +12FA1;CYPRO-MINOAN SIGN CM023;Lo;0;L;;;;;N;;;;; +12FA2;CYPRO-MINOAN SIGN CM024;Lo;0;L;;;;;N;;;;; +12FA3;CYPRO-MINOAN SIGN CM025;Lo;0;L;;;;;N;;;;; +12FA4;CYPRO-MINOAN SIGN CM026;Lo;0;L;;;;;N;;;;; +12FA5;CYPRO-MINOAN SIGN CM027;Lo;0;L;;;;;N;;;;; +12FA6;CYPRO-MINOAN SIGN CM028;Lo;0;L;;;;;N;;;;; +12FA7;CYPRO-MINOAN SIGN CM029;Lo;0;L;;;;;N;;;;; +12FA8;CYPRO-MINOAN SIGN CM030;Lo;0;L;;;;;N;;;;; +12FA9;CYPRO-MINOAN SIGN CM033;Lo;0;L;;;;;N;;;;; +12FAA;CYPRO-MINOAN SIGN CM034;Lo;0;L;;;;;N;;;;; +12FAB;CYPRO-MINOAN SIGN CM035;Lo;0;L;;;;;N;;;;; +12FAC;CYPRO-MINOAN SIGN CM036;Lo;0;L;;;;;N;;;;; +12FAD;CYPRO-MINOAN SIGN CM037;Lo;0;L;;;;;N;;;;; +12FAE;CYPRO-MINOAN SIGN CM038;Lo;0;L;;;;;N;;;;; +12FAF;CYPRO-MINOAN SIGN CM039;Lo;0;L;;;;;N;;;;; +12FB0;CYPRO-MINOAN SIGN CM040;Lo;0;L;;;;;N;;;;; +12FB1;CYPRO-MINOAN SIGN CM041;Lo;0;L;;;;;N;;;;; +12FB2;CYPRO-MINOAN SIGN CM044;Lo;0;L;;;;;N;;;;; +12FB3;CYPRO-MINOAN SIGN CM046;Lo;0;L;;;;;N;;;;; +12FB4;CYPRO-MINOAN SIGN CM047;Lo;0;L;;;;;N;;;;; +12FB5;CYPRO-MINOAN SIGN CM049;Lo;0;L;;;;;N;;;;; +12FB6;CYPRO-MINOAN SIGN CM050;Lo;0;L;;;;;N;;;;; +12FB7;CYPRO-MINOAN SIGN CM051;Lo;0;L;;;;;N;;;;; +12FB8;CYPRO-MINOAN SIGN CM052;Lo;0;L;;;;;N;;;;; +12FB9;CYPRO-MINOAN SIGN CM053;Lo;0;L;;;;;N;;;;; +12FBA;CYPRO-MINOAN SIGN CM054;Lo;0;L;;;;;N;;;;; +12FBB;CYPRO-MINOAN SIGN CM055;Lo;0;L;;;;;N;;;;; +12FBC;CYPRO-MINOAN SIGN CM056;Lo;0;L;;;;;N;;;;; +12FBD;CYPRO-MINOAN SIGN CM058;Lo;0;L;;;;;N;;;;; +12FBE;CYPRO-MINOAN SIGN CM059;Lo;0;L;;;;;N;;;;; +12FBF;CYPRO-MINOAN SIGN CM060;Lo;0;L;;;;;N;;;;; +12FC0;CYPRO-MINOAN SIGN CM061;Lo;0;L;;;;;N;;;;; +12FC1;CYPRO-MINOAN SIGN CM062;Lo;0;L;;;;;N;;;;; +12FC2;CYPRO-MINOAN SIGN CM063;Lo;0;L;;;;;N;;;;; +12FC3;CYPRO-MINOAN SIGN CM064;Lo;0;L;;;;;N;;;;; +12FC4;CYPRO-MINOAN SIGN CM066;Lo;0;L;;;;;N;;;;; +12FC5;CYPRO-MINOAN SIGN CM067;Lo;0;L;;;;;N;;;;; +12FC6;CYPRO-MINOAN SIGN CM068;Lo;0;L;;;;;N;;;;; +12FC7;CYPRO-MINOAN SIGN CM069;Lo;0;L;;;;;N;;;;; +12FC8;CYPRO-MINOAN SIGN CM070;Lo;0;L;;;;;N;;;;; +12FC9;CYPRO-MINOAN SIGN CM071;Lo;0;L;;;;;N;;;;; +12FCA;CYPRO-MINOAN SIGN CM072;Lo;0;L;;;;;N;;;;; +12FCB;CYPRO-MINOAN SIGN CM073;Lo;0;L;;;;;N;;;;; +12FCC;CYPRO-MINOAN SIGN CM074;Lo;0;L;;;;;N;;;;; +12FCD;CYPRO-MINOAN SIGN CM075;Lo;0;L;;;;;N;;;;; +12FCE;CYPRO-MINOAN SIGN CM075B;Lo;0;L;;;;;N;;;;; +12FCF;CYPRO-MINOAN SIGN CM076;Lo;0;L;;;;;N;;;;; +12FD0;CYPRO-MINOAN SIGN CM078;Lo;0;L;;;;;N;;;;; +12FD1;CYPRO-MINOAN SIGN CM079;Lo;0;L;;;;;N;;;;; +12FD2;CYPRO-MINOAN SIGN CM080;Lo;0;L;;;;;N;;;;; +12FD3;CYPRO-MINOAN SIGN CM081;Lo;0;L;;;;;N;;;;; +12FD4;CYPRO-MINOAN SIGN CM082;Lo;0;L;;;;;N;;;;; +12FD5;CYPRO-MINOAN SIGN CM083;Lo;0;L;;;;;N;;;;; +12FD6;CYPRO-MINOAN SIGN CM084;Lo;0;L;;;;;N;;;;; +12FD7;CYPRO-MINOAN SIGN CM085;Lo;0;L;;;;;N;;;;; +12FD8;CYPRO-MINOAN SIGN CM086;Lo;0;L;;;;;N;;;;; +12FD9;CYPRO-MINOAN SIGN CM087;Lo;0;L;;;;;N;;;;; +12FDA;CYPRO-MINOAN SIGN CM088;Lo;0;L;;;;;N;;;;; +12FDB;CYPRO-MINOAN SIGN CM089;Lo;0;L;;;;;N;;;;; +12FDC;CYPRO-MINOAN SIGN CM090;Lo;0;L;;;;;N;;;;; +12FDD;CYPRO-MINOAN SIGN CM091;Lo;0;L;;;;;N;;;;; +12FDE;CYPRO-MINOAN SIGN CM092;Lo;0;L;;;;;N;;;;; +12FDF;CYPRO-MINOAN SIGN CM094;Lo;0;L;;;;;N;;;;; +12FE0;CYPRO-MINOAN SIGN CM095;Lo;0;L;;;;;N;;;;; +12FE1;CYPRO-MINOAN SIGN CM096;Lo;0;L;;;;;N;;;;; +12FE2;CYPRO-MINOAN SIGN CM097;Lo;0;L;;;;;N;;;;; +12FE3;CYPRO-MINOAN SIGN CM098;Lo;0;L;;;;;N;;;;; +12FE4;CYPRO-MINOAN SIGN CM099;Lo;0;L;;;;;N;;;;; +12FE5;CYPRO-MINOAN SIGN CM100;Lo;0;L;;;;;N;;;;; +12FE6;CYPRO-MINOAN SIGN CM101;Lo;0;L;;;;;N;;;;; +12FE7;CYPRO-MINOAN SIGN CM102;Lo;0;L;;;;;N;;;;; +12FE8;CYPRO-MINOAN SIGN CM103;Lo;0;L;;;;;N;;;;; +12FE9;CYPRO-MINOAN SIGN CM104;Lo;0;L;;;;;N;;;;; +12FEA;CYPRO-MINOAN SIGN CM105;Lo;0;L;;;;;N;;;;; +12FEB;CYPRO-MINOAN SIGN CM107;Lo;0;L;;;;;N;;;;; +12FEC;CYPRO-MINOAN SIGN CM108;Lo;0;L;;;;;N;;;;; +12FED;CYPRO-MINOAN SIGN CM109;Lo;0;L;;;;;N;;;;; +12FEE;CYPRO-MINOAN SIGN CM110;Lo;0;L;;;;;N;;;;; +12FEF;CYPRO-MINOAN SIGN CM112;Lo;0;L;;;;;N;;;;; +12FF0;CYPRO-MINOAN SIGN CM114;Lo;0;L;;;;;N;;;;; +12FF1;CYPRO-MINOAN SIGN CM301;Po;0;L;;;;;N;;;;; +12FF2;CYPRO-MINOAN SIGN CM302;Po;0;L;;;;;N;;;;; +13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; +13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; +13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; +13003;EGYPTIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; +13004;EGYPTIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; +13005;EGYPTIAN HIEROGLYPH A005A;Lo;0;L;;;;;N;;;;; +13006;EGYPTIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; +13007;EGYPTIAN HIEROGLYPH A006A;Lo;0;L;;;;;N;;;;; +13008;EGYPTIAN HIEROGLYPH A006B;Lo;0;L;;;;;N;;;;; +13009;EGYPTIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; +1300A;EGYPTIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; +1300B;EGYPTIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; +1300C;EGYPTIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; +1300D;EGYPTIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; +1300E;EGYPTIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; +1300F;EGYPTIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; +13010;EGYPTIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; +13011;EGYPTIAN HIEROGLYPH A014A;Lo;0;L;;;;;N;;;;; +13012;EGYPTIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; +13013;EGYPTIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; +13014;EGYPTIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; +13015;EGYPTIAN HIEROGLYPH A017A;Lo;0;L;;;;;N;;;;; +13016;EGYPTIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; +13017;EGYPTIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; +13018;EGYPTIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; +13019;EGYPTIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; +1301A;EGYPTIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; +1301B;EGYPTIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; +1301C;EGYPTIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; +1301D;EGYPTIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; +1301E;EGYPTIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; +1301F;EGYPTIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; +13020;EGYPTIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; +13021;EGYPTIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; +13022;EGYPTIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; +13023;EGYPTIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; +13024;EGYPTIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; +13025;EGYPTIAN HIEROGLYPH A032A;Lo;0;L;;;;;N;;;;; +13026;EGYPTIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; +13027;EGYPTIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; +13028;EGYPTIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; +13029;EGYPTIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; +1302A;EGYPTIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; +1302B;EGYPTIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; +1302C;EGYPTIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; +1302D;EGYPTIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; +1302E;EGYPTIAN HIEROGLYPH A040A;Lo;0;L;;;;;N;;;;; +1302F;EGYPTIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; +13030;EGYPTIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; +13031;EGYPTIAN HIEROGLYPH A042A;Lo;0;L;;;;;N;;;;; +13032;EGYPTIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; +13033;EGYPTIAN HIEROGLYPH A043A;Lo;0;L;;;;;N;;;;; +13034;EGYPTIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; +13035;EGYPTIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; +13036;EGYPTIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; +13037;EGYPTIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; +13038;EGYPTIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; +13039;EGYPTIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; +1303A;EGYPTIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; +1303B;EGYPTIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; +1303C;EGYPTIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; +1303D;EGYPTIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; +1303E;EGYPTIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; +1303F;EGYPTIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; +13040;EGYPTIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; +13041;EGYPTIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; +13042;EGYPTIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; +13043;EGYPTIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; +13044;EGYPTIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; +13045;EGYPTIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; +13046;EGYPTIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; +13047;EGYPTIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; +13048;EGYPTIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; +13049;EGYPTIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; +1304A;EGYPTIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; +1304B;EGYPTIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; +1304C;EGYPTIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; +1304D;EGYPTIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; +1304E;EGYPTIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; +1304F;EGYPTIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; +13050;EGYPTIAN HIEROGLYPH B001;Lo;0;L;;;;;N;;;;; +13051;EGYPTIAN HIEROGLYPH B002;Lo;0;L;;;;;N;;;;; +13052;EGYPTIAN HIEROGLYPH B003;Lo;0;L;;;;;N;;;;; +13053;EGYPTIAN HIEROGLYPH B004;Lo;0;L;;;;;N;;;;; +13054;EGYPTIAN HIEROGLYPH B005;Lo;0;L;;;;;N;;;;; +13055;EGYPTIAN HIEROGLYPH B005A;Lo;0;L;;;;;N;;;;; +13056;EGYPTIAN HIEROGLYPH B006;Lo;0;L;;;;;N;;;;; +13057;EGYPTIAN HIEROGLYPH B007;Lo;0;L;;;;;N;;;;; +13058;EGYPTIAN HIEROGLYPH B008;Lo;0;L;;;;;N;;;;; +13059;EGYPTIAN HIEROGLYPH B009;Lo;0;L;;;;;N;;;;; +1305A;EGYPTIAN HIEROGLYPH C001;Lo;0;L;;;;;N;;;;; +1305B;EGYPTIAN HIEROGLYPH C002;Lo;0;L;;;;;N;;;;; +1305C;EGYPTIAN HIEROGLYPH C002A;Lo;0;L;;;;;N;;;;; +1305D;EGYPTIAN HIEROGLYPH C002B;Lo;0;L;;;;;N;;;;; +1305E;EGYPTIAN HIEROGLYPH C002C;Lo;0;L;;;;;N;;;;; +1305F;EGYPTIAN HIEROGLYPH C003;Lo;0;L;;;;;N;;;;; +13060;EGYPTIAN HIEROGLYPH C004;Lo;0;L;;;;;N;;;;; +13061;EGYPTIAN HIEROGLYPH C005;Lo;0;L;;;;;N;;;;; +13062;EGYPTIAN HIEROGLYPH C006;Lo;0;L;;;;;N;;;;; +13063;EGYPTIAN HIEROGLYPH C007;Lo;0;L;;;;;N;;;;; +13064;EGYPTIAN HIEROGLYPH C008;Lo;0;L;;;;;N;;;;; +13065;EGYPTIAN HIEROGLYPH C009;Lo;0;L;;;;;N;;;;; +13066;EGYPTIAN HIEROGLYPH C010;Lo;0;L;;;;;N;;;;; +13067;EGYPTIAN HIEROGLYPH C010A;Lo;0;L;;;;;N;;;;; +13068;EGYPTIAN HIEROGLYPH C011;Lo;0;L;;;;;N;;;;; +13069;EGYPTIAN HIEROGLYPH C012;Lo;0;L;;;;;N;;;;; +1306A;EGYPTIAN HIEROGLYPH C013;Lo;0;L;;;;;N;;;;; +1306B;EGYPTIAN HIEROGLYPH C014;Lo;0;L;;;;;N;;;;; +1306C;EGYPTIAN HIEROGLYPH C015;Lo;0;L;;;;;N;;;;; +1306D;EGYPTIAN HIEROGLYPH C016;Lo;0;L;;;;;N;;;;; +1306E;EGYPTIAN HIEROGLYPH C017;Lo;0;L;;;;;N;;;;; +1306F;EGYPTIAN HIEROGLYPH C018;Lo;0;L;;;;;N;;;;; +13070;EGYPTIAN HIEROGLYPH C019;Lo;0;L;;;;;N;;;;; +13071;EGYPTIAN HIEROGLYPH C020;Lo;0;L;;;;;N;;;;; +13072;EGYPTIAN HIEROGLYPH C021;Lo;0;L;;;;;N;;;;; +13073;EGYPTIAN HIEROGLYPH C022;Lo;0;L;;;;;N;;;;; +13074;EGYPTIAN HIEROGLYPH C023;Lo;0;L;;;;;N;;;;; +13075;EGYPTIAN HIEROGLYPH C024;Lo;0;L;;;;;N;;;;; +13076;EGYPTIAN HIEROGLYPH D001;Lo;0;L;;;;;N;;;;; +13077;EGYPTIAN HIEROGLYPH D002;Lo;0;L;;;;;N;;;;; +13078;EGYPTIAN HIEROGLYPH D003;Lo;0;L;;;;;N;;;;; +13079;EGYPTIAN HIEROGLYPH D004;Lo;0;L;;;;;N;;;;; +1307A;EGYPTIAN HIEROGLYPH D005;Lo;0;L;;;;;N;;;;; +1307B;EGYPTIAN HIEROGLYPH D006;Lo;0;L;;;;;N;;;;; +1307C;EGYPTIAN HIEROGLYPH D007;Lo;0;L;;;;;N;;;;; +1307D;EGYPTIAN HIEROGLYPH D008;Lo;0;L;;;;;N;;;;; +1307E;EGYPTIAN HIEROGLYPH D008A;Lo;0;L;;;;;N;;;;; +1307F;EGYPTIAN HIEROGLYPH D009;Lo;0;L;;;;;N;;;;; +13080;EGYPTIAN HIEROGLYPH D010;Lo;0;L;;;;;N;;;;; +13081;EGYPTIAN HIEROGLYPH D011;Lo;0;L;;;;;N;;;;; +13082;EGYPTIAN HIEROGLYPH D012;Lo;0;L;;;;;N;;;;; +13083;EGYPTIAN HIEROGLYPH D013;Lo;0;L;;;;;N;;;;; +13084;EGYPTIAN HIEROGLYPH D014;Lo;0;L;;;;;N;;;;; +13085;EGYPTIAN HIEROGLYPH D015;Lo;0;L;;;;;N;;;;; +13086;EGYPTIAN HIEROGLYPH D016;Lo;0;L;;;;;N;;;;; +13087;EGYPTIAN HIEROGLYPH D017;Lo;0;L;;;;;N;;;;; +13088;EGYPTIAN HIEROGLYPH D018;Lo;0;L;;;;;N;;;;; +13089;EGYPTIAN HIEROGLYPH D019;Lo;0;L;;;;;N;;;;; +1308A;EGYPTIAN HIEROGLYPH D020;Lo;0;L;;;;;N;;;;; +1308B;EGYPTIAN HIEROGLYPH D021;Lo;0;L;;;;;N;;;;; +1308C;EGYPTIAN HIEROGLYPH D022;Lo;0;L;;;;;N;;;;; +1308D;EGYPTIAN HIEROGLYPH D023;Lo;0;L;;;;;N;;;;; +1308E;EGYPTIAN HIEROGLYPH D024;Lo;0;L;;;;;N;;;;; +1308F;EGYPTIAN HIEROGLYPH D025;Lo;0;L;;;;;N;;;;; +13090;EGYPTIAN HIEROGLYPH D026;Lo;0;L;;;;;N;;;;; +13091;EGYPTIAN HIEROGLYPH D027;Lo;0;L;;;;;N;;;;; +13092;EGYPTIAN HIEROGLYPH D027A;Lo;0;L;;;;;N;;;;; +13093;EGYPTIAN HIEROGLYPH D028;Lo;0;L;;;;;N;;;;; +13094;EGYPTIAN HIEROGLYPH D029;Lo;0;L;;;;;N;;;;; +13095;EGYPTIAN HIEROGLYPH D030;Lo;0;L;;;;;N;;;;; +13096;EGYPTIAN HIEROGLYPH D031;Lo;0;L;;;;;N;;;;; +13097;EGYPTIAN HIEROGLYPH D031A;Lo;0;L;;;;;N;;;;; +13098;EGYPTIAN HIEROGLYPH D032;Lo;0;L;;;;;N;;;;; +13099;EGYPTIAN HIEROGLYPH D033;Lo;0;L;;;;;N;;;;; +1309A;EGYPTIAN HIEROGLYPH D034;Lo;0;L;;;;;N;;;;; +1309B;EGYPTIAN HIEROGLYPH D034A;Lo;0;L;;;;;N;;;;; +1309C;EGYPTIAN HIEROGLYPH D035;Lo;0;L;;;;;N;;;;; +1309D;EGYPTIAN HIEROGLYPH D036;Lo;0;L;;;;;N;;;;; +1309E;EGYPTIAN HIEROGLYPH D037;Lo;0;L;;;;;N;;;;; +1309F;EGYPTIAN HIEROGLYPH D038;Lo;0;L;;;;;N;;;;; +130A0;EGYPTIAN HIEROGLYPH D039;Lo;0;L;;;;;N;;;;; +130A1;EGYPTIAN HIEROGLYPH D040;Lo;0;L;;;;;N;;;;; +130A2;EGYPTIAN HIEROGLYPH D041;Lo;0;L;;;;;N;;;;; +130A3;EGYPTIAN HIEROGLYPH D042;Lo;0;L;;;;;N;;;;; +130A4;EGYPTIAN HIEROGLYPH D043;Lo;0;L;;;;;N;;;;; +130A5;EGYPTIAN HIEROGLYPH D044;Lo;0;L;;;;;N;;;;; +130A6;EGYPTIAN HIEROGLYPH D045;Lo;0;L;;;;;N;;;;; +130A7;EGYPTIAN HIEROGLYPH D046;Lo;0;L;;;;;N;;;;; +130A8;EGYPTIAN HIEROGLYPH D046A;Lo;0;L;;;;;N;;;;; +130A9;EGYPTIAN HIEROGLYPH D047;Lo;0;L;;;;;N;;;;; +130AA;EGYPTIAN HIEROGLYPH D048;Lo;0;L;;;;;N;;;;; +130AB;EGYPTIAN HIEROGLYPH D048A;Lo;0;L;;;;;N;;;;; +130AC;EGYPTIAN HIEROGLYPH D049;Lo;0;L;;;;;N;;;;; +130AD;EGYPTIAN HIEROGLYPH D050;Lo;0;L;;;;;N;;;;; +130AE;EGYPTIAN HIEROGLYPH D050A;Lo;0;L;;;;;N;;;;; +130AF;EGYPTIAN HIEROGLYPH D050B;Lo;0;L;;;;;N;;;;; +130B0;EGYPTIAN HIEROGLYPH D050C;Lo;0;L;;;;;N;;;;; +130B1;EGYPTIAN HIEROGLYPH D050D;Lo;0;L;;;;;N;;;;; +130B2;EGYPTIAN HIEROGLYPH D050E;Lo;0;L;;;;;N;;;;; +130B3;EGYPTIAN HIEROGLYPH D050F;Lo;0;L;;;;;N;;;;; +130B4;EGYPTIAN HIEROGLYPH D050G;Lo;0;L;;;;;N;;;;; +130B5;EGYPTIAN HIEROGLYPH D050H;Lo;0;L;;;;;N;;;;; +130B6;EGYPTIAN HIEROGLYPH D050I;Lo;0;L;;;;;N;;;;; +130B7;EGYPTIAN HIEROGLYPH D051;Lo;0;L;;;;;N;;;;; +130B8;EGYPTIAN HIEROGLYPH D052;Lo;0;L;;;;;N;;;;; +130B9;EGYPTIAN HIEROGLYPH D052A;Lo;0;L;;;;;N;;;;; +130BA;EGYPTIAN HIEROGLYPH D053;Lo;0;L;;;;;N;;;;; +130BB;EGYPTIAN HIEROGLYPH D054;Lo;0;L;;;;;N;;;;; +130BC;EGYPTIAN HIEROGLYPH D054A;Lo;0;L;;;;;N;;;;; +130BD;EGYPTIAN HIEROGLYPH D055;Lo;0;L;;;;;N;;;;; +130BE;EGYPTIAN HIEROGLYPH D056;Lo;0;L;;;;;N;;;;; +130BF;EGYPTIAN HIEROGLYPH D057;Lo;0;L;;;;;N;;;;; +130C0;EGYPTIAN HIEROGLYPH D058;Lo;0;L;;;;;N;;;;; +130C1;EGYPTIAN HIEROGLYPH D059;Lo;0;L;;;;;N;;;;; +130C2;EGYPTIAN HIEROGLYPH D060;Lo;0;L;;;;;N;;;;; +130C3;EGYPTIAN HIEROGLYPH D061;Lo;0;L;;;;;N;;;;; +130C4;EGYPTIAN HIEROGLYPH D062;Lo;0;L;;;;;N;;;;; +130C5;EGYPTIAN HIEROGLYPH D063;Lo;0;L;;;;;N;;;;; +130C6;EGYPTIAN HIEROGLYPH D064;Lo;0;L;;;;;N;;;;; +130C7;EGYPTIAN HIEROGLYPH D065;Lo;0;L;;;;;N;;;;; +130C8;EGYPTIAN HIEROGLYPH D066;Lo;0;L;;;;;N;;;;; +130C9;EGYPTIAN HIEROGLYPH D067;Lo;0;L;;;;;N;;;;; +130CA;EGYPTIAN HIEROGLYPH D067A;Lo;0;L;;;;;N;;;;; +130CB;EGYPTIAN HIEROGLYPH D067B;Lo;0;L;;;;;N;;;;; +130CC;EGYPTIAN HIEROGLYPH D067C;Lo;0;L;;;;;N;;;;; +130CD;EGYPTIAN HIEROGLYPH D067D;Lo;0;L;;;;;N;;;;; +130CE;EGYPTIAN HIEROGLYPH D067E;Lo;0;L;;;;;N;;;;; +130CF;EGYPTIAN HIEROGLYPH D067F;Lo;0;L;;;;;N;;;;; +130D0;EGYPTIAN HIEROGLYPH D067G;Lo;0;L;;;;;N;;;;; +130D1;EGYPTIAN HIEROGLYPH D067H;Lo;0;L;;;;;N;;;;; +130D2;EGYPTIAN HIEROGLYPH E001;Lo;0;L;;;;;N;;;;; +130D3;EGYPTIAN HIEROGLYPH E002;Lo;0;L;;;;;N;;;;; +130D4;EGYPTIAN HIEROGLYPH E003;Lo;0;L;;;;;N;;;;; +130D5;EGYPTIAN HIEROGLYPH E004;Lo;0;L;;;;;N;;;;; +130D6;EGYPTIAN HIEROGLYPH E005;Lo;0;L;;;;;N;;;;; +130D7;EGYPTIAN HIEROGLYPH E006;Lo;0;L;;;;;N;;;;; +130D8;EGYPTIAN HIEROGLYPH E007;Lo;0;L;;;;;N;;;;; +130D9;EGYPTIAN HIEROGLYPH E008;Lo;0;L;;;;;N;;;;; +130DA;EGYPTIAN HIEROGLYPH E008A;Lo;0;L;;;;;N;;;;; +130DB;EGYPTIAN HIEROGLYPH E009;Lo;0;L;;;;;N;;;;; +130DC;EGYPTIAN HIEROGLYPH E009A;Lo;0;L;;;;;N;;;;; +130DD;EGYPTIAN HIEROGLYPH E010;Lo;0;L;;;;;N;;;;; +130DE;EGYPTIAN HIEROGLYPH E011;Lo;0;L;;;;;N;;;;; +130DF;EGYPTIAN HIEROGLYPH E012;Lo;0;L;;;;;N;;;;; +130E0;EGYPTIAN HIEROGLYPH E013;Lo;0;L;;;;;N;;;;; +130E1;EGYPTIAN HIEROGLYPH E014;Lo;0;L;;;;;N;;;;; +130E2;EGYPTIAN HIEROGLYPH E015;Lo;0;L;;;;;N;;;;; +130E3;EGYPTIAN HIEROGLYPH E016;Lo;0;L;;;;;N;;;;; +130E4;EGYPTIAN HIEROGLYPH E016A;Lo;0;L;;;;;N;;;;; +130E5;EGYPTIAN HIEROGLYPH E017;Lo;0;L;;;;;N;;;;; +130E6;EGYPTIAN HIEROGLYPH E017A;Lo;0;L;;;;;N;;;;; +130E7;EGYPTIAN HIEROGLYPH E018;Lo;0;L;;;;;N;;;;; +130E8;EGYPTIAN HIEROGLYPH E019;Lo;0;L;;;;;N;;;;; +130E9;EGYPTIAN HIEROGLYPH E020;Lo;0;L;;;;;N;;;;; +130EA;EGYPTIAN HIEROGLYPH E020A;Lo;0;L;;;;;N;;;;; +130EB;EGYPTIAN HIEROGLYPH E021;Lo;0;L;;;;;N;;;;; +130EC;EGYPTIAN HIEROGLYPH E022;Lo;0;L;;;;;N;;;;; +130ED;EGYPTIAN HIEROGLYPH E023;Lo;0;L;;;;;N;;;;; +130EE;EGYPTIAN HIEROGLYPH E024;Lo;0;L;;;;;N;;;;; +130EF;EGYPTIAN HIEROGLYPH E025;Lo;0;L;;;;;N;;;;; +130F0;EGYPTIAN HIEROGLYPH E026;Lo;0;L;;;;;N;;;;; +130F1;EGYPTIAN HIEROGLYPH E027;Lo;0;L;;;;;N;;;;; +130F2;EGYPTIAN HIEROGLYPH E028;Lo;0;L;;;;;N;;;;; +130F3;EGYPTIAN HIEROGLYPH E028A;Lo;0;L;;;;;N;;;;; +130F4;EGYPTIAN HIEROGLYPH E029;Lo;0;L;;;;;N;;;;; +130F5;EGYPTIAN HIEROGLYPH E030;Lo;0;L;;;;;N;;;;; +130F6;EGYPTIAN HIEROGLYPH E031;Lo;0;L;;;;;N;;;;; +130F7;EGYPTIAN HIEROGLYPH E032;Lo;0;L;;;;;N;;;;; +130F8;EGYPTIAN HIEROGLYPH E033;Lo;0;L;;;;;N;;;;; +130F9;EGYPTIAN HIEROGLYPH E034;Lo;0;L;;;;;N;;;;; +130FA;EGYPTIAN HIEROGLYPH E034A;Lo;0;L;;;;;N;;;;; +130FB;EGYPTIAN HIEROGLYPH E036;Lo;0;L;;;;;N;;;;; +130FC;EGYPTIAN HIEROGLYPH E037;Lo;0;L;;;;;N;;;;; +130FD;EGYPTIAN HIEROGLYPH E038;Lo;0;L;;;;;N;;;;; +130FE;EGYPTIAN HIEROGLYPH F001;Lo;0;L;;;;;N;;;;; +130FF;EGYPTIAN HIEROGLYPH F001A;Lo;0;L;;;;;N;;;;; +13100;EGYPTIAN HIEROGLYPH F002;Lo;0;L;;;;;N;;;;; +13101;EGYPTIAN HIEROGLYPH F003;Lo;0;L;;;;;N;;;;; +13102;EGYPTIAN HIEROGLYPH F004;Lo;0;L;;;;;N;;;;; +13103;EGYPTIAN HIEROGLYPH F005;Lo;0;L;;;;;N;;;;; +13104;EGYPTIAN HIEROGLYPH F006;Lo;0;L;;;;;N;;;;; +13105;EGYPTIAN HIEROGLYPH F007;Lo;0;L;;;;;N;;;;; +13106;EGYPTIAN HIEROGLYPH F008;Lo;0;L;;;;;N;;;;; +13107;EGYPTIAN HIEROGLYPH F009;Lo;0;L;;;;;N;;;;; +13108;EGYPTIAN HIEROGLYPH F010;Lo;0;L;;;;;N;;;;; +13109;EGYPTIAN HIEROGLYPH F011;Lo;0;L;;;;;N;;;;; +1310A;EGYPTIAN HIEROGLYPH F012;Lo;0;L;;;;;N;;;;; +1310B;EGYPTIAN HIEROGLYPH F013;Lo;0;L;;;;;N;;;;; +1310C;EGYPTIAN HIEROGLYPH F013A;Lo;0;L;;;;;N;;;;; +1310D;EGYPTIAN HIEROGLYPH F014;Lo;0;L;;;;;N;;;;; +1310E;EGYPTIAN HIEROGLYPH F015;Lo;0;L;;;;;N;;;;; +1310F;EGYPTIAN HIEROGLYPH F016;Lo;0;L;;;;;N;;;;; +13110;EGYPTIAN HIEROGLYPH F017;Lo;0;L;;;;;N;;;;; +13111;EGYPTIAN HIEROGLYPH F018;Lo;0;L;;;;;N;;;;; +13112;EGYPTIAN HIEROGLYPH F019;Lo;0;L;;;;;N;;;;; +13113;EGYPTIAN HIEROGLYPH F020;Lo;0;L;;;;;N;;;;; +13114;EGYPTIAN HIEROGLYPH F021;Lo;0;L;;;;;N;;;;; +13115;EGYPTIAN HIEROGLYPH F021A;Lo;0;L;;;;;N;;;;; +13116;EGYPTIAN HIEROGLYPH F022;Lo;0;L;;;;;N;;;;; +13117;EGYPTIAN HIEROGLYPH F023;Lo;0;L;;;;;N;;;;; +13118;EGYPTIAN HIEROGLYPH F024;Lo;0;L;;;;;N;;;;; +13119;EGYPTIAN HIEROGLYPH F025;Lo;0;L;;;;;N;;;;; +1311A;EGYPTIAN HIEROGLYPH F026;Lo;0;L;;;;;N;;;;; +1311B;EGYPTIAN HIEROGLYPH F027;Lo;0;L;;;;;N;;;;; +1311C;EGYPTIAN HIEROGLYPH F028;Lo;0;L;;;;;N;;;;; +1311D;EGYPTIAN HIEROGLYPH F029;Lo;0;L;;;;;N;;;;; +1311E;EGYPTIAN HIEROGLYPH F030;Lo;0;L;;;;;N;;;;; +1311F;EGYPTIAN HIEROGLYPH F031;Lo;0;L;;;;;N;;;;; +13120;EGYPTIAN HIEROGLYPH F031A;Lo;0;L;;;;;N;;;;; +13121;EGYPTIAN HIEROGLYPH F032;Lo;0;L;;;;;N;;;;; +13122;EGYPTIAN HIEROGLYPH F033;Lo;0;L;;;;;N;;;;; +13123;EGYPTIAN HIEROGLYPH F034;Lo;0;L;;;;;N;;;;; +13124;EGYPTIAN HIEROGLYPH F035;Lo;0;L;;;;;N;;;;; +13125;EGYPTIAN HIEROGLYPH F036;Lo;0;L;;;;;N;;;;; +13126;EGYPTIAN HIEROGLYPH F037;Lo;0;L;;;;;N;;;;; +13127;EGYPTIAN HIEROGLYPH F037A;Lo;0;L;;;;;N;;;;; +13128;EGYPTIAN HIEROGLYPH F038;Lo;0;L;;;;;N;;;;; +13129;EGYPTIAN HIEROGLYPH F038A;Lo;0;L;;;;;N;;;;; +1312A;EGYPTIAN HIEROGLYPH F039;Lo;0;L;;;;;N;;;;; +1312B;EGYPTIAN HIEROGLYPH F040;Lo;0;L;;;;;N;;;;; +1312C;EGYPTIAN HIEROGLYPH F041;Lo;0;L;;;;;N;;;;; +1312D;EGYPTIAN HIEROGLYPH F042;Lo;0;L;;;;;N;;;;; +1312E;EGYPTIAN HIEROGLYPH F043;Lo;0;L;;;;;N;;;;; +1312F;EGYPTIAN HIEROGLYPH F044;Lo;0;L;;;;;N;;;;; +13130;EGYPTIAN HIEROGLYPH F045;Lo;0;L;;;;;N;;;;; +13131;EGYPTIAN HIEROGLYPH F045A;Lo;0;L;;;;;N;;;;; +13132;EGYPTIAN HIEROGLYPH F046;Lo;0;L;;;;;N;;;;; +13133;EGYPTIAN HIEROGLYPH F046A;Lo;0;L;;;;;N;;;;; +13134;EGYPTIAN HIEROGLYPH F047;Lo;0;L;;;;;N;;;;; +13135;EGYPTIAN HIEROGLYPH F047A;Lo;0;L;;;;;N;;;;; +13136;EGYPTIAN HIEROGLYPH F048;Lo;0;L;;;;;N;;;;; +13137;EGYPTIAN HIEROGLYPH F049;Lo;0;L;;;;;N;;;;; +13138;EGYPTIAN HIEROGLYPH F050;Lo;0;L;;;;;N;;;;; +13139;EGYPTIAN HIEROGLYPH F051;Lo;0;L;;;;;N;;;;; +1313A;EGYPTIAN HIEROGLYPH F051A;Lo;0;L;;;;;N;;;;; +1313B;EGYPTIAN HIEROGLYPH F051B;Lo;0;L;;;;;N;;;;; +1313C;EGYPTIAN HIEROGLYPH F051C;Lo;0;L;;;;;N;;;;; +1313D;EGYPTIAN HIEROGLYPH F052;Lo;0;L;;;;;N;;;;; +1313E;EGYPTIAN HIEROGLYPH F053;Lo;0;L;;;;;N;;;;; +1313F;EGYPTIAN HIEROGLYPH G001;Lo;0;L;;;;;N;;;;; +13140;EGYPTIAN HIEROGLYPH G002;Lo;0;L;;;;;N;;;;; +13141;EGYPTIAN HIEROGLYPH G003;Lo;0;L;;;;;N;;;;; +13142;EGYPTIAN HIEROGLYPH G004;Lo;0;L;;;;;N;;;;; +13143;EGYPTIAN HIEROGLYPH G005;Lo;0;L;;;;;N;;;;; +13144;EGYPTIAN HIEROGLYPH G006;Lo;0;L;;;;;N;;;;; +13145;EGYPTIAN HIEROGLYPH G006A;Lo;0;L;;;;;N;;;;; +13146;EGYPTIAN HIEROGLYPH G007;Lo;0;L;;;;;N;;;;; +13147;EGYPTIAN HIEROGLYPH G007A;Lo;0;L;;;;;N;;;;; +13148;EGYPTIAN HIEROGLYPH G007B;Lo;0;L;;;;;N;;;;; +13149;EGYPTIAN HIEROGLYPH G008;Lo;0;L;;;;;N;;;;; +1314A;EGYPTIAN HIEROGLYPH G009;Lo;0;L;;;;;N;;;;; +1314B;EGYPTIAN HIEROGLYPH G010;Lo;0;L;;;;;N;;;;; +1314C;EGYPTIAN HIEROGLYPH G011;Lo;0;L;;;;;N;;;;; +1314D;EGYPTIAN HIEROGLYPH G011A;Lo;0;L;;;;;N;;;;; +1314E;EGYPTIAN HIEROGLYPH G012;Lo;0;L;;;;;N;;;;; +1314F;EGYPTIAN HIEROGLYPH G013;Lo;0;L;;;;;N;;;;; +13150;EGYPTIAN HIEROGLYPH G014;Lo;0;L;;;;;N;;;;; +13151;EGYPTIAN HIEROGLYPH G015;Lo;0;L;;;;;N;;;;; +13152;EGYPTIAN HIEROGLYPH G016;Lo;0;L;;;;;N;;;;; +13153;EGYPTIAN HIEROGLYPH G017;Lo;0;L;;;;;N;;;;; +13154;EGYPTIAN HIEROGLYPH G018;Lo;0;L;;;;;N;;;;; +13155;EGYPTIAN HIEROGLYPH G019;Lo;0;L;;;;;N;;;;; +13156;EGYPTIAN HIEROGLYPH G020;Lo;0;L;;;;;N;;;;; +13157;EGYPTIAN HIEROGLYPH G020A;Lo;0;L;;;;;N;;;;; +13158;EGYPTIAN HIEROGLYPH G021;Lo;0;L;;;;;N;;;;; +13159;EGYPTIAN HIEROGLYPH G022;Lo;0;L;;;;;N;;;;; +1315A;EGYPTIAN HIEROGLYPH G023;Lo;0;L;;;;;N;;;;; +1315B;EGYPTIAN HIEROGLYPH G024;Lo;0;L;;;;;N;;;;; +1315C;EGYPTIAN HIEROGLYPH G025;Lo;0;L;;;;;N;;;;; +1315D;EGYPTIAN HIEROGLYPH G026;Lo;0;L;;;;;N;;;;; +1315E;EGYPTIAN HIEROGLYPH G026A;Lo;0;L;;;;;N;;;;; +1315F;EGYPTIAN HIEROGLYPH G027;Lo;0;L;;;;;N;;;;; +13160;EGYPTIAN HIEROGLYPH G028;Lo;0;L;;;;;N;;;;; +13161;EGYPTIAN HIEROGLYPH G029;Lo;0;L;;;;;N;;;;; +13162;EGYPTIAN HIEROGLYPH G030;Lo;0;L;;;;;N;;;;; +13163;EGYPTIAN HIEROGLYPH G031;Lo;0;L;;;;;N;;;;; +13164;EGYPTIAN HIEROGLYPH G032;Lo;0;L;;;;;N;;;;; +13165;EGYPTIAN HIEROGLYPH G033;Lo;0;L;;;;;N;;;;; +13166;EGYPTIAN HIEROGLYPH G034;Lo;0;L;;;;;N;;;;; +13167;EGYPTIAN HIEROGLYPH G035;Lo;0;L;;;;;N;;;;; +13168;EGYPTIAN HIEROGLYPH G036;Lo;0;L;;;;;N;;;;; +13169;EGYPTIAN HIEROGLYPH G036A;Lo;0;L;;;;;N;;;;; +1316A;EGYPTIAN HIEROGLYPH G037;Lo;0;L;;;;;N;;;;; +1316B;EGYPTIAN HIEROGLYPH G037A;Lo;0;L;;;;;N;;;;; +1316C;EGYPTIAN HIEROGLYPH G038;Lo;0;L;;;;;N;;;;; +1316D;EGYPTIAN HIEROGLYPH G039;Lo;0;L;;;;;N;;;;; +1316E;EGYPTIAN HIEROGLYPH G040;Lo;0;L;;;;;N;;;;; +1316F;EGYPTIAN HIEROGLYPH G041;Lo;0;L;;;;;N;;;;; +13170;EGYPTIAN HIEROGLYPH G042;Lo;0;L;;;;;N;;;;; +13171;EGYPTIAN HIEROGLYPH G043;Lo;0;L;;;;;N;;;;; +13172;EGYPTIAN HIEROGLYPH G043A;Lo;0;L;;;;;N;;;;; +13173;EGYPTIAN HIEROGLYPH G044;Lo;0;L;;;;;N;;;;; +13174;EGYPTIAN HIEROGLYPH G045;Lo;0;L;;;;;N;;;;; +13175;EGYPTIAN HIEROGLYPH G045A;Lo;0;L;;;;;N;;;;; +13176;EGYPTIAN HIEROGLYPH G046;Lo;0;L;;;;;N;;;;; +13177;EGYPTIAN HIEROGLYPH G047;Lo;0;L;;;;;N;;;;; +13178;EGYPTIAN HIEROGLYPH G048;Lo;0;L;;;;;N;;;;; +13179;EGYPTIAN HIEROGLYPH G049;Lo;0;L;;;;;N;;;;; +1317A;EGYPTIAN HIEROGLYPH G050;Lo;0;L;;;;;N;;;;; +1317B;EGYPTIAN HIEROGLYPH G051;Lo;0;L;;;;;N;;;;; +1317C;EGYPTIAN HIEROGLYPH G052;Lo;0;L;;;;;N;;;;; +1317D;EGYPTIAN HIEROGLYPH G053;Lo;0;L;;;;;N;;;;; +1317E;EGYPTIAN HIEROGLYPH G054;Lo;0;L;;;;;N;;;;; +1317F;EGYPTIAN HIEROGLYPH H001;Lo;0;L;;;;;N;;;;; +13180;EGYPTIAN HIEROGLYPH H002;Lo;0;L;;;;;N;;;;; +13181;EGYPTIAN HIEROGLYPH H003;Lo;0;L;;;;;N;;;;; +13182;EGYPTIAN HIEROGLYPH H004;Lo;0;L;;;;;N;;;;; +13183;EGYPTIAN HIEROGLYPH H005;Lo;0;L;;;;;N;;;;; +13184;EGYPTIAN HIEROGLYPH H006;Lo;0;L;;;;;N;;;;; +13185;EGYPTIAN HIEROGLYPH H006A;Lo;0;L;;;;;N;;;;; +13186;EGYPTIAN HIEROGLYPH H007;Lo;0;L;;;;;N;;;;; +13187;EGYPTIAN HIEROGLYPH H008;Lo;0;L;;;;;N;;;;; +13188;EGYPTIAN HIEROGLYPH I001;Lo;0;L;;;;;N;;;;; +13189;EGYPTIAN HIEROGLYPH I002;Lo;0;L;;;;;N;;;;; +1318A;EGYPTIAN HIEROGLYPH I003;Lo;0;L;;;;;N;;;;; +1318B;EGYPTIAN HIEROGLYPH I004;Lo;0;L;;;;;N;;;;; +1318C;EGYPTIAN HIEROGLYPH I005;Lo;0;L;;;;;N;;;;; +1318D;EGYPTIAN HIEROGLYPH I005A;Lo;0;L;;;;;N;;;;; +1318E;EGYPTIAN HIEROGLYPH I006;Lo;0;L;;;;;N;;;;; +1318F;EGYPTIAN HIEROGLYPH I007;Lo;0;L;;;;;N;;;;; +13190;EGYPTIAN HIEROGLYPH I008;Lo;0;L;;;;;N;;;;; +13191;EGYPTIAN HIEROGLYPH I009;Lo;0;L;;;;;N;;;;; +13192;EGYPTIAN HIEROGLYPH I009A;Lo;0;L;;;;;N;;;;; +13193;EGYPTIAN HIEROGLYPH I010;Lo;0;L;;;;;N;;;;; +13194;EGYPTIAN HIEROGLYPH I010A;Lo;0;L;;;;;N;;;;; +13195;EGYPTIAN HIEROGLYPH I011;Lo;0;L;;;;;N;;;;; +13196;EGYPTIAN HIEROGLYPH I011A;Lo;0;L;;;;;N;;;;; +13197;EGYPTIAN HIEROGLYPH I012;Lo;0;L;;;;;N;;;;; +13198;EGYPTIAN HIEROGLYPH I013;Lo;0;L;;;;;N;;;;; +13199;EGYPTIAN HIEROGLYPH I014;Lo;0;L;;;;;N;;;;; +1319A;EGYPTIAN HIEROGLYPH I015;Lo;0;L;;;;;N;;;;; +1319B;EGYPTIAN HIEROGLYPH K001;Lo;0;L;;;;;N;;;;; +1319C;EGYPTIAN HIEROGLYPH K002;Lo;0;L;;;;;N;;;;; +1319D;EGYPTIAN HIEROGLYPH K003;Lo;0;L;;;;;N;;;;; +1319E;EGYPTIAN HIEROGLYPH K004;Lo;0;L;;;;;N;;;;; +1319F;EGYPTIAN HIEROGLYPH K005;Lo;0;L;;;;;N;;;;; +131A0;EGYPTIAN HIEROGLYPH K006;Lo;0;L;;;;;N;;;;; +131A1;EGYPTIAN HIEROGLYPH K007;Lo;0;L;;;;;N;;;;; +131A2;EGYPTIAN HIEROGLYPH K008;Lo;0;L;;;;;N;;;;; +131A3;EGYPTIAN HIEROGLYPH L001;Lo;0;L;;;;;N;;;;; +131A4;EGYPTIAN HIEROGLYPH L002;Lo;0;L;;;;;N;;;;; +131A5;EGYPTIAN HIEROGLYPH L002A;Lo;0;L;;;;;N;;;;; +131A6;EGYPTIAN HIEROGLYPH L003;Lo;0;L;;;;;N;;;;; +131A7;EGYPTIAN HIEROGLYPH L004;Lo;0;L;;;;;N;;;;; +131A8;EGYPTIAN HIEROGLYPH L005;Lo;0;L;;;;;N;;;;; +131A9;EGYPTIAN HIEROGLYPH L006;Lo;0;L;;;;;N;;;;; +131AA;EGYPTIAN HIEROGLYPH L006A;Lo;0;L;;;;;N;;;;; +131AB;EGYPTIAN HIEROGLYPH L007;Lo;0;L;;;;;N;;;;; +131AC;EGYPTIAN HIEROGLYPH L008;Lo;0;L;;;;;N;;;;; +131AD;EGYPTIAN HIEROGLYPH M001;Lo;0;L;;;;;N;;;;; +131AE;EGYPTIAN HIEROGLYPH M001A;Lo;0;L;;;;;N;;;;; +131AF;EGYPTIAN HIEROGLYPH M001B;Lo;0;L;;;;;N;;;;; +131B0;EGYPTIAN HIEROGLYPH M002;Lo;0;L;;;;;N;;;;; +131B1;EGYPTIAN HIEROGLYPH M003;Lo;0;L;;;;;N;;;;; +131B2;EGYPTIAN HIEROGLYPH M003A;Lo;0;L;;;;;N;;;;; +131B3;EGYPTIAN HIEROGLYPH M004;Lo;0;L;;;;;N;;;;; +131B4;EGYPTIAN HIEROGLYPH M005;Lo;0;L;;;;;N;;;;; +131B5;EGYPTIAN HIEROGLYPH M006;Lo;0;L;;;;;N;;;;; +131B6;EGYPTIAN HIEROGLYPH M007;Lo;0;L;;;;;N;;;;; +131B7;EGYPTIAN HIEROGLYPH M008;Lo;0;L;;;;;N;;;;; +131B8;EGYPTIAN HIEROGLYPH M009;Lo;0;L;;;;;N;;;;; +131B9;EGYPTIAN HIEROGLYPH M010;Lo;0;L;;;;;N;;;;; +131BA;EGYPTIAN HIEROGLYPH M010A;Lo;0;L;;;;;N;;;;; +131BB;EGYPTIAN HIEROGLYPH M011;Lo;0;L;;;;;N;;;;; +131BC;EGYPTIAN HIEROGLYPH M012;Lo;0;L;;;;;N;;;;; +131BD;EGYPTIAN HIEROGLYPH M012A;Lo;0;L;;;;;N;;;;; +131BE;EGYPTIAN HIEROGLYPH M012B;Lo;0;L;;;;;N;;;;; +131BF;EGYPTIAN HIEROGLYPH M012C;Lo;0;L;;;;;N;;;;; +131C0;EGYPTIAN HIEROGLYPH M012D;Lo;0;L;;;;;N;;;;; +131C1;EGYPTIAN HIEROGLYPH M012E;Lo;0;L;;;;;N;;;;; +131C2;EGYPTIAN HIEROGLYPH M012F;Lo;0;L;;;;;N;;;;; +131C3;EGYPTIAN HIEROGLYPH M012G;Lo;0;L;;;;;N;;;;; +131C4;EGYPTIAN HIEROGLYPH M012H;Lo;0;L;;;;;N;;;;; +131C5;EGYPTIAN HIEROGLYPH M013;Lo;0;L;;;;;N;;;;; +131C6;EGYPTIAN HIEROGLYPH M014;Lo;0;L;;;;;N;;;;; +131C7;EGYPTIAN HIEROGLYPH M015;Lo;0;L;;;;;N;;;;; +131C8;EGYPTIAN HIEROGLYPH M015A;Lo;0;L;;;;;N;;;;; +131C9;EGYPTIAN HIEROGLYPH M016;Lo;0;L;;;;;N;;;;; +131CA;EGYPTIAN HIEROGLYPH M016A;Lo;0;L;;;;;N;;;;; +131CB;EGYPTIAN HIEROGLYPH M017;Lo;0;L;;;;;N;;;;; +131CC;EGYPTIAN HIEROGLYPH M017A;Lo;0;L;;;;;N;;;;; +131CD;EGYPTIAN HIEROGLYPH M018;Lo;0;L;;;;;N;;;;; +131CE;EGYPTIAN HIEROGLYPH M019;Lo;0;L;;;;;N;;;;; +131CF;EGYPTIAN HIEROGLYPH M020;Lo;0;L;;;;;N;;;;; +131D0;EGYPTIAN HIEROGLYPH M021;Lo;0;L;;;;;N;;;;; +131D1;EGYPTIAN HIEROGLYPH M022;Lo;0;L;;;;;N;;;;; +131D2;EGYPTIAN HIEROGLYPH M022A;Lo;0;L;;;;;N;;;;; +131D3;EGYPTIAN HIEROGLYPH M023;Lo;0;L;;;;;N;;;;; +131D4;EGYPTIAN HIEROGLYPH M024;Lo;0;L;;;;;N;;;;; +131D5;EGYPTIAN HIEROGLYPH M024A;Lo;0;L;;;;;N;;;;; +131D6;EGYPTIAN HIEROGLYPH M025;Lo;0;L;;;;;N;;;;; +131D7;EGYPTIAN HIEROGLYPH M026;Lo;0;L;;;;;N;;;;; +131D8;EGYPTIAN HIEROGLYPH M027;Lo;0;L;;;;;N;;;;; +131D9;EGYPTIAN HIEROGLYPH M028;Lo;0;L;;;;;N;;;;; +131DA;EGYPTIAN HIEROGLYPH M028A;Lo;0;L;;;;;N;;;;; +131DB;EGYPTIAN HIEROGLYPH M029;Lo;0;L;;;;;N;;;;; +131DC;EGYPTIAN HIEROGLYPH M030;Lo;0;L;;;;;N;;;;; +131DD;EGYPTIAN HIEROGLYPH M031;Lo;0;L;;;;;N;;;;; +131DE;EGYPTIAN HIEROGLYPH M031A;Lo;0;L;;;;;N;;;;; +131DF;EGYPTIAN HIEROGLYPH M032;Lo;0;L;;;;;N;;;;; +131E0;EGYPTIAN HIEROGLYPH M033;Lo;0;L;;;;;N;;;;; +131E1;EGYPTIAN HIEROGLYPH M033A;Lo;0;L;;;;;N;;;;; +131E2;EGYPTIAN HIEROGLYPH M033B;Lo;0;L;;;;;N;;;;; +131E3;EGYPTIAN HIEROGLYPH M034;Lo;0;L;;;;;N;;;;; +131E4;EGYPTIAN HIEROGLYPH M035;Lo;0;L;;;;;N;;;;; +131E5;EGYPTIAN HIEROGLYPH M036;Lo;0;L;;;;;N;;;;; +131E6;EGYPTIAN HIEROGLYPH M037;Lo;0;L;;;;;N;;;;; +131E7;EGYPTIAN HIEROGLYPH M038;Lo;0;L;;;;;N;;;;; +131E8;EGYPTIAN HIEROGLYPH M039;Lo;0;L;;;;;N;;;;; +131E9;EGYPTIAN HIEROGLYPH M040;Lo;0;L;;;;;N;;;;; +131EA;EGYPTIAN HIEROGLYPH M040A;Lo;0;L;;;;;N;;;;; +131EB;EGYPTIAN HIEROGLYPH M041;Lo;0;L;;;;;N;;;;; +131EC;EGYPTIAN HIEROGLYPH M042;Lo;0;L;;;;;N;;;;; +131ED;EGYPTIAN HIEROGLYPH M043;Lo;0;L;;;;;N;;;;; +131EE;EGYPTIAN HIEROGLYPH M044;Lo;0;L;;;;;N;;;;; +131EF;EGYPTIAN HIEROGLYPH N001;Lo;0;L;;;;;N;;;;; +131F0;EGYPTIAN HIEROGLYPH N002;Lo;0;L;;;;;N;;;;; +131F1;EGYPTIAN HIEROGLYPH N003;Lo;0;L;;;;;N;;;;; +131F2;EGYPTIAN HIEROGLYPH N004;Lo;0;L;;;;;N;;;;; +131F3;EGYPTIAN HIEROGLYPH N005;Lo;0;L;;;;;N;;;;; +131F4;EGYPTIAN HIEROGLYPH N006;Lo;0;L;;;;;N;;;;; +131F5;EGYPTIAN HIEROGLYPH N007;Lo;0;L;;;;;N;;;;; +131F6;EGYPTIAN HIEROGLYPH N008;Lo;0;L;;;;;N;;;;; +131F7;EGYPTIAN HIEROGLYPH N009;Lo;0;L;;;;;N;;;;; +131F8;EGYPTIAN HIEROGLYPH N010;Lo;0;L;;;;;N;;;;; +131F9;EGYPTIAN HIEROGLYPH N011;Lo;0;L;;;;;N;;;;; +131FA;EGYPTIAN HIEROGLYPH N012;Lo;0;L;;;;;N;;;;; +131FB;EGYPTIAN HIEROGLYPH N013;Lo;0;L;;;;;N;;;;; +131FC;EGYPTIAN HIEROGLYPH N014;Lo;0;L;;;;;N;;;;; +131FD;EGYPTIAN HIEROGLYPH N015;Lo;0;L;;;;;N;;;;; +131FE;EGYPTIAN HIEROGLYPH N016;Lo;0;L;;;;;N;;;;; +131FF;EGYPTIAN HIEROGLYPH N017;Lo;0;L;;;;;N;;;;; +13200;EGYPTIAN HIEROGLYPH N018;Lo;0;L;;;;;N;;;;; +13201;EGYPTIAN HIEROGLYPH N018A;Lo;0;L;;;;;N;;;;; +13202;EGYPTIAN HIEROGLYPH N018B;Lo;0;L;;;;;N;;;;; +13203;EGYPTIAN HIEROGLYPH N019;Lo;0;L;;;;;N;;;;; +13204;EGYPTIAN HIEROGLYPH N020;Lo;0;L;;;;;N;;;;; +13205;EGYPTIAN HIEROGLYPH N021;Lo;0;L;;;;;N;;;;; +13206;EGYPTIAN HIEROGLYPH N022;Lo;0;L;;;;;N;;;;; +13207;EGYPTIAN HIEROGLYPH N023;Lo;0;L;;;;;N;;;;; +13208;EGYPTIAN HIEROGLYPH N024;Lo;0;L;;;;;N;;;;; +13209;EGYPTIAN HIEROGLYPH N025;Lo;0;L;;;;;N;;;;; +1320A;EGYPTIAN HIEROGLYPH N025A;Lo;0;L;;;;;N;;;;; +1320B;EGYPTIAN HIEROGLYPH N026;Lo;0;L;;;;;N;;;;; +1320C;EGYPTIAN HIEROGLYPH N027;Lo;0;L;;;;;N;;;;; +1320D;EGYPTIAN HIEROGLYPH N028;Lo;0;L;;;;;N;;;;; +1320E;EGYPTIAN HIEROGLYPH N029;Lo;0;L;;;;;N;;;;; +1320F;EGYPTIAN HIEROGLYPH N030;Lo;0;L;;;;;N;;;;; +13210;EGYPTIAN HIEROGLYPH N031;Lo;0;L;;;;;N;;;;; +13211;EGYPTIAN HIEROGLYPH N032;Lo;0;L;;;;;N;;;;; +13212;EGYPTIAN HIEROGLYPH N033;Lo;0;L;;;;;N;;;;; +13213;EGYPTIAN HIEROGLYPH N033A;Lo;0;L;;;;;N;;;;; +13214;EGYPTIAN HIEROGLYPH N034;Lo;0;L;;;;;N;;;;; +13215;EGYPTIAN HIEROGLYPH N034A;Lo;0;L;;;;;N;;;;; +13216;EGYPTIAN HIEROGLYPH N035;Lo;0;L;;;;;N;;;;; +13217;EGYPTIAN HIEROGLYPH N035A;Lo;0;L;;;;;N;;;;; +13218;EGYPTIAN HIEROGLYPH N036;Lo;0;L;;;;;N;;;;; +13219;EGYPTIAN HIEROGLYPH N037;Lo;0;L;;;;;N;;;;; +1321A;EGYPTIAN HIEROGLYPH N037A;Lo;0;L;;;;;N;;;;; +1321B;EGYPTIAN HIEROGLYPH N038;Lo;0;L;;;;;N;;;;; +1321C;EGYPTIAN HIEROGLYPH N039;Lo;0;L;;;;;N;;;;; +1321D;EGYPTIAN HIEROGLYPH N040;Lo;0;L;;;;;N;;;;; +1321E;EGYPTIAN HIEROGLYPH N041;Lo;0;L;;;;;N;;;;; +1321F;EGYPTIAN HIEROGLYPH N042;Lo;0;L;;;;;N;;;;; +13220;EGYPTIAN HIEROGLYPH NL001;Lo;0;L;;;;;N;;;;; +13221;EGYPTIAN HIEROGLYPH NL002;Lo;0;L;;;;;N;;;;; +13222;EGYPTIAN HIEROGLYPH NL003;Lo;0;L;;;;;N;;;;; +13223;EGYPTIAN HIEROGLYPH NL004;Lo;0;L;;;;;N;;;;; +13224;EGYPTIAN HIEROGLYPH NL005;Lo;0;L;;;;;N;;;;; +13225;EGYPTIAN HIEROGLYPH NL005A;Lo;0;L;;;;;N;;;;; +13226;EGYPTIAN HIEROGLYPH NL006;Lo;0;L;;;;;N;;;;; +13227;EGYPTIAN HIEROGLYPH NL007;Lo;0;L;;;;;N;;;;; +13228;EGYPTIAN HIEROGLYPH NL008;Lo;0;L;;;;;N;;;;; +13229;EGYPTIAN HIEROGLYPH NL009;Lo;0;L;;;;;N;;;;; +1322A;EGYPTIAN HIEROGLYPH NL010;Lo;0;L;;;;;N;;;;; +1322B;EGYPTIAN HIEROGLYPH NL011;Lo;0;L;;;;;N;;;;; +1322C;EGYPTIAN HIEROGLYPH NL012;Lo;0;L;;;;;N;;;;; +1322D;EGYPTIAN HIEROGLYPH NL013;Lo;0;L;;;;;N;;;;; +1322E;EGYPTIAN HIEROGLYPH NL014;Lo;0;L;;;;;N;;;;; +1322F;EGYPTIAN HIEROGLYPH NL015;Lo;0;L;;;;;N;;;;; +13230;EGYPTIAN HIEROGLYPH NL016;Lo;0;L;;;;;N;;;;; +13231;EGYPTIAN HIEROGLYPH NL017;Lo;0;L;;;;;N;;;;; +13232;EGYPTIAN HIEROGLYPH NL017A;Lo;0;L;;;;;N;;;;; +13233;EGYPTIAN HIEROGLYPH NL018;Lo;0;L;;;;;N;;;;; +13234;EGYPTIAN HIEROGLYPH NL019;Lo;0;L;;;;;N;;;;; +13235;EGYPTIAN HIEROGLYPH NL020;Lo;0;L;;;;;N;;;;; +13236;EGYPTIAN HIEROGLYPH NU001;Lo;0;L;;;;;N;;;;; +13237;EGYPTIAN HIEROGLYPH NU002;Lo;0;L;;;;;N;;;;; +13238;EGYPTIAN HIEROGLYPH NU003;Lo;0;L;;;;;N;;;;; +13239;EGYPTIAN HIEROGLYPH NU004;Lo;0;L;;;;;N;;;;; +1323A;EGYPTIAN HIEROGLYPH NU005;Lo;0;L;;;;;N;;;;; +1323B;EGYPTIAN HIEROGLYPH NU006;Lo;0;L;;;;;N;;;;; +1323C;EGYPTIAN HIEROGLYPH NU007;Lo;0;L;;;;;N;;;;; +1323D;EGYPTIAN HIEROGLYPH NU008;Lo;0;L;;;;;N;;;;; +1323E;EGYPTIAN HIEROGLYPH NU009;Lo;0;L;;;;;N;;;;; +1323F;EGYPTIAN HIEROGLYPH NU010;Lo;0;L;;;;;N;;;;; +13240;EGYPTIAN HIEROGLYPH NU010A;Lo;0;L;;;;;N;;;;; +13241;EGYPTIAN HIEROGLYPH NU011;Lo;0;L;;;;;N;;;;; +13242;EGYPTIAN HIEROGLYPH NU011A;Lo;0;L;;;;;N;;;;; +13243;EGYPTIAN HIEROGLYPH NU012;Lo;0;L;;;;;N;;;;; +13244;EGYPTIAN HIEROGLYPH NU013;Lo;0;L;;;;;N;;;;; +13245;EGYPTIAN HIEROGLYPH NU014;Lo;0;L;;;;;N;;;;; +13246;EGYPTIAN HIEROGLYPH NU015;Lo;0;L;;;;;N;;;;; +13247;EGYPTIAN HIEROGLYPH NU016;Lo;0;L;;;;;N;;;;; +13248;EGYPTIAN HIEROGLYPH NU017;Lo;0;L;;;;;N;;;;; +13249;EGYPTIAN HIEROGLYPH NU018;Lo;0;L;;;;;N;;;;; +1324A;EGYPTIAN HIEROGLYPH NU018A;Lo;0;L;;;;;N;;;;; +1324B;EGYPTIAN HIEROGLYPH NU019;Lo;0;L;;;;;N;;;;; +1324C;EGYPTIAN HIEROGLYPH NU020;Lo;0;L;;;;;N;;;;; +1324D;EGYPTIAN HIEROGLYPH NU021;Lo;0;L;;;;;N;;;;; +1324E;EGYPTIAN HIEROGLYPH NU022;Lo;0;L;;;;;N;;;;; +1324F;EGYPTIAN HIEROGLYPH NU022A;Lo;0;L;;;;;N;;;;; +13250;EGYPTIAN HIEROGLYPH O001;Lo;0;L;;;;;N;;;;; +13251;EGYPTIAN HIEROGLYPH O001A;Lo;0;L;;;;;N;;;;; +13252;EGYPTIAN HIEROGLYPH O002;Lo;0;L;;;;;N;;;;; +13253;EGYPTIAN HIEROGLYPH O003;Lo;0;L;;;;;N;;;;; +13254;EGYPTIAN HIEROGLYPH O004;Lo;0;L;;;;;N;;;;; +13255;EGYPTIAN HIEROGLYPH O005;Lo;0;L;;;;;N;;;;; +13256;EGYPTIAN HIEROGLYPH O005A;Lo;0;L;;;;;N;;;;; +13257;EGYPTIAN HIEROGLYPH O006;Lo;0;L;;;;;N;;;;; +13258;EGYPTIAN HIEROGLYPH O006A;Lo;0;L;;;;;N;;;;; +13259;EGYPTIAN HIEROGLYPH O006B;Lo;0;L;;;;;N;;;;; +1325A;EGYPTIAN HIEROGLYPH O006C;Lo;0;L;;;;;N;;;;; +1325B;EGYPTIAN HIEROGLYPH O006D;Lo;0;L;;;;;N;;;;; +1325C;EGYPTIAN HIEROGLYPH O006E;Lo;0;L;;;;;N;;;;; +1325D;EGYPTIAN HIEROGLYPH O006F;Lo;0;L;;;;;N;;;;; +1325E;EGYPTIAN HIEROGLYPH O007;Lo;0;L;;;;;N;;;;; +1325F;EGYPTIAN HIEROGLYPH O008;Lo;0;L;;;;;N;;;;; +13260;EGYPTIAN HIEROGLYPH O009;Lo;0;L;;;;;N;;;;; +13261;EGYPTIAN HIEROGLYPH O010;Lo;0;L;;;;;N;;;;; +13262;EGYPTIAN HIEROGLYPH O010A;Lo;0;L;;;;;N;;;;; +13263;EGYPTIAN HIEROGLYPH O010B;Lo;0;L;;;;;N;;;;; +13264;EGYPTIAN HIEROGLYPH O010C;Lo;0;L;;;;;N;;;;; +13265;EGYPTIAN HIEROGLYPH O011;Lo;0;L;;;;;N;;;;; +13266;EGYPTIAN HIEROGLYPH O012;Lo;0;L;;;;;N;;;;; +13267;EGYPTIAN HIEROGLYPH O013;Lo;0;L;;;;;N;;;;; +13268;EGYPTIAN HIEROGLYPH O014;Lo;0;L;;;;;N;;;;; +13269;EGYPTIAN HIEROGLYPH O015;Lo;0;L;;;;;N;;;;; +1326A;EGYPTIAN HIEROGLYPH O016;Lo;0;L;;;;;N;;;;; +1326B;EGYPTIAN HIEROGLYPH O017;Lo;0;L;;;;;N;;;;; +1326C;EGYPTIAN HIEROGLYPH O018;Lo;0;L;;;;;N;;;;; +1326D;EGYPTIAN HIEROGLYPH O019;Lo;0;L;;;;;N;;;;; +1326E;EGYPTIAN HIEROGLYPH O019A;Lo;0;L;;;;;N;;;;; +1326F;EGYPTIAN HIEROGLYPH O020;Lo;0;L;;;;;N;;;;; +13270;EGYPTIAN HIEROGLYPH O020A;Lo;0;L;;;;;N;;;;; +13271;EGYPTIAN HIEROGLYPH O021;Lo;0;L;;;;;N;;;;; +13272;EGYPTIAN HIEROGLYPH O022;Lo;0;L;;;;;N;;;;; +13273;EGYPTIAN HIEROGLYPH O023;Lo;0;L;;;;;N;;;;; +13274;EGYPTIAN HIEROGLYPH O024;Lo;0;L;;;;;N;;;;; +13275;EGYPTIAN HIEROGLYPH O024A;Lo;0;L;;;;;N;;;;; +13276;EGYPTIAN HIEROGLYPH O025;Lo;0;L;;;;;N;;;;; +13277;EGYPTIAN HIEROGLYPH O025A;Lo;0;L;;;;;N;;;;; +13278;EGYPTIAN HIEROGLYPH O026;Lo;0;L;;;;;N;;;;; +13279;EGYPTIAN HIEROGLYPH O027;Lo;0;L;;;;;N;;;;; +1327A;EGYPTIAN HIEROGLYPH O028;Lo;0;L;;;;;N;;;;; +1327B;EGYPTIAN HIEROGLYPH O029;Lo;0;L;;;;;N;;;;; +1327C;EGYPTIAN HIEROGLYPH O029A;Lo;0;L;;;;;N;;;;; +1327D;EGYPTIAN HIEROGLYPH O030;Lo;0;L;;;;;N;;;;; +1327E;EGYPTIAN HIEROGLYPH O030A;Lo;0;L;;;;;N;;;;; +1327F;EGYPTIAN HIEROGLYPH O031;Lo;0;L;;;;;N;;;;; +13280;EGYPTIAN HIEROGLYPH O032;Lo;0;L;;;;;N;;;;; +13281;EGYPTIAN HIEROGLYPH O033;Lo;0;L;;;;;N;;;;; +13282;EGYPTIAN HIEROGLYPH O033A;Lo;0;L;;;;;N;;;;; +13283;EGYPTIAN HIEROGLYPH O034;Lo;0;L;;;;;N;;;;; +13284;EGYPTIAN HIEROGLYPH O035;Lo;0;L;;;;;N;;;;; +13285;EGYPTIAN HIEROGLYPH O036;Lo;0;L;;;;;N;;;;; +13286;EGYPTIAN HIEROGLYPH O036A;Lo;0;L;;;;;N;;;;; +13287;EGYPTIAN HIEROGLYPH O036B;Lo;0;L;;;;;N;;;;; +13288;EGYPTIAN HIEROGLYPH O036C;Lo;0;L;;;;;N;;;;; +13289;EGYPTIAN HIEROGLYPH O036D;Lo;0;L;;;;;N;;;;; +1328A;EGYPTIAN HIEROGLYPH O037;Lo;0;L;;;;;N;;;;; +1328B;EGYPTIAN HIEROGLYPH O038;Lo;0;L;;;;;N;;;;; +1328C;EGYPTIAN HIEROGLYPH O039;Lo;0;L;;;;;N;;;;; +1328D;EGYPTIAN HIEROGLYPH O040;Lo;0;L;;;;;N;;;;; +1328E;EGYPTIAN HIEROGLYPH O041;Lo;0;L;;;;;N;;;;; +1328F;EGYPTIAN HIEROGLYPH O042;Lo;0;L;;;;;N;;;;; +13290;EGYPTIAN HIEROGLYPH O043;Lo;0;L;;;;;N;;;;; +13291;EGYPTIAN HIEROGLYPH O044;Lo;0;L;;;;;N;;;;; +13292;EGYPTIAN HIEROGLYPH O045;Lo;0;L;;;;;N;;;;; +13293;EGYPTIAN HIEROGLYPH O046;Lo;0;L;;;;;N;;;;; +13294;EGYPTIAN HIEROGLYPH O047;Lo;0;L;;;;;N;;;;; +13295;EGYPTIAN HIEROGLYPH O048;Lo;0;L;;;;;N;;;;; +13296;EGYPTIAN HIEROGLYPH O049;Lo;0;L;;;;;N;;;;; +13297;EGYPTIAN HIEROGLYPH O050;Lo;0;L;;;;;N;;;;; +13298;EGYPTIAN HIEROGLYPH O050A;Lo;0;L;;;;;N;;;;; +13299;EGYPTIAN HIEROGLYPH O050B;Lo;0;L;;;;;N;;;;; +1329A;EGYPTIAN HIEROGLYPH O051;Lo;0;L;;;;;N;;;;; +1329B;EGYPTIAN HIEROGLYPH P001;Lo;0;L;;;;;N;;;;; +1329C;EGYPTIAN HIEROGLYPH P001A;Lo;0;L;;;;;N;;;;; +1329D;EGYPTIAN HIEROGLYPH P002;Lo;0;L;;;;;N;;;;; +1329E;EGYPTIAN HIEROGLYPH P003;Lo;0;L;;;;;N;;;;; +1329F;EGYPTIAN HIEROGLYPH P003A;Lo;0;L;;;;;N;;;;; +132A0;EGYPTIAN HIEROGLYPH P004;Lo;0;L;;;;;N;;;;; +132A1;EGYPTIAN HIEROGLYPH P005;Lo;0;L;;;;;N;;;;; +132A2;EGYPTIAN HIEROGLYPH P006;Lo;0;L;;;;;N;;;;; +132A3;EGYPTIAN HIEROGLYPH P007;Lo;0;L;;;;;N;;;;; +132A4;EGYPTIAN HIEROGLYPH P008;Lo;0;L;;;;;N;;;;; +132A5;EGYPTIAN HIEROGLYPH P009;Lo;0;L;;;;;N;;;;; +132A6;EGYPTIAN HIEROGLYPH P010;Lo;0;L;;;;;N;;;;; +132A7;EGYPTIAN HIEROGLYPH P011;Lo;0;L;;;;;N;;;;; +132A8;EGYPTIAN HIEROGLYPH Q001;Lo;0;L;;;;;N;;;;; +132A9;EGYPTIAN HIEROGLYPH Q002;Lo;0;L;;;;;N;;;;; +132AA;EGYPTIAN HIEROGLYPH Q003;Lo;0;L;;;;;N;;;;; +132AB;EGYPTIAN HIEROGLYPH Q004;Lo;0;L;;;;;N;;;;; +132AC;EGYPTIAN HIEROGLYPH Q005;Lo;0;L;;;;;N;;;;; +132AD;EGYPTIAN HIEROGLYPH Q006;Lo;0;L;;;;;N;;;;; +132AE;EGYPTIAN HIEROGLYPH Q007;Lo;0;L;;;;;N;;;;; +132AF;EGYPTIAN HIEROGLYPH R001;Lo;0;L;;;;;N;;;;; +132B0;EGYPTIAN HIEROGLYPH R002;Lo;0;L;;;;;N;;;;; +132B1;EGYPTIAN HIEROGLYPH R002A;Lo;0;L;;;;;N;;;;; +132B2;EGYPTIAN HIEROGLYPH R003;Lo;0;L;;;;;N;;;;; +132B3;EGYPTIAN HIEROGLYPH R003A;Lo;0;L;;;;;N;;;;; +132B4;EGYPTIAN HIEROGLYPH R003B;Lo;0;L;;;;;N;;;;; +132B5;EGYPTIAN HIEROGLYPH R004;Lo;0;L;;;;;N;;;;; +132B6;EGYPTIAN HIEROGLYPH R005;Lo;0;L;;;;;N;;;;; +132B7;EGYPTIAN HIEROGLYPH R006;Lo;0;L;;;;;N;;;;; +132B8;EGYPTIAN HIEROGLYPH R007;Lo;0;L;;;;;N;;;;; +132B9;EGYPTIAN HIEROGLYPH R008;Lo;0;L;;;;;N;;;;; +132BA;EGYPTIAN HIEROGLYPH R009;Lo;0;L;;;;;N;;;;; +132BB;EGYPTIAN HIEROGLYPH R010;Lo;0;L;;;;;N;;;;; +132BC;EGYPTIAN HIEROGLYPH R010A;Lo;0;L;;;;;N;;;;; +132BD;EGYPTIAN HIEROGLYPH R011;Lo;0;L;;;;;N;;;;; +132BE;EGYPTIAN HIEROGLYPH R012;Lo;0;L;;;;;N;;;;; +132BF;EGYPTIAN HIEROGLYPH R013;Lo;0;L;;;;;N;;;;; +132C0;EGYPTIAN HIEROGLYPH R014;Lo;0;L;;;;;N;;;;; +132C1;EGYPTIAN HIEROGLYPH R015;Lo;0;L;;;;;N;;;;; +132C2;EGYPTIAN HIEROGLYPH R016;Lo;0;L;;;;;N;;;;; +132C3;EGYPTIAN HIEROGLYPH R016A;Lo;0;L;;;;;N;;;;; +132C4;EGYPTIAN HIEROGLYPH R017;Lo;0;L;;;;;N;;;;; +132C5;EGYPTIAN HIEROGLYPH R018;Lo;0;L;;;;;N;;;;; +132C6;EGYPTIAN HIEROGLYPH R019;Lo;0;L;;;;;N;;;;; +132C7;EGYPTIAN HIEROGLYPH R020;Lo;0;L;;;;;N;;;;; +132C8;EGYPTIAN HIEROGLYPH R021;Lo;0;L;;;;;N;;;;; +132C9;EGYPTIAN HIEROGLYPH R022;Lo;0;L;;;;;N;;;;; +132CA;EGYPTIAN HIEROGLYPH R023;Lo;0;L;;;;;N;;;;; +132CB;EGYPTIAN HIEROGLYPH R024;Lo;0;L;;;;;N;;;;; +132CC;EGYPTIAN HIEROGLYPH R025;Lo;0;L;;;;;N;;;;; +132CD;EGYPTIAN HIEROGLYPH R026;Lo;0;L;;;;;N;;;;; +132CE;EGYPTIAN HIEROGLYPH R027;Lo;0;L;;;;;N;;;;; +132CF;EGYPTIAN HIEROGLYPH R028;Lo;0;L;;;;;N;;;;; +132D0;EGYPTIAN HIEROGLYPH R029;Lo;0;L;;;;;N;;;;; +132D1;EGYPTIAN HIEROGLYPH S001;Lo;0;L;;;;;N;;;;; +132D2;EGYPTIAN HIEROGLYPH S002;Lo;0;L;;;;;N;;;;; +132D3;EGYPTIAN HIEROGLYPH S002A;Lo;0;L;;;;;N;;;;; +132D4;EGYPTIAN HIEROGLYPH S003;Lo;0;L;;;;;N;;;;; +132D5;EGYPTIAN HIEROGLYPH S004;Lo;0;L;;;;;N;;;;; +132D6;EGYPTIAN HIEROGLYPH S005;Lo;0;L;;;;;N;;;;; +132D7;EGYPTIAN HIEROGLYPH S006;Lo;0;L;;;;;N;;;;; +132D8;EGYPTIAN HIEROGLYPH S006A;Lo;0;L;;;;;N;;;;; +132D9;EGYPTIAN HIEROGLYPH S007;Lo;0;L;;;;;N;;;;; +132DA;EGYPTIAN HIEROGLYPH S008;Lo;0;L;;;;;N;;;;; +132DB;EGYPTIAN HIEROGLYPH S009;Lo;0;L;;;;;N;;;;; +132DC;EGYPTIAN HIEROGLYPH S010;Lo;0;L;;;;;N;;;;; +132DD;EGYPTIAN HIEROGLYPH S011;Lo;0;L;;;;;N;;;;; +132DE;EGYPTIAN HIEROGLYPH S012;Lo;0;L;;;;;N;;;;; +132DF;EGYPTIAN HIEROGLYPH S013;Lo;0;L;;;;;N;;;;; +132E0;EGYPTIAN HIEROGLYPH S014;Lo;0;L;;;;;N;;;;; +132E1;EGYPTIAN HIEROGLYPH S014A;Lo;0;L;;;;;N;;;;; +132E2;EGYPTIAN HIEROGLYPH S014B;Lo;0;L;;;;;N;;;;; +132E3;EGYPTIAN HIEROGLYPH S015;Lo;0;L;;;;;N;;;;; +132E4;EGYPTIAN HIEROGLYPH S016;Lo;0;L;;;;;N;;;;; +132E5;EGYPTIAN HIEROGLYPH S017;Lo;0;L;;;;;N;;;;; +132E6;EGYPTIAN HIEROGLYPH S017A;Lo;0;L;;;;;N;;;;; +132E7;EGYPTIAN HIEROGLYPH S018;Lo;0;L;;;;;N;;;;; +132E8;EGYPTIAN HIEROGLYPH S019;Lo;0;L;;;;;N;;;;; +132E9;EGYPTIAN HIEROGLYPH S020;Lo;0;L;;;;;N;;;;; +132EA;EGYPTIAN HIEROGLYPH S021;Lo;0;L;;;;;N;;;;; +132EB;EGYPTIAN HIEROGLYPH S022;Lo;0;L;;;;;N;;;;; +132EC;EGYPTIAN HIEROGLYPH S023;Lo;0;L;;;;;N;;;;; +132ED;EGYPTIAN HIEROGLYPH S024;Lo;0;L;;;;;N;;;;; +132EE;EGYPTIAN HIEROGLYPH S025;Lo;0;L;;;;;N;;;;; +132EF;EGYPTIAN HIEROGLYPH S026;Lo;0;L;;;;;N;;;;; +132F0;EGYPTIAN HIEROGLYPH S026A;Lo;0;L;;;;;N;;;;; +132F1;EGYPTIAN HIEROGLYPH S026B;Lo;0;L;;;;;N;;;;; +132F2;EGYPTIAN HIEROGLYPH S027;Lo;0;L;;;;;N;;;;; +132F3;EGYPTIAN HIEROGLYPH S028;Lo;0;L;;;;;N;;;;; +132F4;EGYPTIAN HIEROGLYPH S029;Lo;0;L;;;;;N;;;;; +132F5;EGYPTIAN HIEROGLYPH S030;Lo;0;L;;;;;N;;;;; +132F6;EGYPTIAN HIEROGLYPH S031;Lo;0;L;;;;;N;;;;; +132F7;EGYPTIAN HIEROGLYPH S032;Lo;0;L;;;;;N;;;;; +132F8;EGYPTIAN HIEROGLYPH S033;Lo;0;L;;;;;N;;;;; +132F9;EGYPTIAN HIEROGLYPH S034;Lo;0;L;;;;;N;;;;; +132FA;EGYPTIAN HIEROGLYPH S035;Lo;0;L;;;;;N;;;;; +132FB;EGYPTIAN HIEROGLYPH S035A;Lo;0;L;;;;;N;;;;; +132FC;EGYPTIAN HIEROGLYPH S036;Lo;0;L;;;;;N;;;;; +132FD;EGYPTIAN HIEROGLYPH S037;Lo;0;L;;;;;N;;;;; +132FE;EGYPTIAN HIEROGLYPH S038;Lo;0;L;;;;;N;;;;; +132FF;EGYPTIAN HIEROGLYPH S039;Lo;0;L;;;;;N;;;;; +13300;EGYPTIAN HIEROGLYPH S040;Lo;0;L;;;;;N;;;;; +13301;EGYPTIAN HIEROGLYPH S041;Lo;0;L;;;;;N;;;;; +13302;EGYPTIAN HIEROGLYPH S042;Lo;0;L;;;;;N;;;;; +13303;EGYPTIAN HIEROGLYPH S043;Lo;0;L;;;;;N;;;;; +13304;EGYPTIAN HIEROGLYPH S044;Lo;0;L;;;;;N;;;;; +13305;EGYPTIAN HIEROGLYPH S045;Lo;0;L;;;;;N;;;;; +13306;EGYPTIAN HIEROGLYPH S046;Lo;0;L;;;;;N;;;;; +13307;EGYPTIAN HIEROGLYPH T001;Lo;0;L;;;;;N;;;;; +13308;EGYPTIAN HIEROGLYPH T002;Lo;0;L;;;;;N;;;;; +13309;EGYPTIAN HIEROGLYPH T003;Lo;0;L;;;;;N;;;;; +1330A;EGYPTIAN HIEROGLYPH T003A;Lo;0;L;;;;;N;;;;; +1330B;EGYPTIAN HIEROGLYPH T004;Lo;0;L;;;;;N;;;;; +1330C;EGYPTIAN HIEROGLYPH T005;Lo;0;L;;;;;N;;;;; +1330D;EGYPTIAN HIEROGLYPH T006;Lo;0;L;;;;;N;;;;; +1330E;EGYPTIAN HIEROGLYPH T007;Lo;0;L;;;;;N;;;;; +1330F;EGYPTIAN HIEROGLYPH T007A;Lo;0;L;;;;;N;;;;; +13310;EGYPTIAN HIEROGLYPH T008;Lo;0;L;;;;;N;;;;; +13311;EGYPTIAN HIEROGLYPH T008A;Lo;0;L;;;;;N;;;;; +13312;EGYPTIAN HIEROGLYPH T009;Lo;0;L;;;;;N;;;;; +13313;EGYPTIAN HIEROGLYPH T009A;Lo;0;L;;;;;N;;;;; +13314;EGYPTIAN HIEROGLYPH T010;Lo;0;L;;;;;N;;;;; +13315;EGYPTIAN HIEROGLYPH T011;Lo;0;L;;;;;N;;;;; +13316;EGYPTIAN HIEROGLYPH T011A;Lo;0;L;;;;;N;;;;; +13317;EGYPTIAN HIEROGLYPH T012;Lo;0;L;;;;;N;;;;; +13318;EGYPTIAN HIEROGLYPH T013;Lo;0;L;;;;;N;;;;; +13319;EGYPTIAN HIEROGLYPH T014;Lo;0;L;;;;;N;;;;; +1331A;EGYPTIAN HIEROGLYPH T015;Lo;0;L;;;;;N;;;;; +1331B;EGYPTIAN HIEROGLYPH T016;Lo;0;L;;;;;N;;;;; +1331C;EGYPTIAN HIEROGLYPH T016A;Lo;0;L;;;;;N;;;;; +1331D;EGYPTIAN HIEROGLYPH T017;Lo;0;L;;;;;N;;;;; +1331E;EGYPTIAN HIEROGLYPH T018;Lo;0;L;;;;;N;;;;; +1331F;EGYPTIAN HIEROGLYPH T019;Lo;0;L;;;;;N;;;;; +13320;EGYPTIAN HIEROGLYPH T020;Lo;0;L;;;;;N;;;;; +13321;EGYPTIAN HIEROGLYPH T021;Lo;0;L;;;;;N;;;;; +13322;EGYPTIAN HIEROGLYPH T022;Lo;0;L;;;;;N;;;;; +13323;EGYPTIAN HIEROGLYPH T023;Lo;0;L;;;;;N;;;;; +13324;EGYPTIAN HIEROGLYPH T024;Lo;0;L;;;;;N;;;;; +13325;EGYPTIAN HIEROGLYPH T025;Lo;0;L;;;;;N;;;;; +13326;EGYPTIAN HIEROGLYPH T026;Lo;0;L;;;;;N;;;;; +13327;EGYPTIAN HIEROGLYPH T027;Lo;0;L;;;;;N;;;;; +13328;EGYPTIAN HIEROGLYPH T028;Lo;0;L;;;;;N;;;;; +13329;EGYPTIAN HIEROGLYPH T029;Lo;0;L;;;;;N;;;;; +1332A;EGYPTIAN HIEROGLYPH T030;Lo;0;L;;;;;N;;;;; +1332B;EGYPTIAN HIEROGLYPH T031;Lo;0;L;;;;;N;;;;; +1332C;EGYPTIAN HIEROGLYPH T032;Lo;0;L;;;;;N;;;;; +1332D;EGYPTIAN HIEROGLYPH T032A;Lo;0;L;;;;;N;;;;; +1332E;EGYPTIAN HIEROGLYPH T033;Lo;0;L;;;;;N;;;;; +1332F;EGYPTIAN HIEROGLYPH T033A;Lo;0;L;;;;;N;;;;; +13330;EGYPTIAN HIEROGLYPH T034;Lo;0;L;;;;;N;;;;; +13331;EGYPTIAN HIEROGLYPH T035;Lo;0;L;;;;;N;;;;; +13332;EGYPTIAN HIEROGLYPH T036;Lo;0;L;;;;;N;;;;; +13333;EGYPTIAN HIEROGLYPH U001;Lo;0;L;;;;;N;;;;; +13334;EGYPTIAN HIEROGLYPH U002;Lo;0;L;;;;;N;;;;; +13335;EGYPTIAN HIEROGLYPH U003;Lo;0;L;;;;;N;;;;; +13336;EGYPTIAN HIEROGLYPH U004;Lo;0;L;;;;;N;;;;; +13337;EGYPTIAN HIEROGLYPH U005;Lo;0;L;;;;;N;;;;; +13338;EGYPTIAN HIEROGLYPH U006;Lo;0;L;;;;;N;;;;; +13339;EGYPTIAN HIEROGLYPH U006A;Lo;0;L;;;;;N;;;;; +1333A;EGYPTIAN HIEROGLYPH U006B;Lo;0;L;;;;;N;;;;; +1333B;EGYPTIAN HIEROGLYPH U007;Lo;0;L;;;;;N;;;;; +1333C;EGYPTIAN HIEROGLYPH U008;Lo;0;L;;;;;N;;;;; +1333D;EGYPTIAN HIEROGLYPH U009;Lo;0;L;;;;;N;;;;; +1333E;EGYPTIAN HIEROGLYPH U010;Lo;0;L;;;;;N;;;;; +1333F;EGYPTIAN HIEROGLYPH U011;Lo;0;L;;;;;N;;;;; +13340;EGYPTIAN HIEROGLYPH U012;Lo;0;L;;;;;N;;;;; +13341;EGYPTIAN HIEROGLYPH U013;Lo;0;L;;;;;N;;;;; +13342;EGYPTIAN HIEROGLYPH U014;Lo;0;L;;;;;N;;;;; +13343;EGYPTIAN HIEROGLYPH U015;Lo;0;L;;;;;N;;;;; +13344;EGYPTIAN HIEROGLYPH U016;Lo;0;L;;;;;N;;;;; +13345;EGYPTIAN HIEROGLYPH U017;Lo;0;L;;;;;N;;;;; +13346;EGYPTIAN HIEROGLYPH U018;Lo;0;L;;;;;N;;;;; +13347;EGYPTIAN HIEROGLYPH U019;Lo;0;L;;;;;N;;;;; +13348;EGYPTIAN HIEROGLYPH U020;Lo;0;L;;;;;N;;;;; +13349;EGYPTIAN HIEROGLYPH U021;Lo;0;L;;;;;N;;;;; +1334A;EGYPTIAN HIEROGLYPH U022;Lo;0;L;;;;;N;;;;; +1334B;EGYPTIAN HIEROGLYPH U023;Lo;0;L;;;;;N;;;;; +1334C;EGYPTIAN HIEROGLYPH U023A;Lo;0;L;;;;;N;;;;; +1334D;EGYPTIAN HIEROGLYPH U024;Lo;0;L;;;;;N;;;;; +1334E;EGYPTIAN HIEROGLYPH U025;Lo;0;L;;;;;N;;;;; +1334F;EGYPTIAN HIEROGLYPH U026;Lo;0;L;;;;;N;;;;; +13350;EGYPTIAN HIEROGLYPH U027;Lo;0;L;;;;;N;;;;; +13351;EGYPTIAN HIEROGLYPH U028;Lo;0;L;;;;;N;;;;; +13352;EGYPTIAN HIEROGLYPH U029;Lo;0;L;;;;;N;;;;; +13353;EGYPTIAN HIEROGLYPH U029A;Lo;0;L;;;;;N;;;;; +13354;EGYPTIAN HIEROGLYPH U030;Lo;0;L;;;;;N;;;;; +13355;EGYPTIAN HIEROGLYPH U031;Lo;0;L;;;;;N;;;;; +13356;EGYPTIAN HIEROGLYPH U032;Lo;0;L;;;;;N;;;;; +13357;EGYPTIAN HIEROGLYPH U032A;Lo;0;L;;;;;N;;;;; +13358;EGYPTIAN HIEROGLYPH U033;Lo;0;L;;;;;N;;;;; +13359;EGYPTIAN HIEROGLYPH U034;Lo;0;L;;;;;N;;;;; +1335A;EGYPTIAN HIEROGLYPH U035;Lo;0;L;;;;;N;;;;; +1335B;EGYPTIAN HIEROGLYPH U036;Lo;0;L;;;;;N;;;;; +1335C;EGYPTIAN HIEROGLYPH U037;Lo;0;L;;;;;N;;;;; +1335D;EGYPTIAN HIEROGLYPH U038;Lo;0;L;;;;;N;;;;; +1335E;EGYPTIAN HIEROGLYPH U039;Lo;0;L;;;;;N;;;;; +1335F;EGYPTIAN HIEROGLYPH U040;Lo;0;L;;;;;N;;;;; +13360;EGYPTIAN HIEROGLYPH U041;Lo;0;L;;;;;N;;;;; +13361;EGYPTIAN HIEROGLYPH U042;Lo;0;L;;;;;N;;;;; +13362;EGYPTIAN HIEROGLYPH V001;Lo;0;L;;;;;N;;;;; +13363;EGYPTIAN HIEROGLYPH V001A;Lo;0;L;;;;;N;;;;; +13364;EGYPTIAN HIEROGLYPH V001B;Lo;0;L;;;;;N;;;;; +13365;EGYPTIAN HIEROGLYPH V001C;Lo;0;L;;;;;N;;;;; +13366;EGYPTIAN HIEROGLYPH V001D;Lo;0;L;;;;;N;;;;; +13367;EGYPTIAN HIEROGLYPH V001E;Lo;0;L;;;;;N;;;;; +13368;EGYPTIAN HIEROGLYPH V001F;Lo;0;L;;;;;N;;;;; +13369;EGYPTIAN HIEROGLYPH V001G;Lo;0;L;;;;;N;;;;; +1336A;EGYPTIAN HIEROGLYPH V001H;Lo;0;L;;;;;N;;;;; +1336B;EGYPTIAN HIEROGLYPH V001I;Lo;0;L;;;;;N;;;;; +1336C;EGYPTIAN HIEROGLYPH V002;Lo;0;L;;;;;N;;;;; +1336D;EGYPTIAN HIEROGLYPH V002A;Lo;0;L;;;;;N;;;;; +1336E;EGYPTIAN HIEROGLYPH V003;Lo;0;L;;;;;N;;;;; +1336F;EGYPTIAN HIEROGLYPH V004;Lo;0;L;;;;;N;;;;; +13370;EGYPTIAN HIEROGLYPH V005;Lo;0;L;;;;;N;;;;; +13371;EGYPTIAN HIEROGLYPH V006;Lo;0;L;;;;;N;;;;; +13372;EGYPTIAN HIEROGLYPH V007;Lo;0;L;;;;;N;;;;; +13373;EGYPTIAN HIEROGLYPH V007A;Lo;0;L;;;;;N;;;;; +13374;EGYPTIAN HIEROGLYPH V007B;Lo;0;L;;;;;N;;;;; +13375;EGYPTIAN HIEROGLYPH V008;Lo;0;L;;;;;N;;;;; +13376;EGYPTIAN HIEROGLYPH V009;Lo;0;L;;;;;N;;;;; +13377;EGYPTIAN HIEROGLYPH V010;Lo;0;L;;;;;N;;;;; +13378;EGYPTIAN HIEROGLYPH V011;Lo;0;L;;;;;N;;;;; +13379;EGYPTIAN HIEROGLYPH V011A;Lo;0;L;;;;;N;;;;; +1337A;EGYPTIAN HIEROGLYPH V011B;Lo;0;L;;;;;N;;;;; +1337B;EGYPTIAN HIEROGLYPH V011C;Lo;0;L;;;;;N;;;;; +1337C;EGYPTIAN HIEROGLYPH V012;Lo;0;L;;;;;N;;;;; +1337D;EGYPTIAN HIEROGLYPH V012A;Lo;0;L;;;;;N;;;;; +1337E;EGYPTIAN HIEROGLYPH V012B;Lo;0;L;;;;;N;;;;; +1337F;EGYPTIAN HIEROGLYPH V013;Lo;0;L;;;;;N;;;;; +13380;EGYPTIAN HIEROGLYPH V014;Lo;0;L;;;;;N;;;;; +13381;EGYPTIAN HIEROGLYPH V015;Lo;0;L;;;;;N;;;;; +13382;EGYPTIAN HIEROGLYPH V016;Lo;0;L;;;;;N;;;;; +13383;EGYPTIAN HIEROGLYPH V017;Lo;0;L;;;;;N;;;;; +13384;EGYPTIAN HIEROGLYPH V018;Lo;0;L;;;;;N;;;;; +13385;EGYPTIAN HIEROGLYPH V019;Lo;0;L;;;;;N;;;;; +13386;EGYPTIAN HIEROGLYPH V020;Lo;0;L;;;;;N;;;;; +13387;EGYPTIAN HIEROGLYPH V020A;Lo;0;L;;;;;N;;;;; +13388;EGYPTIAN HIEROGLYPH V020B;Lo;0;L;;;;;N;;;;; +13389;EGYPTIAN HIEROGLYPH V020C;Lo;0;L;;;;;N;;;;; +1338A;EGYPTIAN HIEROGLYPH V020D;Lo;0;L;;;;;N;;;;; +1338B;EGYPTIAN HIEROGLYPH V020E;Lo;0;L;;;;;N;;;;; +1338C;EGYPTIAN HIEROGLYPH V020F;Lo;0;L;;;;;N;;;;; +1338D;EGYPTIAN HIEROGLYPH V020G;Lo;0;L;;;;;N;;;;; +1338E;EGYPTIAN HIEROGLYPH V020H;Lo;0;L;;;;;N;;;;; +1338F;EGYPTIAN HIEROGLYPH V020I;Lo;0;L;;;;;N;;;;; +13390;EGYPTIAN HIEROGLYPH V020J;Lo;0;L;;;;;N;;;;; +13391;EGYPTIAN HIEROGLYPH V020K;Lo;0;L;;;;;N;;;;; +13392;EGYPTIAN HIEROGLYPH V020L;Lo;0;L;;;;;N;;;;; +13393;EGYPTIAN HIEROGLYPH V021;Lo;0;L;;;;;N;;;;; +13394;EGYPTIAN HIEROGLYPH V022;Lo;0;L;;;;;N;;;;; +13395;EGYPTIAN HIEROGLYPH V023;Lo;0;L;;;;;N;;;;; +13396;EGYPTIAN HIEROGLYPH V023A;Lo;0;L;;;;;N;;;;; +13397;EGYPTIAN HIEROGLYPH V024;Lo;0;L;;;;;N;;;;; +13398;EGYPTIAN HIEROGLYPH V025;Lo;0;L;;;;;N;;;;; +13399;EGYPTIAN HIEROGLYPH V026;Lo;0;L;;;;;N;;;;; +1339A;EGYPTIAN HIEROGLYPH V027;Lo;0;L;;;;;N;;;;; +1339B;EGYPTIAN HIEROGLYPH V028;Lo;0;L;;;;;N;;;;; +1339C;EGYPTIAN HIEROGLYPH V028A;Lo;0;L;;;;;N;;;;; +1339D;EGYPTIAN HIEROGLYPH V029;Lo;0;L;;;;;N;;;;; +1339E;EGYPTIAN HIEROGLYPH V029A;Lo;0;L;;;;;N;;;;; +1339F;EGYPTIAN HIEROGLYPH V030;Lo;0;L;;;;;N;;;;; +133A0;EGYPTIAN HIEROGLYPH V030A;Lo;0;L;;;;;N;;;;; +133A1;EGYPTIAN HIEROGLYPH V031;Lo;0;L;;;;;N;;;;; +133A2;EGYPTIAN HIEROGLYPH V031A;Lo;0;L;;;;;N;;;;; +133A3;EGYPTIAN HIEROGLYPH V032;Lo;0;L;;;;;N;;;;; +133A4;EGYPTIAN HIEROGLYPH V033;Lo;0;L;;;;;N;;;;; +133A5;EGYPTIAN HIEROGLYPH V033A;Lo;0;L;;;;;N;;;;; +133A6;EGYPTIAN HIEROGLYPH V034;Lo;0;L;;;;;N;;;;; +133A7;EGYPTIAN HIEROGLYPH V035;Lo;0;L;;;;;N;;;;; +133A8;EGYPTIAN HIEROGLYPH V036;Lo;0;L;;;;;N;;;;; +133A9;EGYPTIAN HIEROGLYPH V037;Lo;0;L;;;;;N;;;;; +133AA;EGYPTIAN HIEROGLYPH V037A;Lo;0;L;;;;;N;;;;; +133AB;EGYPTIAN HIEROGLYPH V038;Lo;0;L;;;;;N;;;;; +133AC;EGYPTIAN HIEROGLYPH V039;Lo;0;L;;;;;N;;;;; +133AD;EGYPTIAN HIEROGLYPH V040;Lo;0;L;;;;;N;;;;; +133AE;EGYPTIAN HIEROGLYPH V040A;Lo;0;L;;;;;N;;;;; +133AF;EGYPTIAN HIEROGLYPH W001;Lo;0;L;;;;;N;;;;; +133B0;EGYPTIAN HIEROGLYPH W002;Lo;0;L;;;;;N;;;;; +133B1;EGYPTIAN HIEROGLYPH W003;Lo;0;L;;;;;N;;;;; +133B2;EGYPTIAN HIEROGLYPH W003A;Lo;0;L;;;;;N;;;;; +133B3;EGYPTIAN HIEROGLYPH W004;Lo;0;L;;;;;N;;;;; +133B4;EGYPTIAN HIEROGLYPH W005;Lo;0;L;;;;;N;;;;; +133B5;EGYPTIAN HIEROGLYPH W006;Lo;0;L;;;;;N;;;;; +133B6;EGYPTIAN HIEROGLYPH W007;Lo;0;L;;;;;N;;;;; +133B7;EGYPTIAN HIEROGLYPH W008;Lo;0;L;;;;;N;;;;; +133B8;EGYPTIAN HIEROGLYPH W009;Lo;0;L;;;;;N;;;;; +133B9;EGYPTIAN HIEROGLYPH W009A;Lo;0;L;;;;;N;;;;; +133BA;EGYPTIAN HIEROGLYPH W010;Lo;0;L;;;;;N;;;;; +133BB;EGYPTIAN HIEROGLYPH W010A;Lo;0;L;;;;;N;;;;; +133BC;EGYPTIAN HIEROGLYPH W011;Lo;0;L;;;;;N;;;;; +133BD;EGYPTIAN HIEROGLYPH W012;Lo;0;L;;;;;N;;;;; +133BE;EGYPTIAN HIEROGLYPH W013;Lo;0;L;;;;;N;;;;; +133BF;EGYPTIAN HIEROGLYPH W014;Lo;0;L;;;;;N;;;;; +133C0;EGYPTIAN HIEROGLYPH W014A;Lo;0;L;;;;;N;;;;; +133C1;EGYPTIAN HIEROGLYPH W015;Lo;0;L;;;;;N;;;;; +133C2;EGYPTIAN HIEROGLYPH W016;Lo;0;L;;;;;N;;;;; +133C3;EGYPTIAN HIEROGLYPH W017;Lo;0;L;;;;;N;;;;; +133C4;EGYPTIAN HIEROGLYPH W017A;Lo;0;L;;;;;N;;;;; +133C5;EGYPTIAN HIEROGLYPH W018;Lo;0;L;;;;;N;;;;; +133C6;EGYPTIAN HIEROGLYPH W018A;Lo;0;L;;;;;N;;;;; +133C7;EGYPTIAN HIEROGLYPH W019;Lo;0;L;;;;;N;;;;; +133C8;EGYPTIAN HIEROGLYPH W020;Lo;0;L;;;;;N;;;;; +133C9;EGYPTIAN HIEROGLYPH W021;Lo;0;L;;;;;N;;;;; +133CA;EGYPTIAN HIEROGLYPH W022;Lo;0;L;;;;;N;;;;; +133CB;EGYPTIAN HIEROGLYPH W023;Lo;0;L;;;;;N;;;;; +133CC;EGYPTIAN HIEROGLYPH W024;Lo;0;L;;;;;N;;;;; +133CD;EGYPTIAN HIEROGLYPH W024A;Lo;0;L;;;;;N;;;;; +133CE;EGYPTIAN HIEROGLYPH W025;Lo;0;L;;;;;N;;;;; +133CF;EGYPTIAN HIEROGLYPH X001;Lo;0;L;;;;;N;;;;; +133D0;EGYPTIAN HIEROGLYPH X002;Lo;0;L;;;;;N;;;;; +133D1;EGYPTIAN HIEROGLYPH X003;Lo;0;L;;;;;N;;;;; +133D2;EGYPTIAN HIEROGLYPH X004;Lo;0;L;;;;;N;;;;; +133D3;EGYPTIAN HIEROGLYPH X004A;Lo;0;L;;;;;N;;;;; +133D4;EGYPTIAN HIEROGLYPH X004B;Lo;0;L;;;;;N;;;;; +133D5;EGYPTIAN HIEROGLYPH X005;Lo;0;L;;;;;N;;;;; +133D6;EGYPTIAN HIEROGLYPH X006;Lo;0;L;;;;;N;;;;; +133D7;EGYPTIAN HIEROGLYPH X006A;Lo;0;L;;;;;N;;;;; +133D8;EGYPTIAN HIEROGLYPH X007;Lo;0;L;;;;;N;;;;; +133D9;EGYPTIAN HIEROGLYPH X008;Lo;0;L;;;;;N;;;;; +133DA;EGYPTIAN HIEROGLYPH X008A;Lo;0;L;;;;;N;;;;; +133DB;EGYPTIAN HIEROGLYPH Y001;Lo;0;L;;;;;N;;;;; +133DC;EGYPTIAN HIEROGLYPH Y001A;Lo;0;L;;;;;N;;;;; +133DD;EGYPTIAN HIEROGLYPH Y002;Lo;0;L;;;;;N;;;;; +133DE;EGYPTIAN HIEROGLYPH Y003;Lo;0;L;;;;;N;;;;; +133DF;EGYPTIAN HIEROGLYPH Y004;Lo;0;L;;;;;N;;;;; +133E0;EGYPTIAN HIEROGLYPH Y005;Lo;0;L;;;;;N;;;;; +133E1;EGYPTIAN HIEROGLYPH Y006;Lo;0;L;;;;;N;;;;; +133E2;EGYPTIAN HIEROGLYPH Y007;Lo;0;L;;;;;N;;;;; +133E3;EGYPTIAN HIEROGLYPH Y008;Lo;0;L;;;;;N;;;;; +133E4;EGYPTIAN HIEROGLYPH Z001;Lo;0;L;;;;;N;;;;; +133E5;EGYPTIAN HIEROGLYPH Z002;Lo;0;L;;;;;N;;;;; +133E6;EGYPTIAN HIEROGLYPH Z002A;Lo;0;L;;;;;N;;;;; +133E7;EGYPTIAN HIEROGLYPH Z002B;Lo;0;L;;;;;N;;;;; +133E8;EGYPTIAN HIEROGLYPH Z002C;Lo;0;L;;;;;N;;;;; +133E9;EGYPTIAN HIEROGLYPH Z002D;Lo;0;L;;;;;N;;;;; +133EA;EGYPTIAN HIEROGLYPH Z003;Lo;0;L;;;;;N;;;;; +133EB;EGYPTIAN HIEROGLYPH Z003A;Lo;0;L;;;;;N;;;;; +133EC;EGYPTIAN HIEROGLYPH Z003B;Lo;0;L;;;;;N;;;;; +133ED;EGYPTIAN HIEROGLYPH Z004;Lo;0;L;;;;;N;;;;; +133EE;EGYPTIAN HIEROGLYPH Z004A;Lo;0;L;;;;;N;;;;; +133EF;EGYPTIAN HIEROGLYPH Z005;Lo;0;L;;;;;N;;;;; +133F0;EGYPTIAN HIEROGLYPH Z005A;Lo;0;L;;;;;N;;;;; +133F1;EGYPTIAN HIEROGLYPH Z006;Lo;0;L;;;;;N;;;;; +133F2;EGYPTIAN HIEROGLYPH Z007;Lo;0;L;;;;;N;;;;; +133F3;EGYPTIAN HIEROGLYPH Z008;Lo;0;L;;;;;N;;;;; +133F4;EGYPTIAN HIEROGLYPH Z009;Lo;0;L;;;;;N;;;;; +133F5;EGYPTIAN HIEROGLYPH Z010;Lo;0;L;;;;;N;;;;; +133F6;EGYPTIAN HIEROGLYPH Z011;Lo;0;L;;;;;N;;;;; +133F7;EGYPTIAN HIEROGLYPH Z012;Lo;0;L;;;;;N;;;;; +133F8;EGYPTIAN HIEROGLYPH Z013;Lo;0;L;;;;;N;;;;; +133F9;EGYPTIAN HIEROGLYPH Z014;Lo;0;L;;;;;N;;;;; +133FA;EGYPTIAN HIEROGLYPH Z015;Lo;0;L;;;;;N;;;;; +133FB;EGYPTIAN HIEROGLYPH Z015A;Lo;0;L;;;;;N;;;;; +133FC;EGYPTIAN HIEROGLYPH Z015B;Lo;0;L;;;;;N;;;;; +133FD;EGYPTIAN HIEROGLYPH Z015C;Lo;0;L;;;;;N;;;;; +133FE;EGYPTIAN HIEROGLYPH Z015D;Lo;0;L;;;;;N;;;;; +133FF;EGYPTIAN HIEROGLYPH Z015E;Lo;0;L;;;;;N;;;;; +13400;EGYPTIAN HIEROGLYPH Z015F;Lo;0;L;;;;;N;;;;; +13401;EGYPTIAN HIEROGLYPH Z015G;Lo;0;L;;;;;N;;;;; +13402;EGYPTIAN HIEROGLYPH Z015H;Lo;0;L;;;;;N;;;;; +13403;EGYPTIAN HIEROGLYPH Z015I;Lo;0;L;;;;;N;;;;; +13404;EGYPTIAN HIEROGLYPH Z016;Lo;0;L;;;;;N;;;;; +13405;EGYPTIAN HIEROGLYPH Z016A;Lo;0;L;;;;;N;;;;; +13406;EGYPTIAN HIEROGLYPH Z016B;Lo;0;L;;;;;N;;;;; +13407;EGYPTIAN HIEROGLYPH Z016C;Lo;0;L;;;;;N;;;;; +13408;EGYPTIAN HIEROGLYPH Z016D;Lo;0;L;;;;;N;;;;; +13409;EGYPTIAN HIEROGLYPH Z016E;Lo;0;L;;;;;N;;;;; +1340A;EGYPTIAN HIEROGLYPH Z016F;Lo;0;L;;;;;N;;;;; +1340B;EGYPTIAN HIEROGLYPH Z016G;Lo;0;L;;;;;N;;;;; +1340C;EGYPTIAN HIEROGLYPH Z016H;Lo;0;L;;;;;N;;;;; +1340D;EGYPTIAN HIEROGLYPH AA001;Lo;0;L;;;;;N;;;;; +1340E;EGYPTIAN HIEROGLYPH AA002;Lo;0;L;;;;;N;;;;; +1340F;EGYPTIAN HIEROGLYPH AA003;Lo;0;L;;;;;N;;;;; +13410;EGYPTIAN HIEROGLYPH AA004;Lo;0;L;;;;;N;;;;; +13411;EGYPTIAN HIEROGLYPH AA005;Lo;0;L;;;;;N;;;;; +13412;EGYPTIAN HIEROGLYPH AA006;Lo;0;L;;;;;N;;;;; +13413;EGYPTIAN HIEROGLYPH AA007;Lo;0;L;;;;;N;;;;; +13414;EGYPTIAN HIEROGLYPH AA007A;Lo;0;L;;;;;N;;;;; +13415;EGYPTIAN HIEROGLYPH AA007B;Lo;0;L;;;;;N;;;;; +13416;EGYPTIAN HIEROGLYPH AA008;Lo;0;L;;;;;N;;;;; +13417;EGYPTIAN HIEROGLYPH AA009;Lo;0;L;;;;;N;;;;; +13418;EGYPTIAN HIEROGLYPH AA010;Lo;0;L;;;;;N;;;;; +13419;EGYPTIAN HIEROGLYPH AA011;Lo;0;L;;;;;N;;;;; +1341A;EGYPTIAN HIEROGLYPH AA012;Lo;0;L;;;;;N;;;;; +1341B;EGYPTIAN HIEROGLYPH AA013;Lo;0;L;;;;;N;;;;; +1341C;EGYPTIAN HIEROGLYPH AA014;Lo;0;L;;;;;N;;;;; +1341D;EGYPTIAN HIEROGLYPH AA015;Lo;0;L;;;;;N;;;;; +1341E;EGYPTIAN HIEROGLYPH AA016;Lo;0;L;;;;;N;;;;; +1341F;EGYPTIAN HIEROGLYPH AA017;Lo;0;L;;;;;N;;;;; +13420;EGYPTIAN HIEROGLYPH AA018;Lo;0;L;;;;;N;;;;; +13421;EGYPTIAN HIEROGLYPH AA019;Lo;0;L;;;;;N;;;;; +13422;EGYPTIAN HIEROGLYPH AA020;Lo;0;L;;;;;N;;;;; +13423;EGYPTIAN HIEROGLYPH AA021;Lo;0;L;;;;;N;;;;; +13424;EGYPTIAN HIEROGLYPH AA022;Lo;0;L;;;;;N;;;;; +13425;EGYPTIAN HIEROGLYPH AA023;Lo;0;L;;;;;N;;;;; +13426;EGYPTIAN HIEROGLYPH AA024;Lo;0;L;;;;;N;;;;; +13427;EGYPTIAN HIEROGLYPH AA025;Lo;0;L;;;;;N;;;;; +13428;EGYPTIAN HIEROGLYPH AA026;Lo;0;L;;;;;N;;;;; +13429;EGYPTIAN HIEROGLYPH AA027;Lo;0;L;;;;;N;;;;; +1342A;EGYPTIAN HIEROGLYPH AA028;Lo;0;L;;;;;N;;;;; +1342B;EGYPTIAN HIEROGLYPH AA029;Lo;0;L;;;;;N;;;;; +1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; +1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; +1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; +1342F;EGYPTIAN HIEROGLYPH V011D;Lo;0;L;;;;;N;;;;; +13430;EGYPTIAN HIEROGLYPH VERTICAL JOINER;Cf;0;L;;;;;N;;;;; +13431;EGYPTIAN HIEROGLYPH HORIZONTAL JOINER;Cf;0;L;;;;;N;;;;; +13432;EGYPTIAN HIEROGLYPH INSERT AT TOP START;Cf;0;L;;;;;N;;;;; +13433;EGYPTIAN HIEROGLYPH INSERT AT BOTTOM START;Cf;0;L;;;;;N;;;;; +13434;EGYPTIAN HIEROGLYPH INSERT AT TOP END;Cf;0;L;;;;;N;;;;; +13435;EGYPTIAN HIEROGLYPH INSERT AT BOTTOM END;Cf;0;L;;;;;N;;;;; +13436;EGYPTIAN HIEROGLYPH OVERLAY MIDDLE;Cf;0;L;;;;;N;;;;; +13437;EGYPTIAN HIEROGLYPH BEGIN SEGMENT;Cf;0;L;;;;;N;;;;; +13438;EGYPTIAN HIEROGLYPH END SEGMENT;Cf;0;L;;;;;N;;;;; +13439;EGYPTIAN HIEROGLYPH INSERT AT MIDDLE;Cf;0;L;;;;;N;;;;; +1343A;EGYPTIAN HIEROGLYPH INSERT AT TOP;Cf;0;L;;;;;N;;;;; +1343B;EGYPTIAN HIEROGLYPH INSERT AT BOTTOM;Cf;0;L;;;;;N;;;;; +1343C;EGYPTIAN HIEROGLYPH BEGIN ENCLOSURE;Cf;0;L;;;;;N;;;;; +1343D;EGYPTIAN HIEROGLYPH END ENCLOSURE;Cf;0;L;;;;;N;;;;; +1343E;EGYPTIAN HIEROGLYPH BEGIN WALLED ENCLOSURE;Cf;0;L;;;;;N;;;;; +1343F;EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE;Cf;0;L;;;;;N;;;;; +13440;EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY;Mn;0;NSM;;;;;N;;;;; +13441;EGYPTIAN HIEROGLYPH FULL BLANK;Lo;0;L;;;;;N;;;;; +13442;EGYPTIAN HIEROGLYPH HALF BLANK;Lo;0;L;;;;;N;;;;; +13443;EGYPTIAN HIEROGLYPH LOST SIGN;Lo;0;L;;;;;N;;;;; +13444;EGYPTIAN HIEROGLYPH HALF LOST SIGN;Lo;0;L;;;;;N;;;;; +13445;EGYPTIAN HIEROGLYPH TALL LOST SIGN;Lo;0;L;;;;;N;;;;; +13446;EGYPTIAN HIEROGLYPH WIDE LOST SIGN;Lo;0;L;;;;;N;;;;; +13447;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START;Mn;0;NSM;;;;;N;;;;; +13448;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT BOTTOM START;Mn;0;NSM;;;;;N;;;;; +13449;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT START;Mn;0;NSM;;;;;N;;;;; +1344A;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP END;Mn;0;NSM;;;;;N;;;;; +1344B;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP;Mn;0;NSM;;;;;N;;;;; +1344C;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT BOTTOM START AND TOP END;Mn;0;NSM;;;;;N;;;;; +1344D;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT START AND TOP;Mn;0;NSM;;;;;N;;;;; +1344E;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT BOTTOM END;Mn;0;NSM;;;;;N;;;;; +1344F;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START AND BOTTOM END;Mn;0;NSM;;;;;N;;;;; +13450;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT BOTTOM;Mn;0;NSM;;;;;N;;;;; +13451;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT START AND BOTTOM;Mn;0;NSM;;;;;N;;;;; +13452;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT END;Mn;0;NSM;;;;;N;;;;; +13453;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP AND END;Mn;0;NSM;;;;;N;;;;; +13454;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT BOTTOM AND END;Mn;0;NSM;;;;;N;;;;; +13455;EGYPTIAN HIEROGLYPH MODIFIER DAMAGED;Mn;0;NSM;;;;;N;;;;; +13460;EGYPTIAN HIEROGLYPH-13460;Lo;0;L;;;;;N;;;;; +13461;EGYPTIAN HIEROGLYPH-13461;Lo;0;L;;;;;N;;;;; +13462;EGYPTIAN HIEROGLYPH-13462;Lo;0;L;;;;;N;;;;; +13463;EGYPTIAN HIEROGLYPH-13463;Lo;0;L;;;;;N;;;;; +13464;EGYPTIAN HIEROGLYPH-13464;Lo;0;L;;;;;N;;;;; +13465;EGYPTIAN HIEROGLYPH-13465;Lo;0;L;;;;;N;;;;; +13466;EGYPTIAN HIEROGLYPH-13466;Lo;0;L;;;;;N;;;;; +13467;EGYPTIAN HIEROGLYPH-13467;Lo;0;L;;;;;N;;;;; +13468;EGYPTIAN HIEROGLYPH-13468;Lo;0;L;;;;;N;;;;; +13469;EGYPTIAN HIEROGLYPH-13469;Lo;0;L;;;;;N;;;;; +1346A;EGYPTIAN HIEROGLYPH-1346A;Lo;0;L;;;;;N;;;;; +1346B;EGYPTIAN HIEROGLYPH-1346B;Lo;0;L;;;;;N;;;;; +1346C;EGYPTIAN HIEROGLYPH-1346C;Lo;0;L;;;;;N;;;;; +1346D;EGYPTIAN HIEROGLYPH-1346D;Lo;0;L;;;;;N;;;;; +1346E;EGYPTIAN HIEROGLYPH-1346E;Lo;0;L;;;;;N;;;;; +1346F;EGYPTIAN HIEROGLYPH-1346F;Lo;0;L;;;;;N;;;;; +13470;EGYPTIAN HIEROGLYPH-13470;Lo;0;L;;;;;N;;;;; +13471;EGYPTIAN HIEROGLYPH-13471;Lo;0;L;;;;;N;;;;; +13472;EGYPTIAN HIEROGLYPH-13472;Lo;0;L;;;;;N;;;;; +13473;EGYPTIAN HIEROGLYPH-13473;Lo;0;L;;;;;N;;;;; +13474;EGYPTIAN HIEROGLYPH-13474;Lo;0;L;;;;;N;;;;; +13475;EGYPTIAN HIEROGLYPH-13475;Lo;0;L;;;;;N;;;;; +13476;EGYPTIAN HIEROGLYPH-13476;Lo;0;L;;;;;N;;;;; +13477;EGYPTIAN HIEROGLYPH-13477;Lo;0;L;;;;;N;;;;; +13478;EGYPTIAN HIEROGLYPH-13478;Lo;0;L;;;;;N;;;;; +13479;EGYPTIAN HIEROGLYPH-13479;Lo;0;L;;;;;N;;;;; +1347A;EGYPTIAN HIEROGLYPH-1347A;Lo;0;L;;;;;N;;;;; +1347B;EGYPTIAN HIEROGLYPH-1347B;Lo;0;L;;;;;N;;;;; +1347C;EGYPTIAN HIEROGLYPH-1347C;Lo;0;L;;;;;N;;;;; +1347D;EGYPTIAN HIEROGLYPH-1347D;Lo;0;L;;;;;N;;;;; +1347E;EGYPTIAN HIEROGLYPH-1347E;Lo;0;L;;;;;N;;;;; +1347F;EGYPTIAN HIEROGLYPH-1347F;Lo;0;L;;;;;N;;;;; +13480;EGYPTIAN HIEROGLYPH-13480;Lo;0;L;;;;;N;;;;; +13481;EGYPTIAN HIEROGLYPH-13481;Lo;0;L;;;;;N;;;;; +13482;EGYPTIAN HIEROGLYPH-13482;Lo;0;L;;;;;N;;;;; +13483;EGYPTIAN HIEROGLYPH-13483;Lo;0;L;;;;;N;;;;; +13484;EGYPTIAN HIEROGLYPH-13484;Lo;0;L;;;;;N;;;;; +13485;EGYPTIAN HIEROGLYPH-13485;Lo;0;L;;;;;N;;;;; +13486;EGYPTIAN HIEROGLYPH-13486;Lo;0;L;;;;;N;;;;; +13487;EGYPTIAN HIEROGLYPH-13487;Lo;0;L;;;;;N;;;;; +13488;EGYPTIAN HIEROGLYPH-13488;Lo;0;L;;;;;N;;;;; +13489;EGYPTIAN HIEROGLYPH-13489;Lo;0;L;;;;;N;;;;; +1348A;EGYPTIAN HIEROGLYPH-1348A;Lo;0;L;;;;;N;;;;; +1348B;EGYPTIAN HIEROGLYPH-1348B;Lo;0;L;;;;;N;;;;; +1348C;EGYPTIAN HIEROGLYPH-1348C;Lo;0;L;;;;;N;;;;; +1348D;EGYPTIAN HIEROGLYPH-1348D;Lo;0;L;;;;;N;;;;; +1348E;EGYPTIAN HIEROGLYPH-1348E;Lo;0;L;;;;;N;;;;; +1348F;EGYPTIAN HIEROGLYPH-1348F;Lo;0;L;;;;;N;;;;; +13490;EGYPTIAN HIEROGLYPH-13490;Lo;0;L;;;;;N;;;;; +13491;EGYPTIAN HIEROGLYPH-13491;Lo;0;L;;;;;N;;;;; +13492;EGYPTIAN HIEROGLYPH-13492;Lo;0;L;;;;;N;;;;; +13493;EGYPTIAN HIEROGLYPH-13493;Lo;0;L;;;;;N;;;;; +13494;EGYPTIAN HIEROGLYPH-13494;Lo;0;L;;;;;N;;;;; +13495;EGYPTIAN HIEROGLYPH-13495;Lo;0;L;;;;;N;;;;; +13496;EGYPTIAN HIEROGLYPH-13496;Lo;0;L;;;;;N;;;;; +13497;EGYPTIAN HIEROGLYPH-13497;Lo;0;L;;;;;N;;;;; +13498;EGYPTIAN HIEROGLYPH-13498;Lo;0;L;;;;;N;;;;; +13499;EGYPTIAN HIEROGLYPH-13499;Lo;0;L;;;;;N;;;;; +1349A;EGYPTIAN HIEROGLYPH-1349A;Lo;0;L;;;;;N;;;;; +1349B;EGYPTIAN HIEROGLYPH-1349B;Lo;0;L;;;;;N;;;;; +1349C;EGYPTIAN HIEROGLYPH-1349C;Lo;0;L;;;;;N;;;;; +1349D;EGYPTIAN HIEROGLYPH-1349D;Lo;0;L;;;;;N;;;;; +1349E;EGYPTIAN HIEROGLYPH-1349E;Lo;0;L;;;;;N;;;;; +1349F;EGYPTIAN HIEROGLYPH-1349F;Lo;0;L;;;;;N;;;;; +134A0;EGYPTIAN HIEROGLYPH-134A0;Lo;0;L;;;;;N;;;;; +134A1;EGYPTIAN HIEROGLYPH-134A1;Lo;0;L;;;;;N;;;;; +134A2;EGYPTIAN HIEROGLYPH-134A2;Lo;0;L;;;;;N;;;;; +134A3;EGYPTIAN HIEROGLYPH-134A3;Lo;0;L;;;;;N;;;;; +134A4;EGYPTIAN HIEROGLYPH-134A4;Lo;0;L;;;;;N;;;;; +134A5;EGYPTIAN HIEROGLYPH-134A5;Lo;0;L;;;;;N;;;;; +134A6;EGYPTIAN HIEROGLYPH-134A6;Lo;0;L;;;;;N;;;;; +134A7;EGYPTIAN HIEROGLYPH-134A7;Lo;0;L;;;;;N;;;;; +134A8;EGYPTIAN HIEROGLYPH-134A8;Lo;0;L;;;;;N;;;;; +134A9;EGYPTIAN HIEROGLYPH-134A9;Lo;0;L;;;;;N;;;;; +134AA;EGYPTIAN HIEROGLYPH-134AA;Lo;0;L;;;;;N;;;;; +134AB;EGYPTIAN HIEROGLYPH-134AB;Lo;0;L;;;;;N;;;;; +134AC;EGYPTIAN HIEROGLYPH-134AC;Lo;0;L;;;;;N;;;;; +134AD;EGYPTIAN HIEROGLYPH-134AD;Lo;0;L;;;;;N;;;;; +134AE;EGYPTIAN HIEROGLYPH-134AE;Lo;0;L;;;;;N;;;;; +134AF;EGYPTIAN HIEROGLYPH-134AF;Lo;0;L;;;;;N;;;;; +134B0;EGYPTIAN HIEROGLYPH-134B0;Lo;0;L;;;;;N;;;;; +134B1;EGYPTIAN HIEROGLYPH-134B1;Lo;0;L;;;;;N;;;;; +134B2;EGYPTIAN HIEROGLYPH-134B2;Lo;0;L;;;;;N;;;;; +134B3;EGYPTIAN HIEROGLYPH-134B3;Lo;0;L;;;;;N;;;;; +134B4;EGYPTIAN HIEROGLYPH-134B4;Lo;0;L;;;;;N;;;;; +134B5;EGYPTIAN HIEROGLYPH-134B5;Lo;0;L;;;;;N;;;;; +134B6;EGYPTIAN HIEROGLYPH-134B6;Lo;0;L;;;;;N;;;;; +134B7;EGYPTIAN HIEROGLYPH-134B7;Lo;0;L;;;;;N;;;;; +134B8;EGYPTIAN HIEROGLYPH-134B8;Lo;0;L;;;;;N;;;;; +134B9;EGYPTIAN HIEROGLYPH-134B9;Lo;0;L;;;;;N;;;;; +134BA;EGYPTIAN HIEROGLYPH-134BA;Lo;0;L;;;;;N;;;;; +134BB;EGYPTIAN HIEROGLYPH-134BB;Lo;0;L;;;;;N;;;;; +134BC;EGYPTIAN HIEROGLYPH-134BC;Lo;0;L;;;;;N;;;;; +134BD;EGYPTIAN HIEROGLYPH-134BD;Lo;0;L;;;;;N;;;;; +134BE;EGYPTIAN HIEROGLYPH-134BE;Lo;0;L;;;;;N;;;;; +134BF;EGYPTIAN HIEROGLYPH-134BF;Lo;0;L;;;;;N;;;;; +134C0;EGYPTIAN HIEROGLYPH-134C0;Lo;0;L;;;;;N;;;;; +134C1;EGYPTIAN HIEROGLYPH-134C1;Lo;0;L;;;;;N;;;;; +134C2;EGYPTIAN HIEROGLYPH-134C2;Lo;0;L;;;;;N;;;;; +134C3;EGYPTIAN HIEROGLYPH-134C3;Lo;0;L;;;;;N;;;;; +134C4;EGYPTIAN HIEROGLYPH-134C4;Lo;0;L;;;;;N;;;;; +134C5;EGYPTIAN HIEROGLYPH-134C5;Lo;0;L;;;;;N;;;;; +134C6;EGYPTIAN HIEROGLYPH-134C6;Lo;0;L;;;;;N;;;;; +134C7;EGYPTIAN HIEROGLYPH-134C7;Lo;0;L;;;;;N;;;;; +134C8;EGYPTIAN HIEROGLYPH-134C8;Lo;0;L;;;;;N;;;;; +134C9;EGYPTIAN HIEROGLYPH-134C9;Lo;0;L;;;;;N;;;;; +134CA;EGYPTIAN HIEROGLYPH-134CA;Lo;0;L;;;;;N;;;;; +134CB;EGYPTIAN HIEROGLYPH-134CB;Lo;0;L;;;;;N;;;;; +134CC;EGYPTIAN HIEROGLYPH-134CC;Lo;0;L;;;;;N;;;;; +134CD;EGYPTIAN HIEROGLYPH-134CD;Lo;0;L;;;;;N;;;;; +134CE;EGYPTIAN HIEROGLYPH-134CE;Lo;0;L;;;;;N;;;;; +134CF;EGYPTIAN HIEROGLYPH-134CF;Lo;0;L;;;;;N;;;;; +134D0;EGYPTIAN HIEROGLYPH-134D0;Lo;0;L;;;;;N;;;;; +134D1;EGYPTIAN HIEROGLYPH-134D1;Lo;0;L;;;;;N;;;;; +134D2;EGYPTIAN HIEROGLYPH-134D2;Lo;0;L;;;;;N;;;;; +134D3;EGYPTIAN HIEROGLYPH-134D3;Lo;0;L;;;;;N;;;;; +134D4;EGYPTIAN HIEROGLYPH-134D4;Lo;0;L;;;;;N;;;;; +134D5;EGYPTIAN HIEROGLYPH-134D5;Lo;0;L;;;;;N;;;;; +134D6;EGYPTIAN HIEROGLYPH-134D6;Lo;0;L;;;;;N;;;;; +134D7;EGYPTIAN HIEROGLYPH-134D7;Lo;0;L;;;;;N;;;;; +134D8;EGYPTIAN HIEROGLYPH-134D8;Lo;0;L;;;;;N;;;;; +134D9;EGYPTIAN HIEROGLYPH-134D9;Lo;0;L;;;;;N;;;;; +134DA;EGYPTIAN HIEROGLYPH-134DA;Lo;0;L;;;;;N;;;;; +134DB;EGYPTIAN HIEROGLYPH-134DB;Lo;0;L;;;;;N;;;;; +134DC;EGYPTIAN HIEROGLYPH-134DC;Lo;0;L;;;;;N;;;;; +134DD;EGYPTIAN HIEROGLYPH-134DD;Lo;0;L;;;;;N;;;;; +134DE;EGYPTIAN HIEROGLYPH-134DE;Lo;0;L;;;;;N;;;;; +134DF;EGYPTIAN HIEROGLYPH-134DF;Lo;0;L;;;;;N;;;;; +134E0;EGYPTIAN HIEROGLYPH-134E0;Lo;0;L;;;;;N;;;;; +134E1;EGYPTIAN HIEROGLYPH-134E1;Lo;0;L;;;;;N;;;;; +134E2;EGYPTIAN HIEROGLYPH-134E2;Lo;0;L;;;;;N;;;;; +134E3;EGYPTIAN HIEROGLYPH-134E3;Lo;0;L;;;;;N;;;;; +134E4;EGYPTIAN HIEROGLYPH-134E4;Lo;0;L;;;;;N;;;;; +134E5;EGYPTIAN HIEROGLYPH-134E5;Lo;0;L;;;;;N;;;;; +134E6;EGYPTIAN HIEROGLYPH-134E6;Lo;0;L;;;;;N;;;;; +134E7;EGYPTIAN HIEROGLYPH-134E7;Lo;0;L;;;;;N;;;;; +134E8;EGYPTIAN HIEROGLYPH-134E8;Lo;0;L;;;;;N;;;;; +134E9;EGYPTIAN HIEROGLYPH-134E9;Lo;0;L;;;;;N;;;;; +134EA;EGYPTIAN HIEROGLYPH-134EA;Lo;0;L;;;;;N;;;;; +134EB;EGYPTIAN HIEROGLYPH-134EB;Lo;0;L;;;;;N;;;;; +134EC;EGYPTIAN HIEROGLYPH-134EC;Lo;0;L;;;;;N;;;;; +134ED;EGYPTIAN HIEROGLYPH-134ED;Lo;0;L;;;;;N;;;;; +134EE;EGYPTIAN HIEROGLYPH-134EE;Lo;0;L;;;;;N;;;;; +134EF;EGYPTIAN HIEROGLYPH-134EF;Lo;0;L;;;;;N;;;;; +134F0;EGYPTIAN HIEROGLYPH-134F0;Lo;0;L;;;;;N;;;;; +134F1;EGYPTIAN HIEROGLYPH-134F1;Lo;0;L;;;;;N;;;;; +134F2;EGYPTIAN HIEROGLYPH-134F2;Lo;0;L;;;;;N;;;;; +134F3;EGYPTIAN HIEROGLYPH-134F3;Lo;0;L;;;;;N;;;;; +134F4;EGYPTIAN HIEROGLYPH-134F4;Lo;0;L;;;;;N;;;;; +134F5;EGYPTIAN HIEROGLYPH-134F5;Lo;0;L;;;;;N;;;;; +134F6;EGYPTIAN HIEROGLYPH-134F6;Lo;0;L;;;;;N;;;;; +134F7;EGYPTIAN HIEROGLYPH-134F7;Lo;0;L;;;;;N;;;;; +134F8;EGYPTIAN HIEROGLYPH-134F8;Lo;0;L;;;;;N;;;;; +134F9;EGYPTIAN HIEROGLYPH-134F9;Lo;0;L;;;;;N;;;;; +134FA;EGYPTIAN HIEROGLYPH-134FA;Lo;0;L;;;;;N;;;;; +134FB;EGYPTIAN HIEROGLYPH-134FB;Lo;0;L;;;;;N;;;;; +134FC;EGYPTIAN HIEROGLYPH-134FC;Lo;0;L;;;;;N;;;;; +134FD;EGYPTIAN HIEROGLYPH-134FD;Lo;0;L;;;;;N;;;;; +134FE;EGYPTIAN HIEROGLYPH-134FE;Lo;0;L;;;;;N;;;;; +134FF;EGYPTIAN HIEROGLYPH-134FF;Lo;0;L;;;;;N;;;;; +13500;EGYPTIAN HIEROGLYPH-13500;Lo;0;L;;;;;N;;;;; +13501;EGYPTIAN HIEROGLYPH-13501;Lo;0;L;;;;;N;;;;; +13502;EGYPTIAN HIEROGLYPH-13502;Lo;0;L;;;;;N;;;;; +13503;EGYPTIAN HIEROGLYPH-13503;Lo;0;L;;;;;N;;;;; +13504;EGYPTIAN HIEROGLYPH-13504;Lo;0;L;;;;;N;;;;; +13505;EGYPTIAN HIEROGLYPH-13505;Lo;0;L;;;;;N;;;;; +13506;EGYPTIAN HIEROGLYPH-13506;Lo;0;L;;;;;N;;;;; +13507;EGYPTIAN HIEROGLYPH-13507;Lo;0;L;;;;;N;;;;; +13508;EGYPTIAN HIEROGLYPH-13508;Lo;0;L;;;;;N;;;;; +13509;EGYPTIAN HIEROGLYPH-13509;Lo;0;L;;;;;N;;;;; +1350A;EGYPTIAN HIEROGLYPH-1350A;Lo;0;L;;;;;N;;;;; +1350B;EGYPTIAN HIEROGLYPH-1350B;Lo;0;L;;;;;N;;;;; +1350C;EGYPTIAN HIEROGLYPH-1350C;Lo;0;L;;;;;N;;;;; +1350D;EGYPTIAN HIEROGLYPH-1350D;Lo;0;L;;;;;N;;;;; +1350E;EGYPTIAN HIEROGLYPH-1350E;Lo;0;L;;;;;N;;;;; +1350F;EGYPTIAN HIEROGLYPH-1350F;Lo;0;L;;;;;N;;;;; +13510;EGYPTIAN HIEROGLYPH-13510;Lo;0;L;;;;;N;;;;; +13511;EGYPTIAN HIEROGLYPH-13511;Lo;0;L;;;;;N;;;;; +13512;EGYPTIAN HIEROGLYPH-13512;Lo;0;L;;;;;N;;;;; +13513;EGYPTIAN HIEROGLYPH-13513;Lo;0;L;;;;;N;;;;; +13514;EGYPTIAN HIEROGLYPH-13514;Lo;0;L;;;;;N;;;;; +13515;EGYPTIAN HIEROGLYPH-13515;Lo;0;L;;;;;N;;;;; +13516;EGYPTIAN HIEROGLYPH-13516;Lo;0;L;;;;;N;;;;; +13517;EGYPTIAN HIEROGLYPH-13517;Lo;0;L;;;;;N;;;;; +13518;EGYPTIAN HIEROGLYPH-13518;Lo;0;L;;;;;N;;;;; +13519;EGYPTIAN HIEROGLYPH-13519;Lo;0;L;;;;;N;;;;; +1351A;EGYPTIAN HIEROGLYPH-1351A;Lo;0;L;;;;;N;;;;; +1351B;EGYPTIAN HIEROGLYPH-1351B;Lo;0;L;;;;;N;;;;; +1351C;EGYPTIAN HIEROGLYPH-1351C;Lo;0;L;;;;;N;;;;; +1351D;EGYPTIAN HIEROGLYPH-1351D;Lo;0;L;;;;;N;;;;; +1351E;EGYPTIAN HIEROGLYPH-1351E;Lo;0;L;;;;;N;;;;; +1351F;EGYPTIAN HIEROGLYPH-1351F;Lo;0;L;;;;;N;;;;; +13520;EGYPTIAN HIEROGLYPH-13520;Lo;0;L;;;;;N;;;;; +13521;EGYPTIAN HIEROGLYPH-13521;Lo;0;L;;;;;N;;;;; +13522;EGYPTIAN HIEROGLYPH-13522;Lo;0;L;;;;;N;;;;; +13523;EGYPTIAN HIEROGLYPH-13523;Lo;0;L;;;;;N;;;;; +13524;EGYPTIAN HIEROGLYPH-13524;Lo;0;L;;;;;N;;;;; +13525;EGYPTIAN HIEROGLYPH-13525;Lo;0;L;;;;;N;;;;; +13526;EGYPTIAN HIEROGLYPH-13526;Lo;0;L;;;;;N;;;;; +13527;EGYPTIAN HIEROGLYPH-13527;Lo;0;L;;;;;N;;;;; +13528;EGYPTIAN HIEROGLYPH-13528;Lo;0;L;;;;;N;;;;; +13529;EGYPTIAN HIEROGLYPH-13529;Lo;0;L;;;;;N;;;;; +1352A;EGYPTIAN HIEROGLYPH-1352A;Lo;0;L;;;;;N;;;;; +1352B;EGYPTIAN HIEROGLYPH-1352B;Lo;0;L;;;;;N;;;;; +1352C;EGYPTIAN HIEROGLYPH-1352C;Lo;0;L;;;;;N;;;;; +1352D;EGYPTIAN HIEROGLYPH-1352D;Lo;0;L;;;;;N;;;;; +1352E;EGYPTIAN HIEROGLYPH-1352E;Lo;0;L;;;;;N;;;;; +1352F;EGYPTIAN HIEROGLYPH-1352F;Lo;0;L;;;;;N;;;;; +13530;EGYPTIAN HIEROGLYPH-13530;Lo;0;L;;;;;N;;;;; +13531;EGYPTIAN HIEROGLYPH-13531;Lo;0;L;;;;;N;;;;; +13532;EGYPTIAN HIEROGLYPH-13532;Lo;0;L;;;;;N;;;;; +13533;EGYPTIAN HIEROGLYPH-13533;Lo;0;L;;;;;N;;;;; +13534;EGYPTIAN HIEROGLYPH-13534;Lo;0;L;;;;;N;;;;; +13535;EGYPTIAN HIEROGLYPH-13535;Lo;0;L;;;;;N;;;;; +13536;EGYPTIAN HIEROGLYPH-13536;Lo;0;L;;;;;N;;;;; +13537;EGYPTIAN HIEROGLYPH-13537;Lo;0;L;;;;;N;;;;; +13538;EGYPTIAN HIEROGLYPH-13538;Lo;0;L;;;;;N;;;;; +13539;EGYPTIAN HIEROGLYPH-13539;Lo;0;L;;;;;N;;;;; +1353A;EGYPTIAN HIEROGLYPH-1353A;Lo;0;L;;;;;N;;;;; +1353B;EGYPTIAN HIEROGLYPH-1353B;Lo;0;L;;;;;N;;;;; +1353C;EGYPTIAN HIEROGLYPH-1353C;Lo;0;L;;;;;N;;;;; +1353D;EGYPTIAN HIEROGLYPH-1353D;Lo;0;L;;;;;N;;;;; +1353E;EGYPTIAN HIEROGLYPH-1353E;Lo;0;L;;;;;N;;;;; +1353F;EGYPTIAN HIEROGLYPH-1353F;Lo;0;L;;;;;N;;;;; +13540;EGYPTIAN HIEROGLYPH-13540;Lo;0;L;;;;;N;;;;; +13541;EGYPTIAN HIEROGLYPH-13541;Lo;0;L;;;;;N;;;;; +13542;EGYPTIAN HIEROGLYPH-13542;Lo;0;L;;;;;N;;;;; +13543;EGYPTIAN HIEROGLYPH-13543;Lo;0;L;;;;;N;;;;; +13544;EGYPTIAN HIEROGLYPH-13544;Lo;0;L;;;;;N;;;;; +13545;EGYPTIAN HIEROGLYPH-13545;Lo;0;L;;;;;N;;;;; +13546;EGYPTIAN HIEROGLYPH-13546;Lo;0;L;;;;;N;;;;; +13547;EGYPTIAN HIEROGLYPH-13547;Lo;0;L;;;;;N;;;;; +13548;EGYPTIAN HIEROGLYPH-13548;Lo;0;L;;;;;N;;;;; +13549;EGYPTIAN HIEROGLYPH-13549;Lo;0;L;;;;;N;;;;; +1354A;EGYPTIAN HIEROGLYPH-1354A;Lo;0;L;;;;;N;;;;; +1354B;EGYPTIAN HIEROGLYPH-1354B;Lo;0;L;;;;;N;;;;; +1354C;EGYPTIAN HIEROGLYPH-1354C;Lo;0;L;;;;;N;;;;; +1354D;EGYPTIAN HIEROGLYPH-1354D;Lo;0;L;;;;;N;;;;; +1354E;EGYPTIAN HIEROGLYPH-1354E;Lo;0;L;;;;;N;;;;; +1354F;EGYPTIAN HIEROGLYPH-1354F;Lo;0;L;;;;;N;;;;; +13550;EGYPTIAN HIEROGLYPH-13550;Lo;0;L;;;;;N;;;;; +13551;EGYPTIAN HIEROGLYPH-13551;Lo;0;L;;;;;N;;;;; +13552;EGYPTIAN HIEROGLYPH-13552;Lo;0;L;;;;;N;;;;; +13553;EGYPTIAN HIEROGLYPH-13553;Lo;0;L;;;;;N;;;;; +13554;EGYPTIAN HIEROGLYPH-13554;Lo;0;L;;;;;N;;;;; +13555;EGYPTIAN HIEROGLYPH-13555;Lo;0;L;;;;;N;;;;; +13556;EGYPTIAN HIEROGLYPH-13556;Lo;0;L;;;;;N;;;;; +13557;EGYPTIAN HIEROGLYPH-13557;Lo;0;L;;;;;N;;;;; +13558;EGYPTIAN HIEROGLYPH-13558;Lo;0;L;;;;;N;;;;; +13559;EGYPTIAN HIEROGLYPH-13559;Lo;0;L;;;;;N;;;;; +1355A;EGYPTIAN HIEROGLYPH-1355A;Lo;0;L;;;;;N;;;;; +1355B;EGYPTIAN HIEROGLYPH-1355B;Lo;0;L;;;;;N;;;;; +1355C;EGYPTIAN HIEROGLYPH-1355C;Lo;0;L;;;;;N;;;;; +1355D;EGYPTIAN HIEROGLYPH-1355D;Lo;0;L;;;;;N;;;;; +1355E;EGYPTIAN HIEROGLYPH-1355E;Lo;0;L;;;;;N;;;;; +1355F;EGYPTIAN HIEROGLYPH-1355F;Lo;0;L;;;;;N;;;;; +13560;EGYPTIAN HIEROGLYPH-13560;Lo;0;L;;;;;N;;;;; +13561;EGYPTIAN HIEROGLYPH-13561;Lo;0;L;;;;;N;;;;; +13562;EGYPTIAN HIEROGLYPH-13562;Lo;0;L;;;;;N;;;;; +13563;EGYPTIAN HIEROGLYPH-13563;Lo;0;L;;;;;N;;;;; +13564;EGYPTIAN HIEROGLYPH-13564;Lo;0;L;;;;;N;;;;; +13565;EGYPTIAN HIEROGLYPH-13565;Lo;0;L;;;;;N;;;;; +13566;EGYPTIAN HIEROGLYPH-13566;Lo;0;L;;;;;N;;;;; +13567;EGYPTIAN HIEROGLYPH-13567;Lo;0;L;;;;;N;;;;; +13568;EGYPTIAN HIEROGLYPH-13568;Lo;0;L;;;;;N;;;;; +13569;EGYPTIAN HIEROGLYPH-13569;Lo;0;L;;;;;N;;;;; +1356A;EGYPTIAN HIEROGLYPH-1356A;Lo;0;L;;;;;N;;;;; +1356B;EGYPTIAN HIEROGLYPH-1356B;Lo;0;L;;;;;N;;;;; +1356C;EGYPTIAN HIEROGLYPH-1356C;Lo;0;L;;;;;N;;;;; +1356D;EGYPTIAN HIEROGLYPH-1356D;Lo;0;L;;;;;N;;;;; +1356E;EGYPTIAN HIEROGLYPH-1356E;Lo;0;L;;;;;N;;;;; +1356F;EGYPTIAN HIEROGLYPH-1356F;Lo;0;L;;;;;N;;;;; +13570;EGYPTIAN HIEROGLYPH-13570;Lo;0;L;;;;;N;;;;; +13571;EGYPTIAN HIEROGLYPH-13571;Lo;0;L;;;;;N;;;;; +13572;EGYPTIAN HIEROGLYPH-13572;Lo;0;L;;;;;N;;;;; +13573;EGYPTIAN HIEROGLYPH-13573;Lo;0;L;;;;;N;;;;; +13574;EGYPTIAN HIEROGLYPH-13574;Lo;0;L;;;;;N;;;;; +13575;EGYPTIAN HIEROGLYPH-13575;Lo;0;L;;;;;N;;;;; +13576;EGYPTIAN HIEROGLYPH-13576;Lo;0;L;;;;;N;;;;; +13577;EGYPTIAN HIEROGLYPH-13577;Lo;0;L;;;;;N;;;;; +13578;EGYPTIAN HIEROGLYPH-13578;Lo;0;L;;;;;N;;;;; +13579;EGYPTIAN HIEROGLYPH-13579;Lo;0;L;;;;;N;;;;; +1357A;EGYPTIAN HIEROGLYPH-1357A;Lo;0;L;;;;;N;;;;; +1357B;EGYPTIAN HIEROGLYPH-1357B;Lo;0;L;;;;;N;;;;; +1357C;EGYPTIAN HIEROGLYPH-1357C;Lo;0;L;;;;;N;;;;; +1357D;EGYPTIAN HIEROGLYPH-1357D;Lo;0;L;;;;;N;;;;; +1357E;EGYPTIAN HIEROGLYPH-1357E;Lo;0;L;;;;;N;;;;; +1357F;EGYPTIAN HIEROGLYPH-1357F;Lo;0;L;;;;;N;;;;; +13580;EGYPTIAN HIEROGLYPH-13580;Lo;0;L;;;;;N;;;;; +13581;EGYPTIAN HIEROGLYPH-13581;Lo;0;L;;;;;N;;;;; +13582;EGYPTIAN HIEROGLYPH-13582;Lo;0;L;;;;;N;;;;; +13583;EGYPTIAN HIEROGLYPH-13583;Lo;0;L;;;;;N;;;;; +13584;EGYPTIAN HIEROGLYPH-13584;Lo;0;L;;;;;N;;;;; +13585;EGYPTIAN HIEROGLYPH-13585;Lo;0;L;;;;;N;;;;; +13586;EGYPTIAN HIEROGLYPH-13586;Lo;0;L;;;;;N;;;;; +13587;EGYPTIAN HIEROGLYPH-13587;Lo;0;L;;;;;N;;;;; +13588;EGYPTIAN HIEROGLYPH-13588;Lo;0;L;;;;;N;;;;; +13589;EGYPTIAN HIEROGLYPH-13589;Lo;0;L;;;;;N;;;;; +1358A;EGYPTIAN HIEROGLYPH-1358A;Lo;0;L;;;;;N;;;;; +1358B;EGYPTIAN HIEROGLYPH-1358B;Lo;0;L;;;;;N;;;;; +1358C;EGYPTIAN HIEROGLYPH-1358C;Lo;0;L;;;;;N;;;;; +1358D;EGYPTIAN HIEROGLYPH-1358D;Lo;0;L;;;;;N;;;;; +1358E;EGYPTIAN HIEROGLYPH-1358E;Lo;0;L;;;;;N;;;;; +1358F;EGYPTIAN HIEROGLYPH-1358F;Lo;0;L;;;;;N;;;;; +13590;EGYPTIAN HIEROGLYPH-13590;Lo;0;L;;;;;N;;;;; +13591;EGYPTIAN HIEROGLYPH-13591;Lo;0;L;;;;;N;;;;; +13592;EGYPTIAN HIEROGLYPH-13592;Lo;0;L;;;;;N;;;;; +13593;EGYPTIAN HIEROGLYPH-13593;Lo;0;L;;;;;N;;;;; +13594;EGYPTIAN HIEROGLYPH-13594;Lo;0;L;;;;;N;;;;; +13595;EGYPTIAN HIEROGLYPH-13595;Lo;0;L;;;;;N;;;;; +13596;EGYPTIAN HIEROGLYPH-13596;Lo;0;L;;;;;N;;;;; +13597;EGYPTIAN HIEROGLYPH-13597;Lo;0;L;;;;;N;;;;; +13598;EGYPTIAN HIEROGLYPH-13598;Lo;0;L;;;;;N;;;;; +13599;EGYPTIAN HIEROGLYPH-13599;Lo;0;L;;;;;N;;;;; +1359A;EGYPTIAN HIEROGLYPH-1359A;Lo;0;L;;;;;N;;;;; +1359B;EGYPTIAN HIEROGLYPH-1359B;Lo;0;L;;;;;N;;;;; +1359C;EGYPTIAN HIEROGLYPH-1359C;Lo;0;L;;;;;N;;;;; +1359D;EGYPTIAN HIEROGLYPH-1359D;Lo;0;L;;;;;N;;;;; +1359E;EGYPTIAN HIEROGLYPH-1359E;Lo;0;L;;;;;N;;;;; +1359F;EGYPTIAN HIEROGLYPH-1359F;Lo;0;L;;;;;N;;;;; +135A0;EGYPTIAN HIEROGLYPH-135A0;Lo;0;L;;;;;N;;;;; +135A1;EGYPTIAN HIEROGLYPH-135A1;Lo;0;L;;;;;N;;;;; +135A2;EGYPTIAN HIEROGLYPH-135A2;Lo;0;L;;;;;N;;;;; +135A3;EGYPTIAN HIEROGLYPH-135A3;Lo;0;L;;;;;N;;;;; +135A4;EGYPTIAN HIEROGLYPH-135A4;Lo;0;L;;;;;N;;;;; +135A5;EGYPTIAN HIEROGLYPH-135A5;Lo;0;L;;;;;N;;;;; +135A6;EGYPTIAN HIEROGLYPH-135A6;Lo;0;L;;;;;N;;;;; +135A7;EGYPTIAN HIEROGLYPH-135A7;Lo;0;L;;;;;N;;;;; +135A8;EGYPTIAN HIEROGLYPH-135A8;Lo;0;L;;;;;N;;;;; +135A9;EGYPTIAN HIEROGLYPH-135A9;Lo;0;L;;;;;N;;;;; +135AA;EGYPTIAN HIEROGLYPH-135AA;Lo;0;L;;;;;N;;;;; +135AB;EGYPTIAN HIEROGLYPH-135AB;Lo;0;L;;;;;N;;;;; +135AC;EGYPTIAN HIEROGLYPH-135AC;Lo;0;L;;;;;N;;;;; +135AD;EGYPTIAN HIEROGLYPH-135AD;Lo;0;L;;;;;N;;;;; +135AE;EGYPTIAN HIEROGLYPH-135AE;Lo;0;L;;;;;N;;;;; +135AF;EGYPTIAN HIEROGLYPH-135AF;Lo;0;L;;;;;N;;;;; +135B0;EGYPTIAN HIEROGLYPH-135B0;Lo;0;L;;;;;N;;;;; +135B1;EGYPTIAN HIEROGLYPH-135B1;Lo;0;L;;;;;N;;;;; +135B2;EGYPTIAN HIEROGLYPH-135B2;Lo;0;L;;;;;N;;;;; +135B3;EGYPTIAN HIEROGLYPH-135B3;Lo;0;L;;;;;N;;;;; +135B4;EGYPTIAN HIEROGLYPH-135B4;Lo;0;L;;;;;N;;;;; +135B5;EGYPTIAN HIEROGLYPH-135B5;Lo;0;L;;;;;N;;;;; +135B6;EGYPTIAN HIEROGLYPH-135B6;Lo;0;L;;;;;N;;;;; +135B7;EGYPTIAN HIEROGLYPH-135B7;Lo;0;L;;;;;N;;;;; +135B8;EGYPTIAN HIEROGLYPH-135B8;Lo;0;L;;;;;N;;;;; +135B9;EGYPTIAN HIEROGLYPH-135B9;Lo;0;L;;;;;N;;;;; +135BA;EGYPTIAN HIEROGLYPH-135BA;Lo;0;L;;;;;N;;;;; +135BB;EGYPTIAN HIEROGLYPH-135BB;Lo;0;L;;;;;N;;;;; +135BC;EGYPTIAN HIEROGLYPH-135BC;Lo;0;L;;;;;N;;;;; +135BD;EGYPTIAN HIEROGLYPH-135BD;Lo;0;L;;;;;N;;;;; +135BE;EGYPTIAN HIEROGLYPH-135BE;Lo;0;L;;;;;N;;;;; +135BF;EGYPTIAN HIEROGLYPH-135BF;Lo;0;L;;;;;N;;;;; +135C0;EGYPTIAN HIEROGLYPH-135C0;Lo;0;L;;;;;N;;;;; +135C1;EGYPTIAN HIEROGLYPH-135C1;Lo;0;L;;;;;N;;;;; +135C2;EGYPTIAN HIEROGLYPH-135C2;Lo;0;L;;;;;N;;;;; +135C3;EGYPTIAN HIEROGLYPH-135C3;Lo;0;L;;;;;N;;;;; +135C4;EGYPTIAN HIEROGLYPH-135C4;Lo;0;L;;;;;N;;;;; +135C5;EGYPTIAN HIEROGLYPH-135C5;Lo;0;L;;;;;N;;;;; +135C6;EGYPTIAN HIEROGLYPH-135C6;Lo;0;L;;;;;N;;;;; +135C7;EGYPTIAN HIEROGLYPH-135C7;Lo;0;L;;;;;N;;;;; +135C8;EGYPTIAN HIEROGLYPH-135C8;Lo;0;L;;;;;N;;;;; +135C9;EGYPTIAN HIEROGLYPH-135C9;Lo;0;L;;;;;N;;;;; +135CA;EGYPTIAN HIEROGLYPH-135CA;Lo;0;L;;;;;N;;;;; +135CB;EGYPTIAN HIEROGLYPH-135CB;Lo;0;L;;;;;N;;;;; +135CC;EGYPTIAN HIEROGLYPH-135CC;Lo;0;L;;;;;N;;;;; +135CD;EGYPTIAN HIEROGLYPH-135CD;Lo;0;L;;;;;N;;;;; +135CE;EGYPTIAN HIEROGLYPH-135CE;Lo;0;L;;;;;N;;;;; +135CF;EGYPTIAN HIEROGLYPH-135CF;Lo;0;L;;;;;N;;;;; +135D0;EGYPTIAN HIEROGLYPH-135D0;Lo;0;L;;;;;N;;;;; +135D1;EGYPTIAN HIEROGLYPH-135D1;Lo;0;L;;;;;N;;;;; +135D2;EGYPTIAN HIEROGLYPH-135D2;Lo;0;L;;;;;N;;;;; +135D3;EGYPTIAN HIEROGLYPH-135D3;Lo;0;L;;;;;N;;;;; +135D4;EGYPTIAN HIEROGLYPH-135D4;Lo;0;L;;;;;N;;;;; +135D5;EGYPTIAN HIEROGLYPH-135D5;Lo;0;L;;;;;N;;;;; +135D6;EGYPTIAN HIEROGLYPH-135D6;Lo;0;L;;;;;N;;;;; +135D7;EGYPTIAN HIEROGLYPH-135D7;Lo;0;L;;;;;N;;;;; +135D8;EGYPTIAN HIEROGLYPH-135D8;Lo;0;L;;;;;N;;;;; +135D9;EGYPTIAN HIEROGLYPH-135D9;Lo;0;L;;;;;N;;;;; +135DA;EGYPTIAN HIEROGLYPH-135DA;Lo;0;L;;;;;N;;;;; +135DB;EGYPTIAN HIEROGLYPH-135DB;Lo;0;L;;;;;N;;;;; +135DC;EGYPTIAN HIEROGLYPH-135DC;Lo;0;L;;;;;N;;;;; +135DD;EGYPTIAN HIEROGLYPH-135DD;Lo;0;L;;;;;N;;;;; +135DE;EGYPTIAN HIEROGLYPH-135DE;Lo;0;L;;;;;N;;;;; +135DF;EGYPTIAN HIEROGLYPH-135DF;Lo;0;L;;;;;N;;;;; +135E0;EGYPTIAN HIEROGLYPH-135E0;Lo;0;L;;;;;N;;;;; +135E1;EGYPTIAN HIEROGLYPH-135E1;Lo;0;L;;;;;N;;;;; +135E2;EGYPTIAN HIEROGLYPH-135E2;Lo;0;L;;;;;N;;;;; +135E3;EGYPTIAN HIEROGLYPH-135E3;Lo;0;L;;;;;N;;;;; +135E4;EGYPTIAN HIEROGLYPH-135E4;Lo;0;L;;;;;N;;;;; +135E5;EGYPTIAN HIEROGLYPH-135E5;Lo;0;L;;;;;N;;;;; +135E6;EGYPTIAN HIEROGLYPH-135E6;Lo;0;L;;;;;N;;;;; +135E7;EGYPTIAN HIEROGLYPH-135E7;Lo;0;L;;;;;N;;;;; +135E8;EGYPTIAN HIEROGLYPH-135E8;Lo;0;L;;;;;N;;;;; +135E9;EGYPTIAN HIEROGLYPH-135E9;Lo;0;L;;;;;N;;;;; +135EA;EGYPTIAN HIEROGLYPH-135EA;Lo;0;L;;;;;N;;;;; +135EB;EGYPTIAN HIEROGLYPH-135EB;Lo;0;L;;;;;N;;;;; +135EC;EGYPTIAN HIEROGLYPH-135EC;Lo;0;L;;;;;N;;;;; +135ED;EGYPTIAN HIEROGLYPH-135ED;Lo;0;L;;;;;N;;;;; +135EE;EGYPTIAN HIEROGLYPH-135EE;Lo;0;L;;;;;N;;;;; +135EF;EGYPTIAN HIEROGLYPH-135EF;Lo;0;L;;;;;N;;;;; +135F0;EGYPTIAN HIEROGLYPH-135F0;Lo;0;L;;;;;N;;;;; +135F1;EGYPTIAN HIEROGLYPH-135F1;Lo;0;L;;;;;N;;;;; +135F2;EGYPTIAN HIEROGLYPH-135F2;Lo;0;L;;;;;N;;;;; +135F3;EGYPTIAN HIEROGLYPH-135F3;Lo;0;L;;;;;N;;;;; +135F4;EGYPTIAN HIEROGLYPH-135F4;Lo;0;L;;;;;N;;;;; +135F5;EGYPTIAN HIEROGLYPH-135F5;Lo;0;L;;;;;N;;;;; +135F6;EGYPTIAN HIEROGLYPH-135F6;Lo;0;L;;;;;N;;;;; +135F7;EGYPTIAN HIEROGLYPH-135F7;Lo;0;L;;;;;N;;;;; +135F8;EGYPTIAN HIEROGLYPH-135F8;Lo;0;L;;;;;N;;;;; +135F9;EGYPTIAN HIEROGLYPH-135F9;Lo;0;L;;;;;N;;;;; +135FA;EGYPTIAN HIEROGLYPH-135FA;Lo;0;L;;;;;N;;;;; +135FB;EGYPTIAN HIEROGLYPH-135FB;Lo;0;L;;;;;N;;;;; +135FC;EGYPTIAN HIEROGLYPH-135FC;Lo;0;L;;;;;N;;;;; +135FD;EGYPTIAN HIEROGLYPH-135FD;Lo;0;L;;;;;N;;;;; +135FE;EGYPTIAN HIEROGLYPH-135FE;Lo;0;L;;;;;N;;;;; +135FF;EGYPTIAN HIEROGLYPH-135FF;Lo;0;L;;;;;N;;;;; +13600;EGYPTIAN HIEROGLYPH-13600;Lo;0;L;;;;;N;;;;; +13601;EGYPTIAN HIEROGLYPH-13601;Lo;0;L;;;;;N;;;;; +13602;EGYPTIAN HIEROGLYPH-13602;Lo;0;L;;;;;N;;;;; +13603;EGYPTIAN HIEROGLYPH-13603;Lo;0;L;;;;;N;;;;; +13604;EGYPTIAN HIEROGLYPH-13604;Lo;0;L;;;;;N;;;;; +13605;EGYPTIAN HIEROGLYPH-13605;Lo;0;L;;;;;N;;;;; +13606;EGYPTIAN HIEROGLYPH-13606;Lo;0;L;;;;;N;;;;; +13607;EGYPTIAN HIEROGLYPH-13607;Lo;0;L;;;;;N;;;;; +13608;EGYPTIAN HIEROGLYPH-13608;Lo;0;L;;;;;N;;;;; +13609;EGYPTIAN HIEROGLYPH-13609;Lo;0;L;;;;;N;;;;; +1360A;EGYPTIAN HIEROGLYPH-1360A;Lo;0;L;;;;;N;;;;; +1360B;EGYPTIAN HIEROGLYPH-1360B;Lo;0;L;;;;;N;;;;; +1360C;EGYPTIAN HIEROGLYPH-1360C;Lo;0;L;;;;;N;;;;; +1360D;EGYPTIAN HIEROGLYPH-1360D;Lo;0;L;;;;;N;;;;; +1360E;EGYPTIAN HIEROGLYPH-1360E;Lo;0;L;;;;;N;;;;; +1360F;EGYPTIAN HIEROGLYPH-1360F;Lo;0;L;;;;;N;;;;; +13610;EGYPTIAN HIEROGLYPH-13610;Lo;0;L;;;;;N;;;;; +13611;EGYPTIAN HIEROGLYPH-13611;Lo;0;L;;;;;N;;;;; +13612;EGYPTIAN HIEROGLYPH-13612;Lo;0;L;;;;;N;;;;; +13613;EGYPTIAN HIEROGLYPH-13613;Lo;0;L;;;;;N;;;;; +13614;EGYPTIAN HIEROGLYPH-13614;Lo;0;L;;;;;N;;;;; +13615;EGYPTIAN HIEROGLYPH-13615;Lo;0;L;;;;;N;;;;; +13616;EGYPTIAN HIEROGLYPH-13616;Lo;0;L;;;;;N;;;;; +13617;EGYPTIAN HIEROGLYPH-13617;Lo;0;L;;;;;N;;;;; +13618;EGYPTIAN HIEROGLYPH-13618;Lo;0;L;;;;;N;;;;; +13619;EGYPTIAN HIEROGLYPH-13619;Lo;0;L;;;;;N;;;;; +1361A;EGYPTIAN HIEROGLYPH-1361A;Lo;0;L;;;;;N;;;;; +1361B;EGYPTIAN HIEROGLYPH-1361B;Lo;0;L;;;;;N;;;;; +1361C;EGYPTIAN HIEROGLYPH-1361C;Lo;0;L;;;;;N;;;;; +1361D;EGYPTIAN HIEROGLYPH-1361D;Lo;0;L;;;;;N;;;;; +1361E;EGYPTIAN HIEROGLYPH-1361E;Lo;0;L;;;;;N;;;;; +1361F;EGYPTIAN HIEROGLYPH-1361F;Lo;0;L;;;;;N;;;;; +13620;EGYPTIAN HIEROGLYPH-13620;Lo;0;L;;;;;N;;;;; +13621;EGYPTIAN HIEROGLYPH-13621;Lo;0;L;;;;;N;;;;; +13622;EGYPTIAN HIEROGLYPH-13622;Lo;0;L;;;;;N;;;;; +13623;EGYPTIAN HIEROGLYPH-13623;Lo;0;L;;;;;N;;;;; +13624;EGYPTIAN HIEROGLYPH-13624;Lo;0;L;;;;;N;;;;; +13625;EGYPTIAN HIEROGLYPH-13625;Lo;0;L;;;;;N;;;;; +13626;EGYPTIAN HIEROGLYPH-13626;Lo;0;L;;;;;N;;;;; +13627;EGYPTIAN HIEROGLYPH-13627;Lo;0;L;;;;;N;;;;; +13628;EGYPTIAN HIEROGLYPH-13628;Lo;0;L;;;;;N;;;;; +13629;EGYPTIAN HIEROGLYPH-13629;Lo;0;L;;;;;N;;;;; +1362A;EGYPTIAN HIEROGLYPH-1362A;Lo;0;L;;;;;N;;;;; +1362B;EGYPTIAN HIEROGLYPH-1362B;Lo;0;L;;;;;N;;;;; +1362C;EGYPTIAN HIEROGLYPH-1362C;Lo;0;L;;;;;N;;;;; +1362D;EGYPTIAN HIEROGLYPH-1362D;Lo;0;L;;;;;N;;;;; +1362E;EGYPTIAN HIEROGLYPH-1362E;Lo;0;L;;;;;N;;;;; +1362F;EGYPTIAN HIEROGLYPH-1362F;Lo;0;L;;;;;N;;;;; +13630;EGYPTIAN HIEROGLYPH-13630;Lo;0;L;;;;;N;;;;; +13631;EGYPTIAN HIEROGLYPH-13631;Lo;0;L;;;;;N;;;;; +13632;EGYPTIAN HIEROGLYPH-13632;Lo;0;L;;;;;N;;;;; +13633;EGYPTIAN HIEROGLYPH-13633;Lo;0;L;;;;;N;;;;; +13634;EGYPTIAN HIEROGLYPH-13634;Lo;0;L;;;;;N;;;;; +13635;EGYPTIAN HIEROGLYPH-13635;Lo;0;L;;;;;N;;;;; +13636;EGYPTIAN HIEROGLYPH-13636;Lo;0;L;;;;;N;;;;; +13637;EGYPTIAN HIEROGLYPH-13637;Lo;0;L;;;;;N;;;;; +13638;EGYPTIAN HIEROGLYPH-13638;Lo;0;L;;;;;N;;;;; +13639;EGYPTIAN HIEROGLYPH-13639;Lo;0;L;;;;;N;;;;; +1363A;EGYPTIAN HIEROGLYPH-1363A;Lo;0;L;;;;;N;;;;; +1363B;EGYPTIAN HIEROGLYPH-1363B;Lo;0;L;;;;;N;;;;; +1363C;EGYPTIAN HIEROGLYPH-1363C;Lo;0;L;;;;;N;;;;; +1363D;EGYPTIAN HIEROGLYPH-1363D;Lo;0;L;;;;;N;;;;; +1363E;EGYPTIAN HIEROGLYPH-1363E;Lo;0;L;;;;;N;;;;; +1363F;EGYPTIAN HIEROGLYPH-1363F;Lo;0;L;;;;;N;;;;; +13640;EGYPTIAN HIEROGLYPH-13640;Lo;0;L;;;;;N;;;;; +13641;EGYPTIAN HIEROGLYPH-13641;Lo;0;L;;;;;N;;;;; +13642;EGYPTIAN HIEROGLYPH-13642;Lo;0;L;;;;;N;;;;; +13643;EGYPTIAN HIEROGLYPH-13643;Lo;0;L;;;;;N;;;;; +13644;EGYPTIAN HIEROGLYPH-13644;Lo;0;L;;;;;N;;;;; +13645;EGYPTIAN HIEROGLYPH-13645;Lo;0;L;;;;;N;;;;; +13646;EGYPTIAN HIEROGLYPH-13646;Lo;0;L;;;;;N;;;;; +13647;EGYPTIAN HIEROGLYPH-13647;Lo;0;L;;;;;N;;;;; +13648;EGYPTIAN HIEROGLYPH-13648;Lo;0;L;;;;;N;;;;; +13649;EGYPTIAN HIEROGLYPH-13649;Lo;0;L;;;;;N;;;;; +1364A;EGYPTIAN HIEROGLYPH-1364A;Lo;0;L;;;;;N;;;;; +1364B;EGYPTIAN HIEROGLYPH-1364B;Lo;0;L;;;;;N;;;;; +1364C;EGYPTIAN HIEROGLYPH-1364C;Lo;0;L;;;;;N;;;;; +1364D;EGYPTIAN HIEROGLYPH-1364D;Lo;0;L;;;;;N;;;;; +1364E;EGYPTIAN HIEROGLYPH-1364E;Lo;0;L;;;;;N;;;;; +1364F;EGYPTIAN HIEROGLYPH-1364F;Lo;0;L;;;;;N;;;;; +13650;EGYPTIAN HIEROGLYPH-13650;Lo;0;L;;;;;N;;;;; +13651;EGYPTIAN HIEROGLYPH-13651;Lo;0;L;;;;;N;;;;; +13652;EGYPTIAN HIEROGLYPH-13652;Lo;0;L;;;;;N;;;;; +13653;EGYPTIAN HIEROGLYPH-13653;Lo;0;L;;;;;N;;;;; +13654;EGYPTIAN HIEROGLYPH-13654;Lo;0;L;;;;;N;;;;; +13655;EGYPTIAN HIEROGLYPH-13655;Lo;0;L;;;;;N;;;;; +13656;EGYPTIAN HIEROGLYPH-13656;Lo;0;L;;;;;N;;;;; +13657;EGYPTIAN HIEROGLYPH-13657;Lo;0;L;;;;;N;;;;; +13658;EGYPTIAN HIEROGLYPH-13658;Lo;0;L;;;;;N;;;;; +13659;EGYPTIAN HIEROGLYPH-13659;Lo;0;L;;;;;N;;;;; +1365A;EGYPTIAN HIEROGLYPH-1365A;Lo;0;L;;;;;N;;;;; +1365B;EGYPTIAN HIEROGLYPH-1365B;Lo;0;L;;;;;N;;;;; +1365C;EGYPTIAN HIEROGLYPH-1365C;Lo;0;L;;;;;N;;;;; +1365D;EGYPTIAN HIEROGLYPH-1365D;Lo;0;L;;;;;N;;;;; +1365E;EGYPTIAN HIEROGLYPH-1365E;Lo;0;L;;;;;N;;;;; +1365F;EGYPTIAN HIEROGLYPH-1365F;Lo;0;L;;;;;N;;;;; +13660;EGYPTIAN HIEROGLYPH-13660;Lo;0;L;;;;;N;;;;; +13661;EGYPTIAN HIEROGLYPH-13661;Lo;0;L;;;;;N;;;;; +13662;EGYPTIAN HIEROGLYPH-13662;Lo;0;L;;;;;N;;;;; +13663;EGYPTIAN HIEROGLYPH-13663;Lo;0;L;;;;;N;;;;; +13664;EGYPTIAN HIEROGLYPH-13664;Lo;0;L;;;;;N;;;;; +13665;EGYPTIAN HIEROGLYPH-13665;Lo;0;L;;;;;N;;;;; +13666;EGYPTIAN HIEROGLYPH-13666;Lo;0;L;;;;;N;;;;; +13667;EGYPTIAN HIEROGLYPH-13667;Lo;0;L;;;;;N;;;;; +13668;EGYPTIAN HIEROGLYPH-13668;Lo;0;L;;;;;N;;;;; +13669;EGYPTIAN HIEROGLYPH-13669;Lo;0;L;;;;;N;;;;; +1366A;EGYPTIAN HIEROGLYPH-1366A;Lo;0;L;;;;;N;;;;; +1366B;EGYPTIAN HIEROGLYPH-1366B;Lo;0;L;;;;;N;;;;; +1366C;EGYPTIAN HIEROGLYPH-1366C;Lo;0;L;;;;;N;;;;; +1366D;EGYPTIAN HIEROGLYPH-1366D;Lo;0;L;;;;;N;;;;; +1366E;EGYPTIAN HIEROGLYPH-1366E;Lo;0;L;;;;;N;;;;; +1366F;EGYPTIAN HIEROGLYPH-1366F;Lo;0;L;;;;;N;;;;; +13670;EGYPTIAN HIEROGLYPH-13670;Lo;0;L;;;;;N;;;;; +13671;EGYPTIAN HIEROGLYPH-13671;Lo;0;L;;;;;N;;;;; +13672;EGYPTIAN HIEROGLYPH-13672;Lo;0;L;;;;;N;;;;; +13673;EGYPTIAN HIEROGLYPH-13673;Lo;0;L;;;;;N;;;;; +13674;EGYPTIAN HIEROGLYPH-13674;Lo;0;L;;;;;N;;;;; +13675;EGYPTIAN HIEROGLYPH-13675;Lo;0;L;;;;;N;;;;; +13676;EGYPTIAN HIEROGLYPH-13676;Lo;0;L;;;;;N;;;;; +13677;EGYPTIAN HIEROGLYPH-13677;Lo;0;L;;;;;N;;;;; +13678;EGYPTIAN HIEROGLYPH-13678;Lo;0;L;;;;;N;;;;; +13679;EGYPTIAN HIEROGLYPH-13679;Lo;0;L;;;;;N;;;;; +1367A;EGYPTIAN HIEROGLYPH-1367A;Lo;0;L;;;;;N;;;;; +1367B;EGYPTIAN HIEROGLYPH-1367B;Lo;0;L;;;;;N;;;;; +1367C;EGYPTIAN HIEROGLYPH-1367C;Lo;0;L;;;;;N;;;;; +1367D;EGYPTIAN HIEROGLYPH-1367D;Lo;0;L;;;;;N;;;;; +1367E;EGYPTIAN HIEROGLYPH-1367E;Lo;0;L;;;;;N;;;;; +1367F;EGYPTIAN HIEROGLYPH-1367F;Lo;0;L;;;;;N;;;;; +13680;EGYPTIAN HIEROGLYPH-13680;Lo;0;L;;;;;N;;;;; +13681;EGYPTIAN HIEROGLYPH-13681;Lo;0;L;;;;;N;;;;; +13682;EGYPTIAN HIEROGLYPH-13682;Lo;0;L;;;;;N;;;;; +13683;EGYPTIAN HIEROGLYPH-13683;Lo;0;L;;;;;N;;;;; +13684;EGYPTIAN HIEROGLYPH-13684;Lo;0;L;;;;;N;;;;; +13685;EGYPTIAN HIEROGLYPH-13685;Lo;0;L;;;;;N;;;;; +13686;EGYPTIAN HIEROGLYPH-13686;Lo;0;L;;;;;N;;;;; +13687;EGYPTIAN HIEROGLYPH-13687;Lo;0;L;;;;;N;;;;; +13688;EGYPTIAN HIEROGLYPH-13688;Lo;0;L;;;;;N;;;;; +13689;EGYPTIAN HIEROGLYPH-13689;Lo;0;L;;;;;N;;;;; +1368A;EGYPTIAN HIEROGLYPH-1368A;Lo;0;L;;;;;N;;;;; +1368B;EGYPTIAN HIEROGLYPH-1368B;Lo;0;L;;;;;N;;;;; +1368C;EGYPTIAN HIEROGLYPH-1368C;Lo;0;L;;;;;N;;;;; +1368D;EGYPTIAN HIEROGLYPH-1368D;Lo;0;L;;;;;N;;;;; +1368E;EGYPTIAN HIEROGLYPH-1368E;Lo;0;L;;;;;N;;;;; +1368F;EGYPTIAN HIEROGLYPH-1368F;Lo;0;L;;;;;N;;;;; +13690;EGYPTIAN HIEROGLYPH-13690;Lo;0;L;;;;;N;;;;; +13691;EGYPTIAN HIEROGLYPH-13691;Lo;0;L;;;;;N;;;;; +13692;EGYPTIAN HIEROGLYPH-13692;Lo;0;L;;;;;N;;;;; +13693;EGYPTIAN HIEROGLYPH-13693;Lo;0;L;;;;;N;;;;; +13694;EGYPTIAN HIEROGLYPH-13694;Lo;0;L;;;;;N;;;;; +13695;EGYPTIAN HIEROGLYPH-13695;Lo;0;L;;;;;N;;;;; +13696;EGYPTIAN HIEROGLYPH-13696;Lo;0;L;;;;;N;;;;; +13697;EGYPTIAN HIEROGLYPH-13697;Lo;0;L;;;;;N;;;;; +13698;EGYPTIAN HIEROGLYPH-13698;Lo;0;L;;;;;N;;;;; +13699;EGYPTIAN HIEROGLYPH-13699;Lo;0;L;;;;;N;;;;; +1369A;EGYPTIAN HIEROGLYPH-1369A;Lo;0;L;;;;;N;;;;; +1369B;EGYPTIAN HIEROGLYPH-1369B;Lo;0;L;;;;;N;;;;; +1369C;EGYPTIAN HIEROGLYPH-1369C;Lo;0;L;;;;;N;;;;; +1369D;EGYPTIAN HIEROGLYPH-1369D;Lo;0;L;;;;;N;;;;; +1369E;EGYPTIAN HIEROGLYPH-1369E;Lo;0;L;;;;;N;;;;; +1369F;EGYPTIAN HIEROGLYPH-1369F;Lo;0;L;;;;;N;;;;; +136A0;EGYPTIAN HIEROGLYPH-136A0;Lo;0;L;;;;;N;;;;; +136A1;EGYPTIAN HIEROGLYPH-136A1;Lo;0;L;;;;;N;;;;; +136A2;EGYPTIAN HIEROGLYPH-136A2;Lo;0;L;;;;;N;;;;; +136A3;EGYPTIAN HIEROGLYPH-136A3;Lo;0;L;;;;;N;;;;; +136A4;EGYPTIAN HIEROGLYPH-136A4;Lo;0;L;;;;;N;;;;; +136A5;EGYPTIAN HIEROGLYPH-136A5;Lo;0;L;;;;;N;;;;; +136A6;EGYPTIAN HIEROGLYPH-136A6;Lo;0;L;;;;;N;;;;; +136A7;EGYPTIAN HIEROGLYPH-136A7;Lo;0;L;;;;;N;;;;; +136A8;EGYPTIAN HIEROGLYPH-136A8;Lo;0;L;;;;;N;;;;; +136A9;EGYPTIAN HIEROGLYPH-136A9;Lo;0;L;;;;;N;;;;; +136AA;EGYPTIAN HIEROGLYPH-136AA;Lo;0;L;;;;;N;;;;; +136AB;EGYPTIAN HIEROGLYPH-136AB;Lo;0;L;;;;;N;;;;; +136AC;EGYPTIAN HIEROGLYPH-136AC;Lo;0;L;;;;;N;;;;; +136AD;EGYPTIAN HIEROGLYPH-136AD;Lo;0;L;;;;;N;;;;; +136AE;EGYPTIAN HIEROGLYPH-136AE;Lo;0;L;;;;;N;;;;; +136AF;EGYPTIAN HIEROGLYPH-136AF;Lo;0;L;;;;;N;;;;; +136B0;EGYPTIAN HIEROGLYPH-136B0;Lo;0;L;;;;;N;;;;; +136B1;EGYPTIAN HIEROGLYPH-136B1;Lo;0;L;;;;;N;;;;; +136B2;EGYPTIAN HIEROGLYPH-136B2;Lo;0;L;;;;;N;;;;; +136B3;EGYPTIAN HIEROGLYPH-136B3;Lo;0;L;;;;;N;;;;; +136B4;EGYPTIAN HIEROGLYPH-136B4;Lo;0;L;;;;;N;;;;; +136B5;EGYPTIAN HIEROGLYPH-136B5;Lo;0;L;;;;;N;;;;; +136B6;EGYPTIAN HIEROGLYPH-136B6;Lo;0;L;;;;;N;;;;; +136B7;EGYPTIAN HIEROGLYPH-136B7;Lo;0;L;;;;;N;;;;; +136B8;EGYPTIAN HIEROGLYPH-136B8;Lo;0;L;;;;;N;;;;; +136B9;EGYPTIAN HIEROGLYPH-136B9;Lo;0;L;;;;;N;;;;; +136BA;EGYPTIAN HIEROGLYPH-136BA;Lo;0;L;;;;;N;;;;; +136BB;EGYPTIAN HIEROGLYPH-136BB;Lo;0;L;;;;;N;;;;; +136BC;EGYPTIAN HIEROGLYPH-136BC;Lo;0;L;;;;;N;;;;; +136BD;EGYPTIAN HIEROGLYPH-136BD;Lo;0;L;;;;;N;;;;; +136BE;EGYPTIAN HIEROGLYPH-136BE;Lo;0;L;;;;;N;;;;; +136BF;EGYPTIAN HIEROGLYPH-136BF;Lo;0;L;;;;;N;;;;; +136C0;EGYPTIAN HIEROGLYPH-136C0;Lo;0;L;;;;;N;;;;; +136C1;EGYPTIAN HIEROGLYPH-136C1;Lo;0;L;;;;;N;;;;; +136C2;EGYPTIAN HIEROGLYPH-136C2;Lo;0;L;;;;;N;;;;; +136C3;EGYPTIAN HIEROGLYPH-136C3;Lo;0;L;;;;;N;;;;; +136C4;EGYPTIAN HIEROGLYPH-136C4;Lo;0;L;;;;;N;;;;; +136C5;EGYPTIAN HIEROGLYPH-136C5;Lo;0;L;;;;;N;;;;; +136C6;EGYPTIAN HIEROGLYPH-136C6;Lo;0;L;;;;;N;;;;; +136C7;EGYPTIAN HIEROGLYPH-136C7;Lo;0;L;;;;;N;;;;; +136C8;EGYPTIAN HIEROGLYPH-136C8;Lo;0;L;;;;;N;;;;; +136C9;EGYPTIAN HIEROGLYPH-136C9;Lo;0;L;;;;;N;;;;; +136CA;EGYPTIAN HIEROGLYPH-136CA;Lo;0;L;;;;;N;;;;; +136CB;EGYPTIAN HIEROGLYPH-136CB;Lo;0;L;;;;;N;;;;; +136CC;EGYPTIAN HIEROGLYPH-136CC;Lo;0;L;;;;;N;;;;; +136CD;EGYPTIAN HIEROGLYPH-136CD;Lo;0;L;;;;;N;;;;; +136CE;EGYPTIAN HIEROGLYPH-136CE;Lo;0;L;;;;;N;;;;; +136CF;EGYPTIAN HIEROGLYPH-136CF;Lo;0;L;;;;;N;;;;; +136D0;EGYPTIAN HIEROGLYPH-136D0;Lo;0;L;;;;;N;;;;; +136D1;EGYPTIAN HIEROGLYPH-136D1;Lo;0;L;;;;;N;;;;; +136D2;EGYPTIAN HIEROGLYPH-136D2;Lo;0;L;;;;;N;;;;; +136D3;EGYPTIAN HIEROGLYPH-136D3;Lo;0;L;;;;;N;;;;; +136D4;EGYPTIAN HIEROGLYPH-136D4;Lo;0;L;;;;;N;;;;; +136D5;EGYPTIAN HIEROGLYPH-136D5;Lo;0;L;;;;;N;;;;; +136D6;EGYPTIAN HIEROGLYPH-136D6;Lo;0;L;;;;;N;;;;; +136D7;EGYPTIAN HIEROGLYPH-136D7;Lo;0;L;;;;;N;;;;; +136D8;EGYPTIAN HIEROGLYPH-136D8;Lo;0;L;;;;;N;;;;; +136D9;EGYPTIAN HIEROGLYPH-136D9;Lo;0;L;;;;;N;;;;; +136DA;EGYPTIAN HIEROGLYPH-136DA;Lo;0;L;;;;;N;;;;; +136DB;EGYPTIAN HIEROGLYPH-136DB;Lo;0;L;;;;;N;;;;; +136DC;EGYPTIAN HIEROGLYPH-136DC;Lo;0;L;;;;;N;;;;; +136DD;EGYPTIAN HIEROGLYPH-136DD;Lo;0;L;;;;;N;;;;; +136DE;EGYPTIAN HIEROGLYPH-136DE;Lo;0;L;;;;;N;;;;; +136DF;EGYPTIAN HIEROGLYPH-136DF;Lo;0;L;;;;;N;;;;; +136E0;EGYPTIAN HIEROGLYPH-136E0;Lo;0;L;;;;;N;;;;; +136E1;EGYPTIAN HIEROGLYPH-136E1;Lo;0;L;;;;;N;;;;; +136E2;EGYPTIAN HIEROGLYPH-136E2;Lo;0;L;;;;;N;;;;; +136E3;EGYPTIAN HIEROGLYPH-136E3;Lo;0;L;;;;;N;;;;; +136E4;EGYPTIAN HIEROGLYPH-136E4;Lo;0;L;;;;;N;;;;; +136E5;EGYPTIAN HIEROGLYPH-136E5;Lo;0;L;;;;;N;;;;; +136E6;EGYPTIAN HIEROGLYPH-136E6;Lo;0;L;;;;;N;;;;; +136E7;EGYPTIAN HIEROGLYPH-136E7;Lo;0;L;;;;;N;;;;; +136E8;EGYPTIAN HIEROGLYPH-136E8;Lo;0;L;;;;;N;;;;; +136E9;EGYPTIAN HIEROGLYPH-136E9;Lo;0;L;;;;;N;;;;; +136EA;EGYPTIAN HIEROGLYPH-136EA;Lo;0;L;;;;;N;;;;; +136EB;EGYPTIAN HIEROGLYPH-136EB;Lo;0;L;;;;;N;;;;; +136EC;EGYPTIAN HIEROGLYPH-136EC;Lo;0;L;;;;;N;;;;; +136ED;EGYPTIAN HIEROGLYPH-136ED;Lo;0;L;;;;;N;;;;; +136EE;EGYPTIAN HIEROGLYPH-136EE;Lo;0;L;;;;;N;;;;; +136EF;EGYPTIAN HIEROGLYPH-136EF;Lo;0;L;;;;;N;;;;; +136F0;EGYPTIAN HIEROGLYPH-136F0;Lo;0;L;;;;;N;;;;; +136F1;EGYPTIAN HIEROGLYPH-136F1;Lo;0;L;;;;;N;;;;; +136F2;EGYPTIAN HIEROGLYPH-136F2;Lo;0;L;;;;;N;;;;; +136F3;EGYPTIAN HIEROGLYPH-136F3;Lo;0;L;;;;;N;;;;; +136F4;EGYPTIAN HIEROGLYPH-136F4;Lo;0;L;;;;;N;;;;; +136F5;EGYPTIAN HIEROGLYPH-136F5;Lo;0;L;;;;;N;;;;; +136F6;EGYPTIAN HIEROGLYPH-136F6;Lo;0;L;;;;;N;;;;; +136F7;EGYPTIAN HIEROGLYPH-136F7;Lo;0;L;;;;;N;;;;; +136F8;EGYPTIAN HIEROGLYPH-136F8;Lo;0;L;;;;;N;;;;; +136F9;EGYPTIAN HIEROGLYPH-136F9;Lo;0;L;;;;;N;;;;; +136FA;EGYPTIAN HIEROGLYPH-136FA;Lo;0;L;;;;;N;;;;; +136FB;EGYPTIAN HIEROGLYPH-136FB;Lo;0;L;;;;;N;;;;; +136FC;EGYPTIAN HIEROGLYPH-136FC;Lo;0;L;;;;;N;;;;; +136FD;EGYPTIAN HIEROGLYPH-136FD;Lo;0;L;;;;;N;;;;; +136FE;EGYPTIAN HIEROGLYPH-136FE;Lo;0;L;;;;;N;;;;; +136FF;EGYPTIAN HIEROGLYPH-136FF;Lo;0;L;;;;;N;;;;; +13700;EGYPTIAN HIEROGLYPH-13700;Lo;0;L;;;;;N;;;;; +13701;EGYPTIAN HIEROGLYPH-13701;Lo;0;L;;;;;N;;;;; +13702;EGYPTIAN HIEROGLYPH-13702;Lo;0;L;;;;;N;;;;; +13703;EGYPTIAN HIEROGLYPH-13703;Lo;0;L;;;;;N;;;;; +13704;EGYPTIAN HIEROGLYPH-13704;Lo;0;L;;;;;N;;;;; +13705;EGYPTIAN HIEROGLYPH-13705;Lo;0;L;;;;;N;;;;; +13706;EGYPTIAN HIEROGLYPH-13706;Lo;0;L;;;;;N;;;;; +13707;EGYPTIAN HIEROGLYPH-13707;Lo;0;L;;;;;N;;;;; +13708;EGYPTIAN HIEROGLYPH-13708;Lo;0;L;;;;;N;;;;; +13709;EGYPTIAN HIEROGLYPH-13709;Lo;0;L;;;;;N;;;;; +1370A;EGYPTIAN HIEROGLYPH-1370A;Lo;0;L;;;;;N;;;;; +1370B;EGYPTIAN HIEROGLYPH-1370B;Lo;0;L;;;;;N;;;;; +1370C;EGYPTIAN HIEROGLYPH-1370C;Lo;0;L;;;;;N;;;;; +1370D;EGYPTIAN HIEROGLYPH-1370D;Lo;0;L;;;;;N;;;;; +1370E;EGYPTIAN HIEROGLYPH-1370E;Lo;0;L;;;;;N;;;;; +1370F;EGYPTIAN HIEROGLYPH-1370F;Lo;0;L;;;;;N;;;;; +13710;EGYPTIAN HIEROGLYPH-13710;Lo;0;L;;;;;N;;;;; +13711;EGYPTIAN HIEROGLYPH-13711;Lo;0;L;;;;;N;;;;; +13712;EGYPTIAN HIEROGLYPH-13712;Lo;0;L;;;;;N;;;;; +13713;EGYPTIAN HIEROGLYPH-13713;Lo;0;L;;;;;N;;;;; +13714;EGYPTIAN HIEROGLYPH-13714;Lo;0;L;;;;;N;;;;; +13715;EGYPTIAN HIEROGLYPH-13715;Lo;0;L;;;;;N;;;;; +13716;EGYPTIAN HIEROGLYPH-13716;Lo;0;L;;;;;N;;;;; +13717;EGYPTIAN HIEROGLYPH-13717;Lo;0;L;;;;;N;;;;; +13718;EGYPTIAN HIEROGLYPH-13718;Lo;0;L;;;;;N;;;;; +13719;EGYPTIAN HIEROGLYPH-13719;Lo;0;L;;;;;N;;;;; +1371A;EGYPTIAN HIEROGLYPH-1371A;Lo;0;L;;;;;N;;;;; +1371B;EGYPTIAN HIEROGLYPH-1371B;Lo;0;L;;;;;N;;;;; +1371C;EGYPTIAN HIEROGLYPH-1371C;Lo;0;L;;;;;N;;;;; +1371D;EGYPTIAN HIEROGLYPH-1371D;Lo;0;L;;;;;N;;;;; +1371E;EGYPTIAN HIEROGLYPH-1371E;Lo;0;L;;;;;N;;;;; +1371F;EGYPTIAN HIEROGLYPH-1371F;Lo;0;L;;;;;N;;;;; +13720;EGYPTIAN HIEROGLYPH-13720;Lo;0;L;;;;;N;;;;; +13721;EGYPTIAN HIEROGLYPH-13721;Lo;0;L;;;;;N;;;;; +13722;EGYPTIAN HIEROGLYPH-13722;Lo;0;L;;;;;N;;;;; +13723;EGYPTIAN HIEROGLYPH-13723;Lo;0;L;;;;;N;;;;; +13724;EGYPTIAN HIEROGLYPH-13724;Lo;0;L;;;;;N;;;;; +13725;EGYPTIAN HIEROGLYPH-13725;Lo;0;L;;;;;N;;;;; +13726;EGYPTIAN HIEROGLYPH-13726;Lo;0;L;;;;;N;;;;; +13727;EGYPTIAN HIEROGLYPH-13727;Lo;0;L;;;;;N;;;;; +13728;EGYPTIAN HIEROGLYPH-13728;Lo;0;L;;;;;N;;;;; +13729;EGYPTIAN HIEROGLYPH-13729;Lo;0;L;;;;;N;;;;; +1372A;EGYPTIAN HIEROGLYPH-1372A;Lo;0;L;;;;;N;;;;; +1372B;EGYPTIAN HIEROGLYPH-1372B;Lo;0;L;;;;;N;;;;; +1372C;EGYPTIAN HIEROGLYPH-1372C;Lo;0;L;;;;;N;;;;; +1372D;EGYPTIAN HIEROGLYPH-1372D;Lo;0;L;;;;;N;;;;; +1372E;EGYPTIAN HIEROGLYPH-1372E;Lo;0;L;;;;;N;;;;; +1372F;EGYPTIAN HIEROGLYPH-1372F;Lo;0;L;;;;;N;;;;; +13730;EGYPTIAN HIEROGLYPH-13730;Lo;0;L;;;;;N;;;;; +13731;EGYPTIAN HIEROGLYPH-13731;Lo;0;L;;;;;N;;;;; +13732;EGYPTIAN HIEROGLYPH-13732;Lo;0;L;;;;;N;;;;; +13733;EGYPTIAN HIEROGLYPH-13733;Lo;0;L;;;;;N;;;;; +13734;EGYPTIAN HIEROGLYPH-13734;Lo;0;L;;;;;N;;;;; +13735;EGYPTIAN HIEROGLYPH-13735;Lo;0;L;;;;;N;;;;; +13736;EGYPTIAN HIEROGLYPH-13736;Lo;0;L;;;;;N;;;;; +13737;EGYPTIAN HIEROGLYPH-13737;Lo;0;L;;;;;N;;;;; +13738;EGYPTIAN HIEROGLYPH-13738;Lo;0;L;;;;;N;;;;; +13739;EGYPTIAN HIEROGLYPH-13739;Lo;0;L;;;;;N;;;;; +1373A;EGYPTIAN HIEROGLYPH-1373A;Lo;0;L;;;;;N;;;;; +1373B;EGYPTIAN HIEROGLYPH-1373B;Lo;0;L;;;;;N;;;;; +1373C;EGYPTIAN HIEROGLYPH-1373C;Lo;0;L;;;;;N;;;;; +1373D;EGYPTIAN HIEROGLYPH-1373D;Lo;0;L;;;;;N;;;;; +1373E;EGYPTIAN HIEROGLYPH-1373E;Lo;0;L;;;;;N;;;;; +1373F;EGYPTIAN HIEROGLYPH-1373F;Lo;0;L;;;;;N;;;;; +13740;EGYPTIAN HIEROGLYPH-13740;Lo;0;L;;;;;N;;;;; +13741;EGYPTIAN HIEROGLYPH-13741;Lo;0;L;;;;;N;;;;; +13742;EGYPTIAN HIEROGLYPH-13742;Lo;0;L;;;;;N;;;;; +13743;EGYPTIAN HIEROGLYPH-13743;Lo;0;L;;;;;N;;;;; +13744;EGYPTIAN HIEROGLYPH-13744;Lo;0;L;;;;;N;;;;; +13745;EGYPTIAN HIEROGLYPH-13745;Lo;0;L;;;;;N;;;;; +13746;EGYPTIAN HIEROGLYPH-13746;Lo;0;L;;;;;N;;;;; +13747;EGYPTIAN HIEROGLYPH-13747;Lo;0;L;;;;;N;;;;; +13748;EGYPTIAN HIEROGLYPH-13748;Lo;0;L;;;;;N;;;;; +13749;EGYPTIAN HIEROGLYPH-13749;Lo;0;L;;;;;N;;;;; +1374A;EGYPTIAN HIEROGLYPH-1374A;Lo;0;L;;;;;N;;;;; +1374B;EGYPTIAN HIEROGLYPH-1374B;Lo;0;L;;;;;N;;;;; +1374C;EGYPTIAN HIEROGLYPH-1374C;Lo;0;L;;;;;N;;;;; +1374D;EGYPTIAN HIEROGLYPH-1374D;Lo;0;L;;;;;N;;;;; +1374E;EGYPTIAN HIEROGLYPH-1374E;Lo;0;L;;;;;N;;;;; +1374F;EGYPTIAN HIEROGLYPH-1374F;Lo;0;L;;;;;N;;;;; +13750;EGYPTIAN HIEROGLYPH-13750;Lo;0;L;;;;;N;;;;; +13751;EGYPTIAN HIEROGLYPH-13751;Lo;0;L;;;;;N;;;;; +13752;EGYPTIAN HIEROGLYPH-13752;Lo;0;L;;;;;N;;;;; +13753;EGYPTIAN HIEROGLYPH-13753;Lo;0;L;;;;;N;;;;; +13754;EGYPTIAN HIEROGLYPH-13754;Lo;0;L;;;;;N;;;;; +13755;EGYPTIAN HIEROGLYPH-13755;Lo;0;L;;;;;N;;;;; +13756;EGYPTIAN HIEROGLYPH-13756;Lo;0;L;;;;;N;;;;; +13757;EGYPTIAN HIEROGLYPH-13757;Lo;0;L;;;;;N;;;;; +13758;EGYPTIAN HIEROGLYPH-13758;Lo;0;L;;;;;N;;;;; +13759;EGYPTIAN HIEROGLYPH-13759;Lo;0;L;;;;;N;;;;; +1375A;EGYPTIAN HIEROGLYPH-1375A;Lo;0;L;;;;;N;;;;; +1375B;EGYPTIAN HIEROGLYPH-1375B;Lo;0;L;;;;;N;;;;; +1375C;EGYPTIAN HIEROGLYPH-1375C;Lo;0;L;;;;;N;;;;; +1375D;EGYPTIAN HIEROGLYPH-1375D;Lo;0;L;;;;;N;;;;; +1375E;EGYPTIAN HIEROGLYPH-1375E;Lo;0;L;;;;;N;;;;; +1375F;EGYPTIAN HIEROGLYPH-1375F;Lo;0;L;;;;;N;;;;; +13760;EGYPTIAN HIEROGLYPH-13760;Lo;0;L;;;;;N;;;;; +13761;EGYPTIAN HIEROGLYPH-13761;Lo;0;L;;;;;N;;;;; +13762;EGYPTIAN HIEROGLYPH-13762;Lo;0;L;;;;;N;;;;; +13763;EGYPTIAN HIEROGLYPH-13763;Lo;0;L;;;;;N;;;;; +13764;EGYPTIAN HIEROGLYPH-13764;Lo;0;L;;;;;N;;;;; +13765;EGYPTIAN HIEROGLYPH-13765;Lo;0;L;;;;;N;;;;; +13766;EGYPTIAN HIEROGLYPH-13766;Lo;0;L;;;;;N;;;;; +13767;EGYPTIAN HIEROGLYPH-13767;Lo;0;L;;;;;N;;;;; +13768;EGYPTIAN HIEROGLYPH-13768;Lo;0;L;;;;;N;;;;; +13769;EGYPTIAN HIEROGLYPH-13769;Lo;0;L;;;;;N;;;;; +1376A;EGYPTIAN HIEROGLYPH-1376A;Lo;0;L;;;;;N;;;;; +1376B;EGYPTIAN HIEROGLYPH-1376B;Lo;0;L;;;;;N;;;;; +1376C;EGYPTIAN HIEROGLYPH-1376C;Lo;0;L;;;;;N;;;;; +1376D;EGYPTIAN HIEROGLYPH-1376D;Lo;0;L;;;;;N;;;;; +1376E;EGYPTIAN HIEROGLYPH-1376E;Lo;0;L;;;;;N;;;;; +1376F;EGYPTIAN HIEROGLYPH-1376F;Lo;0;L;;;;;N;;;;; +13770;EGYPTIAN HIEROGLYPH-13770;Lo;0;L;;;;;N;;;;; +13771;EGYPTIAN HIEROGLYPH-13771;Lo;0;L;;;;;N;;;;; +13772;EGYPTIAN HIEROGLYPH-13772;Lo;0;L;;;;;N;;;;; +13773;EGYPTIAN HIEROGLYPH-13773;Lo;0;L;;;;;N;;;;; +13774;EGYPTIAN HIEROGLYPH-13774;Lo;0;L;;;;;N;;;;; +13775;EGYPTIAN HIEROGLYPH-13775;Lo;0;L;;;;;N;;;;; +13776;EGYPTIAN HIEROGLYPH-13776;Lo;0;L;;;;;N;;;;; +13777;EGYPTIAN HIEROGLYPH-13777;Lo;0;L;;;;;N;;;;; +13778;EGYPTIAN HIEROGLYPH-13778;Lo;0;L;;;;;N;;;;; +13779;EGYPTIAN HIEROGLYPH-13779;Lo;0;L;;;;;N;;;;; +1377A;EGYPTIAN HIEROGLYPH-1377A;Lo;0;L;;;;;N;;;;; +1377B;EGYPTIAN HIEROGLYPH-1377B;Lo;0;L;;;;;N;;;;; +1377C;EGYPTIAN HIEROGLYPH-1377C;Lo;0;L;;;;;N;;;;; +1377D;EGYPTIAN HIEROGLYPH-1377D;Lo;0;L;;;;;N;;;;; +1377E;EGYPTIAN HIEROGLYPH-1377E;Lo;0;L;;;;;N;;;;; +1377F;EGYPTIAN HIEROGLYPH-1377F;Lo;0;L;;;;;N;;;;; +13780;EGYPTIAN HIEROGLYPH-13780;Lo;0;L;;;;;N;;;;; +13781;EGYPTIAN HIEROGLYPH-13781;Lo;0;L;;;;;N;;;;; +13782;EGYPTIAN HIEROGLYPH-13782;Lo;0;L;;;;;N;;;;; +13783;EGYPTIAN HIEROGLYPH-13783;Lo;0;L;;;;;N;;;;; +13784;EGYPTIAN HIEROGLYPH-13784;Lo;0;L;;;;;N;;;;; +13785;EGYPTIAN HIEROGLYPH-13785;Lo;0;L;;;;;N;;;;; +13786;EGYPTIAN HIEROGLYPH-13786;Lo;0;L;;;;;N;;;;; +13787;EGYPTIAN HIEROGLYPH-13787;Lo;0;L;;;;;N;;;;; +13788;EGYPTIAN HIEROGLYPH-13788;Lo;0;L;;;;;N;;;;; +13789;EGYPTIAN HIEROGLYPH-13789;Lo;0;L;;;;;N;;;;; +1378A;EGYPTIAN HIEROGLYPH-1378A;Lo;0;L;;;;;N;;;;; +1378B;EGYPTIAN HIEROGLYPH-1378B;Lo;0;L;;;;;N;;;;; +1378C;EGYPTIAN HIEROGLYPH-1378C;Lo;0;L;;;;;N;;;;; +1378D;EGYPTIAN HIEROGLYPH-1378D;Lo;0;L;;;;;N;;;;; +1378E;EGYPTIAN HIEROGLYPH-1378E;Lo;0;L;;;;;N;;;;; +1378F;EGYPTIAN HIEROGLYPH-1378F;Lo;0;L;;;;;N;;;;; +13790;EGYPTIAN HIEROGLYPH-13790;Lo;0;L;;;;;N;;;;; +13791;EGYPTIAN HIEROGLYPH-13791;Lo;0;L;;;;;N;;;;; +13792;EGYPTIAN HIEROGLYPH-13792;Lo;0;L;;;;;N;;;;; +13793;EGYPTIAN HIEROGLYPH-13793;Lo;0;L;;;;;N;;;;; +13794;EGYPTIAN HIEROGLYPH-13794;Lo;0;L;;;;;N;;;;; +13795;EGYPTIAN HIEROGLYPH-13795;Lo;0;L;;;;;N;;;;; +13796;EGYPTIAN HIEROGLYPH-13796;Lo;0;L;;;;;N;;;;; +13797;EGYPTIAN HIEROGLYPH-13797;Lo;0;L;;;;;N;;;;; +13798;EGYPTIAN HIEROGLYPH-13798;Lo;0;L;;;;;N;;;;; +13799;EGYPTIAN HIEROGLYPH-13799;Lo;0;L;;;;;N;;;;; +1379A;EGYPTIAN HIEROGLYPH-1379A;Lo;0;L;;;;;N;;;;; +1379B;EGYPTIAN HIEROGLYPH-1379B;Lo;0;L;;;;;N;;;;; +1379C;EGYPTIAN HIEROGLYPH-1379C;Lo;0;L;;;;;N;;;;; +1379D;EGYPTIAN HIEROGLYPH-1379D;Lo;0;L;;;;;N;;;;; +1379E;EGYPTIAN HIEROGLYPH-1379E;Lo;0;L;;;;;N;;;;; +1379F;EGYPTIAN HIEROGLYPH-1379F;Lo;0;L;;;;;N;;;;; +137A0;EGYPTIAN HIEROGLYPH-137A0;Lo;0;L;;;;;N;;;;; +137A1;EGYPTIAN HIEROGLYPH-137A1;Lo;0;L;;;;;N;;;;; +137A2;EGYPTIAN HIEROGLYPH-137A2;Lo;0;L;;;;;N;;;;; +137A3;EGYPTIAN HIEROGLYPH-137A3;Lo;0;L;;;;;N;;;;; +137A4;EGYPTIAN HIEROGLYPH-137A4;Lo;0;L;;;;;N;;;;; +137A5;EGYPTIAN HIEROGLYPH-137A5;Lo;0;L;;;;;N;;;;; +137A6;EGYPTIAN HIEROGLYPH-137A6;Lo;0;L;;;;;N;;;;; +137A7;EGYPTIAN HIEROGLYPH-137A7;Lo;0;L;;;;;N;;;;; +137A8;EGYPTIAN HIEROGLYPH-137A8;Lo;0;L;;;;;N;;;;; +137A9;EGYPTIAN HIEROGLYPH-137A9;Lo;0;L;;;;;N;;;;; +137AA;EGYPTIAN HIEROGLYPH-137AA;Lo;0;L;;;;;N;;;;; +137AB;EGYPTIAN HIEROGLYPH-137AB;Lo;0;L;;;;;N;;;;; +137AC;EGYPTIAN HIEROGLYPH-137AC;Lo;0;L;;;;;N;;;;; +137AD;EGYPTIAN HIEROGLYPH-137AD;Lo;0;L;;;;;N;;;;; +137AE;EGYPTIAN HIEROGLYPH-137AE;Lo;0;L;;;;;N;;;;; +137AF;EGYPTIAN HIEROGLYPH-137AF;Lo;0;L;;;;;N;;;;; +137B0;EGYPTIAN HIEROGLYPH-137B0;Lo;0;L;;;;;N;;;;; +137B1;EGYPTIAN HIEROGLYPH-137B1;Lo;0;L;;;;;N;;;;; +137B2;EGYPTIAN HIEROGLYPH-137B2;Lo;0;L;;;;;N;;;;; +137B3;EGYPTIAN HIEROGLYPH-137B3;Lo;0;L;;;;;N;;;;; +137B4;EGYPTIAN HIEROGLYPH-137B4;Lo;0;L;;;;;N;;;;; +137B5;EGYPTIAN HIEROGLYPH-137B5;Lo;0;L;;;;;N;;;;; +137B6;EGYPTIAN HIEROGLYPH-137B6;Lo;0;L;;;;;N;;;;; +137B7;EGYPTIAN HIEROGLYPH-137B7;Lo;0;L;;;;;N;;;;; +137B8;EGYPTIAN HIEROGLYPH-137B8;Lo;0;L;;;;;N;;;;; +137B9;EGYPTIAN HIEROGLYPH-137B9;Lo;0;L;;;;;N;;;;; +137BA;EGYPTIAN HIEROGLYPH-137BA;Lo;0;L;;;;;N;;;;; +137BB;EGYPTIAN HIEROGLYPH-137BB;Lo;0;L;;;;;N;;;;; +137BC;EGYPTIAN HIEROGLYPH-137BC;Lo;0;L;;;;;N;;;;; +137BD;EGYPTIAN HIEROGLYPH-137BD;Lo;0;L;;;;;N;;;;; +137BE;EGYPTIAN HIEROGLYPH-137BE;Lo;0;L;;;;;N;;;;; +137BF;EGYPTIAN HIEROGLYPH-137BF;Lo;0;L;;;;;N;;;;; +137C0;EGYPTIAN HIEROGLYPH-137C0;Lo;0;L;;;;;N;;;;; +137C1;EGYPTIAN HIEROGLYPH-137C1;Lo;0;L;;;;;N;;;;; +137C2;EGYPTIAN HIEROGLYPH-137C2;Lo;0;L;;;;;N;;;;; +137C3;EGYPTIAN HIEROGLYPH-137C3;Lo;0;L;;;;;N;;;;; +137C4;EGYPTIAN HIEROGLYPH-137C4;Lo;0;L;;;;;N;;;;; +137C5;EGYPTIAN HIEROGLYPH-137C5;Lo;0;L;;;;;N;;;;; +137C6;EGYPTIAN HIEROGLYPH-137C6;Lo;0;L;;;;;N;;;;; +137C7;EGYPTIAN HIEROGLYPH-137C7;Lo;0;L;;;;;N;;;;; +137C8;EGYPTIAN HIEROGLYPH-137C8;Lo;0;L;;;;;N;;;;; +137C9;EGYPTIAN HIEROGLYPH-137C9;Lo;0;L;;;;;N;;;;; +137CA;EGYPTIAN HIEROGLYPH-137CA;Lo;0;L;;;;;N;;;;; +137CB;EGYPTIAN HIEROGLYPH-137CB;Lo;0;L;;;;;N;;;;; +137CC;EGYPTIAN HIEROGLYPH-137CC;Lo;0;L;;;;;N;;;;; +137CD;EGYPTIAN HIEROGLYPH-137CD;Lo;0;L;;;;;N;;;;; +137CE;EGYPTIAN HIEROGLYPH-137CE;Lo;0;L;;;;;N;;;;; +137CF;EGYPTIAN HIEROGLYPH-137CF;Lo;0;L;;;;;N;;;;; +137D0;EGYPTIAN HIEROGLYPH-137D0;Lo;0;L;;;;;N;;;;; +137D1;EGYPTIAN HIEROGLYPH-137D1;Lo;0;L;;;;;N;;;;; +137D2;EGYPTIAN HIEROGLYPH-137D2;Lo;0;L;;;;;N;;;;; +137D3;EGYPTIAN HIEROGLYPH-137D3;Lo;0;L;;;;;N;;;;; +137D4;EGYPTIAN HIEROGLYPH-137D4;Lo;0;L;;;;;N;;;;; +137D5;EGYPTIAN HIEROGLYPH-137D5;Lo;0;L;;;;;N;;;;; +137D6;EGYPTIAN HIEROGLYPH-137D6;Lo;0;L;;;;;N;;;;; +137D7;EGYPTIAN HIEROGLYPH-137D7;Lo;0;L;;;;;N;;;;; +137D8;EGYPTIAN HIEROGLYPH-137D8;Lo;0;L;;;;;N;;;;; +137D9;EGYPTIAN HIEROGLYPH-137D9;Lo;0;L;;;;;N;;;;; +137DA;EGYPTIAN HIEROGLYPH-137DA;Lo;0;L;;;;;N;;;;; +137DB;EGYPTIAN HIEROGLYPH-137DB;Lo;0;L;;;;;N;;;;; +137DC;EGYPTIAN HIEROGLYPH-137DC;Lo;0;L;;;;;N;;;;; +137DD;EGYPTIAN HIEROGLYPH-137DD;Lo;0;L;;;;;N;;;;; +137DE;EGYPTIAN HIEROGLYPH-137DE;Lo;0;L;;;;;N;;;;; +137DF;EGYPTIAN HIEROGLYPH-137DF;Lo;0;L;;;;;N;;;;; +137E0;EGYPTIAN HIEROGLYPH-137E0;Lo;0;L;;;;;N;;;;; +137E1;EGYPTIAN HIEROGLYPH-137E1;Lo;0;L;;;;;N;;;;; +137E2;EGYPTIAN HIEROGLYPH-137E2;Lo;0;L;;;;;N;;;;; +137E3;EGYPTIAN HIEROGLYPH-137E3;Lo;0;L;;;;;N;;;;; +137E4;EGYPTIAN HIEROGLYPH-137E4;Lo;0;L;;;;;N;;;;; +137E5;EGYPTIAN HIEROGLYPH-137E5;Lo;0;L;;;;;N;;;;; +137E6;EGYPTIAN HIEROGLYPH-137E6;Lo;0;L;;;;;N;;;;; +137E7;EGYPTIAN HIEROGLYPH-137E7;Lo;0;L;;;;;N;;;;; +137E8;EGYPTIAN HIEROGLYPH-137E8;Lo;0;L;;;;;N;;;;; +137E9;EGYPTIAN HIEROGLYPH-137E9;Lo;0;L;;;;;N;;;;; +137EA;EGYPTIAN HIEROGLYPH-137EA;Lo;0;L;;;;;N;;;;; +137EB;EGYPTIAN HIEROGLYPH-137EB;Lo;0;L;;;;;N;;;;; +137EC;EGYPTIAN HIEROGLYPH-137EC;Lo;0;L;;;;;N;;;;; +137ED;EGYPTIAN HIEROGLYPH-137ED;Lo;0;L;;;;;N;;;;; +137EE;EGYPTIAN HIEROGLYPH-137EE;Lo;0;L;;;;;N;;;;; +137EF;EGYPTIAN HIEROGLYPH-137EF;Lo;0;L;;;;;N;;;;; +137F0;EGYPTIAN HIEROGLYPH-137F0;Lo;0;L;;;;;N;;;;; +137F1;EGYPTIAN HIEROGLYPH-137F1;Lo;0;L;;;;;N;;;;; +137F2;EGYPTIAN HIEROGLYPH-137F2;Lo;0;L;;;;;N;;;;; +137F3;EGYPTIAN HIEROGLYPH-137F3;Lo;0;L;;;;;N;;;;; +137F4;EGYPTIAN HIEROGLYPH-137F4;Lo;0;L;;;;;N;;;;; +137F5;EGYPTIAN HIEROGLYPH-137F5;Lo;0;L;;;;;N;;;;; +137F6;EGYPTIAN HIEROGLYPH-137F6;Lo;0;L;;;;;N;;;;; +137F7;EGYPTIAN HIEROGLYPH-137F7;Lo;0;L;;;;;N;;;;; +137F8;EGYPTIAN HIEROGLYPH-137F8;Lo;0;L;;;;;N;;;;; +137F9;EGYPTIAN HIEROGLYPH-137F9;Lo;0;L;;;;;N;;;;; +137FA;EGYPTIAN HIEROGLYPH-137FA;Lo;0;L;;;;;N;;;;; +137FB;EGYPTIAN HIEROGLYPH-137FB;Lo;0;L;;;;;N;;;;; +137FC;EGYPTIAN HIEROGLYPH-137FC;Lo;0;L;;;;;N;;;;; +137FD;EGYPTIAN HIEROGLYPH-137FD;Lo;0;L;;;;;N;;;;; +137FE;EGYPTIAN HIEROGLYPH-137FE;Lo;0;L;;;;;N;;;;; +137FF;EGYPTIAN HIEROGLYPH-137FF;Lo;0;L;;;;;N;;;;; +13800;EGYPTIAN HIEROGLYPH-13800;Lo;0;L;;;;;N;;;;; +13801;EGYPTIAN HIEROGLYPH-13801;Lo;0;L;;;;;N;;;;; +13802;EGYPTIAN HIEROGLYPH-13802;Lo;0;L;;;;;N;;;;; +13803;EGYPTIAN HIEROGLYPH-13803;Lo;0;L;;;;;N;;;;; +13804;EGYPTIAN HIEROGLYPH-13804;Lo;0;L;;;;;N;;;;; +13805;EGYPTIAN HIEROGLYPH-13805;Lo;0;L;;;;;N;;;;; +13806;EGYPTIAN HIEROGLYPH-13806;Lo;0;L;;;;;N;;;;; +13807;EGYPTIAN HIEROGLYPH-13807;Lo;0;L;;;;;N;;;;; +13808;EGYPTIAN HIEROGLYPH-13808;Lo;0;L;;;;;N;;;;; +13809;EGYPTIAN HIEROGLYPH-13809;Lo;0;L;;;;;N;;;;; +1380A;EGYPTIAN HIEROGLYPH-1380A;Lo;0;L;;;;;N;;;;; +1380B;EGYPTIAN HIEROGLYPH-1380B;Lo;0;L;;;;;N;;;;; +1380C;EGYPTIAN HIEROGLYPH-1380C;Lo;0;L;;;;;N;;;;; +1380D;EGYPTIAN HIEROGLYPH-1380D;Lo;0;L;;;;;N;;;;; +1380E;EGYPTIAN HIEROGLYPH-1380E;Lo;0;L;;;;;N;;;;; +1380F;EGYPTIAN HIEROGLYPH-1380F;Lo;0;L;;;;;N;;;;; +13810;EGYPTIAN HIEROGLYPH-13810;Lo;0;L;;;;;N;;;;; +13811;EGYPTIAN HIEROGLYPH-13811;Lo;0;L;;;;;N;;;;; +13812;EGYPTIAN HIEROGLYPH-13812;Lo;0;L;;;;;N;;;;; +13813;EGYPTIAN HIEROGLYPH-13813;Lo;0;L;;;;;N;;;;; +13814;EGYPTIAN HIEROGLYPH-13814;Lo;0;L;;;;;N;;;;; +13815;EGYPTIAN HIEROGLYPH-13815;Lo;0;L;;;;;N;;;;; +13816;EGYPTIAN HIEROGLYPH-13816;Lo;0;L;;;;;N;;;;; +13817;EGYPTIAN HIEROGLYPH-13817;Lo;0;L;;;;;N;;;;; +13818;EGYPTIAN HIEROGLYPH-13818;Lo;0;L;;;;;N;;;;; +13819;EGYPTIAN HIEROGLYPH-13819;Lo;0;L;;;;;N;;;;; +1381A;EGYPTIAN HIEROGLYPH-1381A;Lo;0;L;;;;;N;;;;; +1381B;EGYPTIAN HIEROGLYPH-1381B;Lo;0;L;;;;;N;;;;; +1381C;EGYPTIAN HIEROGLYPH-1381C;Lo;0;L;;;;;N;;;;; +1381D;EGYPTIAN HIEROGLYPH-1381D;Lo;0;L;;;;;N;;;;; +1381E;EGYPTIAN HIEROGLYPH-1381E;Lo;0;L;;;;;N;;;;; +1381F;EGYPTIAN HIEROGLYPH-1381F;Lo;0;L;;;;;N;;;;; +13820;EGYPTIAN HIEROGLYPH-13820;Lo;0;L;;;;;N;;;;; +13821;EGYPTIAN HIEROGLYPH-13821;Lo;0;L;;;;;N;;;;; +13822;EGYPTIAN HIEROGLYPH-13822;Lo;0;L;;;;;N;;;;; +13823;EGYPTIAN HIEROGLYPH-13823;Lo;0;L;;;;;N;;;;; +13824;EGYPTIAN HIEROGLYPH-13824;Lo;0;L;;;;;N;;;;; +13825;EGYPTIAN HIEROGLYPH-13825;Lo;0;L;;;;;N;;;;; +13826;EGYPTIAN HIEROGLYPH-13826;Lo;0;L;;;;;N;;;;; +13827;EGYPTIAN HIEROGLYPH-13827;Lo;0;L;;;;;N;;;;; +13828;EGYPTIAN HIEROGLYPH-13828;Lo;0;L;;;;;N;;;;; +13829;EGYPTIAN HIEROGLYPH-13829;Lo;0;L;;;;;N;;;;; +1382A;EGYPTIAN HIEROGLYPH-1382A;Lo;0;L;;;;;N;;;;; +1382B;EGYPTIAN HIEROGLYPH-1382B;Lo;0;L;;;;;N;;;;; +1382C;EGYPTIAN HIEROGLYPH-1382C;Lo;0;L;;;;;N;;;;; +1382D;EGYPTIAN HIEROGLYPH-1382D;Lo;0;L;;;;;N;;;;; +1382E;EGYPTIAN HIEROGLYPH-1382E;Lo;0;L;;;;;N;;;;; +1382F;EGYPTIAN HIEROGLYPH-1382F;Lo;0;L;;;;;N;;;;; +13830;EGYPTIAN HIEROGLYPH-13830;Lo;0;L;;;;;N;;;;; +13831;EGYPTIAN HIEROGLYPH-13831;Lo;0;L;;;;;N;;;;; +13832;EGYPTIAN HIEROGLYPH-13832;Lo;0;L;;;;;N;;;;; +13833;EGYPTIAN HIEROGLYPH-13833;Lo;0;L;;;;;N;;;;; +13834;EGYPTIAN HIEROGLYPH-13834;Lo;0;L;;;;;N;;;;; +13835;EGYPTIAN HIEROGLYPH-13835;Lo;0;L;;;;;N;;;;; +13836;EGYPTIAN HIEROGLYPH-13836;Lo;0;L;;;;;N;;;;; +13837;EGYPTIAN HIEROGLYPH-13837;Lo;0;L;;;;;N;;;;; +13838;EGYPTIAN HIEROGLYPH-13838;Lo;0;L;;;;;N;;;;; +13839;EGYPTIAN HIEROGLYPH-13839;Lo;0;L;;;;;N;;;;; +1383A;EGYPTIAN HIEROGLYPH-1383A;Lo;0;L;;;;;N;;;;; +1383B;EGYPTIAN HIEROGLYPH-1383B;Lo;0;L;;;;;N;;;;; +1383C;EGYPTIAN HIEROGLYPH-1383C;Lo;0;L;;;;;N;;;;; +1383D;EGYPTIAN HIEROGLYPH-1383D;Lo;0;L;;;;;N;;;;; +1383E;EGYPTIAN HIEROGLYPH-1383E;Lo;0;L;;;;;N;;;;; +1383F;EGYPTIAN HIEROGLYPH-1383F;Lo;0;L;;;;;N;;;;; +13840;EGYPTIAN HIEROGLYPH-13840;Lo;0;L;;;;;N;;;;; +13841;EGYPTIAN HIEROGLYPH-13841;Lo;0;L;;;;;N;;;;; +13842;EGYPTIAN HIEROGLYPH-13842;Lo;0;L;;;;;N;;;;; +13843;EGYPTIAN HIEROGLYPH-13843;Lo;0;L;;;;;N;;;;; +13844;EGYPTIAN HIEROGLYPH-13844;Lo;0;L;;;;;N;;;;; +13845;EGYPTIAN HIEROGLYPH-13845;Lo;0;L;;;;;N;;;;; +13846;EGYPTIAN HIEROGLYPH-13846;Lo;0;L;;;;;N;;;;; +13847;EGYPTIAN HIEROGLYPH-13847;Lo;0;L;;;;;N;;;;; +13848;EGYPTIAN HIEROGLYPH-13848;Lo;0;L;;;;;N;;;;; +13849;EGYPTIAN HIEROGLYPH-13849;Lo;0;L;;;;;N;;;;; +1384A;EGYPTIAN HIEROGLYPH-1384A;Lo;0;L;;;;;N;;;;; +1384B;EGYPTIAN HIEROGLYPH-1384B;Lo;0;L;;;;;N;;;;; +1384C;EGYPTIAN HIEROGLYPH-1384C;Lo;0;L;;;;;N;;;;; +1384D;EGYPTIAN HIEROGLYPH-1384D;Lo;0;L;;;;;N;;;;; +1384E;EGYPTIAN HIEROGLYPH-1384E;Lo;0;L;;;;;N;;;;; +1384F;EGYPTIAN HIEROGLYPH-1384F;Lo;0;L;;;;;N;;;;; +13850;EGYPTIAN HIEROGLYPH-13850;Lo;0;L;;;;;N;;;;; +13851;EGYPTIAN HIEROGLYPH-13851;Lo;0;L;;;;;N;;;;; +13852;EGYPTIAN HIEROGLYPH-13852;Lo;0;L;;;;;N;;;;; +13853;EGYPTIAN HIEROGLYPH-13853;Lo;0;L;;;;;N;;;;; +13854;EGYPTIAN HIEROGLYPH-13854;Lo;0;L;;;;;N;;;;; +13855;EGYPTIAN HIEROGLYPH-13855;Lo;0;L;;;;;N;;;;; +13856;EGYPTIAN HIEROGLYPH-13856;Lo;0;L;;;;;N;;;;; +13857;EGYPTIAN HIEROGLYPH-13857;Lo;0;L;;;;;N;;;;; +13858;EGYPTIAN HIEROGLYPH-13858;Lo;0;L;;;;;N;;;;; +13859;EGYPTIAN HIEROGLYPH-13859;Lo;0;L;;;;;N;;;;; +1385A;EGYPTIAN HIEROGLYPH-1385A;Lo;0;L;;;;;N;;;;; +1385B;EGYPTIAN HIEROGLYPH-1385B;Lo;0;L;;;;;N;;;;; +1385C;EGYPTIAN HIEROGLYPH-1385C;Lo;0;L;;;;;N;;;;; +1385D;EGYPTIAN HIEROGLYPH-1385D;Lo;0;L;;;;;N;;;;; +1385E;EGYPTIAN HIEROGLYPH-1385E;Lo;0;L;;;;;N;;;;; +1385F;EGYPTIAN HIEROGLYPH-1385F;Lo;0;L;;;;;N;;;;; +13860;EGYPTIAN HIEROGLYPH-13860;Lo;0;L;;;;;N;;;;; +13861;EGYPTIAN HIEROGLYPH-13861;Lo;0;L;;;;;N;;;;; +13862;EGYPTIAN HIEROGLYPH-13862;Lo;0;L;;;;;N;;;;; +13863;EGYPTIAN HIEROGLYPH-13863;Lo;0;L;;;;;N;;;;; +13864;EGYPTIAN HIEROGLYPH-13864;Lo;0;L;;;;;N;;;;; +13865;EGYPTIAN HIEROGLYPH-13865;Lo;0;L;;;;;N;;;;; +13866;EGYPTIAN HIEROGLYPH-13866;Lo;0;L;;;;;N;;;;; +13867;EGYPTIAN HIEROGLYPH-13867;Lo;0;L;;;;;N;;;;; +13868;EGYPTIAN HIEROGLYPH-13868;Lo;0;L;;;;;N;;;;; +13869;EGYPTIAN HIEROGLYPH-13869;Lo;0;L;;;;;N;;;;; +1386A;EGYPTIAN HIEROGLYPH-1386A;Lo;0;L;;;;;N;;;;; +1386B;EGYPTIAN HIEROGLYPH-1386B;Lo;0;L;;;;;N;;;;; +1386C;EGYPTIAN HIEROGLYPH-1386C;Lo;0;L;;;;;N;;;;; +1386D;EGYPTIAN HIEROGLYPH-1386D;Lo;0;L;;;;;N;;;;; +1386E;EGYPTIAN HIEROGLYPH-1386E;Lo;0;L;;;;;N;;;;; +1386F;EGYPTIAN HIEROGLYPH-1386F;Lo;0;L;;;;;N;;;;; +13870;EGYPTIAN HIEROGLYPH-13870;Lo;0;L;;;;;N;;;;; +13871;EGYPTIAN HIEROGLYPH-13871;Lo;0;L;;;;;N;;;;; +13872;EGYPTIAN HIEROGLYPH-13872;Lo;0;L;;;;;N;;;;; +13873;EGYPTIAN HIEROGLYPH-13873;Lo;0;L;;;;;N;;;;; +13874;EGYPTIAN HIEROGLYPH-13874;Lo;0;L;;;;;N;;;;; +13875;EGYPTIAN HIEROGLYPH-13875;Lo;0;L;;;;;N;;;;; +13876;EGYPTIAN HIEROGLYPH-13876;Lo;0;L;;;;;N;;;;; +13877;EGYPTIAN HIEROGLYPH-13877;Lo;0;L;;;;;N;;;;; +13878;EGYPTIAN HIEROGLYPH-13878;Lo;0;L;;;;;N;;;;; +13879;EGYPTIAN HIEROGLYPH-13879;Lo;0;L;;;;;N;;;;; +1387A;EGYPTIAN HIEROGLYPH-1387A;Lo;0;L;;;;;N;;;;; +1387B;EGYPTIAN HIEROGLYPH-1387B;Lo;0;L;;;;;N;;;;; +1387C;EGYPTIAN HIEROGLYPH-1387C;Lo;0;L;;;;;N;;;;; +1387D;EGYPTIAN HIEROGLYPH-1387D;Lo;0;L;;;;;N;;;;; +1387E;EGYPTIAN HIEROGLYPH-1387E;Lo;0;L;;;;;N;;;;; +1387F;EGYPTIAN HIEROGLYPH-1387F;Lo;0;L;;;;;N;;;;; +13880;EGYPTIAN HIEROGLYPH-13880;Lo;0;L;;;;;N;;;;; +13881;EGYPTIAN HIEROGLYPH-13881;Lo;0;L;;;;;N;;;;; +13882;EGYPTIAN HIEROGLYPH-13882;Lo;0;L;;;;;N;;;;; +13883;EGYPTIAN HIEROGLYPH-13883;Lo;0;L;;;;;N;;;;; +13884;EGYPTIAN HIEROGLYPH-13884;Lo;0;L;;;;;N;;;;; +13885;EGYPTIAN HIEROGLYPH-13885;Lo;0;L;;;;;N;;;;; +13886;EGYPTIAN HIEROGLYPH-13886;Lo;0;L;;;;;N;;;;; +13887;EGYPTIAN HIEROGLYPH-13887;Lo;0;L;;;;;N;;;;; +13888;EGYPTIAN HIEROGLYPH-13888;Lo;0;L;;;;;N;;;;; +13889;EGYPTIAN HIEROGLYPH-13889;Lo;0;L;;;;;N;;;;; +1388A;EGYPTIAN HIEROGLYPH-1388A;Lo;0;L;;;;;N;;;;; +1388B;EGYPTIAN HIEROGLYPH-1388B;Lo;0;L;;;;;N;;;;; +1388C;EGYPTIAN HIEROGLYPH-1388C;Lo;0;L;;;;;N;;;;; +1388D;EGYPTIAN HIEROGLYPH-1388D;Lo;0;L;;;;;N;;;;; +1388E;EGYPTIAN HIEROGLYPH-1388E;Lo;0;L;;;;;N;;;;; +1388F;EGYPTIAN HIEROGLYPH-1388F;Lo;0;L;;;;;N;;;;; +13890;EGYPTIAN HIEROGLYPH-13890;Lo;0;L;;;;;N;;;;; +13891;EGYPTIAN HIEROGLYPH-13891;Lo;0;L;;;;;N;;;;; +13892;EGYPTIAN HIEROGLYPH-13892;Lo;0;L;;;;;N;;;;; +13893;EGYPTIAN HIEROGLYPH-13893;Lo;0;L;;;;;N;;;;; +13894;EGYPTIAN HIEROGLYPH-13894;Lo;0;L;;;;;N;;;;; +13895;EGYPTIAN HIEROGLYPH-13895;Lo;0;L;;;;;N;;;;; +13896;EGYPTIAN HIEROGLYPH-13896;Lo;0;L;;;;;N;;;;; +13897;EGYPTIAN HIEROGLYPH-13897;Lo;0;L;;;;;N;;;;; +13898;EGYPTIAN HIEROGLYPH-13898;Lo;0;L;;;;;N;;;;; +13899;EGYPTIAN HIEROGLYPH-13899;Lo;0;L;;;;;N;;;;; +1389A;EGYPTIAN HIEROGLYPH-1389A;Lo;0;L;;;;;N;;;;; +1389B;EGYPTIAN HIEROGLYPH-1389B;Lo;0;L;;;;;N;;;;; +1389C;EGYPTIAN HIEROGLYPH-1389C;Lo;0;L;;;;;N;;;;; +1389D;EGYPTIAN HIEROGLYPH-1389D;Lo;0;L;;;;;N;;;;; +1389E;EGYPTIAN HIEROGLYPH-1389E;Lo;0;L;;;;;N;;;;; +1389F;EGYPTIAN HIEROGLYPH-1389F;Lo;0;L;;;;;N;;;;; +138A0;EGYPTIAN HIEROGLYPH-138A0;Lo;0;L;;;;;N;;;;; +138A1;EGYPTIAN HIEROGLYPH-138A1;Lo;0;L;;;;;N;;;;; +138A2;EGYPTIAN HIEROGLYPH-138A2;Lo;0;L;;;;;N;;;;; +138A3;EGYPTIAN HIEROGLYPH-138A3;Lo;0;L;;;;;N;;;;; +138A4;EGYPTIAN HIEROGLYPH-138A4;Lo;0;L;;;;;N;;;;; +138A5;EGYPTIAN HIEROGLYPH-138A5;Lo;0;L;;;;;N;;;;; +138A6;EGYPTIAN HIEROGLYPH-138A6;Lo;0;L;;;;;N;;;;; +138A7;EGYPTIAN HIEROGLYPH-138A7;Lo;0;L;;;;;N;;;;; +138A8;EGYPTIAN HIEROGLYPH-138A8;Lo;0;L;;;;;N;;;;; +138A9;EGYPTIAN HIEROGLYPH-138A9;Lo;0;L;;;;;N;;;;; +138AA;EGYPTIAN HIEROGLYPH-138AA;Lo;0;L;;;;;N;;;;; +138AB;EGYPTIAN HIEROGLYPH-138AB;Lo;0;L;;;;;N;;;;; +138AC;EGYPTIAN HIEROGLYPH-138AC;Lo;0;L;;;;;N;;;;; +138AD;EGYPTIAN HIEROGLYPH-138AD;Lo;0;L;;;;;N;;;;; +138AE;EGYPTIAN HIEROGLYPH-138AE;Lo;0;L;;;;;N;;;;; +138AF;EGYPTIAN HIEROGLYPH-138AF;Lo;0;L;;;;;N;;;;; +138B0;EGYPTIAN HIEROGLYPH-138B0;Lo;0;L;;;;;N;;;;; +138B1;EGYPTIAN HIEROGLYPH-138B1;Lo;0;L;;;;;N;;;;; +138B2;EGYPTIAN HIEROGLYPH-138B2;Lo;0;L;;;;;N;;;;; +138B3;EGYPTIAN HIEROGLYPH-138B3;Lo;0;L;;;;;N;;;;; +138B4;EGYPTIAN HIEROGLYPH-138B4;Lo;0;L;;;;;N;;;;; +138B5;EGYPTIAN HIEROGLYPH-138B5;Lo;0;L;;;;;N;;;;; +138B6;EGYPTIAN HIEROGLYPH-138B6;Lo;0;L;;;;;N;;;;; +138B7;EGYPTIAN HIEROGLYPH-138B7;Lo;0;L;;;;;N;;;;; +138B8;EGYPTIAN HIEROGLYPH-138B8;Lo;0;L;;;;;N;;;;; +138B9;EGYPTIAN HIEROGLYPH-138B9;Lo;0;L;;;;;N;;;;; +138BA;EGYPTIAN HIEROGLYPH-138BA;Lo;0;L;;;;;N;;;;; +138BB;EGYPTIAN HIEROGLYPH-138BB;Lo;0;L;;;;;N;;;;; +138BC;EGYPTIAN HIEROGLYPH-138BC;Lo;0;L;;;;;N;;;;; +138BD;EGYPTIAN HIEROGLYPH-138BD;Lo;0;L;;;;;N;;;;; +138BE;EGYPTIAN HIEROGLYPH-138BE;Lo;0;L;;;;;N;;;;; +138BF;EGYPTIAN HIEROGLYPH-138BF;Lo;0;L;;;;;N;;;;; +138C0;EGYPTIAN HIEROGLYPH-138C0;Lo;0;L;;;;;N;;;;; +138C1;EGYPTIAN HIEROGLYPH-138C1;Lo;0;L;;;;;N;;;;; +138C2;EGYPTIAN HIEROGLYPH-138C2;Lo;0;L;;;;;N;;;;; +138C3;EGYPTIAN HIEROGLYPH-138C3;Lo;0;L;;;;;N;;;;; +138C4;EGYPTIAN HIEROGLYPH-138C4;Lo;0;L;;;;;N;;;;; +138C5;EGYPTIAN HIEROGLYPH-138C5;Lo;0;L;;;;;N;;;;; +138C6;EGYPTIAN HIEROGLYPH-138C6;Lo;0;L;;;;;N;;;;; +138C7;EGYPTIAN HIEROGLYPH-138C7;Lo;0;L;;;;;N;;;;; +138C8;EGYPTIAN HIEROGLYPH-138C8;Lo;0;L;;;;;N;;;;; +138C9;EGYPTIAN HIEROGLYPH-138C9;Lo;0;L;;;;;N;;;;; +138CA;EGYPTIAN HIEROGLYPH-138CA;Lo;0;L;;;;;N;;;;; +138CB;EGYPTIAN HIEROGLYPH-138CB;Lo;0;L;;;;;N;;;;; +138CC;EGYPTIAN HIEROGLYPH-138CC;Lo;0;L;;;;;N;;;;; +138CD;EGYPTIAN HIEROGLYPH-138CD;Lo;0;L;;;;;N;;;;; +138CE;EGYPTIAN HIEROGLYPH-138CE;Lo;0;L;;;;;N;;;;; +138CF;EGYPTIAN HIEROGLYPH-138CF;Lo;0;L;;;;;N;;;;; +138D0;EGYPTIAN HIEROGLYPH-138D0;Lo;0;L;;;;;N;;;;; +138D1;EGYPTIAN HIEROGLYPH-138D1;Lo;0;L;;;;;N;;;;; +138D2;EGYPTIAN HIEROGLYPH-138D2;Lo;0;L;;;;;N;;;;; +138D3;EGYPTIAN HIEROGLYPH-138D3;Lo;0;L;;;;;N;;;;; +138D4;EGYPTIAN HIEROGLYPH-138D4;Lo;0;L;;;;;N;;;;; +138D5;EGYPTIAN HIEROGLYPH-138D5;Lo;0;L;;;;;N;;;;; +138D6;EGYPTIAN HIEROGLYPH-138D6;Lo;0;L;;;;;N;;;;; +138D7;EGYPTIAN HIEROGLYPH-138D7;Lo;0;L;;;;;N;;;;; +138D8;EGYPTIAN HIEROGLYPH-138D8;Lo;0;L;;;;;N;;;;; +138D9;EGYPTIAN HIEROGLYPH-138D9;Lo;0;L;;;;;N;;;;; +138DA;EGYPTIAN HIEROGLYPH-138DA;Lo;0;L;;;;;N;;;;; +138DB;EGYPTIAN HIEROGLYPH-138DB;Lo;0;L;;;;;N;;;;; +138DC;EGYPTIAN HIEROGLYPH-138DC;Lo;0;L;;;;;N;;;;; +138DD;EGYPTIAN HIEROGLYPH-138DD;Lo;0;L;;;;;N;;;;; +138DE;EGYPTIAN HIEROGLYPH-138DE;Lo;0;L;;;;;N;;;;; +138DF;EGYPTIAN HIEROGLYPH-138DF;Lo;0;L;;;;;N;;;;; +138E0;EGYPTIAN HIEROGLYPH-138E0;Lo;0;L;;;;;N;;;;; +138E1;EGYPTIAN HIEROGLYPH-138E1;Lo;0;L;;;;;N;;;;; +138E2;EGYPTIAN HIEROGLYPH-138E2;Lo;0;L;;;;;N;;;;; +138E3;EGYPTIAN HIEROGLYPH-138E3;Lo;0;L;;;;;N;;;;; +138E4;EGYPTIAN HIEROGLYPH-138E4;Lo;0;L;;;;;N;;;;; +138E5;EGYPTIAN HIEROGLYPH-138E5;Lo;0;L;;;;;N;;;;; +138E6;EGYPTIAN HIEROGLYPH-138E6;Lo;0;L;;;;;N;;;;; +138E7;EGYPTIAN HIEROGLYPH-138E7;Lo;0;L;;;;;N;;;;; +138E8;EGYPTIAN HIEROGLYPH-138E8;Lo;0;L;;;;;N;;;;; +138E9;EGYPTIAN HIEROGLYPH-138E9;Lo;0;L;;;;;N;;;;; +138EA;EGYPTIAN HIEROGLYPH-138EA;Lo;0;L;;;;;N;;;;; +138EB;EGYPTIAN HIEROGLYPH-138EB;Lo;0;L;;;;;N;;;;; +138EC;EGYPTIAN HIEROGLYPH-138EC;Lo;0;L;;;;;N;;;;; +138ED;EGYPTIAN HIEROGLYPH-138ED;Lo;0;L;;;;;N;;;;; +138EE;EGYPTIAN HIEROGLYPH-138EE;Lo;0;L;;;;;N;;;;; +138EF;EGYPTIAN HIEROGLYPH-138EF;Lo;0;L;;;;;N;;;;; +138F0;EGYPTIAN HIEROGLYPH-138F0;Lo;0;L;;;;;N;;;;; +138F1;EGYPTIAN HIEROGLYPH-138F1;Lo;0;L;;;;;N;;;;; +138F2;EGYPTIAN HIEROGLYPH-138F2;Lo;0;L;;;;;N;;;;; +138F3;EGYPTIAN HIEROGLYPH-138F3;Lo;0;L;;;;;N;;;;; +138F4;EGYPTIAN HIEROGLYPH-138F4;Lo;0;L;;;;;N;;;;; +138F5;EGYPTIAN HIEROGLYPH-138F5;Lo;0;L;;;;;N;;;;; +138F6;EGYPTIAN HIEROGLYPH-138F6;Lo;0;L;;;;;N;;;;; +138F7;EGYPTIAN HIEROGLYPH-138F7;Lo;0;L;;;;;N;;;;; +138F8;EGYPTIAN HIEROGLYPH-138F8;Lo;0;L;;;;;N;;;;; +138F9;EGYPTIAN HIEROGLYPH-138F9;Lo;0;L;;;;;N;;;;; +138FA;EGYPTIAN HIEROGLYPH-138FA;Lo;0;L;;;;;N;;;;; +138FB;EGYPTIAN HIEROGLYPH-138FB;Lo;0;L;;;;;N;;;;; +138FC;EGYPTIAN HIEROGLYPH-138FC;Lo;0;L;;;;;N;;;;; +138FD;EGYPTIAN HIEROGLYPH-138FD;Lo;0;L;;;;;N;;;;; +138FE;EGYPTIAN HIEROGLYPH-138FE;Lo;0;L;;;;;N;;;;; +138FF;EGYPTIAN HIEROGLYPH-138FF;Lo;0;L;;;;;N;;;;; +13900;EGYPTIAN HIEROGLYPH-13900;Lo;0;L;;;;;N;;;;; +13901;EGYPTIAN HIEROGLYPH-13901;Lo;0;L;;;;;N;;;;; +13902;EGYPTIAN HIEROGLYPH-13902;Lo;0;L;;;;;N;;;;; +13903;EGYPTIAN HIEROGLYPH-13903;Lo;0;L;;;;;N;;;;; +13904;EGYPTIAN HIEROGLYPH-13904;Lo;0;L;;;;;N;;;;; +13905;EGYPTIAN HIEROGLYPH-13905;Lo;0;L;;;;;N;;;;; +13906;EGYPTIAN HIEROGLYPH-13906;Lo;0;L;;;;;N;;;;; +13907;EGYPTIAN HIEROGLYPH-13907;Lo;0;L;;;;;N;;;;; +13908;EGYPTIAN HIEROGLYPH-13908;Lo;0;L;;;;;N;;;;; +13909;EGYPTIAN HIEROGLYPH-13909;Lo;0;L;;;;;N;;;;; +1390A;EGYPTIAN HIEROGLYPH-1390A;Lo;0;L;;;;;N;;;;; +1390B;EGYPTIAN HIEROGLYPH-1390B;Lo;0;L;;;;;N;;;;; +1390C;EGYPTIAN HIEROGLYPH-1390C;Lo;0;L;;;;;N;;;;; +1390D;EGYPTIAN HIEROGLYPH-1390D;Lo;0;L;;;;;N;;;;; +1390E;EGYPTIAN HIEROGLYPH-1390E;Lo;0;L;;;;;N;;;;; +1390F;EGYPTIAN HIEROGLYPH-1390F;Lo;0;L;;;;;N;;;;; +13910;EGYPTIAN HIEROGLYPH-13910;Lo;0;L;;;;;N;;;;; +13911;EGYPTIAN HIEROGLYPH-13911;Lo;0;L;;;;;N;;;;; +13912;EGYPTIAN HIEROGLYPH-13912;Lo;0;L;;;;;N;;;;; +13913;EGYPTIAN HIEROGLYPH-13913;Lo;0;L;;;;;N;;;;; +13914;EGYPTIAN HIEROGLYPH-13914;Lo;0;L;;;;;N;;;;; +13915;EGYPTIAN HIEROGLYPH-13915;Lo;0;L;;;;;N;;;;; +13916;EGYPTIAN HIEROGLYPH-13916;Lo;0;L;;;;;N;;;;; +13917;EGYPTIAN HIEROGLYPH-13917;Lo;0;L;;;;;N;;;;; +13918;EGYPTIAN HIEROGLYPH-13918;Lo;0;L;;;;;N;;;;; +13919;EGYPTIAN HIEROGLYPH-13919;Lo;0;L;;;;;N;;;;; +1391A;EGYPTIAN HIEROGLYPH-1391A;Lo;0;L;;;;;N;;;;; +1391B;EGYPTIAN HIEROGLYPH-1391B;Lo;0;L;;;;;N;;;;; +1391C;EGYPTIAN HIEROGLYPH-1391C;Lo;0;L;;;;;N;;;;; +1391D;EGYPTIAN HIEROGLYPH-1391D;Lo;0;L;;;;;N;;;;; +1391E;EGYPTIAN HIEROGLYPH-1391E;Lo;0;L;;;;;N;;;;; +1391F;EGYPTIAN HIEROGLYPH-1391F;Lo;0;L;;;;;N;;;;; +13920;EGYPTIAN HIEROGLYPH-13920;Lo;0;L;;;;;N;;;;; +13921;EGYPTIAN HIEROGLYPH-13921;Lo;0;L;;;;;N;;;;; +13922;EGYPTIAN HIEROGLYPH-13922;Lo;0;L;;;;;N;;;;; +13923;EGYPTIAN HIEROGLYPH-13923;Lo;0;L;;;;;N;;;;; +13924;EGYPTIAN HIEROGLYPH-13924;Lo;0;L;;;;;N;;;;; +13925;EGYPTIAN HIEROGLYPH-13925;Lo;0;L;;;;;N;;;;; +13926;EGYPTIAN HIEROGLYPH-13926;Lo;0;L;;;;;N;;;;; +13927;EGYPTIAN HIEROGLYPH-13927;Lo;0;L;;;;;N;;;;; +13928;EGYPTIAN HIEROGLYPH-13928;Lo;0;L;;;;;N;;;;; +13929;EGYPTIAN HIEROGLYPH-13929;Lo;0;L;;;;;N;;;;; +1392A;EGYPTIAN HIEROGLYPH-1392A;Lo;0;L;;;;;N;;;;; +1392B;EGYPTIAN HIEROGLYPH-1392B;Lo;0;L;;;;;N;;;;; +1392C;EGYPTIAN HIEROGLYPH-1392C;Lo;0;L;;;;;N;;;;; +1392D;EGYPTIAN HIEROGLYPH-1392D;Lo;0;L;;;;;N;;;;; +1392E;EGYPTIAN HIEROGLYPH-1392E;Lo;0;L;;;;;N;;;;; +1392F;EGYPTIAN HIEROGLYPH-1392F;Lo;0;L;;;;;N;;;;; +13930;EGYPTIAN HIEROGLYPH-13930;Lo;0;L;;;;;N;;;;; +13931;EGYPTIAN HIEROGLYPH-13931;Lo;0;L;;;;;N;;;;; +13932;EGYPTIAN HIEROGLYPH-13932;Lo;0;L;;;;;N;;;;; +13933;EGYPTIAN HIEROGLYPH-13933;Lo;0;L;;;;;N;;;;; +13934;EGYPTIAN HIEROGLYPH-13934;Lo;0;L;;;;;N;;;;; +13935;EGYPTIAN HIEROGLYPH-13935;Lo;0;L;;;;;N;;;;; +13936;EGYPTIAN HIEROGLYPH-13936;Lo;0;L;;;;;N;;;;; +13937;EGYPTIAN HIEROGLYPH-13937;Lo;0;L;;;;;N;;;;; +13938;EGYPTIAN HIEROGLYPH-13938;Lo;0;L;;;;;N;;;;; +13939;EGYPTIAN HIEROGLYPH-13939;Lo;0;L;;;;;N;;;;; +1393A;EGYPTIAN HIEROGLYPH-1393A;Lo;0;L;;;;;N;;;;; +1393B;EGYPTIAN HIEROGLYPH-1393B;Lo;0;L;;;;;N;;;;; +1393C;EGYPTIAN HIEROGLYPH-1393C;Lo;0;L;;;;;N;;;;; +1393D;EGYPTIAN HIEROGLYPH-1393D;Lo;0;L;;;;;N;;;;; +1393E;EGYPTIAN HIEROGLYPH-1393E;Lo;0;L;;;;;N;;;;; +1393F;EGYPTIAN HIEROGLYPH-1393F;Lo;0;L;;;;;N;;;;; +13940;EGYPTIAN HIEROGLYPH-13940;Lo;0;L;;;;;N;;;;; +13941;EGYPTIAN HIEROGLYPH-13941;Lo;0;L;;;;;N;;;;; +13942;EGYPTIAN HIEROGLYPH-13942;Lo;0;L;;;;;N;;;;; +13943;EGYPTIAN HIEROGLYPH-13943;Lo;0;L;;;;;N;;;;; +13944;EGYPTIAN HIEROGLYPH-13944;Lo;0;L;;;;;N;;;;; +13945;EGYPTIAN HIEROGLYPH-13945;Lo;0;L;;;;;N;;;;; +13946;EGYPTIAN HIEROGLYPH-13946;Lo;0;L;;;;;N;;;;; +13947;EGYPTIAN HIEROGLYPH-13947;Lo;0;L;;;;;N;;;;; +13948;EGYPTIAN HIEROGLYPH-13948;Lo;0;L;;;;;N;;;;; +13949;EGYPTIAN HIEROGLYPH-13949;Lo;0;L;;;;;N;;;;; +1394A;EGYPTIAN HIEROGLYPH-1394A;Lo;0;L;;;;;N;;;;; +1394B;EGYPTIAN HIEROGLYPH-1394B;Lo;0;L;;;;;N;;;;; +1394C;EGYPTIAN HIEROGLYPH-1394C;Lo;0;L;;;;;N;;;;; +1394D;EGYPTIAN HIEROGLYPH-1394D;Lo;0;L;;;;;N;;;;; +1394E;EGYPTIAN HIEROGLYPH-1394E;Lo;0;L;;;;;N;;;;; +1394F;EGYPTIAN HIEROGLYPH-1394F;Lo;0;L;;;;;N;;;;; +13950;EGYPTIAN HIEROGLYPH-13950;Lo;0;L;;;;;N;;;;; +13951;EGYPTIAN HIEROGLYPH-13951;Lo;0;L;;;;;N;;;;; +13952;EGYPTIAN HIEROGLYPH-13952;Lo;0;L;;;;;N;;;;; +13953;EGYPTIAN HIEROGLYPH-13953;Lo;0;L;;;;;N;;;;; +13954;EGYPTIAN HIEROGLYPH-13954;Lo;0;L;;;;;N;;;;; +13955;EGYPTIAN HIEROGLYPH-13955;Lo;0;L;;;;;N;;;;; +13956;EGYPTIAN HIEROGLYPH-13956;Lo;0;L;;;;;N;;;;; +13957;EGYPTIAN HIEROGLYPH-13957;Lo;0;L;;;;;N;;;;; +13958;EGYPTIAN HIEROGLYPH-13958;Lo;0;L;;;;;N;;;;; +13959;EGYPTIAN HIEROGLYPH-13959;Lo;0;L;;;;;N;;;;; +1395A;EGYPTIAN HIEROGLYPH-1395A;Lo;0;L;;;;;N;;;;; +1395B;EGYPTIAN HIEROGLYPH-1395B;Lo;0;L;;;;;N;;;;; +1395C;EGYPTIAN HIEROGLYPH-1395C;Lo;0;L;;;;;N;;;;; +1395D;EGYPTIAN HIEROGLYPH-1395D;Lo;0;L;;;;;N;;;;; +1395E;EGYPTIAN HIEROGLYPH-1395E;Lo;0;L;;;;;N;;;;; +1395F;EGYPTIAN HIEROGLYPH-1395F;Lo;0;L;;;;;N;;;;; +13960;EGYPTIAN HIEROGLYPH-13960;Lo;0;L;;;;;N;;;;; +13961;EGYPTIAN HIEROGLYPH-13961;Lo;0;L;;;;;N;;;;; +13962;EGYPTIAN HIEROGLYPH-13962;Lo;0;L;;;;;N;;;;; +13963;EGYPTIAN HIEROGLYPH-13963;Lo;0;L;;;;;N;;;;; +13964;EGYPTIAN HIEROGLYPH-13964;Lo;0;L;;;;;N;;;;; +13965;EGYPTIAN HIEROGLYPH-13965;Lo;0;L;;;;;N;;;;; +13966;EGYPTIAN HIEROGLYPH-13966;Lo;0;L;;;;;N;;;;; +13967;EGYPTIAN HIEROGLYPH-13967;Lo;0;L;;;;;N;;;;; +13968;EGYPTIAN HIEROGLYPH-13968;Lo;0;L;;;;;N;;;;; +13969;EGYPTIAN HIEROGLYPH-13969;Lo;0;L;;;;;N;;;;; +1396A;EGYPTIAN HIEROGLYPH-1396A;Lo;0;L;;;;;N;;;;; +1396B;EGYPTIAN HIEROGLYPH-1396B;Lo;0;L;;;;;N;;;;; +1396C;EGYPTIAN HIEROGLYPH-1396C;Lo;0;L;;;;;N;;;;; +1396D;EGYPTIAN HIEROGLYPH-1396D;Lo;0;L;;;;;N;;;;; +1396E;EGYPTIAN HIEROGLYPH-1396E;Lo;0;L;;;;;N;;;;; +1396F;EGYPTIAN HIEROGLYPH-1396F;Lo;0;L;;;;;N;;;;; +13970;EGYPTIAN HIEROGLYPH-13970;Lo;0;L;;;;;N;;;;; +13971;EGYPTIAN HIEROGLYPH-13971;Lo;0;L;;;;;N;;;;; +13972;EGYPTIAN HIEROGLYPH-13972;Lo;0;L;;;;;N;;;;; +13973;EGYPTIAN HIEROGLYPH-13973;Lo;0;L;;;;;N;;;;; +13974;EGYPTIAN HIEROGLYPH-13974;Lo;0;L;;;;;N;;;;; +13975;EGYPTIAN HIEROGLYPH-13975;Lo;0;L;;;;;N;;;;; +13976;EGYPTIAN HIEROGLYPH-13976;Lo;0;L;;;;;N;;;;; +13977;EGYPTIAN HIEROGLYPH-13977;Lo;0;L;;;;;N;;;;; +13978;EGYPTIAN HIEROGLYPH-13978;Lo;0;L;;;;;N;;;;; +13979;EGYPTIAN HIEROGLYPH-13979;Lo;0;L;;;;;N;;;;; +1397A;EGYPTIAN HIEROGLYPH-1397A;Lo;0;L;;;;;N;;;;; +1397B;EGYPTIAN HIEROGLYPH-1397B;Lo;0;L;;;;;N;;;;; +1397C;EGYPTIAN HIEROGLYPH-1397C;Lo;0;L;;;;;N;;;;; +1397D;EGYPTIAN HIEROGLYPH-1397D;Lo;0;L;;;;;N;;;;; +1397E;EGYPTIAN HIEROGLYPH-1397E;Lo;0;L;;;;;N;;;;; +1397F;EGYPTIAN HIEROGLYPH-1397F;Lo;0;L;;;;;N;;;;; +13980;EGYPTIAN HIEROGLYPH-13980;Lo;0;L;;;;;N;;;;; +13981;EGYPTIAN HIEROGLYPH-13981;Lo;0;L;;;;;N;;;;; +13982;EGYPTIAN HIEROGLYPH-13982;Lo;0;L;;;;;N;;;;; +13983;EGYPTIAN HIEROGLYPH-13983;Lo;0;L;;;;;N;;;;; +13984;EGYPTIAN HIEROGLYPH-13984;Lo;0;L;;;;;N;;;;; +13985;EGYPTIAN HIEROGLYPH-13985;Lo;0;L;;;;;N;;;;; +13986;EGYPTIAN HIEROGLYPH-13986;Lo;0;L;;;;;N;;;;; +13987;EGYPTIAN HIEROGLYPH-13987;Lo;0;L;;;;;N;;;;; +13988;EGYPTIAN HIEROGLYPH-13988;Lo;0;L;;;;;N;;;;; +13989;EGYPTIAN HIEROGLYPH-13989;Lo;0;L;;;;;N;;;;; +1398A;EGYPTIAN HIEROGLYPH-1398A;Lo;0;L;;;;;N;;;;; +1398B;EGYPTIAN HIEROGLYPH-1398B;Lo;0;L;;;;;N;;;;; +1398C;EGYPTIAN HIEROGLYPH-1398C;Lo;0;L;;;;;N;;;;; +1398D;EGYPTIAN HIEROGLYPH-1398D;Lo;0;L;;;;;N;;;;; +1398E;EGYPTIAN HIEROGLYPH-1398E;Lo;0;L;;;;;N;;;;; +1398F;EGYPTIAN HIEROGLYPH-1398F;Lo;0;L;;;;;N;;;;; +13990;EGYPTIAN HIEROGLYPH-13990;Lo;0;L;;;;;N;;;;; +13991;EGYPTIAN HIEROGLYPH-13991;Lo;0;L;;;;;N;;;;; +13992;EGYPTIAN HIEROGLYPH-13992;Lo;0;L;;;;;N;;;;; +13993;EGYPTIAN HIEROGLYPH-13993;Lo;0;L;;;;;N;;;;; +13994;EGYPTIAN HIEROGLYPH-13994;Lo;0;L;;;;;N;;;;; +13995;EGYPTIAN HIEROGLYPH-13995;Lo;0;L;;;;;N;;;;; +13996;EGYPTIAN HIEROGLYPH-13996;Lo;0;L;;;;;N;;;;; +13997;EGYPTIAN HIEROGLYPH-13997;Lo;0;L;;;;;N;;;;; +13998;EGYPTIAN HIEROGLYPH-13998;Lo;0;L;;;;;N;;;;; +13999;EGYPTIAN HIEROGLYPH-13999;Lo;0;L;;;;;N;;;;; +1399A;EGYPTIAN HIEROGLYPH-1399A;Lo;0;L;;;;;N;;;;; +1399B;EGYPTIAN HIEROGLYPH-1399B;Lo;0;L;;;;;N;;;;; +1399C;EGYPTIAN HIEROGLYPH-1399C;Lo;0;L;;;;;N;;;;; +1399D;EGYPTIAN HIEROGLYPH-1399D;Lo;0;L;;;;;N;;;;; +1399E;EGYPTIAN HIEROGLYPH-1399E;Lo;0;L;;;;;N;;;;; +1399F;EGYPTIAN HIEROGLYPH-1399F;Lo;0;L;;;;;N;;;;; +139A0;EGYPTIAN HIEROGLYPH-139A0;Lo;0;L;;;;;N;;;;; +139A1;EGYPTIAN HIEROGLYPH-139A1;Lo;0;L;;;;;N;;;;; +139A2;EGYPTIAN HIEROGLYPH-139A2;Lo;0;L;;;;;N;;;;; +139A3;EGYPTIAN HIEROGLYPH-139A3;Lo;0;L;;;;;N;;;;; +139A4;EGYPTIAN HIEROGLYPH-139A4;Lo;0;L;;;;;N;;;;; +139A5;EGYPTIAN HIEROGLYPH-139A5;Lo;0;L;;;;;N;;;;; +139A6;EGYPTIAN HIEROGLYPH-139A6;Lo;0;L;;;;;N;;;;; +139A7;EGYPTIAN HIEROGLYPH-139A7;Lo;0;L;;;;;N;;;;; +139A8;EGYPTIAN HIEROGLYPH-139A8;Lo;0;L;;;;;N;;;;; +139A9;EGYPTIAN HIEROGLYPH-139A9;Lo;0;L;;;;;N;;;;; +139AA;EGYPTIAN HIEROGLYPH-139AA;Lo;0;L;;;;;N;;;;; +139AB;EGYPTIAN HIEROGLYPH-139AB;Lo;0;L;;;;;N;;;;; +139AC;EGYPTIAN HIEROGLYPH-139AC;Lo;0;L;;;;;N;;;;; +139AD;EGYPTIAN HIEROGLYPH-139AD;Lo;0;L;;;;;N;;;;; +139AE;EGYPTIAN HIEROGLYPH-139AE;Lo;0;L;;;;;N;;;;; +139AF;EGYPTIAN HIEROGLYPH-139AF;Lo;0;L;;;;;N;;;;; +139B0;EGYPTIAN HIEROGLYPH-139B0;Lo;0;L;;;;;N;;;;; +139B1;EGYPTIAN HIEROGLYPH-139B1;Lo;0;L;;;;;N;;;;; +139B2;EGYPTIAN HIEROGLYPH-139B2;Lo;0;L;;;;;N;;;;; +139B3;EGYPTIAN HIEROGLYPH-139B3;Lo;0;L;;;;;N;;;;; +139B4;EGYPTIAN HIEROGLYPH-139B4;Lo;0;L;;;;;N;;;;; +139B5;EGYPTIAN HIEROGLYPH-139B5;Lo;0;L;;;;;N;;;;; +139B6;EGYPTIAN HIEROGLYPH-139B6;Lo;0;L;;;;;N;;;;; +139B7;EGYPTIAN HIEROGLYPH-139B7;Lo;0;L;;;;;N;;;;; +139B8;EGYPTIAN HIEROGLYPH-139B8;Lo;0;L;;;;;N;;;;; +139B9;EGYPTIAN HIEROGLYPH-139B9;Lo;0;L;;;;;N;;;;; +139BA;EGYPTIAN HIEROGLYPH-139BA;Lo;0;L;;;;;N;;;;; +139BB;EGYPTIAN HIEROGLYPH-139BB;Lo;0;L;;;;;N;;;;; +139BC;EGYPTIAN HIEROGLYPH-139BC;Lo;0;L;;;;;N;;;;; +139BD;EGYPTIAN HIEROGLYPH-139BD;Lo;0;L;;;;;N;;;;; +139BE;EGYPTIAN HIEROGLYPH-139BE;Lo;0;L;;;;;N;;;;; +139BF;EGYPTIAN HIEROGLYPH-139BF;Lo;0;L;;;;;N;;;;; +139C0;EGYPTIAN HIEROGLYPH-139C0;Lo;0;L;;;;;N;;;;; +139C1;EGYPTIAN HIEROGLYPH-139C1;Lo;0;L;;;;;N;;;;; +139C2;EGYPTIAN HIEROGLYPH-139C2;Lo;0;L;;;;;N;;;;; +139C3;EGYPTIAN HIEROGLYPH-139C3;Lo;0;L;;;;;N;;;;; +139C4;EGYPTIAN HIEROGLYPH-139C4;Lo;0;L;;;;;N;;;;; +139C5;EGYPTIAN HIEROGLYPH-139C5;Lo;0;L;;;;;N;;;;; +139C6;EGYPTIAN HIEROGLYPH-139C6;Lo;0;L;;;;;N;;;;; +139C7;EGYPTIAN HIEROGLYPH-139C7;Lo;0;L;;;;;N;;;;; +139C8;EGYPTIAN HIEROGLYPH-139C8;Lo;0;L;;;;;N;;;;; +139C9;EGYPTIAN HIEROGLYPH-139C9;Lo;0;L;;;;;N;;;;; +139CA;EGYPTIAN HIEROGLYPH-139CA;Lo;0;L;;;;;N;;;;; +139CB;EGYPTIAN HIEROGLYPH-139CB;Lo;0;L;;;;;N;;;;; +139CC;EGYPTIAN HIEROGLYPH-139CC;Lo;0;L;;;;;N;;;;; +139CD;EGYPTIAN HIEROGLYPH-139CD;Lo;0;L;;;;;N;;;;; +139CE;EGYPTIAN HIEROGLYPH-139CE;Lo;0;L;;;;;N;;;;; +139CF;EGYPTIAN HIEROGLYPH-139CF;Lo;0;L;;;;;N;;;;; +139D0;EGYPTIAN HIEROGLYPH-139D0;Lo;0;L;;;;;N;;;;; +139D1;EGYPTIAN HIEROGLYPH-139D1;Lo;0;L;;;;;N;;;;; +139D2;EGYPTIAN HIEROGLYPH-139D2;Lo;0;L;;;;;N;;;;; +139D3;EGYPTIAN HIEROGLYPH-139D3;Lo;0;L;;;;;N;;;;; +139D4;EGYPTIAN HIEROGLYPH-139D4;Lo;0;L;;;;;N;;;;; +139D5;EGYPTIAN HIEROGLYPH-139D5;Lo;0;L;;;;;N;;;;; +139D6;EGYPTIAN HIEROGLYPH-139D6;Lo;0;L;;;;;N;;;;; +139D7;EGYPTIAN HIEROGLYPH-139D7;Lo;0;L;;;;;N;;;;; +139D8;EGYPTIAN HIEROGLYPH-139D8;Lo;0;L;;;;;N;;;;; +139D9;EGYPTIAN HIEROGLYPH-139D9;Lo;0;L;;;;;N;;;;; +139DA;EGYPTIAN HIEROGLYPH-139DA;Lo;0;L;;;;;N;;;;; +139DB;EGYPTIAN HIEROGLYPH-139DB;Lo;0;L;;;;;N;;;;; +139DC;EGYPTIAN HIEROGLYPH-139DC;Lo;0;L;;;;;N;;;;; +139DD;EGYPTIAN HIEROGLYPH-139DD;Lo;0;L;;;;;N;;;;; +139DE;EGYPTIAN HIEROGLYPH-139DE;Lo;0;L;;;;;N;;;;; +139DF;EGYPTIAN HIEROGLYPH-139DF;Lo;0;L;;;;;N;;;;; +139E0;EGYPTIAN HIEROGLYPH-139E0;Lo;0;L;;;;;N;;;;; +139E1;EGYPTIAN HIEROGLYPH-139E1;Lo;0;L;;;;;N;;;;; +139E2;EGYPTIAN HIEROGLYPH-139E2;Lo;0;L;;;;;N;;;;; +139E3;EGYPTIAN HIEROGLYPH-139E3;Lo;0;L;;;;;N;;;;; +139E4;EGYPTIAN HIEROGLYPH-139E4;Lo;0;L;;;;;N;;;;; +139E5;EGYPTIAN HIEROGLYPH-139E5;Lo;0;L;;;;;N;;;;; +139E6;EGYPTIAN HIEROGLYPH-139E6;Lo;0;L;;;;;N;;;;; +139E7;EGYPTIAN HIEROGLYPH-139E7;Lo;0;L;;;;;N;;;;; +139E8;EGYPTIAN HIEROGLYPH-139E8;Lo;0;L;;;;;N;;;;; +139E9;EGYPTIAN HIEROGLYPH-139E9;Lo;0;L;;;;;N;;;;; +139EA;EGYPTIAN HIEROGLYPH-139EA;Lo;0;L;;;;;N;;;;; +139EB;EGYPTIAN HIEROGLYPH-139EB;Lo;0;L;;;;;N;;;;; +139EC;EGYPTIAN HIEROGLYPH-139EC;Lo;0;L;;;;;N;;;;; +139ED;EGYPTIAN HIEROGLYPH-139ED;Lo;0;L;;;;;N;;;;; +139EE;EGYPTIAN HIEROGLYPH-139EE;Lo;0;L;;;;;N;;;;; +139EF;EGYPTIAN HIEROGLYPH-139EF;Lo;0;L;;;;;N;;;;; +139F0;EGYPTIAN HIEROGLYPH-139F0;Lo;0;L;;;;;N;;;;; +139F1;EGYPTIAN HIEROGLYPH-139F1;Lo;0;L;;;;;N;;;;; +139F2;EGYPTIAN HIEROGLYPH-139F2;Lo;0;L;;;;;N;;;;; +139F3;EGYPTIAN HIEROGLYPH-139F3;Lo;0;L;;;;;N;;;;; +139F4;EGYPTIAN HIEROGLYPH-139F4;Lo;0;L;;;;;N;;;;; +139F5;EGYPTIAN HIEROGLYPH-139F5;Lo;0;L;;;;;N;;;;; +139F6;EGYPTIAN HIEROGLYPH-139F6;Lo;0;L;;;;;N;;;;; +139F7;EGYPTIAN HIEROGLYPH-139F7;Lo;0;L;;;;;N;;;;; +139F8;EGYPTIAN HIEROGLYPH-139F8;Lo;0;L;;;;;N;;;;; +139F9;EGYPTIAN HIEROGLYPH-139F9;Lo;0;L;;;;;N;;;;; +139FA;EGYPTIAN HIEROGLYPH-139FA;Lo;0;L;;;;;N;;;;; +139FB;EGYPTIAN HIEROGLYPH-139FB;Lo;0;L;;;;;N;;;;; +139FC;EGYPTIAN HIEROGLYPH-139FC;Lo;0;L;;;;;N;;;;; +139FD;EGYPTIAN HIEROGLYPH-139FD;Lo;0;L;;;;;N;;;;; +139FE;EGYPTIAN HIEROGLYPH-139FE;Lo;0;L;;;;;N;;;;; +139FF;EGYPTIAN HIEROGLYPH-139FF;Lo;0;L;;;;;N;;;;; +13A00;EGYPTIAN HIEROGLYPH-13A00;Lo;0;L;;;;;N;;;;; +13A01;EGYPTIAN HIEROGLYPH-13A01;Lo;0;L;;;;;N;;;;; +13A02;EGYPTIAN HIEROGLYPH-13A02;Lo;0;L;;;;;N;;;;; +13A03;EGYPTIAN HIEROGLYPH-13A03;Lo;0;L;;;;;N;;;;; +13A04;EGYPTIAN HIEROGLYPH-13A04;Lo;0;L;;;;;N;;;;; +13A05;EGYPTIAN HIEROGLYPH-13A05;Lo;0;L;;;;;N;;;;; +13A06;EGYPTIAN HIEROGLYPH-13A06;Lo;0;L;;;;;N;;;;; +13A07;EGYPTIAN HIEROGLYPH-13A07;Lo;0;L;;;;;N;;;;; +13A08;EGYPTIAN HIEROGLYPH-13A08;Lo;0;L;;;;;N;;;;; +13A09;EGYPTIAN HIEROGLYPH-13A09;Lo;0;L;;;;;N;;;;; +13A0A;EGYPTIAN HIEROGLYPH-13A0A;Lo;0;L;;;;;N;;;;; +13A0B;EGYPTIAN HIEROGLYPH-13A0B;Lo;0;L;;;;;N;;;;; +13A0C;EGYPTIAN HIEROGLYPH-13A0C;Lo;0;L;;;;;N;;;;; +13A0D;EGYPTIAN HIEROGLYPH-13A0D;Lo;0;L;;;;;N;;;;; +13A0E;EGYPTIAN HIEROGLYPH-13A0E;Lo;0;L;;;;;N;;;;; +13A0F;EGYPTIAN HIEROGLYPH-13A0F;Lo;0;L;;;;;N;;;;; +13A10;EGYPTIAN HIEROGLYPH-13A10;Lo;0;L;;;;;N;;;;; +13A11;EGYPTIAN HIEROGLYPH-13A11;Lo;0;L;;;;;N;;;;; +13A12;EGYPTIAN HIEROGLYPH-13A12;Lo;0;L;;;;;N;;;;; +13A13;EGYPTIAN HIEROGLYPH-13A13;Lo;0;L;;;;;N;;;;; +13A14;EGYPTIAN HIEROGLYPH-13A14;Lo;0;L;;;;;N;;;;; +13A15;EGYPTIAN HIEROGLYPH-13A15;Lo;0;L;;;;;N;;;;; +13A16;EGYPTIAN HIEROGLYPH-13A16;Lo;0;L;;;;;N;;;;; +13A17;EGYPTIAN HIEROGLYPH-13A17;Lo;0;L;;;;;N;;;;; +13A18;EGYPTIAN HIEROGLYPH-13A18;Lo;0;L;;;;;N;;;;; +13A19;EGYPTIAN HIEROGLYPH-13A19;Lo;0;L;;;;;N;;;;; +13A1A;EGYPTIAN HIEROGLYPH-13A1A;Lo;0;L;;;;;N;;;;; +13A1B;EGYPTIAN HIEROGLYPH-13A1B;Lo;0;L;;;;;N;;;;; +13A1C;EGYPTIAN HIEROGLYPH-13A1C;Lo;0;L;;;;;N;;;;; +13A1D;EGYPTIAN HIEROGLYPH-13A1D;Lo;0;L;;;;;N;;;;; +13A1E;EGYPTIAN HIEROGLYPH-13A1E;Lo;0;L;;;;;N;;;;; +13A1F;EGYPTIAN HIEROGLYPH-13A1F;Lo;0;L;;;;;N;;;;; +13A20;EGYPTIAN HIEROGLYPH-13A20;Lo;0;L;;;;;N;;;;; +13A21;EGYPTIAN HIEROGLYPH-13A21;Lo;0;L;;;;;N;;;;; +13A22;EGYPTIAN HIEROGLYPH-13A22;Lo;0;L;;;;;N;;;;; +13A23;EGYPTIAN HIEROGLYPH-13A23;Lo;0;L;;;;;N;;;;; +13A24;EGYPTIAN HIEROGLYPH-13A24;Lo;0;L;;;;;N;;;;; +13A25;EGYPTIAN HIEROGLYPH-13A25;Lo;0;L;;;;;N;;;;; +13A26;EGYPTIAN HIEROGLYPH-13A26;Lo;0;L;;;;;N;;;;; +13A27;EGYPTIAN HIEROGLYPH-13A27;Lo;0;L;;;;;N;;;;; +13A28;EGYPTIAN HIEROGLYPH-13A28;Lo;0;L;;;;;N;;;;; +13A29;EGYPTIAN HIEROGLYPH-13A29;Lo;0;L;;;;;N;;;;; +13A2A;EGYPTIAN HIEROGLYPH-13A2A;Lo;0;L;;;;;N;;;;; +13A2B;EGYPTIAN HIEROGLYPH-13A2B;Lo;0;L;;;;;N;;;;; +13A2C;EGYPTIAN HIEROGLYPH-13A2C;Lo;0;L;;;;;N;;;;; +13A2D;EGYPTIAN HIEROGLYPH-13A2D;Lo;0;L;;;;;N;;;;; +13A2E;EGYPTIAN HIEROGLYPH-13A2E;Lo;0;L;;;;;N;;;;; +13A2F;EGYPTIAN HIEROGLYPH-13A2F;Lo;0;L;;;;;N;;;;; +13A30;EGYPTIAN HIEROGLYPH-13A30;Lo;0;L;;;;;N;;;;; +13A31;EGYPTIAN HIEROGLYPH-13A31;Lo;0;L;;;;;N;;;;; +13A32;EGYPTIAN HIEROGLYPH-13A32;Lo;0;L;;;;;N;;;;; +13A33;EGYPTIAN HIEROGLYPH-13A33;Lo;0;L;;;;;N;;;;; +13A34;EGYPTIAN HIEROGLYPH-13A34;Lo;0;L;;;;;N;;;;; +13A35;EGYPTIAN HIEROGLYPH-13A35;Lo;0;L;;;;;N;;;;; +13A36;EGYPTIAN HIEROGLYPH-13A36;Lo;0;L;;;;;N;;;;; +13A37;EGYPTIAN HIEROGLYPH-13A37;Lo;0;L;;;;;N;;;;; +13A38;EGYPTIAN HIEROGLYPH-13A38;Lo;0;L;;;;;N;;;;; +13A39;EGYPTIAN HIEROGLYPH-13A39;Lo;0;L;;;;;N;;;;; +13A3A;EGYPTIAN HIEROGLYPH-13A3A;Lo;0;L;;;;;N;;;;; +13A3B;EGYPTIAN HIEROGLYPH-13A3B;Lo;0;L;;;;;N;;;;; +13A3C;EGYPTIAN HIEROGLYPH-13A3C;Lo;0;L;;;;;N;;;;; +13A3D;EGYPTIAN HIEROGLYPH-13A3D;Lo;0;L;;;;;N;;;;; +13A3E;EGYPTIAN HIEROGLYPH-13A3E;Lo;0;L;;;;;N;;;;; +13A3F;EGYPTIAN HIEROGLYPH-13A3F;Lo;0;L;;;;;N;;;;; +13A40;EGYPTIAN HIEROGLYPH-13A40;Lo;0;L;;;;;N;;;;; +13A41;EGYPTIAN HIEROGLYPH-13A41;Lo;0;L;;;;;N;;;;; +13A42;EGYPTIAN HIEROGLYPH-13A42;Lo;0;L;;;;;N;;;;; +13A43;EGYPTIAN HIEROGLYPH-13A43;Lo;0;L;;;;;N;;;;; +13A44;EGYPTIAN HIEROGLYPH-13A44;Lo;0;L;;;;;N;;;;; +13A45;EGYPTIAN HIEROGLYPH-13A45;Lo;0;L;;;;;N;;;;; +13A46;EGYPTIAN HIEROGLYPH-13A46;Lo;0;L;;;;;N;;;;; +13A47;EGYPTIAN HIEROGLYPH-13A47;Lo;0;L;;;;;N;;;;; +13A48;EGYPTIAN HIEROGLYPH-13A48;Lo;0;L;;;;;N;;;;; +13A49;EGYPTIAN HIEROGLYPH-13A49;Lo;0;L;;;;;N;;;;; +13A4A;EGYPTIAN HIEROGLYPH-13A4A;Lo;0;L;;;;;N;;;;; +13A4B;EGYPTIAN HIEROGLYPH-13A4B;Lo;0;L;;;;;N;;;;; +13A4C;EGYPTIAN HIEROGLYPH-13A4C;Lo;0;L;;;;;N;;;;; +13A4D;EGYPTIAN HIEROGLYPH-13A4D;Lo;0;L;;;;;N;;;;; +13A4E;EGYPTIAN HIEROGLYPH-13A4E;Lo;0;L;;;;;N;;;;; +13A4F;EGYPTIAN HIEROGLYPH-13A4F;Lo;0;L;;;;;N;;;;; +13A50;EGYPTIAN HIEROGLYPH-13A50;Lo;0;L;;;;;N;;;;; +13A51;EGYPTIAN HIEROGLYPH-13A51;Lo;0;L;;;;;N;;;;; +13A52;EGYPTIAN HIEROGLYPH-13A52;Lo;0;L;;;;;N;;;;; +13A53;EGYPTIAN HIEROGLYPH-13A53;Lo;0;L;;;;;N;;;;; +13A54;EGYPTIAN HIEROGLYPH-13A54;Lo;0;L;;;;;N;;;;; +13A55;EGYPTIAN HIEROGLYPH-13A55;Lo;0;L;;;;;N;;;;; +13A56;EGYPTIAN HIEROGLYPH-13A56;Lo;0;L;;;;;N;;;;; +13A57;EGYPTIAN HIEROGLYPH-13A57;Lo;0;L;;;;;N;;;;; +13A58;EGYPTIAN HIEROGLYPH-13A58;Lo;0;L;;;;;N;;;;; +13A59;EGYPTIAN HIEROGLYPH-13A59;Lo;0;L;;;;;N;;;;; +13A5A;EGYPTIAN HIEROGLYPH-13A5A;Lo;0;L;;;;;N;;;;; +13A5B;EGYPTIAN HIEROGLYPH-13A5B;Lo;0;L;;;;;N;;;;; +13A5C;EGYPTIAN HIEROGLYPH-13A5C;Lo;0;L;;;;;N;;;;; +13A5D;EGYPTIAN HIEROGLYPH-13A5D;Lo;0;L;;;;;N;;;;; +13A5E;EGYPTIAN HIEROGLYPH-13A5E;Lo;0;L;;;;;N;;;;; +13A5F;EGYPTIAN HIEROGLYPH-13A5F;Lo;0;L;;;;;N;;;;; +13A60;EGYPTIAN HIEROGLYPH-13A60;Lo;0;L;;;;;N;;;;; +13A61;EGYPTIAN HIEROGLYPH-13A61;Lo;0;L;;;;;N;;;;; +13A62;EGYPTIAN HIEROGLYPH-13A62;Lo;0;L;;;;;N;;;;; +13A63;EGYPTIAN HIEROGLYPH-13A63;Lo;0;L;;;;;N;;;;; +13A64;EGYPTIAN HIEROGLYPH-13A64;Lo;0;L;;;;;N;;;;; +13A65;EGYPTIAN HIEROGLYPH-13A65;Lo;0;L;;;;;N;;;;; +13A66;EGYPTIAN HIEROGLYPH-13A66;Lo;0;L;;;;;N;;;;; +13A67;EGYPTIAN HIEROGLYPH-13A67;Lo;0;L;;;;;N;;;;; +13A68;EGYPTIAN HIEROGLYPH-13A68;Lo;0;L;;;;;N;;;;; +13A69;EGYPTIAN HIEROGLYPH-13A69;Lo;0;L;;;;;N;;;;; +13A6A;EGYPTIAN HIEROGLYPH-13A6A;Lo;0;L;;;;;N;;;;; +13A6B;EGYPTIAN HIEROGLYPH-13A6B;Lo;0;L;;;;;N;;;;; +13A6C;EGYPTIAN HIEROGLYPH-13A6C;Lo;0;L;;;;;N;;;;; +13A6D;EGYPTIAN HIEROGLYPH-13A6D;Lo;0;L;;;;;N;;;;; +13A6E;EGYPTIAN HIEROGLYPH-13A6E;Lo;0;L;;;;;N;;;;; +13A6F;EGYPTIAN HIEROGLYPH-13A6F;Lo;0;L;;;;;N;;;;; +13A70;EGYPTIAN HIEROGLYPH-13A70;Lo;0;L;;;;;N;;;;; +13A71;EGYPTIAN HIEROGLYPH-13A71;Lo;0;L;;;;;N;;;;; +13A72;EGYPTIAN HIEROGLYPH-13A72;Lo;0;L;;;;;N;;;;; +13A73;EGYPTIAN HIEROGLYPH-13A73;Lo;0;L;;;;;N;;;;; +13A74;EGYPTIAN HIEROGLYPH-13A74;Lo;0;L;;;;;N;;;;; +13A75;EGYPTIAN HIEROGLYPH-13A75;Lo;0;L;;;;;N;;;;; +13A76;EGYPTIAN HIEROGLYPH-13A76;Lo;0;L;;;;;N;;;;; +13A77;EGYPTIAN HIEROGLYPH-13A77;Lo;0;L;;;;;N;;;;; +13A78;EGYPTIAN HIEROGLYPH-13A78;Lo;0;L;;;;;N;;;;; +13A79;EGYPTIAN HIEROGLYPH-13A79;Lo;0;L;;;;;N;;;;; +13A7A;EGYPTIAN HIEROGLYPH-13A7A;Lo;0;L;;;;;N;;;;; +13A7B;EGYPTIAN HIEROGLYPH-13A7B;Lo;0;L;;;;;N;;;;; +13A7C;EGYPTIAN HIEROGLYPH-13A7C;Lo;0;L;;;;;N;;;;; +13A7D;EGYPTIAN HIEROGLYPH-13A7D;Lo;0;L;;;;;N;;;;; +13A7E;EGYPTIAN HIEROGLYPH-13A7E;Lo;0;L;;;;;N;;;;; +13A7F;EGYPTIAN HIEROGLYPH-13A7F;Lo;0;L;;;;;N;;;;; +13A80;EGYPTIAN HIEROGLYPH-13A80;Lo;0;L;;;;;N;;;;; +13A81;EGYPTIAN HIEROGLYPH-13A81;Lo;0;L;;;;;N;;;;; +13A82;EGYPTIAN HIEROGLYPH-13A82;Lo;0;L;;;;;N;;;;; +13A83;EGYPTIAN HIEROGLYPH-13A83;Lo;0;L;;;;;N;;;;; +13A84;EGYPTIAN HIEROGLYPH-13A84;Lo;0;L;;;;;N;;;;; +13A85;EGYPTIAN HIEROGLYPH-13A85;Lo;0;L;;;;;N;;;;; +13A86;EGYPTIAN HIEROGLYPH-13A86;Lo;0;L;;;;;N;;;;; +13A87;EGYPTIAN HIEROGLYPH-13A87;Lo;0;L;;;;;N;;;;; +13A88;EGYPTIAN HIEROGLYPH-13A88;Lo;0;L;;;;;N;;;;; +13A89;EGYPTIAN HIEROGLYPH-13A89;Lo;0;L;;;;;N;;;;; +13A8A;EGYPTIAN HIEROGLYPH-13A8A;Lo;0;L;;;;;N;;;;; +13A8B;EGYPTIAN HIEROGLYPH-13A8B;Lo;0;L;;;;;N;;;;; +13A8C;EGYPTIAN HIEROGLYPH-13A8C;Lo;0;L;;;;;N;;;;; +13A8D;EGYPTIAN HIEROGLYPH-13A8D;Lo;0;L;;;;;N;;;;; +13A8E;EGYPTIAN HIEROGLYPH-13A8E;Lo;0;L;;;;;N;;;;; +13A8F;EGYPTIAN HIEROGLYPH-13A8F;Lo;0;L;;;;;N;;;;; +13A90;EGYPTIAN HIEROGLYPH-13A90;Lo;0;L;;;;;N;;;;; +13A91;EGYPTIAN HIEROGLYPH-13A91;Lo;0;L;;;;;N;;;;; +13A92;EGYPTIAN HIEROGLYPH-13A92;Lo;0;L;;;;;N;;;;; +13A93;EGYPTIAN HIEROGLYPH-13A93;Lo;0;L;;;;;N;;;;; +13A94;EGYPTIAN HIEROGLYPH-13A94;Lo;0;L;;;;;N;;;;; +13A95;EGYPTIAN HIEROGLYPH-13A95;Lo;0;L;;;;;N;;;;; +13A96;EGYPTIAN HIEROGLYPH-13A96;Lo;0;L;;;;;N;;;;; +13A97;EGYPTIAN HIEROGLYPH-13A97;Lo;0;L;;;;;N;;;;; +13A98;EGYPTIAN HIEROGLYPH-13A98;Lo;0;L;;;;;N;;;;; +13A99;EGYPTIAN HIEROGLYPH-13A99;Lo;0;L;;;;;N;;;;; +13A9A;EGYPTIAN HIEROGLYPH-13A9A;Lo;0;L;;;;;N;;;;; +13A9B;EGYPTIAN HIEROGLYPH-13A9B;Lo;0;L;;;;;N;;;;; +13A9C;EGYPTIAN HIEROGLYPH-13A9C;Lo;0;L;;;;;N;;;;; +13A9D;EGYPTIAN HIEROGLYPH-13A9D;Lo;0;L;;;;;N;;;;; +13A9E;EGYPTIAN HIEROGLYPH-13A9E;Lo;0;L;;;;;N;;;;; +13A9F;EGYPTIAN HIEROGLYPH-13A9F;Lo;0;L;;;;;N;;;;; +13AA0;EGYPTIAN HIEROGLYPH-13AA0;Lo;0;L;;;;;N;;;;; +13AA1;EGYPTIAN HIEROGLYPH-13AA1;Lo;0;L;;;;;N;;;;; +13AA2;EGYPTIAN HIEROGLYPH-13AA2;Lo;0;L;;;;;N;;;;; +13AA3;EGYPTIAN HIEROGLYPH-13AA3;Lo;0;L;;;;;N;;;;; +13AA4;EGYPTIAN HIEROGLYPH-13AA4;Lo;0;L;;;;;N;;;;; +13AA5;EGYPTIAN HIEROGLYPH-13AA5;Lo;0;L;;;;;N;;;;; +13AA6;EGYPTIAN HIEROGLYPH-13AA6;Lo;0;L;;;;;N;;;;; +13AA7;EGYPTIAN HIEROGLYPH-13AA7;Lo;0;L;;;;;N;;;;; +13AA8;EGYPTIAN HIEROGLYPH-13AA8;Lo;0;L;;;;;N;;;;; +13AA9;EGYPTIAN HIEROGLYPH-13AA9;Lo;0;L;;;;;N;;;;; +13AAA;EGYPTIAN HIEROGLYPH-13AAA;Lo;0;L;;;;;N;;;;; +13AAB;EGYPTIAN HIEROGLYPH-13AAB;Lo;0;L;;;;;N;;;;; +13AAC;EGYPTIAN HIEROGLYPH-13AAC;Lo;0;L;;;;;N;;;;; +13AAD;EGYPTIAN HIEROGLYPH-13AAD;Lo;0;L;;;;;N;;;;; +13AAE;EGYPTIAN HIEROGLYPH-13AAE;Lo;0;L;;;;;N;;;;; +13AAF;EGYPTIAN HIEROGLYPH-13AAF;Lo;0;L;;;;;N;;;;; +13AB0;EGYPTIAN HIEROGLYPH-13AB0;Lo;0;L;;;;;N;;;;; +13AB1;EGYPTIAN HIEROGLYPH-13AB1;Lo;0;L;;;;;N;;;;; +13AB2;EGYPTIAN HIEROGLYPH-13AB2;Lo;0;L;;;;;N;;;;; +13AB3;EGYPTIAN HIEROGLYPH-13AB3;Lo;0;L;;;;;N;;;;; +13AB4;EGYPTIAN HIEROGLYPH-13AB4;Lo;0;L;;;;;N;;;;; +13AB5;EGYPTIAN HIEROGLYPH-13AB5;Lo;0;L;;;;;N;;;;; +13AB6;EGYPTIAN HIEROGLYPH-13AB6;Lo;0;L;;;;;N;;;;; +13AB7;EGYPTIAN HIEROGLYPH-13AB7;Lo;0;L;;;;;N;;;;; +13AB8;EGYPTIAN HIEROGLYPH-13AB8;Lo;0;L;;;;;N;;;;; +13AB9;EGYPTIAN HIEROGLYPH-13AB9;Lo;0;L;;;;;N;;;;; +13ABA;EGYPTIAN HIEROGLYPH-13ABA;Lo;0;L;;;;;N;;;;; +13ABB;EGYPTIAN HIEROGLYPH-13ABB;Lo;0;L;;;;;N;;;;; +13ABC;EGYPTIAN HIEROGLYPH-13ABC;Lo;0;L;;;;;N;;;;; +13ABD;EGYPTIAN HIEROGLYPH-13ABD;Lo;0;L;;;;;N;;;;; +13ABE;EGYPTIAN HIEROGLYPH-13ABE;Lo;0;L;;;;;N;;;;; +13ABF;EGYPTIAN HIEROGLYPH-13ABF;Lo;0;L;;;;;N;;;;; +13AC0;EGYPTIAN HIEROGLYPH-13AC0;Lo;0;L;;;;;N;;;;; +13AC1;EGYPTIAN HIEROGLYPH-13AC1;Lo;0;L;;;;;N;;;;; +13AC2;EGYPTIAN HIEROGLYPH-13AC2;Lo;0;L;;;;;N;;;;; +13AC3;EGYPTIAN HIEROGLYPH-13AC3;Lo;0;L;;;;;N;;;;; +13AC4;EGYPTIAN HIEROGLYPH-13AC4;Lo;0;L;;;;;N;;;;; +13AC5;EGYPTIAN HIEROGLYPH-13AC5;Lo;0;L;;;;;N;;;;; +13AC6;EGYPTIAN HIEROGLYPH-13AC6;Lo;0;L;;;;;N;;;;; +13AC7;EGYPTIAN HIEROGLYPH-13AC7;Lo;0;L;;;;;N;;;;; +13AC8;EGYPTIAN HIEROGLYPH-13AC8;Lo;0;L;;;;;N;;;;; +13AC9;EGYPTIAN HIEROGLYPH-13AC9;Lo;0;L;;;;;N;;;;; +13ACA;EGYPTIAN HIEROGLYPH-13ACA;Lo;0;L;;;;;N;;;;; +13ACB;EGYPTIAN HIEROGLYPH-13ACB;Lo;0;L;;;;;N;;;;; +13ACC;EGYPTIAN HIEROGLYPH-13ACC;Lo;0;L;;;;;N;;;;; +13ACD;EGYPTIAN HIEROGLYPH-13ACD;Lo;0;L;;;;;N;;;;; +13ACE;EGYPTIAN HIEROGLYPH-13ACE;Lo;0;L;;;;;N;;;;; +13ACF;EGYPTIAN HIEROGLYPH-13ACF;Lo;0;L;;;;;N;;;;; +13AD0;EGYPTIAN HIEROGLYPH-13AD0;Lo;0;L;;;;;N;;;;; +13AD1;EGYPTIAN HIEROGLYPH-13AD1;Lo;0;L;;;;;N;;;;; +13AD2;EGYPTIAN HIEROGLYPH-13AD2;Lo;0;L;;;;;N;;;;; +13AD3;EGYPTIAN HIEROGLYPH-13AD3;Lo;0;L;;;;;N;;;;; +13AD4;EGYPTIAN HIEROGLYPH-13AD4;Lo;0;L;;;;;N;;;;; +13AD5;EGYPTIAN HIEROGLYPH-13AD5;Lo;0;L;;;;;N;;;;; +13AD6;EGYPTIAN HIEROGLYPH-13AD6;Lo;0;L;;;;;N;;;;; +13AD7;EGYPTIAN HIEROGLYPH-13AD7;Lo;0;L;;;;;N;;;;; +13AD8;EGYPTIAN HIEROGLYPH-13AD8;Lo;0;L;;;;;N;;;;; +13AD9;EGYPTIAN HIEROGLYPH-13AD9;Lo;0;L;;;;;N;;;;; +13ADA;EGYPTIAN HIEROGLYPH-13ADA;Lo;0;L;;;;;N;;;;; +13ADB;EGYPTIAN HIEROGLYPH-13ADB;Lo;0;L;;;;;N;;;;; +13ADC;EGYPTIAN HIEROGLYPH-13ADC;Lo;0;L;;;;;N;;;;; +13ADD;EGYPTIAN HIEROGLYPH-13ADD;Lo;0;L;;;;;N;;;;; +13ADE;EGYPTIAN HIEROGLYPH-13ADE;Lo;0;L;;;;;N;;;;; +13ADF;EGYPTIAN HIEROGLYPH-13ADF;Lo;0;L;;;;;N;;;;; +13AE0;EGYPTIAN HIEROGLYPH-13AE0;Lo;0;L;;;;;N;;;;; +13AE1;EGYPTIAN HIEROGLYPH-13AE1;Lo;0;L;;;;;N;;;;; +13AE2;EGYPTIAN HIEROGLYPH-13AE2;Lo;0;L;;;;;N;;;;; +13AE3;EGYPTIAN HIEROGLYPH-13AE3;Lo;0;L;;;;;N;;;;; +13AE4;EGYPTIAN HIEROGLYPH-13AE4;Lo;0;L;;;;;N;;;;; +13AE5;EGYPTIAN HIEROGLYPH-13AE5;Lo;0;L;;;;;N;;;;; +13AE6;EGYPTIAN HIEROGLYPH-13AE6;Lo;0;L;;;;;N;;;;; +13AE7;EGYPTIAN HIEROGLYPH-13AE7;Lo;0;L;;;;;N;;;;; +13AE8;EGYPTIAN HIEROGLYPH-13AE8;Lo;0;L;;;;;N;;;;; +13AE9;EGYPTIAN HIEROGLYPH-13AE9;Lo;0;L;;;;;N;;;;; +13AEA;EGYPTIAN HIEROGLYPH-13AEA;Lo;0;L;;;;;N;;;;; +13AEB;EGYPTIAN HIEROGLYPH-13AEB;Lo;0;L;;;;;N;;;;; +13AEC;EGYPTIAN HIEROGLYPH-13AEC;Lo;0;L;;;;;N;;;;; +13AED;EGYPTIAN HIEROGLYPH-13AED;Lo;0;L;;;;;N;;;;; +13AEE;EGYPTIAN HIEROGLYPH-13AEE;Lo;0;L;;;;;N;;;;; +13AEF;EGYPTIAN HIEROGLYPH-13AEF;Lo;0;L;;;;;N;;;;; +13AF0;EGYPTIAN HIEROGLYPH-13AF0;Lo;0;L;;;;;N;;;;; +13AF1;EGYPTIAN HIEROGLYPH-13AF1;Lo;0;L;;;;;N;;;;; +13AF2;EGYPTIAN HIEROGLYPH-13AF2;Lo;0;L;;;;;N;;;;; +13AF3;EGYPTIAN HIEROGLYPH-13AF3;Lo;0;L;;;;;N;;;;; +13AF4;EGYPTIAN HIEROGLYPH-13AF4;Lo;0;L;;;;;N;;;;; +13AF5;EGYPTIAN HIEROGLYPH-13AF5;Lo;0;L;;;;;N;;;;; +13AF6;EGYPTIAN HIEROGLYPH-13AF6;Lo;0;L;;;;;N;;;;; +13AF7;EGYPTIAN HIEROGLYPH-13AF7;Lo;0;L;;;;;N;;;;; +13AF8;EGYPTIAN HIEROGLYPH-13AF8;Lo;0;L;;;;;N;;;;; +13AF9;EGYPTIAN HIEROGLYPH-13AF9;Lo;0;L;;;;;N;;;;; +13AFA;EGYPTIAN HIEROGLYPH-13AFA;Lo;0;L;;;;;N;;;;; +13AFB;EGYPTIAN HIEROGLYPH-13AFB;Lo;0;L;;;;;N;;;;; +13AFC;EGYPTIAN HIEROGLYPH-13AFC;Lo;0;L;;;;;N;;;;; +13AFD;EGYPTIAN HIEROGLYPH-13AFD;Lo;0;L;;;;;N;;;;; +13AFE;EGYPTIAN HIEROGLYPH-13AFE;Lo;0;L;;;;;N;;;;; +13AFF;EGYPTIAN HIEROGLYPH-13AFF;Lo;0;L;;;;;N;;;;; +13B00;EGYPTIAN HIEROGLYPH-13B00;Lo;0;L;;;;;N;;;;; +13B01;EGYPTIAN HIEROGLYPH-13B01;Lo;0;L;;;;;N;;;;; +13B02;EGYPTIAN HIEROGLYPH-13B02;Lo;0;L;;;;;N;;;;; +13B03;EGYPTIAN HIEROGLYPH-13B03;Lo;0;L;;;;;N;;;;; +13B04;EGYPTIAN HIEROGLYPH-13B04;Lo;0;L;;;;;N;;;;; +13B05;EGYPTIAN HIEROGLYPH-13B05;Lo;0;L;;;;;N;;;;; +13B06;EGYPTIAN HIEROGLYPH-13B06;Lo;0;L;;;;;N;;;;; +13B07;EGYPTIAN HIEROGLYPH-13B07;Lo;0;L;;;;;N;;;;; +13B08;EGYPTIAN HIEROGLYPH-13B08;Lo;0;L;;;;;N;;;;; +13B09;EGYPTIAN HIEROGLYPH-13B09;Lo;0;L;;;;;N;;;;; +13B0A;EGYPTIAN HIEROGLYPH-13B0A;Lo;0;L;;;;;N;;;;; +13B0B;EGYPTIAN HIEROGLYPH-13B0B;Lo;0;L;;;;;N;;;;; +13B0C;EGYPTIAN HIEROGLYPH-13B0C;Lo;0;L;;;;;N;;;;; +13B0D;EGYPTIAN HIEROGLYPH-13B0D;Lo;0;L;;;;;N;;;;; +13B0E;EGYPTIAN HIEROGLYPH-13B0E;Lo;0;L;;;;;N;;;;; +13B0F;EGYPTIAN HIEROGLYPH-13B0F;Lo;0;L;;;;;N;;;;; +13B10;EGYPTIAN HIEROGLYPH-13B10;Lo;0;L;;;;;N;;;;; +13B11;EGYPTIAN HIEROGLYPH-13B11;Lo;0;L;;;;;N;;;;; +13B12;EGYPTIAN HIEROGLYPH-13B12;Lo;0;L;;;;;N;;;;; +13B13;EGYPTIAN HIEROGLYPH-13B13;Lo;0;L;;;;;N;;;;; +13B14;EGYPTIAN HIEROGLYPH-13B14;Lo;0;L;;;;;N;;;;; +13B15;EGYPTIAN HIEROGLYPH-13B15;Lo;0;L;;;;;N;;;;; +13B16;EGYPTIAN HIEROGLYPH-13B16;Lo;0;L;;;;;N;;;;; +13B17;EGYPTIAN HIEROGLYPH-13B17;Lo;0;L;;;;;N;;;;; +13B18;EGYPTIAN HIEROGLYPH-13B18;Lo;0;L;;;;;N;;;;; +13B19;EGYPTIAN HIEROGLYPH-13B19;Lo;0;L;;;;;N;;;;; +13B1A;EGYPTIAN HIEROGLYPH-13B1A;Lo;0;L;;;;;N;;;;; +13B1B;EGYPTIAN HIEROGLYPH-13B1B;Lo;0;L;;;;;N;;;;; +13B1C;EGYPTIAN HIEROGLYPH-13B1C;Lo;0;L;;;;;N;;;;; +13B1D;EGYPTIAN HIEROGLYPH-13B1D;Lo;0;L;;;;;N;;;;; +13B1E;EGYPTIAN HIEROGLYPH-13B1E;Lo;0;L;;;;;N;;;;; +13B1F;EGYPTIAN HIEROGLYPH-13B1F;Lo;0;L;;;;;N;;;;; +13B20;EGYPTIAN HIEROGLYPH-13B20;Lo;0;L;;;;;N;;;;; +13B21;EGYPTIAN HIEROGLYPH-13B21;Lo;0;L;;;;;N;;;;; +13B22;EGYPTIAN HIEROGLYPH-13B22;Lo;0;L;;;;;N;;;;; +13B23;EGYPTIAN HIEROGLYPH-13B23;Lo;0;L;;;;;N;;;;; +13B24;EGYPTIAN HIEROGLYPH-13B24;Lo;0;L;;;;;N;;;;; +13B25;EGYPTIAN HIEROGLYPH-13B25;Lo;0;L;;;;;N;;;;; +13B26;EGYPTIAN HIEROGLYPH-13B26;Lo;0;L;;;;;N;;;;; +13B27;EGYPTIAN HIEROGLYPH-13B27;Lo;0;L;;;;;N;;;;; +13B28;EGYPTIAN HIEROGLYPH-13B28;Lo;0;L;;;;;N;;;;; +13B29;EGYPTIAN HIEROGLYPH-13B29;Lo;0;L;;;;;N;;;;; +13B2A;EGYPTIAN HIEROGLYPH-13B2A;Lo;0;L;;;;;N;;;;; +13B2B;EGYPTIAN HIEROGLYPH-13B2B;Lo;0;L;;;;;N;;;;; +13B2C;EGYPTIAN HIEROGLYPH-13B2C;Lo;0;L;;;;;N;;;;; +13B2D;EGYPTIAN HIEROGLYPH-13B2D;Lo;0;L;;;;;N;;;;; +13B2E;EGYPTIAN HIEROGLYPH-13B2E;Lo;0;L;;;;;N;;;;; +13B2F;EGYPTIAN HIEROGLYPH-13B2F;Lo;0;L;;;;;N;;;;; +13B30;EGYPTIAN HIEROGLYPH-13B30;Lo;0;L;;;;;N;;;;; +13B31;EGYPTIAN HIEROGLYPH-13B31;Lo;0;L;;;;;N;;;;; +13B32;EGYPTIAN HIEROGLYPH-13B32;Lo;0;L;;;;;N;;;;; +13B33;EGYPTIAN HIEROGLYPH-13B33;Lo;0;L;;;;;N;;;;; +13B34;EGYPTIAN HIEROGLYPH-13B34;Lo;0;L;;;;;N;;;;; +13B35;EGYPTIAN HIEROGLYPH-13B35;Lo;0;L;;;;;N;;;;; +13B36;EGYPTIAN HIEROGLYPH-13B36;Lo;0;L;;;;;N;;;;; +13B37;EGYPTIAN HIEROGLYPH-13B37;Lo;0;L;;;;;N;;;;; +13B38;EGYPTIAN HIEROGLYPH-13B38;Lo;0;L;;;;;N;;;;; +13B39;EGYPTIAN HIEROGLYPH-13B39;Lo;0;L;;;;;N;;;;; +13B3A;EGYPTIAN HIEROGLYPH-13B3A;Lo;0;L;;;;;N;;;;; +13B3B;EGYPTIAN HIEROGLYPH-13B3B;Lo;0;L;;;;;N;;;;; +13B3C;EGYPTIAN HIEROGLYPH-13B3C;Lo;0;L;;;;;N;;;;; +13B3D;EGYPTIAN HIEROGLYPH-13B3D;Lo;0;L;;;;;N;;;;; +13B3E;EGYPTIAN HIEROGLYPH-13B3E;Lo;0;L;;;;;N;;;;; +13B3F;EGYPTIAN HIEROGLYPH-13B3F;Lo;0;L;;;;;N;;;;; +13B40;EGYPTIAN HIEROGLYPH-13B40;Lo;0;L;;;;;N;;;;; +13B41;EGYPTIAN HIEROGLYPH-13B41;Lo;0;L;;;;;N;;;;; +13B42;EGYPTIAN HIEROGLYPH-13B42;Lo;0;L;;;;;N;;;;; +13B43;EGYPTIAN HIEROGLYPH-13B43;Lo;0;L;;;;;N;;;;; +13B44;EGYPTIAN HIEROGLYPH-13B44;Lo;0;L;;;;;N;;;;; +13B45;EGYPTIAN HIEROGLYPH-13B45;Lo;0;L;;;;;N;;;;; +13B46;EGYPTIAN HIEROGLYPH-13B46;Lo;0;L;;;;;N;;;;; +13B47;EGYPTIAN HIEROGLYPH-13B47;Lo;0;L;;;;;N;;;;; +13B48;EGYPTIAN HIEROGLYPH-13B48;Lo;0;L;;;;;N;;;;; +13B49;EGYPTIAN HIEROGLYPH-13B49;Lo;0;L;;;;;N;;;;; +13B4A;EGYPTIAN HIEROGLYPH-13B4A;Lo;0;L;;;;;N;;;;; +13B4B;EGYPTIAN HIEROGLYPH-13B4B;Lo;0;L;;;;;N;;;;; +13B4C;EGYPTIAN HIEROGLYPH-13B4C;Lo;0;L;;;;;N;;;;; +13B4D;EGYPTIAN HIEROGLYPH-13B4D;Lo;0;L;;;;;N;;;;; +13B4E;EGYPTIAN HIEROGLYPH-13B4E;Lo;0;L;;;;;N;;;;; +13B4F;EGYPTIAN HIEROGLYPH-13B4F;Lo;0;L;;;;;N;;;;; +13B50;EGYPTIAN HIEROGLYPH-13B50;Lo;0;L;;;;;N;;;;; +13B51;EGYPTIAN HIEROGLYPH-13B51;Lo;0;L;;;;;N;;;;; +13B52;EGYPTIAN HIEROGLYPH-13B52;Lo;0;L;;;;;N;;;;; +13B53;EGYPTIAN HIEROGLYPH-13B53;Lo;0;L;;;;;N;;;;; +13B54;EGYPTIAN HIEROGLYPH-13B54;Lo;0;L;;;;;N;;;;; +13B55;EGYPTIAN HIEROGLYPH-13B55;Lo;0;L;;;;;N;;;;; +13B56;EGYPTIAN HIEROGLYPH-13B56;Lo;0;L;;;;;N;;;;; +13B57;EGYPTIAN HIEROGLYPH-13B57;Lo;0;L;;;;;N;;;;; +13B58;EGYPTIAN HIEROGLYPH-13B58;Lo;0;L;;;;;N;;;;; +13B59;EGYPTIAN HIEROGLYPH-13B59;Lo;0;L;;;;;N;;;;; +13B5A;EGYPTIAN HIEROGLYPH-13B5A;Lo;0;L;;;;;N;;;;; +13B5B;EGYPTIAN HIEROGLYPH-13B5B;Lo;0;L;;;;;N;;;;; +13B5C;EGYPTIAN HIEROGLYPH-13B5C;Lo;0;L;;;;;N;;;;; +13B5D;EGYPTIAN HIEROGLYPH-13B5D;Lo;0;L;;;;;N;;;;; +13B5E;EGYPTIAN HIEROGLYPH-13B5E;Lo;0;L;;;;;N;;;;; +13B5F;EGYPTIAN HIEROGLYPH-13B5F;Lo;0;L;;;;;N;;;;; +13B60;EGYPTIAN HIEROGLYPH-13B60;Lo;0;L;;;;;N;;;;; +13B61;EGYPTIAN HIEROGLYPH-13B61;Lo;0;L;;;;;N;;;;; +13B62;EGYPTIAN HIEROGLYPH-13B62;Lo;0;L;;;;;N;;;;; +13B63;EGYPTIAN HIEROGLYPH-13B63;Lo;0;L;;;;;N;;;;; +13B64;EGYPTIAN HIEROGLYPH-13B64;Lo;0;L;;;;;N;;;;; +13B65;EGYPTIAN HIEROGLYPH-13B65;Lo;0;L;;;;;N;;;;; +13B66;EGYPTIAN HIEROGLYPH-13B66;Lo;0;L;;;;;N;;;;; +13B67;EGYPTIAN HIEROGLYPH-13B67;Lo;0;L;;;;;N;;;;; +13B68;EGYPTIAN HIEROGLYPH-13B68;Lo;0;L;;;;;N;;;;; +13B69;EGYPTIAN HIEROGLYPH-13B69;Lo;0;L;;;;;N;;;;; +13B6A;EGYPTIAN HIEROGLYPH-13B6A;Lo;0;L;;;;;N;;;;; +13B6B;EGYPTIAN HIEROGLYPH-13B6B;Lo;0;L;;;;;N;;;;; +13B6C;EGYPTIAN HIEROGLYPH-13B6C;Lo;0;L;;;;;N;;;;; +13B6D;EGYPTIAN HIEROGLYPH-13B6D;Lo;0;L;;;;;N;;;;; +13B6E;EGYPTIAN HIEROGLYPH-13B6E;Lo;0;L;;;;;N;;;;; +13B6F;EGYPTIAN HIEROGLYPH-13B6F;Lo;0;L;;;;;N;;;;; +13B70;EGYPTIAN HIEROGLYPH-13B70;Lo;0;L;;;;;N;;;;; +13B71;EGYPTIAN HIEROGLYPH-13B71;Lo;0;L;;;;;N;;;;; +13B72;EGYPTIAN HIEROGLYPH-13B72;Lo;0;L;;;;;N;;;;; +13B73;EGYPTIAN HIEROGLYPH-13B73;Lo;0;L;;;;;N;;;;; +13B74;EGYPTIAN HIEROGLYPH-13B74;Lo;0;L;;;;;N;;;;; +13B75;EGYPTIAN HIEROGLYPH-13B75;Lo;0;L;;;;;N;;;;; +13B76;EGYPTIAN HIEROGLYPH-13B76;Lo;0;L;;;;;N;;;;; +13B77;EGYPTIAN HIEROGLYPH-13B77;Lo;0;L;;;;;N;;;;; +13B78;EGYPTIAN HIEROGLYPH-13B78;Lo;0;L;;;;;N;;;;; +13B79;EGYPTIAN HIEROGLYPH-13B79;Lo;0;L;;;;;N;;;;; +13B7A;EGYPTIAN HIEROGLYPH-13B7A;Lo;0;L;;;;;N;;;;; +13B7B;EGYPTIAN HIEROGLYPH-13B7B;Lo;0;L;;;;;N;;;;; +13B7C;EGYPTIAN HIEROGLYPH-13B7C;Lo;0;L;;;;;N;;;;; +13B7D;EGYPTIAN HIEROGLYPH-13B7D;Lo;0;L;;;;;N;;;;; +13B7E;EGYPTIAN HIEROGLYPH-13B7E;Lo;0;L;;;;;N;;;;; +13B7F;EGYPTIAN HIEROGLYPH-13B7F;Lo;0;L;;;;;N;;;;; +13B80;EGYPTIAN HIEROGLYPH-13B80;Lo;0;L;;;;;N;;;;; +13B81;EGYPTIAN HIEROGLYPH-13B81;Lo;0;L;;;;;N;;;;; +13B82;EGYPTIAN HIEROGLYPH-13B82;Lo;0;L;;;;;N;;;;; +13B83;EGYPTIAN HIEROGLYPH-13B83;Lo;0;L;;;;;N;;;;; +13B84;EGYPTIAN HIEROGLYPH-13B84;Lo;0;L;;;;;N;;;;; +13B85;EGYPTIAN HIEROGLYPH-13B85;Lo;0;L;;;;;N;;;;; +13B86;EGYPTIAN HIEROGLYPH-13B86;Lo;0;L;;;;;N;;;;; +13B87;EGYPTIAN HIEROGLYPH-13B87;Lo;0;L;;;;;N;;;;; +13B88;EGYPTIAN HIEROGLYPH-13B88;Lo;0;L;;;;;N;;;;; +13B89;EGYPTIAN HIEROGLYPH-13B89;Lo;0;L;;;;;N;;;;; +13B8A;EGYPTIAN HIEROGLYPH-13B8A;Lo;0;L;;;;;N;;;;; +13B8B;EGYPTIAN HIEROGLYPH-13B8B;Lo;0;L;;;;;N;;;;; +13B8C;EGYPTIAN HIEROGLYPH-13B8C;Lo;0;L;;;;;N;;;;; +13B8D;EGYPTIAN HIEROGLYPH-13B8D;Lo;0;L;;;;;N;;;;; +13B8E;EGYPTIAN HIEROGLYPH-13B8E;Lo;0;L;;;;;N;;;;; +13B8F;EGYPTIAN HIEROGLYPH-13B8F;Lo;0;L;;;;;N;;;;; +13B90;EGYPTIAN HIEROGLYPH-13B90;Lo;0;L;;;;;N;;;;; +13B91;EGYPTIAN HIEROGLYPH-13B91;Lo;0;L;;;;;N;;;;; +13B92;EGYPTIAN HIEROGLYPH-13B92;Lo;0;L;;;;;N;;;;; +13B93;EGYPTIAN HIEROGLYPH-13B93;Lo;0;L;;;;;N;;;;; +13B94;EGYPTIAN HIEROGLYPH-13B94;Lo;0;L;;;;;N;;;;; +13B95;EGYPTIAN HIEROGLYPH-13B95;Lo;0;L;;;;;N;;;;; +13B96;EGYPTIAN HIEROGLYPH-13B96;Lo;0;L;;;;;N;;;;; +13B97;EGYPTIAN HIEROGLYPH-13B97;Lo;0;L;;;;;N;;;;; +13B98;EGYPTIAN HIEROGLYPH-13B98;Lo;0;L;;;;;N;;;;; +13B99;EGYPTIAN HIEROGLYPH-13B99;Lo;0;L;;;;;N;;;;; +13B9A;EGYPTIAN HIEROGLYPH-13B9A;Lo;0;L;;;;;N;;;;; +13B9B;EGYPTIAN HIEROGLYPH-13B9B;Lo;0;L;;;;;N;;;;; +13B9C;EGYPTIAN HIEROGLYPH-13B9C;Lo;0;L;;;;;N;;;;; +13B9D;EGYPTIAN HIEROGLYPH-13B9D;Lo;0;L;;;;;N;;;;; +13B9E;EGYPTIAN HIEROGLYPH-13B9E;Lo;0;L;;;;;N;;;;; +13B9F;EGYPTIAN HIEROGLYPH-13B9F;Lo;0;L;;;;;N;;;;; +13BA0;EGYPTIAN HIEROGLYPH-13BA0;Lo;0;L;;;;;N;;;;; +13BA1;EGYPTIAN HIEROGLYPH-13BA1;Lo;0;L;;;;;N;;;;; +13BA2;EGYPTIAN HIEROGLYPH-13BA2;Lo;0;L;;;;;N;;;;; +13BA3;EGYPTIAN HIEROGLYPH-13BA3;Lo;0;L;;;;;N;;;;; +13BA4;EGYPTIAN HIEROGLYPH-13BA4;Lo;0;L;;;;;N;;;;; +13BA5;EGYPTIAN HIEROGLYPH-13BA5;Lo;0;L;;;;;N;;;;; +13BA6;EGYPTIAN HIEROGLYPH-13BA6;Lo;0;L;;;;;N;;;;; +13BA7;EGYPTIAN HIEROGLYPH-13BA7;Lo;0;L;;;;;N;;;;; +13BA8;EGYPTIAN HIEROGLYPH-13BA8;Lo;0;L;;;;;N;;;;; +13BA9;EGYPTIAN HIEROGLYPH-13BA9;Lo;0;L;;;;;N;;;;; +13BAA;EGYPTIAN HIEROGLYPH-13BAA;Lo;0;L;;;;;N;;;;; +13BAB;EGYPTIAN HIEROGLYPH-13BAB;Lo;0;L;;;;;N;;;;; +13BAC;EGYPTIAN HIEROGLYPH-13BAC;Lo;0;L;;;;;N;;;;; +13BAD;EGYPTIAN HIEROGLYPH-13BAD;Lo;0;L;;;;;N;;;;; +13BAE;EGYPTIAN HIEROGLYPH-13BAE;Lo;0;L;;;;;N;;;;; +13BAF;EGYPTIAN HIEROGLYPH-13BAF;Lo;0;L;;;;;N;;;;; +13BB0;EGYPTIAN HIEROGLYPH-13BB0;Lo;0;L;;;;;N;;;;; +13BB1;EGYPTIAN HIEROGLYPH-13BB1;Lo;0;L;;;;;N;;;;; +13BB2;EGYPTIAN HIEROGLYPH-13BB2;Lo;0;L;;;;;N;;;;; +13BB3;EGYPTIAN HIEROGLYPH-13BB3;Lo;0;L;;;;;N;;;;; +13BB4;EGYPTIAN HIEROGLYPH-13BB4;Lo;0;L;;;;;N;;;;; +13BB5;EGYPTIAN HIEROGLYPH-13BB5;Lo;0;L;;;;;N;;;;; +13BB6;EGYPTIAN HIEROGLYPH-13BB6;Lo;0;L;;;;;N;;;;; +13BB7;EGYPTIAN HIEROGLYPH-13BB7;Lo;0;L;;;;;N;;;;; +13BB8;EGYPTIAN HIEROGLYPH-13BB8;Lo;0;L;;;;;N;;;;; +13BB9;EGYPTIAN HIEROGLYPH-13BB9;Lo;0;L;;;;;N;;;;; +13BBA;EGYPTIAN HIEROGLYPH-13BBA;Lo;0;L;;;;;N;;;;; +13BBB;EGYPTIAN HIEROGLYPH-13BBB;Lo;0;L;;;;;N;;;;; +13BBC;EGYPTIAN HIEROGLYPH-13BBC;Lo;0;L;;;;;N;;;;; +13BBD;EGYPTIAN HIEROGLYPH-13BBD;Lo;0;L;;;;;N;;;;; +13BBE;EGYPTIAN HIEROGLYPH-13BBE;Lo;0;L;;;;;N;;;;; +13BBF;EGYPTIAN HIEROGLYPH-13BBF;Lo;0;L;;;;;N;;;;; +13BC0;EGYPTIAN HIEROGLYPH-13BC0;Lo;0;L;;;;;N;;;;; +13BC1;EGYPTIAN HIEROGLYPH-13BC1;Lo;0;L;;;;;N;;;;; +13BC2;EGYPTIAN HIEROGLYPH-13BC2;Lo;0;L;;;;;N;;;;; +13BC3;EGYPTIAN HIEROGLYPH-13BC3;Lo;0;L;;;;;N;;;;; +13BC4;EGYPTIAN HIEROGLYPH-13BC4;Lo;0;L;;;;;N;;;;; +13BC5;EGYPTIAN HIEROGLYPH-13BC5;Lo;0;L;;;;;N;;;;; +13BC6;EGYPTIAN HIEROGLYPH-13BC6;Lo;0;L;;;;;N;;;;; +13BC7;EGYPTIAN HIEROGLYPH-13BC7;Lo;0;L;;;;;N;;;;; +13BC8;EGYPTIAN HIEROGLYPH-13BC8;Lo;0;L;;;;;N;;;;; +13BC9;EGYPTIAN HIEROGLYPH-13BC9;Lo;0;L;;;;;N;;;;; +13BCA;EGYPTIAN HIEROGLYPH-13BCA;Lo;0;L;;;;;N;;;;; +13BCB;EGYPTIAN HIEROGLYPH-13BCB;Lo;0;L;;;;;N;;;;; +13BCC;EGYPTIAN HIEROGLYPH-13BCC;Lo;0;L;;;;;N;;;;; +13BCD;EGYPTIAN HIEROGLYPH-13BCD;Lo;0;L;;;;;N;;;;; +13BCE;EGYPTIAN HIEROGLYPH-13BCE;Lo;0;L;;;;;N;;;;; +13BCF;EGYPTIAN HIEROGLYPH-13BCF;Lo;0;L;;;;;N;;;;; +13BD0;EGYPTIAN HIEROGLYPH-13BD0;Lo;0;L;;;;;N;;;;; +13BD1;EGYPTIAN HIEROGLYPH-13BD1;Lo;0;L;;;;;N;;;;; +13BD2;EGYPTIAN HIEROGLYPH-13BD2;Lo;0;L;;;;;N;;;;; +13BD3;EGYPTIAN HIEROGLYPH-13BD3;Lo;0;L;;;;;N;;;;; +13BD4;EGYPTIAN HIEROGLYPH-13BD4;Lo;0;L;;;;;N;;;;; +13BD5;EGYPTIAN HIEROGLYPH-13BD5;Lo;0;L;;;;;N;;;;; +13BD6;EGYPTIAN HIEROGLYPH-13BD6;Lo;0;L;;;;;N;;;;; +13BD7;EGYPTIAN HIEROGLYPH-13BD7;Lo;0;L;;;;;N;;;;; +13BD8;EGYPTIAN HIEROGLYPH-13BD8;Lo;0;L;;;;;N;;;;; +13BD9;EGYPTIAN HIEROGLYPH-13BD9;Lo;0;L;;;;;N;;;;; +13BDA;EGYPTIAN HIEROGLYPH-13BDA;Lo;0;L;;;;;N;;;;; +13BDB;EGYPTIAN HIEROGLYPH-13BDB;Lo;0;L;;;;;N;;;;; +13BDC;EGYPTIAN HIEROGLYPH-13BDC;Lo;0;L;;;;;N;;;;; +13BDD;EGYPTIAN HIEROGLYPH-13BDD;Lo;0;L;;;;;N;;;;; +13BDE;EGYPTIAN HIEROGLYPH-13BDE;Lo;0;L;;;;;N;;;;; +13BDF;EGYPTIAN HIEROGLYPH-13BDF;Lo;0;L;;;;;N;;;;; +13BE0;EGYPTIAN HIEROGLYPH-13BE0;Lo;0;L;;;;;N;;;;; +13BE1;EGYPTIAN HIEROGLYPH-13BE1;Lo;0;L;;;;;N;;;;; +13BE2;EGYPTIAN HIEROGLYPH-13BE2;Lo;0;L;;;;;N;;;;; +13BE3;EGYPTIAN HIEROGLYPH-13BE3;Lo;0;L;;;;;N;;;;; +13BE4;EGYPTIAN HIEROGLYPH-13BE4;Lo;0;L;;;;;N;;;;; +13BE5;EGYPTIAN HIEROGLYPH-13BE5;Lo;0;L;;;;;N;;;;; +13BE6;EGYPTIAN HIEROGLYPH-13BE6;Lo;0;L;;;;;N;;;;; +13BE7;EGYPTIAN HIEROGLYPH-13BE7;Lo;0;L;;;;;N;;;;; +13BE8;EGYPTIAN HIEROGLYPH-13BE8;Lo;0;L;;;;;N;;;;; +13BE9;EGYPTIAN HIEROGLYPH-13BE9;Lo;0;L;;;;;N;;;;; +13BEA;EGYPTIAN HIEROGLYPH-13BEA;Lo;0;L;;;;;N;;;;; +13BEB;EGYPTIAN HIEROGLYPH-13BEB;Lo;0;L;;;;;N;;;;; +13BEC;EGYPTIAN HIEROGLYPH-13BEC;Lo;0;L;;;;;N;;;;; +13BED;EGYPTIAN HIEROGLYPH-13BED;Lo;0;L;;;;;N;;;;; +13BEE;EGYPTIAN HIEROGLYPH-13BEE;Lo;0;L;;;;;N;;;;; +13BEF;EGYPTIAN HIEROGLYPH-13BEF;Lo;0;L;;;;;N;;;;; +13BF0;EGYPTIAN HIEROGLYPH-13BF0;Lo;0;L;;;;;N;;;;; +13BF1;EGYPTIAN HIEROGLYPH-13BF1;Lo;0;L;;;;;N;;;;; +13BF2;EGYPTIAN HIEROGLYPH-13BF2;Lo;0;L;;;;;N;;;;; +13BF3;EGYPTIAN HIEROGLYPH-13BF3;Lo;0;L;;;;;N;;;;; +13BF4;EGYPTIAN HIEROGLYPH-13BF4;Lo;0;L;;;;;N;;;;; +13BF5;EGYPTIAN HIEROGLYPH-13BF5;Lo;0;L;;;;;N;;;;; +13BF6;EGYPTIAN HIEROGLYPH-13BF6;Lo;0;L;;;;;N;;;;; +13BF7;EGYPTIAN HIEROGLYPH-13BF7;Lo;0;L;;;;;N;;;;; +13BF8;EGYPTIAN HIEROGLYPH-13BF8;Lo;0;L;;;;;N;;;;; +13BF9;EGYPTIAN HIEROGLYPH-13BF9;Lo;0;L;;;;;N;;;;; +13BFA;EGYPTIAN HIEROGLYPH-13BFA;Lo;0;L;;;;;N;;;;; +13BFB;EGYPTIAN HIEROGLYPH-13BFB;Lo;0;L;;;;;N;;;;; +13BFC;EGYPTIAN HIEROGLYPH-13BFC;Lo;0;L;;;;;N;;;;; +13BFD;EGYPTIAN HIEROGLYPH-13BFD;Lo;0;L;;;;;N;;;;; +13BFE;EGYPTIAN HIEROGLYPH-13BFE;Lo;0;L;;;;;N;;;;; +13BFF;EGYPTIAN HIEROGLYPH-13BFF;Lo;0;L;;;;;N;;;;; +13C00;EGYPTIAN HIEROGLYPH-13C00;Lo;0;L;;;;;N;;;;; +13C01;EGYPTIAN HIEROGLYPH-13C01;Lo;0;L;;;;;N;;;;; +13C02;EGYPTIAN HIEROGLYPH-13C02;Lo;0;L;;;;;N;;;;; +13C03;EGYPTIAN HIEROGLYPH-13C03;Lo;0;L;;;;;N;;;;; +13C04;EGYPTIAN HIEROGLYPH-13C04;Lo;0;L;;;;;N;;;;; +13C05;EGYPTIAN HIEROGLYPH-13C05;Lo;0;L;;;;;N;;;;; +13C06;EGYPTIAN HIEROGLYPH-13C06;Lo;0;L;;;;;N;;;;; +13C07;EGYPTIAN HIEROGLYPH-13C07;Lo;0;L;;;;;N;;;;; +13C08;EGYPTIAN HIEROGLYPH-13C08;Lo;0;L;;;;;N;;;;; +13C09;EGYPTIAN HIEROGLYPH-13C09;Lo;0;L;;;;;N;;;;; +13C0A;EGYPTIAN HIEROGLYPH-13C0A;Lo;0;L;;;;;N;;;;; +13C0B;EGYPTIAN HIEROGLYPH-13C0B;Lo;0;L;;;;;N;;;;; +13C0C;EGYPTIAN HIEROGLYPH-13C0C;Lo;0;L;;;;;N;;;;; +13C0D;EGYPTIAN HIEROGLYPH-13C0D;Lo;0;L;;;;;N;;;;; +13C0E;EGYPTIAN HIEROGLYPH-13C0E;Lo;0;L;;;;;N;;;;; +13C0F;EGYPTIAN HIEROGLYPH-13C0F;Lo;0;L;;;;;N;;;;; +13C10;EGYPTIAN HIEROGLYPH-13C10;Lo;0;L;;;;;N;;;;; +13C11;EGYPTIAN HIEROGLYPH-13C11;Lo;0;L;;;;;N;;;;; +13C12;EGYPTIAN HIEROGLYPH-13C12;Lo;0;L;;;;;N;;;;; +13C13;EGYPTIAN HIEROGLYPH-13C13;Lo;0;L;;;;;N;;;;; +13C14;EGYPTIAN HIEROGLYPH-13C14;Lo;0;L;;;;;N;;;;; +13C15;EGYPTIAN HIEROGLYPH-13C15;Lo;0;L;;;;;N;;;;; +13C16;EGYPTIAN HIEROGLYPH-13C16;Lo;0;L;;;;;N;;;;; +13C17;EGYPTIAN HIEROGLYPH-13C17;Lo;0;L;;;;;N;;;;; +13C18;EGYPTIAN HIEROGLYPH-13C18;Lo;0;L;;;;;N;;;;; +13C19;EGYPTIAN HIEROGLYPH-13C19;Lo;0;L;;;;;N;;;;; +13C1A;EGYPTIAN HIEROGLYPH-13C1A;Lo;0;L;;;;;N;;;;; +13C1B;EGYPTIAN HIEROGLYPH-13C1B;Lo;0;L;;;;;N;;;;; +13C1C;EGYPTIAN HIEROGLYPH-13C1C;Lo;0;L;;;;;N;;;;; +13C1D;EGYPTIAN HIEROGLYPH-13C1D;Lo;0;L;;;;;N;;;;; +13C1E;EGYPTIAN HIEROGLYPH-13C1E;Lo;0;L;;;;;N;;;;; +13C1F;EGYPTIAN HIEROGLYPH-13C1F;Lo;0;L;;;;;N;;;;; +13C20;EGYPTIAN HIEROGLYPH-13C20;Lo;0;L;;;;;N;;;;; +13C21;EGYPTIAN HIEROGLYPH-13C21;Lo;0;L;;;;;N;;;;; +13C22;EGYPTIAN HIEROGLYPH-13C22;Lo;0;L;;;;;N;;;;; +13C23;EGYPTIAN HIEROGLYPH-13C23;Lo;0;L;;;;;N;;;;; +13C24;EGYPTIAN HIEROGLYPH-13C24;Lo;0;L;;;;;N;;;;; +13C25;EGYPTIAN HIEROGLYPH-13C25;Lo;0;L;;;;;N;;;;; +13C26;EGYPTIAN HIEROGLYPH-13C26;Lo;0;L;;;;;N;;;;; +13C27;EGYPTIAN HIEROGLYPH-13C27;Lo;0;L;;;;;N;;;;; +13C28;EGYPTIAN HIEROGLYPH-13C28;Lo;0;L;;;;;N;;;;; +13C29;EGYPTIAN HIEROGLYPH-13C29;Lo;0;L;;;;;N;;;;; +13C2A;EGYPTIAN HIEROGLYPH-13C2A;Lo;0;L;;;;;N;;;;; +13C2B;EGYPTIAN HIEROGLYPH-13C2B;Lo;0;L;;;;;N;;;;; +13C2C;EGYPTIAN HIEROGLYPH-13C2C;Lo;0;L;;;;;N;;;;; +13C2D;EGYPTIAN HIEROGLYPH-13C2D;Lo;0;L;;;;;N;;;;; +13C2E;EGYPTIAN HIEROGLYPH-13C2E;Lo;0;L;;;;;N;;;;; +13C2F;EGYPTIAN HIEROGLYPH-13C2F;Lo;0;L;;;;;N;;;;; +13C30;EGYPTIAN HIEROGLYPH-13C30;Lo;0;L;;;;;N;;;;; +13C31;EGYPTIAN HIEROGLYPH-13C31;Lo;0;L;;;;;N;;;;; +13C32;EGYPTIAN HIEROGLYPH-13C32;Lo;0;L;;;;;N;;;;; +13C33;EGYPTIAN HIEROGLYPH-13C33;Lo;0;L;;;;;N;;;;; +13C34;EGYPTIAN HIEROGLYPH-13C34;Lo;0;L;;;;;N;;;;; +13C35;EGYPTIAN HIEROGLYPH-13C35;Lo;0;L;;;;;N;;;;; +13C36;EGYPTIAN HIEROGLYPH-13C36;Lo;0;L;;;;;N;;;;; +13C37;EGYPTIAN HIEROGLYPH-13C37;Lo;0;L;;;;;N;;;;; +13C38;EGYPTIAN HIEROGLYPH-13C38;Lo;0;L;;;;;N;;;;; +13C39;EGYPTIAN HIEROGLYPH-13C39;Lo;0;L;;;;;N;;;;; +13C3A;EGYPTIAN HIEROGLYPH-13C3A;Lo;0;L;;;;;N;;;;; +13C3B;EGYPTIAN HIEROGLYPH-13C3B;Lo;0;L;;;;;N;;;;; +13C3C;EGYPTIAN HIEROGLYPH-13C3C;Lo;0;L;;;;;N;;;;; +13C3D;EGYPTIAN HIEROGLYPH-13C3D;Lo;0;L;;;;;N;;;;; +13C3E;EGYPTIAN HIEROGLYPH-13C3E;Lo;0;L;;;;;N;;;;; +13C3F;EGYPTIAN HIEROGLYPH-13C3F;Lo;0;L;;;;;N;;;;; +13C40;EGYPTIAN HIEROGLYPH-13C40;Lo;0;L;;;;;N;;;;; +13C41;EGYPTIAN HIEROGLYPH-13C41;Lo;0;L;;;;;N;;;;; +13C42;EGYPTIAN HIEROGLYPH-13C42;Lo;0;L;;;;;N;;;;; +13C43;EGYPTIAN HIEROGLYPH-13C43;Lo;0;L;;;;;N;;;;; +13C44;EGYPTIAN HIEROGLYPH-13C44;Lo;0;L;;;;;N;;;;; +13C45;EGYPTIAN HIEROGLYPH-13C45;Lo;0;L;;;;;N;;;;; +13C46;EGYPTIAN HIEROGLYPH-13C46;Lo;0;L;;;;;N;;;;; +13C47;EGYPTIAN HIEROGLYPH-13C47;Lo;0;L;;;;;N;;;;; +13C48;EGYPTIAN HIEROGLYPH-13C48;Lo;0;L;;;;;N;;;;; +13C49;EGYPTIAN HIEROGLYPH-13C49;Lo;0;L;;;;;N;;;;; +13C4A;EGYPTIAN HIEROGLYPH-13C4A;Lo;0;L;;;;;N;;;;; +13C4B;EGYPTIAN HIEROGLYPH-13C4B;Lo;0;L;;;;;N;;;;; +13C4C;EGYPTIAN HIEROGLYPH-13C4C;Lo;0;L;;;;;N;;;;; +13C4D;EGYPTIAN HIEROGLYPH-13C4D;Lo;0;L;;;;;N;;;;; +13C4E;EGYPTIAN HIEROGLYPH-13C4E;Lo;0;L;;;;;N;;;;; +13C4F;EGYPTIAN HIEROGLYPH-13C4F;Lo;0;L;;;;;N;;;;; +13C50;EGYPTIAN HIEROGLYPH-13C50;Lo;0;L;;;;;N;;;;; +13C51;EGYPTIAN HIEROGLYPH-13C51;Lo;0;L;;;;;N;;;;; +13C52;EGYPTIAN HIEROGLYPH-13C52;Lo;0;L;;;;;N;;;;; +13C53;EGYPTIAN HIEROGLYPH-13C53;Lo;0;L;;;;;N;;;;; +13C54;EGYPTIAN HIEROGLYPH-13C54;Lo;0;L;;;;;N;;;;; +13C55;EGYPTIAN HIEROGLYPH-13C55;Lo;0;L;;;;;N;;;;; +13C56;EGYPTIAN HIEROGLYPH-13C56;Lo;0;L;;;;;N;;;;; +13C57;EGYPTIAN HIEROGLYPH-13C57;Lo;0;L;;;;;N;;;;; +13C58;EGYPTIAN HIEROGLYPH-13C58;Lo;0;L;;;;;N;;;;; +13C59;EGYPTIAN HIEROGLYPH-13C59;Lo;0;L;;;;;N;;;;; +13C5A;EGYPTIAN HIEROGLYPH-13C5A;Lo;0;L;;;;;N;;;;; +13C5B;EGYPTIAN HIEROGLYPH-13C5B;Lo;0;L;;;;;N;;;;; +13C5C;EGYPTIAN HIEROGLYPH-13C5C;Lo;0;L;;;;;N;;;;; +13C5D;EGYPTIAN HIEROGLYPH-13C5D;Lo;0;L;;;;;N;;;;; +13C5E;EGYPTIAN HIEROGLYPH-13C5E;Lo;0;L;;;;;N;;;;; +13C5F;EGYPTIAN HIEROGLYPH-13C5F;Lo;0;L;;;;;N;;;;; +13C60;EGYPTIAN HIEROGLYPH-13C60;Lo;0;L;;;;;N;;;;; +13C61;EGYPTIAN HIEROGLYPH-13C61;Lo;0;L;;;;;N;;;;; +13C62;EGYPTIAN HIEROGLYPH-13C62;Lo;0;L;;;;;N;;;;; +13C63;EGYPTIAN HIEROGLYPH-13C63;Lo;0;L;;;;;N;;;;; +13C64;EGYPTIAN HIEROGLYPH-13C64;Lo;0;L;;;;;N;;;;; +13C65;EGYPTIAN HIEROGLYPH-13C65;Lo;0;L;;;;;N;;;;; +13C66;EGYPTIAN HIEROGLYPH-13C66;Lo;0;L;;;;;N;;;;; +13C67;EGYPTIAN HIEROGLYPH-13C67;Lo;0;L;;;;;N;;;;; +13C68;EGYPTIAN HIEROGLYPH-13C68;Lo;0;L;;;;;N;;;;; +13C69;EGYPTIAN HIEROGLYPH-13C69;Lo;0;L;;;;;N;;;;; +13C6A;EGYPTIAN HIEROGLYPH-13C6A;Lo;0;L;;;;;N;;;;; +13C6B;EGYPTIAN HIEROGLYPH-13C6B;Lo;0;L;;;;;N;;;;; +13C6C;EGYPTIAN HIEROGLYPH-13C6C;Lo;0;L;;;;;N;;;;; +13C6D;EGYPTIAN HIEROGLYPH-13C6D;Lo;0;L;;;;;N;;;;; +13C6E;EGYPTIAN HIEROGLYPH-13C6E;Lo;0;L;;;;;N;;;;; +13C6F;EGYPTIAN HIEROGLYPH-13C6F;Lo;0;L;;;;;N;;;;; +13C70;EGYPTIAN HIEROGLYPH-13C70;Lo;0;L;;;;;N;;;;; +13C71;EGYPTIAN HIEROGLYPH-13C71;Lo;0;L;;;;;N;;;;; +13C72;EGYPTIAN HIEROGLYPH-13C72;Lo;0;L;;;;;N;;;;; +13C73;EGYPTIAN HIEROGLYPH-13C73;Lo;0;L;;;;;N;;;;; +13C74;EGYPTIAN HIEROGLYPH-13C74;Lo;0;L;;;;;N;;;;; +13C75;EGYPTIAN HIEROGLYPH-13C75;Lo;0;L;;;;;N;;;;; +13C76;EGYPTIAN HIEROGLYPH-13C76;Lo;0;L;;;;;N;;;;; +13C77;EGYPTIAN HIEROGLYPH-13C77;Lo;0;L;;;;;N;;;;; +13C78;EGYPTIAN HIEROGLYPH-13C78;Lo;0;L;;;;;N;;;;; +13C79;EGYPTIAN HIEROGLYPH-13C79;Lo;0;L;;;;;N;;;;; +13C7A;EGYPTIAN HIEROGLYPH-13C7A;Lo;0;L;;;;;N;;;;; +13C7B;EGYPTIAN HIEROGLYPH-13C7B;Lo;0;L;;;;;N;;;;; +13C7C;EGYPTIAN HIEROGLYPH-13C7C;Lo;0;L;;;;;N;;;;; +13C7D;EGYPTIAN HIEROGLYPH-13C7D;Lo;0;L;;;;;N;;;;; +13C7E;EGYPTIAN HIEROGLYPH-13C7E;Lo;0;L;;;;;N;;;;; +13C7F;EGYPTIAN HIEROGLYPH-13C7F;Lo;0;L;;;;;N;;;;; +13C80;EGYPTIAN HIEROGLYPH-13C80;Lo;0;L;;;;;N;;;;; +13C81;EGYPTIAN HIEROGLYPH-13C81;Lo;0;L;;;;;N;;;;; +13C82;EGYPTIAN HIEROGLYPH-13C82;Lo;0;L;;;;;N;;;;; +13C83;EGYPTIAN HIEROGLYPH-13C83;Lo;0;L;;;;;N;;;;; +13C84;EGYPTIAN HIEROGLYPH-13C84;Lo;0;L;;;;;N;;;;; +13C85;EGYPTIAN HIEROGLYPH-13C85;Lo;0;L;;;;;N;;;;; +13C86;EGYPTIAN HIEROGLYPH-13C86;Lo;0;L;;;;;N;;;;; +13C87;EGYPTIAN HIEROGLYPH-13C87;Lo;0;L;;;;;N;;;;; +13C88;EGYPTIAN HIEROGLYPH-13C88;Lo;0;L;;;;;N;;;;; +13C89;EGYPTIAN HIEROGLYPH-13C89;Lo;0;L;;;;;N;;;;; +13C8A;EGYPTIAN HIEROGLYPH-13C8A;Lo;0;L;;;;;N;;;;; +13C8B;EGYPTIAN HIEROGLYPH-13C8B;Lo;0;L;;;;;N;;;;; +13C8C;EGYPTIAN HIEROGLYPH-13C8C;Lo;0;L;;;;;N;;;;; +13C8D;EGYPTIAN HIEROGLYPH-13C8D;Lo;0;L;;;;;N;;;;; +13C8E;EGYPTIAN HIEROGLYPH-13C8E;Lo;0;L;;;;;N;;;;; +13C8F;EGYPTIAN HIEROGLYPH-13C8F;Lo;0;L;;;;;N;;;;; +13C90;EGYPTIAN HIEROGLYPH-13C90;Lo;0;L;;;;;N;;;;; +13C91;EGYPTIAN HIEROGLYPH-13C91;Lo;0;L;;;;;N;;;;; +13C92;EGYPTIAN HIEROGLYPH-13C92;Lo;0;L;;;;;N;;;;; +13C93;EGYPTIAN HIEROGLYPH-13C93;Lo;0;L;;;;;N;;;;; +13C94;EGYPTIAN HIEROGLYPH-13C94;Lo;0;L;;;;;N;;;;; +13C95;EGYPTIAN HIEROGLYPH-13C95;Lo;0;L;;;;;N;;;;; +13C96;EGYPTIAN HIEROGLYPH-13C96;Lo;0;L;;;;;N;;;;; +13C97;EGYPTIAN HIEROGLYPH-13C97;Lo;0;L;;;;;N;;;;; +13C98;EGYPTIAN HIEROGLYPH-13C98;Lo;0;L;;;;;N;;;;; +13C99;EGYPTIAN HIEROGLYPH-13C99;Lo;0;L;;;;;N;;;;; +13C9A;EGYPTIAN HIEROGLYPH-13C9A;Lo;0;L;;;;;N;;;;; +13C9B;EGYPTIAN HIEROGLYPH-13C9B;Lo;0;L;;;;;N;;;;; +13C9C;EGYPTIAN HIEROGLYPH-13C9C;Lo;0;L;;;;;N;;;;; +13C9D;EGYPTIAN HIEROGLYPH-13C9D;Lo;0;L;;;;;N;;;;; +13C9E;EGYPTIAN HIEROGLYPH-13C9E;Lo;0;L;;;;;N;;;;; +13C9F;EGYPTIAN HIEROGLYPH-13C9F;Lo;0;L;;;;;N;;;;; +13CA0;EGYPTIAN HIEROGLYPH-13CA0;Lo;0;L;;;;;N;;;;; +13CA1;EGYPTIAN HIEROGLYPH-13CA1;Lo;0;L;;;;;N;;;;; +13CA2;EGYPTIAN HIEROGLYPH-13CA2;Lo;0;L;;;;;N;;;;; +13CA3;EGYPTIAN HIEROGLYPH-13CA3;Lo;0;L;;;;;N;;;;; +13CA4;EGYPTIAN HIEROGLYPH-13CA4;Lo;0;L;;;;;N;;;;; +13CA5;EGYPTIAN HIEROGLYPH-13CA5;Lo;0;L;;;;;N;;;;; +13CA6;EGYPTIAN HIEROGLYPH-13CA6;Lo;0;L;;;;;N;;;;; +13CA7;EGYPTIAN HIEROGLYPH-13CA7;Lo;0;L;;;;;N;;;;; +13CA8;EGYPTIAN HIEROGLYPH-13CA8;Lo;0;L;;;;;N;;;;; +13CA9;EGYPTIAN HIEROGLYPH-13CA9;Lo;0;L;;;;;N;;;;; +13CAA;EGYPTIAN HIEROGLYPH-13CAA;Lo;0;L;;;;;N;;;;; +13CAB;EGYPTIAN HIEROGLYPH-13CAB;Lo;0;L;;;;;N;;;;; +13CAC;EGYPTIAN HIEROGLYPH-13CAC;Lo;0;L;;;;;N;;;;; +13CAD;EGYPTIAN HIEROGLYPH-13CAD;Lo;0;L;;;;;N;;;;; +13CAE;EGYPTIAN HIEROGLYPH-13CAE;Lo;0;L;;;;;N;;;;; +13CAF;EGYPTIAN HIEROGLYPH-13CAF;Lo;0;L;;;;;N;;;;; +13CB0;EGYPTIAN HIEROGLYPH-13CB0;Lo;0;L;;;;;N;;;;; +13CB1;EGYPTIAN HIEROGLYPH-13CB1;Lo;0;L;;;;;N;;;;; +13CB2;EGYPTIAN HIEROGLYPH-13CB2;Lo;0;L;;;;;N;;;;; +13CB3;EGYPTIAN HIEROGLYPH-13CB3;Lo;0;L;;;;;N;;;;; +13CB4;EGYPTIAN HIEROGLYPH-13CB4;Lo;0;L;;;;;N;;;;; +13CB5;EGYPTIAN HIEROGLYPH-13CB5;Lo;0;L;;;;;N;;;;; +13CB6;EGYPTIAN HIEROGLYPH-13CB6;Lo;0;L;;;;;N;;;;; +13CB7;EGYPTIAN HIEROGLYPH-13CB7;Lo;0;L;;;;;N;;;;; +13CB8;EGYPTIAN HIEROGLYPH-13CB8;Lo;0;L;;;;;N;;;;; +13CB9;EGYPTIAN HIEROGLYPH-13CB9;Lo;0;L;;;;;N;;;;; +13CBA;EGYPTIAN HIEROGLYPH-13CBA;Lo;0;L;;;;;N;;;;; +13CBB;EGYPTIAN HIEROGLYPH-13CBB;Lo;0;L;;;;;N;;;;; +13CBC;EGYPTIAN HIEROGLYPH-13CBC;Lo;0;L;;;;;N;;;;; +13CBD;EGYPTIAN HIEROGLYPH-13CBD;Lo;0;L;;;;;N;;;;; +13CBE;EGYPTIAN HIEROGLYPH-13CBE;Lo;0;L;;;;;N;;;;; +13CBF;EGYPTIAN HIEROGLYPH-13CBF;Lo;0;L;;;;;N;;;;; +13CC0;EGYPTIAN HIEROGLYPH-13CC0;Lo;0;L;;;;;N;;;;; +13CC1;EGYPTIAN HIEROGLYPH-13CC1;Lo;0;L;;;;;N;;;;; +13CC2;EGYPTIAN HIEROGLYPH-13CC2;Lo;0;L;;;;;N;;;;; +13CC3;EGYPTIAN HIEROGLYPH-13CC3;Lo;0;L;;;;;N;;;;; +13CC4;EGYPTIAN HIEROGLYPH-13CC4;Lo;0;L;;;;;N;;;;; +13CC5;EGYPTIAN HIEROGLYPH-13CC5;Lo;0;L;;;;;N;;;;; +13CC6;EGYPTIAN HIEROGLYPH-13CC6;Lo;0;L;;;;;N;;;;; +13CC7;EGYPTIAN HIEROGLYPH-13CC7;Lo;0;L;;;;;N;;;;; +13CC8;EGYPTIAN HIEROGLYPH-13CC8;Lo;0;L;;;;;N;;;;; +13CC9;EGYPTIAN HIEROGLYPH-13CC9;Lo;0;L;;;;;N;;;;; +13CCA;EGYPTIAN HIEROGLYPH-13CCA;Lo;0;L;;;;;N;;;;; +13CCB;EGYPTIAN HIEROGLYPH-13CCB;Lo;0;L;;;;;N;;;;; +13CCC;EGYPTIAN HIEROGLYPH-13CCC;Lo;0;L;;;;;N;;;;; +13CCD;EGYPTIAN HIEROGLYPH-13CCD;Lo;0;L;;;;;N;;;;; +13CCE;EGYPTIAN HIEROGLYPH-13CCE;Lo;0;L;;;;;N;;;;; +13CCF;EGYPTIAN HIEROGLYPH-13CCF;Lo;0;L;;;;;N;;;;; +13CD0;EGYPTIAN HIEROGLYPH-13CD0;Lo;0;L;;;;;N;;;;; +13CD1;EGYPTIAN HIEROGLYPH-13CD1;Lo;0;L;;;;;N;;;;; +13CD2;EGYPTIAN HIEROGLYPH-13CD2;Lo;0;L;;;;;N;;;;; +13CD3;EGYPTIAN HIEROGLYPH-13CD3;Lo;0;L;;;;;N;;;;; +13CD4;EGYPTIAN HIEROGLYPH-13CD4;Lo;0;L;;;;;N;;;;; +13CD5;EGYPTIAN HIEROGLYPH-13CD5;Lo;0;L;;;;;N;;;;; +13CD6;EGYPTIAN HIEROGLYPH-13CD6;Lo;0;L;;;;;N;;;;; +13CD7;EGYPTIAN HIEROGLYPH-13CD7;Lo;0;L;;;;;N;;;;; +13CD8;EGYPTIAN HIEROGLYPH-13CD8;Lo;0;L;;;;;N;;;;; +13CD9;EGYPTIAN HIEROGLYPH-13CD9;Lo;0;L;;;;;N;;;;; +13CDA;EGYPTIAN HIEROGLYPH-13CDA;Lo;0;L;;;;;N;;;;; +13CDB;EGYPTIAN HIEROGLYPH-13CDB;Lo;0;L;;;;;N;;;;; +13CDC;EGYPTIAN HIEROGLYPH-13CDC;Lo;0;L;;;;;N;;;;; +13CDD;EGYPTIAN HIEROGLYPH-13CDD;Lo;0;L;;;;;N;;;;; +13CDE;EGYPTIAN HIEROGLYPH-13CDE;Lo;0;L;;;;;N;;;;; +13CDF;EGYPTIAN HIEROGLYPH-13CDF;Lo;0;L;;;;;N;;;;; +13CE0;EGYPTIAN HIEROGLYPH-13CE0;Lo;0;L;;;;;N;;;;; +13CE1;EGYPTIAN HIEROGLYPH-13CE1;Lo;0;L;;;;;N;;;;; +13CE2;EGYPTIAN HIEROGLYPH-13CE2;Lo;0;L;;;;;N;;;;; +13CE3;EGYPTIAN HIEROGLYPH-13CE3;Lo;0;L;;;;;N;;;;; +13CE4;EGYPTIAN HIEROGLYPH-13CE4;Lo;0;L;;;;;N;;;;; +13CE5;EGYPTIAN HIEROGLYPH-13CE5;Lo;0;L;;;;;N;;;;; +13CE6;EGYPTIAN HIEROGLYPH-13CE6;Lo;0;L;;;;;N;;;;; +13CE7;EGYPTIAN HIEROGLYPH-13CE7;Lo;0;L;;;;;N;;;;; +13CE8;EGYPTIAN HIEROGLYPH-13CE8;Lo;0;L;;;;;N;;;;; +13CE9;EGYPTIAN HIEROGLYPH-13CE9;Lo;0;L;;;;;N;;;;; +13CEA;EGYPTIAN HIEROGLYPH-13CEA;Lo;0;L;;;;;N;;;;; +13CEB;EGYPTIAN HIEROGLYPH-13CEB;Lo;0;L;;;;;N;;;;; +13CEC;EGYPTIAN HIEROGLYPH-13CEC;Lo;0;L;;;;;N;;;;; +13CED;EGYPTIAN HIEROGLYPH-13CED;Lo;0;L;;;;;N;;;;; +13CEE;EGYPTIAN HIEROGLYPH-13CEE;Lo;0;L;;;;;N;;;;; +13CEF;EGYPTIAN HIEROGLYPH-13CEF;Lo;0;L;;;;;N;;;;; +13CF0;EGYPTIAN HIEROGLYPH-13CF0;Lo;0;L;;;;;N;;;;; +13CF1;EGYPTIAN HIEROGLYPH-13CF1;Lo;0;L;;;;;N;;;;; +13CF2;EGYPTIAN HIEROGLYPH-13CF2;Lo;0;L;;;;;N;;;;; +13CF3;EGYPTIAN HIEROGLYPH-13CF3;Lo;0;L;;;;;N;;;;; +13CF4;EGYPTIAN HIEROGLYPH-13CF4;Lo;0;L;;;;;N;;;;; +13CF5;EGYPTIAN HIEROGLYPH-13CF5;Lo;0;L;;;;;N;;;;; +13CF6;EGYPTIAN HIEROGLYPH-13CF6;Lo;0;L;;;;;N;;;;; +13CF7;EGYPTIAN HIEROGLYPH-13CF7;Lo;0;L;;;;;N;;;;; +13CF8;EGYPTIAN HIEROGLYPH-13CF8;Lo;0;L;;;;;N;;;;; +13CF9;EGYPTIAN HIEROGLYPH-13CF9;Lo;0;L;;;;;N;;;;; +13CFA;EGYPTIAN HIEROGLYPH-13CFA;Lo;0;L;;;;;N;;;;; +13CFB;EGYPTIAN HIEROGLYPH-13CFB;Lo;0;L;;;;;N;;;;; +13CFC;EGYPTIAN HIEROGLYPH-13CFC;Lo;0;L;;;;;N;;;;; +13CFD;EGYPTIAN HIEROGLYPH-13CFD;Lo;0;L;;;;;N;;;;; +13CFE;EGYPTIAN HIEROGLYPH-13CFE;Lo;0;L;;;;;N;;;;; +13CFF;EGYPTIAN HIEROGLYPH-13CFF;Lo;0;L;;;;;N;;;;; +13D00;EGYPTIAN HIEROGLYPH-13D00;Lo;0;L;;;;;N;;;;; +13D01;EGYPTIAN HIEROGLYPH-13D01;Lo;0;L;;;;;N;;;;; +13D02;EGYPTIAN HIEROGLYPH-13D02;Lo;0;L;;;;;N;;;;; +13D03;EGYPTIAN HIEROGLYPH-13D03;Lo;0;L;;;;;N;;;;; +13D04;EGYPTIAN HIEROGLYPH-13D04;Lo;0;L;;;;;N;;;;; +13D05;EGYPTIAN HIEROGLYPH-13D05;Lo;0;L;;;;;N;;;;; +13D06;EGYPTIAN HIEROGLYPH-13D06;Lo;0;L;;;;;N;;;;; +13D07;EGYPTIAN HIEROGLYPH-13D07;Lo;0;L;;;;;N;;;;; +13D08;EGYPTIAN HIEROGLYPH-13D08;Lo;0;L;;;;;N;;;;; +13D09;EGYPTIAN HIEROGLYPH-13D09;Lo;0;L;;;;;N;;;;; +13D0A;EGYPTIAN HIEROGLYPH-13D0A;Lo;0;L;;;;;N;;;;; +13D0B;EGYPTIAN HIEROGLYPH-13D0B;Lo;0;L;;;;;N;;;;; +13D0C;EGYPTIAN HIEROGLYPH-13D0C;Lo;0;L;;;;;N;;;;; +13D0D;EGYPTIAN HIEROGLYPH-13D0D;Lo;0;L;;;;;N;;;;; +13D0E;EGYPTIAN HIEROGLYPH-13D0E;Lo;0;L;;;;;N;;;;; +13D0F;EGYPTIAN HIEROGLYPH-13D0F;Lo;0;L;;;;;N;;;;; +13D10;EGYPTIAN HIEROGLYPH-13D10;Lo;0;L;;;;;N;;;;; +13D11;EGYPTIAN HIEROGLYPH-13D11;Lo;0;L;;;;;N;;;;; +13D12;EGYPTIAN HIEROGLYPH-13D12;Lo;0;L;;;;;N;;;;; +13D13;EGYPTIAN HIEROGLYPH-13D13;Lo;0;L;;;;;N;;;;; +13D14;EGYPTIAN HIEROGLYPH-13D14;Lo;0;L;;;;;N;;;;; +13D15;EGYPTIAN HIEROGLYPH-13D15;Lo;0;L;;;;;N;;;;; +13D16;EGYPTIAN HIEROGLYPH-13D16;Lo;0;L;;;;;N;;;;; +13D17;EGYPTIAN HIEROGLYPH-13D17;Lo;0;L;;;;;N;;;;; +13D18;EGYPTIAN HIEROGLYPH-13D18;Lo;0;L;;;;;N;;;;; +13D19;EGYPTIAN HIEROGLYPH-13D19;Lo;0;L;;;;;N;;;;; +13D1A;EGYPTIAN HIEROGLYPH-13D1A;Lo;0;L;;;;;N;;;;; +13D1B;EGYPTIAN HIEROGLYPH-13D1B;Lo;0;L;;;;;N;;;;; +13D1C;EGYPTIAN HIEROGLYPH-13D1C;Lo;0;L;;;;;N;;;;; +13D1D;EGYPTIAN HIEROGLYPH-13D1D;Lo;0;L;;;;;N;;;;; +13D1E;EGYPTIAN HIEROGLYPH-13D1E;Lo;0;L;;;;;N;;;;; +13D1F;EGYPTIAN HIEROGLYPH-13D1F;Lo;0;L;;;;;N;;;;; +13D20;EGYPTIAN HIEROGLYPH-13D20;Lo;0;L;;;;;N;;;;; +13D21;EGYPTIAN HIEROGLYPH-13D21;Lo;0;L;;;;;N;;;;; +13D22;EGYPTIAN HIEROGLYPH-13D22;Lo;0;L;;;;;N;;;;; +13D23;EGYPTIAN HIEROGLYPH-13D23;Lo;0;L;;;;;N;;;;; +13D24;EGYPTIAN HIEROGLYPH-13D24;Lo;0;L;;;;;N;;;;; +13D25;EGYPTIAN HIEROGLYPH-13D25;Lo;0;L;;;;;N;;;;; +13D26;EGYPTIAN HIEROGLYPH-13D26;Lo;0;L;;;;;N;;;;; +13D27;EGYPTIAN HIEROGLYPH-13D27;Lo;0;L;;;;;N;;;;; +13D28;EGYPTIAN HIEROGLYPH-13D28;Lo;0;L;;;;;N;;;;; +13D29;EGYPTIAN HIEROGLYPH-13D29;Lo;0;L;;;;;N;;;;; +13D2A;EGYPTIAN HIEROGLYPH-13D2A;Lo;0;L;;;;;N;;;;; +13D2B;EGYPTIAN HIEROGLYPH-13D2B;Lo;0;L;;;;;N;;;;; +13D2C;EGYPTIAN HIEROGLYPH-13D2C;Lo;0;L;;;;;N;;;;; +13D2D;EGYPTIAN HIEROGLYPH-13D2D;Lo;0;L;;;;;N;;;;; +13D2E;EGYPTIAN HIEROGLYPH-13D2E;Lo;0;L;;;;;N;;;;; +13D2F;EGYPTIAN HIEROGLYPH-13D2F;Lo;0;L;;;;;N;;;;; +13D30;EGYPTIAN HIEROGLYPH-13D30;Lo;0;L;;;;;N;;;;; +13D31;EGYPTIAN HIEROGLYPH-13D31;Lo;0;L;;;;;N;;;;; +13D32;EGYPTIAN HIEROGLYPH-13D32;Lo;0;L;;;;;N;;;;; +13D33;EGYPTIAN HIEROGLYPH-13D33;Lo;0;L;;;;;N;;;;; +13D34;EGYPTIAN HIEROGLYPH-13D34;Lo;0;L;;;;;N;;;;; +13D35;EGYPTIAN HIEROGLYPH-13D35;Lo;0;L;;;;;N;;;;; +13D36;EGYPTIAN HIEROGLYPH-13D36;Lo;0;L;;;;;N;;;;; +13D37;EGYPTIAN HIEROGLYPH-13D37;Lo;0;L;;;;;N;;;;; +13D38;EGYPTIAN HIEROGLYPH-13D38;Lo;0;L;;;;;N;;;;; +13D39;EGYPTIAN HIEROGLYPH-13D39;Lo;0;L;;;;;N;;;;; +13D3A;EGYPTIAN HIEROGLYPH-13D3A;Lo;0;L;;;;;N;;;;; +13D3B;EGYPTIAN HIEROGLYPH-13D3B;Lo;0;L;;;;;N;;;;; +13D3C;EGYPTIAN HIEROGLYPH-13D3C;Lo;0;L;;;;;N;;;;; +13D3D;EGYPTIAN HIEROGLYPH-13D3D;Lo;0;L;;;;;N;;;;; +13D3E;EGYPTIAN HIEROGLYPH-13D3E;Lo;0;L;;;;;N;;;;; +13D3F;EGYPTIAN HIEROGLYPH-13D3F;Lo;0;L;;;;;N;;;;; +13D40;EGYPTIAN HIEROGLYPH-13D40;Lo;0;L;;;;;N;;;;; +13D41;EGYPTIAN HIEROGLYPH-13D41;Lo;0;L;;;;;N;;;;; +13D42;EGYPTIAN HIEROGLYPH-13D42;Lo;0;L;;;;;N;;;;; +13D43;EGYPTIAN HIEROGLYPH-13D43;Lo;0;L;;;;;N;;;;; +13D44;EGYPTIAN HIEROGLYPH-13D44;Lo;0;L;;;;;N;;;;; +13D45;EGYPTIAN HIEROGLYPH-13D45;Lo;0;L;;;;;N;;;;; +13D46;EGYPTIAN HIEROGLYPH-13D46;Lo;0;L;;;;;N;;;;; +13D47;EGYPTIAN HIEROGLYPH-13D47;Lo;0;L;;;;;N;;;;; +13D48;EGYPTIAN HIEROGLYPH-13D48;Lo;0;L;;;;;N;;;;; +13D49;EGYPTIAN HIEROGLYPH-13D49;Lo;0;L;;;;;N;;;;; +13D4A;EGYPTIAN HIEROGLYPH-13D4A;Lo;0;L;;;;;N;;;;; +13D4B;EGYPTIAN HIEROGLYPH-13D4B;Lo;0;L;;;;;N;;;;; +13D4C;EGYPTIAN HIEROGLYPH-13D4C;Lo;0;L;;;;;N;;;;; +13D4D;EGYPTIAN HIEROGLYPH-13D4D;Lo;0;L;;;;;N;;;;; +13D4E;EGYPTIAN HIEROGLYPH-13D4E;Lo;0;L;;;;;N;;;;; +13D4F;EGYPTIAN HIEROGLYPH-13D4F;Lo;0;L;;;;;N;;;;; +13D50;EGYPTIAN HIEROGLYPH-13D50;Lo;0;L;;;;;N;;;;; +13D51;EGYPTIAN HIEROGLYPH-13D51;Lo;0;L;;;;;N;;;;; +13D52;EGYPTIAN HIEROGLYPH-13D52;Lo;0;L;;;;;N;;;;; +13D53;EGYPTIAN HIEROGLYPH-13D53;Lo;0;L;;;;;N;;;;; +13D54;EGYPTIAN HIEROGLYPH-13D54;Lo;0;L;;;;;N;;;;; +13D55;EGYPTIAN HIEROGLYPH-13D55;Lo;0;L;;;;;N;;;;; +13D56;EGYPTIAN HIEROGLYPH-13D56;Lo;0;L;;;;;N;;;;; +13D57;EGYPTIAN HIEROGLYPH-13D57;Lo;0;L;;;;;N;;;;; +13D58;EGYPTIAN HIEROGLYPH-13D58;Lo;0;L;;;;;N;;;;; +13D59;EGYPTIAN HIEROGLYPH-13D59;Lo;0;L;;;;;N;;;;; +13D5A;EGYPTIAN HIEROGLYPH-13D5A;Lo;0;L;;;;;N;;;;; +13D5B;EGYPTIAN HIEROGLYPH-13D5B;Lo;0;L;;;;;N;;;;; +13D5C;EGYPTIAN HIEROGLYPH-13D5C;Lo;0;L;;;;;N;;;;; +13D5D;EGYPTIAN HIEROGLYPH-13D5D;Lo;0;L;;;;;N;;;;; +13D5E;EGYPTIAN HIEROGLYPH-13D5E;Lo;0;L;;;;;N;;;;; +13D5F;EGYPTIAN HIEROGLYPH-13D5F;Lo;0;L;;;;;N;;;;; +13D60;EGYPTIAN HIEROGLYPH-13D60;Lo;0;L;;;;;N;;;;; +13D61;EGYPTIAN HIEROGLYPH-13D61;Lo;0;L;;;;;N;;;;; +13D62;EGYPTIAN HIEROGLYPH-13D62;Lo;0;L;;;;;N;;;;; +13D63;EGYPTIAN HIEROGLYPH-13D63;Lo;0;L;;;;;N;;;;; +13D64;EGYPTIAN HIEROGLYPH-13D64;Lo;0;L;;;;;N;;;;; +13D65;EGYPTIAN HIEROGLYPH-13D65;Lo;0;L;;;;;N;;;;; +13D66;EGYPTIAN HIEROGLYPH-13D66;Lo;0;L;;;;;N;;;;; +13D67;EGYPTIAN HIEROGLYPH-13D67;Lo;0;L;;;;;N;;;;; +13D68;EGYPTIAN HIEROGLYPH-13D68;Lo;0;L;;;;;N;;;;; +13D69;EGYPTIAN HIEROGLYPH-13D69;Lo;0;L;;;;;N;;;;; +13D6A;EGYPTIAN HIEROGLYPH-13D6A;Lo;0;L;;;;;N;;;;; +13D6B;EGYPTIAN HIEROGLYPH-13D6B;Lo;0;L;;;;;N;;;;; +13D6C;EGYPTIAN HIEROGLYPH-13D6C;Lo;0;L;;;;;N;;;;; +13D6D;EGYPTIAN HIEROGLYPH-13D6D;Lo;0;L;;;;;N;;;;; +13D6E;EGYPTIAN HIEROGLYPH-13D6E;Lo;0;L;;;;;N;;;;; +13D6F;EGYPTIAN HIEROGLYPH-13D6F;Lo;0;L;;;;;N;;;;; +13D70;EGYPTIAN HIEROGLYPH-13D70;Lo;0;L;;;;;N;;;;; +13D71;EGYPTIAN HIEROGLYPH-13D71;Lo;0;L;;;;;N;;;;; +13D72;EGYPTIAN HIEROGLYPH-13D72;Lo;0;L;;;;;N;;;;; +13D73;EGYPTIAN HIEROGLYPH-13D73;Lo;0;L;;;;;N;;;;; +13D74;EGYPTIAN HIEROGLYPH-13D74;Lo;0;L;;;;;N;;;;; +13D75;EGYPTIAN HIEROGLYPH-13D75;Lo;0;L;;;;;N;;;;; +13D76;EGYPTIAN HIEROGLYPH-13D76;Lo;0;L;;;;;N;;;;; +13D77;EGYPTIAN HIEROGLYPH-13D77;Lo;0;L;;;;;N;;;;; +13D78;EGYPTIAN HIEROGLYPH-13D78;Lo;0;L;;;;;N;;;;; +13D79;EGYPTIAN HIEROGLYPH-13D79;Lo;0;L;;;;;N;;;;; +13D7A;EGYPTIAN HIEROGLYPH-13D7A;Lo;0;L;;;;;N;;;;; +13D7B;EGYPTIAN HIEROGLYPH-13D7B;Lo;0;L;;;;;N;;;;; +13D7C;EGYPTIAN HIEROGLYPH-13D7C;Lo;0;L;;;;;N;;;;; +13D7D;EGYPTIAN HIEROGLYPH-13D7D;Lo;0;L;;;;;N;;;;; +13D7E;EGYPTIAN HIEROGLYPH-13D7E;Lo;0;L;;;;;N;;;;; +13D7F;EGYPTIAN HIEROGLYPH-13D7F;Lo;0;L;;;;;N;;;;; +13D80;EGYPTIAN HIEROGLYPH-13D80;Lo;0;L;;;;;N;;;;; +13D81;EGYPTIAN HIEROGLYPH-13D81;Lo;0;L;;;;;N;;;;; +13D82;EGYPTIAN HIEROGLYPH-13D82;Lo;0;L;;;;;N;;;;; +13D83;EGYPTIAN HIEROGLYPH-13D83;Lo;0;L;;;;;N;;;;; +13D84;EGYPTIAN HIEROGLYPH-13D84;Lo;0;L;;;;;N;;;;; +13D85;EGYPTIAN HIEROGLYPH-13D85;Lo;0;L;;;;;N;;;;; +13D86;EGYPTIAN HIEROGLYPH-13D86;Lo;0;L;;;;;N;;;;; +13D87;EGYPTIAN HIEROGLYPH-13D87;Lo;0;L;;;;;N;;;;; +13D88;EGYPTIAN HIEROGLYPH-13D88;Lo;0;L;;;;;N;;;;; +13D89;EGYPTIAN HIEROGLYPH-13D89;Lo;0;L;;;;;N;;;;; +13D8A;EGYPTIAN HIEROGLYPH-13D8A;Lo;0;L;;;;;N;;;;; +13D8B;EGYPTIAN HIEROGLYPH-13D8B;Lo;0;L;;;;;N;;;;; +13D8C;EGYPTIAN HIEROGLYPH-13D8C;Lo;0;L;;;;;N;;;;; +13D8D;EGYPTIAN HIEROGLYPH-13D8D;Lo;0;L;;;;;N;;;;; +13D8E;EGYPTIAN HIEROGLYPH-13D8E;Lo;0;L;;;;;N;;;;; +13D8F;EGYPTIAN HIEROGLYPH-13D8F;Lo;0;L;;;;;N;;;;; +13D90;EGYPTIAN HIEROGLYPH-13D90;Lo;0;L;;;;;N;;;;; +13D91;EGYPTIAN HIEROGLYPH-13D91;Lo;0;L;;;;;N;;;;; +13D92;EGYPTIAN HIEROGLYPH-13D92;Lo;0;L;;;;;N;;;;; +13D93;EGYPTIAN HIEROGLYPH-13D93;Lo;0;L;;;;;N;;;;; +13D94;EGYPTIAN HIEROGLYPH-13D94;Lo;0;L;;;;;N;;;;; +13D95;EGYPTIAN HIEROGLYPH-13D95;Lo;0;L;;;;;N;;;;; +13D96;EGYPTIAN HIEROGLYPH-13D96;Lo;0;L;;;;;N;;;;; +13D97;EGYPTIAN HIEROGLYPH-13D97;Lo;0;L;;;;;N;;;;; +13D98;EGYPTIAN HIEROGLYPH-13D98;Lo;0;L;;;;;N;;;;; +13D99;EGYPTIAN HIEROGLYPH-13D99;Lo;0;L;;;;;N;;;;; +13D9A;EGYPTIAN HIEROGLYPH-13D9A;Lo;0;L;;;;;N;;;;; +13D9B;EGYPTIAN HIEROGLYPH-13D9B;Lo;0;L;;;;;N;;;;; +13D9C;EGYPTIAN HIEROGLYPH-13D9C;Lo;0;L;;;;;N;;;;; +13D9D;EGYPTIAN HIEROGLYPH-13D9D;Lo;0;L;;;;;N;;;;; +13D9E;EGYPTIAN HIEROGLYPH-13D9E;Lo;0;L;;;;;N;;;;; +13D9F;EGYPTIAN HIEROGLYPH-13D9F;Lo;0;L;;;;;N;;;;; +13DA0;EGYPTIAN HIEROGLYPH-13DA0;Lo;0;L;;;;;N;;;;; +13DA1;EGYPTIAN HIEROGLYPH-13DA1;Lo;0;L;;;;;N;;;;; +13DA2;EGYPTIAN HIEROGLYPH-13DA2;Lo;0;L;;;;;N;;;;; +13DA3;EGYPTIAN HIEROGLYPH-13DA3;Lo;0;L;;;;;N;;;;; +13DA4;EGYPTIAN HIEROGLYPH-13DA4;Lo;0;L;;;;;N;;;;; +13DA5;EGYPTIAN HIEROGLYPH-13DA5;Lo;0;L;;;;;N;;;;; +13DA6;EGYPTIAN HIEROGLYPH-13DA6;Lo;0;L;;;;;N;;;;; +13DA7;EGYPTIAN HIEROGLYPH-13DA7;Lo;0;L;;;;;N;;;;; +13DA8;EGYPTIAN HIEROGLYPH-13DA8;Lo;0;L;;;;;N;;;;; +13DA9;EGYPTIAN HIEROGLYPH-13DA9;Lo;0;L;;;;;N;;;;; +13DAA;EGYPTIAN HIEROGLYPH-13DAA;Lo;0;L;;;;;N;;;;; +13DAB;EGYPTIAN HIEROGLYPH-13DAB;Lo;0;L;;;;;N;;;;; +13DAC;EGYPTIAN HIEROGLYPH-13DAC;Lo;0;L;;;;;N;;;;; +13DAD;EGYPTIAN HIEROGLYPH-13DAD;Lo;0;L;;;;;N;;;;; +13DAE;EGYPTIAN HIEROGLYPH-13DAE;Lo;0;L;;;;;N;;;;; +13DAF;EGYPTIAN HIEROGLYPH-13DAF;Lo;0;L;;;;;N;;;;; +13DB0;EGYPTIAN HIEROGLYPH-13DB0;Lo;0;L;;;;;N;;;;; +13DB1;EGYPTIAN HIEROGLYPH-13DB1;Lo;0;L;;;;;N;;;;; +13DB2;EGYPTIAN HIEROGLYPH-13DB2;Lo;0;L;;;;;N;;;;; +13DB3;EGYPTIAN HIEROGLYPH-13DB3;Lo;0;L;;;;;N;;;;; +13DB4;EGYPTIAN HIEROGLYPH-13DB4;Lo;0;L;;;;;N;;;;; +13DB5;EGYPTIAN HIEROGLYPH-13DB5;Lo;0;L;;;;;N;;;;; +13DB6;EGYPTIAN HIEROGLYPH-13DB6;Lo;0;L;;;;;N;;;;; +13DB7;EGYPTIAN HIEROGLYPH-13DB7;Lo;0;L;;;;;N;;;;; +13DB8;EGYPTIAN HIEROGLYPH-13DB8;Lo;0;L;;;;;N;;;;; +13DB9;EGYPTIAN HIEROGLYPH-13DB9;Lo;0;L;;;;;N;;;;; +13DBA;EGYPTIAN HIEROGLYPH-13DBA;Lo;0;L;;;;;N;;;;; +13DBB;EGYPTIAN HIEROGLYPH-13DBB;Lo;0;L;;;;;N;;;;; +13DBC;EGYPTIAN HIEROGLYPH-13DBC;Lo;0;L;;;;;N;;;;; +13DBD;EGYPTIAN HIEROGLYPH-13DBD;Lo;0;L;;;;;N;;;;; +13DBE;EGYPTIAN HIEROGLYPH-13DBE;Lo;0;L;;;;;N;;;;; +13DBF;EGYPTIAN HIEROGLYPH-13DBF;Lo;0;L;;;;;N;;;;; +13DC0;EGYPTIAN HIEROGLYPH-13DC0;Lo;0;L;;;;;N;;;;; +13DC1;EGYPTIAN HIEROGLYPH-13DC1;Lo;0;L;;;;;N;;;;; +13DC2;EGYPTIAN HIEROGLYPH-13DC2;Lo;0;L;;;;;N;;;;; +13DC3;EGYPTIAN HIEROGLYPH-13DC3;Lo;0;L;;;;;N;;;;; +13DC4;EGYPTIAN HIEROGLYPH-13DC4;Lo;0;L;;;;;N;;;;; +13DC5;EGYPTIAN HIEROGLYPH-13DC5;Lo;0;L;;;;;N;;;;; +13DC6;EGYPTIAN HIEROGLYPH-13DC6;Lo;0;L;;;;;N;;;;; +13DC7;EGYPTIAN HIEROGLYPH-13DC7;Lo;0;L;;;;;N;;;;; +13DC8;EGYPTIAN HIEROGLYPH-13DC8;Lo;0;L;;;;;N;;;;; +13DC9;EGYPTIAN HIEROGLYPH-13DC9;Lo;0;L;;;;;N;;;;; +13DCA;EGYPTIAN HIEROGLYPH-13DCA;Lo;0;L;;;;;N;;;;; +13DCB;EGYPTIAN HIEROGLYPH-13DCB;Lo;0;L;;;;;N;;;;; +13DCC;EGYPTIAN HIEROGLYPH-13DCC;Lo;0;L;;;;;N;;;;; +13DCD;EGYPTIAN HIEROGLYPH-13DCD;Lo;0;L;;;;;N;;;;; +13DCE;EGYPTIAN HIEROGLYPH-13DCE;Lo;0;L;;;;;N;;;;; +13DCF;EGYPTIAN HIEROGLYPH-13DCF;Lo;0;L;;;;;N;;;;; +13DD0;EGYPTIAN HIEROGLYPH-13DD0;Lo;0;L;;;;;N;;;;; +13DD1;EGYPTIAN HIEROGLYPH-13DD1;Lo;0;L;;;;;N;;;;; +13DD2;EGYPTIAN HIEROGLYPH-13DD2;Lo;0;L;;;;;N;;;;; +13DD3;EGYPTIAN HIEROGLYPH-13DD3;Lo;0;L;;;;;N;;;;; +13DD4;EGYPTIAN HIEROGLYPH-13DD4;Lo;0;L;;;;;N;;;;; +13DD5;EGYPTIAN HIEROGLYPH-13DD5;Lo;0;L;;;;;N;;;;; +13DD6;EGYPTIAN HIEROGLYPH-13DD6;Lo;0;L;;;;;N;;;;; +13DD7;EGYPTIAN HIEROGLYPH-13DD7;Lo;0;L;;;;;N;;;;; +13DD8;EGYPTIAN HIEROGLYPH-13DD8;Lo;0;L;;;;;N;;;;; +13DD9;EGYPTIAN HIEROGLYPH-13DD9;Lo;0;L;;;;;N;;;;; +13DDA;EGYPTIAN HIEROGLYPH-13DDA;Lo;0;L;;;;;N;;;;; +13DDB;EGYPTIAN HIEROGLYPH-13DDB;Lo;0;L;;;;;N;;;;; +13DDC;EGYPTIAN HIEROGLYPH-13DDC;Lo;0;L;;;;;N;;;;; +13DDD;EGYPTIAN HIEROGLYPH-13DDD;Lo;0;L;;;;;N;;;;; +13DDE;EGYPTIAN HIEROGLYPH-13DDE;Lo;0;L;;;;;N;;;;; +13DDF;EGYPTIAN HIEROGLYPH-13DDF;Lo;0;L;;;;;N;;;;; +13DE0;EGYPTIAN HIEROGLYPH-13DE0;Lo;0;L;;;;;N;;;;; +13DE1;EGYPTIAN HIEROGLYPH-13DE1;Lo;0;L;;;;;N;;;;; +13DE2;EGYPTIAN HIEROGLYPH-13DE2;Lo;0;L;;;;;N;;;;; +13DE3;EGYPTIAN HIEROGLYPH-13DE3;Lo;0;L;;;;;N;;;;; +13DE4;EGYPTIAN HIEROGLYPH-13DE4;Lo;0;L;;;;;N;;;;; +13DE5;EGYPTIAN HIEROGLYPH-13DE5;Lo;0;L;;;;;N;;;;; +13DE6;EGYPTIAN HIEROGLYPH-13DE6;Lo;0;L;;;;;N;;;;; +13DE7;EGYPTIAN HIEROGLYPH-13DE7;Lo;0;L;;;;;N;;;;; +13DE8;EGYPTIAN HIEROGLYPH-13DE8;Lo;0;L;;;;;N;;;;; +13DE9;EGYPTIAN HIEROGLYPH-13DE9;Lo;0;L;;;;;N;;;;; +13DEA;EGYPTIAN HIEROGLYPH-13DEA;Lo;0;L;;;;;N;;;;; +13DEB;EGYPTIAN HIEROGLYPH-13DEB;Lo;0;L;;;;;N;;;;; +13DEC;EGYPTIAN HIEROGLYPH-13DEC;Lo;0;L;;;;;N;;;;; +13DED;EGYPTIAN HIEROGLYPH-13DED;Lo;0;L;;;;;N;;;;; +13DEE;EGYPTIAN HIEROGLYPH-13DEE;Lo;0;L;;;;;N;;;;; +13DEF;EGYPTIAN HIEROGLYPH-13DEF;Lo;0;L;;;;;N;;;;; +13DF0;EGYPTIAN HIEROGLYPH-13DF0;Lo;0;L;;;;;N;;;;; +13DF1;EGYPTIAN HIEROGLYPH-13DF1;Lo;0;L;;;;;N;;;;; +13DF2;EGYPTIAN HIEROGLYPH-13DF2;Lo;0;L;;;;;N;;;;; +13DF3;EGYPTIAN HIEROGLYPH-13DF3;Lo;0;L;;;;;N;;;;; +13DF4;EGYPTIAN HIEROGLYPH-13DF4;Lo;0;L;;;;;N;;;;; +13DF5;EGYPTIAN HIEROGLYPH-13DF5;Lo;0;L;;;;;N;;;;; +13DF6;EGYPTIAN HIEROGLYPH-13DF6;Lo;0;L;;;;;N;;;;; +13DF7;EGYPTIAN HIEROGLYPH-13DF7;Lo;0;L;;;;;N;;;;; +13DF8;EGYPTIAN HIEROGLYPH-13DF8;Lo;0;L;;;;;N;;;;; +13DF9;EGYPTIAN HIEROGLYPH-13DF9;Lo;0;L;;;;;N;;;;; +13DFA;EGYPTIAN HIEROGLYPH-13DFA;Lo;0;L;;;;;N;;;;; +13DFB;EGYPTIAN HIEROGLYPH-13DFB;Lo;0;L;;;;;N;;;;; +13DFC;EGYPTIAN HIEROGLYPH-13DFC;Lo;0;L;;;;;N;;;;; +13DFD;EGYPTIAN HIEROGLYPH-13DFD;Lo;0;L;;;;;N;;;;; +13DFE;EGYPTIAN HIEROGLYPH-13DFE;Lo;0;L;;;;;N;;;;; +13DFF;EGYPTIAN HIEROGLYPH-13DFF;Lo;0;L;;;;;N;;;;; +13E00;EGYPTIAN HIEROGLYPH-13E00;Lo;0;L;;;;;N;;;;; +13E01;EGYPTIAN HIEROGLYPH-13E01;Lo;0;L;;;;;N;;;;; +13E02;EGYPTIAN HIEROGLYPH-13E02;Lo;0;L;;;;;N;;;;; +13E03;EGYPTIAN HIEROGLYPH-13E03;Lo;0;L;;;;;N;;;;; +13E04;EGYPTIAN HIEROGLYPH-13E04;Lo;0;L;;;;;N;;;;; +13E05;EGYPTIAN HIEROGLYPH-13E05;Lo;0;L;;;;;N;;;;; +13E06;EGYPTIAN HIEROGLYPH-13E06;Lo;0;L;;;;;N;;;;; +13E07;EGYPTIAN HIEROGLYPH-13E07;Lo;0;L;;;;;N;;;;; +13E08;EGYPTIAN HIEROGLYPH-13E08;Lo;0;L;;;;;N;;;;; +13E09;EGYPTIAN HIEROGLYPH-13E09;Lo;0;L;;;;;N;;;;; +13E0A;EGYPTIAN HIEROGLYPH-13E0A;Lo;0;L;;;;;N;;;;; +13E0B;EGYPTIAN HIEROGLYPH-13E0B;Lo;0;L;;;;;N;;;;; +13E0C;EGYPTIAN HIEROGLYPH-13E0C;Lo;0;L;;;;;N;;;;; +13E0D;EGYPTIAN HIEROGLYPH-13E0D;Lo;0;L;;;;;N;;;;; +13E0E;EGYPTIAN HIEROGLYPH-13E0E;Lo;0;L;;;;;N;;;;; +13E0F;EGYPTIAN HIEROGLYPH-13E0F;Lo;0;L;;;;;N;;;;; +13E10;EGYPTIAN HIEROGLYPH-13E10;Lo;0;L;;;;;N;;;;; +13E11;EGYPTIAN HIEROGLYPH-13E11;Lo;0;L;;;;;N;;;;; +13E12;EGYPTIAN HIEROGLYPH-13E12;Lo;0;L;;;;;N;;;;; +13E13;EGYPTIAN HIEROGLYPH-13E13;Lo;0;L;;;;;N;;;;; +13E14;EGYPTIAN HIEROGLYPH-13E14;Lo;0;L;;;;;N;;;;; +13E15;EGYPTIAN HIEROGLYPH-13E15;Lo;0;L;;;;;N;;;;; +13E16;EGYPTIAN HIEROGLYPH-13E16;Lo;0;L;;;;;N;;;;; +13E17;EGYPTIAN HIEROGLYPH-13E17;Lo;0;L;;;;;N;;;;; +13E18;EGYPTIAN HIEROGLYPH-13E18;Lo;0;L;;;;;N;;;;; +13E19;EGYPTIAN HIEROGLYPH-13E19;Lo;0;L;;;;;N;;;;; +13E1A;EGYPTIAN HIEROGLYPH-13E1A;Lo;0;L;;;;;N;;;;; +13E1B;EGYPTIAN HIEROGLYPH-13E1B;Lo;0;L;;;;;N;;;;; +13E1C;EGYPTIAN HIEROGLYPH-13E1C;Lo;0;L;;;;;N;;;;; +13E1D;EGYPTIAN HIEROGLYPH-13E1D;Lo;0;L;;;;;N;;;;; +13E1E;EGYPTIAN HIEROGLYPH-13E1E;Lo;0;L;;;;;N;;;;; +13E1F;EGYPTIAN HIEROGLYPH-13E1F;Lo;0;L;;;;;N;;;;; +13E20;EGYPTIAN HIEROGLYPH-13E20;Lo;0;L;;;;;N;;;;; +13E21;EGYPTIAN HIEROGLYPH-13E21;Lo;0;L;;;;;N;;;;; +13E22;EGYPTIAN HIEROGLYPH-13E22;Lo;0;L;;;;;N;;;;; +13E23;EGYPTIAN HIEROGLYPH-13E23;Lo;0;L;;;;;N;;;;; +13E24;EGYPTIAN HIEROGLYPH-13E24;Lo;0;L;;;;;N;;;;; +13E25;EGYPTIAN HIEROGLYPH-13E25;Lo;0;L;;;;;N;;;;; +13E26;EGYPTIAN HIEROGLYPH-13E26;Lo;0;L;;;;;N;;;;; +13E27;EGYPTIAN HIEROGLYPH-13E27;Lo;0;L;;;;;N;;;;; +13E28;EGYPTIAN HIEROGLYPH-13E28;Lo;0;L;;;;;N;;;;; +13E29;EGYPTIAN HIEROGLYPH-13E29;Lo;0;L;;;;;N;;;;; +13E2A;EGYPTIAN HIEROGLYPH-13E2A;Lo;0;L;;;;;N;;;;; +13E2B;EGYPTIAN HIEROGLYPH-13E2B;Lo;0;L;;;;;N;;;;; +13E2C;EGYPTIAN HIEROGLYPH-13E2C;Lo;0;L;;;;;N;;;;; +13E2D;EGYPTIAN HIEROGLYPH-13E2D;Lo;0;L;;;;;N;;;;; +13E2E;EGYPTIAN HIEROGLYPH-13E2E;Lo;0;L;;;;;N;;;;; +13E2F;EGYPTIAN HIEROGLYPH-13E2F;Lo;0;L;;;;;N;;;;; +13E30;EGYPTIAN HIEROGLYPH-13E30;Lo;0;L;;;;;N;;;;; +13E31;EGYPTIAN HIEROGLYPH-13E31;Lo;0;L;;;;;N;;;;; +13E32;EGYPTIAN HIEROGLYPH-13E32;Lo;0;L;;;;;N;;;;; +13E33;EGYPTIAN HIEROGLYPH-13E33;Lo;0;L;;;;;N;;;;; +13E34;EGYPTIAN HIEROGLYPH-13E34;Lo;0;L;;;;;N;;;;; +13E35;EGYPTIAN HIEROGLYPH-13E35;Lo;0;L;;;;;N;;;;; +13E36;EGYPTIAN HIEROGLYPH-13E36;Lo;0;L;;;;;N;;;;; +13E37;EGYPTIAN HIEROGLYPH-13E37;Lo;0;L;;;;;N;;;;; +13E38;EGYPTIAN HIEROGLYPH-13E38;Lo;0;L;;;;;N;;;;; +13E39;EGYPTIAN HIEROGLYPH-13E39;Lo;0;L;;;;;N;;;;; +13E3A;EGYPTIAN HIEROGLYPH-13E3A;Lo;0;L;;;;;N;;;;; +13E3B;EGYPTIAN HIEROGLYPH-13E3B;Lo;0;L;;;;;N;;;;; +13E3C;EGYPTIAN HIEROGLYPH-13E3C;Lo;0;L;;;;;N;;;;; +13E3D;EGYPTIAN HIEROGLYPH-13E3D;Lo;0;L;;;;;N;;;;; +13E3E;EGYPTIAN HIEROGLYPH-13E3E;Lo;0;L;;;;;N;;;;; +13E3F;EGYPTIAN HIEROGLYPH-13E3F;Lo;0;L;;;;;N;;;;; +13E40;EGYPTIAN HIEROGLYPH-13E40;Lo;0;L;;;;;N;;;;; +13E41;EGYPTIAN HIEROGLYPH-13E41;Lo;0;L;;;;;N;;;;; +13E42;EGYPTIAN HIEROGLYPH-13E42;Lo;0;L;;;;;N;;;;; +13E43;EGYPTIAN HIEROGLYPH-13E43;Lo;0;L;;;;;N;;;;; +13E44;EGYPTIAN HIEROGLYPH-13E44;Lo;0;L;;;;;N;;;;; +13E45;EGYPTIAN HIEROGLYPH-13E45;Lo;0;L;;;;;N;;;;; +13E46;EGYPTIAN HIEROGLYPH-13E46;Lo;0;L;;;;;N;;;;; +13E47;EGYPTIAN HIEROGLYPH-13E47;Lo;0;L;;;;;N;;;;; +13E48;EGYPTIAN HIEROGLYPH-13E48;Lo;0;L;;;;;N;;;;; +13E49;EGYPTIAN HIEROGLYPH-13E49;Lo;0;L;;;;;N;;;;; +13E4A;EGYPTIAN HIEROGLYPH-13E4A;Lo;0;L;;;;;N;;;;; +13E4B;EGYPTIAN HIEROGLYPH-13E4B;Lo;0;L;;;;;N;;;;; +13E4C;EGYPTIAN HIEROGLYPH-13E4C;Lo;0;L;;;;;N;;;;; +13E4D;EGYPTIAN HIEROGLYPH-13E4D;Lo;0;L;;;;;N;;;;; +13E4E;EGYPTIAN HIEROGLYPH-13E4E;Lo;0;L;;;;;N;;;;; +13E4F;EGYPTIAN HIEROGLYPH-13E4F;Lo;0;L;;;;;N;;;;; +13E50;EGYPTIAN HIEROGLYPH-13E50;Lo;0;L;;;;;N;;;;; +13E51;EGYPTIAN HIEROGLYPH-13E51;Lo;0;L;;;;;N;;;;; +13E52;EGYPTIAN HIEROGLYPH-13E52;Lo;0;L;;;;;N;;;;; +13E53;EGYPTIAN HIEROGLYPH-13E53;Lo;0;L;;;;;N;;;;; +13E54;EGYPTIAN HIEROGLYPH-13E54;Lo;0;L;;;;;N;;;;; +13E55;EGYPTIAN HIEROGLYPH-13E55;Lo;0;L;;;;;N;;;;; +13E56;EGYPTIAN HIEROGLYPH-13E56;Lo;0;L;;;;;N;;;;; +13E57;EGYPTIAN HIEROGLYPH-13E57;Lo;0;L;;;;;N;;;;; +13E58;EGYPTIAN HIEROGLYPH-13E58;Lo;0;L;;;;;N;;;;; +13E59;EGYPTIAN HIEROGLYPH-13E59;Lo;0;L;;;;;N;;;;; +13E5A;EGYPTIAN HIEROGLYPH-13E5A;Lo;0;L;;;;;N;;;;; +13E5B;EGYPTIAN HIEROGLYPH-13E5B;Lo;0;L;;;;;N;;;;; +13E5C;EGYPTIAN HIEROGLYPH-13E5C;Lo;0;L;;;;;N;;;;; +13E5D;EGYPTIAN HIEROGLYPH-13E5D;Lo;0;L;;;;;N;;;;; +13E5E;EGYPTIAN HIEROGLYPH-13E5E;Lo;0;L;;;;;N;;;;; +13E5F;EGYPTIAN HIEROGLYPH-13E5F;Lo;0;L;;;;;N;;;;; +13E60;EGYPTIAN HIEROGLYPH-13E60;Lo;0;L;;;;;N;;;;; +13E61;EGYPTIAN HIEROGLYPH-13E61;Lo;0;L;;;;;N;;;;; +13E62;EGYPTIAN HIEROGLYPH-13E62;Lo;0;L;;;;;N;;;;; +13E63;EGYPTIAN HIEROGLYPH-13E63;Lo;0;L;;;;;N;;;;; +13E64;EGYPTIAN HIEROGLYPH-13E64;Lo;0;L;;;;;N;;;;; +13E65;EGYPTIAN HIEROGLYPH-13E65;Lo;0;L;;;;;N;;;;; +13E66;EGYPTIAN HIEROGLYPH-13E66;Lo;0;L;;;;;N;;;;; +13E67;EGYPTIAN HIEROGLYPH-13E67;Lo;0;L;;;;;N;;;;; +13E68;EGYPTIAN HIEROGLYPH-13E68;Lo;0;L;;;;;N;;;;; +13E69;EGYPTIAN HIEROGLYPH-13E69;Lo;0;L;;;;;N;;;;; +13E6A;EGYPTIAN HIEROGLYPH-13E6A;Lo;0;L;;;;;N;;;;; +13E6B;EGYPTIAN HIEROGLYPH-13E6B;Lo;0;L;;;;;N;;;;; +13E6C;EGYPTIAN HIEROGLYPH-13E6C;Lo;0;L;;;;;N;;;;; +13E6D;EGYPTIAN HIEROGLYPH-13E6D;Lo;0;L;;;;;N;;;;; +13E6E;EGYPTIAN HIEROGLYPH-13E6E;Lo;0;L;;;;;N;;;;; +13E6F;EGYPTIAN HIEROGLYPH-13E6F;Lo;0;L;;;;;N;;;;; +13E70;EGYPTIAN HIEROGLYPH-13E70;Lo;0;L;;;;;N;;;;; +13E71;EGYPTIAN HIEROGLYPH-13E71;Lo;0;L;;;;;N;;;;; +13E72;EGYPTIAN HIEROGLYPH-13E72;Lo;0;L;;;;;N;;;;; +13E73;EGYPTIAN HIEROGLYPH-13E73;Lo;0;L;;;;;N;;;;; +13E74;EGYPTIAN HIEROGLYPH-13E74;Lo;0;L;;;;;N;;;;; +13E75;EGYPTIAN HIEROGLYPH-13E75;Lo;0;L;;;;;N;;;;; +13E76;EGYPTIAN HIEROGLYPH-13E76;Lo;0;L;;;;;N;;;;; +13E77;EGYPTIAN HIEROGLYPH-13E77;Lo;0;L;;;;;N;;;;; +13E78;EGYPTIAN HIEROGLYPH-13E78;Lo;0;L;;;;;N;;;;; +13E79;EGYPTIAN HIEROGLYPH-13E79;Lo;0;L;;;;;N;;;;; +13E7A;EGYPTIAN HIEROGLYPH-13E7A;Lo;0;L;;;;;N;;;;; +13E7B;EGYPTIAN HIEROGLYPH-13E7B;Lo;0;L;;;;;N;;;;; +13E7C;EGYPTIAN HIEROGLYPH-13E7C;Lo;0;L;;;;;N;;;;; +13E7D;EGYPTIAN HIEROGLYPH-13E7D;Lo;0;L;;;;;N;;;;; +13E7E;EGYPTIAN HIEROGLYPH-13E7E;Lo;0;L;;;;;N;;;;; +13E7F;EGYPTIAN HIEROGLYPH-13E7F;Lo;0;L;;;;;N;;;;; +13E80;EGYPTIAN HIEROGLYPH-13E80;Lo;0;L;;;;;N;;;;; +13E81;EGYPTIAN HIEROGLYPH-13E81;Lo;0;L;;;;;N;;;;; +13E82;EGYPTIAN HIEROGLYPH-13E82;Lo;0;L;;;;;N;;;;; +13E83;EGYPTIAN HIEROGLYPH-13E83;Lo;0;L;;;;;N;;;;; +13E84;EGYPTIAN HIEROGLYPH-13E84;Lo;0;L;;;;;N;;;;; +13E85;EGYPTIAN HIEROGLYPH-13E85;Lo;0;L;;;;;N;;;;; +13E86;EGYPTIAN HIEROGLYPH-13E86;Lo;0;L;;;;;N;;;;; +13E87;EGYPTIAN HIEROGLYPH-13E87;Lo;0;L;;;;;N;;;;; +13E88;EGYPTIAN HIEROGLYPH-13E88;Lo;0;L;;;;;N;;;;; +13E89;EGYPTIAN HIEROGLYPH-13E89;Lo;0;L;;;;;N;;;;; +13E8A;EGYPTIAN HIEROGLYPH-13E8A;Lo;0;L;;;;;N;;;;; +13E8B;EGYPTIAN HIEROGLYPH-13E8B;Lo;0;L;;;;;N;;;;; +13E8C;EGYPTIAN HIEROGLYPH-13E8C;Lo;0;L;;;;;N;;;;; +13E8D;EGYPTIAN HIEROGLYPH-13E8D;Lo;0;L;;;;;N;;;;; +13E8E;EGYPTIAN HIEROGLYPH-13E8E;Lo;0;L;;;;;N;;;;; +13E8F;EGYPTIAN HIEROGLYPH-13E8F;Lo;0;L;;;;;N;;;;; +13E90;EGYPTIAN HIEROGLYPH-13E90;Lo;0;L;;;;;N;;;;; +13E91;EGYPTIAN HIEROGLYPH-13E91;Lo;0;L;;;;;N;;;;; +13E92;EGYPTIAN HIEROGLYPH-13E92;Lo;0;L;;;;;N;;;;; +13E93;EGYPTIAN HIEROGLYPH-13E93;Lo;0;L;;;;;N;;;;; +13E94;EGYPTIAN HIEROGLYPH-13E94;Lo;0;L;;;;;N;;;;; +13E95;EGYPTIAN HIEROGLYPH-13E95;Lo;0;L;;;;;N;;;;; +13E96;EGYPTIAN HIEROGLYPH-13E96;Lo;0;L;;;;;N;;;;; +13E97;EGYPTIAN HIEROGLYPH-13E97;Lo;0;L;;;;;N;;;;; +13E98;EGYPTIAN HIEROGLYPH-13E98;Lo;0;L;;;;;N;;;;; +13E99;EGYPTIAN HIEROGLYPH-13E99;Lo;0;L;;;;;N;;;;; +13E9A;EGYPTIAN HIEROGLYPH-13E9A;Lo;0;L;;;;;N;;;;; +13E9B;EGYPTIAN HIEROGLYPH-13E9B;Lo;0;L;;;;;N;;;;; +13E9C;EGYPTIAN HIEROGLYPH-13E9C;Lo;0;L;;;;;N;;;;; +13E9D;EGYPTIAN HIEROGLYPH-13E9D;Lo;0;L;;;;;N;;;;; +13E9E;EGYPTIAN HIEROGLYPH-13E9E;Lo;0;L;;;;;N;;;;; +13E9F;EGYPTIAN HIEROGLYPH-13E9F;Lo;0;L;;;;;N;;;;; +13EA0;EGYPTIAN HIEROGLYPH-13EA0;Lo;0;L;;;;;N;;;;; +13EA1;EGYPTIAN HIEROGLYPH-13EA1;Lo;0;L;;;;;N;;;;; +13EA2;EGYPTIAN HIEROGLYPH-13EA2;Lo;0;L;;;;;N;;;;; +13EA3;EGYPTIAN HIEROGLYPH-13EA3;Lo;0;L;;;;;N;;;;; +13EA4;EGYPTIAN HIEROGLYPH-13EA4;Lo;0;L;;;;;N;;;;; +13EA5;EGYPTIAN HIEROGLYPH-13EA5;Lo;0;L;;;;;N;;;;; +13EA6;EGYPTIAN HIEROGLYPH-13EA6;Lo;0;L;;;;;N;;;;; +13EA7;EGYPTIAN HIEROGLYPH-13EA7;Lo;0;L;;;;;N;;;;; +13EA8;EGYPTIAN HIEROGLYPH-13EA8;Lo;0;L;;;;;N;;;;; +13EA9;EGYPTIAN HIEROGLYPH-13EA9;Lo;0;L;;;;;N;;;;; +13EAA;EGYPTIAN HIEROGLYPH-13EAA;Lo;0;L;;;;;N;;;;; +13EAB;EGYPTIAN HIEROGLYPH-13EAB;Lo;0;L;;;;;N;;;;; +13EAC;EGYPTIAN HIEROGLYPH-13EAC;Lo;0;L;;;;;N;;;;; +13EAD;EGYPTIAN HIEROGLYPH-13EAD;Lo;0;L;;;;;N;;;;; +13EAE;EGYPTIAN HIEROGLYPH-13EAE;Lo;0;L;;;;;N;;;;; +13EAF;EGYPTIAN HIEROGLYPH-13EAF;Lo;0;L;;;;;N;;;;; +13EB0;EGYPTIAN HIEROGLYPH-13EB0;Lo;0;L;;;;;N;;;;; +13EB1;EGYPTIAN HIEROGLYPH-13EB1;Lo;0;L;;;;;N;;;;; +13EB2;EGYPTIAN HIEROGLYPH-13EB2;Lo;0;L;;;;;N;;;;; +13EB3;EGYPTIAN HIEROGLYPH-13EB3;Lo;0;L;;;;;N;;;;; +13EB4;EGYPTIAN HIEROGLYPH-13EB4;Lo;0;L;;;;;N;;;;; +13EB5;EGYPTIAN HIEROGLYPH-13EB5;Lo;0;L;;;;;N;;;;; +13EB6;EGYPTIAN HIEROGLYPH-13EB6;Lo;0;L;;;;;N;;;;; +13EB7;EGYPTIAN HIEROGLYPH-13EB7;Lo;0;L;;;;;N;;;;; +13EB8;EGYPTIAN HIEROGLYPH-13EB8;Lo;0;L;;;;;N;;;;; +13EB9;EGYPTIAN HIEROGLYPH-13EB9;Lo;0;L;;;;;N;;;;; +13EBA;EGYPTIAN HIEROGLYPH-13EBA;Lo;0;L;;;;;N;;;;; +13EBB;EGYPTIAN HIEROGLYPH-13EBB;Lo;0;L;;;;;N;;;;; +13EBC;EGYPTIAN HIEROGLYPH-13EBC;Lo;0;L;;;;;N;;;;; +13EBD;EGYPTIAN HIEROGLYPH-13EBD;Lo;0;L;;;;;N;;;;; +13EBE;EGYPTIAN HIEROGLYPH-13EBE;Lo;0;L;;;;;N;;;;; +13EBF;EGYPTIAN HIEROGLYPH-13EBF;Lo;0;L;;;;;N;;;;; +13EC0;EGYPTIAN HIEROGLYPH-13EC0;Lo;0;L;;;;;N;;;;; +13EC1;EGYPTIAN HIEROGLYPH-13EC1;Lo;0;L;;;;;N;;;;; +13EC2;EGYPTIAN HIEROGLYPH-13EC2;Lo;0;L;;;;;N;;;;; +13EC3;EGYPTIAN HIEROGLYPH-13EC3;Lo;0;L;;;;;N;;;;; +13EC4;EGYPTIAN HIEROGLYPH-13EC4;Lo;0;L;;;;;N;;;;; +13EC5;EGYPTIAN HIEROGLYPH-13EC5;Lo;0;L;;;;;N;;;;; +13EC6;EGYPTIAN HIEROGLYPH-13EC6;Lo;0;L;;;;;N;;;;; +13EC7;EGYPTIAN HIEROGLYPH-13EC7;Lo;0;L;;;;;N;;;;; +13EC8;EGYPTIAN HIEROGLYPH-13EC8;Lo;0;L;;;;;N;;;;; +13EC9;EGYPTIAN HIEROGLYPH-13EC9;Lo;0;L;;;;;N;;;;; +13ECA;EGYPTIAN HIEROGLYPH-13ECA;Lo;0;L;;;;;N;;;;; +13ECB;EGYPTIAN HIEROGLYPH-13ECB;Lo;0;L;;;;;N;;;;; +13ECC;EGYPTIAN HIEROGLYPH-13ECC;Lo;0;L;;;;;N;;;;; +13ECD;EGYPTIAN HIEROGLYPH-13ECD;Lo;0;L;;;;;N;;;;; +13ECE;EGYPTIAN HIEROGLYPH-13ECE;Lo;0;L;;;;;N;;;;; +13ECF;EGYPTIAN HIEROGLYPH-13ECF;Lo;0;L;;;;;N;;;;; +13ED0;EGYPTIAN HIEROGLYPH-13ED0;Lo;0;L;;;;;N;;;;; +13ED1;EGYPTIAN HIEROGLYPH-13ED1;Lo;0;L;;;;;N;;;;; +13ED2;EGYPTIAN HIEROGLYPH-13ED2;Lo;0;L;;;;;N;;;;; +13ED3;EGYPTIAN HIEROGLYPH-13ED3;Lo;0;L;;;;;N;;;;; +13ED4;EGYPTIAN HIEROGLYPH-13ED4;Lo;0;L;;;;;N;;;;; +13ED5;EGYPTIAN HIEROGLYPH-13ED5;Lo;0;L;;;;;N;;;;; +13ED6;EGYPTIAN HIEROGLYPH-13ED6;Lo;0;L;;;;;N;;;;; +13ED7;EGYPTIAN HIEROGLYPH-13ED7;Lo;0;L;;;;;N;;;;; +13ED8;EGYPTIAN HIEROGLYPH-13ED8;Lo;0;L;;;;;N;;;;; +13ED9;EGYPTIAN HIEROGLYPH-13ED9;Lo;0;L;;;;;N;;;;; +13EDA;EGYPTIAN HIEROGLYPH-13EDA;Lo;0;L;;;;;N;;;;; +13EDB;EGYPTIAN HIEROGLYPH-13EDB;Lo;0;L;;;;;N;;;;; +13EDC;EGYPTIAN HIEROGLYPH-13EDC;Lo;0;L;;;;;N;;;;; +13EDD;EGYPTIAN HIEROGLYPH-13EDD;Lo;0;L;;;;;N;;;;; +13EDE;EGYPTIAN HIEROGLYPH-13EDE;Lo;0;L;;;;;N;;;;; +13EDF;EGYPTIAN HIEROGLYPH-13EDF;Lo;0;L;;;;;N;;;;; +13EE0;EGYPTIAN HIEROGLYPH-13EE0;Lo;0;L;;;;;N;;;;; +13EE1;EGYPTIAN HIEROGLYPH-13EE1;Lo;0;L;;;;;N;;;;; +13EE2;EGYPTIAN HIEROGLYPH-13EE2;Lo;0;L;;;;;N;;;;; +13EE3;EGYPTIAN HIEROGLYPH-13EE3;Lo;0;L;;;;;N;;;;; +13EE4;EGYPTIAN HIEROGLYPH-13EE4;Lo;0;L;;;;;N;;;;; +13EE5;EGYPTIAN HIEROGLYPH-13EE5;Lo;0;L;;;;;N;;;;; +13EE6;EGYPTIAN HIEROGLYPH-13EE6;Lo;0;L;;;;;N;;;;; +13EE7;EGYPTIAN HIEROGLYPH-13EE7;Lo;0;L;;;;;N;;;;; +13EE8;EGYPTIAN HIEROGLYPH-13EE8;Lo;0;L;;;;;N;;;;; +13EE9;EGYPTIAN HIEROGLYPH-13EE9;Lo;0;L;;;;;N;;;;; +13EEA;EGYPTIAN HIEROGLYPH-13EEA;Lo;0;L;;;;;N;;;;; +13EEB;EGYPTIAN HIEROGLYPH-13EEB;Lo;0;L;;;;;N;;;;; +13EEC;EGYPTIAN HIEROGLYPH-13EEC;Lo;0;L;;;;;N;;;;; +13EED;EGYPTIAN HIEROGLYPH-13EED;Lo;0;L;;;;;N;;;;; +13EEE;EGYPTIAN HIEROGLYPH-13EEE;Lo;0;L;;;;;N;;;;; +13EEF;EGYPTIAN HIEROGLYPH-13EEF;Lo;0;L;;;;;N;;;;; +13EF0;EGYPTIAN HIEROGLYPH-13EF0;Lo;0;L;;;;;N;;;;; +13EF1;EGYPTIAN HIEROGLYPH-13EF1;Lo;0;L;;;;;N;;;;; +13EF2;EGYPTIAN HIEROGLYPH-13EF2;Lo;0;L;;;;;N;;;;; +13EF3;EGYPTIAN HIEROGLYPH-13EF3;Lo;0;L;;;;;N;;;;; +13EF4;EGYPTIAN HIEROGLYPH-13EF4;Lo;0;L;;;;;N;;;;; +13EF5;EGYPTIAN HIEROGLYPH-13EF5;Lo;0;L;;;;;N;;;;; +13EF6;EGYPTIAN HIEROGLYPH-13EF6;Lo;0;L;;;;;N;;;;; +13EF7;EGYPTIAN HIEROGLYPH-13EF7;Lo;0;L;;;;;N;;;;; +13EF8;EGYPTIAN HIEROGLYPH-13EF8;Lo;0;L;;;;;N;;;;; +13EF9;EGYPTIAN HIEROGLYPH-13EF9;Lo;0;L;;;;;N;;;;; +13EFA;EGYPTIAN HIEROGLYPH-13EFA;Lo;0;L;;;;;N;;;;; +13EFB;EGYPTIAN HIEROGLYPH-13EFB;Lo;0;L;;;;;N;;;;; +13EFC;EGYPTIAN HIEROGLYPH-13EFC;Lo;0;L;;;;;N;;;;; +13EFD;EGYPTIAN HIEROGLYPH-13EFD;Lo;0;L;;;;;N;;;;; +13EFE;EGYPTIAN HIEROGLYPH-13EFE;Lo;0;L;;;;;N;;;;; +13EFF;EGYPTIAN HIEROGLYPH-13EFF;Lo;0;L;;;;;N;;;;; +13F00;EGYPTIAN HIEROGLYPH-13F00;Lo;0;L;;;;;N;;;;; +13F01;EGYPTIAN HIEROGLYPH-13F01;Lo;0;L;;;;;N;;;;; +13F02;EGYPTIAN HIEROGLYPH-13F02;Lo;0;L;;;;;N;;;;; +13F03;EGYPTIAN HIEROGLYPH-13F03;Lo;0;L;;;;;N;;;;; +13F04;EGYPTIAN HIEROGLYPH-13F04;Lo;0;L;;;;;N;;;;; +13F05;EGYPTIAN HIEROGLYPH-13F05;Lo;0;L;;;;;N;;;;; +13F06;EGYPTIAN HIEROGLYPH-13F06;Lo;0;L;;;;;N;;;;; +13F07;EGYPTIAN HIEROGLYPH-13F07;Lo;0;L;;;;;N;;;;; +13F08;EGYPTIAN HIEROGLYPH-13F08;Lo;0;L;;;;;N;;;;; +13F09;EGYPTIAN HIEROGLYPH-13F09;Lo;0;L;;;;;N;;;;; +13F0A;EGYPTIAN HIEROGLYPH-13F0A;Lo;0;L;;;;;N;;;;; +13F0B;EGYPTIAN HIEROGLYPH-13F0B;Lo;0;L;;;;;N;;;;; +13F0C;EGYPTIAN HIEROGLYPH-13F0C;Lo;0;L;;;;;N;;;;; +13F0D;EGYPTIAN HIEROGLYPH-13F0D;Lo;0;L;;;;;N;;;;; +13F0E;EGYPTIAN HIEROGLYPH-13F0E;Lo;0;L;;;;;N;;;;; +13F0F;EGYPTIAN HIEROGLYPH-13F0F;Lo;0;L;;;;;N;;;;; +13F10;EGYPTIAN HIEROGLYPH-13F10;Lo;0;L;;;;;N;;;;; +13F11;EGYPTIAN HIEROGLYPH-13F11;Lo;0;L;;;;;N;;;;; +13F12;EGYPTIAN HIEROGLYPH-13F12;Lo;0;L;;;;;N;;;;; +13F13;EGYPTIAN HIEROGLYPH-13F13;Lo;0;L;;;;;N;;;;; +13F14;EGYPTIAN HIEROGLYPH-13F14;Lo;0;L;;;;;N;;;;; +13F15;EGYPTIAN HIEROGLYPH-13F15;Lo;0;L;;;;;N;;;;; +13F16;EGYPTIAN HIEROGLYPH-13F16;Lo;0;L;;;;;N;;;;; +13F17;EGYPTIAN HIEROGLYPH-13F17;Lo;0;L;;;;;N;;;;; +13F18;EGYPTIAN HIEROGLYPH-13F18;Lo;0;L;;;;;N;;;;; +13F19;EGYPTIAN HIEROGLYPH-13F19;Lo;0;L;;;;;N;;;;; +13F1A;EGYPTIAN HIEROGLYPH-13F1A;Lo;0;L;;;;;N;;;;; +13F1B;EGYPTIAN HIEROGLYPH-13F1B;Lo;0;L;;;;;N;;;;; +13F1C;EGYPTIAN HIEROGLYPH-13F1C;Lo;0;L;;;;;N;;;;; +13F1D;EGYPTIAN HIEROGLYPH-13F1D;Lo;0;L;;;;;N;;;;; +13F1E;EGYPTIAN HIEROGLYPH-13F1E;Lo;0;L;;;;;N;;;;; +13F1F;EGYPTIAN HIEROGLYPH-13F1F;Lo;0;L;;;;;N;;;;; +13F20;EGYPTIAN HIEROGLYPH-13F20;Lo;0;L;;;;;N;;;;; +13F21;EGYPTIAN HIEROGLYPH-13F21;Lo;0;L;;;;;N;;;;; +13F22;EGYPTIAN HIEROGLYPH-13F22;Lo;0;L;;;;;N;;;;; +13F23;EGYPTIAN HIEROGLYPH-13F23;Lo;0;L;;;;;N;;;;; +13F24;EGYPTIAN HIEROGLYPH-13F24;Lo;0;L;;;;;N;;;;; +13F25;EGYPTIAN HIEROGLYPH-13F25;Lo;0;L;;;;;N;;;;; +13F26;EGYPTIAN HIEROGLYPH-13F26;Lo;0;L;;;;;N;;;;; +13F27;EGYPTIAN HIEROGLYPH-13F27;Lo;0;L;;;;;N;;;;; +13F28;EGYPTIAN HIEROGLYPH-13F28;Lo;0;L;;;;;N;;;;; +13F29;EGYPTIAN HIEROGLYPH-13F29;Lo;0;L;;;;;N;;;;; +13F2A;EGYPTIAN HIEROGLYPH-13F2A;Lo;0;L;;;;;N;;;;; +13F2B;EGYPTIAN HIEROGLYPH-13F2B;Lo;0;L;;;;;N;;;;; +13F2C;EGYPTIAN HIEROGLYPH-13F2C;Lo;0;L;;;;;N;;;;; +13F2D;EGYPTIAN HIEROGLYPH-13F2D;Lo;0;L;;;;;N;;;;; +13F2E;EGYPTIAN HIEROGLYPH-13F2E;Lo;0;L;;;;;N;;;;; +13F2F;EGYPTIAN HIEROGLYPH-13F2F;Lo;0;L;;;;;N;;;;; +13F30;EGYPTIAN HIEROGLYPH-13F30;Lo;0;L;;;;;N;;;;; +13F31;EGYPTIAN HIEROGLYPH-13F31;Lo;0;L;;;;;N;;;;; +13F32;EGYPTIAN HIEROGLYPH-13F32;Lo;0;L;;;;;N;;;;; +13F33;EGYPTIAN HIEROGLYPH-13F33;Lo;0;L;;;;;N;;;;; +13F34;EGYPTIAN HIEROGLYPH-13F34;Lo;0;L;;;;;N;;;;; +13F35;EGYPTIAN HIEROGLYPH-13F35;Lo;0;L;;;;;N;;;;; +13F36;EGYPTIAN HIEROGLYPH-13F36;Lo;0;L;;;;;N;;;;; +13F37;EGYPTIAN HIEROGLYPH-13F37;Lo;0;L;;;;;N;;;;; +13F38;EGYPTIAN HIEROGLYPH-13F38;Lo;0;L;;;;;N;;;;; +13F39;EGYPTIAN HIEROGLYPH-13F39;Lo;0;L;;;;;N;;;;; +13F3A;EGYPTIAN HIEROGLYPH-13F3A;Lo;0;L;;;;;N;;;;; +13F3B;EGYPTIAN HIEROGLYPH-13F3B;Lo;0;L;;;;;N;;;;; +13F3C;EGYPTIAN HIEROGLYPH-13F3C;Lo;0;L;;;;;N;;;;; +13F3D;EGYPTIAN HIEROGLYPH-13F3D;Lo;0;L;;;;;N;;;;; +13F3E;EGYPTIAN HIEROGLYPH-13F3E;Lo;0;L;;;;;N;;;;; +13F3F;EGYPTIAN HIEROGLYPH-13F3F;Lo;0;L;;;;;N;;;;; +13F40;EGYPTIAN HIEROGLYPH-13F40;Lo;0;L;;;;;N;;;;; +13F41;EGYPTIAN HIEROGLYPH-13F41;Lo;0;L;;;;;N;;;;; +13F42;EGYPTIAN HIEROGLYPH-13F42;Lo;0;L;;;;;N;;;;; +13F43;EGYPTIAN HIEROGLYPH-13F43;Lo;0;L;;;;;N;;;;; +13F44;EGYPTIAN HIEROGLYPH-13F44;Lo;0;L;;;;;N;;;;; +13F45;EGYPTIAN HIEROGLYPH-13F45;Lo;0;L;;;;;N;;;;; +13F46;EGYPTIAN HIEROGLYPH-13F46;Lo;0;L;;;;;N;;;;; +13F47;EGYPTIAN HIEROGLYPH-13F47;Lo;0;L;;;;;N;;;;; +13F48;EGYPTIAN HIEROGLYPH-13F48;Lo;0;L;;;;;N;;;;; +13F49;EGYPTIAN HIEROGLYPH-13F49;Lo;0;L;;;;;N;;;;; +13F4A;EGYPTIAN HIEROGLYPH-13F4A;Lo;0;L;;;;;N;;;;; +13F4B;EGYPTIAN HIEROGLYPH-13F4B;Lo;0;L;;;;;N;;;;; +13F4C;EGYPTIAN HIEROGLYPH-13F4C;Lo;0;L;;;;;N;;;;; +13F4D;EGYPTIAN HIEROGLYPH-13F4D;Lo;0;L;;;;;N;;;;; +13F4E;EGYPTIAN HIEROGLYPH-13F4E;Lo;0;L;;;;;N;;;;; +13F4F;EGYPTIAN HIEROGLYPH-13F4F;Lo;0;L;;;;;N;;;;; +13F50;EGYPTIAN HIEROGLYPH-13F50;Lo;0;L;;;;;N;;;;; +13F51;EGYPTIAN HIEROGLYPH-13F51;Lo;0;L;;;;;N;;;;; +13F52;EGYPTIAN HIEROGLYPH-13F52;Lo;0;L;;;;;N;;;;; +13F53;EGYPTIAN HIEROGLYPH-13F53;Lo;0;L;;;;;N;;;;; +13F54;EGYPTIAN HIEROGLYPH-13F54;Lo;0;L;;;;;N;;;;; +13F55;EGYPTIAN HIEROGLYPH-13F55;Lo;0;L;;;;;N;;;;; +13F56;EGYPTIAN HIEROGLYPH-13F56;Lo;0;L;;;;;N;;;;; +13F57;EGYPTIAN HIEROGLYPH-13F57;Lo;0;L;;;;;N;;;;; +13F58;EGYPTIAN HIEROGLYPH-13F58;Lo;0;L;;;;;N;;;;; +13F59;EGYPTIAN HIEROGLYPH-13F59;Lo;0;L;;;;;N;;;;; +13F5A;EGYPTIAN HIEROGLYPH-13F5A;Lo;0;L;;;;;N;;;;; +13F5B;EGYPTIAN HIEROGLYPH-13F5B;Lo;0;L;;;;;N;;;;; +13F5C;EGYPTIAN HIEROGLYPH-13F5C;Lo;0;L;;;;;N;;;;; +13F5D;EGYPTIAN HIEROGLYPH-13F5D;Lo;0;L;;;;;N;;;;; +13F5E;EGYPTIAN HIEROGLYPH-13F5E;Lo;0;L;;;;;N;;;;; +13F5F;EGYPTIAN HIEROGLYPH-13F5F;Lo;0;L;;;;;N;;;;; +13F60;EGYPTIAN HIEROGLYPH-13F60;Lo;0;L;;;;;N;;;;; +13F61;EGYPTIAN HIEROGLYPH-13F61;Lo;0;L;;;;;N;;;;; +13F62;EGYPTIAN HIEROGLYPH-13F62;Lo;0;L;;;;;N;;;;; +13F63;EGYPTIAN HIEROGLYPH-13F63;Lo;0;L;;;;;N;;;;; +13F64;EGYPTIAN HIEROGLYPH-13F64;Lo;0;L;;;;;N;;;;; +13F65;EGYPTIAN HIEROGLYPH-13F65;Lo;0;L;;;;;N;;;;; +13F66;EGYPTIAN HIEROGLYPH-13F66;Lo;0;L;;;;;N;;;;; +13F67;EGYPTIAN HIEROGLYPH-13F67;Lo;0;L;;;;;N;;;;; +13F68;EGYPTIAN HIEROGLYPH-13F68;Lo;0;L;;;;;N;;;;; +13F69;EGYPTIAN HIEROGLYPH-13F69;Lo;0;L;;;;;N;;;;; +13F6A;EGYPTIAN HIEROGLYPH-13F6A;Lo;0;L;;;;;N;;;;; +13F6B;EGYPTIAN HIEROGLYPH-13F6B;Lo;0;L;;;;;N;;;;; +13F6C;EGYPTIAN HIEROGLYPH-13F6C;Lo;0;L;;;;;N;;;;; +13F6D;EGYPTIAN HIEROGLYPH-13F6D;Lo;0;L;;;;;N;;;;; +13F6E;EGYPTIAN HIEROGLYPH-13F6E;Lo;0;L;;;;;N;;;;; +13F6F;EGYPTIAN HIEROGLYPH-13F6F;Lo;0;L;;;;;N;;;;; +13F70;EGYPTIAN HIEROGLYPH-13F70;Lo;0;L;;;;;N;;;;; +13F71;EGYPTIAN HIEROGLYPH-13F71;Lo;0;L;;;;;N;;;;; +13F72;EGYPTIAN HIEROGLYPH-13F72;Lo;0;L;;;;;N;;;;; +13F73;EGYPTIAN HIEROGLYPH-13F73;Lo;0;L;;;;;N;;;;; +13F74;EGYPTIAN HIEROGLYPH-13F74;Lo;0;L;;;;;N;;;;; +13F75;EGYPTIAN HIEROGLYPH-13F75;Lo;0;L;;;;;N;;;;; +13F76;EGYPTIAN HIEROGLYPH-13F76;Lo;0;L;;;;;N;;;;; +13F77;EGYPTIAN HIEROGLYPH-13F77;Lo;0;L;;;;;N;;;;; +13F78;EGYPTIAN HIEROGLYPH-13F78;Lo;0;L;;;;;N;;;;; +13F79;EGYPTIAN HIEROGLYPH-13F79;Lo;0;L;;;;;N;;;;; +13F7A;EGYPTIAN HIEROGLYPH-13F7A;Lo;0;L;;;;;N;;;;; +13F7B;EGYPTIAN HIEROGLYPH-13F7B;Lo;0;L;;;;;N;;;;; +13F7C;EGYPTIAN HIEROGLYPH-13F7C;Lo;0;L;;;;;N;;;;; +13F7D;EGYPTIAN HIEROGLYPH-13F7D;Lo;0;L;;;;;N;;;;; +13F7E;EGYPTIAN HIEROGLYPH-13F7E;Lo;0;L;;;;;N;;;;; +13F7F;EGYPTIAN HIEROGLYPH-13F7F;Lo;0;L;;;;;N;;;;; +13F80;EGYPTIAN HIEROGLYPH-13F80;Lo;0;L;;;;;N;;;;; +13F81;EGYPTIAN HIEROGLYPH-13F81;Lo;0;L;;;;;N;;;;; +13F82;EGYPTIAN HIEROGLYPH-13F82;Lo;0;L;;;;;N;;;;; +13F83;EGYPTIAN HIEROGLYPH-13F83;Lo;0;L;;;;;N;;;;; +13F84;EGYPTIAN HIEROGLYPH-13F84;Lo;0;L;;;;;N;;;;; +13F85;EGYPTIAN HIEROGLYPH-13F85;Lo;0;L;;;;;N;;;;; +13F86;EGYPTIAN HIEROGLYPH-13F86;Lo;0;L;;;;;N;;;;; +13F87;EGYPTIAN HIEROGLYPH-13F87;Lo;0;L;;;;;N;;;;; +13F88;EGYPTIAN HIEROGLYPH-13F88;Lo;0;L;;;;;N;;;;; +13F89;EGYPTIAN HIEROGLYPH-13F89;Lo;0;L;;;;;N;;;;; +13F8A;EGYPTIAN HIEROGLYPH-13F8A;Lo;0;L;;;;;N;;;;; +13F8B;EGYPTIAN HIEROGLYPH-13F8B;Lo;0;L;;;;;N;;;;; +13F8C;EGYPTIAN HIEROGLYPH-13F8C;Lo;0;L;;;;;N;;;;; +13F8D;EGYPTIAN HIEROGLYPH-13F8D;Lo;0;L;;;;;N;;;;; +13F8E;EGYPTIAN HIEROGLYPH-13F8E;Lo;0;L;;;;;N;;;;; +13F8F;EGYPTIAN HIEROGLYPH-13F8F;Lo;0;L;;;;;N;;;;; +13F90;EGYPTIAN HIEROGLYPH-13F90;Lo;0;L;;;;;N;;;;; +13F91;EGYPTIAN HIEROGLYPH-13F91;Lo;0;L;;;;;N;;;;; +13F92;EGYPTIAN HIEROGLYPH-13F92;Lo;0;L;;;;;N;;;;; +13F93;EGYPTIAN HIEROGLYPH-13F93;Lo;0;L;;;;;N;;;;; +13F94;EGYPTIAN HIEROGLYPH-13F94;Lo;0;L;;;;;N;;;;; +13F95;EGYPTIAN HIEROGLYPH-13F95;Lo;0;L;;;;;N;;;;; +13F96;EGYPTIAN HIEROGLYPH-13F96;Lo;0;L;;;;;N;;;;; +13F97;EGYPTIAN HIEROGLYPH-13F97;Lo;0;L;;;;;N;;;;; +13F98;EGYPTIAN HIEROGLYPH-13F98;Lo;0;L;;;;;N;;;;; +13F99;EGYPTIAN HIEROGLYPH-13F99;Lo;0;L;;;;;N;;;;; +13F9A;EGYPTIAN HIEROGLYPH-13F9A;Lo;0;L;;;;;N;;;;; +13F9B;EGYPTIAN HIEROGLYPH-13F9B;Lo;0;L;;;;;N;;;;; +13F9C;EGYPTIAN HIEROGLYPH-13F9C;Lo;0;L;;;;;N;;;;; +13F9D;EGYPTIAN HIEROGLYPH-13F9D;Lo;0;L;;;;;N;;;;; +13F9E;EGYPTIAN HIEROGLYPH-13F9E;Lo;0;L;;;;;N;;;;; +13F9F;EGYPTIAN HIEROGLYPH-13F9F;Lo;0;L;;;;;N;;;;; +13FA0;EGYPTIAN HIEROGLYPH-13FA0;Lo;0;L;;;;;N;;;;; +13FA1;EGYPTIAN HIEROGLYPH-13FA1;Lo;0;L;;;;;N;;;;; +13FA2;EGYPTIAN HIEROGLYPH-13FA2;Lo;0;L;;;;;N;;;;; +13FA3;EGYPTIAN HIEROGLYPH-13FA3;Lo;0;L;;;;;N;;;;; +13FA4;EGYPTIAN HIEROGLYPH-13FA4;Lo;0;L;;;;;N;;;;; +13FA5;EGYPTIAN HIEROGLYPH-13FA5;Lo;0;L;;;;;N;;;;; +13FA6;EGYPTIAN HIEROGLYPH-13FA6;Lo;0;L;;;;;N;;;;; +13FA7;EGYPTIAN HIEROGLYPH-13FA7;Lo;0;L;;;;;N;;;;; +13FA8;EGYPTIAN HIEROGLYPH-13FA8;Lo;0;L;;;;;N;;;;; +13FA9;EGYPTIAN HIEROGLYPH-13FA9;Lo;0;L;;;;;N;;;;; +13FAA;EGYPTIAN HIEROGLYPH-13FAA;Lo;0;L;;;;;N;;;;; +13FAB;EGYPTIAN HIEROGLYPH-13FAB;Lo;0;L;;;;;N;;;;; +13FAC;EGYPTIAN HIEROGLYPH-13FAC;Lo;0;L;;;;;N;;;;; +13FAD;EGYPTIAN HIEROGLYPH-13FAD;Lo;0;L;;;;;N;;;;; +13FAE;EGYPTIAN HIEROGLYPH-13FAE;Lo;0;L;;;;;N;;;;; +13FAF;EGYPTIAN HIEROGLYPH-13FAF;Lo;0;L;;;;;N;;;;; +13FB0;EGYPTIAN HIEROGLYPH-13FB0;Lo;0;L;;;;;N;;;;; +13FB1;EGYPTIAN HIEROGLYPH-13FB1;Lo;0;L;;;;;N;;;;; +13FB2;EGYPTIAN HIEROGLYPH-13FB2;Lo;0;L;;;;;N;;;;; +13FB3;EGYPTIAN HIEROGLYPH-13FB3;Lo;0;L;;;;;N;;;;; +13FB4;EGYPTIAN HIEROGLYPH-13FB4;Lo;0;L;;;;;N;;;;; +13FB5;EGYPTIAN HIEROGLYPH-13FB5;Lo;0;L;;;;;N;;;;; +13FB6;EGYPTIAN HIEROGLYPH-13FB6;Lo;0;L;;;;;N;;;;; +13FB7;EGYPTIAN HIEROGLYPH-13FB7;Lo;0;L;;;;;N;;;;; +13FB8;EGYPTIAN HIEROGLYPH-13FB8;Lo;0;L;;;;;N;;;;; +13FB9;EGYPTIAN HIEROGLYPH-13FB9;Lo;0;L;;;;;N;;;;; +13FBA;EGYPTIAN HIEROGLYPH-13FBA;Lo;0;L;;;;;N;;;;; +13FBB;EGYPTIAN HIEROGLYPH-13FBB;Lo;0;L;;;;;N;;;;; +13FBC;EGYPTIAN HIEROGLYPH-13FBC;Lo;0;L;;;;;N;;;;; +13FBD;EGYPTIAN HIEROGLYPH-13FBD;Lo;0;L;;;;;N;;;;; +13FBE;EGYPTIAN HIEROGLYPH-13FBE;Lo;0;L;;;;;N;;;;; +13FBF;EGYPTIAN HIEROGLYPH-13FBF;Lo;0;L;;;;;N;;;;; +13FC0;EGYPTIAN HIEROGLYPH-13FC0;Lo;0;L;;;;;N;;;;; +13FC1;EGYPTIAN HIEROGLYPH-13FC1;Lo;0;L;;;;;N;;;;; +13FC2;EGYPTIAN HIEROGLYPH-13FC2;Lo;0;L;;;;;N;;;;; +13FC3;EGYPTIAN HIEROGLYPH-13FC3;Lo;0;L;;;;;N;;;;; +13FC4;EGYPTIAN HIEROGLYPH-13FC4;Lo;0;L;;;;;N;;;;; +13FC5;EGYPTIAN HIEROGLYPH-13FC5;Lo;0;L;;;;;N;;;;; +13FC6;EGYPTIAN HIEROGLYPH-13FC6;Lo;0;L;;;;;N;;;;; +13FC7;EGYPTIAN HIEROGLYPH-13FC7;Lo;0;L;;;;;N;;;;; +13FC8;EGYPTIAN HIEROGLYPH-13FC8;Lo;0;L;;;;;N;;;;; +13FC9;EGYPTIAN HIEROGLYPH-13FC9;Lo;0;L;;;;;N;;;;; +13FCA;EGYPTIAN HIEROGLYPH-13FCA;Lo;0;L;;;;;N;;;;; +13FCB;EGYPTIAN HIEROGLYPH-13FCB;Lo;0;L;;;;;N;;;;; +13FCC;EGYPTIAN HIEROGLYPH-13FCC;Lo;0;L;;;;;N;;;;; +13FCD;EGYPTIAN HIEROGLYPH-13FCD;Lo;0;L;;;;;N;;;;; +13FCE;EGYPTIAN HIEROGLYPH-13FCE;Lo;0;L;;;;;N;;;;; +13FCF;EGYPTIAN HIEROGLYPH-13FCF;Lo;0;L;;;;;N;;;;; +13FD0;EGYPTIAN HIEROGLYPH-13FD0;Lo;0;L;;;;;N;;;;; +13FD1;EGYPTIAN HIEROGLYPH-13FD1;Lo;0;L;;;;;N;;;;; +13FD2;EGYPTIAN HIEROGLYPH-13FD2;Lo;0;L;;;;;N;;;;; +13FD3;EGYPTIAN HIEROGLYPH-13FD3;Lo;0;L;;;;;N;;;;; +13FD4;EGYPTIAN HIEROGLYPH-13FD4;Lo;0;L;;;;;N;;;;; +13FD5;EGYPTIAN HIEROGLYPH-13FD5;Lo;0;L;;;;;N;;;;; +13FD6;EGYPTIAN HIEROGLYPH-13FD6;Lo;0;L;;;;;N;;;;; +13FD7;EGYPTIAN HIEROGLYPH-13FD7;Lo;0;L;;;;;N;;;;; +13FD8;EGYPTIAN HIEROGLYPH-13FD8;Lo;0;L;;;;;N;;;;; +13FD9;EGYPTIAN HIEROGLYPH-13FD9;Lo;0;L;;;;;N;;;;; +13FDA;EGYPTIAN HIEROGLYPH-13FDA;Lo;0;L;;;;;N;;;;; +13FDB;EGYPTIAN HIEROGLYPH-13FDB;Lo;0;L;;;;;N;;;;; +13FDC;EGYPTIAN HIEROGLYPH-13FDC;Lo;0;L;;;;;N;;;;; +13FDD;EGYPTIAN HIEROGLYPH-13FDD;Lo;0;L;;;;;N;;;;; +13FDE;EGYPTIAN HIEROGLYPH-13FDE;Lo;0;L;;;;;N;;;;; +13FDF;EGYPTIAN HIEROGLYPH-13FDF;Lo;0;L;;;;;N;;;;; +13FE0;EGYPTIAN HIEROGLYPH-13FE0;Lo;0;L;;;;;N;;;;; +13FE1;EGYPTIAN HIEROGLYPH-13FE1;Lo;0;L;;;;;N;;;;; +13FE2;EGYPTIAN HIEROGLYPH-13FE2;Lo;0;L;;;;;N;;;;; +13FE3;EGYPTIAN HIEROGLYPH-13FE3;Lo;0;L;;;;;N;;;;; +13FE4;EGYPTIAN HIEROGLYPH-13FE4;Lo;0;L;;;;;N;;;;; +13FE5;EGYPTIAN HIEROGLYPH-13FE5;Lo;0;L;;;;;N;;;;; +13FE6;EGYPTIAN HIEROGLYPH-13FE6;Lo;0;L;;;;;N;;;;; +13FE7;EGYPTIAN HIEROGLYPH-13FE7;Lo;0;L;;;;;N;;;;; +13FE8;EGYPTIAN HIEROGLYPH-13FE8;Lo;0;L;;;;;N;;;;; +13FE9;EGYPTIAN HIEROGLYPH-13FE9;Lo;0;L;;;;;N;;;;; +13FEA;EGYPTIAN HIEROGLYPH-13FEA;Lo;0;L;;;;;N;;;;; +13FEB;EGYPTIAN HIEROGLYPH-13FEB;Lo;0;L;;;;;N;;;;; +13FEC;EGYPTIAN HIEROGLYPH-13FEC;Lo;0;L;;;;;N;;;;; +13FED;EGYPTIAN HIEROGLYPH-13FED;Lo;0;L;;;;;N;;;;; +13FEE;EGYPTIAN HIEROGLYPH-13FEE;Lo;0;L;;;;;N;;;;; +13FEF;EGYPTIAN HIEROGLYPH-13FEF;Lo;0;L;;;;;N;;;;; +13FF0;EGYPTIAN HIEROGLYPH-13FF0;Lo;0;L;;;;;N;;;;; +13FF1;EGYPTIAN HIEROGLYPH-13FF1;Lo;0;L;;;;;N;;;;; +13FF2;EGYPTIAN HIEROGLYPH-13FF2;Lo;0;L;;;;;N;;;;; +13FF3;EGYPTIAN HIEROGLYPH-13FF3;Lo;0;L;;;;;N;;;;; +13FF4;EGYPTIAN HIEROGLYPH-13FF4;Lo;0;L;;;;;N;;;;; +13FF5;EGYPTIAN HIEROGLYPH-13FF5;Lo;0;L;;;;;N;;;;; +13FF6;EGYPTIAN HIEROGLYPH-13FF6;Lo;0;L;;;;;N;;;;; +13FF7;EGYPTIAN HIEROGLYPH-13FF7;Lo;0;L;;;;;N;;;;; +13FF8;EGYPTIAN HIEROGLYPH-13FF8;Lo;0;L;;;;;N;;;;; +13FF9;EGYPTIAN HIEROGLYPH-13FF9;Lo;0;L;;;;;N;;;;; +13FFA;EGYPTIAN HIEROGLYPH-13FFA;Lo;0;L;;;;;N;;;;; +13FFB;EGYPTIAN HIEROGLYPH-13FFB;Lo;0;L;;;;;N;;;;; +13FFC;EGYPTIAN HIEROGLYPH-13FFC;Lo;0;L;;;;;N;;;;; +13FFD;EGYPTIAN HIEROGLYPH-13FFD;Lo;0;L;;;;;N;;;;; +13FFE;EGYPTIAN HIEROGLYPH-13FFE;Lo;0;L;;;;;N;;;;; +13FFF;EGYPTIAN HIEROGLYPH-13FFF;Lo;0;L;;;;;N;;;;; +14000;EGYPTIAN HIEROGLYPH-14000;Lo;0;L;;;;;N;;;;; +14001;EGYPTIAN HIEROGLYPH-14001;Lo;0;L;;;;;N;;;;; +14002;EGYPTIAN HIEROGLYPH-14002;Lo;0;L;;;;;N;;;;; +14003;EGYPTIAN HIEROGLYPH-14003;Lo;0;L;;;;;N;;;;; +14004;EGYPTIAN HIEROGLYPH-14004;Lo;0;L;;;;;N;;;;; +14005;EGYPTIAN HIEROGLYPH-14005;Lo;0;L;;;;;N;;;;; +14006;EGYPTIAN HIEROGLYPH-14006;Lo;0;L;;;;;N;;;;; +14007;EGYPTIAN HIEROGLYPH-14007;Lo;0;L;;;;;N;;;;; +14008;EGYPTIAN HIEROGLYPH-14008;Lo;0;L;;;;;N;;;;; +14009;EGYPTIAN HIEROGLYPH-14009;Lo;0;L;;;;;N;;;;; +1400A;EGYPTIAN HIEROGLYPH-1400A;Lo;0;L;;;;;N;;;;; +1400B;EGYPTIAN HIEROGLYPH-1400B;Lo;0;L;;;;;N;;;;; +1400C;EGYPTIAN HIEROGLYPH-1400C;Lo;0;L;;;;;N;;;;; +1400D;EGYPTIAN HIEROGLYPH-1400D;Lo;0;L;;;;;N;;;;; +1400E;EGYPTIAN HIEROGLYPH-1400E;Lo;0;L;;;;;N;;;;; +1400F;EGYPTIAN HIEROGLYPH-1400F;Lo;0;L;;;;;N;;;;; +14010;EGYPTIAN HIEROGLYPH-14010;Lo;0;L;;;;;N;;;;; +14011;EGYPTIAN HIEROGLYPH-14011;Lo;0;L;;;;;N;;;;; +14012;EGYPTIAN HIEROGLYPH-14012;Lo;0;L;;;;;N;;;;; +14013;EGYPTIAN HIEROGLYPH-14013;Lo;0;L;;;;;N;;;;; +14014;EGYPTIAN HIEROGLYPH-14014;Lo;0;L;;;;;N;;;;; +14015;EGYPTIAN HIEROGLYPH-14015;Lo;0;L;;;;;N;;;;; +14016;EGYPTIAN HIEROGLYPH-14016;Lo;0;L;;;;;N;;;;; +14017;EGYPTIAN HIEROGLYPH-14017;Lo;0;L;;;;;N;;;;; +14018;EGYPTIAN HIEROGLYPH-14018;Lo;0;L;;;;;N;;;;; +14019;EGYPTIAN HIEROGLYPH-14019;Lo;0;L;;;;;N;;;;; +1401A;EGYPTIAN HIEROGLYPH-1401A;Lo;0;L;;;;;N;;;;; +1401B;EGYPTIAN HIEROGLYPH-1401B;Lo;0;L;;;;;N;;;;; +1401C;EGYPTIAN HIEROGLYPH-1401C;Lo;0;L;;;;;N;;;;; +1401D;EGYPTIAN HIEROGLYPH-1401D;Lo;0;L;;;;;N;;;;; +1401E;EGYPTIAN HIEROGLYPH-1401E;Lo;0;L;;;;;N;;;;; +1401F;EGYPTIAN HIEROGLYPH-1401F;Lo;0;L;;;;;N;;;;; +14020;EGYPTIAN HIEROGLYPH-14020;Lo;0;L;;;;;N;;;;; +14021;EGYPTIAN HIEROGLYPH-14021;Lo;0;L;;;;;N;;;;; +14022;EGYPTIAN HIEROGLYPH-14022;Lo;0;L;;;;;N;;;;; +14023;EGYPTIAN HIEROGLYPH-14023;Lo;0;L;;;;;N;;;;; +14024;EGYPTIAN HIEROGLYPH-14024;Lo;0;L;;;;;N;;;;; +14025;EGYPTIAN HIEROGLYPH-14025;Lo;0;L;;;;;N;;;;; +14026;EGYPTIAN HIEROGLYPH-14026;Lo;0;L;;;;;N;;;;; +14027;EGYPTIAN HIEROGLYPH-14027;Lo;0;L;;;;;N;;;;; +14028;EGYPTIAN HIEROGLYPH-14028;Lo;0;L;;;;;N;;;;; +14029;EGYPTIAN HIEROGLYPH-14029;Lo;0;L;;;;;N;;;;; +1402A;EGYPTIAN HIEROGLYPH-1402A;Lo;0;L;;;;;N;;;;; +1402B;EGYPTIAN HIEROGLYPH-1402B;Lo;0;L;;;;;N;;;;; +1402C;EGYPTIAN HIEROGLYPH-1402C;Lo;0;L;;;;;N;;;;; +1402D;EGYPTIAN HIEROGLYPH-1402D;Lo;0;L;;;;;N;;;;; +1402E;EGYPTIAN HIEROGLYPH-1402E;Lo;0;L;;;;;N;;;;; +1402F;EGYPTIAN HIEROGLYPH-1402F;Lo;0;L;;;;;N;;;;; +14030;EGYPTIAN HIEROGLYPH-14030;Lo;0;L;;;;;N;;;;; +14031;EGYPTIAN HIEROGLYPH-14031;Lo;0;L;;;;;N;;;;; +14032;EGYPTIAN HIEROGLYPH-14032;Lo;0;L;;;;;N;;;;; +14033;EGYPTIAN HIEROGLYPH-14033;Lo;0;L;;;;;N;;;;; +14034;EGYPTIAN HIEROGLYPH-14034;Lo;0;L;;;;;N;;;;; +14035;EGYPTIAN HIEROGLYPH-14035;Lo;0;L;;;;;N;;;;; +14036;EGYPTIAN HIEROGLYPH-14036;Lo;0;L;;;;;N;;;;; +14037;EGYPTIAN HIEROGLYPH-14037;Lo;0;L;;;;;N;;;;; +14038;EGYPTIAN HIEROGLYPH-14038;Lo;0;L;;;;;N;;;;; +14039;EGYPTIAN HIEROGLYPH-14039;Lo;0;L;;;;;N;;;;; +1403A;EGYPTIAN HIEROGLYPH-1403A;Lo;0;L;;;;;N;;;;; +1403B;EGYPTIAN HIEROGLYPH-1403B;Lo;0;L;;;;;N;;;;; +1403C;EGYPTIAN HIEROGLYPH-1403C;Lo;0;L;;;;;N;;;;; +1403D;EGYPTIAN HIEROGLYPH-1403D;Lo;0;L;;;;;N;;;;; +1403E;EGYPTIAN HIEROGLYPH-1403E;Lo;0;L;;;;;N;;;;; +1403F;EGYPTIAN HIEROGLYPH-1403F;Lo;0;L;;;;;N;;;;; +14040;EGYPTIAN HIEROGLYPH-14040;Lo;0;L;;;;;N;;;;; +14041;EGYPTIAN HIEROGLYPH-14041;Lo;0;L;;;;;N;;;;; +14042;EGYPTIAN HIEROGLYPH-14042;Lo;0;L;;;;;N;;;;; +14043;EGYPTIAN HIEROGLYPH-14043;Lo;0;L;;;;;N;;;;; +14044;EGYPTIAN HIEROGLYPH-14044;Lo;0;L;;;;;N;;;;; +14045;EGYPTIAN HIEROGLYPH-14045;Lo;0;L;;;;;N;;;;; +14046;EGYPTIAN HIEROGLYPH-14046;Lo;0;L;;;;;N;;;;; +14047;EGYPTIAN HIEROGLYPH-14047;Lo;0;L;;;;;N;;;;; +14048;EGYPTIAN HIEROGLYPH-14048;Lo;0;L;;;;;N;;;;; +14049;EGYPTIAN HIEROGLYPH-14049;Lo;0;L;;;;;N;;;;; +1404A;EGYPTIAN HIEROGLYPH-1404A;Lo;0;L;;;;;N;;;;; +1404B;EGYPTIAN HIEROGLYPH-1404B;Lo;0;L;;;;;N;;;;; +1404C;EGYPTIAN HIEROGLYPH-1404C;Lo;0;L;;;;;N;;;;; +1404D;EGYPTIAN HIEROGLYPH-1404D;Lo;0;L;;;;;N;;;;; +1404E;EGYPTIAN HIEROGLYPH-1404E;Lo;0;L;;;;;N;;;;; +1404F;EGYPTIAN HIEROGLYPH-1404F;Lo;0;L;;;;;N;;;;; +14050;EGYPTIAN HIEROGLYPH-14050;Lo;0;L;;;;;N;;;;; +14051;EGYPTIAN HIEROGLYPH-14051;Lo;0;L;;;;;N;;;;; +14052;EGYPTIAN HIEROGLYPH-14052;Lo;0;L;;;;;N;;;;; +14053;EGYPTIAN HIEROGLYPH-14053;Lo;0;L;;;;;N;;;;; +14054;EGYPTIAN HIEROGLYPH-14054;Lo;0;L;;;;;N;;;;; +14055;EGYPTIAN HIEROGLYPH-14055;Lo;0;L;;;;;N;;;;; +14056;EGYPTIAN HIEROGLYPH-14056;Lo;0;L;;;;;N;;;;; +14057;EGYPTIAN HIEROGLYPH-14057;Lo;0;L;;;;;N;;;;; +14058;EGYPTIAN HIEROGLYPH-14058;Lo;0;L;;;;;N;;;;; +14059;EGYPTIAN HIEROGLYPH-14059;Lo;0;L;;;;;N;;;;; +1405A;EGYPTIAN HIEROGLYPH-1405A;Lo;0;L;;;;;N;;;;; +1405B;EGYPTIAN HIEROGLYPH-1405B;Lo;0;L;;;;;N;;;;; +1405C;EGYPTIAN HIEROGLYPH-1405C;Lo;0;L;;;;;N;;;;; +1405D;EGYPTIAN HIEROGLYPH-1405D;Lo;0;L;;;;;N;;;;; +1405E;EGYPTIAN HIEROGLYPH-1405E;Lo;0;L;;;;;N;;;;; +1405F;EGYPTIAN HIEROGLYPH-1405F;Lo;0;L;;;;;N;;;;; +14060;EGYPTIAN HIEROGLYPH-14060;Lo;0;L;;;;;N;;;;; +14061;EGYPTIAN HIEROGLYPH-14061;Lo;0;L;;;;;N;;;;; +14062;EGYPTIAN HIEROGLYPH-14062;Lo;0;L;;;;;N;;;;; +14063;EGYPTIAN HIEROGLYPH-14063;Lo;0;L;;;;;N;;;;; +14064;EGYPTIAN HIEROGLYPH-14064;Lo;0;L;;;;;N;;;;; +14065;EGYPTIAN HIEROGLYPH-14065;Lo;0;L;;;;;N;;;;; +14066;EGYPTIAN HIEROGLYPH-14066;Lo;0;L;;;;;N;;;;; +14067;EGYPTIAN HIEROGLYPH-14067;Lo;0;L;;;;;N;;;;; +14068;EGYPTIAN HIEROGLYPH-14068;Lo;0;L;;;;;N;;;;; +14069;EGYPTIAN HIEROGLYPH-14069;Lo;0;L;;;;;N;;;;; +1406A;EGYPTIAN HIEROGLYPH-1406A;Lo;0;L;;;;;N;;;;; +1406B;EGYPTIAN HIEROGLYPH-1406B;Lo;0;L;;;;;N;;;;; +1406C;EGYPTIAN HIEROGLYPH-1406C;Lo;0;L;;;;;N;;;;; +1406D;EGYPTIAN HIEROGLYPH-1406D;Lo;0;L;;;;;N;;;;; +1406E;EGYPTIAN HIEROGLYPH-1406E;Lo;0;L;;;;;N;;;;; +1406F;EGYPTIAN HIEROGLYPH-1406F;Lo;0;L;;;;;N;;;;; +14070;EGYPTIAN HIEROGLYPH-14070;Lo;0;L;;;;;N;;;;; +14071;EGYPTIAN HIEROGLYPH-14071;Lo;0;L;;;;;N;;;;; +14072;EGYPTIAN HIEROGLYPH-14072;Lo;0;L;;;;;N;;;;; +14073;EGYPTIAN HIEROGLYPH-14073;Lo;0;L;;;;;N;;;;; +14074;EGYPTIAN HIEROGLYPH-14074;Lo;0;L;;;;;N;;;;; +14075;EGYPTIAN HIEROGLYPH-14075;Lo;0;L;;;;;N;;;;; +14076;EGYPTIAN HIEROGLYPH-14076;Lo;0;L;;;;;N;;;;; +14077;EGYPTIAN HIEROGLYPH-14077;Lo;0;L;;;;;N;;;;; +14078;EGYPTIAN HIEROGLYPH-14078;Lo;0;L;;;;;N;;;;; +14079;EGYPTIAN HIEROGLYPH-14079;Lo;0;L;;;;;N;;;;; +1407A;EGYPTIAN HIEROGLYPH-1407A;Lo;0;L;;;;;N;;;;; +1407B;EGYPTIAN HIEROGLYPH-1407B;Lo;0;L;;;;;N;;;;; +1407C;EGYPTIAN HIEROGLYPH-1407C;Lo;0;L;;;;;N;;;;; +1407D;EGYPTIAN HIEROGLYPH-1407D;Lo;0;L;;;;;N;;;;; +1407E;EGYPTIAN HIEROGLYPH-1407E;Lo;0;L;;;;;N;;;;; +1407F;EGYPTIAN HIEROGLYPH-1407F;Lo;0;L;;;;;N;;;;; +14080;EGYPTIAN HIEROGLYPH-14080;Lo;0;L;;;;;N;;;;; +14081;EGYPTIAN HIEROGLYPH-14081;Lo;0;L;;;;;N;;;;; +14082;EGYPTIAN HIEROGLYPH-14082;Lo;0;L;;;;;N;;;;; +14083;EGYPTIAN HIEROGLYPH-14083;Lo;0;L;;;;;N;;;;; +14084;EGYPTIAN HIEROGLYPH-14084;Lo;0;L;;;;;N;;;;; +14085;EGYPTIAN HIEROGLYPH-14085;Lo;0;L;;;;;N;;;;; +14086;EGYPTIAN HIEROGLYPH-14086;Lo;0;L;;;;;N;;;;; +14087;EGYPTIAN HIEROGLYPH-14087;Lo;0;L;;;;;N;;;;; +14088;EGYPTIAN HIEROGLYPH-14088;Lo;0;L;;;;;N;;;;; +14089;EGYPTIAN HIEROGLYPH-14089;Lo;0;L;;;;;N;;;;; +1408A;EGYPTIAN HIEROGLYPH-1408A;Lo;0;L;;;;;N;;;;; +1408B;EGYPTIAN HIEROGLYPH-1408B;Lo;0;L;;;;;N;;;;; +1408C;EGYPTIAN HIEROGLYPH-1408C;Lo;0;L;;;;;N;;;;; +1408D;EGYPTIAN HIEROGLYPH-1408D;Lo;0;L;;;;;N;;;;; +1408E;EGYPTIAN HIEROGLYPH-1408E;Lo;0;L;;;;;N;;;;; +1408F;EGYPTIAN HIEROGLYPH-1408F;Lo;0;L;;;;;N;;;;; +14090;EGYPTIAN HIEROGLYPH-14090;Lo;0;L;;;;;N;;;;; +14091;EGYPTIAN HIEROGLYPH-14091;Lo;0;L;;;;;N;;;;; +14092;EGYPTIAN HIEROGLYPH-14092;Lo;0;L;;;;;N;;;;; +14093;EGYPTIAN HIEROGLYPH-14093;Lo;0;L;;;;;N;;;;; +14094;EGYPTIAN HIEROGLYPH-14094;Lo;0;L;;;;;N;;;;; +14095;EGYPTIAN HIEROGLYPH-14095;Lo;0;L;;;;;N;;;;; +14096;EGYPTIAN HIEROGLYPH-14096;Lo;0;L;;;;;N;;;;; +14097;EGYPTIAN HIEROGLYPH-14097;Lo;0;L;;;;;N;;;;; +14098;EGYPTIAN HIEROGLYPH-14098;Lo;0;L;;;;;N;;;;; +14099;EGYPTIAN HIEROGLYPH-14099;Lo;0;L;;;;;N;;;;; +1409A;EGYPTIAN HIEROGLYPH-1409A;Lo;0;L;;;;;N;;;;; +1409B;EGYPTIAN HIEROGLYPH-1409B;Lo;0;L;;;;;N;;;;; +1409C;EGYPTIAN HIEROGLYPH-1409C;Lo;0;L;;;;;N;;;;; +1409D;EGYPTIAN HIEROGLYPH-1409D;Lo;0;L;;;;;N;;;;; +1409E;EGYPTIAN HIEROGLYPH-1409E;Lo;0;L;;;;;N;;;;; +1409F;EGYPTIAN HIEROGLYPH-1409F;Lo;0;L;;;;;N;;;;; +140A0;EGYPTIAN HIEROGLYPH-140A0;Lo;0;L;;;;;N;;;;; +140A1;EGYPTIAN HIEROGLYPH-140A1;Lo;0;L;;;;;N;;;;; +140A2;EGYPTIAN HIEROGLYPH-140A2;Lo;0;L;;;;;N;;;;; +140A3;EGYPTIAN HIEROGLYPH-140A3;Lo;0;L;;;;;N;;;;; +140A4;EGYPTIAN HIEROGLYPH-140A4;Lo;0;L;;;;;N;;;;; +140A5;EGYPTIAN HIEROGLYPH-140A5;Lo;0;L;;;;;N;;;;; +140A6;EGYPTIAN HIEROGLYPH-140A6;Lo;0;L;;;;;N;;;;; +140A7;EGYPTIAN HIEROGLYPH-140A7;Lo;0;L;;;;;N;;;;; +140A8;EGYPTIAN HIEROGLYPH-140A8;Lo;0;L;;;;;N;;;;; +140A9;EGYPTIAN HIEROGLYPH-140A9;Lo;0;L;;;;;N;;;;; +140AA;EGYPTIAN HIEROGLYPH-140AA;Lo;0;L;;;;;N;;;;; +140AB;EGYPTIAN HIEROGLYPH-140AB;Lo;0;L;;;;;N;;;;; +140AC;EGYPTIAN HIEROGLYPH-140AC;Lo;0;L;;;;;N;;;;; +140AD;EGYPTIAN HIEROGLYPH-140AD;Lo;0;L;;;;;N;;;;; +140AE;EGYPTIAN HIEROGLYPH-140AE;Lo;0;L;;;;;N;;;;; +140AF;EGYPTIAN HIEROGLYPH-140AF;Lo;0;L;;;;;N;;;;; +140B0;EGYPTIAN HIEROGLYPH-140B0;Lo;0;L;;;;;N;;;;; +140B1;EGYPTIAN HIEROGLYPH-140B1;Lo;0;L;;;;;N;;;;; +140B2;EGYPTIAN HIEROGLYPH-140B2;Lo;0;L;;;;;N;;;;; +140B3;EGYPTIAN HIEROGLYPH-140B3;Lo;0;L;;;;;N;;;;; +140B4;EGYPTIAN HIEROGLYPH-140B4;Lo;0;L;;;;;N;;;;; +140B5;EGYPTIAN HIEROGLYPH-140B5;Lo;0;L;;;;;N;;;;; +140B6;EGYPTIAN HIEROGLYPH-140B6;Lo;0;L;;;;;N;;;;; +140B7;EGYPTIAN HIEROGLYPH-140B7;Lo;0;L;;;;;N;;;;; +140B8;EGYPTIAN HIEROGLYPH-140B8;Lo;0;L;;;;;N;;;;; +140B9;EGYPTIAN HIEROGLYPH-140B9;Lo;0;L;;;;;N;;;;; +140BA;EGYPTIAN HIEROGLYPH-140BA;Lo;0;L;;;;;N;;;;; +140BB;EGYPTIAN HIEROGLYPH-140BB;Lo;0;L;;;;;N;;;;; +140BC;EGYPTIAN HIEROGLYPH-140BC;Lo;0;L;;;;;N;;;;; +140BD;EGYPTIAN HIEROGLYPH-140BD;Lo;0;L;;;;;N;;;;; +140BE;EGYPTIAN HIEROGLYPH-140BE;Lo;0;L;;;;;N;;;;; +140BF;EGYPTIAN HIEROGLYPH-140BF;Lo;0;L;;;;;N;;;;; +140C0;EGYPTIAN HIEROGLYPH-140C0;Lo;0;L;;;;;N;;;;; +140C1;EGYPTIAN HIEROGLYPH-140C1;Lo;0;L;;;;;N;;;;; +140C2;EGYPTIAN HIEROGLYPH-140C2;Lo;0;L;;;;;N;;;;; +140C3;EGYPTIAN HIEROGLYPH-140C3;Lo;0;L;;;;;N;;;;; +140C4;EGYPTIAN HIEROGLYPH-140C4;Lo;0;L;;;;;N;;;;; +140C5;EGYPTIAN HIEROGLYPH-140C5;Lo;0;L;;;;;N;;;;; +140C6;EGYPTIAN HIEROGLYPH-140C6;Lo;0;L;;;;;N;;;;; +140C7;EGYPTIAN HIEROGLYPH-140C7;Lo;0;L;;;;;N;;;;; +140C8;EGYPTIAN HIEROGLYPH-140C8;Lo;0;L;;;;;N;;;;; +140C9;EGYPTIAN HIEROGLYPH-140C9;Lo;0;L;;;;;N;;;;; +140CA;EGYPTIAN HIEROGLYPH-140CA;Lo;0;L;;;;;N;;;;; +140CB;EGYPTIAN HIEROGLYPH-140CB;Lo;0;L;;;;;N;;;;; +140CC;EGYPTIAN HIEROGLYPH-140CC;Lo;0;L;;;;;N;;;;; +140CD;EGYPTIAN HIEROGLYPH-140CD;Lo;0;L;;;;;N;;;;; +140CE;EGYPTIAN HIEROGLYPH-140CE;Lo;0;L;;;;;N;;;;; +140CF;EGYPTIAN HIEROGLYPH-140CF;Lo;0;L;;;;;N;;;;; +140D0;EGYPTIAN HIEROGLYPH-140D0;Lo;0;L;;;;;N;;;;; +140D1;EGYPTIAN HIEROGLYPH-140D1;Lo;0;L;;;;;N;;;;; +140D2;EGYPTIAN HIEROGLYPH-140D2;Lo;0;L;;;;;N;;;;; +140D3;EGYPTIAN HIEROGLYPH-140D3;Lo;0;L;;;;;N;;;;; +140D4;EGYPTIAN HIEROGLYPH-140D4;Lo;0;L;;;;;N;;;;; +140D5;EGYPTIAN HIEROGLYPH-140D5;Lo;0;L;;;;;N;;;;; +140D6;EGYPTIAN HIEROGLYPH-140D6;Lo;0;L;;;;;N;;;;; +140D7;EGYPTIAN HIEROGLYPH-140D7;Lo;0;L;;;;;N;;;;; +140D8;EGYPTIAN HIEROGLYPH-140D8;Lo;0;L;;;;;N;;;;; +140D9;EGYPTIAN HIEROGLYPH-140D9;Lo;0;L;;;;;N;;;;; +140DA;EGYPTIAN HIEROGLYPH-140DA;Lo;0;L;;;;;N;;;;; +140DB;EGYPTIAN HIEROGLYPH-140DB;Lo;0;L;;;;;N;;;;; +140DC;EGYPTIAN HIEROGLYPH-140DC;Lo;0;L;;;;;N;;;;; +140DD;EGYPTIAN HIEROGLYPH-140DD;Lo;0;L;;;;;N;;;;; +140DE;EGYPTIAN HIEROGLYPH-140DE;Lo;0;L;;;;;N;;;;; +140DF;EGYPTIAN HIEROGLYPH-140DF;Lo;0;L;;;;;N;;;;; +140E0;EGYPTIAN HIEROGLYPH-140E0;Lo;0;L;;;;;N;;;;; +140E1;EGYPTIAN HIEROGLYPH-140E1;Lo;0;L;;;;;N;;;;; +140E2;EGYPTIAN HIEROGLYPH-140E2;Lo;0;L;;;;;N;;;;; +140E3;EGYPTIAN HIEROGLYPH-140E3;Lo;0;L;;;;;N;;;;; +140E4;EGYPTIAN HIEROGLYPH-140E4;Lo;0;L;;;;;N;;;;; +140E5;EGYPTIAN HIEROGLYPH-140E5;Lo;0;L;;;;;N;;;;; +140E6;EGYPTIAN HIEROGLYPH-140E6;Lo;0;L;;;;;N;;;;; +140E7;EGYPTIAN HIEROGLYPH-140E7;Lo;0;L;;;;;N;;;;; +140E8;EGYPTIAN HIEROGLYPH-140E8;Lo;0;L;;;;;N;;;;; +140E9;EGYPTIAN HIEROGLYPH-140E9;Lo;0;L;;;;;N;;;;; +140EA;EGYPTIAN HIEROGLYPH-140EA;Lo;0;L;;;;;N;;;;; +140EB;EGYPTIAN HIEROGLYPH-140EB;Lo;0;L;;;;;N;;;;; +140EC;EGYPTIAN HIEROGLYPH-140EC;Lo;0;L;;;;;N;;;;; +140ED;EGYPTIAN HIEROGLYPH-140ED;Lo;0;L;;;;;N;;;;; +140EE;EGYPTIAN HIEROGLYPH-140EE;Lo;0;L;;;;;N;;;;; +140EF;EGYPTIAN HIEROGLYPH-140EF;Lo;0;L;;;;;N;;;;; +140F0;EGYPTIAN HIEROGLYPH-140F0;Lo;0;L;;;;;N;;;;; +140F1;EGYPTIAN HIEROGLYPH-140F1;Lo;0;L;;;;;N;;;;; +140F2;EGYPTIAN HIEROGLYPH-140F2;Lo;0;L;;;;;N;;;;; +140F3;EGYPTIAN HIEROGLYPH-140F3;Lo;0;L;;;;;N;;;;; +140F4;EGYPTIAN HIEROGLYPH-140F4;Lo;0;L;;;;;N;;;;; +140F5;EGYPTIAN HIEROGLYPH-140F5;Lo;0;L;;;;;N;;;;; +140F6;EGYPTIAN HIEROGLYPH-140F6;Lo;0;L;;;;;N;;;;; +140F7;EGYPTIAN HIEROGLYPH-140F7;Lo;0;L;;;;;N;;;;; +140F8;EGYPTIAN HIEROGLYPH-140F8;Lo;0;L;;;;;N;;;;; +140F9;EGYPTIAN HIEROGLYPH-140F9;Lo;0;L;;;;;N;;;;; +140FA;EGYPTIAN HIEROGLYPH-140FA;Lo;0;L;;;;;N;;;;; +140FB;EGYPTIAN HIEROGLYPH-140FB;Lo;0;L;;;;;N;;;;; +140FC;EGYPTIAN HIEROGLYPH-140FC;Lo;0;L;;;;;N;;;;; +140FD;EGYPTIAN HIEROGLYPH-140FD;Lo;0;L;;;;;N;;;;; +140FE;EGYPTIAN HIEROGLYPH-140FE;Lo;0;L;;;;;N;;;;; +140FF;EGYPTIAN HIEROGLYPH-140FF;Lo;0;L;;;;;N;;;;; +14100;EGYPTIAN HIEROGLYPH-14100;Lo;0;L;;;;;N;;;;; +14101;EGYPTIAN HIEROGLYPH-14101;Lo;0;L;;;;;N;;;;; +14102;EGYPTIAN HIEROGLYPH-14102;Lo;0;L;;;;;N;;;;; +14103;EGYPTIAN HIEROGLYPH-14103;Lo;0;L;;;;;N;;;;; +14104;EGYPTIAN HIEROGLYPH-14104;Lo;0;L;;;;;N;;;;; +14105;EGYPTIAN HIEROGLYPH-14105;Lo;0;L;;;;;N;;;;; +14106;EGYPTIAN HIEROGLYPH-14106;Lo;0;L;;;;;N;;;;; +14107;EGYPTIAN HIEROGLYPH-14107;Lo;0;L;;;;;N;;;;; +14108;EGYPTIAN HIEROGLYPH-14108;Lo;0;L;;;;;N;;;;; +14109;EGYPTIAN HIEROGLYPH-14109;Lo;0;L;;;;;N;;;;; +1410A;EGYPTIAN HIEROGLYPH-1410A;Lo;0;L;;;;;N;;;;; +1410B;EGYPTIAN HIEROGLYPH-1410B;Lo;0;L;;;;;N;;;;; +1410C;EGYPTIAN HIEROGLYPH-1410C;Lo;0;L;;;;;N;;;;; +1410D;EGYPTIAN HIEROGLYPH-1410D;Lo;0;L;;;;;N;;;;; +1410E;EGYPTIAN HIEROGLYPH-1410E;Lo;0;L;;;;;N;;;;; +1410F;EGYPTIAN HIEROGLYPH-1410F;Lo;0;L;;;;;N;;;;; +14110;EGYPTIAN HIEROGLYPH-14110;Lo;0;L;;;;;N;;;;; +14111;EGYPTIAN HIEROGLYPH-14111;Lo;0;L;;;;;N;;;;; +14112;EGYPTIAN HIEROGLYPH-14112;Lo;0;L;;;;;N;;;;; +14113;EGYPTIAN HIEROGLYPH-14113;Lo;0;L;;;;;N;;;;; +14114;EGYPTIAN HIEROGLYPH-14114;Lo;0;L;;;;;N;;;;; +14115;EGYPTIAN HIEROGLYPH-14115;Lo;0;L;;;;;N;;;;; +14116;EGYPTIAN HIEROGLYPH-14116;Lo;0;L;;;;;N;;;;; +14117;EGYPTIAN HIEROGLYPH-14117;Lo;0;L;;;;;N;;;;; +14118;EGYPTIAN HIEROGLYPH-14118;Lo;0;L;;;;;N;;;;; +14119;EGYPTIAN HIEROGLYPH-14119;Lo;0;L;;;;;N;;;;; +1411A;EGYPTIAN HIEROGLYPH-1411A;Lo;0;L;;;;;N;;;;; +1411B;EGYPTIAN HIEROGLYPH-1411B;Lo;0;L;;;;;N;;;;; +1411C;EGYPTIAN HIEROGLYPH-1411C;Lo;0;L;;;;;N;;;;; +1411D;EGYPTIAN HIEROGLYPH-1411D;Lo;0;L;;;;;N;;;;; +1411E;EGYPTIAN HIEROGLYPH-1411E;Lo;0;L;;;;;N;;;;; +1411F;EGYPTIAN HIEROGLYPH-1411F;Lo;0;L;;;;;N;;;;; +14120;EGYPTIAN HIEROGLYPH-14120;Lo;0;L;;;;;N;;;;; +14121;EGYPTIAN HIEROGLYPH-14121;Lo;0;L;;;;;N;;;;; +14122;EGYPTIAN HIEROGLYPH-14122;Lo;0;L;;;;;N;;;;; +14123;EGYPTIAN HIEROGLYPH-14123;Lo;0;L;;;;;N;;;;; +14124;EGYPTIAN HIEROGLYPH-14124;Lo;0;L;;;;;N;;;;; +14125;EGYPTIAN HIEROGLYPH-14125;Lo;0;L;;;;;N;;;;; +14126;EGYPTIAN HIEROGLYPH-14126;Lo;0;L;;;;;N;;;;; +14127;EGYPTIAN HIEROGLYPH-14127;Lo;0;L;;;;;N;;;;; +14128;EGYPTIAN HIEROGLYPH-14128;Lo;0;L;;;;;N;;;;; +14129;EGYPTIAN HIEROGLYPH-14129;Lo;0;L;;;;;N;;;;; +1412A;EGYPTIAN HIEROGLYPH-1412A;Lo;0;L;;;;;N;;;;; +1412B;EGYPTIAN HIEROGLYPH-1412B;Lo;0;L;;;;;N;;;;; +1412C;EGYPTIAN HIEROGLYPH-1412C;Lo;0;L;;;;;N;;;;; +1412D;EGYPTIAN HIEROGLYPH-1412D;Lo;0;L;;;;;N;;;;; +1412E;EGYPTIAN HIEROGLYPH-1412E;Lo;0;L;;;;;N;;;;; +1412F;EGYPTIAN HIEROGLYPH-1412F;Lo;0;L;;;;;N;;;;; +14130;EGYPTIAN HIEROGLYPH-14130;Lo;0;L;;;;;N;;;;; +14131;EGYPTIAN HIEROGLYPH-14131;Lo;0;L;;;;;N;;;;; +14132;EGYPTIAN HIEROGLYPH-14132;Lo;0;L;;;;;N;;;;; +14133;EGYPTIAN HIEROGLYPH-14133;Lo;0;L;;;;;N;;;;; +14134;EGYPTIAN HIEROGLYPH-14134;Lo;0;L;;;;;N;;;;; +14135;EGYPTIAN HIEROGLYPH-14135;Lo;0;L;;;;;N;;;;; +14136;EGYPTIAN HIEROGLYPH-14136;Lo;0;L;;;;;N;;;;; +14137;EGYPTIAN HIEROGLYPH-14137;Lo;0;L;;;;;N;;;;; +14138;EGYPTIAN HIEROGLYPH-14138;Lo;0;L;;;;;N;;;;; +14139;EGYPTIAN HIEROGLYPH-14139;Lo;0;L;;;;;N;;;;; +1413A;EGYPTIAN HIEROGLYPH-1413A;Lo;0;L;;;;;N;;;;; +1413B;EGYPTIAN HIEROGLYPH-1413B;Lo;0;L;;;;;N;;;;; +1413C;EGYPTIAN HIEROGLYPH-1413C;Lo;0;L;;;;;N;;;;; +1413D;EGYPTIAN HIEROGLYPH-1413D;Lo;0;L;;;;;N;;;;; +1413E;EGYPTIAN HIEROGLYPH-1413E;Lo;0;L;;;;;N;;;;; +1413F;EGYPTIAN HIEROGLYPH-1413F;Lo;0;L;;;;;N;;;;; +14140;EGYPTIAN HIEROGLYPH-14140;Lo;0;L;;;;;N;;;;; +14141;EGYPTIAN HIEROGLYPH-14141;Lo;0;L;;;;;N;;;;; +14142;EGYPTIAN HIEROGLYPH-14142;Lo;0;L;;;;;N;;;;; +14143;EGYPTIAN HIEROGLYPH-14143;Lo;0;L;;;;;N;;;;; +14144;EGYPTIAN HIEROGLYPH-14144;Lo;0;L;;;;;N;;;;; +14145;EGYPTIAN HIEROGLYPH-14145;Lo;0;L;;;;;N;;;;; +14146;EGYPTIAN HIEROGLYPH-14146;Lo;0;L;;;;;N;;;;; +14147;EGYPTIAN HIEROGLYPH-14147;Lo;0;L;;;;;N;;;;; +14148;EGYPTIAN HIEROGLYPH-14148;Lo;0;L;;;;;N;;;;; +14149;EGYPTIAN HIEROGLYPH-14149;Lo;0;L;;;;;N;;;;; +1414A;EGYPTIAN HIEROGLYPH-1414A;Lo;0;L;;;;;N;;;;; +1414B;EGYPTIAN HIEROGLYPH-1414B;Lo;0;L;;;;;N;;;;; +1414C;EGYPTIAN HIEROGLYPH-1414C;Lo;0;L;;;;;N;;;;; +1414D;EGYPTIAN HIEROGLYPH-1414D;Lo;0;L;;;;;N;;;;; +1414E;EGYPTIAN HIEROGLYPH-1414E;Lo;0;L;;;;;N;;;;; +1414F;EGYPTIAN HIEROGLYPH-1414F;Lo;0;L;;;;;N;;;;; +14150;EGYPTIAN HIEROGLYPH-14150;Lo;0;L;;;;;N;;;;; +14151;EGYPTIAN HIEROGLYPH-14151;Lo;0;L;;;;;N;;;;; +14152;EGYPTIAN HIEROGLYPH-14152;Lo;0;L;;;;;N;;;;; +14153;EGYPTIAN HIEROGLYPH-14153;Lo;0;L;;;;;N;;;;; +14154;EGYPTIAN HIEROGLYPH-14154;Lo;0;L;;;;;N;;;;; +14155;EGYPTIAN HIEROGLYPH-14155;Lo;0;L;;;;;N;;;;; +14156;EGYPTIAN HIEROGLYPH-14156;Lo;0;L;;;;;N;;;;; +14157;EGYPTIAN HIEROGLYPH-14157;Lo;0;L;;;;;N;;;;; +14158;EGYPTIAN HIEROGLYPH-14158;Lo;0;L;;;;;N;;;;; +14159;EGYPTIAN HIEROGLYPH-14159;Lo;0;L;;;;;N;;;;; +1415A;EGYPTIAN HIEROGLYPH-1415A;Lo;0;L;;;;;N;;;;; +1415B;EGYPTIAN HIEROGLYPH-1415B;Lo;0;L;;;;;N;;;;; +1415C;EGYPTIAN HIEROGLYPH-1415C;Lo;0;L;;;;;N;;;;; +1415D;EGYPTIAN HIEROGLYPH-1415D;Lo;0;L;;;;;N;;;;; +1415E;EGYPTIAN HIEROGLYPH-1415E;Lo;0;L;;;;;N;;;;; +1415F;EGYPTIAN HIEROGLYPH-1415F;Lo;0;L;;;;;N;;;;; +14160;EGYPTIAN HIEROGLYPH-14160;Lo;0;L;;;;;N;;;;; +14161;EGYPTIAN HIEROGLYPH-14161;Lo;0;L;;;;;N;;;;; +14162;EGYPTIAN HIEROGLYPH-14162;Lo;0;L;;;;;N;;;;; +14163;EGYPTIAN HIEROGLYPH-14163;Lo;0;L;;;;;N;;;;; +14164;EGYPTIAN HIEROGLYPH-14164;Lo;0;L;;;;;N;;;;; +14165;EGYPTIAN HIEROGLYPH-14165;Lo;0;L;;;;;N;;;;; +14166;EGYPTIAN HIEROGLYPH-14166;Lo;0;L;;;;;N;;;;; +14167;EGYPTIAN HIEROGLYPH-14167;Lo;0;L;;;;;N;;;;; +14168;EGYPTIAN HIEROGLYPH-14168;Lo;0;L;;;;;N;;;;; +14169;EGYPTIAN HIEROGLYPH-14169;Lo;0;L;;;;;N;;;;; +1416A;EGYPTIAN HIEROGLYPH-1416A;Lo;0;L;;;;;N;;;;; +1416B;EGYPTIAN HIEROGLYPH-1416B;Lo;0;L;;;;;N;;;;; +1416C;EGYPTIAN HIEROGLYPH-1416C;Lo;0;L;;;;;N;;;;; +1416D;EGYPTIAN HIEROGLYPH-1416D;Lo;0;L;;;;;N;;;;; +1416E;EGYPTIAN HIEROGLYPH-1416E;Lo;0;L;;;;;N;;;;; +1416F;EGYPTIAN HIEROGLYPH-1416F;Lo;0;L;;;;;N;;;;; +14170;EGYPTIAN HIEROGLYPH-14170;Lo;0;L;;;;;N;;;;; +14171;EGYPTIAN HIEROGLYPH-14171;Lo;0;L;;;;;N;;;;; +14172;EGYPTIAN HIEROGLYPH-14172;Lo;0;L;;;;;N;;;;; +14173;EGYPTIAN HIEROGLYPH-14173;Lo;0;L;;;;;N;;;;; +14174;EGYPTIAN HIEROGLYPH-14174;Lo;0;L;;;;;N;;;;; +14175;EGYPTIAN HIEROGLYPH-14175;Lo;0;L;;;;;N;;;;; +14176;EGYPTIAN HIEROGLYPH-14176;Lo;0;L;;;;;N;;;;; +14177;EGYPTIAN HIEROGLYPH-14177;Lo;0;L;;;;;N;;;;; +14178;EGYPTIAN HIEROGLYPH-14178;Lo;0;L;;;;;N;;;;; +14179;EGYPTIAN HIEROGLYPH-14179;Lo;0;L;;;;;N;;;;; +1417A;EGYPTIAN HIEROGLYPH-1417A;Lo;0;L;;;;;N;;;;; +1417B;EGYPTIAN HIEROGLYPH-1417B;Lo;0;L;;;;;N;;;;; +1417C;EGYPTIAN HIEROGLYPH-1417C;Lo;0;L;;;;;N;;;;; +1417D;EGYPTIAN HIEROGLYPH-1417D;Lo;0;L;;;;;N;;;;; +1417E;EGYPTIAN HIEROGLYPH-1417E;Lo;0;L;;;;;N;;;;; +1417F;EGYPTIAN HIEROGLYPH-1417F;Lo;0;L;;;;;N;;;;; +14180;EGYPTIAN HIEROGLYPH-14180;Lo;0;L;;;;;N;;;;; +14181;EGYPTIAN HIEROGLYPH-14181;Lo;0;L;;;;;N;;;;; +14182;EGYPTIAN HIEROGLYPH-14182;Lo;0;L;;;;;N;;;;; +14183;EGYPTIAN HIEROGLYPH-14183;Lo;0;L;;;;;N;;;;; +14184;EGYPTIAN HIEROGLYPH-14184;Lo;0;L;;;;;N;;;;; +14185;EGYPTIAN HIEROGLYPH-14185;Lo;0;L;;;;;N;;;;; +14186;EGYPTIAN HIEROGLYPH-14186;Lo;0;L;;;;;N;;;;; +14187;EGYPTIAN HIEROGLYPH-14187;Lo;0;L;;;;;N;;;;; +14188;EGYPTIAN HIEROGLYPH-14188;Lo;0;L;;;;;N;;;;; +14189;EGYPTIAN HIEROGLYPH-14189;Lo;0;L;;;;;N;;;;; +1418A;EGYPTIAN HIEROGLYPH-1418A;Lo;0;L;;;;;N;;;;; +1418B;EGYPTIAN HIEROGLYPH-1418B;Lo;0;L;;;;;N;;;;; +1418C;EGYPTIAN HIEROGLYPH-1418C;Lo;0;L;;;;;N;;;;; +1418D;EGYPTIAN HIEROGLYPH-1418D;Lo;0;L;;;;;N;;;;; +1418E;EGYPTIAN HIEROGLYPH-1418E;Lo;0;L;;;;;N;;;;; +1418F;EGYPTIAN HIEROGLYPH-1418F;Lo;0;L;;;;;N;;;;; +14190;EGYPTIAN HIEROGLYPH-14190;Lo;0;L;;;;;N;;;;; +14191;EGYPTIAN HIEROGLYPH-14191;Lo;0;L;;;;;N;;;;; +14192;EGYPTIAN HIEROGLYPH-14192;Lo;0;L;;;;;N;;;;; +14193;EGYPTIAN HIEROGLYPH-14193;Lo;0;L;;;;;N;;;;; +14194;EGYPTIAN HIEROGLYPH-14194;Lo;0;L;;;;;N;;;;; +14195;EGYPTIAN HIEROGLYPH-14195;Lo;0;L;;;;;N;;;;; +14196;EGYPTIAN HIEROGLYPH-14196;Lo;0;L;;;;;N;;;;; +14197;EGYPTIAN HIEROGLYPH-14197;Lo;0;L;;;;;N;;;;; +14198;EGYPTIAN HIEROGLYPH-14198;Lo;0;L;;;;;N;;;;; +14199;EGYPTIAN HIEROGLYPH-14199;Lo;0;L;;;;;N;;;;; +1419A;EGYPTIAN HIEROGLYPH-1419A;Lo;0;L;;;;;N;;;;; +1419B;EGYPTIAN HIEROGLYPH-1419B;Lo;0;L;;;;;N;;;;; +1419C;EGYPTIAN HIEROGLYPH-1419C;Lo;0;L;;;;;N;;;;; +1419D;EGYPTIAN HIEROGLYPH-1419D;Lo;0;L;;;;;N;;;;; +1419E;EGYPTIAN HIEROGLYPH-1419E;Lo;0;L;;;;;N;;;;; +1419F;EGYPTIAN HIEROGLYPH-1419F;Lo;0;L;;;;;N;;;;; +141A0;EGYPTIAN HIEROGLYPH-141A0;Lo;0;L;;;;;N;;;;; +141A1;EGYPTIAN HIEROGLYPH-141A1;Lo;0;L;;;;;N;;;;; +141A2;EGYPTIAN HIEROGLYPH-141A2;Lo;0;L;;;;;N;;;;; +141A3;EGYPTIAN HIEROGLYPH-141A3;Lo;0;L;;;;;N;;;;; +141A4;EGYPTIAN HIEROGLYPH-141A4;Lo;0;L;;;;;N;;;;; +141A5;EGYPTIAN HIEROGLYPH-141A5;Lo;0;L;;;;;N;;;;; +141A6;EGYPTIAN HIEROGLYPH-141A6;Lo;0;L;;;;;N;;;;; +141A7;EGYPTIAN HIEROGLYPH-141A7;Lo;0;L;;;;;N;;;;; +141A8;EGYPTIAN HIEROGLYPH-141A8;Lo;0;L;;;;;N;;;;; +141A9;EGYPTIAN HIEROGLYPH-141A9;Lo;0;L;;;;;N;;;;; +141AA;EGYPTIAN HIEROGLYPH-141AA;Lo;0;L;;;;;N;;;;; +141AB;EGYPTIAN HIEROGLYPH-141AB;Lo;0;L;;;;;N;;;;; +141AC;EGYPTIAN HIEROGLYPH-141AC;Lo;0;L;;;;;N;;;;; +141AD;EGYPTIAN HIEROGLYPH-141AD;Lo;0;L;;;;;N;;;;; +141AE;EGYPTIAN HIEROGLYPH-141AE;Lo;0;L;;;;;N;;;;; +141AF;EGYPTIAN HIEROGLYPH-141AF;Lo;0;L;;;;;N;;;;; +141B0;EGYPTIAN HIEROGLYPH-141B0;Lo;0;L;;;;;N;;;;; +141B1;EGYPTIAN HIEROGLYPH-141B1;Lo;0;L;;;;;N;;;;; +141B2;EGYPTIAN HIEROGLYPH-141B2;Lo;0;L;;;;;N;;;;; +141B3;EGYPTIAN HIEROGLYPH-141B3;Lo;0;L;;;;;N;;;;; +141B4;EGYPTIAN HIEROGLYPH-141B4;Lo;0;L;;;;;N;;;;; +141B5;EGYPTIAN HIEROGLYPH-141B5;Lo;0;L;;;;;N;;;;; +141B6;EGYPTIAN HIEROGLYPH-141B6;Lo;0;L;;;;;N;;;;; +141B7;EGYPTIAN HIEROGLYPH-141B7;Lo;0;L;;;;;N;;;;; +141B8;EGYPTIAN HIEROGLYPH-141B8;Lo;0;L;;;;;N;;;;; +141B9;EGYPTIAN HIEROGLYPH-141B9;Lo;0;L;;;;;N;;;;; +141BA;EGYPTIAN HIEROGLYPH-141BA;Lo;0;L;;;;;N;;;;; +141BB;EGYPTIAN HIEROGLYPH-141BB;Lo;0;L;;;;;N;;;;; +141BC;EGYPTIAN HIEROGLYPH-141BC;Lo;0;L;;;;;N;;;;; +141BD;EGYPTIAN HIEROGLYPH-141BD;Lo;0;L;;;;;N;;;;; +141BE;EGYPTIAN HIEROGLYPH-141BE;Lo;0;L;;;;;N;;;;; +141BF;EGYPTIAN HIEROGLYPH-141BF;Lo;0;L;;;;;N;;;;; +141C0;EGYPTIAN HIEROGLYPH-141C0;Lo;0;L;;;;;N;;;;; +141C1;EGYPTIAN HIEROGLYPH-141C1;Lo;0;L;;;;;N;;;;; +141C2;EGYPTIAN HIEROGLYPH-141C2;Lo;0;L;;;;;N;;;;; +141C3;EGYPTIAN HIEROGLYPH-141C3;Lo;0;L;;;;;N;;;;; +141C4;EGYPTIAN HIEROGLYPH-141C4;Lo;0;L;;;;;N;;;;; +141C5;EGYPTIAN HIEROGLYPH-141C5;Lo;0;L;;;;;N;;;;; +141C6;EGYPTIAN HIEROGLYPH-141C6;Lo;0;L;;;;;N;;;;; +141C7;EGYPTIAN HIEROGLYPH-141C7;Lo;0;L;;;;;N;;;;; +141C8;EGYPTIAN HIEROGLYPH-141C8;Lo;0;L;;;;;N;;;;; +141C9;EGYPTIAN HIEROGLYPH-141C9;Lo;0;L;;;;;N;;;;; +141CA;EGYPTIAN HIEROGLYPH-141CA;Lo;0;L;;;;;N;;;;; +141CB;EGYPTIAN HIEROGLYPH-141CB;Lo;0;L;;;;;N;;;;; +141CC;EGYPTIAN HIEROGLYPH-141CC;Lo;0;L;;;;;N;;;;; +141CD;EGYPTIAN HIEROGLYPH-141CD;Lo;0;L;;;;;N;;;;; +141CE;EGYPTIAN HIEROGLYPH-141CE;Lo;0;L;;;;;N;;;;; +141CF;EGYPTIAN HIEROGLYPH-141CF;Lo;0;L;;;;;N;;;;; +141D0;EGYPTIAN HIEROGLYPH-141D0;Lo;0;L;;;;;N;;;;; +141D1;EGYPTIAN HIEROGLYPH-141D1;Lo;0;L;;;;;N;;;;; +141D2;EGYPTIAN HIEROGLYPH-141D2;Lo;0;L;;;;;N;;;;; +141D3;EGYPTIAN HIEROGLYPH-141D3;Lo;0;L;;;;;N;;;;; +141D4;EGYPTIAN HIEROGLYPH-141D4;Lo;0;L;;;;;N;;;;; +141D5;EGYPTIAN HIEROGLYPH-141D5;Lo;0;L;;;;;N;;;;; +141D6;EGYPTIAN HIEROGLYPH-141D6;Lo;0;L;;;;;N;;;;; +141D7;EGYPTIAN HIEROGLYPH-141D7;Lo;0;L;;;;;N;;;;; +141D8;EGYPTIAN HIEROGLYPH-141D8;Lo;0;L;;;;;N;;;;; +141D9;EGYPTIAN HIEROGLYPH-141D9;Lo;0;L;;;;;N;;;;; +141DA;EGYPTIAN HIEROGLYPH-141DA;Lo;0;L;;;;;N;;;;; +141DB;EGYPTIAN HIEROGLYPH-141DB;Lo;0;L;;;;;N;;;;; +141DC;EGYPTIAN HIEROGLYPH-141DC;Lo;0;L;;;;;N;;;;; +141DD;EGYPTIAN HIEROGLYPH-141DD;Lo;0;L;;;;;N;;;;; +141DE;EGYPTIAN HIEROGLYPH-141DE;Lo;0;L;;;;;N;;;;; +141DF;EGYPTIAN HIEROGLYPH-141DF;Lo;0;L;;;;;N;;;;; +141E0;EGYPTIAN HIEROGLYPH-141E0;Lo;0;L;;;;;N;;;;; +141E1;EGYPTIAN HIEROGLYPH-141E1;Lo;0;L;;;;;N;;;;; +141E2;EGYPTIAN HIEROGLYPH-141E2;Lo;0;L;;;;;N;;;;; +141E3;EGYPTIAN HIEROGLYPH-141E3;Lo;0;L;;;;;N;;;;; +141E4;EGYPTIAN HIEROGLYPH-141E4;Lo;0;L;;;;;N;;;;; +141E5;EGYPTIAN HIEROGLYPH-141E5;Lo;0;L;;;;;N;;;;; +141E6;EGYPTIAN HIEROGLYPH-141E6;Lo;0;L;;;;;N;;;;; +141E7;EGYPTIAN HIEROGLYPH-141E7;Lo;0;L;;;;;N;;;;; +141E8;EGYPTIAN HIEROGLYPH-141E8;Lo;0;L;;;;;N;;;;; +141E9;EGYPTIAN HIEROGLYPH-141E9;Lo;0;L;;;;;N;;;;; +141EA;EGYPTIAN HIEROGLYPH-141EA;Lo;0;L;;;;;N;;;;; +141EB;EGYPTIAN HIEROGLYPH-141EB;Lo;0;L;;;;;N;;;;; +141EC;EGYPTIAN HIEROGLYPH-141EC;Lo;0;L;;;;;N;;;;; +141ED;EGYPTIAN HIEROGLYPH-141ED;Lo;0;L;;;;;N;;;;; +141EE;EGYPTIAN HIEROGLYPH-141EE;Lo;0;L;;;;;N;;;;; +141EF;EGYPTIAN HIEROGLYPH-141EF;Lo;0;L;;;;;N;;;;; +141F0;EGYPTIAN HIEROGLYPH-141F0;Lo;0;L;;;;;N;;;;; +141F1;EGYPTIAN HIEROGLYPH-141F1;Lo;0;L;;;;;N;;;;; +141F2;EGYPTIAN HIEROGLYPH-141F2;Lo;0;L;;;;;N;;;;; +141F3;EGYPTIAN HIEROGLYPH-141F3;Lo;0;L;;;;;N;;;;; +141F4;EGYPTIAN HIEROGLYPH-141F4;Lo;0;L;;;;;N;;;;; +141F5;EGYPTIAN HIEROGLYPH-141F5;Lo;0;L;;;;;N;;;;; +141F6;EGYPTIAN HIEROGLYPH-141F6;Lo;0;L;;;;;N;;;;; +141F7;EGYPTIAN HIEROGLYPH-141F7;Lo;0;L;;;;;N;;;;; +141F8;EGYPTIAN HIEROGLYPH-141F8;Lo;0;L;;;;;N;;;;; +141F9;EGYPTIAN HIEROGLYPH-141F9;Lo;0;L;;;;;N;;;;; +141FA;EGYPTIAN HIEROGLYPH-141FA;Lo;0;L;;;;;N;;;;; +141FB;EGYPTIAN HIEROGLYPH-141FB;Lo;0;L;;;;;N;;;;; +141FC;EGYPTIAN HIEROGLYPH-141FC;Lo;0;L;;;;;N;;;;; +141FD;EGYPTIAN HIEROGLYPH-141FD;Lo;0;L;;;;;N;;;;; +141FE;EGYPTIAN HIEROGLYPH-141FE;Lo;0;L;;;;;N;;;;; +141FF;EGYPTIAN HIEROGLYPH-141FF;Lo;0;L;;;;;N;;;;; +14200;EGYPTIAN HIEROGLYPH-14200;Lo;0;L;;;;;N;;;;; +14201;EGYPTIAN HIEROGLYPH-14201;Lo;0;L;;;;;N;;;;; +14202;EGYPTIAN HIEROGLYPH-14202;Lo;0;L;;;;;N;;;;; +14203;EGYPTIAN HIEROGLYPH-14203;Lo;0;L;;;;;N;;;;; +14204;EGYPTIAN HIEROGLYPH-14204;Lo;0;L;;;;;N;;;;; +14205;EGYPTIAN HIEROGLYPH-14205;Lo;0;L;;;;;N;;;;; +14206;EGYPTIAN HIEROGLYPH-14206;Lo;0;L;;;;;N;;;;; +14207;EGYPTIAN HIEROGLYPH-14207;Lo;0;L;;;;;N;;;;; +14208;EGYPTIAN HIEROGLYPH-14208;Lo;0;L;;;;;N;;;;; +14209;EGYPTIAN HIEROGLYPH-14209;Lo;0;L;;;;;N;;;;; +1420A;EGYPTIAN HIEROGLYPH-1420A;Lo;0;L;;;;;N;;;;; +1420B;EGYPTIAN HIEROGLYPH-1420B;Lo;0;L;;;;;N;;;;; +1420C;EGYPTIAN HIEROGLYPH-1420C;Lo;0;L;;;;;N;;;;; +1420D;EGYPTIAN HIEROGLYPH-1420D;Lo;0;L;;;;;N;;;;; +1420E;EGYPTIAN HIEROGLYPH-1420E;Lo;0;L;;;;;N;;;;; +1420F;EGYPTIAN HIEROGLYPH-1420F;Lo;0;L;;;;;N;;;;; +14210;EGYPTIAN HIEROGLYPH-14210;Lo;0;L;;;;;N;;;;; +14211;EGYPTIAN HIEROGLYPH-14211;Lo;0;L;;;;;N;;;;; +14212;EGYPTIAN HIEROGLYPH-14212;Lo;0;L;;;;;N;;;;; +14213;EGYPTIAN HIEROGLYPH-14213;Lo;0;L;;;;;N;;;;; +14214;EGYPTIAN HIEROGLYPH-14214;Lo;0;L;;;;;N;;;;; +14215;EGYPTIAN HIEROGLYPH-14215;Lo;0;L;;;;;N;;;;; +14216;EGYPTIAN HIEROGLYPH-14216;Lo;0;L;;;;;N;;;;; +14217;EGYPTIAN HIEROGLYPH-14217;Lo;0;L;;;;;N;;;;; +14218;EGYPTIAN HIEROGLYPH-14218;Lo;0;L;;;;;N;;;;; +14219;EGYPTIAN HIEROGLYPH-14219;Lo;0;L;;;;;N;;;;; +1421A;EGYPTIAN HIEROGLYPH-1421A;Lo;0;L;;;;;N;;;;; +1421B;EGYPTIAN HIEROGLYPH-1421B;Lo;0;L;;;;;N;;;;; +1421C;EGYPTIAN HIEROGLYPH-1421C;Lo;0;L;;;;;N;;;;; +1421D;EGYPTIAN HIEROGLYPH-1421D;Lo;0;L;;;;;N;;;;; +1421E;EGYPTIAN HIEROGLYPH-1421E;Lo;0;L;;;;;N;;;;; +1421F;EGYPTIAN HIEROGLYPH-1421F;Lo;0;L;;;;;N;;;;; +14220;EGYPTIAN HIEROGLYPH-14220;Lo;0;L;;;;;N;;;;; +14221;EGYPTIAN HIEROGLYPH-14221;Lo;0;L;;;;;N;;;;; +14222;EGYPTIAN HIEROGLYPH-14222;Lo;0;L;;;;;N;;;;; +14223;EGYPTIAN HIEROGLYPH-14223;Lo;0;L;;;;;N;;;;; +14224;EGYPTIAN HIEROGLYPH-14224;Lo;0;L;;;;;N;;;;; +14225;EGYPTIAN HIEROGLYPH-14225;Lo;0;L;;;;;N;;;;; +14226;EGYPTIAN HIEROGLYPH-14226;Lo;0;L;;;;;N;;;;; +14227;EGYPTIAN HIEROGLYPH-14227;Lo;0;L;;;;;N;;;;; +14228;EGYPTIAN HIEROGLYPH-14228;Lo;0;L;;;;;N;;;;; +14229;EGYPTIAN HIEROGLYPH-14229;Lo;0;L;;;;;N;;;;; +1422A;EGYPTIAN HIEROGLYPH-1422A;Lo;0;L;;;;;N;;;;; +1422B;EGYPTIAN HIEROGLYPH-1422B;Lo;0;L;;;;;N;;;;; +1422C;EGYPTIAN HIEROGLYPH-1422C;Lo;0;L;;;;;N;;;;; +1422D;EGYPTIAN HIEROGLYPH-1422D;Lo;0;L;;;;;N;;;;; +1422E;EGYPTIAN HIEROGLYPH-1422E;Lo;0;L;;;;;N;;;;; +1422F;EGYPTIAN HIEROGLYPH-1422F;Lo;0;L;;;;;N;;;;; +14230;EGYPTIAN HIEROGLYPH-14230;Lo;0;L;;;;;N;;;;; +14231;EGYPTIAN HIEROGLYPH-14231;Lo;0;L;;;;;N;;;;; +14232;EGYPTIAN HIEROGLYPH-14232;Lo;0;L;;;;;N;;;;; +14233;EGYPTIAN HIEROGLYPH-14233;Lo;0;L;;;;;N;;;;; +14234;EGYPTIAN HIEROGLYPH-14234;Lo;0;L;;;;;N;;;;; +14235;EGYPTIAN HIEROGLYPH-14235;Lo;0;L;;;;;N;;;;; +14236;EGYPTIAN HIEROGLYPH-14236;Lo;0;L;;;;;N;;;;; +14237;EGYPTIAN HIEROGLYPH-14237;Lo;0;L;;;;;N;;;;; +14238;EGYPTIAN HIEROGLYPH-14238;Lo;0;L;;;;;N;;;;; +14239;EGYPTIAN HIEROGLYPH-14239;Lo;0;L;;;;;N;;;;; +1423A;EGYPTIAN HIEROGLYPH-1423A;Lo;0;L;;;;;N;;;;; +1423B;EGYPTIAN HIEROGLYPH-1423B;Lo;0;L;;;;;N;;;;; +1423C;EGYPTIAN HIEROGLYPH-1423C;Lo;0;L;;;;;N;;;;; +1423D;EGYPTIAN HIEROGLYPH-1423D;Lo;0;L;;;;;N;;;;; +1423E;EGYPTIAN HIEROGLYPH-1423E;Lo;0;L;;;;;N;;;;; +1423F;EGYPTIAN HIEROGLYPH-1423F;Lo;0;L;;;;;N;;;;; +14240;EGYPTIAN HIEROGLYPH-14240;Lo;0;L;;;;;N;;;;; +14241;EGYPTIAN HIEROGLYPH-14241;Lo;0;L;;;;;N;;;;; +14242;EGYPTIAN HIEROGLYPH-14242;Lo;0;L;;;;;N;;;;; +14243;EGYPTIAN HIEROGLYPH-14243;Lo;0;L;;;;;N;;;;; +14244;EGYPTIAN HIEROGLYPH-14244;Lo;0;L;;;;;N;;;;; +14245;EGYPTIAN HIEROGLYPH-14245;Lo;0;L;;;;;N;;;;; +14246;EGYPTIAN HIEROGLYPH-14246;Lo;0;L;;;;;N;;;;; +14247;EGYPTIAN HIEROGLYPH-14247;Lo;0;L;;;;;N;;;;; +14248;EGYPTIAN HIEROGLYPH-14248;Lo;0;L;;;;;N;;;;; +14249;EGYPTIAN HIEROGLYPH-14249;Lo;0;L;;;;;N;;;;; +1424A;EGYPTIAN HIEROGLYPH-1424A;Lo;0;L;;;;;N;;;;; +1424B;EGYPTIAN HIEROGLYPH-1424B;Lo;0;L;;;;;N;;;;; +1424C;EGYPTIAN HIEROGLYPH-1424C;Lo;0;L;;;;;N;;;;; +1424D;EGYPTIAN HIEROGLYPH-1424D;Lo;0;L;;;;;N;;;;; +1424E;EGYPTIAN HIEROGLYPH-1424E;Lo;0;L;;;;;N;;;;; +1424F;EGYPTIAN HIEROGLYPH-1424F;Lo;0;L;;;;;N;;;;; +14250;EGYPTIAN HIEROGLYPH-14250;Lo;0;L;;;;;N;;;;; +14251;EGYPTIAN HIEROGLYPH-14251;Lo;0;L;;;;;N;;;;; +14252;EGYPTIAN HIEROGLYPH-14252;Lo;0;L;;;;;N;;;;; +14253;EGYPTIAN HIEROGLYPH-14253;Lo;0;L;;;;;N;;;;; +14254;EGYPTIAN HIEROGLYPH-14254;Lo;0;L;;;;;N;;;;; +14255;EGYPTIAN HIEROGLYPH-14255;Lo;0;L;;;;;N;;;;; +14256;EGYPTIAN HIEROGLYPH-14256;Lo;0;L;;;;;N;;;;; +14257;EGYPTIAN HIEROGLYPH-14257;Lo;0;L;;;;;N;;;;; +14258;EGYPTIAN HIEROGLYPH-14258;Lo;0;L;;;;;N;;;;; +14259;EGYPTIAN HIEROGLYPH-14259;Lo;0;L;;;;;N;;;;; +1425A;EGYPTIAN HIEROGLYPH-1425A;Lo;0;L;;;;;N;;;;; +1425B;EGYPTIAN HIEROGLYPH-1425B;Lo;0;L;;;;;N;;;;; +1425C;EGYPTIAN HIEROGLYPH-1425C;Lo;0;L;;;;;N;;;;; +1425D;EGYPTIAN HIEROGLYPH-1425D;Lo;0;L;;;;;N;;;;; +1425E;EGYPTIAN HIEROGLYPH-1425E;Lo;0;L;;;;;N;;;;; +1425F;EGYPTIAN HIEROGLYPH-1425F;Lo;0;L;;;;;N;;;;; +14260;EGYPTIAN HIEROGLYPH-14260;Lo;0;L;;;;;N;;;;; +14261;EGYPTIAN HIEROGLYPH-14261;Lo;0;L;;;;;N;;;;; +14262;EGYPTIAN HIEROGLYPH-14262;Lo;0;L;;;;;N;;;;; +14263;EGYPTIAN HIEROGLYPH-14263;Lo;0;L;;;;;N;;;;; +14264;EGYPTIAN HIEROGLYPH-14264;Lo;0;L;;;;;N;;;;; +14265;EGYPTIAN HIEROGLYPH-14265;Lo;0;L;;;;;N;;;;; +14266;EGYPTIAN HIEROGLYPH-14266;Lo;0;L;;;;;N;;;;; +14267;EGYPTIAN HIEROGLYPH-14267;Lo;0;L;;;;;N;;;;; +14268;EGYPTIAN HIEROGLYPH-14268;Lo;0;L;;;;;N;;;;; +14269;EGYPTIAN HIEROGLYPH-14269;Lo;0;L;;;;;N;;;;; +1426A;EGYPTIAN HIEROGLYPH-1426A;Lo;0;L;;;;;N;;;;; +1426B;EGYPTIAN HIEROGLYPH-1426B;Lo;0;L;;;;;N;;;;; +1426C;EGYPTIAN HIEROGLYPH-1426C;Lo;0;L;;;;;N;;;;; +1426D;EGYPTIAN HIEROGLYPH-1426D;Lo;0;L;;;;;N;;;;; +1426E;EGYPTIAN HIEROGLYPH-1426E;Lo;0;L;;;;;N;;;;; +1426F;EGYPTIAN HIEROGLYPH-1426F;Lo;0;L;;;;;N;;;;; +14270;EGYPTIAN HIEROGLYPH-14270;Lo;0;L;;;;;N;;;;; +14271;EGYPTIAN HIEROGLYPH-14271;Lo;0;L;;;;;N;;;;; +14272;EGYPTIAN HIEROGLYPH-14272;Lo;0;L;;;;;N;;;;; +14273;EGYPTIAN HIEROGLYPH-14273;Lo;0;L;;;;;N;;;;; +14274;EGYPTIAN HIEROGLYPH-14274;Lo;0;L;;;;;N;;;;; +14275;EGYPTIAN HIEROGLYPH-14275;Lo;0;L;;;;;N;;;;; +14276;EGYPTIAN HIEROGLYPH-14276;Lo;0;L;;;;;N;;;;; +14277;EGYPTIAN HIEROGLYPH-14277;Lo;0;L;;;;;N;;;;; +14278;EGYPTIAN HIEROGLYPH-14278;Lo;0;L;;;;;N;;;;; +14279;EGYPTIAN HIEROGLYPH-14279;Lo;0;L;;;;;N;;;;; +1427A;EGYPTIAN HIEROGLYPH-1427A;Lo;0;L;;;;;N;;;;; +1427B;EGYPTIAN HIEROGLYPH-1427B;Lo;0;L;;;;;N;;;;; +1427C;EGYPTIAN HIEROGLYPH-1427C;Lo;0;L;;;;;N;;;;; +1427D;EGYPTIAN HIEROGLYPH-1427D;Lo;0;L;;;;;N;;;;; +1427E;EGYPTIAN HIEROGLYPH-1427E;Lo;0;L;;;;;N;;;;; +1427F;EGYPTIAN HIEROGLYPH-1427F;Lo;0;L;;;;;N;;;;; +14280;EGYPTIAN HIEROGLYPH-14280;Lo;0;L;;;;;N;;;;; +14281;EGYPTIAN HIEROGLYPH-14281;Lo;0;L;;;;;N;;;;; +14282;EGYPTIAN HIEROGLYPH-14282;Lo;0;L;;;;;N;;;;; +14283;EGYPTIAN HIEROGLYPH-14283;Lo;0;L;;;;;N;;;;; +14284;EGYPTIAN HIEROGLYPH-14284;Lo;0;L;;;;;N;;;;; +14285;EGYPTIAN HIEROGLYPH-14285;Lo;0;L;;;;;N;;;;; +14286;EGYPTIAN HIEROGLYPH-14286;Lo;0;L;;;;;N;;;;; +14287;EGYPTIAN HIEROGLYPH-14287;Lo;0;L;;;;;N;;;;; +14288;EGYPTIAN HIEROGLYPH-14288;Lo;0;L;;;;;N;;;;; +14289;EGYPTIAN HIEROGLYPH-14289;Lo;0;L;;;;;N;;;;; +1428A;EGYPTIAN HIEROGLYPH-1428A;Lo;0;L;;;;;N;;;;; +1428B;EGYPTIAN HIEROGLYPH-1428B;Lo;0;L;;;;;N;;;;; +1428C;EGYPTIAN HIEROGLYPH-1428C;Lo;0;L;;;;;N;;;;; +1428D;EGYPTIAN HIEROGLYPH-1428D;Lo;0;L;;;;;N;;;;; +1428E;EGYPTIAN HIEROGLYPH-1428E;Lo;0;L;;;;;N;;;;; +1428F;EGYPTIAN HIEROGLYPH-1428F;Lo;0;L;;;;;N;;;;; +14290;EGYPTIAN HIEROGLYPH-14290;Lo;0;L;;;;;N;;;;; +14291;EGYPTIAN HIEROGLYPH-14291;Lo;0;L;;;;;N;;;;; +14292;EGYPTIAN HIEROGLYPH-14292;Lo;0;L;;;;;N;;;;; +14293;EGYPTIAN HIEROGLYPH-14293;Lo;0;L;;;;;N;;;;; +14294;EGYPTIAN HIEROGLYPH-14294;Lo;0;L;;;;;N;;;;; +14295;EGYPTIAN HIEROGLYPH-14295;Lo;0;L;;;;;N;;;;; +14296;EGYPTIAN HIEROGLYPH-14296;Lo;0;L;;;;;N;;;;; +14297;EGYPTIAN HIEROGLYPH-14297;Lo;0;L;;;;;N;;;;; +14298;EGYPTIAN HIEROGLYPH-14298;Lo;0;L;;;;;N;;;;; +14299;EGYPTIAN HIEROGLYPH-14299;Lo;0;L;;;;;N;;;;; +1429A;EGYPTIAN HIEROGLYPH-1429A;Lo;0;L;;;;;N;;;;; +1429B;EGYPTIAN HIEROGLYPH-1429B;Lo;0;L;;;;;N;;;;; +1429C;EGYPTIAN HIEROGLYPH-1429C;Lo;0;L;;;;;N;;;;; +1429D;EGYPTIAN HIEROGLYPH-1429D;Lo;0;L;;;;;N;;;;; +1429E;EGYPTIAN HIEROGLYPH-1429E;Lo;0;L;;;;;N;;;;; +1429F;EGYPTIAN HIEROGLYPH-1429F;Lo;0;L;;;;;N;;;;; +142A0;EGYPTIAN HIEROGLYPH-142A0;Lo;0;L;;;;;N;;;;; +142A1;EGYPTIAN HIEROGLYPH-142A1;Lo;0;L;;;;;N;;;;; +142A2;EGYPTIAN HIEROGLYPH-142A2;Lo;0;L;;;;;N;;;;; +142A3;EGYPTIAN HIEROGLYPH-142A3;Lo;0;L;;;;;N;;;;; +142A4;EGYPTIAN HIEROGLYPH-142A4;Lo;0;L;;;;;N;;;;; +142A5;EGYPTIAN HIEROGLYPH-142A5;Lo;0;L;;;;;N;;;;; +142A6;EGYPTIAN HIEROGLYPH-142A6;Lo;0;L;;;;;N;;;;; +142A7;EGYPTIAN HIEROGLYPH-142A7;Lo;0;L;;;;;N;;;;; +142A8;EGYPTIAN HIEROGLYPH-142A8;Lo;0;L;;;;;N;;;;; +142A9;EGYPTIAN HIEROGLYPH-142A9;Lo;0;L;;;;;N;;;;; +142AA;EGYPTIAN HIEROGLYPH-142AA;Lo;0;L;;;;;N;;;;; +142AB;EGYPTIAN HIEROGLYPH-142AB;Lo;0;L;;;;;N;;;;; +142AC;EGYPTIAN HIEROGLYPH-142AC;Lo;0;L;;;;;N;;;;; +142AD;EGYPTIAN HIEROGLYPH-142AD;Lo;0;L;;;;;N;;;;; +142AE;EGYPTIAN HIEROGLYPH-142AE;Lo;0;L;;;;;N;;;;; +142AF;EGYPTIAN HIEROGLYPH-142AF;Lo;0;L;;;;;N;;;;; +142B0;EGYPTIAN HIEROGLYPH-142B0;Lo;0;L;;;;;N;;;;; +142B1;EGYPTIAN HIEROGLYPH-142B1;Lo;0;L;;;;;N;;;;; +142B2;EGYPTIAN HIEROGLYPH-142B2;Lo;0;L;;;;;N;;;;; +142B3;EGYPTIAN HIEROGLYPH-142B3;Lo;0;L;;;;;N;;;;; +142B4;EGYPTIAN HIEROGLYPH-142B4;Lo;0;L;;;;;N;;;;; +142B5;EGYPTIAN HIEROGLYPH-142B5;Lo;0;L;;;;;N;;;;; +142B6;EGYPTIAN HIEROGLYPH-142B6;Lo;0;L;;;;;N;;;;; +142B7;EGYPTIAN HIEROGLYPH-142B7;Lo;0;L;;;;;N;;;;; +142B8;EGYPTIAN HIEROGLYPH-142B8;Lo;0;L;;;;;N;;;;; +142B9;EGYPTIAN HIEROGLYPH-142B9;Lo;0;L;;;;;N;;;;; +142BA;EGYPTIAN HIEROGLYPH-142BA;Lo;0;L;;;;;N;;;;; +142BB;EGYPTIAN HIEROGLYPH-142BB;Lo;0;L;;;;;N;;;;; +142BC;EGYPTIAN HIEROGLYPH-142BC;Lo;0;L;;;;;N;;;;; +142BD;EGYPTIAN HIEROGLYPH-142BD;Lo;0;L;;;;;N;;;;; +142BE;EGYPTIAN HIEROGLYPH-142BE;Lo;0;L;;;;;N;;;;; +142BF;EGYPTIAN HIEROGLYPH-142BF;Lo;0;L;;;;;N;;;;; +142C0;EGYPTIAN HIEROGLYPH-142C0;Lo;0;L;;;;;N;;;;; +142C1;EGYPTIAN HIEROGLYPH-142C1;Lo;0;L;;;;;N;;;;; +142C2;EGYPTIAN HIEROGLYPH-142C2;Lo;0;L;;;;;N;;;;; +142C3;EGYPTIAN HIEROGLYPH-142C3;Lo;0;L;;;;;N;;;;; +142C4;EGYPTIAN HIEROGLYPH-142C4;Lo;0;L;;;;;N;;;;; +142C5;EGYPTIAN HIEROGLYPH-142C5;Lo;0;L;;;;;N;;;;; +142C6;EGYPTIAN HIEROGLYPH-142C6;Lo;0;L;;;;;N;;;;; +142C7;EGYPTIAN HIEROGLYPH-142C7;Lo;0;L;;;;;N;;;;; +142C8;EGYPTIAN HIEROGLYPH-142C8;Lo;0;L;;;;;N;;;;; +142C9;EGYPTIAN HIEROGLYPH-142C9;Lo;0;L;;;;;N;;;;; +142CA;EGYPTIAN HIEROGLYPH-142CA;Lo;0;L;;;;;N;;;;; +142CB;EGYPTIAN HIEROGLYPH-142CB;Lo;0;L;;;;;N;;;;; +142CC;EGYPTIAN HIEROGLYPH-142CC;Lo;0;L;;;;;N;;;;; +142CD;EGYPTIAN HIEROGLYPH-142CD;Lo;0;L;;;;;N;;;;; +142CE;EGYPTIAN HIEROGLYPH-142CE;Lo;0;L;;;;;N;;;;; +142CF;EGYPTIAN HIEROGLYPH-142CF;Lo;0;L;;;;;N;;;;; +142D0;EGYPTIAN HIEROGLYPH-142D0;Lo;0;L;;;;;N;;;;; +142D1;EGYPTIAN HIEROGLYPH-142D1;Lo;0;L;;;;;N;;;;; +142D2;EGYPTIAN HIEROGLYPH-142D2;Lo;0;L;;;;;N;;;;; +142D3;EGYPTIAN HIEROGLYPH-142D3;Lo;0;L;;;;;N;;;;; +142D4;EGYPTIAN HIEROGLYPH-142D4;Lo;0;L;;;;;N;;;;; +142D5;EGYPTIAN HIEROGLYPH-142D5;Lo;0;L;;;;;N;;;;; +142D6;EGYPTIAN HIEROGLYPH-142D6;Lo;0;L;;;;;N;;;;; +142D7;EGYPTIAN HIEROGLYPH-142D7;Lo;0;L;;;;;N;;;;; +142D8;EGYPTIAN HIEROGLYPH-142D8;Lo;0;L;;;;;N;;;;; +142D9;EGYPTIAN HIEROGLYPH-142D9;Lo;0;L;;;;;N;;;;; +142DA;EGYPTIAN HIEROGLYPH-142DA;Lo;0;L;;;;;N;;;;; +142DB;EGYPTIAN HIEROGLYPH-142DB;Lo;0;L;;;;;N;;;;; +142DC;EGYPTIAN HIEROGLYPH-142DC;Lo;0;L;;;;;N;;;;; +142DD;EGYPTIAN HIEROGLYPH-142DD;Lo;0;L;;;;;N;;;;; +142DE;EGYPTIAN HIEROGLYPH-142DE;Lo;0;L;;;;;N;;;;; +142DF;EGYPTIAN HIEROGLYPH-142DF;Lo;0;L;;;;;N;;;;; +142E0;EGYPTIAN HIEROGLYPH-142E0;Lo;0;L;;;;;N;;;;; +142E1;EGYPTIAN HIEROGLYPH-142E1;Lo;0;L;;;;;N;;;;; +142E2;EGYPTIAN HIEROGLYPH-142E2;Lo;0;L;;;;;N;;;;; +142E3;EGYPTIAN HIEROGLYPH-142E3;Lo;0;L;;;;;N;;;;; +142E4;EGYPTIAN HIEROGLYPH-142E4;Lo;0;L;;;;;N;;;;; +142E5;EGYPTIAN HIEROGLYPH-142E5;Lo;0;L;;;;;N;;;;; +142E6;EGYPTIAN HIEROGLYPH-142E6;Lo;0;L;;;;;N;;;;; +142E7;EGYPTIAN HIEROGLYPH-142E7;Lo;0;L;;;;;N;;;;; +142E8;EGYPTIAN HIEROGLYPH-142E8;Lo;0;L;;;;;N;;;;; +142E9;EGYPTIAN HIEROGLYPH-142E9;Lo;0;L;;;;;N;;;;; +142EA;EGYPTIAN HIEROGLYPH-142EA;Lo;0;L;;;;;N;;;;; +142EB;EGYPTIAN HIEROGLYPH-142EB;Lo;0;L;;;;;N;;;;; +142EC;EGYPTIAN HIEROGLYPH-142EC;Lo;0;L;;;;;N;;;;; +142ED;EGYPTIAN HIEROGLYPH-142ED;Lo;0;L;;;;;N;;;;; +142EE;EGYPTIAN HIEROGLYPH-142EE;Lo;0;L;;;;;N;;;;; +142EF;EGYPTIAN HIEROGLYPH-142EF;Lo;0;L;;;;;N;;;;; +142F0;EGYPTIAN HIEROGLYPH-142F0;Lo;0;L;;;;;N;;;;; +142F1;EGYPTIAN HIEROGLYPH-142F1;Lo;0;L;;;;;N;;;;; +142F2;EGYPTIAN HIEROGLYPH-142F2;Lo;0;L;;;;;N;;;;; +142F3;EGYPTIAN HIEROGLYPH-142F3;Lo;0;L;;;;;N;;;;; +142F4;EGYPTIAN HIEROGLYPH-142F4;Lo;0;L;;;;;N;;;;; +142F5;EGYPTIAN HIEROGLYPH-142F5;Lo;0;L;;;;;N;;;;; +142F6;EGYPTIAN HIEROGLYPH-142F6;Lo;0;L;;;;;N;;;;; +142F7;EGYPTIAN HIEROGLYPH-142F7;Lo;0;L;;;;;N;;;;; +142F8;EGYPTIAN HIEROGLYPH-142F8;Lo;0;L;;;;;N;;;;; +142F9;EGYPTIAN HIEROGLYPH-142F9;Lo;0;L;;;;;N;;;;; +142FA;EGYPTIAN HIEROGLYPH-142FA;Lo;0;L;;;;;N;;;;; +142FB;EGYPTIAN HIEROGLYPH-142FB;Lo;0;L;;;;;N;;;;; +142FC;EGYPTIAN HIEROGLYPH-142FC;Lo;0;L;;;;;N;;;;; +142FD;EGYPTIAN HIEROGLYPH-142FD;Lo;0;L;;;;;N;;;;; +142FE;EGYPTIAN HIEROGLYPH-142FE;Lo;0;L;;;;;N;;;;; +142FF;EGYPTIAN HIEROGLYPH-142FF;Lo;0;L;;;;;N;;;;; +14300;EGYPTIAN HIEROGLYPH-14300;Lo;0;L;;;;;N;;;;; +14301;EGYPTIAN HIEROGLYPH-14301;Lo;0;L;;;;;N;;;;; +14302;EGYPTIAN HIEROGLYPH-14302;Lo;0;L;;;;;N;;;;; +14303;EGYPTIAN HIEROGLYPH-14303;Lo;0;L;;;;;N;;;;; +14304;EGYPTIAN HIEROGLYPH-14304;Lo;0;L;;;;;N;;;;; +14305;EGYPTIAN HIEROGLYPH-14305;Lo;0;L;;;;;N;;;;; +14306;EGYPTIAN HIEROGLYPH-14306;Lo;0;L;;;;;N;;;;; +14307;EGYPTIAN HIEROGLYPH-14307;Lo;0;L;;;;;N;;;;; +14308;EGYPTIAN HIEROGLYPH-14308;Lo;0;L;;;;;N;;;;; +14309;EGYPTIAN HIEROGLYPH-14309;Lo;0;L;;;;;N;;;;; +1430A;EGYPTIAN HIEROGLYPH-1430A;Lo;0;L;;;;;N;;;;; +1430B;EGYPTIAN HIEROGLYPH-1430B;Lo;0;L;;;;;N;;;;; +1430C;EGYPTIAN HIEROGLYPH-1430C;Lo;0;L;;;;;N;;;;; +1430D;EGYPTIAN HIEROGLYPH-1430D;Lo;0;L;;;;;N;;;;; +1430E;EGYPTIAN HIEROGLYPH-1430E;Lo;0;L;;;;;N;;;;; +1430F;EGYPTIAN HIEROGLYPH-1430F;Lo;0;L;;;;;N;;;;; +14310;EGYPTIAN HIEROGLYPH-14310;Lo;0;L;;;;;N;;;;; +14311;EGYPTIAN HIEROGLYPH-14311;Lo;0;L;;;;;N;;;;; +14312;EGYPTIAN HIEROGLYPH-14312;Lo;0;L;;;;;N;;;;; +14313;EGYPTIAN HIEROGLYPH-14313;Lo;0;L;;;;;N;;;;; +14314;EGYPTIAN HIEROGLYPH-14314;Lo;0;L;;;;;N;;;;; +14315;EGYPTIAN HIEROGLYPH-14315;Lo;0;L;;;;;N;;;;; +14316;EGYPTIAN HIEROGLYPH-14316;Lo;0;L;;;;;N;;;;; +14317;EGYPTIAN HIEROGLYPH-14317;Lo;0;L;;;;;N;;;;; +14318;EGYPTIAN HIEROGLYPH-14318;Lo;0;L;;;;;N;;;;; +14319;EGYPTIAN HIEROGLYPH-14319;Lo;0;L;;;;;N;;;;; +1431A;EGYPTIAN HIEROGLYPH-1431A;Lo;0;L;;;;;N;;;;; +1431B;EGYPTIAN HIEROGLYPH-1431B;Lo;0;L;;;;;N;;;;; +1431C;EGYPTIAN HIEROGLYPH-1431C;Lo;0;L;;;;;N;;;;; +1431D;EGYPTIAN HIEROGLYPH-1431D;Lo;0;L;;;;;N;;;;; +1431E;EGYPTIAN HIEROGLYPH-1431E;Lo;0;L;;;;;N;;;;; +1431F;EGYPTIAN HIEROGLYPH-1431F;Lo;0;L;;;;;N;;;;; +14320;EGYPTIAN HIEROGLYPH-14320;Lo;0;L;;;;;N;;;;; +14321;EGYPTIAN HIEROGLYPH-14321;Lo;0;L;;;;;N;;;;; +14322;EGYPTIAN HIEROGLYPH-14322;Lo;0;L;;;;;N;;;;; +14323;EGYPTIAN HIEROGLYPH-14323;Lo;0;L;;;;;N;;;;; +14324;EGYPTIAN HIEROGLYPH-14324;Lo;0;L;;;;;N;;;;; +14325;EGYPTIAN HIEROGLYPH-14325;Lo;0;L;;;;;N;;;;; +14326;EGYPTIAN HIEROGLYPH-14326;Lo;0;L;;;;;N;;;;; +14327;EGYPTIAN HIEROGLYPH-14327;Lo;0;L;;;;;N;;;;; +14328;EGYPTIAN HIEROGLYPH-14328;Lo;0;L;;;;;N;;;;; +14329;EGYPTIAN HIEROGLYPH-14329;Lo;0;L;;;;;N;;;;; +1432A;EGYPTIAN HIEROGLYPH-1432A;Lo;0;L;;;;;N;;;;; +1432B;EGYPTIAN HIEROGLYPH-1432B;Lo;0;L;;;;;N;;;;; +1432C;EGYPTIAN HIEROGLYPH-1432C;Lo;0;L;;;;;N;;;;; +1432D;EGYPTIAN HIEROGLYPH-1432D;Lo;0;L;;;;;N;;;;; +1432E;EGYPTIAN HIEROGLYPH-1432E;Lo;0;L;;;;;N;;;;; +1432F;EGYPTIAN HIEROGLYPH-1432F;Lo;0;L;;;;;N;;;;; +14330;EGYPTIAN HIEROGLYPH-14330;Lo;0;L;;;;;N;;;;; +14331;EGYPTIAN HIEROGLYPH-14331;Lo;0;L;;;;;N;;;;; +14332;EGYPTIAN HIEROGLYPH-14332;Lo;0;L;;;;;N;;;;; +14333;EGYPTIAN HIEROGLYPH-14333;Lo;0;L;;;;;N;;;;; +14334;EGYPTIAN HIEROGLYPH-14334;Lo;0;L;;;;;N;;;;; +14335;EGYPTIAN HIEROGLYPH-14335;Lo;0;L;;;;;N;;;;; +14336;EGYPTIAN HIEROGLYPH-14336;Lo;0;L;;;;;N;;;;; +14337;EGYPTIAN HIEROGLYPH-14337;Lo;0;L;;;;;N;;;;; +14338;EGYPTIAN HIEROGLYPH-14338;Lo;0;L;;;;;N;;;;; +14339;EGYPTIAN HIEROGLYPH-14339;Lo;0;L;;;;;N;;;;; +1433A;EGYPTIAN HIEROGLYPH-1433A;Lo;0;L;;;;;N;;;;; +1433B;EGYPTIAN HIEROGLYPH-1433B;Lo;0;L;;;;;N;;;;; +1433C;EGYPTIAN HIEROGLYPH-1433C;Lo;0;L;;;;;N;;;;; +1433D;EGYPTIAN HIEROGLYPH-1433D;Lo;0;L;;;;;N;;;;; +1433E;EGYPTIAN HIEROGLYPH-1433E;Lo;0;L;;;;;N;;;;; +1433F;EGYPTIAN HIEROGLYPH-1433F;Lo;0;L;;;;;N;;;;; +14340;EGYPTIAN HIEROGLYPH-14340;Lo;0;L;;;;;N;;;;; +14341;EGYPTIAN HIEROGLYPH-14341;Lo;0;L;;;;;N;;;;; +14342;EGYPTIAN HIEROGLYPH-14342;Lo;0;L;;;;;N;;;;; +14343;EGYPTIAN HIEROGLYPH-14343;Lo;0;L;;;;;N;;;;; +14344;EGYPTIAN HIEROGLYPH-14344;Lo;0;L;;;;;N;;;;; +14345;EGYPTIAN HIEROGLYPH-14345;Lo;0;L;;;;;N;;;;; +14346;EGYPTIAN HIEROGLYPH-14346;Lo;0;L;;;;;N;;;;; +14347;EGYPTIAN HIEROGLYPH-14347;Lo;0;L;;;;;N;;;;; +14348;EGYPTIAN HIEROGLYPH-14348;Lo;0;L;;;;;N;;;;; +14349;EGYPTIAN HIEROGLYPH-14349;Lo;0;L;;;;;N;;;;; +1434A;EGYPTIAN HIEROGLYPH-1434A;Lo;0;L;;;;;N;;;;; +1434B;EGYPTIAN HIEROGLYPH-1434B;Lo;0;L;;;;;N;;;;; +1434C;EGYPTIAN HIEROGLYPH-1434C;Lo;0;L;;;;;N;;;;; +1434D;EGYPTIAN HIEROGLYPH-1434D;Lo;0;L;;;;;N;;;;; +1434E;EGYPTIAN HIEROGLYPH-1434E;Lo;0;L;;;;;N;;;;; +1434F;EGYPTIAN HIEROGLYPH-1434F;Lo;0;L;;;;;N;;;;; +14350;EGYPTIAN HIEROGLYPH-14350;Lo;0;L;;;;;N;;;;; +14351;EGYPTIAN HIEROGLYPH-14351;Lo;0;L;;;;;N;;;;; +14352;EGYPTIAN HIEROGLYPH-14352;Lo;0;L;;;;;N;;;;; +14353;EGYPTIAN HIEROGLYPH-14353;Lo;0;L;;;;;N;;;;; +14354;EGYPTIAN HIEROGLYPH-14354;Lo;0;L;;;;;N;;;;; +14355;EGYPTIAN HIEROGLYPH-14355;Lo;0;L;;;;;N;;;;; +14356;EGYPTIAN HIEROGLYPH-14356;Lo;0;L;;;;;N;;;;; +14357;EGYPTIAN HIEROGLYPH-14357;Lo;0;L;;;;;N;;;;; +14358;EGYPTIAN HIEROGLYPH-14358;Lo;0;L;;;;;N;;;;; +14359;EGYPTIAN HIEROGLYPH-14359;Lo;0;L;;;;;N;;;;; +1435A;EGYPTIAN HIEROGLYPH-1435A;Lo;0;L;;;;;N;;;;; +1435B;EGYPTIAN HIEROGLYPH-1435B;Lo;0;L;;;;;N;;;;; +1435C;EGYPTIAN HIEROGLYPH-1435C;Lo;0;L;;;;;N;;;;; +1435D;EGYPTIAN HIEROGLYPH-1435D;Lo;0;L;;;;;N;;;;; +1435E;EGYPTIAN HIEROGLYPH-1435E;Lo;0;L;;;;;N;;;;; +1435F;EGYPTIAN HIEROGLYPH-1435F;Lo;0;L;;;;;N;;;;; +14360;EGYPTIAN HIEROGLYPH-14360;Lo;0;L;;;;;N;;;;; +14361;EGYPTIAN HIEROGLYPH-14361;Lo;0;L;;;;;N;;;;; +14362;EGYPTIAN HIEROGLYPH-14362;Lo;0;L;;;;;N;;;;; +14363;EGYPTIAN HIEROGLYPH-14363;Lo;0;L;;;;;N;;;;; +14364;EGYPTIAN HIEROGLYPH-14364;Lo;0;L;;;;;N;;;;; +14365;EGYPTIAN HIEROGLYPH-14365;Lo;0;L;;;;;N;;;;; +14366;EGYPTIAN HIEROGLYPH-14366;Lo;0;L;;;;;N;;;;; +14367;EGYPTIAN HIEROGLYPH-14367;Lo;0;L;;;;;N;;;;; +14368;EGYPTIAN HIEROGLYPH-14368;Lo;0;L;;;;;N;;;;; +14369;EGYPTIAN HIEROGLYPH-14369;Lo;0;L;;;;;N;;;;; +1436A;EGYPTIAN HIEROGLYPH-1436A;Lo;0;L;;;;;N;;;;; +1436B;EGYPTIAN HIEROGLYPH-1436B;Lo;0;L;;;;;N;;;;; +1436C;EGYPTIAN HIEROGLYPH-1436C;Lo;0;L;;;;;N;;;;; +1436D;EGYPTIAN HIEROGLYPH-1436D;Lo;0;L;;;;;N;;;;; +1436E;EGYPTIAN HIEROGLYPH-1436E;Lo;0;L;;;;;N;;;;; +1436F;EGYPTIAN HIEROGLYPH-1436F;Lo;0;L;;;;;N;;;;; +14370;EGYPTIAN HIEROGLYPH-14370;Lo;0;L;;;;;N;;;;; +14371;EGYPTIAN HIEROGLYPH-14371;Lo;0;L;;;;;N;;;;; +14372;EGYPTIAN HIEROGLYPH-14372;Lo;0;L;;;;;N;;;;; +14373;EGYPTIAN HIEROGLYPH-14373;Lo;0;L;;;;;N;;;;; +14374;EGYPTIAN HIEROGLYPH-14374;Lo;0;L;;;;;N;;;;; +14375;EGYPTIAN HIEROGLYPH-14375;Lo;0;L;;;;;N;;;;; +14376;EGYPTIAN HIEROGLYPH-14376;Lo;0;L;;;;;N;;;;; +14377;EGYPTIAN HIEROGLYPH-14377;Lo;0;L;;;;;N;;;;; +14378;EGYPTIAN HIEROGLYPH-14378;Lo;0;L;;;;;N;;;;; +14379;EGYPTIAN HIEROGLYPH-14379;Lo;0;L;;;;;N;;;;; +1437A;EGYPTIAN HIEROGLYPH-1437A;Lo;0;L;;;;;N;;;;; +1437B;EGYPTIAN HIEROGLYPH-1437B;Lo;0;L;;;;;N;;;;; +1437C;EGYPTIAN HIEROGLYPH-1437C;Lo;0;L;;;;;N;;;;; +1437D;EGYPTIAN HIEROGLYPH-1437D;Lo;0;L;;;;;N;;;;; +1437E;EGYPTIAN HIEROGLYPH-1437E;Lo;0;L;;;;;N;;;;; +1437F;EGYPTIAN HIEROGLYPH-1437F;Lo;0;L;;;;;N;;;;; +14380;EGYPTIAN HIEROGLYPH-14380;Lo;0;L;;;;;N;;;;; +14381;EGYPTIAN HIEROGLYPH-14381;Lo;0;L;;;;;N;;;;; +14382;EGYPTIAN HIEROGLYPH-14382;Lo;0;L;;;;;N;;;;; +14383;EGYPTIAN HIEROGLYPH-14383;Lo;0;L;;;;;N;;;;; +14384;EGYPTIAN HIEROGLYPH-14384;Lo;0;L;;;;;N;;;;; +14385;EGYPTIAN HIEROGLYPH-14385;Lo;0;L;;;;;N;;;;; +14386;EGYPTIAN HIEROGLYPH-14386;Lo;0;L;;;;;N;;;;; +14387;EGYPTIAN HIEROGLYPH-14387;Lo;0;L;;;;;N;;;;; +14388;EGYPTIAN HIEROGLYPH-14388;Lo;0;L;;;;;N;;;;; +14389;EGYPTIAN HIEROGLYPH-14389;Lo;0;L;;;;;N;;;;; +1438A;EGYPTIAN HIEROGLYPH-1438A;Lo;0;L;;;;;N;;;;; +1438B;EGYPTIAN HIEROGLYPH-1438B;Lo;0;L;;;;;N;;;;; +1438C;EGYPTIAN HIEROGLYPH-1438C;Lo;0;L;;;;;N;;;;; +1438D;EGYPTIAN HIEROGLYPH-1438D;Lo;0;L;;;;;N;;;;; +1438E;EGYPTIAN HIEROGLYPH-1438E;Lo;0;L;;;;;N;;;;; +1438F;EGYPTIAN HIEROGLYPH-1438F;Lo;0;L;;;;;N;;;;; +14390;EGYPTIAN HIEROGLYPH-14390;Lo;0;L;;;;;N;;;;; +14391;EGYPTIAN HIEROGLYPH-14391;Lo;0;L;;;;;N;;;;; +14392;EGYPTIAN HIEROGLYPH-14392;Lo;0;L;;;;;N;;;;; +14393;EGYPTIAN HIEROGLYPH-14393;Lo;0;L;;;;;N;;;;; +14394;EGYPTIAN HIEROGLYPH-14394;Lo;0;L;;;;;N;;;;; +14395;EGYPTIAN HIEROGLYPH-14395;Lo;0;L;;;;;N;;;;; +14396;EGYPTIAN HIEROGLYPH-14396;Lo;0;L;;;;;N;;;;; +14397;EGYPTIAN HIEROGLYPH-14397;Lo;0;L;;;;;N;;;;; +14398;EGYPTIAN HIEROGLYPH-14398;Lo;0;L;;;;;N;;;;; +14399;EGYPTIAN HIEROGLYPH-14399;Lo;0;L;;;;;N;;;;; +1439A;EGYPTIAN HIEROGLYPH-1439A;Lo;0;L;;;;;N;;;;; +1439B;EGYPTIAN HIEROGLYPH-1439B;Lo;0;L;;;;;N;;;;; +1439C;EGYPTIAN HIEROGLYPH-1439C;Lo;0;L;;;;;N;;;;; +1439D;EGYPTIAN HIEROGLYPH-1439D;Lo;0;L;;;;;N;;;;; +1439E;EGYPTIAN HIEROGLYPH-1439E;Lo;0;L;;;;;N;;;;; +1439F;EGYPTIAN HIEROGLYPH-1439F;Lo;0;L;;;;;N;;;;; +143A0;EGYPTIAN HIEROGLYPH-143A0;Lo;0;L;;;;;N;;;;; +143A1;EGYPTIAN HIEROGLYPH-143A1;Lo;0;L;;;;;N;;;;; +143A2;EGYPTIAN HIEROGLYPH-143A2;Lo;0;L;;;;;N;;;;; +143A3;EGYPTIAN HIEROGLYPH-143A3;Lo;0;L;;;;;N;;;;; +143A4;EGYPTIAN HIEROGLYPH-143A4;Lo;0;L;;;;;N;;;;; +143A5;EGYPTIAN HIEROGLYPH-143A5;Lo;0;L;;;;;N;;;;; +143A6;EGYPTIAN HIEROGLYPH-143A6;Lo;0;L;;;;;N;;;;; +143A7;EGYPTIAN HIEROGLYPH-143A7;Lo;0;L;;;;;N;;;;; +143A8;EGYPTIAN HIEROGLYPH-143A8;Lo;0;L;;;;;N;;;;; +143A9;EGYPTIAN HIEROGLYPH-143A9;Lo;0;L;;;;;N;;;;; +143AA;EGYPTIAN HIEROGLYPH-143AA;Lo;0;L;;;;;N;;;;; +143AB;EGYPTIAN HIEROGLYPH-143AB;Lo;0;L;;;;;N;;;;; +143AC;EGYPTIAN HIEROGLYPH-143AC;Lo;0;L;;;;;N;;;;; +143AD;EGYPTIAN HIEROGLYPH-143AD;Lo;0;L;;;;;N;;;;; +143AE;EGYPTIAN HIEROGLYPH-143AE;Lo;0;L;;;;;N;;;;; +143AF;EGYPTIAN HIEROGLYPH-143AF;Lo;0;L;;;;;N;;;;; +143B0;EGYPTIAN HIEROGLYPH-143B0;Lo;0;L;;;;;N;;;;; +143B1;EGYPTIAN HIEROGLYPH-143B1;Lo;0;L;;;;;N;;;;; +143B2;EGYPTIAN HIEROGLYPH-143B2;Lo;0;L;;;;;N;;;;; +143B3;EGYPTIAN HIEROGLYPH-143B3;Lo;0;L;;;;;N;;;;; +143B4;EGYPTIAN HIEROGLYPH-143B4;Lo;0;L;;;;;N;;;;; +143B5;EGYPTIAN HIEROGLYPH-143B5;Lo;0;L;;;;;N;;;;; +143B6;EGYPTIAN HIEROGLYPH-143B6;Lo;0;L;;;;;N;;;;; +143B7;EGYPTIAN HIEROGLYPH-143B7;Lo;0;L;;;;;N;;;;; +143B8;EGYPTIAN HIEROGLYPH-143B8;Lo;0;L;;;;;N;;;;; +143B9;EGYPTIAN HIEROGLYPH-143B9;Lo;0;L;;;;;N;;;;; +143BA;EGYPTIAN HIEROGLYPH-143BA;Lo;0;L;;;;;N;;;;; +143BB;EGYPTIAN HIEROGLYPH-143BB;Lo;0;L;;;;;N;;;;; +143BC;EGYPTIAN HIEROGLYPH-143BC;Lo;0;L;;;;;N;;;;; +143BD;EGYPTIAN HIEROGLYPH-143BD;Lo;0;L;;;;;N;;;;; +143BE;EGYPTIAN HIEROGLYPH-143BE;Lo;0;L;;;;;N;;;;; +143BF;EGYPTIAN HIEROGLYPH-143BF;Lo;0;L;;;;;N;;;;; +143C0;EGYPTIAN HIEROGLYPH-143C0;Lo;0;L;;;;;N;;;;; +143C1;EGYPTIAN HIEROGLYPH-143C1;Lo;0;L;;;;;N;;;;; +143C2;EGYPTIAN HIEROGLYPH-143C2;Lo;0;L;;;;;N;;;;; +143C3;EGYPTIAN HIEROGLYPH-143C3;Lo;0;L;;;;;N;;;;; +143C4;EGYPTIAN HIEROGLYPH-143C4;Lo;0;L;;;;;N;;;;; +143C5;EGYPTIAN HIEROGLYPH-143C5;Lo;0;L;;;;;N;;;;; +143C6;EGYPTIAN HIEROGLYPH-143C6;Lo;0;L;;;;;N;;;;; +143C7;EGYPTIAN HIEROGLYPH-143C7;Lo;0;L;;;;;N;;;;; +143C8;EGYPTIAN HIEROGLYPH-143C8;Lo;0;L;;;;;N;;;;; +143C9;EGYPTIAN HIEROGLYPH-143C9;Lo;0;L;;;;;N;;;;; +143CA;EGYPTIAN HIEROGLYPH-143CA;Lo;0;L;;;;;N;;;;; +143CB;EGYPTIAN HIEROGLYPH-143CB;Lo;0;L;;;;;N;;;;; +143CC;EGYPTIAN HIEROGLYPH-143CC;Lo;0;L;;;;;N;;;;; +143CD;EGYPTIAN HIEROGLYPH-143CD;Lo;0;L;;;;;N;;;;; +143CE;EGYPTIAN HIEROGLYPH-143CE;Lo;0;L;;;;;N;;;;; +143CF;EGYPTIAN HIEROGLYPH-143CF;Lo;0;L;;;;;N;;;;; +143D0;EGYPTIAN HIEROGLYPH-143D0;Lo;0;L;;;;;N;;;;; +143D1;EGYPTIAN HIEROGLYPH-143D1;Lo;0;L;;;;;N;;;;; +143D2;EGYPTIAN HIEROGLYPH-143D2;Lo;0;L;;;;;N;;;;; +143D3;EGYPTIAN HIEROGLYPH-143D3;Lo;0;L;;;;;N;;;;; +143D4;EGYPTIAN HIEROGLYPH-143D4;Lo;0;L;;;;;N;;;;; +143D5;EGYPTIAN HIEROGLYPH-143D5;Lo;0;L;;;;;N;;;;; +143D6;EGYPTIAN HIEROGLYPH-143D6;Lo;0;L;;;;;N;;;;; +143D7;EGYPTIAN HIEROGLYPH-143D7;Lo;0;L;;;;;N;;;;; +143D8;EGYPTIAN HIEROGLYPH-143D8;Lo;0;L;;;;;N;;;;; +143D9;EGYPTIAN HIEROGLYPH-143D9;Lo;0;L;;;;;N;;;;; +143DA;EGYPTIAN HIEROGLYPH-143DA;Lo;0;L;;;;;N;;;;; +143DB;EGYPTIAN HIEROGLYPH-143DB;Lo;0;L;;;;;N;;;;; +143DC;EGYPTIAN HIEROGLYPH-143DC;Lo;0;L;;;;;N;;;;; +143DD;EGYPTIAN HIEROGLYPH-143DD;Lo;0;L;;;;;N;;;;; +143DE;EGYPTIAN HIEROGLYPH-143DE;Lo;0;L;;;;;N;;;;; +143DF;EGYPTIAN HIEROGLYPH-143DF;Lo;0;L;;;;;N;;;;; +143E0;EGYPTIAN HIEROGLYPH-143E0;Lo;0;L;;;;;N;;;;; +143E1;EGYPTIAN HIEROGLYPH-143E1;Lo;0;L;;;;;N;;;;; +143E2;EGYPTIAN HIEROGLYPH-143E2;Lo;0;L;;;;;N;;;;; +143E3;EGYPTIAN HIEROGLYPH-143E3;Lo;0;L;;;;;N;;;;; +143E4;EGYPTIAN HIEROGLYPH-143E4;Lo;0;L;;;;;N;;;;; +143E5;EGYPTIAN HIEROGLYPH-143E5;Lo;0;L;;;;;N;;;;; +143E6;EGYPTIAN HIEROGLYPH-143E6;Lo;0;L;;;;;N;;;;; +143E7;EGYPTIAN HIEROGLYPH-143E7;Lo;0;L;;;;;N;;;;; +143E8;EGYPTIAN HIEROGLYPH-143E8;Lo;0;L;;;;;N;;;;; +143E9;EGYPTIAN HIEROGLYPH-143E9;Lo;0;L;;;;;N;;;;; +143EA;EGYPTIAN HIEROGLYPH-143EA;Lo;0;L;;;;;N;;;;; +143EB;EGYPTIAN HIEROGLYPH-143EB;Lo;0;L;;;;;N;;;;; +143EC;EGYPTIAN HIEROGLYPH-143EC;Lo;0;L;;;;;N;;;;; +143ED;EGYPTIAN HIEROGLYPH-143ED;Lo;0;L;;;;;N;;;;; +143EE;EGYPTIAN HIEROGLYPH-143EE;Lo;0;L;;;;;N;;;;; +143EF;EGYPTIAN HIEROGLYPH-143EF;Lo;0;L;;;;;N;;;;; +143F0;EGYPTIAN HIEROGLYPH-143F0;Lo;0;L;;;;;N;;;;; +143F1;EGYPTIAN HIEROGLYPH-143F1;Lo;0;L;;;;;N;;;;; +143F2;EGYPTIAN HIEROGLYPH-143F2;Lo;0;L;;;;;N;;;;; +143F3;EGYPTIAN HIEROGLYPH-143F3;Lo;0;L;;;;;N;;;;; +143F4;EGYPTIAN HIEROGLYPH-143F4;Lo;0;L;;;;;N;;;;; +143F5;EGYPTIAN HIEROGLYPH-143F5;Lo;0;L;;;;;N;;;;; +143F6;EGYPTIAN HIEROGLYPH-143F6;Lo;0;L;;;;;N;;;;; +143F7;EGYPTIAN HIEROGLYPH-143F7;Lo;0;L;;;;;N;;;;; +143F8;EGYPTIAN HIEROGLYPH-143F8;Lo;0;L;;;;;N;;;;; +143F9;EGYPTIAN HIEROGLYPH-143F9;Lo;0;L;;;;;N;;;;; +143FA;EGYPTIAN HIEROGLYPH-143FA;Lo;0;L;;;;;N;;;;; +14400;ANATOLIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;; +14401;ANATOLIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;; +14402;ANATOLIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;; +14403;ANATOLIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;; +14404;ANATOLIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;; +14405;ANATOLIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;; +14406;ANATOLIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;; +14407;ANATOLIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;; +14408;ANATOLIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;; +14409;ANATOLIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;; +1440A;ANATOLIAN HIEROGLYPH A010A;Lo;0;L;;;;;N;;;;; +1440B;ANATOLIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;; +1440C;ANATOLIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;; +1440D;ANATOLIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;; +1440E;ANATOLIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;; +1440F;ANATOLIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;; +14410;ANATOLIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;; +14411;ANATOLIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;; +14412;ANATOLIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;; +14413;ANATOLIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;; +14414;ANATOLIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;; +14415;ANATOLIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;; +14416;ANATOLIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;; +14417;ANATOLIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;; +14418;ANATOLIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;; +14419;ANATOLIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;; +1441A;ANATOLIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;; +1441B;ANATOLIAN HIEROGLYPH A026A;Lo;0;L;;;;;N;;;;; +1441C;ANATOLIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;; +1441D;ANATOLIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;; +1441E;ANATOLIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;; +1441F;ANATOLIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;; +14420;ANATOLIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;; +14421;ANATOLIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;; +14422;ANATOLIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;; +14423;ANATOLIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;; +14424;ANATOLIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;; +14425;ANATOLIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;; +14426;ANATOLIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;; +14427;ANATOLIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;; +14428;ANATOLIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;; +14429;ANATOLIAN HIEROGLYPH A039A;Lo;0;L;;;;;N;;;;; +1442A;ANATOLIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;; +1442B;ANATOLIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;; +1442C;ANATOLIAN HIEROGLYPH A041A;Lo;0;L;;;;;N;;;;; +1442D;ANATOLIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;; +1442E;ANATOLIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;; +1442F;ANATOLIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;; +14430;ANATOLIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;; +14431;ANATOLIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;; +14432;ANATOLIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;; +14433;ANATOLIAN HIEROGLYPH A046A;Lo;0;L;;;;;N;;;;; +14434;ANATOLIAN HIEROGLYPH A046B;Lo;0;L;;;;;N;;;;; +14435;ANATOLIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;; +14436;ANATOLIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;; +14437;ANATOLIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;; +14438;ANATOLIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;; +14439;ANATOLIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;; +1443A;ANATOLIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;; +1443B;ANATOLIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;; +1443C;ANATOLIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;; +1443D;ANATOLIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;; +1443E;ANATOLIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;; +1443F;ANATOLIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;; +14440;ANATOLIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;; +14441;ANATOLIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;; +14442;ANATOLIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;; +14443;ANATOLIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;; +14444;ANATOLIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;; +14445;ANATOLIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;; +14446;ANATOLIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;; +14447;ANATOLIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;; +14448;ANATOLIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;; +14449;ANATOLIAN HIEROGLYPH A066A;Lo;0;L;;;;;N;;;;; +1444A;ANATOLIAN HIEROGLYPH A066B;Lo;0;L;;;;;N;;;;; +1444B;ANATOLIAN HIEROGLYPH A066C;Lo;0;L;;;;;N;;;;; +1444C;ANATOLIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;; +1444D;ANATOLIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;; +1444E;ANATOLIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;; +1444F;ANATOLIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;; +14450;ANATOLIAN HIEROGLYPH A071;Lo;0;L;;;;;N;;;;; +14451;ANATOLIAN HIEROGLYPH A072;Lo;0;L;;;;;N;;;;; +14452;ANATOLIAN HIEROGLYPH A073;Lo;0;L;;;;;N;;;;; +14453;ANATOLIAN HIEROGLYPH A074;Lo;0;L;;;;;N;;;;; +14454;ANATOLIAN HIEROGLYPH A075;Lo;0;L;;;;;N;;;;; +14455;ANATOLIAN HIEROGLYPH A076;Lo;0;L;;;;;N;;;;; +14456;ANATOLIAN HIEROGLYPH A077;Lo;0;L;;;;;N;;;;; +14457;ANATOLIAN HIEROGLYPH A078;Lo;0;L;;;;;N;;;;; +14458;ANATOLIAN HIEROGLYPH A079;Lo;0;L;;;;;N;;;;; +14459;ANATOLIAN HIEROGLYPH A080;Lo;0;L;;;;;N;;;;; +1445A;ANATOLIAN HIEROGLYPH A081;Lo;0;L;;;;;N;;;;; +1445B;ANATOLIAN HIEROGLYPH A082;Lo;0;L;;;;;N;;;;; +1445C;ANATOLIAN HIEROGLYPH A083;Lo;0;L;;;;;N;;;;; +1445D;ANATOLIAN HIEROGLYPH A084;Lo;0;L;;;;;N;;;;; +1445E;ANATOLIAN HIEROGLYPH A085;Lo;0;L;;;;;N;;;;; +1445F;ANATOLIAN HIEROGLYPH A086;Lo;0;L;;;;;N;;;;; +14460;ANATOLIAN HIEROGLYPH A087;Lo;0;L;;;;;N;;;;; +14461;ANATOLIAN HIEROGLYPH A088;Lo;0;L;;;;;N;;;;; +14462;ANATOLIAN HIEROGLYPH A089;Lo;0;L;;;;;N;;;;; +14463;ANATOLIAN HIEROGLYPH A090;Lo;0;L;;;;;N;;;;; +14464;ANATOLIAN HIEROGLYPH A091;Lo;0;L;;;;;N;;;;; +14465;ANATOLIAN HIEROGLYPH A092;Lo;0;L;;;;;N;;;;; +14466;ANATOLIAN HIEROGLYPH A093;Lo;0;L;;;;;N;;;;; +14467;ANATOLIAN HIEROGLYPH A094;Lo;0;L;;;;;N;;;;; +14468;ANATOLIAN HIEROGLYPH A095;Lo;0;L;;;;;N;;;;; +14469;ANATOLIAN HIEROGLYPH A096;Lo;0;L;;;;;N;;;;; +1446A;ANATOLIAN HIEROGLYPH A097;Lo;0;L;;;;;N;;;;; +1446B;ANATOLIAN HIEROGLYPH A097A;Lo;0;L;;;;;N;;;;; +1446C;ANATOLIAN HIEROGLYPH A098;Lo;0;L;;;;;N;;;;; +1446D;ANATOLIAN HIEROGLYPH A098A;Lo;0;L;;;;;N;;;;; +1446E;ANATOLIAN HIEROGLYPH A099;Lo;0;L;;;;;N;;;;; +1446F;ANATOLIAN HIEROGLYPH A100;Lo;0;L;;;;;N;;;;; +14470;ANATOLIAN HIEROGLYPH A100A;Lo;0;L;;;;;N;;;;; +14471;ANATOLIAN HIEROGLYPH A101;Lo;0;L;;;;;N;;;;; +14472;ANATOLIAN HIEROGLYPH A101A;Lo;0;L;;;;;N;;;;; +14473;ANATOLIAN HIEROGLYPH A102;Lo;0;L;;;;;N;;;;; +14474;ANATOLIAN HIEROGLYPH A102A;Lo;0;L;;;;;N;;;;; +14475;ANATOLIAN HIEROGLYPH A103;Lo;0;L;;;;;N;;;;; +14476;ANATOLIAN HIEROGLYPH A104;Lo;0;L;;;;;N;;;;; +14477;ANATOLIAN HIEROGLYPH A104A;Lo;0;L;;;;;N;;;;; +14478;ANATOLIAN HIEROGLYPH A104B;Lo;0;L;;;;;N;;;;; +14479;ANATOLIAN HIEROGLYPH A104C;Lo;0;L;;;;;N;;;;; +1447A;ANATOLIAN HIEROGLYPH A105;Lo;0;L;;;;;N;;;;; +1447B;ANATOLIAN HIEROGLYPH A105A;Lo;0;L;;;;;N;;;;; +1447C;ANATOLIAN HIEROGLYPH A105B;Lo;0;L;;;;;N;;;;; +1447D;ANATOLIAN HIEROGLYPH A106;Lo;0;L;;;;;N;;;;; +1447E;ANATOLIAN HIEROGLYPH A107;Lo;0;L;;;;;N;;;;; +1447F;ANATOLIAN HIEROGLYPH A107A;Lo;0;L;;;;;N;;;;; +14480;ANATOLIAN HIEROGLYPH A107B;Lo;0;L;;;;;N;;;;; +14481;ANATOLIAN HIEROGLYPH A107C;Lo;0;L;;;;;N;;;;; +14482;ANATOLIAN HIEROGLYPH A108;Lo;0;L;;;;;N;;;;; +14483;ANATOLIAN HIEROGLYPH A109;Lo;0;L;;;;;N;;;;; +14484;ANATOLIAN HIEROGLYPH A110;Lo;0;L;;;;;N;;;;; +14485;ANATOLIAN HIEROGLYPH A110A;Lo;0;L;;;;;N;;;;; +14486;ANATOLIAN HIEROGLYPH A110B;Lo;0;L;;;;;N;;;;; +14487;ANATOLIAN HIEROGLYPH A111;Lo;0;L;;;;;N;;;;; +14488;ANATOLIAN HIEROGLYPH A112;Lo;0;L;;;;;N;;;;; +14489;ANATOLIAN HIEROGLYPH A113;Lo;0;L;;;;;N;;;;; +1448A;ANATOLIAN HIEROGLYPH A114;Lo;0;L;;;;;N;;;;; +1448B;ANATOLIAN HIEROGLYPH A115;Lo;0;L;;;;;N;;;;; +1448C;ANATOLIAN HIEROGLYPH A115A;Lo;0;L;;;;;N;;;;; +1448D;ANATOLIAN HIEROGLYPH A116;Lo;0;L;;;;;N;;;;; +1448E;ANATOLIAN HIEROGLYPH A117;Lo;0;L;;;;;N;;;;; +1448F;ANATOLIAN HIEROGLYPH A118;Lo;0;L;;;;;N;;;;; +14490;ANATOLIAN HIEROGLYPH A119;Lo;0;L;;;;;N;;;;; +14491;ANATOLIAN HIEROGLYPH A120;Lo;0;L;;;;;N;;;;; +14492;ANATOLIAN HIEROGLYPH A121;Lo;0;L;;;;;N;;;;; +14493;ANATOLIAN HIEROGLYPH A122;Lo;0;L;;;;;N;;;;; +14494;ANATOLIAN HIEROGLYPH A123;Lo;0;L;;;;;N;;;;; +14495;ANATOLIAN HIEROGLYPH A124;Lo;0;L;;;;;N;;;;; +14496;ANATOLIAN HIEROGLYPH A125;Lo;0;L;;;;;N;;;;; +14497;ANATOLIAN HIEROGLYPH A125A;Lo;0;L;;;;;N;;;;; +14498;ANATOLIAN HIEROGLYPH A126;Lo;0;L;;;;;N;;;;; +14499;ANATOLIAN HIEROGLYPH A127;Lo;0;L;;;;;N;;;;; +1449A;ANATOLIAN HIEROGLYPH A128;Lo;0;L;;;;;N;;;;; +1449B;ANATOLIAN HIEROGLYPH A129;Lo;0;L;;;;;N;;;;; +1449C;ANATOLIAN HIEROGLYPH A130;Lo;0;L;;;;;N;;;;; +1449D;ANATOLIAN HIEROGLYPH A131;Lo;0;L;;;;;N;;;;; +1449E;ANATOLIAN HIEROGLYPH A132;Lo;0;L;;;;;N;;;;; +1449F;ANATOLIAN HIEROGLYPH A133;Lo;0;L;;;;;N;;;;; +144A0;ANATOLIAN HIEROGLYPH A134;Lo;0;L;;;;;N;;;;; +144A1;ANATOLIAN HIEROGLYPH A135;Lo;0;L;;;;;N;;;;; +144A2;ANATOLIAN HIEROGLYPH A135A;Lo;0;L;;;;;N;;;;; +144A3;ANATOLIAN HIEROGLYPH A136;Lo;0;L;;;;;N;;;;; +144A4;ANATOLIAN HIEROGLYPH A137;Lo;0;L;;;;;N;;;;; +144A5;ANATOLIAN HIEROGLYPH A138;Lo;0;L;;;;;N;;;;; +144A6;ANATOLIAN HIEROGLYPH A139;Lo;0;L;;;;;N;;;;; +144A7;ANATOLIAN HIEROGLYPH A140;Lo;0;L;;;;;N;;;;; +144A8;ANATOLIAN HIEROGLYPH A141;Lo;0;L;;;;;N;;;;; +144A9;ANATOLIAN HIEROGLYPH A142;Lo;0;L;;;;;N;;;;; +144AA;ANATOLIAN HIEROGLYPH A143;Lo;0;L;;;;;N;;;;; +144AB;ANATOLIAN HIEROGLYPH A144;Lo;0;L;;;;;N;;;;; +144AC;ANATOLIAN HIEROGLYPH A145;Lo;0;L;;;;;N;;;;; +144AD;ANATOLIAN HIEROGLYPH A146;Lo;0;L;;;;;N;;;;; +144AE;ANATOLIAN HIEROGLYPH A147;Lo;0;L;;;;;N;;;;; +144AF;ANATOLIAN HIEROGLYPH A148;Lo;0;L;;;;;N;;;;; +144B0;ANATOLIAN HIEROGLYPH A149;Lo;0;L;;;;;N;;;;; +144B1;ANATOLIAN HIEROGLYPH A150;Lo;0;L;;;;;N;;;;; +144B2;ANATOLIAN HIEROGLYPH A151;Lo;0;L;;;;;N;;;;; +144B3;ANATOLIAN HIEROGLYPH A152;Lo;0;L;;;;;N;;;;; +144B4;ANATOLIAN HIEROGLYPH A153;Lo;0;L;;;;;N;;;;; +144B5;ANATOLIAN HIEROGLYPH A154;Lo;0;L;;;;;N;;;;; +144B6;ANATOLIAN HIEROGLYPH A155;Lo;0;L;;;;;N;;;;; +144B7;ANATOLIAN HIEROGLYPH A156;Lo;0;L;;;;;N;;;;; +144B8;ANATOLIAN HIEROGLYPH A157;Lo;0;L;;;;;N;;;;; +144B9;ANATOLIAN HIEROGLYPH A158;Lo;0;L;;;;;N;;;;; +144BA;ANATOLIAN HIEROGLYPH A159;Lo;0;L;;;;;N;;;;; +144BB;ANATOLIAN HIEROGLYPH A160;Lo;0;L;;;;;N;;;;; +144BC;ANATOLIAN HIEROGLYPH A161;Lo;0;L;;;;;N;;;;; +144BD;ANATOLIAN HIEROGLYPH A162;Lo;0;L;;;;;N;;;;; +144BE;ANATOLIAN HIEROGLYPH A163;Lo;0;L;;;;;N;;;;; +144BF;ANATOLIAN HIEROGLYPH A164;Lo;0;L;;;;;N;;;;; +144C0;ANATOLIAN HIEROGLYPH A165;Lo;0;L;;;;;N;;;;; +144C1;ANATOLIAN HIEROGLYPH A166;Lo;0;L;;;;;N;;;;; +144C2;ANATOLIAN HIEROGLYPH A167;Lo;0;L;;;;;N;;;;; +144C3;ANATOLIAN HIEROGLYPH A168;Lo;0;L;;;;;N;;;;; +144C4;ANATOLIAN HIEROGLYPH A169;Lo;0;L;;;;;N;;;;; +144C5;ANATOLIAN HIEROGLYPH A170;Lo;0;L;;;;;N;;;;; +144C6;ANATOLIAN HIEROGLYPH A171;Lo;0;L;;;;;N;;;;; +144C7;ANATOLIAN HIEROGLYPH A172;Lo;0;L;;;;;N;;;;; +144C8;ANATOLIAN HIEROGLYPH A173;Lo;0;L;;;;;N;;;;; +144C9;ANATOLIAN HIEROGLYPH A174;Lo;0;L;;;;;N;;;;; +144CA;ANATOLIAN HIEROGLYPH A175;Lo;0;L;;;;;N;;;;; +144CB;ANATOLIAN HIEROGLYPH A176;Lo;0;L;;;;;N;;;;; +144CC;ANATOLIAN HIEROGLYPH A177;Lo;0;L;;;;;N;;;;; +144CD;ANATOLIAN HIEROGLYPH A178;Lo;0;L;;;;;N;;;;; +144CE;ANATOLIAN HIEROGLYPH A179;Lo;0;L;;;;;N;;;;; +144CF;ANATOLIAN HIEROGLYPH A180;Lo;0;L;;;;;N;;;;; +144D0;ANATOLIAN HIEROGLYPH A181;Lo;0;L;;;;;N;;;;; +144D1;ANATOLIAN HIEROGLYPH A182;Lo;0;L;;;;;N;;;;; +144D2;ANATOLIAN HIEROGLYPH A183;Lo;0;L;;;;;N;;;;; +144D3;ANATOLIAN HIEROGLYPH A184;Lo;0;L;;;;;N;;;;; +144D4;ANATOLIAN HIEROGLYPH A185;Lo;0;L;;;;;N;;;;; +144D5;ANATOLIAN HIEROGLYPH A186;Lo;0;L;;;;;N;;;;; +144D6;ANATOLIAN HIEROGLYPH A187;Lo;0;L;;;;;N;;;;; +144D7;ANATOLIAN HIEROGLYPH A188;Lo;0;L;;;;;N;;;;; +144D8;ANATOLIAN HIEROGLYPH A189;Lo;0;L;;;;;N;;;;; +144D9;ANATOLIAN HIEROGLYPH A190;Lo;0;L;;;;;N;;;;; +144DA;ANATOLIAN HIEROGLYPH A191;Lo;0;L;;;;;N;;;;; +144DB;ANATOLIAN HIEROGLYPH A192;Lo;0;L;;;;;N;;;;; +144DC;ANATOLIAN HIEROGLYPH A193;Lo;0;L;;;;;N;;;;; +144DD;ANATOLIAN HIEROGLYPH A194;Lo;0;L;;;;;N;;;;; +144DE;ANATOLIAN HIEROGLYPH A195;Lo;0;L;;;;;N;;;;; +144DF;ANATOLIAN HIEROGLYPH A196;Lo;0;L;;;;;N;;;;; +144E0;ANATOLIAN HIEROGLYPH A197;Lo;0;L;;;;;N;;;;; +144E1;ANATOLIAN HIEROGLYPH A198;Lo;0;L;;;;;N;;;;; +144E2;ANATOLIAN HIEROGLYPH A199;Lo;0;L;;;;;N;;;;; +144E3;ANATOLIAN HIEROGLYPH A200;Lo;0;L;;;;;N;;;;; +144E4;ANATOLIAN HIEROGLYPH A201;Lo;0;L;;;;;N;;;;; +144E5;ANATOLIAN HIEROGLYPH A202;Lo;0;L;;;;;N;;;;; +144E6;ANATOLIAN HIEROGLYPH A202A;Lo;0;L;;;;;N;;;;; +144E7;ANATOLIAN HIEROGLYPH A202B;Lo;0;L;;;;;N;;;;; +144E8;ANATOLIAN HIEROGLYPH A203;Lo;0;L;;;;;N;;;;; +144E9;ANATOLIAN HIEROGLYPH A204;Lo;0;L;;;;;N;;;;; +144EA;ANATOLIAN HIEROGLYPH A205;Lo;0;L;;;;;N;;;;; +144EB;ANATOLIAN HIEROGLYPH A206;Lo;0;L;;;;;N;;;;; +144EC;ANATOLIAN HIEROGLYPH A207;Lo;0;L;;;;;N;;;;; +144ED;ANATOLIAN HIEROGLYPH A207A;Lo;0;L;;;;;N;;;;; +144EE;ANATOLIAN HIEROGLYPH A208;Lo;0;L;;;;;N;;;;; +144EF;ANATOLIAN HIEROGLYPH A209;Lo;0;L;;;;;N;;;;; +144F0;ANATOLIAN HIEROGLYPH A209A;Lo;0;L;;;;;N;;;;; +144F1;ANATOLIAN HIEROGLYPH A210;Lo;0;L;;;;;N;;;;; +144F2;ANATOLIAN HIEROGLYPH A211;Lo;0;L;;;;;N;;;;; +144F3;ANATOLIAN HIEROGLYPH A212;Lo;0;L;;;;;N;;;;; +144F4;ANATOLIAN HIEROGLYPH A213;Lo;0;L;;;;;N;;;;; +144F5;ANATOLIAN HIEROGLYPH A214;Lo;0;L;;;;;N;;;;; +144F6;ANATOLIAN HIEROGLYPH A215;Lo;0;L;;;;;N;;;;; +144F7;ANATOLIAN HIEROGLYPH A215A;Lo;0;L;;;;;N;;;;; +144F8;ANATOLIAN HIEROGLYPH A216;Lo;0;L;;;;;N;;;;; +144F9;ANATOLIAN HIEROGLYPH A216A;Lo;0;L;;;;;N;;;;; +144FA;ANATOLIAN HIEROGLYPH A217;Lo;0;L;;;;;N;;;;; +144FB;ANATOLIAN HIEROGLYPH A218;Lo;0;L;;;;;N;;;;; +144FC;ANATOLIAN HIEROGLYPH A219;Lo;0;L;;;;;N;;;;; +144FD;ANATOLIAN HIEROGLYPH A220;Lo;0;L;;;;;N;;;;; +144FE;ANATOLIAN HIEROGLYPH A221;Lo;0;L;;;;;N;;;;; +144FF;ANATOLIAN HIEROGLYPH A222;Lo;0;L;;;;;N;;;;; +14500;ANATOLIAN HIEROGLYPH A223;Lo;0;L;;;;;N;;;;; +14501;ANATOLIAN HIEROGLYPH A224;Lo;0;L;;;;;N;;;;; +14502;ANATOLIAN HIEROGLYPH A225;Lo;0;L;;;;;N;;;;; +14503;ANATOLIAN HIEROGLYPH A226;Lo;0;L;;;;;N;;;;; +14504;ANATOLIAN HIEROGLYPH A227;Lo;0;L;;;;;N;;;;; +14505;ANATOLIAN HIEROGLYPH A227A;Lo;0;L;;;;;N;;;;; +14506;ANATOLIAN HIEROGLYPH A228;Lo;0;L;;;;;N;;;;; +14507;ANATOLIAN HIEROGLYPH A229;Lo;0;L;;;;;N;;;;; +14508;ANATOLIAN HIEROGLYPH A230;Lo;0;L;;;;;N;;;;; +14509;ANATOLIAN HIEROGLYPH A231;Lo;0;L;;;;;N;;;;; +1450A;ANATOLIAN HIEROGLYPH A232;Lo;0;L;;;;;N;;;;; +1450B;ANATOLIAN HIEROGLYPH A233;Lo;0;L;;;;;N;;;;; +1450C;ANATOLIAN HIEROGLYPH A234;Lo;0;L;;;;;N;;;;; +1450D;ANATOLIAN HIEROGLYPH A235;Lo;0;L;;;;;N;;;;; +1450E;ANATOLIAN HIEROGLYPH A236;Lo;0;L;;;;;N;;;;; +1450F;ANATOLIAN HIEROGLYPH A237;Lo;0;L;;;;;N;;;;; +14510;ANATOLIAN HIEROGLYPH A238;Lo;0;L;;;;;N;;;;; +14511;ANATOLIAN HIEROGLYPH A239;Lo;0;L;;;;;N;;;;; +14512;ANATOLIAN HIEROGLYPH A240;Lo;0;L;;;;;N;;;;; +14513;ANATOLIAN HIEROGLYPH A241;Lo;0;L;;;;;N;;;;; +14514;ANATOLIAN HIEROGLYPH A242;Lo;0;L;;;;;N;;;;; +14515;ANATOLIAN HIEROGLYPH A243;Lo;0;L;;;;;N;;;;; +14516;ANATOLIAN HIEROGLYPH A244;Lo;0;L;;;;;N;;;;; +14517;ANATOLIAN HIEROGLYPH A245;Lo;0;L;;;;;N;;;;; +14518;ANATOLIAN HIEROGLYPH A246;Lo;0;L;;;;;N;;;;; +14519;ANATOLIAN HIEROGLYPH A247;Lo;0;L;;;;;N;;;;; +1451A;ANATOLIAN HIEROGLYPH A248;Lo;0;L;;;;;N;;;;; +1451B;ANATOLIAN HIEROGLYPH A249;Lo;0;L;;;;;N;;;;; +1451C;ANATOLIAN HIEROGLYPH A250;Lo;0;L;;;;;N;;;;; +1451D;ANATOLIAN HIEROGLYPH A251;Lo;0;L;;;;;N;;;;; +1451E;ANATOLIAN HIEROGLYPH A252;Lo;0;L;;;;;N;;;;; +1451F;ANATOLIAN HIEROGLYPH A253;Lo;0;L;;;;;N;;;;; +14520;ANATOLIAN HIEROGLYPH A254;Lo;0;L;;;;;N;;;;; +14521;ANATOLIAN HIEROGLYPH A255;Lo;0;L;;;;;N;;;;; +14522;ANATOLIAN HIEROGLYPH A256;Lo;0;L;;;;;N;;;;; +14523;ANATOLIAN HIEROGLYPH A257;Lo;0;L;;;;;N;;;;; +14524;ANATOLIAN HIEROGLYPH A258;Lo;0;L;;;;;N;;;;; +14525;ANATOLIAN HIEROGLYPH A259;Lo;0;L;;;;;N;;;;; +14526;ANATOLIAN HIEROGLYPH A260;Lo;0;L;;;;;N;;;;; +14527;ANATOLIAN HIEROGLYPH A261;Lo;0;L;;;;;N;;;;; +14528;ANATOLIAN HIEROGLYPH A262;Lo;0;L;;;;;N;;;;; +14529;ANATOLIAN HIEROGLYPH A263;Lo;0;L;;;;;N;;;;; +1452A;ANATOLIAN HIEROGLYPH A264;Lo;0;L;;;;;N;;;;; +1452B;ANATOLIAN HIEROGLYPH A265;Lo;0;L;;;;;N;;;;; +1452C;ANATOLIAN HIEROGLYPH A266;Lo;0;L;;;;;N;;;;; +1452D;ANATOLIAN HIEROGLYPH A267;Lo;0;L;;;;;N;;;;; +1452E;ANATOLIAN HIEROGLYPH A267A;Lo;0;L;;;;;N;;;;; +1452F;ANATOLIAN HIEROGLYPH A268;Lo;0;L;;;;;N;;;;; +14530;ANATOLIAN HIEROGLYPH A269;Lo;0;L;;;;;N;;;;; +14531;ANATOLIAN HIEROGLYPH A270;Lo;0;L;;;;;N;;;;; +14532;ANATOLIAN HIEROGLYPH A271;Lo;0;L;;;;;N;;;;; +14533;ANATOLIAN HIEROGLYPH A272;Lo;0;L;;;;;N;;;;; +14534;ANATOLIAN HIEROGLYPH A273;Lo;0;L;;;;;N;;;;; +14535;ANATOLIAN HIEROGLYPH A274;Lo;0;L;;;;;N;;;;; +14536;ANATOLIAN HIEROGLYPH A275;Lo;0;L;;;;;N;;;;; +14537;ANATOLIAN HIEROGLYPH A276;Lo;0;L;;;;;N;;;;; +14538;ANATOLIAN HIEROGLYPH A277;Lo;0;L;;;;;N;;;;; +14539;ANATOLIAN HIEROGLYPH A278;Lo;0;L;;;;;N;;;;; +1453A;ANATOLIAN HIEROGLYPH A279;Lo;0;L;;;;;N;;;;; +1453B;ANATOLIAN HIEROGLYPH A280;Lo;0;L;;;;;N;;;;; +1453C;ANATOLIAN HIEROGLYPH A281;Lo;0;L;;;;;N;;;;; +1453D;ANATOLIAN HIEROGLYPH A282;Lo;0;L;;;;;N;;;;; +1453E;ANATOLIAN HIEROGLYPH A283;Lo;0;L;;;;;N;;;;; +1453F;ANATOLIAN HIEROGLYPH A284;Lo;0;L;;;;;N;;;;; +14540;ANATOLIAN HIEROGLYPH A285;Lo;0;L;;;;;N;;;;; +14541;ANATOLIAN HIEROGLYPH A286;Lo;0;L;;;;;N;;;;; +14542;ANATOLIAN HIEROGLYPH A287;Lo;0;L;;;;;N;;;;; +14543;ANATOLIAN HIEROGLYPH A288;Lo;0;L;;;;;N;;;;; +14544;ANATOLIAN HIEROGLYPH A289;Lo;0;L;;;;;N;;;;; +14545;ANATOLIAN HIEROGLYPH A289A;Lo;0;L;;;;;N;;;;; +14546;ANATOLIAN HIEROGLYPH A290;Lo;0;L;;;;;N;;;;; +14547;ANATOLIAN HIEROGLYPH A291;Lo;0;L;;;;;N;;;;; +14548;ANATOLIAN HIEROGLYPH A292;Lo;0;L;;;;;N;;;;; +14549;ANATOLIAN HIEROGLYPH A293;Lo;0;L;;;;;N;;;;; +1454A;ANATOLIAN HIEROGLYPH A294;Lo;0;L;;;;;N;;;;; +1454B;ANATOLIAN HIEROGLYPH A294A;Lo;0;L;;;;;N;;;;; +1454C;ANATOLIAN HIEROGLYPH A295;Lo;0;L;;;;;N;;;;; +1454D;ANATOLIAN HIEROGLYPH A296;Lo;0;L;;;;;N;;;;; +1454E;ANATOLIAN HIEROGLYPH A297;Lo;0;L;;;;;N;;;;; +1454F;ANATOLIAN HIEROGLYPH A298;Lo;0;L;;;;;N;;;;; +14550;ANATOLIAN HIEROGLYPH A299;Lo;0;L;;;;;N;;;;; +14551;ANATOLIAN HIEROGLYPH A299A;Lo;0;L;;;;;N;;;;; +14552;ANATOLIAN HIEROGLYPH A300;Lo;0;L;;;;;N;;;;; +14553;ANATOLIAN HIEROGLYPH A301;Lo;0;L;;;;;N;;;;; +14554;ANATOLIAN HIEROGLYPH A302;Lo;0;L;;;;;N;;;;; +14555;ANATOLIAN HIEROGLYPH A303;Lo;0;L;;;;;N;;;;; +14556;ANATOLIAN HIEROGLYPH A304;Lo;0;L;;;;;N;;;;; +14557;ANATOLIAN HIEROGLYPH A305;Lo;0;L;;;;;N;;;;; +14558;ANATOLIAN HIEROGLYPH A306;Lo;0;L;;;;;N;;;;; +14559;ANATOLIAN HIEROGLYPH A307;Lo;0;L;;;;;N;;;;; +1455A;ANATOLIAN HIEROGLYPH A308;Lo;0;L;;;;;N;;;;; +1455B;ANATOLIAN HIEROGLYPH A309;Lo;0;L;;;;;N;;;;; +1455C;ANATOLIAN HIEROGLYPH A309A;Lo;0;L;;;;;N;;;;; +1455D;ANATOLIAN HIEROGLYPH A310;Lo;0;L;;;;;N;;;;; +1455E;ANATOLIAN HIEROGLYPH A311;Lo;0;L;;;;;N;;;;; +1455F;ANATOLIAN HIEROGLYPH A312;Lo;0;L;;;;;N;;;;; +14560;ANATOLIAN HIEROGLYPH A313;Lo;0;L;;;;;N;;;;; +14561;ANATOLIAN HIEROGLYPH A314;Lo;0;L;;;;;N;;;;; +14562;ANATOLIAN HIEROGLYPH A315;Lo;0;L;;;;;N;;;;; +14563;ANATOLIAN HIEROGLYPH A316;Lo;0;L;;;;;N;;;;; +14564;ANATOLIAN HIEROGLYPH A317;Lo;0;L;;;;;N;;;;; +14565;ANATOLIAN HIEROGLYPH A318;Lo;0;L;;;;;N;;;;; +14566;ANATOLIAN HIEROGLYPH A319;Lo;0;L;;;;;N;;;;; +14567;ANATOLIAN HIEROGLYPH A320;Lo;0;L;;;;;N;;;;; +14568;ANATOLIAN HIEROGLYPH A321;Lo;0;L;;;;;N;;;;; +14569;ANATOLIAN HIEROGLYPH A322;Lo;0;L;;;;;N;;;;; +1456A;ANATOLIAN HIEROGLYPH A323;Lo;0;L;;;;;N;;;;; +1456B;ANATOLIAN HIEROGLYPH A324;Lo;0;L;;;;;N;;;;; +1456C;ANATOLIAN HIEROGLYPH A325;Lo;0;L;;;;;N;;;;; +1456D;ANATOLIAN HIEROGLYPH A326;Lo;0;L;;;;;N;;;;; +1456E;ANATOLIAN HIEROGLYPH A327;Lo;0;L;;;;;N;;;;; +1456F;ANATOLIAN HIEROGLYPH A328;Lo;0;L;;;;;N;;;;; +14570;ANATOLIAN HIEROGLYPH A329;Lo;0;L;;;;;N;;;;; +14571;ANATOLIAN HIEROGLYPH A329A;Lo;0;L;;;;;N;;;;; +14572;ANATOLIAN HIEROGLYPH A330;Lo;0;L;;;;;N;;;;; +14573;ANATOLIAN HIEROGLYPH A331;Lo;0;L;;;;;N;;;;; +14574;ANATOLIAN HIEROGLYPH A332A;Lo;0;L;;;;;N;;;;; +14575;ANATOLIAN HIEROGLYPH A332B;Lo;0;L;;;;;N;;;;; +14576;ANATOLIAN HIEROGLYPH A332C;Lo;0;L;;;;;N;;;;; +14577;ANATOLIAN HIEROGLYPH A333;Lo;0;L;;;;;N;;;;; +14578;ANATOLIAN HIEROGLYPH A334;Lo;0;L;;;;;N;;;;; +14579;ANATOLIAN HIEROGLYPH A335;Lo;0;L;;;;;N;;;;; +1457A;ANATOLIAN HIEROGLYPH A336;Lo;0;L;;;;;N;;;;; +1457B;ANATOLIAN HIEROGLYPH A336A;Lo;0;L;;;;;N;;;;; +1457C;ANATOLIAN HIEROGLYPH A336B;Lo;0;L;;;;;N;;;;; +1457D;ANATOLIAN HIEROGLYPH A336C;Lo;0;L;;;;;N;;;;; +1457E;ANATOLIAN HIEROGLYPH A337;Lo;0;L;;;;;N;;;;; +1457F;ANATOLIAN HIEROGLYPH A338;Lo;0;L;;;;;N;;;;; +14580;ANATOLIAN HIEROGLYPH A339;Lo;0;L;;;;;N;;;;; +14581;ANATOLIAN HIEROGLYPH A340;Lo;0;L;;;;;N;;;;; +14582;ANATOLIAN HIEROGLYPH A341;Lo;0;L;;;;;N;;;;; +14583;ANATOLIAN HIEROGLYPH A342;Lo;0;L;;;;;N;;;;; +14584;ANATOLIAN HIEROGLYPH A343;Lo;0;L;;;;;N;;;;; +14585;ANATOLIAN HIEROGLYPH A344;Lo;0;L;;;;;N;;;;; +14586;ANATOLIAN HIEROGLYPH A345;Lo;0;L;;;;;N;;;;; +14587;ANATOLIAN HIEROGLYPH A346;Lo;0;L;;;;;N;;;;; +14588;ANATOLIAN HIEROGLYPH A347;Lo;0;L;;;;;N;;;;; +14589;ANATOLIAN HIEROGLYPH A348;Lo;0;L;;;;;N;;;;; +1458A;ANATOLIAN HIEROGLYPH A349;Lo;0;L;;;;;N;;;;; +1458B;ANATOLIAN HIEROGLYPH A350;Lo;0;L;;;;;N;;;;; +1458C;ANATOLIAN HIEROGLYPH A351;Lo;0;L;;;;;N;;;;; +1458D;ANATOLIAN HIEROGLYPH A352;Lo;0;L;;;;;N;;;;; +1458E;ANATOLIAN HIEROGLYPH A353;Lo;0;L;;;;;N;;;;; +1458F;ANATOLIAN HIEROGLYPH A354;Lo;0;L;;;;;N;;;;; +14590;ANATOLIAN HIEROGLYPH A355;Lo;0;L;;;;;N;;;;; +14591;ANATOLIAN HIEROGLYPH A356;Lo;0;L;;;;;N;;;;; +14592;ANATOLIAN HIEROGLYPH A357;Lo;0;L;;;;;N;;;;; +14593;ANATOLIAN HIEROGLYPH A358;Lo;0;L;;;;;N;;;;; +14594;ANATOLIAN HIEROGLYPH A359;Lo;0;L;;;;;N;;;;; +14595;ANATOLIAN HIEROGLYPH A359A;Lo;0;L;;;;;N;;;;; +14596;ANATOLIAN HIEROGLYPH A360;Lo;0;L;;;;;N;;;;; +14597;ANATOLIAN HIEROGLYPH A361;Lo;0;L;;;;;N;;;;; +14598;ANATOLIAN HIEROGLYPH A362;Lo;0;L;;;;;N;;;;; +14599;ANATOLIAN HIEROGLYPH A363;Lo;0;L;;;;;N;;;;; +1459A;ANATOLIAN HIEROGLYPH A364;Lo;0;L;;;;;N;;;;; +1459B;ANATOLIAN HIEROGLYPH A364A;Lo;0;L;;;;;N;;;;; +1459C;ANATOLIAN HIEROGLYPH A365;Lo;0;L;;;;;N;;;;; +1459D;ANATOLIAN HIEROGLYPH A366;Lo;0;L;;;;;N;;;;; +1459E;ANATOLIAN HIEROGLYPH A367;Lo;0;L;;;;;N;;;;; +1459F;ANATOLIAN HIEROGLYPH A368;Lo;0;L;;;;;N;;;;; +145A0;ANATOLIAN HIEROGLYPH A368A;Lo;0;L;;;;;N;;;;; +145A1;ANATOLIAN HIEROGLYPH A369;Lo;0;L;;;;;N;;;;; +145A2;ANATOLIAN HIEROGLYPH A370;Lo;0;L;;;;;N;;;;; +145A3;ANATOLIAN HIEROGLYPH A371;Lo;0;L;;;;;N;;;;; +145A4;ANATOLIAN HIEROGLYPH A371A;Lo;0;L;;;;;N;;;;; +145A5;ANATOLIAN HIEROGLYPH A372;Lo;0;L;;;;;N;;;;; +145A6;ANATOLIAN HIEROGLYPH A373;Lo;0;L;;;;;N;;;;; +145A7;ANATOLIAN HIEROGLYPH A374;Lo;0;L;;;;;N;;;;; +145A8;ANATOLIAN HIEROGLYPH A375;Lo;0;L;;;;;N;;;;; +145A9;ANATOLIAN HIEROGLYPH A376;Lo;0;L;;;;;N;;;;; +145AA;ANATOLIAN HIEROGLYPH A377;Lo;0;L;;;;;N;;;;; +145AB;ANATOLIAN HIEROGLYPH A378;Lo;0;L;;;;;N;;;;; +145AC;ANATOLIAN HIEROGLYPH A379;Lo;0;L;;;;;N;;;;; +145AD;ANATOLIAN HIEROGLYPH A380;Lo;0;L;;;;;N;;;;; +145AE;ANATOLIAN HIEROGLYPH A381;Lo;0;L;;;;;N;;;;; +145AF;ANATOLIAN HIEROGLYPH A381A;Lo;0;L;;;;;N;;;;; +145B0;ANATOLIAN HIEROGLYPH A382;Lo;0;L;;;;;N;;;;; +145B1;ANATOLIAN HIEROGLYPH A383 RA OR RI;Lo;0;L;;;;;N;;;;; +145B2;ANATOLIAN HIEROGLYPH A383A;Lo;0;L;;;;;N;;;;; +145B3;ANATOLIAN HIEROGLYPH A384;Lo;0;L;;;;;N;;;;; +145B4;ANATOLIAN HIEROGLYPH A385;Lo;0;L;;;;;N;;;;; +145B5;ANATOLIAN HIEROGLYPH A386;Lo;0;L;;;;;N;;;;; +145B6;ANATOLIAN HIEROGLYPH A386A;Lo;0;L;;;;;N;;;;; +145B7;ANATOLIAN HIEROGLYPH A387;Lo;0;L;;;;;N;;;;; +145B8;ANATOLIAN HIEROGLYPH A388;Lo;0;L;;;;;N;;;;; +145B9;ANATOLIAN HIEROGLYPH A389;Lo;0;L;;;;;N;;;;; +145BA;ANATOLIAN HIEROGLYPH A390;Lo;0;L;;;;;N;;;;; +145BB;ANATOLIAN HIEROGLYPH A391;Lo;0;L;;;;;N;;;;; +145BC;ANATOLIAN HIEROGLYPH A392;Lo;0;L;;;;;N;;;;; +145BD;ANATOLIAN HIEROGLYPH A393 EIGHT;Lo;0;L;;;;;N;;;;; +145BE;ANATOLIAN HIEROGLYPH A394;Lo;0;L;;;;;N;;;;; +145BF;ANATOLIAN HIEROGLYPH A395;Lo;0;L;;;;;N;;;;; +145C0;ANATOLIAN HIEROGLYPH A396;Lo;0;L;;;;;N;;;;; +145C1;ANATOLIAN HIEROGLYPH A397;Lo;0;L;;;;;N;;;;; +145C2;ANATOLIAN HIEROGLYPH A398;Lo;0;L;;;;;N;;;;; +145C3;ANATOLIAN HIEROGLYPH A399;Lo;0;L;;;;;N;;;;; +145C4;ANATOLIAN HIEROGLYPH A400;Lo;0;L;;;;;N;;;;; +145C5;ANATOLIAN HIEROGLYPH A401;Lo;0;L;;;;;N;;;;; +145C6;ANATOLIAN HIEROGLYPH A402;Lo;0;L;;;;;N;;;;; +145C7;ANATOLIAN HIEROGLYPH A403;Lo;0;L;;;;;N;;;;; +145C8;ANATOLIAN HIEROGLYPH A404;Lo;0;L;;;;;N;;;;; +145C9;ANATOLIAN HIEROGLYPH A405;Lo;0;L;;;;;N;;;;; +145CA;ANATOLIAN HIEROGLYPH A406;Lo;0;L;;;;;N;;;;; +145CB;ANATOLIAN HIEROGLYPH A407;Lo;0;L;;;;;N;;;;; +145CC;ANATOLIAN HIEROGLYPH A408;Lo;0;L;;;;;N;;;;; +145CD;ANATOLIAN HIEROGLYPH A409;Lo;0;L;;;;;N;;;;; +145CE;ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; +145CF;ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK;Lo;0;L;;;;;N;;;;; +145D0;ANATOLIAN HIEROGLYPH A411;Lo;0;L;;;;;N;;;;; +145D1;ANATOLIAN HIEROGLYPH A412;Lo;0;L;;;;;N;;;;; +145D2;ANATOLIAN HIEROGLYPH A413;Lo;0;L;;;;;N;;;;; +145D3;ANATOLIAN HIEROGLYPH A414;Lo;0;L;;;;;N;;;;; +145D4;ANATOLIAN HIEROGLYPH A415;Lo;0;L;;;;;N;;;;; +145D5;ANATOLIAN HIEROGLYPH A416;Lo;0;L;;;;;N;;;;; +145D6;ANATOLIAN HIEROGLYPH A417;Lo;0;L;;;;;N;;;;; +145D7;ANATOLIAN HIEROGLYPH A418;Lo;0;L;;;;;N;;;;; +145D8;ANATOLIAN HIEROGLYPH A419;Lo;0;L;;;;;N;;;;; +145D9;ANATOLIAN HIEROGLYPH A420;Lo;0;L;;;;;N;;;;; +145DA;ANATOLIAN HIEROGLYPH A421;Lo;0;L;;;;;N;;;;; +145DB;ANATOLIAN HIEROGLYPH A422;Lo;0;L;;;;;N;;;;; +145DC;ANATOLIAN HIEROGLYPH A423;Lo;0;L;;;;;N;;;;; +145DD;ANATOLIAN HIEROGLYPH A424;Lo;0;L;;;;;N;;;;; +145DE;ANATOLIAN HIEROGLYPH A425;Lo;0;L;;;;;N;;;;; +145DF;ANATOLIAN HIEROGLYPH A426;Lo;0;L;;;;;N;;;;; +145E0;ANATOLIAN HIEROGLYPH A427;Lo;0;L;;;;;N;;;;; +145E1;ANATOLIAN HIEROGLYPH A428;Lo;0;L;;;;;N;;;;; +145E2;ANATOLIAN HIEROGLYPH A429;Lo;0;L;;;;;N;;;;; +145E3;ANATOLIAN HIEROGLYPH A430;Lo;0;L;;;;;N;;;;; +145E4;ANATOLIAN HIEROGLYPH A431;Lo;0;L;;;;;N;;;;; +145E5;ANATOLIAN HIEROGLYPH A432;Lo;0;L;;;;;N;;;;; +145E6;ANATOLIAN HIEROGLYPH A433;Lo;0;L;;;;;N;;;;; +145E7;ANATOLIAN HIEROGLYPH A434;Lo;0;L;;;;;N;;;;; +145E8;ANATOLIAN HIEROGLYPH A435;Lo;0;L;;;;;N;;;;; +145E9;ANATOLIAN HIEROGLYPH A436;Lo;0;L;;;;;N;;;;; +145EA;ANATOLIAN HIEROGLYPH A437;Lo;0;L;;;;;N;;;;; +145EB;ANATOLIAN HIEROGLYPH A438;Lo;0;L;;;;;N;;;;; +145EC;ANATOLIAN HIEROGLYPH A439;Lo;0;L;;;;;N;;;;; +145ED;ANATOLIAN HIEROGLYPH A440;Lo;0;L;;;;;N;;;;; +145EE;ANATOLIAN HIEROGLYPH A441;Lo;0;L;;;;;N;;;;; +145EF;ANATOLIAN HIEROGLYPH A442;Lo;0;L;;;;;N;;;;; +145F0;ANATOLIAN HIEROGLYPH A443;Lo;0;L;;;;;N;;;;; +145F1;ANATOLIAN HIEROGLYPH A444;Lo;0;L;;;;;N;;;;; +145F2;ANATOLIAN HIEROGLYPH A445;Lo;0;L;;;;;N;;;;; +145F3;ANATOLIAN HIEROGLYPH A446;Lo;0;L;;;;;N;;;;; +145F4;ANATOLIAN HIEROGLYPH A447;Lo;0;L;;;;;N;;;;; +145F5;ANATOLIAN HIEROGLYPH A448;Lo;0;L;;;;;N;;;;; +145F6;ANATOLIAN HIEROGLYPH A449;Lo;0;L;;;;;N;;;;; +145F7;ANATOLIAN HIEROGLYPH A450;Lo;0;L;;;;;N;;;;; +145F8;ANATOLIAN HIEROGLYPH A450A;Lo;0;L;;;;;N;;;;; +145F9;ANATOLIAN HIEROGLYPH A451;Lo;0;L;;;;;N;;;;; +145FA;ANATOLIAN HIEROGLYPH A452;Lo;0;L;;;;;N;;;;; +145FB;ANATOLIAN HIEROGLYPH A453;Lo;0;L;;;;;N;;;;; +145FC;ANATOLIAN HIEROGLYPH A454;Lo;0;L;;;;;N;;;;; +145FD;ANATOLIAN HIEROGLYPH A455;Lo;0;L;;;;;N;;;;; +145FE;ANATOLIAN HIEROGLYPH A456;Lo;0;L;;;;;N;;;;; +145FF;ANATOLIAN HIEROGLYPH A457;Lo;0;L;;;;;N;;;;; +14600;ANATOLIAN HIEROGLYPH A457A;Lo;0;L;;;;;N;;;;; +14601;ANATOLIAN HIEROGLYPH A458;Lo;0;L;;;;;N;;;;; +14602;ANATOLIAN HIEROGLYPH A459;Lo;0;L;;;;;N;;;;; +14603;ANATOLIAN HIEROGLYPH A460;Lo;0;L;;;;;N;;;;; +14604;ANATOLIAN HIEROGLYPH A461;Lo;0;L;;;;;N;;;;; +14605;ANATOLIAN HIEROGLYPH A462;Lo;0;L;;;;;N;;;;; +14606;ANATOLIAN HIEROGLYPH A463;Lo;0;L;;;;;N;;;;; +14607;ANATOLIAN HIEROGLYPH A464;Lo;0;L;;;;;N;;;;; +14608;ANATOLIAN HIEROGLYPH A465;Lo;0;L;;;;;N;;;;; +14609;ANATOLIAN HIEROGLYPH A466;Lo;0;L;;;;;N;;;;; +1460A;ANATOLIAN HIEROGLYPH A467;Lo;0;L;;;;;N;;;;; +1460B;ANATOLIAN HIEROGLYPH A468;Lo;0;L;;;;;N;;;;; +1460C;ANATOLIAN HIEROGLYPH A469;Lo;0;L;;;;;N;;;;; +1460D;ANATOLIAN HIEROGLYPH A470;Lo;0;L;;;;;N;;;;; +1460E;ANATOLIAN HIEROGLYPH A471;Lo;0;L;;;;;N;;;;; +1460F;ANATOLIAN HIEROGLYPH A472;Lo;0;L;;;;;N;;;;; +14610;ANATOLIAN HIEROGLYPH A473;Lo;0;L;;;;;N;;;;; +14611;ANATOLIAN HIEROGLYPH A474;Lo;0;L;;;;;N;;;;; +14612;ANATOLIAN HIEROGLYPH A475;Lo;0;L;;;;;N;;;;; +14613;ANATOLIAN HIEROGLYPH A476;Lo;0;L;;;;;N;;;;; +14614;ANATOLIAN HIEROGLYPH A477;Lo;0;L;;;;;N;;;;; +14615;ANATOLIAN HIEROGLYPH A478;Lo;0;L;;;;;N;;;;; +14616;ANATOLIAN HIEROGLYPH A479;Lo;0;L;;;;;N;;;;; +14617;ANATOLIAN HIEROGLYPH A480;Lo;0;L;;;;;N;;;;; +14618;ANATOLIAN HIEROGLYPH A481;Lo;0;L;;;;;N;;;;; +14619;ANATOLIAN HIEROGLYPH A482;Lo;0;L;;;;;N;;;;; +1461A;ANATOLIAN HIEROGLYPH A483;Lo;0;L;;;;;N;;;;; +1461B;ANATOLIAN HIEROGLYPH A484;Lo;0;L;;;;;N;;;;; +1461C;ANATOLIAN HIEROGLYPH A485;Lo;0;L;;;;;N;;;;; +1461D;ANATOLIAN HIEROGLYPH A486;Lo;0;L;;;;;N;;;;; +1461E;ANATOLIAN HIEROGLYPH A487;Lo;0;L;;;;;N;;;;; +1461F;ANATOLIAN HIEROGLYPH A488;Lo;0;L;;;;;N;;;;; +14620;ANATOLIAN HIEROGLYPH A489;Lo;0;L;;;;;N;;;;; +14621;ANATOLIAN HIEROGLYPH A490;Lo;0;L;;;;;N;;;;; +14622;ANATOLIAN HIEROGLYPH A491;Lo;0;L;;;;;N;;;;; +14623;ANATOLIAN HIEROGLYPH A492;Lo;0;L;;;;;N;;;;; +14624;ANATOLIAN HIEROGLYPH A493;Lo;0;L;;;;;N;;;;; +14625;ANATOLIAN HIEROGLYPH A494;Lo;0;L;;;;;N;;;;; +14626;ANATOLIAN HIEROGLYPH A495;Lo;0;L;;;;;N;;;;; +14627;ANATOLIAN HIEROGLYPH A496;Lo;0;L;;;;;N;;;;; +14628;ANATOLIAN HIEROGLYPH A497;Lo;0;L;;;;;N;;;;; +14629;ANATOLIAN HIEROGLYPH A501;Lo;0;L;;;;;N;;;;; +1462A;ANATOLIAN HIEROGLYPH A502;Lo;0;L;;;;;N;;;;; +1462B;ANATOLIAN HIEROGLYPH A503;Lo;0;L;;;;;N;;;;; +1462C;ANATOLIAN HIEROGLYPH A504;Lo;0;L;;;;;N;;;;; +1462D;ANATOLIAN HIEROGLYPH A505;Lo;0;L;;;;;N;;;;; +1462E;ANATOLIAN HIEROGLYPH A506;Lo;0;L;;;;;N;;;;; +1462F;ANATOLIAN HIEROGLYPH A507;Lo;0;L;;;;;N;;;;; +14630;ANATOLIAN HIEROGLYPH A508;Lo;0;L;;;;;N;;;;; +14631;ANATOLIAN HIEROGLYPH A509;Lo;0;L;;;;;N;;;;; +14632;ANATOLIAN HIEROGLYPH A510;Lo;0;L;;;;;N;;;;; +14633;ANATOLIAN HIEROGLYPH A511;Lo;0;L;;;;;N;;;;; +14634;ANATOLIAN HIEROGLYPH A512;Lo;0;L;;;;;N;;;;; +14635;ANATOLIAN HIEROGLYPH A513;Lo;0;L;;;;;N;;;;; +14636;ANATOLIAN HIEROGLYPH A514;Lo;0;L;;;;;N;;;;; +14637;ANATOLIAN HIEROGLYPH A515;Lo;0;L;;;;;N;;;;; +14638;ANATOLIAN HIEROGLYPH A516;Lo;0;L;;;;;N;;;;; +14639;ANATOLIAN HIEROGLYPH A517;Lo;0;L;;;;;N;;;;; +1463A;ANATOLIAN HIEROGLYPH A518;Lo;0;L;;;;;N;;;;; +1463B;ANATOLIAN HIEROGLYPH A519;Lo;0;L;;;;;N;;;;; +1463C;ANATOLIAN HIEROGLYPH A520;Lo;0;L;;;;;N;;;;; +1463D;ANATOLIAN HIEROGLYPH A521;Lo;0;L;;;;;N;;;;; +1463E;ANATOLIAN HIEROGLYPH A522;Lo;0;L;;;;;N;;;;; +1463F;ANATOLIAN HIEROGLYPH A523;Lo;0;L;;;;;N;;;;; +14640;ANATOLIAN HIEROGLYPH A524;Lo;0;L;;;;;N;;;;; +14641;ANATOLIAN HIEROGLYPH A525;Lo;0;L;;;;;N;;;;; +14642;ANATOLIAN HIEROGLYPH A526;Lo;0;L;;;;;N;;;;; +14643;ANATOLIAN HIEROGLYPH A527;Lo;0;L;;;;;N;;;;; +14644;ANATOLIAN HIEROGLYPH A528;Lo;0;L;;;;;N;;;;; +14645;ANATOLIAN HIEROGLYPH A529;Lo;0;L;;;;;N;;;;; +14646;ANATOLIAN HIEROGLYPH A530;Lo;0;L;;;;;N;;;;; +16100;GURUNG KHEMA LETTER A;Lo;0;L;;;;;N;;;;; +16101;GURUNG KHEMA LETTER KA;Lo;0;L;;;;;N;;;;; +16102;GURUNG KHEMA LETTER KHA;Lo;0;L;;;;;N;;;;; +16103;GURUNG KHEMA LETTER GA;Lo;0;L;;;;;N;;;;; +16104;GURUNG KHEMA LETTER GHA;Lo;0;L;;;;;N;;;;; +16105;GURUNG KHEMA LETTER NGA;Lo;0;L;;;;;N;;;;; +16106;GURUNG KHEMA LETTER CA;Lo;0;L;;;;;N;;;;; +16107;GURUNG KHEMA LETTER CHA;Lo;0;L;;;;;N;;;;; +16108;GURUNG KHEMA LETTER JA;Lo;0;L;;;;;N;;;;; +16109;GURUNG KHEMA LETTER JHA;Lo;0;L;;;;;N;;;;; +1610A;GURUNG KHEMA LETTER HA;Lo;0;L;;;;;N;;;;; +1610B;GURUNG KHEMA LETTER TTA;Lo;0;L;;;;;N;;;;; +1610C;GURUNG KHEMA LETTER TTHA;Lo;0;L;;;;;N;;;;; +1610D;GURUNG KHEMA LETTER DDA;Lo;0;L;;;;;N;;;;; +1610E;GURUNG KHEMA LETTER DDHA;Lo;0;L;;;;;N;;;;; +1610F;GURUNG KHEMA LETTER VA;Lo;0;L;;;;;N;;;;; +16110;GURUNG KHEMA LETTER TA;Lo;0;L;;;;;N;;;;; +16111;GURUNG KHEMA LETTER THA;Lo;0;L;;;;;N;;;;; +16112;GURUNG KHEMA LETTER DA;Lo;0;L;;;;;N;;;;; +16113;GURUNG KHEMA LETTER DHA;Lo;0;L;;;;;N;;;;; +16114;GURUNG KHEMA LETTER NA;Lo;0;L;;;;;N;;;;; +16115;GURUNG KHEMA LETTER PA;Lo;0;L;;;;;N;;;;; +16116;GURUNG KHEMA LETTER PHA;Lo;0;L;;;;;N;;;;; +16117;GURUNG KHEMA LETTER BA;Lo;0;L;;;;;N;;;;; +16118;GURUNG KHEMA LETTER BHA;Lo;0;L;;;;;N;;;;; +16119;GURUNG KHEMA LETTER MA;Lo;0;L;;;;;N;;;;; +1611A;GURUNG KHEMA LETTER YA;Lo;0;L;;;;;N;;;;; +1611B;GURUNG KHEMA LETTER RA;Lo;0;L;;;;;N;;;;; +1611C;GURUNG KHEMA LETTER LA;Lo;0;L;;;;;N;;;;; +1611D;GURUNG KHEMA LETTER SA;Lo;0;L;;;;;N;;;;; +1611E;GURUNG KHEMA VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +1611F;GURUNG KHEMA VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +16120;GURUNG KHEMA VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +16121;GURUNG KHEMA VOWEL SIGN U;Mn;0;NSM;1611E 1611E;;;;N;;;;; +16122;GURUNG KHEMA VOWEL SIGN UU;Mn;0;NSM;1611E 16129;;;;N;;;;; +16123;GURUNG KHEMA VOWEL SIGN E;Mn;0;NSM;1611E 1611F;;;;N;;;;; +16124;GURUNG KHEMA VOWEL SIGN EE;Mn;0;NSM;16129 1611F;;;;N;;;;; +16125;GURUNG KHEMA VOWEL SIGN AI;Mn;0;NSM;1611E 16120;;;;N;;;;; +16126;GURUNG KHEMA VOWEL SIGN O;Mn;0;NSM;16121 1611F;;;;N;;;;; +16127;GURUNG KHEMA VOWEL SIGN OO;Mn;0;NSM;16122 1611F;;;;N;;;;; +16128;GURUNG KHEMA VOWEL SIGN AU;Mn;0;NSM;16121 16120;;;;N;;;;; +16129;GURUNG KHEMA VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;; +1612A;GURUNG KHEMA CONSONANT SIGN MEDIAL YA;Mc;0;L;;;;;N;;;;; +1612B;GURUNG KHEMA CONSONANT SIGN MEDIAL VA;Mc;0;L;;;;;N;;;;; +1612C;GURUNG KHEMA CONSONANT SIGN MEDIAL HA;Mc;0;L;;;;;N;;;;; +1612D;GURUNG KHEMA SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +1612E;GURUNG KHEMA CONSONANT SIGN MEDIAL RA;Mn;0;NSM;;;;;N;;;;; +1612F;GURUNG KHEMA SIGN THOLHOMA;Mn;9;NSM;;;;;N;;;;; +16130;GURUNG KHEMA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16131;GURUNG KHEMA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16132;GURUNG KHEMA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16133;GURUNG KHEMA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16134;GURUNG KHEMA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16135;GURUNG KHEMA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16136;GURUNG KHEMA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16137;GURUNG KHEMA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16138;GURUNG KHEMA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16139;GURUNG KHEMA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;; +16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;; +16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;; +16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;; +16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;; +16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;; +16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;; +16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;; +16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;; +1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;; +1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;; +1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;; +1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;; +1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;; +16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;; +16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;; +16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;; +16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;; +16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;; +16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;; +16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;; +16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;; +16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;; +16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;; +1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;; +1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;; +1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;; +1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;; +1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;; +1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;; +16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;; +16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;; +16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;; +16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;; +16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;; +16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;; +16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;; +16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;; +16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;; +16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;; +1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;; +1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;; +1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;; +1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;; +1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;; +1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;; +16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;; +16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;; +16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;; +16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;; +16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;; +16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;; +16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;; +16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;; +16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;; +16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;; +1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;; +1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;; +1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;; +1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;; +1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;; +1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;; +16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;; +16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;; +16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;; +16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;; +16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;; +16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;; +16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;; +16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;; +16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;; +16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;; +1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;; +1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;; +1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;; +1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;; +1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;; +1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;; +16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;; +16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;; +16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;; +16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;; +16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;; +16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;; +16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;; +16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;; +16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;; +16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;; +1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;; +1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;; +1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;; +1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;; +1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;; +1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;; +16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;; +16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;; +16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;; +16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;; +16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;; +16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;; +16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;; +16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;; +16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;; +16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;; +1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;; +1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;; +1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;; +1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;; +1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;; +1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;; +16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;; +16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;; +16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;; +16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;; +16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;; +16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;; +16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;; +16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;; +16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;; +16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;; +1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;; +1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;; +1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;; +1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;; +1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;; +1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;; +16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;; +16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;; +16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;; +16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;; +16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;; +16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;; +16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;; +16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;; +16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;; +16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;; +1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;; +1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;; +1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;; +1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;; +1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;; +1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;; +16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;; +16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;; +16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;; +16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;; +16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;; +16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;; +16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;; +16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;; +16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;; +16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;; +1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;; +1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;; +1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;; +1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;; +1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;; +1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;; +168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;; +168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;; +168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;; +168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;; +168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;; +168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;; +168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;; +168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;; +168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;; +168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;; +168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;; +168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;; +168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;; +168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;; +168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;; +168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;; +168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;; +168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;; +168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;; +168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;; +168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;; +168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;; +168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;; +168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;; +168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;; +168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;; +168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;; +168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;; +168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;; +168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;; +168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;; +168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;; +168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;; +168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;; +168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;; +168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;; +168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;; +168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;; +168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;; +168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;; +168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;; +168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;; +168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;; +168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;; +168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;; +168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;; +168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;; +168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;; +168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;; +168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;; +168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;; +168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;; +168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;; +168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;; +168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;; +168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;; +168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;; +168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;; +168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;; +168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;; +168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;; +168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;; +168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;; +168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;; +168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;; +168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;; +168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;; +168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;; +168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;; +168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;; +168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;; +168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;; +168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;; +168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;; +168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;; +168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;; +168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;; +168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;; +168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;; +168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;; +168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;; +168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;; +168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;; +168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;; +168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;; +168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;; +168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;; +168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;; +168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;; +168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;; +168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;; +168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;; +168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;; +168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;; +168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;; +168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;; +16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;; +16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;; +16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;; +16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;; +16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;; +16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;; +16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;; +16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;; +16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;; +16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;; +1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;; +1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;; +1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;; +1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;; +1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;; +1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;; +16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;; +16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;; +16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;; +16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;; +16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;; +16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;; +16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;; +16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;; +16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;; +16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;; +1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;; +1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;; +1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;; +1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;; +1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;; +1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;; +16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;; +16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;; +16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;; +16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;; +16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;; +16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;; +16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;; +16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;; +16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;; +16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;; +1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;; +1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;; +1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;; +1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;; +1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;; +1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;; +16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;; +16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;; +16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;; +16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;; +16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;; +16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;; +16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;; +16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;; +16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;; +16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;; +1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;; +1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;; +1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;; +1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;; +1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;; +1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;; +16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;; +16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;; +16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;; +16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;; +16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;; +16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;; +16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;; +16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;; +16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;; +16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;; +1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;; +1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;; +1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;; +1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;; +1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;; +1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;; +16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;; +16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;; +16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;; +16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;; +16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;; +16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;; +16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;; +16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;; +16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;; +16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;; +1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;; +1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;; +1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;; +1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;; +1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;; +1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;; +16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;; +16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;; +16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;; +16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;; +16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;; +16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;; +16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;; +16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;; +16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;; +16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;; +1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;; +1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;; +1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;; +1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;; +1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;; +1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;; +16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;; +16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;; +16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;; +16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;; +16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;; +16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;; +16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;; +16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;; +16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;; +16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;; +1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;; +1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;; +1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;; +1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;; +1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;; +1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;; +16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;; +16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;; +16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;; +16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;; +16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;; +16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;; +16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;; +16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;; +16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;; +16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;; +1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;; +1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;; +1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;; +1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;; +1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;; +1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;; +16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;; +16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;; +16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;; +16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;; +16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;; +16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;; +16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;; +16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;; +16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;; +16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;; +1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;; +1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;; +1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;; +1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;; +1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;; +1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;; +169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;; +169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;; +169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;; +169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;; +169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;; +169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;; +169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;; +169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;; +169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;; +169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;; +169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;; +169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;; +169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;; +169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;; +169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;; +169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;; +169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;; +169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;; +169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;; +169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;; +169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;; +169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;; +169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;; +169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;; +169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;; +169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;; +169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;; +169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;; +169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;; +169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;; +169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;; +169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;; +169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;; +169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;; +169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;; +169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;; +169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;; +169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;; +169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;; +169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;; +169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;; +169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;; +169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;; +169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;; +169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;; +169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;; +169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;; +169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;; +169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;; +169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;; +169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;; +169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;; +169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;; +169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;; +169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;; +169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;; +169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;; +169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;; +169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;; +169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;; +169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;; +169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;; +169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;; +169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;; +169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;; +169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;; +169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;; +169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;; +169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;; +169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;; +169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;; +169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;; +169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;; +169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;; +169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;; +169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;; +169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;; +169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;; +169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;; +169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;; +169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;; +169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;; +169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;; +169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;; +169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;; +169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;; +169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;; +169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;; +169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;; +169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;; +169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;; +169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;; +169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;; +169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;; +169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;; +169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;; +16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;; +16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;; +16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;; +16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;; +16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;; +16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;; +16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;; +16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;; +16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;; +16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;; +16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;; +16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;; +16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;; +16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;; +16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;; +16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;; +16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;; +16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;; +16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;; +16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;; +16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;; +16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;; +16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;; +16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;; +16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;; +16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;; +16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;; +16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;; +16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;; +16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;; +16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;; +16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;; +16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;; +16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;; +16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;; +16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;; +16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;; +16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;; +16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;; +16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;; +16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;; +16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;; +16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;; +16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;; +16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;; +16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;; +16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;; +16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;; +16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;; +16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;; +16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;; +16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;; +16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;; +16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;; +16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;; +16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;; +16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;; +16A40;MRO LETTER TA;Lo;0;L;;;;;N;;;;; +16A41;MRO LETTER NGI;Lo;0;L;;;;;N;;;;; +16A42;MRO LETTER YO;Lo;0;L;;;;;N;;;;; +16A43;MRO LETTER MIM;Lo;0;L;;;;;N;;;;; +16A44;MRO LETTER BA;Lo;0;L;;;;;N;;;;; +16A45;MRO LETTER DA;Lo;0;L;;;;;N;;;;; +16A46;MRO LETTER A;Lo;0;L;;;;;N;;;;; +16A47;MRO LETTER PHI;Lo;0;L;;;;;N;;;;; +16A48;MRO LETTER KHAI;Lo;0;L;;;;;N;;;;; +16A49;MRO LETTER HAO;Lo;0;L;;;;;N;;;;; +16A4A;MRO LETTER DAI;Lo;0;L;;;;;N;;;;; +16A4B;MRO LETTER CHU;Lo;0;L;;;;;N;;;;; +16A4C;MRO LETTER KEAAE;Lo;0;L;;;;;N;;;;; +16A4D;MRO LETTER OL;Lo;0;L;;;;;N;;;;; +16A4E;MRO LETTER MAEM;Lo;0;L;;;;;N;;;;; +16A4F;MRO LETTER NIN;Lo;0;L;;;;;N;;;;; +16A50;MRO LETTER PA;Lo;0;L;;;;;N;;;;; +16A51;MRO LETTER OO;Lo;0;L;;;;;N;;;;; +16A52;MRO LETTER O;Lo;0;L;;;;;N;;;;; +16A53;MRO LETTER RO;Lo;0;L;;;;;N;;;;; +16A54;MRO LETTER SHI;Lo;0;L;;;;;N;;;;; +16A55;MRO LETTER THEA;Lo;0;L;;;;;N;;;;; +16A56;MRO LETTER EA;Lo;0;L;;;;;N;;;;; +16A57;MRO LETTER WA;Lo;0;L;;;;;N;;;;; +16A58;MRO LETTER E;Lo;0;L;;;;;N;;;;; +16A59;MRO LETTER KO;Lo;0;L;;;;;N;;;;; +16A5A;MRO LETTER LAN;Lo;0;L;;;;;N;;;;; +16A5B;MRO LETTER LA;Lo;0;L;;;;;N;;;;; +16A5C;MRO LETTER HAI;Lo;0;L;;;;;N;;;;; +16A5D;MRO LETTER RI;Lo;0;L;;;;;N;;;;; +16A5E;MRO LETTER TEK;Lo;0;L;;;;;N;;;;; +16A60;MRO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16A61;MRO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16A62;MRO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16A63;MRO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16A64;MRO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16A65;MRO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16A66;MRO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16A67;MRO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16A68;MRO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16A6E;MRO DANDA;Po;0;L;;;;;N;;;;; +16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;; +16A70;TANGSA LETTER OZ;Lo;0;L;;;;;N;;;;; +16A71;TANGSA LETTER OC;Lo;0;L;;;;;N;;;;; +16A72;TANGSA LETTER OQ;Lo;0;L;;;;;N;;;;; +16A73;TANGSA LETTER OX;Lo;0;L;;;;;N;;;;; +16A74;TANGSA LETTER AZ;Lo;0;L;;;;;N;;;;; +16A75;TANGSA LETTER AC;Lo;0;L;;;;;N;;;;; +16A76;TANGSA LETTER AQ;Lo;0;L;;;;;N;;;;; +16A77;TANGSA LETTER AX;Lo;0;L;;;;;N;;;;; +16A78;TANGSA LETTER VZ;Lo;0;L;;;;;N;;;;; +16A79;TANGSA LETTER VC;Lo;0;L;;;;;N;;;;; +16A7A;TANGSA LETTER VQ;Lo;0;L;;;;;N;;;;; +16A7B;TANGSA LETTER VX;Lo;0;L;;;;;N;;;;; +16A7C;TANGSA LETTER EZ;Lo;0;L;;;;;N;;;;; +16A7D;TANGSA LETTER EC;Lo;0;L;;;;;N;;;;; +16A7E;TANGSA LETTER EQ;Lo;0;L;;;;;N;;;;; +16A7F;TANGSA LETTER EX;Lo;0;L;;;;;N;;;;; +16A80;TANGSA LETTER IZ;Lo;0;L;;;;;N;;;;; +16A81;TANGSA LETTER IC;Lo;0;L;;;;;N;;;;; +16A82;TANGSA LETTER IQ;Lo;0;L;;;;;N;;;;; +16A83;TANGSA LETTER IX;Lo;0;L;;;;;N;;;;; +16A84;TANGSA LETTER UZ;Lo;0;L;;;;;N;;;;; +16A85;TANGSA LETTER UC;Lo;0;L;;;;;N;;;;; +16A86;TANGSA LETTER UQ;Lo;0;L;;;;;N;;;;; +16A87;TANGSA LETTER UX;Lo;0;L;;;;;N;;;;; +16A88;TANGSA LETTER AWZ;Lo;0;L;;;;;N;;;;; +16A89;TANGSA LETTER AWC;Lo;0;L;;;;;N;;;;; +16A8A;TANGSA LETTER AWQ;Lo;0;L;;;;;N;;;;; +16A8B;TANGSA LETTER AWX;Lo;0;L;;;;;N;;;;; +16A8C;TANGSA LETTER UIZ;Lo;0;L;;;;;N;;;;; +16A8D;TANGSA LETTER UIC;Lo;0;L;;;;;N;;;;; +16A8E;TANGSA LETTER UIQ;Lo;0;L;;;;;N;;;;; +16A8F;TANGSA LETTER UIX;Lo;0;L;;;;;N;;;;; +16A90;TANGSA LETTER FINAL NG;Lo;0;L;;;;;N;;;;; +16A91;TANGSA LETTER LONG UEX;Lo;0;L;;;;;N;;;;; +16A92;TANGSA LETTER SHORT UEZ;Lo;0;L;;;;;N;;;;; +16A93;TANGSA LETTER SHORT AWX;Lo;0;L;;;;;N;;;;; +16A94;TANGSA LETTER UEC;Lo;0;L;;;;;N;;;;; +16A95;TANGSA LETTER UEZ;Lo;0;L;;;;;N;;;;; +16A96;TANGSA LETTER UEQ;Lo;0;L;;;;;N;;;;; +16A97;TANGSA LETTER UEX;Lo;0;L;;;;;N;;;;; +16A98;TANGSA LETTER UIUZ;Lo;0;L;;;;;N;;;;; +16A99;TANGSA LETTER UIUC;Lo;0;L;;;;;N;;;;; +16A9A;TANGSA LETTER UIUQ;Lo;0;L;;;;;N;;;;; +16A9B;TANGSA LETTER UIUX;Lo;0;L;;;;;N;;;;; +16A9C;TANGSA LETTER MZ;Lo;0;L;;;;;N;;;;; +16A9D;TANGSA LETTER MC;Lo;0;L;;;;;N;;;;; +16A9E;TANGSA LETTER MQ;Lo;0;L;;;;;N;;;;; +16A9F;TANGSA LETTER MX;Lo;0;L;;;;;N;;;;; +16AA0;TANGSA LETTER KA;Lo;0;L;;;;;N;;;;; +16AA1;TANGSA LETTER KHA;Lo;0;L;;;;;N;;;;; +16AA2;TANGSA LETTER GA;Lo;0;L;;;;;N;;;;; +16AA3;TANGSA LETTER NGA;Lo;0;L;;;;;N;;;;; +16AA4;TANGSA LETTER SA;Lo;0;L;;;;;N;;;;; +16AA5;TANGSA LETTER YA;Lo;0;L;;;;;N;;;;; +16AA6;TANGSA LETTER WA;Lo;0;L;;;;;N;;;;; +16AA7;TANGSA LETTER PA;Lo;0;L;;;;;N;;;;; +16AA8;TANGSA LETTER NYA;Lo;0;L;;;;;N;;;;; +16AA9;TANGSA LETTER PHA;Lo;0;L;;;;;N;;;;; +16AAA;TANGSA LETTER BA;Lo;0;L;;;;;N;;;;; +16AAB;TANGSA LETTER MA;Lo;0;L;;;;;N;;;;; +16AAC;TANGSA LETTER NA;Lo;0;L;;;;;N;;;;; +16AAD;TANGSA LETTER HA;Lo;0;L;;;;;N;;;;; +16AAE;TANGSA LETTER LA;Lo;0;L;;;;;N;;;;; +16AAF;TANGSA LETTER HTA;Lo;0;L;;;;;N;;;;; +16AB0;TANGSA LETTER TA;Lo;0;L;;;;;N;;;;; +16AB1;TANGSA LETTER DA;Lo;0;L;;;;;N;;;;; +16AB2;TANGSA LETTER RA;Lo;0;L;;;;;N;;;;; +16AB3;TANGSA LETTER NHA;Lo;0;L;;;;;N;;;;; +16AB4;TANGSA LETTER SHA;Lo;0;L;;;;;N;;;;; +16AB5;TANGSA LETTER CA;Lo;0;L;;;;;N;;;;; +16AB6;TANGSA LETTER TSA;Lo;0;L;;;;;N;;;;; +16AB7;TANGSA LETTER GHA;Lo;0;L;;;;;N;;;;; +16AB8;TANGSA LETTER HTTA;Lo;0;L;;;;;N;;;;; +16AB9;TANGSA LETTER THA;Lo;0;L;;;;;N;;;;; +16ABA;TANGSA LETTER XA;Lo;0;L;;;;;N;;;;; +16ABB;TANGSA LETTER FA;Lo;0;L;;;;;N;;;;; +16ABC;TANGSA LETTER DHA;Lo;0;L;;;;;N;;;;; +16ABD;TANGSA LETTER CHA;Lo;0;L;;;;;N;;;;; +16ABE;TANGSA LETTER ZA;Lo;0;L;;;;;N;;;;; +16AC0;TANGSA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16AC1;TANGSA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16AC2;TANGSA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16AC3;TANGSA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16AC4;TANGSA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16AC5;TANGSA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16AC6;TANGSA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16AC7;TANGSA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16AC8;TANGSA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16AC9;TANGSA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;; +16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;; +16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;; +16AD3;BASSA VAH LETTER FA;Lo;0;L;;;;;N;;;;; +16AD4;BASSA VAH LETTER MBE;Lo;0;L;;;;;N;;;;; +16AD5;BASSA VAH LETTER YIE;Lo;0;L;;;;;N;;;;; +16AD6;BASSA VAH LETTER GAH;Lo;0;L;;;;;N;;;;; +16AD7;BASSA VAH LETTER DHII;Lo;0;L;;;;;N;;;;; +16AD8;BASSA VAH LETTER KPAH;Lo;0;L;;;;;N;;;;; +16AD9;BASSA VAH LETTER JO;Lo;0;L;;;;;N;;;;; +16ADA;BASSA VAH LETTER HWAH;Lo;0;L;;;;;N;;;;; +16ADB;BASSA VAH LETTER WA;Lo;0;L;;;;;N;;;;; +16ADC;BASSA VAH LETTER ZO;Lo;0;L;;;;;N;;;;; +16ADD;BASSA VAH LETTER GBU;Lo;0;L;;;;;N;;;;; +16ADE;BASSA VAH LETTER DO;Lo;0;L;;;;;N;;;;; +16ADF;BASSA VAH LETTER CE;Lo;0;L;;;;;N;;;;; +16AE0;BASSA VAH LETTER UWU;Lo;0;L;;;;;N;;;;; +16AE1;BASSA VAH LETTER TO;Lo;0;L;;;;;N;;;;; +16AE2;BASSA VAH LETTER BA;Lo;0;L;;;;;N;;;;; +16AE3;BASSA VAH LETTER VU;Lo;0;L;;;;;N;;;;; +16AE4;BASSA VAH LETTER YEIN;Lo;0;L;;;;;N;;;;; +16AE5;BASSA VAH LETTER PA;Lo;0;L;;;;;N;;;;; +16AE6;BASSA VAH LETTER WADDA;Lo;0;L;;;;;N;;;;; +16AE7;BASSA VAH LETTER A;Lo;0;L;;;;;N;;;;; +16AE8;BASSA VAH LETTER O;Lo;0;L;;;;;N;;;;; +16AE9;BASSA VAH LETTER OO;Lo;0;L;;;;;N;;;;; +16AEA;BASSA VAH LETTER U;Lo;0;L;;;;;N;;;;; +16AEB;BASSA VAH LETTER EE;Lo;0;L;;;;;N;;;;; +16AEC;BASSA VAH LETTER E;Lo;0;L;;;;;N;;;;; +16AED;BASSA VAH LETTER I;Lo;0;L;;;;;N;;;;; +16AF0;BASSA VAH COMBINING HIGH TONE;Mn;1;NSM;;;;;N;;;;; +16AF1;BASSA VAH COMBINING LOW TONE;Mn;1;NSM;;;;;N;;;;; +16AF2;BASSA VAH COMBINING MID TONE;Mn;1;NSM;;;;;N;;;;; +16AF3;BASSA VAH COMBINING LOW-MID TONE;Mn;1;NSM;;;;;N;;;;; +16AF4;BASSA VAH COMBINING HIGH-LOW TONE;Mn;1;NSM;;;;;N;;;;; +16AF5;BASSA VAH FULL STOP;Po;0;L;;;;;N;;;;; +16B00;PAHAWH HMONG VOWEL KEEB;Lo;0;L;;;;;N;;;;; +16B01;PAHAWH HMONG VOWEL KEEV;Lo;0;L;;;;;N;;;;; +16B02;PAHAWH HMONG VOWEL KIB;Lo;0;L;;;;;N;;;;; +16B03;PAHAWH HMONG VOWEL KIV;Lo;0;L;;;;;N;;;;; +16B04;PAHAWH HMONG VOWEL KAUB;Lo;0;L;;;;;N;;;;; +16B05;PAHAWH HMONG VOWEL KAUV;Lo;0;L;;;;;N;;;;; +16B06;PAHAWH HMONG VOWEL KUB;Lo;0;L;;;;;N;;;;; +16B07;PAHAWH HMONG VOWEL KUV;Lo;0;L;;;;;N;;;;; +16B08;PAHAWH HMONG VOWEL KEB;Lo;0;L;;;;;N;;;;; +16B09;PAHAWH HMONG VOWEL KEV;Lo;0;L;;;;;N;;;;; +16B0A;PAHAWH HMONG VOWEL KAIB;Lo;0;L;;;;;N;;;;; +16B0B;PAHAWH HMONG VOWEL KAIV;Lo;0;L;;;;;N;;;;; +16B0C;PAHAWH HMONG VOWEL KOOB;Lo;0;L;;;;;N;;;;; +16B0D;PAHAWH HMONG VOWEL KOOV;Lo;0;L;;;;;N;;;;; +16B0E;PAHAWH HMONG VOWEL KAWB;Lo;0;L;;;;;N;;;;; +16B0F;PAHAWH HMONG VOWEL KAWV;Lo;0;L;;;;;N;;;;; +16B10;PAHAWH HMONG VOWEL KUAB;Lo;0;L;;;;;N;;;;; +16B11;PAHAWH HMONG VOWEL KUAV;Lo;0;L;;;;;N;;;;; +16B12;PAHAWH HMONG VOWEL KOB;Lo;0;L;;;;;N;;;;; +16B13;PAHAWH HMONG VOWEL KOV;Lo;0;L;;;;;N;;;;; +16B14;PAHAWH HMONG VOWEL KIAB;Lo;0;L;;;;;N;;;;; +16B15;PAHAWH HMONG VOWEL KIAV;Lo;0;L;;;;;N;;;;; +16B16;PAHAWH HMONG VOWEL KAB;Lo;0;L;;;;;N;;;;; +16B17;PAHAWH HMONG VOWEL KAV;Lo;0;L;;;;;N;;;;; +16B18;PAHAWH HMONG VOWEL KWB;Lo;0;L;;;;;N;;;;; +16B19;PAHAWH HMONG VOWEL KWV;Lo;0;L;;;;;N;;;;; +16B1A;PAHAWH HMONG VOWEL KAAB;Lo;0;L;;;;;N;;;;; +16B1B;PAHAWH HMONG VOWEL KAAV;Lo;0;L;;;;;N;;;;; +16B1C;PAHAWH HMONG CONSONANT VAU;Lo;0;L;;;;;N;;;;; +16B1D;PAHAWH HMONG CONSONANT NTSAU;Lo;0;L;;;;;N;;;;; +16B1E;PAHAWH HMONG CONSONANT LAU;Lo;0;L;;;;;N;;;;; +16B1F;PAHAWH HMONG CONSONANT HAU;Lo;0;L;;;;;N;;;;; +16B20;PAHAWH HMONG CONSONANT NLAU;Lo;0;L;;;;;N;;;;; +16B21;PAHAWH HMONG CONSONANT RAU;Lo;0;L;;;;;N;;;;; +16B22;PAHAWH HMONG CONSONANT NKAU;Lo;0;L;;;;;N;;;;; +16B23;PAHAWH HMONG CONSONANT QHAU;Lo;0;L;;;;;N;;;;; +16B24;PAHAWH HMONG CONSONANT YAU;Lo;0;L;;;;;N;;;;; +16B25;PAHAWH HMONG CONSONANT HLAU;Lo;0;L;;;;;N;;;;; +16B26;PAHAWH HMONG CONSONANT MAU;Lo;0;L;;;;;N;;;;; +16B27;PAHAWH HMONG CONSONANT CHAU;Lo;0;L;;;;;N;;;;; +16B28;PAHAWH HMONG CONSONANT NCHAU;Lo;0;L;;;;;N;;;;; +16B29;PAHAWH HMONG CONSONANT HNAU;Lo;0;L;;;;;N;;;;; +16B2A;PAHAWH HMONG CONSONANT PLHAU;Lo;0;L;;;;;N;;;;; +16B2B;PAHAWH HMONG CONSONANT NTHAU;Lo;0;L;;;;;N;;;;; +16B2C;PAHAWH HMONG CONSONANT NAU;Lo;0;L;;;;;N;;;;; +16B2D;PAHAWH HMONG CONSONANT AU;Lo;0;L;;;;;N;;;;; +16B2E;PAHAWH HMONG CONSONANT XAU;Lo;0;L;;;;;N;;;;; +16B2F;PAHAWH HMONG CONSONANT CAU;Lo;0;L;;;;;N;;;;; +16B30;PAHAWH HMONG MARK CIM TUB;Mn;230;NSM;;;;;N;;;;; +16B31;PAHAWH HMONG MARK CIM SO;Mn;230;NSM;;;;;N;;;;; +16B32;PAHAWH HMONG MARK CIM KES;Mn;230;NSM;;;;;N;;;;; +16B33;PAHAWH HMONG MARK CIM KHAV;Mn;230;NSM;;;;;N;;;;; +16B34;PAHAWH HMONG MARK CIM SUAM;Mn;230;NSM;;;;;N;;;;; +16B35;PAHAWH HMONG MARK CIM HOM;Mn;230;NSM;;;;;N;;;;; +16B36;PAHAWH HMONG MARK CIM TAUM;Mn;230;NSM;;;;;N;;;;; +16B37;PAHAWH HMONG SIGN VOS THOM;Po;0;L;;;;;N;;;;; +16B38;PAHAWH HMONG SIGN VOS TSHAB CEEB;Po;0;L;;;;;N;;;;; +16B39;PAHAWH HMONG SIGN CIM CHEEM;Po;0;L;;;;;N;;;;; +16B3A;PAHAWH HMONG SIGN VOS THIAB;Po;0;L;;;;;N;;;;; +16B3B;PAHAWH HMONG SIGN VOS FEEM;Po;0;L;;;;;N;;;;; +16B3C;PAHAWH HMONG SIGN XYEEM NTXIV;So;0;L;;;;;N;;;;; +16B3D;PAHAWH HMONG SIGN XYEEM RHO;So;0;L;;;;;N;;;;; +16B3E;PAHAWH HMONG SIGN XYEEM TOV;So;0;L;;;;;N;;;;; +16B3F;PAHAWH HMONG SIGN XYEEM FAIB;So;0;L;;;;;N;;;;; +16B40;PAHAWH HMONG SIGN VOS SEEV;Lm;0;L;;;;;N;;;;; +16B41;PAHAWH HMONG SIGN MEEJ SUAB;Lm;0;L;;;;;N;;;;; +16B42;PAHAWH HMONG SIGN VOS NRUA;Lm;0;L;;;;;N;;;;; +16B43;PAHAWH HMONG SIGN IB YAM;Lm;0;L;;;;;N;;;;; +16B44;PAHAWH HMONG SIGN XAUS;Po;0;L;;;;;N;;;;; +16B45;PAHAWH HMONG SIGN CIM TSOV ROG;So;0;L;;;;;N;;;;; +16B50;PAHAWH HMONG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16B51;PAHAWH HMONG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16B52;PAHAWH HMONG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16B53;PAHAWH HMONG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16B54;PAHAWH HMONG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16B55;PAHAWH HMONG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16B56;PAHAWH HMONG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16B57;PAHAWH HMONG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16B58;PAHAWH HMONG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16B59;PAHAWH HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16B5B;PAHAWH HMONG NUMBER TENS;No;0;L;;;;10;N;;;;; +16B5C;PAHAWH HMONG NUMBER HUNDREDS;No;0;L;;;;100;N;;;;; +16B5D;PAHAWH HMONG NUMBER TEN THOUSANDS;No;0;L;;;;10000;N;;;;; +16B5E;PAHAWH HMONG NUMBER MILLIONS;No;0;L;;;;1000000;N;;;;; +16B5F;PAHAWH HMONG NUMBER HUNDRED MILLIONS;No;0;L;;;;100000000;N;;;;; +16B60;PAHAWH HMONG NUMBER TEN BILLIONS;No;0;L;;;;10000000000;N;;;;; +16B61;PAHAWH HMONG NUMBER TRILLIONS;No;0;L;;;;1000000000000;N;;;;; +16B63;PAHAWH HMONG SIGN VOS LUB;Lo;0;L;;;;;N;;;;; +16B64;PAHAWH HMONG SIGN XYOO;Lo;0;L;;;;;N;;;;; +16B65;PAHAWH HMONG SIGN HLI;Lo;0;L;;;;;N;;;;; +16B66;PAHAWH HMONG SIGN THIRD-STAGE HLI;Lo;0;L;;;;;N;;;;; +16B67;PAHAWH HMONG SIGN ZWJ THAJ;Lo;0;L;;;;;N;;;;; +16B68;PAHAWH HMONG SIGN HNUB;Lo;0;L;;;;;N;;;;; +16B69;PAHAWH HMONG SIGN NQIG;Lo;0;L;;;;;N;;;;; +16B6A;PAHAWH HMONG SIGN XIAB;Lo;0;L;;;;;N;;;;; +16B6B;PAHAWH HMONG SIGN NTUJ;Lo;0;L;;;;;N;;;;; +16B6C;PAHAWH HMONG SIGN AV;Lo;0;L;;;;;N;;;;; +16B6D;PAHAWH HMONG SIGN TXHEEJ CEEV;Lo;0;L;;;;;N;;;;; +16B6E;PAHAWH HMONG SIGN MEEJ TSEEB;Lo;0;L;;;;;N;;;;; +16B6F;PAHAWH HMONG SIGN TAU;Lo;0;L;;;;;N;;;;; +16B70;PAHAWH HMONG SIGN LOS;Lo;0;L;;;;;N;;;;; +16B71;PAHAWH HMONG SIGN MUS;Lo;0;L;;;;;N;;;;; +16B72;PAHAWH HMONG SIGN CIM HAIS LUS NTOG NTOG;Lo;0;L;;;;;N;;;;; +16B73;PAHAWH HMONG SIGN CIM CUAM TSHOOJ;Lo;0;L;;;;;N;;;;; +16B74;PAHAWH HMONG SIGN CIM TXWV;Lo;0;L;;;;;N;;;;; +16B75;PAHAWH HMONG SIGN CIM TXWV CHWV;Lo;0;L;;;;;N;;;;; +16B76;PAHAWH HMONG SIGN CIM PUB DAWB;Lo;0;L;;;;;N;;;;; +16B77;PAHAWH HMONG SIGN CIM NRES TOS;Lo;0;L;;;;;N;;;;; +16B7D;PAHAWH HMONG CLAN SIGN TSHEEJ;Lo;0;L;;;;;N;;;;; +16B7E;PAHAWH HMONG CLAN SIGN YEEG;Lo;0;L;;;;;N;;;;; +16B7F;PAHAWH HMONG CLAN SIGN LIS;Lo;0;L;;;;;N;;;;; +16B80;PAHAWH HMONG CLAN SIGN LAUJ;Lo;0;L;;;;;N;;;;; +16B81;PAHAWH HMONG CLAN SIGN XYOOJ;Lo;0;L;;;;;N;;;;; +16B82;PAHAWH HMONG CLAN SIGN KOO;Lo;0;L;;;;;N;;;;; +16B83;PAHAWH HMONG CLAN SIGN HAWJ;Lo;0;L;;;;;N;;;;; +16B84;PAHAWH HMONG CLAN SIGN MUAS;Lo;0;L;;;;;N;;;;; +16B85;PAHAWH HMONG CLAN SIGN THOJ;Lo;0;L;;;;;N;;;;; +16B86;PAHAWH HMONG CLAN SIGN TSAB;Lo;0;L;;;;;N;;;;; +16B87;PAHAWH HMONG CLAN SIGN PHAB;Lo;0;L;;;;;N;;;;; +16B88;PAHAWH HMONG CLAN SIGN KHAB;Lo;0;L;;;;;N;;;;; +16B89;PAHAWH HMONG CLAN SIGN HAM;Lo;0;L;;;;;N;;;;; +16B8A;PAHAWH HMONG CLAN SIGN VAJ;Lo;0;L;;;;;N;;;;; +16B8B;PAHAWH HMONG CLAN SIGN FAJ;Lo;0;L;;;;;N;;;;; +16B8C;PAHAWH HMONG CLAN SIGN YAJ;Lo;0;L;;;;;N;;;;; +16B8D;PAHAWH HMONG CLAN SIGN TSWB;Lo;0;L;;;;;N;;;;; +16B8E;PAHAWH HMONG CLAN SIGN KWM;Lo;0;L;;;;;N;;;;; +16B8F;PAHAWH HMONG CLAN SIGN VWJ;Lo;0;L;;;;;N;;;;; +16D40;KIRAT RAI SIGN ANUSVARA;Lm;0;L;;;;;N;;;;; +16D41;KIRAT RAI SIGN TONPI;Lm;0;L;;;;;N;;;;; +16D42;KIRAT RAI SIGN VISARGA;Lm;0;L;;;;;N;;;;; +16D43;KIRAT RAI LETTER A;Lo;0;L;;;;;N;;;;; +16D44;KIRAT RAI LETTER KA;Lo;0;L;;;;;N;;;;; +16D45;KIRAT RAI LETTER KHA;Lo;0;L;;;;;N;;;;; +16D46;KIRAT RAI LETTER GA;Lo;0;L;;;;;N;;;;; +16D47;KIRAT RAI LETTER GHA;Lo;0;L;;;;;N;;;;; +16D48;KIRAT RAI LETTER NGA;Lo;0;L;;;;;N;;;;; +16D49;KIRAT RAI LETTER CA;Lo;0;L;;;;;N;;;;; +16D4A;KIRAT RAI LETTER CHA;Lo;0;L;;;;;N;;;;; +16D4B;KIRAT RAI LETTER JA;Lo;0;L;;;;;N;;;;; +16D4C;KIRAT RAI LETTER JHA;Lo;0;L;;;;;N;;;;; +16D4D;KIRAT RAI LETTER NYA;Lo;0;L;;;;;N;;;;; +16D4E;KIRAT RAI LETTER TTA;Lo;0;L;;;;;N;;;;; +16D4F;KIRAT RAI LETTER TTHA;Lo;0;L;;;;;N;;;;; +16D50;KIRAT RAI LETTER DDA;Lo;0;L;;;;;N;;;;; +16D51;KIRAT RAI LETTER DDHA;Lo;0;L;;;;;N;;;;; +16D52;KIRAT RAI LETTER TA;Lo;0;L;;;;;N;;;;; +16D53;KIRAT RAI LETTER THA;Lo;0;L;;;;;N;;;;; +16D54;KIRAT RAI LETTER DA;Lo;0;L;;;;;N;;;;; +16D55;KIRAT RAI LETTER DHA;Lo;0;L;;;;;N;;;;; +16D56;KIRAT RAI LETTER NA;Lo;0;L;;;;;N;;;;; +16D57;KIRAT RAI LETTER PA;Lo;0;L;;;;;N;;;;; +16D58;KIRAT RAI LETTER PHA;Lo;0;L;;;;;N;;;;; +16D59;KIRAT RAI LETTER BA;Lo;0;L;;;;;N;;;;; +16D5A;KIRAT RAI LETTER BHA;Lo;0;L;;;;;N;;;;; +16D5B;KIRAT RAI LETTER MA;Lo;0;L;;;;;N;;;;; +16D5C;KIRAT RAI LETTER YA;Lo;0;L;;;;;N;;;;; +16D5D;KIRAT RAI LETTER RA;Lo;0;L;;;;;N;;;;; +16D5E;KIRAT RAI LETTER LA;Lo;0;L;;;;;N;;;;; +16D5F;KIRAT RAI LETTER VA;Lo;0;L;;;;;N;;;;; +16D60;KIRAT RAI LETTER SA;Lo;0;L;;;;;N;;;;; +16D61;KIRAT RAI LETTER SHA;Lo;0;L;;;;;N;;;;; +16D62;KIRAT RAI LETTER HA;Lo;0;L;;;;;N;;;;; +16D63;KIRAT RAI VOWEL SIGN AA;Lo;0;L;;;;;N;;;;; +16D64;KIRAT RAI VOWEL SIGN I;Lo;0;L;;;;;N;;;;; +16D65;KIRAT RAI VOWEL SIGN U;Lo;0;L;;;;;N;;;;; +16D66;KIRAT RAI VOWEL SIGN UE;Lo;0;L;;;;;N;;;;; +16D67;KIRAT RAI VOWEL SIGN E;Lo;0;L;;;;;N;;;;; +16D68;KIRAT RAI VOWEL SIGN AI;Lo;0;L;16D67 16D67;;;;N;;;;; +16D69;KIRAT RAI VOWEL SIGN O;Lo;0;L;16D63 16D67;;;;N;;;;; +16D6A;KIRAT RAI VOWEL SIGN AU;Lo;0;L;16D69 16D67;;;;N;;;;; +16D6B;KIRAT RAI SIGN VIRAMA;Lm;0;L;;;;;N;;;;; +16D6C;KIRAT RAI SIGN SAAT;Lm;0;L;;;;;N;;;;; +16D6D;KIRAT RAI SIGN YUPI;Po;0;L;;;;;N;;;;; +16D6E;KIRAT RAI DANDA;Po;0;L;;;;;N;;;;; +16D6F;KIRAT RAI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +16D70;KIRAT RAI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +16D71;KIRAT RAI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +16D72;KIRAT RAI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +16D73;KIRAT RAI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +16D74;KIRAT RAI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +16D75;KIRAT RAI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +16D76;KIRAT RAI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +16D77;KIRAT RAI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +16D78;KIRAT RAI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +16D79;KIRAT RAI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +16E40;MEDEFAIDRIN CAPITAL LETTER M;Lu;0;L;;;;;N;;;;16E60; +16E41;MEDEFAIDRIN CAPITAL LETTER S;Lu;0;L;;;;;N;;;;16E61; +16E42;MEDEFAIDRIN CAPITAL LETTER V;Lu;0;L;;;;;N;;;;16E62; +16E43;MEDEFAIDRIN CAPITAL LETTER W;Lu;0;L;;;;;N;;;;16E63; +16E44;MEDEFAIDRIN CAPITAL LETTER ATIU;Lu;0;L;;;;;N;;;;16E64; +16E45;MEDEFAIDRIN CAPITAL LETTER Z;Lu;0;L;;;;;N;;;;16E65; +16E46;MEDEFAIDRIN CAPITAL LETTER KP;Lu;0;L;;;;;N;;;;16E66; +16E47;MEDEFAIDRIN CAPITAL LETTER P;Lu;0;L;;;;;N;;;;16E67; +16E48;MEDEFAIDRIN CAPITAL LETTER T;Lu;0;L;;;;;N;;;;16E68; +16E49;MEDEFAIDRIN CAPITAL LETTER G;Lu;0;L;;;;;N;;;;16E69; +16E4A;MEDEFAIDRIN CAPITAL LETTER F;Lu;0;L;;;;;N;;;;16E6A; +16E4B;MEDEFAIDRIN CAPITAL LETTER I;Lu;0;L;;;;;N;;;;16E6B; +16E4C;MEDEFAIDRIN CAPITAL LETTER K;Lu;0;L;;;;;N;;;;16E6C; +16E4D;MEDEFAIDRIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;16E6D; +16E4E;MEDEFAIDRIN CAPITAL LETTER J;Lu;0;L;;;;;N;;;;16E6E; +16E4F;MEDEFAIDRIN CAPITAL LETTER E;Lu;0;L;;;;;N;;;;16E6F; +16E50;MEDEFAIDRIN CAPITAL LETTER B;Lu;0;L;;;;;N;;;;16E70; +16E51;MEDEFAIDRIN CAPITAL LETTER C;Lu;0;L;;;;;N;;;;16E71; +16E52;MEDEFAIDRIN CAPITAL LETTER U;Lu;0;L;;;;;N;;;;16E72; +16E53;MEDEFAIDRIN CAPITAL LETTER YU;Lu;0;L;;;;;N;;;;16E73; +16E54;MEDEFAIDRIN CAPITAL LETTER L;Lu;0;L;;;;;N;;;;16E74; +16E55;MEDEFAIDRIN CAPITAL LETTER Q;Lu;0;L;;;;;N;;;;16E75; +16E56;MEDEFAIDRIN CAPITAL LETTER HP;Lu;0;L;;;;;N;;;;16E76; +16E57;MEDEFAIDRIN CAPITAL LETTER NY;Lu;0;L;;;;;N;;;;16E77; +16E58;MEDEFAIDRIN CAPITAL LETTER X;Lu;0;L;;;;;N;;;;16E78; +16E59;MEDEFAIDRIN CAPITAL LETTER D;Lu;0;L;;;;;N;;;;16E79; +16E5A;MEDEFAIDRIN CAPITAL LETTER OE;Lu;0;L;;;;;N;;;;16E7A; +16E5B;MEDEFAIDRIN CAPITAL LETTER N;Lu;0;L;;;;;N;;;;16E7B; +16E5C;MEDEFAIDRIN CAPITAL LETTER R;Lu;0;L;;;;;N;;;;16E7C; +16E5D;MEDEFAIDRIN CAPITAL LETTER O;Lu;0;L;;;;;N;;;;16E7D; +16E5E;MEDEFAIDRIN CAPITAL LETTER AI;Lu;0;L;;;;;N;;;;16E7E; +16E5F;MEDEFAIDRIN CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;16E7F; +16E60;MEDEFAIDRIN SMALL LETTER M;Ll;0;L;;;;;N;;;16E40;;16E40 +16E61;MEDEFAIDRIN SMALL LETTER S;Ll;0;L;;;;;N;;;16E41;;16E41 +16E62;MEDEFAIDRIN SMALL LETTER V;Ll;0;L;;;;;N;;;16E42;;16E42 +16E63;MEDEFAIDRIN SMALL LETTER W;Ll;0;L;;;;;N;;;16E43;;16E43 +16E64;MEDEFAIDRIN SMALL LETTER ATIU;Ll;0;L;;;;;N;;;16E44;;16E44 +16E65;MEDEFAIDRIN SMALL LETTER Z;Ll;0;L;;;;;N;;;16E45;;16E45 +16E66;MEDEFAIDRIN SMALL LETTER KP;Ll;0;L;;;;;N;;;16E46;;16E46 +16E67;MEDEFAIDRIN SMALL LETTER P;Ll;0;L;;;;;N;;;16E47;;16E47 +16E68;MEDEFAIDRIN SMALL LETTER T;Ll;0;L;;;;;N;;;16E48;;16E48 +16E69;MEDEFAIDRIN SMALL LETTER G;Ll;0;L;;;;;N;;;16E49;;16E49 +16E6A;MEDEFAIDRIN SMALL LETTER F;Ll;0;L;;;;;N;;;16E4A;;16E4A +16E6B;MEDEFAIDRIN SMALL LETTER I;Ll;0;L;;;;;N;;;16E4B;;16E4B +16E6C;MEDEFAIDRIN SMALL LETTER K;Ll;0;L;;;;;N;;;16E4C;;16E4C +16E6D;MEDEFAIDRIN SMALL LETTER A;Ll;0;L;;;;;N;;;16E4D;;16E4D +16E6E;MEDEFAIDRIN SMALL LETTER J;Ll;0;L;;;;;N;;;16E4E;;16E4E +16E6F;MEDEFAIDRIN SMALL LETTER E;Ll;0;L;;;;;N;;;16E4F;;16E4F +16E70;MEDEFAIDRIN SMALL LETTER B;Ll;0;L;;;;;N;;;16E50;;16E50 +16E71;MEDEFAIDRIN SMALL LETTER C;Ll;0;L;;;;;N;;;16E51;;16E51 +16E72;MEDEFAIDRIN SMALL LETTER U;Ll;0;L;;;;;N;;;16E52;;16E52 +16E73;MEDEFAIDRIN SMALL LETTER YU;Ll;0;L;;;;;N;;;16E53;;16E53 +16E74;MEDEFAIDRIN SMALL LETTER L;Ll;0;L;;;;;N;;;16E54;;16E54 +16E75;MEDEFAIDRIN SMALL LETTER Q;Ll;0;L;;;;;N;;;16E55;;16E55 +16E76;MEDEFAIDRIN SMALL LETTER HP;Ll;0;L;;;;;N;;;16E56;;16E56 +16E77;MEDEFAIDRIN SMALL LETTER NY;Ll;0;L;;;;;N;;;16E57;;16E57 +16E78;MEDEFAIDRIN SMALL LETTER X;Ll;0;L;;;;;N;;;16E58;;16E58 +16E79;MEDEFAIDRIN SMALL LETTER D;Ll;0;L;;;;;N;;;16E59;;16E59 +16E7A;MEDEFAIDRIN SMALL LETTER OE;Ll;0;L;;;;;N;;;16E5A;;16E5A +16E7B;MEDEFAIDRIN SMALL LETTER N;Ll;0;L;;;;;N;;;16E5B;;16E5B +16E7C;MEDEFAIDRIN SMALL LETTER R;Ll;0;L;;;;;N;;;16E5C;;16E5C +16E7D;MEDEFAIDRIN SMALL LETTER O;Ll;0;L;;;;;N;;;16E5D;;16E5D +16E7E;MEDEFAIDRIN SMALL LETTER AI;Ll;0;L;;;;;N;;;16E5E;;16E5E +16E7F;MEDEFAIDRIN SMALL LETTER Y;Ll;0;L;;;;;N;;;16E5F;;16E5F +16E80;MEDEFAIDRIN DIGIT ZERO;No;0;L;;;;0;N;;;;; +16E81;MEDEFAIDRIN DIGIT ONE;No;0;L;;;;1;N;;;;; +16E82;MEDEFAIDRIN DIGIT TWO;No;0;L;;;;2;N;;;;; +16E83;MEDEFAIDRIN DIGIT THREE;No;0;L;;;;3;N;;;;; +16E84;MEDEFAIDRIN DIGIT FOUR;No;0;L;;;;4;N;;;;; +16E85;MEDEFAIDRIN DIGIT FIVE;No;0;L;;;;5;N;;;;; +16E86;MEDEFAIDRIN DIGIT SIX;No;0;L;;;;6;N;;;;; +16E87;MEDEFAIDRIN DIGIT SEVEN;No;0;L;;;;7;N;;;;; +16E88;MEDEFAIDRIN DIGIT EIGHT;No;0;L;;;;8;N;;;;; +16E89;MEDEFAIDRIN DIGIT NINE;No;0;L;;;;9;N;;;;; +16E8A;MEDEFAIDRIN NUMBER TEN;No;0;L;;;;10;N;;;;; +16E8B;MEDEFAIDRIN NUMBER ELEVEN;No;0;L;;;;11;N;;;;; +16E8C;MEDEFAIDRIN NUMBER TWELVE;No;0;L;;;;12;N;;;;; +16E8D;MEDEFAIDRIN NUMBER THIRTEEN;No;0;L;;;;13;N;;;;; +16E8E;MEDEFAIDRIN NUMBER FOURTEEN;No;0;L;;;;14;N;;;;; +16E8F;MEDEFAIDRIN NUMBER FIFTEEN;No;0;L;;;;15;N;;;;; +16E90;MEDEFAIDRIN NUMBER SIXTEEN;No;0;L;;;;16;N;;;;; +16E91;MEDEFAIDRIN NUMBER SEVENTEEN;No;0;L;;;;17;N;;;;; +16E92;MEDEFAIDRIN NUMBER EIGHTEEN;No;0;L;;;;18;N;;;;; +16E93;MEDEFAIDRIN NUMBER NINETEEN;No;0;L;;;;19;N;;;;; +16E94;MEDEFAIDRIN DIGIT ONE ALTERNATE FORM;No;0;L;;;;1;N;;;;; +16E95;MEDEFAIDRIN DIGIT TWO ALTERNATE FORM;No;0;L;;;;2;N;;;;; +16E96;MEDEFAIDRIN DIGIT THREE ALTERNATE FORM;No;0;L;;;;3;N;;;;; +16E97;MEDEFAIDRIN COMMA;Po;0;L;;;;;N;;;;; +16E98;MEDEFAIDRIN FULL STOP;Po;0;L;;;;;N;;;;; +16E99;MEDEFAIDRIN SYMBOL AIVA;Po;0;L;;;;;N;;;;; +16E9A;MEDEFAIDRIN EXCLAMATION OH;Po;0;L;;;;;N;;;;; +16EA0;BERIA ERFE CAPITAL LETTER ARKAB;Lu;0;L;;;;;N;;;;16EBB; +16EA1;BERIA ERFE CAPITAL LETTER BASIGNA;Lu;0;L;;;;;N;;;;16EBC; +16EA2;BERIA ERFE CAPITAL LETTER DARBAI;Lu;0;L;;;;;N;;;;16EBD; +16EA3;BERIA ERFE CAPITAL LETTER EH;Lu;0;L;;;;;N;;;;16EBE; +16EA4;BERIA ERFE CAPITAL LETTER FITKO;Lu;0;L;;;;;N;;;;16EBF; +16EA5;BERIA ERFE CAPITAL LETTER GOWAY;Lu;0;L;;;;;N;;;;16EC0; +16EA6;BERIA ERFE CAPITAL LETTER HIRDEABO;Lu;0;L;;;;;N;;;;16EC1; +16EA7;BERIA ERFE CAPITAL LETTER I;Lu;0;L;;;;;N;;;;16EC2; +16EA8;BERIA ERFE CAPITAL LETTER DJAI;Lu;0;L;;;;;N;;;;16EC3; +16EA9;BERIA ERFE CAPITAL LETTER KOBO;Lu;0;L;;;;;N;;;;16EC4; +16EAA;BERIA ERFE CAPITAL LETTER LAKKO;Lu;0;L;;;;;N;;;;16EC5; +16EAB;BERIA ERFE CAPITAL LETTER MERI;Lu;0;L;;;;;N;;;;16EC6; +16EAC;BERIA ERFE CAPITAL LETTER NINI;Lu;0;L;;;;;N;;;;16EC7; +16EAD;BERIA ERFE CAPITAL LETTER GNA;Lu;0;L;;;;;N;;;;16EC8; +16EAE;BERIA ERFE CAPITAL LETTER NGAY;Lu;0;L;;;;;N;;;;16EC9; +16EAF;BERIA ERFE CAPITAL LETTER OI;Lu;0;L;;;;;N;;;;16ECA; +16EB0;BERIA ERFE CAPITAL LETTER PI;Lu;0;L;;;;;N;;;;16ECB; +16EB1;BERIA ERFE CAPITAL LETTER ERIGO;Lu;0;L;;;;;N;;;;16ECC; +16EB2;BERIA ERFE CAPITAL LETTER ERIGO TAMURA;Lu;0;L;;;;;N;;;;16ECD; +16EB3;BERIA ERFE CAPITAL LETTER SERI;Lu;0;L;;;;;N;;;;16ECE; +16EB4;BERIA ERFE CAPITAL LETTER SHEP;Lu;0;L;;;;;N;;;;16ECF; +16EB5;BERIA ERFE CAPITAL LETTER TATASOUE;Lu;0;L;;;;;N;;;;16ED0; +16EB6;BERIA ERFE CAPITAL LETTER UI;Lu;0;L;;;;;N;;;;16ED1; +16EB7;BERIA ERFE CAPITAL LETTER WASSE;Lu;0;L;;;;;N;;;;16ED2; +16EB8;BERIA ERFE CAPITAL LETTER AY;Lu;0;L;;;;;N;;;;16ED3; +16EBB;BERIA ERFE SMALL LETTER ARKAB;Ll;0;L;;;;;N;;;16EA0;;16EA0 +16EBC;BERIA ERFE SMALL LETTER BASIGNA;Ll;0;L;;;;;N;;;16EA1;;16EA1 +16EBD;BERIA ERFE SMALL LETTER DARBAI;Ll;0;L;;;;;N;;;16EA2;;16EA2 +16EBE;BERIA ERFE SMALL LETTER EH;Ll;0;L;;;;;N;;;16EA3;;16EA3 +16EBF;BERIA ERFE SMALL LETTER FITKO;Ll;0;L;;;;;N;;;16EA4;;16EA4 +16EC0;BERIA ERFE SMALL LETTER GOWAY;Ll;0;L;;;;;N;;;16EA5;;16EA5 +16EC1;BERIA ERFE SMALL LETTER HIRDEABO;Ll;0;L;;;;;N;;;16EA6;;16EA6 +16EC2;BERIA ERFE SMALL LETTER I;Ll;0;L;;;;;N;;;16EA7;;16EA7 +16EC3;BERIA ERFE SMALL LETTER DJAI;Ll;0;L;;;;;N;;;16EA8;;16EA8 +16EC4;BERIA ERFE SMALL LETTER KOBO;Ll;0;L;;;;;N;;;16EA9;;16EA9 +16EC5;BERIA ERFE SMALL LETTER LAKKO;Ll;0;L;;;;;N;;;16EAA;;16EAA +16EC6;BERIA ERFE SMALL LETTER MERI;Ll;0;L;;;;;N;;;16EAB;;16EAB +16EC7;BERIA ERFE SMALL LETTER NINI;Ll;0;L;;;;;N;;;16EAC;;16EAC +16EC8;BERIA ERFE SMALL LETTER GNA;Ll;0;L;;;;;N;;;16EAD;;16EAD +16EC9;BERIA ERFE SMALL LETTER NGAY;Ll;0;L;;;;;N;;;16EAE;;16EAE +16ECA;BERIA ERFE SMALL LETTER OI;Ll;0;L;;;;;N;;;16EAF;;16EAF +16ECB;BERIA ERFE SMALL LETTER PI;Ll;0;L;;;;;N;;;16EB0;;16EB0 +16ECC;BERIA ERFE SMALL LETTER ERIGO;Ll;0;L;;;;;N;;;16EB1;;16EB1 +16ECD;BERIA ERFE SMALL LETTER ERIGO TAMURA;Ll;0;L;;;;;N;;;16EB2;;16EB2 +16ECE;BERIA ERFE SMALL LETTER SERI;Ll;0;L;;;;;N;;;16EB3;;16EB3 +16ECF;BERIA ERFE SMALL LETTER SHEP;Ll;0;L;;;;;N;;;16EB4;;16EB4 +16ED0;BERIA ERFE SMALL LETTER TATASOUE;Ll;0;L;;;;;N;;;16EB5;;16EB5 +16ED1;BERIA ERFE SMALL LETTER UI;Ll;0;L;;;;;N;;;16EB6;;16EB6 +16ED2;BERIA ERFE SMALL LETTER WASSE;Ll;0;L;;;;;N;;;16EB7;;16EB7 +16ED3;BERIA ERFE SMALL LETTER AY;Ll;0;L;;;;;N;;;16EB8;;16EB8 +16F00;MIAO LETTER PA;Lo;0;L;;;;;N;;;;; +16F01;MIAO LETTER BA;Lo;0;L;;;;;N;;;;; +16F02;MIAO LETTER YI PA;Lo;0;L;;;;;N;;;;; +16F03;MIAO LETTER PLA;Lo;0;L;;;;;N;;;;; +16F04;MIAO LETTER MA;Lo;0;L;;;;;N;;;;; +16F05;MIAO LETTER MHA;Lo;0;L;;;;;N;;;;; +16F06;MIAO LETTER ARCHAIC MA;Lo;0;L;;;;;N;;;;; +16F07;MIAO LETTER FA;Lo;0;L;;;;;N;;;;; +16F08;MIAO LETTER VA;Lo;0;L;;;;;N;;;;; +16F09;MIAO LETTER VFA;Lo;0;L;;;;;N;;;;; +16F0A;MIAO LETTER TA;Lo;0;L;;;;;N;;;;; +16F0B;MIAO LETTER DA;Lo;0;L;;;;;N;;;;; +16F0C;MIAO LETTER YI TTA;Lo;0;L;;;;;N;;;;; +16F0D;MIAO LETTER YI TA;Lo;0;L;;;;;N;;;;; +16F0E;MIAO LETTER TTA;Lo;0;L;;;;;N;;;;; +16F0F;MIAO LETTER DDA;Lo;0;L;;;;;N;;;;; +16F10;MIAO LETTER NA;Lo;0;L;;;;;N;;;;; +16F11;MIAO LETTER NHA;Lo;0;L;;;;;N;;;;; +16F12;MIAO LETTER YI NNA;Lo;0;L;;;;;N;;;;; +16F13;MIAO LETTER ARCHAIC NA;Lo;0;L;;;;;N;;;;; +16F14;MIAO LETTER NNA;Lo;0;L;;;;;N;;;;; +16F15;MIAO LETTER NNHA;Lo;0;L;;;;;N;;;;; +16F16;MIAO LETTER LA;Lo;0;L;;;;;N;;;;; +16F17;MIAO LETTER LYA;Lo;0;L;;;;;N;;;;; +16F18;MIAO LETTER LHA;Lo;0;L;;;;;N;;;;; +16F19;MIAO LETTER LHYA;Lo;0;L;;;;;N;;;;; +16F1A;MIAO LETTER TLHA;Lo;0;L;;;;;N;;;;; +16F1B;MIAO LETTER DLHA;Lo;0;L;;;;;N;;;;; +16F1C;MIAO LETTER TLHYA;Lo;0;L;;;;;N;;;;; +16F1D;MIAO LETTER DLHYA;Lo;0;L;;;;;N;;;;; +16F1E;MIAO LETTER KA;Lo;0;L;;;;;N;;;;; +16F1F;MIAO LETTER GA;Lo;0;L;;;;;N;;;;; +16F20;MIAO LETTER YI KA;Lo;0;L;;;;;N;;;;; +16F21;MIAO LETTER QA;Lo;0;L;;;;;N;;;;; +16F22;MIAO LETTER QGA;Lo;0;L;;;;;N;;;;; +16F23;MIAO LETTER NGA;Lo;0;L;;;;;N;;;;; +16F24;MIAO LETTER NGHA;Lo;0;L;;;;;N;;;;; +16F25;MIAO LETTER ARCHAIC NGA;Lo;0;L;;;;;N;;;;; +16F26;MIAO LETTER HA;Lo;0;L;;;;;N;;;;; +16F27;MIAO LETTER XA;Lo;0;L;;;;;N;;;;; +16F28;MIAO LETTER GHA;Lo;0;L;;;;;N;;;;; +16F29;MIAO LETTER GHHA;Lo;0;L;;;;;N;;;;; +16F2A;MIAO LETTER TSSA;Lo;0;L;;;;;N;;;;; +16F2B;MIAO LETTER DZZA;Lo;0;L;;;;;N;;;;; +16F2C;MIAO LETTER NYA;Lo;0;L;;;;;N;;;;; +16F2D;MIAO LETTER NYHA;Lo;0;L;;;;;N;;;;; +16F2E;MIAO LETTER TSHA;Lo;0;L;;;;;N;;;;; +16F2F;MIAO LETTER DZHA;Lo;0;L;;;;;N;;;;; +16F30;MIAO LETTER YI TSHA;Lo;0;L;;;;;N;;;;; +16F31;MIAO LETTER YI DZHA;Lo;0;L;;;;;N;;;;; +16F32;MIAO LETTER REFORMED TSHA;Lo;0;L;;;;;N;;;;; +16F33;MIAO LETTER SHA;Lo;0;L;;;;;N;;;;; +16F34;MIAO LETTER SSA;Lo;0;L;;;;;N;;;;; +16F35;MIAO LETTER ZHA;Lo;0;L;;;;;N;;;;; +16F36;MIAO LETTER ZSHA;Lo;0;L;;;;;N;;;;; +16F37;MIAO LETTER TSA;Lo;0;L;;;;;N;;;;; +16F38;MIAO LETTER DZA;Lo;0;L;;;;;N;;;;; +16F39;MIAO LETTER YI TSA;Lo;0;L;;;;;N;;;;; +16F3A;MIAO LETTER SA;Lo;0;L;;;;;N;;;;; +16F3B;MIAO LETTER ZA;Lo;0;L;;;;;N;;;;; +16F3C;MIAO LETTER ZSA;Lo;0;L;;;;;N;;;;; +16F3D;MIAO LETTER ZZA;Lo;0;L;;;;;N;;;;; +16F3E;MIAO LETTER ZZSA;Lo;0;L;;;;;N;;;;; +16F3F;MIAO LETTER ARCHAIC ZZA;Lo;0;L;;;;;N;;;;; +16F40;MIAO LETTER ZZYA;Lo;0;L;;;;;N;;;;; +16F41;MIAO LETTER ZZSYA;Lo;0;L;;;;;N;;;;; +16F42;MIAO LETTER WA;Lo;0;L;;;;;N;;;;; +16F43;MIAO LETTER AH;Lo;0;L;;;;;N;;;;; +16F44;MIAO LETTER HHA;Lo;0;L;;;;;N;;;;; +16F45;MIAO LETTER BRI;Lo;0;L;;;;;N;;;;; +16F46;MIAO LETTER SYI;Lo;0;L;;;;;N;;;;; +16F47;MIAO LETTER DZYI;Lo;0;L;;;;;N;;;;; +16F48;MIAO LETTER TE;Lo;0;L;;;;;N;;;;; +16F49;MIAO LETTER TSE;Lo;0;L;;;;;N;;;;; +16F4A;MIAO LETTER RTE;Lo;0;L;;;;;N;;;;; +16F4F;MIAO SIGN CONSONANT MODIFIER BAR;Mn;0;NSM;;;;;N;;;;; +16F50;MIAO LETTER NASALIZATION;Lo;0;L;;;;;N;;;;; +16F51;MIAO SIGN ASPIRATION;Mc;0;L;;;;;N;;;;; +16F52;MIAO SIGN REFORMED VOICING;Mc;0;L;;;;;N;;;;; +16F53;MIAO SIGN REFORMED ASPIRATION;Mc;0;L;;;;;N;;;;; +16F54;MIAO VOWEL SIGN A;Mc;0;L;;;;;N;;;;; +16F55;MIAO VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; +16F56;MIAO VOWEL SIGN AHH;Mc;0;L;;;;;N;;;;; +16F57;MIAO VOWEL SIGN AN;Mc;0;L;;;;;N;;;;; +16F58;MIAO VOWEL SIGN ANG;Mc;0;L;;;;;N;;;;; +16F59;MIAO VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +16F5A;MIAO VOWEL SIGN OO;Mc;0;L;;;;;N;;;;; +16F5B;MIAO VOWEL SIGN WO;Mc;0;L;;;;;N;;;;; +16F5C;MIAO VOWEL SIGN W;Mc;0;L;;;;;N;;;;; +16F5D;MIAO VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +16F5E;MIAO VOWEL SIGN EN;Mc;0;L;;;;;N;;;;; +16F5F;MIAO VOWEL SIGN ENG;Mc;0;L;;;;;N;;;;; +16F60;MIAO VOWEL SIGN OEY;Mc;0;L;;;;;N;;;;; +16F61;MIAO VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +16F62;MIAO VOWEL SIGN IA;Mc;0;L;;;;;N;;;;; +16F63;MIAO VOWEL SIGN IAN;Mc;0;L;;;;;N;;;;; +16F64;MIAO VOWEL SIGN IANG;Mc;0;L;;;;;N;;;;; +16F65;MIAO VOWEL SIGN IO;Mc;0;L;;;;;N;;;;; +16F66;MIAO VOWEL SIGN IE;Mc;0;L;;;;;N;;;;; +16F67;MIAO VOWEL SIGN II;Mc;0;L;;;;;N;;;;; +16F68;MIAO VOWEL SIGN IU;Mc;0;L;;;;;N;;;;; +16F69;MIAO VOWEL SIGN ING;Mc;0;L;;;;;N;;;;; +16F6A;MIAO VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +16F6B;MIAO VOWEL SIGN UA;Mc;0;L;;;;;N;;;;; +16F6C;MIAO VOWEL SIGN UAN;Mc;0;L;;;;;N;;;;; +16F6D;MIAO VOWEL SIGN UANG;Mc;0;L;;;;;N;;;;; +16F6E;MIAO VOWEL SIGN UU;Mc;0;L;;;;;N;;;;; +16F6F;MIAO VOWEL SIGN UEI;Mc;0;L;;;;;N;;;;; +16F70;MIAO VOWEL SIGN UNG;Mc;0;L;;;;;N;;;;; +16F71;MIAO VOWEL SIGN Y;Mc;0;L;;;;;N;;;;; +16F72;MIAO VOWEL SIGN YI;Mc;0;L;;;;;N;;;;; +16F73;MIAO VOWEL SIGN AE;Mc;0;L;;;;;N;;;;; +16F74;MIAO VOWEL SIGN AEE;Mc;0;L;;;;;N;;;;; +16F75;MIAO VOWEL SIGN ERR;Mc;0;L;;;;;N;;;;; +16F76;MIAO VOWEL SIGN ROUNDED ERR;Mc;0;L;;;;;N;;;;; +16F77;MIAO VOWEL SIGN ER;Mc;0;L;;;;;N;;;;; +16F78;MIAO VOWEL SIGN ROUNDED ER;Mc;0;L;;;;;N;;;;; +16F79;MIAO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;; +16F7A;MIAO VOWEL SIGN EI;Mc;0;L;;;;;N;;;;; +16F7B;MIAO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; +16F7C;MIAO VOWEL SIGN OU;Mc;0;L;;;;;N;;;;; +16F7D;MIAO VOWEL SIGN N;Mc;0;L;;;;;N;;;;; +16F7E;MIAO VOWEL SIGN NG;Mc;0;L;;;;;N;;;;; +16F7F;MIAO VOWEL SIGN UOG;Mc;0;L;;;;;N;;;;; +16F80;MIAO VOWEL SIGN YUI;Mc;0;L;;;;;N;;;;; +16F81;MIAO VOWEL SIGN OG;Mc;0;L;;;;;N;;;;; +16F82;MIAO VOWEL SIGN OER;Mc;0;L;;;;;N;;;;; +16F83;MIAO VOWEL SIGN VW;Mc;0;L;;;;;N;;;;; +16F84;MIAO VOWEL SIGN IG;Mc;0;L;;;;;N;;;;; +16F85;MIAO VOWEL SIGN EA;Mc;0;L;;;;;N;;;;; +16F86;MIAO VOWEL SIGN IONG;Mc;0;L;;;;;N;;;;; +16F87;MIAO VOWEL SIGN UI;Mc;0;L;;;;;N;;;;; +16F8F;MIAO TONE RIGHT;Mn;0;NSM;;;;;N;;;;; +16F90;MIAO TONE TOP RIGHT;Mn;0;NSM;;;;;N;;;;; +16F91;MIAO TONE ABOVE;Mn;0;NSM;;;;;N;;;;; +16F92;MIAO TONE BELOW;Mn;0;NSM;;;;;N;;;;; +16F93;MIAO LETTER TONE-2;Lm;0;L;;;;;N;;;;; +16F94;MIAO LETTER TONE-3;Lm;0;L;;;;;N;;;;; +16F95;MIAO LETTER TONE-4;Lm;0;L;;;;;N;;;;; +16F96;MIAO LETTER TONE-5;Lm;0;L;;;;;N;;;;; +16F97;MIAO LETTER TONE-6;Lm;0;L;;;;;N;;;;; +16F98;MIAO LETTER TONE-7;Lm;0;L;;;;;N;;;;; +16F99;MIAO LETTER TONE-8;Lm;0;L;;;;;N;;;;; +16F9A;MIAO LETTER REFORMED TONE-1;Lm;0;L;;;;;N;;;;; +16F9B;MIAO LETTER REFORMED TONE-2;Lm;0;L;;;;;N;;;;; +16F9C;MIAO LETTER REFORMED TONE-4;Lm;0;L;;;;;N;;;;; +16F9D;MIAO LETTER REFORMED TONE-5;Lm;0;L;;;;;N;;;;; +16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;; +16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;; +16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE2;OLD CHINESE HOOK MARK;Po;0;ON;;;;;N;;;;; +16FE3;OLD CHINESE ITERATION MARK;Lm;0;L;;;;;N;;;;; +16FE4;KHITAN SMALL SCRIPT FILLER;Mn;0;NSM;;;;;N;;;;; +16FF0;VIETNAMESE ALTERNATE READING MARK CA;Mc;6;L;;;;;N;;;;; +16FF1;VIETNAMESE ALTERNATE READING MARK NHAY;Mc;6;L;;;;;N;;;;; +16FF2;CHINESE SMALL SIMPLIFIED ER;Lm;0;L;;;;;N;;;;; +16FF3;CHINESE SMALL TRADITIONAL ER;Lm;0;L;;;;;N;;;;; +16FF4;YANGQIN SIGN SLOW ONE BEAT;Nl;0;L;;;;1;N;;;;; +16FF5;YANGQIN SIGN SLOW THREE HALF BEATS;Nl;0;L;;;;3/2;N;;;;; +16FF6;YANGQIN SIGN SLOW TWO BEATS;Nl;0;L;;;;2;N;;;;; +17000;;Lo;0;L;;;;;N;;;;; +187FF;;Lo;0;L;;;;;N;;;;; +18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;; +18801;TANGUT COMPONENT-002;Lo;0;L;;;;;N;;;;; +18802;TANGUT COMPONENT-003;Lo;0;L;;;;;N;;;;; +18803;TANGUT COMPONENT-004;Lo;0;L;;;;;N;;;;; +18804;TANGUT COMPONENT-005;Lo;0;L;;;;;N;;;;; +18805;TANGUT COMPONENT-006;Lo;0;L;;;;;N;;;;; +18806;TANGUT COMPONENT-007;Lo;0;L;;;;;N;;;;; +18807;TANGUT COMPONENT-008;Lo;0;L;;;;;N;;;;; +18808;TANGUT COMPONENT-009;Lo;0;L;;;;;N;;;;; +18809;TANGUT COMPONENT-010;Lo;0;L;;;;;N;;;;; +1880A;TANGUT COMPONENT-011;Lo;0;L;;;;;N;;;;; +1880B;TANGUT COMPONENT-012;Lo;0;L;;;;;N;;;;; +1880C;TANGUT COMPONENT-013;Lo;0;L;;;;;N;;;;; +1880D;TANGUT COMPONENT-014;Lo;0;L;;;;;N;;;;; +1880E;TANGUT COMPONENT-015;Lo;0;L;;;;;N;;;;; +1880F;TANGUT COMPONENT-016;Lo;0;L;;;;;N;;;;; +18810;TANGUT COMPONENT-017;Lo;0;L;;;;;N;;;;; +18811;TANGUT COMPONENT-018;Lo;0;L;;;;;N;;;;; +18812;TANGUT COMPONENT-019;Lo;0;L;;;;;N;;;;; +18813;TANGUT COMPONENT-020;Lo;0;L;;;;;N;;;;; +18814;TANGUT COMPONENT-021;Lo;0;L;;;;;N;;;;; +18815;TANGUT COMPONENT-022;Lo;0;L;;;;;N;;;;; +18816;TANGUT COMPONENT-023;Lo;0;L;;;;;N;;;;; +18817;TANGUT COMPONENT-024;Lo;0;L;;;;;N;;;;; +18818;TANGUT COMPONENT-025;Lo;0;L;;;;;N;;;;; +18819;TANGUT COMPONENT-026;Lo;0;L;;;;;N;;;;; +1881A;TANGUT COMPONENT-027;Lo;0;L;;;;;N;;;;; +1881B;TANGUT COMPONENT-028;Lo;0;L;;;;;N;;;;; +1881C;TANGUT COMPONENT-029;Lo;0;L;;;;;N;;;;; +1881D;TANGUT COMPONENT-030;Lo;0;L;;;;;N;;;;; +1881E;TANGUT COMPONENT-031;Lo;0;L;;;;;N;;;;; +1881F;TANGUT COMPONENT-032;Lo;0;L;;;;;N;;;;; +18820;TANGUT COMPONENT-033;Lo;0;L;;;;;N;;;;; +18821;TANGUT COMPONENT-034;Lo;0;L;;;;;N;;;;; +18822;TANGUT COMPONENT-035;Lo;0;L;;;;;N;;;;; +18823;TANGUT COMPONENT-036;Lo;0;L;;;;;N;;;;; +18824;TANGUT COMPONENT-037;Lo;0;L;;;;;N;;;;; +18825;TANGUT COMPONENT-038;Lo;0;L;;;;;N;;;;; +18826;TANGUT COMPONENT-039;Lo;0;L;;;;;N;;;;; +18827;TANGUT COMPONENT-040;Lo;0;L;;;;;N;;;;; +18828;TANGUT COMPONENT-041;Lo;0;L;;;;;N;;;;; +18829;TANGUT COMPONENT-042;Lo;0;L;;;;;N;;;;; +1882A;TANGUT COMPONENT-043;Lo;0;L;;;;;N;;;;; +1882B;TANGUT COMPONENT-044;Lo;0;L;;;;;N;;;;; +1882C;TANGUT COMPONENT-045;Lo;0;L;;;;;N;;;;; +1882D;TANGUT COMPONENT-046;Lo;0;L;;;;;N;;;;; +1882E;TANGUT COMPONENT-047;Lo;0;L;;;;;N;;;;; +1882F;TANGUT COMPONENT-048;Lo;0;L;;;;;N;;;;; +18830;TANGUT COMPONENT-049;Lo;0;L;;;;;N;;;;; +18831;TANGUT COMPONENT-050;Lo;0;L;;;;;N;;;;; +18832;TANGUT COMPONENT-051;Lo;0;L;;;;;N;;;;; +18833;TANGUT COMPONENT-052;Lo;0;L;;;;;N;;;;; +18834;TANGUT COMPONENT-053;Lo;0;L;;;;;N;;;;; +18835;TANGUT COMPONENT-054;Lo;0;L;;;;;N;;;;; +18836;TANGUT COMPONENT-055;Lo;0;L;;;;;N;;;;; +18837;TANGUT COMPONENT-056;Lo;0;L;;;;;N;;;;; +18838;TANGUT COMPONENT-057;Lo;0;L;;;;;N;;;;; +18839;TANGUT COMPONENT-058;Lo;0;L;;;;;N;;;;; +1883A;TANGUT COMPONENT-059;Lo;0;L;;;;;N;;;;; +1883B;TANGUT COMPONENT-060;Lo;0;L;;;;;N;;;;; +1883C;TANGUT COMPONENT-061;Lo;0;L;;;;;N;;;;; +1883D;TANGUT COMPONENT-062;Lo;0;L;;;;;N;;;;; +1883E;TANGUT COMPONENT-063;Lo;0;L;;;;;N;;;;; +1883F;TANGUT COMPONENT-064;Lo;0;L;;;;;N;;;;; +18840;TANGUT COMPONENT-065;Lo;0;L;;;;;N;;;;; +18841;TANGUT COMPONENT-066;Lo;0;L;;;;;N;;;;; +18842;TANGUT COMPONENT-067;Lo;0;L;;;;;N;;;;; +18843;TANGUT COMPONENT-068;Lo;0;L;;;;;N;;;;; +18844;TANGUT COMPONENT-069;Lo;0;L;;;;;N;;;;; +18845;TANGUT COMPONENT-070;Lo;0;L;;;;;N;;;;; +18846;TANGUT COMPONENT-071;Lo;0;L;;;;;N;;;;; +18847;TANGUT COMPONENT-072;Lo;0;L;;;;;N;;;;; +18848;TANGUT COMPONENT-073;Lo;0;L;;;;;N;;;;; +18849;TANGUT COMPONENT-074;Lo;0;L;;;;;N;;;;; +1884A;TANGUT COMPONENT-075;Lo;0;L;;;;;N;;;;; +1884B;TANGUT COMPONENT-076;Lo;0;L;;;;;N;;;;; +1884C;TANGUT COMPONENT-077;Lo;0;L;;;;;N;;;;; +1884D;TANGUT COMPONENT-078;Lo;0;L;;;;;N;;;;; +1884E;TANGUT COMPONENT-079;Lo;0;L;;;;;N;;;;; +1884F;TANGUT COMPONENT-080;Lo;0;L;;;;;N;;;;; +18850;TANGUT COMPONENT-081;Lo;0;L;;;;;N;;;;; +18851;TANGUT COMPONENT-082;Lo;0;L;;;;;N;;;;; +18852;TANGUT COMPONENT-083;Lo;0;L;;;;;N;;;;; +18853;TANGUT COMPONENT-084;Lo;0;L;;;;;N;;;;; +18854;TANGUT COMPONENT-085;Lo;0;L;;;;;N;;;;; +18855;TANGUT COMPONENT-086;Lo;0;L;;;;;N;;;;; +18856;TANGUT COMPONENT-087;Lo;0;L;;;;;N;;;;; +18857;TANGUT COMPONENT-088;Lo;0;L;;;;;N;;;;; +18858;TANGUT COMPONENT-089;Lo;0;L;;;;;N;;;;; +18859;TANGUT COMPONENT-090;Lo;0;L;;;;;N;;;;; +1885A;TANGUT COMPONENT-091;Lo;0;L;;;;;N;;;;; +1885B;TANGUT COMPONENT-092;Lo;0;L;;;;;N;;;;; +1885C;TANGUT COMPONENT-093;Lo;0;L;;;;;N;;;;; +1885D;TANGUT COMPONENT-094;Lo;0;L;;;;;N;;;;; +1885E;TANGUT COMPONENT-095;Lo;0;L;;;;;N;;;;; +1885F;TANGUT COMPONENT-096;Lo;0;L;;;;;N;;;;; +18860;TANGUT COMPONENT-097;Lo;0;L;;;;;N;;;;; +18861;TANGUT COMPONENT-098;Lo;0;L;;;;;N;;;;; +18862;TANGUT COMPONENT-099;Lo;0;L;;;;;N;;;;; +18863;TANGUT COMPONENT-100;Lo;0;L;;;;;N;;;;; +18864;TANGUT COMPONENT-101;Lo;0;L;;;;;N;;;;; +18865;TANGUT COMPONENT-102;Lo;0;L;;;;;N;;;;; +18866;TANGUT COMPONENT-103;Lo;0;L;;;;;N;;;;; +18867;TANGUT COMPONENT-104;Lo;0;L;;;;;N;;;;; +18868;TANGUT COMPONENT-105;Lo;0;L;;;;;N;;;;; +18869;TANGUT COMPONENT-106;Lo;0;L;;;;;N;;;;; +1886A;TANGUT COMPONENT-107;Lo;0;L;;;;;N;;;;; +1886B;TANGUT COMPONENT-108;Lo;0;L;;;;;N;;;;; +1886C;TANGUT COMPONENT-109;Lo;0;L;;;;;N;;;;; +1886D;TANGUT COMPONENT-110;Lo;0;L;;;;;N;;;;; +1886E;TANGUT COMPONENT-111;Lo;0;L;;;;;N;;;;; +1886F;TANGUT COMPONENT-112;Lo;0;L;;;;;N;;;;; +18870;TANGUT COMPONENT-113;Lo;0;L;;;;;N;;;;; +18871;TANGUT COMPONENT-114;Lo;0;L;;;;;N;;;;; +18872;TANGUT COMPONENT-115;Lo;0;L;;;;;N;;;;; +18873;TANGUT COMPONENT-116;Lo;0;L;;;;;N;;;;; +18874;TANGUT COMPONENT-117;Lo;0;L;;;;;N;;;;; +18875;TANGUT COMPONENT-118;Lo;0;L;;;;;N;;;;; +18876;TANGUT COMPONENT-119;Lo;0;L;;;;;N;;;;; +18877;TANGUT COMPONENT-120;Lo;0;L;;;;;N;;;;; +18878;TANGUT COMPONENT-121;Lo;0;L;;;;;N;;;;; +18879;TANGUT COMPONENT-122;Lo;0;L;;;;;N;;;;; +1887A;TANGUT COMPONENT-123;Lo;0;L;;;;;N;;;;; +1887B;TANGUT COMPONENT-124;Lo;0;L;;;;;N;;;;; +1887C;TANGUT COMPONENT-125;Lo;0;L;;;;;N;;;;; +1887D;TANGUT COMPONENT-126;Lo;0;L;;;;;N;;;;; +1887E;TANGUT COMPONENT-127;Lo;0;L;;;;;N;;;;; +1887F;TANGUT COMPONENT-128;Lo;0;L;;;;;N;;;;; +18880;TANGUT COMPONENT-129;Lo;0;L;;;;;N;;;;; +18881;TANGUT COMPONENT-130;Lo;0;L;;;;;N;;;;; +18882;TANGUT COMPONENT-131;Lo;0;L;;;;;N;;;;; +18883;TANGUT COMPONENT-132;Lo;0;L;;;;;N;;;;; +18884;TANGUT COMPONENT-133;Lo;0;L;;;;;N;;;;; +18885;TANGUT COMPONENT-134;Lo;0;L;;;;;N;;;;; +18886;TANGUT COMPONENT-135;Lo;0;L;;;;;N;;;;; +18887;TANGUT COMPONENT-136;Lo;0;L;;;;;N;;;;; +18888;TANGUT COMPONENT-137;Lo;0;L;;;;;N;;;;; +18889;TANGUT COMPONENT-138;Lo;0;L;;;;;N;;;;; +1888A;TANGUT COMPONENT-139;Lo;0;L;;;;;N;;;;; +1888B;TANGUT COMPONENT-140;Lo;0;L;;;;;N;;;;; +1888C;TANGUT COMPONENT-141;Lo;0;L;;;;;N;;;;; +1888D;TANGUT COMPONENT-142;Lo;0;L;;;;;N;;;;; +1888E;TANGUT COMPONENT-143;Lo;0;L;;;;;N;;;;; +1888F;TANGUT COMPONENT-144;Lo;0;L;;;;;N;;;;; +18890;TANGUT COMPONENT-145;Lo;0;L;;;;;N;;;;; +18891;TANGUT COMPONENT-146;Lo;0;L;;;;;N;;;;; +18892;TANGUT COMPONENT-147;Lo;0;L;;;;;N;;;;; +18893;TANGUT COMPONENT-148;Lo;0;L;;;;;N;;;;; +18894;TANGUT COMPONENT-149;Lo;0;L;;;;;N;;;;; +18895;TANGUT COMPONENT-150;Lo;0;L;;;;;N;;;;; +18896;TANGUT COMPONENT-151;Lo;0;L;;;;;N;;;;; +18897;TANGUT COMPONENT-152;Lo;0;L;;;;;N;;;;; +18898;TANGUT COMPONENT-153;Lo;0;L;;;;;N;;;;; +18899;TANGUT COMPONENT-154;Lo;0;L;;;;;N;;;;; +1889A;TANGUT COMPONENT-155;Lo;0;L;;;;;N;;;;; +1889B;TANGUT COMPONENT-156;Lo;0;L;;;;;N;;;;; +1889C;TANGUT COMPONENT-157;Lo;0;L;;;;;N;;;;; +1889D;TANGUT COMPONENT-158;Lo;0;L;;;;;N;;;;; +1889E;TANGUT COMPONENT-159;Lo;0;L;;;;;N;;;;; +1889F;TANGUT COMPONENT-160;Lo;0;L;;;;;N;;;;; +188A0;TANGUT COMPONENT-161;Lo;0;L;;;;;N;;;;; +188A1;TANGUT COMPONENT-162;Lo;0;L;;;;;N;;;;; +188A2;TANGUT COMPONENT-163;Lo;0;L;;;;;N;;;;; +188A3;TANGUT COMPONENT-164;Lo;0;L;;;;;N;;;;; +188A4;TANGUT COMPONENT-165;Lo;0;L;;;;;N;;;;; +188A5;TANGUT COMPONENT-166;Lo;0;L;;;;;N;;;;; +188A6;TANGUT COMPONENT-167;Lo;0;L;;;;;N;;;;; +188A7;TANGUT COMPONENT-168;Lo;0;L;;;;;N;;;;; +188A8;TANGUT COMPONENT-169;Lo;0;L;;;;;N;;;;; +188A9;TANGUT COMPONENT-170;Lo;0;L;;;;;N;;;;; +188AA;TANGUT COMPONENT-171;Lo;0;L;;;;;N;;;;; +188AB;TANGUT COMPONENT-172;Lo;0;L;;;;;N;;;;; +188AC;TANGUT COMPONENT-173;Lo;0;L;;;;;N;;;;; +188AD;TANGUT COMPONENT-174;Lo;0;L;;;;;N;;;;; +188AE;TANGUT COMPONENT-175;Lo;0;L;;;;;N;;;;; +188AF;TANGUT COMPONENT-176;Lo;0;L;;;;;N;;;;; +188B0;TANGUT COMPONENT-177;Lo;0;L;;;;;N;;;;; +188B1;TANGUT COMPONENT-178;Lo;0;L;;;;;N;;;;; +188B2;TANGUT COMPONENT-179;Lo;0;L;;;;;N;;;;; +188B3;TANGUT COMPONENT-180;Lo;0;L;;;;;N;;;;; +188B4;TANGUT COMPONENT-181;Lo;0;L;;;;;N;;;;; +188B5;TANGUT COMPONENT-182;Lo;0;L;;;;;N;;;;; +188B6;TANGUT COMPONENT-183;Lo;0;L;;;;;N;;;;; +188B7;TANGUT COMPONENT-184;Lo;0;L;;;;;N;;;;; +188B8;TANGUT COMPONENT-185;Lo;0;L;;;;;N;;;;; +188B9;TANGUT COMPONENT-186;Lo;0;L;;;;;N;;;;; +188BA;TANGUT COMPONENT-187;Lo;0;L;;;;;N;;;;; +188BB;TANGUT COMPONENT-188;Lo;0;L;;;;;N;;;;; +188BC;TANGUT COMPONENT-189;Lo;0;L;;;;;N;;;;; +188BD;TANGUT COMPONENT-190;Lo;0;L;;;;;N;;;;; +188BE;TANGUT COMPONENT-191;Lo;0;L;;;;;N;;;;; +188BF;TANGUT COMPONENT-192;Lo;0;L;;;;;N;;;;; +188C0;TANGUT COMPONENT-193;Lo;0;L;;;;;N;;;;; +188C1;TANGUT COMPONENT-194;Lo;0;L;;;;;N;;;;; +188C2;TANGUT COMPONENT-195;Lo;0;L;;;;;N;;;;; +188C3;TANGUT COMPONENT-196;Lo;0;L;;;;;N;;;;; +188C4;TANGUT COMPONENT-197;Lo;0;L;;;;;N;;;;; +188C5;TANGUT COMPONENT-198;Lo;0;L;;;;;N;;;;; +188C6;TANGUT COMPONENT-199;Lo;0;L;;;;;N;;;;; +188C7;TANGUT COMPONENT-200;Lo;0;L;;;;;N;;;;; +188C8;TANGUT COMPONENT-201;Lo;0;L;;;;;N;;;;; +188C9;TANGUT COMPONENT-202;Lo;0;L;;;;;N;;;;; +188CA;TANGUT COMPONENT-203;Lo;0;L;;;;;N;;;;; +188CB;TANGUT COMPONENT-204;Lo;0;L;;;;;N;;;;; +188CC;TANGUT COMPONENT-205;Lo;0;L;;;;;N;;;;; +188CD;TANGUT COMPONENT-206;Lo;0;L;;;;;N;;;;; +188CE;TANGUT COMPONENT-207;Lo;0;L;;;;;N;;;;; +188CF;TANGUT COMPONENT-208;Lo;0;L;;;;;N;;;;; +188D0;TANGUT COMPONENT-209;Lo;0;L;;;;;N;;;;; +188D1;TANGUT COMPONENT-210;Lo;0;L;;;;;N;;;;; +188D2;TANGUT COMPONENT-211;Lo;0;L;;;;;N;;;;; +188D3;TANGUT COMPONENT-212;Lo;0;L;;;;;N;;;;; +188D4;TANGUT COMPONENT-213;Lo;0;L;;;;;N;;;;; +188D5;TANGUT COMPONENT-214;Lo;0;L;;;;;N;;;;; +188D6;TANGUT COMPONENT-215;Lo;0;L;;;;;N;;;;; +188D7;TANGUT COMPONENT-216;Lo;0;L;;;;;N;;;;; +188D8;TANGUT COMPONENT-217;Lo;0;L;;;;;N;;;;; +188D9;TANGUT COMPONENT-218;Lo;0;L;;;;;N;;;;; +188DA;TANGUT COMPONENT-219;Lo;0;L;;;;;N;;;;; +188DB;TANGUT COMPONENT-220;Lo;0;L;;;;;N;;;;; +188DC;TANGUT COMPONENT-221;Lo;0;L;;;;;N;;;;; +188DD;TANGUT COMPONENT-222;Lo;0;L;;;;;N;;;;; +188DE;TANGUT COMPONENT-223;Lo;0;L;;;;;N;;;;; +188DF;TANGUT COMPONENT-224;Lo;0;L;;;;;N;;;;; +188E0;TANGUT COMPONENT-225;Lo;0;L;;;;;N;;;;; +188E1;TANGUT COMPONENT-226;Lo;0;L;;;;;N;;;;; +188E2;TANGUT COMPONENT-227;Lo;0;L;;;;;N;;;;; +188E3;TANGUT COMPONENT-228;Lo;0;L;;;;;N;;;;; +188E4;TANGUT COMPONENT-229;Lo;0;L;;;;;N;;;;; +188E5;TANGUT COMPONENT-230;Lo;0;L;;;;;N;;;;; +188E6;TANGUT COMPONENT-231;Lo;0;L;;;;;N;;;;; +188E7;TANGUT COMPONENT-232;Lo;0;L;;;;;N;;;;; +188E8;TANGUT COMPONENT-233;Lo;0;L;;;;;N;;;;; +188E9;TANGUT COMPONENT-234;Lo;0;L;;;;;N;;;;; +188EA;TANGUT COMPONENT-235;Lo;0;L;;;;;N;;;;; +188EB;TANGUT COMPONENT-236;Lo;0;L;;;;;N;;;;; +188EC;TANGUT COMPONENT-237;Lo;0;L;;;;;N;;;;; +188ED;TANGUT COMPONENT-238;Lo;0;L;;;;;N;;;;; +188EE;TANGUT COMPONENT-239;Lo;0;L;;;;;N;;;;; +188EF;TANGUT COMPONENT-240;Lo;0;L;;;;;N;;;;; +188F0;TANGUT COMPONENT-241;Lo;0;L;;;;;N;;;;; +188F1;TANGUT COMPONENT-242;Lo;0;L;;;;;N;;;;; +188F2;TANGUT COMPONENT-243;Lo;0;L;;;;;N;;;;; +188F3;TANGUT COMPONENT-244;Lo;0;L;;;;;N;;;;; +188F4;TANGUT COMPONENT-245;Lo;0;L;;;;;N;;;;; +188F5;TANGUT COMPONENT-246;Lo;0;L;;;;;N;;;;; +188F6;TANGUT COMPONENT-247;Lo;0;L;;;;;N;;;;; +188F7;TANGUT COMPONENT-248;Lo;0;L;;;;;N;;;;; +188F8;TANGUT COMPONENT-249;Lo;0;L;;;;;N;;;;; +188F9;TANGUT COMPONENT-250;Lo;0;L;;;;;N;;;;; +188FA;TANGUT COMPONENT-251;Lo;0;L;;;;;N;;;;; +188FB;TANGUT COMPONENT-252;Lo;0;L;;;;;N;;;;; +188FC;TANGUT COMPONENT-253;Lo;0;L;;;;;N;;;;; +188FD;TANGUT COMPONENT-254;Lo;0;L;;;;;N;;;;; +188FE;TANGUT COMPONENT-255;Lo;0;L;;;;;N;;;;; +188FF;TANGUT COMPONENT-256;Lo;0;L;;;;;N;;;;; +18900;TANGUT COMPONENT-257;Lo;0;L;;;;;N;;;;; +18901;TANGUT COMPONENT-258;Lo;0;L;;;;;N;;;;; +18902;TANGUT COMPONENT-259;Lo;0;L;;;;;N;;;;; +18903;TANGUT COMPONENT-260;Lo;0;L;;;;;N;;;;; +18904;TANGUT COMPONENT-261;Lo;0;L;;;;;N;;;;; +18905;TANGUT COMPONENT-262;Lo;0;L;;;;;N;;;;; +18906;TANGUT COMPONENT-263;Lo;0;L;;;;;N;;;;; +18907;TANGUT COMPONENT-264;Lo;0;L;;;;;N;;;;; +18908;TANGUT COMPONENT-265;Lo;0;L;;;;;N;;;;; +18909;TANGUT COMPONENT-266;Lo;0;L;;;;;N;;;;; +1890A;TANGUT COMPONENT-267;Lo;0;L;;;;;N;;;;; +1890B;TANGUT COMPONENT-268;Lo;0;L;;;;;N;;;;; +1890C;TANGUT COMPONENT-269;Lo;0;L;;;;;N;;;;; +1890D;TANGUT COMPONENT-270;Lo;0;L;;;;;N;;;;; +1890E;TANGUT COMPONENT-271;Lo;0;L;;;;;N;;;;; +1890F;TANGUT COMPONENT-272;Lo;0;L;;;;;N;;;;; +18910;TANGUT COMPONENT-273;Lo;0;L;;;;;N;;;;; +18911;TANGUT COMPONENT-274;Lo;0;L;;;;;N;;;;; +18912;TANGUT COMPONENT-275;Lo;0;L;;;;;N;;;;; +18913;TANGUT COMPONENT-276;Lo;0;L;;;;;N;;;;; +18914;TANGUT COMPONENT-277;Lo;0;L;;;;;N;;;;; +18915;TANGUT COMPONENT-278;Lo;0;L;;;;;N;;;;; +18916;TANGUT COMPONENT-279;Lo;0;L;;;;;N;;;;; +18917;TANGUT COMPONENT-280;Lo;0;L;;;;;N;;;;; +18918;TANGUT COMPONENT-281;Lo;0;L;;;;;N;;;;; +18919;TANGUT COMPONENT-282;Lo;0;L;;;;;N;;;;; +1891A;TANGUT COMPONENT-283;Lo;0;L;;;;;N;;;;; +1891B;TANGUT COMPONENT-284;Lo;0;L;;;;;N;;;;; +1891C;TANGUT COMPONENT-285;Lo;0;L;;;;;N;;;;; +1891D;TANGUT COMPONENT-286;Lo;0;L;;;;;N;;;;; +1891E;TANGUT COMPONENT-287;Lo;0;L;;;;;N;;;;; +1891F;TANGUT COMPONENT-288;Lo;0;L;;;;;N;;;;; +18920;TANGUT COMPONENT-289;Lo;0;L;;;;;N;;;;; +18921;TANGUT COMPONENT-290;Lo;0;L;;;;;N;;;;; +18922;TANGUT COMPONENT-291;Lo;0;L;;;;;N;;;;; +18923;TANGUT COMPONENT-292;Lo;0;L;;;;;N;;;;; +18924;TANGUT COMPONENT-293;Lo;0;L;;;;;N;;;;; +18925;TANGUT COMPONENT-294;Lo;0;L;;;;;N;;;;; +18926;TANGUT COMPONENT-295;Lo;0;L;;;;;N;;;;; +18927;TANGUT COMPONENT-296;Lo;0;L;;;;;N;;;;; +18928;TANGUT COMPONENT-297;Lo;0;L;;;;;N;;;;; +18929;TANGUT COMPONENT-298;Lo;0;L;;;;;N;;;;; +1892A;TANGUT COMPONENT-299;Lo;0;L;;;;;N;;;;; +1892B;TANGUT COMPONENT-300;Lo;0;L;;;;;N;;;;; +1892C;TANGUT COMPONENT-301;Lo;0;L;;;;;N;;;;; +1892D;TANGUT COMPONENT-302;Lo;0;L;;;;;N;;;;; +1892E;TANGUT COMPONENT-303;Lo;0;L;;;;;N;;;;; +1892F;TANGUT COMPONENT-304;Lo;0;L;;;;;N;;;;; +18930;TANGUT COMPONENT-305;Lo;0;L;;;;;N;;;;; +18931;TANGUT COMPONENT-306;Lo;0;L;;;;;N;;;;; +18932;TANGUT COMPONENT-307;Lo;0;L;;;;;N;;;;; +18933;TANGUT COMPONENT-308;Lo;0;L;;;;;N;;;;; +18934;TANGUT COMPONENT-309;Lo;0;L;;;;;N;;;;; +18935;TANGUT COMPONENT-310;Lo;0;L;;;;;N;;;;; +18936;TANGUT COMPONENT-311;Lo;0;L;;;;;N;;;;; +18937;TANGUT COMPONENT-312;Lo;0;L;;;;;N;;;;; +18938;TANGUT COMPONENT-313;Lo;0;L;;;;;N;;;;; +18939;TANGUT COMPONENT-314;Lo;0;L;;;;;N;;;;; +1893A;TANGUT COMPONENT-315;Lo;0;L;;;;;N;;;;; +1893B;TANGUT COMPONENT-316;Lo;0;L;;;;;N;;;;; +1893C;TANGUT COMPONENT-317;Lo;0;L;;;;;N;;;;; +1893D;TANGUT COMPONENT-318;Lo;0;L;;;;;N;;;;; +1893E;TANGUT COMPONENT-319;Lo;0;L;;;;;N;;;;; +1893F;TANGUT COMPONENT-320;Lo;0;L;;;;;N;;;;; +18940;TANGUT COMPONENT-321;Lo;0;L;;;;;N;;;;; +18941;TANGUT COMPONENT-322;Lo;0;L;;;;;N;;;;; +18942;TANGUT COMPONENT-323;Lo;0;L;;;;;N;;;;; +18943;TANGUT COMPONENT-324;Lo;0;L;;;;;N;;;;; +18944;TANGUT COMPONENT-325;Lo;0;L;;;;;N;;;;; +18945;TANGUT COMPONENT-326;Lo;0;L;;;;;N;;;;; +18946;TANGUT COMPONENT-327;Lo;0;L;;;;;N;;;;; +18947;TANGUT COMPONENT-328;Lo;0;L;;;;;N;;;;; +18948;TANGUT COMPONENT-329;Lo;0;L;;;;;N;;;;; +18949;TANGUT COMPONENT-330;Lo;0;L;;;;;N;;;;; +1894A;TANGUT COMPONENT-331;Lo;0;L;;;;;N;;;;; +1894B;TANGUT COMPONENT-332;Lo;0;L;;;;;N;;;;; +1894C;TANGUT COMPONENT-333;Lo;0;L;;;;;N;;;;; +1894D;TANGUT COMPONENT-334;Lo;0;L;;;;;N;;;;; +1894E;TANGUT COMPONENT-335;Lo;0;L;;;;;N;;;;; +1894F;TANGUT COMPONENT-336;Lo;0;L;;;;;N;;;;; +18950;TANGUT COMPONENT-337;Lo;0;L;;;;;N;;;;; +18951;TANGUT COMPONENT-338;Lo;0;L;;;;;N;;;;; +18952;TANGUT COMPONENT-339;Lo;0;L;;;;;N;;;;; +18953;TANGUT COMPONENT-340;Lo;0;L;;;;;N;;;;; +18954;TANGUT COMPONENT-341;Lo;0;L;;;;;N;;;;; +18955;TANGUT COMPONENT-342;Lo;0;L;;;;;N;;;;; +18956;TANGUT COMPONENT-343;Lo;0;L;;;;;N;;;;; +18957;TANGUT COMPONENT-344;Lo;0;L;;;;;N;;;;; +18958;TANGUT COMPONENT-345;Lo;0;L;;;;;N;;;;; +18959;TANGUT COMPONENT-346;Lo;0;L;;;;;N;;;;; +1895A;TANGUT COMPONENT-347;Lo;0;L;;;;;N;;;;; +1895B;TANGUT COMPONENT-348;Lo;0;L;;;;;N;;;;; +1895C;TANGUT COMPONENT-349;Lo;0;L;;;;;N;;;;; +1895D;TANGUT COMPONENT-350;Lo;0;L;;;;;N;;;;; +1895E;TANGUT COMPONENT-351;Lo;0;L;;;;;N;;;;; +1895F;TANGUT COMPONENT-352;Lo;0;L;;;;;N;;;;; +18960;TANGUT COMPONENT-353;Lo;0;L;;;;;N;;;;; +18961;TANGUT COMPONENT-354;Lo;0;L;;;;;N;;;;; +18962;TANGUT COMPONENT-355;Lo;0;L;;;;;N;;;;; +18963;TANGUT COMPONENT-356;Lo;0;L;;;;;N;;;;; +18964;TANGUT COMPONENT-357;Lo;0;L;;;;;N;;;;; +18965;TANGUT COMPONENT-358;Lo;0;L;;;;;N;;;;; +18966;TANGUT COMPONENT-359;Lo;0;L;;;;;N;;;;; +18967;TANGUT COMPONENT-360;Lo;0;L;;;;;N;;;;; +18968;TANGUT COMPONENT-361;Lo;0;L;;;;;N;;;;; +18969;TANGUT COMPONENT-362;Lo;0;L;;;;;N;;;;; +1896A;TANGUT COMPONENT-363;Lo;0;L;;;;;N;;;;; +1896B;TANGUT COMPONENT-364;Lo;0;L;;;;;N;;;;; +1896C;TANGUT COMPONENT-365;Lo;0;L;;;;;N;;;;; +1896D;TANGUT COMPONENT-366;Lo;0;L;;;;;N;;;;; +1896E;TANGUT COMPONENT-367;Lo;0;L;;;;;N;;;;; +1896F;TANGUT COMPONENT-368;Lo;0;L;;;;;N;;;;; +18970;TANGUT COMPONENT-369;Lo;0;L;;;;;N;;;;; +18971;TANGUT COMPONENT-370;Lo;0;L;;;;;N;;;;; +18972;TANGUT COMPONENT-371;Lo;0;L;;;;;N;;;;; +18973;TANGUT COMPONENT-372;Lo;0;L;;;;;N;;;;; +18974;TANGUT COMPONENT-373;Lo;0;L;;;;;N;;;;; +18975;TANGUT COMPONENT-374;Lo;0;L;;;;;N;;;;; +18976;TANGUT COMPONENT-375;Lo;0;L;;;;;N;;;;; +18977;TANGUT COMPONENT-376;Lo;0;L;;;;;N;;;;; +18978;TANGUT COMPONENT-377;Lo;0;L;;;;;N;;;;; +18979;TANGUT COMPONENT-378;Lo;0;L;;;;;N;;;;; +1897A;TANGUT COMPONENT-379;Lo;0;L;;;;;N;;;;; +1897B;TANGUT COMPONENT-380;Lo;0;L;;;;;N;;;;; +1897C;TANGUT COMPONENT-381;Lo;0;L;;;;;N;;;;; +1897D;TANGUT COMPONENT-382;Lo;0;L;;;;;N;;;;; +1897E;TANGUT COMPONENT-383;Lo;0;L;;;;;N;;;;; +1897F;TANGUT COMPONENT-384;Lo;0;L;;;;;N;;;;; +18980;TANGUT COMPONENT-385;Lo;0;L;;;;;N;;;;; +18981;TANGUT COMPONENT-386;Lo;0;L;;;;;N;;;;; +18982;TANGUT COMPONENT-387;Lo;0;L;;;;;N;;;;; +18983;TANGUT COMPONENT-388;Lo;0;L;;;;;N;;;;; +18984;TANGUT COMPONENT-389;Lo;0;L;;;;;N;;;;; +18985;TANGUT COMPONENT-390;Lo;0;L;;;;;N;;;;; +18986;TANGUT COMPONENT-391;Lo;0;L;;;;;N;;;;; +18987;TANGUT COMPONENT-392;Lo;0;L;;;;;N;;;;; +18988;TANGUT COMPONENT-393;Lo;0;L;;;;;N;;;;; +18989;TANGUT COMPONENT-394;Lo;0;L;;;;;N;;;;; +1898A;TANGUT COMPONENT-395;Lo;0;L;;;;;N;;;;; +1898B;TANGUT COMPONENT-396;Lo;0;L;;;;;N;;;;; +1898C;TANGUT COMPONENT-397;Lo;0;L;;;;;N;;;;; +1898D;TANGUT COMPONENT-398;Lo;0;L;;;;;N;;;;; +1898E;TANGUT COMPONENT-399;Lo;0;L;;;;;N;;;;; +1898F;TANGUT COMPONENT-400;Lo;0;L;;;;;N;;;;; +18990;TANGUT COMPONENT-401;Lo;0;L;;;;;N;;;;; +18991;TANGUT COMPONENT-402;Lo;0;L;;;;;N;;;;; +18992;TANGUT COMPONENT-403;Lo;0;L;;;;;N;;;;; +18993;TANGUT COMPONENT-404;Lo;0;L;;;;;N;;;;; +18994;TANGUT COMPONENT-405;Lo;0;L;;;;;N;;;;; +18995;TANGUT COMPONENT-406;Lo;0;L;;;;;N;;;;; +18996;TANGUT COMPONENT-407;Lo;0;L;;;;;N;;;;; +18997;TANGUT COMPONENT-408;Lo;0;L;;;;;N;;;;; +18998;TANGUT COMPONENT-409;Lo;0;L;;;;;N;;;;; +18999;TANGUT COMPONENT-410;Lo;0;L;;;;;N;;;;; +1899A;TANGUT COMPONENT-411;Lo;0;L;;;;;N;;;;; +1899B;TANGUT COMPONENT-412;Lo;0;L;;;;;N;;;;; +1899C;TANGUT COMPONENT-413;Lo;0;L;;;;;N;;;;; +1899D;TANGUT COMPONENT-414;Lo;0;L;;;;;N;;;;; +1899E;TANGUT COMPONENT-415;Lo;0;L;;;;;N;;;;; +1899F;TANGUT COMPONENT-416;Lo;0;L;;;;;N;;;;; +189A0;TANGUT COMPONENT-417;Lo;0;L;;;;;N;;;;; +189A1;TANGUT COMPONENT-418;Lo;0;L;;;;;N;;;;; +189A2;TANGUT COMPONENT-419;Lo;0;L;;;;;N;;;;; +189A3;TANGUT COMPONENT-420;Lo;0;L;;;;;N;;;;; +189A4;TANGUT COMPONENT-421;Lo;0;L;;;;;N;;;;; +189A5;TANGUT COMPONENT-422;Lo;0;L;;;;;N;;;;; +189A6;TANGUT COMPONENT-423;Lo;0;L;;;;;N;;;;; +189A7;TANGUT COMPONENT-424;Lo;0;L;;;;;N;;;;; +189A8;TANGUT COMPONENT-425;Lo;0;L;;;;;N;;;;; +189A9;TANGUT COMPONENT-426;Lo;0;L;;;;;N;;;;; +189AA;TANGUT COMPONENT-427;Lo;0;L;;;;;N;;;;; +189AB;TANGUT COMPONENT-428;Lo;0;L;;;;;N;;;;; +189AC;TANGUT COMPONENT-429;Lo;0;L;;;;;N;;;;; +189AD;TANGUT COMPONENT-430;Lo;0;L;;;;;N;;;;; +189AE;TANGUT COMPONENT-431;Lo;0;L;;;;;N;;;;; +189AF;TANGUT COMPONENT-432;Lo;0;L;;;;;N;;;;; +189B0;TANGUT COMPONENT-433;Lo;0;L;;;;;N;;;;; +189B1;TANGUT COMPONENT-434;Lo;0;L;;;;;N;;;;; +189B2;TANGUT COMPONENT-435;Lo;0;L;;;;;N;;;;; +189B3;TANGUT COMPONENT-436;Lo;0;L;;;;;N;;;;; +189B4;TANGUT COMPONENT-437;Lo;0;L;;;;;N;;;;; +189B5;TANGUT COMPONENT-438;Lo;0;L;;;;;N;;;;; +189B6;TANGUT COMPONENT-439;Lo;0;L;;;;;N;;;;; +189B7;TANGUT COMPONENT-440;Lo;0;L;;;;;N;;;;; +189B8;TANGUT COMPONENT-441;Lo;0;L;;;;;N;;;;; +189B9;TANGUT COMPONENT-442;Lo;0;L;;;;;N;;;;; +189BA;TANGUT COMPONENT-443;Lo;0;L;;;;;N;;;;; +189BB;TANGUT COMPONENT-444;Lo;0;L;;;;;N;;;;; +189BC;TANGUT COMPONENT-445;Lo;0;L;;;;;N;;;;; +189BD;TANGUT COMPONENT-446;Lo;0;L;;;;;N;;;;; +189BE;TANGUT COMPONENT-447;Lo;0;L;;;;;N;;;;; +189BF;TANGUT COMPONENT-448;Lo;0;L;;;;;N;;;;; +189C0;TANGUT COMPONENT-449;Lo;0;L;;;;;N;;;;; +189C1;TANGUT COMPONENT-450;Lo;0;L;;;;;N;;;;; +189C2;TANGUT COMPONENT-451;Lo;0;L;;;;;N;;;;; +189C3;TANGUT COMPONENT-452;Lo;0;L;;;;;N;;;;; +189C4;TANGUT COMPONENT-453;Lo;0;L;;;;;N;;;;; +189C5;TANGUT COMPONENT-454;Lo;0;L;;;;;N;;;;; +189C6;TANGUT COMPONENT-455;Lo;0;L;;;;;N;;;;; +189C7;TANGUT COMPONENT-456;Lo;0;L;;;;;N;;;;; +189C8;TANGUT COMPONENT-457;Lo;0;L;;;;;N;;;;; +189C9;TANGUT COMPONENT-458;Lo;0;L;;;;;N;;;;; +189CA;TANGUT COMPONENT-459;Lo;0;L;;;;;N;;;;; +189CB;TANGUT COMPONENT-460;Lo;0;L;;;;;N;;;;; +189CC;TANGUT COMPONENT-461;Lo;0;L;;;;;N;;;;; +189CD;TANGUT COMPONENT-462;Lo;0;L;;;;;N;;;;; +189CE;TANGUT COMPONENT-463;Lo;0;L;;;;;N;;;;; +189CF;TANGUT COMPONENT-464;Lo;0;L;;;;;N;;;;; +189D0;TANGUT COMPONENT-465;Lo;0;L;;;;;N;;;;; +189D1;TANGUT COMPONENT-466;Lo;0;L;;;;;N;;;;; +189D2;TANGUT COMPONENT-467;Lo;0;L;;;;;N;;;;; +189D3;TANGUT COMPONENT-468;Lo;0;L;;;;;N;;;;; +189D4;TANGUT COMPONENT-469;Lo;0;L;;;;;N;;;;; +189D5;TANGUT COMPONENT-470;Lo;0;L;;;;;N;;;;; +189D6;TANGUT COMPONENT-471;Lo;0;L;;;;;N;;;;; +189D7;TANGUT COMPONENT-472;Lo;0;L;;;;;N;;;;; +189D8;TANGUT COMPONENT-473;Lo;0;L;;;;;N;;;;; +189D9;TANGUT COMPONENT-474;Lo;0;L;;;;;N;;;;; +189DA;TANGUT COMPONENT-475;Lo;0;L;;;;;N;;;;; +189DB;TANGUT COMPONENT-476;Lo;0;L;;;;;N;;;;; +189DC;TANGUT COMPONENT-477;Lo;0;L;;;;;N;;;;; +189DD;TANGUT COMPONENT-478;Lo;0;L;;;;;N;;;;; +189DE;TANGUT COMPONENT-479;Lo;0;L;;;;;N;;;;; +189DF;TANGUT COMPONENT-480;Lo;0;L;;;;;N;;;;; +189E0;TANGUT COMPONENT-481;Lo;0;L;;;;;N;;;;; +189E1;TANGUT COMPONENT-482;Lo;0;L;;;;;N;;;;; +189E2;TANGUT COMPONENT-483;Lo;0;L;;;;;N;;;;; +189E3;TANGUT COMPONENT-484;Lo;0;L;;;;;N;;;;; +189E4;TANGUT COMPONENT-485;Lo;0;L;;;;;N;;;;; +189E5;TANGUT COMPONENT-486;Lo;0;L;;;;;N;;;;; +189E6;TANGUT COMPONENT-487;Lo;0;L;;;;;N;;;;; +189E7;TANGUT COMPONENT-488;Lo;0;L;;;;;N;;;;; +189E8;TANGUT COMPONENT-489;Lo;0;L;;;;;N;;;;; +189E9;TANGUT COMPONENT-490;Lo;0;L;;;;;N;;;;; +189EA;TANGUT COMPONENT-491;Lo;0;L;;;;;N;;;;; +189EB;TANGUT COMPONENT-492;Lo;0;L;;;;;N;;;;; +189EC;TANGUT COMPONENT-493;Lo;0;L;;;;;N;;;;; +189ED;TANGUT COMPONENT-494;Lo;0;L;;;;;N;;;;; +189EE;TANGUT COMPONENT-495;Lo;0;L;;;;;N;;;;; +189EF;TANGUT COMPONENT-496;Lo;0;L;;;;;N;;;;; +189F0;TANGUT COMPONENT-497;Lo;0;L;;;;;N;;;;; +189F1;TANGUT COMPONENT-498;Lo;0;L;;;;;N;;;;; +189F2;TANGUT COMPONENT-499;Lo;0;L;;;;;N;;;;; +189F3;TANGUT COMPONENT-500;Lo;0;L;;;;;N;;;;; +189F4;TANGUT COMPONENT-501;Lo;0;L;;;;;N;;;;; +189F5;TANGUT COMPONENT-502;Lo;0;L;;;;;N;;;;; +189F6;TANGUT COMPONENT-503;Lo;0;L;;;;;N;;;;; +189F7;TANGUT COMPONENT-504;Lo;0;L;;;;;N;;;;; +189F8;TANGUT COMPONENT-505;Lo;0;L;;;;;N;;;;; +189F9;TANGUT COMPONENT-506;Lo;0;L;;;;;N;;;;; +189FA;TANGUT COMPONENT-507;Lo;0;L;;;;;N;;;;; +189FB;TANGUT COMPONENT-508;Lo;0;L;;;;;N;;;;; +189FC;TANGUT COMPONENT-509;Lo;0;L;;;;;N;;;;; +189FD;TANGUT COMPONENT-510;Lo;0;L;;;;;N;;;;; +189FE;TANGUT COMPONENT-511;Lo;0;L;;;;;N;;;;; +189FF;TANGUT COMPONENT-512;Lo;0;L;;;;;N;;;;; +18A00;TANGUT COMPONENT-513;Lo;0;L;;;;;N;;;;; +18A01;TANGUT COMPONENT-514;Lo;0;L;;;;;N;;;;; +18A02;TANGUT COMPONENT-515;Lo;0;L;;;;;N;;;;; +18A03;TANGUT COMPONENT-516;Lo;0;L;;;;;N;;;;; +18A04;TANGUT COMPONENT-517;Lo;0;L;;;;;N;;;;; +18A05;TANGUT COMPONENT-518;Lo;0;L;;;;;N;;;;; +18A06;TANGUT COMPONENT-519;Lo;0;L;;;;;N;;;;; +18A07;TANGUT COMPONENT-520;Lo;0;L;;;;;N;;;;; +18A08;TANGUT COMPONENT-521;Lo;0;L;;;;;N;;;;; +18A09;TANGUT COMPONENT-522;Lo;0;L;;;;;N;;;;; +18A0A;TANGUT COMPONENT-523;Lo;0;L;;;;;N;;;;; +18A0B;TANGUT COMPONENT-524;Lo;0;L;;;;;N;;;;; +18A0C;TANGUT COMPONENT-525;Lo;0;L;;;;;N;;;;; +18A0D;TANGUT COMPONENT-526;Lo;0;L;;;;;N;;;;; +18A0E;TANGUT COMPONENT-527;Lo;0;L;;;;;N;;;;; +18A0F;TANGUT COMPONENT-528;Lo;0;L;;;;;N;;;;; +18A10;TANGUT COMPONENT-529;Lo;0;L;;;;;N;;;;; +18A11;TANGUT COMPONENT-530;Lo;0;L;;;;;N;;;;; +18A12;TANGUT COMPONENT-531;Lo;0;L;;;;;N;;;;; +18A13;TANGUT COMPONENT-532;Lo;0;L;;;;;N;;;;; +18A14;TANGUT COMPONENT-533;Lo;0;L;;;;;N;;;;; +18A15;TANGUT COMPONENT-534;Lo;0;L;;;;;N;;;;; +18A16;TANGUT COMPONENT-535;Lo;0;L;;;;;N;;;;; +18A17;TANGUT COMPONENT-536;Lo;0;L;;;;;N;;;;; +18A18;TANGUT COMPONENT-537;Lo;0;L;;;;;N;;;;; +18A19;TANGUT COMPONENT-538;Lo;0;L;;;;;N;;;;; +18A1A;TANGUT COMPONENT-539;Lo;0;L;;;;;N;;;;; +18A1B;TANGUT COMPONENT-540;Lo;0;L;;;;;N;;;;; +18A1C;TANGUT COMPONENT-541;Lo;0;L;;;;;N;;;;; +18A1D;TANGUT COMPONENT-542;Lo;0;L;;;;;N;;;;; +18A1E;TANGUT COMPONENT-543;Lo;0;L;;;;;N;;;;; +18A1F;TANGUT COMPONENT-544;Lo;0;L;;;;;N;;;;; +18A20;TANGUT COMPONENT-545;Lo;0;L;;;;;N;;;;; +18A21;TANGUT COMPONENT-546;Lo;0;L;;;;;N;;;;; +18A22;TANGUT COMPONENT-547;Lo;0;L;;;;;N;;;;; +18A23;TANGUT COMPONENT-548;Lo;0;L;;;;;N;;;;; +18A24;TANGUT COMPONENT-549;Lo;0;L;;;;;N;;;;; +18A25;TANGUT COMPONENT-550;Lo;0;L;;;;;N;;;;; +18A26;TANGUT COMPONENT-551;Lo;0;L;;;;;N;;;;; +18A27;TANGUT COMPONENT-552;Lo;0;L;;;;;N;;;;; +18A28;TANGUT COMPONENT-553;Lo;0;L;;;;;N;;;;; +18A29;TANGUT COMPONENT-554;Lo;0;L;;;;;N;;;;; +18A2A;TANGUT COMPONENT-555;Lo;0;L;;;;;N;;;;; +18A2B;TANGUT COMPONENT-556;Lo;0;L;;;;;N;;;;; +18A2C;TANGUT COMPONENT-557;Lo;0;L;;;;;N;;;;; +18A2D;TANGUT COMPONENT-558;Lo;0;L;;;;;N;;;;; +18A2E;TANGUT COMPONENT-559;Lo;0;L;;;;;N;;;;; +18A2F;TANGUT COMPONENT-560;Lo;0;L;;;;;N;;;;; +18A30;TANGUT COMPONENT-561;Lo;0;L;;;;;N;;;;; +18A31;TANGUT COMPONENT-562;Lo;0;L;;;;;N;;;;; +18A32;TANGUT COMPONENT-563;Lo;0;L;;;;;N;;;;; +18A33;TANGUT COMPONENT-564;Lo;0;L;;;;;N;;;;; +18A34;TANGUT COMPONENT-565;Lo;0;L;;;;;N;;;;; +18A35;TANGUT COMPONENT-566;Lo;0;L;;;;;N;;;;; +18A36;TANGUT COMPONENT-567;Lo;0;L;;;;;N;;;;; +18A37;TANGUT COMPONENT-568;Lo;0;L;;;;;N;;;;; +18A38;TANGUT COMPONENT-569;Lo;0;L;;;;;N;;;;; +18A39;TANGUT COMPONENT-570;Lo;0;L;;;;;N;;;;; +18A3A;TANGUT COMPONENT-571;Lo;0;L;;;;;N;;;;; +18A3B;TANGUT COMPONENT-572;Lo;0;L;;;;;N;;;;; +18A3C;TANGUT COMPONENT-573;Lo;0;L;;;;;N;;;;; +18A3D;TANGUT COMPONENT-574;Lo;0;L;;;;;N;;;;; +18A3E;TANGUT COMPONENT-575;Lo;0;L;;;;;N;;;;; +18A3F;TANGUT COMPONENT-576;Lo;0;L;;;;;N;;;;; +18A40;TANGUT COMPONENT-577;Lo;0;L;;;;;N;;;;; +18A41;TANGUT COMPONENT-578;Lo;0;L;;;;;N;;;;; +18A42;TANGUT COMPONENT-579;Lo;0;L;;;;;N;;;;; +18A43;TANGUT COMPONENT-580;Lo;0;L;;;;;N;;;;; +18A44;TANGUT COMPONENT-581;Lo;0;L;;;;;N;;;;; +18A45;TANGUT COMPONENT-582;Lo;0;L;;;;;N;;;;; +18A46;TANGUT COMPONENT-583;Lo;0;L;;;;;N;;;;; +18A47;TANGUT COMPONENT-584;Lo;0;L;;;;;N;;;;; +18A48;TANGUT COMPONENT-585;Lo;0;L;;;;;N;;;;; +18A49;TANGUT COMPONENT-586;Lo;0;L;;;;;N;;;;; +18A4A;TANGUT COMPONENT-587;Lo;0;L;;;;;N;;;;; +18A4B;TANGUT COMPONENT-588;Lo;0;L;;;;;N;;;;; +18A4C;TANGUT COMPONENT-589;Lo;0;L;;;;;N;;;;; +18A4D;TANGUT COMPONENT-590;Lo;0;L;;;;;N;;;;; +18A4E;TANGUT COMPONENT-591;Lo;0;L;;;;;N;;;;; +18A4F;TANGUT COMPONENT-592;Lo;0;L;;;;;N;;;;; +18A50;TANGUT COMPONENT-593;Lo;0;L;;;;;N;;;;; +18A51;TANGUT COMPONENT-594;Lo;0;L;;;;;N;;;;; +18A52;TANGUT COMPONENT-595;Lo;0;L;;;;;N;;;;; +18A53;TANGUT COMPONENT-596;Lo;0;L;;;;;N;;;;; +18A54;TANGUT COMPONENT-597;Lo;0;L;;;;;N;;;;; +18A55;TANGUT COMPONENT-598;Lo;0;L;;;;;N;;;;; +18A56;TANGUT COMPONENT-599;Lo;0;L;;;;;N;;;;; +18A57;TANGUT COMPONENT-600;Lo;0;L;;;;;N;;;;; +18A58;TANGUT COMPONENT-601;Lo;0;L;;;;;N;;;;; +18A59;TANGUT COMPONENT-602;Lo;0;L;;;;;N;;;;; +18A5A;TANGUT COMPONENT-603;Lo;0;L;;;;;N;;;;; +18A5B;TANGUT COMPONENT-604;Lo;0;L;;;;;N;;;;; +18A5C;TANGUT COMPONENT-605;Lo;0;L;;;;;N;;;;; +18A5D;TANGUT COMPONENT-606;Lo;0;L;;;;;N;;;;; +18A5E;TANGUT COMPONENT-607;Lo;0;L;;;;;N;;;;; +18A5F;TANGUT COMPONENT-608;Lo;0;L;;;;;N;;;;; +18A60;TANGUT COMPONENT-609;Lo;0;L;;;;;N;;;;; +18A61;TANGUT COMPONENT-610;Lo;0;L;;;;;N;;;;; +18A62;TANGUT COMPONENT-611;Lo;0;L;;;;;N;;;;; +18A63;TANGUT COMPONENT-612;Lo;0;L;;;;;N;;;;; +18A64;TANGUT COMPONENT-613;Lo;0;L;;;;;N;;;;; +18A65;TANGUT COMPONENT-614;Lo;0;L;;;;;N;;;;; +18A66;TANGUT COMPONENT-615;Lo;0;L;;;;;N;;;;; +18A67;TANGUT COMPONENT-616;Lo;0;L;;;;;N;;;;; +18A68;TANGUT COMPONENT-617;Lo;0;L;;;;;N;;;;; +18A69;TANGUT COMPONENT-618;Lo;0;L;;;;;N;;;;; +18A6A;TANGUT COMPONENT-619;Lo;0;L;;;;;N;;;;; +18A6B;TANGUT COMPONENT-620;Lo;0;L;;;;;N;;;;; +18A6C;TANGUT COMPONENT-621;Lo;0;L;;;;;N;;;;; +18A6D;TANGUT COMPONENT-622;Lo;0;L;;;;;N;;;;; +18A6E;TANGUT COMPONENT-623;Lo;0;L;;;;;N;;;;; +18A6F;TANGUT COMPONENT-624;Lo;0;L;;;;;N;;;;; +18A70;TANGUT COMPONENT-625;Lo;0;L;;;;;N;;;;; +18A71;TANGUT COMPONENT-626;Lo;0;L;;;;;N;;;;; +18A72;TANGUT COMPONENT-627;Lo;0;L;;;;;N;;;;; +18A73;TANGUT COMPONENT-628;Lo;0;L;;;;;N;;;;; +18A74;TANGUT COMPONENT-629;Lo;0;L;;;;;N;;;;; +18A75;TANGUT COMPONENT-630;Lo;0;L;;;;;N;;;;; +18A76;TANGUT COMPONENT-631;Lo;0;L;;;;;N;;;;; +18A77;TANGUT COMPONENT-632;Lo;0;L;;;;;N;;;;; +18A78;TANGUT COMPONENT-633;Lo;0;L;;;;;N;;;;; +18A79;TANGUT COMPONENT-634;Lo;0;L;;;;;N;;;;; +18A7A;TANGUT COMPONENT-635;Lo;0;L;;;;;N;;;;; +18A7B;TANGUT COMPONENT-636;Lo;0;L;;;;;N;;;;; +18A7C;TANGUT COMPONENT-637;Lo;0;L;;;;;N;;;;; +18A7D;TANGUT COMPONENT-638;Lo;0;L;;;;;N;;;;; +18A7E;TANGUT COMPONENT-639;Lo;0;L;;;;;N;;;;; +18A7F;TANGUT COMPONENT-640;Lo;0;L;;;;;N;;;;; +18A80;TANGUT COMPONENT-641;Lo;0;L;;;;;N;;;;; +18A81;TANGUT COMPONENT-642;Lo;0;L;;;;;N;;;;; +18A82;TANGUT COMPONENT-643;Lo;0;L;;;;;N;;;;; +18A83;TANGUT COMPONENT-644;Lo;0;L;;;;;N;;;;; +18A84;TANGUT COMPONENT-645;Lo;0;L;;;;;N;;;;; +18A85;TANGUT COMPONENT-646;Lo;0;L;;;;;N;;;;; +18A86;TANGUT COMPONENT-647;Lo;0;L;;;;;N;;;;; +18A87;TANGUT COMPONENT-648;Lo;0;L;;;;;N;;;;; +18A88;TANGUT COMPONENT-649;Lo;0;L;;;;;N;;;;; +18A89;TANGUT COMPONENT-650;Lo;0;L;;;;;N;;;;; +18A8A;TANGUT COMPONENT-651;Lo;0;L;;;;;N;;;;; +18A8B;TANGUT COMPONENT-652;Lo;0;L;;;;;N;;;;; +18A8C;TANGUT COMPONENT-653;Lo;0;L;;;;;N;;;;; +18A8D;TANGUT COMPONENT-654;Lo;0;L;;;;;N;;;;; +18A8E;TANGUT COMPONENT-655;Lo;0;L;;;;;N;;;;; +18A8F;TANGUT COMPONENT-656;Lo;0;L;;;;;N;;;;; +18A90;TANGUT COMPONENT-657;Lo;0;L;;;;;N;;;;; +18A91;TANGUT COMPONENT-658;Lo;0;L;;;;;N;;;;; +18A92;TANGUT COMPONENT-659;Lo;0;L;;;;;N;;;;; +18A93;TANGUT COMPONENT-660;Lo;0;L;;;;;N;;;;; +18A94;TANGUT COMPONENT-661;Lo;0;L;;;;;N;;;;; +18A95;TANGUT COMPONENT-662;Lo;0;L;;;;;N;;;;; +18A96;TANGUT COMPONENT-663;Lo;0;L;;;;;N;;;;; +18A97;TANGUT COMPONENT-664;Lo;0;L;;;;;N;;;;; +18A98;TANGUT COMPONENT-665;Lo;0;L;;;;;N;;;;; +18A99;TANGUT COMPONENT-666;Lo;0;L;;;;;N;;;;; +18A9A;TANGUT COMPONENT-667;Lo;0;L;;;;;N;;;;; +18A9B;TANGUT COMPONENT-668;Lo;0;L;;;;;N;;;;; +18A9C;TANGUT COMPONENT-669;Lo;0;L;;;;;N;;;;; +18A9D;TANGUT COMPONENT-670;Lo;0;L;;;;;N;;;;; +18A9E;TANGUT COMPONENT-671;Lo;0;L;;;;;N;;;;; +18A9F;TANGUT COMPONENT-672;Lo;0;L;;;;;N;;;;; +18AA0;TANGUT COMPONENT-673;Lo;0;L;;;;;N;;;;; +18AA1;TANGUT COMPONENT-674;Lo;0;L;;;;;N;;;;; +18AA2;TANGUT COMPONENT-675;Lo;0;L;;;;;N;;;;; +18AA3;TANGUT COMPONENT-676;Lo;0;L;;;;;N;;;;; +18AA4;TANGUT COMPONENT-677;Lo;0;L;;;;;N;;;;; +18AA5;TANGUT COMPONENT-678;Lo;0;L;;;;;N;;;;; +18AA6;TANGUT COMPONENT-679;Lo;0;L;;;;;N;;;;; +18AA7;TANGUT COMPONENT-680;Lo;0;L;;;;;N;;;;; +18AA8;TANGUT COMPONENT-681;Lo;0;L;;;;;N;;;;; +18AA9;TANGUT COMPONENT-682;Lo;0;L;;;;;N;;;;; +18AAA;TANGUT COMPONENT-683;Lo;0;L;;;;;N;;;;; +18AAB;TANGUT COMPONENT-684;Lo;0;L;;;;;N;;;;; +18AAC;TANGUT COMPONENT-685;Lo;0;L;;;;;N;;;;; +18AAD;TANGUT COMPONENT-686;Lo;0;L;;;;;N;;;;; +18AAE;TANGUT COMPONENT-687;Lo;0;L;;;;;N;;;;; +18AAF;TANGUT COMPONENT-688;Lo;0;L;;;;;N;;;;; +18AB0;TANGUT COMPONENT-689;Lo;0;L;;;;;N;;;;; +18AB1;TANGUT COMPONENT-690;Lo;0;L;;;;;N;;;;; +18AB2;TANGUT COMPONENT-691;Lo;0;L;;;;;N;;;;; +18AB3;TANGUT COMPONENT-692;Lo;0;L;;;;;N;;;;; +18AB4;TANGUT COMPONENT-693;Lo;0;L;;;;;N;;;;; +18AB5;TANGUT COMPONENT-694;Lo;0;L;;;;;N;;;;; +18AB6;TANGUT COMPONENT-695;Lo;0;L;;;;;N;;;;; +18AB7;TANGUT COMPONENT-696;Lo;0;L;;;;;N;;;;; +18AB8;TANGUT COMPONENT-697;Lo;0;L;;;;;N;;;;; +18AB9;TANGUT COMPONENT-698;Lo;0;L;;;;;N;;;;; +18ABA;TANGUT COMPONENT-699;Lo;0;L;;;;;N;;;;; +18ABB;TANGUT COMPONENT-700;Lo;0;L;;;;;N;;;;; +18ABC;TANGUT COMPONENT-701;Lo;0;L;;;;;N;;;;; +18ABD;TANGUT COMPONENT-702;Lo;0;L;;;;;N;;;;; +18ABE;TANGUT COMPONENT-703;Lo;0;L;;;;;N;;;;; +18ABF;TANGUT COMPONENT-704;Lo;0;L;;;;;N;;;;; +18AC0;TANGUT COMPONENT-705;Lo;0;L;;;;;N;;;;; +18AC1;TANGUT COMPONENT-706;Lo;0;L;;;;;N;;;;; +18AC2;TANGUT COMPONENT-707;Lo;0;L;;;;;N;;;;; +18AC3;TANGUT COMPONENT-708;Lo;0;L;;;;;N;;;;; +18AC4;TANGUT COMPONENT-709;Lo;0;L;;;;;N;;;;; +18AC5;TANGUT COMPONENT-710;Lo;0;L;;;;;N;;;;; +18AC6;TANGUT COMPONENT-711;Lo;0;L;;;;;N;;;;; +18AC7;TANGUT COMPONENT-712;Lo;0;L;;;;;N;;;;; +18AC8;TANGUT COMPONENT-713;Lo;0;L;;;;;N;;;;; +18AC9;TANGUT COMPONENT-714;Lo;0;L;;;;;N;;;;; +18ACA;TANGUT COMPONENT-715;Lo;0;L;;;;;N;;;;; +18ACB;TANGUT COMPONENT-716;Lo;0;L;;;;;N;;;;; +18ACC;TANGUT COMPONENT-717;Lo;0;L;;;;;N;;;;; +18ACD;TANGUT COMPONENT-718;Lo;0;L;;;;;N;;;;; +18ACE;TANGUT COMPONENT-719;Lo;0;L;;;;;N;;;;; +18ACF;TANGUT COMPONENT-720;Lo;0;L;;;;;N;;;;; +18AD0;TANGUT COMPONENT-721;Lo;0;L;;;;;N;;;;; +18AD1;TANGUT COMPONENT-722;Lo;0;L;;;;;N;;;;; +18AD2;TANGUT COMPONENT-723;Lo;0;L;;;;;N;;;;; +18AD3;TANGUT COMPONENT-724;Lo;0;L;;;;;N;;;;; +18AD4;TANGUT COMPONENT-725;Lo;0;L;;;;;N;;;;; +18AD5;TANGUT COMPONENT-726;Lo;0;L;;;;;N;;;;; +18AD6;TANGUT COMPONENT-727;Lo;0;L;;;;;N;;;;; +18AD7;TANGUT COMPONENT-728;Lo;0;L;;;;;N;;;;; +18AD8;TANGUT COMPONENT-729;Lo;0;L;;;;;N;;;;; +18AD9;TANGUT COMPONENT-730;Lo;0;L;;;;;N;;;;; +18ADA;TANGUT COMPONENT-731;Lo;0;L;;;;;N;;;;; +18ADB;TANGUT COMPONENT-732;Lo;0;L;;;;;N;;;;; +18ADC;TANGUT COMPONENT-733;Lo;0;L;;;;;N;;;;; +18ADD;TANGUT COMPONENT-734;Lo;0;L;;;;;N;;;;; +18ADE;TANGUT COMPONENT-735;Lo;0;L;;;;;N;;;;; +18ADF;TANGUT COMPONENT-736;Lo;0;L;;;;;N;;;;; +18AE0;TANGUT COMPONENT-737;Lo;0;L;;;;;N;;;;; +18AE1;TANGUT COMPONENT-738;Lo;0;L;;;;;N;;;;; +18AE2;TANGUT COMPONENT-739;Lo;0;L;;;;;N;;;;; +18AE3;TANGUT COMPONENT-740;Lo;0;L;;;;;N;;;;; +18AE4;TANGUT COMPONENT-741;Lo;0;L;;;;;N;;;;; +18AE5;TANGUT COMPONENT-742;Lo;0;L;;;;;N;;;;; +18AE6;TANGUT COMPONENT-743;Lo;0;L;;;;;N;;;;; +18AE7;TANGUT COMPONENT-744;Lo;0;L;;;;;N;;;;; +18AE8;TANGUT COMPONENT-745;Lo;0;L;;;;;N;;;;; +18AE9;TANGUT COMPONENT-746;Lo;0;L;;;;;N;;;;; +18AEA;TANGUT COMPONENT-747;Lo;0;L;;;;;N;;;;; +18AEB;TANGUT COMPONENT-748;Lo;0;L;;;;;N;;;;; +18AEC;TANGUT COMPONENT-749;Lo;0;L;;;;;N;;;;; +18AED;TANGUT COMPONENT-750;Lo;0;L;;;;;N;;;;; +18AEE;TANGUT COMPONENT-751;Lo;0;L;;;;;N;;;;; +18AEF;TANGUT COMPONENT-752;Lo;0;L;;;;;N;;;;; +18AF0;TANGUT COMPONENT-753;Lo;0;L;;;;;N;;;;; +18AF1;TANGUT COMPONENT-754;Lo;0;L;;;;;N;;;;; +18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;; +18AF3;TANGUT COMPONENT-756;Lo;0;L;;;;;N;;;;; +18AF4;TANGUT COMPONENT-757;Lo;0;L;;;;;N;;;;; +18AF5;TANGUT COMPONENT-758;Lo;0;L;;;;;N;;;;; +18AF6;TANGUT COMPONENT-759;Lo;0;L;;;;;N;;;;; +18AF7;TANGUT COMPONENT-760;Lo;0;L;;;;;N;;;;; +18AF8;TANGUT COMPONENT-761;Lo;0;L;;;;;N;;;;; +18AF9;TANGUT COMPONENT-762;Lo;0;L;;;;;N;;;;; +18AFA;TANGUT COMPONENT-763;Lo;0;L;;;;;N;;;;; +18AFB;TANGUT COMPONENT-764;Lo;0;L;;;;;N;;;;; +18AFC;TANGUT COMPONENT-765;Lo;0;L;;;;;N;;;;; +18AFD;TANGUT COMPONENT-766;Lo;0;L;;;;;N;;;;; +18AFE;TANGUT COMPONENT-767;Lo;0;L;;;;;N;;;;; +18AFF;TANGUT COMPONENT-768;Lo;0;L;;;;;N;;;;; +18B00;KHITAN SMALL SCRIPT CHARACTER-18B00;Lo;0;L;;;;;N;;;;; +18B01;KHITAN SMALL SCRIPT CHARACTER-18B01;Lo;0;L;;;;;N;;;;; +18B02;KHITAN SMALL SCRIPT CHARACTER-18B02;Lo;0;L;;;;;N;;;;; +18B03;KHITAN SMALL SCRIPT CHARACTER-18B03;Lo;0;L;;;;;N;;;;; +18B04;KHITAN SMALL SCRIPT CHARACTER-18B04;Lo;0;L;;;;;N;;;;; +18B05;KHITAN SMALL SCRIPT CHARACTER-18B05;Lo;0;L;;;;;N;;;;; +18B06;KHITAN SMALL SCRIPT CHARACTER-18B06;Lo;0;L;;;;;N;;;;; +18B07;KHITAN SMALL SCRIPT CHARACTER-18B07;Lo;0;L;;;;;N;;;;; +18B08;KHITAN SMALL SCRIPT CHARACTER-18B08;Lo;0;L;;;;;N;;;;; +18B09;KHITAN SMALL SCRIPT CHARACTER-18B09;Lo;0;L;;;;;N;;;;; +18B0A;KHITAN SMALL SCRIPT CHARACTER-18B0A;Lo;0;L;;;;;N;;;;; +18B0B;KHITAN SMALL SCRIPT CHARACTER-18B0B;Lo;0;L;;;;;N;;;;; +18B0C;KHITAN SMALL SCRIPT CHARACTER-18B0C;Lo;0;L;;;;;N;;;;; +18B0D;KHITAN SMALL SCRIPT CHARACTER-18B0D;Lo;0;L;;;;;N;;;;; +18B0E;KHITAN SMALL SCRIPT CHARACTER-18B0E;Lo;0;L;;;;;N;;;;; +18B0F;KHITAN SMALL SCRIPT CHARACTER-18B0F;Lo;0;L;;;;;N;;;;; +18B10;KHITAN SMALL SCRIPT CHARACTER-18B10;Lo;0;L;;;;;N;;;;; +18B11;KHITAN SMALL SCRIPT CHARACTER-18B11;Lo;0;L;;;;;N;;;;; +18B12;KHITAN SMALL SCRIPT CHARACTER-18B12;Lo;0;L;;;;;N;;;;; +18B13;KHITAN SMALL SCRIPT CHARACTER-18B13;Lo;0;L;;;;;N;;;;; +18B14;KHITAN SMALL SCRIPT CHARACTER-18B14;Lo;0;L;;;;;N;;;;; +18B15;KHITAN SMALL SCRIPT CHARACTER-18B15;Lo;0;L;;;;;N;;;;; +18B16;KHITAN SMALL SCRIPT CHARACTER-18B16;Lo;0;L;;;;;N;;;;; +18B17;KHITAN SMALL SCRIPT CHARACTER-18B17;Lo;0;L;;;;;N;;;;; +18B18;KHITAN SMALL SCRIPT CHARACTER-18B18;Lo;0;L;;;;;N;;;;; +18B19;KHITAN SMALL SCRIPT CHARACTER-18B19;Lo;0;L;;;;;N;;;;; +18B1A;KHITAN SMALL SCRIPT CHARACTER-18B1A;Lo;0;L;;;;;N;;;;; +18B1B;KHITAN SMALL SCRIPT CHARACTER-18B1B;Lo;0;L;;;;;N;;;;; +18B1C;KHITAN SMALL SCRIPT CHARACTER-18B1C;Lo;0;L;;;;;N;;;;; +18B1D;KHITAN SMALL SCRIPT CHARACTER-18B1D;Lo;0;L;;;;;N;;;;; +18B1E;KHITAN SMALL SCRIPT CHARACTER-18B1E;Lo;0;L;;;;;N;;;;; +18B1F;KHITAN SMALL SCRIPT CHARACTER-18B1F;Lo;0;L;;;;;N;;;;; +18B20;KHITAN SMALL SCRIPT CHARACTER-18B20;Lo;0;L;;;;;N;;;;; +18B21;KHITAN SMALL SCRIPT CHARACTER-18B21;Lo;0;L;;;;;N;;;;; +18B22;KHITAN SMALL SCRIPT CHARACTER-18B22;Lo;0;L;;;;;N;;;;; +18B23;KHITAN SMALL SCRIPT CHARACTER-18B23;Lo;0;L;;;;;N;;;;; +18B24;KHITAN SMALL SCRIPT CHARACTER-18B24;Lo;0;L;;;;;N;;;;; +18B25;KHITAN SMALL SCRIPT CHARACTER-18B25;Lo;0;L;;;;;N;;;;; +18B26;KHITAN SMALL SCRIPT CHARACTER-18B26;Lo;0;L;;;;;N;;;;; +18B27;KHITAN SMALL SCRIPT CHARACTER-18B27;Lo;0;L;;;;;N;;;;; +18B28;KHITAN SMALL SCRIPT CHARACTER-18B28;Lo;0;L;;;;;N;;;;; +18B29;KHITAN SMALL SCRIPT CHARACTER-18B29;Lo;0;L;;;;;N;;;;; +18B2A;KHITAN SMALL SCRIPT CHARACTER-18B2A;Lo;0;L;;;;;N;;;;; +18B2B;KHITAN SMALL SCRIPT CHARACTER-18B2B;Lo;0;L;;;;;N;;;;; +18B2C;KHITAN SMALL SCRIPT CHARACTER-18B2C;Lo;0;L;;;;;N;;;;; +18B2D;KHITAN SMALL SCRIPT CHARACTER-18B2D;Lo;0;L;;;;;N;;;;; +18B2E;KHITAN SMALL SCRIPT CHARACTER-18B2E;Lo;0;L;;;;;N;;;;; +18B2F;KHITAN SMALL SCRIPT CHARACTER-18B2F;Lo;0;L;;;;;N;;;;; +18B30;KHITAN SMALL SCRIPT CHARACTER-18B30;Lo;0;L;;;;;N;;;;; +18B31;KHITAN SMALL SCRIPT CHARACTER-18B31;Lo;0;L;;;;;N;;;;; +18B32;KHITAN SMALL SCRIPT CHARACTER-18B32;Lo;0;L;;;;;N;;;;; +18B33;KHITAN SMALL SCRIPT CHARACTER-18B33;Lo;0;L;;;;;N;;;;; +18B34;KHITAN SMALL SCRIPT CHARACTER-18B34;Lo;0;L;;;;;N;;;;; +18B35;KHITAN SMALL SCRIPT CHARACTER-18B35;Lo;0;L;;;;;N;;;;; +18B36;KHITAN SMALL SCRIPT CHARACTER-18B36;Lo;0;L;;;;;N;;;;; +18B37;KHITAN SMALL SCRIPT CHARACTER-18B37;Lo;0;L;;;;;N;;;;; +18B38;KHITAN SMALL SCRIPT CHARACTER-18B38;Lo;0;L;;;;;N;;;;; +18B39;KHITAN SMALL SCRIPT CHARACTER-18B39;Lo;0;L;;;;;N;;;;; +18B3A;KHITAN SMALL SCRIPT CHARACTER-18B3A;Lo;0;L;;;;;N;;;;; +18B3B;KHITAN SMALL SCRIPT CHARACTER-18B3B;Lo;0;L;;;;;N;;;;; +18B3C;KHITAN SMALL SCRIPT CHARACTER-18B3C;Lo;0;L;;;;;N;;;;; +18B3D;KHITAN SMALL SCRIPT CHARACTER-18B3D;Lo;0;L;;;;;N;;;;; +18B3E;KHITAN SMALL SCRIPT CHARACTER-18B3E;Lo;0;L;;;;;N;;;;; +18B3F;KHITAN SMALL SCRIPT CHARACTER-18B3F;Lo;0;L;;;;;N;;;;; +18B40;KHITAN SMALL SCRIPT CHARACTER-18B40;Lo;0;L;;;;;N;;;;; +18B41;KHITAN SMALL SCRIPT CHARACTER-18B41;Lo;0;L;;;;;N;;;;; +18B42;KHITAN SMALL SCRIPT CHARACTER-18B42;Lo;0;L;;;;;N;;;;; +18B43;KHITAN SMALL SCRIPT CHARACTER-18B43;Lo;0;L;;;;;N;;;;; +18B44;KHITAN SMALL SCRIPT CHARACTER-18B44;Lo;0;L;;;;;N;;;;; +18B45;KHITAN SMALL SCRIPT CHARACTER-18B45;Lo;0;L;;;;;N;;;;; +18B46;KHITAN SMALL SCRIPT CHARACTER-18B46;Lo;0;L;;;;;N;;;;; +18B47;KHITAN SMALL SCRIPT CHARACTER-18B47;Lo;0;L;;;;;N;;;;; +18B48;KHITAN SMALL SCRIPT CHARACTER-18B48;Lo;0;L;;;;;N;;;;; +18B49;KHITAN SMALL SCRIPT CHARACTER-18B49;Lo;0;L;;;;;N;;;;; +18B4A;KHITAN SMALL SCRIPT CHARACTER-18B4A;Lo;0;L;;;;;N;;;;; +18B4B;KHITAN SMALL SCRIPT CHARACTER-18B4B;Lo;0;L;;;;;N;;;;; +18B4C;KHITAN SMALL SCRIPT CHARACTER-18B4C;Lo;0;L;;;;;N;;;;; +18B4D;KHITAN SMALL SCRIPT CHARACTER-18B4D;Lo;0;L;;;;;N;;;;; +18B4E;KHITAN SMALL SCRIPT CHARACTER-18B4E;Lo;0;L;;;;;N;;;;; +18B4F;KHITAN SMALL SCRIPT CHARACTER-18B4F;Lo;0;L;;;;;N;;;;; +18B50;KHITAN SMALL SCRIPT CHARACTER-18B50;Lo;0;L;;;;;N;;;;; +18B51;KHITAN SMALL SCRIPT CHARACTER-18B51;Lo;0;L;;;;;N;;;;; +18B52;KHITAN SMALL SCRIPT CHARACTER-18B52;Lo;0;L;;;;;N;;;;; +18B53;KHITAN SMALL SCRIPT CHARACTER-18B53;Lo;0;L;;;;;N;;;;; +18B54;KHITAN SMALL SCRIPT CHARACTER-18B54;Lo;0;L;;;;;N;;;;; +18B55;KHITAN SMALL SCRIPT CHARACTER-18B55;Lo;0;L;;;;;N;;;;; +18B56;KHITAN SMALL SCRIPT CHARACTER-18B56;Lo;0;L;;;;;N;;;;; +18B57;KHITAN SMALL SCRIPT CHARACTER-18B57;Lo;0;L;;;;;N;;;;; +18B58;KHITAN SMALL SCRIPT CHARACTER-18B58;Lo;0;L;;;;;N;;;;; +18B59;KHITAN SMALL SCRIPT CHARACTER-18B59;Lo;0;L;;;;;N;;;;; +18B5A;KHITAN SMALL SCRIPT CHARACTER-18B5A;Lo;0;L;;;;;N;;;;; +18B5B;KHITAN SMALL SCRIPT CHARACTER-18B5B;Lo;0;L;;;;;N;;;;; +18B5C;KHITAN SMALL SCRIPT CHARACTER-18B5C;Lo;0;L;;;;;N;;;;; +18B5D;KHITAN SMALL SCRIPT CHARACTER-18B5D;Lo;0;L;;;;;N;;;;; +18B5E;KHITAN SMALL SCRIPT CHARACTER-18B5E;Lo;0;L;;;;;N;;;;; +18B5F;KHITAN SMALL SCRIPT CHARACTER-18B5F;Lo;0;L;;;;;N;;;;; +18B60;KHITAN SMALL SCRIPT CHARACTER-18B60;Lo;0;L;;;;;N;;;;; +18B61;KHITAN SMALL SCRIPT CHARACTER-18B61;Lo;0;L;;;;;N;;;;; +18B62;KHITAN SMALL SCRIPT CHARACTER-18B62;Lo;0;L;;;;;N;;;;; +18B63;KHITAN SMALL SCRIPT CHARACTER-18B63;Lo;0;L;;;;;N;;;;; +18B64;KHITAN SMALL SCRIPT CHARACTER-18B64;Lo;0;L;;;;;N;;;;; +18B65;KHITAN SMALL SCRIPT CHARACTER-18B65;Lo;0;L;;;;;N;;;;; +18B66;KHITAN SMALL SCRIPT CHARACTER-18B66;Lo;0;L;;;;;N;;;;; +18B67;KHITAN SMALL SCRIPT CHARACTER-18B67;Lo;0;L;;;;;N;;;;; +18B68;KHITAN SMALL SCRIPT CHARACTER-18B68;Lo;0;L;;;;;N;;;;; +18B69;KHITAN SMALL SCRIPT CHARACTER-18B69;Lo;0;L;;;;;N;;;;; +18B6A;KHITAN SMALL SCRIPT CHARACTER-18B6A;Lo;0;L;;;;;N;;;;; +18B6B;KHITAN SMALL SCRIPT CHARACTER-18B6B;Lo;0;L;;;;;N;;;;; +18B6C;KHITAN SMALL SCRIPT CHARACTER-18B6C;Lo;0;L;;;;;N;;;;; +18B6D;KHITAN SMALL SCRIPT CHARACTER-18B6D;Lo;0;L;;;;;N;;;;; +18B6E;KHITAN SMALL SCRIPT CHARACTER-18B6E;Lo;0;L;;;;;N;;;;; +18B6F;KHITAN SMALL SCRIPT CHARACTER-18B6F;Lo;0;L;;;;;N;;;;; +18B70;KHITAN SMALL SCRIPT CHARACTER-18B70;Lo;0;L;;;;;N;;;;; +18B71;KHITAN SMALL SCRIPT CHARACTER-18B71;Lo;0;L;;;;;N;;;;; +18B72;KHITAN SMALL SCRIPT CHARACTER-18B72;Lo;0;L;;;;;N;;;;; +18B73;KHITAN SMALL SCRIPT CHARACTER-18B73;Lo;0;L;;;;;N;;;;; +18B74;KHITAN SMALL SCRIPT CHARACTER-18B74;Lo;0;L;;;;;N;;;;; +18B75;KHITAN SMALL SCRIPT CHARACTER-18B75;Lo;0;L;;;;;N;;;;; +18B76;KHITAN SMALL SCRIPT CHARACTER-18B76;Lo;0;L;;;;;N;;;;; +18B77;KHITAN SMALL SCRIPT CHARACTER-18B77;Lo;0;L;;;;;N;;;;; +18B78;KHITAN SMALL SCRIPT CHARACTER-18B78;Lo;0;L;;;;;N;;;;; +18B79;KHITAN SMALL SCRIPT CHARACTER-18B79;Lo;0;L;;;;;N;;;;; +18B7A;KHITAN SMALL SCRIPT CHARACTER-18B7A;Lo;0;L;;;;;N;;;;; +18B7B;KHITAN SMALL SCRIPT CHARACTER-18B7B;Lo;0;L;;;;;N;;;;; +18B7C;KHITAN SMALL SCRIPT CHARACTER-18B7C;Lo;0;L;;;;;N;;;;; +18B7D;KHITAN SMALL SCRIPT CHARACTER-18B7D;Lo;0;L;;;;;N;;;;; +18B7E;KHITAN SMALL SCRIPT CHARACTER-18B7E;Lo;0;L;;;;;N;;;;; +18B7F;KHITAN SMALL SCRIPT CHARACTER-18B7F;Lo;0;L;;;;;N;;;;; +18B80;KHITAN SMALL SCRIPT CHARACTER-18B80;Lo;0;L;;;;;N;;;;; +18B81;KHITAN SMALL SCRIPT CHARACTER-18B81;Lo;0;L;;;;;N;;;;; +18B82;KHITAN SMALL SCRIPT CHARACTER-18B82;Lo;0;L;;;;;N;;;;; +18B83;KHITAN SMALL SCRIPT CHARACTER-18B83;Lo;0;L;;;;;N;;;;; +18B84;KHITAN SMALL SCRIPT CHARACTER-18B84;Lo;0;L;;;;;N;;;;; +18B85;KHITAN SMALL SCRIPT CHARACTER-18B85;Lo;0;L;;;;;N;;;;; +18B86;KHITAN SMALL SCRIPT CHARACTER-18B86;Lo;0;L;;;;;N;;;;; +18B87;KHITAN SMALL SCRIPT CHARACTER-18B87;Lo;0;L;;;;;N;;;;; +18B88;KHITAN SMALL SCRIPT CHARACTER-18B88;Lo;0;L;;;;;N;;;;; +18B89;KHITAN SMALL SCRIPT CHARACTER-18B89;Lo;0;L;;;;;N;;;;; +18B8A;KHITAN SMALL SCRIPT CHARACTER-18B8A;Lo;0;L;;;;;N;;;;; +18B8B;KHITAN SMALL SCRIPT CHARACTER-18B8B;Lo;0;L;;;;;N;;;;; +18B8C;KHITAN SMALL SCRIPT CHARACTER-18B8C;Lo;0;L;;;;;N;;;;; +18B8D;KHITAN SMALL SCRIPT CHARACTER-18B8D;Lo;0;L;;;;;N;;;;; +18B8E;KHITAN SMALL SCRIPT CHARACTER-18B8E;Lo;0;L;;;;;N;;;;; +18B8F;KHITAN SMALL SCRIPT CHARACTER-18B8F;Lo;0;L;;;;;N;;;;; +18B90;KHITAN SMALL SCRIPT CHARACTER-18B90;Lo;0;L;;;;;N;;;;; +18B91;KHITAN SMALL SCRIPT CHARACTER-18B91;Lo;0;L;;;;;N;;;;; +18B92;KHITAN SMALL SCRIPT CHARACTER-18B92;Lo;0;L;;;;;N;;;;; +18B93;KHITAN SMALL SCRIPT CHARACTER-18B93;Lo;0;L;;;;;N;;;;; +18B94;KHITAN SMALL SCRIPT CHARACTER-18B94;Lo;0;L;;;;;N;;;;; +18B95;KHITAN SMALL SCRIPT CHARACTER-18B95;Lo;0;L;;;;;N;;;;; +18B96;KHITAN SMALL SCRIPT CHARACTER-18B96;Lo;0;L;;;;;N;;;;; +18B97;KHITAN SMALL SCRIPT CHARACTER-18B97;Lo;0;L;;;;;N;;;;; +18B98;KHITAN SMALL SCRIPT CHARACTER-18B98;Lo;0;L;;;;;N;;;;; +18B99;KHITAN SMALL SCRIPT CHARACTER-18B99;Lo;0;L;;;;;N;;;;; +18B9A;KHITAN SMALL SCRIPT CHARACTER-18B9A;Lo;0;L;;;;;N;;;;; +18B9B;KHITAN SMALL SCRIPT CHARACTER-18B9B;Lo;0;L;;;;;N;;;;; +18B9C;KHITAN SMALL SCRIPT CHARACTER-18B9C;Lo;0;L;;;;;N;;;;; +18B9D;KHITAN SMALL SCRIPT CHARACTER-18B9D;Lo;0;L;;;;;N;;;;; +18B9E;KHITAN SMALL SCRIPT CHARACTER-18B9E;Lo;0;L;;;;;N;;;;; +18B9F;KHITAN SMALL SCRIPT CHARACTER-18B9F;Lo;0;L;;;;;N;;;;; +18BA0;KHITAN SMALL SCRIPT CHARACTER-18BA0;Lo;0;L;;;;;N;;;;; +18BA1;KHITAN SMALL SCRIPT CHARACTER-18BA1;Lo;0;L;;;;;N;;;;; +18BA2;KHITAN SMALL SCRIPT CHARACTER-18BA2;Lo;0;L;;;;;N;;;;; +18BA3;KHITAN SMALL SCRIPT CHARACTER-18BA3;Lo;0;L;;;;;N;;;;; +18BA4;KHITAN SMALL SCRIPT CHARACTER-18BA4;Lo;0;L;;;;;N;;;;; +18BA5;KHITAN SMALL SCRIPT CHARACTER-18BA5;Lo;0;L;;;;;N;;;;; +18BA6;KHITAN SMALL SCRIPT CHARACTER-18BA6;Lo;0;L;;;;;N;;;;; +18BA7;KHITAN SMALL SCRIPT CHARACTER-18BA7;Lo;0;L;;;;;N;;;;; +18BA8;KHITAN SMALL SCRIPT CHARACTER-18BA8;Lo;0;L;;;;;N;;;;; +18BA9;KHITAN SMALL SCRIPT CHARACTER-18BA9;Lo;0;L;;;;;N;;;;; +18BAA;KHITAN SMALL SCRIPT CHARACTER-18BAA;Lo;0;L;;;;;N;;;;; +18BAB;KHITAN SMALL SCRIPT CHARACTER-18BAB;Lo;0;L;;;;;N;;;;; +18BAC;KHITAN SMALL SCRIPT CHARACTER-18BAC;Lo;0;L;;;;;N;;;;; +18BAD;KHITAN SMALL SCRIPT CHARACTER-18BAD;Lo;0;L;;;;;N;;;;; +18BAE;KHITAN SMALL SCRIPT CHARACTER-18BAE;Lo;0;L;;;;;N;;;;; +18BAF;KHITAN SMALL SCRIPT CHARACTER-18BAF;Lo;0;L;;;;;N;;;;; +18BB0;KHITAN SMALL SCRIPT CHARACTER-18BB0;Lo;0;L;;;;;N;;;;; +18BB1;KHITAN SMALL SCRIPT CHARACTER-18BB1;Lo;0;L;;;;;N;;;;; +18BB2;KHITAN SMALL SCRIPT CHARACTER-18BB2;Lo;0;L;;;;;N;;;;; +18BB3;KHITAN SMALL SCRIPT CHARACTER-18BB3;Lo;0;L;;;;;N;;;;; +18BB4;KHITAN SMALL SCRIPT CHARACTER-18BB4;Lo;0;L;;;;;N;;;;; +18BB5;KHITAN SMALL SCRIPT CHARACTER-18BB5;Lo;0;L;;;;;N;;;;; +18BB6;KHITAN SMALL SCRIPT CHARACTER-18BB6;Lo;0;L;;;;;N;;;;; +18BB7;KHITAN SMALL SCRIPT CHARACTER-18BB7;Lo;0;L;;;;;N;;;;; +18BB8;KHITAN SMALL SCRIPT CHARACTER-18BB8;Lo;0;L;;;;;N;;;;; +18BB9;KHITAN SMALL SCRIPT CHARACTER-18BB9;Lo;0;L;;;;;N;;;;; +18BBA;KHITAN SMALL SCRIPT CHARACTER-18BBA;Lo;0;L;;;;;N;;;;; +18BBB;KHITAN SMALL SCRIPT CHARACTER-18BBB;Lo;0;L;;;;;N;;;;; +18BBC;KHITAN SMALL SCRIPT CHARACTER-18BBC;Lo;0;L;;;;;N;;;;; +18BBD;KHITAN SMALL SCRIPT CHARACTER-18BBD;Lo;0;L;;;;;N;;;;; +18BBE;KHITAN SMALL SCRIPT CHARACTER-18BBE;Lo;0;L;;;;;N;;;;; +18BBF;KHITAN SMALL SCRIPT CHARACTER-18BBF;Lo;0;L;;;;;N;;;;; +18BC0;KHITAN SMALL SCRIPT CHARACTER-18BC0;Lo;0;L;;;;;N;;;;; +18BC1;KHITAN SMALL SCRIPT CHARACTER-18BC1;Lo;0;L;;;;;N;;;;; +18BC2;KHITAN SMALL SCRIPT CHARACTER-18BC2;Lo;0;L;;;;;N;;;;; +18BC3;KHITAN SMALL SCRIPT CHARACTER-18BC3;Lo;0;L;;;;;N;;;;; +18BC4;KHITAN SMALL SCRIPT CHARACTER-18BC4;Lo;0;L;;;;;N;;;;; +18BC5;KHITAN SMALL SCRIPT CHARACTER-18BC5;Lo;0;L;;;;;N;;;;; +18BC6;KHITAN SMALL SCRIPT CHARACTER-18BC6;Lo;0;L;;;;;N;;;;; +18BC7;KHITAN SMALL SCRIPT CHARACTER-18BC7;Lo;0;L;;;;;N;;;;; +18BC8;KHITAN SMALL SCRIPT CHARACTER-18BC8;Lo;0;L;;;;;N;;;;; +18BC9;KHITAN SMALL SCRIPT CHARACTER-18BC9;Lo;0;L;;;;;N;;;;; +18BCA;KHITAN SMALL SCRIPT CHARACTER-18BCA;Lo;0;L;;;;;N;;;;; +18BCB;KHITAN SMALL SCRIPT CHARACTER-18BCB;Lo;0;L;;;;;N;;;;; +18BCC;KHITAN SMALL SCRIPT CHARACTER-18BCC;Lo;0;L;;;;;N;;;;; +18BCD;KHITAN SMALL SCRIPT CHARACTER-18BCD;Lo;0;L;;;;;N;;;;; +18BCE;KHITAN SMALL SCRIPT CHARACTER-18BCE;Lo;0;L;;;;;N;;;;; +18BCF;KHITAN SMALL SCRIPT CHARACTER-18BCF;Lo;0;L;;;;;N;;;;; +18BD0;KHITAN SMALL SCRIPT CHARACTER-18BD0;Lo;0;L;;;;;N;;;;; +18BD1;KHITAN SMALL SCRIPT CHARACTER-18BD1;Lo;0;L;;;;;N;;;;; +18BD2;KHITAN SMALL SCRIPT CHARACTER-18BD2;Lo;0;L;;;;;N;;;;; +18BD3;KHITAN SMALL SCRIPT CHARACTER-18BD3;Lo;0;L;;;;;N;;;;; +18BD4;KHITAN SMALL SCRIPT CHARACTER-18BD4;Lo;0;L;;;;;N;;;;; +18BD5;KHITAN SMALL SCRIPT CHARACTER-18BD5;Lo;0;L;;;;;N;;;;; +18BD6;KHITAN SMALL SCRIPT CHARACTER-18BD6;Lo;0;L;;;;;N;;;;; +18BD7;KHITAN SMALL SCRIPT CHARACTER-18BD7;Lo;0;L;;;;;N;;;;; +18BD8;KHITAN SMALL SCRIPT CHARACTER-18BD8;Lo;0;L;;;;;N;;;;; +18BD9;KHITAN SMALL SCRIPT CHARACTER-18BD9;Lo;0;L;;;;;N;;;;; +18BDA;KHITAN SMALL SCRIPT CHARACTER-18BDA;Lo;0;L;;;;;N;;;;; +18BDB;KHITAN SMALL SCRIPT CHARACTER-18BDB;Lo;0;L;;;;;N;;;;; +18BDC;KHITAN SMALL SCRIPT CHARACTER-18BDC;Lo;0;L;;;;;N;;;;; +18BDD;KHITAN SMALL SCRIPT CHARACTER-18BDD;Lo;0;L;;;;;N;;;;; +18BDE;KHITAN SMALL SCRIPT CHARACTER-18BDE;Lo;0;L;;;;;N;;;;; +18BDF;KHITAN SMALL SCRIPT CHARACTER-18BDF;Lo;0;L;;;;;N;;;;; +18BE0;KHITAN SMALL SCRIPT CHARACTER-18BE0;Lo;0;L;;;;;N;;;;; +18BE1;KHITAN SMALL SCRIPT CHARACTER-18BE1;Lo;0;L;;;;;N;;;;; +18BE2;KHITAN SMALL SCRIPT CHARACTER-18BE2;Lo;0;L;;;;;N;;;;; +18BE3;KHITAN SMALL SCRIPT CHARACTER-18BE3;Lo;0;L;;;;;N;;;;; +18BE4;KHITAN SMALL SCRIPT CHARACTER-18BE4;Lo;0;L;;;;;N;;;;; +18BE5;KHITAN SMALL SCRIPT CHARACTER-18BE5;Lo;0;L;;;;;N;;;;; +18BE6;KHITAN SMALL SCRIPT CHARACTER-18BE6;Lo;0;L;;;;;N;;;;; +18BE7;KHITAN SMALL SCRIPT CHARACTER-18BE7;Lo;0;L;;;;;N;;;;; +18BE8;KHITAN SMALL SCRIPT CHARACTER-18BE8;Lo;0;L;;;;;N;;;;; +18BE9;KHITAN SMALL SCRIPT CHARACTER-18BE9;Lo;0;L;;;;;N;;;;; +18BEA;KHITAN SMALL SCRIPT CHARACTER-18BEA;Lo;0;L;;;;;N;;;;; +18BEB;KHITAN SMALL SCRIPT CHARACTER-18BEB;Lo;0;L;;;;;N;;;;; +18BEC;KHITAN SMALL SCRIPT CHARACTER-18BEC;Lo;0;L;;;;;N;;;;; +18BED;KHITAN SMALL SCRIPT CHARACTER-18BED;Lo;0;L;;;;;N;;;;; +18BEE;KHITAN SMALL SCRIPT CHARACTER-18BEE;Lo;0;L;;;;;N;;;;; +18BEF;KHITAN SMALL SCRIPT CHARACTER-18BEF;Lo;0;L;;;;;N;;;;; +18BF0;KHITAN SMALL SCRIPT CHARACTER-18BF0;Lo;0;L;;;;;N;;;;; +18BF1;KHITAN SMALL SCRIPT CHARACTER-18BF1;Lo;0;L;;;;;N;;;;; +18BF2;KHITAN SMALL SCRIPT CHARACTER-18BF2;Lo;0;L;;;;;N;;;;; +18BF3;KHITAN SMALL SCRIPT CHARACTER-18BF3;Lo;0;L;;;;;N;;;;; +18BF4;KHITAN SMALL SCRIPT CHARACTER-18BF4;Lo;0;L;;;;;N;;;;; +18BF5;KHITAN SMALL SCRIPT CHARACTER-18BF5;Lo;0;L;;;;;N;;;;; +18BF6;KHITAN SMALL SCRIPT CHARACTER-18BF6;Lo;0;L;;;;;N;;;;; +18BF7;KHITAN SMALL SCRIPT CHARACTER-18BF7;Lo;0;L;;;;;N;;;;; +18BF8;KHITAN SMALL SCRIPT CHARACTER-18BF8;Lo;0;L;;;;;N;;;;; +18BF9;KHITAN SMALL SCRIPT CHARACTER-18BF9;Lo;0;L;;;;;N;;;;; +18BFA;KHITAN SMALL SCRIPT CHARACTER-18BFA;Lo;0;L;;;;;N;;;;; +18BFB;KHITAN SMALL SCRIPT CHARACTER-18BFB;Lo;0;L;;;;;N;;;;; +18BFC;KHITAN SMALL SCRIPT CHARACTER-18BFC;Lo;0;L;;;;;N;;;;; +18BFD;KHITAN SMALL SCRIPT CHARACTER-18BFD;Lo;0;L;;;;;N;;;;; +18BFE;KHITAN SMALL SCRIPT CHARACTER-18BFE;Lo;0;L;;;;;N;;;;; +18BFF;KHITAN SMALL SCRIPT CHARACTER-18BFF;Lo;0;L;;;;;N;;;;; +18C00;KHITAN SMALL SCRIPT CHARACTER-18C00;Lo;0;L;;;;;N;;;;; +18C01;KHITAN SMALL SCRIPT CHARACTER-18C01;Lo;0;L;;;;;N;;;;; +18C02;KHITAN SMALL SCRIPT CHARACTER-18C02;Lo;0;L;;;;;N;;;;; +18C03;KHITAN SMALL SCRIPT CHARACTER-18C03;Lo;0;L;;;;;N;;;;; +18C04;KHITAN SMALL SCRIPT CHARACTER-18C04;Lo;0;L;;;;;N;;;;; +18C05;KHITAN SMALL SCRIPT CHARACTER-18C05;Lo;0;L;;;;;N;;;;; +18C06;KHITAN SMALL SCRIPT CHARACTER-18C06;Lo;0;L;;;;;N;;;;; +18C07;KHITAN SMALL SCRIPT CHARACTER-18C07;Lo;0;L;;;;;N;;;;; +18C08;KHITAN SMALL SCRIPT CHARACTER-18C08;Lo;0;L;;;;;N;;;;; +18C09;KHITAN SMALL SCRIPT CHARACTER-18C09;Lo;0;L;;;;;N;;;;; +18C0A;KHITAN SMALL SCRIPT CHARACTER-18C0A;Lo;0;L;;;;;N;;;;; +18C0B;KHITAN SMALL SCRIPT CHARACTER-18C0B;Lo;0;L;;;;;N;;;;; +18C0C;KHITAN SMALL SCRIPT CHARACTER-18C0C;Lo;0;L;;;;;N;;;;; +18C0D;KHITAN SMALL SCRIPT CHARACTER-18C0D;Lo;0;L;;;;;N;;;;; +18C0E;KHITAN SMALL SCRIPT CHARACTER-18C0E;Lo;0;L;;;;;N;;;;; +18C0F;KHITAN SMALL SCRIPT CHARACTER-18C0F;Lo;0;L;;;;;N;;;;; +18C10;KHITAN SMALL SCRIPT CHARACTER-18C10;Lo;0;L;;;;;N;;;;; +18C11;KHITAN SMALL SCRIPT CHARACTER-18C11;Lo;0;L;;;;;N;;;;; +18C12;KHITAN SMALL SCRIPT CHARACTER-18C12;Lo;0;L;;;;;N;;;;; +18C13;KHITAN SMALL SCRIPT CHARACTER-18C13;Lo;0;L;;;;;N;;;;; +18C14;KHITAN SMALL SCRIPT CHARACTER-18C14;Lo;0;L;;;;;N;;;;; +18C15;KHITAN SMALL SCRIPT CHARACTER-18C15;Lo;0;L;;;;;N;;;;; +18C16;KHITAN SMALL SCRIPT CHARACTER-18C16;Lo;0;L;;;;;N;;;;; +18C17;KHITAN SMALL SCRIPT CHARACTER-18C17;Lo;0;L;;;;;N;;;;; +18C18;KHITAN SMALL SCRIPT CHARACTER-18C18;Lo;0;L;;;;;N;;;;; +18C19;KHITAN SMALL SCRIPT CHARACTER-18C19;Lo;0;L;;;;;N;;;;; +18C1A;KHITAN SMALL SCRIPT CHARACTER-18C1A;Lo;0;L;;;;;N;;;;; +18C1B;KHITAN SMALL SCRIPT CHARACTER-18C1B;Lo;0;L;;;;;N;;;;; +18C1C;KHITAN SMALL SCRIPT CHARACTER-18C1C;Lo;0;L;;;;;N;;;;; +18C1D;KHITAN SMALL SCRIPT CHARACTER-18C1D;Lo;0;L;;;;;N;;;;; +18C1E;KHITAN SMALL SCRIPT CHARACTER-18C1E;Lo;0;L;;;;;N;;;;; +18C1F;KHITAN SMALL SCRIPT CHARACTER-18C1F;Lo;0;L;;;;;N;;;;; +18C20;KHITAN SMALL SCRIPT CHARACTER-18C20;Lo;0;L;;;;;N;;;;; +18C21;KHITAN SMALL SCRIPT CHARACTER-18C21;Lo;0;L;;;;;N;;;;; +18C22;KHITAN SMALL SCRIPT CHARACTER-18C22;Lo;0;L;;;;;N;;;;; +18C23;KHITAN SMALL SCRIPT CHARACTER-18C23;Lo;0;L;;;;;N;;;;; +18C24;KHITAN SMALL SCRIPT CHARACTER-18C24;Lo;0;L;;;;;N;;;;; +18C25;KHITAN SMALL SCRIPT CHARACTER-18C25;Lo;0;L;;;;;N;;;;; +18C26;KHITAN SMALL SCRIPT CHARACTER-18C26;Lo;0;L;;;;;N;;;;; +18C27;KHITAN SMALL SCRIPT CHARACTER-18C27;Lo;0;L;;;;;N;;;;; +18C28;KHITAN SMALL SCRIPT CHARACTER-18C28;Lo;0;L;;;;;N;;;;; +18C29;KHITAN SMALL SCRIPT CHARACTER-18C29;Lo;0;L;;;;;N;;;;; +18C2A;KHITAN SMALL SCRIPT CHARACTER-18C2A;Lo;0;L;;;;;N;;;;; +18C2B;KHITAN SMALL SCRIPT CHARACTER-18C2B;Lo;0;L;;;;;N;;;;; +18C2C;KHITAN SMALL SCRIPT CHARACTER-18C2C;Lo;0;L;;;;;N;;;;; +18C2D;KHITAN SMALL SCRIPT CHARACTER-18C2D;Lo;0;L;;;;;N;;;;; +18C2E;KHITAN SMALL SCRIPT CHARACTER-18C2E;Lo;0;L;;;;;N;;;;; +18C2F;KHITAN SMALL SCRIPT CHARACTER-18C2F;Lo;0;L;;;;;N;;;;; +18C30;KHITAN SMALL SCRIPT CHARACTER-18C30;Lo;0;L;;;;;N;;;;; +18C31;KHITAN SMALL SCRIPT CHARACTER-18C31;Lo;0;L;;;;;N;;;;; +18C32;KHITAN SMALL SCRIPT CHARACTER-18C32;Lo;0;L;;;;;N;;;;; +18C33;KHITAN SMALL SCRIPT CHARACTER-18C33;Lo;0;L;;;;;N;;;;; +18C34;KHITAN SMALL SCRIPT CHARACTER-18C34;Lo;0;L;;;;;N;;;;; +18C35;KHITAN SMALL SCRIPT CHARACTER-18C35;Lo;0;L;;;;;N;;;;; +18C36;KHITAN SMALL SCRIPT CHARACTER-18C36;Lo;0;L;;;;;N;;;;; +18C37;KHITAN SMALL SCRIPT CHARACTER-18C37;Lo;0;L;;;;;N;;;;; +18C38;KHITAN SMALL SCRIPT CHARACTER-18C38;Lo;0;L;;;;;N;;;;; +18C39;KHITAN SMALL SCRIPT CHARACTER-18C39;Lo;0;L;;;;;N;;;;; +18C3A;KHITAN SMALL SCRIPT CHARACTER-18C3A;Lo;0;L;;;;;N;;;;; +18C3B;KHITAN SMALL SCRIPT CHARACTER-18C3B;Lo;0;L;;;;;N;;;;; +18C3C;KHITAN SMALL SCRIPT CHARACTER-18C3C;Lo;0;L;;;;;N;;;;; +18C3D;KHITAN SMALL SCRIPT CHARACTER-18C3D;Lo;0;L;;;;;N;;;;; +18C3E;KHITAN SMALL SCRIPT CHARACTER-18C3E;Lo;0;L;;;;;N;;;;; +18C3F;KHITAN SMALL SCRIPT CHARACTER-18C3F;Lo;0;L;;;;;N;;;;; +18C40;KHITAN SMALL SCRIPT CHARACTER-18C40;Lo;0;L;;;;;N;;;;; +18C41;KHITAN SMALL SCRIPT CHARACTER-18C41;Lo;0;L;;;;;N;;;;; +18C42;KHITAN SMALL SCRIPT CHARACTER-18C42;Lo;0;L;;;;;N;;;;; +18C43;KHITAN SMALL SCRIPT CHARACTER-18C43;Lo;0;L;;;;;N;;;;; +18C44;KHITAN SMALL SCRIPT CHARACTER-18C44;Lo;0;L;;;;;N;;;;; +18C45;KHITAN SMALL SCRIPT CHARACTER-18C45;Lo;0;L;;;;;N;;;;; +18C46;KHITAN SMALL SCRIPT CHARACTER-18C46;Lo;0;L;;;;;N;;;;; +18C47;KHITAN SMALL SCRIPT CHARACTER-18C47;Lo;0;L;;;;;N;;;;; +18C48;KHITAN SMALL SCRIPT CHARACTER-18C48;Lo;0;L;;;;;N;;;;; +18C49;KHITAN SMALL SCRIPT CHARACTER-18C49;Lo;0;L;;;;;N;;;;; +18C4A;KHITAN SMALL SCRIPT CHARACTER-18C4A;Lo;0;L;;;;;N;;;;; +18C4B;KHITAN SMALL SCRIPT CHARACTER-18C4B;Lo;0;L;;;;;N;;;;; +18C4C;KHITAN SMALL SCRIPT CHARACTER-18C4C;Lo;0;L;;;;;N;;;;; +18C4D;KHITAN SMALL SCRIPT CHARACTER-18C4D;Lo;0;L;;;;;N;;;;; +18C4E;KHITAN SMALL SCRIPT CHARACTER-18C4E;Lo;0;L;;;;;N;;;;; +18C4F;KHITAN SMALL SCRIPT CHARACTER-18C4F;Lo;0;L;;;;;N;;;;; +18C50;KHITAN SMALL SCRIPT CHARACTER-18C50;Lo;0;L;;;;;N;;;;; +18C51;KHITAN SMALL SCRIPT CHARACTER-18C51;Lo;0;L;;;;;N;;;;; +18C52;KHITAN SMALL SCRIPT CHARACTER-18C52;Lo;0;L;;;;;N;;;;; +18C53;KHITAN SMALL SCRIPT CHARACTER-18C53;Lo;0;L;;;;;N;;;;; +18C54;KHITAN SMALL SCRIPT CHARACTER-18C54;Lo;0;L;;;;;N;;;;; +18C55;KHITAN SMALL SCRIPT CHARACTER-18C55;Lo;0;L;;;;;N;;;;; +18C56;KHITAN SMALL SCRIPT CHARACTER-18C56;Lo;0;L;;;;;N;;;;; +18C57;KHITAN SMALL SCRIPT CHARACTER-18C57;Lo;0;L;;;;;N;;;;; +18C58;KHITAN SMALL SCRIPT CHARACTER-18C58;Lo;0;L;;;;;N;;;;; +18C59;KHITAN SMALL SCRIPT CHARACTER-18C59;Lo;0;L;;;;;N;;;;; +18C5A;KHITAN SMALL SCRIPT CHARACTER-18C5A;Lo;0;L;;;;;N;;;;; +18C5B;KHITAN SMALL SCRIPT CHARACTER-18C5B;Lo;0;L;;;;;N;;;;; +18C5C;KHITAN SMALL SCRIPT CHARACTER-18C5C;Lo;0;L;;;;;N;;;;; +18C5D;KHITAN SMALL SCRIPT CHARACTER-18C5D;Lo;0;L;;;;;N;;;;; +18C5E;KHITAN SMALL SCRIPT CHARACTER-18C5E;Lo;0;L;;;;;N;;;;; +18C5F;KHITAN SMALL SCRIPT CHARACTER-18C5F;Lo;0;L;;;;;N;;;;; +18C60;KHITAN SMALL SCRIPT CHARACTER-18C60;Lo;0;L;;;;;N;;;;; +18C61;KHITAN SMALL SCRIPT CHARACTER-18C61;Lo;0;L;;;;;N;;;;; +18C62;KHITAN SMALL SCRIPT CHARACTER-18C62;Lo;0;L;;;;;N;;;;; +18C63;KHITAN SMALL SCRIPT CHARACTER-18C63;Lo;0;L;;;;;N;;;;; +18C64;KHITAN SMALL SCRIPT CHARACTER-18C64;Lo;0;L;;;;;N;;;;; +18C65;KHITAN SMALL SCRIPT CHARACTER-18C65;Lo;0;L;;;;;N;;;;; +18C66;KHITAN SMALL SCRIPT CHARACTER-18C66;Lo;0;L;;;;;N;;;;; +18C67;KHITAN SMALL SCRIPT CHARACTER-18C67;Lo;0;L;;;;;N;;;;; +18C68;KHITAN SMALL SCRIPT CHARACTER-18C68;Lo;0;L;;;;;N;;;;; +18C69;KHITAN SMALL SCRIPT CHARACTER-18C69;Lo;0;L;;;;;N;;;;; +18C6A;KHITAN SMALL SCRIPT CHARACTER-18C6A;Lo;0;L;;;;;N;;;;; +18C6B;KHITAN SMALL SCRIPT CHARACTER-18C6B;Lo;0;L;;;;;N;;;;; +18C6C;KHITAN SMALL SCRIPT CHARACTER-18C6C;Lo;0;L;;;;;N;;;;; +18C6D;KHITAN SMALL SCRIPT CHARACTER-18C6D;Lo;0;L;;;;;N;;;;; +18C6E;KHITAN SMALL SCRIPT CHARACTER-18C6E;Lo;0;L;;;;;N;;;;; +18C6F;KHITAN SMALL SCRIPT CHARACTER-18C6F;Lo;0;L;;;;;N;;;;; +18C70;KHITAN SMALL SCRIPT CHARACTER-18C70;Lo;0;L;;;;;N;;;;; +18C71;KHITAN SMALL SCRIPT CHARACTER-18C71;Lo;0;L;;;;;N;;;;; +18C72;KHITAN SMALL SCRIPT CHARACTER-18C72;Lo;0;L;;;;;N;;;;; +18C73;KHITAN SMALL SCRIPT CHARACTER-18C73;Lo;0;L;;;;;N;;;;; +18C74;KHITAN SMALL SCRIPT CHARACTER-18C74;Lo;0;L;;;;;N;;;;; +18C75;KHITAN SMALL SCRIPT CHARACTER-18C75;Lo;0;L;;;;;N;;;;; +18C76;KHITAN SMALL SCRIPT CHARACTER-18C76;Lo;0;L;;;;;N;;;;; +18C77;KHITAN SMALL SCRIPT CHARACTER-18C77;Lo;0;L;;;;;N;;;;; +18C78;KHITAN SMALL SCRIPT CHARACTER-18C78;Lo;0;L;;;;;N;;;;; +18C79;KHITAN SMALL SCRIPT CHARACTER-18C79;Lo;0;L;;;;;N;;;;; +18C7A;KHITAN SMALL SCRIPT CHARACTER-18C7A;Lo;0;L;;;;;N;;;;; +18C7B;KHITAN SMALL SCRIPT CHARACTER-18C7B;Lo;0;L;;;;;N;;;;; +18C7C;KHITAN SMALL SCRIPT CHARACTER-18C7C;Lo;0;L;;;;;N;;;;; +18C7D;KHITAN SMALL SCRIPT CHARACTER-18C7D;Lo;0;L;;;;;N;;;;; +18C7E;KHITAN SMALL SCRIPT CHARACTER-18C7E;Lo;0;L;;;;;N;;;;; +18C7F;KHITAN SMALL SCRIPT CHARACTER-18C7F;Lo;0;L;;;;;N;;;;; +18C80;KHITAN SMALL SCRIPT CHARACTER-18C80;Lo;0;L;;;;;N;;;;; +18C81;KHITAN SMALL SCRIPT CHARACTER-18C81;Lo;0;L;;;;;N;;;;; +18C82;KHITAN SMALL SCRIPT CHARACTER-18C82;Lo;0;L;;;;;N;;;;; +18C83;KHITAN SMALL SCRIPT CHARACTER-18C83;Lo;0;L;;;;;N;;;;; +18C84;KHITAN SMALL SCRIPT CHARACTER-18C84;Lo;0;L;;;;;N;;;;; +18C85;KHITAN SMALL SCRIPT CHARACTER-18C85;Lo;0;L;;;;;N;;;;; +18C86;KHITAN SMALL SCRIPT CHARACTER-18C86;Lo;0;L;;;;;N;;;;; +18C87;KHITAN SMALL SCRIPT CHARACTER-18C87;Lo;0;L;;;;;N;;;;; +18C88;KHITAN SMALL SCRIPT CHARACTER-18C88;Lo;0;L;;;;;N;;;;; +18C89;KHITAN SMALL SCRIPT CHARACTER-18C89;Lo;0;L;;;;;N;;;;; +18C8A;KHITAN SMALL SCRIPT CHARACTER-18C8A;Lo;0;L;;;;;N;;;;; +18C8B;KHITAN SMALL SCRIPT CHARACTER-18C8B;Lo;0;L;;;;;N;;;;; +18C8C;KHITAN SMALL SCRIPT CHARACTER-18C8C;Lo;0;L;;;;;N;;;;; +18C8D;KHITAN SMALL SCRIPT CHARACTER-18C8D;Lo;0;L;;;;;N;;;;; +18C8E;KHITAN SMALL SCRIPT CHARACTER-18C8E;Lo;0;L;;;;;N;;;;; +18C8F;KHITAN SMALL SCRIPT CHARACTER-18C8F;Lo;0;L;;;;;N;;;;; +18C90;KHITAN SMALL SCRIPT CHARACTER-18C90;Lo;0;L;;;;;N;;;;; +18C91;KHITAN SMALL SCRIPT CHARACTER-18C91;Lo;0;L;;;;;N;;;;; +18C92;KHITAN SMALL SCRIPT CHARACTER-18C92;Lo;0;L;;;;;N;;;;; +18C93;KHITAN SMALL SCRIPT CHARACTER-18C93;Lo;0;L;;;;;N;;;;; +18C94;KHITAN SMALL SCRIPT CHARACTER-18C94;Lo;0;L;;;;;N;;;;; +18C95;KHITAN SMALL SCRIPT CHARACTER-18C95;Lo;0;L;;;;;N;;;;; +18C96;KHITAN SMALL SCRIPT CHARACTER-18C96;Lo;0;L;;;;;N;;;;; +18C97;KHITAN SMALL SCRIPT CHARACTER-18C97;Lo;0;L;;;;;N;;;;; +18C98;KHITAN SMALL SCRIPT CHARACTER-18C98;Lo;0;L;;;;;N;;;;; +18C99;KHITAN SMALL SCRIPT CHARACTER-18C99;Lo;0;L;;;;;N;;;;; +18C9A;KHITAN SMALL SCRIPT CHARACTER-18C9A;Lo;0;L;;;;;N;;;;; +18C9B;KHITAN SMALL SCRIPT CHARACTER-18C9B;Lo;0;L;;;;;N;;;;; +18C9C;KHITAN SMALL SCRIPT CHARACTER-18C9C;Lo;0;L;;;;;N;;;;; +18C9D;KHITAN SMALL SCRIPT CHARACTER-18C9D;Lo;0;L;;;;;N;;;;; +18C9E;KHITAN SMALL SCRIPT CHARACTER-18C9E;Lo;0;L;;;;;N;;;;; +18C9F;KHITAN SMALL SCRIPT CHARACTER-18C9F;Lo;0;L;;;;;N;;;;; +18CA0;KHITAN SMALL SCRIPT CHARACTER-18CA0;Lo;0;L;;;;;N;;;;; +18CA1;KHITAN SMALL SCRIPT CHARACTER-18CA1;Lo;0;L;;;;;N;;;;; +18CA2;KHITAN SMALL SCRIPT CHARACTER-18CA2;Lo;0;L;;;;;N;;;;; +18CA3;KHITAN SMALL SCRIPT CHARACTER-18CA3;Lo;0;L;;;;;N;;;;; +18CA4;KHITAN SMALL SCRIPT CHARACTER-18CA4;Lo;0;L;;;;;N;;;;; +18CA5;KHITAN SMALL SCRIPT CHARACTER-18CA5;Lo;0;L;;;;;N;;;;; +18CA6;KHITAN SMALL SCRIPT CHARACTER-18CA6;Lo;0;L;;;;;N;;;;; +18CA7;KHITAN SMALL SCRIPT CHARACTER-18CA7;Lo;0;L;;;;;N;;;;; +18CA8;KHITAN SMALL SCRIPT CHARACTER-18CA8;Lo;0;L;;;;;N;;;;; +18CA9;KHITAN SMALL SCRIPT CHARACTER-18CA9;Lo;0;L;;;;;N;;;;; +18CAA;KHITAN SMALL SCRIPT CHARACTER-18CAA;Lo;0;L;;;;;N;;;;; +18CAB;KHITAN SMALL SCRIPT CHARACTER-18CAB;Lo;0;L;;;;;N;;;;; +18CAC;KHITAN SMALL SCRIPT CHARACTER-18CAC;Lo;0;L;;;;;N;;;;; +18CAD;KHITAN SMALL SCRIPT CHARACTER-18CAD;Lo;0;L;;;;;N;;;;; +18CAE;KHITAN SMALL SCRIPT CHARACTER-18CAE;Lo;0;L;;;;;N;;;;; +18CAF;KHITAN SMALL SCRIPT CHARACTER-18CAF;Lo;0;L;;;;;N;;;;; +18CB0;KHITAN SMALL SCRIPT CHARACTER-18CB0;Lo;0;L;;;;;N;;;;; +18CB1;KHITAN SMALL SCRIPT CHARACTER-18CB1;Lo;0;L;;;;;N;;;;; +18CB2;KHITAN SMALL SCRIPT CHARACTER-18CB2;Lo;0;L;;;;;N;;;;; +18CB3;KHITAN SMALL SCRIPT CHARACTER-18CB3;Lo;0;L;;;;;N;;;;; +18CB4;KHITAN SMALL SCRIPT CHARACTER-18CB4;Lo;0;L;;;;;N;;;;; +18CB5;KHITAN SMALL SCRIPT CHARACTER-18CB5;Lo;0;L;;;;;N;;;;; +18CB6;KHITAN SMALL SCRIPT CHARACTER-18CB6;Lo;0;L;;;;;N;;;;; +18CB7;KHITAN SMALL SCRIPT CHARACTER-18CB7;Lo;0;L;;;;;N;;;;; +18CB8;KHITAN SMALL SCRIPT CHARACTER-18CB8;Lo;0;L;;;;;N;;;;; +18CB9;KHITAN SMALL SCRIPT CHARACTER-18CB9;Lo;0;L;;;;;N;;;;; +18CBA;KHITAN SMALL SCRIPT CHARACTER-18CBA;Lo;0;L;;;;;N;;;;; +18CBB;KHITAN SMALL SCRIPT CHARACTER-18CBB;Lo;0;L;;;;;N;;;;; +18CBC;KHITAN SMALL SCRIPT CHARACTER-18CBC;Lo;0;L;;;;;N;;;;; +18CBD;KHITAN SMALL SCRIPT CHARACTER-18CBD;Lo;0;L;;;;;N;;;;; +18CBE;KHITAN SMALL SCRIPT CHARACTER-18CBE;Lo;0;L;;;;;N;;;;; +18CBF;KHITAN SMALL SCRIPT CHARACTER-18CBF;Lo;0;L;;;;;N;;;;; +18CC0;KHITAN SMALL SCRIPT CHARACTER-18CC0;Lo;0;L;;;;;N;;;;; +18CC1;KHITAN SMALL SCRIPT CHARACTER-18CC1;Lo;0;L;;;;;N;;;;; +18CC2;KHITAN SMALL SCRIPT CHARACTER-18CC2;Lo;0;L;;;;;N;;;;; +18CC3;KHITAN SMALL SCRIPT CHARACTER-18CC3;Lo;0;L;;;;;N;;;;; +18CC4;KHITAN SMALL SCRIPT CHARACTER-18CC4;Lo;0;L;;;;;N;;;;; +18CC5;KHITAN SMALL SCRIPT CHARACTER-18CC5;Lo;0;L;;;;;N;;;;; +18CC6;KHITAN SMALL SCRIPT CHARACTER-18CC6;Lo;0;L;;;;;N;;;;; +18CC7;KHITAN SMALL SCRIPT CHARACTER-18CC7;Lo;0;L;;;;;N;;;;; +18CC8;KHITAN SMALL SCRIPT CHARACTER-18CC8;Lo;0;L;;;;;N;;;;; +18CC9;KHITAN SMALL SCRIPT CHARACTER-18CC9;Lo;0;L;;;;;N;;;;; +18CCA;KHITAN SMALL SCRIPT CHARACTER-18CCA;Lo;0;L;;;;;N;;;;; +18CCB;KHITAN SMALL SCRIPT CHARACTER-18CCB;Lo;0;L;;;;;N;;;;; +18CCC;KHITAN SMALL SCRIPT CHARACTER-18CCC;Lo;0;L;;;;;N;;;;; +18CCD;KHITAN SMALL SCRIPT CHARACTER-18CCD;Lo;0;L;;;;;N;;;;; +18CCE;KHITAN SMALL SCRIPT CHARACTER-18CCE;Lo;0;L;;;;;N;;;;; +18CCF;KHITAN SMALL SCRIPT CHARACTER-18CCF;Lo;0;L;;;;;N;;;;; +18CD0;KHITAN SMALL SCRIPT CHARACTER-18CD0;Lo;0;L;;;;;N;;;;; +18CD1;KHITAN SMALL SCRIPT CHARACTER-18CD1;Lo;0;L;;;;;N;;;;; +18CD2;KHITAN SMALL SCRIPT CHARACTER-18CD2;Lo;0;L;;;;;N;;;;; +18CD3;KHITAN SMALL SCRIPT CHARACTER-18CD3;Lo;0;L;;;;;N;;;;; +18CD4;KHITAN SMALL SCRIPT CHARACTER-18CD4;Lo;0;L;;;;;N;;;;; +18CD5;KHITAN SMALL SCRIPT CHARACTER-18CD5;Lo;0;L;;;;;N;;;;; +18CFF;KHITAN SMALL SCRIPT CHARACTER-18CFF;Lo;0;L;;;;;N;;;;; +18D00;;Lo;0;L;;;;;N;;;;; +18D1E;;Lo;0;L;;;;;N;;;;; +18D80;TANGUT COMPONENT-769;Lo;0;L;;;;;N;;;;; +18D81;TANGUT COMPONENT-770;Lo;0;L;;;;;N;;;;; +18D82;TANGUT COMPONENT-771;Lo;0;L;;;;;N;;;;; +18D83;TANGUT COMPONENT-772;Lo;0;L;;;;;N;;;;; +18D84;TANGUT COMPONENT-773;Lo;0;L;;;;;N;;;;; +18D85;TANGUT COMPONENT-774;Lo;0;L;;;;;N;;;;; +18D86;TANGUT COMPONENT-775;Lo;0;L;;;;;N;;;;; +18D87;TANGUT COMPONENT-776;Lo;0;L;;;;;N;;;;; +18D88;TANGUT COMPONENT-777;Lo;0;L;;;;;N;;;;; +18D89;TANGUT COMPONENT-778;Lo;0;L;;;;;N;;;;; +18D8A;TANGUT COMPONENT-779;Lo;0;L;;;;;N;;;;; +18D8B;TANGUT COMPONENT-780;Lo;0;L;;;;;N;;;;; +18D8C;TANGUT COMPONENT-781;Lo;0;L;;;;;N;;;;; +18D8D;TANGUT COMPONENT-782;Lo;0;L;;;;;N;;;;; +18D8E;TANGUT COMPONENT-783;Lo;0;L;;;;;N;;;;; +18D8F;TANGUT COMPONENT-784;Lo;0;L;;;;;N;;;;; +18D90;TANGUT COMPONENT-785;Lo;0;L;;;;;N;;;;; +18D91;TANGUT COMPONENT-786;Lo;0;L;;;;;N;;;;; +18D92;TANGUT COMPONENT-787;Lo;0;L;;;;;N;;;;; +18D93;TANGUT COMPONENT-788;Lo;0;L;;;;;N;;;;; +18D94;TANGUT COMPONENT-789;Lo;0;L;;;;;N;;;;; +18D95;TANGUT COMPONENT-790;Lo;0;L;;;;;N;;;;; +18D96;TANGUT COMPONENT-791;Lo;0;L;;;;;N;;;;; +18D97;TANGUT COMPONENT-792;Lo;0;L;;;;;N;;;;; +18D98;TANGUT COMPONENT-793;Lo;0;L;;;;;N;;;;; +18D99;TANGUT COMPONENT-794;Lo;0;L;;;;;N;;;;; +18D9A;TANGUT COMPONENT-795;Lo;0;L;;;;;N;;;;; +18D9B;TANGUT COMPONENT-796;Lo;0;L;;;;;N;;;;; +18D9C;TANGUT COMPONENT-797;Lo;0;L;;;;;N;;;;; +18D9D;TANGUT COMPONENT-798;Lo;0;L;;;;;N;;;;; +18D9E;TANGUT COMPONENT-799;Lo;0;L;;;;;N;;;;; +18D9F;TANGUT COMPONENT-800;Lo;0;L;;;;;N;;;;; +18DA0;TANGUT COMPONENT-801;Lo;0;L;;;;;N;;;;; +18DA1;TANGUT COMPONENT-802;Lo;0;L;;;;;N;;;;; +18DA2;TANGUT COMPONENT-803;Lo;0;L;;;;;N;;;;; +18DA3;TANGUT COMPONENT-804;Lo;0;L;;;;;N;;;;; +18DA4;TANGUT COMPONENT-805;Lo;0;L;;;;;N;;;;; +18DA5;TANGUT COMPONENT-806;Lo;0;L;;;;;N;;;;; +18DA6;TANGUT COMPONENT-807;Lo;0;L;;;;;N;;;;; +18DA7;TANGUT COMPONENT-808;Lo;0;L;;;;;N;;;;; +18DA8;TANGUT COMPONENT-809;Lo;0;L;;;;;N;;;;; +18DA9;TANGUT COMPONENT-810;Lo;0;L;;;;;N;;;;; +18DAA;TANGUT COMPONENT-811;Lo;0;L;;;;;N;;;;; +18DAB;TANGUT COMPONENT-812;Lo;0;L;;;;;N;;;;; +18DAC;TANGUT COMPONENT-813;Lo;0;L;;;;;N;;;;; +18DAD;TANGUT COMPONENT-814;Lo;0;L;;;;;N;;;;; +18DAE;TANGUT COMPONENT-815;Lo;0;L;;;;;N;;;;; +18DAF;TANGUT COMPONENT-816;Lo;0;L;;;;;N;;;;; +18DB0;TANGUT COMPONENT-817;Lo;0;L;;;;;N;;;;; +18DB1;TANGUT COMPONENT-818;Lo;0;L;;;;;N;;;;; +18DB2;TANGUT COMPONENT-819;Lo;0;L;;;;;N;;;;; +18DB3;TANGUT COMPONENT-820;Lo;0;L;;;;;N;;;;; +18DB4;TANGUT COMPONENT-821;Lo;0;L;;;;;N;;;;; +18DB5;TANGUT COMPONENT-822;Lo;0;L;;;;;N;;;;; +18DB6;TANGUT COMPONENT-823;Lo;0;L;;;;;N;;;;; +18DB7;TANGUT COMPONENT-824;Lo;0;L;;;;;N;;;;; +18DB8;TANGUT COMPONENT-825;Lo;0;L;;;;;N;;;;; +18DB9;TANGUT COMPONENT-826;Lo;0;L;;;;;N;;;;; +18DBA;TANGUT COMPONENT-827;Lo;0;L;;;;;N;;;;; +18DBB;TANGUT COMPONENT-828;Lo;0;L;;;;;N;;;;; +18DBC;TANGUT COMPONENT-829;Lo;0;L;;;;;N;;;;; +18DBD;TANGUT COMPONENT-830;Lo;0;L;;;;;N;;;;; +18DBE;TANGUT COMPONENT-831;Lo;0;L;;;;;N;;;;; +18DBF;TANGUT COMPONENT-832;Lo;0;L;;;;;N;;;;; +18DC0;TANGUT COMPONENT-833;Lo;0;L;;;;;N;;;;; +18DC1;TANGUT COMPONENT-834;Lo;0;L;;;;;N;;;;; +18DC2;TANGUT COMPONENT-835;Lo;0;L;;;;;N;;;;; +18DC3;TANGUT COMPONENT-836;Lo;0;L;;;;;N;;;;; +18DC4;TANGUT COMPONENT-837;Lo;0;L;;;;;N;;;;; +18DC5;TANGUT COMPONENT-838;Lo;0;L;;;;;N;;;;; +18DC6;TANGUT COMPONENT-839;Lo;0;L;;;;;N;;;;; +18DC7;TANGUT COMPONENT-840;Lo;0;L;;;;;N;;;;; +18DC8;TANGUT COMPONENT-841;Lo;0;L;;;;;N;;;;; +18DC9;TANGUT COMPONENT-842;Lo;0;L;;;;;N;;;;; +18DCA;TANGUT COMPONENT-843;Lo;0;L;;;;;N;;;;; +18DCB;TANGUT COMPONENT-844;Lo;0;L;;;;;N;;;;; +18DCC;TANGUT COMPONENT-845;Lo;0;L;;;;;N;;;;; +18DCD;TANGUT COMPONENT-846;Lo;0;L;;;;;N;;;;; +18DCE;TANGUT COMPONENT-847;Lo;0;L;;;;;N;;;;; +18DCF;TANGUT COMPONENT-848;Lo;0;L;;;;;N;;;;; +18DD0;TANGUT COMPONENT-849;Lo;0;L;;;;;N;;;;; +18DD1;TANGUT COMPONENT-850;Lo;0;L;;;;;N;;;;; +18DD2;TANGUT COMPONENT-851;Lo;0;L;;;;;N;;;;; +18DD3;TANGUT COMPONENT-852;Lo;0;L;;;;;N;;;;; +18DD4;TANGUT COMPONENT-853;Lo;0;L;;;;;N;;;;; +18DD5;TANGUT COMPONENT-854;Lo;0;L;;;;;N;;;;; +18DD6;TANGUT COMPONENT-855;Lo;0;L;;;;;N;;;;; +18DD7;TANGUT COMPONENT-856;Lo;0;L;;;;;N;;;;; +18DD8;TANGUT COMPONENT-857;Lo;0;L;;;;;N;;;;; +18DD9;TANGUT COMPONENT-858;Lo;0;L;;;;;N;;;;; +18DDA;TANGUT COMPONENT-859;Lo;0;L;;;;;N;;;;; +18DDB;TANGUT COMPONENT-860;Lo;0;L;;;;;N;;;;; +18DDC;TANGUT COMPONENT-861;Lo;0;L;;;;;N;;;;; +18DDD;TANGUT COMPONENT-862;Lo;0;L;;;;;N;;;;; +18DDE;TANGUT COMPONENT-863;Lo;0;L;;;;;N;;;;; +18DDF;TANGUT COMPONENT-864;Lo;0;L;;;;;N;;;;; +18DE0;TANGUT COMPONENT-865;Lo;0;L;;;;;N;;;;; +18DE1;TANGUT COMPONENT-866;Lo;0;L;;;;;N;;;;; +18DE2;TANGUT COMPONENT-867;Lo;0;L;;;;;N;;;;; +18DE3;TANGUT COMPONENT-868;Lo;0;L;;;;;N;;;;; +18DE4;TANGUT COMPONENT-869;Lo;0;L;;;;;N;;;;; +18DE5;TANGUT COMPONENT-870;Lo;0;L;;;;;N;;;;; +18DE6;TANGUT COMPONENT-871;Lo;0;L;;;;;N;;;;; +18DE7;TANGUT COMPONENT-872;Lo;0;L;;;;;N;;;;; +18DE8;TANGUT COMPONENT-873;Lo;0;L;;;;;N;;;;; +18DE9;TANGUT COMPONENT-874;Lo;0;L;;;;;N;;;;; +18DEA;TANGUT COMPONENT-875;Lo;0;L;;;;;N;;;;; +18DEB;TANGUT COMPONENT-876;Lo;0;L;;;;;N;;;;; +18DEC;TANGUT COMPONENT-877;Lo;0;L;;;;;N;;;;; +18DED;TANGUT COMPONENT-878;Lo;0;L;;;;;N;;;;; +18DEE;TANGUT COMPONENT-879;Lo;0;L;;;;;N;;;;; +18DEF;TANGUT COMPONENT-880;Lo;0;L;;;;;N;;;;; +18DF0;TANGUT COMPONENT-881;Lo;0;L;;;;;N;;;;; +18DF1;TANGUT COMPONENT-882;Lo;0;L;;;;;N;;;;; +18DF2;TANGUT COMPONENT-883;Lo;0;L;;;;;N;;;;; +1AFF0;KATAKANA LETTER MINNAN TONE-2;Lm;0;L;;;;;N;;;;; +1AFF1;KATAKANA LETTER MINNAN TONE-3;Lm;0;L;;;;;N;;;;; +1AFF2;KATAKANA LETTER MINNAN TONE-4;Lm;0;L;;;;;N;;;;; +1AFF3;KATAKANA LETTER MINNAN TONE-5;Lm;0;L;;;;;N;;;;; +1AFF5;KATAKANA LETTER MINNAN TONE-7;Lm;0;L;;;;;N;;;;; +1AFF6;KATAKANA LETTER MINNAN TONE-8;Lm;0;L;;;;;N;;;;; +1AFF7;KATAKANA LETTER MINNAN NASALIZED TONE-1;Lm;0;L;;;;;N;;;;; +1AFF8;KATAKANA LETTER MINNAN NASALIZED TONE-2;Lm;0;L;;;;;N;;;;; +1AFF9;KATAKANA LETTER MINNAN NASALIZED TONE-3;Lm;0;L;;;;;N;;;;; +1AFFA;KATAKANA LETTER MINNAN NASALIZED TONE-4;Lm;0;L;;;;;N;;;;; +1AFFB;KATAKANA LETTER MINNAN NASALIZED TONE-5;Lm;0;L;;;;;N;;;;; +1AFFD;KATAKANA LETTER MINNAN NASALIZED TONE-7;Lm;0;L;;;;;N;;;;; +1AFFE;KATAKANA LETTER MINNAN NASALIZED TONE-8;Lm;0;L;;;;;N;;;;; +1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; +1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;; +1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;; +1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;; +1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;; +1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;; +1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;; +1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;; +1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;; +1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;; +1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;; +1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;; +1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;; +1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;; +1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;; +1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;; +1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;; +1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;; +1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;; +1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;; +1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;; +1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;; +1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;; +1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;; +1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;; +1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;; +1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;; +1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;; +1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;; +1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;; +1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;; +1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;; +1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;; +1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;; +1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;; +1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;; +1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;; +1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;; +1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;; +1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;; +1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;; +1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;; +1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;; +1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;; +1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;; +1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;; +1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;; +1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;; +1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;; +1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;; +1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;; +1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;; +1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;; +1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;; +1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;; +1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;; +1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;; +1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;; +1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;; +1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;; +1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;; +1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;; +1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;; +1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;; +1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;; +1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;; +1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;; +1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;; +1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;; +1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;; +1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;; +1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;; +1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;; +1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;; +1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;; +1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;; +1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;; +1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;; +1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;; +1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;; +1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;; +1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;; +1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;; +1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;; +1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;; +1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;; +1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;; +1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;; +1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;; +1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;; +1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;; +1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;; +1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;; +1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;; +1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;; +1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;; +1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;; +1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;; +1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;; +1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;; +1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;; +1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;; +1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;; +1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;; +1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;; +1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;; +1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;; +1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;; +1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;; +1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;; +1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;; +1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;; +1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;; +1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;; +1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;; +1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;; +1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;; +1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;; +1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;; +1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;; +1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;; +1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;; +1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;; +1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;; +1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;; +1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;; +1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;; +1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;; +1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;; +1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;; +1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;; +1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;; +1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;; +1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;; +1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;; +1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;; +1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;; +1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;; +1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;; +1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;; +1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;; +1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;; +1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;; +1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;; +1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;; +1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;; +1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;; +1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;; +1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;; +1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;; +1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;; +1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;; +1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;; +1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;; +1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;; +1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;; +1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;; +1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;; +1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;; +1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;; +1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;; +1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;; +1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;; +1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;; +1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;; +1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;; +1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;; +1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;; +1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;; +1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;; +1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;; +1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;; +1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;; +1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;; +1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;; +1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;; +1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;; +1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;; +1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;; +1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;; +1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;; +1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;; +1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;; +1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;; +1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;; +1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;; +1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;; +1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;; +1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;; +1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;; +1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;; +1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;; +1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;; +1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;; +1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;; +1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;; +1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;; +1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;; +1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;; +1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;; +1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;; +1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;; +1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;; +1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;; +1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;; +1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;; +1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;; +1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;; +1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;; +1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;; +1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;; +1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;; +1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;; +1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;; +1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;; +1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;; +1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;; +1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;; +1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;; +1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;; +1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;; +1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;; +1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;; +1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;; +1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;; +1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;; +1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;; +1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;; +1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;; +1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;; +1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;; +1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;; +1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;; +1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;; +1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;; +1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;; +1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;; +1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;; +1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;; +1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;; +1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;; +1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;; +1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;; +1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;; +1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;; +1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;; +1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;; +1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;; +1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;; +1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;; +1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;; +1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;; +1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;; +1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;; +1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;; +1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;; +1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;; +1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;; +1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;; +1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;; +1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;; +1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;; +1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;; +1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;; +1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;; +1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;; +1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;; +1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;; +1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;; +1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;; +1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;; +1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;; +1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;; +1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;; +1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;; +1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;; +1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;; +1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;; +1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;; +1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;; +1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;; +1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;; +1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;; +1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;; +1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;; +1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;; +1B11F;HIRAGANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;; +1B120;KATAKANA LETTER ARCHAIC YI;Lo;0;L;;;;;N;;;;; +1B121;KATAKANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; +1B122;KATAKANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;; +1B132;HIRAGANA LETTER SMALL KO;Lo;0;L;;;;;N;;;;; +1B150;HIRAGANA LETTER SMALL WI;Lo;0;L;;;;;N;;;;; +1B151;HIRAGANA LETTER SMALL WE;Lo;0;L;;;;;N;;;;; +1B152;HIRAGANA LETTER SMALL WO;Lo;0;L;;;;;N;;;;; +1B155;KATAKANA LETTER SMALL KO;Lo;0;L;;;;;N;;;;; +1B164;KATAKANA LETTER SMALL WI;Lo;0;L;;;;;N;;;;; +1B165;KATAKANA LETTER SMALL WE;Lo;0;L;;;;;N;;;;; +1B166;KATAKANA LETTER SMALL WO;Lo;0;L;;;;;N;;;;; +1B167;KATAKANA LETTER SMALL N;Lo;0;L;;;;;N;;;;; +1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;; +1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;; +1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;; +1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;; +1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;; +1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;; +1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;; +1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;; +1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;; +1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;; +1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;; +1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;; +1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;; +1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;; +1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;; +1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;; +1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;; +1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;; +1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;; +1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;; +1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;; +1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;; +1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;; +1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;; +1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;; +1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;; +1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;; +1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;; +1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;; +1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;; +1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;; +1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;; +1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;; +1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;; +1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;; +1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;; +1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;; +1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;; +1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;; +1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;; +1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;; +1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;; +1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;; +1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;; +1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;; +1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;; +1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;; +1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;; +1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;; +1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;; +1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;; +1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;; +1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;; +1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;; +1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;; +1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;; +1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;; +1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;; +1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;; +1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;; +1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;; +1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;; +1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;; +1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;; +1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;; +1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;; +1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;; +1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;; +1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;; +1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;; +1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;; +1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;; +1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;; +1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;; +1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;; +1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;; +1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;; +1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;; +1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;; +1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;; +1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;; +1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;; +1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;; +1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;; +1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;; +1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;; +1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;; +1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;; +1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;; +1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;; +1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;; +1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;; +1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;; +1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;; +1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;; +1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;; +1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;; +1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;; +1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;; +1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;; +1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;; +1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;; +1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;; +1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;; +1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;; +1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;; +1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;; +1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;; +1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;; +1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;; +1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;; +1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;; +1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;; +1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;; +1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;; +1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;; +1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;; +1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;; +1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;; +1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;; +1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;; +1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;; +1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;; +1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;; +1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;; +1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;; +1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;; +1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;; +1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;; +1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;; +1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;; +1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;; +1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;; +1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;; +1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;; +1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;; +1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;; +1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;; +1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;; +1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;; +1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;; +1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;; +1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;; +1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;; +1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;; +1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;; +1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;; +1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;; +1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;; +1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;; +1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;; +1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;; +1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;; +1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;; +1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;; +1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;; +1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;; +1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;; +1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;; +1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;; +1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;; +1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;; +1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;; +1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;; +1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;; +1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;; +1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;; +1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;; +1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;; +1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;; +1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;; +1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;; +1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;; +1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;; +1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;; +1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;; +1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;; +1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;; +1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;; +1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;; +1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;; +1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;; +1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;; +1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;; +1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;; +1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;; +1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;; +1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;; +1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;; +1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;; +1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;; +1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;; +1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;; +1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;; +1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;; +1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;; +1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;; +1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;; +1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;; +1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;; +1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;; +1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;; +1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;; +1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;; +1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;; +1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;; +1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;; +1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;; +1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;; +1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;; +1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;; +1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;; +1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;; +1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;; +1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;; +1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;; +1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;; +1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;; +1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;; +1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;; +1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;; +1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;; +1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;; +1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;; +1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;; +1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;; +1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;; +1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;; +1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;; +1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;; +1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;; +1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;; +1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;; +1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;; +1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;; +1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;; +1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;; +1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;; +1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;; +1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;; +1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;; +1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;; +1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;; +1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;; +1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;; +1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;; +1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;; +1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;; +1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;; +1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;; +1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;; +1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;; +1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;; +1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;; +1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;; +1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;; +1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;; +1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;; +1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;; +1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;; +1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;; +1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;; +1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;; +1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;; +1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;; +1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;; +1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;; +1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;; +1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;; +1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;; +1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;; +1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;; +1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;; +1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;; +1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;; +1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;; +1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;; +1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;; +1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;; +1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;; +1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;; +1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;; +1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;; +1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;; +1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;; +1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;; +1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;; +1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;; +1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;; +1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;; +1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;; +1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;; +1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;; +1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;; +1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;; +1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;; +1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;; +1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;; +1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;; +1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;; +1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;; +1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;; +1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;; +1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;; +1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;; +1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;; +1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;; +1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;; +1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;; +1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;; +1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;; +1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;; +1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;; +1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;; +1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;; +1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;; +1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;; +1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;; +1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;; +1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;; +1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;; +1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;; +1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;; +1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;; +1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;; +1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;; +1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;; +1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;; +1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;; +1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;; +1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;; +1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;; +1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;; +1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;; +1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;; +1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;; +1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;; +1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;; +1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;; +1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;; +1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;; +1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;; +1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;; +1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;; +1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;; +1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;; +1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;; +1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;; +1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;; +1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;; +1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;; +1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;; +1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;; +1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;; +1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;; +1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;; +1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;; +1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;; +1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;; +1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;; +1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;; +1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;; +1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;; +1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;; +1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;; +1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;; +1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;; +1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;; +1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;; +1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;; +1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;; +1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;; +1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;; +1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;; +1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;; +1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;; +1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;; +1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;; +1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;; +1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;; +1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;; +1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;; +1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;; +1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;; +1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;; +1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;; +1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;; +1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;; +1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;; +1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;; +1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;; +1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;; +1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;; +1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;; +1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;; +1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;; +1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;; +1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;; +1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;; +1BC03;DUPLOYAN LETTER T;Lo;0;L;;;;;N;;;;; +1BC04;DUPLOYAN LETTER F;Lo;0;L;;;;;N;;;;; +1BC05;DUPLOYAN LETTER K;Lo;0;L;;;;;N;;;;; +1BC06;DUPLOYAN LETTER L;Lo;0;L;;;;;N;;;;; +1BC07;DUPLOYAN LETTER B;Lo;0;L;;;;;N;;;;; +1BC08;DUPLOYAN LETTER D;Lo;0;L;;;;;N;;;;; +1BC09;DUPLOYAN LETTER V;Lo;0;L;;;;;N;;;;; +1BC0A;DUPLOYAN LETTER G;Lo;0;L;;;;;N;;;;; +1BC0B;DUPLOYAN LETTER R;Lo;0;L;;;;;N;;;;; +1BC0C;DUPLOYAN LETTER P N;Lo;0;L;;;;;N;;;;; +1BC0D;DUPLOYAN LETTER D S;Lo;0;L;;;;;N;;;;; +1BC0E;DUPLOYAN LETTER F N;Lo;0;L;;;;;N;;;;; +1BC0F;DUPLOYAN LETTER K M;Lo;0;L;;;;;N;;;;; +1BC10;DUPLOYAN LETTER R S;Lo;0;L;;;;;N;;;;; +1BC11;DUPLOYAN LETTER TH;Lo;0;L;;;;;N;;;;; +1BC12;DUPLOYAN LETTER SLOAN DH;Lo;0;L;;;;;N;;;;; +1BC13;DUPLOYAN LETTER DH;Lo;0;L;;;;;N;;;;; +1BC14;DUPLOYAN LETTER KK;Lo;0;L;;;;;N;;;;; +1BC15;DUPLOYAN LETTER SLOAN J;Lo;0;L;;;;;N;;;;; +1BC16;DUPLOYAN LETTER HL;Lo;0;L;;;;;N;;;;; +1BC17;DUPLOYAN LETTER LH;Lo;0;L;;;;;N;;;;; +1BC18;DUPLOYAN LETTER RH;Lo;0;L;;;;;N;;;;; +1BC19;DUPLOYAN LETTER M;Lo;0;L;;;;;N;;;;; +1BC1A;DUPLOYAN LETTER N;Lo;0;L;;;;;N;;;;; +1BC1B;DUPLOYAN LETTER J;Lo;0;L;;;;;N;;;;; +1BC1C;DUPLOYAN LETTER S;Lo;0;L;;;;;N;;;;; +1BC1D;DUPLOYAN LETTER M N;Lo;0;L;;;;;N;;;;; +1BC1E;DUPLOYAN LETTER N M;Lo;0;L;;;;;N;;;;; +1BC1F;DUPLOYAN LETTER J M;Lo;0;L;;;;;N;;;;; +1BC20;DUPLOYAN LETTER S J;Lo;0;L;;;;;N;;;;; +1BC21;DUPLOYAN LETTER M WITH DOT;Lo;0;L;;;;;N;;;;; +1BC22;DUPLOYAN LETTER N WITH DOT;Lo;0;L;;;;;N;;;;; +1BC23;DUPLOYAN LETTER J WITH DOT;Lo;0;L;;;;;N;;;;; +1BC24;DUPLOYAN LETTER J WITH DOTS INSIDE AND ABOVE;Lo;0;L;;;;;N;;;;; +1BC25;DUPLOYAN LETTER S WITH DOT;Lo;0;L;;;;;N;;;;; +1BC26;DUPLOYAN LETTER S WITH DOT BELOW;Lo;0;L;;;;;N;;;;; +1BC27;DUPLOYAN LETTER M S;Lo;0;L;;;;;N;;;;; +1BC28;DUPLOYAN LETTER N S;Lo;0;L;;;;;N;;;;; +1BC29;DUPLOYAN LETTER J S;Lo;0;L;;;;;N;;;;; +1BC2A;DUPLOYAN LETTER S S;Lo;0;L;;;;;N;;;;; +1BC2B;DUPLOYAN LETTER M N S;Lo;0;L;;;;;N;;;;; +1BC2C;DUPLOYAN LETTER N M S;Lo;0;L;;;;;N;;;;; +1BC2D;DUPLOYAN LETTER J M S;Lo;0;L;;;;;N;;;;; +1BC2E;DUPLOYAN LETTER S J S;Lo;0;L;;;;;N;;;;; +1BC2F;DUPLOYAN LETTER J S WITH DOT;Lo;0;L;;;;;N;;;;; +1BC30;DUPLOYAN LETTER J N;Lo;0;L;;;;;N;;;;; +1BC31;DUPLOYAN LETTER J N S;Lo;0;L;;;;;N;;;;; +1BC32;DUPLOYAN LETTER S T;Lo;0;L;;;;;N;;;;; +1BC33;DUPLOYAN LETTER S T R;Lo;0;L;;;;;N;;;;; +1BC34;DUPLOYAN LETTER S P;Lo;0;L;;;;;N;;;;; +1BC35;DUPLOYAN LETTER S P R;Lo;0;L;;;;;N;;;;; +1BC36;DUPLOYAN LETTER T S;Lo;0;L;;;;;N;;;;; +1BC37;DUPLOYAN LETTER T R S;Lo;0;L;;;;;N;;;;; +1BC38;DUPLOYAN LETTER W;Lo;0;L;;;;;N;;;;; +1BC39;DUPLOYAN LETTER WH;Lo;0;L;;;;;N;;;;; +1BC3A;DUPLOYAN LETTER W R;Lo;0;L;;;;;N;;;;; +1BC3B;DUPLOYAN LETTER S N;Lo;0;L;;;;;N;;;;; +1BC3C;DUPLOYAN LETTER S M;Lo;0;L;;;;;N;;;;; +1BC3D;DUPLOYAN LETTER K R S;Lo;0;L;;;;;N;;;;; +1BC3E;DUPLOYAN LETTER G R S;Lo;0;L;;;;;N;;;;; +1BC3F;DUPLOYAN LETTER S K;Lo;0;L;;;;;N;;;;; +1BC40;DUPLOYAN LETTER S K R;Lo;0;L;;;;;N;;;;; +1BC41;DUPLOYAN LETTER A;Lo;0;L;;;;;N;;;;; +1BC42;DUPLOYAN LETTER SLOAN OW;Lo;0;L;;;;;N;;;;; +1BC43;DUPLOYAN LETTER OA;Lo;0;L;;;;;N;;;;; +1BC44;DUPLOYAN LETTER O;Lo;0;L;;;;;N;;;;; +1BC45;DUPLOYAN LETTER AOU;Lo;0;L;;;;;N;;;;; +1BC46;DUPLOYAN LETTER I;Lo;0;L;;;;;N;;;;; +1BC47;DUPLOYAN LETTER E;Lo;0;L;;;;;N;;;;; +1BC48;DUPLOYAN LETTER IE;Lo;0;L;;;;;N;;;;; +1BC49;DUPLOYAN LETTER SHORT I;Lo;0;L;;;;;N;;;;; +1BC4A;DUPLOYAN LETTER UI;Lo;0;L;;;;;N;;;;; +1BC4B;DUPLOYAN LETTER EE;Lo;0;L;;;;;N;;;;; +1BC4C;DUPLOYAN LETTER SLOAN EH;Lo;0;L;;;;;N;;;;; +1BC4D;DUPLOYAN LETTER ROMANIAN I;Lo;0;L;;;;;N;;;;; +1BC4E;DUPLOYAN LETTER SLOAN EE;Lo;0;L;;;;;N;;;;; +1BC4F;DUPLOYAN LETTER LONG I;Lo;0;L;;;;;N;;;;; +1BC50;DUPLOYAN LETTER YE;Lo;0;L;;;;;N;;;;; +1BC51;DUPLOYAN LETTER U;Lo;0;L;;;;;N;;;;; +1BC52;DUPLOYAN LETTER EU;Lo;0;L;;;;;N;;;;; +1BC53;DUPLOYAN LETTER XW;Lo;0;L;;;;;N;;;;; +1BC54;DUPLOYAN LETTER U N;Lo;0;L;;;;;N;;;;; +1BC55;DUPLOYAN LETTER LONG U;Lo;0;L;;;;;N;;;;; +1BC56;DUPLOYAN LETTER ROMANIAN U;Lo;0;L;;;;;N;;;;; +1BC57;DUPLOYAN LETTER UH;Lo;0;L;;;;;N;;;;; +1BC58;DUPLOYAN LETTER SLOAN U;Lo;0;L;;;;;N;;;;; +1BC59;DUPLOYAN LETTER OOH;Lo;0;L;;;;;N;;;;; +1BC5A;DUPLOYAN LETTER OW;Lo;0;L;;;;;N;;;;; +1BC5B;DUPLOYAN LETTER OU;Lo;0;L;;;;;N;;;;; +1BC5C;DUPLOYAN LETTER WA;Lo;0;L;;;;;N;;;;; +1BC5D;DUPLOYAN LETTER WO;Lo;0;L;;;;;N;;;;; +1BC5E;DUPLOYAN LETTER WI;Lo;0;L;;;;;N;;;;; +1BC5F;DUPLOYAN LETTER WEI;Lo;0;L;;;;;N;;;;; +1BC60;DUPLOYAN LETTER WOW;Lo;0;L;;;;;N;;;;; +1BC61;DUPLOYAN LETTER NASAL U;Lo;0;L;;;;;N;;;;; +1BC62;DUPLOYAN LETTER NASAL O;Lo;0;L;;;;;N;;;;; +1BC63;DUPLOYAN LETTER NASAL I;Lo;0;L;;;;;N;;;;; +1BC64;DUPLOYAN LETTER NASAL A;Lo;0;L;;;;;N;;;;; +1BC65;DUPLOYAN LETTER PERNIN AN;Lo;0;L;;;;;N;;;;; +1BC66;DUPLOYAN LETTER PERNIN AM;Lo;0;L;;;;;N;;;;; +1BC67;DUPLOYAN LETTER SLOAN EN;Lo;0;L;;;;;N;;;;; +1BC68;DUPLOYAN LETTER SLOAN AN;Lo;0;L;;;;;N;;;;; +1BC69;DUPLOYAN LETTER SLOAN ON;Lo;0;L;;;;;N;;;;; +1BC6A;DUPLOYAN LETTER VOCALIC M;Lo;0;L;;;;;N;;;;; +1BC70;DUPLOYAN AFFIX LEFT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC71;DUPLOYAN AFFIX MID HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC72;DUPLOYAN AFFIX RIGHT HORIZONTAL SECANT;Lo;0;L;;;;;N;;;;; +1BC73;DUPLOYAN AFFIX LOW VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC74;DUPLOYAN AFFIX MID VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC75;DUPLOYAN AFFIX HIGH VERTICAL SECANT;Lo;0;L;;;;;N;;;;; +1BC76;DUPLOYAN AFFIX ATTACHED SECANT;Lo;0;L;;;;;N;;;;; +1BC77;DUPLOYAN AFFIX ATTACHED LEFT-TO-RIGHT SECANT;Lo;0;L;;;;;N;;;;; +1BC78;DUPLOYAN AFFIX ATTACHED TANGENT;Lo;0;L;;;;;N;;;;; +1BC79;DUPLOYAN AFFIX ATTACHED TAIL;Lo;0;L;;;;;N;;;;; +1BC7A;DUPLOYAN AFFIX ATTACHED E HOOK;Lo;0;L;;;;;N;;;;; +1BC7B;DUPLOYAN AFFIX ATTACHED I HOOK;Lo;0;L;;;;;N;;;;; +1BC7C;DUPLOYAN AFFIX ATTACHED TANGENT HOOK;Lo;0;L;;;;;N;;;;; +1BC80;DUPLOYAN AFFIX HIGH ACUTE;Lo;0;L;;;;;N;;;;; +1BC81;DUPLOYAN AFFIX HIGH TIGHT ACUTE;Lo;0;L;;;;;N;;;;; +1BC82;DUPLOYAN AFFIX HIGH GRAVE;Lo;0;L;;;;;N;;;;; +1BC83;DUPLOYAN AFFIX HIGH LONG GRAVE;Lo;0;L;;;;;N;;;;; +1BC84;DUPLOYAN AFFIX HIGH DOT;Lo;0;L;;;;;N;;;;; +1BC85;DUPLOYAN AFFIX HIGH CIRCLE;Lo;0;L;;;;;N;;;;; +1BC86;DUPLOYAN AFFIX HIGH LINE;Lo;0;L;;;;;N;;;;; +1BC87;DUPLOYAN AFFIX HIGH WAVE;Lo;0;L;;;;;N;;;;; +1BC88;DUPLOYAN AFFIX HIGH VERTICAL;Lo;0;L;;;;;N;;;;; +1BC90;DUPLOYAN AFFIX LOW ACUTE;Lo;0;L;;;;;N;;;;; +1BC91;DUPLOYAN AFFIX LOW TIGHT ACUTE;Lo;0;L;;;;;N;;;;; +1BC92;DUPLOYAN AFFIX LOW GRAVE;Lo;0;L;;;;;N;;;;; +1BC93;DUPLOYAN AFFIX LOW LONG GRAVE;Lo;0;L;;;;;N;;;;; +1BC94;DUPLOYAN AFFIX LOW DOT;Lo;0;L;;;;;N;;;;; +1BC95;DUPLOYAN AFFIX LOW CIRCLE;Lo;0;L;;;;;N;;;;; +1BC96;DUPLOYAN AFFIX LOW LINE;Lo;0;L;;;;;N;;;;; +1BC97;DUPLOYAN AFFIX LOW WAVE;Lo;0;L;;;;;N;;;;; +1BC98;DUPLOYAN AFFIX LOW VERTICAL;Lo;0;L;;;;;N;;;;; +1BC99;DUPLOYAN AFFIX LOW ARROW;Lo;0;L;;;;;N;;;;; +1BC9C;DUPLOYAN SIGN O WITH CROSS;So;0;L;;;;;N;;;;; +1BC9D;DUPLOYAN THICK LETTER SELECTOR;Mn;0;NSM;;;;;N;;;;; +1BC9E;DUPLOYAN DOUBLE MARK;Mn;1;NSM;;;;;N;;;;; +1BC9F;DUPLOYAN PUNCTUATION CHINOOK FULL STOP;Po;0;L;;;;;N;;;;; +1BCA0;SHORTHAND FORMAT LETTER OVERLAP;Cf;0;BN;;;;;N;;;;; +1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;; +1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;; +1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;; +1CC00;UP-POINTING GO-KART;So;0;ON;;;;;N;;;;; +1CC01;RIGHT-POINTING GO-KART;So;0;ON;;;;;N;;;;; +1CC02;LEFT-POINTING STICK FIGURE;So;0;ON;;;;;N;;;;; +1CC03;RIGHT-POINTING STICK FIGURE;So;0;ON;;;;;N;;;;; +1CC04;DOWN-POINTING STICK FIGURE;So;0;ON;;;;;N;;;;; +1CC05;LOWER HORIZONTAL RULER SEGMENT;So;0;ON;;;;;N;;;;; +1CC06;RIGHT VERTICAL RULER SEGMENT;So;0;ON;;;;;N;;;;; +1CC07;LOWER RIGHT RULER SEGMENT;So;0;ON;;;;;N;;;;; +1CC08;ANTENNA;So;0;ON;;;;;N;;;;; +1CC09;HORIZONTAL RESISTOR SEGMENT;So;0;ON;;;;;N;;;;; +1CC0A;VERTICAL RESISTOR SEGMENT;So;0;ON;;;;;N;;;;; +1CC0B;LEFT THIRD INDUCTOR;So;0;ON;;;;;N;;;;; +1CC0C;MIDDLE THIRD INDUCTOR;So;0;ON;;;;;N;;;;; +1CC0D;RIGHT THIRD INDUCTOR;So;0;ON;;;;;N;;;;; +1CC0E;LEFT-POINTING DIODE;So;0;ON;;;;;N;;;;; +1CC0F;RIGHT-POINTING DIODE;So;0;ON;;;;;N;;;;; +1CC10;NPN TRANSISTOR;So;0;ON;;;;;N;;;;; +1CC11;PNP TRANSISTOR;So;0;ON;;;;;N;;;;; +1CC12;RECEPTACLE;So;0;ON;;;;;N;;;;; +1CC13;HORIZONTAL CAPACITOR;So;0;ON;;;;;N;;;;; +1CC14;VERTICAL CAPACITOR;So;0;ON;;;;;N;;;;; +1CC15;LOGIC GATE OR;So;0;ON;;;;;N;;;;; +1CC16;LOGIC GATE AND;So;0;ON;;;;;N;;;;; +1CC17;LOGIC GATE INVERTED INPUTS;So;0;ON;;;;;N;;;;; +1CC18;LOGIC GATE INVERTED OUTPUT;So;0;ON;;;;;N;;;;; +1CC19;LOGIC GATE BUFFER;So;0;ON;;;;;N;;;;; +1CC1A;LOGIC GATE BUFFER WITH INVERTED INPUT;So;0;ON;;;;;N;;;;; +1CC1B;BOX DRAWINGS LIGHT HORIZONTAL AND UPPER RIGHT;So;0;ON;;;;;N;;;;; +1CC1C;BOX DRAWINGS LIGHT HORIZONTAL AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +1CC1D;BOX DRAWINGS LIGHT TOP AND UPPER LEFT;So;0;ON;;;;;N;;;;; +1CC1E;BOX DRAWINGS LIGHT BOTTOM AND LOWER LEFT;So;0;ON;;;;;N;;;;; +1CC1F;BOX DRAWINGS DOUBLE DIAGONAL UPPER RIGHT TO LOWER LEFT;So;0;ON;;;;;N;;;;; +1CC20;BOX DRAWINGS DOUBLE DIAGONAL UPPER LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1CC21;SEPARATED BLOCK QUADRANT-1;So;0;ON;;;;;N;;;;; +1CC22;SEPARATED BLOCK QUADRANT-2;So;0;ON;;;;;N;;;;; +1CC23;SEPARATED BLOCK QUADRANT-12;So;0;ON;;;;;N;;;;; +1CC24;SEPARATED BLOCK QUADRANT-3;So;0;ON;;;;;N;;;;; +1CC25;SEPARATED BLOCK QUADRANT-13;So;0;ON;;;;;N;;;;; +1CC26;SEPARATED BLOCK QUADRANT-23;So;0;ON;;;;;N;;;;; +1CC27;SEPARATED BLOCK QUADRANT-123;So;0;ON;;;;;N;;;;; +1CC28;SEPARATED BLOCK QUADRANT-4;So;0;ON;;;;;N;;;;; +1CC29;SEPARATED BLOCK QUADRANT-14;So;0;ON;;;;;N;;;;; +1CC2A;SEPARATED BLOCK QUADRANT-24;So;0;ON;;;;;N;;;;; +1CC2B;SEPARATED BLOCK QUADRANT-124;So;0;ON;;;;;N;;;;; +1CC2C;SEPARATED BLOCK QUADRANT-34;So;0;ON;;;;;N;;;;; +1CC2D;SEPARATED BLOCK QUADRANT-134;So;0;ON;;;;;N;;;;; +1CC2E;SEPARATED BLOCK QUADRANT-234;So;0;ON;;;;;N;;;;; +1CC2F;SEPARATED BLOCK QUADRANT-1234;So;0;ON;;;;;N;;;;; +1CC30;UPPER LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC31;UPPER CENTRE LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC32;UPPER CENTRE RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC33;UPPER RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC34;UPPER MIDDLE LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC35;UPPER LEFT QUARTER CIRCLE;So;0;ON;;;;;N;;;;; +1CC36;UPPER RIGHT QUARTER CIRCLE;So;0;ON;;;;;N;;;;; +1CC37;UPPER MIDDLE RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC38;LOWER MIDDLE LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC39;LOWER LEFT QUARTER CIRCLE;So;0;ON;;;;;N;;;;; +1CC3A;LOWER RIGHT QUARTER CIRCLE;So;0;ON;;;;;N;;;;; +1CC3B;LOWER MIDDLE RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC3C;LOWER LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC3D;LOWER CENTRE LEFT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC3E;LOWER CENTRE RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC3F;LOWER RIGHT TWELFTH CIRCLE;So;0;ON;;;;;N;;;;; +1CC40;SPARSE HORIZONTAL FILL;So;0;ON;;;;;N;;;;; +1CC41;SPARSE VERTICAL FILL;So;0;ON;;;;;N;;;;; +1CC42;ORTHOGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +1CC43;DIAGONAL CROSSHATCH FILL;So;0;ON;;;;;N;;;;; +1CC44;DENSE VERTICAL FILL;So;0;ON;;;;;N;;;;; +1CC45;DENSE HORIZONTAL FILL;So;0;ON;;;;;N;;;;; +1CC46;SPECKLE FILL FRAME-1;So;0;ON;;;;;N;;;;; +1CC47;SPECKLE FILL FRAME-2;So;0;ON;;;;;N;;;;; +1CC48;LEFT-FACING BASSINET;So;0;ON;;;;;N;;;;; +1CC49;RIGHT-FACING BASSINET;So;0;ON;;;;;N;;;;; +1CC4A;FLYING SAUCER WITH BEAMS;So;0;ON;;;;;N;;;;; +1CC4B;FLYING SAUCER WITHOUT BEAMS;So;0;ON;;;;;N;;;;; +1CC4C;ALIEN MONSTER OPEN JAWS;So;0;ON;;;;;N;;;;; +1CC4D;ALIEN MONSTER CLOSED JAWS;So;0;ON;;;;;N;;;;; +1CC4E;ALIEN SQUID OPEN TENTACLES;So;0;ON;;;;;N;;;;; +1CC4F;ALIEN SQUID CLOSED TENTACLES;So;0;ON;;;;;N;;;;; +1CC50;ALIEN CRAB STEPPING RIGHT;So;0;ON;;;;;N;;;;; +1CC51;ALIEN CRAB STEPPING LEFT;So;0;ON;;;;;N;;;;; +1CC52;ALIEN SPIDER CROUCHING;So;0;ON;;;;;N;;;;; +1CC53;ALIEN SPIDER SPREAD;So;0;ON;;;;;N;;;;; +1CC54;ALIEN MONSTER STEP-1;So;0;ON;;;;;N;;;;; +1CC55;ALIEN MONSTER STEP-2;So;0;ON;;;;;N;;;;; +1CC56;LEFT-POINTING ROCKET SHIP;So;0;ON;;;;;N;;;;; +1CC57;UP-POINTING ROCKET SHIP;So;0;ON;;;;;N;;;;; +1CC58;RIGHT-POINTING ROCKET SHIP;So;0;ON;;;;;N;;;;; +1CC59;DOWN-POINTING ROCKET SHIP;So;0;ON;;;;;N;;;;; +1CC5A;TOP HALF LEFT-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC5B;TOP HALF FORWARD-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC5C;TOP HALF RIGHT-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC5D;BOTTOM HALF LEFT-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC5E;BOTTOM HALF FORWARD-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC5F;BOTTOM HALF RIGHT-FACING ROBOT;So;0;ON;;;;;N;;;;; +1CC60;LEFT-POINTING ATOMIC BOMB;So;0;ON;;;;;N;;;;; +1CC61;UP-POINTING ATOMIC BOMB;So;0;ON;;;;;N;;;;; +1CC62;RIGHT-POINTING ATOMIC BOMB;So;0;ON;;;;;N;;;;; +1CC63;DOWN-POINTING ATOMIC BOMB;So;0;ON;;;;;N;;;;; +1CC64;MUSHROOM CLOUD;So;0;ON;;;;;N;;;;; +1CC65;LEFT-POINTING RIFLE;So;0;ON;;;;;N;;;;; +1CC66;UP-POINTING RIFLE;So;0;ON;;;;;N;;;;; +1CC67;RIGHT-POINTING RIFLE;So;0;ON;;;;;N;;;;; +1CC68;DOWN-POINTING RIFLE;So;0;ON;;;;;N;;;;; +1CC69;EIGHT RAYS INWARD;So;0;ON;;;;;N;;;;; +1CC6A;EIGHT RAYS OUTWARD;So;0;ON;;;;;N;;;;; +1CC6B;BLACK LARGE CIRCLE MINUS LEFT QUARTER SECTION;So;0;ON;;;;;N;;;;; +1CC6C;BLACK LARGE CIRCLE MINUS UPPER QUARTER SECTION;So;0;ON;;;;;N;;;;; +1CC6D;BLACK LARGE CIRCLE MINUS RIGHT QUARTER SECTION;So;0;ON;;;;;N;;;;; +1CC6E;BLACK LARGE CIRCLE MINUS LOWER QUARTER SECTION;So;0;ON;;;;;N;;;;; +1CC6F;BLACK NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1CC70;LEFT-FACING SNAKE HEAD WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC71;UP-FACING SNAKE HEAD WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC72;RIGHT-FACING SNAKE HEAD WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC73;DOWN-FACING SNAKE HEAD WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC74;LEFT-FACING SNAKE HEAD WITH CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1CC75;UP-FACING SNAKE HEAD WITH CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1CC76;RIGHT-FACING SNAKE HEAD WITH CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1CC77;DOWN-FACING SNAKE HEAD WITH CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1CC78;LEFT-POINTING ENERGY WAVE;So;0;ON;;;;;N;;;;; +1CC79;UP-POINTING ENERGY WAVE;So;0;ON;;;;;N;;;;; +1CC7A;RIGHT-POINTING ENERGY WAVE;So;0;ON;;;;;N;;;;; +1CC7B;DOWN-POINTING ENERGY WAVE;So;0;ON;;;;;N;;;;; +1CC7C;SQUARE SPIRAL FROM TOP LEFT;So;0;ON;;;;;N;;;;; +1CC7D;SQUARE SPIRAL FROM TOP RIGHT;So;0;ON;;;;;N;;;;; +1CC7E;SQUARE SPIRAL FROM BOTTOM RIGHT;So;0;ON;;;;;N;;;;; +1CC7F;SQUARE SPIRAL FROM BOTTOM LEFT;So;0;ON;;;;;N;;;;; +1CC80;STRIPED LEFT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +1CC81;STRIPED UP-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +1CC82;STRIPED RIGHT-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +1CC83;STRIPED DOWN-POINTING TRIANGLE;So;0;ON;;;;;N;;;;; +1CC84;VERTICAL LADDER;So;0;ON;;;;;N;;;;; +1CC85;HORIZONTAL LADDER;So;0;ON;;;;;N;;;;; +1CC86;WHITE LOWER LEFT POINTER;So;0;ON;;;;;N;;;;; +1CC87;WHITE LOWER RIGHT POINTER;So;0;ON;;;;;N;;;;; +1CC88;TWO RINGS ALIGNED HORIZONTALLY;So;0;ON;;;;;N;;;;; +1CC89;SQUARE FOUR CORNER SALTIRES;So;0;ON;;;;;N;;;;; +1CC8A;SQUARE FOUR CORNER DIAGONALS;So;0;ON;;;;;N;;;;; +1CC8B;SQUARE FOUR CORNER BLACK TRIANGLES;So;0;ON;;;;;N;;;;; +1CC8C;SQUARE APERTURE;So;0;ON;;;;;N;;;;; +1CC8D;INVERSE BLACK DIAMOND;So;0;ON;;;;;N;;;;; +1CC8E;LEFT AND UPPER ONE EIGHTH BLOCK CONTAINING BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +1CC8F;INVERSE BLACK SMALL SQUARE;So;0;ON;;;;;N;;;;; +1CC90;VERTICAL LINE WITH FOUR TICK MARKS;So;0;ON;;;;;N;;;;; +1CC91;HORIZONTAL LINE WITH FOUR TICK MARKS;So;0;ON;;;;;N;;;;; +1CC92;LEFT-FACING FISH;So;0;ON;;;;;N;;;;; +1CC93;RIGHT-FACING FISH;So;0;ON;;;;;N;;;;; +1CC94;LEFT-FACING FISH WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC95;RIGHT-FACING FISH WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CC96;FLAPPING BIRD;So;0;ON;;;;;N;;;;; +1CC97;LEFT-POINTING RACING CAR;So;0;ON;;;;;N;;;;; +1CC98;UP-POINTING RACING CAR;So;0;ON;;;;;N;;;;; +1CC99;RIGHT-POINTING RACING CAR;So;0;ON;;;;;N;;;;; +1CC9A;DOWN-POINTING RACING CAR;So;0;ON;;;;;N;;;;; +1CC9B;HORIZONTAL RACING CAR;So;0;ON;;;;;N;;;;; +1CC9C;VERTICAL RACING CAR;So;0;ON;;;;;N;;;;; +1CC9D;VERTICAL GO-KART;So;0;ON;;;;;N;;;;; +1CC9E;LEFT-POINTING TANK;So;0;ON;;;;;N;;;;; +1CC9F;RIGHT-POINTING TANK;So;0;ON;;;;;N;;;;; +1CCA0;LEFT-POINTING ROCKET BOOSTER;So;0;ON;;;;;N;;;;; +1CCA1;RIGHT-POINTING ROCKET BOOSTER;So;0;ON;;;;;N;;;;; +1CCA2;LEFT-POINTING ROLLER COASTER CAR;So;0;ON;;;;;N;;;;; +1CCA3;RIGHT-POINTING ROLLER COASTER CAR;So;0;ON;;;;;N;;;;; +1CCA4;LEFT HALF FLYING SAUCER;So;0;ON;;;;;N;;;;; +1CCA5;RIGHT HALF FLYING SAUCER;So;0;ON;;;;;N;;;;; +1CCA6;UPPER LEFT QUADRANT FACE WITH OPEN EYES;So;0;ON;;;;;N;;;;; +1CCA7;UPPER RIGHT QUADRANT FACE WITH OPEN EYES;So;0;ON;;;;;N;;;;; +1CCA8;UPPER LEFT QUADRANT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1CCA9;UPPER RIGHT QUADRANT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1CCAA;LOWER LEFT QUADRANT SMILING FACE;So;0;ON;;;;;N;;;;; +1CCAB;LOWER RIGHT QUADRANT SMILING FACE;So;0;ON;;;;;N;;;;; +1CCAC;LOWER LEFT QUADRANT NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1CCAD;LOWER RIGHT QUADRANT NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1CCAE;LOWER LEFT QUADRANT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CCAF;LOWER RIGHT QUADRANT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1CCB0;LOWER LEFT QUADRANT FROWNING FACE;So;0;ON;;;;;N;;;;; +1CCB1;LOWER RIGHT QUADRANT FROWNING FACE;So;0;ON;;;;;N;;;;; +1CCB2;UPPER LEFT QUADRANT TELEVISION;So;0;ON;;;;;N;;;;; +1CCB3;UPPER RIGHT QUADRANT TELEVISION;So;0;ON;;;;;N;;;;; +1CCB4;LOWER LEFT QUADRANT TELEVISION;So;0;ON;;;;;N;;;;; +1CCB5;LOWER RIGHT QUADRANT TELEVISION;So;0;ON;;;;;N;;;;; +1CCB6;UPPER LEFT QUADRANT MICROCOMPUTER;So;0;ON;;;;;N;;;;; +1CCB7;UPPER RIGHT QUADRANT MICROCOMPUTER;So;0;ON;;;;;N;;;;; +1CCB8;LOWER LEFT QUADRANT MICROCOMPUTER;So;0;ON;;;;;N;;;;; +1CCB9;LOWER RIGHT QUADRANT MICROCOMPUTER;So;0;ON;;;;;N;;;;; +1CCBA;UPPER LEFT QUADRANT CHESS KING;So;0;ON;;;;;N;;;;; +1CCBB;UPPER RIGHT QUADRANT CHESS KING;So;0;ON;;;;;N;;;;; +1CCBC;LOWER LEFT QUADRANT CHESS KING;So;0;ON;;;;;N;;;;; +1CCBD;LOWER RIGHT QUADRANT CHESS KING;So;0;ON;;;;;N;;;;; +1CCBE;UPPER LEFT QUADRANT CHESS QUEEN;So;0;ON;;;;;N;;;;; +1CCBF;UPPER RIGHT QUADRANT CHESS QUEEN;So;0;ON;;;;;N;;;;; +1CCC0;LOWER LEFT QUADRANT CHESS QUEEN;So;0;ON;;;;;N;;;;; +1CCC1;LOWER RIGHT QUADRANT CHESS QUEEN;So;0;ON;;;;;N;;;;; +1CCC2;UPPER LEFT QUADRANT CHESS ROOK;So;0;ON;;;;;N;;;;; +1CCC3;UPPER RIGHT QUADRANT CHESS ROOK;So;0;ON;;;;;N;;;;; +1CCC4;LOWER LEFT QUADRANT CHESS ROOK;So;0;ON;;;;;N;;;;; +1CCC5;LOWER RIGHT QUADRANT CHESS ROOK;So;0;ON;;;;;N;;;;; +1CCC6;UPPER LEFT QUADRANT CHESS BISHOP;So;0;ON;;;;;N;;;;; +1CCC7;UPPER RIGHT QUADRANT CHESS BISHOP;So;0;ON;;;;;N;;;;; +1CCC8;LOWER LEFT QUADRANT CHESS BISHOP;So;0;ON;;;;;N;;;;; +1CCC9;LOWER RIGHT QUADRANT CHESS BISHOP;So;0;ON;;;;;N;;;;; +1CCCA;UPPER LEFT QUADRANT CHESS KNIGHT;So;0;ON;;;;;N;;;;; +1CCCB;UPPER RIGHT QUADRANT CHESS KNIGHT;So;0;ON;;;;;N;;;;; +1CCCC;LOWER LEFT QUADRANT CHESS KNIGHT;So;0;ON;;;;;N;;;;; +1CCCD;LOWER RIGHT QUADRANT CHESS KNIGHT;So;0;ON;;;;;N;;;;; +1CCCE;UPPER LEFT QUADRANT CHESS PAWN;So;0;ON;;;;;N;;;;; +1CCCF;UPPER RIGHT QUADRANT CHESS PAWN;So;0;ON;;;;;N;;;;; +1CCD0;LOWER LEFT QUADRANT CHESS PAWN;So;0;ON;;;;;N;;;;; +1CCD1;LOWER RIGHT QUADRANT CHESS PAWN;So;0;ON;;;;;N;;;;; +1CCD2;UPPER LEFT QUADRANT STANDING KNIGHT;So;0;ON;;;;;N;;;;; +1CCD3;UPPER RIGHT QUADRANT STANDING KNIGHT;So;0;ON;;;;;N;;;;; +1CCD4;LOWER LEFT QUADRANT STANDING KNIGHT;So;0;ON;;;;;N;;;;; +1CCD5;LOWER RIGHT QUADRANT STANDING KNIGHT;So;0;ON;;;;;N;;;;; +1CCD6;OUTLINED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;; +1CCD7;OUTLINED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;; +1CCD8;OUTLINED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; +1CCD9;OUTLINED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;; +1CCDA;OUTLINED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;; +1CCDB;OUTLINED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;; +1CCDC;OUTLINED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;; +1CCDD;OUTLINED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;; +1CCDE;OUTLINED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;; +1CCDF;OUTLINED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;; +1CCE0;OUTLINED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;; +1CCE1;OUTLINED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;; +1CCE2;OUTLINED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;; +1CCE3;OUTLINED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;; +1CCE4;OUTLINED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;; +1CCE5;OUTLINED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;; +1CCE6;OUTLINED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;; +1CCE7;OUTLINED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; +1CCE8;OUTLINED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;; +1CCE9;OUTLINED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;; +1CCEA;OUTLINED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;; +1CCEB;OUTLINED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;; +1CCEC;OUTLINED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;; +1CCED;OUTLINED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;; +1CCEE;OUTLINED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;; +1CCEF;OUTLINED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;; +1CCF0;OUTLINED DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1CCF1;OUTLINED DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1CCF2;OUTLINED DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1CCF3;OUTLINED DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1CCF4;OUTLINED DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1CCF5;OUTLINED DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1CCF6;OUTLINED DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1CCF7;OUTLINED DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1CCF8;OUTLINED DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1CCF9;OUTLINED DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1CCFA;SNAKE SYMBOL;So;0;ON;;;;;N;;;;; +1CCFB;FLYING SAUCER SYMBOL;So;0;ON;;;;;N;;;;; +1CCFC;NOSE SYMBOL;So;0;ON;;;;;N;;;;; +1CD00;BLOCK OCTANT-3;So;0;ON;;;;;N;;;;; +1CD01;BLOCK OCTANT-23;So;0;ON;;;;;N;;;;; +1CD02;BLOCK OCTANT-123;So;0;ON;;;;;N;;;;; +1CD03;BLOCK OCTANT-4;So;0;ON;;;;;N;;;;; +1CD04;BLOCK OCTANT-14;So;0;ON;;;;;N;;;;; +1CD05;BLOCK OCTANT-124;So;0;ON;;;;;N;;;;; +1CD06;BLOCK OCTANT-34;So;0;ON;;;;;N;;;;; +1CD07;BLOCK OCTANT-134;So;0;ON;;;;;N;;;;; +1CD08;BLOCK OCTANT-234;So;0;ON;;;;;N;;;;; +1CD09;BLOCK OCTANT-5;So;0;ON;;;;;N;;;;; +1CD0A;BLOCK OCTANT-15;So;0;ON;;;;;N;;;;; +1CD0B;BLOCK OCTANT-25;So;0;ON;;;;;N;;;;; +1CD0C;BLOCK OCTANT-125;So;0;ON;;;;;N;;;;; +1CD0D;BLOCK OCTANT-135;So;0;ON;;;;;N;;;;; +1CD0E;BLOCK OCTANT-235;So;0;ON;;;;;N;;;;; +1CD0F;BLOCK OCTANT-1235;So;0;ON;;;;;N;;;;; +1CD10;BLOCK OCTANT-45;So;0;ON;;;;;N;;;;; +1CD11;BLOCK OCTANT-145;So;0;ON;;;;;N;;;;; +1CD12;BLOCK OCTANT-245;So;0;ON;;;;;N;;;;; +1CD13;BLOCK OCTANT-1245;So;0;ON;;;;;N;;;;; +1CD14;BLOCK OCTANT-345;So;0;ON;;;;;N;;;;; +1CD15;BLOCK OCTANT-1345;So;0;ON;;;;;N;;;;; +1CD16;BLOCK OCTANT-2345;So;0;ON;;;;;N;;;;; +1CD17;BLOCK OCTANT-12345;So;0;ON;;;;;N;;;;; +1CD18;BLOCK OCTANT-6;So;0;ON;;;;;N;;;;; +1CD19;BLOCK OCTANT-16;So;0;ON;;;;;N;;;;; +1CD1A;BLOCK OCTANT-26;So;0;ON;;;;;N;;;;; +1CD1B;BLOCK OCTANT-126;So;0;ON;;;;;N;;;;; +1CD1C;BLOCK OCTANT-36;So;0;ON;;;;;N;;;;; +1CD1D;BLOCK OCTANT-136;So;0;ON;;;;;N;;;;; +1CD1E;BLOCK OCTANT-236;So;0;ON;;;;;N;;;;; +1CD1F;BLOCK OCTANT-1236;So;0;ON;;;;;N;;;;; +1CD20;BLOCK OCTANT-146;So;0;ON;;;;;N;;;;; +1CD21;BLOCK OCTANT-246;So;0;ON;;;;;N;;;;; +1CD22;BLOCK OCTANT-1246;So;0;ON;;;;;N;;;;; +1CD23;BLOCK OCTANT-346;So;0;ON;;;;;N;;;;; +1CD24;BLOCK OCTANT-1346;So;0;ON;;;;;N;;;;; +1CD25;BLOCK OCTANT-2346;So;0;ON;;;;;N;;;;; +1CD26;BLOCK OCTANT-12346;So;0;ON;;;;;N;;;;; +1CD27;BLOCK OCTANT-56;So;0;ON;;;;;N;;;;; +1CD28;BLOCK OCTANT-156;So;0;ON;;;;;N;;;;; +1CD29;BLOCK OCTANT-256;So;0;ON;;;;;N;;;;; +1CD2A;BLOCK OCTANT-1256;So;0;ON;;;;;N;;;;; +1CD2B;BLOCK OCTANT-356;So;0;ON;;;;;N;;;;; +1CD2C;BLOCK OCTANT-1356;So;0;ON;;;;;N;;;;; +1CD2D;BLOCK OCTANT-2356;So;0;ON;;;;;N;;;;; +1CD2E;BLOCK OCTANT-12356;So;0;ON;;;;;N;;;;; +1CD2F;BLOCK OCTANT-456;So;0;ON;;;;;N;;;;; +1CD30;BLOCK OCTANT-1456;So;0;ON;;;;;N;;;;; +1CD31;BLOCK OCTANT-2456;So;0;ON;;;;;N;;;;; +1CD32;BLOCK OCTANT-12456;So;0;ON;;;;;N;;;;; +1CD33;BLOCK OCTANT-3456;So;0;ON;;;;;N;;;;; +1CD34;BLOCK OCTANT-13456;So;0;ON;;;;;N;;;;; +1CD35;BLOCK OCTANT-23456;So;0;ON;;;;;N;;;;; +1CD36;BLOCK OCTANT-17;So;0;ON;;;;;N;;;;; +1CD37;BLOCK OCTANT-27;So;0;ON;;;;;N;;;;; +1CD38;BLOCK OCTANT-127;So;0;ON;;;;;N;;;;; +1CD39;BLOCK OCTANT-37;So;0;ON;;;;;N;;;;; +1CD3A;BLOCK OCTANT-137;So;0;ON;;;;;N;;;;; +1CD3B;BLOCK OCTANT-237;So;0;ON;;;;;N;;;;; +1CD3C;BLOCK OCTANT-1237;So;0;ON;;;;;N;;;;; +1CD3D;BLOCK OCTANT-47;So;0;ON;;;;;N;;;;; +1CD3E;BLOCK OCTANT-147;So;0;ON;;;;;N;;;;; +1CD3F;BLOCK OCTANT-247;So;0;ON;;;;;N;;;;; +1CD40;BLOCK OCTANT-1247;So;0;ON;;;;;N;;;;; +1CD41;BLOCK OCTANT-347;So;0;ON;;;;;N;;;;; +1CD42;BLOCK OCTANT-1347;So;0;ON;;;;;N;;;;; +1CD43;BLOCK OCTANT-2347;So;0;ON;;;;;N;;;;; +1CD44;BLOCK OCTANT-12347;So;0;ON;;;;;N;;;;; +1CD45;BLOCK OCTANT-157;So;0;ON;;;;;N;;;;; +1CD46;BLOCK OCTANT-257;So;0;ON;;;;;N;;;;; +1CD47;BLOCK OCTANT-1257;So;0;ON;;;;;N;;;;; +1CD48;BLOCK OCTANT-357;So;0;ON;;;;;N;;;;; +1CD49;BLOCK OCTANT-2357;So;0;ON;;;;;N;;;;; +1CD4A;BLOCK OCTANT-12357;So;0;ON;;;;;N;;;;; +1CD4B;BLOCK OCTANT-457;So;0;ON;;;;;N;;;;; +1CD4C;BLOCK OCTANT-1457;So;0;ON;;;;;N;;;;; +1CD4D;BLOCK OCTANT-12457;So;0;ON;;;;;N;;;;; +1CD4E;BLOCK OCTANT-3457;So;0;ON;;;;;N;;;;; +1CD4F;BLOCK OCTANT-13457;So;0;ON;;;;;N;;;;; +1CD50;BLOCK OCTANT-23457;So;0;ON;;;;;N;;;;; +1CD51;BLOCK OCTANT-67;So;0;ON;;;;;N;;;;; +1CD52;BLOCK OCTANT-167;So;0;ON;;;;;N;;;;; +1CD53;BLOCK OCTANT-267;So;0;ON;;;;;N;;;;; +1CD54;BLOCK OCTANT-1267;So;0;ON;;;;;N;;;;; +1CD55;BLOCK OCTANT-367;So;0;ON;;;;;N;;;;; +1CD56;BLOCK OCTANT-1367;So;0;ON;;;;;N;;;;; +1CD57;BLOCK OCTANT-2367;So;0;ON;;;;;N;;;;; +1CD58;BLOCK OCTANT-12367;So;0;ON;;;;;N;;;;; +1CD59;BLOCK OCTANT-467;So;0;ON;;;;;N;;;;; +1CD5A;BLOCK OCTANT-1467;So;0;ON;;;;;N;;;;; +1CD5B;BLOCK OCTANT-2467;So;0;ON;;;;;N;;;;; +1CD5C;BLOCK OCTANT-12467;So;0;ON;;;;;N;;;;; +1CD5D;BLOCK OCTANT-3467;So;0;ON;;;;;N;;;;; +1CD5E;BLOCK OCTANT-13467;So;0;ON;;;;;N;;;;; +1CD5F;BLOCK OCTANT-23467;So;0;ON;;;;;N;;;;; +1CD60;BLOCK OCTANT-123467;So;0;ON;;;;;N;;;;; +1CD61;BLOCK OCTANT-567;So;0;ON;;;;;N;;;;; +1CD62;BLOCK OCTANT-1567;So;0;ON;;;;;N;;;;; +1CD63;BLOCK OCTANT-2567;So;0;ON;;;;;N;;;;; +1CD64;BLOCK OCTANT-12567;So;0;ON;;;;;N;;;;; +1CD65;BLOCK OCTANT-3567;So;0;ON;;;;;N;;;;; +1CD66;BLOCK OCTANT-13567;So;0;ON;;;;;N;;;;; +1CD67;BLOCK OCTANT-23567;So;0;ON;;;;;N;;;;; +1CD68;BLOCK OCTANT-123567;So;0;ON;;;;;N;;;;; +1CD69;BLOCK OCTANT-4567;So;0;ON;;;;;N;;;;; +1CD6A;BLOCK OCTANT-14567;So;0;ON;;;;;N;;;;; +1CD6B;BLOCK OCTANT-24567;So;0;ON;;;;;N;;;;; +1CD6C;BLOCK OCTANT-124567;So;0;ON;;;;;N;;;;; +1CD6D;BLOCK OCTANT-34567;So;0;ON;;;;;N;;;;; +1CD6E;BLOCK OCTANT-134567;So;0;ON;;;;;N;;;;; +1CD6F;BLOCK OCTANT-234567;So;0;ON;;;;;N;;;;; +1CD70;BLOCK OCTANT-1234567;So;0;ON;;;;;N;;;;; +1CD71;BLOCK OCTANT-18;So;0;ON;;;;;N;;;;; +1CD72;BLOCK OCTANT-28;So;0;ON;;;;;N;;;;; +1CD73;BLOCK OCTANT-128;So;0;ON;;;;;N;;;;; +1CD74;BLOCK OCTANT-38;So;0;ON;;;;;N;;;;; +1CD75;BLOCK OCTANT-138;So;0;ON;;;;;N;;;;; +1CD76;BLOCK OCTANT-238;So;0;ON;;;;;N;;;;; +1CD77;BLOCK OCTANT-1238;So;0;ON;;;;;N;;;;; +1CD78;BLOCK OCTANT-48;So;0;ON;;;;;N;;;;; +1CD79;BLOCK OCTANT-148;So;0;ON;;;;;N;;;;; +1CD7A;BLOCK OCTANT-248;So;0;ON;;;;;N;;;;; +1CD7B;BLOCK OCTANT-1248;So;0;ON;;;;;N;;;;; +1CD7C;BLOCK OCTANT-348;So;0;ON;;;;;N;;;;; +1CD7D;BLOCK OCTANT-1348;So;0;ON;;;;;N;;;;; +1CD7E;BLOCK OCTANT-2348;So;0;ON;;;;;N;;;;; +1CD7F;BLOCK OCTANT-12348;So;0;ON;;;;;N;;;;; +1CD80;BLOCK OCTANT-58;So;0;ON;;;;;N;;;;; +1CD81;BLOCK OCTANT-158;So;0;ON;;;;;N;;;;; +1CD82;BLOCK OCTANT-258;So;0;ON;;;;;N;;;;; +1CD83;BLOCK OCTANT-1258;So;0;ON;;;;;N;;;;; +1CD84;BLOCK OCTANT-358;So;0;ON;;;;;N;;;;; +1CD85;BLOCK OCTANT-1358;So;0;ON;;;;;N;;;;; +1CD86;BLOCK OCTANT-2358;So;0;ON;;;;;N;;;;; +1CD87;BLOCK OCTANT-12358;So;0;ON;;;;;N;;;;; +1CD88;BLOCK OCTANT-458;So;0;ON;;;;;N;;;;; +1CD89;BLOCK OCTANT-1458;So;0;ON;;;;;N;;;;; +1CD8A;BLOCK OCTANT-2458;So;0;ON;;;;;N;;;;; +1CD8B;BLOCK OCTANT-12458;So;0;ON;;;;;N;;;;; +1CD8C;BLOCK OCTANT-3458;So;0;ON;;;;;N;;;;; +1CD8D;BLOCK OCTANT-13458;So;0;ON;;;;;N;;;;; +1CD8E;BLOCK OCTANT-23458;So;0;ON;;;;;N;;;;; +1CD8F;BLOCK OCTANT-123458;So;0;ON;;;;;N;;;;; +1CD90;BLOCK OCTANT-168;So;0;ON;;;;;N;;;;; +1CD91;BLOCK OCTANT-268;So;0;ON;;;;;N;;;;; +1CD92;BLOCK OCTANT-1268;So;0;ON;;;;;N;;;;; +1CD93;BLOCK OCTANT-368;So;0;ON;;;;;N;;;;; +1CD94;BLOCK OCTANT-2368;So;0;ON;;;;;N;;;;; +1CD95;BLOCK OCTANT-12368;So;0;ON;;;;;N;;;;; +1CD96;BLOCK OCTANT-468;So;0;ON;;;;;N;;;;; +1CD97;BLOCK OCTANT-1468;So;0;ON;;;;;N;;;;; +1CD98;BLOCK OCTANT-12468;So;0;ON;;;;;N;;;;; +1CD99;BLOCK OCTANT-3468;So;0;ON;;;;;N;;;;; +1CD9A;BLOCK OCTANT-13468;So;0;ON;;;;;N;;;;; +1CD9B;BLOCK OCTANT-23468;So;0;ON;;;;;N;;;;; +1CD9C;BLOCK OCTANT-568;So;0;ON;;;;;N;;;;; +1CD9D;BLOCK OCTANT-1568;So;0;ON;;;;;N;;;;; +1CD9E;BLOCK OCTANT-2568;So;0;ON;;;;;N;;;;; +1CD9F;BLOCK OCTANT-12568;So;0;ON;;;;;N;;;;; +1CDA0;BLOCK OCTANT-3568;So;0;ON;;;;;N;;;;; +1CDA1;BLOCK OCTANT-13568;So;0;ON;;;;;N;;;;; +1CDA2;BLOCK OCTANT-23568;So;0;ON;;;;;N;;;;; +1CDA3;BLOCK OCTANT-123568;So;0;ON;;;;;N;;;;; +1CDA4;BLOCK OCTANT-4568;So;0;ON;;;;;N;;;;; +1CDA5;BLOCK OCTANT-14568;So;0;ON;;;;;N;;;;; +1CDA6;BLOCK OCTANT-24568;So;0;ON;;;;;N;;;;; +1CDA7;BLOCK OCTANT-124568;So;0;ON;;;;;N;;;;; +1CDA8;BLOCK OCTANT-34568;So;0;ON;;;;;N;;;;; +1CDA9;BLOCK OCTANT-134568;So;0;ON;;;;;N;;;;; +1CDAA;BLOCK OCTANT-234568;So;0;ON;;;;;N;;;;; +1CDAB;BLOCK OCTANT-1234568;So;0;ON;;;;;N;;;;; +1CDAC;BLOCK OCTANT-178;So;0;ON;;;;;N;;;;; +1CDAD;BLOCK OCTANT-278;So;0;ON;;;;;N;;;;; +1CDAE;BLOCK OCTANT-1278;So;0;ON;;;;;N;;;;; +1CDAF;BLOCK OCTANT-378;So;0;ON;;;;;N;;;;; +1CDB0;BLOCK OCTANT-1378;So;0;ON;;;;;N;;;;; +1CDB1;BLOCK OCTANT-2378;So;0;ON;;;;;N;;;;; +1CDB2;BLOCK OCTANT-12378;So;0;ON;;;;;N;;;;; +1CDB3;BLOCK OCTANT-478;So;0;ON;;;;;N;;;;; +1CDB4;BLOCK OCTANT-1478;So;0;ON;;;;;N;;;;; +1CDB5;BLOCK OCTANT-2478;So;0;ON;;;;;N;;;;; +1CDB6;BLOCK OCTANT-12478;So;0;ON;;;;;N;;;;; +1CDB7;BLOCK OCTANT-3478;So;0;ON;;;;;N;;;;; +1CDB8;BLOCK OCTANT-13478;So;0;ON;;;;;N;;;;; +1CDB9;BLOCK OCTANT-23478;So;0;ON;;;;;N;;;;; +1CDBA;BLOCK OCTANT-123478;So;0;ON;;;;;N;;;;; +1CDBB;BLOCK OCTANT-578;So;0;ON;;;;;N;;;;; +1CDBC;BLOCK OCTANT-1578;So;0;ON;;;;;N;;;;; +1CDBD;BLOCK OCTANT-2578;So;0;ON;;;;;N;;;;; +1CDBE;BLOCK OCTANT-12578;So;0;ON;;;;;N;;;;; +1CDBF;BLOCK OCTANT-3578;So;0;ON;;;;;N;;;;; +1CDC0;BLOCK OCTANT-13578;So;0;ON;;;;;N;;;;; +1CDC1;BLOCK OCTANT-23578;So;0;ON;;;;;N;;;;; +1CDC2;BLOCK OCTANT-123578;So;0;ON;;;;;N;;;;; +1CDC3;BLOCK OCTANT-4578;So;0;ON;;;;;N;;;;; +1CDC4;BLOCK OCTANT-14578;So;0;ON;;;;;N;;;;; +1CDC5;BLOCK OCTANT-24578;So;0;ON;;;;;N;;;;; +1CDC6;BLOCK OCTANT-124578;So;0;ON;;;;;N;;;;; +1CDC7;BLOCK OCTANT-34578;So;0;ON;;;;;N;;;;; +1CDC8;BLOCK OCTANT-134578;So;0;ON;;;;;N;;;;; +1CDC9;BLOCK OCTANT-234578;So;0;ON;;;;;N;;;;; +1CDCA;BLOCK OCTANT-1234578;So;0;ON;;;;;N;;;;; +1CDCB;BLOCK OCTANT-678;So;0;ON;;;;;N;;;;; +1CDCC;BLOCK OCTANT-1678;So;0;ON;;;;;N;;;;; +1CDCD;BLOCK OCTANT-2678;So;0;ON;;;;;N;;;;; +1CDCE;BLOCK OCTANT-12678;So;0;ON;;;;;N;;;;; +1CDCF;BLOCK OCTANT-3678;So;0;ON;;;;;N;;;;; +1CDD0;BLOCK OCTANT-13678;So;0;ON;;;;;N;;;;; +1CDD1;BLOCK OCTANT-23678;So;0;ON;;;;;N;;;;; +1CDD2;BLOCK OCTANT-123678;So;0;ON;;;;;N;;;;; +1CDD3;BLOCK OCTANT-4678;So;0;ON;;;;;N;;;;; +1CDD4;BLOCK OCTANT-14678;So;0;ON;;;;;N;;;;; +1CDD5;BLOCK OCTANT-24678;So;0;ON;;;;;N;;;;; +1CDD6;BLOCK OCTANT-124678;So;0;ON;;;;;N;;;;; +1CDD7;BLOCK OCTANT-34678;So;0;ON;;;;;N;;;;; +1CDD8;BLOCK OCTANT-134678;So;0;ON;;;;;N;;;;; +1CDD9;BLOCK OCTANT-234678;So;0;ON;;;;;N;;;;; +1CDDA;BLOCK OCTANT-1234678;So;0;ON;;;;;N;;;;; +1CDDB;BLOCK OCTANT-15678;So;0;ON;;;;;N;;;;; +1CDDC;BLOCK OCTANT-25678;So;0;ON;;;;;N;;;;; +1CDDD;BLOCK OCTANT-125678;So;0;ON;;;;;N;;;;; +1CDDE;BLOCK OCTANT-35678;So;0;ON;;;;;N;;;;; +1CDDF;BLOCK OCTANT-235678;So;0;ON;;;;;N;;;;; +1CDE0;BLOCK OCTANT-1235678;So;0;ON;;;;;N;;;;; +1CDE1;BLOCK OCTANT-45678;So;0;ON;;;;;N;;;;; +1CDE2;BLOCK OCTANT-145678;So;0;ON;;;;;N;;;;; +1CDE3;BLOCK OCTANT-1245678;So;0;ON;;;;;N;;;;; +1CDE4;BLOCK OCTANT-1345678;So;0;ON;;;;;N;;;;; +1CDE5;BLOCK OCTANT-2345678;So;0;ON;;;;;N;;;;; +1CDE6;TOP HALF STANDING PERSON;So;0;ON;;;;;N;;;;; +1CDE7;BOTTOM HALF STANDING PERSON;So;0;ON;;;;;N;;;;; +1CDE8;TOP HALF RIGHT-FACING RUNNER FRAME-1;So;0;ON;;;;;N;;;;; +1CDE9;BOTTOM HALF RIGHT-FACING RUNNER FRAME-1;So;0;ON;;;;;N;;;;; +1CDEA;TOP HALF RIGHT-FACING RUNNER FRAME-2;So;0;ON;;;;;N;;;;; +1CDEB;BOTTOM HALF RIGHT-FACING RUNNER FRAME-2;So;0;ON;;;;;N;;;;; +1CDEC;TOP HALF LEFT-FACING RUNNER FRAME-1;So;0;ON;;;;;N;;;;; +1CDED;BOTTOM HALF LEFT-FACING RUNNER FRAME-1;So;0;ON;;;;;N;;;;; +1CDEE;TOP HALF LEFT-FACING RUNNER FRAME-2;So;0;ON;;;;;N;;;;; +1CDEF;BOTTOM HALF LEFT-FACING RUNNER FRAME-2;So;0;ON;;;;;N;;;;; +1CDF0;TOP HALF FORWARD-FACING RUNNER;So;0;ON;;;;;N;;;;; +1CDF1;BOTTOM HALF FORWARD-FACING RUNNER FRAME-1;So;0;ON;;;;;N;;;;; +1CDF2;BOTTOM HALF FORWARD-FACING RUNNER FRAME-2;So;0;ON;;;;;N;;;;; +1CDF3;BOTTOM HALF FORWARD-FACING RUNNER FRAME-3;So;0;ON;;;;;N;;;;; +1CDF4;BOTTOM HALF FORWARD-FACING RUNNER FRAME-4;So;0;ON;;;;;N;;;;; +1CDF5;MOON LANDER;So;0;ON;;;;;N;;;;; +1CDF6;TOP HALF FLAILING ROBOT FRAME-1;So;0;ON;;;;;N;;;;; +1CDF7;TOP HALF FLAILING ROBOT FRAME-2;So;0;ON;;;;;N;;;;; +1CDF8;DOWN-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1CDF9;LEFT-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1CDFA;SMALL UP-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1CDFB;UP-POINTING FROG;So;0;ON;;;;;N;;;;; +1CDFC;DOWN-POINTING FROG;So;0;ON;;;;;N;;;;; +1CDFD;EXPLOSION FRAME-1;So;0;ON;;;;;N;;;;; +1CDFE;EXPLOSION FRAME-2;So;0;ON;;;;;N;;;;; +1CDFF;EXPLOSION FRAME-3;So;0;ON;;;;;N;;;;; +1CE00;RIGHT HALF AND LEFT HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1CE01;LOWER HALF AND UPPER HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1CE02;EXPLOSION AT HORIZON;So;0;ON;;;;;N;;;;; +1CE03;UPPER HALF HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1CE04;LOWER HALF HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1CE05;HEAVY WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +1CE06;WHITE VERTICAL RECTANGLE WITH HORIZONTAL BAR;So;0;ON;;;;;N;;;;; +1CE07;TOP LEFT BLACK LEFT-POINTING SMALL TRIANGLE;So;0;ON;;;;;N;;;;; +1CE08;FUNNEL;So;0;ON;;;;;N;;;;; +1CE09;BOX DRAWINGS DOUBLE DIAGONAL LOWER LEFT TO MIDDLE CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1CE0A;BOX DRAWINGS DOUBLE DIAGONAL UPPER LEFT TO MIDDLE CENTRE TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1CE0B;LEFT HALF WHITE ELLIPSE;So;0;ON;;;;;N;;;;; +1CE0C;RIGHT HALF WHITE ELLIPSE;So;0;ON;;;;;N;;;;; +1CE0D;LEFT HALF TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;;;;; +1CE0E;RIGHT HALF TRIPLE DASH HORIZONTAL;So;0;ON;;;;;N;;;;; +1CE0F;HORIZONTAL LINE WITH TICK MARK;So;0;ON;;;;;N;;;;; +1CE10;LEFT HALF HORIZONTAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE11;RIGHT HALF HORIZONTAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE12;HORIZONTAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE13;LOWER HALF VERTICAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE14;UPPER HALF VERTICAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE15;VERTICAL LINE WITH THREE TICK MARKS;So;0;ON;;;;;N;;;;; +1CE16;BOX DRAWINGS LIGHT VERTICAL AND TOP RIGHT;So;0;ON;;;;;N;;;;; +1CE17;BOX DRAWINGS LIGHT VERTICAL AND BOTTOM RIGHT;So;0;ON;;;;;N;;;;; +1CE18;BOX DRAWINGS LIGHT VERTICAL AND TOP LEFT;So;0;ON;;;;;N;;;;; +1CE19;BOX DRAWINGS LIGHT VERTICAL AND BOTTOM LEFT;So;0;ON;;;;;N;;;;; +1CE1A;LARGE TYPE PIECE UPPER LEFT ARC;So;0;ON;;;;;N;;;;; +1CE1B;LARGE TYPE PIECE UPPER LEFT CORNER;So;0;ON;;;;;N;;;;; +1CE1C;LARGE TYPE PIECE UPPER TERMINAL;So;0;ON;;;;;N;;;;; +1CE1D;LARGE TYPE PIECE UPPER LEFT CROTCH;So;0;ON;;;;;N;;;;; +1CE1E;LARGE TYPE PIECE LEFT ARM;So;0;ON;;;;;N;;;;; +1CE1F;LARGE TYPE PIECE CROSSBAR;So;0;ON;;;;;N;;;;; +1CE20;LARGE TYPE PIECE CROSSBAR WITH LOWER STEM;So;0;ON;;;;;N;;;;; +1CE21;LARGE TYPE PIECE UPPER HALF VERTEX OF M;So;0;ON;;;;;N;;;;; +1CE22;LARGE TYPE PIECE DIAGONAL LOWER LEFT;So;0;ON;;;;;N;;;;; +1CE23;LARGE TYPE PIECE SHORT UPPER TERMINAL;So;0;ON;;;;;N;;;;; +1CE24;LARGE TYPE PIECE UPPER RIGHT ARC;So;0;ON;;;;;N;;;;; +1CE25;LARGE TYPE PIECE RIGHT ARM;So;0;ON;;;;;N;;;;; +1CE26;LARGE TYPE PIECE UPPER RIGHT CROTCH;So;0;ON;;;;;N;;;;; +1CE27;LARGE TYPE PIECE UPPER RIGHT CORNER;So;0;ON;;;;;N;;;;; +1CE28;LARGE TYPE PIECE STEM WITH RIGHT CROSSBAR;So;0;ON;;;;;N;;;;; +1CE29;LARGE TYPE PIECE STEM;So;0;ON;;;;;N;;;;; +1CE2A;LARGE TYPE PIECE DIAGONAL UPPER RIGHT AND LOWER RIGHT;So;0;ON;;;;;N;;;;; +1CE2B;LARGE TYPE PIECE DIAGONAL UPPER RIGHT;So;0;ON;;;;;N;;;;; +1CE2C;LARGE TYPE PIECE DIAGONAL LOWER RIGHT;So;0;ON;;;;;N;;;;; +1CE2D;LARGE TYPE PIECE SHORT LOWER TERMINAL;So;0;ON;;;;;N;;;;; +1CE2E;LARGE TYPE PIECE LOWER LEFT AND UPPER LEFT ARC;So;0;ON;;;;;N;;;;; +1CE2F;LARGE TYPE PIECE CENTRE OF K;So;0;ON;;;;;N;;;;; +1CE30;LARGE TYPE PIECE LOWER HALF VERTEX OF M;So;0;ON;;;;;N;;;;; +1CE31;LARGE TYPE PIECE UPPER HALF VERTEX OF W;So;0;ON;;;;;N;;;;; +1CE32;LARGE TYPE PIECE CENTRE OF X;So;0;ON;;;;;N;;;;; +1CE33;LARGE TYPE PIECE CENTRE OF Y;So;0;ON;;;;;N;;;;; +1CE34;LARGE TYPE PIECE CENTRE OF Z WITH CROSSBAR;So;0;ON;;;;;N;;;;; +1CE35;LARGE TYPE PIECE RAISED UPPER LEFT ARC;So;0;ON;;;;;N;;;;; +1CE36;LARGE TYPE PIECE STEM WITH LEFT CROSSBAR;So;0;ON;;;;;N;;;;; +1CE37;LARGE TYPE PIECE LOWER RIGHT AND UPPER RIGHT ARC;So;0;ON;;;;;N;;;;; +1CE38;LARGE TYPE PIECE DIAGONAL UPPER LEFT AND LOWER LEFT;So;0;ON;;;;;N;;;;; +1CE39;LARGE TYPE PIECE STEM WITH LEFT JOINT;So;0;ON;;;;;N;;;;; +1CE3A;LARGE TYPE PIECE STEM WITH CROSSBAR;So;0;ON;;;;;N;;;;; +1CE3B;LARGE TYPE PIECE DIAGONAL UPPER LEFT;So;0;ON;;;;;N;;;;; +1CE3C;LARGE TYPE PIECE LOWER TERMINAL;So;0;ON;;;;;N;;;;; +1CE3D;LARGE TYPE PIECE LOWER LEFT CORNER;So;0;ON;;;;;N;;;;; +1CE3E;LARGE TYPE PIECE LOWER LEFT ARC;So;0;ON;;;;;N;;;;; +1CE3F;LARGE TYPE PIECE LOWER LEFT CROTCH;So;0;ON;;;;;N;;;;; +1CE40;LARGE TYPE PIECE CROSSBAR WITH UPPER STEM;So;0;ON;;;;;N;;;;; +1CE41;LARGE TYPE PIECE VERTEX OF V;So;0;ON;;;;;N;;;;; +1CE42;LARGE TYPE PIECE LOWER HALF VERTEX OF W;So;0;ON;;;;;N;;;;; +1CE43;LARGE TYPE PIECE LOWER RIGHT ARC;So;0;ON;;;;;N;;;;; +1CE44;LARGE TYPE PIECE LOWER RIGHT CORNER;So;0;ON;;;;;N;;;;; +1CE45;LARGE TYPE PIECE LOWER RIGHT ARC WITH TAIL;So;0;ON;;;;;N;;;;; +1CE46;LARGE TYPE PIECE LOWER RIGHT CROTCH;So;0;ON;;;;;N;;;;; +1CE47;LARGE TYPE PIECE STEM-45;So;0;ON;;;;;N;;;;; +1CE48;LARGE TYPE PIECE STEM-2345;So;0;ON;;;;;N;;;;; +1CE49;LARGE TYPE PIECE STEM-4;So;0;ON;;;;;N;;;;; +1CE4A;LARGE TYPE PIECE STEM-34;So;0;ON;;;;;N;;;;; +1CE4B;LARGE TYPE PIECE STEM-234;So;0;ON;;;;;N;;;;; +1CE4C;LARGE TYPE PIECE STEM-1234;So;0;ON;;;;;N;;;;; +1CE4D;LARGE TYPE PIECE STEM-3;So;0;ON;;;;;N;;;;; +1CE4E;LARGE TYPE PIECE STEM-23;So;0;ON;;;;;N;;;;; +1CE4F;LARGE TYPE PIECE STEM-2;So;0;ON;;;;;N;;;;; +1CE50;LARGE TYPE PIECE STEM-12;So;0;ON;;;;;N;;;;; +1CE51;SEPARATED BLOCK SEXTANT-1;So;0;ON;;;;;N;;;;; +1CE52;SEPARATED BLOCK SEXTANT-2;So;0;ON;;;;;N;;;;; +1CE53;SEPARATED BLOCK SEXTANT-12;So;0;ON;;;;;N;;;;; +1CE54;SEPARATED BLOCK SEXTANT-3;So;0;ON;;;;;N;;;;; +1CE55;SEPARATED BLOCK SEXTANT-13;So;0;ON;;;;;N;;;;; +1CE56;SEPARATED BLOCK SEXTANT-23;So;0;ON;;;;;N;;;;; +1CE57;SEPARATED BLOCK SEXTANT-123;So;0;ON;;;;;N;;;;; +1CE58;SEPARATED BLOCK SEXTANT-4;So;0;ON;;;;;N;;;;; +1CE59;SEPARATED BLOCK SEXTANT-14;So;0;ON;;;;;N;;;;; +1CE5A;SEPARATED BLOCK SEXTANT-24;So;0;ON;;;;;N;;;;; +1CE5B;SEPARATED BLOCK SEXTANT-124;So;0;ON;;;;;N;;;;; +1CE5C;SEPARATED BLOCK SEXTANT-34;So;0;ON;;;;;N;;;;; +1CE5D;SEPARATED BLOCK SEXTANT-134;So;0;ON;;;;;N;;;;; +1CE5E;SEPARATED BLOCK SEXTANT-234;So;0;ON;;;;;N;;;;; +1CE5F;SEPARATED BLOCK SEXTANT-1234;So;0;ON;;;;;N;;;;; +1CE60;SEPARATED BLOCK SEXTANT-5;So;0;ON;;;;;N;;;;; +1CE61;SEPARATED BLOCK SEXTANT-15;So;0;ON;;;;;N;;;;; +1CE62;SEPARATED BLOCK SEXTANT-25;So;0;ON;;;;;N;;;;; +1CE63;SEPARATED BLOCK SEXTANT-125;So;0;ON;;;;;N;;;;; +1CE64;SEPARATED BLOCK SEXTANT-35;So;0;ON;;;;;N;;;;; +1CE65;SEPARATED BLOCK SEXTANT-135;So;0;ON;;;;;N;;;;; +1CE66;SEPARATED BLOCK SEXTANT-235;So;0;ON;;;;;N;;;;; +1CE67;SEPARATED BLOCK SEXTANT-1235;So;0;ON;;;;;N;;;;; +1CE68;SEPARATED BLOCK SEXTANT-45;So;0;ON;;;;;N;;;;; +1CE69;SEPARATED BLOCK SEXTANT-145;So;0;ON;;;;;N;;;;; +1CE6A;SEPARATED BLOCK SEXTANT-245;So;0;ON;;;;;N;;;;; +1CE6B;SEPARATED BLOCK SEXTANT-1245;So;0;ON;;;;;N;;;;; +1CE6C;SEPARATED BLOCK SEXTANT-345;So;0;ON;;;;;N;;;;; +1CE6D;SEPARATED BLOCK SEXTANT-1345;So;0;ON;;;;;N;;;;; +1CE6E;SEPARATED BLOCK SEXTANT-2345;So;0;ON;;;;;N;;;;; +1CE6F;SEPARATED BLOCK SEXTANT-12345;So;0;ON;;;;;N;;;;; +1CE70;SEPARATED BLOCK SEXTANT-6;So;0;ON;;;;;N;;;;; +1CE71;SEPARATED BLOCK SEXTANT-16;So;0;ON;;;;;N;;;;; +1CE72;SEPARATED BLOCK SEXTANT-26;So;0;ON;;;;;N;;;;; +1CE73;SEPARATED BLOCK SEXTANT-126;So;0;ON;;;;;N;;;;; +1CE74;SEPARATED BLOCK SEXTANT-36;So;0;ON;;;;;N;;;;; +1CE75;SEPARATED BLOCK SEXTANT-136;So;0;ON;;;;;N;;;;; +1CE76;SEPARATED BLOCK SEXTANT-236;So;0;ON;;;;;N;;;;; +1CE77;SEPARATED BLOCK SEXTANT-1236;So;0;ON;;;;;N;;;;; +1CE78;SEPARATED BLOCK SEXTANT-46;So;0;ON;;;;;N;;;;; +1CE79;SEPARATED BLOCK SEXTANT-146;So;0;ON;;;;;N;;;;; +1CE7A;SEPARATED BLOCK SEXTANT-246;So;0;ON;;;;;N;;;;; +1CE7B;SEPARATED BLOCK SEXTANT-1246;So;0;ON;;;;;N;;;;; +1CE7C;SEPARATED BLOCK SEXTANT-346;So;0;ON;;;;;N;;;;; +1CE7D;SEPARATED BLOCK SEXTANT-1346;So;0;ON;;;;;N;;;;; +1CE7E;SEPARATED BLOCK SEXTANT-2346;So;0;ON;;;;;N;;;;; +1CE7F;SEPARATED BLOCK SEXTANT-12346;So;0;ON;;;;;N;;;;; +1CE80;SEPARATED BLOCK SEXTANT-56;So;0;ON;;;;;N;;;;; +1CE81;SEPARATED BLOCK SEXTANT-156;So;0;ON;;;;;N;;;;; +1CE82;SEPARATED BLOCK SEXTANT-256;So;0;ON;;;;;N;;;;; +1CE83;SEPARATED BLOCK SEXTANT-1256;So;0;ON;;;;;N;;;;; +1CE84;SEPARATED BLOCK SEXTANT-356;So;0;ON;;;;;N;;;;; +1CE85;SEPARATED BLOCK SEXTANT-1356;So;0;ON;;;;;N;;;;; +1CE86;SEPARATED BLOCK SEXTANT-2356;So;0;ON;;;;;N;;;;; +1CE87;SEPARATED BLOCK SEXTANT-12356;So;0;ON;;;;;N;;;;; +1CE88;SEPARATED BLOCK SEXTANT-456;So;0;ON;;;;;N;;;;; +1CE89;SEPARATED BLOCK SEXTANT-1456;So;0;ON;;;;;N;;;;; +1CE8A;SEPARATED BLOCK SEXTANT-2456;So;0;ON;;;;;N;;;;; +1CE8B;SEPARATED BLOCK SEXTANT-12456;So;0;ON;;;;;N;;;;; +1CE8C;SEPARATED BLOCK SEXTANT-3456;So;0;ON;;;;;N;;;;; +1CE8D;SEPARATED BLOCK SEXTANT-13456;So;0;ON;;;;;N;;;;; +1CE8E;SEPARATED BLOCK SEXTANT-23456;So;0;ON;;;;;N;;;;; +1CE8F;SEPARATED BLOCK SEXTANT-123456;So;0;ON;;;;;N;;;;; +1CE90;UPPER LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE91;UPPER CENTRE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE92;UPPER CENTRE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE93;UPPER RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE94;UPPER MIDDLE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE95;UPPER MIDDLE CENTRE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE96;UPPER MIDDLE CENTRE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE97;UPPER MIDDLE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE98;LOWER MIDDLE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE99;LOWER MIDDLE CENTRE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9A;LOWER MIDDLE CENTRE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9B;LOWER MIDDLE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9C;LOWER LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9D;LOWER CENTRE LEFT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9E;LOWER CENTRE RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CE9F;LOWER RIGHT ONE SIXTEENTH BLOCK;So;0;ON;;;;;N;;;;; +1CEA0;RIGHT HALF LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA1;RIGHT THREE QUARTERS LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA2;LEFT THREE QUARTERS LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA3;LEFT HALF LOWER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA4;LOWER HALF LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA5;LOWER THREE QUARTERS LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA6;UPPER THREE QUARTERS LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA7;UPPER HALF LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA8;LEFT HALF UPPER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEA9;LEFT THREE QUARTERS UPPER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAA;RIGHT THREE QUARTERS UPPER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAB;RIGHT HALF UPPER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAC;UPPER HALF RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAD;UPPER THREE QUARTERS RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAE;LOWER THREE QUARTERS RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEAF;LOWER HALF RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1CEB0;HORIZONTAL ZIGZAG LINE;So;0;ON;;;;;N;;;;; +1CEB1;KEYHOLE;So;0;ON;;;;;N;;;;; +1CEB2;OLD PERSONAL COMPUTER WITH MONITOR IN PORTRAIT ORIENTATION;So;0;ON;;;;;N;;;;; +1CEB3;BLACK RIGHT TRIANGLE CARET;So;0;ON;;;;;N;;;;; +1CEBA;FRAGILE SYMBOL;So;0;ON;;;;;N;;;;; +1CEBB;OFFICE BUILDING SYMBOL;So;0;ON;;;;;N;;;;; +1CEBC;TREE SYMBOL;So;0;ON;;;;;N;;;;; +1CEBD;APPLE SYMBOL;So;0;ON;;;;;N;;;;; +1CEBE;CHERRY SYMBOL;So;0;ON;;;;;N;;;;; +1CEBF;STRAWBERRY SYMBOL;So;0;ON;;;;;N;;;;; +1CEC0;HEBE;So;0;ON;;;;;N;;;;; +1CEC1;IRIS;So;0;ON;;;;;N;;;;; +1CEC2;FLORA;So;0;ON;;;;;N;;;;; +1CEC3;METIS;So;0;ON;;;;;N;;;;; +1CEC4;PARTHENOPE;So;0;ON;;;;;N;;;;; +1CEC5;VICTORIA;So;0;ON;;;;;N;;;;; +1CEC6;EGERIA;So;0;ON;;;;;N;;;;; +1CEC7;IRENE;So;0;ON;;;;;N;;;;; +1CEC8;EUNOMIA;So;0;ON;;;;;N;;;;; +1CEC9;PSYCHE;So;0;ON;;;;;N;;;;; +1CECA;THETIS;So;0;ON;;;;;N;;;;; +1CECB;MELPOMENE;So;0;ON;;;;;N;;;;; +1CECC;FORTUNA;So;0;ON;;;;;N;;;;; +1CECD;ASTRONOMICAL SYMBOL FOR ASTEROID PROSERPINA;So;0;ON;;;;;N;;;;; +1CECE;BELLONA;So;0;ON;;;;;N;;;;; +1CECF;AMPHITRITE;So;0;ON;;;;;N;;;;; +1CED0;LEUKOTHEA;So;0;ON;;;;;N;;;;; +1CEE0;GEOMANTIC FIGURE POPULUS;So;0;ON;;;;;N;;;;; +1CEE1;GEOMANTIC FIGURE TRISTITIA;So;0;ON;;;;;N;;;;; +1CEE2;GEOMANTIC FIGURE ALBUS;So;0;ON;;;;;N;;;;; +1CEE3;GEOMANTIC FIGURE FORTUNA MAJOR;So;0;ON;;;;;N;;;;; +1CEE4;GEOMANTIC FIGURE RUBEUS;So;0;ON;;;;;N;;;;; +1CEE5;GEOMANTIC FIGURE ACQUISITIO;So;0;ON;;;;;N;;;;; +1CEE6;GEOMANTIC FIGURE CONJUNCTIO;So;0;ON;;;;;N;;;;; +1CEE7;GEOMANTIC FIGURE CAPUT DRACONIS;So;0;ON;;;;;N;;;;; +1CEE8;GEOMANTIC FIGURE LAETITIA;So;0;ON;;;;;N;;;;; +1CEE9;GEOMANTIC FIGURE CARCER;So;0;ON;;;;;N;;;;; +1CEEA;GEOMANTIC FIGURE AMISSIO;So;0;ON;;;;;N;;;;; +1CEEB;GEOMANTIC FIGURE PUELLA;So;0;ON;;;;;N;;;;; +1CEEC;GEOMANTIC FIGURE FORTUNA MINOR;So;0;ON;;;;;N;;;;; +1CEED;GEOMANTIC FIGURE PUER;So;0;ON;;;;;N;;;;; +1CEEE;GEOMANTIC FIGURE CAUDA DRACONIS;So;0;ON;;;;;N;;;;; +1CEEF;GEOMANTIC FIGURE VIA;So;0;ON;;;;;N;;;;; +1CEF0;MEDIUM SMALL WHITE CIRCLE WITH HORIZONTAL BAR;Sm;0;ON;;;;;N;;;;; +1CF00;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF01;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF02;ZNAMENNY COMBINING MARK TSATA ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF03;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF04;ZNAMENNY COMBINING MARK NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF05;ZNAMENNY COMBINING MARK SREDNE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF06;ZNAMENNY COMBINING MARK MALO POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF07;ZNAMENNY COMBINING MARK POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF08;ZNAMENNY COMBINING MARK VYSOKO ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF09;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0A;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0B;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF0C;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0D;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0E;ZNAMENNY COMBINING MARK TSATA ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF0F;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF10;ZNAMENNY COMBINING MARK NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF11;ZNAMENNY COMBINING MARK SREDNE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF12;ZNAMENNY COMBINING MARK MALO POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF13;ZNAMENNY COMBINING MARK POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF14;ZNAMENNY COMBINING MARK VYSOKO ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF15;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF16;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF17;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;; +1CF18;ZNAMENNY COMBINING MARK TSATA S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF19;ZNAMENNY COMBINING MARK MALO POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1A;ZNAMENNY COMBINING MARK STRANNO MALO POVYSHE;Mn;0;NSM;;;;;N;;;;; +1CF1B;ZNAMENNY COMBINING MARK POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1C;ZNAMENNY COMBINING MARK POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;; +1CF1D;ZNAMENNY COMBINING MARK VYSOKO S KRYZHEM;Mn;0;NSM;;;;;N;;;;; +1CF1E;ZNAMENNY COMBINING MARK MALO POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;; +1CF1F;ZNAMENNY COMBINING MARK GORAZDO VYSOKO;Mn;0;NSM;;;;;N;;;;; +1CF20;ZNAMENNY COMBINING MARK ZELO;Mn;0;NSM;;;;;N;;;;; +1CF21;ZNAMENNY COMBINING MARK ON;Mn;0;NSM;;;;;N;;;;; +1CF22;ZNAMENNY COMBINING MARK RAVNO;Mn;0;NSM;;;;;N;;;;; +1CF23;ZNAMENNY COMBINING MARK TIKHAYA;Mn;0;NSM;;;;;N;;;;; +1CF24;ZNAMENNY COMBINING MARK BORZAYA;Mn;0;NSM;;;;;N;;;;; +1CF25;ZNAMENNY COMBINING MARK UDARKA;Mn;0;NSM;;;;;N;;;;; +1CF26;ZNAMENNY COMBINING MARK PODVERTKA;Mn;0;NSM;;;;;N;;;;; +1CF27;ZNAMENNY COMBINING MARK LOMKA;Mn;0;NSM;;;;;N;;;;; +1CF28;ZNAMENNY COMBINING MARK KUPNAYA;Mn;0;NSM;;;;;N;;;;; +1CF29;ZNAMENNY COMBINING MARK KACHKA;Mn;0;NSM;;;;;N;;;;; +1CF2A;ZNAMENNY COMBINING MARK ZEVOK;Mn;0;NSM;;;;;N;;;;; +1CF2B;ZNAMENNY COMBINING MARK SKOBA;Mn;0;NSM;;;;;N;;;;; +1CF2C;ZNAMENNY COMBINING MARK RAZSEKA;Mn;0;NSM;;;;;N;;;;; +1CF2D;ZNAMENNY COMBINING MARK KRYZH ON LEFT;Mn;0;NSM;;;;;N;;;;; +1CF30;ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO;Mn;0;NSM;;;;;N;;;;; +1CF31;ZNAMENNY COMBINING TONAL RANGE MARK SVETLO;Mn;0;NSM;;;;;N;;;;; +1CF32;ZNAMENNY COMBINING TONAL RANGE MARK TRESVETLO;Mn;0;NSM;;;;;N;;;;; +1CF33;ZNAMENNY COMBINING MARK ZADERZHKA;Mn;0;NSM;;;;;N;;;;; +1CF34;ZNAMENNY COMBINING MARK DEMESTVENNY ZADERZHKA;Mn;0;NSM;;;;;N;;;;; +1CF35;ZNAMENNY COMBINING MARK OTSECHKA;Mn;0;NSM;;;;;N;;;;; +1CF36;ZNAMENNY COMBINING MARK PODCHASHIE;Mn;0;NSM;;;;;N;;;;; +1CF37;ZNAMENNY COMBINING MARK PODCHASHIE WITH VERTICAL STROKE;Mn;0;NSM;;;;;N;;;;; +1CF38;ZNAMENNY COMBINING MARK CHASHKA;Mn;0;NSM;;;;;N;;;;; +1CF39;ZNAMENNY COMBINING MARK CHASHKA POLNAYA;Mn;0;NSM;;;;;N;;;;; +1CF3A;ZNAMENNY COMBINING MARK OBLACHKO;Mn;0;NSM;;;;;N;;;;; +1CF3B;ZNAMENNY COMBINING MARK SOROCHYA NOZHKA;Mn;0;NSM;;;;;N;;;;; +1CF3C;ZNAMENNY COMBINING MARK TOCHKA;Mn;0;NSM;;;;;N;;;;; +1CF3D;ZNAMENNY COMBINING MARK DVOETOCHIE;Mn;0;NSM;;;;;N;;;;; +1CF3E;ZNAMENNY COMBINING ATTACHING VERTICAL OMET;Mn;0;NSM;;;;;N;;;;; +1CF3F;ZNAMENNY COMBINING MARK CURVED OMET;Mn;0;NSM;;;;;N;;;;; +1CF40;ZNAMENNY COMBINING MARK KRYZH;Mn;0;NSM;;;;;N;;;;; +1CF41;ZNAMENNY COMBINING LOWER TONAL RANGE INDICATOR;Mn;0;NSM;;;;;N;;;;; +1CF42;ZNAMENNY PRIZNAK MODIFIER LEVEL-2;Mn;0;NSM;;;;;N;;;;; +1CF43;ZNAMENNY PRIZNAK MODIFIER LEVEL-3;Mn;0;NSM;;;;;N;;;;; +1CF44;ZNAMENNY PRIZNAK MODIFIER DIRECTION FLIP;Mn;0;NSM;;;;;N;;;;; +1CF45;ZNAMENNY PRIZNAK MODIFIER KRYZH;Mn;0;NSM;;;;;N;;;;; +1CF46;ZNAMENNY PRIZNAK MODIFIER ROG;Mn;0;NSM;;;;;N;;;;; +1CF50;ZNAMENNY NEUME KRYUK;So;0;L;;;;;N;;;;; +1CF51;ZNAMENNY NEUME KRYUK TIKHY;So;0;L;;;;;N;;;;; +1CF52;ZNAMENNY NEUME PARAKLIT;So;0;L;;;;;N;;;;; +1CF53;ZNAMENNY NEUME DVA V CHELNU;So;0;L;;;;;N;;;;; +1CF54;ZNAMENNY NEUME KLYUCH;So;0;L;;;;;N;;;;; +1CF55;ZNAMENNY NEUME ZANOZHEK;So;0;L;;;;;N;;;;; +1CF56;ZNAMENNY NEUME STOPITSA;So;0;L;;;;;N;;;;; +1CF57;ZNAMENNY NEUME STOPITSA S OCHKOM;So;0;L;;;;;N;;;;; +1CF58;ZNAMENNY NEUME PEREVODKA;So;0;L;;;;;N;;;;; +1CF59;ZNAMENNY NEUME PEREVODKA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF5A;ZNAMENNY NEUME STOPITSA WITH SOROCHYA NOZHKA;So;0;L;;;;;N;;;;; +1CF5B;ZNAMENNY NEUME CHELYUSTKA;So;0;L;;;;;N;;;;; +1CF5C;ZNAMENNY NEUME PALKA;So;0;L;;;;;N;;;;; +1CF5D;ZNAMENNY NEUME ZAPYATAYA;So;0;L;;;;;N;;;;; +1CF5E;ZNAMENNY NEUME GOLUBCHIK BORZY;So;0;L;;;;;N;;;;; +1CF5F;ZNAMENNY NEUME GOLUBCHIK TIKHY;So;0;L;;;;;N;;;;; +1CF60;ZNAMENNY NEUME GOLUBCHIK MRACHNY;So;0;L;;;;;N;;;;; +1CF61;ZNAMENNY NEUME GOLUBCHIK SVETLY;So;0;L;;;;;N;;;;; +1CF62;ZNAMENNY NEUME GOLUBCHIK TRESVETLY;So;0;L;;;;;N;;;;; +1CF63;ZNAMENNY NEUME VRAKHIYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF64;ZNAMENNY NEUME VRAKHIYA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF65;ZNAMENNY NEUME VRAKHIYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF66;ZNAMENNY NEUME VRAKHIYA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF67;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF68;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF69;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF6A;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF6B;ZNAMENNY NEUME DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CF6C;ZNAMENNY NEUME REVERSED CHELYUSTKA;So;0;L;;;;;N;;;;; +1CF6D;ZNAMENNY NEUME DERBITSA;So;0;L;;;;;N;;;;; +1CF6E;ZNAMENNY NEUME KHAMILO;So;0;L;;;;;N;;;;; +1CF6F;ZNAMENNY NEUME CHASHKA;So;0;L;;;;;N;;;;; +1CF70;ZNAMENNY NEUME PODCHASHIE;So;0;L;;;;;N;;;;; +1CF71;ZNAMENNY NEUME SKAMEYTSA MRACHNAYA;So;0;L;;;;;N;;;;; +1CF72;ZNAMENNY NEUME SKAMEYTSA SVETLAYA;So;0;L;;;;;N;;;;; +1CF73;ZNAMENNY NEUME SKAMEYTSA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CF74;ZNAMENNY NEUME SKAMEYTSA TIKHAYA;So;0;L;;;;;N;;;;; +1CF75;ZNAMENNY NEUME DEMESTVENNY KLYUCH;So;0;L;;;;;N;;;;; +1CF76;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF77;ZNAMENNY NEUME SKAMEYTSA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF78;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA TIKHAYA;So;0;L;;;;;N;;;;; +1CF79;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA PROSTAYA;So;0;L;;;;;N;;;;; +1CF7A;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CF7B;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF7C;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CF7D;ZNAMENNY NEUME SLOZHITIE;So;0;L;;;;;N;;;;; +1CF7E;ZNAMENNY NEUME SLOZHITIE S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF7F;ZNAMENNY NEUME SLOZHITIE ZAKRYTOE;So;0;L;;;;;N;;;;; +1CF80;ZNAMENNY NEUME SLOZHITIE S KRYZHEM;So;0;L;;;;;N;;;;; +1CF81;ZNAMENNY NEUME KRYZH;So;0;L;;;;;N;;;;; +1CF82;ZNAMENNY NEUME ROG;So;0;L;;;;;N;;;;; +1CF83;ZNAMENNY NEUME FITA;So;0;L;;;;;N;;;;; +1CF84;ZNAMENNY NEUME KOBYLA;So;0;L;;;;;N;;;;; +1CF85;ZNAMENNY NEUME ZMEYTSA;So;0;L;;;;;N;;;;; +1CF86;ZNAMENNY NEUME STATYA;So;0;L;;;;;N;;;;; +1CF87;ZNAMENNY NEUME STATYA S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF88;ZNAMENNY NEUME STATYA S KRYZHEM;So;0;L;;;;;N;;;;; +1CF89;ZNAMENNY NEUME STATYA S ZAPYATOY I KRYZHEM;So;0;L;;;;;N;;;;; +1CF8A;ZNAMENNY NEUME STATYA S KRYZHEM I ZAPYATOY;So;0;L;;;;;N;;;;; +1CF8B;ZNAMENNY NEUME STATYA ZAKRYTAYA;So;0;L;;;;;N;;;;; +1CF8C;ZNAMENNY NEUME STATYA ZAKRYTAYA S ZAPYATOY;So;0;L;;;;;N;;;;; +1CF8D;ZNAMENNY NEUME STATYA S ROGOM;So;0;L;;;;;N;;;;; +1CF8E;ZNAMENNY NEUME STATYA S DVUMYA ZAPYATYMI;So;0;L;;;;;N;;;;; +1CF8F;ZNAMENNY NEUME STATYA S ZAPYATOY I PODCHASHIEM;So;0;L;;;;;N;;;;; +1CF90;ZNAMENNY NEUME POLKULIZMY;So;0;L;;;;;N;;;;; +1CF91;ZNAMENNY NEUME STATYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF92;ZNAMENNY NEUME STRELA PROSTAYA;So;0;L;;;;;N;;;;; +1CF93;ZNAMENNY NEUME STRELA MRACHNOTIKHAYA;So;0;L;;;;;N;;;;; +1CF94;ZNAMENNY NEUME STRELA KRYZHEVAYA;So;0;L;;;;;N;;;;; +1CF95;ZNAMENNY NEUME STRELA POLUPOVODNAYA;So;0;L;;;;;N;;;;; +1CF96;ZNAMENNY NEUME STRELA POVODNAYA;So;0;L;;;;;N;;;;; +1CF97;ZNAMENNY NEUME STRELA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF98;ZNAMENNY NEUME STRELA KLYUCHEPOVODNAYA;So;0;L;;;;;N;;;;; +1CF99;ZNAMENNY NEUME STRELA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CF9A;ZNAMENNY NEUME STRELA TIKHAYA PUTNAYA;So;0;L;;;;;N;;;;; +1CF9B;ZNAMENNY NEUME STRELA DVOECHELNAYA;So;0;L;;;;;N;;;;; +1CF9C;ZNAMENNY NEUME STRELA DVOECHELNOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CF9D;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA;So;0;L;;;;;N;;;;; +1CF9E;ZNAMENNY NEUME STRELA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CF9F;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;; +1CFA0;ZNAMENNY NEUME STRELA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA1;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA2;ZNAMENNY NEUME STRELA GROMNAYA;So;0;L;;;;;N;;;;; +1CFA3;ZNAMENNY NEUME STRELA GROMOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFA4;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFA5;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CFA6;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFA7;ZNAMENNY NEUME MECHIK;So;0;L;;;;;N;;;;; +1CFA8;ZNAMENNY NEUME MECHIK POVODNY;So;0;L;;;;;N;;;;; +1CFA9;ZNAMENNY NEUME MECHIK KLYUCHEVOY;So;0;L;;;;;N;;;;; +1CFAA;ZNAMENNY NEUME MECHIK KLYUCHEPOVODNY;So;0;L;;;;;N;;;;; +1CFAB;ZNAMENNY NEUME MECHIK KLYUCHENEPOSTOYANNY;So;0;L;;;;;N;;;;; +1CFAC;ZNAMENNY NEUME STRELA TRYASOGLASNAYA;So;0;L;;;;;N;;;;; +1CFAD;ZNAMENNY NEUME STRELA TRYASOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFAE;ZNAMENNY NEUME STRELA TRYASOSTRELNAYA;So;0;L;;;;;N;;;;; +1CFAF;ZNAMENNY NEUME OSOKA;So;0;L;;;;;N;;;;; +1CFB0;ZNAMENNY NEUME OSOKA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB1;ZNAMENNY NEUME OSOKA TRESVETLAYA;So;0;L;;;;;N;;;;; +1CFB2;ZNAMENNY NEUME OSOKA KRYUKOVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB3;ZNAMENNY NEUME OSOKA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;; +1CFB4;ZNAMENNY NEUME OSOKA KLYUCHEVAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;; +1CFB5;ZNAMENNY NEUME STRELA KRYUKOVAYA;So;0;L;;;;;N;;;;; +1CFB6;ZNAMENNY NEUME STRELA KRYUKOVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFB7;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFB8;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFB9;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA;So;0;L;;;;;N;;;;; +1CFBA;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA;So;0;L;;;;;N;;;;; +1CFBB;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;; +1CFBC;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;; +1CFBD;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;; +1CFBE;ZNAMENNY NEUME STRELA KRYUKOVAYA TRYASKA;So;0;L;;;;;N;;;;; +1CFBF;ZNAMENNY NEUME KUFISMA;So;0;L;;;;;N;;;;; +1CFC0;ZNAMENNY NEUME OBLAKO;So;0;L;;;;;N;;;;; +1CFC1;ZNAMENNY NEUME DUDA;So;0;L;;;;;N;;;;; +1CFC2;ZNAMENNY NEUME NEMKA;So;0;L;;;;;N;;;;; +1CFC3;ZNAMENNY NEUME PAUK;So;0;L;;;;;N;;;;; +1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; +1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; +1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; +1D003;BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON;So;0;L;;;;;N;;;;; +1D004;BYZANTINE MUSICAL SYMBOL OXEIA DIPLI;So;0;L;;;;;N;;;;; +1D005;BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON;So;0;L;;;;;N;;;;; +1D006;BYZANTINE MUSICAL SYMBOL VAREIA DIPLI;So;0;L;;;;;N;;;;; +1D007;BYZANTINE MUSICAL SYMBOL KATHISTI;So;0;L;;;;;N;;;;; +1D008;BYZANTINE MUSICAL SYMBOL SYRMATIKI;So;0;L;;;;;N;;;;; +1D009;BYZANTINE MUSICAL SYMBOL PARAKLITIKI;So;0;L;;;;;N;;;;; +1D00A;BYZANTINE MUSICAL SYMBOL YPOKRISIS;So;0;L;;;;;N;;;;; +1D00B;BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI;So;0;L;;;;;N;;;;; +1D00C;BYZANTINE MUSICAL SYMBOL KREMASTI;So;0;L;;;;;N;;;;; +1D00D;BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON;So;0;L;;;;;N;;;;; +1D00E;BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON;So;0;L;;;;;N;;;;; +1D00F;BYZANTINE MUSICAL SYMBOL TELEIA;So;0;L;;;;;N;;;;; +1D010;BYZANTINE MUSICAL SYMBOL KENTIMATA;So;0;L;;;;;N;;;;; +1D011;BYZANTINE MUSICAL SYMBOL APOSTROFOS;So;0;L;;;;;N;;;;; +1D012;BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI;So;0;L;;;;;N;;;;; +1D013;BYZANTINE MUSICAL SYMBOL SYNEVMA;So;0;L;;;;;N;;;;; +1D014;BYZANTINE MUSICAL SYMBOL THITA;So;0;L;;;;;N;;;;; +1D015;BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION;So;0;L;;;;;N;;;;; +1D016;BYZANTINE MUSICAL SYMBOL GORGON ARCHAION;So;0;L;;;;;N;;;;; +1D017;BYZANTINE MUSICAL SYMBOL PSILON;So;0;L;;;;;N;;;;; +1D018;BYZANTINE MUSICAL SYMBOL CHAMILON;So;0;L;;;;;N;;;;; +1D019;BYZANTINE MUSICAL SYMBOL VATHY;So;0;L;;;;;N;;;;; +1D01A;BYZANTINE MUSICAL SYMBOL ISON ARCHAION;So;0;L;;;;;N;;;;; +1D01B;BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION;So;0;L;;;;;N;;;;; +1D01C;BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION;So;0;L;;;;;N;;;;; +1D01D;BYZANTINE MUSICAL SYMBOL SAXIMATA;So;0;L;;;;;N;;;;; +1D01E;BYZANTINE MUSICAL SYMBOL PARICHON;So;0;L;;;;;N;;;;; +1D01F;BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA;So;0;L;;;;;N;;;;; +1D020;BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION;So;0;L;;;;;N;;;;; +1D021;BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION;So;0;L;;;;;N;;;;; +1D022;BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION;So;0;L;;;;;N;;;;; +1D023;BYZANTINE MUSICAL SYMBOL APOTHEMA;So;0;L;;;;;N;;;;; +1D024;BYZANTINE MUSICAL SYMBOL KLASMA;So;0;L;;;;;N;;;;; +1D025;BYZANTINE MUSICAL SYMBOL REVMA;So;0;L;;;;;N;;;;; +1D026;BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION;So;0;L;;;;;N;;;;; +1D027;BYZANTINE MUSICAL SYMBOL TINAGMA;So;0;L;;;;;N;;;;; +1D028;BYZANTINE MUSICAL SYMBOL ANATRICHISMA;So;0;L;;;;;N;;;;; +1D029;BYZANTINE MUSICAL SYMBOL SEISMA;So;0;L;;;;;N;;;;; +1D02A;BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION;So;0;L;;;;;N;;;;; +1D02B;BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU;So;0;L;;;;;N;;;;; +1D02C;BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION;So;0;L;;;;;N;;;;; +1D02D;BYZANTINE MUSICAL SYMBOL THEMA;So;0;L;;;;;N;;;;; +1D02E;BYZANTINE MUSICAL SYMBOL LEMOI;So;0;L;;;;;N;;;;; +1D02F;BYZANTINE MUSICAL SYMBOL DYO;So;0;L;;;;;N;;;;; +1D030;BYZANTINE MUSICAL SYMBOL TRIA;So;0;L;;;;;N;;;;; +1D031;BYZANTINE MUSICAL SYMBOL TESSERA;So;0;L;;;;;N;;;;; +1D032;BYZANTINE MUSICAL SYMBOL KRATIMATA;So;0;L;;;;;N;;;;; +1D033;BYZANTINE MUSICAL SYMBOL APESO EXO NEO;So;0;L;;;;;N;;;;; +1D034;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION;So;0;L;;;;;N;;;;; +1D035;BYZANTINE MUSICAL SYMBOL IMIFTHORA;So;0;L;;;;;N;;;;; +1D036;BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION;So;0;L;;;;;N;;;;; +1D037;BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON;So;0;L;;;;;N;;;;; +1D038;BYZANTINE MUSICAL SYMBOL PELASTON;So;0;L;;;;;N;;;;; +1D039;BYZANTINE MUSICAL SYMBOL PSIFISTON;So;0;L;;;;;N;;;;; +1D03A;BYZANTINE MUSICAL SYMBOL KONTEVMA;So;0;L;;;;;N;;;;; +1D03B;BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION;So;0;L;;;;;N;;;;; +1D03C;BYZANTINE MUSICAL SYMBOL RAPISMA;So;0;L;;;;;N;;;;; +1D03D;BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION;So;0;L;;;;;N;;;;; +1D03E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION;So;0;L;;;;;N;;;;; +1D03F;BYZANTINE MUSICAL SYMBOL ICHADIN;So;0;L;;;;;N;;;;; +1D040;BYZANTINE MUSICAL SYMBOL NANA;So;0;L;;;;;N;;;;; +1D041;BYZANTINE MUSICAL SYMBOL PETASMA;So;0;L;;;;;N;;;;; +1D042;BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO;So;0;L;;;;;N;;;;; +1D043;BYZANTINE MUSICAL SYMBOL TROMIKON ALLO;So;0;L;;;;;N;;;;; +1D044;BYZANTINE MUSICAL SYMBOL STRAGGISMATA;So;0;L;;;;;N;;;;; +1D045;BYZANTINE MUSICAL SYMBOL GRONTHISMATA;So;0;L;;;;;N;;;;; +1D046;BYZANTINE MUSICAL SYMBOL ISON NEO;So;0;L;;;;;N;;;;; +1D047;BYZANTINE MUSICAL SYMBOL OLIGON NEO;So;0;L;;;;;N;;;;; +1D048;BYZANTINE MUSICAL SYMBOL OXEIA NEO;So;0;L;;;;;N;;;;; +1D049;BYZANTINE MUSICAL SYMBOL PETASTI;So;0;L;;;;;N;;;;; +1D04A;BYZANTINE MUSICAL SYMBOL KOUFISMA;So;0;L;;;;;N;;;;; +1D04B;BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA;So;0;L;;;;;N;;;;; +1D04C;BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA;So;0;L;;;;;N;;;;; +1D04D;BYZANTINE MUSICAL SYMBOL PELASTON NEO;So;0;L;;;;;N;;;;; +1D04E;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO;So;0;L;;;;;N;;;;; +1D04F;BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO;So;0;L;;;;;N;;;;; +1D050;BYZANTINE MUSICAL SYMBOL YPSILI;So;0;L;;;;;N;;;;; +1D051;BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO;So;0;L;;;;;N;;;;; +1D052;BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO;So;0;L;;;;;N;;;;; +1D053;BYZANTINE MUSICAL SYMBOL YPORROI;So;0;L;;;;;N;;;;; +1D054;BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON;So;0;L;;;;;N;;;;; +1D055;BYZANTINE MUSICAL SYMBOL ELAFRON;So;0;L;;;;;N;;;;; +1D056;BYZANTINE MUSICAL SYMBOL CHAMILI;So;0;L;;;;;N;;;;; +1D057;BYZANTINE MUSICAL SYMBOL MIKRON ISON;So;0;L;;;;;N;;;;; +1D058;BYZANTINE MUSICAL SYMBOL VAREIA NEO;So;0;L;;;;;N;;;;; +1D059;BYZANTINE MUSICAL SYMBOL PIASMA NEO;So;0;L;;;;;N;;;;; +1D05A;BYZANTINE MUSICAL SYMBOL PSIFISTON NEO;So;0;L;;;;;N;;;;; +1D05B;BYZANTINE MUSICAL SYMBOL OMALON;So;0;L;;;;;N;;;;; +1D05C;BYZANTINE MUSICAL SYMBOL ANTIKENOMA;So;0;L;;;;;N;;;;; +1D05D;BYZANTINE MUSICAL SYMBOL LYGISMA;So;0;L;;;;;N;;;;; +1D05E;BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO;So;0;L;;;;;N;;;;; +1D05F;BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO;So;0;L;;;;;N;;;;; +1D060;BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA;So;0;L;;;;;N;;;;; +1D061;BYZANTINE MUSICAL SYMBOL KYLISMA;So;0;L;;;;;N;;;;; +1D062;BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA;So;0;L;;;;;N;;;;; +1D063;BYZANTINE MUSICAL SYMBOL TROMIKON NEO;So;0;L;;;;;N;;;;; +1D064;BYZANTINE MUSICAL SYMBOL EKSTREPTON;So;0;L;;;;;N;;;;; +1D065;BYZANTINE MUSICAL SYMBOL SYNAGMA NEO;So;0;L;;;;;N;;;;; +1D066;BYZANTINE MUSICAL SYMBOL SYRMA;So;0;L;;;;;N;;;;; +1D067;BYZANTINE MUSICAL SYMBOL CHOREVMA NEO;So;0;L;;;;;N;;;;; +1D068;BYZANTINE MUSICAL SYMBOL EPEGERMA;So;0;L;;;;;N;;;;; +1D069;BYZANTINE MUSICAL SYMBOL SEISMA NEO;So;0;L;;;;;N;;;;; +1D06A;BYZANTINE MUSICAL SYMBOL XIRON KLASMA;So;0;L;;;;;N;;;;; +1D06B;BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON;So;0;L;;;;;N;;;;; +1D06C;BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA;So;0;L;;;;;N;;;;; +1D06D;BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA;So;0;L;;;;;N;;;;; +1D06E;BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA;So;0;L;;;;;N;;;;; +1D06F;BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA;So;0;L;;;;;N;;;;; +1D070;BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA;So;0;L;;;;;N;;;;; +1D071;BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA;So;0;L;;;;;N;;;;; +1D072;BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON;So;0;L;;;;;N;;;;; +1D073;BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON;So;0;L;;;;;N;;;;; +1D074;BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON;So;0;L;;;;;N;;;;; +1D075;BYZANTINE MUSICAL SYMBOL OYRANISMA NEO;So;0;L;;;;;N;;;;; +1D076;BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO;So;0;L;;;;;N;;;;; +1D077;BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO;So;0;L;;;;;N;;;;; +1D078;BYZANTINE MUSICAL SYMBOL THEMA APLOUN;So;0;L;;;;;N;;;;; +1D079;BYZANTINE MUSICAL SYMBOL THES KAI APOTHES;So;0;L;;;;;N;;;;; +1D07A;BYZANTINE MUSICAL SYMBOL KATAVASMA;So;0;L;;;;;N;;;;; +1D07B;BYZANTINE MUSICAL SYMBOL ENDOFONON;So;0;L;;;;;N;;;;; +1D07C;BYZANTINE MUSICAL SYMBOL YFEN KATO;So;0;L;;;;;N;;;;; +1D07D;BYZANTINE MUSICAL SYMBOL YFEN ANO;So;0;L;;;;;N;;;;; +1D07E;BYZANTINE MUSICAL SYMBOL STAVROS;So;0;L;;;;;N;;;;; +1D07F;BYZANTINE MUSICAL SYMBOL KLASMA ANO;So;0;L;;;;;N;;;;; +1D080;BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION;So;0;L;;;;;N;;;;; +1D081;BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION;So;0;L;;;;;N;;;;; +1D082;BYZANTINE MUSICAL SYMBOL KRATIMA ALLO;So;0;L;;;;;N;;;;; +1D083;BYZANTINE MUSICAL SYMBOL KRATIMA NEO;So;0;L;;;;;N;;;;; +1D084;BYZANTINE MUSICAL SYMBOL APODERMA NEO;So;0;L;;;;;N;;;;; +1D085;BYZANTINE MUSICAL SYMBOL APLI;So;0;L;;;;;N;;;;; +1D086;BYZANTINE MUSICAL SYMBOL DIPLI;So;0;L;;;;;N;;;;; +1D087;BYZANTINE MUSICAL SYMBOL TRIPLI;So;0;L;;;;;N;;;;; +1D088;BYZANTINE MUSICAL SYMBOL TETRAPLI;So;0;L;;;;;N;;;;; +1D089;BYZANTINE MUSICAL SYMBOL KORONIS;So;0;L;;;;;N;;;;; +1D08A;BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU;So;0;L;;;;;N;;;;; +1D08B;BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON;So;0;L;;;;;N;;;;; +1D08C;BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON;So;0;L;;;;;N;;;;; +1D08D;BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON;So;0;L;;;;;N;;;;; +1D08E;BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU;So;0;L;;;;;N;;;;; +1D08F;BYZANTINE MUSICAL SYMBOL GORGON NEO ANO;So;0;L;;;;;N;;;;; +1D090;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA;So;0;L;;;;;N;;;;; +1D091;BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; +1D092;BYZANTINE MUSICAL SYMBOL DIGORGON;So;0;L;;;;;N;;;;; +1D093;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO;So;0;L;;;;;N;;;;; +1D094;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO;So;0;L;;;;;N;;;;; +1D095;BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA;So;0;L;;;;;N;;;;; +1D096;BYZANTINE MUSICAL SYMBOL TRIGORGON;So;0;L;;;;;N;;;;; +1D097;BYZANTINE MUSICAL SYMBOL ARGON;So;0;L;;;;;N;;;;; +1D098;BYZANTINE MUSICAL SYMBOL IMIDIARGON;So;0;L;;;;;N;;;;; +1D099;BYZANTINE MUSICAL SYMBOL DIARGON;So;0;L;;;;;N;;;;; +1D09A;BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI;So;0;L;;;;;N;;;;; +1D09B;BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI;So;0;L;;;;;N;;;;; +1D09C;BYZANTINE MUSICAL SYMBOL AGOGI ARGI;So;0;L;;;;;N;;;;; +1D09D;BYZANTINE MUSICAL SYMBOL AGOGI METRIA;So;0;L;;;;;N;;;;; +1D09E;BYZANTINE MUSICAL SYMBOL AGOGI MESI;So;0;L;;;;;N;;;;; +1D09F;BYZANTINE MUSICAL SYMBOL AGOGI GORGI;So;0;L;;;;;N;;;;; +1D0A0;BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI;So;0;L;;;;;N;;;;; +1D0A1;BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI;So;0;L;;;;;N;;;;; +1D0A2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A3;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A4;BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS;So;0;L;;;;;N;;;;; +1D0A5;BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS;So;0;L;;;;;N;;;;; +1D0A6;BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS;So;0;L;;;;;N;;;;; +1D0A7;BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS;So;0;L;;;;;N;;;;; +1D0A8;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS;So;0;L;;;;;N;;;;; +1D0A9;BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS;So;0;L;;;;;N;;;;; +1D0AA;BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS;So;0;L;;;;;N;;;;; +1D0AB;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS;So;0;L;;;;;N;;;;; +1D0AC;BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; +1D0AD;BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS;So;0;L;;;;;N;;;;; +1D0AE;BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS;So;0;L;;;;;N;;;;; +1D0AF;BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS;So;0;L;;;;;N;;;;; +1D0B0;BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS;So;0;L;;;;;N;;;;; +1D0B1;BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS;So;0;L;;;;;N;;;;; +1D0B2;BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS;So;0;L;;;;;N;;;;; +1D0B3;BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS;So;0;L;;;;;N;;;;; +1D0B4;BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN;So;0;L;;;;;N;;;;; +1D0B5;BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN;So;0;L;;;;;N;;;;; +1D0B6;BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU;So;0;L;;;;;N;;;;; +1D0B7;BYZANTINE MUSICAL SYMBOL IMIFONON;So;0;L;;;;;N;;;;; +1D0B8;BYZANTINE MUSICAL SYMBOL IMIFTHORON;So;0;L;;;;;N;;;;; +1D0B9;BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU;So;0;L;;;;;N;;;;; +1D0BA;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA;So;0;L;;;;;N;;;;; +1D0BB;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA;So;0;L;;;;;N;;;;; +1D0BC;BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS;So;0;L;;;;;N;;;;; +1D0BD;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI;So;0;L;;;;;N;;;;; +1D0BE;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI;So;0;L;;;;;N;;;;; +1D0BF;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE;So;0;L;;;;;N;;;;; +1D0C0;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO;So;0;L;;;;;N;;;;; +1D0C1;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO;So;0;L;;;;;N;;;;; +1D0C2;BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO;So;0;L;;;;;N;;;;; +1D0C3;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS;So;0;L;;;;;N;;;;; +1D0C4;BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS;So;0;L;;;;;N;;;;; +1D0C5;BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS;So;0;L;;;;;N;;;;; +1D0C6;BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI;So;0;L;;;;;N;;;;; +1D0C7;BYZANTINE MUSICAL SYMBOL FTHORA NENANO;So;0;L;;;;;N;;;;; +1D0C8;BYZANTINE MUSICAL SYMBOL CHROA ZYGOS;So;0;L;;;;;N;;;;; +1D0C9;BYZANTINE MUSICAL SYMBOL CHROA KLITON;So;0;L;;;;;N;;;;; +1D0CA;BYZANTINE MUSICAL SYMBOL CHROA SPATHI;So;0;L;;;;;N;;;;; +1D0CB;BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION;So;0;L;;;;;N;;;;; +1D0CC;BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA;So;0;L;;;;;N;;;;; +1D0CD;BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION;So;0;L;;;;;N;;;;; +1D0CE;BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION;So;0;L;;;;;N;;;;; +1D0CF;BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION;So;0;L;;;;;N;;;;; +1D0D0;BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; +1D0D1;BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; +1D0D2;BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; +1D0D3;BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; +1D0D4;BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA;So;0;L;;;;;N;;;;; +1D0D5;BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA;So;0;L;;;;;N;;;;; +1D0D6;BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA;So;0;L;;;;;N;;;;; +1D0D7;BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA;So;0;L;;;;;N;;;;; +1D0D8;BYZANTINE MUSICAL SYMBOL GENIKI DIESIS;So;0;L;;;;;N;;;;; +1D0D9;BYZANTINE MUSICAL SYMBOL GENIKI YFESIS;So;0;L;;;;;N;;;;; +1D0DA;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI;So;0;L;;;;;N;;;;; +1D0DB;BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI;So;0;L;;;;;N;;;;; +1D0DC;BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI;So;0;L;;;;;N;;;;; +1D0DD;BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS;So;0;L;;;;;N;;;;; +1D0DE;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS;So;0;L;;;;;N;;;;; +1D0DF;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU;So;0;L;;;;;N;;;;; +1D0E0;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU;So;0;L;;;;;N;;;;; +1D0E1;BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU;So;0;L;;;;;N;;;;; +1D0E2;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS;So;0;L;;;;;N;;;;; +1D0E3;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU;So;0;L;;;;;N;;;;; +1D0E4;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU;So;0;L;;;;;N;;;;; +1D0E5;BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU;So;0;L;;;;;N;;;;; +1D0E6;BYZANTINE MUSICAL SYMBOL DIGRAMMA GG;So;0;L;;;;;N;;;;; +1D0E7;BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU;So;0;L;;;;;N;;;;; +1D0E8;BYZANTINE MUSICAL SYMBOL STIGMA;So;0;L;;;;;N;;;;; +1D0E9;BYZANTINE MUSICAL SYMBOL ARKTIKO PA;So;0;L;;;;;N;;;;; +1D0EA;BYZANTINE MUSICAL SYMBOL ARKTIKO VOU;So;0;L;;;;;N;;;;; +1D0EB;BYZANTINE MUSICAL SYMBOL ARKTIKO GA;So;0;L;;;;;N;;;;; +1D0EC;BYZANTINE MUSICAL SYMBOL ARKTIKO DI;So;0;L;;;;;N;;;;; +1D0ED;BYZANTINE MUSICAL SYMBOL ARKTIKO KE;So;0;L;;;;;N;;;;; +1D0EE;BYZANTINE MUSICAL SYMBOL ARKTIKO ZO;So;0;L;;;;;N;;;;; +1D0EF;BYZANTINE MUSICAL SYMBOL ARKTIKO NI;So;0;L;;;;;N;;;;; +1D0F0;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO;So;0;L;;;;;N;;;;; +1D0F1;BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO;So;0;L;;;;;N;;;;; +1D0F2;BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO;So;0;L;;;;;N;;;;; +1D0F3;BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO;So;0;L;;;;;N;;;;; +1D0F4;BYZANTINE MUSICAL SYMBOL KLASMA KATO;So;0;L;;;;;N;;;;; +1D0F5;BYZANTINE MUSICAL SYMBOL GORGON NEO KATO;So;0;L;;;;;N;;;;; +1D100;MUSICAL SYMBOL SINGLE BARLINE;So;0;L;;;;;N;;;;; +1D101;MUSICAL SYMBOL DOUBLE BARLINE;So;0;L;;;;;N;;;;; +1D102;MUSICAL SYMBOL FINAL BARLINE;So;0;L;;;;;N;;;;; +1D103;MUSICAL SYMBOL REVERSE FINAL BARLINE;So;0;L;;;;;N;;;;; +1D104;MUSICAL SYMBOL DASHED BARLINE;So;0;L;;;;;N;;;;; +1D105;MUSICAL SYMBOL SHORT BARLINE;So;0;L;;;;;N;;;;; +1D106;MUSICAL SYMBOL LEFT REPEAT SIGN;So;0;L;;;;;N;;;;; +1D107;MUSICAL SYMBOL RIGHT REPEAT SIGN;So;0;L;;;;;N;;;;; +1D108;MUSICAL SYMBOL REPEAT DOTS;So;0;L;;;;;N;;;;; +1D109;MUSICAL SYMBOL DAL SEGNO;So;0;L;;;;;N;;;;; +1D10A;MUSICAL SYMBOL DA CAPO;So;0;L;;;;;N;;;;; +1D10B;MUSICAL SYMBOL SEGNO;So;0;L;;;;;N;;;;; +1D10C;MUSICAL SYMBOL CODA;So;0;L;;;;;N;;;;; +1D10D;MUSICAL SYMBOL REPEATED FIGURE-1;So;0;L;;;;;N;;;;; +1D10E;MUSICAL SYMBOL REPEATED FIGURE-2;So;0;L;;;;;N;;;;; +1D10F;MUSICAL SYMBOL REPEATED FIGURE-3;So;0;L;;;;;N;;;;; +1D110;MUSICAL SYMBOL FERMATA;So;0;L;;;;;N;;;;; +1D111;MUSICAL SYMBOL FERMATA BELOW;So;0;L;;;;;N;;;;; +1D112;MUSICAL SYMBOL BREATH MARK;So;0;L;;;;;N;;;;; +1D113;MUSICAL SYMBOL CAESURA;So;0;L;;;;;N;;;;; +1D114;MUSICAL SYMBOL BRACE;So;0;L;;;;;N;;;;; +1D115;MUSICAL SYMBOL BRACKET;So;0;L;;;;;N;;;;; +1D116;MUSICAL SYMBOL ONE-LINE STAFF;So;0;L;;;;;N;;;;; +1D117;MUSICAL SYMBOL TWO-LINE STAFF;So;0;L;;;;;N;;;;; +1D118;MUSICAL SYMBOL THREE-LINE STAFF;So;0;L;;;;;N;;;;; +1D119;MUSICAL SYMBOL FOUR-LINE STAFF;So;0;L;;;;;N;;;;; +1D11A;MUSICAL SYMBOL FIVE-LINE STAFF;So;0;L;;;;;N;;;;; +1D11B;MUSICAL SYMBOL SIX-LINE STAFF;So;0;L;;;;;N;;;;; +1D11C;MUSICAL SYMBOL SIX-STRING FRETBOARD;So;0;L;;;;;N;;;;; +1D11D;MUSICAL SYMBOL FOUR-STRING FRETBOARD;So;0;L;;;;;N;;;;; +1D11E;MUSICAL SYMBOL G CLEF;So;0;L;;;;;N;;;;; +1D11F;MUSICAL SYMBOL G CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D120;MUSICAL SYMBOL G CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D121;MUSICAL SYMBOL C CLEF;So;0;L;;;;;N;;;;; +1D122;MUSICAL SYMBOL F CLEF;So;0;L;;;;;N;;;;; +1D123;MUSICAL SYMBOL F CLEF OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D124;MUSICAL SYMBOL F CLEF OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D125;MUSICAL SYMBOL DRUM CLEF-1;So;0;L;;;;;N;;;;; +1D126;MUSICAL SYMBOL DRUM CLEF-2;So;0;L;;;;;N;;;;; +1D129;MUSICAL SYMBOL MULTIPLE MEASURE REST;So;0;L;;;;;N;;;;; +1D12A;MUSICAL SYMBOL DOUBLE SHARP;So;0;L;;;;;N;;;;; +1D12B;MUSICAL SYMBOL DOUBLE FLAT;So;0;L;;;;;N;;;;; +1D12C;MUSICAL SYMBOL FLAT UP;So;0;L;;;;;N;;;;; +1D12D;MUSICAL SYMBOL FLAT DOWN;So;0;L;;;;;N;;;;; +1D12E;MUSICAL SYMBOL NATURAL UP;So;0;L;;;;;N;;;;; +1D12F;MUSICAL SYMBOL NATURAL DOWN;So;0;L;;;;;N;;;;; +1D130;MUSICAL SYMBOL SHARP UP;So;0;L;;;;;N;;;;; +1D131;MUSICAL SYMBOL SHARP DOWN;So;0;L;;;;;N;;;;; +1D132;MUSICAL SYMBOL QUARTER TONE SHARP;So;0;L;;;;;N;;;;; +1D133;MUSICAL SYMBOL QUARTER TONE FLAT;So;0;L;;;;;N;;;;; +1D134;MUSICAL SYMBOL COMMON TIME;So;0;L;;;;;N;;;;; +1D135;MUSICAL SYMBOL CUT TIME;So;0;L;;;;;N;;;;; +1D136;MUSICAL SYMBOL OTTAVA ALTA;So;0;L;;;;;N;;;;; +1D137;MUSICAL SYMBOL OTTAVA BASSA;So;0;L;;;;;N;;;;; +1D138;MUSICAL SYMBOL QUINDICESIMA ALTA;So;0;L;;;;;N;;;;; +1D139;MUSICAL SYMBOL QUINDICESIMA BASSA;So;0;L;;;;;N;;;;; +1D13A;MUSICAL SYMBOL MULTI REST;So;0;L;;;;;N;;;;; +1D13B;MUSICAL SYMBOL WHOLE REST;So;0;L;;;;;N;;;;; +1D13C;MUSICAL SYMBOL HALF REST;So;0;L;;;;;N;;;;; +1D13D;MUSICAL SYMBOL QUARTER REST;So;0;L;;;;;N;;;;; +1D13E;MUSICAL SYMBOL EIGHTH REST;So;0;L;;;;;N;;;;; +1D13F;MUSICAL SYMBOL SIXTEENTH REST;So;0;L;;;;;N;;;;; +1D140;MUSICAL SYMBOL THIRTY-SECOND REST;So;0;L;;;;;N;;;;; +1D141;MUSICAL SYMBOL SIXTY-FOURTH REST;So;0;L;;;;;N;;;;; +1D142;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST;So;0;L;;;;;N;;;;; +1D143;MUSICAL SYMBOL X NOTEHEAD;So;0;L;;;;;N;;;;; +1D144;MUSICAL SYMBOL PLUS NOTEHEAD;So;0;L;;;;;N;;;;; +1D145;MUSICAL SYMBOL CIRCLE X NOTEHEAD;So;0;L;;;;;N;;;;; +1D146;MUSICAL SYMBOL SQUARE NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D147;MUSICAL SYMBOL SQUARE NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D148;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE;So;0;L;;;;;N;;;;; +1D149;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK;So;0;L;;;;;N;;;;; +1D14A;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE;So;0;L;;;;;N;;;;; +1D14B;MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK;So;0;L;;;;;N;;;;; +1D14C;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE;So;0;L;;;;;N;;;;; +1D14D;MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK;So;0;L;;;;;N;;;;; +1D14E;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; +1D14F;MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; +1D150;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE;So;0;L;;;;;N;;;;; +1D151;MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK;So;0;L;;;;;N;;;;; +1D152;MUSICAL SYMBOL MOON NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D153;MUSICAL SYMBOL MOON NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D154;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE;So;0;L;;;;;N;;;;; +1D155;MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK;So;0;L;;;;;N;;;;; +1D156;MUSICAL SYMBOL PARENTHESIS NOTEHEAD;So;0;L;;;;;N;;;;; +1D157;MUSICAL SYMBOL VOID NOTEHEAD;So;0;L;;;;;N;;;;; +1D158;MUSICAL SYMBOL NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D159;MUSICAL SYMBOL NULL NOTEHEAD;So;0;L;;;;;N;;;;; +1D15A;MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE;So;0;L;;;;;N;;;;; +1D15B;MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK;So;0;L;;;;;N;;;;; +1D15C;MUSICAL SYMBOL BREVE;So;0;L;;;;;N;;;;; +1D15D;MUSICAL SYMBOL WHOLE NOTE;So;0;L;;;;;N;;;;; +1D15E;MUSICAL SYMBOL HALF NOTE;So;0;L;1D157 1D165;;;;N;;;;; +1D15F;MUSICAL SYMBOL QUARTER NOTE;So;0;L;1D158 1D165;;;;N;;;;; +1D160;MUSICAL SYMBOL EIGHTH NOTE;So;0;L;1D15F 1D16E;;;;N;;;;; +1D161;MUSICAL SYMBOL SIXTEENTH NOTE;So;0;L;1D15F 1D16F;;;;N;;;;; +1D162;MUSICAL SYMBOL THIRTY-SECOND NOTE;So;0;L;1D15F 1D170;;;;N;;;;; +1D163;MUSICAL SYMBOL SIXTY-FOURTH NOTE;So;0;L;1D15F 1D171;;;;N;;;;; +1D164;MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE;So;0;L;1D15F 1D172;;;;N;;;;; +1D165;MUSICAL SYMBOL COMBINING STEM;Mc;216;L;;;;;N;;;;; +1D166;MUSICAL SYMBOL COMBINING SPRECHGESANG STEM;Mc;216;L;;;;;N;;;;; +1D167;MUSICAL SYMBOL COMBINING TREMOLO-1;Mn;1;NSM;;;;;N;;;;; +1D168;MUSICAL SYMBOL COMBINING TREMOLO-2;Mn;1;NSM;;;;;N;;;;; +1D169;MUSICAL SYMBOL COMBINING TREMOLO-3;Mn;1;NSM;;;;;N;;;;; +1D16A;MUSICAL SYMBOL FINGERED TREMOLO-1;So;0;L;;;;;N;;;;; +1D16B;MUSICAL SYMBOL FINGERED TREMOLO-2;So;0;L;;;;;N;;;;; +1D16C;MUSICAL SYMBOL FINGERED TREMOLO-3;So;0;L;;;;;N;;;;; +1D16D;MUSICAL SYMBOL COMBINING AUGMENTATION DOT;Mc;226;L;;;;;N;;;;; +1D16E;MUSICAL SYMBOL COMBINING FLAG-1;Mc;216;L;;;;;N;;;;; +1D16F;MUSICAL SYMBOL COMBINING FLAG-2;Mc;216;L;;;;;N;;;;; +1D170;MUSICAL SYMBOL COMBINING FLAG-3;Mc;216;L;;;;;N;;;;; +1D171;MUSICAL SYMBOL COMBINING FLAG-4;Mc;216;L;;;;;N;;;;; +1D172;MUSICAL SYMBOL COMBINING FLAG-5;Mc;216;L;;;;;N;;;;; +1D173;MUSICAL SYMBOL BEGIN BEAM;Cf;0;BN;;;;;N;;;;; +1D174;MUSICAL SYMBOL END BEAM;Cf;0;BN;;;;;N;;;;; +1D175;MUSICAL SYMBOL BEGIN TIE;Cf;0;BN;;;;;N;;;;; +1D176;MUSICAL SYMBOL END TIE;Cf;0;BN;;;;;N;;;;; +1D177;MUSICAL SYMBOL BEGIN SLUR;Cf;0;BN;;;;;N;;;;; +1D178;MUSICAL SYMBOL END SLUR;Cf;0;BN;;;;;N;;;;; +1D179;MUSICAL SYMBOL BEGIN PHRASE;Cf;0;BN;;;;;N;;;;; +1D17A;MUSICAL SYMBOL END PHRASE;Cf;0;BN;;;;;N;;;;; +1D17B;MUSICAL SYMBOL COMBINING ACCENT;Mn;220;NSM;;;;;N;;;;; +1D17C;MUSICAL SYMBOL COMBINING STACCATO;Mn;220;NSM;;;;;N;;;;; +1D17D;MUSICAL SYMBOL COMBINING TENUTO;Mn;220;NSM;;;;;N;;;;; +1D17E;MUSICAL SYMBOL COMBINING STACCATISSIMO;Mn;220;NSM;;;;;N;;;;; +1D17F;MUSICAL SYMBOL COMBINING MARCATO;Mn;220;NSM;;;;;N;;;;; +1D180;MUSICAL SYMBOL COMBINING MARCATO-STACCATO;Mn;220;NSM;;;;;N;;;;; +1D181;MUSICAL SYMBOL COMBINING ACCENT-STACCATO;Mn;220;NSM;;;;;N;;;;; +1D182;MUSICAL SYMBOL COMBINING LOURE;Mn;220;NSM;;;;;N;;;;; +1D183;MUSICAL SYMBOL ARPEGGIATO UP;So;0;L;;;;;N;;;;; +1D184;MUSICAL SYMBOL ARPEGGIATO DOWN;So;0;L;;;;;N;;;;; +1D185;MUSICAL SYMBOL COMBINING DOIT;Mn;230;NSM;;;;;N;;;;; +1D186;MUSICAL SYMBOL COMBINING RIP;Mn;230;NSM;;;;;N;;;;; +1D187;MUSICAL SYMBOL COMBINING FLIP;Mn;230;NSM;;;;;N;;;;; +1D188;MUSICAL SYMBOL COMBINING SMEAR;Mn;230;NSM;;;;;N;;;;; +1D189;MUSICAL SYMBOL COMBINING BEND;Mn;230;NSM;;;;;N;;;;; +1D18A;MUSICAL SYMBOL COMBINING DOUBLE TONGUE;Mn;220;NSM;;;;;N;;;;; +1D18B;MUSICAL SYMBOL COMBINING TRIPLE TONGUE;Mn;220;NSM;;;;;N;;;;; +1D18C;MUSICAL SYMBOL RINFORZANDO;So;0;L;;;;;N;;;;; +1D18D;MUSICAL SYMBOL SUBITO;So;0;L;;;;;N;;;;; +1D18E;MUSICAL SYMBOL Z;So;0;L;;;;;N;;;;; +1D18F;MUSICAL SYMBOL PIANO;So;0;L;;;;;N;;;;; +1D190;MUSICAL SYMBOL MEZZO;So;0;L;;;;;N;;;;; +1D191;MUSICAL SYMBOL FORTE;So;0;L;;;;;N;;;;; +1D192;MUSICAL SYMBOL CRESCENDO;So;0;L;;;;;N;;;;; +1D193;MUSICAL SYMBOL DECRESCENDO;So;0;L;;;;;N;;;;; +1D194;MUSICAL SYMBOL GRACE NOTE SLASH;So;0;L;;;;;N;;;;; +1D195;MUSICAL SYMBOL GRACE NOTE NO SLASH;So;0;L;;;;;N;;;;; +1D196;MUSICAL SYMBOL TR;So;0;L;;;;;N;;;;; +1D197;MUSICAL SYMBOL TURN;So;0;L;;;;;N;;;;; +1D198;MUSICAL SYMBOL INVERTED TURN;So;0;L;;;;;N;;;;; +1D199;MUSICAL SYMBOL TURN SLASH;So;0;L;;;;;N;;;;; +1D19A;MUSICAL SYMBOL TURN UP;So;0;L;;;;;N;;;;; +1D19B;MUSICAL SYMBOL ORNAMENT STROKE-1;So;0;L;;;;;N;;;;; +1D19C;MUSICAL SYMBOL ORNAMENT STROKE-2;So;0;L;;;;;N;;;;; +1D19D;MUSICAL SYMBOL ORNAMENT STROKE-3;So;0;L;;;;;N;;;;; +1D19E;MUSICAL SYMBOL ORNAMENT STROKE-4;So;0;L;;;;;N;;;;; +1D19F;MUSICAL SYMBOL ORNAMENT STROKE-5;So;0;L;;;;;N;;;;; +1D1A0;MUSICAL SYMBOL ORNAMENT STROKE-6;So;0;L;;;;;N;;;;; +1D1A1;MUSICAL SYMBOL ORNAMENT STROKE-7;So;0;L;;;;;N;;;;; +1D1A2;MUSICAL SYMBOL ORNAMENT STROKE-8;So;0;L;;;;;N;;;;; +1D1A3;MUSICAL SYMBOL ORNAMENT STROKE-9;So;0;L;;;;;N;;;;; +1D1A4;MUSICAL SYMBOL ORNAMENT STROKE-10;So;0;L;;;;;N;;;;; +1D1A5;MUSICAL SYMBOL ORNAMENT STROKE-11;So;0;L;;;;;N;;;;; +1D1A6;MUSICAL SYMBOL HAUPTSTIMME;So;0;L;;;;;N;;;;; +1D1A7;MUSICAL SYMBOL NEBENSTIMME;So;0;L;;;;;N;;;;; +1D1A8;MUSICAL SYMBOL END OF STIMME;So;0;L;;;;;N;;;;; +1D1A9;MUSICAL SYMBOL DEGREE SLASH;So;0;L;;;;;N;;;;; +1D1AA;MUSICAL SYMBOL COMBINING DOWN BOW;Mn;230;NSM;;;;;N;;;;; +1D1AB;MUSICAL SYMBOL COMBINING UP BOW;Mn;230;NSM;;;;;N;;;;; +1D1AC;MUSICAL SYMBOL COMBINING HARMONIC;Mn;230;NSM;;;;;N;;;;; +1D1AD;MUSICAL SYMBOL COMBINING SNAP PIZZICATO;Mn;230;NSM;;;;;N;;;;; +1D1AE;MUSICAL SYMBOL PEDAL MARK;So;0;L;;;;;N;;;;; +1D1AF;MUSICAL SYMBOL PEDAL UP MARK;So;0;L;;;;;N;;;;; +1D1B0;MUSICAL SYMBOL HALF PEDAL MARK;So;0;L;;;;;N;;;;; +1D1B1;MUSICAL SYMBOL GLISSANDO UP;So;0;L;;;;;N;;;;; +1D1B2;MUSICAL SYMBOL GLISSANDO DOWN;So;0;L;;;;;N;;;;; +1D1B3;MUSICAL SYMBOL WITH FINGERNAILS;So;0;L;;;;;N;;;;; +1D1B4;MUSICAL SYMBOL DAMP;So;0;L;;;;;N;;;;; +1D1B5;MUSICAL SYMBOL DAMP ALL;So;0;L;;;;;N;;;;; +1D1B6;MUSICAL SYMBOL MAXIMA;So;0;L;;;;;N;;;;; +1D1B7;MUSICAL SYMBOL LONGA;So;0;L;;;;;N;;;;; +1D1B8;MUSICAL SYMBOL BREVIS;So;0;L;;;;;N;;;;; +1D1B9;MUSICAL SYMBOL SEMIBREVIS WHITE;So;0;L;;;;;N;;;;; +1D1BA;MUSICAL SYMBOL SEMIBREVIS BLACK;So;0;L;;;;;N;;;;; +1D1BB;MUSICAL SYMBOL MINIMA;So;0;L;1D1B9 1D165;;;;N;;;;; +1D1BC;MUSICAL SYMBOL MINIMA BLACK;So;0;L;1D1BA 1D165;;;;N;;;;; +1D1BD;MUSICAL SYMBOL SEMIMINIMA WHITE;So;0;L;1D1BB 1D16E;;;;N;;;;; +1D1BE;MUSICAL SYMBOL SEMIMINIMA BLACK;So;0;L;1D1BC 1D16E;;;;N;;;;; +1D1BF;MUSICAL SYMBOL FUSA WHITE;So;0;L;1D1BB 1D16F;;;;N;;;;; +1D1C0;MUSICAL SYMBOL FUSA BLACK;So;0;L;1D1BC 1D16F;;;;N;;;;; +1D1C1;MUSICAL SYMBOL LONGA PERFECTA REST;So;0;L;;;;;N;;;;; +1D1C2;MUSICAL SYMBOL LONGA IMPERFECTA REST;So;0;L;;;;;N;;;;; +1D1C3;MUSICAL SYMBOL BREVIS REST;So;0;L;;;;;N;;;;; +1D1C4;MUSICAL SYMBOL SEMIBREVIS REST;So;0;L;;;;;N;;;;; +1D1C5;MUSICAL SYMBOL MINIMA REST;So;0;L;;;;;N;;;;; +1D1C6;MUSICAL SYMBOL SEMIMINIMA REST;So;0;L;;;;;N;;;;; +1D1C7;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; +1D1C8;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; +1D1C9;MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; +1D1CA;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA;So;0;L;;;;;N;;;;; +1D1CB;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA;So;0;L;;;;;N;;;;; +1D1CC;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1;So;0;L;;;;;N;;;;; +1D1CD;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2;So;0;L;;;;;N;;;;; +1D1CE;MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3;So;0;L;;;;;N;;;;; +1D1CF;MUSICAL SYMBOL CROIX;So;0;L;;;;;N;;;;; +1D1D0;MUSICAL SYMBOL GREGORIAN C CLEF;So;0;L;;;;;N;;;;; +1D1D1;MUSICAL SYMBOL GREGORIAN F CLEF;So;0;L;;;;;N;;;;; +1D1D2;MUSICAL SYMBOL SQUARE B;So;0;L;;;;;N;;;;; +1D1D3;MUSICAL SYMBOL VIRGA;So;0;L;;;;;N;;;;; +1D1D4;MUSICAL SYMBOL PODATUS;So;0;L;;;;;N;;;;; +1D1D5;MUSICAL SYMBOL CLIVIS;So;0;L;;;;;N;;;;; +1D1D6;MUSICAL SYMBOL SCANDICUS;So;0;L;;;;;N;;;;; +1D1D7;MUSICAL SYMBOL CLIMACUS;So;0;L;;;;;N;;;;; +1D1D8;MUSICAL SYMBOL TORCULUS;So;0;L;;;;;N;;;;; +1D1D9;MUSICAL SYMBOL PORRECTUS;So;0;L;;;;;N;;;;; +1D1DA;MUSICAL SYMBOL PORRECTUS FLEXUS;So;0;L;;;;;N;;;;; +1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;; +1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;; +1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;; +1D1DE;MUSICAL SYMBOL KIEVAN C CLEF;So;0;L;;;;;N;;;;; +1D1DF;MUSICAL SYMBOL KIEVAN END OF PIECE;So;0;L;;;;;N;;;;; +1D1E0;MUSICAL SYMBOL KIEVAN FINAL NOTE;So;0;L;;;;;N;;;;; +1D1E1;MUSICAL SYMBOL KIEVAN RECITATIVE MARK;So;0;L;;;;;N;;;;; +1D1E2;MUSICAL SYMBOL KIEVAN WHOLE NOTE;So;0;L;;;;;N;;;;; +1D1E3;MUSICAL SYMBOL KIEVAN HALF NOTE;So;0;L;;;;;N;;;;; +1D1E4;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM DOWN;So;0;L;;;;;N;;;;; +1D1E5;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM UP;So;0;L;;;;;N;;;;; +1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;; +1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;; +1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;; +1D1E9;MUSICAL SYMBOL SORI;So;0;ON;;;;;N;;;;; +1D1EA;MUSICAL SYMBOL KORON;So;0;ON;;;;;N;;;;; +1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; +1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; +1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;; +1D203;GREEK VOCAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; +1D204;GREEK VOCAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; +1D205;GREEK VOCAL NOTATION SYMBOL-6;So;0;ON;;;;;N;;;;; +1D206;GREEK VOCAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; +1D207;GREEK VOCAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; +1D208;GREEK VOCAL NOTATION SYMBOL-9;So;0;ON;;;;;N;;;;; +1D209;GREEK VOCAL NOTATION SYMBOL-10;So;0;ON;;;;;N;;;;; +1D20A;GREEK VOCAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; +1D20B;GREEK VOCAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; +1D20C;GREEK VOCAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; +1D20D;GREEK VOCAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; +1D20E;GREEK VOCAL NOTATION SYMBOL-15;So;0;ON;;;;;N;;;;; +1D20F;GREEK VOCAL NOTATION SYMBOL-16;So;0;ON;;;;;N;;;;; +1D210;GREEK VOCAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; +1D211;GREEK VOCAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; +1D212;GREEK VOCAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; +1D213;GREEK VOCAL NOTATION SYMBOL-20;So;0;ON;;;;;N;;;;; +1D214;GREEK VOCAL NOTATION SYMBOL-21;So;0;ON;;;;;N;;;;; +1D215;GREEK VOCAL NOTATION SYMBOL-22;So;0;ON;;;;;N;;;;; +1D216;GREEK VOCAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; +1D217;GREEK VOCAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; +1D218;GREEK VOCAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; +1D219;GREEK VOCAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; +1D21A;GREEK VOCAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; +1D21B;GREEK VOCAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; +1D21C;GREEK VOCAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; +1D21D;GREEK INSTRUMENTAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;; +1D21E;GREEK INSTRUMENTAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;; +1D21F;GREEK INSTRUMENTAL NOTATION SYMBOL-4;So;0;ON;;;;;N;;;;; +1D220;GREEK INSTRUMENTAL NOTATION SYMBOL-5;So;0;ON;;;;;N;;;;; +1D221;GREEK INSTRUMENTAL NOTATION SYMBOL-7;So;0;ON;;;;;N;;;;; +1D222;GREEK INSTRUMENTAL NOTATION SYMBOL-8;So;0;ON;;;;;N;;;;; +1D223;GREEK INSTRUMENTAL NOTATION SYMBOL-11;So;0;ON;;;;;N;;;;; +1D224;GREEK INSTRUMENTAL NOTATION SYMBOL-12;So;0;ON;;;;;N;;;;; +1D225;GREEK INSTRUMENTAL NOTATION SYMBOL-13;So;0;ON;;;;;N;;;;; +1D226;GREEK INSTRUMENTAL NOTATION SYMBOL-14;So;0;ON;;;;;N;;;;; +1D227;GREEK INSTRUMENTAL NOTATION SYMBOL-17;So;0;ON;;;;;N;;;;; +1D228;GREEK INSTRUMENTAL NOTATION SYMBOL-18;So;0;ON;;;;;N;;;;; +1D229;GREEK INSTRUMENTAL NOTATION SYMBOL-19;So;0;ON;;;;;N;;;;; +1D22A;GREEK INSTRUMENTAL NOTATION SYMBOL-23;So;0;ON;;;;;N;;;;; +1D22B;GREEK INSTRUMENTAL NOTATION SYMBOL-24;So;0;ON;;;;;N;;;;; +1D22C;GREEK INSTRUMENTAL NOTATION SYMBOL-25;So;0;ON;;;;;N;;;;; +1D22D;GREEK INSTRUMENTAL NOTATION SYMBOL-26;So;0;ON;;;;;N;;;;; +1D22E;GREEK INSTRUMENTAL NOTATION SYMBOL-27;So;0;ON;;;;;N;;;;; +1D22F;GREEK INSTRUMENTAL NOTATION SYMBOL-29;So;0;ON;;;;;N;;;;; +1D230;GREEK INSTRUMENTAL NOTATION SYMBOL-30;So;0;ON;;;;;N;;;;; +1D231;GREEK INSTRUMENTAL NOTATION SYMBOL-32;So;0;ON;;;;;N;;;;; +1D232;GREEK INSTRUMENTAL NOTATION SYMBOL-36;So;0;ON;;;;;N;;;;; +1D233;GREEK INSTRUMENTAL NOTATION SYMBOL-37;So;0;ON;;;;;N;;;;; +1D234;GREEK INSTRUMENTAL NOTATION SYMBOL-38;So;0;ON;;;;;N;;;;; +1D235;GREEK INSTRUMENTAL NOTATION SYMBOL-39;So;0;ON;;;;;N;;;;; +1D236;GREEK INSTRUMENTAL NOTATION SYMBOL-40;So;0;ON;;;;;N;;;;; +1D237;GREEK INSTRUMENTAL NOTATION SYMBOL-42;So;0;ON;;;;;N;;;;; +1D238;GREEK INSTRUMENTAL NOTATION SYMBOL-43;So;0;ON;;;;;N;;;;; +1D239;GREEK INSTRUMENTAL NOTATION SYMBOL-45;So;0;ON;;;;;N;;;;; +1D23A;GREEK INSTRUMENTAL NOTATION SYMBOL-47;So;0;ON;;;;;N;;;;; +1D23B;GREEK INSTRUMENTAL NOTATION SYMBOL-48;So;0;ON;;;;;N;;;;; +1D23C;GREEK INSTRUMENTAL NOTATION SYMBOL-49;So;0;ON;;;;;N;;;;; +1D23D;GREEK INSTRUMENTAL NOTATION SYMBOL-50;So;0;ON;;;;;N;;;;; +1D23E;GREEK INSTRUMENTAL NOTATION SYMBOL-51;So;0;ON;;;;;N;;;;; +1D23F;GREEK INSTRUMENTAL NOTATION SYMBOL-52;So;0;ON;;;;;N;;;;; +1D240;GREEK INSTRUMENTAL NOTATION SYMBOL-53;So;0;ON;;;;;N;;;;; +1D241;GREEK INSTRUMENTAL NOTATION SYMBOL-54;So;0;ON;;;;;N;;;;; +1D242;COMBINING GREEK MUSICAL TRISEME;Mn;230;NSM;;;;;N;;;;; +1D243;COMBINING GREEK MUSICAL TETRASEME;Mn;230;NSM;;;;;N;;;;; +1D244;COMBINING GREEK MUSICAL PENTASEME;Mn;230;NSM;;;;;N;;;;; +1D245;GREEK MUSICAL LEIMMA;So;0;ON;;;;;N;;;;; +1D2C0;KAKTOVIK NUMERAL ZERO;No;0;L;;;;0;N;;;;; +1D2C1;KAKTOVIK NUMERAL ONE;No;0;L;;;;1;N;;;;; +1D2C2;KAKTOVIK NUMERAL TWO;No;0;L;;;;2;N;;;;; +1D2C3;KAKTOVIK NUMERAL THREE;No;0;L;;;;3;N;;;;; +1D2C4;KAKTOVIK NUMERAL FOUR;No;0;L;;;;4;N;;;;; +1D2C5;KAKTOVIK NUMERAL FIVE;No;0;L;;;;5;N;;;;; +1D2C6;KAKTOVIK NUMERAL SIX;No;0;L;;;;6;N;;;;; +1D2C7;KAKTOVIK NUMERAL SEVEN;No;0;L;;;;7;N;;;;; +1D2C8;KAKTOVIK NUMERAL EIGHT;No;0;L;;;;8;N;;;;; +1D2C9;KAKTOVIK NUMERAL NINE;No;0;L;;;;9;N;;;;; +1D2CA;KAKTOVIK NUMERAL TEN;No;0;L;;;;10;N;;;;; +1D2CB;KAKTOVIK NUMERAL ELEVEN;No;0;L;;;;11;N;;;;; +1D2CC;KAKTOVIK NUMERAL TWELVE;No;0;L;;;;12;N;;;;; +1D2CD;KAKTOVIK NUMERAL THIRTEEN;No;0;L;;;;13;N;;;;; +1D2CE;KAKTOVIK NUMERAL FOURTEEN;No;0;L;;;;14;N;;;;; +1D2CF;KAKTOVIK NUMERAL FIFTEEN;No;0;L;;;;15;N;;;;; +1D2D0;KAKTOVIK NUMERAL SIXTEEN;No;0;L;;;;16;N;;;;; +1D2D1;KAKTOVIK NUMERAL SEVENTEEN;No;0;L;;;;17;N;;;;; +1D2D2;KAKTOVIK NUMERAL EIGHTEEN;No;0;L;;;;18;N;;;;; +1D2D3;KAKTOVIK NUMERAL NINETEEN;No;0;L;;;;19;N;;;;; +1D2E0;MAYAN NUMERAL ZERO;No;0;L;;;;0;N;;;;; +1D2E1;MAYAN NUMERAL ONE;No;0;L;;;;1;N;;;;; +1D2E2;MAYAN NUMERAL TWO;No;0;L;;;;2;N;;;;; +1D2E3;MAYAN NUMERAL THREE;No;0;L;;;;3;N;;;;; +1D2E4;MAYAN NUMERAL FOUR;No;0;L;;;;4;N;;;;; +1D2E5;MAYAN NUMERAL FIVE;No;0;L;;;;5;N;;;;; +1D2E6;MAYAN NUMERAL SIX;No;0;L;;;;6;N;;;;; +1D2E7;MAYAN NUMERAL SEVEN;No;0;L;;;;7;N;;;;; +1D2E8;MAYAN NUMERAL EIGHT;No;0;L;;;;8;N;;;;; +1D2E9;MAYAN NUMERAL NINE;No;0;L;;;;9;N;;;;; +1D2EA;MAYAN NUMERAL TEN;No;0;L;;;;10;N;;;;; +1D2EB;MAYAN NUMERAL ELEVEN;No;0;L;;;;11;N;;;;; +1D2EC;MAYAN NUMERAL TWELVE;No;0;L;;;;12;N;;;;; +1D2ED;MAYAN NUMERAL THIRTEEN;No;0;L;;;;13;N;;;;; +1D2EE;MAYAN NUMERAL FOURTEEN;No;0;L;;;;14;N;;;;; +1D2EF;MAYAN NUMERAL FIFTEEN;No;0;L;;;;15;N;;;;; +1D2F0;MAYAN NUMERAL SIXTEEN;No;0;L;;;;16;N;;;;; +1D2F1;MAYAN NUMERAL SEVENTEEN;No;0;L;;;;17;N;;;;; +1D2F2;MAYAN NUMERAL EIGHTEEN;No;0;L;;;;18;N;;;;; +1D2F3;MAYAN NUMERAL NINETEEN;No;0;L;;;;19;N;;;;; +1D300;MONOGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +1D301;DIGRAM FOR HEAVENLY EARTH;So;0;ON;;;;;N;;;;; +1D302;DIGRAM FOR HUMAN EARTH;So;0;ON;;;;;N;;;;; +1D303;DIGRAM FOR EARTHLY HEAVEN;So;0;ON;;;;;N;;;;; +1D304;DIGRAM FOR EARTHLY HUMAN;So;0;ON;;;;;N;;;;; +1D305;DIGRAM FOR EARTH;So;0;ON;;;;;N;;;;; +1D306;TETRAGRAM FOR CENTRE;So;0;ON;;;;;N;;;;; +1D307;TETRAGRAM FOR FULL CIRCLE;So;0;ON;;;;;N;;;;; +1D308;TETRAGRAM FOR MIRED;So;0;ON;;;;;N;;;;; +1D309;TETRAGRAM FOR BARRIER;So;0;ON;;;;;N;;;;; +1D30A;TETRAGRAM FOR KEEPING SMALL;So;0;ON;;;;;N;;;;; +1D30B;TETRAGRAM FOR CONTRARIETY;So;0;ON;;;;;N;;;;; +1D30C;TETRAGRAM FOR ASCENT;So;0;ON;;;;;N;;;;; +1D30D;TETRAGRAM FOR OPPOSITION;So;0;ON;;;;;N;;;;; +1D30E;TETRAGRAM FOR BRANCHING OUT;So;0;ON;;;;;N;;;;; +1D30F;TETRAGRAM FOR DEFECTIVENESS OR DISTORTION;So;0;ON;;;;;N;;;;; +1D310;TETRAGRAM FOR DIVERGENCE;So;0;ON;;;;;N;;;;; +1D311;TETRAGRAM FOR YOUTHFULNESS;So;0;ON;;;;;N;;;;; +1D312;TETRAGRAM FOR INCREASE;So;0;ON;;;;;N;;;;; +1D313;TETRAGRAM FOR PENETRATION;So;0;ON;;;;;N;;;;; +1D314;TETRAGRAM FOR REACH;So;0;ON;;;;;N;;;;; +1D315;TETRAGRAM FOR CONTACT;So;0;ON;;;;;N;;;;; +1D316;TETRAGRAM FOR HOLDING BACK;So;0;ON;;;;;N;;;;; +1D317;TETRAGRAM FOR WAITING;So;0;ON;;;;;N;;;;; +1D318;TETRAGRAM FOR FOLLOWING;So;0;ON;;;;;N;;;;; +1D319;TETRAGRAM FOR ADVANCE;So;0;ON;;;;;N;;;;; +1D31A;TETRAGRAM FOR RELEASE;So;0;ON;;;;;N;;;;; +1D31B;TETRAGRAM FOR RESISTANCE;So;0;ON;;;;;N;;;;; +1D31C;TETRAGRAM FOR EASE;So;0;ON;;;;;N;;;;; +1D31D;TETRAGRAM FOR JOY;So;0;ON;;;;;N;;;;; +1D31E;TETRAGRAM FOR CONTENTION;So;0;ON;;;;;N;;;;; +1D31F;TETRAGRAM FOR ENDEAVOUR;So;0;ON;;;;;N;;;;; +1D320;TETRAGRAM FOR DUTIES;So;0;ON;;;;;N;;;;; +1D321;TETRAGRAM FOR CHANGE;So;0;ON;;;;;N;;;;; +1D322;TETRAGRAM FOR DECISIVENESS;So;0;ON;;;;;N;;;;; +1D323;TETRAGRAM FOR BOLD RESOLUTION;So;0;ON;;;;;N;;;;; +1D324;TETRAGRAM FOR PACKING;So;0;ON;;;;;N;;;;; +1D325;TETRAGRAM FOR LEGION;So;0;ON;;;;;N;;;;; +1D326;TETRAGRAM FOR CLOSENESS;So;0;ON;;;;;N;;;;; +1D327;TETRAGRAM FOR KINSHIP;So;0;ON;;;;;N;;;;; +1D328;TETRAGRAM FOR GATHERING;So;0;ON;;;;;N;;;;; +1D329;TETRAGRAM FOR STRENGTH;So;0;ON;;;;;N;;;;; +1D32A;TETRAGRAM FOR PURITY;So;0;ON;;;;;N;;;;; +1D32B;TETRAGRAM FOR FULLNESS;So;0;ON;;;;;N;;;;; +1D32C;TETRAGRAM FOR RESIDENCE;So;0;ON;;;;;N;;;;; +1D32D;TETRAGRAM FOR LAW OR MODEL;So;0;ON;;;;;N;;;;; +1D32E;TETRAGRAM FOR RESPONSE;So;0;ON;;;;;N;;;;; +1D32F;TETRAGRAM FOR GOING TO MEET;So;0;ON;;;;;N;;;;; +1D330;TETRAGRAM FOR ENCOUNTERS;So;0;ON;;;;;N;;;;; +1D331;TETRAGRAM FOR STOVE;So;0;ON;;;;;N;;;;; +1D332;TETRAGRAM FOR GREATNESS;So;0;ON;;;;;N;;;;; +1D333;TETRAGRAM FOR ENLARGEMENT;So;0;ON;;;;;N;;;;; +1D334;TETRAGRAM FOR PATTERN;So;0;ON;;;;;N;;;;; +1D335;TETRAGRAM FOR RITUAL;So;0;ON;;;;;N;;;;; +1D336;TETRAGRAM FOR FLIGHT;So;0;ON;;;;;N;;;;; +1D337;TETRAGRAM FOR VASTNESS OR WASTING;So;0;ON;;;;;N;;;;; +1D338;TETRAGRAM FOR CONSTANCY;So;0;ON;;;;;N;;;;; +1D339;TETRAGRAM FOR MEASURE;So;0;ON;;;;;N;;;;; +1D33A;TETRAGRAM FOR ETERNITY;So;0;ON;;;;;N;;;;; +1D33B;TETRAGRAM FOR UNITY;So;0;ON;;;;;N;;;;; +1D33C;TETRAGRAM FOR DIMINISHMENT;So;0;ON;;;;;N;;;;; +1D33D;TETRAGRAM FOR CLOSED MOUTH;So;0;ON;;;;;N;;;;; +1D33E;TETRAGRAM FOR GUARDEDNESS;So;0;ON;;;;;N;;;;; +1D33F;TETRAGRAM FOR GATHERING IN;So;0;ON;;;;;N;;;;; +1D340;TETRAGRAM FOR MASSING;So;0;ON;;;;;N;;;;; +1D341;TETRAGRAM FOR ACCUMULATION;So;0;ON;;;;;N;;;;; +1D342;TETRAGRAM FOR EMBELLISHMENT;So;0;ON;;;;;N;;;;; +1D343;TETRAGRAM FOR DOUBT;So;0;ON;;;;;N;;;;; +1D344;TETRAGRAM FOR WATCH;So;0;ON;;;;;N;;;;; +1D345;TETRAGRAM FOR SINKING;So;0;ON;;;;;N;;;;; +1D346;TETRAGRAM FOR INNER;So;0;ON;;;;;N;;;;; +1D347;TETRAGRAM FOR DEPARTURE;So;0;ON;;;;;N;;;;; +1D348;TETRAGRAM FOR DARKENING;So;0;ON;;;;;N;;;;; +1D349;TETRAGRAM FOR DIMMING;So;0;ON;;;;;N;;;;; +1D34A;TETRAGRAM FOR EXHAUSTION;So;0;ON;;;;;N;;;;; +1D34B;TETRAGRAM FOR SEVERANCE;So;0;ON;;;;;N;;;;; +1D34C;TETRAGRAM FOR STOPPAGE;So;0;ON;;;;;N;;;;; +1D34D;TETRAGRAM FOR HARDNESS;So;0;ON;;;;;N;;;;; +1D34E;TETRAGRAM FOR COMPLETION;So;0;ON;;;;;N;;;;; +1D34F;TETRAGRAM FOR CLOSURE;So;0;ON;;;;;N;;;;; +1D350;TETRAGRAM FOR FAILURE;So;0;ON;;;;;N;;;;; +1D351;TETRAGRAM FOR AGGRAVATION;So;0;ON;;;;;N;;;;; +1D352;TETRAGRAM FOR COMPLIANCE;So;0;ON;;;;;N;;;;; +1D353;TETRAGRAM FOR ON THE VERGE;So;0;ON;;;;;N;;;;; +1D354;TETRAGRAM FOR DIFFICULTIES;So;0;ON;;;;;N;;;;; +1D355;TETRAGRAM FOR LABOURING;So;0;ON;;;;;N;;;;; +1D356;TETRAGRAM FOR FOSTERING;So;0;ON;;;;;N;;;;; +1D360;COUNTING ROD UNIT DIGIT ONE;No;0;L;;;;1;N;;;;; +1D361;COUNTING ROD UNIT DIGIT TWO;No;0;L;;;;2;N;;;;; +1D362;COUNTING ROD UNIT DIGIT THREE;No;0;L;;;;3;N;;;;; +1D363;COUNTING ROD UNIT DIGIT FOUR;No;0;L;;;;4;N;;;;; +1D364;COUNTING ROD UNIT DIGIT FIVE;No;0;L;;;;5;N;;;;; +1D365;COUNTING ROD UNIT DIGIT SIX;No;0;L;;;;6;N;;;;; +1D366;COUNTING ROD UNIT DIGIT SEVEN;No;0;L;;;;7;N;;;;; +1D367;COUNTING ROD UNIT DIGIT EIGHT;No;0;L;;;;8;N;;;;; +1D368;COUNTING ROD UNIT DIGIT NINE;No;0;L;;;;9;N;;;;; +1D369;COUNTING ROD TENS DIGIT ONE;No;0;L;;;;10;N;;;;; +1D36A;COUNTING ROD TENS DIGIT TWO;No;0;L;;;;20;N;;;;; +1D36B;COUNTING ROD TENS DIGIT THREE;No;0;L;;;;30;N;;;;; +1D36C;COUNTING ROD TENS DIGIT FOUR;No;0;L;;;;40;N;;;;; +1D36D;COUNTING ROD TENS DIGIT FIVE;No;0;L;;;;50;N;;;;; +1D36E;COUNTING ROD TENS DIGIT SIX;No;0;L;;;;60;N;;;;; +1D36F;COUNTING ROD TENS DIGIT SEVEN;No;0;L;;;;70;N;;;;; +1D370;COUNTING ROD TENS DIGIT EIGHT;No;0;L;;;;80;N;;;;; +1D371;COUNTING ROD TENS DIGIT NINE;No;0;L;;;;90;N;;;;; +1D372;IDEOGRAPHIC TALLY MARK ONE;No;0;L;;;;1;N;;;;; +1D373;IDEOGRAPHIC TALLY MARK TWO;No;0;L;;;;2;N;;;;; +1D374;IDEOGRAPHIC TALLY MARK THREE;No;0;L;;;;3;N;;;;; +1D375;IDEOGRAPHIC TALLY MARK FOUR;No;0;L;;;;4;N;;;;; +1D376;IDEOGRAPHIC TALLY MARK FIVE;No;0;L;;;;5;N;;;;; +1D377;TALLY MARK ONE;No;0;L;;;;1;N;;;;; +1D378;TALLY MARK FIVE;No;0;L;;;;5;N;;;;; +1D400;MATHEMATICAL BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D401;MATHEMATICAL BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D402;MATHEMATICAL BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D403;MATHEMATICAL BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D404;MATHEMATICAL BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D405;MATHEMATICAL BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D406;MATHEMATICAL BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D407;MATHEMATICAL BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D408;MATHEMATICAL BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D409;MATHEMATICAL BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D40A;MATHEMATICAL BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D40B;MATHEMATICAL BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D40C;MATHEMATICAL BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D40D;MATHEMATICAL BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D40E;MATHEMATICAL BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D40F;MATHEMATICAL BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D410;MATHEMATICAL BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D411;MATHEMATICAL BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D412;MATHEMATICAL BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D413;MATHEMATICAL BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D414;MATHEMATICAL BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D415;MATHEMATICAL BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D416;MATHEMATICAL BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D417;MATHEMATICAL BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D418;MATHEMATICAL BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D419;MATHEMATICAL BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D41A;MATHEMATICAL BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D41B;MATHEMATICAL BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D41C;MATHEMATICAL BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D41D;MATHEMATICAL BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D41E;MATHEMATICAL BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D41F;MATHEMATICAL BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D420;MATHEMATICAL BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D421;MATHEMATICAL BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D422;MATHEMATICAL BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D423;MATHEMATICAL BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D424;MATHEMATICAL BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D425;MATHEMATICAL BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D426;MATHEMATICAL BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D427;MATHEMATICAL BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D428;MATHEMATICAL BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D429;MATHEMATICAL BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D42A;MATHEMATICAL BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D42B;MATHEMATICAL BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D42C;MATHEMATICAL BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D42D;MATHEMATICAL BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D42E;MATHEMATICAL BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D42F;MATHEMATICAL BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D430;MATHEMATICAL BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D431;MATHEMATICAL BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D432;MATHEMATICAL BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D433;MATHEMATICAL BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D434;MATHEMATICAL ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D435;MATHEMATICAL ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D436;MATHEMATICAL ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D437;MATHEMATICAL ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D438;MATHEMATICAL ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D439;MATHEMATICAL ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D43A;MATHEMATICAL ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D43B;MATHEMATICAL ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D43C;MATHEMATICAL ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D43D;MATHEMATICAL ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D43E;MATHEMATICAL ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D43F;MATHEMATICAL ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D440;MATHEMATICAL ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D441;MATHEMATICAL ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D442;MATHEMATICAL ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D443;MATHEMATICAL ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D444;MATHEMATICAL ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D445;MATHEMATICAL ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D446;MATHEMATICAL ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D447;MATHEMATICAL ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D448;MATHEMATICAL ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D449;MATHEMATICAL ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D44A;MATHEMATICAL ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D44B;MATHEMATICAL ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D44C;MATHEMATICAL ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D44D;MATHEMATICAL ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D44E;MATHEMATICAL ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D44F;MATHEMATICAL ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D450;MATHEMATICAL ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D451;MATHEMATICAL ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D452;MATHEMATICAL ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D453;MATHEMATICAL ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D454;MATHEMATICAL ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D456;MATHEMATICAL ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D457;MATHEMATICAL ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D458;MATHEMATICAL ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D459;MATHEMATICAL ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D45A;MATHEMATICAL ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D45B;MATHEMATICAL ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D45C;MATHEMATICAL ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D45D;MATHEMATICAL ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D45E;MATHEMATICAL ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D45F;MATHEMATICAL ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D460;MATHEMATICAL ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D461;MATHEMATICAL ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D462;MATHEMATICAL ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D463;MATHEMATICAL ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D464;MATHEMATICAL ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D465;MATHEMATICAL ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D466;MATHEMATICAL ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D467;MATHEMATICAL ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D468;MATHEMATICAL BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D469;MATHEMATICAL BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D46A;MATHEMATICAL BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D46B;MATHEMATICAL BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D46C;MATHEMATICAL BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D46D;MATHEMATICAL BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D46E;MATHEMATICAL BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D46F;MATHEMATICAL BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D470;MATHEMATICAL BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D471;MATHEMATICAL BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D472;MATHEMATICAL BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D473;MATHEMATICAL BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D474;MATHEMATICAL BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D475;MATHEMATICAL BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D476;MATHEMATICAL BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D477;MATHEMATICAL BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D478;MATHEMATICAL BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D479;MATHEMATICAL BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D47A;MATHEMATICAL BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D47B;MATHEMATICAL BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D47C;MATHEMATICAL BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D47D;MATHEMATICAL BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D47E;MATHEMATICAL BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D47F;MATHEMATICAL BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D480;MATHEMATICAL BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D481;MATHEMATICAL BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D482;MATHEMATICAL BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D483;MATHEMATICAL BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D484;MATHEMATICAL BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D485;MATHEMATICAL BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D486;MATHEMATICAL BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D487;MATHEMATICAL BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D488;MATHEMATICAL BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D489;MATHEMATICAL BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D48A;MATHEMATICAL BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D48B;MATHEMATICAL BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D48C;MATHEMATICAL BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D48D;MATHEMATICAL BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D48E;MATHEMATICAL BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D48F;MATHEMATICAL BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D490;MATHEMATICAL BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D491;MATHEMATICAL BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D492;MATHEMATICAL BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D493;MATHEMATICAL BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D494;MATHEMATICAL BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D495;MATHEMATICAL BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D496;MATHEMATICAL BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D497;MATHEMATICAL BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D498;MATHEMATICAL BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D499;MATHEMATICAL BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D49A;MATHEMATICAL BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D49B;MATHEMATICAL BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D49C;MATHEMATICAL SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D49E;MATHEMATICAL SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D49F;MATHEMATICAL SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D4A2;MATHEMATICAL SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D4A5;MATHEMATICAL SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D4A6;MATHEMATICAL SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D4A9;MATHEMATICAL SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D4AA;MATHEMATICAL SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D4AB;MATHEMATICAL SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D4AC;MATHEMATICAL SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D4AE;MATHEMATICAL SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D4AF;MATHEMATICAL SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D4B0;MATHEMATICAL SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D4B1;MATHEMATICAL SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D4B2;MATHEMATICAL SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D4B3;MATHEMATICAL SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D4B4;MATHEMATICAL SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D4B5;MATHEMATICAL SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D4B6;MATHEMATICAL SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D4B7;MATHEMATICAL SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D4B8;MATHEMATICAL SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D4B9;MATHEMATICAL SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D4BB;MATHEMATICAL SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D4BD;MATHEMATICAL SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D4BE;MATHEMATICAL SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D4BF;MATHEMATICAL SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D4C0;MATHEMATICAL SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D4C1;MATHEMATICAL SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D4C2;MATHEMATICAL SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D4C3;MATHEMATICAL SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D4C5;MATHEMATICAL SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D4C6;MATHEMATICAL SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D4C7;MATHEMATICAL SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D4C8;MATHEMATICAL SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D4C9;MATHEMATICAL SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D4CA;MATHEMATICAL SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D4CB;MATHEMATICAL SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D4CC;MATHEMATICAL SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D4CD;MATHEMATICAL SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D4CE;MATHEMATICAL SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D4CF;MATHEMATICAL SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D4D0;MATHEMATICAL BOLD SCRIPT CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D4D1;MATHEMATICAL BOLD SCRIPT CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D4D2;MATHEMATICAL BOLD SCRIPT CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D4D3;MATHEMATICAL BOLD SCRIPT CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D4D4;MATHEMATICAL BOLD SCRIPT CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D4D5;MATHEMATICAL BOLD SCRIPT CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D4D6;MATHEMATICAL BOLD SCRIPT CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D4D7;MATHEMATICAL BOLD SCRIPT CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D4D8;MATHEMATICAL BOLD SCRIPT CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D4D9;MATHEMATICAL BOLD SCRIPT CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D4DA;MATHEMATICAL BOLD SCRIPT CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D4DB;MATHEMATICAL BOLD SCRIPT CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D4DC;MATHEMATICAL BOLD SCRIPT CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D4DD;MATHEMATICAL BOLD SCRIPT CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D4DE;MATHEMATICAL BOLD SCRIPT CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D4DF;MATHEMATICAL BOLD SCRIPT CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D4E0;MATHEMATICAL BOLD SCRIPT CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D4E1;MATHEMATICAL BOLD SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D4E2;MATHEMATICAL BOLD SCRIPT CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D4E3;MATHEMATICAL BOLD SCRIPT CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D4E4;MATHEMATICAL BOLD SCRIPT CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D4E5;MATHEMATICAL BOLD SCRIPT CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D4E6;MATHEMATICAL BOLD SCRIPT CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D4E7;MATHEMATICAL BOLD SCRIPT CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D4E8;MATHEMATICAL BOLD SCRIPT CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D4E9;MATHEMATICAL BOLD SCRIPT CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D4EA;MATHEMATICAL BOLD SCRIPT SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D4EB;MATHEMATICAL BOLD SCRIPT SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D4EC;MATHEMATICAL BOLD SCRIPT SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D4ED;MATHEMATICAL BOLD SCRIPT SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D4EE;MATHEMATICAL BOLD SCRIPT SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D4EF;MATHEMATICAL BOLD SCRIPT SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D4F0;MATHEMATICAL BOLD SCRIPT SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D4F1;MATHEMATICAL BOLD SCRIPT SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D4F2;MATHEMATICAL BOLD SCRIPT SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D4F3;MATHEMATICAL BOLD SCRIPT SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D4F4;MATHEMATICAL BOLD SCRIPT SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D4F5;MATHEMATICAL BOLD SCRIPT SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D4F6;MATHEMATICAL BOLD SCRIPT SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D4F7;MATHEMATICAL BOLD SCRIPT SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D4F8;MATHEMATICAL BOLD SCRIPT SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D4F9;MATHEMATICAL BOLD SCRIPT SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D4FA;MATHEMATICAL BOLD SCRIPT SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D4FB;MATHEMATICAL BOLD SCRIPT SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D4FC;MATHEMATICAL BOLD SCRIPT SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D4FD;MATHEMATICAL BOLD SCRIPT SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D4FE;MATHEMATICAL BOLD SCRIPT SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D4FF;MATHEMATICAL BOLD SCRIPT SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D500;MATHEMATICAL BOLD SCRIPT SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D501;MATHEMATICAL BOLD SCRIPT SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D502;MATHEMATICAL BOLD SCRIPT SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D503;MATHEMATICAL BOLD SCRIPT SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D504;MATHEMATICAL FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D505;MATHEMATICAL FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D507;MATHEMATICAL FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D508;MATHEMATICAL FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D509;MATHEMATICAL FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D50A;MATHEMATICAL FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D50D;MATHEMATICAL FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D50E;MATHEMATICAL FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D50F;MATHEMATICAL FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D510;MATHEMATICAL FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D511;MATHEMATICAL FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D512;MATHEMATICAL FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D513;MATHEMATICAL FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D514;MATHEMATICAL FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D516;MATHEMATICAL FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D517;MATHEMATICAL FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D518;MATHEMATICAL FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D519;MATHEMATICAL FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D51A;MATHEMATICAL FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D51B;MATHEMATICAL FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D51C;MATHEMATICAL FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D51E;MATHEMATICAL FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D51F;MATHEMATICAL FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D520;MATHEMATICAL FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D521;MATHEMATICAL FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D522;MATHEMATICAL FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D523;MATHEMATICAL FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D524;MATHEMATICAL FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D525;MATHEMATICAL FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D526;MATHEMATICAL FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D527;MATHEMATICAL FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D528;MATHEMATICAL FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D529;MATHEMATICAL FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D52A;MATHEMATICAL FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D52B;MATHEMATICAL FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D52C;MATHEMATICAL FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D52D;MATHEMATICAL FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D52E;MATHEMATICAL FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D52F;MATHEMATICAL FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D530;MATHEMATICAL FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D531;MATHEMATICAL FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D532;MATHEMATICAL FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D533;MATHEMATICAL FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D534;MATHEMATICAL FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D535;MATHEMATICAL FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D536;MATHEMATICAL FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D537;MATHEMATICAL FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D538;MATHEMATICAL DOUBLE-STRUCK CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D539;MATHEMATICAL DOUBLE-STRUCK CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D53B;MATHEMATICAL DOUBLE-STRUCK CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D53C;MATHEMATICAL DOUBLE-STRUCK CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D53D;MATHEMATICAL DOUBLE-STRUCK CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D53E;MATHEMATICAL DOUBLE-STRUCK CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D540;MATHEMATICAL DOUBLE-STRUCK CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D541;MATHEMATICAL DOUBLE-STRUCK CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D542;MATHEMATICAL DOUBLE-STRUCK CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D543;MATHEMATICAL DOUBLE-STRUCK CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D544;MATHEMATICAL DOUBLE-STRUCK CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D546;MATHEMATICAL DOUBLE-STRUCK CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D54A;MATHEMATICAL DOUBLE-STRUCK CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D54B;MATHEMATICAL DOUBLE-STRUCK CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D54C;MATHEMATICAL DOUBLE-STRUCK CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D54D;MATHEMATICAL DOUBLE-STRUCK CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D54E;MATHEMATICAL DOUBLE-STRUCK CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D54F;MATHEMATICAL DOUBLE-STRUCK CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D550;MATHEMATICAL DOUBLE-STRUCK CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D552;MATHEMATICAL DOUBLE-STRUCK SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D553;MATHEMATICAL DOUBLE-STRUCK SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D554;MATHEMATICAL DOUBLE-STRUCK SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D555;MATHEMATICAL DOUBLE-STRUCK SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D556;MATHEMATICAL DOUBLE-STRUCK SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D557;MATHEMATICAL DOUBLE-STRUCK SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D558;MATHEMATICAL DOUBLE-STRUCK SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D559;MATHEMATICAL DOUBLE-STRUCK SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D55A;MATHEMATICAL DOUBLE-STRUCK SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D55B;MATHEMATICAL DOUBLE-STRUCK SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D55C;MATHEMATICAL DOUBLE-STRUCK SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D55D;MATHEMATICAL DOUBLE-STRUCK SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D55E;MATHEMATICAL DOUBLE-STRUCK SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D55F;MATHEMATICAL DOUBLE-STRUCK SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D560;MATHEMATICAL DOUBLE-STRUCK SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D561;MATHEMATICAL DOUBLE-STRUCK SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D562;MATHEMATICAL DOUBLE-STRUCK SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D563;MATHEMATICAL DOUBLE-STRUCK SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D564;MATHEMATICAL DOUBLE-STRUCK SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D565;MATHEMATICAL DOUBLE-STRUCK SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D566;MATHEMATICAL DOUBLE-STRUCK SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D567;MATHEMATICAL DOUBLE-STRUCK SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D568;MATHEMATICAL DOUBLE-STRUCK SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D569;MATHEMATICAL DOUBLE-STRUCK SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D56A;MATHEMATICAL DOUBLE-STRUCK SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D56B;MATHEMATICAL DOUBLE-STRUCK SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D56C;MATHEMATICAL BOLD FRAKTUR CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D56D;MATHEMATICAL BOLD FRAKTUR CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D56E;MATHEMATICAL BOLD FRAKTUR CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D56F;MATHEMATICAL BOLD FRAKTUR CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D570;MATHEMATICAL BOLD FRAKTUR CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D571;MATHEMATICAL BOLD FRAKTUR CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D572;MATHEMATICAL BOLD FRAKTUR CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D573;MATHEMATICAL BOLD FRAKTUR CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D574;MATHEMATICAL BOLD FRAKTUR CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D575;MATHEMATICAL BOLD FRAKTUR CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D576;MATHEMATICAL BOLD FRAKTUR CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D577;MATHEMATICAL BOLD FRAKTUR CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D578;MATHEMATICAL BOLD FRAKTUR CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D579;MATHEMATICAL BOLD FRAKTUR CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D57A;MATHEMATICAL BOLD FRAKTUR CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D57B;MATHEMATICAL BOLD FRAKTUR CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D57C;MATHEMATICAL BOLD FRAKTUR CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D57D;MATHEMATICAL BOLD FRAKTUR CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D57E;MATHEMATICAL BOLD FRAKTUR CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D57F;MATHEMATICAL BOLD FRAKTUR CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D580;MATHEMATICAL BOLD FRAKTUR CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D581;MATHEMATICAL BOLD FRAKTUR CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D582;MATHEMATICAL BOLD FRAKTUR CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D583;MATHEMATICAL BOLD FRAKTUR CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D584;MATHEMATICAL BOLD FRAKTUR CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D585;MATHEMATICAL BOLD FRAKTUR CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D586;MATHEMATICAL BOLD FRAKTUR SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D587;MATHEMATICAL BOLD FRAKTUR SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D588;MATHEMATICAL BOLD FRAKTUR SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D589;MATHEMATICAL BOLD FRAKTUR SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D58A;MATHEMATICAL BOLD FRAKTUR SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D58B;MATHEMATICAL BOLD FRAKTUR SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D58C;MATHEMATICAL BOLD FRAKTUR SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D58D;MATHEMATICAL BOLD FRAKTUR SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D58E;MATHEMATICAL BOLD FRAKTUR SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D58F;MATHEMATICAL BOLD FRAKTUR SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D590;MATHEMATICAL BOLD FRAKTUR SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D591;MATHEMATICAL BOLD FRAKTUR SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D592;MATHEMATICAL BOLD FRAKTUR SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D593;MATHEMATICAL BOLD FRAKTUR SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D594;MATHEMATICAL BOLD FRAKTUR SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D595;MATHEMATICAL BOLD FRAKTUR SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D596;MATHEMATICAL BOLD FRAKTUR SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D597;MATHEMATICAL BOLD FRAKTUR SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D598;MATHEMATICAL BOLD FRAKTUR SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D599;MATHEMATICAL BOLD FRAKTUR SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D59A;MATHEMATICAL BOLD FRAKTUR SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D59B;MATHEMATICAL BOLD FRAKTUR SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D59C;MATHEMATICAL BOLD FRAKTUR SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D59D;MATHEMATICAL BOLD FRAKTUR SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D59E;MATHEMATICAL BOLD FRAKTUR SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D59F;MATHEMATICAL BOLD FRAKTUR SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D5A0;MATHEMATICAL SANS-SERIF CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D5A1;MATHEMATICAL SANS-SERIF CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D5A2;MATHEMATICAL SANS-SERIF CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D5A3;MATHEMATICAL SANS-SERIF CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D5A4;MATHEMATICAL SANS-SERIF CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D5A5;MATHEMATICAL SANS-SERIF CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D5A6;MATHEMATICAL SANS-SERIF CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D5A7;MATHEMATICAL SANS-SERIF CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D5A8;MATHEMATICAL SANS-SERIF CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D5A9;MATHEMATICAL SANS-SERIF CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D5AA;MATHEMATICAL SANS-SERIF CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D5AB;MATHEMATICAL SANS-SERIF CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D5AC;MATHEMATICAL SANS-SERIF CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D5AD;MATHEMATICAL SANS-SERIF CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D5AE;MATHEMATICAL SANS-SERIF CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D5AF;MATHEMATICAL SANS-SERIF CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D5B0;MATHEMATICAL SANS-SERIF CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D5B1;MATHEMATICAL SANS-SERIF CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D5B2;MATHEMATICAL SANS-SERIF CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D5B3;MATHEMATICAL SANS-SERIF CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D5B4;MATHEMATICAL SANS-SERIF CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D5B5;MATHEMATICAL SANS-SERIF CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D5B6;MATHEMATICAL SANS-SERIF CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D5B7;MATHEMATICAL SANS-SERIF CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D5B8;MATHEMATICAL SANS-SERIF CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D5B9;MATHEMATICAL SANS-SERIF CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D5BA;MATHEMATICAL SANS-SERIF SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D5BB;MATHEMATICAL SANS-SERIF SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D5BC;MATHEMATICAL SANS-SERIF SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D5BD;MATHEMATICAL SANS-SERIF SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D5BE;MATHEMATICAL SANS-SERIF SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D5BF;MATHEMATICAL SANS-SERIF SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D5C0;MATHEMATICAL SANS-SERIF SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D5C1;MATHEMATICAL SANS-SERIF SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D5C2;MATHEMATICAL SANS-SERIF SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D5C3;MATHEMATICAL SANS-SERIF SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D5C4;MATHEMATICAL SANS-SERIF SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D5C5;MATHEMATICAL SANS-SERIF SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D5C6;MATHEMATICAL SANS-SERIF SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D5C7;MATHEMATICAL SANS-SERIF SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D5C8;MATHEMATICAL SANS-SERIF SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D5C9;MATHEMATICAL SANS-SERIF SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D5CA;MATHEMATICAL SANS-SERIF SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D5CB;MATHEMATICAL SANS-SERIF SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D5CC;MATHEMATICAL SANS-SERIF SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D5CD;MATHEMATICAL SANS-SERIF SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D5CE;MATHEMATICAL SANS-SERIF SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D5CF;MATHEMATICAL SANS-SERIF SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D5D0;MATHEMATICAL SANS-SERIF SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D5D1;MATHEMATICAL SANS-SERIF SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D5D2;MATHEMATICAL SANS-SERIF SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D5D3;MATHEMATICAL SANS-SERIF SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D5D4;MATHEMATICAL SANS-SERIF BOLD CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D5D5;MATHEMATICAL SANS-SERIF BOLD CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D5D6;MATHEMATICAL SANS-SERIF BOLD CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D5D7;MATHEMATICAL SANS-SERIF BOLD CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D5D8;MATHEMATICAL SANS-SERIF BOLD CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D5D9;MATHEMATICAL SANS-SERIF BOLD CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D5DA;MATHEMATICAL SANS-SERIF BOLD CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D5DB;MATHEMATICAL SANS-SERIF BOLD CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D5DC;MATHEMATICAL SANS-SERIF BOLD CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D5DD;MATHEMATICAL SANS-SERIF BOLD CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D5DE;MATHEMATICAL SANS-SERIF BOLD CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D5DF;MATHEMATICAL SANS-SERIF BOLD CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D5E0;MATHEMATICAL SANS-SERIF BOLD CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D5E1;MATHEMATICAL SANS-SERIF BOLD CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D5E2;MATHEMATICAL SANS-SERIF BOLD CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D5E3;MATHEMATICAL SANS-SERIF BOLD CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D5E4;MATHEMATICAL SANS-SERIF BOLD CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D5E5;MATHEMATICAL SANS-SERIF BOLD CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D5E6;MATHEMATICAL SANS-SERIF BOLD CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D5E7;MATHEMATICAL SANS-SERIF BOLD CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D5E8;MATHEMATICAL SANS-SERIF BOLD CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D5E9;MATHEMATICAL SANS-SERIF BOLD CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D5EA;MATHEMATICAL SANS-SERIF BOLD CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D5EB;MATHEMATICAL SANS-SERIF BOLD CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D5EC;MATHEMATICAL SANS-SERIF BOLD CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D5ED;MATHEMATICAL SANS-SERIF BOLD CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D5EE;MATHEMATICAL SANS-SERIF BOLD SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D5EF;MATHEMATICAL SANS-SERIF BOLD SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D5F0;MATHEMATICAL SANS-SERIF BOLD SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D5F1;MATHEMATICAL SANS-SERIF BOLD SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D5F2;MATHEMATICAL SANS-SERIF BOLD SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D5F3;MATHEMATICAL SANS-SERIF BOLD SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D5F4;MATHEMATICAL SANS-SERIF BOLD SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D5F5;MATHEMATICAL SANS-SERIF BOLD SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D5F6;MATHEMATICAL SANS-SERIF BOLD SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D5F7;MATHEMATICAL SANS-SERIF BOLD SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D5F8;MATHEMATICAL SANS-SERIF BOLD SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D5F9;MATHEMATICAL SANS-SERIF BOLD SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D5FA;MATHEMATICAL SANS-SERIF BOLD SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D5FB;MATHEMATICAL SANS-SERIF BOLD SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D5FC;MATHEMATICAL SANS-SERIF BOLD SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D5FD;MATHEMATICAL SANS-SERIF BOLD SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D5FE;MATHEMATICAL SANS-SERIF BOLD SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D5FF;MATHEMATICAL SANS-SERIF BOLD SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D600;MATHEMATICAL SANS-SERIF BOLD SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D601;MATHEMATICAL SANS-SERIF BOLD SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D602;MATHEMATICAL SANS-SERIF BOLD SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D603;MATHEMATICAL SANS-SERIF BOLD SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D604;MATHEMATICAL SANS-SERIF BOLD SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D605;MATHEMATICAL SANS-SERIF BOLD SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D606;MATHEMATICAL SANS-SERIF BOLD SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D607;MATHEMATICAL SANS-SERIF BOLD SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D608;MATHEMATICAL SANS-SERIF ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D609;MATHEMATICAL SANS-SERIF ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D60A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D60B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D60C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D60D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D60E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D60F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D610;MATHEMATICAL SANS-SERIF ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D611;MATHEMATICAL SANS-SERIF ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D612;MATHEMATICAL SANS-SERIF ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D613;MATHEMATICAL SANS-SERIF ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D614;MATHEMATICAL SANS-SERIF ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D615;MATHEMATICAL SANS-SERIF ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D616;MATHEMATICAL SANS-SERIF ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D617;MATHEMATICAL SANS-SERIF ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D618;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D619;MATHEMATICAL SANS-SERIF ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D61A;MATHEMATICAL SANS-SERIF ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D61B;MATHEMATICAL SANS-SERIF ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D61C;MATHEMATICAL SANS-SERIF ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D61D;MATHEMATICAL SANS-SERIF ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D61E;MATHEMATICAL SANS-SERIF ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D61F;MATHEMATICAL SANS-SERIF ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D620;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D621;MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D622;MATHEMATICAL SANS-SERIF ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D623;MATHEMATICAL SANS-SERIF ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D624;MATHEMATICAL SANS-SERIF ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D625;MATHEMATICAL SANS-SERIF ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D626;MATHEMATICAL SANS-SERIF ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D627;MATHEMATICAL SANS-SERIF ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D628;MATHEMATICAL SANS-SERIF ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D629;MATHEMATICAL SANS-SERIF ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D62A;MATHEMATICAL SANS-SERIF ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D62B;MATHEMATICAL SANS-SERIF ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D62C;MATHEMATICAL SANS-SERIF ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D62D;MATHEMATICAL SANS-SERIF ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D62E;MATHEMATICAL SANS-SERIF ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D62F;MATHEMATICAL SANS-SERIF ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D630;MATHEMATICAL SANS-SERIF ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D631;MATHEMATICAL SANS-SERIF ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D632;MATHEMATICAL SANS-SERIF ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D633;MATHEMATICAL SANS-SERIF ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D634;MATHEMATICAL SANS-SERIF ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D635;MATHEMATICAL SANS-SERIF ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D636;MATHEMATICAL SANS-SERIF ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D637;MATHEMATICAL SANS-SERIF ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D638;MATHEMATICAL SANS-SERIF ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D639;MATHEMATICAL SANS-SERIF ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D63A;MATHEMATICAL SANS-SERIF ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D63B;MATHEMATICAL SANS-SERIF ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D63C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D63D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D63E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D63F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D640;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D641;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D642;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D643;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D644;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D645;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D646;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D647;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D648;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D649;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D64A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D64B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D64C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D64D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D64E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D64F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D650;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D651;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D652;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D653;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D654;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D655;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D656;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D657;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D658;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D659;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D65A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D65B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D65C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D65D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D65E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D65F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D660;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D661;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D662;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D663;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D664;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D665;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D666;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D667;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D668;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D669;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D66A;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D66B;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D66C;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D66D;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D66E;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D66F;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D670;MATHEMATICAL MONOSPACE CAPITAL A;Lu;0;L; 0041;;;;N;;;;; +1D671;MATHEMATICAL MONOSPACE CAPITAL B;Lu;0;L; 0042;;;;N;;;;; +1D672;MATHEMATICAL MONOSPACE CAPITAL C;Lu;0;L; 0043;;;;N;;;;; +1D673;MATHEMATICAL MONOSPACE CAPITAL D;Lu;0;L; 0044;;;;N;;;;; +1D674;MATHEMATICAL MONOSPACE CAPITAL E;Lu;0;L; 0045;;;;N;;;;; +1D675;MATHEMATICAL MONOSPACE CAPITAL F;Lu;0;L; 0046;;;;N;;;;; +1D676;MATHEMATICAL MONOSPACE CAPITAL G;Lu;0;L; 0047;;;;N;;;;; +1D677;MATHEMATICAL MONOSPACE CAPITAL H;Lu;0;L; 0048;;;;N;;;;; +1D678;MATHEMATICAL MONOSPACE CAPITAL I;Lu;0;L; 0049;;;;N;;;;; +1D679;MATHEMATICAL MONOSPACE CAPITAL J;Lu;0;L; 004A;;;;N;;;;; +1D67A;MATHEMATICAL MONOSPACE CAPITAL K;Lu;0;L; 004B;;;;N;;;;; +1D67B;MATHEMATICAL MONOSPACE CAPITAL L;Lu;0;L; 004C;;;;N;;;;; +1D67C;MATHEMATICAL MONOSPACE CAPITAL M;Lu;0;L; 004D;;;;N;;;;; +1D67D;MATHEMATICAL MONOSPACE CAPITAL N;Lu;0;L; 004E;;;;N;;;;; +1D67E;MATHEMATICAL MONOSPACE CAPITAL O;Lu;0;L; 004F;;;;N;;;;; +1D67F;MATHEMATICAL MONOSPACE CAPITAL P;Lu;0;L; 0050;;;;N;;;;; +1D680;MATHEMATICAL MONOSPACE CAPITAL Q;Lu;0;L; 0051;;;;N;;;;; +1D681;MATHEMATICAL MONOSPACE CAPITAL R;Lu;0;L; 0052;;;;N;;;;; +1D682;MATHEMATICAL MONOSPACE CAPITAL S;Lu;0;L; 0053;;;;N;;;;; +1D683;MATHEMATICAL MONOSPACE CAPITAL T;Lu;0;L; 0054;;;;N;;;;; +1D684;MATHEMATICAL MONOSPACE CAPITAL U;Lu;0;L; 0055;;;;N;;;;; +1D685;MATHEMATICAL MONOSPACE CAPITAL V;Lu;0;L; 0056;;;;N;;;;; +1D686;MATHEMATICAL MONOSPACE CAPITAL W;Lu;0;L; 0057;;;;N;;;;; +1D687;MATHEMATICAL MONOSPACE CAPITAL X;Lu;0;L; 0058;;;;N;;;;; +1D688;MATHEMATICAL MONOSPACE CAPITAL Y;Lu;0;L; 0059;;;;N;;;;; +1D689;MATHEMATICAL MONOSPACE CAPITAL Z;Lu;0;L; 005A;;;;N;;;;; +1D68A;MATHEMATICAL MONOSPACE SMALL A;Ll;0;L; 0061;;;;N;;;;; +1D68B;MATHEMATICAL MONOSPACE SMALL B;Ll;0;L; 0062;;;;N;;;;; +1D68C;MATHEMATICAL MONOSPACE SMALL C;Ll;0;L; 0063;;;;N;;;;; +1D68D;MATHEMATICAL MONOSPACE SMALL D;Ll;0;L; 0064;;;;N;;;;; +1D68E;MATHEMATICAL MONOSPACE SMALL E;Ll;0;L; 0065;;;;N;;;;; +1D68F;MATHEMATICAL MONOSPACE SMALL F;Ll;0;L; 0066;;;;N;;;;; +1D690;MATHEMATICAL MONOSPACE SMALL G;Ll;0;L; 0067;;;;N;;;;; +1D691;MATHEMATICAL MONOSPACE SMALL H;Ll;0;L; 0068;;;;N;;;;; +1D692;MATHEMATICAL MONOSPACE SMALL I;Ll;0;L; 0069;;;;N;;;;; +1D693;MATHEMATICAL MONOSPACE SMALL J;Ll;0;L; 006A;;;;N;;;;; +1D694;MATHEMATICAL MONOSPACE SMALL K;Ll;0;L; 006B;;;;N;;;;; +1D695;MATHEMATICAL MONOSPACE SMALL L;Ll;0;L; 006C;;;;N;;;;; +1D696;MATHEMATICAL MONOSPACE SMALL M;Ll;0;L; 006D;;;;N;;;;; +1D697;MATHEMATICAL MONOSPACE SMALL N;Ll;0;L; 006E;;;;N;;;;; +1D698;MATHEMATICAL MONOSPACE SMALL O;Ll;0;L; 006F;;;;N;;;;; +1D699;MATHEMATICAL MONOSPACE SMALL P;Ll;0;L; 0070;;;;N;;;;; +1D69A;MATHEMATICAL MONOSPACE SMALL Q;Ll;0;L; 0071;;;;N;;;;; +1D69B;MATHEMATICAL MONOSPACE SMALL R;Ll;0;L; 0072;;;;N;;;;; +1D69C;MATHEMATICAL MONOSPACE SMALL S;Ll;0;L; 0073;;;;N;;;;; +1D69D;MATHEMATICAL MONOSPACE SMALL T;Ll;0;L; 0074;;;;N;;;;; +1D69E;MATHEMATICAL MONOSPACE SMALL U;Ll;0;L; 0075;;;;N;;;;; +1D69F;MATHEMATICAL MONOSPACE SMALL V;Ll;0;L; 0076;;;;N;;;;; +1D6A0;MATHEMATICAL MONOSPACE SMALL W;Ll;0;L; 0077;;;;N;;;;; +1D6A1;MATHEMATICAL MONOSPACE SMALL X;Ll;0;L; 0078;;;;N;;;;; +1D6A2;MATHEMATICAL MONOSPACE SMALL Y;Ll;0;L; 0079;;;;N;;;;; +1D6A3;MATHEMATICAL MONOSPACE SMALL Z;Ll;0;L; 007A;;;;N;;;;; +1D6A4;MATHEMATICAL ITALIC SMALL DOTLESS I;Ll;0;L; 0131;;;;N;;;;; +1D6A5;MATHEMATICAL ITALIC SMALL DOTLESS J;Ll;0;L; 0237;;;;N;;;;; +1D6A8;MATHEMATICAL BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; +1D6A9;MATHEMATICAL BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; +1D6AA;MATHEMATICAL BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +1D6AB;MATHEMATICAL BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; +1D6AC;MATHEMATICAL BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; +1D6AD;MATHEMATICAL BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; +1D6AE;MATHEMATICAL BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; +1D6AF;MATHEMATICAL BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; +1D6B0;MATHEMATICAL BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; +1D6B1;MATHEMATICAL BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; +1D6B2;MATHEMATICAL BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; +1D6B3;MATHEMATICAL BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; +1D6B4;MATHEMATICAL BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; +1D6B5;MATHEMATICAL BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; +1D6B6;MATHEMATICAL BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; +1D6B7;MATHEMATICAL BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +1D6B8;MATHEMATICAL BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; +1D6B9;MATHEMATICAL BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; +1D6BA;MATHEMATICAL BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; +1D6BB;MATHEMATICAL BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; +1D6BC;MATHEMATICAL BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; +1D6BD;MATHEMATICAL BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; +1D6BE;MATHEMATICAL BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; +1D6BF;MATHEMATICAL BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; +1D6C0;MATHEMATICAL BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; +1D6C1;MATHEMATICAL BOLD NABLA;Sm;0;ON; 2207;;;;N;;;;; +1D6C2;MATHEMATICAL BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; +1D6C3;MATHEMATICAL BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; +1D6C4;MATHEMATICAL BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +1D6C5;MATHEMATICAL BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; +1D6C6;MATHEMATICAL BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; +1D6C7;MATHEMATICAL BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; +1D6C8;MATHEMATICAL BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; +1D6C9;MATHEMATICAL BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; +1D6CA;MATHEMATICAL BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; +1D6CB;MATHEMATICAL BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; +1D6CC;MATHEMATICAL BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; +1D6CD;MATHEMATICAL BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; +1D6CE;MATHEMATICAL BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; +1D6CF;MATHEMATICAL BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; +1D6D0;MATHEMATICAL BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; +1D6D1;MATHEMATICAL BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +1D6D2;MATHEMATICAL BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; +1D6D3;MATHEMATICAL BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; +1D6D4;MATHEMATICAL BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; +1D6D5;MATHEMATICAL BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; +1D6D6;MATHEMATICAL BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; +1D6D7;MATHEMATICAL BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; +1D6D8;MATHEMATICAL BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; +1D6D9;MATHEMATICAL BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; +1D6DA;MATHEMATICAL BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; +1D6DB;MATHEMATICAL BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; +1D6DC;MATHEMATICAL BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; +1D6DD;MATHEMATICAL BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; +1D6DE;MATHEMATICAL BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; +1D6DF;MATHEMATICAL BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; +1D6E0;MATHEMATICAL BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; +1D6E1;MATHEMATICAL BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; +1D6E2;MATHEMATICAL ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; +1D6E3;MATHEMATICAL ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; +1D6E4;MATHEMATICAL ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +1D6E5;MATHEMATICAL ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; +1D6E6;MATHEMATICAL ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; +1D6E7;MATHEMATICAL ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; +1D6E8;MATHEMATICAL ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; +1D6E9;MATHEMATICAL ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; +1D6EA;MATHEMATICAL ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; +1D6EB;MATHEMATICAL ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; +1D6EC;MATHEMATICAL ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; +1D6ED;MATHEMATICAL ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; +1D6EE;MATHEMATICAL ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; +1D6EF;MATHEMATICAL ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; +1D6F0;MATHEMATICAL ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; +1D6F1;MATHEMATICAL ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +1D6F2;MATHEMATICAL ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; +1D6F3;MATHEMATICAL ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; +1D6F4;MATHEMATICAL ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; +1D6F5;MATHEMATICAL ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; +1D6F6;MATHEMATICAL ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; +1D6F7;MATHEMATICAL ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; +1D6F8;MATHEMATICAL ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; +1D6F9;MATHEMATICAL ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; +1D6FA;MATHEMATICAL ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; +1D6FB;MATHEMATICAL ITALIC NABLA;Sm;0;ON; 2207;;;;N;;;;; +1D6FC;MATHEMATICAL ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; +1D6FD;MATHEMATICAL ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; +1D6FE;MATHEMATICAL ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +1D6FF;MATHEMATICAL ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; +1D700;MATHEMATICAL ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; +1D701;MATHEMATICAL ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; +1D702;MATHEMATICAL ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; +1D703;MATHEMATICAL ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; +1D704;MATHEMATICAL ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; +1D705;MATHEMATICAL ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; +1D706;MATHEMATICAL ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; +1D707;MATHEMATICAL ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; +1D708;MATHEMATICAL ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; +1D709;MATHEMATICAL ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; +1D70A;MATHEMATICAL ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; +1D70B;MATHEMATICAL ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +1D70C;MATHEMATICAL ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; +1D70D;MATHEMATICAL ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; +1D70E;MATHEMATICAL ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; +1D70F;MATHEMATICAL ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; +1D710;MATHEMATICAL ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; +1D711;MATHEMATICAL ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; +1D712;MATHEMATICAL ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; +1D713;MATHEMATICAL ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; +1D714;MATHEMATICAL ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; +1D715;MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; +1D716;MATHEMATICAL ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; +1D717;MATHEMATICAL ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; +1D718;MATHEMATICAL ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; +1D719;MATHEMATICAL ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; +1D71A;MATHEMATICAL ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; +1D71B;MATHEMATICAL ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; +1D71C;MATHEMATICAL BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; +1D71D;MATHEMATICAL BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; +1D71E;MATHEMATICAL BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +1D71F;MATHEMATICAL BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; +1D720;MATHEMATICAL BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; +1D721;MATHEMATICAL BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; +1D722;MATHEMATICAL BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; +1D723;MATHEMATICAL BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; +1D724;MATHEMATICAL BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; +1D725;MATHEMATICAL BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; +1D726;MATHEMATICAL BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; +1D727;MATHEMATICAL BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; +1D728;MATHEMATICAL BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; +1D729;MATHEMATICAL BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; +1D72A;MATHEMATICAL BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; +1D72B;MATHEMATICAL BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +1D72C;MATHEMATICAL BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; +1D72D;MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; +1D72E;MATHEMATICAL BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; +1D72F;MATHEMATICAL BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; +1D730;MATHEMATICAL BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; +1D731;MATHEMATICAL BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; +1D732;MATHEMATICAL BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; +1D733;MATHEMATICAL BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; +1D734;MATHEMATICAL BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; +1D735;MATHEMATICAL BOLD ITALIC NABLA;Sm;0;ON; 2207;;;;N;;;;; +1D736;MATHEMATICAL BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; +1D737;MATHEMATICAL BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; +1D738;MATHEMATICAL BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +1D739;MATHEMATICAL BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; +1D73A;MATHEMATICAL BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; +1D73B;MATHEMATICAL BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; +1D73C;MATHEMATICAL BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; +1D73D;MATHEMATICAL BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; +1D73E;MATHEMATICAL BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; +1D73F;MATHEMATICAL BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; +1D740;MATHEMATICAL BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; +1D741;MATHEMATICAL BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; +1D742;MATHEMATICAL BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; +1D743;MATHEMATICAL BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; +1D744;MATHEMATICAL BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; +1D745;MATHEMATICAL BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +1D746;MATHEMATICAL BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; +1D747;MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; +1D748;MATHEMATICAL BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; +1D749;MATHEMATICAL BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; +1D74A;MATHEMATICAL BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; +1D74B;MATHEMATICAL BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; +1D74C;MATHEMATICAL BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; +1D74D;MATHEMATICAL BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; +1D74E;MATHEMATICAL BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; +1D74F;MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; +1D750;MATHEMATICAL BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; +1D751;MATHEMATICAL BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; +1D752;MATHEMATICAL BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; +1D753;MATHEMATICAL BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; +1D754;MATHEMATICAL BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; +1D755;MATHEMATICAL BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; +1D756;MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; +1D757;MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; +1D758;MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +1D759;MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; +1D75A;MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; +1D75B;MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; +1D75C;MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; +1D75D;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; +1D75E;MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; +1D75F;MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; +1D760;MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; +1D761;MATHEMATICAL SANS-SERIF BOLD CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; +1D762;MATHEMATICAL SANS-SERIF BOLD CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; +1D763;MATHEMATICAL SANS-SERIF BOLD CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; +1D764;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; +1D765;MATHEMATICAL SANS-SERIF BOLD CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +1D766;MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; +1D767;MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; +1D768;MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; +1D769;MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; +1D76A;MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; +1D76B;MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; +1D76C;MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; +1D76D;MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; +1D76E;MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; +1D76F;MATHEMATICAL SANS-SERIF BOLD NABLA;Sm;0;ON; 2207;;;;N;;;;; +1D770;MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; +1D771;MATHEMATICAL SANS-SERIF BOLD SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; +1D772;MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +1D773;MATHEMATICAL SANS-SERIF BOLD SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; +1D774;MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; +1D775;MATHEMATICAL SANS-SERIF BOLD SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; +1D776;MATHEMATICAL SANS-SERIF BOLD SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; +1D777;MATHEMATICAL SANS-SERIF BOLD SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; +1D778;MATHEMATICAL SANS-SERIF BOLD SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; +1D779;MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; +1D77A;MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; +1D77B;MATHEMATICAL SANS-SERIF BOLD SMALL MU;Ll;0;L; 03BC;;;;N;;;;; +1D77C;MATHEMATICAL SANS-SERIF BOLD SMALL NU;Ll;0;L; 03BD;;;;N;;;;; +1D77D;MATHEMATICAL SANS-SERIF BOLD SMALL XI;Ll;0;L; 03BE;;;;N;;;;; +1D77E;MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; +1D77F;MATHEMATICAL SANS-SERIF BOLD SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +1D780;MATHEMATICAL SANS-SERIF BOLD SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; +1D781;MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; +1D782;MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; +1D783;MATHEMATICAL SANS-SERIF BOLD SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; +1D784;MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; +1D785;MATHEMATICAL SANS-SERIF BOLD SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; +1D786;MATHEMATICAL SANS-SERIF BOLD SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; +1D787;MATHEMATICAL SANS-SERIF BOLD SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; +1D788;MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; +1D789;MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; +1D78A;MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; +1D78B;MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; +1D78C;MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; +1D78D;MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; +1D78E;MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; +1D78F;MATHEMATICAL SANS-SERIF BOLD PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; +1D790;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA;Lu;0;L; 0391;;;;N;;;;; +1D791;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA;Lu;0;L; 0392;;;;N;;;;; +1D792;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA;Lu;0;L; 0393;;;;N;;;;; +1D793;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA;Lu;0;L; 0394;;;;N;;;;; +1D794;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON;Lu;0;L; 0395;;;;N;;;;; +1D795;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA;Lu;0;L; 0396;;;;N;;;;; +1D796;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA;Lu;0;L; 0397;;;;N;;;;; +1D797;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA;Lu;0;L; 0398;;;;N;;;;; +1D798;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA;Lu;0;L; 0399;;;;N;;;;; +1D799;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA;Lu;0;L; 039A;;;;N;;;;; +1D79A;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA;Lu;0;L; 039B;;;;N;;;;; +1D79B;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU;Lu;0;L; 039C;;;;N;;;;; +1D79C;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU;Lu;0;L; 039D;;;;N;;;;; +1D79D;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI;Lu;0;L; 039E;;;;N;;;;; +1D79E;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON;Lu;0;L; 039F;;;;N;;;;; +1D79F;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI;Lu;0;L; 03A0;;;;N;;;;; +1D7A0;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO;Lu;0;L; 03A1;;;;N;;;;; +1D7A1;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL;Lu;0;L; 03F4;;;;N;;;;; +1D7A2;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA;Lu;0;L; 03A3;;;;N;;;;; +1D7A3;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU;Lu;0;L; 03A4;;;;N;;;;; +1D7A4;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON;Lu;0;L; 03A5;;;;N;;;;; +1D7A5;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI;Lu;0;L; 03A6;;;;N;;;;; +1D7A6;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI;Lu;0;L; 03A7;;;;N;;;;; +1D7A7;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI;Lu;0;L; 03A8;;;;N;;;;; +1D7A8;MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA;Lu;0;L; 03A9;;;;N;;;;; +1D7A9;MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA;Sm;0;ON; 2207;;;;N;;;;; +1D7AA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA;Ll;0;L; 03B1;;;;N;;;;; +1D7AB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA;Ll;0;L; 03B2;;;;N;;;;; +1D7AC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA;Ll;0;L; 03B3;;;;N;;;;; +1D7AD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA;Ll;0;L; 03B4;;;;N;;;;; +1D7AE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON;Ll;0;L; 03B5;;;;N;;;;; +1D7AF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA;Ll;0;L; 03B6;;;;N;;;;; +1D7B0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA;Ll;0;L; 03B7;;;;N;;;;; +1D7B1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA;Ll;0;L; 03B8;;;;N;;;;; +1D7B2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA;Ll;0;L; 03B9;;;;N;;;;; +1D7B3;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA;Ll;0;L; 03BA;;;;N;;;;; +1D7B4;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA;Ll;0;L; 03BB;;;;N;;;;; +1D7B5;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU;Ll;0;L; 03BC;;;;N;;;;; +1D7B6;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU;Ll;0;L; 03BD;;;;N;;;;; +1D7B7;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI;Ll;0;L; 03BE;;;;N;;;;; +1D7B8;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON;Ll;0;L; 03BF;;;;N;;;;; +1D7B9;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI;Ll;0;L; 03C0;;;;N;;;;; +1D7BA;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO;Ll;0;L; 03C1;;;;N;;;;; +1D7BB;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA;Ll;0;L; 03C2;;;;N;;;;; +1D7BC;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA;Ll;0;L; 03C3;;;;N;;;;; +1D7BD;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU;Ll;0;L; 03C4;;;;N;;;;; +1D7BE;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON;Ll;0;L; 03C5;;;;N;;;;; +1D7BF;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI;Ll;0;L; 03C6;;;;N;;;;; +1D7C0;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI;Ll;0;L; 03C7;;;;N;;;;; +1D7C1;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI;Ll;0;L; 03C8;;;;N;;;;; +1D7C2;MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA;Ll;0;L; 03C9;;;;N;;;;; +1D7C3;MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL;Sm;0;ON; 2202;;;;Y;;;;; +1D7C4;MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL;Ll;0;L; 03F5;;;;N;;;;; +1D7C5;MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL;Ll;0;L; 03D1;;;;N;;;;; +1D7C6;MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL;Ll;0;L; 03F0;;;;N;;;;; +1D7C7;MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL;Ll;0;L; 03D5;;;;N;;;;; +1D7C8;MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL;Ll;0;L; 03F1;;;;N;;;;; +1D7C9;MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL;Ll;0;L; 03D6;;;;N;;;;; +1D7CA;MATHEMATICAL BOLD CAPITAL DIGAMMA;Lu;0;L; 03DC;;;;N;;;;; +1D7CB;MATHEMATICAL BOLD SMALL DIGAMMA;Ll;0;L; 03DD;;;;N;;;;; +1D7CE;MATHEMATICAL BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1D7CF;MATHEMATICAL BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1D7D0;MATHEMATICAL BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1D7D1;MATHEMATICAL BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1D7D2;MATHEMATICAL BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1D7D3;MATHEMATICAL BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1D7D4;MATHEMATICAL BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1D7D5;MATHEMATICAL BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1D7D6;MATHEMATICAL BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1D7D7;MATHEMATICAL BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1D7D8;MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1D7D9;MATHEMATICAL DOUBLE-STRUCK DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1D7DA;MATHEMATICAL DOUBLE-STRUCK DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1D7DB;MATHEMATICAL DOUBLE-STRUCK DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1D7DC;MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1D7DD;MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1D7DE;MATHEMATICAL DOUBLE-STRUCK DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1D7DF;MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1D7E0;MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1D7E1;MATHEMATICAL DOUBLE-STRUCK DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1D7E2;MATHEMATICAL SANS-SERIF DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1D7E3;MATHEMATICAL SANS-SERIF DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1D7E4;MATHEMATICAL SANS-SERIF DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1D7E5;MATHEMATICAL SANS-SERIF DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1D7E6;MATHEMATICAL SANS-SERIF DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1D7E7;MATHEMATICAL SANS-SERIF DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1D7E8;MATHEMATICAL SANS-SERIF DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1D7E9;MATHEMATICAL SANS-SERIF DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1D7EA;MATHEMATICAL SANS-SERIF DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1D7EB;MATHEMATICAL SANS-SERIF DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1D7EC;MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1D7ED;MATHEMATICAL SANS-SERIF BOLD DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1D7EE;MATHEMATICAL SANS-SERIF BOLD DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1D7EF;MATHEMATICAL SANS-SERIF BOLD DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1D7F0;MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1D7F1;MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1D7F2;MATHEMATICAL SANS-SERIF BOLD DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1D7F3;MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1D7F4;MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1D7F5;MATHEMATICAL SANS-SERIF BOLD DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1D7F6;MATHEMATICAL MONOSPACE DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1D7F7;MATHEMATICAL MONOSPACE DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1D7F8;MATHEMATICAL MONOSPACE DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1D7F9;MATHEMATICAL MONOSPACE DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1D7FA;MATHEMATICAL MONOSPACE DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1D7FB;MATHEMATICAL MONOSPACE DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1D7FC;MATHEMATICAL MONOSPACE DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1D800;SIGNWRITING HAND-FIST INDEX;So;0;L;;;;;N;;;;; +1D801;SIGNWRITING HAND-CIRCLE INDEX;So;0;L;;;;;N;;;;; +1D802;SIGNWRITING HAND-CUP INDEX;So;0;L;;;;;N;;;;; +1D803;SIGNWRITING HAND-OVAL INDEX;So;0;L;;;;;N;;;;; +1D804;SIGNWRITING HAND-HINGE INDEX;So;0;L;;;;;N;;;;; +1D805;SIGNWRITING HAND-ANGLE INDEX;So;0;L;;;;;N;;;;; +1D806;SIGNWRITING HAND-FIST INDEX BENT;So;0;L;;;;;N;;;;; +1D807;SIGNWRITING HAND-CIRCLE INDEX BENT;So;0;L;;;;;N;;;;; +1D808;SIGNWRITING HAND-FIST THUMB UNDER INDEX BENT;So;0;L;;;;;N;;;;; +1D809;SIGNWRITING HAND-FIST INDEX RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D80A;SIGNWRITING HAND-FIST INDEX CUPPED;So;0;L;;;;;N;;;;; +1D80B;SIGNWRITING HAND-FIST INDEX HINGED;So;0;L;;;;;N;;;;; +1D80C;SIGNWRITING HAND-FIST INDEX HINGED LOW;So;0;L;;;;;N;;;;; +1D80D;SIGNWRITING HAND-CIRCLE INDEX HINGE;So;0;L;;;;;N;;;;; +1D80E;SIGNWRITING HAND-FIST INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D80F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D810;SIGNWRITING HAND-FIST INDEX MIDDLE BENT;So;0;L;;;;;N;;;;; +1D811;SIGNWRITING HAND-FIST INDEX MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D812;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D813;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D814;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP;So;0;L;;;;;N;;;;; +1D815;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED;So;0;L;;;;;N;;;;; +1D816;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED INDEX BENT;So;0;L;;;;;N;;;;; +1D817;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED MIDDLE BENT;So;0;L;;;;;N;;;;; +1D818;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED;So;0;L;;;;;N;;;;; +1D819;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED;So;0;L;;;;;N;;;;; +1D81A;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; +1D81B;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;; +1D81C;SIGNWRITING HAND-FIST MIDDLE BENT OVER INDEX;So;0;L;;;;;N;;;;; +1D81D;SIGNWRITING HAND-FIST INDEX BENT OVER MIDDLE;So;0;L;;;;;N;;;;; +1D81E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D81F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D820;SIGNWRITING HAND-FIST INDEX MIDDLE STRAIGHT THUMB BENT;So;0;L;;;;;N;;;;; +1D821;SIGNWRITING HAND-FIST INDEX MIDDLE BENT THUMB STRAIGHT;So;0;L;;;;;N;;;;; +1D822;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB BENT;So;0;L;;;;;N;;;;; +1D823;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED SPREAD THUMB SIDE;So;0;L;;;;;N;;;;; +1D824;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D825;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB CONJOINED;So;0;L;;;;;N;;;;; +1D826;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; +1D827;SIGNWRITING HAND-FIST INDEX MIDDLE UP SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; +1D828;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CUPPED;So;0;L;;;;;N;;;;; +1D829;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CIRCLED;So;0;L;;;;;N;;;;; +1D82A;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HOOKED;So;0;L;;;;;N;;;;; +1D82B;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HINGED;So;0;L;;;;;N;;;;; +1D82C;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE STRAIGHT;So;0;L;;;;;N;;;;; +1D82D;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE;So;0;L;;;;;N;;;;; +1D82E;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; +1D82F;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D830;SIGNWRITING HAND-FIST MIDDLE THUMB HOOKED INDEX UP;So;0;L;;;;;N;;;;; +1D831;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE UP;So;0;L;;;;;N;;;;; +1D832;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D833;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED THUMB SIDE;So;0;L;;;;;N;;;;; +1D834;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB FORWARD;So;0;L;;;;;N;;;;; +1D835;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED THUMB FORWARD;So;0;L;;;;;N;;;;; +1D836;SIGNWRITING HAND-FIST MIDDLE THUMB CUPPED INDEX UP;So;0;L;;;;;N;;;;; +1D837;SIGNWRITING HAND-FIST INDEX THUMB CUPPED MIDDLE UP;So;0;L;;;;;N;;;;; +1D838;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX UP;So;0;L;;;;;N;;;;; +1D839;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX HINGED;So;0;L;;;;;N;;;;; +1D83A;SIGNWRITING HAND-FIST INDEX THUMB ANGLED OUT MIDDLE UP;So;0;L;;;;;N;;;;; +1D83B;SIGNWRITING HAND-FIST INDEX THUMB ANGLED IN MIDDLE UP;So;0;L;;;;;N;;;;; +1D83C;SIGNWRITING HAND-FIST INDEX THUMB CIRCLED MIDDLE UP;So;0;L;;;;;N;;;;; +1D83D;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CONJOINED HINGED;So;0;L;;;;;N;;;;; +1D83E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED OUT;So;0;L;;;;;N;;;;; +1D83F;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED;So;0;L;;;;;N;;;;; +1D840;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX UP;So;0;L;;;;;N;;;;; +1D841;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX CROSSED;So;0;L;;;;;N;;;;; +1D842;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED INDEX UP;So;0;L;;;;;N;;;;; +1D843;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE HINGED;So;0;L;;;;;N;;;;; +1D844;SIGNWRITING HAND-FLAT FOUR FINGERS;So;0;L;;;;;N;;;;; +1D845;SIGNWRITING HAND-FLAT FOUR FINGERS BENT;So;0;L;;;;;N;;;;; +1D846;SIGNWRITING HAND-FLAT FOUR FINGERS HINGED;So;0;L;;;;;N;;;;; +1D847;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D848;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED SPLIT;So;0;L;;;;;N;;;;; +1D849;SIGNWRITING HAND-CLAW FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D84A;SIGNWRITING HAND-FIST FOUR FINGERS CONJOINED BENT;So;0;L;;;;;N;;;;; +1D84B;SIGNWRITING HAND-HINGE FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;; +1D84C;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D84D;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D84E;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; +1D84F;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;; +1D850;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; +1D851;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;; +1D852;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;; +1D853;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D854;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; +1D855;SIGNWRITING HAND-HINGE FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;; +1D856;SIGNWRITING HAND-OVAL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;; +1D857;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED;So;0;L;;;;;N;;;;; +1D858;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED THUMB SIDE;So;0;L;;;;;N;;;;; +1D859;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED NO THUMB;So;0;L;;;;;N;;;;; +1D85A;SIGNWRITING HAND-FLAT;So;0;L;;;;;N;;;;; +1D85B;SIGNWRITING HAND-FLAT BETWEEN PALM FACINGS;So;0;L;;;;;N;;;;; +1D85C;SIGNWRITING HAND-FLAT HEEL;So;0;L;;;;;N;;;;; +1D85D;SIGNWRITING HAND-FLAT THUMB SIDE;So;0;L;;;;;N;;;;; +1D85E;SIGNWRITING HAND-FLAT HEEL THUMB SIDE;So;0;L;;;;;N;;;;; +1D85F;SIGNWRITING HAND-FLAT THUMB BENT;So;0;L;;;;;N;;;;; +1D860;SIGNWRITING HAND-FLAT THUMB FORWARD;So;0;L;;;;;N;;;;; +1D861;SIGNWRITING HAND-FLAT SPLIT INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D862;SIGNWRITING HAND-FLAT SPLIT CENTRE;So;0;L;;;;;N;;;;; +1D863;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE;So;0;L;;;;;N;;;;; +1D864;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D865;SIGNWRITING HAND-FLAT SPLIT LITTLE;So;0;L;;;;;N;;;;; +1D866;SIGNWRITING HAND-CLAW;So;0;L;;;;;N;;;;; +1D867;SIGNWRITING HAND-CLAW THUMB SIDE;So;0;L;;;;;N;;;;; +1D868;SIGNWRITING HAND-CLAW NO THUMB;So;0;L;;;;;N;;;;; +1D869;SIGNWRITING HAND-CLAW THUMB FORWARD;So;0;L;;;;;N;;;;; +1D86A;SIGNWRITING HAND-HOOK CURLICUE;So;0;L;;;;;N;;;;; +1D86B;SIGNWRITING HAND-HOOK;So;0;L;;;;;N;;;;; +1D86C;SIGNWRITING HAND-CUP OPEN;So;0;L;;;;;N;;;;; +1D86D;SIGNWRITING HAND-CUP;So;0;L;;;;;N;;;;; +1D86E;SIGNWRITING HAND-CUP OPEN THUMB SIDE;So;0;L;;;;;N;;;;; +1D86F;SIGNWRITING HAND-CUP THUMB SIDE;So;0;L;;;;;N;;;;; +1D870;SIGNWRITING HAND-CUP OPEN NO THUMB;So;0;L;;;;;N;;;;; +1D871;SIGNWRITING HAND-CUP NO THUMB;So;0;L;;;;;N;;;;; +1D872;SIGNWRITING HAND-CUP OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; +1D873;SIGNWRITING HAND-CUP THUMB FORWARD;So;0;L;;;;;N;;;;; +1D874;SIGNWRITING HAND-CURLICUE OPEN;So;0;L;;;;;N;;;;; +1D875;SIGNWRITING HAND-CURLICUE;So;0;L;;;;;N;;;;; +1D876;SIGNWRITING HAND-CIRCLE;So;0;L;;;;;N;;;;; +1D877;SIGNWRITING HAND-OVAL;So;0;L;;;;;N;;;;; +1D878;SIGNWRITING HAND-OVAL THUMB SIDE;So;0;L;;;;;N;;;;; +1D879;SIGNWRITING HAND-OVAL NO THUMB;So;0;L;;;;;N;;;;; +1D87A;SIGNWRITING HAND-OVAL THUMB FORWARD;So;0;L;;;;;N;;;;; +1D87B;SIGNWRITING HAND-HINGE OPEN;So;0;L;;;;;N;;;;; +1D87C;SIGNWRITING HAND-HINGE OPEN THUMB FORWARD;So;0;L;;;;;N;;;;; +1D87D;SIGNWRITING HAND-HINGE;So;0;L;;;;;N;;;;; +1D87E;SIGNWRITING HAND-HINGE SMALL;So;0;L;;;;;N;;;;; +1D87F;SIGNWRITING HAND-HINGE OPEN THUMB SIDE;So;0;L;;;;;N;;;;; +1D880;SIGNWRITING HAND-HINGE THUMB SIDE;So;0;L;;;;;N;;;;; +1D881;SIGNWRITING HAND-HINGE OPEN NO THUMB;So;0;L;;;;;N;;;;; +1D882;SIGNWRITING HAND-HINGE NO THUMB;So;0;L;;;;;N;;;;; +1D883;SIGNWRITING HAND-HINGE THUMB SIDE TOUCHING INDEX;So;0;L;;;;;N;;;;; +1D884;SIGNWRITING HAND-HINGE THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; +1D885;SIGNWRITING HAND-ANGLE;So;0;L;;;;;N;;;;; +1D886;SIGNWRITING HAND-FIST INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D887;SIGNWRITING HAND-CIRCLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D888;SIGNWRITING HAND-HINGE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D889;SIGNWRITING HAND-ANGLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;; +1D88A;SIGNWRITING HAND-HINGE LITTLE;So;0;L;;;;;N;;;;; +1D88B;SIGNWRITING HAND-FIST INDEX MIDDLE RING BENT;So;0;L;;;;;N;;;;; +1D88C;SIGNWRITING HAND-FIST INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; +1D88D;SIGNWRITING HAND-HINGE INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;; +1D88E;SIGNWRITING HAND-FIST LITTLE DOWN;So;0;L;;;;;N;;;;; +1D88F;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE STRAIGHT;So;0;L;;;;;N;;;;; +1D890;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE CURVED;So;0;L;;;;;N;;;;; +1D891;SIGNWRITING HAND-FIST LITTLE DOWN OTHERS CIRCLED;So;0;L;;;;;N;;;;; +1D892;SIGNWRITING HAND-FIST LITTLE UP;So;0;L;;;;;N;;;;; +1D893;SIGNWRITING HAND-FIST THUMB UNDER LITTLE UP;So;0;L;;;;;N;;;;; +1D894;SIGNWRITING HAND-CIRCLE LITTLE UP;So;0;L;;;;;N;;;;; +1D895;SIGNWRITING HAND-OVAL LITTLE UP;So;0;L;;;;;N;;;;; +1D896;SIGNWRITING HAND-ANGLE LITTLE UP;So;0;L;;;;;N;;;;; +1D897;SIGNWRITING HAND-FIST LITTLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D898;SIGNWRITING HAND-FIST LITTLE BENT;So;0;L;;;;;N;;;;; +1D899;SIGNWRITING HAND-FIST LITTLE TOUCHES THUMB;So;0;L;;;;;N;;;;; +1D89A;SIGNWRITING HAND-FIST LITTLE THUMB;So;0;L;;;;;N;;;;; +1D89B;SIGNWRITING HAND-HINGE LITTLE THUMB;So;0;L;;;;;N;;;;; +1D89C;SIGNWRITING HAND-FIST LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D89D;SIGNWRITING HAND-HINGE LITTLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D89E;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB OUT;So;0;L;;;;;N;;;;; +1D89F;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB;So;0;L;;;;;N;;;;; +1D8A0;SIGNWRITING HAND-FIST LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A1;SIGNWRITING HAND-CIRCLE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A2;SIGNWRITING HAND-HINGE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A3;SIGNWRITING HAND-ANGLE LITTLE INDEX;So;0;L;;;;;N;;;;; +1D8A4;SIGNWRITING HAND-FIST INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A5;SIGNWRITING HAND-CIRCLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A6;SIGNWRITING HAND-HINGE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A7;SIGNWRITING HAND-HINGE RING;So;0;L;;;;;N;;;;; +1D8A8;SIGNWRITING HAND-ANGLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8A9;SIGNWRITING HAND-FIST INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; +1D8AA;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;; +1D8AB;SIGNWRITING HAND-FIST RING DOWN;So;0;L;;;;;N;;;;; +1D8AC;SIGNWRITING HAND-HINGE RING DOWN INDEX THUMB HOOK MIDDLE;So;0;L;;;;;N;;;;; +1D8AD;SIGNWRITING HAND-ANGLE RING DOWN MIDDLE THUMB INDEX CROSS;So;0;L;;;;;N;;;;; +1D8AE;SIGNWRITING HAND-FIST RING UP;So;0;L;;;;;N;;;;; +1D8AF;SIGNWRITING HAND-FIST RING RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D8B0;SIGNWRITING HAND-FIST RING LITTLE;So;0;L;;;;;N;;;;; +1D8B1;SIGNWRITING HAND-CIRCLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8B2;SIGNWRITING HAND-OVAL RING LITTLE;So;0;L;;;;;N;;;;; +1D8B3;SIGNWRITING HAND-ANGLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8B4;SIGNWRITING HAND-FIST RING MIDDLE;So;0;L;;;;;N;;;;; +1D8B5;SIGNWRITING HAND-FIST RING MIDDLE CONJOINED;So;0;L;;;;;N;;;;; +1D8B6;SIGNWRITING HAND-FIST RING MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D8B7;SIGNWRITING HAND-FIST RING INDEX;So;0;L;;;;;N;;;;; +1D8B8;SIGNWRITING HAND-FIST RING THUMB;So;0;L;;;;;N;;;;; +1D8B9;SIGNWRITING HAND-HOOK RING THUMB;So;0;L;;;;;N;;;;; +1D8BA;SIGNWRITING HAND-FIST INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8BB;SIGNWRITING HAND-CIRCLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8BC;SIGNWRITING HAND-CURLICUE INDEX RING LITTLE ON;So;0;L;;;;;N;;;;; +1D8BD;SIGNWRITING HAND-HOOK INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8BE;SIGNWRITING HAND-HOOK INDEX RING LITTLE IN;So;0;L;;;;;N;;;;; +1D8BF;SIGNWRITING HAND-HOOK INDEX RING LITTLE UNDER;So;0;L;;;;;N;;;;; +1D8C0;SIGNWRITING HAND-CUP INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C1;SIGNWRITING HAND-HINGE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C2;SIGNWRITING HAND-ANGLE INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8C3;SIGNWRITING HAND-ANGLE INDEX RING LITTLE;So;0;L;;;;;N;;;;; +1D8C4;SIGNWRITING HAND-FIST MIDDLE DOWN;So;0;L;;;;;N;;;;; +1D8C5;SIGNWRITING HAND-HINGE MIDDLE;So;0;L;;;;;N;;;;; +1D8C6;SIGNWRITING HAND-FIST MIDDLE UP;So;0;L;;;;;N;;;;; +1D8C7;SIGNWRITING HAND-CIRCLE MIDDLE UP;So;0;L;;;;;N;;;;; +1D8C8;SIGNWRITING HAND-FIST MIDDLE RAISED KNUCKLE;So;0;L;;;;;N;;;;; +1D8C9;SIGNWRITING HAND-FIST MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;; +1D8CA;SIGNWRITING HAND-HOOK MIDDLE THUMB;So;0;L;;;;;N;;;;; +1D8CB;SIGNWRITING HAND-FIST MIDDLE THUMB LITTLE;So;0;L;;;;;N;;;;; +1D8CC;SIGNWRITING HAND-FIST MIDDLE LITTLE;So;0;L;;;;;N;;;;; +1D8CD;SIGNWRITING HAND-FIST MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8CE;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8CF;SIGNWRITING HAND-CURLICUE MIDDLE RING LITTLE ON;So;0;L;;;;;N;;;;; +1D8D0;SIGNWRITING HAND-CUP MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D1;SIGNWRITING HAND-HINGE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D2;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE OUT;So;0;L;;;;;N;;;;; +1D8D3;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE IN;So;0;L;;;;;N;;;;; +1D8D4;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;; +1D8D5;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE BENT;So;0;L;;;;;N;;;;; +1D8D6;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; +1D8D7;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED SIDE;So;0;L;;;;;N;;;;; +1D8D8;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED OUT;So;0;L;;;;;N;;;;; +1D8D9;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED IN;So;0;L;;;;;N;;;;; +1D8DA;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;; +1D8DB;SIGNWRITING HAND-HINGE INDEX HINGED;So;0;L;;;;;N;;;;; +1D8DC;SIGNWRITING HAND-FIST INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D8DD;SIGNWRITING HAND-HINGE INDEX THUMB SIDE;So;0;L;;;;;N;;;;; +1D8DE;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB DIAGONAL;So;0;L;;;;;N;;;;; +1D8DF;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB CONJOINED;So;0;L;;;;;N;;;;; +1D8E0;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB BENT;So;0;L;;;;;N;;;;; +1D8E1;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX BENT;So;0;L;;;;;N;;;;; +1D8E2;SIGNWRITING HAND-FIST INDEX THUMB SIDE BOTH BENT;So;0;L;;;;;N;;;;; +1D8E3;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX HINGE;So;0;L;;;;;N;;;;; +1D8E4;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX STRAIGHT;So;0;L;;;;;N;;;;; +1D8E5;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX BENT;So;0;L;;;;;N;;;;; +1D8E6;SIGNWRITING HAND-FIST INDEX THUMB HOOK;So;0;L;;;;;N;;;;; +1D8E7;SIGNWRITING HAND-FIST INDEX THUMB CURLICUE;So;0;L;;;;;N;;;;; +1D8E8;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; +1D8E9;SIGNWRITING HAND-CLAW INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;; +1D8EA;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB UNDER;So;0;L;;;;;N;;;;; +1D8EB;SIGNWRITING HAND-FIST INDEX THUMB CIRCLE;So;0;L;;;;;N;;;;; +1D8EC;SIGNWRITING HAND-CUP INDEX THUMB;So;0;L;;;;;N;;;;; +1D8ED;SIGNWRITING HAND-CUP INDEX THUMB OPEN;So;0;L;;;;;N;;;;; +1D8EE;SIGNWRITING HAND-HINGE INDEX THUMB OPEN;So;0;L;;;;;N;;;;; +1D8EF;SIGNWRITING HAND-HINGE INDEX THUMB LARGE;So;0;L;;;;;N;;;;; +1D8F0;SIGNWRITING HAND-HINGE INDEX THUMB;So;0;L;;;;;N;;;;; +1D8F1;SIGNWRITING HAND-HINGE INDEX THUMB SMALL;So;0;L;;;;;N;;;;; +1D8F2;SIGNWRITING HAND-ANGLE INDEX THUMB OUT;So;0;L;;;;;N;;;;; +1D8F3;SIGNWRITING HAND-ANGLE INDEX THUMB IN;So;0;L;;;;;N;;;;; +1D8F4;SIGNWRITING HAND-ANGLE INDEX THUMB;So;0;L;;;;;N;;;;; +1D8F5;SIGNWRITING HAND-FIST THUMB;So;0;L;;;;;N;;;;; +1D8F6;SIGNWRITING HAND-FIST THUMB HEEL;So;0;L;;;;;N;;;;; +1D8F7;SIGNWRITING HAND-FIST THUMB SIDE DIAGONAL;So;0;L;;;;;N;;;;; +1D8F8;SIGNWRITING HAND-FIST THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;; +1D8F9;SIGNWRITING HAND-FIST THUMB SIDE BENT;So;0;L;;;;;N;;;;; +1D8FA;SIGNWRITING HAND-FIST THUMB FORWARD;So;0;L;;;;;N;;;;; +1D8FB;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE;So;0;L;;;;;N;;;;; +1D8FC;SIGNWRITING HAND-FIST THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;; +1D8FD;SIGNWRITING HAND-FIST THUMB BETWEEN RING LITTLE;So;0;L;;;;;N;;;;; +1D8FE;SIGNWRITING HAND-FIST THUMB UNDER TWO FINGERS;So;0;L;;;;;N;;;;; +1D8FF;SIGNWRITING HAND-FIST THUMB OVER TWO FINGERS;So;0;L;;;;;N;;;;; +1D900;SIGNWRITING HAND-FIST THUMB UNDER THREE FINGERS;So;0;L;;;;;N;;;;; +1D901;SIGNWRITING HAND-FIST THUMB UNDER FOUR FINGERS;So;0;L;;;;;N;;;;; +1D902;SIGNWRITING HAND-FIST THUMB OVER FOUR RAISED KNUCKLES;So;0;L;;;;;N;;;;; +1D903;SIGNWRITING HAND-FIST;So;0;L;;;;;N;;;;; +1D904;SIGNWRITING HAND-FIST HEEL;So;0;L;;;;;N;;;;; +1D905;SIGNWRITING TOUCH SINGLE;So;0;L;;;;;N;;;;; +1D906;SIGNWRITING TOUCH MULTIPLE;So;0;L;;;;;N;;;;; +1D907;SIGNWRITING TOUCH BETWEEN;So;0;L;;;;;N;;;;; +1D908;SIGNWRITING GRASP SINGLE;So;0;L;;;;;N;;;;; +1D909;SIGNWRITING GRASP MULTIPLE;So;0;L;;;;;N;;;;; +1D90A;SIGNWRITING GRASP BETWEEN;So;0;L;;;;;N;;;;; +1D90B;SIGNWRITING STRIKE SINGLE;So;0;L;;;;;N;;;;; +1D90C;SIGNWRITING STRIKE MULTIPLE;So;0;L;;;;;N;;;;; +1D90D;SIGNWRITING STRIKE BETWEEN;So;0;L;;;;;N;;;;; +1D90E;SIGNWRITING BRUSH SINGLE;So;0;L;;;;;N;;;;; +1D90F;SIGNWRITING BRUSH MULTIPLE;So;0;L;;;;;N;;;;; +1D910;SIGNWRITING BRUSH BETWEEN;So;0;L;;;;;N;;;;; +1D911;SIGNWRITING RUB SINGLE;So;0;L;;;;;N;;;;; +1D912;SIGNWRITING RUB MULTIPLE;So;0;L;;;;;N;;;;; +1D913;SIGNWRITING RUB BETWEEN;So;0;L;;;;;N;;;;; +1D914;SIGNWRITING SURFACE SYMBOLS;So;0;L;;;;;N;;;;; +1D915;SIGNWRITING SURFACE BETWEEN;So;0;L;;;;;N;;;;; +1D916;SIGNWRITING SQUEEZE LARGE SINGLE;So;0;L;;;;;N;;;;; +1D917;SIGNWRITING SQUEEZE SMALL SINGLE;So;0;L;;;;;N;;;;; +1D918;SIGNWRITING SQUEEZE LARGE MULTIPLE;So;0;L;;;;;N;;;;; +1D919;SIGNWRITING SQUEEZE SMALL MULTIPLE;So;0;L;;;;;N;;;;; +1D91A;SIGNWRITING SQUEEZE SEQUENTIAL;So;0;L;;;;;N;;;;; +1D91B;SIGNWRITING FLICK LARGE SINGLE;So;0;L;;;;;N;;;;; +1D91C;SIGNWRITING FLICK SMALL SINGLE;So;0;L;;;;;N;;;;; +1D91D;SIGNWRITING FLICK LARGE MULTIPLE;So;0;L;;;;;N;;;;; +1D91E;SIGNWRITING FLICK SMALL MULTIPLE;So;0;L;;;;;N;;;;; +1D91F;SIGNWRITING FLICK SEQUENTIAL;So;0;L;;;;;N;;;;; +1D920;SIGNWRITING SQUEEZE FLICK ALTERNATING;So;0;L;;;;;N;;;;; +1D921;SIGNWRITING MOVEMENT-HINGE UP DOWN LARGE;So;0;L;;;;;N;;;;; +1D922;SIGNWRITING MOVEMENT-HINGE UP DOWN SMALL;So;0;L;;;;;N;;;;; +1D923;SIGNWRITING MOVEMENT-HINGE UP SEQUENTIAL;So;0;L;;;;;N;;;;; +1D924;SIGNWRITING MOVEMENT-HINGE DOWN SEQUENTIAL;So;0;L;;;;;N;;;;; +1D925;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING LARGE;So;0;L;;;;;N;;;;; +1D926;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING SMALL;So;0;L;;;;;N;;;;; +1D927;SIGNWRITING MOVEMENT-HINGE SIDE TO SIDE SCISSORS;So;0;L;;;;;N;;;;; +1D928;SIGNWRITING MOVEMENT-WALLPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; +1D929;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CONTACT;So;0;L;;;;;N;;;;; +1D92A;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; +1D92B;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; +1D92C;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; +1D92D;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; +1D92E;SIGNWRITING MOVEMENT-WALLPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D92F;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; +1D930;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D931;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; +1D932;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D933;SIGNWRITING MOVEMENT-WALLPLANE CROSS;So;0;L;;;;;N;;;;; +1D934;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; +1D935;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D936;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING;So;0;L;;;;;N;;;;; +1D937;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D938;SIGNWRITING MOVEMENT-WALLPLANE BEND SMALL;So;0;L;;;;;N;;;;; +1D939;SIGNWRITING MOVEMENT-WALLPLANE BEND MEDIUM;So;0;L;;;;;N;;;;; +1D93A;SIGNWRITING MOVEMENT-WALLPLANE BEND LARGE;So;0;L;;;;;N;;;;; +1D93B;SIGNWRITING MOVEMENT-WALLPLANE CORNER SMALL;So;0;L;;;;;N;;;;; +1D93C;SIGNWRITING MOVEMENT-WALLPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; +1D93D;SIGNWRITING MOVEMENT-WALLPLANE CORNER LARGE;So;0;L;;;;;N;;;;; +1D93E;SIGNWRITING MOVEMENT-WALLPLANE CORNER ROTATION;So;0;L;;;;;N;;;;; +1D93F;SIGNWRITING MOVEMENT-WALLPLANE CHECK SMALL;So;0;L;;;;;N;;;;; +1D940;SIGNWRITING MOVEMENT-WALLPLANE CHECK MEDIUM;So;0;L;;;;;N;;;;; +1D941;SIGNWRITING MOVEMENT-WALLPLANE CHECK LARGE;So;0;L;;;;;N;;;;; +1D942;SIGNWRITING MOVEMENT-WALLPLANE BOX SMALL;So;0;L;;;;;N;;;;; +1D943;SIGNWRITING MOVEMENT-WALLPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; +1D944;SIGNWRITING MOVEMENT-WALLPLANE BOX LARGE;So;0;L;;;;;N;;;;; +1D945;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; +1D946;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; +1D947;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; +1D948;SIGNWRITING MOVEMENT-WALLPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; +1D949;SIGNWRITING MOVEMENT-WALLPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; +1D94A;SIGNWRITING MOVEMENT-WALLPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; +1D94B;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D94C;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D94D;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D94E;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D94F;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D950;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D951;SIGNWRITING TRAVEL-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; +1D952;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL SINGLE;So;0;L;;;;;N;;;;; +1D953;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL DOUBLE;So;0;L;;;;;N;;;;; +1D954;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL TRIPLE;So;0;L;;;;;N;;;;; +1D955;SIGNWRITING MOVEMENT-DIAGONAL AWAY SMALL;So;0;L;;;;;N;;;;; +1D956;SIGNWRITING MOVEMENT-DIAGONAL AWAY MEDIUM;So;0;L;;;;;N;;;;; +1D957;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGE;So;0;L;;;;;N;;;;; +1D958;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGEST;So;0;L;;;;;N;;;;; +1D959;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS SMALL;So;0;L;;;;;N;;;;; +1D95A;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS MEDIUM;So;0;L;;;;;N;;;;; +1D95B;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGE;So;0;L;;;;;N;;;;; +1D95C;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGEST;So;0;L;;;;;N;;;;; +1D95D;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY SMALL;So;0;L;;;;;N;;;;; +1D95E;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY MEDIUM;So;0;L;;;;;N;;;;; +1D95F;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGE;So;0;L;;;;;N;;;;; +1D960;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGEST;So;0;L;;;;;N;;;;; +1D961;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS SMALL;So;0;L;;;;;N;;;;; +1D962;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS MEDIUM;So;0;L;;;;;N;;;;; +1D963;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGE;So;0;L;;;;;N;;;;; +1D964;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGEST;So;0;L;;;;;N;;;;; +1D965;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;; +1D966;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;; +1D967;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;; +1D968;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;; +1D969;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D96A;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;; +1D96B;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D96C;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;; +1D96D;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D96E;SIGNWRITING MOVEMENT-FLOORPLANE CROSS;So;0;L;;;;;N;;;;; +1D96F;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;; +1D970;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;; +1D971;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING MOVEMENT;So;0;L;;;;;N;;;;; +1D972;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;; +1D973;SIGNWRITING MOVEMENT-FLOORPLANE BEND;So;0;L;;;;;N;;;;; +1D974;SIGNWRITING MOVEMENT-FLOORPLANE CORNER SMALL;So;0;L;;;;;N;;;;; +1D975;SIGNWRITING MOVEMENT-FLOORPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;; +1D976;SIGNWRITING MOVEMENT-FLOORPLANE CORNER LARGE;So;0;L;;;;;N;;;;; +1D977;SIGNWRITING MOVEMENT-FLOORPLANE CHECK;So;0;L;;;;;N;;;;; +1D978;SIGNWRITING MOVEMENT-FLOORPLANE BOX SMALL;So;0;L;;;;;N;;;;; +1D979;SIGNWRITING MOVEMENT-FLOORPLANE BOX MEDIUM;So;0;L;;;;;N;;;;; +1D97A;SIGNWRITING MOVEMENT-FLOORPLANE BOX LARGE;So;0;L;;;;;N;;;;; +1D97B;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;; +1D97C;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;; +1D97D;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;; +1D97E;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS SMALL;So;0;L;;;;;N;;;;; +1D97F;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;; +1D980;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS LARGE;So;0;L;;;;;N;;;;; +1D981;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D982;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D983;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D984;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D985;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D986;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D987;SIGNWRITING TRAVEL-FLOORPLANE SHAKING;So;0;L;;;;;N;;;;; +1D988;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER SMALL;So;0;L;;;;;N;;;;; +1D989;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER MEDIUM;So;0;L;;;;;N;;;;; +1D98A;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGE;So;0;L;;;;;N;;;;; +1D98B;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGEST;So;0;L;;;;;N;;;;; +1D98C;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE SMALL;So;0;L;;;;;N;;;;; +1D98D;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE MEDIUM;So;0;L;;;;;N;;;;; +1D98E;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGE;So;0;L;;;;;N;;;;; +1D98F;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGEST;So;0;L;;;;;N;;;;; +1D990;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE SMALL;So;0;L;;;;;N;;;;; +1D991;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE MEDIUM;So;0;L;;;;;N;;;;; +1D992;SIGNWRITING MOVEMENT-WALLPLANE HUMP SMALL;So;0;L;;;;;N;;;;; +1D993;SIGNWRITING MOVEMENT-WALLPLANE HUMP MEDIUM;So;0;L;;;;;N;;;;; +1D994;SIGNWRITING MOVEMENT-WALLPLANE HUMP LARGE;So;0;L;;;;;N;;;;; +1D995;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL;So;0;L;;;;;N;;;;; +1D996;SIGNWRITING MOVEMENT-WALLPLANE LOOP MEDIUM;So;0;L;;;;;N;;;;; +1D997;SIGNWRITING MOVEMENT-WALLPLANE LOOP LARGE;So;0;L;;;;;N;;;;; +1D998;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D999;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE SMALL;So;0;L;;;;;N;;;;; +1D99A;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE MEDIUM;So;0;L;;;;;N;;;;; +1D99B;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE LARGE;So;0;L;;;;;N;;;;; +1D99C;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE SMALL;So;0;L;;;;;N;;;;; +1D99D;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE MEDIUM;So;0;L;;;;;N;;;;; +1D99E;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE LARGE;So;0;L;;;;;N;;;;; +1D99F;SIGNWRITING MOVEMENT-WALLPLANE CURVE THEN STRAIGHT;So;0;L;;;;;N;;;;; +1D9A0;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS SMALL;So;0;L;;;;;N;;;;; +1D9A1;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS MEDIUM;So;0;L;;;;;N;;;;; +1D9A2;SIGNWRITING ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;; +1D9A3;SIGNWRITING ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D9A4;SIGNWRITING ROTATION-WALLPLANE ALTERNATE;So;0;L;;;;;N;;;;; +1D9A5;SIGNWRITING MOVEMENT-WALLPLANE SHAKING;So;0;L;;;;;N;;;;; +1D9A6;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A7;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A8;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9A9;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AA;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AB;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AC;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING FRONT WALL;So;0;L;;;;;N;;;;; +1D9AD;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9AE;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING CHEST;So;0;L;;;;;N;;;;; +1D9AF;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B0;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B1;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B2;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B3;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING CHEST;So;0;L;;;;;N;;;;; +1D9B4;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH SMALL;So;0;L;;;;;N;;;;; +1D9B5;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH MEDIUM;So;0;L;;;;;N;;;;; +1D9B6;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH LARGE;So;0;L;;;;;N;;;;; +1D9B7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; +1D9B8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; +1D9B9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9BA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9BB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL TRIPLE;So;0;L;;;;;N;;;;; +1D9BC;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE TRIPLE;So;0;L;;;;;N;;;;; +1D9BD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9BE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9BF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9C0;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9C1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;; +1D9C2;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;; +1D9C3;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C4;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C5;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING CEILING;So;0;L;;;;;N;;;;; +1D9C6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; +1D9C7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; +1D9C8;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9C9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9CA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE SMALL TRIPLE;So;0;L;;;;;N;;;;; +1D9CB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE LARGE TRIPLE;So;0;L;;;;;N;;;;; +1D9CC;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9CD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9CE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9CF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9D0;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;; +1D9D1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;; +1D9D2;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D3;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D4;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING FLOOR;So;0;L;;;;;N;;;;; +1D9D5;SIGNWRITING MOVEMENT-FLOORPLANE CURVE SMALL;So;0;L;;;;;N;;;;; +1D9D6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE MEDIUM;So;0;L;;;;;N;;;;; +1D9D7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGE;So;0;L;;;;;N;;;;; +1D9D8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGEST;So;0;L;;;;;N;;;;; +1D9D9;SIGNWRITING MOVEMENT-FLOORPLANE CURVE COMBINED;So;0;L;;;;;N;;;;; +1D9DA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP SMALL;So;0;L;;;;;N;;;;; +1D9DB;SIGNWRITING MOVEMENT-FLOORPLANE LOOP SMALL;So;0;L;;;;;N;;;;; +1D9DC;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SNAKE;So;0;L;;;;;N;;;;; +1D9DD;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SMALL;So;0;L;;;;;N;;;;; +1D9DE;SIGNWRITING MOVEMENT-FLOORPLANE WAVE LARGE;So;0;L;;;;;N;;;;; +1D9DF;SIGNWRITING ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;; +1D9E0;SIGNWRITING ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;; +1D9E1;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;; +1D9E2;SIGNWRITING MOVEMENT-FLOORPLANE SHAKING PARALLEL;So;0;L;;;;;N;;;;; +1D9E3;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9E4;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM SINGLE;So;0;L;;;;;N;;;;; +1D9E5;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9E6;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM DOUBLE;So;0;L;;;;;N;;;;; +1D9E7;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL SINGLE;So;0;L;;;;;N;;;;; +1D9E8;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM SINGLE;So;0;L;;;;;N;;;;; +1D9E9;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE SINGLE;So;0;L;;;;;N;;;;; +1D9EA;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL DOUBLE;So;0;L;;;;;N;;;;; +1D9EB;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM DOUBLE;So;0;L;;;;;N;;;;; +1D9EC;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE DOUBLE;So;0;L;;;;;N;;;;; +1D9ED;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT SINGLE;So;0;L;;;;;N;;;;; +1D9EE;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT DOUBLE;So;0;L;;;;;N;;;;; +1D9EF;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL SINGLE;So;0;L;;;;;N;;;;; +1D9F0;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; +1D9F1;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES SINGLE;So;0;L;;;;;N;;;;; +1D9F2;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES DOUBLE;So;0;L;;;;;N;;;;; +1D9F3;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL SINGLE;So;0;L;;;;;N;;;;; +1D9F4;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL DOUBLE;So;0;L;;;;;N;;;;; +1D9F5;SIGNWRITING DYNAMIC ARROWHEAD SMALL;So;0;L;;;;;N;;;;; +1D9F6;SIGNWRITING DYNAMIC ARROWHEAD LARGE;So;0;L;;;;;N;;;;; +1D9F7;SIGNWRITING DYNAMIC FAST;So;0;L;;;;;N;;;;; +1D9F8;SIGNWRITING DYNAMIC SLOW;So;0;L;;;;;N;;;;; +1D9F9;SIGNWRITING DYNAMIC TENSE;So;0;L;;;;;N;;;;; +1D9FA;SIGNWRITING DYNAMIC RELAXED;So;0;L;;;;;N;;;;; +1D9FB;SIGNWRITING DYNAMIC SIMULTANEOUS;So;0;L;;;;;N;;;;; +1D9FC;SIGNWRITING DYNAMIC SIMULTANEOUS ALTERNATING;So;0;L;;;;;N;;;;; +1D9FD;SIGNWRITING DYNAMIC EVERY OTHER TIME;So;0;L;;;;;N;;;;; +1D9FE;SIGNWRITING DYNAMIC GRADUAL;So;0;L;;;;;N;;;;; +1D9FF;SIGNWRITING HEAD;So;0;L;;;;;N;;;;; +1DA00;SIGNWRITING HEAD RIM;Mn;0;NSM;;;;;N;;;;; +1DA01;SIGNWRITING HEAD MOVEMENT-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA02;SIGNWRITING HEAD MOVEMENT-WALLPLANE TILT;Mn;0;NSM;;;;;N;;;;; +1DA03;SIGNWRITING HEAD MOVEMENT-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA04;SIGNWRITING HEAD MOVEMENT-WALLPLANE CURVE;Mn;0;NSM;;;;;N;;;;; +1DA05;SIGNWRITING HEAD MOVEMENT-FLOORPLANE CURVE;Mn;0;NSM;;;;;N;;;;; +1DA06;SIGNWRITING HEAD MOVEMENT CIRCLE;Mn;0;NSM;;;;;N;;;;; +1DA07;SIGNWRITING FACE DIRECTION POSITION NOSE FORWARD TILTING;Mn;0;NSM;;;;;N;;;;; +1DA08;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN;Mn;0;NSM;;;;;N;;;;; +1DA09;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN TILTING;Mn;0;NSM;;;;;N;;;;; +1DA0A;SIGNWRITING EYEBROWS STRAIGHT UP;Mn;0;NSM;;;;;N;;;;; +1DA0B;SIGNWRITING EYEBROWS STRAIGHT NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA0C;SIGNWRITING EYEBROWS STRAIGHT DOWN;Mn;0;NSM;;;;;N;;;;; +1DA0D;SIGNWRITING DREAMY EYEBROWS NEUTRAL DOWN;Mn;0;NSM;;;;;N;;;;; +1DA0E;SIGNWRITING DREAMY EYEBROWS DOWN NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA0F;SIGNWRITING DREAMY EYEBROWS UP NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA10;SIGNWRITING DREAMY EYEBROWS NEUTRAL UP;Mn;0;NSM;;;;;N;;;;; +1DA11;SIGNWRITING FOREHEAD NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA12;SIGNWRITING FOREHEAD CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA13;SIGNWRITING FOREHEAD WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA14;SIGNWRITING EYES OPEN;Mn;0;NSM;;;;;N;;;;; +1DA15;SIGNWRITING EYES SQUEEZED;Mn;0;NSM;;;;;N;;;;; +1DA16;SIGNWRITING EYES CLOSED;Mn;0;NSM;;;;;N;;;;; +1DA17;SIGNWRITING EYE BLINK SINGLE;Mn;0;NSM;;;;;N;;;;; +1DA18;SIGNWRITING EYE BLINK MULTIPLE;Mn;0;NSM;;;;;N;;;;; +1DA19;SIGNWRITING EYES HALF OPEN;Mn;0;NSM;;;;;N;;;;; +1DA1A;SIGNWRITING EYES WIDE OPEN;Mn;0;NSM;;;;;N;;;;; +1DA1B;SIGNWRITING EYES HALF CLOSED;Mn;0;NSM;;;;;N;;;;; +1DA1C;SIGNWRITING EYES WIDENING MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA1D;SIGNWRITING EYE WINK;Mn;0;NSM;;;;;N;;;;; +1DA1E;SIGNWRITING EYELASHES UP;Mn;0;NSM;;;;;N;;;;; +1DA1F;SIGNWRITING EYELASHES DOWN;Mn;0;NSM;;;;;N;;;;; +1DA20;SIGNWRITING EYELASHES FLUTTERING;Mn;0;NSM;;;;;N;;;;; +1DA21;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA22;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA23;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; +1DA24;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;; +1DA25;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA26;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;; +1DA27;SIGNWRITING EYEGAZE-WALLPLANE CURVED;Mn;0;NSM;;;;;N;;;;; +1DA28;SIGNWRITING EYEGAZE-FLOORPLANE CURVED;Mn;0;NSM;;;;;N;;;;; +1DA29;SIGNWRITING EYEGAZE-WALLPLANE CIRCLING;Mn;0;NSM;;;;;N;;;;; +1DA2A;SIGNWRITING CHEEKS PUFFED;Mn;0;NSM;;;;;N;;;;; +1DA2B;SIGNWRITING CHEEKS NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA2C;SIGNWRITING CHEEKS SUCKED;Mn;0;NSM;;;;;N;;;;; +1DA2D;SIGNWRITING TENSE CHEEKS HIGH;Mn;0;NSM;;;;;N;;;;; +1DA2E;SIGNWRITING TENSE CHEEKS MIDDLE;Mn;0;NSM;;;;;N;;;;; +1DA2F;SIGNWRITING TENSE CHEEKS LOW;Mn;0;NSM;;;;;N;;;;; +1DA30;SIGNWRITING EARS;Mn;0;NSM;;;;;N;;;;; +1DA31;SIGNWRITING NOSE NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA32;SIGNWRITING NOSE CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA33;SIGNWRITING NOSE WRINKLES;Mn;0;NSM;;;;;N;;;;; +1DA34;SIGNWRITING NOSE WIGGLES;Mn;0;NSM;;;;;N;;;;; +1DA35;SIGNWRITING AIR BLOWING OUT;Mn;0;NSM;;;;;N;;;;; +1DA36;SIGNWRITING AIR SUCKING IN;Mn;0;NSM;;;;;N;;;;; +1DA37;SIGNWRITING AIR BLOW SMALL ROTATIONS;So;0;L;;;;;N;;;;; +1DA38;SIGNWRITING AIR SUCK SMALL ROTATIONS;So;0;L;;;;;N;;;;; +1DA39;SIGNWRITING BREATH INHALE;So;0;L;;;;;N;;;;; +1DA3A;SIGNWRITING BREATH EXHALE;So;0;L;;;;;N;;;;; +1DA3B;SIGNWRITING MOUTH CLOSED NEUTRAL;Mn;0;NSM;;;;;N;;;;; +1DA3C;SIGNWRITING MOUTH CLOSED FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA3D;SIGNWRITING MOUTH CLOSED CONTACT;Mn;0;NSM;;;;;N;;;;; +1DA3E;SIGNWRITING MOUTH SMILE;Mn;0;NSM;;;;;N;;;;; +1DA3F;SIGNWRITING MOUTH SMILE WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA40;SIGNWRITING MOUTH SMILE OPEN;Mn;0;NSM;;;;;N;;;;; +1DA41;SIGNWRITING MOUTH FROWN;Mn;0;NSM;;;;;N;;;;; +1DA42;SIGNWRITING MOUTH FROWN WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA43;SIGNWRITING MOUTH FROWN OPEN;Mn;0;NSM;;;;;N;;;;; +1DA44;SIGNWRITING MOUTH OPEN CIRCLE;Mn;0;NSM;;;;;N;;;;; +1DA45;SIGNWRITING MOUTH OPEN FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA46;SIGNWRITING MOUTH OPEN WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA47;SIGNWRITING MOUTH OPEN OVAL;Mn;0;NSM;;;;;N;;;;; +1DA48;SIGNWRITING MOUTH OPEN OVAL WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA49;SIGNWRITING MOUTH OPEN OVAL YAWN;Mn;0;NSM;;;;;N;;;;; +1DA4A;SIGNWRITING MOUTH OPEN RECTANGLE;Mn;0;NSM;;;;;N;;;;; +1DA4B;SIGNWRITING MOUTH OPEN RECTANGLE WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA4C;SIGNWRITING MOUTH OPEN RECTANGLE YAWN;Mn;0;NSM;;;;;N;;;;; +1DA4D;SIGNWRITING MOUTH KISS;Mn;0;NSM;;;;;N;;;;; +1DA4E;SIGNWRITING MOUTH KISS FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA4F;SIGNWRITING MOUTH KISS WRINKLED;Mn;0;NSM;;;;;N;;;;; +1DA50;SIGNWRITING MOUTH TENSE;Mn;0;NSM;;;;;N;;;;; +1DA51;SIGNWRITING MOUTH TENSE FORWARD;Mn;0;NSM;;;;;N;;;;; +1DA52;SIGNWRITING MOUTH TENSE SUCKED;Mn;0;NSM;;;;;N;;;;; +1DA53;SIGNWRITING LIPS PRESSED TOGETHER;Mn;0;NSM;;;;;N;;;;; +1DA54;SIGNWRITING LIP LOWER OVER UPPER;Mn;0;NSM;;;;;N;;;;; +1DA55;SIGNWRITING LIP UPPER OVER LOWER;Mn;0;NSM;;;;;N;;;;; +1DA56;SIGNWRITING MOUTH CORNERS;Mn;0;NSM;;;;;N;;;;; +1DA57;SIGNWRITING MOUTH WRINKLES SINGLE;Mn;0;NSM;;;;;N;;;;; +1DA58;SIGNWRITING MOUTH WRINKLES DOUBLE;Mn;0;NSM;;;;;N;;;;; +1DA59;SIGNWRITING TONGUE STICKING OUT FAR;Mn;0;NSM;;;;;N;;;;; +1DA5A;SIGNWRITING TONGUE LICKING LIPS;Mn;0;NSM;;;;;N;;;;; +1DA5B;SIGNWRITING TONGUE TIP BETWEEN LIPS;Mn;0;NSM;;;;;N;;;;; +1DA5C;SIGNWRITING TONGUE TIP TOUCHING INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; +1DA5D;SIGNWRITING TONGUE INSIDE MOUTH RELAXED;Mn;0;NSM;;;;;N;;;;; +1DA5E;SIGNWRITING TONGUE MOVES AGAINST CHEEK;Mn;0;NSM;;;;;N;;;;; +1DA5F;SIGNWRITING TONGUE CENTRE STICKING OUT;Mn;0;NSM;;;;;N;;;;; +1DA60;SIGNWRITING TONGUE CENTRE INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;; +1DA61;SIGNWRITING TEETH;Mn;0;NSM;;;;;N;;;;; +1DA62;SIGNWRITING TEETH MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA63;SIGNWRITING TEETH ON TONGUE;Mn;0;NSM;;;;;N;;;;; +1DA64;SIGNWRITING TEETH ON TONGUE MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA65;SIGNWRITING TEETH ON LIPS;Mn;0;NSM;;;;;N;;;;; +1DA66;SIGNWRITING TEETH ON LIPS MOVEMENT;Mn;0;NSM;;;;;N;;;;; +1DA67;SIGNWRITING TEETH BITE LIPS;Mn;0;NSM;;;;;N;;;;; +1DA68;SIGNWRITING MOVEMENT-WALLPLANE JAW;Mn;0;NSM;;;;;N;;;;; +1DA69;SIGNWRITING MOVEMENT-FLOORPLANE JAW;Mn;0;NSM;;;;;N;;;;; +1DA6A;SIGNWRITING NECK;Mn;0;NSM;;;;;N;;;;; +1DA6B;SIGNWRITING HAIR;Mn;0;NSM;;;;;N;;;;; +1DA6C;SIGNWRITING EXCITEMENT;Mn;0;NSM;;;;;N;;;;; +1DA6D;SIGNWRITING SHOULDER HIP SPINE;So;0;L;;;;;N;;;;; +1DA6E;SIGNWRITING SHOULDER HIP POSITIONS;So;0;L;;;;;N;;;;; +1DA6F;SIGNWRITING WALLPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; +1DA70;SIGNWRITING FLOORPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;; +1DA71;SIGNWRITING SHOULDER TILTING FROM WAIST;So;0;L;;;;;N;;;;; +1DA72;SIGNWRITING TORSO-WALLPLANE STRAIGHT STRETCH;So;0;L;;;;;N;;;;; +1DA73;SIGNWRITING TORSO-WALLPLANE CURVED BEND;So;0;L;;;;;N;;;;; +1DA74;SIGNWRITING TORSO-FLOORPLANE TWISTING;So;0;L;;;;;N;;;;; +1DA75;SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS;Mn;0;NSM;;;;;N;;;;; +1DA76;SIGNWRITING LIMB COMBINATION;So;0;L;;;;;N;;;;; +1DA77;SIGNWRITING LIMB LENGTH-1;So;0;L;;;;;N;;;;; +1DA78;SIGNWRITING LIMB LENGTH-2;So;0;L;;;;;N;;;;; +1DA79;SIGNWRITING LIMB LENGTH-3;So;0;L;;;;;N;;;;; +1DA7A;SIGNWRITING LIMB LENGTH-4;So;0;L;;;;;N;;;;; +1DA7B;SIGNWRITING LIMB LENGTH-5;So;0;L;;;;;N;;;;; +1DA7C;SIGNWRITING LIMB LENGTH-6;So;0;L;;;;;N;;;;; +1DA7D;SIGNWRITING LIMB LENGTH-7;So;0;L;;;;;N;;;;; +1DA7E;SIGNWRITING FINGER;So;0;L;;;;;N;;;;; +1DA7F;SIGNWRITING LOCATION-WALLPLANE SPACE;So;0;L;;;;;N;;;;; +1DA80;SIGNWRITING LOCATION-FLOORPLANE SPACE;So;0;L;;;;;N;;;;; +1DA81;SIGNWRITING LOCATION HEIGHT;So;0;L;;;;;N;;;;; +1DA82;SIGNWRITING LOCATION WIDTH;So;0;L;;;;;N;;;;; +1DA83;SIGNWRITING LOCATION DEPTH;So;0;L;;;;;N;;;;; +1DA84;SIGNWRITING LOCATION HEAD NECK;Mn;0;NSM;;;;;N;;;;; +1DA85;SIGNWRITING LOCATION TORSO;So;0;L;;;;;N;;;;; +1DA86;SIGNWRITING LOCATION LIMBS DIGITS;So;0;L;;;;;N;;;;; +1DA87;SIGNWRITING COMMA;Po;0;L;;;;;N;;;;; +1DA88;SIGNWRITING FULL STOP;Po;0;L;;;;;N;;;;; +1DA89;SIGNWRITING SEMICOLON;Po;0;L;;;;;N;;;;; +1DA8A;SIGNWRITING COLON;Po;0;L;;;;;N;;;;; +1DA8B;SIGNWRITING PARENTHESIS;Po;0;L;;;;;N;;;;; +1DA9B;SIGNWRITING FILL MODIFIER-2;Mn;0;NSM;;;;;N;;;;; +1DA9C;SIGNWRITING FILL MODIFIER-3;Mn;0;NSM;;;;;N;;;;; +1DA9D;SIGNWRITING FILL MODIFIER-4;Mn;0;NSM;;;;;N;;;;; +1DA9E;SIGNWRITING FILL MODIFIER-5;Mn;0;NSM;;;;;N;;;;; +1DA9F;SIGNWRITING FILL MODIFIER-6;Mn;0;NSM;;;;;N;;;;; +1DAA1;SIGNWRITING ROTATION MODIFIER-2;Mn;0;NSM;;;;;N;;;;; +1DAA2;SIGNWRITING ROTATION MODIFIER-3;Mn;0;NSM;;;;;N;;;;; +1DAA3;SIGNWRITING ROTATION MODIFIER-4;Mn;0;NSM;;;;;N;;;;; +1DAA4;SIGNWRITING ROTATION MODIFIER-5;Mn;0;NSM;;;;;N;;;;; +1DAA5;SIGNWRITING ROTATION MODIFIER-6;Mn;0;NSM;;;;;N;;;;; +1DAA6;SIGNWRITING ROTATION MODIFIER-7;Mn;0;NSM;;;;;N;;;;; +1DAA7;SIGNWRITING ROTATION MODIFIER-8;Mn;0;NSM;;;;;N;;;;; +1DAA8;SIGNWRITING ROTATION MODIFIER-9;Mn;0;NSM;;;;;N;;;;; +1DAA9;SIGNWRITING ROTATION MODIFIER-10;Mn;0;NSM;;;;;N;;;;; +1DAAA;SIGNWRITING ROTATION MODIFIER-11;Mn;0;NSM;;;;;N;;;;; +1DAAB;SIGNWRITING ROTATION MODIFIER-12;Mn;0;NSM;;;;;N;;;;; +1DAAC;SIGNWRITING ROTATION MODIFIER-13;Mn;0;NSM;;;;;N;;;;; +1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;; +1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;; +1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;; +1DF00;LATIN SMALL LETTER FENG DIGRAPH WITH TRILL;Ll;0;L;;;;;N;;;;; +1DF01;LATIN SMALL LETTER REVERSED SCRIPT G;Ll;0;L;;;;;N;;;;; +1DF02;LATIN LETTER SMALL CAPITAL TURNED G;Ll;0;L;;;;;N;;;;; +1DF03;LATIN SMALL LETTER REVERSED K;Ll;0;L;;;;;N;;;;; +1DF04;LATIN LETTER SMALL CAPITAL L WITH BELT;Ll;0;L;;;;;N;;;;; +1DF05;LATIN SMALL LETTER LEZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF06;LATIN SMALL LETTER TURNED Y WITH BELT;Ll;0;L;;;;;N;;;;; +1DF07;LATIN SMALL LETTER REVERSED ENG;Ll;0;L;;;;;N;;;;; +1DF08;LATIN SMALL LETTER TURNED R WITH LONG LEG AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF09;LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF0A;LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lo;0;L;;;;;N;;;;; +1DF0B;LATIN SMALL LETTER ESH WITH DOUBLE BAR;Ll;0;L;;;;;N;;;;; +1DF0C;LATIN SMALL LETTER ESH WITH DOUBLE BAR AND CURL;Ll;0;L;;;;;N;;;;; +1DF0D;LATIN SMALL LETTER TURNED T WITH CURL;Ll;0;L;;;;;N;;;;; +1DF0E;LATIN LETTER INVERTED GLOTTAL STOP WITH CURL;Ll;0;L;;;;;N;;;;; +1DF0F;LATIN LETTER STRETCHED C WITH CURL;Ll;0;L;;;;;N;;;;; +1DF10;LATIN LETTER SMALL CAPITAL TURNED K;Ll;0;L;;;;;N;;;;; +1DF11;LATIN SMALL LETTER L WITH FISHHOOK;Ll;0;L;;;;;N;;;;; +1DF12;LATIN SMALL LETTER DEZH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF13;LATIN SMALL LETTER L WITH BELT AND PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF14;LATIN SMALL LETTER ENG WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF15;LATIN SMALL LETTER TURNED R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF16;LATIN SMALL LETTER R WITH FISHHOOK AND PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF17;LATIN SMALL LETTER TESH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF18;LATIN SMALL LETTER EZH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;; +1DF19;LATIN SMALL LETTER DEZH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1A;LATIN SMALL LETTER I WITH STROKE AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1B;LATIN SMALL LETTER O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1C;LATIN SMALL LETTER TESH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1D;LATIN SMALL LETTER C WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;; +1DF1E;LATIN SMALL LETTER S WITH CURL;Ll;0;L;;;;;N;;;;; +1DF25;LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1DF26;LATIN SMALL LETTER L WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1DF27;LATIN SMALL LETTER N WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1DF28;LATIN SMALL LETTER R WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1DF29;LATIN SMALL LETTER S WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1DF2A;LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK;Ll;0;L;;;;;N;;;;; +1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;; +1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;; +1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;; +1E003;COMBINING GLAGOLITIC LETTER GLAGOLI;Mn;230;NSM;;;;;N;;;;; +1E004;COMBINING GLAGOLITIC LETTER DOBRO;Mn;230;NSM;;;;;N;;;;; +1E005;COMBINING GLAGOLITIC LETTER YESTU;Mn;230;NSM;;;;;N;;;;; +1E006;COMBINING GLAGOLITIC LETTER ZHIVETE;Mn;230;NSM;;;;;N;;;;; +1E008;COMBINING GLAGOLITIC LETTER ZEMLJA;Mn;230;NSM;;;;;N;;;;; +1E009;COMBINING GLAGOLITIC LETTER IZHE;Mn;230;NSM;;;;;N;;;;; +1E00A;COMBINING GLAGOLITIC LETTER INITIAL IZHE;Mn;230;NSM;;;;;N;;;;; +1E00B;COMBINING GLAGOLITIC LETTER I;Mn;230;NSM;;;;;N;;;;; +1E00C;COMBINING GLAGOLITIC LETTER DJERVI;Mn;230;NSM;;;;;N;;;;; +1E00D;COMBINING GLAGOLITIC LETTER KAKO;Mn;230;NSM;;;;;N;;;;; +1E00E;COMBINING GLAGOLITIC LETTER LJUDIJE;Mn;230;NSM;;;;;N;;;;; +1E00F;COMBINING GLAGOLITIC LETTER MYSLITE;Mn;230;NSM;;;;;N;;;;; +1E010;COMBINING GLAGOLITIC LETTER NASHI;Mn;230;NSM;;;;;N;;;;; +1E011;COMBINING GLAGOLITIC LETTER ONU;Mn;230;NSM;;;;;N;;;;; +1E012;COMBINING GLAGOLITIC LETTER POKOJI;Mn;230;NSM;;;;;N;;;;; +1E013;COMBINING GLAGOLITIC LETTER RITSI;Mn;230;NSM;;;;;N;;;;; +1E014;COMBINING GLAGOLITIC LETTER SLOVO;Mn;230;NSM;;;;;N;;;;; +1E015;COMBINING GLAGOLITIC LETTER TVRIDO;Mn;230;NSM;;;;;N;;;;; +1E016;COMBINING GLAGOLITIC LETTER UKU;Mn;230;NSM;;;;;N;;;;; +1E017;COMBINING GLAGOLITIC LETTER FRITU;Mn;230;NSM;;;;;N;;;;; +1E018;COMBINING GLAGOLITIC LETTER HERU;Mn;230;NSM;;;;;N;;;;; +1E01B;COMBINING GLAGOLITIC LETTER SHTA;Mn;230;NSM;;;;;N;;;;; +1E01C;COMBINING GLAGOLITIC LETTER TSI;Mn;230;NSM;;;;;N;;;;; +1E01D;COMBINING GLAGOLITIC LETTER CHRIVI;Mn;230;NSM;;;;;N;;;;; +1E01E;COMBINING GLAGOLITIC LETTER SHA;Mn;230;NSM;;;;;N;;;;; +1E01F;COMBINING GLAGOLITIC LETTER YERU;Mn;230;NSM;;;;;N;;;;; +1E020;COMBINING GLAGOLITIC LETTER YERI;Mn;230;NSM;;;;;N;;;;; +1E021;COMBINING GLAGOLITIC LETTER YATI;Mn;230;NSM;;;;;N;;;;; +1E023;COMBINING GLAGOLITIC LETTER YU;Mn;230;NSM;;;;;N;;;;; +1E024;COMBINING GLAGOLITIC LETTER SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E026;COMBINING GLAGOLITIC LETTER YO;Mn;230;NSM;;;;;N;;;;; +1E027;COMBINING GLAGOLITIC LETTER IOTATED SMALL YUS;Mn;230;NSM;;;;;N;;;;; +1E028;COMBINING GLAGOLITIC LETTER BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E029;COMBINING GLAGOLITIC LETTER IOTATED BIG YUS;Mn;230;NSM;;;;;N;;;;; +1E02A;COMBINING GLAGOLITIC LETTER FITA;Mn;230;NSM;;;;;N;;;;; +1E030;MODIFIER LETTER CYRILLIC SMALL A;Lm;0;L; 0430;;;;N;;;;; +1E031;MODIFIER LETTER CYRILLIC SMALL BE;Lm;0;L; 0431;;;;N;;;;; +1E032;MODIFIER LETTER CYRILLIC SMALL VE;Lm;0;L; 0432;;;;N;;;;; +1E033;MODIFIER LETTER CYRILLIC SMALL GHE;Lm;0;L; 0433;;;;N;;;;; +1E034;MODIFIER LETTER CYRILLIC SMALL DE;Lm;0;L; 0434;;;;N;;;;; +1E035;MODIFIER LETTER CYRILLIC SMALL IE;Lm;0;L; 0435;;;;N;;;;; +1E036;MODIFIER LETTER CYRILLIC SMALL ZHE;Lm;0;L; 0436;;;;N;;;;; +1E037;MODIFIER LETTER CYRILLIC SMALL ZE;Lm;0;L; 0437;;;;N;;;;; +1E038;MODIFIER LETTER CYRILLIC SMALL I;Lm;0;L; 0438;;;;N;;;;; +1E039;MODIFIER LETTER CYRILLIC SMALL KA;Lm;0;L; 043A;;;;N;;;;; +1E03A;MODIFIER LETTER CYRILLIC SMALL EL;Lm;0;L; 043B;;;;N;;;;; +1E03B;MODIFIER LETTER CYRILLIC SMALL EM;Lm;0;L; 043C;;;;N;;;;; +1E03C;MODIFIER LETTER CYRILLIC SMALL O;Lm;0;L; 043E;;;;N;;;;; +1E03D;MODIFIER LETTER CYRILLIC SMALL PE;Lm;0;L; 043F;;;;N;;;;; +1E03E;MODIFIER LETTER CYRILLIC SMALL ER;Lm;0;L; 0440;;;;N;;;;; +1E03F;MODIFIER LETTER CYRILLIC SMALL ES;Lm;0;L; 0441;;;;N;;;;; +1E040;MODIFIER LETTER CYRILLIC SMALL TE;Lm;0;L; 0442;;;;N;;;;; +1E041;MODIFIER LETTER CYRILLIC SMALL U;Lm;0;L; 0443;;;;N;;;;; +1E042;MODIFIER LETTER CYRILLIC SMALL EF;Lm;0;L; 0444;;;;N;;;;; +1E043;MODIFIER LETTER CYRILLIC SMALL HA;Lm;0;L; 0445;;;;N;;;;; +1E044;MODIFIER LETTER CYRILLIC SMALL TSE;Lm;0;L; 0446;;;;N;;;;; +1E045;MODIFIER LETTER CYRILLIC SMALL CHE;Lm;0;L; 0447;;;;N;;;;; +1E046;MODIFIER LETTER CYRILLIC SMALL SHA;Lm;0;L; 0448;;;;N;;;;; +1E047;MODIFIER LETTER CYRILLIC SMALL YERU;Lm;0;L; 044B;;;;N;;;;; +1E048;MODIFIER LETTER CYRILLIC SMALL E;Lm;0;L; 044D;;;;N;;;;; +1E049;MODIFIER LETTER CYRILLIC SMALL YU;Lm;0;L; 044E;;;;N;;;;; +1E04A;MODIFIER LETTER CYRILLIC SMALL DZZE;Lm;0;L; A689;;;;N;;;;; +1E04B;MODIFIER LETTER CYRILLIC SMALL SCHWA;Lm;0;L; 04D9;;;;N;;;;; +1E04C;MODIFIER LETTER CYRILLIC SMALL BYELORUSSIAN-UKRAINIAN I;Lm;0;L; 0456;;;;N;;;;; +1E04D;MODIFIER LETTER CYRILLIC SMALL JE;Lm;0;L; 0458;;;;N;;;;; +1E04E;MODIFIER LETTER CYRILLIC SMALL BARRED O;Lm;0;L; 04E9;;;;N;;;;; +1E04F;MODIFIER LETTER CYRILLIC SMALL STRAIGHT U;Lm;0;L; 04AF;;;;N;;;;; +1E050;MODIFIER LETTER CYRILLIC SMALL PALOCHKA;Lm;0;L; 04CF;;;;N;;;;; +1E051;CYRILLIC SUBSCRIPT SMALL LETTER A;Lm;0;L; 0430;;;;N;;;;; +1E052;CYRILLIC SUBSCRIPT SMALL LETTER BE;Lm;0;L; 0431;;;;N;;;;; +1E053;CYRILLIC SUBSCRIPT SMALL LETTER VE;Lm;0;L; 0432;;;;N;;;;; +1E054;CYRILLIC SUBSCRIPT SMALL LETTER GHE;Lm;0;L; 0433;;;;N;;;;; +1E055;CYRILLIC SUBSCRIPT SMALL LETTER DE;Lm;0;L; 0434;;;;N;;;;; +1E056;CYRILLIC SUBSCRIPT SMALL LETTER IE;Lm;0;L; 0435;;;;N;;;;; +1E057;CYRILLIC SUBSCRIPT SMALL LETTER ZHE;Lm;0;L; 0436;;;;N;;;;; +1E058;CYRILLIC SUBSCRIPT SMALL LETTER ZE;Lm;0;L; 0437;;;;N;;;;; +1E059;CYRILLIC SUBSCRIPT SMALL LETTER I;Lm;0;L; 0438;;;;N;;;;; +1E05A;CYRILLIC SUBSCRIPT SMALL LETTER KA;Lm;0;L; 043A;;;;N;;;;; +1E05B;CYRILLIC SUBSCRIPT SMALL LETTER EL;Lm;0;L; 043B;;;;N;;;;; +1E05C;CYRILLIC SUBSCRIPT SMALL LETTER O;Lm;0;L; 043E;;;;N;;;;; +1E05D;CYRILLIC SUBSCRIPT SMALL LETTER PE;Lm;0;L; 043F;;;;N;;;;; +1E05E;CYRILLIC SUBSCRIPT SMALL LETTER ES;Lm;0;L; 0441;;;;N;;;;; +1E05F;CYRILLIC SUBSCRIPT SMALL LETTER U;Lm;0;L; 0443;;;;N;;;;; +1E060;CYRILLIC SUBSCRIPT SMALL LETTER EF;Lm;0;L; 0444;;;;N;;;;; +1E061;CYRILLIC SUBSCRIPT SMALL LETTER HA;Lm;0;L; 0445;;;;N;;;;; +1E062;CYRILLIC SUBSCRIPT SMALL LETTER TSE;Lm;0;L; 0446;;;;N;;;;; +1E063;CYRILLIC SUBSCRIPT SMALL LETTER CHE;Lm;0;L; 0447;;;;N;;;;; +1E064;CYRILLIC SUBSCRIPT SMALL LETTER SHA;Lm;0;L; 0448;;;;N;;;;; +1E065;CYRILLIC SUBSCRIPT SMALL LETTER HARD SIGN;Lm;0;L; 044A;;;;N;;;;; +1E066;CYRILLIC SUBSCRIPT SMALL LETTER YERU;Lm;0;L; 044B;;;;N;;;;; +1E067;CYRILLIC SUBSCRIPT SMALL LETTER GHE WITH UPTURN;Lm;0;L; 0491;;;;N;;;;; +1E068;CYRILLIC SUBSCRIPT SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Lm;0;L; 0456;;;;N;;;;; +1E069;CYRILLIC SUBSCRIPT SMALL LETTER DZE;Lm;0;L; 0455;;;;N;;;;; +1E06A;CYRILLIC SUBSCRIPT SMALL LETTER DZHE;Lm;0;L; 045F;;;;N;;;;; +1E06B;MODIFIER LETTER CYRILLIC SMALL ES WITH DESCENDER;Lm;0;L; 04AB;;;;N;;;;; +1E06C;MODIFIER LETTER CYRILLIC SMALL YERU WITH BACK YER;Lm;0;L; A651;;;;N;;;;; +1E06D;MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE;Lm;0;L; 04B1;;;;N;;;;; +1E08F;COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I;Mn;230;NSM;;;;;N;;;;; +1E100;NYIAKENG PUACHUE HMONG LETTER MA;Lo;0;L;;;;;N;;;;; +1E101;NYIAKENG PUACHUE HMONG LETTER TSA;Lo;0;L;;;;;N;;;;; +1E102;NYIAKENG PUACHUE HMONG LETTER NTA;Lo;0;L;;;;;N;;;;; +1E103;NYIAKENG PUACHUE HMONG LETTER TA;Lo;0;L;;;;;N;;;;; +1E104;NYIAKENG PUACHUE HMONG LETTER HA;Lo;0;L;;;;;N;;;;; +1E105;NYIAKENG PUACHUE HMONG LETTER NA;Lo;0;L;;;;;N;;;;; +1E106;NYIAKENG PUACHUE HMONG LETTER XA;Lo;0;L;;;;;N;;;;; +1E107;NYIAKENG PUACHUE HMONG LETTER NKA;Lo;0;L;;;;;N;;;;; +1E108;NYIAKENG PUACHUE HMONG LETTER CA;Lo;0;L;;;;;N;;;;; +1E109;NYIAKENG PUACHUE HMONG LETTER LA;Lo;0;L;;;;;N;;;;; +1E10A;NYIAKENG PUACHUE HMONG LETTER SA;Lo;0;L;;;;;N;;;;; +1E10B;NYIAKENG PUACHUE HMONG LETTER ZA;Lo;0;L;;;;;N;;;;; +1E10C;NYIAKENG PUACHUE HMONG LETTER NCA;Lo;0;L;;;;;N;;;;; +1E10D;NYIAKENG PUACHUE HMONG LETTER NTSA;Lo;0;L;;;;;N;;;;; +1E10E;NYIAKENG PUACHUE HMONG LETTER KA;Lo;0;L;;;;;N;;;;; +1E10F;NYIAKENG PUACHUE HMONG LETTER DA;Lo;0;L;;;;;N;;;;; +1E110;NYIAKENG PUACHUE HMONG LETTER NYA;Lo;0;L;;;;;N;;;;; +1E111;NYIAKENG PUACHUE HMONG LETTER NRA;Lo;0;L;;;;;N;;;;; +1E112;NYIAKENG PUACHUE HMONG LETTER VA;Lo;0;L;;;;;N;;;;; +1E113;NYIAKENG PUACHUE HMONG LETTER NTXA;Lo;0;L;;;;;N;;;;; +1E114;NYIAKENG PUACHUE HMONG LETTER TXA;Lo;0;L;;;;;N;;;;; +1E115;NYIAKENG PUACHUE HMONG LETTER FA;Lo;0;L;;;;;N;;;;; +1E116;NYIAKENG PUACHUE HMONG LETTER RA;Lo;0;L;;;;;N;;;;; +1E117;NYIAKENG PUACHUE HMONG LETTER QA;Lo;0;L;;;;;N;;;;; +1E118;NYIAKENG PUACHUE HMONG LETTER YA;Lo;0;L;;;;;N;;;;; +1E119;NYIAKENG PUACHUE HMONG LETTER NQA;Lo;0;L;;;;;N;;;;; +1E11A;NYIAKENG PUACHUE HMONG LETTER PA;Lo;0;L;;;;;N;;;;; +1E11B;NYIAKENG PUACHUE HMONG LETTER XYA;Lo;0;L;;;;;N;;;;; +1E11C;NYIAKENG PUACHUE HMONG LETTER NPA;Lo;0;L;;;;;N;;;;; +1E11D;NYIAKENG PUACHUE HMONG LETTER DLA;Lo;0;L;;;;;N;;;;; +1E11E;NYIAKENG PUACHUE HMONG LETTER NPLA;Lo;0;L;;;;;N;;;;; +1E11F;NYIAKENG PUACHUE HMONG LETTER HAH;Lo;0;L;;;;;N;;;;; +1E120;NYIAKENG PUACHUE HMONG LETTER MLA;Lo;0;L;;;;;N;;;;; +1E121;NYIAKENG PUACHUE HMONG LETTER PLA;Lo;0;L;;;;;N;;;;; +1E122;NYIAKENG PUACHUE HMONG LETTER GA;Lo;0;L;;;;;N;;;;; +1E123;NYIAKENG PUACHUE HMONG LETTER RRA;Lo;0;L;;;;;N;;;;; +1E124;NYIAKENG PUACHUE HMONG LETTER A;Lo;0;L;;;;;N;;;;; +1E125;NYIAKENG PUACHUE HMONG LETTER AA;Lo;0;L;;;;;N;;;;; +1E126;NYIAKENG PUACHUE HMONG LETTER I;Lo;0;L;;;;;N;;;;; +1E127;NYIAKENG PUACHUE HMONG LETTER U;Lo;0;L;;;;;N;;;;; +1E128;NYIAKENG PUACHUE HMONG LETTER O;Lo;0;L;;;;;N;;;;; +1E129;NYIAKENG PUACHUE HMONG LETTER OO;Lo;0;L;;;;;N;;;;; +1E12A;NYIAKENG PUACHUE HMONG LETTER E;Lo;0;L;;;;;N;;;;; +1E12B;NYIAKENG PUACHUE HMONG LETTER EE;Lo;0;L;;;;;N;;;;; +1E12C;NYIAKENG PUACHUE HMONG LETTER W;Lo;0;L;;;;;N;;;;; +1E130;NYIAKENG PUACHUE HMONG TONE-B;Mn;230;NSM;;;;;N;;;;; +1E131;NYIAKENG PUACHUE HMONG TONE-M;Mn;230;NSM;;;;;N;;;;; +1E132;NYIAKENG PUACHUE HMONG TONE-J;Mn;230;NSM;;;;;N;;;;; +1E133;NYIAKENG PUACHUE HMONG TONE-V;Mn;230;NSM;;;;;N;;;;; +1E134;NYIAKENG PUACHUE HMONG TONE-S;Mn;230;NSM;;;;;N;;;;; +1E135;NYIAKENG PUACHUE HMONG TONE-G;Mn;230;NSM;;;;;N;;;;; +1E136;NYIAKENG PUACHUE HMONG TONE-D;Mn;230;NSM;;;;;N;;;;; +1E137;NYIAKENG PUACHUE HMONG SIGN FOR PERSON;Lm;0;L;;;;;N;;;;; +1E138;NYIAKENG PUACHUE HMONG SIGN FOR THING;Lm;0;L;;;;;N;;;;; +1E139;NYIAKENG PUACHUE HMONG SIGN FOR LOCATION;Lm;0;L;;;;;N;;;;; +1E13A;NYIAKENG PUACHUE HMONG SIGN FOR ANIMAL;Lm;0;L;;;;;N;;;;; +1E13B;NYIAKENG PUACHUE HMONG SIGN FOR INVERTEBRATE;Lm;0;L;;;;;N;;;;; +1E13C;NYIAKENG PUACHUE HMONG SIGN XW XW;Lm;0;L;;;;;N;;;;; +1E13D;NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER;Lm;0;L;;;;;N;;;;; +1E140;NYIAKENG PUACHUE HMONG DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1E141;NYIAKENG PUACHUE HMONG DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1E142;NYIAKENG PUACHUE HMONG DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1E143;NYIAKENG PUACHUE HMONG DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1E144;NYIAKENG PUACHUE HMONG DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1E145;NYIAKENG PUACHUE HMONG DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1E146;NYIAKENG PUACHUE HMONG DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1E147;NYIAKENG PUACHUE HMONG DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1E148;NYIAKENG PUACHUE HMONG DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1E149;NYIAKENG PUACHUE HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1E14E;NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ;Lo;0;L;;;;;N;;;;; +1E14F;NYIAKENG PUACHUE HMONG CIRCLED CA;So;0;L;;;;;N;;;;; +1E290;TOTO LETTER PA;Lo;0;L;;;;;N;;;;; +1E291;TOTO LETTER BA;Lo;0;L;;;;;N;;;;; +1E292;TOTO LETTER TA;Lo;0;L;;;;;N;;;;; +1E293;TOTO LETTER DA;Lo;0;L;;;;;N;;;;; +1E294;TOTO LETTER KA;Lo;0;L;;;;;N;;;;; +1E295;TOTO LETTER GA;Lo;0;L;;;;;N;;;;; +1E296;TOTO LETTER MA;Lo;0;L;;;;;N;;;;; +1E297;TOTO LETTER NA;Lo;0;L;;;;;N;;;;; +1E298;TOTO LETTER NGA;Lo;0;L;;;;;N;;;;; +1E299;TOTO LETTER SA;Lo;0;L;;;;;N;;;;; +1E29A;TOTO LETTER CHA;Lo;0;L;;;;;N;;;;; +1E29B;TOTO LETTER YA;Lo;0;L;;;;;N;;;;; +1E29C;TOTO LETTER WA;Lo;0;L;;;;;N;;;;; +1E29D;TOTO LETTER JA;Lo;0;L;;;;;N;;;;; +1E29E;TOTO LETTER HA;Lo;0;L;;;;;N;;;;; +1E29F;TOTO LETTER RA;Lo;0;L;;;;;N;;;;; +1E2A0;TOTO LETTER LA;Lo;0;L;;;;;N;;;;; +1E2A1;TOTO LETTER I;Lo;0;L;;;;;N;;;;; +1E2A2;TOTO LETTER BREATHY I;Lo;0;L;;;;;N;;;;; +1E2A3;TOTO LETTER IU;Lo;0;L;;;;;N;;;;; +1E2A4;TOTO LETTER BREATHY IU;Lo;0;L;;;;;N;;;;; +1E2A5;TOTO LETTER U;Lo;0;L;;;;;N;;;;; +1E2A6;TOTO LETTER E;Lo;0;L;;;;;N;;;;; +1E2A7;TOTO LETTER BREATHY E;Lo;0;L;;;;;N;;;;; +1E2A8;TOTO LETTER EO;Lo;0;L;;;;;N;;;;; +1E2A9;TOTO LETTER BREATHY EO;Lo;0;L;;;;;N;;;;; +1E2AA;TOTO LETTER O;Lo;0;L;;;;;N;;;;; +1E2AB;TOTO LETTER AE;Lo;0;L;;;;;N;;;;; +1E2AC;TOTO LETTER BREATHY AE;Lo;0;L;;;;;N;;;;; +1E2AD;TOTO LETTER A;Lo;0;L;;;;;N;;;;; +1E2AE;TOTO SIGN RISING TONE;Mn;230;NSM;;;;;N;;;;; +1E2C0;WANCHO LETTER AA;Lo;0;L;;;;;N;;;;; +1E2C1;WANCHO LETTER A;Lo;0;L;;;;;N;;;;; +1E2C2;WANCHO LETTER BA;Lo;0;L;;;;;N;;;;; +1E2C3;WANCHO LETTER CA;Lo;0;L;;;;;N;;;;; +1E2C4;WANCHO LETTER DA;Lo;0;L;;;;;N;;;;; +1E2C5;WANCHO LETTER GA;Lo;0;L;;;;;N;;;;; +1E2C6;WANCHO LETTER YA;Lo;0;L;;;;;N;;;;; +1E2C7;WANCHO LETTER PHA;Lo;0;L;;;;;N;;;;; +1E2C8;WANCHO LETTER LA;Lo;0;L;;;;;N;;;;; +1E2C9;WANCHO LETTER NA;Lo;0;L;;;;;N;;;;; +1E2CA;WANCHO LETTER PA;Lo;0;L;;;;;N;;;;; +1E2CB;WANCHO LETTER TA;Lo;0;L;;;;;N;;;;; +1E2CC;WANCHO LETTER THA;Lo;0;L;;;;;N;;;;; +1E2CD;WANCHO LETTER FA;Lo;0;L;;;;;N;;;;; +1E2CE;WANCHO LETTER SA;Lo;0;L;;;;;N;;;;; +1E2CF;WANCHO LETTER SHA;Lo;0;L;;;;;N;;;;; +1E2D0;WANCHO LETTER JA;Lo;0;L;;;;;N;;;;; +1E2D1;WANCHO LETTER ZA;Lo;0;L;;;;;N;;;;; +1E2D2;WANCHO LETTER WA;Lo;0;L;;;;;N;;;;; +1E2D3;WANCHO LETTER VA;Lo;0;L;;;;;N;;;;; +1E2D4;WANCHO LETTER KA;Lo;0;L;;;;;N;;;;; +1E2D5;WANCHO LETTER O;Lo;0;L;;;;;N;;;;; +1E2D6;WANCHO LETTER AU;Lo;0;L;;;;;N;;;;; +1E2D7;WANCHO LETTER RA;Lo;0;L;;;;;N;;;;; +1E2D8;WANCHO LETTER MA;Lo;0;L;;;;;N;;;;; +1E2D9;WANCHO LETTER KHA;Lo;0;L;;;;;N;;;;; +1E2DA;WANCHO LETTER HA;Lo;0;L;;;;;N;;;;; +1E2DB;WANCHO LETTER E;Lo;0;L;;;;;N;;;;; +1E2DC;WANCHO LETTER I;Lo;0;L;;;;;N;;;;; +1E2DD;WANCHO LETTER NGA;Lo;0;L;;;;;N;;;;; +1E2DE;WANCHO LETTER U;Lo;0;L;;;;;N;;;;; +1E2DF;WANCHO LETTER LLHA;Lo;0;L;;;;;N;;;;; +1E2E0;WANCHO LETTER TSA;Lo;0;L;;;;;N;;;;; +1E2E1;WANCHO LETTER TRA;Lo;0;L;;;;;N;;;;; +1E2E2;WANCHO LETTER ONG;Lo;0;L;;;;;N;;;;; +1E2E3;WANCHO LETTER AANG;Lo;0;L;;;;;N;;;;; +1E2E4;WANCHO LETTER ANG;Lo;0;L;;;;;N;;;;; +1E2E5;WANCHO LETTER ING;Lo;0;L;;;;;N;;;;; +1E2E6;WANCHO LETTER ON;Lo;0;L;;;;;N;;;;; +1E2E7;WANCHO LETTER EN;Lo;0;L;;;;;N;;;;; +1E2E8;WANCHO LETTER AAN;Lo;0;L;;;;;N;;;;; +1E2E9;WANCHO LETTER NYA;Lo;0;L;;;;;N;;;;; +1E2EA;WANCHO LETTER UEN;Lo;0;L;;;;;N;;;;; +1E2EB;WANCHO LETTER YIH;Lo;0;L;;;;;N;;;;; +1E2EC;WANCHO TONE TUP;Mn;230;NSM;;;;;N;;;;; +1E2ED;WANCHO TONE TUPNI;Mn;230;NSM;;;;;N;;;;; +1E2EE;WANCHO TONE KOI;Mn;230;NSM;;;;;N;;;;; +1E2EF;WANCHO TONE KOINI;Mn;230;NSM;;;;;N;;;;; +1E2F0;WANCHO DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1E2F1;WANCHO DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1E2F2;WANCHO DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1E2F3;WANCHO DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1E2F4;WANCHO DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1E2F5;WANCHO DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1E2F6;WANCHO DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1E2F7;WANCHO DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1E2F8;WANCHO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1E2F9;WANCHO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1E2FF;WANCHO NGUN SIGN;Sc;0;ET;;;;;N;;;;; +1E4D0;NAG MUNDARI LETTER O;Lo;0;L;;;;;N;;;;; +1E4D1;NAG MUNDARI LETTER OP;Lo;0;L;;;;;N;;;;; +1E4D2;NAG MUNDARI LETTER OL;Lo;0;L;;;;;N;;;;; +1E4D3;NAG MUNDARI LETTER OY;Lo;0;L;;;;;N;;;;; +1E4D4;NAG MUNDARI LETTER ONG;Lo;0;L;;;;;N;;;;; +1E4D5;NAG MUNDARI LETTER A;Lo;0;L;;;;;N;;;;; +1E4D6;NAG MUNDARI LETTER AJ;Lo;0;L;;;;;N;;;;; +1E4D7;NAG MUNDARI LETTER AB;Lo;0;L;;;;;N;;;;; +1E4D8;NAG MUNDARI LETTER ANY;Lo;0;L;;;;;N;;;;; +1E4D9;NAG MUNDARI LETTER AH;Lo;0;L;;;;;N;;;;; +1E4DA;NAG MUNDARI LETTER I;Lo;0;L;;;;;N;;;;; +1E4DB;NAG MUNDARI LETTER IS;Lo;0;L;;;;;N;;;;; +1E4DC;NAG MUNDARI LETTER IDD;Lo;0;L;;;;;N;;;;; +1E4DD;NAG MUNDARI LETTER IT;Lo;0;L;;;;;N;;;;; +1E4DE;NAG MUNDARI LETTER IH;Lo;0;L;;;;;N;;;;; +1E4DF;NAG MUNDARI LETTER U;Lo;0;L;;;;;N;;;;; +1E4E0;NAG MUNDARI LETTER UC;Lo;0;L;;;;;N;;;;; +1E4E1;NAG MUNDARI LETTER UD;Lo;0;L;;;;;N;;;;; +1E4E2;NAG MUNDARI LETTER UK;Lo;0;L;;;;;N;;;;; +1E4E3;NAG MUNDARI LETTER UR;Lo;0;L;;;;;N;;;;; +1E4E4;NAG MUNDARI LETTER E;Lo;0;L;;;;;N;;;;; +1E4E5;NAG MUNDARI LETTER ENN;Lo;0;L;;;;;N;;;;; +1E4E6;NAG MUNDARI LETTER EG;Lo;0;L;;;;;N;;;;; +1E4E7;NAG MUNDARI LETTER EM;Lo;0;L;;;;;N;;;;; +1E4E8;NAG MUNDARI LETTER EN;Lo;0;L;;;;;N;;;;; +1E4E9;NAG MUNDARI LETTER ETT;Lo;0;L;;;;;N;;;;; +1E4EA;NAG MUNDARI LETTER ELL;Lo;0;L;;;;;N;;;;; +1E4EB;NAG MUNDARI SIGN OJOD;Lm;0;L;;;;;N;;;;; +1E4EC;NAG MUNDARI SIGN MUHOR;Mn;232;NSM;;;;;N;;;;; +1E4ED;NAG MUNDARI SIGN TOYOR;Mn;232;NSM;;;;;N;;;;; +1E4EE;NAG MUNDARI SIGN IKIR;Mn;220;NSM;;;;;N;;;;; +1E4EF;NAG MUNDARI SIGN SUTUH;Mn;230;NSM;;;;;N;;;;; +1E4F0;NAG MUNDARI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1E4F1;NAG MUNDARI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1E4F2;NAG MUNDARI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1E4F3;NAG MUNDARI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1E4F4;NAG MUNDARI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1E4F5;NAG MUNDARI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1E4F6;NAG MUNDARI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1E4F7;NAG MUNDARI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1E4F8;NAG MUNDARI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1E4F9;NAG MUNDARI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1E5D0;OL ONAL LETTER O;Lo;0;L;;;;;N;;;;; +1E5D1;OL ONAL LETTER OM;Lo;0;L;;;;;N;;;;; +1E5D2;OL ONAL LETTER ONG;Lo;0;L;;;;;N;;;;; +1E5D3;OL ONAL LETTER ORR;Lo;0;L;;;;;N;;;;; +1E5D4;OL ONAL LETTER OO;Lo;0;L;;;;;N;;;;; +1E5D5;OL ONAL LETTER OY;Lo;0;L;;;;;N;;;;; +1E5D6;OL ONAL LETTER A;Lo;0;L;;;;;N;;;;; +1E5D7;OL ONAL LETTER AD;Lo;0;L;;;;;N;;;;; +1E5D8;OL ONAL LETTER AB;Lo;0;L;;;;;N;;;;; +1E5D9;OL ONAL LETTER AH;Lo;0;L;;;;;N;;;;; +1E5DA;OL ONAL LETTER AL;Lo;0;L;;;;;N;;;;; +1E5DB;OL ONAL LETTER AW;Lo;0;L;;;;;N;;;;; +1E5DC;OL ONAL LETTER I;Lo;0;L;;;;;N;;;;; +1E5DD;OL ONAL LETTER IT;Lo;0;L;;;;;N;;;;; +1E5DE;OL ONAL LETTER IP;Lo;0;L;;;;;N;;;;; +1E5DF;OL ONAL LETTER ITT;Lo;0;L;;;;;N;;;;; +1E5E0;OL ONAL LETTER ID;Lo;0;L;;;;;N;;;;; +1E5E1;OL ONAL LETTER IN;Lo;0;L;;;;;N;;;;; +1E5E2;OL ONAL LETTER U;Lo;0;L;;;;;N;;;;; +1E5E3;OL ONAL LETTER UK;Lo;0;L;;;;;N;;;;; +1E5E4;OL ONAL LETTER UDD;Lo;0;L;;;;;N;;;;; +1E5E5;OL ONAL LETTER UJ;Lo;0;L;;;;;N;;;;; +1E5E6;OL ONAL LETTER UNY;Lo;0;L;;;;;N;;;;; +1E5E7;OL ONAL LETTER UR;Lo;0;L;;;;;N;;;;; +1E5E8;OL ONAL LETTER E;Lo;0;L;;;;;N;;;;; +1E5E9;OL ONAL LETTER ES;Lo;0;L;;;;;N;;;;; +1E5EA;OL ONAL LETTER EH;Lo;0;L;;;;;N;;;;; +1E5EB;OL ONAL LETTER EC;Lo;0;L;;;;;N;;;;; +1E5EC;OL ONAL LETTER ENN;Lo;0;L;;;;;N;;;;; +1E5ED;OL ONAL LETTER EG;Lo;0;L;;;;;N;;;;; +1E5EE;OL ONAL SIGN MU;Mn;230;NSM;;;;;N;;;;; +1E5EF;OL ONAL SIGN IKIR;Mn;220;NSM;;;;;N;;;;; +1E5F0;OL ONAL SIGN HODDOND;Lo;0;L;;;;;N;;;;; +1E5F1;OL ONAL DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +1E5F2;OL ONAL DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +1E5F3;OL ONAL DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +1E5F4;OL ONAL DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1E5F5;OL ONAL DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1E5F6;OL ONAL DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1E5F7;OL ONAL DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1E5F8;OL ONAL DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1E5F9;OL ONAL DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1E5FA;OL ONAL DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1E5FF;OL ONAL ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; +1E6C0;TAI YO LETTER LOW KO;Lo;0;L;;;;;N;;;;; +1E6C1;TAI YO LETTER HIGH KO;Lo;0;L;;;;;N;;;;; +1E6C2;TAI YO LETTER LOW KHO;Lo;0;L;;;;;N;;;;; +1E6C3;TAI YO LETTER HIGH KHO;Lo;0;L;;;;;N;;;;; +1E6C4;TAI YO LETTER GO;Lo;0;L;;;;;N;;;;; +1E6C5;TAI YO LETTER NGO;Lo;0;L;;;;;N;;;;; +1E6C6;TAI YO LETTER CO;Lo;0;L;;;;;N;;;;; +1E6C7;TAI YO LETTER LOW XO;Lo;0;L;;;;;N;;;;; +1E6C8;TAI YO LETTER HIGH XO;Lo;0;L;;;;;N;;;;; +1E6C9;TAI YO LETTER LOW NYO;Lo;0;L;;;;;N;;;;; +1E6CA;TAI YO LETTER HIGH NYO;Lo;0;L;;;;;N;;;;; +1E6CB;TAI YO LETTER DO;Lo;0;L;;;;;N;;;;; +1E6CC;TAI YO LETTER LOW TO;Lo;0;L;;;;;N;;;;; +1E6CD;TAI YO LETTER HIGH TO;Lo;0;L;;;;;N;;;;; +1E6CE;TAI YO LETTER THO;Lo;0;L;;;;;N;;;;; +1E6CF;TAI YO LETTER NO;Lo;0;L;;;;;N;;;;; +1E6D0;TAI YO LETTER BO;Lo;0;L;;;;;N;;;;; +1E6D1;TAI YO LETTER LOW PO;Lo;0;L;;;;;N;;;;; +1E6D2;TAI YO LETTER HIGH PO;Lo;0;L;;;;;N;;;;; +1E6D3;TAI YO LETTER PHO;Lo;0;L;;;;;N;;;;; +1E6D4;TAI YO LETTER LOW FO;Lo;0;L;;;;;N;;;;; +1E6D5;TAI YO LETTER HIGH FO;Lo;0;L;;;;;N;;;;; +1E6D6;TAI YO LETTER MO;Lo;0;L;;;;;N;;;;; +1E6D7;TAI YO LETTER YO;Lo;0;L;;;;;N;;;;; +1E6D8;TAI YO LETTER LO;Lo;0;L;;;;;N;;;;; +1E6D9;TAI YO LETTER VO;Lo;0;L;;;;;N;;;;; +1E6DA;TAI YO LETTER LOW HO;Lo;0;L;;;;;N;;;;; +1E6DB;TAI YO LETTER HIGH HO;Lo;0;L;;;;;N;;;;; +1E6DC;TAI YO LETTER QO;Lo;0;L;;;;;N;;;;; +1E6DD;TAI YO LETTER LOW KVO;Lo;0;L;;;;;N;;;;; +1E6DE;TAI YO LETTER HIGH KVO;Lo;0;L;;;;;N;;;;; +1E6E0;TAI YO LETTER AA;Lo;0;L;;;;;N;;;;; +1E6E1;TAI YO LETTER I;Lo;0;L;;;;;N;;;;; +1E6E2;TAI YO LETTER UE;Lo;0;L;;;;;N;;;;; +1E6E3;TAI YO SIGN UE;Mn;230;NSM;;;;;N;;;;; +1E6E4;TAI YO LETTER U;Lo;0;L;;;;;N;;;;; +1E6E5;TAI YO LETTER AE;Lo;0;L;;;;;N;;;;; +1E6E6;TAI YO SIGN AU;Mn;230;NSM;;;;;N;;;;; +1E6E7;TAI YO LETTER O;Lo;0;L;;;;;N;;;;; +1E6E8;TAI YO LETTER E;Lo;0;L;;;;;N;;;;; +1E6E9;TAI YO LETTER IA;Lo;0;L;;;;;N;;;;; +1E6EA;TAI YO LETTER UEA;Lo;0;L;;;;;N;;;;; +1E6EB;TAI YO LETTER UA;Lo;0;L;;;;;N;;;;; +1E6EC;TAI YO LETTER OO;Lo;0;L;;;;;N;;;;; +1E6ED;TAI YO LETTER AUE;Lo;0;L;;;;;N;;;;; +1E6EE;TAI YO SIGN AY;Mn;230;NSM;;;;;N;;;;; +1E6EF;TAI YO SIGN ANG;Mn;230;NSM;;;;;N;;;;; +1E6F0;TAI YO LETTER AN;Lo;0;L;;;;;N;;;;; +1E6F1;TAI YO LETTER AM;Lo;0;L;;;;;N;;;;; +1E6F2;TAI YO LETTER AK;Lo;0;L;;;;;N;;;;; +1E6F3;TAI YO LETTER AT;Lo;0;L;;;;;N;;;;; +1E6F4;TAI YO LETTER AP;Lo;0;L;;;;;N;;;;; +1E6F5;TAI YO SIGN OM;Mn;230;NSM;;;;;N;;;;; +1E6FE;TAI YO SYMBOL MUEANG;Lo;0;L;;;;;N;;;;; +1E6FF;TAI YO XAM LAI;Lm;0;L;;;;;N;;;;; +1E7E0;ETHIOPIC SYLLABLE HHYA;Lo;0;L;;;;;N;;;;; +1E7E1;ETHIOPIC SYLLABLE HHYU;Lo;0;L;;;;;N;;;;; +1E7E2;ETHIOPIC SYLLABLE HHYI;Lo;0;L;;;;;N;;;;; +1E7E3;ETHIOPIC SYLLABLE HHYAA;Lo;0;L;;;;;N;;;;; +1E7E4;ETHIOPIC SYLLABLE HHYEE;Lo;0;L;;;;;N;;;;; +1E7E5;ETHIOPIC SYLLABLE HHYE;Lo;0;L;;;;;N;;;;; +1E7E6;ETHIOPIC SYLLABLE HHYO;Lo;0;L;;;;;N;;;;; +1E7E8;ETHIOPIC SYLLABLE GURAGE HHWA;Lo;0;L;;;;;N;;;;; +1E7E9;ETHIOPIC SYLLABLE HHWI;Lo;0;L;;;;;N;;;;; +1E7EA;ETHIOPIC SYLLABLE HHWEE;Lo;0;L;;;;;N;;;;; +1E7EB;ETHIOPIC SYLLABLE HHWE;Lo;0;L;;;;;N;;;;; +1E7ED;ETHIOPIC SYLLABLE GURAGE MWI;Lo;0;L;;;;;N;;;;; +1E7EE;ETHIOPIC SYLLABLE GURAGE MWEE;Lo;0;L;;;;;N;;;;; +1E7F0;ETHIOPIC SYLLABLE GURAGE QWI;Lo;0;L;;;;;N;;;;; +1E7F1;ETHIOPIC SYLLABLE GURAGE QWEE;Lo;0;L;;;;;N;;;;; +1E7F2;ETHIOPIC SYLLABLE GURAGE QWE;Lo;0;L;;;;;N;;;;; +1E7F3;ETHIOPIC SYLLABLE GURAGE BWI;Lo;0;L;;;;;N;;;;; +1E7F4;ETHIOPIC SYLLABLE GURAGE BWEE;Lo;0;L;;;;;N;;;;; +1E7F5;ETHIOPIC SYLLABLE GURAGE KWI;Lo;0;L;;;;;N;;;;; +1E7F6;ETHIOPIC SYLLABLE GURAGE KWEE;Lo;0;L;;;;;N;;;;; +1E7F7;ETHIOPIC SYLLABLE GURAGE KWE;Lo;0;L;;;;;N;;;;; +1E7F8;ETHIOPIC SYLLABLE GURAGE GWI;Lo;0;L;;;;;N;;;;; +1E7F9;ETHIOPIC SYLLABLE GURAGE GWEE;Lo;0;L;;;;;N;;;;; +1E7FA;ETHIOPIC SYLLABLE GURAGE GWE;Lo;0;L;;;;;N;;;;; +1E7FB;ETHIOPIC SYLLABLE GURAGE FWI;Lo;0;L;;;;;N;;;;; +1E7FC;ETHIOPIC SYLLABLE GURAGE FWEE;Lo;0;L;;;;;N;;;;; +1E7FD;ETHIOPIC SYLLABLE GURAGE PWI;Lo;0;L;;;;;N;;;;; +1E7FE;ETHIOPIC SYLLABLE GURAGE PWEE;Lo;0;L;;;;;N;;;;; +1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;; +1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;; +1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;; +1E803;MENDE KIKAKUI SYLLABLE M065 KEE;Lo;0;R;;;;;N;;;;; +1E804;MENDE KIKAKUI SYLLABLE M095 KE;Lo;0;R;;;;;N;;;;; +1E805;MENDE KIKAKUI SYLLABLE M076 KOO;Lo;0;R;;;;;N;;;;; +1E806;MENDE KIKAKUI SYLLABLE M048 KO;Lo;0;R;;;;;N;;;;; +1E807;MENDE KIKAKUI SYLLABLE M179 KUA;Lo;0;R;;;;;N;;;;; +1E808;MENDE KIKAKUI SYLLABLE M004 WI;Lo;0;R;;;;;N;;;;; +1E809;MENDE KIKAKUI SYLLABLE M005 WA;Lo;0;R;;;;;N;;;;; +1E80A;MENDE KIKAKUI SYLLABLE M006 WU;Lo;0;R;;;;;N;;;;; +1E80B;MENDE KIKAKUI SYLLABLE M126 WEE;Lo;0;R;;;;;N;;;;; +1E80C;MENDE KIKAKUI SYLLABLE M118 WE;Lo;0;R;;;;;N;;;;; +1E80D;MENDE KIKAKUI SYLLABLE M114 WOO;Lo;0;R;;;;;N;;;;; +1E80E;MENDE KIKAKUI SYLLABLE M045 WO;Lo;0;R;;;;;N;;;;; +1E80F;MENDE KIKAKUI SYLLABLE M194 WUI;Lo;0;R;;;;;N;;;;; +1E810;MENDE KIKAKUI SYLLABLE M143 WEI;Lo;0;R;;;;;N;;;;; +1E811;MENDE KIKAKUI SYLLABLE M061 WVI;Lo;0;R;;;;;N;;;;; +1E812;MENDE KIKAKUI SYLLABLE M049 WVA;Lo;0;R;;;;;N;;;;; +1E813;MENDE KIKAKUI SYLLABLE M139 WVE;Lo;0;R;;;;;N;;;;; +1E814;MENDE KIKAKUI SYLLABLE M007 MIN;Lo;0;R;;;;;N;;;;; +1E815;MENDE KIKAKUI SYLLABLE M008 MAN;Lo;0;R;;;;;N;;;;; +1E816;MENDE KIKAKUI SYLLABLE M009 MUN;Lo;0;R;;;;;N;;;;; +1E817;MENDE KIKAKUI SYLLABLE M059 MEN;Lo;0;R;;;;;N;;;;; +1E818;MENDE KIKAKUI SYLLABLE M094 MON;Lo;0;R;;;;;N;;;;; +1E819;MENDE KIKAKUI SYLLABLE M154 MUAN;Lo;0;R;;;;;N;;;;; +1E81A;MENDE KIKAKUI SYLLABLE M189 MUEN;Lo;0;R;;;;;N;;;;; +1E81B;MENDE KIKAKUI SYLLABLE M010 BI;Lo;0;R;;;;;N;;;;; +1E81C;MENDE KIKAKUI SYLLABLE M011 BA;Lo;0;R;;;;;N;;;;; +1E81D;MENDE KIKAKUI SYLLABLE M012 BU;Lo;0;R;;;;;N;;;;; +1E81E;MENDE KIKAKUI SYLLABLE M150 BEE;Lo;0;R;;;;;N;;;;; +1E81F;MENDE KIKAKUI SYLLABLE M097 BE;Lo;0;R;;;;;N;;;;; +1E820;MENDE KIKAKUI SYLLABLE M103 BOO;Lo;0;R;;;;;N;;;;; +1E821;MENDE KIKAKUI SYLLABLE M138 BO;Lo;0;R;;;;;N;;;;; +1E822;MENDE KIKAKUI SYLLABLE M013 I;Lo;0;R;;;;;N;;;;; +1E823;MENDE KIKAKUI SYLLABLE M014 A;Lo;0;R;;;;;N;;;;; +1E824;MENDE KIKAKUI SYLLABLE M015 U;Lo;0;R;;;;;N;;;;; +1E825;MENDE KIKAKUI SYLLABLE M163 EE;Lo;0;R;;;;;N;;;;; +1E826;MENDE KIKAKUI SYLLABLE M100 E;Lo;0;R;;;;;N;;;;; +1E827;MENDE KIKAKUI SYLLABLE M165 OO;Lo;0;R;;;;;N;;;;; +1E828;MENDE KIKAKUI SYLLABLE M147 O;Lo;0;R;;;;;N;;;;; +1E829;MENDE KIKAKUI SYLLABLE M137 EI;Lo;0;R;;;;;N;;;;; +1E82A;MENDE KIKAKUI SYLLABLE M131 IN;Lo;0;R;;;;;N;;;;; +1E82B;MENDE KIKAKUI SYLLABLE M135 IN;Lo;0;R;;;;;N;;;;; +1E82C;MENDE KIKAKUI SYLLABLE M195 AN;Lo;0;R;;;;;N;;;;; +1E82D;MENDE KIKAKUI SYLLABLE M178 EN;Lo;0;R;;;;;N;;;;; +1E82E;MENDE KIKAKUI SYLLABLE M019 SI;Lo;0;R;;;;;N;;;;; +1E82F;MENDE KIKAKUI SYLLABLE M020 SA;Lo;0;R;;;;;N;;;;; +1E830;MENDE KIKAKUI SYLLABLE M021 SU;Lo;0;R;;;;;N;;;;; +1E831;MENDE KIKAKUI SYLLABLE M162 SEE;Lo;0;R;;;;;N;;;;; +1E832;MENDE KIKAKUI SYLLABLE M116 SE;Lo;0;R;;;;;N;;;;; +1E833;MENDE KIKAKUI SYLLABLE M136 SOO;Lo;0;R;;;;;N;;;;; +1E834;MENDE KIKAKUI SYLLABLE M079 SO;Lo;0;R;;;;;N;;;;; +1E835;MENDE KIKAKUI SYLLABLE M196 SIA;Lo;0;R;;;;;N;;;;; +1E836;MENDE KIKAKUI SYLLABLE M025 LI;Lo;0;R;;;;;N;;;;; +1E837;MENDE KIKAKUI SYLLABLE M026 LA;Lo;0;R;;;;;N;;;;; +1E838;MENDE KIKAKUI SYLLABLE M027 LU;Lo;0;R;;;;;N;;;;; +1E839;MENDE KIKAKUI SYLLABLE M084 LEE;Lo;0;R;;;;;N;;;;; +1E83A;MENDE KIKAKUI SYLLABLE M073 LE;Lo;0;R;;;;;N;;;;; +1E83B;MENDE KIKAKUI SYLLABLE M054 LOO;Lo;0;R;;;;;N;;;;; +1E83C;MENDE KIKAKUI SYLLABLE M153 LO;Lo;0;R;;;;;N;;;;; +1E83D;MENDE KIKAKUI SYLLABLE M110 LONG LE;Lo;0;R;;;;;N;;;;; +1E83E;MENDE KIKAKUI SYLLABLE M016 DI;Lo;0;R;;;;;N;;;;; +1E83F;MENDE KIKAKUI SYLLABLE M017 DA;Lo;0;R;;;;;N;;;;; +1E840;MENDE KIKAKUI SYLLABLE M018 DU;Lo;0;R;;;;;N;;;;; +1E841;MENDE KIKAKUI SYLLABLE M089 DEE;Lo;0;R;;;;;N;;;;; +1E842;MENDE KIKAKUI SYLLABLE M180 DOO;Lo;0;R;;;;;N;;;;; +1E843;MENDE KIKAKUI SYLLABLE M181 DO;Lo;0;R;;;;;N;;;;; +1E844;MENDE KIKAKUI SYLLABLE M022 TI;Lo;0;R;;;;;N;;;;; +1E845;MENDE KIKAKUI SYLLABLE M023 TA;Lo;0;R;;;;;N;;;;; +1E846;MENDE KIKAKUI SYLLABLE M024 TU;Lo;0;R;;;;;N;;;;; +1E847;MENDE KIKAKUI SYLLABLE M091 TEE;Lo;0;R;;;;;N;;;;; +1E848;MENDE KIKAKUI SYLLABLE M055 TE;Lo;0;R;;;;;N;;;;; +1E849;MENDE KIKAKUI SYLLABLE M104 TOO;Lo;0;R;;;;;N;;;;; +1E84A;MENDE KIKAKUI SYLLABLE M069 TO;Lo;0;R;;;;;N;;;;; +1E84B;MENDE KIKAKUI SYLLABLE M028 JI;Lo;0;R;;;;;N;;;;; +1E84C;MENDE KIKAKUI SYLLABLE M029 JA;Lo;0;R;;;;;N;;;;; +1E84D;MENDE KIKAKUI SYLLABLE M030 JU;Lo;0;R;;;;;N;;;;; +1E84E;MENDE KIKAKUI SYLLABLE M157 JEE;Lo;0;R;;;;;N;;;;; +1E84F;MENDE KIKAKUI SYLLABLE M113 JE;Lo;0;R;;;;;N;;;;; +1E850;MENDE KIKAKUI SYLLABLE M160 JOO;Lo;0;R;;;;;N;;;;; +1E851;MENDE KIKAKUI SYLLABLE M063 JO;Lo;0;R;;;;;N;;;;; +1E852;MENDE KIKAKUI SYLLABLE M175 LONG JO;Lo;0;R;;;;;N;;;;; +1E853;MENDE KIKAKUI SYLLABLE M031 YI;Lo;0;R;;;;;N;;;;; +1E854;MENDE KIKAKUI SYLLABLE M032 YA;Lo;0;R;;;;;N;;;;; +1E855;MENDE KIKAKUI SYLLABLE M033 YU;Lo;0;R;;;;;N;;;;; +1E856;MENDE KIKAKUI SYLLABLE M109 YEE;Lo;0;R;;;;;N;;;;; +1E857;MENDE KIKAKUI SYLLABLE M080 YE;Lo;0;R;;;;;N;;;;; +1E858;MENDE KIKAKUI SYLLABLE M141 YOO;Lo;0;R;;;;;N;;;;; +1E859;MENDE KIKAKUI SYLLABLE M121 YO;Lo;0;R;;;;;N;;;;; +1E85A;MENDE KIKAKUI SYLLABLE M034 FI;Lo;0;R;;;;;N;;;;; +1E85B;MENDE KIKAKUI SYLLABLE M035 FA;Lo;0;R;;;;;N;;;;; +1E85C;MENDE KIKAKUI SYLLABLE M036 FU;Lo;0;R;;;;;N;;;;; +1E85D;MENDE KIKAKUI SYLLABLE M078 FEE;Lo;0;R;;;;;N;;;;; +1E85E;MENDE KIKAKUI SYLLABLE M075 FE;Lo;0;R;;;;;N;;;;; +1E85F;MENDE KIKAKUI SYLLABLE M133 FOO;Lo;0;R;;;;;N;;;;; +1E860;MENDE KIKAKUI SYLLABLE M088 FO;Lo;0;R;;;;;N;;;;; +1E861;MENDE KIKAKUI SYLLABLE M197 FUA;Lo;0;R;;;;;N;;;;; +1E862;MENDE KIKAKUI SYLLABLE M101 FAN;Lo;0;R;;;;;N;;;;; +1E863;MENDE KIKAKUI SYLLABLE M037 NIN;Lo;0;R;;;;;N;;;;; +1E864;MENDE KIKAKUI SYLLABLE M038 NAN;Lo;0;R;;;;;N;;;;; +1E865;MENDE KIKAKUI SYLLABLE M039 NUN;Lo;0;R;;;;;N;;;;; +1E866;MENDE KIKAKUI SYLLABLE M117 NEN;Lo;0;R;;;;;N;;;;; +1E867;MENDE KIKAKUI SYLLABLE M169 NON;Lo;0;R;;;;;N;;;;; +1E868;MENDE KIKAKUI SYLLABLE M176 HI;Lo;0;R;;;;;N;;;;; +1E869;MENDE KIKAKUI SYLLABLE M041 HA;Lo;0;R;;;;;N;;;;; +1E86A;MENDE KIKAKUI SYLLABLE M186 HU;Lo;0;R;;;;;N;;;;; +1E86B;MENDE KIKAKUI SYLLABLE M040 HEE;Lo;0;R;;;;;N;;;;; +1E86C;MENDE KIKAKUI SYLLABLE M096 HE;Lo;0;R;;;;;N;;;;; +1E86D;MENDE KIKAKUI SYLLABLE M042 HOO;Lo;0;R;;;;;N;;;;; +1E86E;MENDE KIKAKUI SYLLABLE M140 HO;Lo;0;R;;;;;N;;;;; +1E86F;MENDE KIKAKUI SYLLABLE M083 HEEI;Lo;0;R;;;;;N;;;;; +1E870;MENDE KIKAKUI SYLLABLE M128 HOOU;Lo;0;R;;;;;N;;;;; +1E871;MENDE KIKAKUI SYLLABLE M053 HIN;Lo;0;R;;;;;N;;;;; +1E872;MENDE KIKAKUI SYLLABLE M130 HAN;Lo;0;R;;;;;N;;;;; +1E873;MENDE KIKAKUI SYLLABLE M087 HUN;Lo;0;R;;;;;N;;;;; +1E874;MENDE KIKAKUI SYLLABLE M052 HEN;Lo;0;R;;;;;N;;;;; +1E875;MENDE KIKAKUI SYLLABLE M193 HON;Lo;0;R;;;;;N;;;;; +1E876;MENDE KIKAKUI SYLLABLE M046 HUAN;Lo;0;R;;;;;N;;;;; +1E877;MENDE KIKAKUI SYLLABLE M090 NGGI;Lo;0;R;;;;;N;;;;; +1E878;MENDE KIKAKUI SYLLABLE M043 NGGA;Lo;0;R;;;;;N;;;;; +1E879;MENDE KIKAKUI SYLLABLE M082 NGGU;Lo;0;R;;;;;N;;;;; +1E87A;MENDE KIKAKUI SYLLABLE M115 NGGEE;Lo;0;R;;;;;N;;;;; +1E87B;MENDE KIKAKUI SYLLABLE M146 NGGE;Lo;0;R;;;;;N;;;;; +1E87C;MENDE KIKAKUI SYLLABLE M156 NGGOO;Lo;0;R;;;;;N;;;;; +1E87D;MENDE KIKAKUI SYLLABLE M120 NGGO;Lo;0;R;;;;;N;;;;; +1E87E;MENDE KIKAKUI SYLLABLE M159 NGGAA;Lo;0;R;;;;;N;;;;; +1E87F;MENDE KIKAKUI SYLLABLE M127 NGGUA;Lo;0;R;;;;;N;;;;; +1E880;MENDE KIKAKUI SYLLABLE M086 LONG NGGE;Lo;0;R;;;;;N;;;;; +1E881;MENDE KIKAKUI SYLLABLE M106 LONG NGGOO;Lo;0;R;;;;;N;;;;; +1E882;MENDE KIKAKUI SYLLABLE M183 LONG NGGO;Lo;0;R;;;;;N;;;;; +1E883;MENDE KIKAKUI SYLLABLE M155 GI;Lo;0;R;;;;;N;;;;; +1E884;MENDE KIKAKUI SYLLABLE M111 GA;Lo;0;R;;;;;N;;;;; +1E885;MENDE KIKAKUI SYLLABLE M168 GU;Lo;0;R;;;;;N;;;;; +1E886;MENDE KIKAKUI SYLLABLE M190 GEE;Lo;0;R;;;;;N;;;;; +1E887;MENDE KIKAKUI SYLLABLE M166 GUEI;Lo;0;R;;;;;N;;;;; +1E888;MENDE KIKAKUI SYLLABLE M167 GUAN;Lo;0;R;;;;;N;;;;; +1E889;MENDE KIKAKUI SYLLABLE M184 NGEN;Lo;0;R;;;;;N;;;;; +1E88A;MENDE KIKAKUI SYLLABLE M057 NGON;Lo;0;R;;;;;N;;;;; +1E88B;MENDE KIKAKUI SYLLABLE M177 NGUAN;Lo;0;R;;;;;N;;;;; +1E88C;MENDE KIKAKUI SYLLABLE M068 PI;Lo;0;R;;;;;N;;;;; +1E88D;MENDE KIKAKUI SYLLABLE M099 PA;Lo;0;R;;;;;N;;;;; +1E88E;MENDE KIKAKUI SYLLABLE M050 PU;Lo;0;R;;;;;N;;;;; +1E88F;MENDE KIKAKUI SYLLABLE M081 PEE;Lo;0;R;;;;;N;;;;; +1E890;MENDE KIKAKUI SYLLABLE M051 PE;Lo;0;R;;;;;N;;;;; +1E891;MENDE KIKAKUI SYLLABLE M102 POO;Lo;0;R;;;;;N;;;;; +1E892;MENDE KIKAKUI SYLLABLE M066 PO;Lo;0;R;;;;;N;;;;; +1E893;MENDE KIKAKUI SYLLABLE M145 MBI;Lo;0;R;;;;;N;;;;; +1E894;MENDE KIKAKUI SYLLABLE M062 MBA;Lo;0;R;;;;;N;;;;; +1E895;MENDE KIKAKUI SYLLABLE M122 MBU;Lo;0;R;;;;;N;;;;; +1E896;MENDE KIKAKUI SYLLABLE M047 MBEE;Lo;0;R;;;;;N;;;;; +1E897;MENDE KIKAKUI SYLLABLE M188 MBEE;Lo;0;R;;;;;N;;;;; +1E898;MENDE KIKAKUI SYLLABLE M072 MBE;Lo;0;R;;;;;N;;;;; +1E899;MENDE KIKAKUI SYLLABLE M172 MBOO;Lo;0;R;;;;;N;;;;; +1E89A;MENDE KIKAKUI SYLLABLE M174 MBO;Lo;0;R;;;;;N;;;;; +1E89B;MENDE KIKAKUI SYLLABLE M187 MBUU;Lo;0;R;;;;;N;;;;; +1E89C;MENDE KIKAKUI SYLLABLE M161 LONG MBE;Lo;0;R;;;;;N;;;;; +1E89D;MENDE KIKAKUI SYLLABLE M105 LONG MBOO;Lo;0;R;;;;;N;;;;; +1E89E;MENDE KIKAKUI SYLLABLE M142 LONG MBO;Lo;0;R;;;;;N;;;;; +1E89F;MENDE KIKAKUI SYLLABLE M132 KPI;Lo;0;R;;;;;N;;;;; +1E8A0;MENDE KIKAKUI SYLLABLE M092 KPA;Lo;0;R;;;;;N;;;;; +1E8A1;MENDE KIKAKUI SYLLABLE M074 KPU;Lo;0;R;;;;;N;;;;; +1E8A2;MENDE KIKAKUI SYLLABLE M044 KPEE;Lo;0;R;;;;;N;;;;; +1E8A3;MENDE KIKAKUI SYLLABLE M108 KPE;Lo;0;R;;;;;N;;;;; +1E8A4;MENDE KIKAKUI SYLLABLE M112 KPOO;Lo;0;R;;;;;N;;;;; +1E8A5;MENDE KIKAKUI SYLLABLE M158 KPO;Lo;0;R;;;;;N;;;;; +1E8A6;MENDE KIKAKUI SYLLABLE M124 GBI;Lo;0;R;;;;;N;;;;; +1E8A7;MENDE KIKAKUI SYLLABLE M056 GBA;Lo;0;R;;;;;N;;;;; +1E8A8;MENDE KIKAKUI SYLLABLE M148 GBU;Lo;0;R;;;;;N;;;;; +1E8A9;MENDE KIKAKUI SYLLABLE M093 GBEE;Lo;0;R;;;;;N;;;;; +1E8AA;MENDE KIKAKUI SYLLABLE M107 GBE;Lo;0;R;;;;;N;;;;; +1E8AB;MENDE KIKAKUI SYLLABLE M071 GBOO;Lo;0;R;;;;;N;;;;; +1E8AC;MENDE KIKAKUI SYLLABLE M070 GBO;Lo;0;R;;;;;N;;;;; +1E8AD;MENDE KIKAKUI SYLLABLE M171 RA;Lo;0;R;;;;;N;;;;; +1E8AE;MENDE KIKAKUI SYLLABLE M123 NDI;Lo;0;R;;;;;N;;;;; +1E8AF;MENDE KIKAKUI SYLLABLE M129 NDA;Lo;0;R;;;;;N;;;;; +1E8B0;MENDE KIKAKUI SYLLABLE M125 NDU;Lo;0;R;;;;;N;;;;; +1E8B1;MENDE KIKAKUI SYLLABLE M191 NDEE;Lo;0;R;;;;;N;;;;; +1E8B2;MENDE KIKAKUI SYLLABLE M119 NDE;Lo;0;R;;;;;N;;;;; +1E8B3;MENDE KIKAKUI SYLLABLE M067 NDOO;Lo;0;R;;;;;N;;;;; +1E8B4;MENDE KIKAKUI SYLLABLE M064 NDO;Lo;0;R;;;;;N;;;;; +1E8B5;MENDE KIKAKUI SYLLABLE M152 NJA;Lo;0;R;;;;;N;;;;; +1E8B6;MENDE KIKAKUI SYLLABLE M192 NJU;Lo;0;R;;;;;N;;;;; +1E8B7;MENDE KIKAKUI SYLLABLE M149 NJEE;Lo;0;R;;;;;N;;;;; +1E8B8;MENDE KIKAKUI SYLLABLE M134 NJOO;Lo;0;R;;;;;N;;;;; +1E8B9;MENDE KIKAKUI SYLLABLE M182 VI;Lo;0;R;;;;;N;;;;; +1E8BA;MENDE KIKAKUI SYLLABLE M185 VA;Lo;0;R;;;;;N;;;;; +1E8BB;MENDE KIKAKUI SYLLABLE M151 VU;Lo;0;R;;;;;N;;;;; +1E8BC;MENDE KIKAKUI SYLLABLE M173 VEE;Lo;0;R;;;;;N;;;;; +1E8BD;MENDE KIKAKUI SYLLABLE M085 VE;Lo;0;R;;;;;N;;;;; +1E8BE;MENDE KIKAKUI SYLLABLE M144 VOO;Lo;0;R;;;;;N;;;;; +1E8BF;MENDE KIKAKUI SYLLABLE M077 VO;Lo;0;R;;;;;N;;;;; +1E8C0;MENDE KIKAKUI SYLLABLE M164 NYIN;Lo;0;R;;;;;N;;;;; +1E8C1;MENDE KIKAKUI SYLLABLE M058 NYAN;Lo;0;R;;;;;N;;;;; +1E8C2;MENDE KIKAKUI SYLLABLE M170 NYUN;Lo;0;R;;;;;N;;;;; +1E8C3;MENDE KIKAKUI SYLLABLE M098 NYEN;Lo;0;R;;;;;N;;;;; +1E8C4;MENDE KIKAKUI SYLLABLE M060 NYON;Lo;0;R;;;;;N;;;;; +1E8C7;MENDE KIKAKUI DIGIT ONE;No;0;R;;;;1;N;;;;; +1E8C8;MENDE KIKAKUI DIGIT TWO;No;0;R;;;;2;N;;;;; +1E8C9;MENDE KIKAKUI DIGIT THREE;No;0;R;;;;3;N;;;;; +1E8CA;MENDE KIKAKUI DIGIT FOUR;No;0;R;;;;4;N;;;;; +1E8CB;MENDE KIKAKUI DIGIT FIVE;No;0;R;;;;5;N;;;;; +1E8CC;MENDE KIKAKUI DIGIT SIX;No;0;R;;;;6;N;;;;; +1E8CD;MENDE KIKAKUI DIGIT SEVEN;No;0;R;;;;7;N;;;;; +1E8CE;MENDE KIKAKUI DIGIT EIGHT;No;0;R;;;;8;N;;;;; +1E8CF;MENDE KIKAKUI DIGIT NINE;No;0;R;;;;9;N;;;;; +1E8D0;MENDE KIKAKUI COMBINING NUMBER TEENS;Mn;220;NSM;;;;;N;;;;; +1E8D1;MENDE KIKAKUI COMBINING NUMBER TENS;Mn;220;NSM;;;;;N;;;;; +1E8D2;MENDE KIKAKUI COMBINING NUMBER HUNDREDS;Mn;220;NSM;;;;;N;;;;; +1E8D3;MENDE KIKAKUI COMBINING NUMBER THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D4;MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D5;MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS;Mn;220;NSM;;;;;N;;;;; +1E8D6;MENDE KIKAKUI COMBINING NUMBER MILLIONS;Mn;220;NSM;;;;;N;;;;; +1E900;ADLAM CAPITAL LETTER ALIF;Lu;0;R;;;;;N;;;;1E922; +1E901;ADLAM CAPITAL LETTER DAALI;Lu;0;R;;;;;N;;;;1E923; +1E902;ADLAM CAPITAL LETTER LAAM;Lu;0;R;;;;;N;;;;1E924; +1E903;ADLAM CAPITAL LETTER MIIM;Lu;0;R;;;;;N;;;;1E925; +1E904;ADLAM CAPITAL LETTER BA;Lu;0;R;;;;;N;;;;1E926; +1E905;ADLAM CAPITAL LETTER SINNYIIYHE;Lu;0;R;;;;;N;;;;1E927; +1E906;ADLAM CAPITAL LETTER PE;Lu;0;R;;;;;N;;;;1E928; +1E907;ADLAM CAPITAL LETTER BHE;Lu;0;R;;;;;N;;;;1E929; +1E908;ADLAM CAPITAL LETTER RA;Lu;0;R;;;;;N;;;;1E92A; +1E909;ADLAM CAPITAL LETTER E;Lu;0;R;;;;;N;;;;1E92B; +1E90A;ADLAM CAPITAL LETTER FA;Lu;0;R;;;;;N;;;;1E92C; +1E90B;ADLAM CAPITAL LETTER I;Lu;0;R;;;;;N;;;;1E92D; +1E90C;ADLAM CAPITAL LETTER O;Lu;0;R;;;;;N;;;;1E92E; +1E90D;ADLAM CAPITAL LETTER DHA;Lu;0;R;;;;;N;;;;1E92F; +1E90E;ADLAM CAPITAL LETTER YHE;Lu;0;R;;;;;N;;;;1E930; +1E90F;ADLAM CAPITAL LETTER WAW;Lu;0;R;;;;;N;;;;1E931; +1E910;ADLAM CAPITAL LETTER NUN;Lu;0;R;;;;;N;;;;1E932; +1E911;ADLAM CAPITAL LETTER KAF;Lu;0;R;;;;;N;;;;1E933; +1E912;ADLAM CAPITAL LETTER YA;Lu;0;R;;;;;N;;;;1E934; +1E913;ADLAM CAPITAL LETTER U;Lu;0;R;;;;;N;;;;1E935; +1E914;ADLAM CAPITAL LETTER JIIM;Lu;0;R;;;;;N;;;;1E936; +1E915;ADLAM CAPITAL LETTER CHI;Lu;0;R;;;;;N;;;;1E937; +1E916;ADLAM CAPITAL LETTER HA;Lu;0;R;;;;;N;;;;1E938; +1E917;ADLAM CAPITAL LETTER QAAF;Lu;0;R;;;;;N;;;;1E939; +1E918;ADLAM CAPITAL LETTER GA;Lu;0;R;;;;;N;;;;1E93A; +1E919;ADLAM CAPITAL LETTER NYA;Lu;0;R;;;;;N;;;;1E93B; +1E91A;ADLAM CAPITAL LETTER TU;Lu;0;R;;;;;N;;;;1E93C; +1E91B;ADLAM CAPITAL LETTER NHA;Lu;0;R;;;;;N;;;;1E93D; +1E91C;ADLAM CAPITAL LETTER VA;Lu;0;R;;;;;N;;;;1E93E; +1E91D;ADLAM CAPITAL LETTER KHA;Lu;0;R;;;;;N;;;;1E93F; +1E91E;ADLAM CAPITAL LETTER GBE;Lu;0;R;;;;;N;;;;1E940; +1E91F;ADLAM CAPITAL LETTER ZAL;Lu;0;R;;;;;N;;;;1E941; +1E920;ADLAM CAPITAL LETTER KPO;Lu;0;R;;;;;N;;;;1E942; +1E921;ADLAM CAPITAL LETTER SHA;Lu;0;R;;;;;N;;;;1E943; +1E922;ADLAM SMALL LETTER ALIF;Ll;0;R;;;;;N;;;1E900;;1E900 +1E923;ADLAM SMALL LETTER DAALI;Ll;0;R;;;;;N;;;1E901;;1E901 +1E924;ADLAM SMALL LETTER LAAM;Ll;0;R;;;;;N;;;1E902;;1E902 +1E925;ADLAM SMALL LETTER MIIM;Ll;0;R;;;;;N;;;1E903;;1E903 +1E926;ADLAM SMALL LETTER BA;Ll;0;R;;;;;N;;;1E904;;1E904 +1E927;ADLAM SMALL LETTER SINNYIIYHE;Ll;0;R;;;;;N;;;1E905;;1E905 +1E928;ADLAM SMALL LETTER PE;Ll;0;R;;;;;N;;;1E906;;1E906 +1E929;ADLAM SMALL LETTER BHE;Ll;0;R;;;;;N;;;1E907;;1E907 +1E92A;ADLAM SMALL LETTER RA;Ll;0;R;;;;;N;;;1E908;;1E908 +1E92B;ADLAM SMALL LETTER E;Ll;0;R;;;;;N;;;1E909;;1E909 +1E92C;ADLAM SMALL LETTER FA;Ll;0;R;;;;;N;;;1E90A;;1E90A +1E92D;ADLAM SMALL LETTER I;Ll;0;R;;;;;N;;;1E90B;;1E90B +1E92E;ADLAM SMALL LETTER O;Ll;0;R;;;;;N;;;1E90C;;1E90C +1E92F;ADLAM SMALL LETTER DHA;Ll;0;R;;;;;N;;;1E90D;;1E90D +1E930;ADLAM SMALL LETTER YHE;Ll;0;R;;;;;N;;;1E90E;;1E90E +1E931;ADLAM SMALL LETTER WAW;Ll;0;R;;;;;N;;;1E90F;;1E90F +1E932;ADLAM SMALL LETTER NUN;Ll;0;R;;;;;N;;;1E910;;1E910 +1E933;ADLAM SMALL LETTER KAF;Ll;0;R;;;;;N;;;1E911;;1E911 +1E934;ADLAM SMALL LETTER YA;Ll;0;R;;;;;N;;;1E912;;1E912 +1E935;ADLAM SMALL LETTER U;Ll;0;R;;;;;N;;;1E913;;1E913 +1E936;ADLAM SMALL LETTER JIIM;Ll;0;R;;;;;N;;;1E914;;1E914 +1E937;ADLAM SMALL LETTER CHI;Ll;0;R;;;;;N;;;1E915;;1E915 +1E938;ADLAM SMALL LETTER HA;Ll;0;R;;;;;N;;;1E916;;1E916 +1E939;ADLAM SMALL LETTER QAAF;Ll;0;R;;;;;N;;;1E917;;1E917 +1E93A;ADLAM SMALL LETTER GA;Ll;0;R;;;;;N;;;1E918;;1E918 +1E93B;ADLAM SMALL LETTER NYA;Ll;0;R;;;;;N;;;1E919;;1E919 +1E93C;ADLAM SMALL LETTER TU;Ll;0;R;;;;;N;;;1E91A;;1E91A +1E93D;ADLAM SMALL LETTER NHA;Ll;0;R;;;;;N;;;1E91B;;1E91B +1E93E;ADLAM SMALL LETTER VA;Ll;0;R;;;;;N;;;1E91C;;1E91C +1E93F;ADLAM SMALL LETTER KHA;Ll;0;R;;;;;N;;;1E91D;;1E91D +1E940;ADLAM SMALL LETTER GBE;Ll;0;R;;;;;N;;;1E91E;;1E91E +1E941;ADLAM SMALL LETTER ZAL;Ll;0;R;;;;;N;;;1E91F;;1E91F +1E942;ADLAM SMALL LETTER KPO;Ll;0;R;;;;;N;;;1E920;;1E920 +1E943;ADLAM SMALL LETTER SHA;Ll;0;R;;;;;N;;;1E921;;1E921 +1E944;ADLAM ALIF LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E945;ADLAM VOWEL LENGTHENER;Mn;230;NSM;;;;;N;;;;; +1E946;ADLAM GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; +1E947;ADLAM HAMZA;Mn;230;NSM;;;;;N;;;;; +1E948;ADLAM CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E949;ADLAM GEMINATE CONSONANT MODIFIER;Mn;230;NSM;;;;;N;;;;; +1E94A;ADLAM NUKTA;Mn;7;NSM;;;;;N;;;;; +1E94B;ADLAM NASALIZATION MARK;Lm;0;R;;;;;N;;;;; +1E950;ADLAM DIGIT ZERO;Nd;0;R;;0;0;0;N;;;;; +1E951;ADLAM DIGIT ONE;Nd;0;R;;1;1;1;N;;;;; +1E952;ADLAM DIGIT TWO;Nd;0;R;;2;2;2;N;;;;; +1E953;ADLAM DIGIT THREE;Nd;0;R;;3;3;3;N;;;;; +1E954;ADLAM DIGIT FOUR;Nd;0;R;;4;4;4;N;;;;; +1E955;ADLAM DIGIT FIVE;Nd;0;R;;5;5;5;N;;;;; +1E956;ADLAM DIGIT SIX;Nd;0;R;;6;6;6;N;;;;; +1E957;ADLAM DIGIT SEVEN;Nd;0;R;;7;7;7;N;;;;; +1E958;ADLAM DIGIT EIGHT;Nd;0;R;;8;8;8;N;;;;; +1E959;ADLAM DIGIT NINE;Nd;0;R;;9;9;9;N;;;;; +1E95E;ADLAM INITIAL EXCLAMATION MARK;Po;0;R;;;;;N;;;;; +1E95F;ADLAM INITIAL QUESTION MARK;Po;0;R;;;;;N;;;;; +1EC71;INDIC SIYAQ NUMBER ONE;No;0;AL;;;;1;N;;;;; +1EC72;INDIC SIYAQ NUMBER TWO;No;0;AL;;;;2;N;;;;; +1EC73;INDIC SIYAQ NUMBER THREE;No;0;AL;;;;3;N;;;;; +1EC74;INDIC SIYAQ NUMBER FOUR;No;0;AL;;;;4;N;;;;; +1EC75;INDIC SIYAQ NUMBER FIVE;No;0;AL;;;;5;N;;;;; +1EC76;INDIC SIYAQ NUMBER SIX;No;0;AL;;;;6;N;;;;; +1EC77;INDIC SIYAQ NUMBER SEVEN;No;0;AL;;;;7;N;;;;; +1EC78;INDIC SIYAQ NUMBER EIGHT;No;0;AL;;;;8;N;;;;; +1EC79;INDIC SIYAQ NUMBER NINE;No;0;AL;;;;9;N;;;;; +1EC7A;INDIC SIYAQ NUMBER TEN;No;0;AL;;;;10;N;;;;; +1EC7B;INDIC SIYAQ NUMBER TWENTY;No;0;AL;;;;20;N;;;;; +1EC7C;INDIC SIYAQ NUMBER THIRTY;No;0;AL;;;;30;N;;;;; +1EC7D;INDIC SIYAQ NUMBER FORTY;No;0;AL;;;;40;N;;;;; +1EC7E;INDIC SIYAQ NUMBER FIFTY;No;0;AL;;;;50;N;;;;; +1EC7F;INDIC SIYAQ NUMBER SIXTY;No;0;AL;;;;60;N;;;;; +1EC80;INDIC SIYAQ NUMBER SEVENTY;No;0;AL;;;;70;N;;;;; +1EC81;INDIC SIYAQ NUMBER EIGHTY;No;0;AL;;;;80;N;;;;; +1EC82;INDIC SIYAQ NUMBER NINETY;No;0;AL;;;;90;N;;;;; +1EC83;INDIC SIYAQ NUMBER ONE HUNDRED;No;0;AL;;;;100;N;;;;; +1EC84;INDIC SIYAQ NUMBER TWO HUNDRED;No;0;AL;;;;200;N;;;;; +1EC85;INDIC SIYAQ NUMBER THREE HUNDRED;No;0;AL;;;;300;N;;;;; +1EC86;INDIC SIYAQ NUMBER FOUR HUNDRED;No;0;AL;;;;400;N;;;;; +1EC87;INDIC SIYAQ NUMBER FIVE HUNDRED;No;0;AL;;;;500;N;;;;; +1EC88;INDIC SIYAQ NUMBER SIX HUNDRED;No;0;AL;;;;600;N;;;;; +1EC89;INDIC SIYAQ NUMBER SEVEN HUNDRED;No;0;AL;;;;700;N;;;;; +1EC8A;INDIC SIYAQ NUMBER EIGHT HUNDRED;No;0;AL;;;;800;N;;;;; +1EC8B;INDIC SIYAQ NUMBER NINE HUNDRED;No;0;AL;;;;900;N;;;;; +1EC8C;INDIC SIYAQ NUMBER ONE THOUSAND;No;0;AL;;;;1000;N;;;;; +1EC8D;INDIC SIYAQ NUMBER TWO THOUSAND;No;0;AL;;;;2000;N;;;;; +1EC8E;INDIC SIYAQ NUMBER THREE THOUSAND;No;0;AL;;;;3000;N;;;;; +1EC8F;INDIC SIYAQ NUMBER FOUR THOUSAND;No;0;AL;;;;4000;N;;;;; +1EC90;INDIC SIYAQ NUMBER FIVE THOUSAND;No;0;AL;;;;5000;N;;;;; +1EC91;INDIC SIYAQ NUMBER SIX THOUSAND;No;0;AL;;;;6000;N;;;;; +1EC92;INDIC SIYAQ NUMBER SEVEN THOUSAND;No;0;AL;;;;7000;N;;;;; +1EC93;INDIC SIYAQ NUMBER EIGHT THOUSAND;No;0;AL;;;;8000;N;;;;; +1EC94;INDIC SIYAQ NUMBER NINE THOUSAND;No;0;AL;;;;9000;N;;;;; +1EC95;INDIC SIYAQ NUMBER TEN THOUSAND;No;0;AL;;;;10000;N;;;;; +1EC96;INDIC SIYAQ NUMBER TWENTY THOUSAND;No;0;AL;;;;20000;N;;;;; +1EC97;INDIC SIYAQ NUMBER THIRTY THOUSAND;No;0;AL;;;;30000;N;;;;; +1EC98;INDIC SIYAQ NUMBER FORTY THOUSAND;No;0;AL;;;;40000;N;;;;; +1EC99;INDIC SIYAQ NUMBER FIFTY THOUSAND;No;0;AL;;;;50000;N;;;;; +1EC9A;INDIC SIYAQ NUMBER SIXTY THOUSAND;No;0;AL;;;;60000;N;;;;; +1EC9B;INDIC SIYAQ NUMBER SEVENTY THOUSAND;No;0;AL;;;;70000;N;;;;; +1EC9C;INDIC SIYAQ NUMBER EIGHTY THOUSAND;No;0;AL;;;;80000;N;;;;; +1EC9D;INDIC SIYAQ NUMBER NINETY THOUSAND;No;0;AL;;;;90000;N;;;;; +1EC9E;INDIC SIYAQ NUMBER LAKH;No;0;AL;;;;100000;N;;;;; +1EC9F;INDIC SIYAQ NUMBER LAKHAN;No;0;AL;;;;200000;N;;;;; +1ECA0;INDIC SIYAQ LAKH MARK;No;0;AL;;;;100000;N;;;;; +1ECA1;INDIC SIYAQ NUMBER KAROR;No;0;AL;;;;10000000;N;;;;; +1ECA2;INDIC SIYAQ NUMBER KARORAN;No;0;AL;;;;20000000;N;;;;; +1ECA3;INDIC SIYAQ NUMBER PREFIXED ONE;No;0;AL;;;;1;N;;;;; +1ECA4;INDIC SIYAQ NUMBER PREFIXED TWO;No;0;AL;;;;2;N;;;;; +1ECA5;INDIC SIYAQ NUMBER PREFIXED THREE;No;0;AL;;;;3;N;;;;; +1ECA6;INDIC SIYAQ NUMBER PREFIXED FOUR;No;0;AL;;;;4;N;;;;; +1ECA7;INDIC SIYAQ NUMBER PREFIXED FIVE;No;0;AL;;;;5;N;;;;; +1ECA8;INDIC SIYAQ NUMBER PREFIXED SIX;No;0;AL;;;;6;N;;;;; +1ECA9;INDIC SIYAQ NUMBER PREFIXED SEVEN;No;0;AL;;;;7;N;;;;; +1ECAA;INDIC SIYAQ NUMBER PREFIXED EIGHT;No;0;AL;;;;8;N;;;;; +1ECAB;INDIC SIYAQ NUMBER PREFIXED NINE;No;0;AL;;;;9;N;;;;; +1ECAC;INDIC SIYAQ PLACEHOLDER;So;0;AL;;;;;N;;;;; +1ECAD;INDIC SIYAQ FRACTION ONE QUARTER;No;0;AL;;;;1/4;N;;;;; +1ECAE;INDIC SIYAQ FRACTION ONE HALF;No;0;AL;;;;1/2;N;;;;; +1ECAF;INDIC SIYAQ FRACTION THREE QUARTERS;No;0;AL;;;;3/4;N;;;;; +1ECB0;INDIC SIYAQ RUPEE MARK;Sc;0;AL;;;;;N;;;;; +1ECB1;INDIC SIYAQ NUMBER ALTERNATE ONE;No;0;AL;;;;1;N;;;;; +1ECB2;INDIC SIYAQ NUMBER ALTERNATE TWO;No;0;AL;;;;2;N;;;;; +1ECB3;INDIC SIYAQ NUMBER ALTERNATE TEN THOUSAND;No;0;AL;;;;10000;N;;;;; +1ECB4;INDIC SIYAQ ALTERNATE LAKH MARK;No;0;AL;;;;100000;N;;;;; +1ED01;OTTOMAN SIYAQ NUMBER ONE;No;0;AL;;;;1;N;;;;; +1ED02;OTTOMAN SIYAQ NUMBER TWO;No;0;AL;;;;2;N;;;;; +1ED03;OTTOMAN SIYAQ NUMBER THREE;No;0;AL;;;;3;N;;;;; +1ED04;OTTOMAN SIYAQ NUMBER FOUR;No;0;AL;;;;4;N;;;;; +1ED05;OTTOMAN SIYAQ NUMBER FIVE;No;0;AL;;;;5;N;;;;; +1ED06;OTTOMAN SIYAQ NUMBER SIX;No;0;AL;;;;6;N;;;;; +1ED07;OTTOMAN SIYAQ NUMBER SEVEN;No;0;AL;;;;7;N;;;;; +1ED08;OTTOMAN SIYAQ NUMBER EIGHT;No;0;AL;;;;8;N;;;;; +1ED09;OTTOMAN SIYAQ NUMBER NINE;No;0;AL;;;;9;N;;;;; +1ED0A;OTTOMAN SIYAQ NUMBER TEN;No;0;AL;;;;10;N;;;;; +1ED0B;OTTOMAN SIYAQ NUMBER TWENTY;No;0;AL;;;;20;N;;;;; +1ED0C;OTTOMAN SIYAQ NUMBER THIRTY;No;0;AL;;;;30;N;;;;; +1ED0D;OTTOMAN SIYAQ NUMBER FORTY;No;0;AL;;;;40;N;;;;; +1ED0E;OTTOMAN SIYAQ NUMBER FIFTY;No;0;AL;;;;50;N;;;;; +1ED0F;OTTOMAN SIYAQ NUMBER SIXTY;No;0;AL;;;;60;N;;;;; +1ED10;OTTOMAN SIYAQ NUMBER SEVENTY;No;0;AL;;;;70;N;;;;; +1ED11;OTTOMAN SIYAQ NUMBER EIGHTY;No;0;AL;;;;80;N;;;;; +1ED12;OTTOMAN SIYAQ NUMBER NINETY;No;0;AL;;;;90;N;;;;; +1ED13;OTTOMAN SIYAQ NUMBER ONE HUNDRED;No;0;AL;;;;100;N;;;;; +1ED14;OTTOMAN SIYAQ NUMBER TWO HUNDRED;No;0;AL;;;;200;N;;;;; +1ED15;OTTOMAN SIYAQ NUMBER THREE HUNDRED;No;0;AL;;;;300;N;;;;; +1ED16;OTTOMAN SIYAQ NUMBER FOUR HUNDRED;No;0;AL;;;;400;N;;;;; +1ED17;OTTOMAN SIYAQ NUMBER FIVE HUNDRED;No;0;AL;;;;500;N;;;;; +1ED18;OTTOMAN SIYAQ NUMBER SIX HUNDRED;No;0;AL;;;;600;N;;;;; +1ED19;OTTOMAN SIYAQ NUMBER SEVEN HUNDRED;No;0;AL;;;;700;N;;;;; +1ED1A;OTTOMAN SIYAQ NUMBER EIGHT HUNDRED;No;0;AL;;;;800;N;;;;; +1ED1B;OTTOMAN SIYAQ NUMBER NINE HUNDRED;No;0;AL;;;;900;N;;;;; +1ED1C;OTTOMAN SIYAQ NUMBER ONE THOUSAND;No;0;AL;;;;1000;N;;;;; +1ED1D;OTTOMAN SIYAQ NUMBER TWO THOUSAND;No;0;AL;;;;2000;N;;;;; +1ED1E;OTTOMAN SIYAQ NUMBER THREE THOUSAND;No;0;AL;;;;3000;N;;;;; +1ED1F;OTTOMAN SIYAQ NUMBER FOUR THOUSAND;No;0;AL;;;;4000;N;;;;; +1ED20;OTTOMAN SIYAQ NUMBER FIVE THOUSAND;No;0;AL;;;;5000;N;;;;; +1ED21;OTTOMAN SIYAQ NUMBER SIX THOUSAND;No;0;AL;;;;6000;N;;;;; +1ED22;OTTOMAN SIYAQ NUMBER SEVEN THOUSAND;No;0;AL;;;;7000;N;;;;; +1ED23;OTTOMAN SIYAQ NUMBER EIGHT THOUSAND;No;0;AL;;;;8000;N;;;;; +1ED24;OTTOMAN SIYAQ NUMBER NINE THOUSAND;No;0;AL;;;;9000;N;;;;; +1ED25;OTTOMAN SIYAQ NUMBER TEN THOUSAND;No;0;AL;;;;10000;N;;;;; +1ED26;OTTOMAN SIYAQ NUMBER TWENTY THOUSAND;No;0;AL;;;;20000;N;;;;; +1ED27;OTTOMAN SIYAQ NUMBER THIRTY THOUSAND;No;0;AL;;;;30000;N;;;;; +1ED28;OTTOMAN SIYAQ NUMBER FORTY THOUSAND;No;0;AL;;;;40000;N;;;;; +1ED29;OTTOMAN SIYAQ NUMBER FIFTY THOUSAND;No;0;AL;;;;50000;N;;;;; +1ED2A;OTTOMAN SIYAQ NUMBER SIXTY THOUSAND;No;0;AL;;;;60000;N;;;;; +1ED2B;OTTOMAN SIYAQ NUMBER SEVENTY THOUSAND;No;0;AL;;;;70000;N;;;;; +1ED2C;OTTOMAN SIYAQ NUMBER EIGHTY THOUSAND;No;0;AL;;;;80000;N;;;;; +1ED2D;OTTOMAN SIYAQ NUMBER NINETY THOUSAND;No;0;AL;;;;90000;N;;;;; +1ED2E;OTTOMAN SIYAQ MARRATAN;So;0;AL;;;;;N;;;;; +1ED2F;OTTOMAN SIYAQ ALTERNATE NUMBER TWO;No;0;AL;;;;2;N;;;;; +1ED30;OTTOMAN SIYAQ ALTERNATE NUMBER THREE;No;0;AL;;;;3;N;;;;; +1ED31;OTTOMAN SIYAQ ALTERNATE NUMBER FOUR;No;0;AL;;;;4;N;;;;; +1ED32;OTTOMAN SIYAQ ALTERNATE NUMBER FIVE;No;0;AL;;;;5;N;;;;; +1ED33;OTTOMAN SIYAQ ALTERNATE NUMBER SIX;No;0;AL;;;;6;N;;;;; +1ED34;OTTOMAN SIYAQ ALTERNATE NUMBER SEVEN;No;0;AL;;;;7;N;;;;; +1ED35;OTTOMAN SIYAQ ALTERNATE NUMBER EIGHT;No;0;AL;;;;8;N;;;;; +1ED36;OTTOMAN SIYAQ ALTERNATE NUMBER NINE;No;0;AL;;;;9;N;;;;; +1ED37;OTTOMAN SIYAQ ALTERNATE NUMBER TEN;No;0;AL;;;;10;N;;;;; +1ED38;OTTOMAN SIYAQ ALTERNATE NUMBER FOUR HUNDRED;No;0;AL;;;;400;N;;;;; +1ED39;OTTOMAN SIYAQ ALTERNATE NUMBER SIX HUNDRED;No;0;AL;;;;600;N;;;;; +1ED3A;OTTOMAN SIYAQ ALTERNATE NUMBER TWO THOUSAND;No;0;AL;;;;2000;N;;;;; +1ED3B;OTTOMAN SIYAQ ALTERNATE NUMBER TEN THOUSAND;No;0;AL;;;;10000;N;;;;; +1ED3C;OTTOMAN SIYAQ FRACTION ONE HALF;No;0;AL;;;;1/2;N;;;;; +1ED3D;OTTOMAN SIYAQ FRACTION ONE SIXTH;No;0;AL;;;;1/6;N;;;;; +1EE00;ARABIC MATHEMATICAL ALEF;Lo;0;AL; 0627;;;;N;;;;; +1EE01;ARABIC MATHEMATICAL BEH;Lo;0;AL; 0628;;;;N;;;;; +1EE02;ARABIC MATHEMATICAL JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EE03;ARABIC MATHEMATICAL DAL;Lo;0;AL; 062F;;;;N;;;;; +1EE05;ARABIC MATHEMATICAL WAW;Lo;0;AL; 0648;;;;N;;;;; +1EE06;ARABIC MATHEMATICAL ZAIN;Lo;0;AL; 0632;;;;N;;;;; +1EE07;ARABIC MATHEMATICAL HAH;Lo;0;AL; 062D;;;;N;;;;; +1EE08;ARABIC MATHEMATICAL TAH;Lo;0;AL; 0637;;;;N;;;;; +1EE09;ARABIC MATHEMATICAL YEH;Lo;0;AL; 064A;;;;N;;;;; +1EE0A;ARABIC MATHEMATICAL KAF;Lo;0;AL; 0643;;;;N;;;;; +1EE0B;ARABIC MATHEMATICAL LAM;Lo;0;AL; 0644;;;;N;;;;; +1EE0C;ARABIC MATHEMATICAL MEEM;Lo;0;AL; 0645;;;;N;;;;; +1EE0D;ARABIC MATHEMATICAL NOON;Lo;0;AL; 0646;;;;N;;;;; +1EE0E;ARABIC MATHEMATICAL SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EE0F;ARABIC MATHEMATICAL AIN;Lo;0;AL; 0639;;;;N;;;;; +1EE10;ARABIC MATHEMATICAL FEH;Lo;0;AL; 0641;;;;N;;;;; +1EE11;ARABIC MATHEMATICAL SAD;Lo;0;AL; 0635;;;;N;;;;; +1EE12;ARABIC MATHEMATICAL QAF;Lo;0;AL; 0642;;;;N;;;;; +1EE13;ARABIC MATHEMATICAL REH;Lo;0;AL; 0631;;;;N;;;;; +1EE14;ARABIC MATHEMATICAL SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EE15;ARABIC MATHEMATICAL TEH;Lo;0;AL; 062A;;;;N;;;;; +1EE16;ARABIC MATHEMATICAL THEH;Lo;0;AL; 062B;;;;N;;;;; +1EE17;ARABIC MATHEMATICAL KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EE18;ARABIC MATHEMATICAL THAL;Lo;0;AL; 0630;;;;N;;;;; +1EE19;ARABIC MATHEMATICAL DAD;Lo;0;AL; 0636;;;;N;;;;; +1EE1A;ARABIC MATHEMATICAL ZAH;Lo;0;AL; 0638;;;;N;;;;; +1EE1B;ARABIC MATHEMATICAL GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EE1C;ARABIC MATHEMATICAL DOTLESS BEH;Lo;0;AL; 066E;;;;N;;;;; +1EE1D;ARABIC MATHEMATICAL DOTLESS NOON;Lo;0;AL; 06BA;;;;N;;;;; +1EE1E;ARABIC MATHEMATICAL DOTLESS FEH;Lo;0;AL; 06A1;;;;N;;;;; +1EE1F;ARABIC MATHEMATICAL DOTLESS QAF;Lo;0;AL; 066F;;;;N;;;;; +1EE21;ARABIC MATHEMATICAL INITIAL BEH;Lo;0;AL; 0628;;;;N;;;;; +1EE22;ARABIC MATHEMATICAL INITIAL JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EE24;ARABIC MATHEMATICAL INITIAL HEH;Lo;0;AL; 0647;;;;N;;;;; +1EE27;ARABIC MATHEMATICAL INITIAL HAH;Lo;0;AL; 062D;;;;N;;;;; +1EE29;ARABIC MATHEMATICAL INITIAL YEH;Lo;0;AL; 064A;;;;N;;;;; +1EE2A;ARABIC MATHEMATICAL INITIAL KAF;Lo;0;AL; 0643;;;;N;;;;; +1EE2B;ARABIC MATHEMATICAL INITIAL LAM;Lo;0;AL; 0644;;;;N;;;;; +1EE2C;ARABIC MATHEMATICAL INITIAL MEEM;Lo;0;AL; 0645;;;;N;;;;; +1EE2D;ARABIC MATHEMATICAL INITIAL NOON;Lo;0;AL; 0646;;;;N;;;;; +1EE2E;ARABIC MATHEMATICAL INITIAL SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EE2F;ARABIC MATHEMATICAL INITIAL AIN;Lo;0;AL; 0639;;;;N;;;;; +1EE30;ARABIC MATHEMATICAL INITIAL FEH;Lo;0;AL; 0641;;;;N;;;;; +1EE31;ARABIC MATHEMATICAL INITIAL SAD;Lo;0;AL; 0635;;;;N;;;;; +1EE32;ARABIC MATHEMATICAL INITIAL QAF;Lo;0;AL; 0642;;;;N;;;;; +1EE34;ARABIC MATHEMATICAL INITIAL SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EE35;ARABIC MATHEMATICAL INITIAL TEH;Lo;0;AL; 062A;;;;N;;;;; +1EE36;ARABIC MATHEMATICAL INITIAL THEH;Lo;0;AL; 062B;;;;N;;;;; +1EE37;ARABIC MATHEMATICAL INITIAL KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EE39;ARABIC MATHEMATICAL INITIAL DAD;Lo;0;AL; 0636;;;;N;;;;; +1EE3B;ARABIC MATHEMATICAL INITIAL GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EE42;ARABIC MATHEMATICAL TAILED JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EE47;ARABIC MATHEMATICAL TAILED HAH;Lo;0;AL; 062D;;;;N;;;;; +1EE49;ARABIC MATHEMATICAL TAILED YEH;Lo;0;AL; 064A;;;;N;;;;; +1EE4B;ARABIC MATHEMATICAL TAILED LAM;Lo;0;AL; 0644;;;;N;;;;; +1EE4D;ARABIC MATHEMATICAL TAILED NOON;Lo;0;AL; 0646;;;;N;;;;; +1EE4E;ARABIC MATHEMATICAL TAILED SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EE4F;ARABIC MATHEMATICAL TAILED AIN;Lo;0;AL; 0639;;;;N;;;;; +1EE51;ARABIC MATHEMATICAL TAILED SAD;Lo;0;AL; 0635;;;;N;;;;; +1EE52;ARABIC MATHEMATICAL TAILED QAF;Lo;0;AL; 0642;;;;N;;;;; +1EE54;ARABIC MATHEMATICAL TAILED SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EE57;ARABIC MATHEMATICAL TAILED KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EE59;ARABIC MATHEMATICAL TAILED DAD;Lo;0;AL; 0636;;;;N;;;;; +1EE5B;ARABIC MATHEMATICAL TAILED GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EE5D;ARABIC MATHEMATICAL TAILED DOTLESS NOON;Lo;0;AL; 06BA;;;;N;;;;; +1EE5F;ARABIC MATHEMATICAL TAILED DOTLESS QAF;Lo;0;AL; 066F;;;;N;;;;; +1EE61;ARABIC MATHEMATICAL STRETCHED BEH;Lo;0;AL; 0628;;;;N;;;;; +1EE62;ARABIC MATHEMATICAL STRETCHED JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EE64;ARABIC MATHEMATICAL STRETCHED HEH;Lo;0;AL; 0647;;;;N;;;;; +1EE67;ARABIC MATHEMATICAL STRETCHED HAH;Lo;0;AL; 062D;;;;N;;;;; +1EE68;ARABIC MATHEMATICAL STRETCHED TAH;Lo;0;AL; 0637;;;;N;;;;; +1EE69;ARABIC MATHEMATICAL STRETCHED YEH;Lo;0;AL; 064A;;;;N;;;;; +1EE6A;ARABIC MATHEMATICAL STRETCHED KAF;Lo;0;AL; 0643;;;;N;;;;; +1EE6C;ARABIC MATHEMATICAL STRETCHED MEEM;Lo;0;AL; 0645;;;;N;;;;; +1EE6D;ARABIC MATHEMATICAL STRETCHED NOON;Lo;0;AL; 0646;;;;N;;;;; +1EE6E;ARABIC MATHEMATICAL STRETCHED SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EE6F;ARABIC MATHEMATICAL STRETCHED AIN;Lo;0;AL; 0639;;;;N;;;;; +1EE70;ARABIC MATHEMATICAL STRETCHED FEH;Lo;0;AL; 0641;;;;N;;;;; +1EE71;ARABIC MATHEMATICAL STRETCHED SAD;Lo;0;AL; 0635;;;;N;;;;; +1EE72;ARABIC MATHEMATICAL STRETCHED QAF;Lo;0;AL; 0642;;;;N;;;;; +1EE74;ARABIC MATHEMATICAL STRETCHED SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EE75;ARABIC MATHEMATICAL STRETCHED TEH;Lo;0;AL; 062A;;;;N;;;;; +1EE76;ARABIC MATHEMATICAL STRETCHED THEH;Lo;0;AL; 062B;;;;N;;;;; +1EE77;ARABIC MATHEMATICAL STRETCHED KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EE79;ARABIC MATHEMATICAL STRETCHED DAD;Lo;0;AL; 0636;;;;N;;;;; +1EE7A;ARABIC MATHEMATICAL STRETCHED ZAH;Lo;0;AL; 0638;;;;N;;;;; +1EE7B;ARABIC MATHEMATICAL STRETCHED GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EE7C;ARABIC MATHEMATICAL STRETCHED DOTLESS BEH;Lo;0;AL; 066E;;;;N;;;;; +1EE7E;ARABIC MATHEMATICAL STRETCHED DOTLESS FEH;Lo;0;AL; 06A1;;;;N;;;;; +1EE80;ARABIC MATHEMATICAL LOOPED ALEF;Lo;0;AL; 0627;;;;N;;;;; +1EE81;ARABIC MATHEMATICAL LOOPED BEH;Lo;0;AL; 0628;;;;N;;;;; +1EE82;ARABIC MATHEMATICAL LOOPED JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EE83;ARABIC MATHEMATICAL LOOPED DAL;Lo;0;AL; 062F;;;;N;;;;; +1EE84;ARABIC MATHEMATICAL LOOPED HEH;Lo;0;AL; 0647;;;;N;;;;; +1EE85;ARABIC MATHEMATICAL LOOPED WAW;Lo;0;AL; 0648;;;;N;;;;; +1EE86;ARABIC MATHEMATICAL LOOPED ZAIN;Lo;0;AL; 0632;;;;N;;;;; +1EE87;ARABIC MATHEMATICAL LOOPED HAH;Lo;0;AL; 062D;;;;N;;;;; +1EE88;ARABIC MATHEMATICAL LOOPED TAH;Lo;0;AL; 0637;;;;N;;;;; +1EE89;ARABIC MATHEMATICAL LOOPED YEH;Lo;0;AL; 064A;;;;N;;;;; +1EE8B;ARABIC MATHEMATICAL LOOPED LAM;Lo;0;AL; 0644;;;;N;;;;; +1EE8C;ARABIC MATHEMATICAL LOOPED MEEM;Lo;0;AL; 0645;;;;N;;;;; +1EE8D;ARABIC MATHEMATICAL LOOPED NOON;Lo;0;AL; 0646;;;;N;;;;; +1EE8E;ARABIC MATHEMATICAL LOOPED SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EE8F;ARABIC MATHEMATICAL LOOPED AIN;Lo;0;AL; 0639;;;;N;;;;; +1EE90;ARABIC MATHEMATICAL LOOPED FEH;Lo;0;AL; 0641;;;;N;;;;; +1EE91;ARABIC MATHEMATICAL LOOPED SAD;Lo;0;AL; 0635;;;;N;;;;; +1EE92;ARABIC MATHEMATICAL LOOPED QAF;Lo;0;AL; 0642;;;;N;;;;; +1EE93;ARABIC MATHEMATICAL LOOPED REH;Lo;0;AL; 0631;;;;N;;;;; +1EE94;ARABIC MATHEMATICAL LOOPED SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EE95;ARABIC MATHEMATICAL LOOPED TEH;Lo;0;AL; 062A;;;;N;;;;; +1EE96;ARABIC MATHEMATICAL LOOPED THEH;Lo;0;AL; 062B;;;;N;;;;; +1EE97;ARABIC MATHEMATICAL LOOPED KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EE98;ARABIC MATHEMATICAL LOOPED THAL;Lo;0;AL; 0630;;;;N;;;;; +1EE99;ARABIC MATHEMATICAL LOOPED DAD;Lo;0;AL; 0636;;;;N;;;;; +1EE9A;ARABIC MATHEMATICAL LOOPED ZAH;Lo;0;AL; 0638;;;;N;;;;; +1EE9B;ARABIC MATHEMATICAL LOOPED GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EEA1;ARABIC MATHEMATICAL DOUBLE-STRUCK BEH;Lo;0;AL; 0628;;;;N;;;;; +1EEA2;ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM;Lo;0;AL; 062C;;;;N;;;;; +1EEA3;ARABIC MATHEMATICAL DOUBLE-STRUCK DAL;Lo;0;AL; 062F;;;;N;;;;; +1EEA5;ARABIC MATHEMATICAL DOUBLE-STRUCK WAW;Lo;0;AL; 0648;;;;N;;;;; +1EEA6;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN;Lo;0;AL; 0632;;;;N;;;;; +1EEA7;ARABIC MATHEMATICAL DOUBLE-STRUCK HAH;Lo;0;AL; 062D;;;;N;;;;; +1EEA8;ARABIC MATHEMATICAL DOUBLE-STRUCK TAH;Lo;0;AL; 0637;;;;N;;;;; +1EEA9;ARABIC MATHEMATICAL DOUBLE-STRUCK YEH;Lo;0;AL; 064A;;;;N;;;;; +1EEAB;ARABIC MATHEMATICAL DOUBLE-STRUCK LAM;Lo;0;AL; 0644;;;;N;;;;; +1EEAC;ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM;Lo;0;AL; 0645;;;;N;;;;; +1EEAD;ARABIC MATHEMATICAL DOUBLE-STRUCK NOON;Lo;0;AL; 0646;;;;N;;;;; +1EEAE;ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN;Lo;0;AL; 0633;;;;N;;;;; +1EEAF;ARABIC MATHEMATICAL DOUBLE-STRUCK AIN;Lo;0;AL; 0639;;;;N;;;;; +1EEB0;ARABIC MATHEMATICAL DOUBLE-STRUCK FEH;Lo;0;AL; 0641;;;;N;;;;; +1EEB1;ARABIC MATHEMATICAL DOUBLE-STRUCK SAD;Lo;0;AL; 0635;;;;N;;;;; +1EEB2;ARABIC MATHEMATICAL DOUBLE-STRUCK QAF;Lo;0;AL; 0642;;;;N;;;;; +1EEB3;ARABIC MATHEMATICAL DOUBLE-STRUCK REH;Lo;0;AL; 0631;;;;N;;;;; +1EEB4;ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN;Lo;0;AL; 0634;;;;N;;;;; +1EEB5;ARABIC MATHEMATICAL DOUBLE-STRUCK TEH;Lo;0;AL; 062A;;;;N;;;;; +1EEB6;ARABIC MATHEMATICAL DOUBLE-STRUCK THEH;Lo;0;AL; 062B;;;;N;;;;; +1EEB7;ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH;Lo;0;AL; 062E;;;;N;;;;; +1EEB8;ARABIC MATHEMATICAL DOUBLE-STRUCK THAL;Lo;0;AL; 0630;;;;N;;;;; +1EEB9;ARABIC MATHEMATICAL DOUBLE-STRUCK DAD;Lo;0;AL; 0636;;;;N;;;;; +1EEBA;ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH;Lo;0;AL; 0638;;;;N;;;;; +1EEBB;ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN;Lo;0;AL; 063A;;;;N;;;;; +1EEF0;ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL;Sm;0;ON;;;;;N;;;;; +1EEF1;ARABIC MATHEMATICAL OPERATOR HAH WITH DAL;Sm;0;ON;;;;;N;;;;; +1F000;MAHJONG TILE EAST WIND;So;0;ON;;;;;N;;;;; +1F001;MAHJONG TILE SOUTH WIND;So;0;ON;;;;;N;;;;; +1F002;MAHJONG TILE WEST WIND;So;0;ON;;;;;N;;;;; +1F003;MAHJONG TILE NORTH WIND;So;0;ON;;;;;N;;;;; +1F004;MAHJONG TILE RED DRAGON;So;0;ON;;;;;N;;;;; +1F005;MAHJONG TILE GREEN DRAGON;So;0;ON;;;;;N;;;;; +1F006;MAHJONG TILE WHITE DRAGON;So;0;ON;;;;;N;;;;; +1F007;MAHJONG TILE ONE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F008;MAHJONG TILE TWO OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F009;MAHJONG TILE THREE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00A;MAHJONG TILE FOUR OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00B;MAHJONG TILE FIVE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00C;MAHJONG TILE SIX OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00D;MAHJONG TILE SEVEN OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00E;MAHJONG TILE EIGHT OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F00F;MAHJONG TILE NINE OF CHARACTERS;So;0;ON;;;;;N;;;;; +1F010;MAHJONG TILE ONE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F011;MAHJONG TILE TWO OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F012;MAHJONG TILE THREE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F013;MAHJONG TILE FOUR OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F014;MAHJONG TILE FIVE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F015;MAHJONG TILE SIX OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F016;MAHJONG TILE SEVEN OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F017;MAHJONG TILE EIGHT OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F018;MAHJONG TILE NINE OF BAMBOOS;So;0;ON;;;;;N;;;;; +1F019;MAHJONG TILE ONE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01A;MAHJONG TILE TWO OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01B;MAHJONG TILE THREE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01C;MAHJONG TILE FOUR OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01D;MAHJONG TILE FIVE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01E;MAHJONG TILE SIX OF CIRCLES;So;0;ON;;;;;N;;;;; +1F01F;MAHJONG TILE SEVEN OF CIRCLES;So;0;ON;;;;;N;;;;; +1F020;MAHJONG TILE EIGHT OF CIRCLES;So;0;ON;;;;;N;;;;; +1F021;MAHJONG TILE NINE OF CIRCLES;So;0;ON;;;;;N;;;;; +1F022;MAHJONG TILE PLUM;So;0;ON;;;;;N;;;;; +1F023;MAHJONG TILE ORCHID;So;0;ON;;;;;N;;;;; +1F024;MAHJONG TILE BAMBOO;So;0;ON;;;;;N;;;;; +1F025;MAHJONG TILE CHRYSANTHEMUM;So;0;ON;;;;;N;;;;; +1F026;MAHJONG TILE SPRING;So;0;ON;;;;;N;;;;; +1F027;MAHJONG TILE SUMMER;So;0;ON;;;;;N;;;;; +1F028;MAHJONG TILE AUTUMN;So;0;ON;;;;;N;;;;; +1F029;MAHJONG TILE WINTER;So;0;ON;;;;;N;;;;; +1F02A;MAHJONG TILE JOKER;So;0;ON;;;;;N;;;;; +1F02B;MAHJONG TILE BACK;So;0;ON;;;;;N;;;;; +1F030;DOMINO TILE HORIZONTAL BACK;So;0;ON;;;;;N;;;;; +1F031;DOMINO TILE HORIZONTAL-00-00;So;0;ON;;;;;N;;;;; +1F032;DOMINO TILE HORIZONTAL-00-01;So;0;ON;;;;;N;;;;; +1F033;DOMINO TILE HORIZONTAL-00-02;So;0;ON;;;;;N;;;;; +1F034;DOMINO TILE HORIZONTAL-00-03;So;0;ON;;;;;N;;;;; +1F035;DOMINO TILE HORIZONTAL-00-04;So;0;ON;;;;;N;;;;; +1F036;DOMINO TILE HORIZONTAL-00-05;So;0;ON;;;;;N;;;;; +1F037;DOMINO TILE HORIZONTAL-00-06;So;0;ON;;;;;N;;;;; +1F038;DOMINO TILE HORIZONTAL-01-00;So;0;ON;;;;;N;;;;; +1F039;DOMINO TILE HORIZONTAL-01-01;So;0;ON;;;;;N;;;;; +1F03A;DOMINO TILE HORIZONTAL-01-02;So;0;ON;;;;;N;;;;; +1F03B;DOMINO TILE HORIZONTAL-01-03;So;0;ON;;;;;N;;;;; +1F03C;DOMINO TILE HORIZONTAL-01-04;So;0;ON;;;;;N;;;;; +1F03D;DOMINO TILE HORIZONTAL-01-05;So;0;ON;;;;;N;;;;; +1F03E;DOMINO TILE HORIZONTAL-01-06;So;0;ON;;;;;N;;;;; +1F03F;DOMINO TILE HORIZONTAL-02-00;So;0;ON;;;;;N;;;;; +1F040;DOMINO TILE HORIZONTAL-02-01;So;0;ON;;;;;N;;;;; +1F041;DOMINO TILE HORIZONTAL-02-02;So;0;ON;;;;;N;;;;; +1F042;DOMINO TILE HORIZONTAL-02-03;So;0;ON;;;;;N;;;;; +1F043;DOMINO TILE HORIZONTAL-02-04;So;0;ON;;;;;N;;;;; +1F044;DOMINO TILE HORIZONTAL-02-05;So;0;ON;;;;;N;;;;; +1F045;DOMINO TILE HORIZONTAL-02-06;So;0;ON;;;;;N;;;;; +1F046;DOMINO TILE HORIZONTAL-03-00;So;0;ON;;;;;N;;;;; +1F047;DOMINO TILE HORIZONTAL-03-01;So;0;ON;;;;;N;;;;; +1F048;DOMINO TILE HORIZONTAL-03-02;So;0;ON;;;;;N;;;;; +1F049;DOMINO TILE HORIZONTAL-03-03;So;0;ON;;;;;N;;;;; +1F04A;DOMINO TILE HORIZONTAL-03-04;So;0;ON;;;;;N;;;;; +1F04B;DOMINO TILE HORIZONTAL-03-05;So;0;ON;;;;;N;;;;; +1F04C;DOMINO TILE HORIZONTAL-03-06;So;0;ON;;;;;N;;;;; +1F04D;DOMINO TILE HORIZONTAL-04-00;So;0;ON;;;;;N;;;;; +1F04E;DOMINO TILE HORIZONTAL-04-01;So;0;ON;;;;;N;;;;; +1F04F;DOMINO TILE HORIZONTAL-04-02;So;0;ON;;;;;N;;;;; +1F050;DOMINO TILE HORIZONTAL-04-03;So;0;ON;;;;;N;;;;; +1F051;DOMINO TILE HORIZONTAL-04-04;So;0;ON;;;;;N;;;;; +1F052;DOMINO TILE HORIZONTAL-04-05;So;0;ON;;;;;N;;;;; +1F053;DOMINO TILE HORIZONTAL-04-06;So;0;ON;;;;;N;;;;; +1F054;DOMINO TILE HORIZONTAL-05-00;So;0;ON;;;;;N;;;;; +1F055;DOMINO TILE HORIZONTAL-05-01;So;0;ON;;;;;N;;;;; +1F056;DOMINO TILE HORIZONTAL-05-02;So;0;ON;;;;;N;;;;; +1F057;DOMINO TILE HORIZONTAL-05-03;So;0;ON;;;;;N;;;;; +1F058;DOMINO TILE HORIZONTAL-05-04;So;0;ON;;;;;N;;;;; +1F059;DOMINO TILE HORIZONTAL-05-05;So;0;ON;;;;;N;;;;; +1F05A;DOMINO TILE HORIZONTAL-05-06;So;0;ON;;;;;N;;;;; +1F05B;DOMINO TILE HORIZONTAL-06-00;So;0;ON;;;;;N;;;;; +1F05C;DOMINO TILE HORIZONTAL-06-01;So;0;ON;;;;;N;;;;; +1F05D;DOMINO TILE HORIZONTAL-06-02;So;0;ON;;;;;N;;;;; +1F05E;DOMINO TILE HORIZONTAL-06-03;So;0;ON;;;;;N;;;;; +1F05F;DOMINO TILE HORIZONTAL-06-04;So;0;ON;;;;;N;;;;; +1F060;DOMINO TILE HORIZONTAL-06-05;So;0;ON;;;;;N;;;;; +1F061;DOMINO TILE HORIZONTAL-06-06;So;0;ON;;;;;N;;;;; +1F062;DOMINO TILE VERTICAL BACK;So;0;ON;;;;;N;;;;; +1F063;DOMINO TILE VERTICAL-00-00;So;0;ON;;;;;N;;;;; +1F064;DOMINO TILE VERTICAL-00-01;So;0;ON;;;;;N;;;;; +1F065;DOMINO TILE VERTICAL-00-02;So;0;ON;;;;;N;;;;; +1F066;DOMINO TILE VERTICAL-00-03;So;0;ON;;;;;N;;;;; +1F067;DOMINO TILE VERTICAL-00-04;So;0;ON;;;;;N;;;;; +1F068;DOMINO TILE VERTICAL-00-05;So;0;ON;;;;;N;;;;; +1F069;DOMINO TILE VERTICAL-00-06;So;0;ON;;;;;N;;;;; +1F06A;DOMINO TILE VERTICAL-01-00;So;0;ON;;;;;N;;;;; +1F06B;DOMINO TILE VERTICAL-01-01;So;0;ON;;;;;N;;;;; +1F06C;DOMINO TILE VERTICAL-01-02;So;0;ON;;;;;N;;;;; +1F06D;DOMINO TILE VERTICAL-01-03;So;0;ON;;;;;N;;;;; +1F06E;DOMINO TILE VERTICAL-01-04;So;0;ON;;;;;N;;;;; +1F06F;DOMINO TILE VERTICAL-01-05;So;0;ON;;;;;N;;;;; +1F070;DOMINO TILE VERTICAL-01-06;So;0;ON;;;;;N;;;;; +1F071;DOMINO TILE VERTICAL-02-00;So;0;ON;;;;;N;;;;; +1F072;DOMINO TILE VERTICAL-02-01;So;0;ON;;;;;N;;;;; +1F073;DOMINO TILE VERTICAL-02-02;So;0;ON;;;;;N;;;;; +1F074;DOMINO TILE VERTICAL-02-03;So;0;ON;;;;;N;;;;; +1F075;DOMINO TILE VERTICAL-02-04;So;0;ON;;;;;N;;;;; +1F076;DOMINO TILE VERTICAL-02-05;So;0;ON;;;;;N;;;;; +1F077;DOMINO TILE VERTICAL-02-06;So;0;ON;;;;;N;;;;; +1F078;DOMINO TILE VERTICAL-03-00;So;0;ON;;;;;N;;;;; +1F079;DOMINO TILE VERTICAL-03-01;So;0;ON;;;;;N;;;;; +1F07A;DOMINO TILE VERTICAL-03-02;So;0;ON;;;;;N;;;;; +1F07B;DOMINO TILE VERTICAL-03-03;So;0;ON;;;;;N;;;;; +1F07C;DOMINO TILE VERTICAL-03-04;So;0;ON;;;;;N;;;;; +1F07D;DOMINO TILE VERTICAL-03-05;So;0;ON;;;;;N;;;;; +1F07E;DOMINO TILE VERTICAL-03-06;So;0;ON;;;;;N;;;;; +1F07F;DOMINO TILE VERTICAL-04-00;So;0;ON;;;;;N;;;;; +1F080;DOMINO TILE VERTICAL-04-01;So;0;ON;;;;;N;;;;; +1F081;DOMINO TILE VERTICAL-04-02;So;0;ON;;;;;N;;;;; +1F082;DOMINO TILE VERTICAL-04-03;So;0;ON;;;;;N;;;;; +1F083;DOMINO TILE VERTICAL-04-04;So;0;ON;;;;;N;;;;; +1F084;DOMINO TILE VERTICAL-04-05;So;0;ON;;;;;N;;;;; +1F085;DOMINO TILE VERTICAL-04-06;So;0;ON;;;;;N;;;;; +1F086;DOMINO TILE VERTICAL-05-00;So;0;ON;;;;;N;;;;; +1F087;DOMINO TILE VERTICAL-05-01;So;0;ON;;;;;N;;;;; +1F088;DOMINO TILE VERTICAL-05-02;So;0;ON;;;;;N;;;;; +1F089;DOMINO TILE VERTICAL-05-03;So;0;ON;;;;;N;;;;; +1F08A;DOMINO TILE VERTICAL-05-04;So;0;ON;;;;;N;;;;; +1F08B;DOMINO TILE VERTICAL-05-05;So;0;ON;;;;;N;;;;; +1F08C;DOMINO TILE VERTICAL-05-06;So;0;ON;;;;;N;;;;; +1F08D;DOMINO TILE VERTICAL-06-00;So;0;ON;;;;;N;;;;; +1F08E;DOMINO TILE VERTICAL-06-01;So;0;ON;;;;;N;;;;; +1F08F;DOMINO TILE VERTICAL-06-02;So;0;ON;;;;;N;;;;; +1F090;DOMINO TILE VERTICAL-06-03;So;0;ON;;;;;N;;;;; +1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; +1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; +1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; +1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;; +1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;; +1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;; +1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;; +1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;; +1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;; +1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;; +1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BF;PLAYING CARD RED JOKER;So;0;ON;;;;;N;;;;; +1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;; +1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;; +1F0E0;PLAYING CARD FOOL;So;0;ON;;;;;N;;;;; +1F0E1;PLAYING CARD TRUMP-1;So;0;ON;;;;;N;;;;; +1F0E2;PLAYING CARD TRUMP-2;So;0;ON;;;;;N;;;;; +1F0E3;PLAYING CARD TRUMP-3;So;0;ON;;;;;N;;;;; +1F0E4;PLAYING CARD TRUMP-4;So;0;ON;;;;;N;;;;; +1F0E5;PLAYING CARD TRUMP-5;So;0;ON;;;;;N;;;;; +1F0E6;PLAYING CARD TRUMP-6;So;0;ON;;;;;N;;;;; +1F0E7;PLAYING CARD TRUMP-7;So;0;ON;;;;;N;;;;; +1F0E8;PLAYING CARD TRUMP-8;So;0;ON;;;;;N;;;;; +1F0E9;PLAYING CARD TRUMP-9;So;0;ON;;;;;N;;;;; +1F0EA;PLAYING CARD TRUMP-10;So;0;ON;;;;;N;;;;; +1F0EB;PLAYING CARD TRUMP-11;So;0;ON;;;;;N;;;;; +1F0EC;PLAYING CARD TRUMP-12;So;0;ON;;;;;N;;;;; +1F0ED;PLAYING CARD TRUMP-13;So;0;ON;;;;;N;;;;; +1F0EE;PLAYING CARD TRUMP-14;So;0;ON;;;;;N;;;;; +1F0EF;PLAYING CARD TRUMP-15;So;0;ON;;;;;N;;;;; +1F0F0;PLAYING CARD TRUMP-16;So;0;ON;;;;;N;;;;; +1F0F1;PLAYING CARD TRUMP-17;So;0;ON;;;;;N;;;;; +1F0F2;PLAYING CARD TRUMP-18;So;0;ON;;;;;N;;;;; +1F0F3;PLAYING CARD TRUMP-19;So;0;ON;;;;;N;;;;; +1F0F4;PLAYING CARD TRUMP-20;So;0;ON;;;;;N;;;;; +1F0F5;PLAYING CARD TRUMP-21;So;0;ON;;;;;N;;;;; +1F100;DIGIT ZERO FULL STOP;No;0;EN; 0030 002E;;0;0;N;;;;; +1F101;DIGIT ZERO COMMA;No;0;EN; 0030 002C;;0;0;N;;;;; +1F102;DIGIT ONE COMMA;No;0;EN; 0031 002C;;1;1;N;;;;; +1F103;DIGIT TWO COMMA;No;0;EN; 0032 002C;;2;2;N;;;;; +1F104;DIGIT THREE COMMA;No;0;EN; 0033 002C;;3;3;N;;;;; +1F105;DIGIT FOUR COMMA;No;0;EN; 0034 002C;;4;4;N;;;;; +1F106;DIGIT FIVE COMMA;No;0;EN; 0035 002C;;5;5;N;;;;; +1F107;DIGIT SIX COMMA;No;0;EN; 0036 002C;;6;6;N;;;;; +1F108;DIGIT SEVEN COMMA;No;0;EN; 0037 002C;;7;7;N;;;;; +1F109;DIGIT EIGHT COMMA;No;0;EN; 0038 002C;;8;8;N;;;;; +1F10A;DIGIT NINE COMMA;No;0;EN; 0039 002C;;9;9;N;;;;; +1F10B;DINGBAT CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; +1F10C;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO;No;0;ON;;;;0;N;;;;; +1F10D;CIRCLED ZERO WITH SLASH;So;0;ON;;;;;N;;;;; +1F10E;CIRCLED ANTICLOCKWISE ARROW;So;0;ON;;;;;N;;;;; +1F10F;CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH;So;0;ON;;;;;N;;;;; +1F110;PARENTHESIZED LATIN CAPITAL LETTER A;So;0;L; 0028 0041 0029;;;;N;;;;; +1F111;PARENTHESIZED LATIN CAPITAL LETTER B;So;0;L; 0028 0042 0029;;;;N;;;;; +1F112;PARENTHESIZED LATIN CAPITAL LETTER C;So;0;L; 0028 0043 0029;;;;N;;;;; +1F113;PARENTHESIZED LATIN CAPITAL LETTER D;So;0;L; 0028 0044 0029;;;;N;;;;; +1F114;PARENTHESIZED LATIN CAPITAL LETTER E;So;0;L; 0028 0045 0029;;;;N;;;;; +1F115;PARENTHESIZED LATIN CAPITAL LETTER F;So;0;L; 0028 0046 0029;;;;N;;;;; +1F116;PARENTHESIZED LATIN CAPITAL LETTER G;So;0;L; 0028 0047 0029;;;;N;;;;; +1F117;PARENTHESIZED LATIN CAPITAL LETTER H;So;0;L; 0028 0048 0029;;;;N;;;;; +1F118;PARENTHESIZED LATIN CAPITAL LETTER I;So;0;L; 0028 0049 0029;;;;N;;;;; +1F119;PARENTHESIZED LATIN CAPITAL LETTER J;So;0;L; 0028 004A 0029;;;;N;;;;; +1F11A;PARENTHESIZED LATIN CAPITAL LETTER K;So;0;L; 0028 004B 0029;;;;N;;;;; +1F11B;PARENTHESIZED LATIN CAPITAL LETTER L;So;0;L; 0028 004C 0029;;;;N;;;;; +1F11C;PARENTHESIZED LATIN CAPITAL LETTER M;So;0;L; 0028 004D 0029;;;;N;;;;; +1F11D;PARENTHESIZED LATIN CAPITAL LETTER N;So;0;L; 0028 004E 0029;;;;N;;;;; +1F11E;PARENTHESIZED LATIN CAPITAL LETTER O;So;0;L; 0028 004F 0029;;;;N;;;;; +1F11F;PARENTHESIZED LATIN CAPITAL LETTER P;So;0;L; 0028 0050 0029;;;;N;;;;; +1F120;PARENTHESIZED LATIN CAPITAL LETTER Q;So;0;L; 0028 0051 0029;;;;N;;;;; +1F121;PARENTHESIZED LATIN CAPITAL LETTER R;So;0;L; 0028 0052 0029;;;;N;;;;; +1F122;PARENTHESIZED LATIN CAPITAL LETTER S;So;0;L; 0028 0053 0029;;;;N;;;;; +1F123;PARENTHESIZED LATIN CAPITAL LETTER T;So;0;L; 0028 0054 0029;;;;N;;;;; +1F124;PARENTHESIZED LATIN CAPITAL LETTER U;So;0;L; 0028 0055 0029;;;;N;;;;; +1F125;PARENTHESIZED LATIN CAPITAL LETTER V;So;0;L; 0028 0056 0029;;;;N;;;;; +1F126;PARENTHESIZED LATIN CAPITAL LETTER W;So;0;L; 0028 0057 0029;;;;N;;;;; +1F127;PARENTHESIZED LATIN CAPITAL LETTER X;So;0;L; 0028 0058 0029;;;;N;;;;; +1F128;PARENTHESIZED LATIN CAPITAL LETTER Y;So;0;L; 0028 0059 0029;;;;N;;;;; +1F129;PARENTHESIZED LATIN CAPITAL LETTER Z;So;0;L; 0028 005A 0029;;;;N;;;;; +1F12A;TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S;So;0;L; 3014 0053 3015;;;;N;;;;; +1F12B;CIRCLED ITALIC LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; +1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; +1F12D;CIRCLED CD;So;0;L; 0043 0044;;;;N;;;;; +1F12E;CIRCLED WZ;So;0;L; 0057 005A;;;;N;;;;; +1F12F;COPYLEFT SYMBOL;So;0;ON;;;;;N;;;;; +1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;; +1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;; +1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; +1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;; +1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;; +1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;; +1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;; +1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;; +1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;; +1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;; +1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;; +1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;; +1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;; +1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;; +1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;; +1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;; +1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;; +1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; +1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;; +1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;; +1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;; +1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;; +1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;; +1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;; +1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;; +1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;; +1F14A;SQUARED HV;So;0;L; 0048 0056;;;;N;;;;; +1F14B;SQUARED MV;So;0;L; 004D 0056;;;;N;;;;; +1F14C;SQUARED SD;So;0;L; 0053 0044;;;;N;;;;; +1F14D;SQUARED SS;So;0;L; 0053 0053;;;;N;;;;; +1F14E;SQUARED PPV;So;0;L; 0050 0050 0056;;;;N;;;;; +1F14F;SQUARED WC;So;0;L; 0057 0043;;;;N;;;;; +1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; +1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; +1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; +1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; +1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; +1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; +1F16A;RAISED MC SIGN;So;0;ON; 004D 0043;;;;N;;;;; +1F16B;RAISED MD SIGN;So;0;ON; 004D 0044;;;;N;;;;; +1F16C;RAISED MR SIGN;So;0;ON; 004D 0052;;;;N;;;;; +1F16D;CIRCLED CC;So;0;ON;;;;;N;;;;; +1F16E;CIRCLED C WITH OVERLAID BACKSLASH;So;0;ON;;;;;N;;;;; +1F16F;CIRCLED HUMAN FIGURE;So;0;ON;;;;;N;;;;; +1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; +1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; +1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; +1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; +1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; +1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; +1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; +1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; +1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; +1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;; +1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;; +1F190;SQUARE DJ;So;0;L; 0044 004A;;;;N;;;;; +1F191;SQUARED CL;So;0;L;;;;;N;;;;; +1F192;SQUARED COOL;So;0;L;;;;;N;;;;; +1F193;SQUARED FREE;So;0;L;;;;;N;;;;; +1F194;SQUARED ID;So;0;L;;;;;N;;;;; +1F195;SQUARED NEW;So;0;L;;;;;N;;;;; +1F196;SQUARED NG;So;0;L;;;;;N;;;;; +1F197;SQUARED OK;So;0;L;;;;;N;;;;; +1F198;SQUARED SOS;So;0;L;;;;;N;;;;; +1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; +1F19A;SQUARED VS;So;0;L;;;;;N;;;;; +1F19B;SQUARED THREE D;So;0;L;;;;;N;;;;; +1F19C;SQUARED SECOND SCREEN;So;0;L;;;;;N;;;;; +1F19D;SQUARED TWO K;So;0;L;;;;;N;;;;; +1F19E;SQUARED FOUR K;So;0;L;;;;;N;;;;; +1F19F;SQUARED EIGHT K;So;0;L;;;;;N;;;;; +1F1A0;SQUARED FIVE POINT ONE;So;0;L;;;;;N;;;;; +1F1A1;SQUARED SEVEN POINT ONE;So;0;L;;;;;N;;;;; +1F1A2;SQUARED TWENTY-TWO POINT TWO;So;0;L;;;;;N;;;;; +1F1A3;SQUARED SIXTY P;So;0;L;;;;;N;;;;; +1F1A4;SQUARED ONE HUNDRED TWENTY P;So;0;L;;;;;N;;;;; +1F1A5;SQUARED LATIN SMALL LETTER D;So;0;L;;;;;N;;;;; +1F1A6;SQUARED HC;So;0;L;;;;;N;;;;; +1F1A7;SQUARED HDR;So;0;L;;;;;N;;;;; +1F1A8;SQUARED HI-RES;So;0;L;;;;;N;;;;; +1F1A9;SQUARED LOSSLESS;So;0;L;;;;;N;;;;; +1F1AA;SQUARED SHV;So;0;L;;;;;N;;;;; +1F1AB;SQUARED UHD;So;0;L;;;;;N;;;;; +1F1AC;SQUARED VOD;So;0;L;;;;;N;;;;; +1F1AD;MASK WORK SYMBOL;So;0;ON;;;;;N;;;;; +1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; +1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; +1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; +1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;; +1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;; +1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;; +1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;; +1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;; +1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;; +1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;; +1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;; +1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;; +1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;; +1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;; +1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;; +1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;; +1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;; +1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;; +1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;; +1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;; +1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;; +1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;; +1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;; +1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;; +1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;; +1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;; +1F200;SQUARE HIRAGANA HOKA;So;0;L; 307B 304B;;;;N;;;;; +1F201;SQUARED KATAKANA KOKO;So;0;L; 30B3 30B3;;;;N;;;;; +1F202;SQUARED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; +1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L; 624B;;;;N;;;;; +1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L; 5B57;;;;N;;;;; +1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L; 53CC;;;;N;;;;; +1F213;SQUARED KATAKANA DE;So;0;L; 30C7;;;;N;;;;; +1F214;SQUARED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 4E8C;;;;N;;;;; +1F215;SQUARED CJK UNIFIED IDEOGRAPH-591A;So;0;L; 591A;;;;N;;;;; +1F216;SQUARED CJK UNIFIED IDEOGRAPH-89E3;So;0;L; 89E3;;;;N;;;;; +1F217;SQUARED CJK UNIFIED IDEOGRAPH-5929;So;0;L; 5929;;;;N;;;;; +1F218;SQUARED CJK UNIFIED IDEOGRAPH-4EA4;So;0;L; 4EA4;;;;N;;;;; +1F219;SQUARED CJK UNIFIED IDEOGRAPH-6620;So;0;L; 6620;;;;N;;;;; +1F21A;SQUARED CJK UNIFIED IDEOGRAPH-7121;So;0;L; 7121;;;;N;;;;; +1F21B;SQUARED CJK UNIFIED IDEOGRAPH-6599;So;0;L; 6599;;;;N;;;;; +1F21C;SQUARED CJK UNIFIED IDEOGRAPH-524D;So;0;L; 524D;;;;N;;;;; +1F21D;SQUARED CJK UNIFIED IDEOGRAPH-5F8C;So;0;L; 5F8C;;;;N;;;;; +1F21E;SQUARED CJK UNIFIED IDEOGRAPH-518D;So;0;L; 518D;;;;N;;;;; +1F21F;SQUARED CJK UNIFIED IDEOGRAPH-65B0;So;0;L; 65B0;;;;N;;;;; +1F220;SQUARED CJK UNIFIED IDEOGRAPH-521D;So;0;L; 521D;;;;N;;;;; +1F221;SQUARED CJK UNIFIED IDEOGRAPH-7D42;So;0;L; 7D42;;;;N;;;;; +1F222;SQUARED CJK UNIFIED IDEOGRAPH-751F;So;0;L; 751F;;;;N;;;;; +1F223;SQUARED CJK UNIFIED IDEOGRAPH-8CA9;So;0;L; 8CA9;;;;N;;;;; +1F224;SQUARED CJK UNIFIED IDEOGRAPH-58F0;So;0;L; 58F0;;;;N;;;;; +1F225;SQUARED CJK UNIFIED IDEOGRAPH-5439;So;0;L; 5439;;;;N;;;;; +1F226;SQUARED CJK UNIFIED IDEOGRAPH-6F14;So;0;L; 6F14;;;;N;;;;; +1F227;SQUARED CJK UNIFIED IDEOGRAPH-6295;So;0;L; 6295;;;;N;;;;; +1F228;SQUARED CJK UNIFIED IDEOGRAPH-6355;So;0;L; 6355;;;;N;;;;; +1F229;SQUARED CJK UNIFIED IDEOGRAPH-4E00;So;0;L; 4E00;;;;N;;;;; +1F22A;SQUARED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 4E09;;;;N;;;;; +1F22B;SQUARED CJK UNIFIED IDEOGRAPH-904A;So;0;L; 904A;;;;N;;;;; +1F22C;SQUARED CJK UNIFIED IDEOGRAPH-5DE6;So;0;L; 5DE6;;;;N;;;;; +1F22D;SQUARED CJK UNIFIED IDEOGRAPH-4E2D;So;0;L; 4E2D;;;;N;;;;; +1F22E;SQUARED CJK UNIFIED IDEOGRAPH-53F3;So;0;L; 53F3;;;;N;;;;; +1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L; 6307;;;;N;;;;; +1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L; 8D70;;;;N;;;;; +1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 6253;;;;N;;;;; +1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L; 7981;;;;N;;;;; +1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L; 7A7A;;;;N;;;;; +1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L; 5408;;;;N;;;;; +1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L; 6E80;;;;N;;;;; +1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L; 6709;;;;N;;;;; +1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L; 6708;;;;N;;;;; +1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L; 7533;;;;N;;;;; +1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L; 5272;;;;N;;;;; +1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L; 55B6;;;;N;;;;; +1F23B;SQUARED CJK UNIFIED IDEOGRAPH-914D;So;0;L; 914D;;;;N;;;;; +1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L; 3014 672C 3015;;;;N;;;;; +1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 3014 4E09 3015;;;;N;;;;; +1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 3014 4E8C 3015;;;;N;;;;; +1F243;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89;So;0;L; 3014 5B89 3015;;;;N;;;;; +1F244;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9;So;0;L; 3014 70B9 3015;;;;N;;;;; +1F245;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 3014 6253 3015;;;;N;;;;; +1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L; 3014 76D7 3015;;;;N;;;;; +1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L; 3014 52DD 3015;;;;N;;;;; +1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L; 3014 6557 3015;;;;N;;;;; +1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L; 5F97;;;;N;;;;; +1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L; 53EF;;;;N;;;;; +1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;; +1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;; +1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;; +1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;; +1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;; +1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;; +1F300;CYCLONE;So;0;ON;;;;;N;;;;; +1F301;FOGGY;So;0;ON;;;;;N;;;;; +1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; +1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;; +1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;; +1F305;SUNRISE;So;0;ON;;;;;N;;;;; +1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;; +1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;; +1F308;RAINBOW;So;0;ON;;;;;N;;;;; +1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;; +1F30A;WATER WAVE;So;0;ON;;;;;N;;;;; +1F30B;VOLCANO;So;0;ON;;;;;N;;;;; +1F30C;MILKY WAY;So;0;ON;;;;;N;;;;; +1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;; +1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;; +1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;; +1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;; +1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;; +1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;; +1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;; +1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;; +1F321;THERMOMETER;So;0;ON;;;;;N;;;;; +1F322;BLACK DROPLET;So;0;ON;;;;;N;;;;; +1F323;WHITE SUN;So;0;ON;;;;;N;;;;; +1F324;WHITE SUN WITH SMALL CLOUD;So;0;ON;;;;;N;;;;; +1F325;WHITE SUN BEHIND CLOUD;So;0;ON;;;;;N;;;;; +1F326;WHITE SUN BEHIND CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; +1F327;CLOUD WITH RAIN;So;0;ON;;;;;N;;;;; +1F328;CLOUD WITH SNOW;So;0;ON;;;;;N;;;;; +1F329;CLOUD WITH LIGHTNING;So;0;ON;;;;;N;;;;; +1F32A;CLOUD WITH TORNADO;So;0;ON;;;;;N;;;;; +1F32B;FOG;So;0;ON;;;;;N;;;;; +1F32C;WIND BLOWING FACE;So;0;ON;;;;;N;;;;; +1F32D;HOT DOG;So;0;ON;;;;;N;;;;; +1F32E;TACO;So;0;ON;;;;;N;;;;; +1F32F;BURRITO;So;0;ON;;;;;N;;;;; +1F330;CHESTNUT;So;0;ON;;;;;N;;;;; +1F331;SEEDLING;So;0;ON;;;;;N;;;;; +1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;; +1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;; +1F334;PALM TREE;So;0;ON;;;;;N;;;;; +1F335;CACTUS;So;0;ON;;;;;N;;;;; +1F336;HOT PEPPER;So;0;ON;;;;;N;;;;; +1F337;TULIP;So;0;ON;;;;;N;;;;; +1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;; +1F339;ROSE;So;0;ON;;;;;N;;;;; +1F33A;HIBISCUS;So;0;ON;;;;;N;;;;; +1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;; +1F33C;BLOSSOM;So;0;ON;;;;;N;;;;; +1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;; +1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;; +1F33F;HERB;So;0;ON;;;;;N;;;;; +1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;; +1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;; +1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;; +1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;; +1F344;MUSHROOM;So;0;ON;;;;;N;;;;; +1F345;TOMATO;So;0;ON;;;;;N;;;;; +1F346;AUBERGINE;So;0;ON;;;;;N;;;;; +1F347;GRAPES;So;0;ON;;;;;N;;;;; +1F348;MELON;So;0;ON;;;;;N;;;;; +1F349;WATERMELON;So;0;ON;;;;;N;;;;; +1F34A;TANGERINE;So;0;ON;;;;;N;;;;; +1F34B;LEMON;So;0;ON;;;;;N;;;;; +1F34C;BANANA;So;0;ON;;;;;N;;;;; +1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;; +1F34E;RED APPLE;So;0;ON;;;;;N;;;;; +1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;; +1F350;PEAR;So;0;ON;;;;;N;;;;; +1F351;PEACH;So;0;ON;;;;;N;;;;; +1F352;CHERRIES;So;0;ON;;;;;N;;;;; +1F353;STRAWBERRY;So;0;ON;;;;;N;;;;; +1F354;HAMBURGER;So;0;ON;;;;;N;;;;; +1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;; +1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;; +1F357;POULTRY LEG;So;0;ON;;;;;N;;;;; +1F358;RICE CRACKER;So;0;ON;;;;;N;;;;; +1F359;RICE BALL;So;0;ON;;;;;N;;;;; +1F35A;COOKED RICE;So;0;ON;;;;;N;;;;; +1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;; +1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;; +1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;; +1F35E;BREAD;So;0;ON;;;;;N;;;;; +1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;; +1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;; +1F361;DANGO;So;0;ON;;;;;N;;;;; +1F362;ODEN;So;0;ON;;;;;N;;;;; +1F363;SUSHI;So;0;ON;;;;;N;;;;; +1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;; +1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;; +1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;; +1F367;SHAVED ICE;So;0;ON;;;;;N;;;;; +1F368;ICE CREAM;So;0;ON;;;;;N;;;;; +1F369;DOUGHNUT;So;0;ON;;;;;N;;;;; +1F36A;COOKIE;So;0;ON;;;;;N;;;;; +1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;; +1F36C;CANDY;So;0;ON;;;;;N;;;;; +1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;; +1F36E;CUSTARD;So;0;ON;;;;;N;;;;; +1F36F;HONEY POT;So;0;ON;;;;;N;;;;; +1F370;SHORTCAKE;So;0;ON;;;;;N;;;;; +1F371;BENTO BOX;So;0;ON;;;;;N;;;;; +1F372;POT OF FOOD;So;0;ON;;;;;N;;;;; +1F373;COOKING;So;0;ON;;;;;N;;;;; +1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;; +1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;; +1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;; +1F377;WINE GLASS;So;0;ON;;;;;N;;;;; +1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;; +1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;; +1F37A;BEER MUG;So;0;ON;;;;;N;;;;; +1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;; +1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;; +1F37D;FORK AND KNIFE WITH PLATE;So;0;ON;;;;;N;;;;; +1F37E;BOTTLE WITH POPPING CORK;So;0;ON;;;;;N;;;;; +1F37F;POPCORN;So;0;ON;;;;;N;;;;; +1F380;RIBBON;So;0;ON;;;;;N;;;;; +1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;; +1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;; +1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;; +1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;; +1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F386;FIREWORKS;So;0;ON;;;;;N;;;;; +1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;; +1F388;BALLOON;So;0;ON;;;;;N;;;;; +1F389;PARTY POPPER;So;0;ON;;;;;N;;;;; +1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;; +1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;; +1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;; +1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;; +1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;; +1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;; +1F390;WIND CHIME;So;0;ON;;;;;N;;;;; +1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;; +1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;; +1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;; +1F394;HEART WITH TIP ON THE LEFT;So;0;ON;;;;;N;;;;; +1F395;BOUQUET OF FLOWERS;So;0;ON;;;;;N;;;;; +1F396;MILITARY MEDAL;So;0;ON;;;;;N;;;;; +1F397;REMINDER RIBBON;So;0;ON;;;;;N;;;;; +1F398;MUSICAL KEYBOARD WITH JACKS;So;0;ON;;;;;N;;;;; +1F399;STUDIO MICROPHONE;So;0;ON;;;;;N;;;;; +1F39A;LEVEL SLIDER;So;0;ON;;;;;N;;;;; +1F39B;CONTROL KNOBS;So;0;ON;;;;;N;;;;; +1F39C;BEAMED ASCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F39D;BEAMED DESCENDING MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F39E;FILM FRAMES;So;0;ON;;;;;N;;;;; +1F39F;ADMISSION TICKETS;So;0;ON;;;;;N;;;;; +1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;; +1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;; +1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;; +1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;; +1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;; +1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;; +1F3A6;CINEMA;So;0;ON;;;;;N;;;;; +1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;; +1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;; +1F3A9;TOP HAT;So;0;ON;;;;;N;;;;; +1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;; +1F3AB;TICKET;So;0;ON;;;;;N;;;;; +1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;; +1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;; +1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;; +1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;; +1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;; +1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;; +1F3B2;GAME DIE;So;0;ON;;;;;N;;;;; +1F3B3;BOWLING;So;0;ON;;;;;N;;;;; +1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;; +1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;; +1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;; +1F3B8;GUITAR;So;0;ON;;;;;N;;;;; +1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;; +1F3BA;TRUMPET;So;0;ON;;;;;N;;;;; +1F3BB;VIOLIN;So;0;ON;;;;;N;;;;; +1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;; +1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;; +1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;; +1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;; +1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;; +1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;; +1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;; +1F3C3;RUNNER;So;0;ON;;;;;N;;;;; +1F3C4;SURFER;So;0;ON;;;;;N;;;;; +1F3C5;SPORTS MEDAL;So;0;ON;;;;;N;;;;; +1F3C6;TROPHY;So;0;ON;;;;;N;;;;; +1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;; +1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;; +1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;; +1F3CA;SWIMMER;So;0;ON;;;;;N;;;;; +1F3CB;WEIGHT LIFTER;So;0;ON;;;;;N;;;;; +1F3CC;GOLFER;So;0;ON;;;;;N;;;;; +1F3CD;RACING MOTORCYCLE;So;0;ON;;;;;N;;;;; +1F3CE;RACING CAR;So;0;ON;;;;;N;;;;; +1F3CF;CRICKET BAT AND BALL;So;0;ON;;;;;N;;;;; +1F3D0;VOLLEYBALL;So;0;ON;;;;;N;;;;; +1F3D1;FIELD HOCKEY STICK AND BALL;So;0;ON;;;;;N;;;;; +1F3D2;ICE HOCKEY STICK AND PUCK;So;0;ON;;;;;N;;;;; +1F3D3;TABLE TENNIS PADDLE AND BALL;So;0;ON;;;;;N;;;;; +1F3D4;SNOW CAPPED MOUNTAIN;So;0;ON;;;;;N;;;;; +1F3D5;CAMPING;So;0;ON;;;;;N;;;;; +1F3D6;BEACH WITH UMBRELLA;So;0;ON;;;;;N;;;;; +1F3D7;BUILDING CONSTRUCTION;So;0;ON;;;;;N;;;;; +1F3D8;HOUSE BUILDINGS;So;0;ON;;;;;N;;;;; +1F3D9;CITYSCAPE;So;0;ON;;;;;N;;;;; +1F3DA;DERELICT HOUSE BUILDING;So;0;ON;;;;;N;;;;; +1F3DB;CLASSICAL BUILDING;So;0;ON;;;;;N;;;;; +1F3DC;DESERT;So;0;ON;;;;;N;;;;; +1F3DD;DESERT ISLAND;So;0;ON;;;;;N;;;;; +1F3DE;NATIONAL PARK;So;0;ON;;;;;N;;;;; +1F3DF;STADIUM;So;0;ON;;;;;N;;;;; +1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;; +1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;; +1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;; +1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;; +1F3E6;BANK;So;0;ON;;;;;N;;;;; +1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;; +1F3E8;HOTEL;So;0;ON;;;;;N;;;;; +1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;; +1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;; +1F3EB;SCHOOL;So;0;ON;;;;;N;;;;; +1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;; +1F3ED;FACTORY;So;0;ON;;;;;N;;;;; +1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;; +1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;; +1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;; +1F3F1;WHITE PENNANT;So;0;ON;;;;;N;;;;; +1F3F2;BLACK PENNANT;So;0;ON;;;;;N;;;;; +1F3F3;WAVING WHITE FLAG;So;0;ON;;;;;N;;;;; +1F3F4;WAVING BLACK FLAG;So;0;ON;;;;;N;;;;; +1F3F5;ROSETTE;So;0;ON;;;;;N;;;;; +1F3F6;BLACK ROSETTE;So;0;ON;;;;;N;;;;; +1F3F7;LABEL;So;0;ON;;;;;N;;;;; +1F3F8;BADMINTON RACQUET AND SHUTTLECOCK;So;0;ON;;;;;N;;;;; +1F3F9;BOW AND ARROW;So;0;ON;;;;;N;;;;; +1F3FA;AMPHORA;So;0;ON;;;;;N;;;;; +1F3FB;EMOJI MODIFIER FITZPATRICK TYPE-1-2;Sk;0;ON;;;;;N;;;;; +1F3FC;EMOJI MODIFIER FITZPATRICK TYPE-3;Sk;0;ON;;;;;N;;;;; +1F3FD;EMOJI MODIFIER FITZPATRICK TYPE-4;Sk;0;ON;;;;;N;;;;; +1F3FE;EMOJI MODIFIER FITZPATRICK TYPE-5;Sk;0;ON;;;;;N;;;;; +1F3FF;EMOJI MODIFIER FITZPATRICK TYPE-6;Sk;0;ON;;;;;N;;;;; +1F400;RAT;So;0;ON;;;;;N;;;;; +1F401;MOUSE;So;0;ON;;;;;N;;;;; +1F402;OX;So;0;ON;;;;;N;;;;; +1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;; +1F404;COW;So;0;ON;;;;;N;;;;; +1F405;TIGER;So;0;ON;;;;;N;;;;; +1F406;LEOPARD;So;0;ON;;;;;N;;;;; +1F407;RABBIT;So;0;ON;;;;;N;;;;; +1F408;CAT;So;0;ON;;;;;N;;;;; +1F409;DRAGON;So;0;ON;;;;;N;;;;; +1F40A;CROCODILE;So;0;ON;;;;;N;;;;; +1F40B;WHALE;So;0;ON;;;;;N;;;;; +1F40C;SNAIL;So;0;ON;;;;;N;;;;; +1F40D;SNAKE;So;0;ON;;;;;N;;;;; +1F40E;HORSE;So;0;ON;;;;;N;;;;; +1F40F;RAM;So;0;ON;;;;;N;;;;; +1F410;GOAT;So;0;ON;;;;;N;;;;; +1F411;SHEEP;So;0;ON;;;;;N;;;;; +1F412;MONKEY;So;0;ON;;;;;N;;;;; +1F413;ROOSTER;So;0;ON;;;;;N;;;;; +1F414;CHICKEN;So;0;ON;;;;;N;;;;; +1F415;DOG;So;0;ON;;;;;N;;;;; +1F416;PIG;So;0;ON;;;;;N;;;;; +1F417;BOAR;So;0;ON;;;;;N;;;;; +1F418;ELEPHANT;So;0;ON;;;;;N;;;;; +1F419;OCTOPUS;So;0;ON;;;;;N;;;;; +1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;; +1F41B;BUG;So;0;ON;;;;;N;;;;; +1F41C;ANT;So;0;ON;;;;;N;;;;; +1F41D;HONEYBEE;So;0;ON;;;;;N;;;;; +1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;; +1F41F;FISH;So;0;ON;;;;;N;;;;; +1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;; +1F421;BLOWFISH;So;0;ON;;;;;N;;;;; +1F422;TURTLE;So;0;ON;;;;;N;;;;; +1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;; +1F424;BABY CHICK;So;0;ON;;;;;N;;;;; +1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;; +1F426;BIRD;So;0;ON;;;;;N;;;;; +1F427;PENGUIN;So;0;ON;;;;;N;;;;; +1F428;KOALA;So;0;ON;;;;;N;;;;; +1F429;POODLE;So;0;ON;;;;;N;;;;; +1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;; +1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;; +1F42C;DOLPHIN;So;0;ON;;;;;N;;;;; +1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;; +1F42E;COW FACE;So;0;ON;;;;;N;;;;; +1F42F;TIGER FACE;So;0;ON;;;;;N;;;;; +1F430;RABBIT FACE;So;0;ON;;;;;N;;;;; +1F431;CAT FACE;So;0;ON;;;;;N;;;;; +1F432;DRAGON FACE;So;0;ON;;;;;N;;;;; +1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;; +1F434;HORSE FACE;So;0;ON;;;;;N;;;;; +1F435;MONKEY FACE;So;0;ON;;;;;N;;;;; +1F436;DOG FACE;So;0;ON;;;;;N;;;;; +1F437;PIG FACE;So;0;ON;;;;;N;;;;; +1F438;FROG FACE;So;0;ON;;;;;N;;;;; +1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;; +1F43A;WOLF FACE;So;0;ON;;;;;N;;;;; +1F43B;BEAR FACE;So;0;ON;;;;;N;;;;; +1F43C;PANDA FACE;So;0;ON;;;;;N;;;;; +1F43D;PIG NOSE;So;0;ON;;;;;N;;;;; +1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;; +1F43F;CHIPMUNK;So;0;ON;;;;;N;;;;; +1F440;EYES;So;0;ON;;;;;N;;;;; +1F441;EYE;So;0;ON;;;;;N;;;;; +1F442;EAR;So;0;ON;;;;;N;;;;; +1F443;NOSE;So;0;ON;;;;;N;;;;; +1F444;MOUTH;So;0;ON;;;;;N;;;;; +1F445;TONGUE;So;0;ON;;;;;N;;;;; +1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;; +1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;; +1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;; +1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;; +1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; +1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;; +1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;; +1F451;CROWN;So;0;ON;;;;;N;;;;; +1F452;WOMANS HAT;So;0;ON;;;;;N;;;;; +1F453;EYEGLASSES;So;0;ON;;;;;N;;;;; +1F454;NECKTIE;So;0;ON;;;;;N;;;;; +1F455;T-SHIRT;So;0;ON;;;;;N;;;;; +1F456;JEANS;So;0;ON;;;;;N;;;;; +1F457;DRESS;So;0;ON;;;;;N;;;;; +1F458;KIMONO;So;0;ON;;;;;N;;;;; +1F459;BIKINI;So;0;ON;;;;;N;;;;; +1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;; +1F45B;PURSE;So;0;ON;;;;;N;;;;; +1F45C;HANDBAG;So;0;ON;;;;;N;;;;; +1F45D;POUCH;So;0;ON;;;;;N;;;;; +1F45E;MANS SHOE;So;0;ON;;;;;N;;;;; +1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;; +1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;; +1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;; +1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;; +1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;; +1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F466;BOY;So;0;ON;;;;;N;;;;; +1F467;GIRL;So;0;ON;;;;;N;;;;; +1F468;MAN;So;0;ON;;;;;N;;;;; +1F469;WOMAN;So;0;ON;;;;;N;;;;; +1F46A;FAMILY;So;0;ON;;;;;N;;;;; +1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;; +1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;; +1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;; +1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;; +1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;; +1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;; +1F474;OLDER MAN;So;0;ON;;;;;N;;;;; +1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;; +1F476;BABY;So;0;ON;;;;;N;;;;; +1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;; +1F478;PRINCESS;So;0;ON;;;;;N;;;;; +1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;; +1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;; +1F47B;GHOST;So;0;ON;;;;;N;;;;; +1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;; +1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;; +1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;; +1F47F;IMP;So;0;ON;;;;;N;;;;; +1F480;SKULL;So;0;ON;;;;;N;;;;; +1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;; +1F482;GUARDSMAN;So;0;ON;;;;;N;;;;; +1F483;DANCER;So;0;ON;;;;;N;;;;; +1F484;LIPSTICK;So;0;ON;;;;;N;;;;; +1F485;NAIL POLISH;So;0;ON;;;;;N;;;;; +1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;; +1F487;HAIRCUT;So;0;ON;;;;;N;;;;; +1F488;BARBER POLE;So;0;ON;;;;;N;;;;; +1F489;SYRINGE;So;0;ON;;;;;N;;;;; +1F48A;PILL;So;0;ON;;;;;N;;;;; +1F48B;KISS MARK;So;0;ON;;;;;N;;;;; +1F48C;LOVE LETTER;So;0;ON;;;;;N;;;;; +1F48D;RING;So;0;ON;;;;;N;;;;; +1F48E;GEM STONE;So;0;ON;;;;;N;;;;; +1F48F;KISS;So;0;ON;;;;;N;;;;; +1F490;BOUQUET;So;0;ON;;;;;N;;;;; +1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;; +1F492;WEDDING;So;0;ON;;;;;N;;;;; +1F493;BEATING HEART;So;0;ON;;;;;N;;;;; +1F494;BROKEN HEART;So;0;ON;;;;;N;;;;; +1F495;TWO HEARTS;So;0;ON;;;;;N;;;;; +1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;; +1F497;GROWING HEART;So;0;ON;;;;;N;;;;; +1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;; +1F499;BLUE HEART;So;0;ON;;;;;N;;;;; +1F49A;GREEN HEART;So;0;ON;;;;;N;;;;; +1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;; +1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;; +1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;; +1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;; +1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;; +1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;; +1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;; +1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;; +1F4A3;BOMB;So;0;ON;;;;;N;;;;; +1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;; +1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;; +1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;; +1F4A7;DROPLET;So;0;ON;;;;;N;;;;; +1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;; +1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;; +1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;; +1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;; +1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;; +1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;; +1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;; +1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;; +1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;; +1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;; +1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;; +1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;; +1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;; +1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;; +1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;; +1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;; +1F4BA;SEAT;So;0;ON;;;;;N;;;;; +1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; +1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;; +1F4BD;MINIDISC;So;0;ON;;;;;N;;;;; +1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;; +1F4C0;DVD;So;0;ON;;;;;N;;;;; +1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;; +1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;; +1F4C5;CALENDAR;So;0;ON;;;;;N;;;;; +1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;; +1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;; +1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;; +1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;; +1F4CA;BAR CHART;So;0;ON;;;;;N;;;;; +1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;; +1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;; +1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;; +1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;; +1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;; +1F4D2;LEDGER;So;0;ON;;;;;N;;;;; +1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;; +1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;; +1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;; +1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;; +1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;; +1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;; +1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;; +1F4DA;BOOKS;So;0;ON;;;;;N;;;;; +1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;; +1F4DC;SCROLL;So;0;ON;;;;;N;;;;; +1F4DD;MEMO;So;0;ON;;;;;N;;;;; +1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F4DF;PAGER;So;0;ON;;;;;N;;;;; +1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;; +1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;; +1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;; +1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;; +1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E6;PACKAGE;So;0;ON;;;;;N;;;;; +1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;; +1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;; +1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EE;POSTBOX;So;0;ON;;;;;N;;;;; +1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;; +1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;; +1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;; +1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;; +1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;; +1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;; +1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;; +1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;; +1F4F7;CAMERA;So;0;ON;;;;;N;;;;; +1F4F8;CAMERA WITH FLASH;So;0;ON;;;;;N;;;;; +1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;; +1F4FA;TELEVISION;So;0;ON;;;;;N;;;;; +1F4FB;RADIO;So;0;ON;;;;;N;;;;; +1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;; +1F4FD;FILM PROJECTOR;So;0;ON;;;;;N;;;;; +1F4FE;PORTABLE STEREO;So;0;ON;;;;;N;;;;; +1F4FF;PRAYER BEADS;So;0;ON;;;;;N;;;;; +1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;; +1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;; +1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F508;SPEAKER;So;0;ON;;;;;N;;;;; +1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; +1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; +1F50B;BATTERY;So;0;ON;;;;;N;;;;; +1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;; +1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;; +1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;; +1F511;KEY;So;0;ON;;;;;N;;;;; +1F512;LOCK;So;0;ON;;;;;N;;;;; +1F513;OPEN LOCK;So;0;ON;;;;;N;;;;; +1F514;BELL;So;0;ON;;;;;N;;;;; +1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F516;BOOKMARK;So;0;ON;;;;;N;;;;; +1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;; +1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;; +1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;; +1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;; +1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;; +1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;; +1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;; +1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;; +1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;ON;;;;;N;;;;; +1F525;FIRE;So;0;ON;;;;;N;;;;; +1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;; +1F527;WRENCH;So;0;ON;;;;;N;;;;; +1F528;HAMMER;So;0;ON;;;;;N;;;;; +1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;; +1F52A;HOCHO;So;0;ON;;;;;N;;;;; +1F52B;PISTOL;So;0;ON;;;;;N;;;;; +1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;; +1F52D;TELESCOPE;So;0;ON;;;;;N;;;;; +1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;; +1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; +1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;; +1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;; +1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;; +1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;; +1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53E;LOWER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F53F;UPPER RIGHT SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F540;CIRCLED CROSS POMMEE;So;0;ON;;;;;N;;;;; +1F541;CROSS POMMEE WITH HALF-CIRCLE BELOW;So;0;ON;;;;;N;;;;; +1F542;CROSS POMMEE;So;0;ON;;;;;N;;;;; +1F543;NOTCHED LEFT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F544;NOTCHED RIGHT SEMICIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F545;SYMBOL FOR MARKS CHAPTER;So;0;ON;;;;;N;;;;; +1F546;WHITE LATIN CROSS;So;0;ON;;;;;N;;;;; +1F547;HEAVY LATIN CROSS;So;0;ON;;;;;N;;;;; +1F548;CELTIC CROSS;So;0;ON;;;;;N;;;;; +1F549;OM SYMBOL;So;0;ON;;;;;N;;;;; +1F54A;DOVE OF PEACE;So;0;ON;;;;;N;;;;; +1F54B;KAABA;So;0;ON;;;;;N;;;;; +1F54C;MOSQUE;So;0;ON;;;;;N;;;;; +1F54D;SYNAGOGUE;So;0;ON;;;;;N;;;;; +1F54E;MENORAH WITH NINE BRANCHES;So;0;ON;;;;;N;;;;; +1F54F;BOWL OF HYGIEIA;So;0;ON;;;;;N;;;;; +1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;; +1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;; +1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;; +1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;; +1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;; +1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;; +1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;; +1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;; +1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;; +1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;; +1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;; +1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;; +1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;; +1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;; +1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;; +1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;; +1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;; +1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;; +1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;; +1F568;RIGHT SPEAKER;So;0;ON;;;;;N;;;;; +1F569;RIGHT SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; +1F56A;RIGHT SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; +1F56B;BULLHORN;So;0;ON;;;;;N;;;;; +1F56C;BULLHORN WITH SOUND WAVES;So;0;ON;;;;;N;;;;; +1F56D;RINGING BELL;So;0;ON;;;;;N;;;;; +1F56E;BOOK;So;0;ON;;;;;N;;;;; +1F56F;CANDLE;So;0;ON;;;;;N;;;;; +1F570;MANTELPIECE CLOCK;So;0;ON;;;;;N;;;;; +1F571;BLACK SKULL AND CROSSBONES;So;0;ON;;;;;N;;;;; +1F572;NO PIRACY;So;0;ON;;;;;N;;;;; +1F573;HOLE;So;0;ON;;;;;N;;;;; +1F574;MAN IN BUSINESS SUIT LEVITATING;So;0;ON;;;;;N;;;;; +1F575;SLEUTH OR SPY;So;0;ON;;;;;N;;;;; +1F576;DARK SUNGLASSES;So;0;ON;;;;;N;;;;; +1F577;SPIDER;So;0;ON;;;;;N;;;;; +1F578;SPIDER WEB;So;0;ON;;;;;N;;;;; +1F579;JOYSTICK;So;0;ON;;;;;N;;;;; +1F57A;MAN DANCING;So;0;ON;;;;;N;;;;; +1F57B;LEFT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F57C;TELEPHONE RECEIVER WITH PAGE;So;0;ON;;;;;N;;;;; +1F57D;RIGHT HAND TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F57E;WHITE TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; +1F57F;BLACK TOUCHTONE TELEPHONE;So;0;ON;;;;;N;;;;; +1F580;TELEPHONE ON TOP OF MODEM;So;0;ON;;;;;N;;;;; +1F581;CLAMSHELL MOBILE PHONE;So;0;ON;;;;;N;;;;; +1F582;BACK OF ENVELOPE;So;0;ON;;;;;N;;;;; +1F583;STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; +1F584;ENVELOPE WITH LIGHTNING;So;0;ON;;;;;N;;;;; +1F585;FLYING ENVELOPE;So;0;ON;;;;;N;;;;; +1F586;PEN OVER STAMPED ENVELOPE;So;0;ON;;;;;N;;;;; +1F587;LINKED PAPERCLIPS;So;0;ON;;;;;N;;;;; +1F588;BLACK PUSHPIN;So;0;ON;;;;;N;;;;; +1F589;LOWER LEFT PENCIL;So;0;ON;;;;;N;;;;; +1F58A;LOWER LEFT BALLPOINT PEN;So;0;ON;;;;;N;;;;; +1F58B;LOWER LEFT FOUNTAIN PEN;So;0;ON;;;;;N;;;;; +1F58C;LOWER LEFT PAINTBRUSH;So;0;ON;;;;;N;;;;; +1F58D;LOWER LEFT CRAYON;So;0;ON;;;;;N;;;;; +1F58E;LEFT WRITING HAND;So;0;ON;;;;;N;;;;; +1F58F;TURNED OK HAND SIGN;So;0;ON;;;;;N;;;;; +1F590;RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; +1F591;REVERSED RAISED HAND WITH FINGERS SPLAYED;So;0;ON;;;;;N;;;;; +1F592;REVERSED THUMBS UP SIGN;So;0;ON;;;;;N;;;;; +1F593;REVERSED THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; +1F594;REVERSED VICTORY HAND;So;0;ON;;;;;N;;;;; +1F595;REVERSED HAND WITH MIDDLE FINGER EXTENDED;So;0;ON;;;;;N;;;;; +1F596;RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS;So;0;ON;;;;;N;;;;; +1F597;WHITE DOWN POINTING LEFT HAND INDEX;So;0;ON;;;;;N;;;;; +1F598;SIDEWAYS WHITE LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F599;SIDEWAYS WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59A;SIDEWAYS BLACK LEFT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59B;SIDEWAYS BLACK RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59C;BLACK LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F59D;BLACK RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F59E;SIDEWAYS WHITE UP POINTING INDEX;So;0;ON;;;;;N;;;;; +1F59F;SIDEWAYS WHITE DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A0;SIDEWAYS BLACK UP POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A1;SIDEWAYS BLACK DOWN POINTING INDEX;So;0;ON;;;;;N;;;;; +1F5A2;BLACK UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F5A3;BLACK DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F5A4;BLACK HEART;So;0;ON;;;;;N;;;;; +1F5A5;DESKTOP COMPUTER;So;0;ON;;;;;N;;;;; +1F5A6;KEYBOARD AND MOUSE;So;0;ON;;;;;N;;;;; +1F5A7;THREE NETWORKED COMPUTERS;So;0;ON;;;;;N;;;;; +1F5A8;PRINTER;So;0;ON;;;;;N;;;;; +1F5A9;POCKET CALCULATOR;So;0;ON;;;;;N;;;;; +1F5AA;BLACK HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AB;WHITE HARD SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AC;SOFT SHELL FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F5AD;TAPE CARTRIDGE;So;0;ON;;;;;N;;;;; +1F5AE;WIRED KEYBOARD;So;0;ON;;;;;N;;;;; +1F5AF;ONE BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B0;TWO BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B1;THREE BUTTON MOUSE;So;0;ON;;;;;N;;;;; +1F5B2;TRACKBALL;So;0;ON;;;;;N;;;;; +1F5B3;OLD PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; +1F5B4;HARD DISK;So;0;ON;;;;;N;;;;; +1F5B5;SCREEN;So;0;ON;;;;;N;;;;; +1F5B6;PRINTER ICON;So;0;ON;;;;;N;;;;; +1F5B7;FAX ICON;So;0;ON;;;;;N;;;;; +1F5B8;OPTICAL DISC ICON;So;0;ON;;;;;N;;;;; +1F5B9;DOCUMENT WITH TEXT;So;0;ON;;;;;N;;;;; +1F5BA;DOCUMENT WITH TEXT AND PICTURE;So;0;ON;;;;;N;;;;; +1F5BB;DOCUMENT WITH PICTURE;So;0;ON;;;;;N;;;;; +1F5BC;FRAME WITH PICTURE;So;0;ON;;;;;N;;;;; +1F5BD;FRAME WITH TILES;So;0;ON;;;;;N;;;;; +1F5BE;FRAME WITH AN X;So;0;ON;;;;;N;;;;; +1F5BF;BLACK FOLDER;So;0;ON;;;;;N;;;;; +1F5C0;FOLDER;So;0;ON;;;;;N;;;;; +1F5C1;OPEN FOLDER;So;0;ON;;;;;N;;;;; +1F5C2;CARD INDEX DIVIDERS;So;0;ON;;;;;N;;;;; +1F5C3;CARD FILE BOX;So;0;ON;;;;;N;;;;; +1F5C4;FILE CABINET;So;0;ON;;;;;N;;;;; +1F5C5;EMPTY NOTE;So;0;ON;;;;;N;;;;; +1F5C6;EMPTY NOTE PAGE;So;0;ON;;;;;N;;;;; +1F5C7;EMPTY NOTE PAD;So;0;ON;;;;;N;;;;; +1F5C8;NOTE;So;0;ON;;;;;N;;;;; +1F5C9;NOTE PAGE;So;0;ON;;;;;N;;;;; +1F5CA;NOTE PAD;So;0;ON;;;;;N;;;;; +1F5CB;EMPTY DOCUMENT;So;0;ON;;;;;N;;;;; +1F5CC;EMPTY PAGE;So;0;ON;;;;;N;;;;; +1F5CD;EMPTY PAGES;So;0;ON;;;;;N;;;;; +1F5CE;DOCUMENT;So;0;ON;;;;;N;;;;; +1F5CF;PAGE;So;0;ON;;;;;N;;;;; +1F5D0;PAGES;So;0;ON;;;;;N;;;;; +1F5D1;WASTEBASKET;So;0;ON;;;;;N;;;;; +1F5D2;SPIRAL NOTE PAD;So;0;ON;;;;;N;;;;; +1F5D3;SPIRAL CALENDAR PAD;So;0;ON;;;;;N;;;;; +1F5D4;DESKTOP WINDOW;So;0;ON;;;;;N;;;;; +1F5D5;MINIMIZE;So;0;ON;;;;;N;;;;; +1F5D6;MAXIMIZE;So;0;ON;;;;;N;;;;; +1F5D7;OVERLAP;So;0;ON;;;;;N;;;;; +1F5D8;CLOCKWISE RIGHT AND LEFT SEMICIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F5D9;CANCELLATION X;So;0;ON;;;;;N;;;;; +1F5DA;INCREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; +1F5DB;DECREASE FONT SIZE SYMBOL;So;0;ON;;;;;N;;;;; +1F5DC;COMPRESSION;So;0;ON;;;;;N;;;;; +1F5DD;OLD KEY;So;0;ON;;;;;N;;;;; +1F5DE;ROLLED-UP NEWSPAPER;So;0;ON;;;;;N;;;;; +1F5DF;PAGE WITH CIRCLED TEXT;So;0;ON;;;;;N;;;;; +1F5E0;STOCK CHART;So;0;ON;;;;;N;;;;; +1F5E1;DAGGER KNIFE;So;0;ON;;;;;N;;;;; +1F5E2;LIPS;So;0;ON;;;;;N;;;;; +1F5E3;SPEAKING HEAD IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F5E4;THREE RAYS ABOVE;So;0;ON;;;;;N;;;;; +1F5E5;THREE RAYS BELOW;So;0;ON;;;;;N;;;;; +1F5E6;THREE RAYS LEFT;So;0;ON;;;;;N;;;;; +1F5E7;THREE RAYS RIGHT;So;0;ON;;;;;N;;;;; +1F5E8;LEFT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; +1F5E9;RIGHT SPEECH BUBBLE;So;0;ON;;;;;N;;;;; +1F5EA;TWO SPEECH BUBBLES;So;0;ON;;;;;N;;;;; +1F5EB;THREE SPEECH BUBBLES;So;0;ON;;;;;N;;;;; +1F5EC;LEFT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; +1F5ED;RIGHT THOUGHT BUBBLE;So;0;ON;;;;;N;;;;; +1F5EE;LEFT ANGER BUBBLE;So;0;ON;;;;;N;;;;; +1F5EF;RIGHT ANGER BUBBLE;So;0;ON;;;;;N;;;;; +1F5F0;MOOD BUBBLE;So;0;ON;;;;;N;;;;; +1F5F1;LIGHTNING MOOD BUBBLE;So;0;ON;;;;;N;;;;; +1F5F2;LIGHTNING MOOD;So;0;ON;;;;;N;;;;; +1F5F3;BALLOT BOX WITH BALLOT;So;0;ON;;;;;N;;;;; +1F5F4;BALLOT SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F5;BALLOT BOX WITH SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F6;BALLOT BOLD SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F7;BALLOT BOX WITH BOLD SCRIPT X;So;0;ON;;;;;N;;;;; +1F5F8;LIGHT CHECK MARK;So;0;ON;;;;;N;;;;; +1F5F9;BALLOT BOX WITH BOLD CHECK;So;0;ON;;;;;N;;;;; +1F5FA;WORLD MAP;So;0;ON;;;;;N;;;;; +1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;; +1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;; +1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;; +1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;; +1F5FF;MOYAI;So;0;ON;;;;;N;;;;; +1F600;GRINNING FACE;So;0;ON;;;;;N;;;;; +1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;; +1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;; +1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;; +1F609;WINKING FACE;So;0;ON;;;;;N;;;;; +1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;; +1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;; +1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;; +1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1F611;EXPRESSIONLESS FACE;So;0;ON;;;;;N;;;;; +1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;; +1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;; +1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;; +1F615;CONFUSED FACE;So;0;ON;;;;;N;;;;; +1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;; +1F617;KISSING FACE;So;0;ON;;;;;N;;;;; +1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;; +1F619;KISSING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61B;FACE WITH STUCK-OUT TONGUE;So;0;ON;;;;;N;;;;; +1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;; +1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;; +1F61F;WORRIED FACE;So;0;ON;;;;;N;;;;; +1F620;ANGRY FACE;So;0;ON;;;;;N;;;;; +1F621;POUTING FACE;So;0;ON;;;;;N;;;;; +1F622;CRYING FACE;So;0;ON;;;;;N;;;;; +1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;; +1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;; +1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F626;FROWNING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F627;ANGUISHED FACE;So;0;ON;;;;;N;;;;; +1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;; +1F629;WEARY FACE;So;0;ON;;;;;N;;;;; +1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;; +1F62B;TIRED FACE;So;0;ON;;;;;N;;;;; +1F62C;GRIMACING FACE;So;0;ON;;;;;N;;;;; +1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;; +1F62E;FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F62F;HUSHED FACE;So;0;ON;;;;;N;;;;; +1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;; +1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;; +1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;; +1F634;SLEEPING FACE;So;0;ON;;;;;N;;;;; +1F635;DIZZY FACE;So;0;ON;;;;;N;;;;; +1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;; +1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;; +1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;; +1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;; +1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;; +1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;; +1F641;SLIGHTLY FROWNING FACE;So;0;ON;;;;;N;;;;; +1F642;SLIGHTLY SMILING FACE;So;0;ON;;;;;N;;;;; +1F643;UPSIDE-DOWN FACE;So;0;ON;;;;;N;;;;; +1F644;FACE WITH ROLLING EYES;So;0;ON;;;;;N;;;;; +1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;; +1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;; +1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;; +1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;; +1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;; +1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;; +1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;; +1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;; +1F650;NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F651;SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F652;NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F653;SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F654;TURNED NORTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F655;TURNED SOUTH WEST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F656;TURNED NORTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F657;TURNED SOUTH EAST POINTING LEAF;So;0;ON;;;;;N;;;;; +1F658;NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F659;SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65A;NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65B;SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65C;HEAVY NORTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65D;HEAVY SOUTH WEST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65E;HEAVY NORTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F65F;HEAVY SOUTH EAST POINTING VINE LEAF;So;0;ON;;;;;N;;;;; +1F660;NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F661;SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F662;NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F663;SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F664;HEAVY NORTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F665;HEAVY SOUTH WEST POINTING BUD;So;0;ON;;;;;N;;;;; +1F666;HEAVY NORTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F667;HEAVY SOUTH EAST POINTING BUD;So;0;ON;;;;;N;;;;; +1F668;HOLLOW QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; +1F669;HOLLOW QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +1F66A;SOLID QUILT SQUARE ORNAMENT;So;0;ON;;;;;N;;;;; +1F66B;SOLID QUILT SQUARE ORNAMENT IN BLACK SQUARE;So;0;ON;;;;;N;;;;; +1F66C;LEFTWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66D;UPWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66E;RIGHTWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F66F;DOWNWARDS ROCKET;So;0;ON;;;;;N;;;;; +1F670;SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F671;HEAVY SCRIPT LIGATURE ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F672;LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F673;HEAVY LIGATURE OPEN ET ORNAMENT;So;0;ON;;;;;N;;;;; +1F674;HEAVY AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; +1F675;SWASH AMPERSAND ORNAMENT;So;0;ON;;;;;N;;;;; +1F676;SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F677;SANS-SERIF HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F678;SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +1F679;HEAVY INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67A;SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67B;HEAVY SANS-SERIF INTERROBANG ORNAMENT;So;0;ON;;;;;N;;;;; +1F67C;VERY HEAVY SOLIDUS;So;0;ON;;;;;N;;;;; +1F67D;VERY HEAVY REVERSE SOLIDUS;So;0;ON;;;;;N;;;;; +1F67E;CHECKER BOARD;So;0;ON;;;;;N;;;;; +1F67F;REVERSE CHECKER BOARD;So;0;ON;;;;;N;;;;; +1F680;ROCKET;So;0;ON;;;;;N;;;;; +1F681;HELICOPTER;So;0;ON;;;;;N;;;;; +1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;; +1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;; +1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;; +1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;; +1F686;TRAIN;So;0;ON;;;;;N;;;;; +1F687;METRO;So;0;ON;;;;;N;;;;; +1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;; +1F689;STATION;So;0;ON;;;;;N;;;;; +1F68A;TRAM;So;0;ON;;;;;N;;;;; +1F68B;TRAM CAR;So;0;ON;;;;;N;;;;; +1F68C;BUS;So;0;ON;;;;;N;;;;; +1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;; +1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;; +1F68F;BUS STOP;So;0;ON;;;;;N;;;;; +1F690;MINIBUS;So;0;ON;;;;;N;;;;; +1F691;AMBULANCE;So;0;ON;;;;;N;;;;; +1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;; +1F693;POLICE CAR;So;0;ON;;;;;N;;;;; +1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;; +1F695;TAXI;So;0;ON;;;;;N;;;;; +1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;; +1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;; +1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;; +1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;; +1F69C;TRACTOR;So;0;ON;;;;;N;;;;; +1F69D;MONORAIL;So;0;ON;;;;;N;;;;; +1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;; +1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;; +1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;; +1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;; +1F6A2;SHIP;So;0;ON;;;;;N;;;;; +1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;; +1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;; +1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;; +1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;; +1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;; +1F6AA;DOOR;So;0;ON;;;;;N;;;;; +1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;; +1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;; +1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B2;BICYCLE;So;0;ON;;;;;N;;;;; +1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;; +1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;; +1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;; +1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;; +1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BB;RESTROOM;So;0;ON;;;;;N;;;;; +1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;; +1F6BD;TOILET;So;0;ON;;;;;N;;;;; +1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;; +1F6BF;SHOWER;So;0;ON;;;;;N;;;;; +1F6C0;BATH;So;0;ON;;;;;N;;;;; +1F6C1;BATHTUB;So;0;ON;;;;;N;;;;; +1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;; +1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;; +1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;; +1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;; +1F6C6;TRIANGLE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; +1F6C7;PROHIBITED SIGN;So;0;ON;;;;;N;;;;; +1F6C8;CIRCLED INFORMATION SOURCE;So;0;ON;;;;;N;;;;; +1F6C9;BOYS SYMBOL;So;0;ON;;;;;N;;;;; +1F6CA;GIRLS SYMBOL;So;0;ON;;;;;N;;;;; +1F6CB;COUCH AND LAMP;So;0;ON;;;;;N;;;;; +1F6CC;SLEEPING ACCOMMODATION;So;0;ON;;;;;N;;;;; +1F6CD;SHOPPING BAGS;So;0;ON;;;;;N;;;;; +1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;; +1F6CF;BED;So;0;ON;;;;;N;;;;; +1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;; +1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;; +1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;; +1F6D3;STUPA;So;0;ON;;;;;N;;;;; +1F6D4;PAGODA;So;0;ON;;;;;N;;;;; +1F6D5;HINDU TEMPLE;So;0;ON;;;;;N;;;;; +1F6D6;HUT;So;0;ON;;;;;N;;;;; +1F6D7;ELEVATOR;So;0;ON;;;;;N;;;;; +1F6D8;LANDSLIDE;So;0;ON;;;;;N;;;;; +1F6DC;WIRELESS;So;0;ON;;;;;N;;;;; +1F6DD;PLAYGROUND SLIDE;So;0;ON;;;;;N;;;;; +1F6DE;WHEEL;So;0;ON;;;;;N;;;;; +1F6DF;RING BUOY;So;0;ON;;;;;N;;;;; +1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;; +1F6E1;SHIELD;So;0;ON;;;;;N;;;;; +1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;; +1F6E3;MOTORWAY;So;0;ON;;;;;N;;;;; +1F6E4;RAILWAY TRACK;So;0;ON;;;;;N;;;;; +1F6E5;MOTOR BOAT;So;0;ON;;;;;N;;;;; +1F6E6;UP-POINTING MILITARY AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E7;UP-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E8;UP-POINTING SMALL AIRPLANE;So;0;ON;;;;;N;;;;; +1F6E9;SMALL AIRPLANE;So;0;ON;;;;;N;;;;; +1F6EA;NORTHEAST-POINTING AIRPLANE;So;0;ON;;;;;N;;;;; +1F6EB;AIRPLANE DEPARTURE;So;0;ON;;;;;N;;;;; +1F6EC;AIRPLANE ARRIVING;So;0;ON;;;;;N;;;;; +1F6F0;SATELLITE;So;0;ON;;;;;N;;;;; +1F6F1;ONCOMING FIRE ENGINE;So;0;ON;;;;;N;;;;; +1F6F2;DIESEL LOCOMOTIVE;So;0;ON;;;;;N;;;;; +1F6F3;PASSENGER SHIP;So;0;ON;;;;;N;;;;; +1F6F4;SCOOTER;So;0;ON;;;;;N;;;;; +1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;; +1F6F6;CANOE;So;0;ON;;;;;N;;;;; +1F6F7;SLED;So;0;ON;;;;;N;;;;; +1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;; +1F6F9;SKATEBOARD;So;0;ON;;;;;N;;;;; +1F6FA;AUTO RICKSHAW;So;0;ON;;;;;N;;;;; +1F6FB;PICKUP TRUCK;So;0;ON;;;;;N;;;;; +1F6FC;ROLLER SKATE;So;0;ON;;;;;N;;;;; +1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; +1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; +1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; +1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;; +1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;; +1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;; +1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;; +1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;; +1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;; +1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;; +1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;; +1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;; +1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;; +1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;; +1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;; +1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;; +1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;; +1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;; +1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;; +1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;; +1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;; +1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;; +1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;; +1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;; +1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;; +1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;; +1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;; +1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;; +1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;; +1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;; +1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;; +1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;; +1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;; +1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;; +1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;; +1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;; +1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;; +1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;; +1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;; +1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;; +1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;; +1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;; +1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;; +1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;; +1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;; +1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;; +1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;; +1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;; +1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;; +1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;; +1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;; +1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;; +1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;; +1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;; +1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;; +1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;; +1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;; +1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;; +1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;; +1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;; +1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;; +1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;; +1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;; +1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;; +1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;; +1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;; +1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;; +1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;; +1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;; +1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;; +1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;; +1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;; +1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;; +1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;; +1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;; +1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;; +1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;; +1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;; +1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;; +1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;; +1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;; +1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;; +1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;; +1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;; +1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;; +1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;; +1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;; +1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;; +1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;; +1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;; +1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;; +1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;; +1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;; +1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;; +1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;; +1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;; +1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;; +1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;; +1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;; +1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;; +1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;; +1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;; +1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;; +1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;; +1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;; +1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;; +1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;; +1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;; +1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;; +1F774;LOT OF FORTUNE;So;0;ON;;;;;N;;;;; +1F775;OCCULTATION;So;0;ON;;;;;N;;;;; +1F776;LUNAR ECLIPSE;So;0;ON;;;;;N;;;;; +1F777;VESTA FORM TWO;So;0;ON;;;;;N;;;;; +1F778;ASTRAEA FORM TWO;So;0;ON;;;;;N;;;;; +1F779;HYGIEA FORM TWO;So;0;ON;;;;;N;;;;; +1F77A;PARTHENOPE FORM TWO;So;0;ON;;;;;N;;;;; +1F77B;HAUMEA;So;0;ON;;;;;N;;;;; +1F77C;MAKEMAKE;So;0;ON;;;;;N;;;;; +1F77D;GONGGONG;So;0;ON;;;;;N;;;;; +1F77E;QUAOAR;So;0;ON;;;;;N;;;;; +1F77F;ORCUS;So;0;ON;;;;;N;;;;; +1F780;BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F781;BLACK UP-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F782;BLACK RIGHT-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F783;BLACK DOWN-POINTING ISOSCELES RIGHT TRIANGLE;So;0;ON;;;;;N;;;;; +1F784;BLACK SLIGHTLY SMALL CIRCLE;So;0;ON;;;;;N;;;;; +1F785;MEDIUM BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F786;BOLD WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F787;HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F788;VERY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F789;EXTREMELY HEAVY WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1F78A;WHITE CIRCLE CONTAINING BLACK SMALL CIRCLE;So;0;ON;;;;;N;;;;; +1F78B;ROUND TARGET;So;0;ON;;;;;N;;;;; +1F78C;BLACK TINY SQUARE;So;0;ON;;;;;N;;;;; +1F78D;BLACK SLIGHTLY SMALL SQUARE;So;0;ON;;;;;N;;;;; +1F78E;LIGHT WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F78F;MEDIUM WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F790;BOLD WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F791;HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F792;VERY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F793;EXTREMELY HEAVY WHITE SQUARE;So;0;ON;;;;;N;;;;; +1F794;WHITE SQUARE CONTAINING BLACK VERY SMALL SQUARE;So;0;ON;;;;;N;;;;; +1F795;WHITE SQUARE CONTAINING BLACK MEDIUM SQUARE;So;0;ON;;;;;N;;;;; +1F796;SQUARE TARGET;So;0;ON;;;;;N;;;;; +1F797;BLACK TINY DIAMOND;So;0;ON;;;;;N;;;;; +1F798;BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F799;BLACK MEDIUM SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F79A;WHITE DIAMOND CONTAINING BLACK VERY SMALL DIAMOND;So;0;ON;;;;;N;;;;; +1F79B;WHITE DIAMOND CONTAINING BLACK MEDIUM DIAMOND;So;0;ON;;;;;N;;;;; +1F79C;DIAMOND TARGET;So;0;ON;;;;;N;;;;; +1F79D;BLACK TINY LOZENGE;So;0;ON;;;;;N;;;;; +1F79E;BLACK VERY SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F79F;BLACK MEDIUM SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F7A0;WHITE LOZENGE CONTAINING BLACK SMALL LOZENGE;So;0;ON;;;;;N;;;;; +1F7A1;THIN GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A2;LIGHT GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A3;MEDIUM GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A4;BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A5;VERY BOLD GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A6;VERY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A7;EXTREMELY HEAVY GREEK CROSS;So;0;ON;;;;;N;;;;; +1F7A8;THIN SALTIRE;So;0;ON;;;;;N;;;;; +1F7A9;LIGHT SALTIRE;So;0;ON;;;;;N;;;;; +1F7AA;MEDIUM SALTIRE;So;0;ON;;;;;N;;;;; +1F7AB;BOLD SALTIRE;So;0;ON;;;;;N;;;;; +1F7AC;HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AD;VERY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AE;EXTREMELY HEAVY SALTIRE;So;0;ON;;;;;N;;;;; +1F7AF;LIGHT FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B0;MEDIUM FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B1;BOLD FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B2;HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B3;VERY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B4;EXTREMELY HEAVY FIVE SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B5;LIGHT SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B6;MEDIUM SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B7;BOLD SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B8;HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7B9;VERY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BA;EXTREMELY HEAVY SIX SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BB;LIGHT EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BC;MEDIUM EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BD;BOLD EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BE;HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7BF;VERY HEAVY EIGHT SPOKED ASTERISK;So;0;ON;;;;;N;;;;; +1F7C0;LIGHT THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C1;MEDIUM THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C2;THREE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C3;MEDIUM THREE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C4;LIGHT FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C5;MEDIUM FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C6;FOUR POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7C7;MEDIUM FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C8;REVERSE LIGHT FOUR POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7C9;LIGHT FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CA;HEAVY FIVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CB;MEDIUM SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CC;HEAVY SIX POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CD;SIX POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7CE;MEDIUM EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7CF;HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D0;VERY HEAVY EIGHT POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D1;HEAVY EIGHT POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7D2;LIGHT TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D3;HEAVY TWELVE POINTED BLACK STAR;So;0;ON;;;;;N;;;;; +1F7D4;HEAVY TWELVE POINTED PINWHEEL STAR;So;0;ON;;;;;N;;;;; +1F7D5;CIRCLED TRIANGLE;So;0;ON;;;;;N;;;;; +1F7D6;NEGATIVE CIRCLED TRIANGLE;So;0;ON;;;;;N;;;;; +1F7D7;CIRCLED SQUARE;So;0;ON;;;;;N;;;;; +1F7D8;NEGATIVE CIRCLED SQUARE;So;0;ON;;;;;N;;;;; +1F7D9;NINE POINTED WHITE STAR;So;0;ON;;;;;N;;;;; +1F7E0;LARGE ORANGE CIRCLE;So;0;ON;;;;;N;;;;; +1F7E1;LARGE YELLOW CIRCLE;So;0;ON;;;;;N;;;;; +1F7E2;LARGE GREEN CIRCLE;So;0;ON;;;;;N;;;;; +1F7E3;LARGE PURPLE CIRCLE;So;0;ON;;;;;N;;;;; +1F7E4;LARGE BROWN CIRCLE;So;0;ON;;;;;N;;;;; +1F7E5;LARGE RED SQUARE;So;0;ON;;;;;N;;;;; +1F7E6;LARGE BLUE SQUARE;So;0;ON;;;;;N;;;;; +1F7E7;LARGE ORANGE SQUARE;So;0;ON;;;;;N;;;;; +1F7E8;LARGE YELLOW SQUARE;So;0;ON;;;;;N;;;;; +1F7E9;LARGE GREEN SQUARE;So;0;ON;;;;;N;;;;; +1F7EA;LARGE PURPLE SQUARE;So;0;ON;;;;;N;;;;; +1F7EB;LARGE BROWN SQUARE;So;0;ON;;;;;N;;;;; +1F7F0;HEAVY EQUALS SIGN;So;0;ON;;;;;N;;;;; +1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F803;DOWNWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F804;LEFTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F805;UPWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F806;RIGHTWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F807;DOWNWARDS ARROW WITH MEDIUM TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F808;LEFTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F809;UPWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F80A;RIGHTWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F80B;DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F810;LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F811;UPWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F812;RIGHTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F813;DOWNWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F814;LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F815;UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F816;RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F817;DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F818;HEAVY LEFTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F819;HEAVY UPWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81A;HEAVY RIGHTWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81B;HEAVY DOWNWARDS ARROW WITH EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81C;HEAVY LEFTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81D;HEAVY UPWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81E;HEAVY RIGHTWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F81F;HEAVY DOWNWARDS ARROW WITH LARGE EQUILATERAL ARROWHEAD;So;0;ON;;;;;N;;;;; +1F820;LEFTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F821;UPWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F822;RIGHTWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F823;DOWNWARDS TRIANGLE-HEADED ARROW WITH NARROW SHAFT;So;0;ON;;;;;N;;;;; +1F824;LEFTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F825;UPWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F826;RIGHTWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F827;DOWNWARDS TRIANGLE-HEADED ARROW WITH MEDIUM SHAFT;So;0;ON;;;;;N;;;;; +1F828;LEFTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F829;UPWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82A;RIGHTWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82B;DOWNWARDS TRIANGLE-HEADED ARROW WITH BOLD SHAFT;So;0;ON;;;;;N;;;;; +1F82C;LEFTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82D;UPWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82E;RIGHTWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F82F;DOWNWARDS TRIANGLE-HEADED ARROW WITH HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F830;LEFTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F831;UPWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F832;RIGHTWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F833;DOWNWARDS TRIANGLE-HEADED ARROW WITH VERY HEAVY SHAFT;So;0;ON;;;;;N;;;;; +1F834;LEFTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F835;UPWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F836;RIGHTWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F837;DOWNWARDS FINGER-POST ARROW;So;0;ON;;;;;N;;;;; +1F838;LEFTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F839;UPWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83A;RIGHTWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83B;DOWNWARDS SQUARED ARROW;So;0;ON;;;;;N;;;;; +1F83C;LEFTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83D;UPWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83E;RIGHTWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F83F;DOWNWARDS COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F840;LEFTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F841;UPWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F842;RIGHTWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F843;DOWNWARDS HEAVY COMPRESSED ARROW;So;0;ON;;;;;N;;;;; +1F844;LEFTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F845;UPWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F846;RIGHTWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F847;DOWNWARDS HEAVY ARROW;So;0;ON;;;;;N;;;;; +1F850;LEFTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F851;UPWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F852;RIGHTWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F853;DOWNWARDS SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F854;NORTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F855;NORTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F856;SOUTH EAST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F857;SOUTH WEST SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F858;LEFT RIGHT SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F859;UP DOWN SANS-SERIF ARROW;So;0;ON;;;;;N;;;;; +1F860;WIDE-HEADED LEFTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F861;WIDE-HEADED UPWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F862;WIDE-HEADED RIGHTWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F863;WIDE-HEADED DOWNWARDS LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F864;WIDE-HEADED NORTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F865;WIDE-HEADED NORTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F866;WIDE-HEADED SOUTH EAST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F867;WIDE-HEADED SOUTH WEST LIGHT BARB ARROW;So;0;ON;;;;;N;;;;; +1F868;WIDE-HEADED LEFTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F869;WIDE-HEADED UPWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86A;WIDE-HEADED RIGHTWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86B;WIDE-HEADED DOWNWARDS BARB ARROW;So;0;ON;;;;;N;;;;; +1F86C;WIDE-HEADED NORTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86D;WIDE-HEADED NORTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86E;WIDE-HEADED SOUTH EAST BARB ARROW;So;0;ON;;;;;N;;;;; +1F86F;WIDE-HEADED SOUTH WEST BARB ARROW;So;0;ON;;;;;N;;;;; +1F870;WIDE-HEADED LEFTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F871;WIDE-HEADED UPWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F872;WIDE-HEADED RIGHTWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F873;WIDE-HEADED DOWNWARDS MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F874;WIDE-HEADED NORTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F875;WIDE-HEADED NORTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F876;WIDE-HEADED SOUTH EAST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F877;WIDE-HEADED SOUTH WEST MEDIUM BARB ARROW;So;0;ON;;;;;N;;;;; +1F878;WIDE-HEADED LEFTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F879;WIDE-HEADED UPWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87A;WIDE-HEADED RIGHTWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87B;WIDE-HEADED DOWNWARDS HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87C;WIDE-HEADED NORTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87D;WIDE-HEADED NORTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87E;WIDE-HEADED SOUTH EAST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F87F;WIDE-HEADED SOUTH WEST HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F880;WIDE-HEADED LEFTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F881;WIDE-HEADED UPWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F882;WIDE-HEADED RIGHTWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F883;WIDE-HEADED DOWNWARDS VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F884;WIDE-HEADED NORTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F885;WIDE-HEADED NORTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F886;WIDE-HEADED SOUTH EAST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F887;WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW;So;0;ON;;;;;N;;;;; +1F890;LEFTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F891;UPWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F892;RIGHTWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F893;DOWNWARDS TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F894;LEFTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F895;UPWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F896;RIGHTWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F897;DOWNWARDS WHITE ARROW WITHIN TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;; +1F898;LEFTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F899;UPWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89A;RIGHTWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89B;DOWNWARDS ARROW WITH NOTCHED TAIL;So;0;ON;;;;;N;;;;; +1F89C;HEAVY ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; +1F89D;HEAVY ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F89E;HEAVY ARROW SHAFT WIDTH ONE HALF;So;0;ON;;;;;N;;;;; +1F89F;HEAVY ARROW SHAFT WIDTH ONE THIRD;So;0;ON;;;;;N;;;;; +1F8A0;LEFTWARDS BOTTOM-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A1;RIGHTWARDS BOTTOM SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A2;LEFTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A3;RIGHTWARDS TOP SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A4;LEFTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A5;RIGHTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A6;LEFTWARDS RIGHT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A7;RIGHTWARDS LEFT-SHADED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A8;LEFTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8A9;RIGHTWARDS BACK-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AA;LEFTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;; +1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;; +1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;; +1F8B0;ARROW POINTING UPWARDS THEN NORTH WEST;So;0;ON;;;;;N;;;;; +1F8B1;ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST;So;0;ON;;;;;N;;;;; +1F8B2;RIGHTWARDS ARROW WITH LOWER HOOK;So;0;ON;;;;;N;;;;; +1F8B3;DOWNWARDS BLACK ARROW TO BAR;So;0;ON;;;;;N;;;;; +1F8B4;NEGATIVE SQUARED LEFTWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8B5;NEGATIVE SQUARED UPWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8B6;NEGATIVE SQUARED RIGHTWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8B7;NEGATIVE SQUARED DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8B8;NORTH WEST ARROW FROM BAR;So;0;ON;;;;;N;;;;; +1F8B9;NORTH EAST ARROW FROM BAR;So;0;ON;;;;;N;;;;; +1F8BA;SOUTH EAST ARROW FROM BAR;So;0;ON;;;;;N;;;;; +1F8BB;SOUTH WEST ARROW FROM BAR;So;0;ON;;;;;N;;;;; +1F8C0;LEFTWARDS ARROW FROM DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8C1;RIGHTWARDS ARROW FROM DOWNWARDS ARROW;So;0;ON;;;;;N;;;;; +1F8D0;LONG RIGHTWARDS ARROW OVER LONG LEFTWARDS ARROW;Sm;0;ON;;;;;N;;;;; +1F8D1;LONG RIGHTWARDS HARPOON OVER LONG LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;; +1F8D2;LONG RIGHTWARDS HARPOON ABOVE SHORT LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;; +1F8D3;SHORT RIGHTWARDS HARPOON ABOVE LONG LEFTWARDS HARPOON;Sm;0;ON;;;;;N;;;;; +1F8D4;LONG LEFTWARDS HARPOON ABOVE SHORT RIGHTWARDS HARPOON;Sm;0;ON;;;;;N;;;;; +1F8D5;SHORT LEFTWARDS HARPOON ABOVE LONG RIGHTWARDS HARPOON;Sm;0;ON;;;;;N;;;;; +1F8D6;LONG RIGHTWARDS ARROW THROUGH X;Sm;0;ON;;;;;N;;;;; +1F8D7;LONG RIGHTWARDS ARROW WITH DOUBLE SLASH;Sm;0;ON;;;;;N;;;;; +1F8D8;LONG LEFT RIGHT ARROW WITH DEPENDENT LOBE;Sm;0;ON;;;;;N;;;;; +1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;; +1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;; +1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;; +1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;; +1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;; +1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;; +1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;; +1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;; +1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;; +1F90C;PINCHED FINGERS;So;0;ON;;;;;N;;;;; +1F90D;WHITE HEART;So;0;ON;;;;;N;;;;; +1F90E;BROWN HEART;So;0;ON;;;;;N;;;;; +1F90F;PINCHING HAND;So;0;ON;;;;;N;;;;; +1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;; +1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;; +1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;; +1F913;NERD FACE;So;0;ON;;;;;N;;;;; +1F914;THINKING FACE;So;0;ON;;;;;N;;;;; +1F915;FACE WITH HEAD-BANDAGE;So;0;ON;;;;;N;;;;; +1F916;ROBOT FACE;So;0;ON;;;;;N;;;;; +1F917;HUGGING FACE;So;0;ON;;;;;N;;;;; +1F918;SIGN OF THE HORNS;So;0;ON;;;;;N;;;;; +1F919;CALL ME HAND;So;0;ON;;;;;N;;;;; +1F91A;RAISED BACK OF HAND;So;0;ON;;;;;N;;;;; +1F91B;LEFT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;; +1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;; +1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;; +1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;; +1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;; +1F921;CLOWN FACE;So;0;ON;;;;;N;;;;; +1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;; +1F923;ROLLING ON THE FLOOR LAUGHING;So;0;ON;;;;;N;;;;; +1F924;DROOLING FACE;So;0;ON;;;;;N;;;;; +1F925;LYING FACE;So;0;ON;;;;;N;;;;; +1F926;FACE PALM;So;0;ON;;;;;N;;;;; +1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;; +1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;; +1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;; +1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;; +1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;; +1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;; +1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;; +1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;; +1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;; +1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;; +1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;; +1F933;SELFIE;So;0;ON;;;;;N;;;;; +1F934;PRINCE;So;0;ON;;;;;N;;;;; +1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;; +1F936;MOTHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F937;SHRUG;So;0;ON;;;;;N;;;;; +1F938;PERSON DOING CARTWHEEL;So;0;ON;;;;;N;;;;; +1F939;JUGGLING;So;0;ON;;;;;N;;;;; +1F93A;FENCER;So;0;ON;;;;;N;;;;; +1F93B;MODERN PENTATHLON;So;0;ON;;;;;N;;;;; +1F93C;WRESTLERS;So;0;ON;;;;;N;;;;; +1F93D;WATER POLO;So;0;ON;;;;;N;;;;; +1F93E;HANDBALL;So;0;ON;;;;;N;;;;; +1F93F;DIVING MASK;So;0;ON;;;;;N;;;;; +1F940;WILTED FLOWER;So;0;ON;;;;;N;;;;; +1F941;DRUM WITH DRUMSTICKS;So;0;ON;;;;;N;;;;; +1F942;CLINKING GLASSES;So;0;ON;;;;;N;;;;; +1F943;TUMBLER GLASS;So;0;ON;;;;;N;;;;; +1F944;SPOON;So;0;ON;;;;;N;;;;; +1F945;GOAL NET;So;0;ON;;;;;N;;;;; +1F946;RIFLE;So;0;ON;;;;;N;;;;; +1F947;FIRST PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F948;SECOND PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;; +1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;; +1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;; +1F94C;CURLING STONE;So;0;ON;;;;;N;;;;; +1F94D;LACROSSE STICK AND BALL;So;0;ON;;;;;N;;;;; +1F94E;SOFTBALL;So;0;ON;;;;;N;;;;; +1F94F;FLYING DISC;So;0;ON;;;;;N;;;;; +1F950;CROISSANT;So;0;ON;;;;;N;;;;; +1F951;AVOCADO;So;0;ON;;;;;N;;;;; +1F952;CUCUMBER;So;0;ON;;;;;N;;;;; +1F953;BACON;So;0;ON;;;;;N;;;;; +1F954;POTATO;So;0;ON;;;;;N;;;;; +1F955;CARROT;So;0;ON;;;;;N;;;;; +1F956;BAGUETTE BREAD;So;0;ON;;;;;N;;;;; +1F957;GREEN SALAD;So;0;ON;;;;;N;;;;; +1F958;SHALLOW PAN OF FOOD;So;0;ON;;;;;N;;;;; +1F959;STUFFED FLATBREAD;So;0;ON;;;;;N;;;;; +1F95A;EGG;So;0;ON;;;;;N;;;;; +1F95B;GLASS OF MILK;So;0;ON;;;;;N;;;;; +1F95C;PEANUTS;So;0;ON;;;;;N;;;;; +1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;; +1F95E;PANCAKES;So;0;ON;;;;;N;;;;; +1F95F;DUMPLING;So;0;ON;;;;;N;;;;; +1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;; +1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;; +1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;; +1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;; +1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;; +1F965;COCONUT;So;0;ON;;;;;N;;;;; +1F966;BROCCOLI;So;0;ON;;;;;N;;;;; +1F967;PIE;So;0;ON;;;;;N;;;;; +1F968;PRETZEL;So;0;ON;;;;;N;;;;; +1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;; +1F96A;SANDWICH;So;0;ON;;;;;N;;;;; +1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;; +1F96C;LEAFY GREEN;So;0;ON;;;;;N;;;;; +1F96D;MANGO;So;0;ON;;;;;N;;;;; +1F96E;MOON CAKE;So;0;ON;;;;;N;;;;; +1F96F;BAGEL;So;0;ON;;;;;N;;;;; +1F970;SMILING FACE WITH SMILING EYES AND THREE HEARTS;So;0;ON;;;;;N;;;;; +1F971;YAWNING FACE;So;0;ON;;;;;N;;;;; +1F972;SMILING FACE WITH TEAR;So;0;ON;;;;;N;;;;; +1F973;FACE WITH PARTY HORN AND PARTY HAT;So;0;ON;;;;;N;;;;; +1F974;FACE WITH UNEVEN EYES AND WAVY MOUTH;So;0;ON;;;;;N;;;;; +1F975;OVERHEATED FACE;So;0;ON;;;;;N;;;;; +1F976;FREEZING FACE;So;0;ON;;;;;N;;;;; +1F977;NINJA;So;0;ON;;;;;N;;;;; +1F978;DISGUISED FACE;So;0;ON;;;;;N;;;;; +1F979;FACE HOLDING BACK TEARS;So;0;ON;;;;;N;;;;; +1F97A;FACE WITH PLEADING EYES;So;0;ON;;;;;N;;;;; +1F97B;SARI;So;0;ON;;;;;N;;;;; +1F97C;LAB COAT;So;0;ON;;;;;N;;;;; +1F97D;GOGGLES;So;0;ON;;;;;N;;;;; +1F97E;HIKING BOOT;So;0;ON;;;;;N;;;;; +1F97F;FLAT SHOE;So;0;ON;;;;;N;;;;; +1F980;CRAB;So;0;ON;;;;;N;;;;; +1F981;LION FACE;So;0;ON;;;;;N;;;;; +1F982;SCORPION;So;0;ON;;;;;N;;;;; +1F983;TURKEY;So;0;ON;;;;;N;;;;; +1F984;UNICORN FACE;So;0;ON;;;;;N;;;;; +1F985;EAGLE;So;0;ON;;;;;N;;;;; +1F986;DUCK;So;0;ON;;;;;N;;;;; +1F987;BAT;So;0;ON;;;;;N;;;;; +1F988;SHARK;So;0;ON;;;;;N;;;;; +1F989;OWL;So;0;ON;;;;;N;;;;; +1F98A;FOX FACE;So;0;ON;;;;;N;;;;; +1F98B;BUTTERFLY;So;0;ON;;;;;N;;;;; +1F98C;DEER;So;0;ON;;;;;N;;;;; +1F98D;GORILLA;So;0;ON;;;;;N;;;;; +1F98E;LIZARD;So;0;ON;;;;;N;;;;; +1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;; +1F990;SHRIMP;So;0;ON;;;;;N;;;;; +1F991;SQUID;So;0;ON;;;;;N;;;;; +1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;; +1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;; +1F994;HEDGEHOG;So;0;ON;;;;;N;;;;; +1F995;SAUROPOD;So;0;ON;;;;;N;;;;; +1F996;T-REX;So;0;ON;;;;;N;;;;; +1F997;CRICKET;So;0;ON;;;;;N;;;;; +1F998;KANGAROO;So;0;ON;;;;;N;;;;; +1F999;LLAMA;So;0;ON;;;;;N;;;;; +1F99A;PEACOCK;So;0;ON;;;;;N;;;;; +1F99B;HIPPOPOTAMUS;So;0;ON;;;;;N;;;;; +1F99C;PARROT;So;0;ON;;;;;N;;;;; +1F99D;RACCOON;So;0;ON;;;;;N;;;;; +1F99E;LOBSTER;So;0;ON;;;;;N;;;;; +1F99F;MOSQUITO;So;0;ON;;;;;N;;;;; +1F9A0;MICROBE;So;0;ON;;;;;N;;;;; +1F9A1;BADGER;So;0;ON;;;;;N;;;;; +1F9A2;SWAN;So;0;ON;;;;;N;;;;; +1F9A3;MAMMOTH;So;0;ON;;;;;N;;;;; +1F9A4;DODO;So;0;ON;;;;;N;;;;; +1F9A5;SLOTH;So;0;ON;;;;;N;;;;; +1F9A6;OTTER;So;0;ON;;;;;N;;;;; +1F9A7;ORANGUTAN;So;0;ON;;;;;N;;;;; +1F9A8;SKUNK;So;0;ON;;;;;N;;;;; +1F9A9;FLAMINGO;So;0;ON;;;;;N;;;;; +1F9AA;OYSTER;So;0;ON;;;;;N;;;;; +1F9AB;BEAVER;So;0;ON;;;;;N;;;;; +1F9AC;BISON;So;0;ON;;;;;N;;;;; +1F9AD;SEAL;So;0;ON;;;;;N;;;;; +1F9AE;GUIDE DOG;So;0;ON;;;;;N;;;;; +1F9AF;PROBING CANE;So;0;ON;;;;;N;;;;; +1F9B0;EMOJI COMPONENT RED HAIR;So;0;ON;;;;;N;;;;; +1F9B1;EMOJI COMPONENT CURLY HAIR;So;0;ON;;;;;N;;;;; +1F9B2;EMOJI COMPONENT BALD;So;0;ON;;;;;N;;;;; +1F9B3;EMOJI COMPONENT WHITE HAIR;So;0;ON;;;;;N;;;;; +1F9B4;BONE;So;0;ON;;;;;N;;;;; +1F9B5;LEG;So;0;ON;;;;;N;;;;; +1F9B6;FOOT;So;0;ON;;;;;N;;;;; +1F9B7;TOOTH;So;0;ON;;;;;N;;;;; +1F9B8;SUPERHERO;So;0;ON;;;;;N;;;;; +1F9B9;SUPERVILLAIN;So;0;ON;;;;;N;;;;; +1F9BA;SAFETY VEST;So;0;ON;;;;;N;;;;; +1F9BB;EAR WITH HEARING AID;So;0;ON;;;;;N;;;;; +1F9BC;MOTORIZED WHEELCHAIR;So;0;ON;;;;;N;;;;; +1F9BD;MANUAL WHEELCHAIR;So;0;ON;;;;;N;;;;; +1F9BE;MECHANICAL ARM;So;0;ON;;;;;N;;;;; +1F9BF;MECHANICAL LEG;So;0;ON;;;;;N;;;;; +1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;; +1F9C1;CUPCAKE;So;0;ON;;;;;N;;;;; +1F9C2;SALT SHAKER;So;0;ON;;;;;N;;;;; +1F9C3;BEVERAGE BOX;So;0;ON;;;;;N;;;;; +1F9C4;GARLIC;So;0;ON;;;;;N;;;;; +1F9C5;ONION;So;0;ON;;;;;N;;;;; +1F9C6;FALAFEL;So;0;ON;;;;;N;;;;; +1F9C7;WAFFLE;So;0;ON;;;;;N;;;;; +1F9C8;BUTTER;So;0;ON;;;;;N;;;;; +1F9C9;MATE DRINK;So;0;ON;;;;;N;;;;; +1F9CA;ICE CUBE;So;0;ON;;;;;N;;;;; +1F9CB;BUBBLE TEA;So;0;ON;;;;;N;;;;; +1F9CC;TROLL;So;0;ON;;;;;N;;;;; +1F9CD;STANDING PERSON;So;0;ON;;;;;N;;;;; +1F9CE;KNEELING PERSON;So;0;ON;;;;;N;;;;; +1F9CF;DEAF PERSON;So;0;ON;;;;;N;;;;; +1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;; +1F9D1;ADULT;So;0;ON;;;;;N;;;;; +1F9D2;CHILD;So;0;ON;;;;;N;;;;; +1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;; +1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;; +1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;; +1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;; +1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;; +1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;; +1F9D9;MAGE;So;0;ON;;;;;N;;;;; +1F9DA;FAIRY;So;0;ON;;;;;N;;;;; +1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;; +1F9DC;MERPERSON;So;0;ON;;;;;N;;;;; +1F9DD;ELF;So;0;ON;;;;;N;;;;; +1F9DE;GENIE;So;0;ON;;;;;N;;;;; +1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;; +1F9E0;BRAIN;So;0;ON;;;;;N;;;;; +1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;; +1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;; +1F9E3;SCARF;So;0;ON;;;;;N;;;;; +1F9E4;GLOVES;So;0;ON;;;;;N;;;;; +1F9E5;COAT;So;0;ON;;;;;N;;;;; +1F9E6;SOCKS;So;0;ON;;;;;N;;;;; +1F9E7;RED GIFT ENVELOPE;So;0;ON;;;;;N;;;;; +1F9E8;FIRECRACKER;So;0;ON;;;;;N;;;;; +1F9E9;JIGSAW PUZZLE PIECE;So;0;ON;;;;;N;;;;; +1F9EA;TEST TUBE;So;0;ON;;;;;N;;;;; +1F9EB;PETRI DISH;So;0;ON;;;;;N;;;;; +1F9EC;DNA DOUBLE HELIX;So;0;ON;;;;;N;;;;; +1F9ED;COMPASS;So;0;ON;;;;;N;;;;; +1F9EE;ABACUS;So;0;ON;;;;;N;;;;; +1F9EF;FIRE EXTINGUISHER;So;0;ON;;;;;N;;;;; +1F9F0;TOOLBOX;So;0;ON;;;;;N;;;;; +1F9F1;BRICK;So;0;ON;;;;;N;;;;; +1F9F2;MAGNET;So;0;ON;;;;;N;;;;; +1F9F3;LUGGAGE;So;0;ON;;;;;N;;;;; +1F9F4;LOTION BOTTLE;So;0;ON;;;;;N;;;;; +1F9F5;SPOOL OF THREAD;So;0;ON;;;;;N;;;;; +1F9F6;BALL OF YARN;So;0;ON;;;;;N;;;;; +1F9F7;SAFETY PIN;So;0;ON;;;;;N;;;;; +1F9F8;TEDDY BEAR;So;0;ON;;;;;N;;;;; +1F9F9;BROOM;So;0;ON;;;;;N;;;;; +1F9FA;BASKET;So;0;ON;;;;;N;;;;; +1F9FB;ROLL OF PAPER;So;0;ON;;;;;N;;;;; +1F9FC;BAR OF SOAP;So;0;ON;;;;;N;;;;; +1F9FD;SPONGE;So;0;ON;;;;;N;;;;; +1F9FE;RECEIPT;So;0;ON;;;;;N;;;;; +1F9FF;NAZAR AMULET;So;0;ON;;;;;N;;;;; +1FA00;NEUTRAL CHESS KING;So;0;ON;;;;;N;;;;; +1FA01;NEUTRAL CHESS QUEEN;So;0;ON;;;;;N;;;;; +1FA02;NEUTRAL CHESS ROOK;So;0;ON;;;;;N;;;;; +1FA03;NEUTRAL CHESS BISHOP;So;0;ON;;;;;N;;;;; +1FA04;NEUTRAL CHESS KNIGHT;So;0;ON;;;;;N;;;;; +1FA05;NEUTRAL CHESS PAWN;So;0;ON;;;;;N;;;;; +1FA06;WHITE CHESS KNIGHT ROTATED FORTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA07;BLACK CHESS KNIGHT ROTATED FORTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA08;NEUTRAL CHESS KNIGHT ROTATED FORTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA09;WHITE CHESS KING ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0A;WHITE CHESS QUEEN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0B;WHITE CHESS ROOK ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0C;WHITE CHESS BISHOP ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0D;WHITE CHESS KNIGHT ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0E;WHITE CHESS PAWN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA0F;BLACK CHESS KING ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA10;BLACK CHESS QUEEN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA11;BLACK CHESS ROOK ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA12;BLACK CHESS BISHOP ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA13;BLACK CHESS KNIGHT ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA14;BLACK CHESS PAWN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA15;NEUTRAL CHESS KING ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA16;NEUTRAL CHESS QUEEN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA17;NEUTRAL CHESS ROOK ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA18;NEUTRAL CHESS BISHOP ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA19;NEUTRAL CHESS KNIGHT ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA1A;NEUTRAL CHESS PAWN ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA1B;WHITE CHESS KNIGHT ROTATED ONE HUNDRED THIRTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA1C;BLACK CHESS KNIGHT ROTATED ONE HUNDRED THIRTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA1D;NEUTRAL CHESS KNIGHT ROTATED ONE HUNDRED THIRTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA1E;WHITE CHESS TURNED KING;So;0;ON;;;;;N;;;;; +1FA1F;WHITE CHESS TURNED QUEEN;So;0;ON;;;;;N;;;;; +1FA20;WHITE CHESS TURNED ROOK;So;0;ON;;;;;N;;;;; +1FA21;WHITE CHESS TURNED BISHOP;So;0;ON;;;;;N;;;;; +1FA22;WHITE CHESS TURNED KNIGHT;So;0;ON;;;;;N;;;;; +1FA23;WHITE CHESS TURNED PAWN;So;0;ON;;;;;N;;;;; +1FA24;BLACK CHESS TURNED KING;So;0;ON;;;;;N;;;;; +1FA25;BLACK CHESS TURNED QUEEN;So;0;ON;;;;;N;;;;; +1FA26;BLACK CHESS TURNED ROOK;So;0;ON;;;;;N;;;;; +1FA27;BLACK CHESS TURNED BISHOP;So;0;ON;;;;;N;;;;; +1FA28;BLACK CHESS TURNED KNIGHT;So;0;ON;;;;;N;;;;; +1FA29;BLACK CHESS TURNED PAWN;So;0;ON;;;;;N;;;;; +1FA2A;NEUTRAL CHESS TURNED KING;So;0;ON;;;;;N;;;;; +1FA2B;NEUTRAL CHESS TURNED QUEEN;So;0;ON;;;;;N;;;;; +1FA2C;NEUTRAL CHESS TURNED ROOK;So;0;ON;;;;;N;;;;; +1FA2D;NEUTRAL CHESS TURNED BISHOP;So;0;ON;;;;;N;;;;; +1FA2E;NEUTRAL CHESS TURNED KNIGHT;So;0;ON;;;;;N;;;;; +1FA2F;NEUTRAL CHESS TURNED PAWN;So;0;ON;;;;;N;;;;; +1FA30;WHITE CHESS KNIGHT ROTATED TWO HUNDRED TWENTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA31;BLACK CHESS KNIGHT ROTATED TWO HUNDRED TWENTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA32;NEUTRAL CHESS KNIGHT ROTATED TWO HUNDRED TWENTY-FIVE DEGREES;So;0;ON;;;;;N;;;;; +1FA33;WHITE CHESS KING ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA34;WHITE CHESS QUEEN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA35;WHITE CHESS ROOK ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA36;WHITE CHESS BISHOP ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA37;WHITE CHESS KNIGHT ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA38;WHITE CHESS PAWN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA39;BLACK CHESS KING ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3A;BLACK CHESS QUEEN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3B;BLACK CHESS ROOK ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3C;BLACK CHESS BISHOP ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3D;BLACK CHESS KNIGHT ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3E;BLACK CHESS PAWN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA3F;NEUTRAL CHESS KING ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA40;NEUTRAL CHESS QUEEN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA41;NEUTRAL CHESS ROOK ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA42;NEUTRAL CHESS BISHOP ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA43;NEUTRAL CHESS KNIGHT ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA44;NEUTRAL CHESS PAWN ROTATED TWO HUNDRED SEVENTY DEGREES;So;0;ON;;;;;N;;;;; +1FA45;WHITE CHESS KNIGHT ROTATED THREE HUNDRED FIFTEEN DEGREES;So;0;ON;;;;;N;;;;; +1FA46;BLACK CHESS KNIGHT ROTATED THREE HUNDRED FIFTEEN DEGREES;So;0;ON;;;;;N;;;;; +1FA47;NEUTRAL CHESS KNIGHT ROTATED THREE HUNDRED FIFTEEN DEGREES;So;0;ON;;;;;N;;;;; +1FA48;WHITE CHESS EQUIHOPPER;So;0;ON;;;;;N;;;;; +1FA49;BLACK CHESS EQUIHOPPER;So;0;ON;;;;;N;;;;; +1FA4A;NEUTRAL CHESS EQUIHOPPER;So;0;ON;;;;;N;;;;; +1FA4B;WHITE CHESS EQUIHOPPER ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA4C;BLACK CHESS EQUIHOPPER ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA4D;NEUTRAL CHESS EQUIHOPPER ROTATED NINETY DEGREES;So;0;ON;;;;;N;;;;; +1FA4E;WHITE CHESS KNIGHT-QUEEN;So;0;ON;;;;;N;;;;; +1FA4F;WHITE CHESS KNIGHT-ROOK;So;0;ON;;;;;N;;;;; +1FA50;WHITE CHESS KNIGHT-BISHOP;So;0;ON;;;;;N;;;;; +1FA51;BLACK CHESS KNIGHT-QUEEN;So;0;ON;;;;;N;;;;; +1FA52;BLACK CHESS KNIGHT-ROOK;So;0;ON;;;;;N;;;;; +1FA53;BLACK CHESS KNIGHT-BISHOP;So;0;ON;;;;;N;;;;; +1FA54;WHITE CHESS FERZ;So;0;ON;;;;;N;;;;; +1FA55;WHITE CHESS ALFIL;So;0;ON;;;;;N;;;;; +1FA56;BLACK CHESS FERZ;So;0;ON;;;;;N;;;;; +1FA57;BLACK CHESS ALFIL;So;0;ON;;;;;N;;;;; +1FA60;XIANGQI RED GENERAL;So;0;ON;;;;;N;;;;; +1FA61;XIANGQI RED MANDARIN;So;0;ON;;;;;N;;;;; +1FA62;XIANGQI RED ELEPHANT;So;0;ON;;;;;N;;;;; +1FA63;XIANGQI RED HORSE;So;0;ON;;;;;N;;;;; +1FA64;XIANGQI RED CHARIOT;So;0;ON;;;;;N;;;;; +1FA65;XIANGQI RED CANNON;So;0;ON;;;;;N;;;;; +1FA66;XIANGQI RED SOLDIER;So;0;ON;;;;;N;;;;; +1FA67;XIANGQI BLACK GENERAL;So;0;ON;;;;;N;;;;; +1FA68;XIANGQI BLACK MANDARIN;So;0;ON;;;;;N;;;;; +1FA69;XIANGQI BLACK ELEPHANT;So;0;ON;;;;;N;;;;; +1FA6A;XIANGQI BLACK HORSE;So;0;ON;;;;;N;;;;; +1FA6B;XIANGQI BLACK CHARIOT;So;0;ON;;;;;N;;;;; +1FA6C;XIANGQI BLACK CANNON;So;0;ON;;;;;N;;;;; +1FA6D;XIANGQI BLACK SOLDIER;So;0;ON;;;;;N;;;;; +1FA70;BALLET SHOES;So;0;ON;;;;;N;;;;; +1FA71;ONE-PIECE SWIMSUIT;So;0;ON;;;;;N;;;;; +1FA72;BRIEFS;So;0;ON;;;;;N;;;;; +1FA73;SHORTS;So;0;ON;;;;;N;;;;; +1FA74;THONG SANDAL;So;0;ON;;;;;N;;;;; +1FA75;LIGHT BLUE HEART;So;0;ON;;;;;N;;;;; +1FA76;GREY HEART;So;0;ON;;;;;N;;;;; +1FA77;PINK HEART;So;0;ON;;;;;N;;;;; +1FA78;DROP OF BLOOD;So;0;ON;;;;;N;;;;; +1FA79;ADHESIVE BANDAGE;So;0;ON;;;;;N;;;;; +1FA7A;STETHOSCOPE;So;0;ON;;;;;N;;;;; +1FA7B;X-RAY;So;0;ON;;;;;N;;;;; +1FA7C;CRUTCH;So;0;ON;;;;;N;;;;; +1FA80;YO-YO;So;0;ON;;;;;N;;;;; +1FA81;KITE;So;0;ON;;;;;N;;;;; +1FA82;PARACHUTE;So;0;ON;;;;;N;;;;; +1FA83;BOOMERANG;So;0;ON;;;;;N;;;;; +1FA84;MAGIC WAND;So;0;ON;;;;;N;;;;; +1FA85;PINATA;So;0;ON;;;;;N;;;;; +1FA86;NESTING DOLLS;So;0;ON;;;;;N;;;;; +1FA87;MARACAS;So;0;ON;;;;;N;;;;; +1FA88;FLUTE;So;0;ON;;;;;N;;;;; +1FA89;HARP;So;0;ON;;;;;N;;;;; +1FA8A;TROMBONE;So;0;ON;;;;;N;;;;; +1FA8E;TREASURE CHEST;So;0;ON;;;;;N;;;;; +1FA8F;SHOVEL;So;0;ON;;;;;N;;;;; +1FA90;RINGED PLANET;So;0;ON;;;;;N;;;;; +1FA91;CHAIR;So;0;ON;;;;;N;;;;; +1FA92;RAZOR;So;0;ON;;;;;N;;;;; +1FA93;AXE;So;0;ON;;;;;N;;;;; +1FA94;DIYA LAMP;So;0;ON;;;;;N;;;;; +1FA95;BANJO;So;0;ON;;;;;N;;;;; +1FA96;MILITARY HELMET;So;0;ON;;;;;N;;;;; +1FA97;ACCORDION;So;0;ON;;;;;N;;;;; +1FA98;LONG DRUM;So;0;ON;;;;;N;;;;; +1FA99;COIN;So;0;ON;;;;;N;;;;; +1FA9A;CARPENTRY SAW;So;0;ON;;;;;N;;;;; +1FA9B;SCREWDRIVER;So;0;ON;;;;;N;;;;; +1FA9C;LADDER;So;0;ON;;;;;N;;;;; +1FA9D;HOOK;So;0;ON;;;;;N;;;;; +1FA9E;MIRROR;So;0;ON;;;;;N;;;;; +1FA9F;WINDOW;So;0;ON;;;;;N;;;;; +1FAA0;PLUNGER;So;0;ON;;;;;N;;;;; +1FAA1;SEWING NEEDLE;So;0;ON;;;;;N;;;;; +1FAA2;KNOT;So;0;ON;;;;;N;;;;; +1FAA3;BUCKET;So;0;ON;;;;;N;;;;; +1FAA4;MOUSE TRAP;So;0;ON;;;;;N;;;;; +1FAA5;TOOTHBRUSH;So;0;ON;;;;;N;;;;; +1FAA6;HEADSTONE;So;0;ON;;;;;N;;;;; +1FAA7;PLACARD;So;0;ON;;;;;N;;;;; +1FAA8;ROCK;So;0;ON;;;;;N;;;;; +1FAA9;MIRROR BALL;So;0;ON;;;;;N;;;;; +1FAAA;IDENTIFICATION CARD;So;0;ON;;;;;N;;;;; +1FAAB;LOW BATTERY;So;0;ON;;;;;N;;;;; +1FAAC;HAMSA;So;0;ON;;;;;N;;;;; +1FAAD;FOLDING HAND FAN;So;0;ON;;;;;N;;;;; +1FAAE;HAIR PICK;So;0;ON;;;;;N;;;;; +1FAAF;KHANDA;So;0;ON;;;;;N;;;;; +1FAB0;FLY;So;0;ON;;;;;N;;;;; +1FAB1;WORM;So;0;ON;;;;;N;;;;; +1FAB2;BEETLE;So;0;ON;;;;;N;;;;; +1FAB3;COCKROACH;So;0;ON;;;;;N;;;;; +1FAB4;POTTED PLANT;So;0;ON;;;;;N;;;;; +1FAB5;WOOD;So;0;ON;;;;;N;;;;; +1FAB6;FEATHER;So;0;ON;;;;;N;;;;; +1FAB7;LOTUS;So;0;ON;;;;;N;;;;; +1FAB8;CORAL;So;0;ON;;;;;N;;;;; +1FAB9;EMPTY NEST;So;0;ON;;;;;N;;;;; +1FABA;NEST WITH EGGS;So;0;ON;;;;;N;;;;; +1FABB;HYACINTH;So;0;ON;;;;;N;;;;; +1FABC;JELLYFISH;So;0;ON;;;;;N;;;;; +1FABD;WING;So;0;ON;;;;;N;;;;; +1FABE;LEAFLESS TREE;So;0;ON;;;;;N;;;;; +1FABF;GOOSE;So;0;ON;;;;;N;;;;; +1FAC0;ANATOMICAL HEART;So;0;ON;;;;;N;;;;; +1FAC1;LUNGS;So;0;ON;;;;;N;;;;; +1FAC2;PEOPLE HUGGING;So;0;ON;;;;;N;;;;; +1FAC3;PREGNANT MAN;So;0;ON;;;;;N;;;;; +1FAC4;PREGNANT PERSON;So;0;ON;;;;;N;;;;; +1FAC5;PERSON WITH CROWN;So;0;ON;;;;;N;;;;; +1FAC6;FINGERPRINT;So;0;ON;;;;;N;;;;; +1FAC8;HAIRY CREATURE;So;0;ON;;;;;N;;;;; +1FACD;ORCA;So;0;ON;;;;;N;;;;; +1FACE;MOOSE;So;0;ON;;;;;N;;;;; +1FACF;DONKEY;So;0;ON;;;;;N;;;;; +1FAD0;BLUEBERRIES;So;0;ON;;;;;N;;;;; +1FAD1;BELL PEPPER;So;0;ON;;;;;N;;;;; +1FAD2;OLIVE;So;0;ON;;;;;N;;;;; +1FAD3;FLATBREAD;So;0;ON;;;;;N;;;;; +1FAD4;TAMALE;So;0;ON;;;;;N;;;;; +1FAD5;FONDUE;So;0;ON;;;;;N;;;;; +1FAD6;TEAPOT;So;0;ON;;;;;N;;;;; +1FAD7;POURING LIQUID;So;0;ON;;;;;N;;;;; +1FAD8;BEANS;So;0;ON;;;;;N;;;;; +1FAD9;JAR;So;0;ON;;;;;N;;;;; +1FADA;GINGER ROOT;So;0;ON;;;;;N;;;;; +1FADB;PEA POD;So;0;ON;;;;;N;;;;; +1FADC;ROOT VEGETABLE;So;0;ON;;;;;N;;;;; +1FADF;SPLATTER;So;0;ON;;;;;N;;;;; +1FAE0;MELTING FACE;So;0;ON;;;;;N;;;;; +1FAE1;SALUTING FACE;So;0;ON;;;;;N;;;;; +1FAE2;FACE WITH OPEN EYES AND HAND OVER MOUTH;So;0;ON;;;;;N;;;;; +1FAE3;FACE WITH PEEKING EYE;So;0;ON;;;;;N;;;;; +1FAE4;FACE WITH DIAGONAL MOUTH;So;0;ON;;;;;N;;;;; +1FAE5;DOTTED LINE FACE;So;0;ON;;;;;N;;;;; +1FAE6;BITING LIP;So;0;ON;;;;;N;;;;; +1FAE7;BUBBLES;So;0;ON;;;;;N;;;;; +1FAE8;SHAKING FACE;So;0;ON;;;;;N;;;;; +1FAE9;FACE WITH BAGS UNDER EYES;So;0;ON;;;;;N;;;;; +1FAEA;DISTORTED FACE;So;0;ON;;;;;N;;;;; +1FAEF;FIGHT CLOUD;So;0;ON;;;;;N;;;;; +1FAF0;HAND WITH INDEX FINGER AND THUMB CROSSED;So;0;ON;;;;;N;;;;; +1FAF1;RIGHTWARDS HAND;So;0;ON;;;;;N;;;;; +1FAF2;LEFTWARDS HAND;So;0;ON;;;;;N;;;;; +1FAF3;PALM DOWN HAND;So;0;ON;;;;;N;;;;; +1FAF4;PALM UP HAND;So;0;ON;;;;;N;;;;; +1FAF5;INDEX POINTING AT THE VIEWER;So;0;ON;;;;;N;;;;; +1FAF6;HEART HANDS;So;0;ON;;;;;N;;;;; +1FAF7;LEFTWARDS PUSHING HAND;So;0;ON;;;;;N;;;;; +1FAF8;RIGHTWARDS PUSHING HAND;So;0;ON;;;;;N;;;;; +1FB00;BLOCK SEXTANT-1;So;0;ON;;;;;N;;;;; +1FB01;BLOCK SEXTANT-2;So;0;ON;;;;;N;;;;; +1FB02;BLOCK SEXTANT-12;So;0;ON;;;;;N;;;;; +1FB03;BLOCK SEXTANT-3;So;0;ON;;;;;N;;;;; +1FB04;BLOCK SEXTANT-13;So;0;ON;;;;;N;;;;; +1FB05;BLOCK SEXTANT-23;So;0;ON;;;;;N;;;;; +1FB06;BLOCK SEXTANT-123;So;0;ON;;;;;N;;;;; +1FB07;BLOCK SEXTANT-4;So;0;ON;;;;;N;;;;; +1FB08;BLOCK SEXTANT-14;So;0;ON;;;;;N;;;;; +1FB09;BLOCK SEXTANT-24;So;0;ON;;;;;N;;;;; +1FB0A;BLOCK SEXTANT-124;So;0;ON;;;;;N;;;;; +1FB0B;BLOCK SEXTANT-34;So;0;ON;;;;;N;;;;; +1FB0C;BLOCK SEXTANT-134;So;0;ON;;;;;N;;;;; +1FB0D;BLOCK SEXTANT-234;So;0;ON;;;;;N;;;;; +1FB0E;BLOCK SEXTANT-1234;So;0;ON;;;;;N;;;;; +1FB0F;BLOCK SEXTANT-5;So;0;ON;;;;;N;;;;; +1FB10;BLOCK SEXTANT-15;So;0;ON;;;;;N;;;;; +1FB11;BLOCK SEXTANT-25;So;0;ON;;;;;N;;;;; +1FB12;BLOCK SEXTANT-125;So;0;ON;;;;;N;;;;; +1FB13;BLOCK SEXTANT-35;So;0;ON;;;;;N;;;;; +1FB14;BLOCK SEXTANT-235;So;0;ON;;;;;N;;;;; +1FB15;BLOCK SEXTANT-1235;So;0;ON;;;;;N;;;;; +1FB16;BLOCK SEXTANT-45;So;0;ON;;;;;N;;;;; +1FB17;BLOCK SEXTANT-145;So;0;ON;;;;;N;;;;; +1FB18;BLOCK SEXTANT-245;So;0;ON;;;;;N;;;;; +1FB19;BLOCK SEXTANT-1245;So;0;ON;;;;;N;;;;; +1FB1A;BLOCK SEXTANT-345;So;0;ON;;;;;N;;;;; +1FB1B;BLOCK SEXTANT-1345;So;0;ON;;;;;N;;;;; +1FB1C;BLOCK SEXTANT-2345;So;0;ON;;;;;N;;;;; +1FB1D;BLOCK SEXTANT-12345;So;0;ON;;;;;N;;;;; +1FB1E;BLOCK SEXTANT-6;So;0;ON;;;;;N;;;;; +1FB1F;BLOCK SEXTANT-16;So;0;ON;;;;;N;;;;; +1FB20;BLOCK SEXTANT-26;So;0;ON;;;;;N;;;;; +1FB21;BLOCK SEXTANT-126;So;0;ON;;;;;N;;;;; +1FB22;BLOCK SEXTANT-36;So;0;ON;;;;;N;;;;; +1FB23;BLOCK SEXTANT-136;So;0;ON;;;;;N;;;;; +1FB24;BLOCK SEXTANT-236;So;0;ON;;;;;N;;;;; +1FB25;BLOCK SEXTANT-1236;So;0;ON;;;;;N;;;;; +1FB26;BLOCK SEXTANT-46;So;0;ON;;;;;N;;;;; +1FB27;BLOCK SEXTANT-146;So;0;ON;;;;;N;;;;; +1FB28;BLOCK SEXTANT-1246;So;0;ON;;;;;N;;;;; +1FB29;BLOCK SEXTANT-346;So;0;ON;;;;;N;;;;; +1FB2A;BLOCK SEXTANT-1346;So;0;ON;;;;;N;;;;; +1FB2B;BLOCK SEXTANT-2346;So;0;ON;;;;;N;;;;; +1FB2C;BLOCK SEXTANT-12346;So;0;ON;;;;;N;;;;; +1FB2D;BLOCK SEXTANT-56;So;0;ON;;;;;N;;;;; +1FB2E;BLOCK SEXTANT-156;So;0;ON;;;;;N;;;;; +1FB2F;BLOCK SEXTANT-256;So;0;ON;;;;;N;;;;; +1FB30;BLOCK SEXTANT-1256;So;0;ON;;;;;N;;;;; +1FB31;BLOCK SEXTANT-356;So;0;ON;;;;;N;;;;; +1FB32;BLOCK SEXTANT-1356;So;0;ON;;;;;N;;;;; +1FB33;BLOCK SEXTANT-2356;So;0;ON;;;;;N;;;;; +1FB34;BLOCK SEXTANT-12356;So;0;ON;;;;;N;;;;; +1FB35;BLOCK SEXTANT-456;So;0;ON;;;;;N;;;;; +1FB36;BLOCK SEXTANT-1456;So;0;ON;;;;;N;;;;; +1FB37;BLOCK SEXTANT-2456;So;0;ON;;;;;N;;;;; +1FB38;BLOCK SEXTANT-12456;So;0;ON;;;;;N;;;;; +1FB39;BLOCK SEXTANT-3456;So;0;ON;;;;;N;;;;; +1FB3A;BLOCK SEXTANT-13456;So;0;ON;;;;;N;;;;; +1FB3B;BLOCK SEXTANT-23456;So;0;ON;;;;;N;;;;; +1FB3C;LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB3D;LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB3E;LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB3F;LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB40;LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB41;LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB42;LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB43;LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB44;LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB45;LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB46;LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB47;LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB48;LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB49;LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB4A;LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB4B;LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB4C;LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB4D;LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB4E;LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB4F;LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB50;LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB51;LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB52;UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB53;UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB54;UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB55;UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB56;UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FB57;UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB58;UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB59;UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB5A;UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB5B;UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE;So;0;ON;;;;;N;;;;; +1FB5C;UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB5D;UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB5E;UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB5F;UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB60;UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB61;UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FB62;UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB63;UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB64;UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB65;UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB66;UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FB67;UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FB68;UPPER AND RIGHT AND LOWER TRIANGULAR THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB69;LEFT AND LOWER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB6A;UPPER AND LEFT AND LOWER TRIANGULAR THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB6B;LEFT AND UPPER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB6C;LEFT TRIANGULAR ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB6D;UPPER TRIANGULAR ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB6E;RIGHT TRIANGULAR ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB6F;LOWER TRIANGULAR ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB70;VERTICAL ONE EIGHTH BLOCK-2;So;0;ON;;;;;N;;;;; +1FB71;VERTICAL ONE EIGHTH BLOCK-3;So;0;ON;;;;;N;;;;; +1FB72;VERTICAL ONE EIGHTH BLOCK-4;So;0;ON;;;;;N;;;;; +1FB73;VERTICAL ONE EIGHTH BLOCK-5;So;0;ON;;;;;N;;;;; +1FB74;VERTICAL ONE EIGHTH BLOCK-6;So;0;ON;;;;;N;;;;; +1FB75;VERTICAL ONE EIGHTH BLOCK-7;So;0;ON;;;;;N;;;;; +1FB76;HORIZONTAL ONE EIGHTH BLOCK-2;So;0;ON;;;;;N;;;;; +1FB77;HORIZONTAL ONE EIGHTH BLOCK-3;So;0;ON;;;;;N;;;;; +1FB78;HORIZONTAL ONE EIGHTH BLOCK-4;So;0;ON;;;;;N;;;;; +1FB79;HORIZONTAL ONE EIGHTH BLOCK-5;So;0;ON;;;;;N;;;;; +1FB7A;HORIZONTAL ONE EIGHTH BLOCK-6;So;0;ON;;;;;N;;;;; +1FB7B;HORIZONTAL ONE EIGHTH BLOCK-7;So;0;ON;;;;;N;;;;; +1FB7C;LEFT AND LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FB7D;LEFT AND UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FB7E;RIGHT AND UPPER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FB7F;RIGHT AND LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FB80;UPPER AND LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FB81;HORIZONTAL ONE EIGHTH BLOCK-1358;So;0;ON;;;;;N;;;;; +1FB82;UPPER ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB83;UPPER THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB84;UPPER FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB85;UPPER THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB86;UPPER SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB87;RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FB88;RIGHT THREE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB89;RIGHT FIVE EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB8A;RIGHT THREE QUARTERS BLOCK;So;0;ON;;;;;N;;;;; +1FB8B;RIGHT SEVEN EIGHTHS BLOCK;So;0;ON;;;;;N;;;;; +1FB8C;LEFT HALF MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB8D;RIGHT HALF MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB8E;UPPER HALF MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB8F;LOWER HALF MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB90;INVERSE MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB91;UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB92;UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK;So;0;ON;;;;;N;;;;; +1FB94;LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK;So;0;ON;;;;;N;;;;; +1FB95;CHECKER BOARD FILL;So;0;ON;;;;;N;;;;; +1FB96;INVERSE CHECKER BOARD FILL;So;0;ON;;;;;N;;;;; +1FB97;HEAVY HORIZONTAL FILL;So;0;ON;;;;;N;;;;; +1FB98;UPPER LEFT TO LOWER RIGHT FILL;So;0;ON;;;;;N;;;;; +1FB99;UPPER RIGHT TO LOWER LEFT FILL;So;0;ON;;;;;N;;;;; +1FB9A;UPPER AND LOWER TRIANGULAR HALF BLOCK;So;0;ON;;;;;N;;;;; +1FB9B;LEFT AND RIGHT TRIANGULAR HALF BLOCK;So;0;ON;;;;;N;;;;; +1FB9C;UPPER LEFT TRIANGULAR MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB9D;UPPER RIGHT TRIANGULAR MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB9E;LOWER RIGHT TRIANGULAR MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FB9F;LOWER LEFT TRIANGULAR MEDIUM SHADE;So;0;ON;;;;;N;;;;; +1FBA0;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE LEFT;So;0;ON;;;;;N;;;;; +1FBA1;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FBA2;BOX DRAWINGS LIGHT DIAGONAL MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBA3;BOX DRAWINGS LIGHT DIAGONAL MIDDLE RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBA4;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBA5;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBA6;BOX DRAWINGS LIGHT DIAGONAL MIDDLE LEFT TO LOWER CENTRE TO MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FBA7;BOX DRAWINGS LIGHT DIAGONAL MIDDLE LEFT TO UPPER CENTRE TO MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FBA8;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE LEFT AND MIDDLE RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBA9;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT AND MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBAA;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT TO LOWER CENTRE TO MIDDLE LEFT;So;0;ON;;;;;N;;;;; +1FBAB;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE LEFT TO LOWER CENTRE TO MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FBAC;BOX DRAWINGS LIGHT DIAGONAL MIDDLE LEFT TO UPPER CENTRE TO MIDDLE RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBAD;BOX DRAWINGS LIGHT DIAGONAL MIDDLE RIGHT TO UPPER CENTRE TO MIDDLE LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBAE;BOX DRAWINGS LIGHT DIAGONAL DIAMOND;So;0;ON;;;;;N;;;;; +1FBAF;BOX DRAWINGS LIGHT HORIZONTAL WITH VERTICAL STROKE;So;0;ON;;;;;N;;;;; +1FBB0;ARROWHEAD-SHAPED POINTER;So;0;ON;;;;;N;;;;; +1FBB1;INVERSE CHECK MARK;So;0;ON;;;;;N;;;;; +1FBB2;LEFT HALF RUNNING MAN;So;0;ON;;;;;N;;;;; +1FBB3;RIGHT HALF RUNNING MAN;So;0;ON;;;;;N;;;;; +1FBB4;INVERSE DOWNWARDS ARROW WITH TIP LEFTWARDS;So;0;ON;;;;;N;;;;; +1FBB5;LEFTWARDS ARROW AND UPPER AND LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FBB6;RIGHTWARDS ARROW AND UPPER AND LOWER ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FBB7;DOWNWARDS ARROW AND RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FBB8;UPWARDS ARROW AND RIGHT ONE EIGHTH BLOCK;So;0;ON;;;;;N;;;;; +1FBB9;LEFT HALF FOLDER;So;0;ON;;;;;N;;;;; +1FBBA;RIGHT HALF FOLDER;So;0;ON;;;;;N;;;;; +1FBBB;VOIDED GREEK CROSS;So;0;ON;;;;;N;;;;; +1FBBC;RIGHT OPEN SQUARED DOT;So;0;ON;;;;;N;;;;; +1FBBD;NEGATIVE DIAGONAL CROSS;So;0;ON;;;;;N;;;;; +1FBBE;NEGATIVE DIAGONAL MIDDLE RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBBF;NEGATIVE DIAGONAL DIAMOND;So;0;ON;;;;;N;;;;; +1FBC0;WHITE HEAVY SALTIRE WITH ROUNDED CORNERS;So;0;ON;;;;;N;;;;; +1FBC1;LEFT THIRD WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1FBC2;MIDDLE THIRD WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1FBC3;RIGHT THIRD WHITE RIGHT POINTING INDEX;So;0;ON;;;;;N;;;;; +1FBC4;NEGATIVE SQUARED QUESTION MARK;So;0;ON;;;;;N;;;;; +1FBC5;STICK FIGURE;So;0;ON;;;;;N;;;;; +1FBC6;STICK FIGURE WITH ARMS RAISED;So;0;ON;;;;;N;;;;; +1FBC7;STICK FIGURE LEANING LEFT;So;0;ON;;;;;N;;;;; +1FBC8;STICK FIGURE LEANING RIGHT;So;0;ON;;;;;N;;;;; +1FBC9;STICK FIGURE WITH DRESS;So;0;ON;;;;;N;;;;; +1FBCA;WHITE UP-POINTING CHEVRON;So;0;ON;;;;;N;;;;; +1FBCB;WHITE CROSS MARK;So;0;ON;;;;;N;;;;; +1FBCC;RAISED SMALL LEFT SQUARE BRACKET;So;0;ON;;;;;N;;;;; +1FBCD;BLACK SMALL UP-POINTING CHEVRON;So;0;ON;;;;;N;;;;; +1FBCE;LEFT TWO THIRDS BLOCK;So;0;ON;;;;;N;;;;; +1FBCF;LEFT ONE THIRD BLOCK;So;0;ON;;;;;N;;;;; +1FBD0;BOX DRAWINGS LIGHT DIAGONAL MIDDLE RIGHT TO LOWER LEFT;So;0;ON;;;;;N;;;;; +1FBD1;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO MIDDLE LEFT;So;0;ON;;;;;N;;;;; +1FBD2;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO MIDDLE RIGHT;So;0;ON;;;;;N;;;;; +1FBD3;BOX DRAWINGS LIGHT DIAGONAL MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBD4;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBD5;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBD6;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER CENTRE;So;0;ON;;;;;N;;;;; +1FBD7;BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO LOWER LEFT;So;0;ON;;;;;N;;;;; +1FBD8;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO MIDDLE CENTRE TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FBD9;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO MIDDLE CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBDA;BOX DRAWINGS LIGHT DIAGONAL LOWER LEFT TO MIDDLE CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBDB;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO MIDDLE CENTRE TO LOWER LEFT;So;0;ON;;;;;N;;;;; +1FBDC;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER CENTRE TO UPPER RIGHT;So;0;ON;;;;;N;;;;; +1FBDD;BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO MIDDLE LEFT TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBDE;BOX DRAWINGS LIGHT DIAGONAL LOWER LEFT TO UPPER CENTRE TO LOWER RIGHT;So;0;ON;;;;;N;;;;; +1FBDF;BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO MIDDLE RIGHT TO LOWER LEFT;So;0;ON;;;;;N;;;;; +1FBE0;TOP JUSTIFIED LOWER HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1FBE1;RIGHT JUSTIFIED LEFT HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1FBE2;BOTTOM JUSTIFIED UPPER HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1FBE3;LEFT JUSTIFIED RIGHT HALF WHITE CIRCLE;So;0;ON;;;;;N;;;;; +1FBE4;UPPER CENTRE ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FBE5;LOWER CENTRE ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FBE6;MIDDLE LEFT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FBE7;MIDDLE RIGHT ONE QUARTER BLOCK;So;0;ON;;;;;N;;;;; +1FBE8;TOP JUSTIFIED LOWER HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBE9;RIGHT JUSTIFIED LEFT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBEA;BOTTOM JUSTIFIED UPPER HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBEB;LEFT JUSTIFIED RIGHT HALF BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBEC;TOP RIGHT JUSTIFIED LOWER LEFT QUARTER BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBED;BOTTOM LEFT JUSTIFIED UPPER RIGHT QUARTER BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBEE;BOTTOM RIGHT JUSTIFIED UPPER LEFT QUARTER BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBEF;TOP LEFT JUSTIFIED LOWER RIGHT QUARTER BLACK CIRCLE;So;0;ON;;;;;N;;;;; +1FBF0;SEGMENTED DIGIT ZERO;Nd;0;EN; 0030;0;0;0;N;;;;; +1FBF1;SEGMENTED DIGIT ONE;Nd;0;EN; 0031;1;1;1;N;;;;; +1FBF2;SEGMENTED DIGIT TWO;Nd;0;EN; 0032;2;2;2;N;;;;; +1FBF3;SEGMENTED DIGIT THREE;Nd;0;EN; 0033;3;3;3;N;;;;; +1FBF4;SEGMENTED DIGIT FOUR;Nd;0;EN; 0034;4;4;4;N;;;;; +1FBF5;SEGMENTED DIGIT FIVE;Nd;0;EN; 0035;5;5;5;N;;;;; +1FBF6;SEGMENTED DIGIT SIX;Nd;0;EN; 0036;6;6;6;N;;;;; +1FBF7;SEGMENTED DIGIT SEVEN;Nd;0;EN; 0037;7;7;7;N;;;;; +1FBF8;SEGMENTED DIGIT EIGHT;Nd;0;EN; 0038;8;8;8;N;;;;; +1FBF9;SEGMENTED DIGIT NINE;Nd;0;EN; 0039;9;9;9;N;;;;; +1FBFA;ALARM BELL SYMBOL;So;0;ON;;;;;N;;;;; +20000;;Lo;0;L;;;;;N;;;;; +2A6DF;;Lo;0;L;;;;;N;;;;; +2A700;;Lo;0;L;;;;;N;;;;; +2B73F;;Lo;0;L;;;;;N;;;;; +2B740;;Lo;0;L;;;;;N;;;;; +2B81D;;Lo;0;L;;;;;N;;;;; +2B820;;Lo;0;L;;;;;N;;;;; +2CEAD;;Lo;0;L;;;;;N;;;;; +2CEB0;;Lo;0;L;;;;;N;;;;; +2EBE0;;Lo;0;L;;;;;N;;;;; +2EBF0;;Lo;0;L;;;;;N;;;;; +2EE5D;;Lo;0;L;;;;;N;;;;; +2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; +2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; +2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; +2F803;CJK COMPATIBILITY IDEOGRAPH-2F803;Lo;0;L;20122;;;;N;;;;; +2F804;CJK COMPATIBILITY IDEOGRAPH-2F804;Lo;0;L;4F60;;;;N;;;;; +2F805;CJK COMPATIBILITY IDEOGRAPH-2F805;Lo;0;L;4FAE;;;;N;;;;; +2F806;CJK COMPATIBILITY IDEOGRAPH-2F806;Lo;0;L;4FBB;;;;N;;;;; +2F807;CJK COMPATIBILITY IDEOGRAPH-2F807;Lo;0;L;5002;;;;N;;;;; +2F808;CJK COMPATIBILITY IDEOGRAPH-2F808;Lo;0;L;507A;;;;N;;;;; +2F809;CJK COMPATIBILITY IDEOGRAPH-2F809;Lo;0;L;5099;;;;N;;;;; +2F80A;CJK COMPATIBILITY IDEOGRAPH-2F80A;Lo;0;L;50E7;;;;N;;;;; +2F80B;CJK COMPATIBILITY IDEOGRAPH-2F80B;Lo;0;L;50CF;;;;N;;;;; +2F80C;CJK COMPATIBILITY IDEOGRAPH-2F80C;Lo;0;L;349E;;;;N;;;;; +2F80D;CJK COMPATIBILITY IDEOGRAPH-2F80D;Lo;0;L;2063A;;;;N;;;;; +2F80E;CJK COMPATIBILITY IDEOGRAPH-2F80E;Lo;0;L;514D;;;;N;;;;; +2F80F;CJK COMPATIBILITY IDEOGRAPH-2F80F;Lo;0;L;5154;;;;N;;;;; +2F810;CJK COMPATIBILITY IDEOGRAPH-2F810;Lo;0;L;5164;;;;N;;;;; +2F811;CJK COMPATIBILITY IDEOGRAPH-2F811;Lo;0;L;5177;;;;N;;;;; +2F812;CJK COMPATIBILITY IDEOGRAPH-2F812;Lo;0;L;2051C;;;;N;;;;; +2F813;CJK COMPATIBILITY IDEOGRAPH-2F813;Lo;0;L;34B9;;;;N;;;;; +2F814;CJK COMPATIBILITY IDEOGRAPH-2F814;Lo;0;L;5167;;;;N;;;;; +2F815;CJK COMPATIBILITY IDEOGRAPH-2F815;Lo;0;L;518D;;;;N;;;;; +2F816;CJK COMPATIBILITY IDEOGRAPH-2F816;Lo;0;L;2054B;;;;N;;;;; +2F817;CJK COMPATIBILITY IDEOGRAPH-2F817;Lo;0;L;5197;;;;N;;;;; +2F818;CJK COMPATIBILITY IDEOGRAPH-2F818;Lo;0;L;51A4;;;;N;;;;; +2F819;CJK COMPATIBILITY IDEOGRAPH-2F819;Lo;0;L;4ECC;;;;N;;;;; +2F81A;CJK COMPATIBILITY IDEOGRAPH-2F81A;Lo;0;L;51AC;;;;N;;;;; +2F81B;CJK COMPATIBILITY IDEOGRAPH-2F81B;Lo;0;L;51B5;;;;N;;;;; +2F81C;CJK COMPATIBILITY IDEOGRAPH-2F81C;Lo;0;L;291DF;;;;N;;;;; +2F81D;CJK COMPATIBILITY IDEOGRAPH-2F81D;Lo;0;L;51F5;;;;N;;;;; +2F81E;CJK COMPATIBILITY IDEOGRAPH-2F81E;Lo;0;L;5203;;;;N;;;;; +2F81F;CJK COMPATIBILITY IDEOGRAPH-2F81F;Lo;0;L;34DF;;;;N;;;;; +2F820;CJK COMPATIBILITY IDEOGRAPH-2F820;Lo;0;L;523B;;;;N;;;;; +2F821;CJK COMPATIBILITY IDEOGRAPH-2F821;Lo;0;L;5246;;;;N;;;;; +2F822;CJK COMPATIBILITY IDEOGRAPH-2F822;Lo;0;L;5272;;;;N;;;;; +2F823;CJK COMPATIBILITY IDEOGRAPH-2F823;Lo;0;L;5277;;;;N;;;;; +2F824;CJK COMPATIBILITY IDEOGRAPH-2F824;Lo;0;L;3515;;;;N;;;;; +2F825;CJK COMPATIBILITY IDEOGRAPH-2F825;Lo;0;L;52C7;;;;N;;;;; +2F826;CJK COMPATIBILITY IDEOGRAPH-2F826;Lo;0;L;52C9;;;;N;;;;; +2F827;CJK COMPATIBILITY IDEOGRAPH-2F827;Lo;0;L;52E4;;;;N;;;;; +2F828;CJK COMPATIBILITY IDEOGRAPH-2F828;Lo;0;L;52FA;;;;N;;;;; +2F829;CJK COMPATIBILITY IDEOGRAPH-2F829;Lo;0;L;5305;;;;N;;;;; +2F82A;CJK COMPATIBILITY IDEOGRAPH-2F82A;Lo;0;L;5306;;;;N;;;;; +2F82B;CJK COMPATIBILITY IDEOGRAPH-2F82B;Lo;0;L;5317;;;;N;;;;; +2F82C;CJK COMPATIBILITY IDEOGRAPH-2F82C;Lo;0;L;5349;;;;N;;;;; +2F82D;CJK COMPATIBILITY IDEOGRAPH-2F82D;Lo;0;L;5351;;;;N;;;;; +2F82E;CJK COMPATIBILITY IDEOGRAPH-2F82E;Lo;0;L;535A;;;;N;;;;; +2F82F;CJK COMPATIBILITY IDEOGRAPH-2F82F;Lo;0;L;5373;;;;N;;;;; +2F830;CJK COMPATIBILITY IDEOGRAPH-2F830;Lo;0;L;537D;;;;N;;;;; +2F831;CJK COMPATIBILITY IDEOGRAPH-2F831;Lo;0;L;537F;;;;N;;;;; +2F832;CJK COMPATIBILITY IDEOGRAPH-2F832;Lo;0;L;537F;;;;N;;;;; +2F833;CJK COMPATIBILITY IDEOGRAPH-2F833;Lo;0;L;537F;;;;N;;;;; +2F834;CJK COMPATIBILITY IDEOGRAPH-2F834;Lo;0;L;20A2C;;;;N;;;;; +2F835;CJK COMPATIBILITY IDEOGRAPH-2F835;Lo;0;L;7070;;;;N;;;;; +2F836;CJK COMPATIBILITY IDEOGRAPH-2F836;Lo;0;L;53CA;;;;N;;;;; +2F837;CJK COMPATIBILITY IDEOGRAPH-2F837;Lo;0;L;53DF;;;;N;;;;; +2F838;CJK COMPATIBILITY IDEOGRAPH-2F838;Lo;0;L;20B63;;;;N;;;;; +2F839;CJK COMPATIBILITY IDEOGRAPH-2F839;Lo;0;L;53EB;;;;N;;;;; +2F83A;CJK COMPATIBILITY IDEOGRAPH-2F83A;Lo;0;L;53F1;;;;N;;;;; +2F83B;CJK COMPATIBILITY IDEOGRAPH-2F83B;Lo;0;L;5406;;;;N;;;;; +2F83C;CJK COMPATIBILITY IDEOGRAPH-2F83C;Lo;0;L;549E;;;;N;;;;; +2F83D;CJK COMPATIBILITY IDEOGRAPH-2F83D;Lo;0;L;5438;;;;N;;;;; +2F83E;CJK COMPATIBILITY IDEOGRAPH-2F83E;Lo;0;L;5448;;;;N;;;;; +2F83F;CJK COMPATIBILITY IDEOGRAPH-2F83F;Lo;0;L;5468;;;;N;;;;; +2F840;CJK COMPATIBILITY IDEOGRAPH-2F840;Lo;0;L;54A2;;;;N;;;;; +2F841;CJK COMPATIBILITY IDEOGRAPH-2F841;Lo;0;L;54F6;;;;N;;;;; +2F842;CJK COMPATIBILITY IDEOGRAPH-2F842;Lo;0;L;5510;;;;N;;;;; +2F843;CJK COMPATIBILITY IDEOGRAPH-2F843;Lo;0;L;5553;;;;N;;;;; +2F844;CJK COMPATIBILITY IDEOGRAPH-2F844;Lo;0;L;5563;;;;N;;;;; +2F845;CJK COMPATIBILITY IDEOGRAPH-2F845;Lo;0;L;5584;;;;N;;;;; +2F846;CJK COMPATIBILITY IDEOGRAPH-2F846;Lo;0;L;5584;;;;N;;;;; +2F847;CJK COMPATIBILITY IDEOGRAPH-2F847;Lo;0;L;5599;;;;N;;;;; +2F848;CJK COMPATIBILITY IDEOGRAPH-2F848;Lo;0;L;55AB;;;;N;;;;; +2F849;CJK COMPATIBILITY IDEOGRAPH-2F849;Lo;0;L;55B3;;;;N;;;;; +2F84A;CJK COMPATIBILITY IDEOGRAPH-2F84A;Lo;0;L;55C2;;;;N;;;;; +2F84B;CJK COMPATIBILITY IDEOGRAPH-2F84B;Lo;0;L;5716;;;;N;;;;; +2F84C;CJK COMPATIBILITY IDEOGRAPH-2F84C;Lo;0;L;5606;;;;N;;;;; +2F84D;CJK COMPATIBILITY IDEOGRAPH-2F84D;Lo;0;L;5717;;;;N;;;;; +2F84E;CJK COMPATIBILITY IDEOGRAPH-2F84E;Lo;0;L;5651;;;;N;;;;; +2F84F;CJK COMPATIBILITY IDEOGRAPH-2F84F;Lo;0;L;5674;;;;N;;;;; +2F850;CJK COMPATIBILITY IDEOGRAPH-2F850;Lo;0;L;5207;;;;N;;;;; +2F851;CJK COMPATIBILITY IDEOGRAPH-2F851;Lo;0;L;58EE;;;;N;;;;; +2F852;CJK COMPATIBILITY IDEOGRAPH-2F852;Lo;0;L;57CE;;;;N;;;;; +2F853;CJK COMPATIBILITY IDEOGRAPH-2F853;Lo;0;L;57F4;;;;N;;;;; +2F854;CJK COMPATIBILITY IDEOGRAPH-2F854;Lo;0;L;580D;;;;N;;;;; +2F855;CJK COMPATIBILITY IDEOGRAPH-2F855;Lo;0;L;578B;;;;N;;;;; +2F856;CJK COMPATIBILITY IDEOGRAPH-2F856;Lo;0;L;5832;;;;N;;;;; +2F857;CJK COMPATIBILITY IDEOGRAPH-2F857;Lo;0;L;5831;;;;N;;;;; +2F858;CJK COMPATIBILITY IDEOGRAPH-2F858;Lo;0;L;58AC;;;;N;;;;; +2F859;CJK COMPATIBILITY IDEOGRAPH-2F859;Lo;0;L;214E4;;;;N;;;;; +2F85A;CJK COMPATIBILITY IDEOGRAPH-2F85A;Lo;0;L;58F2;;;;N;;;;; +2F85B;CJK COMPATIBILITY IDEOGRAPH-2F85B;Lo;0;L;58F7;;;;N;;;;; +2F85C;CJK COMPATIBILITY IDEOGRAPH-2F85C;Lo;0;L;5906;;;;N;;;;; +2F85D;CJK COMPATIBILITY IDEOGRAPH-2F85D;Lo;0;L;591A;;;;N;;;;; +2F85E;CJK COMPATIBILITY IDEOGRAPH-2F85E;Lo;0;L;5922;;;;N;;;;; +2F85F;CJK COMPATIBILITY IDEOGRAPH-2F85F;Lo;0;L;5962;;;;N;;;;; +2F860;CJK COMPATIBILITY IDEOGRAPH-2F860;Lo;0;L;216A8;;;;N;;;;; +2F861;CJK COMPATIBILITY IDEOGRAPH-2F861;Lo;0;L;216EA;;;;N;;;;; +2F862;CJK COMPATIBILITY IDEOGRAPH-2F862;Lo;0;L;59EC;;;;N;;;;; +2F863;CJK COMPATIBILITY IDEOGRAPH-2F863;Lo;0;L;5A1B;;;;N;;;;; +2F864;CJK COMPATIBILITY IDEOGRAPH-2F864;Lo;0;L;5A27;;;;N;;;;; +2F865;CJK COMPATIBILITY IDEOGRAPH-2F865;Lo;0;L;59D8;;;;N;;;;; +2F866;CJK COMPATIBILITY IDEOGRAPH-2F866;Lo;0;L;5A66;;;;N;;;;; +2F867;CJK COMPATIBILITY IDEOGRAPH-2F867;Lo;0;L;36EE;;;;N;;;;; +2F868;CJK COMPATIBILITY IDEOGRAPH-2F868;Lo;0;L;36FC;;;;N;;;;; +2F869;CJK COMPATIBILITY IDEOGRAPH-2F869;Lo;0;L;5B08;;;;N;;;;; +2F86A;CJK COMPATIBILITY IDEOGRAPH-2F86A;Lo;0;L;5B3E;;;;N;;;;; +2F86B;CJK COMPATIBILITY IDEOGRAPH-2F86B;Lo;0;L;5B3E;;;;N;;;;; +2F86C;CJK COMPATIBILITY IDEOGRAPH-2F86C;Lo;0;L;219C8;;;;N;;;;; +2F86D;CJK COMPATIBILITY IDEOGRAPH-2F86D;Lo;0;L;5BC3;;;;N;;;;; +2F86E;CJK COMPATIBILITY IDEOGRAPH-2F86E;Lo;0;L;5BD8;;;;N;;;;; +2F86F;CJK COMPATIBILITY IDEOGRAPH-2F86F;Lo;0;L;5BE7;;;;N;;;;; +2F870;CJK COMPATIBILITY IDEOGRAPH-2F870;Lo;0;L;5BF3;;;;N;;;;; +2F871;CJK COMPATIBILITY IDEOGRAPH-2F871;Lo;0;L;21B18;;;;N;;;;; +2F872;CJK COMPATIBILITY IDEOGRAPH-2F872;Lo;0;L;5BFF;;;;N;;;;; +2F873;CJK COMPATIBILITY IDEOGRAPH-2F873;Lo;0;L;5C06;;;;N;;;;; +2F874;CJK COMPATIBILITY IDEOGRAPH-2F874;Lo;0;L;5F53;;;;N;;;;; +2F875;CJK COMPATIBILITY IDEOGRAPH-2F875;Lo;0;L;5C22;;;;N;;;;; +2F876;CJK COMPATIBILITY IDEOGRAPH-2F876;Lo;0;L;3781;;;;N;;;;; +2F877;CJK COMPATIBILITY IDEOGRAPH-2F877;Lo;0;L;5C60;;;;N;;;;; +2F878;CJK COMPATIBILITY IDEOGRAPH-2F878;Lo;0;L;5C6E;;;;N;;;;; +2F879;CJK COMPATIBILITY IDEOGRAPH-2F879;Lo;0;L;5CC0;;;;N;;;;; +2F87A;CJK COMPATIBILITY IDEOGRAPH-2F87A;Lo;0;L;5C8D;;;;N;;;;; +2F87B;CJK COMPATIBILITY IDEOGRAPH-2F87B;Lo;0;L;21DE4;;;;N;;;;; +2F87C;CJK COMPATIBILITY IDEOGRAPH-2F87C;Lo;0;L;5D43;;;;N;;;;; +2F87D;CJK COMPATIBILITY IDEOGRAPH-2F87D;Lo;0;L;21DE6;;;;N;;;;; +2F87E;CJK COMPATIBILITY IDEOGRAPH-2F87E;Lo;0;L;5D6E;;;;N;;;;; +2F87F;CJK COMPATIBILITY IDEOGRAPH-2F87F;Lo;0;L;5D6B;;;;N;;;;; +2F880;CJK COMPATIBILITY IDEOGRAPH-2F880;Lo;0;L;5D7C;;;;N;;;;; +2F881;CJK COMPATIBILITY IDEOGRAPH-2F881;Lo;0;L;5DE1;;;;N;;;;; +2F882;CJK COMPATIBILITY IDEOGRAPH-2F882;Lo;0;L;5DE2;;;;N;;;;; +2F883;CJK COMPATIBILITY IDEOGRAPH-2F883;Lo;0;L;382F;;;;N;;;;; +2F884;CJK COMPATIBILITY IDEOGRAPH-2F884;Lo;0;L;5DFD;;;;N;;;;; +2F885;CJK COMPATIBILITY IDEOGRAPH-2F885;Lo;0;L;5E28;;;;N;;;;; +2F886;CJK COMPATIBILITY IDEOGRAPH-2F886;Lo;0;L;5E3D;;;;N;;;;; +2F887;CJK COMPATIBILITY IDEOGRAPH-2F887;Lo;0;L;5E69;;;;N;;;;; +2F888;CJK COMPATIBILITY IDEOGRAPH-2F888;Lo;0;L;3862;;;;N;;;;; +2F889;CJK COMPATIBILITY IDEOGRAPH-2F889;Lo;0;L;22183;;;;N;;;;; +2F88A;CJK COMPATIBILITY IDEOGRAPH-2F88A;Lo;0;L;387C;;;;N;;;;; +2F88B;CJK COMPATIBILITY IDEOGRAPH-2F88B;Lo;0;L;5EB0;;;;N;;;;; +2F88C;CJK COMPATIBILITY IDEOGRAPH-2F88C;Lo;0;L;5EB3;;;;N;;;;; +2F88D;CJK COMPATIBILITY IDEOGRAPH-2F88D;Lo;0;L;5EB6;;;;N;;;;; +2F88E;CJK COMPATIBILITY IDEOGRAPH-2F88E;Lo;0;L;5ECA;;;;N;;;;; +2F88F;CJK COMPATIBILITY IDEOGRAPH-2F88F;Lo;0;L;2A392;;;;N;;;;; +2F890;CJK COMPATIBILITY IDEOGRAPH-2F890;Lo;0;L;5EFE;;;9;N;;;;; +2F891;CJK COMPATIBILITY IDEOGRAPH-2F891;Lo;0;L;22331;;;;N;;;;; +2F892;CJK COMPATIBILITY IDEOGRAPH-2F892;Lo;0;L;22331;;;;N;;;;; +2F893;CJK COMPATIBILITY IDEOGRAPH-2F893;Lo;0;L;8201;;;;N;;;;; +2F894;CJK COMPATIBILITY IDEOGRAPH-2F894;Lo;0;L;5F22;;;;N;;;;; +2F895;CJK COMPATIBILITY IDEOGRAPH-2F895;Lo;0;L;5F22;;;;N;;;;; +2F896;CJK COMPATIBILITY IDEOGRAPH-2F896;Lo;0;L;38C7;;;;N;;;;; +2F897;CJK COMPATIBILITY IDEOGRAPH-2F897;Lo;0;L;232B8;;;;N;;;;; +2F898;CJK COMPATIBILITY IDEOGRAPH-2F898;Lo;0;L;261DA;;;;N;;;;; +2F899;CJK COMPATIBILITY IDEOGRAPH-2F899;Lo;0;L;5F62;;;;N;;;;; +2F89A;CJK COMPATIBILITY IDEOGRAPH-2F89A;Lo;0;L;5F6B;;;;N;;;;; +2F89B;CJK COMPATIBILITY IDEOGRAPH-2F89B;Lo;0;L;38E3;;;;N;;;;; +2F89C;CJK COMPATIBILITY IDEOGRAPH-2F89C;Lo;0;L;5F9A;;;;N;;;;; +2F89D;CJK COMPATIBILITY IDEOGRAPH-2F89D;Lo;0;L;5FCD;;;;N;;;;; +2F89E;CJK COMPATIBILITY IDEOGRAPH-2F89E;Lo;0;L;5FD7;;;;N;;;;; +2F89F;CJK COMPATIBILITY IDEOGRAPH-2F89F;Lo;0;L;5FF9;;;;N;;;;; +2F8A0;CJK COMPATIBILITY IDEOGRAPH-2F8A0;Lo;0;L;6081;;;;N;;;;; +2F8A1;CJK COMPATIBILITY IDEOGRAPH-2F8A1;Lo;0;L;393A;;;;N;;;;; +2F8A2;CJK COMPATIBILITY IDEOGRAPH-2F8A2;Lo;0;L;391C;;;;N;;;;; +2F8A3;CJK COMPATIBILITY IDEOGRAPH-2F8A3;Lo;0;L;6094;;;;N;;;;; +2F8A4;CJK COMPATIBILITY IDEOGRAPH-2F8A4;Lo;0;L;226D4;;;;N;;;;; +2F8A5;CJK COMPATIBILITY IDEOGRAPH-2F8A5;Lo;0;L;60C7;;;;N;;;;; +2F8A6;CJK COMPATIBILITY IDEOGRAPH-2F8A6;Lo;0;L;6148;;;;N;;;;; +2F8A7;CJK COMPATIBILITY IDEOGRAPH-2F8A7;Lo;0;L;614C;;;;N;;;;; +2F8A8;CJK COMPATIBILITY IDEOGRAPH-2F8A8;Lo;0;L;614E;;;;N;;;;; +2F8A9;CJK COMPATIBILITY IDEOGRAPH-2F8A9;Lo;0;L;614C;;;;N;;;;; +2F8AA;CJK COMPATIBILITY IDEOGRAPH-2F8AA;Lo;0;L;617A;;;;N;;;;; +2F8AB;CJK COMPATIBILITY IDEOGRAPH-2F8AB;Lo;0;L;618E;;;;N;;;;; +2F8AC;CJK COMPATIBILITY IDEOGRAPH-2F8AC;Lo;0;L;61B2;;;;N;;;;; +2F8AD;CJK COMPATIBILITY IDEOGRAPH-2F8AD;Lo;0;L;61A4;;;;N;;;;; +2F8AE;CJK COMPATIBILITY IDEOGRAPH-2F8AE;Lo;0;L;61AF;;;;N;;;;; +2F8AF;CJK COMPATIBILITY IDEOGRAPH-2F8AF;Lo;0;L;61DE;;;;N;;;;; +2F8B0;CJK COMPATIBILITY IDEOGRAPH-2F8B0;Lo;0;L;61F2;;;;N;;;;; +2F8B1;CJK COMPATIBILITY IDEOGRAPH-2F8B1;Lo;0;L;61F6;;;;N;;;;; +2F8B2;CJK COMPATIBILITY IDEOGRAPH-2F8B2;Lo;0;L;6210;;;;N;;;;; +2F8B3;CJK COMPATIBILITY IDEOGRAPH-2F8B3;Lo;0;L;621B;;;;N;;;;; +2F8B4;CJK COMPATIBILITY IDEOGRAPH-2F8B4;Lo;0;L;625D;;;;N;;;;; +2F8B5;CJK COMPATIBILITY IDEOGRAPH-2F8B5;Lo;0;L;62B1;;;;N;;;;; +2F8B6;CJK COMPATIBILITY IDEOGRAPH-2F8B6;Lo;0;L;62D4;;;;N;;;;; +2F8B7;CJK COMPATIBILITY IDEOGRAPH-2F8B7;Lo;0;L;6350;;;;N;;;;; +2F8B8;CJK COMPATIBILITY IDEOGRAPH-2F8B8;Lo;0;L;22B0C;;;;N;;;;; +2F8B9;CJK COMPATIBILITY IDEOGRAPH-2F8B9;Lo;0;L;633D;;;;N;;;;; +2F8BA;CJK COMPATIBILITY IDEOGRAPH-2F8BA;Lo;0;L;62FC;;;;N;;;;; +2F8BB;CJK COMPATIBILITY IDEOGRAPH-2F8BB;Lo;0;L;6368;;;;N;;;;; +2F8BC;CJK COMPATIBILITY IDEOGRAPH-2F8BC;Lo;0;L;6383;;;;N;;;;; +2F8BD;CJK COMPATIBILITY IDEOGRAPH-2F8BD;Lo;0;L;63E4;;;;N;;;;; +2F8BE;CJK COMPATIBILITY IDEOGRAPH-2F8BE;Lo;0;L;22BF1;;;;N;;;;; +2F8BF;CJK COMPATIBILITY IDEOGRAPH-2F8BF;Lo;0;L;6422;;;;N;;;;; +2F8C0;CJK COMPATIBILITY IDEOGRAPH-2F8C0;Lo;0;L;63C5;;;;N;;;;; +2F8C1;CJK COMPATIBILITY IDEOGRAPH-2F8C1;Lo;0;L;63A9;;;;N;;;;; +2F8C2;CJK COMPATIBILITY IDEOGRAPH-2F8C2;Lo;0;L;3A2E;;;;N;;;;; +2F8C3;CJK COMPATIBILITY IDEOGRAPH-2F8C3;Lo;0;L;6469;;;;N;;;;; +2F8C4;CJK COMPATIBILITY IDEOGRAPH-2F8C4;Lo;0;L;647E;;;;N;;;;; +2F8C5;CJK COMPATIBILITY IDEOGRAPH-2F8C5;Lo;0;L;649D;;;;N;;;;; +2F8C6;CJK COMPATIBILITY IDEOGRAPH-2F8C6;Lo;0;L;6477;;;;N;;;;; +2F8C7;CJK COMPATIBILITY IDEOGRAPH-2F8C7;Lo;0;L;3A6C;;;;N;;;;; +2F8C8;CJK COMPATIBILITY IDEOGRAPH-2F8C8;Lo;0;L;654F;;;;N;;;;; +2F8C9;CJK COMPATIBILITY IDEOGRAPH-2F8C9;Lo;0;L;656C;;;;N;;;;; +2F8CA;CJK COMPATIBILITY IDEOGRAPH-2F8CA;Lo;0;L;2300A;;;;N;;;;; +2F8CB;CJK COMPATIBILITY IDEOGRAPH-2F8CB;Lo;0;L;65E3;;;;N;;;;; +2F8CC;CJK COMPATIBILITY IDEOGRAPH-2F8CC;Lo;0;L;66F8;;;;N;;;;; +2F8CD;CJK COMPATIBILITY IDEOGRAPH-2F8CD;Lo;0;L;6649;;;;N;;;;; +2F8CE;CJK COMPATIBILITY IDEOGRAPH-2F8CE;Lo;0;L;3B19;;;;N;;;;; +2F8CF;CJK COMPATIBILITY IDEOGRAPH-2F8CF;Lo;0;L;6691;;;;N;;;;; +2F8D0;CJK COMPATIBILITY IDEOGRAPH-2F8D0;Lo;0;L;3B08;;;;N;;;;; +2F8D1;CJK COMPATIBILITY IDEOGRAPH-2F8D1;Lo;0;L;3AE4;;;;N;;;;; +2F8D2;CJK COMPATIBILITY IDEOGRAPH-2F8D2;Lo;0;L;5192;;;;N;;;;; +2F8D3;CJK COMPATIBILITY IDEOGRAPH-2F8D3;Lo;0;L;5195;;;;N;;;;; +2F8D4;CJK COMPATIBILITY IDEOGRAPH-2F8D4;Lo;0;L;6700;;;;N;;;;; +2F8D5;CJK COMPATIBILITY IDEOGRAPH-2F8D5;Lo;0;L;669C;;;;N;;;;; +2F8D6;CJK COMPATIBILITY IDEOGRAPH-2F8D6;Lo;0;L;80AD;;;;N;;;;; +2F8D7;CJK COMPATIBILITY IDEOGRAPH-2F8D7;Lo;0;L;43D9;;;;N;;;;; +2F8D8;CJK COMPATIBILITY IDEOGRAPH-2F8D8;Lo;0;L;6717;;;;N;;;;; +2F8D9;CJK COMPATIBILITY IDEOGRAPH-2F8D9;Lo;0;L;671B;;;;N;;;;; +2F8DA;CJK COMPATIBILITY IDEOGRAPH-2F8DA;Lo;0;L;6721;;;;N;;;;; +2F8DB;CJK COMPATIBILITY IDEOGRAPH-2F8DB;Lo;0;L;675E;;;;N;;;;; +2F8DC;CJK COMPATIBILITY IDEOGRAPH-2F8DC;Lo;0;L;6753;;;;N;;;;; +2F8DD;CJK COMPATIBILITY IDEOGRAPH-2F8DD;Lo;0;L;233C3;;;;N;;;;; +2F8DE;CJK COMPATIBILITY IDEOGRAPH-2F8DE;Lo;0;L;3B49;;;;N;;;;; +2F8DF;CJK COMPATIBILITY IDEOGRAPH-2F8DF;Lo;0;L;67FA;;;;N;;;;; +2F8E0;CJK COMPATIBILITY IDEOGRAPH-2F8E0;Lo;0;L;6785;;;;N;;;;; +2F8E1;CJK COMPATIBILITY IDEOGRAPH-2F8E1;Lo;0;L;6852;;;;N;;;;; +2F8E2;CJK COMPATIBILITY IDEOGRAPH-2F8E2;Lo;0;L;6885;;;;N;;;;; +2F8E3;CJK COMPATIBILITY IDEOGRAPH-2F8E3;Lo;0;L;2346D;;;;N;;;;; +2F8E4;CJK COMPATIBILITY IDEOGRAPH-2F8E4;Lo;0;L;688E;;;;N;;;;; +2F8E5;CJK COMPATIBILITY IDEOGRAPH-2F8E5;Lo;0;L;681F;;;;N;;;;; +2F8E6;CJK COMPATIBILITY IDEOGRAPH-2F8E6;Lo;0;L;6914;;;;N;;;;; +2F8E7;CJK COMPATIBILITY IDEOGRAPH-2F8E7;Lo;0;L;3B9D;;;;N;;;;; +2F8E8;CJK COMPATIBILITY IDEOGRAPH-2F8E8;Lo;0;L;6942;;;;N;;;;; +2F8E9;CJK COMPATIBILITY IDEOGRAPH-2F8E9;Lo;0;L;69A3;;;;N;;;;; +2F8EA;CJK COMPATIBILITY IDEOGRAPH-2F8EA;Lo;0;L;69EA;;;;N;;;;; +2F8EB;CJK COMPATIBILITY IDEOGRAPH-2F8EB;Lo;0;L;6AA8;;;;N;;;;; +2F8EC;CJK COMPATIBILITY IDEOGRAPH-2F8EC;Lo;0;L;236A3;;;;N;;;;; +2F8ED;CJK COMPATIBILITY IDEOGRAPH-2F8ED;Lo;0;L;6ADB;;;;N;;;;; +2F8EE;CJK COMPATIBILITY IDEOGRAPH-2F8EE;Lo;0;L;3C18;;;;N;;;;; +2F8EF;CJK COMPATIBILITY IDEOGRAPH-2F8EF;Lo;0;L;6B21;;;;N;;;;; +2F8F0;CJK COMPATIBILITY IDEOGRAPH-2F8F0;Lo;0;L;238A7;;;;N;;;;; +2F8F1;CJK COMPATIBILITY IDEOGRAPH-2F8F1;Lo;0;L;6B54;;;;N;;;;; +2F8F2;CJK COMPATIBILITY IDEOGRAPH-2F8F2;Lo;0;L;3C4E;;;;N;;;;; +2F8F3;CJK COMPATIBILITY IDEOGRAPH-2F8F3;Lo;0;L;6B72;;;;N;;;;; +2F8F4;CJK COMPATIBILITY IDEOGRAPH-2F8F4;Lo;0;L;6B9F;;;;N;;;;; +2F8F5;CJK COMPATIBILITY IDEOGRAPH-2F8F5;Lo;0;L;6BBA;;;;N;;;;; +2F8F6;CJK COMPATIBILITY IDEOGRAPH-2F8F6;Lo;0;L;6BBB;;;;N;;;;; +2F8F7;CJK COMPATIBILITY IDEOGRAPH-2F8F7;Lo;0;L;23A8D;;;;N;;;;; +2F8F8;CJK COMPATIBILITY IDEOGRAPH-2F8F8;Lo;0;L;21D0B;;;;N;;;;; +2F8F9;CJK COMPATIBILITY IDEOGRAPH-2F8F9;Lo;0;L;23AFA;;;;N;;;;; +2F8FA;CJK COMPATIBILITY IDEOGRAPH-2F8FA;Lo;0;L;6C4E;;;;N;;;;; +2F8FB;CJK COMPATIBILITY IDEOGRAPH-2F8FB;Lo;0;L;23CBC;;;;N;;;;; +2F8FC;CJK COMPATIBILITY IDEOGRAPH-2F8FC;Lo;0;L;6CBF;;;;N;;;;; +2F8FD;CJK COMPATIBILITY IDEOGRAPH-2F8FD;Lo;0;L;6CCD;;;;N;;;;; +2F8FE;CJK COMPATIBILITY IDEOGRAPH-2F8FE;Lo;0;L;6C67;;;;N;;;;; +2F8FF;CJK COMPATIBILITY IDEOGRAPH-2F8FF;Lo;0;L;6D16;;;;N;;;;; +2F900;CJK COMPATIBILITY IDEOGRAPH-2F900;Lo;0;L;6D3E;;;;N;;;;; +2F901;CJK COMPATIBILITY IDEOGRAPH-2F901;Lo;0;L;6D77;;;;N;;;;; +2F902;CJK COMPATIBILITY IDEOGRAPH-2F902;Lo;0;L;6D41;;;;N;;;;; +2F903;CJK COMPATIBILITY IDEOGRAPH-2F903;Lo;0;L;6D69;;;;N;;;;; +2F904;CJK COMPATIBILITY IDEOGRAPH-2F904;Lo;0;L;6D78;;;;N;;;;; +2F905;CJK COMPATIBILITY IDEOGRAPH-2F905;Lo;0;L;6D85;;;;N;;;;; +2F906;CJK COMPATIBILITY IDEOGRAPH-2F906;Lo;0;L;23D1E;;;;N;;;;; +2F907;CJK COMPATIBILITY IDEOGRAPH-2F907;Lo;0;L;6D34;;;;N;;;;; +2F908;CJK COMPATIBILITY IDEOGRAPH-2F908;Lo;0;L;6E2F;;;;N;;;;; +2F909;CJK COMPATIBILITY IDEOGRAPH-2F909;Lo;0;L;6E6E;;;;N;;;;; +2F90A;CJK COMPATIBILITY IDEOGRAPH-2F90A;Lo;0;L;3D33;;;;N;;;;; +2F90B;CJK COMPATIBILITY IDEOGRAPH-2F90B;Lo;0;L;6ECB;;;;N;;;;; +2F90C;CJK COMPATIBILITY IDEOGRAPH-2F90C;Lo;0;L;6EC7;;;;N;;;;; +2F90D;CJK COMPATIBILITY IDEOGRAPH-2F90D;Lo;0;L;23ED1;;;;N;;;;; +2F90E;CJK COMPATIBILITY IDEOGRAPH-2F90E;Lo;0;L;6DF9;;;;N;;;;; +2F90F;CJK COMPATIBILITY IDEOGRAPH-2F90F;Lo;0;L;6F6E;;;;N;;;;; +2F910;CJK COMPATIBILITY IDEOGRAPH-2F910;Lo;0;L;23F5E;;;;N;;;;; +2F911;CJK COMPATIBILITY IDEOGRAPH-2F911;Lo;0;L;23F8E;;;;N;;;;; +2F912;CJK COMPATIBILITY IDEOGRAPH-2F912;Lo;0;L;6FC6;;;;N;;;;; +2F913;CJK COMPATIBILITY IDEOGRAPH-2F913;Lo;0;L;7039;;;;N;;;;; +2F914;CJK COMPATIBILITY IDEOGRAPH-2F914;Lo;0;L;701E;;;;N;;;;; +2F915;CJK COMPATIBILITY IDEOGRAPH-2F915;Lo;0;L;701B;;;;N;;;;; +2F916;CJK COMPATIBILITY IDEOGRAPH-2F916;Lo;0;L;3D96;;;;N;;;;; +2F917;CJK COMPATIBILITY IDEOGRAPH-2F917;Lo;0;L;704A;;;;N;;;;; +2F918;CJK COMPATIBILITY IDEOGRAPH-2F918;Lo;0;L;707D;;;;N;;;;; +2F919;CJK COMPATIBILITY IDEOGRAPH-2F919;Lo;0;L;7077;;;;N;;;;; +2F91A;CJK COMPATIBILITY IDEOGRAPH-2F91A;Lo;0;L;70AD;;;;N;;;;; +2F91B;CJK COMPATIBILITY IDEOGRAPH-2F91B;Lo;0;L;20525;;;;N;;;;; +2F91C;CJK COMPATIBILITY IDEOGRAPH-2F91C;Lo;0;L;7145;;;;N;;;;; +2F91D;CJK COMPATIBILITY IDEOGRAPH-2F91D;Lo;0;L;24263;;;;N;;;;; +2F91E;CJK COMPATIBILITY IDEOGRAPH-2F91E;Lo;0;L;719C;;;;N;;;;; +2F91F;CJK COMPATIBILITY IDEOGRAPH-2F91F;Lo;0;L;243AB;;;;N;;;;; +2F920;CJK COMPATIBILITY IDEOGRAPH-2F920;Lo;0;L;7228;;;;N;;;;; +2F921;CJK COMPATIBILITY IDEOGRAPH-2F921;Lo;0;L;7235;;;;N;;;;; +2F922;CJK COMPATIBILITY IDEOGRAPH-2F922;Lo;0;L;7250;;;;N;;;;; +2F923;CJK COMPATIBILITY IDEOGRAPH-2F923;Lo;0;L;24608;;;;N;;;;; +2F924;CJK COMPATIBILITY IDEOGRAPH-2F924;Lo;0;L;7280;;;;N;;;;; +2F925;CJK COMPATIBILITY IDEOGRAPH-2F925;Lo;0;L;7295;;;;N;;;;; +2F926;CJK COMPATIBILITY IDEOGRAPH-2F926;Lo;0;L;24735;;;;N;;;;; +2F927;CJK COMPATIBILITY IDEOGRAPH-2F927;Lo;0;L;24814;;;;N;;;;; +2F928;CJK COMPATIBILITY IDEOGRAPH-2F928;Lo;0;L;737A;;;;N;;;;; +2F929;CJK COMPATIBILITY IDEOGRAPH-2F929;Lo;0;L;738B;;;;N;;;;; +2F92A;CJK COMPATIBILITY IDEOGRAPH-2F92A;Lo;0;L;3EAC;;;;N;;;;; +2F92B;CJK COMPATIBILITY IDEOGRAPH-2F92B;Lo;0;L;73A5;;;;N;;;;; +2F92C;CJK COMPATIBILITY IDEOGRAPH-2F92C;Lo;0;L;3EB8;;;;N;;;;; +2F92D;CJK COMPATIBILITY IDEOGRAPH-2F92D;Lo;0;L;3EB8;;;;N;;;;; +2F92E;CJK COMPATIBILITY IDEOGRAPH-2F92E;Lo;0;L;7447;;;;N;;;;; +2F92F;CJK COMPATIBILITY IDEOGRAPH-2F92F;Lo;0;L;745C;;;;N;;;;; +2F930;CJK COMPATIBILITY IDEOGRAPH-2F930;Lo;0;L;7471;;;;N;;;;; +2F931;CJK COMPATIBILITY IDEOGRAPH-2F931;Lo;0;L;7485;;;;N;;;;; +2F932;CJK COMPATIBILITY IDEOGRAPH-2F932;Lo;0;L;74CA;;;;N;;;;; +2F933;CJK COMPATIBILITY IDEOGRAPH-2F933;Lo;0;L;3F1B;;;;N;;;;; +2F934;CJK COMPATIBILITY IDEOGRAPH-2F934;Lo;0;L;7524;;;;N;;;;; +2F935;CJK COMPATIBILITY IDEOGRAPH-2F935;Lo;0;L;24C36;;;;N;;;;; +2F936;CJK COMPATIBILITY IDEOGRAPH-2F936;Lo;0;L;753E;;;;N;;;;; +2F937;CJK COMPATIBILITY IDEOGRAPH-2F937;Lo;0;L;24C92;;;;N;;;;; +2F938;CJK COMPATIBILITY IDEOGRAPH-2F938;Lo;0;L;7570;;;;N;;;;; +2F939;CJK COMPATIBILITY IDEOGRAPH-2F939;Lo;0;L;2219F;;;;N;;;;; +2F93A;CJK COMPATIBILITY IDEOGRAPH-2F93A;Lo;0;L;7610;;;;N;;;;; +2F93B;CJK COMPATIBILITY IDEOGRAPH-2F93B;Lo;0;L;24FA1;;;;N;;;;; +2F93C;CJK COMPATIBILITY IDEOGRAPH-2F93C;Lo;0;L;24FB8;;;;N;;;;; +2F93D;CJK COMPATIBILITY IDEOGRAPH-2F93D;Lo;0;L;25044;;;;N;;;;; +2F93E;CJK COMPATIBILITY IDEOGRAPH-2F93E;Lo;0;L;3FFC;;;;N;;;;; +2F93F;CJK COMPATIBILITY IDEOGRAPH-2F93F;Lo;0;L;4008;;;;N;;;;; +2F940;CJK COMPATIBILITY IDEOGRAPH-2F940;Lo;0;L;76F4;;;;N;;;;; +2F941;CJK COMPATIBILITY IDEOGRAPH-2F941;Lo;0;L;250F3;;;;N;;;;; +2F942;CJK COMPATIBILITY IDEOGRAPH-2F942;Lo;0;L;250F2;;;;N;;;;; +2F943;CJK COMPATIBILITY IDEOGRAPH-2F943;Lo;0;L;25119;;;;N;;;;; +2F944;CJK COMPATIBILITY IDEOGRAPH-2F944;Lo;0;L;25133;;;;N;;;;; +2F945;CJK COMPATIBILITY IDEOGRAPH-2F945;Lo;0;L;771E;;;;N;;;;; +2F946;CJK COMPATIBILITY IDEOGRAPH-2F946;Lo;0;L;771F;;;;N;;;;; +2F947;CJK COMPATIBILITY IDEOGRAPH-2F947;Lo;0;L;771F;;;;N;;;;; +2F948;CJK COMPATIBILITY IDEOGRAPH-2F948;Lo;0;L;774A;;;;N;;;;; +2F949;CJK COMPATIBILITY IDEOGRAPH-2F949;Lo;0;L;4039;;;;N;;;;; +2F94A;CJK COMPATIBILITY IDEOGRAPH-2F94A;Lo;0;L;778B;;;;N;;;;; +2F94B;CJK COMPATIBILITY IDEOGRAPH-2F94B;Lo;0;L;4046;;;;N;;;;; +2F94C;CJK COMPATIBILITY IDEOGRAPH-2F94C;Lo;0;L;4096;;;;N;;;;; +2F94D;CJK COMPATIBILITY IDEOGRAPH-2F94D;Lo;0;L;2541D;;;;N;;;;; +2F94E;CJK COMPATIBILITY IDEOGRAPH-2F94E;Lo;0;L;784E;;;;N;;;;; +2F94F;CJK COMPATIBILITY IDEOGRAPH-2F94F;Lo;0;L;788C;;;;N;;;;; +2F950;CJK COMPATIBILITY IDEOGRAPH-2F950;Lo;0;L;78CC;;;;N;;;;; +2F951;CJK COMPATIBILITY IDEOGRAPH-2F951;Lo;0;L;40E3;;;;N;;;;; +2F952;CJK COMPATIBILITY IDEOGRAPH-2F952;Lo;0;L;25626;;;;N;;;;; +2F953;CJK COMPATIBILITY IDEOGRAPH-2F953;Lo;0;L;7956;;;;N;;;;; +2F954;CJK COMPATIBILITY IDEOGRAPH-2F954;Lo;0;L;2569A;;;;N;;;;; +2F955;CJK COMPATIBILITY IDEOGRAPH-2F955;Lo;0;L;256C5;;;;N;;;;; +2F956;CJK COMPATIBILITY IDEOGRAPH-2F956;Lo;0;L;798F;;;;N;;;;; +2F957;CJK COMPATIBILITY IDEOGRAPH-2F957;Lo;0;L;79EB;;;;N;;;;; +2F958;CJK COMPATIBILITY IDEOGRAPH-2F958;Lo;0;L;412F;;;;N;;;;; +2F959;CJK COMPATIBILITY IDEOGRAPH-2F959;Lo;0;L;7A40;;;;N;;;;; +2F95A;CJK COMPATIBILITY IDEOGRAPH-2F95A;Lo;0;L;7A4A;;;;N;;;;; +2F95B;CJK COMPATIBILITY IDEOGRAPH-2F95B;Lo;0;L;7A4F;;;;N;;;;; +2F95C;CJK COMPATIBILITY IDEOGRAPH-2F95C;Lo;0;L;2597C;;;;N;;;;; +2F95D;CJK COMPATIBILITY IDEOGRAPH-2F95D;Lo;0;L;25AA7;;;;N;;;;; +2F95E;CJK COMPATIBILITY IDEOGRAPH-2F95E;Lo;0;L;25AA7;;;;N;;;;; +2F95F;CJK COMPATIBILITY IDEOGRAPH-2F95F;Lo;0;L;7AEE;;;;N;;;;; +2F960;CJK COMPATIBILITY IDEOGRAPH-2F960;Lo;0;L;4202;;;;N;;;;; +2F961;CJK COMPATIBILITY IDEOGRAPH-2F961;Lo;0;L;25BAB;;;;N;;;;; +2F962;CJK COMPATIBILITY IDEOGRAPH-2F962;Lo;0;L;7BC6;;;;N;;;;; +2F963;CJK COMPATIBILITY IDEOGRAPH-2F963;Lo;0;L;7BC9;;;;N;;;;; +2F964;CJK COMPATIBILITY IDEOGRAPH-2F964;Lo;0;L;4227;;;;N;;;;; +2F965;CJK COMPATIBILITY IDEOGRAPH-2F965;Lo;0;L;25C80;;;;N;;;;; +2F966;CJK COMPATIBILITY IDEOGRAPH-2F966;Lo;0;L;7CD2;;;;N;;;;; +2F967;CJK COMPATIBILITY IDEOGRAPH-2F967;Lo;0;L;42A0;;;;N;;;;; +2F968;CJK COMPATIBILITY IDEOGRAPH-2F968;Lo;0;L;7CE8;;;;N;;;;; +2F969;CJK COMPATIBILITY IDEOGRAPH-2F969;Lo;0;L;7CE3;;;;N;;;;; +2F96A;CJK COMPATIBILITY IDEOGRAPH-2F96A;Lo;0;L;7D00;;;;N;;;;; +2F96B;CJK COMPATIBILITY IDEOGRAPH-2F96B;Lo;0;L;25F86;;;;N;;;;; +2F96C;CJK COMPATIBILITY IDEOGRAPH-2F96C;Lo;0;L;7D63;;;;N;;;;; +2F96D;CJK COMPATIBILITY IDEOGRAPH-2F96D;Lo;0;L;4301;;;;N;;;;; +2F96E;CJK COMPATIBILITY IDEOGRAPH-2F96E;Lo;0;L;7DC7;;;;N;;;;; +2F96F;CJK COMPATIBILITY IDEOGRAPH-2F96F;Lo;0;L;7E02;;;;N;;;;; +2F970;CJK COMPATIBILITY IDEOGRAPH-2F970;Lo;0;L;7E45;;;;N;;;;; +2F971;CJK COMPATIBILITY IDEOGRAPH-2F971;Lo;0;L;4334;;;;N;;;;; +2F972;CJK COMPATIBILITY IDEOGRAPH-2F972;Lo;0;L;26228;;;;N;;;;; +2F973;CJK COMPATIBILITY IDEOGRAPH-2F973;Lo;0;L;26247;;;;N;;;;; +2F974;CJK COMPATIBILITY IDEOGRAPH-2F974;Lo;0;L;4359;;;;N;;;;; +2F975;CJK COMPATIBILITY IDEOGRAPH-2F975;Lo;0;L;262D9;;;;N;;;;; +2F976;CJK COMPATIBILITY IDEOGRAPH-2F976;Lo;0;L;7F7A;;;;N;;;;; +2F977;CJK COMPATIBILITY IDEOGRAPH-2F977;Lo;0;L;2633E;;;;N;;;;; +2F978;CJK COMPATIBILITY IDEOGRAPH-2F978;Lo;0;L;7F95;;;;N;;;;; +2F979;CJK COMPATIBILITY IDEOGRAPH-2F979;Lo;0;L;7FFA;;;;N;;;;; +2F97A;CJK COMPATIBILITY IDEOGRAPH-2F97A;Lo;0;L;8005;;;;N;;;;; +2F97B;CJK COMPATIBILITY IDEOGRAPH-2F97B;Lo;0;L;264DA;;;;N;;;;; +2F97C;CJK COMPATIBILITY IDEOGRAPH-2F97C;Lo;0;L;26523;;;;N;;;;; +2F97D;CJK COMPATIBILITY IDEOGRAPH-2F97D;Lo;0;L;8060;;;;N;;;;; +2F97E;CJK COMPATIBILITY IDEOGRAPH-2F97E;Lo;0;L;265A8;;;;N;;;;; +2F97F;CJK COMPATIBILITY IDEOGRAPH-2F97F;Lo;0;L;8070;;;;N;;;;; +2F980;CJK COMPATIBILITY IDEOGRAPH-2F980;Lo;0;L;2335F;;;;N;;;;; +2F981;CJK COMPATIBILITY IDEOGRAPH-2F981;Lo;0;L;43D5;;;;N;;;;; +2F982;CJK COMPATIBILITY IDEOGRAPH-2F982;Lo;0;L;80B2;;;;N;;;;; +2F983;CJK COMPATIBILITY IDEOGRAPH-2F983;Lo;0;L;8103;;;;N;;;;; +2F984;CJK COMPATIBILITY IDEOGRAPH-2F984;Lo;0;L;440B;;;;N;;;;; +2F985;CJK COMPATIBILITY IDEOGRAPH-2F985;Lo;0;L;813E;;;;N;;;;; +2F986;CJK COMPATIBILITY IDEOGRAPH-2F986;Lo;0;L;5AB5;;;;N;;;;; +2F987;CJK COMPATIBILITY IDEOGRAPH-2F987;Lo;0;L;267A7;;;;N;;;;; +2F988;CJK COMPATIBILITY IDEOGRAPH-2F988;Lo;0;L;267B5;;;;N;;;;; +2F989;CJK COMPATIBILITY IDEOGRAPH-2F989;Lo;0;L;23393;;;;N;;;;; +2F98A;CJK COMPATIBILITY IDEOGRAPH-2F98A;Lo;0;L;2339C;;;;N;;;;; +2F98B;CJK COMPATIBILITY IDEOGRAPH-2F98B;Lo;0;L;8201;;;;N;;;;; +2F98C;CJK COMPATIBILITY IDEOGRAPH-2F98C;Lo;0;L;8204;;;;N;;;;; +2F98D;CJK COMPATIBILITY IDEOGRAPH-2F98D;Lo;0;L;8F9E;;;;N;;;;; +2F98E;CJK COMPATIBILITY IDEOGRAPH-2F98E;Lo;0;L;446B;;;;N;;;;; +2F98F;CJK COMPATIBILITY IDEOGRAPH-2F98F;Lo;0;L;8291;;;;N;;;;; +2F990;CJK COMPATIBILITY IDEOGRAPH-2F990;Lo;0;L;828B;;;;N;;;;; +2F991;CJK COMPATIBILITY IDEOGRAPH-2F991;Lo;0;L;829D;;;;N;;;;; +2F992;CJK COMPATIBILITY IDEOGRAPH-2F992;Lo;0;L;52B3;;;;N;;;;; +2F993;CJK COMPATIBILITY IDEOGRAPH-2F993;Lo;0;L;82B1;;;;N;;;;; +2F994;CJK COMPATIBILITY IDEOGRAPH-2F994;Lo;0;L;82B3;;;;N;;;;; +2F995;CJK COMPATIBILITY IDEOGRAPH-2F995;Lo;0;L;82BD;;;;N;;;;; +2F996;CJK COMPATIBILITY IDEOGRAPH-2F996;Lo;0;L;82E6;;;;N;;;;; +2F997;CJK COMPATIBILITY IDEOGRAPH-2F997;Lo;0;L;26B3C;;;;N;;;;; +2F998;CJK COMPATIBILITY IDEOGRAPH-2F998;Lo;0;L;82E5;;;;N;;;;; +2F999;CJK COMPATIBILITY IDEOGRAPH-2F999;Lo;0;L;831D;;;;N;;;;; +2F99A;CJK COMPATIBILITY IDEOGRAPH-2F99A;Lo;0;L;8363;;;;N;;;;; +2F99B;CJK COMPATIBILITY IDEOGRAPH-2F99B;Lo;0;L;83AD;;;;N;;;;; +2F99C;CJK COMPATIBILITY IDEOGRAPH-2F99C;Lo;0;L;8323;;;;N;;;;; +2F99D;CJK COMPATIBILITY IDEOGRAPH-2F99D;Lo;0;L;83BD;;;;N;;;;; +2F99E;CJK COMPATIBILITY IDEOGRAPH-2F99E;Lo;0;L;83E7;;;;N;;;;; +2F99F;CJK COMPATIBILITY IDEOGRAPH-2F99F;Lo;0;L;8457;;;;N;;;;; +2F9A0;CJK COMPATIBILITY IDEOGRAPH-2F9A0;Lo;0;L;8353;;;;N;;;;; +2F9A1;CJK COMPATIBILITY IDEOGRAPH-2F9A1;Lo;0;L;83CA;;;;N;;;;; +2F9A2;CJK COMPATIBILITY IDEOGRAPH-2F9A2;Lo;0;L;83CC;;;;N;;;;; +2F9A3;CJK COMPATIBILITY IDEOGRAPH-2F9A3;Lo;0;L;83DC;;;;N;;;;; +2F9A4;CJK COMPATIBILITY IDEOGRAPH-2F9A4;Lo;0;L;26C36;;;;N;;;;; +2F9A5;CJK COMPATIBILITY IDEOGRAPH-2F9A5;Lo;0;L;26D6B;;;;N;;;;; +2F9A6;CJK COMPATIBILITY IDEOGRAPH-2F9A6;Lo;0;L;26CD5;;;;N;;;;; +2F9A7;CJK COMPATIBILITY IDEOGRAPH-2F9A7;Lo;0;L;452B;;;;N;;;;; +2F9A8;CJK COMPATIBILITY IDEOGRAPH-2F9A8;Lo;0;L;84F1;;;;N;;;;; +2F9A9;CJK COMPATIBILITY IDEOGRAPH-2F9A9;Lo;0;L;84F3;;;;N;;;;; +2F9AA;CJK COMPATIBILITY IDEOGRAPH-2F9AA;Lo;0;L;8516;;;;N;;;;; +2F9AB;CJK COMPATIBILITY IDEOGRAPH-2F9AB;Lo;0;L;273CA;;;;N;;;;; +2F9AC;CJK COMPATIBILITY IDEOGRAPH-2F9AC;Lo;0;L;8564;;;;N;;;;; +2F9AD;CJK COMPATIBILITY IDEOGRAPH-2F9AD;Lo;0;L;26F2C;;;;N;;;;; +2F9AE;CJK COMPATIBILITY IDEOGRAPH-2F9AE;Lo;0;L;455D;;;;N;;;;; +2F9AF;CJK COMPATIBILITY IDEOGRAPH-2F9AF;Lo;0;L;4561;;;;N;;;;; +2F9B0;CJK COMPATIBILITY IDEOGRAPH-2F9B0;Lo;0;L;26FB1;;;;N;;;;; +2F9B1;CJK COMPATIBILITY IDEOGRAPH-2F9B1;Lo;0;L;270D2;;;;N;;;;; +2F9B2;CJK COMPATIBILITY IDEOGRAPH-2F9B2;Lo;0;L;456B;;;;N;;;;; +2F9B3;CJK COMPATIBILITY IDEOGRAPH-2F9B3;Lo;0;L;8650;;;;N;;;;; +2F9B4;CJK COMPATIBILITY IDEOGRAPH-2F9B4;Lo;0;L;865C;;;;N;;;;; +2F9B5;CJK COMPATIBILITY IDEOGRAPH-2F9B5;Lo;0;L;8667;;;;N;;;;; +2F9B6;CJK COMPATIBILITY IDEOGRAPH-2F9B6;Lo;0;L;8669;;;;N;;;;; +2F9B7;CJK COMPATIBILITY IDEOGRAPH-2F9B7;Lo;0;L;86A9;;;;N;;;;; +2F9B8;CJK COMPATIBILITY IDEOGRAPH-2F9B8;Lo;0;L;8688;;;;N;;;;; +2F9B9;CJK COMPATIBILITY IDEOGRAPH-2F9B9;Lo;0;L;870E;;;;N;;;;; +2F9BA;CJK COMPATIBILITY IDEOGRAPH-2F9BA;Lo;0;L;86E2;;;;N;;;;; +2F9BB;CJK COMPATIBILITY IDEOGRAPH-2F9BB;Lo;0;L;8779;;;;N;;;;; +2F9BC;CJK COMPATIBILITY IDEOGRAPH-2F9BC;Lo;0;L;8728;;;;N;;;;; +2F9BD;CJK COMPATIBILITY IDEOGRAPH-2F9BD;Lo;0;L;876B;;;;N;;;;; +2F9BE;CJK COMPATIBILITY IDEOGRAPH-2F9BE;Lo;0;L;8786;;;;N;;;;; +2F9BF;CJK COMPATIBILITY IDEOGRAPH-2F9BF;Lo;0;L;45D7;;;;N;;;;; +2F9C0;CJK COMPATIBILITY IDEOGRAPH-2F9C0;Lo;0;L;87E1;;;;N;;;;; +2F9C1;CJK COMPATIBILITY IDEOGRAPH-2F9C1;Lo;0;L;8801;;;;N;;;;; +2F9C2;CJK COMPATIBILITY IDEOGRAPH-2F9C2;Lo;0;L;45F9;;;;N;;;;; +2F9C3;CJK COMPATIBILITY IDEOGRAPH-2F9C3;Lo;0;L;8860;;;;N;;;;; +2F9C4;CJK COMPATIBILITY IDEOGRAPH-2F9C4;Lo;0;L;8863;;;;N;;;;; +2F9C5;CJK COMPATIBILITY IDEOGRAPH-2F9C5;Lo;0;L;27667;;;;N;;;;; +2F9C6;CJK COMPATIBILITY IDEOGRAPH-2F9C6;Lo;0;L;88D7;;;;N;;;;; +2F9C7;CJK COMPATIBILITY IDEOGRAPH-2F9C7;Lo;0;L;88DE;;;;N;;;;; +2F9C8;CJK COMPATIBILITY IDEOGRAPH-2F9C8;Lo;0;L;4635;;;;N;;;;; +2F9C9;CJK COMPATIBILITY IDEOGRAPH-2F9C9;Lo;0;L;88FA;;;;N;;;;; +2F9CA;CJK COMPATIBILITY IDEOGRAPH-2F9CA;Lo;0;L;34BB;;;;N;;;;; +2F9CB;CJK COMPATIBILITY IDEOGRAPH-2F9CB;Lo;0;L;278AE;;;;N;;;;; +2F9CC;CJK COMPATIBILITY IDEOGRAPH-2F9CC;Lo;0;L;27966;;;;N;;;;; +2F9CD;CJK COMPATIBILITY IDEOGRAPH-2F9CD;Lo;0;L;46BE;;;;N;;;;; +2F9CE;CJK COMPATIBILITY IDEOGRAPH-2F9CE;Lo;0;L;46C7;;;;N;;;;; +2F9CF;CJK COMPATIBILITY IDEOGRAPH-2F9CF;Lo;0;L;8AA0;;;;N;;;;; +2F9D0;CJK COMPATIBILITY IDEOGRAPH-2F9D0;Lo;0;L;8AED;;;;N;;;;; +2F9D1;CJK COMPATIBILITY IDEOGRAPH-2F9D1;Lo;0;L;8B8A;;;;N;;;;; +2F9D2;CJK COMPATIBILITY IDEOGRAPH-2F9D2;Lo;0;L;8C55;;;;N;;;;; +2F9D3;CJK COMPATIBILITY IDEOGRAPH-2F9D3;Lo;0;L;27CA8;;;;N;;;;; +2F9D4;CJK COMPATIBILITY IDEOGRAPH-2F9D4;Lo;0;L;8CAB;;;;N;;;;; +2F9D5;CJK COMPATIBILITY IDEOGRAPH-2F9D5;Lo;0;L;8CC1;;;;N;;;;; +2F9D6;CJK COMPATIBILITY IDEOGRAPH-2F9D6;Lo;0;L;8D1B;;;;N;;;;; +2F9D7;CJK COMPATIBILITY IDEOGRAPH-2F9D7;Lo;0;L;8D77;;;;N;;;;; +2F9D8;CJK COMPATIBILITY IDEOGRAPH-2F9D8;Lo;0;L;27F2F;;;;N;;;;; +2F9D9;CJK COMPATIBILITY IDEOGRAPH-2F9D9;Lo;0;L;20804;;;;N;;;;; +2F9DA;CJK COMPATIBILITY IDEOGRAPH-2F9DA;Lo;0;L;8DCB;;;;N;;;;; +2F9DB;CJK COMPATIBILITY IDEOGRAPH-2F9DB;Lo;0;L;8DBC;;;;N;;;;; +2F9DC;CJK COMPATIBILITY IDEOGRAPH-2F9DC;Lo;0;L;8DF0;;;;N;;;;; +2F9DD;CJK COMPATIBILITY IDEOGRAPH-2F9DD;Lo;0;L;208DE;;;;N;;;;; +2F9DE;CJK COMPATIBILITY IDEOGRAPH-2F9DE;Lo;0;L;8ED4;;;;N;;;;; +2F9DF;CJK COMPATIBILITY IDEOGRAPH-2F9DF;Lo;0;L;8F38;;;;N;;;;; +2F9E0;CJK COMPATIBILITY IDEOGRAPH-2F9E0;Lo;0;L;285D2;;;;N;;;;; +2F9E1;CJK COMPATIBILITY IDEOGRAPH-2F9E1;Lo;0;L;285ED;;;;N;;;;; +2F9E2;CJK COMPATIBILITY IDEOGRAPH-2F9E2;Lo;0;L;9094;;;;N;;;;; +2F9E3;CJK COMPATIBILITY IDEOGRAPH-2F9E3;Lo;0;L;90F1;;;;N;;;;; +2F9E4;CJK COMPATIBILITY IDEOGRAPH-2F9E4;Lo;0;L;9111;;;;N;;;;; +2F9E5;CJK COMPATIBILITY IDEOGRAPH-2F9E5;Lo;0;L;2872E;;;;N;;;;; +2F9E6;CJK COMPATIBILITY IDEOGRAPH-2F9E6;Lo;0;L;911B;;;;N;;;;; +2F9E7;CJK COMPATIBILITY IDEOGRAPH-2F9E7;Lo;0;L;9238;;;;N;;;;; +2F9E8;CJK COMPATIBILITY IDEOGRAPH-2F9E8;Lo;0;L;92D7;;;;N;;;;; +2F9E9;CJK COMPATIBILITY IDEOGRAPH-2F9E9;Lo;0;L;92D8;;;;N;;;;; +2F9EA;CJK COMPATIBILITY IDEOGRAPH-2F9EA;Lo;0;L;927C;;;;N;;;;; +2F9EB;CJK COMPATIBILITY IDEOGRAPH-2F9EB;Lo;0;L;93F9;;;;N;;;;; +2F9EC;CJK COMPATIBILITY IDEOGRAPH-2F9EC;Lo;0;L;9415;;;;N;;;;; +2F9ED;CJK COMPATIBILITY IDEOGRAPH-2F9ED;Lo;0;L;28BFA;;;;N;;;;; +2F9EE;CJK COMPATIBILITY IDEOGRAPH-2F9EE;Lo;0;L;958B;;;;N;;;;; +2F9EF;CJK COMPATIBILITY IDEOGRAPH-2F9EF;Lo;0;L;4995;;;;N;;;;; +2F9F0;CJK COMPATIBILITY IDEOGRAPH-2F9F0;Lo;0;L;95B7;;;;N;;;;; +2F9F1;CJK COMPATIBILITY IDEOGRAPH-2F9F1;Lo;0;L;28D77;;;;N;;;;; +2F9F2;CJK COMPATIBILITY IDEOGRAPH-2F9F2;Lo;0;L;49E6;;;;N;;;;; +2F9F3;CJK COMPATIBILITY IDEOGRAPH-2F9F3;Lo;0;L;96C3;;;;N;;;;; +2F9F4;CJK COMPATIBILITY IDEOGRAPH-2F9F4;Lo;0;L;5DB2;;;;N;;;;; +2F9F5;CJK COMPATIBILITY IDEOGRAPH-2F9F5;Lo;0;L;9723;;;;N;;;;; +2F9F6;CJK COMPATIBILITY IDEOGRAPH-2F9F6;Lo;0;L;29145;;;;N;;;;; +2F9F7;CJK COMPATIBILITY IDEOGRAPH-2F9F7;Lo;0;L;2921A;;;;N;;;;; +2F9F8;CJK COMPATIBILITY IDEOGRAPH-2F9F8;Lo;0;L;4A6E;;;;N;;;;; +2F9F9;CJK COMPATIBILITY IDEOGRAPH-2F9F9;Lo;0;L;4A76;;;;N;;;;; +2F9FA;CJK COMPATIBILITY IDEOGRAPH-2F9FA;Lo;0;L;97E0;;;;N;;;;; +2F9FB;CJK COMPATIBILITY IDEOGRAPH-2F9FB;Lo;0;L;2940A;;;;N;;;;; +2F9FC;CJK COMPATIBILITY IDEOGRAPH-2F9FC;Lo;0;L;4AB2;;;;N;;;;; +2F9FD;CJK COMPATIBILITY IDEOGRAPH-2F9FD;Lo;0;L;29496;;;;N;;;;; +2F9FE;CJK COMPATIBILITY IDEOGRAPH-2F9FE;Lo;0;L;980B;;;;N;;;;; +2F9FF;CJK COMPATIBILITY IDEOGRAPH-2F9FF;Lo;0;L;980B;;;;N;;;;; +2FA00;CJK COMPATIBILITY IDEOGRAPH-2FA00;Lo;0;L;9829;;;;N;;;;; +2FA01;CJK COMPATIBILITY IDEOGRAPH-2FA01;Lo;0;L;295B6;;;;N;;;;; +2FA02;CJK COMPATIBILITY IDEOGRAPH-2FA02;Lo;0;L;98E2;;;;N;;;;; +2FA03;CJK COMPATIBILITY IDEOGRAPH-2FA03;Lo;0;L;4B33;;;;N;;;;; +2FA04;CJK COMPATIBILITY IDEOGRAPH-2FA04;Lo;0;L;9929;;;;N;;;;; +2FA05;CJK COMPATIBILITY IDEOGRAPH-2FA05;Lo;0;L;99A7;;;;N;;;;; +2FA06;CJK COMPATIBILITY IDEOGRAPH-2FA06;Lo;0;L;99C2;;;;N;;;;; +2FA07;CJK COMPATIBILITY IDEOGRAPH-2FA07;Lo;0;L;99FE;;;;N;;;;; +2FA08;CJK COMPATIBILITY IDEOGRAPH-2FA08;Lo;0;L;4BCE;;;;N;;;;; +2FA09;CJK COMPATIBILITY IDEOGRAPH-2FA09;Lo;0;L;29B30;;;;N;;;;; +2FA0A;CJK COMPATIBILITY IDEOGRAPH-2FA0A;Lo;0;L;9B12;;;;N;;;;; +2FA0B;CJK COMPATIBILITY IDEOGRAPH-2FA0B;Lo;0;L;9C40;;;;N;;;;; +2FA0C;CJK COMPATIBILITY IDEOGRAPH-2FA0C;Lo;0;L;9CFD;;;;N;;;;; +2FA0D;CJK COMPATIBILITY IDEOGRAPH-2FA0D;Lo;0;L;4CCE;;;;N;;;;; +2FA0E;CJK COMPATIBILITY IDEOGRAPH-2FA0E;Lo;0;L;4CED;;;;N;;;;; +2FA0F;CJK COMPATIBILITY IDEOGRAPH-2FA0F;Lo;0;L;9D67;;;;N;;;;; +2FA10;CJK COMPATIBILITY IDEOGRAPH-2FA10;Lo;0;L;2A0CE;;;;N;;;;; +2FA11;CJK COMPATIBILITY IDEOGRAPH-2FA11;Lo;0;L;4CF8;;;;N;;;;; +2FA12;CJK COMPATIBILITY IDEOGRAPH-2FA12;Lo;0;L;2A105;;;;N;;;;; +2FA13;CJK COMPATIBILITY IDEOGRAPH-2FA13;Lo;0;L;2A20E;;;;N;;;;; +2FA14;CJK COMPATIBILITY IDEOGRAPH-2FA14;Lo;0;L;2A291;;;;N;;;;; +2FA15;CJK COMPATIBILITY IDEOGRAPH-2FA15;Lo;0;L;9EBB;;;;N;;;;; +2FA16;CJK COMPATIBILITY IDEOGRAPH-2FA16;Lo;0;L;4D56;;;;N;;;;; +2FA17;CJK COMPATIBILITY IDEOGRAPH-2FA17;Lo;0;L;9EF9;;;;N;;;;; +2FA18;CJK COMPATIBILITY IDEOGRAPH-2FA18;Lo;0;L;9EFE;;;;N;;;;; +2FA19;CJK COMPATIBILITY IDEOGRAPH-2FA19;Lo;0;L;9F05;;;;N;;;;; +2FA1A;CJK COMPATIBILITY IDEOGRAPH-2FA1A;Lo;0;L;9F0F;;;;N;;;;; +2FA1B;CJK COMPATIBILITY IDEOGRAPH-2FA1B;Lo;0;L;9F16;;;;N;;;;; +2FA1C;CJK COMPATIBILITY IDEOGRAPH-2FA1C;Lo;0;L;9F3B;;;;N;;;;; +2FA1D;CJK COMPATIBILITY IDEOGRAPH-2FA1D;Lo;0;L;2A600;;;;N;;;;; +30000;;Lo;0;L;;;;;N;;;;; +3134A;;Lo;0;L;;;;;N;;;;; +31350;;Lo;0;L;;;;;N;;;;; +323AF;;Lo;0;L;;;;;N;;;;; +323B0;;Lo;0;L;;;;;N;;;;; +33479;;Lo;0;L;;;;;N;;;;; +E0001;LANGUAGE TAG;Cf;0;BN;;;;;N;;;;; +E0020;TAG SPACE;Cf;0;BN;;;;;N;;;;; +E0021;TAG EXCLAMATION MARK;Cf;0;BN;;;;;N;;;;; +E0022;TAG QUOTATION MARK;Cf;0;BN;;;;;N;;;;; +E0023;TAG NUMBER SIGN;Cf;0;BN;;;;;N;;;;; +E0024;TAG DOLLAR SIGN;Cf;0;BN;;;;;N;;;;; +E0025;TAG PERCENT SIGN;Cf;0;BN;;;;;N;;;;; +E0026;TAG AMPERSAND;Cf;0;BN;;;;;N;;;;; +E0027;TAG APOSTROPHE;Cf;0;BN;;;;;N;;;;; +E0028;TAG LEFT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E0029;TAG RIGHT PARENTHESIS;Cf;0;BN;;;;;N;;;;; +E002A;TAG ASTERISK;Cf;0;BN;;;;;N;;;;; +E002B;TAG PLUS SIGN;Cf;0;BN;;;;;N;;;;; +E002C;TAG COMMA;Cf;0;BN;;;;;N;;;;; +E002D;TAG HYPHEN-MINUS;Cf;0;BN;;;;;N;;;;; +E002E;TAG FULL STOP;Cf;0;BN;;;;;N;;;;; +E002F;TAG SOLIDUS;Cf;0;BN;;;;;N;;;;; +E0030;TAG DIGIT ZERO;Cf;0;BN;;;;;N;;;;; +E0031;TAG DIGIT ONE;Cf;0;BN;;;;;N;;;;; +E0032;TAG DIGIT TWO;Cf;0;BN;;;;;N;;;;; +E0033;TAG DIGIT THREE;Cf;0;BN;;;;;N;;;;; +E0034;TAG DIGIT FOUR;Cf;0;BN;;;;;N;;;;; +E0035;TAG DIGIT FIVE;Cf;0;BN;;;;;N;;;;; +E0036;TAG DIGIT SIX;Cf;0;BN;;;;;N;;;;; +E0037;TAG DIGIT SEVEN;Cf;0;BN;;;;;N;;;;; +E0038;TAG DIGIT EIGHT;Cf;0;BN;;;;;N;;;;; +E0039;TAG DIGIT NINE;Cf;0;BN;;;;;N;;;;; +E003A;TAG COLON;Cf;0;BN;;;;;N;;;;; +E003B;TAG SEMICOLON;Cf;0;BN;;;;;N;;;;; +E003C;TAG LESS-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003D;TAG EQUALS SIGN;Cf;0;BN;;;;;N;;;;; +E003E;TAG GREATER-THAN SIGN;Cf;0;BN;;;;;N;;;;; +E003F;TAG QUESTION MARK;Cf;0;BN;;;;;N;;;;; +E0040;TAG COMMERCIAL AT;Cf;0;BN;;;;;N;;;;; +E0041;TAG LATIN CAPITAL LETTER A;Cf;0;BN;;;;;N;;;;; +E0042;TAG LATIN CAPITAL LETTER B;Cf;0;BN;;;;;N;;;;; +E0043;TAG LATIN CAPITAL LETTER C;Cf;0;BN;;;;;N;;;;; +E0044;TAG LATIN CAPITAL LETTER D;Cf;0;BN;;;;;N;;;;; +E0045;TAG LATIN CAPITAL LETTER E;Cf;0;BN;;;;;N;;;;; +E0046;TAG LATIN CAPITAL LETTER F;Cf;0;BN;;;;;N;;;;; +E0047;TAG LATIN CAPITAL LETTER G;Cf;0;BN;;;;;N;;;;; +E0048;TAG LATIN CAPITAL LETTER H;Cf;0;BN;;;;;N;;;;; +E0049;TAG LATIN CAPITAL LETTER I;Cf;0;BN;;;;;N;;;;; +E004A;TAG LATIN CAPITAL LETTER J;Cf;0;BN;;;;;N;;;;; +E004B;TAG LATIN CAPITAL LETTER K;Cf;0;BN;;;;;N;;;;; +E004C;TAG LATIN CAPITAL LETTER L;Cf;0;BN;;;;;N;;;;; +E004D;TAG LATIN CAPITAL LETTER M;Cf;0;BN;;;;;N;;;;; +E004E;TAG LATIN CAPITAL LETTER N;Cf;0;BN;;;;;N;;;;; +E004F;TAG LATIN CAPITAL LETTER O;Cf;0;BN;;;;;N;;;;; +E0050;TAG LATIN CAPITAL LETTER P;Cf;0;BN;;;;;N;;;;; +E0051;TAG LATIN CAPITAL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0052;TAG LATIN CAPITAL LETTER R;Cf;0;BN;;;;;N;;;;; +E0053;TAG LATIN CAPITAL LETTER S;Cf;0;BN;;;;;N;;;;; +E0054;TAG LATIN CAPITAL LETTER T;Cf;0;BN;;;;;N;;;;; +E0055;TAG LATIN CAPITAL LETTER U;Cf;0;BN;;;;;N;;;;; +E0056;TAG LATIN CAPITAL LETTER V;Cf;0;BN;;;;;N;;;;; +E0057;TAG LATIN CAPITAL LETTER W;Cf;0;BN;;;;;N;;;;; +E0058;TAG LATIN CAPITAL LETTER X;Cf;0;BN;;;;;N;;;;; +E0059;TAG LATIN CAPITAL LETTER Y;Cf;0;BN;;;;;N;;;;; +E005A;TAG LATIN CAPITAL LETTER Z;Cf;0;BN;;;;;N;;;;; +E005B;TAG LEFT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005C;TAG REVERSE SOLIDUS;Cf;0;BN;;;;;N;;;;; +E005D;TAG RIGHT SQUARE BRACKET;Cf;0;BN;;;;;N;;;;; +E005E;TAG CIRCUMFLEX ACCENT;Cf;0;BN;;;;;N;;;;; +E005F;TAG LOW LINE;Cf;0;BN;;;;;N;;;;; +E0060;TAG GRAVE ACCENT;Cf;0;BN;;;;;N;;;;; +E0061;TAG LATIN SMALL LETTER A;Cf;0;BN;;;;;N;;;;; +E0062;TAG LATIN SMALL LETTER B;Cf;0;BN;;;;;N;;;;; +E0063;TAG LATIN SMALL LETTER C;Cf;0;BN;;;;;N;;;;; +E0064;TAG LATIN SMALL LETTER D;Cf;0;BN;;;;;N;;;;; +E0065;TAG LATIN SMALL LETTER E;Cf;0;BN;;;;;N;;;;; +E0066;TAG LATIN SMALL LETTER F;Cf;0;BN;;;;;N;;;;; +E0067;TAG LATIN SMALL LETTER G;Cf;0;BN;;;;;N;;;;; +E0068;TAG LATIN SMALL LETTER H;Cf;0;BN;;;;;N;;;;; +E0069;TAG LATIN SMALL LETTER I;Cf;0;BN;;;;;N;;;;; +E006A;TAG LATIN SMALL LETTER J;Cf;0;BN;;;;;N;;;;; +E006B;TAG LATIN SMALL LETTER K;Cf;0;BN;;;;;N;;;;; +E006C;TAG LATIN SMALL LETTER L;Cf;0;BN;;;;;N;;;;; +E006D;TAG LATIN SMALL LETTER M;Cf;0;BN;;;;;N;;;;; +E006E;TAG LATIN SMALL LETTER N;Cf;0;BN;;;;;N;;;;; +E006F;TAG LATIN SMALL LETTER O;Cf;0;BN;;;;;N;;;;; +E0070;TAG LATIN SMALL LETTER P;Cf;0;BN;;;;;N;;;;; +E0071;TAG LATIN SMALL LETTER Q;Cf;0;BN;;;;;N;;;;; +E0072;TAG LATIN SMALL LETTER R;Cf;0;BN;;;;;N;;;;; +E0073;TAG LATIN SMALL LETTER S;Cf;0;BN;;;;;N;;;;; +E0074;TAG LATIN SMALL LETTER T;Cf;0;BN;;;;;N;;;;; +E0075;TAG LATIN SMALL LETTER U;Cf;0;BN;;;;;N;;;;; +E0076;TAG LATIN SMALL LETTER V;Cf;0;BN;;;;;N;;;;; +E0077;TAG LATIN SMALL LETTER W;Cf;0;BN;;;;;N;;;;; +E0078;TAG LATIN SMALL LETTER X;Cf;0;BN;;;;;N;;;;; +E0079;TAG LATIN SMALL LETTER Y;Cf;0;BN;;;;;N;;;;; +E007A;TAG LATIN SMALL LETTER Z;Cf;0;BN;;;;;N;;;;; +E007B;TAG LEFT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007C;TAG VERTICAL LINE;Cf;0;BN;;;;;N;;;;; +E007D;TAG RIGHT CURLY BRACKET;Cf;0;BN;;;;;N;;;;; +E007E;TAG TILDE;Cf;0;BN;;;;;N;;;;; +E007F;CANCEL TAG;Cf;0;BN;;;;;N;;;;; +E0100;VARIATION SELECTOR-17;Mn;0;NSM;;;;;N;;;;; +E0101;VARIATION SELECTOR-18;Mn;0;NSM;;;;;N;;;;; +E0102;VARIATION SELECTOR-19;Mn;0;NSM;;;;;N;;;;; +E0103;VARIATION SELECTOR-20;Mn;0;NSM;;;;;N;;;;; +E0104;VARIATION SELECTOR-21;Mn;0;NSM;;;;;N;;;;; +E0105;VARIATION SELECTOR-22;Mn;0;NSM;;;;;N;;;;; +E0106;VARIATION SELECTOR-23;Mn;0;NSM;;;;;N;;;;; +E0107;VARIATION SELECTOR-24;Mn;0;NSM;;;;;N;;;;; +E0108;VARIATION SELECTOR-25;Mn;0;NSM;;;;;N;;;;; +E0109;VARIATION SELECTOR-26;Mn;0;NSM;;;;;N;;;;; +E010A;VARIATION SELECTOR-27;Mn;0;NSM;;;;;N;;;;; +E010B;VARIATION SELECTOR-28;Mn;0;NSM;;;;;N;;;;; +E010C;VARIATION SELECTOR-29;Mn;0;NSM;;;;;N;;;;; +E010D;VARIATION SELECTOR-30;Mn;0;NSM;;;;;N;;;;; +E010E;VARIATION SELECTOR-31;Mn;0;NSM;;;;;N;;;;; +E010F;VARIATION SELECTOR-32;Mn;0;NSM;;;;;N;;;;; +E0110;VARIATION SELECTOR-33;Mn;0;NSM;;;;;N;;;;; +E0111;VARIATION SELECTOR-34;Mn;0;NSM;;;;;N;;;;; +E0112;VARIATION SELECTOR-35;Mn;0;NSM;;;;;N;;;;; +E0113;VARIATION SELECTOR-36;Mn;0;NSM;;;;;N;;;;; +E0114;VARIATION SELECTOR-37;Mn;0;NSM;;;;;N;;;;; +E0115;VARIATION SELECTOR-38;Mn;0;NSM;;;;;N;;;;; +E0116;VARIATION SELECTOR-39;Mn;0;NSM;;;;;N;;;;; +E0117;VARIATION SELECTOR-40;Mn;0;NSM;;;;;N;;;;; +E0118;VARIATION SELECTOR-41;Mn;0;NSM;;;;;N;;;;; +E0119;VARIATION SELECTOR-42;Mn;0;NSM;;;;;N;;;;; +E011A;VARIATION SELECTOR-43;Mn;0;NSM;;;;;N;;;;; +E011B;VARIATION SELECTOR-44;Mn;0;NSM;;;;;N;;;;; +E011C;VARIATION SELECTOR-45;Mn;0;NSM;;;;;N;;;;; +E011D;VARIATION SELECTOR-46;Mn;0;NSM;;;;;N;;;;; +E011E;VARIATION SELECTOR-47;Mn;0;NSM;;;;;N;;;;; +E011F;VARIATION SELECTOR-48;Mn;0;NSM;;;;;N;;;;; +E0120;VARIATION SELECTOR-49;Mn;0;NSM;;;;;N;;;;; +E0121;VARIATION SELECTOR-50;Mn;0;NSM;;;;;N;;;;; +E0122;VARIATION SELECTOR-51;Mn;0;NSM;;;;;N;;;;; +E0123;VARIATION SELECTOR-52;Mn;0;NSM;;;;;N;;;;; +E0124;VARIATION SELECTOR-53;Mn;0;NSM;;;;;N;;;;; +E0125;VARIATION SELECTOR-54;Mn;0;NSM;;;;;N;;;;; +E0126;VARIATION SELECTOR-55;Mn;0;NSM;;;;;N;;;;; +E0127;VARIATION SELECTOR-56;Mn;0;NSM;;;;;N;;;;; +E0128;VARIATION SELECTOR-57;Mn;0;NSM;;;;;N;;;;; +E0129;VARIATION SELECTOR-58;Mn;0;NSM;;;;;N;;;;; +E012A;VARIATION SELECTOR-59;Mn;0;NSM;;;;;N;;;;; +E012B;VARIATION SELECTOR-60;Mn;0;NSM;;;;;N;;;;; +E012C;VARIATION SELECTOR-61;Mn;0;NSM;;;;;N;;;;; +E012D;VARIATION SELECTOR-62;Mn;0;NSM;;;;;N;;;;; +E012E;VARIATION SELECTOR-63;Mn;0;NSM;;;;;N;;;;; +E012F;VARIATION SELECTOR-64;Mn;0;NSM;;;;;N;;;;; +E0130;VARIATION SELECTOR-65;Mn;0;NSM;;;;;N;;;;; +E0131;VARIATION SELECTOR-66;Mn;0;NSM;;;;;N;;;;; +E0132;VARIATION SELECTOR-67;Mn;0;NSM;;;;;N;;;;; +E0133;VARIATION SELECTOR-68;Mn;0;NSM;;;;;N;;;;; +E0134;VARIATION SELECTOR-69;Mn;0;NSM;;;;;N;;;;; +E0135;VARIATION SELECTOR-70;Mn;0;NSM;;;;;N;;;;; +E0136;VARIATION SELECTOR-71;Mn;0;NSM;;;;;N;;;;; +E0137;VARIATION SELECTOR-72;Mn;0;NSM;;;;;N;;;;; +E0138;VARIATION SELECTOR-73;Mn;0;NSM;;;;;N;;;;; +E0139;VARIATION SELECTOR-74;Mn;0;NSM;;;;;N;;;;; +E013A;VARIATION SELECTOR-75;Mn;0;NSM;;;;;N;;;;; +E013B;VARIATION SELECTOR-76;Mn;0;NSM;;;;;N;;;;; +E013C;VARIATION SELECTOR-77;Mn;0;NSM;;;;;N;;;;; +E013D;VARIATION SELECTOR-78;Mn;0;NSM;;;;;N;;;;; +E013E;VARIATION SELECTOR-79;Mn;0;NSM;;;;;N;;;;; +E013F;VARIATION SELECTOR-80;Mn;0;NSM;;;;;N;;;;; +E0140;VARIATION SELECTOR-81;Mn;0;NSM;;;;;N;;;;; +E0141;VARIATION SELECTOR-82;Mn;0;NSM;;;;;N;;;;; +E0142;VARIATION SELECTOR-83;Mn;0;NSM;;;;;N;;;;; +E0143;VARIATION SELECTOR-84;Mn;0;NSM;;;;;N;;;;; +E0144;VARIATION SELECTOR-85;Mn;0;NSM;;;;;N;;;;; +E0145;VARIATION SELECTOR-86;Mn;0;NSM;;;;;N;;;;; +E0146;VARIATION SELECTOR-87;Mn;0;NSM;;;;;N;;;;; +E0147;VARIATION SELECTOR-88;Mn;0;NSM;;;;;N;;;;; +E0148;VARIATION SELECTOR-89;Mn;0;NSM;;;;;N;;;;; +E0149;VARIATION SELECTOR-90;Mn;0;NSM;;;;;N;;;;; +E014A;VARIATION SELECTOR-91;Mn;0;NSM;;;;;N;;;;; +E014B;VARIATION SELECTOR-92;Mn;0;NSM;;;;;N;;;;; +E014C;VARIATION SELECTOR-93;Mn;0;NSM;;;;;N;;;;; +E014D;VARIATION SELECTOR-94;Mn;0;NSM;;;;;N;;;;; +E014E;VARIATION SELECTOR-95;Mn;0;NSM;;;;;N;;;;; +E014F;VARIATION SELECTOR-96;Mn;0;NSM;;;;;N;;;;; +E0150;VARIATION SELECTOR-97;Mn;0;NSM;;;;;N;;;;; +E0151;VARIATION SELECTOR-98;Mn;0;NSM;;;;;N;;;;; +E0152;VARIATION SELECTOR-99;Mn;0;NSM;;;;;N;;;;; +E0153;VARIATION SELECTOR-100;Mn;0;NSM;;;;;N;;;;; +E0154;VARIATION SELECTOR-101;Mn;0;NSM;;;;;N;;;;; +E0155;VARIATION SELECTOR-102;Mn;0;NSM;;;;;N;;;;; +E0156;VARIATION SELECTOR-103;Mn;0;NSM;;;;;N;;;;; +E0157;VARIATION SELECTOR-104;Mn;0;NSM;;;;;N;;;;; +E0158;VARIATION SELECTOR-105;Mn;0;NSM;;;;;N;;;;; +E0159;VARIATION SELECTOR-106;Mn;0;NSM;;;;;N;;;;; +E015A;VARIATION SELECTOR-107;Mn;0;NSM;;;;;N;;;;; +E015B;VARIATION SELECTOR-108;Mn;0;NSM;;;;;N;;;;; +E015C;VARIATION SELECTOR-109;Mn;0;NSM;;;;;N;;;;; +E015D;VARIATION SELECTOR-110;Mn;0;NSM;;;;;N;;;;; +E015E;VARIATION SELECTOR-111;Mn;0;NSM;;;;;N;;;;; +E015F;VARIATION SELECTOR-112;Mn;0;NSM;;;;;N;;;;; +E0160;VARIATION SELECTOR-113;Mn;0;NSM;;;;;N;;;;; +E0161;VARIATION SELECTOR-114;Mn;0;NSM;;;;;N;;;;; +E0162;VARIATION SELECTOR-115;Mn;0;NSM;;;;;N;;;;; +E0163;VARIATION SELECTOR-116;Mn;0;NSM;;;;;N;;;;; +E0164;VARIATION SELECTOR-117;Mn;0;NSM;;;;;N;;;;; +E0165;VARIATION SELECTOR-118;Mn;0;NSM;;;;;N;;;;; +E0166;VARIATION SELECTOR-119;Mn;0;NSM;;;;;N;;;;; +E0167;VARIATION SELECTOR-120;Mn;0;NSM;;;;;N;;;;; +E0168;VARIATION SELECTOR-121;Mn;0;NSM;;;;;N;;;;; +E0169;VARIATION SELECTOR-122;Mn;0;NSM;;;;;N;;;;; +E016A;VARIATION SELECTOR-123;Mn;0;NSM;;;;;N;;;;; +E016B;VARIATION SELECTOR-124;Mn;0;NSM;;;;;N;;;;; +E016C;VARIATION SELECTOR-125;Mn;0;NSM;;;;;N;;;;; +E016D;VARIATION SELECTOR-126;Mn;0;NSM;;;;;N;;;;; +E016E;VARIATION SELECTOR-127;Mn;0;NSM;;;;;N;;;;; +E016F;VARIATION SELECTOR-128;Mn;0;NSM;;;;;N;;;;; +E0170;VARIATION SELECTOR-129;Mn;0;NSM;;;;;N;;;;; +E0171;VARIATION SELECTOR-130;Mn;0;NSM;;;;;N;;;;; +E0172;VARIATION SELECTOR-131;Mn;0;NSM;;;;;N;;;;; +E0173;VARIATION SELECTOR-132;Mn;0;NSM;;;;;N;;;;; +E0174;VARIATION SELECTOR-133;Mn;0;NSM;;;;;N;;;;; +E0175;VARIATION SELECTOR-134;Mn;0;NSM;;;;;N;;;;; +E0176;VARIATION SELECTOR-135;Mn;0;NSM;;;;;N;;;;; +E0177;VARIATION SELECTOR-136;Mn;0;NSM;;;;;N;;;;; +E0178;VARIATION SELECTOR-137;Mn;0;NSM;;;;;N;;;;; +E0179;VARIATION SELECTOR-138;Mn;0;NSM;;;;;N;;;;; +E017A;VARIATION SELECTOR-139;Mn;0;NSM;;;;;N;;;;; +E017B;VARIATION SELECTOR-140;Mn;0;NSM;;;;;N;;;;; +E017C;VARIATION SELECTOR-141;Mn;0;NSM;;;;;N;;;;; +E017D;VARIATION SELECTOR-142;Mn;0;NSM;;;;;N;;;;; +E017E;VARIATION SELECTOR-143;Mn;0;NSM;;;;;N;;;;; +E017F;VARIATION SELECTOR-144;Mn;0;NSM;;;;;N;;;;; +E0180;VARIATION SELECTOR-145;Mn;0;NSM;;;;;N;;;;; +E0181;VARIATION SELECTOR-146;Mn;0;NSM;;;;;N;;;;; +E0182;VARIATION SELECTOR-147;Mn;0;NSM;;;;;N;;;;; +E0183;VARIATION SELECTOR-148;Mn;0;NSM;;;;;N;;;;; +E0184;VARIATION SELECTOR-149;Mn;0;NSM;;;;;N;;;;; +E0185;VARIATION SELECTOR-150;Mn;0;NSM;;;;;N;;;;; +E0186;VARIATION SELECTOR-151;Mn;0;NSM;;;;;N;;;;; +E0187;VARIATION SELECTOR-152;Mn;0;NSM;;;;;N;;;;; +E0188;VARIATION SELECTOR-153;Mn;0;NSM;;;;;N;;;;; +E0189;VARIATION SELECTOR-154;Mn;0;NSM;;;;;N;;;;; +E018A;VARIATION SELECTOR-155;Mn;0;NSM;;;;;N;;;;; +E018B;VARIATION SELECTOR-156;Mn;0;NSM;;;;;N;;;;; +E018C;VARIATION SELECTOR-157;Mn;0;NSM;;;;;N;;;;; +E018D;VARIATION SELECTOR-158;Mn;0;NSM;;;;;N;;;;; +E018E;VARIATION SELECTOR-159;Mn;0;NSM;;;;;N;;;;; +E018F;VARIATION SELECTOR-160;Mn;0;NSM;;;;;N;;;;; +E0190;VARIATION SELECTOR-161;Mn;0;NSM;;;;;N;;;;; +E0191;VARIATION SELECTOR-162;Mn;0;NSM;;;;;N;;;;; +E0192;VARIATION SELECTOR-163;Mn;0;NSM;;;;;N;;;;; +E0193;VARIATION SELECTOR-164;Mn;0;NSM;;;;;N;;;;; +E0194;VARIATION SELECTOR-165;Mn;0;NSM;;;;;N;;;;; +E0195;VARIATION SELECTOR-166;Mn;0;NSM;;;;;N;;;;; +E0196;VARIATION SELECTOR-167;Mn;0;NSM;;;;;N;;;;; +E0197;VARIATION SELECTOR-168;Mn;0;NSM;;;;;N;;;;; +E0198;VARIATION SELECTOR-169;Mn;0;NSM;;;;;N;;;;; +E0199;VARIATION SELECTOR-170;Mn;0;NSM;;;;;N;;;;; +E019A;VARIATION SELECTOR-171;Mn;0;NSM;;;;;N;;;;; +E019B;VARIATION SELECTOR-172;Mn;0;NSM;;;;;N;;;;; +E019C;VARIATION SELECTOR-173;Mn;0;NSM;;;;;N;;;;; +E019D;VARIATION SELECTOR-174;Mn;0;NSM;;;;;N;;;;; +E019E;VARIATION SELECTOR-175;Mn;0;NSM;;;;;N;;;;; +E019F;VARIATION SELECTOR-176;Mn;0;NSM;;;;;N;;;;; +E01A0;VARIATION SELECTOR-177;Mn;0;NSM;;;;;N;;;;; +E01A1;VARIATION SELECTOR-178;Mn;0;NSM;;;;;N;;;;; +E01A2;VARIATION SELECTOR-179;Mn;0;NSM;;;;;N;;;;; +E01A3;VARIATION SELECTOR-180;Mn;0;NSM;;;;;N;;;;; +E01A4;VARIATION SELECTOR-181;Mn;0;NSM;;;;;N;;;;; +E01A5;VARIATION SELECTOR-182;Mn;0;NSM;;;;;N;;;;; +E01A6;VARIATION SELECTOR-183;Mn;0;NSM;;;;;N;;;;; +E01A7;VARIATION SELECTOR-184;Mn;0;NSM;;;;;N;;;;; +E01A8;VARIATION SELECTOR-185;Mn;0;NSM;;;;;N;;;;; +E01A9;VARIATION SELECTOR-186;Mn;0;NSM;;;;;N;;;;; +E01AA;VARIATION SELECTOR-187;Mn;0;NSM;;;;;N;;;;; +E01AB;VARIATION SELECTOR-188;Mn;0;NSM;;;;;N;;;;; +E01AC;VARIATION SELECTOR-189;Mn;0;NSM;;;;;N;;;;; +E01AD;VARIATION SELECTOR-190;Mn;0;NSM;;;;;N;;;;; +E01AE;VARIATION SELECTOR-191;Mn;0;NSM;;;;;N;;;;; +E01AF;VARIATION SELECTOR-192;Mn;0;NSM;;;;;N;;;;; +E01B0;VARIATION SELECTOR-193;Mn;0;NSM;;;;;N;;;;; +E01B1;VARIATION SELECTOR-194;Mn;0;NSM;;;;;N;;;;; +E01B2;VARIATION SELECTOR-195;Mn;0;NSM;;;;;N;;;;; +E01B3;VARIATION SELECTOR-196;Mn;0;NSM;;;;;N;;;;; +E01B4;VARIATION SELECTOR-197;Mn;0;NSM;;;;;N;;;;; +E01B5;VARIATION SELECTOR-198;Mn;0;NSM;;;;;N;;;;; +E01B6;VARIATION SELECTOR-199;Mn;0;NSM;;;;;N;;;;; +E01B7;VARIATION SELECTOR-200;Mn;0;NSM;;;;;N;;;;; +E01B8;VARIATION SELECTOR-201;Mn;0;NSM;;;;;N;;;;; +E01B9;VARIATION SELECTOR-202;Mn;0;NSM;;;;;N;;;;; +E01BA;VARIATION SELECTOR-203;Mn;0;NSM;;;;;N;;;;; +E01BB;VARIATION SELECTOR-204;Mn;0;NSM;;;;;N;;;;; +E01BC;VARIATION SELECTOR-205;Mn;0;NSM;;;;;N;;;;; +E01BD;VARIATION SELECTOR-206;Mn;0;NSM;;;;;N;;;;; +E01BE;VARIATION SELECTOR-207;Mn;0;NSM;;;;;N;;;;; +E01BF;VARIATION SELECTOR-208;Mn;0;NSM;;;;;N;;;;; +E01C0;VARIATION SELECTOR-209;Mn;0;NSM;;;;;N;;;;; +E01C1;VARIATION SELECTOR-210;Mn;0;NSM;;;;;N;;;;; +E01C2;VARIATION SELECTOR-211;Mn;0;NSM;;;;;N;;;;; +E01C3;VARIATION SELECTOR-212;Mn;0;NSM;;;;;N;;;;; +E01C4;VARIATION SELECTOR-213;Mn;0;NSM;;;;;N;;;;; +E01C5;VARIATION SELECTOR-214;Mn;0;NSM;;;;;N;;;;; +E01C6;VARIATION SELECTOR-215;Mn;0;NSM;;;;;N;;;;; +E01C7;VARIATION SELECTOR-216;Mn;0;NSM;;;;;N;;;;; +E01C8;VARIATION SELECTOR-217;Mn;0;NSM;;;;;N;;;;; +E01C9;VARIATION SELECTOR-218;Mn;0;NSM;;;;;N;;;;; +E01CA;VARIATION SELECTOR-219;Mn;0;NSM;;;;;N;;;;; +E01CB;VARIATION SELECTOR-220;Mn;0;NSM;;;;;N;;;;; +E01CC;VARIATION SELECTOR-221;Mn;0;NSM;;;;;N;;;;; +E01CD;VARIATION SELECTOR-222;Mn;0;NSM;;;;;N;;;;; +E01CE;VARIATION SELECTOR-223;Mn;0;NSM;;;;;N;;;;; +E01CF;VARIATION SELECTOR-224;Mn;0;NSM;;;;;N;;;;; +E01D0;VARIATION SELECTOR-225;Mn;0;NSM;;;;;N;;;;; +E01D1;VARIATION SELECTOR-226;Mn;0;NSM;;;;;N;;;;; +E01D2;VARIATION SELECTOR-227;Mn;0;NSM;;;;;N;;;;; +E01D3;VARIATION SELECTOR-228;Mn;0;NSM;;;;;N;;;;; +E01D4;VARIATION SELECTOR-229;Mn;0;NSM;;;;;N;;;;; +E01D5;VARIATION SELECTOR-230;Mn;0;NSM;;;;;N;;;;; +E01D6;VARIATION SELECTOR-231;Mn;0;NSM;;;;;N;;;;; +E01D7;VARIATION SELECTOR-232;Mn;0;NSM;;;;;N;;;;; +E01D8;VARIATION SELECTOR-233;Mn;0;NSM;;;;;N;;;;; +E01D9;VARIATION SELECTOR-234;Mn;0;NSM;;;;;N;;;;; +E01DA;VARIATION SELECTOR-235;Mn;0;NSM;;;;;N;;;;; +E01DB;VARIATION SELECTOR-236;Mn;0;NSM;;;;;N;;;;; +E01DC;VARIATION SELECTOR-237;Mn;0;NSM;;;;;N;;;;; +E01DD;VARIATION SELECTOR-238;Mn;0;NSM;;;;;N;;;;; +E01DE;VARIATION SELECTOR-239;Mn;0;NSM;;;;;N;;;;; +E01DF;VARIATION SELECTOR-240;Mn;0;NSM;;;;;N;;;;; +E01E0;VARIATION SELECTOR-241;Mn;0;NSM;;;;;N;;;;; +E01E1;VARIATION SELECTOR-242;Mn;0;NSM;;;;;N;;;;; +E01E2;VARIATION SELECTOR-243;Mn;0;NSM;;;;;N;;;;; +E01E3;VARIATION SELECTOR-244;Mn;0;NSM;;;;;N;;;;; +E01E4;VARIATION SELECTOR-245;Mn;0;NSM;;;;;N;;;;; +E01E5;VARIATION SELECTOR-246;Mn;0;NSM;;;;;N;;;;; +E01E6;VARIATION SELECTOR-247;Mn;0;NSM;;;;;N;;;;; +E01E7;VARIATION SELECTOR-248;Mn;0;NSM;;;;;N;;;;; +E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;; +E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;; +E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;; +E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;; +E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;; +E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;; +E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;; +E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;; +F0000;;Co;0;L;;;;;N;;;;; +FFFFD;;Co;0;L;;;;;N;;;;; +100000;;Co;0;L;;;;;N;;;;; +10FFFD;;Co;0;L;;;;;N;;;;; diff --git a/tests/core/assets/UCD/license.txt b/tests/core/assets/UCD/license.txt new file mode 100644 index 000000000..56da58912 --- /dev/null +++ b/tests/core/assets/UCD/license.txt @@ -0,0 +1,39 @@ +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2026 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. diff --git a/tests/core/assets/Wycheproof/.gitignore b/tests/core/assets/Wycheproof/.gitignore new file mode 100644 index 000000000..94a2dd146 --- /dev/null +++ b/tests/core/assets/Wycheproof/.gitignore @@ -0,0 +1 @@ +*.json \ No newline at end of file diff --git a/tests/core/compress/test_core_compress.odin b/tests/core/compress/test_core_compress.odin index 1f3481f35..d18a03d8c 100644 --- a/tests/core/compress/test_core_compress.odin +++ b/tests/core/compress/test_core_compress.odin @@ -2,7 +2,7 @@ package test_core_compress /* Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. diff --git a/tests/core/container/test_core_handle_map.odin b/tests/core/container/test_core_handle_map.odin new file mode 100644 index 000000000..1753ee91b --- /dev/null +++ b/tests/core/container/test_core_handle_map.odin @@ -0,0 +1,141 @@ +package test_core_container + +import hm "core:container/handle_map" +import "core:container/xar" +import "core:testing" + +Item :: struct { + v: int, + p: ^Item, + handle: hm.Handle32, + my_idx: u16, +} + +@test +test_dynamic_handle_map :: proc(t: ^testing.T) { + dhm: hm.Dynamic_Handle_Map(Item, hm.Handle32) + hm.dynamic_init(&dhm, context.allocator) + defer hm.dynamic_destroy(&dhm) + + items: [dynamic]Item + defer delete(items) + + N :: 512 + for i in 1..=N { + h, add_err := hm.dynamic_add(&dhm, Item{v = i * 10 + 1}) + assert(add_err == nil) + + item := hm.dynamic_get(&dhm, h) + item.handle = h + item.p = item + item.my_idx = h.idx + + append(&items, item^) + } + + testing.expect(t, hm.dynamic_len(dhm) == N) + testing.expect(t, hm.dynamic_cap(dhm) >= N) + + for v in items { + item := hm.dynamic_get(&dhm, v.handle) + assert(item^ == v) + + // Remove half of the items + if item.handle.idx & 1 == 0 { + found, found_err := hm.dynamic_remove(&dhm, v.handle) + assert(found && found_err == nil) + + // These removed handles should no longer be valid + assert(!hm.dynamic_is_valid(&dhm, v.handle)) + } else { + // Non-removed handles should still be valid + assert(hm.dynamic_is_valid(&dhm, v.handle)) + } + } + + testing.expect(t, hm.dynamic_len(dhm) == N / 2) + testing.expect(t, hm.dynamic_cap(dhm) >= N / 2) + testing.expect(t, xar.len(dhm.unused_items) == N / 2) + + it := hm.dynamic_iterator_make(&dhm) + for v, handle in hm.iterate(&it) { + assert(v.handle.idx & 1 == 1) + assert(hm.dynamic_is_valid(&dhm, handle)) + + item := hm.dynamic_get(&dhm, handle) + assert(item.my_idx == v.handle.idx) + } + + for i in 1..=N / 2 { + h, add_err := hm.dynamic_add(&dhm, Item{v = i * 10 + 1}) + assert(add_err == nil) + assert(h.gen == 2) + } + + hm.dynamic_clear(&dhm) + testing.expect(t, hm.dynamic_len(dhm) == 0) + testing.expect(t, hm.dynamic_cap(dhm) >= N) +} + +test_static_handle_map :: proc(t: ^testing.T) { + N :: 512 + + shm: hm.Static_Handle_Map(N, Item, hm.Handle32) + + items: [dynamic]Item + defer delete(items) + + + for i in 1..=N { + h, add_ok := hm.static_add(&shm, Item{v = i * 10 + 1}) + assert(add_ok) + + item := hm.static_get(&shm, h) + item.handle = h + item.p = item + item.my_idx = h.idx + + append(&items, item^) + } + + testing.expect(t, hm.static_len(shm) == N) + testing.expect(t, hm.static_cap(shm) >= N) + + for v in items { + item := hm.static_get(&shm, v.handle) + assert(item^ == v) + + // Remove half of the items + if item.handle.idx & 1 == 0 { + assert(hm.static_remove(&shm, v.handle)) + + // These removed handles should no longer be valid + assert(!hm.static_is_valid(shm, v.handle)) + } else { + // Non-removed handles should still be valid + assert(hm.static_is_valid(shm, v.handle)) + } + } + + testing.expect(t, hm.static_len(shm) == N / 2) + testing.expect(t, hm.static_cap(shm) >= N / 2) + + it := hm.static_iterator_make(&shm) + for v, handle in hm.iterate(&it) { + assert(v.handle.idx & 1 == 1) + assert(hm.static_is_valid(shm, handle)) + + item := hm.static_get(&shm, handle) + assert(item.my_idx == v.handle.idx) + } + + for i in 1..=N / 2 { + h, add_ok := hm.static_add(&shm, Item{v = i * 10 + 1}) + assert(add_ok) + assert(h.gen == 2) + } + + hm.static_clear(&shm) + testing.expect(t, hm.static_len(shm) == 0) + testing.expect(t, hm.static_cap(shm) == N) +} \ No newline at end of file diff --git a/tests/core/container/test_core_priority_queue.odin b/tests/core/container/test_core_priority_queue.odin new file mode 100644 index 000000000..417056d48 --- /dev/null +++ b/tests/core/container/test_core_priority_queue.odin @@ -0,0 +1,113 @@ +package test_core_container + +import "base:runtime" +import pq "core:container/priority_queue" +import "core:math/rand" +import "core:testing" + +@test +test_priority_queue :: proc(t: ^testing.T) { + q: pq.Priority_Queue(int) + pq.init(&q, proc(a, b: int) -> bool { + return a < b + }, pq.default_swap_proc(int)) + defer pq.destroy(&q) + + assert(pq.cap(q) == pq.DEFAULT_CAPACITY) + + pq.push(&q, 42) + assert(pq.len(q) == 1) + assert(pq.peek(q) == 42) + + v := pq.pop(&q) + assert(v == 42) + assert(pq.len(q) == 0) + + ok: bool + v, ok = pq.peek_safe(q) + assert(v == 0 && ok == false) + + v, ok = pq.pop_safe(&q) + assert(v == 0 && ok == false) + + N :: 15 + for _ in 0.. 0 { + v = pq.pop(&q) + assert(v >= last) + last = v + } + + vals := []int{6, 15, 3, 9, 12} + for _v in vals { + pq.push(&q, _v) + } + // Break ordering and fix it + q.queue[3] = 42 + pq.fix(&q, 3) + + last = 0 + for pq.len(q) > 0 { + v = pq.pop(&q) + assert(v >= last) + last = v + } + + assert(pq.len(q) == 0) + + for _v in vals { + pq.push(&q, _v) + } + + // Break ordering again, but this time delete that index + q.queue[3] = 42 + v, ok = pq.remove(&q, 3) + assert(v == 42 && ok == true) + + last = 0 + for pq.len(q) > 0 { + v = pq.pop(&q) + assert(v >= last && v != 42) + last = v + } +} + +@(test) +test_pq_init_from_dynamic_array :: proc(t: ^testing.T) { + N :: 50_000 + + arr := make_dynamic_array_len_cap([dynamic]u64, N, N, context.allocator) + assert(runtime.random_generator_read_ptr(context.random_generator, raw_data(arr), N * size_of(u64))) + + q: pq.Priority_Queue(u64) + pq.init_from_dynamic_array( + pq = &q, + queue = arr, + less = proc(a, b: u64) -> bool { return a < b }, + swap = pq.default_swap_proc(u64), + ) + defer pq.destroy(&q) + + assert(pq.len(q) == N) + + last: u64 + for pq.len(q) > 0 { + v := pq.pop(&q) + assert(v >= last) + last = v + } + + assert(pq.len(q) == 0) + assert(pq.cap(q) == N) + + pq.reserve(&q, N + 12) + assert(pq.cap(q) == N + 12) + +} \ No newline at end of file diff --git a/tests/core/container/test_core_queue.odin b/tests/core/container/test_core_queue.odin new file mode 100644 index 000000000..56d2e1dca --- /dev/null +++ b/tests/core/container/test_core_queue.odin @@ -0,0 +1,157 @@ +package test_core_container + +import "base:runtime" +import "core:container/queue" +import "core:testing" + +@test +test_queue :: proc(t: ^testing.T) { + buf := [?]int{99, 99, 99, 99, 99} + q: queue.Queue(int) + + testing.expect(t, queue.init_from_slice(&q, buf[:])) + testing.expect_value(t, queue.reserve(&q, len(buf)), nil) + + queue.push_back(&q, 1) + queue.push_back_elems(&q, 2, 3) + queue.push_front(&q, 0) + + // { + // data = [1, 2, 3, 99, 0], + // len = 4, + // offset = 4, + // } + + testing.expect_value(t, queue.back(&q), 3) + testing.expect_value(t, queue.back_ptr(&q), &buf[2]) + testing.expect_value(t, queue.front(&q), 0) + testing.expect_value(t, queue.front_ptr(&q), &buf[4]) + + queue.get(&q, 3) + + for i in 0..<4 { + testing.expect_value(t, queue.get(&q, i), i) + queue.set(&q, i, i) + } + testing.expect_value(t, queue.get_ptr(&q, 3), &buf[2]) + + queue.consume_back(&q, 1) + queue.consume_front(&q, 1) + testing.expect_value(t, queue.pop_back(&q), 2) + v, ok := queue.pop_back_safe(&q) + testing.expect_value(t, v, 1) + testing.expect_value(t, ok, true) + + + // Test `init_with_contents`. + buf2 := [?]int{99, 3, 5} + + queue.init_with_contents(&q, buf2[:]) + push_ok, push_err := queue.push_back(&q, 1) + testing.expect(t, !push_ok) + testing.expect_value(t, push_err, runtime.Allocator_Error.Out_Of_Memory) + push_ok, push_err = queue.push_front(&q, 2) + testing.expect(t, !push_ok) + testing.expect_value(t, push_err, runtime.Allocator_Error.Out_Of_Memory) + + pop_front_v, pop_front_ok := queue.pop_front_safe(&q) + testing.expect(t, pop_front_ok) + testing.expect_value(t, pop_front_v, 99) + + // Re-initialization. + queue.init(&q, 0) + defer queue.destroy(&q) + + queue.push_back_elems(&q, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) + testing.expect_value(t, queue.len(q), 18) + queue.push_back_elems(&q, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) + testing.expect_value(t, queue.len(q), 36) + + for i in 1..=18 { + testing.expect_value(t, queue.pop_front(&q), i) + } + for i in 1..=18 { + testing.expect_value(t, queue.pop_front(&q), i) + } +} + +@test +test_queue_grow_edge_case :: proc(t: ^testing.T) { + // Create a situation in which we trigger `q.offset + q.len > n` inside + // `_grow` to evaluate the `copy` behavior. + qq: queue.Queue(int) + queue.init(&qq, 0) + defer queue.destroy(&qq) + + queue.push_back_elems(&qq, 1, 2, 3, 4, 5, 6, 7) + testing.expect_value(t, queue.pop_front(&qq), 1) + testing.expect_value(t, queue.pop_front(&qq), 2) + testing.expect_value(t, queue.pop_front(&qq), 3) + queue.push_back(&qq, 8) + queue.push_back(&qq, 9) + + testing.expect_value(t, qq.len, 6) + testing.expect_value(t, qq.offset, 3) + testing.expect_value(t, len(qq.data), 8) // value contingent on smallest dynamic array capacity on first allocation + + queue.reserve(&qq, 16) + + testing.expect_value(t, queue.len(qq), 6) + for i in 4..=9 { + testing.expect_value(t, queue.pop_front(&qq), i) + } + testing.expect_value(t, queue.len(qq), 0) + + // If we made it to this point without failure, the queue should have + // copied the data into the right place after resizing the backing array. +} + +@test +test_queue_grow_edge_case_2 :: proc(t: ^testing.T) { + // Create a situation in which we trigger `insert_from + insert_to > sz` inside `push_back_elems` + // to evaluate the modified `insert_to` behavior. + qq: queue.Queue(int) + queue.init(&qq, 8) + defer queue.destroy(&qq) + + queue.push_back_elems(&qq, -1, -2, -3, -4, -5, -6, -7) + queue.consume_front(&qq, 3) + queue.push_back_elems(&qq, -8, -9, -10) + + queue.push_back_elems(&qq, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + testing.expect_value(t, queue.len(qq), 17) + for i in 4..=10 { + testing.expect_value(t, queue.pop_front(&qq), -i) + } + for i in 1..=10 { + testing.expect_value(t, queue.pop_front(&qq), i) + } + testing.expect_value(t, queue.len(qq), 0) +} + +@test +test_queue_shrink :: proc(t: ^testing.T) { + qq: queue.Queue(int) + queue.init(&qq, 8) + defer queue.destroy(&qq) + + queue.push_back_elems(&qq, -1, -2, -3, -4, -5, -6, -7) + queue.consume_front(&qq, 3) + queue.push_back_elems(&qq, -8, -9, -10) + + queue.push_back_elems(&qq, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + queue.shrink(&qq) + queue.consume_front(&qq, 7) + queue.shrink(&qq) + + for i in 1..=10 { + testing.expect_value(t, queue.pop_front(&qq), i) + } + + buf: [1]int + qq_backed: queue.Queue(int) + queue.init_from_slice(&qq_backed, buf[:]) + queue.shrink(&qq_backed) +} diff --git a/tests/core/container/test_core_rbtree.odin b/tests/core/container/test_core_rbtree.odin index d220b7ed6..78d710b7f 100644 --- a/tests/core/container/test_core_rbtree.odin +++ b/tests/core/container/test_core_rbtree.odin @@ -4,22 +4,15 @@ import rb "core:container/rbtree" import "core:math/rand" import "core:testing" import "base:intrinsics" -import "core:mem" import "core:slice" import "core:log" test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { - track: mem.Tracking_Allocator - mem.tracking_allocator_init(&track, context.allocator) - track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array - defer mem.tracking_allocator_destroy(&track) - context.allocator = mem.tracking_allocator(&track) - log.infof("Testing Red-Black Tree($Key=%v,$Value=%v) using random seed %v.", type_info_of(Key), type_info_of(Value), t.seed) tree: rb.Tree(Key, Value) rb.init(&tree) - testing.expect(t, rb.len(&tree) == 0, "empty: len should be 0") + testing.expect(t, rb.len(tree) == 0, "empty: len should be 0") testing.expect(t, rb.first(&tree) == nil, "empty: first should be nil") testing.expect(t, rb.last(&tree) == nil, "empty: last should be nil") iter := rb.iterator(&tree, .Forward) @@ -48,7 +41,7 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { } entry_count := len(inserted_map) - testing.expect(t, rb.len(&tree) == entry_count, "insert: len after") + testing.expect(t, rb.len(tree) == entry_count, "insert: len after") validate_rbtree(t, &tree) first := rb.first(&tree) @@ -58,8 +51,8 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { // Ensure that all entries can be found. for k, v in inserted_map { - testing.expect(t, v == rb.find(&tree, k), "Find(): Node") - testing.expect(t, k == v.key, "Find(): Node key") + testing.expect(t, v == rb.find(tree, k), "Find(): Node") + testing.expect(t, k == v.key, "Find(): Node key") } // Test the forward/backward iterators. @@ -97,17 +90,17 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { (^int)(user_data)^ -= 1 } for k, i in inserted_keys { - node := rb.find(&tree, k) + node := rb.find(tree, k) testing.expect(t, node != nil, "remove: find (pre)") ok := rb.remove(&tree, k) testing.expect(t, ok, "remove: succeeds") - testing.expect(t, entry_count - (i + 1) == rb.len(&tree), "remove: len (post)") + testing.expect(t, entry_count - (i + 1) == rb.len(tree), "remove: len (post)") validate_rbtree(t, &tree) - testing.expect(t, nil == rb.find(&tree, k), "remove: find (post") + testing.expect(t, nil == rb.find(tree, k), "remove: find (post") } - testing.expect(t, rb.len(&tree) == 0, "remove: len should be 0") + testing.expect(t, rb.len(tree) == 0, "remove: len should be 0") testing.expectf(t, callback_count == 0, "remove: on_remove should've been called %v times, it was %v", entry_count, callback_count) testing.expect(t, rb.first(&tree) == nil, "remove: first should be nil") testing.expect(t, rb.last(&tree) == nil, "remove: last should be nil") @@ -129,28 +122,25 @@ test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { ok = rb.iterator_remove(&iter) testing.expect(t, !ok, "iterator/remove: redundant removes should fail") - testing.expect(t, rb.find(&tree, k) == nil, "iterator/remove: node should be gone") + testing.expect(t, rb.find(tree, k) == nil, "iterator/remove: node should be gone") testing.expect(t, rb.iterator_get(&iter) == nil, "iterator/remove: get should return nil") // Ensure that iterator_next still works. node, ok = rb.iterator_next(&iter) - testing.expect(t, ok == (rb.len(&tree) > 0), "iterator/remove: next should return false") + testing.expect(t, ok == (rb.len(tree) > 0), "iterator/remove: next should return false") testing.expect(t, node == rb.first(&tree), "iterator/remove: next should return first") validate_rbtree(t, &tree) } - testing.expect(t, rb.len(&tree) == entry_count - 1, "iterator/remove: len should drop by 1") + testing.expect(t, rb.len(tree) == entry_count - 1, "iterator/remove: len should drop by 1") rb.destroy(&tree) - testing.expect(t, rb.len(&tree) == 0, "destroy: len should be 0") + testing.expect(t, rb.len(tree) == 0, "destroy: len should be 0") testing.expectf(t, callback_count == 0, "remove: on_remove should've been called %v times, it was %v", entry_count, callback_count) // print_tree_node(tree._root) delete(inserted_map) delete(inserted_keys) - testing.expectf(t, len(track.allocation_map) == 0, "Expected 0 leaks, have %v", len(track.allocation_map)) - testing.expectf(t, len(track.bad_free_array) == 0, "Expected 0 bad frees, have %v", len(track.bad_free_array)) - return } @(test) diff --git a/tests/core/container/test_core_small_array.odin b/tests/core/container/test_core_small_array.odin index 21f35f112..86342c6a5 100644 --- a/tests/core/container/test_core_small_array.odin +++ b/tests/core/container/test_core_small_array.odin @@ -54,6 +54,28 @@ test_small_array_push_back_elems :: proc(t: ^testing.T) { testing.expect(t, slice_equal(small_array.slice(&array), []int { 1, 2 })) } +@(test) +test_small_array_resize :: proc(t: ^testing.T) { + + array: small_array.Small_Array(4, int) + + for i in 0..<4 { + small_array.append(&array, i+1) + } + testing.expect(t, slice_equal(small_array.slice(&array), []int{1, 2, 3, 4}), "Expected to initialize the array with 1, 2, 3, 4") + + small_array.clear(&array) + testing.expect(t, slice_equal(small_array.slice(&array), []int{}), "Expected to clear the array") + + small_array.non_zero_resize(&array, 4) + testing.expect(t, slice_equal(small_array.slice(&array), []int{1, 2, 3, 4}), "Expected non_zero_resize to set length 4 with previous values") + + small_array.clear(&array) + small_array.resize(&array, 4) + testing.expect(t, slice_equal(small_array.slice(&array), []int{0, 0, 0, 0}), "Expected resize to set length 4 with zeroed values") +} + + slice_equal :: proc(a, b: []int) -> bool { if len(a) != len(b) { return false diff --git a/tests/core/container/test_core_xar.odin b/tests/core/container/test_core_xar.odin new file mode 100644 index 000000000..ee9318097 --- /dev/null +++ b/tests/core/container/test_core_xar.odin @@ -0,0 +1,39 @@ +package test_core_container + +import "core:container/xar" +import "core:testing" + +@test +test_xar_pointer_stability :: proc(t: ^testing.T) { + Value :: struct { + v: int, + p: ^int, + } + + x: xar.Array(int, 4) + defer xar.destroy(&x) + + values: [dynamic]Value + defer delete(values) + + N :: 512 + for i in 1..=N { + v := i * 10 + 1 + xar.push_back(&x, v) + ptr := xar.get_ptr(&x, i - 1) + append(&values, Value{v = v, p = ptr}) + } + + assert(xar.len(x) == N) + assert(xar.cap(x) >= N) + + for value, i in values { + ptr := xar.get_ptr(&x, i) + assert(ptr == value.p) + assert(ptr^ == value.v) + } + + xar.clear(&x) + assert(xar.len(x) == 0) + assert(xar.cap(x) >= N) +} \ No newline at end of file diff --git a/tests/core/crypto/common/common.odin b/tests/core/crypto/common/common.odin new file mode 100644 index 000000000..8cef8ce86 --- /dev/null +++ b/tests/core/crypto/common/common.odin @@ -0,0 +1,25 @@ +package test_crypto_common + +import "core:bytes" +import "core:encoding/hex" + +// Common helpers for cryptography tests. + +Hex_Bytes :: string + +hexbytes_compare :: proc(x: Hex_Bytes, b: []byte, allocator := context.allocator) -> bool { + dst := hexbytes_decode(x) + defer delete(dst) + + return bytes.equal(dst, b) +} + +hexbytes_decode :: proc(x: Hex_Bytes, allocator := context.allocator) -> []byte { + dst, ok := hex.decode(transmute([]byte)(x), allocator) + if !ok { + panic("Hex_Bytes: invalid hex encoding") + } + + return dst +} + diff --git a/tests/core/crypto/noise/main.odin b/tests/core/crypto/noise/main.odin new file mode 100644 index 000000000..e97dbfe1e --- /dev/null +++ b/tests/core/crypto/noise/main.odin @@ -0,0 +1,440 @@ +package test_noise + +import "core:crypto/ecdh" +import "core:crypto/noise" +import "core:log" +import "core:mem" +import "core:os" +import "core:strings" +import "core:testing" + +import "../common" + +ARENA_SIZE :: 8 * 1024 * 1024 + +BASE_PATH :: ODIN_ROOT + "tests/core/assets/Noise" + +@(test) +print_test_vector_path :: proc(t: ^testing.T) { + log.infof("noise path: %s", BASE_PATH) +} + +@(test) +test_vectors_snow :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("noise/snow: starting") + + F :: "snow.txt" + fn, _ := os.join_path([]string{BASE_PATH, F}, context.allocator) + defer delete(fn) + test_vectors: Test_Vectors + testing.expectf(t, load(&test_vectors, fn), "unable to load {}", fn) + + run_test_vectors(t, F, &test_vectors) +} + +@(test) +test_vectors_noise_c_basic :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("noise/noise-c-basic: starting") + + F :: "noise-c-basic.txt" + fn, _ := os.join_path([]string{BASE_PATH, F}, context.allocator) + defer delete(fn) + test_vectors: Test_Vectors + testing.expectf(t, load(&test_vectors, fn), "unable to load {}", fn) + + run_test_vectors(t, F, &test_vectors) +} + +@(test) +test_vectors_cacophony :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("noise/cacophony: starting") + + F :: "cacophony.txt" + fn, _ := os.join_path([]string{BASE_PATH, F}, context.allocator) + defer delete(fn) + test_vectors: Test_Vectors + testing.expectf(t, load(&test_vectors, fn), "unable to load {}", fn) + + run_test_vectors(t, F, &test_vectors) +} + +run_test_vectors :: proc(t: ^testing.T, f: string, tvs: ^Test_Vectors) { + num_ran, num_passed, num_failed, num_skipped: int + tv_loop: for &v, i in tvs.vectors { + num_ran += 1 + + protocol_name: string + switch { + case v.protocol_name != "": + protocol_name = v.protocol_name + case v.name != "": + // Old test vector format used by the C impl. + v.protocol_name = v.name + protocol_name = v.name + } + + // Skip unsupported test vectors + if v.fail { + num_skipped += 1 + log.debugf("%s[%d]: %s - skipped, fail tests not supported", f, i, protocol_name) + continue + } + if v.fallback { + num_skipped += 1 + log.debugf("%s[%d]: %s - skipped, fallback patterns not supported", f, i, protocol_name) + continue + } + if strings.has_prefix(protocol_name, "NoisePSK") { + num_skipped += 1 + log.debugf("%s[%d]: %s - skipped, Old PSK not supported", f, i, protocol_name) + continue + } + if len(v.init_psks) > 1 || len(v.resp_psks) > 1 { + num_skipped += 1 + log.debugf("%s[%d]: %s - skipped, Multi-PSK not supported", f, i, protocol_name) + continue + } + + // Initialize Handshake_Statuses + pattern, dh, _, _, status := noise.split_protocol_string(protocol_name) + if !testing.expectf(t, status == .Ok, "%s[%d]: failed to parse protocol '%s': %v", f, i, protocol_name, status) { + num_failed += 1 + continue + } + ini_hs, res_hs: noise.Handshake_State + if !testing.expect(t, handshake_states_from_tv(t, &ini_hs, &res_hs, &v, dh, f, i)) { + num_failed += 1 + continue + } + defer noise.handshake_reset(&ini_hs) + defer noise.handshake_reset(&res_hs) + + // Play back the messages + if !testing.expectf( + t, + replay_messages_from_tv_rw(t, &ini_hs, &v, pattern, f), + "%s[%d]: %s - failed to playback messages (initiator)", f, i, protocol_name, + ) { + num_failed += 1 + continue + } + if !testing.expectf( + t, + replay_messages_from_tv_rw(t, &res_hs, &v, pattern, f), + "%s[%d]: %s - failed to playback messages (responder)", f, i, protocol_name, + ) { + num_failed += 1 + continue + } + + // Check handshake hash/peer identities. + if v.handshake_hash != "" { + ini_hash, _ := noise.handshake_hash(&ini_hs) + res_hash, _ := noise.handshake_hash(&res_hs) + if !testing.expectf( + t, + common.hexbytes_compare(v.handshake_hash, ini_hash), + "%s[%d]: %s - invalid initiator handshake hash: %x expected: %s", f, i, protocol_name, ini_hash, v.handshake_hash, + ) { + num_failed += 1 + continue + } + if !testing.expectf( + t, + common.hexbytes_compare(v.handshake_hash, res_hash), + "%s[%d]: %s - invalid responder handshake hash: %x expected: %s", f, i, protocol_name, res_hash, v.handshake_hash, + ) { + num_failed += 1 + continue + } + } + if ecdh.curve(&ini_hs.s) != .Invalid { + pub_key, _ := noise.handshake_peer_identity(&res_hs) + if !testing.expectf( + t, + pub_key != nil && ecdh.public_key_equal(&ini_hs.s._pub_key, pub_key), + "%s[%d]: %s - invalid initiator static public key known by responder", f, i, protocol_name, + ) { + num_failed += 1 + continue + } + } + if ecdh.curve(&res_hs.s) != .Invalid { + pub_key, _ := noise.handshake_peer_identity(&ini_hs) + if !testing.expectf( + t, + pub_key != nil && ecdh.public_key_equal(&res_hs.s._pub_key, pub_key), + "%s[%d]: %s - invalid responder static public key known by initiator", f, i, protocol_name, + ) { + num_failed += 1 + continue + } + } + + log.debugf("%s[%d]: %s - Passed", f, i, protocol_name) + num_passed += 1 + } + + assert(num_ran == len(tvs.vectors)) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s: ran %d, passed %d, failed %d, skipped %d", + f, + num_ran, + num_passed, + num_failed, + num_skipped, + ) +} + +handshake_states_from_tv :: proc( + t: ^testing.T, + ini_hs, res_hs: ^noise.Handshake_State, + v: ^Vector, + dh: ecdh.Curve, + f: string, + i: int, +) -> bool { + protocol_name := v.protocol_name + + ini_static, ini_ephemeral: ecdh.Private_Key + res_static, res_ephemeral: ecdh.Private_Key + ini_res_static, res_ini_static: ecdh.Public_Key + + ini_s, ini_e: ^ecdh.Private_Key + ini_s_p, ini_e_p: ^ecdh.Public_Key + ini_r_s: ^ecdh.Public_Key + if len(v.init_static) != 0 { + if !testing.expectf( + t, + ecdh.private_key_set_bytes(&ini_static, dh, common.hexbytes_decode(v.init_static)), + "%s[%d]: %s - failed to parse init_static", f, i, protocol_name, + ) { + return false + } + ini_s = &ini_static + ini_s_p = &ini_s._pub_key + } + if len(v.init_ephemeral) != 0 { + if !testing.expectf( + t, + ecdh.private_key_set_bytes(&ini_ephemeral, dh, common.hexbytes_decode(v.init_ephemeral)), + "%s[%d]: %s - failed to parse init_ephemeral", f, i, protocol_name, + ) { + return false + } + ini_e = &ini_ephemeral + ini_e_p = &ini_e._pub_key + } + if len(v.init_remote_static) != 0 { + if !testing.expectf( + t, + ecdh.public_key_set_bytes(&ini_res_static, dh, common.hexbytes_decode(v.init_remote_static)), + "%s[%d]: %s - failed to parse init_remote_static", f, i, protocol_name, + ) { + return false + } + ini_r_s = &ini_res_static + } + + res_s, res_e: ^ecdh.Private_Key + res_s_p, res_e_p: ^ecdh.Public_Key + res_i_s: ^ecdh.Public_Key + if len(v.resp_static) != 0 { + if !testing.expectf( + t, + ecdh.private_key_set_bytes(&res_static, dh, common.hexbytes_decode(v.resp_static)), + "%s[%d]: %s - failed to parse resp_static", f, i, protocol_name, + ) { + return false + } + res_s = &res_static + res_s_p = &res_s._pub_key + } + if len(v.resp_ephemeral) != 0 { + if !testing.expectf( + t, + ecdh.private_key_set_bytes(&res_ephemeral, dh, common.hexbytes_decode(v.resp_ephemeral)), + "%s[%d]: %s - failed to parse resp_ephemeral", f, i, protocol_name, + ) { + return false + } + res_e = &res_ephemeral + res_e_p = &res_e._pub_key + } + if len(v.resp_remote_static) != 0 { + if !testing.expectf( + t, + ecdh.public_key_set_bytes(&res_ini_static, dh, common.hexbytes_decode(v.resp_remote_static)), + "%s[%d]: %s - failed to parse remote_init_static", f, i, protocol_name, + ) { + return false + } + res_i_s = &res_ini_static + } + + ini_psk, res_psk: []byte + if len(v.init_psks) > 0 { + ini_psk = common.hexbytes_decode(v.init_psks[0]) + } + if len(v.resp_psks) > 0 { + res_psk = common.hexbytes_decode(v.resp_psks[0]) + } + + status := noise.handshake_init( + ini_hs, + true, + common.hexbytes_decode(v.init_prologue), + ini_s, + ini_r_s, + protocol_name, + ini_psk, + ini_e, + ) + if !testing.expectf( + t, + status == .Ok, + "%s[%d]: %s - failed to initialize ini_hs: %v", f, i, protocol_name, status, + ) { + return false + } + + status = noise.handshake_init( + res_hs, + false, + common.hexbytes_decode(v.resp_prologue), + res_s, + res_i_s, + protocol_name, + res_psk, + res_e, + ) + if !testing.expectf( + t, + status == .Ok, + "%s[%d]: %s - failed to initialize res_hs: %v", f, i, protocol_name, status, + ) { + return false + } + + return true +} + +replay_messages_from_tv_rw :: proc( + t: ^testing.T, + hs: ^noise.Handshake_State, + v: ^Vector, + pattern: noise.Handshake_Pattern, + f: string, +) -> bool { + protocol_name := v.protocol_name + pattern_is_one_way := noise.pattern_is_one_way(pattern) + is_initiator := hs.initiator + + cs: noise.Cipher_States + + defer noise.cipherstates_reset(&cs) + + hs_done: bool + for &msg, i in &v.messages { + dst: []byte + status: noise.Status + expected: common.Hex_Bytes + + switch hs_done { + case false: + if (i & 1 == 0) == is_initiator { + dst, status = noise.handshake_write_message(hs, common.hexbytes_decode(msg.payload)) + expected = msg.ciphertext + } else { + dst, status = noise.handshake_read_message(hs, common.hexbytes_decode(msg.ciphertext)) + expected = msg.payload + } + defer delete(dst) + + if !testing.expectf( + t, + status == .Handshake_Pending || status == .Handshake_Complete, + "%s: %s[%d] - unexpected handshake status: %v", f, protocol_name, i, status, + ) { + return false + } + if !testing.expectf( + t, + common.hexbytes_compare(expected, dst), + "%s: %s[%d] - unexpected message/payload: %x expected: %s", f, protocol_name, i, dst, expected, + ) { + return false + } + if status == .Handshake_Complete { + status = noise.handshake_split(hs, &cs) + if !testing.expectf( + t, + status == .Ok, + "%s: %s[%d] - handshake_split failed: %v", f, protocol_name, i, status, + ) { + return false + } + hs_done = true + } + case true: + // The messages that use the derived cipherstates just follow the + // handshake message(s), and the flow continues. + if pattern_is_one_way { + // Except one-way patterns which go from initiator to responder. + if is_initiator { + dst, status = noise.seal_message(&cs, nil, common.hexbytes_decode(msg.payload)) + expected = msg.ciphertext + } else { + dst, status = noise.open_message(&cs, nil, common.hexbytes_decode(msg.ciphertext)) + expected = msg.payload + } + } else { + if (i & 1 == 0) == is_initiator { + dst, status = noise.seal_message(&cs, nil, common.hexbytes_decode(msg.payload)) + expected = msg.ciphertext + } else { + dst, status = noise.open_message(&cs, nil, common.hexbytes_decode(msg.ciphertext)) + expected = msg.payload + } + } + defer delete(dst) + + if !testing.expectf( + t, + status == .Ok, + "%s: %s[%d] - seal/open failed: %v", f, protocol_name, i, status, + ) { + return false + } + if !testing.expectf( + t, + common.hexbytes_compare(expected, dst), + "%s: %s[%d] - unexpected ciphertext/plaintext: %x expected: %s", f, protocol_name, i, dst, expected, + ) { + return false + } + } + } + + return true +} diff --git a/tests/core/crypto/noise/schemas.odin b/tests/core/crypto/noise/schemas.odin new file mode 100644 index 000000000..9eb6bdbd6 --- /dev/null +++ b/tests/core/crypto/noise/schemas.odin @@ -0,0 +1,56 @@ +package test_noise + +import "core:encoding/json" +import "core:log" +import "core:os" + +import "../common" + +Message :: struct { + payload: common.Hex_Bytes `json:"payload"`, + ciphertext: common.Hex_Bytes `json:"ciphertext"`, +} + +Vector :: struct { + name: string `json:"name"`, + + protocol_name: string `json:"protocol_name"`, + fail: bool `json:"fail"`, + fallback: bool `json:"fallback"`, + fallback_pattern: string `json:"fallback_pattern"`, + + init_prologue: common.Hex_Bytes `json:"init_prologue"`, + init_psks: []common.Hex_Bytes `json:"init_psks"`, + init_static: common.Hex_Bytes `json:"init_static"`, + init_ephemeral: common.Hex_Bytes `json:"init_ephemeral"`, + init_remote_static: common.Hex_Bytes `json:"init_remote_static"`, + + resp_prologue: common.Hex_Bytes `json:"resp_prologue"`, + resp_psks: []common.Hex_Bytes `json:"resp_psks"`, + resp_static: common.Hex_Bytes `json:"resp_static"`, + resp_ephemeral: common.Hex_Bytes `json:"resp_ephemeral"`, + resp_remote_static: common.Hex_Bytes `json:"resp_remote_static"`, + + handshake_hash: common.Hex_Bytes `json:"handshake_hash"`, + + messages: []Message `json:"messages"`, +} + +Test_Vectors :: struct { + vectors: []Vector `json:"vectors"`, +} + +load :: proc(tvs: ^Test_Vectors, fn: string) -> bool { + raw_json, err := os.read_entire_file_from_path(fn, context.allocator) + if err != os.ERROR_NONE { + log.error("failed to load raw JSON") + return false + } + + if err := json.unmarshal(raw_json, tvs); err != nil { + log.errorf("failed to parse JSON: %v", err) + return false + } + + return true +} diff --git a/tests/core/crypto/test_core_crypto.odin b/tests/core/crypto/test_core_crypto.odin index b3eb6e041..984f61bd8 100644 --- a/tests/core/crypto/test_core_crypto.odin +++ b/tests/core/crypto/test_core_crypto.odin @@ -2,7 +2,7 @@ package test_core_crypto /* Copyright 2021 zhibog - Made available under the BSD-3 license. + Made available under Odin's license. List of contributors: zhibog, dotbmp: Initial implementation. diff --git a/tests/core/crypto/test_core_crypto_ecdh.odin b/tests/core/crypto/test_core_crypto_ecdh.odin new file mode 100644 index 000000000..e34671c84 --- /dev/null +++ b/tests/core/crypto/test_core_crypto_ecdh.odin @@ -0,0 +1,167 @@ +package test_core_crypto + +import "core:encoding/hex" +import "core:testing" + +import "core:crypto/ecdh" + +@(test) +test_ecdh :: proc(t: ^testing.T) { + test_vectors := []struct { + curve: ecdh.Curve, + scalar: string, + point: string, + product: string, + } { + // X25519 Test vectors from RFC 7748 + { + .X25519, + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + }, + { + .X25519, + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", + }, + // X448 Test vectors from RFC 7748 + { + .X448, + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", + }, + { + .X448, + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", + }, + // secp256r1 Test vectors (subset) from NIST CAVP + { + .SECP256R1, + "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534", + "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac", + "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b", + }, + { + .SECP256R1, + "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5", + "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3", + "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67", + }, + // secp384r1 Test vectors (subset) from NIST CAVP + { + .SECP384R1, + "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1", + "04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c50066ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a", + "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1", + }, + { + .SECP384R1, + "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783", + "0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e025e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757", + "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff", + }, + } + + for v, _ in test_vectors { + raw_scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator) + raw_point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator) + + pub_key: ecdh.Public_Key + priv_key: ecdh.Private_Key + + ok := ecdh.private_key_set_bytes(&priv_key, v.curve, raw_scalar) + testing.expectf(t, ok, "failed to deserialize private key: %v %x", v.curve, raw_scalar) + + ok = ecdh.public_key_set_bytes(&pub_key, v.curve, raw_point) + testing.expectf(t, ok, "failed to deserialize public key: %v %x", v.curve, raw_scalar) + + shared_secret := make([]byte, ecdh.shared_secret_size(&pub_key), context.temp_allocator) + ok = ecdh.ecdh(&priv_key, &pub_key, shared_secret) + testing.expectf(t, ok, "ecdh failed: %v %v %v", v.curve, &priv_key, &pub_key) + + ss_str := string(hex.encode(shared_secret, context.temp_allocator)) + testing.expectf( + t, + ss_str == v.product, + "Expected %s for %v %s * %s, but got %s instead", + v.product, + v.curve, + v.scalar, + v.point, + ss_str, + ) + } +} + +@(test) +test_ecdh_scalar_basemult :: proc(t: ^testing.T) { + test_vectors := []struct { + curve: ecdh.Curve, + scalar : string, + point: string, + } { + // X25519 from RFC 7748 6.1 + { + .X25519, + "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", + }, + { + .X25519, + "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", + "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", + }, + // X448 from RFC 7748 6.2 + { + .X448, + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b", + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0", + }, + { + .X448, + "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d", + "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609", + }, + // secp256r1 Test vectors (subset) from NIST CAVP + { + .SECP256R1, + "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534", + "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141", + }, + { + .SECP256R1, + "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5", + "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d", + }, + } + + for v, _ in test_vectors { + raw_scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator) + + priv_key: ecdh.Private_Key + pub_key: ecdh.Public_Key + + ok := ecdh.private_key_set_bytes(&priv_key, v.curve, raw_scalar) + testing.expectf(t, ok, "failed to deserialize private key: %v %x", v.curve, raw_scalar) + + ecdh.public_key_set_priv(&pub_key, &priv_key) + b := make([]byte, ecdh.key_size(&pub_key), context.temp_allocator) + ecdh.public_key_bytes(&pub_key, b) + + pub_str := string(hex.encode(b, context.temp_allocator)) + testing.expectf( + t, + pub_str == v.point, + "Expected %s for %v %s * G, but got %s instead", + v.point, + v.curve, + v.scalar, + pub_str, + ) + } +} \ No newline at end of file diff --git a/tests/core/crypto/test_core_crypto_edwards.odin b/tests/core/crypto/test_core_crypto_edwards.odin index 61933c00f..2983e6cbb 100644 --- a/tests/core/crypto/test_core_crypto_edwards.odin +++ b/tests/core/crypto/test_core_crypto_edwards.odin @@ -4,13 +4,10 @@ import "core:encoding/hex" import "core:testing" import field "core:crypto/_fiat/field_curve25519" -import "core:crypto/ed25519" import "core:crypto/ristretto255" -import "core:crypto/x25519" -import "core:crypto/x448" @(test) -test_sqrt_ratio_m1 :: proc(t: ^testing.T) { +test_edwards25519_sqrt_ratio_m1 :: proc(t: ^testing.T) { test_vectors := []struct { u: string, v: string, @@ -320,443 +317,16 @@ test_ristretto255 :: proc(t: ^testing.T) { } } -@(test) -test_ed25519 :: proc(t: ^testing.T) { - test_vectors_rfc := []struct { - priv_key: string, - pub_key: string, - msg: string, - sig: string, - } { - // Test vectors from RFC 8032 - { - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", - "", - "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", - }, - { - "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", - "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", - "72", - "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", - }, - { - "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", - "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", - "af82", - "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", - }, - // TEST 1024 omitted for brevity, because all that does is add more to SHA-512 - { - "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", - "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", - "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", - "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704", - }, - } - for v, _ in test_vectors_rfc { - priv_bytes, _ := hex.decode(transmute([]byte)(v.priv_key), context.temp_allocator) - pub_bytes, _ := hex.decode(transmute([]byte)(v.pub_key), context.temp_allocator) - msg_bytes, _ := hex.decode(transmute([]byte)(v.msg), context.temp_allocator) - sig_bytes, _ := hex.decode(transmute([]byte)(v.sig), context.temp_allocator) - - priv_key: ed25519.Private_Key - ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes) - testing.expectf( - t, - ok, - "Expected %s to be a valid private key", - v.priv_key, - ) - - key_bytes: [32]byte - ed25519.private_key_bytes(&priv_key, key_bytes[:]) - testing.expectf( - t, - ok, - "Expected private key %s round-trip, got %s", - v.priv_key, - string(hex.encode(key_bytes[:], context.temp_allocator)), - ) - - pub_key: ed25519.Public_Key - ok = ed25519.public_key_set_bytes(&pub_key, pub_bytes) - testing.expectf( - t, - ok, - "Expected %s to be a valid public key (priv->pub: %s)", - v.pub_key, - string(hex.encode(priv_key._pub_key._b[:], context.temp_allocator)), - ) - - ed25519.public_key_bytes(&pub_key, key_bytes[:]) - testing.expectf( - t, - ok, - "Expected public key %s round-trip, got %s", - v.pub_key, - string(hex.encode(key_bytes[:], context.temp_allocator)), - ) - - sig: [ed25519.SIGNATURE_SIZE]byte - ed25519.sign(&priv_key, msg_bytes, sig[:]) - x := string(hex.encode(sig[:], context.temp_allocator)) - testing.expectf( - t, - x == v.sig, - "Expected %s for sign(%s, %s), got %s", - v.sig, - v.priv_key, - v.msg, - x, - ) - - ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) - testing.expectf( - t, - ok, - "Expected true for verify(%s, %s, %s)", - v.pub_key, - v.msg, - v.sig, - ) - - ok = ed25519.verify(&priv_key._pub_key, msg_bytes, sig_bytes) - testing.expectf( - t, - ok, - "Expected true for verify(pub(%s), %s %s)", - v.priv_key, - v.msg, - v.sig, - ) - - // Corrupt the message and make sure verification fails. - switch len(msg_bytes) { - case 0: - tmp_msg := []byte{69} - msg_bytes = tmp_msg[:] - case: - msg_bytes[0] = msg_bytes[0] ~ 69 - } - ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) - testing.expectf( - t, - ok == false, - "Expected false for verify(%s, %s (corrupted), %s)", - v.pub_key, - v.msg, - v.sig, - ) - } - - // Test cases from "Taming the many EdDSAs", which aim to exercise - // all of the ed25519 edge cases/implementation differences. - // - // - https://eprint.iacr.org/2020/1244 - // - https://github.com/novifinancial/ed25519-speccheck - test_vectors_speccheck := []struct { - pub_key: string, - msg: string, - sig: string, - pub_key_ok: bool, - sig_ok: bool, - sig_ok_relaxed: bool, // Ok if the small-order A check is relaxed. - } { - // S = 0, small-order A, small-order R - { - "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", - "8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6", - "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", - true, - false, - true, - }, - // 0 < S < L, small-order A, mixed-order R - { - "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", - "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79", - "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", - true, - false, - true, - }, - // 0 < S < L, mixed-order A, small-order R - { - "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", - "aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab", - "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e", - true, - true, - true, - }, - // 0 < S < L, mixed-order A, mixed-order R - { - "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", - "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79", - "9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009", - true, - true, - true, - }, - // 0 < S < L, mixed-order A, mixed-order R - { - "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", - "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c", - "160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09", - true, - true, // cofactored-only - true, - }, - // 0 < S < L, mixed-order A, L-order R - { - "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", - "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c", - "21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405", - true, - true, // cofactored only, (fail if 8h is pre-reduced) - true, - }, - // S > L, L-order A, L-order R - { - "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623", - "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40", - "e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514", - true, - false, - false, - }, - // S >> L, L-order A, L-order R - { - "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623", - "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40", - "8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22", - true, - false, - false, - }, - // 0 < S < L, mixed-order A, small-order R (non-canonical R, reduced for hash) - { - "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", - "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f", - true, - false, - false, - }, - // 0 < S < L, mixed-order A, small-order R (non-canonical R, not reduced for hash) - { - "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", - "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908", - true, - false, - false, - }, - // 0 < S < L, small-order A, mixed-order R (non-canonical A, reduced for hash) - { - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b", - "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", - false, - false, - false, - }, - // 0 < S < L, small-order A, mixed-order R (non-canonical A, not reduced for hash) - { - "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f", - "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", - false, - false, - false, - }, - } - for v, i in test_vectors_speccheck { - pub_bytes, _ := hex.decode(transmute([]byte)(v.pub_key), context.temp_allocator) - msg_bytes, _ := hex.decode(transmute([]byte)(v.msg), context.temp_allocator) - sig_bytes, _ := hex.decode(transmute([]byte)(v.sig), context.temp_allocator) - - pub_key: ed25519.Public_Key - ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes) - testing.expectf( - t, - ok == v.pub_key_ok, - "speccheck/%d: Expected %s to be a (in)valid public key, got %v", - i, - v.pub_key, - ok, - ) - - // If A is rejected for being non-canonical, skip signature check. - if !v.pub_key_ok { - continue - } - - ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) - testing.expectf( - t, - ok == v.sig_ok, - "speccheck/%d Expected %v for verify(%s, %s, %s)", - i, - v.sig_ok, - v.pub_key, - v.msg, - v.sig, - ) - - // If the signature is accepted, skip the relaxed signature check. - if v.sig_ok { - continue - } - - ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes, true) - testing.expectf( - t, - ok == v.sig_ok_relaxed, - "speccheck/%d Expected %v for verify(%s, %s, %s, true)", - i, - v.sig_ok_relaxed, - v.pub_key, - v.msg, - v.sig, - ) - } -} - -@(test) -test_x25519 :: proc(t: ^testing.T) { - // Local copy of this so that the base point doesn't need to be exported. - _BASE_POINT: [32]byte = { - 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - } - - test_vectors := []struct { - scalar: string, - point: string, - product: string, - } { - // Test vectors from RFC 7748 - { - "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", - "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", - "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", - }, - { - "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", - "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", - "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", - }, - } - for v, _ in test_vectors { - scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator) - point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator) - - derived_point: [x25519.POINT_SIZE]byte - x25519.scalarmult(derived_point[:], scalar[:], point[:]) - derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator)) - - testing.expectf( - t, - derived_point_str == v.product, - "Expected %s for %s * %s, but got %s instead", - v.product, - v.scalar, - v.point, - derived_point_str, - ) - - // Abuse the test vectors to sanity-check the scalar-basepoint multiply. - p1, p2: [x25519.POINT_SIZE]byte - x25519.scalarmult_basepoint(p1[:], scalar[:]) - x25519.scalarmult(p2[:], scalar[:], _BASE_POINT[:]) - p1_str := string(hex.encode(p1[:], context.temp_allocator)) - p2_str := string(hex.encode(p2[:], context.temp_allocator)) - testing.expectf( - t, - p1_str == p2_str, - "Expected %s for %s * basepoint, but got %s instead", - p2_str, - v.scalar, - p1_str, - ) - } -} - -@(test) -test_x448 :: proc(t: ^testing.T) { - // Local copy of this so that the base point doesn't need to be exported. - _BASE_POINT: [56]byte = { - 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - } - - test_vectors := []struct { - scalar: string, - point: string, - product: string, - } { - // Test vectors from RFC 7748 - { - "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", - "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", - "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", - }, - { - "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", - "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", - "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", - }, - } - for v, _ in test_vectors { - scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator) - point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator) - - derived_point: [x448.POINT_SIZE]byte - x448.scalarmult(derived_point[:], scalar[:], point[:]) - derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator)) - - testing.expectf( - t, - derived_point_str == v.product, - "Expected %s for %s * %s, but got %s instead", - v.product, - v.scalar, - v.point, - derived_point_str, - ) - - // Abuse the test vectors to sanity-check the scalar-basepoint multiply. - p1, p2: [x448.POINT_SIZE]byte - x448.scalarmult_basepoint(p1[:], scalar[:]) - x448.scalarmult(p2[:], scalar[:], _BASE_POINT[:]) - p1_str := string(hex.encode(p1[:], context.temp_allocator)) - p2_str := string(hex.encode(p2[:], context.temp_allocator)) - testing.expectf( - t, - p1_str == p2_str, - "Expected %s for %s * basepoint, but got %s instead", - p2_str, - v.scalar, - p1_str, - ) - } -} - -@(private) +@(private="file") ge_str :: proc(ge: ^ristretto255.Group_Element) -> string { b: [ristretto255.ELEMENT_SIZE]byte ristretto255.ge_bytes(ge, b[:]) return string(hex.encode(b[:], context.temp_allocator)) } -@(private) +@(private="file") fe_str :: proc(fe: ^field.Tight_Field_Element) -> string { b: [32]byte field.fe_to_bytes(&b, fe) return string(hex.encode(b[:], context.temp_allocator)) -} \ No newline at end of file +} diff --git a/tests/core/crypto/test_core_crypto_exdsa.odin b/tests/core/crypto/test_core_crypto_exdsa.odin new file mode 100644 index 000000000..944f8747a --- /dev/null +++ b/tests/core/crypto/test_core_crypto_exdsa.odin @@ -0,0 +1,568 @@ +package test_core_crypto + +import "core:bytes" +import "core:encoding/hex" +import "core:testing" + +import "core:crypto" +import "core:crypto/ecdsa" +import "core:crypto/ed25519" +import "core:crypto/hash" + +@(test) +test_ecdsa :: proc(t: ^testing.T) { + test_vectors_deterministic := []struct{ + curve: ecdsa.Curve, + hash: hash.Algorithm, + priv_key: string, + pub_key: string, + msg: string, + sig_raw: string, + } { + // Test vectors from RFC 6979 + { + .SECP256R1, + .SHA256, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "sample", + "efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8", + }, + { + .SECP256R1, + .SHA384, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "sample", + "0eafea039b20e9b42309fb1d89e213057cbf973dc0cfc8f129edddc800ef77194861f0491e6998b9455193e34e7b0d284ddd7149a74b95b9261f13abde940954", + }, + { + .SECP256R1, + .SHA512, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "sample", + "8496a60b5e9b47c825488827e0495b0e3fa109ec4568fd3f8d1097678eb97f002362ab1adbe2b8adf9cb9edab740ea6049c028114f2460f96554f61fae3302fe", + }, + { + .SECP256R1, + .SHA256, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "test", + "f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d38367019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083", + }, + { + .SECP256R1, + .SHA384, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "test", + "83910e8b48bb0c74244ebdf7f07a1c5413d61472bd941ef3920e623fbccebeb68ddbec54cf8cd5874883841d712142a56a8d0f218f5003cb0296b6b509619f2c", + }, + { + .SECP256R1, + .SHA512, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "test", + "461d93f31b6540894788fd206c07cfa0cc35f46fa3c91816fff1040ad1581a0439af9f15de0db8d97e72719c74820d304ce5226e32dedae67519e840d1194e55", + }, + { + .SECP384R1, + .SHA384, + "6b9d3dad2e1b8c1c05b19875b6659f4de23c3b667bf297ba9aa47740787137d896d5724e4c70a825f872c9ea60d2edf5", + "04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720", + "sample", + "94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe4699ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8", + }, + { + .SECP384R1, + .SHA512, + "6b9d3dad2e1b8c1c05b19875b6659f4de23c3b667bf297ba9aa47740787137d896d5724e4c70a825f872c9ea60d2edf5", + "04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720", + "sample", + "ed0959d5880ab2d869ae7f6c2915c6d60f96507f9cb3e047c0046861da4a799cfe30f35cc900056d7c99cd7882433709512c8cceee3890a84058ce1e22dbc2198f42323ce8aca9135329f03c068e5112dc7cc3ef3446defceb01a45c2667fdd5", + }, + { + .SECP384R1, + .SHA384, + "6b9d3dad2e1b8c1c05b19875b6659f4de23c3b667bf297ba9aa47740787137d896d5724e4c70a825f872c9ea60d2edf5", + "04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720", + "test", + "8203b63d3c853e8d77227fb377bcf7b7b772e97892a80f36ab775d509d7a5feb0542a7f0812998da8f1dd3ca3cf023dbddd0760448d42d8a43af45af836fce4de8be06b485e9b61b827c2f13173923e06a739f040649a667bf3b828246baa5a5", + }, + { + .SECP384R1, + .SHA512, + "6b9d3dad2e1b8c1c05b19875b6659f4de23c3b667bf297ba9aa47740787137d896d5724e4c70a825f872c9ea60d2edf5", + "04ec3a4e415b4e19a4568618029f427fa5da9a8bc4ae92e02e06aae5286b300c64def8f0ea9055866064a254515480bc138015d9b72d7d57244ea8ef9ac0c621896708a59367f9dfb9f54ca84b3f1c9db1288b231c3ae0d4fe7344fd2533264720", + "test", + "a0d5d090c9980faf3c2ce57b7ae951d31977dd11c775d314af55f76c676447d06fb6495cd21b4b6e340fc236584fb277976984e59b4c77b0e8e4460dca3d9f20e07b9bb1f63beefaf576f6b2e8b224634a2092cd3792e0159ad9cee37659c736", + }, + // Special case that exercises the rejection sampling. + // https://github.com/C2SP/CCTV/tree/main/RFC6979 + { + .SECP256R1, + .SHA256, + "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "0460fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb67903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299", + "wv[vnX", + "efd9073b652e76da1b5a019c0e4a2e3fa529b035a6abb91ef67f0ed7a1f212343db4706c9d9f4a4fe13bb5e08ef0fab53a57dbab2061c83a35fa411c68d2ba33", + }, + } + for v, _ in test_vectors_deterministic { + priv_bytes, _ := hex.decode(transmute([]byte)(v.priv_key), context.temp_allocator) + pub_bytes, _ := hex.decode(transmute([]byte)(v.pub_key), context.temp_allocator) + msg_bytes := bytes.clone(transmute([]byte)(v.msg), context.temp_allocator) + sig_bytes, _ := hex.decode(transmute([]byte)(v.sig_raw), context.temp_allocator) + + priv_key: ecdsa.Private_Key + ok := ecdsa.private_key_set_bytes(&priv_key, v.curve, priv_bytes) + testing.expectf( + t, + ok, + "Expected %s to be a valid %v private key", + v.priv_key, + v.curve, + ) + + priv_key_bytes := make([]byte, ecdsa.PRIVATE_KEY_SIZES[v.curve], context.temp_allocator) + ecdsa.private_key_bytes(&priv_key, priv_key_bytes) + priv_s := string(hex.encode(priv_key_bytes, context.temp_allocator)) + testing.expectf( + t, + priv_s == v.priv_key, + "Expected private key %s round-trip, got %s", + v.priv_key, + priv_s, + ) + + pub_key: ecdsa.Public_Key + ok = ecdsa.public_key_set_bytes(&pub_key, v.curve, pub_bytes) + testing.expectf( + t, + ok, + "Expected %s to be a valid %s public key", + v.pub_key, + v.curve, + ) + + pub_key_bytes := make([]byte, ecdsa.PUBLIC_KEY_SIZES[v.curve], context.temp_allocator) + ecdsa.public_key_bytes(&pub_key, pub_key_bytes) + pub_s := string(hex.encode(pub_key_bytes, context.temp_allocator)) + testing.expectf( + t, + pub_s == v.pub_key, + "Expected public key %s round-trip, got %s", + v.pub_key, + pub_s, + ) + + priv_pub_key: ecdsa.Public_Key + ecdsa.public_key_set_priv(&priv_pub_key, &priv_key) + ok = ecdsa.public_key_equal(&pub_key, &priv_pub_key) + testing.expectf( + t, + ok, + "Expected %v to be %s's public key", + &priv_pub_key, + v.priv_key, + ) + + ok = ecdsa.verify_raw(&pub_key, v.hash, msg_bytes, sig_bytes) + testing.expectf( + t, + ok, + "Expected true for verify(%s, %v, %s, %s)", + v.pub_key, + v.hash, + v.msg, + v.sig_raw, + ) + + // Signatures are deterministic for these test cases. + sig := make([]byte, ecdsa.RAW_SIGNATURE_SIZES[v.curve], context.temp_allocator) + ok = ecdsa.sign_raw(&priv_key, v.hash, msg_bytes, sig, true) + x := string(hex.encode(sig[:], context.temp_allocator)) + testing.expectf( + t, + ok && x == v.sig_raw, + "Expected %s for sign(%s, %v, %s), got %s", + v.sig_raw, + v.priv_key, + v.hash, + v.msg, + x, + ) + + // But when possible, we also add entropy by default. + when crypto.HAS_RAND_BYTES { + ok = ecdsa.sign_raw(&priv_key, v.hash, msg_bytes, sig) + x = string(hex.encode(sig[:], context.temp_allocator)) + testing.expectf( + t, + ok && x != v.sig_raw, + "Expected not %s for sign(%s, %v, %s), got %s", + v.sig_raw, + v.priv_key, + v.hash, + v.msg, + x, + ) + } + + // Corrupt the message and make sure verification fails. + msg_bytes[0] ~= 0x69 + ok = ecdsa.verify_raw(&pub_key, v.hash, msg_bytes, sig_bytes) + testing.expectf( + t, + ok == false, + "Expected false for verify(%s, %v %s (corrupted), %s)", + v.pub_key, + v.hash, + v.msg, + v.sig_raw, + ) + } + + // ASN.1 tests requires entorpy. + when crypto.HAS_RAND_BYTES == false { + return + } + msg_str : string : "Feed the Fire. Let the Last Cinders Burn." + for _ in 0 ..< 1000 { + msg := transmute([]byte)(msg_str) + + priv_key: ecdsa.Private_Key + ok := ecdsa.private_key_generate(&priv_key, .SECP256R1) + testing.expectf(t, ok, "Failed to generate private key") + + sig: []byte + sig, ok = ecdsa.sign_asn1(&priv_key, .SHA256, msg, context.temp_allocator) + testing.expectf( + t, + ok && len(sig) > 0, + "Failed for sign(%v, secp256r1/SHA256, %s)", + priv_key, + msg, + ) + + pub_key := &priv_key._pub_key + ok = ecdsa.verify_asn1(pub_key, .SHA256, msg, sig) + testing.expectf( + t, + ok, + "Expected true for verify(%v, SHA256, %s, %x)", + pub_key, + msg, + sig, + ) + } +} + +@(test) +test_ed25519 :: proc(t: ^testing.T) { + test_vectors_rfc := []struct { + priv_key: string, + pub_key: string, + msg: string, + sig: string, + } { + // Test vectors from RFC 8032 + { + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + "", + "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + }, + { + "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + "72", + "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + }, + { + "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + "af82", + "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + }, + // TEST 1024 omitted for brevity, because all that does is add more to SHA-512 + { + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704", + }, + } + for v, _ in test_vectors_rfc { + priv_bytes, _ := hex.decode(transmute([]byte)(v.priv_key), context.temp_allocator) + pub_bytes, _ := hex.decode(transmute([]byte)(v.pub_key), context.temp_allocator) + msg_bytes, _ := hex.decode(transmute([]byte)(v.msg), context.temp_allocator) + sig_bytes, _ := hex.decode(transmute([]byte)(v.sig), context.temp_allocator) + + priv_key: ed25519.Private_Key + ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes) + testing.expectf( + t, + ok, + "Expected %s to be a valid private key", + v.priv_key, + ) + + key_bytes: [32]byte + ed25519.private_key_bytes(&priv_key, key_bytes[:]) + priv_s := string(hex.encode(key_bytes[:], context.temp_allocator)) + testing.expectf( + t, + priv_s == v.priv_key, + "Expected private key %s round-trip, got %s", + v.priv_key, + priv_s, + ) + + pub_key: ed25519.Public_Key + ok = ed25519.public_key_set_bytes(&pub_key, pub_bytes) + testing.expectf( + t, + ok, + "Expected %s to be a valid public key (priv->pub: %s)", + v.pub_key, + ) + + ed25519.public_key_bytes(&pub_key, key_bytes[:]) + pub_s := string(hex.encode(priv_key._pub_key._b[:], context.temp_allocator)) + testing.expectf( + t, + pub_s == v.pub_key, + "Expected public key %s round-trip, got %s", + v.pub_key, + pub_s, + ) + + sig: [ed25519.SIGNATURE_SIZE]byte + ed25519.sign(&priv_key, msg_bytes, sig[:]) + x := string(hex.encode(sig[:], context.temp_allocator)) + testing.expectf( + t, + x == v.sig, + "Expected %s for sign(%s, %s), got %s", + v.sig, + v.priv_key, + v.msg, + x, + ) + + ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) + testing.expectf( + t, + ok, + "Expected true for verify(%s, %s, %s)", + v.pub_key, + v.msg, + v.sig, + ) + + ok = ed25519.verify(&priv_key._pub_key, msg_bytes, sig_bytes) + testing.expectf( + t, + ok, + "Expected true for verify(pub(%s), %s %s)", + v.priv_key, + v.msg, + v.sig, + ) + + // Corrupt the message and make sure verification fails. + switch len(msg_bytes) { + case 0: + tmp_msg := []byte{69} + msg_bytes = tmp_msg[:] + case: + msg_bytes[0] = msg_bytes[0] ~ 69 + } + ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) + testing.expectf( + t, + ok == false, + "Expected false for verify(%s, %s (corrupted), %s)", + v.pub_key, + v.msg, + v.sig, + ) + } + + // Test cases from "Taming the many EdDSAs", which aim to exercise + // all of the ed25519 edge cases/implementation differences. + // + // - https://eprint.iacr.org/2020/1244 + // - https://github.com/novifinancial/ed25519-speccheck + test_vectors_speccheck := []struct { + pub_key: string, + msg: string, + sig: string, + pub_key_ok: bool, + sig_ok: bool, + sig_ok_relaxed: bool, // Ok if the small-order A check is relaxed. + } { + // S = 0, small-order A, small-order R + { + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6", + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + true, + false, + true, + }, + // 0 < S < L, small-order A, mixed-order R + { + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79", + "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", + true, + false, + true, + }, + // 0 < S < L, mixed-order A, small-order R + { + "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", + "aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab", + "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e", + true, + true, + true, + }, + // 0 < S < L, mixed-order A, mixed-order R + { + "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", + "9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79", + "9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009", + true, + true, + true, + }, + // 0 < S < L, mixed-order A, mixed-order R + { + "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", + "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c", + "160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09", + true, + true, // cofactored-only + true, + }, + // 0 < S < L, mixed-order A, L-order R + { + "cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d", + "e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c", + "21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405", + true, + true, // cofactored only, (fail if 8h is pre-reduced) + true, + }, + // S > L, L-order A, L-order R + { + "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623", + "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40", + "e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514", + true, + false, + false, + }, + // S >> L, L-order A, L-order R + { + "442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623", + "85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40", + "8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22", + true, + false, + false, + }, + // 0 < S < L, mixed-order A, small-order R (non-canonical R, reduced for hash) + { + "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", + "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f", + true, + false, + false, + }, + // 0 < S < L, mixed-order A, small-order R (non-canonical R, not reduced for hash) + { + "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", + "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908", + true, + false, + false, + }, + // 0 < S < L, small-order A, mixed-order R (non-canonical A, reduced for hash) + { + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b", + "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", + false, + false, + false, + }, + // 0 < S < L, small-order A, mixed-order R (non-canonical A, not reduced for hash) + { + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f", + "a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04", + false, + false, + false, + }, + } + for v, i in test_vectors_speccheck { + pub_bytes, _ := hex.decode(transmute([]byte)(v.pub_key), context.temp_allocator) + msg_bytes, _ := hex.decode(transmute([]byte)(v.msg), context.temp_allocator) + sig_bytes, _ := hex.decode(transmute([]byte)(v.sig), context.temp_allocator) + + pub_key: ed25519.Public_Key + ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes) + testing.expectf( + t, + ok == v.pub_key_ok, + "speccheck/%d: Expected %s to be a (in)valid public key, got %v", + i, + v.pub_key, + ok, + ) + + // If A is rejected for being non-canonical, skip signature check. + if !v.pub_key_ok { + continue + } + + ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes) + testing.expectf( + t, + ok == v.sig_ok, + "speccheck/%d Expected %v for verify(%s, %s, %s)", + i, + v.sig_ok, + v.pub_key, + v.msg, + v.sig, + ) + + // If the signature is accepted, skip the relaxed signature check. + if v.sig_ok { + continue + } + + ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes, true) + testing.expectf( + t, + ok == v.sig_ok_relaxed, + "speccheck/%d Expected %v for verify(%s, %s, %s, true)", + i, + v.sig_ok_relaxed, + v.pub_key, + v.msg, + v.sig, + ) + } +} diff --git a/tests/core/crypto/test_core_crypto_hash.odin b/tests/core/crypto/test_core_crypto_hash.odin index 9a9d0cc76..76c2aef6a 100644 --- a/tests/core/crypto/test_core_crypto_hash.odin +++ b/tests/core/crypto/test_core_crypto_hash.odin @@ -5,6 +5,9 @@ import "core:bytes" import "core:encoding/hex" import "core:strings" import "core:testing" + +import "core:crypto/blake2b" +import "core:crypto/blake2s" import "core:crypto/hash" @(test) @@ -596,4 +599,139 @@ test_hash :: proc(t: ^testing.T) { c_str, ) } -} \ No newline at end of file +} + +@(private="file") +selftest_seq :: proc(dst: []byte, seed: u32) { + a := 0xdead4bad * seed + b: u32 = 1 + + for i in 0 ..< len(dst) { + a, b = b, a + b + dst[i] = byte(b >> 24) + } +} + +@(test) +test_blake2b_self :: proc(t: ^testing.T) { + expected := []byte{ + 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, + 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, + 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, + 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75, + } + md_lens := []int{20, 32, 48, 64} + src_lens := []int{0, 3, 128, 129, 255, 1024} + + b2b := proc(dst, src: []byte) { + ctx: blake2b.Context + + blake2b.init(&ctx, len(dst)) + blake2b.update(&ctx, src) + blake2b.final(&ctx, dst) + } + b2b_keyed := proc(dst, key, src: []byte) { + ctx: blake2b.Context + + blake2b.init_mac(&ctx, key, len(dst)) + blake2b.update(&ctx, src) + blake2b.final(&ctx, dst) + } + + buf: [1024]byte + md, key: [64]byte + + ctx: blake2b.Context + blake2b.init(&ctx, 32) + + for md_len in md_lens { + dst := md[:md_len] + for src_len in src_lens { + src := buf[:src_len] + + selftest_seq(src, u32(src_len)) + b2b(dst, src) + blake2b.update(&ctx, dst) + + k := key[:md_len] + selftest_seq(k, u32(md_len)) + b2b_keyed(dst, k, src) + blake2b.update(&ctx, dst) + } + } + + blake2b.final(&ctx, md[:32]) + + expected_str := string(hex.encode(expected, context.temp_allocator)) + actual_str := string(hex.encode(md[:32], context.temp_allocator)) + + testing.expectf( + t, + expected_str == actual_str, + "blake2b/self-test: Expected: %s Got %s", + expected_str, + actual_str, + ) +} + +@(test) +test_blake2s_self :: proc(t: ^testing.T) { + expected := []byte{ + 0x6A, 0x41, 0x1F, 0x08, 0xCE, 0x25, 0xAD, 0xCD, + 0xFB, 0x02, 0xAB, 0xA6, 0x41, 0x45, 0x1C, 0xEC, + 0x53, 0xC5, 0x98, 0xB2, 0x4F, 0x4F, 0xC7, 0x87, + 0xFB, 0xDC, 0x88, 0x79, 0x7F, 0x4C, 0x1D, 0xFE, + } + md_lens := []int{16, 20, 28, 32} + src_lens := []int{0, 3, 64, 65, 255, 1024} + + b2s := proc(dst, src: []byte) { + ctx: blake2s.Context + + blake2s.init(&ctx, len(dst)) + blake2s.update(&ctx, src) + blake2s.final(&ctx, dst) + } + b2s_keyed := proc(dst, key, src: []byte) { + ctx: blake2s.Context + + blake2s.init_mac(&ctx, key, len(dst)) + blake2s.update(&ctx, src) + blake2s.final(&ctx, dst) + } + + buf: [1024]byte + md, key: [32]byte + + ctx: blake2s.Context + blake2s.init(&ctx) + + for md_len in md_lens { + dst := md[:md_len] + for src_len in src_lens { + src := buf[:src_len] + + selftest_seq(src, u32(src_len)) + b2s(dst, src) + blake2s.update(&ctx, dst) + + k := key[:md_len] + selftest_seq(k, u32(md_len)) + b2s_keyed(dst, k, src) + blake2s.update(&ctx, dst) + } + } + + blake2s.final(&ctx, md[:]) + + expected_str := string(hex.encode(expected, context.temp_allocator)) + actual_str := string(hex.encode(md[:], context.temp_allocator)) + + testing.expectf( + t, + expected_str == actual_str, + "blake2s/self-test: Expected: %s Got %s", + expected_str, + actual_str, + ) +} diff --git a/tests/core/crypto/test_core_crypto_kdf.odin b/tests/core/crypto/test_core_crypto_kdf.odin index c15dc2206..d0266e4d1 100644 --- a/tests/core/crypto/test_core_crypto_kdf.odin +++ b/tests/core/crypto/test_core_crypto_kdf.odin @@ -3,10 +3,63 @@ package test_core_crypto import "base:runtime" import "core:encoding/hex" import "core:testing" +import "core:crypto/argon2id" import "core:crypto/hash" import "core:crypto/hkdf" import "core:crypto/pbkdf2" +@(test) +test_argon2id :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + test_vectors := []struct { + params: ^argon2id.Parameters, + password: string, + salt: string, + secret: string, + ad: string, + tag: string, + } { + // RFC 9106 5.3. + { + &argon2id.Parameters{ + 32, + 3, + 4, + }, + "0101010101010101010101010101010101010101010101010101010101010101", + "02020202020202020202020202020202", + "0303030303030303", + "040404040404040404040404", + "0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659", + }, + } + for v, _ in test_vectors { + tag := make([]byte, len(v.tag)/2, context.temp_allocator) + + password, _ := hex.decode(transmute([]byte)(v.password), context.temp_allocator) + salt, _ := hex.decode(transmute([]byte)(v.salt), context.temp_allocator) + secret, _ := hex.decode(transmute([]byte)(v.secret), context.temp_allocator) + ad, _ := hex.decode(transmute([]byte)(v.ad), context.temp_allocator) + + _ = argon2id.derive(v.params, password, salt, tag, secret, ad) + + tag_str := string(hex.encode(tag, context.temp_allocator)) + + testing.expectf( + t, + tag_str == v.tag, + "argon2id: Expected: %s for input of (%s, %s, %s, %s), but got %s instead", + v.tag, + v.password, + v.salt, + v.secret, + v.ad, + tag_str, + ) + } +} + @(test) test_hkdf :: proc(t: ^testing.T) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() diff --git a/tests/core/crypto/test_core_crypto_noise.odin b/tests/core/crypto/test_core_crypto_noise.odin new file mode 100644 index 000000000..6371900ca --- /dev/null +++ b/tests/core/crypto/test_core_crypto_noise.odin @@ -0,0 +1,306 @@ +package test_core_crypto + +import "core:bytes" +import "core:crypto" +import "core:crypto/aead" +import "core:crypto/ecdh" +import "core:crypto/hash" +import "core:crypto/noise" +import "core:fmt" +import "core:log" +import "core:math/rand" +import "core:testing" + +@(private = "file") +DH_CURVES :: []ecdh.Curve { + .X25519, + .X448, +} +@(private = "file") +CIPHERS :: []aead.Algorithm{ + .AES_GCM_256, + .CHACHA20POLY1305, +} +@(private = "file") +HASHES :: []hash.Algorithm{ + .SHA256, + .SHA512, + .BLAKE2S, + .BLAKE2B, +} + +@(test) +test_supported_protocols :: proc(t: ^testing.T) { + if !crypto.HAS_RAND_BYTES { + log.info("rand_bytes not supported - skipping") + return + } + + protocol: Test_Protocol + for pattern in noise.Handshake_Pattern { + if pattern == .Invalid { + continue + } + protocol.handshake_pattern = pattern + for dh in DH_CURVES { + protocol.dh = dh + for cipher in CIPHERS { + protocol.cipher = cipher + for hash in HASHES { + protocol.hash = hash + if !testing.expectf( + t, + test_noise_one_protocol(t, &protocol, context.temp_allocator), + "Failed protocol: %v", protocol, + ) { + testing.fail(t) + break + } + } + } + } + } +} + +@(private = "file") +test_noise_one_protocol :: proc(t: ^testing.T, protocol: ^Test_Protocol, allocator := context.allocator) -> bool { + protocol_name := test_protocol_string(protocol, allocator) + defer delete(protocol_name, allocator) + + log.debugf("crypto/noise: %s", protocol_name) + + is_one_way := noise.pattern_is_one_way(protocol.handshake_pattern) + + initiator_s, responder_s: ecdh.Private_Key + ini_s, res_s: ^ecdh.Private_Key + ini_s_pub, res_s_pub: ^ecdh.Public_Key + + pre, hs := noise.pattern_requires_initiator_s(protocol.handshake_pattern) + if pre || hs { + if !testing.expect(t, ecdh.private_key_generate(&initiator_s, protocol.dh), "failed to generate initiator s") { + return false + } + ini_s = &initiator_s + if pre { + ini_s_pub = &initiator_s._pub_key + } + } + pre, hs = noise.pattern_requires_responder_s(protocol.handshake_pattern) + if pre || hs { + if !testing.expect(t, ecdh.private_key_generate(&responder_s, protocol.dh), "failed to generate responder s") { + return false + } + res_s = &responder_s + if pre { + res_s_pub = &responder_s._pub_key + } + } + + psk_buf: [32]byte = --- + psk: []byte + if noise.pattern_is_psk(protocol.handshake_pattern) { + crypto.rand_bytes(psk_buf[:]) + psk = psk_buf[:] + } + + ini_hs, res_hs: noise.Handshake_State + status := noise.handshake_init(&ini_hs, true, nil, ini_s, res_s_pub, protocol_name, psk) + if !testing.expectf(t, status == .Ok, "failed to initialize initiator Handshake_State: %v", status) { + return false + } + status = noise.handshake_init(&res_hs, false, nil, res_s, ini_s_pub, protocol_name, psk) + if !testing.expectf(t, status == .Ok, "failed to initialize responder Handshake_State: %v", status) { + return false + } + + ini_status, res_status: noise.Status + ini_msg, res_msg: []byte + ini_payload, res_payload: []byte + hs_msg_buf: [noise.MAX_STEP_MSG_SIZE]byte + for i := 0; ; i += 1 { + if ini_status == .Handshake_Complete && res_status == .Handshake_Complete { + break + } + + // Test the allocation path + res_msg, res_payload, ini_status = noise.handshake_initiator_step(&ini_hs, ini_msg, allocator = allocator) + ini_msg = nil + + if ini_status == .Handshake_Complete && res_status == .Handshake_Complete { + break + } + + if !testing.expectf(t, len(res_payload) == 0, "step %d: unexpected responder payload: %x", i, res_payload) { + return false + } + if !testing.expectf(t, ini_status == .Handshake_Pending || ini_status == .Handshake_Complete, "step %d: initiator step failed: %v", i, ini_status) { + return false + } + + // Test the non-allocation path + ini_msg, ini_payload, res_status = noise.handshake_responder_step(&res_hs, res_msg, nil, dst = hs_msg_buf[:]) + delete(res_msg, allocator) + res_msg = nil + + if !testing.expectf(t, len(ini_payload) == 0, "step %d: unexpected initiator payload: %x", i, ini_payload) { + return false + } + if !testing.expectf(t, res_status == .Handshake_Pending || res_status == .Handshake_Complete, "step %d: responder step failed: %v", i, res_status) { + return false + } + } + delete(res_msg, allocator) + + hs_pub: ^ecdh.Public_Key + if ini_s != nil { + hs_pub, status = noise.handshake_peer_identity(&res_hs) + if !testing.expect(t, status == .Ok) { + return false + } + if !testing.expectf(t, ecdh.public_key_equal(&ini_s._pub_key, hs_pub), "responder has incorrect initiator identity") { + return false + } + } + if res_s != nil { + hs_pub, status = noise.handshake_peer_identity(&ini_hs) + if !testing.expect(t, status == .Ok) { + return false + } + if !testing.expectf(t, ecdh.public_key_equal(&res_s._pub_key, hs_pub), "initiator has incorrect responder identity") { + return false + } + } + + h1, h2: []byte + h1, status = noise.handshake_hash(&ini_hs) + if !testing.expect(t, status == .Ok) { + return false + } + h2, status = noise.handshake_hash(&res_hs) + if !testing.expect(t, status == .Ok) { + return false + } + if !testing.expectf(t, bytes.equal(h1, h2), "handshake hash mismatch: %x != %x", h1, h2) { + return false + } + + ini_cs, res_cs: noise.Cipher_States + if !testing.expectf(t, .Ok == noise.handshake_split(&ini_hs, &ini_cs), "failed to split initiator: %v") { + return false + } + if !testing.expectf(t, .Ok == noise.handshake_split(&res_hs, &res_cs), "failed to split responder: %v") { + return false + } + + noise.handshake_reset(&ini_hs) + noise.handshake_reset(&res_hs) + + if !testing.expect(t, test_messages(t, &ini_cs, &res_cs, is_one_way, allocator), "message tests failed") { + return false + } + + noise.cipherstates_reset(&ini_cs) + noise.cipherstates_reset(&res_cs) + + return true +} + +@(private = "file") +test_messages :: proc(t: ^testing.T, ini_cs, res_cs: ^noise.Cipher_States, is_one_way: bool, allocator := context.allocator) -> bool { + ad_buf: [256]byte = --- + payload_buf: [noise.MAX_PACKET_SIZE-noise.TAG_SIZE]byte = --- + + for i in 0..<10 { + ad := ad_buf[:rand.int_max(len(ad_buf))] + payload := payload_buf[:rand.int_max(len(payload_buf))] + + _ = rand.read(payload) + _ = rand.read(ad) + + // Initiator -> Responder (allocate buffers) + tx_msg, status := noise.seal_message(ini_cs, ad, payload, allocator = allocator) + defer delete(tx_msg, allocator) + if !testing.expectf(t, status == .Ok, "i->r %d: seal failed: %v", i, status) { + return false + } + + rx_dst: []byte + rx_dst, status = noise.open_message(res_cs, ad, tx_msg, allocator = allocator) + defer delete(rx_dst, allocator) + if !testing.expectf(t, status == .Ok, "i->r %d: open failed: %v", i, status) { + return false + } + + if !testing.expectf(t, bytes.equal(rx_dst, payload), "i->r %d: payload mismatch") { + return false + } + + if i == 5 { + status = noise.cipherstates_rekey(ini_cs, true) + if !testing.expectf(t, status == .Ok, "i %d: rekey failed: %v", i, status) { + return false + } + status = noise.cipherstates_rekey(res_cs, false) + if !testing.expectf(t, status == .Ok, "r %d: rekey failed: %v", i, status) { + return false + } + } + + if is_one_way { + continue + } + + // Responder -> Initiator (reuse allocated buffers) + tx_msg, status = noise.seal_message(res_cs, ad, payload, tx_msg) + if !testing.expectf(t, status == .Ok, "r->i %d: seal failed: %v", i, status) { + return false + } + + _, status = noise.open_message(ini_cs, ad, tx_msg, rx_dst) + if !testing.expectf(t, status == .Ok, "r->i %d: open failed: %v", i, status) { + return false + } + + if !testing.expectf(t, bytes.equal(rx_dst, payload), "r-i %d: payload mismatch") { + return false + } + } + + return true +} + +@(private = "file") +Test_Protocol :: struct { + handshake_pattern: noise.Handshake_Pattern, + dh: ecdh.Curve, + cipher: aead.Algorithm, + hash: hash.Algorithm, +} + +@(private = "file") +test_protocol_string :: proc(protocol: ^Test_Protocol, allocator := context.allocator) -> string { + dh: string + #partial switch protocol.dh { + case .X25519: dh = "25519" + case .X448: dh = "448" + case: panic("crypto/noise: unsupported DH") + } + + cipher: string + #partial switch protocol.cipher { + case .AES_GCM_256: cipher = "AESGCM" + case .CHACHA20POLY1305: cipher = "ChaChaPoly" + case: panic("crypto/noise: unsupported cipher") + } + + hash: string + #partial switch protocol.hash { + case .SHA256: hash = "SHA256" + case .SHA512: hash = "SHA512" + case .BLAKE2S: hash = "BLAKE2s" + case .BLAKE2B: hash = "BLAKE2b" + case: panic("crypto/noise: unsupported hash") + } + + return fmt.aprintf("Noise_%v_%v_%v_%v", protocol.handshake_pattern, dh, cipher, hash, allocator = allocator) +} diff --git a/tests/core/crypto/test_core_crypto_pqc.odin b/tests/core/crypto/test_core_crypto_pqc.odin new file mode 100644 index 000000000..f00e47b5a --- /dev/null +++ b/tests/core/crypto/test_core_crypto_pqc.odin @@ -0,0 +1,159 @@ +package test_core_crypto + +import "core:bytes" +import "core:fmt" +import "core:log" +import "core:testing" + +import "core:crypto" +import "core:crypto/mldsa" +import "core:crypto/mlkem" + +@(test) +test_mlkem :: proc(t: ^testing.T) { + if !crypto.HAS_RAND_BYTES { + log.info("rand_bytes not supported - skipping") + return + } + + // Test vectors are huge, and are covered by the wycheproof corpus, + // so just test a full key exchange with all supported parameter + // sets. + for params in mlkem.Parameters { + if params == .Invalid { + continue + } + + // Alice + decaps_key: mlkem.Decapsulation_Key + if !testing.expectf( + t, + mlkem.decapsulation_key_generate(&decaps_key, params), + "%v: decapsulation_key_generate", + params, + ) { + continue + } + defer mlkem.decapsulation_key_clear(&decaps_key) + + ek_bytes := make([]byte, mlkem.ENCAPSULATION_KEY_SIZES[params]) + defer delete(ek_bytes) + mlkem.decapsulation_key_encaps_bytes(&decaps_key, ek_bytes) + + // Bob + bob_shared_secret: [mlkem.SHARED_SECRET_SIZE]byte + ciphertext := make([]byte, mlkem.CIPHERTEXT_SIZES[params]) + defer delete(ciphertext) + if !testing.expectf( + t, + mlkem.encaps(params, ek_bytes, bob_shared_secret[:], ciphertext), + "%v: encaps", + params, + ) { + continue + } + + // Alice + alice_shared_secret: [mlkem.SHARED_SECRET_SIZE]byte + if !testing.expectf( + t, + mlkem.decaps(&decaps_key, ciphertext, alice_shared_secret[:]), + "%v: decaps", + params, + ) { + continue + } + + testing.expectf( + t, + bytes.equal(alice_shared_secret[:], bob_shared_secret[:]), + "%v: shared secret mismatch", + params, + ) + } +} + +@(test) +test_mldsa :: proc(t: ^testing.T) { + TEST_MSG : string : "ML-DSA test message" + msg_bytes := transmute([]byte)(TEST_MSG) + + // Test vectors are huge, and are covered by the wycheproof corpus, + // so do some casual tests. + for params in mldsa.Parameters { + if params == .Invalid { + continue + } + + seed: [mldsa.PRIVATE_KEY_SEED_SIZE]byte + fmt.bprintf(seed[:], "odin test - %v", params) + + priv_key: mldsa.Private_Key + if !testing.expectf( + t, + mldsa.private_key_set_bytes(&priv_key, params, seed[:]), + "%v: private_key_set_bytes", + params, + ) { + continue + } + + sig_det_bytes := make([]byte, mldsa.SIGNATURE_SIZES[params]) + defer delete(sig_det_bytes) + + if !testing.expectf( + t, + mldsa.sign(&priv_key, nil, msg_bytes, sig_det_bytes, true), + "%v: sign (deterministic)", + params, + ) { + continue + } + + pub_key: mldsa.Public_Key + mldsa.public_key_set_priv(&pub_key, &priv_key) + + if !testing.expectf( + t, + mldsa.verify(&pub_key, nil, msg_bytes, sig_det_bytes), + "%v: verify (deterministic)", + params, + ) { + continue + } + + if !crypto.HAS_RAND_BYTES { + continue + } + + sig_hedged_bytes := make([]byte, mldsa.SIGNATURE_SIZES[params]) + defer delete(sig_hedged_bytes) + + if !testing.expectf( + t, + mldsa.sign(&priv_key, nil, msg_bytes, sig_hedged_bytes), + "%v: sign (hedged)", + params, + ) { + continue + } + + if !testing.expectf( + t, + mldsa.verify(&pub_key, nil, msg_bytes, sig_hedged_bytes), + "%v: verify (hedged)", + params, + ) { + continue + } + + // False positive rate of 1/(2^256), assuming a functional + // entropy source. + testing.expectf( + t, + !bytes.equal(sig_det_bytes, sig_hedged_bytes), + "%v: deterministic sig should not equal hedged", + params, + ) + } +} diff --git a/tests/core/crypto/test_core_crypto_weierstrass.odin b/tests/core/crypto/test_core_crypto_weierstrass.odin new file mode 100644 index 000000000..dcb17aa3d --- /dev/null +++ b/tests/core/crypto/test_core_crypto_weierstrass.odin @@ -0,0 +1,950 @@ +package test_core_crypto + +import "core:crypto" +import ec "core:crypto/_weierstrass" +import "core:encoding/hex" +import "core:math/big" +import "core:testing" + +@(private="file") +P256_G_X : string : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296" +@(private="file") +P256_G_Y : string : "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" +@(private="file") +P256_G_UNCOMPRESSED :: "04" + P256_G_X + P256_G_Y + +@(private="file") +P384_G_X : string : "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7" +@(private="file") +P384_G_Y : string : "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f" + +@(test) +test_p256_a :: proc(t: ^testing.T) { + a_str := "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + + fe, a_fe: ec.Field_Element_p256r1 + ec.fe_a(&fe) + ec.fe_a(&a_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == a_str) + + b_, _ := hex.decode(transmute([]byte)(a_str), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &a_fe) == 1, "%v", &fe) +} + +@(test) +test_p384_a :: proc(t: ^testing.T) { + a_str := "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc" + fe, a_fe: ec.Field_Element_p384r1 + ec.fe_a(&fe) + ec.fe_a(&a_fe) + + b: [48]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == a_str) + + b_, _ := hex.decode(transmute([]byte)(a_str), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &a_fe) == 1, "%v", &fe) +} + +@(test) +test_p256_b :: proc(t: ^testing.T) { + b_str := "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b" + + fe, b_fe: ec.Field_Element_p256r1 + ec.fe_b(&fe) + ec.fe_b(&b_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == b_str) + + b_, _ := hex.decode(transmute([]byte)(b_str), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &b_fe) == 1, "%v", &fe) +} + +@(test) +test_p384_b :: proc(t: ^testing.T) { + b_str := "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef" + fe, b_fe: ec.Field_Element_p384r1 + ec.fe_b(&fe) + ec.fe_b(&b_fe) + + b: [48]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == b_str) + + b_, _ := hex.decode(transmute([]byte)(b_str), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &b_fe) == 1, "%v", &fe) +} + +@(test) +test_p256_g_x :: proc(t: ^testing.T) { + fe, x_fe: ec.Field_Element_p256r1 + ec.fe_gen_x(&fe) + ec.fe_gen_x(&x_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P256_G_X) + + b_, _ := hex.decode(transmute([]byte)(P256_G_X), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &x_fe) == 1, "%v", &fe) +} + +@(test) +test_p384_g_x :: proc(t: ^testing.T) { + fe, x_fe: ec.Field_Element_p384r1 + ec.fe_gen_x(&fe) + ec.fe_gen_x(&x_fe) + + b: [48]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P384_G_X) + + b_, _ := hex.decode(transmute([]byte)(P384_G_X), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &x_fe) == 1, "%v", &fe) +} + +@(test) +test_p256_g_y :: proc(t: ^testing.T) { + fe, y_fe: ec.Field_Element_p256r1 + ec.fe_gen_y(&fe) + ec.fe_gen_y(&y_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P256_G_Y) + + b_, _ := hex.decode(transmute([]byte)(P256_G_Y), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &y_fe) == 1, "%v", &fe) +} + +@(test) +test_p384_g_y :: proc(t: ^testing.T) { + fe, y_fe: ec.Field_Element_p384r1 + ec.fe_gen_y(&fe) + ec.fe_gen_y(&y_fe) + + b: [48]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P384_G_Y) + + b_, _ := hex.decode(transmute([]byte)(P384_G_Y), context.temp_allocator) + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b_) + + testing.expectf(t, ec.fe_equal(&fe, &y_fe) == 1, "%v", &fe) +} + +@(test) +test_p256_scalar_reduce :: proc(t: ^testing.T) { + test_vectors := []struct { + raw: string, + reduced: string, + } { + // n + { + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + // n + 1 + { + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "0000000000000000000000000000000000000000000000000000000000000001", + }, + // 2^384 (Sage) + { + "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "431905529c0166ce652e96b7ccca0a99679b73e19ad16947f01cf013fc632551", + }, + // SHA384 odin-linux-amd64-dev-2026-01.tar.gz (Sage) + { + "87622f79b4b0e76001f9c99b0337b61a0bcd2b5a8e9a3937176825ad75ef0fe8742a348a251dd2682d711f76b33df3e6", + "f66db86e28d903033d1e17d818c0eb13fe3d1ae095b4d2ecbcd1a1eccf9f2f8c", + }, + // SHA512 odin-linux-amd64-dev-2026-01.tar.gz (Sage) + { + "6f85507cec3a35fdb3d4f40d23583681144561e77bc4ea88ab0ea219d5c17b7c9178f5f5a6296a2d18eddd4bdf19e61830fc85d7de23fd4fbde31c4cf6694719", + "3217ecbee32c8b0dfcca0f10a884fe43658fbe91458f25d0f1bf2075759c5ebe", + }, + } + + for v, _ in test_vectors { + raw_bytes, _ := hex.decode(transmute([]byte)(v.raw), context.temp_allocator) + + sc: ec.Scalar_p256r1 + _ = ec.sc_set_bytes(&sc, raw_bytes) + + b: [ec.SC_SIZE_P256R1]byte + ec.sc_bytes(b[:], &sc) + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expectf(t, v.reduced == s, "sc: raw %s reduced: %s, expected: %s", v.raw, s, v.reduced) + } +} + +@(test) +test_p384_scalar_reduce :: proc(t: ^testing.T) { + test_vectors := []struct { + raw: string, + reduced: string, + } { + // n + { + "ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + // n + 1 + { + "ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52974", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + }, + // SHA384 odin-linux-amd64-dev-2026-01.tar.gz + { + "87622f79b4b0e76001f9c99b0337b61a0bcd2b5a8e9a3937176825ad75ef0fe8742a348a251dd2682d711f76b33df3e6", + "87622f79b4b0e76001f9c99b0337b61a0bcd2b5a8e9a3937176825ad75ef0fe8742a348a251dd2682d711f76b33df3e6", + }, + // SHA512 odin-linux-amd64-dev-2026-01.tar.gz (Sage) + { + "6f85507cec3a35fdb3d4f40d23583681144561e77bc4ea88ab0ea219d5c17b7c9178f5f5a6296a2d18eddd4bdf19e61830fc85d7de23fd4fbde31c4cf6694719", + "144561e77bc4ea88c3b80eb3d044daa78b2dd5878dca766578e9c1aad3dba0d211ec862c36d2a7412917b70237c92226", + }, + } + + for v, _ in test_vectors { + raw_bytes, _ := hex.decode(transmute([]byte)(v.raw), context.temp_allocator) + + sc: ec.Scalar_p384r1 + _ = ec.sc_set_bytes(&sc, raw_bytes) + + b: [ec.SC_SIZE_P384R1]byte + ec.sc_bytes(b[:], &sc) + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expectf(t, v.reduced == s, "sc: raw %s reduced: %s (%v), expected: %s", v.raw, s, &sc, v.reduced) + } +} + +@(test) +test_p256_scalar_mul :: proc(t: ^testing.T) { + test_vectors := []struct { + scalar: string, // NOTE: Base 10 + x, y: string, + } { + // Test vectors from http://point-at-infinity.org/ecc/nisttv + { + "1", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + + }, + { + "2", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1", + }, + { + "3", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032", + }, + { + "4", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "E0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6", + }, + { + "5", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "E0C17DA8904A727D8AE1BF36BF8A79260D012F00D4D80888D1D0BB44FDA16DA4", + }, + { + "6", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "E85C10743237DAD56FEC0E2DFBA703791C00F7701C7E16BDFD7C48538FC77FE2", + }, + { + "7", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "73EB1DBDE03318366D069F83A6F5900053C73633CB041B21C55E1A86C1F400B4", + }, + { + "8", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "AD5ACCBD91E9D8244FF15D771167CEE0A2ED51F6BBE76A78DA540A6A0F09957E", + }, + { + "9", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "2A2744C972C9FCE787014A964A8EA0C84D714FEAA4DE823FE85A224A4DD048FA", + }, + { + "10", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "878662A229AAAE906E123CDD9D3B4C10590DED29FE751EEECA34BBAA44AF0773", + }, + { + "11", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "9099209ACCC4C8A224C843AFA4F4C68A090D04DA5E9889DAE2F8EEFCE82A3740", + }, + { + "12", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "0770B46A9C385FDC567383554887B1548EEB912C35BA5CA71995FF22CD4481D3", + }, + { + "13", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "63BB58CD4EBEA558A24091ADB40F4E7226EE14C3A1FB4DF39C43BBE2EFC7BFD8", + }, + { + "14", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "F599F1BB29F4317542121F8C05A2E7C37171EA77735090081BA7C82F60D0B375", + }, + { + "15", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "B5B93EE3592E2D1F4E6594E51F9643E62A3B21CE75B5FA3F47E59CDE0D034F36", + }, + { + "16", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "A985FE61341F260E6CB0A1B5E11E87208599A0040FC78BAA0E9DDD724B8C5110", + }, + { + "17", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "AA005EE6B5B957286231856577648E8381B2804428D5733F32F787FF71F1FCDC", + }, + { + "18", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2", + }, + { + "19", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "58D7614B24D9EF515C35E7100D6D6CE4A496716E30FA3E03E39150752BCECDAA", + }, + { + "20", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "76E49B6DE2F73234AE6A5EB9D612B75C9F2202BB6923F54FF8240AAA86F640B8", + }, + { + "112233445566778899", + "339150844EC15234807FE862A86BE77977DBFB3AE3D96F4C22795513AEAAB82F", + "B1C14DDFDC8EC1B2583F51E85A5EB3A155840F2034730E9B5ADA38B674336A21", + }, + { + "112233445566778899112233445566778899", + "1B7E046A076CC25E6D7FA5003F6729F665CC3241B5ADAB12B498CD32F2803264", + "BFEA79BE2B666B073DB69A2A241ADAB0738FE9D2DD28B5604EB8C8CF097C457B", + }, + { + "029852220098221261079183923314599206100666902414330245206392788703677545185283", + "9EACE8F4B071E677C5350B02F2BB2B384AAE89D58AA72CA97A170572E0FB222F", + "1BBDAEC2430B09B93F7CB08678636CE12EAAFD58390699B5FD2F6E1188FC2A78", + }, + { + "057896042899961394862005778464643882389978449576758748073725983489954366354431", + "878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D", + "714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E", + }, + { + "57896042899961394862005778464643882389978449576758748073725983489954366354431", + "878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D", + "714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E", + }, + { + "1766845392945710151501889105729049882997660004824848915955419660366636031", + "659A379625AB122F2512B8DADA02C6348D53B54452DFF67AC7ACE4E8856295CA", + "49D81AB97B648464D0B4A288BD7818FAB41A16426E943527C4FED8736C53D0F6", + }, + { + "28948025760307534517734791687894775804466072615242963443097661355606862201087", + "CBCEAAA8A4DD44BBCE58E8DB7740A5510EC2CB7EA8DA8D8F036B3FB04CDA4DE4", + "4BD7AA301A80D7F59FD983FEDBE59BB7B2863FE46494935E3745B360E32332FA", + }, + { + "113078210460870548944811695960290644973229224625838436424477095834645696384", + "F0C4A0576154FF3A33A3460D42EAED806E854DFA37125221D37935124BA462A4", + "5B392FA964434D29EEC6C9DBC261CF116796864AA2FAADB984A2DF38D1AEF7A3", + }, + { + "12078056106883488161242983286051341125085761470677906721917479268909056", + "5E6C8524B6369530B12C62D31EC53E0288173BD662BDF680B53A41ECBCAD00CC", + "447FE742C2BFEF4D0DB14B5B83A2682309B5618E0064A94804E9282179FE089F", + }, + { + "57782969857385448082319957860328652998540760998293976083718804450708503920639", + "03792E541BC209076A3D7920A915021ECD396A6EB5C3960024BE5575F3223484", + "FC774AE092403101563B712F68170312304F20C80B40C06282063DB25F268DE4", + }, + { + "57896017119460046759583662757090100341435943767777707906455551163257755533312", + "2379FF85AB693CDF901D6CE6F2473F39C04A2FE3DCD842CE7AAB0E002095BCF8", + "F8B476530A634589D5129E46F322B02FBC610A703D80875EE70D7CE1877436A1", + }, + { + "452312848374287284681282171017647412726433684238464212999305864837160993279", + "C1E4072C529BF2F44DA769EFC934472848003B3AF2C0F5AA8F8DDBD53E12ED7C", + "39A6EE77812BB37E8079CD01ED649D3830FCA46F718C1D3993E4A591824ABCDB", + }, + { + "904571339174065134293634407946054000774746055866917729876676367558469746684", + "34DFBC09404C21E250A9B40FA8772897AC63A094877DB65862B61BD1507B34F3", + "CF6F8A876C6F99CEAEC87148F18C7E1E0DA6E165FFC8ED82ABB65955215F77D3", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044349", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "891B64911D08CDCC5195A14629ED48A360DDFD4596DC0AB007DBF5557909BF47", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044350", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "A7289EB3DB2610AFA3CA18EFF292931B5B698E92CF05C1FC1C6EAF8AD4313255", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044351", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "090E9BA4EA341A246056482026911A58233EE4A4A10B0E08727C4CC6C395BA5D", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044352", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "55FFA1184A46A8D89DCE7A9A889B717C7E4D7FBCD72A8CC0CD0878008E0E0323", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044353", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "567A019DCBE0D9F2934F5E4A1EE178DF7A665FFCF0387455F162228DB473AEEF", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044354", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "4A46C11BA6D1D2E1B19A6B1AE069BC19D5C4DE328A4A05C0B81A6321F2FCB0C9", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044355", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "0A660E43D60BCE8BBDEDE073FA5D183C8E8E15898CAF6FF7E45837D09F2F4C8A", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044356", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "9C44A731B1415AA85DBF6E524BF0B18DD911EB3D5E04B20C63BC441D10384027", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044357", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "F88F4B9463C7A024A98C7CAAB7784EAB71146ED4CA45A358E66A00DD32BB7E2C", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044358", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "6F66DF64333B375EDB37BC505B0B3975F6F2FB26A16776251D07110317D5C8BF", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044359", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "78799D5CD655517091EDC32262C4B3EFA6F212D7018AE11135CB4455BB50F88C", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044360", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "D5D8BB358D36031978FEB569B5715F37B28EB0165B217DC017A5DDB5B22FB705", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044361", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "52A533416E1627DCB00EA288EE98311F5D12AE0A4418958725ABF595F0F66A81", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044362", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "8C14E2411FCCE7CA92F9607C590A6FFFAC38C9CD34FBE4DE3AA1E5793E0BFF4B", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044363", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "17A3EF8ACDC8252B9013F1D20458FC86E3FF0890E381E9420283B7AC7038801D", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044364", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "1F3E82566FB58D83751E40C9407586D9F2FED1002B27F7772E2F44BB025E925B", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044365", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "1F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044366", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044367", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044368", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A", + }, + } + + for v, _ in test_vectors { + x_bytes, _ := hex.decode(transmute([]byte)(v.x), context.temp_allocator) + y_bytes, _ := hex.decode(transmute([]byte)(v.y), context.temp_allocator) + + k_big: big.Int + err := big.set(&k_big, v.scalar, 10, context.temp_allocator) + testing.expectf(t, err == nil, "failed to parse k", err) + + k_sz: int + k_sz, err = big.int_to_bytes_size(&k_big, allocator = context.temp_allocator) + testing.expect(t, err == nil) + + k_bytes := make([]byte, k_sz, context.temp_allocator) + err = big.int_to_bytes_big(&k_big, k_bytes, allocator = context.temp_allocator) + + p, q, expected, g: ec.Point_p256r1 + sc: ec.Scalar_p256r1 + + _ = ec.sc_set_bytes(&sc, k_bytes) + + ec.pt_generator(&g) + ok := ec.pt_set_xy_bytes(&expected, x_bytes, y_bytes) + testing.expectf(t, ok, "failed to set point; %s, %s", v.x, v.y) + + ec.pt_scalar_mul(&p, &g, &sc) + ec.pt_scalar_mul_generator(&q, &sc) + ec.pt_rescale(&p, &p) + ec.pt_rescale(&q, &q) + + testing.expect(t, ec.pt_equal(&p, &q) == 1) + testing.expectf(t, ec.pt_equal(&p, &expected) == 1, "sc: %s actual: %v expected: %v", v.scalar, &p, &expected) + } +} + +@(test) +test_p384_scalar_mul :: proc(t: ^testing.T) { + test_vectors := []struct { + scalar: string, // NOTE: Base 10 + x, y: string, + } { + // Test vectors from http://point-at-infinity.org/ecc/nisttv + { + "1", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + }, + { + "2", + "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61", + "8E80F1FA5B1B3CEDB7BFE8DFFD6DBA74B275D875BC6CC43E904E505F256AB4255FFD43E94D39E22D61501E700A940E80", + }, + { + "3", + "077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831", + "C995F7CA0B0C42837D0BBE9602A9FC998520B41C85115AA5F7684C0EDC111EACC24ABD6BE4B5D298B65F28600A2F1DF1", + }, + { + "4", + "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835", + "CACAE29869A62E1631E8A28181AB56616DC45D918ABC09F3AB0E63CF792AA4DCED7387BE37BBA569549F1C02B270ED67", + }, + { + "5", + "11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B037882F4A1CA297E60ABCDBC3836D84BC", + "8FA696C77440F92D0F5837E90A00E7C5284B447754D5DEE88C986533B6901AEB3177686D0AE8FB33184414ABE6C1713A", + }, + { + "6", + "627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F26257383021317D7202FF30E50937F0854E35C5DF", + "09766A4CB3F8B1C21BE6DDA6C14F1575B2C95352644F774C99864F613715441604C45B8D84E165311733A408D3F0F934", + }, + { + "7", + "283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05526F55B9EBB2040F05B48FB6D0E1", + "9475C99061E41B88BA52EFDB8C1690471A61D867ED799729D9C92CD01DBD225630D84EDE32A78F9E64664CDAC512EF8C", + }, + { + "8", + "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D", + "DCD2365700D4106A835388BA3DB8FD0E22554ADC6D521CD4BD1C30C2EC0EEC196BADE1E9CDD1708D6F6ABFA4022B0AD2", + }, + { + "9", + "8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388528BFEE2B9535C55E4461079118B", + "62C77E1438B601D6452C4A5322C3A9799A9B3D7CA3C400C6B7678854AED9B3029E743EFEDFD51B68262DA4F9AC664AF8", + }, + { + "10", + "A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E85AB507BF91AA9CB2D13186658FB", + "A988B72AE7C1279F22D9083DB5F0ECDDF70119550C183C31C502DF78C3B705A8296D8195248288D997784F6AB73A21DD", + }, + { + "11", + "099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749B66E3AFB81D626356F3B55B4DDD8", + "2E4C0C234E30AB96688505544AC5E0396FC4EED8DFC363FD43FF93F41B52A3255466D51263AAFF357D5DBA8138C5E0BB", + }, + { + "12", + "952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A5E22DA817CB466DA2EA77D2A7022", + "A0320FAF84B5BC0563052DEAE6F66F2E09FB8036CE18A0EBB9028B096196B50D031AA64589743E229EF6BACCE21BD16E", + }, + { + "13", + "A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5F441ABD99F1BAAF1CA1E3B5CBCE7", + "DE1B38B3989F3318644E4147AF164ECC5185595046932EC086329BE057857D66776BCB8272218A7D6423A12736F429CC", + }, + { + "14", + "E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41ABA24DBC02DE6637209ACCF0F59EA0", + "891AE44356FC8AE0932BCBF6DE52C8A933B86191E7728D79C8319413A09D0F48FC468BA05509DE22D7EE5C9E1B67B888", + }, + { + "15", + "B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849557A10B6383B4B88701A9606860B", + "152919E7DF9162A61B049B2536164B1BEEBAC4A11D749AF484D1114373DFBFD9838D24F8B284AF50985D588D33F7BD62", + }, + { + "16", + "D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8EBC773D157811A462B892401DAFCF", + "D815229DE12906D241816D5E9A9448F1D41D4FC40E2A3BDB9CABA57E440A7ABAD1210CB8F49BF2236822B755EBAB3673", + }, + { + "17", + "4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F817012A991AF1F486CAF3A9ADD9FFCC03", + "5ECF94777833059839474594AF603598163AD3F8008AD0CD9B797D277F2388B304DA4D2FAA9680ECFA650EF5E23B09A0", + }, + { + "18", + "DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C2355169CC9C99DFB44692A9B93DD", + "453ACA1243B5EC6B423A68A25587E1613A634C1C42D2EE7E6C57F449A1C91DC89168B7036EC0A7F37A366185233EC522", + }, + { + "19", + "8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8651060801C0E9599E68713F5D41B", + "A1592FF0121460857BE99F2A60669050B2291B68A1039AA0594B32FD7ADC0E8C11FFBA5608004E646995B07E75E52245", + }, + { + "20", + "605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A105D70D4F85C50599BE5800A623F", + "5158EE87962AC6B81F00A103B8543A07381B7639A3A65F1353AEF11B733106DDE92E99B78DE367B48E238C38DAD8EEDD", + }, + { + "112233445566778899", + "A499EFE48839BC3ABCD1C5CEDBDD51904F9514DB44F4686DB918983B0C9DC3AEE05A88B72433E9515F91A329F5F4FA60", + "3B7CA28EF31F809C2F1BA24AAED847D0F8B406A4B8968542DE139DB5828CA410E615D1182E25B91B1131E230B727D36A", + }, + { + "112233445566778899112233445566778899", + "90A0B1CAC601676B083F21E07BC7090A3390FE1B9C7F61D842D27FA315FB38D83667A11A71438773E483F2A114836B24", + "3197D3C6123F0D6CD65D5F0DE106FEF36656CB16DC7CD1A6817EB1D51510135A8F492F72665CFD1053F75ED03A7D04C9", + }, + { + "10158184112867540819754776755819761756724522948540419979637868435924061464745859402573149498125806098880003248619520", + "F2A066BD332DC59BBC3D01DA1B124C687D8BB44611186422DE94C1DA4ECF150E664D353CCDB5CB2652685F8EB4D2CD49", + "D6ED0BF75FDD8E53D87765FA746835B673881D6D1907163A2C43990D75B454294F942EC571AD5AAE1806CAF2BB8E9A4A", + }, + { + "9850501551105991028245052605056992139810094908912799254115847683881357749738726091734403950439157209401153690566655", + "5C7F9845D1C4AA44747F9137B6F9C39B36B26B8A62E8AF97290434D5F3B214F5A0131550ADB19058DC4C8780C4165C4A", + "712F7FCCC86F647E70DB8798228CB16344AF3D00B139B6F8502939C2A965AF0EB4E39E2E16AB8F597B8D5630A50C9D85", + }, + { + "9850502723405747097317271194763310482462751455185699630571661657946308788426092983270628740691202018691293898608608", + "DD5838F7EC3B8ACF1BECFD746F8B668C577107E93548ED93ED0D254C112E76B10F053109EF8428BFCD50D38C4C030C57", + "33244F479CDAC34F160D9E4CE2D19D2FF0E3305B5BF0EEF29E91E9DE6E28F678C61B773AA7E3C03740E1A49D1AA2493C", + }, + { + "1146189371817832990947611400450889406070215735255370280811736587845016396640969656447803207438173695115264", + "CB8ED893530BFBA04B4CA655923AAAD109A62BC8411D5925316C32D33602459C33057A1FBCB5F70AEB295D90F9165FBC", + "426AEE3E91B08420F9B357B66D5AFCBCF3956590BF5564DBF9086042EB880493D19DA39AAA6436C6B5FC66CE5596B43F", + }, + { + "9619341438217097641865390297189708858938017986426152622639500179774624579127744608993294698873437325090751520764", + "67F714012B6B070182122DDD435CC1C2262A1AB88939BC6A2906CB2B4137C5E82B4582160F6403CAB887ACDF5786A268", + "90E31CF398CE2F8C5897C7380BF541075D1B4D3CB70547262B7095731252F181AC0597C66AF8311C7780DB39DEC0BD32", + }, + { + "1231307996623833742387400352380172566077927415136813282735641918395585376659282194317590461518639141730493780722175", + "55A79DF7B53A99D31462C7E1A5ED5623970715BB1021098CB973A7520CBD6365E613E4B2467486FB37E86E01CEE09B8F", + "B95AEB71693189911661B709A886A1867F056A0EFE401EE11C06030E46F7A87731DA4575863178012208707DD666727C", + }, + { + "587118838854683800942906722504810343086699021451906946003274128973058942197377013128840514404789143516741631", + "9539A968CF819A0E52E10EEA3BACA1B6480D7E4DF69BC07002C568569047110EE4FE72FCA423FDD5179D6E0E19C44844", + "A7728F37A0AE0DF2716061900D83A4DA149144129F89A214A8260464BAB609BB322E4E67DE5E4C4C6CB8D25983EC19B0", + }, + { + "153914077530671739663795070876894766451466019374644150541452557147890542143280855693795882295846834387672681660416", + "933FC13276672AB360D909161CD02D830B1628935DF0D800C6ED602C59D575A86A8A97E3A2D697E3ED06BE741C0097D6", + "F35296BD7A6B4C6C025ED6D84338CCCC7522A45C5D4FBDB1442556CAEFB598128FA188793ADA510EB5F44E90A4E4BEF1", + }, + { + "75148784606135150476268171850082176256856776750560539466196504390587921789283134009866871754361028131485122560", + "0CE31E1C4A937071E6EBACA026A93D783848BCC0C1585DAF639518125FCD1F1629D63041ABFB11FFC8F03FA8B6FCF6BF", + "A69EA55BE4BEAB2D5224050FEBFFBDFCFD614624C3B4F228909EB80012F003756D1C377E52F04FA539237F24DD080E2E", + }, + { + "19691383761310193665095292424754807745686799029814707849273381514021788371252213000473497648851202400395528761229312", + "6842CFE3589AC268818291F31D44177A9168DCBC19F321ED66D81ECF59E31B54CCA0DDFD4C4136780171748D69A91C54", + "E3A5ECD5AC725F13DBC631F358C6E817EDCF3A613B83832741A9DB591A0BAE767FC714F70C2E7EA891E4312047DECCC0", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942623", + "605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A105D70D4F85C50599BE5800A623F", + "AEA7117869D53947E0FF5EFC47ABC5F8C7E489C65C59A0ECAC510EE48CCEF92116D16647721C984B71DC73C825271122", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942624", + "8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8651060801C0E9599E68713F5D41B", + "5EA6D00FEDEB9F7A841660D59F996FAF4DD6E4975EFC655FA6B4CD028523F172EE0045A8F7FFB19B966A4F828A1ADDBA", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942625", + "DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C2355169CC9C99DFB44692A9B93DD", + "BAC535EDBC4A1394BDC5975DAA781E9EC59CB3E3BD2D118193A80BB65E36E2366E9748FB913F580C85C99E7BDCC13ADD", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942626", + "4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F817012A991AF1F486CAF3A9ADD9FFCC03", + "A1306B8887CCFA67C6B8BA6B509FCA67E9C52C07FF752F32648682D880DC774BFB25B2CF55697F13059AF10B1DC4F65F", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942627", + "D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8EBC773D157811A462B892401DAFCF", + "27EADD621ED6F92DBE7E92A1656BB70E2BE2B03BF1D5C42463545A81BBF585442EDEF3460B640DDC97DD48AB1454C98C", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942628", + "B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849557A10B6383B4B88701A9606860B", + "EAD6E618206E9D59E4FB64DAC9E9B4E411453B5EE28B650B7B2EEEBC8C2040257C72DB064D7B50AF67A2A773CC08429D", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942629", + "E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41ABA24DBC02DE6637209ACCF0F59EA0", + "76E51BBCA903751F6CD4340921AD3756CC479E6E188D728637CE6BEC5F62F0B603B9745EAAF621DD2811A362E4984777", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942630", + "A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5F441ABD99F1BAAF1CA1E3B5CBCE7", + "21E4C74C6760CCE79BB1BEB850E9B133AE7AA6AFB96CD13F79CD641FA87A82988894347C8DDE75829BDC5ED9C90BD633", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942631", + "952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A5E22DA817CB466DA2EA77D2A7022", + "5FCDF0507B4A43FA9CFAD215190990D1F6047FC931E75F1446FD74F69E694AF1FCE559B9768BC1DD610945341DE42E91", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942632", + "099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749B66E3AFB81D626356F3B55B4DDD8", + "D1B3F3DCB1CF5469977AFAABB53A1FC6903B1127203C9C02BC006C0BE4AD5CD9AB992AEC9C5500CA82A2457FC73A1F44", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942633", + "A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E85AB507BF91AA9CB2D13186658FB", + "567748D5183ED860DD26F7C24A0F132208FEE6AAF3E7C3CE3AFD20873C48FA56D6927E69DB7D77266887B09648C5DE22", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942634", + "8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388528BFEE2B9535C55E4461079118B", + "9D3881EBC749FE29BAD3B5ACDD3C56866564C2835C3BFF39489877AB51264CFC618BC100202AE497D9D25B075399B507", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942635", + "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A3258D6F403D5ECE6E9B269D822C87D", + "232DC9A8FF2BEF957CAC7745C24702F1DDAAB52392ADE32B42E3CF3D13F113E594521E15322E8F729095405CFDD4F52D", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942636", + "283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05526F55B9EBB2040F05B48FB6D0E1", + "6B8A366F9E1BE47745AD102473E96FB8E59E2798128668D62636D32FE242DDA8CF27B120CD5870619B99B3263AED1073", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942637", + "627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F26257383021317D7202FF30E50937F0854E35C5DF", + "F68995B34C074E3DE41922593EB0EA8A4D36ACAD9BB088B36679B09EC8EABBE8FB3BA4717B1E9ACEE8CC5BF82C0F06CB", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942638", + "11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B037882F4A1CA297E60ABCDBC3836D84BC", + "705969388BBF06D2F0A7C816F5FF183AD7B4BB88AB2A211773679ACC496FE513CE889791F51704CCE7BBEB55193E8EC5", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942639", + "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589A1597E3A5120E1EFD631C63E1835", + "35351D679659D1E9CE175D7E7E54A99E923BA26E7543F60C54F19C3086D55B22128C7840C8445A96AB60E3FE4D8F1298", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942640", + "077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831", + "366A0835F4F3BD7C82F44169FD5603667ADF4BE37AEEA55A0897B3F123EEE1523DB542931B4A2D6749A0D7A0F5D0E20E", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942641", + "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0E86EBE0E64F85B96A9C75295DF61", + "717F0E05A4E4C312484017200292458B4D8A278A43933BC16FB1AFA0DA954BD9A002BC15B2C61DD29EAFE190F56BF17F", + }, + { + "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942642", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "C9E821B569D9D390A26167406D6D23D6070BE242D765EB831625CEEC4A0F473EF59F4E30E2817E6285BCE2846F15F1A0", + }, + } + + for v, _ in test_vectors { + x_bytes, _ := hex.decode(transmute([]byte)(v.x), context.temp_allocator) + y_bytes, _ := hex.decode(transmute([]byte)(v.y), context.temp_allocator) + + k_big: big.Int + err := big.set(&k_big, v.scalar, 10, context.temp_allocator) + testing.expectf(t, err == nil, "failed to parse k", err) + + k_sz: int + k_sz, err = big.int_to_bytes_size(&k_big, allocator = context.temp_allocator) + testing.expect(t, err == nil) + + k_bytes := make([]byte, k_sz, context.temp_allocator) + err = big.int_to_bytes_big(&k_big, k_bytes, allocator = context.temp_allocator) + + p, q, expected, g: ec.Point_p384r1 + sc: ec.Scalar_p384r1 + + _ = ec.sc_set_bytes(&sc, k_bytes) + + ec.pt_generator(&g) + ok := ec.pt_set_xy_bytes(&expected, x_bytes, y_bytes) + testing.expectf(t, ok, "failed to set point; %s, %s", v.x, v.y) + + ec.pt_scalar_mul(&p, &g, &sc) + ec.pt_scalar_mul_generator(&q, &sc) + ec.pt_rescale(&p, &p) + ec.pt_rescale(&q, &q) + + testing.expect(t, ec.pt_equal(&p, &q) == 1) + testing.expectf(t, ec.pt_equal(&p, &expected) == 1, "sc: %s actual: %v expected: %v", v.scalar, &p, &expected) + } +} + +@(test) +test_p256_s11n_sec_identity :: proc(t: ^testing.T) { + p: ec.Point_p256r1 + + ec.pt_generator(&p) + ok := ec.pt_set_sec_bytes(&p, []byte{0x00}) + testing.expect(t, ok) + testing.expectf(t, ec.pt_is_identity(&p) == 1, "%v", p) + + b := []byte{0xff} + ok = ec.pt_sec_bytes(b, &p, true) + testing.expect(t, ok) + testing.expect(t, b[0] == 0x00) + + b = []byte{0xff} + ok = ec.pt_sec_bytes(b, &p, false) + testing.expect(t, ok) + testing.expect(t, b[0] == 0x00) +} + +@(test) +test_p256_s11n_sec_generator :: proc(t: ^testing.T) { + p, g: ec.Point_p256r1 + + ec.pt_generator(&g) + ec.pt_identity(&p) + + b: [65]byte + ok := ec.pt_sec_bytes(b[:], &g, false) + testing.expect(t, ok) + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expectf(t, s == P256_G_UNCOMPRESSED, "g: %v bytes: %v, %v", g, P256_G_UNCOMPRESSED, s) + + ok = ec.pt_set_sec_bytes(&p, b[:]) + testing.expectf(t, ok, "%s", s) + testing.expect(t, ec.pt_equal(&g, &p) == 1) +} + +@(test) +test_p256_sc_inv :: proc(t: ^testing.T) { + if crypto.HAS_RAND_BYTES == false { + return + } + + sc, sc_inv, sc_prod, sc_one: ec.Scalar_p256r1 + ec.sc_set_random(&sc) + ec.sc_inv(&sc_inv, &sc) + ec.sc_one(&sc_one) + + ec.sc_mul(&sc_prod, &sc, &sc_inv) + testing.expect(t, ec.sc_equal(&sc_prod, &sc_one) == 1) +} + +@(test) +test_p384_sc_inv :: proc(t: ^testing.T) { + if crypto.HAS_RAND_BYTES == false { + return + } + + sc, sc_inv, sc_prod, sc_one: ec.Scalar_p384r1 + ec.sc_set_random(&sc) + ec.sc_inv(&sc_inv, &sc) + ec.sc_one(&sc_one) + + ec.sc_mul(&sc_prod, &sc, &sc_inv) + testing.expect(t, ec.sc_equal(&sc_prod, &sc_one) == 1) +} \ No newline at end of file diff --git a/tests/core/crypto/wycheproof/README.md b/tests/core/crypto/wycheproof/README.md new file mode 100644 index 000000000..29381c9c0 --- /dev/null +++ b/tests/core/crypto/wycheproof/README.md @@ -0,0 +1,13 @@ +### odin-wycheproof - Odin core/crypto tests +#### Yawning Angel (yawning at schwanenlied dot me) + +This is a test harness that exercises the [Odin][1] `core/crypto` +library with corpus from [Wycheproof][2]. + +``` +$ odin build . -o:speed +$ ./odin-wycheproof ../wycheproof +``` + +[1]: https://odin-lang.org +[2]: https://github.com/C2SP/wycheproof diff --git a/tests/core/crypto/wycheproof/aead.odin b/tests/core/crypto/wycheproof/aead.odin new file mode 100644 index 000000000..6c2b61d72 --- /dev/null +++ b/tests/core/crypto/wycheproof/aead.odin @@ -0,0 +1,514 @@ +package test_wycheproof + +import "core:encoding/hex" +import "core:log" +import "core:mem" +import "core:os" +import "core:slice" +import "core:testing" + +import chacha_simd128 "core:crypto/_chacha20/simd128" +import chacha_simd256 "core:crypto/_chacha20/simd256" +import "core:crypto/aegis" +import "core:crypto/aes" +import "core:crypto/chacha20" +import "core:crypto/chacha20poly1305" + +import "../common" + +supported_aegis_impls :: proc() -> [dynamic]aes.Implementation { + impls := make([dynamic]aes.Implementation, 0, 2, context.temp_allocator) + append(&impls, aes.Implementation.Portable) + if aegis.is_hardware_accelerated() { + append(&impls, aes.Implementation.Hardware) + } + + return impls +} + +@(test) +test_aead_aegis :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + files := []string { + "aegis128L_test.json", + "aegis256_test.json", + } + + log.debug("aead/aegis: starting") + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Aead_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + for impl in supported_aegis_impls() { + testing.expectf(t, test_aead_aegis_impl(&test_vectors, impl), "impl {} failed", impl) + } + } +} + +test_aead_aegis_impl :: proc( + test_vectors: ^Test_Vectors(Aead_Test_Group), + impl: aes.Implementation, +) -> bool { + log.debug("aead/aegis/%v: starting", impl) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "aead/aegis/%v/%d: %s: %+v", + impl, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("aead/aegis/%v/%d: %+v", + impl, + test_vector.tc_id, + test_vector.flags, + ) + } + + key := common.hexbytes_decode(test_vector.key) + iv := common.hexbytes_decode(test_vector.iv) + aad := common.hexbytes_decode(test_vector.aad) + msg := common.hexbytes_decode(test_vector.msg) + ct := common.hexbytes_decode(test_vector.ct) + tag := common.hexbytes_decode(test_vector.tag) + + if len(iv) == 0 { + log.infof( + "aead/aegis/%v/%d: skipped, invalid IVs panic", + impl, + test_vector.tc_id, + ) + num_skipped += 1 + continue + } + + ctx: aegis.Context + aegis.init(&ctx, key, impl) + + if result_is_valid(test_vector.result) { + ct_ := make([]byte, len(ct)) + tag_ := make([]byte, len(tag)) + aegis.seal(&ctx, ct_, tag_, iv, aad, msg) + + ok := common.hexbytes_compare(test_vector.ct, ct_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(ct_)) + log.errorf( + "aead/aegis/%v/%d: ciphertext: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.ct, + x, + ) + num_failed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.tag, tag_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(tag_)) + log.errorf( + "aead/aegis/%v/%d: tag: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.tag, + x, + ) + num_failed += 1 + continue + } + } + + msg_ := make([]byte, len(msg)) + ok := aegis.open(&ctx, msg_, iv, aad, ct, tag) + if !result_check(test_vector.result, ok) { + log.errorf("aead/aegis/%v/%d: decrypt failed", impl, test_vector.tc_id) + num_failed += 1 + continue + } + + if ok && !common.hexbytes_compare(test_vector.msg, msg_) { + x := transmute(string)(hex.encode(msg_)) + log.errorf( + "aead/aegis/%v/%d: decrypt msg: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.msg, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "aead/aegis: ran %d, passed %d, failed %d, skipped %d", + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +supported_aes_impls :: proc() -> [dynamic]aes.Implementation { + impls := make([dynamic]aes.Implementation, 0, 2) + append(&impls, aes.Implementation.Portable) + if aes.is_hardware_accelerated() { + append(&impls, aes.Implementation.Hardware) + } + + return impls +} + +@(test) +test_aead_aes_gcm :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + fn, _ := os.join_path([]string{BASE_PATH, "aes_gcm_test.json"}, context.allocator) + + log.debug("aead/aes-gcm: starting") + + test_vectors: Test_Vectors(Aead_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", fn) { + return + } + + for impl in supported_aes_impls() { + testing.expectf(t, test_aead_aes_gcm_impl(&test_vectors, impl), "impl {} failed", impl) + } +} + +test_aead_aes_gcm_impl :: proc( + test_vectors: ^Test_Vectors(Aead_Test_Group), + impl: aes.Implementation, +) -> bool { + log.debug("aead/aes-gcm/%v: starting", impl) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "aead/aes-gcm/%v/%d: %s: %+v", + impl, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("aead/aes-gcm/%v/%d: %+v", + impl, + test_vector.tc_id, + test_vector.flags, + ) + } + + key := common.hexbytes_decode(test_vector.key) + iv := common.hexbytes_decode(test_vector.iv) + aad := common.hexbytes_decode(test_vector.aad) + msg := common.hexbytes_decode(test_vector.msg) + ct := common.hexbytes_decode(test_vector.ct) + tag := common.hexbytes_decode(test_vector.tag) + + if len(iv) == 0 { + log.infof( + "aead/aes-gcm/%v/%d: skipped, invalid IVs panic", + impl, + test_vector.tc_id, + ) + num_skipped += 1 + continue + } + + ctx: aes.Context_GCM + aes.init_gcm(&ctx, key, impl) + + if result_is_valid(test_vector.result) { + ct_ := make([]byte, len(ct)) + tag_ := make([]byte, len(tag)) + aes.seal_gcm(&ctx, ct_, tag_, iv, aad, msg) + + ok := common.hexbytes_compare(test_vector.ct, ct_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(ct_)) + log.errorf( + "aead/aes-gcm/%v/%d: ciphertext: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.ct, + x, + ) + num_failed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.tag, tag_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(tag_)) + log.errorf( + "aead/aes-gcm/%v/%d: tag: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.tag, + x, + ) + num_failed += 1 + continue + } + } + + msg_ := make([]byte, len(msg)) + ok := aes.open_gcm(&ctx, msg_, iv, aad, ct, tag) + if !result_check(test_vector.result, ok) { + log.errorf("aead/aes-gcm/%v/%d: decrypt failed", impl, test_vector.tc_id) + num_failed += 1 + continue + } + + if ok && !common.hexbytes_compare(test_vector.msg, msg_) { + x := transmute(string)(hex.encode(msg_)) + log.errorf( + "aead/aes-gcm/%v/%d: decrypt msg: expected %s actual %s", + impl, + test_vector.tc_id, + test_vector.msg, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "aead/aes-gcm: ran %d, passed %d, failed %d, skipped %d", + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +supported_chacha_impls :: proc() -> [dynamic]chacha20.Implementation { + impls := make([dynamic]chacha20.Implementation, 0, 3) + append(&impls, chacha20.Implementation.Portable) + if chacha_simd128.is_performant() { + append(&impls, chacha20.Implementation.Simd128) + } + if chacha_simd256.is_performant() { + append(&impls, chacha20.Implementation.Simd256) + } + + return impls +} + +@(test) +test_aead_chacha20_poly1305 :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + files := []string { + "chacha20_poly1305_test.json", + "xchacha20_poly1305_test.json", + } + + log.debug("aead/(x)chacha20poly1305: starting") + + for f, i in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Aead_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + for impl in supported_chacha_impls() { + testing.expectf(t, test_aead_chacha20_poly1305_impl(&test_vectors, i == 1, impl), "impl {} failed", impl) + } + } +} + +test_aead_chacha20_poly1305_impl :: proc( + test_vectors: ^Test_Vectors(Aead_Test_Group), + is_xchacha: bool, + impl: chacha20.Implementation, +) -> bool { + FLAG_INVALID_NONCE_SIZE :: "InvalidNonceSize" + + alg_str := is_xchacha ? "xchacha20poly1305" : "chacha20poly1305" + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "aead/%s/%v/%d: %s: %+v", + alg_str, + impl, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("aead/%s/%v/%d: %+v", + alg_str, + impl, + test_vector.tc_id, + test_vector.flags, + ) + } + + key := common.hexbytes_decode(test_vector.key) + iv := common.hexbytes_decode(test_vector.iv) + aad := common.hexbytes_decode(test_vector.aad) + msg := common.hexbytes_decode(test_vector.msg) + ct := common.hexbytes_decode(test_vector.ct) + tag := common.hexbytes_decode(test_vector.tag) + + if slice.contains(test_vector.flags, FLAG_INVALID_NONCE_SIZE) { + log.infof( + "aead/%s/%v/%d: skipped, invalid nonces panic", + alg_str, + impl, + test_vector.tc_id, + ) + num_skipped += 1 + continue + } + + ctx: chacha20poly1305.Context + switch is_xchacha { + case true: + chacha20poly1305.init_xchacha(&ctx, key, impl) + case false: + chacha20poly1305.init(&ctx, key, impl) + } + + if result_is_valid(test_vector.result) { + ct_ := make([]byte, len(ct)) + tag_ := make([]byte, len(tag)) + chacha20poly1305.seal(&ctx, ct_, tag_, iv, aad, msg) + + ok := common.hexbytes_compare(test_vector.ct, ct_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(ct_)) + log.errorf( + "aead/%s/%v/%d: ciphertext: expected %s actual %s", + alg_str, + impl, + test_vector.tc_id, + test_vector.ct, + x, + ) + num_failed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.tag, tag_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(tag_)) + log.errorf( + "aead/%s/%v/%d: tag: expected %s actual %s", + alg_str, + impl, + test_vector.tc_id, + test_vector.tag, + x, + ) + num_failed += 1 + continue + } + } + + msg_ := make([]byte, len(msg)) + ok := chacha20poly1305.open(&ctx, msg_, iv, aad, ct, tag) + if !result_check(test_vector.result, ok) { + log.errorf("aead/%s/%v/%d: decrypt failed", + alg_str, + impl, + test_vector.tc_id, + ) + num_failed += 1 + continue + } + + if ok && !common.hexbytes_compare(test_vector.msg, msg_) { + x := transmute(string)(hex.encode(msg_)) + log.errorf( + "aead/%s/%v/%d: decrypt msg: expected %s actual %s", + alg_str, + impl, + test_vector.tc_id, + test_vector.msg, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "aead/%s/%v: ran %d, passed %d, failed %d, skipped %d", + alg_str, + impl, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} diff --git a/tests/core/crypto/wycheproof/ecc.odin b/tests/core/crypto/wycheproof/ecc.odin new file mode 100644 index 000000000..839f152bb --- /dev/null +++ b/tests/core/crypto/wycheproof/ecc.odin @@ -0,0 +1,427 @@ +package test_wycheproof + +import "core:encoding/hex" +import "core:log" +import "core:mem" +import "core:os" +import "core:slice" +import "core:strings" +import "core:testing" + +import "core:crypto/hash" +import "core:crypto/ecdh" +import "core:crypto/ecdsa" +import "core:crypto/ed25519" + +import "../common" + +@(test) +test_eddsa_ed25519 :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + fn, _ := os.join_path([]string{BASE_PATH, "ed25519_test.json"}, context.allocator) + + log.debug("eddsa/ed25519: starting") + + test_vectors: Test_Vectors(Eddsa_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", fn) { + return + } + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, i in test_vectors.test_groups { + mem.free_all() // Probably don't need this, but be safe. + pk_bytes := common.hexbytes_decode(test_group.public_key.pk) + + pk: ed25519.Public_Key + pk_ok := ed25519.public_key_set_bytes(&pk, pk_bytes) + if !testing.expectf(t, pk_ok, "eddsa/ed25519/%d: invalid public key: %s", i, test_group.public_key.pk) { + num_failed += len(test_group.tests) + continue + } + + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "eddsa/ed25519/%d: %s: %+v", + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("eddsa/ed25519/%d: %+v", test_vector.tc_id, test_vector.flags) + } + + msg := common.hexbytes_decode(test_vector.msg) + sig := common.hexbytes_decode(test_vector.sig) + + verify_ok := ed25519.verify(&pk, msg, sig) + if !testing.expectf( + t, + result_check(test_vector.result, verify_ok), + "eddsa/ed25519/%d: verify failed: expected %s actual %v", + test_vector.tc_id, + test_vector.result, + verify_ok, + ) { + num_failed += 1 + continue + } + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "eddsa/ed25519: ran %d, passed %d, failed %d, skipped %d", + num_ran, + num_passed, + num_failed, + num_skipped, + ) +} + +@(test) +test_ecdsa :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("ecdsa: starting") + + files := []string { + "ecdsa_secp256r1_sha256_test.json", + "ecdsa_secp256r1_sha512_test.json", + "ecdsa_secp384r1_sha384_test.json", + } + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Ecdsa_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_ecdsa_impl(t, &test_vectors), "ecdsa failed") + } +} + +test_ecdsa_impl :: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Ecdsa_Test_Group)) -> bool { + curve_str := test_vectors.test_groups[0].public_key.curve + hash_str := test_vectors.test_groups[0].sha + + curve_alg: ecdsa.Curve + switch curve_str { + case "secp256r1": + curve_alg = .SECP256R1 + case "secp384r1": + curve_alg = .SECP384R1 + case: + log.errorf("ecdsa: unsupported curve: %s", curve_str) + } + + hash_alg: hash.Algorithm + switch hash_str { + case "SHA-256": + hash_alg = .SHA256 + case "SHA-384": + hash_alg = .SHA384 + case "SHA-512": + hash_alg = .SHA512 + case: + log.errorf("ecdsa: unsupported hash: %s", hash_str) + } + + log.debugf("ecdsa/%s/%s: starting", curve_str, hash_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, i in test_vectors.test_groups { + pk_bytes := common.hexbytes_decode(test_group.public_key.uncompressed) + + pk: ecdsa.Public_Key + pk_ok := ecdsa.public_key_set_bytes(&pk, curve_alg, pk_bytes) + if !testing.expectf(t, pk_ok, "ecdsa/%s/%s/%d: invalid public key: %s", curve_str, hash_str, i, test_group.public_key.uncompressed) { + num_failed += len(test_group.tests) + continue + } + + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "ecdsa/%s/%s/%d: %s: %+v", + curve_str, + hash_str, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("ecdsa/%s/%s/%d: %+v", curve_str, hash_str, test_vector.tc_id, test_vector.flags) + } + + msg := common.hexbytes_decode(test_vector.msg) + sig := common.hexbytes_decode(test_vector.sig) + + verify_ok := ecdsa.verify_asn1(&pk, hash_alg, msg, sig) + if !testing.expectf( + t, + result_check(test_vector.result, verify_ok), + "ecdsa/%s/%s/%d: verify failed: expected %s actual %v", + curve_str, + hash_str, + test_vector.tc_id, + test_vector.result, + verify_ok, + ) { + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "ecdsa/%s/%s: ran %d, passed %d, failed %d, skipped %d", + curve_str, + hash_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +@(test) +test_ecdh :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + PREFIX_TEST_ECDH :: "ecdh_" + SUFFIX_TEST_ECPOINT :: "_ecpoint" + + files := []string { + "ecdh_secp256r1_ecpoint_test.json", + "ecdh_secp384r1_ecpoint_test.json", + "x25519_test.json", + "x448_test.json", + } + + log.debug("ecdh: starting") + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Ecdh_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + alg_str := strings.trim_suffix(f, SUFFIX_TEST_JSON) + alg_str = strings.trim_suffix(alg_str, SUFFIX_TEST_ECPOINT) + alg_str = strings.trim_prefix(alg_str, PREFIX_TEST_ECDH) + testing.expectf(t, test_ecdh_impl(&test_vectors, alg_str), "alg {} failed", alg_str) + } +} + +test_ecdh_impl :: proc( + test_vectors: ^Test_Vectors(Ecdh_Test_Group), + alg_str: string, +) -> bool { + ALG_P256 :: "secp256r1" + ALG_P384 :: "secp384r1" + ALG_X25519 :: "x25519" + ALG_X448 :: "x448" + + // XDH exceptions + FLAG_PUBLIC_KEY_TOO_LONG :: "PublicKeyTooLong" + FLAG_ZERO_SHARED_SECRET :: "ZeroSharedSecret" + + // ECDH exceptions + FLAG_COMPRESSED_POINT :: "CompressedPoint" + FLAG_INVALID_CURVE :: "InvalidCurveAttack" + FLAG_INVALID_ENCODING :: "InvalidEncoding" + + log.debugf("ecdh/%s: starting", alg_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf("ecdh/%s/%d: %s: %+v", alg_str, test_vector.tc_id, comment, test_vector.flags) + } else { + log.debugf("ecdh/%s/%d: %+v", alg_str, test_vector.tc_id, test_vector.flags) + } + + raw_pub := common.hexbytes_decode(test_vector.public) + raw_priv := common.hexbytes_decode(test_vector.private) + + curve: ecdh.Curve + priv_key: ecdh.Private_Key + pub_key: ecdh.Public_Key + + is_nist, is_xdh: bool + switch alg_str { + case ALG_P256: + curve = .SECP256R1 + // Ugh, ASN.1 :( + l := len(raw_priv) + if l == 33 { + if raw_priv[0] == 0 { + raw_priv = raw_priv[1:] + } + } else if l < 32 { + // left-pad.odin + tmp := make([]byte, 32) + copy(tmp[32-l:], raw_priv) + raw_priv = tmp + } + is_nist = true + case ALG_P384: + curve = .SECP384R1 + // Ugh, ASN.1 :( + l := len(raw_priv) + if l == 49 { + if raw_priv[0] == 0 { + raw_priv = raw_priv[1:] + } + } else if l < 48 { + // left-pad.odin + tmp := make([]byte, 48) + copy(tmp[48-l:], raw_priv) + raw_priv = tmp + } + is_nist = true + case ALG_X25519: + curve = .X25519 + is_xdh = true + case ALG_X448: + curve = .X448 + is_xdh = true + case: + log.errorf("ecdh: unsupported algorithm: %s", alg_str) + return false + } + + if ok := ecdh.private_key_set_bytes(&priv_key, curve, raw_priv); !ok { + log.errorf( + "ecdh/%s/%d: failed to deserialize private_key: %s %d %x", + alg_str, + test_vector.tc_id, + test_vector.private, + len(raw_priv), + raw_priv, + ) + num_failed += 1 + continue + } + + if ok := ecdh.public_key_set_bytes(&pub_key, curve, raw_pub); !ok { + if is_nist { + if slice.contains(test_vector.flags, FLAG_COMPRESSED_POINT) { + num_passed += 1 + continue + } + if slice.contains(test_vector.flags, FLAG_INVALID_CURVE) { + num_passed += 1 + continue + } + if slice.contains(test_vector.flags, FLAG_INVALID_ENCODING) { + num_passed += 1 + continue + } + } + if slice.contains(test_vector.flags, FLAG_PUBLIC_KEY_TOO_LONG) { + num_passed += 1 + continue + } + + log.errorf( + "ecdh/%s/%d: failed to deserialize public_key: %s", + alg_str, + test_vector.tc_id, + test_vector.public, + ) + num_failed += 1 + continue + } + + shared := make([]byte, ecdh.SHARED_SECRET_SIZES[curve]) + + ok := ecdh.ecdh(&priv_key, &pub_key, shared) + if !ok { + if is_xdh && slice.contains(test_vector.flags, FLAG_ZERO_SHARED_SECRET) { + num_passed += 1 + continue + } + // unused: x := transmute(string)(hex.encode(shared)) + log.errorf( + "ecdh/%s/%d: ecdh failed", + alg_str, + test_vector.tc_id, + ) + num_failed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.shared, shared) + // "acceptable" results are fine from here because we have + // checked for the all-zero shared secret XDH case already. + if !result_check(test_vector.result, ok, false) { + x := transmute(string)(hex.encode(shared)) + log.errorf( + "ecdh/%s/%d: shared: expected %s actual %s", + alg_str, + test_vector.tc_id, + test_vector.shared, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "ecdh/%s: ran %d, passed %d, failed %d, skipped %d", + alg_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} diff --git a/tests/core/crypto/wycheproof/helpers.odin b/tests/core/crypto/wycheproof/helpers.odin new file mode 100644 index 000000000..13bf4ab4f --- /dev/null +++ b/tests/core/crypto/wycheproof/helpers.odin @@ -0,0 +1,74 @@ +package test_wycheproof + +import "core:crypto/hash" +import "core:fmt" +import "core:strings" + +hash_name_to_algorithm :: proc(alg_str: string) -> (hash.Algorithm, bool) { + alg_enums := [][hash.Algorithm]string { + hash.ALGORITHM_NAMES, + // The HMAC test vectors omit `-`. + #partial [hash.Algorithm]string { + .SHA224 = "SHA224", + .SHA256 = "SHA256", + .SHA384 = "SHA384", + .SHA512 = "SHA512", + .SHA512_256 = "SHA512/256", + .Insecure_SHA1 = "SHA1", + }, + } + for &e in alg_enums { + for n, alg in e { + if n == alg_str { + return alg, true + } + } + } + + return .Invalid, false +} + +MAC_ALGORITHM :: enum { + Invalid, + HMAC, + KMAC128, + KMAC256, + SIPHASH_1_3, + SIPHASH_2_4, + SIPHASH_4_8, +} + +mac_algorithm :: proc(alg_str: string) -> (MAC_ALGORITHM, hash.Algorithm, string, bool) { + PREFIX_HMAC :: "HMAC" + + if strings.has_prefix(alg_str, PREFIX_HMAC) { + alg_str_ := strings.trim_prefix(alg_str, PREFIX_HMAC) + alg, ok := hash_name_to_algorithm(alg_str_) + alg_str_ = fmt.aprintf("hmac/%s", strings.to_lower(alg_str_)) + return .HMAC, alg, alg_str_, ok + } + + ALG_KMAC128 :: "KMAC128" + ALG_KMAC256 :: "KMAC256" + ALG_SIPHASH_1_3 :: "SipHash-1-3" + ALG_SIPHASH_2_4 :: "SipHash-2-4" + ALG_SIPHASH_4_8 :: "SipHash-4-8" + + mac_alg := MAC_ALGORITHM.Invalid + ok := true + switch alg_str { + case ALG_KMAC128: + mac_alg = .KMAC128 + case ALG_KMAC256: + mac_alg = .KMAC256 + case ALG_SIPHASH_1_3: + mac_alg = .SIPHASH_1_3 + case ALG_SIPHASH_2_4: + mac_alg = .SIPHASH_2_4 + case ALG_SIPHASH_4_8: + mac_alg = .SIPHASH_4_8 + case: + ok = false + } + return mac_alg, .Invalid, strings.to_lower(alg_str), ok +} \ No newline at end of file diff --git a/tests/core/crypto/wycheproof/kdf.odin b/tests/core/crypto/wycheproof/kdf.odin new file mode 100644 index 000000000..5b5ea1f2d --- /dev/null +++ b/tests/core/crypto/wycheproof/kdf.odin @@ -0,0 +1,238 @@ +package test_wycheproof + +import "core:encoding/hex" +import "core:log" +import "core:mem" +import "core:os" +import "core:slice" +import "core:strings" +import "core:testing" + +import "core:crypto/hkdf" +import "core:crypto/pbkdf2" + +import "../common" + +@(test) +test_hkdf :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("hkdf: starting") + + files := []string { + "hkdf_sha1_test.json", + "hkdf_sha256_test.json", + "hkdf_sha384_test.json", + "hkdf_sha512_test.json", + } + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Hkdf_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_hkdf_impl(&test_vectors), "hkdf failed") + } +} + +test_hkdf_impl :: proc(test_vectors: ^Test_Vectors(Hkdf_Test_Group)) -> bool { + PREFIX_HKDF :: "HKDF-" + FLAG_SIZE_TOO_LARGE :: "SizeTooLarge" + + alg_str := strings.trim_prefix(test_vectors.algorithm, PREFIX_HKDF) + alg, ok := hash_name_to_algorithm(alg_str) + if !ok { + return false + } + alg_str = strings.to_lower(alg_str) + + log.debugf("hkdf/%s: starting", alg_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "hkdf/%s/%d: %s: %+v", + alg_str, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("hkdf/%s/%d: %+v", alg_str, test_vector.tc_id, test_vector.flags) + } + + ikm := common.hexbytes_decode(test_vector.ikm) + salt := common.hexbytes_decode(test_vector.salt) + info := common.hexbytes_decode(test_vector.info) + + if slice.contains(test_vector.flags, FLAG_SIZE_TOO_LARGE) { + log.infof( + "hkdf/%s/%d: skipped, oversized outputs panic", + alg_str, + test_vector.tc_id, + ) + num_skipped += 1 + continue + } + + okm_ := make([]byte, test_vector.size) + hkdf.extract_and_expand(alg, salt, ikm, info, okm_) + + ok = common.hexbytes_compare(test_vector.okm, okm_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(okm_)) + log.errorf( + "hkdf/%s/%d: shared: expected %s actual %s", + alg_str, + test_vector.tc_id, + test_vector.okm, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "hkdf/%s: ran %d, passed %d, failed %d, skipped %d", + alg_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +@(test) +test_pbkdf2 :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("pbkdf2: starting") + + files := []string { + "pbkdf2_hmacsha1_test.json", + "pbkdf2_hmacsha224_test.json", + "pbkdf2_hmacsha256_test.json", + "pbkdf2_hmacsha384_test.json", + "pbkdf2_hmacsha512_test.json", + } + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Pbkdf_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_pbkdf2_impl(&test_vectors), "pbkdf2 failed") + } +} + +test_pbkdf2_impl :: proc( + test_vectors: ^Test_Vectors(Pbkdf_Test_Group), +) -> bool { + PREFIX_PBKDF_HMAC :: "PBKDF2-HMAC" + FLAG_LARGE_ITERATION_COUNT :: "LargeIterationCount" + + alg_str := strings.trim_prefix(test_vectors.algorithm, PREFIX_PBKDF_HMAC) + alg, ok := hash_name_to_algorithm(alg_str) + if !ok { + return false + } + alg_str = strings.to_lower(alg_str) + + log.debugf("pbkdf2/hmac-%s: starting", alg_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "pbkdf2/hmac-%s/%d: %s: %+v", + alg_str, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("pbkdf2/hmac-%s/%d: %+v", alg_str, test_vector.tc_id, test_vector.flags) + } + + if slice.contains(test_vector.flags, FLAG_LARGE_ITERATION_COUNT) { + log.infof( + "pbkdf2/hmac-%s/%d: skipped, takes fucking forever", + alg_str, + test_vector.tc_id, + ) + num_skipped += 1 + continue + } + + password := common.hexbytes_decode(test_vector.password) + salt := common.hexbytes_decode(test_vector.salt) + + dk_ := make([]byte, test_vector.dk_len) + pbkdf2.derive(alg, password, salt, test_vector.iteration_count, dk_) + + ok = common.hexbytes_compare(test_vector.dk, dk_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(dk_)) + log.errorf( + "pbkdf2/hmac-%s/%d: shared: expected %s actual %s", + alg_str, + test_vector.tc_id, + test_vector.dk, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "pbkdf2/%s: ran %d, passed %d, failed %d, skipped %d", + alg_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} diff --git a/tests/core/crypto/wycheproof/mac.odin b/tests/core/crypto/wycheproof/mac.odin new file mode 100644 index 000000000..35dcc1fde --- /dev/null +++ b/tests/core/crypto/wycheproof/mac.odin @@ -0,0 +1,156 @@ +package test_wycheproof + +import "core:encoding/hex" + +import "core:log" +import "core:mem" +import "core:os" +import "core:testing" + +import "core:crypto/hmac" +import "core:crypto/kmac" +import "core:crypto/siphash" + +import "../common" + +@(test) +test_mac :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("mac: starting") + + files := []string { + "hmac_sha1_test.json", + "hmac_sha224_test.json", + "hmac_sha256_test.json", + "hmac_sha3_224_test.json", + "hmac_sha3_256_test.json", + "hmac_sha3_384_test.json", + "hmac_sha3_512_test.json", + "hmac_sha384_test.json", + // "hmac_sha512_224_test.json", + "hmac_sha512_256_test.json", + "hmac_sha512_test.json", + "hmac_sm3_test.json", + "kmac128_no_customization_test.json", + "kmac256_no_customization_test.json", + "siphash_1_3_test.json", + "siphash_2_4_test.json", + "siphash_4_8_test.json", + } + + for f in files { + mem.free_all() // Probably don't need this, but be safe. + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Mac_Test_Group) + if !testing.expectf(t, load(&test_vectors, fn), "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mac_impl(&test_vectors), "hkdf failed") + } +} + +test_mac_impl :: proc(test_vectors: ^Test_Vectors(Mac_Test_Group)) -> bool { + PREFIX_HMAC :: "HMAC" + PREFIX_KMAC :: "KMAC" + + mac_alg, hmac_alg, alg_str, ok := mac_algorithm(test_vectors.algorithm) + if !ok { + log.errorf("mac: unsupported algorith: %s", test_vectors.algorithm) + return false + } + + log.debugf("%s: starting", alg_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/%d: %s: %+v", + alg_str, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/%d: %+v", alg_str, test_vector.tc_id, test_vector.flags) + } + + key := common.hexbytes_decode(test_vector.key) + msg := common.hexbytes_decode(test_vector.msg) + + tag_ := make([]byte, len(test_vector.tag) / 2) + + #partial switch mac_alg { + case .HMAC: + ctx: hmac.Context + hmac.init(&ctx, hmac_alg, key) + hmac.update(&ctx, msg) + if l := hmac.tag_size(&ctx); l == len(tag_) { + hmac.final(&ctx, tag_) + } else { + // Our hmac package does not support truncation. + tmp := make([]byte, l) + hmac.final(&ctx, tmp) + copy(tag_, tmp) + } + case .KMAC128, .KMAC256: + ctx: kmac.Context + #partial switch mac_alg { + case .KMAC128: + kmac.init_128(&ctx, key, nil) + case .KMAC256: + kmac.init_256(&ctx, key, nil) + } + kmac.update(&ctx, msg) + kmac.final(&ctx, tag_) + case .SIPHASH_1_3: + siphash.sum_1_3(msg, key, tag_) + case .SIPHASH_2_4: + siphash.sum_2_4(msg, key, tag_) + case .SIPHASH_4_8: + siphash.sum_4_8(msg, key, tag_) + } + + ok = common.hexbytes_compare(test_vector.tag, tag_) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(tag_)) + log.errorf( + "%s/%d: tag: expected %s actual %s", + alg_str, + test_vector.tc_id, + test_vector.tag, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s: ran %d, passed %d, failed %d, skipped %d", + alg_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} diff --git a/tests/core/crypto/wycheproof/main.odin b/tests/core/crypto/wycheproof/main.odin new file mode 100644 index 000000000..bfb4884cd --- /dev/null +++ b/tests/core/crypto/wycheproof/main.odin @@ -0,0 +1,84 @@ +package test_wycheproof + +import "core:log" +import "core:testing" + +// Covered: +// - crypto/aegis +// - aegis128L_test.json +// - aegis256_test.json +// - crypto/aes +// - aes_gcm_test.json +// - crypto/chacha20poly1305 +// - chacha20_poly1305_test.json +// - xchacha20_poly1305_test.json +// - crypto/ed25519 +// - ed25519_test.json +// - crypto/hkdf +// - hkdf_sha1_test.json +// - hkdf_sha256_test.json +// - hkdf_sha384_test.json +// - hkdf_sha512_test.json +// - crypto/hmac (Note: We do not implement SHA-512/224) +// - hmac_sha1_test.json +// - hmac_sha224_test.json +// - hmac_sha256_test.json +// - hmac_sha3_224_test.json +// - hmac_sha3_256_test.json +// - hmac_sha3_384_test.json +// - hmac_sha3_512_test.json +// - hmac_sha384_test.json +// - hmac_sha512_224_test.json +// - hmac_sha512_256_test.json +// - hmac_sha512_test.json +// - hmac_sm3_test.json +// - crypto/kmac +// - kmac128_no_customization_test.json +// - kmac256_no_customization_test.json +// - crypto/mlkem +// - mlkem_512_keygen_seed_test.json +// - mlkem_512_encaps_test.json +// - mlkem_512_test.json +// - mlkem_768_keygen_seed_test.json +// - mlkem_768_encaps_test.json +// - mlkem_768_test.json +// - mlkem_1024_keygen_seed_test.json +// - mlkem_1024_encaps_test.json +// - mlkem_1024_test.json +// - crypto/pbkdf2 +// - pbkdf2_hmacsha1_test.json +// - pbkdf2_hmacsha224_test.json +// - pbkdf2_hmacsha256_test.json +// - pbkdf2_hmacsha384_test.json +// - pbkdf2_hmacsha512_test.json +// - crypto/siphash +// - siphash_1_3_test.json +// - siphash_2_4_test.json +// - siphash_4_8_test.json +// - crypto/x25519 +// - x25519_test.json +// - crypto/x448 +// - x448_test.json +// - crypto/_weierstrass +// - ecdh_secp256r1_ecpoint_test.json +// - ecdh_secp384r1_ecpoint_test.json +// - ecdsa_secp256r1_sha256_test.json +// - ecdsa_secp256r1_sha512_test.json +// - ecdsa_secp384r1_sha384_test.json +// +// Not covered (not in wycheproof): +// - crypto/blake2b +// - crypto/blake2s +// - crypto/legacy/keccak +// - crypto/legacy/md5 +// - crypto/tuplehash + +ARENA_SIZE :: 8 * 1024 * 1024 // There is no kill like overkill. + +BASE_PATH :: ODIN_ROOT + "tests/core/assets/Wycheproof" +SUFFIX_TEST_JSON :: "_test.json" + +@(test) +print_test_vector_path :: proc(t: ^testing.T) { + log.infof("wycheproof path: %s", BASE_PATH) +} diff --git a/tests/core/crypto/wycheproof/pqc.odin b/tests/core/crypto/wycheproof/pqc.odin new file mode 100644 index 000000000..07ce2d02c --- /dev/null +++ b/tests/core/crypto/wycheproof/pqc.odin @@ -0,0 +1,782 @@ +package test_wycheproof + +import "core:encoding/hex" +import "core:log" +import "core:mem" +import "core:os" +import "core:slice" +import "core:testing" + +import "core:crypto/_mlkem" +import "core:crypto/mlkem" + +import "core:crypto/_mldsa" +import "core:crypto/mldsa" + +import "../common" + +@(test) +test_mlkem :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("mlkem: starting") + + files_keygen := []string { + "mlkem_512_keygen_seed_test.json", + "mlkem_768_keygen_seed_test.json", + "mlkem_1024_keygen_seed_test.json", + } + for f in files_keygen { + mem.free_all() + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Kem_Test_Group) + load_ok := load(&test_vectors, fn) + if !testing.expectf(t, load_ok, "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mlkem_keygen(t, &test_vectors), "ML-KEM KeyGen failed") + } + + files_encaps := []string { + "mlkem_512_encaps_test.json", + "mlkem_768_encaps_test.json", + "mlkem_1024_encaps_test.json", + } + for f in files_encaps { + mem.free_all() + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Kem_Test_Group) + load_ok := load(&test_vectors, fn) + if !testing.expectf(t, load_ok, "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mlkem_encaps(t, &test_vectors), "ML-KEM Encaps failed") + } + + files_decaps := []string { + "mlkem_512_test.json", + "mlkem_768_test.json", + "mlkem_1024_test.json", + } + for f in files_decaps { + mem.free_all() + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Kem_Test_Group) + load_ok := load(&test_vectors, fn) + if !testing.expectf(t, load_ok, "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mlkem_decaps(t, &test_vectors), "ML-KEM Decaps failed") + } +} + +test_mlkem_keygen :: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Kem_Test_Group)) -> bool { + params_str := test_vectors.test_groups[0].parameter_set + params := mlkem_parameter_set_to_params(params_str) + if params == .Invalid { + return false + } + + log.debugf("%s: KeyGen starting", params_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, tg_id in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/KeyGen/%d/%d: %s: %+v", + params_str, + tg_id, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/KeyGen/%d/%d: %+v", params_str, tg_id, test_vector.tc_id, test_vector.flags) + } + + seed := common.hexbytes_decode(test_vector.seed) + + dk: mlkem.Decapsulation_Key + if !testing.expectf( + t, + mlkem.decapsulation_key_set_bytes(&dk, params, seed), + "%s/KeyGen/%d/%d: failed to set decapsulation key from seed: %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.seed, + ) { + num_failed += 1 + continue + } + + ek_bytes := make([]byte, mlkem.ENCAPSULATION_KEY_SIZES[params]) + mlkem.decapsulation_key_encaps_bytes(&dk, ek_bytes) + + ok := common.hexbytes_compare(test_vector.ek, ek_bytes) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(ek_bytes)) + log.errorf( + "%s/KeyGen/%d/%d: ek: expected %s actual %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.ek, + x, + ) + num_failed += 1 + continue + } + + dk_bytes := make([]byte, mlkem.DECAPSULATION_KEY_EXPANDED_SIZES[params]) + mlkem.decapsulation_key_expanded_bytes(&dk, dk_bytes) + + ok = common.hexbytes_compare(test_vector.dk, dk_bytes) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(dk_bytes)) + log.errorf( + "%s/KeyGen/%d/%d: dk: expected %s actual %s", + tg_id, + params_str, + test_vector.tc_id, + test_vector.dk, + x, + ) + num_failed += 1 + continue + } + + seed_bytes: [mlkem.DECAPSULATION_KEY_SEED_SIZE]byte + mlkem.decapsulation_key_bytes(&dk, seed_bytes[:]) + + ok = common.hexbytes_compare(test_vector.seed, seed_bytes[:]) + if !result_check(test_vector.result, ok) { + x := transmute(string)(hex.encode(seed_bytes[:])) + log.errorf( + "%s/KeyGen/%d/%d: seed: expected %s actual %s", + tg_id, + params_str, + test_vector.tc_id, + test_vector.seed, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s/KeyGen: ran %d, passed %d, failed %d, skipped %d", + params_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +test_mlkem_encaps :: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Kem_Test_Group)) -> bool { + params_str := test_vectors.test_groups[0].parameter_set + params := mlkem_parameter_set_to_params(params_str) + if params == .Invalid { + return false + } + + log.debugf("%s: Encaps starting", params_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, tg_id in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/Encaps/%d/%d: %s: %+v", + params_str, + tg_id, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/Encaps/%d/%d: %+v", params_str, tg_id, test_vector.tc_id, test_vector.flags) + } + + ek: mlkem.Encapsulation_Key + ok := mlkem.encapsulation_key_set_bytes( + &ek, + params, + common.hexbytes_decode(test_vector.ek), + ) + + // The current corpus can only fail if the encapsulation key + // is malformed in some way. + if !result_check(test_vector.result, ok) { + log.errorf( + "%s/Encaps/%d/%d: unexpected set encapsulation key from bytes: %s (%v != %v)", + params_str, + tg_id, + test_vector.tc_id, + test_vector.ek, + test_vector.result, + ok, + ) + num_failed += 1 + continue + } + if !ok { + num_passed += 1 + continue + } + + shared_secret: [mlkem.SHARED_SECRET_SIZE]byte + ciphertext := make([]byte, mlkem.CIPHERTEXT_SIZES[params]) + + _mlkem.kem_encaps_internal( + shared_secret[:], + ciphertext, + &ek, + common.hexbytes_decode(test_vector.m), + ) + + ok = common.hexbytes_compare(test_vector.c, ciphertext) + if !ok { + x := transmute(string)(hex.encode(ciphertext)) + log.errorf( + "%s/Encaps/%d/%d: ciphertext: expected: %s actual: %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.c, + x, + ) + num_failed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.k, shared_secret[:]) + if !ok { + x := transmute(string)(hex.encode(shared_secret[:])) + log.errorf( + "%s/Encaps/%d/%d: shared_secret: expected: %s actual: %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.k, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s/Encaps: ran %d, passed %d, failed %d, skipped %d", + params_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +test_mlkem_decaps :: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Kem_Test_Group)) -> bool { + params_str := test_vectors.test_groups[0].parameter_set + params := mlkem_parameter_set_to_params(params_str) + if params == .Invalid { + return false + } + + log.debugf("%s: Decaps starting", params_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, tg_id in test_vectors.test_groups { + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/Decaps/%d/%d: %s: %+v", + params_str, + tg_id, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/Decaps/%d/%d: %+v", params_str, tg_id, test_vector.tc_id, test_vector.flags) + } + + // We do not have an API for decaps with raw seed. + seed := common.hexbytes_decode(test_vector.seed) + switch len(seed) { + case mlkem.DECAPSULATION_KEY_SEED_SIZE: + case: + if testing.expectf( + t, + result_is_invalid(test_vector.result), + "%s/Decaps/%d/%d: test vector expects success with invalid seed", + params_str, + tg_id, + test_vector.tc_id, + ) { + num_passed += 1 + } else { + num_failed += 1 + } + continue + } + + dk: mlkem.Decapsulation_Key + if !testing.expectf( + t, + mlkem.decapsulation_key_set_bytes(&dk, params, seed), + "%s/Decaps/%d/%d: failed to set decapsulation key from seed", + params_str, + tg_id, + test_vector.tc_id, + test_vector.seed, + ) { + num_failed *= 1 + continue + } + + shared_secret: [mlkem.SHARED_SECRET_SIZE]byte + + ok := mlkem.decaps( + &dk, + common.hexbytes_decode(test_vector.c), + shared_secret[:], + ) + if !result_check(test_vector.result, ok) { + log.errorf( + "%s/Decaps/%d/%d: unexpected decapsulation failure", + params_str, + tg_id, + test_vector.tc_id, + ) + num_failed += 1 + continue + } + if !ok { + num_passed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.k, shared_secret[:]) + if !ok { + x := transmute(string)(hex.encode(shared_secret[:])) + log.errorf( + "%s/Decaps/%d/%d: shared_secret: expected: %s actual: %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.k, + x, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s/Decaps: ran %d, passed %d, failed %d, skipped %d", + params_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +@(require_results,private="file") +mlkem_parameter_set_to_params :: proc(s: string) -> mlkem.Parameters { + switch s { + case "ML-KEM-512": + return .ML_KEM_512 + case "ML-KEM-768": + return .ML_KEM_768 + case "ML-KEM-1024": + return .ML_KEM_1024 + case: + return .Invalid + } +} + +@(test) +test_mldsa :: proc(t: ^testing.T) { + arena: mem.Arena + arena_backing := make([]byte, ARENA_SIZE) + defer delete(arena_backing) + mem.arena_init(&arena, arena_backing) + context.allocator = mem.arena_allocator(&arena) + + log.debug("mldsa: starting") + + files_sign := []string { + "mldsa_44_sign_seed_test.json", + "mldsa_65_sign_seed_test.json", + "mldsa_87_sign_seed_test.json", + } + for f in files_sign { + mem.free_all() + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Mldsa_Test_Group) + load_ok := load(&test_vectors, fn) + if !testing.expectf(t, load_ok, "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mldsa_sign(t, &test_vectors), "ML-DSA Sign failed") + } + + files_verify := []string { + "mldsa_44_verify_test.json", + "mldsa_65_verify_test.json", + "mldsa_87_verify_test.json", + } + for f in files_verify { + mem.free_all() + + fn, _ := os.join_path([]string{BASE_PATH, f}, context.allocator) + + test_vectors: Test_Vectors(Mldsa_Test_Group) + load_ok := load(&test_vectors, fn) + if !testing.expectf(t, load_ok, "Unable to load {}", f) { + continue + } + + testing.expectf(t, test_mldsa_verify(t, &test_vectors), "ML-DSA Verify failed") + } +} + +test_mldsa_sign :: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Mldsa_Test_Group)) -> bool { + FLAG_INTERNAL :: "Internal" + FLAG_RANDOMIZED :: "Randomized" + + dummy_rnd: [_mldsa.RNDBYTES]byte + + params_str := test_vectors.algorithm + params := mldsa_parameter_set_to_params(params_str) + if params == .Invalid { + return false + } + + log.debugf("%s: Sign starting", params_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, tg_id in test_vectors.test_groups { + seed := common.hexbytes_decode(test_group.private_seed) + priv_key: mldsa.Private_Key + + tg_len := len(test_group.tests) + switch len(test_group.public_key) { + case 0: + for &test_vector in test_group.tests { + num_ran += 1 + switch result_is_invalid(test_vector.result) { + case true: + num_passed += 1 + case false: + num_failed += 1 + } + } + continue + case: + if !testing.expectf( + t, + mldsa.private_key_set_bytes(&priv_key, params, seed), + "%s/Sign/%d: failed to set private key from seed: %s", + params_str, + tg_id, + test_group.private_seed, + ) { + num_ran += tg_len + num_failed += tg_len + continue + } + } + + pub_bytes := make([]byte, mldsa.PUBLIC_KEY_SIZES[params]) + mldsa.private_key_public_bytes(&priv_key, pub_bytes) + + ok := common.hexbytes_compare(test_group.public_key, pub_bytes) + if !ok { + x := transmute(string)(hex.encode(pub_bytes[:])) + log.errorf( + "%s/Sign/%d: public key: expected: %s actual: %s", + params_str, + tg_id, + test_group.public_key, + x, + ) + num_ran += tg_len + num_failed += tg_len + continue + } + + pub_key: mldsa.Public_Key + if !testing.expectf( + t, + mldsa.public_key_set_bytes(&pub_key, params, pub_bytes), + "%s/Sign/%d: failed to set public key", + params_str, + tg_id, + ) { + num_ran += tg_len + num_failed += tg_len + continue + } + + sig := make([]byte, mldsa.SIGNATURE_SIZES[params]) + for &test_vector in test_group.tests { + num_ran += 1 + + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/Sign/%d/%d: %s: %+v", + params_str, + tg_id, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/Sign/%d/%d: %+v", params_str, tg_id, test_vector.tc_id, test_vector.flags) + } + + ctx := common.hexbytes_decode(test_vector.ctx) + msg := common.hexbytes_decode(test_vector.msg) + + is_external_mu := slice.contains(test_vector.flags, FLAG_INTERNAL) || slice.contains(test_vector.flags, FLAG_RANDOMIZED) + switch is_external_mu { + case false: + ok = mldsa.sign( + &priv_key, + ctx, + msg, + sig, + true, + ) + case true: + rnd := dummy_rnd[:] + if len(test_vector.rnd) != 0 { + rnd = common.hexbytes_decode(test_vector.rnd) + } + + ok = _mldsa.dsa_sign_internal( + sig, + msg, + ctx, + rnd, + &priv_key, + common.hexbytes_decode(test_vector.mu), + ) + } + if !result_check(test_vector.result, ok) { + log.errorf( + "%s/Sign/%d/%d: unexpected sign result: %v", + params_str, + tg_id, + test_vector.tc_id, + ok, + ) + num_failed += 1 + continue + } + if result_is_invalid(test_vector.result) { + num_passed += 1 + continue + } + + ok = common.hexbytes_compare(test_vector.sig, sig) + if !ok { + x := transmute(string)(hex.encode(sig)) + log.errorf( + "%s/Sign/%d/%d: sign: expected: %s actual: %s", + params_str, + tg_id, + test_vector.tc_id, + test_vector.sig, + x, + ) + num_failed += 1 + continue + } + + // Might as well verify as well if we have the ctx/msg. + if !is_external_mu { + if !testing.expectf( + t, + mldsa.verify(&pub_key, ctx, msg, sig), + "%s/Sign/%d/%d: verify failed", + params_str, + tg_id, + test_vector.tc_id, + ) { + num_failed += 1 + continue + } + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s/Sign: ran %d, passed %d, failed %d, skipped %d", + params_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +test_mldsa_verify:: proc(t: ^testing.T, test_vectors: ^Test_Vectors(Mldsa_Test_Group)) -> bool { + params_str := test_vectors.algorithm + params := mldsa_parameter_set_to_params(params_str) + if params == .Invalid { + return false + } + + log.debugf("%s: Verify starting", params_str) + + num_ran, num_passed, num_failed, num_skipped: int + for &test_group, tg_id in test_vectors.test_groups { + tg_len := len(test_group.tests) + + pub_key_bytes := common.hexbytes_decode(test_group.public_key) + pub_key: mldsa.Public_Key + + expected := len(pub_key_bytes) == mldsa.PUBLIC_KEY_SIZES[params] + ok := mldsa.public_key_set_bytes(&pub_key, params, pub_key_bytes) + if !testing.expectf( + t, + ok == expected, + "%s/Verify/%d: failed to set public key", + params_str, + tg_id, + ) { + num_ran += tg_len + num_failed += tg_len + continue + } + if expected == false { + num_ran += tg_len + num_passed += tg_len + continue + } + + for &test_vector in test_group.tests { + if comment := test_vector.comment; comment != "" { + log.debugf( + "%s/Verify/%d/%d: %s: %+v", + params_str, + tg_id, + test_vector.tc_id, + comment, + test_vector.flags, + ) + } else { + log.debugf("%s/Verify/%d/%d: %+v", params_str, tg_id, test_vector.tc_id, test_vector.flags) + } + + num_ran += 1 + + ctx := common.hexbytes_decode(test_vector.ctx) + msg := common.hexbytes_decode(test_vector.msg) + sig := common.hexbytes_decode(test_vector.sig) + + ok = mldsa.verify(&pub_key, ctx, msg, sig) + if !result_check(test_vector.result, ok) { + log.errorf( + "%s/Verify/%d/%d: unexpected verify result: %v", + params_str, + tg_id, + test_vector.tc_id, + ok, + ) + num_failed += 1 + continue + } + + num_passed += 1 + } + } + + assert(num_ran == test_vectors.number_of_tests) + assert(num_passed + num_failed + num_skipped == num_ran) + + log.infof( + "%s/Verify: ran %d, passed %d, failed %d, skipped %d", + params_str, + num_ran, + num_passed, + num_failed, + num_skipped, + ) + + return num_failed == 0 +} + +@(require_results,private="file") +mldsa_parameter_set_to_params :: proc(s: string) -> mldsa.Parameters { + switch s { + case "ML-DSA-44": + return .ML_DSA_44 + case "ML-DSA-65": + return .ML_DSA_65 + case "ML-DSA-87": + return .ML_DSA_87 + case: + return .Invalid + } +} diff --git a/tests/core/crypto/wycheproof/schemas.odin b/tests/core/crypto/wycheproof/schemas.odin new file mode 100644 index 000000000..2e72a1098 --- /dev/null +++ b/tests/core/crypto/wycheproof/schemas.odin @@ -0,0 +1,243 @@ +package test_wycheproof + +@(require) import "core:encoding/json" +@(require) import "core:log" +@(require) import "core:os" + +import "../common" + +Result :: string + +result_check :: proc(r: Result, ok: bool, is_strict := true) -> bool { + switch r { + case "valid": + return ok + case "invalid": + return !ok + case "acceptable": + return !is_strict && ok + case: + panic("wycheproof/common/Result: invalid result string") + } +} + +result_is_valid :: proc(r: Result) -> bool { + return r == "valid" +} + +result_is_invalid :: proc(r: Result) -> bool { + return r == "invalid" +} + +load :: proc(tvs: ^$T/Test_Vectors, fn: string) -> bool { + raw_json, err := os.read_entire_file_from_path(fn, context.allocator) + if err != os.ERROR_NONE { + log.error("failed to load raw JSON") + return false + } + + if err := json.unmarshal(raw_json, tvs); err != nil { + log.errorf("failed to parse JSON: %v", err) + return false + } + + return true +} + +Test_Vectors :: struct($Test_Group: typeid) { + algorithm: string `json:"algorithm"`, + generator_version: string `json:"generatorVersion"`, + number_of_tests: int `json:"numberOfTests"`, + header: []string `json:"header"`, + notes: map[string]Test_Vectors_Note `json:"notes"`, + schema: string `json:"schema"`, + test_groups: []Test_Group `json:"testGroups"`, +} + +Test_Vectors_Note :: struct { + bug_type: string `json:"bugType"`, + description: string `json:"description"`, + links: []string `json:"links"`, +} + +Test_Group_Source :: struct { + name: string `json:"name"`, + version: string `json:"version"`, +} + +Aead_Test_Group :: struct { + iv_size: int `json:"ivSize"`, + key_size: int `json:"keySize"`, + tag_size: int `json:"tagSize"`, + tests: []Aead_Test_Vector `json:"tests"`, +} + +Aead_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + key: common.Hex_Bytes `json:"key"`, + iv: common.Hex_Bytes `json:"iv"`, + aad: common.Hex_Bytes `json:"aad"`, + msg: common.Hex_Bytes `json:"msg"`, + ct: common.Hex_Bytes `json:"ct"`, + tag: common.Hex_Bytes `json:"tag"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Hkdf_Test_Group :: struct { + key_size: int `json:"keySize"`, + tests: []Hkdf_Test_Vector `json:"tests"`, +} + +Hkdf_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + ikm: common.Hex_Bytes `json:"ikm"`, + salt: common.Hex_Bytes `json:"salt"`, + info: common.Hex_Bytes `json:"info"`, + size: int `json:"size"`, + okm: common.Hex_Bytes `json:"okm"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Mac_Test_Group :: struct { + key_size: int `json:"keySize"`, + tag_size: int `json:"tagSize"`, + tests: []Mac_Test_Vector `json:"tests"`, +} + +Mac_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + key: common.Hex_Bytes `json:"key"`, + msg: common.Hex_Bytes `json:"msg"`, + tag: common.Hex_Bytes `json:"tag"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Ecdh_Test_Group :: struct { + curve: string `json:"curve"`, + tests: []Ecdh_Test_Vector `json:"tests"`, +} + +Ecdh_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + public: common.Hex_Bytes `json:"public"`, + private: common.Hex_Bytes `json:"private"`, + shared: common.Hex_Bytes `json:"shared"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Eddsa_Test_Group :: struct { + public_key: Eddsa_Key `json:"publicKey"`, + public_key_der: common.Hex_Bytes `json:"publicKeyDer"`, + public_key_pem: string `json:"publicKeyPem"`, + public_key_jwk: Eddsa_Jwk `json:"publicKeyJwk"`, + type: string `json:"type"`, + tests: []Dsa_Test_Vector `json:"tests"`, +} + +Eddsa_Key :: struct { + type: string `json:"type"`, + curve: string `json:"curve"`, + key_size: int `json:"keySize"`, + pk: common.Hex_Bytes `json:"pk"`, +} + +Eddsa_Jwk :: struct { + kid: string `json:"kid"`, + crv: string `json:"crv"`, + kty: string `json:"kty"`, + x: string `json:"x"`, +} + +Ecdsa_Key :: struct { + type: string `json:"type"`, + curve: string `json:"curve"`, + key_size: int `json:"keySize"`, + uncompressed: common.Hex_Bytes `json:"uncompressed"`, + wx: common.Hex_Bytes `json:"wx"`, + wy: common.Hex_Bytes `json:"wy"`, +} + +Ecdsa_Test_Group :: struct { + public_key: Ecdsa_Key `json:"publicKey"`, + public_key_der: common.Hex_Bytes `json:"publicKeyDer"`, + public_key_pem: string `json:"publicKeyPem"`, + type: string `json:"type"`, + sha: string `json:"sha"`, + tests: []Dsa_Test_Vector `json:"tests"`, +} + +Dsa_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + msg: common.Hex_Bytes `json:"msg"`, + sig: common.Hex_Bytes `json:"sig"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Pbkdf_Test_Group :: struct { + type: string `json:"type"`, + tests: []Pbkdf_Test_Vector `json:"tests"`, +} + +Pbkdf_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + password: common.Hex_Bytes `json:"password"`, + salt: common.Hex_Bytes `json:"salt"`, + iteration_count: u32 `json:"iterationCount"`, + dk_len: int `json:"dkLen"`, + dk: common.Hex_Bytes `json:"dk"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} + +Kem_Test_Group :: struct { + type: string `json:"type"`, + source: Test_Group_Source `json:"source"`, + parameter_set: string `json:"parameterSet"`, + tests: []Kem_Test_Vector `json:"tests"`, +} + +Kem_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + flags: []string `json:"flags"`, + comment: string `json:"comment"`, + seed: common.Hex_Bytes `json:"seed"`, + m: common.Hex_Bytes `json:"m"`, + ek: common.Hex_Bytes `json:"ek"`, + dk: common.Hex_Bytes `json:"dk"`, + c: common.Hex_Bytes `json:"c"`, + k: common.Hex_Bytes `json:"K"`, + result: Result `json:"result"`, +} + +Mldsa_Test_Group :: struct { + type: string `json:"type"`, + private_seed: common.Hex_Bytes `json:"privateSeed"`, + private_key_pkcs8: common.Hex_Bytes `json:"privateKeyPkcs8"`, + public_key: common.Hex_Bytes `json:"publicKey"`, + public_key_der: common.Hex_Bytes `json:"publicKeyDer"`, + source: Test_Group_Source `json:"source"`, + tests: []Mldsa_Test_Vector `json:"tests"`, +} + +Mldsa_Test_Vector :: struct { + tc_id: int `json:"tcId"`, + comment: string `json:"comment"`, + msg: common.Hex_Bytes `json:"msg"`, + rnd: common.Hex_Bytes `json:"rnd"`, + ctx: common.Hex_Bytes `json:"ctx"`, + mu: common.Hex_Bytes `json:"mu"`, + sig: common.Hex_Bytes `json:"sig"`, + result: Result `json:"result"`, + flags: []string `json:"flags"`, +} diff --git a/tests/core/download_assets.py b/tests/core/download_assets.py index fc4a71cdc..e7cc0220d 100644 --- a/tests/core/download_assets.py +++ b/tests/core/download_assets.py @@ -6,281 +6,635 @@ import os import zipfile import hashlib import hmac +import sys +import io +sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') -TEST_SUITES = ['PNG', 'XML', 'BMP'] -DOWNLOAD_BASE_PATH = sys.argv[1] + "/{}" +# The OpenSSL CLI tool installed can be used to easily generate digests: +# $ openssl sha3-512 -mac HMAC -macopt key:"$HMAC_KEY" $FILE_NAME +TEST_SUITES = ['PNG', 'XML', 'BMP', 'JPG', 'Wycheproof', 'Noise'] ASSETS_BASE_URL = "https://raw.githubusercontent.com/odin-lang/test-assets/master/{}/{}" HMAC_KEY = "https://odin-lang.org" HMAC_HASH = hashlib.sha3_512 HMAC_DIGESTS = { - 'basi0g01.png': "eb26159a783a4dcf27878754e34db6960e992072fc565b12360c894746bc6369101df579e3b9a5c478167f0435e89efb2ab5484056f66c7104f07267f043c82d", - 'basi0g02.png': "f0f74d33ee4b3d3c9f1f4aacf8b0620a33cf1d5c6e9f409e11b4a6e95f2ab1c9159c1bd0bcf6f9553397bf670f4c92712b703d496665d4c6e88fdaf6a0c98620", - 'basi0g04.png': "7b81665f353ff6347304b761d26b4f1baa6118daefc4790f4b0e690150a4e6306514f2aef87e2c39e83e56a0b704df987b10a5366244da58697cda4d5d2745c1", - 'basi0g08.png': "6c809574674494d10eb04c58191c4e0b35813c45962ecafe36a9fe5ba44e5d74ba098e0a524a30c1508eb2dad601f04d5230dceb61a307ef1120f07a8bcbc92f", - 'basi0g16.png': "dd439069fb704b8deff3de822314c012e91a0bd84984d2e79888c6394b78557a0ae6197a7b0a4d64eb4e16fc758946c4f1f13d0d06e512ed9743c4a355b02488", - 'basi2c08.png': "e851fb030f88ead2541a01591882dde5fd9f5dea6bb2b11b374394ed86abc7289e72c4c90808b261aceac13111d3c05b39033168b42ffd1c7ea367314b3a8dc5", - 'basi2c16.png': "e0f81dd459860f7eaf04a2c54932547f41cdc9903a1295a26cc4a2087fd79c98a2e5d5e74f22345dba08b1eb12f3f53c9b904c88b756cbae0c19f9d680e2f1e8", - 'basi3p01.png': "aa21cbcd5d64e6e88056af907509f3b98b00d105198ea2a669fcb25b6966f06d5e4e3afc160b2382935e8ab8e7ccf61733424dfb39b9e864306b82f8355bbb58", - 'basi3p02.png': "d6182370236630d42fd75eed7dc54079ddb7fa9bd601eba22a8dc3331dce31b9a9465027145c29bd56cf778ab0ac029df6aa6481ef65c9464a1ce1d89423faa5", - 'basi3p04.png': "2b35fb98884da370f25833d25f0ab4b188cc26440321e95519131c675818c128b2029d38b3477ef94d88052ec6e9f8b1f7410c5576ce0b47b2fb7a5ba771ce48", - 'basi3p08.png': "7415890831958ca34c73de3e33a9c88980e788d10c983c3a00967886f05053d359499bf0bad386af8ee1bfdb73f666e1d541b0ab682c6092ebdbad3d93e145b1", - 'basi4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", - 'basi4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", - 'basi6a08.png': "aea929866edc5e607d7dc90fcd871f4b6d548abb379b9427fce75a773705e0d8c3ed03bb64e530482b72973eb09844638db5db93666ca1605ff6bbaf194f70e8", - 'basi6a16.png': "29b6ce7c2469e24587b87559f85551334c51bd9d7867f4066c0f7dcb01d710e11e87ee8654c91dc986454cd70f8bd6021e2086ea40e48a28d68a9bdf2283573f", - 'basn0g01.png': "52da610af6f97b03fd8e9f8e52276227f57a97e2bc7e47ae9484b2a37472330f8f5ecef2d6de7fde8f7eb8f144f233bdcf8a3d716c5d193e44d9590af2709cea", - 'basn0g02.png': "676c727faf143af658ed6c6333b15e50387c566c1846a4dda636ed4a2dbb1c0d6d32f0db635479f6851047a32c6d9c52898cfda004ea986853f3ee13750ed90a", - 'basn0g04.png': "123a6652b56f5b858373836509f6b7433221e6ff4eb9ce8a68d0d12bfb27cad0c1bb0cb159523ef1ae5997cb07f994bfbfeabcf0a813aa83495f8269a7a6c4e5", - 'basn0g08.png': "ad5ff30613a462a9b61242d42bb7c854b8247d80a1d03a3919dfdfe8a91c8a962ff51932b2411f714f1be7b803cbd4605c1d4441882cad7e8f44dd8d927198a4", - 'basn0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", - 'basn2c08.png': "fd92ba13d2038c632fd8bdd3e33971cc69f561bee1eb04ff7920625c6771e0cf7fdda29e48b8a6ca71702c0624ebbca232793f28bb2073b0247d30ce0c549ad5", - 'basn2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", - 'basn3p01.png': "d262c97549cd1d43e36f5990dac051ead80f1456693c8b1e19a8a48796195831a6ddd5c4a0ac44d22fee51ce4d9392c1c40a0be05571b1b2a961691636d69cd3", - 'basn3p02.png': "a00e375e1fbcc23de38b3b11a0fda4d0204f55473f74e37e0bb5c5f391b37c019293ccddbb99196b9457cd0b7fe5b9e34a55dc6b8167b6909b38813e37a95e46", - 'basn3p04.png': "1a6ab4c567e75b20ee6cdb400dd1f7764a05679c35010e6144fede5a55767dd1861df8e6240e1e59d4166e25d972ff05a41cdfd527818b6ec960a0f9d57d0939", - 'basn3p08.png': "b8f99f6410cc1ac0ceb366e93fc1008f45fb2499e39c489fafa143e8e881f334735e118eec93dde687bf4ea524b4548741c520d770ba6d7071e8fdce576644de", - 'basn4a08.png': "4b7758d4fce3bba95ef3d09cff0ab28c21b8bf568156730fd4e3bcea1c1c2d3ff77f53fe3551f617bd01c8c96e929eb20bf04f5c1a84f37c3cd6bacd4730e6eb", - 'basn4a16.png': "aa0c411f8bb15fc801b072f1048de2fd08761fe245ad267e8503eef8ffe1c39be845e99c04245771afe9b102328129f6375869a4e6cec60eeca641b3e5df3a8b", - 'basn6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", - 'basn6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", - 'bgai4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", - 'bgai4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", - 'bgan6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", - 'bgan6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", - 'bgbn4a08.png': "4fb9b1023c8c7accb93cf42bd345846c787735df01f7db0df4233737f144e2d5348afaededcdd8c2bcf2e53ce00e2ff095c91de14d7818b4b41c396ab85c9137", - 'bggn4a16.png': "302d7c02ddb0be62aeffeeda46957102c13a2701b841a757486cb3eec7b5456cfabc6ee1954f334ad525badc7c607621a72559b01ce338a0f39e2426d0a03fce", - 'bgwn6a08.png': "d380c477775d102288b43c387dbd7b931f85520f2f6151e3ccc5a25764169312d98fcebf69fb86d3d12520edc3de9bfced559ddf73366f0679e52defb9116424", - 'bgyn6a16.png': "b688d395552eb2a8506fa539ee9159b40a57d02c81860bcf76176213504eb10bdd89de7ce9da452e43f2a46c15290755cdc4816738620b27aed45b3ea7f7ee84", - 'ccwn2c08.png': "c4d58269ef360e42870cce5fb0b1134bfe5706f172c5ff916a338978798fc541a463ab4fdb7c91c424fa385f0ac5d6f576967f178b858d7503f609b2daeacb64", - 'ccwn3p08.png': "d89becf7d24dc57c931a8af1b9dc03ae10302785cc67028cec7255e1aa0ffb0d508d894023a98c10a24cf145aa60b93f977acb8231c8fee9d3f0934484757c30", - 'cdfn2c08.png': "a5faf9cfd284d3750ce2c2f8e15d0ff1bca09da4a9d46b8797c7a1a9f2ebe79d7a7a552bad3c3c049d6186460e81e1e7f9b94e7bb98a3c79d2516f6fb7ac6aa6", - 'cdhn2c08.png': "396eec14e76c00d22ee153171243ac531dcf7adad830948dfd5d6f0a84155734b90407e74f8c1ab8cfb0af5084c03f511530739751f8da070379c826545d0237", - 'cdsn2c08.png': "051b0defa4363ceb3fbc44f460f99a10cdd7c15797ea6d8aa62513b8b6fc5000fe542899db464db30eac56d0c9cd2a5d3778c6962f3aaa85a20881951a7f963a", - 'cdun2c08.png': "946074446fb99f0b790146df0f6e362c68e79b46ec7cbc4ce3d3dc9f75f66e58715caac4b3d7aa8fe8360c32abd2702e7228f9c03b4ba2a0d7f2f970a7ba8f32", - 'ch1n3p04.png': "6680e895195295989850129bcf9d0d0c47efca1c3bc363e4ea822c688707955cdcd07ae92e6e213ee388a62e14b51e036f9a9e075ad7b0f736b0cbc5cc4a108d", - 'ch2n3p08.png': "778ba389d9d0bcbe188e2501c7c1d047f1287179b3760b43da0053f0853e77a0575c7179a02f2442b83efa6cc0951b32d09bd7ea3b6848f261f10b8127e4b0e0", - 'cm0n0g04.png': "9e7e94d201a1222383294bd60e2627207b7b99c0bd80aecd677a1b7d8b372de4981b781fb794811d29a4b2c4db4f5a40c953039c31084f8f3de9aff13fbd1dc9", - 'cm7n0g04.png': "33bb0ffdfe54d655683e4e1bd6d963b9a35a6500129b5dd574245e78971de8d19f27b86a76d42056716b90c2bfc950241bfdc6c4b52ee0e125571de36ba61904", - 'cm9n0g04.png': "fd59386d15a1a324c5ff32f574484c1209afe4ad99f7dc12dce45b2a9bfefd33311ec93211fea3a8e61d1ad2f98220b0c15d151be304bdaa7f88126d54299f68", - 'cs3n2c16.png': "93ca3eeba9aef67de15f943fb2383d208ad1a68518ab78c9fa5ea306ad077b789e873f9e453f0354535167aa4e3d3fec715df05e827bf510948bf0e6fa0dacad", - 'cs3n3p08.png': "e8ddabbf0b17db03bcd7ff0c61d08cc971b3b88e3b3ecd2d4a296da8cf7d7708fa5b42ff3d5813d936ab7f5b4bafbf5842fa4c0fcf0cff15258548d2d26882f3", - 'cs5n2c08.png': "4e3eae53e8c27d4c58d8ad8cdff2c06b00a61d1528a41f5566694f10ef33c4a66f40d3d9fc247731c3ba6dfb734c9f2f90ef031c64486fbdf8a825e354fd67b9", - 'cs5n3p08.png': "31ee0f7f789c1203a9b0e81da34960a47017f3fce37bf2b711738ebd535bb3003ef60c2b0b1fca16587a59955c1ae24b9d186d7ead1d3ece6ada2bbfbc5aee85", - 'cs8n2c08.png': "11bbc80c3168f632deb4453f9199c7994255a0f4f2d7d2d2b06a00931fda4c56985b5a2ca8e969893ff2d65bf330c3d3148b80cbf72aacfe0054b612e6ae05e6", - 'cs8n3p08.png': "49ae3a9050487f6cae826407d421f32a8c67977dd057a6e36f1b2e1ec6abdf5cd46c8929ef4d7b565921ed6c9ae0dde89e243714fdf1510503c7d7b8af6d66e3", - 'ct0n0g04.png': "b6a66fda9ad82cb3287a1ef54702926204bbd4186969cdc2e0741a28dae1869ed76939199f44fd7dd78332753cb8b20a53c4bf740e353f2cc4247870cf576848", - 'ct1n0g04.png': "7cdbaebb6be5d9165972b5fa24f2b64ab437f5337f0548f3d212be8aa95e5dee6ff9abd76ec232faafedc4a41ab8825221b6ced2ecab81c1b3ab20042ceb81a3", - 'cten0g04.png': "648769788c3eb4acd06784dc428bab9e7868328aa3cfe3718ee6656e13e40c4502ca5ac1fe6d4baccb666d4a4f6b3a5d3c97d489f9919ae0d26c2dcdc62e526c", - 'ctfn0g04.png': "c40768807f13dee8dd80ab012bf82b7e8551cb20bde3c7b5c4c45ed19c764cb981945ef036292bd9a2838d34b1b52284295133fea326aea9fc391708bf1d1fbe", - 'ctgn0g04.png': "e0cb7a2d983f1c1c38054b02aabeec657e3f85dba3a52b4878798664c8c6db77cef84d01f042368de6e77cd07b7c2cc6e324aa70bd44c2c8a3642f0cc8fc6a65", - 'cthn0g04.png': "b8614c14bc8c32bb3b29d3b0ac9f3d04c0fcaa40818ab86866e2a8ba1e0c6a87a989f499f208a776d47bff8ab09bfa09352d52089b3cd5bf599faf27627a630b", - 'ctjn0g04.png': "02e2e0a5fa8054e7c7e1c583945da06fb31eff9a3fdd1a7c9f76ba3333f20ce60aec8fafe07f608e9d65a6543e97bab0ff8ae66f3995e8035c05a7c53168ca9a", - 'ctzn0g04.png': "ac35974bd1182e339327245ffa1c0afde634b3a67ee9d6e4e22deee983d6d31054e7843cf1720087b88f6510ed70276e9b0bf43deaf861bd16ceb166140352f9", - 'emblem-1024.png': "5b2e174847274069fc8f4e30c32870ddc7c0e3616a3f04fd41583543aa99ac6d9b7d5a63ed1da672c551b4d193568bb58ddac5e87a101b73367c7c3b01e36fa9", - 'exif2c08.png': "e81b85aa36c9aab55754dd8b73d42497c38eddf9ff3c2981529eb62993d8c0ab33d1b5146a350dd8a1c528d42a967733b2f86248ac615e0254fed53d66d0d895", - 'f00n0g08.png': "fa362f0262ce522297ce52bd7d18b1dc28a2eee3e099b4104c2fb6bdc3fbce0b70303e6df31b709b4033b41e8acec29c81d456c67cde741243c9a54f1ba17f17", - 'f00n2c08.png': "040e95e05152c4bb30608556c828f453c46253c7e0ab18984076cde29b5b6afea7b6658cb019a2723af02a5aabadb1af3b1190655256f3477cd54b9ebdd4df91", - 'f01n0g08.png': "5c60761dc803de1509ef33b4e0ee350d15488d73f4b4e2f93311beb19667626f42d91af39873cd078617c5a2e7c46cceb831d53299c3ff2e7486b43a02ce4967", - 'f01n2c08.png': "a2762a0c4905d05469178176966e86ed4f14c3fcf5c88336209cb923d76e73acc94c619947be87b9183afc20bcd002ab2cc84d81897ec8fc0a4bdeb02a2b7863", - 'f02n0g08.png': "adf640a6f60662ad1b47b5666d2ce86489c685284e50d47344af7cda37f4a42697b5e249f5140413bb3c3e563cca09b2693dcea8bd9ad9adad1adf654ce00bb1", - 'f02n2c08.png': "5f70f19d318ff1d9de4c2f728d83952b12b59bfebac213766ef835dd19f8214f56fa92318041eff25e720503542d067bc9fdf91d86016713c68eb1c52870bad4", - 'f03n0g08.png': "742efed3d25ada0449ed60e4fe1dc94abbe494870536946810cc0eef5c3bfbebefd9bb6d1a482cd5e2c2ee0f34a74b2ea796772254d05accb6739c1ab4d19cdd", - 'f03n2c08.png': "adfac7d6dcc7354467cb3f65742e30ecd44a09b5913ffb656664c9c4730e9cfab9c5e0df2ff8995d412b1ea9cd30ec061eead939546bf795e50a2d49cd10bf92", - 'f04n0g08.png': "9f229c609e87e6c3b83fa82f4f59d7b6494b70c7f85cc807b3611a12d5c59953f11c163228f2bb8b2e7ce77ad204e0da099ab06f8fc480d3ab0ca99fef83c23d", - 'f04n2c08.png': "2dd8b926d1f370b3d3ebaa982491fbe446f3c22b89e635c76eeab60c9ccd3ee7cf39773108d2cec647e480d40de88c4173369b4a12a3fccfba9e4040752cfb4b", - 'f99n0g04.png': "b41996ddf1b770d01900c309cfd2f96d6e60df8313cfda3585a731f32166aa447bcf66ef4af907d6417528024961408d06ca0894fbd6a63fd47ee5a9ed541b51", - 'g03n0g16.png': "02a49b9735063a4d1888b550ed961251b150794422b00ca3800ebba09cd55bdcba15cc8dfe0c41e5a99b2f4d3976b32b1cd08aba92f3dfc3960c71e28ec6cb51", - 'g03n2c08.png': "70b3d643218e033959c51279439d80982f338016b4355aff12be51e7bc59a79f5a5d519c0fa5f13db072cc667fb9635654766af2a11ea25c1b6673f554ceb1f4", - 'g03n3p04.png': "7bfab2aef6f2c04063c438a8f5cda38f3221892ec22a83ab3d3441a900b97c0a7184336ffc2e0c6748e4d931fc80855eed5d6b208ba6ac0709ef02bfbab3e8f2", - 'g04n0g16.png': "9a1d60c89bd63e1f2c81adf1ce7025b7f465e00f0c5142d8a67b5a92e2b042d41a352704969f237883e376bf50c911db196d46f8c28c30ef5763e1e717710c8a", - 'g04n2c08.png': "8e482c99cbc90e6e4aa678e5dbdc39f5b432d740ff260ab1ec04ffa199d97ed2e06491cf88eb0bbbda2f4133f174cf3741474305d9645e0268916aaaab43299d", - 'g04n3p04.png': "d95a52bdc83db74dd19aaa56b40bcbcea268492498c7b2348882a4a5ea70c2b258462c3d5cef85e5372188f21001f719afeb2fac635006486c8fc84b96cc4622", - 'g05n0g16.png': "75954c2e19aa2ba43f7011adecded403035ecb21595a5d116896d2bfc1b71eac42c9b6f008a748cd21b70004921832b3e0dafa1fc0fda4c51ad44cd2b4d782c9", - 'g05n2c08.png': "272baa8dc73cbd63f4fb9545288cfdfcee544e266c9074b73b401895188a123960a6000959f9c034f7b5abe2bfa5e6185253447bac82e9fbfa9634d7e9981d95", - 'g05n3p04.png': "81105d25df2bbbdce60e90cb9a7d0784326bc3c2857fdca4f1f3ef7ab301627685057b97b8d0c0c725d92bc0b48aa1b156dadf5e302ca35917f0b407689ba054", - 'g07n0g16.png': "cb6babe4e25f4cc7e0c3602d9f0e9e538f46a4c4e40420c29521799c528da31afd07b614ae64fbc0e9d0904c9f3e7395b31452abdc69c6a03bf1b5817035b669", - 'g07n2c08.png': "c61e8f936afda939d6497687597d3381485b7cc00716101fc4d6f3abf44df63659b762c77ee252a8735f8e0be0809961db17abbd42c5deab5bad10d0b6b28a55", - 'g07n3p04.png': "8151fa9e9ccd1991a05ea129a7363e23de80688c65d0554c7f3142ed7099d01d82d8ef122986693718f221202657ff965b1b6387a237b36ae741e3d4ea693280", - 'g10n0g16.png': "28ad93f3bebed928c3b0bb4beecaa1b1b55e480c7922d2a36c8f92fc0de012adab523c42f22871b82c6683a7ae74864ed1c35a76cfad92dc6692be0b78c22f50", - 'g10n2c08.png': "4b922386b48c0dd51aee3852da4e52c5c4f3eabe3fcb000e4cfdf0c0e8b27d6a6f77fed944932726fe884f468ac24d89c5c46d65db99be1ae797bc4bbee4cd01", - 'g10n3p04.png': "9b106a0db8ea7e4bc3876beed0f13d83b6f3d6d7d7211441379dd8d18db080f5dc81c6d15312cc3c8ae569b991852ad48f167229dec033f1a974d2a95c83cb3c", - 'g25n0g16.png': "0910ee601a4c4cb546c3bf2b5e8a799d199e34e1434c58c75ddad17f2b295920cf3dde9fe05eee19689705f76b11474b4edc73f4ff346b6ab2d02ec40a13d3cb", - 'g25n2c08.png': "080ed57fd4185c00c6c70e48c27612621393a6ef3987aefd1481611f74d0aebc58d1a90386e4e7bb0321eca961e97cd403a7e727f7324196c5a3cf0e07bffce3", - 'g25n3p04.png': "1deb4281d9792af858e715c39ef7e6756f3004845d87f52054efc9f02c679b2b1b6c2a548a5e6a3f31604b115469ba4bb81510470a47ff9a22b133427375a8db", - 'logo-slim.png': "0104624a95b1b8a97bb5013927cb8fbe330a8c9e7197814147702702cd1d44cdde956404786bb0e69927c6b03ed8031bab566599b1291b995ce747f7cb2135eb", - 'oi1n0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", - 'oi1n2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", - 'oi2n0g16.png': "aab1bbfc7b711ba66260985bd8bda6ffaa1e09a0a546b2fe8869b508d823a9e5a412ba6337355a81d87f010e9db8c95eee5f5084b21ddd5cca5d7db7725603b0", - 'oi2n2c16.png': "8d1dd257f3b1bf44ef0bf38338a1e3f2ff78670ac779959751a56231109ca1ed82414f50a221aa45333263073e1e1a950ac8df8e5318e2ed695422d49400c540", - 'oi4n0g16.png': "7675dfa4cff547c3029b21cc892b90a8647199dc9290add932535b04b4eaadaedbc338704f98a075f4690b87815eec8cc0f90a3dbaa2a7809aa03f238ebc5815", - 'oi4n2c16.png': "66313c9d4731e2a9fa006ee9e43c6ac4a3034ce2826c6213f67bfa349bb8bb3cfd8acd2c4553fd1fcd4b2f43993a54539ec8b7fb7f07b3a406adfe919f17b065", - 'oi9n0g16.png': "5615cd4c277be96b21031827d08c8fb2971fda090a0031fd34594f77f7cc558bc68917542597a32bc39c0cd29f7759f0f0429203aa285c163bba8c8f78894e72", - 'oi9n2c16.png': "e2184c00b952a3aa53078a5f995715fa683718a9cbe42705fae3a7c77b236ee6ad706f6dbf2c243aeea17e2c53e84724907724634545e065dd16ff400f5677ab", - 'PngSuite.png': "af1d473e986b3f5cb1006340f8f99156e980e2f8c9f804f0e27c57a51d0dec332a81d99c6e50162f63792d89da44857a6072f8431aa735f1e8f86c06520eff4e", - 'pp0n2c16.png': "82ee5674861b5f9bdab6cf41910d980fc33b5188e191b8892b051dc3b3bbceb4c6d421cbed7bc9b71a9a14db43991c0458ed2cbe5166939f1cbb1e20e445e8b1", - 'pp0n6a08.png': "71c0d4c87b6b2644a4529cd240c8d583c25d45e79fd8bb71ca850dada37e46571052b2da28b926a8194169b82da505c9a3e3a701816d91ac968ad6ff41132b70", - 'ps1n0g08.png': "b273e94c2f826640b10b27b50c605be06541b397ea1289be6f4ea821dff6c7b4b209ec8817a315db442de04c975b7cfecba07b51c6cec965ab9062c05ba04edd", - 'ps1n2c16.png': "833993b81801432eb3a9dbca81f4fdd8ab720c76f8d99a2d298fa1dc4ebd19759c158dd10a68f690f999ea643f62fb7e779e916df86aeb05c43bc4db62aa520b", - 'ps2n0g08.png': "4abea03946d751f03e1438e5987ae691607e528c577db52e893051b54a5d147969dd965e44aaf5540fea75baad873327d76aa71a07c81de31f04f3b781d01e3c", - 'ps2n2c16.png': "bfea51d7be49c04293de034c7649472d34becb663169608490916795fe988df7b812ff8950a3f8d896ee27756effcf9fb525d8d455226cf3965595ee85188581", - 's01i3p01.png': "18b405c902977d2553aab1738a3c00e602e40d11c121a7007c9b7b4cc499aba1fab12fc12aecbdbd5b5cd2638ec5ca5157b5d8fce5dad3cdc3bea02b0904c9cf", - 's01n3p01.png': "8e3e1c9754ebde8c687355b80eee4bf0e0ee8e37b39b784f1997cd2eb60ece7f077b40c8027b0d7f4b7e8f242c22173a244f4e599db33985187439bd918d4486", - 's02i3p01.png': "3e26a8cf35e3df1650adc1656f2d3e7c9b5e1c7932826cf792cbe2cc538c1283ff145f66e4682d459bb0b4f2a2f9ce7209f1997e336e06ca49a83f75270ccad1", - 's02n3p01.png': "d34685ade19ee550ba52e81657627832cb9ba3655f6fe336ebb5fdc4d35c380e819efc1556e1bd1ca2b4e456727dbc5312eb513e7254dfd057a25963e57f0ff4", - 's03i3p01.png': "818a2c91d6c0f96b13806d945d1fc1b4c64f17a9b6a2ede2658c84e20269cd80289312a163761165f0d99e1824f283844f1b4696af314c05714fd349acf7609e", - 's03n3p01.png': "fe847a62eb64bf9db4d9751600b19333f057b626f2f2eb80ee78a3374ae562944c2ebc9c2712f3bbf862798ef9205f38297cad44e8df5dcd96c158ca2e9d9233", - 's04i3p01.png': "1c63332a0d2f31b3a6457038ec2b8c5b4bd3192320fb1c44873947375dcaa028ea07151853e53c6f3fff6878cf90adedea35ae819e5a1b2dbf92399b29464d56", - 's04n3p01.png': "1312d9f3e5bb07b6cbf0c6798c3ae9b0a6cebae465ae6d4ba115ef585616b3b1f7723c6481fcfaa00626d6c62e4fbff7023faf1e92eedeb5354b9805542d43b6", - 's05i3p02.png': "13225a16a79579c4040cdc03f11c71d8589ab322a4f3926e32d9499fe4ca8503a43870e532b2da2597a6c3dd89c3904428cf89c25a8637d40bb3a353017cad5e", - 's05n3p02.png': "d07f2ef30c06a29b9c5c6a52ce1485a3bb9dacb5f119c2829c4cfd69c8fa272d6065eab21a5acd016bdb4f4c724214e8a737c2b76e0f0151e6afcbe5586a37ad", - 's06i3p02.png': "b386f0387e8496849b6d325e710440f7937a403b123886a52af8327e69e411fd632db19daaecfe2e712d49279630515d7217533112acde73cb429e2cfa465b63", - 's06n3p02.png': "df0968c77975f350a86fc09c047d9e3a0a2b71890a0ae67bdfedb23e7f0ce303ff883a463668e10df1dcf2e57cea8cf1fc7c836f5d13a73c1ecd8d66284fc0c5", - 's07i3p02.png': "0f67816f188ce11f15d0f345d2695f1920a322d84be3f332d542c5d20d10a9cef2cebf1e8ae778b25677beeda229c06221eb3450b851ea0e8cd102e5cad14e66", - 's07n3p02.png': "0af60c935e2da2a8a3173edf614085ad0df095c882a140437bdf93ecd5494cfeb5c068dc7ea4d49e181c67d26dd9cf8c969bb2d95f2fbce212ddf5817dd7f642", - 's08i3p02.png': "3204dd0879b6b1284f197a0437e674c4280adad180d4a1d37dff1555be1924d6234dad5d02266aa575d782c53fa52fd4580d452482ba939c732c09709075306f", - 's08n3p02.png': "135039621ce2079465ef49c1b7e5a5aeab299993d2bac864d822ff0669843df1e733a729ca5226ec05c94ddfebdcb2f4b78699fb3adb741db993d9757b4ca71c", - 's09i3p02.png': "dc4d8ed06a81fcd604f949f43e7d5f482c3ad9efd113d220b709de38ca0ca1a340f4cce7e929ca6323390b4ea7c4399cf2f1f2e34c1ef1b38c8296b51d7e8f4b", - 's09n3p02.png': "96b8204f7008899993d8d277ff42c8eb7c85e7cd522cae2e9cf28b8e10e3904c7ec2e3227372f397f6c5a381875dd747a42409471a29ad5049240417ec1441f3", - 's32i3p04.png': "a4de495c70f54eeccd115492a0dfe1cbbcf7f308343eacf6a57515d7a248b356a2639f5e88246d630c8713724cfd7ab1d5d388c677f026a1c5c9b4270a837c67", - 's32n3p04.png': "757009a2fdf19d1187d85930eeb4e75c6831387348fd8e618d1ef971c27d2682b2464b4160a743a6c6d712553fd7fe1f0e5d78226e348f270093495297ec83bf", - 's33i3p04.png': "19259eaf76a42fec949a21c4c55715247a027c2b59ba4bd0f45fdea1f3406cb475c33213b662fd64089b697a6cd25700364f76923dc2531fa0b39546242b3356", - 's33n3p04.png': "3f42b5f3896c1a47fe5dff9921d56234b4326dcffb70a7c6b1f0e7193a6f8f898438635f3b1cfef92c59d7ab827e2a3f40671d97c8547c8e7063a0076c97fba9", - 's34i3p04.png': "db0f7fe138fd732eae4a5c1b8d013167eb3be4afa86141b3e6ad096eabec67644e3108189311b3ce2c78f891d1ea7f5dfa1c30be59509edf123696064eecd00c", - 's34n3p04.png': "e35d9338637ae4c7a1c74a0e73a5c4ba405c2b0d36efd92512b7572d418c25e7d06361be2a8d16323c2708ff3921da24b76be5a41bd3cccf09c27ad472078261", - 's35i3p04.png': "9f0602e1160b81c2e88fc30daf295ff29c4f6faa5a3391c69d895621e7ab76e2071ced6f5a798e294f69621bb32272070ff4ceeeb1436b1cf03640417961a9d1", - 's35n3p04.png': "f12e6a7364073b7a010db0cf952989f5f5da20c592b0256efabb5e82e96d928dce7695c2a0af0749ddfa2739e3ca985463eb0f4a7fb6b8ab0638d65079fc6265", - 's36i3p04.png': "a2d0374bba6fb665deda98b1bd0ef767243b7a974b9f00c78d54bdbfed2c00decf6faef95816ef711efdc359247142be08ce2b86f7860b7384948ba394b4dd21", - 's36n3p04.png': "e200a6869dba1fc9e2eeeff6e686e02313c366a990bfb5582f66dba486251392a465db03806092543008e1130624f1d16cde61613d0ae2a9589941f69a1608db", - 's37i3p04.png': "555f1f7ec2d8ddb58ced7162a4dec315780be13b7cb9ed6d8978046c7fbcb91b4ecf6fcc5c99bd5b8b8d348e4cd202d882a31dec1ecd25156af8968c4a06fbff", - 's37n3p04.png': "d28b3f442b481214774d543924ab07b75fee5916262e6404992962184ea0059ca34fb32d14076642ecd83a3063966ea80676e3165759632782ffd844702cb74e", - 's38i3p04.png': "d4fe0179effbf28f7d28c0192de614512870367cec14ca04d86eb9fff9d6864b1074a68144023244e46cb69ad601e81632c36eb2ed307a32a3c37b7683f882d5", - 's38n3p04.png': "19d23ca8b9b44d26bc9173a69d1d8332e4e7b2ce6e6422195e71dfd0701158023253b130a831a035b2fce0a1556004e8de74e893caeea3d12410909e6e649831", - 's39i3p04.png': "f0c783232707d288b086398565918079e510677742bb5dab09b4520687a06809ae328d24508ebd8f5c26cf85105300ba98e55c29e3773579929839ed9ddbf7fa", - 's39n3p04.png': "39763c31a17edf2751442cf45ae3cc315623ed5b04141bbced2ee8d233485b2d1a2cc0678d60a1c84e3d89a7513634bfd9c82b58754cdfe95885f7a54ff18e2c", - 's40i3p04.png': "d33b29e6669accf1325e8212c555a6cb1d8413c445140aecb62eb6b40912743ef7c6298ad4bc2e232bc448ddaba37f79fa4d25e0cc8e3d53a5ebc93f8f984555", - 's40n3p04.png': "463eb60a2f0884fc368ea0650c5b7b6469c1429e5f006a6537e4aac721094bbd57baa6bcfe4025939089e27b344d7077ff09618e9ce3a5bd40ee3fe5a0e33ce0", - 'tbbn0g04.png': "24fb55d9fed351946869552edb15bf20a2e7a050094ca4b51ebd135958f8b77401e0e9b18618de0cbd18f835e16df24dc57ef094d3b456f0eb9f73c31748ce2a", - 'tbbn2c16.png': "ee98ae3a1cb4a851830ee3e8f4112d08bd74c2a05b778ce51102780ba9d7170c5200c9cc4e1a5c0833618ebe137595eb8fc0591b8798bb6e4e94c234f8cbba3b", - 'tbbn3p08.png': "ed325815b8525d3a5fa37c968b7c85946add7c08abd1c66d86e0264951cfa5a377078b910a78cc664ec2c43d352093c2609b8d01c9572f4ba922d98264e55c04", - 'tbgn2c16.png': "e6da4190d4cea04b0002d598d68c0536448899dd8fca4931b44bc8ea6d47e6946c55ebc5d2049936db2f7f52caef124648d25a360e838571f5f7cb2795eb3657", - 'tbgn3p08.png': "865358d285a8d8682a16b050d9c1b7492042e1a217b0b5753ad28ae1a698dd77150f8cd6510f345157e1efa1411b4e4d5938a81024c150c9d5e76e423105d9c8", - 'tbrn2c08.png': "cc3cd3b8b6cc9920914e0184bdedcf9e59975db3f99c39b93ea1202cf6e11689eb966fc40ae2caca8ef224a8aac03723142b58b701ca2a02fd73a62e379f7a6b", - 'tbwn0g16.png': "fa8359bf8cdac3ab9ac54cd4f1e96b1469ff3e3494102be179b5c7394a4e37953ef54f5e1ccffe771b4f028225ec164b410b0d08f82224ed93a654433feb14fe", - 'tbwn3p08.png': "a0e10707fe9df085596a724561ba6c80662f87095ba479b2345c985f4beb2933f7767fe3d07b30002591259dc14012f4b26fa9b503cc75fd644def7c27c9f2e6", - 'tbyn3p08.png': "9920b40b016c4a05a094c28a989d06e108e2ebd5d72c2a6ddca359b68ad95238b0b6dca0f60b78c56b551a2e44f924d5a443071bda6f6e31669b0a78c09b18af", - 'tm3n3p02.png': "e9910a8ccb78a10980c55c6ca7115757b48075e42c14a83aece92a7f85eee538d5e1d9301efc443a867628993ceff1c13aebcc574641ad85eec48ae05df9997c", - 'tp0n0g08.png': "57fbf8a07060565c23918420952d1feb506ce5b1bdb25f22d41ee1de4ce9655c6dde04b9643d2491b59efba229b7e0cacd6799010a89005802c28a300a4e578e", - 'tp0n2c08.png': "eed3f6c18bd81d96870a47c737574746293c71c517b6a5ba88afdad5ef89fa30d975717f8a8f84ec16cb98390353934cbdd6e4b099e86f0ca3fe8d50fa07bb11", - 'tp0n3p08.png': "9650347d0f4a1a6596828f48766949947148952c93c4899541324a48289ea558c5d7bd1a076ac0e32f71d197e478ffc418e424c52b3fcacd2f94eaae98a566c3", - 'tp1n3p08.png': "fbd0f987d98d96f85679ec237c05925032e8d7783551b3f3cffb1b7db6ebdb3afb61214460386b2a3a011826bbda8340757ba22727325eea9fe518c136969f24", - 'xc1n0g08.png': "6aa3e16f11e82378fa7d3767a785840960f2c152338374e3f64f94eb0799e1f29637a1a66435b6dcdbffb9208efbff65a70e17e80f1e05b3038a837dcf79312c", - 'xc9n2c08.png': "7e0d4285bc67345e092656f04b235b4fc273c7892e26dea339dc2bb8df6348d8477f7e6573fe4f40ede1c94b49a60d46ef47ff4f7327fb12cd6de3737e8b5e4c", - 'xcrn0g04.png': "f971b781eb229ada882bb333bbcce956740f9761581d68ba95b49d998b89499bdd4598c4155e72240d6a5b74c04d7081fe284f78fd3f85f2550a3d2171f6efbb", - 'xcsn0g01.png': "9e1d234c3775920546ab9f9eeabdb75457bd823d48ed677fdfe61a95c02c65730182ba7e84209bfbf59de5d1bea533ca57c90ff6a49ea6d5749636f949bdc16a", - 'xd0n2c08.png': "6458d4b8f10a01ff86207496fbf38b25c35857cc537e9e11085fd5fa7befe956e707e6c1c61bdd76a393a816fdc916e2003fcecf5b33dfeb53c4bb071110eaf0", - 'xd3n2c08.png': "fdf261941945d1231ff3b8e91db063ac5a52e8e56f1fc80c5c51149ed255a4eebb4351194d76ae156bdff1eaf5180184c2aa2dd27e4129498279360e00d7db4e", - 'xd9n2c08.png': "b7a3a47c0863bde4ae8aa5ef5fe5d43f8e29abb413dc002553b63d6a4c1fb79eaee66011f1f45887c218aef3fcd63fda847a1b1bc1975252c3b4fcad553c7b70", - 'xdtn0g01.png': "788ed6f9e7ed64e5f4dfa8b62dd88f6f37f7abd1c8e3abf4db2d1c46f0344e7ba638f6721e69ebffa19cf6536f7685f485e9eb548a3cae55131963da05950acd", - 'xhdn0g08.png': "1f06044e4607902e7bd8ba291bf2b9bbb855a881b4a7dde6a21e9f5f9b74f0f43f55a8aa31fa6d1c225d0dc891744943c1544aa17836b3ecf900f041b1cca23c", - 'xlfn0g04.png': "bf3467f8aa9d35f7ae17cd59c3b2d5f6bf110b71afdb3a501ee88306647d669e8419e78b93b995651193a9ff99c849f82530a0bd410cec445feffe36c8df8dd1", - 'xs1n0g01.png': "d1bae1e471886f1661354f23b3564a34c9e1b076bd158ba129388aeb1f287d39ba647269b955bf3cc81f2b962ac6a3eb1a887a8c85243574e84778e48096cf88", - 'xs2n0g01.png': "abd509aa6253d8367980e4f6f4d96bb4b3732287601a7bd3dfb0fa4c70dc3908937c16e6459961421409c74f9952b4693ed1d352dc002bd120a57ba5407cac1f", - 'xs4n0g01.png': "015a1bdc1f878435c3de87feed442e467b3c96f3db3134d1e23653b6759a3a3d68f05325d15992ecce18ec5c00cab7e430c1965ccf36b434d8c9f9a4e8194bfe", - 'xs7n0g01.png': "03dab5037599a58f25dcbd1be556ff60dba08ed3e0e92e5791c53e98041b0ef174a9ebdf75fd997696521ca96a19ca1bb9a5eff929f1a7c0dc1a7d3598d07d04", - 'z00n2c08.png': "9a65f94ebb3614b65e093534a7763f55687144fc9a82e2680e7cad9863d72947a0de3dfe57468e11b578234b8460485e8ee895c681c391d140d84b15c7a40f41", - 'z03n2c08.png': "847fd249d190ccd8ec54afc910afaecf007db7ea5753c18eec8de654b159f4cdf99b70bdd55ec276ce5340fd2ede5290468fe4c6029b5e4c0825ca881a75bde3", - 'z06n2c08.png': "94268c1998de1f4304d24219e31175def7375cc26e2bbfc7d1ac20465a42fae49bcc8ff7626873138b537588e8bce21b6d5e1373efaade1f83cae455334074aa", - 'z09n2c08.png': "3cbb1bb58d78ecc9dd5568a8e9093ba020b63449ef3ab102f98fac4220fc9619feaa873336a25f3c1ad99cfb3e5d32bcfe52d966bc8640d1d5ba4e061741743e", + 'basi0g01.png': "eb26159a783a4dcf27878754e34db6960e992072fc565b12360c894746bc6369101df579e3b9a5c478167f0435e89efb2ab5484056f66c7104f07267f043c82d", + 'basi0g02.png': "f0f74d33ee4b3d3c9f1f4aacf8b0620a33cf1d5c6e9f409e11b4a6e95f2ab1c9159c1bd0bcf6f9553397bf670f4c92712b703d496665d4c6e88fdaf6a0c98620", + 'basi0g04.png': "7b81665f353ff6347304b761d26b4f1baa6118daefc4790f4b0e690150a4e6306514f2aef87e2c39e83e56a0b704df987b10a5366244da58697cda4d5d2745c1", + 'basi0g08.png': "6c809574674494d10eb04c58191c4e0b35813c45962ecafe36a9fe5ba44e5d74ba098e0a524a30c1508eb2dad601f04d5230dceb61a307ef1120f07a8bcbc92f", + 'basi0g16.png': "dd439069fb704b8deff3de822314c012e91a0bd84984d2e79888c6394b78557a0ae6197a7b0a4d64eb4e16fc758946c4f1f13d0d06e512ed9743c4a355b02488", + 'basi2c08.png': "e851fb030f88ead2541a01591882dde5fd9f5dea6bb2b11b374394ed86abc7289e72c4c90808b261aceac13111d3c05b39033168b42ffd1c7ea367314b3a8dc5", + 'basi2c16.png': "e0f81dd459860f7eaf04a2c54932547f41cdc9903a1295a26cc4a2087fd79c98a2e5d5e74f22345dba08b1eb12f3f53c9b904c88b756cbae0c19f9d680e2f1e8", + 'basi3p01.png': "aa21cbcd5d64e6e88056af907509f3b98b00d105198ea2a669fcb25b6966f06d5e4e3afc160b2382935e8ab8e7ccf61733424dfb39b9e864306b82f8355bbb58", + 'basi3p02.png': "d6182370236630d42fd75eed7dc54079ddb7fa9bd601eba22a8dc3331dce31b9a9465027145c29bd56cf778ab0ac029df6aa6481ef65c9464a1ce1d89423faa5", + 'basi3p04.png': "2b35fb98884da370f25833d25f0ab4b188cc26440321e95519131c675818c128b2029d38b3477ef94d88052ec6e9f8b1f7410c5576ce0b47b2fb7a5ba771ce48", + 'basi3p08.png': "7415890831958ca34c73de3e33a9c88980e788d10c983c3a00967886f05053d359499bf0bad386af8ee1bfdb73f666e1d541b0ab682c6092ebdbad3d93e145b1", + 'basi4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", + 'basi4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", + 'basi6a08.png': "aea929866edc5e607d7dc90fcd871f4b6d548abb379b9427fce75a773705e0d8c3ed03bb64e530482b72973eb09844638db5db93666ca1605ff6bbaf194f70e8", + 'basi6a16.png': "29b6ce7c2469e24587b87559f85551334c51bd9d7867f4066c0f7dcb01d710e11e87ee8654c91dc986454cd70f8bd6021e2086ea40e48a28d68a9bdf2283573f", + 'basn0g01.png': "52da610af6f97b03fd8e9f8e52276227f57a97e2bc7e47ae9484b2a37472330f8f5ecef2d6de7fde8f7eb8f144f233bdcf8a3d716c5d193e44d9590af2709cea", + 'basn0g02.png': "676c727faf143af658ed6c6333b15e50387c566c1846a4dda636ed4a2dbb1c0d6d32f0db635479f6851047a32c6d9c52898cfda004ea986853f3ee13750ed90a", + 'basn0g04.png': "123a6652b56f5b858373836509f6b7433221e6ff4eb9ce8a68d0d12bfb27cad0c1bb0cb159523ef1ae5997cb07f994bfbfeabcf0a813aa83495f8269a7a6c4e5", + 'basn0g08.png': "ad5ff30613a462a9b61242d42bb7c854b8247d80a1d03a3919dfdfe8a91c8a962ff51932b2411f714f1be7b803cbd4605c1d4441882cad7e8f44dd8d927198a4", + 'basn0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", + 'basn2c08.png': "fd92ba13d2038c632fd8bdd3e33971cc69f561bee1eb04ff7920625c6771e0cf7fdda29e48b8a6ca71702c0624ebbca232793f28bb2073b0247d30ce0c549ad5", + 'basn2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", + 'basn3p01.png': "d262c97549cd1d43e36f5990dac051ead80f1456693c8b1e19a8a48796195831a6ddd5c4a0ac44d22fee51ce4d9392c1c40a0be05571b1b2a961691636d69cd3", + 'basn3p02.png': "a00e375e1fbcc23de38b3b11a0fda4d0204f55473f74e37e0bb5c5f391b37c019293ccddbb99196b9457cd0b7fe5b9e34a55dc6b8167b6909b38813e37a95e46", + 'basn3p04.png': "1a6ab4c567e75b20ee6cdb400dd1f7764a05679c35010e6144fede5a55767dd1861df8e6240e1e59d4166e25d972ff05a41cdfd527818b6ec960a0f9d57d0939", + 'basn3p08.png': "b8f99f6410cc1ac0ceb366e93fc1008f45fb2499e39c489fafa143e8e881f334735e118eec93dde687bf4ea524b4548741c520d770ba6d7071e8fdce576644de", + 'basn4a08.png': "4b7758d4fce3bba95ef3d09cff0ab28c21b8bf568156730fd4e3bcea1c1c2d3ff77f53fe3551f617bd01c8c96e929eb20bf04f5c1a84f37c3cd6bacd4730e6eb", + 'basn4a16.png': "aa0c411f8bb15fc801b072f1048de2fd08761fe245ad267e8503eef8ffe1c39be845e99c04245771afe9b102328129f6375869a4e6cec60eeca641b3e5df3a8b", + 'basn6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", + 'basn6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", + 'bgai4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", + 'bgai4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", + 'bgan6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", + 'bgan6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", + 'bgbn4a08.png': "4fb9b1023c8c7accb93cf42bd345846c787735df01f7db0df4233737f144e2d5348afaededcdd8c2bcf2e53ce00e2ff095c91de14d7818b4b41c396ab85c9137", + 'bggn4a16.png': "302d7c02ddb0be62aeffeeda46957102c13a2701b841a757486cb3eec7b5456cfabc6ee1954f334ad525badc7c607621a72559b01ce338a0f39e2426d0a03fce", + 'bgwn6a08.png': "d380c477775d102288b43c387dbd7b931f85520f2f6151e3ccc5a25764169312d98fcebf69fb86d3d12520edc3de9bfced559ddf73366f0679e52defb9116424", + 'bgyn6a16.png': "b688d395552eb2a8506fa539ee9159b40a57d02c81860bcf76176213504eb10bdd89de7ce9da452e43f2a46c15290755cdc4816738620b27aed45b3ea7f7ee84", + 'ccwn2c08.png': "c4d58269ef360e42870cce5fb0b1134bfe5706f172c5ff916a338978798fc541a463ab4fdb7c91c424fa385f0ac5d6f576967f178b858d7503f609b2daeacb64", + 'ccwn3p08.png': "d89becf7d24dc57c931a8af1b9dc03ae10302785cc67028cec7255e1aa0ffb0d508d894023a98c10a24cf145aa60b93f977acb8231c8fee9d3f0934484757c30", + 'cdfn2c08.png': "a5faf9cfd284d3750ce2c2f8e15d0ff1bca09da4a9d46b8797c7a1a9f2ebe79d7a7a552bad3c3c049d6186460e81e1e7f9b94e7bb98a3c79d2516f6fb7ac6aa6", + 'cdhn2c08.png': "396eec14e76c00d22ee153171243ac531dcf7adad830948dfd5d6f0a84155734b90407e74f8c1ab8cfb0af5084c03f511530739751f8da070379c826545d0237", + 'cdsn2c08.png': "051b0defa4363ceb3fbc44f460f99a10cdd7c15797ea6d8aa62513b8b6fc5000fe542899db464db30eac56d0c9cd2a5d3778c6962f3aaa85a20881951a7f963a", + 'cdun2c08.png': "946074446fb99f0b790146df0f6e362c68e79b46ec7cbc4ce3d3dc9f75f66e58715caac4b3d7aa8fe8360c32abd2702e7228f9c03b4ba2a0d7f2f970a7ba8f32", + 'ch1n3p04.png': "6680e895195295989850129bcf9d0d0c47efca1c3bc363e4ea822c688707955cdcd07ae92e6e213ee388a62e14b51e036f9a9e075ad7b0f736b0cbc5cc4a108d", + 'ch2n3p08.png': "778ba389d9d0bcbe188e2501c7c1d047f1287179b3760b43da0053f0853e77a0575c7179a02f2442b83efa6cc0951b32d09bd7ea3b6848f261f10b8127e4b0e0", + 'cm0n0g04.png': "9e7e94d201a1222383294bd60e2627207b7b99c0bd80aecd677a1b7d8b372de4981b781fb794811d29a4b2c4db4f5a40c953039c31084f8f3de9aff13fbd1dc9", + 'cm7n0g04.png': "33bb0ffdfe54d655683e4e1bd6d963b9a35a6500129b5dd574245e78971de8d19f27b86a76d42056716b90c2bfc950241bfdc6c4b52ee0e125571de36ba61904", + 'cm9n0g04.png': "fd59386d15a1a324c5ff32f574484c1209afe4ad99f7dc12dce45b2a9bfefd33311ec93211fea3a8e61d1ad2f98220b0c15d151be304bdaa7f88126d54299f68", + 'cs3n2c16.png': "93ca3eeba9aef67de15f943fb2383d208ad1a68518ab78c9fa5ea306ad077b789e873f9e453f0354535167aa4e3d3fec715df05e827bf510948bf0e6fa0dacad", + 'cs3n3p08.png': "e8ddabbf0b17db03bcd7ff0c61d08cc971b3b88e3b3ecd2d4a296da8cf7d7708fa5b42ff3d5813d936ab7f5b4bafbf5842fa4c0fcf0cff15258548d2d26882f3", + 'cs5n2c08.png': "4e3eae53e8c27d4c58d8ad8cdff2c06b00a61d1528a41f5566694f10ef33c4a66f40d3d9fc247731c3ba6dfb734c9f2f90ef031c64486fbdf8a825e354fd67b9", + 'cs5n3p08.png': "31ee0f7f789c1203a9b0e81da34960a47017f3fce37bf2b711738ebd535bb3003ef60c2b0b1fca16587a59955c1ae24b9d186d7ead1d3ece6ada2bbfbc5aee85", + 'cs8n2c08.png': "11bbc80c3168f632deb4453f9199c7994255a0f4f2d7d2d2b06a00931fda4c56985b5a2ca8e969893ff2d65bf330c3d3148b80cbf72aacfe0054b612e6ae05e6", + 'cs8n3p08.png': "49ae3a9050487f6cae826407d421f32a8c67977dd057a6e36f1b2e1ec6abdf5cd46c8929ef4d7b565921ed6c9ae0dde89e243714fdf1510503c7d7b8af6d66e3", + 'ct0n0g04.png': "b6a66fda9ad82cb3287a1ef54702926204bbd4186969cdc2e0741a28dae1869ed76939199f44fd7dd78332753cb8b20a53c4bf740e353f2cc4247870cf576848", + 'ct1n0g04.png': "7cdbaebb6be5d9165972b5fa24f2b64ab437f5337f0548f3d212be8aa95e5dee6ff9abd76ec232faafedc4a41ab8825221b6ced2ecab81c1b3ab20042ceb81a3", + 'cten0g04.png': "648769788c3eb4acd06784dc428bab9e7868328aa3cfe3718ee6656e13e40c4502ca5ac1fe6d4baccb666d4a4f6b3a5d3c97d489f9919ae0d26c2dcdc62e526c", + 'ctfn0g04.png': "c40768807f13dee8dd80ab012bf82b7e8551cb20bde3c7b5c4c45ed19c764cb981945ef036292bd9a2838d34b1b52284295133fea326aea9fc391708bf1d1fbe", + 'ctgn0g04.png': "e0cb7a2d983f1c1c38054b02aabeec657e3f85dba3a52b4878798664c8c6db77cef84d01f042368de6e77cd07b7c2cc6e324aa70bd44c2c8a3642f0cc8fc6a65", + 'cthn0g04.png': "b8614c14bc8c32bb3b29d3b0ac9f3d04c0fcaa40818ab86866e2a8ba1e0c6a87a989f499f208a776d47bff8ab09bfa09352d52089b3cd5bf599faf27627a630b", + 'ctjn0g04.png': "02e2e0a5fa8054e7c7e1c583945da06fb31eff9a3fdd1a7c9f76ba3333f20ce60aec8fafe07f608e9d65a6543e97bab0ff8ae66f3995e8035c05a7c53168ca9a", + 'ctzn0g04.png': "ac35974bd1182e339327245ffa1c0afde634b3a67ee9d6e4e22deee983d6d31054e7843cf1720087b88f6510ed70276e9b0bf43deaf861bd16ceb166140352f9", + 'emblem-1024.png': "5b2e174847274069fc8f4e30c32870ddc7c0e3616a3f04fd41583543aa99ac6d9b7d5a63ed1da672c551b4d193568bb58ddac5e87a101b73367c7c3b01e36fa9", + 'exif2c08.png': "e81b85aa36c9aab55754dd8b73d42497c38eddf9ff3c2981529eb62993d8c0ab33d1b5146a350dd8a1c528d42a967733b2f86248ac615e0254fed53d66d0d895", + 'f00n0g08.png': "fa362f0262ce522297ce52bd7d18b1dc28a2eee3e099b4104c2fb6bdc3fbce0b70303e6df31b709b4033b41e8acec29c81d456c67cde741243c9a54f1ba17f17", + 'f00n2c08.png': "040e95e05152c4bb30608556c828f453c46253c7e0ab18984076cde29b5b6afea7b6658cb019a2723af02a5aabadb1af3b1190655256f3477cd54b9ebdd4df91", + 'f01n0g08.png': "5c60761dc803de1509ef33b4e0ee350d15488d73f4b4e2f93311beb19667626f42d91af39873cd078617c5a2e7c46cceb831d53299c3ff2e7486b43a02ce4967", + 'f01n2c08.png': "a2762a0c4905d05469178176966e86ed4f14c3fcf5c88336209cb923d76e73acc94c619947be87b9183afc20bcd002ab2cc84d81897ec8fc0a4bdeb02a2b7863", + 'f02n0g08.png': "adf640a6f60662ad1b47b5666d2ce86489c685284e50d47344af7cda37f4a42697b5e249f5140413bb3c3e563cca09b2693dcea8bd9ad9adad1adf654ce00bb1", + 'f02n2c08.png': "5f70f19d318ff1d9de4c2f728d83952b12b59bfebac213766ef835dd19f8214f56fa92318041eff25e720503542d067bc9fdf91d86016713c68eb1c52870bad4", + 'f03n0g08.png': "742efed3d25ada0449ed60e4fe1dc94abbe494870536946810cc0eef5c3bfbebefd9bb6d1a482cd5e2c2ee0f34a74b2ea796772254d05accb6739c1ab4d19cdd", + 'f03n2c08.png': "adfac7d6dcc7354467cb3f65742e30ecd44a09b5913ffb656664c9c4730e9cfab9c5e0df2ff8995d412b1ea9cd30ec061eead939546bf795e50a2d49cd10bf92", + 'f04n0g08.png': "9f229c609e87e6c3b83fa82f4f59d7b6494b70c7f85cc807b3611a12d5c59953f11c163228f2bb8b2e7ce77ad204e0da099ab06f8fc480d3ab0ca99fef83c23d", + 'f04n2c08.png': "2dd8b926d1f370b3d3ebaa982491fbe446f3c22b89e635c76eeab60c9ccd3ee7cf39773108d2cec647e480d40de88c4173369b4a12a3fccfba9e4040752cfb4b", + 'f99n0g04.png': "b41996ddf1b770d01900c309cfd2f96d6e60df8313cfda3585a731f32166aa447bcf66ef4af907d6417528024961408d06ca0894fbd6a63fd47ee5a9ed541b51", + 'g03n0g16.png': "02a49b9735063a4d1888b550ed961251b150794422b00ca3800ebba09cd55bdcba15cc8dfe0c41e5a99b2f4d3976b32b1cd08aba92f3dfc3960c71e28ec6cb51", + 'g03n2c08.png': "70b3d643218e033959c51279439d80982f338016b4355aff12be51e7bc59a79f5a5d519c0fa5f13db072cc667fb9635654766af2a11ea25c1b6673f554ceb1f4", + 'g03n3p04.png': "7bfab2aef6f2c04063c438a8f5cda38f3221892ec22a83ab3d3441a900b97c0a7184336ffc2e0c6748e4d931fc80855eed5d6b208ba6ac0709ef02bfbab3e8f2", + 'g04n0g16.png': "9a1d60c89bd63e1f2c81adf1ce7025b7f465e00f0c5142d8a67b5a92e2b042d41a352704969f237883e376bf50c911db196d46f8c28c30ef5763e1e717710c8a", + 'g04n2c08.png': "8e482c99cbc90e6e4aa678e5dbdc39f5b432d740ff260ab1ec04ffa199d97ed2e06491cf88eb0bbbda2f4133f174cf3741474305d9645e0268916aaaab43299d", + 'g04n3p04.png': "d95a52bdc83db74dd19aaa56b40bcbcea268492498c7b2348882a4a5ea70c2b258462c3d5cef85e5372188f21001f719afeb2fac635006486c8fc84b96cc4622", + 'g05n0g16.png': "75954c2e19aa2ba43f7011adecded403035ecb21595a5d116896d2bfc1b71eac42c9b6f008a748cd21b70004921832b3e0dafa1fc0fda4c51ad44cd2b4d782c9", + 'g05n2c08.png': "272baa8dc73cbd63f4fb9545288cfdfcee544e266c9074b73b401895188a123960a6000959f9c034f7b5abe2bfa5e6185253447bac82e9fbfa9634d7e9981d95", + 'g05n3p04.png': "81105d25df2bbbdce60e90cb9a7d0784326bc3c2857fdca4f1f3ef7ab301627685057b97b8d0c0c725d92bc0b48aa1b156dadf5e302ca35917f0b407689ba054", + 'g07n0g16.png': "cb6babe4e25f4cc7e0c3602d9f0e9e538f46a4c4e40420c29521799c528da31afd07b614ae64fbc0e9d0904c9f3e7395b31452abdc69c6a03bf1b5817035b669", + 'g07n2c08.png': "c61e8f936afda939d6497687597d3381485b7cc00716101fc4d6f3abf44df63659b762c77ee252a8735f8e0be0809961db17abbd42c5deab5bad10d0b6b28a55", + 'g07n3p04.png': "8151fa9e9ccd1991a05ea129a7363e23de80688c65d0554c7f3142ed7099d01d82d8ef122986693718f221202657ff965b1b6387a237b36ae741e3d4ea693280", + 'g10n0g16.png': "28ad93f3bebed928c3b0bb4beecaa1b1b55e480c7922d2a36c8f92fc0de012adab523c42f22871b82c6683a7ae74864ed1c35a76cfad92dc6692be0b78c22f50", + 'g10n2c08.png': "4b922386b48c0dd51aee3852da4e52c5c4f3eabe3fcb000e4cfdf0c0e8b27d6a6f77fed944932726fe884f468ac24d89c5c46d65db99be1ae797bc4bbee4cd01", + 'g10n3p04.png': "9b106a0db8ea7e4bc3876beed0f13d83b6f3d6d7d7211441379dd8d18db080f5dc81c6d15312cc3c8ae569b991852ad48f167229dec033f1a974d2a95c83cb3c", + 'g25n0g16.png': "0910ee601a4c4cb546c3bf2b5e8a799d199e34e1434c58c75ddad17f2b295920cf3dde9fe05eee19689705f76b11474b4edc73f4ff346b6ab2d02ec40a13d3cb", + 'g25n2c08.png': "080ed57fd4185c00c6c70e48c27612621393a6ef3987aefd1481611f74d0aebc58d1a90386e4e7bb0321eca961e97cd403a7e727f7324196c5a3cf0e07bffce3", + 'g25n3p04.png': "1deb4281d9792af858e715c39ef7e6756f3004845d87f52054efc9f02c679b2b1b6c2a548a5e6a3f31604b115469ba4bb81510470a47ff9a22b133427375a8db", + 'logo-slim.png': "0104624a95b1b8a97bb5013927cb8fbe330a8c9e7197814147702702cd1d44cdde956404786bb0e69927c6b03ed8031bab566599b1291b995ce747f7cb2135eb", + 'oi1n0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", + 'oi1n2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", + 'oi2n0g16.png': "aab1bbfc7b711ba66260985bd8bda6ffaa1e09a0a546b2fe8869b508d823a9e5a412ba6337355a81d87f010e9db8c95eee5f5084b21ddd5cca5d7db7725603b0", + 'oi2n2c16.png': "8d1dd257f3b1bf44ef0bf38338a1e3f2ff78670ac779959751a56231109ca1ed82414f50a221aa45333263073e1e1a950ac8df8e5318e2ed695422d49400c540", + 'oi4n0g16.png': "7675dfa4cff547c3029b21cc892b90a8647199dc9290add932535b04b4eaadaedbc338704f98a075f4690b87815eec8cc0f90a3dbaa2a7809aa03f238ebc5815", + 'oi4n2c16.png': "66313c9d4731e2a9fa006ee9e43c6ac4a3034ce2826c6213f67bfa349bb8bb3cfd8acd2c4553fd1fcd4b2f43993a54539ec8b7fb7f07b3a406adfe919f17b065", + 'oi9n0g16.png': "5615cd4c277be96b21031827d08c8fb2971fda090a0031fd34594f77f7cc558bc68917542597a32bc39c0cd29f7759f0f0429203aa285c163bba8c8f78894e72", + 'oi9n2c16.png': "e2184c00b952a3aa53078a5f995715fa683718a9cbe42705fae3a7c77b236ee6ad706f6dbf2c243aeea17e2c53e84724907724634545e065dd16ff400f5677ab", + 'PngSuite.png': "af1d473e986b3f5cb1006340f8f99156e980e2f8c9f804f0e27c57a51d0dec332a81d99c6e50162f63792d89da44857a6072f8431aa735f1e8f86c06520eff4e", + 'pp0n2c16.png': "82ee5674861b5f9bdab6cf41910d980fc33b5188e191b8892b051dc3b3bbceb4c6d421cbed7bc9b71a9a14db43991c0458ed2cbe5166939f1cbb1e20e445e8b1", + 'pp0n6a08.png': "71c0d4c87b6b2644a4529cd240c8d583c25d45e79fd8bb71ca850dada37e46571052b2da28b926a8194169b82da505c9a3e3a701816d91ac968ad6ff41132b70", + 'ps1n0g08.png': "b273e94c2f826640b10b27b50c605be06541b397ea1289be6f4ea821dff6c7b4b209ec8817a315db442de04c975b7cfecba07b51c6cec965ab9062c05ba04edd", + 'ps1n2c16.png': "833993b81801432eb3a9dbca81f4fdd8ab720c76f8d99a2d298fa1dc4ebd19759c158dd10a68f690f999ea643f62fb7e779e916df86aeb05c43bc4db62aa520b", + 'ps2n0g08.png': "4abea03946d751f03e1438e5987ae691607e528c577db52e893051b54a5d147969dd965e44aaf5540fea75baad873327d76aa71a07c81de31f04f3b781d01e3c", + 'ps2n2c16.png': "bfea51d7be49c04293de034c7649472d34becb663169608490916795fe988df7b812ff8950a3f8d896ee27756effcf9fb525d8d455226cf3965595ee85188581", + 's01i3p01.png': "18b405c902977d2553aab1738a3c00e602e40d11c121a7007c9b7b4cc499aba1fab12fc12aecbdbd5b5cd2638ec5ca5157b5d8fce5dad3cdc3bea02b0904c9cf", + 's01n3p01.png': "8e3e1c9754ebde8c687355b80eee4bf0e0ee8e37b39b784f1997cd2eb60ece7f077b40c8027b0d7f4b7e8f242c22173a244f4e599db33985187439bd918d4486", + 's02i3p01.png': "3e26a8cf35e3df1650adc1656f2d3e7c9b5e1c7932826cf792cbe2cc538c1283ff145f66e4682d459bb0b4f2a2f9ce7209f1997e336e06ca49a83f75270ccad1", + 's02n3p01.png': "d34685ade19ee550ba52e81657627832cb9ba3655f6fe336ebb5fdc4d35c380e819efc1556e1bd1ca2b4e456727dbc5312eb513e7254dfd057a25963e57f0ff4", + 's03i3p01.png': "818a2c91d6c0f96b13806d945d1fc1b4c64f17a9b6a2ede2658c84e20269cd80289312a163761165f0d99e1824f283844f1b4696af314c05714fd349acf7609e", + 's03n3p01.png': "fe847a62eb64bf9db4d9751600b19333f057b626f2f2eb80ee78a3374ae562944c2ebc9c2712f3bbf862798ef9205f38297cad44e8df5dcd96c158ca2e9d9233", + 's04i3p01.png': "1c63332a0d2f31b3a6457038ec2b8c5b4bd3192320fb1c44873947375dcaa028ea07151853e53c6f3fff6878cf90adedea35ae819e5a1b2dbf92399b29464d56", + 's04n3p01.png': "1312d9f3e5bb07b6cbf0c6798c3ae9b0a6cebae465ae6d4ba115ef585616b3b1f7723c6481fcfaa00626d6c62e4fbff7023faf1e92eedeb5354b9805542d43b6", + 's05i3p02.png': "13225a16a79579c4040cdc03f11c71d8589ab322a4f3926e32d9499fe4ca8503a43870e532b2da2597a6c3dd89c3904428cf89c25a8637d40bb3a353017cad5e", + 's05n3p02.png': "d07f2ef30c06a29b9c5c6a52ce1485a3bb9dacb5f119c2829c4cfd69c8fa272d6065eab21a5acd016bdb4f4c724214e8a737c2b76e0f0151e6afcbe5586a37ad", + 's06i3p02.png': "b386f0387e8496849b6d325e710440f7937a403b123886a52af8327e69e411fd632db19daaecfe2e712d49279630515d7217533112acde73cb429e2cfa465b63", + 's06n3p02.png': "df0968c77975f350a86fc09c047d9e3a0a2b71890a0ae67bdfedb23e7f0ce303ff883a463668e10df1dcf2e57cea8cf1fc7c836f5d13a73c1ecd8d66284fc0c5", + 's07i3p02.png': "0f67816f188ce11f15d0f345d2695f1920a322d84be3f332d542c5d20d10a9cef2cebf1e8ae778b25677beeda229c06221eb3450b851ea0e8cd102e5cad14e66", + 's07n3p02.png': "0af60c935e2da2a8a3173edf614085ad0df095c882a140437bdf93ecd5494cfeb5c068dc7ea4d49e181c67d26dd9cf8c969bb2d95f2fbce212ddf5817dd7f642", + 's08i3p02.png': "3204dd0879b6b1284f197a0437e674c4280adad180d4a1d37dff1555be1924d6234dad5d02266aa575d782c53fa52fd4580d452482ba939c732c09709075306f", + 's08n3p02.png': "135039621ce2079465ef49c1b7e5a5aeab299993d2bac864d822ff0669843df1e733a729ca5226ec05c94ddfebdcb2f4b78699fb3adb741db993d9757b4ca71c", + 's09i3p02.png': "dc4d8ed06a81fcd604f949f43e7d5f482c3ad9efd113d220b709de38ca0ca1a340f4cce7e929ca6323390b4ea7c4399cf2f1f2e34c1ef1b38c8296b51d7e8f4b", + 's09n3p02.png': "96b8204f7008899993d8d277ff42c8eb7c85e7cd522cae2e9cf28b8e10e3904c7ec2e3227372f397f6c5a381875dd747a42409471a29ad5049240417ec1441f3", + 's32i3p04.png': "a4de495c70f54eeccd115492a0dfe1cbbcf7f308343eacf6a57515d7a248b356a2639f5e88246d630c8713724cfd7ab1d5d388c677f026a1c5c9b4270a837c67", + 's32n3p04.png': "757009a2fdf19d1187d85930eeb4e75c6831387348fd8e618d1ef971c27d2682b2464b4160a743a6c6d712553fd7fe1f0e5d78226e348f270093495297ec83bf", + 's33i3p04.png': "19259eaf76a42fec949a21c4c55715247a027c2b59ba4bd0f45fdea1f3406cb475c33213b662fd64089b697a6cd25700364f76923dc2531fa0b39546242b3356", + 's33n3p04.png': "3f42b5f3896c1a47fe5dff9921d56234b4326dcffb70a7c6b1f0e7193a6f8f898438635f3b1cfef92c59d7ab827e2a3f40671d97c8547c8e7063a0076c97fba9", + 's34i3p04.png': "db0f7fe138fd732eae4a5c1b8d013167eb3be4afa86141b3e6ad096eabec67644e3108189311b3ce2c78f891d1ea7f5dfa1c30be59509edf123696064eecd00c", + 's34n3p04.png': "e35d9338637ae4c7a1c74a0e73a5c4ba405c2b0d36efd92512b7572d418c25e7d06361be2a8d16323c2708ff3921da24b76be5a41bd3cccf09c27ad472078261", + 's35i3p04.png': "9f0602e1160b81c2e88fc30daf295ff29c4f6faa5a3391c69d895621e7ab76e2071ced6f5a798e294f69621bb32272070ff4ceeeb1436b1cf03640417961a9d1", + 's35n3p04.png': "f12e6a7364073b7a010db0cf952989f5f5da20c592b0256efabb5e82e96d928dce7695c2a0af0749ddfa2739e3ca985463eb0f4a7fb6b8ab0638d65079fc6265", + 's36i3p04.png': "a2d0374bba6fb665deda98b1bd0ef767243b7a974b9f00c78d54bdbfed2c00decf6faef95816ef711efdc359247142be08ce2b86f7860b7384948ba394b4dd21", + 's36n3p04.png': "e200a6869dba1fc9e2eeeff6e686e02313c366a990bfb5582f66dba486251392a465db03806092543008e1130624f1d16cde61613d0ae2a9589941f69a1608db", + 's37i3p04.png': "555f1f7ec2d8ddb58ced7162a4dec315780be13b7cb9ed6d8978046c7fbcb91b4ecf6fcc5c99bd5b8b8d348e4cd202d882a31dec1ecd25156af8968c4a06fbff", + 's37n3p04.png': "d28b3f442b481214774d543924ab07b75fee5916262e6404992962184ea0059ca34fb32d14076642ecd83a3063966ea80676e3165759632782ffd844702cb74e", + 's38i3p04.png': "d4fe0179effbf28f7d28c0192de614512870367cec14ca04d86eb9fff9d6864b1074a68144023244e46cb69ad601e81632c36eb2ed307a32a3c37b7683f882d5", + 's38n3p04.png': "19d23ca8b9b44d26bc9173a69d1d8332e4e7b2ce6e6422195e71dfd0701158023253b130a831a035b2fce0a1556004e8de74e893caeea3d12410909e6e649831", + 's39i3p04.png': "f0c783232707d288b086398565918079e510677742bb5dab09b4520687a06809ae328d24508ebd8f5c26cf85105300ba98e55c29e3773579929839ed9ddbf7fa", + 's39n3p04.png': "39763c31a17edf2751442cf45ae3cc315623ed5b04141bbced2ee8d233485b2d1a2cc0678d60a1c84e3d89a7513634bfd9c82b58754cdfe95885f7a54ff18e2c", + 's40i3p04.png': "d33b29e6669accf1325e8212c555a6cb1d8413c445140aecb62eb6b40912743ef7c6298ad4bc2e232bc448ddaba37f79fa4d25e0cc8e3d53a5ebc93f8f984555", + 's40n3p04.png': "463eb60a2f0884fc368ea0650c5b7b6469c1429e5f006a6537e4aac721094bbd57baa6bcfe4025939089e27b344d7077ff09618e9ce3a5bd40ee3fe5a0e33ce0", + 'tbbn0g04.png': "24fb55d9fed351946869552edb15bf20a2e7a050094ca4b51ebd135958f8b77401e0e9b18618de0cbd18f835e16df24dc57ef094d3b456f0eb9f73c31748ce2a", + 'tbbn2c16.png': "ee98ae3a1cb4a851830ee3e8f4112d08bd74c2a05b778ce51102780ba9d7170c5200c9cc4e1a5c0833618ebe137595eb8fc0591b8798bb6e4e94c234f8cbba3b", + 'tbbn3p08.png': "ed325815b8525d3a5fa37c968b7c85946add7c08abd1c66d86e0264951cfa5a377078b910a78cc664ec2c43d352093c2609b8d01c9572f4ba922d98264e55c04", + 'tbgn2c16.png': "e6da4190d4cea04b0002d598d68c0536448899dd8fca4931b44bc8ea6d47e6946c55ebc5d2049936db2f7f52caef124648d25a360e838571f5f7cb2795eb3657", + 'tbgn3p08.png': "865358d285a8d8682a16b050d9c1b7492042e1a217b0b5753ad28ae1a698dd77150f8cd6510f345157e1efa1411b4e4d5938a81024c150c9d5e76e423105d9c8", + 'tbrn2c08.png': "cc3cd3b8b6cc9920914e0184bdedcf9e59975db3f99c39b93ea1202cf6e11689eb966fc40ae2caca8ef224a8aac03723142b58b701ca2a02fd73a62e379f7a6b", + 'tbwn0g16.png': "fa8359bf8cdac3ab9ac54cd4f1e96b1469ff3e3494102be179b5c7394a4e37953ef54f5e1ccffe771b4f028225ec164b410b0d08f82224ed93a654433feb14fe", + 'tbwn3p08.png': "a0e10707fe9df085596a724561ba6c80662f87095ba479b2345c985f4beb2933f7767fe3d07b30002591259dc14012f4b26fa9b503cc75fd644def7c27c9f2e6", + 'tbyn3p08.png': "9920b40b016c4a05a094c28a989d06e108e2ebd5d72c2a6ddca359b68ad95238b0b6dca0f60b78c56b551a2e44f924d5a443071bda6f6e31669b0a78c09b18af", + 'tm3n3p02.png': "e9910a8ccb78a10980c55c6ca7115757b48075e42c14a83aece92a7f85eee538d5e1d9301efc443a867628993ceff1c13aebcc574641ad85eec48ae05df9997c", + 'tp0n0g08.png': "57fbf8a07060565c23918420952d1feb506ce5b1bdb25f22d41ee1de4ce9655c6dde04b9643d2491b59efba229b7e0cacd6799010a89005802c28a300a4e578e", + 'tp0n2c08.png': "eed3f6c18bd81d96870a47c737574746293c71c517b6a5ba88afdad5ef89fa30d975717f8a8f84ec16cb98390353934cbdd6e4b099e86f0ca3fe8d50fa07bb11", + 'tp0n3p08.png': "9650347d0f4a1a6596828f48766949947148952c93c4899541324a48289ea558c5d7bd1a076ac0e32f71d197e478ffc418e424c52b3fcacd2f94eaae98a566c3", + 'tp1n3p08.png': "fbd0f987d98d96f85679ec237c05925032e8d7783551b3f3cffb1b7db6ebdb3afb61214460386b2a3a011826bbda8340757ba22727325eea9fe518c136969f24", + 'xc1n0g08.png': "6aa3e16f11e82378fa7d3767a785840960f2c152338374e3f64f94eb0799e1f29637a1a66435b6dcdbffb9208efbff65a70e17e80f1e05b3038a837dcf79312c", + 'xc9n2c08.png': "7e0d4285bc67345e092656f04b235b4fc273c7892e26dea339dc2bb8df6348d8477f7e6573fe4f40ede1c94b49a60d46ef47ff4f7327fb12cd6de3737e8b5e4c", + 'xcrn0g04.png': "f971b781eb229ada882bb333bbcce956740f9761581d68ba95b49d998b89499bdd4598c4155e72240d6a5b74c04d7081fe284f78fd3f85f2550a3d2171f6efbb", + 'xcsn0g01.png': "9e1d234c3775920546ab9f9eeabdb75457bd823d48ed677fdfe61a95c02c65730182ba7e84209bfbf59de5d1bea533ca57c90ff6a49ea6d5749636f949bdc16a", + 'xd0n2c08.png': "6458d4b8f10a01ff86207496fbf38b25c35857cc537e9e11085fd5fa7befe956e707e6c1c61bdd76a393a816fdc916e2003fcecf5b33dfeb53c4bb071110eaf0", + 'xd3n2c08.png': "fdf261941945d1231ff3b8e91db063ac5a52e8e56f1fc80c5c51149ed255a4eebb4351194d76ae156bdff1eaf5180184c2aa2dd27e4129498279360e00d7db4e", + 'xd9n2c08.png': "b7a3a47c0863bde4ae8aa5ef5fe5d43f8e29abb413dc002553b63d6a4c1fb79eaee66011f1f45887c218aef3fcd63fda847a1b1bc1975252c3b4fcad553c7b70", + 'xdtn0g01.png': "788ed6f9e7ed64e5f4dfa8b62dd88f6f37f7abd1c8e3abf4db2d1c46f0344e7ba638f6721e69ebffa19cf6536f7685f485e9eb548a3cae55131963da05950acd", + 'xhdn0g08.png': "1f06044e4607902e7bd8ba291bf2b9bbb855a881b4a7dde6a21e9f5f9b74f0f43f55a8aa31fa6d1c225d0dc891744943c1544aa17836b3ecf900f041b1cca23c", + 'xlfn0g04.png': "bf3467f8aa9d35f7ae17cd59c3b2d5f6bf110b71afdb3a501ee88306647d669e8419e78b93b995651193a9ff99c849f82530a0bd410cec445feffe36c8df8dd1", + 'xs1n0g01.png': "d1bae1e471886f1661354f23b3564a34c9e1b076bd158ba129388aeb1f287d39ba647269b955bf3cc81f2b962ac6a3eb1a887a8c85243574e84778e48096cf88", + 'xs2n0g01.png': "abd509aa6253d8367980e4f6f4d96bb4b3732287601a7bd3dfb0fa4c70dc3908937c16e6459961421409c74f9952b4693ed1d352dc002bd120a57ba5407cac1f", + 'xs4n0g01.png': "015a1bdc1f878435c3de87feed442e467b3c96f3db3134d1e23653b6759a3a3d68f05325d15992ecce18ec5c00cab7e430c1965ccf36b434d8c9f9a4e8194bfe", + 'xs7n0g01.png': "03dab5037599a58f25dcbd1be556ff60dba08ed3e0e92e5791c53e98041b0ef174a9ebdf75fd997696521ca96a19ca1bb9a5eff929f1a7c0dc1a7d3598d07d04", + 'z00n2c08.png': "9a65f94ebb3614b65e093534a7763f55687144fc9a82e2680e7cad9863d72947a0de3dfe57468e11b578234b8460485e8ee895c681c391d140d84b15c7a40f41", + 'z03n2c08.png': "847fd249d190ccd8ec54afc910afaecf007db7ea5753c18eec8de654b159f4cdf99b70bdd55ec276ce5340fd2ede5290468fe4c6029b5e4c0825ca881a75bde3", + 'z06n2c08.png': "94268c1998de1f4304d24219e31175def7375cc26e2bbfc7d1ac20465a42fae49bcc8ff7626873138b537588e8bce21b6d5e1373efaade1f83cae455334074aa", + 'z09n2c08.png': "3cbb1bb58d78ecc9dd5568a8e9093ba020b63449ef3ab102f98fac4220fc9619feaa873336a25f3c1ad99cfb3e5d32bcfe52d966bc8640d1d5ba4e061741743e", - 'ba-bm.bmp': "2f76d46b1b9bea62e08e7fc5306452a495616cb7af7a0cbb79237ed457b083418d5859c9e6cfd0d9fbf1fe24495319b6f206135f36f2bd19330de01a8eaf20c8", - 'badbitcount.bmp': "2d37e22aa2e659416c950815841e5a402f2e9c21eb677390fc026eefaeb5be64345a7ef0fac2965a2cae8abe78c1e12086a7d93d8e62cc8659b35168c82f6d5f", - 'badbitssize.bmp': "f59cc30827bcb56f7e946dcffcaab22a5e197f2e3884cf80a2e596f5653f5203b3927674d9d5190486239964e65228f4e3f359cdd2f7d061b09846f5f26bfaa9", - 'baddens1.bmp': "aa84bebc41b3d50329269da9ee61fd7e1518ffd0e8f733af6872323bc46ace6ed1c9931a65a367d97b8b2cb2aa772ccd94fd3def0a79fd1c0baf185d669c386f", - 'baddens2.bmp': "5c254a8cde716fae77ebf20294a404383fd6afc705d783c5418762e7c4138aa621625bc6d08a8946ee3f1e8c40c767681a39806735bb3b3026fee5eb91d8fadc", - 'badfilesize.bmp': "9019b6853a91f69bd246f9b28da47007aec871c0e46fea7cd6ab5c30460a6938a1b09da8fa7ba8895650e37ce14a79d4183e9f2401eb510f60455410e2266eb5", - 'badheadersize.bmp': "90412d7c3bff7336d5e0c7ae899d8a53b82235072034f00783fb2403479447cd2959644f7ec70ae0988f99cc49b63356c8710b808ddd2280e19dca484f34074e", - 'badpalettesize.bmp': "d914a89f7b78fcdd6ab4433c176355755687b65c3cfc23db57de9d04447c440fa31d993db184940c1dc09b37e8e044324d8237877d3d1b1ad5657c4929d8435a", - 'badplanes.bmp': "46f583d4a43ef0c9964765b9d8820369955f0568a4eae0bf215434f508e8e03457bd759b73c344c2f88de7f33fc5379517ce3cf5b2e5a16ebc20c05df73aa723", - 'badrle.bmp': "a64e1551fd60159ff469ce25e1f5b4575dc462684f4ff66c7ea69b2990c7c9d2547b72237020e2d001f69dfd31f1ac45e0a9630d0ddd11c77584881f3e25609e", - 'badrle4.bmp': "2bd22418010b1ac3eac50932ed06e578411ac2741bfa50a9edd1b360686efa28c74df8b14d92e05b711eeb88a5e826256c6a5cf5a0176a29369fb92b336efb93", - 'badrle4bis.bmp': "d7a24ab095e1ca5e888dd1bcb732b19bb1983f787c64c1eb5a273da0f58c4b8cd137197df9ac47572a74c3026aab5af1f08551a2121af37b8941cffa71df1951", - 'badrle4ter.bmp': "825cc5361378d44524205b117825f95228c4d093d39ac2fc2ab755be743df78784529f2019418deca31059f3e46889a66658e7424b4f896668ee4cfa281574bc", - 'badrlebis.bmp': "f41acfd4f989302bb5ec42a2e759a56f71a5ecac5a814842e32542742ca015464f8579ebeec0e7e9cea45e2aafe51456cfe18b48b509bc3704f992bcc9d321af", - 'badrleter.bmp': "a8f3e0b0668fc4f43353028d5fca87d6cac6ff0c917c4e7a61c624918360ff598ec9eaa32f5c6a070da9bf6e90c58426f5a901fdab9dfb0a4fdca0c72ba67de4", - 'badwidth.bmp': "68f192a55b8de66f8e13fe316647262a5e4641365eb77d4987c84ab1eae35b7cba20827277cd569583543819de70ec75f383367f72cd229e48743ad1e45bfa9e", - 'pal1.bmp': "0194c9b501ac7e043fab78746e6f142e0c880917d0fd6dbb7215765b8fc1ce4403ad85146c555665ba6e37d3b47edad5e687b9260e7a61a27d8a059bc81bb525", - 'pal1bg.bmp': "3aafc29122bd6e97d88d740be1f61cb9febe8373d19ae6d731f4af776c868dd489260287bf0cf1c960f9d9afcbc7448e83e45435d3e42e913823c0f5c2a80d9f", - 'pal1huffmsb.bmp': "4e122f602c3556f4f5ab45f9e13a617d8210d81f587d08cbd6c2110dc6231573aec92a6344aeb4734c00d3dcf380130f53a887002756811d8edd6bc5aabbafc0", - 'pal1p1.bmp': "33e2b2b1c1bed43ba64888d7739eb830c7789857352513de08b6e35718ac0e421afcdae0e7bab97c25d1ad972eb4f09e2c6556c416d4d7367c545330c4123df0", - 'pal1wb.bmp': "bc583ad4eaae40f5d2e3a6280aeb3c62ee11b2cf05ba7c8386f9578587e29b66819293992bdcd31c2750c21cd9bf97daa603ce1051fbfdd40fadbc1860156853", - 'pal2.bmp': "7b560ba972cf58ca1ed01910fa4f630ca74e657d46d134e2ac0df733eb5773d0a1788e745d5240efa18f182bd8dce22c7ac7cee6f99ddc946a27b65297762764", - 'pal2color.bmp': "b868a8aaa22fac3aa86bbd5270eb5ffee06959461be8177880829d838be0391d9617d11d73fab1643520a92364dc333c25c0510bb2628c8fb945719518d2675f", - 'pal4.bmp': "53a39fdb86630c828d9003a1e95dbd59c47524c4ec044d8ce72e1b643166b4c2b6ec06ab5191cb25d17be2fcb18bd7a9e0b7ec169722e6d89b725609a15b1df1", - 'pal4gs.bmp': "ab4c2078943afdf19bcc02b1ebbe5a69cfa93d1152f7882db6176c39b917191a2760fbb2127e5207b0bfb3dafd711593a6aed61d312807605913062aa1ce9c2f", - 'pal4rle.bmp': "c86c86280b75a252ccf484e4bba2df45d3747dc1e4879795e925613959a0c451e2fc4890532e8aef9911e38e45e7d6a8baf29d57e573d26c20923a5823700443", - 'pal4rlecut.bmp': "f38d485dbb8e67bdeaefba181f9a05556a986ed3f834edca723c088e813764bb2b42240d4fbb938a1775370b79b9ea2f14277ffe9c7247c1e0e77766fec27189", - 'pal4rletrns.bmp': "b81e7fed38854d201a3199ce50ca05e92ca287c860797142857ac20b4a2f28952b058e21687c0fae60712f5784cd2c950ce70148ba1316efe31d4f3fc4006817", - 'pal8-0.bmp': "f39a4f1827c52bb620d975f8c72f5e95f90ac6c65ae0a6776ff1ad95808c090de17cbd182188a85157396fd9649ea4b5d84bb7c9175ab49ce2845da214c16bff", - 'pal8.bmp': "be27e55a866cbb655fdd917435cd6a5b62c20ae0d6ef7c1533c5a01dd9a893f058cc4ba2d902ab9315380009808e06b7f180116c9b790587cf62aa770c7a4a07", - 'pal8badindex.bmp': "bd5fc036985ae705182915a560dee2e5dfb3bd8b50932337b9085e190259c66e6bae5fbc813a261d352a60dcb0755798bdc251d6c2a0b638a7e337ba58811811", - 'pal8gs.bmp': "228f944b3e45359f62a2839d4e7b94d7f3a1074ad9e25661fdb9e8fff4c15581c85a7bb0ac75c92b95c7537ececc9d80b835cfe55bc7560a513118224a9ed36f", - 'pal8nonsquare.bmp': "b8adc9b03880975b232849ea1e8f87705937929d743df3d35420902b32557065354ab71d0d8176646bf0ad72c583c884cfcd1511017260ffca8c41d5a358a3eb", - 'pal8offs.bmp': "c92f1e1835d753fd8484be5198b2b8a2660d5e54117f6c4fc6d2ebc8d1def72a8d09cd820b1b8dcee15740b47151d62b8b7aca0b843e696252e28226b51361cf", - 'pal8os2-hs.bmp': "477c04048787eb412f192e7fe47ae96f14d7995391e78b10cc4c365f8c762f60c54cad7ef9d1705a78bd490a578fb346ee0a383c3a3fdf790558a12589eb04eb", - 'pal8os2-sz.bmp': "fd0eeb733be9b39f492d0f67dd28fc67207149e41691c206d4de4c693b5dea9458b88699a781383e7050a3b343259659aae64fec0616c98f3f8555cbf5c9e46c", - 'pal8os2.bmp': "cdab3ed7bc9f38d89117332a21418b3c916a99a8d8fb6b7ce456d54288c96152af12c0380293b04e96594a7867b83be5c99913d224c9750c7d38295924e0735a", - 'pal8os2sp.bmp': "f6e595a6db992ab7d1f79442d31f39f648061e7de13e51b07933283df065ce405c0208e6101ac916e4eb0613e412116f008510021a2d17543aa7f0a32349c96f", - 'pal8os2v2-16.bmp': "f52877d434218aa6b772a7aa0aaba4c2ae6ce35ecfa6876943bb350fdf9554f1f763a8d5bb054362fb8f9848eb71ce14a371f4a76da4b9475cdcee4f286109a4", - 'pal8os2v2-40sz.bmp': "9481691ada527df1f529316d44b5857c6a840c5dafa7e9795c9cb92dac02c6cc35739d3f6ce33d4ab6ff6bcd6b949741e89dc8c42cf52ad4546ff58cd3b5b66a", - 'pal8os2v2-sz.bmp': "99cd2836f90591cd27b0c8696ecff1e7a1debcef284bbe5d21e68759270c1bfe1f32ee8f576c49f3e64d8f4e4d9096574f3c8c79bfdae0545689da18364de3e7", - 'pal8os2v2.bmp': "7859b265956c7d369db7a0a357ce09bcda74e98954de88f454cae5e7cb021222146687a7770ce0cc2c58f1439c7c21c45c0c27464944e73913e1c88afc836c8a", - 'pal8oversizepal.bmp': "e778864e0669a33fce27c0ccd5b6460b572a5db01975e8d56acec8a9447e1c58d6051ad3516cfa96a39f4eb7f2576154188ea62ec187bcf4ae323883499383c0", - 'pal8rle.bmp': "88942a1cd2e36d1e0f0e2748a888034057919c7ec0f8d9b2664deb1daf1a6e45ed3e722dff5d810f413d6fc182e700a16d6563dd25f67dc6d135d751cd736dea", - 'pal8rlecut.bmp': "cda9fa274cde590aeaca81516e0465684cfae84e934eb983301801e978e6e2e9c590d22af992d9912e51bb9c2761945276bdbe0b6c47f3a021514414e1f3f455", - 'pal8rletrns.bmp': "0b2d5618dc9c81caa72c070070a4245dd9cd3de5d344b76ce9c15d0eeb72e2675efc264201f8709dfcffd234df09e76d6f328f16f2ad873ba846f870cadfa486", - 'pal8topdown.bmp': "d470a2b7556fa88eac820427cb900f59a121732cdb4a7f3530ed457798139c946a884a34ab79d822feb84c2ca6f4d9a65f6e792994eafc3a189948b9e4543546", - 'pal8v4.bmp': "0382610e32c49d5091a096cb48a54ebbf44d9ba1def96e2f30826fd3ddf249f5aed70ca5b74c484b6cdc3924f4d4bfed2f5194ad0bcf1d99bfaa3a619e299d86", - 'pal8v5.bmp': "50fadaa93aac2a377b565c4dc852fd4602538863b913cb43155f5ad7cf79928127ca28b33e5a3b0230076ea4a6e339e3bf57f019333f42c4e9f003a8f2376325", - 'pal8w124.bmp': "e54a901b9badda655cad828d226b381831aea7e36aec8729147e9e95a9f2b21a9d74d93756e908e812902a01197f1379fe7e35498dbafed02e27c853a24097b7", - 'pal8w125.bmp': "d7a04d45ef5b3830da071ca598f1e2a413c46834968b2db7518985cf8d8c7380842145899e133e71355b6b7d040ee9e97adec1e928ce4739282e0533058467c0", - 'pal8w126.bmp': "4b93845a98797679423c669c541a248b4cdfee80736f01cec29d8b40584bf55a27835c80656a2bf5c7ad3ed211c1f7d3c7d5831a6726904b39f10043a76b658d", - 'reallybig.bmp': "babbf0335bac63fd2e95a89210c61ae6bbaaeeab5f07974034e76b4dc2a5c755f77501e3d056479357445aac442e2807d7170ec44067bab8fd35742f0e7b8440", - 'rgb16-231.bmp': "611a87cb5d29f16ef71971714a3b0e3863a6df51fff16ce4d4df8ee028442f9ce03669fb5d7a6a838a12a75d8a887b56b5a2e44a3ad62f4ef3fc2e238c33f6a1", - 'rgb16-3103.bmp': "7fdff66f4d94341da522b4e40586b3b8c327be9778e461bca1600e938bfbaa872b484192b35cd84d9430ca20aa922ec0301567a74fb777c808400819db90b09d", - 'rgb16-565.bmp': "777883f64b9ae80d77bf16c6d062082b7a4702f8260c183680afee6ec26e48681bcca75f0f81c470be1ac8fcb55620b3af5ce31d9e114b582dfd82300a3d6654", - 'rgb16-565pal.bmp': "57e9dcf159415b3574a1b343a484391b0859ab2f480e22157f2a84bc188fde141a48826f960c6f30b1d1f17ef6503ec3afc883a2f25ff09dd50c437244f9ae7f", - 'rgb16-880.bmp': "8d61183623002da4f7a0a66b42aa58a120e3a91578bb0c4a5e2c5ba7d08b875d43a22f2b5b3a449d3caf4cc303cb05111dd1d5169953f288493b7ea3c2423d24", - 'rgb16.bmp': "1c0fe56661d4998edd76efedda520a441171d42ae4dad95b350e3b61deda984c3a3255392481fe1903e5e751357da3f35164935e323377f015774280036ba39e", - 'rgb16bfdef.bmp': "ed55d086e27ba472076df418be0046b740944958afeb84d05aa2bbe578dec27ced122ffefb6d549e1d07e05eb608979b3ac9b1bd809f8237cf0984ffdaa24716", - 'rgb16faketrns.bmp': "9cd4a8e05fe125649e360715851ef912e78a56d30e0ea1b1cfb6eaafd386437d45de9c1e1a845dd8d63ff5a414832355b8ae0e2a96d72a42a7205e8a2742d37c", - 'rgb24.bmp': "4f0ce2978bbfea948798b2fdcc4bdbe8983a6c94d1b7326f39daa6059368e08ebf239260984b64eeb0948f7c8089a523e74b7fa6b0437f9205d8af8891340389", - 'rgb24largepal.bmp': "b377aee1594c5d9fc806a70bc62ee83cf8d1852b4a2b18fd3e9409a31aa3b5a4cf5e3b4af2cbdebcef2b5861b7985a248239684a72072437c50151adc524e9df", - 'rgb24pal.bmp': "f40bb6e01f6ecb3d55aa992bf1d1e2988ea5eb11e3e58a0c59a4fea2448de26f231f45e9f378b7ee1bdd529ec57a1de38ea536e397f5e1ac6998921e066ab427", - 'rgb24png.bmp': "c60890bbd79c12472205665959eb6e2dd2103671571f80117b9e963f897cffca103181374a4797f53c7768af01a705e830a0de4dd8fab7241d24c17bee4a4dbe", - 'rgb24rle24.bmp': "ea0ff3f512dd04176d14b43dfbee73ac7f1913aa1b77587e187e271781c7dacec880cec73850c4127ea9f8dd885f069e281f159bb5232e93cbb2d1ee9cb50438", - 'rgb32-111110.bmp': "732884e300d4edbcf31556a038947beefc0c5e749131a66d2d7aa1d4ec8c8eba07833133038a03bbe4c4fa61a805a5df1f797b5853339ee6a8140478f5f70a76", - 'rgb32-7187.bmp': "4c55aab2e4ecf63dc30b04e5685c5d9fba7354ca0e1327d7c4b15d6da10ac66ca1cea6f0303f9c5f046da3bcd2566275384e0e7bb14fcc5196ec39ca90fac194", - 'rgb32-xbgr.bmp': "1e9f240eaec6ac2833f8c719f1fb53cc7551809936620e871ccacfab26402e1afc6503b9f707e4ec25f15529e3ce6433c7f999d5714af31dfb856eb67e772f64", - 'rgb32.bmp': "32033dbf9462e5321b1182ba739624ed535aa4d33b775ffeeaf09d2d4cb663e4c3505e8c05489d940f754dde4b50a2e0b0688b21d06755e717e6e511b0947525", - 'rgb32bf.bmp': "7243c215827a9b4a1d7d52d67fb04ffb43b0b176518fbdab43d413e2a0c18883b106797f1acd85ba68d494ec939b0caab8789564670d058caf0e1175ce7983fb", - 'rgb32bfdef.bmp': "a81433babb67ce714285346a77bfccd19cf6203ac1d8245288855aff20cf38146a783f4a7eac221db63d1ee31345da1329e945b432f0e7bcf279ea88ff5bb302", - 'rgb32fakealpha.bmp': "abecaf1b5bfad322de7aec897efe7aa6525f2a77a0af86cc0a0a366ed1650da703cf4b7b117a7ba34f21d03a8a0045e5821248cdefa00b0c78e01d434b55e746", - 'rgb32h52.bmp': "707d734393c83384bc75720330075ec9ffefc69167343259ebf95f9393948364a40f33712619f962e7056483b73334584570962c16da212cd5291f764b3f2cd1", - 'rgba16-1924.bmp': "3e41a5d8d951bac580c780370ca21e0783de8154f4081106bc58d1185bb2815fc5b7f08f2a1c75cd205fc52c888e9d07c91856651603a2d756c9cfc392585598", - 'rgba16-4444.bmp': "a6662186b23bd434a7e019d2a71cd95f53a47b64a1afea4c27ae1120685d041a9ff98800a43a9d8f332682670585bdb2fa77ff77b6def65139fe725323f91561", - 'rgba16-5551.bmp': "a7d9f8ae7f8349cd6df651ab9d814411939fa2a235506ddfdd0df5a8f8abcf75552c32481ea035ff29e683bdcd34da68eb23730857e0716b79af51d69a60757b", - 'rgba32-1.bmp': "3958d18d2a7f32ada69cb11e0b4397821225a5c40acc7b6d36ff28ee4565e150cc508971278a2ddf8948aaff86f66ec6a0c24513db44962d81b79c4239b3e612", - 'rgba32-1010102.bmp': "59a28db5563caf954d31b20a1d1cc59366fcfd258b7ba2949f7281978460a3d94bedcc314c089243dd7463bb18d36a9473355158a7d903912cb25b98eab6b068", - 'rgba32-2.bmp': "9b7e5965ff9888f011540936ab6b3022edf9f6c5d7e541d6882cb81820cf1d68326d65695a6f0d01999ac10a496a504440906aa45e413da593405563c54c1a05", - 'rgba32-61754.bmp': "784ae0a32b19fa925e0c86dbff3bd38d80904d0fa7dc3b03e9d4f707d42b1604c1f54229e901ccc249cab8c2976d58b1e16980157d9bf3dbc4e035e2b2fd1779", - 'rgba32-81284.bmp': "fcfca645017c0d15d44b08598a90d238d063763fd06db665d9a8e36ef5099ce0bf4d440e615c6d6b1bf99f38230d4848318bfa1e6d9bfdd6dfd521cc633ba110", - 'rgba32abf.bmp': "2883d676966d298d235196f102e044e52ef18f3cb5bb0dd84738c679f0a1901181483ca2df1cccf6e4b3b4e98be39e81de69c9a58f0d70bc3ebb0fcea80daa0c", - 'rgba32h56.bmp': "507d0caf29ccb011c83c0c069c21105ea1d58e06b92204f9c612f26102123a7680eae53fef023c701952d903e11b61f8aa07618c381ea08f6808c523f5a84546", - 'rgba64.bmp': "d01f14f649c1c33e3809508cc6f089dd2ab0a538baf833a91042f2e54eca3f8e409908e15fa8763b059d7fa022cf5c074d9f5720eed5293a4c922e131c2eae68", - 'rletopdown.bmp': "37500893aad0b40656aa80fd5c7c5f9b35d033018b8070d8b1d7baeb34c90f90462288b13295204b90aa3e5c9be797d22a328e3714ab259334e879a09a3de175", - 'shortfile.bmp': "be3ffade7999304f00f9b7d152b5b27811ad1166d0fd43004392467a28f44b6a4ec02a23c0296bacd4f02f8041cd824b9ca6c9fc31fed27e36e572113bb47d73", + 'ba-bm.bmp': "2f76d46b1b9bea62e08e7fc5306452a495616cb7af7a0cbb79237ed457b083418d5859c9e6cfd0d9fbf1fe24495319b6f206135f36f2bd19330de01a8eaf20c8", + 'badbitcount.bmp': "2d37e22aa2e659416c950815841e5a402f2e9c21eb677390fc026eefaeb5be64345a7ef0fac2965a2cae8abe78c1e12086a7d93d8e62cc8659b35168c82f6d5f", + 'badbitssize.bmp': "f59cc30827bcb56f7e946dcffcaab22a5e197f2e3884cf80a2e596f5653f5203b3927674d9d5190486239964e65228f4e3f359cdd2f7d061b09846f5f26bfaa9", + 'baddens1.bmp': "aa84bebc41b3d50329269da9ee61fd7e1518ffd0e8f733af6872323bc46ace6ed1c9931a65a367d97b8b2cb2aa772ccd94fd3def0a79fd1c0baf185d669c386f", + 'baddens2.bmp': "5c254a8cde716fae77ebf20294a404383fd6afc705d783c5418762e7c4138aa621625bc6d08a8946ee3f1e8c40c767681a39806735bb3b3026fee5eb91d8fadc", + 'badfilesize.bmp': "9019b6853a91f69bd246f9b28da47007aec871c0e46fea7cd6ab5c30460a6938a1b09da8fa7ba8895650e37ce14a79d4183e9f2401eb510f60455410e2266eb5", + 'badheadersize.bmp': "90412d7c3bff7336d5e0c7ae899d8a53b82235072034f00783fb2403479447cd2959644f7ec70ae0988f99cc49b63356c8710b808ddd2280e19dca484f34074e", + 'badpalettesize.bmp': "d914a89f7b78fcdd6ab4433c176355755687b65c3cfc23db57de9d04447c440fa31d993db184940c1dc09b37e8e044324d8237877d3d1b1ad5657c4929d8435a", + 'badplanes.bmp': "46f583d4a43ef0c9964765b9d8820369955f0568a4eae0bf215434f508e8e03457bd759b73c344c2f88de7f33fc5379517ce3cf5b2e5a16ebc20c05df73aa723", + 'badrle.bmp': "a64e1551fd60159ff469ce25e1f5b4575dc462684f4ff66c7ea69b2990c7c9d2547b72237020e2d001f69dfd31f1ac45e0a9630d0ddd11c77584881f3e25609e", + 'badrle4.bmp': "2bd22418010b1ac3eac50932ed06e578411ac2741bfa50a9edd1b360686efa28c74df8b14d92e05b711eeb88a5e826256c6a5cf5a0176a29369fb92b336efb93", + 'badrle4bis.bmp': "d7a24ab095e1ca5e888dd1bcb732b19bb1983f787c64c1eb5a273da0f58c4b8cd137197df9ac47572a74c3026aab5af1f08551a2121af37b8941cffa71df1951", + 'badrle4ter.bmp': "825cc5361378d44524205b117825f95228c4d093d39ac2fc2ab755be743df78784529f2019418deca31059f3e46889a66658e7424b4f896668ee4cfa281574bc", + 'badrlebis.bmp': "f41acfd4f989302bb5ec42a2e759a56f71a5ecac5a814842e32542742ca015464f8579ebeec0e7e9cea45e2aafe51456cfe18b48b509bc3704f992bcc9d321af", + 'badrleter.bmp': "a8f3e0b0668fc4f43353028d5fca87d6cac6ff0c917c4e7a61c624918360ff598ec9eaa32f5c6a070da9bf6e90c58426f5a901fdab9dfb0a4fdca0c72ba67de4", + 'badwidth.bmp': "68f192a55b8de66f8e13fe316647262a5e4641365eb77d4987c84ab1eae35b7cba20827277cd569583543819de70ec75f383367f72cd229e48743ad1e45bfa9e", + 'pal1.bmp': "0194c9b501ac7e043fab78746e6f142e0c880917d0fd6dbb7215765b8fc1ce4403ad85146c555665ba6e37d3b47edad5e687b9260e7a61a27d8a059bc81bb525", + 'pal1bg.bmp': "3aafc29122bd6e97d88d740be1f61cb9febe8373d19ae6d731f4af776c868dd489260287bf0cf1c960f9d9afcbc7448e83e45435d3e42e913823c0f5c2a80d9f", + 'pal1huffmsb.bmp': "4e122f602c3556f4f5ab45f9e13a617d8210d81f587d08cbd6c2110dc6231573aec92a6344aeb4734c00d3dcf380130f53a887002756811d8edd6bc5aabbafc0", + 'pal1p1.bmp': "33e2b2b1c1bed43ba64888d7739eb830c7789857352513de08b6e35718ac0e421afcdae0e7bab97c25d1ad972eb4f09e2c6556c416d4d7367c545330c4123df0", + 'pal1wb.bmp': "bc583ad4eaae40f5d2e3a6280aeb3c62ee11b2cf05ba7c8386f9578587e29b66819293992bdcd31c2750c21cd9bf97daa603ce1051fbfdd40fadbc1860156853", + 'pal2.bmp': "7b560ba972cf58ca1ed01910fa4f630ca74e657d46d134e2ac0df733eb5773d0a1788e745d5240efa18f182bd8dce22c7ac7cee6f99ddc946a27b65297762764", + 'pal2color.bmp': "b868a8aaa22fac3aa86bbd5270eb5ffee06959461be8177880829d838be0391d9617d11d73fab1643520a92364dc333c25c0510bb2628c8fb945719518d2675f", + 'pal4.bmp': "53a39fdb86630c828d9003a1e95dbd59c47524c4ec044d8ce72e1b643166b4c2b6ec06ab5191cb25d17be2fcb18bd7a9e0b7ec169722e6d89b725609a15b1df1", + 'pal4gs.bmp': "ab4c2078943afdf19bcc02b1ebbe5a69cfa93d1152f7882db6176c39b917191a2760fbb2127e5207b0bfb3dafd711593a6aed61d312807605913062aa1ce9c2f", + 'pal4rle.bmp': "c86c86280b75a252ccf484e4bba2df45d3747dc1e4879795e925613959a0c451e2fc4890532e8aef9911e38e45e7d6a8baf29d57e573d26c20923a5823700443", + 'pal4rlecut.bmp': "f38d485dbb8e67bdeaefba181f9a05556a986ed3f834edca723c088e813764bb2b42240d4fbb938a1775370b79b9ea2f14277ffe9c7247c1e0e77766fec27189", + 'pal4rletrns.bmp': "b81e7fed38854d201a3199ce50ca05e92ca287c860797142857ac20b4a2f28952b058e21687c0fae60712f5784cd2c950ce70148ba1316efe31d4f3fc4006817", + 'pal8-0.bmp': "f39a4f1827c52bb620d975f8c72f5e95f90ac6c65ae0a6776ff1ad95808c090de17cbd182188a85157396fd9649ea4b5d84bb7c9175ab49ce2845da214c16bff", + 'pal8.bmp': "be27e55a866cbb655fdd917435cd6a5b62c20ae0d6ef7c1533c5a01dd9a893f058cc4ba2d902ab9315380009808e06b7f180116c9b790587cf62aa770c7a4a07", + 'pal8badindex.bmp': "bd5fc036985ae705182915a560dee2e5dfb3bd8b50932337b9085e190259c66e6bae5fbc813a261d352a60dcb0755798bdc251d6c2a0b638a7e337ba58811811", + 'pal8gs.bmp': "228f944b3e45359f62a2839d4e7b94d7f3a1074ad9e25661fdb9e8fff4c15581c85a7bb0ac75c92b95c7537ececc9d80b835cfe55bc7560a513118224a9ed36f", + 'pal8nonsquare.bmp': "b8adc9b03880975b232849ea1e8f87705937929d743df3d35420902b32557065354ab71d0d8176646bf0ad72c583c884cfcd1511017260ffca8c41d5a358a3eb", + 'pal8offs.bmp': "c92f1e1835d753fd8484be5198b2b8a2660d5e54117f6c4fc6d2ebc8d1def72a8d09cd820b1b8dcee15740b47151d62b8b7aca0b843e696252e28226b51361cf", + 'pal8os2-hs.bmp': "477c04048787eb412f192e7fe47ae96f14d7995391e78b10cc4c365f8c762f60c54cad7ef9d1705a78bd490a578fb346ee0a383c3a3fdf790558a12589eb04eb", + 'pal8os2-sz.bmp': "fd0eeb733be9b39f492d0f67dd28fc67207149e41691c206d4de4c693b5dea9458b88699a781383e7050a3b343259659aae64fec0616c98f3f8555cbf5c9e46c", + 'pal8os2.bmp': "cdab3ed7bc9f38d89117332a21418b3c916a99a8d8fb6b7ce456d54288c96152af12c0380293b04e96594a7867b83be5c99913d224c9750c7d38295924e0735a", + 'pal8os2sp.bmp': "f6e595a6db992ab7d1f79442d31f39f648061e7de13e51b07933283df065ce405c0208e6101ac916e4eb0613e412116f008510021a2d17543aa7f0a32349c96f", + 'pal8os2v2-16.bmp': "f52877d434218aa6b772a7aa0aaba4c2ae6ce35ecfa6876943bb350fdf9554f1f763a8d5bb054362fb8f9848eb71ce14a371f4a76da4b9475cdcee4f286109a4", + 'pal8os2v2-40sz.bmp': "9481691ada527df1f529316d44b5857c6a840c5dafa7e9795c9cb92dac02c6cc35739d3f6ce33d4ab6ff6bcd6b949741e89dc8c42cf52ad4546ff58cd3b5b66a", + 'pal8os2v2-sz.bmp': "99cd2836f90591cd27b0c8696ecff1e7a1debcef284bbe5d21e68759270c1bfe1f32ee8f576c49f3e64d8f4e4d9096574f3c8c79bfdae0545689da18364de3e7", + 'pal8os2v2.bmp': "7859b265956c7d369db7a0a357ce09bcda74e98954de88f454cae5e7cb021222146687a7770ce0cc2c58f1439c7c21c45c0c27464944e73913e1c88afc836c8a", + 'pal8oversizepal.bmp': "e778864e0669a33fce27c0ccd5b6460b572a5db01975e8d56acec8a9447e1c58d6051ad3516cfa96a39f4eb7f2576154188ea62ec187bcf4ae323883499383c0", + 'pal8rle.bmp': "88942a1cd2e36d1e0f0e2748a888034057919c7ec0f8d9b2664deb1daf1a6e45ed3e722dff5d810f413d6fc182e700a16d6563dd25f67dc6d135d751cd736dea", + 'pal8rlecut.bmp': "cda9fa274cde590aeaca81516e0465684cfae84e934eb983301801e978e6e2e9c590d22af992d9912e51bb9c2761945276bdbe0b6c47f3a021514414e1f3f455", + 'pal8rletrns.bmp': "0b2d5618dc9c81caa72c070070a4245dd9cd3de5d344b76ce9c15d0eeb72e2675efc264201f8709dfcffd234df09e76d6f328f16f2ad873ba846f870cadfa486", + 'pal8topdown.bmp': "d470a2b7556fa88eac820427cb900f59a121732cdb4a7f3530ed457798139c946a884a34ab79d822feb84c2ca6f4d9a65f6e792994eafc3a189948b9e4543546", + 'pal8v4.bmp': "0382610e32c49d5091a096cb48a54ebbf44d9ba1def96e2f30826fd3ddf249f5aed70ca5b74c484b6cdc3924f4d4bfed2f5194ad0bcf1d99bfaa3a619e299d86", + 'pal8v5.bmp': "50fadaa93aac2a377b565c4dc852fd4602538863b913cb43155f5ad7cf79928127ca28b33e5a3b0230076ea4a6e339e3bf57f019333f42c4e9f003a8f2376325", + 'pal8w124.bmp': "e54a901b9badda655cad828d226b381831aea7e36aec8729147e9e95a9f2b21a9d74d93756e908e812902a01197f1379fe7e35498dbafed02e27c853a24097b7", + 'pal8w125.bmp': "d7a04d45ef5b3830da071ca598f1e2a413c46834968b2db7518985cf8d8c7380842145899e133e71355b6b7d040ee9e97adec1e928ce4739282e0533058467c0", + 'pal8w126.bmp': "4b93845a98797679423c669c541a248b4cdfee80736f01cec29d8b40584bf55a27835c80656a2bf5c7ad3ed211c1f7d3c7d5831a6726904b39f10043a76b658d", + 'reallybig.bmp': "babbf0335bac63fd2e95a89210c61ae6bbaaeeab5f07974034e76b4dc2a5c755f77501e3d056479357445aac442e2807d7170ec44067bab8fd35742f0e7b8440", + 'rgb16-231.bmp': "611a87cb5d29f16ef71971714a3b0e3863a6df51fff16ce4d4df8ee028442f9ce03669fb5d7a6a838a12a75d8a887b56b5a2e44a3ad62f4ef3fc2e238c33f6a1", + 'rgb16-3103.bmp': "7fdff66f4d94341da522b4e40586b3b8c327be9778e461bca1600e938bfbaa872b484192b35cd84d9430ca20aa922ec0301567a74fb777c808400819db90b09d", + 'rgb16-565.bmp': "777883f64b9ae80d77bf16c6d062082b7a4702f8260c183680afee6ec26e48681bcca75f0f81c470be1ac8fcb55620b3af5ce31d9e114b582dfd82300a3d6654", + 'rgb16-565pal.bmp': "57e9dcf159415b3574a1b343a484391b0859ab2f480e22157f2a84bc188fde141a48826f960c6f30b1d1f17ef6503ec3afc883a2f25ff09dd50c437244f9ae7f", + 'rgb16-880.bmp': "8d61183623002da4f7a0a66b42aa58a120e3a91578bb0c4a5e2c5ba7d08b875d43a22f2b5b3a449d3caf4cc303cb05111dd1d5169953f288493b7ea3c2423d24", + 'rgb16.bmp': "1c0fe56661d4998edd76efedda520a441171d42ae4dad95b350e3b61deda984c3a3255392481fe1903e5e751357da3f35164935e323377f015774280036ba39e", + 'rgb16bfdef.bmp': "ed55d086e27ba472076df418be0046b740944958afeb84d05aa2bbe578dec27ced122ffefb6d549e1d07e05eb608979b3ac9b1bd809f8237cf0984ffdaa24716", + 'rgb16faketrns.bmp': "9cd4a8e05fe125649e360715851ef912e78a56d30e0ea1b1cfb6eaafd386437d45de9c1e1a845dd8d63ff5a414832355b8ae0e2a96d72a42a7205e8a2742d37c", + 'rgb24.bmp': "4f0ce2978bbfea948798b2fdcc4bdbe8983a6c94d1b7326f39daa6059368e08ebf239260984b64eeb0948f7c8089a523e74b7fa6b0437f9205d8af8891340389", + 'rgb24largepal.bmp': "b377aee1594c5d9fc806a70bc62ee83cf8d1852b4a2b18fd3e9409a31aa3b5a4cf5e3b4af2cbdebcef2b5861b7985a248239684a72072437c50151adc524e9df", + 'rgb24pal.bmp': "f40bb6e01f6ecb3d55aa992bf1d1e2988ea5eb11e3e58a0c59a4fea2448de26f231f45e9f378b7ee1bdd529ec57a1de38ea536e397f5e1ac6998921e066ab427", + 'rgb24png.bmp': "c60890bbd79c12472205665959eb6e2dd2103671571f80117b9e963f897cffca103181374a4797f53c7768af01a705e830a0de4dd8fab7241d24c17bee4a4dbe", + 'rgb24rle24.bmp': "ea0ff3f512dd04176d14b43dfbee73ac7f1913aa1b77587e187e271781c7dacec880cec73850c4127ea9f8dd885f069e281f159bb5232e93cbb2d1ee9cb50438", + 'rgb32-111110.bmp': "732884e300d4edbcf31556a038947beefc0c5e749131a66d2d7aa1d4ec8c8eba07833133038a03bbe4c4fa61a805a5df1f797b5853339ee6a8140478f5f70a76", + 'rgb32-7187.bmp': "4c55aab2e4ecf63dc30b04e5685c5d9fba7354ca0e1327d7c4b15d6da10ac66ca1cea6f0303f9c5f046da3bcd2566275384e0e7bb14fcc5196ec39ca90fac194", + 'rgb32-xbgr.bmp': "1e9f240eaec6ac2833f8c719f1fb53cc7551809936620e871ccacfab26402e1afc6503b9f707e4ec25f15529e3ce6433c7f999d5714af31dfb856eb67e772f64", + 'rgb32.bmp': "32033dbf9462e5321b1182ba739624ed535aa4d33b775ffeeaf09d2d4cb663e4c3505e8c05489d940f754dde4b50a2e0b0688b21d06755e717e6e511b0947525", + 'rgb32bf.bmp': "7243c215827a9b4a1d7d52d67fb04ffb43b0b176518fbdab43d413e2a0c18883b106797f1acd85ba68d494ec939b0caab8789564670d058caf0e1175ce7983fb", + 'rgb32bfdef.bmp': "a81433babb67ce714285346a77bfccd19cf6203ac1d8245288855aff20cf38146a783f4a7eac221db63d1ee31345da1329e945b432f0e7bcf279ea88ff5bb302", + 'rgb32fakealpha.bmp': "abecaf1b5bfad322de7aec897efe7aa6525f2a77a0af86cc0a0a366ed1650da703cf4b7b117a7ba34f21d03a8a0045e5821248cdefa00b0c78e01d434b55e746", + 'rgb32h52.bmp': "707d734393c83384bc75720330075ec9ffefc69167343259ebf95f9393948364a40f33712619f962e7056483b73334584570962c16da212cd5291f764b3f2cd1", + 'rgba16-1924.bmp': "3e41a5d8d951bac580c780370ca21e0783de8154f4081106bc58d1185bb2815fc5b7f08f2a1c75cd205fc52c888e9d07c91856651603a2d756c9cfc392585598", + 'rgba16-4444.bmp': "a6662186b23bd434a7e019d2a71cd95f53a47b64a1afea4c27ae1120685d041a9ff98800a43a9d8f332682670585bdb2fa77ff77b6def65139fe725323f91561", + 'rgba16-5551.bmp': "a7d9f8ae7f8349cd6df651ab9d814411939fa2a235506ddfdd0df5a8f8abcf75552c32481ea035ff29e683bdcd34da68eb23730857e0716b79af51d69a60757b", + 'rgba32-1.bmp': "3958d18d2a7f32ada69cb11e0b4397821225a5c40acc7b6d36ff28ee4565e150cc508971278a2ddf8948aaff86f66ec6a0c24513db44962d81b79c4239b3e612", + 'rgba32-1010102.bmp': "59a28db5563caf954d31b20a1d1cc59366fcfd258b7ba2949f7281978460a3d94bedcc314c089243dd7463bb18d36a9473355158a7d903912cb25b98eab6b068", + 'rgba32-2.bmp': "9b7e5965ff9888f011540936ab6b3022edf9f6c5d7e541d6882cb81820cf1d68326d65695a6f0d01999ac10a496a504440906aa45e413da593405563c54c1a05", + 'rgba32-61754.bmp': "784ae0a32b19fa925e0c86dbff3bd38d80904d0fa7dc3b03e9d4f707d42b1604c1f54229e901ccc249cab8c2976d58b1e16980157d9bf3dbc4e035e2b2fd1779", + 'rgba32-81284.bmp': "fcfca645017c0d15d44b08598a90d238d063763fd06db665d9a8e36ef5099ce0bf4d440e615c6d6b1bf99f38230d4848318bfa1e6d9bfdd6dfd521cc633ba110", + 'rgba32abf.bmp': "2883d676966d298d235196f102e044e52ef18f3cb5bb0dd84738c679f0a1901181483ca2df1cccf6e4b3b4e98be39e81de69c9a58f0d70bc3ebb0fcea80daa0c", + 'rgba32h56.bmp': "507d0caf29ccb011c83c0c069c21105ea1d58e06b92204f9c612f26102123a7680eae53fef023c701952d903e11b61f8aa07618c381ea08f6808c523f5a84546", + 'rgba64.bmp': "d01f14f649c1c33e3809508cc6f089dd2ab0a538baf833a91042f2e54eca3f8e409908e15fa8763b059d7fa022cf5c074d9f5720eed5293a4c922e131c2eae68", + 'rletopdown.bmp': "37500893aad0b40656aa80fd5c7c5f9b35d033018b8070d8b1d7baeb34c90f90462288b13295204b90aa3e5c9be797d22a328e3714ab259334e879a09a3de175", + 'shortfile.bmp': "be3ffade7999304f00f9b7d152b5b27811ad1166d0fd43004392467a28f44b6a4ec02a23c0296bacd4f02f8041cd824b9ca6c9fc31fed27e36e572113bb47d73", - 'unicode.xml': "e0cdc94f07fdbb15eea811ed2ae6dcf494a83d197dafe6580c740270feb0d8f5f7146d4a7d4c2d2ea25f8bd9678bc986123484b39399819a6b7262687959d1ae", + 'emblem-1024.jpg': "d7b7e3ffaa5cda04c667e3742752091d78e02aa2d3c7a63406af679ce810a0a86666b10fcab12cc7ead2fadf2f6c2e1237bc94f892a62a4c218e18a20f96dbe4", + 'emblem-1024-progressive.jpg': "7a6f4b112bd7189320c58dcddb9129968bcf268798c1e0c4f2243c10b3e3d9a6962c9f142d9fd65f8fb31e9a1e899008cae22b3ffde713250d315499b412e160", + 'emblem-1024-gray.jpg': "4c25aaab92451e0452cdb165833b2b5a51978c2571de9d053950944667847666ba198d3001291615acda098ebe45b7d2d53c210c492f077b04a6bfe386f8a5fd", + + 'unicode.xml': "ba3a0f730efd6cbb89a54dafddf8902ace1b4e22e96d5c8e47cfcd1b9b79705d1985ea4abd25c5ede1c47a5a7d9456b25b093c1ec9d7705f0c6bf52a515c9aa9", + + 'a128cbc_hs256_test.json': "4d2c8e5c9c669dba8f4ca88398efaa03003a1f0350a50df6ad94fbc5d93cb9b9ab6f96b727e1bf85298e98b5d5cf2538d38fab745ceca65cd35bf8dd7562ce87", + 'a192cbc_hs384_test.json': "3de5725108dc43dfe49571de089488de035631ff378c7708bd51fcdc854f306ca47cf731c65e45662759c8aed232f5111101d6c33836d9c2f8f700e775b8aa82", + 'a256cbc_hs512_test.json': "ea178a43c0bdf5ba8be435364424829e6d507bd90d5fd946b7c0f95190377f97de9b54c000049ca380d71d64b5e28e3d8977132143243e05559d878311c84c02", + 'aead_aes_siv_cmac_test.json': "b6de9c2559952f0eef286c1d28fd03c2cad4b73f006d3f74fc9f3de9a2c6d213c1851e126d29aa2d40ead31a01caaf301e00bacda7febbf303eabc76097396b4", + 'aegis128L_test.json': "be6f45c99c7814626c108f668aff5577196e8f9500074b3bef2541b16396c6444116108aecb61f0a1fa043a45e9216319fe4e82794eed93c95838e491b1d5571", + 'aegis128_test.json': "334996ec6b297bcb3410d13cfe10d63d884c8e90219a958d50b05adb0ff45acf80a215ca34de92756964f4cadf487734bd8443d67f668e292edd24228e55a8cc", + 'aegis256_test.json': "e134580630fa642024f7b8666f05d53b7e013c6f34614f9e5df1fa272348c8cf30e9ec34d1c7fffcb0c40f13e6a2ac1273e54670ecb6a6851e1ae59f0b6dc623", + 'aes_cbc_pkcs5_test.json': "42ad3d7ccc3409521db3b7d4bcc812b56d5656b0425f93a8d22ada118ee5a1b55c644b162d8074db36dd69b97dce27c8099b0571724eacf0b34bbbb59b4d9e79", + 'aes_ccm_test.json': "ad1585b5fe8a5ba90f5ae825f7c318da47d82ad63e98440ecb981ebad9746fdb2139e7801f6f714b3971e5f97a917714d857cda38e66d5b19eb718c404419c8c", + 'aes_cmac_test.json': "dfcf3e6effe5c7e2a44c4bd7c39fbff2b3537064f39e1407c28e47e5d4ee7fa29ef4225e44ed83b6b4ef24b87e4cecb84342528ff4d0ec28db529a8d3a1b47e4", + 'aes_eax_test.json': "b6ed02c28bd5945feef804ce9af8145f4313bbe6e5c0c4bd09e4138a1b618fe4a48f4fb80359f4dec41e26657840f3e8a9a333fd5edc8a0201924ee49a9b1d37", + 'aes_ff1_base10_test.json': "24c3d89a097b993902fe7913d92d1250f11a4371d2376c6715db1f7ca5e958a4bf52bff70b86c0cd6001acd7d12737d67e8ce78548a9c5b8e628bf7cff004a49", + 'aes_ff1_base16_test.json': "cd4eb61faee16b09f6f6fc99bfbe29439dec618a710b2a4de291ae44c1c8692f6084910abcc0e1445f022942c22b1078cc860b4696b2aab6e4379e8e63dc6188", + 'aes_ff1_base26_test.json': "6f3e6239ce0c0e5213d1c706082989a31519e9198d4f72f2cce8029e2b91aefd5bc522e2040fe807581bc026da659a7cd1c93095382441c3f40bbbeb4ada7f74", + 'aes_ff1_base32_test.json': "84b725e1b89ef9e6e28dd3915b5dd5a6d8858cb119cc5e5c91a94311ebe6c68b833005af227ef50987347a1b9f853ede7aa3b250ba9127ee74cbe0f1ee3d8c31", + 'aes_ff1_base36_test.json': "f1189ce66cfb610520eb0d9383d2dddf39a2ba04b82eae803c31b59cbddab42bd82f18a1aaacc8206f3ff7bb1dd9a75095534d6f3295baa3a9560f85f279dac2", + 'aes_ff1_base45_test.json': "bf370df32834cafe7e71e638d1c034f4540221f052d1a57d8e4ed7e0cbce0dc04d9752246909befcaef8bde6bd43c4336af9d36b2899bfb158becc60bd1b3e35", + 'aes_ff1_base62_test.json': "2f74c4f052e9eb70fbc52229a9e7d73313cf7ffa8ece832d4bbe6923a662e2efe549f1c6959440e2aef32cb682d44dbc3d25afe9f46cf60f3cb49494b94cecc9", + 'aes_ff1_base64_test.json': "284ce27d4903d94d6e5216290460388749e959f34ab7a4cc5080634f1067fe6c2fadcc9f65aa716793a21e3828b5fa364b5172428b48ae08a38b74c217a89053", + 'aes_ff1_base85_test.json': "81c67c4547a39b95db863fe6115d5258d59b345c29f9714f863666b578092a985a1c3af6e140b811c0a501fb70fb5ff23fb3688cd4f31bb47b471a8e4a46ca6e", + 'aes_ff1_radix10_test.json': "121ffd39b271aa4ba33d0cca7c8d53a5854825c6c03d91c115b8c0072f50219e60ccfc039297693b2f38cb0878a2198847f212d4f6401c56adc58c2b3b4693d3", + 'aes_ff1_radix16_test.json': "d77f9ca3f0e31192c932e8efe2995ce08ae29c214f811220ca817937643d44c71f66ee3775a7b28a5f6cfcff087d864e91077dcec1294c8e7e56a5913c824c67", + 'aes_ff1_radix255_test.json': "59201883feddf63968ba6cb685704345ef4a265451e617059df854089e299b6540e32f02171ed84a4d3321eb68da3730f3e2fc0c42d694dd3570f4e3c6ccdf9f", + 'aes_ff1_radix256_test.json': "d89f6b91c278af43634db849a981551aad2b8ec9012cb787cb37cf08a5c0e37569202220cbbc9f68857c01f2b307b3ec6a9c255bb5349dd733a5262d402601c5", + 'aes_ff1_radix26_test.json': "e21360f98d3bb6fb3e810a844a71e7870dc9892d14c9aa72e9e1c2158a7bae0f2458cc430aca4143f5fdd801a3d0ba256503a7e39a0aba9829e12a6fc4c6135a", + 'aes_ff1_radix32_test.json': "b5c74059593c85e902b76eca70bb43683503c7a510f964548830fefb07c71875a79ed0d8bc57df3ff19d3fc0aa6ca383d7a640419c00827bd9a3a44bbc38a541", + 'aes_ff1_radix36_test.json': "ca8e530579bcdbba9edad518bf9487bc8cecdbb0f41a523e292cbf1edbd4d48135b04cbc956b46bcdc2ce4749af3a1d223a69622cd1897ae28c03b4a42cf5f3b", + 'aes_ff1_radix45_test.json': "6711c5ec7e5bb9d855d12f8dc2b2f863b1d22de03322fda7878ad9350834985e134fda6157adbf87f3284111ff34bde9ca325e155e2f779ac5f32f0ec86d01d1", + 'aes_ff1_radix62_test.json': "ded71ce5521e8603b7cefeeadbf448dca6d80394bb73e037e31c7f2018b55c2d1fad727a0969d94d40a3ab3d4d080ce0617b28bc7f2acdfd239e0e281d6420a2", + 'aes_ff1_radix64_test.json': "8f663baf03b24e4d81441a5bee3421c268054c4ae175683698e7410a031275d42f25c13e0d0843c6da53e71abd201ce2e53ad4a928e82ff3eaffa2011ba967ef", + 'aes_ff1_radix65535_test.json': "9260f514add588a56391bd485b8ce97ebb0592e86bc09b050572368681be7f737f1aedd6ab4ad4bb72fb1a5c2168658243d12da0c167eb16c92e361301393721", + 'aes_ff1_radix65536_test.json': "2ffe5c12f6f55c363a3fc5d030d5c2eb7d8d71c14184f069bed0b3d349321831043eb23a35e5a9b79e3f04a8de196bd37438824534a1ba9afeb5ecf29aaa5869", + 'aes_ff1_radix85_test.json': "ba5be98fdf9154ac0d7c1369ea7bdd570c7959e45a1be960e6681974f52e4c77ad71eafe68a86c35974e5ec42accdafb35e638a522298fa4ed146f5c3b31cfbb", + 'aes_gcm_siv_test.json': "fbd2c29f40d396a247f1c5aa2e8823a6d00e1ceaa390bf0900fa99b793801fa2f3b44a8558d8b178a720fdd003a31ecab8598c7d4c709b783cf29d4a1f1c1fee", + 'aes_gcm_test.json': "5a41e50d865cf2e4a206bf96e05bb4f67d74ecd519480ca372d662c64d26dbc954f530c65fd477992de3600c978d3a6447b9e9dbf511a9b2c2ffdac28fbb1d95", + 'aes_gmac_test.json': "3226a4f531c8427a9604591e4486e4fb706ab0b57488ef53415303a503b5409c0f4852add453895434cc94771f59a87604dd15d47c861fd904d4bee0e0921b5c", + 'aes_kwp_test.json': "f9473060ba0e4e24c0b1938a38d1aed9333ae32109132c0c69701d9e706a8c21579444c046546e218d6982d3d90d5cafc2a99d31e3be432b13dda0b9f627a635", + 'aes_siv_cmac_test.json': "a5025be2398884ef5d6b2431db6bb90b9096dbde77f06c353b78d1b35e82f6d5a8e701a025685f95d8412998800293498643017ddc792cee3360c943bbe6590c", + 'aes_wrap_test.json': "b569c6aaac4e01df7e91f2ec942f4a32ea17ec789efe50ba640be5596519e1533dd15aba1dfd3aa2ff29077cfd800caf76adc15e1d8e5f31b10492a96a06175e", + 'aes_xts_test.json': "66ba73b3270436f8706f32e8d7fdb7e47f5638d10db83cf9311feecf70ac3ff1d66ff9aea528250b92e01177786f90fd06e8df72404de2e5c14ecf4aabc6e790", + 'aria_cbc_pkcs5_test.json': "9e8c33fc364d6fec2b541c542d6f822354c3deab61afc37b3c0881388e82e9b1e9c87f28fb6caa639edc765ba362fb98324a232c7f2f7492f6cc794bf57d66a0", + 'aria_ccm_test.json': "28bf6139961f41c8bfedf130cf327ac3012c1116f4dbf820416a912f4928ac8e1e4bf9aa0d7681f9ea43de264125fcd3fdb29d4f9ab9d27a0a72287a85d890bd", + 'aria_cmac_test.json': "1de6a919708adf65b96ade5dbb29a95e894e904f7f6f1a58cba08da927460982bae16ae8fa167f89a3a2889458b6adfba2a39e07990b0c589db06dbea26b6941", + 'aria_gcm_test.json': "663770e79111916abc82309245e64d90a2a75e409aefc17e6965cd183dc843fd810d61f49a3ae8ceaa216cfb9d44782130796f579c5eac75efbe43875678d891", + 'aria_kwp_test.json': "65db98e93fc0a7f4bedb3d8056c5bebf35de24e7bf7059299298e520791e232799e5b8dd733d928c349d6345f74b45c5c44f207a3cf1027d2c7c172ca8eeacb5", + 'aria_wrap_test.json': "4f1ad34ef5819383d5b999abf3fdaaf66c5801d851e83425162aa77d9873478fbab30be31a23955a1e279052e147ab6984de9c48f63d4d5c9732defb5f15e9a6", + 'ascon128a_test.json': "6ee774046ff065ad60c56bffe644ee97b6c617b62a8e291c476854895eb5c49e8c83bcf85fe86a0ad0656e0564bd90bf4ce812e0870c463c2fa50e6fe5672fec", + 'ascon128_test.json': "73d81b184dd53fee8f479d99478943349e5a2dbb997c4aa37482fa17d128e4f8664f8f06a0c2ac7f9668b0ab12b2d1378808c6d2b3b96f01225dc41a83366b0d", + 'ascon80pq_test.json': "dc2d8093cc93537e11d2672508035b4a366878a8b1e3b2d6bdd6bcd87915cff4835c704ced257e841dbc459e223ad8b5e3db21862626263fe9666e7bdfdc6841", + 'camellia_cbc_pkcs5_test.json': "01951132ec42955ce8eb74c1f431f7104212be90e345d16cc01a3cd4639e882f00947fa1009d8500d5b73a76b288cff2ebed7e176662cc862fbe8ddeb3a0fae8", + 'camellia_ccm_test.json': "1ac5a769ace83143ec341d4205e42c8dca037c6242af631c04f6590ecf6895420a14ed70910119bdbe1a9272fb703a7cf4df97943087b2db42775cc78fb189a5", + 'camellia_cmac_test.json': "ce8ca04c8b8316c56076ea913befa8d468d5a92266d3f381930b5fba4832d7be72046ce9c988ef8103ac0c350187ec8c146ef090a21540df6933dd1c31bab78a", + 'camellia_wrap_test.json': "6d261b753a88a10cb813ed9b4ebb25265306582f36998a6761dfa930293d4d3508df609b117aa0d278167fa9ab2e4327165adeff57835935964ecfec5c07307e", + 'chacha20_poly1305_test.json': "4edc434f10a9b026c98901aa7a48933e0de03d24f2445ecd9cb30c2e063390f97ff7e0b58b12135a231845e5771cc38c22b07ae814f85cee14f62d6a68ceeaac", + 'dsa_2048_224_sha224_p1363_test.json': "3de70432fb46585a0d980b124f33fb15ad5bb700d417ee2d051d00a1521507454ee9d1c41ccac04d79a3a76ae4442f4511cfbbfee66c092348d7c9762309d83c", + 'dsa_2048_224_sha224_test.json': "27149b08174f990da4152ff6efefe12c0008e8d24d3385c743d7d5bcaaa97b948da14703156c4142aacdfb324a276f87c1ccffd051fc6261ebc3deec4e9fa101", + 'dsa_2048_224_sha256_p1363_test.json': "7605f35381b9802104810b95e34835de72863ed4898cb56d004d55e7523fa5e12552460594ab0bd62c69ac8156113bffccb3118bfeb78f22566e3a210d96bf75", + 'dsa_2048_224_sha256_test.json': "c57b50d45969cfbe3ec80fb315179887e48e3b743e4d0c9c0384fb4a19220a7159c4033fc077d98266dde50424a0e186faec875408bfbe80d8c63b5bf00bfece", + 'dsa_2048_256_sha256_p1363_test.json': "4ca9c67c5bd4f220025d5725e06b63fb66f2b761f47fac94c84dfb97d433097c6138bd0868ccefa53f5da73d1020e1287dc7152143b125ca141ad27cb5b46c07", + 'dsa_2048_256_sha256_test.json': "67d1860659160aee1d13a2008f370db7afdea022278733b6c64e5204efe6aeefb175cb2e4b4f02fbcb845c010e1041757c37386016fc30143c9f13bc55ff8330", + 'dsa_3072_256_sha256_p1363_test.json': "806d22e4676f4890be78517f64279ba94b2a4d723985ec6002ed05deddda8610518588422a424410d32f3ed4c93b6ea7b0e8b2dfdc0eab8658b88e47041f9374", + 'dsa_3072_256_sha256_test.json': "2a24217dd91e159657c7ab24e26b6f9869a77208ef1c898433d9e10bbb5fd1f00b69e6a3b0ba4c336a8c02fa9208723b5ff782395baf1cd9d7556897cce93975", + 'ecdh_brainpoolP224r1_test.json': "0b654d630ad6bf1faf177631daea94b6d68a17fce1e5da0ab0e12702e206b7fc982aff4d331c6b0e55da536f2b648f06dfea0f10cec7b9d5c7845b1da0591732", + 'ecdh_brainpoolP256r1_test.json': "3df7d06433c5f85bcc834e598d63ba7ca611f859b1102bcdb0363421f0e8bb60154b13dd3639020504dc80ef44ec1aaa72529467ed503d646ec49b3d566b8b0d", + 'ecdh_brainpoolP320r1_test.json': "e3a8cc1e2e028d0cf5926dd507825c863c24ebcbfee685430d80277300bcaca3eb37a1a937b47007e4479bac69bdcd80e83cf3ab583566024b2c15add713311d", + 'ecdh_brainpoolP384r1_test.json': "8161986b7d3d061647a051b176306ca7f5f6a7ed55af77a676e3711b8ce9b4c036ddb65aac3a1789c5366fcb4b048946f4c8611fa0fc8af7deb37ec24ea97fa7", + 'ecdh_brainpoolP512r1_test.json': "0cec6745113ff9e5b79649470dbfaa95e059cf46cce4cc4ebf5f41ec93bd10974ca17e12aba54f75ea9691ccc50a1f8a031f7dc22cc03c17606e2a9258d8b3bc", + 'ecdh_secp224r1_ecpoint_test.json': "63ffedb647198fd97a2aa532175472442169d2c002aac88c8327625fcbe85631614431b5b24172a069311ebbe6ae0aff55f71ac601ec706066caf5268dcd639c", + 'ecdh_secp224r1_pem_test.json': "50e094fde7bb6077e7f378be72b03067ab9509aad6e4d473e982d5d3e710236889e81f10158240d9ea74a835b3f4c1cc6a17ef2deaa8715e1b23b77296f1567b", + 'ecdh_secp224r1_test.json': "ed1d7c38f5203df529252f01ad7a29c91beb1ea8724d46b7e5c819f9447f9dd28575b97802e17fb12ed9b65f72c10aacdb83e10c5b30c43486a4f37b6440a365", + 'ecdh_secp256k1_test.json': "efdde98724a6aa908fb588d79c0ad0dee83534105368b281964223c12e775f947adca5e910dfe457d3da84d8393549c0d753763f4a9461589b60d8adc1b88943", + 'ecdh_secp256k1_webcrypto_test.json': "d019b26616a43bbcb9ae42057b6526cdea94025572d141a0644d20547175b845326328dcfef320a9b66b6a6d18e644932336d958372a7be6cc6677c06a3393bd", + 'ecdh_secp256r1_ecpoint_test.json': "08a3a91f8269082f1557275e14ddd10270d03d04a2e394a1951c7364042f1ab66c7679df4e86869444fa7704d4f546d8ccae597992532539e53e405a080be7cc", + 'ecdh_secp256r1_pem_test.json': "adda0a1ba574fa2e27279d2ab796816dc57c2479ac389c83db2e9467ec3a727d10cb8f05e04741e7cbfcc4966c075ed56ee6f038d3afc09b6e5377b7b035a27d", + 'ecdh_secp256r1_test.json': "89eeee692fe4b898530e25c07d4417287cf326f1cafd0a4f1b3e3a206f4faba8a571a6805d31c7106424c597d8131b5201a5f4e0fd64dfa2cb73775f657066be", + 'ecdh_secp256r1_webcrypto_test.json': "ab289f42fa6a031ee8569f0a67bba6035f43616a369ae3ea88b5b43356a629b739e8fad3b01fe3055d0f8ba1322f25f94fbfbc8942eaa1a69e0766911dd77401", + 'ecdh_secp384r1_ecpoint_test.json': "fc8568f074fa963489d205db2ae25061b725128755b822821d52b2995750882ae1b9be9f5c5daf53b1ff6ae8de223d22d96a64ec5e336c4e671300ad6450cbc0", + 'ecdh_secp384r1_pem_test.json': "b9560104ddb35aa7d2454d140dbf71266af689b0298a77d86092766e950fc1a6c99adeaa875be8c5c27fc0ebaf9d4d97f2dc77c45032f7b1d4de030a8f552eb5", + 'ecdh_secp384r1_test.json': "60c50e940f92bad9b6ceb4e8cb98cba97774e6bbe62490b4fef53a81a8bf1eac0e8ff18b8250413e7b395dd607bf3946f296adc3e2274747c04481a0ace8158f", + 'ecdh_secp384r1_webcrypto_test.json': "db910d22b74b63b0a94f5ce4cf5231d80fde50410a7c118c2ca23f1ef41bf29bb43045d48890871df8ac6a90de0fd58133277acf63ab0524ffacc447e113616e", + 'ecdh_secp521r1_ecpoint_test.json': "54cfaa89c2c7716fdb89e38734ab1300496bb4b1794f789a837553f1c4112c65c2498572f101ce16d0000e4ee5e1f1d39a1e1135749101a7c165df8c502b1a2a", + 'ecdh_secp521r1_pem_test.json': "076b10984795e5e74da179f5d33807707ce305f877c27dbb67cc7009d09ab678ffa2eb730d445121a152566481a040e6a2f8c6b371262694e95ee632268eb8ca", + 'ecdh_secp521r1_test.json': "2c578c3588b0dded23bc1f6b2c3c5cd44824d1d955e92eab77c4d107bfa60965991cc74424a2270a182f92e1c0bd22dd30c1e9dede574eae78f7ee1c17d396d6", + 'ecdh_secp521r1_webcrypto_test.json': "3e9c1d6dcf3cfde667a6a0d4c389a7bcb8308095d0f062fb5a633c0a78695789d79f5f8e637dde866cbaa49a7038e690ae7516aa707fd65320feb2b959c32c80", + 'ecdh_sect283k1_test.json': "54607e398d77eccf7526d8aff7d5243b238dc00c06c072a1c30c9ad2226d8d6da659b83194a2e4dd0a62369f27f8f44c9a50bc716780bf26bb5869a529835df7", + 'ecdh_sect283r1_test.json': "295c73b9daba0acc13fca624d2210c5247b704396b2fe8004d8c62bc5e5434dbda478b547b8b9a7176132de88aba46e1917efb45291561bf8251e284bbf3f257", + 'ecdh_sect409k1_test.json': "161840a74cdb562acf49e3e389f743779aac773f2ea3a4e2920b427617211532514cc83788513533cae8487e486787c89e5fe50066e104b43af15aaf46dddc6a", + 'ecdh_sect409r1_test.json': "f43791e15318478221f6692558115c31590567a8b969d55e648711023e4164ce60b1998585fc89a1b07f8922722203cc36c48069565710f0d7897d5c8dcc7d0d", + 'ecdh_sect571k1_test.json': "b944b9de3b6d3954aeeea4b3ef6b9c7e12cbb25bff6acb385062ec8a35c4e7052384d4c14285f8feb870e9b1042237fbc2e7138db013b5b65edd78f795fb695e", + 'ecdh_sect571r1_test.json': "3baa06212ebaef756daee791abbec499ea145dcdbc54758519503550efa2836ea89717b740e59cfc044a61e88ddc2e3892a168f27c27679a1f89701a66999283", + 'ecdsa_brainpoolP224r1_sha224_p1363_test.json': "b5f9fec57916ab49d1373cbf55ef441edc481825993fae3b07c42a38c3646e90d28075b8b1cc35157928be74b875fdc990bfda582f83ac8a68009bb9804890f6", + 'ecdsa_brainpoolP224r1_sha224_test.json': "f352487bb90f666b6adca5e9c41d48f09c28c69404a884fbff3c6780ded73681e31fdaaf0da1d53a9d8fe964ab4678170ab4f5085e5f551f5e56adab2c9a8e2e", + 'ecdsa_brainpoolP224r1_sha3_224_test.json': "ca83567e3e2d62417974066b5cad977b12627418baccdf4dfe9c9a1972af83de6d3869e25a66a986a062862e5cbdfcef2642b72bcc5deb9b78cbbfa3e8d5cef9", + 'ecdsa_brainpoolP256r1_sha256_p1363_test.json': "9a41d67ee9f2353bf9d54928564db3f0804c4704838bc67af33eb70a1dbce4af70e449fcc74f98192bca9ab2eb0879604bac34bb87e832a7984fcb12c6d4cdfd", + 'ecdsa_brainpoolP256r1_sha256_test.json': "94a6da4a541efc83e29758a2f321d4acc937dff585a9f33ce170f66c0f46c8459db12643e56b41bdbe388d0ea0ad3f6b9a7d3d0cbd58aadc81e66eca4ca68210", + 'ecdsa_brainpoolP256r1_sha3_256_test.json': "efca09da2c39791e634fa5910d9ed4fedf9ec22f6858bc65976e4bdfdcf9eb4af2efe793cc39273d2001ed1f5b394826df91a4ee30d37e4f50aec3451b167aff", + 'ecdsa_brainpoolP320r1_sha384_p1363_test.json': "a3483693f6dbaf99e0c7669602b64a5f19a14e3451b84558f8aff6a73988b48b46c02c9b95cd17263dad25e32721f602898eb2369c607dd6debf64eb294dfa36", + 'ecdsa_brainpoolP320r1_sha384_test.json': "bd2b3290124ca707ac214d0ab0b2f7df44cbe33910f5c690485814333c0fb9df95de39eee99ae392e89dfd151aa1389c89248c5e89e5c9fb9002d159159068e7", + 'ecdsa_brainpoolP320r1_sha3_384_test.json': "02ecf9b37ed128edc759b5ee0530960d719bd724fe7ea7f02fd70486e5cb01d9a51e50f9a7cce9e33ac6c053d7b3b6949011863dad17442e5d642825a2004f71", + 'ecdsa_brainpoolP384r1_sha384_p1363_test.json': "05b23eb103e9d9ad92e015db8871edc6f0ae88ac02a2f7e9a582328a75779ee09dbc5e30aadf3f0bc8f6ae28ddbda90d4bd2502fd33e4bc60cf6ce99b5e76c97", + 'ecdsa_brainpoolP384r1_sha384_test.json': "62c3d506c42a25915cfa8ccc3a7a4d17efe4c725ec95caa94973b30257b08009622035d751d676f857f2e8a2923360db1cfc63c5fcc00963ba877d077d39b2fb", + 'ecdsa_brainpoolP384r1_sha3_384_test.json': "91bdc6d6b1374d688ab0da4be495a8b3ffa5e7834422ce9f27a7256dd9ec1b76488c9a1b3949713784a531a06bd49692b721ecd36f88431b90ea03313f07682a", + 'ecdsa_brainpoolP512r1_sha3_512_test.json': "5ddb3f9b65409291a26567ebf28953f788d6dd5f70b0af39153cb7f20e8cd80a23db9c11362bc86a92697f0d9a77903ad528b16fe23b8cfcf310730d71ba24b2", + 'ecdsa_brainpoolP512r1_sha512_p1363_test.json': "e5383f4df48561e5ff91fe87c67a0a002b14c4d0fd70f345933acd6bed23f9dce35ec92c4cfc5c7d4be5bab2b64780e2de3c8147e00b8ce9140e4c2b39e587c6", + 'ecdsa_brainpoolP512r1_sha512_test.json': "bdacf47247e475e0a259c87b96a77032be653c2fc9489534197a80fc736f16ef0f48f4736c45eafbb875f266a4ef0cfd08f0566d6382ba1abb16ffb4ac741dfc", + 'ecdsa_secp160k1_sha256_p1363_test.json': "56b607a6e9faf19e14c27f4f70d64f9786e3c0de50924ad6715bef65bfd5156b1cd401695ca1c3486227a4d3b9de49d81d70900e07169ad36170c38d2e8a53f1", + 'ecdsa_secp160k1_sha256_test.json': "e48c03f62d45e39d2572097282574421447953bed47168928b930b32680bd68be5aaf7ef0ac6c7632c7ef3887985f0bc1788167299c42e5cbabe5925fb5eeaa5", + 'ecdsa_secp160r1_sha256_p1363_test.json': "0ba341b6a70732017971c0ab38c48b264808bb5aab563bb3c66ef31e685f2491abebe3a3f114d541ac3bcc503b59e7f02e8f35536b9ce781b8f6b9c57c72a731", + 'ecdsa_secp160r1_sha256_test.json': "70b593c449b671b3da62d1224a1c7fc372cc34d5a067fb87f70a65d14a236a47121bef499b072acc9ab2c4c70d3a4305c90b89059719ad41dd2473d5fcb7a14b", + 'ecdsa_secp160r2_sha256_p1363_test.json': "277067478dd5b6f3d81da3bdd706a68429d7d8b0ad85d3c0843ab7bf022a0857df05ca628c61e92358162e75c4a505fedf7c0c643382279bf6ac47e7cf2864c0", + 'ecdsa_secp160r2_sha256_test.json': "2f1b0d917d703e0acdfe863078d46f5dd0a51d9e2fa07b2fa34180aa6ca4b175e6a14f6972b9a2eab3523b5c1d11adacec8c92c969671b379f30ef0b9185ba67", + 'ecdsa_secp192k1_sha256_p1363_test.json': "dc703ac1ee295c20df496009c8beaf6b1f1ebf00654c76f335dcd983ce0a19d3e8c2136be3f78ef2294a58b4f953dba53c8da97786064d66ea8e7d85ec77ff0b", + 'ecdsa_secp192k1_sha256_test.json': "132c2a1656a03397d1334048be3bf3d4825c6e08096196b8d5d1c11843b4e543f0a8c898bb7812355ea8774a979f749c8b8f9e5062e1d91c22d7220c678f8846", + 'ecdsa_secp192r1_sha256_p1363_test.json': "4669db3e1921dacab450e901612cc219ea681941f2b18a0f8c874a018dbccb30edfd421ff167b685180cd6e9ba87c684cb6f0a18d6da467b5f2167fcffc94b5a", + 'ecdsa_secp192r1_sha256_test.json': "9d03dc6a28e9e131ec37a2dbcc66b0d7beabd8b8e43af314b2a1bd5b8e731fb4d0706233d17a4a9b5260e638c1c4b5b7e5cd69357eadd1f02ac19f47b82f7cbf", + 'ecdsa_secp224k1_sha224_p1363_test.json': "28417835fc6237dea10e8f747b2a12d3276409a1746994771562d66d80374c571408eb27dcf907adde920748dded41b00482a26ba1b1a00b07efa4b6939467e9", + 'ecdsa_secp224k1_sha224_test.json': "693254ce147e24c082e913862231c2dec907ef280c95543de17cd22893bb5ba47f5fa0b83854848e583941e60e93bf24d925af26f020e743a6ab6a63e73076b6", + 'ecdsa_secp224k1_sha256_p1363_test.json': "971a6632780defc1022a4138b3df8a8335e2b92e91ecf8971404dc4e71a35ac136b2eb1f4d54fa8474bbaff7a67d918a52fb34ab6101cf7d775766d024f06221", + 'ecdsa_secp224k1_sha256_test.json': "79b739ae824a532c5eedd62de60ce14e11a7b7f5ad0550bc7f97bea21e2db9492c0b0538edfa170e40493ae6dca0fa9b0f9f7e182c5bb503405b246de3d06c2a", + 'ecdsa_secp224r1_sha224_p1363_test.json': "5014189fd6535307640f56df4bb4b11ecc040c95cfde90e8d0da92a55fbd6861257566849b899874106171ed40579981a98f1dfa482b72d021c9dbb409bef254", + 'ecdsa_secp224r1_sha224_test.json': "d81458ba50f06d0157e42abb441f12b0be4c409b1430bdee9d6cf8aba2985d596534b606ec17caa3f176d4c2c9a95fea3aa52a3b3dfa136f287c30348f429c5b", + 'ecdsa_secp224r1_sha256_p1363_test.json': "7b8e4264ce143ada9ab97576c63000629701e602a94ca47045b750f55876a68b9502ee6d4adcb03533c58bf9cb78b3ef4ae8c91361543dc02d29acc210c3804e", + 'ecdsa_secp224r1_sha256_test.json': "6e6aca400c5b5c49a9412aec7263fa75b76577abe19a9decdbe350e580211b9ad08b8a757c74b5674f4d3427f95e452fdac1e8551056c8cc37fc0622be3375ba", + 'ecdsa_secp224r1_sha3_224_test.json': "0468c5c71ff3a7a1e8942e570552f718077a54d83e698cffe7635342fe121935358ad70c7c6f8b69bdfc8454204cc3d772367fdb42302262418d867d8683dee8", + 'ecdsa_secp224r1_sha3_256_test.json': "e423747bd477797d04b3196b4d1690751e045e737b4030010a3662a584eef0ce213562e8c204883a5b8901a970d2d6a736a740161793f6ca73bb5d8469f95381", + 'ecdsa_secp224r1_sha3_512_test.json': "094d0d96b38b87f7060cc28cae6158a0a14092648eab4c85b9e701f5c08e0c9a312a500c452cc0cffdfe46482e5c65ee9973643f3a144902557adca00962d5b4", + 'ecdsa_secp224r1_sha512_p1363_test.json': "02c1d323331ad22eb82ddb44d3f29b48285b3cfcfca43d28a2694f912762188f5dbecd968c0bd3ce7a552641e49502db679eba8044c1a0c5fa9c054273384f5c", + 'ecdsa_secp224r1_sha512_test.json': "9bd69463d1e24c9a086cddba4323a1eed6fe34ebc6d0b087c5e40d067260bda62c07250bf4ab8069b95eff2826fdf4abadc01f5f34d9c37a218bb0f77625d151", + 'ecdsa_secp224r1_shake128_p1363_test.json': "4d675b55466f79ae3308a082b07c3631296ffb947c2cbe8033cb52a3ac3f8a83db484f2f22b4c70d5aa345e1140fcab48ab1067d75e3feb2de260a3bc4ef2baa", + 'ecdsa_secp224r1_shake128_test.json': "4b9ea752fce41061c8de045b33127f665d7a53f627c687c82462775f7b2d9e1fc5e531fb3bdf735218a309afa40d4894ac092c2c8620e3ca1c50f300eb26f6d4", + 'ecdsa_secp256k1_sha256_bitcoin_test.json': "88f6be4d25f879097e12cfdad377c2d77a20189e4b5effd8ea866092e2477e8b48e51e4ba8ce55332ca223edecb30fea69b3a3d8748976d28aed98869e80cf21", + 'ecdsa_secp256k1_sha256_p1363_test.json': "38adcb33ea8cd18ceec78a1c0a7c36d3d8ef47303906751fedea0207f4c3cb1fc57fefc109612c30b61c75b3f9eb91cfb56713a745175d0834841cd660cae327", + 'ecdsa_secp256k1_sha256_test.json': "86a211d21b7bd9d6db3e8aa81ad769373f6e18c3fd05c519af217a5a4304c02abc36b70dd306094c7fddfa6489a9c9b5a3e9cedcea28c4081441db1800ff6aec", + 'ecdsa_secp256k1_sha3_256_test.json': "7d649655e9a1aa67b6c275e2547a7dbee605ec487ab292f2f1c67fa8881cdeca841a82a8093217c521ec2bba36cc9c6e05c0cdc4ce64679fa6654a68c76c3782", + 'ecdsa_secp256k1_sha3_512_test.json': "38e1a39e8aa538f33d4facbef07b9fd9793a95c9c5270c2c41dd9a0da9d2b32cd84dd525fd379de94348794cbd82c8feae1a925b0ff323d260cb01f58eb16f3f", + 'ecdsa_secp256k1_sha512_p1363_test.json': "7bfa57b2accc0071db8c849685769eaa0e20c0a35f18469a284d0e27e340a3f7f1198898d5268500b053b60a0e019308a3b9c536a27c95dde581490a5215c438", + 'ecdsa_secp256k1_sha512_test.json': "1c1b635cbd9a56e910959f3a4551247d1c8a42930a418cf0fa8a686d6370c8730a274ff56cfa4b3e338c9321fb94ee5adaf76dd30ac312db0c7ce74c0457c55a", + 'ecdsa_secp256k1_shake128_p1363_test.json': "ddf80ba820144a9d55775d4ef2ff65117f462943988d0e9be4cdf0dc9a013604d8ad0f638866caa66643f6bb3837480270d528eb4c86ca3233d7b70ac1089e03", + 'ecdsa_secp256k1_shake128_test.json': "da83dc544d289622eede109b35c148715e92e36cedf8146b5c5856431302c0bf2696179122e0d4eda54e8cd2447b78d2198c4dd7a1e38ce436a57e6b9298323c", + 'ecdsa_secp256k1_shake256_p1363_test.json': "d3b27fadc3e13ce29c285d50b579f0552175bb7af62b7982fabd4185c114da01581bde46652beb0c5374ad6fa63217d85a3686fdfcd8a04ac524f5779c995bee", + 'ecdsa_secp256k1_shake256_test.json': "f6a04a4e3706be7c85f5186842c193b030d4e4f7359c71e8b3ce3d78f33b62513f68e76aa841caef9c2de4140755cc5227572bab1d5c978b1585036b2c08d4e3", + 'ecdsa_secp256r1_sha256_p1363_test.json': "b69438a1c52b7848c14d42b5497864e028a00ab2b6bd9535c7ccdda8250a71d4fa6aa8efa133de9d04b2f7e8d4e882955dda5b818a87748a6c42e105deb7a9d7", + 'ecdsa_secp256r1_sha256_test.json': "f3bf0aa82757e24bc0a7ff310d070b41beed993fd6ca83712761a398914783c86d76f4a4aad5bac678f980425ce5f4c1cab05c48de5fdaa22261682789ede7b5", + 'ecdsa_secp256r1_sha3_256_test.json': "c95bd5bf590fec6e7e942dde5ef9736cdaa1f4751bb7ef3898e4cd36fba2f27425ca59d239e653cba9757f531e9ba057966d016f30a0b569b24bd5190cdabbc4", + 'ecdsa_secp256r1_sha3_512_test.json': "3f77e25e3d2c0a9ad73d67ed499adce02b98521acb1bcf4b51c8fda545e849bdca0625789ad635846e1691a175101f6749e0c3885f657e8dd34eb416e3935fe0", + 'ecdsa_secp256r1_sha512_p1363_test.json': "4f0e573b4f56cf770cc64e552b86aeee9503a65aa51f6e6faafef5b81646fa773be21b0bdd0e055bfd607c81dc07ad813860461e3bedde9b7b31be33c16d2f71", + 'ecdsa_secp256r1_sha512_test.json': "542bfa5f83b4a44b497859e114f4d326548743d7955ce627fa8583af1ab704f5ba4e219a87154e41bc43cd4896d375070e95b2f76f5292a28ab6947b92d79254", + 'ecdsa_secp256r1_shake128_p1363_test.json': "91d7684cdf93f62aadcbbceab1f925d0fe383081f99232a6894235c662bfbab7142f097593c290e6a2fd6528d5ba6db9c1a0960f81e5481c89e99a27bee19a1b", + 'ecdsa_secp256r1_shake128_test.json': "5a42bb44f2e5a1671a584110f1664806050ad644631e6f1a67ed3beb6c788e5ba8e9e4933e58a11ddad2006d86d4ab02795b6d58236df15e92d4b268ea995336", + 'ecdsa_secp384r1_sha256_test.json': "b19291081e85e8d5411c01feafa3cd75abfea1e81a12ad90ea5f8d54f0c116c1e79b79be9175e8c9ada21aef5826349e417a0ef93a092339c42562b6192c137f", + 'ecdsa_secp384r1_sha384_p1363_test.json': "fe2204047f88ae726ed5188916110296e59930787b5db8b243cc296b96e449b6e4336ca16c20ef464add1a7712d8775aa9eb149e2460b56ebd73d674ef115984", + 'ecdsa_secp384r1_sha384_test.json': "b34934d80b603f5f1c56eeb341015f91e36ace086479aa677e7e32f5cecc5e25d6e2b8e5901968d9c041173bd828e23e06fa264f1ec5d8c7a242b3bdc7dd060f", + 'ecdsa_secp384r1_sha3_384_test.json': "146a5ff3d62dd4a8a75822e435c55913b7b9c8e40fb93447e65c11471034068783dfe4e5af600280a367988aa1b4b73212d98da6e3f720741b03011829afcda0", + 'ecdsa_secp384r1_sha3_512_test.json': "514de7b81e7b466adc3e255583543eb039d9a9254ce112df48509bae2819d77ab828ead9072484f699c7c0343a6688ec69c1764c3a90b15b4d83c23c99649a95", + 'ecdsa_secp384r1_sha512_p1363_test.json': "1e199e57c2c9529e9b719c63791387b0ce58977603853e10a6ebc77b1a8bae38977d6149a5b9ec8a2d34e99aa6be96c0fefae141250410018d0ccc9241bf46f7", + 'ecdsa_secp384r1_sha512_test.json': "e168ce7aa71cb3456a412ba4dcf370ec0d85b683e588e3aaf43e400a374f848fc508c8a6cccf667e64aa6db5811d7bf7614dbb6b20feee0bab410236c730516b", + 'ecdsa_secp384r1_shake256_p1363_test.json': "9c1e9d8f2366c8a166754bb5966829b97bcf7ce24a138df5af98a5f9b9d1cabd8fcaa5588600fe550362b3a43a0eab01b8d240020bbfffeda1b3cf3954c79709", + 'ecdsa_secp384r1_shake256_test.json': "216fc6a38b2cd11c72dbca9a0c91033bfcd08b9d644d2890aabc56f75993928b1d1be42f9d2e516b8e7f91a76c7284ee9a0a7e3cd3a72a2724cfe262021f88b3", + 'ecdsa_secp521r1_sha3_512_test.json': "1d22bd1409174eca101e466bd145b72d24f7d0a3581b748517d7bf715534f6d785cbaf1c5f3f8c340cc3e3577c23e7e34cb0051d6e45690225e0e91cdcf4ab3d", + 'ecdsa_secp521r1_sha512_p1363_test.json': "d69715e60aecc95138071d9d1f3465aa37a98cd8b2d5eb3a7e49a8dd5a9dcd96ff04e61e45eed576eb391aa4eaec48381cd497b85588a11b2f6d6db5222b2eb9", + 'ecdsa_secp521r1_sha512_test.json': "1014452d732f9a33b6acf340a6fd6ad37457059ce97b0e1c3b2f0f6f39bcf2590cbad459a201571da14305b02fcc847c756afd389cd76103fd99ed973dec693c", + 'ecdsa_secp521r1_shake256_p1363_test.json': "b3aa4a85832cdba635d0b55204e71612af4055ab6eccbff575a16ae9645dd8b70da988c8e176ea9f951c157b48c92f04594e9d61a56eeebbf87b80066ad2ab26", + 'ecdsa_secp521r1_shake256_test.json': "26a3cdc7a24e31efd1d5a6818617d6b68865c04b1ecae8214805b1440d0b691564bb0042cce9635fbdc8d3ef6536a175cd6feea883fdd4bc44cabb07f0486a8a", + 'ec_prime_order_curves_test.json': "e736e7353d810e499290d340ac922faa7f1906018279f3127f4383265f6fbe97f84b4c334b20807666a20608bdb6182ab289cef4ddbf192fbc2a2f49d3e71e73", + 'ed25519_test.json': "c3429b58132268803f3766b686a2e15ef52d9e59a3b1d0462c9d8c2ece0ae8d6d9b41d051ab37ea72388519bab78312500ea7e2052b7fce00271c2a86adf9645", + 'ed448_test.json': "63d02608e45125f3b9e72235a465cc4b050e30ac9914befb17f2cd0478791cef2fb5ac5c36773b836b51c1dac3ce3688b90f69e8dd3a404388cc18379ba447be", + 'hkdf_sha1_test.json': "037187bfb616b1938eb11a0b9afcc0152aa806d9fe1dd944d2524660a9d2c6474059d38265e838de0677bb6b993ab40e1a6ad18c70ca0efaf1cbefde7bfe588c", + 'hkdf_sha256_test.json': "b8d9854b418d79a265b890aec7436f9a6856bed22d7a31506699874e0505b251f5547cf064f9960f56c955a0f95f73ce39011a3ac9e2787a9beb3f5049b3414a", + 'hkdf_sha384_test.json': "424ca85042c09305ff0ff7c1c95ae8bc621a135ff28da42792ea8ec7758d4d3d096fb4a9c01dac8a0359717a4e1f043ff28992e7b19f5d6b2fd4c13e4a5dd0c0", + 'hkdf_sha512_test.json': "ad0988cd4d049284694686c32f350c39ea18c20c4b926d0b5653432d463e3183847387e37fd612cd65376301fad9b8755dc1de577262715adf46869321ebc97a", + 'hmac_sha1_test.json': "b99d895f358207ebca2d9109162d848d94b32ea4eeb71a7a5b10841695020bd2656c9f413b2d42b3fa1926a7edc6330f240d55463e674942e0dfe17ee37116fa", + 'hmac_sha224_test.json': "c3e3d603df286caa065111875550b6713a5e35b7756aafd491b537b5330304293005f62ed535e30ab5f8970803b85e8f1436a6ac4c0d49db33550804cb0b5185", + 'hmac_sha256_test.json': "f763fb3cc36280c67abde9d8cd7182e4762d4eb27708e213dd09f37ef4a88b371169f4b8675b0c4a6ec72fabc6c07823ec9c05e51a36c24eb408e71526123ea4", + 'hmac_sha384_test.json': "c263583f6775713024323e3b2d0ad5f7da811476b002bc835131b5d36f86d9a1271309a2fb06371b451ef08ff65380188fcec4508f829c61d75b25518d03d631", + 'hmac_sha3_224_test.json': "96b3e8b2f1687256c29d781f413eae5566b9769289f78b93676d57ab224cd2e70ff03f1ffefeb6fe5877b75d92609d5dcb6e5ca7331e24d12c3f88f25577890d", + 'hmac_sha3_256_test.json': "ed3d16591015756c72ff09823d87dc36221fbc483190387f129816653b9c96d8797d134e50ad7765197913b04a60a301418f12040b55c51947ca75f0392af745", + 'hmac_sha3_384_test.json': "5bb6387eabfb602060f4e2a7483111a83e0be37d5507b443c5f484ef91c717d2b5af71d8316eada168ebe81a47c0d399e503050928093f424000f92899c73d95", + 'hmac_sha3_512_test.json': "b40c162f68e2878b39c8ee15a7cb381f99e2103346b115d73830cd15531f19c6d607a0327d78cca46788db37e2936b1bcade6739515e951e7e0e79e38e51f7f1", + 'hmac_sha512_224_test.json': "88278c017075ff186dce6aa9a3500cb40a2053cef4bae8ff634aabce422125a199909f50f2dcbdc213098307c8a81fee9efce193d909de213b7342955c411a32", + 'hmac_sha512_256_test.json': "eec3fa84e6bb73505f9e4e76f06443ed6d6c4874fd495f3bc038a04c56e74c5b8e070542c2360a7db383468e15e9479413665113fd7fd10001f77cbaf528f468", + 'hmac_sha512_test.json': "47a25df89a8030c5f9845fadfee5e22fb17902488f85f32e90eed2d87b4251c78b1c98494a1a563d89c52a9312c06f13fdecff6f4db6fa191a47fe5cd887165a", + 'hmac_sm3_test.json': "d3299c5d21c99f2f9da28ee4e348fac2c5fbd69f23f224db74f77db1972f4a2a6813c00cea22a9472cc5a2944b3560a44320eb11b4a6a66a930f5c614cb424f6", + 'json_web_crypto_test.json': "6e7f5c6218b460255560f547bd5f730e9be43d64702f1f42bfbda74eb8b043f9da51a0c8569b5433305793aa6942bbb8af3f83ee33e5677b0adcce911dc2c9bc", + 'json_web_encryption_test.json': "ba8f4ce4c48102e32662e655ccace79ab6413be8c6292df85c7be32978892f5e280ecbb23c2f5bebbf18d2581458e2ddcf0d38a92513a4482f779b28da0a80a7", + 'json_web_key_test.json': "35ce8c596fdede766bbf60bcf3cd2be5e8cc2a874fb5545722374817234da3a4dd2e5462645dbbddd7ca346884c5c9064e13ee12eb57dd013c87874e029c24af", + 'json_web_signature_test.json': "f57e6dd1ec52fe8f4412a5622310813d44c2c5b0ecc12c58ec68527fe433b4d4096a314319aee90b981a0a350676f186a25ca059fc35ed6ead30b3b6dfe20677", + 'kmac128_no_customization_test.json': "f746e985e40d65cb05f16b27dcb89749cc8aa8789a1eb298acd27bab186c5c4e2214806b1b31cb4eedb7bd9fbec5c58cf506988e1838d36d3489d4b46890f35d", + 'kmac256_no_customization_test.json': "93c31894cbe055881484ee79da9b64f79314d91edcf139c58395c7550ea92ff0fb8928b583f9967da850e01abcc49f651f78d10732cc67f0791cd9cd4fab4d3b", + 'LICENSE': "8cf5c2279c45d0b1215be0b06a332782695ffaa810f93ee90a60c9aba8694dcb5ae798ea8e58743b82e60f134db0e2d91fd9c5ccb29417150368ab61c6f0af60", + 'mldsa_44_sign_noseed_test.json': "5e06e259dd15cde1ce7fd724ed22e15701e772f7a7e14aece0917b03862cec5a9302111adcf2f7e9d3e6e87ff50dcd577c1d3acbb8924dc0287a33861cd3c7bf", + 'mldsa_44_sign_seed_test.json': "fbbd614f6550b55da045eb28f6e91db41e9f184d8c79de5b8eb83e61641a916c8fe530a96ca3bdb48eabd4748c682d95f4652e4e3b02a538f7b0eefd01cffa1f", + 'mldsa_44_verify_test.json': "0d883abc079a4a984407f339ff2eb0e8d98ab640e00fb92c941d1179ed9e36a5835572dd2a6fa8a998f60a253b7253b5ae27b7f12bc461cdd4a2e1c3dc08fa69", + 'mldsa_65_sign_noseed_test.json': "c189879c24a3e30df55c987ae902499a582d00514e1e512b421ef1a1f1615c651bbd7e58c12c6fb2f59c3c918170c1d6f04511fbd13b78fad1df422f14f6ca0a", + 'mldsa_65_sign_seed_test.json': "459251fd096b4c93f2ae7dfcc99464da1704ed969a9c929a6b48a1e8ee709bee77b2d275b3333278a52d881011ed4d7af129f92dc94f4d2a37a34a369c0fd717", + 'mldsa_65_verify_test.json': "6e34eec8e7604e77d18d23e418089ddc2b650d44584e62a57ec9353ce0a305933ef34a1a60f196e5d1ce190241800e74a10a94ce93818170bc2144cce8ff929c", + 'mldsa_87_sign_noseed_test.json': "82ea848426d521804cddffd8cb9a9ec1834a039e2363111fb5996ce3a82709670119dc5ef55f18e4e0b65896d054176c69fa555133d629f6bb2a75cfedf4be27", + 'mldsa_87_sign_seed_test.json': "aeef0e74488b1b0625853fa87b9f1021180352d674203bdfa505f1ad40322ec8a30a8545405c3a5a8976c77375220fd434e3fb7f20b895271bb4695029dfe850", + 'mldsa_87_verify_test.json': "e0fdbdb42b5936a92fe9c0a61ecfda7d10e78f991b66b6a9c3a1409cccbe544023444a8db338086ed8015bf0078f7f7769bc244a404ba2473c54be9b5f5018be", + 'mlkem_1024_encaps_test.json': "40e081ea7406909aeb38b4ecf7469c546036d15a1f7d3709420fefafbea2895ba1eddf6e568b220507bb1888047e8c8f1729d34252ffbeed056f6f17d996c05e", + 'mlkem_1024_keygen_seed_test.json': "fb401e343275356717a7a0ee6d6f2d9c68ebb5ed16726c25daf42aab88cab4daad51ae025b9fb5483e7582d70cc7e3c0167968d351f8a8a386e2b54eeed18f9d", + 'mlkem_1024_semi_expanded_decaps_test.json': "75b300e5a60151b46469c6aaaf24910db60bd463cec418fb699fcdb45ecb01bbf8febfc66c7e725073564934435d3a4e6f79ce0f1cb7e6bb96e5b94c8b7e28ad", + 'mlkem_1024_test.json': "610ccae8443178f81dbf3e73d53710daf9935a6179cf19208c5083a9def2bf37e99988822bba2956e9fd8bcaf5947b3ab0636272c1798c9ca2fc734d74a568a8", + 'mlkem_512_encaps_test.json': "c1a658f023b982063868f0bf8c3d7b63f7835d8312c07d92f35eadc8010fc48bed541d95903275cfc9d77199e375c7aed2ef6f79e256e5da0361bc289d9dff68", + 'mlkem_512_keygen_seed_test.json': "7b69a209c5489bd99b5b4c18af14a1a1c23d4e6d92c7ad9ca159043a80a28095114bd6411c20676fc377a516562c17e11559d4859dc8f2a6e3a0d15347199226", + 'mlkem_512_semi_expanded_decaps_test.json': "aa7005a88e19fa6e32235324774fd1b4511fa6c5d57c661258d9aaa259b74138b02b5ab6bf5caaa73282279ace6952896c0e501b274172742ad65a488d842498", + 'mlkem_512_test.json': "69b6ac80f6e9a342177ccfcd89cf9e63859319e8e00239789f694bd1d66232bb983acd738d4b09220f595e703ceb515901fa683d3740ad6a3fdfff05478a31b5", + 'mlkem_768_encaps_test.json': "fa4bf9229ea60af13175c37f729d59cdcb6429e489b75d4f63e892f57f4e6e03533f2e2e0d7e019f4822ed16b0aed453490558a836a64e1a6c1a821853f33677", + 'mlkem_768_keygen_seed_test.json': "238d5a7e0d7177df2976e8ea0ceb5261caaf02966cd6b0cb828567678b13b6daf2f73fa48eab6b8597b1e4b237f40d82e0c2411d834d156f852a128852d6dd27", + 'mlkem_768_semi_expanded_decaps_test.json': "34472ce67ee1bf722e887baf6aa64510dd89b71cd58b98abf19dbb63993a8a40800fcbdffae1eef6993390a8a96ad082fe82bd241520bfb9ea62393a40d95bf9", + 'mlkem_768_test.json': "33c51ac42f702b0d8258184fbd7b8716e2cce53efcf19a408596f1b406c2fdbd4b80e638e869289794253264ad29c253b0bb57f10471dcee911e6b5a36949cca", + 'morus1280_test.json': "1bd1c271807b26e06cf33b7f50de1c7406efa38dd91966838400e296076451f1dd3ada4308098aa185b3962a91be3286d62344472305472def5fe0aefd5b5695", + 'morus640_test.json': "2619a079189ca8c4ad79071a80f9cb0dc5af4330b25490b03432af12997be48b046cd6949a1dc4f76ca1d93159d2b0229de89ce1bf19055a47e38a06789cd05d", + 'pbes2_hmacsha1_aes_128_test.json': "4dcd8511a36a39cf8ebf36dfc921c1bbb79b0d5dff179dddd2a37ed79b58bb8f45aa1bcb3fd7a02024580458df1813c7d1c87a63df46c9285ba99c3318d479fc", + 'pbes2_hmacsha1_aes_192_test.json': "65e072bc0faea0d0ef649c1eaf82984a241a139d91414b636679c661f4539c16aa4e9ba3852ea22e42da366450507fc3c1ee61b0c78263a59897de1b003617dd", + 'pbes2_hmacsha1_aes_256_test.json': "8a56690029fa28e8df80bb5a95389a72d1c5d23fb76ccadeb767f3e40cf2b06fa7506e7a01abe63912c13bc94123aba540aa0e0c92a43b8e6dc48ca972b5ab72", + 'pbes2_hmacsha224_aes_128_test.json': "98a5c1f874d4e85c964d23be4c46ead32f157c6231002ae0b9aa03b1a4d7833fee2719715ecae31ecd4265b44237beb409fcda197422cb6d25ef3bfce88d55a3", + 'pbes2_hmacsha224_aes_192_test.json': "f3e099e0e0f8fc8b3bfe3a6c67b28c54567f50d2d35fc845e7cc34d6c7366eaa78a48074290714a01213faf57407eb24a3b2d614823d49458dd63d4900aa0e45", + 'pbes2_hmacsha224_aes_256_test.json': "fb149363b319dfff8bd9b44453f62620af662e7e59d12e37d01c65c1504f0ab076414c475634525d6549f362da208e6dc1c0f445a92d1020af4d020b29d8f04d", + 'pbes2_hmacsha256_aes_128_test.json': "9791d10cac4cfe6aa13e955d9a1f606231455d27b13a48184eedd1cec587b4c20fec516a969b8fe82de1ed6e653d325b1d230c926e0365230e8321a535fff164", + 'pbes2_hmacsha256_aes_192_test.json': "ee31846af4512fc081c2a520a6900abfe70488341ed3b94c591dd65ebbf75c806b2d362b6d3aea04985a7b55515da07e52208aff5684be4108a0a40a5444223b", + 'pbes2_hmacsha256_aes_256_test.json': "3319746609c74a8678e2c02393da33b7b8e4f5cc9f122a79aced3d3f829d12368fd667d273b90ea3be3abf27eaf12b3ff7034f5a2c124b647d2ade0709212d65", + 'pbes2_hmacsha384_aes_128_test.json': "4734268d3045cd6c1c3d001152bceb91045ca367e998e94c2b8123bae1c0bc6e40a646b05566ebb8e27ff21c07f96a2d34b71b29cf7ba47a41af1327a12a0817", + 'pbes2_hmacsha384_aes_192_test.json': "5c415d4a16b3b0646ef2e288ce230fde3b41016b3d2ffdd42f1dab576c519087ba89cbe087abd1dc6841ed3e86e87f8e0896ccc55fb37aa4d8b91dde47e97612", + 'pbes2_hmacsha384_aes_256_test.json': "7499b1e8faa06f155dedd282d49baaf1c3103d92a90d9fd9ea9d43342ee7f037cd61ec6db11c758eefc8a2ab37aaac0c0cad946979dd90d89b0cab05c3e2e4f5", + 'pbes2_hmacsha512_aes_128_test.json': "ae7a8419b4080d1edcf051791dd162b21fbbde87671c692042d090fa7b0a3a50e740ad1ff600efe16b669e29a0a8cc76c70168ac595fddfa15358f44ffed2b43", + 'pbes2_hmacsha512_aes_192_test.json': "018312ddd664d54d1f61887c5b2eca6c53445ad687c541a112f4e01214f4bdfca3c1c040a4f58073e25bab81f9cc16594b325126ed094f25947d6736cf2dae68", + 'pbes2_hmacsha512_aes_256_test.json': "88a6744e681e932bc88cba92707dd4175d7628b28722650e583bb88996a4359cd3bfd9bf6e7d7251bacb6f6ec3f373c89a8726a7941b0fddf80950ae3853be29", + 'pbkdf2_hmacsha1_test.json': "ef7f30803bb875100f03243a4ecdaa828c931727d987b02ccdf5e11c016a9d39b701a104f139249070c0c9608bfa21094f12c1288a154146a4d5d445d6a414d4", + 'pbkdf2_hmacsha224_test.json': "c76b458adb68d4298d4488c9298e22660b88d339663bd916d4a4dca16a6c45b3deece24670f93822893fd82f1ed4fcd83320a2bd17dbd01eab4b6bd424f421c1", + 'pbkdf2_hmacsha256_test.json': "68266130cf691a7de55812ffe8467c5af0d925dd7e51a1bf7bf37920dfabb63ebbf4d63e7726c6e7c0d62267391d73225af3788d63c2aa4108d34d53ebb774b2", + 'pbkdf2_hmacsha384_test.json': "7258ded76df3f3afa2ae644fabb61ca31e2adff87a3dfb7735ffa269fdc4c84154c561292a1bcf0a604e8757390243cab30b021b65bef0a61ee368dfc0c340f3", + 'pbkdf2_hmacsha512_test.json': "acf31741f9fd073b2de96fcc054d2740b05a72d5bf28e96238bf7eaf74e036ebf1920bfa97060b572ea625ed243d62e6586f31a6e6fe79a18d7e82cc677283fd", + 'primality_test.json': "f67b59682c44c867b39ad8de4db11ae3cec54903d3ae5664665d0176c09d6247a9a759e3ddaf74557a0d463aef33e096c3c3bafb0d86ec9e84a42372d47be228", + 'rsa_oaep_2048_sha1_mgf1sha1_test.json': "11b5bdfe2e8b182188f5afc85ba9f2a90805f47f9160e9a7a09e7cbacbd09dcd50034b64cf4586f3c1dc8a5740f6961a654849f33e83843a243a8db90320efed", + 'rsa_oaep_2048_sha224_mgf1sha1_test.json': "25d839c8e212bc5c4edb42ffe782e7047d96720a5de72939e2a1ade18c6a1b7fc65aea03568c6343dd193e97c3220232c6a2ad482bd553a87a9c10f5391690a2", + 'rsa_oaep_2048_sha224_mgf1sha224_test.json': "ee36d3b23f5b30e6e2b53de9f96eb21642011dbe43082ea68f6f367e640ad278f6fb315d0159f6cfa9dfb7d65ffff3934ef97c80f83f6732dc8542afee373cc6", + 'rsa_oaep_2048_sha256_mgf1sha1_test.json': "afc711f13ff6e5b34630031fbc302eece309f132e3d31310cd43ef05f36605bc3a006a12412bca8ddff984fa358656a4a2666f2e1fcd0d6669a7be5b4c225adf", + 'rsa_oaep_2048_sha256_mgf1sha256_test.json': "3830a5ed60d6234996dd8fa336e7973c371ad5d6a3916d6e641e8bb2d1fce620db0aa68ad2a46747970a49d4215c09d649bb70fb0b67bc497c5e2c332c2bdc38", + 'rsa_oaep_2048_sha384_mgf1sha1_test.json': "8cffeb10a6b0ad360d0cb9fc598d6dbfe3e36ce905b2e5e11548b487b12cfbd962799bc58f31b106b1d4609ab7e36d1c4dda081a9f7b4c121b9c718b1ccffc96", + 'rsa_oaep_2048_sha384_mgf1sha384_test.json': "3b4295e01d8ecc5f3977639d6e83926bbeb718a5539223840eba3509f65ca03812ae704edc82b7b6b78322ce013ddc9e7f4c877b9609afdc4f50bd39ee59f5d2", + 'rsa_oaep_2048_sha512_224_mgf1sha1_test.json': "a2692a73b9f7106a6187fbee744bc95700afae8726c214b9e010f587df17cc7e15ee3a650335646c066311e948862d68b427d791f134f74acaab3af8684609c2", + 'rsa_oaep_2048_sha512_224_mgf1sha512_224_test.json': "fddfe64945f4658eaf2e2ab37dbc57684eb41374ab76634c74a9944612e0e12f18a31d82b45d47a106a5a48ff0cf5656248b09fdb05c45b8c9f8510b30e59d55", + 'rsa_oaep_2048_sha512_mgf1sha1_test.json': "06b6d80b295d82c298e7017a748ef40de6a2d7158d6720fbcf939d8402e1219e657dc78486b6a51f74ed5c1a24a8d9bae33a9a752afb86b68ac2a657734eae4f", + 'rsa_oaep_2048_sha512_mgf1sha512_test.json': "5f66c09045781395b6b0d0f34f6ed5a6a794536c6883f2e198c24ea4d2cb6fef12d96e5551ef36e9a6c09b3a5b97809a1d9d996072c65e9dbdf28690ee1f10ba", + 'rsa_oaep_3072_sha256_mgf1sha1_test.json': "6202abfba2b997f3d3f7601317bba95938230078a2edd4012ebf353169975ed788f273c841c18ed88399c167a2d089b383c0f16de6777cfa68c2d131e967a7ca", + 'rsa_oaep_3072_sha256_mgf1sha256_test.json': "893470dd1ae0fc4d943eae9f2f7bb3518ed2e075cae7817962e75e0892540ffc40c6a1eae937f0a4fa8bf26a0a0ff59b08842c30e02813dbaff32a8c7c16eaa4", + 'rsa_oaep_3072_sha512_256_mgf1sha1_test.json': "e8a98b51883b223923daf500ac36d97b727e146c877d37e70ded077e2158c320535ee9fa06faefc4139b87288def292b95738a20cbada659dc32b113f7688a68", + 'rsa_oaep_3072_sha512_256_mgf1sha512_256_test.json': "8553b7ae98101c4f01f916e4523684611ef03f94ffa069ad4361cad6f7e0603a1d7327488b5aa60c7a85f044228f97b7396e318014d274028c62f74e6faf5ae3", + 'rsa_oaep_3072_sha512_mgf1sha1_test.json': "6373311f8465bb8b93086a2fee08e80221b26fec6727e2e758f54645a7ec19642c5d16340d581cdecf0e90bb34d13412e8e3a3c020b6fbcb3fbb3263a5a025e2", + 'rsa_oaep_3072_sha512_mgf1sha512_test.json': "16e04b37123ef54cfac757e5654176f90a9b085ea822116221edbd3ad5afc7d8352dc4c18f4d60abdca6ba0d050872f5f9bcddbb45862839c998876e746cc800", + 'rsa_oaep_4096_sha256_mgf1sha1_test.json': "48ea4b20873c1bea93bb9e322ef038d805000b1d54a24f387f825c42544c204bd2a4ae2e7bf6c368443505611e9fb5ab0d524461dc94e4432c0016a450f88762", + 'rsa_oaep_4096_sha256_mgf1sha256_test.json': "b490d0aea765ae739715a91f4adccd6ab75822eeea2aa77ea25961a5b11208b77b20a445d6cd5833fb4a384bf490a3f37472492219e7d638f2101757529e555c", + 'rsa_oaep_4096_sha512_mgf1sha1_test.json': "b9849c95be878f3b5b1831f42c45a56d8a46b92e2b187dee3f2be87c376a5c3d4e9fd3c6f0242ebbc2944c62740f56aca21b508a19c8d1915cffb91deb82292c", + 'rsa_oaep_4096_sha512_mgf1sha512_test.json': "3d6dfcf28380a6395fa7908344e5e2bc6bdfadbebc64fe1d11fa2d519bfbd78f603f27a36e5310d4e76ebe7378d90f5965870ea2a542d966e58717f149410f4e", + 'rsa_oaep_misc_test.json': "c6b1b8563ee47e4079c8f1273242021fc61a2190b7f8d9d4facecff8905164235b28e64490bba35cdc2a80eaafc7a92f1d1c367f2e26bfee7b7318e03ee25f7a", + 'rsa_pkcs1_1024_sig_gen_test.json': "41f2989c6508e330f57c94fa336873734c90ce608e9bb884bdc58232db230dbd1ef10740ccbde8ce5d60251a307d9b47a9bc3d255f7775565fb3d38f72867186", + 'rsa_pkcs1_1536_sig_gen_test.json': "94aacc899097a50d0cdf361b36e7c8d94bdd115bcf9e8eb03fee0fdaf4380576ff9922f3d382208661234f3d515d763e7dfabce2aa50010dbda311cd37061a00", + 'rsa_pkcs1_2048_sig_gen_test.json': "94b8e6c8c215d66f467fc2b475982be0743fd7f9018277eaeddf231a34a1ef9fdf55b13d512ab15a6a0da1905e6c4b08fd2866b9953a2cd1f9712d5a7c06aa01", + 'rsa_pkcs1_2048_test.json': "e4afbe133355c2a726d4f2c5fefd4dfbd3318c6b337be32af129eaf0af4bab233c83f9314332cab919327a6d76a1819f15e6a0a33484fa11cfa4b9315a2ce50f", + 'rsa_pkcs1_3072_sig_gen_test.json': "662d1d04eb6ed436ea1eef20cf9ba05ed45aed7e45266e847f2fcd999bddfd465458ec352fe2355d806ce7b347324b3d8a13b74dabd37aa88989368926a4cbfe", + 'rsa_pkcs1_3072_test.json': "7164db87ed34cbc0dddfbddb3e1449b569ed48a9c53dd76f2c64cf38101c8c5d54bf1244c37ac0d94b7d11c1cc31fc7c76cc1d85801355bcc9a7eee17e95e0db", + 'rsa_pkcs1_4096_sig_gen_test.json': "709437bdd819439ea8c354bf15d894ef10b07db1da159e14b1d35d4a1c4c47e5d7b67e39d11be8b2b012517eacb609596939f652a78670ebaae12242f4958f3a", + 'rsa_pkcs1_4096_test.json': "e36e0d26558ea8f7b5f640d4b18cb6d2cd9758b5dacda1fe28f91032f6015ee8e03cf49d59e9c6d41eac691c37e330db862412e7fd7221f4c580f5aa7e452fa7", + 'rsa_pss_2048_sha1_mgf1_20_params_test.json': "cdbcefd215211d7dde12fc7c27de31cb2b771fb34f6a171ae902336525241e4685eba6150a773e669e845a7e8269b65ecd7e8e46e7350715abe838330cea2088", + 'rsa_pss_2048_sha1_mgf1_20_test.json': "e6469899ca6bc76ef2073a43b94ed3884aa76a3d9cba3cd49c32bf5ec0ca5e1a08c457fd4cd61a4d67dc837402024be37fa32338fb91261b9ebb0e81f6d73af9", + 'rsa_pss_2048_sha256_mgf1sha1_20_test.json': "fea4d48e541a65a1afd222f333961f78aa7bdc360cc702fce35d09a92f637103483e1bbae5d0c52de25fa19c979984803f82e22c29aa6ec5530611ed325a4196", + 'rsa_pss_2048_sha256_mgf1_0_params_test.json': "f5a8830bbaf9bb72f1e4efc695e8a34efcfe498f4602c0ea254f346c1ce8c278c33c3fdff2cc4a3c041100ef89aa675f57573df2a5c3a538dd367e6bbed6a3a1", + 'rsa_pss_2048_sha256_mgf1_0_test.json': "c847a70a03ba42f1e114fcc3f721d7aedd9dda5d4b792e617a329432da7a6c38f2e5910ee9477dafda0780a8a829de5d7a549e08ca4abdacfe3b801dd05f98d0", + 'rsa_pss_2048_sha256_mgf1_32_params_test.json': "833fbb7b9259401df2308eade2cb3d1351caee834c1cf68c8d51f152a049cbc31638e2c00d5c74ef85109f048b83ecba0d45d5ecbeeb342f496dd2aad0df2da6", + 'rsa_pss_2048_sha256_mgf1_32_test.json': "7baf1f5ddaffcd00f61cffb0c51ab65d4d2e1264609f1fcadf6d1f291b352c05b308ceb1e4cf9a7b8579858f816b47fe74220c9f8efddfdebfd8d2e2bfce8ca8", + 'rsa_pss_2048_sha384_mgf1_48_test.json': "b883cf86afc1a4b3ca926bea1279b5176926290c14e5e035c2d8f7cb5d3515b2077edec725ed2706c0f354f1fbe58ed3c850dab1969b6a52ceb8c56e3d0f5e5c", + 'rsa_pss_2048_sha512_224_mgf1_28_test.json': "d7aee7bcfabf5f9e2840ce29f56e7bb9674020a965c2825068caa7ed4ef2c0bf6b3f363530148f52081df339a954b62dd037a889980bd5b6db79f812fff921b5", + 'rsa_pss_2048_sha512_256_mgf1_32_test.json': "87b67c07d2246381774d8655ba55800cf1df881111e322312fb91f4c0138d70945bb664790ca9c8c29f267974d2d9278c7172aa22115760c9580e3bf13cd332b", + 'rsa_pss_2048_sha512_mgf1sha256_32_params_test.json': "84cc291697b82aad164b1cb39dd1a827355f962df606097f528d1c1fc55c9c965d56976c1eecfc83b04ffa7377fcb8ff5c59bef5d213b95a9f1791fa40a35eae", + 'rsa_pss_2048_shake128_test.json': "87e89755102a90496314e7daf254071486c222d3880b6dbf9f0600cc5325b96f0a405de46bcf4424605799fccb24414a929f0200fb9e98103cb273c10a406cc3", + 'rsa_pss_2048_shake256_test.json': "ac0ed3c4beb5ce6c3ece709bfc28a5ac8d189b622f59ee3920d6eb30f862b03128003b15fb814c05400570deafa8e91dcc6781dee424b9cc0615fa2a5b020082", + 'rsa_pss_3072_sha256_mgf1_32_params_test.json': "a15a20bc37a2090bfd47382510e8fda94e32819bab8b1f1c2a797786968845f1c840038e8852fdbaae5bb003e519acfbc5059913925fd4a6f4a2a386dfaea536", + 'rsa_pss_3072_sha256_mgf1_32_test.json': "308cf529b12f39e97b2ec10dacecdc06eace7a94dbec1f1aefac717a7da6d43375c9273b400ff3fdc392bd136920943012c3917069d0c4e99215202a4be70f9f", + 'rsa_pss_3072_shake128_test.json': "6417d966ddfb9e0862bcc9b02ab967421ff7aad2d2b13011cca1070c3281b5109a0c6ce1dd6ac0aa6e5ece4be5d2ce91bd40508403dd10a0dfe9268df937705e", + 'rsa_pss_3072_shake256_test.json': "ead39cf4877b98a79583ade599c7e0e118d3dd69ec6c82ef1590122f3621f6cf0f6d569df3d58c6bbe086102889feb685f964554aed2defd3f05639184231cc6", + 'rsa_pss_4096_sha256_mgf1_32_test.json': "1812b9988cb867f67bd975f940560751bd7317279bc6a08769b6060c453ce464ce420c6c5fdbb02df90e036ed3474b8f052eaf351c67cab0a21f911f156c69d2", + 'rsa_pss_4096_sha384_mgf1_48_test.json': "edcf2757d25e8824a33bf64fcc8622071ef510cd4ef21878002cb3b79c88d69a03e77dfa73d083cbdc62e8eb7accc12fcea447c9c2a805bac2492e7df7dea615", + 'rsa_pss_4096_sha512_mgf1_32_params_test.json': "fb5c743dafffae4fa96564d50be5decb8712d8247e4066f0e2eee040bc0fd0d458a803e72327151dc7eae93223455f162c6ef46d7c5650a1abc9e483c5f262ac", + 'rsa_pss_4096_sha512_mgf1_32_test.json': "b1e6ee3d4a7be1562237e8362450319df027318042111eb11add1bb0cc5e35db274962dc6f61718fcb83165a8ed8fe0adaf3d446b2e2b75486ddb948574e0d08", + 'rsa_pss_4096_sha512_mgf1_64_params_test.json': "61109281f59667eaec913bd98ba9dd5b84418fe697331a6dc9b53720833f98da64c8b561b57c853c797f7d5de8ae212554eb6836087d62d016f9208835844b05", + 'rsa_pss_4096_sha512_mgf1_64_test.json': "fb3632478e0d261741443865f5cbe7954103186ecf8098d5c52f88b2f85c870961a3c90599e256fe46185f8b6ab8b1c36b326aa30fea4090f5e55eb6b9ff3544", + 'rsa_pss_4096_shake256_test.json': "5add00e096f35b72f062f169a4c6cb11ea8f93235d9ff7ea72b4ab4d226fd8a470368dfd5335b4f7abf3a5cb3f81759a8c99ca8209c4891e0d7bc08ffaa4ab5a", + 'rsa_pss_misc_params_test.json': "aa871f1dcd047e116f67edf398a839ee9e93f301ba746592a4f718d1f351e1dfaa731501ae18881217ce48086258a7c0a107a85c900bf3ecff4d64f639f98a17", + 'rsa_pss_misc_test.json': "2ad28380f1455adf0048369df811c7c6d6a3c7002945e3f30ef889243f94b62f8602ad7f461f616dfbe0b75c96269eac86f99ad6288d842ddc3c9cc4fd7b3dd6", + 'rsa_signature_2048_sha224_test.json': "6601b34eaf82d03c3c3b1b4041a7009de8aaf2c4e3bf527519ce237ba94b38b848e3bbf04eaacd3d084d3bef9126f2f4ff9b678126fc3fdfa5429503a028f546", + 'rsa_signature_2048_sha256_test.json': "d5150fe23f6215406edc768682ea71070f49c8f4a718b2f3da113e9a5213577f2c79e1eff1d4506c8ba89fc42ecbb5fd301a47c26030490f4ac06f2feabc936e", + 'rsa_signature_2048_sha384_test.json': "cb045c76ad23f9fdb3abb38bcfa7a78cea1e13a7f512e777cd44b21f644d96ebe780d042435b4ed32f16582745c895fff4ddf9071b7f7c4bbbd0a71631b4f57d", + 'rsa_signature_2048_sha3_224_test.json': "527f64300e61defd85cbe2d4c4f4eab2c2a6baa0ea16ba918ecf399c51ea530bf3b63f4322b3e7a0eee15aaf50d1cc851cc076b30219c2bb0b2d28348006e3fb", + 'rsa_signature_2048_sha3_256_test.json': "1038614b3760b2d57017c266985e17527002eac224945c4584da572611c46d0ca2b58293b663b7709bbb27646802634dab8d4fb123f36fad01f5a74b1324e23d", + 'rsa_signature_2048_sha3_384_test.json': "d386a2a69d558f9a4f5d09795486d628044c5b56fe34c4d5d66063533133541594b4f5f9330541cdeebd1c1ab7a11488d96a852e5fd69ba9fa08c9157d102fd6", + 'rsa_signature_2048_sha3_512_test.json': "f5ea0d29bb0887f9401bafff3cdc35a45c0196070616df75e5ac8a12caaf5e238080eceb4265962aae4e299f991be73eb0e4fddead0bc795e32b023547160761", + 'rsa_signature_2048_sha512_224_test.json': "96e0032b3af2ae3a8d5626a79488a112926b599f1f9fc4e47d5d7941898a5dbb0afe689de16bc79dcf13656e0b32e052b6704bdec673ae2b99383b68285cdbd5", + 'rsa_signature_2048_sha512_256_test.json': "fe54c5821e526f3374d03e7c1313e3783cd986b07a4c9858bcf3aa20d8c85b27d898394b4c37c1483fc16ca1ac5b59681ace58fba625f84feb9af7455d38ab20", + 'rsa_signature_2048_sha512_test.json': "2b9f6c3da08266a40b7529443aa42738bf7fd23842ad3792cdee9a587fd6056bf7eb1ec72867d3006f1a98728a3e528575ffdd7229325e13fafd6f363edda0a7", + 'rsa_signature_3072_sha256_test.json': "17999b3add8f853b07d6ca9e24fd58b275abb725bca8f7203787f57d8af0c03f7bdc15a6eacee1337d9621b2d53a8cac86de7b2e6a444abe81da8139838a8c7e", + 'rsa_signature_3072_sha384_test.json': "9f9a8ee0d78bb6481d94c1f9e41eb77438f33308c163c1634ec122dffe133fdef9c5cf1eb8c7ce4b0161df651f2d04a0250fa25d7fc82deb9eea105fe69121f2", + 'rsa_signature_3072_sha3_256_test.json': "6f4b2e8ba2436fe4c21e3d19e4a8572227bae64e9860a55462fc1b439900e9f443fbea4c5294cf262805d35ff8360ce48ea6c80ec5e4d82ad70c193680c8e28e", + 'rsa_signature_3072_sha3_384_test.json': "05b4a8736086dd21af73e84240ecf2ae217d45aab051f5c65744ac95777e82ca45bd0026881e08b1d817e7e015ccd8372e7d4c83356e896914307242eabab0b0", + 'rsa_signature_3072_sha3_512_test.json': "f188eb1849e68f30fb8d7e925ec6c575702ef0b1b06db618db558f35a01c4e541e8dedcb10e4eeec416cff82a4136a086cb2fc3b9e37434e4a5d8b5d11004d4e", + 'rsa_signature_3072_sha512_256_test.json': "d9e04c0bb74c874f1a51219b1dcba0b23780f64fb552d810683a48d1e47809acb84a4b2ce54e17f77be15b1798bbef64eb44c0722920dd96deff9472f5262093", + 'rsa_signature_3072_sha512_test.json': "23b528243e764425738dcafdd598845c59a3d8bbaeeefe432fb25f8ade7fd611f4f336d3fa91e079b149ea125c1d9d889317606a351827fb73b93a2dc8301e09", + 'rsa_signature_4096_sha256_test.json': "13c86fcb11277e72dbb54cd1e4c4cfadbc5605eeba3672130827a593b6bb703d927138bafee5daa03ae30bae15a352bf22abcdf518cebacd0f5b55c08bdaeccb", + 'rsa_signature_4096_sha384_test.json': "8881628f3b4015a729d88167fa98b3be5eb9cbda23e6766d5ba45a4a00dfa684d60cd269662e6df54771b7393cf01ce0fecdd572395606ad2e9d129e0b992a0f", + 'rsa_signature_4096_sha512_256_test.json': "6cd08b03cba8779ac57782d4030dff7fe277393aa1e308a647c5be1a64066eb0faf43a3e5f526bc76706e8e0d808c5b37ee4a4e0046e61aa68b41f1b80306a43", + 'rsa_signature_4096_sha512_test.json': "021cb140c1f7f7f87c22cf891c40ae5544f1c92926e9c8ea7af838ea496bb4dba646c120fe6fe75d81808cdbb515799bcfc8df1b1c3cbb4f9561821891a6d92b", + 'rsa_signature_8192_sha256_test.json': "8dbea635f9123af876287f583849b29186030cd270b709dd08b272f03acf4cec0c3cc3e77d45542ad606d101e59cb7feafe8af094f2bc2b38bc3cf08d8169266", + 'rsa_signature_8192_sha384_test.json': "c518417449709d88f3ad7aa1307b60a5d17fb575754674523a848b5030fa89a0501b396fb5fdc77902eec3f000272cb28458efe3473a80a407dcea0de6a06a8f", + 'rsa_signature_8192_sha512_test.json': "1cd1800f716214697507df8c099c3c01f512491ef8c008003da8f83326e3d08476365c96c03f91e0f22395f99fc01aa750aeee254fa22f81dc903418f41784bb", + 'rsa_three_primes_oaep_2048_sha1_mgf1sha1_test.json': "c629e7997fcec21d05891d944ab5fffcd673e5f2eb26b3931885f900081d9cfd63dfc09e009e95972118e1f1096803ca108c425b996ae0f83b90e9ecf3277247", + 'rsa_three_primes_oaep_3072_sha224_mgf1sha224_test.json': "d74d361bae2e5516ae5595afd929dbab2dcb03802c89899a6d097b86b1a815cb2237a55cf5e54df6179f08ebff573a03f59815fe2869308b752f52812ce7f6b0", + 'rsa_three_primes_oaep_4096_sha256_mgf1sha256_test.json': "214c700242fc7bad97b8086b13b4c607c7a51e4fa6eb0ba0263741c97ecd7969cbdb85bf0359254080da13e112af458b8fd0a100178b10ef5881162ec3658345", + 'seed_ccm_test.json': "b9d61c16f439b9547ce15344b806d98f36da7030f31d4eab1c558029d4e3410470b97e8d471a27dc75eb74ecec99cdcfb7911b605e5f700b665e50d6a7ad42be", + 'seed_gcm_test.json': "422745f91d72d71d3d1238269ba1dc6234f2a5445d637988acd86d9a383bdfde5391bf5c3c3d4fa0f9fc415d371a9724b2f76f0535229eadc29bda0c01d2c812", + 'seed_wrap_test.json': "a87be3d6c8127970b617d67f35b95be529808273a078bf82f2d8b2bbde2a6608e21559c2a2ee276552745da6cb1f0a253eca67991af2b05b57ed7487ff2fed4f", + 'siphashx_2_4_test.json': "72d16dcd5b56f08079146c79918f3b80a442a17cdc62b2097c8c2956f799e90ba9cca9d80cc8b0220b7f1fb83b4a1e27b6658cc5cd24e2f5c42a57fc47e4cd64", + 'siphashx_4_8_test.json': "d183ba80de092cd66ff8443286b9d22d838d79214827d02aa5323081d578d9dab21485cdeb6c0dda59d151bb6d0596d50d8254836fd25d9278f1a795f5d807d4", + 'siphash_1_3_test.json': "ac056415a0d4e45d802179b7efeebd034a7fc2110fee14b293e16af1edf95448a12160a6e6c2d95b36fe937102ba33264b29c2b1eb452df2ac766fe29b368436", + 'siphash_2_4_test.json': "d7cff2d63f881285567f9aeaca23fc2c94ea465fb442687b0ea94e9647eddcfc05d1b36c2435482b1d492c32b21fc50636a258e2e9c62d9ae6ddbabc93564ca9", + 'siphash_4_8_test.json': "6e49e401186510df582b68df50f8b331ad67609e18fbffe4adb359eb8d9e8f727a6abf3f4d5de1f33f4efb82b86a07f004f49c52d2c5e775e9319fd2c7d969e7", + 'sm4_ccm_test.json': "e963c49fab1e0d8ee050658e797d8c5b2d80cce39fa338833d46a2d7bc5e54036a41610063c0c74644e56589d1697396e1bfa4925e7a5592fa2247cb983441f0", + 'sm4_gcm_test.json': "9f64992c6c5469827d281a55c1612b0029fe344322c8cd7a7f2cefecc597dfb0f3f7b6cf85153f79e12c3539d553d591a8e9a1d0d714a58fb967e6fdfdfebc30", + 'vmac_128_test.json': "9fc97358a5ad56d4badc2b2ba35c07cd4872cf3687da667fddc3f628765330e6a9fc179e55c9a28b87cc02c92b80461d4db99073637fb17b1cf2a74bd5347a68", + 'vmac_64_test.json': "835e384b5d53bef8680520fc2ddb94ecc5d30e8aa65cdf0c6a48615e93273850d6333e19670d0ad40eeee645ebfd5c139f377518987e37ea6f6e6b28a22d0bde", + 'x25519_asn_test.json': "d43e2003c96c50c616cb093b8bcc4f70ca8931d2be83b1ca860900acaf65cd25ab347100c1a6fcb2561f1f29eedb52ff3e1bde70b29a757d4f814daf3cad35db", + 'x25519_jwk_test.json': "2f7f54dccb9c0882ec4a5e9da7c7779d18b7551729e805d2db51bd84a16abd07dcc3b0d7c922dc322b2da05708f0e00c612cea1b2d0c6f567aca09d846629b7e", + 'x25519_pem_test.json': "73530bc171e3a9ab5d82236a8c9c2fa4e565d8e1c83169036920ed22aa29f1122dbda9cae1c33dc5366b2b21aeec377930d6c305e6f00404bf25c4e679572841", + 'x25519_test.json': "857144ffa55ca421df7231594b23a5ed5b83f0f04ac1a707177c6d80d3cf1f69f42436abd3d7b2551788064cdbf01a2e2e25e0272d1ca8bc4a943b981dccefd5", + 'x448_asn_test.json': "b4fe61c5b1a57a887e539afe815ed970afba6eca055b674cb615945df39da911aeb41092570fcf480b5ad347520cc678aa0baf93ae574b272ce2457b802d4dcd", + 'x448_jwk_test.json': "402813856f68470b39df34e160211b53f90cfeba63c6b32c8b49d4d4bfa60b68c94cd1a04fdc09f07676a8f2942bc227ef75165456f6055cc0df3cc1e4381cd4", + 'x448_pem_test.json': "718ef327a5e8cc3a34467974193a051efe89323352f32f248c874457f28f6a2836cb6c2c15f40044df96428051591766fc0b44771236145a17835e714360ca51", + 'x448_test.json': "ca811349ede46fc253d656c26b058e2fe903aae8a225d7f6703bef3dec122df4c48af190a070df4c4066690f50ed4996d69089794b5484b57f2c4233216f98f5", + 'xchacha20_poly1305_test.json': "5debf381018af54fa2f9041044a257f8faff85b9a2eda314f21a05a55de2aacd2767a4962ecc58f69ed65404dc7d2b1eb8526038e7641610ce3a988456838fce", + + 'LICENSE-APACHE-snow.txt': "6d94a2c13b32d3c0db347511a19f71e5c2ec15025f3f3fdb333ae72e3c671b0b4d8796a9adf3e9b1ec941acea28a054e7108914ee93ebae673d894d2ac4a7cad", + 'LICENSE-MIT-snow.txt': "c0d9d5f399729560ffbabcb46a1e282e9a214d436a59b86dd8765556290a93c204c126234401f935f6a18aff50d69cc8af4decc6f0bb1574f899412c77fb9b31", + 'LICENSE-cacophony.txt': "cab56e8608950b3e9d5c0d8262f8c67e34254569726e78968896a964bab84e67fd66ccce43653118152fba5a3e670e0de23c725ecd85f65cacce4d987b1258e8", + 'LICENSE-noise-c.txt': "ca6ef9d13d0832659efa04f03d06998af3050b0f65886f1b4f33ef4bd9b6df639fcaac0c73a7c28bc47c502e7915e30608863340245eac7620ab50ee66e99ff6", + 'cacophony.txt': "d2c492f02287ee562a9cf43a4cd2a055f5235734779d091bc404aede4c37a552029e76c12e873632e52423804ad24b86138cd3d4fe54506108571d9f2f925033", + 'noise-c-basic.txt': "7e25c5d692c53dd045060f27a562332178ca030d17687fc2ab58216b4298fb577ddc9d703db11c920fb04c28604fdc1a30337f58aad3617e07201a62c3a9b295", + 'snow.txt': "35088303de90e6bac22656e1e0ac4a5ea73d8cdb5ada23a078d703e14714ffe19e08437bf46108e0419acd8b5be6fa797a68a621c20cdd063d94a4a970aa8634", } def try_download_file(url, out_file): @@ -291,63 +645,71 @@ def try_download_file(url, out_file): print("Could not download", url) return 1 -def try_download_and_unpack_zip(suite): +def try_download_and_unpack_zip(base_path, suite, debug): url = ASSETS_BASE_URL.format(suite, "{}.zip".format(suite)) - out_file = DOWNLOAD_BASE_PATH.format(suite) + "/{}.zip".format(suite) + out_file = base_path + "/{}.zip".format(suite) - print("\tDownloading {} to {}".format(url, out_file)) + print("Downloading {} to {}".format(url, out_file)) - if try_download_file(url, out_file) is not None: - print("Could not download ZIP file") - return 1 + try_download_file(url, out_file) # Try opening the ZIP file and extracting the test images #try: with zipfile.ZipFile(out_file) as z: - print("\tUnpacking and verifying using HMAC(\"{}\", data, {}):\n".format(HMAC_KEY, HMAC_HASH.__name__)) + print("Unpacking and verifying using HMAC(\"{}\", data, {}):\n".format(HMAC_KEY, HMAC_HASH.__name__)) for file in z.filelist: if file.filename not in HMAC_DIGESTS: print("Missing digest for {}".format(file.filename)) return 3 - extract_path = DOWNLOAD_BASE_PATH.format(suite) - z.extract(file, extract_path) + z.extract(file, base_path) - file_path = "{}/{}".format(extract_path, file.filename) + file_path = "{}/{}".format(base_path, file.filename) with open(file_path, "rb") as f: file_data = f.read() digest = hashlib.sha3_512(file_data).hexdigest() hmac_digest = hmac.new(HMAC_KEY.encode(), file_data, HMAC_HASH).hexdigest() - print("{} *{}".format(hmac_digest, file.filename)) if not hmac.compare_digest(hmac_digest, HMAC_DIGESTS[file.filename]): - print("FAIL! Expected: {}".format(HMAC_DIGESTS[file.filename])) + print("❌ Expected {}, got {} for {}".format(HMAC_DIGESTS[file.filename], hmac_digest, file.filename)) return 4 + else: + if debug: + print("✅ {} *{}".format(hmac_digest, file.filename)) + + if debug: + print("\n") #except: # print("Could not extract ZIP file") # return 2 def main(): - for suite in TEST_SUITES: - print("Downloading {} assets".format(suite)) + if len(sys.argv) < 2: + print("Usage: {} [debug]".format(sys.argv[0])) + return 1 + debug = False + if len(sys.argv) >= 3 and sys.argv[2] == "debug": + debug = True + + for suite in TEST_SUITES: + base_path = sys.argv[1] + "/{}".format(suite) # Make assets path try: - path = DOWNLOAD_BASE_PATH.format(suite) - os.makedirs(path) + os.makedirs(base_path) except FileExistsError: pass # Try downloading and unpacking the assets - r = try_download_and_unpack_zip(suite) + r = try_download_and_unpack_zip(base_path, suite, debug) if r is not None: return r # We could fall back on downloading the PNG files individually, but it's slow - print("\nDone downloading {} assets.".format(suite)) + print("Done downloading {} assets.\n".format(suite)) return 0 diff --git a/core/encoding/base32/base32_test.odin b/tests/core/encoding/base32/base32.odin similarity index 82% rename from core/encoding/base32/base32_test.odin rename to tests/core/encoding/base32/base32.odin index ea41ae36f..2abb244ca 100644 --- a/core/encoding/base32/base32_test.odin +++ b/tests/core/encoding/base32/base32.odin @@ -1,7 +1,10 @@ -package encoding_base32 +package test_encoding_base32 import "core:testing" import "core:bytes" +import "core:encoding/base32" + +Error :: base32.Error @(test) test_base32_decode_valid :: proc(t: ^testing.T) { @@ -19,7 +22,7 @@ test_base32_decode_valid :: proc(t: ^testing.T) { } for c in cases { - output, err := decode(c.input) + output, err := base32.decode(c.input) if output != nil { defer delete(output) } @@ -49,7 +52,7 @@ test_base32_encode :: proc(t: ^testing.T) { } for c in cases { - output := encode(transmute([]byte)c.input) + output := base32.encode(transmute([]byte)c.input) defer delete(output) testing.expect(t, output == c.expected) } @@ -61,7 +64,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Characters outside alphabet input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7) - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -70,7 +73,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Lowercase not allowed input := "mzxq====" - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -79,9 +82,18 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { // Section 3.2 - Padding requirements { - // Padding must only be at end + // Padding in middle without trailing padding + input := "MZ===YTBMZXW6YTB" // '===' in middle, no trailing padding + output, err := base32.decode(input) + if output != nil { + defer delete(output) + } + testing.expect_value(t, err, Error.Malformed_Input) + } + { + // Padding must only be at end (with trailing padding) input := "MZ=Q====" - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -90,7 +102,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Missing padding input := "MZXQ" // Should be MZXQ==== - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -99,7 +111,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Incorrect padding length input := "MZXQ=" // Needs 4 padding chars - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -108,7 +120,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Too much padding input := "MY=========" // Extra padding chars - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -119,7 +131,7 @@ test_base32_decode_invalid :: proc(t: ^testing.T) { { // Single character (invalid block) input := "M" - output, err := decode(input) + output, err := base32.decode(input) if output != nil { defer delete(output) } @@ -140,9 +152,9 @@ test_base32_roundtrip :: proc(t: ^testing.T) { } for input in cases { - encoded := encode(transmute([]byte)input) + encoded := base32.encode(transmute([]byte)input) defer delete(encoded) - decoded, err := decode(encoded) + decoded, err := base32.decode(encoded) if decoded != nil { defer delete(decoded) } @@ -187,7 +199,7 @@ test_base32_custom_alphabet :: proc(t: ^testing.T) { */ custom_validate :: proc(c: byte) -> bool { - return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(PADDING) + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(base32.PADDING) } cases := [?]struct { @@ -201,12 +213,12 @@ test_base32_custom_alphabet :: proc(t: ^testing.T) { for c in cases { // Test encoding - encoded := encode(transmute([]byte)c.input, custom_enc_table) + encoded := base32.encode(transmute([]byte)c.input, custom_enc_table) defer delete(encoded) testing.expect(t, encoded == c.enc_expected) // Test decoding - decoded, err := decode(encoded, custom_dec_table, custom_validate) + decoded, err := base32.decode(encoded, custom_dec_table, custom_validate) defer if decoded != nil { delete(decoded) } @@ -218,7 +230,7 @@ test_base32_custom_alphabet :: proc(t: ^testing.T) { // Test invalid character detection { input := "WXY=====" // Contains chars not in our alphabet - output, err := decode(input, custom_dec_table, custom_validate) + output, err := base32.decode(input, custom_dec_table, custom_validate) if output != nil { delete(output) } diff --git a/tests/core/encoding/base64/base64.odin b/tests/core/encoding/base64/base64.odin index 6679c8ce2..ba7572139 100644 --- a/tests/core/encoding/base64/base64.odin +++ b/tests/core/encoding/base64/base64.odin @@ -31,8 +31,56 @@ test_encoding :: proc(t: ^testing.T) { @(test) test_decoding :: proc(t: ^testing.T) { for test in tests { - v := string(base64.decode(test.base64)) + v, err := base64.decode(test.base64) + if !testing.expect_value(t, err, nil) { + continue + } defer delete(v) - testing.expect_value(t, v, test.vector) + testing.expect_value(t, string(v), test.vector) } } + +@(test) +test_decoding_failure :: proc(t: ^testing.T) { + v, err := base64.decode("!#$%") + testing.expect(t, v == nil) + testing.expect(t, err == base64.Decode_Error.Invalid_Character) +} + +@(test) +test_roundtrip :: proc(t: ^testing.T) { + values: [1024]u8 + for &v, i in values[:] { + v = u8(i) + } + + encoded := base64.encode(values[:]) + defer delete(encoded) + + decoded, err := base64.decode(encoded) + if !testing.expect_value(t, err, nil) { + return + } + defer delete(decoded) + + for v, i in decoded { + testing.expect_value(t, v, values[i]) + } +} + +@(test) +test_base64url :: proc(t: ^testing.T) { + plain := ">>>" + url := "Pj4-" + + encoded := base64.encode(transmute([]byte)plain, base64.ENC_URL_TABLE) + defer delete(encoded) + testing.expect_value(t, encoded, url) + + decoded, err := base64.decode(url, base64.DEC_URL_TABLE) + if !testing.expect_value(t, err, nil) { + return + } + defer delete(decoded) + testing.expect_value(t, string(decoded), plain) +} diff --git a/tests/core/encoding/cbor/test_core_cbor.odin b/tests/core/encoding/cbor/test_core_cbor.odin index ee853ebac..6e3312779 100644 --- a/tests/core/encoding/cbor/test_core_cbor.odin +++ b/tests/core/encoding/cbor/test_core_cbor.odin @@ -43,6 +43,8 @@ Foo :: struct { biggest: big.Int, smallest: big.Int, ignore_this: ^Foo `cbor:"-"`, + mat: matrix[4, 4]f32, + vec: #simd [4]f64, } FooBar :: enum { @@ -95,6 +97,8 @@ test_marshalling :: proc(t: ^testing.T) { onetwenty = i128(12345), small_onetwenty = -i128(max(u64)), ignore_this = &Foo{}, + mat = 1, + vec = 2, } big.atoi(&f.biggest, "1234567891011121314151617181920") @@ -120,11 +124,35 @@ test_marshalling :: proc(t: ^testing.T) { defer delete(diagnosis) testing.expect_value(t, diagnosis, `{ "no": null, + "mat": [ + 1.0000, + 0.0000, + 0.0000, + 0.0000, + 0.0000, + 1.0000, + 0.0000, + 0.0000, + 0.0000, + 0.0000, + 1.0000, + 0.0000, + 0.0000, + 0.0000, + 0.0000, + 1.0000 + ], "neg": -69, "nos": undefined, "now": 1(1701117968), "pos": 1212, "str": "Hellope", + "vec": [ + 2.0000, + 2.0000, + 2.0000, + 2.0000 + ], "yes": true, "comp": [ 32.0000, @@ -399,6 +427,7 @@ test_unmarshal_map_into_struct_partially :: proc(t: ^testing.T) { } Foo_More :: struct { + foo: bool, bar: struct { hello: string, world: string, @@ -408,6 +437,7 @@ test_unmarshal_map_into_struct_partially :: proc(t: ^testing.T) { baz: int, } more := Foo_More{ + foo = false, bar = { hello = "hello", world = "world", diff --git a/tests/core/encoding/hxa/test_core_hxa.odin b/tests/core/encoding/hxa/test_core_hxa.odin index a8f3e94f6..a4fee030c 100644 --- a/tests/core/encoding/hxa/test_core_hxa.odin +++ b/tests/core/encoding/hxa/test_core_hxa.odin @@ -1,6 +1,3 @@ -// Tests "core:encoding:hxa". -// Must be run with `-collection:tests=` flag, e.g. -// ./odin run tests/core/encoding/hxa/test_core_hxa.odin -out=tests/core/test_core_hxa -collection:tests=./tests package test_core_hxa import "core:encoding/hxa" @@ -13,13 +10,11 @@ import "core:os" @test test_read :: proc(t: ^testing.T) { - data, _ := os.read_entire_file(TEAPOT_PATH) - // file, err := hxa.read_from_file(TEAPOT_PATH) + data, _ := os.read_entire_file(TEAPOT_PATH, context.allocator) file, err := hxa.read(data) file.backing = data file.allocator = context.allocator hxa.file_destroy(file) - // fmt.printfln("%#v", file) e :: hxa.Read_Error.None testing.expectf(t, err == e, "read_from_file(%v) -> %v != %v", TEAPOT_PATH, err, e) diff --git a/tests/core/encoding/ini/test_core_ini.odin b/tests/core/encoding/ini/test_core_ini.odin index 6e6c8152e..8c554c6b5 100644 --- a/tests/core/encoding/ini/test_core_ini.odin +++ b/tests/core/encoding/ini/test_core_ini.odin @@ -1,8 +1,7 @@ +#+feature dynamic-literals package test_core_ini -import "base:runtime" import "core:encoding/ini" -import "core:mem/virtual" import "core:strings" import "core:testing" @@ -64,7 +63,7 @@ ini_to_string :: proc(t: ^testing.T) { testing.expectf( t, - strings.contains(str, "[LEVEL]LOG = debug"), + strings.contains(str, "[LEVEL]\nLOG = debug"), "Expected `ini.save_map_to_string` to return a string equal to \"[LEVEL]LOG = debug\", got %v", str, ) diff --git a/tests/core/encoding/pem/pem.odin b/tests/core/encoding/pem/pem.odin new file mode 100644 index 000000000..6da8ecd1a --- /dev/null +++ b/tests/core/encoding/pem/pem.odin @@ -0,0 +1,86 @@ +package test_core_pem + +import "core:bytes" +import "core:encoding/hex" +import "core:encoding/pem" +import "core:testing" + +// RFC 7468 Section 9. +@(private) +CMS_PEM_TEXT : string : \ +`-----BEGIN CMS----- +MIGDBgsqhkiG9w0BCRABCaB0MHICAQAwDQYLKoZIhvcNAQkQAwgwXgYJKoZIhvcN +AQcBoFEET3icc87PK0nNK9ENqSxItVIoSa0o0S/ISczMs1ZIzkgsKk4tsQ0N1nUM +dvb05OXi5XLPLEtViMwvLVLwSE0sKlFIVHAqSk3MBkkBAJv0Fx0= +-----END CMS-----` +@(private) +CMS_PEM_PAYLOAD : string : "308183060b2a864886f70d0109100109a0743072020100300d060b2a864886f70d0109100308305e06092a864886f70d010701a051044f789c73cecf2b49cd2bd10da92c48b5522849ad28d12fc849ccccb35648ce482c2a4e2db10d0dd6750c76f6f4e4e5e2e572cf2c4b5588cc2f2d52f0484d2c2a514854702a4a4dcc064901009bf4171d" +@(private) +NOT_PEM_TEXT : string : \ +` +Socialism is not in the least what it pretends to be. +It is not the pioneer of a better and finer world, but the spoiler of what thousands of years of civilization have created. +It does not build, it destroys. +For destruction is the essence of it. +It produces nothing, it only consumes what the social order based on private ownership in the means of production has created. ` +@(private) +COMMENT_TEXT : string : "# 9. Textual Encoding of Cryptographic Message Syntax" + +@(test) +test_pem_roundtrip :: proc(t: ^testing.T) { + // Decode. + blk, remaining, err := pem.decode(transmute([]byte)(CMS_PEM_TEXT)) + if !testing.expectf(t, err == nil, "PEM decode failed: %v", err) { + return + } + defer pem.block_delete(blk) + + if !testing.expectf(t, len(remaining) == 0, "PEM decode left trailing garbage: '%s'", remaining) { + return + } + + // Ensure contents match. + if !testing.expectf(t, blk.label == pem.LABEL_CMS, "PEM unexpected label: '%s'", blk.label) { + return + } + expected_payload, _ := hex.decode(transmute([]byte)(CMS_PEM_PAYLOAD)) + defer delete(expected_payload) + + if !testing.expectf(t, bytes.equal(pem.block_bytes(blk), expected_payload), "PEM unexpected data: '%x'", blk.data) { + return + } + + // Encode and compare. + encoded := pem.encode(blk.label, pem.block_bytes(blk)) + defer delete(encoded) + testing.expectf(t, CMS_PEM_TEXT == transmute(string)(encoded), "PEM encode mismatch: '%s'", encoded) +} + +@(test) +test_pem_no_blocks :: proc(t: ^testing.T) { + blk, remaining, err := pem.decode(transmute([]byte)(NOT_PEM_TEXT)) + testing.expect(t, blk == nil) + testing.expect(t, len(remaining) == 0) + testing.expect(t, err == nil) +} + +@(test) +test_pem_surrounded :: proc(t: ^testing.T) { + blob := COMMENT_TEXT + "\n" + CMS_PEM_TEXT + "\n" + NOT_PEM_TEXT + + // Should skip `COMMENT_TEXT` + blk, remaining, err := pem.decode(transmute([]byte)(blob)) + if !testing.expectf(t, err == nil, "PEM decode failed: %v", err) { + return + } + defer pem.block_delete(blk) + + // Check if the decode is correct by ensuring it round-trips. + encoded := pem.encode(blk.label, pem.block_bytes(blk)) + defer delete(encoded) + if !testing.expectf(t, CMS_PEM_TEXT == transmute(string)(encoded), "PEM encode mismatch: '%s'", encoded) { + return + } + + testing.expectf(t, NOT_PEM_TEXT == transmute(string)(remaining), "PEM remaining not preserved: '%s'", remaining) +} diff --git a/tests/core/encoding/xml/test_core_xml.odin b/tests/core/encoding/xml/test_core_xml.odin index 409a8c9c0..c03dfe29d 100644 --- a/tests/core/encoding/xml/test_core_xml.odin +++ b/tests/core/encoding/xml/test_core_xml.odin @@ -114,7 +114,7 @@ xml_test_entities :: proc(t: ^testing.T) { }, expected_doctype = "html", }, - crc32 = 0x48f41216, + crc32 = 0x98791215, }) } @@ -128,7 +128,7 @@ xml_test_entities_unbox :: proc(t: ^testing.T) { }, expected_doctype = "html", }, - crc32 = 0xd0567818, + crc32 = 0x5fd5ab4e, }) } @@ -142,7 +142,7 @@ xml_test_entities_unbox_decode :: proc(t: ^testing.T) { }, expected_doctype = "html", }, - crc32 = 0x68d2571e, + crc32 = 0xda1ac384, }) } @@ -186,7 +186,7 @@ xml_test_unicode :: proc(t: ^testing.T) { expected_doctype = "", }, err = .None, - crc32 = 0x73070b55, + crc32 = 0x738664b1, }) } @@ -298,4 +298,4 @@ doc_to_string :: proc(doc: ^xml.Document) -> (result: string) { print(strings.to_writer(&buf), doc) return strings.clone(strings.to_string(buf)) -} \ No newline at end of file +} diff --git a/tests/core/flags/test_core_flags.odin b/tests/core/flags/test_core_flags.odin index 8fcd6a8a7..f6399461f 100644 --- a/tests/core/flags/test_core_flags.odin +++ b/tests/core/flags/test_core_flags.odin @@ -1,23 +1,23 @@ package test_core_flags -import "base:runtime" -import "core:bytes" -import "core:flags" -import "core:fmt" -@require import "core:log" -import "core:math" -@require import "core:net" -import "core:os" -import "core:strings" -import "core:testing" -import "core:time/datetime" +import "base:runtime" +import "core:bytes" +import "core:flags" +import "core:fmt" +@(require) import "core:log" +import "core:math" +@(require) import "core:net" +import "core:os" +import "core:strings" +import "core:testing" +import "core:time/datetime" Custom_Data :: struct { a: int, } @(init) -init_custom_type_setter :: proc() { +init_custom_type_setter :: proc "contextless" () { // NOTE: This is done here so it can be out of the flow of the // multi-threaded test runner, to prevent any data races that could be // reported by using `-sanitize:thread`. @@ -307,7 +307,7 @@ test_all_bit_sets :: proc(t: ^testing.T) { "-a:10101", "-b:0000_0000_0000_0001", "-c:11", - "-d:___1", + "-d:1", "-e:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "-f:1", "-g:01", @@ -333,6 +333,65 @@ test_all_bit_sets :: proc(t: ^testing.T) { testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) } } + { + // Starting a binary string with underscore is disallowed. + args := [?]string { "-d:_1" } + result := flags.parse(&s, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } + + E2 :: enum { + Option_A=5, + Option_B, + Option_C=3, + Option_D, + } + R :: struct { + a: bit_set[E2], + } + r: R + { + // Least significant bit > 0 + args := [?]string { + "-a:Option_A,Option_D", + } + result := flags.parse(&r, args[:]) + testing.expect_value(t, result, nil) + testing.expect_value(t, r.a, bit_set[E2]{E2.Option_A, E2.Option_D}) + } + { + args := [?]string { "-a:Option_Non_Existent" } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } + { + // Value names list must be strictly comma-separated. + args := [?]string { "-a:Option_A, Option_B" } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } + { + // Value names list must not end with a comma. + args := [?]string { "-a:Option_A,Option_B," } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } } @(test) @@ -454,44 +513,44 @@ test_arrays :: proc(t: ^testing.T) { @(test) test_varargs :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]string, + overflow: [dynamic]string, } s: S args := [?]string { "abc", "foo", "bar" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) - if len(s.varg) < 3 { + if len(s.overflow) < 3 { return } - testing.expect_value(t, s.varg[0], "abc") - testing.expect_value(t, s.varg[1], "foo") - testing.expect_value(t, s.varg[2], "bar") + testing.expect_value(t, s.overflow[0], "abc") + testing.expect_value(t, s.overflow[1], "foo") + testing.expect_value(t, s.overflow[2], "bar") } @(test) test_mixed_varargs :: proc(t: ^testing.T) { S :: struct { input: string `args:"pos=0"`, - varg: [dynamic]string, + overflow: [dynamic]string, } s: S args := [?]string { "abc", "foo", "bar" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 2) + testing.expect_value(t, len(s.overflow), 2) - if len(s.varg) < 2 { + if len(s.overflow) < 2 { return } testing.expect_value(t, s.input, "abc") - testing.expect_value(t, s.varg[0], "foo") - testing.expect_value(t, s.varg[1], "bar") + testing.expect_value(t, s.overflow[0], "foo") + testing.expect_value(t, s.overflow[1], "bar") } @(test) @@ -718,23 +777,23 @@ test_tags_required_limit_max :: proc(t: ^testing.T) { test_tags_pos_out_of_order :: proc(t: ^testing.T) { S :: struct { a: int `args:"pos=2"`, - varg: [dynamic]int, + overflow: [dynamic]int, } s: S args := [?]string { "1", "2", "3", "4" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) - if len(s.varg) < 3 { + if len(s.overflow) < 3 { return } testing.expect_value(t, s.a, 3) - testing.expect_value(t, s.varg[0], 1) - testing.expect_value(t, s.varg[1], 2) - testing.expect_value(t, s.varg[2], 4) + testing.expect_value(t, s.overflow[0], 1) + testing.expect_value(t, s.overflow[1], 2) + testing.expect_value(t, s.overflow[2], 4) } @(test) @@ -899,7 +958,7 @@ test_pos_nonoverlap :: proc(t: ^testing.T) { @(test) test_pos_many_args :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]int, + overflow: [dynamic]int, a: int `args:"pos=0,required"`, b: int `args:"pos=64,required"`, c: int `args:"pos=66,required"`, @@ -908,7 +967,7 @@ test_pos_many_args :: proc(t: ^testing.T) { s: S args: [dynamic]string - defer delete(s.varg) + defer delete(s.overflow) for i in 0 ..< 130 { append(&args, fmt.aprintf("%i", 1 + i)) } defer { @@ -922,14 +981,14 @@ test_pos_many_args :: proc(t: ^testing.T) { testing.expect_value(t, result, nil) testing.expect_value(t, s.a, 1) - for i in 1 ..< 63 { testing.expect_value(t, s.varg[i], 2 + i) } + for i in 1 ..< 63 { testing.expect_value(t, s.overflow[i], 2 + i) } testing.expect_value(t, s.b, 65) - testing.expect_value(t, s.varg[63], 66) + testing.expect_value(t, s.overflow[63], 66) testing.expect_value(t, s.c, 67) - testing.expect_value(t, s.varg[64], 68) - testing.expect_value(t, s.varg[65], 69) - testing.expect_value(t, s.varg[66], 70) - for i in 67 ..< 126 { testing.expect_value(t, s.varg[i], 4 + i) } + testing.expect_value(t, s.overflow[64], 68) + testing.expect_value(t, s.overflow[65], 69) + testing.expect_value(t, s.overflow[66], 70) + for i in 67 ..< 126 { testing.expect_value(t, s.overflow[i], 4 + i) } testing.expect_value(t, s.d, 130) } @@ -966,9 +1025,9 @@ test_unix :: proc(t: ^testing.T) { } @(test) -test_unix_variadic :: proc(t: ^testing.T) { +test_unix_manifold :: proc(t: ^testing.T) { S :: struct { - a: [dynamic]int `args:"variadic"`, + a: [dynamic]int `args:"manifold"`, } s: S @@ -989,9 +1048,9 @@ test_unix_variadic :: proc(t: ^testing.T) { } @(test) -test_unix_variadic_limited :: proc(t: ^testing.T) { +test_unix_manifold_limited :: proc(t: ^testing.T) { S :: struct { - a: [dynamic]int `args:"variadic=2"`, + a: [dynamic]int `args:"manifold=2"`, b: int, } s: S @@ -1012,6 +1071,110 @@ test_unix_variadic_limited :: proc(t: ^testing.T) { testing.expect_value(t, s.b, 3) } +@(test) +test_unix_two_manifold_limited :: proc(t: ^testing.T) { + S :: struct { + a: [dynamic]int `args:"manifold=2"`, + b: [dynamic]int `args:"manifold=2"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + testing.expect_value(t, result, nil) + testing.expect_value(t, len(s.a), 2) + testing.expect_value(t, len(s.b), 2) + + if len(s.a) < 2 || len(s.b) < 2 { + return + } + + testing.expect_value(t, s.a[0], 11) + testing.expect_value(t, s.a[1], 101) + testing.expect_value(t, s.b[0], 3) + testing.expect_value(t, s.b[1], 7) + testing.expect_value(t, s.c, 9) +} + +@(test) +test_unix_two_manifold_string :: proc(t: ^testing.T) { + // The expected behavior of a manifold flag is to consume all arguments as + // fitting for the element type. + S :: struct { + a: [dynamic]string `args:"manifold"`, + b: [dynamic]string `args:"manifold"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + + testing.expect_value(t, result, nil) + testing.expect_value(t, len(s.a), 7) + testing.expect_value(t, len(s.b), 0) + + if len(s.a) != 7 { + return + } + + testing.expect_value(t, s.a[0], "11") + testing.expect_value(t, s.a[1], "101") + testing.expect_value(t, s.a[2], "-b") + testing.expect_value(t, s.a[3], "3") + testing.expect_value(t, s.a[4], "7") + testing.expect_value(t, s.a[5], "-c") + testing.expect_value(t, s.a[6], "9") +} + +@(test) +test_unix_two_manifold_int :: proc(t: ^testing.T) { + // If a manifold flag encounters an argument that it cannot convert to the + // element type, then this is an error. + S :: struct { + a: [dynamic]int `args:"manifold"`, + b: [dynamic]int `args:"manifold"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + + // It is expected that arguments which pass will still be available. + testing.expect_value(t, len(s.a), 2) + testing.expect_value(t, len(s.b), 0) + + if len(s.a) != 2 { + return + } + + testing.expect_value(t, s.a[0], 11) + testing.expect_value(t, s.a[1], 101) +} + @(test) test_unix_positional :: proc(t: ^testing.T) { S :: struct { @@ -1029,10 +1192,10 @@ test_unix_positional :: proc(t: ^testing.T) { } @(test) -test_unix_positional_with_variadic :: proc(t: ^testing.T) { +test_unix_positional_with_manifold :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]int, - v: [dynamic]int `args:"variadic"`, + overflow: [dynamic]int, + v: [dynamic]int `args:"manifold"`, } s: S @@ -1040,18 +1203,18 @@ test_unix_positional_with_variadic :: proc(t: ^testing.T) { result := flags.parse(&s, args[:], .Unix) defer { - delete(s.varg) + delete(s.overflow) delete(s.v) } testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 1) + testing.expect_value(t, len(s.overflow), 1) testing.expect_value(t, len(s.v), 2) } @(test) -test_unix_double_dash_variadic :: proc(t: ^testing.T) { +test_unix_double_dash_varargs :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]string, + overflow: [dynamic]string, i: int, } s: S @@ -1060,19 +1223,19 @@ test_unix_double_dash_variadic :: proc(t: ^testing.T) { result := flags.parse(&s, args[:], .Unix) defer { - delete(s.varg) + delete(s.overflow) } testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) testing.expect_value(t, s.i, 3) - if len(s.varg) != 3 { + if len(s.overflow) != 3 { return } - testing.expect_value(t, s.varg[0], "hellope") - testing.expect_value(t, s.varg[1], "-i") - testing.expect_value(t, s.varg[2], "5") + testing.expect_value(t, s.overflow[0], "hellope") + testing.expect_value(t, s.overflow[1], "-i") + testing.expect_value(t, s.overflow[2], "5") } @(test) @@ -1096,17 +1259,17 @@ test_unix_no_value :: proc(t: ^testing.T) { @(test) test_if_dynamic_cstrings_get_freed :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]cstring, + overflow: [dynamic]cstring, } s: S args := [?]string { "Hellope", "world!" } result := flags.parse(&s, args[:]) defer { - for v in s.varg { + for v in s.overflow { delete(v) } - delete(s.varg) + delete(s.overflow) } testing.expect_value(t, result, nil) } @@ -1145,7 +1308,7 @@ test_os_handle :: proc(t: ^testing.T) { test_data := "Hellope!" W :: struct { - outf: os.Handle `args:"file=cw"`, + outf: ^os.File `args:"file=cw"`, } w: W @@ -1159,7 +1322,7 @@ test_os_handle :: proc(t: ^testing.T) { os.write_string(w.outf, test_data) R :: struct { - inf: os.Handle `args:"file=r"`, + inf: ^os.File `args:"file=r"`, } r: R @@ -1170,8 +1333,8 @@ test_os_handle :: proc(t: ^testing.T) { return } defer os.close(r.inf) - data, read_ok := os.read_entire_file_from_handle(r.inf, context.temp_allocator) - testing.expect_value(t, read_ok, true) + data, read_err := os.read_entire_file(r.inf, context.temp_allocator) + testing.expect_value(t, read_err, nil) file_contents_equal := 0 == bytes.compare(transmute([]u8)test_data, data) testing.expectf(t, file_contents_equal, "expected file contents to be the same, got %v", data) } @@ -1184,13 +1347,11 @@ test_distinct_types :: proc(t: ^testing.T) { unmodified_i: I, } s: S - { args := [?]string {"-base-i:1"} result := flags.parse(&s, args[:]) testing.expect_value(t, result, nil) } - { args := [?]string {"-unmodified-i:1"} result := flags.parse(&s, args[:]) @@ -1324,7 +1485,7 @@ very nicely. debug: bool `args:"hidden" usage:"print debug info"`, verbose: bool, - varg: [dynamic]string, + overflow: [dynamic]string, } builder := strings.builder_make() @@ -1337,7 +1498,7 @@ very nicely. @(test) test_usage_write_unix :: proc(t: ^testing.T) { Expected_Output :: `Usage: - varg required-number [number] [name] --bars --bots --foos --gadgets --variadic-flag --widgets [--array] [--count] [--greek] [--verbose] ... + overflow required-number [number] [name] --bars --bots --foos --gadgets --manifold-flag --widgets [--array] [--count] [--greek] [--verbose] ... Flags: --required-number , required | some number --number | some other number @@ -1349,7 +1510,7 @@ Flags: --bots , at least 1 | --foos , between 2 and 3 | --gadgets , at least 1 | - --variadic-flag , at least 2 | + --manifold-flag , at least 2 | --widgets , at most 2 | | --array , multiple | @@ -1378,7 +1539,7 @@ very nicely. greek: Custom_Enum, array: [dynamic]rune, - variadic_flag: [dynamic]int `args:"variadic,required=2"`, + manifold_flag: [dynamic]int `args:"manifold,required=2"`, gadgets: [dynamic]string `args:"required=1"`, widgets: [dynamic]string `args:"required=<3"`, @@ -1389,12 +1550,12 @@ very nicely. debug: bool `args:"hidden" usage:"print debug info"`, verbose: bool, - varg: [dynamic]string, + overflow: [dynamic]string, } builder := strings.builder_make() defer strings.builder_destroy(&builder) writer := strings.to_stream(&builder) - flags.write_usage(writer, S, "varg", .Unix) + flags.write_usage(writer, S, "overflow", .Unix) testing.expect_value(t, strings.to_string(builder), Expected_Output) } diff --git a/tests/core/hash/test_core_hash.odin b/tests/core/hash/test_core_hash.odin index adb55d2d8..30ee911a8 100644 --- a/tests/core/hash/test_core_hash.odin +++ b/tests/core/hash/test_core_hash.odin @@ -1,140 +1,187 @@ #+feature dynamic-literals package test_core_hash -import "core:hash/xxhash" import "core:hash" import "core:testing" -import "core:math/rand" import "base:intrinsics" +/* + Built-in `#hash`es: + #hash("murmur32"), + #hash("murmur64"), + }; +*/ + +V16 :: struct{s: string, h: u16} +V32 :: struct{s: string, h: u32} +V64 :: struct{s: string, h: u64} + @test -test_xxhash_zero_fixed :: proc(t: ^testing.T) { - many_zeroes := make([]u8, 16 * 1024 * 1024) - defer delete(many_zeroes) - - // All at once. - for i, v in ZERO_VECTORS { - b := many_zeroes[:i] - - xxh32 := xxhash.XXH32(b) - xxh64 := xxhash.XXH64(b) - xxh3_64 := xxhash.XXH3_64(b) - xxh3_128 := xxhash.XXH3_128(b) - - testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) - testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) - testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) - testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) +test_adler32_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 0x00000001}, + {"a" , 0x00620062}, + {"abc" , 0x024d0127}, + {"Hello" , 0x058c01f5}, + {"world" , 0x06a60229}, + {"Hello, world!", 0x205e048a}, } + + for vector in vectors { + b := transmute([]u8)vector.s + adler := hash.adler32(b) + testing.expectf(t, adler == vector.h, "\n\t[ADLER-32(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, adler) + } + + testing.expect_value(t, #hash(vectors[0].s, "adler32"), int(vectors[0].h)) + testing.expect_value(t, #hash(vectors[1].s, "adler32"), int(vectors[1].h)) + testing.expect_value(t, #hash(vectors[2].s, "adler32"), int(vectors[2].h)) + testing.expect_value(t, #hash(vectors[3].s, "adler32"), int(vectors[3].h)) + testing.expect_value(t, #hash(vectors[4].s, "adler32"), int(vectors[4].h)) + testing.expect_value(t, #hash(vectors[5].s, "adler32"), int(vectors[5].h)) } -@(test) -test_xxhash_zero_streamed_random_updates :: proc(t: ^testing.T) { - many_zeroes := make([]u8, 16 * 1024 * 1024) - defer delete(many_zeroes) +@test +test_djb2_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 5381}, // Initial seed + {"a" , 0x0002b606}, + {"abc" , 0x0b885c8b}, + {"Hello" , 0x0d4f2079}, + {"world" , 0x10a7356d}, + {"Hello, world!", 0xe18796ae}, + } - // Streamed - for i, v in ZERO_VECTORS { - b := many_zeroes[:i] - - xxh_32_state, xxh_32_err := xxhash.XXH32_create_state() - defer xxhash.XXH32_destroy_state(xxh_32_state) - testing.expect(t, xxh_32_err == nil, "Problem initializing XXH_32 state") - - xxh_64_state, xxh_64_err := xxhash.XXH64_create_state() - defer xxhash.XXH64_destroy_state(xxh_64_state) - testing.expect(t, xxh_64_err == nil, "Problem initializing XXH_64 state") - - xxh3_64_state, xxh3_64_err := xxhash.XXH3_create_state() - defer xxhash.XXH3_destroy_state(xxh3_64_state) - testing.expect(t, xxh3_64_err == nil, "Problem initializing XXH3_64 state") - - xxh3_128_state, xxh3_128_err := xxhash.XXH3_create_state() - defer xxhash.XXH3_destroy_state(xxh3_128_state) - testing.expect(t, xxh3_128_err == nil, "Problem initializing XXH3_128 state") - - // XXH3_128_update - rand.reset(t.seed) - for len(b) > 0 { - update_size := min(len(b), rand.int_max(8192)) - if update_size > 4096 { - update_size %= 73 - } - xxhash.XXH32_update (xxh_32_state, b[:update_size]) - xxhash.XXH64_update (xxh_64_state, b[:update_size]) - - xxhash.XXH3_64_update (xxh3_64_state, b[:update_size]) - xxhash.XXH3_128_update(xxh3_128_state, b[:update_size]) - - b = b[update_size:] - } - - // Now finalize - xxh32 := xxhash.XXH32_digest(xxh_32_state) - xxh64 := xxhash.XXH64_digest(xxh_64_state) - - xxh3_64 := xxhash.XXH3_64_digest(xxh3_64_state) - xxh3_128 := xxhash.XXH3_128_digest(xxh3_128_state) - - testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) - testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) - testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) - testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) + for vector in vectors { + b := transmute([]u8)vector.s + djb2 := hash.djb2(b) + testing.expectf(t, djb2 == vector.h, "\n\t[DJB-2(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, djb2) } } @test -test_xxhash_seeded :: proc(t: ^testing.T) { - buf := make([]u8, 256) - defer delete(buf) - - for seed, table in XXHASH_TEST_VECTOR_SEEDED { - for v, i in table { - b := buf[:i] - - xxh32 := xxhash.XXH32(b, u32(seed)) - xxh64 := xxhash.XXH64(b, seed) - xxh3_64 := xxhash.XXH3_64(b, seed) - xxh3_128 := xxhash.XXH3_128(b, seed) - - testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) - testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) - testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) - testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) - - if len(b) > xxhash.XXH3_MIDSIZE_MAX { - xxh3_state, _ := xxhash.XXH3_create_state() - xxhash.XXH3_64_reset_with_seed(xxh3_state, seed) - xxhash.XXH3_64_update(xxh3_state, b) - xxh3_64_streamed := xxhash.XXH3_64_digest(xxh3_state) - xxhash.XXH3_destroy_state(xxh3_state) - testing.expectf(t, xxh3_64_streamed == v.xxh3_64, "[XXH3_64s(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64_streamed) - - xxh3_state2, _ := xxhash.XXH3_create_state() - xxhash.XXH3_128_reset_with_seed(xxh3_state2, seed) - xxhash.XXH3_128_update(xxh3_state2, b) - xxh3_128_streamed := xxhash.XXH3_128_digest(xxh3_state2) - xxhash.XXH3_destroy_state(xxh3_state2) - testing.expectf(t, xxh3_128_streamed == v.xxh3_128, "[XXH3_128s(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128_streamed) - } - } +test_fnv32_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 0x811c9dc5}, + {"a" , 0x050c5d7e}, + {"abc" , 0x439c2f4b}, + {"Hello" , 0x3726bd47}, + {"world" , 0x9b8e862f}, + {"Hello, world!", 0xe84ead66}, } + + for vector in vectors { + b := transmute([]u8)vector.s + fnv := hash.fnv32_no_a(b) + testing.expectf(t, fnv == vector.h, "\n\t[FNV-32(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, fnv) + } + + testing.expect_value(t, #hash(vectors[0].s, "fnv32"), int(vectors[0].h)) + testing.expect_value(t, #hash(vectors[1].s, "fnv32"), int(vectors[1].h)) + testing.expect_value(t, #hash(vectors[2].s, "fnv32"), int(vectors[2].h)) + testing.expect_value(t, #hash(vectors[3].s, "fnv32"), int(vectors[3].h)) + testing.expect_value(t, #hash(vectors[4].s, "fnv32"), int(vectors[4].h)) + testing.expect_value(t, #hash(vectors[5].s, "fnv32"), int(vectors[5].h)) } @test -test_xxhash_secret :: proc(t: ^testing.T) { - buf := make([]u8, 256) - defer delete(buf) - - for secret, table in XXHASH_TEST_VECTOR_SECRET { - secret_bytes := transmute([]u8)secret - for v, i in table { - b := buf[:i] - - xxh3_128 := xxhash.XXH3_128(b, secret_bytes) - testing.expectf(t, xxh3_128 == v.xxh3_128_secret, "[XXH3_128(%03d)] Expected: %32x, got: %32x", i, v.xxh3_128_secret, xxh3_128) - } +test_fnv64_vectors :: proc(t: ^testing.T) { + vectors :: []V64{ + {"" , 0xcbf29ce484222325}, + {"a" , 0xaf63bd4c8601b7be}, + {"abc" , 0xd8dcca186bafadcb}, + {"Hello" , 0xfa365282a44c0ba7}, + {"world" , 0x3ec0cf0cc4a6540f}, + {"Hello, world!", 0x6519bd6389aaa166}, } + + for vector in vectors { + b := transmute([]u8)vector.s + fnv := hash.fnv64_no_a(b) + testing.expectf(t, fnv == vector.h, "\n\t[FNV-64(%v)] Expected: 0x%16x, got: 0x%16x", vector.s, vector.h, fnv) + } + + testing.expect_value(t, i128(#hash(vectors[0].s, "fnv64")), i128(vectors[0].h)) + testing.expect_value(t, i128(#hash(vectors[1].s, "fnv64")), i128(vectors[1].h)) + testing.expect_value(t, i128(#hash(vectors[2].s, "fnv64")), i128(vectors[2].h)) + testing.expect_value(t, i128(#hash(vectors[3].s, "fnv64")), i128(vectors[3].h)) + testing.expect_value(t, i128(#hash(vectors[4].s, "fnv64")), i128(vectors[4].h)) + testing.expect_value(t, i128(#hash(vectors[5].s, "fnv64")), i128(vectors[5].h)) +} + +@test +test_fnv32a_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 0x811c9dc5}, + {"a" , 0xe40c292c}, + {"abc" , 0x1a47e90b}, + {"Hello" , 0xf55c314b}, + {"world" , 0x37a3e893}, + {"Hello, world!", 0xed90f094}, + } + + for vector in vectors { + b := transmute([]u8)vector.s + fnv := hash.fnv32a(b) + testing.expectf(t, fnv == vector.h, "\n\t[FNV-32a(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, fnv) + } + + testing.expect_value(t, #hash(vectors[0].s, "fnv32a"), int(vectors[0].h)) + testing.expect_value(t, #hash(vectors[1].s, "fnv32a"), int(vectors[1].h)) + testing.expect_value(t, #hash(vectors[2].s, "fnv32a"), int(vectors[2].h)) + testing.expect_value(t, #hash(vectors[3].s, "fnv32a"), int(vectors[3].h)) + testing.expect_value(t, #hash(vectors[4].s, "fnv32a"), int(vectors[4].h)) + testing.expect_value(t, #hash(vectors[5].s, "fnv32a"), int(vectors[5].h)) +} + +@test +test_fnv64a_vectors :: proc(t: ^testing.T) { + vectors :: []V64{ + {"" , 0xcbf29ce484222325}, + {"a" , 0xaf63dc4c8601ec8c}, + {"abc" , 0xe71fa2190541574b}, + {"Hello" , 0x63f0bfacf2c00f6b}, + {"world" , 0x4f59ff5e730c8af3}, + {"Hello, world!", 0x38d1334144987bf4}, + } + + for vector in vectors { + b := transmute([]u8)vector.s + fnv := hash.fnv64a(b) + testing.expectf(t, fnv == vector.h, "\n\t[FNV-64a(%v)] Expected: 0x%16x, got: 0x%16x", vector.s, vector.h, fnv) + } + + testing.expect_value(t, i128(#hash(vectors[0].s, "fnv64a")), i128(vectors[0].h)) + testing.expect_value(t, i128(#hash(vectors[1].s, "fnv64a")), i128(vectors[1].h)) + testing.expect_value(t, i128(#hash(vectors[2].s, "fnv64a")), i128(vectors[2].h)) + testing.expect_value(t, i128(#hash(vectors[3].s, "fnv64a")), i128(vectors[3].h)) + testing.expect_value(t, i128(#hash(vectors[4].s, "fnv64a")), i128(vectors[4].h)) + testing.expect_value(t, i128(#hash(vectors[5].s, "fnv64a")), i128(vectors[5].h)) +} + +@test +test_crc32_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 0x00000000}, + {"a" , 0xe8b7be43}, + {"abc" , 0x352441c2}, + {"Hello" , 0xf7d18982}, + {"world" , 0x3a771143}, + {"Hello, world!", 0xebe6c6e6}, + } + + for vector in vectors { + b := transmute([]u8)vector.s + crc := hash.crc32(b) + testing.expectf(t, crc == vector.h, "\n\t[CRC-32(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, crc) + } + + testing.expect_value(t, #hash(vectors[0].s, "crc32"), int(vectors[0].h)) + testing.expect_value(t, #hash(vectors[1].s, "crc32"), int(vectors[1].h)) + testing.expect_value(t, #hash(vectors[2].s, "crc32"), int(vectors[2].h)) + testing.expect_value(t, #hash(vectors[3].s, "crc32"), int(vectors[3].h)) + testing.expect_value(t, #hash(vectors[4].s, "crc32"), int(vectors[4].h)) + testing.expect_value(t, #hash(vectors[5].s, "crc32"), int(vectors[5].h)) } @test @@ -167,4 +214,72 @@ test_crc64_vectors :: proc(t: ^testing.T) { testing.expectf(t, iso == expected[2], "[ CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[2], iso) testing.expectf(t, iso2 == expected[3], "[~CRC-64 ISO 3306] Expected: %016x, got: %016x", expected[3], iso2) } +} + +@test +test_murmur32_vectors :: proc(t: ^testing.T) { + vectors :: []V32{ + {"" , 0xebb6c228}, + {"a" , 0x7fa09ea6}, + {"abc" , 0xc84a62dd}, + {"Hello" , 0xec73fdbe}, + {"world" , 0xd7f8a5f2}, + {"Hello, world!", 0x24884cba}, + } + + for vector in vectors { + b := transmute([]u8)vector.s + murmur := hash.murmur32(b) + testing.expectf(t, murmur == vector.h, "\n\t[MURMUR-32(%v)] Expected: 0x%08x, got: 0x%08x", vector.s, vector.h, murmur) + } + + testing.expect_value(t, #hash(vectors[0].s, "murmur32"), int(vectors[0].h)) + testing.expect_value(t, #hash(vectors[1].s, "murmur32"), int(vectors[1].h)) + testing.expect_value(t, #hash(vectors[2].s, "murmur32"), int(vectors[2].h)) + testing.expect_value(t, #hash(vectors[3].s, "murmur32"), int(vectors[3].h)) + testing.expect_value(t, #hash(vectors[4].s, "murmur32"), int(vectors[4].h)) + testing.expect_value(t, #hash(vectors[5].s, "murmur32"), int(vectors[5].h)) +} + +@test +test_murmur64_vectors :: proc(t: ^testing.T) { + vectors :: []V64{ + {"" , 0x8397626cd6895052}, + {"a" , 0xe96b6245652273ae}, + {"abc" , 0xa9316c8740c81414}, + {"Hello" , 0x89cc3a85a7045a4f}, + {"world" , 0xf030e222b1f740f6}, + {"Hello, world!", 0x710583fa7f802a84}, + } + + for vector in vectors { + b := transmute([]u8)vector.s + murmur := hash.murmur64a(b) + testing.expectf(t, murmur == vector.h, "\n\t[MURMUR-64(%v)] Expected: 0x%16x, got: 0x%16x", vector.s, vector.h, murmur) + } + + testing.expect_value(t, i128(#hash(vectors[0].s, "murmur64")), i128(vectors[0].h)) + testing.expect_value(t, i128(#hash(vectors[1].s, "murmur64")), i128(vectors[1].h)) + testing.expect_value(t, i128(#hash(vectors[2].s, "murmur64")), i128(vectors[2].h)) + testing.expect_value(t, i128(#hash(vectors[3].s, "murmur64")), i128(vectors[3].h)) + testing.expect_value(t, i128(#hash(vectors[4].s, "murmur64")), i128(vectors[4].h)) + testing.expect_value(t, i128(#hash(vectors[5].s, "murmur64")), i128(vectors[5].h)) +} + +@test +test_crc16_ccitt_0x1021_vectors :: proc(t: ^testing.T) { + vectors :: []V16{ + {"" , 0x0000}, + {"abc" , 0x9dd6}, + {"Hello" , 0xcbd6}, + {"world" , 0x2363}, + {"Hello, world!", 0x7ade}, + {"\x70\x6a\x77" , 0x3299}, // ECMA-167, 7.2.6 Descriptor CRC + } + + for vector in vectors { + b := transmute([]u8)vector.s + crc16 := hash.crc16_ccitt_0x1021(b) + testing.expectf(t, crc16 == vector.h, "\n\t[CCITT CRC-16({0:q})] Expected: 0x{1:4x}, got: 0x{2:4x}", vector.s, vector.h, crc16) + } } \ No newline at end of file diff --git a/tests/core/hash/test_vectors_xxhash.odin b/tests/core/hash/test_core_xxhash.odin similarity index 98% rename from tests/core/hash/test_vectors_xxhash.odin rename to tests/core/hash/test_core_xxhash.odin index 04e2d4f1f..f544f6699 100644 --- a/tests/core/hash/test_vectors_xxhash.odin +++ b/tests/core/hash/test_core_xxhash.odin @@ -2,6 +2,140 @@ #+feature dynamic-literals package test_core_hash +import "core:hash/xxhash" +import "core:testing" +import "core:math/rand" + +@test +test_xxhash_zero_fixed :: proc(t: ^testing.T) { + many_zeroes := make([]u8, 16 * 1024 * 1024) + defer delete(many_zeroes) + + // All at once. + for i, v in ZERO_VECTORS { + b := many_zeroes[:i] + + xxh32 := xxhash.XXH32(b) + xxh64 := xxhash.XXH64(b) + xxh3_64 := xxhash.XXH3_64(b) + xxh3_128 := xxhash.XXH3_128(b) + + testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) + testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) + testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) + testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) + } +} + +@(test) +test_xxhash_zero_streamed_random_updates :: proc(t: ^testing.T) { + many_zeroes := make([]u8, 16 * 1024 * 1024) + defer delete(many_zeroes) + + // Streamed + for i, v in ZERO_VECTORS { + b := many_zeroes[:i] + + xxh_32_state, xxh_32_err := xxhash.XXH32_create_state() + defer xxhash.XXH32_destroy_state(xxh_32_state) + testing.expect(t, xxh_32_err == nil, "Problem initializing XXH_32 state") + + xxh_64_state, xxh_64_err := xxhash.XXH64_create_state() + defer xxhash.XXH64_destroy_state(xxh_64_state) + testing.expect(t, xxh_64_err == nil, "Problem initializing XXH_64 state") + + xxh3_64_state, xxh3_64_err := xxhash.XXH3_create_state() + defer xxhash.XXH3_destroy_state(xxh3_64_state) + testing.expect(t, xxh3_64_err == nil, "Problem initializing XXH3_64 state") + + xxh3_128_state, xxh3_128_err := xxhash.XXH3_create_state() + defer xxhash.XXH3_destroy_state(xxh3_128_state) + testing.expect(t, xxh3_128_err == nil, "Problem initializing XXH3_128 state") + + // XXH3_128_update + rand.reset(t.seed) + for len(b) > 0 { + update_size := min(len(b), rand.int_max(8192)) + if update_size > 4096 { + update_size %= 73 + } + xxhash.XXH32_update (xxh_32_state, b[:update_size]) + xxhash.XXH64_update (xxh_64_state, b[:update_size]) + + xxhash.XXH3_64_update (xxh3_64_state, b[:update_size]) + xxhash.XXH3_128_update(xxh3_128_state, b[:update_size]) + + b = b[update_size:] + } + + // Now finalize + xxh32 := xxhash.XXH32_digest(xxh_32_state) + xxh64 := xxhash.XXH64_digest(xxh_64_state) + + xxh3_64 := xxhash.XXH3_64_digest(xxh3_64_state) + xxh3_128 := xxhash.XXH3_128_digest(xxh3_128_state) + + testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) + testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) + testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) + testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) + } +} + +@test +test_xxhash_seeded :: proc(t: ^testing.T) { + buf := make([]u8, 256) + defer delete(buf) + + for seed, table in XXHASH_TEST_VECTOR_SEEDED { + for v, i in table { + b := buf[:i] + + xxh32 := xxhash.XXH32(b, u32(seed)) + xxh64 := xxhash.XXH64(b, seed) + xxh3_64 := xxhash.XXH3_64(b, seed) + xxh3_128 := xxhash.XXH3_128(b, seed) + + testing.expectf(t, xxh32 == v.xxh_32, "[ XXH32(%03d) ] Expected: %08x, got: %08x", i, v.xxh_32, xxh32) + testing.expectf(t, xxh64 == v.xxh_64, "[ XXH64(%03d) ] Expected: %16x, got: %16x", i, v.xxh_64, xxh64) + testing.expectf(t, xxh3_64 == v.xxh3_64, "[XXH3_64(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64) + testing.expectf(t, xxh3_128 == v.xxh3_128, "[XXH3_128(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128) + + if len(b) > xxhash.XXH3_MIDSIZE_MAX { + xxh3_state, _ := xxhash.XXH3_create_state() + xxhash.XXH3_64_reset_with_seed(xxh3_state, seed) + xxhash.XXH3_64_update(xxh3_state, b) + xxh3_64_streamed := xxhash.XXH3_64_digest(xxh3_state) + xxhash.XXH3_destroy_state(xxh3_state) + testing.expectf(t, xxh3_64_streamed == v.xxh3_64, "[XXH3_64s(%03d) ] Expected: %16x, got: %16x", i, v.xxh3_64, xxh3_64_streamed) + + xxh3_state2, _ := xxhash.XXH3_create_state() + xxhash.XXH3_128_reset_with_seed(xxh3_state2, seed) + xxhash.XXH3_128_update(xxh3_state2, b) + xxh3_128_streamed := xxhash.XXH3_128_digest(xxh3_state2) + xxhash.XXH3_destroy_state(xxh3_state2) + testing.expectf(t, xxh3_128_streamed == v.xxh3_128, "[XXH3_128s(%03d) ] Expected: %32x, got: %32x", i, v.xxh3_128, xxh3_128_streamed) + } + } + } +} + +@test +test_xxhash_secret :: proc(t: ^testing.T) { + buf := make([]u8, 256) + defer delete(buf) + + for secret, table in XXHASH_TEST_VECTOR_SECRET { + secret_bytes := transmute([]u8)secret + for v, i in table { + b := buf[:i] + + xxh3_128 := xxhash.XXH3_128(b, secret_bytes) + testing.expectf(t, xxh3_128 == v.xxh3_128_secret, "[XXH3_128(%03d)] Expected: %32x, got: %32x", i, v.xxh3_128_secret, xxh3_128) + } + } +} + XXHASH_Test_Vectors :: struct #packed { /* Old hashes diff --git a/tests/core/image/test_core_image.odin b/tests/core/image/test_core_image.odin index 8f6091481..46790bc8c 100644 --- a/tests/core/image/test_core_image.odin +++ b/tests/core/image/test_core_image.odin @@ -1,11 +1,11 @@ /* Copyright 2021-2024 Jeroen van Rijn . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. - A test suite for PNG, TGA, NetPBM, QOI and BMP. + A test suite for PNG, TGA, NetPBM, QOI, BMP, and JPEG. */ #+feature dynamic-literals package test_core_image @@ -19,6 +19,7 @@ import pbm "core:image/netpbm" import "core:image/png" import "core:image/qoi" import "core:image/tga" +import "core:image/jpeg" import "core:bytes" import "core:hash" @@ -28,6 +29,7 @@ import "core:time" TEST_SUITE_PATH_PNG :: ODIN_ROOT + "tests/core/assets/PNG" TEST_SUITE_PATH_BMP :: ODIN_ROOT + "tests/core/assets/BMP" +TEST_SUITE_PATH_JPG :: ODIN_ROOT + "tests/core/assets/JPG" I_Error :: image.Error @@ -49,6 +51,7 @@ Blend_BG_Keep :: image.Options{.blend_background, .alpha_add_if_missing} Return_Metadata :: image.Options{.return_metadata} No_Channel_Expansion :: image.Options{.do_not_expand_channels, .return_metadata} + Dims :: struct { width: int, height: int, @@ -2360,6 +2363,66 @@ run_bmp_suite :: proc(t: ^testing.T, suite: []Test) { return } +// JPG test image +Basic_JPG_Tests := []Test{ + { + "emblem-1024", { + {Default, nil, {1024, 1024, 3, 8}, 0x_46a29e0f}, + {Alpha_Add, nil, {1024, 1024, 4, 8}, 0x_cae2d532}, + }, + }, + { + "emblem-1024-progressive", { + {Default, .Unsupported_Frame_Type, {1024, 1024, 3, 8}, 0x_46a29e0f}, + }, + }, + { + "emblem-1024-gray", { + {Default, nil, {1024, 1024, 3, 8}, 0x_4115d669}, + {Alpha_Add, nil, {1024, 1024, 4, 8}, 0x_db496297}, + {No_Channel_Expansion, .Unsupported_Option, {1024, 1024, 1, 8}, 0}, + }, + }, +} + +@test +jpeg_test_basic :: proc(t: ^testing.T) { + run_jpg_suite(t, Basic_JPG_Tests) +} + +run_jpg_suite :: proc(t: ^testing.T, suite: []Test) { + for file in suite { + test_file := strings.concatenate({TEST_SUITE_PATH_JPG, "/", file.file, ".jpg"}, context.allocator) + defer delete(test_file) + + for test in file.tests { + img, err := jpeg.load(test_file, test.options) + defer jpeg.destroy(img) + + passed := (test.expected_error == nil && err == nil) || (test.expected_error == err) + testing.expectf(t, passed, "%q failed to load with error %v.", file.file, err) + + // No point in running the other tests if it didn't load. + (err == nil) or_continue + + pixels := bytes.buffer_to_bytes(&img.pixels) + dims := Dims{img.width, img.height, img.channels, img.depth} + testing.expectf(t, test.dims == dims, "%v has %v, expected: %v.", file.file, dims, test.dims) + + img_hash := hash.crc32(pixels) + testing.expectf(t, test.hash == img_hash, "%v test #1's hash is %08x, expected %08x with %v.", file.file, img_hash, test.hash, test.options) + + // Optionally save to QOI file to check file loaded properly during development + when false { + test_qoi := strings.concatenate({TEST_SUITE_PATH_JPG, "/", file.file, ".qoi"}, context.temp_allocator) + save_err := qoi.save(test_qoi, img) + testing.expectf(t, save_err == nil, "expected saving to QOI not to raise error, got %v", save_err) + } + } + } + return +} + @test will_it_blend :: proc(t: ^testing.T) { Pixel :: image.RGB_Pixel diff --git a/tests/core/io/test_core_io.odin b/tests/core/io/test_core_io.odin index 10c9550cb..728771b1b 100644 --- a/tests/core/io/test_core_io.odin +++ b/tests/core/io/test_core_io.odin @@ -5,7 +5,6 @@ import "core:bytes" import "core:io" import "core:log" import "core:os" -import "core:os/os2" import "core:strings" import "core:testing" @@ -552,12 +551,12 @@ test_os_file_stream :: proc(t: ^testing.T) { TEMPORARY_FILENAME :: "test_core_io_os_file_stream" - fd, open_err := os.open(TEMPORARY_FILENAME, os.O_RDWR | os.O_CREATE | os.O_TRUNC, 0o644) + fd, open_err := os.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc}) if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) { return } - - stream := os.stream_from_handle(fd) + + stream := os.to_stream(fd) bytes_written, write_err := io.write(stream, buf[:]) if !testing.expectf(t, bytes_written == len(buf) && write_err == nil, @@ -571,44 +570,7 @@ test_os_file_stream :: proc(t: ^testing.T) { return } - results, _ := _test_stream(t, stream, buf[:]) - - log.debugf("%#v", results) -} - -@test -test_os2_file_stream :: proc(t: ^testing.T) { - defer if !testing.failed(t) { - testing.expect_value(t, os2.remove(TEMPORARY_FILENAME), nil) - } - - buf: [32]u8 - for i in 0.. != len_buf<%v>, %v", bytes_written, len(buf), write_err) { - return - } - - flush_err := io.flush(stream) - if !testing.expectf(t, flush_err == nil, - "failed to Flush initial buffer: %v", write_err) { - return - } - - // os2 file stream proc close and destroy are the same. + // os file stream proc close and destroy are the same. results, _ := _test_stream(t, stream, buf[:], do_destroy = false) log.debugf("%#v", results) @@ -676,10 +638,10 @@ test_bufio_buffered_reader :: proc(t: ^testing.T) { @test test_bufio_buffered_read_writer :: proc(t: ^testing.T) { - // Using an os2.File as the backing stream for both reader & writer. + // Using an os.File as the backing stream for both reader & writer. defer if !testing.failed(t) { - testing.expect_value(t, os2.remove(TEMPORARY_FILENAME), nil) + testing.expect_value(t, os.remove(TEMPORARY_FILENAME), nil) } buf: [32]u8 @@ -687,15 +649,15 @@ test_bufio_buffered_read_writer :: proc(t: ^testing.T) { buf[i] = 'A' + i } - TEMPORARY_FILENAME :: "test_core_io_bufio_read_writer_os2_file_stream" + TEMPORARY_FILENAME :: "test_core_io_bufio_read_writer_os_file_stream" - fd, open_err := os2.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc}) + fd, open_err := os.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc}) if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) { return } - defer testing.expect_value(t, os2.close(fd), nil) + defer testing.expect_value(t, os.close(fd), nil) - stream := os2.to_stream(fd) + stream := os.to_stream(fd) bytes_written, write_err := io.write(stream, buf[:]) if !testing.expectf(t, bytes_written == len(buf) && write_err == nil, @@ -709,7 +671,7 @@ test_bufio_buffered_read_writer :: proc(t: ^testing.T) { return } - // bufio.Read_Writer isn't capable of seeking, so we have to reset the os2 + // bufio.Read_Writer isn't capable of seeking, so we have to reset the os // stream back to the start here. pos, seek_err := io.seek(stream, 0, .Start) if !testing.expectf(t, pos == 0 && seek_err == nil, diff --git a/tests/core/math/big/build.bat b/tests/core/math/big/build.bat deleted file mode 100644 index ad199d775..000000000 --- a/tests/core/math/big/build.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -rem math/big tests -set PATH_TO_ODIN==..\..\..\..\odin -set TEST_ARGS=-fast-tests -set TEST_ARGS=-no-random -set TEST_ARGS= -set OUT_NAME=math_big_test_library.dll -set COMMON=-build-mode:shared -show-timings -no-bounds-check -define:MATH_BIG_EXE=false -vet -strict-style -echo --- -echo Running core:math/big tests -echo --- - -%PATH_TO_ODIN% build . %COMMON% -o:speed -out:%OUT_NAME% -python3 test.py %TEST_ARGS% \ No newline at end of file diff --git a/tests/core/math/big/test.py b/tests/core/math/big/generate_tests.py similarity index 75% rename from tests/core/math/big/test.py rename to tests/core/math/big/generate_tests.py index c0e695848..4e4d7e53d 100644 --- a/tests/core/math/big/test.py +++ b/tests/core/math/big/generate_tests.py @@ -1,776 +1,650 @@ -# -# Copyright 2021 Jeroen van Rijn . -# Made available under Odin's BSD-3 license. -# -# A BigInt implementation in Odin. -# For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. -# The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. -# - -from ctypes import * -from random import * -import math -import os -import platform -import time -import gc -from enum import Enum -import argparse - -parser = argparse.ArgumentParser( - description = "Odin core:math/big test suite", - epilog = "By default we run regression and random tests with preset parameters.", - formatter_class = argparse.ArgumentDefaultsHelpFormatter, -) - -# -# Normally, we report the number of passes and fails. With this option set, we exit at first fail. -# -parser.add_argument( - "-exit-on-fail", - help = "Exit when a test fails", - action = "store_true", -) - -# -# We skip randomized tests altogether if this is set. -# -no_random = parser.add_mutually_exclusive_group() - -no_random.add_argument( - "-no-random", - help = "No random tests", - action = "store_true", -) - -# -# Normally we run a given number of cycles on each test. -# Timed tests budget 1 second per 20_000 bits instead. -# -# For timed tests we budget a second per `n` bits and iterate until we hit that time. -# -timed_or_fast = no_random.add_mutually_exclusive_group() - -timed_or_fast.add_argument( - "-timed", - type = bool, - default = False, - help = "Timed tests instead of a preset number of iterations.", -) -parser.add_argument( - "-timed-bits", - type = int, - metavar = "BITS", - default = 20_000, - help = "Timed tests. Every `BITS` worth of input is given a second of running time.", -) - -# -# For normal tests (non-timed), `-fast-tests` cuts down on the number of iterations. -# -timed_or_fast.add_argument( - "-fast-tests", - help = "Cut down on the number of iterations of each test", - action = "store_true", -) - -args = parser.parse_args() - -EXIT_ON_FAIL = args.exit_on_fail - -# -# How many iterations of each random test do we want to run? -# -BITS_AND_ITERATIONS = [ - ( 120, 10_000), - ( 1_200, 1_000), - ( 4_096, 100), - (12_000, 10), -] - -if args.fast_tests: - for k in range(len(BITS_AND_ITERATIONS)): - b, i = BITS_AND_ITERATIONS[k] - BITS_AND_ITERATIONS[k] = (b, i // 10 if i >= 100 else 5) - -if args.no_random: - BITS_AND_ITERATIONS = [] - -# -# Where is the DLL? If missing, build using: `odin build . -build-mode:shared` -# -if platform.system() == "Windows": - LIB_PATH = os.getcwd() + os.sep + "math_big_test_library.dll" -elif platform.system() == "Linux": - LIB_PATH = os.getcwd() + os.sep + "math_big_test_library.so" -elif platform.system() == "Darwin": - LIB_PATH = os.getcwd() + os.sep + "math_big_test_library.dylib" -else: - print("Platform is unsupported.") - exit(1) - - -TOTAL_TIME = 0 -UNTIL_TIME = 0 -UNTIL_ITERS = 0 - -def we_iterate(): - if args.timed: - return TOTAL_TIME < UNTIL_TIME - else: - global UNTIL_ITERS - UNTIL_ITERS -= 1 - return UNTIL_ITERS != -1 - -# -# Error enum values -# -class Error(Enum): - Okay = 0 - Out_Of_Memory = 1 - Invalid_Pointer = 2 - Invalid_Argument = 3 - Unknown_Error = 4 - Assignment_To_Immutable = 10 - Max_Iterations_Reached = 11 - Buffer_Overflow = 12 - Integer_Overflow = 13 - Integer_Underflow = 14 - Division_by_Zero = 30 - Math_Domain_Error = 31 - Cannot_Open_File = 50 - Cannot_Read_File = 51 - Cannot_Write_File = 52 - Unimplemented = 127 - -# -# Disable garbage collection -# -gc.disable() - -# -# Set up exported procedures -# -try: - l = cdll.LoadLibrary(LIB_PATH) -except: - print("Couldn't find or load " + LIB_PATH + ".") - exit(1) - -def load(export_name, args, res): - export_name.argtypes = args - export_name.restype = res - return export_name - - - -# -# Result values will be passed in a struct { res: cstring, err: Error } -# -class Res(Structure): - _fields_ = [("res", c_char_p), ("err", c_uint64)] - -initialize_constants = load(l.test_initialize_constants, [], c_uint64) - -NAILS = initialize_constants() -LEG_BITS = 64 - NAILS - -print("LEG BITS: ", LEG_BITS) - -error_string = load(l.test_error_string, [c_byte], c_char_p) - -add = load(l.test_add, [c_char_p, c_char_p ], Res) -sub = load(l.test_sub, [c_char_p, c_char_p ], Res) -mul = load(l.test_mul, [c_char_p, c_char_p ], Res) -sqr = load(l.test_sqr, [c_char_p ], Res) -div = load(l.test_div, [c_char_p, c_char_p ], Res) - -# Powers and such -int_log = load(l.test_log, [c_char_p, c_longlong], Res) -int_pow = load(l.test_pow, [c_char_p, c_longlong], Res) -int_sqrt = load(l.test_sqrt, [c_char_p ], Res) -int_root_n = load(l.test_root_n, [c_char_p, c_longlong], Res) - -# Logical operations -int_shl_leg = load(l.test_shl_leg, [c_char_p, c_longlong], Res) -int_shr_leg = load(l.test_shr_leg, [c_char_p, c_longlong], Res) -int_shl = load(l.test_shl, [c_char_p, c_longlong], Res) -int_shr = load(l.test_shr, [c_char_p, c_longlong], Res) -int_shr_signed = load(l.test_shr_signed, [c_char_p, c_longlong], Res) - -int_factorial = load(l.test_factorial, [c_uint64 ], Res) -int_gcd = load(l.test_gcd, [c_char_p, c_char_p ], Res) -int_lcm = load(l.test_lcm, [c_char_p, c_char_p ], Res) - -is_square = load(l.test_is_square, [c_char_p ], Res) - -def test(test_name: "", res: Res, param=[], expected_error = Error.Okay, expected_result = "", radix=16): - passed = True - r = None - err = Error(res.err) - - if err != expected_error: - error_loc = res.res.decode('utf-8') - error = "{}: {} in '{}'".format(test_name, err, error_loc) - - if len(param): - error += " with params {}".format(param) - - print(error, flush=True) - passed = False - elif err == Error.Okay: - r = None - try: - r = res.res.decode('utf-8') - r = int(res.res, radix) - except: - pass - - if r != expected_result: - error = "{}: Result was '{}', expected '{}'".format(test_name, r, expected_result) - if len(param): - error += " with params {}".format(param) - - print(error, flush=True) - passed = False - - if EXIT_ON_FAIL and not passed: exit(res.err) - - return passed - -def arg_to_odin(a): - if a >= 0: - s = hex(a)[2:] - else: - s = '-' + hex(a)[3:] - return s.encode('utf-8') - - -def big_integer_sqrt(src): - # The Python version on Github's CI doesn't offer math.isqrt. - # We implement our own - count = src.bit_length() - a, b = count >> 1, count & 1 - - x = 1 << (a + b) - - while True: - # y = (x + n // x) // 2 - t1 = src // x - t2 = t1 + x - y = t2 >> 1 - - if y >= x: - return x - - x, y = y, x - -def big_integer_lcm(a, b): - # Computes least common multiple as `|a*b|/gcd(a,b)` - # Divide the smallest by the GCD. - - if a == 0 or b == 0: - return 0 - - if abs(a) < abs(b): - # Store quotient in `t2` such that `t2 * b` is the LCM. - lcm = a // math.gcd(a, b) - return abs(b * lcm) - else: - # Store quotient in `t2` such that `t2 * a` is the LCM. - lcm = b // math.gcd(a, b) - return abs(a * lcm) - -def test_add(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - res = add(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = a + b - return test("test_add", res, [a, b], expected_error, expected_result) - -def test_sub(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - res = sub(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = a - b - return test("test_sub", res, [a, b], expected_error, expected_result) - -def test_mul(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - try: - res = mul(*args) - except OSError as e: - print("{} while trying to multiply {} x {}.".format(e, a, b)) - if EXIT_ON_FAIL: exit(3) - return False - - expected_result = None - if expected_error == Error.Okay: - expected_result = a * b - return test("test_mul", res, [a, b], expected_error, expected_result) - -def test_sqr(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a)] - try: - res = sqr(*args) - except OSError as e: - print("{} while trying to square {}.".format(e, a)) - if EXIT_ON_FAIL: exit(3) - return False - - expected_result = None - if expected_error == Error.Okay: - expected_result = a * a - return test("test_sqr", res, [a], expected_error, expected_result) - -def test_div(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - try: - res = div(*args) - except OSError as e: - print("{} while trying divide to {} / {}.".format(e, a, b)) - if EXIT_ON_FAIL: exit(3) - return False - expected_result = None - if expected_error == Error.Okay: - # - # We don't round the division results, so if one component is negative, we're off by one. - # - if a < 0 and b > 0: - expected_result = int(-(abs(a) // b)) - elif b < 0 and a > 0: - expected_result = int(-(a // abs((b)))) - else: - expected_result = a // b if b != 0 else None - return test("test_div", res, [a, b], expected_error, expected_result) - - -def test_log(a = 0, base = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), base] - res = int_log(*args) - - expected_result = None - if expected_error == Error.Okay: - expected_result = int(math.log(a, base)) - return test("test_log", res, [a, base], expected_error, expected_result) - -def test_pow(base = 0, power = 0, expected_error = Error.Okay): - args = [arg_to_odin(base), power] - res = int_pow(*args) - - expected_result = None - if expected_error == Error.Okay: - if power < 0: - expected_result = 0 - else: - # NOTE(Jeroen): Don't use `math.pow`, it's a floating point approximation. - # Use built-in `pow` or `a**b` instead. - expected_result = pow(base, power) - return test("test_pow", res, [base, power], expected_error, expected_result) - -def test_sqrt(number = 0, expected_error = Error.Okay): - args = [arg_to_odin(number)] - try: - res = int_sqrt(*args) - except OSError as e: - print("{} while trying to sqrt {}.".format(e, number)) - if EXIT_ON_FAIL: exit(3) - return False - - expected_result = None - if expected_error == Error.Okay: - if number < 0: - expected_result = 0 - else: - expected_result = big_integer_sqrt(number) - return test("test_sqrt", res, [number], expected_error, expected_result) - -def root_n(number, root): - u, s = number, number + 1 - while u < s: - s = u - t = (root-1) * s + number // pow(s, root - 1) - u = t // root - return s - -def test_root_n(number = 0, root = 0, expected_error = Error.Okay): - args = [arg_to_odin(number), root] - res = int_root_n(*args) - expected_result = None - if expected_error == Error.Okay: - if number < 0: - expected_result = 0 - else: - expected_result = root_n(number, root) - - return test("test_root_n", res, [number, root], expected_error, expected_result) - -def test_shl_leg(a = 0, digits = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), digits] - res = int_shl_leg(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = a << (digits * LEG_BITS) - return test("test_shl_leg", res, [a, digits], expected_error, expected_result) - -def test_shr_leg(a = 0, digits = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), digits] - res = int_shr_leg(*args) - expected_result = None - if expected_error == Error.Okay: - if a < 0: - # Don't pass negative numbers. We have a shr_signed. - return False - else: - expected_result = a >> (digits * LEG_BITS) - - return test("test_shr_leg", res, [a, digits], expected_error, expected_result) - -def test_shl(a = 0, bits = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), bits] - res = int_shl(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = a << bits - return test("test_shl", res, [a, bits], expected_error, expected_result) - -def test_shr(a = 0, bits = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), bits] - res = int_shr(*args) - expected_result = None - if expected_error == Error.Okay: - if a < 0: - # Don't pass negative numbers. We have a shr_signed. - return False - else: - expected_result = a >> bits - - return test("test_shr", res, [a, bits], expected_error, expected_result) - -def test_shr_signed(a = 0, bits = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), bits] - res = int_shr_signed(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = a >> bits - - return test("test_shr_signed", res, [a, bits], expected_error, expected_result) - -def test_factorial(number = 0, expected_error = Error.Okay): - args = [number] - try: - res = int_factorial(*args) - except OSError as e: - print("{} while trying to factorial {}.".format(e, number)) - if EXIT_ON_FAIL: exit(3) - return False - - expected_result = None - if expected_error == Error.Okay: - expected_result = math.factorial(number) - - return test("test_factorial", res, [number], expected_error, expected_result) - -def test_gcd(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - res = int_gcd(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = math.gcd(a, b) - - return test("test_gcd", res, [a, b], expected_error, expected_result) - -def test_lcm(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a), arg_to_odin(b)] - res = int_lcm(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = big_integer_lcm(a, b) - - return test("test_lcm", res, [a, b], expected_error, expected_result) - -def test_is_square(a = 0, b = 0, expected_error = Error.Okay): - args = [arg_to_odin(a)] - res = is_square(*args) - expected_result = None - if expected_error == Error.Okay: - expected_result = str(big_integer_sqrt(a) ** 2 == a) if a > 0 else "False" - - return test("test_is_square", res, [a], expected_error, expected_result) - -# TODO(Jeroen): Make sure tests cover edge cases, fast paths, and so on. -# -# The last two arguments in tests are the expected error and expected result. -# -# The expected error defaults to None. -# By default the Odin implementation will be tested against the Python one. -# You can override that by supplying an expected result as the last argument instead. - -TESTS = { - test_add: [ - [ 1234, 5432], - ], - test_sub: [ - [ 1234, 5432], - ], - test_mul: [ - [ 1234, 5432], - [ 0xd3b4e926aaba3040e1c12b5ea553b5, 0x1a821e41257ed9281bee5bc7789ea7 ], - [ 1 << 21_105, 1 << 21_501 ], - [ - 0x200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, - 0x200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, - ] - ], - test_sqr: [ - [ 5432], - [ 0xd3b4e926aaba3040e1c12b5ea553b5 ], - ], - test_div: [ - [ 54321, 12345], - [ 55431, 0, Error.Division_by_Zero], - [ 12980742146337069150589594264770969721, 4611686018427387904 ], - [ 831956404029821402159719858789932422, 243087903122332132 ], - ], - test_log: [ - [ 3192, 1, Error.Invalid_Argument], - [ -1234, 2, Error.Math_Domain_Error], - [ 0, 2, Error.Math_Domain_Error], - [ 1024, 2], - ], - test_pow: [ - [ 0, -1, Error.Math_Domain_Error ], # Math - [ 0, 0 ], # 1 - [ 0, 2 ], # 0 - [ 42, -1,], # 0 - [ 42, 1 ], # 1 - [ 42, 0 ], # 42 - [ 42, 2 ], # 42*42 - [ 1023423462055631945665902260039819522, 6], - [ 2351415513563017480724958108064794964140712340951636081608226461329298597792428177392182921045756382154475969841516481766099091057155043079113409578271460350765774152509347176654430118446048617733844782454267084644777022821998489944144604889308377152515711394170267839394315842510152114743680838721625924309675796181595284284935359605488617487126635442626578631, 4], - ], - test_sqrt: [ - [ -1, Error.Invalid_Argument, ], - [ 42, Error.Okay, ], - [ 12345678901234567890, Error.Okay, ], - [ 1298074214633706907132624082305024, Error.Okay, ], - [ 0xa85e79177036820e9e63d14514884413c283db3dba2771f66ec888ae94fe253826ed3230efc1de0cbb4a2ba16fede5fe980d232472cca9e8f339714c56a9e64b5cff7538c33773f128898e8cad47234e8a086b4ce5b902231e2da75cc6cb510d892feb9c9c19ee5f5b7967cb7f081fb79099afe2d20203b0693ecc95c656e5515e0903a4ebc84d22fc2a176ba36dd795195535cfdf473e547930fbd6eae51ad11e974198b4733a10115f391c0fefd22654f5acd63c6415d4cbdaad6c1fc1812333d701b64bb230307fb37911561f5287efd67c2eec5a26a694931aec299c67874881bab0c42941cf0f4ef8ca3548e1adcc7f712eb714762184d656385ceacc7b9f75620dfa7ec62b70ee92a5998cee14ad2b9df3f0c861678bc3311c1fe78c5ce4ed30b90c56d18d50261a4f46fdbf6af94737920b50adf1229503edea8b32900000697f366eba632074a66dcd9999a1510ccefa6110bac2207602b16cd4ce42a36fbf276b5b14550faf75194256f175a867169ff30f8e4770d094b617e3df29612359e33d2a3e8f4e12acf243a22b2732e35a5039fea630886e80f49fb310cb34cd1ecb0dc3036761ac8eed5e2e3d6ea88c5b2f552405149fcb100f50368e969c7d1d45db10ea868838dddc3fbc54c9b658761522c31e46661f46205a6c8783d60638db10bc9515ece8509aa181332207c5a2753ee4a8297a65695fbd8184de, Error.Okay, ], - ], - test_root_n: [ - [ 1298074214633706907132624082305024, 2, Error.Okay, ], - ], - test_shl_leg: [ - [ 3192, 1 ], - [ 1298074214633706907132624082305024, 2 ], - [ 1024, 3 ], - ], - test_shr_leg: [ - [ 3680125442705055547392, 1 ], - [ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ], - [ 219504133884436710204395031992179571, 2 ], - ], - test_shl: [ - [ 3192, 1 ], - [ 1298074214633706907132624082305024, 2 ], - [ 1024, 3 ], - ], - test_shr: [ - [ 3680125442705055547392, 1 ], - [ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ], - [ 219504133884436710204395031992179571, 2 ], - ], - test_shr_signed: [ - [ -611105530635358368578155082258244262, 12 ], - [ -149195686190273039203651143129455, 12 ], - [ 611105530635358368578155082258244262, 12 ], - [ 149195686190273039203651143129455, 12 ], - ], - test_factorial: [ - [ 6_000 ], # Regular factorial, see cutoff in common.odin. - [ 12_345 ], # Binary split factorial - ], - test_gcd: [ - [ 23, 25, ], - [ 125, 25, ], - [ 125, 0, ], - [ 0, 0, ], - [ 0, 125,], - ], - test_lcm: [ - [ 23, 25,], - [ 125, 25, ], - [ 125, 0, ], - [ 0, 0, ], - [ 0, 125,], - ], - test_is_square: [ - [ 12, ], - [ 0x4fa3f9fe4edb58bfae7bab80b94ffce6e02cdd067c509f75a5918e510d002a8b41949dee96f482678b6e593ee2a984aa68809af5bdc3c0ee839c588b3b619e0f4a5267a7533765f8621dd20994a9a5bdd7faca4aab4f84a72f4f30d623a44cbc974d48e7ab63259d3141da5467e0a2225d90e6388f8d05e0bcdcb67f6d11c4e17d4c168b9fb23bf0932d6082ed82241b01d7d80bb43bf516fc650d86d62e13df218557df8b3f2e4eb295485e3f221c01130791c0b1b4c77fae4ae98e000e42d943a1dff9bfd960fdabe6a729913f99d74b1a7736c213b6c134bbc6914e0b5ae9d1909a32c2084af5a49a99a97a8c3856fdf1e4ff39306ede6234f85f0dca94382a118d97058d0be641c7b0cecead08450042a56dff16808115f78857d8844df61d8e930427d410ee33a63c79, ] - ], -} - -if not args.fast_tests: - TESTS[test_factorial].append( - # This one on its own takes around 800ms, so we exclude it for FAST_TESTS - [ 10_000 ], - ) - -total_passes = 0 -total_failures = 0 - -# -# test_shr_signed also tests shr, so we're not going to test shr randomly. -# -RANDOM_TESTS = [ - test_add, test_sub, test_mul, test_sqr, - test_log, test_pow, test_sqrt, test_root_n, - test_shl_leg, test_shr_leg, test_shl, test_shr_signed, - test_gcd, test_lcm, test_is_square, test_div, -] -SKIP_LARGE = [ - test_pow, test_root_n, # test_gcd, -] -SKIP_LARGEST = [] - -# Untimed warmup. -for test_proc in TESTS: - for t in TESTS[test_proc]: - res = test_proc(*t) - -if __name__ == '__main__': - print("\n---- math/big tests ----") - print() - - max_name = 0 - for test_proc in TESTS: - max_name = max(max_name, len(test_proc.__name__)) - - fmt_string = "{name:>{max_name}}: {count_pass:7,} passes and {count_fail:7,} failures in {timing:9.3f} ms." - fmt_string = fmt_string.replace("{max_name}", str(max_name)) - - for test_proc in TESTS: - count_pass = 0 - count_fail = 0 - TIMINGS = {} - for t in TESTS[test_proc]: - start = time.perf_counter() - res = test_proc(*t) - diff = time.perf_counter() - start - TOTAL_TIME += diff - - if test_proc not in TIMINGS: - TIMINGS[test_proc] = diff - else: - TIMINGS[test_proc] += diff - - if res: - count_pass += 1 - total_passes += 1 - else: - count_fail += 1 - total_failures += 1 - - print(fmt_string.format(name=test_proc.__name__, count_pass=count_pass, count_fail=count_fail, timing=TIMINGS[test_proc] * 1_000)) - - for BITS, ITERATIONS in BITS_AND_ITERATIONS: - print() - print("---- math/big with two random {bits:,} bit numbers ----".format(bits=BITS)) - print() - - # - # We've already tested up to the 10th root. - # - TEST_ROOT_N_PARAMS = [2, 3, 4, 5, 6] - - for test_proc in RANDOM_TESTS: - if BITS > 1_200 and test_proc in SKIP_LARGE: continue - if BITS > 4_096 and test_proc in SKIP_LARGEST: continue - - count_pass = 0 - count_fail = 0 - TIMINGS = {} - - UNTIL_ITERS = ITERATIONS - if test_proc == test_root_n and BITS == 1_200: - UNTIL_ITERS /= 10 - - UNTIL_TIME = TOTAL_TIME + BITS / args.timed_bits - # We run each test for a second per 20k bits - - index = 0 - - while we_iterate(): - a = randint(-(1 << BITS), 1 << BITS) - b = randint(-(1 << BITS), 1 << BITS) - - if test_proc == test_div: - # We've already tested division by zero above. - bits = int(BITS * 0.6) - b = randint(-(1 << bits), 1 << bits) - if b == 0: - b == 42 - elif test_proc == test_log: - # We've already tested log's domain errors. - a = randint(1, 1 << BITS) - b = randint(2, 1 << 60) - elif test_proc == test_pow: - b = randint(1, 10) - elif test_proc == test_sqrt: - a = randint(1, 1 << BITS) - b = Error.Okay - elif test_proc == test_root_n: - a = randint(1, 1 << BITS) - b = TEST_ROOT_N_PARAMS[index] - index = (index + 1) % len(TEST_ROOT_N_PARAMS) - elif test_proc == test_shl_leg: - b = randint(0, 10); - elif test_proc == test_shr_leg: - a = abs(a) - b = randint(0, 10); - elif test_proc == test_shl: - b = randint(0, min(BITS, 120)) - elif test_proc == test_shr_signed: - b = randint(0, min(BITS, 120)) - elif test_proc == test_is_square: - a = randint(0, 1 << BITS) - elif test_proc == test_lcm: - smallest = min(a, b) - biggest = max(a, b) - - # Randomly swap biggest and smallest - if randint(1, 11) % 2 == 0: - smallest, biggest = biggest, smallest - - a, b = smallest, biggest - else: - b = randint(0, 1 << BITS) - - res = None - - start = time.perf_counter() - res = test_proc(a, b) - diff = time.perf_counter() - start - - TOTAL_TIME += diff - - if test_proc not in TIMINGS: - TIMINGS[test_proc] = diff - else: - TIMINGS[test_proc] += diff - - if res: - count_pass += 1; total_passes += 1 - else: - count_fail += 1; total_failures += 1 - - print(fmt_string.format(name=test_proc.__name__, count_pass=count_pass, count_fail=count_fail, timing=TIMINGS[test_proc] * 1_000)) - - print() - print("---- THE END ----") - print() - print(fmt_string.format(name="total", count_pass=total_passes, count_fail=total_failures, timing=TOTAL_TIME * 1_000)) - - if total_failures: +# +# Copyright 2021 Jeroen van Rijn . +# Made available under Odin's license. +# +# A BigInt implementation in Odin. +# For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. +# The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. +# + +from random import * +import math +import os +import platform +import time +import gc +from enum import Enum +import argparse + +LEG_BITS = 60 + +vectors = open('../test_vectors.odin', 'w') +vectors.write("""package test_core_math_big + +import "core:math/big" + +// GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED +// +// This file is generated using `test_generator.py` +// +// GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED + +Big_Test_Operation :: enum { + Add, + Sub, + Mul, + Div, + Sqr, + Log, + Sqrt, + Pow, + Root, + Shl, + Shr, + Shr_Signed, + Factorial, + Gcd, + Lcm, + Is_Square, +} + +Big_Test_Vector :: struct { + op: Big_Test_Operation, + a: string, + b: string, + exp: string, + err: big.Error, +} + +big_test_vectors := []Big_Test_Vector{ +""") + +parser = argparse.ArgumentParser( + description = "Odin core:math/big test suite generator", + epilog = "By default we generate regression and random tests with preset parameters.", + formatter_class = argparse.ArgumentDefaultsHelpFormatter, +) + +# +# We skip randomized tests altogether if this is set. +# +no_random = parser.add_mutually_exclusive_group() + +no_random.add_argument( + "-no-random", + help = "Don't generate random tests", + action = "store_true", +) + +# +# Normally we run a given number of cycles on each test. +# Timed tests budget 1 second per 20_000 bits instead. +# +# For timed tests we budget a second per `n` bits and iterate until we hit that time. +# +timed_or_fast = no_random.add_mutually_exclusive_group() + +timed_or_fast.add_argument( + "-timed", + type = bool, + default = False, + help = "Timed tests instead of a preset number of iterations.", +) +parser.add_argument( + "-timed-bits", + type = int, + metavar = "BITS", + default = 20_000, + help = "Timed tests. Every `BITS` worth of input is given a second of running time.", +) + +# +# For normal tests (non-timed), `-fast-tests` cuts down on the number of iterations. +# +timed_or_fast.add_argument( + "-fast-tests", + help = "Cut down on the number of iterations of each test", + action = "store_true", +) + +args = parser.parse_args() + +# +# How many iterations of each random test do we want to run? +# +BITS_AND_ITERATIONS = [ + ( 120, 100), + ( 1_200, 100), + ( 4_096, 100), + (12_000, 10), +] + +if args.fast_tests: + for k in range(len(BITS_AND_ITERATIONS)): + b, i = BITS_AND_ITERATIONS[k] + BITS_AND_ITERATIONS[k] = (b, i // 10 if i >= 100 else 5) + +if args.no_random: + BITS_AND_ITERATIONS = [] + +TOTAL_TIME = 0 +UNTIL_TIME = 0 +UNTIL_ITERS = 0 + +def we_iterate(): + if args.timed: + return TOTAL_TIME < UNTIL_TIME + else: + global UNTIL_ITERS + UNTIL_ITERS -= 1 + return UNTIL_ITERS != -1 + +# +# Error enum values +# +class Error(Enum): + Okay = 0 + Out_Of_Memory = 1 + Invalid_Pointer = 2 + Invalid_Argument = 3 + Mode_Not_Implemented = 4 + Assignment_To_Immutable = 10 + Max_Iterations_Reached = 11 + Buffer_Overflow = 12 + Integer_Overflow = 13 + Integer_Underflow = 14 + Division_by_Zero = 30 + Math_Domain_Error = 31 + Cannot_Open_File = 50 + Cannot_Read_File = 51 + Cannot_Write_File = 52 + Unimplemented = 127 + +# +# Disable garbage collection +# +gc.disable() + +def arg_to_odin(a): + if a >= 0: + s = hex(a)[2:] + else: + s = '-' + hex(a)[3:] + return s.encode('utf-8') + + +def big_integer_sqrt(src): + # The Python version on Github's CI doesn't offer math.isqrt. + # We implement our own + count = src.bit_length() + a, b = count >> 1, count & 1 + + x = 1 << (a + b) + + while True: + # y = (x + n // x) // 2 + t1 = src // x + t2 = t1 + x + y = t2 >> 1 + + if y >= x: + return x + + x, y = y, x + +def big_integer_lcm(a, b): + # Computes least common multiple as `|a*b|/gcd(a,b)` + # Divide the smallest by the GCD. + + if a == 0 or b == 0: + return 0 + + if abs(a) < abs(b): + # Store quotient in `t2` such that `t2 * b` is the LCM. + lcm = a // math.gcd(a, b) + return abs(b * lcm) + else: + # Store quotient in `t2` such that `t2 * a` is the LCM. + lcm = b // math.gcd(a, b) + return abs(a * lcm) + +def write_test_case(op = "", a = 0, b = 0, expected_result = 0, expected_error = Error.Okay): + def test_arg_to_odin(a): + if a >= 0: + s = hex(a)[2:] + else: + s = '-' + hex(a)[3:] + return s + + vectors.write("\t{{{}, ".format(op)) + vectors.write("\"{}\", ".format(test_arg_to_odin(a))) + vectors.write("\"{}\", ".format(test_arg_to_odin(b))) + if expected_result == None: + vectors.write("\"0\", ") + else: + vectors.write("\"{}\", ".format(test_arg_to_odin(expected_result))) + + if expected_error == Error.Okay: + expected_error = "Error.None" + vectors.write("{}}},\n".format(expected_error)[5:]) + +def test_add(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + expected_result = a + b + + write_test_case(".Add", a, b, expected_result, expected_error) + +def test_sub(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + expected_result = a - b + + write_test_case(".Sub", a, b, expected_result, expected_error) + +def test_mul(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + expected_result = a * b + + write_test_case(".Mul", a, b, expected_result, expected_error) + +def test_sqr(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a)] + expected_result = None + if expected_error == Error.Okay: + expected_result = a * a + + write_test_case(".Sqr", a, b, expected_result, expected_error) + +def test_div(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + # + # We don't round the division results, so if one component is negative, we're off by one. + # + if a < 0 and b > 0: + expected_result = int(-(abs(a) // b)) + elif b < 0 and a > 0: + expected_result = int(-(a // abs((b)))) + else: + expected_result = a // b if b != 0 else None + + write_test_case(".Div", a, b, expected_result, expected_error) + +def test_log(a = 0, base = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), base] + expected_result = None + if expected_error == Error.Okay: + expected_result = int(math.log(a, base)) + + write_test_case(".Log", a, base, expected_result, expected_error) + +def test_pow(base = 0, power = 0, expected_error = Error.Okay): + args = [arg_to_odin(base), power] + expected_result = None + if expected_error == Error.Okay: + if power < 0: + expected_result = 0 + else: + # NOTE(Jeroen): Don't use `math.pow`, it's a floating point approximation. + # Use built-in `pow` or `a**b` instead. + expected_result = pow(base, power) + + write_test_case(".Pow", base, power, expected_result, expected_error) + +def test_sqrt(number = 0, expected_error = Error.Okay): + args = [arg_to_odin(number)] + expected_result = None + if expected_error == Error.Okay: + if number < 0: + expected_result = 0 + else: + expected_result = big_integer_sqrt(number) + + write_test_case(".Sqrt", number, 0, expected_result, expected_error) + +def root_n(number, root): + u, s = number, number + 1 + while u < s: + s = u + t = (root-1) * s + number // pow(s, root - 1) + u = t // root + return s + +def test_root_n(number = 0, root = 0, expected_error = Error.Okay): + args = [arg_to_odin(number), root] + expected_result = None + if expected_error == Error.Okay: + if number < 0: + expected_result = 0 + else: + expected_result = root_n(number, root) + + write_test_case(".Root", number, root, expected_result, expected_error) + +def test_shl_leg(a = 0, digits = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), digits] + expected_result = None + if expected_error == Error.Okay: + expected_result = a << (digits * LEG_BITS) + + write_test_case(".Shl", a, (digits * LEG_BITS), expected_result, expected_error) + +def test_shr_leg(a = 0, digits = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), digits] + expected_result = None + if expected_error == Error.Okay: + if a < 0: + # Don't pass negative numbers. We have a shr_signed. + return False + else: + expected_result = a >> (digits * LEG_BITS) + + write_test_case(".Shr", a, (digits * LEG_BITS), expected_result, expected_error) + +def test_shl(a = 0, bits = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), bits] + expected_result = None + if expected_error == Error.Okay: + expected_result = a << bits + + write_test_case(".Shl", a, bits, expected_result, expected_error) + +def test_shr(a = 0, bits = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), bits] + expected_result = None + if expected_error == Error.Okay: + if a < 0: + # Don't pass negative numbers. We have a shr_signed. + return False + else: + expected_result = a >> bits + + write_test_case(".Shr", a, bits, expected_result, expected_error) + +def test_shr_signed(a = 0, bits = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), bits] + expected_result = None + if expected_error == Error.Okay: + expected_result = a >> bits + + write_test_case(".Shr_Signed", a, bits, expected_result, expected_error) + +def test_factorial(number = 0, expected_error = Error.Okay): + args = [number] + expected_result = None + if expected_error == Error.Okay: + expected_result = math.factorial(number) + + write_test_case(".Factorial", number, 0, expected_result, expected_error) + +def test_gcd(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + expected_result = math.gcd(a, b) + + write_test_case(".Gcd", a, b, expected_result, expected_error) + +def test_lcm(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a), arg_to_odin(b)] + expected_result = None + if expected_error == Error.Okay: + expected_result = big_integer_lcm(a, b) + + write_test_case(".Lcm", a, b, expected_result, expected_error) + +def test_is_square(a = 0, b = 0, expected_error = Error.Okay): + args = [arg_to_odin(a)] + expected_result = False + if expected_error == Error.Okay and a > 0: + expected_result = big_integer_sqrt(a) ** 2 == a + + write_test_case(".Is_Square", a, 0, expected_result, expected_error) + +# TODO(Jeroen): Make sure tests cover edge cases, fast paths, and so on. +# +# The last two arguments in tests are the expected error and expected result. +# +# The expected error defaults to None. +# By default the Odin implementation will be tested against the Python one. +# You can override that by supplying an expected result as the last argument instead. + +TESTS = { + test_add: [ + [ 1234, 5432], + ], + test_sub: [ + [ 1234, 5432], + ], + test_mul: [ + [ 1234, 5432], + [ 0xd3b4e926aaba3040e1c12b5ea553b5, 0x1a821e41257ed9281bee5bc7789ea7 ], + [ 1 << 21_105, 1 << 21_501 ], + [ + 0x200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + 0x200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + ] + ], + test_sqr: [ + [ 5432], + [ 0xd3b4e926aaba3040e1c12b5ea553b5 ], + ], + test_div: [ + [ 54321, 12345], + [ 55431, 0, Error.Division_by_Zero], + [ 12980742146337069150589594264770969721, 4611686018427387904 ], + [ 831956404029821402159719858789932422, 243087903122332132 ], + ], + test_log: [ + [ 3192, 1, Error.Invalid_Argument], + [ -1234, 2, Error.Math_Domain_Error], + [ 0, 2, Error.Math_Domain_Error], + [ 1024, 2], + ], + test_pow: [ + [ 0, -1, Error.Math_Domain_Error ], # Math + [ 0, 0 ], # 1 + [ 0, 2 ], # 0 + [ 42, -1,], # 0 + [ 42, 1 ], # 1 + [ 42, 0 ], # 42 + [ 42, 2 ], # 42*42 + [ 1023423462055631945665902260039819522, 6], + [ 2351415513563017480724958108064794964140712340951636081608226461329298597792428177392182921045756382154475969841516481766099091057155043079113409578271460350765774152509347176654430118446048617733844782454267084644777022821998489944144604889308377152515711394170267839394315842510152114743680838721625924309675796181595284284935359605488617487126635442626578631, 4], + ], + test_sqrt: [ + [ -1, Error.Invalid_Argument, ], + [ 42, Error.Okay, ], + [ 12345678901234567890, Error.Okay, ], + [ 1298074214633706907132624082305024, Error.Okay, ], + [ 0xa85e79177036820e9e63d14514884413c283db3dba2771f66ec888ae94fe253826ed3230efc1de0cbb4a2ba16fede5fe980d232472cca9e8f339714c56a9e64b5cff7538c33773f128898e8cad47234e8a086b4ce5b902231e2da75cc6cb510d892feb9c9c19ee5f5b7967cb7f081fb79099afe2d20203b0693ecc95c656e5515e0903a4ebc84d22fc2a176ba36dd795195535cfdf473e547930fbd6eae51ad11e974198b4733a10115f391c0fefd22654f5acd63c6415d4cbdaad6c1fc1812333d701b64bb230307fb37911561f5287efd67c2eec5a26a694931aec299c67874881bab0c42941cf0f4ef8ca3548e1adcc7f712eb714762184d656385ceacc7b9f75620dfa7ec62b70ee92a5998cee14ad2b9df3f0c861678bc3311c1fe78c5ce4ed30b90c56d18d50261a4f46fdbf6af94737920b50adf1229503edea8b32900000697f366eba632074a66dcd9999a1510ccefa6110bac2207602b16cd4ce42a36fbf276b5b14550faf75194256f175a867169ff30f8e4770d094b617e3df29612359e33d2a3e8f4e12acf243a22b2732e35a5039fea630886e80f49fb310cb34cd1ecb0dc3036761ac8eed5e2e3d6ea88c5b2f552405149fcb100f50368e969c7d1d45db10ea868838dddc3fbc54c9b658761522c31e46661f46205a6c8783d60638db10bc9515ece8509aa181332207c5a2753ee4a8297a65695fbd8184de, Error.Okay, ], + ], + test_root_n: [ + [ 1298074214633706907132624082305024, 2, Error.Okay, ], + ], + test_shl_leg: [ + [ 3192, 1 ], + [ 1298074214633706907132624082305024, 2 ], + [ 1024, 3 ], + ], + test_shr_leg: [ + [ 3680125442705055547392, 1 ], + [ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ], + [ 219504133884436710204395031992179571, 2 ], + ], + test_shl: [ + [ 3192, 1 ], + [ 1298074214633706907132624082305024, 2 ], + [ 1024, 3 ], + ], + test_shr: [ + [ 3680125442705055547392, 1 ], + [ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ], + [ 219504133884436710204395031992179571, 2 ], + ], + test_shr_signed: [ + [ -611105530635358368578155082258244262, 12 ], + [ -149195686190273039203651143129455, 12 ], + [ 611105530635358368578155082258244262, 12 ], + [ 149195686190273039203651143129455, 12 ], + ], + test_factorial: [ + [ 6_000 ], # Regular factorial, see cutoff in common.odin. + [ 12_345 ], # Binary split factorial + ], + test_gcd: [ + [ 23, 25, ], + [ 125, 25, ], + [ 125, 0, ], + [ 0, 0, ], + [ 0, 125,], + ], + test_lcm: [ + [ 23, 25,], + [ 125, 25, ], + [ 125, 0, ], + [ 0, 0, ], + [ 0, 125,], + ], + test_is_square: [ + [ 12, ], + [ 0x4fa3f9fe4edb58bfae7bab80b94ffce6e02cdd067c509f75a5918e510d002a8b41949dee96f482678b6e593ee2a984aa68809af5bdc3c0ee839c588b3b619e0f4a5267a7533765f8621dd20994a9a5bdd7faca4aab4f84a72f4f30d623a44cbc974d48e7ab63259d3141da5467e0a2225d90e6388f8d05e0bcdcb67f6d11c4e17d4c168b9fb23bf0932d6082ed82241b01d7d80bb43bf516fc650d86d62e13df218557df8b3f2e4eb295485e3f221c01130791c0b1b4c77fae4ae98e000e42d943a1dff9bfd960fdabe6a729913f99d74b1a7736c213b6c134bbc6914e0b5ae9d1909a32c2084af5a49a99a97a8c3856fdf1e4ff39306ede6234f85f0dca94382a118d97058d0be641c7b0cecead08450042a56dff16808115f78857d8844df61d8e930427d410ee33a63c79, ] + ], +} + +if not args.fast_tests: + TESTS[test_factorial].append( + # This one on its own takes around 800ms, so we exclude it for FAST_TESTS + [ 10_000 ], + ) + +total_passes = 0 +total_failures = 0 + +# +# test_shr_signed also tests shr, so we're not going to test shr randomly. +# +RANDOM_TESTS = [ + test_add, test_sub, test_mul, test_sqr, + test_log, test_pow, test_sqrt, test_root_n, + test_shl_leg, test_shr_leg, test_shl, test_shr_signed, + test_gcd, test_lcm, test_is_square, test_div, +] +SKIP_LARGE = [ + test_pow, test_root_n, # test_gcd, +] +SKIP_LARGEST = [] + +# Untimed warmup. +for test_proc in TESTS: + for t in TESTS[test_proc]: + res = test_proc(*t) + +if __name__ == '__main__': + print("\n---- math/big tests ----") + print() + + max_name = 0 + for test_proc in TESTS: + max_name = max(max_name, len(test_proc.__name__)) + + fmt_string = "{name:>{max_name}}, {test_count} tests" + fmt_string = fmt_string.replace("{max_name}", str(max_name)) + + for test_proc in TESTS: + count = 0 + for t in TESTS[test_proc]: + count += 1 + test_proc(*t) + + print(fmt_string.format(name=test_proc.__name__, test_count=count)) + + for BITS, ITERATIONS in BITS_AND_ITERATIONS: + print() + print("---- math/big with two random {bits:,} bit numbers ----".format(bits=BITS)) + print() + + # + # We've already tested up to the 10th root. + # + TEST_ROOT_N_PARAMS = [2, 3, 4, 5, 6] + + for test_proc in RANDOM_TESTS: + if BITS > 1_200 and test_proc in SKIP_LARGE: continue + if BITS > 4_096 and test_proc in SKIP_LARGEST: continue + + count = 0 + + UNTIL_ITERS = ITERATIONS + if test_proc == test_root_n and BITS == 1_200: + UNTIL_ITERS /= 10 + + UNTIL_TIME = TOTAL_TIME + BITS / args.timed_bits + # We run each test for a second per 20k bits + + index = 0 + + while we_iterate(): + a = randint(-(1 << BITS), 1 << BITS) + b = randint(-(1 << BITS), 1 << BITS) + + if test_proc == test_div: + # We've already tested division by zero above. + bits = int(BITS * 0.6) + b = randint(-(1 << bits), 1 << bits) + if b == 0: + b == 42 + elif test_proc == test_log: + # We've already tested log's domain errors. + a = randint(1, 1 << BITS) + b = randint(2, 1 << 60) + elif test_proc == test_pow: + b = randint(1, 10) + elif test_proc == test_sqrt: + a = randint(1, 1 << BITS) + b = Error.Okay + elif test_proc == test_root_n: + a = randint(1, 1 << BITS) + b = TEST_ROOT_N_PARAMS[index] + index = (index + 1) % len(TEST_ROOT_N_PARAMS) + elif test_proc == test_shl_leg: + b = randint(0, 10); + elif test_proc == test_shr_leg: + a = abs(a) + b = randint(0, 10); + elif test_proc == test_shl: + b = randint(0, min(BITS, 120)) + elif test_proc == test_shr_signed: + b = randint(0, min(BITS, 120)) + elif test_proc == test_is_square: + a = randint(0, 1 << BITS) + elif test_proc == test_lcm: + smallest = min(a, b) + biggest = max(a, b) + + # Randomly swap biggest and smallest + if randint(1, 11) % 2 == 0: + smallest, biggest = biggest, smallest + + a, b = smallest, biggest + else: + b = randint(0, 1 << BITS) + + count += 1 + test_proc(a, b) + + print(fmt_string.format(name=test_proc.__name__, test_count=count)) + + print() + print("---- THE END ----") + + vectors.write("}") + + if total_failures: exit(1) \ No newline at end of file diff --git a/tests/core/math/big/test.odin b/tests/core/math/big/test.odin deleted file mode 100644 index f35f0b72b..000000000 --- a/tests/core/math/big/test.odin +++ /dev/null @@ -1,362 +0,0 @@ -/* - Copyright 2021 Jeroen van Rijn . - Made available under Odin's BSD-3 license. - - An arbitrary precision mathematics implementation in Odin. - For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3. - The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks. - - This file exports procedures for use with the test.py test suite. -*/ -package test_core_math_big - -/* - TODO: Write tests for `internal_*` and test reusing parameters with the public implementations. -*/ - -import "base:runtime" -import "core:strings" -import "core:math/big" - -PyRes :: struct { - res: cstring, - err: big.Error, -} - -print_to_buffer :: proc(val: ^big.Int) -> cstring { - context = runtime.default_context() - r, _ := big.int_itoa_cstring(val, 16, context.allocator) - return r -} - -@export test_initialize_constants :: proc "c" () -> (res: u64) { - context = runtime.default_context() - _ = big.initialize_constants() - - return u64(big._DIGIT_NAILS) -} - -@export test_error_string :: proc "c" (err: big.Error) -> (res: cstring) { - context = runtime.default_context() - es := big.Error_String - return strings.clone_to_cstring(es[err], context.allocator) -} - -@export test_add :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - aa, bb, sum := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(aa, bb, sum) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":add:atoi(a):", err=err} } - if err = big.atoi(bb, string(b), 16); err != nil { return PyRes{res=":add:atoi(b):", err=err} } - if bb.used == 1 { - if err = #force_inline big.internal_add(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err} } - } else { - if err = #force_inline big.internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err} } - } - - r := print_to_buffer(sum) - - return PyRes{res = r, err = nil} -} - -@export test_sub :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - aa, bb, sum := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(aa, bb, sum) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":sub:atoi(a):", err=err} } - if err = big.atoi(bb, string(b), 16); err != nil { return PyRes{res=":sub:atoi(b):", err=err} } - if bb.used == 1 { - if err = #force_inline big.internal_sub(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err} } - } else { - if err = #force_inline big.internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err} } - } - - r := print_to_buffer(sum) - if err != nil { return PyRes{res=":sub:itoa(sum):", err=err} } - return PyRes{res = r, err = nil} -} - -@export test_mul :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - aa, bb, product := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(aa, bb, product) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":mul:atoi(a):", err=err} } - if err = big.atoi(bb, string(b), 16); err != nil { return PyRes{res=":mul:atoi(b):", err=err} } - if err = #force_inline big.internal_mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err} } - - r := print_to_buffer(product) - return PyRes{res = r, err = nil} -} - -@export test_sqr :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - aa, square := &big.Int{}, &big.Int{} - defer big.internal_destroy(aa, square) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":sqr:atoi(a):", err=err} } - if err = #force_inline big.internal_sqr(square, aa); err != nil { return PyRes{res=":sqr:sqr(square,a):", err=err} } - - r := print_to_buffer(square) - return PyRes{res = r, err = nil} -} - -/* - NOTE(Jeroen): For simplicity, we don't return the quotient and the remainder, just the quotient. -*/ -@export test_div :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - aa, bb, quotient := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(aa, bb, quotient) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":div:atoi(a):", err=err} } - if err = big.atoi(bb, string(b), 16); err != nil { return PyRes{res=":div:atoi(b):", err=err} } - if err = #force_inline big.internal_div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err} } - - r := print_to_buffer(quotient) - return PyRes{res = r, err = nil} -} - -/* - res = log(a, base) -*/ -@export test_log :: proc "c" (a: cstring, base := big.DIGIT(2)) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - l: int - - aa := &big.Int{} - defer big.internal_destroy(aa) - - if err = big.atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err} } - if l, err = #force_inline big.internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err} } - - #force_inline big.internal_zero(aa) - aa.digit[0] = big.DIGIT(l) & big._MASK - aa.digit[1] = big.DIGIT(l) >> big._DIGIT_BITS - aa.used = 2 - big.clamp(aa) - - r := print_to_buffer(aa) - return PyRes{res = r, err = nil} -} - -/* - dest = base^power -*/ -@export test_pow :: proc "c" (base: cstring, power := int(2)) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - dest, bb := &big.Int{}, &big.Int{} - defer big.internal_destroy(dest, bb) - - if err = big.atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", err=err} } - if err = #force_inline big.internal_pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err} } - - r := print_to_buffer(dest) - return PyRes{res = r, err = nil} -} - -/* - dest = sqrt(src) -*/ -@export test_sqrt :: proc "c" (source: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(src):", err=err} } - if err = #force_inline big.internal_sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = root_n(src, power) -*/ -@export test_root_n :: proc "c" (source: cstring, power: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(src):", err=err} } - if err = #force_inline big.internal_root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = shr_digit(src, digits) -*/ -@export test_shr_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err} } - if err = #force_inline big._private_int_shr_leg(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = shl_digit(src, digits) -*/ -@export test_shl_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err} } - if err = #force_inline big._private_int_shl_leg(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = shr(src, bits) -*/ -@export test_shr :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", err=err} } - if err = #force_inline big.internal_shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = shr_signed(src, bits) -*/ -@export test_shr_signed :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", err=err} } - if err = #force_inline big.internal_shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = shl(src, bits) -*/ -@export test_shl :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - src := &big.Int{} - defer big.internal_destroy(src) - - if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", err=err} } - if err = #force_inline big.internal_shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err} } - - r := print_to_buffer(src) - return PyRes{res = r, err = nil} -} - -/* - dest = factorial(n) -*/ -@export test_factorial :: proc "c" (n: int) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - dest := &big.Int{} - defer big.internal_destroy(dest) - - if err = #force_inline big.internal_int_factorial(dest, n); err != nil { return PyRes{res=":factorial:factorial(n):", err=err} } - - r := print_to_buffer(dest) - return PyRes{res = r, err = nil} -} - -/* - dest = gcd(a, b) -*/ -@export test_gcd :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - ai, bi, dest := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(ai, bi, dest) - - if err = big.atoi(ai, string(a), 16); err != nil { return PyRes{res=":gcd:atoi(a):", err=err} } - if err = big.atoi(bi, string(b), 16); err != nil { return PyRes{res=":gcd:atoi(b):", err=err} } - if err = #force_inline big.internal_int_gcd_lcm(dest, nil, ai, bi); err != nil { return PyRes{res=":gcd:gcd(a, b):", err=err} } - - r := print_to_buffer(dest) - return PyRes{res = r, err = nil} -} - -/* - dest = lcm(a, b) -*/ -@export test_lcm :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - - ai, bi, dest := &big.Int{}, &big.Int{}, &big.Int{} - defer big.internal_destroy(ai, bi, dest) - - if err = big.atoi(ai, string(a), 16); err != nil { return PyRes{res=":lcm:atoi(a):", err=err} } - if err = big.atoi(bi, string(b), 16); err != nil { return PyRes{res=":lcm:atoi(b):", err=err} } - if err = #force_inline big.internal_int_gcd_lcm(nil, dest, ai, bi); err != nil { return PyRes{res=":lcm:lcm(a, b):", err=err} } - - r := print_to_buffer(dest) - return PyRes{res = r, err = nil} -} - -/* - dest = lcm(a, b) -*/ -@export test_is_square :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context() - err: big.Error - square: bool - - ai := &big.Int{} - defer big.internal_destroy(ai) - - if err = big.atoi(ai, string(a), 16); err != nil { return PyRes{res=":is_square:atoi(a):", err=err} } - if square, err = #force_inline big.internal_int_is_square(ai); err != nil { return PyRes{res=":is_square:is_square(a):", err=err} } - - if square { - return PyRes{"True", nil} - } - return PyRes{"False", nil} -} \ No newline at end of file diff --git a/tests/core/math/big/test_core_math_big.odin b/tests/core/math/big/test_core_math_big.odin index 9a1e7b01b..ed9d1c206 100644 --- a/tests/core/math/big/test_core_math_big.odin +++ b/tests/core/math/big/test_core_math_big.odin @@ -1,6 +1,7 @@ package test_core_math_big import "core:math/big" +import "core:strconv" import "core:testing" @(test) @@ -35,3 +36,297 @@ test_permutations_and_combinations :: proc(t: ^testing.T) { testing.expect_value(t, error, nil) } } + +Rational_Vectors :: struct { + numerator: int, + denominator: int, + expected_f64: f64, + expected_f32: f32, + expected_f16: f16, + exact_f64: bool, + exact_f32: bool, + exact_f16: bool, +} +rational_vectors := []Rational_Vectors{ + {-1, 1, -1.00, -1.00, -1.00, true, true, true}, + { 1, 4, 0.25, 0.25, 0.25, true, true, true}, + { 3, 4, 0.75, 0.75, 0.75, true, true, true}, + {-3, 4, -0.75, -0.75, -0.75, true, true, true}, +} + +@(test) +test_rational_to_float :: proc(t: ^testing.T) { + for vec in rational_vectors { + r: big.Rat + defer big.destroy(&r) + big.set(&r.a, vec.numerator) + big.set(&r.b, vec.denominator) + + { + float, exact, err := big.rat_to_f64(&r) + testing.expect_value(t, float, vec.expected_f64) + testing.expect(t, exact == vec.exact_f64) + testing.expect(t, err == nil) + } + + { + float, exact, err := big.rat_to_f32(&r) + testing.expect_value(t, float, vec.expected_f32) + testing.expect(t, exact == vec.exact_f32) + testing.expect(t, err == nil) + } + + { + float, exact, err := big.rat_to_f16(&r) + testing.expect_value(t, float, vec.expected_f16) + testing.expect(t, exact == vec.exact_f16) + testing.expect(t, err == nil) + } + } +} + +import "core:log" + +@(test) +test_big_math_vectors :: proc(t: ^testing.T) { + for vec in big_test_vectors { + a, b, res, expected := &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{} + defer big.destroy(a, b, res, expected) + + atoi(t, a, vec.a) or_continue + atoi(t, b, vec.b) or_continue + atoi(t, expected, vec.exp) or_continue + + #partial switch vec.op { + case .Add: + err := big.add(res, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected add(%v, %v) to be %v, got %v", a, b, expected, res, err) + + case .Sub: + err := big.sub(res, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected sub(%v, %v) to be %v, got %v", a, b, expected, res, err) + + case .Mul: + err := big.mul(res, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected mul(%v, %v) to be %v, got %v", a, b, expected, res, err) + + case .Div: + err := big.div(res, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected div(%v, %v) to be %v, got %v", a, b, expected, res, err) + + case .Sqr: + err := big.sqr(res, a) + testing.expect(t, err == vec.err) + + expect_a(t, "Expected sqr(%v) to be %v, got %v", a, expected, res, err) + + case .Log: + base, base_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, base_ok == true) + + log_res, err := big.log(a, big.DIGIT(base)) + testing.expect(t, err == vec.err) + + big.set(res, log_res) + expect_ab(t, "Expected log(%v, %v) to be %v, got %v", a, b, expected, res, err) + + case .Sqrt: + err := big.sqrt(res, a) + testing.expect(t, err == vec.err) + + expect_a(t, "Expected sqrt(%v) to be %v, got %v", a, expected, res, err) + + case .Pow: + power, power_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, power_ok == true) + + err := big.pow(res, a, int(power)) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected pow(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Root: + n, n_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, n_ok == true) + + err := big.root_n(res, a, int(n)) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected root_n(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Shl: + bits, bits_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, bits_ok == true) + + err := big.internal_int_shl(res, a, int(bits)) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected internal_int_shl(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Shr: + bits, bits_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, bits_ok == true) + + err := big.internal_int_shr(res, a, int(bits)) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected internal_int_shr(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Shr_Signed: + bits, bits_ok := strconv.parse_i64_of_base(vec.b, 16) + testing.expect(t, bits_ok == true) + + big.set(res, a) + err := big.internal_int_shr_signed(res, res, int(bits)) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected internal_int_shr_signed(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Factorial: + n, n_ok := strconv.parse_i64_of_base(vec.a, 16) + testing.expect(t, n_ok == true) + + err := big.factorial(res, int(n)) + testing.expect(t, err == vec.err) + + expect_a(t, "Expected factorial(%v) to be %q, got %q", a, expected, res, err) + + case .Gcd: + err := big.internal_int_gcd_lcm(res, nil, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected gcd(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Lcm: + err := big.internal_int_gcd_lcm(nil, res, a, b) + testing.expect(t, err == vec.err) + + expect_ab(t, "Expected lcm(%v, %v) to be %q, got %q", a, b, expected, res, err) + + case .Is_Square: + square, err := big.internal_int_is_square(a) + testing.expect(t, err == vec.err) + + big.set(res, 1 if square else 0) + expect_a(t, "Expected is_square(%v) to be %q, got %q", a, expected, res, err) + + case: + log.assertf(false, "Unhandled op: %v", vec.op) + } + } +} + +@(test) +bug_5931 :: proc(t: ^testing.T) { + numerator, divisor, quotient, remainder: big.Int + defer big.destroy(&numerator, &divisor, "ient, &remainder) + + big.string_to_int(&numerator, "3351951982485649274893506249551461531869841455148098344430890360930192345844485855956241793418914802713278852793799976230545127411560969441984014513833901") + big.string_to_int(&divisor, "115792089237316195423570985008687907853269984665640564039457584007908834671663") + + big.int_divmod("ient, &remainder, &numerator, &divisor) + quo_str, _ := big.int_itoa_string("ient) + defer delete(quo_str) + assert(quo_str == "28948022309329048855892746252171976963317496166410141009864396001977208667923") + + rem_str, _ := big.int_itoa_string(&remainder) + defer delete(rem_str) + assert(rem_str == "28948022309329048855892746252171976963317496166410141009864396001977208667952") +} + + +// Test helpers + +expect_a :: proc(t: ^testing.T, format: string, a, expected, res: ^big.Int, err: big.Error, loc := #caller_location) { + if err != nil { return } + + equal, _ := big.equals(res, expected) + if !equal { + as, _ := big.itoa(a) + rs, _ := big.itoa(res) + es, _ := big.itoa(expected) + + defer delete(as) + defer delete(rs) + defer delete(es) + + testing.expectf(t, equal, format, as, es, rs, loc=loc) + assert(equal) + } +} + +expect_ab :: proc(t: ^testing.T, format: string, a, b, expected, res: ^big.Int, err: big.Error, loc := #caller_location) { + if err != nil { return } + + equal, _ := big.equals(res, expected) + if !equal { + as, _ := big.itoa(a) + bs, _ := big.itoa(b) + rs, _ := big.itoa(res) + es, _ := big.itoa(expected) + + defer delete(as) + defer delete(bs) + defer delete(rs) + defer delete(es) + + testing.expectf(t, equal, format, as, bs, es, rs, loc=loc) + assert(equal) + } +} + +atoi :: proc(t: ^testing.T, i: ^big.Int, a: string, loc := #caller_location) -> bool { + err := big.atoi(i, a, 16) + testing.expect(t, err == nil, loc=loc) + return err == nil +} + +@(test) +test_itoa :: proc(t: ^testing.T) { + a := &big.Int{} + big.random(a, 2048) + defer big.destroy(a) + + for radix in 2..=64 { + if big.is_power_of_two(radix) { + // Powers of two are trivial, and are handled before `_itoa_raw_*` is called. + continue + } + + size, _ := big.radix_size(a, i8(radix), false) + buffer_old := make([]u8, size) + defer delete(buffer_old) + buffer_new := make([]u8, size) + defer delete(buffer_new) + + written_old, _ := big._itoa_raw_old (a, i8(radix), buffer_old, false) + written_new, _ := big._itoa_raw_full(a, i8(radix), buffer_new, false) + + str_old := string(buffer_old[:written_old]) + str_new := string(buffer_new[:written_new]) + testing.expect_value(t, str_new, str_old) + } + + // Also test a number with a large number of zeroes + big.set(a, "2970714761494550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000802525522395693895558562897961119110387707542077460459880227570865486047631557732177235787527971863645406120285117781450154113859156752194121206131440514109132606823127467068869589613665129498148285292867292641704871893467328665051712596763187306247339023362481") + size, _ := big.radix_size(a, 10, false) + buffer_old := make([]u8, size) + defer delete(buffer_old) + buffer_new := make([]u8, size) + defer delete(buffer_new) + + written_old, _ := big._itoa_raw_old (a, 10, buffer_old, false) + written_new, _ := big._itoa_raw_full(a, 10, buffer_new, false) + + str_old := string(buffer_old[:written_old]) + str_new := string(buffer_new[:written_new]) + testing.expect_value(t, str_new, str_old) +} \ No newline at end of file diff --git a/tests/core/math/big/test_vectors.odin b/tests/core/math/big/test_vectors.odin new file mode 100644 index 000000000..f560e9e67 --- /dev/null +++ b/tests/core/math/big/test_vectors.odin @@ -0,0 +1,4813 @@ +package test_core_math_big + +import "core:math/big" + +// GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED +// +// This file is generated using `test_generator.py` +// +// GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED -=- GENERATED + +Big_Test_Operation :: enum { + Add, + Sub, + Mul, + Div, + Sqr, + Log, + Sqrt, + Pow, + Root, + Shl, + Shr, + Shr_Signed, + Factorial, + Gcd, + Lcm, + Is_Square, +} + +Big_Test_Vector :: struct { + op: Big_Test_Operation, + a: string, + b: string, + exp: string, + err: big.Error, +} + +big_test_vectors := []Big_Test_Vector{ + {.Add, "4d2", "1538", "1a0a", .None}, + {.Sub, "4d2", "1538", "-1066", .None}, + {.Mul, "4d2", "1538", "6647f0", .None}, + {.Mul, "d3b4e926aaba3040e1c12b5ea553b5", "1a821e41257ed9281bee5bc7789ea7", "15ebfa91663d62991f82757b52c07a1f61e42109fbda6012b09cb75b5113", .None}, + {.Mul, "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Mul, "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Sqr, "1538", "0", "1c23c40", .None}, + {.Sqr, "d3b4e926aaba3040e1c12b5ea553b5", "0", "af13b82e702669fcdc5a22d7fb20a286cd5d7357dc65dae8dd0beeb0ddf9", .None}, + {.Div, "d431", "3039", "4", .None}, + {.Div, "d887", "0", "0", .Division_by_Zero}, + {.Div, "9c40000000000044c00000000000079", "4000000000000000", "2710000000000011", .None}, + {.Div, "a03a9e1c9ecd4600a73553b5e7dd86", "35f9f28f2cd19e4", "2f7efced80593f1d", .None}, + {.Log, "c78", "1", "0", .Invalid_Argument}, + {.Log, "-4d2", "2", "0", .Math_Domain_Error}, + {.Log, "0", "2", "0", .Math_Domain_Error}, + {.Log, "400", "2", "a", .None}, + {.Pow, "0", "-1", "0", .Math_Domain_Error}, + {.Pow, "0", "0", "1", .None}, + {.Pow, "0", "2", "0", .None}, + {.Pow, "2a", "-1", "0", .None}, + {.Pow, "2a", "1", "2a", .None}, + {.Pow, "2a", "0", "1", .None}, + {.Pow, "2a", "2", "6e4", .None}, + {.Pow, "c51aac23a451627370e2767c51a102", "6", "355498cbf9889c7102a7cc5d500db60ee1bc0779bd9ae18e4aa442a4924eb20a307dc73634be3ea4fce13da5358090f92533943d7dee9ae7dc573c770d10ef76adb6bb13be22c27d8835053840178dd55fafaaa406f8aa28c040", .None}, + {.Pow, "22f5d30a14315d48df4a328b2157657583ef58244138029542bbdb4658c8c4811b81d571ff0de06579eb3ed0c4802a84602ff832ce7854f60e3a3a5ae31323eb8a2a7d12a4bb29ee6db08086bbc22cfe6ac7cb201e21c790c328cc5f4be7040c614e68f6f49da2e5dd72a54adbba17eec5deb657d02c899dc911380dbffec0286a03ed9ea3ca6e11148dfb80c89ce4c0999d8c9748c7", "4", "16cb3bba77f95103473e405521a073b6d8a1b81af0bae0cfa44a593ab8c8ee7f78b34e4bfffebc16bd494fc711f01f75cf76331ffa347c54532c78b8abd905c5dcb5bdfb68402cbc6d4256845bf63bd54577fee63b1bbcc32a762b29b64b9d491039e56854ea4474698f4c9fccdc886a8174b247d711aca335361c3a2037889d1426956af6df38584a36674f5782a07887622c33f9bbddbf5633690223b0761f00d21078d8d34726784c35d21b42c404633b2dc1a00f741653b9aba1b7b2a5454ccf4e8e6c0e7faa698921c5793c2b84ade8bf4b99bcf93eb6c33c3b0b59c2e93e6cc388a1fb2529e79877bd2c8885b7509fa8de77fcaff2e7faa7ca0daf37aed817f084a2df013f517d05e8fed27e38e29e45fb67172cfbbe3db09fb033936bf301ef73ca020adf88f538872448b02bedbb0bb9620d0efea3be30e9a6ccee5908cd215e8ab16d1cf8bba202718556a404cc55f2efc42fbcc3e65f629b4abe81436b3ac002406e81e42e370a31e787789bab92dec3f14b765d4028405a15e92336939bbef80fdfb455615a068063553a486805e71d05643fa415f4dd4d8efa886536c5d3d6f00a0d78d8792a71b5af3283bd7b0f4653b90108c518bdcea241ccd604aeabec6c7d881df3892e9307e7651d35278f09a2c991eff47f84406b3c950e3bc0a36ce803185e196df0f8ed1f5991e5586da5336786fd8e140d7de14bdac58001ea1b707d3d9d4ed6447c4a7810c34e3208d322bbb22f031cb180002e009637eb17768ba1d008ad513c097ceb161767cadffc58130b4166a67cac830766e4f32703d4bfd4ac257e3fc96a9f0803d82f489ec74e61", .None}, + {.Sqrt, "-1", "0", "0", .Invalid_Argument}, + {.Sqrt, "2a", "0", "6", .None}, + {.Sqrt, "ab54a98ceb1f0ad2", "0", "d16deb64", .None}, + {.Sqrt, "4000000000000000000000000000", "0", "80000000000000", .None}, + {.Sqrt, "a85e79177036820e9e63d14514884413c283db3dba2771f66ec888ae94fe253826ed3230efc1de0cbb4a2ba16fede5fe980d232472cca9e8f339714c56a9e64b5cff7538c33773f128898e8cad47234e8a086b4ce5b902231e2da75cc6cb510d892feb9c9c19ee5f5b7967cb7f081fb79099afe2d20203b0693ecc95c656e5515e0903a4ebc84d22fc2a176ba36dd795195535cfdf473e547930fbd6eae51ad11e974198b4733a10115f391c0fefd22654f5acd63c6415d4cbdaad6c1fc1812333d701b64bb230307fb37911561f5287efd67c2eec5a26a694931aec299c67874881bab0c42941cf0f4ef8ca3548e1adcc7f712eb714762184d656385ceacc7b9f75620dfa7ec62b70ee92a5998cee14ad2b9df3f0c861678bc3311c1fe78c5ce4ed30b90c56d18d50261a4f46fdbf6af94737920b50adf1229503edea8b32900000697f366eba632074a66dcd9999a1510ccefa6110bac2207602b16cd4ce42a36fbf276b5b14550faf75194256f175a867169ff30f8e4770d094b617e3df29612359e33d2a3e8f4e12acf243a22b2732e35a5039fea630886e80f49fb310cb34cd1ecb0dc3036761ac8eed5e2e3d6ea88c5b2f552405149fcb100f50368e969c7d1d45db10ea868838dddc3fbc54c9b658761522c31e46661f46205a6c8783d60638db10bc9515ece8509aa181332207c5a2753ee4a8297a65695fbd8184de", "0", "cf9c817dc096c3ad7b725c9ac52b0969fac4ff38ce527bec81fc7ede5a3f4802879e1c4f3a834d254725bf5ca902904334b22971d34f21d64321c0d5ad190791bd5004a54bcd7e70f265c9ee5c1ea266b687fdad448013bddd2c01436026be89ea2bd2b5cac4ecca23df5f6b3a1794836dd5ed890ed11a19a5c30135f76d1811e77984e69dff031f2151b3707bcded26c8b34e96a74cf392b85495cb1d6aa85000c652fe295d952cc784e29244fe53e52e6b9f44533b11fbd1425bfb8ccf69932dc717e7f614c39596e3ea7dd338f10c34a58dfcfdfa79c4aa11239476d5c201de5fda26e7bf1af62b3cf07058fe82e1cfc00725cd9da6a621b785af6554a4b2", .None}, + {.Root, "4000000000000000000000000000", "2", "80000000000000", .None}, + {.Shl, "c78", "3c", "c78000000000000000", .None}, + {.Shl, "4000000000000000000000000000", "78", "4000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "400", "b4", "400000000000000000000000000000000000000000000000", .None}, + {.Shr, "c78000000000000000", "3c", "c78", .None}, + {.Shr, "4000000000000000000000000000000000000000000000000000000000", "78", "4000000000000000000000000000", .None}, + {.Shr, "2a4663ad14733d6c985e64bf979b73", "78", "0", .None}, + {.Shl, "c78", "1", "18f0", .None}, + {.Shl, "4000000000000000000000000000", "2", "10000000000000000000000000000", .None}, + {.Shl, "400", "3", "2000", .None}, + {.Shr, "c78000000000000000", "1", "63c000000000000000", .None}, + {.Shr, "4000000000000000000000000000000000000000000000000000000000", "2", "1000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "2a4663ad14733d6c985e64bf979b73", "2", "a9198eb451ccf5b2617992fe5e6dc", .None}, + {.Shr_Signed, "-75b1d4317d7fae6627576acd96e2a6", "c", "-75b1d4317d7fae6627576acd96f", .None}, + {.Shr_Signed, "-75b1d4317d7fae6627576acd96f", "c", "-75b1d4317d7fae6627576ace", .None}, + {.Shr_Signed, "75b1d4317d7fae6627576acd96e2a6", "c", "75b1d4317d7fae6627576acd96e", .None}, + {.Shr_Signed, "75b1d4317d7fae6627576acd96f", "c", "75b1d4317d7fae6627576acd", .None}, + {.Factorial, "1770", "0", "f0c93f984a54cc898047e57386e7170240f087f83b708cc5c1e3a0ad90b4e49923d442417a3dfc63d84db68daa950fb6c614e914cd54a006182dffd0967443f778a2b47cc1018efd34894fc11f723707e7e166153b0e0c2b4d7372785c450b1dd0f3de4e0d7cafd21180823e6cf11ed0c3241eb2ada4cc01852be8e2955f49204f04ad9d122d796b23835c62d7f15fb97925af7017271bfcd6f133410859470febdac7f22664fa1ae053d03c87a13fc2707128560505863df4dc233af70ff2ed86489f30c34a691951b950c86761b2e456457172902c0c4d4370b7ebe83972f2dd01c6449c983a51c17853ff4eed4082a6e42a99b6179b54e87b189fa5c4ecd1d345c88e5fc66b09d38ae9c49aba18eae2efc8c3e2932ab9a1bcf78c341b7c4e13ec55d43d67e6b15da8f6c789b91f876fb25af1fb6f2af3b7ba4104a198bf4215b13f89b6352bd58d4acb8bb248a646db3806e309ff66229e48c25d7128bd64647bd50527071238cb1795b03b509480c060cd17b77f949b007bdb5277faac50770c10c4bb83674776ce8a4610b0be3ea1565e7ac09fda913b04d6eba6ccbc03e4a49ad123711bed73de938b70e7808fbc02f01ab1b614559ffba61381b80685f8218ee679c0423f3c5859624bd20d2371682c139b4c58b95e90de1af532066d33f57c4b34e6c493bf30b01353ab50cc224a15cec1701a455a58e1de7ac797f598bb3d433fa5ba4d0a9657c98c08ee99fa3d0d5acc50537f4769606bc52b4dbf0cb11c2fe76985ef922cf3021d5b1e1db231cdc6f8f083e9a02d7dafd0867b829b849d636946227850ccabea4aed8056051f15ecc2304687734e81902a4929eb751a725ccfefe90f3156c20669c1566af2d9acc9f9798fb24f601571181e0b182a65356172261a23104c873b6c5cae0228699cb9077de65028f8bb53b4db83af02e580bbd4f0ef6ba996d93e321a6e3bae37f27ef9e316ebb350d8700079b7e84a1e5afb5d75e325a10738fa3cc5342354f0357d5b1457820f07698a3315a08730e9b2f58a73e74b294b50653883a8cae6da1b700440060dc7d25fe9f3756db15418f6128594fde0f48f7a543f977ce62ff9bf750954dc507f4de9cc54a61c072cb4bed5bfb4a35645782e3ccd4d0c257e74ea7a88a2c4e39a2d0d181b6f96f93d05261451fa4f64a17607465cfdcd16a67b73c38a5a09edbddf0728769aed09d0d5e4b7464f7942ecab0ea88649a04a4f9470176d4550b175f9900f984769d23fa45259dfb5e859146accccda8757d0c0a4b5858936cd8c89a64dca5eb9b42331075d32c3017d9c1f16424edc5dffe5e37ec7f51a3e3b047e207d1ca4f7239e90b76bae580f307685107f5a03e0cf2dc7c3ffd14d3b1a85e3af277c3793037cf84520bd6ce8fe99fa5259495808341e9406dbcebd8480b3ceb74b052039241ba4d1add796075ec99a0ecc948bc87c6c72f88082c0153677cc70317d55dc155f9574785494b26f997f379fdd80031c1d8eb2f7d43a6ea7ec4954a7fa5a496fe4fdc70f4f8ae5b1b78363e4441a073b5fef4e86b787d7084bfa0f462198b1c28cab2fdc669a1b486c026cb288654c1f18c8d2c1bcdcc33bc62ada91a10f7fa219c8d8db7597c6dc50e5d4342d93c2da55e05d835fe7a106958c80837af5a79f0b4552179ff57289958391ba7e387cee50a501930d31651e3b53e1cf95be74115dd42fbdff68926c4631b95400ec05fcf03324770a56e07fe364c1c78061e866a66357f5745fa8eff1eb11e1d77b284fe717ead053f26ff428ee773da48a66a3607d2d29d184065467c52ea251a1b8557bdae491f87a2764911a56edd4426df2039cc48b1ccb97e3ef48595408b168a1432fdc2017c0be74d587affc0e9fbb7d11304259dfc134e04a9f4913a7dc10259c0c698103a18c07c2947153bd5c04a10f24216a8f79fdab9340fa6cbb2c8714a4f39adbf6d99541ee288dcf824198140426b97abe5793f8446ef2b663ff6206e99f8cb5d87b7a30656fdacdba9c3cdc9e8911d9b470ae2fe7b37f5825e2e2018b9c26d6da0c0bfb3f7c1134423ea34a51daae7475e893f854625daad3507fdf93becc8cfe789aa45dcd4665b9cd92acd987c82e9a42a941b63484972bcf276549165fad3779472cad25121b79708beb9317c6179528c1801aedd208a94891ed897434fb7fced1d9e0d103ee64733038ee82a4dbcb29a1424c7b9d7b39c5abb2dccd8926558ebc2c7bc7714c39aa177f00c883e546c18fd0056e310ce09fb11edce0171dcd32057cf75c3a52be45361a5ac9d5be3745e9dcaec928c8311b44efc660bac4efbee5996b6e8d40672d4c9bd4bb1d203bc158dfec1478f47010106927a77a72101e3419d693acb64c2812508559e5fa9fb9d1fdca914941bfa78c2b0cce0d6e45e52751f29d682ddc49b47e17f22ebeb777ebfb4df4be344814f120585b407d7a4c5b24b1416e4a3a45a9e7602ee353b960309bacc6cd8f1eea4f297838b9028528347394d4cc6a63ee15000ecf4f64ccd0367caf08bb421dfd4278aa81185e50f8bce64be925c5d422d62feb1162cefadd4d48d4c606222e1e4aead7c05e7a44c9a1bc3d7e010c4fd8b5e754962f30a2ac0641d4581ac55871b6bfb1604747db02bd7b19c9fbd4e0cee9bdf3edfc4cd1c42bd91f30e86950349174cb96675830553acbd744ac318ebfbada54c6e3373aceeff6a62aeb1a0aca442580e8e2637a98887f548b43730db3532a3641e7dfca75f0766db4251d435973c4304ee8c79394642727245d8b5adce9970f0a74df28c1a7ae46b9f1a7b20f5b7759a50c238c90ff2c9f75807bf59abf38be876d404869cbf5ac6ea34a527ee35fc15db1e61fa7fa42879bddf7292922a485b792ea9eeecb4f58a070316dd89251bf826370c4fdcc0e1590365ed972d5a14703e94f122b357313eaedea12d4027dc77f0f16e35d17a7500cb36711952655280042deeb5b252486f2c42a0dd1a23768c2be59aaec3c760b878b114fca7ac863878d1ddb6aaf1543350a8eefda4ac5539d40dcabbfcfdc172e94709361a84da76638009a9c1b2823a0f213dcf46cf73931677c0b9b312bbe40a1848c0dd9152d5a9b3a377697167e287f6d620dacd1044e0d5d3ae07ae9e564dc07bcc9d1b552b140ec822d6c8ee6679444d58f0ea5710097d7c3be4a5c751c58a610031905539a1f391d8a7c0169a4bd082a42294887bc16d89fbf06d8388e989cb35593f2092cbae11ddd47bffc9b86b70ca9b41816f0b1654757781873b54c36eac4886ca2af9526c8ce0a8f85b51528a368d08c7a3570112031a67ab623f763bc19aa7939d0fb119ac0286648ccc7a12f3befe175f8d09c90f35fa0dca68a649cdfc859aa016047339ae9bf328fc9a0eae3a5ad1214f5220446372292b9ec461c44cc466e201aa6590f4bfc213865679d3403d4c2ac8380874cee3f65d6335bba1573d7d20ab9e73be9af1ba405f028b8341615bb07218ada3c2d36d18376277bf9f94fc1ce9189552c864298962f3195c9ef146874232fbc42f1768be379f94fc4edd747dc5b613da50c5e3322507ed9931c9cc17a7de16f5c06f6b24a4285ebe21458741f3855aca1aff3a015b840e23b4bef69505857940aa34fee44b3c8f11add91db976ba5c0b55659d2dd1d322e784578dfc4101c7e68c579052b5ae9cc923e2fbebc62d103dd68a966b49118747b64ae8dc9269ac6aced716427b91a14f8e17c011ca79816528aa8cf6589ef47db181fc5d48a5ec5da3dc629b0058ab91a9832f19b1b54c19b986613e7bd3b09c07de25e41c26aa1ebda72e38f169930813bfbfe74cc39fedb2e91255b5dba52600f38580669170749d7f52d39d2aa493ad83bf4ebb492d05a20ba4d7829ea7fcad7ed4ac9d9b037826289f5799d65d6c4817160239ce1a0f45d872229449d7b50f0932cf5982de3ede587ef5252b03349f60525c8e59a87bfd10fada76fae0c73dbb73e0a6f5c5fa6927c1eda01e4142d356fc02741af9d9e87183428c9d3389d08e9bf2c6514c0dcb87cfdbc1fb60cfd2714fe6f21b7206fec61a5ec7cb2e7eac92eb21c3164564d0303bf06edbaee1e7fe60a1bf8c69513412263b7c5cdedb96e36b5676a040396201981435d906321d9d5740dbf59a9723db18c65b32d84b684ef1ecc0723239c5b534e562df86d81f7aafa879b6bf9e1ca9a10caab41d2b616c107165b6756bca480dcccbf2880f5e7bafd49c186b03719836afba6eeb4f861c5aa4e00b226e42e0bc02c0cd7b0715eabf8cd67c7f4c2102e7772708d5824ccc2457641377775f8359a23bc94e514c414453dc7c486137e89a9c191d6f21b324cc1e02ac88fe60cea1261c9470507d2190b4d672185711c29871d20c91a332976a3aeffdce84c6b4b1c216dd9daa1e7065a629beaf9f92329712caff6dff95d61e93e5a0155e236b972de03f808253f8690aacf505d32682daeeabcb28789eb43c9026c32e535a956ee9e71f283dcdb02bae5b1c34d7dfb07202af8b5e900bfb3240d0049ac8e85b17276f012913128b53e2116887260d6a1df9e6c935850efa3e813ea85a0c743108a2f56f36bdb0c1e5ff14a3fd76f25a5b5e58241ae3302dfef6c778b230ec4c37d194b8369e3a511d98bd953ba26d418c25d6e15d4a8006a6b430deb02b00fd41f709c73bd30fbdef6b8b1cb7ee518c50c46cc09ad40949ae6b69da642baaa2f06a0a3d0dc4915f61ebddf1ab91c48af5dc75947f257eed2dd3cedc33fd0ff8df54b627be63974368c819054a4b893bb00f54d7933876c1e7838951417429faebadf917c3e1eb5f2ab3beeb3efa9cc4833c62901df6fcdc5e1505e659daf6310ea0b5f52acd8b4216ab7ce6b3591086a92ba093caf874cab14b006f5434fc1a4414bd16ab63a5a022b0cb0ba36cb1ed7860a3142ec646e0171f73d22822b2156cdc1848ea90eea94225add5ccf33e13db42654238424ae67a46066084cb0359fe32d307532dccf32f5c11233f8d3bcb398ef07fda2a5e465c12049032503675c6d3ef3576fe1d1c15047cbb0ce29fb7f353e43a8458822c252f02355d3d14f1cc33494b77f0bf55b88cf57871c6fdd2257adeef7962a4c3d4b857707b4ce8b02468347b58bde0466aff3d6057363e9125eeabcbb7d5936ebd656704fc6b045d27b9fc8514031c9cd90a635fe68a9a080713b9cf1918584f7461829f6cc3a7483a43e76601622f285734e21b56feca35f2458d40f4be31cc2931bce61f0f79a5eab3e492df63840a0a97b40a27d4516b32eb4cb6b643c5b562b5977f6e1d41c38940e9fe13240ea92421a7aaf97a2f68456802da771432df3a5d46eec42a74e780941f690353ef75f42d97a2eccc5da14dfbc277fc635c2fdb9cab322a51d92d4cd0ff70d009fa57435636550f4bc95926e7ff28467529ad9bcbac85de4d5ce5de6597ffa8a71e8197c937fca44bd206908fb9feb9ecc50071b00ec09940bfbc5679a4587e1d511f331586940663b65546777b23396366f996b002aca4520c6a997e7a368fb8698939a546e74eb00a0c0e4dab5927afa7b88cce9d8f07ef7a74818ed7e35448bfad0b07296992e21b514a6ecbca930e6f0543223b8780aa7b65612e0b394f93d19c3cf2188678bd5a5e2ad327bcc2860bedbfebbf343f31db337c48b2e8275bf6643192b2d3034d5d2404ee4129bf387c9572a773669aaf16ab2fbed600bb5060a2125e89b15f075ea947137e8d8777ea9bf260dfdc16bce48adcbbb5895081e8f0e966d69479de7d4197e2652961bd19ed5d651e45484ef6ecfd0033b0a9873f4497129575f2afcca46f1c42e4ad5e7cf3a72497ed83dd2cab5ed36c3a1c4a9ea3cd835792fbf77ec37a8b69c4f38fe8a77319c6e4e1f00dab8fa5629568843dd671d8f3ae36fb69772b02af3c94434c3c6e1b2ce38ae23feed4971dce4de59cb5843ee10bf1585c73a3898fe5848d74273ba3a6f9242d267207bf4250064b27445aeff713123de18ece118f989520b1e45bb7e3bce9c40a4c82bb12970b877bfd24332e1efd856306d53d9a4706f6ac0546af464fb6f5d97dba6da4bab8fa7254c0e517cc5d7622371db8ffb9aa9b2c2ce4a3cf5508beb12704a12bf89eb9eaf7aa0e9d4a578c0c17a505673124a2a0d0c19dcc4271b5bc67e7f6e470af0b232a6fd236fd4063d3fc9bc0d0b46b73b789af4c0c1b0b53f1d50ec1c648483bb153808e7ac4a829ae5bfe44fb193aa48a6231fda4292824da37b646d44a2548af78093154cd0f6c5880ded57959c4204526ff7fb88f36b2e753b857b1a95bea6f4448c0cb1c1c92dff1f6353f93e326cde06e5c4fec88143fdc29ff21e54625845db53a160058c8f8a8ca9c45f30a72c5f3f3c0d60ca21c97d01eb7d3bbbd68f973cfc4b7aff7ba10045e1e9deb4cdce9b95aeaf00b9b9a35adec07c593a518611c8d744669b12a3e52a37e26f5161ab89d02d32036349918ac5446235a0e59781eb0810809a077f473dc928b207ff5c5e3bf3a1ceab0e30088baba22fbdd3cc4a617b2376f2ccd5467bd87887ad618857ebb71434375896ef164ae95550d6bcc3086ab70ecf6fc17f3d3eb677ccf81a7dfe2fc58b5eaeae41dc540690b12e8e1b584432f05bd0f06db46742672a9c1e3031cf17b1c93849d9adf7e190e035f4e7f23e786f3102a3f6378ebc8bd19b7e9d3c73852c398118ff24a2d9b0e512173133692cdb6732ac4c35e0689c499d30195fa1a22addf95c0012a5ca5e62161dd88dcd75aaa29f043f987abdc5e1d0fdf03a67c859b96b7d92b6ccb9ab42b20903b2510e0f93fc43d9a7930ddc26d7c9caf4f8234723d24c1fd1cc7272e76a575778497d077592720ce020fe85a8fd94cee7e227d63dc67ea82b44992209963bc9c57a537c60848d7c98a880384ff4caf6fc4614109254beb4e91df94edc52b632448c4dbdaf7165792d79e687b4d720c5a6894e7019df3ee266148c52c93bce66073de054bf2e9887f77f7ebad94c70dfa3b0d6aeb47313f46125975c6187d34ab471d1aa4387829fa7a15f7ca89625ac8eec953b722ad0fd7d5581c35b895a7ad5efd9e2f355bec54c84dc1c01d40923039cc393950083496d2b75b8388fb4c93061ab0b962541819791038bfaf614e4a5805a66a2be678bbff245f6c35b73171a6b394b9fd4c24f742ee444bd70c7f4d2761450fdda51e82c7fe65f7f49bf0f2412a1e1d171db69fde747623c43749053b372db8948812c23f9efbf1bd318d20ae5a488e897350122bbe5e3d34c0871c05ca7ef9e02585ba1cff6fcb1c92d1063ea04fd4c22f014de06c494e9418b5f5df9c8d30b25b7ef180c45c07804cbff18e980e8e8ac2e65a24f48666b4f6bfb7fdaf68327575e1f486b6b69e4a6ce921ff6bde3ff11752c7788bb5f62b5966f6e6b501347e7342e089bc4b3daae8aed81b86a60911f454037d0d2e977f8658c362fe19f6bae39ffc626248e08b19f8211ab85913ed9849abe785e26e1137c6642134025dcd1cd138b178fde95f6785db77a39ffa444aa1f6b7cc19fa3f1b41af6c777ddae4e3d95d9df69b72da35d35f7d303ca85e28cca1a78644bcc2f3f97be8c3cba1fc31aa2df6d96f92b25dc3af7891ba3bcf5c9f8561613a9ffcb056a65d98e2a4232e8150ac3a5b328d44793d66a491ca2809fe5eabee9ed8f9d4738201a84eb4825b495db74921f766edabd1b06d25ade0b7e52ebc95ebc21c80f1cbf476c27fd23505b78f67eb885b4ed8e7cde831fe4fb52226a2323213a10c2957b2330e8d5f0160ed936e81261cc30e79e6d1aaffe0ae553f5392075af9a82750ffdc61e574e31bbe39affcc2ee6b8c6a64a056b62516506f2b58077093318293b47dac025bd280ef05beebe7dc7dd1fd5831b53624c9adf1096064470356db08a604e588e674553398782ff7c66694a44455574c6da206ecbb2225343e47f6198ee9ccbe38083b0ce60f8f074afe3887241691f8081e709c3d9b79c7cfd04d43b8bf1f34285acae5ddb1df8d26a7d7665af94e5d83ea90b24ae986611b26b35ce70e25e80a98b05d21f0d65a0f12d8c5033592d00cb69dc2e643db190389eaae0e98747c430e766801c223a94d87c9d727aa0888d982108d9a2078265a242d2d193a79fe0ccb3307b9c78925201a0f6e1c514ab705a8c43dd8d18ab3dbaf2969ce1c9108a1c03634c907d0ed2a01242a035be228ab9c39674c09799a84e5fe64f7f583085962e9c3522743f16320f6df80b07e16dcceee6c9860ecb992946ba773c3b4e9359775ab2443935d0cfed8c0091e33b55c4ef722d611b7550beab45853ea6f32bc4c184f6efdc339dd8b101a852b33aaae8ac13bdc9a1f5c9290c13e3533a0ecf6f3bec41031e0c901656f8c22021e3f9f57c2dec915155688d364e559220d1bb467473afa48d4e91e9637488c7f0d6382002eeebd4984ecc553679aabafd70ab008429355d018425db8e6a88e778b922e939e85bcc16a043ac0ff6e4ba3fd74332c075bcd496abd44bb8f73226980aecc55f14d1899764a9c7ce9bea4a9b4b1073a6ec2015181eca06907175ffdb2705f6fd00e5a013d21fc66d7a308235cc786f6627dc5909302b5188c42bd7de5350e06c1865316cf96300a79184d8cec06771c1b6ed8bfe661284c3f44ef5b41d7e70ba10bc6f41328787e778d5538e9785e5f032bea564bb4815fa9f09f47c5f73d4fa678d2104d8e0380c722c4ed6cabcb41da71ddc570028b7abadcf2899ad8be648e5d9aaf40c3a5411d704a57343c534f90c724f7981842a51691b8bea457e38e448908b66d9aa481c3c0763ad1afe7176630e646e9e00897bb348105ce4dc9a4c37ae615dc1b70ec5b1847d1aa9fe982dd649036fa8f5ef0c23e588c07f11de24e1bcffbaebbdd3215234935a08d389d6bcb6aea5be84e4929cf18e79eb8e5a8be348032eabd5509ce786ccbdc3344c87861c1b38b8ac59d21b0281e286927361a0797bee2700f625d3a8f87adc373258f6a9f35e65d68f2ab6570a0ccc21bffcb344f5b7d061a8a20646777bcf245e00a1ccdaefe2891f3b0c7580e3801dc7a3880fe66a70c0f0a2c880f79f110829cc7681623f36e022ba219e516ea2a46fa4f0fce0c489f67ed3484d67cbebeb5b9b3d75d82132059d4d7ce062fcfdc5c131b08d1c966eb103241d4d3228cfd1018e53003076d631150724f4ba6a7d6cd8719cb61d51fd83f09ebc9d11105b97af876566d80da59e977a0f665b3c28c7ed40cd778bca8f1a908319a14c5d6ad390cc55e5aaee779cc3916ec0963aa262dd7062a9ffc94aa86e7da473a44c0dee5c7f6820f327ba6b36e64154f5435474d09e3f3593f63216a3d6e206d3c8210a9430facdcfadb5cd50ebede3fc02d6bc1c43b3ece4793d0032f1f9a12cc9577a4bed8157c407f93f2ddc9b91aa5eea506c0386b55517f7a96ae01aef1e42a9479fe41be7c644d018301dce9c3ecddff37b1641beaefd486baacbbd24187f76cb9f154a33e6543155d29176fea515eaeaa28a321cd41255a1abb7efeedbbc0982f09563909fd76762f5b178d9003d37e2565908095f44cd376a8147ff2319d7cca6a0135f7bdd1f30f79c70c6f799f39f9bb88eb511858d4eb34c7d20b574f46ac8236a29b714d6575e58562a363b7c6286eae49d42831a14653ee16045446385a7797b6bcf1823f8b1b52a2376c3be5dc0b6a8282203d98df652455402ffd6208a6596570d264c2311a01da0a5b119172ef6d473321ab354460918f53c3eadd764c937c674a9fe3179d5c9cd54348805af4f29ccb5715d8e129d918040e4ec47f2c99022e1e00034d87d157a572d0d969032f04983cd54b8d18612a4c2875894c48feab0c96141e9ba648ad6a2f1ef1c0d4e44761bb14107126ff157ffd5c27568c37bd28a44ca81140cfc0d2a6dd864c4e27521ab9a1078d48e497b8d2b2104f1e4c3ba4a2f95e401667fa5e388c6807fac08d8c4c71bb5a0d50366d39987426dfd9172ae535e1497b0119bbf4c15f79fbe496350dbbe7ba335d9aa66ced3271eddec663d16120b0b0176987d463c5e47fed463e2ef2a230c17a5417f535aa26dad59615d603ec118670f88efba66f392aa3ad7a5d483ccfd8c8eb69728d982399cbb42c5a90449027efc2eb0432b90801d74a9418469af89eb75352e4a3dc2d1c589373eb8a2352aaf853e1bbaf7e4fd8e9c95567987bf453a46e7cfcc31fd61e6c0f1a2c658aba4feff965be68d6b5e964e2872f25eab5323b3c326c34729acf20c71698c43bc10ea039c977d4d7ab3927512c9a13134b4c4d518bbaaf831299632244228f2088eb6cba674fb68852c7cc3a2c721c84e8db66d2c5b0e4d0a95f0e0d928e7e5ac0602cb4f84ca84f200f33e7f189220f6a945b538480e4ecc07aeae6adf89c3f7b65737c0c15bc7f8a4ae2a2553d4fad3dbaf438ee0ba7a0f085b0743e6db6e425c1186aef4d134af4491222400e21e054ec39004f35862c17661ac52820005ab99c257de614f5d078073e323933c533b0e4ffdcbe8aa81c816e0fb3cbcb7e19a9fc228c2206c663f8b7bd4a166d527839b8204f3ffaf11af7b181e2f18c310f25eb7ccfdd9af1b5b00720fb719f5ba905163308736bc7833e400cd56c32198c6bcd137447df307a67567c8429adbe05028c3386ad96249552ca630fc67d7bacb109cf5f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Factorial, "3039", "0", "725bc54b19f7229a2368a8438d231aa6742a9bdffda109af918973d185bd1142da42abe786438fbfb3b6a1d6732b6a1fb468d8908f1cd36ffb7efc0669264f2b5f3f92abfa5e2adb4ca4d9e2750eaf98c210de9067729c35a08bab7b52a889aa4f7462af4d00f28a02a41c9c63cdb0633b8afc137bcf9d06b7308fcf3aaa5d6a6cd571ae149530e773c9ab20fb61de0a754b959f749ed22fadd2ff0753c623eb2b377d75d7a730e0ab4fb8ab8097108085b68b81df361751ab9543dc4d640128718f886cd2deab7ce07c032728489f9b4c2ef223b13260de9c5b5eb26d5d3e4ba9439bdc3061afc6083ac8a60ef74d770d15557742c93e03f6df30dd5010a76761026e3e93b48e439d4cf71e41cfdc00e6c559f3a0047a5bcb54acee326ea538297a91cefdcc9a3b05d5d0c05319635a817fbe6edf12fa501e2024cdcd86f1ca3a12bfd485a55b0cb9717e5c29b65fd7f6a45ffe75300aa09ee79b9a0ef022d4ab09eef62544bef7042ad3c0dddd7cf6eda293ccf9d9cfe38e96c7a29cb0b8ec360cad98f97826dbeb94e444928d64bd1b01d7d562cec000c84d5a4b4b00039a82307a3dbd32dd5047fbef8d5a11d177bc6f09aa580ebcc9cfc1f1b73df77e247e23222e58592a5eb496e7fde5fe202b09f43734e4ea1318052095c689d7ead46695c1213cb6987c6a3fb6da2c7c7802af9b7d6eb6938d3660c87ee7a76b11b9f964063c7bc3e161f0edae8433de09febfcd2e37bcb9a48e519529aab496382dbace40b8c75a831e8401804a13c3f567691f03d84ef70c345c42a3afe869e4e59cb240b50811856f3a8202d2975289ea2ebeffa878a1f29a7576609c57c27c015a411e75fb25333ca49e6a6edd6f668b86f4ee9a7f6208e1af9ccd3553c00902692f9db06357f399b90cdbb05912070619c448159a4227526054ce00c7ca069d595557fc5374528b6739e29c2b27f81034eaa3a3b0358641c5b699db45256519da785dca487d0f88b41bdf388e460fedeacda9c27934bf453b96d7f8ea2acf573b33346a0a6f39c10104cc6eab077cab4ff1843b6f1ba2439808523c3f7ad9ca9d411ce0bafe9aaa543b82c54964cd1e7bb0692d314570f35d1b51e7a1b81f2d259f4ebef59e018a2e8781258ea2bf4b0a1053a0114089b70aff5657bdf835d73828d00878a3a74c9beb017901a593127907e14a350b40c15ec821a1e502cb5e8ff7e807f9277d7c18cfd82648aa7a7fb9732d3f7574386eb49b66ca927eea6154098f45efae6b7e46c4a0c9d8e5e432d7f9bbac3f06635f1e7edce3088e5baa7edfa7cb5ba90198b97020878e727c1481ba9399846092d81cc0d2f6e85edc6d995885335264e8423a8922b251f98113a89a14bd729b1aa895a7b8fd1d92ac8f826f0e5e39b23a4939313345f6a4c055f819b2689b8bb9fbab5bea96a69df4ca93566d1bf9b106f7f7826dd7ed7d2b14a1172e754ccfaa9aae397593a83e9a222830792c1d630ef0bcfa1ac7737630f56d5e4daf8d678b40167b5333923c78e4a962aeea8785886e19fadc2aef83eb5feee8b7cfa4583ab9122b3d784bf8ae0a0085a9617a2728013fa15c5ee1cfece8d6f1ec2edea5c02e98b3257e135957cb427f6dbfc179fb94229dc7c6867d93ab740b75c41522aa26dbfbf786e9a24b417cffe0c0c6b8049877706bf9ba0f302b93ee248f5cea90f098bc557a19d6e93383c3549b8ea7c2cf478d2be3006445e133cc899b05f8ce12f35caaadde7431ebd6aca51bac7e1a8677af175aff8ae9bcd31bd284f9b8bf99556e8c679aa617f35d89817636c0e32b28939cd5590a75d587d83a72478c68f289056350ce93a652a7ae531110e6e23340b64311c584263f2425aef4fa73ef808455688cf111ea17ea9ff5eea3aaf22cefab591dcc10167d9031659e9510c580b7ba675e75addd4ac4ad92b337ecb2024d1398a8933285da3affa4ae82f2ecc1add5881e42a9327c42be0f6e575d4d7c31a9257a7982dceede1e3cbd39b2808b739269413e6e764619554ae0e069cd4c18b54ebc7146100d735afcdcfbc969488470c0e12ad4dd9806d12cff39d431e008658e5b10a1bd72106ee0042c3e738000f7d825e4d9f1addd2ed0c1cef0756a29ac3500ab0a6278252f00e8b6d9b40bbd9425ddc7602a1332e4540a637ab94cf245e0d7453fe6d0cb94cf2ca5a279a565827052d9bdfd0a0a99fdbaab8f7bcdb5b3a19d70c19f6d3a87b47d8414d9fc7d617e8c2b8644adfdd761784174f1e7248eb7f04b538dc35eca7afe3df9ee02b9c5758c2ff06eccb89a918f607609a944a72e8917118a1fe1cf16b8993589d89f99044a5eb68d2efdb1cfdb894a7af03e3a24a2f98ef9ff47ff5813d2a38e13b76d66e3075fb0944c71f5510dcc5224236a1d4530c5abd60d439eca82c788c2bd84ed5455c395bb14b18f90fb6e23c1eb4396319642cd0c13c6026942c62022fbb9c26f180cd283960466e5649a62bf965721fa5930e844aa151f96abb4ba1dae7ae1095cc42cde8badd8662a997d213b23044077d29093b8d0951808f3a7c9cc1d60459506717d6db29d6f85eba257d1a8a7c0fbf049722923f5c5eede2ae0c4a2e8bd8881dd0f08ddefe11cb645350d8fa807a97ccd21b61bb271998eeaf0b60be41036525dc97fc80d7a8c648caf700468ffe7720aa279d5c5c1403646dfb3b9e0f4326876bdc7a89ed3a54aaddd84242264c0f4cec48fca3cdf8f59b548b8eff1cb3f31405cf068e1e3bf9cf4e378adc0662fb447f73c008724e6f8e212f5e57311385247d07429659c71b7eb7d8f2311a5edf73e1498ebf216b2b1cdbc83a182726a5f086b82c1465bfb43b25104eb3c947072a884edf2b8cdfed8bc1546d6daa21c4907350924fe9b5454c5cc5da4349809faabc2920a2b5d39e8d7d4149b69b5731155edc00f1c0f9f227a5794e2d0e47f5da6247e12afc1bbb76e679d3fd5d92a8e94300eca12e75fbbd423aaf5187a37ebd0796d063bf58c9575cb380672d5acfa6c2bb242f7a78a67b785f8982d0ec337fa809becb0dd8534b36b1908c5f10adc3f988eeb43acae2e271ffef9811ced071aa3608b9f887594d44824137f3e26104a2f3c49728dba805d410dc64afdb4911b070e32d5bef14bc10520e354cc7fa2f35998dc82173229ee64606ecbc14a9bf3d614a4a773e492d27b2ee8d34a7a772eb53392161027ba1bdbf88760f3f427186ec53844a991f75fef3de31e2e041a485d7bd09c977bfc1b7cd20d356db265a4bf17edf03a1bae0bfedad9290eae53a4e8a67ef0b1cb03efc5f2f3077beef63ec1a03e7db55671f2d0231d24a41f523705fa9109514d9d807a197d09685327da1fa35234f68b8942fe991a1b8f2454fbd2e4e1196a0f37eba6d24729bb4b6d50442a978d4638288aac01ef36a8e7b8f6f7b199a953c8b4c4c497f8cd32f558b18c58f021fe5cfe61a19a47b5cc5eada8796f666387b4a978b46319fda2f768b1f6a107019ad7aa813253449c8e6a419d2fedf59db4b39d899bc948250944aa7a586263fc0c06956c9f205369bf85ea63dae27f04f8850cc399b7b8b232ba9dfc5b59fce0373789f3566fb8df2ad50bc2f975830b92851c01886b2e737ffcd5065fe439f18f0b251925a430b438b6f9497d93c6f5eca03f2ee720689e7a981f7e54ea0c62777a0129a4e71348561d9122048081f5ff8c4f076d16d386406ffa3af8f1c399c8535df945e9fe17caf64255d175fb109a978db8a63f825e312c318c6b0dc59c55044a80ca4ac0e1ca2a98b70d32101c9aad6f9ad52abd939cc387cd4e4cd775524c7a7bab8328ad2d8096ded7c278f71ae9fdb8ac00e265db358c3030cfda95b6967495ae6f6a2c35886964f83a042a9a2d549fecde7eb49b221a8cd0f34ef4691e186a63154e76c7b9f8d8a6e885a36f0cebb3250d3a0da49237eb6079e06c81f1a082ded2cedb36d505f27351031d6d9643e03b1b87b64766c5c8935f13aa1f795554f1b55b9295e7d2b3e18f1ee84595978b8d8abde40d32a8e81ca08cbe0b3b44c50d5198e76b09b82764feae609ac46129d222ff5b861a41137e88605953642183894d1b4ba6afa59d7c69592d0feee7a9a92348d5082de0c84336861a1f6bcb3ff7708aabaef25955fcedf1435aad33a83aa9d3bbfbdbc174d12141c51f7ca91e356c76c9870e4a32d41dd7915d6c21ce24f5f49c334591907561fa6bf6d47b5bb41c1a83d6eb1e823acef38833f0798599f693c6711c9f7adf2887a8d8a4c0e615968e3e2d86fb51e92277f674ab129415a9d5b11b20a51dff9598a25d8f4b5f4fe8e03895158269b154c0a169e3c90a655c92b8f6c48c763df4bd134a1d23293379d36c9513455db5395e684dc79c74907a02c9ddb0ae562e1a4e307399b965511e05fc7e88e3abc495fd42d6f61ac5d5937249f9a0380127db9cf8235afcbfa7e136f6ace515bb3041c9dc54fa9eab903862a2d5ae1c0a14d8466e58ee872b6e3c8e8e11d63d67308d001cccbd58601fb1fe7874b80b927e0e97122a9d8c62f193a110d1431b696d1fdbd2216f421bcaea463ba82c7c8d583ab9629868b962d3152136d420083abec0fbf4a0d16b9120ebea914dece3df525788b0a18b953434b5899b24a0c601254974c65fc1623fdf2c11c10991493eeca2e1a9da5d0ed107cbaaf0f71f6592588f31aecf8e98cf25ca746242439ce908752a49a20de527caac3c707eef57543f98cfcd692ac1d039e19d5a09b9ce03fb307f00229f96cc5316747e1eaf619304a6a502c4edc236e76138789fd75a9a993cb77e7df97f7f0b847c92e4be0380b6e94d02e641a1677198b4dddb79b3fff93401b5bb6b7514d15afa918aff2943276d98ad8c61af100629ee7c90abadf959677760cd866f8d6fb7528e93320ca0f99351c5f0fa3d589bd9185fb615d501aa22191a46ad0501f2cdf61c92ff4e549dccdc531b775589d39672a16a2884a1cae8fc12233264b60ee868b1fa550b5fd541ed37e970d9ad7347fb9e338960a40ad8211cea809ae3ce928b5a003a01c3e45e5397ed20c1560944660285edcd5d68f0f8c7590feb49a2516856fe0c2ee49c958f9e8b7ac0d03814dfab8477079cecab4310bf97fb0306efce6cd933fcf0543c72862848f7159ac74eb354ed6f747ff82b13e801d8a274e5e2bb4f327b4e0bfa72a1428bde3281e685b095bb7807904717fc5f86cb96b896c24fdd3062fdcfe9a94a4ec84289e44e0f51da86158ba8ef895054ef3e9b609c3174f0f40b50f122f7d1b0cb2a4d4f8e6d84d04d7ab363fb6638323cd11a48efec0efc47eb7bd6ab5e40bef4f4a7f7acef17d9b5eb47181f155428eda5738943900323f4640c2adaa231b0d290d3166cbef6ecefd78e4295c391f6e7c350ad0840dfe5842d66fe4ab9c251ed7aa6b93799f9c57dab554929f687e8315ac0d306d763457d04b0892e5fc5fca44a65dbd58225f2c8a778b22fb0b376e72114845cc32a6dcf5fe7bf08d522ec9012f4e6f2238b10f23276df884f9cc813b9591dbf51441f6938c695b1c529dcdd8673eac84a75df4c2818fc5b73c54ca30b1f6865fa434c2721571cc115f864525af71fa9a7435a7a2645bd1c1be9888de21b354f0809f2cc4fec623a9f5d9d552e32dd8b93ba66e8b62baf97302ab20b3489efde5ab2c204c5a7dcf9742132f9acaa5093b75d5d4b2148c873e72cc9838c6e79ebb909d9d8b07e93ed565f3ad13f4676df70cdb366cb6ad4ad9e180465b9bc207852592933870a4312f4be267cbeffa80709217e2914515d259ab3bc4554293dff34518ed301a964cbee5e0da5f38da3e8d734b79c89095f08d782e6dc376723c48f3d60893375210dcf810149ed90592eb20e954e862e93afa885194c35f845c47d56ce469f6ca72d0c3d2880d96da5979b5dd865384484acedb1bab199888fb8af337d4af221542e664c8ceae0c004bd4d3145270583b6b666f3f62f0a2c6b9381b1673e73b08ffc34a693e02ed21cf9250b12f1daa9f1ba541fef727606e24072118bf69287170b3a33dbcbdbc068b855a2e65fa2406b3314af6eadee0f3464cff2416b6529c684c93037e2a17d674a1b56e96cc03ff13dd75d1ef0cea3831f1509ba1fcc6c7729363e7594e19e486b49b737a40e603ab2ce28e0ed7f4616fb2e6105df369cdf5490db1f75b2445025b86db0fdb0cc22bf63b68967cb2bcf2a7b1132c461f058be9e59254e1b7f240d9fdb01a9408a9c5770deaf74ba74af642a506c1c958fc95d8ae2293c4c5134573de18693c8d16c3c5ce7023f921842672adcda4e5e3f926b40bf14808ad2bd8fa91b28b2a1dcd380e8f1e5a566c48d8293d90efadef5fb104294109c393373e77bee58a932ce30f7c7ec46f52ab228fdeb883765fbb61d98f1869768f244182d40a5eeca6eb32111b381c8c9c82495ecdd41d4a27ac29effc82562b41fa41b60294bab971853ee48da85ce2ba803ea6573d1047406964c3f8f79653adc8bef5c818ef50623f468720c9828ae7f8038aba74f77d65db2bcbed9e1f415ed8819689e37d050a57e624cb527792b8709a0c31f921aab8a6098c9d23a542574686b52cbb4ba7d0922f28d1816684cd2359351227b2ed1a9864db623d87036ba16abe2742b54bcb23ac4bf7a1ed529b8382b290e5b000cc0f9582fda44d7a389400a51c8ead0bfac541bf7c95263750184f5a78091a8248720d67213ea1aed2d5a08419ab31cdb8d8052ec04a3f6a11cd0f47f0cfed6e4fce7d6e56e0996d06c5739238a5a5d89908c4e66ebd9aad357220ef39032330b35d40b7a4ad7e6174865fe64636e9e6f15ef4d37b0f390c81df3999e0dd73f191f1088bbc74c6cb9a742276c9a7023147043c81d00b6d3b82845c45d267fac6121fbd77093f22eca95af3a364c7934da516f75605c1aeb92fe9c801c571a366843df64f2cd4ce30636b37295620b9f74ec966ab52bbe3cea589f3e95bc0161b3305753b8a0af49979cdc8ae2e50006377b81a0a9c4718025572675fcf68aae62cdc47c71b272cedeea9ccad80c1c705a43650492cba6aa50b3375fd578f3a822d051dca2030218c2a4cfb16065716be81f4d1613b8d006af780fa5de4c7248fcef3cad3a58f242d9f254fe5486abd2f4bac666c01e90e892ab937fe39c243776a3475ffac7f8f96d68d3ea093ca3c4646a6618c31bde5374bc64c7efc0995989ebcbe816be8b6a3b1a43cbb63be86ad279a7c30c57fba1c469ef65270f46440e7d5cece01381c735afcb544872dfa7c4e7216cefa56584797dfad0313e6574eb4e01acf34f8a6c4395db3dc1efec7cd7f2562b082203120ecb56d54910c91db6dccf41da71fa22e5a68f2ad2a946415747bd8f7c79b2a02c177f185c55f9c32cec441bc96b00c8d21e977c0206ae8aae2e4fc7f74a787d603e8468bc823d39f0d1851b5d10bdf5ba813e2e214517a10a00c7e34d372034c126876c94aba7d03ac13ac36de981ed0ed51b8710c02b9a3dd6423af828425307910e7d8a5133c0a21e2182cf37512710f31681d5007e879ad75f40ee9cc3a4c3a6fe33e933a652a72f023fcba97d7774d167ab4c04d4a4bbdb7e330d220d84f877d3f577c1d499bd1e6fb999799e5259ca39f39f2463d371c9b8083a26225abd7487dc2fb20e8cdeb37200de1b82002b39f0ff70bb078c919d6bde528b0eb785e35d884fdfeb5127aa2dfad66df8761e5faf2f7a07c597aa4c9ef901116d69d45cf3565159383c8dfdca0c320512ce612654351e4cc2c72e5dc148786b75230d6fd463ed2164cc7da95f32cd26dccf7df8d97983f93dfb0239ea736f32c65f6469b9877bca5c0b9882e7171ed41b1366a2a86988642ef1c0c47cac31ee6e9354d9757d3057c00157be6f98a3f9754cad44883946a6fad81a64bb5ac661b2280e49e9f95e09c5af94615fab511082b6465a73c021ccb64dd1ccda8fad72562fb6eb55f1eeb5b2dc0687375cad33bcd0d74daad4298b1c592b5a624b26c5e0dcab7d631e6b217fadc76cb8f2aaabd5e50f2b4a28bc2effe011374d32ad6f3f7674333803c9beb262b60b539fa190f7b477c07922d645baea18ccbb3c06b5690d38fb125fce9be0988104066c15c7ca93ecb52ab3e1f936c2454a2e26783f5e8175c101c921a546dd33adb20d9153bf6f1bf79c3c284331133c605320cf313db6d1274f093015941e70ce615f10458ba48a30544d6f44b62e2847045fdb51c784a37edbe4eaec58974d8768684285e49ac15a33fc0cacf23e5afaa2e04524b71b1bb8535e53872f59aa647d13297a2dfe305116e82f1c72d27036898d2b544d6bb7bcec44db12d45cc6ad030875b170e3266581e544b07c8893f7829ae448eb888458a1ab8314e38ea687ca817ae1a7f7b77267a5ba136b546d5440025a9269f16546077fe2bc158bc31c1f4f77c5cd0850338917c5683f67207840e80caf6fdbfda8ebe105dfbc37d868545a40b97882769791d39d5547277320448ceb05c8f3d91d2a437d92adad44b78cffb6e81263cc900d99f57a0f3520d8acc2d1ce4ebf8bd494e4c84cb17d87ecfbbd595296a00949979a509037ac20b694adea16ab8e095fe8a42b4d12a4ea677f5a9baf4ba7409710e55d723ee1220c75ccdccae4389e6b7899a59417fe746d3607a120f64e15a64a3b50ec4e53575d82d348f445f1d6c1bc4cb9a6d8994a44c400bea87891ac5da3aba7fcfed7bf78ac3e90ef91bf55dbb16691a30476a6382de3fde7b8e07458e3cb4c7ccf53a870677d17ffdaf4590444f2586eed1d1814ee03ea49b3825168ca030299681114e0b5fec1be8b5d4dba691911acf1cf1e494261514613dc9be675d9a53d7c8a9733b8895eb746a7707adad425776b2400e1cfae03dd9ce639d964782a7894372d58245ff37e49fc09f86ec157898a5c55cf7a1c3977da3490190c82d4d6a54ebaf006634234ff6ff8070a9a992298f2e3d9ea3a74df937ec5e7b8263484e9815d731ef0f5b2d6eaa8c8f6bd966e0828a34144799bd575c4b7e6d5aa057518f7689b19ba446691f7813608c49fb424e9d4bb040c2a72d015aec8e049a0f6c985cd89cd106959d1beabeddbdd4042d5933cbfdc035e9718c98a2b5eee9cf9350a7e71749f3100309d59c41153c435e7cc7391538fe549fb1ccac1cdf7ba1f4b03d62d883da32fad505b5e98bc6ceb89b447852fcf5b84d64046daf583f42f88df6c936300339a49d121cc6814f5268d30bf827da8e83ee4672877c9ada3417f3fd1acc1c2bcebc22d9623a27068b83719b71f86a242fef992894ee32f53d60ca000779145c5b9274027c39711b8b4c697e4bcaf7c588a9d688d25f6312b9ee9dacdd1a28d0bd45883bcd665810c19170d80a6517dfaa83e489e38f4e70d2e70e605d7ecbdb0fde1e34f4633cd67ce2a24d845b1fa063fa12e141b51521071b40f73f2422d93498a456554be6eddfe155bb50e145ad0e24173daa9ab3aa808e156056821804d4e9ddf501379cecd91a37de9e2822e8465fcfd3968039c9d7617f685d6b567e8331eb117bf05768196b4c1384744bdf11fb824ea241386b882aa5c2fea9ca93165d13539e080462e8dd7ed58ae577f7d109fa864bc958b80c62cd5446a0048193b63423028291dc40355e63030988af8298013205330e292108aab5b29a19a0b5aff56e8d71c55a604fccdbb78f0b16443f3a4ecf292c57d72a09786346c0def2d97b1968c7d8313da150becfc0fe7bc2777fde63b05da1eb7b7dbf07a6c88e94ba3a1f03025b8abe363733243480a63fc68e687cfbeae555da8767b127d7a2893aa1259b300edb46d53df4e7659418a556a52c5920109c9f320448afc6567ea2c496f7340876e99bccebcef40f7653a7f66e6a4c53b893fe5a2009406226d119f526a6fc15e1aea77e505f8d339e7c0cf4f5ccd1474be0b49b629e27b07d754a056ffa66d8392384854477622ec093c2d16a9f430048743763acc2235bca3dac5745ea0b5dc7990ec5225eaf13025aba88319b8917c00e7c965fda36716122173659fc954e104436f86d3acba2d0052edb0d3edb273f56ce0fc763da0dd818e066e461f39e33892c72ee57d709fa22610ff698985a1a1095bd2ddd7f106283bb1c3c063d3e75d52e487fb56a4e3f5b619db7cc165fda958e417e86fe04018d2fd5347addfe9495bc39c26ff88730aab36f53c95d93d99102d0462c1e2837c27a9b0f4a2c011c5ac55b63c5a70d55f257e1c00102c2026c1f92451dcf82fb3c512f01339ed129472b9eba077b35aeac2acba39df315ab46ad5ecfa8e5a658ec4d0691d2b1b9d8578a341de65e918ab7969246ed3e790fb3d7753bda3bb855f2a4d9eb42355d5c68fa928ee2f21690d384a72576cc5a6592e5ab629968deb8ae9299eef30e71f77d135e77053dc67166059d1dcae2e723c345ffa14e730cb6a18c1489d585e255e300374afb1e1e52f41fcf72b43152346770f28c5ca6c35aab04bddfdee2180b762a55182b18b7978ab942f989843305303722db875219f6b37360c5d5f4bca44bd8cd199f3248b9ee383105f82822af392fc5899b175e32c11e7cf8f1b29201940e26d9bb189dd8c46c7f37a3c2cdb94496cc166f86a4c8ce1f6a91f7b178571050cf74dab79250512f4a84eeefe96d85a97159602049f5ebbb8e5cbc15a89cfc241277ce10fd3e8ecfd8ff462c7c5ee7a7adf5ea57acbc3df8c80806661dd31927413f43cd8d84e6768d3b580be97e1137bdf79637c4e672684a73534c8752cda954e4d1ff352eb82409b14aa45b843399414aa2c8d3f5262565c59cc7fb26ffd88cfe82e764ade5f563db295962cc802ee3ecbae87d3266b915835ca38a00cf7d64e90b5103305b91ca9ac97a4e274327f7899540163db95952ecfd1e0fd8bb1969f52558327a93e48a5108ba76add9e94e20a5e2a69f19d192c2c6e840acbb4e3d84b4397759a7e6249e011316f76d9fe6a918bcb411d2b41b12df3e9e968f404c52385affe1025d32b530a0dd0d39c96fe17fb80a274ad549d2b69565352fe67a0e1cc3046c2f4799e360b554e519a2626fa29fd5b4e5613f0663a8f4b1a4286d80ec4838efda3cededb362de4b822a77eeb2f37b131a65e17a8b25e36343512286e864e68545746ce255cf4797d92658d67938f7484cd525fb4e5655692e70fd47088ab206cb071cb404460e22a611dd0a55501841daf09f2f7cc4fccc494029cb99ee54f78eb4d4489a6f098572b209f7bbd6a8698572b67b99626d5e081f1a2da858fc7003980a9b5fd2ec77f6c267d9c0dc23ff60f0aecf26751ef29cf65d8581206fcae001b5766c889e897218cd00b372d9bc00c66d5f2edc77bb1505b9050788d3f559107c4efca0f66b09b0c4410454668090aaa52e3a1a918457e0d465874789340c043b121f0adb07b02fbb6510f785b904758ae1e0c215fa40b9ba0f6ad7925dd69dd4c2a323374e9705cc28d65e968a18e04d2859ff82e759d782e80f600fa5afaa0ffe880b1484fe3d76fb75845eaae145eb57f633d5121d451b1728a69a9c5af05b439e133bb78f4b59304628102e95f05d6eb13d86660d4d92b2693ec518d4f24e69462116c39ed1caa37fb3ac88dbafc999ae7477069a755e2b1c00a00890b401b74619f5d114def3ab936b141edf19dab04b1f5e4a179ebfb9e20efe8cc679e0b9a499a20c06e366bd890a83673ebcd551b957ff936a7a3e36fa9cb1152fa10c1357a4bbe55b96f925949eaac849f515363155f6db5b68317ac83ebb0245891e936cb82a95a4ef75a1ecc0945829cd5ff654d7dbb97b583d92073890e82a1cee2e3ab77c1fbc14f6898c2e40b5e0d7b32f6cc28e51b5103d8c341c63a01b1ad6a431858ec1cc9d2c1fb93c541af46408be1ce1ca9eefb051ca708b3e9c54f8fa6a6bee5782043eabc72d5da51feb40c9a4a2cadb452fd0d36c93efa3538353cb11c35163e4f888300653ee9e65baee3842ca51a54d716c6000ea285175cc2d1710f7a7681c273c022aee162427bac6eab5a74b4e7a5629ecf42224c9618824ffbb6c05f61f534ce5e7e81db01ae6c6c6bde41f3afb0320eae94784d0c414738b8d34a43088115281d61cb62da069876980e31eba34442183578e00a47581ce3706640cff00322a8461865ce796d021b632265a879af27cc3a20c5ca908243521449643a78a41f721ceadddc731d7cf020e063898322769075ecd33a2c3154a701a5def543de939b43c9fae25880ed4aee9f37ca20e7382ad469b1e0981d4d44820ff8ba2569149d634b522c101630cb9ed80c17d8ba19804a392912f77d9b655cd5800dfe7c2c654cff4d85eb3f6ae3707cd52112cca670e1e44e5454ff71e865da547c91e50b317050aa0eecdf99bbd32cb97d6278d88a28af732aad02e31609bcc8ac93511f17f95070fc37aa7cfd3959769da931638300842cc5af97376faeedbb31b084d53401f55f64b7086531094b27c48ad0b115f0fc7d959b1aad516856f95dc56328609ad27542970e4af282a2f61f6c61ce69c545b471ed0eb041ae17e132f7565457e8498fbf38151296f96016682f0082e220ba5abb0ad8ca52b4766680915e205d1650fc50c6d49e221c0466fd643b42d8d6a953cc5e21d048171df599aaf542f542123b0876b620d46bab078e6a37f4b78efc621d578e20948cd20b3be2623bbbea0d23b141fa102beda7e8e9d0839d2f023bb9e1914c9d948d7ef0fc24ab504ff7477a34a96fc6e1537bc6ef55f27d16c6368ab5d5ee7baf994ecdff8dfe2bc37047131714e25544b864328dcbf92fbb02df76096290022fb461292d0f4d5a4366441e18e9a14663a3a7905d2bc41aecb4723a16ac95ee7d59a8e5fc27a1c5f4bb2ec455cd460fa4d66b969afd2f0b5f47a88bf03102a9a62c81f8ef1e566f76a371a29b8c37555e214107bc269e562a3be6a619a251e80aa37d1c38a98c3c37094dfa6abe3ec47a2bff90af5bd31f2ff3f09f3a511e9864419bf4e65b24ad192481e28cf5382561f7fa38bc4eb88277ce3c2ce13ca49203e6feae0f0bc5dce32e6f9d0830eb95a7e8f43921dd360bdb4ad3c9a3135c8ec7abca027bf3a81d9362d2636958dada1f680aa2f331ae60bd0ea70c47fad08269a001c0138a7c737736f6d922ee42f9a7e596f5dbcd2473e108515248ce9c145bdd5f9f0acbe52735eb53ab092b4cec5585736641df0a60c1cea49392ad29a34eafc2ee940c7d2188cae84bfe86dd965d2a679efafc4153d56135b01ccb9c6d9d30723b64d6a853e114f35a4fb3e000b33c11f7219c1bb869436d5af69da81f80814d76fe7f0c5fca346c39ac275a7fd31d298f32da0db543b302d4559eede2f7e60a5d2a423954af3c1dacc6a4f4e0954e37e1fd89fa101f722b4515fa9628415d97688ab1017788ece393ffbf7ffabd3f92db0ad9773d0ec3a4f0cbedc6e1513acf1743974cfa4fa90a9922249bb0b1bbb39c118b044454f3ad1d3a0ab774bf8c2b5a240b743e59534770ddab84191454f3a8fd320d7583b5732b4df32e06c216652613b62a1dcce0068adb139471c804184403b14984549e8f13e54a710924fe9374fbf158cbb00ff93b2a14085888873d3296731cd618930c83936ee610aefe6bd85601399d5b6d7f86bddc06b5b1fa10e785a01a2b8918aee9a6f582735754bd3d707c4946a153ab047e5e89ad969ee922fb55356dc9a04cda997c3b74f447cff8c1f5dbd52290c979ffbdcc58f61cb00dcba292582b3df0979d3a0de42b7417344ec426f4129538b0fd2585369a6c4c55a906501bf5ebf5881fcc9dced7da46b6e02cdd425b45b480ded9e024468136affe521a0054a6b2d2b729eead54be36f5b7ca2f417220ccf6a4f44d4a3fa2de432ec7d1036c7e2ee052852f6d6f3f96ff24189b95e2b75ba4559a2c5fc3ffa13a9c3669a9981a625e0dfb608c14e722d7261c07cf6954b81a91ca482a234746a74cd70511b825f1a0bdd9ea4a2542f2625b3a509c273d7b731e77874b1f13a8460e72a69faea0197d0d5d5ed5b438db26aa7d8733af50e39b2c70089b8a9eecb64ba2b43c03bac29bd06c38e5cb9cf68b7571beaf8dff317194f2fca4927c933a4edebeca13a04b7329c759a5cc1377e7433d9d9b9f146dc435e749141173c1c3151ba17c07ada58e81876332fd13d055eef69b415ac3044d8cd3477e8cb2462b356a890be8d8779228078e2c5a383db483dfd7c6d00f0ab56c09860b9742ba8432ce6136634034fa0cc8e0adac49a90dc65c2e65d2db22894480aaa79763da47d231b7db3d32b29253ca247fbc9e79ff5b4bcead3fe2dbb4a52f8fd8248801f300a4eb1e51fa0688d0ebdf256938b8e2a7d91a0fdb992a9040a2c44a01d1ab23778ef4adf57bb87e1e92160de955d63130ede951632bebe2c5b06547b1bdf19d3713592511d312c54644d8fc2ab932aab9520e231cf1cb27c3e89c7ae3e0c20710a3b714cfcaf95201c5fd098eab2f5614b29238da7ba800fa3497cb66ab5eb6b75b7c02ac2588850a45841f97f5a64b19a45760657ae049040296272bb09e23e87c140543f7b8a4d60a529a51220df11e91fdfc1af002b12efce7b9644376f81e4e94dbb4235d614fce00dc3fc299aef5b940b75290b37b44c34cd2da3738234fc0b20e854100fd1bef48cb9744699af523a2f5144d66d50af156d92384167ea8ffcd787e1ec1b6f5cf7df126fd91e1b4e585c12373fd325e03bbb7190e9ad4e0c72703a68b68271defcfd9677b23a166d8c5776b027e2d5ed02535c942be13dac3a7d47ea7c47bf3c3fd8b106c6bcca427d33e9f595117e0959e0d161270af9132dfef909ac73c13a8fb8bed47b81dd9f3f2d8e9f15d6a1b70654c5033a1c55ad6f5ef997994d3de619393491b6cccfe6ec2b57e9c2fb272aee196dd7f22e93b99c863df54403fbb3e27d37a690509b28035b554e648da7c33151fdb5438ffc63cea2bf246910eaf0e7b4cc88b49a99fbe00b195857ac0e129c530a377cc80ac974c74b83e3913da4066809261a5e299433f05dc1e7923093e7f8d29fee14f9006e489dfad5261986b6b25892ba0aa7312dc2b09415b5c4240cb05d620e36ed118ffbfb7c33191306a96d5771ba3c53b94d4408e44222f4a2987803e1f2e6f6e45af1b326f8d6ca77bed58f5f298fec58a7c95bc55b090f95fee694081fb536004b87eda39e5335896d8837f8134379cfeeab19b94d1da87f18d1fea951b53fa834e22e8cbf4788cd6a4480ead97250c9ff94e4dbe6d2989d3f7c9030f51beffb77dfc34691a41fff28718971eb11241795a55b4449a5eaac0f778191f7e6671662701284d9fb2d1b672a17adf8f0b325b78580f2444a84fb2229856a08f5dbf9322c554652c472af56186ad44d9f6f5b0c1359d1c6d58bec2ed66a590e9722af0e2eb8534fbb20027e48938b3b053aa5733d2f5e7e68286d5070e9b86ad911eaf8610df35c159332fefe83b18de39aed770859b1b86fcbe3bce19e14a480006b5611d98fefb5ef8f9e7d9b3521d382e375036b30ce9329529b2c011a9828f0e2b17ca5992706f440e076dfd2cc141e3ac2070ff416bbac3b64c39586f4ad65cd9d90329115c4857bdad488267b16e0420ee3c614be0b688236204bfae1a628ca70f5f278a9bdf1a781425f19c92cc873413f1db021648e1ec950a809c0cc8e58b1f22e5896145002e3e7490ac94dea751ed1fdc1ffe4d0d3bbdc5e5a63fae6762e9cbb2702ad62c5bcfbcd0275df23410bd8c5ffe5f2a4f97fe98b8f8e8856588097f04c792af45db8b253cf2cf06d2e33103aebcb893caf345c8b90d99278ebcc5f38ee0b03b8c78703db3054118db82421df9b57a950e57b930b058970c77a8769a0b6fe11b9aa72fe68a80f45f001e554070a4a93e57feb6a10df68fe0839b67d6a49a9005ca84d753a761d2b653e6b4aa93628be0af0019c71d4ea2a6aa5777e8dbfaf8c685c261c318c49b5a63ca5db3b10544371c4e6f26936de4e7c90487472b4c645903751f6ef8f6894c587da5d8fbf2b5a28946601feadbc986dd8a6b8bb6f7a66af8fcd635d717bf51c3118b59fb93081cb23f90ea6113e67a1862810e7faa88bb8adf9a3420800c52969d6eb0dace5bf08091ec91855500f6b2b4a0944e62db48ea660bcabac290163fe8783ec1d8b3bbafecaa9a3d1e701cffff9ba6f6218a13a5bf0a15834876bc7556cafb4a9d139d6e95ef58fef0397b9e0233098e9418ed85560bd6690a19483e2af3b3b7125a7b2287e790e05af50b42a4fcd8d9a12166d257af7c3abd6b2c68308c824df3eb9ba69e2da4e2eb0555af20f85be582d761778f92c40cdad161e89d0d682916b21bb305e5418e015f5cb6c06ed8edf466f5470c3e38ac21b9868ca9af622cfa6cb16818bd23cf28720d534255bf1eb29c43e3c81b61493299b73acb33d06c14be46e43ec8d2925fc44cbfb40cdf4d45d2a10cd6b9e889f8fcb13c045be5c9e3dfc11f0a2a465839ad7a0a415c2c30c3af27670b126e782f2b9dcb46880f27a43625cf87455c5698edf8bf31039354d86ba908a5ca151a6c52188dd9ef4133e3fff4f8edb473146ca5c67ac9985720115cf853d7b185b12da78335876a854fcabf7f233e740857349be3a8a39649e6640f3d7c7ce7b1cde3a1a27a98cfd91b37edecee14c058f4c0552aae300133b1c6642b1bc06ddb77cf77774104f0b1efb892f9ce0ca69510229708223dfe994edde5b792d5d960f8dce8e02eb7d6844d2dc51d157d5d63f751a97c519f3858d8cf1aa125b43e5d23c9607f1986187d7d583a97bdd28e1887d3d49abac8e2191ffeca0609aff1877514b905e7a8e6a989560abda529a4dc48e26faed7b2fef60fc823b92d9705fce99baad49ab95dfb85f1dd3474b3c92231cfbeb9bed3d780a42fbcfb222dccc7ed8bf02ee691fbe48d754a9f6bc1677feef36dfe184f8c68919ab728bcde8fefcdb441cb24ad1b54449513b6f87dc91cc3b0ed00ff2123d12a54c913d3fd02178e160f5ab56aee87b622ad99362d7a37672f319197bfcf45e97a20091ff72e19c0242992bce3ab55517c8fe94df26d1b16ac8dbc764bd9c0d5322cfebc20f2c375705c1e02c6337c09b6d032cbafeb30acf05b398ae1239ec192d8a3f49f3f48f0c7c64d032b6b7c49e6fd3cb01e0b0ad634cc35c729d59bd224f81cb342a6f58e6eeea903ca71b992bf38147814839034aa0290dc9bc5f9edfd8a42106ef7fab25cee24aa01d0ab9ecec620474c054247502f788913bead3d2559eaf79547205dec18e8050c01bab45c3fa01e8bbd94ee39e7e4111e10aa0f088b83a0530d78e9af5e7f897c8b75a87094692a798731dda56d6db32cc6437f717930b823c93b0bb54fa4eda11f68ac1c8511d85c3ab85025f800cf6f1b30bd6b0698d32e7953ccc8df96deee47eab0d973b75f6ee1dda4d12ca65bf577d64243aa96fa4a23b0aab424ccabf9181f8fc796477e1bf518361a705f44c0997423dc4178b3e5177e01b61ee934153e72843f90e0cb038841461ee0a9dd1c4b6a5865f994e0ed4e8ef17f3ae6dd81618362553ec4c82e79e9cd6a28dcc08b01c12021edb0de622ec517e3188759c009cf39c99dce9f198c97ecc5c178e831ed2bc14c42f5a4448b346538e38d3af1c63c717fed3abcde5249777ca524d63c555357a55306b83cbcf161ba9c8cc40c9e7c8c56cf37c86063f7701728f744764c9ac4a02c73daab6f9d778334fc7436853c51696c92493f69713518508d814c3e4b9031abfbf6f00db522e534e27bc70cc6e898d0d38b4576b94f000f4f150c1b8d947092d6c10f4d019e23f4a7e7650eadd991041e3363cd35890b8e22d72be8b3b9c038b4012197e9ef68df121242ba4c08cb824dfb28174d3e243ff0034eff232bf05c5426bb9f953a854acda19e99f33dfe5638d54b6b16670c19db4dccea85bdfcfb4b8687f81ce873ed64d3e3e1f4c2ea0df642f578abf6cc4e4cb4a71b5bbc11a7aea5257b05ed844d4977c643ea7723625079a5878c830f172e87ec0c4331966e6d4c59ef9815ddd9bbcd561f71a8f70ae4fd8daf4467cdc710911c30d4f1948e7076761699664e7eeec0431925cbd78c6cd170f33e022dcf147093e871f4a50bb234d800a2f27b7cc29df3a2ef92d4879d4697c567a0a9defa65f31baf3a7bf8207e436394dbcfe2ae6b76f741a2cba489fc5bd48427bbf6a24c4fef78ae5b3ddf9b425c529753e4ef7a9545b65af10b964fb6a9e7913f22ecd3cab772bdbe28c05e73acfecf73b000cada683b9615447a54839771794c42fe7c5d9964e4bedea74d2f64f2bb4b343a9df2bf9ad1c9f34e938e4aadfc9ef13cd39ead8555b5c998938d545fa9b7aa168beeca7a2ea41cc883bd110bfbff34276251b3503037a9fba98d8a633187a9ad00340ea3bb84e5663ddbe85a0dd588410148b3b9ba87cd0c744804d645735f884314b88f5beee86f9d8d371c20e293a8ab3b2d236309dad668ae4174392efb181e9bd5c6cfc5d7b53e73a0c687f0f76044cad80b030b324e7146f3e1bc792e609146482ae796976a4c1d67dcf3c354e07e31668584a9cf38f483780f1e99da5fc0b501e16b2f8a04c1abfea1dc92b3a9094c7591fe0cb277b6984c7832c6a875dcdb96a7355ed51946ee848673bb6fa3dee32b2b57de8460b0323fea9d4ec49d96da198df3bea137496f05dd5a0e4d37a9216e95b3df9e37285d6de053ce093034b68c1374bec1a879e090cd6c72efd345e411bbe56a6573df724334d264b267cc6aa09130034746351e4a303157ad80aad83e2bec2ac64c9f4b2c76f9d5eb00376b0804ff123d3f79549239dce5bd88b5eacf3c46633faa89815b7adc3a9735d62879d189062c5bb51b6570db95bace9ff871b12f5b9038a675a61b2205ecd2ffdbcda62e6d0a5f9010ca25747b0a3ae540ccfbe3d4dc2a0ab13ea6736c9243062afb210814cab29dd2ce929ce27bc5c0bd812549edd07ea62454b935974d4488c453f721cf700c08a10e37255f545529b0265ed388524fb7f86a4f1a2f8b8d110ff520da45642c54d7aefdadf14987d1479a95b11a528197bb7e3bfb137af6351d4baa30438e4dc9ed9dcf425488c108f4f0c4cb137e66fc18fa55f190785776a0b355f903669d96b4683b39093a6d9c77fd3917f5092734b6f1a9a561c9dcb0c7b9291f0a178d4164a5beec174378015a49b933614b2e8861e1e148d637a4f97195446a8f61972b67801e1adcf79cad37f21001ba5b31bc0e44fcfebdfa32ae9b7a7dec4ec3b8e5092afc64fc1563fef7adf69ca5805569c888a558336647ef32e7d4cfdc9a2336172bcce3a5230d6d02e11c82e3eefb274bf6fc7ba79767086f1a34a50856e8a7fb4e8f20c205c6cfbcbd0290a27ebaa76c8192bb28732725852f4e0b5e685ea9ce22b10620ffce58c2a6db3936fa59b54473b58c3eb1c373e0aa790b7d9f9f41abc80e3bc62b583bd29aa81efc7c30586709e6b9f38ebd5e03dd83c35814a2bec905e1354fe364ab8009f9568e75dbe58222af10f794ffde0458fdaa7ebb97354c6f02d5e8d5a8be02c9273b507727dbd04975897f9c8e234b13a70e22465db48d364404bdd4aef5d54f6cc6cffe2cf70663c747c75284b14b1516377b5a8d67e29d3139d24a5382134a962341d43230c66f608e934d6b284e8d3988b5f43437e7d329c40cd405c44e9048e003ff73d4aca4c9fe4c053e888dd38fcfa3d2d6a88f0397595f32c6e18b88ab8663857f5c41e93ad3a1df6e27e6d0292e478dc6f8e10187ba2262fcc156affdeb39d3c600b578656eb6ff5faa86e15fbaa91cf57ad561a9d0eba6337cc7e3c366e9092c36457a57926da1bdeb3b122708f19991feea6c13b147a451df681a071fbf2c41de91f865d4049fe3dd29c98c8e4d2ce9dfd3b294c8017acde5aa643979784e1566d7221ff7acae71d8667813013e6ac617d63bbc77872e2956c418f1a10ca7593238299f24bdb9fbb5c8ebe205641e75d0e8b85b11b6dc57e0be057ba8ace9e612844bff75d973e7c632e57b2283e4c7a6086ea31fb037c8369653c8513aa0830d9cab47fce14ee966b520bd5286425e161f6cc7fce0da2b1351118a13c394775af0aaa58483b14493728ddfaaee96f49804869a26cdbdcd23baac7f9ff820faf588f73a8857b938639023feabbb2aae1953c4909a64497fa1209801a498a51074c95cf77579df848a31865fc394f30bf68dff472284cfe2f0b043fc52fb9f0e927636e7b5fbce922a16b96983bd2b95d51017779fd6f31d44e77b0cf6b5a8f9ed5986e0efa3e961a6e9c91ef590e52afdc2e942f57b957fe40ef421d77d04765bbd795a703e0530f2f34020ef643365f6212fcfd112a29be6f9ae54d87d71960386f2baf4b91703eca61f74000f9d8518d7cecb80b95dfd0818923a5f256d3bc881fdc335f0a112bb7fd9f160fbd91c1536dc7b12a4ce77101398a31755da91f9a2b9871cc55759800d0aab556560ac3051c6a1e969704a12ac2072bebf0f115d10a3f825a8fc4dc700f3d998ab311e4a2f38402c2350910d9125b9e5833d1103ab53638393f15f3cfe00f92ed621d9b77bd9c026233649ce924c6aaa6bbc174626f84a0524a3380e9e2cd9c0f6cf8fb8a38f76affff10afea89d9746a6febebf70ad7aaac1cacebd33aa2d419863e22d4eb0cb7bf98738c40354ae8e187fab46ca5a2bb540a6c30b0bc1ad0670ed8f112740883d9ddc20407cfc560b5c49a43812a0615b8bd8f1aa79c7d9677a6823f8b8cc8e46ba08c158a5b826ee46406e21c2884b54938cc9dae1e6abd0d933681cb72a922c1945f434891e9529485d8a0f2d4a245be1888c635ed0041e0571c112edf7379657bd02edb3604623060b37d9be7499ed24f40e710cd742688987c3a629db429d739b36b503ba4c234e6d7769bcf11c6c1e3e0a0160b81b3972c6364a95722e381144980d1df9040c9f9e198cde30cc19023179edfbb21130e8d93d54a147cf245bb01b56bc9651ba14330f3d57fb26d727df6cc4c9dc492feee249ec295c7a04d8b1576846b29ea80d17e6afefd4c005a18746c5cc8a436ef3aed4700ad55045c396b585472f724970be262c4259935da85bfc40d60d0a93a89bb5e7946d342913d86c3b81390b944021e7d4a280bbd3ec45434fbc6da17c3f6f76c34e3360d536cd97a1e8bdebbac9d7b17c3f2aee0a2c0db0fed3dbda8281d5fbc48c31dbf3788c9284d11ce5c1c89849e01395d540bc5b3d899c68157c44456a1e34a57a87c2009724f149993187c1d7867081384777b2a32da95939e6f3d189f1c9d7152b269bda393c04c2063c268d29d8a7a957e1fbd80417cb85e38767a853527a998b913aae8e0411e16fec0a8faf4fe136e278edaa595f3534586911143fbdc4a5c040067d5b2ecab2542ee80896dd144126c904a1766822a02d6ac22c299c9bd292ca3aede53db7094e2cba2821684d0b5f4ae581b3f9badc13e7233c6210ee0c251e86f62db001a90749bf9c4580316a29caa3cc195423bcf0b4cafc8c4af0af6771ffd7513b31dd89ef8c772485dfb41686f92cd3941df273a293bd6010509fcffe3cee99c26744d2382fa0a9740aabc6635e31dd48bd440a968746e5f97b67c3f41c7e35283e520f1e50c4560d917089f4abe120f85417f1c602e1e4af8d1db73d23d691e2b1f93a14b3e2df815b906253b64ddf31262e823e752196ba2071ea22a448f9f8addd05db9fa0153c6c274fc4a485bc0e5796dd1e1e5fb82a2cd3c88c6ccc194ebf0ea867c88db2da0443a731e23fceb8eb084084bdf1b9785f0ca607bdef3b3c28f78e55e28efbc95b8693348c877427269fd7b6321730ac393dc95ecc23c9cc37175399d2d8602e6556b97e426d6da4f1bafdf7eb280813e01f968e9cee7cd9dcc389831d44289c22c4bbc2e04429a506564971111e9285b3edd0e102b1dd6d20e65c73d442677cd32c8a422fdc2407d27ee92398966981b5617e49029e992c0daff96202e163e19f38c19b5da56de7f2b3e855ffc1dde515b9722ada399274ede13d5a6956cf7837749de6a322a86a6e8cbccc5ecdb3adfacbea8d455907b87d466f6a6c2fead2fdbae7eac3490dfe78e7315f26cbf575dff2eca2bb9e6c40cf1bd93e682f5a4127abb1e825f1bb166ca80df9616d22406d28ef5bb20a833feca0bd92c3dcf8530178f8acded12f9754eb570f236ff7aeedf620b491052f6d4d9d2c61fdde387034f8baf80fdd985d57bdad5ae393c2114983992fe4de81a37cce1b5b6e5d03d850def948f068b4d27fe6767131bb60129922facad0ecbdc8e7df91954e7c30907b7503a8b35fe220c6ecea5e0f524e6bacf445ad4fef7a31a6921d211ad16639cbc34bb2a2c2e28bf82d40db44875563767f7feee50f5c16b0cc79fb9015b66d648bffb3fa72f62b940fa6ad888e9dcbe9e455fc614682cbacbd91aaf5fb95e4d0d76117c631d9b4a15ad28f1130b05a7a853fe2e64d4f4e51248d1d09685422cdf4e110fafd8732f2f809589696d7351615257051a60e0f9cf3f240eaa87bcd3a5b8a258b1b19eb4b568dfbba5e14018b120b0f01f0e786b93497d0ef674d1f2d5e5dcc32955ee85473ccac9e13dfd3fbca84926d48c984e9f41e5179add983d1a70653c5eefcb1b12612ef302e610cd4a637e946f6223fb2603f49e6bccf10fc47abe43842fa0ca449008abab34c897e74b49cb6cba57048601199537ada51a6a458693fefc5b75d58dbd4988bbd492f500f7d00bdfd342d820a1471f23ee14815d56b5d7c6239f0f0f70f1517c7a8b36de07f6c62427b04e059f9dfb65d626bc0a6ed58807b00b2241e1da33e855640f456082637153d49321cc2e6eb85560d357f4c42b62e88a1b281194a211bd11f331360349549fc9a3b1f36d58f8876ab841f8bc233b85c6c94214509fc2fd5d98a763c1c62eba0a87980a02f63f401a36fde197e3dfd08f62cace04f0287f06ee830a9424d6166d1d07992bfcfd4f91e02daf2869e95697b430d569575f9158b6bbbe1046a08e40e19fb1bdc9a70e5ddb5f3012b2b199598c84de4c3ebe60207afa6f2f500a15e3950ad5435c89adc8b3a2634f56b1458f1498cc9b811c4dcac8abe738f954f45b0016d7300d62dc1f2bec0817a05589e78e5f0b7b3d9c73094ed3205ec6ddeeed09596464328730795d7eaf102138e70ded3ab4ecada677ea7f6be7eccfe1fa37e0712ab605c0802745d5c2f61bd4f720bc12c5ecf3c680968c59b8abd8bbddba0cb6f0c52cd7bc28f5ffc813cfaedaf7f2b259783be66244cf89f40fabd80168de87e408f939d42c1f9afcb4e638bd751029eba4ae6e07621b196310ecad95189e7c7053314e2f2b433451a1d70ea7589a283f25830d373beca7378c43c30b38e40ba92e4bc101085a1496fa63e0226eefda58109c33f90624fb40fa34db777abad28eab975994d30c86e9ebcde7ea6c3febb66d5620564d6d8a88a2162de3dfd07d69bd993eb5cb5b65fe3f6e1344848728df60be3baf1b7638cee8e02642ad3ea8294eb166df35a09703cd8e1ca7103b1c59d9293ba7a9548eac974c833e2256cc5fe8af0b333c9db1c1f2d351bc8f280e4ab9fe42fd48ba1a9ee60009cb68190100604c2fe1015426666bc3aaf26f8e8d5922ca44c26d81af0f2a703455e52acd24a3f9bd93b912bd80b9238c9798ae9aeaa50f38858aa40840a4ed65cf9bf75b7d0d56c07a68781cf93e75baa5b5053cb5d03944778d9dd74eeb372d0a88fdcfb211c3447628518a1b4cc15968006ed432d1341c259f8976d6168d95bb9e4bc6f03efd198ae5b19419d4f65b43f8d3a914a7bdd2d55edd316772a7e00df0438e0b7710fdc747c023d389ec8a8fd280c9ee35921ff155763b0e6267be4ff5b94a0981705cc1d6580addd78e711e88eb37aeea20afe2cdb4801e2be2db3c999450e44d5b361c08fb76ca4aa7cd27e1cc1b81e354cfb99c53e064bb50ce337174350a54fb55ba7752f17908c2d2859e82b054376d4bcf95f10dc8fbd5ef316f8e04430ee50ed489ca8070d24cc9ea689e1c8b9a5c0ecbc5024940e5ef6b83994151b7c333779b80ffbe5268cdf5c159369ae3e8bbd6251b1f939cf45028ab2997253e1c5394048cee1d0be4eef1e6e1a0083312b8c157484591898ff201b87eb7811463f96b8bf4d5cfc835960db71ee61482ef550460c7eefba06cd3d6f445358719a4fe9d9d4f0fd036069afe2eb15979d59c8d54077ab7fe0158de7408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Factorial, "2710", "0", "46ab3ae48966202d0fde097bfa88fadc512ae8afc0ea1d1d376a4109f10105e9e21f1e907151e85f926b8d82737b9030d572715fa32690be8dd16867f348b981683cda4be4f9e259977e69c16905ecee567d26742c1ba1cdfdd1274a067c3b39020f8d500f1199aa73884607e93fe423a99f3646585b76278922e3583c349cd3368417a0e630a075839ec290393d2f669d948980b23bb114fac5d62ac52e9883c9e3b8e0cd6bf0df411911f40d9f968f8691630a6033e9972c3090ed2c0ecb3a3d8ace0be058877cbb7e2bb8e9065af1d1eed955881cfa5ab0a4e155f84311203ba7489fdf5d08cac67c97920e676fd54a972b0297285841d9ee665dfff40bf3f162cc2a4ac74be168d996eadc9fe38b406af8f23cad528527097e4247c49d52aea83abfd77472110ad2dca4c977e104e041386a942d62e362e968b12bfc2549a5a3cefe5bb6b799e97d12f047aab8e219751f940689c3278e3e64583fbc3ad07d44745bf43feb42a8b7a860906dd98a5eae125fe7f3a013383b23331796878a2936e276a021f2fae759567bc8a261a4f1b8967ca3dea6d54ff6f97c97c791dcaeb6dbf4bde55bfaa1ceb679941675d1863a9a730e380099157bc0887a09e4b3d255dea2ce3fcbdaab5a783d0c60dceb7be6194d9ae7dcc515c4394cfa8b0fc765ddca6c64a5fe82883d6d2340f71ee3ca84f60339742b3ba82b5f05ecb540fd7e9a97c0a78e30f26307137efaa9aff7d462bc617e6ed6b9a9ec63728d4cd5b1a7f6fea10db84925e948df375d23ef6f7d912bf9c9af213874975b528b10fe2b791b39d1bf875d01a65b3c17d97ad2fd2eb5adc8a8a4b9516024e92a37ed14d6f087c5b99ac523e7f1157817eae88373990d19998b0a412e8add60b47f61ffcd2336bc3c137857c698be679024789ce95c19199b13a783f56a7e15ac38e63155a08337a9d4305cf94548f6788ba19af84e2c25578a346282e907c3380200a1acf5c43ef3b974da2a962acca9caeb1bf88e1c4d91d1f38164a360cb6f5fb48b8d18d9316023f1bfa0590c4a68a4fc49d4a17ac7d96dee097b3dc5c9e960636fc9a8c6220e8f3d6d0d7a79dd8861263a876b4b16b749c4ac6b4dc708d08f20acf42cbf98b7f4b9ece0f979d35f2c1dda29a8c313e23dddad30013aab39b415a058a2043350ddc2fe9ae3c66171fc1e8c54f59e53f734388a013b449ee0dd9b5eeeb432ecf6e60c14cde94916e0154a2baf84a3165a28ccbbceb5017504673bc32da530e90c8d074dc6f2071c36042d41f8decac8968a61445097cacf98fae342ecfaf7f567eb7ed8d11486c5c5290da57b6058d1799ce94330dae1e672954e134fde55d5629aed6f499ef81aa7c8dbac75ce7a391f23a0ea37cfc1509090e5d67b3989a6d01535e083b499bb51b2338f598ce2ad3f3fa614c2ca084442230989f8b464af87bf519287198f75949eacd7c245eb00f1fb2b055932fe4bc6eb0f7d6520030d93ee1feb0ee237a1114e6e60a49f3bf5fdff37c3a136ea5f9237d194efa6a7d551a64325d4708e784755cbeb0326b906df2161b5438ff1f91db3a60318be09b6c19ce0b8bc2f5a8d11f5dbe8f4a8c8ff47beb5cf58ebdaa03b69d29d6ff0c68115b753faf65deb98d2568867b18081532da2159c817d0def17c0edf7194300dc14f751694964043934a350eb0821a42f8a651e4b66fd78dca89c89d1f8d1c12f30a87f4307c58da161dd92214ec84fc4b2846f6e8265497ebd458c19832584fbf09437df477fde4dab76e8a5e45b78a23961a305d5351e0a9335cb4473d8b8b4e4b08094e93063792cc1364272cf4df8953cb07302dd1bcea4b8da10fedb4e201fd24fe4d51df15f9681fa9138784167981b3ec1f2d1ddf31e441cb7706b553053348e79670de2a3f361c84aca5ca4c582d19ddc3431961929f21ca5d5dbfbce6004da1e1f43d44273bc5e9f7ef49048bca2752a37c586aa46f75c3556e40eb317671ddac982869d64f56b2d43e249f75a9a6d1cbc653fd797b3cc455e0ed6a9b50a8c9520390b14938a545bf5345d6ad4e1866ad9e97d054508a6e427f008549813a94d979f5f23ba1f7978569f16a65fed6be7acbe5c98ade564e6aa6cc142fd7b66298c9d4c336521d324d5f077935cc1399d886cc10abdc65534915cd91cbc2dfb0306bf73d81f4ef0443e619e40b031ab33c9960553ea696def99741c478a0ca7fc5803e47bdf766bbf3013ea912fd3b0aa35d223ea524ed2ab1925719d95b9dd9091b328a2333f50ff66f3320fc45a88855f82cafdcfab6d5a63249080e513974003149b5ec731740ce5b0479092eedb086fc3d31aba7ab3abaad48605e37d5e82ad82f3fb34d97be49437a7349671b730ce1c8be8b4b7ae36323c240efbbf98ec3a90e2ef496e4e1e1b028db99bfa5a8933499205543522715230a86afda04348d7e8b7702d15dd2bd96d7c379c507a0413d4e9f5878b55fea0b08aaddc25b4f42a76d3ae788f6ea6daa6bb7c3bdffede9016fecb1c11759f061784127c7da411a7da6515a8fc32d60a9bc91bba213bc7c6de230ca5ff5eb23a759fd2876817c42ac700b938fca3d0cf04537858c05552d15a90b8097f9dabfab959360f0b28e3709610060f4df935282a025b0d61c503220b69582beaeeab70843c2c59585d8b8c705975064c26d6540afd294b4b4a05a9053d0917b0fcdbbe6b85f70bfc801758222402f44303d562a841ea945c7bd52c464942738dff502183b9968fdee9c14f72f1143f2ddb48c372aaa8301e89ec506ca67b412548375a53844742fb70fca23796e3ddaf1b0472cf2addb4ef0abe6691e00bc11b637e5e819895deb4bd02431785ee0286f544578371e9829993524d558886c6607986e7b9f113ec7068998a173bf8b045b0585d065aca7d20d71b238215c7dff981310e21c6ebb4753b34b506776967a0234c1efdf988f4028e015c6260be9a69d8330f71081a36447faf7ea5ed5f9fab1255e4ac5b935ff77a58aacc24ea6a3881b75137377df9734ad197b9e4db8dfc6e4bb56ef57b13c196e064b34e4e53c0dd3986a2238965b1fbae3d2cbdd5f25f6060f48867b89e848bbe0f58a103c496697c07e6eb15cd1aa946ed19b79b178345db2b04150a73d0adec11c73675a7aba51582b460d89bc5a32aaed5694540ec894a9a574588dc97fa84bbdc03183b7172dd380ffef0d87fa96d1048d475f8008d8ae72484a9bfd04f8863844365d014ff0acda7af8f8ad80bdf7289abbddb4c7f6aa33063c758638afe3c0c92f4502c32b41c5b0dd556590cc4823805ca76f6a98c675bedcbe801ad0d8eda46a842235096235d29d11b2528e5f135cee19fc318889d0aa32985fd15c2fb32df392767fc3c50f2f793432a07ffee46fd84e98cb1b3ea2cfc39feab6f285429be0378694a3100cc79e3736bf815df3941133f752bb1f004dc2219c303301a2a8cf82c082563d4a93c9ddb1f9dc81d48020c8c012e9b1428e2b1df6086c2652801ed0df764ec439939843af56d9b57aaf5b3d271114be8625cc012196e0a212e84731f510fbc65709c29ec95271a562d8a0b29792e304558ca06875505c13413a6408fefebc8af202e1749abf62fecd8c7aa9fd2645e8b9a5984c42a99fade37e44f25e5fc8bf9642e1a87e0307ef779cb8e9e78459563e96feb51826391b1904277fe8f817ad0b01d6f8c76658843d4465bdb034ab84497ec0bc0e10ed700c01c51283fabcb3337f977035f5678dea02687ab0e6bc300111f788db415d4fca2d74aa8e5a1fbf7173cd4b6ff754a87cfaafeab973ecc0234bdeee4f15f8209f029d9e92d9040650c7c974e033c1a27c94e13bc7dcf16c9968b12ff921eb40124abdc99bdf9790eb802aaf89dafff148ec9d85d7ec90130bacf688e47bb631b69bb7a26fba906867cf665df8e8b0f4f5fb5f52607f07843a02ec44c88adc563724cf225e831169d7f1aacdb203faccbc589c3ee39235b246758319185a16c729bbceec30eac34c5b6c14b20d9ee7253c43c8925b5b04580a50ac16ece44329c369bbef09138186d0f5d866c93445e8fea018618ddff8024fac522a6e2aca986eb7c2a4fc9a7a76694ff136124eeae14c33413457063f7187fb4a95aad2b901aa5a37b08eb3d08e6404f27e04ca044d6ea1880a06596015213ab62eaead531c16a25b470f10f5bff2f5ceae0dc455d8d0b16a320b3fd1c43e4d23b77a1538e44f085293aed9bf9ee0f09a3a9dab49fd884760ac4838d644fdcaae3d43e3dac8cfe109d061052030c21eea94fdfda541af578bcd7177df332e2d6a5c24930548679a9b7991049d33249fa188e5d48b7aadb2081453f9cdfd633789f5f8508d0584c2d99876c913ead946c9c7f927b541e26ed87c9aaecbb147245e09062678eb4feab8913fe570b3b59fda8aae679129cedada0e258d697ba4a44676dc457998321f2e99bb24957433f4de842ebdc3b29c00691ff56c0293a15dc05e72c01dbbd1e836fa990e83820f4ab1800e0864fc430229baf0593c9690b935dd19958c1ec1372479dd89e738f553a994003c0d716d0cf6ee13bf24f9ebbfac05226105f210e230f75a60c919c0cd358b08ff280b85a259a68d916b507f0ac6c11b4f13e3bf70a2e0be9502030e308a12f3e42065e0d119fa7ad365df0d40240e04449f3618a64750d7be318122d0a58d943dddd57d1b95da2e6c42d955d0589d35a5c912718d79fc98e451b51271163026139d57b534d2f847e766999e69e0b5724b7ccb665d10c3cd8fdd3f56ba2adf83ad11cb7debbb8f699e432fe89b97abb7dbdc7877616d2a6dcadf6b5a1918479bb0bacf2717aab4ed45a77be27ae4d07d934a0e805f43b961c70545aba66e40b463104168d693f87418905ceab9b9433455564d4cc6eadb867cdc3008fb5554fcb9f254947b6b6fe2dd03a499eac56bb20275bef9b4e680a5fd9664a61177ab24588bdb131134cd3cc919614459796f2a387f903cff1a7cd91d31ad12deabd1081f116891dabc228a2cd7c2684aaedb49aa19cff2a68af4b08bdccc7417d44233884d68e47d27986c381b8fa4346906363e21e0e403e35f17b109b085b45c8ce32ca30f20d31c71050304b5be00617fdfce24d273a9b88e37fa9d2a30705387747fbf1e2ad21130ea10c652ec3a08b9414562b3b6aab2e2255e86d7125d063517441df00e4c2d44528ef32fca26c30a3743488691ee3a4ea4d3ff747c62a43d78912a13bc778943b31d154a4167b6b1cd0a826633ed39496d3d773b0c6869acd6384c4f31c531288ff5a46656bb33ea9122b269c4fcc9ca7b8cea33025f62703fe5cfe21a7f2c1e7346392d06e8562e8d119192a73f20fa7b458f30900f277c49ec0b0ffa82e158c5600a655b2863a74d24a245ac7c1be0bf0e3cc9ee15eef5ff6e4202fb837005cce72d678dc38d41cd04f5224ca9b7e15d640e2ddde831da01f70f79c38f865cfd1d0ec1fe9dba06085ef99f55571fd236a4d5a4021186a2d7c493d97ff957e2d006572f31932f324a4e49dbf63e306dcc8ac43aec139d505f3e0f815b9ef2be2340d3aad5e80ad1881fd1d28237cd2f40cc92106e607cfca4176543bd4bd5108e47bdf33383dc72f3c18e59fe5e6fa6a5d364a3d882b77deb70c8889fc9ae9f6c84bb6ecb1c2ee936c84b0785ac45d301b30cf5d4c438571a8d64849bbd99d934cf5b1561dc2bea6c2656eb3787f87ef872eaa59379faf661cffeb3988ea725eba5ad2433e43381eb052b20a1014a26aaf45d471722a632da82ce5f5063217353b6bb9b07aa657abf30f1557f2de74cc2916f4c44941942473afe31946d7f58999343e3a2661f2f22533b2deb5a1a04abd257c01038575dc79b29b7b7b8f265b0691fcb9bcbe1313206e0c95d22258d8f18bc01c9aa8c7f08cf3555ddeb3c06b30b9794d80a85518a84fe1a2d2845d66f0aec9c148dbcc2cf687b40e1abbb5d3edff42f4821fe73440f5412451c3f191ec8aea7953317cb4e0820322e5fc395abc83be3e85fae54ec77b1c7dc6278918c3bef9f9ebc4a46e1c5f68922044b50942eb00d981253a2eee3821954d534bb60dff4c7dfc6ea796ef28371db88303b23ae012eb85bd1fde4361782181cc57b18f95e841d87f31afed1ab5fd8562dfa2ddd54e0fd7344eb6120f767821decf414c8cf02293bd351d4f7b297a3b58c57bd8fb73705922bce5dd8d4c32fac0f06791c76d8a85e08d19bf3739cc6c62f77431b6f264d98c2a74a87f9c9519612ca28cedf14eabde3732b9fcb54befe49ded72691a9fe75e504f856441f7e55d4ff1f56d36774106acd0e7a7203704e4fe5ff1fb0b61ab765090001d92692884a41b3ec9d416f050e09ae9c277308ed872ad7fd6d13ac276c9c80ec92ca00fbeb3b8cbcb276224740bd1a49b456b6620eda9afd5f3c0d107377f5ad0dc2159796eb36480cf296bc6915c53d2d7dfd763e0ba0d24123e4093c7d5575c916cbb053356dd91229a378338d467e3f52a9a79ecf3aca1d0234cf654278e9e5add18651c08d6671ce942e16ff782db772f4f2660c583fd6409de2aefd2bacf1a9d69a5ccd45d747fd28159d26a09c017f3c5c17eb25d4b1d406eb8e57f63178fdadd5d5459cc27b7c79758fd9e0dacfa35b7bcdc1c131faeaef6e7a4773551ccdfdae6afa29eb62b2d5c13a004ab5332dd8aadd891a8ff858044caeda2010f08350391d65a5af5804d8686b233699fa59f5a8f8150d72a099cee5fba38fc1741c00867efad3676c2b10e86bc781b0adedb847d80704688787b67b91c17bd80a48b44634fbdbb448ad71592b525be28914fbf171ea3b21cc1c4dc9480f44c4c130625a781856c42825ccc186c689a2b0244c17f71d1173ebe9fcfe0b3cd02e567476294eaf606d85878a8e79ad6c784718528131e8c7407f6139cc413a7e8af3ade39e0d9b21051d4e9d9c96da56b6c19e3a9cb183b8d4276aba1e288072bddfd2cdfcdbfcc2d764c10e8eb246a5198aa32589b12ecfaabf19903976935437d546aa5948c1c99afb48c9fd137e325541a2388fdfe10eeef0326b6ff9df84f6ceaf0eeef036f7ac5b5937c4bccdcc836e63520b9db1d71e741c3574bda69e75455d3aae9a28166f4cf7aec8e2cbd39cee6cb8f83c7a4bac99ae51728da436fa3560d102a7cf77d56bb3fa361945d7760bcdb35bef5708e26708f847be6e1fd34aef155ba46eb8e3a99c759e11e03b4aef8be536affdfba72608a39cc825a5732ce170acfa863e801c41aaf911a1edb0ca460a0f609db69b797e669e45e3a7513349e8450bda1d725b2b7cd2cf97bb4dbc2691a2ab4ffeb8ff7a9b9b42d9d3d1f4b40f05c02979357029c93c706153ca19bfa5f2097ea71d695a08566e71802f6212a11b9a8273892494a6b4ba6562b1636187f019eadc23955eb84ac47d0832707a81a1cb73105cc592dd665d4877f93446849cf350a2f049c437160ef4fb3afac228c905e67dbd69c737de4082cef3af1508177ec57e6127526d19bc6231517f2a17d291309709406329b96f4fe13e3c8af3f299c1868063a6608d26315151a3c1c922fb4cc41641bd4935171c3fe5d08abe9344ad126e7eec9a7e13faa0283a6dde54be2fc6c7917ec029fafbf1e35e62563e6d02f6cd40cd4e207697ab39b915e2954440dcda72836b83340fea34b25791a22f5d92a89c5e144b8979be83ed9855e744c34286a8ca5cccfad486c2342e6cb5004061d7583097ddd88a0546f3afc76e585a556ce38d2c5226e35553e8521e60f68e09f946eea2c2ddddd3332e70bce5b7c363a725df279277b240dae99f045ecc96d96f34a2ea31c5724ba3515e5d3e12c5d1145a4b2a0b2d5c5267b9a0505acc2907d8f2053c579311410430695b863147fd89c148b1e6e874049e99dff17ffee22dc9d5ecae98f517165d57e84777fed0897346b2e2321749ecdae78ab111555796c0ec5fba8f1dca54176bc4e3caef6e1b8fe677f85ddea2763ddce431db9cff719515325d9b14dfe6bbd7dd58a39263a2583d1b96203e4a86b16af5be494c4557f88490150fe2863ae12df9366674b8e55ca91e37771a90587ebcfdcf518108501d241ce8af6cf2343f06ebe88692480fb24e8690886c6ebb9518578f6971c558f887b3860d58468d6a54c0d59b1a913a8714358c779bc9493cd66d814a431675c7fd3126fddcc2ed2bbd99c5a95555525b2e4aa7b147173e5325a6ac23788d71341c87c33dc14598896ee067c9e4f26b9e56d9a43d30599b1f0ae6d670f42f1e8246102e3ac3e66ee24ebed90700abae2003214fd3de924bb2cb0b5e5988cd91a784b425781463910e68ae15b9466d54b5458d9ce76216feac1ad86ee53a1d52896b4bb1f0457fc9fef894dfd6abdb671fcaf5f2d9085ace8909e9dd5445a0f59ef0cba872cfc0941f9a71d4ec9fb64b8cc626a4290d2d031e008012b5d6a25e0d5d4de574230c585859eacb962c9be39978c2ee7359b2b59ec08565f7cb398b5363327bfd0d78b8865fbca3898a5d1d52a4a6ee34448c452aea62d7da63d80f93ad6e45c3bfa928880e25c0689c50d9a58a1bed660aa59dccb8789606339efa899c6242fb69b5f27f9fd9d1c4d2923b3d6e99d40da26f6f0477ca514b41eb413633d5afa23b1fd20845fba729c14cf32b3dba9a08dfcea29ad11eec4a87f413b57729c398dd04b39c854b6140f4ac71602bce1f66ac270e323a23bd6e3c8555583d2e5609ca6a597ddfd9672c7fe843cd6b43734b895368306bae1951c94d8d9b811a4c34ef5e4663e3acf1723f82ecb4361473e960f8730a0b44df4f78b89c938e83a9b99914eca4fc89cc345d53366d040920dd3649a867e0503c586aa33f7751196621c62475c97dfcdbf66ed18a26937391f22c183a9046ae89330102ec8bd4d44b2c1f866184800acf6ec936d712469830cfd0e715fcb6047575c0fef744443f960005b8cf76d72eeb754f91798a4587aebd4632d4baef76b0765ca0467eb0a095a8a6584d09f467209cfc2d26fac23fd864f38e65babf829ade897b1b851da66c2a9911c2bd8854c4e986021d0cdb18e82c245d683b512579c872f169da25ce018fd782b640c71ab5879c563a7f94817f3dd4942705a5d7902b78d84ab1eb8c6f32999ae93693f93605d93128f0d50b23515caeb6779eb5e1bf2206c3a7b2ac1fb571d97a736cfa4c5ab51ff0103e858edeedc02d437dd7df13eab9ca65f18b5fb8db7b872e88bb33a5713f484943efce65254e148c1a73c07453d26969c4c57c94b949933458f33739a3d4900a5e0a04811c283fe95347f6a31635fcc6dc8d7af5f411f36849790526efb109928e62a6cc9f06322c656b43bf5cc5717ee8f642ef05093e965d3902ffdf6083b4202972a9479642bfe0ee385cfc41fe807061392b5965098702edf8b9c2c7f304fb98c2c72c655fe362ae9c4aaac92ee5ad6d2a801fa28e962bc5051ad8a7e96df5c9183dc90693a1a209a5c92b3cc1158c28e1050a2ebd4141a103292654f5966b3f5c2996a7d1a422687fa374c267db1a25a50d19c8e490eb4da70b935df48be33ff6b9246c6021eb060135a32a40c2bdc6ad52da78bc628a4bb4d4de626946b098dc4399d6c6ad26e15e15e1995f6a178d2806bf82df301d4592371e17d46ed0283ca752bf342ccd3efdf0addd78fdf6ccb25e78114ce0bb28fe4686322eb2437202b330e59b17c34e39c02d4dbbf78f1be15511406b52dacba7b6482dd68809ee6f44ed1c5718bd0607fd46c828dc24707e6d103058dbb0e6d86012430cfd4a6d8fd579186cc46e51fd551adf7f02c4fa1316eaa8a793e33c6ecb5761fa6c1e15da8fdee5c4ccc90fc0c305df18033b169dd4fbdabac0786ae1b088066c269c2137b4f189750ee1c7c84064b4aaff510a087e69d88c9c39e18ff75077c8971583b9cd81aaed88bfe7386b894e00db13a9413c6bcd769919a6d16a41de83973b49fe2fadebc6cd1848327c6312f9f88900c988030d153b3b9c6214a5e9e2d9700c844f6ea72f0eee53b4e3de6b1e9078a9cf29c503fe8d8f2fd9ba85793cb16fe33b5695202c397ec0fee7bac0cfd1d303ce6f8d424cb6082e54d81bb0f8ff0dd660eced0f8e0a5a09e5400fb5b1fc4d309fa9f05b63e5ebf7ff1f5061f3d5c3514fee1254794a29dab5112a9477bda6ff75e86c61216ab6d16ac2ea32b8042115b3249f8ca49ce0541e13c60ee7356cf60a6a70722b43b33073c656e27223be8e71e8725b6912ad5eb4cb9153c424828224d2a91ed8a6be78c2029465e3df9810451954768807ab4ffba41c5e4cc6257ccb862c0ab85369db0f3545eb681757eb88b6f9829283c9f95946c4a35d56f66a9e85d12c66f6d0049e5aa8adcbf66512a83779a14a6ab64ad18d39d158253e1e6214c68388924adc08bc2e09721136906e77c60f5ad675f466385f76c0e028587835279cd8eb5272a5ca98077809c1fd023aad238c9a3b452f1a73a677582f8c9d1143db75f879b1d3e9d007aadac05f7b64b5ca98d0cb0156b75b8e2bc30b58397584f0501a62429a654e58353af8315005b50192a54aa7f84fd233e09cb33322040c22fa31b97f1926661959cb7046aa905cc2e783ca7333b5dd1ebb2e48036e11a66327d154f8a8686d0b23863bac33e4cb2d8098423a440b17259824c4b24c04a27b9326afd94b718110072de3fa95a646aa051cb050829fae50f0cd3f9c00329a7f170f555a4e8b36640d01f6d443fe257b553af510928cd3ed5e5b61444f64a65800a322a3baecf41ac3ac8ee3e56dfcce208cf1cfa3c00cbc935f2e04c746c3212767b99da2333b949d621387524c6900dfb3c81a321f7bf364747484eed0492fa53ada6d83b5f808c8ef28ec1a86ab3d48ccfa27c65bd5c78bb61a2ba2c009911813b37464dbb780dff4bc70bf84497201ff9270b5360fe755954cccb6b3646b6d6c93d1f0abc524beef628c095ece27e48ec3f5bd948f1fdbc5dcded5879a34ae862279c5fb34f15ab3bc66d9d0c24a9b4ecebc1fc99d916ec64a153bfe0d97067af1e991d012a54c6ba830c7ebb95838f9eb4c866aafc7a816047c1729aab34a9a85fa7fc9952b676c85e468287810de1cb65fe554287580d9bb6e7b6c4b108113013ce0f21fafb4731601ee25b027bed5ba4ea9cd284cd5348fffa47fbc36e3ac17fa0ba2ace9740ef0bb9bbf687d151e2ef3bf8aa86b4888abfd0cb6b797a4788e11488f20c1d7a767e6d4c4b2f351bfd749ff85ab2f6d5eb913a925520bc7a81ff78d5a7f6397c78aa4fdf9d677429ae3ab7444680c5e7e928d36ee2cd639948b74b053149ae0f89f884adf95b2581cad66071b988af45beb92c556c8bf870b6b0c5f744ba31b4e4c5faac45b9aaf08beb8dda565b653ea6038d547f9e277492ce0596063234b1e0ba98a1f0cda3e5a450135b0d454918c8649d049965d79b17c246daa0eed1bb7f99726448f4c16692c9a3dd8aea1d55b34b796ef23d29cc004c4950dc79e2a038a360d78b1db2a314555d7b74f34d1a5c4096dc8283abb9a75430abc9113c3445c47c43013ba67625c2f857714b8c825cea5dcbd9b5ce33c73edcfd62d13b705eff0d51e653c00434e47e1c28da114033f0bbe03ffbc81f9db41a9513299342c3d2734c445ca43e15800c0e7b61ed765c3c94ed30ea94cf95f14ab58120052d7002717eccb528731857d73d4efac2a80bb2289b8b1020290ca0505b54f9e8aa6cffc10b52fc40548b279f7c187d520e17e0e9155afc33df4ffe034faa1a61abc6a6748c6f5f54da1e9ba3433ae470849793d4f2721ae0a8646042a4469fbeb22e801446d66fb878ec9cab4f3806d43b472331db1c6681ac64b3f1a06e501c9e9927c06ea064e7e8000d6fe954dca772ef9cba71c7319a15c7d8df920867527fe6686b733c59e72500f139cc82e52799018f7e8cb6f37b64ab87e66863ff12dc3bd3e00a3442e69c7d3f176e0a1d51fe697d221c8a499e0185fd2d342110da11e430605c6dab0239ed0ad399281e9864d8acff1f1f80d44d36cb3a7ff11b7d9d0564c8c3c0cffc7f2bbd036e3ee6316f7c063bbf8b90c8dd49dceafc6b06a4911ef8ac2be209d245d5288e80ad9b04532ba47ae888239b07a4ea1b39812c4304ca22e0cd13638022ccb02923b8c787169df3d54d177b81d87aacd518f118e9bdab589abe93113f03c31a5fd1c237258523e98e62d33aafbaee238b9fc6118d198a977169bb3894b8b9051283549f968eb983c440e0ac26e62e6aa4872e7ebdac7c6eef7440e75f94a857bea674419cc76f90a9f95a80df90a0ac14d03bddda89b052131a1bd8d29e2ef09424116c88db97db1c929a730c6ed0701130020389f558ba3328673f1f30e968bc36aa08ba10e82c441851d7a595f7c531094f072a61b70e84d4b51fc5354c3a6219c810982366481e4c4212047d09aae0aec1e0a22c3e826873c96bb54da8525e58cfdb465af9525eb90ca9091641b0dd30bfcc32ac2667a951861a0a48c974a8829fdb2b100c07f0aa9afd7b512b7604f4de407f7d0d9c1465ace055885a97eb9e9beaee9a5dae4acbe3c290098995fea4685bbb54a0d29ea15dbda44ae6b305994d121125cfb2cd33e2f2c99b90d24811c363f37b811b26c5f85ab1455a4591ce649d5186a775573fa2d466a4f59a28bc265bd7415e5a06c6473c6b5b9db901f7a7faffcf64ba002a9d3634439f5b710f674c3191a26e344ecfb8439135fe7d5f9da121e9d141ffee2ba498647a6c4dfe330cf9e16389149bcc478865dded2f5225ee2ac8eee78afce5b62f36d926e0d17d0b47a2a36235559b5e15625fd40284305878c4ea25e18ceb27bfbf24857fe13f29a996a4cbf6b384c06d88501f452cfbf3d807f96d08bbec387f8ddab442e80741492293915555ea52c44dc84b698b496bd80e977a8c69aad2d045c2f83668dc98d989e305c446a6e512037755d87312860fbfd48ee1acfc496320a749e3253c1629432ad905b7eb92aa6b41476ae60edd178cc56a7b63864642d38e3311e5d249ea23d1c3bd1743b02fccc34aa488495c5b2caf1408c42b7bbbf5e68dab9f74dce918a9e224338a1b403f07c26a1a1a5d43a30e387f7b3f68ccaf51fa2d52ec919c75419dd647ed947f7a76f5231e6764b05ae0477e50bab26c070aa2788ae5b2078ccd520a2b63c5e72374aab3793912e1ea906c472d831f4bdf71dee8fa2b545809264c101d62951e5728dc39b2d1e0dfa803b1dbb8a478786f35c825c6aa52c67ef7516c5278e1d43080ea59d77f4851a94d50b31b2160e95b60a6d8c53936202bbf580d48b1b1497244c9549fa0b5985b4809d8a50b0ebb314482b46f0f3de81d6be7ebb8aacc6e46d78a4a146f2ba79dead8757bc383e09bca5924709f3f834b20786a215fac852b20d6120bcf731852c2a459116689d5c1a863396adb2ccc368848954c3206bf2615cac62fcd95d27405f32eb6042a98e0ee87a1704284dbbc173b51f96b4264740fb1561f112893a5fc3477a161b634ceb8f4385c96d0839b4fad22c1dbdaeaad3405afbb13a4c6b63208f3018492f1f65c33922a824258998fe4ac671bc33676fa26bc9335027df743993f62702ae2943a2e5887e64802f8c1e425b9945c98c99843a8343cf705866fdccff6a42011df33acbe61d200598951d921f8c5377075876163372d558ff7e26e0c9c758fd62a7edb0743b55b864ce66ae124883eedeb54bf87dca99fe685e05f5cc18793044e5fbdc87ccbb6bccd9f3f6933b0898250704eacbd5bfbb2100b23bfec478741e9d345fa54b568d727854ed920e16e757a47c7c36816582d4b0b69eb28574eb167360988af8c549ae17b533368f035a37864c73664c94027949f4386228ffdfc03fd3775eb90249a10df5651795e63f2b934b109ffb48f8b4465e8f8b89bee2fd3db94c19c4d269f8dc8cf60acd897add04dc7e14e8eb4d8588795eb28787fd40681c4d26afb49116a713b7680d2c45825b58747e8ffbb7dd9456ad9721a17d13a84022c227b0cec4ad9bb15b5b30f786e0b0ffdef7babd2135e4791fa30df1c8504f9db232d9267396b82fd658558523002814f4fbe14eaf4d502b5167b2f1d5c7e0cd7b43938ee3a8de668bb7261c07140e6e300f9a7e782ad0822a5400132fdcb037d679527d00ddc416a699bfca0d1e1e75e458807a3d95ca7eaba0d6606791a9446806a052dfca2c16fb504296c52cdd30bbc376d2943ca3f30564a37923a4d66316b3ca97a34e7e898cc839f764b8bfa2a977f7d0e516c4e3d1e010f84c695d5ad3faa1bfe209a8067060e7d3f2df20abd6ca9d9bd945c26b6b19ceab7012634697937dfd47e6e0ed5d031773a1a2b48b12f020f5e529bea36a085f4c5174bfb2020d012573231cd849854180954896f021759a944a4138c53340a508e7f4bfe5db2fda6f8d7770df4a77e58358a646b33ae0a2567492a356c2d85f32d1397430170e05ed1f94534bfac858387d1dd489cdfe875854f9190e1f1d265461cbe9c489c02e2729509898abde3e9e33644fb828f1a577c357042dbccd3b7dfebf4ff5850c449f7580002e864fd5dbff42142485b52a77273672e5970eef51485080d09d7b8f18f53000e63b322463390030e31813ea611fc988f5d9ff17ef56c87834f7743b456ef634fa9ec9961dad80506bde195a7ff8e45b2bc97732487dfd8a2bcf7c0efb7c9d3a2f903a29ad0c25b4135a94efdba9cbd6db56d12371d2bdcd0798c76e51522a630e1bea9f0c6643d3d171dbb0136e2d142c870d41b59e588832e20db2cd33fe94870a1e06727122a8917676d7e9b9604351a6d5929c1228b87fbb6e702d1df7b70a0a106d142a686985ccb88cf7724a059967c60c7821c67095d99bb20620b83c44d85647e5ee87f440193ff2712d7a4f2fdd7167f036ed09496bcd75a5d80fad2420a1556f1b222548bbf623bcb248ebf0089b025b4e43e4cf6fa04adda2448b3c5f037107cdbb64b7a779e0eda16ff3e0752a6790c68b0662a4c2368a994aae2856988444e5fb641983f38764a4375c1e5f2d71472462b390a91815cbb361dd7a09e91ddefa283914c3db7a7b2d4d39722d6c8e7c0df25c0681ecdca053c7049f5513eec948aecbcb750f710b2f60363d8bdcd5ab89021a35621e8109a3a07ebc648add14475091a9e18730573e5b84f0696198cd4a331fb8898dca94ae293dd9dbcdd46fb4f83ddc9898c626f1384578d2026ad7aff3ec5291f502224aa9037a8d12f49db519d3ce2d08b844e824e2f49a6db73d8b926760c2197f28f8914e3435e9418173782a9c549299192609d7dd399ae5ccc0238defbc8479799fb0d2334e3aceba774599a5b305cea49d493da522cba400f7c0f360048718e2132c8de8a7d9af1d4e8bf320a4a1137f4b35743a676db799cff44d42f9f01f1f509580ad4f6e2e4e74d11480da66537773b0316a8161420a74b92d3c484b9aac6c8f627f555515a44e5a173d8d1578f4a4bd563f856162923bf16b2e30297b99e0a43b03f20be7cf3b042fd449cef279f31c0f17fb002ec9211d47dd4e3df4fa3920716f4f17141d0a7085ea652477eda5efe7f4079f4cd71e8c691f60b9c9aa9b0e5fb6d5367642c4c3bfaf6edaeb4bbc79294a4c9875b1ab6702f2b98e328be732a7709714ea30fc1914b80b220671e0d272b88d960793ba3c4bf59b83e00c67b19a9a648955f4a4391ab8f9f69dc425e1f2505d499b2e2452b15f12f8c2217e87e9bded9ec58d25490cf2298b347b64e8d937651b3197e17f82e867a9594c88df9d7cfc861cf3a1a5c7c263cf65765dd836061949077eb1cea0251a7ad46628ca46069f5438ec75278acb3d30fa0db064a8f4283477fae64863162979b5718de0585cb21bd0ec6cc8f6fd0dab37318b648df49f8f67579cdebea18d4a8aeb9050cbf0ddc5eb16ede21c9ed2608a1e5b4accefeeba463c5b198ac0ff49229b7eb039846473155f1005645894a39f6e1ab51b2e3b87f586d8d3c38ff395525a817c8ad8d59e066d66706ff5b6f09e273c9a598dab6032746819f0b9c6cb76b69d75c2a03f4c8745ebd5490898a0483f950b047384e2310ea72b899e9a3c5b00345c16721f64882187dac78dad0ca1705b0b423075847ef2a477e91323c4a6f0d33f359b8ffd4ffa2f56d1f33e8cdb84cf2feafe4c0d3fce79ec54b9e9dd7356a0faf12fa78e75006c10122fb44d3ed19d47c3051b8c4c445c623a78bd4edc30b378a8be503098414284c808818df9b1a5553ed49acf0302878dfc6a876cdee06af197cb766532b2554d5d2a78472f4a6b78490809d3ee9788e07efdbda1a6c37f3441f9e8c0da66cbaed367714e40649ab7ad376b0798a0cec386e84342f5a8a730e1472545eb8f4b58cb5b24eab5c9eff1ed72a9645a9adab96e1d4300dbacb0a2e3c95a0dfa7d301aca2c8bfb1f64ef2b65b28d6303f253da5edb3f789e0e759dce59332197e7c05416b6342c0502b4ff731b716a73d8e95d1fe0c8c4e13e57ed31c32f8b00ee79843c40337d8b03a1d7caa3ed25b35f7e1a50e8ffb7da2ef42f7923eeba5d085f422b490eb3ebd29751b9e3864e01ccec9a0f78b5383777d7abe50a79a788f93219cd9546b5b528b6da673175fba0c8f497bba25eed660743ad0cc76db8c4c587fcfd2282bb596a3dcddcd71a3597dc8109d946e5a275e69a595905c89457c57e18914c289fc71443e7aa69b7731a27fb51ce9ea73ea37143bec5416f5c2f004912ab5de9856970bc4160c56691b7a6ce9ba97a9723ed9e45daa2f2adf39bd3bc0ffb9bc890147a39aa982a5cdc496e34389cd5f57df6c397c28474dcf5b55b7a5a52e504efd312b6e5e93fa1dfe34cfa443814d2a93b9494e64e6f9b5ba984a32823d8b7a6d24e191e29cd7ce8b96c58ca7de52dc51083f898c7b00b4b8a791280c3d1c226520722e4287844c0d629632a5b1d8ed722d952ddc117887b5c96495124cf6cc26bddc282b7de876c1d0aa9046a7d447b9943ab068bc52ac2f39f6d80fd837e0d0bc7efd5fac76c0d235c0b4b5bcac3eb69ee1ceea2fa3e9ca45cbc30871d64c80f664f008c9a7808247343e9f88f44e135079166e7085bd2bb6b06bda132bd2f319363a9961984de3062d62c36792d4ab3ff170bcfa5fdb101cf5d65d62956c9ac0e80c8a62c3143bde74b271c042b347a6fdd64ee02bc90f3925afc993689cc40acaebc45c8784a148af4a4c18231d3d8202398e04f38f19fe10e836a706880c10b82b8a84920f1de969fcd2b24b2aa25c8c8fad01e8465e64c37a657e77b8cca9cfb49e8d8ee3d51df258a514d1364aeea79d5061430ff93a08c6ee102bed3b661865bc159edfb9d7d6bea574666b922c702111fc27a02d710fd9860e9e8b27f8db180fbb6e175e5e60fa273246884ec0591a353abac75eb28724244583d58cf8f1608a18c1afdf29b3eda92254e3fe22c726191f174e1a2c526de6d1b92299a41bb495b29c0f4e81eccaf87034a6a78c57e8e033fc994da026da623695ae39ad73e7e1bc247842fa6d06bcb2dbbaf11764368a041d338ac30553748dad4c62cbbfc6c032c064c2782d27bcdb44fa2e86b805bae549ef2a6bf8c68d6f2b3267d9b77f1b81d24b6ebee42cb35ff5f639ee4dc138d053b00f4ae71cfc998512dce05f03317996a6d4a787fcd619a52bdfff1446c0d8f96d7021f589a82c2860de4aeea62c661276dedaaace58538d278de51a8677a44a24b4d7c5487f80d3413f841b3d02b2f7c590ce4fe84c783404d6a587385f9a0f7cd57918db136766c4ee248b0006bbe94bc9d7f9c10b3df317e1a5e45f101a367d8543115388aef3efac2f49953df5b58b64746257cb3e8db2f8408f9e695e340dbc90458089c87b7a71635b1ab94cf061f3f540128a0b7bf0a1d0afa8a57030c3c41ce6db5902fa6cf4d16965f942c418ef4558c4ef98051420d3c8580699f3679770797cfc6ad7c2a17636c5ec201cf483aaa1196e42ff90d0f8516cee152a7b50fc19afb80ed0b03973bebb7ef3bc4d0b75613b31d60aa821e3be410ae1bb5329b5f98006aa6cb7d7e9856492c1d106e05989083f24471d480a09b0472fcc3a20d99865f53f1d56edaa4c2c38cfd457ad561ee229baadb3221cd27232909043eecb5698d4cba6695191d6af7918acfb929fbc14577bef688ab404df00c15b1965fd930277c2b959ec1c747456da64e6ba719d9b426c654142fe008dc7c86729a0e68189ca6548eaa29f9cfcb189ad0911da879b7a0995b3836a1b5778b185ed518ffe59f173530af0fd7a2522cf939a9b97e8b03a5376c1099d373b99fe8f9082c622cbcab33e5eec492558265857418b7a08f505ffebf77a5f4ea71621eb216b2c49ba85d9daaae490ba0181db4338d8d3753251395a683ea18fa2fc81441c3edd4c289c4a009b5404b41bd97ddbdf619da7a012495754cdcf5089c708fb8125e9a5fb306d9d192cf7ca80a1d0b373862df6f514f900de3259292d68c2c31311bec941fd933ba6803a1c258a453c5528d66e7300585abe75ecd65f33ec1c67118e03351b2d2de692d80edd4780bba8f9c477d4b2d1dc75dcadd5a21ffc40bd00f1cb424654f492f6cfc5b1c75dd83e3a5964243526e4acfd505f23a31ca8dd7e3605efb3ec4c8831535bbbccc8e3ceca3ca848ffd163fa25010cb787d4bcbae58cf904514b06329667d21ef42419fb49e009cb6574bb850540e1f848010134842cd09f6717dc4ece7b9d4ca09c1f9ad40ea3f212677e5f9b10e28ff870b597753426cd0743cacbe3e6e28718bf20f31d79ff1f08e374b19eaeae30a1ae97324f3efdbf550621fdc915b9ec409a30983bfef2b3e3b86b38d39a985b2b4bd98b19758760f80d74b0eae01ba8381ae29a8f8fa5dbd4ce3b16b56f6bc72000edeeae8c5d863b87b88f532deb8a2302625d05c6abc1b970da583253dd662669f21fcb77463cc6c9f30f85c3e73fe612885f791882f11abca9c6796fe1d39478cc83bdce0268e63f748cf34db669536b0d9e8fe93e2b5b869abe893d2f3c7491a3ee098ece52145b244474291e3a1d0c50bf2cd7b722f98e6fecfda6c0f4f7557996cd71ae3a6634aec3b221393ea234ba007a76ae86df800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Gcd, "17", "19", "1", .None}, + {.Gcd, "7d", "19", "19", .None}, + {.Gcd, "7d", "0", "7d", .None}, + {.Gcd, "0", "0", "0", .None}, + {.Gcd, "0", "7d", "7d", .None}, + {.Lcm, "17", "19", "23f", .None}, + {.Lcm, "7d", "19", "7d", .None}, + {.Lcm, "7d", "0", "0", .None}, + {.Lcm, "0", "0", "0", .None}, + {.Lcm, "0", "7d", "0", .None}, + {.Is_Square, "c", "0", "0", .None}, + {.Is_Square, "4fa3f9fe4edb58bfae7bab80b94ffce6e02cdd067c509f75a5918e510d002a8b41949dee96f482678b6e593ee2a984aa68809af5bdc3c0ee839c588b3b619e0f4a5267a7533765f8621dd20994a9a5bdd7faca4aab4f84a72f4f30d623a44cbc974d48e7ab63259d3141da5467e0a2225d90e6388f8d05e0bcdcb67f6d11c4e17d4c168b9fb23bf0932d6082ed82241b01d7d80bb43bf516fc650d86d62e13df218557df8b3f2e4eb295485e3f221c01130791c0b1b4c77fae4ae98e000e42d943a1dff9bfd960fdabe6a729913f99d74b1a7736c213b6c134bbc6914e0b5ae9d1909a32c2084af5a49a99a97a8c3856fdf1e4ff39306ede6234f85f0dca94382a118d97058d0be641c7b0cecead08450042a56dff16808115f78857d8844df61d8e930427d410ee33a63c79", "0", "1", .None}, + {.Add, "4d2", "1538", "1a0a", .None}, + {.Sub, "4d2", "1538", "-1066", .None}, + {.Mul, "4d2", "1538", "6647f0", .None}, + {.Mul, "d3b4e926aaba3040e1c12b5ea553b5", "1a821e41257ed9281bee5bc7789ea7", "15ebfa91663d62991f82757b52c07a1f61e42109fbda6012b09cb75b5113", .None}, + {.Mul, "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Mul, "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Sqr, "1538", "0", "1c23c40", .None}, + {.Sqr, "d3b4e926aaba3040e1c12b5ea553b5", "0", "af13b82e702669fcdc5a22d7fb20a286cd5d7357dc65dae8dd0beeb0ddf9", .None}, + {.Div, "d431", "3039", "4", .None}, + {.Div, "d887", "0", "0", .Division_by_Zero}, + {.Div, "9c40000000000044c00000000000079", "4000000000000000", "2710000000000011", .None}, + {.Div, "a03a9e1c9ecd4600a73553b5e7dd86", "35f9f28f2cd19e4", "2f7efced80593f1d", .None}, + {.Log, "c78", "1", "0", .Invalid_Argument}, + {.Log, "-4d2", "2", "0", .Math_Domain_Error}, + {.Log, "0", "2", "0", .Math_Domain_Error}, + {.Log, "400", "2", "a", .None}, + {.Pow, "0", "-1", "0", .Math_Domain_Error}, + {.Pow, "0", "0", "1", .None}, + {.Pow, "0", "2", "0", .None}, + {.Pow, "2a", "-1", "0", .None}, + {.Pow, "2a", "1", "2a", .None}, + {.Pow, "2a", "0", "1", .None}, + {.Pow, "2a", "2", "6e4", .None}, + {.Pow, "c51aac23a451627370e2767c51a102", "6", "355498cbf9889c7102a7cc5d500db60ee1bc0779bd9ae18e4aa442a4924eb20a307dc73634be3ea4fce13da5358090f92533943d7dee9ae7dc573c770d10ef76adb6bb13be22c27d8835053840178dd55fafaaa406f8aa28c040", .None}, + {.Pow, "22f5d30a14315d48df4a328b2157657583ef58244138029542bbdb4658c8c4811b81d571ff0de06579eb3ed0c4802a84602ff832ce7854f60e3a3a5ae31323eb8a2a7d12a4bb29ee6db08086bbc22cfe6ac7cb201e21c790c328cc5f4be7040c614e68f6f49da2e5dd72a54adbba17eec5deb657d02c899dc911380dbffec0286a03ed9ea3ca6e11148dfb80c89ce4c0999d8c9748c7", "4", "16cb3bba77f95103473e405521a073b6d8a1b81af0bae0cfa44a593ab8c8ee7f78b34e4bfffebc16bd494fc711f01f75cf76331ffa347c54532c78b8abd905c5dcb5bdfb68402cbc6d4256845bf63bd54577fee63b1bbcc32a762b29b64b9d491039e56854ea4474698f4c9fccdc886a8174b247d711aca335361c3a2037889d1426956af6df38584a36674f5782a07887622c33f9bbddbf5633690223b0761f00d21078d8d34726784c35d21b42c404633b2dc1a00f741653b9aba1b7b2a5454ccf4e8e6c0e7faa698921c5793c2b84ade8bf4b99bcf93eb6c33c3b0b59c2e93e6cc388a1fb2529e79877bd2c8885b7509fa8de77fcaff2e7faa7ca0daf37aed817f084a2df013f517d05e8fed27e38e29e45fb67172cfbbe3db09fb033936bf301ef73ca020adf88f538872448b02bedbb0bb9620d0efea3be30e9a6ccee5908cd215e8ab16d1cf8bba202718556a404cc55f2efc42fbcc3e65f629b4abe81436b3ac002406e81e42e370a31e787789bab92dec3f14b765d4028405a15e92336939bbef80fdfb455615a068063553a486805e71d05643fa415f4dd4d8efa886536c5d3d6f00a0d78d8792a71b5af3283bd7b0f4653b90108c518bdcea241ccd604aeabec6c7d881df3892e9307e7651d35278f09a2c991eff47f84406b3c950e3bc0a36ce803185e196df0f8ed1f5991e5586da5336786fd8e140d7de14bdac58001ea1b707d3d9d4ed6447c4a7810c34e3208d322bbb22f031cb180002e009637eb17768ba1d008ad513c097ceb161767cadffc58130b4166a67cac830766e4f32703d4bfd4ac257e3fc96a9f0803d82f489ec74e61", .None}, + {.Sqrt, "-1", "0", "0", .Invalid_Argument}, + {.Sqrt, "2a", "0", "6", .None}, + {.Sqrt, "ab54a98ceb1f0ad2", "0", "d16deb64", .None}, + {.Sqrt, "4000000000000000000000000000", "0", "80000000000000", .None}, + {.Sqrt, "a85e79177036820e9e63d14514884413c283db3dba2771f66ec888ae94fe253826ed3230efc1de0cbb4a2ba16fede5fe980d232472cca9e8f339714c56a9e64b5cff7538c33773f128898e8cad47234e8a086b4ce5b902231e2da75cc6cb510d892feb9c9c19ee5f5b7967cb7f081fb79099afe2d20203b0693ecc95c656e5515e0903a4ebc84d22fc2a176ba36dd795195535cfdf473e547930fbd6eae51ad11e974198b4733a10115f391c0fefd22654f5acd63c6415d4cbdaad6c1fc1812333d701b64bb230307fb37911561f5287efd67c2eec5a26a694931aec299c67874881bab0c42941cf0f4ef8ca3548e1adcc7f712eb714762184d656385ceacc7b9f75620dfa7ec62b70ee92a5998cee14ad2b9df3f0c861678bc3311c1fe78c5ce4ed30b90c56d18d50261a4f46fdbf6af94737920b50adf1229503edea8b32900000697f366eba632074a66dcd9999a1510ccefa6110bac2207602b16cd4ce42a36fbf276b5b14550faf75194256f175a867169ff30f8e4770d094b617e3df29612359e33d2a3e8f4e12acf243a22b2732e35a5039fea630886e80f49fb310cb34cd1ecb0dc3036761ac8eed5e2e3d6ea88c5b2f552405149fcb100f50368e969c7d1d45db10ea868838dddc3fbc54c9b658761522c31e46661f46205a6c8783d60638db10bc9515ece8509aa181332207c5a2753ee4a8297a65695fbd8184de", "0", "cf9c817dc096c3ad7b725c9ac52b0969fac4ff38ce527bec81fc7ede5a3f4802879e1c4f3a834d254725bf5ca902904334b22971d34f21d64321c0d5ad190791bd5004a54bcd7e70f265c9ee5c1ea266b687fdad448013bddd2c01436026be89ea2bd2b5cac4ecca23df5f6b3a1794836dd5ed890ed11a19a5c30135f76d1811e77984e69dff031f2151b3707bcded26c8b34e96a74cf392b85495cb1d6aa85000c652fe295d952cc784e29244fe53e52e6b9f44533b11fbd1425bfb8ccf69932dc717e7f614c39596e3ea7dd338f10c34a58dfcfdfa79c4aa11239476d5c201de5fda26e7bf1af62b3cf07058fe82e1cfc00725cd9da6a621b785af6554a4b2", .None}, + {.Root, "4000000000000000000000000000", "2", "80000000000000", .None}, + {.Shl, "c78", "3c", "c78000000000000000", .None}, + {.Shl, "4000000000000000000000000000", "78", "4000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "400", "b4", "400000000000000000000000000000000000000000000000", .None}, + {.Shr, "c78000000000000000", "3c", "c78", .None}, + {.Shr, "4000000000000000000000000000000000000000000000000000000000", "78", "4000000000000000000000000000", .None}, + {.Shr, "2a4663ad14733d6c985e64bf979b73", "78", "0", .None}, + {.Shl, "c78", "1", "18f0", .None}, + {.Shl, "4000000000000000000000000000", "2", "10000000000000000000000000000", .None}, + {.Shl, "400", "3", "2000", .None}, + {.Shr, "c78000000000000000", "1", "63c000000000000000", .None}, + {.Shr, "4000000000000000000000000000000000000000000000000000000000", "2", "1000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "2a4663ad14733d6c985e64bf979b73", "2", "a9198eb451ccf5b2617992fe5e6dc", .None}, + {.Shr_Signed, "-75b1d4317d7fae6627576acd96e2a6", "c", "-75b1d4317d7fae6627576acd96f", .None}, + {.Shr_Signed, "-75b1d4317d7fae6627576acd96f", "c", "-75b1d4317d7fae6627576ace", .None}, + {.Shr_Signed, "75b1d4317d7fae6627576acd96e2a6", "c", "75b1d4317d7fae6627576acd96e", .None}, + {.Shr_Signed, "75b1d4317d7fae6627576acd96f", "c", "75b1d4317d7fae6627576acd", .None}, + {.Factorial, "1770", "0", "f0c93f984a54cc898047e57386e7170240f087f83b708cc5c1e3a0ad90b4e49923d442417a3dfc63d84db68daa950fb6c614e914cd54a006182dffd0967443f778a2b47cc1018efd34894fc11f723707e7e166153b0e0c2b4d7372785c450b1dd0f3de4e0d7cafd21180823e6cf11ed0c3241eb2ada4cc01852be8e2955f49204f04ad9d122d796b23835c62d7f15fb97925af7017271bfcd6f133410859470febdac7f22664fa1ae053d03c87a13fc2707128560505863df4dc233af70ff2ed86489f30c34a691951b950c86761b2e456457172902c0c4d4370b7ebe83972f2dd01c6449c983a51c17853ff4eed4082a6e42a99b6179b54e87b189fa5c4ecd1d345c88e5fc66b09d38ae9c49aba18eae2efc8c3e2932ab9a1bcf78c341b7c4e13ec55d43d67e6b15da8f6c789b91f876fb25af1fb6f2af3b7ba4104a198bf4215b13f89b6352bd58d4acb8bb248a646db3806e309ff66229e48c25d7128bd64647bd50527071238cb1795b03b509480c060cd17b77f949b007bdb5277faac50770c10c4bb83674776ce8a4610b0be3ea1565e7ac09fda913b04d6eba6ccbc03e4a49ad123711bed73de938b70e7808fbc02f01ab1b614559ffba61381b80685f8218ee679c0423f3c5859624bd20d2371682c139b4c58b95e90de1af532066d33f57c4b34e6c493bf30b01353ab50cc224a15cec1701a455a58e1de7ac797f598bb3d433fa5ba4d0a9657c98c08ee99fa3d0d5acc50537f4769606bc52b4dbf0cb11c2fe76985ef922cf3021d5b1e1db231cdc6f8f083e9a02d7dafd0867b829b849d636946227850ccabea4aed8056051f15ecc2304687734e81902a4929eb751a725ccfefe90f3156c20669c1566af2d9acc9f9798fb24f601571181e0b182a65356172261a23104c873b6c5cae0228699cb9077de65028f8bb53b4db83af02e580bbd4f0ef6ba996d93e321a6e3bae37f27ef9e316ebb350d8700079b7e84a1e5afb5d75e325a10738fa3cc5342354f0357d5b1457820f07698a3315a08730e9b2f58a73e74b294b50653883a8cae6da1b700440060dc7d25fe9f3756db15418f6128594fde0f48f7a543f977ce62ff9bf750954dc507f4de9cc54a61c072cb4bed5bfb4a35645782e3ccd4d0c257e74ea7a88a2c4e39a2d0d181b6f96f93d05261451fa4f64a17607465cfdcd16a67b73c38a5a09edbddf0728769aed09d0d5e4b7464f7942ecab0ea88649a04a4f9470176d4550b175f9900f984769d23fa45259dfb5e859146accccda8757d0c0a4b5858936cd8c89a64dca5eb9b42331075d32c3017d9c1f16424edc5dffe5e37ec7f51a3e3b047e207d1ca4f7239e90b76bae580f307685107f5a03e0cf2dc7c3ffd14d3b1a85e3af277c3793037cf84520bd6ce8fe99fa5259495808341e9406dbcebd8480b3ceb74b052039241ba4d1add796075ec99a0ecc948bc87c6c72f88082c0153677cc70317d55dc155f9574785494b26f997f379fdd80031c1d8eb2f7d43a6ea7ec4954a7fa5a496fe4fdc70f4f8ae5b1b78363e4441a073b5fef4e86b787d7084bfa0f462198b1c28cab2fdc669a1b486c026cb288654c1f18c8d2c1bcdcc33bc62ada91a10f7fa219c8d8db7597c6dc50e5d4342d93c2da55e05d835fe7a106958c80837af5a79f0b4552179ff57289958391ba7e387cee50a501930d31651e3b53e1cf95be74115dd42fbdff68926c4631b95400ec05fcf03324770a56e07fe364c1c78061e866a66357f5745fa8eff1eb11e1d77b284fe717ead053f26ff428ee773da48a66a3607d2d29d184065467c52ea251a1b8557bdae491f87a2764911a56edd4426df2039cc48b1ccb97e3ef48595408b168a1432fdc2017c0be74d587affc0e9fbb7d11304259dfc134e04a9f4913a7dc10259c0c698103a18c07c2947153bd5c04a10f24216a8f79fdab9340fa6cbb2c8714a4f39adbf6d99541ee288dcf824198140426b97abe5793f8446ef2b663ff6206e99f8cb5d87b7a30656fdacdba9c3cdc9e8911d9b470ae2fe7b37f5825e2e2018b9c26d6da0c0bfb3f7c1134423ea34a51daae7475e893f854625daad3507fdf93becc8cfe789aa45dcd4665b9cd92acd987c82e9a42a941b63484972bcf276549165fad3779472cad25121b79708beb9317c6179528c1801aedd208a94891ed897434fb7fced1d9e0d103ee64733038ee82a4dbcb29a1424c7b9d7b39c5abb2dccd8926558ebc2c7bc7714c39aa177f00c883e546c18fd0056e310ce09fb11edce0171dcd32057cf75c3a52be45361a5ac9d5be3745e9dcaec928c8311b44efc660bac4efbee5996b6e8d40672d4c9bd4bb1d203bc158dfec1478f47010106927a77a72101e3419d693acb64c2812508559e5fa9fb9d1fdca914941bfa78c2b0cce0d6e45e52751f29d682ddc49b47e17f22ebeb777ebfb4df4be344814f120585b407d7a4c5b24b1416e4a3a45a9e7602ee353b960309bacc6cd8f1eea4f297838b9028528347394d4cc6a63ee15000ecf4f64ccd0367caf08bb421dfd4278aa81185e50f8bce64be925c5d422d62feb1162cefadd4d48d4c606222e1e4aead7c05e7a44c9a1bc3d7e010c4fd8b5e754962f30a2ac0641d4581ac55871b6bfb1604747db02bd7b19c9fbd4e0cee9bdf3edfc4cd1c42bd91f30e86950349174cb96675830553acbd744ac318ebfbada54c6e3373aceeff6a62aeb1a0aca442580e8e2637a98887f548b43730db3532a3641e7dfca75f0766db4251d435973c4304ee8c79394642727245d8b5adce9970f0a74df28c1a7ae46b9f1a7b20f5b7759a50c238c90ff2c9f75807bf59abf38be876d404869cbf5ac6ea34a527ee35fc15db1e61fa7fa42879bddf7292922a485b792ea9eeecb4f58a070316dd89251bf826370c4fdcc0e1590365ed972d5a14703e94f122b357313eaedea12d4027dc77f0f16e35d17a7500cb36711952655280042deeb5b252486f2c42a0dd1a23768c2be59aaec3c760b878b114fca7ac863878d1ddb6aaf1543350a8eefda4ac5539d40dcabbfcfdc172e94709361a84da76638009a9c1b2823a0f213dcf46cf73931677c0b9b312bbe40a1848c0dd9152d5a9b3a377697167e287f6d620dacd1044e0d5d3ae07ae9e564dc07bcc9d1b552b140ec822d6c8ee6679444d58f0ea5710097d7c3be4a5c751c58a610031905539a1f391d8a7c0169a4bd082a42294887bc16d89fbf06d8388e989cb35593f2092cbae11ddd47bffc9b86b70ca9b41816f0b1654757781873b54c36eac4886ca2af9526c8ce0a8f85b51528a368d08c7a3570112031a67ab623f763bc19aa7939d0fb119ac0286648ccc7a12f3befe175f8d09c90f35fa0dca68a649cdfc859aa016047339ae9bf328fc9a0eae3a5ad1214f5220446372292b9ec461c44cc466e201aa6590f4bfc213865679d3403d4c2ac8380874cee3f65d6335bba1573d7d20ab9e73be9af1ba405f028b8341615bb07218ada3c2d36d18376277bf9f94fc1ce9189552c864298962f3195c9ef146874232fbc42f1768be379f94fc4edd747dc5b613da50c5e3322507ed9931c9cc17a7de16f5c06f6b24a4285ebe21458741f3855aca1aff3a015b840e23b4bef69505857940aa34fee44b3c8f11add91db976ba5c0b55659d2dd1d322e784578dfc4101c7e68c579052b5ae9cc923e2fbebc62d103dd68a966b49118747b64ae8dc9269ac6aced716427b91a14f8e17c011ca79816528aa8cf6589ef47db181fc5d48a5ec5da3dc629b0058ab91a9832f19b1b54c19b986613e7bd3b09c07de25e41c26aa1ebda72e38f169930813bfbfe74cc39fedb2e91255b5dba52600f38580669170749d7f52d39d2aa493ad83bf4ebb492d05a20ba4d7829ea7fcad7ed4ac9d9b037826289f5799d65d6c4817160239ce1a0f45d872229449d7b50f0932cf5982de3ede587ef5252b03349f60525c8e59a87bfd10fada76fae0c73dbb73e0a6f5c5fa6927c1eda01e4142d356fc02741af9d9e87183428c9d3389d08e9bf2c6514c0dcb87cfdbc1fb60cfd2714fe6f21b7206fec61a5ec7cb2e7eac92eb21c3164564d0303bf06edbaee1e7fe60a1bf8c69513412263b7c5cdedb96e36b5676a040396201981435d906321d9d5740dbf59a9723db18c65b32d84b684ef1ecc0723239c5b534e562df86d81f7aafa879b6bf9e1ca9a10caab41d2b616c107165b6756bca480dcccbf2880f5e7bafd49c186b03719836afba6eeb4f861c5aa4e00b226e42e0bc02c0cd7b0715eabf8cd67c7f4c2102e7772708d5824ccc2457641377775f8359a23bc94e514c414453dc7c486137e89a9c191d6f21b324cc1e02ac88fe60cea1261c9470507d2190b4d672185711c29871d20c91a332976a3aeffdce84c6b4b1c216dd9daa1e7065a629beaf9f92329712caff6dff95d61e93e5a0155e236b972de03f808253f8690aacf505d32682daeeabcb28789eb43c9026c32e535a956ee9e71f283dcdb02bae5b1c34d7dfb07202af8b5e900bfb3240d0049ac8e85b17276f012913128b53e2116887260d6a1df9e6c935850efa3e813ea85a0c743108a2f56f36bdb0c1e5ff14a3fd76f25a5b5e58241ae3302dfef6c778b230ec4c37d194b8369e3a511d98bd953ba26d418c25d6e15d4a8006a6b430deb02b00fd41f709c73bd30fbdef6b8b1cb7ee518c50c46cc09ad40949ae6b69da642baaa2f06a0a3d0dc4915f61ebddf1ab91c48af5dc75947f257eed2dd3cedc33fd0ff8df54b627be63974368c819054a4b893bb00f54d7933876c1e7838951417429faebadf917c3e1eb5f2ab3beeb3efa9cc4833c62901df6fcdc5e1505e659daf6310ea0b5f52acd8b4216ab7ce6b3591086a92ba093caf874cab14b006f5434fc1a4414bd16ab63a5a022b0cb0ba36cb1ed7860a3142ec646e0171f73d22822b2156cdc1848ea90eea94225add5ccf33e13db42654238424ae67a46066084cb0359fe32d307532dccf32f5c11233f8d3bcb398ef07fda2a5e465c12049032503675c6d3ef3576fe1d1c15047cbb0ce29fb7f353e43a8458822c252f02355d3d14f1cc33494b77f0bf55b88cf57871c6fdd2257adeef7962a4c3d4b857707b4ce8b02468347b58bde0466aff3d6057363e9125eeabcbb7d5936ebd656704fc6b045d27b9fc8514031c9cd90a635fe68a9a080713b9cf1918584f7461829f6cc3a7483a43e76601622f285734e21b56feca35f2458d40f4be31cc2931bce61f0f79a5eab3e492df63840a0a97b40a27d4516b32eb4cb6b643c5b562b5977f6e1d41c38940e9fe13240ea92421a7aaf97a2f68456802da771432df3a5d46eec42a74e780941f690353ef75f42d97a2eccc5da14dfbc277fc635c2fdb9cab322a51d92d4cd0ff70d009fa57435636550f4bc95926e7ff28467529ad9bcbac85de4d5ce5de6597ffa8a71e8197c937fca44bd206908fb9feb9ecc50071b00ec09940bfbc5679a4587e1d511f331586940663b65546777b23396366f996b002aca4520c6a997e7a368fb8698939a546e74eb00a0c0e4dab5927afa7b88cce9d8f07ef7a74818ed7e35448bfad0b07296992e21b514a6ecbca930e6f0543223b8780aa7b65612e0b394f93d19c3cf2188678bd5a5e2ad327bcc2860bedbfebbf343f31db337c48b2e8275bf6643192b2d3034d5d2404ee4129bf387c9572a773669aaf16ab2fbed600bb5060a2125e89b15f075ea947137e8d8777ea9bf260dfdc16bce48adcbbb5895081e8f0e966d69479de7d4197e2652961bd19ed5d651e45484ef6ecfd0033b0a9873f4497129575f2afcca46f1c42e4ad5e7cf3a72497ed83dd2cab5ed36c3a1c4a9ea3cd835792fbf77ec37a8b69c4f38fe8a77319c6e4e1f00dab8fa5629568843dd671d8f3ae36fb69772b02af3c94434c3c6e1b2ce38ae23feed4971dce4de59cb5843ee10bf1585c73a3898fe5848d74273ba3a6f9242d267207bf4250064b27445aeff713123de18ece118f989520b1e45bb7e3bce9c40a4c82bb12970b877bfd24332e1efd856306d53d9a4706f6ac0546af464fb6f5d97dba6da4bab8fa7254c0e517cc5d7622371db8ffb9aa9b2c2ce4a3cf5508beb12704a12bf89eb9eaf7aa0e9d4a578c0c17a505673124a2a0d0c19dcc4271b5bc67e7f6e470af0b232a6fd236fd4063d3fc9bc0d0b46b73b789af4c0c1b0b53f1d50ec1c648483bb153808e7ac4a829ae5bfe44fb193aa48a6231fda4292824da37b646d44a2548af78093154cd0f6c5880ded57959c4204526ff7fb88f36b2e753b857b1a95bea6f4448c0cb1c1c92dff1f6353f93e326cde06e5c4fec88143fdc29ff21e54625845db53a160058c8f8a8ca9c45f30a72c5f3f3c0d60ca21c97d01eb7d3bbbd68f973cfc4b7aff7ba10045e1e9deb4cdce9b95aeaf00b9b9a35adec07c593a518611c8d744669b12a3e52a37e26f5161ab89d02d32036349918ac5446235a0e59781eb0810809a077f473dc928b207ff5c5e3bf3a1ceab0e30088baba22fbdd3cc4a617b2376f2ccd5467bd87887ad618857ebb71434375896ef164ae95550d6bcc3086ab70ecf6fc17f3d3eb677ccf81a7dfe2fc58b5eaeae41dc540690b12e8e1b584432f05bd0f06db46742672a9c1e3031cf17b1c93849d9adf7e190e035f4e7f23e786f3102a3f6378ebc8bd19b7e9d3c73852c398118ff24a2d9b0e512173133692cdb6732ac4c35e0689c499d30195fa1a22addf95c0012a5ca5e62161dd88dcd75aaa29f043f987abdc5e1d0fdf03a67c859b96b7d92b6ccb9ab42b20903b2510e0f93fc43d9a7930ddc26d7c9caf4f8234723d24c1fd1cc7272e76a575778497d077592720ce020fe85a8fd94cee7e227d63dc67ea82b44992209963bc9c57a537c60848d7c98a880384ff4caf6fc4614109254beb4e91df94edc52b632448c4dbdaf7165792d79e687b4d720c5a6894e7019df3ee266148c52c93bce66073de054bf2e9887f77f7ebad94c70dfa3b0d6aeb47313f46125975c6187d34ab471d1aa4387829fa7a15f7ca89625ac8eec953b722ad0fd7d5581c35b895a7ad5efd9e2f355bec54c84dc1c01d40923039cc393950083496d2b75b8388fb4c93061ab0b962541819791038bfaf614e4a5805a66a2be678bbff245f6c35b73171a6b394b9fd4c24f742ee444bd70c7f4d2761450fdda51e82c7fe65f7f49bf0f2412a1e1d171db69fde747623c43749053b372db8948812c23f9efbf1bd318d20ae5a488e897350122bbe5e3d34c0871c05ca7ef9e02585ba1cff6fcb1c92d1063ea04fd4c22f014de06c494e9418b5f5df9c8d30b25b7ef180c45c07804cbff18e980e8e8ac2e65a24f48666b4f6bfb7fdaf68327575e1f486b6b69e4a6ce921ff6bde3ff11752c7788bb5f62b5966f6e6b501347e7342e089bc4b3daae8aed81b86a60911f454037d0d2e977f8658c362fe19f6bae39ffc626248e08b19f8211ab85913ed9849abe785e26e1137c6642134025dcd1cd138b178fde95f6785db77a39ffa444aa1f6b7cc19fa3f1b41af6c777ddae4e3d95d9df69b72da35d35f7d303ca85e28cca1a78644bcc2f3f97be8c3cba1fc31aa2df6d96f92b25dc3af7891ba3bcf5c9f8561613a9ffcb056a65d98e2a4232e8150ac3a5b328d44793d66a491ca2809fe5eabee9ed8f9d4738201a84eb4825b495db74921f766edabd1b06d25ade0b7e52ebc95ebc21c80f1cbf476c27fd23505b78f67eb885b4ed8e7cde831fe4fb52226a2323213a10c2957b2330e8d5f0160ed936e81261cc30e79e6d1aaffe0ae553f5392075af9a82750ffdc61e574e31bbe39affcc2ee6b8c6a64a056b62516506f2b58077093318293b47dac025bd280ef05beebe7dc7dd1fd5831b53624c9adf1096064470356db08a604e588e674553398782ff7c66694a44455574c6da206ecbb2225343e47f6198ee9ccbe38083b0ce60f8f074afe3887241691f8081e709c3d9b79c7cfd04d43b8bf1f34285acae5ddb1df8d26a7d7665af94e5d83ea90b24ae986611b26b35ce70e25e80a98b05d21f0d65a0f12d8c5033592d00cb69dc2e643db190389eaae0e98747c430e766801c223a94d87c9d727aa0888d982108d9a2078265a242d2d193a79fe0ccb3307b9c78925201a0f6e1c514ab705a8c43dd8d18ab3dbaf2969ce1c9108a1c03634c907d0ed2a01242a035be228ab9c39674c09799a84e5fe64f7f583085962e9c3522743f16320f6df80b07e16dcceee6c9860ecb992946ba773c3b4e9359775ab2443935d0cfed8c0091e33b55c4ef722d611b7550beab45853ea6f32bc4c184f6efdc339dd8b101a852b33aaae8ac13bdc9a1f5c9290c13e3533a0ecf6f3bec41031e0c901656f8c22021e3f9f57c2dec915155688d364e559220d1bb467473afa48d4e91e9637488c7f0d6382002eeebd4984ecc553679aabafd70ab008429355d018425db8e6a88e778b922e939e85bcc16a043ac0ff6e4ba3fd74332c075bcd496abd44bb8f73226980aecc55f14d1899764a9c7ce9bea4a9b4b1073a6ec2015181eca06907175ffdb2705f6fd00e5a013d21fc66d7a308235cc786f6627dc5909302b5188c42bd7de5350e06c1865316cf96300a79184d8cec06771c1b6ed8bfe661284c3f44ef5b41d7e70ba10bc6f41328787e778d5538e9785e5f032bea564bb4815fa9f09f47c5f73d4fa678d2104d8e0380c722c4ed6cabcb41da71ddc570028b7abadcf2899ad8be648e5d9aaf40c3a5411d704a57343c534f90c724f7981842a51691b8bea457e38e448908b66d9aa481c3c0763ad1afe7176630e646e9e00897bb348105ce4dc9a4c37ae615dc1b70ec5b1847d1aa9fe982dd649036fa8f5ef0c23e588c07f11de24e1bcffbaebbdd3215234935a08d389d6bcb6aea5be84e4929cf18e79eb8e5a8be348032eabd5509ce786ccbdc3344c87861c1b38b8ac59d21b0281e286927361a0797bee2700f625d3a8f87adc373258f6a9f35e65d68f2ab6570a0ccc21bffcb344f5b7d061a8a20646777bcf245e00a1ccdaefe2891f3b0c7580e3801dc7a3880fe66a70c0f0a2c880f79f110829cc7681623f36e022ba219e516ea2a46fa4f0fce0c489f67ed3484d67cbebeb5b9b3d75d82132059d4d7ce062fcfdc5c131b08d1c966eb103241d4d3228cfd1018e53003076d631150724f4ba6a7d6cd8719cb61d51fd83f09ebc9d11105b97af876566d80da59e977a0f665b3c28c7ed40cd778bca8f1a908319a14c5d6ad390cc55e5aaee779cc3916ec0963aa262dd7062a9ffc94aa86e7da473a44c0dee5c7f6820f327ba6b36e64154f5435474d09e3f3593f63216a3d6e206d3c8210a9430facdcfadb5cd50ebede3fc02d6bc1c43b3ece4793d0032f1f9a12cc9577a4bed8157c407f93f2ddc9b91aa5eea506c0386b55517f7a96ae01aef1e42a9479fe41be7c644d018301dce9c3ecddff37b1641beaefd486baacbbd24187f76cb9f154a33e6543155d29176fea515eaeaa28a321cd41255a1abb7efeedbbc0982f09563909fd76762f5b178d9003d37e2565908095f44cd376a8147ff2319d7cca6a0135f7bdd1f30f79c70c6f799f39f9bb88eb511858d4eb34c7d20b574f46ac8236a29b714d6575e58562a363b7c6286eae49d42831a14653ee16045446385a7797b6bcf1823f8b1b52a2376c3be5dc0b6a8282203d98df652455402ffd6208a6596570d264c2311a01da0a5b119172ef6d473321ab354460918f53c3eadd764c937c674a9fe3179d5c9cd54348805af4f29ccb5715d8e129d918040e4ec47f2c99022e1e00034d87d157a572d0d969032f04983cd54b8d18612a4c2875894c48feab0c96141e9ba648ad6a2f1ef1c0d4e44761bb14107126ff157ffd5c27568c37bd28a44ca81140cfc0d2a6dd864c4e27521ab9a1078d48e497b8d2b2104f1e4c3ba4a2f95e401667fa5e388c6807fac08d8c4c71bb5a0d50366d39987426dfd9172ae535e1497b0119bbf4c15f79fbe496350dbbe7ba335d9aa66ced3271eddec663d16120b0b0176987d463c5e47fed463e2ef2a230c17a5417f535aa26dad59615d603ec118670f88efba66f392aa3ad7a5d483ccfd8c8eb69728d982399cbb42c5a90449027efc2eb0432b90801d74a9418469af89eb75352e4a3dc2d1c589373eb8a2352aaf853e1bbaf7e4fd8e9c95567987bf453a46e7cfcc31fd61e6c0f1a2c658aba4feff965be68d6b5e964e2872f25eab5323b3c326c34729acf20c71698c43bc10ea039c977d4d7ab3927512c9a13134b4c4d518bbaaf831299632244228f2088eb6cba674fb68852c7cc3a2c721c84e8db66d2c5b0e4d0a95f0e0d928e7e5ac0602cb4f84ca84f200f33e7f189220f6a945b538480e4ecc07aeae6adf89c3f7b65737c0c15bc7f8a4ae2a2553d4fad3dbaf438ee0ba7a0f085b0743e6db6e425c1186aef4d134af4491222400e21e054ec39004f35862c17661ac52820005ab99c257de614f5d078073e323933c533b0e4ffdcbe8aa81c816e0fb3cbcb7e19a9fc228c2206c663f8b7bd4a166d527839b8204f3ffaf11af7b181e2f18c310f25eb7ccfdd9af1b5b00720fb719f5ba905163308736bc7833e400cd56c32198c6bcd137447df307a67567c8429adbe05028c3386ad96249552ca630fc67d7bacb109cf5f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Factorial, "3039", "0", "725bc54b19f7229a2368a8438d231aa6742a9bdffda109af918973d185bd1142da42abe786438fbfb3b6a1d6732b6a1fb468d8908f1cd36ffb7efc0669264f2b5f3f92abfa5e2adb4ca4d9e2750eaf98c210de9067729c35a08bab7b52a889aa4f7462af4d00f28a02a41c9c63cdb0633b8afc137bcf9d06b7308fcf3aaa5d6a6cd571ae149530e773c9ab20fb61de0a754b959f749ed22fadd2ff0753c623eb2b377d75d7a730e0ab4fb8ab8097108085b68b81df361751ab9543dc4d640128718f886cd2deab7ce07c032728489f9b4c2ef223b13260de9c5b5eb26d5d3e4ba9439bdc3061afc6083ac8a60ef74d770d15557742c93e03f6df30dd5010a76761026e3e93b48e439d4cf71e41cfdc00e6c559f3a0047a5bcb54acee326ea538297a91cefdcc9a3b05d5d0c05319635a817fbe6edf12fa501e2024cdcd86f1ca3a12bfd485a55b0cb9717e5c29b65fd7f6a45ffe75300aa09ee79b9a0ef022d4ab09eef62544bef7042ad3c0dddd7cf6eda293ccf9d9cfe38e96c7a29cb0b8ec360cad98f97826dbeb94e444928d64bd1b01d7d562cec000c84d5a4b4b00039a82307a3dbd32dd5047fbef8d5a11d177bc6f09aa580ebcc9cfc1f1b73df77e247e23222e58592a5eb496e7fde5fe202b09f43734e4ea1318052095c689d7ead46695c1213cb6987c6a3fb6da2c7c7802af9b7d6eb6938d3660c87ee7a76b11b9f964063c7bc3e161f0edae8433de09febfcd2e37bcb9a48e519529aab496382dbace40b8c75a831e8401804a13c3f567691f03d84ef70c345c42a3afe869e4e59cb240b50811856f3a8202d2975289ea2ebeffa878a1f29a7576609c57c27c015a411e75fb25333ca49e6a6edd6f668b86f4ee9a7f6208e1af9ccd3553c00902692f9db06357f399b90cdbb05912070619c448159a4227526054ce00c7ca069d595557fc5374528b6739e29c2b27f81034eaa3a3b0358641c5b699db45256519da785dca487d0f88b41bdf388e460fedeacda9c27934bf453b96d7f8ea2acf573b33346a0a6f39c10104cc6eab077cab4ff1843b6f1ba2439808523c3f7ad9ca9d411ce0bafe9aaa543b82c54964cd1e7bb0692d314570f35d1b51e7a1b81f2d259f4ebef59e018a2e8781258ea2bf4b0a1053a0114089b70aff5657bdf835d73828d00878a3a74c9beb017901a593127907e14a350b40c15ec821a1e502cb5e8ff7e807f9277d7c18cfd82648aa7a7fb9732d3f7574386eb49b66ca927eea6154098f45efae6b7e46c4a0c9d8e5e432d7f9bbac3f06635f1e7edce3088e5baa7edfa7cb5ba90198b97020878e727c1481ba9399846092d81cc0d2f6e85edc6d995885335264e8423a8922b251f98113a89a14bd729b1aa895a7b8fd1d92ac8f826f0e5e39b23a4939313345f6a4c055f819b2689b8bb9fbab5bea96a69df4ca93566d1bf9b106f7f7826dd7ed7d2b14a1172e754ccfaa9aae397593a83e9a222830792c1d630ef0bcfa1ac7737630f56d5e4daf8d678b40167b5333923c78e4a962aeea8785886e19fadc2aef83eb5feee8b7cfa4583ab9122b3d784bf8ae0a0085a9617a2728013fa15c5ee1cfece8d6f1ec2edea5c02e98b3257e135957cb427f6dbfc179fb94229dc7c6867d93ab740b75c41522aa26dbfbf786e9a24b417cffe0c0c6b8049877706bf9ba0f302b93ee248f5cea90f098bc557a19d6e93383c3549b8ea7c2cf478d2be3006445e133cc899b05f8ce12f35caaadde7431ebd6aca51bac7e1a8677af175aff8ae9bcd31bd284f9b8bf99556e8c679aa617f35d89817636c0e32b28939cd5590a75d587d83a72478c68f289056350ce93a652a7ae531110e6e23340b64311c584263f2425aef4fa73ef808455688cf111ea17ea9ff5eea3aaf22cefab591dcc10167d9031659e9510c580b7ba675e75addd4ac4ad92b337ecb2024d1398a8933285da3affa4ae82f2ecc1add5881e42a9327c42be0f6e575d4d7c31a9257a7982dceede1e3cbd39b2808b739269413e6e764619554ae0e069cd4c18b54ebc7146100d735afcdcfbc969488470c0e12ad4dd9806d12cff39d431e008658e5b10a1bd72106ee0042c3e738000f7d825e4d9f1addd2ed0c1cef0756a29ac3500ab0a6278252f00e8b6d9b40bbd9425ddc7602a1332e4540a637ab94cf245e0d7453fe6d0cb94cf2ca5a279a565827052d9bdfd0a0a99fdbaab8f7bcdb5b3a19d70c19f6d3a87b47d8414d9fc7d617e8c2b8644adfdd761784174f1e7248eb7f04b538dc35eca7afe3df9ee02b9c5758c2ff06eccb89a918f607609a944a72e8917118a1fe1cf16b8993589d89f99044a5eb68d2efdb1cfdb894a7af03e3a24a2f98ef9ff47ff5813d2a38e13b76d66e3075fb0944c71f5510dcc5224236a1d4530c5abd60d439eca82c788c2bd84ed5455c395bb14b18f90fb6e23c1eb4396319642cd0c13c6026942c62022fbb9c26f180cd283960466e5649a62bf965721fa5930e844aa151f96abb4ba1dae7ae1095cc42cde8badd8662a997d213b23044077d29093b8d0951808f3a7c9cc1d60459506717d6db29d6f85eba257d1a8a7c0fbf049722923f5c5eede2ae0c4a2e8bd8881dd0f08ddefe11cb645350d8fa807a97ccd21b61bb271998eeaf0b60be41036525dc97fc80d7a8c648caf700468ffe7720aa279d5c5c1403646dfb3b9e0f4326876bdc7a89ed3a54aaddd84242264c0f4cec48fca3cdf8f59b548b8eff1cb3f31405cf068e1e3bf9cf4e378adc0662fb447f73c008724e6f8e212f5e57311385247d07429659c71b7eb7d8f2311a5edf73e1498ebf216b2b1cdbc83a182726a5f086b82c1465bfb43b25104eb3c947072a884edf2b8cdfed8bc1546d6daa21c4907350924fe9b5454c5cc5da4349809faabc2920a2b5d39e8d7d4149b69b5731155edc00f1c0f9f227a5794e2d0e47f5da6247e12afc1bbb76e679d3fd5d92a8e94300eca12e75fbbd423aaf5187a37ebd0796d063bf58c9575cb380672d5acfa6c2bb242f7a78a67b785f8982d0ec337fa809becb0dd8534b36b1908c5f10adc3f988eeb43acae2e271ffef9811ced071aa3608b9f887594d44824137f3e26104a2f3c49728dba805d410dc64afdb4911b070e32d5bef14bc10520e354cc7fa2f35998dc82173229ee64606ecbc14a9bf3d614a4a773e492d27b2ee8d34a7a772eb53392161027ba1bdbf88760f3f427186ec53844a991f75fef3de31e2e041a485d7bd09c977bfc1b7cd20d356db265a4bf17edf03a1bae0bfedad9290eae53a4e8a67ef0b1cb03efc5f2f3077beef63ec1a03e7db55671f2d0231d24a41f523705fa9109514d9d807a197d09685327da1fa35234f68b8942fe991a1b8f2454fbd2e4e1196a0f37eba6d24729bb4b6d50442a978d4638288aac01ef36a8e7b8f6f7b199a953c8b4c4c497f8cd32f558b18c58f021fe5cfe61a19a47b5cc5eada8796f666387b4a978b46319fda2f768b1f6a107019ad7aa813253449c8e6a419d2fedf59db4b39d899bc948250944aa7a586263fc0c06956c9f205369bf85ea63dae27f04f8850cc399b7b8b232ba9dfc5b59fce0373789f3566fb8df2ad50bc2f975830b92851c01886b2e737ffcd5065fe439f18f0b251925a430b438b6f9497d93c6f5eca03f2ee720689e7a981f7e54ea0c62777a0129a4e71348561d9122048081f5ff8c4f076d16d386406ffa3af8f1c399c8535df945e9fe17caf64255d175fb109a978db8a63f825e312c318c6b0dc59c55044a80ca4ac0e1ca2a98b70d32101c9aad6f9ad52abd939cc387cd4e4cd775524c7a7bab8328ad2d8096ded7c278f71ae9fdb8ac00e265db358c3030cfda95b6967495ae6f6a2c35886964f83a042a9a2d549fecde7eb49b221a8cd0f34ef4691e186a63154e76c7b9f8d8a6e885a36f0cebb3250d3a0da49237eb6079e06c81f1a082ded2cedb36d505f27351031d6d9643e03b1b87b64766c5c8935f13aa1f795554f1b55b9295e7d2b3e18f1ee84595978b8d8abde40d32a8e81ca08cbe0b3b44c50d5198e76b09b82764feae609ac46129d222ff5b861a41137e88605953642183894d1b4ba6afa59d7c69592d0feee7a9a92348d5082de0c84336861a1f6bcb3ff7708aabaef25955fcedf1435aad33a83aa9d3bbfbdbc174d12141c51f7ca91e356c76c9870e4a32d41dd7915d6c21ce24f5f49c334591907561fa6bf6d47b5bb41c1a83d6eb1e823acef38833f0798599f693c6711c9f7adf2887a8d8a4c0e615968e3e2d86fb51e92277f674ab129415a9d5b11b20a51dff9598a25d8f4b5f4fe8e03895158269b154c0a169e3c90a655c92b8f6c48c763df4bd134a1d23293379d36c9513455db5395e684dc79c74907a02c9ddb0ae562e1a4e307399b965511e05fc7e88e3abc495fd42d6f61ac5d5937249f9a0380127db9cf8235afcbfa7e136f6ace515bb3041c9dc54fa9eab903862a2d5ae1c0a14d8466e58ee872b6e3c8e8e11d63d67308d001cccbd58601fb1fe7874b80b927e0e97122a9d8c62f193a110d1431b696d1fdbd2216f421bcaea463ba82c7c8d583ab9629868b962d3152136d420083abec0fbf4a0d16b9120ebea914dece3df525788b0a18b953434b5899b24a0c601254974c65fc1623fdf2c11c10991493eeca2e1a9da5d0ed107cbaaf0f71f6592588f31aecf8e98cf25ca746242439ce908752a49a20de527caac3c707eef57543f98cfcd692ac1d039e19d5a09b9ce03fb307f00229f96cc5316747e1eaf619304a6a502c4edc236e76138789fd75a9a993cb77e7df97f7f0b847c92e4be0380b6e94d02e641a1677198b4dddb79b3fff93401b5bb6b7514d15afa918aff2943276d98ad8c61af100629ee7c90abadf959677760cd866f8d6fb7528e93320ca0f99351c5f0fa3d589bd9185fb615d501aa22191a46ad0501f2cdf61c92ff4e549dccdc531b775589d39672a16a2884a1cae8fc12233264b60ee868b1fa550b5fd541ed37e970d9ad7347fb9e338960a40ad8211cea809ae3ce928b5a003a01c3e45e5397ed20c1560944660285edcd5d68f0f8c7590feb49a2516856fe0c2ee49c958f9e8b7ac0d03814dfab8477079cecab4310bf97fb0306efce6cd933fcf0543c72862848f7159ac74eb354ed6f747ff82b13e801d8a274e5e2bb4f327b4e0bfa72a1428bde3281e685b095bb7807904717fc5f86cb96b896c24fdd3062fdcfe9a94a4ec84289e44e0f51da86158ba8ef895054ef3e9b609c3174f0f40b50f122f7d1b0cb2a4d4f8e6d84d04d7ab363fb6638323cd11a48efec0efc47eb7bd6ab5e40bef4f4a7f7acef17d9b5eb47181f155428eda5738943900323f4640c2adaa231b0d290d3166cbef6ecefd78e4295c391f6e7c350ad0840dfe5842d66fe4ab9c251ed7aa6b93799f9c57dab554929f687e8315ac0d306d763457d04b0892e5fc5fca44a65dbd58225f2c8a778b22fb0b376e72114845cc32a6dcf5fe7bf08d522ec9012f4e6f2238b10f23276df884f9cc813b9591dbf51441f6938c695b1c529dcdd8673eac84a75df4c2818fc5b73c54ca30b1f6865fa434c2721571cc115f864525af71fa9a7435a7a2645bd1c1be9888de21b354f0809f2cc4fec623a9f5d9d552e32dd8b93ba66e8b62baf97302ab20b3489efde5ab2c204c5a7dcf9742132f9acaa5093b75d5d4b2148c873e72cc9838c6e79ebb909d9d8b07e93ed565f3ad13f4676df70cdb366cb6ad4ad9e180465b9bc207852592933870a4312f4be267cbeffa80709217e2914515d259ab3bc4554293dff34518ed301a964cbee5e0da5f38da3e8d734b79c89095f08d782e6dc376723c48f3d60893375210dcf810149ed90592eb20e954e862e93afa885194c35f845c47d56ce469f6ca72d0c3d2880d96da5979b5dd865384484acedb1bab199888fb8af337d4af221542e664c8ceae0c004bd4d3145270583b6b666f3f62f0a2c6b9381b1673e73b08ffc34a693e02ed21cf9250b12f1daa9f1ba541fef727606e24072118bf69287170b3a33dbcbdbc068b855a2e65fa2406b3314af6eadee0f3464cff2416b6529c684c93037e2a17d674a1b56e96cc03ff13dd75d1ef0cea3831f1509ba1fcc6c7729363e7594e19e486b49b737a40e603ab2ce28e0ed7f4616fb2e6105df369cdf5490db1f75b2445025b86db0fdb0cc22bf63b68967cb2bcf2a7b1132c461f058be9e59254e1b7f240d9fdb01a9408a9c5770deaf74ba74af642a506c1c958fc95d8ae2293c4c5134573de18693c8d16c3c5ce7023f921842672adcda4e5e3f926b40bf14808ad2bd8fa91b28b2a1dcd380e8f1e5a566c48d8293d90efadef5fb104294109c393373e77bee58a932ce30f7c7ec46f52ab228fdeb883765fbb61d98f1869768f244182d40a5eeca6eb32111b381c8c9c82495ecdd41d4a27ac29effc82562b41fa41b60294bab971853ee48da85ce2ba803ea6573d1047406964c3f8f79653adc8bef5c818ef50623f468720c9828ae7f8038aba74f77d65db2bcbed9e1f415ed8819689e37d050a57e624cb527792b8709a0c31f921aab8a6098c9d23a542574686b52cbb4ba7d0922f28d1816684cd2359351227b2ed1a9864db623d87036ba16abe2742b54bcb23ac4bf7a1ed529b8382b290e5b000cc0f9582fda44d7a389400a51c8ead0bfac541bf7c95263750184f5a78091a8248720d67213ea1aed2d5a08419ab31cdb8d8052ec04a3f6a11cd0f47f0cfed6e4fce7d6e56e0996d06c5739238a5a5d89908c4e66ebd9aad357220ef39032330b35d40b7a4ad7e6174865fe64636e9e6f15ef4d37b0f390c81df3999e0dd73f191f1088bbc74c6cb9a742276c9a7023147043c81d00b6d3b82845c45d267fac6121fbd77093f22eca95af3a364c7934da516f75605c1aeb92fe9c801c571a366843df64f2cd4ce30636b37295620b9f74ec966ab52bbe3cea589f3e95bc0161b3305753b8a0af49979cdc8ae2e50006377b81a0a9c4718025572675fcf68aae62cdc47c71b272cedeea9ccad80c1c705a43650492cba6aa50b3375fd578f3a822d051dca2030218c2a4cfb16065716be81f4d1613b8d006af780fa5de4c7248fcef3cad3a58f242d9f254fe5486abd2f4bac666c01e90e892ab937fe39c243776a3475ffac7f8f96d68d3ea093ca3c4646a6618c31bde5374bc64c7efc0995989ebcbe816be8b6a3b1a43cbb63be86ad279a7c30c57fba1c469ef65270f46440e7d5cece01381c735afcb544872dfa7c4e7216cefa56584797dfad0313e6574eb4e01acf34f8a6c4395db3dc1efec7cd7f2562b082203120ecb56d54910c91db6dccf41da71fa22e5a68f2ad2a946415747bd8f7c79b2a02c177f185c55f9c32cec441bc96b00c8d21e977c0206ae8aae2e4fc7f74a787d603e8468bc823d39f0d1851b5d10bdf5ba813e2e214517a10a00c7e34d372034c126876c94aba7d03ac13ac36de981ed0ed51b8710c02b9a3dd6423af828425307910e7d8a5133c0a21e2182cf37512710f31681d5007e879ad75f40ee9cc3a4c3a6fe33e933a652a72f023fcba97d7774d167ab4c04d4a4bbdb7e330d220d84f877d3f577c1d499bd1e6fb999799e5259ca39f39f2463d371c9b8083a26225abd7487dc2fb20e8cdeb37200de1b82002b39f0ff70bb078c919d6bde528b0eb785e35d884fdfeb5127aa2dfad66df8761e5faf2f7a07c597aa4c9ef901116d69d45cf3565159383c8dfdca0c320512ce612654351e4cc2c72e5dc148786b75230d6fd463ed2164cc7da95f32cd26dccf7df8d97983f93dfb0239ea736f32c65f6469b9877bca5c0b9882e7171ed41b1366a2a86988642ef1c0c47cac31ee6e9354d9757d3057c00157be6f98a3f9754cad44883946a6fad81a64bb5ac661b2280e49e9f95e09c5af94615fab511082b6465a73c021ccb64dd1ccda8fad72562fb6eb55f1eeb5b2dc0687375cad33bcd0d74daad4298b1c592b5a624b26c5e0dcab7d631e6b217fadc76cb8f2aaabd5e50f2b4a28bc2effe011374d32ad6f3f7674333803c9beb262b60b539fa190f7b477c07922d645baea18ccbb3c06b5690d38fb125fce9be0988104066c15c7ca93ecb52ab3e1f936c2454a2e26783f5e8175c101c921a546dd33adb20d9153bf6f1bf79c3c284331133c605320cf313db6d1274f093015941e70ce615f10458ba48a30544d6f44b62e2847045fdb51c784a37edbe4eaec58974d8768684285e49ac15a33fc0cacf23e5afaa2e04524b71b1bb8535e53872f59aa647d13297a2dfe305116e82f1c72d27036898d2b544d6bb7bcec44db12d45cc6ad030875b170e3266581e544b07c8893f7829ae448eb888458a1ab8314e38ea687ca817ae1a7f7b77267a5ba136b546d5440025a9269f16546077fe2bc158bc31c1f4f77c5cd0850338917c5683f67207840e80caf6fdbfda8ebe105dfbc37d868545a40b97882769791d39d5547277320448ceb05c8f3d91d2a437d92adad44b78cffb6e81263cc900d99f57a0f3520d8acc2d1ce4ebf8bd494e4c84cb17d87ecfbbd595296a00949979a509037ac20b694adea16ab8e095fe8a42b4d12a4ea677f5a9baf4ba7409710e55d723ee1220c75ccdccae4389e6b7899a59417fe746d3607a120f64e15a64a3b50ec4e53575d82d348f445f1d6c1bc4cb9a6d8994a44c400bea87891ac5da3aba7fcfed7bf78ac3e90ef91bf55dbb16691a30476a6382de3fde7b8e07458e3cb4c7ccf53a870677d17ffdaf4590444f2586eed1d1814ee03ea49b3825168ca030299681114e0b5fec1be8b5d4dba691911acf1cf1e494261514613dc9be675d9a53d7c8a9733b8895eb746a7707adad425776b2400e1cfae03dd9ce639d964782a7894372d58245ff37e49fc09f86ec157898a5c55cf7a1c3977da3490190c82d4d6a54ebaf006634234ff6ff8070a9a992298f2e3d9ea3a74df937ec5e7b8263484e9815d731ef0f5b2d6eaa8c8f6bd966e0828a34144799bd575c4b7e6d5aa057518f7689b19ba446691f7813608c49fb424e9d4bb040c2a72d015aec8e049a0f6c985cd89cd106959d1beabeddbdd4042d5933cbfdc035e9718c98a2b5eee9cf9350a7e71749f3100309d59c41153c435e7cc7391538fe549fb1ccac1cdf7ba1f4b03d62d883da32fad505b5e98bc6ceb89b447852fcf5b84d64046daf583f42f88df6c936300339a49d121cc6814f5268d30bf827da8e83ee4672877c9ada3417f3fd1acc1c2bcebc22d9623a27068b83719b71f86a242fef992894ee32f53d60ca000779145c5b9274027c39711b8b4c697e4bcaf7c588a9d688d25f6312b9ee9dacdd1a28d0bd45883bcd665810c19170d80a6517dfaa83e489e38f4e70d2e70e605d7ecbdb0fde1e34f4633cd67ce2a24d845b1fa063fa12e141b51521071b40f73f2422d93498a456554be6eddfe155bb50e145ad0e24173daa9ab3aa808e156056821804d4e9ddf501379cecd91a37de9e2822e8465fcfd3968039c9d7617f685d6b567e8331eb117bf05768196b4c1384744bdf11fb824ea241386b882aa5c2fea9ca93165d13539e080462e8dd7ed58ae577f7d109fa864bc958b80c62cd5446a0048193b63423028291dc40355e63030988af8298013205330e292108aab5b29a19a0b5aff56e8d71c55a604fccdbb78f0b16443f3a4ecf292c57d72a09786346c0def2d97b1968c7d8313da150becfc0fe7bc2777fde63b05da1eb7b7dbf07a6c88e94ba3a1f03025b8abe363733243480a63fc68e687cfbeae555da8767b127d7a2893aa1259b300edb46d53df4e7659418a556a52c5920109c9f320448afc6567ea2c496f7340876e99bccebcef40f7653a7f66e6a4c53b893fe5a2009406226d119f526a6fc15e1aea77e505f8d339e7c0cf4f5ccd1474be0b49b629e27b07d754a056ffa66d8392384854477622ec093c2d16a9f430048743763acc2235bca3dac5745ea0b5dc7990ec5225eaf13025aba88319b8917c00e7c965fda36716122173659fc954e104436f86d3acba2d0052edb0d3edb273f56ce0fc763da0dd818e066e461f39e33892c72ee57d709fa22610ff698985a1a1095bd2ddd7f106283bb1c3c063d3e75d52e487fb56a4e3f5b619db7cc165fda958e417e86fe04018d2fd5347addfe9495bc39c26ff88730aab36f53c95d93d99102d0462c1e2837c27a9b0f4a2c011c5ac55b63c5a70d55f257e1c00102c2026c1f92451dcf82fb3c512f01339ed129472b9eba077b35aeac2acba39df315ab46ad5ecfa8e5a658ec4d0691d2b1b9d8578a341de65e918ab7969246ed3e790fb3d7753bda3bb855f2a4d9eb42355d5c68fa928ee2f21690d384a72576cc5a6592e5ab629968deb8ae9299eef30e71f77d135e77053dc67166059d1dcae2e723c345ffa14e730cb6a18c1489d585e255e300374afb1e1e52f41fcf72b43152346770f28c5ca6c35aab04bddfdee2180b762a55182b18b7978ab942f989843305303722db875219f6b37360c5d5f4bca44bd8cd199f3248b9ee383105f82822af392fc5899b175e32c11e7cf8f1b29201940e26d9bb189dd8c46c7f37a3c2cdb94496cc166f86a4c8ce1f6a91f7b178571050cf74dab79250512f4a84eeefe96d85a97159602049f5ebbb8e5cbc15a89cfc241277ce10fd3e8ecfd8ff462c7c5ee7a7adf5ea57acbc3df8c80806661dd31927413f43cd8d84e6768d3b580be97e1137bdf79637c4e672684a73534c8752cda954e4d1ff352eb82409b14aa45b843399414aa2c8d3f5262565c59cc7fb26ffd88cfe82e764ade5f563db295962cc802ee3ecbae87d3266b915835ca38a00cf7d64e90b5103305b91ca9ac97a4e274327f7899540163db95952ecfd1e0fd8bb1969f52558327a93e48a5108ba76add9e94e20a5e2a69f19d192c2c6e840acbb4e3d84b4397759a7e6249e011316f76d9fe6a918bcb411d2b41b12df3e9e968f404c52385affe1025d32b530a0dd0d39c96fe17fb80a274ad549d2b69565352fe67a0e1cc3046c2f4799e360b554e519a2626fa29fd5b4e5613f0663a8f4b1a4286d80ec4838efda3cededb362de4b822a77eeb2f37b131a65e17a8b25e36343512286e864e68545746ce255cf4797d92658d67938f7484cd525fb4e5655692e70fd47088ab206cb071cb404460e22a611dd0a55501841daf09f2f7cc4fccc494029cb99ee54f78eb4d4489a6f098572b209f7bbd6a8698572b67b99626d5e081f1a2da858fc7003980a9b5fd2ec77f6c267d9c0dc23ff60f0aecf26751ef29cf65d8581206fcae001b5766c889e897218cd00b372d9bc00c66d5f2edc77bb1505b9050788d3f559107c4efca0f66b09b0c4410454668090aaa52e3a1a918457e0d465874789340c043b121f0adb07b02fbb6510f785b904758ae1e0c215fa40b9ba0f6ad7925dd69dd4c2a323374e9705cc28d65e968a18e04d2859ff82e759d782e80f600fa5afaa0ffe880b1484fe3d76fb75845eaae145eb57f633d5121d451b1728a69a9c5af05b439e133bb78f4b59304628102e95f05d6eb13d86660d4d92b2693ec518d4f24e69462116c39ed1caa37fb3ac88dbafc999ae7477069a755e2b1c00a00890b401b74619f5d114def3ab936b141edf19dab04b1f5e4a179ebfb9e20efe8cc679e0b9a499a20c06e366bd890a83673ebcd551b957ff936a7a3e36fa9cb1152fa10c1357a4bbe55b96f925949eaac849f515363155f6db5b68317ac83ebb0245891e936cb82a95a4ef75a1ecc0945829cd5ff654d7dbb97b583d92073890e82a1cee2e3ab77c1fbc14f6898c2e40b5e0d7b32f6cc28e51b5103d8c341c63a01b1ad6a431858ec1cc9d2c1fb93c541af46408be1ce1ca9eefb051ca708b3e9c54f8fa6a6bee5782043eabc72d5da51feb40c9a4a2cadb452fd0d36c93efa3538353cb11c35163e4f888300653ee9e65baee3842ca51a54d716c6000ea285175cc2d1710f7a7681c273c022aee162427bac6eab5a74b4e7a5629ecf42224c9618824ffbb6c05f61f534ce5e7e81db01ae6c6c6bde41f3afb0320eae94784d0c414738b8d34a43088115281d61cb62da069876980e31eba34442183578e00a47581ce3706640cff00322a8461865ce796d021b632265a879af27cc3a20c5ca908243521449643a78a41f721ceadddc731d7cf020e063898322769075ecd33a2c3154a701a5def543de939b43c9fae25880ed4aee9f37ca20e7382ad469b1e0981d4d44820ff8ba2569149d634b522c101630cb9ed80c17d8ba19804a392912f77d9b655cd5800dfe7c2c654cff4d85eb3f6ae3707cd52112cca670e1e44e5454ff71e865da547c91e50b317050aa0eecdf99bbd32cb97d6278d88a28af732aad02e31609bcc8ac93511f17f95070fc37aa7cfd3959769da931638300842cc5af97376faeedbb31b084d53401f55f64b7086531094b27c48ad0b115f0fc7d959b1aad516856f95dc56328609ad27542970e4af282a2f61f6c61ce69c545b471ed0eb041ae17e132f7565457e8498fbf38151296f96016682f0082e220ba5abb0ad8ca52b4766680915e205d1650fc50c6d49e221c0466fd643b42d8d6a953cc5e21d048171df599aaf542f542123b0876b620d46bab078e6a37f4b78efc621d578e20948cd20b3be2623bbbea0d23b141fa102beda7e8e9d0839d2f023bb9e1914c9d948d7ef0fc24ab504ff7477a34a96fc6e1537bc6ef55f27d16c6368ab5d5ee7baf994ecdff8dfe2bc37047131714e25544b864328dcbf92fbb02df76096290022fb461292d0f4d5a4366441e18e9a14663a3a7905d2bc41aecb4723a16ac95ee7d59a8e5fc27a1c5f4bb2ec455cd460fa4d66b969afd2f0b5f47a88bf03102a9a62c81f8ef1e566f76a371a29b8c37555e214107bc269e562a3be6a619a251e80aa37d1c38a98c3c37094dfa6abe3ec47a2bff90af5bd31f2ff3f09f3a511e9864419bf4e65b24ad192481e28cf5382561f7fa38bc4eb88277ce3c2ce13ca49203e6feae0f0bc5dce32e6f9d0830eb95a7e8f43921dd360bdb4ad3c9a3135c8ec7abca027bf3a81d9362d2636958dada1f680aa2f331ae60bd0ea70c47fad08269a001c0138a7c737736f6d922ee42f9a7e596f5dbcd2473e108515248ce9c145bdd5f9f0acbe52735eb53ab092b4cec5585736641df0a60c1cea49392ad29a34eafc2ee940c7d2188cae84bfe86dd965d2a679efafc4153d56135b01ccb9c6d9d30723b64d6a853e114f35a4fb3e000b33c11f7219c1bb869436d5af69da81f80814d76fe7f0c5fca346c39ac275a7fd31d298f32da0db543b302d4559eede2f7e60a5d2a423954af3c1dacc6a4f4e0954e37e1fd89fa101f722b4515fa9628415d97688ab1017788ece393ffbf7ffabd3f92db0ad9773d0ec3a4f0cbedc6e1513acf1743974cfa4fa90a9922249bb0b1bbb39c118b044454f3ad1d3a0ab774bf8c2b5a240b743e59534770ddab84191454f3a8fd320d7583b5732b4df32e06c216652613b62a1dcce0068adb139471c804184403b14984549e8f13e54a710924fe9374fbf158cbb00ff93b2a14085888873d3296731cd618930c83936ee610aefe6bd85601399d5b6d7f86bddc06b5b1fa10e785a01a2b8918aee9a6f582735754bd3d707c4946a153ab047e5e89ad969ee922fb55356dc9a04cda997c3b74f447cff8c1f5dbd52290c979ffbdcc58f61cb00dcba292582b3df0979d3a0de42b7417344ec426f4129538b0fd2585369a6c4c55a906501bf5ebf5881fcc9dced7da46b6e02cdd425b45b480ded9e024468136affe521a0054a6b2d2b729eead54be36f5b7ca2f417220ccf6a4f44d4a3fa2de432ec7d1036c7e2ee052852f6d6f3f96ff24189b95e2b75ba4559a2c5fc3ffa13a9c3669a9981a625e0dfb608c14e722d7261c07cf6954b81a91ca482a234746a74cd70511b825f1a0bdd9ea4a2542f2625b3a509c273d7b731e77874b1f13a8460e72a69faea0197d0d5d5ed5b438db26aa7d8733af50e39b2c70089b8a9eecb64ba2b43c03bac29bd06c38e5cb9cf68b7571beaf8dff317194f2fca4927c933a4edebeca13a04b7329c759a5cc1377e7433d9d9b9f146dc435e749141173c1c3151ba17c07ada58e81876332fd13d055eef69b415ac3044d8cd3477e8cb2462b356a890be8d8779228078e2c5a383db483dfd7c6d00f0ab56c09860b9742ba8432ce6136634034fa0cc8e0adac49a90dc65c2e65d2db22894480aaa79763da47d231b7db3d32b29253ca247fbc9e79ff5b4bcead3fe2dbb4a52f8fd8248801f300a4eb1e51fa0688d0ebdf256938b8e2a7d91a0fdb992a9040a2c44a01d1ab23778ef4adf57bb87e1e92160de955d63130ede951632bebe2c5b06547b1bdf19d3713592511d312c54644d8fc2ab932aab9520e231cf1cb27c3e89c7ae3e0c20710a3b714cfcaf95201c5fd098eab2f5614b29238da7ba800fa3497cb66ab5eb6b75b7c02ac2588850a45841f97f5a64b19a45760657ae049040296272bb09e23e87c140543f7b8a4d60a529a51220df11e91fdfc1af002b12efce7b9644376f81e4e94dbb4235d614fce00dc3fc299aef5b940b75290b37b44c34cd2da3738234fc0b20e854100fd1bef48cb9744699af523a2f5144d66d50af156d92384167ea8ffcd787e1ec1b6f5cf7df126fd91e1b4e585c12373fd325e03bbb7190e9ad4e0c72703a68b68271defcfd9677b23a166d8c5776b027e2d5ed02535c942be13dac3a7d47ea7c47bf3c3fd8b106c6bcca427d33e9f595117e0959e0d161270af9132dfef909ac73c13a8fb8bed47b81dd9f3f2d8e9f15d6a1b70654c5033a1c55ad6f5ef997994d3de619393491b6cccfe6ec2b57e9c2fb272aee196dd7f22e93b99c863df54403fbb3e27d37a690509b28035b554e648da7c33151fdb5438ffc63cea2bf246910eaf0e7b4cc88b49a99fbe00b195857ac0e129c530a377cc80ac974c74b83e3913da4066809261a5e299433f05dc1e7923093e7f8d29fee14f9006e489dfad5261986b6b25892ba0aa7312dc2b09415b5c4240cb05d620e36ed118ffbfb7c33191306a96d5771ba3c53b94d4408e44222f4a2987803e1f2e6f6e45af1b326f8d6ca77bed58f5f298fec58a7c95bc55b090f95fee694081fb536004b87eda39e5335896d8837f8134379cfeeab19b94d1da87f18d1fea951b53fa834e22e8cbf4788cd6a4480ead97250c9ff94e4dbe6d2989d3f7c9030f51beffb77dfc34691a41fff28718971eb11241795a55b4449a5eaac0f778191f7e6671662701284d9fb2d1b672a17adf8f0b325b78580f2444a84fb2229856a08f5dbf9322c554652c472af56186ad44d9f6f5b0c1359d1c6d58bec2ed66a590e9722af0e2eb8534fbb20027e48938b3b053aa5733d2f5e7e68286d5070e9b86ad911eaf8610df35c159332fefe83b18de39aed770859b1b86fcbe3bce19e14a480006b5611d98fefb5ef8f9e7d9b3521d382e375036b30ce9329529b2c011a9828f0e2b17ca5992706f440e076dfd2cc141e3ac2070ff416bbac3b64c39586f4ad65cd9d90329115c4857bdad488267b16e0420ee3c614be0b688236204bfae1a628ca70f5f278a9bdf1a781425f19c92cc873413f1db021648e1ec950a809c0cc8e58b1f22e5896145002e3e7490ac94dea751ed1fdc1ffe4d0d3bbdc5e5a63fae6762e9cbb2702ad62c5bcfbcd0275df23410bd8c5ffe5f2a4f97fe98b8f8e8856588097f04c792af45db8b253cf2cf06d2e33103aebcb893caf345c8b90d99278ebcc5f38ee0b03b8c78703db3054118db82421df9b57a950e57b930b058970c77a8769a0b6fe11b9aa72fe68a80f45f001e554070a4a93e57feb6a10df68fe0839b67d6a49a9005ca84d753a761d2b653e6b4aa93628be0af0019c71d4ea2a6aa5777e8dbfaf8c685c261c318c49b5a63ca5db3b10544371c4e6f26936de4e7c90487472b4c645903751f6ef8f6894c587da5d8fbf2b5a28946601feadbc986dd8a6b8bb6f7a66af8fcd635d717bf51c3118b59fb93081cb23f90ea6113e67a1862810e7faa88bb8adf9a3420800c52969d6eb0dace5bf08091ec91855500f6b2b4a0944e62db48ea660bcabac290163fe8783ec1d8b3bbafecaa9a3d1e701cffff9ba6f6218a13a5bf0a15834876bc7556cafb4a9d139d6e95ef58fef0397b9e0233098e9418ed85560bd6690a19483e2af3b3b7125a7b2287e790e05af50b42a4fcd8d9a12166d257af7c3abd6b2c68308c824df3eb9ba69e2da4e2eb0555af20f85be582d761778f92c40cdad161e89d0d682916b21bb305e5418e015f5cb6c06ed8edf466f5470c3e38ac21b9868ca9af622cfa6cb16818bd23cf28720d534255bf1eb29c43e3c81b61493299b73acb33d06c14be46e43ec8d2925fc44cbfb40cdf4d45d2a10cd6b9e889f8fcb13c045be5c9e3dfc11f0a2a465839ad7a0a415c2c30c3af27670b126e782f2b9dcb46880f27a43625cf87455c5698edf8bf31039354d86ba908a5ca151a6c52188dd9ef4133e3fff4f8edb473146ca5c67ac9985720115cf853d7b185b12da78335876a854fcabf7f233e740857349be3a8a39649e6640f3d7c7ce7b1cde3a1a27a98cfd91b37edecee14c058f4c0552aae300133b1c6642b1bc06ddb77cf77774104f0b1efb892f9ce0ca69510229708223dfe994edde5b792d5d960f8dce8e02eb7d6844d2dc51d157d5d63f751a97c519f3858d8cf1aa125b43e5d23c9607f1986187d7d583a97bdd28e1887d3d49abac8e2191ffeca0609aff1877514b905e7a8e6a989560abda529a4dc48e26faed7b2fef60fc823b92d9705fce99baad49ab95dfb85f1dd3474b3c92231cfbeb9bed3d780a42fbcfb222dccc7ed8bf02ee691fbe48d754a9f6bc1677feef36dfe184f8c68919ab728bcde8fefcdb441cb24ad1b54449513b6f87dc91cc3b0ed00ff2123d12a54c913d3fd02178e160f5ab56aee87b622ad99362d7a37672f319197bfcf45e97a20091ff72e19c0242992bce3ab55517c8fe94df26d1b16ac8dbc764bd9c0d5322cfebc20f2c375705c1e02c6337c09b6d032cbafeb30acf05b398ae1239ec192d8a3f49f3f48f0c7c64d032b6b7c49e6fd3cb01e0b0ad634cc35c729d59bd224f81cb342a6f58e6eeea903ca71b992bf38147814839034aa0290dc9bc5f9edfd8a42106ef7fab25cee24aa01d0ab9ecec620474c054247502f788913bead3d2559eaf79547205dec18e8050c01bab45c3fa01e8bbd94ee39e7e4111e10aa0f088b83a0530d78e9af5e7f897c8b75a87094692a798731dda56d6db32cc6437f717930b823c93b0bb54fa4eda11f68ac1c8511d85c3ab85025f800cf6f1b30bd6b0698d32e7953ccc8df96deee47eab0d973b75f6ee1dda4d12ca65bf577d64243aa96fa4a23b0aab424ccabf9181f8fc796477e1bf518361a705f44c0997423dc4178b3e5177e01b61ee934153e72843f90e0cb038841461ee0a9dd1c4b6a5865f994e0ed4e8ef17f3ae6dd81618362553ec4c82e79e9cd6a28dcc08b01c12021edb0de622ec517e3188759c009cf39c99dce9f198c97ecc5c178e831ed2bc14c42f5a4448b346538e38d3af1c63c717fed3abcde5249777ca524d63c555357a55306b83cbcf161ba9c8cc40c9e7c8c56cf37c86063f7701728f744764c9ac4a02c73daab6f9d778334fc7436853c51696c92493f69713518508d814c3e4b9031abfbf6f00db522e534e27bc70cc6e898d0d38b4576b94f000f4f150c1b8d947092d6c10f4d019e23f4a7e7650eadd991041e3363cd35890b8e22d72be8b3b9c038b4012197e9ef68df121242ba4c08cb824dfb28174d3e243ff0034eff232bf05c5426bb9f953a854acda19e99f33dfe5638d54b6b16670c19db4dccea85bdfcfb4b8687f81ce873ed64d3e3e1f4c2ea0df642f578abf6cc4e4cb4a71b5bbc11a7aea5257b05ed844d4977c643ea7723625079a5878c830f172e87ec0c4331966e6d4c59ef9815ddd9bbcd561f71a8f70ae4fd8daf4467cdc710911c30d4f1948e7076761699664e7eeec0431925cbd78c6cd170f33e022dcf147093e871f4a50bb234d800a2f27b7cc29df3a2ef92d4879d4697c567a0a9defa65f31baf3a7bf8207e436394dbcfe2ae6b76f741a2cba489fc5bd48427bbf6a24c4fef78ae5b3ddf9b425c529753e4ef7a9545b65af10b964fb6a9e7913f22ecd3cab772bdbe28c05e73acfecf73b000cada683b9615447a54839771794c42fe7c5d9964e4bedea74d2f64f2bb4b343a9df2bf9ad1c9f34e938e4aadfc9ef13cd39ead8555b5c998938d545fa9b7aa168beeca7a2ea41cc883bd110bfbff34276251b3503037a9fba98d8a633187a9ad00340ea3bb84e5663ddbe85a0dd588410148b3b9ba87cd0c744804d645735f884314b88f5beee86f9d8d371c20e293a8ab3b2d236309dad668ae4174392efb181e9bd5c6cfc5d7b53e73a0c687f0f76044cad80b030b324e7146f3e1bc792e609146482ae796976a4c1d67dcf3c354e07e31668584a9cf38f483780f1e99da5fc0b501e16b2f8a04c1abfea1dc92b3a9094c7591fe0cb277b6984c7832c6a875dcdb96a7355ed51946ee848673bb6fa3dee32b2b57de8460b0323fea9d4ec49d96da198df3bea137496f05dd5a0e4d37a9216e95b3df9e37285d6de053ce093034b68c1374bec1a879e090cd6c72efd345e411bbe56a6573df724334d264b267cc6aa09130034746351e4a303157ad80aad83e2bec2ac64c9f4b2c76f9d5eb00376b0804ff123d3f79549239dce5bd88b5eacf3c46633faa89815b7adc3a9735d62879d189062c5bb51b6570db95bace9ff871b12f5b9038a675a61b2205ecd2ffdbcda62e6d0a5f9010ca25747b0a3ae540ccfbe3d4dc2a0ab13ea6736c9243062afb210814cab29dd2ce929ce27bc5c0bd812549edd07ea62454b935974d4488c453f721cf700c08a10e37255f545529b0265ed388524fb7f86a4f1a2f8b8d110ff520da45642c54d7aefdadf14987d1479a95b11a528197bb7e3bfb137af6351d4baa30438e4dc9ed9dcf425488c108f4f0c4cb137e66fc18fa55f190785776a0b355f903669d96b4683b39093a6d9c77fd3917f5092734b6f1a9a561c9dcb0c7b9291f0a178d4164a5beec174378015a49b933614b2e8861e1e148d637a4f97195446a8f61972b67801e1adcf79cad37f21001ba5b31bc0e44fcfebdfa32ae9b7a7dec4ec3b8e5092afc64fc1563fef7adf69ca5805569c888a558336647ef32e7d4cfdc9a2336172bcce3a5230d6d02e11c82e3eefb274bf6fc7ba79767086f1a34a50856e8a7fb4e8f20c205c6cfbcbd0290a27ebaa76c8192bb28732725852f4e0b5e685ea9ce22b10620ffce58c2a6db3936fa59b54473b58c3eb1c373e0aa790b7d9f9f41abc80e3bc62b583bd29aa81efc7c30586709e6b9f38ebd5e03dd83c35814a2bec905e1354fe364ab8009f9568e75dbe58222af10f794ffde0458fdaa7ebb97354c6f02d5e8d5a8be02c9273b507727dbd04975897f9c8e234b13a70e22465db48d364404bdd4aef5d54f6cc6cffe2cf70663c747c75284b14b1516377b5a8d67e29d3139d24a5382134a962341d43230c66f608e934d6b284e8d3988b5f43437e7d329c40cd405c44e9048e003ff73d4aca4c9fe4c053e888dd38fcfa3d2d6a88f0397595f32c6e18b88ab8663857f5c41e93ad3a1df6e27e6d0292e478dc6f8e10187ba2262fcc156affdeb39d3c600b578656eb6ff5faa86e15fbaa91cf57ad561a9d0eba6337cc7e3c366e9092c36457a57926da1bdeb3b122708f19991feea6c13b147a451df681a071fbf2c41de91f865d4049fe3dd29c98c8e4d2ce9dfd3b294c8017acde5aa643979784e1566d7221ff7acae71d8667813013e6ac617d63bbc77872e2956c418f1a10ca7593238299f24bdb9fbb5c8ebe205641e75d0e8b85b11b6dc57e0be057ba8ace9e612844bff75d973e7c632e57b2283e4c7a6086ea31fb037c8369653c8513aa0830d9cab47fce14ee966b520bd5286425e161f6cc7fce0da2b1351118a13c394775af0aaa58483b14493728ddfaaee96f49804869a26cdbdcd23baac7f9ff820faf588f73a8857b938639023feabbb2aae1953c4909a64497fa1209801a498a51074c95cf77579df848a31865fc394f30bf68dff472284cfe2f0b043fc52fb9f0e927636e7b5fbce922a16b96983bd2b95d51017779fd6f31d44e77b0cf6b5a8f9ed5986e0efa3e961a6e9c91ef590e52afdc2e942f57b957fe40ef421d77d04765bbd795a703e0530f2f34020ef643365f6212fcfd112a29be6f9ae54d87d71960386f2baf4b91703eca61f74000f9d8518d7cecb80b95dfd0818923a5f256d3bc881fdc335f0a112bb7fd9f160fbd91c1536dc7b12a4ce77101398a31755da91f9a2b9871cc55759800d0aab556560ac3051c6a1e969704a12ac2072bebf0f115d10a3f825a8fc4dc700f3d998ab311e4a2f38402c2350910d9125b9e5833d1103ab53638393f15f3cfe00f92ed621d9b77bd9c026233649ce924c6aaa6bbc174626f84a0524a3380e9e2cd9c0f6cf8fb8a38f76affff10afea89d9746a6febebf70ad7aaac1cacebd33aa2d419863e22d4eb0cb7bf98738c40354ae8e187fab46ca5a2bb540a6c30b0bc1ad0670ed8f112740883d9ddc20407cfc560b5c49a43812a0615b8bd8f1aa79c7d9677a6823f8b8cc8e46ba08c158a5b826ee46406e21c2884b54938cc9dae1e6abd0d933681cb72a922c1945f434891e9529485d8a0f2d4a245be1888c635ed0041e0571c112edf7379657bd02edb3604623060b37d9be7499ed24f40e710cd742688987c3a629db429d739b36b503ba4c234e6d7769bcf11c6c1e3e0a0160b81b3972c6364a95722e381144980d1df9040c9f9e198cde30cc19023179edfbb21130e8d93d54a147cf245bb01b56bc9651ba14330f3d57fb26d727df6cc4c9dc492feee249ec295c7a04d8b1576846b29ea80d17e6afefd4c005a18746c5cc8a436ef3aed4700ad55045c396b585472f724970be262c4259935da85bfc40d60d0a93a89bb5e7946d342913d86c3b81390b944021e7d4a280bbd3ec45434fbc6da17c3f6f76c34e3360d536cd97a1e8bdebbac9d7b17c3f2aee0a2c0db0fed3dbda8281d5fbc48c31dbf3788c9284d11ce5c1c89849e01395d540bc5b3d899c68157c44456a1e34a57a87c2009724f149993187c1d7867081384777b2a32da95939e6f3d189f1c9d7152b269bda393c04c2063c268d29d8a7a957e1fbd80417cb85e38767a853527a998b913aae8e0411e16fec0a8faf4fe136e278edaa595f3534586911143fbdc4a5c040067d5b2ecab2542ee80896dd144126c904a1766822a02d6ac22c299c9bd292ca3aede53db7094e2cba2821684d0b5f4ae581b3f9badc13e7233c6210ee0c251e86f62db001a90749bf9c4580316a29caa3cc195423bcf0b4cafc8c4af0af6771ffd7513b31dd89ef8c772485dfb41686f92cd3941df273a293bd6010509fcffe3cee99c26744d2382fa0a9740aabc6635e31dd48bd440a968746e5f97b67c3f41c7e35283e520f1e50c4560d917089f4abe120f85417f1c602e1e4af8d1db73d23d691e2b1f93a14b3e2df815b906253b64ddf31262e823e752196ba2071ea22a448f9f8addd05db9fa0153c6c274fc4a485bc0e5796dd1e1e5fb82a2cd3c88c6ccc194ebf0ea867c88db2da0443a731e23fceb8eb084084bdf1b9785f0ca607bdef3b3c28f78e55e28efbc95b8693348c877427269fd7b6321730ac393dc95ecc23c9cc37175399d2d8602e6556b97e426d6da4f1bafdf7eb280813e01f968e9cee7cd9dcc389831d44289c22c4bbc2e04429a506564971111e9285b3edd0e102b1dd6d20e65c73d442677cd32c8a422fdc2407d27ee92398966981b5617e49029e992c0daff96202e163e19f38c19b5da56de7f2b3e855ffc1dde515b9722ada399274ede13d5a6956cf7837749de6a322a86a6e8cbccc5ecdb3adfacbea8d455907b87d466f6a6c2fead2fdbae7eac3490dfe78e7315f26cbf575dff2eca2bb9e6c40cf1bd93e682f5a4127abb1e825f1bb166ca80df9616d22406d28ef5bb20a833feca0bd92c3dcf8530178f8acded12f9754eb570f236ff7aeedf620b491052f6d4d9d2c61fdde387034f8baf80fdd985d57bdad5ae393c2114983992fe4de81a37cce1b5b6e5d03d850def948f068b4d27fe6767131bb60129922facad0ecbdc8e7df91954e7c30907b7503a8b35fe220c6ecea5e0f524e6bacf445ad4fef7a31a6921d211ad16639cbc34bb2a2c2e28bf82d40db44875563767f7feee50f5c16b0cc79fb9015b66d648bffb3fa72f62b940fa6ad888e9dcbe9e455fc614682cbacbd91aaf5fb95e4d0d76117c631d9b4a15ad28f1130b05a7a853fe2e64d4f4e51248d1d09685422cdf4e110fafd8732f2f809589696d7351615257051a60e0f9cf3f240eaa87bcd3a5b8a258b1b19eb4b568dfbba5e14018b120b0f01f0e786b93497d0ef674d1f2d5e5dcc32955ee85473ccac9e13dfd3fbca84926d48c984e9f41e5179add983d1a70653c5eefcb1b12612ef302e610cd4a637e946f6223fb2603f49e6bccf10fc47abe43842fa0ca449008abab34c897e74b49cb6cba57048601199537ada51a6a458693fefc5b75d58dbd4988bbd492f500f7d00bdfd342d820a1471f23ee14815d56b5d7c6239f0f0f70f1517c7a8b36de07f6c62427b04e059f9dfb65d626bc0a6ed58807b00b2241e1da33e855640f456082637153d49321cc2e6eb85560d357f4c42b62e88a1b281194a211bd11f331360349549fc9a3b1f36d58f8876ab841f8bc233b85c6c94214509fc2fd5d98a763c1c62eba0a87980a02f63f401a36fde197e3dfd08f62cace04f0287f06ee830a9424d6166d1d07992bfcfd4f91e02daf2869e95697b430d569575f9158b6bbbe1046a08e40e19fb1bdc9a70e5ddb5f3012b2b199598c84de4c3ebe60207afa6f2f500a15e3950ad5435c89adc8b3a2634f56b1458f1498cc9b811c4dcac8abe738f954f45b0016d7300d62dc1f2bec0817a05589e78e5f0b7b3d9c73094ed3205ec6ddeeed09596464328730795d7eaf102138e70ded3ab4ecada677ea7f6be7eccfe1fa37e0712ab605c0802745d5c2f61bd4f720bc12c5ecf3c680968c59b8abd8bbddba0cb6f0c52cd7bc28f5ffc813cfaedaf7f2b259783be66244cf89f40fabd80168de87e408f939d42c1f9afcb4e638bd751029eba4ae6e07621b196310ecad95189e7c7053314e2f2b433451a1d70ea7589a283f25830d373beca7378c43c30b38e40ba92e4bc101085a1496fa63e0226eefda58109c33f90624fb40fa34db777abad28eab975994d30c86e9ebcde7ea6c3febb66d5620564d6d8a88a2162de3dfd07d69bd993eb5cb5b65fe3f6e1344848728df60be3baf1b7638cee8e02642ad3ea8294eb166df35a09703cd8e1ca7103b1c59d9293ba7a9548eac974c833e2256cc5fe8af0b333c9db1c1f2d351bc8f280e4ab9fe42fd48ba1a9ee60009cb68190100604c2fe1015426666bc3aaf26f8e8d5922ca44c26d81af0f2a703455e52acd24a3f9bd93b912bd80b9238c9798ae9aeaa50f38858aa40840a4ed65cf9bf75b7d0d56c07a68781cf93e75baa5b5053cb5d03944778d9dd74eeb372d0a88fdcfb211c3447628518a1b4cc15968006ed432d1341c259f8976d6168d95bb9e4bc6f03efd198ae5b19419d4f65b43f8d3a914a7bdd2d55edd316772a7e00df0438e0b7710fdc747c023d389ec8a8fd280c9ee35921ff155763b0e6267be4ff5b94a0981705cc1d6580addd78e711e88eb37aeea20afe2cdb4801e2be2db3c999450e44d5b361c08fb76ca4aa7cd27e1cc1b81e354cfb99c53e064bb50ce337174350a54fb55ba7752f17908c2d2859e82b054376d4bcf95f10dc8fbd5ef316f8e04430ee50ed489ca8070d24cc9ea689e1c8b9a5c0ecbc5024940e5ef6b83994151b7c333779b80ffbe5268cdf5c159369ae3e8bbd6251b1f939cf45028ab2997253e1c5394048cee1d0be4eef1e6e1a0083312b8c157484591898ff201b87eb7811463f96b8bf4d5cfc835960db71ee61482ef550460c7eefba06cd3d6f445358719a4fe9d9d4f0fd036069afe2eb15979d59c8d54077ab7fe0158de7408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Factorial, "2710", "0", "46ab3ae48966202d0fde097bfa88fadc512ae8afc0ea1d1d376a4109f10105e9e21f1e907151e85f926b8d82737b9030d572715fa32690be8dd16867f348b981683cda4be4f9e259977e69c16905ecee567d26742c1ba1cdfdd1274a067c3b39020f8d500f1199aa73884607e93fe423a99f3646585b76278922e3583c349cd3368417a0e630a075839ec290393d2f669d948980b23bb114fac5d62ac52e9883c9e3b8e0cd6bf0df411911f40d9f968f8691630a6033e9972c3090ed2c0ecb3a3d8ace0be058877cbb7e2bb8e9065af1d1eed955881cfa5ab0a4e155f84311203ba7489fdf5d08cac67c97920e676fd54a972b0297285841d9ee665dfff40bf3f162cc2a4ac74be168d996eadc9fe38b406af8f23cad528527097e4247c49d52aea83abfd77472110ad2dca4c977e104e041386a942d62e362e968b12bfc2549a5a3cefe5bb6b799e97d12f047aab8e219751f940689c3278e3e64583fbc3ad07d44745bf43feb42a8b7a860906dd98a5eae125fe7f3a013383b23331796878a2936e276a021f2fae759567bc8a261a4f1b8967ca3dea6d54ff6f97c97c791dcaeb6dbf4bde55bfaa1ceb679941675d1863a9a730e380099157bc0887a09e4b3d255dea2ce3fcbdaab5a783d0c60dceb7be6194d9ae7dcc515c4394cfa8b0fc765ddca6c64a5fe82883d6d2340f71ee3ca84f60339742b3ba82b5f05ecb540fd7e9a97c0a78e30f26307137efaa9aff7d462bc617e6ed6b9a9ec63728d4cd5b1a7f6fea10db84925e948df375d23ef6f7d912bf9c9af213874975b528b10fe2b791b39d1bf875d01a65b3c17d97ad2fd2eb5adc8a8a4b9516024e92a37ed14d6f087c5b99ac523e7f1157817eae88373990d19998b0a412e8add60b47f61ffcd2336bc3c137857c698be679024789ce95c19199b13a783f56a7e15ac38e63155a08337a9d4305cf94548f6788ba19af84e2c25578a346282e907c3380200a1acf5c43ef3b974da2a962acca9caeb1bf88e1c4d91d1f38164a360cb6f5fb48b8d18d9316023f1bfa0590c4a68a4fc49d4a17ac7d96dee097b3dc5c9e960636fc9a8c6220e8f3d6d0d7a79dd8861263a876b4b16b749c4ac6b4dc708d08f20acf42cbf98b7f4b9ece0f979d35f2c1dda29a8c313e23dddad30013aab39b415a058a2043350ddc2fe9ae3c66171fc1e8c54f59e53f734388a013b449ee0dd9b5eeeb432ecf6e60c14cde94916e0154a2baf84a3165a28ccbbceb5017504673bc32da530e90c8d074dc6f2071c36042d41f8decac8968a61445097cacf98fae342ecfaf7f567eb7ed8d11486c5c5290da57b6058d1799ce94330dae1e672954e134fde55d5629aed6f499ef81aa7c8dbac75ce7a391f23a0ea37cfc1509090e5d67b3989a6d01535e083b499bb51b2338f598ce2ad3f3fa614c2ca084442230989f8b464af87bf519287198f75949eacd7c245eb00f1fb2b055932fe4bc6eb0f7d6520030d93ee1feb0ee237a1114e6e60a49f3bf5fdff37c3a136ea5f9237d194efa6a7d551a64325d4708e784755cbeb0326b906df2161b5438ff1f91db3a60318be09b6c19ce0b8bc2f5a8d11f5dbe8f4a8c8ff47beb5cf58ebdaa03b69d29d6ff0c68115b753faf65deb98d2568867b18081532da2159c817d0def17c0edf7194300dc14f751694964043934a350eb0821a42f8a651e4b66fd78dca89c89d1f8d1c12f30a87f4307c58da161dd92214ec84fc4b2846f6e8265497ebd458c19832584fbf09437df477fde4dab76e8a5e45b78a23961a305d5351e0a9335cb4473d8b8b4e4b08094e93063792cc1364272cf4df8953cb07302dd1bcea4b8da10fedb4e201fd24fe4d51df15f9681fa9138784167981b3ec1f2d1ddf31e441cb7706b553053348e79670de2a3f361c84aca5ca4c582d19ddc3431961929f21ca5d5dbfbce6004da1e1f43d44273bc5e9f7ef49048bca2752a37c586aa46f75c3556e40eb317671ddac982869d64f56b2d43e249f75a9a6d1cbc653fd797b3cc455e0ed6a9b50a8c9520390b14938a545bf5345d6ad4e1866ad9e97d054508a6e427f008549813a94d979f5f23ba1f7978569f16a65fed6be7acbe5c98ade564e6aa6cc142fd7b66298c9d4c336521d324d5f077935cc1399d886cc10abdc65534915cd91cbc2dfb0306bf73d81f4ef0443e619e40b031ab33c9960553ea696def99741c478a0ca7fc5803e47bdf766bbf3013ea912fd3b0aa35d223ea524ed2ab1925719d95b9dd9091b328a2333f50ff66f3320fc45a88855f82cafdcfab6d5a63249080e513974003149b5ec731740ce5b0479092eedb086fc3d31aba7ab3abaad48605e37d5e82ad82f3fb34d97be49437a7349671b730ce1c8be8b4b7ae36323c240efbbf98ec3a90e2ef496e4e1e1b028db99bfa5a8933499205543522715230a86afda04348d7e8b7702d15dd2bd96d7c379c507a0413d4e9f5878b55fea0b08aaddc25b4f42a76d3ae788f6ea6daa6bb7c3bdffede9016fecb1c11759f061784127c7da411a7da6515a8fc32d60a9bc91bba213bc7c6de230ca5ff5eb23a759fd2876817c42ac700b938fca3d0cf04537858c05552d15a90b8097f9dabfab959360f0b28e3709610060f4df935282a025b0d61c503220b69582beaeeab70843c2c59585d8b8c705975064c26d6540afd294b4b4a05a9053d0917b0fcdbbe6b85f70bfc801758222402f44303d562a841ea945c7bd52c464942738dff502183b9968fdee9c14f72f1143f2ddb48c372aaa8301e89ec506ca67b412548375a53844742fb70fca23796e3ddaf1b0472cf2addb4ef0abe6691e00bc11b637e5e819895deb4bd02431785ee0286f544578371e9829993524d558886c6607986e7b9f113ec7068998a173bf8b045b0585d065aca7d20d71b238215c7dff981310e21c6ebb4753b34b506776967a0234c1efdf988f4028e015c6260be9a69d8330f71081a36447faf7ea5ed5f9fab1255e4ac5b935ff77a58aacc24ea6a3881b75137377df9734ad197b9e4db8dfc6e4bb56ef57b13c196e064b34e4e53c0dd3986a2238965b1fbae3d2cbdd5f25f6060f48867b89e848bbe0f58a103c496697c07e6eb15cd1aa946ed19b79b178345db2b04150a73d0adec11c73675a7aba51582b460d89bc5a32aaed5694540ec894a9a574588dc97fa84bbdc03183b7172dd380ffef0d87fa96d1048d475f8008d8ae72484a9bfd04f8863844365d014ff0acda7af8f8ad80bdf7289abbddb4c7f6aa33063c758638afe3c0c92f4502c32b41c5b0dd556590cc4823805ca76f6a98c675bedcbe801ad0d8eda46a842235096235d29d11b2528e5f135cee19fc318889d0aa32985fd15c2fb32df392767fc3c50f2f793432a07ffee46fd84e98cb1b3ea2cfc39feab6f285429be0378694a3100cc79e3736bf815df3941133f752bb1f004dc2219c303301a2a8cf82c082563d4a93c9ddb1f9dc81d48020c8c012e9b1428e2b1df6086c2652801ed0df764ec439939843af56d9b57aaf5b3d271114be8625cc012196e0a212e84731f510fbc65709c29ec95271a562d8a0b29792e304558ca06875505c13413a6408fefebc8af202e1749abf62fecd8c7aa9fd2645e8b9a5984c42a99fade37e44f25e5fc8bf9642e1a87e0307ef779cb8e9e78459563e96feb51826391b1904277fe8f817ad0b01d6f8c76658843d4465bdb034ab84497ec0bc0e10ed700c01c51283fabcb3337f977035f5678dea02687ab0e6bc300111f788db415d4fca2d74aa8e5a1fbf7173cd4b6ff754a87cfaafeab973ecc0234bdeee4f15f8209f029d9e92d9040650c7c974e033c1a27c94e13bc7dcf16c9968b12ff921eb40124abdc99bdf9790eb802aaf89dafff148ec9d85d7ec90130bacf688e47bb631b69bb7a26fba906867cf665df8e8b0f4f5fb5f52607f07843a02ec44c88adc563724cf225e831169d7f1aacdb203faccbc589c3ee39235b246758319185a16c729bbceec30eac34c5b6c14b20d9ee7253c43c8925b5b04580a50ac16ece44329c369bbef09138186d0f5d866c93445e8fea018618ddff8024fac522a6e2aca986eb7c2a4fc9a7a76694ff136124eeae14c33413457063f7187fb4a95aad2b901aa5a37b08eb3d08e6404f27e04ca044d6ea1880a06596015213ab62eaead531c16a25b470f10f5bff2f5ceae0dc455d8d0b16a320b3fd1c43e4d23b77a1538e44f085293aed9bf9ee0f09a3a9dab49fd884760ac4838d644fdcaae3d43e3dac8cfe109d061052030c21eea94fdfda541af578bcd7177df332e2d6a5c24930548679a9b7991049d33249fa188e5d48b7aadb2081453f9cdfd633789f5f8508d0584c2d99876c913ead946c9c7f927b541e26ed87c9aaecbb147245e09062678eb4feab8913fe570b3b59fda8aae679129cedada0e258d697ba4a44676dc457998321f2e99bb24957433f4de842ebdc3b29c00691ff56c0293a15dc05e72c01dbbd1e836fa990e83820f4ab1800e0864fc430229baf0593c9690b935dd19958c1ec1372479dd89e738f553a994003c0d716d0cf6ee13bf24f9ebbfac05226105f210e230f75a60c919c0cd358b08ff280b85a259a68d916b507f0ac6c11b4f13e3bf70a2e0be9502030e308a12f3e42065e0d119fa7ad365df0d40240e04449f3618a64750d7be318122d0a58d943dddd57d1b95da2e6c42d955d0589d35a5c912718d79fc98e451b51271163026139d57b534d2f847e766999e69e0b5724b7ccb665d10c3cd8fdd3f56ba2adf83ad11cb7debbb8f699e432fe89b97abb7dbdc7877616d2a6dcadf6b5a1918479bb0bacf2717aab4ed45a77be27ae4d07d934a0e805f43b961c70545aba66e40b463104168d693f87418905ceab9b9433455564d4cc6eadb867cdc3008fb5554fcb9f254947b6b6fe2dd03a499eac56bb20275bef9b4e680a5fd9664a61177ab24588bdb131134cd3cc919614459796f2a387f903cff1a7cd91d31ad12deabd1081f116891dabc228a2cd7c2684aaedb49aa19cff2a68af4b08bdccc7417d44233884d68e47d27986c381b8fa4346906363e21e0e403e35f17b109b085b45c8ce32ca30f20d31c71050304b5be00617fdfce24d273a9b88e37fa9d2a30705387747fbf1e2ad21130ea10c652ec3a08b9414562b3b6aab2e2255e86d7125d063517441df00e4c2d44528ef32fca26c30a3743488691ee3a4ea4d3ff747c62a43d78912a13bc778943b31d154a4167b6b1cd0a826633ed39496d3d773b0c6869acd6384c4f31c531288ff5a46656bb33ea9122b269c4fcc9ca7b8cea33025f62703fe5cfe21a7f2c1e7346392d06e8562e8d119192a73f20fa7b458f30900f277c49ec0b0ffa82e158c5600a655b2863a74d24a245ac7c1be0bf0e3cc9ee15eef5ff6e4202fb837005cce72d678dc38d41cd04f5224ca9b7e15d640e2ddde831da01f70f79c38f865cfd1d0ec1fe9dba06085ef99f55571fd236a4d5a4021186a2d7c493d97ff957e2d006572f31932f324a4e49dbf63e306dcc8ac43aec139d505f3e0f815b9ef2be2340d3aad5e80ad1881fd1d28237cd2f40cc92106e607cfca4176543bd4bd5108e47bdf33383dc72f3c18e59fe5e6fa6a5d364a3d882b77deb70c8889fc9ae9f6c84bb6ecb1c2ee936c84b0785ac45d301b30cf5d4c438571a8d64849bbd99d934cf5b1561dc2bea6c2656eb3787f87ef872eaa59379faf661cffeb3988ea725eba5ad2433e43381eb052b20a1014a26aaf45d471722a632da82ce5f5063217353b6bb9b07aa657abf30f1557f2de74cc2916f4c44941942473afe31946d7f58999343e3a2661f2f22533b2deb5a1a04abd257c01038575dc79b29b7b7b8f265b0691fcb9bcbe1313206e0c95d22258d8f18bc01c9aa8c7f08cf3555ddeb3c06b30b9794d80a85518a84fe1a2d2845d66f0aec9c148dbcc2cf687b40e1abbb5d3edff42f4821fe73440f5412451c3f191ec8aea7953317cb4e0820322e5fc395abc83be3e85fae54ec77b1c7dc6278918c3bef9f9ebc4a46e1c5f68922044b50942eb00d981253a2eee3821954d534bb60dff4c7dfc6ea796ef28371db88303b23ae012eb85bd1fde4361782181cc57b18f95e841d87f31afed1ab5fd8562dfa2ddd54e0fd7344eb6120f767821decf414c8cf02293bd351d4f7b297a3b58c57bd8fb73705922bce5dd8d4c32fac0f06791c76d8a85e08d19bf3739cc6c62f77431b6f264d98c2a74a87f9c9519612ca28cedf14eabde3732b9fcb54befe49ded72691a9fe75e504f856441f7e55d4ff1f56d36774106acd0e7a7203704e4fe5ff1fb0b61ab765090001d92692884a41b3ec9d416f050e09ae9c277308ed872ad7fd6d13ac276c9c80ec92ca00fbeb3b8cbcb276224740bd1a49b456b6620eda9afd5f3c0d107377f5ad0dc2159796eb36480cf296bc6915c53d2d7dfd763e0ba0d24123e4093c7d5575c916cbb053356dd91229a378338d467e3f52a9a79ecf3aca1d0234cf654278e9e5add18651c08d6671ce942e16ff782db772f4f2660c583fd6409de2aefd2bacf1a9d69a5ccd45d747fd28159d26a09c017f3c5c17eb25d4b1d406eb8e57f63178fdadd5d5459cc27b7c79758fd9e0dacfa35b7bcdc1c131faeaef6e7a4773551ccdfdae6afa29eb62b2d5c13a004ab5332dd8aadd891a8ff858044caeda2010f08350391d65a5af5804d8686b233699fa59f5a8f8150d72a099cee5fba38fc1741c00867efad3676c2b10e86bc781b0adedb847d80704688787b67b91c17bd80a48b44634fbdbb448ad71592b525be28914fbf171ea3b21cc1c4dc9480f44c4c130625a781856c42825ccc186c689a2b0244c17f71d1173ebe9fcfe0b3cd02e567476294eaf606d85878a8e79ad6c784718528131e8c7407f6139cc413a7e8af3ade39e0d9b21051d4e9d9c96da56b6c19e3a9cb183b8d4276aba1e288072bddfd2cdfcdbfcc2d764c10e8eb246a5198aa32589b12ecfaabf19903976935437d546aa5948c1c99afb48c9fd137e325541a2388fdfe10eeef0326b6ff9df84f6ceaf0eeef036f7ac5b5937c4bccdcc836e63520b9db1d71e741c3574bda69e75455d3aae9a28166f4cf7aec8e2cbd39cee6cb8f83c7a4bac99ae51728da436fa3560d102a7cf77d56bb3fa361945d7760bcdb35bef5708e26708f847be6e1fd34aef155ba46eb8e3a99c759e11e03b4aef8be536affdfba72608a39cc825a5732ce170acfa863e801c41aaf911a1edb0ca460a0f609db69b797e669e45e3a7513349e8450bda1d725b2b7cd2cf97bb4dbc2691a2ab4ffeb8ff7a9b9b42d9d3d1f4b40f05c02979357029c93c706153ca19bfa5f2097ea71d695a08566e71802f6212a11b9a8273892494a6b4ba6562b1636187f019eadc23955eb84ac47d0832707a81a1cb73105cc592dd665d4877f93446849cf350a2f049c437160ef4fb3afac228c905e67dbd69c737de4082cef3af1508177ec57e6127526d19bc6231517f2a17d291309709406329b96f4fe13e3c8af3f299c1868063a6608d26315151a3c1c922fb4cc41641bd4935171c3fe5d08abe9344ad126e7eec9a7e13faa0283a6dde54be2fc6c7917ec029fafbf1e35e62563e6d02f6cd40cd4e207697ab39b915e2954440dcda72836b83340fea34b25791a22f5d92a89c5e144b8979be83ed9855e744c34286a8ca5cccfad486c2342e6cb5004061d7583097ddd88a0546f3afc76e585a556ce38d2c5226e35553e8521e60f68e09f946eea2c2ddddd3332e70bce5b7c363a725df279277b240dae99f045ecc96d96f34a2ea31c5724ba3515e5d3e12c5d1145a4b2a0b2d5c5267b9a0505acc2907d8f2053c579311410430695b863147fd89c148b1e6e874049e99dff17ffee22dc9d5ecae98f517165d57e84777fed0897346b2e2321749ecdae78ab111555796c0ec5fba8f1dca54176bc4e3caef6e1b8fe677f85ddea2763ddce431db9cff719515325d9b14dfe6bbd7dd58a39263a2583d1b96203e4a86b16af5be494c4557f88490150fe2863ae12df9366674b8e55ca91e37771a90587ebcfdcf518108501d241ce8af6cf2343f06ebe88692480fb24e8690886c6ebb9518578f6971c558f887b3860d58468d6a54c0d59b1a913a8714358c779bc9493cd66d814a431675c7fd3126fddcc2ed2bbd99c5a95555525b2e4aa7b147173e5325a6ac23788d71341c87c33dc14598896ee067c9e4f26b9e56d9a43d30599b1f0ae6d670f42f1e8246102e3ac3e66ee24ebed90700abae2003214fd3de924bb2cb0b5e5988cd91a784b425781463910e68ae15b9466d54b5458d9ce76216feac1ad86ee53a1d52896b4bb1f0457fc9fef894dfd6abdb671fcaf5f2d9085ace8909e9dd5445a0f59ef0cba872cfc0941f9a71d4ec9fb64b8cc626a4290d2d031e008012b5d6a25e0d5d4de574230c585859eacb962c9be39978c2ee7359b2b59ec08565f7cb398b5363327bfd0d78b8865fbca3898a5d1d52a4a6ee34448c452aea62d7da63d80f93ad6e45c3bfa928880e25c0689c50d9a58a1bed660aa59dccb8789606339efa899c6242fb69b5f27f9fd9d1c4d2923b3d6e99d40da26f6f0477ca514b41eb413633d5afa23b1fd20845fba729c14cf32b3dba9a08dfcea29ad11eec4a87f413b57729c398dd04b39c854b6140f4ac71602bce1f66ac270e323a23bd6e3c8555583d2e5609ca6a597ddfd9672c7fe843cd6b43734b895368306bae1951c94d8d9b811a4c34ef5e4663e3acf1723f82ecb4361473e960f8730a0b44df4f78b89c938e83a9b99914eca4fc89cc345d53366d040920dd3649a867e0503c586aa33f7751196621c62475c97dfcdbf66ed18a26937391f22c183a9046ae89330102ec8bd4d44b2c1f866184800acf6ec936d712469830cfd0e715fcb6047575c0fef744443f960005b8cf76d72eeb754f91798a4587aebd4632d4baef76b0765ca0467eb0a095a8a6584d09f467209cfc2d26fac23fd864f38e65babf829ade897b1b851da66c2a9911c2bd8854c4e986021d0cdb18e82c245d683b512579c872f169da25ce018fd782b640c71ab5879c563a7f94817f3dd4942705a5d7902b78d84ab1eb8c6f32999ae93693f93605d93128f0d50b23515caeb6779eb5e1bf2206c3a7b2ac1fb571d97a736cfa4c5ab51ff0103e858edeedc02d437dd7df13eab9ca65f18b5fb8db7b872e88bb33a5713f484943efce65254e148c1a73c07453d26969c4c57c94b949933458f33739a3d4900a5e0a04811c283fe95347f6a31635fcc6dc8d7af5f411f36849790526efb109928e62a6cc9f06322c656b43bf5cc5717ee8f642ef05093e965d3902ffdf6083b4202972a9479642bfe0ee385cfc41fe807061392b5965098702edf8b9c2c7f304fb98c2c72c655fe362ae9c4aaac92ee5ad6d2a801fa28e962bc5051ad8a7e96df5c9183dc90693a1a209a5c92b3cc1158c28e1050a2ebd4141a103292654f5966b3f5c2996a7d1a422687fa374c267db1a25a50d19c8e490eb4da70b935df48be33ff6b9246c6021eb060135a32a40c2bdc6ad52da78bc628a4bb4d4de626946b098dc4399d6c6ad26e15e15e1995f6a178d2806bf82df301d4592371e17d46ed0283ca752bf342ccd3efdf0addd78fdf6ccb25e78114ce0bb28fe4686322eb2437202b330e59b17c34e39c02d4dbbf78f1be15511406b52dacba7b6482dd68809ee6f44ed1c5718bd0607fd46c828dc24707e6d103058dbb0e6d86012430cfd4a6d8fd579186cc46e51fd551adf7f02c4fa1316eaa8a793e33c6ecb5761fa6c1e15da8fdee5c4ccc90fc0c305df18033b169dd4fbdabac0786ae1b088066c269c2137b4f189750ee1c7c84064b4aaff510a087e69d88c9c39e18ff75077c8971583b9cd81aaed88bfe7386b894e00db13a9413c6bcd769919a6d16a41de83973b49fe2fadebc6cd1848327c6312f9f88900c988030d153b3b9c6214a5e9e2d9700c844f6ea72f0eee53b4e3de6b1e9078a9cf29c503fe8d8f2fd9ba85793cb16fe33b5695202c397ec0fee7bac0cfd1d303ce6f8d424cb6082e54d81bb0f8ff0dd660eced0f8e0a5a09e5400fb5b1fc4d309fa9f05b63e5ebf7ff1f5061f3d5c3514fee1254794a29dab5112a9477bda6ff75e86c61216ab6d16ac2ea32b8042115b3249f8ca49ce0541e13c60ee7356cf60a6a70722b43b33073c656e27223be8e71e8725b6912ad5eb4cb9153c424828224d2a91ed8a6be78c2029465e3df9810451954768807ab4ffba41c5e4cc6257ccb862c0ab85369db0f3545eb681757eb88b6f9829283c9f95946c4a35d56f66a9e85d12c66f6d0049e5aa8adcbf66512a83779a14a6ab64ad18d39d158253e1e6214c68388924adc08bc2e09721136906e77c60f5ad675f466385f76c0e028587835279cd8eb5272a5ca98077809c1fd023aad238c9a3b452f1a73a677582f8c9d1143db75f879b1d3e9d007aadac05f7b64b5ca98d0cb0156b75b8e2bc30b58397584f0501a62429a654e58353af8315005b50192a54aa7f84fd233e09cb33322040c22fa31b97f1926661959cb7046aa905cc2e783ca7333b5dd1ebb2e48036e11a66327d154f8a8686d0b23863bac33e4cb2d8098423a440b17259824c4b24c04a27b9326afd94b718110072de3fa95a646aa051cb050829fae50f0cd3f9c00329a7f170f555a4e8b36640d01f6d443fe257b553af510928cd3ed5e5b61444f64a65800a322a3baecf41ac3ac8ee3e56dfcce208cf1cfa3c00cbc935f2e04c746c3212767b99da2333b949d621387524c6900dfb3c81a321f7bf364747484eed0492fa53ada6d83b5f808c8ef28ec1a86ab3d48ccfa27c65bd5c78bb61a2ba2c009911813b37464dbb780dff4bc70bf84497201ff9270b5360fe755954cccb6b3646b6d6c93d1f0abc524beef628c095ece27e48ec3f5bd948f1fdbc5dcded5879a34ae862279c5fb34f15ab3bc66d9d0c24a9b4ecebc1fc99d916ec64a153bfe0d97067af1e991d012a54c6ba830c7ebb95838f9eb4c866aafc7a816047c1729aab34a9a85fa7fc9952b676c85e468287810de1cb65fe554287580d9bb6e7b6c4b108113013ce0f21fafb4731601ee25b027bed5ba4ea9cd284cd5348fffa47fbc36e3ac17fa0ba2ace9740ef0bb9bbf687d151e2ef3bf8aa86b4888abfd0cb6b797a4788e11488f20c1d7a767e6d4c4b2f351bfd749ff85ab2f6d5eb913a925520bc7a81ff78d5a7f6397c78aa4fdf9d677429ae3ab7444680c5e7e928d36ee2cd639948b74b053149ae0f89f884adf95b2581cad66071b988af45beb92c556c8bf870b6b0c5f744ba31b4e4c5faac45b9aaf08beb8dda565b653ea6038d547f9e277492ce0596063234b1e0ba98a1f0cda3e5a450135b0d454918c8649d049965d79b17c246daa0eed1bb7f99726448f4c16692c9a3dd8aea1d55b34b796ef23d29cc004c4950dc79e2a038a360d78b1db2a314555d7b74f34d1a5c4096dc8283abb9a75430abc9113c3445c47c43013ba67625c2f857714b8c825cea5dcbd9b5ce33c73edcfd62d13b705eff0d51e653c00434e47e1c28da114033f0bbe03ffbc81f9db41a9513299342c3d2734c445ca43e15800c0e7b61ed765c3c94ed30ea94cf95f14ab58120052d7002717eccb528731857d73d4efac2a80bb2289b8b1020290ca0505b54f9e8aa6cffc10b52fc40548b279f7c187d520e17e0e9155afc33df4ffe034faa1a61abc6a6748c6f5f54da1e9ba3433ae470849793d4f2721ae0a8646042a4469fbeb22e801446d66fb878ec9cab4f3806d43b472331db1c6681ac64b3f1a06e501c9e9927c06ea064e7e8000d6fe954dca772ef9cba71c7319a15c7d8df920867527fe6686b733c59e72500f139cc82e52799018f7e8cb6f37b64ab87e66863ff12dc3bd3e00a3442e69c7d3f176e0a1d51fe697d221c8a499e0185fd2d342110da11e430605c6dab0239ed0ad399281e9864d8acff1f1f80d44d36cb3a7ff11b7d9d0564c8c3c0cffc7f2bbd036e3ee6316f7c063bbf8b90c8dd49dceafc6b06a4911ef8ac2be209d245d5288e80ad9b04532ba47ae888239b07a4ea1b39812c4304ca22e0cd13638022ccb02923b8c787169df3d54d177b81d87aacd518f118e9bdab589abe93113f03c31a5fd1c237258523e98e62d33aafbaee238b9fc6118d198a977169bb3894b8b9051283549f968eb983c440e0ac26e62e6aa4872e7ebdac7c6eef7440e75f94a857bea674419cc76f90a9f95a80df90a0ac14d03bddda89b052131a1bd8d29e2ef09424116c88db97db1c929a730c6ed0701130020389f558ba3328673f1f30e968bc36aa08ba10e82c441851d7a595f7c531094f072a61b70e84d4b51fc5354c3a6219c810982366481e4c4212047d09aae0aec1e0a22c3e826873c96bb54da8525e58cfdb465af9525eb90ca9091641b0dd30bfcc32ac2667a951861a0a48c974a8829fdb2b100c07f0aa9afd7b512b7604f4de407f7d0d9c1465ace055885a97eb9e9beaee9a5dae4acbe3c290098995fea4685bbb54a0d29ea15dbda44ae6b305994d121125cfb2cd33e2f2c99b90d24811c363f37b811b26c5f85ab1455a4591ce649d5186a775573fa2d466a4f59a28bc265bd7415e5a06c6473c6b5b9db901f7a7faffcf64ba002a9d3634439f5b710f674c3191a26e344ecfb8439135fe7d5f9da121e9d141ffee2ba498647a6c4dfe330cf9e16389149bcc478865dded2f5225ee2ac8eee78afce5b62f36d926e0d17d0b47a2a36235559b5e15625fd40284305878c4ea25e18ceb27bfbf24857fe13f29a996a4cbf6b384c06d88501f452cfbf3d807f96d08bbec387f8ddab442e80741492293915555ea52c44dc84b698b496bd80e977a8c69aad2d045c2f83668dc98d989e305c446a6e512037755d87312860fbfd48ee1acfc496320a749e3253c1629432ad905b7eb92aa6b41476ae60edd178cc56a7b63864642d38e3311e5d249ea23d1c3bd1743b02fccc34aa488495c5b2caf1408c42b7bbbf5e68dab9f74dce918a9e224338a1b403f07c26a1a1a5d43a30e387f7b3f68ccaf51fa2d52ec919c75419dd647ed947f7a76f5231e6764b05ae0477e50bab26c070aa2788ae5b2078ccd520a2b63c5e72374aab3793912e1ea906c472d831f4bdf71dee8fa2b545809264c101d62951e5728dc39b2d1e0dfa803b1dbb8a478786f35c825c6aa52c67ef7516c5278e1d43080ea59d77f4851a94d50b31b2160e95b60a6d8c53936202bbf580d48b1b1497244c9549fa0b5985b4809d8a50b0ebb314482b46f0f3de81d6be7ebb8aacc6e46d78a4a146f2ba79dead8757bc383e09bca5924709f3f834b20786a215fac852b20d6120bcf731852c2a459116689d5c1a863396adb2ccc368848954c3206bf2615cac62fcd95d27405f32eb6042a98e0ee87a1704284dbbc173b51f96b4264740fb1561f112893a5fc3477a161b634ceb8f4385c96d0839b4fad22c1dbdaeaad3405afbb13a4c6b63208f3018492f1f65c33922a824258998fe4ac671bc33676fa26bc9335027df743993f62702ae2943a2e5887e64802f8c1e425b9945c98c99843a8343cf705866fdccff6a42011df33acbe61d200598951d921f8c5377075876163372d558ff7e26e0c9c758fd62a7edb0743b55b864ce66ae124883eedeb54bf87dca99fe685e05f5cc18793044e5fbdc87ccbb6bccd9f3f6933b0898250704eacbd5bfbb2100b23bfec478741e9d345fa54b568d727854ed920e16e757a47c7c36816582d4b0b69eb28574eb167360988af8c549ae17b533368f035a37864c73664c94027949f4386228ffdfc03fd3775eb90249a10df5651795e63f2b934b109ffb48f8b4465e8f8b89bee2fd3db94c19c4d269f8dc8cf60acd897add04dc7e14e8eb4d8588795eb28787fd40681c4d26afb49116a713b7680d2c45825b58747e8ffbb7dd9456ad9721a17d13a84022c227b0cec4ad9bb15b5b30f786e0b0ffdef7babd2135e4791fa30df1c8504f9db232d9267396b82fd658558523002814f4fbe14eaf4d502b5167b2f1d5c7e0cd7b43938ee3a8de668bb7261c07140e6e300f9a7e782ad0822a5400132fdcb037d679527d00ddc416a699bfca0d1e1e75e458807a3d95ca7eaba0d6606791a9446806a052dfca2c16fb504296c52cdd30bbc376d2943ca3f30564a37923a4d66316b3ca97a34e7e898cc839f764b8bfa2a977f7d0e516c4e3d1e010f84c695d5ad3faa1bfe209a8067060e7d3f2df20abd6ca9d9bd945c26b6b19ceab7012634697937dfd47e6e0ed5d031773a1a2b48b12f020f5e529bea36a085f4c5174bfb2020d012573231cd849854180954896f021759a944a4138c53340a508e7f4bfe5db2fda6f8d7770df4a77e58358a646b33ae0a2567492a356c2d85f32d1397430170e05ed1f94534bfac858387d1dd489cdfe875854f9190e1f1d265461cbe9c489c02e2729509898abde3e9e33644fb828f1a577c357042dbccd3b7dfebf4ff5850c449f7580002e864fd5dbff42142485b52a77273672e5970eef51485080d09d7b8f18f53000e63b322463390030e31813ea611fc988f5d9ff17ef56c87834f7743b456ef634fa9ec9961dad80506bde195a7ff8e45b2bc97732487dfd8a2bcf7c0efb7c9d3a2f903a29ad0c25b4135a94efdba9cbd6db56d12371d2bdcd0798c76e51522a630e1bea9f0c6643d3d171dbb0136e2d142c870d41b59e588832e20db2cd33fe94870a1e06727122a8917676d7e9b9604351a6d5929c1228b87fbb6e702d1df7b70a0a106d142a686985ccb88cf7724a059967c60c7821c67095d99bb20620b83c44d85647e5ee87f440193ff2712d7a4f2fdd7167f036ed09496bcd75a5d80fad2420a1556f1b222548bbf623bcb248ebf0089b025b4e43e4cf6fa04adda2448b3c5f037107cdbb64b7a779e0eda16ff3e0752a6790c68b0662a4c2368a994aae2856988444e5fb641983f38764a4375c1e5f2d71472462b390a91815cbb361dd7a09e91ddefa283914c3db7a7b2d4d39722d6c8e7c0df25c0681ecdca053c7049f5513eec948aecbcb750f710b2f60363d8bdcd5ab89021a35621e8109a3a07ebc648add14475091a9e18730573e5b84f0696198cd4a331fb8898dca94ae293dd9dbcdd46fb4f83ddc9898c626f1384578d2026ad7aff3ec5291f502224aa9037a8d12f49db519d3ce2d08b844e824e2f49a6db73d8b926760c2197f28f8914e3435e9418173782a9c549299192609d7dd399ae5ccc0238defbc8479799fb0d2334e3aceba774599a5b305cea49d493da522cba400f7c0f360048718e2132c8de8a7d9af1d4e8bf320a4a1137f4b35743a676db799cff44d42f9f01f1f509580ad4f6e2e4e74d11480da66537773b0316a8161420a74b92d3c484b9aac6c8f627f555515a44e5a173d8d1578f4a4bd563f856162923bf16b2e30297b99e0a43b03f20be7cf3b042fd449cef279f31c0f17fb002ec9211d47dd4e3df4fa3920716f4f17141d0a7085ea652477eda5efe7f4079f4cd71e8c691f60b9c9aa9b0e5fb6d5367642c4c3bfaf6edaeb4bbc79294a4c9875b1ab6702f2b98e328be732a7709714ea30fc1914b80b220671e0d272b88d960793ba3c4bf59b83e00c67b19a9a648955f4a4391ab8f9f69dc425e1f2505d499b2e2452b15f12f8c2217e87e9bded9ec58d25490cf2298b347b64e8d937651b3197e17f82e867a9594c88df9d7cfc861cf3a1a5c7c263cf65765dd836061949077eb1cea0251a7ad46628ca46069f5438ec75278acb3d30fa0db064a8f4283477fae64863162979b5718de0585cb21bd0ec6cc8f6fd0dab37318b648df49f8f67579cdebea18d4a8aeb9050cbf0ddc5eb16ede21c9ed2608a1e5b4accefeeba463c5b198ac0ff49229b7eb039846473155f1005645894a39f6e1ab51b2e3b87f586d8d3c38ff395525a817c8ad8d59e066d66706ff5b6f09e273c9a598dab6032746819f0b9c6cb76b69d75c2a03f4c8745ebd5490898a0483f950b047384e2310ea72b899e9a3c5b00345c16721f64882187dac78dad0ca1705b0b423075847ef2a477e91323c4a6f0d33f359b8ffd4ffa2f56d1f33e8cdb84cf2feafe4c0d3fce79ec54b9e9dd7356a0faf12fa78e75006c10122fb44d3ed19d47c3051b8c4c445c623a78bd4edc30b378a8be503098414284c808818df9b1a5553ed49acf0302878dfc6a876cdee06af197cb766532b2554d5d2a78472f4a6b78490809d3ee9788e07efdbda1a6c37f3441f9e8c0da66cbaed367714e40649ab7ad376b0798a0cec386e84342f5a8a730e1472545eb8f4b58cb5b24eab5c9eff1ed72a9645a9adab96e1d4300dbacb0a2e3c95a0dfa7d301aca2c8bfb1f64ef2b65b28d6303f253da5edb3f789e0e759dce59332197e7c05416b6342c0502b4ff731b716a73d8e95d1fe0c8c4e13e57ed31c32f8b00ee79843c40337d8b03a1d7caa3ed25b35f7e1a50e8ffb7da2ef42f7923eeba5d085f422b490eb3ebd29751b9e3864e01ccec9a0f78b5383777d7abe50a79a788f93219cd9546b5b528b6da673175fba0c8f497bba25eed660743ad0cc76db8c4c587fcfd2282bb596a3dcddcd71a3597dc8109d946e5a275e69a595905c89457c57e18914c289fc71443e7aa69b7731a27fb51ce9ea73ea37143bec5416f5c2f004912ab5de9856970bc4160c56691b7a6ce9ba97a9723ed9e45daa2f2adf39bd3bc0ffb9bc890147a39aa982a5cdc496e34389cd5f57df6c397c28474dcf5b55b7a5a52e504efd312b6e5e93fa1dfe34cfa443814d2a93b9494e64e6f9b5ba984a32823d8b7a6d24e191e29cd7ce8b96c58ca7de52dc51083f898c7b00b4b8a791280c3d1c226520722e4287844c0d629632a5b1d8ed722d952ddc117887b5c96495124cf6cc26bddc282b7de876c1d0aa9046a7d447b9943ab068bc52ac2f39f6d80fd837e0d0bc7efd5fac76c0d235c0b4b5bcac3eb69ee1ceea2fa3e9ca45cbc30871d64c80f664f008c9a7808247343e9f88f44e135079166e7085bd2bb6b06bda132bd2f319363a9961984de3062d62c36792d4ab3ff170bcfa5fdb101cf5d65d62956c9ac0e80c8a62c3143bde74b271c042b347a6fdd64ee02bc90f3925afc993689cc40acaebc45c8784a148af4a4c18231d3d8202398e04f38f19fe10e836a706880c10b82b8a84920f1de969fcd2b24b2aa25c8c8fad01e8465e64c37a657e77b8cca9cfb49e8d8ee3d51df258a514d1364aeea79d5061430ff93a08c6ee102bed3b661865bc159edfb9d7d6bea574666b922c702111fc27a02d710fd9860e9e8b27f8db180fbb6e175e5e60fa273246884ec0591a353abac75eb28724244583d58cf8f1608a18c1afdf29b3eda92254e3fe22c726191f174e1a2c526de6d1b92299a41bb495b29c0f4e81eccaf87034a6a78c57e8e033fc994da026da623695ae39ad73e7e1bc247842fa6d06bcb2dbbaf11764368a041d338ac30553748dad4c62cbbfc6c032c064c2782d27bcdb44fa2e86b805bae549ef2a6bf8c68d6f2b3267d9b77f1b81d24b6ebee42cb35ff5f639ee4dc138d053b00f4ae71cfc998512dce05f03317996a6d4a787fcd619a52bdfff1446c0d8f96d7021f589a82c2860de4aeea62c661276dedaaace58538d278de51a8677a44a24b4d7c5487f80d3413f841b3d02b2f7c590ce4fe84c783404d6a587385f9a0f7cd57918db136766c4ee248b0006bbe94bc9d7f9c10b3df317e1a5e45f101a367d8543115388aef3efac2f49953df5b58b64746257cb3e8db2f8408f9e695e340dbc90458089c87b7a71635b1ab94cf061f3f540128a0b7bf0a1d0afa8a57030c3c41ce6db5902fa6cf4d16965f942c418ef4558c4ef98051420d3c8580699f3679770797cfc6ad7c2a17636c5ec201cf483aaa1196e42ff90d0f8516cee152a7b50fc19afb80ed0b03973bebb7ef3bc4d0b75613b31d60aa821e3be410ae1bb5329b5f98006aa6cb7d7e9856492c1d106e05989083f24471d480a09b0472fcc3a20d99865f53f1d56edaa4c2c38cfd457ad561ee229baadb3221cd27232909043eecb5698d4cba6695191d6af7918acfb929fbc14577bef688ab404df00c15b1965fd930277c2b959ec1c747456da64e6ba719d9b426c654142fe008dc7c86729a0e68189ca6548eaa29f9cfcb189ad0911da879b7a0995b3836a1b5778b185ed518ffe59f173530af0fd7a2522cf939a9b97e8b03a5376c1099d373b99fe8f9082c622cbcab33e5eec492558265857418b7a08f505ffebf77a5f4ea71621eb216b2c49ba85d9daaae490ba0181db4338d8d3753251395a683ea18fa2fc81441c3edd4c289c4a009b5404b41bd97ddbdf619da7a012495754cdcf5089c708fb8125e9a5fb306d9d192cf7ca80a1d0b373862df6f514f900de3259292d68c2c31311bec941fd933ba6803a1c258a453c5528d66e7300585abe75ecd65f33ec1c67118e03351b2d2de692d80edd4780bba8f9c477d4b2d1dc75dcadd5a21ffc40bd00f1cb424654f492f6cfc5b1c75dd83e3a5964243526e4acfd505f23a31ca8dd7e3605efb3ec4c8831535bbbccc8e3ceca3ca848ffd163fa25010cb787d4bcbae58cf904514b06329667d21ef42419fb49e009cb6574bb850540e1f848010134842cd09f6717dc4ece7b9d4ca09c1f9ad40ea3f212677e5f9b10e28ff870b597753426cd0743cacbe3e6e28718bf20f31d79ff1f08e374b19eaeae30a1ae97324f3efdbf550621fdc915b9ec409a30983bfef2b3e3b86b38d39a985b2b4bd98b19758760f80d74b0eae01ba8381ae29a8f8fa5dbd4ce3b16b56f6bc72000edeeae8c5d863b87b88f532deb8a2302625d05c6abc1b970da583253dd662669f21fcb77463cc6c9f30f85c3e73fe612885f791882f11abca9c6796fe1d39478cc83bdce0268e63f748cf34db669536b0d9e8fe93e2b5b869abe893d2f3c7491a3ee098ece52145b244474291e3a1d0c50bf2cd7b722f98e6fecfda6c0f4f7557996cd71ae3a6634aec3b221393ea234ba007a76ae86df800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Gcd, "17", "19", "1", .None}, + {.Gcd, "7d", "19", "19", .None}, + {.Gcd, "7d", "0", "7d", .None}, + {.Gcd, "0", "0", "0", .None}, + {.Gcd, "0", "7d", "7d", .None}, + {.Lcm, "17", "19", "23f", .None}, + {.Lcm, "7d", "19", "7d", .None}, + {.Lcm, "7d", "0", "0", .None}, + {.Lcm, "0", "0", "0", .None}, + {.Lcm, "0", "7d", "0", .None}, + {.Is_Square, "c", "0", "0", .None}, + {.Is_Square, "4fa3f9fe4edb58bfae7bab80b94ffce6e02cdd067c509f75a5918e510d002a8b41949dee96f482678b6e593ee2a984aa68809af5bdc3c0ee839c588b3b619e0f4a5267a7533765f8621dd20994a9a5bdd7faca4aab4f84a72f4f30d623a44cbc974d48e7ab63259d3141da5467e0a2225d90e6388f8d05e0bcdcb67f6d11c4e17d4c168b9fb23bf0932d6082ed82241b01d7d80bb43bf516fc650d86d62e13df218557df8b3f2e4eb295485e3f221c01130791c0b1b4c77fae4ae98e000e42d943a1dff9bfd960fdabe6a729913f99d74b1a7736c213b6c134bbc6914e0b5ae9d1909a32c2084af5a49a99a97a8c3856fdf1e4ff39306ede6234f85f0dca94382a118d97058d0be641c7b0cecead08450042a56dff16808115f78857d8844df61d8e930427d410ee33a63c79", "0", "1", .None}, + {.Add, "-569ee5408deb61a6d9232b12cadb73", "3248bc748056a33eec0c55f2ec0a49", "-245628cc0d94be67ed16d51fded12a", .None}, + {.Add, "-934b3cd66484ad0da5da23aa2c09fe", "405747b2c6d4dc10a0a453e08abd35", "-52f3f5239dafd0fd0535cfc9a14cc9", .None}, + {.Add, "-a497c6ab621818982512350f6f6324", "2c4a22e64d274f3968fa38e0079790", "-784da3c514f0c95ebc17fc2f67cb94", .None}, + {.Add, "f496179976924a7e94882e7a2abdbf", "1afce56f84a129940ee36e73041806", "10f92fd08fb337412a36b9ced2ed5c5", .None}, + {.Add, "7b768f42ef9ea9bd96b25d89d079e2", "c5b99b425e03bc09c8fc8842caedf2", "141302a854da265c75faee5cc9b67d4", .None}, + {.Add, "69c9d904d101e10680ad9f458b55a3", "1ba939736eb74c0775c72df23d47e2", "857312783fb92d0df674cd37c89d85", .None}, + {.Add, "-a6c804d3a2e562e918ba02c8cd9116", "8315acbe2c92566e29055611058955", "-23b2581576530c7aefb4acb7c807c1", .None}, + {.Add, "62c6f756b8e2a2774093f051503a90", "969e656b3dbc84d57c14f158d4bec1", "f9655cc1f69f274cbca8e1aa24f951", .None}, + {.Add, "f9e0ed137b655090b9f85a18cede30", "4badaa4c2f22bb383630fd744d58d8", "1458e975faa880bc8f029578d1c3708", .None}, + {.Add, "-ca868ef03da0cf72601c0e4d6f1f7f", "9a640689f71ccbebe88196a9998f25", "-3022886646840386779a77a3d5905a", .None}, + {.Add, "20ff037e64dbdff86f503201229289", "356cc9355432086cd5902b568e6057", "566bccb3b90de86544e05d57b0f2e0", .None}, + {.Add, "99dd0ed8047ba4b1e094b29144315d", "d1ccf8d7f9f21f74d6ec4be0fb605a", "16baa07affe6dc426b780fe723f91b7", .None}, + {.Add, "b47f4644cc7d56b23ad893ef6efb93", "397da0aa1c9c589541e4dcf762901e", "edfce6eee919af477cbd70e6d18bb1", .None}, + {.Add, "1411c2281750f2194de2bf576d2a85", "c73e2167fd2c3f126b4eec1b9ae8ca", "db4fe390147d312bb931ab7308134f", .None}, + {.Add, "-96cfc8ea05fd378290d18e07baa946", "c51cef0192af4ab6929ad6ca95ef8c", "2e4d26178cb2133401c948c2db4646", .None}, + {.Add, "-99836225715db20973ab0a01852dbd", "717355a66e5488602b8581db11326b", "-28100c7f030929a94825882673fb52", .None}, + {.Add, "c3ad4cd4c01ed667d8dfe5d0504517", "d07f2730ceaa5378ff34db85749e8b", "1942c74058ec929e0d814c155c4e3a2", .None}, + {.Add, "258b124033eb1870bbe95dcdf89316", "28a13f0fdfe07c821c7e408d86cfa8", "4e2c515013cb94f2d8679e5b7f62be", .None}, + {.Add, "e9d73ff0911f351acfb6914571efe3", "55cc12ce275998f6641233ed5b6a1a", "13fa352beb878ce1133c8c532cd59fd", .None}, + {.Add, "-c41d4581d8f2bd0205aa850cf1b4f1", "9e542a92b2ecbba92a4f4fb6b823d8", "-25c91aef26060158db5b3556399119", .None}, + {.Add, "-134289fe593181a8668de701f28f0f", "dcd3ec76ee80a9c03423c1e9bd16a0", "c9916278954f2817cd95dae7ca8791", .None}, + {.Add, "ce14284fa075e6381fcfdb81b1b1ea", "af365890ceb276ec56c1cfc8163fc4", "17d4a80e06f285d247691ab49c7f1ae", .None}, + {.Add, "6f8ab2f7d5a6066bb5de568f909f4f", "6d6faace70938b4dfa99c6c3bbda3a", "dcfa5dc6463991b9b0781d534c7989", .None}, + {.Add, "3f6861ad6695b09d5e0cc5964eb29b", "cf71eb6962703657e54af0848277cf", "10eda4d16c905e6f54357b61ad12a6a", .None}, + {.Add, "-ea5b72bb50d9c1d013d1aa1ad184c4", "442751754613757893e60a4f46eb5a", "-a63421460ac64c577feb9fcb8a996a", .None}, + {.Add, "ebc80596c377f4f7effa0000061d23", "e76869ede6da873b4f64d49c08229d", "1d3306f84aa527c333f5ed49c0e3fc0", .None}, + {.Add, "-14e786d470e33c05576b433d81be28", "f0b0a56cfa41deb25bf59c4893d80d", "dbc91e98895ea2ad048a590b1219e5", .None}, + {.Add, "1e147d13b45d32d6d32a8ae5562b32", "8d54b2e690e312db7d01cb8f0686c4", "ab692ffa454045b2502c56745cb1f6", .None}, + {.Add, "-3eda367af1da871561770837dc2001", "409b11667fafb48507fad1a48a9646", "1c0daeb8dd52d6fa683c96cae7645", .None}, + {.Add, "10d0643aaa6788797ab686217c848a", "84f9a2976ca6bcf87c5f08e1d2823f", "95ca06d2170e4571f7158f034f06c9", .None}, + {.Add, "abd25b8960a741bbe04ef6307d9de3", "8c387767e9a86808a277aae46fb0c2", "1380ad2f14a4fa9c482c6a114ed4ea5", .None}, + {.Add, "-698649c629001ab737d1f535e173a2", "44595ae8bb7c45116f4cfa793f0549", "-252ceedd6d83d5a5c884fabca26e59", .None}, + {.Add, "385a6078aaab170d7e1dad26e2ac7d", "2b77c05e659e9c53048bb42203b4c1", "63d220d71049b36082a96148e6613e", .None}, + {.Add, "186534b60f4bb2dfb81a48ce3da520", "57706db7e4e5e016c3ed248e3046e", "1ddc3b918d9a10e124591b1720a98e", .None}, + {.Add, "c56bdabb9343b9f400bddb0e7c5092", "2cc7bea46ca0ba30f2eb7c80e0508d", "f233995fffe47424f3a9578f5ca11f", .None}, + {.Add, "-b02250ec97fe005840b59d59620470", "f35d3ce5fed4573e5657d0bca6c54c", "433aebf966d656e615a2336344c0dc", .None}, + {.Add, "b87e0b8ecefa8860ff4457b4dd8f6c", "43645d3e9560f8b9611ed3c17c8c81", "fbe268cd645b811a60632b765a1bed", .None}, + {.Add, "4347e862f7480f9ccd1e2cbadbe0a7", "2c3ff6ed7cd20ef15fb72eaf1c3553", "6f87df50741a1e8e2cd55b69f815fa", .None}, + {.Add, "fd90dfc8cda3a4511673b862afecc5", "aefbd925f02ea98d54df3d648eb684", "1ac8cb8eebdd24dde6b52f5c73ea349", .None}, + {.Add, "77ebeaeac60505e3c8ee2e589b057c", "e7a02280e43bc19c4e4066c1275ef3", "15f8c0d6baa40c780172e9519c2646f", .None}, + {.Add, "-d8c286454f185406aaf1b77257f8e8", "f91fbe9e55cc6904a375a5b6b70ed3", "205d385906b414fdf883ee445f15eb", .None}, + {.Add, "-2dcce9c3eeceb2f390ce258c57a694", "cb6192b7687efc28b92dd4cb3b99e3", "9d94a8f379b04935285faf3ee3f34f", .None}, + {.Add, "459fdcb6595ff5190cf0b3c30322bd", "f42e29cc0ee1b24cc70b08f6350bfc", "139ce06826841a765d3fbbcb9382eb9", .None}, + {.Add, "a060c184a981170349654d49ef60ee", "4c45fafe1325c6c76d13271a43d1a", "a52521348ab3736fc0367fbb939e08", .None}, + {.Add, "21141c50fc6166451a4e9c7a15def9", "581d083529a6015f77eaec04c95ee2", "79312486260767a49239887edf3ddb", .None}, + {.Add, "-47a2127a2f3d586b0a0cd6347c0371", "748e8df8963a3d8eedf760a3863b4c", "2cec7b7e66fce523e3ea8a6f0a37db", .None}, + {.Add, "-7f37105534a36143980d426034c74f", "e0b49225c493d585803025a802df15", "617d81d08ff07441e822e347ce17c6", .None}, + {.Add, "b139ada1f3c07ff1439d5c662ee73c", "8b84e9493052af2b6ae18e77cb34b6", "13cbe96eb24132f1cae7eeaddfa1bf2", .None}, + {.Add, "-8eda708e51a4e96a5e884867836549", "a61eb7547c7537173d68999ec89c88", "174446c62ad04dacdee0513745373f", .None}, + {.Add, "-eed1b8b90fa07e638ebe48b0f8e608", "9abcfc93ea37ea1f23d68554d0f9e4", "-5414bc25256894446ae7c35c27ec24", .None}, + {.Add, "-2917c4bb7c3fd0f2177bc2481824f1", "4538b1537786a1ecdbe4d3f5ce9603", "1c20ec97fb46d0fac46911adb67112", .None}, + {.Add, "48946ce6f1cfd14cc24f5e3ea14c28", "9f613f621204deb766216ca84510a4", "e7f5ac4903d4b0042870cae6e65ccc", .None}, + {.Add, "aa250cb306da11292bbb1f64cf79ac", "47e9cc0e24107f5022835bf1af1811", "f20ed8c12aea90794e3e7b567e91bd", .None}, + {.Add, "-c6e1fcb7289318d6c68abfc9c86611", "6766d236c9d50c8916acc8a7ecfca6", "-5f7b2a805ebe0c4dafddf721db696b", .None}, + {.Add, "-d0e49985afa421979c9e06215c044d", "d4a21370a03afebc31510e37271e2d", "3bd79eaf096dd2494b30815cb19e0", .None}, + {.Add, "-dfe730ed8f4b3b6067e17801e21bee", "8fd587c0180cc2406172c5e21ddfae", "-5011a92d773e7920066eb21fc43c40", .None}, + {.Add, "-bb0884fdd6cd56b677c1968773eec1", "fe4f24b30249e58264d9f63a4da13f", "43469fb52b7c8ecbed185fb2d9b27e", .None}, + {.Add, "5152430a62ad0458a990ab04133467", "be6faba007b6b06bc5081028a4d9c3", "10fc1eeaa6a63b4c46e98bb2cb80e2a", .None}, + {.Add, "b3c1bff207a1929bf122cfec5f1fc0", "bf6366a2eb3742fd07c9d031bc36a8", "173252694f2d8d598f8eca01e1b5668", .None}, + {.Add, "c2eee9181f615cabf6513385746a15", "b8721458a27b4a280767db6bde59a5", "17b60fd70c1dca6d3fdb90ef152c3ba", .None}, + {.Add, "186824d924fdeef31cae2795b27ba3", "be9600f1b0f652672106699748514a", "d6fe25cad5f4415a3db4912cfacced", .None}, + {.Add, "e4645b2c4e730338448eba62378dfb", "ab5031f7201c24451e96282d97cddf", "18fb48d236e8f277d6324e28fcf5bda", .None}, + {.Add, "-80a73f04c208bf8c64cb2f46734a82", "eb9971b6a3d8bc1f596ef65e1e6577", "6af232b1e1cffc92f4a3c717ab1af5", .None}, + {.Add, "-9a69ed1d2e211df986602de1de87ff", "de7036d55aec03b5360e3315854e6f", "440649b82ccae5bbafae0533a6c670", .None}, + {.Add, "3c6cd691cfc4ee80bbc5f4a31a18ef", "a7574bf8472f3d3217b8b3cd7ebea9", "e3c4228a16f42bb2d37ea87098d798", .None}, + {.Add, "-54c4efe8f5ffbc212a9b1bdaacc8b4", "d99d1460975bab75564e75874346bc", "84d82477a15bef542bb359ac967e08", .None}, + {.Add, "da5af996fe757b4c1dfb0873d1499f", "e8babc0e0422656e7dcbc267a65065", "1c315b5a50297e0ba9bc6cadb779a04", .None}, + {.Add, "c984a3fdfff0b399ce2092bb4a991f", "1c2b816ddde20959bd8da081324c9b", "e5b0256bddd2bcf38bae333c7ce5ba", .None}, + {.Add, "-3f3182cd7e2ee8b0866aef997e4951", "967f488fde697d9b863f00246ab26e", "574dc5c2603a94eaffd4108aec691d", .None}, + {.Add, "-7955a9e3a5e4ee025bb1416ed14f50", "bd3bce22aa50ab7947b2a9a333e8b7", "43e6243f046bbd76ec016834629967", .None}, + {.Add, "190ccd720f626b83e7da8156e929d9", "ce93743833bf4b262cf07e921f3e15", "e7a041aa4321b6aa14caffe90867ee", .None}, + {.Add, "1cd9d5af13016c2d26239594df7d85", "bd8ff99dfe35e34b83041deb2e3924", "da69cf4d11374f78a927b3800db6a9", .None}, + {.Add, "ecb4daeabb77fe0f45c2453f8027f8", "81aba6312a58837c2a859ff6214ab4", "16e60811be5d0818b7047e535a172ac", .None}, + {.Add, "f8c0dc0e239a640a74e2dd3461bb3c", "544c6edde5340509f7d16c3b1ca4c3", "14d0d4aec08ce69146cb4496f7e5fff", .None}, + {.Add, "-a7a10c857721aac8f31ae1867a5252", "2f249ee848dffa4318825ff09e7829", "-787c6d9d2e41b085da988195dbda29", .None}, + {.Add, "548baed9e9c89a8368ebfec0dce354", "e91df190e6c733a9b877b86bc6395e", "13da9a06ad08fce2d2163b72ca31cb2", .None}, + {.Add, "ba4be5b2c217db9e28643a753c83a1", "e236bc13cb5e41beaf2f8386da2c4d", "19c82a1c68d761d5cd793bdfc16afee", .None}, + {.Add, "94118dedc79c6ad0c84f07611215a8", "296c103df4ae5c41be532c0efeaa5", "96a84ef1a6e75094e4343a2202004d", .None}, + {.Add, "a4af0adc2874dbd6aedc75c28cb062", "63536d6c616339a1415c4e31b39ffd", "10802784889d81577f038c3f440505f", .None}, + {.Add, "ae830a122e9acfac3c901ea99c8f67", "cb0dc5f6e42eb56c8767eb2e8888d8", "17990d00912c98518c3f809d825183f", .None}, + {.Add, "2281b0b1e987e6babd77dd6c9a9bd7", "138d9abb628b8a9394c32f934f1b38", "360f4b6d4c13714e523b0cffe9b70f", .None}, + {.Add, "-a7a7dc01aa7081edf076d647644e33", "9cb6ba46c5fe4bdb1248aff4201e48", "-af121bae4723612de2e2653442feb", .None}, + {.Add, "4b67d6b571e5e9bb07f485a17103ba", "fa51d75ea20868f3c51c794bb3eccd", "145b9ae1413ee52aecd10feed24f087", .None}, + {.Add, "f2ad7c055ab51ad62ed2dbc8c45b1b", "ac4de4f7ed7d13d56258c56a0c7001", "19efb60fd48322eab912ba132d0cb1c", .None}, + {.Add, "-2477edb593e8cbc46228081170e285", "f5d4e4168071641281259444d58841", "d15cf660ec88984e1efd8c3364a5bc", .None}, + {.Add, "132990dfc782a0e3688becdcd59a98", "9702cf61d44d3a59d08b383996dbb1", "aa2c60419bcfdb3d391725166c7649", .None}, + {.Add, "-66c9535d19e0477d631d6979de39ff", "694197b141647da4901e25a48f70e2", "2784454278436272d00bc2ab136e3", .None}, + {.Add, "67f1b9c7a3146e07457bbbd69863be", "b3074fcb2fd5dece8fdd7603167fe2", "11af90992d2ea4cd5d55931d9aee3a0", .None}, + {.Add, "915103c5fc3203b759c1d0291654b4", "95ac376a339734060c7562e124b4dd", "126fd3b302fc937bd6637330a3b0991", .None}, + {.Add, "-5e0e7a2d1de15922e82ecae9d1e50c", "d32d25991d47cb3c2976456cf46f86", "751eab6bff66721941477a83228a7a", .None}, + {.Add, "fe3aa15d3dbf542bdcbce2d9761cd2", "d1417bb13741457f27f5153c636784", "1cf7c1d0e750099ab04b1f815d98456", .None}, + {.Add, "df171cbf141404439205e4a5c104c5", "e72068cf8c0e2a33a88d9f86802d8b", "1c637858ea0222e773a93842c413250", .None}, + {.Add, "-fe169c3c58fdf58028d99dcdb494b", "8a995d11bef25a0837ad8966589df1", "7ab7f34df9627ab0351fef897d54a6", .None}, + {.Add, "-108794d0b6d9a7a29acc0e5f85b882", "dbd71f5fbce1f14665348130808a8a", "cb4f8a8f060849a3ca6872d0fad208", .None}, + {.Add, "adc6d78b62fcc9ea6d66b5813af6ab", "639ffc0027a8e2154e42c3ff78935f", "11166d38b8aa5abffbba97980b38a0a", .None}, + {.Add, "-72c1bbbe1cfe00650cfe4f454519c6", "fb9d070e564c87e23103cd013efd4b", "88db4b50394e877d24057dbbf9e385", .None}, + {.Add, "-af7b7d0eb9fe8ae996a8c4c5b8e853", "638a00cbebadf31daa823dc34183a2", "-4bf17c42ce5097cbec2687027764b1", .None}, + {.Add, "-57a6ceb0081c5fb28d4ac11e204605", "458dcad55ca60994242b80f89cb382", "-121903daab76561e691f4025839283", .None}, + {.Add, "-8a1092197b0102b41a2f4f90857758", "888809d2ba016d63b74138199e197", "-8188117c4f60ebdddebb3c0eeb95c1", .None}, + {.Add, "-646aebad41e4e5244aa9cf37f63c6d", "518da42bc2e7ad33eb654ddd0e6bde", "-12dd47817efd37f05f44815ae7d08f", .None}, + {.Sub, "-9eece2f9574233b8b5cc1ac1532d52", "63742ac24e90bd70af412d12299766", "-102610dbba5d2f129650d47d37cc4b8", .None}, + {.Sub, "-9d822ab4ce4cbad725bf7daee4184", "d507b2b86042df114abd97a4c44a2f", "-dedfd563ad27aabebd198f7fb28bb3", .None}, + {.Sub, "-2fdb011980a2093da0971b3f95b33f", "bb345afaf9f204ca8ed17ee2bca1ff", "-eb0f5c147a940e082f689a2252553e", .None}, + {.Sub, "7946cb75589257eca4544394e4d647", "dd11ee8c0682782aac12f9ca590ad", "6b75ac8c982a3069f99313f83f459a", .None}, + {.Sub, "f39c7790cf765c2cb8b7ce5a6ff85", "e3d2b13ea956fe50445468d6536c12", "-d498e9c59c5f988d78c8ebf0ac6c8d", .None}, + {.Sub, "-8c8bf853bc5b263e9ab57ffe166907", "f19097f56dc22035124bb95d6a2e5e", "-17e1c90492a1d4673ad01395b809765", .None}, + {.Sub, "-b380c899b277ae1cd457f73dbcf0d", "f0c8c541a5e904b5a2cb74eaaffb98", "-fc00d1cb41107f977010f45e8bcaa5", .None}, + {.Sub, "-cb684d80b640b63e8101b5c9138488", "b0e553d184e96e7352d5f4ffd0d203", "-17c4da1523b2a24b1d3d7aac8e4568b", .None}, + {.Sub, "-2cf7e4ddbdcf880b30af8c8d2d1761", "c4127b7a2b5f89b535e37072f16538", "-f10a6057e92f11c06692fd001e7c99", .None}, + {.Sub, "592ebe97b11407a6911fa8496edd22", "5462bbbff43701e1a06fa5b3e559b9", "4cc02d7bcdd05c4f0b00295898369", .None}, + {.Sub, "-b295054ffc5a2cb3738b24924f6c86", "f67b3673ce86c4874c166d89f33532", "-1a9103bc3cae0f13abfa1921c42a1b8", .None}, + {.Sub, "-944843676aadeebf4127cd0e7aeef6", "8a6bb7fae6084b1ed47298250c1bc6", "-11eb3fb6250b639de159a6533870abc", .None}, + {.Sub, "60001b2e087568c426309be4281eb0", "7b8d3f0c5ecd22093c340476c848d8", "-1b8d23de5657b94516036892a02a28", .None}, + {.Sub, "9a2c1a9fdabadb6a2e5fb5c4f7a761", "3def959750b06c4d494505a2f469ab", "5c3c85088a0a6f1ce51ab022033db6", .None}, + {.Sub, "-788f377cf7e12a24c969a808d10b7a", "5386173351c66d3eb62a281296b115", "-cc154eb049a797637f93d01b67bc8f", .None}, + {.Sub, "-e1985ce1b20aed09e5eeee9a5a75c4", "3459f181a6d3b3ab1e07bad91f323", "-e4ddfbf9cc78284497cf6a47ec68e7", .None}, + {.Sub, "-78007faed211b9c9deb8060d7e36ce", "edd1e639149caa5c33c3c428dd98e0", "-165d265e7e6ae6426127bca365bcfae", .None}, + {.Sub, "-3a512137a2ce06f7fddfbb1737bbb4", "6fd30de597ee3925f2c2acd2d06946", "-aa242f1d3abc401df0a267ea0824fa", .None}, + {.Sub, "14d88a9302795ddef8e5d426ad792a", "494e1ec3f4b784bdd22c35268bf555", "-34759430f23e26ded94660ffde7c2b", .None}, + {.Sub, "-715b499d174129da58d327775d136f", "cab7b2010f537b329c17fb1d8c6691", "-13c12fb9e2694a50cf4eb2294e97a00", .None}, + {.Sub, "56e14835414c242920f7559cb98b7e", "69987f127eab5d62021fd36c9bff20", "-12b736dd3d5f3938e1287dcfe273a2", .None}, + {.Sub, "-aba455acc668443e3983a00e4a1714", "72711380b01a87796cf63d63afcae1", "-11e15692d7682cbb7a679dd71f9e1f5", .None}, + {.Sub, "-2d60dd157238001fb3708464b1f0e", "4b01f758f51fb8047db15ead1f5958", "-4dd8052a4c43380678e866f36a7866", .None}, + {.Sub, "9598f10e2f1ce544b54596d393fd07", "9e849db215bf5c598dc657ef5b9dec", "-8ebaca3e6a27714d880c11bc7a0e5", .None}, + {.Sub, "-ae4c06ac5859d736e2893f9be503a0", "9d722bb23feff5f3a01b698ac816a5", "-14bbe325e9849cd2a82a4a926ad1a45", .None}, + {.Sub, "616dd3b5715d070010c09fbf08cceb", "5a1de2a466df223678a7112ae5e940", "74ff1110a7de4c998198e9422e3ab", .None}, + {.Sub, "4c5d8a45e9e2c78072368c1926879f", "6ba08db40dee87aceb5076dc4d0e2c", "-1f43036e240bc02c7919eac326868d", .None}, + {.Sub, "98064099179083123ac9e85bf03692", "1e292653505407b4c88a146747eacc", "79dd1a45c73c7b5d723fd3f4a84bc6", .None}, + {.Sub, "63912aa9e23ce61d5d842e36d31ab0", "9607d75985a3332de34b40cc7a332e", "-3276acafa3664d1085c71295a7187e", .None}, + {.Sub, "f7c7dabd2c0aca183a8788711a203b", "4f0fcabd904feab88ca1e2a11d9f74", "a8b80fff9bbadf5fade5a5cffc80c7", .None}, + {.Sub, "47c975054ecad952075e58e399ebc1", "1d9dffb0e09d929202b05715873d32", "2a2b75546e2d46c004ae01ce12ae8f", .None}, + {.Sub, "d4c06b1a5b0a6a2b7d4e9e55efc25d", "d34d30179cad6c67f69631f8e4cd61", "1733b02be5cfdc386b86c5d0af4fc", .None}, + {.Sub, "-f1783608c4057e1cd70f595db6f5c5", "1a5a668b0f326ee287d5a4bf15ced3", "-10bd29c93d337ecff5ee4fe1cccc498", .None}, + {.Sub, "-4532f966c8e1723bef836b65eea07b", "eea3e1d4e0f498703bb898d573ac06", "-133d6db3ba9d60aac2b3c043b624c81", .None}, + {.Sub, "d5d4ad2922f46732bcecd3b7f8faa", "c728355644e63249e18978d92ac943", "-b9caea83b2b6ebd6b5baab9dab3999", .None}, + {.Sub, "ed1b919e00c96123f1fce3137f8be1", "f7c1ecaae302401526010ac214750f", "-aa65b0ce238def1340427ae94e92e", .None}, + {.Sub, "-b704fd3001229c3ac44794b29e7e88", "668a2e76deda5518b9b0f3fa87b284", "-11d8f2ba6dffcf1537df888ad26310c", .None}, + {.Sub, "-79972d8bb133971875b00bfccff221", "7568fa5b9d9bee507ed0796ace944d", "-ef0027e74ecf8568f48085679e866e", .None}, + {.Sub, "60f88bb68b29040b1e866cd8aff4ed", "8f8d1890aa6fdc9cfd06b32134bf3c", "-2e948cda1f46d891de80464884ca4f", .None}, + {.Sub, "-25b7b807a049bf5917a272008a2f76", "b5dfa68be94b92f7e98f109dbe2c12", "-db975e93899552510131829e485b88", .None}, + {.Sub, "-be0ec3af8b0ad1016a54e727b33cd2", "45e4764abe399e2d02c6ef618bb72b", "-103f339fa49446f2e6d1bd6893ef3fd", .None}, + {.Sub, "b69470a9e9d2e5bfb000bc33c31b2b", "fa6141c1f33e16568ae1e9ca23eaee", "-43ccd118096b3096dae12d9660cfc3", .None}, + {.Sub, "-13d695eeac6c814082d794baf7ad39", "d21e30897a92aefc6084b2a4e680a7", "-e5f4c67826ff303ce35c475fde2de0", .None}, + {.Sub, "-50542901e938b6b003a75ca39347ca", "64ff1946d1670544e9a6b9ed0198fc", "-b5534248ba9fbbf4ed4e169094e0c6", .None}, + {.Sub, "-18cdda83e2021ea9f3a107f67926c", "73c42092bcf1a6c19f8bdb639a9775", "-7550fe3afb11c8ac3ec5ebe30229e1", .None}, + {.Sub, "-fe09c9adbb90dc1a14eb42ab3032b8", "55491f219fd9580c251ae0c8e29a4", "-1035e5b9fd58e719ad73cf0b7be5c5c", .None}, + {.Sub, "-94c58bcd7fc07039c78c40a3b701f7", "63a456a516cc6d7e50f4378941e0bf", "-f869e272968cddb81880782cf8e2b6", .None}, + {.Sub, "-ef3ef8f65a420225562e90b0cedf29", "6dc0fc5510479d3e88b2c05a12d5a6", "-15cfff54b6a899f63dee1510ae1b4cf", .None}, + {.Sub, "-a0105bcabb38d6594b6eecc0718408", "28168d68cf805e299428207fc511ea", "-c826e9338ab93482df970d403695f2", .None}, + {.Sub, "989a1563e3a44412c8fbf6bb12dcc0", "9168abd0f7af5536c99d4b133a1f2c", "7316992ebf4eedbff5eaba7d8bd94", .None}, + {.Sub, "-a5e269d69e73bc5adcb5c01a8d54bd", "2e4a02f5510b42a2d059334a5620dc", "-d42c6ccbef7efefdad0ef364e37599", .None}, + {.Sub, "-48b18b8e4a210e436bd2a922c856aa", "fac8e29fa7a66a5b31a5421c461a26", "-1437a6e2df1c7789e9d77eb3f0e70d0", .None}, + {.Sub, "-39ca6fb330355b7a392b068bfd1d1b", "d7eb2415c0424e89cc29237bba7649", "-111b593c8f077aa0405542a07b79364", .None}, + {.Sub, "7947c07a46ddaf14c97a172065be1b", "416e17b0f89d76d1f82e0684b02c9", "7530deff3753d7a7a9f736b81abb52", .None}, + {.Sub, "7beec1f44641e40dae2b979ffabe15", "ac8e979a2708526ec564ae1564ea4f", "-309fd5a5e0c66e61173916756a2c3a", .None}, + {.Sub, "9d9812884485efde1183f29c26dc54", "912d1674da451f92fa3a9c85181dfb", "c6afc136a40d04b174956170ebe59", .None}, + {.Sub, "e7982e91f2f9bc9e95069be9445e5a", "e30c60d9bf323ed1cac0283322bced", "48bcdb833c77dccca4673b621a16d", .None}, + {.Sub, "6c531d2c8260e769cd6192e4060f7b", "e34297513c438b14c1d7c27fd98d96", "-76ef7a24b9e2a3aaf4762f9bd37e1b", .None}, + {.Sub, "-f28d5aff0d5328d41f18841f1b3709", "2c85901971b43c73148601c241769", "-f555b400a46e6c9b5060e43b3f4e72", .None}, + {.Sub, "-f59307200163e9b3dcad44a57c1cdf", "3c2b2d700820102d314bef424d6121", "-131be34900983f9e10df933e7c97e00", .None}, + {.Sub, "-cc30c975662c2c3d4ff9046fc62a9a", "a7fb32016f860a61b4cab360bd839a", "-1742bfb76d5b2369f04c3b7d083ae34", .None}, + {.Sub, "-2d644f2ffd67e479a4755c536cae2c", "eb3132b2f70baed631f038026b955b", "-1189581e2f473934fd6659455d84387", .None}, + {.Sub, "7a23538ebc4584e0238ec20afb67e6", "a9fe02d626652cf99d48c78e8aad7b", "-2fdaaf476a1fa81979ba05838f4595", .None}, + {.Sub, "-dafb46eb0e81ed169ce94d4ce5a75c", "9871d0c82923bc330262cbc8199fdc", "-1736d17b337a5a9499f4c1914ff4738", .None}, + {.Sub, "-425c29630560c018661c7ab4c6211", "f40b10c653e19949ddfb64f7e8bab6", "-f830d35c8437a54b645d2ca3351cc7", .None}, + {.Sub, "b005c0bb66c003bc1378b1ac77b2fb", "d0c47984ae59b1adbc31cd1e20a5d4", "-20beb8c94799adf1a8b91b71a8f2d9", .None}, + {.Sub, "-b3b976c04552c73064f7f5daa6742f", "cd5fc6be3926d75481c632f14639f7", "-181193d7e7e799e84e6be28cbecae26", .None}, + {.Sub, "-863013a1eb034793fb134f1cb40654", "38a7cf55c75f95576396629f3d2fcb", "-bed7e2f7b262dceb5ea9b1bbf1361f", .None}, + {.Sub, "f346e361377bce14a774836fbccb34", "10c2e5b89a4bd9cb7e2c8ad0076ccd", "e283fda89d2ff4492947f89fb55e67", .None}, + {.Sub, "-9094da74a66b31b6f7ca93dc894683", "cf4da785182e7ca5c78529324a8071", "-15fe281f9be99ae5cbf4fbd0ed3c6f4", .None}, + {.Sub, "-389df45566eda8f95db4f4614e82dd", "4b306eeeef4e577eec90b041049a97", "-83ce6344563c00784a45a4a2531d74", .None}, + {.Sub, "-45430c9807be85170b84a176db6719", "cbaf33754b8c184c6f889ff5f43ee6", "-110f2400d534a9d637b0d416ccfa5ff", .None}, + {.Sub, "-9d780698c87c24a0c812a1baf07805", "45a86b6129e9ee853bd834125dafc2", "-e32071f9f266132603ead5cd4e27c7", .None}, + {.Sub, "-91967effa2b47bbae28a0f4d55e502", "3429eb8f411db359c4e3fc9e64f8d5", "-c5c06a8ee3d22f14a76e0bebbaddd7", .None}, + {.Sub, "a5c679dddb5617bf2ed0161592ba61", "88350d447bc97d507b6047e5b1d7cf", "1d916c995f8c9a6eb36fce2fe0e292", .None}, + {.Sub, "5a2b871defe6ff506b39585cc172ab", "b3009fe5fd3f332ef238d8d1e4710b", "-58d518c80d5833de86ff807522fe60", .None}, + {.Sub, "3c4437628b5b3043e64b8d2df935c", "8d7efcfdc8135817ee1f1f8bd1ae84", "-89bab9879f5da513afba66b8f21b28", .None}, + {.Sub, "fe4e8ce5980acc37920104793c8c5b", "4aa73b2ff57534fdb29e4103acc011", "b3a751b5a2959739df62c3758fcc4a", .None}, + {.Sub, "8102058057d2695ab2be1f40e22857", "ecf8ede44e9c884527c70f78963187", "-6bf6e863f6ca1eea7508f037b40930", .None}, + {.Sub, "-58ad3c0ff2eac768af8a45689f0f0a", "c5ab15a2f119ee930c5006bae02077", "-11e5851b2e404b5fbbbda4c237f2f81", .None}, + {.Sub, "-1ccccbce8c01c7549f2e5582f2e4b1", "5220ed36a92ef5226623fb9b17dddf", "-6eedb9053530bc770552511e0ac290", .None}, + {.Sub, "-7f7f4bfcd79590bc748622e937c622", "cf9424b3c3f86da1f66624cdc4e1fa", "-14f1370b09b8dfe5e6aec47b6fca81c", .None}, + {.Sub, "-dbc54af5b66e44747e09d55a4775ae", "78728e3ca1f26724e1f7c1bbcb95af", "-15437d9325860ab9960019716130b5d", .None}, + {.Sub, "-fc98b6e9b4d4353c812242d963ff5a", "df0c0bb18a1b10d7ae593e7dcb0cb6", "-1dba4c29b3eef46142f7b81572f0c10", .None}, + {.Sub, "ed562ee66dfc6239f55e0b6f0b2cf", "1181a7213e7feaa99658e414b4d2a8", "-2ac4432d7a02485f703035dc41fd9", .None}, + {.Sub, "-9c23f0ecbbe97014c49ef97142e78a", "a7d3168d010431b7f487b57dc8c6f6", "-143f70779bceda1ccb926aeef0bae80", .None}, + {.Sub, "119f896fccdbfa4deed0ecbfbb8c99", "8fbad3985011f45f72b3d5cc6ee19a", "-7e1b4a288335fa1183e2e90cb35501", .None}, + {.Sub, "-cf03ffc878e147ad8321b126a884e6", "2ef865fd3c8cdc2540c28bd16fa0ac", "-fdfc65c5b56e23d2c3e43cf8182592", .None}, + {.Sub, "2829b210731c645aa71e80de2921fd", "94f456b06107331e0c8512180b0047", "-6ccaa49fedeacec365669139e1de4a", .None}, + {.Sub, "-87272340592e836388768a7fe6cb26", "768e939f7d540a14f70074ac6a2470", "-fdb5b6dfd6828d787f76ff2c50ef96", .None}, + {.Sub, "-4f0507156f8af50ebe5c74e9004d78", "21c8b862515e875d1155601e62f2dd", "-70cdbf77c0e97c6bcfb1d507634055", .None}, + {.Sub, "-6c9cc85902f4eb71670a925b55acf9", "c8914a4b7e48994af91a3642dee237", "-1352e12a4813d84bc6024c89e348f30", .None}, + {.Sub, "34f7f1bec7ac859ce0935b935eb52c", "a86b6c7174303ff8fbfb3ed90312c3", "-73737ab2ac83ba5c1b67e345a45d97", .None}, + {.Sub, "7cb7d2b29a6ecc131927a7180d951", "2a4f4fa3c00a3ff75b25cde6fe3860", "-2283d27896635336299353757d5f0f", .None}, + {.Sub, "ae8cbc3898c4b3d3548df0b2b144c8", "11efad9c98ab651398136b7da16b9", "ad6dc15ecf39fd821b0cb9fad72e0f", .None}, + {.Sub, "6a623bbf6d91d5d1d3f956641ee1a2", "510c7f29a4664da4b3beb6378a851f", "1955bc95c92b882d203aa02c945c83", .None}, + {.Sub, "3a4e2e93824f6f7aea2f20f20a338", "c2550cb346a7e1ea855c10400d47d8", "-beb029ca0e82eaf2d6b91e30eca4a0", .None}, + {.Sub, "-4bd7c098d75f9ab839bb618b9cf39d", "ff7d0dab8bafad2fda37c1e775edb9", "-14b54ce44630f47e813f3237312e156", .None}, + {.Sub, "d7561fd3874deeb8133051e18c2b0", "1fb2e2a3e9fcd337767bb91379b3dc", "-123d80a6b187f44bf548b3f560f12c", .None}, + {.Sub, "-892a192e9f534b79b9afdee0362cbe", "18ad6aae43adbedec0991798ba066e", "-a1d783dce3010a587a48f678f0332c", .None}, + {.Mul, "ba85edad8e2339e7e6bf7136dd450", "b80c5ccc86eb6a294be5ffefb166c0", "861944b908bd615ae37b8f46d00fecd4a900cb304dd2b8f6ee2d0471c00", .None}, + {.Mul, "-e8f09bb2f6aaaa2aea99e7891a03d3", "c07460c22b02f3a333ae0f25521ffd", "-af1e59d7adf3f8cd6363b33b5e6e1f2de355ef17786a68a073ac5dc25487", .None}, + {.Mul, "50c0259b61e9243dcdacf794fc2e18", "39865a087210c037f82f44396289a6", "122529597f56cfc51041a3a84088d97bd67d2dd601242a947c728d60bb90", .None}, + {.Mul, "44866ab7ec87112628bde0e9758a63", "b7d58a410dfc656ba4ee7febe6bf82", "31353f222482fab9a5e85e018f304e9aa760645919e7f51f912575e22346", .None}, + {.Mul, "575f46aebf14ea609353907230532d", "4637817bb446da1237bf290e1ea189", "17f6fefd32b6f601a83d38e4bf270921703a02b32fe168087b88b571d015", .None}, + {.Mul, "-d3cbdbd2f21ebd144454c334b93df4", "3ebfbbb5e8ecc2b92ea18cff4a1ebc", "-33e9ffa2827039fb21e40fbb6c9a06309be340b90049a12b373a61d41730", .None}, + {.Mul, "84a3cd15d34847a9758d3b11961af2", "433101297ccfde0cdaeb8ccad0acb3", "22d042a11a2d54bf4bff86726879ea291ea58a77a54e86db0daefeaf6f36", .None}, + {.Mul, "-64136a6266ed6abe87ed3706943fd8", "dbdcbffafafa73d199f7f4d7efcd1d", "-55f2e7be340fbb5d05f4191b01ad717f943b54052d56ea3ed76678933378", .None}, + {.Mul, "-5bfe6e7be4b0b0ca17f787a072688b", "41ce527e375b102dfbc78ade5d075", "-17a5be6f3745564b0b9477a2e1afd36db0b125777b34b4e3f7ebc91b787", .None}, + {.Mul, "-3b1b33854b020ecbb222f02ecdade", "6a516cf7da760278519b5a97701d14", "-188c101931a6f00282bf087e5727e05cab4a01ee8fe20d057c5c26c3f58", .None}, + {.Mul, "af79829a187f36fd50a0f0484732ff", "95ac06bcf623838446fa186d0d03ac", "6697a345cecd217a22949b3df9c0c6555d3612bd7be55b3cbc858f624054", .None}, + {.Mul, "-cf9b03bdaadbd17183b885e99361ff", "e9622ffa660477ce783a70e4dac206", "-bd43b6a794ea566fd47a3ae9b3008fc072ce5ad78a6c97329e7db8dd89fa", .None}, + {.Mul, "-b84e91c9541248b95281d6cb08dd4d", "148cb3bc780846dcbe55c27b63a9cb", "-ecb6fc214b907201c2fd78b4c8e2dc9fddc05dec14d0f19cd776de6510f", .None}, + {.Mul, "-7bad2a44ef9022693285de9e3f5eb", "8e92cffd58004640e88d8141cc1b97", "-44e0faafc206bf98aed665582e775f9679c816f785350915493a2a9d69d", .None}, + {.Mul, "e1f4ac61db7beff8e476d7dfdbe066", "b5bc67e0d168566895ec87eaf6889", "a068493fa852dd048be35a374d68527c16c1ce5451fdb0e4fe8b98e8696", .None}, + {.Mul, "-6b9a96470c99dcd170ffaeeb164756", "5482e2cdad6205a78faecf2ff36e04", "-2385bd248c8c9db7c5790d8772a00b32426b6572a387d25d8787bfa21158", .None}, + {.Mul, "85335af4a1e42c9667d2ed0fae777b", "f734f0113b13274395534c15dd4d61", "80a018199e4f3896f52378f8854609841de32fe2d314b4d76c78a73a449b", .None}, + {.Mul, "7166d3abae4e93b9be030e2ee66b4e", "b9a72bd1356bca84302312f0a3c45f", "523d5c7418202cf6cea7836cd205a28289d4d278b15dc95914f7445389f2", .None}, + {.Mul, "79f689cfe4875f5eb61e5e08aff7c5", "99e2700dcbd8c220cd4950c0994acb", "49503965580a5ed437bc7ea40a53509693d37af558a8594e08a295e56b37", .None}, + {.Mul, "-76442ae1ae81d078455b1a1327d6d9", "24fe3d11def7f411e59531e40f7e81", "-111709e0c835af6598eaecffe0e8f3263860eb806151c129c4c91d891159", .None}, + {.Mul, "-e800025b39a4c886bd83c9f84b9635", "4a8914a5e9e5c49964e8cf96776a75", "-438c3b65fda45cc57217122f10cc28d766bc212d31f546800e1ea7609839", .None}, + {.Mul, "522b38dbca9e077a790b6c77eaaa7", "12879eaefeafee973f31cc14e3efe5", "5f291b9485e9cd87a0b1ad522366849de9d2bda350ca5ad67a13b59063", .None}, + {.Mul, "-97ee3b756e79745435dc5da4631f5c", "26503f7f98938b4a9603246802c1a7", "-16bcfcf55d76f66f0864edc606f194220e6b32bf62828cff64789605d104", .None}, + {.Mul, "db1fd8b842eaa28a1da00f6e88c828", "35f5a9bae3eebbd35babf49224875f", "2e2fdea08c814dcdb5c1c1f3ad3c875ef99adb6664f505e594871bef5ed8", .None}, + {.Mul, "93013e0282d0b755f96ed81d9d7495", "348e54b9201d4af63b7bd7f8e3c9d", "1e2dfbef9ea691b04541320d68582d857179585f0a23eb9c0a8a6896b61", .None}, + {.Mul, "2f897b2233ad22b26904c7b448fe4d", "1df9947cede6533e06f81ae388c17e", "590eb3e521356be776e8e2d973d889a7255a0a8c1cf3cd1d54d238d36e6", .None}, + {.Mul, "-51009b6b8c43f3fee26550c60577d", "292546c83ec4f258e0892d36a5c619", "-d04e46036d7730ffc6423eba1e9345936158752150567618667aa43935", .None}, + {.Mul, "-a6ef5dd6d1f941412e7b8623841181", "edd510fbacb79ca621a2dcc62f0806", "-9b168a1c074f72dab2b3769447fb74715cbf7433ef5f683f6de5f2537106", .None}, + {.Mul, "8061ba53224c247556d7274cd34399", "5e6ef27960d04c52c6b7277191aa44", "2f5b8601d731755f0770b08814129c3f4325272b92240ff4af4385aa8ea4", .None}, + {.Mul, "-2d1c0f72bc893b2bc3cfbd949ce351", "dbc1bca671b3ed66a1620c6ca2873d", "-26b9249cbc5ce734974f8cf3fa5e7a36d164e84992bc63305e852a83e14d", .None}, + {.Mul, "-52a5c60b609ad56df65e2b990a6734", "e3bfa2b9faa4e03e43cce2a19c93aa", "-4986dcd3cb30ce1fac68ae4a2b541dd51c75264963e34b86eafb31db6488", .None}, + {.Mul, "8deafaeb613bcc1bfb4598383751a5", "fcd5a11357f0d58bb1dffbfe9a2f8e", "8c29bccdfa8dc93e601c84daaaf2e07123379cdc23a3e4f108d129ee9486", .None}, + {.Mul, "7f8f3f0656c91ea54faf15981c39c8", "2ded5174d142c3e7b06a040e476c6f", "16e26e47fe3e79e95f88505d6924c467eef03089a2e94a9678a5d3156db8", .None}, + {.Mul, "-b298e4e765fd328ccd189aed3baaa3", "d737f0e239ca51659ab6917bffd284", "-96256f24ae42c324ec65137b4926242997dbfe8fc0e18967483b8e1ab20c", .None}, + {.Mul, "-445e93872381bf7c34c713e89ec7ce", "2d7fa42d25a67f8dc1a864d1d8db50", "-c26b6b29679103e2921c0f94de536f53919108e998959f561c84a5baa60", .None}, + {.Mul, "-90a6fcee3eea8595fa63bb36793624", "a8afbea51a2f043e273554e84db607", "-5f50e3dc7a4c48fab6d2f2ec8101817989c93c8f00d1b4e4462e92a212fc", .None}, + {.Mul, "424d5f783f1d5988f6cb445a61fbe8", "1deb12f4664e3665f6bdbc3742fee4", "7bfa5bfff7ccbd5a74efd369ca6f7249e8a0359615640647b4f81048aa0", .None}, + {.Mul, "-32b66061bcc8dca1342b8f5c80b513", "c7f3690f21423cf2e57cd4ba1838fc", "-279bfcd94354b3d77dd1e1311e6b270999f935de454539d294b7fe1666b4", .None}, + {.Mul, "3eafdfe69c23f68c58d2aa3030f4ab", "80fc4c274bda04ba2bcea26e8bd6c4", "1f95b7b98aea2aaee55ee9f90b5959ab25720c525df871ce308224db44ec", .None}, + {.Mul, "-151b990d5024a131895aa46d4691d2", "e9555a7075ec61e16cea135eaccd44", "-133d27ebe8f7b155c5492b9bf0685c51ad6279b685a520c9dab99e9be5c8", .None}, + {.Mul, "db728ed1d46b208417ebdb4d85e6e7", "785434d6c806ed59f43c3e548fcf98", "6725e1d49aa95cab5bfdd463e3232d13e24ce624ace80692ab67143ee228", .None}, + {.Mul, "-e510bf187b74481b6d4c11acca819", "1a395e5bb0044925d244314cbfb350", "-17770891399b9056db54fe10f95cc386db1912322106f421377502502d0", .None}, + {.Mul, "65212dfc5a04472a2ce5d73d07d6a5", "c9cb69cad2343849c6bb27693df42c", "4fb7683554dd600214633837596b8692c47ff5142d222db4a334c83f285c", .None}, + {.Mul, "1a1a416297ab7d56bf1b7d676de207", "1d807e26eb39386fdaab38d3b2fc58", "3021365c08a6dd9a054e51117b0f6e6dbadc42fa9a3f32c7f26a6229668", .None}, + {.Mul, "39ca434489546ef160936326abb745", "c2b336423f3ca7594ec23230a01267", "2bf3bba6979a467c71f84367301ff876749adff2df521fe2b8c61d1996c3", .None}, + {.Mul, "-df5edbd9c635c583d77dd7e3882bec", "dd1b949aa17a6227709afe98ec7ca5", "-c0ecf475f323ebe46dc647d47bbeaa9b1c2531451f3a63bed620399a9f1c", .None}, + {.Mul, "-7e4b9aa40fff0ffc6ef342cce21f7a", "bc848f00f9e34c6d13cf2ab48419d6", "-5d00eb18ef00e0590e7a7f76b4aa23561d0609d0e24bfd9c52975d0139fc", .None}, + {.Mul, "-4831b33c1b288f9b29ec5949dcc16d", "a038f9e44c50189ef9fdaf626a9427", "-2d2f215d7f3dba4260c56056c05458498044889e97c4fd5baa44b1967b9b", .None}, + {.Mul, "-36b936b99eb9b33b656020f242b099", "2051e2b773bf7d92993e6b348ae5c7", "-6e8a7e83e068e96865760657a12b8cee6ae27bda75a93d93417404a23ef", .None}, + {.Mul, "-26fe93415bfb0ebdc93c075526c9e6", "74c8c08c38f185da5b3e4f594e2240", "-11c9eef0f313a5ce8da5aa0998f00e770155c319862b4fbe6b20ea970580", .None}, + {.Mul, "-ae362073dc0c468ca8b2b5a1d59fad", "a83756ea4c8673f95b521d119fd65b", "-72792e12a1c07ba61d30d166660ada8c7c80a7deebadddc18fbac3dd607f", .None}, + {.Mul, "-24110701a8d75f8c6116242fe92f4e", "a94c2f969941a10e4fd878a602df63", "-17d9f96284cf2330016bf721f58cb2aa9bdc33ef93569178a6c999fe3d2a", .None}, + {.Mul, "44420de61a79b74296fc1a97ebabf7", "3c1475021307f3f0aaacad72a7aae4", "1004ef9dc21fe43d162ddc17be032b6423f7a7d8d269a2b567cdfa382dfc", .None}, + {.Mul, "-110dea3ab5feb4de6bdb7e039405c3", "4b06753507078f16346e0d234ee8b6", "-4ff81c19518189bc050f47438af4e050861a299cc73b114a79f1aded0a2", .None}, + {.Mul, "-d64b33e9d82a0d913b6f4bb440f667", "99db8444aac20b03eb173eaab801db", "-80cab3146cebca57a596bc742d35f964d95da7328246a0d021baf491311d", .None}, + {.Mul, "-daa746dcf01f18a5ba49ed22f15bd5", "c28e6f9789da0fb68f61a9861b7c0", "-a62c6bccb2a71f26b0500ccf66bec76c7ea3ba0974fe6738371015f22c0", .None}, + {.Mul, "-95960b7095fccba3c7e24a6f33feaf", "b6ec572d13d8fc70f9a2ba4cfd7c2e", "-6ae2c564eb48308a2aa1c67ee8bd79986b1652d00d5bf742d661d1a78772", .None}, + {.Mul, "3b14b87809513ba75ee477d9da55cc", "dc41767bad609c0ea578b4c9f022c5", "32d4ea22167b6f4e339d14830c4fd08912ff335ace98aafe58a73fa91dfc", .None}, + {.Mul, "-b56e0ce822a4cbdee0fd898e06b3c1", "8eb0a145f1146cdd1fedb2deee74b0", "-6520391d6a71c6a3737d24343134a200dca6b04a85ba830e263b297d08b0", .None}, + {.Mul, "e454a1e4bed1213a3d57e882515522", "b8756cc542e5b9da9b79bac82cc41d", "a485900e0bc952330b34f2eea117223f3bbe7b81ee69f1f1d64e3a3cacda", .None}, + {.Mul, "-46aac845c5d8de07ac1090c89ab176", "562cccfd5318b64b97eede32ccfb8", "-17c9bd37e1c493bdc36b7dd6704324e360e321a3b0110a8fe7566f5f6d0", .None}, + {.Mul, "-3151fbbd6b9b6383ede98a2142f16b", "30b3d37ac0ab7116a833fc9da2f37c", "-9620444c24cfca072bbc99279a0393656361aca25b7eff04d3a0c4b80d4", .None}, + {.Mul, "335c84c9c64d828ed030660a0965d0", "aa53af88985931af7b92d1418b58bc", "222c3a64b198118e6252e38a5f683e75e5410d92f5414a273326b1d644c0", .None}, + {.Mul, "1e508dc9ea2bb670e8cdb2927abf6e", "4147ed828c29d40bc68e2079cecd61", "7baf877a039fb52e250d0d0e854276f545af4fb06ee5076c4f6d4519eae", .None}, + {.Mul, "d845cfefc2150ef4b79e700b34ae58", "f10f4174e330fe9d8624fcb8ef8316", "cba69c245e1f96ce7a0b163ff6766d70b6a127d9477e1af3457aefe60390", .None}, + {.Mul, "-a84892b7a41abf2f677eeae9ea1de9", "62a7477d3ef9dbee3a49e745cdc200", "-40d9be807824af83474a37f839af33ce67aa95371ddb9ae9de0c2b3f9200", .None}, + {.Mul, "6dd464ada799a21da3dc6692280d29", "66eaa64f07673fbebaf74d57927652", "2c274b9ad8832fd8affd595c7906853015def63d6fc52cc75bdeb7471d22", .None}, + {.Mul, "ba6f587aff239ec44869ead277eb4a", "ed9c631b8584d323810a5fdf3198c6", "ad0af8f0e359ed794ce7085aeb211e0d21af3b927b6a1a294bf57b9deb3c", .None}, + {.Mul, "9488439fcb0ca82ffef3b1e73c95cb", "58daf70289573fbb034abc9c781152", "338de29975de823a0df0f5a7a79ba0de875f161649a55051de1902827606", .None}, + {.Mul, "-f5ebce766834dfec83d9bedef2e76f", "dda4005977ad80a0433da5276713ec", "-d4ea1ca26dc2773c4762774c6fdabde704db36ba5412083a390995c39754", .None}, + {.Mul, "18a25b8fdb088f2d75f906a6d6bd13", "ec4f8d1df6a13df060d2d105e8ed1d", "16bd54172dde9e9f41e87fc3aae5d7310fd8c836abaf40bbb5056b960227", .None}, + {.Mul, "6bce9c86489e6e4121f9eaf16bbb9b", "6752dba265ee657ed07588aaa930f7", "2b8305a64dcdd6c96cd5548d683a8db85a4250dd89276cf89afee972128d", .None}, + {.Mul, "-389c9899726c8953a7980b2fb7aa50", "2c1f985315137474bbc2d84ca7e8f", "-9c1e6e034493e543c102ba30fe3f324dcf701e67c34ead7a89b08b82b0", .None}, + {.Mul, "-638156a2797b74bf1afe4a6a155829", "74e164b5144532b3c52a7de6e51b1e", "-2d6e3713ac036f12805ce36e7c3532d6b8f3fbdc2f43614b7e3a6179a7ce", .None}, + {.Mul, "17c56d621ec0bf9f4988c9ffb58a58", "96e2a0b903fecb43e9bfeb73b2536e", "e02b94ea10c6e9bba96d075905ebfd5b13fca1546fd433a44db750bf9d0", .None}, + {.Mul, "5434db36000e8bac5f54a265937cd7", "1ec75f704c2cc774c86cec4efeaa4d", "a1fc62b48831d1767efda6025693c1119798832ea556b8dcedfdd9552ab", .None}, + {.Mul, "b5ea69928f817ed539233771138671", "90ecda3eedca99db6bf31cc8143ae4", "66fc2a92197b7e74e5e988c776d8faafad1bc5965259ac84fae9eaad56a4", .None}, + {.Mul, "2eeb40708b583201f9e304583327b0", "abc439d3f6e56308f0e18ff0a6084a", "1f7b1ac1bdbddf3a804070e3814a666cb0d9b8aa4e969849c3b3d426f8e0", .None}, + {.Mul, "22bb60094453f07452cadfebc0cc1a", "4de319ec33a75def81f40d687f6b05", "a912b8d49e44f1473055080d09259a2f93135d41c0657b2facb00f8da82", .None}, + {.Mul, "-c622e25a31b2630787c2c3cc7f048d", "825ab77d8a98ef9b0a52b6ff1d6d89", "-64e3ed397b0e3abf0141ac94f6da8c0df799e8edc1a48cb9af047be27875", .None}, + {.Mul, "-78fa9f5871df4be60284a53506ace8", "555ebe5c004b5baa6333a5fdbaa33e", "-2857fce45cc1793c2ebbe5b63cdd3f5115b51b64c9ab63f91a0900459830", .None}, + {.Mul, "f9223a939918688ebd108b67b0dd13", "b47a0c09de8ae7284d2eea4ebdffd4", "afa2d736e781f5b8655d159cb164bdc3836417f112553eaa7e080bb400bc", .None}, + {.Mul, "-943737729352b29148a5ede873428", "7fca102a1b1f730192c073ff1bdc68", "-49fc616f6bb88ff6d3e82dff6f798b620f3f72781a0b39650f4eff79040", .None}, + {.Mul, "f678ab3edab18671450523dcecff60", "7f893b373234e50954d8a3de35a854", "7ac9fc8ac6dbe0130693fcb69c4b8e50e0e60dc3140d6de71566243acb80", .None}, + {.Mul, "b1c0078695f4151046315ab1eaecf7", "196cf07614b6c545ce901c306736d0", "11a764b5555fa5ba87584178e5b105c17044dac55306c109b82fc43da2b0", .None}, + {.Mul, "c07906a11538195b97aad3d600412e", "4c39beb28c41eb9174bfa488e0cfe9", "394f584a5cb04a3c7629b6025d5714d66d1cb146643be2da3b29732f84de", .None}, + {.Mul, "-f8df3efc9c22fbeec950e5948c1aff", "5c19a4554b1a0cc3ff59a493ce7772", "-59892831de444a641451cd1ad116e7a129fb1293ed6dd76face36d228e8e", .None}, + {.Mul, "-bce363aa51ffa47bc5b0e065ece971", "d7f2338955216fbc4e7c18ec2425b0", "-9f55adaee33aa7222ee77361d87450a061604a5246d9d3b5641e5081d2b0", .None}, + {.Mul, "-a0b4a8aeb0fb50d8af47f668a7af51", "16f6c674eb22c0402ece9dfa29824f", "-e6a70ae3b02de036e6a67f0339e092c57b0da09df5fe7c48ceca0bf3bff", .None}, + {.Mul, "a7b130f6922209b6c811bdafe63957", "8f5760cef0b54fc39b3ab1b67d50a8", "5de536fb600b6ca359009c61d7c41f8f7e04c28f2cb7c15bd6c83a7bd118", .None}, + {.Mul, "e70bee0106fab769314a0aefb7b703", "7e7961010c65032c60194b99c77d44", "72256b547755be26a0c20ae2bed50809885f592ff0a56ad60f056f7e13cc", .None}, + {.Mul, "a626ee3e55572e9a2755990517ed66", "5f4ab1e2de21c7dbe733f38a45ae26", "3dd8ed1e28f320dd0bf192ece649680fbada240fdbab400da56afd669124", .None}, + {.Mul, "f930583e6fe961405c62264fd0ac0", "d601e9ddec95bd88b4e34db2c5fc1d", "d05046998f22dbf1e2e172e159aed275fedd0853631a60571414cff37c0", .None}, + {.Mul, "2987f181680da944d99703f3bde7fd", "d90f796edb6c14b41c90cd746e33ca", "2336be6114f17160e00be5870112f4d3dd5c8fe5e120a028d0fe7bc674a2", .None}, + {.Mul, "b55e5cf9862622af4c42b2e401b4f", "7e35533a3115eaa5b766001cc1ecd6", "596a3942e1fc18c5439856a6ab71492dafc2b95ecb7266b260cfd52a80a", .None}, + {.Mul, "57418ba7b340d0a54fd0108bab5299", "372b8451c37dc28af9cc4031eab297", "12cdea1d270f7be4abbcffbaaba44e44492dc7ff64559c1242884a561a3f", .None}, + {.Mul, "4cbfd5c01bf90779f2f8712b25e2c5", "d19291e213df2ba484a436cc500f54", "3ed48ea62dc7eb9f91fa452601782d0f66e76d35feea92dfdcc33a47f3a4", .None}, + {.Mul, "e3772c48f879556b2742db96dbf7ab", "8a3e17a26c610dc22e4135c1c09909", "7ad569bc164eacfebdb42fce91eb4a9aa1cfbe230c8e18ea42fa7000e803", .None}, + {.Mul, "8acfc29a311cb6a71b172aaca92a9e", "b7b6c917925a82527064c1bc14c3a5", "639da0da7a8b8e15d2b03d324ead73a842c930f5a2a7fe8c01a780d6d1d6", .None}, + {.Mul, "84d4bcbf06db9f99c7a914cbc74a7c", "bb7dad92efe9ed05c14f8ac3a19234", "61489bcfb4a58038a7816a4cdfb7704ef14317ae5513352f955b58f1d930", .None}, + {.Sqr, "-96032b1863272aeabca0bf9c563edb", "bcf7f027360196e1ff31b7270971ca", "57e7b68a9e056cd7fcb704e0b9d9cab5d76c0900b6472464c4733292cf59", .None}, + {.Sqr, "65c210762a52b74725be8116ebe140", "c6850a990ce9bb13d7c3e25b9e6ec8", "2872b41a318c65d14dc69fc39dcc98a5258704545fbedaa1668e51b19000", .None}, + {.Sqr, "e144ec2dafbef25ad3b3700c27e2a3", "ddda1d7608e010982362e85a1c76fc", "c63a39b6a11747a3b9012a4ef9eecac033db69b267509f1c04161e4e33c9", .None}, + {.Sqr, "-ba5b5d0fd1c3a6228e2bbb0754af21", "68af15c533186ac5aea79f8a881669", "87a8e3d647e3ede4baac3d00fde0c1e44f108f68625d355eadcd33762241", .None}, + {.Sqr, "-18cba201d349bb0bf72980f8855d33", "763cbbf829ba9b5a5044ee117ad00d", "266d05aad09396d8902fe7b879e6204e9775d04d67268e4330cc8ec1829", .None}, + {.Sqr, "-9f58c789e4840488acbc20758a982", "7584cc11f734750f0c43ef65486d6", "632f66a71430c3f084dd34a5cf7f85cd8e1ba4f6a59f930d02159ce604", .None}, + {.Sqr, "a8cb4a1772191b050c5527a2b23526", "bd0e3b03699883aff445dad3e33a78", "6f4b72ad5c617763b12d77a2a0f5e10f1a4aee3630f9c88d74e60be0c1a4", .None}, + {.Sqr, "-ecec85c1509f63d696d351c22c27b3", "c69b2cf4f3330702672843a03817b5", "db44f1234ef4f5b40131384706c2be02ba0ac0384cc1066d250ef7b00729", .None}, + {.Sqr, "6e78c5e09ed2332c772bcafe2235f3", "46570392f186c3c0ba3764445c313f", "2fac030724050290053d7c7d88fd1e6a12fabfaa0381384ead1c93ea84a9", .None}, + {.Sqr, "a9fb6d596e151b2974e03a3eed2493", "2c91f1c6ae5e683057d72b95b78231", "70dded4faf6b023bb2bf92089a2109b5de3273b0cd01ce258bfff167ac69", .None}, + {.Sqr, "bc8bdf3efb952c1f7f2036aed630be", "10f49df8b775088db48d5d4137749d", "8addbc50b2971698e349777a06e1442499e34398fd062677ed9fceefcd04", .None}, + {.Sqr, "-d933f443efdd3bb7fad9614ce780e1", "370153cf234131f3ae7bb40fb37c4a", "b8491ea668c834a8daf546be84579332e2d7f7eb297b3c7b62616eefc5c1", .None}, + {.Sqr, "f4101d1231f1cb088c95aecd299126", "a835ee5b4488b864fb5e6d91f5e09a", "e8aeb86e54c849dd84cdd913cc7980d59cff8749aefb0d7324deac7811a4", .None}, + {.Sqr, "cb3917e1d3d9bf8b59ebccefba0204", "cbc58df3bc21c6ddf6c08b8a599db8", "a153989bcac6080581286a17e2dbb9ac58bfc3965bac2f6b654a65d41010", .None}, + {.Sqr, "-7f75582e48af0b22ffedbcb280adfb", "d3ee9198b10014cc03e55005e428cb", "3f75a347a4cbf763731ecf02ec4c6ea316bcf038d5bc31a379477d3d3419", .None}, + {.Sqr, "b02ca54b742092e9afc3b8ddb046ce", "dabf5009db86e960f23d423430b5db", "793d6b10fc570f230f2664407d96bcfb28057d616215c2e16fc11ad54dc4", .None}, + {.Sqr, "-a072035a521af3abb1ee2905679287", "dfcc7b8498c40898e390470b66ccf6", "648eb6f7e31e0e621a52cd385f7e7d139b5a1661bbe2486b28de82804331", .None}, + {.Sqr, "51d07c5e42ce3c83746fe0f73aa323", "1af6e06fdf02221a9d21934359c632", "1a25987dfbde84da70cec8d922da31be52bde5dfb89818900b7bddd196c9", .None}, + {.Sqr, "8794606f0ac40c6f56db89d5f276e4", "b3956272d660c8609e9b7d010c394", "47cdd3b4c212b0092e222a04bcbc82d1d96c1b0165a520eab7846646fb10", .None}, + {.Sqr, "-f34bdc4e02092c322babd4fff2c45a", "bd20405e84a72901fcc82b40856805", "e7391ab6eb28c68c25df1bb3937dc16347eb5788e2585a86fa731cc1efa4", .None}, + {.Sqr, "-42127fd5f7d57944f48ae1009b2a78", "bc028bb9a9ff29b7e5353acd311a37", "110d8b408db6eb48c345d8f2c485ebd6ea3cfb7cc6320f4a64fc745b9840", .None}, + {.Sqr, "4557b3659835cbb67aef9141111e9f", "93707b149c91f3d23fba0881503d5d", "12c864c030d1af8d84208e4081440c88c7d1d9cb4bee00a744cfd2c7a6c1", .None}, + {.Sqr, "-8b2de3edce3acb586810c048f5e0d3", "5ae0f63f75676df66f31319e0d5e91", "4baaddbe2a7df22141b4bdb445bd71eefa0370e31685fd26d71ec94fede9", .None}, + {.Sqr, "-2c3bac51f80aa01cafcc5991254f29", "10c5ad10b716e77b45cadaf3a329e1", "7a491250f0a3b7cd7dbbc058063a90776324795a03ce673ab9e6c545491", .None}, + {.Sqr, "248d700f3747480b070b40a1af4e50", "5bbfd64ed6faddc6afa67bac3c697a", "53815a8e95c420e5b74b8d51eb3218e73b46258f38776e0008cc954d900", .None}, + {.Sqr, "-8b55eecbc429730db7a985df0bbed8", "7904128c9f91f1fa733ccafb43bace", "4bd66e29b914c9650e878616a7f9d1e7cefa58bcc0bbcf52f37644d55640", .None}, + {.Sqr, "a1bdb894ef3e2fbdd7873ae8004eb6", "4f02f4304b8eb587f85ba11f021fac", "66302ec565ebe86e2b859b580547393f9058250261cf371c2d21f8336964", .None}, + {.Sqr, "eedf0d73d59ccdd4339daab88c782e", "2c127094537aabb8ecb30f8b1ecb4b", "dee37f5bd1b2ae00b1b1de9193b31fc9c24708c590e5fd5642edcabb2844", .None}, + {.Sqr, "214cbdc62577328fab7c04a41cbc43", "d84a5871925e2078bd9a30c8d75a08", "454dfee4ffd267f0a09d06506aacf997042fb3dabf3bbfd9e87911a7989", .None}, + {.Sqr, "b0ec53e6723d1bd57cb8354b3988c5", "d0ec3c7ef033cae001d7e3c1bd0427", "7a45cd87a975e475f5f02ac5a934e71d5120bc20001d416094a39ecbe799", .None}, + {.Sqr, "-38404a00734c5096468848dbebec40", "a1644a4836e092ad830ef045f8ce67", "c5c3085480f4c125c836bf265430d315637fb57e4474fa663a117861000", .None}, + {.Sqr, "-fcd241657f20427a6f26ee177c4ba9", "ce6b5a4a00fc192aca3160afbf2360", "f9ae9d6f2d80c69a0c0aa7b07f047254cad95175a57344486c2dc0147591", .None}, + {.Sqr, "-b5f088b23f4d364e7c7c3dbb80ef89", "2f30a66627b9de15ce55da24373215", "814e034ca4b7beeeefeb19ac5a42c84c9d354a478b33558c7e2c8f211751", .None}, + {.Sqr, "8a92aa874fb37a1c07c9b45525b96e", "2e3e3c282710161a6fd8834f264993", "4b0273e0d5dc65bd06a69f96e24855de3842789226354a9191622c1c2b44", .None}, + {.Sqr, "-9fa4bae36f6bdcc76a7eb1f8d3e024", "aee102fb155a58a4e085ff894780f5", "638e0a26803e066a1c63dab550c155aea0b6dbae78782d4a9368ff970510", .None}, + {.Sqr, "-c1f9d90198b3969115c916b7b76f41", "3ec6e76519fd14e6ce2824170f8be7", "92faad0c454d8b44aad47a48795fd2c9c214c787e4ce06bcf5ab2d476e81", .None}, + {.Sqr, "b119dcdabe5610fe04a3cc67202f59", "a68b6b550b1b75bf081f4593bbae4", "7a84c6035c74e25b3954cf666f9e1f5dab5783c6bc9d97e9b5fd7d01ccf1", .None}, + {.Sqr, "a844ac579705561ee0be91e36647ff", "bc4ad79ad7f7d5dd8e4c3f57a86caa", "6e9a349ef8c50cc571d2d769b3ebe9352d1f46d121e0f8fa9f69ad737001", .None}, + {.Sqr, "-8ced1e5e3e8f37a3a2fc430617e03e", "f4eda682bbcf282360f49f86db0cd9", "4d9434d85286b36390c095d40c361e00116307f9c1f5f4969130f7908f04", .None}, + {.Sqr, "-2eba35216dbcc884cbd8c80522aa4c", "7afb66b27fe2e8d671c1158377bd6c", "8877289430a2a30bef71b81065308939cd75717c04afa2cb618a5790690", .None}, + {.Sqr, "-a5e6949e50966c173b1ef81d88651c", "47ed84c8b1359007932c1b32e8f554", "6b830b4376a224b5abfacc760dd0154a9b9a627d560ed646a5d3edaf1b10", .None}, + {.Sqr, "680a7e1e171b20cdd710ee090575db", "abb926f6ecba4a8c8885e32802a957", "2a4886e68b417b0def8ec171ebb15e409d6294f82d22290de59b36cfe959", .None}, + {.Sqr, "395116aed9d21fa229faadfd618c99", "439ac2bc8ca604a1eaee182d0d5eea", "cd535c939a7edeb2bb8f7ddeb94ef7078ca358ff961a43ecfdc4329b371", .None}, + {.Sqr, "-1aee81a32e364dba31d14dfa1dbae9", "50441f54bd4a7b9ae95050c552a54d", "2d5508a7272d158f42755c7f846630c95c9fce6194b16a2f6acf5416811", .None}, + {.Sqr, "6eb5a368a85218a76731d6a2c1d5a5", "2035c67b087a775d70914057bb3861", "2fe0994e6af30268762bd10a359aaf6f233e56897de9e81a3f04a915fc59", .None}, + {.Sqr, "-b0f31a0264dd1143754d57f2a4fd4c", "3367f4d90096891e514b8233cfceb5", "7a4f2a9daddfefee2a0e7707a7db26469b25fd6309ab61f83ae133ff4e90", .None}, + {.Sqr, "6d15b89c35c34d91cc77a6ae2f7e9c", "67997e3fc9261b2a6ff03806c624a6", "2e7b810cd48a0eb332dc024c80bb3582c4b36aef9d6d0471d33bcbe5ef10", .None}, + {.Sqr, "1cfa83e5e9440eef4f6fff95b430a7", "22dc3a236081d52b713ee94f476a23", "347c2002c07976854603f603c5c2af04b36f9d0854fafc6fe28da170cf1", .None}, + {.Sqr, "-7b5ae7477513e82ee5b7d4aab8e0d9", "786a84452370385898b488b2f04c5a", "3b707a8619b17c586552cbf9eafb4999145398a75b9fc5beb58c316c77f1", .None}, + {.Sqr, "67ad65482b34d4b6bfa149cbacfa94", "98b3baa5d472a952a40ffd71a2aa97", "29fcfcf21e60ef02920d6dbd30cadefb9f960958ecfdb6b8dab064256590", .None}, + {.Sqr, "c2ca6c24bc7d45fc9efab97a33b534", "4eb5e4be10b10b376f34146489a019", "94376bf68556581494aff612a3912b06a472be4be3a8e32ac84f42fa9290", .None}, + {.Sqr, "-70c9e4c01c5725520cc45430ae7999", "24296b291c7008fc59afaa4d50d95", "31b147611adf84262659259bff91d2795eedb03280b6904bf8eae5bdfd71", .None}, + {.Sqr, "-31b628481c0cda61513161e16608f9", "405b4dfacdc6b39584747b967b93bd", "9a73d08e79b6af392006a370d165011762fef5d332804c8a322d8bc8231", .None}, + {.Sqr, "-4f2c45d269d7be9ff96d19f8b94941", "3aa585c94a0a1c10aa22d269d0cadd", "187c5abff0b2a3d06168bea3701be6033416d5610c5b8cab2cbae4e82281", .None}, + {.Sqr, "a8785b19af72d3e36d2b173d96bae3", "c74562d8a2773434b2c42936497c2c", "6ede30273ec6771083ce2a20e9b1c07bd6188d88d0c879fd0499b872a549", .None}, + {.Sqr, "98ec9821f78394afa1a0901c5ebcd5", "6cf823b54c8a4f3bd2af63a844b87b", "5b59cf512ef4f598b38cbcee27548cb3a3a97093fe3313ad8bfdcfb58939", .None}, + {.Sqr, "ed6216463744f4add0e26f802cb8d0", "2ee92b08ea59cc9be1178a1b77a181", "dc1ec2d3120822974989927b6de380cf6928b18495d4cf4445000ceba900", .None}, + {.Sqr, "-30b7f627a3be5a4567eea8a33c0b93", "568188220cacdcb6d81ea62daedd", "9458080b6c3b0d4386cefd527ea59b5e43a40c80e84dab409c29f6df669", .None}, + {.Sqr, "-5d47be6143bbfa9b1ce098466281d8", "6278930829ec6004371ff8115c4ade", "21fd346dd2beabd923634ad623e5ecbb260d54bcae6802ce3569cb3b6640", .None}, + {.Sqr, "63ac545335cb6ca9c939d1808db7c9", "17c884da5041ad1a01189df4381070", "26cebd39c73255bec24edc85300b8f9e2aea1c0bc97c3f6d9e6ef75afbd1", .None}, + {.Sqr, "bfa2b3d84303899e3aab1d299bbf87", "a18951c3f64c810d559b9f14ce86e", "8f742fc4d00c3c3c61c3f138a0fffdbb9a5e3acd3c63f31700b0bac4b931", .None}, + {.Sqr, "-2e23d45ad1358df4473159249f1abf", "f4ad96e434812035929ae48b3bc744", "850e554642afe61121e163045a380b9402a86f966b2520cd935f40d5a81", .None}, + {.Sqr, "54ca18250ebb51e6eaa9294c014ec5", "5f12ed18733a2af6fd592d9ba1da53", "1c153f626e6d257d2cc354d49cab363e3a15754c7f9b25201be0adc6a399", .None}, + {.Sqr, "-9f43be5f99e71daff219f3969bbe00", "26b61fb6edd9989030a5a1184848fd", "63153867f4c9b200bef43c41b17d2830049a67403368e7619567a1040000", .None}, + {.Sqr, "63d0f08280f1760d7a4c5086bf3716", "b8ce289c7d5efd0124dadb6546ae10", "26eb448ca5c13dfa360547175576c5939a86ad2df776c41c3a3e46ae75e4", .None}, + {.Sqr, "-a75543565266c3904d3af4c1404eeb", "a42cafef60a060f6c4dd002fd4e200", "6d605a40688b17a16485206447d1bb4833b7f79fe90bf198f31de3d40bb9", .None}, + {.Sqr, "a0457cd6d82d076cb183745024ade9", "f2b3abb6deaa0b63b78834598d7746", "6456eee916e9a7479f81bc64097c9edefae97a4b71115883031affacbe11", .None}, + {.Sqr, "9b54af2dc69edc92c8680a319114b2", "f30cc65c0e3c066a7a9a328d9da41a", "5e3fa824dc6e55171e85d9ff79f68bb5635138fe80e927df1a0c97504bc4", .None}, + {.Sqr, "3c2e31ba79c2be3ab6b58636d442ab", "de2145e27d83436b9f0aca16528ada", "e25afa551bff599987753614b6b45b769f8062955bddf5dd522a0949e39", .None}, + {.Sqr, "55412ebbf0948bf7cc22b37e3e2c1d", "ae1f8ccb372e3e518d2f1e9bdb7eda", "1c6459a191bae4d05ecd1ad4706496a4e411bf46c7169122a713f1a5fb49", .None}, + {.Sqr, "-212f13957bb75538fdd44c030d0a17", "67d2240fb3368c7e4136fb2a083805", "44d2bb4bc4838f0723748c166a81eedbd15b2d14d1569f3648e90bbce11", .None}, + {.Sqr, "-2e095600260357389361f3e1f56025", "f104e645e4fb954330192e78ab7b78", "8475b3f368ff91ebb30917e1eb9a84b6278366fca954c9fce7034edc559", .None}, + {.Sqr, "f629397893aa69fcd06fb12774e872", "3a27912177c98c89f7daccbbb7b9fa", "ecb341173151bad47bb4853cfff24b0ade45ebd377ed20911dda365ed2c4", .None}, + {.Sqr, "d98cc96f03e0d143d95f3972f751f2", "94f9cfe6a2d2ff5d0a66b8859e4471", "b8dffaeb247ee4e54e5a3e103eb644dc0e48f3e559898cd94daec33708c4", .None}, + {.Sqr, "81c2f149f5b2263c842e90b712ce47", "77dd4c5db29530d6dc6e8f2368404", "41c60b9f2122428268557cf7ec52954e6cf1b5dbe8c33b6d782b2a3257b1", .None}, + {.Sqr, "22515e3f0b57630710ccef95c4a77f", "3330c0292f00c6a8f1d4904b9eda7e", "499b6e5859abf754d2b9f7b3a6056ee4e03c30e0ee249a1a92cbe0ef101", .None}, + {.Sqr, "adb2e213127734d6c8b9734accd187", "18138247a31392360624d0f341dc14", "75db428cf1207935fe4bd4f106bfd8f154135a87c53567a46a4aa6a5b531", .None}, + {.Sqr, "dd40fcc9ff662e35e45b2ef1b389d4", "4c9f376eb9141520eec71c2d533362", "bf3944f421946d145f72ffb11ca8578d526966dfbf80ae55c79b30ac9790", .None}, + {.Sqr, "22fdda62d588f05897d9a55fa83aa2", "91ed60055f221cad7819a4af416f7", "4c869bba25eea57ffbe03c4e4835e7e9627df325784311c82e53e0dce84", .None}, + {.Sqr, "2803e9993e962fb08fe5f2f448dda1", "c6e75a51ef28d7e525628729ee2eb6", "641390f324eb6158cbcb9820f1a5de7f3d3a653b6e0193e099c526f5f41", .None}, + {.Sqr, "8794a88c92a6a36a4cbf83017d7cbd", "90b6890cef2a6b54356e359eca463b", "47ce2017942e1eb2809b7977ef3269909ffe656f81c05ac9e7ea8759a389", .None}, + {.Sqr, "7faaec48779bce8ad099180a967c65", "1873f1f30cbc89f9928cd9bb66b915", "3fab088e910122e6cfab48b6da7af58f0aa2c8c1b21ce578271de6cdffd9", .None}, + {.Sqr, "b391ac8612f741249a7119786e3d4", "92d90da7de72757d9bb29a99f2fdf8", "7df50a2862abb0e5173a338ed824909587eeeda7ff35c141ff64b1a790", .None}, + {.Sqr, "-bd660261f701f4e8e6bc82c7ddf4de", "18a8066918a33440e923ca443a2ad2", "8c1fc82a8ccf668833ee3a0a6345076c01d7cb7a4a33f8059499d583f084", .None}, + {.Sqr, "-7a6df80e66a29688607c9f149b6922", "84b4b991227c32190e30b2c5d8cf84", "3a8cffaae672459892af9ad2a78765821a7f10254eec220e2f01ca58e884", .None}, + {.Sqr, "b85fac04d66d7ab86d73cf7e0477dc", "b37dfaef2702e6cdc73322f6abdc82", "84c9ab08136b05e4b626970e43428fdbc331465f652f5e49e3d886fe4510", .None}, + {.Sqr, "651dc912c5f2f91a0288e6dfa2a856", "68f158c7787f8a20591d43871602b0", "27f0841ffc610dd2f04a52d20a466c9a36d30f48b5db87d6a3274f88fce4", .None}, + {.Sqr, "b74915a7cd300b974bcf07993d763a", "2be4259283cfafd6a061b0d7cdb9b2", "833991d342e2aba025b72658f34b7c193eff29297e82d444c93ee23d8524", .None}, + {.Sqr, "57f65bca8d169c6c937ce19b9ef1e5", "d16339db1a1c6eddf35102ae8d6297", "1e395f783616265775904bdbc34bfaea17add8de554feb52e824c93cf6d9", .None}, + {.Sqr, "2050cb3485a802bf47d620ee931f4b", "e65a13e8da82f761bde67e690154a1", "4144c4cc389e0708fe6e8d15cd5d7dd01d96cabde93c109197c67f53ff9", .None}, + {.Sqr, "69222037cb29258d77fea5e75bc25d", "3c034b2d755ddf5a8ac389e818e692", "2b2d02fa5787b6af3c4e8cb07cbf6dcfcb1bf6abc6e94785d18997af15c9", .None}, + {.Sqr, "-7fb7e2912d8a392918857405c2fc3", "72687e4a096916d55a2bd2cfd063c5", "3fb7f6e1bf42e7112ab0aa7d1f6b45282df446c359487bdf9ddd112e89", .None}, + {.Sqr, "daee27f327fbb4a51cb1201631ff4f", "6a7a7a576d2293d6bcf5de3e58847e", "bb3a79986e7304d0b700ecb5f0724c945c2d9b34a1da60bfb3654edc7a61", .None}, + {.Sqr, "-699862b24656dd10d71506811e94bf", "6c149fff90eb0dfd6c888bd64a7400", "2b8e5bab9773c27eb9ce96c35278526e191f91fbeb150bc82483b1316681", .None}, + {.Sqr, "f7960e959f85e4a210cc4b4779cfee", "f3f05a5fe39f62ed0684662fb1c46e", "ef72e819d20004fe649b5f32b851bdc39d68ab92d6604e77f0c03bdec144", .None}, + {.Sqr, "-df7b2873af17a43dd018c5eb5e9c2e", "b4af2f981f31f2669e8eb09ec7efff", "c317cbb97099cbd9ae4355ea6218e5d7f0e2025ba4418c0bd47f85101844", .None}, + {.Sqr, "8ca2d0bc8fc46c432ccc6759d808a0", "7a35024f72d4e86c60cdb7d8dd01cf", "4d427bdb1617bf85272d76dc06da58cf63a03dff1eb0701ddd0dce4a6400", .None}, + {.Sqr, "-2f4394d14cbd3264a2b9a3a9ef7c89", "c6fbe6d3d68699ba7c348b7de4a19", "8b9e27c163e4f627a9edd7b9c5ec4475942f94b10269f28aaeca6630151", .None}, + {.Sqr, "3e197e7056aac9cbf3d1951d275f1a", "b60190174cf1aa8f9a1c225d92ffba", "f105bc85a5e6db6455bab268eb1775478bcc08078db03cb19de01404ea4", .None}, + {.Sqr, "-8596662d7610ebd77034f35dd1c796", "ae62daef0f82f7f06edde669c0c776", "45b59e8722bc330a6f64b49d421b9e2e5dbe59db67a90ef7edae7a868be4", .None}, + {.Log, "cb3a39fc19ec020e1cfc863258eccb", "bd3da0743421e99", "2", .None}, + {.Log, "fae16beb299a5357f15f768746a97b", "d94c2b3644dc4c2", "2", .None}, + {.Log, "cdfc1c960b0a7dbbcc7712aed948ba", "fb3cd2e174eee34", "1", .None}, + {.Log, "a24e310c260dd862e8d77664524a94", "b6b6a51de02490a", "2", .None}, + {.Log, "69b2d0fca14bef60fa1f6a52c31194", "10d3db86455a713", "2", .None}, + {.Log, "d50c7d7625306fc5040061c739a1b0", "ae22cd2eb93ba96", "2", .None}, + {.Log, "49da58d5bcd586ce39e552a56a0ad9", "40228bb0adb8c86", "2", .None}, + {.Log, "d3f2d1b029221d5545cc44bbf904a2", "556f006ff86e617", "2", .None}, + {.Log, "5bfebdfae1b3e243a703ae1ed77b61", "9c9ce969a2387fa", "1", .None}, + {.Log, "703a3ff964275e2739799d6d53ff5a", "4aa2c9e71cbf1a3", "2", .None}, + {.Log, "a32c26c418cf4ce70d424e8fb86fde", "a00ef549af2b3e2", "2", .None}, + {.Log, "a34def4b294cb01cd502957a46d9da", "30fda2f84bcbc18", "2", .None}, + {.Log, "645c6f7d9334bae974b367ebbf87ab", "e57ec1f191e853c", "1", .None}, + {.Log, "eac99d848424ea1e2de7c72dffcd56", "d2f371e2f152226", "2", .None}, + {.Log, "1082c8483da1c096947915dc8c454", "bff5e2b08bef7da", "1", .None}, + {.Log, "e012b224160dabefd0faff6acab746", "259f7f571921f1", "2", .None}, + {.Log, "5096801b89c3283b8a77372529a9a0", "b828e3688c92943", "1", .None}, + {.Log, "1d08cf90d7a683f3ca234f41dc9ed8", "ae6e339254d9d90", "1", .None}, + {.Log, "845183d028d7827d5c69d2898563a8", "f524236e909b009", "1", .None}, + {.Log, "cebbc28e67d991e30b992d315a5317", "fbe3d82de57f52a", "1", .None}, + {.Log, "5f166836737adcb5f0e4ddeeea1bc7", "8c6051e2879023", "2", .None}, + {.Log, "5bb360eca0eb29340f044cee3c6294", "ba4019b9a9d95f2", "1", .None}, + {.Log, "3b9f4205b467515a78878f0702b0b7", "59eebd58e5f019a", "2", .None}, + {.Log, "de75ab6f5bc2d46b762f8d1c714402", "e34ebe203ee3250", "2", .None}, + {.Log, "a6ffafc0e9f3f2187767212bcfb18b", "8c8858493503d03", "2", .None}, + {.Log, "3bafa218c63dc62d102ad99605b139", "d1f79d8a882890", "2", .None}, + {.Log, "93c738e8636110a2e66e83e6ac1ae9", "478050e6175edf4", "2", .None}, + {.Log, "1c0e83b6ccc01563f6e4172f92a136", "cb55cfbc85b8db6", "1", .None}, + {.Log, "81d7846fdac3622ff78a5901fd1325", "d8918b77e0db47d", "1", .None}, + {.Log, "382d28fa74b6b86b24bdfccc551ce9", "2cba17e4b282f07", "2", .None}, + {.Log, "d4fc4fcf0994eae4b37fcdb3ef1612", "159a0919c9f3125", "2", .None}, + {.Log, "76f1d2c0fef9f815c41d60281e41de", "34932e42d095d77", "2", .None}, + {.Log, "d98ddacb7c4670c8df23d5944c4210", "d58ae09d3bd28e0", "2", .None}, + {.Log, "e07aa0eb95ff9d40f6295dde22416f", "d4f02a19e4ab493", "2", .None}, + {.Log, "b6d401a28cd04cd0c3072c9e8a8062", "8d7a4797da4e62c", "2", .None}, + {.Log, "8b2ce11d18e7ad9e07379e77f7f7a2", "1331d5635b2a6c0", "2", .None}, + {.Log, "9db731db5f3eb843195e29b1eb0b9", "2afc0341ce706c9", "2", .None}, + {.Log, "9bc7e1d8b9fd1ac549622f3aea83d", "b958e35adb913cd", "1", .None}, + {.Log, "cc631f2ff49b7eb1551db34d3fe220", "59080edbdefa980", "2", .None}, + {.Log, "283beeff4967a48f660a705d439fbd", "fb84b09fc46f22b", "1", .None}, + {.Log, "6aaf60954b6954cda37e1a4dc51adc", "787aa7527a54318", "2", .None}, + {.Log, "a69363adb74e9bf563aa95a45cea8f", "cbcf8d13ee65de1", "2", .None}, + {.Log, "ae62e1abc4e2b240609629e4a07d6", "7ecf16aceeb05fb", "1", .None}, + {.Log, "2723f000c76a7e0e5ec48cb659c6e9", "8dcc8f357fda2d8", "1", .None}, + {.Log, "f7e08f5a6953b02d24284a095aa41a", "48136a8d43d6ce1", "2", .None}, + {.Log, "c4e84985a8760f0f05f9c1e545ee84", "a671517d0ab9b06", "2", .None}, + {.Log, "e44c310f21c64ccfd0e4947ac424e8", "3a0fda19a01b1c7", "2", .None}, + {.Log, "a4000d8c479dc711e42a9ad787c4a2", "a3e45f7e1313448", "2", .None}, + {.Log, "88649c423067075b80dfedcab0adde", "1e69f0805ea2d2b", "2", .None}, + {.Log, "8505a1894ec708760ca925a828ba08", "9ae06a649ace934", "2", .None}, + {.Log, "8d3da583c668f8051c4a0dfd5ac64f", "56b60518bb6c3d9", "2", .None}, + {.Log, "375d588dacb3bd40acf7587c242502", "2d5ec2dd689f7ed", "2", .None}, + {.Log, "ca551431cc9663bb612c021f871b31", "bc31b240c621910", "2", .None}, + {.Log, "c2829899802afb2175401a8cd3a078", "93e88f300394765", "2", .None}, + {.Log, "7f907583581e65e9131b2a768341a6", "ae0d56342ba5ccb", "2", .None}, + {.Log, "c2c0b37b18c50edd66df6704867680", "24d7b5fbb8142d7", "2", .None}, + {.Log, "c677811ea6e0510c09cc3a207047a1", "c6a05c4d2008298", "2", .None}, + {.Log, "42c153a9186ba30130352630fe5e6c", "c9bf2854f84a9c3", "1", .None}, + {.Log, "89d130dd62d1dcdcd694e7fedac889", "268987cb09a0178", "2", .None}, + {.Log, "5c3e19434906d7e9265e4e8e0dc076", "f4a47a8bb587427", "1", .None}, + {.Log, "6d589034f29ceacd34c882059c831a", "4dace7536bf85ac", "2", .None}, + {.Log, "a8f42481d65b630b4e7bf84135214e", "a956fa60dc3aba", "2", .None}, + {.Log, "13ca01b34888158c2079ba0773d6c2", "df75ef7ad973a4", "2", .None}, + {.Log, "36b7ecb6d77cc9feb04bc0116bc370", "a55054e0601fd2e", "1", .None}, + {.Log, "51116a1f2d38e53dba54d3cc644af4", "e80318d395fab8c", "1", .None}, + {.Log, "b7312884cc700d1727619f190c2597", "fca8dd0a164204d", "1", .None}, + {.Log, "afd7b290db7ac38915685748e57609", "30df6155be32c78", "2", .None}, + {.Log, "dc69dd6a13f293817e85f9829a119d", "e8fbc13c6c0ecdc", "2", .None}, + {.Log, "4cd2168cb3bc339f38f8a4c0165234", "e7249f33de7121d", "1", .None}, + {.Log, "7dd63a7ff8368e635967f2f7ce00d0", "ea109319e6b5182", "1", .None}, + {.Log, "667dc16f839662472a1b2749eb440f", "5eeb67b4f768c89", "2", .None}, + {.Log, "65768d1c8bc8b5479e24aa2049e5ca", "edb52b127f93d1c", "1", .None}, + {.Log, "c7da20787846d0c3e12291fdddd7ff", "ea4eb1d8fa7e2cd", "1", .None}, + {.Log, "962b35feb594e6d0f50fc0631fbf38", "1b3543ab4c1789c", "2", .None}, + {.Log, "f1ef187e4609625f5c816fc335c132", "d78d7e8ec9b3a40", "2", .None}, + {.Log, "262e29cedde5e8e019063f7a6c57ef", "2f9bd7d9efe3611", "2", .None}, + {.Log, "88f381f2930f09c0d1ea262e3f8a04", "7f0adfa6eaa9ce4", "2", .None}, + {.Log, "fb6fb7370c668155598f2b2014dab", "35d39a1a9703767", "2", .None}, + {.Log, "5548cf40e313e36b97878e41fce9a1", "61732722b0f7cfd", "2", .None}, + {.Log, "415873e9b7622498cae35e11a07af", "fa76e055cc27872", "1", .None}, + {.Log, "773fdf08655056ce8cee24dffce307", "cf20cc36db9a469", "1", .None}, + {.Log, "33b952cff6b34348f344ffc074d9a0", "2857995ef0c4a60", "2", .None}, + {.Log, "61cad3b75752ed8a24d035f5688121", "3ccc4b3cbbcfb0", "2", .None}, + {.Log, "931a6cad328afca6f94881d700176f", "2b0afe2d2063f3", "2", .None}, + {.Log, "d7f39d01508fb6a7a0442af85f5d60", "9bbeec8551179ff", "2", .None}, + {.Log, "a7f89ee314afe38340e6d226aab5e0", "5fb10ca56f08a34", "2", .None}, + {.Log, "5d23fb88d58d7563523213dd3ab40f", "e8da5bfaf6c4179", "1", .None}, + {.Log, "430958e14a8b4b14ad4b4671bba0ab", "424a7f78d4d532", "2", .None}, + {.Log, "d84aa2bc4c9daddf9b7d5a9f801ac0", "7ce17503c85ab18", "2", .None}, + {.Log, "cc8fd14f948daabedf3354ad74e992", "ecc3e1db35d207d", "1", .None}, + {.Log, "c6d669ba28c06962b6df98ff4a23c0", "1915ef1bff87ea1", "2", .None}, + {.Log, "4b925f549d8a5e8f035441423f3057", "a1dd44bc0019787", "1", .None}, + {.Log, "20f5abbeccbac2cc2d2d6af8920b04", "efffb00f033f760", "1", .None}, + {.Log, "f2ad9665e51666c07c0370ee08a994", "4d8fb606233d34d", "2", .None}, + {.Log, "fc1679174e11bf9da2f51602465785", "25ab2a6e7fc6871", "2", .None}, + {.Log, "b169ce1f73c21c9953d2aa7eafb97", "918e4351aa87298", "1", .None}, + {.Log, "fc85619aece0b0444418992a09bb72", "913cd6c05ee588a", "2", .None}, + {.Log, "e6512b5c8d420b7fc6caf40af46d0b", "7048e4bec5550e5", "2", .None}, + {.Log, "f370bdbb7d96201924d5ccdf9de34d", "35c2260d0559ee3", "2", .None}, + {.Log, "301b8db1b7cf196e74bcb16021b2a5", "d7a68e9a0550d36", "1", .None}, + {.Pow, "2206d8f0b603917a901508864ee863", "1", "2206d8f0b603917a901508864ee863", .None}, + {.Pow, "-2c3bf60e93e9d4468a23539d58c617", "a", "65e49a5ebdbd374353556071d156a6ccff7c69a47d326c558b233cc991296f220ed6ff668917096e3cf03b71015f35aa60954b7ff6e499e61318f996a6256da4e60438a37c81d4a60408cd7ca914fb10ec0a027400d57eb9809d61daa8c9668ac85e6ad751183bd201ecc3988d00f409967eb3a4bcfcf76cb1863084e8dc67d19cb9f8a6b47bf4a20fae51d1628e7470831851", .None}, + {.Pow, "-9010aac0d5e163bf2fe4b8a007ccb2", "8", "293386a5eba6b3f9fcbbc0e98719e5975ba29039ad1eaf7ca8ab6fef603135f457c02706d316b20c66ac0d2ffc69ad623cb635062cad7cb4e244a562c1f2cbbf16cbf90eb246a6973b176053467967138b11af8b18eef9d563f052147684fff3501c61de4790786657ce640fd9b57272f5b6df9bab1c100", .None}, + {.Pow, "-376b2a21b6cb1302ab29c93923e39a", "3", "-298dae345418fdec0ef6d448afa4b4b830738b69c55edb37230b19bdc889c21f7a50cfe362afa1fa2faa9fea8", .None}, + {.Pow, "-58fff78e9dc0d43decf4a4a562796e", "a", "1b0ba1e90052b14ae4a16498fd08f086e9b4133c00e75aef862524eec4f8add7fc66fa9dcd062f17473056f8a96a882dea48f78671a74efc6e87beb17a920e9639ab1e5efb101d0431039b42b8210ac963298edca91a1969309799cf6b58e8bfc55ce31259504dd826d956671bcfb87551c06308d5b91acc57a851b7741820fd45f39e6f6c9d85e7eead130848a68fe55d2c04400", .None}, + {.Pow, "dd9b4a1aa8530eddaa6b685cbd64e3", "7", "5d3f7607988628638f4ed0e4e437c28a0dfaf3d6ba1da0cf78f3c84826bcb22a820149ad8d1aa6bc0124e3794fd1ded9c74c265b40d9ea42e748b40afdec88584eb996326ba7b067d37263ab916b8a62a7857c276ee8d94aa5e603219233342bd6885d0648f47c51ab", .None}, + {.Pow, "1236df56639b3dc67290c8d2a554e6", "6", "22d3008e8477eae31d0790fe7471b54932dd52b9c9fadb39d82f737ff9c0696ff50614ad025cb8ecd4bdf78fefd52528c9159422ea68af619e79c43d64d0f286a505ebd73a77d23ce3a94d1a25c386730167a394570ee40", .None}, + {.Pow, "8f8b001c39bf3be1d04947e2432c85", "6", "7f4b8c8699c34fec566020aa7c2d47a6fdd6ee21d7bfcb20a876056efc55155bbd8fc0202c3a7965027d2b7357abe7157b78ddcc73beb06a7f60c903c73e65f3b28e5fcb3af4006b4699625be23b0f1f10a0047ca321c614409", .None}, + {.Pow, "-46845f7ca064ad057fcf7732d01099", "4", "1794f2818483683547a1cffcd3ebcf49e7bae2c575870ad35583d90414b5689d1ceb7b2ce424be6f84d3b2506ce7c29590c9329ccb02b42b58bc7e1", .None}, + {.Pow, "f8647d9e3b234f2e5f56a1551b1288", "7", "cf44573b281256247f9d7dfc3c04dd47e9937f3a807d1e8ad1e02b478c774b369e7cd00dbe7562f3ae8005916f98c1ceed447f3bb71162c95176fa6b8426df15ff9bc2eb578f3c15af21d1e82f80b1ff44fe8fd466b1c44b52d23e66b938a6186fdbeecd4da6200000", .None}, + {.Pow, "-f611795a362c75b728447f9fa93d41", "3", "-e358838806a59a0582c1948476e64e7f1d08456dbc36eb2a9290594ab0158ea60749c544c7a3c08050eda667c1", .None}, + {.Pow, "6f6024aee0cd108386cf7d48da671c", "8", "541dbc3ebefc44b68c2566da7f213e20e0ca76fd89cd838b36f10fcc825fabf429390f7cdf29b1d426cecb57e061bb0b6b32d8abac4f1c1bb0e6f2f7d1cb2901f37d87175e78211e25b769e884b3779168c0165d8d7bbfbf109004ed127ebe1cca88c793e086587e0056f847e644dabe7f348c78c10000", .None}, + {.Pow, "-d0146255ec11de294f912267578be8", "4", "6fbcc26915f227d7407a7eff28f14cff25cb8d8594f61b2d562e082dd04e6b112d9e46bed7c5428c7a388a112136516fbfc03144f06d126bb9e51000", .None}, + {.Pow, "-f3130333e8f3e7a136c9df0812a99", "7", "-b220dd46ba721200e8e5e4e0ed3cfdf46720cc972857739d240f14fbde3dff1623c35acf5258919ba45bf04c0ccc8c9e83db5763cb980906a5bc6e4709a7b252fea4472e997baa75b3adf6f81ae1ae3f0a3b7b60fbcce8eadfd0db6d2405428d92897d1a369", .None}, + {.Pow, "-ae837330860700867afc3cb6abc00a", "3", "-5118efccb24ee7f4f829ab443a9970f2c2fd71991cae3b276b9a54bf009f626678cef829370e1389f3f14503e8", .None}, + {.Pow, "-62141e1e58e9836ebe5bac82acb876", "1", "-62141e1e58e9836ebe5bac82acb876", .None}, + {.Pow, "-77a7487373ca48384538cc78f75f69", "6", "2ab44c423fb02feeabef6db77734746c2009edc12f2f1028fad2d2cef5a7e4ddc82a52771aeb4ac9b4dbe21f6b7a38dfdaff24edb8f93bd536451c3532a2406a44a4506baff81f065b7e33f7472f29c0d6de8ca5f0d6c3ebe31", .None}, + {.Pow, "e5c8ec0a5137d13d79acb62de3842c", "8", "6bde2151a0cdce92d900015fa999ee54bdee4706d825a7ce2c809da506071d7eb850a6c0229b4bc240a703af9896045675c553673c1569e3824ab94e99447aa5d8a689a4c338c79ea39b2a7274463d85720a42bab71e6020ea61cdfd49e29ec0b44d98b555394d8dae15c4e48dc038744a0744a5f3610000", .None}, + {.Pow, "db0af5a085a0081dcf915a606b6374", "9", "3eed787efa26e3206e2e5d36d0b09577e77b5b906587d312418308ae9cad6ec1d966be667b395394b9634295a66131ccff9cf7a37d709082c526d66b64d9bb1562b4282d1464c240d70a31bf8d844a804e5a30e2b542d2ad4eb0bbe7527b753475c6c8b78b28132f1a19634c2437d7cfc46eb20ea377093fd883615f89a85d1d8d9e63bbf40000", .None}, + {.Pow, "-e4bb27ca5fc85817db7691d7ccb133", "3", "-b6990ab819c30774f9a2eb9e8fa11786a25d8e41a9e96efa6f79cb8d2159263db289b066e6950ea36d3912112b", .None}, + {.Pow, "be711e83e60b31038b3772e6f7fdd5", "3", "6964561a72ec69c3e9e83310aa4e12f90c773c193525f48df184c95f64357484c02b01cc1cf6c4b39e7577736d", .None}, + {.Pow, "-111e68b34d1b751c9afdf34dbb63fd", "6", "18005fecb2070ecf54e2e9bf32d548a8582d14e2d768d01d2d97a8512b0cad257edaedca81a37ef53a4edd241866eee264890a88ae4136a86453e70c9182416113f1beb43ccb87437b0fbc914678c80dd6249e897b07ad9", .None}, + {.Pow, "-695f82a5b2ffd43d03768ef61c0db1", "1", "-695f82a5b2ffd43d03768ef61c0db1", .None}, + {.Pow, "a05ee20c182fc37a3bdca4725ee04a", "8", "61262f65d164f16243dba86b94cc02ee59bb142962d8163d9f30f04e1ab9148d0bbc945ab3a64f914bf4954ef9f32b84ec6c1c927b64e0ddd1c14c45151fbbfc1c14ac7a345e37207d93c7952208f10e96b0c29f869f2f3c91ae0e01fcaace2de3a768f13948f22013d908fe130fe7247e61294dc92e100", .None}, + {.Pow, "89c65434b7cf7530bbb2611e6f9d9f", "3", "27e7b670283365609dc9138e84fff7215632abbc05913761bf1c25bb3cdc852693367b6eba6310579900006cdf", .None}, + {.Pow, "-6e1f3a892459a3cb311c56099898b5", "2", "2f5eda1d15d64468d4bcf5fceeab1fa9e2f94eb2ee1b5794474e6c076ff9", .None}, + {.Pow, "72a91be7bfc9c471e4e6ce8be767aa", "8", "6a237b1fcaa911ff5e8b43cd9ec5314a78deb453f047a1355a0d359480a16ee154e4fadc96627dc35751def8aac81f4c12f9c784f0565a8f8d28c8059ca08d4d8532ed2d9031045249718d74bb7d4bbb6cc7f13260108034952fafa284816ffd313dbc710f90c5719573823e12def7b73f614ec9ae6100", .None}, + {.Pow, "-393af93ec422b97f10a8b98c9c28a1", "6", "82e4d373338245ae81ba782992e815aa7e620c4dfe955a58c3be12ae619dc6329e1d236a457631ee36dfd1b6a1234e2ec6b0fa09f98b2e9bf28ec2ccac0454dbc76ae56d31fbad900677dcac6f452d0ad5d6ea50d9daecfc1", .None}, + {.Pow, "-71b4617c57af5fc9cfec9d90353a32", "a", "139509f0699fc2d86574dac9b466029791fe81a1f1c4882ecfb6cf4ed0dd6cebf8e1f0ee8b4df51a265648a287059a1147536e78623eaefbc81d40b23728c40e9d73ec128125aed0428b59ad2367a720ca5aed2bc90a80479251b2f8699de3ce497aa5768cc9b6f692146128b909b455e9747793e7f2b876feda234a5f8d79995deed328e8b2a9061abe571b724856033002a0c400", .None}, + {.Pow, "ee09d9c15973bca3fe7a31841443ba", "a", "7baefdc80ccc1d14d32d2ace03209b691546e4514c270e9ed6646a4be497342ba5ed4bb19a84d0fa70bbe1825dad309b400155d859747e30d44d4ec514e89c05f9a51dfa9b925dd59117574d7a7e31d041627ac6a109471e37a1f1f3666d46a220b6338793c8057d63b802295a965a3433cfc5da00ecb36b8a3274598050c278f2327a3cecb4650fe31e6eea59bd2cfddca2d8e9a400", .None}, + {.Pow, "-ec176c07681a36886be6f9077a3b78", "2", "d9bb31523edb494e4d3ca4254874f4f3594859a801ac652b390d4c308840", .None}, + {.Pow, "ffae3c1232dddfd78853db0e3c7586", "3", "ff0b0286f8915a41195006180fa77e1ba8dd5850334cea38393ff9cd236b18137ce07dbf68b13e6d870ea212d8", .None}, + {.Pow, "59efddfa5fefc15055cca67c357bb9", "3", "b19adb502a6353522466c7f920f6ea07c22cd798aae0372d9c3c615548282b8b1917873daf7a5874c1a36bde9", .None}, + {.Pow, "-69d68656c4c7c4b72bf7f9966f0415", "a", "98f932466803d334bec8bd08ab61c1a109cb2d5401fe40c6206bed871556ca1a13b4c977c146f8f70c879c972ff56c6840ac59833936d022f000fe7c32d0fc5558de4e57a9d8c121fb9a1e5200f500478eb4e1c174839b8f5937ff5d2dd21a5c7ebb7709d84783539632d9ec01ffd69d9870d1d18deccffbd32aa37187c55340ec4cb73f6c61ddbab8bfcfab96c0911c0eefdb719", .None}, + {.Pow, "33dd262c3d0d6d7e8e7e8da9600247", "9", "9a55b893daaf57d89651c26fe00bc0bc6301977523c5be78a48c86b9f26e2688e8ad9227da10633032e4f2e7c7e600065df0f3eb4e5fe982c99e797aa6a8a719c3044f7eed08c301aa9826cc585981c10b0fab27ab0b6b53919aadd5952b317e306b7326b612c2418434d3facfc969ba0d6d2e8a7535600aae17979bc7d36f1b6bbb44387", .None}, + {.Pow, "2e13bd778ab3cd0281b96a72362811", "9", "35377430096f6272ca59e68bac3fa972f1d3133cdf5d09b9a2d83bc3c41e09070f877acb5e2eb38cccaeff6aa451d3972584056dd67df9584858d8dc44874a322ae8df94e6ce9b2783fe1b3da7a2aa7ba52ffa20a9e984d11855ab1643985474068631de4292eae426ef339725a73f6aa02517787d8dc5d8af35fbf05d816eecd105ecc91", .None}, + {.Pow, "6efaafe68d89121f60e367f2c1d81c", "4", "90aa8e47b3760573607f2ab1fd7098ae39116f1afee38e45c449ee1816cec5f2958aa14f706d7f6a0c454e7edf3d05d3ce06b9940d8c4d890716100", .None}, + {.Pow, "a5bab2f361900861a99f5711972f9c", "9", "51cec037dda04d236c67a7382c0d283c9b2f9ed2947faf7e59c549f8e054da5010494c87324be0dec5d98fc28bc5d28c2953e48577047502da5fc0f4778a71c6fa4c1462edfda2f8a6cd3eb3def8ee97c568ec241410d83c5cd840f330ed851ae764597cf14af9c2ca59409e062efbdadd588e64c19217578d4da6d024235b9daa771089c0000", .None}, + {.Pow, "df43ef5af5547b7297ce47cfa8dabc", "4", "941a84ac9f13831f1673b8830a195a1201c38852e643d6a123f83cfd42b0b3a03593aaf031fd3e630bc3206646d37a0b829afac84e8135ce0bbb4100", .None}, + {.Pow, "-a571054669f962822c9da7a21f3a9b", "4", "2ca75b3ef918c4ba5046994f5f381e3ff96b51d68e8a176cae4d9e94954df096fc470ae87fe04afa13e9028503ab81ac5a91f52b20ee08f7561d19f1", .None}, + {.Pow, "ae4af940538070083cdaa6587a0e3c", "3", "50ca4d35ab2412f8e918eb3c3f33a7df5683b1af7d464bf19015131b3907f6db72e342d25dfefab929bf01ebc0", .None}, + {.Pow, "8ad17a592b8bb615b455c1890024eb", "7", "3877f30b83eae82ccdbb328c54822e9259378cf6727b585ae2b8d19f2057158d71623e8d55c4b5d8cdc7eed7d77aaadc0024e303310087ef0596a90d9996e8ff22bc30f7b4ccf9da8f856705ec69b73c9410c01b479dd3d4b94fa897820189256e21c49aec39d4ce3", .None}, + {.Pow, "-702a4bc625ac4a43c1cffdcaf51550", "9", "-26ff8760d6d71efe131a5f9ee7f82b7fc37d83287b3aec2bd351d07b4e2515644f771388e99ce3d17109d951d92e21544f7cdbdc7cedc3c2d7483ad698aca7dd82371481850879b275a429e3bbbd4b44ab5dcf44485bfaf3c7eca910acfe13fed7ab29ce8f87cff62b24110283ccce7bc365428e32968319e2f2b674f673b4d0335000000000", .None}, + {.Pow, "-59b0c77fdc41adcbeca5bf17907129", "6", "793472bec69061f3e138a719163d0a7179b15899c49bbe361768a818ed94a25f374b65b3c4cfe41cefb6b79c5bfdbb1ed950913e55a17ad480a7ec34ef9b06e02a6c82750accaec78675a7a10b864576ad61e4ad330d232cb1", .None}, + {.Pow, "-3d81665d47265ee471d69b7404eadb", "2", "ec6ec30c6d87493d9c04b72b535acaa83601c9cefdf5884fe20a64d1759", .None}, + {.Pow, "dc618027bf202c606ecc3a469320c8", "7", "59b266dc2017359869734db0a391184ca82069ae6c5fe84b6ba4cd348cd41dba2f8fde61f65638810488a050a3d50e3168bbe1ea53d2cf3e7221fc3a2435a7038c99e94aeee6dc1d2cadf58268e7c5ce0dfb1deadaf58addf485cc7dfa2d93f83ae9213df7bd200000", .None}, + {.Pow, "ab4bcf3f3aca33a12c63c8569a9f37", "2", "729e5d518f5de4248e419e52d948d6d9d5122c7b0d16eef1904ce5315dd1", .None}, + {.Pow, "-6d653d754112620b638d39d9e5c4bf", "1", "-6d653d754112620b638d39d9e5c4bf", .None}, + {.Pow, "-5d249eb9b0b3db88c4e45823d6151b", "9", "-7529fbf1092e45050d758571b1fbb11dd8ad9df727f927bb3553cab02fe30d76558721116112edcf1ed0e8b48be8a9ea412d8e9f4275c0f2385b1ca2e0e6b958964260d629ab1bb6b456c46d67b5cc0d4db4bd40c0d47943d4d6e9a0011ef7ea9970c7dc93a7aed9554b51076de5cc936b521a5f17dc2e65332702e0a9b23b3631bce179cbb", .None}, + {.Pow, "727859eb61909bfbb5163978b8b4dc", "9", "2ed52e5e5f4883f6544c8981e3147fdbea8ceb4ef96c4f47b19da1793aae499b9f0556684294f967ee8b20c6ddbb4b026bcb079db8127a63fe52dae53542aded342f50337c105f724b1c1919670333ae3e7de5d6628b1e5384c88ddea785bf8629895246fb6bcc475235be00e4feade974309acacdb8336d91d426f141cfe3d9acd957dc0000", .None}, + {.Pow, "17525ca439abdbca41673ca4de3a12", "7", "dfab26990b2262c724d33f3b849129df268cb9486912ed76237888e52bfad0e565aec44dfeab9b24dd7342d619349b5ddc399c5d1d468641f81526903f37a0f56a81c3fd35d2962546064ad09a555d7092242374cbaff399506ad40eb3f37c47ed08778b3c80", .None}, + {.Pow, "4e7bf97137853808c794051bb09458", "3", "76075fa58bd3590a0def8b99a3b3a86e4cdb6e66076d59c9be1507401fed64c0495c1c167bced15fc55016600", .None}, + {.Pow, "-7892bc6a187948e73c48bddb12a2ec", "6", "2cb649162559056c315b233092e749dbfb45e83bd59fe2bb9428308575c68cf282eae353d4a11c15a0367ae6a436c902a3f619dc0e4aee169f5daf52356eb3febd91489d6aac92422089201d54836f8390860215d76e0e89000", .None}, + {.Pow, "-f4a25a887646314f0c1ad399194d0c", "8", "b203f0087b28bb6ce79fbf5e440632afe549c6d7df354b8f6d7b3c240527154284badb422a8554e944d0ad9003438cc556eb7db957c19467631d4b482cdef7e4a6b1c18b2c580495d694bd8e2ee411a4011831de5dc27d04d8af4096679921f143390438c30f17d03db874175a1d3c88686cf57b77a10000", .None}, + {.Pow, "-af2c93264c3887dc4e6e152f32b0d3", "3", "-52059c3a1ce005846b5ef28e72bbd4fa4b5d8d75d4d7888b55b770ea041ba705b56e378b7242dcf82593c5e70b", .None}, + {.Pow, "1c9e31b496e9ad5b091e89f1b57faa", "8", "68bf9dab778450aa17c7512e93a194c9aa450e5ac8e2a7e92b486fb8657b5118a53730e88dd07a52f2f33b001386b5227aa55914db7130d820ae94a7a161d7169d2c5eba88fa5bbae06eb2f1a7e2f886f3fd22e5f4190da8f5bd1df355844ff3dd73e1a690e1dbdbc725efc401605a481ec48e6100", .None}, + {.Pow, "14f4267ddda71579c73a53a254ea", "5", "3da278a0f4dacf09d0bee2cff8d21c60e4980aa747e85a7fe5cc997bc9892ab76efb4956c05d2fdc33615c0d2dadc2ae8ed26dd7164fa38cbf8ecbad6fec61ed5b06eca0", .None}, + {.Pow, "1a26f1a2c23166df604cddeb652ff7", "1", "1a26f1a2c23166df604cddeb652ff7", .None}, + {.Pow, "fbcd1127908cfa432f2d658b7e5ba6", "6", "e7d12853c1e5ee98e3ee6f92c06a2afcfd436ad0039ecc3463cd806b4256119e46c100552bf2ee755f49563e7c1dc0b3377b8b8995184031f4df143febcd5c75b8678b803694f6bd9dba9f3eb6d703d74e78413ba58b66a91e40", .None}, + {.Pow, "98d9786272c2e66a717338decfec3a", "3", "367d49c043d9278d24abc2399490595f354f0636cc380eb903f3e17161cac297ab33894d593325e91a7c8e8a28", .None}, + {.Pow, "df918e587ba95c01fe95ab17291241", "1", "df918e587ba95c01fe95ab17291241", .None}, + {.Pow, "-410f52a08ab5d4a7745672f4dbe9c6", "1", "-410f52a08ab5d4a7745672f4dbe9c6", .None}, + {.Pow, "-fcf2eff9d40fda99c7c971a43fca7d", "a", "e3133a93e8fe1b893b5fdb35c14199889402872dfc7afa07e17c962c3d1028bb2e18f4d0c70207f440494effe828627372e04dc69316dd6e012f4aff4affee2de91b5f54b85a4e4e532fbe24f98c79ce20e51ec3fd4900eeccfece3ba27ed8b4bd4a856e9f6b97aa56791f25fce0ffb1a24524d6463b77abcb3b27e2daa3c6bc064f885d8da5044ada18420c5d166a2305c23b588ba9", .None}, + {.Pow, "9cd608e91590eb2b705ce0db353aca", "4", "24102c2bccb86e8084a211f6d56c8156cf9331658a227634c47db948ab01778d6fd59ee002170cb550deb5cb3f326923f34ae33ecb5c05e1e22f9f10", .None}, + {.Pow, "a8d0f16543e8abf6268dc6e44da213", "1", "a8d0f16543e8abf6268dc6e44da213", .None}, + {.Pow, "caf4f59c21d7ea2dc8dcebf04fa87a", "8", "27f3fd83c46a7c6f4b40b8e30c79dc8e9699332c1bd4e3a7bcacc749211ca3ad3b376a2a27b892cd5bf7f39fe03c1d7a865cb850f248ed0db859006251bfb7589f47f8a1c01e265e40a59a3bfa18fb43ffafd3fe201b603d63c0936610ca173cf7520240e52ce9fa62f4d3f4f83ea5bf88a5ae71e1e3a100", .None}, + {.Pow, "e19dfce60912bf65fcb94ac99ee7d7", "a", "485ed5255bebf6fc9d3d4cf8639d2d5377889590ae6a0806389b0fe095d5aca848e65237a308dd1e0c1afc210fa2c8106528f729a7b30467fac10b8004b848065040389f5a0c7c5aa8af976dc992f8acbf6b1b7011b0a5946c22f877ca8783397cf025a8b0be9dbc755d94120c46cfb9afb9cfbe8664e5ec95832cb6aee17c2d4e057872d543f731b2557de328a9e644b55148fbdad1", .None}, + {.Pow, "-b031e070844b907d1f5641a7275a67", "a", "61b30c54ebe9086ec96eee44154c9a5aa78ca8ca1842f7b35f0e3361a1dfdad4712c44d539e6451a976894a54b19cbe08ffaa8f0a29110e906dad939b8be7e64aef4cd99c0b422439424a37d443085861d25e3cd0718f95bc4bff91e02d495fbf4a85ff38753684ca944f9dea95fae5c9e140a24be095a4bb022aadd58f9fd776edcb55487a8cc4fde18a2628826a1423c6d3fdf531", .None}, + {.Pow, "3025d0ff86d0226b6d0aeef44347af", "7", "8ba8cfea60977a0cdddbda28bec3e924e114954a7722703a52ef1f1460a15ac6d344cc688a670eff60aeaea3f443718dae55254195189e87382a9059abc5bbaf73bfd5d443160caf56d29c9ab539d0cfcab08cd5b2b644eb128c11a932a063299dd99ff3d978cf", .None}, + {.Pow, "-d815dca658f229e7decd656b5724b", "2", "b664e636a7919369d9016a6069c4c370200084af85d0b1c6c93514e1f9", .None}, + {.Pow, "5583d2c3589576955bada9fb8c0578", "7", "1e6a5996c4f78c0e00d2e9cb89339920b3c520ab1dc28d9b9a2f9c2bd7f142d01e69933ff7265377288932ffadfa87f0c0b08662ff9306acab1cb949dbf09c8a65ac714f43738bc7b9a10689ea19a276a59c7cb33a8da6429e85758acab77087ab51cba4f9e00000", .None}, + {.Pow, "b876d85d6fd6e1a31c09c19a541962", "a", "9a8dff059172840f790246aa72061cc24ccf7f8c855453f4d4e7bf2a7f38e827076c32b112dc58cea48a2e4be00cdc5914993a5aa8261ee68103eecd1a8ffca53d4910a99dd49b5fbf8607cd5113c4e0c89c8606b2bfad1051439ca4cc3c839ac55f6d20c6efb48d6f2f9d7d87101cb830b9e76d023404f3b7ac77a56a6d3ad345aeaecf14a98950dc37eb399f671069a1c030f8400", .None}, + {.Pow, "-be578c7b3bc1024abd58f4b7b0934d", "6", "2b408d5ace1c333aefef31da14dbcc907c66c9d78a87ec3f1a3cc23ccf147aad828b9b8887153a653eff194132377a00f4cf29fa40c3086e7f4e8c4fc616253b0c1c34f4bcd69dedf1c09dfdc077370862355c176b56c7d30c39", .None}, + {.Pow, "5dbbf26d0e02a47165181718f501f9", "1", "5dbbf26d0e02a47165181718f501f9", .None}, + {.Pow, "-7735c196a06f2dc15f6ae8429c535f", "6", "29c36ee3913299c47bff1bf4793e49478be4bd81be857d558f0cf498ed9bbce6fa9e921a9cc275f7c39183fa52b40d430dea4df5abf9941d783bb30edc7eab6d2eca005687bbb619b6ff7ce1e6ec35a038cef9b0100f4b6e7c1", .None}, + {.Pow, "-8954f7a7eed3c106dabcdadbf837e5", "4", "153393334cfefca36abb5870b8df47d1fdf673b66389ba57220afeb4a5d3baeadaa56a0346e7b254df723dcd510ac4b36df0afa76ad7892156a17bf1", .None}, + {.Pow, "9b6a02e23c60f65ef176cde6f88e9d", "1", "9b6a02e23c60f65ef176cde6f88e9d", .None}, + {.Pow, "c5a882ac2a84add1595dfe06bc9ca5", "2", "989cc808be1b50a04031f233baa8726b5ae7febd12e2bcfe1bba2e318259", .None}, + {.Pow, "-32b5f8157905fea81641b5d08b9c9d", "1", "-32b5f8157905fea81641b5d08b9c9d", .None}, + {.Pow, "6d3f0cd7a5c65b68238865f2822223", "3", "13e5135aba88d5f1932619f6d4d1081de97823c39a12162e8804b7b0aee13e89128f816f25396b5c897c42bd7b", .None}, + {.Pow, "-4c18c3954aa272dc798a1238283e20", "2", "169eb685e5bb396be358abff9dbdf0bb1aa53d2dbb290f34de0179138400", .None}, + {.Pow, "-e347a70c585cdf7e48623ca3cd1239", "7", "-6f4c490497c80459cc4ba3e0ea7205eabd78e948b79818275cab00f5c311f638a063f6b65f942be54f47d56f27c7d663ee86777a4c0cdebee2c0e44cdc078660434e16b792a38acfd4def7535ef7cb2c80d1f2724b15e8d3fca1bda1feda41358ef5c14c029ebddac9", .None}, + {.Pow, "-cee64ed1f76e89cb3e76b29e1ede2d", "7", "-39a9161c6e6f9e7e3e45b365e3bfdba363e852bf21745e53e0be358ba0cc54f86cee0cfe1f882e983e6de66a4e7bf94bf98ecb316b45c2a6f661f1f8bde1b7eeb3376e8c97674cf9fa37915bc435310e443d3403086209a0eba3b3462e0497f1a30c5ae3f5b563df45", .None}, + {.Pow, "fda45f76db952b29c14fdcc0c2951b", "3", "f8fdbf318a7b22b5cd2f359de829db9266da323900989b7d39fadb37372d549b9c96c9f50787e0f545efd833e3", .None}, + {.Pow, "69e5bd72f3d269a2de3d246f4775ef", "7", "87d4a7b2beae31a2eb011505cce2f2b9e5b0b04584e6cdb1f77b765d4a925a69726ef9d663b34435ffd018702979e2394f142e516dd46e0f93378f07a0e5f75add218248fbef8cf8eec63c773a9d096e1cd00cade16528d9d5e08f46d67a672309816b8a6186b48f", .None}, + {.Pow, "-4e65e48942655032232741971297c8", "9", "-18d78b360935e7022e40e166748805faf6f054c750d38bf505712aba5e2e1fe686397548136937fa777a871da01744fee6d7585fd9287789d9c65c46435ecb0d6c5f386a03478dc8158ff9938add2736a7abe567e168281a9cdca9900fc28f8a23d0f7713ef1eac672a00c064aae2e2f064902d89edffc25c05015af073b0679b5dc8000000", .None}, + {.Pow, "7d7bddc5f64ad3514bc53cc2b48904", "5", "73e77c9ed8ec567caeeee003cb1d6d010f9df73bf7868e885eae5dc369af29ad69c74f8014b530a4c81cf78646e6b500da23be1b890c5d8258ec1325194db7448320777a774f4712d0400", .None}, + {.Pow, "-4af665b61c5943771348bcdcca165d", "a", "4dc2be4dc8ea54dadb8c528f01cc541bcd6719e623176193a7266d5920c33bdcf4ed0c407df6c1f0489b97dbe37675db07b8a4da978f7e38ec490b5d9997a2eace307590b3931fb49a4306bb26d4f40cf7c2b15ad5c1f420369d08943ab8ab6ad78eb568f9d3fb85762fae5a278a0227045019e608b5dbbfdeccea4f0962fbeac97803bb5c7fb47fbc0b9edb1545aaa1f79ed369", .None}, + {.Pow, "-399544502d77cca458b6a62e311b5c", "6", "87cf27724bb990d5d6ef8d314148c102c659aadd2f16e18354e1d380d54f54a1022fee8696a8ce6d6be3f98a9a13fb4f20de58db6c5c06b3404d75d7c864fdcc0968492ff1986ebf43fbde26b5dafdb7e4bad6dd405cb1000", .None}, + {.Pow, "-86e78ea52f96dfb87ace8bb5d05f83", "9", "-cd615aa9e3caf100df2529c91951a80b970cdac7da8e450d826af49c3b0bd3b85f3cd3c8fc3eb8cc310d17e270b1625a2396cd0b30192c9a25ea224dc4d6436d5001e167fbad9c385173fb702775769a8c9d8011e68328db8402a0bee960ba0ec31d4ac241cd4c5ccbe6378b0aaae989e77df977ac00e9b80c4a9ed7fcc9f292c35d7e3f5863", .None}, + {.Pow, "40a498dcb7507d15c7fa3edbf8e623", "7", "44a37e043e25e99101eb4134828b162239775d0c4ff3a0681c6f479cffaec14343ffd69f36d07d47256b36899bd5f1c2c71529b355421783c022edc257ac9a57cd6504123b2ba81a38f9a30b5056f5b1278d9d0f77b4a6fc3fc17e9915a4b8bb881d8cb4dfefc6b", .None}, + {.Pow, "-19379814ba1e94f347d02606d86f3f", "a", "5e926fcad1cc9fc2493d24ccbbf0582d760bba6268deedf5c5eb907a569506e3ff0ae20cc0934e0cd8d75e5f6de082a68089fbfcd499983486db2d3b0b3fd91edbb0374dc784aea10d1572f8363f30b98c81b11b2042880390bc73243694d08100b5e7549902f19d870b9a15ff3320e9a048985a8d58ffb52a6b81bbcfece5d75a3e96cb78fdf67b72c61fcd6f1653bcf781", .None}, + {.Pow, "-c25cb5ced1b8937e20a742a2855ea9", "1", "-c25cb5ced1b8937e20a742a2855ea9", .None}, + {.Pow, "-8a112a419a4ebe67628c46a89d11ea", "7", "-365d27f57e456d1dd5de22c9b361b4a675bcc004fcb5ca40f2010535af1946111a93f729cfbfc28d9e9cbcb81dcad5ba5d74901c7d2f11ed9f973133ba0a0c2a373e538f93c8db24cff771404891daf7e79dd72865b74220fba2421b8d1d330f000fb5cd0b99e9e80", .None}, + {.Pow, "7188150a4277a37d641d1f28a3283b", "1", "7188150a4277a37d641d1f28a3283b", .None}, + {.Pow, "-fbc110bac3fb830672a31ef62f7794", "8", "dff0e1d70627062e382b40fe165c80319be8452e3aa0a97e734749979c3661bee734a73762b641a984e5612aebaebfa0ed79c99cf5471e5fa6fadb37d4342ab95391a0228fdb20b691262b86d05ac381164b3e7c884b0538cc0b95e851a9def52f6b97e75075616662b89262d498bd73066050cae8e10000", .None}, + {.Pow, "ff4f128d55f28839be6e30a62c1392", "6", "fbe192e781f7a831cf000cb8f58878d62f167638ed75e0b4149e8eeffb45a8955c7e979720a1234ecfd017327c5d56a2c3217258144b74c6b0ad15b1774f16103a8c9f68e1596cee6c43cdb84710f068b5ea69644ba4b26a9c40", .None}, + {.Pow, "-8459d6cbd22cde71b9bce26a8ef292", "4", "1249f6e3c0c184b91d9e7acfa9face3458bb60dfaefa95d230f5ddad28c31f0227bf45ef3eef81a89e1ace2240f6b74bd45930cebadcfb1927096a10", .None}, + {.Pow, "-539a899c9ca8c21da5c0be7b6fbf9d", "5", "-f372befc775f46e9292833fa7c9626abd94458352e8b19b2c6a136d76186e2316b8a5dadd5881bf13c96a88423979eb319f4fe509fa8765f06e0e3a9a81627c00d4605148c2298552f2d", .None}, + {.Pow, "-9cb02dbdd6dfb2b9ab6486696bb60e", "7", "-83ce425a0184b2f64af523584f72c28fb8ff38ebeaef3f4a4900f0b61a164ef852f16ddca0ff074561e2ec0472fd2e94cf1bc149904421bf1cdf3f6ccfae772e954a448ac71bfb193f7624d55d6002f9060e72e8c32f4857a3f8b76ef71e760a631899f2776eefb80", .None}, + {.Sqrt, "62c2ab8db7b6932e55157d636aa211", "0", "9f0158303abb829", .None}, + {.Sqrt, "ee58ebb144e2c98f9f84e6af04745d", "0", "f7041ac0fefe786", .None}, + {.Sqrt, "41499cdf6a2d0250e9be5098546039", "0", "8147f8b22181cbd", .None}, + {.Sqrt, "40586bb3074ece191cfe4fcc0949d2", "0", "80584d3dd57dc64", .None}, + {.Sqrt, "f5afbe46a94c3385a2d07487edf4bb", "0", "faca4d029482b42", .None}, + {.Sqrt, "23ebce49ddcf3bd9fa8aa854c2a6cf", "0", "5fe50f4572101c0", .None}, + {.Sqrt, "a34da9d49b5191bb27ccccabb00ac0", "0", "cc76de84373a66c", .None}, + {.Sqrt, "ac0ae5c69f98410cd0289237d576bb", "0", "d1dd2ef54a64e47", .None}, + {.Sqrt, "d7cabeba065c7ec9f1c0f81e349ea0", "0", "eb09aa23328db66", .None}, + {.Sqrt, "6851a61a6922364578d8a428feb8cb", "0", "a36b2b60af162ab", .None}, + {.Sqrt, "d9676eb119b4c88ea78412589b8561", "0", "ebe9fe43b073095", .None}, + {.Sqrt, "29bc2958436cceb9ed758169768502", "0", "675d3d5f361a149", .None}, + {.Sqrt, "9b217456b160770a6bac21cc9910d4", "0", "c74847fec9d9277", .None}, + {.Sqrt, "2e6cb6899949b0af960dd65a7069fe", "0", "6d045c23ec09f3e", .None}, + {.Sqrt, "c8989b28efd9aefa6f26fea016ac7e", "0", "e29c7348a08580d", .None}, + {.Sqrt, "972f45ef7e78ce4b9c2a21b7927f2b", "0", "c4bb41ef16557b4", .None}, + {.Sqrt, "c949455b0af94d02e3c35ea9c90e68", "0", "e300271ba4167af", .None}, + {.Sqrt, "bd32e399983566a1a3a0a8a6b06e5f", "0", "dc144ba190a6d3b", .None}, + {.Sqrt, "676183e81b208998c701fbe72944ce", "0", "a2aea818a09c586", .None}, + {.Sqrt, "5307d5ce04b68fd9c1cfcac7335a5d", "0", "91cb3729eb1e93d", .None}, + {.Sqrt, "294a1889547731da1971d2b7f17ba6", "0", "66cf9bd2c73759c", .None}, + {.Sqrt, "7e5762fd15f2d911e06c086d6b8379", "0", "b3d7b95a43503b7", .None}, + {.Sqrt, "f679c13f0d059ae3ee1e6ff77d38d7", "0", "fb31527b9990866", .None}, + {.Sqrt, "94c6d3318e67bdd71fcfa3e199be95", "0", "c32890e9a64ed29", .None}, + {.Sqrt, "f5f93d9b086786181986696a367993", "0", "faefcd4cd42069d", .None}, + {.Sqrt, "b34102fbd4de585558a6327fcd7829", "0", "d6379adc111ffce", .None}, + {.Sqrt, "95fa3583fb180e53946f40ec5ff88d", "0", "c3f1c4642f21f8c", .None}, + {.Sqrt, "4dec057cad04042c7339581208d0f7", "0", "8d3cca7c7dbb5a3", .None}, + {.Sqrt, "fd65a69380b2f2a42130f0c9b7284b", "0", "feb1f95f1a57e00", .None}, + {.Sqrt, "6c1e9c59b396589fc169dd2339dd49", "0", "a65e7033bf8b12d", .None}, + {.Sqrt, "cfe7bcd4acc362fd0e619deda5db29", "0", "e6b3e4685413ed8", .None}, + {.Sqrt, "a21a9e762f680c767f56e190ea4d8c", "0", "cbb64c12df30dc1", .None}, + {.Sqrt, "cc3af5afd6524a11f616c5a30bdfdb", "0", "e4a798aec0b5442", .None}, + {.Sqrt, "677b6e93abdf54a263f36ad1e25f4d", "0", "a2c30b0af0c5fe4", .None}, + {.Sqrt, "1ac358809774879291b3a114453a9f", "0", "52c5d9e640f4234", .None}, + {.Sqrt, "e855b1013ac87b4f7bbf75543a82d9", "0", "f3e16786e4810c6", .None}, + {.Sqrt, "43cc18385569ecc68c37b198e36674", "0", "83be168b96b1c82", .None}, + {.Sqrt, "6ad681956385784bab44bdfabb8d6c", "0", "a561401bba88b76", .None}, + {.Sqrt, "413fba54478ea8cfba9881b9500083", "0", "813e2edbd4d6278", .None}, + {.Sqrt, "462e8d80effaa9018b6a0aff71283e", "0", "860a14296a2db97", .None}, + {.Sqrt, "5d1d08361c9a6593f2319faa00f28", "0", "26991e1595bb4f4", .None}, + {.Sqrt, "539ef39258bf7e9d808d94c72fc2bb", "0", "924fa7441b8cc41", .None}, + {.Sqrt, "5e58fee290a03951552daaebcf4a42", "0", "9b698f29235cae6", .None}, + {.Sqrt, "3f484e4a855f30d8751c4257ea746c", "0", "7f47c9bc78cc47a", .None}, + {.Sqrt, "3fae57824431bc21c79bfc05b30991", "0", "7fae3d658a84ecf", .None}, + {.Sqrt, "99945378f2fd79c8d617819de0a324", "0", "c648901995a5d27", .None}, + {.Sqrt, "3fc8e13b68a2479ada31c11d662283", "0", "7fc8d5580d5c7b8", .None}, + {.Sqrt, "d354c4c63d25616f4ac56dce132210", "0", "e898810fd8f8b0c", .None}, + {.Sqrt, "689428d43ae00c8a49e7e4adb25707", "0", "a39f3b83564c35f", .None}, + {.Sqrt, "4ab763edfefa5d963a0ad2e9415cd4", "0", "8a4d43596cf3d7c", .None}, + {.Sqrt, "54378f4583d1b20a7e6833d7491872", "0", "92d4ecdd3d92762", .None}, + {.Sqrt, "ccb53a34f927c2f89d2a5feda1304", "0", "393b00170f971bf", .None}, + {.Sqrt, "d5d00e90251c5a565cebe1f88456ab", "0", "e9f517072caa9cd", .None}, + {.Sqrt, "1ec8401f06c1188faf3ca1f965c89b", "0", "58c55180b56790f", .None}, + {.Sqrt, "43ebe83dd11c880daac81119413f94", "0", "83dcfb96e522a65", .None}, + {.Sqrt, "609214726db102cbbeb380c6cce48c", "0", "9d3b897538f306a", .None}, + {.Sqrt, "b3c27f7510065a4f02d84879a395ea", "0", "d684ebed67f01db", .None}, + {.Sqrt, "e2efd3576332b6b42511ec3dbb7fee", "0", "f107dfa782ff16c", .None}, + {.Sqrt, "89ed891a9a638c6a1b6b3143b4527a", "0", "bbe88774eaa576d", .None}, + {.Sqrt, "bfcfb7b6468dc02a6cde4fc06d0fa6", "0", "dd97f54ab582a17", .None}, + {.Sqrt, "ca8b28a610c37a037a7f8f36d51710", "0", "e3b55ff0ebc6230", .None}, + {.Sqrt, "daf6ecf36444ddfb9ba18490103b05", "0", "ecc25bdf77a672c", .None}, + {.Sqrt, "6668e1e1803352bce4205be66bb993", "0", "a1ea91737f88d9d", .None}, + {.Sqrt, "bcdac6f810da24c962ef4e29588b43", "0", "dbe106875b9e15a", .None}, + {.Sqrt, "36a5bafd6dd4c71f4d6111fa206d73", "0", "76473783e47bc5c", .None}, + {.Sqrt, "18fdc2674c90ebf224a47a7f5f9d29", "0", "4ffc6a2a4fc6f4f", .None}, + {.Sqrt, "fbe0ec5f63f281c8b56df996f11b62", "0", "fdee5237dc6bad1", .None}, + {.Sqrt, "b82e7d1b8939820009b616124e657c", "0", "d924420c530110b", .None}, + {.Sqrt, "2ba3edd8b22f225adada9fd4688dc0", "0", "69b2854f49c1ee4", .None}, + {.Sqrt, "794f616fbe7d3990ec7e9b278be6fb", "0", "b039b1c529a1c8c", .None}, + {.Sqrt, "390f2f3d572fa3395e55aa5ecc12a8", "0", "78dc3524397c99b", .None}, + {.Sqrt, "27741a7ee02570389925496ce3fbe1", "0", "647fd03ba86aac8", .None}, + {.Sqrt, "1733222348d968dbcac89bd1243606", "0", "4d10d67df503409", .None}, + {.Sqrt, "df96780f8ecafc5c8eff473cc1932d", "0", "ef3ee144601b67d", .None}, + {.Sqrt, "cc307b09640d4fa9221004ffaaa804", "0", "e4a1badec54cbab", .None}, + {.Sqrt, "c2a86946b21a5631468c5869ba1244", "0", "df3b538815e16bc", .None}, + {.Sqrt, "f83b52882a0a5c02e824c89eb0a1f5", "0", "fc1600535b4869d", .None}, + {.Sqrt, "e6f47093373592fbad981db8dbd881", "0", "f327b9a1c7cd27b", .None}, + {.Sqrt, "bb65083acf8607c9b4d1afc344bf86", "0", "db0708343aaf0f2", .None}, + {.Sqrt, "773cb6e586b49a71b4ff35caef6b24", "0", "aeb6968f85f27ea", .None}, + {.Sqrt, "fbddd611ffb5b01da993e685d73e41", "0", "fdecc3d7b12de49", .None}, + {.Sqrt, "7f63e2a2149b6f97cf549cb30b6bae", "0", "b4966dae7b2012a", .None}, + {.Sqrt, "a3515f5730cddcff6544052a9b9d49", "0", "cc7930ebdd2b9a0", .None}, + {.Sqrt, "b278c732affce7e9b1cf484118cd8a", "0", "d5bfd46764a43fe", .None}, + {.Sqrt, "b4b1a31b9f4831ba61e2585e0c21dc", "0", "d7136d5379926e4", .None}, + {.Sqrt, "9fcebce4aa6a1184399b4cf4e799fe", "0", "ca439779ae51247", .None}, + {.Sqrt, "fa720d99be8ea97ca1345e23038378", "0", "fd3520ab9c7fc07", .None}, + {.Sqrt, "3a8d3a84c96e3bb8f6d445dd6bfa4c", "0", "7a6e3595b61784c", .None}, + {.Sqrt, "6e3e8b29121a3a1f955fbed25b2cf5", "0", "a7fee3ed9787255", .None}, + {.Sqrt, "2cc4fe65ff1d85aec569158ed2a6b2", "0", "6b0e5809de378b4", .None}, + {.Sqrt, "65d7d3decb2feedcf2649cd228c5f7", "0", "a177bd1c2bf6d16", .None}, + {.Sqrt, "792f3453cf72659d342d52e826788c", "0", "b02251418bd0851", .None}, + {.Sqrt, "258e79a17b5d62fd12376d33e1d024", "0", "620dad956921374", .None}, + {.Sqrt, "36a542b61f778b9c4c410fd14086ed", "0", "7646b5596ebe42f", .None}, + {.Sqrt, "496fee91f65382a99bbb70b8692547", "0", "891ce35391ebb45", .None}, + {.Sqrt, "5af744259d784155c4dc69d9322e47", "0", "989a064bd29a4ce", .None}, + {.Sqrt, "599ce14acfa8c050db4b568adba434", "0", "9776647bc824b5a", .None}, + {.Sqrt, "24a4ce3955655f6f7e601adf90a3d7", "0", "60dac45dbed0f16", .None}, + {.Sqrt, "f43d1b8e08207c2d7fd0d89488beaa", "0", "fa0cda93df0bfac", .None}, + {.Sqrt, "72c7d23e1b522650631b59ac38eec0", "0", "ab6ac6e426d1cdf", .None}, + {.Root, "10a157217ea8f01c4e185d80f40062", "2", "413f90706a04225", .None}, + {.Root, "cf51f1c733afbd10a4b4e52cf9013", "3", "5eb24bc09a", .None}, + {.Root, "6bd2a7cc718bdc2c4b3d1f1aa1d32c", "4", "338ee5e3", .None}, + {.Root, "495b51e970c7bd88720679d0a11575", "5", "c76116", .None}, + {.Root, "8af38458a8c7e3ed2843d6a1250560", "6", "e7364", .None}, + {.Root, "4f0a1e036625a983f0fb34d944703", "2", "238fc9901fb44a1", .None}, + {.Root, "c8fe3d6ad535dd07fdbf4772479b34", "3", "ec2aea0484", .None}, + {.Root, "90676f1c38c055c1ba86a5d7c3dfaf", "4", "3776e717", .None}, + {.Root, "db69281cfb4849292ffdccf0f8bd76", "5", "f83950", .None}, + {.Root, "735a1d31617440d5fecc288cb49bb7", "6", "e0263", .None}, + {.Root, "8f113145acd8e518eb73de0d6289f", "2", "2fd82252d5907fd", .None}, + {.Root, "2b7dc9e2fe4b215d16f6231dde37d3", "3", "8dc8bd3c79", .None}, + {.Root, "3dfe2af5f83dc0fd613f74914126bc", "4", "2ce550d2", .None}, + {.Root, "fc88d07eaa28592bd07f6aecd08559", "5", "ff4d98", .None}, + {.Root, "ee6b1b9d99059e8ff52816b54420aa", "6", "fcfb7", .None}, + {.Root, "1199dd464a8544575a5be55afb7b77", "2", "43203032110fa4c", .None}, + {.Root, "7362b17a7315e07c0c404f04152eb5", "3", "c447cca711", .None}, + {.Root, "449863d201bfc9bfb160b7aa0a5cca", "4", "2e0bd1eb", .None}, + {.Root, "2cf343e670ef62aedc0614c31da82c", "5", "b4c667", .None}, + {.Root, "c5ec71f2f89bd6f08fb011ec7257f1", "6", "f5410", .None}, + {.Root, "1a25d415009c87207e226e75bfdf6c", "2", "51d0d998c94a5b6", .None}, + {.Root, "85dae3292186347dda43947d899a50", "3", "ce3d4655f9", .None}, + {.Root, "9a537b3b88d1341cfe29466d4428d", "4", "1c326184", .None}, + {.Root, "fc4b9d679e3d8612a2fd0006c4ef39", "5", "ff4137", .None}, + {.Root, "e93095f254a0cf57adc3ac6f984451", "6", "fc0c8", .None}, + {.Root, "c21c6ebfa92f7f321eeb922f11e883", "2", "deeb01bccfdf0ad", .None}, + {.Root, "b0159bb163ef09987bb98103c6e57b", "3", "e1fa78e4c0", .None}, + {.Root, "3711741cba9e63e2e89dace66e00b1", "4", "2b95f7e5", .None}, + {.Root, "3243911422bf5f4b6519d28ecfd20f", "5", "b8dc31", .None}, + {.Root, "2fabbd07ba0e7223d385e4657076", "6", "4cc59", .None}, + {.Root, "57b84cc1d65b846b13856fc91bc52a", "2", "95dab0e9b62bdf3", .None}, + {.Root, "f9617697bee20a0441fd78ce766d99", "3", "fdc63705c4", .None}, + {.Root, "393e4b220db0fec9d70e3331914dea", "4", "2c028e53", .None}, + {.Root, "eb5c9eef6f92bbe1e17d6a7323fb7c", "5", "fbbb80", .None}, + {.Root, "d681e149745e595444b1f26573708e", "6", "f890b", .None}, + {.Root, "76d921190f00462fd6167ad2a6ca1e", "2", "ae6d91cda9cd47f", .None}, + {.Root, "a257b74d69b81ee527efede4c760ec", "3", "dbf0a273ba", .None}, + {.Root, "2fdf81ab17e17a4e4be749c8ebdecc", "4", "2a1624d8", .None}, + {.Root, "a0a48d9d492db77b0b26141fc4f512", "5", "e9381a", .None}, + {.Root, "bbafe9b789fe88c2e094cd06a0487d", "6", "f317c", .None}, + {.Root, "a2edc69cd59bf1b5d47f874b2e7303", "2", "cc3ace7f218777f", .None}, + {.Root, "f2f872878cc11d132b0a22301faa1b", "3", "fb94bbddbc", .None}, + {.Root, "4c6b0e0843a9cc35400c27c14303f7", "4", "2f4e6af1", .None}, + {.Root, "52cb822bc4f33cad45caa98a3ae269", "5", "cc43b1", .None}, + {.Root, "d4e5eb898735c13739b889e18b5314", "6", "f840e", .None}, + {.Root, "4d318bee6eb48920ac5a49b7dc170e", "2", "8c93658b92691c2", .None}, + {.Root, "5be8e98e42e2048fd511d511a89013", "3", "b5f2afbf5f", .None}, + {.Root, "3151a74df49baf66d40c7e8a57a82", "4", "15334b84", .None}, + {.Root, "7576c7e01fd1dc093fc787d5db0216", "5", "db10a1", .None}, + {.Root, "63fa04245cdc853fc79790962bacd7", "6", "dade4", .None}, + {.Root, "8f80162d1b70f1d35b6bc298ce1ed2", "2", "bfaaa67b068e613", .None}, + {.Root, "8e138f06bc8de3ee191d843b9fef75", "3", "d260ce4299", .None}, + {.Root, "f91bdb74842b1e5f5c9ef197ac3c3c", "4", "3f909c3a", .None}, + {.Root, "39fd817b76548f3b04e8d5ff35285e", "5", "be3915", .None}, + {.Root, "4066a7bab77d18353efd2d46b0ff5a", "6", "cb662", .None}, + {.Root, "3b3709f390db0a44a7b5cdaf30c88f", "2", "7b1f3e952d316dc", .None}, + {.Root, "9e2694752de2474c213ca576450110", "3", "da07c7389c", .None}, + {.Root, "25d4a34d56e1bf1012fbd9be58fb5", "4", "13d725b5", .None}, + {.Root, "4ea15f090b9e4ba9f7c79f561d9a5b", "5", "ca2ab9", .None}, + {.Root, "fbaad1cb36dea7724678cf188a096a", "6", "ff45d", .None}, + {.Root, "22c036b8243f8588d740b98311d5e9", "2", "5e51da9e0cfceca", .None}, + {.Root, "9002f56d2b23b747a35f3613510968", "3", "d354392be5", .None}, + {.Root, "2e06a68e9dc4ae3ccd914ae676e71e", "4", "29acae30", .None}, + {.Root, "6745de62dc4bf78a9ef599fca04821", "5", "d57eea", .None}, + {.Root, "6b34af81f0095e1dbf26aba0af5183", "6", "dd6e1", .None}, + {.Root, "e34ead33d4706f11f22bda070089fc", "2", "f13a3956ff07f9c", .None}, + {.Root, "1324d40a92b6492b14925ce54905da", "3", "6bdaa37191", .None}, + {.Root, "58db01228b8318833a4a5eb69c72b9", "4", "311faa9c", .None}, + {.Root, "234184556dceba1da58da8c5f68ad8", "5", "ac33bb", .None}, + {.Root, "d1b3d3cecb45e816316806e7c5009c", "6", "f7a0e", .None}, + {.Root, "39397f780192fd4233223d0eb9b70a", "2", "7908fcfd0e8a786", .None}, + {.Root, "c27e00b8ca788ebff945160aba1587", "3", "e997ede82a", .None}, + {.Root, "e71c5d0e4cc7983f31ed0f5cb0cd0d", "4", "3e625efb", .None}, + {.Root, "7a57bebc13b5845221f72fe9042f59", "5", "dcdaee", .None}, + {.Root, "9ed13eb706eb814786e826697beec", "6", "94ef5", .None}, + {.Root, "de9040e209f486141923474d990c72", "2", "eeb26dfe54724ca", .None}, + {.Root, "c854161033296360bdad6d4501928a", "3", "ebe83260e5", .None}, + {.Root, "3e3516d2a0979e8ddf7bf80e2775a3", "4", "2cef3f17", .None}, + {.Root, "ad20ac49059848dec6df28fbfc69f7", "5", "ecbc8c", .None}, + {.Root, "837ce0850edf789b553158498fba4a", "6", "e5182", .None}, + {.Root, "3bdb6716894515e982b75ee0f4aa1b", "2", "7bc9a8d4475f6ea", .None}, + {.Root, "7b5c0a74a825b969eab0f8bda12dac", "3", "c8b39d8e98", .None}, + {.Root, "6883c1e90dd7d53610037aa934d018", "4", "33287873", .None}, + {.Root, "7fe952b2f16ac29a0b189432199c6f", "5", "ded480", .None}, + {.Root, "426db1f971f26d8b953192c44f675d", "6", "cc73d", .None}, + {.Root, "b83fb79ed83d2e31999aeeebe2477f", "2", "d92e69b4e6fa43c", .None}, + {.Root, "b590bf66580632da19e8939ba86481", "3", "e44c973d96", .None}, + {.Root, "4c5702ed0e9a8c64c54e7a9d421323", "4", "2f4b508a", .None}, + {.Root, "71d69da6bf4520dd2d3c87f1c64169", "5", "d9b213", .None}, + {.Root, "5d32f403622bd752b2c94610b27b67", "6", "d8529", .None}, + {.Root, "43fcb414b9d5e0978aeb10d5295f9b", "2", "83ed4872cfe0ec2", .None}, + {.Root, "80cad211d850368606fff486f234f3", "3", "cb9b0e63e2", .None}, + {.Root, "45f894372cc647d16f1db6c55f7fa5", "4", "2e467c00", .None}, + {.Root, "68f2eb764edf9148ea9bc08796b4ea", "5", "d62f2b", .None}, + {.Root, "fcb283e1a3d7bec0bc670b6d5250c4", "6", "ff725", .None}, + {.Root, "dadce8f6507f08f01d9373db6116e9", "2", "ecb44ad7502e275", .None}, + {.Root, "2e3a5b838a51430f403338bc5c2f88", "3", "90b29ac1eb", .None}, + {.Root, "3bf0444f1bf582301cd31be40203d2", "4", "2c84e4c0", .None}, + {.Root, "5ae6d8a4d99a8189ee2e511e4669b9", "5", "d01dcf", .None}, + {.Root, "f49c1d20d5ea28aaf157ab7b0f0cb3", "6", "fe10c", .None}, + {.Shl, "-658d3d08e731450523288b993bdfbf", "3c", "-658d3d08e731450523288b993bdfbf000000000000000", .None}, + {.Shl, "a189599945cd53f46acc6f4ac90488", "0", "a189599945cd53f46acc6f4ac90488", .None}, + {.Shl, "-e8084215bade34a2a832d43b9ea4fb", "78", "-e8084215bade34a2a832d43b9ea4fb000000000000000000000000000000", .None}, + {.Shl, "d28decc587a041d7e42a1f2fa28007", "258", "d28decc587a041d7e42a1f2fa28007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "7569d5e1a75d7f73d14ce469835452", "3c", "7569d5e1a75d7f73d14ce469835452000000000000000", .None}, + {.Shl, "-24a51f36e5e302158e5a88ed5c3dd", "f0", "-24a51f36e5e302158e5a88ed5c3dd000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "2d90d15bee02bd7aca9a66777d005f", "78", "2d90d15bee02bd7aca9a66777d005f000000000000000000000000000000", .None}, + {.Shl, "238b064bb74cd5645e8e20f254e3c4", "f0", "238b064bb74cd5645e8e20f254e3c4000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "77097dd67669de087e31db3c4558d", "78", "77097dd67669de087e31db3c4558d000000000000000000000000000000", .None}, + {.Shl, "-b2e7b6eee99021b5b7b2b2d647481e", "21c", "-b2e7b6eee99021b5b7b2b2d647481e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "6309dd4d898be926a69106f85f1c46", "1a4", "6309dd4d898be926a69106f85f1c46000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-707d0b9a1b3126f26f990593636f1e", "b4", "-707d0b9a1b3126f26f990593636f1e000000000000000000000000000000000000000000000", .None}, + {.Shl, "790a29c144992ce75eae07115982b1", "12c", "790a29c144992ce75eae07115982b1000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-772002671f998cea41950c33a295eb", "f0", "-772002671f998cea41950c33a295eb000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "c2c68423de26917271baa68db64a3f", "0", "c2c68423de26917271baa68db64a3f", .None}, + {.Shl, "-6600bbec432116ea389decd67fece3", "78", "-6600bbec432116ea389decd67fece3000000000000000000000000000000", .None}, + {.Shl, "-944c70dc7667fdab30117d2bbed4aa", "1e0", "-944c70dc7667fdab30117d2bbed4aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "6455f8815e82a4abec258b125155af", "3c", "6455f8815e82a4abec258b125155af000000000000000", .None}, + {.Shl, "-f78acd68f7afb295c1f349796650fd", "168", "-f78acd68f7afb295c1f349796650fd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ea3c758da2e3bac2ef7f10699ce980", "258", "ea3c758da2e3bac2ef7f10699ce980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-121b346cd116d61944cbe39cf02e18", "f0", "-121b346cd116d61944cbe39cf02e18000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-f6bd7793cb62c5fe5a4cf4668022bf", "b4", "-f6bd7793cb62c5fe5a4cf4668022bf000000000000000000000000000000000000000000000", .None}, + {.Shl, "e67adba938d4a5ba3ab9ffb717afe", "3c", "e67adba938d4a5ba3ab9ffb717afe000000000000000", .None}, + {.Shl, "f74e955ca1c5983e9da4100dcac037", "3c", "f74e955ca1c5983e9da4100dcac037000000000000000", .None}, + {.Shl, "-da6c4d25768161e4155f976e7fd32d", "1a4", "-da6c4d25768161e4155f976e7fd32d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-508805b06e0b273e7c0de2b4e42ce5", "168", "-508805b06e0b273e7c0de2b4e42ce5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "21cac804f76655bf3b63bb60c6b42", "b4", "21cac804f76655bf3b63bb60c6b42000000000000000000000000000000000000000000000", .None}, + {.Shl, "fac290d4a58edb998777ce26332437", "1e0", "fac290d4a58edb998777ce26332437000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-d2f71eccbd401cf34b6f2772c33504", "3c", "-d2f71eccbd401cf34b6f2772c33504000000000000000", .None}, + {.Shl, "-983b3a02d754e76a2136bfe04538f7", "1e0", "-983b3a02d754e76a2136bfe04538f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b8bd8ce0cbb8684e6bba8214b9175a", "3c", "-b8bd8ce0cbb8684e6bba8214b9175a000000000000000", .None}, + {.Shl, "-ad9d1c5cb6e62e46626cf8ec3c636c", "1e0", "-ad9d1c5cb6e62e46626cf8ec3c636c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-54cb3bfa1944106d16b7dd1b8e9bc5", "3c", "-54cb3bfa1944106d16b7dd1b8e9bc5000000000000000", .None}, + {.Shl, "4c82756e3e83c0d4d856ba8f0d4472", "258", "4c82756e3e83c0d4d856ba8f0d4472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-8d87c19d6f8aecb713b722e2ca5847", "168", "-8d87c19d6f8aecb713b722e2ca5847000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "701f015c25c06c4f49b2af5c98cea0", "1a4", "701f015c25c06c4f49b2af5c98cea0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "60a4a494ca89cd11eaee20872fad25", "b4", "60a4a494ca89cd11eaee20872fad25000000000000000000000000000000000000000000000", .None}, + {.Shl, "-ddef18322467fa6d382c35d528cbaa", "0", "-ddef18322467fa6d382c35d528cbaa", .None}, + {.Shl, "52d7e1c5aeceea088584080e7bae34", "0", "52d7e1c5aeceea088584080e7bae34", .None}, + {.Shl, "698b2e8973088cc64a4c0faea21cdf", "21c", "698b2e8973088cc64a4c0faea21cdf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-8c54f6339c4ae8bebb9dca6d59d655", "78", "-8c54f6339c4ae8bebb9dca6d59d655000000000000000000000000000000", .None}, + {.Shl, "-483bd7a66ae9bf14a8e0ffb5331444", "0", "-483bd7a66ae9bf14a8e0ffb5331444", .None}, + {.Shl, "463f8dd1512737e7878b61e912309a", "1e0", "463f8dd1512737e7878b61e912309a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "b0ff158395e9c5637ba2d608b0c8e0", "258", "b0ff158395e9c5637ba2d608b0c8e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-189dacac8d5275bf5db45590d69f14", "b4", "-189dacac8d5275bf5db45590d69f14000000000000000000000000000000000000000000000", .None}, + {.Shl, "-cf78ac49617f519b2907fe7d5f09b1", "1a4", "-cf78ac49617f519b2907fe7d5f09b1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-8e26ed632298e36e7ab270dff8a3a4", "21c", "-8e26ed632298e36e7ab270dff8a3a4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-d6d6ac0a5a03ed6aad82d3f4b50df9", "0", "-d6d6ac0a5a03ed6aad82d3f4b50df9", .None}, + {.Shl, "fe277a9f1bc8b294ed743528f9e14c", "0", "fe277a9f1bc8b294ed743528f9e14c", .None}, + {.Shl, "-886ef6cbd61932b7b9e1dfb6785399", "78", "-886ef6cbd61932b7b9e1dfb6785399000000000000000000000000000000", .None}, + {.Shl, "-bc2457a3ed4f9a8f1948338f874960", "b4", "-bc2457a3ed4f9a8f1948338f874960000000000000000000000000000000000000000000000", .None}, + {.Shl, "-426bd1f974dc0609b9c1050ff8324c", "12c", "-426bd1f974dc0609b9c1050ff8324c000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-3a8342f9e8dbe7756f244fbfad4dd4", "b4", "-3a8342f9e8dbe7756f244fbfad4dd4000000000000000000000000000000000000000000000", .None}, + {.Shl, "-8a428a37bf21ad928f1abe71e629b7", "78", "-8a428a37bf21ad928f1abe71e629b7000000000000000000000000000000", .None}, + {.Shl, "-e45a05bccf7e80c5d241d6f60d7c42", "12c", "-e45a05bccf7e80c5d241d6f60d7c42000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-200dc45c64f05bb129cc529e564f92", "168", "-200dc45c64f05bb129cc529e564f92000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-a5f1e2bc4e6e3a71434f8f0b227f3e", "12c", "-a5f1e2bc4e6e3a71434f8f0b227f3e000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e0baf9fab9cf811a0052281f9c0e96", "1e0", "-e0baf9fab9cf811a0052281f9c0e96000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-864ffc64f0869ffb4fc65f37a6b999", "1a4", "-864ffc64f0869ffb4fc65f37a6b999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ded81eb544433c41895a4cab5a3e47", "1a4", "ded81eb544433c41895a4cab5a3e47000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "60d02474a900fa9e0658aa8635300a", "258", "60d02474a900fa9e0658aa8635300a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "10bdc62a35e240e2c2c816b41dd32f", "78", "10bdc62a35e240e2c2c816b41dd32f000000000000000000000000000000", .None}, + {.Shl, "39e71136e71e3a8e712ebd7ccd321b", "f0", "39e71136e71e3a8e712ebd7ccd321b000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-48bf1c52f962dbf26979a7e27c4f6f", "f0", "-48bf1c52f962dbf26979a7e27c4f6f000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-952b905ae68b83644a5085b4347303", "168", "-952b905ae68b83644a5085b4347303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-87c58ff7391b413a7d9eb7a0bc138d", "258", "-87c58ff7391b413a7d9eb7a0bc138d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "58949fb5d92360f2acb4b46155a644", "f0", "58949fb5d92360f2acb4b46155a644000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "f6c75c94e711343bfa870f439310c", "1a4", "f6c75c94e711343bfa870f439310c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-62f1ab29771a502d3452b405e7d0fc", "168", "-62f1ab29771a502d3452b405e7d0fc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "66762e87d6815c8cac54c084ab1e6e", "168", "66762e87d6815c8cac54c084ab1e6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "dbecc16a2b12b89941f1b074e4eabb", "78", "dbecc16a2b12b89941f1b074e4eabb000000000000000000000000000000", .None}, + {.Shl, "53312830f014e38440efff2955d542", "3c", "53312830f014e38440efff2955d542000000000000000", .None}, + {.Shl, "-71a485b29edf13c7e9bbbe81f28d55", "3c", "-71a485b29edf13c7e9bbbe81f28d55000000000000000", .None}, + {.Shl, "-aeedc8bc4a2bc625e3395d61a54f3a", "1a4", "-aeedc8bc4a2bc625e3395d61a54f3a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "1dae7091a8e5382590407fb85a3446", "3c", "1dae7091a8e5382590407fb85a3446000000000000000", .None}, + {.Shl, "-1f2848713247c481b19a7841ceec0b", "0", "-1f2848713247c481b19a7841ceec0b", .None}, + {.Shl, "-719cf5e1852efe103dbb8f9f56402", "1e0", "-719cf5e1852efe103dbb8f9f56402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-4cbb612a8993dc0785468bea82b84a", "78", "-4cbb612a8993dc0785468bea82b84a000000000000000000000000000000", .None}, + {.Shl, "-c4323fe1e34002a86ca6550bc570d5", "3c", "-c4323fe1e34002a86ca6550bc570d5000000000000000", .None}, + {.Shl, "-4ff49bc6aa65580bc525d8f781d955", "0", "-4ff49bc6aa65580bc525d8f781d955", .None}, + {.Shl, "124597f9ee1db2a29c9155e0ba994e", "258", "124597f9ee1db2a29c9155e0ba994e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "54ee206493a1872cc8baf80cfa1154", "258", "54ee206493a1872cc8baf80cfa1154000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-8e0366464e9ebefe00df4765c47820", "258", "-8e0366464e9ebefe00df4765c47820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-188fc9eafcd3751ba40609942f7890", "1a4", "-188fc9eafcd3751ba40609942f7890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "dd0993224cab3cfc44f677abcf5977", "78", "dd0993224cab3cfc44f677abcf5977000000000000000000000000000000", .None}, + {.Shl, "-4cf88736b9569635174dc0e91d1af7", "168", "-4cf88736b9569635174dc0e91d1af7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-1b9dcf0cc32f13d88ec4687129ef8f", "1a4", "-1b9dcf0cc32f13d88ec4687129ef8f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "310b5680963f337bd2a1e8bd5f9f4d", "1a4", "310b5680963f337bd2a1e8bd5f9f4d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "2e5cca517cd419eb978ffe8f7d32f9", "12c", "2e5cca517cd419eb978ffe8f7d32f9000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "4cb82c43e0bdb2e83b2d577c95f200", "78", "4cb82c43e0bdb2e83b2d577c95f200000000000000000000000000000000", .None}, + {.Shl, "d7771c0fc5d53c6a091ba61713a54f", "1e0", "d7771c0fc5d53c6a091ba61713a54f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e88fe006377fcaceb008967fcbb6ee", "78", "-e88fe006377fcaceb008967fcbb6ee000000000000000000000000000000", .None}, + {.Shl, "e0b5ab720e8bc8927ac2c62723d205", "78", "e0b5ab720e8bc8927ac2c62723d205000000000000000000000000000000", .None}, + {.Shl, "e441ad16143d98743ca2d247c0583e", "b4", "e441ad16143d98743ca2d247c0583e000000000000000000000000000000000000000000000", .None}, + {.Shl, "6772b1de4cc1c1c1dff44cf3b65f29", "b4", "6772b1de4cc1c1c1dff44cf3b65f29000000000000000000000000000000000000000000000", .None}, + {.Shl, "-c7a908c675996a5c78776de01c42f3", "1e0", "-c7a908c675996a5c78776de01c42f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-49e4164e8bd234d2b812ba40c75562", "b4", "-49e4164e8bd234d2b812ba40c75562000000000000000000000000000000000000000000000", .None}, + {.Shl, "d8b7b4e05ae24f2cf37d546135f7cc", "3c", "d8b7b4e05ae24f2cf37d546135f7cc000000000000000", .None}, + {.Shl, "-89fae13d7439b1aeba0df993cc606c", "21c", "-89fae13d7439b1aeba0df993cc606c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "5ba139cacf39236cec672b7af31d9", "f0", "5ba139cacf39236cec672b7af31d9000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "1fc44e1c8f5073aa85d4ab14a3391b", "f0", "0", .None}, + {.Shr, "7fa5e5f6f5ee17eaddee98f5ba5bc1", "12c", "0", .None}, + {.Shr, "ae3d7a618e61f43fb093b2f17d89be", "12c", "0", .None}, + {.Shr, "e5f51680ef93b5142492683eddce9", "78", "0", .None}, + {.Shr, "18488f8a42581b61c882d5dd9013fc", "1e0", "0", .None}, + {.Shr, "ea1d6461d9ed01cfb38243c6922b66", "b4", "0", .None}, + {.Shr, "d00631ebe3f98fa76c99a00954d443", "78", "0", .None}, + {.Shr, "ab84f35e0437fcaf6f24a33be80cac", "f0", "0", .None}, + {.Shr, "b18dadb89ed579ba28b89f7ed31596", "1e0", "0", .None}, + {.Shr, "3df6eeaf5cda3935f8f7d656412592", "78", "0", .None}, + {.Shr, "fac43c91e42fdb66eb43a554f1f527", "258", "0", .None}, + {.Shr, "bb30af0fc3ee4c10c70204c1afd4f2", "f0", "0", .None}, + {.Shr, "66670b671486f4e46fb39d09fd9c48", "21c", "0", .None}, + {.Shr, "c566deff1abe3cfe09f0fc9c5f6a34", "78", "0", .None}, + {.Shr, "84a522c9965455fa52a9d0b5b7775f", "168", "0", .None}, + {.Shr, "fcab1b67d1e92818b9b5be5d9ea048", "3c", "fcab1b67d1e9281", .None}, + {.Shr, "d1ee2ae5ddd7c69bc77d5d46fd33f7", "3c", "d1ee2ae5ddd7c69", .None}, + {.Shr, "ec84b92b427ad1d886d61d8679b48", "168", "0", .None}, + {.Shr, "7d6419fc5d66dc4e97d9c6eba31f65", "1a4", "0", .None}, + {.Shr, "7339383db5316b94cbfd2cb1e9a42b", "1e0", "0", .None}, + {.Shr, "200961abb4c0512f282bc6814f1648", "1e0", "0", .None}, + {.Shr, "6484bdee4978fcc629bfa6a24b9d", "f0", "0", .None}, + {.Shr, "10376509c1859dfd1ef57904fe0f6b", "12c", "0", .None}, + {.Shr, "40b7958ae4e99b9b61cd8f8017860e", "258", "0", .None}, + {.Shr, "a262e80d02aa62b7eddf40e0c1a333", "258", "0", .None}, + {.Shr, "6aa121a01cad630cbac92baebb43a7", "78", "0", .None}, + {.Shr, "ae96af31baf3a1559d9bea96e75568", "21c", "0", .None}, + {.Shr, "5606d35754ee4f9aa07018828b404b", "b4", "0", .None}, + {.Shr, "b02648545551476f92175d8f22af67", "168", "0", .None}, + {.Shr, "fa0b72077dc24bd279aab163583db7", "1e0", "0", .None}, + {.Shr, "32761894f68eba2ecdd4ac918ec8bf", "78", "0", .None}, + {.Shr, "caa5bed3ae8142c996cd68e80983df", "b4", "0", .None}, + {.Shr, "b203d7d210dfc5fe78a39be3d95429", "1a4", "0", .None}, + {.Shr, "40177f4578998bd04a6d2a718ab043", "258", "0", .None}, + {.Shr, "409102784539816b4010e899ff4649", "f0", "0", .None}, + {.Shr, "53eb0d31bc11ef199f78aad44a9e78", "12c", "0", .None}, + {.Shr, "42079a0a28c33ca7c4c164533eec65", "1e0", "0", .None}, + {.Shr, "825a5b2c2b787b07269d94675ff037", "3c", "825a5b2c2b787b0", .None}, + {.Shr, "de11733c4514f98ab148bda0167831", "12c", "0", .None}, + {.Shr, "9fbc7df64a215c3573a813e49a3ba5", "1a4", "0", .None}, + {.Shr, "f557b381b56f724c2379e0414230bc", "258", "0", .None}, + {.Shr, "76dfea4c3784bdf674db60d6769965", "21c", "0", .None}, + {.Shr, "b8c1a0975018862a0f060d94e8b078", "3c", "b8c1a0975018862", .None}, + {.Shr, "71f35af151cc6f3066ce5a80787e53", "12c", "0", .None}, + {.Shr, "65f3df82d52ac5b1bd025cc490b461", "b4", "0", .None}, + {.Shr, "9dac37375e68fb8489411801f1854c", "f0", "0", .None}, + {.Shr, "36e249e98eb6c592633609c102b0d1", "258", "0", .None}, + {.Shr, "d9682b71fb53408b8c5a5bb8e6b929", "78", "0", .None}, + {.Shr, "b59946cebfab79bce24daffe509296", "78", "0", .None}, + {.Shr, "8c1350ce18f3067931b2d7eeff31d6", "f0", "0", .None}, + {.Shr, "44056923bdde2078dad1208240e182", "1e0", "0", .None}, + {.Shr, "aa5cff9c7d280818558a06923e674d", "f0", "0", .None}, + {.Shr, "f96770c9f8edcee259c98fd04172d", "0", "f96770c9f8edcee259c98fd04172d", .None}, + {.Shr, "4fb74295e5fe2543ea85b9b320001d", "0", "4fb74295e5fe2543ea85b9b320001d", .None}, + {.Shr, "e5a349a39512b46d170a0ba8dbe03d", "78", "0", .None}, + {.Shr, "74d0d1bdfa5307be0f01d18f57a6e", "1e0", "0", .None}, + {.Shr, "ff1d71786ab7272f46baafb3fb009c", "78", "0", .None}, + {.Shr, "5bd31982ece463bf09e716d135d9d4", "1a4", "0", .None}, + {.Shr, "3fdf6d44dd2fa6cf6227e1f4b42e4d", "0", "3fdf6d44dd2fa6cf6227e1f4b42e4d", .None}, + {.Shr, "be0cc4fe8049b06e04a3f69616a585", "21c", "0", .None}, + {.Shr, "64b196c09ac9ed4a779e6893098ea4", "1a4", "0", .None}, + {.Shr, "baea13cae5aaa509893a70efceab3c", "0", "baea13cae5aaa509893a70efceab3c", .None}, + {.Shr, "86e4ea0a5abefd50810c95c06d6909", "78", "0", .None}, + {.Shr, "4840a41269268b23d1dc688fa6a272", "258", "0", .None}, + {.Shr, "8c191f2ff6afaeb886e88593344fe", "1e0", "0", .None}, + {.Shr, "91a583b4cf8d8ed12a4adb9ace912", "78", "0", .None}, + {.Shr, "fa04769e975833cd237fd0d6a59c62", "0", "fa04769e975833cd237fd0d6a59c62", .None}, + {.Shr, "37d566faa6d1c71f128f688a63a729", "12c", "0", .None}, + {.Shr, "379d16eaab9b9d4527b7127d9e3e85", "1e0", "0", .None}, + {.Shr, "c034b3da2c26916e2b2ebddb5019ec", "b4", "0", .None}, + {.Shr, "da529ef77b79ab0c67a2df06311c7b", "78", "0", .None}, + {.Shr, "dc7ec792a767a911c861fce1e23030", "21c", "0", .None}, + {.Shr, "41c423963b378beca1dc3d15ba90df", "168", "0", .None}, + {.Shr, "1a802e1ff08f2fd58c240b724c28e8", "b4", "0", .None}, + {.Shr, "5f5c74b071faabc15840802ec4209c", "258", "0", .None}, + {.Shr, "6007683b140fb1750495fd6000ccf2", "12c", "0", .None}, + {.Shr, "deb48a4b6513663d229f0d3d779287", "3c", "deb48a4b6513663", .None}, + {.Shr, "298084a29ef5084516a4a377791b05", "0", "298084a29ef5084516a4a377791b05", .None}, + {.Shr, "83ef35717378da10f1cf863019cb07", "78", "0", .None}, + {.Shr, "efe13f12aa5b8d75506de90220091f", "12c", "0", .None}, + {.Shr, "4bcce2d1e8104f5b6ffe5a2c625223", "0", "4bcce2d1e8104f5b6ffe5a2c625223", .None}, + {.Shr, "321a2b2ddb17162a0e358f9f7ec1c3", "0", "321a2b2ddb17162a0e358f9f7ec1c3", .None}, + {.Shr, "c517c313b12846964fc03f0e7c8f01", "0", "c517c313b12846964fc03f0e7c8f01", .None}, + {.Shr, "8779232c5bf4a8f63411fc0682b277", "168", "0", .None}, + {.Shr, "74589d16e3b619fe2f3816e0627fc2", "21c", "0", .None}, + {.Shr, "3d4bef779013adc7ea0901f5a6fbd3", "1e0", "0", .None}, + {.Shr, "99392ea73a0dde4125b39f9762018", "1e0", "0", .None}, + {.Shr, "8c3e168c8efb59c146f045aa8092d6", "78", "0", .None}, + {.Shr, "d18b630a8a7962fbbeb9baf54975e5", "168", "0", .None}, + {.Shr, "39a9550c2d5405fbc34a48940071f1", "3c", "39a9550c2d5405f", .None}, + {.Shr, "d207c731f09536a30daa7900d9c674", "f0", "0", .None}, + {.Shr, "3dcad14fab82254df4cf499619dfd0", "78", "0", .None}, + {.Shr, "fe7c24b1e99f76f4897068ebcbe6d6", "258", "0", .None}, + {.Shr, "4c8fa40ae81be73e9ad4e5bcacc280", "1a4", "0", .None}, + {.Shr, "97bad43211c08a2b98ad1867866309", "0", "97bad43211c08a2b98ad1867866309", .None}, + {.Shr, "41c2ef52c8aaa5f5bab2a4f69c8e32", "78", "0", .None}, + {.Shr, "39800dc581db76a0dc8daa73525b61", "258", "0", .None}, + {.Shr, "342b2b446280bac44a1f578f1269c6", "b4", "0", .None}, + {.Shr, "1bccc1a51e27e60e4cd4b91655fcf0", "12c", "0", .None}, + {.Shr, "df97403177c8d24caaf1523cff3eb8", "21c", "0", .None}, + {.Shl, "244570854e3f425c6bdad06ca8f2f3", "18", "244570854e3f425c6bdad06ca8f2f3000000", .None}, + {.Shl, "-66a05544c910528cea93f56197dad3", "62", "-19a81551324414a33aa4fd5865f6b4c000000000000000000000000", .None}, + {.Shl, "f54bf2eac9af50f6e1f0459be92da9", "12", "3d52fcbab26bd43db87c1166fa4b6a40000", .None}, + {.Shl, "-935ca9ea6a627d45c42180e0c78ec", "a", "-24d72a7a9a989f517108603831e3b000", .None}, + {.Shl, "be143b95d5da6eaa6133c9bdc2baec", "45", "17c28772babb4dd54c267937b8575d800000000000000000", .None}, + {.Shl, "-8694fdc2ecd05a80879ce81e71600", "3", "-434a7ee176682d4043ce740f38b000", .None}, + {.Shl, "39b904ded7c985278421fc3d9c50f7", "23", "1cdc826f6be4c293c210fe1ece287b800000000", .None}, + {.Shl, "-8eea96d025abb9ad01c44a62849f45", "8", "-8eea96d025abb9ad01c44a62849f4500", .None}, + {.Shl, "-ba1a2f83b32346bdbed5d1f6f98c71", "11", "-174345f0766468d7b7daba3edf318e20000", .None}, + {.Shl, "-f64d76d11266c9edd6cfa93d8d49f2", "45", "-1ec9aeda224cd93dbad9f527b1a93e400000000000000000", .None}, + {.Shl, "-ec06059c1af58d82cf8fbc0de61281", "33", "-760302ce0d7ac6c167c7de06f309408000000000000", .None}, + {.Shl, "1387237cf7fb303d1848680c7b9dad", "75", "270e46f9eff6607a3090d018f73b5a00000000000000000000000000000", .None}, + {.Shl, "-d08ae02ccbc6269bf89263033705ee", "3c", "-d08ae02ccbc6269bf89263033705ee000000000000000", .None}, + {.Shl, "-e4af23fe2a26607d2a51b1dc1d04ef", "34", "-e4af23fe2a26607d2a51b1dc1d04ef0000000000000", .None}, + {.Shl, "1eb19883ee0ce2c4e3e9c256eaf11c", "34", "1eb19883ee0ce2c4e3e9c256eaf11c0000000000000", .None}, + {.Shl, "6f1c4434a95a72391b216c8702bf1a", "56", "1bc7110d2a569c8e46c85b21c0afc68000000000000000000000", .None}, + {.Shl, "-c95ca0e6c5b096f182a8cbdc6b0f89", "28", "-c95ca0e6c5b096f182a8cbdc6b0f890000000000", .None}, + {.Shl, "8c6f9ac8a2a1b1164f93a3bc241ae", "6f", "4637cd645150d88b27c9d1de120d70000000000000000000000000000", .None}, + {.Shl, "-82eaac537f5e60c1b922c5ae5e2f28", "e", "-20baab14dfd798306e48b16b978bca0000", .None}, + {.Shl, "-8c4a436b9972479b498f8a682513d8", "2", "-231290dae65c91e6d263e29a0944f60", .None}, + {.Shl, "-bcb905712c7a9d993e0d13f23543d", "c", "-bcb905712c7a9d993e0d13f23543d000", .None}, + {.Shl, "c617550f4ed58032e97babcd732af9", "4d", "18c2eaa1e9dab0065d2f7579ae655f20000000000000000000", .None}, + {.Shl, "3553c9fcc27ab9402fda0bd1b1075f", "53", "1aa9e4fe613d5ca017ed05e8d883af800000000000000000000", .None}, + {.Shl, "-9446b6bb675c42d09a49ac3aa8d699", "24", "-9446b6bb675c42d09a49ac3aa8d699000000000", .None}, + {.Shl, "23498564192b548d10d26cd4ebf3ae", "60", "23498564192b548d10d26cd4ebf3ae000000000000000000000000", .None}, + {.Shl, "ec7d6d997639d51cab76d9c9bacd0f", "65", "1d8fadb32ec73aa3956edb393759a1e0000000000000000000000000", .None}, + {.Shl, "-bdc8dfff866ed8c12532d8600673cd", "37", "-5ee46fffc3376c6092996c300339e680000000000000", .None}, + {.Shl, "-81dc3af2096563a00cde5b3d72b229", "65", "-103b875e412cac74019bcb67ae564520000000000000000000000000", .None}, + {.Shl, "eadf5e9d96d6c76ae5dbee8432608", "3b", "756faf4ecb6b63b572edf74219304000000000000000", .None}, + {.Shl, "-883ce2770e168051da7384e9f61d96", "55", "-11079c4ee1c2d00a3b4e709d3ec3b2c000000000000000000000", .None}, + {.Shl, "-e78eeb075a4b4931db92d212e961bd", "1f", "-73c77583ad25a498edc9690974b0de80000000", .None}, + {.Shl, "-ed50a0dd5eff2fa4323ba52620656a", "3", "-76a8506eaf7f97d2191dd2931032b50", .None}, + {.Shl, "825c4932faaf58cdc0415c66520bab", "8", "825c4932faaf58cdc0415c66520bab00", .None}, + {.Shl, "d6a1029746a8b2a242830f64516b19", "3b", "6b50814ba3545951214187b228b58c800000000000000", .None}, + {.Shl, "-5bd92a0e142451bb71af4f3f2599c0", "36", "-16f64a838509146edc6bd3cfc9667000000000000000", .None}, + {.Shl, "c0be8cef6e800c0fcb3acc3c37a811", "f", "605f4677b7400607e59d661e1bd4088000", .None}, + {.Shl, "11c91e59c4dcdda9f7dd3ee8c81055", "3c", "11c91e59c4dcdda9f7dd3ee8c81055000000000000000", .None}, + {.Shl, "-88807cec625a9dc410424a598b5b1c", "62", "-22201f3b1896a7710410929662d6c70000000000000000000000000", .None}, + {.Shl, "e24c27a2fc9196b8d358cf20ec7e95", "3a", "389309e8bf2465ae34d633c83b1fa5400000000000000", .None}, + {.Shl, "95c9cb4b2ceae8365134ffd45d8050", "52", "257272d2cb3aba0d944d3ff5176014000000000000000000000", .None}, + {.Shl, "a60cf77f73d57dd05c0d5aebd48d5c", "5e", "29833ddfdcf55f74170356baf52357000000000000000000000000", .None}, + {.Shl, "-df6a832cea6d8480f5fd08e268f591", "77", "-6fb541967536c2407afe8471347ac8800000000000000000000000000000", .None}, + {.Shl, "-1bb9278c2e9db1551856ad6545dcd8", "42", "-6ee49e30ba76c554615ab5951773600000000000000000", .None}, + {.Shl, "-92e9b031cb6a42a79d5b485d40a0ff", "72", "-24ba6c0c72da90a9e756d21750283fc0000000000000000000000000000", .None}, + {.Shl, "-67944e9550a59b37ee41f0910783", "2c", "-67944e9550a59b37ee41f091078300000000000", .None}, + {.Shl, "e84086f2c4b36687acc2f22c3eed53", "15", "1d0810de58966cd0f5985e4587ddaa600000", .None}, + {.Shl, "-618644ced4c6207e950261bfba604e", "3f", "-30c322676a63103f4a8130dfdd30270000000000000000", .None}, + {.Shl, "-7643e6494e66c382a33093dfc24b23", "64", "-7643e6494e66c382a33093dfc24b230000000000000000000000000", .None}, + {.Shl, "775fd7aaf5f14307b2e1aa0612902f", "75", "eebfaf55ebe2860f65c3540c25205e00000000000000000000000000000", .None}, + {.Shl, "9817da610a78edaf89c9d78786dbfc", "1d", "1302fb4c214f1db5f1393af0f0db7f80000000", .None}, + {.Shl, "5e68236cc7b4ae21a91b225019d968", "73", "2f3411b663da5710d48d91280cecb400000000000000000000000000000", .None}, + {.Shl, "-47a958accdafbcd7685b305d006778", "44", "-47a958accdafbcd7685b305d00677800000000000000000", .None}, + {.Shl, "-32f28e6f786a56f6ce8b797d99fede", "4d", "-65e51cdef0d4aded9d16f2fb33fdbc0000000000000000000", .None}, + {.Shl, "6fad5bdf93a994295718ce9cebc16b", "45", "df5ab7bf27532852ae319d39d782d600000000000000000", .None}, + {.Shl, "-840bc2e57e624169065fff4db85c50", "41", "-1081785cafcc482d20cbffe9b70b8a00000000000000000", .None}, + {.Shl, "-42dd661ce9b320eca8c9cdfffde556", "19", "-85bacc39d36641d951939bfffbcaac000000", .None}, + {.Shl, "78c3350e4d391d5b4366a51394dd2e", "28", "78c3350e4d391d5b4366a51394dd2e0000000000", .None}, + {.Shl, "-fc0534e6c89b099c1a5ee98ac4aabb", "54", "-fc0534e6c89b099c1a5ee98ac4aabb000000000000000000000", .None}, + {.Shl, "a1b0fabe6e746fe0acdcc6179f810c", "30", "a1b0fabe6e746fe0acdcc6179f810c000000000000", .None}, + {.Shl, "7f293f74d8696367a09a5f7b3b6eed", "20", "7f293f74d8696367a09a5f7b3b6eed00000000", .None}, + {.Shl, "f51b619818c5e976f0fa2f35c052e5", "52", "3d46d86606317a5dbc3e8bcd7014b9400000000000000000000", .None}, + {.Shl, "-1fc572fa3b5cfc9f9cb3153813e202", "58", "-1fc572fa3b5cfc9f9cb3153813e2020000000000000000000000", .None}, + {.Shl, "74618b46ef3827013928e9e7eec321", "4d", "e8c3168dde704e027251d3cfdd86420000000000000000000", .None}, + {.Shl, "-1d01b3679444c49f80714aaf950b0a", "35", "-3a0366cf2889893f00e2955f2a16140000000000000", .None}, + {.Shl, "fb592627d64f0ef6899f8eadb7d31c", "4a", "3ed64989f593c3bda267e3ab6df4c70000000000000000000", .None}, + {.Shl, "-16cd3bbfd8116215c98f5f5b2321c9", "56", "-5b34eeff60458857263d7d6c8c8724000000000000000000000", .None}, + {.Shl, "-2372c4d05c394a1d388c80d4bcdc31", "1c", "-2372c4d05c394a1d388c80d4bcdc310000000", .None}, + {.Shl, "-82b806ec5dcf2e40086758419b574b", "18", "-82b806ec5dcf2e40086758419b574b000000", .None}, + {.Shl, "-b2001ee46f7a02309d77188809fd64", "17", "-59000f7237bd01184ebb8c4404feb2000000", .None}, + {.Shl, "d5a1b04966a6a032d3029fffb7f61e", "35", "1ab436092cd4d4065a6053fff6fec3c0000000000000", .None}, + {.Shl, "-9db1b796cff0efab2611fec89fb671", "5a", "-276c6de5b3fc3beac9847fb227ed9c40000000000000000000000", .None}, + {.Shl, "-f4fc439a0b43f15b82f6a70678e837", "10", "-f4fc439a0b43f15b82f6a70678e8370000", .None}, + {.Shl, "-a593b6c4d7051e50cacc5d102bb78f", "2d", "-14b276d89ae0a3ca19598ba20576f1e00000000000", .None}, + {.Shl, "-10328ca66a7d7830d20554fd8b3e57", "65", "-2065194cd4faf061a40aa9fb167cae0000000000000000000000000", .None}, + {.Shl, "-636a47aa3c0b7f6a1966512c843197", "15", "-c6d48f547816fed432cca25908632e00000", .None}, + {.Shl, "508d5929a86191f196509f54510661", "45", "a11ab25350c323e32ca13ea8a20cc200000000000000000", .None}, + {.Shl, "-33a5dc7ec7462562b32bb728ce6463", "13", "-19d2ee3f63a312b15995db9467323180000", .None}, + {.Shl, "-21bcfdadf613fce63e02967b582b64", "29", "-4379fb5bec27f9cc7c052cf6b056c80000000000", .None}, + {.Shl, "-b9695ab458487ebe9f67b8d804dcd0", "3b", "-5cb4ad5a2c243f5f4fb3dc6c026e68000000000000000", .None}, + {.Shl, "-87848efbc5f608a7579459c74550cc", "65", "-10f091df78bec114eaf28b38e8aa1980000000000000000000000000", .None}, + {.Shl, "-c456a0a074644f0f77962d104873cc", "1d", "-188ad4140e8c89e1eef2c5a2090e7980000000", .None}, + {.Shl, "-57632b4719085f32fab22e65795d60", "6b", "-2bb195a38c842f997d591732bcaeb0000000000000000000000000000", .None}, + {.Shl, "5af676fe65b250cf70589aa549cee3", "10", "5af676fe65b250cf70589aa549cee30000", .None}, + {.Shl, "4e24c612eb533fcecc515b53779a65", "22", "13893184bad4cff3b31456d4dde699400000000", .None}, + {.Shl, "4d628d616b733db8bc28563c3081da", "49", "9ac51ac2d6e67b717850ac786103b4000000000000000000", .None}, + {.Shl, "-e080cae50f00d7cfa30fb6da05a1da", "26", "-382032b943c035f3e8c3edb68168768000000000", .None}, + {.Shl, "9aca0d83271160de30418081df4084", "5", "135941b064e22c1bc60830103be81080", .None}, + {.Shl, "-247b2aec569d1449c0ceb2b7cb3ba6", "2e", "-91ecabb15a745127033acadf2cee9800000000000", .None}, + {.Shl, "-8f6586935566a2b9d065d2488a2cbf", "6c", "-8f6586935566a2b9d065d2488a2cbf000000000000000000000000000", .None}, + {.Shl, "89e6658a4d5ffe74917b51e107983f", "6f", "44f332c526afff3a48bda8f083cc1f8000000000000000000000000000", .None}, + {.Shl, "f053afb82928e9b1c0deeba4b01398", "70", "f053afb82928e9b1c0deeba4b013980000000000000000000000000000", .None}, + {.Shl, "9b3c28c07885a3cd6d3677aee77533", "5c", "9b3c28c07885a3cd6d3677aee7753300000000000000000000000", .None}, + {.Shl, "64f9333ac7d6605b4befee8da5184d", "14", "64f9333ac7d6605b4befee8da5184d00000", .None}, + {.Shl, "-a5052ce72ba9f201f3d05adc32666e", "b", "-5282967395d4f900f9e82d6e193337000", .None}, + {.Shl, "-abe5a5940f6341e6446857f10e65e9", "1b", "-55f2d2ca07b1a0f322342bf88732f48000000", .None}, + {.Shl, "-855064e0e247a0065f68e702edffc5", "45", "-10aa0c9c1c48f400cbed1ce05dbff8a00000000000000000", .None}, + {.Shl, "41c885d8586156b2f92d8cc6094f63", "29", "83910bb0b0c2ad65f25b198c129ec60000000000", .None}, + {.Shl, "-27f8b8a4de04b5d60cd1420ae15da2", "53", "-13fc5c526f025aeb0668a10570aed1000000000000000000000", .None}, + {.Shl, "a9d50a5148ecdc33ff283f8dbc4a31", "49", "153aa14a291d9b867fe507f1b789462000000000000000000", .None}, + {.Shl, "-7b5eed436d567cac26e6b5b1506b39", "59", "-f6bdda86daacf9584dcd6b62a0d6720000000000000000000000", .None}, + {.Shr_Signed, "f505a74110c962cf7b56b75335cb51", "3c", "f505a74110c962c", .None}, + {.Shr_Signed, "4851199e761aa96b72973d6b3ff0c1", "3e", "121446679d86aa5", .None}, + {.Shr_Signed, "-8fd2c7f5fb1aea06df586c491bde12", "4c", "-8fd2c7f5fb2", .None}, + {.Shr_Signed, "6507b0c2c98556e4e6048bd0fdfb7e", "e", "1941ec30b26155b9398122f43f7", .None}, + {.Shr_Signed, "243db5b47f31737b9e97e59f464ec1", "59", "121edada", .None}, + {.Shr_Signed, "4ffd272fb7253b7dafd6a18836064", "2a", "13ff49cbedc94edf6bf", .None}, + {.Shr_Signed, "-b474c729be9282346dfd22cf41b3f1", "5f", "-168e98f", .None}, + {.Shr_Signed, "a900b420f50a75ea2c893aa3aea05e", "44", "a900b420f50a7", .None}, + {.Shr_Signed, "b0524c91330420ecfd58873de19f0e", "6b", "160a", .None}, + {.Shr_Signed, "e99b440cc6414dbddc96d824183ed9", "31", "74cda2066320a6deee", .None}, + {.Shr_Signed, "80f1d6caaae98caa26bd2e301ca8bd", "6c", "80f", .None}, + {.Shr_Signed, "-ee920f7c84371690107fe2bd5ead6b", "71", "-78", .None}, + {.Shr_Signed, "13518b580b07f70e435577340cdbb6", "1b", "26a316b0160fee1c86aaee6", .None}, + {.Shr_Signed, "-9990b504a6ab3395a261d903e2bf71", "a", "-26642d4129aacce568987640f8b0", .None}, + {.Shr_Signed, "-7b396462fdebd4f301ba56cec2dc4", "78", "-1", .None}, + {.Shr_Signed, "-188f7ab283b57560e1e3ff9a41bdd8", "3e", "-623deaca0ed5d6", .None}, + {.Shr_Signed, "5410ab901a612cf84a9de47360b096", "6a", "1504", .None}, + {.Shr_Signed, "-ad87b77c53de7af48707ddd1afb04", "1", "-56c3dbbe29ef3d7a4383eee8d7d82", .None}, + {.Shr_Signed, "-ff4d3c26efd1cea754d892e56273bd", "3f", "-1fe9a784ddfa39e", .None}, + {.Shr_Signed, "-ffcd163a5ca59813aaa571a60006df", "3f", "-1ff9a2c74b94b31", .None}, + {.Shr_Signed, "c447786dace008544af6391f075260", "18", "c447786dace008544af6391f", .None}, + {.Shr_Signed, "8523557ac99a3e4ab203bf431fc8f9", "5d", "4291aab", .None}, + {.Shr_Signed, "ac278b96516cfcb52199d268779740", "37", "1584f172ca2d9f96a", .None}, + {.Shr_Signed, "f264e9661ef1b10ca8eda6a0e76810", "4b", "1e4c9d2cc3de", .None}, + {.Shr_Signed, "-917a7fcabb5cc8a27bdc445e7e6c03", "6", "-245e9ff2aed732289ef711179f9b1", .None}, + {.Shr_Signed, "995bd6c7b52f8a1237b623a2f7e6a5", "70", "99", .None}, + {.Shr_Signed, "-d9f8fdff4545c7368e20625b70001e", "3d", "-6cfc7effa2a2e3a", .None}, + {.Shr_Signed, "-dc01543982540e7decfa7faf245a65", "18", "-dc01543982540e7decfa7fb0", .None}, + {.Shr_Signed, "-1bb065907020b0d8c6af798490a5da", "6a", "-6ed", .None}, + {.Shr_Signed, "-df1b32415d5d017e58143442a683b5", "0", "-df1b32415d5d017e58143442a683b5", .None}, + {.Shr_Signed, "931dd9d87ae49ee72925a6e734f9d5", "4a", "24c776761eb9", .None}, + {.Shr_Signed, "cd780f4cd054a2962f3a3081aa5c53", "12", "335e03d3341528a58bce8c206a", .None}, + {.Shr_Signed, "-d85572c8fa834ca54e757b4746f81a", "21", "-6c2ab9647d41a652a73abe", .None}, + {.Shr_Signed, "e5758ceda2c303c267178cea759dff", "76", "3", .None}, + {.Shr_Signed, "-c9a365248e680fd9fe9596f613c2c0", "2e", "-3268d949239a03f67fb", .None}, + {.Shr_Signed, "-b7865656974ad1bc68ebac7766a1d3", "28", "-b7865656974ad1bc68ec", .None}, + {.Shr_Signed, "38186df888ed244e7571c30a6b1a6b", "51", "1c0c36fc44", .None}, + {.Shr_Signed, "613aa19e40ce5f51d5b0024c87d1d", "71", "3", .None}, + {.Shr_Signed, "a3b6542301fae9754a9d1e24ed88af", "2a", "28ed9508c07eba5d52a7", .None}, + {.Shr_Signed, "-1bb55b6f87c385d6352dc8f41ff99f", "55", "-ddaadb7d", .None}, + {.Shr_Signed, "-3093a78469c4b5b528ec784d6b3d18", "4", "-3093a78469c4b5b528ec784d6b3d2", .None}, + {.Shr_Signed, "cee91938fb5537ea2b7bbe6edd3eb0", "73", "19", .None}, + {.Shr_Signed, "-943cdb7c7a33c52bc9a6a65bacc6f1", "78", "-1", .None}, + {.Shr_Signed, "8b7880a8577a851d3375deca364335", "9", "45bc40542bbd428e99baef651b21", .None}, + {.Shr_Signed, "-188a684c20d96c816effdaa3708576", "22", "-6229a1308365b205bbff7", .None}, + {.Shr_Signed, "e2d76eaa2d351c33b23b21e9df7f50", "e", "38b5dbaa8b4d470cec8ec87a77d", .None}, + {.Shr_Signed, "61cd20dfdc10c190aef91627749ba4", "53", "c39a41bfb", .None}, + {.Shr_Signed, "724ea6e5c18e23fab7c6db4f15a620", "1f", "e49d4dcb831c47f56f8db6", .None}, + {.Shr_Signed, "-b797764a1b99d703ca96e1ac79d0df", "16", "-2de5dd9286e675c0f2a5b86b2", .None}, + {.Shr_Signed, "-6aafdd33ed0dc8518409eeda9bc1fb", "7", "-d55fba67da1b90a30813ddb53784", .None}, + {.Shr_Signed, "91f20f0c86fab55530f07239f9d02c", "75", "4", .None}, + {.Shr_Signed, "-e252360e796ed727062996e2d11f1a", "39", "-71291b073cb76b94", .None}, + {.Shr_Signed, "c1e3ebe78066b7980932d7b8cc132b", "42", "3078faf9e019ad", .None}, + {.Shr_Signed, "f69ac1092893d804a06bbd212a2a6b", "72", "3d", .None}, + {.Shr_Signed, "6e81a8337c70755772f0e3949cf9a4", "61", "3740d4", .None}, + {.Shr_Signed, "aaeb77fb8862c0ac6abccf46544c11", "3a", "2abaddfee218b02b", .None}, + {.Shr_Signed, "2ab104f087c35cfbad828d429b5645", "47", "556209e10f86", .None}, + {.Shr_Signed, "-5f3b4235d84aa3449fd542ee7b5448", "c", "-5f3b4235d84aa3449fd542ee7b6", .None}, + {.Shr_Signed, "-1d7a5737f0d5b6c659d7de8e48f6a4", "5d", "-ebd2ba", .None}, + {.Shr_Signed, "bfd6cf330eca8c286e5ddb9979e422", "5e", "2ff5b3c", .None}, + {.Shr_Signed, "1e7bed8f118e42b80b185e4a43479e", "42", "79efb63c46390", .None}, + {.Shr_Signed, "-eda1c10db1c3d20ed3ccbe5073b174", "65", "-76d0f", .None}, + {.Shr_Signed, "-813852d42d6156b667ecc5fb76486e", "74", "-9", .None}, + {.Shr_Signed, "3cc47d3e7bd2d845266bb431d59e30", "68", "3cc4", .None}, + {.Shr_Signed, "-b557e9f5baa60645541863b6838b9", "46", "-2d55fa7d6eaa", .None}, + {.Shr_Signed, "2dad05cedfa197a7e80602bb4d6523", "1f", "5b5a0b9dbf432f4fd00c05", .None}, + {.Shr_Signed, "44bc2a21d351e1e57f5d5beb400424", "60", "44bc2a", .None}, + {.Shr_Signed, "-911167d451df8e3bf5f106a5c2109a", "44", "-911167d451df9", .None}, + {.Shr_Signed, "-2e4b89b7cef88c3ff79683a9d773a", "59", "-1725c4e", .None}, + {.Shr_Signed, "-5aead6eb00db1009a88f20aeab851e", "48", "-5aead6eb00dc", .None}, + {.Shr_Signed, "-4ca6b848bfd975e9a47946d3a8c0a8", "76", "-2", .None}, + {.Shr_Signed, "d15699410818a32940e3bc484e0d07", "15", "68ab4ca0840c5194a071de242", .None}, + {.Shr_Signed, "-ad118f38d1d39c88be50c65761af69", "51", "-5688c79c69", .None}, + {.Shr_Signed, "3935dc66ea50694532d66f656e0e84", "3c", "3935dc66ea50694", .None}, + {.Shr_Signed, "-f20a74ce7836276118f8bd25cfc598", "2e", "-3c829d339e0d89d8464", .None}, + {.Shr_Signed, "7ff8c319a6ee6fa15d95d980ea325f", "65", "3ffc6", .None}, + {.Shr_Signed, "-a127d639b643aa9fdf662ed8d423c2", "9", "-5093eb1cdb21d54fefb3176c6a12", .None}, + {.Shr_Signed, "cf75f41b2395138bdbc3dffe1ad870", "61", "67bafa", .None}, + {.Shr_Signed, "-e25fb42c533dbbe15560e764fd5e8d", "5e", "-3897ed1", .None}, + {.Shr_Signed, "-b79c5224b07cf3da60331ef12fa4b5", "47", "-16f38a44960fa", .None}, + {.Shr_Signed, "9ff7848afe362c320fa75cdb760e27", "54", "9ff7848af", .None}, + {.Shr_Signed, "6853d26bc29f2145b85a05499093f", "31", "3429e935e14f90a2d", .None}, + {.Shr_Signed, "4bf09639b556660ff7a56707cc5557", "1e", "12fc258e6d559983fde959c", .None}, + {.Shr_Signed, "fc89fe25139751e80b1192cb3fc94", "53", "1f913fc4a", .None}, + {.Shr_Signed, "fb9e2faf97606c822ca65a81e5e4c3", "37", "1f73c5f5f2ec0d904", .None}, + {.Shr_Signed, "-fabedc7f33180ade07ed5ba438e175", "44", "-fabedc7f33181", .None}, + {.Shr_Signed, "-f4607949c424de1c173d39604cd1f8", "13", "-1e8c0f2938849bc382e7a72c0a", .None}, + {.Shr_Signed, "d2cd7805a291a96c3d5311fbbb4a7a", "48", "d2cd7805a291", .None}, + {.Shr_Signed, "4c44d6eb617ba09d5db2d428e6fe5a", "54", "4c44d6eb6", .None}, + {.Shr_Signed, "b9362fea06abe02a863ec54cc4a092", "e", "2e4d8bfa81aaf80aa18fb153312", .None}, + {.Shr_Signed, "-77b831009229e412861bcbda19775d", "63", "-ef707", .None}, + {.Shr_Signed, "76872f45874f717552b85c9726525", "1f", "ed0e5e8b0e9ee2eaa570b", .None}, + {.Shr_Signed, "-7ab1f10606483ebb2d314dde778cad", "60", "-7ab1f2", .None}, + {.Shr_Signed, "-e0047609aa7c793b194e173ad7d89", "3", "-1c008ec1354f8f276329c2e75afb2", .None}, + {.Shr_Signed, "-9fff37c79a2a8d8e97cefe8e8baf2e", "62", "-27ffce", .None}, + {.Shr_Signed, "874f29f822671e78612adef74c6b13", "6", "21d3ca7e0899c79e184ab7bdd31ac", .None}, + {.Shr_Signed, "74d3eff7aafd124da395a9fa7343d4", "3f", "e9a7dfef55fa24", .None}, + {.Shr_Signed, "-18210572b61d9fc4ad8eab130aba1d", "3", "-30420ae56c3b3f895b1d562615744", .None}, + {.Shr_Signed, "-56d0a199ff8af06e9196e936531394", "65", "-2b686", .None}, + {.Shr_Signed, "-126aa9639bcc77a94dd2f4e311fe3b", "1", "-93554b1cde63bd4a6e97a7188ff1e", .None}, + {.Gcd, "8fff185f6107d80881ff3363ef088d", "5371c850e6a36895f5c5d610a9db7c", "1", .None}, + {.Gcd, "-9acba82db6cd4a903b19679adcdcd3", "ef98270815e36957d9a046654ab7fe", "1", .None}, + {.Gcd, "-ffa4c58748eaeb76ba4cc598e07edc", "4c21bba4a4f89c359e56ab3a2a0bbb", "1", .None}, + {.Gcd, "8c3237e5f62d84dc89f9b095d77887", "3a0f690410b436c3fa3bc746260d0e", "1", .None}, + {.Gcd, "-4cf58721af510a2de14716c6f86450", "23eb39998a18f6a68d78fec8d43ef9", "1", .None}, + {.Gcd, "58c9e3d62b1c29115545ffd48474a4", "70374665c43668c65c22ffc494c159", "1", .None}, + {.Gcd, "cfb27c85faf89c538b831c6e1b3c21", "ea5a66ad684b3fb311b430fe650b3d", "1", .None}, + {.Gcd, "-5cee8770e63d97626fde1b3eddd466", "f0c6eed1552f27a86d596737c5218f", "1", .None}, + {.Gcd, "-dd451d361443d6c21787018b075234", "59062f7f888cb7af697ebb942e989c", "4", .None}, + {.Gcd, "79b1171a84e2d40b488b5917054a2c", "754cde4a9196b9c1c923eb0f158b35", "1", .None}, + {.Gcd, "-81ed095a0d8c99dab75edba285d79", "f630c098bf168b0620009fe3118228", "1", .None}, + {.Gcd, "-b0d592ba341ec9c92e7dbedd624a71", "dfb4ab3b8f0f45ba01e516c16f2cf1", "1", .None}, + {.Gcd, "-cd0ddb13a997b700ef45a4f3328920", "287677f46e212cdbb0e783d7532cf8", "18", .None}, + {.Gcd, "-c75632758cfa10de39779d7d023dbc", "4e7a7a3e793f6387d7332a8d0f36c4", "4", .None}, + {.Gcd, "807db04912cd9211518f877e0f1245", "993c9edd89480cc85e8050f5e2cecc", "1", .None}, + {.Gcd, "-a20bac5407d78a789fba2d4dfcf238", "721bbe9a756196b077adfc49c00446", "6", .None}, + {.Gcd, "-1a1a72ba37882b0d45d52d3c83e93b", "b5dc6d94ff76803daa9064f48254e0", "1", .None}, + {.Gcd, "-1170b57406809fee6642e0c1fb1afc", "77463f38b4d9c7cc65e9eb7f3695a9", "1", .None}, + {.Gcd, "-7832b08d05a3e46d7d4db79dcece43", "63b1045c955f391be8ddafd45a647e", "1", .None}, + {.Gcd, "679a79d2d1c275ea401cc916d516f1", "ec7ebdefe590317c41ba0c8e4c31c4", "1", .None}, + {.Gcd, "7d40599f86e41c74d78da6d740c5c", "f10cfb2bd8ce167f7ade361eb985c3", "1", .None}, + {.Gcd, "24e99808df24240a575b426407e258", "81a235608b5b719e43687958b05697", "1", .None}, + {.Gcd, "-8ec64c42c82e842f6e5b9cf4a4534e", "65505aabdbe46126ccdeae7fb9c770", "42", .None}, + {.Gcd, "28412d3e42806215afc23bc3f17e1", "27153011d37f4287f5c1cb0f9c1b8b", "1", .None}, + {.Gcd, "-bf54738920158140f0b432a0c3fdf0", "490727eb7b1a573e550c16c62eb0d0", "10", .None}, + {.Gcd, "97cd608287346c0d2bd688b49ce5cc", "90787853b6fdbc8161a65a6ba3a417", "1", .None}, + {.Gcd, "-f32ea8adc2139e7e36a2b49fc5eebf", "b90f8edcd61c10aec27f1720ffc4f1", "1", .None}, + {.Gcd, "f4ef41bbda6dd3c87027418bde074", "2b5a8b0684e2a387bcf316968658dc", "4", .None}, + {.Gcd, "-dd4dc8c6af5a57c572ac60f9544e5e", "5b58f200eb271e3319c220ba408c48", "2", .None}, + {.Gcd, "-199872febf7c89c3d9964fa579c45d", "170d208d0b1129c9c702a1d43a3ba", "1", .None}, + {.Gcd, "-2e3f9977cbcaa5733a961d51941c74", "d408c476d7c1d2d9bce208d4d985d5", "1", .None}, + {.Gcd, "-cdd3d857726af67237e9063890cc1b", "cec4456b4b1bb36ec7268904ecf2dc", "1", .None}, + {.Gcd, "-b75304ce57f6d3531505d26d00b782", "d278f3c0ac85fa26607c37bf992434", "2", .None}, + {.Gcd, "-534ff7eefaeb10877c78c5ad128377", "4a690bcea60798800026f8b9b55032", "d", .None}, + {.Gcd, "8c5ca76a1a3cb6bcd4811e0533f01d", "7d6cbebd45dff0ce2bf3dc6391cc3b", "1", .None}, + {.Gcd, "d05cc2b5639c740cf9241244cdfde8", "ace1a1fec830d6dba80d7270da6f7d", "1", .None}, + {.Gcd, "-c4bbcb45dd163fc8367b7eb9a0e3ed", "6752a4bc501d744f0df0b439461418", "1", .None}, + {.Gcd, "-e4816abad8651f00f264efdeee05c8", "97638db5ab0b5cff1869930e5961a3", "1", .None}, + {.Gcd, "-2ba5d511557eb142c220d190cef594", "5c7504e016abb9439c9c7822831ae2", "6", .None}, + {.Gcd, "bdc9610c5bf313f42979f904787fd6", "2983c41788ab37fa455a829ccbd393", "1", .None}, + {.Gcd, "7d7901fa8e74e75d80faf0c12ed9fd", "3354ff9dd960527f71209362bd3410", "3", .None}, + {.Gcd, "-aa384b6fb616a72cfc7e8755de373", "acc168d1ead5da29a0c70cbab41648", "5", .None}, + {.Gcd, "-82780bee2308594f88fc196c2f601f", "aafea75aeceb38f597f92f1d1b1889", "1", .None}, + {.Gcd, "c48489fe0cf469b770d7efb79ab333", "68d6cfdf8a0c39861590e7cde260e2", "1", .None}, + {.Gcd, "-b626981d540fa942b1d5b09cdcf9f2", "783e356236414870871f1d6b297a53", "1", .None}, + {.Gcd, "84a230dd4cce490040ed8028b9c5fb", "dbc3b6e1c8722c0800db55f215c540", "5", .None}, + {.Gcd, "-6d8a2c582d9b9c78826f2c0295183e", "9a8353fa4069b804c160f2dd81dd35", "3", .None}, + {.Gcd, "2eceea848654cebaf2c3532ee33eee", "754c1bc016df2b55728859dbe55f13", "1", .None}, + {.Gcd, "-f47af7c2b5e7d3016b33c1308c7267", "7b22d0faae3e007cb0a08140ca85c", "3", .None}, + {.Gcd, "-d95deaf3069dce7d3210b8bb39164a", "699104954b690bf5b37f80ebaf4095", "1", .None}, + {.Gcd, "1dced0c0adebd6e40899d393f0d1b9", "231746312e77b56885a48f5c7587ea", "1", .None}, + {.Gcd, "-1b55a6de342fc38f0ebd5a4ce26f40", "b224585169743f3b8138c6a60201ee", "2", .None}, + {.Gcd, "5fc42aa5d99e797add7f1e3c6a827f", "d178159dcc505db5b4d3ee98a27681", "1", .None}, + {.Gcd, "6d7caaa59766746628fecfe5ef11b0", "3e3af45e3471c711f736b3e80fe96d", "1", .None}, + {.Gcd, "5d0ebc5cf857f008f5346abe2bfb5", "62950fddb1b24c2017f32973fb29d5", "1", .None}, + {.Gcd, "-7a4936de4435fdb989f98d8c834e3a", "b4f4bc20511b730891d41b3c78bc4", "2", .None}, + {.Gcd, "6ce419c3ba5bee4fec1e2375bff1f4", "af4347ba9e307e98402a05295cfe37", "3", .None}, + {.Gcd, "ddf9a56ab36f4ff13026cb8e04ba7d", "a609e1111e074708b1f8572cadd44d", "3", .None}, + {.Gcd, "-9044df5cb6a3ed1c232732c7166302", "decbc1dc6b2372c72c94b7f4ab4dcf", "1", .None}, + {.Gcd, "602b182bd0181086856a91ef0cf2ed", "f0c1a77d8126abcfaeeec493f8a493", "1", .None}, + {.Gcd, "-3803d07c8f8fbd9a01d1640e022fbe", "e897a1368f6a09017175fe2efdfe2e", "2", .None}, + {.Gcd, "3b28caec5c52ae7e72f7d0effb2fdd", "67c8e2d766b144544ab04fcc15a5e", "1", .None}, + {.Gcd, "2e2c92823cd7afcf5355b8f4feddd", "804d7d72204534eac3df0e6222201d", "1", .None}, + {.Gcd, "-6cfae5008c0283168ce19a27c3440c", "a5b9bb2b6792c8f5cfb4e74db41ddf", "1", .None}, + {.Gcd, "af1ca49fb0e36f2109d83cb3a66ab5", "8579f32e9386ce39e2624705cd96f9", "1", .None}, + {.Gcd, "-4bc5915bc75c840626e8861636a44e", "353d5376d1f11f8fac99f2a5c25610", "2", .None}, + {.Gcd, "d744608b698478f74774517833b9b4", "566d3f9e729b0fb6656758c5ef23e4", "4", .None}, + {.Gcd, "29431bd9736f166e47082babc83dd8", "c77c4a14396f9f59e4f2b26fb09f5e", "2", .None}, + {.Gcd, "257529ca95ad3acc048cbea5782d64", "d2df3c7055f51aca346588fc56535d", "1", .None}, + {.Gcd, "-97950ade4fa835f7515243c7910b92", "a74b9953949f898a8c530ccefdf9b8", "2", .None}, + {.Gcd, "2b218cf429d534930bb0cf227ccd21", "a5534482723abc574fa731cd5e2c62", "1", .None}, + {.Gcd, "b0ec89f5d1f31fa28469777e6506ad", "d103f321040f7158a0a883534db44c", "1", .None}, + {.Gcd, "f666f06656d0731684705acd290746", "14a4925a6ea0182c8aa562555c2ea", "2", .None}, + {.Gcd, "9123848874f3b40fa1af3ce2bd7461", "2eccf53149bfdacf9230064438c27a", "1", .None}, + {.Gcd, "-df29a0ee74ca389c23c8d89d393c5e", "400e5acc9972660e4d48af01901543", "1", .None}, + {.Gcd, "10d54577ec9eb1e60e26f5cbe7f206", "bd1125e7cc92fcac0172b8ac9a4c6f", "1", .None}, + {.Gcd, "d6e858d998125cc94766c6d768df8c", "850c33954b7ebb5441bac7a9992859", "1", .None}, + {.Gcd, "c4cd3c88f617308cfc33a8c784561d", "ec66a37fe0a9da0d35633f97716a55", "1", .None}, + {.Gcd, "e650b984babd887084fb614b654067", "13712f7c5e98032650f0539e8351ee", "1", .None}, + {.Gcd, "-7e5c3b6d268a95ad3fc99fe8e1ad71", "d7bc1bb0b65e20d0f8bf2c986a020d", "1", .None}, + {.Gcd, "e04e63ffe3a0f4c1f606649f2798d7", "c6e35f19291e1ef8bd087213c9c25a", "1", .None}, + {.Gcd, "-1059d76aa4bd4ba59c5682dc0ada53", "fe6c28d5a13bebea29cca5770d539f", "1", .None}, + {.Gcd, "33ad8328efaccfc9db78ff693a14aa", "15cdd2e82f4e5b323fe9fe995fdf80", "2", .None}, + {.Gcd, "496a3672028205426ddae004b546ff", "d452a8f8bad06826d0ffd80afa550a", "3", .None}, + {.Gcd, "-68a3dd5fdf10663f268d4318062b1e", "a3e02abf776053a872f37eade7ff6c", "2", .None}, + {.Gcd, "-b95e8352367e477bdfe45b6d7b59c6", "6c175f9331affd06d843c7385120ac", "e", .None}, + {.Gcd, "27d43b0a5aa44da3b6002437e0257f", "3945033458244162bec43ead843c00", "1", .None}, + {.Gcd, "-73d4a90bbe33f2279f9945a554499e", "c13524c80ec69aea10bd7e9c555496", "2", .None}, + {.Gcd, "-695a8efba3e403a3c37bd78dc5c2e3", "20f8a05bcedf6b68f65f86e1d5a423", "1", .None}, + {.Gcd, "cb2249c6c7f6ac3b850838966fe392", "304465288fdb70cf3acde9fd752da2", "2", .None}, + {.Gcd, "bb2716aca4b0f71f81845cc3a57e82", "c9dceb3715d23766c0fec6bdde3960", "6", .None}, + {.Gcd, "d736eed3b6a31f7142b65cd4a49187", "45d986048d564f093cc3262c997d1", "1", .None}, + {.Gcd, "-7d5c01bff51874f85fed3e82e5988e", "f2f955ffce82e7e967a03e95bae6c3", "1", .None}, + {.Gcd, "b5d52913a1022662df85af07d1f65e", "312a995b3a30381e3e74be43611c78", "2", .None}, + {.Gcd, "4c8a89e780fbbc23bc71092299b68b", "a2f1afe4c48c5b7ecada9d05fce2b6", "1", .None}, + {.Gcd, "a70b96df3f876b3f3070d7b3dc80e4", "fbec75055b71dafacbc4582e1de4c", "4", .None}, + {.Gcd, "-3eb89d15c5beb79c7d8ab455ddf9ae", "60b3b80189f7089920d1642a2acc24", "2", .None}, + {.Gcd, "-ba4215cbdbba9eab09681e10acc358", "7e306f1f360e28b63408f978aefd00", "8", .None}, + {.Gcd, "cf7db37e850efef5a937ca0758c6fc", "91ec27caf6e3b4f99841363a4defa4", "4", .None}, + {.Gcd, "6e993447fad6138d69125cadcd5128", "fcef1427fc0c97bb23abe343c4d573", "1", .None}, + {.Lcm, "-330184adbbafb54d09634c8b077bdf", "ba7a01c6b710ab086b6faf63d6c565", "2527697a0e53cf95663e8ffed8c47edec517f491f59f40e68fc965b079fb", .None}, + {.Lcm, "-3f90fbe8db7fe9a27b95dea402cfc5", "-2915cf0d7521ef62d8531610f83290", "a33a2a68865427b8f43ee7fa217d7fa1458873b9a615c8b92e8650158d0", .None}, + {.Lcm, "dd3772aac4b58eeb0338659b1b1304", "-adca2d783ccfb18943c0c0c133ba82", "4b1696c443b012cbb3c409e00b66d7f3093c6a66200622b384829eae4804", .None}, + {.Lcm, "ed2f0e6bde667f6e6ff61de8ab784", "-48c00c40cb3f41e8cc1790935f2676", "21b39559b2199b17e11b83031588e152ff65fd8bd2cc918c8a00895176c", .None}, + {.Lcm, "22ab1f0c25e72e3e407c5d63ad6975", "316b3637044b9110581ecb4e8ab43b", "6b145ced93a3b5893265ac52d2765914b9db72aac4a1c1b3aff662f91f7", .None}, + {.Lcm, "de956b68f2806389a964cd51658259", "ca864b63cb80e139e2381a0008dcc3", "b016aa8393791115b2a9ee60dab7ae5049ec2ac34feef1777a8e4f1ec5cb", .None}, + {.Lcm, "2a092f45b7c2fa6b4d20f0c5adc0b7", "c74e66d05d11dc8dd977352d632343", "20ba036d78ab02ee5a9fab6c9f9624982a24824d174188397dff2f9774e5", .None}, + {.Lcm, "-3816677d5e16adfc4dc82781887a82", "-f3b1449de3999ebb0f5c058e0166d1", "35641ac21915dfa4575c4717a862ab98e6b3c596a9f0629077e3b7bdd022", .None}, + {.Lcm, "591337790d66ee4e6990831c4c037d", "-7f44b8f4095e0b8c961af1e99dbc5b", "2c4871fa833fe69952a0f09e4cfa344f4a93332a52af1df82bdaca3e096f", .None}, + {.Lcm, "-bc8e6c5343fbd659f567af16983a84", "-e0054651892d3ab50c4860e5eca257", "a500815bf8d542a87e16198d43023a7814a99754f52e6e5d1afb08736adc", .None}, + {.Lcm, "-5a2871f6ebcace46bdbd21774a5b07", "-a70981fea8f119a94b263571b325ad", "c394b8ad6240f75e9200453637478dc1bd57eaa1f9400f311588a3e727", .None}, + {.Lcm, "-34d3ab54942396cf8798b0200f8f9a", "-fe3683b6ca2cc5ae6ae886e314a0a0", "1a3aa1e90bd973b827fe9c0b18339e326a9dc56fa7dfc935452344c10020", .None}, + {.Lcm, "54127a249bef69c28b67774f3597f2", "74d6dab381744268da639174d611c8", "66527c4e5737c076905f88314876a8a676cdcc646a783eefbdd84e04bd8", .None}, + {.Lcm, "-2ebceedac57779fa1b18166bd03f90", "-aacf0368c2e668a656f79f8d8f512e", "f97a100e094ecd3ebe7e3676de2dc0931ab31c25e89f7b861750a7bfdf0", .None}, + {.Lcm, "-86430be2b1b1e5350ad12bfa406ecd", "11b920cfcca1d41680976dcda6db81", "94b8b7301a4792986c2e1900fa844a5073a4ab5203a6897fd093b2f344d", .None}, + {.Lcm, "8f4fe2fa409ffb60cf8438b576853f", "-6e1af14199b6608b74792c98fc9994", "3da368b383325e231a8088659ab74cc6b06d681f1a299c7502d9502baf6c", .None}, + {.Lcm, "-73b554777c40793c1156cc5fb365df", "-b8266bc4be938502b154908beeeb15", "be3f4e7bbc26101faaba1888f229644bd991ce29c0e0df0f0bc54ef949d", .None}, + {.Lcm, "-d3669fe660c1c45d6427b07ab0557e", "-b00597d384d6711a7aa7487b671f9f", "915b2c4fb59dc85fb3f8f27e4855e23e16510b548da3f86058ed7d915b42", .None}, + {.Lcm, "-dc0f946365f84cf59d001cc07dadb", "-c5748dda18bc0cd4ccd0d6075c42dd", "a9bc2e2fc9c47fec6b6aae58a9fc9a29a697b10311da8497507cce8650f", .None}, + {.Lcm, "-6770b7031960e7669f3570096fd33f", "8d4cf21ef996f349b1d8c713fad04f", "39182c181af5e8edd07a9a0180f7e7d65db4b75cdda43c626718bdab6071", .None}, + {.Lcm, "-20c93a9162317828ae93d2274bc2de", "432f18a81ebc67e65e3ee67e6832a9", "89ab26e32dfc0174c965f7ff925fc5c2900480b367d199cb98d2b43008e", .None}, + {.Lcm, "64e3cfa428b8ec87e7c0ccdf914339", "381a8886764284bfa86d4bf9c593de", "161c4a5d03bdb4d7817499091eeef82d865487735a1c8f6121e8756f066e", .None}, + {.Lcm, "46a2297aa7b80f105f4cc59dbf1b9c", "-debf057271690a8a5c8f5febd6b56c", "231e79680827876fa5bb460a19e8382dab5aa7b1c819d0822acb6699aec", .None}, + {.Lcm, "3bb7ae73b820bd1033c7e77de89d91", "-bc5ffee65afcb8d56c2d248557a8f0", "2bf148bcb38072e82f220fd7308c0f14623723e39f7916659cf492c1dff0", .None}, + {.Lcm, "-341f8aaa546353bfae7e3add83987", "-930eeb1d7978174abb388a506c24a3", "1df12638585e1359f13be9e95d1a8f5dbb5070da61c82801e628db79cf5", .None}, + {.Lcm, "5cc6f6f287ab1a22ed105a37830fc1", "d2e8f8a625c3d2a0622ba6d798c75a", "197a8c553c56b4422fbf20d7d01cbe8dadef0ee2b854914083b047a3859e", .None}, + {.Lcm, "b31fac9de33c82a3416df91efbf7ef", "-b4478bb616e491e86e5f7886ca7952", "7e2454e97ed3ab674e15d86cc0754c5069e11c9924cd8c8a3911c17b618e", .None}, + {.Lcm, "-55d0f404b4a8a53885c07322da2662", "-db8ec639407dcd1e0f18001bf91e49", "188889b36502f426cbd773b0f42d797650cf0a952cb7c4e627b7640224a6", .None}, + {.Lcm, "b338062e8df573ff2a15f913d5488", "e9463f7ede34774152c7e6a411e518", "1469e56cb552e0f8944165dd057b69e1180f13d3e7ed7dba6e966ecb298", .None}, + {.Lcm, "27a7931112811f6adc8777d205f896", "-daa3760893508eba11d104988b4bd", "21de0537bf78e7f4a266c4a02b14d886f3719d18108ec7a119116e1febe", .None}, + {.Lcm, "2f6450fd63599e1b6b54efd102773c", "-c3332e976698a3f1d3d222f42f22ff", "2422e34d32df95c7c6be2092c1a14d40b7c9a4a6bd9447063bb4994ebcc4", .None}, + {.Lcm, "12540fcc28299f68ce8494fe47d4de", "-65dd21cec756555174266315d63e97", "74aff38d30aa5e965f5d8c1b1702961961f18114de5954d03d3898052f2", .None}, + {.Lcm, "-562cd68a75809b227fec9dbcd4c906", "2a7e707f4cbe351632267ef101783a", "726f59163aea3d7d4b805b864e64844c294b49244284082b7a3fabb2dae", .None}, + {.Lcm, "-defa9a061783c589a101c88f1ceb89", "-5456fca55338dfb84abe2555bd4fd6", "187caa42cf2110979fee781fc94df9b69c1ba523dcc072c61f0efaab0e82", .None}, + {.Lcm, "-be3fe938d990740ac37cadae00360b", "-fa121fb4ed4a9efdd9d401799fd259", "252b2d299f65c577db3943cbaa3310d512af74af68bbd54942f77c728ff7", .None}, + {.Lcm, "215ad800bfeffd32da262e490badeb", "-85b5ed25e7aa93434801403ac8992c", "116be65926887f7267436f130a9a0333960fb6d2f99728b755e3a68b5764", .None}, + {.Lcm, "-a466d5aa18cac96f484087936ccd6a", "8d97c0677d1f08d28bf404dd1d4a4f", "5aee17e64cf5ff0986b6d111a66f9f90ccb71c5e91bf119df8c3b8f607b6", .None}, + {.Lcm, "-5a74ef547f4c461e78c47ce039d8e", "20683bccea3d2e9322e44b9927e1b", "b73728d2558f181946361da64fbc5bdfb8599fd02924c9b9bfae981fa", .None}, + {.Lcm, "11e8f38cad060e8f097d50abb82063", "-4a97d828a9539dea5b9473488917dd", "537f5edb7bb311b2be0f72dfb9c810d72a2350efd06ad8be52ff5d7da77", .None}, + {.Lcm, "434dae6dc9f4fc57b099d1fe2f999d", "11f2e850db01668dac4e4c3995acad", "4b80517d62002294ba57177ef498de66a6871bbec69d7ee05351ec14b19", .None}, + {.Lcm, "fc57811500b2ff76e2d63967a790f", "83abdc9b723839a7bf5f8ac0acfa57", "81ca2ef564e2a81026c631b6a0b990f722fed0f58368aac75f653ebca19", .None}, + {.Lcm, "6a668bcdd1d256fab6564b591f7863", "3531e395c74d6f9df95c18d13b2e9", "75ea7b88470d3acc8d0c5fbd1fb67af30acd1233d4d8e3c0f1273b7809", .None}, + {.Lcm, "b57475e61fd7ea25e8c1cb2b4bf0d", "4f32a7889e2f1a01a1d33f57c3a5d7", "9a86734728657bf75a0e96f8a145fa9e6b7f03d8365ae98a2a69c75e7", .None}, + {.Lcm, "f26d207d1ed04ad4b37cbd9a2e7a89", "-e40e2a7fa94bd911ea463c9a92f7f9", "47fcde6200b0e70c30e9507a1d90fe173e06a602b9eb6725c780b3db1f6b", .None}, + {.Lcm, "-3cdfc9746afbecc929b017d525dbd8", "-426f1b8b35492d5c7a5bf4c0642140", "a8813ae0ba87cb8b60188405a532f4b5c45534ab8a78e4eb6a75cc9340", .None}, + {.Lcm, "-9efe4f7f7f6b6886d75bc4500e3752", "b30ba7eb1931642b6c00eabdcfa1d6", "37998766bcc39e41e46d9ce150c2e9e771b9ac3372ea4a957bdf10fd6846", .None}, + {.Lcm, "-70a3120da6c7297a43bc847ead33fa", "98a0f99d0f2ecbcc1ddb0b2512e392", "2193d33b8d66fddc56df2993d7a16a16d819df62da35f55285294eb9294a", .None}, + {.Lcm, "-dfbfdae3e824fdbed779efb98c59d5", "d290b87c0ae6028083cb633b097bea", "3d589f92cc23186fe65a7ec79da17e4d4d3543d22e2f0214b76d6da57be6", .None}, + {.Lcm, "179ce4be5322f0ca2dfa0d087fbaaa", "-d7d3b59ba0316cdc37dd29375bb992", "9f4259654984609c543ae955ef3853eb80bb2f1ee3f854092278395a77a", .None}, + {.Lcm, "-b4c08cfb0b30ec40e1a08f0dbb8817", "46ddecda5ddee4498e9c028884ac11", "3209580209fed94f3516e71aaa9650619fa5a828f8b71e118fe64cbf7d87", .None}, + {.Lcm, "-4c71ec3a4592aa84faa29dd49decf9", "3d47d0746e7c96fa92051600205884", "124c9721bb49c902b4ff9e1b6b8bef37038b3846dd10b811e89b8a03c864", .None}, + {.Lcm, "-b9a3c5e36188f402fcefa584a01fa9", "fcdc4ebaa7d035265bde0f2a5c35db", "b75cf8a12464828411acbfe05f9b1590dc3b3c419ae52b259eb1b6451293", .None}, + {.Lcm, "-e8840b401312818acf5dd042ee8b37", "-10ea1f867bf2c73eb4c05c4c9afdc8", "f5ce6086cd1300e53d8096420eddaed1092834f8038cfae79721d081df8", .None}, + {.Lcm, "88161dd30ded3067163347a10d3455", "501ed3849f0aa61c7416ae7791d8c4", "2a974c5a2d9d7bea47939b7278272d6a9b768217d4cc9bafee4e9968c914", .None}, + {.Lcm, "-693310b64b281b48daf6ae18e491ac", "-9d2dab439f056d6d6827ece9d47757", "4097159aa202e50a2fb6d7bb94042b34b2fd59d8af6376b0e72ae3d47574", .None}, + {.Lcm, "15528023bb4e970bca935db9f8a0f3", "-9cb187d311c622e36a3d637b9f3392", "d0d0f7074e5d5d4d31f4eed78d25d5ee2aa01c4ad9ceb92d33a4fc93396", .None}, + {.Lcm, "-841907fe87cd16be5ccff76ecb85dd", "99d76edf8a24ec1fffce6595fbcc7d", "4f622002f0738094362a8ce1cb822d67eb002843934a6a4774c228bb78e9", .None}, + {.Lcm, "-e647b772d9b07e9d0418fdc776c724", "-4f2fe75f3e4862cf70f82f8b7af42c", "11cece39e09be8008d2c81f802666e7cb394d7ad0ae2210f8a84bc58228c", .None}, + {.Lcm, "-8ea035af47b3325ddea769a714a816", "-e081344b8504e79c6a3082a568fe5", "7d142ad70a0339b78812f710c5223fe38a1726e1390b1468d0b12c2a5ae", .None}, + {.Lcm, "3aac26076a5688a3433363b945d7dc", "4cda98ce179f9b77e762682f16587f", "119d34e808674b53c4fa3f96d86e64ad1006836b4d1ede1c6e2adcc1b624", .None}, + {.Lcm, "87bf57ab73069588273b3a50cfaf0e", "-e9876339555819e001456614ff37e8", "3dea78a7d66edc6a3b4b2280c1b8e68be339f770856b3d55392b28e25358", .None}, + {.Lcm, "-c9f51b6bd08d28bc5224120bd36822", "5c63c9e49315985406192384d3548d", "48e2ceea1e813c04fb2a9f6cee3a71ffeb652381a47691eb19683da182ba", .None}, + {.Lcm, "f18fbe8aa837eedbca0ea3638186af", "dc6dcb7d96f238c7c261bbb0c51b1d", "cfff21f6c7507749606beb91004b86383c9a7e5f29faaad7341ae38bb6d3", .None}, + {.Lcm, "39834d43d4c5ada8c6b8ce099847d1", "94a3c058400c6487c674a5f1f67f16", "2164b27bb6abcd36eaed0af1ddf602130fd8ec747306961eaa1d228cdaf6", .None}, + {.Lcm, "fd88810809e233cc58e9cd44535b23", "-90a18320f59a23e714a4b6c8384dd7", "1476642f4f226d5fc3442cc37f3319c26ecb5aac5b9da66132773f707033", .None}, + {.Lcm, "-dfd07e9f3ce81dec27507402bddc24", "8b6ac16cf011e6d42508f82ccbb68f", "1860b53cdd0ff790286ad5e20c5482847271c263766ef6b9ec00da38b66c", .None}, + {.Lcm, "-a5fe411c99b6cb54946924c2870e3d", "-66dfb2adbfb91b56af0cb775f3bfc6", "42b45a478f91577f35dacb97b9cb65f3997dd979033b5cf128e09cfb862e", .None}, + {.Lcm, "-c9e67c9ecf20deeb21e41f0fd307f1", "25589535416d2058842ff22b18013f", "9d1644e507597148b2e80fc1ad8c67d3b0b519b736714abfb36fb2fa1c5", .None}, + {.Lcm, "-535e402a56607f2b61164c57f81b7e", "b02f56621d7e2987f259907361828b", "3960368c8065bf8d65e5bc539511a98dc20c9609859fc5b5ee5bc66ae96a", .None}, + {.Lcm, "1e1847fa3fd6671296b048d658a133", "-eac07e0f5e4bf8f5180f3d54d76562", "1b98d2d27bf916e8df86266d67db82f57f2f27b41717b515b7ee235bd486", .None}, + {.Lcm, "72a242ebfd565118679e31b0169a4f", "43413b69f777c4505f9bf53de6bb01", "1e1dad519a02f038cd4b49084244a5dd0e4bc962f231e8f00380a8c84f4f", .None}, + {.Lcm, "-153cac3e309375bffaeeacd86f2648", "89f473422f592afdaf30c2a4a1ce1f", "b71bf91323717b3087967c94e7fc6deb1c80b4f7da62f6dd214d98b92b8", .None}, + {.Lcm, "-1fd66bd2e661d43697568edc60002d", "-f17355b20f7a5c644e8953db60e218", "1e07337c51705ddaaac1fed7d9d9beb79f5e7f771fa1d9a123aef907be38", .None}, + {.Lcm, "-72f454b3515d4f39bcbf6cc0db2fca", "84b77bf88f34293ef94fcdf43a6793", "3b98600003d563d2d69e7c77e06e19bac4bd2898a3a89999e30249dab6fe", .None}, + {.Lcm, "30605ef273552589af9d60016358dc", "-ad24b526d848aee16ca4f68aabc67e", "105c07f9562ba911823e288c5538ed777889df2d3de5a59e427f3c49f224", .None}, + {.Lcm, "6c8db5570ed34c30a2d204fcf9eaec", "-cf56e099912517a48b252e12473263", "57eb6c796d2561cfb10022660ac7d93a2e3cfb03aabe87283f9363fbf144", .None}, + {.Lcm, "7857eef7b43537052b5b9d1d7393eb", "d99ea37ffae08314c743fc894557ff", "664d1cb19b59030961ed643e759d13b1deafed56d84c3d978d263ebc3415", .None}, + {.Lcm, "-6691b1fc834f628c0f0ec30a4c47e8", "e4397dfe346b3bf9d61ff933e5f9be", "2db865b841d1b2170b9bcbd3c5a25b53d10ef67d307456728d7eb08b0318", .None}, + {.Lcm, "-3bf5c27d5e3f7117998b1cc9cda76", "8a6eb2dc872aee82babce310afe3f3", "206c6855aec3a93d8aaf99a36ae596c696e5817c2352c66a4b705440002", .None}, + {.Lcm, "-db035191cd04b83adb8bbe0eb368a2", "96f1813ede02d18d671563269339c0", "4091473ed69d24865ac8901981ef4a9d2ca30d857f6e9a9df9820cf045c0", .None}, + {.Lcm, "-76627d9b78901dad6097d62b28ecde", "-92f53e36f424eaba036c9bf52e0849", "43f594aa24a5aaf582555a474e6ca665d2654edcdfee2d62fbe09bf67b4e", .None}, + {.Lcm, "-ddfca22285baaab71b17ca0483f3e9", "-ca42c1a6aa5c813a8880bf6de2575", "af633afd0632e88d30d87fcca23aebd79c82093a3a602800bcd8c9d267d", .None}, + {.Lcm, "91f56ca66b1ab7376dc68d089910d2", "9f8374bf64f97d5c740c8d9fce12ab", "5af261a24a97fcca6e9e966f90778959a662a42cdaf51c5da31778690046", .None}, + {.Lcm, "67cda88d6e76b68aa39415c22fa9e9", "-39dcd1af7d846a68002ce22874f137", "ab9c02202d8c24b2f181493db1d8743fcbebf6b749baf19f52d405a725", .None}, + {.Lcm, "-28c164ad59426352bdb11dbd745579", "9f4684b1301ea81f5fa93425a94d1d", "195b57891f1fc606b452c638e1402e7416b8ad16b5004dbc22155dc413b5", .None}, + {.Lcm, "-9fc7e634b1964a0ca0302593449768", "e2faa6e33e7367aecd089fdc52758b", "8daaea9ac8bdd748162b165684ed57ec5e1471a96a485230b8632ec0bd78", .None}, + {.Lcm, "-5ec40c173b860d6e787e730f6af4ef", "60a38aea758fa9b90d6a598a877c1", "23c60ec8e2598693f219e1a178bb869711be692cf8a6c681892fc55c12f", .None}, + {.Lcm, "1f1491ad91247d8b9f0df00ae255ed", "ffa85442fd893984fb4456a104b3a8", "2d25b594e7cd3aabbf537f83839e1661d678d629c86a8b9077c127bbc98", .None}, + {.Lcm, "45f348e76b76a6f50942008019187c", "50a951673704e93c33425076445c28", "58292a86815cbf3d3937a8fe9181fcde858e727d173b44ced342c6a18d8", .None}, + {.Lcm, "ec7a9a817bd2e11d29a149740de4ce", "-e8655ad718f0ffd7efb9586c3a2200", "6b565e270cd02e1f7a6595df26f968b31dec537052654e3bb6f34b87ae00", .None}, + {.Lcm, "bc24036774cb05e6b48d3486ef1475", "1d5e0588a6c5ea6cf987bc250d2e32", "15952dad19fb84aa062c3dec55dfd31ee9bd3c26c308b0f82586435004da", .None}, + {.Lcm, "71a40eb75cefaa78a8ebcffaa54890", "-9d495d281748fc8ff4b23b021b53e8", "8ba45c52173311c26a1a43dee5d3b5361030b00f3e97cc756bdd0700e50", .None}, + {.Lcm, "3bf71262a17726672a3bc76c4cf670", "-f051d0a85a921b0f68ce7e7208fb9e", "1c2565a4bb700a2a3bce500725c49afddc2818f43ece55693fc4f04ff490", .None}, + {.Lcm, "-712173914a62c5b0a9831a7bbb2ce8", "df21960cca03bed67366fc478c1987", "629afb4ab6153a4054079f1d060873154ec788eab8be3e5af13d6df75658", .None}, + {.Lcm, "6697d34958812c422fe876f0c5038a", "63b108d857fb221c3d81b950224348", "13f9d49cf27379b4bcfc0fd3444e4d9e1084779da5dbb3b2133b6fd50e68", .None}, + {.Lcm, "d2681f7784d4b4dab217787c360e10", "5341b42f1c667687d1f5283cf221ce", "2236e15dd5ff8daa80ce16cb97b23dfd829faaf9d919362781edfb37b070", .None}, + {.Lcm, "258a965e27d9a8324489e42c142206", "cdb935440e46310254f7ee2207a939", "1e2b235fbbfd668b9518dcf57679b9ab942dd94c188020e5a18cd51b8956", .None}, + {.Lcm, "451fb8f37173247c01f16187dcd456", "-4ee984c22379d46438d3592ac261a4", "aa75c09248fa0c32f000fc31dd6cbbe145071a9d3e531c03d855d8c4e8c", .None}, + {.Lcm, "8ecd862c25fbe4a574db42a0a47fe", "-8086625a795671f297a8aaa00100a8", "23d8dcc3b9b3a1a116817caf9322f05fa60a0c2921ff71509f84f5e9f58", .None}, + {.Lcm, "-8abc80418a7fd6579c49e84fb5d463", "-d7cc0c04ca8f1b0e0d996cadf20bef", "74f2e470ae47198f6537f37eaa0076e63918c4d0b57edd3afa7ce777896d", .None}, + {.Is_Square, "6d3046d98a8d28cf933e46d39212dd", "0", "0", .None}, + {.Is_Square, "c2f6029a7a373a61d38bab37a0cf33", "0", "0", .None}, + {.Is_Square, "b438507b2aebcd537da462c9738a7e", "0", "0", .None}, + {.Is_Square, "afb51078ef643c89896dd49f269a92", "0", "0", .None}, + {.Is_Square, "6b2fe00100db2a03faa424bdb902e", "0", "0", .None}, + {.Is_Square, "5e7b12801899449cc59434d48cb448", "0", "0", .None}, + {.Is_Square, "48d469eec9f46e95e071bd8bbe8830", "0", "0", .None}, + {.Is_Square, "3f510b5a40c14dde50a668fd4bc0fa", "0", "0", .None}, + {.Is_Square, "37e0de8e5805b7d67e0a7f1d6daa18", "0", "0", .None}, + {.Is_Square, "bfe90ccdcab17921ac8f19da45f7ef", "0", "0", .None}, + {.Is_Square, "d2ef3d6ba9584cbf0dbfbf0e3ee5b8", "0", "0", .None}, + {.Is_Square, "3f27e59f09a9ab2f68b111374f1750", "0", "0", .None}, + {.Is_Square, "ddf4c77ffa69ff1b495b7d4756fec2", "0", "0", .None}, + {.Is_Square, "56d46a7ccf8f10d642aa0581e133ce", "0", "0", .None}, + {.Is_Square, "1b6d755880ae9a3cb7504459727ace", "0", "0", .None}, + {.Is_Square, "e943782ae1b2b0a49dab0e80fab7ce", "0", "0", .None}, + {.Is_Square, "f455f1e9c88c9b4f186e348cb15506", "0", "0", .None}, + {.Is_Square, "4f5e31dcef20ec10f9507267377bb0", "0", "0", .None}, + {.Is_Square, "153c3be5e4086cd7480604492a07bc", "0", "0", .None}, + {.Is_Square, "ab7976ce5f96ade9ccd9041a8e7452", "0", "0", .None}, + {.Is_Square, "34b2c47592b418819900d9b372a72", "0", "0", .None}, + {.Is_Square, "5bc9164f87031189c168de3604473b", "0", "0", .None}, + {.Is_Square, "32f66f05c0db98ab6f4fe8ac7aad98", "0", "0", .None}, + {.Is_Square, "6fc69cf14b7b1860b62e1e1eb83529", "0", "0", .None}, + {.Is_Square, "e42c2c9489f0dfd61e1fa1f3ec7d9a", "0", "0", .None}, + {.Is_Square, "33d223e4784bb2fa8f6de8d0a8caac", "0", "0", .None}, + {.Is_Square, "5e87bbd59aa99e3ba022beee39e604", "0", "0", .None}, + {.Is_Square, "5a49bfc95e7990f54db9df1fd09a5e", "0", "0", .None}, + {.Is_Square, "95f6b7ff48e35fb7e078ee45227027", "0", "0", .None}, + {.Is_Square, "8521fdf36e9a24ce200ac191082d5e", "0", "0", .None}, + {.Is_Square, "e0a9902892b1c6ca9f2e95ec4e6096", "0", "0", .None}, + {.Is_Square, "14fdc6139eb81592c20da4875c7079", "0", "0", .None}, + {.Is_Square, "7aa8e84d7491946c45e35aee36bbbb", "0", "0", .None}, + {.Is_Square, "d6cae90b8b4cf48120c059965cd266", "0", "0", .None}, + {.Is_Square, "ae00f8ea9ba5aaefc5837c8b838162", "0", "0", .None}, + {.Is_Square, "7e749b05b2549bf342e7c1f47f88eb", "0", "0", .None}, + {.Is_Square, "a742de3bdac2d6c114518d6850fb88", "0", "0", .None}, + {.Is_Square, "b4fbe2a7fe8a3e106d32a0d91c2474", "0", "0", .None}, + {.Is_Square, "14026afb8521fc56ad14e657fb4ae6", "0", "0", .None}, + {.Is_Square, "25c682acffa20087dea3bd578ee576", "0", "0", .None}, + {.Is_Square, "65e028dcc1ba992876427779ed6e42", "0", "0", .None}, + {.Is_Square, "bcc380bd2880c3a03a6e034020065b", "0", "0", .None}, + {.Is_Square, "d496e79f18b65e98f8c755701bbfa2", "0", "0", .None}, + {.Is_Square, "397824267f568501059bd5b8611b52", "0", "0", .None}, + {.Is_Square, "d6a77fd4ef7e7f4d06571ac1f90d12", "0", "0", .None}, + {.Is_Square, "4a6dc60430e896267f4bd69fa9b52e", "0", "0", .None}, + {.Is_Square, "5f694dbdbfaf8f97ef462ae7058f", "0", "0", .None}, + {.Is_Square, "596869c1c9ef1a86441a38ee5ae26f", "0", "0", .None}, + {.Is_Square, "1a3f595a1ba479cece3d484360d4d2", "0", "0", .None}, + {.Is_Square, "3206661323c6d78a2caa43bba9676a", "0", "0", .None}, + {.Is_Square, "bb03c411e27766db73e817745b7b0c", "0", "0", .None}, + {.Is_Square, "7d54645c18548916209ac483bf1b35", "0", "0", .None}, + {.Is_Square, "731a37b1dea24db3bd29b584ef63fa", "0", "0", .None}, + {.Is_Square, "d9258d206838300239a1cc2f3d18c", "0", "0", .None}, + {.Is_Square, "682b6e7d09f02dcc5004224a9db2e0", "0", "0", .None}, + {.Is_Square, "11c8dc8af64134ff07063e79161ae1", "0", "0", .None}, + {.Is_Square, "e78279bf2b5b6710c743899bca5917", "0", "0", .None}, + {.Is_Square, "2146d3dbd109e624aaee4dc5c49f7d", "0", "0", .None}, + {.Is_Square, "f74d194701bbf25083dbf59f3de975", "0", "0", .None}, + {.Is_Square, "bc308fc6d4724dab89652bb10a431d", "0", "0", .None}, + {.Is_Square, "7d90797aed10014f94aba06d7c0202", "0", "0", .None}, + {.Is_Square, "7c93f7b1c99fb871e85e267f7432eb", "0", "0", .None}, + {.Is_Square, "67b33305601e1cda0b760008542389", "0", "0", .None}, + {.Is_Square, "45997273027c600d9d3fde11a6c56c", "0", "0", .None}, + {.Is_Square, "4ea259ab283528cfff9bef38f22a72", "0", "0", .None}, + {.Is_Square, "e91f774af12652a77b5f41a4e48e6d", "0", "0", .None}, + {.Is_Square, "4f3e7d0398d2cf219a7c67965ee9bd", "0", "0", .None}, + {.Is_Square, "60e5c5c574c075fe85db43bf4d40a5", "0", "0", .None}, + {.Is_Square, "8edbfae7991889ddf39d5f9f5be3aa", "0", "0", .None}, + {.Is_Square, "5ece7bd90913eeef1f4c289d25c381", "0", "0", .None}, + {.Is_Square, "12d69ab32fb3a0efcc0f6ad4a0db8c", "0", "0", .None}, + {.Is_Square, "95a57109dae44481110322bb342a01", "0", "0", .None}, + {.Is_Square, "3674b08179c8ada49ac8865815a99f", "0", "0", .None}, + {.Is_Square, "f0a78e0a8adbf25f0befe5ac438eb7", "0", "0", .None}, + {.Is_Square, "84f94c4e355d9c5cb03f72b16f256", "0", "0", .None}, + {.Is_Square, "e0ed88c2f29700a0a35e5158227135", "0", "0", .None}, + {.Is_Square, "3e615275b690a7941c4b56278e4bb8", "0", "0", .None}, + {.Is_Square, "82441c43604597c29e451a5620cc2e", "0", "0", .None}, + {.Is_Square, "e4696fd25bf1effbd13985701d9907", "0", "0", .None}, + {.Is_Square, "a9a32b9fde70b7320ea0aa633ec1ef", "0", "0", .None}, + {.Is_Square, "38d6c2278f48ecba67573ef33906d1", "0", "0", .None}, + {.Is_Square, "debee9a269b91f1aa66cef63cc2f08", "0", "0", .None}, + {.Is_Square, "d9ce4324030e62d134b6792b922c4a", "0", "0", .None}, + {.Is_Square, "5184051a7c16d22221a72a1810e23a", "0", "0", .None}, + {.Is_Square, "8529ec56e586cb52afd87302c77a26", "0", "0", .None}, + {.Is_Square, "4b7ba70f16a19089c5ef1b4ffebad1", "0", "0", .None}, + {.Is_Square, "a2c3f472012281e66d3079e37cc17e", "0", "0", .None}, + {.Is_Square, "b029aa8a89e90655da40be95361bdf", "0", "0", .None}, + {.Is_Square, "dd7330f0c4301f7f3ece00800d7d9c", "0", "0", .None}, + {.Is_Square, "337abbc3805819eab96fe8b228fecd", "0", "0", .None}, + {.Is_Square, "b7d8b1f08eda91a558466b03a94517", "0", "0", .None}, + {.Is_Square, "f8008ddb221b6f30f921eca33b360a", "0", "0", .None}, + {.Is_Square, "5f1a18d80a8a4f88c618cebd060f10", "0", "0", .None}, + {.Is_Square, "5e627cdaf40009f025d0a9739125d8", "0", "0", .None}, + {.Is_Square, "7500e127b2b59fec01ce91cffbeb37", "0", "0", .None}, + {.Is_Square, "5d056faa631d856e3bb352c3a07060", "0", "0", .None}, + {.Is_Square, "bfce7fd6ff6b49f42ce986e59fc16c", "0", "0", .None}, + {.Is_Square, "7501a470da2baf705c80f43db42c3a", "0", "0", .None}, + {.Is_Square, "bbe51f989a8ed695328d5af15aa9fd", "0", "0", .None}, + {.Is_Square, "3d170c8fef5aa8f7fd1448ad8e67a6", "0", "0", .None}, + {.Div, "-959faea2d7c966a8e60cd491fe3d1d", "c4e990ed395a84d680", "-c2857eb5c666", .None}, + {.Div, "36758d1217f555c66454c587c1478b", "73cb91e3472d06e1bf", "7865faa40b27", .None}, + {.Div, "-fe6fb2d49ba1f07c6612c49986911", "409f8ef42d9b81cdeb", "-3efedecdc8bb", .None}, + {.Div, "-f00632476eb2d3be116b0ebb75abef", "6b3bf3d3c0dfaaef78", "-23d0266ca25ea", .None}, + {.Div, "-144a2754e6951339ef181e32088402", "85f8c7132b5783e324", "-26c53fb4d6f0", .None}, + {.Div, "59b44a61370f82fde4e86e55c3f78", "7b17e2784d32e606ee", "ba8f5e9d16c", .None}, + {.Div, "-a45e78b5a62d01628421bce4c45472", "-5faa60a47d64c00733", "1b7d98f543fc1", .None}, + {.Div, "-73e99d4daf3e95d918f8ca3f39b6de", "809f2cc2ef2d36c7c2", "-e6b455eb4e40", .None}, + {.Div, "-8f519805f2146ba217ada057f7dc37", "-b31a8708893ec8dd64", "ccd9e8e2c082", .None}, + {.Div, "89955d955e5a16c3e72a8a7fb3f24e", "5268046fb7e1bc2680", "1ab69366d8da5", .None}, + {.Div, "e9dbc687ab18a4961a0867ccf2f1d1", "629d7864989d9c918e", "25f15cd77db05", .None}, + {.Div, "-6bb2d97f52ac297a2890e6cee3e185", "588d8032d19813125b", "-13759782792a9", .None}, + {.Div, "-d32a59db3e4ec0aefddaf6a6e2e7de", "-a057287d539c2b554", "15125b4599d0a4", .None}, + {.Div, "20f1ca44fa54328e2f1b644088500a", "61477050d8177ee424", "56b26647bd5e", .None}, + {.Div, "-19fd0d2c78844e9d990f0da9476bc7", "c06777974a547b834d", "-229419e905c2", .None}, + {.Div, "3c1c8ef5d72c135ed117d6ea1a633f", "109b04f878b2164dd8", "39eb6498fe640", .None}, + {.Div, "2864cd5ffe09f9369cfcff31aed472", "-f3eac027e808fe7b98", "-2a650ef02134", .None}, + {.Div, "d98aa0af0f7b582831c0bd6d682dbd", "-339599962404d76baa", "-4379a473367f7", .None}, + {.Div, "-2525dc8eb7da93b701028d44f0e978", "24426a20349573f690", "-10645d41d545b", .None}, + {.Div, "de25961d2719f78033ff6c7f1891fa", "-45cccb8f79f6db426f", "-32ec030a0e8f8", .None}, + {.Div, "b196a9d67861c2ba4e497b69634d55", "3123727c8ffedbfcc1", "39d31ec6c5c74", .None}, + {.Div, "39766c20db13678177b3e6dd97cdd2", "-a6164c40e4f4fc8d4b", "-58920e2dfebe", .None}, + {.Div, "11e17cb55a818d26e09e745426fda1", "71277419ec43f34c3b", "28741cb5d9c1", .None}, + {.Div, "777db5e2c55b6a552b5d048ad12025", "-5763496f485d62f0dd", "-15e0b9ed66a64", .None}, + {.Div, "fa28a6ae21b24a01fdd1120e517f35", "-28c38b5b0175abe9b", "-623041599776de", .None}, + {.Div, "138c1961c0dd614de4eea73513fbc", "2783aaf67f7bbfc044", "7ea3deded40", .None}, + {.Div, "-ebf032d7eceda2c87fc2ab5cbe1881", "-85762d70a79b31baba", "1c490e671b774", .None}, + {.Div, "fcbb08d5443f9a811191bcfa6db04c", "a741eaf11132320c7b", "182d2ac353735", .None}, + {.Div, "ead26daa53e4822f8ad33297ce81e1", "-57e1c3ac744d075517", "-2ac095cf6427b", .None}, + {.Div, "3c8ff056397a3c48ccec5b46f7debb", "-aab15a4158b2ec42df", "-5ad4599740c6", .None}, + {.Div, "-49ff6fe0be655905e054fcc42de420", "fbf0fdf81da3082fb8", "-4b309abd7762", .None}, + {.Div, "-9f4d831160768627b760de18b1dde0", "44ce49f6434e6afb78", "-250b45583b0e4", .None}, + {.Div, "8a391b9eed29172c0e11575f71cb5a", "b723ee62751b1d1b48", "c1368ad5ee9e", .None}, + {.Div, "-532b70424f9de54b65624c7d104707", "48a7b153b0a693b660", "-1250c5d2b50c6", .None}, + {.Div, "-fd642b62b8f5afb33eb5b56112ecde", "9fc6a5315cd9f2133f", "-195fe9b573f63", .None}, + {.Div, "bffd3c988ba4b2e49bde67eb835d2e", "-32cce6f7c66148750c", "-3c77f3efe05b8", .None}, + {.Div, "90e2b6fe5efed809a09e400b80624f", "b215cbc10cfaea5de2", "d04672424401", .None}, + {.Div, "5d56442b98353e733c9133426aae87", "5b0096da0a202219d7", "1069155a83d87", .None}, + {.Div, "-7ebb6961e588370580213fd77cff91", "-b298d5ba28dd8224d", "b5a8366e0dedd", .None}, + {.Div, "-183789c84eb554f254437be43ba7b5", "36e267999a272ee40", "-70f4d055dda17", .None}, + {.Div, "-3835be1eb909f882080a7f8012d582", "-38b21bba4cf9905bf8", "fdce72ab7d3a", .None}, + {.Div, "-1ed6f73074ab3b85ab3341ea4cfcb0", "d12b41b3507f6b88c6", "-25be93967691", .None}, + {.Div, "8e10c7e5aaf956b020acc3cdbdd7a4", "dfb951bdb6a36ea4d9", "a28f9d82cac0", .None}, + {.Div, "-f906ede6cdbcf2c3f6de9c42462b5c", "ee3ea1ee37ef6b904d", "-10b96027c9f42", .None}, + {.Div, "-7becb056d38400f66d2823d60067d4", "-bff6fa99aacd654a00", "a54359972337", .None}, + {.Div, "cdfd0443b381208ff383bfc4b44162", "-92b3d0fb9bfdf32917", "-16774a8c735c6", .None}, + {.Div, "-4d235d4c7696d0fca8980847e50f32", "4b9bc5e9ecaadab582", "-1052ddfeea926", .None}, + {.Div, "-86a7b82ee7a5c9f11cdf768e27ccb8", "e6d30488cdefe8d8c2", "-95578192d900", .None}, + {.Div, "-5a0f6bb21c2be0d01b9db89b30b589", "-c26a14860940f46c7d", "7696cd857646", .None}, + {.Div, "-8b9bb689c9309bd3bec30aeeb49092", "-df11308d3d37e5fa3e", "a03832fe3d64", .None}, + {.Div, "-b62e2800fb88a5a231d0bfbbc1974", "-5029243fb4b289a25b", "245cee4c17f5", .None}, + {.Div, "507e3895e8f53b7a2105ebe4357b76", "461a9b9356367a0221", "125f02a4941e5", .None}, + {.Div, "-8d4d026b8eaf0271dc8895433920ea", "-c2049fd3326c2d4111", "ba7102fa128d", .None}, + {.Div, "-e26de8b66e47c98545d14e109da5c7", "-329dbbfb329c08fbd6", "47934b07fe09a", .None}, + {.Div, "-22d5d925d04892ab547cc2fcab2c21", "c5c3a98d7a36ee735a", "-2d17e3859b74", .None}, + {.Div, "-27fde827fc4147549c3991d12737f3", "f891d93f60b4df3f96", "-292ff091701b", .None}, + {.Div, "7a876b20ac79c1576d3252d9a5de04", "-3cff4e7b4886a603bf", "-2023e28ca7ae6", .None}, + {.Div, "ec302d60143291ae0e1c916f657bef", "3688b02ca6634fed94", "454be775702a6", .None}, + {.Div, "9f92e07e9818e03f5128192e97030", "-e08045a8dadd322b6c", "-b5f68441252", .None}, + {.Div, "-228889ba132e960b245bda5d960ca3", "4c070aa5a393534229", "-7447e16eb4f3", .None}, + {.Div, "-ec03c3e82ef5492c552ae98ea896df", "be86445f5720ccc715", "-13d1f951fd79d", .None}, + {.Div, "-6a9607d27da99b586747d7b55d37bb", "c20444029f6b527a6d", "-8ca3374da22f", .None}, + {.Div, "a8b5d1b9fd852f372814d3487c3eeb", "-92f66b3ec2ed472b9a", "-125e213ed3cd5", .None}, + {.Div, "-4cc84441824c11bd88aebca9737ac3", "-6a6018da01f6c78e74", "b8c8381dcabd", .None}, + {.Div, "-921ec2b89238285f7e25797638fda4", "-d1d6132dbcca243da2", "b24436512711", .None}, + {.Div, "9339605a172d9b44a80fe28c91893b", "5b2d2888066a9248b4", "19d5e1ff51894", .None}, + {.Div, "-5ce94d61e7ca8c6e4fa3cc1318d92e", "-72b2476c0a10e30081", "cf604d9ec809", .None}, + {.Div, "-7960c3eb6cf4ed52a39e32da13a5e5", "-938eaa59a7df3a04a6", "d294be526dcc", .None}, + {.Div, "-ed596674efff9ef2418f5916b95d25", "c3f1fc5dca1c21d6f4", "-1361800391995", .None}, + {.Div, "4a43a13a0fd492e5961e762c5869fe", "-2f0ad46aa16149564e", "-1942395cbc063", .None}, + {.Div, "9fb2d8cb6a4ed522bab540bb4503bb", "54e030678f5190886d", "1e1adc81b13d9", .None}, + {.Div, "-55cb78264ce23b89c3a61caf8048a", "-9d69a083117bf194e3", "8b872c63bfa", .None}, + {.Div, "22bae741b7f11b1b4a76521e784535", "be78890ea9d1fd8198", "2eadb5adb450", .None}, + {.Div, "-803f0644c7bf99a1c67b522f8b0946", "cbcaaf8f955f332d95", "-a119d1dce9fe", .None}, + {.Div, "74ba9e1b43a828907a97c425847063", "-66df6a4386fe3173a0", "-1227b41a92ed5", .None}, + {.Div, "-a59fd5947d424452f7f2c8c7e072b7", "518de4ca9431717ebe", "-207e5ac0f0e5b", .None}, + {.Div, "5b46363f0fb7b426c6997201561a1b", "1255a75ee4f4cf2993", "4fa6f0277b5fb", .None}, + {.Div, "152936acf622ee87038b45ded441e8", "c3745f83a68bdcb8c5", "1bb749e364e5", .None}, + {.Div, "-7822b122a8eb122d342d0103ef7740", "e198f4879d0e894d6", "-885354b252c0c", .None}, + {.Div, "-68274052b3d416620fb4711a96caca", "4495a557c402727cef", "-184c3c11d8eef", .None}, + {.Div, "264c9467a7c006a2a2b9d99ee7b3ae", "-5f2a280d7c9e6d40fb", "-67070b2125e4", .None}, + {.Div, "d2f432544fbea5b166eec2eaa1070e", "64e7aa2c5e64f88721", "21732e0649432", .None}, + {.Div, "-337abe80f0aa39251233cbc8233b89", "308fb99e9857d79421", "-10f620a7b413f", .None}, + {.Div, "3ac389f2f715f9260cb753d0b7c9d2", "e9f22cc15b501c0e40", "404db0169e24", .None}, + {.Div, "5ff703bbc664ecfa07ec8eb8f30f50", "-8c617aa791be367fe7", "-af00b0af7287", .None}, + {.Div, "c37f709d5ef7b9e5685abb96894c22", "a9cff0277708fffe02", "126b8e129ba37", .None}, + {.Div, "-532d77996335f4235ecd6bdf01f4cd", "-308d82ee78554ab62a", "1b69034a3617e", .None}, + {.Div, "f842828c9f3ee5348747794ee5534d", "-d0d77acbd275985516", "-13051ac497e1e", .None}, + {.Div, "-27bf89ae13d69f3405cb540a19fcdb", "-d2670cda0611757985", "305cbba97e74", .None}, + {.Div, "-fe0baef3541584889a3582ae1645ec", "38a21e37607906d0a9", "-47c5d8113910c", .None}, + {.Div, "-24def4c31f9b96ff841a52512159cf", "18acc9c2f245af21c4", "-17e88287cf1d0", .None}, + {.Div, "8f7d571c5e2573e3336786ec27438", "-b698ab6a6216741b43", "-c92c1f3d88f", .None}, + {.Div, "-ef59f33b27bf3d9e0dbc71bed16f1c", "-f80e88399ae56ac27e", "f7040e00ac4a", .None}, + {.Div, "a10c4226406262fea77cc4ea5ea7f3", "-2c3800d71f6c29e7b6", "-3a45ec7e31b1e", .None}, + {.Div, "-e5532bb498073824d1f2263996df34", "3e16e4d316380aa159", "-3b186a93387a3", .None}, + {.Div, "-4747eed6ab898355a05652c2318049", "-fd6ada4bf2bdddca7", "4801e6595b9ea", .None}, + {.Div, "-dbccc726b60d381c6ee323575d8825", "-6a4006ca7d4ce59c89", "2119685f845b4", .None}, + {.Div, "-41d891e51db76ec5be466efd590246", "-ef45e40a127827b315", "4672f8aa3ab0", .None}, + {.Div, "-a2116f7d3446286ba0bbe236d2e521", "-6a2668707adf2fed19", "186db4734b2b2", .None}, + {.Div, "-8f614b0ca9fc87cdf009652d9c47f6", "4052e15cd6f50f6a5b", "-23aa233034aa2", .None}, + {.Add, "-6d0d2e3e64a4fdecc1fc23bccb64c7d8c44f3319bffde7fb1a1ba34af5b6aa5b34fd2c26e8a9ca7f1426b8d72a98685743f288f432e0c8d45de8cd91424f632b330086de9f68a811ec457bb5a474736cd7b0784275ded3fca8224211cb9f453c5b7bf4dd3fe1c868e0f3e7c45080ecdfd9fb1aaf0dfcc817c8caa1c0daabea3a006922d2312a0db92f0ff37f3a9277ac24dc8f4db1da", "67b98907a6b254a38fa65e33b93c664b867a7f1395f5617efa827844c53a3cb3306f95b7f2cf146111c9d42edd93fc301472463f7ca845339f8c65c2f42a798b22808d98e04b17777123b0d824b615cb6f8927603f152f530dc8c8e8eb65bea5ec0318fc0ddfaf6914b2dad9dcf16157b2fed975e35e8c92333d19c35b0788236ffee6db6bc145c3f46498c19a98cc4f4370f876755d", "-553a536bdf2a9493255c5891228618d3dd4b4062a08867c1f992b06307c6da8048d966ef5dab61e025ce4a84d046c272f8042b4b63883a0be5c67ce4e24e9a0107ff945bf1d909a7b21cadd7fbe5da1682750e236c9a4a99a597928e03986966f78dbe1320218ffcc410cea738f8b8826fc41392a9e3b85958d87fd7fa46216906a3bf6c568c7f53aab5abd9ff9ab5ce16b96d73c7d", .None}, + {.Add, "e54c2803657181c71480b480d2023c62ffe1ae25a538b1273ba7da988b4e0000704404ac8d536da8c8f317b192fe1f03cc6cdd817e2f19d67fea0fe55f8a6a525ac9c75ea14c3469e0b18aecd05afc76c0d384cc10f1f8aab1a587d92c91dace8b1bfe141a4f623a852408a76da04a6ba981bc0a09e0e6e17d9c9d63fd7a92c1700faea006b1ad9521935853088988351f80fd7dfd9b", "6a88cacb1abb581d2e17ef7e5d99d864c86f26d9a3d111e212948c14ecfe090a7d42b636429451da2369159ef64c499642fa2c4c697f9f5dfc09b2c8229aab7145540514f3103411afabf142df4ac4742b56ce99ce2b52168e92fae6cc897e20dcc2bb8d52e782d43ba04cf3a5b37a13e52c61022be2aa21f89812d5114726978b37e480441370e125629c2ba57c5b4726d5c33b5cac", "14fd4f2ce802cd9e44298a3ff2f9c14c7c850d4ff4909c3094e3c66ad784c090aed86bae2cfe7bf82ec5c2d50894a689a0f6709cde7aeb9347bf3c2ad822515c3a01dcc73945c687b905d7c2fafa5c0eaec2a5365df1d4ac1403882bff91b58ef67deb9a16d36e50ec0c4559b1353c47f8eae1d0c35c391037634b0390ec1b958fb4793204ac51e7646f5f47eae05e37c4656c0b95a47", .None}, + {.Add, "f6d614431a4c862c35d0c6d0c8b41d830c11324f3729f205330e62ac5bebaf10bb1198028e5f782ec8663683a1dee6872ac86acb38f61b8d659b9e615a606eb425e3728c6b21812edf8c65096e2c4e3a23f22610c5bfc0d3e28a6480ed1c7de8cd9c0207644d170e06500d21dd5ade8e86ac993c5f277a17aa5ee68893108bd3291da3e0557610b28215706b9ee895f26a63b8a65a7", "e9289d183e029e15585b3214d0f57df40e76e5154b511ae4016e141d865432e7a86987c56f680f8901b7c6161fe62222971684b821414b4f9dc20bb8ede5a1a723aebf3925ff7a1c8508a66e0906940694934d0b593baddfadb35dc0dff7ac280b3c34d5418a6e466dc242c4f9c957f80fbfbe864119991789053cae856235623b386498e94b1eea89e5521c228f7267534a246bd987", "f895fe5c6fa766781bb83e81dd80bfcc3f37f83a3ec3ba04549efa484c12edd8b41aa145984e070bee3e297e5a04108b09c30b64d4d0ad08741bc59f038ba892660cf661ecb1922f73016cbe9fe958ea36d26f6c6597a9ecebdc0408eec974069815f4f5b7cf3fb74e274397179f05e0f82a881a070c10b903ab2b170e933e1f6dca3ed6eea27ff5b206a922dc7dfbc679f05ff63f2e", .None}, + {.Add, "e103a19a541d096806269492b75c12b39d5d9d77aa0e6ad8ee91a8d438afbfb29fbb7a349d999c446fa890d56959fde4cb24e0398b820f438f64349cde36c6135f235721962c512c3e6993ee9d69fbeda001279b56ac43ef6da9dc7088cec3cfdc487e06f1dedd859375e64a5cdeb9592de6f315d8eb92c5f5d3e1b076039d8f1abd59750b6ff18280b18c019fb5c58d482bb84353ee", "177ea39946dab028ac6d5f5cb09e5fde2bc3fe03c62794d53deef31853da98450513b08fb9d6f8871af3c46b8ecc913905e333a106a2b65689e2ce6b51832da6121b5faf2cac723744e572224f2ae296c4839cbbdaf747db20775533c548efa2d104e9a395b3dcf2a4897fb4b24448d03c7fc40c83ffdebef2082fdee835be6f4b0563b3ddbe1a25b6abf62a9754a00e49302d89d1ff", "f88245339af7b990b293f3ef67fa7291c9219b7b7035ffae2c809bec8c8a57f7a4cf2ac4577094cb8a9c5540f8268f1dd10813da9224c59a194703082fb9f3b9713eb6d0c2d8c363834f0610ec94de846484c45731a38bca8e2131a44e17b372ad4d67aa8792ba7837ff65ff0f2302296a66b7225ceb7184e7dc118f5e395bfe65c2bd28e92e0ba8375d822c370a659b915be5cd25ed", .None}, + {.Add, "40e0f92b34a7b3ebb3fc5b0d5289effa5c84cd889afb6f8fceb4887ff4893a9a23f6a762c3c6d8d55ee70578918c5c8751d5120dc8b5ca3a041c2d787f44b8c01d664f250b1ae08c6267eac3da33927d2f0a5607fe467a662d5b1633695c34fe6f26cfc868a1099c8977cdf8e43d6f49d7e94738d6a9a35c7e19a6b2cabcf000ddd91abb369e212d19e1be8b6823b0e9541755130df4", "458ccd95d51f42e915514a7a6b06ff826681dda4b9800517eccbc4cf949d6351e44a021f275d5e7f417fcb1fd1ab0ba38b3260d937754a7d88a7967a787b418cf340095a2a39743492dcb570deb458f269169e46cc18c0203c4624af4cb73a8d8675b7aadb3d64c39d015c8aa81c4f3f77a9ea25c58fcdc7b4a62ffe963c21aba454c035248a89930cd700cc1791e96d8c9f183679d8", "866dc6c109c6f6d4c94da587bd90ef7cc306ab2d547b74a7bb804d4f89269dec0840a981eb243754a066d0986337682add0772e7002b14b78cc3c3f2f7bffa4d10a6587f355454c0f544a034b8e7eb6f9820f44eca5f3a8669a13ae2b6136f8bf59c877343de6e6026792a838c59be894f93315e9c39712432bfd6b160f911ac822ddaf05b28aac026b8bf577fb59a56e0b66d4987cc", .None}, + {.Add, "b01df46bcb1cbca4ade0d8aebeb2768e61984f5e87a05dcca93c301429c2d26438e4c04904078d8684b21313664aa9a0c30e5d66c635013241048218935e8880c4e54f1a6a22fe9bbc443afd236f525238e1570aa29532f5b586bdec2d7b2371bff7e0b7b398dccfd469c9b3affa64e112bccd486e3b16f282fa1c14445decdb2912ffbd55ce7be1384e48537c180d5a3aebbdcaee19", "82a30021418501d19686096c0c294f0d34876626144ab7e30cb19dd54e809969a1d4db5a410b6a7daae402814ddb310d5ffd909c63ecf39f70638a2559f1baaed4a5d8ef388b66e20d91a4a78f8fed546dca0d06588dba52425da3eddadb778581a5b0bc00c7f0e3c47ae453df843c6328f603ee5b0dbe06a2c20afe6cda715cadb83b89e8dcb408400f5c36e24342e76a76414653bc", "132c0f48d0ca1be764466e21acadbc59b961fb5849beb15afb5edcde978436bcddab99ba34512f8042f961594b425daae230bee032a21f4d1b1680c3ded50432f998b2809a2ae657dc9d5dfa4b2ff3fa6a6ab6410fb22ed47f7e461da08569af7419d9173b460cdb398e4ae078f7ea1443bb2d136c948d4f925bc2712b1385e37d6cb3b473eab2fe9785da48a5e5b5041a561ff1141d5", .None}, + {.Add, "-6e05b38860799917814d5d5c2e4ae6e5531f83e2a13339bf8b46cc96726d1467144b64ed3f86bd7be5e6b83013df6103e812eba8b3214a131895bb6419872539f428aa18b4f2d166deb307f96e65810b4150c4e62543b1dcb6a20779a42257f2186de141dbaefd9ca8b70b307ef65ef73b71f99de33ae9d9eaa022532cc1ce0e91679ec74aa9ce794103a04c2cc9301b0810a8ed3503", "18976f48959735273df3d5ad443facc99a35a4206129e6490b7d9c79549c2bc1bffadc4ac99d06f3f0fe28b84a2083130f37db8cef5f524160e3fc3d2e082eb466ff29ed84884b8679e96be86a5226fd20cddfdcee5e168e74697b74e73bdaa22c506798f6fbb78b13255f173fe697580134553ba6c3c974009eb6b6f43b5d0ab6c012d20cf314412a4ce92e90ff42d4058b02553915", "-556e443fcae263f0435987aeea0b3a1bb8e9dfc2400953767fc9301d1dd0e8a5545088a275e9b687f4e88f77c9beddf0d8db101bc3c1f7d1b7b1bf26eb7ef6858d29802b306a85e064c99c1104135a0e2082e50936e59b4e42388c04bce67d4fec1d79a8e4b346119591ac193f0fc79f3a3da4623c772065ea016b9c38867103daa78bf53db6ba3816b6b71d9bc9ed470285a697fbee", .None}, + {.Add, "ff39673de5efff39be2b92e67c6b46c455dc452f808b8e2416058e585b0ad88b240dec7e7dba6d7b19b67f688701325642963845975dcd205cfd70d57465f0a82a2d66efd65743882c5d6fa3ec190e2ff93cc945c249a477cc9f78529f7c99eb23bb633949636ca8b1a3f8af1f1684789a0b6e9f1d1b80e661a0e08bf5471a9e209559b9ca8f50bb692a9c6ea6700d22b0c11e7c1005", "ece6aaf16e29e2c6ede298bdf3c89ada55df04ee96dabf258dd786884f522bd6bac2f934d437fa9a4a10457c9a3608b2bcebebc18ebbfbbec9c6a25750330659b32477d68c54ef64d8b1b3d3ede543bc912fa812c92bdc6ce72e419c63cacd5d975818f814b611331907140727c54b63a33cfab79ea520edc172eb8fe24b4a98c557d724cf3089aeb3057e795c56a58d752997d0acd", "10e07d1ecfcd29d662d09bc725ba7d071fb3a357e69f93a166ee306c0dffffb488fba1c11cafded24be5783c050a492e16e64f701b0498cdc4999dafae969210dc55fae6d3f1c927e79e88ae12af7626bc24fc3c6eedc623e9b125c6c65b946c0fd30e4c8caaecdbbe33469ef9192d92ed43f3e4a9705d2f53db80f44f36bcf47acead72c17825956545af4563c35777b8813b7f91ad2", .None}, + {.Add, "-fc7f3d93fd925d25b9b8818eeca384d6d0e138135d32c62502d7092599733b045268dc762c025b7e1628ac692ba79a1696a52fabcc6f599f97246e2be41c7483498e0138632ac53fc6b6d0b8a2a8bdaea316c6316f662352f8a30cc98264f148400d114a6b8c37aac5c8f23679470e8087be8b469be4ba0349e6effd9a05b1100ef4f7d31f40718b17e4fddb0eb89c248e27ea3b4d4d", "7c36cc101540d88a5b92731a87b7eb29bda23e18ccdd0e824dd7558bc158931f78c7548b6c8f19edafb6409322654b14d6812c386cad70d46dc71e77649b9024b19d93f6cddee3bb9644c8d224c0c43a9c747f84959b1c3b8938856fd7d1be590795f93e14aabc3b982c42ddee58f9301348de2158bef0581ac3545504cde59fc4452be6b7f27399ac20e3bea17d2c0966f368c51fcb", "-80487183e851849b5e260e7464eb99ad133ef9fa9055b7a2b4ffb399d81aa7e4d9a187eabf73419066726bd609424f01c02403735fc1e8cb295d4fb47f80e45e97f06d41954be184307207e67de7f97406a246acd9cb07176f6a8759aa9332ef3877180c56e17b6f2d9caf588aee15507475ad254325c9ab2f239ba89537cb704aafcbec674dfdf16bc41a1c6d3b701b273481762d82", .None}, + {.Add, "-cce914f3e45dd0a34952ab73592d87340615ebe3b0327c57be92dfbb1393fc4ccc71e5052fc914cadbc0be479241de12269e8cbd023efd447e5d895ee1f79e5e72858983179c841b14b3060f3abd4551e207582d47551762321ef617527b3ea63f3177ee1cc828629e36304c36031590f59e372260c9ef9bd2d3b2c72591007e9818708add97e95c36e1d33345a1eb3b0debdea5afd2", "815a9c56beea0cc65f92efa255a70d3a810f79f9faab35c7a5c24ac7491f4f62eb4691f6a40fefca757ab1a017a8851c0ce9f2d1ea8c7f069ce84a9981d367ae9169efb625739120252b0f5c3d1d2954acc4943962e331b0416ae527c67c5f130a75b11ae3583d39e43849afd862e140ecdcd3826688b7c37f746714debc3504922827f8fc8ecb6029f9d9dc7b832487759232187e03", "-4b8e789d2573c3dce9bfbbd1038679f9850671e9b587469018d094f3ca74ace9e12b530e8bb9250066460ca77a9958f619b499eb17b27e3de1753ec5602436afe11b99ccf228f2faef87f6b2fda01bfd3542c3f3e471e5b1f0b410ef8bfedf9334bbc6d3396feb28b9fde69c5da0345008c1639ffa4137d8535f4bb246d4cb7a05f04891e1091dfc0ce7f956ca1ec6b39859ac8d31cf", .None}, + {.Add, "-5dc0ecb20fc0fcbee05e1c2eee9abfc5b86d3c92095713d0616235d8d00ca6455ef4d5e0065ef6c1d467d4681ea68dbc8a4d5fa254442da5633955325fa04cd9864d7aa80d36eea5438918f99da74eeeb334aec8461b66e60336bf6f3206cc6e5d3201c9552ecc6940b1d0dc29a98774d8a459fe92ab9aa8d094ed25a65dd3d10d5d51500154d0478df5f5c9e7c7a9f0e745d27290f6", "cf839a6d27b0661bb0ba7a0937df9f8880a7bf1af2a436158687beb202bc58e175e7c24f4bef44aab16646a2f0d8f985a17d82428483df605917c4d99ed34eec614ecff1525e2f363f191f0f065d531a68ed6ec7e0b3875f76f9f7a0a73f9adbaa1182c4499b231b04553afe41e7ee2bac33a9d3b4016f417ad6816f7cf0102132734084f1523e8f56bb71dd0249cbcd1e38a5f4718b", "71c2adbb17ef695cd05c5dda4944dfc2c83a8288e94d2245252588d932afb29c16f2ec6f45904de8dcfe723ad2326bc9173022a0303fb1baf5de6fa73f330212db01554945274090fb90061568b6042bb5b8bfff9a98207973c338317538ce6d4cdf80faf46c56b1c3a36a22183e66b6d38f4fd52155d498aa419449d6923c502515ef34effd6e47c8c57c131a8221dc36f2d381e095", .None}, + {.Add, "-d89034f1803a97bc005fde03e08cee79b80cf58ab9fcc76b7323d182e5328ddbd8ea03e9cd379e7a2b09378d36ff9239c781574d6c81136e6768af8cde84e5217d57e4e3b1ef77b1ce5ecd6a7d510f98149b67feadd1195571749f0b6e56e9d005cf6c066aca563fbf7841f4ea107b34c7bd53aedc759d0e9ef9e9a951225e83248f9316237d94242d1626392a8f00a92c23fbbc9ec2", "13986998cd3198b83b6d0d5197724d4ecb195185858758461e416296c7d4a53b65415f05feb8a6f22714ac6e98dc7a77ac0fcaba4a7c65fd13c3ed30e93d9a970c45fb4611205aa4abf3120973db13fb5a545b2b41f95b82d2213f84c5c832c17397a039488b9cd96cd85ac76d384e3cd5436c1c439b546264c9b9c894e69f0c0c31791283ecf4746f06dfb4d9f4037b97a59cf40d98", "-c4f7cb58b308ff03c4f2d0b2491aa12aecf3a40534756f2554e26eec1d5de8a073a8a4e3ce7ef78803f48b1e9e2317c21b718c932204ad7153a4c25bf5474a8a7111e99da0cf1d0d226bbb610975fb9cba470cd36bd7bdd29f535f86a88eb70e9237cbcd223eb966529fe72d7cd82cf7f279e79298da48ac3a302fe0bc3bbf77185e1a039f909fafbe0f4684509afd2d947e5ec8912a", .None}, + {.Add, "be7713598b24aa192fe285fb2b0c0689858782f853b75e9fdf6d996d2cb2254ac9fceab67aa2cbed1012dfc0fb203405a918224f9fab60ca57be38414c6687713c6408ecbe1f20990e08ac50ccc5eac9a3465720aacfcb00905c63a64ec61b0c1c25553c3d68f20ff12fd56d352f421414bfcd1db08ad5f9ce5f9d49e9732c2702ad6af41e06c23af7a0feeab30c4094672faafa43c4", "f1b0785ae963946cbaf948165676c2ac2e5de45a1a62bedd3e1ba79db47886a85ebaf8cd01eac99184246e893dc44bfdae6b691988290ba8d1312ab77ff6dde75db7457033d96cfa169cbb8f20bb6a548d6fb5e5536d81857115d1e734b999d02830681aea49ebfd326e8600dfcd4c9aa9d1a06a334eb931b962d53e540c353f5dc1d073b0e9f7a29d783ea14c6bfad08027b6e5344", "cd921adf39bae35ffb921a7c907372b4486d613df55d8a8db34f53e707f9adb54fe89a434ac17886285526a98efc78c583fed8e1382df184e4d14aecc465f54fb23f7d43c15cb768af727809bed1a16eec1d527f0006a318e76dc0c4c211b4a91ea85bbdec0d90cfc456bdcd432c16ddbf5ce72453bfc18ce9f5ca9dceb3ef7af88987fb591561b5217882d4c7d300416f3226689708", .None}, + {.Add, "f09b50443e7bde0d9fd9146cbe5f3523c17f7b6c8c2c644741c48bcb0b4e42405eb6df126a362a372d60f2d9592d3940c354f3259c96491e13e8f595867b61dcc7dac003db99d35a4d021eeb6a339b34194c7cbbbb8b40bb9c1ec5c76efe023eae10de147a6d938714f2430116b0a689b9b65cf0a7b096a81a31cf4068a9467d06ddccdd27483e1c9748d8d7e6d46a15a7b58e0374ea", "e5ed8258bf8b688bf366f9c549e9ae20a3d4d5df7a96765f706e39590730293eede15584806a22b5cca7c7e99288ef5b72b9b19546d85b3877cbc3df4d049df0983d21ef1c9bc7553875efaef4f2054143c9802c5809f8504b3721f84a3ada4efe2845c428f4ab245887490e7b81e2d8f8025d2aa2076f6b1036facf1e9dbb17bd6b25244d586564ddcedbcc9a245952dbf00977862", "fefa2869ca7494965f0f840912fdd005cbbcc8ca83d5cbad38cb6f609bc144d44d94f46ab23ccc628a2b6f57f255c8367a808e3ef103ced19b65b1d37b4babbbd15e9222cd638fcfa0897de65982bb882d8914be810be040a0d237e6f3a1afe39df36270bcfcde395a7ab791fe68c4b7493682c351d10d9ecb353eed5a93222e82b47f2f6c1dc472e525c694b076afaad5748e9aed4c", .None}, + {.Add, "8a4304e315a744898113e411ec641728edbf65ae25b53c31b819ddde4067105e41ddb4a695edb16b343bf388dff94d924a24bc28da08cb44a12c2c696431f42d72140b6b3dc3cfdeb3b3bbcda34dd0def161685994cc2ae05182a5754e0e7a8517f52c914842a1151862cc05da61def5606779c46787104a070d5fee846033761368bd4ebe4c3da4eff18601c7fd106b2943e72dca69", "82118a3a9e48e83e6986e6ed4ffb564afb15f81009559adab59250d2d1d83277ad42da5fce59114e802e491d0b44d32b5064663b1ac04edaf0fbc83b5e474dcb714e2dc5c4df174c440aa54dbf27a3fd5b0b79741fef449f853ee2206bdee641f81cb8285058e43d9b66e3b74fd0f6fd6177bd51d80b7c0c0aa9bd983b297c74fd76dfe288d6c1abfdae900d690a9444918f8a821928", "10c548f1db3f02cc7ea9acaff3c5f6d73e8d55dbe2f0ad70c6dac2eb1123f42d5ef208f066446c2b9b46a3ca5eb3e20bd9a892263f4c91a1f9227f4a4c27941f8e362393102a2e72af7be611b627574dc4c6ce1cdb4bb6f7fd6c18795b9ed60c71011e4b9989b8552b3c9afbd2a32d5f2c1df37163f928c5611b71d86bf89afeb10df9d314722ff50eda0160f3107a4afbad371afe391", .None}, + {.Add, "b4e6ef5cd10b421a116fa9f0148909e56d10ba22f5a8322bfd7565bcd684e01fa173c31e9e9b57c1d7143607f3d425c514dbb4901ad5c53d74ae6962d2ede7508b1cc0d1423dca8dd4a7fe605378b1d3a4788ac2508ea653a145ecd9bb77efbc35726de707fe7995c0217edc0eb316938a6a4ee51a37abbd85479e23edd9d3492c636359957592b844220ea43215927dd7a48d7bdee1", "6439aa8c3b1716c0ccbcc2ba58e996a701752030909be060adef3df671e8adc7fca6a7b8b5da6f8067b009b51db3a8882fb14a68638c284a1a3d8d154b3dcd04656b6408bbde38538e91a5d79dc48daaef7e9d8d5cda5c47f88579ce4c1e44ffeb81c767e6fa5e445c214dca86ca9336d8f981ecf01dc10207b6dd1956e373816417f7ade7fcb32e5f082230a8b1c1a48440981451f2", "1192099e90c2258dade2c6caa6d72a08c6e85da538644128cab64a3b3486d8de79e1a6ad75475c7423ec43fbd1187ce4d448cfef87e61ed878eebf6781e2bb454f08824d9fe1c02e16339a437f13d3f7e93f7284fad69029b99cb66a8079634bc20f4354eeef8d7da1c42cca6957da9ca6363d0d20a556cbf8cfe7b3d44bd46ca907b5b077d7245e6a32a30d4dac754225be5259030d3", .None}, + {.Add, "-162f4d4d660510b6b57e39c370e782ddc79e2efc28c18c71f34b52d996740f9f344b2a2b0947a0cb85327dd99153897bfab1b34ee9313b54611945207ef8c80f5c8a644b32f9384cd9d187b2bb87302bb59952302d5c754bcf9667ede59336f99316088698be90798519592b4a868874ae233ec8d297264fe48254ca8fd9692fc0f863ea4d24433dc9d071dccfcb46e7f1707199d7bc", "3cdab4366d2d0e492c4bedd3cfb1a9196ff33c2c5bc6a00f91e7e4d6f9d3da0af1129d6e91afeb8c0d7f585651d314f46d317380e4c5f065051da50c86f3b25bc891b93551d3a40ffeb9d439b45f06063f3afde639ed7144c644a8a25fea69118fc83c98f34d228764dd098dbbb218d8919f401e40a61ac212ec5aece2b0a6bc60b1638b1983a944159a5702de4132756ba99d5528f9", "26ab66e90727fd9276cdb4105eca263ba8550d303305139d9e9c91fd635fca6bbcc7734388684ac0884cda7cc07f8b78727fc031fb94b510a4045fec07faea4c6c0754ea1eda6bc324e84c86f8d7d5da89a1abb60c90fbf8f6ae40b47a573217fcb234125a8e920ddfc3b062712b9063e37c01556e0ef4722e6a062252d73d8c9fb8ffa0cc5f66064bc9e5260e75eb8d7a392bbb513d", .None}, + {.Add, "-d1805aecc70f15e9f46cf28bdee5bf768e5d38336a3eeb18aa79349ee3ba5bcb917d7c9eed54021be98f82834e9171715bc2ebc40d3aef5cbb74dff529acdbacec32a35562e6e26d66186bf5a5f9e8df6b96f215ccec8e1f7c59e701aa96260e5c24705ff6238444b0ff3f8472f7b98aec4ba4b603f0d1b6695a59f7efacd983783fc2fedc3ba94a5c33f9afb1b0ec58de306c9c696c", "47df3a1bdabe17783aeb771b244756f6bd8387afc5b7a58ea6f9ff1fcb93798bff09f4efd2576f032985643317b5c2d37d8c67f2f0f49fdb47038a3472180823afe1cc9b97cd36e6be2f948b1c2d4a223d3603c4eed7cf1d740032fa30998c57781638bb27f885c3eebcdc571f0d0fbca4e2657da1395f5453849d0d8683b3ff376b0504140092e27db386560ddb978f8fa30f20ab19", "-89a120d0ec50fe71b9817b70ba9e687fd0d9b083a487458a037f357f1826e23f927387af1afc9318c00a1e5036dbae9dde3683d11c464f81747155c0b794d3893c50d6b9cb19ab86a7e8d76a89cc9ebd2e60ee50de14bf020859b40779fc99b6e40e37a4ce2afe80c242632d53eaa9ce47693f3862b7726215d5bcea6929258440d4bdfac83b1667de807359a3d554c94e8d5d7bbe53", .None}, + {.Add, "-9f9bc83773f8655406eaa8df5ba51978f005c5929d361214bf14baf306353cefa2455a75350c254e3d03db7cb1d56c814f53f6939c887740291aa3c770b49bc3c77bca2b45e8b1cc82fdb7c8b482187ac6d5b5a3cfd99d48db6e1922422f848f6b20f1b9998aa378f21ed92a13c5461c577f8abf017b3492a2353ed0b9493345ab97718575dddddfbd787eecd9204f3799b27000bc52", "1f8d5e5c74b9c6abb9fa152e1fe93befac2b6aff1e76f6097f8573d79572dff1c3d7cacb10fcb2bd11b87436bc174a71d7f398009791b29c0452e9d9c7af267758510b14fe5f481581957e10e9523a41a382f79f300804a933ccc16c625451a5346bec648f227bf3dab46e77e52a0f7116c30833e87cd4aa4c288d41515004f9c56259509615df635c77057d1436ef409865badc3bdf", "-800e69daff3e9ea84cf093b13bbbdd8943da5a937ebf1c0b3f8f471b70c25cfdde6d8faa240f72912b4b6745f5be220f77605e9304f6c4a424c7b9eda905754c6f2abf16478969b7016839b7cb2fde392352be049fd1989fa7a157b5dfdb32ea36b505550a682785176a6ab22e9b36ab40bc828b18fe5fe8560cb18f67f92e4be6351834dfc7fe7c6101796fc4e95ff7014cb5248073", .None}, + {.Add, "-4a3d3a1d157a78430431d06d0769cb33dd6ad2a21a5553b6a78e49f73d5d72446b8ec23337e2619ea70550861c64df7d27ec00f6a622b4bb7566cd11e87c0363e25cd7ddee4b620d43e874562f22cd78416b14308a4fff9ce17f429552113c523303db10420a7ce82cc27ecbb04479fc1467763d97492dd02a37b75daebb76689bff26afb29211ad93d54c14e01891135bd501008150", "4ede342339474be61c8e9f2c4aeacba46ac9708472cb7ae9dcace7942b7c733977b2c48daec738c1a7a9d1407862a8647941d728ae2fc445f80975a8b7f8af2a219a90b53d822f598284c12eccf8200fc1c50092044990c2f189e831530a548ebf47993bbb5b6deac332fe61b6d185664407e5b5f22eb1c96b2369a4f104e1e6b3afc4b943b0d40d4d6f52091448272900ee29ba1b6c", "4a0fa0623ccd3a3185ccebf438100708d5e9de258762733351e9d9cee1f00f50c24025a76e4d72300a480ba5bfdc8e75155d632080d0f8a82a2a896cf7cabc63f3db8d74f36cd4c3e9c4cd89dd552978059ec6179f99126100aa59c00f9183c8c43be2b7950f10296707f96068d0b6a2fa06f785ae583f940ebb24742496b7e17b09e09911ec25fb99a05f4342f9615a51928b99a1c", .None}, + {.Add, "-54439616ede259c214b82c0a5c7a1def22ea2e0de7310f7881bbc247bbe67c6981a8ac1d994ae3dc54d09e5321700ae1c2a99abdb4d8b2863c82f8c493bf972fbf8ab156ce88998e246653181fb8a9ec8fa7e600440912cdb954712680194a9495da78da04cef56a05a95c91028cb052c686488fa28e71543e207847c71b1f2fcfb06210d49a44f12cc5ab6a9a41e0f944acd0e64bf", "9ea9d5c049449b0394e3d24de0858749d1da2d2ac7421aa820c1443887533c58686a28de984f929065c4701e933ef0fcf06ec96224686d913cf253e156150bc7d5b862d23df695a2cff457014c71738e8e5cbaaee2d5ef3225f39d25cc3be98c378057d644d3a3e09578cfe1443f5e0afc197d80199893c34c50dfe259c89cd51558902e2675226f34ff63c5eb85d260f63689902c30", "99659c5eda66756773984f8d3abde56adfab8a49e8cf09b098a588140b94d491d04f9e1cbebae452a07766396127f04ed4442fb6491ae268d92a24550cd91254d9bfb7bcd10e0c09edadf1cfca75e8efc5623c4ede955e054a5e5613643a54e2ee22b048a486b489f51e3a1834169305cfb118f71f6facae086ed85ddd56eae2185d8a0d192b7e202233090f41e1b45161ebbc81c771", .None}, + {.Add, "289668854d82ef0ec228b59f5770a1d38ec15395b20ceed6e71985402c774fe1b38702e8e5e5271df77e074ea58ce1788cf72f007ce69d89f5873445cc5b948dbd921c45bc9ab55c743088ffe185e261fe633f57cd6d28f93fbd465363a09b38a0a0e93751f0d982d4ef0963500e63c9d5211dd763e2eb04b844e7ac266c654fa4861c61b9618e05b3ef7dc47022f1ccf45b2e902f7d", "9fa4e3bf50bb6049157c4487904bb045cda4879d155bab2e865cc064990f25b70c8d6a732a62eaa6a92b29cbd3a62aa25c6c57954e0304384a59f0914789866a8c99655ba3802cd5c0de6416bc7574512c5a43531ffca2ae6dee2d98ee85cd69a824b259d71fc9b5d987b3e5cff97fbcf30129b7985c7a1dcb8157a663539a462ad2305b062494d36dd2380f9609e6a6f390df05ef71", "c83b4c449e3e4f57d7a4fa26e7bc52195c65db32c7689a056d7645a4c5867598c0146d5c104811c4a0a9311a79330c1ae9638695cae9a1c23fe124d713e51af84a2b81a1601ae232350eed169dfb56b32abd82aaed69cba7adab73ec522668a248c59b912910a338ae76bd492007e386c822478efc3f652283c63f5289bfff95cf584cbcbf8622d921c1b5d4062cd873e7ec0d961eee", .None}, + {.Add, "4504fbd7ec2c1abcb92ec40e5470403812aad380252c4ec20fd58b8a6485d0773796a29da0cd49224fd07c5d0c209a05faaaeb9232cbb9f3e8bf45747160e7499e4df7a7d0c083c49e3512ae14df62dc4f900afe1142df353fb7ce737f9e8cb713f79ec200b184b036a96b6ae9e3eb1303d36800f9ac914d770e567f1c949a2a775d0e4812c02045364bfbb18b6cfb5908df0df8db76", "58099286ed236f9a9588a5bc1b4182de74245dfbfb444cc6d43e3a39ab2ec7af1a71069606b3807a756dc70b9aa83601fdcf9b7fc806a51928f57f0cace7cd7812b9dda7d8c550be7641188bb8f0bb00099c221b434b41e00b64183985932a0a4e4602e408eb8cd3a36e517ee46f81d861a06fa0ead9cc1ea7a98c5981bbffa300136266eac7e175989f12b88ea3d7fe815ab7fbe096", "9d0e8e5ed94f8a574eb769ca6fb1c31686cf317c20709b88e413c5c40fb498265207a933a780c99cc53e4368a6c8d007f87a8711fad25f0d11b4c4811e48b4c1b107d54fa985d48314762b39cdd01ddc592c2d19548e21154b1be6ad0531b6c1623da1a6099d1183da17bce9ce536ceb6573d7a1e4865d6c1eb7e2d89e5099cd777070aefd8801baceeb0e6a1a10d3578a39c5f4bc0c", .None}, + {.Add, "38d9b1b3ccd6c0ec2b03b75dc1d084c60bc0b6ddb8e34ebd98a3bd463720cc7d08574c35a5bbc480f8d01a2f10f86cc22448a6973b236d4e3afc0300a227127a8a4d7033a952db66579f6533434a41cc56cf736035c6d5b49e3e241b64fef0972200b868bf805225510b61b0dc79dfb01ca309cc66fc99ecd009968249c24d348f9b6c04ce7825ef5ac1a2769ce51acfa3840f0675f0", "fa0d6e16dee75b40c59f11cc9c774996752bf180c64924553bc5722f6afeefbd14bb2853c421a07ecc3c9a2d5a6cb08c82b9dfbfe413c3148d7adcef7d73312611e55dd4d5f26ec210ca13bd64cebba487df539fba0d3de5b44ea84c4015d7d03e5be1b23978ade9135e41716e44d8bd376f9861c6d31b083f16f49bf28f0741dae1ca336ee5bb27dd3648c74d5f0c57403a967afba6", "132e71fcaabbe1c2cf0a2c92a5e47ce5c80eca85e7f2c7312d4692f75a21fbc3a1d12748969dd64ffc50cb45c6b651d4ea70286571f373062c876dff01f9a43a09c32ce087f454a28686978f0a818fd70deaec6ffefd4139a528ccc67a514c867605c9a1af8f9000e6469a3224abeb86d5412a22e2dcfb4f50f208b1e3c5154766a7d36383d5de11737f7eb3dea442726e3bea5817196", .None}, + {.Add, "-716dd5b720ed39cd662b8d798c2caa84839399d377f5ce48bdaba074b83ff062eaa82a3b48b4dc2d1c1133070e95cf21f0ae1887e788e36a37fe8de52868c975a60dd7bf17291dd27266f8c16ca4f5b7d64f9655b3be6391b961580008bc299f7d313488e5f9a7ce4b0064874694f2dd31052ba48f5cf572d892d9cf46a8cb1f67209aaa0d8005977a6d9c0b468edfe111dfd0ae2e7", "e515e3ef9b21c45dd18f313edfa6ce7ea698873215d510d29972e13efa34cfd0bcb17be061ee65d8341f737fb63c7afbefdff42e09843f4fb9c7a411df5ae7b4b08b0616a2bfa3e1d491a00b72405c6a9c5cdeda6219206a9ad3dc2c0b3bc5fa5e2293386d1defd0784bed5f91e65ce8d4947e6eaa1fdbd7fb211809d90a62a368acf6044088f1e3d0fab74f11c228cf38223f7fafb9", "ddff06942912f0c0fb2c786746e403d65e5f4d94de55b3ee0d982737aeb0d0ca8e06f93cad631815625e604f45531e09d0d512a58b0bb1191647bb338cd45b1d562a289ab14d1204ad6b307f5b760d0f1ef7e57506dd3a317f3dc6ac0ab00360664f7fefdebe5553939be7171d7d0dbb01842bb4612a0c80cd97ea6ce49fd5f1723aec599fb0f18a5953dd8e5d593ad127044274ccd2", .None}, + {.Add, "-d994df8ab6c3bdc16ded508afece30675886cd72de50f4570e94405a35c8ade6818bc27acf63832735c37e62e0b753c0cdff586c4cfa13c0672cf5dc875194b74091d27ec25592d4ee7bbe54f299a48565a386403b5218a5fa310f784976825950488255adc61b708215343f0898c214331d7f637b72831fc8d2b6c0f2277cb70fcfd74c1fb34147d4e9b0005266af619ba15eeda5ad", "dfa1da364d904f4fd80d1a35c4ff3a761bd8dad8c2c7427613b106c478be33816166e9bbf64546983187e24db87e3a6b422e0c781924ce3340a48c314d3b8f17e1d12794232822566f391a29a912c5f2aa3103f97ac794c7f76449efef3fe08b70aba44de9bcac8f04214c350a986ffaf6a393f01acb2b9af9f78fc3e60c645fd8e7dadcb6a758ee86a2b2546c1112cefbcfddc073ae", "60cfaab96cc918e6a1fc9aac6310a0ec3520d65e4764e1f051cc66a42f5859adfdb274126e1c370fbc463ead7c6e6aa742eb40bcc2aba72d9779654c5e9fa60a13f551560d28f8180bd5bd4b679216d448d7db93f757c21fd333a77a5c95e32206321f83bf6911e820c17f601ffade6c386148c9f58a87b3124d902f3e4e7a8c918039096f417a6b1b9025419aa636d602e7ed2ce01", .None}, + {.Add, "372ad1abc567667457fa276eef90459c43b0b49d98c021a281f12cc62d7658866b6b65cdc30581620420782cf77960358da7031a31e45969f1470092d236b604de2cd890e76577bbdcdc8fc049320679f04eac70697227e730fc90453e447dec35866561cce1fc7da3a7a81e07aff0c359693227ef6d2603131718537385bf45289e8d0cca21b34ec9abacf4e068aeb85decc62608ef", "8d9cdbd9abc3973e7424195865393354560d646ec4dce621d3e05b1f07f9dbc28de2153745121595f16b845a613a26b0c7f519e2c03e8c9388372674cc09cf4130b96f57bb0208c389bd7631e5f36a207c19c9fc862419026d5c7c1480554313ee1faaa3549ae701a1913ec56929851f45115c611c54d4741b06ca6aa53b7b0b071b7adf6e778182cb6bbe0c83d92307687a027f5487", "c4c7ad85712afdb2cc1e40c754c978f099be190c5d9d07c455d187e535703448f94d7b05081796f7f58bfc8758b386e6559c1cfcf222e5fd797e27079e4085460ee647e8a267807f669a05f22f25709a6c68766cef9640e99e590c59be99c10023a61005217ce37f4538e6e370d975e29e7a8e890bc1fa772e1de2be18c13a502fba07ec389934d195176b016441d1bfc666c8a55d76", .None}, + {.Add, "f0b7cf82bc313132005fcc4b290328eee5adbb2f9bfe6b46fe5b2426cd07e25ff6937247fdb2db580011df7a7695cd80b685cd9c9d5f454f4694ea703323fa15550dca66b28fe80d4a262e0431a5f0d797377705933c3164c584f99aa248a4bf90dbae99d3119e6203b8aeff486bfe8b45b4cff5cb6af4f3c07a9c339c818085ba39d374794a5249f788db69cef00976b27e83fb84cf", "2d803250ef80e4bfe4c84a4246e4c519e51d35ae0a1f05978cdf81ea3737cc90e33659261e1310dca95b584e989e13b6c2aa83eb4ae7a203ca1d0cbffcd21f6ed135be9d86aee76f8e5557915059a244fc4229bf293ba887e12a7095c4b34519d1be350d0677ff8b5d1da0c1594eb9dfc43caa313bf5b28c941372785308cafbd35dcb6ec58937a30514530ffd840490d344bd7755a8", "11e3801d3abb215f1e528168d6fe7ee08cacaf0dda61d70de8b3aa611043faef0d9c9cb6e1bc5ec34a96d37c90f33e13779305187e846e75310b1f7302ff6198426438904393ecf7cd87b859581ff931c9379a0c4bc77d9eca6af6a3066fbe9d96299e3a6d9899ded60d64fc0a1bab86b09f17a270760a780548e0eabef8a4b818d979ee33ed389ecfc9d2e79cc740e0785c34172da77", .None}, + {.Add, "c7a79b0b1f42a46dbbd79e7738b3bf035d397d38e4fb592c1520486c7afc38a90d756435b5a72c3a4f4d635a97472353908756b5981f9f3ab234e8bc2b4bacd9584451ddc6fdce66ed4b77a16e4555a2404d3b24188307cc93f4c533f2e2280d7ca9a8eaa2a579ffe5d7969a186054232234ef3a9958ec10225e092a2f45744e4b93509a2efa731cfee23da0ead3545e6d68fe5ceba0", "c7ea6381cadd647f69062bfc04de4fbf9e5caa352f0350eaad281fb04c05b8be5d6cd8c0f493c82161b5e6fa0b07b0ac59d33a0b6e8c92498e2c4a1b5447d0a20e64fb5397d2f3869c6cb4e87810d7044e0b0efa58c613a9ddd13989054e75716123043ed6227091ccadc65978547d2a0048bdafab09b00edd7f6a3e82c43562f2bc13e01225773bd9ec874dd33300b9ac7e742869f0", "18f91fe8cea2008ed24ddca733d920ec2fb96276e13feaa16c248681cc701f1676ae23cf6aa3af45bb1034a54a24ed3ffea5a90c106ac3184406132d77f937d7b66a94d315ed0c1ed89b82c89e6562ca68e584a1e71491b7671c5febcf8309d7eddccad2978c7ea91b2855cf390b4d14d227dacea44629c1effdd7368b209a9b13e4f647a411fea58d8cec4eebe06551819e772855590", .None}, + {.Add, "761b64692affd01b05a902ffa9cbafe12aa6bf0671c244861b8810302deae23b8611c62bc2a4a479d092506924b92494e7e975bbb70dc5a6f93cf170682e564e6e8f00a663110fcf062e578f8e760ca2e82943a85c28d535350fdae1aa802fdce6ebd9676d20d773b7478693379200f374a4804a9cc1da31775a547770efa78210163da8fe930c833e5eab4c645173adf2c34bc9c347", "2c1f9121d6625cc7ed1195719a53101e5de5cb2ea50eecdc7e91521976ecabff5e0782cad8b1d6918705dd938e756ed74475a5001112646c12fa657f5c6e5b3635f839c17e2c7a5455c395ffadb9e00b9d8addd508c2f9e33561bfc43650e94307f0ed4559e18fdb02a0bbb3dae2dd2048a7f59e2269f5bfcdd189521495841cfac7ed40c069ca1ce577eb1fb734c0c429030c927478", "a23af58b01622ce2f2ba9871441ebfff888c8a3516d131629a196249a4d78e3ae41948f69b567b0b57982dfcb32e936c2c5f1abbc8202a130c3756efc49cb184a4873a67e13d8a235bf1ed8f3c2fecae85b4217d64ebcf186a719aa5e0d1191feedcc6acc702674eb9e842471274de13bd4c75e8bf2bcff1452bddc985852b9f0ade2ae9befcd6a023d6966c1b8634721bc6585c37bf", .None}, + {.Add, "-d68d4e65052c350ce980e154551dcff180dce4f717c0843fac7e6def983e4813db6821814c0bdbda303a7f75903e56d41727e4b7422a6065058a79a6bf550266d4b636f3da913821a3c4fea9b0bafdbd42dfb2967a9c4620e8fee2faeb897c4e605d0765ebf3321ac0e4a1476ee6374b7af459a7e5243fb0ea6e9770c41983a570abef34af0f6606327f9ab7d74b4351ce4c7047064c", "4463ee651423e22ca0f45fbc9511c7f2214caadd9ed5bd5368178e378f8a0cdb5c870dab18eb57aa452e540c86ff0a8d625011e9f32d34efd14a29d64ae8cdf6817fd3d4f146ca477332e3678a7df0904e83d2925df266739345e9b0a579888611754fbd8e957c10f581113d4fc575fdf432ccd6190ed5ab73270d7424954315146aeaa4e6dfce2fc934b185531dcd9e44a32c124b2a", "-92295ffff10852e0488c8197c00c07ff5f903a1978eac6ec4466dfb808b43b387ee113d63320842feb0c2b69093f4c46b4d7d2cd4efd2b7534404fd0746c34705336631ee94a6dda30921b42263d0d2cf45be0041ca9dfad55b8f94a460ff3c84ee7b7a85d5db609cb63900a1f20c14d86c18cd1cc156a05774789fc9f8440905c41048fc82f97d6694ae932842d75b389a94434bb22", .None}, + {.Add, "be6ffe4f3ad0a80ec2f503350d27ce704b80c736f91398c703750f9ef0519b5560f7d2b16f72ecb81d98d104df2f4fe3036b50899b7f86f569ab8a7df0c5dd792003bc7adfdb22fef2d659f408a78829d50aaac5e1d79d2c55e15b59cfd9f938f819bf312bdec4e2bbbc251d022fdd26bf7de5fa2cc95db1b00e6bd8cbf317080ea7674b020f6b0c196d43a5e4007972caa58a3c2f60", "2f1b04b7a63e1601e1e99a42f845f9ea762880ff5893043d3bbe53c37e41eb8feb5a5a936f9e3247a9b5f40d398a97a2ba40b296548925bda76349c2d2849ef406a242a082e4dca388d2adaa0378a83cad2fe24772a616c2d17cef9a878547a23301dabe772158bae84d9def24ee1e7ed6089d8b88ed3b4d6a50ec221179746d9f65bcf04cf1e051db4d62e26ea57f9b93dee9b0d7ee", "ed8b0306e10ebe10a4de9d78056dc85ac1a9483651a69d043f3363626e9386e54c522d44df111effc74ec51218b9e785bdac031ff008acb3110ed440c34a7c6d26a5ff1b62bfffa27ba9079e0c203066823a8d0d547db3ef275e4af4575f40db2b1b99efa3001d9da409c30c271dfba595868385b5b698ff1a5f57fadd6c8b75ae0d243b4f014b5df4baa68852a5f90e5e8473ed074e", .None}, + {.Add, "4381eb2bb7f24280687f7dd3f56520ea5813358360bcad80f55fff158a2074c82c98618c6dcfaf1374af3a5238e6908049d516368b52176ac02e3b1746f1d5aa29493d4f7975c7b2e5957ce7f326e0a7f47b5252c9c901abbbdfa710f6c03e8c17bc367636088db671d82b6cd26c2ad1916b4693c4bfda04fceddf8ecde771355c2150100c2e9a7d7d53a6ef7397820c9212e799234f", "579c18f2f2d188a00c9e29c633efccee44acb1d30357c729f0ce26a68dbe9c5463899c292933a26a739ef2501f0102ec4c472a7eed751c58ccfcd3ec4749016b56c25490fad2e233c37d6be53a0e3825c16c2c1c2ffae0c3653d7e7a25501c95e74ac4811918aa4e20d1e6e1c4de9a5fb25dbf39db8c59c220739c61fb66da14872ebabb36733caf8f210d79b793917a1aefd68a7572", "9b1e041eaac3cb20751da79a2954edd89cbfe756641474aae62e25bc17df111c9021fdb59703517de84e2ca257e7936c961c40b578c733c38d2b0f038e3ad715800b91e07448a9e6a912e8cd2d3518cdb5e77e6ef9c3e26f211d258b1c105b21ff06faf74f21380492aa124e974ac53143c905cda04c33c71d617bf0c94e4b49e3500acb42a1d72d0c74b4692b2b1386ad02be2398c1", .None}, + {.Add, "-d34554b584a81432bd07a82a57b7d2aac43068e1e9232ea7895589db2f06c3ea736c1cee90328028b5f4b6ee4ddcd39c4c9f9117be6114837be161410ab377ebc37a5cf3b1c22875cc0bb66e12ecd6d3f5dc1e2d22ad1a6214884fb5c8b5ce8806d80790c0d61c31c815fe9606b451d1f1382ebbb0a5fd85e4097f5e2fa6b5e481aeb295e764c717ed0ea7165a2abb02bad390b8cac8", "15f8b121d4a4b37e0bb13efd5fac6cb141155f3c3f68831d1b8525d3abf6ca4c7bfff77f512d1ff4d6b9bb1de1a46dc2a2b0a1895b403e55c7dff15ecef2898f74d9a4ca83a8fdfa03dea3085c55908a98a73c00bb155d0f4e6c9628e035975749e57ab73516bd0700f9563d19893457478c93cec79af93dce7fca34c920976c96ac3318ec4f0929c387a649eaa60780388f644b5f76", "-bd4ca393b00360b4b156692cf80b65f9831b09a5a9baab8a6dd06407830ff99df76c256f3f056033df3afbd06c3865d9a9eeef8e6320d62db4016fe23bc0ee5c4ea0b8292e192a7bc82d1365b69746495d34e22c6797bd52c61bb98ce8803730bcf28cd98bbf5f2ac71ca858ed2b1d7aa9ab9aece90b04481589b52966861e77eb027f7cfb15bdee298700cc6f84b38282442c6d6b52", .None}, + {.Add, "-2dd3c016cafb9720f1575d6db270ac98b91eb1f84acf64a3558d0c984a0a8e693c8db761ca2e8d005a606a6315cf083ae12702fb0dd161d3394aca3cc0da9facc3ac09d5107cbccf385c5aaa6eeaa7d772060253ffd82f9ce5ee3b855a5b41c9c32020579a0b271060c6b250893cae5f0838c85acc40f399753395009b8aaf641a1a06a5037248ab0ce2cc8605ce31e068c80d4697e", "b07ddb83555e8c44751d636dd833b43738f87f2838cd28a55916ea1768e5bc8d82ca85367dd5eed57886eaf612a59b1d36d9e88aaee7e406972e7539b4ab694df3391f7f1d6ca6ee7a36cc3eca0f24f215d73166b9702f5a74d3a0a681cf43d175b9cd9e4a1298f8dddb06f25804f8b935b9654436709e893c0a99a06922eedd68b7a102640be01cc91544cb3b286c291926641160ea", "ada09f81e8aed2d26607ed96fd0ca96dad669408b420325b23be194de44513a6ef01a9c06133060572e0e44fe148aa9988c7785afe0acde96399c895e89dbf5326fe5ee1cc64db2186b1069423207a749eb6d1417972ac60a674bcee2c298fb4d987cb98d071e687d7ce9bcd4f712dd34535d8be89ac8f4fa4b760505f6a43e72716009813d4bb9218471802dacb890b1299e33cf76c", .None}, + {.Add, "-aabf8d8b4ad4fbbccbc4171cd8991e6cfbcf0954debce0b8b245c7379c8770cffdbe307b3cda1519a72a15b78500f6dd6b985152629cb6d393f5aebe84707647cf15ae24a696cacd7fb8645d182087ef299fe90ce2c182d9981a57feaff7ed0a2f995765bbe8174afce1c1cfae1acdffbb572dde200b358a31c3982d4d20d4ec344511f466bc729a179c99ce7b13c4f01e3d3141c592", "f192145011e794c2de8411b7463138acce2e0c22c069b007f12d92b35d000a0c9ea1dc86269183111f94ac31fb0bb38baaf599f16d6271c82c8df0542b30d0c17ff2d088d4c7aa40bd7bf917dc2c5aa52c7b7494e124e01482fb75edfd56c7a16bf642ce886098277b3895a44822bd97eb4ecdc12f106058d6ff438ad95ae38d24a92dc73092681e2a2a1440e560d25149a04cf899ae", "46d286c4c712990612bffa9a6d981a3fd25f02cde1accf4f3ee7cb7bc078993ca0e3ac0ae9b76df7786a967a760abcae3f5d489f0ac5baf498984195a6c05a79b0dd22642e30df733dc394bac40bd2b602db8b87fe635d3aeae11def4d5eda973c5ceb68cc7880dc7e56d3d49a07ef982ff79fe30f052acea53bab5d8c3a0ea0f0641bd2c9d5f584128d7a726a4d0d612b631bb6d41c", .None}, + {.Add, "f3f6c3aa8116caed10008fb4c595c55ecb110ceeac3a43c1a0608d7e058b5311a016e0d8daae24cf40b41950d5706f1eb730c2bee2efda6cf55944eb8384ed8f58bc3d8a346380851df98271bca77533936f0763a9a91431f76b23d326e305d659f140fec195e8c301a97117c9cd6bf26ce546ba01457f70bc7044e02e714d5c9c56632d219d8b287cfaa542829fc3b2bdde3a2df6af", "116bc9b9fa743f1a30df81abf24884e76a485dcb9b3e18e85166bdbfeb489bd41640adaef48b598cb4ef6d49d79e96349c78b74f06397d451c65134539c6800d829ae850460bfbdbf9a04637ee27d7046071ff97a20273b202c538d7038f9e16be4d668239f5033dbfbd390f647294642a2fde78dc0e157c80b4b425b23c562a745d4cf6dad18cf6c7f760b06f1a5561fb3dc9c2c2df", "105628d647b8b0a0740e01160b7de4a4635596aba47785ca9f1c74b3df0d3eee5b6578e87cf397e5bf5a3869aad0f055353a97a0de92957b211be5830bd4b6d9cdb5725da7a6f7c611799c8a9aacf4c37f3e106fb4bab87e3fa305caa2a72a3ed183ea780fb8aec00c166aa272e40005697152532dd5394ed3d24f905e0ada38710b3b023fc6f181f44f205f2f1ba1914b91c03f0b98e", .None}, + {.Add, "-f0c224aba19d92d3a00d5c8383cc5d8d46f64d3274d0fffc9a543b038e2484b6da0153eea8a859db71839fa6aa093ee7484e2995d81a65a3a77f1477b4327468c2d43a4d153199bef37cc46fefd9f4c220feec4594c6d745b293d1e919c288651c426f3477cb06e5b1ff204845abe228aa816a6403c615d14d667543d3620ca257c5a978322e42ef572296c1d1e70973b698b1495b", "64ee5a41521d1b26db1ae59121dfaaddadde1408b7d19ef232a38db94a95074cb179776cff4f421250ef84d61911bd152396203ffdcede34701ab9feeed537c3b522397bac061492beb40c1f25fd9860269ccda909ef4b1cac5470dedb356d80403fcd13c95b03db03d4c836fab2881a023ce12bbe167a92e599054be381822151d61097fd0a7955e7eec6088961adc22abf173e4796", "63fd981ca67b7d94077ad8349e5bde8020971dbb855ccdf23609397e4706e2c7fa9f761910a699b8757e01367267b3d63c4dd21667f6c3cecc733aea7721054f4c5f65415ef0e2f8ffc08f5ab60dbe6b647bcebcc45a844566a1dd0cf21baaf7db238aa494e338d41e22c916b26cdc37d9925fc15a12b47d144b9ed69fae2014af7e4aee84d84b12f897a371c78fc6b8b7087e8cfe3b", .None}, + {.Add, "-9928fa0a3635c0bd71b050764fd7a14b11219a3575bd87504ca483d93deff2e74e569957ea2a69ff5be14de1f508d79acb5c037aaca1a6f899b375c561fb2deb549babad83adab8e95764009343e94d157db3b97b1ddfc0db7fb7fe4fba9bbf4d47766647103f8f1eb891d7030fa5e6f88da1e232a3341fb00046aee9c584866ffcf5a573c47b3b1b0bb9b490d8621e68578ce40d1b", "7c4199ea1019f61c103899d93dd9f52d39cd57f13b7cf060d08b79a76b893b66be74ca5cfffb1ccdbd0e3c8f8d903f4e71924fa100a79bdd450676022523fab5f6dbb5d8de48cb7255b5d0936babb89cb1ac1e57f48b54549b91ecec758caba10c06364cd56c3993985f0624cdd184aee20899fda7166e5eef41ef6f7a5401089179fb3afc28179ef0780879b88f740ca4deb479e16c", "72af0a496cb69a10391d94d1d8dc7b1888bb3e4de42117ebcbc13169d7aa3c38498f60c78158762dc75027b16e3fb1d4c4dc8f6955dd816dbb6b3ea5cf0447d74191fb1e060df0b96c5e6c92d867cf4f9c2e6a9e796d7493c01234ee25d20fe1bebebfe68e5bfa0479a6744dcac1dec7e97af81b74733a3f3f41a8c0908e7c82217d059588639c63d56c4ec527b711ee3c872795d451", .None}, + {.Add, "-a24095719c0cb134e6e4f5e395b15adf124b29bc0135cdf7df92f1b236390cb55dfd186e7dc46e0f89be1790f040a2edce0e9b806deb5a896e859c133ffafb9332379660e64246fa765e2cd543bbacb28d1d2ec9cc3413d7c2bc3f06e3b6424ce3ddfdaa3d6533c51c890e4aee9383564f6356a4d6fbc6c7d674420d00bea8b9275c8256357305dbd7f896d1fef846b097a9b679c7d0", "699cbe1fd7adcdcdebbd66481e62e240d384162c29b100957b70a188262a31273f0fa29048739f52615a4672fcea721ba969fee4f8420a0fdc77833d726e8b5cf59cafea575543521e6361d76152427775d144380392d5133fe8fafe5d583a10bcfc2fb2207e2bc79cab8fe326a9ba0cd7205068ab93a9cd80d29e858590094fefb6f778ae77b030dd6b2c89df0b47a9dc96f257d60e", "-38a3d751c45ee366fb278f9b774e789e3ec7138fd784cd626422502a100edb8e1eed75de3550cebd2863d11df35630d224a49c9b75a95079920e18d5cd8c70363c9ae6768eed03a857facafde2696a3b174bea91c8a13ec482d34408865e083c26e1cdf81ce707fd7fdd7e67c7e9c9497843063c2b681cfa55a1a3877b2e9f6937a58add86fb55aafa8d6a481fecff06bb12c421f1c2", .None}, + {.Add, "60a4de167f9611d237771b12be26038cefee10400020e15534684e71adcce76898e08f65aeb83963e27024cbbc49968205e83ae237bd1ee0ea2ccf4f92016232c98a284352f31054c3206c22e6a9178837a92fed828797c5db0b9f44df1abb60d039ed53a9685b3b1332d5c47bd88c05e4b944d425298e2e8cddae28405ce4844acfae6eefd8e97ab462d5180cd0866ffe043faa348a", "18aa129e27987d3dbc076bea5b4fa54ecfd25cdf83de871819a37bd9d34360ca3b1a1f6af6dee6d828a1a71c6b02be65437ccd96889acc817b09f48b76e19ec5af7d4598cddedb0b39b326422effb12de31071ab356c7c3592d3afadcafa851c9b048bdb0db34c09827faf4bbc908a5a60d7bbe8bf78b5252f9f4a63ae9c66cea20e923b31df61b3f1a82dbab0f7d037b40aff48189e", "794ef0b4a72e8f0ff37e86fd1975a8dbbfc06d1f83ff686d4e0bca4b81104832d3faaed0a597203c0b11cbe8274c54e749650878c057eb626536c3db08e300f879076ddc20d1eb5ffcd3926515a8c8b61ab9a198b7f413fb6ddf4ef2aa15407d6b3e792eb71ba74495b2851038691660459100bce4a24353bc7cf88beef94b52ecde40aa21b84b2ea60b02d2bdc856a7b20f3ef24d28", .None}, + {.Add, "f2f1cd1f31c0a1e00df1df1f76b938ab881f7f873b301f2368dbf347936f238ab591a8db0efd2cfb20e2e5be64a37e0f19ea5a8025559fd9cbddd70e4412aa2b2088616e5e4ffdd234560e4c0d2bc3fcb82e7fd4e39a8e1acb13e64b1f472e29a5a8f5d81343b14e753f0e1d8fda53e8159949b1a76b5ae4aeabe15e767a1c9e2a6af77ceaf66f4eb80e5a8a66a610af856d706de428", "227d6661058da56c3d578deb1aa957ea29fabc32c477c748a89578eff022a822e7f11234f746f0d556fb269115922935505a2ad3e8c52a8150e31f00b9cc34206fe529f0c03aa637f1cbe4a135111387bfdbce806f60ff0208418801daaccd2bc55b1c92ab7d6f9accdb77c8c345e80a2bfb367dea9628df957ce73b6a39bdf52ad577c138704b1d7a5c8ed71d5d4f734171ea336ae3", "1156f3380374e474c4b496d0a91629095b21a3bb9ffa7e66c11716c378391cbad9d82bb1006441dd077de0c4f7a35a7446a4485540e1aca5b1cc0f60efddede4b906d8b5f1e8aa40a2621f2ed423cd784780a4e5552fb8d1cd3556e4cf9f3fb556b04126abec120e9421a85e653203bf24194802f920183c44428c899e0b3da9355406f3e2366ba6c326ae96184036022c6df5aa14f0b", .None}, + {.Add, "469399830b30878f43d2fea8f6b720f6d63be396cdac2b6037ee61af1099c58c42c6df7d6b65d720239db219a15674b1fc1b000a01ff76fa211a8b300c286d3d48c387b7e23c8f659f68c37008b09fad2a6e9e4a8a7b7bf98d17c459a7b4da4751e4321570fe7e62ec8e8ba0130753824764815da4553f5b45026944cb91330d38d2b386c922659790ab3c22203d4e3524530c0cf29c", "b041205baecbad6ee1f7a5861b35cd467301ea42ff51944e3dfb073a486dc36243b58f51889b824581ddf83113d3a04aa43a813c7c6cb7fb2fc0d4ea9a38120fa82ce45975219a6706d09badc92684fe6a8e0f326a1ea68b639cdec69ad6aeb82d4c7bb222c954d2ee5ebb92ddaa3d21810417bb5e9e67a9255164257569a7aeaac1fe06738b0fbc337e1f19a4a373030a143e2fdb54", "f6d4b9deb9fc34fe25caa42f11ecee3d493dcdd9ccfdbfae75e968e9590788ee867c6ecef4015965a57baa4ab52a14fca05581467e6c2ef550db601aa6607f4cf0f06c11575e29cca6395f1dd1d724ab94fcad7cf49a2284f0b4a320428b88ff7f30adc793c7d335daed4732f0b190a3c868991902f3a7046a53cd6a40fadabbe394b18d3cad7553c4295b3bc4e0c1382e674a3ccdf0", .None}, + {.Add, "-56118f754b60faf0b274b80744248e042d0cc110cc8b968548971d0c617f37a21903b28a8ea4dfe51821891dd40ea3d0d8ed786b129212602ebc0c3a622e651e17ca348c4ea9dee68af04259e147e456b76379e45a9f180bceebf4111587a9c2281c0ac2c14ed9e580a14fe9e4a10158b0555c19be78f423106766bf286c32e326f5d87f9864559e1129c3f0586efe88e33a671e1df1", "d2bb1332aec63d38521b9a25891c9c029f900391a0635be65eb6552dc9cc3fa274e74739b32dbb0c8a4e6c07478155ebeef1628b8c2db7c90d14c81b764a3df27e15cd86313928b96a05b99b8bf3e83602d84bc5fa695fe53f85d706edcfaba8070eadffaa50aee0eaa234adcd5253f5619bc97e6f5abd501b32979a3b24c93f09c32ffbbd7321721bb006b45f01407cf7c08e123ecc", "7ca983bd636542479fa6e21e44f80dfe72834280d3d7c561161f3821684d08005be394af2488db27722ce2e97372b21b1603ea20799ba568de58bbe1141bd8d4664b98f9e28f49d2df157741aaac03df4b74d1e19fca47d97099e2f5d84801e5def2a33ce901d4fb6a00e4c3e8b1529cb1466d64b0e1c92d0acb30db12b8965be2cd577c250ecbd40a8642c4069241f4148626f420db", .None}, + {.Add, "-9810aef14a3cb9d45ecfa2dab27731d7682a156cdf454af9a059765210e778993690bb28853e668d7ddd2bcf1c5b9da9f06077c046d68d2b61d95fbc4c4844900ee3e11b739c630fdefb24217192aa359b6d94cff5baee9c9d862e909f3562d0291ffcdd624873e550c166bda37401a4a5dcb6f44bb2893c3a82d4284089aace8c5eb3dd3f41b40643ccf5717d4e606a3806204c1354", "bd00f5bcbe0b5292f5698ad39e7ca4531ca322a1bbce0a5a0f214d9e1745934c9043ad06ed241dbc265f3fb39340b3676a40cdc05e46caf49d37a01b9d8014a827590e100bc03d1279c0eecb04d9a1dc824e43edcb4390b1a793fe2ff417847b51df5ee12c2030d3a9088fffbe15377946b879483afc9e99ee698f834d67845f7fce9ac4b958207a877a843324e580437c7f7dc7d0c8", "24f046cb73ce98be9699e7f8ec05727bb4790d34dc88bf606ec7d74c065e1ab359b2f1de67e5b72ea88213e476e515bd79e0560017703dc93b5e405f5137d01818752cf49823da029ac5caa99346f7a6e6e0af1dd588a2150a0dcf9f54e221ab28bf6203c9d7bcee584729421aa135d4a0dbc253ef4a155db3e6bb5b0cddd990f36fe6e77a166c7443ad8ec1a7971fd944795d7bbd74", .None}, + {.Add, "1826a049ea719a24d599f48d23373807941eb5f3aaf4430ff4159d48b75d6358722a23766b7857525a4612ecdd487d6161e7987a920754335ce9d1c453e612fd5dcbd69bed698d2aed77778cb3fd1a19d0b4d93e28d79cfe1b9030fffea856a8ff8357f3082a8db1a90dfdd0f141e0e2b27cc176037ffc1170a79758150afc93764d8099456460113e01c549cb68354ebca65e95567d", "5c79d602f5032f553d7bb2c8ffb9587ca600fbe52894a1e18fdb9428ba0040998438151df2d9bb0888953b2168aecceae1ce611e6723d8fd15dad79e02dd1bb1c327b20a3f9ed34aec7999acf9c511a8ea706aab2adc46ee486956b38d2702833d8ae7c8c8b27fca8b255a088ab4c87a01258de3475fe5f06324e30cc8a8cb887b6c2e1e7adedce8437d20cbe33dccc9ba18c57ba760", "74a0764cdf74c97a1315a75622f090843a1fb1d8d388e4f183f13171715da3f1f66238945e52125ae2db4e0e45f74a4c43b5f998f92b2d3072c4a96256c32eaf20f388a62d086075d9f11139adc22bc2bb2543e953b3e3ec63f987b38bcf592c3d0e3fbbd0dd0d7c343357d97bf6a95cb3a24f594adfe201d3cc7a64ddb3c81bf1b9aeb7c0433cf9817ee615aea6021876bf2410fddd", .None}, + {.Add, "c85420e76df8b3eff8c0bf8183d15e3489982b6e48b5561c49eb43ebf4ad0a5ec9ee389473dbeab896fe18f25ae126235a65ffcb1a06ee860372eb4465ecae4ea0d57700c61b569fc8eb776db2ccd11ecc7f98fd5f7ff9391ab6286612c383f5c3f16318533082f94429b48ef562b51982e5e7510442015f9d2837ab72817f9fbdbc3ef0f8d116b5e1bdc4d93074f54ce8615ddbfee4", "b8da68939477441dad319c36f66023cfcc0d7afcaf27ccb5c5afab7964013ae52f779ea0226ff0e5112a1dafa2d8672c7a598ee8e414ebe6dda2e0d87e241329351ad67fd5b781217f66ffdd640293a9f089485232d7d2ae0257d585b5add3fe10341ed2a90b47b7390c3413ca9824c2760c579d6a44870f9c2f86aa16b018c42db76a1bec5ab6f3e6c7f0f8f94b18c5204c3e131772", "1812e897b026ff80da5f25bb87a31820455a5a66af7dd22d20f9aef6558ae4543f965d734964bdb9da82836a1fdb98d4fd4bf8eb3fe1bda6ce115cc1ce410c177d5f04d809bd2d7c14852774b16cf64c8bd08e14f9257cbe71d0dfdebc87157f3d42581eafc3bcab07d35e8a2bffad9dbf8f23eee6e86886f3957be5589319863eb73a90ce52bcda9c885b5d229c00e1208ad9bef1656", .None}, + {.Add, "-fbede47381280c4d281d6896500ff39f15c15a3a00ce36b53405f56faeb4442cc9d39ec1677b9f192d3f0ccdf8f9ad4ec204b6ada77a6f4f75b2c8d3af127b8e02f538c05191f5f3aca9a84233ac659dd569a3838df2ee4fd67087b5e5fca659fc96ad7dc14559a692fff4b34c4230f16fc1ae406096743723f6c8e429353dc2b068e68a74b6a346d81d8d4027849e75c1cd46b5d70a", "3f597d96a127f1eacf71ab586eb64c99427310b21b868f5b2dea99b8a0c3b3774487a6a7593df9b526670bff01fcc8a6d6a5f5f79eaf824b30f834ba8ec53d1ef088195471143d40689a62d9933061688ff95a53c6a212ed9f75525c8a7054eb87d2647aacdda4838ed24635e101a791e410f656aee2de3cf4bbac69bf62d4f41109a4a9299fd669fa7d64e75f30cc034713ad19f3a2", "-bc9466dce0001a6258abbd3de159a705d34e4987e547a75a061b5bb70df090b5854bf81a0e3da56406d800cef6fce4a7eb5ec0b608caed0444ba9419204d3e6f126d1f6be07db8b3440f4568a07c04354570492fc750db6236fb35595b8c516e74c449031467b523042dae7d6b40895f8bb0b7e9b1b395fa2f3b1c7a69d268ce9f5f41e14b16ccdcdda02858c853d2727ab9999be368", .None}, + {.Add, "d42675195a747be77ee83026b5adee6bc0cdd3fe8a24227ef6924dd6a458fb67ab6e7d600b50c90bd73495fdc35e243ce92bd9f0edcad66871157c71b6a60447dde35d58ed42cf75f48e121a4f2117e1c9004e13933e09d7119f53a0b6d6dbdc794a3c96fc9ee42369f68611e1a4ebd3340dab9e4105636de2270a3f3b9f34d6822be02233bac021fc0c7d4516cb642be5568ad75b1d", "8198a6a1249f9dfc3ad7efa2dbeb3aae10c8476a84275a59adc036bd0d80628a6cf2224b55f2bc3d8713c7d38884a1215fbad0ce3209ecd0b411942b5f8b641c3e18e3c172a6f760447afb90d3d3b8a2322324ddfb476ed5098c66a69162f04cb32cb734f48954c40e3b4b0f22d1063da9246732d3631b4d112dcf756bc563ba06c03313de8e3d4782914129fc65e58857a5a70b9a5f", "155bf1bba7f1419e3b9c01fc991992919d1961b690e4b7cd8a4528493b1d95df218609fab614385495e485dd14be2c55e48e6aabf1fd4c3392527109d163168641bfc411a5fe9c6d639090dab22f4d083fb2372f18e8578ac1b2bba474839cc292c76f3cbf12838e77831d1210475f210dd3212d114687ebaf354d9b4a764989088ec13361248fd697e9dbe6f133149b43cfc31e2f57c", .None}, + {.Add, "-d20633d961418c0d3f3db3e1edae405e170d6e5f06929a1510d254989b5817362ad29ccb52159a74de788b99d3c19dbae9d9acdf9bf90f35dd0cab496f61531f0cdb0bcb914e3d5a84b1e1a39743928ff65dbc8ac976babe6c6fe70dbea58b2b34fee8a4df7990b832305817e2f290bcd6a85587ea52a2e9fa21349f68c4ba7cd9d8cdb88bf8f682476b986af063d8e2b7daacaba836", "f4577c0c24f7ff21aa499e844938a009d3715e0db2e423253ad63fa0ec2983cdbcb16b2b9be16837cd11bf667527b956096917d9cbf268609a4281dcb99a0389c9598fb400894b8d18c3151f375d95009f56792144ddff6a79b7ae8d337a0cb14c827c1abf079c9052bdfaf4b6ff5b654511e609507c8c4641d5720e2c2a52640feeb2cdfbb7639eaf22065092818c94a96febbb2083", "22514832c3b673146b0beaa25b8a5fabbc63efaeac5189102a03eb0850d16c9791dece6049cbcdc2ee9933cca1661b9b1f8f6afa2ff9592abd35d6934a38b06abc7e83e86f3b0e329411337ba01a0270a8f8bc967b6744ac0d47c77f74d4818617839375df8e0bd8208da2dcd40ccaa86e6990816629e95c47b43d6ec36597e73615e5156fbe6d1c67b66de5a21db3b1f1953f0f784d", .None}, + {.Add, "7278e6d2c66dc76361b7bd2a9c426283d3fafec0616d0d4c6522b10045db4470f9ac3c636a2b9305eac291ae39f47e84037a82eed18af7aad156bc7eadd0a19484bdadf4adf2d4c80dc6b6a8f04422fdf724f885978683a2783942a4b7b0b77f69831461d0b050e0674d618c5aef73a6517b8dd4d8ca9e619fd9ea62ee764e223b00110c6754e1f15cb3e3f929169685859bf5dd53d9", "2b7792570620919886eff316c58058e61871fae36514b4176d5fe87e315e2347c28d21da0fc3716ab239000717d1e776496b1ab290dac18fc758a50edf00274b22d3ca408aa6cf2fb0de07c823d301514c91ec7ba16bbf333ee4a89168698aa89ddf7828e995547e9f7a751f55e90abaea1b48414ec071cac70eceec9c75696e2da9d7e1d4f11e5412702d228705d0df443320c41fd", "75305ff836cfd07cea26bc5c089a681235821e6e97be588ddbf8af8828f126a575d50e810b27ca1c95e621aeab719cfb68113499fa98a3c3cdcc46cf9bc0a40936eaea98b69d41bb08d49725728153130bee174d519d3f95ac278d2dce375029f3610be45f49a628514508de504e0452001d4258edb6a57e4c4ad751b83da4b91ddaae8a84a3f3d69ddae6cb5186f39379df27e995d6", .None}, + {.Add, "f98c1158aa0bc610a31222fad535c2f2356bd842d8b3581efe964bbeba6383bec9dc024b41107632953c3f92c1581d8c97452ce4b4d3cd94742b8b92b9bca0ba18eb14c60e7d184e2fb622efa3cbbf7e05d9c9fb1fafe9cc5d7c76fd63849d5c1ae9d302ebf1e72c98db491d8e0c95b6b5a8b1790316fafd774561709ab54ae69db3b4a37dcff3f41c42e97b4411aec3fef401b8a3eb", "7802a17fcf876b34b4241846ed9738faca15b88a625c2801d9edb4c3f2198f0b9ef6cfe2413842d255cc227699e0cc38fd7572929b3ac58ed049cc333a0ef67b88e0cb1c00c49ffc0d49889c89b247be1dde3fde86431fbb444799f0f91f21373dbaa8e633c1974268b716a48f6ccaa80728b23cb2b7ac88e9b4d0913a07109041fd03b83f685d36744d85698057a3c85a18d5d18ea8", "1718eb2d87993314557363b41c2ccfbecff8190cd3b0f8020d8840082ac7d12ca68d2d22d8248b904eb0862095b38e9c594ba9f77500e9323447557c5f3cb9735a1cbdfe20f41b84a3cffab8c2d7e073c23b809d9a5f30987a1c410ee5ca3be9358a47be91fb37e6f01925fc21d79605ebcd163b5b5cea78660fa3201d4bc5b76dfb0b85bbd38512a90906ee4c469528c590cd78a3293", .None}, + {.Add, "110048ba5b4ab8faf2b0289944ccddc0edad73f04d6dfdbf416789ed033fd41b395ee621a12fb2dacd3ce07cf221426d6311990f866d117b7725fa1783c36abe43d26a2ecd3a2545e0b30aeef1a157e592e41b6390db44367aaffaaf2eab5f3cd14510019ee0e473bafde61485b09c49a9ca671dc6df5d11833d9326796cd02b4613af70786fbf4656fa4870a084aa9af1260892217f", "60ae114227ca5bfa924d8f2f6eb1f3455cbfe30a0798d10496070b60abeb15d4f7c2845297cf06c0733756513aa6894678129bc949bfe442cbfe4a5a05d047991d59129cbb0ffd71effc4c3bb40d211dcadb9e8ce3c2e5bd6656013ce7be5a4728bf37321d8b418ab1a61d3ede0ead96536aba67f9f7b94c91935434a157f8dddcd723e007b7d6d49c79af54ccef5555df9780d4be02", "71ae59fc831514f584fdb7c8b37ed1064a6d56fa5506cec3d76e954daf2ae9f031216a7438feb99b407436ce2cc7cbb3db2434d8d02cf5be432444718993b257612b7ccb884a22b7d0af572aa5ae79035dbfb9f0749e29f3e105fbec1669b983fa044733bc6c25fe6ca4035363bf49dffd352185c0d7165e14d0e75b1ac4c90922ead3508027961af373f7c56d73fff0d0bd8966df81", .None}, + {.Add, "dc75961619f86ff8bf340e00cc94f6797c9e1a7413b78721d42fe4a4a27be3c3b3123313ff0fe6d9f43f7f9488ba540df79b4ce2aa208e707ef49e20def0883ca205095319d5446e37de113c0b7138c7ae47098df8af52c4b5869d8d191e59779988a105f696f12bbf29198259ba6fa006c975e800e01ed91bf4eb3a85a508cb7c2322eec51822ead9be98b58e4346eb8d18ba6d372b", "774b7df9b190ebbb32d24d0b9c7a27db1fdd94f79187072197f48fcc1a2fa878d36af8166ef9dcbe7a615dec832978a7b1afe8ab454c911b6102a25d63de2d725ae986180ec35c0b9f31ab2ee5f79daf576df1b98e5309142d6afac8c042555beead2cdb53b9c104ee61e3832af8b3bc8175ad5de713da5082181d776ffe4d195fa710c9562ea3a94d79f945c9d5f759d3ac40d20b2d", "153c1140fcb895bb3f2065b0c690f1e549c7baf6ba53e8e436c247470bcab8c3c867d2b2a6e09c3986ea0dd810be3ccb5a94b358def6d1f8bdff7407e42ceb5aefcee8f6b2898a079d70fbc6af168d67705b4fb4787025bd8e2f19855d960aed38835cde14a50b230ad8afd0584b3235c883f2345e7f3f9299e0d08b1f5a355e4dbca33b81b46c694273891fb58193e4560c4fb3f4258", .None}, + {.Add, "-2831d5fb3411f0f90146b11b5363d730dd40b2ae043583392b58c09f8bcf7b0a1cf56def649aa0769c767d95f7bbd1c7c3dd26d6348c56b9a840965d726a793af6db36a817b83ca57376dc909a4231952f357300d8f2691bb82a77f109340cabc44aae6cbcf33ea721f57ed199ae0d8f6fb54e29bbecc73ad7d6180a76b9461f5414ba294b419807d2fcfc66da4a06c11f27445e45e7", "31b4d18aeb44c2b1743961923f781d1d07fa3039345ab46e3f12c39828fb589266ba1e4d6688203da0b959d54356ea983e60ff03be430bc0cbb3e9c46d20f39e63454974d46eca9f886584f646f8131c3278da6dfba8a219a04755ab47da7c7e4686867872378f24d0fcfd882abd173466cd80a83c29a327ead0b9b0d68d233b9b6a25126e96a06dd9da52ded25f68a9190080622dd3", "982fb8fb732d1b872f2b076ec1445ec2ab97d8b3025313513ba02f89d2bdd8849c4b05e01ed7fc70442dc3f4b9b18d07a83d82d89b6b50723735366fab67a636c6a12ccbcb68dfa14eea865acb5e1870343676d22b638fde81cddba3ea66fd2823bd80bb544507daf077eb6910f09a4f718327e803cdbed12faa1a65fd3dd1c47556ae92355086606dd5677f81561e7f9d93c03e7ec", .None}, + {.Add, "-6ca20a67b9a5403eafa8dfc6cd0e782996bf0dfdf83ccc1961bc68315455337f1c88d6689b2a4361dc396fe66f8c72ba0c47e09dc30d5959eda89e3e74e95cbd8358e2589997036148302b2c8dcb74a9756f020efde93d14c19eb1058494d0a455ac59054af1a8ba9232bfcb7d50130d1cbde06c146e4870576aec1a7ccce170d203a191803dec4f85c1acf9176be916ccb965214729", "47687cc33971af6b92788ce999cd85787889828fbe85d58e8cfd0ee11fc3d5a0bf2c89ebfd146aab17c6436d7198161c17de2e0c542ce6117a1e593697316a6a82290b09da7840c2c0d2be9d073eec1b3d7f194037fbb53641eb4dbd7badcec767cb69352ea369da8cc0d34ec660f4160c573311042e8ecd28044491a1b37c1d45cb84cdffce4694a6277b1d2441e0209c52d6096d25", "-25398da4803390d31d3052dd3340f2b11e358b6e39b6f68ad4bf595034915dde5d5c4c7c9e15d8b6c4732c78fdf45c9df469b2916ee07348738a4507ddb7f253012fd74ebf1ec29e875d6c8f868c888e37efe8cec5ed87de7fb3634808e701dcede0efd01c4e3ee00571ec7cb6ef1ef71066ad5b103fb9a32f66a788db1965538c381cc3806fa5badf9a31dbf32a08f630668f17da04", .None}, + {.Add, "e40c9d22691161d7c55002dc34d36e04d1ffeb42a77534c441e36467ca9c7121115ad6301cd8fd8ded4778c8865ec274a8a3ebc5aa902f4f07eaa3c982853993bcd106fc3f90ae4fc9b590c6624f1f89a87111e6335b513993e0fbe9e6f507d75e8b18b498e873332f1d60ac47e11688967aadc6a12f868eb567134f77ebb6685053ee1a05b6151ed543da6418f082090eee5c79c27f", "724af0b972ab0e6254f09ed21453cec11c79c4a5baf88b179a034ffc37216b2efaf19bf22053ff1c6ab47d0e3ddb7f4a5a99d5fa4b655cf150ad4084b579cbc573429d6be0b3374ed121a84ae52d95338ae8ee23777aa5ff89603e06879ed2bb3b07cf66cbc3d40aa3a92ef5abd144e95e14194b50c7a5fce09e22ac6e93ab18fbd2b8b263212e89891af862672aa7456df7ba1db96a", "156578ddbdbbc703a1a40a1ae49273cc5ee79afe8626dbfdbdbe6b46401bddc500c4c72223d2cfcaa57fbf5d6c43a41bf033dc1bff5f58c405897e44e37ff05593013a4682043e59e9ad73911477cb4bd335a0009aad5f7391d4139f06e93da929992e81b64ac473dd2c68fa1f3b25b71f48ec711f1f72c8b960535fbe67f61814c26a6cc68d743a85e5ed2c6801b294e7ce616977be9", .None}, + {.Add, "8b70ba4cd073518709bf123a93f0bc8eea0b90d8d500b97434091c3febe24133082456fb64d42f09c8f5b6b99316e454006cadc5c9d543ffdcf7449f519fb5880295f263039668410256c5364fac9770f81ef6847e59d791b40be8f60ae7a10e7c841ce77aa99ee7b6b20f8eb988b57e26ed7e91462ce806e93a0ded3afd2595be6ced9782bb5f73ea23c6c35a83bfe066b937f4915a", "62c924d07922ad4090ffd0b3fa3c12a8c67b794c23692bd97c3aaa555e711c19f574fdb2d70b08dd25a26043e807fb441dbd4aaeb014bc572e7f4c7f357dd5961f7d0a2313b592df3df5846b0b54fa449f5b69c14e06530acb20481c706f56bf6a4be8c768e835a7f10ec961a5efe4092fa6743a5fba42b3eab68694569346a75d1e8f6645a1dbf545f61d5dc7ba2db106c338b098e5", "ee39df1d4995fec79abee2ee8e2ccf37b0870a24f869e54db043c6954a535d4cfd9954ae3bdf37e6ee9816fd7b1edf981e29f87479ea00570b76911e871d8b1e2212fc86174bfb20404c49a15b0191b5977a6045cc602a9c7f2c31127b56f7cde6d005aee391d48fa7c0d8f05f7899875693f2cba5e72abad3f0948191906c3d1b8b7cfdc85d3b693019e421223ded916d7c70a52a3f", .None}, + {.Add, "d5066ab19085e91c49dcddf0e3acfe43834f0c4c9efa0232838d5ef7f04066843b3dace3480d9375f83bbd4c448c03c06c4def1a861f796eddbf661bf0cfe005bf67e68f0dbe4e4fee09cc6f4ec4a0470a0a8aa48a4d6f56ed822b47c13e015bba9a7250d3686c519e1355b62fc224490d5ab30392081bffa8120025471f6bfcd1af8b84848a4d3644ff075785a44a89c309266ff032", "be39e68d025cac807aa8acb19b2b5a63a15a84cbd752ac80c149b78da3b0c918f1600228466ea1cb14e24790b8a70e32bafaaa3e125a3fb40e2b0a25fe5f0b3eb68a61dbb7fd279231b85e78c710260149c3c6375f8694c3128b249081fb7be2455c87986bb607f240e5e6d0156fbb7fb4249e8e10a1dd1fe098b55605205b3279fc4bd8b3847ab1db8654a4905dde6c2652b239abb0", "19340513e92e2959cc4858aa27ed858a724a99118764caeb344d7168593f12f9d2c9daf0b8e7c35410d1e04dcfd3311f3274899589879b922ebea7041ef2eeb4475f2486ac5bb75e21fc22ae815d4c64853ce50dbe9d4041a000d4fd843397d3dfff6f9e93f1e7443def93c864531dfc8c17f5191a2a9f91f88aab57b4c3fc72f4babd75d380ec7e820855bfc160228f5e95bd8a99be2", .None}, + {.Add, "-40b97d0835fe8bc602175c80190d26f822f5b23c94db9c1f07929b78b411208478fab07b5b621b7568347b1e49801e93a4fd497c5319b22f4eac07148ef1297118ef4f31d852b902292d4a296ca6cac69a92db6748874a8569d3ce40ce3231145e6e494da5820cc80bd258bb175a18cf865c5a9190caf5f0754389d84ae65df168c46f9669cc9877f9ed4c3dbb5ce7a12fb07ac72be4", "ca0c5bc91d3b2efbb309bea3eeb43719772f323d1efb944a14e3c31967b97416db3f14b9bbaaae8de11b9f41eacbbefdd81659f78dd7a912dee0f3a868186d89be841f6d7656fa6f73f68e82b0ead71c4f595dafce8c8ca25cdfbdda1a6410ac544c2ed43980259c40a188257af91c6aadcd60523a4589d280788a33c69725f585af895aab088b8bdb13ecdb6440fe5a9053bbd3f979", "8952dec0e73ca335b0f26223d5a71021543980008a1ff82b0d5127a0b3a853926244643e6048931878e72423a14ba06a3319107b3abdf6e39034ec93d9274418a594d03b9e04416d4ac9445944440c55b4c682488605421cf30bef994c31df97f5dde58693fe18d434cf2f6a639f039b277105c0a97a93e20b35005b7bb0c8041ceb19c4413bf313e126a09da8e416b960a3410ccd95", .None}, + {.Add, "f0eba78931bd29e8c51348c310cbade0befae08bbfdbe9e3ac7ae7130abc1d1006fac87a2b077643ff88b69e7b1abbd7bc18b831692e1a09bca97d466c13c7308e6ce8a5d0cfb86d65a38c5d9523b54a0954039c442e7164cfaad6818d367c47f3964325af0a6d91bf69880aa53c6762cb11af2fa82402b9fbe6c8904f50bec65447e1f8ff0e5f099b26200e092dae296f0eed05ad77", "6577c6125f23358e7b1e95e0f07b448658ba402c15b5d538fab74420f875f4a48b96ee7bb72da50f03c22d7af0ba51dd2464837f9fe66d84498e3cb7f200518e6e74ba743faec038766c3760195235e38f68af45759ec9f95a06a0631dccc6c2bfbd62ad1c1baabca89397a80ecc6fe7eec9567debd158efd7b52d45d5723f6f28c52f7cf2128335cf6617aeb5a5ae9c0476fdb4cf70", "156636d9b90e05f774031dea40146f26717b520b7d591bf1ca7322b34033211b49291b6f5e2351b53034ae4196bd50db4e07d3bb10914878e0637b9fe5e1418befce1a31a107e78a5dc0fc3bdae75eb2d98bcb2e1b9cd3b5e29b176e4ab03430ab353a5d2cb26184e67fd1fb2b408d74ab9db05ad93f55ba9d39bf5d624c2fe357d0d1175f120e23f6a8c37bcbed35cc57385eaba7ce7", .None}, + {.Add, "5f28931047e52bccb44958c19d623fc78a74143e5f62716223b1cd05b12817cf1e6b70c90008bd732d1381385af48c45ee6c6bb4df28ea073fb8f745aa23db6e9d41aaa1cefb1719814a2cee876bf441a8028435ec8130116ce8088b4c22cb436dcf467f6419c3831500d30f4e3fd0f0679269f449467a6d3760e18b26b16ede6d748f959fbeb7e9f826fdebf33971fc744caf56f056", "4efb56a18a132486a478a6b77c32cb8b660fea3633de0e3f1b9002b89795853ee466299dea0c77976b5445522f3c369eb3e92999543598c08eecdcf164c858c3953a2ba98696bba1355af29704e56ced78af4d469d32b37c463f891a35d32a37a76df7b04ce621939b2da67026f03240bdd76708867ffc9f4f219244f7cabb329c835f0203376742fac1456049ce5d21ca057615fd2b", "ae23e9b1d1f8505358c1ff7919950b52f083fe7493407fa13f41cfbe48bd9d0e02d19a66ea15350a9867c68a8a30c2e4a255954e335e82c7cea5d4370eec3432327bd64b5591d2bab6a51f858c51612f20b1d17c89b3e38db32791a581f5f57b153d3e2fb0ffe516b02e797f753003312569d0fccfc6770c868273d01e7c2a1109f7ee97a2f61f2cf2e8434c3d07cf1e3e52256ced81", .None}, + {.Add, "-1672f2d2f6b05ed51374c5a891160806d53a010da16ed6986f04808b3318dcf239b544dc8243853844639cab102ef0e6c393b7917abae9412bacaacd72b76b8d25b486b585aba3fd43e5a4600e63d8b6af4b6b2534d9c499f78aef4600d12636456b2f9e5ff2ef91b7b0ed3121228b89671e0860c486e18e095d840bf2af2574c7401921568c91b7bdcc09b76cfc589aed51d215e4c4", "49489c93f617cc585af66f9cd7a106d1c4337a2d6372e474ae88c7c1c54d44ddf1a1c8f38040aa3a356177e4271cd8285146bb8f30f053c2885157e270c263d7957b89d1f238d00ff790b222313c704d0f05e3ed4c02b4c59f68159b5469ef729d40d606e00b5d38ce40421ff5344187981526f8ba581fc3f5055a8b1fe69e345b67e20061d331a49fc8acba78cf282485ddd2427af8", "32d5a9c0ff676d834781a9f4468afecaeef9791fc2040ddc3f844736923467ebb7ec8416fdfd2501f0fddb3916ede7418db303fdb6356a815ca4ad14fe0af84a6fc7031c6c8d2c12b3ab0dc222d897965fba78c81728f02ba7dd26555398c93c57d5a66880186da7168f54eed411b5fe30f71e97f5d13e35eba7d67f2d3778bf9427c8df0b469fece1fca3030bd2cf89988c002c9634", .None}, + {.Add, "-b8c70e4d9951d5f1d5f806a51e68270f79782903b420eaba63a53172a19d6879123ceeae5962b9d6fae5a563053dedc887ac87d46120fcd26f0a96459b5c6aff84966cd95a2e04793c68b75ba095d0bf0f1ef984fe6a63cd3fa66e4b557d921e37a70c06b73573497513802aa7b9ba172c8790aae00c146b39889f08cc1e536cc754b82311d4515e393c0b5bb4531e8ad3dc3907ab4d", "2596291a567428567c58263e39bc3f2475cc4036fb4bf3c9464714245bef4a463ad8899a4df4396e3efa7d91ce63ec090684310507baf79d71381df2096a6866dad84c153a1b75a57cf6c18614b6b16c76b92cefa4ca32553d807ad25c8e3d957321bfb4f9eb785ccb4740e2b4fbbd8ed56efcec17122004c9eed9d72b3a70110a4698a62fc3f14dd73d21dfdeeb74cc4736c3628d13", "-9330e53342ddad9b599fe066e4abe7eb03abe8ccb8d4f6f11d5e1d4e45ae1e32d76465140b6e8068bbeb27d136da01bf812856cf59660534fdd2785391f20298a9be20c420128ed3bf71f5d58bdf1f529865cc9559a031780225f378f8ef5488c4854c51bd49faeca9cc3f47f2bdfc88571893bec8f9f4666f99c531a0e3e35bbd0e1f7ce210601061fee97bd567a9be8ca575a51e3a", .None}, + {.Add, "-aa882c038295c0aba09d9911e02f9c014b005fb4204bdb50babdf6ebdc2868c52b0d386dddc55391928d01fee8a68e18ff6aa5e1ac8c111576a34c0314269794975b91bfd7c9269fbec67dab4f454b4cff7ed7121b8e4bf9a03098f492c6acc4c64f0b0b494e8b3eabdb049cf4d36a5bf825d2c083ce2e8cf466239c8c8fefcb4d8fba08eb82bec29622a1814f5aeba56519ceac5fc0", "c7ec16efb1db6706550c1f2ff9f6cadcf6c8a398ebf3c6d8af204d28ef88225d2e3956a74a8282bb5f1e2d35046fb4fb6df33a9ec39b7ac6f4288f71e9078c02b36f720ad14248ef954af13d0a28f0d0a4c7b71364d623f007a1e6dc5a7b781efabbe0d242b8897111793199d4573844aad6bfbed7ec34273709f61be9a9f7afcf41da0252749d4eb57a2f38a2f3e74de586563831c6", "1d63eaec2f45a65ab46e861e19c72edbabc843e4cba7eb87f462563d135fb998032c1e396cbd2f29cc912b361bc926e26e8894bd170f69b17d85436ed4e0f46e1c13e04af979224fd6847391bae3a583a548e0014947d7f667714de7c7b4cb5a346cd5c6f969fe32659e2cfcdf83cde8b2b0ecfe541e059a42a3d27f5d1a07e481b21ff966f1de8c1f578db75398fba8806c878bd206", .None}, + {.Add, "6538d0b912cd1b3865c44e573a9e3f18fbb405cf32e0e87d487b78f4441a3730342bb3be3f4af441634e87049f6ea2ae10f090eeab838828da89dc97c21139379240ea91ef4e913fe97a16acd8b14063d3cf8c9680e698425ba354ee9f38adcfc8b929f2915be799859a2af27dea48aa845e95b70065d3cf39133a605e8a06a8619b67fea4d947bbf07ed074f780bc5b6c2f86c93ac1", "ce1fcd591c6d27a191e7eaddd37371898185bf28f2f778c5ae51888e51d98cbbc3e21a71567c21f3885be2c3bf4ee3e689c22608453c4bb3ffa31d2ddca1f720f7f8c672a706fe44aa3821358eac4dd854a19add8cae14a8730c3e68a1b6348c5208b72dd1b38a08da19f8ae67860cf622bc654effe3a493393825095d6d490135d9352aa592647e017f0bf5a02d7c92409108eb275c", "133589e122f3a42d9f7ac39350e11b0a27d39c4f825d86142f6cd018295f3c3ebf80dce2f95c71634ebaa69c85ebd86949ab2b6f6f0bfd3dcda2cf9c59eb330588a39b10496558f8493b237e2675d8e3c287127740d94aceaceaf935740eee25c1ac1e120630f71a25fb423a0e57055a0a71afb0600497862724b5f69bbf74fa997749d294a6bac39f1fddc6a97ae38edacc08fb4621d", .None}, + {.Add, "-de427833df540079e271116c51232db8b40486fed15caadd79e155a174af2a0d1b5a6090951a4737a03b07f04e4bc8fa76c1c74a7d4175650c3b4a5370deca33321fe360acd27f10d5894bf291bcdc3010142ff44adcfb1c0ec2d5aa4e426ae0638cf40d83576706e1b5831558b34a32176346ed332d0fa2775abf7972c5e8cbc338e7f29dbd1fe52f7b3ed9c6eac30f5ea7129b8828", "c7d3281efcdf64c9261976ae3b9f292b692a705679a0595a645aff9e0a746a30504ded17cf689b26b1cb3a9c6f5a744e7bff7f6db25b5aac7bdb8d03c274c1c35f03803e9846fd6eeb514b9898cd6fe25773df1c7a65f7b2bc43f878add685ac7897e22e6dc617791836cf91d73d56d9bd716c258a922737f98e6ab5fb9c082a056c6081fae04714e5176b01fde3948e8b8770bc257c", "-166f5014e2749bb0bc579abe1584048d4ada16a857bc5183158656036a3abfdccb0c7378c5b1ac10ee6fcd53def154abfac247dccae61ab8905fbd4fae6a086fd31c6322148b81a1ea380059f8ef6c4db8a050d7d0770369527edd31a06be533eaf511df15914f8dc97eb3838175f35859f1dac7a89ae86a7dcc54c37729e0a1bdcc8770a2dcd8d04a63d3d7c9072e80d31fa1df62ac", .None}, + {.Add, "4aca8e0ec98f92c4ec3cf59ac6a4d4245a7a4a9180bdd2247c9b1117c642e2a7c1565285bca4da967322ab5722e372742e157a6055d48322eb62607d1a3b05bfcfe0c4acf154e10e19fa61bacb5a2473e6167277bb6e297fd36f67de4a09313422d1aa12011ba84c432274b34080972db325f62e29f235c7b3ea3170c0d83c1e1258c01099a42c4e1d7480461ce75fa43ce4143df099", "66f9b4bddb0af6d6c8f0041fe06bb15347a6231f3552db59891711dba42c2dca1c96eb9bdae349bc2c1a78482495f1e88c82f8039329f20897a688aa4497f6290d8163f05429b55a2d354c437198eeecdbe70a70772bcb7b7ef3377fb01ac519929cf1969091210e670c85454369a98f7c4d2f94b0790a41cef94f793843ed5ef2fbfcb2eaad5e18b6b05f9c09b0dcc783d57e79b7ad", "b1c442cca49a899bb52cf9baa7108577a2206db0b610ad7e05b222f36a6f1071dded3e21978824529f3d239f4779645cba987263e8fe752b8308e9275ed2fbe8dd62289d457e9668472fadfe3cf31360c1fd7ce83299f4fb52629f5dfa23f64db56e9ba891acc95aaa2ef9f883ea40bd2f7325c2da6b400982e380e9f91c297d0554bcc384518a66d424dfe226983c6bc0b992b7a846", .None}, + {.Add, "-285a239a72ff96724846e07610eca7e5dae351657790f8f2be68910ae79f3b348dd80cb97f3731bee1d0f647c3f734fb26a68f641a64dd66f69e8379e7591e7ae91578b9d144bec7302a4aadc99b0f671aedb07ad075cfd4fe4293314db543ab4ef89c1812726d40757502c8cc8059763aacfc00d574144510c5aff4e259ff9de97761704ddff59d1b0773b2a375a808aebee4b2a998", "4d0c0db5146959f62380517ef6fbea3d6a9f7c64be78d9eb71e3d8f9c7405a42f3789696aab95d49066914abdbffd7ecd58a8bf84e72047348884b40e35452844ad002ca9185b6a3caa2977558fbb262d07df4d8bba7c038670b5ac0e18975914547dfd44b46fb70cde02844472a92184539face1ccf9d48299b4666d59727c1d3324cbeca093d18d898f80b1307f9880e58af3dc74c", "24b1ea1aa169c383db397108e60f42578fbc2aff46e7e0f8b37b47eedfa11f0e65a089dd2b822b8a24981e641808a2f1aee3fc94340d270c51e9c7c6fbfb340961ba8a10c040f7dc9a784cc78f60a2fbb590445deb31f06368c8c78f93d431e5f64f43bc38d48e30586b257b7aaa38a20a8cfecd475b890318d59671f33d2823e9baeb4e7c29477bbd9184586f92517f5f99ca8b1db4", .None}, + {.Add, "d2888a595c4519c8d00fad553943be37aaa9ff192a59a576c4c58b156b863fd135cd2b3a1825004f32a511500a566964c213e72b17f176cd6803dc7d2b700a674c8f4d5967ee4d910827dd697361042554216644bef7118d5061c27b22d6217e556abf104fe0aa74615fe89da84d1b25dc0f58b0447e9ad98e1dcf13e3c32f131a9c85746a047f0370fa8659cbafd2a7bf0f8eb7d5c4", "da75d70a06c273fd180f35c529fa57a8b762ce1d17b0dea154c99258c7cf565a1b1a5905c61150e4ddcb95fcfb28baa355d67a5ce20b2c6e03be7ab56bb225c8dc70e44f3780b7b730eaaf4e8b0a440c22869a6fafc0708a4b773bae71d85e87f4d52a2612e38810f0e2f03766d033e3335ce0243a37c2f9975dcb7310b4a037f52f77d38740a8b0f15c1fc037cb9e74178e722b210a", "1acfe616363078dc5e81ee31a633e15e0620ccd36420a8418198f1d6e3355962b50e7843fde3651341070a74d057f240817ea6187f9fca33b6bc2573297223030290031a89f6f054839128cb7fe6b483176a800b46eb782179bd8fe2994ae80064a3fe93662c432855242d8d50f1d4f090f6c38d47eb65dd3257b9a86f477cf4b0fcbfd47f14527b46256a61a037b711bd69e00e2f6ce", .None}, + {.Add, "8189b27ad95dbe331aeee12438505c490f018980e3b268c5bac503c43d2051abc2e1a4fc5ea4e9311038536a1129d8ba8d7aa3f65709a1072a6c2cafc85e4b26095bbe147c00337caca0c00309285ddd9723a0533e368e1bc8c772dabd3fa0509b13390f36702417644034280db1b67e87f01ef628bbfb457909b2c2f06dea621fdd63a96ab10418c3c4c809647c937aba41b1fcaa8c", "c201d73bbc5c7920df5fa86537fe1b9f3c362953aa837ac188a56487955cde3137b8ab1b18ee8cb2d60b911c1ee83c6e24abb64e217f52ee2a56862a2e9710611de3f96d68a850e8464e3fa346a672ba8e2e1d33cf7916e56f08021061d4ddf369297dbef1b1514b8ebb2b6f6fe429597a5ab062d678e6c4cf46f76a8a53ea9322dcb66a69feedfae1fb98a1b78372fe15f4d0cdc9b0", "1438b89b695ba3753fa4e8989704e77e84b37b2d48e35e387436a684bd27d2fdcfa9a5017779375e3e643e48630121528b2265a447888f3f554c2b2d9f6f55b87273fb781e4a88464f2eeffa64fced0982551bd870dafa50137cf74eb1f147e44043cb6ce28217562f2fb5f977d95dfd8024acf58ff34e20a4850aa2d7ac1d4f542ba1a13d4aff213a5c060ab1c000678d03682ca743c", .None}, + {.Add, "-e3fb78863c6d172b9c03fc2921c1f47142a318fa5e4642afa4bfc0d6d5621713eaf0a92e385d3a11772cfd62cdd333cfc5f6691d136c768ae705d20cd863c2e0bd4bbbfa2b9caa8270f938905cf6f36e74a0dabc3c0e947f9d2ee256aae8080cc6b307772cc05d1a159e537b1892e2c9f49bd938d57f66fcc433e256af8da67eb90a5bda7b2a4587d9745097b39f8c236feacc246b9e", "d0f5d1dcb2ea55cfe13244e9769243f24902b5f0faec267028e0ac7ee1af6a577fd922644966922e7c5fd58c626aa5c39bf9fb87a30eed09f098ed53d63ca331bdcff59f1b0d2343322662b8cc4d0814ef9208cee47673c5f139e342e5ad689af46fb60e30f68b65468bbd7001b5b703522448323a477869cb5e3cb8f8ea65ac5e25f4b46b3040781ccc091cb988c5c81d3bc745aba3", "-1305a6a98982c15bbad1b73fab2fb07ef9a06309635a1c3f7bdf1457f3b2acbc6b1786c9eef6a7e2facd27d66b688e0c29fc6d95705d8980f66ce4b902271faeff7bc65b108f873f3ed2d5d790a9eb59850ed1ed579820b9abf4ff13c53a9f71d2435168fbc9d1b4cf12960b16dd2bc6a27791069b37ee92f8d5a59db6a340d25ae467260ffa050fbca8477afa16c65b52af04debffb", .None}, + {.Add, "-e915d954afe8a771955ce495bc3beb1c83b8df0a12d765aabe4916f0b1dd50905a43b8a163c6babb713af749b5a6168e550163d7da07e07cfee69e56596a76951c8ee45bf2974f49166b2f2b69364eaec30c4d9585572dce7c83cb533ef057fe95ec377407f5a8e1f4f25384cd7ca492dbd99547979e88cd0fe52be62389e87b1e934a6b92ccbf824b56c765675f0489adf5e1ae553f", "51b763232804eb492114812b40106f1f69510ae4213276d3d244e57ade303ad7ed356724643b773dc5bcb7c35bbead5e690c00dfbeec016a20c61c9d16b2b131b573cda5e8c3ffeef7fe3ec4e9ef86abb7f35e7cb19e1471bd93a5441b9c4864bafe20eac2d4128704cafaa232585b50c9667e3d7f5c07f7e5b04f060810887592dda633aeb8832c0c2c73e0c444fb9b0485f2cecfe1", "-975e763187e3bc287448636a7c2b7bfd1a67d425f1a4eed6ec043175d3ad15b86d0e517cff8b437dab7e3f8659e7692febf562f81b1bdf12de2081b942b7c563671b16b609d34f5a1e6cf0667f46c8030b18ef18d3b9195cbef0260f23540f99daee16894521965af02758e29b2449421273170a184280d52a34dce01b7960058bb5a437e4143c563f2a5384a31a08eea96feedf855e", .None}, + {.Add, "e8af14f5b4dbbc6af684b4751c1cea09c39ebe19a13a1e836a770ad7a823c91c44fbe6038ac1e18ec263c4294bd767098789dbb01c05e4c090abaec88709d7caa366e84007e69f8f1958c66a67709e6dc8d5d700027fc571fc09e181d969159be19da9761dc64f1bdac6328d9bfc2b92b3d032eaf2cfe37faef75b342ed2a4727168bda71103d6452983f3fa8c69b85863d1b40b514e", "8101f4b7fc4099b7565019bb94c137617372e4bfdf7b7c510482245aca5d49c0f94192bb4047a1d1a7e13b846eef027c1c46ff815fece5a474a034362a4409ecbcf8c8dae3a363b79ea888cb138bcc41cc950115e27ee2b9a28864c8b3618904154473af63eb0ffb2e66b31379a52b9b6b3537b0ed110675e92cc1af3c4ad8738de290f7d0414350d172e7c2f32c0195aad524d8db82", "169b109adb11c56224cd4ce30b0de216b3711a2d980b59ad46ef92f32728112dd3e3d78becb0983606a44ffadbac66985a3d0db317bf2ca65054be2feb14de1b7605fb11aeb8a0346b8014f357afc6aaf956ad815e4fea82b9e92464a8cca9e9ff6e21d2581b15f17092ce5a115a1572e1f056a9bdfe0e9f598241ce36b1d7ce5ff4b4e9ee1451995faf6dbbd7f95b9ee0ea6d8e42cd0", .None}, + {.Add, "-8e3fb2b8f8d2fcc9c88f70df2a69a1522e11b6b6fb6ce030535d5c5c48024a2429ab6daed2ac4973c945bbacfc6e8b43f46b44e25e2453fe2b75535676db8d5a602414a6957e131d808f9f632dd66e786f6c8fec89b89b76e8271875c97aed16411ad2758cb383c55ebbb60837ad54392573839dbff21834908d353fa4e830d641437e142bff520d7975e0950df63da77e1266bf425b", "5495ffeeb8beb9d27394e3f025b5412819923ae75dcac04fac6350556cef56232fa5d801cf3729901adeab33ca6f10ffa890a12759547bf48802f36e7bcd686d0c51d8497f8d6178c8bb0a4e873527d17d1fbc4d7b33479059c20afb8b4e961599da53323564b9e57040c90a28b4ccf117c7b7b774976f21c8226cf30ac63cab54b531e4bf47722f90afe5f04cd4ebbbec8b0db2cc12", "-39a9b2ca401442f754fa8cef04b4602a147f7bcf9da21fe0a6fa0c06db12f400fa0595ad03751fe3ae67107931ff7a444bdaa3bb04cfd809a3725fe7fb0e24ed53d23c5d15f0b1a4b7d49514a6a146a6f24cd39f0e8553e68e650d7a3e2c5700a7407f43574ec9dfee7aecfe0ef887480dabcbe64b5aa912c86ac84c9a21f42aec8e4c2f6cb7dfdde8c5faa4c12151eb9187590c7649", .None}, + {.Add, "b233b87798a8018c7bcd20b80085eaaeb4e49e20b82a50cd63180030121509d66c28eb3dfd96fe076cb68ccf96c4feed6ba3c2bd46a7067fde2e4881f26a6b5d6a438e124e9994f3e999c7618a18f7c7c5031e737e962291ae4987920e6f642b58eddc25fb95710c5f50e6d96b6ab13bd52d16bcff018beb3b8a10aeed7fa497900c5f61c90ec5cdc59915d3fbdad9fe7fde514052a4", "664e6a4ce68c0f176c878a60bd7a99197f9234b139b02aa0febf33d8ac53fc84ae5544d7d56d1d99a2750a6b14db583ec2da8c8a4ff533756747c2d25ce4b9e62c4f2d00555376607dc99ab8ec83f95cb62ffcc01ee4f67057e07184e948324c863eb5bb90d3bbd88de8da1c87f9b7c809eaa12210bde0af57ca9ea780a53638112925e529517e79869f7f6227adaea7793bda47ca1c", "1188222c47f3410a3e854ab18be0083c83476d2d1f1da7b6e61d73408be69065b1a7e3015d3041ba10f2b973aaba0572c2e7e4f47969c39f545760b544f4f25439692bb12a3ed0b546763621a769cf1247b331b339d7b19020629f916f7b79677df2c91e18c692ce4ed39c0f5f3646903df17b7df0fbf6c9a9354af566e24dacfa1358546f26044474c389536238888a5f91a2b881cc0", .None}, + {.Add, "-1d16a793a86d839c9003bfdd05fa1878b1c87416a3872bc38d640daaac86b3e6e7b9e837b75bcf939faf0e7b781b295e8e1e312525f3aeb97eeb47c08efafb212d1c510ea71f3cd30bc0c697b494b73d7aedba84d77d145d2bcb7b61240361abd6249e17af578939bac7cebbe8f5a3ee9c2c195b66ce0e1b2757b95cfd3677acfd40c2ce0714f1a562e016f16dfb90cab07c041784be", "a7db0b4a3378c896695d40c140ece8a0315a3d78a73a8b81f8cf5fd6a3cf7d66b1212dfdfa5972d3e61827ecc672ff60c340683cbd9b3853974279ca0c7c6091bbf2d9ad0cbe7cbbf041ab90e931004459845e46abb8f55948961dfb55d857908ddb1cb46501e7a364b6e557d2dcc813173116ec5385c011fcd855b920f6374f42f6a5f4dd98954ea90b0647e197f42af2d3d0df968e", "8ac463b68b0b44f9d95980e43af2d0277f91c96203b35fbe6b6b522bf748c97fc96745c642fda340466919714e57d6023522371797a7899a185732097d8165708ed6889e659f3fe8e480e4f9349c4906de96a3c1d43be0fc1ccaa29a31d4f5e4b7b67e9cb5aa5e69a9ef169be9e724247b04fd90ecb7b1f6d5809c5c23bfbfa245b5e326d683a3a9462aef56739c63604257ccc811d0", .None}, + {.Add, "-94511fb1d18c9a0821e2a756065422132824a3bbbb4219e0cb5b644288105583057c05d118e1ec3685fa6c3f53370250976d1b7de578a899bd42ad8ba0bd6a6260001b9749e8c141434b4fe6ca99e4f7bfde524d1a89d4b2815bd38a2871d961bb81ba60996188d6abbb45986d282f78921329d8f5c737c7c278ed4cf569cf5cb361391f3d691dabb369fc047673e73d432ea4cf7620", "6c410cfb62a9ccf087f2d26dabdbefe53669aa4dd6436bc383dc7e8f42986b0eff39b361be59737328e99df77bcbb111967ac928347d27290a79729bfb4655f807e6769a4b7d7466d5166acb2bf7c2efc7e5ce431d9608f82740bb4e47a67aba8a5fc8a731904a4df40256995edfea6a66efd0fa7699e4500b4d6b94e38ecae9c6fe6555936411bccba7ed9af1e1566f3ffde0047af2", "-281012b66ee2cd1799efd4e85a78322df1baf96de4feae1d477ee5b34577ea740642526f5a8878c35d10ce47d76b513f00f25255b0fb8170b2c93aefa577146a5819a4fcfe6b4cda6e34e51b9ea22207f7f88409fcf3cbba5a1b183be0cb5ea73121f1b967d13e88b7b8eeff0e48450e2b2358de7f2d5377b72b81b811db0472ec62d3c9aa050beee7c20e69849290ce0330c4cafb2e", .None}, + {.Add, "81be11440f7c6fde6f814e89e3983b5258e0636bd767f8b6668556551a83781c80177299912f44c6b5b753fb2bef4f73ea3f61add919579105f9d181d82ae4b34784585fb0336fe6445133da8ff6938ad2a95956ee8b01aa5126aab75d15592dca6b5e56bdc2ca41b284000884b61cad86a5bfb1805bfd9ee5025176cd3bc3f126016b6036fd7c59509376cceec13f6a193eec61f0c5", "4c77d42c340566363a368d335452822080fdc0ce682d907c01f3d70242442fb22c26d71acb359bbddff50e04fd56bad4bcaf4567362be3ad8c84466137d1b2aa2aa73ee981bfd1f81b7bbc292f63a6edebb3d9ba7adacfc784b87a05f68657544af23856262aa0e95ba157172326c879f52fa664e57c8acad72e54ccad1ec6a37f2418f637c97660af2dfb7e0956a16418cace030a94", "ce35e5704381d614a9b7dbbd37eabd72d9de243a3f95893268792d575cc7a7ceac3e49b45c64e08495ac620029460a48a6eea7150f453b3e927e17e30ffc975d722b974931f341de5fccf003bf5a3a78be5d33116965d171d5df24bd539bb082155d96ace3ed6b2b0e25571fa7dce5277bd5661665d88869bc30a6437a5a8a94a52584566ec6f2b9ffc1724af817e0ce3209ba64fb59", .None}, + {.Add, "-22a6224d381b36a3a7468e0f0efaddd3e987984bc2ea99e2a8b312109b99e157e20b6534f251e73812bce7af93dd5b6e3108df39641d2abd6e2f61c367baec407dd6cd99a80f35e03bb280923a876d890e4b0dbc2427b97e34b3eb894b72824678651d1adec7e9f0888112ab0b7d6d1ffd3c64ad33914e049da5f7298e6493c13313a1eabd118c9e2a92d129edff6d252edc49d4e354", "918e944f55c6bc10b04110ae28fd79edb227827384eb873effbe197c56391991df271ba62523f9297878846a2ec73b75ca30a5f8928572bd54acd9f3a0e86bd26479207ac28eb66bb424aad3345bf6040ba7a598db0028104528f8d2a3e9f0631f6eadb29cf374d46c04ee192c6740211dcf8eef3223cdd95a94b93b2ba0572e9118a2f3eddd7bb80d7abef1e013bef10fb1a576bab9", "6ee872021dab856d08fa829f1a029c19c89fea27c200ed5c570b076bba9f3839fd1bb67132d211f165bb9cba9ae9e0079927c6bf2e6847ffe67d7830392d7f91e6a252e11a7f808b78722a40f9d4887afd5c97dcb6d86e9210750d4958776e1ca7099097be2b8ae3e383db6e20e9d30120932a41fe927fd4bceec2119d3bc36d5e05010930cbef19e2e7edc7f21451cbe0d55ba1d765", .None}, + {.Add, "5b3b4bd41b68d9d49b9e03eae4630a25db5ad23943f76bba9d0bec99bf0db1fbf3b0331777444e8000aaed56fe41d769ea689292e9e4157a655bbb45593ff543a91fd20ca9de8b12cfd6991e82a10b20fca17a6a2d56ea37d590140467c65f1e9814dc372a6d89d2bfdf54f48cb6f654bda110a2acd8c13e72065202302fc27e97899a4796c3c7018e22fea19d6dd501e25c801f8a17", "5a8b283d511100cd06f5e5120632d23804de28974d5a51caffad56f6ebfee9f9bcc0f1c0d0e73054c2368712228d01d87f7191f18fc0ce92b1b675162932ff0d7d1ee101ef78c23847c8860d2a13fd9b6bf01a24ca92b64daef1272ba2df901b66833e37ebb9cd23b1882689a388ed4bbdf837160867da235c25ace2b2457725252fe1522818fcccd9f3eb7980ea66ff40e870f10639", "b5c674116c79daa1a293e8fcea95dc5de038fad09151bd859cb94390ab0c9bf5b07124d8482b7ed4c2e1746920ced94269da248479a4e40d1712305b8272f451263eb30e99574d4b179f1f2bacb508bc6891948ef7e9a08584813b300aa5ef39fe981a6f162756f671677b7e303fe3a07b9947b8b5409b61ce2bfee4e27539a3bcb97b99bedcc3ce6816ea1b1e583c012344f1109050", .None}, + {.Add, "c974f852f8164ce5d4c0d5bf07e6dd1bbdee1bc76448e3bf5c86f812ed0c779bd2ccc5d333f64f145a0893831e5d9e3f5297f281c6734e5f1c725e641c4d4bdc8ef839a8492d1a934d4c6fd40425f8f03aec87eeb976e694f0f49a86f5b920e2bf89a6392d3980a5acf908c4798f50be653ed49a81f37c5e183a10e9d6593aa04f41ff6b1af3baae8b75d98d923ecb884224fead2cca", "cf660b93282bbd389228eb8fa4dca8c4e9c47ff8a7a66c53c485a11e7dc81f33e1d56091554953fc14e4ff06a7f11640481bc605c1f09e88c1cde706e9994fc17ca9b7d3638788a970f289b2c02e0786144f9971a163e879066aadc52b380af0ab9fc1912c1db1b225d2d842d3a0b19f5d4d4a3a48b8db277298e4beb06419542e2ad07f9f5885790e6125e74fd73273e5f23b2bde2a", "198db03e620420a1e66e9c14eacc385e0a7b29bc00bef5013210c99316ad496cfb4a22664893fa3106eed9289c64eb47f9ab3b8878863ece7de40456b05e69b9e0ba1f17bacb4a33cbe3ef986c45400764f3c21605adacf0df75f484c20f12bd36b2967ca59573257d2cbe1074d30025dc28c1ed4caac57858ad2f5a886bd53f47d6ccfeaba4c402799d6ff74e215fdfc281739d90af4", .None}, + {.Add, "-896381848fb26af670f495bddb71cd6489c1eb20f2feeb950245576d486236d2e24bc1257f21c00cddc1b3cd95995777bbf8e9c3a51e4e10e39feb052f939fb08a0ce1689e8dfe2bbf66b7895a71a0d74fdad816653287aa6e4c2055a4ccdc48ae882d95e7f501aa7586c33ac7316acbdf92cb6fbdcaba35c466d8a0997dab5a82bdd8690560e14003ebff4a8b3d0e236789d7990e9f", "dd7672963d0e9df5928e101d8ad068a6bedeef303199af58bb6c18cb2c31e985f8d8df9807a9d742fcfa853c4434b1ad621aa2b1be23d6656ed97167bc12f805dc349b5b4790e85063b9df8042e021587bbfa688611a198fedf58fec1193f918aa0d13639d99eebcadaf667cc67145662e2fbfec2d2b137505fca8b3e734c3042a278e73ff2a59dc16753ec898f67112a6a96cfb9a7", "-7b8c1a5b2be1811717cbb4bc02c4c6da1dd3fc2defe5509f768e95e0959f183a82be332bfea72298adf20b79d1560c5ce5d73f98893c10aa8cb253eeb3d270302c4997b2ea14efa6b92b199156439ec1c81eddaddf20e6116f6cc756e3b39cb723e75c5fae1b62beaaabccd2faca56757cafcf70faf808fe74070e155b0a5f2a401b5f81c56e3ba24284ab5e01ada7123d1f40c954f8", .None}, + {.Add, "-987a011fac158cf32c8966f33757a8a282359f95a5ce1c10e890d0ac9671b8d5e89aa2269cff50d679b7bb747627dcc2013b619a9b8d4b70bbfa7078f6abe5dc16860223cf17f173631c338e3ad56b7f3b4728e8c963ce7a2835a2b4b561a76d471f8cc17022ecd219fabe28d70258000558aea8feab8b922e3a14cdb59558f963682dadccc84dc478f4c89acc791a6badedd9b75b72", "23b3e4daf2355c3c18259c3ab9ad7836a61d84a03f385cdf946d63b18785d487a4f890dc5a2b071d7081c3792ccd05023a999d8cd2f04a6a76f5f4eb61f093cfecb98367603ce3bb0632394a1ba757430a3672abc66de20089571c4ff54253df15b65946ddbd4f49d6a80fe1025a30d43123b28cb8ec3d02544cc4339aa255596e88a011e0aba4edc41a61ae2038e607b2ced04c0b8a", "-74c61c44b9e030b71463cab87daa306bdc181af56695bf3154236cfb0eebe44e43a2114a42d449b90935f7fb495ad7bfc6a1c40dc89d010645047b8d94bb520c29cc7ebc6edb0db85ce9fa441f2e143c3110b63d02f5ec799ede8664c01f538e3169337a92659d884352ae47d4a8272bd434fc1c45bf4e8fd9ed509a1af3039ff4df8d9bec1ca8d6b4da66ecac403463fb1f096b4fe8", .None}, + {.Add, "-ef3a8aafea9f1b6a1b5cc765f8a5adceea56ffc2cf3d4b70a8b43ddb2e058459d37cebdb02df70a080366615f53e321d2a0cc398dfd443305ebc9fa4d702feb8451dbb9e1d3763f5b286181c80fd4a9421ef9ac56dad506b159aeb420b3407a23635ff8301185b840c50319fdbd45203d72a9b47f0150d9fe9c09f3268f42dbd298a1518764355092f393841b00919ca6fe92997729c", "a2812823079dd4c12807d5bed97501837ba58779f2af80105779cca8f1d49006dc46371f885c700520dbf4b5955dfeb741d03d46eb557e6ff3870aa857a13a4fa6f7a8c08e551392b9421f1ebdf52c6ede6f4439e727ce7a4572b9e8f078574df428bcbdd6857c5c97718bd853c6d505b01a81946fc4082595ef809508045c6e8a24b9c6cc61ffe3066a768f413270910be85dbbd8d2", "-4cb9628ce30146a8f354f1a71f30ac4b6eb17848dc8dcb60513a71323c30f452f736b4bb7a83009b5f5a71605fe03365e83c8651f47ec4c06b3594fc7f61c4689e2612dd8ee25062f943f8fdc3081e254380568b868581f0d02831591abbb054420d42c52a92df2774dea5c7880d7cfe271019b38051057a53d11e9d60efd14e9f655b51a9e1552628cec1b26ed6a9396400cbdb99ca", .None}, + {.Add, "1aa80c9044d5273c2b88fa817a679ef19e4c8c626abc3761eedeb52f727ac6cd14b30cdfe0a6afaad548c076388502ca8751a6b76573eb06dc4621a6305aa6f4f682aedfa5a80a3352929e2011b573fb6dbb70ab45ccb538f1ff74a2e4085902c409de95293b4be1fb6723d726276b5375893c0523a0bc44f2539c80979ef6cb3e20121b1bf98acab6ec9146712d7a581a6ac87adc05", "8d6912eff4febe26afea21453229f59771fc7089394fef6a88cb7951e7e3319c08a5d1ec2ea8300142bf8ede60f485a5189e19bd90cdbfade872a2ee70710d0e61a8aa50c32a1ead6a9f3839b962bd23338cbfcd1dbd52f47a31f302e85f98920cc097bb2b8e5585cbdfd2aaa7f0f192ba65813ff18b606743a973803f13e60a90b44db7f1227b7cba1ab2e4701f4d62e52fb3c79283", "a8111f8039d3e562db731bc6ac9194891048fceba40c26cc77aa2e815a5df8691d58decc0f4edfac18084f549979886f9fefc074f641aab4c4b8c494a0cbb403582b593068d228e0bd31d659cb18311ea1483078638a082d6c3167a5cc67f194d0ca765054c9a167c746f681ce185ce62feebd45152c1cac35fd1000d6b2dcd5ced45fd30d1c06477107442ae14cc7baff9a7c426e88", .None}, + {.Add, "db2906c9441d86504eba0da43f3a805643b838a9f048bcf01bf601b09c2fcb86df17d978cf5051c34ac369c4e4ff1e2f54afc891fce7548f82a3042127a55cd594e57ffe48529ebf3ad859c6b17610336da6cfd577fa2764756061c9e4f5c23f54e5491e0262d45f735cb3ff4d472df543e18dba1c93e976f50b6c0a0f2437d28dc44d74c3b7e93b73c6f90cf8b5156b223f57296691", "ca31f41ea469b0524a33fde9e954968d1f5f696f8716e39fba110df673f780110775f9870022912c9903cd6d0a6b2ecc70166a045737117abc641ea3559b7c295b47ee9b7304e450290b4690120a9a93f665f25b745ea50d8ae6a01e0c661ed667134e27e96871b51f4b96e85ae82e8f54b7ea707855480e2b58277d7647fbde11fab24c70673e71055185d5971ba12b76d05251b9c", "e7cc260b2e642155735d4d82ddcfc9bf15ae2f40e8ba2b2a17971290036f4387ef8f39113f527ad61453a69bb5a5d11c1bb12f32425ac5a72e69460b5cff14982a99fee7ff82ed043d690e2fb296b9dcad0d2efb2f4011b54e0ecbcbc5bc242cbb567e0080f95b7ac5516d6dd2f5b0de392d0c6124193df7d7c0ee81e688b7906ee3f8998abe5d22841c116a5226cf7dd9ac5c4e822d", .None}, + {.Add, "-a195876bdc4adb3677d20816f1f364f5a9dae0f388225f587ba3518e82a56378ee58bf870c8946a1c376f5c8d27f626c13ff4f21c5e07c46405a8e90966d99dd1e0ccb8bedf6ad7978c85677037cb8fae5ff1f31f61f9867195365789f9ee950947792cf037eec14d1647b80e004124bffd82fa99d2956a41e4302f9157c05207267b00188058ad708ee5b1a2bf47b1521dcd335598", "31229f0988db88d8b945b698a9fddba810bd9e4f50d16f258e2d13ad6432c0c9e80ac185ed6727c4be286f689a648e0e60e425fd080744bd525917695b96ad88a5bb077a7e6d1f5b6b5fb725c85c82ddd4ae5ddea7e75c8f4c6ae382e22f131b39ce3456b58ca55a76f0fb4f26d563449b3b5a281a6842eeb8b4126911472431088796f356519413242d7a7f379296754a4dc1975e04", "27094692cb16db2551c896173adea558b61ff040184f49300672de947c086a925925358d7c9e935aa1f1000c0d3c97e79fa4310aeba93cf8ee536e80522fd3ead3da3ac1bf8db483d3d331be5824b74e264e6beb88856308dad5ad2b583524863086bb29c554b69929dab39718d5221fdb3dd72d8095ad8476cfe2397fef63df01611bf33dd13b65b39e94cd94d34ec3f82ff464086c", .None}, + {.Add, "ac101d8be1369910b586cd3161829ca1aebcf83995dfcd58a1bf292a4405b5c8c8b2fc4ea683b5d25ec8cd79c22af468d9eda047078757a96fd0829400a1e74045f7912a9166d3f354c835a4b629f3edd96879b5e304c78730f6058ebb82149e5b606f7273af77f9efcb19733572db41b8dabd0da62ba4ee37560be065f4677ce71c75408a7a0512e0c2b9967f66688802de4f704dfc", "98c216258db4d3f74b72a699b6439d172d1a845e706f4f753aee2ae03721622d000e7441065654425436ba59ab2e4093608670c477f4b3d509b25a13ff72b0876d26b0ecb081aea06308e8075daefb28d8ff07a1f2bdd2adf5c76f56834b8ab5206839aa3f6532919772a6c66b0363ac1f0d161beaa838892c4ac5326785a9ffbead0612e24680a8a5ff13e5024d7fe5a2bee09f6276", "144d233b16eeb6d0800f973cb17c639b8dbd77c98064f1ccddcad540a7b2717f5c8c1708facda0a14b2ff87d36d5934fc3a74110b7f7c0b7e7982dca8001497c7b31e421741e88293b7d11dac13d8ef16b2678157d5c29a3526bd74e53ecd9f537bc8a91cb314aa8b873dc039a0763eedd7e7d32990d3dd7763a0d112cd7a117ca5c97b536cc085bb86c1cd7b81b3e86da59d300fb072", .None}, + {.Add, "-49a1871a31f230685359a05c2a84fca188c4f5f8c66b326a48d525bdafa244f0542a944d8667913b3484e27fa8a3a8615c542ca6d1cc4092e0d93464504b3cbe937945a8e3bbeb3cb4979d94115d16d9abc36e7d50a620514016357b9447f5d5c7d80fab837d35b8341711e5f482022b74658e6b1d8d3b6f081e374e22412e19717e7b6c2507116b68dce57e94c218c16de4d9e17887", "886038b13212a844003c4762d98694801253b29aacbf436d2bd085007b2679289252bb2f5b5647b37eb5e9ec3cc6de7a4f839b0fff2772225a91d1b7958d2e918548a6e448df05ff9ba16e4b39667786c6479bee9feb808375a5e2dadfd8773a3f42d78ad1d951d9f0c066c4e6df612860dae4489a3709edfe5cfa2bc1bc605401609a94006b3a50bb932b2d714779d75eb6a673ca8d", "3ebeb197002077dbace2a706af0197de898ebca1e6541102e2fb5f42cb8434383e2826e1d4eeb6784a31076c94233618f32f6e692d5b318f79b89d534541f1d2f1cf613b65231ac2e709d0b7280960ad1a842d714f456032358fad5f4b908164776ac7df4e5c1c21bca954def25d5efcec7555dd7ca9ce7ef63ec2dd9f7b323a8fe21f27db6428e552b645aedc856115f0d1cc925206", .None}, + {.Add, "-d89a36d154d908c7b0b4d492c0770b4b4c0094683952fe156f7ae236be0dacdaed9943af899fd850676c866407251ad100326139a77fbe3db4b51fa2c8396a1348dc29da3c68bc4355c3b6e02a436421c78e09e3ecbc1beba74b51f5776e4b0e44932f87a4990e46a4dade0cb03f2f4e6322082fd33ff5948f7380e4c95ce8802060f2df167d689ce41c4be79813c22c59136cd5ae8d", "e724928bc87d938c3cd2ddd2f5cd71a8386c263031e7735f6749faf7b377c99fe604e40ef2edf6075b3b4a4ea2014fbd307e54987041ef6464ee07a83b87020697cdd1120bfb9c5849805581a568c5c532e550022bff7ea86c2d7816c8a7ecd28d9ed23325a9e3402df03a3ec3dcbb2b184545e0daf71b39b3300ba79369a79e39d681a5d9a988b9b289cc57dd00ef8909808acbf29b", "e8a5bba73a48ac48c1e09403556665cec6b91c7f8947549f7cf18c0f56a1cc4f86ba05f694e1db6f3cec3ea9adc34ec304bf35ec8c23126b038e805734d97f34ef1a737cf92e014f3bc9ea17b2561a36b57461e3f4362bcc4e226215139a1c4490ba2ab8110d4f989155c32139d8bdcb5233db107b725a523bc8ac2ca0cbf1e19758ec6c32c201cce6d807044ed2d5cb06d1df6440e", .None}, + {.Add, "-8f90ac9f1ddbca465358b73bcd28ada444fd274e148c4a6ddee117292869aa2755cd257c3d40d2335ea38802632f18d69a535c87526f769409e7225355ea437e60e3e40d2558ccb80e38ad652f0a3217954e033fae8627c02122a0e8cd57835de193008a0e867b1b7753136181a46abe71204de42f9495e150ba5efe297823faca49bee7a212597d80625359db239099b8a88b3dc6d9", "ec89a787375fa466a466791f215ac4e84f953b2eaefbfc13f52d7fb7e0c32116aac41e846eb10be95d03abf13c87065e2a0f55ac22d1617dc4801416c90349287f60ec87be44be40db44b886d2a20214ac3d937a6ad3fcfa9dcd537a473fc69e3d8b014821cfb0b14a35db49d6f1e8871a4b0c9c2b9e011cee1a9a2682af6371db155e0e49d59510fa722a2c4fddb468b8caf26c9932", "5cf8fae81983da20510dc1e3543217440a9813e09a6fb1a6164c688eb85976ef54f6f908317039b5fe6023eed957ed878fbbf924d061eae9ba98f1c3731905aa1e7d087a98ebf188cd0c0b21a397cffd16ef903abc4dd53a7caab29179e843405bf800be13493595d2e2c7e8554d7dc8a92abeb7fc096b3b9d603b2859373f7710cb9f26a7c33b937a0fd6d274ba23cf0022672ed259", .None}, + {.Add, "-72e98c819c38e5f6da612cf2faf273d65eafb11324d03f1a26a16459bb82b295fcfe7ba867c145111bd0b8ba55277ce159947704fdc8ef5d94e0505a3c8a4f469a51324f7bcb1db50eb75ae8c02cc6283e52defd7dbaba4bbfe37d1549be607e72e91745c7ae8fea09637b6962e5b1f11b26f8f55ee5ae6043790cf95761290bd49d387d2a098f781cdd8ad9174d6c0f7c4676d6f35b", "b7aa52413199ca4a2a04647e15a847aa2af7da88f3f5c64b2d7d04d75a0c59db5f35ccf77eb2ffe24271bffe78dc323ee0af94a977829a83059f95827a07c163831fdd4997b42f0f190024d02fb5278d9083feb8856f573b9f724089dfeb759ff7859f10d0ae1346e90004c75c442910d4b1125d34c8284c0c8ed84583722ca6f7958aa991e7c3a0ea3565b415a66b1966927455c49b", "44c0c5bf9560e4534fa3378b1ab5d3d3cc482975cf25873106dba07d9e89a7456237514f16f1bad126a1074423b4b55d871b1da479b9ab2570bf45283d7d721ce8ceaafa1be9115a0a48c9e76f88616552311fbb07b49cefdf8ec374962d1521849c87cb08ff835cdf9c895df95e771fb98a1967d5e279ebc915cb4c2c11039b22f8522c67de3428cd57dadafe58ff09ea4bfd7ed140", .None}, + {.Add, "-e044950bbabc4a6c3459d2c72dff3348a54cf96568b3692f63e83c8f20666bfd355ee82141d0b8c73ffc4391db5d92bcea439cc3c7b603ae15f8235adf2754465689d0e7da834b57dd821cbc162c26cdf625b13b850c1c7dfa040bc64226a51847f8dd68036bb7b7fcc7f65603236ea9e9bdf0ea98459701e01f8f49cf24bb7c72eca4e65f619c4a52e8cb1e863a543140381d37cd08", "a9674312f7d121d1d337dfd63b3d08d9018e5cefb9a13781f05f392435c1af9838927707d5f8eeb7b0d8150df177a2db96eb0a99d4742b5968895fe52bab9938be456359c244a792a344e5284e534c1bd32d7f4b708bff6b346be71dd4faa5b820d79f7264364a4519895ed0c02354fd15254a02076f569d704f0f23dba666b26c8d5612978ca0a8cfcf5929b88a1ee40c9363c15e86", "-36dd51f8c2eb289a6121f2f0f2c22a6fa3be9c75af1231ad7389036aeaa4bc64fccc71196bd7ca0f8f242e83e9e5efe153589229f341d854ad6ec375b37bbb0d98446d8e183ea3c53a3d3793c7d8dab222f831f014801d12c59824a86d2bff6027213df59f356d72e33e9785430019acd498a6e890d640646fd08025f37e54ca065f4ed3c7d4fba1831971f4cdb0354d33a4b9766e82", .None}, + {.Add, "-a650f3c6d0886da42ef39e05e15bf46b11462bcd9ddfa7041eeeb1b20b86f88f295888bc5c2e7163768ee5b7682b8898d90ef9b2078baf9bd962d242f054cfa06c55ecf3a74fc7d58b5cf72a246cd10486f33423c12ee1f5e0185bc0631d05c348c7a7bc83a9c7fc2f6616944ff7ef073ddb3a7fdf9ea31be688c87cfa20e9894587e653acb63ed1d5ae6a0762a6ca093827623c8b34", "7e396bdd3fe62a8ef5604a8d24cf3716c809e9c4fb724e660f67a32ced45a875fe5783bf2fef0f262d821aaaa63c2749ebe3f8266485f81baff3f00ddb193e84e7312581c7180f571fc8d85f297adb2beb2d85bb07555a274056598e27377749008575742516282736e9040db194f7c2d90547802dd7b76e6c8a070a594078b42943c0241778320d34a5876df0e21ba76b9c121d8d71", "-281787e990a2431539935378bc8cbd54493c4208a26d589e0f870e851e4150192b0104fd2c3f623d490ccb0cc1ef614eed2b018ba305b780296ee235153b911b8524c771e037b87e6b941ecafaf1f5d89bc5ae68b9d987ce9fc202323be58e7a484232485e939fd4f87d12869e62f74464d5f2ffb1c6ebad79fec172a0e070d51c44262f953e0cc4a108e29971c4ae61cc8b501efdc3", .None}, + {.Add, "329b7b6f7052956df5a62bcb38c5c16e681cfa31fc7a8d284abd6c8e406e7cfbd402f5c8fede55a05d39c9443b0d2fc9138dcfe274a4c7bbd09cee494c2af394cab3bffef79a4e0c7060a728053607cc223751ec03e1e866c53d1017c7be7e3bb7805c3f83a89caacc4b789a1b34a993f7bae6b6f3bc5988c9d8068ba5f21d9c429e2a1e6e90fa37c52415d7e97a85653715b1563044", "4621cf46f772122ad9d80416210e3fb0ec87cdc7e05adbacaaee00aec11cccb83b4aa701a1f8c738c511e6903ca9dd8174e894a2ae5863338002b345a47c714c57bd73a56bb6637666409fa67a19a39e5291791a026dfd3248793789bbdfa32ccbd4952e990e19b4af3c7249561581799a8539da603a7b05f8bfa7e60da6975b6e3104e912f876d4a2e53e2b104f2252d1ac1db6bae2", "78bd4ab667c4a798cf7e2fe159d4011f54a4c7f9dcd568d4f5ab6d3d018b49b40f4d9ccaa0d71cd9224bafd477b70d4a8876648522fd2aef509fa18ef0a764e1227133a46350b182d6a146ce7f4fab6a74c8cb06064fe5990db647a1839e21688354f16e1cb6b65f7b87eae3714a2b0d9240209153f6d48ec297ae71b398b4f7b0cf2f078189710c68095402f9c9a7b808c1cf0ceb26", .None}, + {.Add, "9a9e982b619334bc0695a6cf89abc158faff5e6f105e89d3906f63dcb9f3bc797b1a758341debb8552c031bc370a747d26449b80cb928b8cb969dd95872501d8d6ecdc6a870b818b77e4842dfc5994e75f48b94d4c1df233e2406dd2a6c4eee6c4076802042b658f4d339472f1dfa5e0ba2c73bf09916daa4fdd09d8671bcb53c13b03532db1117e4335289a8da4192b89bce00e72fd", "77d62f3c465e63d72da3033f567bab73f12cdc4d42ec457c5dc56bcc8c98043e3caf48782280a7b343d3757051f1f8fb36675d9bea2293e8ea6d7abdbca4c1606bbbc141a7fd4748425b8e3c2a8789c052403145449bb3d8bb642133f38891b058a9b1a3ec8f54123ebecd1df1370203ca8f25e026fc5df026f7f89be2263db95d252ffb07f88277a04e2478900841bc29bdee410739", "11274c767a7f198933438aa0ee0276cccec2c3abc534acf4fee34cfa9468bc0b7b7c9bdfb645f63389693a72c88fc6d785cabf91cb5b51f75a3d7585343c9c33942a89dac2f08c8d3ba40126a26e11ea7b188ea9290b9a60c9da48f069a4d80971cb119a5f0bab9a18bf26190e316a7e484bb999f308dcb9a76d502744942090d1e60334e35a993f5e3834d131dac5ae7b37ace4f7a36", .None}, + {.Add, "30db468ec0c99a0c41bd1a7e2191980fa415dc0e9758778ab6028a63dcce09326943b5a05a3f3f9395b4f78ee11bbe975e5ca597d6dd82c666b63e8631eb233338a65980152adfe40cc0f3fe63b5b7a31064f65c85d7e7319a12e248a530b77a5d5d4452baad8d156312e07290ec9ea1063545d77f9013892d9d32bcb487e2b93c33cd910f3cf8ce258925a825efcba38b5047a19322", "788eeda70478608f7ee7b446c7293861f3530743a512786f3f616fec260bea35037e0434b531d98a9833c4219795312b2ee6f142e3978e8cf307ae111fcdc52aa39b28e4d07076a7126de2ea445a388bf520b6039d8b9d320a57d8b8ff888f3b196e4351e9c4bbda506168811f84bac9303226bab38cb69401156859c7b3d8320086dc496db6cb4658236e359e1edf960c81dce20be0", "a96a3435c541fa9bc0a4cec4e8bad0719768e3523c6aeff9f563fa5002d9f3676cc1b9d50f71191e2de8bbb078b0efc28d4396daba75115359bdec9751b8e85ddc418264e59b568b1f2ed6e8a80ff02f0585ac6023638463a46abb01a4b946b576cb87a4a47248efb37448f3b071596a36676c92331cca1d2eb29b167c3bbaeb3cbaa9da7cf3c4147dac93ddc40eab3997d224839f02", .None}, + {.Add, "-4853b8173958dff0ba4509803da828f735e6e23dbf7b4c46c6a7db99118bf81b2b919d199202a7879699ea48cbf13998b0690e10e5c40b00f5a58f053829b839dd111b7ff98a9a13cb89b1477ddb3cdd7e112dfe7dcc690c28d18106f59c825ebebc48fe4e3cfe0352bcb31ca0dfbdac1eaa8df3061c64030f0e3e65a87c455c34cc89e878e7c49a77f72e87797e51effe5abe6d9fd8", "39ae45525eb8c45717403e4fa932156cc596646c823ac2dc3a025bff147432e0164c8cd266a456bae34c32a9a8450dcbb29be955bc774ca5b341ff5f3e2b777af68b27b9469c0081d84d603daf5491f1476c399bec903586792336622330c3a35a17bb3f88f2ca4f013a0ab6bd97f555b6cd82c6ea4b3c37fe209946efaf16edc4244991e99fe599141ca93049ad11f684795296a95a", "-ea572c4daa01b99a304cb309476138a70507dd13d40896a8ca57f99fd17c53b154510472b5e50ccb34db79f23ac2bccfdcd24bb294cbe5b42638fa5f9fe40bee685f3c6b2ee9991f33c5109ce86aaec36a4f462913c3385afae4aa4d26bbebb64a48dbec54a33b45182a865e347c85667dd0b2c1bd127cb10eda51eb8cd2e6e70a840568f47df0163da85572fd13ff979e16bd6f67e", .None}, + {.Add, "174a9c04b50453ad00401437039d6416830d64a37b069fc229775fd068cbc0a3b3c381027704e191d08ddbc1c3aa32647c211f6470fa003145b7d130375894d4c5c70f7299ab54e83b24569f421825fcbabec220c9b84aebe863b4741745337256816cb421c67a32b6cd3cca69c77ef5b81f95b7171a2100129399c856b69acb8e193275b3fdb49b808bb583f2c13d590362b6a72e22", "fac9b00db005ac8a2ca601cf309b10c30f9eb00120bef31cfd1bfc79d63c1ff656498421772cd928fa730322cc452c452a4c29ff4405576ff60dde234bd646aef83be7d9f563d05eb2203a737de439fb27a25d0098dabf0fe25a8d170625361f8c0590bfaec5413e4e6ad5d479de0ba68f05aa560ea0c778647d25e406d3845331790fd6cb569dfbc263a8806c2ab932862349bbf748", "112144c12650a00372ce61606343874d992ac14a49bc592df26935c4a3f07e09a0a0d0523ee31babacb00dee48fef5ea9a66d4963b4ff57a13bc5af53832edb83be02f74c8f0f2546ed449112bffc5ff7e2611f21629309fbcabe418b1d6a6991e286fd73d08bbb710538129ee3a58a9c4725400d25bae8787710bfac5d8a1f1ebf92424c7f54529742ef5e045eebf68b89860063256a", .None}, + {.Sub, "-28ca54039072a6db84452b44c65e1313b9dd0fb1b1e2bd98d4d8a62eb2bbcfbfdd32484e2d795d4494e923f1716d7e58fbdf76279b873ea2ef471418ef26ec791114d86673509cafdfe1e1e38db8ed56cd18b40e85b72086688d792ce177bb8de0bbeec65d432f43af32af177dfc3937075ae29b789eacce1d77520bc126fd4a0598294307aa7634e291da7f7223b207e77dd6cb920b", "20df9e35cf331ac3e23c53af2ba989f63c4b6ce9675586765f0feee2212f68bda42501c4cf86f996650a476afe3d6ced7e9275dcd86d266b43e7cfc7534d6ebd30fd6b488b0b638a57221dd71a60d562a1837502f7063043ec40bab0bbd7e7ffc5d7a7c401ed29200253fbc629ed38658261a85b2be260669844eef874b503b2a8975505cf9dcb7d194cd24e52b32252105a43aa8934", "-49a9f2395fa5c19f66817ef3f2079d09f6287c9b1938440f33e89510d3eb387d81574a12fd0056daf9f36b5c6faaeb467a71ec0473f4650e332ee3e042745b36421243aefe5c003a3703ffbaa819c2b96e9c29117cbd50ca54ce33dd9d4fa38da693968a5f305863b186aadda7e9719c89bc8af6a4810d34b5bc410435dc00fcae2f7e48d74841b1fbdeaccdc4d6d459f7d81a761b3f", .None}, + {.Sub, "-54c29f918703304790dbe6422a9c76f584e9df4faa3cd588c68db774df1d738182b2db6bd3a34cda103457dbde9143a4fc9d3840342eaf4684875fd0ae8951e968140eca9625eb9f0bb21985898fcd9e2bb0c0a3d65da72974f15d61c71460f4f9b7a6ac5d6f7467ea80173fe84097d3f50b10621e1674eb5c98179a5fa2c74571af8dd64ca788481d95043d92433f15a6d30c02970e", "443927c0201574bdb072b432dd5c3e1ea5c1c46df2db0d139cff3ce042b74563c5d7460fd1da9d2dafe32278b7da938cf94feef0b075f1ddf0c38b4a657023a71c729209b8fddffbd6eedda59b44de5db2bbb658a4575891eb7723b9a9e12a22bfb86506ba0917cd568d65d84d95c092bb439020f621ce302a9ed17e96a433cef1284aaf270e9963411db84e7d7550076d11566da0b0", "-98fbc751a718a505414e9a7507f8b5142aaba3bd9d17e29c638cf45521d4b8e5488a217ba57dea07c0177a54966bd731f5ed2730e4a4a124754aeb1b13f975908486a0d44f23cb9ae2a0f72b24d4abfbde6c76fc7ab4ffbb6068811b70f58b17b9700bb317788c35410d7d1835d65866b04ea0831438431b8736e918f646fb1462d7d88573b621ab5eb2bc8c0fb88f1d13e4627037be", .None}, + {.Sub, "-20d50e2e5bc3050b94be91ace5cd5d8cf0ae3af5b936c2df391a7a2abd3b57d4d8623ed56a202fbfca820a612e34fb7b8b3136d21486ccfc3057bc5494db84b34c774d9f02adc66ee586d85ffc90d826908c5449daeaef28eab4f2b2e25ae9cc53c0bf7441bbfa573903c450c29a0fd7f427690e1f1934b681338f7117af5e96d5abbdd440a94c0001be2b3300fee1deeafd341a8661", "eec3305d80723a0dcead0338c5fc5698779f760aba6acdd4441a4c705b11c0f8d67ae3e18c6c7f893edf8887e3dc8d1747d980a96bbe323f9442471339af31b374385404575ff90da921d3cacadd14b285686df70569cf90a8fae672df599f3e961d039ca4a9481226e92d714bba64bc07b6bd7d3263d1a10312ccc8521089a4e2e486367fc5919b46351eb2833f9a756ac6f5eabd75", "-10f983e8bdc353f19636b94e5abc9b425684db10073a190b37d34c69b184d18cdaedd22b6f68caf49096192e912118892d30ab77b8044ff3bc49a0367ce8ab666c0afa1a35a0dbf7c8ea8ac2ac76decd915f4c240e054beb993afd925c1b4890ae9ddc310e66542695fecf1c20e547493fbde268b517d065784465c3969bfe83bb890440ac06edd9b47f349e5843e7c5455c42a0543d6", .None}, + {.Sub, "-dfdfa5ba6a972e199a2b9b64e4c5d54fca7684664d30ef183da7a2dd107bb2996c23ef990065763869157979fffeb990990f3e67604a4c4af7dae67a4f9857fd3c3d819425c3ae1ae2224fb616f9867f0541f9637073cb43c447de10238407376772eb0a9055fed3c928cda7df5811f7eb56eb51bc4738ca6a0f8ddd568ef1a70193de4b6a6e61f2527a04f78f3286969921115d41c1", "adb4378d631b7e2ea71d720b7ba91e673e5c92acc5375167ac75e3ed126350a4542ce16203446ddbd5b42b64838b133de134baa1fe7dc2b114f92c9d90c489ede2e2b561b89976fe8c19ba9315e9788bd9700158e84949c51a39c776e8f362563a36908602c86783f3a2298fa1d904b137d7ddbca66ea0869795daac019886f2e30aef5bb3e10211ca4635b2b93dd606af32a4534203", "-18d93dd47cdb2ac4841490d70606ef3b708d317131268407fea1d86ca22df033dc050d0fb03a9e4143ec9a4de8389ccce7a43f9095ec80efc0cd41317e05ce1eb1f2036f5de5d25196e3c0a492ce2ff0adeb1fabc58bd1508de81a5870c77698da1a97b90931e6657bccaf737813116a9232ec90e62b5d95101a5688958277899e49ecda71e4f64041cc03aaa48705c9d4853b5b083c4", .None}, + {.Sub, "b35512d4bba7631d7488939f232673f48f6e26d6be224287f7771f60025d383c1e4010593932628cb52e501ae5e57c041f14cbbddf8ed0e2efe70bc6e55de84fdc44f1dc7e12d8059ba59229c0c004ca32186291059ff07f8de7d8ffe3b91c512c064cdf637eab973ab02ac12ef7121fb5c841b137fb78b407facaa3adcee3748d929fa6e56da8fabbc5d5c1dfbca6eadd461cb72bc", "464a7f97c438e458a69415ce184373606698452e2aa80ea8974ba720e3a24876731e9107916907d8cd7c0d2591a2bd70ac4e7bec6c0d5c06065d56be39da7e42b55a9ec8cf3a84d76e9e26ddd1084be340e123a010134f3ff57d0c71e8b8d96aa6990013aaca39556ff33210a25529fd3b20ab949228ea42c04857e9740981082403c5ce1644954108bcdd22df2e4ffc62a1ff9b8520", "-3b152e6a787e6e26cf4b8c9426110c211da162c0bec5ea8017d4352ae37c74f2b13a9001fdd5e1b002292823e34465b06a5d2f308e146ef7d75ee601cb849fbdb7964fab0759575714e3cdbb34fc4b969dbf9d76ffb95037fc9e8ee1ea7d47a593d89b45b4924e9bfc482f648f65b8db3fc427797ea932b77fc8ab3f392c92d0db2a9bd3a7edbab15d007fc6c132858db4cd9dd01264", .None}, + {.Sub, "-fdbc1ef4cf1f7825845e163fee28506530aca768813d8f27885f57a0b082852d7cb8698763449d3a9ff5678c14175c42c7b1b725d6772ee7d8f2b6da0ede67c9ef49b2d14d2b6c80a48cef973ae3dcf98afa3f9f4f11d7a37c30c77ab9b95722181b084480dc9622d344332d0d32b8e4841c7996c9214fb8a3d93ffeb2163d5c2e4df059cb7933de5871c949b18aabe5aee162e72f46", "6ade2f5c4cfb2a6f13bc22a9be733be5a460e9f2fce014b8cac4d5d6c11ec3dff4419d69ea0220233bcd72e478649282cc4946ea0a9de23b421319a48f7c57fe0c791a7fb1d50183bae7210f6525160e4a113db88e1ee93f9bc16334087fe08ab3e50ea655c552092289a3b2d185557320ed1dfa781869c83e372f913df0727d5b098704c70b87f69975da9934ad6e77988968e92e7f", "-1689a4e511c1aa294981a38e9ac9b8c4ad50d915b7e1da3e053242d7771a1490d70fa06f14d46bd5ddbc2da708c7beec593fafe0fe11511231b05d07e9e5abfc7fbc2cd50ff006e045f7410a6a008f307d50b7d57dd30c0e317f22aaec23937accc0016ead6a1e82bf5cdd6dfdeb80e57a50997914139b980e2106f8ff006afd98957775e9284bbd4f1e7a3e2e6381a5d476acbd05dc5", .None}, + {.Sub, "-f20702d999a0fa193c113de38874795756af7a44368da2165c4c6f47ae6eaa43ac44b4aea4c8cf7f69f703e46773c1e6026c776755a49db7916428e16d2907a50c258f139f8bf613faaa5b23c54f1d7caa7c06d4efb2c5481a6e821b5ce05e963ad69d4f6a57c64f08e08d3cef991b93233318b8cb53d5266a081984a4735c461646e762dbf6e9a39df21a4fa207e096c66442a52fad", "401d6bd7124b904d72f790813e67094409b961896f9aa14c880c83179bff801ec57ddf1328c5a11ac03d266543f196e1638a73f7c1df022a95dcf8e25471b7648bd9d13701f39f50ffb54b6eeb29b3c4842a80eed038798152e598fe628947782ab27a721347f83a695fe0f3292fdc1fcc333844a15f33a5272faedc29939204639109a67de7429e5eac9b7733a095e092772d3731e4", "-132246eb0abec8a66af08ce64c6db829b6068dbcda6284362e458f25f4a6e2a6271c293c1cd8e709a2a342a49ab6558c765f6eb5f17839fe2274121c3c19abf0997ff604aa17f9564fa5fa692b078d1412ea687c3bfeb3ec96d541b19bf69a60e658917c17d9fbe8972406e3018c8f7b2ef6650fd6cb308cb9137c860ce06ee4a79d7f10959de2c41fc9eb5c6d5a8767758db6fdc6191", .None}, + {.Sub, "-41930f6dd645f896d431202caf963d1aaf4af9de0a44f3d3abc9e13429ae0489626ddb7354fecd695d4afdf918437349df96231cf8c11577dd2ea1b295d886f30644f1bad3518c7b062e774e4bde3d5c4e526d7b7b978c168b5a9701892df74aa3e4a47652ce02f06a58bd5b39e59280e7490e098772c60c400b1106ef12504ee8ec089bb6c36b8d40d0a1876332b290677087229874", "76d6657760711ffed878bf2a17d9ce6f24a670fe6fff2a12ddfc018402be95424e2f9d4b9473b1ba1ec7d8fa1ff9a830b2b5405ccb736d5b8ad0c1de1e18f3cca2f517d051e409865ef0a436d6e420c458ec8397347cd1d781bd773d9efbc05e80a6e70d495c34baa2207da5a9d2ea7f40191b12bc47f7ab9b62235921ca70c90d9687f9d4b1c97309c382efadd40ed4022361454c3c", "-b86974e536b71895aca9df56c7700b89d3f16adc7a441de689c5e2b82c6c99cbb09d78bee9727f237c12d6f3383d1b7a924b6379c43482d367ff6390b3f17abfa93a098b25359601651f1b8522c25e20a73ef112b0145dee0d180e3f2829b7a9248b8b839c2a37ab0c793b00e3b87d002762291c43babdb7db6d346010dcc117f68290958b7535004a9424771106c1646993e867e4b0", .None}, + {.Sub, "-58f84d3440b1481e1d5477993e03eced47c6c58be306608c64f59859a8117953551f114b2b870a6dbd6d9c882b16f100393db0b409b00e008bae0a5fc4c9418ed16108e8c1cda08b2cf229ae2abd2c0dd55815fd472f22bc8ebfdba2aac231bae164b7c66a2b312d60203fe5ecb278cd166f11fa92c7bc11669c19ec66320e086ebcf7d68993f95dcd05fd40a2bb26f08c697b0cefa0", "bb942fe12fd015d03a0d5ec11eec514164a29c02015cecf3ce64dc2cb374ac77a60b60aada09540ca86a2eac142452e62f18743ad1b742046930887d9508826f0e64326bae0b207f3a3fbe18e4de24d787e0addd77b9e49777a723a734f7c7416012838fb455fe256b265f56bb112aab5cdec632796ebb05e4c99f4907902d599ca84d2c9dc3a004e3f5294cf857f596cda1901736fb", "-1148c7d1570815dee5761d65a5cf03e2eac69618de4634d80335a74865b8625cafb2a71f605905e7a65d7cb343f3b43e6685624eedb675004f4de92dd59d1c3fddfc53b546fd8c10a6731e7c70f9b50e55d38c3dabee907540666ff49dfb9f8fc41773b561e812f52cb469f3ca7c3a378734dd82d0c3677174b65b9356dc23b620b65450327579962b0fb268d9b131c875a0b0b24269b", .None}, + {.Sub, "487ad545a973559d76ca5de766289f4f7d3a2e1bf15f0568c117f9dcc08b26462c344788c8a79bb4f4b091a072a2adb9f4200480f897547a9d62660642c26413c4bd55a0c6d49cf83bd2a987cfebfabeab8776fa4746a6e6f5300676474de21942a9a0b5d3206e0e0c9a09c9a78e39d57dfda659f54ad61f59f2258387570c02dfd6b3bf27b3d2f83e55bc3fd3f1e971d4d87cdd72d", "758583d7f4018fc0c4191741523c3b9e83351e02c7a14b2377cc707ba6abadf40047ba3b4c88b1a8eb90c816815f960a668370beb9064325b880ce2db54c06df1173e9ce79409c08ae6e77f9704ae44cc41f17def42a9297696874985a38437e0ce8aa1fe39c6045b35c9bcd711946c2d8e8f97779b24dd5eacd57371b52b3d6f0816b58f4a217387e9d20a638bf71ae0076ed5f4c51", "-70fdd683996a5a66ecac7162dbd9b1a98b617b21088b5accebbaf0dddaa2fb8f9d8475c2bffe37ed9c45befc7a356b2ec7417076a97ccdde0eaaa7cd511fe09dd52814746cd352392ab14d60f34c24a0d966a06f4fb62828fa157430f5c3655c78be1014866a5964d292fb30d6a0632581091f11da5da073f52e34dee2dd4316c284001d0226da08fab7c4e23b805316e32965917524", .None}, + {.Sub, "7726389aa316a95172438de543cd5b9df03242c6518d3223f3b6ff79d3ece6d1707d9b27859911ee76c2c4b8795703538cd542c95f1fdc26e95ff613849e73bf2563e459272b8efe0e16cacba4b75bff11cf32178a57f6032af422d276fd1daf7aa32ef0709132b98236ea5511a6924737b0381346321ff61f6368904bd408eaf41487125b9ebd607de77f908a19373b9547f235f9e7", "bc0482cfcbec41531c7e0e908622aea8b58f793db0c9ae9d3523c4a7135a503e2a602199a966dfdd9d85d8a9f18e0f6528f3085655bf0f9fccf9396c66ce8d7e368c12b988359ee1beb83c934aa54c14ecc243a08a2c6e631c43f67a1ef67059d356a9cd97a9b210a35affda71666763e4cf04c86bef9c4c1e803fe780e7162455c27a8cf2853a27523c7c33c96dff3cbbc5aa14ed31", "-44de4a3528d59801aa3a80ab4255530ac55d36775f3c7c79416cc52d3f6d696cb9e2867223cdcdef26c313f178370c119c1dc58cf69f3378e3994358e23019bf11282e60610a0fe3b0a171c7a5edf015daf31188ffd4785ff14fd3a7a7f952aa58b37add27187f57212415855fbfd51cad1eccb525bd7c55ff1cd75735130d3961adf37a96e67cc6d454fca33f54c801267db7def34a", .None}, + {.Sub, "54844dc3a3f2f627bf25dc8bd3c119115021bd866a243b67e4e6cfa7bfece30a363ca9b71e33b05d7ad818c4bc295b1f039995f5c8d833511922ec9ec3de46df8202f47b68b6cd614e1d4e460927cfbb95825ad6049bdade21367a40b6bffd7b548a1dde5c63b9521c2aaa75f63801c8bead98d1271174befc6dbea32c75f867759f6bbd487b264e2ac4e537154db95e2ddb3933239", "179990d4a28711eca27d59ebd2af30dc8722f1bd9dcc3ad058d530f230578bb66691dbc1fe0d05702011e45be2cbef272f1802ba1b28348b75f6ece4b1b2bb8f11b0de2a5163a422cfa92633d9e58fa28eebf35ce85e6241ad1efe16a7f6241f8c31e2371e7053fd4f64f310ce1d0ebcfecbf018674dae34c3814a8688f3c81d9d135df95ef90c3852d1c108f3779eb88f4e8aef8518", "-12514bf86847e28a268afc2315731f4b7220d5e53729f719da86c3f7b458bd85c32e11268c29ca6a486462cf970959753ede695abe9ab1566464be1ac574d7211990aee29ad8374cbac7514f795312a6d593cdaf8814a493cb0b96729c8a2447d6e9405938aa18682da248696eb98ea072e1168b54dc96e8d3ba6e9c562c689725b9673d8a7159d3702572b58222c322ac70d75c52df", .None}, + {.Sub, "-57387ec90c2f238f94fc3e40e12ed3ebb4f68e8ae815986fa4efedc54368ba7954735aba88a5f0803efac9b8c84e4d9894d752f5e03891e9e27208590fcf71c5ba4f6a81bc453d788ee0e47b071cefdeb9e23284738a9d3834597f4d9e4186352475ca4f86d3a8a3f56f257bd410b666054a22eb90d517c831fa830053c9a3d15c4aa97e40d3cda3176cca89a81e5fd45aa8c4c2c16d", "670c15bf78ffbdda169f8222572224477b73cb8ec043357ebabe6e5f87c7909ca7d2be973f34a0b557a649328c3a07b9077c840f19571ce0f0ff471974b423e884889085e9976593f54d708bd80b94fc8d367555ce00cbe863bdaa2ef4ad294f90ae25b68d3898d2b927be8a4b9fca56b5f36cd1edfa6e6db415278bdda084f8b7cde9ece4a3b8d5208ef522c2cf75bc2b86d0f2e8bb", "-be449488852ee169ab9bc0633850f833306a5a19a858cdee5fae5c24cb304b15fc461951c7da913596a112eb548855519c53d704f98faecad3714f72848395ae3ed7fb07a5dca30c842e5506df2884db4718a7da418b69209817297c92eeaf84b523f006140c4176ae96e4061fb080bcbb3d8fbd7ecf8635e60faa8c316a28ca1418936b2577867837fbbfac6aedd590862f95b5aa28", .None}, + {.Sub, "82298924850fbb61e8bc9ed1f9def5c048cc4bf4a278451f633924a10fda3fa736510cd6ce95146562983e665d9e6ec387b57991e484e4f20c71f7d60e36d025cc488fc5524fe0d992dbe9dae8e4465ab3a0f615d8541558223fdbdf158b1be5b04b53cbda94550558279f6a8dc3730f3b95f82ef4c7fc5662467052d0344aaa48517b08413d685b19d3905350f0f819a6e1408c1a3c", "5d361f8afb7e9c84129dd1f2faa5f0bcde8a49df2486571e91b67b38f6114a2d011fd7a8165d171b3475c8a17880877021a4b3ef87b5fdf9a944573a41b8341675281c0d3254ed387f74471f4507bec41c80044ec24a90f45b923b517d3a1a78b5475fb64d49fc4b551a8116f19c166f4bf2babab9c78c96f055e8f3c7f0853e992c94374db5f66a6e13a1288a61c521e4d0d1cc871", "7c56272bd557d199a792c1b2ca3496b47ae3a756b02fdfad7a1dbced80792b04663f0f5c4d2f42f3af50e1dc4616664c859b2e52ec09851271ddb2626a1b4ce464f60e047f2a92060ae4a568f493ca6e71d8f5d0ec2f6c48dc86b829fdb77a3e24f6ddd075bfb540a2d5f7591ea9b1a846d6cc83492b838cf34111c393b542565ebeb1c4cc6208f472f25640c84adbc78894336f51cb", .None}, + {.Sub, "-d99e7dd93bc09610a749c5863caecdf411c86cd7534c3d701487dda260dce42276a1ea6ce6c66135855383a05ff74d1e7422cf10536f35ed75e62a979bd8f6333f3ee29ad04851730f8ebc35aa8ad436d74e52b23e0e1a013bddfdf9c55cdce264608f9b066823917ff71c591106d325bec7c48b7936b6dff97f020237c8bab2b2571d2658a54dec343bcc7cc3bce2676152ff03a615", "2453090144b44ae7b704aebb3aeab5ae9d3f56f8b6d54da0252d6b342f4822c9cdce2f9f8451223cb2e46d309df4ff761f155214ae09a33e3d3aa2ea908fab9a09c8d9bb96d095aa81b7264e13d0ac9e68ce76e3b3d8fb229a1c773f978b44424dea19042ac37b497989bd061bb80a6dc58b1c47ab41597383da1f83eba98a2248eec3cc98b106317abed829077642c980d7de7e08a5", "-fdf186da8074e0f85e4e7441779983a2af07c3d00a218b1039b548d6902506ec44701a0c6b1783723837f0d0fdec4c94933821250178d92bb320cd822c68a1cd4907bc566718e71d9145e283be5b80d5401cc995f1e71523d5fa75395ce82124b24aa89f312b9edaf980d95f2cbedd938452e0d3247810537d592186237244d4fb45e0f2f156541daefaa4a5cb332530e22add81aeba", .None}, + {.Sub, "9f18bebfac40db9840e0069d7a320ec6fc7d758766461c100f2dec0d0a988ff74fdb2c898054e32de360111181d3ea4397a4c27da72072750f0a052029ea26ce3183522f1f1557dd6f515ae60684654853c7479cc57fed2d51ec0868b1ef33c88bef66768a3816fe59a603649921c22762435c0a250fd5461a36121c2fa6eb0ea352dad60e2adfdcd1e5855aa9d67dc70344b67d17b4", "4d2cd1d3a589a42d593fd3c6e386581a2b886d9c508eaec18b0de919dcd37508841ffa2ba91ec0878fe519ffa4b866766f0f21f0714407a9f56f1304addb1fc55c88329dbd32cbb5bed67c8128ff42076be3e27cb62420ff0ef636a5773da60b59408f46ac1b86bb6098d9ee76f5feecceac553072a33f95cffef23d508650ee251be2c350130813fac5522c959f450ee4df03982907", "51ebecec06b7376ae7a032d696abb6acd0f507eb15b76d4e842002f32dc51aeecbbb325dd73622a6537af711dd1b83cd2895a08d35dc6acb199af21b7c0f0708d4fb1f9161e28c27b07ade64dd852340e7e365200f5bcc2e42f5d1c33ab18dbd32aed72fde1c9042f90d2976222bc33a939706d9b26c95b04a371fdedf209a207e36f812be17d7c8d720332e143738b81e65b2e4eead", .None}, + {.Sub, "306815455c975c6fcffafeaf44b5f41f3326140fb66f20514b14ecd34c8b9c618b950b2f93f2bb1266a7eb300bc76e9e35c65a076d5a5e2b3592dba6716d1bca2d7ba5fceb6f1530557d84e36fe98bf45d770879c9ccaf94da2f30d4d1ba0e167393e922db757f5963c9af4334175864d13bdb1e6f4711f2dde8a0908f762a82371da0d83c3b679b85e65f057cb4166b7fd062207870", "1b2ec3d946216d34a45627417306c2e3ecf209ceed1218edf8561ad6376e28d31e516c7bef71103fb5f57458902cb8c2e13986776111ed724c9bd299a81e08f55d0a0088e005cd997789e55d9ce80cf532c2095e0f3e3fddc516d0d2c2a684e2b033ebf8374f75e9b695e30281b3927b2128ac464c389fcb5df71fac4d51eb3c461ecdaa9101523a552405f205b746c51553bedfbf1f", "1539516c1675ef3b2ba4d76dd1af313b46340a40c95d076352bed1fd151d738e6d439eb3a481aad2b0b276d77b9ab5db548cd3900c4870b8e8f7090cc94f12d4d071a5740b694796ddf39f85d3017eff2ab4ff1bba8e6fb7151860020f138933c35ffd2aa426096fad33cc40b263c5e9b0132ed8230e72277ff180e442243f45f0fed32dab3a156130c2591376fccfa66a7ca340b951", .None}, + {.Sub, "e8e335097057b90ac0cf5268f75c81ea8d05105c57a2da574ef821c75c69bc7259a26e62b132dee6d6d9dc98821f4aee949851520f38ee93383153d5cfbffd96faa15a6b4856901a42849c3f086004f74610ecef3cf0c108ffa33963ce56200a35929616a024b62d55fc35a91b00c81f2344d28fe71c83af5c86ca19aec209fa94547e9281576006fa19f0bc085c2e255f9cf166d978", "56eb5c41737b1e0b50d8149a7abfed76e3bea47084196c2a5650121dffa8d4292cffc0ff8398a5f142da7df11bb09e1b5157d54716aca5f03a2415751c5126c08b4536d4f1a38964f43dd670fbd119c3ebbc0986c1e6a35dce8806e5bb02d4cfa909e37c29b275ecf003edad04967daccebf464782472f81050ad6f61926960c5cac878881dd924c7af338046040783ddbcddd74bdf6", "91f7d8c7fcdc9aff6ff73dce7c9c9473a9466bebd3896e2cf8a80fa95cc0e8492ca2ad632d9a38f593ff5ea7666eacd343407c0af88c48a2fe0d3e60b36ed6d66f5c239656b306b54e46c5ce0c8eeb335a54e3687b0a1dab311b327e13534b3a8c88b29a7672404065f847fc166a4a7254858c4864d5542e577bf323959b73ee37a7f709ff79cdba7f26b8b7a81bb5e783cf13f21b82", .None}, + {.Sub, "-f7b79297871fe6ff8388d1e1b027435b27129c6e3ea5935faa4cf1ea941483c781b71fb114c94a32408a42386049d5e7c041bae2168a5b63f82f9cdc2effb7172d20da164a62ff5244ba4fb9d060e1a0622e51fdc8defcbc92a9953456ae11936be87093f727a5d2f3015a9af9a170d3f98bfc1d6b85515e52ff55109513cf6cb6dec1d0210a5b18befc25e38f1bdb6ec3921851ec25", "5a46310ef7517a0ae7633ea7b22e1bb7b75b4230f817d600d3188862292f0160633d7d5b5b0b9019758d507992a343e715f2ce085818dcae7ee196c9276e336983920fa804c65c475796f468d2179e43ec572f5e2c9c47ff4b81bf2f0724fdaf6247dfdfaeb4f621f8732ea8dba6fbb9298fdb46b3fdf51857a1fb7a10e0790dfe855568cf133550a5ebbc4ef2ee7b54f728e22f42e1", "-151fdc3a67e71610a6aec108962555f12de6dde9f36bd69607d657a4cbd438527e4f49d0c6fd4da4bb61792b1f2ed19ced63488ea6ea33812771133a5566dea80b0b2e9be4f295b999c514422a2787fe44e85815bf57b44bbde2b54635dd30f42ce305073a5dc9bf4eb748943d5486c8d231bd7641f834676aaa1508aa5f4487ab5641738f01d906964e7e232820a56c3babafa812f06", .None}, + {.Sub, "-872506b51b6934a92a28b8e7834a73389f2d3a00d6f5ab9ed812982224c268ecbed5ad3552d00b48ee559c481278b665121038e6e78eeebe965d51703827fecdda71cc6677855a59ec7dd5b1067587b1b99fe18dd5a48f99aeefaeba57b7455305c5e831db974de5388dd5950ae8c955066635b7cf48e0dbdfbe625a2f43599395f0351624a026e4bb98ae2e6d30513330f6ebc98a11", "a4c944fec1e0fe078fbcc6780ef7d16b67aaff4d44b3a438c7f9a10924236fbd24162ed3121985d86fbb9f40f7a0c5ed247330af2408439adf63caf2fc00c47139abdaeb2f2e51b095b0b2f01937b3f53040e2cba9767845238af1c7804cb6217e85624b7ef3278fcd025da22c36b07226a90e7307c248560e5d7de0c6ed0ea6ee607b598f249d2af71ef30c46f12bdc564c058b57f5", "-12bee4bb3dd4a32b0b9e57f5f924244a406d8394e1ba94fd7a00c392b48e5d8a9e2ebdc0864e991215e113b890a197c52368369960b97325975c11c633428c33f141da751a6b3ac0a822e88a11fad3ba6e9e0c4597f1b07ded27aa081d803fb74844b4a7d5a8a757505903337371f79c72d0f442ad70b2931ee1be03af630683a8450b06fb3c4c40fb2b7a13ab4217d0f8742f154e206", .None}, + {.Sub, "-83bfd9ced00afc9d21887e67fb2bac51a06b4116a7a1efc9f8b4edc48bdd812102fbed6219756784d7b0d11e2f925a785cb521fc88fea0881bbaa332cf2bd7baff782ddb222502f014347ac78c9902e5b09e946d6c75f923b2de25cb7bc7a9abb91eda67863a22bc704c70d3edae80dc899c1d760edfc8aa846939a3504c5ed41d61d9db24d83f21d416e1559aaeec74acc87b290252", "8d0e98ec7c5de4dcdeb4115e92d71c1d36eeae7606fd5ab4a6eb29fba613c9e6a5e5d4297802d2787317f6ca1a78e6560259fd79325e8ad154a25546c7f1d46f0efcb1b135474ee1686296b7194c60c7d542c38e9d65dc94d2d2e410dc612984ced1de27e328fc3eba50dfff65f7a3196a1c186ed713caff174616f714dbceead57354243e92504bf032251b5903b7d469dcbf4af2d8", "-110ce72bb4c68e17a003c8fc68e02c86ed759ef8cae9f4a7e9fa017c031f14b07a8e1c18b917839fd4ac8c7e84a0b40ce5f0f1f75bb5d2b59705cf879971dac2a0e74df8c576c51d17c97117ea5e563ad85e157fc09dbd5b885b109dc5828d33087f0b88f69631efb2a9d50d353a623f5f3b835e4e5f393a99baf509a65282dbef2d52dff636a8f6dc4490670f3b2a44916a53a73f52a", .None}, + {.Sub, "-3d80758b3708c7856fed4c70f79ee801d4253e19394fab9f29e101dd6cee76f94389dbc6a3a3e778842447c06dcb40f9bdebd207df2377034ad7bbd9c39a370afafee7795d7c0762ace37c19d220a4f90ef31d1f7b6551bbf8b7589c58ee404ad5ecd831e44d1d0d95a085581e79dde385f23fcfaf1ffc6a3bec1fe53636eef2177062dd1fba38ebb88a3cf09c6b4b5084d5f04cff26", "bbf81a362bdd701e3a28984b0b73713362dcd3f93c867c0208295b20ab3a8fe37128d11a19ba1b25c5e3bd25f47d67ceb230a15c94592a51cd81b68c4c39c174382c8e2d06309654eb167b6f6f791dade2d9cc61a470f1c87c2d80081b5067f01ddf91a5c56384450089db6d366457ee9e0c9015fb3c6e8cd4c05015bfb80ea8793db65ee4dcf950b184cec76cca242fa346e6b9f35b", "-f9788fc162e637a3aa15e4bc031259353702121275d627a1320a5cfe182906dcb4b2ace0bd5e029e4a0804e66248a8c8701c7364737ca155185972660fd3f87f332b75a663ac9db797f9f7894199c2a6f1cce9811fd6438474e4d8a4743ea83af3cc69d7a9b0a152962a60c554de35d223fecfe5aa5c6af710ac6ffaf5eefd9a90ae193c0497323c6a0f0bb809356f80281cd706f281", .None}, + {.Sub, "-3a6d3e85991d88d3e2c7512c5a3087483d019fa662e3a3101cbd21ab500d4a4c0f65148786ad7a07d3dd9fd92fe466ddbffb3907a9c3f01ea17dfc669c74319026ac67b30b2fd6eaa5b948426da54a7df35993f884fd98971e7ff3747643f059052c67c607d11ee13793ccc1d8dd17b51acba688b4f62ca01572f660c54c2d43b0d2fb13b539fe9800ac4c117fb8f1af61a5982820c0", "393c342ea44859bb10459b325fddd5a0492c40638f5dcf3893ac51de438e65b3019d8f6392da062dbb3c42910a6565ad14a7ef4a39540d87b1251bbc85e7702f40396429352913ae4dda96b45551759c9122fe20705cde2fa9faf6f91829be14f0b2409be6f378b40c1cb7e7341da40cbd6ba013d3a8f0b4713fd0a5e6688b2c93aec1c0f83bca0888f3f0a03f10ebb7a5d44c0bd95b", "-73a972b43d65e28ef30cec5eba0e5ce8862de009f2417248b0697389939bafff1102a3eb198780358f19e26a3a49cc8ad4a32851e317fda652a31823225ba1bf66e5cbdc4058ea98f393def6c2f6c01a847c9218f55a76c6c87aea6d8e6dae6df5dea861eec4979543b084a90cfabbc1d837469c889f1d5486b2c706abb4b8704481bcd4ad75c8a089a03cb1bec9dd670779e433fa1b", .None}, + {.Sub, "21ebbcdef2f4b1b2237360811c98753ec21feac8e43e52953ff24887b27a771c2131065cace5b18543c6b3f490e35a727224dd4e920beef7823b375ba1da82b865050f3240ee04d5a712aa7aa8b8457e160be503c7e42d6cd7198c5d504a1621c6477395fba0f8b7215a7d1bc74ca1ac8280dd2e869eb21069220f4ade42098689355dcdcb29448b673cc87814929e75908a4d1ca0de", "3d1ceaecc84e06a63638c1de96f040916f167b929257eeda4ca630d967e8e6872a2552b1e5d899e9437cb2ad4f4795a51cba4e2ad37d2c9dbc6ddf941c2d89fbf20c13746d229cc7f10658f7cd607e331c33fed7137d162c44b46ce3e0c95d52b4dcab3703e34b6c9eed3b75b4449040bdf4181c55bdd8f80b00ccb7cd2f8f31cde6df0141cca7caa70db2ae3ce1f2ae8748da050847", "-1b312e0dd55954f412c5615d7a57cb52acf690c9ae199c450cb3e851b56e6f6b08f44c5538f2e863ffb5feb8be643b32aa9570dc41713da63a32a8387a5307438d0704422c3497f249f3ae7d24a838b5062819d34b98e8bf6d9ae086907f4730ee9537a1084252b57d92be59ecf7ee943b733aedcf1f26e7a1debd6ceeed85ab44b1813376a3633f3fd0ea36284f5438f6be8ce86769", .None}, + {.Sub, "-ed70aef606e646e18c0af8c52de232651e6700e212cb717c305cac81a395c13edc1bfabde9bc6d3a1d77620f735658d96e9470c462a2da0200193927c3a9decad32751889efd058106bdf87ba2effbc062ea7a8db817309b39fb6f2db4a8522b53f3e83008e5f04efed0d1cb9f0139c1f13e7bf3db6cb27a9e4c002da006757170024cad9faf054417202ace20b92460319d1824cb88", "b56cc6b37179eabd180805229d183f8b1e90b92b2d379e5646fde57eb28844eabb5b33455aeab6adb61d38dc84a2b0634fc735d4b5527b9bc69246763274e20203d7b9eb074e7e760ba22bb4aa247e81aa16ff6c78221be1140c5d18277db509dbc288d1cc6a58a05cdf6eea2fe7027bc56fb70500fc11ee1b60cf916e399a849af5a278aca4590d36880a4b4ee0e244db6ece5fa650", "-1a2dd75a97860319ea412fde7cafa71f03cf7ba0d40030fd2775a9200561e062997772e0344a723e7d3949aebf7f9093cbe5ba69917f5559dc6ab7f9df61ec0ccd6ff0b73a64b83f7126024304d147a420d0179fa30394c7c4e07cc45dc2607352fb67101d55048ef5bb040b5cee83c3db6ae32f8dc68c468b9accfbf0e400ff60af7ef264c535e514da835196f9a06a50d0be68471d8", .None}, + {.Sub, "-53e3717614f4451790f6bbb4eed7e58b6d62e6ca9f6655b64216c4be7581fa1356fe438c19e39f04c28b39c28dd530acfe01cb0f6c72f0e0b9013c53c2206f577f5f5ffeae2becc9c9136ec8a36a548c27c5e82c8c3fe66ca47c701954b67e2f2709586abefd6b101394c57168d722393bc198cf6fe0213defa6e92715f3da17fd76ce93f7ef1a9ffff05469064a630b6d4f936d9a95", "8d50598fd78439477a5c7018f14a7f392d0de50bd487512fb05e99936998e0554665f8edf6ed2eb01814a163c32dcfca08bd1e780bad896aac79c73603709b438aba3b80bc0a7e06715aa68b78bb67ff5fc8506f93f23a86b1133d31a1d9a124d836b2f73214610898c85fc9ed4c488d724138393c64f9e4a99aa68d16798542eb501467398fb8f58c5122eef348b04f01e2b42e36fe", "-e133cb05ec787e5f0b532bcde02264c49a70cbd673eda6e5f2755e51df1ada689d643c7a10d0cdb4da9fdb265103007706bee98778207a4b657b0389c5910a9b0a199b7f6a366ad03a6e15541c25bc8b878e389c203220f3558fad4af6901f53ff400b61f111cc18ac5d253b56236ac6ae02d108ac451b2299418fb42c6d5f5ae8c6e2fb317ed3958c417757f993135a6f32479bd193", .None}, + {.Sub, "-3f8bb0d4a755003f61b71c0c7c63c4ff6cdf8026f7ea5dc867f4cf7a1a04649591659c5aff4b31f052d70d881453692aa023cfaf593dd615669eb11e376476e70f0cbfa48e80ba6e6de2515958f845c59befa2cba41fb0a687913dc7960fccfc5feeadbd6d712c7dfb30a844d92ae0640a39c5c54a8f3203e7a636ddaf2f2ee1694a7fd1d1d58e66afbb137a0a6fa13d1bdc2269b536", "de145d35494c97b8bea82c8b698cff476e636063d433584d581e39d92a6f22d9ce7021331a7b4b08599c94e1dcd1a7fe94a633c7c40c05230a3aaf5cd0f0364cbb04e3cdfd6157607b74e3dd5c98036572a60ef3ed6db7449a5652d69629989935189b953c764c84b9f859a62b72caef453ae8cf1d90719b1474432e2fccc2c36bd81d2d1df9423836a78708ffa643faa0fbbe12063b", "-11da00e09f0a197f8205f4897e5f0c446db42e08acc1db615c01309534473876f5fd5bd8e19c67cf8ac73a269f125112934ca03771d49db3870d9607b0854ad33ca11a3728be211cee9573536b590492b0e95b1bf918d67eb21e7909e2c39659595074952a9e77902b52901eb049dab534f74ae94681fa39efc1a7a0bdefbf1a4d5229cfeefced09ee6629a830a15e537bcd7e07bbb71", .None}, + {.Sub, "10350085f26436b307f5465f19e929c1379956aae3c846fcc07e1a207ba9ef53e3eb37ca4eb155b3aa8ae092625abb1ff559a90a90745fa9c53ba9245eab71226999b1a7d4d594f140110445755b554c7ebddccbb7079ec4e7fa7ecda47b9f758e79273653ffc1a38b45050463de3c074a88846b93bfa41b3227a5c2bce2ce53df8f0af174ff55ab491931f5f6ea7a8b04282d972e49", "e233ab87d3cf770ffe31c167f123ac0978791a27ad85a34d7f1ad1d7ebd833b74b45ec4863252f37b347d5114683641c0da7c01e51a4d043f4038dbed6f270b36203c3a123587d420a8e2d7eb6743b62ff3554dd59c43bf8548c6cb47416a1e0e92ab68bc4f3e74a25e945b468e52c3452ff300d5757bef152071119cc11a31542966426196ec79d68f28602ecb15e13e6b9a81b6826", "-d1feab01e16b405cf63c7b08d73a824840dfc37cc9bd5c50be9cb7b7702e4463675ab47e1473d98408bcf47ee428a8fc184e1713c130709a2ec7e49a7846ff90f86a11f94e82e850ca7d29394118e61680777811a2bc9d336c91ede6cf9b026b5ab18f5570f425a69aa440b00506f02d0876aba1c3981ad61fdf6b570f2ed4c163075934a46f71f21fd9540cf5c6e388e2917a8439dd", .None}, + {.Sub, "7ee79f46a3fb768a5b5b30d1f089980937f91dfbb44ce88282bfe561dbc0e528432893336c45af1bef918cf8295429a65581ce0940adb6561616708c088acd14accab6393d5f89f4b443a035505f65e44c0a2fcdaaa540e415ff8d04a26efa0d3057b558667589821eb8c2e87abc9afa3d27ae5ffe10a3eff8760fbdd2e9e6fd17fbd35d6a172e6a1135fe01ebcf329b81f4caa8f640", "103ea738455e03d8c4d5ef168bd29b8db15eab8d8f3b3e9a8258f5978854d1f40d452b119b589caa49064dfbc52f2cdaef4ec8547ab03106b0d588032d0e032ac268de4e158cc470b8731d93eb50aeb549fe9d8422c950f522cae1b60ee7d5de644b592226280b42598c8206a074656ba2197f789ad7c9a80692dbe4e7e1c6ea8ccd207c3576c6ec2bc27eaeb28e9033e1ce86e7d400", "6ea8f80e5e9d72b1968541bb64b6fc7b869a726e2511a9e80066efca536c133435e36821d0ed1271a68b3efc6424fccb663305b4c5fd854f6540e888db7cc9e9ea61d7eb27d2c583fbd082a1650eb72f020b924987dbefeef334ab4e9387242ecc0c5c36404d7e3fc52c40e1da48358e9b0e2ee76338da47f1e333d8eb0820128b2eb2e134a0677de5737f533940a267a02643c12240", .None}, + {.Sub, "-bb06e305207438f2dd14bf5a8fe983870e743d7bf376db742f74a6e9eddf2010b53de002c9a5cde5f70bce2747456273043a6d7e99f87a9733e369ae77641043b76d7cc6f5f0c98e25931072006f11e759669f0d5e49e1ebcd4064c789fbb4f2aed1f5a0e01cd8fbe1305922d31f4ea6ad33b02667a922d7cd7f48d0411afae9087771f7cd288e46dd9bbdd652b71223bdbdbbcba133", "48f09777ef84df9441c36301aa10fe7faf833667eed02bb16ea8f41d58d7a0b898677a839f09617cb8a813f89bdca7bd4f85d08a463afa17c810e1fe2d118618873c69d05695492af393f0e3df83b7067fbd5ceee1a6a316deee0d1340758c4a08b3c411d154a1c281affb88a30a3fabecae019256ce0b6ad103867101f2aac1aac91de01c7cf075e4827cac8d1dd9531ea371fb2494", "-103f77a7d0ff918871ed8225c39fa8206bdf773e3e24707259e1d9b0746b6c0c94da55a8668af2f62afb3e21fe3220a3053c03e08e03374aefbf44baca475965c3ea9e6974c8612b919270155dff2c8edd923fbfc3ff08502ac2e71daca71413cb785b9b2b1717abe62e054ab76298e5299e1b1b8be772e429e82cf41430da5aab3408fd7e9a57ebcc21e3a82dfd4eb76dc612dc6c5c7", .None}, + {.Sub, "44c835d29f2ee0221c458446c61267dd014aadf471bdba16288fb60af8d8c6c57064074d721edf698d1aad07a6c3bea17c4160c0821c6acc3e9620956de0b8e7b94829196dcea2038d550ce0b5cdda9b8e67a7524459d7be9f4fc9818868e2eebc06b31e8f6f524438f9694df25aacdc0a35b3043f14aae5d6694e08ba24f6e15d0406f2d7b286edf1854c60fb08f8d4a6812eda02df", "bb9ee61ad9dcfd30140b0e80d438f7a9385ff41e70669096e9115ef43c911e0d7757be29b90c999c234b010dd2f695a78eadd4340b412c384403b37c3dec23891868c37d39b5849dcf3206f1d54a05ce126ea749828cbd8fca003de0ad06ecfc75e38bb1ab3826633d7d0a249cab306f179e9ba55ec2c2688efd43b162f75c54c521f36851643d61644cd0cbc289e7eb0b7ec9a4ed0", "390e4770f191104f1b04d35eb8ced8626dc4aeb28ab7510cb9fea01bb50fb4e498ee8b6ad68e15cfcae5fcf6c99455470356837d41685808ba55e55daa01f6af27c19ce19a3349b9b061ec7198793a3ead40bcddac310be5a2afc5a37d98741ef4a87a6374bbcfde052198aba88ff9d518bbc949e9287ebf4d7979cda3f5811c10b1e7bc529c4317db407f543ee05a55f5c9423fb40f", .None}, + {.Sub, "-a653f3d70bd0b50b6f663ed0d473cd9b4c4db7b6b1494310a38f5aaab1297fcb152cd91dc9fba4ac785de42e7d50dd5fdf335696a025578a2d1d97336317c442278c8f520cc2a3245aca0ce458f460a2c7edab5395283a4b0a470eebb1a16dd76a5a856fdcc28d3fa1cd06cf33cdb8eec2e89178cc7ca4c4824ab0722ca89ad0f736081ece4a2e51e3d9a625c49e7723ab00cfec3ea2", "175fc6a62f5239055e32cb570b92b84df1a7581b2fb59e0193739cda20554c4d6960dd9b0fef9c413159f0632915f4991433931f36e72876c6568622adb0baa88eb595f886039e1cd038df25dd8c2b471729902c2094b1770a0c3cf0e3d9e2c9506e0008e8819d7aebe57f59bc52f86874613242943ad068674deb9baf19b9b9e1e171b3f5044ec959f44a2e0f5a6f158c541f51ad01", "-bdb3ba7d3b22ee10cd990a27e00685e93df50fd1e0fee1123702f784d17ecc187e8db6b8d9eb40eda9b7d491a666d1f8f366e9b5d70c8000f3741d5610c87eeab642254a92c641412b02ec0a36808be9df173b7fb5bcebc214534bdc957b50a0bac88578c5442aba8db28628f020b1573749c3bb60b7752ce9989c0ddbc2548ad91779d2c34e7d1b3dcdf053d3f8e6393754ef3deba3", .None}, + {.Sub, "-5d7bab5e3916e9a193f41eb0d4e4bd9cd50de5596d257670329ee4eb30fb4fa43b5ca1edef1e4823fa22d46852a7e4cc015bfc352e33bc5d5da0c1a472b8bcdfb3127a1d4e83188bacc46b9d11dc777fd36339b4d444a0b344b3007b60458ac527dad5b36e8f44170a69ada5f1e0a5710f439febb9f5f0211f120073f2e369693ed87da7748cafbbae417cb51b7383d340a6bf91aa41", "dff0877ebc262e6d6b2b3dd0ba518246a272ff9ec3306e7063382a9ffea249a6ecc5135980fc756ff51074399a48fb33482fee054d1d2f9f04d96aaaa962e2474edbb32881d58f694510895e44306ae32b68f3b700d4efae23340f6c405e6a2ef081056761b7bca49b0dfab80a2dbc9a8eb50930bf9e6dd5bf017f96bc3986f495b71d271f815bba915e83fbe4e0beabf384efdd82b4", "-13d6c32dcf53d180eff1f5c818f363fe37780e4f83055e4e095d70f8b2f9d994b2821b547701abd93ef3348a1ecf0dfff498bea3a7b50ebfc627a2c4f1c1b9f2701ee2d45d058a7f4f1d4f4fb560ce262fecc2d6bd519906167e70fe7a0a3f4f4185bdb1ad04700bba577a85dfc0e620b9df8a91c79945df6de13800aaf1cf05dd48f9ace940e0b763fa000b10054427f342baf6f2cf5", .None}, + {.Sub, "-3b894802b78bce65c246994ff817464ae37a83fbb200ebb6498766f4e547483d4d0892e167541d230c6c41f4efc20f3986abb9f08000469aeeb70006a07e0ec2c55548fa3e9dac38a06ff12fe3f0eca92e17ff8deae366580cae55c3634f62a25ca28053efea28e0baf05463bbb57010a6abbacb02ce4bde8d2f21c402f827c85e90a534f92f2f7731bdb4c427769c614fde4625145d", "cf1391ac35fd20344336fd7aed1727977f4a91bf068c6cdc2330ea03aa011edf55d74c5663dda915bdbe4e2c72163785a5a5fafff8accc734f5bb2da030577fe1d49fbe6f9727c9c4daabfe72ed19c7749eae4031f120a47e6e464f878dd975ece882b2e56517b3a287d0b42be9f520fccddb23aa04720ba6eaefc26bcc4035d215097ead4382f2299a9642deb2c974f06d2b80af2a7", "-10a9cd9aeed88ee9a057d96cae52e6de262c515bab88d58926cb850f88f48671ca2dfdf37cb31c638ca2a902161d846bf2c51b4f078ad130e3e12b2e0a38386c0e29f44e1381028d4ee1ab11712c289207802e39109f5709ff392babbdc2cfa012b2aab82463ba41ae36d5fa67a54c22073896d05a3156c98fbde1deabfbc2b257fe13d1fcd675e99cb6718f212a333b056b0fe300704", .None}, + {.Sub, "aef4fd633eaeae20ae20748a136a0ece33b878a60405a436d52df47c2567453e395f6146e952535a74f141cf334054ac3d4dbc5a8b3ed8f1f15d39a2aa6e9c6c0b6ad7de88a7a4bb44edadd1ee7a61040c4fe02b87f175f8b334ee063cc71836010dd656adc814cb08a6b5f461573266e9fb4b369d2820299f3f1a4fe656034f18ca60f1866f721ef28be08e253329040be82fe08725", "12f032c500e1cab5f7dc2ee41f984546e5879bd229e869260b6a2a3170e268cc4a7811f79569bf6f88d0b721ccc51f5f0416fac0ba969a7f802995b38aed4ddb890ad42e6eef6488f9b0b7cff54cd0ec14b7a5001d80b6e14c7960ef058493355a196aa3c0b3ec357002aa7dcb7f6458d9a611b39b22c972173f86d046c564de29d65808d9cd07a6f32475b2fa4cc902ae0c9d0f5e9d", "9c04ca9e3dcce36ab64445a5f3d1c9874e30dcd3da1d3b10c9c3ca4ab484dc71eee74f4f53e893eaec208aad667b354d3936c199d0a83e727133a3ef1f814e90826003b019b840324b3cf601f92d9017f7983b2b6a70bf1766bb8d1737428500a6f46bb2ed14289598a40b7695d7ce0e10553983020556b787ff937f9f909e70eef408e8aca26a77ff676adb2ae660015ddb92d12888", .None}, + {.Sub, "-531b9b70d466bd795816c9e902fea79c047448c3459f949078c5842f0aa6c615c743c6f22c071c8feb133086c5240b8a9072586c76e5016bea0ce11bfa664bdf05ee11a1a3f827a857a839e13cb9f8a07af4aa0aa7a3c32a212cf5089692c120d7dc3c2f8b2b6d9cd112108d77b40609200e443ae53d6f13f7ea75776e9be610a354036bfeb4d910baa5774cdc9260486560b6b6b453", "8992169d388b562da51391034721c29b7d0aaa4d70bda61936b261ec502a3fa09fb33f7d164b0dc97ce84a27cb4107cc2aa19487029c64574942c10235e0cc43e22adfe85aa559dd06b5c85013aa3ec5b4259d61cb718733cfd7641a1b89bca38e6674db229a26c519c494e84ea5dcedab22497effd4d22349657c6fac34dc3415903ec0e283408f72c98bfcc2a6b30b9516806de53a", "-dcadb20e0cf213a6fd2a5aec4a206a37817ef310b65d3aa9af77e61b5ad105b666f7066f42522a5967fb7aae90651356bb13ecf3798165c3334fa21e30471822e818f189fe9d81855e5e0231506437662f1a476c73154a5df1045922b21c7dc46642b10aadc59461ead6a575c659e2f6cb308db9e5124137414ff1e71ad0c244b8e4422ce13819a02d6f03499f391353fa773724998d", .None}, + {.Sub, "-981ff1794fa33437d46f40876fd0a8e759a0c892186980e5e85faaffd1c2a3dba0cda44cc819425b7752893f935256e437e3d38612e6d556ebdcf7550c6f7203eeed0a2486a19c93c54ca249c6a9879fc7c55fbc36d0f0e553fb0be6baf925d6a77099deec78053358ad25c19ec9642f529f2d678174f518e23e70839f308e7a9c9cceb47fe560885080223d7aab6a914c37e411bcda", "41cd1b8330d720b7a6d575b0bfb5339b5eb00e540fe033f65bceca8435fccff432ddd640aa452a99ba2dc570f8eb030375754db8002f3d14032f7f06d245eb9525c9cad46e1eea1cbda1e65de43c976c4d7766768c57af5eb24658b01d7c1bd1b3e6dc4d2f8667add9342345dc3a7e877a53bddccd6e27d761a12a7e3846703a150b24521747699ce96dd0a0e733e4493ca4ec5e5c6b", "-d9ed0cfc807a54ef7b44b6382f85dc82b850d6e62849b4dc442e758407bf73cfd3ab7a8d725e6cf531804eb08c3d59e7ad59213e1316126aef0c765bdeb55d9914b6d4f8f4c086b082ee88a7aae61f0c153cc632c328a04406416496d87541a85b57762c1bfe6ce131e149077b03e2b6ccf2eb444ee31cf043df9b01d776feb4b1a7f306972cca2539edf2de61df4eda88dcd0701945", .None}, + {.Sub, "-71fa04094a3f0d160fb207cdf60e48b2b33e8fff58c7f554bf6337956d97655cb7504f7020929cbc4b6dd1679bc6f94877c1d6cb3758e2d283ce68b4d4c8c3dade60f0cddc6b5a4baf16db1e2003e993408307dbd8d26cf5ac8a6ee1f23da7719502eb926675368914fe9cb652ebf78d2c70e2750153e9cbd160cb948a7ee68d4d79a2f21e05c60e6199b9867b7a601265cc0856a669", "89f1e175dfe782acf5c44bd1fbd0ee307a4d478517ed29bb4fa4334245fc92fe0fd1f7ce8e06ea1f91ba9cadd4a943685bcc86bcdbdf92eb9eaa1881871a9f6e6a01aa64f086f29e97d02e9f9e52acf1a69fbe74b221ff253be4c5dd9d2f88b1c7c3632dd102ebf13561e1bf2c52d44aa8ff6757dba662ef05e8e783937f65680532a7f95bf998ff3039ea5e44a3a84727fc18b74069", "-fbebe57f2a268fc30576539ff1df36e32d8bd78470b51f100f076ad7b393f85ac722473eae9986dbdd286e1570703cb0d38e5d88133875be227881365be3634948629b32ccf24cea46e709bdbe569684e722c6508af46c1ae86f34bf8f6d30235cc64ec03778227a4a607e757f3ecbd7d57049ccdcfa4cbad749b3181dfe4bf552ac4aeb79ff5f0d91d3a3e4c01e08598dc8210de6d2", .None}, + {.Sub, "dc5f6775b8adffbebcd2962eeb08caff11481263e823b3f3c32689fe88eef93f9b047eee5e875c07f44f4f5613ad2901c5c09f448197663e7e368b2273042e5c572623f675bfe9a8c47c8c4499b7579f3d1d95a23807ce1c0e4276535472066a0815544c8904d8db321a2243079971306c3032137ea53bbb29d60fe4c209e9603402762f1a8a6ac398079e3c95ac664e1416dfa7afb4", "3dcc9a827aa51b2cf8b685c6e9e567674deebf690c75e79267beccf8edddc880784501c73076dd8f1f96eadaa1a73adad4a99e11e37fd30348af96af9c4b4fcededd6f51fdeb6b3edddd46ebb199469f977079e127cdd1b34e0cb1030022075d50f7aa95de6a94ac22d4373231ebfb6377e5d5f640f208b6d1d8f6b75089d1cb68c114ae13c392b2489cf769d573373d07db3abd2491", "9e92ccf33e08e491c41c106801236397c35952fadbadcc615b67bd059b1130bf22bf7d272e107e78d4b8647b7205ee26f11701329e17933b3586f472d6b8de8d7848b4a477d47e69e69f4558e81e10ffa5ad1bc11039fc68c035c550544fff0cb71da9b6aa9a442f0f45eb10d5ad75ccf44a5c1d3db3330457fd192d71801794cb41618106c6d8114f6aa6d2c0392f110c3ba4ea8b23", .None}, + {.Sub, "-5bddb8f1bbd13829b4d8405f0639cb1b25323e53f9d68ba587461bcafb46ab142128e7adb569f7713bec40ce51d271fce4fdb22b94a70bb31b94c79e1959450bea56f441328decd7bc29c39a989d1956a77a998cdda66a445102e19071702407df6716e0bfd3b6ce1d365f214fca4326568f5cd5d9a74d82f90c2cd73356362b5c60475e06f91c0ae25257ddc4e47d7bb284ece247f", "43cbea3ed31b81db8071caddbe6463d8f1e918d063e885586830945b030a681ffeb69a4ccabbb798fb7d0a7f76da0656483137dd165c40fb5e3e12ec61788995b0a6281be6158c439a719488232e8095a9cb5f46b2db914293cd3d220f556d22c0aff9df161dc761b45101b418998cc1da6272c08035c15ee2e2fe2db0a42f8656b5cc2822436a43e6afb43acd0fc8c2eb518a9c9ce8", "-4989c5cdeed8955e1bbf4ee3aec8008aa43c3cb5a385ee12c0a4f617b2bed2d140c928c7a61257100f3bce8c5bf72d76168112ffcfa6b1b68ff75f66430e1de66f4b975ff93e6b11163430c1ccb8522b144308df80b5f7e6d8dd6b3b166c6f633ea66b4d221b02ce962467a62d9630f43fcb688dddd036371273c0fb23d992e90c7bd09e02b2fc0494d4d9b8a95e109aa679d96ac167", .None}, + {.Sub, "538d6ba80c020e70cd8580f33af8afd6c3099a44e3342d15b67367c9d7c05b6fcfe843fa7c015e003d14284131f362e98b6a671675b3082532ea4a9968eebd6967510423bd6f2c9c1afbf7abfc12f5e34a3bec6007363e9d8310489aebab2c6da418bc727906e34daa59478b8241bfa70c5aa5f2e2417ffa1cb0a142472fff15a6e91099b1bd686d12720103bd8f6ed1a20c977784fc", "fd8d29234d9d04f4752f5a639ee4a41f326e92e243b65e6a84d1c64406e8279bedd60f164c43fa57b35020471c0440a2167a86f87fac4992d43675cd7c53417d705a65239dbf33ae783bab62cc73ad381f587b15489d8a8c358b06294441607a4e801fd7cbdfeb0c98ddfecd2ea4e19d592f88d797d794acf56d0c4a179c837c7b82d272955d103348f6c4928319d91faec9f7cb0de5", "-a9ffbd7b419af683a7a9d97063ebf4486f64f89d60823154ce5e5e7a2f27cc2c1dedcb1bd0429c57763bf805ea10ddb88b101fe209f9416da14c2b3413648414090960ffe05007125d3fb3b6d060b754d51c8eb541674beeb27abd8e5896340caa67636552d907beee84b741ac6321f64cd4e2e4b59614b2d8bc6b07d06c8466d499c1d8e39fa7c63684c38ec58a6a4e0cbd605388e9", .None}, + {.Sub, "f20b467e474b38e8a27ee22a200f4ffbaaf8b89e3a94ebe177ec410f65fe6ba94e5611ee43190808a58142d7dce92b7a4a5163a24f6f00c90d8e48f39a5a557c4027aed95cdd13b07dcbb8488a02dd6ca9558ce084d1fc604603749ce235c6d6a17cbdd1dc29aa38fdd69d1f8645dfbceed8bdcde6c25d40babc0b485de6ebe441c3c4280cc424514ebb70e59d0a3b7c856c82d5814b", "7ca6b8aaa264b49e8f57458f592bf62bf42f28ed3b3c4932808050b97de1390b5f742944092fdcd708e6917386963b7a763e74f167b954520f8a998570ff967ff22361d9e160ead086cd6a7a0eae9f0ea74d0ba4c4e953dd42703e1e571fdee4e3e6b1150850335ae75f44e5861fcd5ffb0ce4f248266d61fdd58239b0cad30a39e3f13f8418c0ce0697d2cf58b0346a4574aaa85e1a", "75648dd3a4e6844a13279c9ac6e359cfb6c98fb0ff58a2aef76bf055e81d329deee1e8aa39e92b319c9ab1645652efffd412eeb0e7b5ac76fe03af6e295abefc4e044cff7b7c28dff6fe4dce7b543e5e0208813bbfe8a8830393367e8b15e7f1bd960cbcd3d976de1677583a0026125cf3cbd8db9e9befdebce6890ead1c18da07dfd2e888ab638348239e16445a07123ff7d82d2331", .None}, + {.Sub, "-4917dcf7c52cb06a68078a1b3f7b5490cfa74b15d6b46ab509520ba5443a596b53e0718369a6433c1b184fd823b823c535d7f7931542663ec10a309370cb2961ec693b40354be0b522eb6d1ea4f63995ef7c11cf9bc4f32235c6c9cde7c154f105f9e6594987ecbad1cf65e5cf5f3300683b530cad05f3c87e8ec4710b18aeba5eb9c851f9ce71a32d7329450ae34d731717e08657c1", "d90a9b9c3dc5b65dae2fa3d5c46c07a3a2cbdf2e51b68d27822bcefc2051d0b4e1e3b74d0be556524641fc0cea1a6accfdbc0d7bb354ae090829b60391d7f5f706f92506b81f26a490b9b107e7edb1a57ba552cfd254f9c0c09e0b01919dae65953c656d5b0100404d2e4fa96454444978ef0b2d8cc2d060ae9b9aa79534b13397b7e73504a680755d7b5fa69ca54b0c80326118d099", "-12222789402f266c816372df103e75c3472732a44286af7dc8b7ddaa1648c2a2035c428d0758b998e615a4be50dd28e923394050ec8971447c933e69702a31f58f3626046ed6b0759b3a51e268ce3eb3b6b21649f6e19ece2f664d4cf795f03569b364bc6a488ecfb1efdb58f33b37749e12a5e3a39c8c4292d2a5f18a04d5fedf671af86fe74f2188aee88eba788987f974a419f285a", .None}, + {.Sub, "be6f45343f010c9a3c679eeddfbbbd2ace092889a8673f03b3adbf64044fbbdf4f690898b322e3b3e1b47f0807c28c5036f423a5e0ca111f5d7d92659c741af694f4793374beaf4fe487823fbd14064a15cef2f191a747406a7706555b2d9321411d52c603c25ae01946037323e28afc8ca07e9e3306fdd95d6fab0088a15fa7c736f2df3c2aa35ece51d4d63253a4d1a194ea0d32e3", "abe9d611f8791741e45a62f4234d54c065a1025da370d655af16e53ffaad12d95a698c62bb8b6f1fe8c5a37a93629141295e16d31d59eaef9eaa79517751b80e128caf9acba36eacff947994db509bcaf14d89eb5fe24d4a9826f39a60d9705e5ce3aecc0a858f44b9848b3f973cc846b12258d9942e66371bba0cf2950bc53c7f8c606d4b329aef6884de7bdbd4470ea4c6e42283f9", "12856f224687f558580d3bf9bc6e686a6868262c04f668ae0496da2409a2a905f4ff7c35f7977493f8eedb8d745ffb0f0d960cd2c370262fbed31914252262e88267c998a91b40a2e4f308aae1c36a7f2481690631c4f9f5d25012bafa5422c2e439a3f9f93ccb9b5fc178338ca5c2b5db7e25c49ed897a241b59e0df3959a6b47aa9271f0f8086f65ccf65a567f5dc2fcce05eaaeea", .None}, + {.Sub, "-d43e1bee188939668bb23ebf0827252e8291538277249343bf8ea607c1143709f0253c3cd6418cda24f0227647a4ce428518d87c816a5b23c8e317cfa458034b5e441cdf190f9c51953ae66f4f3ba64efe3cf9baa8a6ca0341ea205f58c933cc879451fd737cdf952cd9ee3b36d7f1659e739715240e89487d8ceae0f1c47e6f441aba8cd35a644e0baf66fba7552dd2e2518ae3eee3", "40488723b6e92aa00c1a4f9e66b1dbd39831ad9b17a01d15e7b4400cf330c28ad616fc8e28dd4684fae1a005fc14d49dae119b8071f232704a3b653e0dac6d3e1190756d1853207c5fc7ec399bac06abe847bc58ab5b8511097d1de208e8d12fdb1fa4767b21a169930888c069e0bbec1e36c60bbac1dec7fbbf58385825705bd4921c6ba1c24f98cbc6ad0ce7188bd1a57850451f25", "-11486a311cf72640697cc8e5d6ed901021ac3011d8ec4b059a742e614b444f994c63c38caff1ed35f1fd1c27c43b9a2e0332a73fcf35c8d94131e7d0db20470896fd4924c3162bccdf502d2a8eae7acfae684b61354024f144b673e4161b204fc62b3f673ee9e80febfe276fba0b8ad51bcaa5d20ded06810794c431949e9eecb18acd6f8751cb3e6d77614088e6db9a487c9db290e08", .None}, + {.Sub, "-341727b90dd65e137419d7bfc4539b65071a028e50321d6385ea7f2de9c0f71693b17ae8a683de51d5c2b27f33142cfd451a3db62909e72a1a1ffd600fbbb4146239a80925bebe41555fc71672f349974e3ddd3bc9e38142a6a8eb58305a1c957e80606ba9a411b947ee659a83b534cbe77f7a18ad30b1babbc466a07404d8db060676db3adb936e37abdba88100be846c062bd206d", "40dd68ce2e9c812d1f0b31fe92c611019956c7355453bfde6de9cf0d0e1d18beed21877ba7dbaff7f6b0384ef8bfe68a9ae211c5792944c26ea37f4a886c2f99f691e011029fb0a811b781f1f17da4a49547965c9ffe66196ec2847cccf2a84499d679e1ce027abd99b4ac0eba13354469d7f789b030870cf3fa51e6a84c11f8cb2641821e869883951fe8d945f1c9f589d2b7d99c98", "-441edb49bf79e70e564ccf7a8f0b4ab7e9c8675e3956e1b4a64876ffecb92830565c9f2a3243eddd140c6376ebf1295a6f33b5a0dbb9e33510457f208967eadb3cb57a9194fb9c8c270d7e6358acd93e0a2b74305c9c9e2d992d13324ff84a0df1be7fe8889cbbd92e339268624e8891284fef2b3b0392289fb69850af8c5f867b86a8efd23451ba789aa693ce01d5ddd0931a96bd05", .None}, + {.Sub, "289c5af9776135933591dd5adb5d7905da6a2f0542827c0b1735be52bf7243189b6649f3d2a26d00b80f75b1522d772cc87ddda59682d18791015546edb4d202b8ba368e044ae8a6a40764df9e670d7fb065013ddbeaa75df950afd356e748dad39fede3333f08274eee3b66c1c20e5067783bc4dc9008baace9a510315304867dad7d2f891bdf8627e886795f185f55a9433426e76e", "609fb91ac674537d7d30159f5012c28a3b3a9bb33443d568fbd39494b385729fcb4676f6711422ed82e1b1594c30217362c815c3f62783e89b4b5c9cc71a808223fc0538d7ea6fe434efcab2b504ae8b64d3fdfbf7ee2c7a225f4a35f488699925125ef409843b01130035f132e269f9ef32db726360e24529735281c1aa7fdf0f056313daf4c8039503c2c31f89ecb3cdaa2b1a216", "22925f67caf9f05b5dbedc00e65c4cdd36b6854a0f3e3eb4877885097439ebee9eb1e2846b912ad1dfe15a9bbd6a751592515c4957205949074c9f7d214329fa967a763a76cc41a860b868347316c296fa17c15e1c6bc496572abb2ff79ec241414ec7f3f2a6c4773dbe3807ae93e7b0c8850e0db659fa965a526fe815385c888cbd26fe4b6c9305ee984a4d2d1fc08a6c6891754558", .None}, + {.Sub, "94c945ad02e3a770f61aeb1771e2bcd1ea517b2b8ef93ce0f0e921bd773a2433c817e1db8f4a8b2e9d1bf2fbd05b842146603bd7e808f0c2e0f4dee74a934fa497de1e9e0fa37421bb7ae44802e2506b1c459d5d0ee2d6737ee63e3c9991dc7f3a7f385ebe452c9839eb069b91a5fa7623dbc9f83cc0b7d328604ad2b857e93877269bca8a3790f3247451d5f49185a29d3586a02bce", "fcd5a95ea22f7a1640729e02d3b7d0327ab32b196e84b8133403294644eade503c77a85b417b3e91180cc2a430316cfe3db4661eddb3632527d05fe49497df0c6e5122d6340e206c2ed105a0dd63af52b9fa26ee446deb4e459e9cade03b9b448f2f4e2fe4ef3c799ba8ec956763813f5c32f964deb8bc457d11ee93f499eed39f37dbbacea3f0a8263df055c4f85c94e8c7e2e5cb74", "-680c63b19f4bd2a54a57b2eb61d513609061afeddf8b7b32431a0788cdb0ba1c745fc67fb230b3627af0cfa85fd5e8dcf7542a46f5aa726246db80fd4a048f67d6730438246aac4a73562158da815ee79db48991358b14dac6b85e7146a9bec554b015d126aa0fe161bde5f9d5bd86c938572f6ca1f8047254b1a3c13c42059b28113ff0446c5fb501c99e7fd066d6f24b925c459fa6", .None}, + {.Sub, "-1a4f39ecc7024e4c9fec68c628d0bc9edbf348de82cbba2ebf629e3a13e6c4305ccad90608192d2f0771d07d4144aaef2d76d39fc764a6949d6bd5b06aef4f516d88a27b64f2022801fd14deb1caa6d2df04eb37120b326a117142f0d1ed63d0e72968068330f016c10961e2f3e80d3cc6d1509e584169ab86b95cb510e56439d542cec2c3e90512f3b459d80ce5a6fea58056085c18", "e17a3704c63a82e6c35e0e2e1a3a6713dadfcb9a3e17f3a0919ef69dc4672ba776c240a7701ff3261265ead4c0038ff69f10da1cc957cf74b33a59af484456a592dc292963373699516cb93d293c4c5b54c9cd3f75f8c85dc6075eb51fcbcb945592623cff5de4571288ee3b5f9dc9baf50389390684511d6f5471dddcf164893a56d22a0ce1376ae2f18ad53104ade44c29529ea38b", "-fbc970f18d3cd133634a76f4430b23b2b6d31478c0e3adcf510194d7d84defd7d38d19ad7839205519d7bb5201483ae5cc87adbc90bc760950a62f5fb333a5f70064cba4c82938c15369ce1bdb06f32e33ceb8768803fac7d778a1a5f1b92f653cbbca43828ed46dd392501e5385d6f7bbd4d9d75ec5bac8f60dce92edd6c8c30f99a0ecd0ca3c7dd6a5e4ad3dea54e2f1a9a8a6ffa3", .None}, + {.Sub, "bbe35b87c5cd81a4f6fcef911f3558d29dec06dad4e5402e8140d1aecdebde13fbb629c5313acd68e53ea2801f7dfbd5d64d77bd8b6450ebb499e88fa944ef216cd0b2aa60af8aa13a6fbc81190b413cc24d866c8a6ffbeacaa0c28fe3f7ed58f9b9b4d7527ee1b456b051968ae9501839eadac55c4a8279489de8b755730f7705aae4aa75bde25edc5de834819e373b29a167d9622", "71a7c184d5f7a83f4bae70f6bff261b7f8fe536b03449344f0e6da71a6addd9c2a0d863a17c2dc7f98ed1abd4a0df436b49517f260f1d94186bf9af4f6445be6d7cac4d38cbe5c47786f809d02c4c77d1c9cdfa92c84d228209d5c1ee13c5ff9c31349f5e860ec969cd879685f15dc6a241a9eb3f3f5a9c04cdf27fba56f311d3e932f7732129a4630c143e71cf42940d1c5e7c0e17d", "-65e98bcc599ad024fc3ea1fdadff0c2acf1f92fd55f63f4208d2cd56b9cf1fbaea52239dc4af2fa90a9930954816147957304076883b9432cb75fc6bfbb00cf4c0fdb9a8e6b3639d64c884d4f13413695078074263ddd26973f34ff5e2fce1243377aea87338fe7b576d744ef6674768a07bf1079e310198b855497030180025ce38812c8ab6bc2042fb6563d4da45cd1f2bd1434b5b", .None}, + {.Sub, "-c493bb16fcfc3113aadf8d32a7494f3b70d820dbffcbd90247c923835aa19b7f75934a88c012679e5a737828586876228cc96fc6b9a2c302c77c101e2f849ca191f38624607cb59a0fb904f6415e9681abcc06cfa7f030f0ac0d40507a7c34dce5faee61f81d0d2feff585c54a5e4006bcb57253d3e9f26b9c3c681065648bb5f2b252ce906c59c9550c4a6409ae1b71897d5a669687", "a184080e79ba79fad73d7bab56272d3f37ef6a710c15f9ac178292c09321c4fdc31806331fc595b4e822679e64c1d486ca6646b5c303bb3776552593c34e37a65df236a1ce5e2e74028e9265ed6e6a9f93e1d98ff3041ad358c2a6a5a2a6c3dcf323a2c0efa5b3cb282eec98facc5c4c124cc31fa56ad18bf356a4873cb31e7a5ca7191a1cdf2d5ca2a81754b74dd45020ebf00a23f0", "-16617c32576b6ab0e821d08ddfd707c7aa8c78b4d0be1d2ae5f4bb643edc3607d38ab50bbdfd7fd534295dfc6bd2a4aa9572fb67c7ca67e3a3dd135b1f2d2d447efe5bcc62edae40e1247975c2ecd01213fade05f9af44bc404cfe6f61d22f8b9d91e9122e7c2c0fb1824725e452a9c52cf0235737954c3f78f930c97a217aa304f596be8ad4b8725f7b461b8c0fbefc1aa694a70ba77", .None}, + {.Sub, "-f42076fe0d01a39e7e3b76812e9b5cfaca2c1ecc837757ed516797b16b6e5e15f11fc7e5afb3165a015e142b38be4510cdee746afd6ba57889a8fb133cc3016e30f4a1ee0bb685fe0e900e46eb98d473384a9c31dbf44c5658686108e359bd489e4d6c0956190c0d7e1b13ca789dfa13bdecd3f8a1e823480da3d43f0ae39333f6aa153d875fe995c74bfc778b379520f3fcd4c70128", "259c23997f38313caa42eef25dff94dcfb6033571baf31eedcd5a6478bb3eb503f546db052350d70fe7a6f78181625fb91067940e058cae52aa87fb017e9e51180212e68f57676a125466847e9bc957cda01fabaa64b087f3cae4c3ac24551d6003494e0fde80210eaaf02d37737c24718c95be37210a45f7edf8871754859b980258580b23ca87db2d43275f7271346344ad30e574c", "-119bc9a978c39d4db287e65738c9af1d7c58c52239f2689dc2e3d3df8f72249663074359601e823caffd883a350d46b0c5ef4edabddc4705db4517ac354ace67fb115d057012cfc9f33d6768ed55569f0124c96ec823f54d59516ad43a59f0f1e9e8200ea54010e1e68ca169defd5bc5ad6b62fdc13f8c7a78c835cb0802beced76cf9abe399c92137a202eed825ea8672847a7d55874", .None}, + {.Sub, "b251cdd5b99ba223e3df60e1eff6e8ddadfc24c3f1bd17923a9ac7af8751abc33aace8fe7fb157116121772c62db4630159f4a45ea76ad7c33e0a31b5cafbe826d80282299886f92f6f404cd361589aadde8f288206b87c867edd46d5ea82d32de1e507524e75a71b3ae451d7af3069181318ecc643008299bc47f4872d564cb15f1aade697d0c2dfbba2729cec8d4a456c769f85d9", "10e48db686d83d7664b6af1236c5a890dbc478b7bfc21423fa4733f3bb622ebf9bb1807a30592644ad6e23b004f9cf7aff198554daea34b852f52d0511807cbb87480e3c3dc808efa54b3dc36c012878abbaa24aad0a5068deca994cf0066c07ea7b531374a3620857675d7d53a6db06dfb848fc6e7b9b6a83c7d8a580a5868eec4c483aea1b4653f8cf8185402b815c76b8e82eca54", "-5bf70d92b3e83542678b90417c63a0300e4b66b80a642aad69d8778c2ed14036806b1ea485e10d3975c0c3d3ecc1b17fdbf90b07c42c9e08fb722d35bb580d360700bba142f81f675dbfd76989fcfddfddc13222b0397ec584bbc061a1be934bc996e0c2254ec613c2c792b7bf7aa9dc7a5300fa8389ae7ea0b90b0f97830423aed2d8d038375911913df12a33ef412314c718f447b", .None}, + {.Sub, "-e98b3b6c91fe9af1e1ba605b3262fd76a712b2967cf2b72a8f2e2c8ecc94511b652aaf4c5e844ef67e6a67ab74b7720e89c19fbee2a75e021b980b27fb5ae2db47b33682554fe9065a691b900630dcc047793edce325c29a98db0b805f7cd94e7cd2e7bdf88a444213466070491efd67477caae974f2cf6d72be207eee1b816d9d7e8ef192ca4d9e9fef7db92c57c68bf66afc962f04", "662362c9856d844ee25e3efddcdd7cbd9908508390bf2b7d4f8c56bda8b2cfbf0d0157dd824a4fa202cc2b52b53ba12e2b3ca06680ad75265dabc7a599d96bf9ba6ca772f4cefcaced07a431c3cc09c6610928491793ba380b62994e1842174b07564d9d5b216ba0c393412e5b358258f05c6d920dcb3dce398ac266ff086e96b69c8dff97eb8951e2b19269194cbf4030ae7cf44b35", "-14fae9e36176c1f40c4189f590f407a34401b031a0db1e2a7deba834c754720da722c0729e0ce9e98813692fe29f3133cb4fe40256354d3287943d2cd95344ed5021fddf54a1ee5b34770bfc1c9fce686a8826725fab97cd2a43da4ce77bef0998429355b53abafe2d6d9a19ea4547fc037d9187b82be0d3bac48e2e5ed23f004541b1cf12ab5d6f082a1102245a485cc2719798a7a39", .None}, + {.Sub, "-4b3914a3467f48f2bc3ef8301da96bddf8d3e5bc0e1e40cc52dfafb1181d9a900367cb4cede6244e58859d363aef67a675a393d16a86c0ca8436a085716537dbe73f1be0ca0aa263415b683ccccd8523aaa91849a234a9914d21ec088606cf482487a833cd13d1459ceb0faf02edf894664d0f82ae347490ba55b37abaff3a813a68db55301667ab0d6e66ac3802314c261f0da53f99", "158bc0e8ad71a7badd87c4718cab8376d5e7f09f487e3a7367c7d98a686da7ea37d7cb181471c357d15ef15c540a020be201f4e2d9d7a8c34d237988e7e2fc5dbbb2b2254fa1f77da78a3df7313d5806f9311841883424640eff0521206c1fd612927ae69b73a66053fae3b0287baa226f873486173dcead846bcf022f8ed9f653638b61508c1d486e1647b13c7a82d4466b16f7ca89", "-60c4d58bf3f0f0ad99c6bca1aa54ef54cebbd65b569c7b3fbaa7893b808b427a3b3f96650257e7a629e48e928ef969b257a588b4445e698dd15a1a0e59483439a2f1ce0619ac99e0e8e5a633fe0add2aa3da308b2a68cdf55c20f129a672ef1e371a231a688777a5f0e5f35f2b69a2b6d5d44408c572433e3ec1827cea8e14778dcc66b680a284f37b84ae5d747cb4206c8a249d0a22", .None}, + {.Sub, "7559a2b9b2a2e3cf75b32871a62a750ae49adcae99d7b5604012c3a8a8523249d6c1776403ca628881b7f316ab6366f07ba8e77101c4698f8ef770aeef64d65417249a8516f6e88f3fef85a078a0da9f1f28d94e724c602c1b0e65d893f5f13cdf39d6801f546fb25b0e1467f2edec2574064a2382ae4a7cfa6a689c4b7505f7ed00e3437752e40d1f7c7e36a907a2dcb17916c59bed", "e7f3e84add00c449bda4a8b8916ec2a17717c5125e8fc5342029557fa48400a6f67301f1650537e788cc5e3243a336f4996373114b47b1b5170c56de5ff123e827bb632a84a7816a8f90244c0c283a0528c85f08f4e340907f6fb73c47de54124eef31c1629cae82bba942875f53e84ab225e0dabf9b084aaba3d889ae513a66ef3a92fa92f30c0d9c276a8d1c14a1a817b1f9950b99", "-729a45912a5de07a47f18046eb444d96927ce863c4b80fd3e01691d6fc31ce5d1fb18a8d613ad55f07146b1b983fd0041dba8ba0498348258814e62f708c4d941096c8a56db098db4fa09eab93875f66099f85ba8296e06464615163b3e862d56fb55b4143483ed0609b2e1f6c65fc253e1f96b73cecbdcdb1396fed62dc346f0239afb71ba028007caaec56730cfecb6638e2cf6fac", .None}, + {.Sub, "-2e6c95f78518e9c755b845e6e41563ed78105eeb1f636774d0feda7b03e75bbfe1b28c717a24b7f0221f5a12ef7d5bfec7e19c69831583ba8f0e7abbeb68f76acd136aa3fec7b9d9c063a80dedcdb6ad0a568c4e8a3467f7e5f52e2c9f30a3d378d70f8cbc1ebd4a2809a9fa7dca94fdfc0e3a916d0d58d00719c81975c85fcba411f2c35ea7bf46e6adf293fbf58fd7d322c142d82b", "7c6a9a0250a81ee2c53b78d554ce30719181771d1f0754df94201134f05cde659599daaa875e4a0156777e35f78cce2f2b7add097bcc4c6f950a68bb2c218924646a7d482274f97ca4e14b4967fa3c8d48af3d7b9111e24c289b1df8976971e2a6ff35bc956e2a06bafdacf99191291a2dae45b7ddd5c54fc9a933793a29bbf5e51072856fd63a6f72b7c0ae6f5f45a93bd45f6ed36b", "-aad72ff9d5c108aa1af3bebc38e3945f0991d6083e6abc54651eebaff4443a25774c671c018301f17896d848e70a2a2df35c7972fee1d02a2418e377178a808f317de7ec213cb3566544f35755c7f33a5305c9ca1b464a440e904c25369a15b61fd64549518ce750e30756f40f5bbe1829bc80494ae31e1fd0c2fb92aff21bc189226548ce7df9b65965b3426b54d5810ef720b1ab96", .None}, + {.Sub, "-8b7b7233ca1967b8938201a00fb756f425b17d05c75fafe5eda031c67bed76ddc6cfd2ab63b5ce7b0a4c384e118dffcd6b7cc79ab81d7b49b84a2766744ca91efc092d9fc172a3c933d7d9fff411b8d9d7da174a7010ceb365c67cb03249d96f4e4779b783d9d0484d2bf563a561d0c28f76c626eb30c6359ca1eacaa3ea04a10e3cf4ffb1caf7a287855d5bb868960448d2d4ab2f4f", "d435648ff58e26d33390c65ca41bb8ecc59fd8cbff311cd58021296c7c5312479866473d3c175a7a86d381457b3c52687c29e1fb08e8c3fa5abde15076be79f7d99a6cd6b182de8ff7517a90eda918cce605b463ce9c19d7cb6582d4ddd01da6903056304220d21ed3e8a12ce465b9e1afac42b53a66306f0ed189170f7532554c55cc30bb3f54582661df9501d074a388f9f3357e4e", "-15fb0d6c3bfa78e8bc712c7fcb3d30fe0eb5155d1c690ccbb6dc15b32f84089255f3619e89fcd28f5911fb9938cca5235e7a6a995c1063f44130808b6eb0b2316d5a39a7672f582592b295490e1bad1a6bddfcbae3eace88b312bff851019f715de77cfe7c5faa2672114969089c78aa43f2308dc2596f6a4ab7373e1b35f36f65a92c1306d0a4bfaade73cf0ba390aa7d1ccc7e0ad9d", .None}, + {.Sub, "-76420af5b40797a747964ae2ef76aeeaefbcfe0c21ca8d67fde4fd38a08c2da17806174a64a462e11ab38097d9dbe855fb5d7a9acb7fef0b4b11dfae7128d2823511ece72afd73fd015ef9c9b050ab07fcaa3446f7849578dc9cf7f34ed6c0951cfb139c7c6aa338b8ce1ab08c45631e063372708f35c38de64f6ff31ea6da49ad142a425b9505885d8dbed966cf3dc6f3c07a9c704", "35b8e99824095188dbd1081677a19bd1fba3fc6aef8838239fe7e9267fa536326b5187e2ce054c026969841d79f578dd9f251063baa7bca7d2ae75bb7a49a75b2832d902bf49f5e4f0f6e86f8ec3641ebad4460f59b670673d5f6711667ea7466985b6e3cf7887771e22f6ff45d9929a6070da290e455886d16f8cf6c8e16b7cff13a447d809127482e94c43395d71089e3f11daea32", "-3d1d0a477f49cb03504a6cc4a69906c0aa9fcc4bb1a4e0fa1fc638fa09adf90c82d1e957744f92307b14bc26f7933762fedae80d675fbb98875f93b6615c34834b83f7d131f9cd24c10cd80c29c86ecf3a9ee953c92eb9becb2936909b6c134fbb55681d973f31aaa9afd8aa4e9de8cc40d411501738b4bfafd483f5facbd92199e4e6ebfdc262cd08c22830cfca64e50d7b1984b136", .None}, + {.Sub, "8fd68a7af4a3019fdfc37ab5850ec0e0f89b0d977614200b7dabf52125b690c2a4006af162f981cb0aa48fabdfb8548eaebfe7767c8ecd9b0e3563a6e64dd36103c03dbccf55afe7b32d7475481aa760b0abc6c39b8f223c31ecb63186c15fd93a4af088447917739071bcdb39a55c83625f227fdbfe137c0892e4de2e150a630c09640068bd60ae26e2fde2c7e28131226dc17dfb9", "2ce3737f5b8a491baa0990908c969157ee36b5a910917fdf012f00fa5af9dce3f732b5dc2de9fb8d327879cc21dd903fd492ed30ef91028c5e6d215734145fec4f18dbba1b61d7ebdc519175fe669da9fb50d6143405cc5de9a031722b24481673ca29473a164416559b76f003f98d0c22fdc6c00c25d478fbe125b2de0752d18340939c1ac56aabf115c029693860f344c9210c90fc", "-23e60ad7ac401901ac0d58e53445a549dead04cf99303dde495441a8489e73d7ccf2af2d17ba637081ce30d163e20af6e9a6eeb987c815b2ad89cb1cc5af82b63edcd7de4e6c7ced611eba2ea9e4f333f04619a7fa4cda3a2681660f12b83218e0257a3eb5ceb29f1c945b22505f3743ecd7d4980e65f3413b57f764fb26022b527ffd5c143994a10ea7904b3cba38e032a244f4b143", .None}, + {.Sub, "3528065a240495671812be950bff304c014a8f7c32f03b229148ec8b9aa1f764fe41b77cc9a8d854e09954c39552dd0545512160f28eb6311f20e39cc0ebbb94a9b777fb292b212e45eae514f5d73eb704f9e2a06ce24911fe298141bf9381864e79618ae9da05fa45ef79e629da413eecd25faaf16970eaafbabb01eac5ffa2e9d200bce1aac75088b1657b1fde63372f1128958506", "6cdec2d3baccb013558e5564dd6c99e159e96b10b3f927c3f63ce0556f0a3d0df4382f6bfb32614a024b7458385d5adae88f28c3200f8bc3528d71912f3c8eb6033f02181e90c496f5e62b49d9aa14e7f712c0f54a8ae626bf7c2aef105ef56b35d0bc242fbd2238446b2248deab72d1adca32539dfc58abee61914b5bb81dab44fe4fdfb554e9f136352c857dc9e57f61153f914d9a", "-37b6bc7996c81aac3d7b96cfd16d6995589edb948108eca164f3f3c9d46845a8f5f677ef318988f521b21f94a30a7dd5a33e07622d80d592336c8df46e50d32159878a1cf565a368affb4634e3d2d630f218de54dda89d14c152a9ad50cb73e4e7575a9945e31c3dfe7ba862b4d13192c0f7d2a8ac92e7c13ea6d64970f21e085b2c4f22d3aa22a0ad83c70a5deb8248320416fbc894", .None}, + {.Sub, "6e58eb2f7480dce811af72eb71dd10cb491506228ab9fbce30119b04b230c9a661096479664c23d5c8c0a07b668805c33ec7445dc069872528187dc136f67c201a2ac047a118e68137ed0f32829118a039ab825f56493e047a4397dc2b6c6eb1a92800f7e2b201779f2302da7a899be24ed0a56a065a52a3a3196ed8432387df67ff3f586f32f667b1622b7054ce27328f05810ea1ad", "645820c387e9f4961d63e78fce313a1141c0d6020f20464bf89a38b78598666dbb0f903346ff17363783fc506d6445dea84aefc6f73c7c337f9ab37b71be925647a19d2ffb2714ad987637223db74a34d3866a43b5b9f3ae91e4d07d4a8c9164243d3d0594ca573e58a97a24b8bda4cf07aed4e05b370431d195b5b3b43966a48a3072541fcbdb26b55b7f923fc23d8b0bb023d4cceb", "a00ca6bec96e851f44b8b5ba3abd6ba075430207b99b5823777624d2c986338a5f9d4461f4d0c9f913ca42af923bfe4967c5496c92d0af1a87dca45c537e9c9d2892317a5f1d1d39f76d81044d9ce6b6625181ba08f4a55e85ec75ee0dfdd4d84eac3f24de7aa39467988b5c1cbf7134721d089ab234e71d183b9248eea213addcecd044f671b40fc06abde150be9a783555d39d4c2", .None}, + {.Sub, "26749906f4306325de45d63b6def89cd9f7eb2717c7dbe285bdacd5973702baccc92d71a813548cf5dc5f9cd3e42fe344dc4fda371fce720cecea071fd43c453d1d6f231fdeea079c23dbc14ef3c49a4fdee718c2ecfe4e22a59b668a6b64ed61a8aae056e7e6f34e3b375386ac49519230949618c550410ba906509ffadc64215b936862ba5052f44dde9caa6f1cb32de1ae9d90036", "78d54d5105d7b8ca5433c2de9ae39e6bd0edf404a07d030e4d4f037a6c2ac64171a17bfada3e35f8170808f1749bf65c68911d3c4e5e04b2da264e5e273eb1f4a23f2eb32344b7e275de9b2a0744191ed75f418d516fe69eaacdac91f628779d2ea6bf882b33ddd6702510607589dec5bb8b459359a81239adf76187e6b843b07f9c4a228018b1cf6faedf7765088842495a4acfc858", "-5260b44a11a755a475edeca32cf4149e316f419323ff44e5f1743620f8ba9a94a50ea4e05908ed28b9420f243658f8281acc1f98dc611d920b57adec29faeda0d0683c8125561768b3a0df151807cf79d970d00122a001bc8073f6294f7228c7141c1182bcb56ea18c719b280ac549ac9881fc31cd530e28f366fc7de70a7d6e69e3139c5473aca02ad0f5acbe16bd0f6b3f60f6c822", .None}, + {.Sub, "9a1a57f8120924f2806ada27acb696a3d77e3c9fbe1709defd812090126a7938e4259e1d9da6e314cb12d2462177f28e94f331907f297678195033e60712ea5e5ac1f3c06ac2915a42741da3a267b8b6c1e1b83db2a5f0dc57dbf1945523fd69ac058b0e85a330f041ffe6ff0739f60cb861eb51a29b4f159a61ffc3c00709eab505fe7f51fbfbc1c3d6c8f5f151a44d842588d206ef", "9dbc18c2bcf848f7880db048bb791273fac685438e596800012dcecafb0497fde9376bac4f18fc6d6fc04ac09a3867f87636e8d697bdf7acab4734eef5fff4449b328ec0bd76ca6b7fcf59f9a9ed7fabefaa2c0d4584431e186e1df5b15ff159c601328bcdf4489962be3e344b6343b3f2e991de15c65c577108b2523347d9677de27b2dd95c39cf677db350772cf0fc3c75e1af3be5", "-3a1c0caaaef240507a2d6210ec27bd0234848a3d0425e2103acae3ae89a1ec50511cd8eb1721958a4ad787a78c07569e143b7461894813491f70108eeed09e640709b0052b439113d5b3c560785c6f52dc873cf92de5241c0922c615c3bf3f019fba77d485117a920be573544294da73a87a68c732b0d41d6a6b28e7340cf7cc8dc7cae87603e0da3a6ea5a85db4caeb85058dd34f6", .None}, + {.Sub, "-fc4fa78b992cd2b3e0afc9c5062999e15420063fab875b30f76bbb7c9c945349ac4484e1ee391ed14b45df61369366f21a45fd93ad35eda851fafa5a96018420cbf549dbf583b9c6ed415e101a2336974ab4833e9d80bec3524013dfb5ca5f56a147eeba784306588279b30fcffef8215abe63563634986f6c5b0d49abce614a340028ebfcd57677fea9b61cd8b2be0e3568556df64f", "a6d8fbbf17c942d2e009c2825289ec282cf6da2d34d6781f018a554d6cacc21c4886640606c6dc1079fb576209b8590e486c688455ef05d585a9fd513fa1e9b24b1e20f1c131783d6702aa935746a1f62b99080fd2d7208cbbf3bb9f0b6579cac5e4364f1d271b1fade9776be31c172444ee7ed70217a4f9457a3d3c002232797fab599650ceb041d99d80e5d39076b0c976380f15c", "-106bd37478aa966e10eb065ed2b5238a3d6ef73e27ed4c2b2e78460d1735f1f6b70cceb224ea58c9252e594d7572eec82feccc41bf294de05aa559a2fa9fba2bbf0a72beb1196d14ac3b188b94f97a0b6ad6e13bf9aae30cc1dff4f99a680b6f34da6321f6a15780a7d584a868e30b9939f0d4b43a65612bf00b2b11d6bd08471cbfade8561e2617c1c438e2b35ebc57941ffb8eee7ab", .None}, + {.Sub, "382d0a0dbf5e21aaccb9bab50fe300f86dd6ee85e888a275502276d3a1fbfdd10e037bc874ed2be54a15e948893de0e7e9d1674b2b53706f3b6735c7fdca9f099927d1dce120550bfc8e262a8517534842f8eea053424feaa2fca7b93ee5f76d1e55d7cee871370e502606c25a6852af5f88aecebbf5f68b262996c82de861c1b32d9879741814e2b9f610d30b1819dd7193807c0838", "a04ef06e3011e04ba2c76b05da7ad1c0663d4e049e6a82ee7b2e15ab56750599ac5b17844beb3319ef3d7a06b617f92393866fd745c7b48f89f06064764997010dc32e4230730869ab9295a4afa00f42a4cb47f78d30bd419ceaabdc31a480fc3e8ee44c5f96d4793403889f4c3bb5296671f066e2733948cd93dd13838670e72377f02d2fe9e61abafe67aa1661029e3022190645b5", "-6821e66070b3bea0d60db050ca97d0c7f8665f7eb5e1e0792b0b9ed7b47907c89e579bbbd6fe0734a52790be2cda183ba9b5088c1a7444204e892a9c787ef7f7749b5c654f52b35daf046f7a2a88bbfa61d2595739ee6d56f9ee0422f2be898f20390c7d77259d6ae3dd81dcf1d3627a06e94198267d42bda76a464b559e0f25704a57b3bbd1d138010856d70b48e8c0be8e988a3d7d", .None}, + {.Sub, "-d623564c831b411fcad4077315d0db1462c0534802983add2440025a98353c012702267c54783d79cc22ff229f1d82ceca5651cc232b6d64a5264ba56ae45f21fa28aa7e2bde531941a34310527954400af484ce11c6fe246a750248a6bf204fb2b9d9c9aee7d2352a32289a7f2bc743c5d54005ba9613e40b4b2c3105913c29b03984486727dd26b4c7c1e7779a01685027b4c1119", "475428c868a4b9e0aa13dbcb451e6da057c203b0b2c025ddfdd40a7314d9f5064a939dc7cccbd26479cc12ec99cd087607600572a5df27c83e624c0cba4e3e5a8df4b33a44a529e049736d0b77a5b4b3b9a1c5d27ef3754011d057f219ba7da0d961cab60b6fb473d7bc3a9530431f6add62577c33834dc885363cf3ac7b46a4c58392a118fa6f11414e64cbb3c9a74bc4e61a67fff8", "-54b65e2d30d66df2a6c11c42767b7b519dee08e532e9a98bd0180a98be5d48c65d03c02f9213563c168e42dec3bee0a2f4056a8f6811de9e88b4b0c710fc844cad973de227630f11dd8da13c7ccd49f7ba510e1f600fe5225877a816a4266fa5d48d6852a65e31972a5f5d1ed835dbdf19bfab7c8f2caf06c5eaefb6bcd45a6760872ae59f6cece3ac9ae0ea2b43476249e895b41111", .None}, + {.Sub, "bcf0687e22f4d1f21756f3878179968188ff520f8d3bf15e40cd47efe9ffe57e7ecdb1859696dace056d24286d7211af595e171d0740c5420a342823eede71ba8c488e9bcd9258b4c4192b1dee34d01b214cae030f3127265452d5fb43259f591cc77662fb5a45fb8dcf9de0762ae47db84af36069e3b011a9c3c9b3dc821248e547eaec50f69244678105f015cfbaaada2906639b3f", "fd65908645f5ca5eb8c385dd5bf9e380eeadbbe230d8feb42dbcafd51e56cbbe75307e78bd89f200bcebef42fc0835d28841fd6005612a7ebb79dbcf62b9efe22abcb81bd210c92c949517ba1178cc7cc787dd9b19f7102d9695b02e277fb64444b15f2b11c25e6666528e245a3f6f570df87abf81da2f0cf78b2924a08eefa9381f5c51b79cffb52a74f0edacc4860ab36fcbbd24a7", "-407528082300f86ca16c9255da804cff65ae69d2a39d0d55ecef67e53456e63ff662ccf326f31732b77ecb1a8e9624232ee3e642fe20653cb145b3ab73db7e279e742980047e7077d07bec9c2343fc61a63b2f980ac5e9074242da32e45a16eb27e9e8c81668186ad882f043e4148ad955ad875f17f67efb4dc75f70c40cdd6052d7716566a66d70c2f3eafd96f4cb5fd946c5598968", .None}, + {.Sub, "-10f0bbb6d01a355b5d85339b0c96ff7fc8432783941b23571601a9b1da2d6986ef333a37983f63ebb96a933ef9987441a6e7fbe89237b7017e288ed3f94988cd02de71234d7ed1e01a6219093d77e5daa6400daf49509745e01abe99e4cac69bacd3f6799983c1ee052c99d3756023d8d05a49d738f21ccabafdcc3a94b3133fdb43b22aa6fed84b665a9719a3fcbae59c342642c085", "6d52150290e1086679acea555a8fc57d6dd8c4b59fe31797f2bf8c2729be46449a853b5625ed4ad947facf342dfcbf280f482289bd36af4db2dbed5e7e19e825131afd05449974c61832179a19cd05c6979a9cabfe9ba8bb15bf228f13d0dfa03b5804579a609e920b0f451e9dce765799e21b5f23a661150820ec8fe3fce3fbabc5bdb1416b8bdad32c543766f3171245de6f126cf6", "-7e42d0b960fb3dc1d7321df06726c4fd361bec3933fe3aef08c135d903ebafcb89b8758dbe2caec50165627327953369b6301e724f6e664f31047c32776370f215f96e28921846a6329430a35744eba13ddaaa5b47ec4000f5d9e128f89ba63be82bfad133e46080103bdef2132e9a306a3c65365c987ddfc31eb8ca78aff73b87096fdbe86a64263986eb510aefd1f7e21295552d7b", .None}, + {.Sub, "2a695155f3ea5d1af348064d4538076e3e8ba68d584a48756490804c0e3148ea155becf116617b32579dbc1350ce1940f4ddb80d7f7ed84f6963e62a675a2b699a8fdbf6e4f6d0788c27f15b79b43f1eaee2ebd7129a3fc0ba24a66f619eed24c18951dfa28603c332399bdfd1c2d9b04ede4f52675ef4342da2f466e9f36291212688f3f5588f17246c6e71749c756e32ea128d048e", "eb28982ecf3d508a002a0937884ddec326085abf00ace79f1910b6df7af3ded1e3e0a5b080759eee23db8e989d40abbe5c88f4a5c68dd9249e02981880f70bb745d4667196f74a4ee9a7186bf2102203f7dfb73fbfe830bacc09d48ed058b26b83912bb8621cab85cf337465b813194f0b49a6ff7ecc90b42c343ff680c151273700bda0b912d8e9c72504b272fcde8a0eb9be67ae6", "1bb6c7d306f68812534565b9ccb329820c2b20e1683f79fb72ff74de16820afcf71de2960e5a214375600329c6fa0e850f1528c32315fabd1f83bca8df4abaae2632958fcb875bd39d8d7fd4ba933cfe6f64f063169bbcb50d640926749961fe09503f241c64390ad54664997641a81b5e29b4e26f722b28eadfb06781e74d7eadb67d19e9c7618887fa1e264d6ca78591fe76a689a8", .None}, + {.Sub, "c884450ef0decd497a60a7018c566afd54547830b9af664dc457e94dd164742e72f5c3a9caedd8571b157989c73a64ccd8138008e90c5c0a2c2fbaa0c7435fd23f3f9cda272416408b9796162f2864e12b714d6a94008cd3048e70687d9095523a92b606ad6d800201b973a5932d5d873b34af896011f013e47726465ebdd89dfb0a6c61e44c38b94e15778a2fe248d0e149403814a6", "3cfc2b6146ac72f99cc8e63520cba7e7f9ff3d5dc092040ea05dc6deb363b990339ab43238192cd3bb694ccdc4e27256ee130dce2373435fcfa38afcca9a7038aa9436c3779adec2d4dfe7532a76056e5abc34786ed8669d6b4c43fa0be453f529e51d9ed650523a0e95fab88de403b719dedd1e90acfa7d551cec2ee7c03c69f039fce1944d34624a761639dcade1972d93b7fe60fd", "8b8819adaa325a4fdd97c0cc6b8ac3155a553ad2f91d623f23fa226f1e00ba9e3f5b0f7792d4ab835fac2cbc0257f275ea00723ac59918aa5c8c2fa3fca8ef9994ab6616af89377db6b7aec304b25f72d0b518f22528263599422c6e71ac415d10ad9867d71d2dc7f32378ed054959d02155d26acf64f5968f5a3a1776fd9c340ad06f804fff0457039f615053346739b3b58839b3a9", .None}, + {.Sub, "-8a5aabfce8aa134a984deffa272624d207c62763d3e191bed600570d3e921277f20b111c21aa7c83d7f9455a5a6b315a1f6197fb455e696bf6c6ddb55a1b3abf66bea966b17032b76899e86ff67d1af6bc412fa43870a19f7aa95ce25e9c8b488f7582018ddc7c3300e3680d4b341eb7c87c0ff250ddbb94c3e48bb53a094532bb3ad52f11e4f836939fb278c1f9adea143010eb570f", "b36b4f462f828c065af00803f8a2c0b6c023838529d25021f14243c0f569674fd4f896574907a1dd072776c570252264926b3b03c7d9600a5d6428f49d4c27530a1896e5451357f0e0f92e1ba15b93d819cfe4471a5f5002e5a997c82ed23219bdd61f96933c094657b6a44c38b1680255c7c526a4addcf6ca2c5689e2c02d9a334a61f3711ee21b2cf0292517260ffec5ce0b3b042a", "-13dc5fb43182c9f50f33df7fe1fc8e588c7e9aae8fdb3e1e0c7429ace33fb79c7c703a7736ab21e60df20bc1fca9053beb1ccd2ff0d37c976542b06a9f767621270d7404bf6838aa84993168b97d8aeced61113eb52cff1a26052f4aa8d6ebd624d4ba19821188579589a0c5983e586ba1e43d518f58b988b8e10e23f1cc972ccee8537228303da51c08fdb9dd91fbde8d9fe1c265b39", .None}, + {.Sub, "de3708357ef2429d26bc698a8f7df5b73ee74298c945ab5690e417ccb5df6c931ba88b7421bf09d7b80df2b51976a4586588be445b78d210bcdca247e1a4db8f5bcccff478471a3a973221481ac7ff14d88621f736aa2aece879e2df95fa30b32da7a25df99aa737278ac2e0f49e6542eb5f02e5c8b612456b345b548ee5fe62ae21d5d933d031e200bc01c11b50fc9311ab532eb6fe", "fd3c9d7fa222070833ec30284f9b27dffa80b10829bfda55ea0b831ca52348c0c6c8a3b7d6c99954834c9c67e54e094f14e7cad26151d8a26067dce5ffb19205e1a198a3dafd9f00076f2744bfcd767c9b9e86d9204ba06626c00a493cccc13d320b3908e260245d9acd49d8bb547e454bfac7bebc65c4d76c5efe1ee3ecb1ba74f76a0c93edca98ddd1facccd7aa68a08003f879f6b", "-1f05954a232fc46b0d2fc69dc01d3228bb996e6f607a2eff59276b4fef43dc2dab201843b50a8f7ccb3ea9b2cbd764f6af5f0c8e05d90691a38b3a9e1e0cb67685d4c8af62b684c5703d05fca5057767c31864e1e9a175793e462769a6d2908a046396aae8c57d26734286f7c6b61902609bc4d8f3afb292012aa2ca5506b357c6d59433601d98b6dd15f90bb229a9f6f654ec58e86d", .None}, + {.Sub, "-f2df752352d603e97131d44a11cf8f639f345e41267d94d2d057eaba0d72385ca0854aa2d05b44fe47db490fd19a3237f250167d1897d4ee4e5bb1a01b61395849cd9801f830b260d2276915a9324169c3140fb110c166b3f1b31baf394bbbc1d5384489235f1a8721659f50542c920b21ab9b0b1934f4e0fe7af997887d82cc830f876f8a2210361a88062461de52da5074964e4e0a", "bf89386867f8de20db9d54c606da324fbe7ba97e292ecfd9268bbb9f5ce2219c1dc787739cf71b73d641c4fb60de0f2ecf0851d57b9a6b5a761fd13dd43dbc3a35859a40f52ee804674a55b9fd3182b47ef2e07134b2a419ce0ff97e46d82477a0259987dd1311ef62f62447ddd2d8f956d6d531fb5c40572d4482a3b9e83c7609f030113ac039a9cd50a891f7e77754269faf4d0cb3", "-1b268ad8bbacee20a4ccf291018a9c1b35db007bf4fac64abf6e3a6596a5459f8be4cd2166d5260721e1d0e0b32784166c158685294324048c47b82ddef9ef5927f533242ed5f9a653971becfa663c41e4206f02245740acdbfc3152d8023e039755dde1100722c76845bc39831ff6b047882703d149135382bbf7c3b4265bf428cffb780c4e249dfe7d8aeb659c5ca2e7714459b5abd", .None}, + {.Sub, "1ea5621dbbb390ebd94447836c7e748674b6460feec2341240971487cac430829850b046533059ad0ec74d74c6c1863164d0b091bbf6774083817d70724b53dbb0d0a92b151a5402cd9d6dffab3ab27787d8b438871ebef4e7c4d8cc68482821d52af15cbe7b294670ab8746b3be773a659a49d9e6e27c096f13afdb12e4c072b57e0e572812ac0a133e8f113bebda18f6261bac85d5", "1ef6246bda7db653749d4f1d38edf29d1399ec143e50e7e6abd3dcc4423b958d15d86b075a808f7b738665c7913dc7c9dd77233660d50bdf12a16cdf8c6602da00c9bb668de24ee778b0d0b322f1adb653cb5b616bcde06ef3130c222cebdfa0ff28cd868b78287cace1973e5acd56734d474470e1c213aadfa71ada847b7ac4281130228edfa31c6056149a645c6896499b4d79dad6", "-50c24e1eca25679b590799cc6f7e169ee3a6044f8eb3d46b3cc83c7777650a7d87bac1075035ce64bf1852ca7c419878a672a4a4de949e8f1fef6f1a1aaefe4ff9123b78c7fae4ab1362b377b6fb3ecbf2a728e4af217a0b4e3355c4a3b77f29fddc29ccfcff363c360ff7a70edf38e7acfa96fadf97a170936aff7196ba51729321cb66ccf7124d17858928708e7d537531cd5501", .None}, + {.Sub, "52dfb418cb86ac4213ba118dbebe1216e65ea5d4d17a122b72b30eaedb62f30f03e89169ae51d893fb2a757dcae15c22090176bc63eaeec4464afb3269cf33add41a3744ab36f70bb83138855ce4fc60c3374acfcd7906c4c180995836066fa6083b22ddf9dc1073e2f7261a8a166a7129cb9d7a8021eb75191ee2d4e83542fa2703e2933797453d991e3e8eaa0b220c0e0916f71b90", "54d7d211c915b59343c2acad571e30aca97373edabb8b120d77ea71ce6d52ad185c4517d8376e3592d1daedbbc9509d6b0703283bf4ca004e2a31140fc119f8f6ea4afd09be063bbf30eef2644d9d5dd33e2777be9e56a850062fe663e993dc004243559bdfa673d9b0a50eb926a97517e29681922e5e90123eb07a328b3731ef5c8df04258b86758ddbda435a5a0ea689d744cc41d2", "-1f81df8fd8f095130089b1f98601e95c314ce18da3e9ef564cb986e0b7237c281dbc013d5250ac531f3395df1b3adb4a76ebbc75b61b1409c58160e92426be19a8a788bf0a96cb03addb6a0e7f4d97c70ab2cac1c6c63c03ee2650e0892ce19fbe9127bc41e56c9b8132ad108542ce0545dca9ea2c3fd8c0acc24ce407e3024cec4fc70edf44137f4bd9bb4b04eec9a7bce2dd52642", .None}, + {.Sub, "eaff7c24402b425e36cdb7ec8491a87e1d558d0a827c3204de86dca10579d878958f4b096fd48b01d14d06d0793c47adf7e8811d6ff1d8d52e6f0df05f608967c40bc6fc7b2db9b25388c98253a3b15bfbd1cb28616d9086efcc5c3cd54c57b6b3fb707cd125eac36719b4b6a06514892573ef8f0cd17b644d030cdbbc57f61ff3740e5f630e1c12f2743668315352fa906dfb2a6dea", "2095596d8b2cbb1491a99c7288d1adecb56c0d6face9a67757e90557a7e561431545339e74f534b333742825eb37008561c51ef51f162a27fefe2d15d4044802171722173d6b8197210cfe94a838a9e32d781743a1c1a9524f9cc44df012534db852ff0c07cab45d943e5bc2f71498c05d717b89918b9138d926e2ec6a0c9fe0a8512a07d01b54544027506b25e990e2f8348d72fc2a", "ca6a22b6b4fe8749a5241b79fbbffa9167e97f9ad5928b8d869dd7495d947735804a176afadf564e9dd8deaa8e0547289623622850dbaead2f70e0da8b5c4165acf4a4e53dc2381b327bcaedab6b0778ce59b3e4bfabe734a02f97eee53a0468fba87170c95b3665d2db58f3a9507bc8c80274057b45ea2b73dc29ef524b563f4b22e45792f2c7beb24ce5fd0b69c21798396db771c0", .None}, + {.Sub, "-c2908c701ee67d5877befd1dc3f307df291a2c2b28f3ad1520297ccb1e423db7fbc67416c77ee2e23f44aa35f96746f65be859195036bc4e4716562347bc5e9e437838122fc1d0f18977dbdb3e47e9b21f20184c5d6151d1b4357cb1f369f9e8a0a344c3d419c4ade75ebf1f162cd8e4f49128165d144e3f8f46d27ef17d791ae3bef60d9626a31787925be0d426d314a22c7104f6b4", "19cf33278b2a6d977c1728d1299b25776a3f8ccec345e42b226f6a8e9a263dbb1f5f6a55955e5a16396c1e053f615e163cac1bb437152f41d9df2be34cd02f3d71c16a6e06b8661603e5010ff0fa84d7effe46f8c4aa50a0c8aa931af8f3880ca558a37554953a0a95987ff08c560443301332a78fba95ba8d05336e45d4d93d8c55a53ab8c3c3c6160ecf2102d3bc9008bd7a0a3635", "-dc5fbf97aa10eaeff3d625eeed8e2d569359b8f9ec3991404298e759b8687b731b25de6c5cdd3cf878b0c83b38c8a50c989474cd874beb9020f58206948c8ddbb539a280367a37078d5cdceb2f426e8a0f1e5f45220ba2727ce00fccec5d81f545fbe83928aefeb87cf73f0fa282dd2824a45abdeccee3fa1c4c05ed3752525870149b484eea66dd9da12b01d6fa8fa4aae9eb0f2ce9", .None}, + {.Sub, "-8434216e66c80baf1a3e99b0e5160fdac1ea6383843d3444c57ad2fa01eb094b12515e8c61eedef56ad2915ec9cc6cf90cc4f002b4adc80636c61cf8ec2ffbf58944bb412041671cf6edc66bb295bcee0bf55b743e9fff2cd84be90bc40c172d61841a555379226a89b2fbc545f32d150ade33d7381599e2a70d8a8b0467dcded348d3d32e4961efec915d2a8d07e5c9495f35e56a46", "d0293c89c3616542f73061e2d2a44431e4384e2b908416ad3fce51686ea0027f5588f53360b9b40342d30ac2301116841aa1f060c7a638b77fc0361168c1d22f78415ddb1acae72d762e482000a3c1f7437bd334af6d930736a1a69b8a698afd9e8cba1366bf15f37683dd01ce17275b4a215324e9e4348ec57bb2ceaa1a524196e1f9355185e93991860ba3c6689295f49976dd58d8", "-1545d5df82a2970f2116efb93b7ba540ca622b1af14c14af205492462708b0bca67da53bfc2a892f8ada59c20f9dd837d2766e0637c5400bdb686530a54f1ce250186191c3b0c4e4a6d1c0e8bb3397ee54f712ea8ee0d92340eed8fa74e75a22b0010d468ba38385e0036d8c7140a547054ff86fc21f9ce716c893d59ae822f206a2acd087fcf4b297e1768ce5370785f3df8acc2c31e", .None}, + {.Sub, "-234fa1df97b2f8d3a4773556465e40c107d4b43e4158dab69fb0beb6141a75cab3d167b67cb08b11b7e27015cc1a924583e985ef00da8896387e7e7f9a40ef14095ae5342ec3a1e1a8be5b15d6a700f5d5ca540daa21a7dde24987344367970e5239dd24a6e42ebaeb22634586dac6c72bc2157fddee83427861a4e11f2df23a2944a3462cd5d9c490d902b7e6284b5a8a2910bded45", "5e5204a51dbe99246506bfacc63f46efd99539ba0536db2d4c1bea0469221c6e5908a21e2ab94f5eaa766704b16ee9e482a51fa173c0028dacb8fea5355cf6e216c26b80f7398480eb41027a5d64bf420b81222122be24e354d9506cf7f4b83c43dfc841d9105d78f21ca6db8cd9cab1fb7293def80102c0e70a84580c3994572c869ab635ce4360c3fedb26e2cdf4fcf9de6b98e641", "-81a1a684b57191f8097df5030c9d87b0e169edf8468fb5e3ebcca8ba7d3c92390cda09d4a769da706258d71a7d897c2a068ea590749a8b23e5377d24cf9de5f6201d50b525fd266293ff5d90340bc037e14b762eccdfccc13722d7a13b5c4f4a9619a5667ff48c33dd3f0a2113b491792734a95ed5ef86035f6c29392b67869155cb3dfc62a41d2554d7dddec8f6405784077c56d386", .None}, + {.Sub, "434a180317b9bf7ab4998ed663085db690916fd95a13dd10b716007c713830ee2e3822e0be30f790381b3cb622dcbbdf2fc1dc5d6a304403eb2acfb9faa9a34e7436b2f2d3d26a7ac83714e6eff56f4b12596ae375b0a04f2fcf2fbd91ffd093065e75e9277ba20999cc912a8c93fc3dc0da02e16a4dc8fe31109a1e396478573f271fc7e6cdf0aa71072629e007f88903617d45d1fc", "8eddd0becada60daf23034767ecd147f5bd07b88c64889263109e37b429bb3a03fe38c88dad0ee7dd352697802e4d5d2dd3e575730675c2b69a9d79092d1fa4465b3d964d407399e2dbd90d8ee2c95e858863db05d0422fc7aa0189f580b6e287ba798c620946921918791c910344cd118721e4813c992975ccb5f0545666db71d9d19bb65af28732dad833667fb942a55f6449cd6cc", "-4b93b8bbb320a1603d96a5a01bc4b6c8cb3f0baf6c34ac1579f3e2fed16382b211ab69a81c9ff6ed9b372cc1e00819f3ad7c7af9c63718277e7f07d6982856f5f17d26720034cf2365867bf1fe37269d462cd2cce75382ad4ad0e8e1c60b9d95754922dcf918c717f7bb009e83a0509357981b66a97bc9992bbac4e70c01f55fde75f9f37ee137c8bca65d0c87f39ba15294c75704d0", .None}, + {.Sub, "-94bf80941c773ba26910763699df63350d7efc1f6e55ef0e8bce4e36a01f23bab76e6e899a46eac4aa8654bd384496290033e61e09f5792114564d6821c3a572977072e3faeb6493931d756af84f4fe7701aef815674dbb4877b2d5abe9c0a9904f9f75233c2988418632fe8b6c70fa0bac22dfad478f9bfab69e2142d7021e8b904ca1c5a893f4df844cd31bbfa76e9daf5facab592", "2229a50d2868a645ea4af705b7a4ee6fe9230214bfa7b482e05fe56435d5ce066eea0b28312afa10f8a954f89fc0185f838a93eac290a8687dc38360c636c8014084dda3bac636eee057ee7962249aee093f31128184ef86b44ed160b0b5526fce56a71e125d7bcd8d6d0dbadee96d15d7cc712e0be33c0658da242b406e06092d4dd60f586e859fc33ab5ad85ac8308b19b335ecfd8", "-b6e925a144dfe1e8535b6d3c518451a4f6a1fe342dfda3916c2e339ad5f4f1c1265879b1cb71e4d5a32fa9b5d804ae8883be7a08cc8621899219d0c8e7fa6d73d7f55087b5b19b82737563e45a73ead5795a2093d7f9cb3b3bc9febb6f515d08d3509e7046201451a5d03da395b07cb6928e9f28e05c35c60444063f6dde27f1e652a02bb2f7c4edbb7f82df41a6f9f28c912e29856a", .None}, + {.Sub, "e9e6d5fa55b2ce6a11a291e1fc1ea12334e190ceb0785f44bd75759966c6d71325ef445a3571ff215cd4cd7bb37a45ffc2edcfd81e4759d2bf90eac7b6efb456e0514d101cc6eced0186372eeb77e41758f959edfcf40d02ee90638ac7daf5d9a00b1e6b256b8b7ae8d8787a75585893339ff5f0219fbf275dc3b47a7bb377feefd7290c04ddee25f93b118266ddc2a600a02ea9cf61", "3257ffacea6065acbca634a4d28cc1c7861727f63ddbcb57fb1bd37f353221b4b8a385bab79e0c974650386c73acfb2c8cd2c581d21a123d39f2d9c19a16b0ba01e1b38f04ba0c826b4f0f5e9ececc20e0f60b799da3e0fbe50e59fa9c42e8af245bcc374c887e1b8611fa131a400e6f71c42222a8f7644964bc59cc50979e73bc6f129085890ad2ade2a6e24037fb6357130b277993", "b78ed64d6b5268bd54fc5d3d2991df5baeca68d8729c93ecc259a21a3194b55e6d4bbe9f7dd3f28a1684950f3fcd4ad3361b0a564c2d4795859e11061cd9039cde6f9981180ce06a963727d04ca917f678034e745f502c07098209902b980d2a7baf5233d8e30d5f62c67e675b184a23c1dbd3cd78a85addf9075aae2b1bd98b3368167b7f54e3534b586aa026a5c742a98d238255ce", .None}, + {.Sub, "-bd8421cfa13e6c43266cc1554a14897bd68432b3ff3719c5929c088d1c3416d421df2c3d57c754fa2a37ddc4cb47dd7a98aefb7d4548b51b5876e378493f076af52a9811535e57f4f637f5c683277065103a737cb67e272fb7f909b3ec0f1aa3a7537911cd96fbeae3fe94ee215b9ea577188cfa0864d5c72f26dcfc3bc12160dc78a204cc2bd27bbb4813bea9cba250010ea932c264", "ad3c44791d61bd6f8e3399bfe1d2ccd7daf09bd5013a85edc5bb27e47d1f5c42436c82902f74ffd54264795bab6c7b0386ccff123c397ff09343a1a917edf72530c5c26eff3df09ceccdf4dd2ea9ea5003d8f6401d8331fc0178f26b6e6fa40c0852410a4ac925b17d3e67bb1f71036970f24a71b3014f2ba805852d54cd01c8662381da7052f1af614e1a54924f59dfc804365fb07c", "-16ac06648bea029b2b4a05b152be75653b174ce8900719fb35857307199537316654baecd873c54cf6c9c572076b4587e1f7bfa8f8182350bebba8521612cfe9025f05a80529c4891e305eaa3b1d15ab5141369bcd401592bb971fc1f5a7ebeafafa5ba1c1860219c613cfca940cca20ee80ad76bbb6624f2d72c6229908e2329429c23df3c7ec42b1c962e133c1afc2fc912df9272e0", .None}, + {.Sub, "-acb798cbf50532c8ade6e014770e41948b5b43018af8d9b604e470593260220c1a9c75939210858d0f844e107e4d9797df13603cd3882d086071a1a4512b6774a41a62308c3f6ee174193c44ef7e8453f58869dc5075a0c104f0911b6a55ecfc418575dd275ad1d1b15abb99c6268ab5a9af0c38ad56bc92dfc9928727bd1801fb99d9b3926692c52311d3ea4e43b53a4dc217d70a99", "2947eaaac8732df4c98acf14cf381b64b80dafc4fe39eef06e79c89e58474d052b3dd9df5a26454db70b19a6ce4fe6066b4ef8d2c1420a868a568b6830a05f1a3bd3a3d8207794b242087553f4a45ce692091568da72904b667669d27919f31ebcc4ee6e225bf40cb4ba0dbf0c76c78b84d21a75b166912b2aa6f5b8c36e9c4ce60ea638835411fb357900c82f60377827df9a4178f5", "-d5ff8376bd7860bd7771af2946465cf94368f2c68932c8a6735e38f78aa76f1145da4f72ec36cadac68f67b74c9d7d9e4a62590f94ca378eeac82d0c81cbc68edfee0608acb70393b621b198e422e13a87917f452ae8310c6b66faede36fe01afe4a644b49b6c5de6614c958d29d52412e8126ae5ebd4dbe0a70883feb2bb44ee1a87fec15baa4c0588ad4b27da3ecb275a1b218838e", .None}, + {.Sub, "9a57bf4e62ac450fb44e231a2195729ac200194fa3107ef4a7889e9a5d6050e1cf8136f3354ef551a6b6a70ccde850e5a2677fa492ebdcf2acdc92d0af8aa856ca06b42a0a297c47db0d77e2d1bae7c8b130f3761ef56fbb9d5a65edd5cc633ef43f281459f43ea9d3c280dc3e6d4c2bed8fcd7442f5231fd7dbf3e5bd9dcb7750ada7bedb8b72564a1bee1465dbe7be838ca54d96b3", "caf18626e0ae28d3c7fd0a9a5e2efbca7ad4b74f52c35e5158d0757d8507619c046836bc3daa109e7c476c055bbda4d74a537b087a5d42458821eea6c29b2fc28abade6a01a10ba6387dd4f8e0dd79558528e48c22e9ce98f5f62006ea43437cb643b890c1852e32e95c882da94068f489322b3890d10ce8cb4959dd27e99516a573ee3d842ab798be0a4798466f88ee082c33e54440", "-3099c6d87e01e3c413aee7803c99892fb8d49dffafb2df5cb147d6e327a710ba34e6ffc9085b1b4cd590c4f88dd553f1a7ebfb63e7716552db455bd61310876bc0b42a3ff7778f5e5d705d160f22918cd3f7f11603f45edd589bba191476e03dc204907c6790ef89159a07516ad31cc89ba25dc44ddbe9c8f36d65f76a4bc99f54c6467ea89f454273ee5983e093a12f849f8e97ad8d", .None}, + {.Sub, "ef2bc60446645de651fb8cb6c423a940e17f1cb6d5f07792f546391085e8502c2885e55bb0a4aecc553142b803c70c7e5326dff3eb3f21d80d5992783987c386ec13d3ca5b0c54a294ed01b3ef54b8f3de7ce0f31a13e06530d2511c8bd2765454fdf3c1bf552eb8e1b5bb99b0a5bd1ae685a574dc4325f4b279ed3f890d516e486ad915fdebc671e85d5cce8e31577497b2db79ff21", "e0439760bb00104942766bc250bad7ccc78c100af9a32a3be94a2ba0c3cbbb6d2099e9942e83a76441b162254f5a4c03c20d3ec8cf909f32393400eadd8e5456c412e1889d00721a3a1173ae327352ed4a07446b96092e93f5204a40ea105c638f0e378563b591ae58bd44488df5bdead5d8a220de583f6865feee6dcd62d6a6a91393788dfe25e498072a89d337afb402575ab0d5", "ee4b826ce5a95dd608b9164b01d2ee6914b790a6caf6d468b95ceee4e5248470bb654b721c762b24f0ef9155de77b2324f64d2b5226f9138db205e774eaa3532954fc0e8d26f54307ab2f040412245a0f132d9aeae7dd7369cdd30d24ae865f7f16ee58a39f17927335cfe556817c75cfbafccd2bb64cdb54a13ee511b3fee97a1c1c582855dc84c03c555a4045e1fc4e3b0841f4e4c", .None}, + {.Sub, "-ae02be8116bfd6b2ef911bbd8e9a2d7e7b98471ed847edc4b0a8319c3129d1950d4e13ee695593ab2c2369ed0cb2f5ca3b416b13dcff705df84f907b25c08431163450d552179d76253d3e0532c72e79609018345bc0e796641a9de8d28920aee04087a4127c76cedbeb8b72aef9733fb4e424449d745f1c2cc3943dc739b135673a152002109d5643de6287d0c8da985f7e45bda04a", "a66668e3d7cd63801cd5d37cb884922dbf3bf8340f25a8d2e8219e8f8961e68b048e0773cc8f7ce1c29cc90227d55ea6f5e9d509007a658e668cf8d06f64bb66c2075fdf9189702b9438bc207054b620c6e591802566a8c416e8d82eb1ddf0e6ff8831768de53a4574df39ac2f7c42164c5fb33aebace4820b6c861018631265ab08cb23d91e05019e2d44ea1efa5de841a3bc7baa79", "-154692764ee8d3a330c66ef3a471ebfac3ad43f52e76d969798c9d02bba8bb82011dc1b6235e5108ceec032ef34885471312b401cdd79d5ec5edc894b95253f97d83bb0b4e3a10da1b975fa25a31be49a2775a9b48127905a7b03761784671195dfc8b91aa061b11450cac51ede75b5560143d77f8921439e38301a4ddf9cc39b1242e043db2ea257e20ba771efc33880a12202394ac3", .None}, + {.Sub, "-10860195e30b93462a925609a7cbeeffd2a41c986ea7cb37fda7101848998e74692a09296dd218c262c397a1edffff0c5e42cb0d52526772115149bc9d1295273cb6a642b23ea58ac6d8dfab9735a21a3df910a0ea02f0643481d3c1aa54bb44311dfd62eb08185ea5741d907832ca7cdb7b506775763faacebbb7d41626112f1b1b85d10c3e62b9948ee5451ee3f94070c85790f01f", "d3e07b03ce63d3f0e69dc160dce51f7d09a5f5a415c45861c5d96d37a1fc4c06ea60493bdb420ffc1287c23165468b7dc822fa93eac9410caaaee9dc72baecf368b3a05394921a0c7822b04a777d8820152a451bd7defc5ccd2fa743ca4dfb14738d658530edd26c9282eb14229ba8b6d427fc720d226fbd8688024975784e40f7ec9da415335fb2223ac51bb082889fd91bdb0d1a38", "-e4667c99b16f67371130176a84b10e7cdc4a123c846c2399c3807d4fea95da7b538a5265491428be754b59d353468a8a2665c5a13d1ba87ebc0033990fcd821aa56a469646d0bf973efb8ff60eb32a3a532355bcc1e1ecc101b17b0574a2b658a4ab62e81bf5eacb37f708a49ace7333afa34cd98298af685543ba1d8b9e5f70130823752171c26bb6c9aa60cf6681e049e4329e0a57", .None}, + {.Sub, "-ef6072f469e5b0dbc7808efea0e715cc8c29a91a5ef206c35d28741cb04e1e088a4a2074e530256976f5a138b5f0d0e4b549ce3800a194a7995eb6b525952d347bf1534391d1e16888c3d98432bf65776f1e198110f61f78d79473a0f779dd4b0340c29e1eb138e5826289f86840cb16a8c57239758905a546851315ffcf2da4e1ba0687d5693c0b9710b8511c816b4b1b79892b3a4f", "24dbc75e373e2ad36a397b1e59a0b1dc071b5185481fe732e9836a3eda7edec956e838f4e6f907e729910b285f40ca36a0b7e5bda747b59f3e876f8f47490115d85091c1d8d6d0da3870b032fb8b0f2dbb6943c26a1f9feb5fc9740e85ea7295ee98c29cb204467292222f0b5fc9a247f83d78af41c6abcfb2af0467de6fdd49cfbaa94c61bececc2ff4014a704f18fea99808f5d77e", "-1143c3a52a123dbaf31ba0a1cfa87c7a89344fa9fa711edf646abde5b8accfcd1e1325969cc292d50a086ac6115319b1b5601b3f5a7e94a46d7e626446cde2e4a5441e5056aa8b242c13489b72e4a74a52a875d437b15bf64375de7af7d644fe0f1d9853ad0b57f581484b903c80a6d5ea102eae8b74fb174f934177dde3f0aeeb174afd437280ad7c704b99b8cd08449c511922111cd", .None}, + {.Sub, "d6f5d183b371ba08776812eccd7f73cb98fe81235e0e31816354e74bc37ef7e6e02f32be66d8fba30b20f1765ab6a08cc53e79f7ad6db94bddd006a3017c73ad2c512ddbc36eddda686c366389ed4e228c5c2f7476bb0fef919822f85a0dc439436e46a0e8757d6ada5d5c84781ec17039846ac3b8f746e896992ac63fc0bea5d75355539e387d1e0443bb62d336980d1168b8aaa982", "840356bc93152a20496261f2b6f8d5e409eca14b1fe0663ba38b3f6e675db75a86f1aebe63102a9bdf84e123c7def4bfbf6f5b4d2f58b905fdf7a2ca2cc47169732bc8cbf7a32731fb081fe20e0617a40306784f045445e611cb2122efe5e8c9996f4b9a9ab21a4c2a122c7d3fab10ad56e70138ac94845b66a2ff367382ad78c3886bdb3ecfff71b6ad9ecad0341788cee0655b636d", "52f27ac7205c8fe82e05b0fa16869de78f11dfd83e2dcb45bfc9a7dd5c21408c593d840003c8d1072b9c105292d7abcd05cf1eaa7e150045dfd863d8d4b80243b925650fcbcbb6a86d6416817be7367e8955b7257266ca097fcd01d56a27db6fa9fefb064dc3631eb04b30073873b0c2e29d698b0c62c28d2ff62b8fcc3e112d13cae9785f687dac4d961c98030280844288534f4615", .None}, + {.Sub, "cc9859534c70ce34798fc78992d8061146195af9d33bfd1b28dcc2daff60c098e8f214e52e85315af0cad448eaad05e09788b73ed13dfab1706524969962d024fa29de8f1c8c5771bd4af27c6e1ff9800e668cb0ef2363e0a54b35ff92de5d015444f0c510eb92153d4899c385e12107f11998dbf5ccfbdb475256623da1cc8f8c85b27071adac975c49b4c898f4a39766f8121948eb", "b18da8c45c893516f483c5afd80a2bd8a19c62357aca87dfc11529bab0c71e18db0b9fbf0010e50c533f8ffe936e7752b56cf4bc6960fc17752605b5487288b321c28d21dd592b758f811368f0feb837830f5dae97dfd271264a26b77fec3b6ee720e879df10f8547b28f7862867105b69d01f7ba616a709715ff4deec901db9aec2dcaf0567cff6d39409b0f6566c8e28f17f1819c7", "1b0ab08eefe7991d850c01d9bacdda38a47cf8c45871753b67c799204e99a2800de675262e744c4e9d8b444a573e8e8de21bc28267dcfe99fb3f1ee150f04771d867516d3f332bfc2dc9df137d2141488b572f025743916f7f010f4812f221926d24084b31da99c0c21fa23d5d7a10ac874979604fb654d1d5f261835111aed5ddc2d5c16c45dca088b5ab17a29e37093e0693012f24", .None}, + {.Sub, "-fc7ebb2b811d9d51879f00b92397c1f9ce59b44a501c318c21c689ac2db7c2077bdc271cc90f02e8d0d8fcc094bbe316e260070816248a16a0b7c72a765494a8f25da56d3358a890b13008a4ca4d67855a4a808101363c3ed34784d3756732c61ffa493739cf1d30f1bf1257ae80ed35b85ba8e87f89956988e57682946e2dd5fd73957c7b23917aefd82457e2cfb8efbf87a41bf595", "7b738f4d2482377ddf082750f8c9544d1befb57a173d5cb0283576b988751bc643c15cc8ac1f90693e9f8222dabc130bfcd390aa7368bf0ad39faf5db59cd1dd573974f48d09d32b29cab0be2fae7b185aad276ec2a1967362ad4d16ccf12c087ef1495e9ce2a9d699049b663596eadbb2bc7e0742305796b83782c9959eed5bcdb6cb47da0c0cb9beb02f338fc8e650fb6f91b5e527", "-177f24a78a59fd4cf66a7280a1c611646ea4969c467598e3c49fc0065b62cddcdbf9d83e5752e93520f787ee36f77f622df3397b2898d4921745776882bf1668649971a61c0627bbbdafab962f9fbe29db4f7a7efc3d7d2b235f4d1ea42585ece9eeb9295d6b1c7078ac3adbde417d8116b1826efc1b9ed00411cf94c2a0d1b31cb2a60c4552f9e34ae88538b72989f40baf735d1dabc", .None}, + {.Sub, "-12cc21e163507d82c84a9ff140ff64695423ae49ad657903ca9db1e06217a1e3348587eb7a125d962ae251ce152849f29af9465a1959dec4a60919d114bf301abe7944fab32319be76ee496308707fb9f4f0d84786e7164a873ca8ebc32ac9600aa52f01d43a3f9fcfd826d4fc543d331d0cb9a9093ceda8a11ec80f96698ae7b5c370d434f4e509ccbe54ef50dc6468a01b9a2b5dd4", "866cda704a03b081f9428460df2ce8a480d938ba95b42ed46597189c7ce33192e69c4e50541c60e68a883f296c1ef7ae5e22dcde09d12c3040a4bcd916f020f3287ed86babfef8d2ad0809da32636748f2e6f150ffffe730e12a9a6921bcf7ed7c9b7f4b0d066924f208dae4fa86a0e8e3c64ef7f5465b47ff6f16cfa661a34c4487d324ea37db06d8f33d02df770836f64d7777060d", "-9938fc51ad542e04c18d2452202c4d0dd4fce7044319a7d83034ca7cdefad3761b21d63bce2ebe7cb56a90f7814741a0f91c2338232b0af4e6add6aa2baf510de6f81d665f22129123f6533d3ad3e702e7d7c99886e6fd7b68674354e4e7c14d8740ae4ce140a8c4c1e101b9f6dade1c00d308a0fe8348f0a08ddedf3ccb2e33fa4b43f91f2cc010a5b191f230536c9f966911a263e1", .None}, + {.Sub, "-99ce546d73ed837414b1099e2efc2f3a49db2fa0130b3fa955cd58c5fbdf8b9775263b8f53a4384bb9df93a11b06d09ade79d2747a965eb467336437755d9682d177fef131f766b55bd2698310e8b976a4f43e688d8831e0e351a87e064b03e5221f47a475aee4e83445893d21a7b762d8d1304398e60ed687266349282fa918e411f2d718a990dca87e4cc202b951fbc725a3e211c", "7ec8cc36f4c6452bf197eefa576eb18691ed76e2ef1ab44f7df961b7c25bb78ae746b81bb45d5b37be4a27ca0d05457facbaeab4386e3400f5ec3194702f880520d335520c82deb0af6b010fc3612df1daa5a70410985d449d1d187945599aa55c886555bc198ef7e025588d2eb74c351705488aedf3b3ad9e050826cb96b60f26201c08841398e290d857fcf78b5fbedb4244341481", "-8865b17dcc051d6332e2ff943a5e747a368b29dcf04b684a135637442219b0445e991bd4a9979ebc79e821041eb5b2895aa287db801799ec3c5f67d7e785616d4deab5411fa2551c052827a7f46fb98944f4eaea9970e062ab52330125be4ae3aeaa59d003747d466369b12100d1c7ab44925b8f2782149b06776e5b5e19b0a0b4613b35f59e31f05b603cc917b6f4de97b49e72359d", .None}, + {.Sub, "9924e733470eb7235edde8a1428cac3da08f3edc92a4a78ec101dfe719726b40def5606d6aefe72f9296112b8f27cfeba0f3141fe244ea396e03e4ac7b609fee4a724d9dbb2817eed5e980decba83ac402d4ec9198adbff67a9dbd276bf344fd7307ac0750b90f534eed473a75b133a710b105dcbe5f1994cb225fe72fb71620566f5c63bd37de85371e8aa6574cdb8c2ae252cd149", "f02369a7dcdc9caf15bd088a64de4a00618cf25b9610139e82d96eab4413c285fdd44ffb8d09fa0c0a85dd78fe0d005926972d8b300c484bc8565144707df3f296ea0ddd14714f5637b0f864f33f03f1ca6432ca761cb214355e072ac5765db0c9f9d3b8553b365b40c2f2a7dce41c243a859815b9e11c94cd9b2d3a4b9e610672912f07f4f734014768aaa4cbec91c9f5bd0d8a2e00", "-e6911b34a86bb13cdfcf2a0050b57f3c8783fe6dcce5c92596c950acd27c9bd1efe4f9f4b65afb99115c7c66451a835a6c87fc4931e7f9a8317612f9a8c7e9f3b242e90338becdd74a526057068480458a36e4015c91d614cdb42b584eb72960f2c958f7e02fa5660bd41e34358908e9c97a87b7edfb2afb80e9073bd8a2efa46d2a3941b923b618f3f6c1fa6677c411330ee85d5cb7", .None}, + {.Sub, "-fdb783bd20178cbda678a5de37917f05c10169a70a4bbd7de6d28f5448a8a1eb81c8b13ac5f51ce9b87f213d4a9a8c67dd3993e58c7ec7863961dbaf3fb5eb0e978e63b01d1e7df35f077563be89d101ae6b6ff8d11858a4f0b0e8b0048650c38cddff99aa49e59717c2f2988dc000cda36bd8b40bef5c47128e118ea74fc7693407016a03dcd12cd8a9b286c2333a9b7914ca9bbf9a", "f67ece0c0e1a5e8f0938b11254f4d0232f79ac5c3dfff989ab733276dd00eee480b29fcd32501c61068da4f410a9a3b1a5b13a10ef63be9e05dcc326223a82430165eca22f227bd4f68383a48567de7b45ec460f9b35afe011c0f75c0478eb5eddde61487d4a874ab7246dd2a91e18bbfdda83ed9fb46b08c3b4e0711f3b61ed60f1cbf18ca848c01efa6c11ea37695831f813900605", "-1f43651c92e31eb4cafb156f08c864f28f07b1603484bb7079245c1cb25a990d0027b5107f845394abf0cc6315b44301982eacdf67be286243f3e9ed561f06d5198f450524c40f9c8558af90843f1af7cf457b6086c4e08850271e00c08ff3c226abc60e227946ce1cee7606b36de1989a1465ca1aba3c74fd642f1ffc68b295694f8cd5b908519ecf7a41e98ac6aa3f3ab0cde2bc59f", .None}, + {.Sub, "-d2784179884f12ad65830347dbb2f51fbc1a1ac0af18125ed05fa3b78a93ac1d87de1b5f532ad297f375ce98a40f37c99fc695a6d55b1ccf02a3efce03e06848af9e23abd4e7c435666c183940bbe35ee7284f4d32aa6fc99e3fd19cd0c9cc70ecb251d3a32ae5e8184daeff6f44507c5c82b6945d021c83bc840dfed4f0d0e4389d3aa53c77c07c3091c396868deb620070ad4511ce", "882bda65a0f69936b387b61eb516a153f7ab4bd016052f5cab79f914fe8d0a505126a810fa12bdc02a55e2417c0b193a67e248c1b725648e4d2dca4edb0781ece1d4ed2aabe06b70e8b096b1259766b6d0efd38f5f279e06d6a29cbb65331a7f689b10dd6b0a5bd2a56a1446468f31db1009f61193556d925ea782db42080a56b3fd8336bb08c3ed3d2074e951d2fce0beb285d9ee83", "-15aa41bdf2945abe4190ab96690c99673b3c56690c51d41bb7bd99ccc8920b66dd904c3704d3d90581dcbb0da201a510407a8de688c80815d4fd1ba1cdee7ea35917310d680c82fa64f1caeea66534a15b81822dc91d20dd074e26e5835fce6f0554d62b10e3541babdb7c345b5d382576c8caca5f0578a161b2b90da16f8db3aec9abddbf78084696db2387fd860e842bf23331f0051", .None}, + {.Sub, "9ef49ade1c41fa5876649403b3714465c0b8415862c25ac868b60e08c2b5940b24fc7fbc31b427d14ab8699e9e3e1685857f41a31f3187543ed30b8e1d261a75e02857392c637c05fb8a333d87c911f018814aa0da85eab30695a6073d14296a4dbf8b7ed35fff293f97ec8069b5097098a68571b337a8b14472dcdfe80c0aa0496dee98217f16541c2524e9bc7aef78ae0a1d08c299", "c6de7ed220d9a250afa12990764b4178442f9dacca5b8b62fdf70496b6d0e5e19d07c4b2caf223e78eeb2cec3381d19e7546689e15a0cd439c6be8a663fc3b6e6f2dbb62f84705a4c1777eaa3477f1dcc5bee58508f9918ba370f392b3d83806c8651774556bf5fd150e3d7883e56fe45f6adf634605595560963f1c0283bb6a439f1b14180f18dbafc97f82f8c7d7c844a78b67b7e4", "-27e9e3f40497a7f8393c958cc2d9fd1283775c546799309a9540f68df41b51d6780b44f6993dfc164432c34d9543bb18efc726faf66f45ef5d98dd1846d620f88f056429cbe3899ec5ed4b6cacaedfecad3d9ae42e73a6d89cdb4d8b76c40e9c7aa58bf5820bf6d3d57650f81a306673c6c459f192cdb0a41c23623c1a77b0c9fa312c7bf690028793a45a993c4ce84f969d6e5ef54b", .None}, + {.Sub, "22d7f1c429cd10c0d8f9c4ba093bd92b11d1420ee65b80a300ba8785061199bac89b17e6e682b482de6ece92abd6b8d269106d9a75c65441da652e81bff819b45b2c678b8725d45e8ffe82300045b295c9258e67a53ddc55f459cfde3db8666855b4b6db8cd1fdb63cdac0d4da39e37b559fd28c442193a9315c16a7455a5f4a6722d3373af3f6605baba9ac0ea069ccd0e97543de18", "6e618a9bb55b6ef12a5949062ba6d5aa2263a31ddf6de430100870cbbec3fbee00cdda53a4707be5d4e6f1d9ae054b14688f49a2d88eb9e24cc6d6276c8441f0a01036244bbf3d556ecccf437fb42cb629401e35190725805520bbcfa42aaf5b0794cf9d4dee29f02bcbac79f3e7b126d332799385d146303f310cb51da21700e08d90b5d1cc99992f28525e6af271264a0bb9cdb598", "-4b8998d78b8e5e30515f844c226afc7f1092610ef912638d0f4de946b8b262333832c26cbdedc762f6782347022e9241ff7edc0862c865a07261a7a5ac8c283c44e3ce98c49968f6dece4d137f6e7a20601a8fcd73c9492a60c6ebf1667248f2b1e018c1c11c2c39eef0eba519adcdab7d92a70741afb2870dd4f60dd847b7b6796abd7e96d8a338d37ca8b25c52075979224489d780", .None}, + {.Mul, "5e832f3f3f0f185b6d79e87a12fd44b2d9ee80880c46b4e7bd4c4f110c4fac7388ba3dcd13b65295be7c6e8fda354dfcf307ef0fb76db773663b56a048bee4ca6483eee69b59e8941a9c19f88aa64ec2230638c028d4e462730206b433fcd27c5651aa3d101a355a03b1150fbb0058f1052a9521666468cfaa0935e908e2192b3414a7beff3e8370c168689ce0ff6fc1c5f55a4621fc", "bed8d1c18dc39c3a0b2c95e667a5ba5692ee56261df43b92828ffd753b69228ec90a5699c51c8998b2ecc29b8749e7729f4a815879c9add4a37605013b105c397973d4bf7d477ada55d4badd8efac12f4067fdb6274c5f9c8354b9116020cfe6658e7ea5606f497ce42fcfadcbff5d37fb4ad468017e2436866f8bc12f800ff6a4f1fd40bae8275c3f4ea09a85c92eeee94d7f43dda3", "467569315cfa229a77348b4b77346711ee58387b32b287c12bc874b845cf7f55792fd53433e53a7c822dd2ae71b2a09ddb03370b4ec68764c3bc0137fa98ba5a7c794748f84e83d4fd9c78c4bd79ff2d19fe05d5b2dd269e53d4108318b73f58004955a617c034b3dc50e692279d38d3d388365f2faa27b85524aeca85c5efaaf40ef722a290d7736a8e1a9ca6efd7b0369c9aab861a2286d047f335e4b8af12383eb393a703213aed12a19cf67296bb185ff7f5a347e36e1186a7a15a4c48b81bdd6165ab670e2c1e52ef85089562ddacc06b5529c6fc67326779cd7798580153cf86421f2cb2337ffe8c8f44480e88202038bcc6e536928d99cae41477956b8dd17affff8222ddfb633636336a5b53a9b8bb6807b9ed5570d8e343fccec57c0283232ad393da29eef22f74", .None}, + {.Mul, "-ca5fa63b814cd1219cee6316ece624343444cb141b7af17d583679628ecbcd37cba97b34da4c263c823a6b9e9111f1191acc2f8519a8f91a89110119dae76ff8db8b0dabcd107a17606b905389ff510911629c80d7e26a5ade8b28d891b1e09d445e68f3c0069430f35cec2f8fc64b000bc6b77fe40275681649a0e86598adf228ac66e39c3d11e4da92475296e33f41471450f5e205", "1af3b536417e273a0bbb48955b88e083ef1bf7aaad35a24f096b13b30f8e5e8ccc40a53492d60e4ed6f25beffb401a61fbea7d634a0ee1c35908a899dccd4e1bab3d9c90dbf2864f561e1470c741016a6f0d88c61ff78ab89d5177d4ca26ac0757ab0b67a847e2eea324a62601e2a61f13e1a8101b59419c12d6dbe5d15f041b02167daff617952a0beabaf64a48a9e8fede3ff807c0", "-154e5eed5a18af6be54c15de74a010f6575cb589c1e5c231184d04d32d5eed6118df05173d8e2e13b636409a20616e1ecea78b12f8b8ce27df1f772935e431fd12c27e11e9c75b4bf2655a10164fc72831d370e7d66f67f186bf586ad2fd6883963fcaa1de9d85842839b3bec978dd17c9da7a29def72ffaf9c2830032eb8e808378f77fcdede7eb0904fed0a5ca90c4bf528ce03ebdc7d9b0f1501fd25d7764c959f80ecf05dc4882eedb58e25729dd113e5069a6344596de5830bea53c9e32ce42e369d2a3da7c6e1ffd6494124b7ab789611db737b356c9e040fa6166fccdc1f3aba8380ab89c0f453fb4eaa928e73b0c0c285de37b4b75fc31304ac3f27bbbbbca18b3496417dc31e52a296eb7d21eb7dc4fd9a36a3aa69106d0417134e3f71039496284c49ba16fa6c0", .None}, + {.Mul, "a8999bcc987f3c3b03823d6302001f77badffd945ac56524c09eadd150255af3ee05a45955564907c184326ab28dff200f098a7e371a79d90de124ee3171aeb7b3b6bc9cb54e0fb9a2f0fa173003194a55f6a3e7960fa6e5846bf83708a96242f0a8be77bd3edb873b0cc37f30f719a79d752b3a00d6f94e3134ed1a1faa5d8192ad6e8dcab3388bae33cdc3b0028096f4582476efcd", "49262a393470da2a38cfbb56f9023b011f65ed450b0a20d848e277cdfad83ab5245e42d7920bb2381e8dfc067da9fa50192dce456775297d5dcd67e49294e3ea2ed42dc693d2d59d4ffc7d52b29670079479b95bb72a49ae580ab0ba2f8866b86580d7725eaabe09e6ba05f554033bf1b48a4edd73842212e70313ebcacf352310ad59eddbeb4709c8ae4db5004be207fb27258b4101", "302cf0095827b32aeebf838c6b3b2d43def3a6a724f950f619714ac41375ca984ef6bb9d4b3024c1094507af3b9cfabc7402044d5540cd8bab6b44587bcf3af21de0b2fd28100e0164a711e5a4ba4f136f3751a948655013749c2dd6a1fff36f43a1bbdf7b64d44a3336f47ef15e97a06830b43da9b423795f1c665f3276c09cbf7e6e50a2b7e2b773ca4b886100d3d63307fdadced7894e5dde82c152aea67c02a3829003b7bfd89c475f68088373844d8275e299739fb8e5fbc05a839b70f36801a31ff3caa34db5f0190556780a863e09c053be43c4930e130f5e75f73ac9e247fc9bca9a35ecfdef52cedfe0bd03fd08fb5427ec0050bf5c3a81b96b8ad9f424d448c36a79e05d24e3e18636286436ec5d6edd079d36cd3e7eaced852cd0665adb20f199da122ca8fccd", .None}, + {.Mul, "-cd5666373273117f18da0a79dba4b2c85c8e2b3162fe0a407df7fc7aebc5304cce1912d8a6f5d88364fc5d04250b5f76cf4aa719f0c59fe94d82299a2f4f040c8425ecdf8829e9288bc638093e1baa297484d5de95df9d8baac324b3205af4ebbc57ba3686dc1e6ffd7fe8c3df22d8889855786c64b61791ecc8df5be7fcc1aae7be7be6c86fe6c8e53722921ee82a13f28253031cbc", "b9e19a2aca0d4b63ee51f84a91bf01d08a2f035fa9407c2b5b41a8f25a3d5a18412f2eca5c094b26c88a88ad1e7e8238661272f77ca9208df7a31559ea06287853fc588c07d25ea4f6948fffb2ae0e407d7c58b1e316e4478f7bc977e8394090e44500bd5de22eea26f187541f7955c1e1740ac9aeff66b3c41030e21eb23f1a00c40a4bfa8f37c1d8f6b87559c53bf7a76332196265", "-9518647605b34eb1ef31de4e13db8129192aeea47d452dd9768b618947cdb260d91a3df1db26b5534f8444a591f47f7effdec7e85e4d1d7f99838d1957ea0d65587f2e268b2806e1301f2121c541c641d23610613e245d3e39f97686f6b8b8aacace9efd4ae7a3dcd3af5f6a73140636aa7623e1bbff9d6e493fea7fb4817c11518a6065795b7029c10a7b657931154fd92a8f70d09fbbb8fe64acbd848e4a0d4655257cff11911b2e4be80bdd540adec1f30ae72d081611f422b232de0c8797e2ac3a286d8d8102c27a9958cfa949f6bfb2784032b209b2ebad38a4c086d4d1dcbe73878184fe380c960db0474c32cdef87c3caf88fc676c53ea38a3cf5a11f4088e953fa8794ef3cc48f6afbcb36d87fd46b01b0dc28c57c744a61655e648a767727dd8efc08d077964e2c", .None}, + {.Mul, "4d58ed38405f223c69ec1f5f10b34cc0ece26e8a968549eda9ef4ab606a0ad76d8e3e9d82cf0c5e66197ecccb2bb1beb441ddf27e5e5f8cc466ae70987e601f1bafccf4ad5b89b81ff884475cfd01043cd6cde65e81d47cdcae152e2179eafcff25dd81d999bce7d40ca0b331b36f7e5fad1eede1e4ec24aff6ff4fba85beca97433b4156cb187856ad71a82403460f209d71c8544d3", "6f51305365a26c379dd1e5e802fbdfb7babd86ab3928838bb494029da348ba208b42be72aab57321b27eefb11b161e06b9adc4a91b32371c9f9779484317f024f558e16fc76d358b7fdc701c9b7a865610385137a454cc8fc52921c2626950c7e8e317aeac55666f7106d35e6d1f4c6080b48e7fe027e305ef9f1abfdead7f0f4c0b0ba1ab3d7254dd9baf17154acc6ee941f6769a5f", "21a2169851ba3bd05d2a3e4209c10b4a236600ca93a1cf42f618d6fe0812821fc412196f9874181f3106369e6ff34b049d761dd4539f6c829da1595ea389f3858ca724d7a7f95e9e1d5fdd9e621e57c2f4d38de41e68846c7830b9545bd6e8e887b2b55b91f5ed344c86cc8a1f408ac0b60fcd735cb4539d58a2e08f364007a946b474c4da4b74e64b99a3dbf04f55796fe193cc0a1fc87078a4e64d7841ba6fc44cc9fe07cd3b047790b0504c124f202ccd8eae7d465449ee3773491eec6f01491ad002bee17dc824ae273d40a0d81b754e8574067be407d0b19d4f0ee4d546fd9f139806beca10965385c4303fec6f7b578f1d7296fa374f11214eca607744b237d1aac1c1a18a95684ea64d6ed7ef95565e24c103790652b59e86c69ae92d44f48b741270c81f3c1d784d", .None}, + {.Mul, "b00062ba181753c0d627e64d48de8935064df280553d8f43cf5e5e0063895351fe92276f69490c554cb1878b1c1e6b84083a1007f73435fe33314a1607ce2f1784d7cfb7cabe5365fb06f177cb003d45a911326c5bb5823999d4b5b6fe8df5400e2ac9aa2ea0ea56e5ca613f9928b1489aee7d6185a8b982aa95a95d5f4115e09f888011e3bb8ea644ade26d16839d949ea5a6e77c5b", "518428e928275bfa4b7cdd2d3b700ce7952167f97b0fa362e6db6fc6d91caec0640440dd933baf67bb9153cd1c744877cd951cbd1a5322102d8c7742109cdbc22fe29889e058dd8e5a78e2616161e3f1dd11e65bc4fb503f4282e8395a5aede294376d884981f8bff980a9437079e3307fbde79463f7ee8c14df607dd447e9b5d53ffbd9222e5ee06bcd76df1ac859abbd77dda7fa6b", "380afb9024f5db631afe3e85d4f48087d953dc01ee27e44745c73095b29fbbcc7cdfd3d476e005f007eac00d1bb5a968ca2d74676ef8bb7afda41d8b778020425861d6f2cace9bb80f5f718a843abef71eed141799eade68e06bb855e938bea322735e399c9b291a3842252fca44ff19e5a6263987eff3da01f7438b7d58f1e6c75d6c2ac4752a6d6a0580a60155075fe1439276a03fd96b19b8a27583586463c083233852dbd8e0574529ae966b23f576d0a04988b2facb4f9fcd2c66336cc31c69955b361f79142d418157408e96bd87d572022a36616116b7b8588905bc50e8c9b468f22e1c9e6d98a461f577791c71538cda62c5258710c1a6db8f733d459a0478d20212358556c353cb8f217ba6338c34e318b7fd1a6ed3e388e1eb6e8c301c70fbaf64c8e4808ed809", .None}, + {.Mul, "25617f8125e004d98abed16e1596284bbde1b442e8ca6b53854491767fd9b7b74c2b2bcfe1b6535f4daa12ec33684cfe1e8413880e8c753d87c008b9cd0f93535c14168fde176370b2621cc5316d57eab1ae2f912fb9c5fe70aaa7c4fd81ddcc4a90767d3013e1e7c3b71547be886420b38a4aee9f8bf4abb8405de19a82129c8408a4f9cc1dc438fb4094f2934c2aab19e1fd53bb5b", "a4d6a859fe7491a8325e37a5576a12377c3944e88156f72a77c3fa94962bf817b6b5172c79f85d015184045842bb913b6d6b4bca556c75c6b4700d80e60987264394b2de532d023fc9c0d22b208e1c4b8f7e73fe5e33549302e2b40e2c3d97a0cb5bed4a1431391b695dd8e95faa57fad9e48cd66fa9afbe68df781ab6a2b14eda6e46442d7e397683c0bf4d3918df6ce2354efa1c35", "1811cdc471f303154b74bab6f7711952f58e8becc071541317684b3190ed1fbfb18f630a12e837980264967ba20624dc4a04eb7af71c8f4397329bbf4edc5cd4f75a5879c0ddc5a0c61a5542e36b1241627796c45d295b0298ed3af0f2daa6df53738058888fd1e3d208be67560af43fa1495772979777ed89d5d8daf714064fc1f362f8bf4d265d8dba7ba2042e496c3b0e3b6be5d3c1dd417697a5087a6fe6980635b3c2400f253a14e3949928eae2eea9b493f4a7595145b2e9812e914dfcd500714d36552278e3e57f60eaaed608d05e8fe00ecae7a6d82e7882674577f88aae123e16df92db001d1c770831f00ab58d79ca886ca327a23aa7790a7c356a396a9d5487f0bacdaef1ba645ac2ebc6b14298fbb4040843063c9bf953afb968b8ef20e65b421a304bb1bdd7", .None}, + {.Mul, "fc5be50ff14b20b6a09ca03d8b3cdd35f86bfceb91682dda1eea03f92e83c8b670ffb94d831a611834f1e33c3698166fc9f1a34f10ca6cb36831cb9646dde25b6b2e704ad1b0345f2a615c4b1958e2be1ce32b9c102f8513460aebade610eb84aceb14f68c9a52f3ecc63a38c8dea904e0279b626b9cab0d385d130d62c57fb7825c6907581dfe40b07e7a568342fcf77e51066ac81d", "1963b5275f5ed883039b0e6d4fa625f94a349904131cb50966427895d19611b67d31b1ca3678228ee63f6d281ec747e2c1eeb8e94dc825a2ff6043f3453ea49700e9ed67e0f65193c4048be0928fff37e420a6d9e7562e74ece0885b5a3b32f6ae444215e5ce7fbfb35a2ca34dfe5033b0e72f1994d1d46d8e277ec0ba525939c670f717ba987705bc2064553373c04a35cb7394db95", "1907437becb26a751321969e7de92a785a1945e6c2aac700e2a5e0b7623f1071682b21158411564a82b9b8c9b25224910bc5fd33309034f8f48186f6fcd2cf3811c50c04e98dc593e13a27a088b79d34af32194ad2f643bc5f733b168e5afc0bd62318eb5b1078fbdc6144cd980030233f9ac1b98b5ecbc028a67caf352b911def1ac5e917cb544bb599deae820c347298e773c691953e5787a3bd0a44e6043929df290b3770bbe5459d0c5b7c64ccdcc5a98132e8a4730b386c1b1720c57230c70a964957fe9df300d61bf32c068af03e077c8a2eb4321c3eb0f89811bf5daf6cd2b26f919b2954f112b55720fbfe1abbe8d9b776feb3bce4e20c125e513315803b8e2454cc523c308fe447029c0883126ba9ba2f9dfaf883194de46c343ff23c1caec72c523345cd1b47e1", .None}, + {.Mul, "-d19b1bc03b5587828a1bfe8813635630990221522cdd5945bd81abdb7927722dda2886eee6db730a3f98cc08c77ab5d58651029e941dd1c48fcb5329d52a062864ea41f54fb4a94cc7a8b98f59186ba4ba2a205a8bc1f0de0af8e6b17dd5c732d1146c52b8538b23a7dc34fac36857801f710202c315f725638f72f31ee8d1d4dc90a5585902a1bcb635e610d9d9bb528eb476a87b61", "7a74ffcdc40df2e6e496202e943877c6bac41e954f4caa0efbc50ae7f010c36e992de080a0b7a903f65bcabc74dfa88f81c196a579a97dfaa0b6130b7e447dfbfe693147e70b58c7800269daae7225e586fb6e6d28ba3e4d13d92f336179055a8c2e56fda885813682cbd7567b7849d206bb2e3e76f5bf8933925f019cf7d1fce5407cf280e6d96f5a45c5c3aa170efd6fad410d9bae", "-6443b6f429c186609560aceda457f34e60cb2bdf90fc7a2b08b8bada36e0a9be81f7652066d69ddedfebcc58c1e7c7cc5dbb6d3ed23079ca69c9e4c15d3c563bb86243976aa6fc25353804a483e5f8b173e297f8f09c4375a9b21c38ddccf509ee4f9adcf71e6fb486b67f38e3b8c1fc89d1df0cd77225b6a31094238989c6443aa869eebd6c3f992b5320ed5d7fb7d6b0c785bc0a39e3fc36f3c06bd3a839db0d6ec16c8de1c12852be64069e875b445666897dfe309ed2e87ecde80fc904f35bf368ee26405f952d02271ad4901c0234511d770ec24adea1d845b9f85195cb1383056f1743f520fb9f153fa44453a0c508182c85f6516500dbb283251fa87bff7095282e7c97ae93b05f35781a6957a0ea3793903c740762b5ea1b45cfc34a606f0a34da067fef8e2496ee", .None}, + {.Mul, "-a0a96692dfacd9fb362f94ec00a45c6f307a9d0d6d902170cec3e2dea2a73fc143df5e4f1038527b7c5ce4616bbbe356a3c2e1a16e7e6802a57c0f9bf8f5b2d7a94b9bb1facde8271c5caa83f494b0c76e2f61a5b5b079206bdb11f5f27e52bafaeae7b3bec8f135b78668e674285deb661b3a26da665206681777a41ee8f626bff3ba5418cae4a38b987f78b09f3312c5060f36b152", "2e61798a128fbab1c4c5d34eb33b73ac56fc2740593330b9ff6af634c6ea5db35eacd047ff5de3532b1ce53d742ed1fc24f4f468d8a83e7dffa3c8c07598f5fcbb9a1e71891ec285712a5b268b3cb6f3bc3a4f7bd566060494c083164421dedb935b5f859eb97c5ab4c80736a08e9acae62803f0f085a6819400dfb6391711ee32dab5ec7848a56bedb676379f1f265bc589ff64c41a", "-1d1b9ce4fa4aa390470ae7449883fbe423f83193a9486458a804fa208a9ef8229f6b1ffedb55ee00cae857871170bc39d437b1276774044b09748bec09e07af1a874525313836eeddbb5dcb31f2c84a38a0a456d579698da35c25e77b1266d44c048b056685e6b051f030172fe4b3b359a14385dd58eff7c510136acc74a511e2d0d5db08e29347e3242245412ae70a3e4a7b55100d942850d2b852855bbd7f6d6f5127f1365d5baf512713dab26cfd75d6798dfa672e9627d901affbd5a10414913a7fc3141bdd310b1d6080e5713d4e3ec922d204293bb6bf76146938241bb524370be7714d6559bf420a96b8aab107579f1f326828fbafa00930ff7d4f495d1910074c81c8b7286333db6b67b665bb3a4d80f2211991196d5d9ddc0fafe8a55fd807ffd2511235d58ca54", .None}, + {.Mul, "-7cb09b5f56a61b3c9f9588bb2c80e0f180d4c8ab86d48f7c693c05ad410d6e625220c2ed916a903a3009687a74e9fad2a28c1c62c6e14f5d7be87d70b5cc333832bc123683ec94e6734a743284860e6c206945830ee07360b8ae6c9697bbe3dfbf03334440d43a1942c2aa805ef9b9108218dec2044446bc4b05bad30865ae1b3c41b25f36808a9c3e993c092e9bdfceae984dea74cd", "680d7229c6ef3189e1e930fbaf8e61aed92f2ddf52e65b643dbb0010952655115efc1be43db69cb10f51f91e202eec74ac31f1ebe3e89357eebd811ecfb884f0d323116abade738d1a4c2aeed10421607084ddb842382975758d55f8d73f961f9def740076ab80492548c2cf9ec6371519f10d03a4698edfeadf76f27fed0acc7224b5125f7e910aaec0a3fea128da7b3126b900d852", "-32ae4bb19d6951889cf3c6d18547d5aa1afc8cda8a33ea20458d97c2f65bca35ee95f9e7475f66746d0832ea1d3eaf0c0fdda72c39d22b96bfc34c6c962e2ba9a3c3f84a3e5f08a8149fde28120d4387190117af59176543f4c27ee23ccf9a9a86067117d4a6a4355741ba492c8b00b5f84dcd278f66135371e2ef2e6396f10198ffa7fad6023502a768125e2535b32a62d392ccc205cac72c2cddbbe0c206f1c711111287a8f6f10dfa2a45990ab7d98d69a9c2c1fbe154fcf35d6024ea03729fcdc642be3468b509ce046e6a9294d736e380b189f6913b99c02a3c03b4228e4e876c35cabaeee3f52e6c0ea1f557c71dd17d8f3540de1a3d8e68eedcfbcd9e43c935334591908db478985a1e563c3fc83b95bdcef3922afc65f3726512dbec071e249a457a705ceca661aa", .None}, + {.Mul, "1afe9cbcc1b1a6e4eba2cd72e02f58775aa22c85492148364d8eb6ce799e03dd7491e412a3a9a277708d0b94e460a346eeb0d9f197112b2a0ded7fa0b640792ee048e4c6f09d2a76321fc2dd4b7bf4b39237aea032decaf8f24ea10361f37f5c1199930100ff6e16fb527307d140dd2832f2641953933f8b43d1dee4540b25bc82dbacb167ace1570a70502c4a274269aa3e7566ea1c", "a562e16e5916455de329d12c92da630e0a70fce88aaa5f66c7ba610a67b330509aafb09693649efff4463a7eda0eed58f9883a3e62e6e38c915b0a9e92845fe41f6b103fe3035c2b9f45170ab2f263cd7450b238a04c5c4a45d41aac7cff8cba13deb766a8de37d55641db4feca498e35dd038f9b07e53339ed42d4811929cf4339a08436f853a491eb8b03648dfc5e7bf85e52a878e", "1170884313a7c39b6bc873173f4c964cebc4d28bfb1017e125496b8364ac9f51349fdfe26d19702683748908d1a120efd9734ab183ad2a7503781d1a1df6c365f3204894e9df6e04e4da685154e413e8e260446e4f8e6e5a19b98def4127d231457415af05ff9ef9cadf2267e410f5f1bf9a2240225e9f34bb1e6dab3189a88691cbaa9a6f7f627fae0ac80c072d5f35aebf081e4c19d6fc7e1325b2e8ab993d3afae4a89723b3e93e683fd0ee317e20a0538669afa2bfca3ee72fd75beada4766fce741d267c1bb6ff17ba8b8b076f756e945c55f36ee6684b26183960951561d471b1fbb275f7b6515d1bcf0d7dc21fde3099ca669993343cd5c98a9c64feca89be107df288639a0f74a60335c3bd7307a7ccf2e4f51235d0caf54dbffc6affa893cdfef0e3567d9229f88", .None}, + {.Mul, "-56bba34281fe6efc2e4cb08947018c480f4618ab43bb97db6965a37e8baacc37e73e8a99bcc83a0e54283ba6892067b4aea05f6cb183dbd0a6f71fe7b3af29a7df2e8d7cf9e759dc5d91de25a306d02d24d798ec5d805d863fc04ddede3338e5b4096c2ebdfcc1201c252559ba41bbbba0a68223a630676670e285ae53e27f6bfff92ff32dad205e9bc4977487a6f9fd2973fbdbba40", "684f6629770d3c967fc63676917cc3f203ef94e91ef1020a8c136719a326f6678237abbc6dc911ce39820bd683046f32b20173c6c8daabca5eac271c8a55233be2251ac6f5d72bf48fe3bcf41d69e558ecaf045b18a2e4766900b10155831515a896ad04dee9de79121fb5cf10ad2f91f8dcf8539087b4a8b93fa77b823166756a0c38af09671ddd520f46c532d452a6fe68f03aaeeb", "-235720d735c4d4ff10e70ebce5663dfba37cf41441a6a8a817072b74331c092fec91e19995790462c2ec910e8df713a41d0c618a3607862ff4baf53671cbb8bbe719c518d8a6d6d9ede78984818a1b0a3884e4062d900fcea80f341c2d51ee550382f7180079c616531fa2647e3cc1f38ff258aabe10bd0197bcd319863baefaae7f671eedc465f21687dcc51af17a66c9b6d73d57d6899ff78e66d704d1209091c33f0d3d175e2ccbbbd066363c52eab2d3ec053b33ace4c8a575a7af62d48a596b4a13a6bcfe50301497b420aae1dac7742154e921d69b126dc2b0f1b4137c2026f73154f8c011009708214ce981b183cfe2ad7be7533496effd691c2f9b38c7520a5938e72dad1203c6c2e042a8cfec8e3de18ad9c2aa392421cd772e6f4b97d0588f47861b0bbdcb78c0", .None}, + {.Mul, "5eaa54c7b6e2304cae438ac714febdeb1cb49b7221ebbd5c44f762f8fb938553c00c1fa35309b83d0d2860eb84c0d167bbf40cce064733514084afafe099de5564732dcf132f7d612d03d74e17a98e2639ca1531754a3efecc94811960f5ad78bb9168308afbe11ef4d60a2fa39e343225d7763e8ec17d1e8c87e751dd2a2d336ebc22bfb6af449327626952051af9039245e082b37", "3f7c0a70c45bd5ff88004b0301b18718d4f457357c47dd4f4492c48248a71fb7132e7cb7dd5ac512b57ed498ef884bbbac36419e85f0ef19d087b44887a2b466567ebab85c256ab57f2b05b0943fe4bd8c659a8f4e6a7f332811cc52d12a46cb255d28eff5071e77d6dd8f1e43591cdf7b0fa6d47c168007273095848c1db0c6090fcd16fdae4da04592a34c78339f30c09d4347464a", "1779c93a912f828e5e618e7b725ae6511200ebacf2d9504451d219a6bf2be3ff182ab025207b92347169888f202ea7256786a2f514011572c3c7dfb43e4ccc92c678d3a8342ae8c05e8410918f7e4f1fc461aff156303e150c0de16f9842744b81c9cae0a0b8117bf25f05020e41594ab6d057c0a5d629e69ab22660a4b8703f1d5bf0142ebd281f333289c25a52400b1d1e22624aacd6789b8d329dcc1021f63dab16350e031be330767fc620b094eeb0991d22965e93b8bd942cc4b175166b38c83280334a8716e3a5257b8b7260be2f1c8f9f2ac4c355648db2b697c885ceaf5fa02b6f98d693ecb4ab82c0cc7d399a5db771a656a29dff652a3a1b7651f5ab4a1b70894204d9e39b34ad19369dde5550a3c798ca400057544fdedbe3873d24987ba9bbe6e87cb6e87e6", .None}, + {.Mul, "46f6a4225eb856203567200b7ae7a3bca705b7ed339bf3da2fdc9b2d225dcc5b6d0f7c456ff4be48f3c1557ca7dcb1cc35cb2179ce15ac92481a527b1cedba6b64a4bf094060dbcbb71cee9711e669e66fc9d0fc0f2eef6360b72a47a6b4f488d45aab3c40b60395f8ff5bfb31092e0b3d2ab8fddb60ca8ef5e9da8a3082a6ec5de70f3c5893e474cf5bcfebe013af4ff0db6417dbeb", "c2c9c0ade9dff0b6f798ff82aff8a0760f4adbb871ca980907fd48c289da17944e8b3e6ec77069a1c1b83ca39096cde749b1c4295666ed61ed00ac7b1acfb7a7bff5123eed3f6349f350b56ff09ed5571f00cbf1d962046f22b96f5c077d6fbcb625ae7adc520732b61c0dae81745f34f4f84972f505ee6a2c5229d9bc84196d7113cb18be5caa9001812268065cea2ebd6089ad1fbe", "35fed5721b5f513a7eee03e74ea64fd19fdb2ed40b99af68646c81454455f6748c97dbb432d75fc21ecb004f396bc1b1833d2ce6bab76335fbcd533c57a46cc99c6e60079785de4b24b36a693cc584ecca4a21cca0c51728b0b0437a51c54c3d09b10132050d48ccb55f729eac61b5959ae51c64ad790a2f574007f98689c0e197e5310e4ef24cad4aa6796e34643609aa899b5b8412d4adae48602178966329cc8ccf13146995956ee47b7bd861ba013f9560bc9e66a3be27cf8db15866fb0d215e69249cd0dd54bcdb7d71a313e2f2f63f8f652158951929dd4e8671437e15f745c9113b15cbfec860c76141194e9606ea1664130df0b8c53f0e91813bb5fe48221fc1357e995b20cf27086d5e98445f6b7bdf7fd463561362b3fa7ca7287a803a92af70dbb3e38e25ad6a", .None}, + {.Mul, "27f25bc8989c8d431f67e9ace636991c71d2a00f0e9dfe978d13b873ed0b7b9ee26312fa631a3ebd53c9980764fa77a7bcbcba10d26d25dc37fdba0fc05783a29b4e728db48d78bcf7d1c29b90131c5f57a1d4829984382cbed29a1615e383bae5f3bf571b7baf8e6941502991913503f07111fe1445d2f2d07f86567e5b2112202fa6e4b47aafb50241cde1169da17175b44c4d9838", "82e14ec549fee11420c539fe791a783aaa6d59f8e235f0dc54f80f7d7e8f126eaf48fe9138f737cb11058c1d16df7e152987a9470c391040d549a4f3c019a875c7defa7d4a39169000771e43ccbc03422a2e350d0b88231fae4d90d4b085cc599dd4cbc3ada27556776922341445cfb3f2456723e9ac5511c394690b1e2d38e59cc2fb4d782a8519e4df8ac5c69d07188e56658e5fe3", "146c3ae929d142f3ccb822a73335ce69028d463e3b12dc99201b43e7cf0f21757ba61a1e0f138b1d1ea0e7cab1ab436ff8b81988c66615d8912c9a5e63766008782916d7b5db825e2a9b98641cc428a728a7cc150c289669afbcaeac42d946c25b52948c403928b5bca765bc46d0e0c6a6a6075160474eba44ca12a421da38b83cba9528713db335e1476736a317f881e3ab3dec3972210568c45f0ccd2aa51f45fe38f11b9c20b1d069af8c5793d75b3bad49eb1ab65fee6d8026f95612c166addd9ef2cb2c95d8903141189196fd4058f9554f727705456cbc624c7665e0a293bd1595a89484d23d7e3cb8fc1b1fd101779e5d9eb2f15b9ed4b57869ab03e4102aa8424b18b10f0203414c204645208d007f9a27e250a6f8b56f78b38c590616eb5abb28266a18fb5ac1a8", .None}, + {.Mul, "-416071e5eb609e95d08db0eeefa45c854cea748894c91f94e03865a4c418e46b7738603183026e4f127c5fac030cdcdec40e95aaad93e49534c2b9150a131facd9bca67d38e79d2440723e9f045a2242a9e5972e45a9d2ca54794f956da28eccf0c98f049745393f356eccd1f6aa94af80ea7c2dfdb61ef315967d004e52afed4c1bae50e7e96d5385b629044c5f939edc263593c051", "19f29261cec54ffb8fe030ae1dfda9a2ea966a8159820f7c51ea986c8a53226893cd70d963c4bb215d09b01e59e5bab9bbd508950935b9722ece1e8b0ceaef26d46ea747037fdc54703cf9916a5c29a40af03c06f4c36cd760db0747046269ef31fa39e2d9dd1880aa591a704848168a5e3f46d9c88da72cfbda03d54c4b42387be39854d960e694699d8d2912d169e0c2354e8dff89", "-6a05dad1aa338797fd425663fdf475813ce12706687963f059739327f33994e35f9638e41b0ba5accc8d98adafeeeb051cfb056785efd4684c4400ce4f378ab50b5470b2df49068b7e65816bd7a89f74d7107e262d5c04365b13550abf80df844d2a78950a99c91b7dba242377116a9ed15556014db7867975f09ecb39ff7ff1b591b4415d2f5fb751a0999833d0cd8ef3531e4393b80ed617f700e9986b6bee58b3d79116fe328a9403105759e5d42555aea8cbec2226a12ae16bdf4eb0d18a618a3b891962cad5088aca4bb7800ac1537eb0f77789de333c05510f84c5cf1b012e2341a9c8839d5fc5c65f9cd436352852ecc7be86fdd02b9aab294d14f480257ccb568663129333c116aa6ce199d4bfaa91c239c8127db750f8908c80428363e8091b1e0998f733f9a59", .None}, + {.Mul, "2a53bd3c245492156404455392f9865f99e23f8d0f3f5b35d46012be560ba913926487fa803b49754ad1f5a1753e95b87ba80d6e03602a1c638e048460de99e4ef184c6c818b8499ceb987482a7d1defbdb7aa99ea86a5016cdbcefb2e76445322f605b4e907e77b571bfac4eb1f23bbc6acafedab51747b26536ab56d98c08251d0c2c035182dab61dc8e0f4c57a74fb44c441811a5", "c309e9a594578239b162528a8bd4e6fc11f7365fe62b50f758991314dbdfa7269d7a0837e067809102d55e0244b799a30cc083f521097548cd2cff7d181093ee07a838137447863c75999449c68f8b191fd715f9b2db75026a12cb9e554f663cfc42fb52593b7bffa0a229e6df962070ef7692ff9f8e12223d7841348e2dc2426c9b181e8176b5a17b4bd22f2d32b8a6c75e2733dd6", "203f6cb80e854877f5ea765a3fdd27915be70a73319cc5f559c301311b53c330d6ec46cc1c9caa9a7fcb268694cf3c1e3b1f61435103977d0393c3fad1ae4b6802011da488c86a21fa972a97d939b7154bd1b635b4a9a68675b10b16d9c8996611f667ce378d93438ead8045ece0922b57edfc388fb1308b307b55440c9553bd0b1dfd3b5978bbd82ae9eb8c5d517d70b3a1e3df20b6d73196de332eb64f90ea5b8762b808e77313ba4ac99a2315cea4d2e83ff8df67ee7d19455fceb9900b9703d6828cd382c12cef552d7a42ec6fed975571475ffe1422dc6116e8ed47c458319e4789e1f5382fc21a122490c11e2997b090234590935bff3ea4cbb4ca5161fd5178d3482c04550030bd236a23860ecdf48322f2dcb3a239f77c8a5acdfda348812a1ad5a66c73f7210ee", .None}, + {.Mul, "cc71aad10e8497c8ffdffe736dfd9d10169bf7346f2fa9eb4b8c00fada5860e7549d4fc870425d87a6faac076be0bb65ed67e561161be63a8dc2df32dc7812f302eef3a87ab369ef91970bdcd30b204e13326a1337dc764f57f1a6cb0af9324030464942089d624fcc25ee44ffc576da8f189bead767a1a678567b3092e3d37bd1b7becf07f38ccea38615e3ee0f092f57b047f55523", "d86658a4a348b69e332c11b79f559536c60017b045acd21efef27f5b0cd93476ab8c8124b1355dd861f1f9f877604be46cf779692551dc8f6e0447991e5efce87f2288c617ce152b75d1b3a2bb68f9213966c0443cbab1bb1882c0fa07825690ff8755d8c9faa77d3ffcf6047faec9e93d80f91053ff83676a4ac92751a7fe1b7ab8cd7610fb0554c52b426e553c87f7a99852009168", "acd1a435017b65634099aca9c99f81bccced99511ad071844015ba86097e8f6915b34b14ebd83d715c57149c6b7626748dea928928f35dbe263f13f4392ff2a2fda1f536ddfd9b148a67b3b508a3af0cfd2920f507151b98b43df6f2d3c2eb452e632ab6fd4cb967ac01d19fc05f0cdd611a42d42c331c6f9ec3c0f450063d11467cffa1bc274e938a2c7d9e44fc5ba7665f1ef45fbebc19833f43cd0742b488fb67b8e9dd8cdfe019cf0b8279efd48fe3321b2ab3d28b7da8047847fe2f1afa7a141f82b1a7873d3b213dbd1cbe45d62e00befd4a617e1901b2f50a7898676d87995313f4bf498b15f38424998933c45c6b236986561dbbb04032a9baa28a869e0d61239360ec04aee29460061f1c67816369a4ca91eb099e3cae94c622f97d033635604b96b56c66e36938", .None}, + {.Mul, "40b6d5ea3d3bdaad2568e66c3912a37f14d044f4dc6bdead7271f4fa06c29cf58605a99fb422e546927200efa216491ceb97399899334a7b1549f4992fcb9434a30b8fd5d4793dbeff32bac2bdfda790c1e1903085f566ffc77cfe490acd024cb8a0efdffbe33d7f494c02635a926bf92bab5427dade79f6ad8a3fa45e34acdac1087cf575884ab7d4cdab7ea3f8ddebadd0bd0846de", "da87216ef08babf17fa63a8c2187a8733b19902a02f5c775e8341022f46bfd40b136990b2b989481fbd2df769a26495f4011034981b16d8496573444dbba3fce71c49a782c7c3601dfdf33b92e1a587c78aef0131ca93ae45afe1ad63df65f23cdb21a8274cde413d0bca09f2345e2d972f69f7961ef83da0b0d35a95b58677dc9220855f5b06063d847d49b49043a8b0983213f1c32", "373ddb07e39d169bb6f14529b7256bba14be2c7fda1fbb4184fca608fe528af485b0df3aa7b6fb874d9b409c831c1ba53778916b31a8a491fc06eddba89788ac1c726603746a40f8805e58bf30e726cb705f9b3d49f18a5782515ea512e1c0f1354598ef06770079c801075e386b0b8e93b9d83753e4f0181ac2d68c43b1a0d8d7061141c851ede89cf4bd4c29b4fe10ae2b4cdd64554f5274f836d120697ec9056b2d434675deffb50294b822f50e6377d457af3501202bba0e6024580e51bd81b40bdf54bf906d630105585882c6d45584af271415c32e0c81908edc793d3378a223bd531a90b877e223e91d827163a01516be6bb4d360decc2a5f30a6d1adbfaf5480350f72e2d2655d9cc8ef1de8d954cfe658788650ff18aa3f0bfda6295c2672c39a0b6f37e2001f5c", .None}, + {.Mul, "-58f29a32aa870abf7020dc38feaa1c21b94e1f672fcdc49127b960b80c9cd9ad00c430beb2500ff7125da1c5901df127083d19600162de4fd48e51081919d67fc273a4c1f6c37539dff306e1b0231afc3356186a7253f9702c04cc984b4b875905898e7c982a02d52870877e1bc9fe6cfa077901cf0ad05d934f860dde50a73e38707995a72ccfae941db2669fc9b96241703eb54c9", "625929f13c2dcf0525a8c75e0c96da8876749e3a7b76b6a294ef93d05df5f10264ce34f0a29d4fba645cb7a512996644ef4a7c58f44941d21e7ccea0efa28427af915a0633bae2180abf79e39563b0f13b44eaa1cd5215edd4b239c80f3c5f8f96b289c3c37c56761983d336779e24d7dc93bfc1bc036221ddde6c4c4917a52364ee9dbe13c95d970b6316d5504a1b7ed906ac14b65", "-222bd9f1ace308c91eb5a6ce42fbbcca8c88fbba5c8d8fc32b8809711d14d81296f2d8212aa734e7b068e7f092597ad823ce3b1c0e257d73fa9e45c7cd9fc9050642bcdb28fbc52487ebe7d23d1db29b95b0aff05cc64944e457b1ed22be450c27bed4a104931a14c00c6dde1660542df0b892a66bc9c8ef3f3fedc0930e759961cc90a8338509667f869b0a5be69cd8e9fb528a0f54ef42ff1c9cd4d64e75f1f7804dd2182a70699e61629172365a72a7a1ab53946a25ee506a6b6aea3c929e1c906d006b8e4db54070cc83be0d0defd0f8b08d7facf945f8df467c811be72fa0839b840adc53ac6e654ebb92dcdaac758ca5d098979716e1ed053e59e7771e357bb45e8e6aa332c59b5269767f5c8344c27e8f26cee6917acd979f87b32cc643c2a4325526d0a338564d", .None}, + {.Mul, "788ff50c41b1004495893f753dc1594375631d802f4a155ecbb876812244617ac3907b9171f37634a9abf48745f15655bb3939ef7ed5d4e75c8f9dbd93f6048cd41b01bce7e9dc28573c2f3b414a1411e51a2c14eebb827708a1769cd5b8af5e05b32a391b7bc7b7eba2039061ea2787eb92a0626602046d010e570ed31a063c418d98d51f68c92552d4eedc98dc08486af1e4c61ad9", "5941b0b7165ea866b14105fbf805ba99a727a5420bbced163b2a8fd9e0b89c2814b24ba984ceba4ccd824e2e7845534065ff1898cd7a1555225fc5c1e61627cd17adb1de5a535c22ca934844789f04d1a77950b4f8a0a20268af6d702117946fe65e36a854a01f2da0ab3a82134e355ea1dac055b83474727c902a6d40d53b04ae39ec5d8fc070687f60f826e79648187971d303ba1b", "2a08fbf7acdcc32f6ce8318c9dfa66352f3d1f872b5ae287591ac44360e967fd08ef5da38c90b8165b03f61325d052272b34fce9f0cc03f395cd2730996965bcde4be5e9fadc7750e81aad5e0c6cc98bf03b215df6c234bdce9bb09dd7da913ec0aa7b85c5c3e7f5cf82a220e3e017293bab2cd40c2665c2613ae525683d2971ff68a47577ce6b1ed3c562890d6bf576a0a61364954328ffb4d46ccab7750095be3cc172e64dfa0bc83208460b61f1861c188c6c59255c6256b9919d9bd25384a3d2b093f676ff79e29a4109e35dc5ffae42211fae31bb4fd81ef4e26d7f3fc934dac1a8dfba5295f9062e6091cabd6a0a03ff54cb40bf5f2e15abf2ebbaac3998b617590e8301b5635ea08d13131abb009c9fd389afe2affceec5660b4c357191c80465483668f73bf17ee3", .None}, + {.Mul, "-43ffeaa74127b7100bf00956cfea2252c26eec5fcd669f6bc34c410ce10d410f00c8b942900e88abbd7e92b8d741089b1773ea43b9d6f843e9dcceb94b6a55a51c5ea7e9445d5c06889ddd346c4bcb17405bbd5e3fd561486c224887fda2ba96d10320933c8c8024a529bcede0db6baf8bc52bd870ff95e9432750ba567a464602f671c173b8bb81b6b2d873a806af5260b3eb3b577f", "223f979977149887b1aece2ae16eb5509b959e7d133bdfb6ffa0f1d308ec6a61fc90ebce2e775414df68bcbb4889c8aba083d22d77f52524b4000c4b20b30a480bd4ea7ffbc911e4a09eb36939b6054ff972754a3a34d5005c14c2b682d5fd8ab3324a20a2ea533f28ccad6efba95580417b8f73301f014ac85b2c632ab72b5ce851f2d5d24e67488d107f4acecd8c5b8473b21fb0f6", "-918e169accda3109f14aaf9b3cdca240d3fa89409d7db58ab928741c7b4a083127ad29e05cab679d55340bc9cf692ffefaf72bdcc9d5b2dc82aaa74e2ba4e4761b63fd77aed9a8e7b257ab5c551fa2b1cb374df86948edae6d80b340ae13667b1e09a7becf93252aab043528f24dc9796faa1f1c32bf1d3813b73b8a2cbee71f567a5f228a0cf39278de1fa87cf819a9da453e5b31b59fc0a80f35f8e717d32d63c9f48a98499d1a19d24b0e70eb4f6e0a855f5a5f5e95aad3863cb8b9db0cef6549e84b3b8691eb41f46495953be8c8fb772c92779c5eeb7cfb4ca04ecf75059c13de78f01a5112d6acbda1fa8fa98dff44980d8e2eb3f696a70cdd043b248041cc3f8b796c1f760ec6382743380f8a1ad26f62564d5e50a8812bb135d83efec791bedbde827afbd8e640a", .None}, + {.Mul, "-84353ee0ba4b75990fadef6369260f7a4396f36e4e42791565bf80d2fbb8b1009726a82ffd479209a7999f3c9c02f7c39e4652c910bdaedfafb389a18c5fb4be9dd0090efc6a8985f39e9809ee767cbbd678f86466cdc9de7ccd8c90ca14b5c17ac1cccaa4afa0fc2f190d41679d6d8db513b8ccf2a1aa4c888b812b974f76a0e8140ea79cbb2b6372bc302d6d53c4e4df8def32bf26", "1321306fcf072cec67984e56991d8a87530bee8ea808e85977f33ef2e1852048070a0908a858646947a4a6f9e4dabd159fe282c49546882416a200e2c2dd9bc4a38f34200a4131cd0610b57953f4c8876dfe1e5c823ab4ed540d284efdcb8ffb873465a81a81f8f7deeb20a6a5a7c29f04d18db478097d316e8c522626a318cea368befbb946f03607dd84028b6ff0dae743d95e0ed2", "-9e1178b8296c6531dd6663509114086147155e8ca49f7b1a0dbbcb48cc2aac70a0fb6a14309fe2f1bd3ad3c769a52690e0aeea1155a7c5185a53c8ef88d74139ccf68d00fa851c8d91658bcf788b63a782d547a3cc14a4797dcbc2903e180bfdf33289dd908b8b1a57f5a6b26b703fc51a791fff5e0ff81237d801c492c7d6e7a67d0ca59088e6e7ae2af47b98c2200a1c33375810f8e90fe0f7e63b3ed788ea5f0c351654dcfd1af0dbb2d4db0a161420332b22d0fc107be2da7b98f5b3ffe5f3c37cac30f14af9f659fa011a6386768b506ca4382def7c15d58818a532655b1226a11b190f413baadee8db98f2aa97b127db4c655b5fb26b2ac496b3e8415de31bf8cdba05a1bc67861aa737d0e307e8d248d24c042d05def8e3d505f219cffb9ede638f84f1e6408e12c", .None}, + {.Mul, "-76cb13777748efe8490381d80f263f55d9699a07934633b6b462e1a9da8eeafba0fdb62c98dfc11632b36a314570a7ade3210b73b9da4426368b39f42f332ebad2b560f888400ee4c137672a7d3b1b1fe7c629edef9c2cbf3a0f3355ec274fe832f88098de6b66264a26ba0334cd0dbbb2419c94d172d2eb9d280ec8123b91ab0f26f4aacd00835368120d15a98a266e25c20802f416", "798682795f24db437b0d19bf943892c59494f1f61f602e551aea8a859b2fce328713ba44ff3007e306dc7115b86b446a5a04d50e43bc632dfc8f9957d8f8a306d167bd71ce312b0e88c2a1a1bec60c3c79e97b203ec88d5824d8098968bc8df7a69f2900f22a50b0a91ee5e309430e4b8cfa272ce5f7d4dc6c0bc3110eca993bf1610eeb2fe998a9e606b9f9ac297af4225d10a4c29f", "-3864670b19ef3e23e55e03490c811d3d98145900213a6f456bdf526021a9469f9b0fc7aed1abe2a0c01fb355b19ba336dba2eb6f75cdeac6244388d3db43e3bdb460a19ea9cb0843cf6c25cbd5d254da9748f0d599200bcb4ff8cf8d8acd73b6cdbfb5dbffe24ff8772ad405d0c091fc92440a4e6a5c45a210799ea02e875138257e7d259f3b1fad99b5baf1152d2081792be3571a3defdcce3262f5ade0a52542666586bb3a6fb257a53ae8baa9ba05cc449aaeb736f7afd8fc6ec2e269ba30cab19d024b25f65e7f89350391c1bdf369537169f8314b9d4011151546c3a8f001fd29f26b076024e0ec9f8eab09dba0b04db1c1ab17d927870be2864a9492d95ba12d18ff35152237d349dffdfe7e776e8d72cd332c8c31d21b7486c5d6f01b697ce610164966b8f4e645aa", .None}, + {.Mul, "17d2042b34343f8f3e441c26f66273be29e751823dc1fdee002aba0b8ad094ec8753f3b3ff766b4d2ea1e3287b0363addfd6a81b35be7c1b1243c1e7ae0125ae55b641ab50240fcf63fd79ff1e04473935d29445b60f4d17c4f09bf1de4d1a291054a3468a7168070efff2878d7a6a249a7a1cbaa320070c69fd09f7b5fd7ff7f6ee032cb79986226fa8f76719ebc679e7049ee26c7", "d4278dee8428046262d662cdd0dbe6b8f44aadc7b6b5bba679daaffd045394816225dff62453e68c53838d3c6a88aefaa22c52b48ff0484bb18aa284f93eb3b15111edd65c70e7c0a689492ef75c219883121804729655f6dd220308e2bd636985a75d80c24327b5cc166f59e168398a1d09715cc0c4c9dfa57e2645ab6fb343b4019aea6a39a6cb754eb54a06a2185805b65d04b380", "13bd99a747a7e7e2fb4b96cc1e96bbd92024d5d721104f2f2b179bef660876c0f5212ce6b676e7bd65669fe4ea57d6b3ddebc0381b18f63a752d8a738c3c1875cd7aa5f8ecd1d90568630ae653cb4f780897310b0186323ab1eb4a1bd22cd585d82ae9626d1a856f6ead6a019e6aac799386e6e29cbfa6b2042f858326d1d4b9d88da3edb54fdfe9d3c4ecad367e3978c773340e448e0d06a955f3f6fadc8fc2c609ab92801ef9ab5ca9b69732ddb761473c09e6ebe317671cd928d75f65585fbaf7045b31c7082b3fd4ed514fd107d798ce5a46a1124d9475b8badccd1efd8b3bec5bd4d4a7a408f16aaf2cea7c4e94a37a677bd60027c3f69dd1aa493e98703ea3edae10004ebe7eb785f5efe01bfe0024076ed3602002eb3d77bb31db867390529fc1eaddc1f624c8880", .None}, + {.Mul, "-c307f748fe4ca6b45d07d7ab592ae3b980f31b29d026fec10ef829b2e845e1590dceb69d177bb4955bb4285941ffd1791c25db786493260a9c225bf5858633705980059bcae526ca9a7da41a5be8467f83433c54189b5d5551044e0416df6f1fbe3411ebc0ce92b2647b1da6033f22232df55f9ceb3d46ab95672a14284883f02d1f05853e1de25be517ac3d9c1b28317e335fc7a4db", "5a501e8b5e177f2e1598a160c9b54750689c1a79d72102ac35eb42f55996418ecbbf65bd0e4799db888417e7bc51dae21501f31d00429d224020c0ec7fa36d959a451fc72b85fd7e552f8c959095f68c1b3b5f1e5b71a7d8ee732ff9db0b99a29fb597c98b692d6b89e3141aaa312ef27b8a6592f33c62ad323f3b3b34f66f05e7fbc9f9c4393dbb3f6ca1ad8e21e73b3519d7f583c7", "-44cdd6b20c331066a4b80d6f8da41203af2a283fad1196fe069e75c63141d4593365bd9b94bd46ba7020ba80467168ea4adcf7e2e87824ac43b136422c4b4e3f4b92ec2e846f2ed2ab7b463da27b3441996c1cb9882f46fda9216d4e0f76f910e65b70a586f0c5514cf882fd7e3fcd0b4ded6c21ec873b3afad65156be36a0dc9eaf57ec5dafb540e3b9bafb14a9d9cd98f420ba9d1ec2265c54c7e5e789524b9301f37c1aba5885a8777242927cbc6a2c402ee54362ab38a7792ba148b929105db4bac295007dd3c762c2a34b8ba5bfe751d451cbb5e58861d69965eb499a65483479ae151cc05de0bcbca5aec9e6f9e854e38e37c598586bb24f964ae9653d26536e63ee92d08795eae93f15728a738307fb6673c892654c7a392c8af10f9975ec2fe0c9c229da5024373d", .None}, + {.Mul, "-1b3a21c15e19ae0a19aefab7a8b3beb063b190a64e7f6e8b2be0ba95ed1f88f4b410b431feedb4edb538ef3a3b468eeeabf7eabd4cc6c707bc6e9b1f4b73fc61cfc36415496188e7d5562f6095f695c195d3f9659cdf099c6bdc6a3152a764aef0289fbe4c0af263dc7f5107a7982c08af4122c8623c1e570f4191bc7dae2f2a9bf8b863e99bd35f9b90718ea9a9b936767d53f2441a", "a069f0534819b6b2a333e3a3d4ae79a9d9433999d072cb2141557aa6ed88e9acda7ed03e46a12823d3b15f87f736c14373fe0161dba8b1374a9ec91e27d0b90e875766c5f0dd5b4c85309f81b9cbc6003cc7f6e38a26e611843447902ba539f0b92c3f251026f7a6df74bc97c55109bf05e8027abe13527817a799701a61d3e77cb68e65e6ec6a6bb771fadef126012676be31d3c635", "-110f99800e48f4d249ceade95458aa6376d49d12bd24f536cd1146a778933460ab5414b2e2ead3a965ac6c1389be968193de81229b7e8af52440a7856cabb01ad559e346d5af33b1610b7ffb4aa7bc43fd94155c7ee7a03b84d7396f38714007e49093740aa22165b3534f5b17e47665359ceb4a22e726cf0dcf5be2831022b0192cd185b3b2bb4a40ec079808d749f395c19637d88a8bced49b4534a4c7570c02009be874e1bfde4a1f0a18e029bff276096aff8a0aace1e4f03876d76864a5c9a634aab731a6ec53867df30a64c7b9139884b1c2ed3565e42f0f0631d387f549bc753f42b4a47338f1baa89635354bd6ce3fe0e1db455f26764bd6a8ee03e50fdb48344b5621bc16b802b5a998e29f46346d098f931bbce76d0cf5d5af4a61ccb02dc14d578de2dd423562", .None}, + {.Mul, "-5245912aa2b4881688eae5bb197a4d08c254d23a90bf0960618b45b581ce40b1631f83eec3e9db88662b9028e24499f86c0f15c67a9a676ba030848a8b90607ce72f4cf72724d4c5a9cab43c24f02c7b0cc31db19b35c311fb33f39f41224eb2006025c100a2524ddeb3a2bfdb15c5b3aceefa9cea92ca2e981f48402f399aa97ed7cbc31eafb447a91a98c01248d230c9a5e9baea15", "6384af28b17077ad9cf25f14343d2723bd3a8916fd3ac7be569c3f4e29bc983eaef14aba332067fd2a44e9496d3b402ee0867e143fe0f7930ea14df0036e6aa8af74570b3825ac2cff9c4ed9f739aabecfddbeea52439c94ea1b230a55ae84c82dac55bb0dae5679534493d3f760151214a9a64da1cb5aea74b1f8ebd7688b51849f4b14085eca85d1d6b0543f83b019bdff3ff77883", "-1ffb8b4cf908c7ddd6e250604966beebb26d792e0135a3aca86fa2d424fd761c4665ad189a4d7f455257dccd7a8877608540d64c6a9d8ce9b395592edda9a7258cc4779dbe843344e1306d5643868738d2559fdcdebfe3f30bc1687f895f2b8deb6cf2a2eb5fdf3a37b92940e487f0d867c00c1cb023663923119556213a88497c67b2ca001808aef8066aba902e0b1f42d1b71f52142cb1371c386f8af21e0197eabc8aac9303fb9c74e97767d54baf0c8109542c39cf8a239af5846d132fce60d4e114b9aae0324a424bc160b175bf5034552573e79d9bb525c3d74dd3b7b5fffe7f8ba4b477b9b53f6adb7b4a50982de3b1243d5beb805a8f3dc83fdb23782713341f0be7e36f75a89f23e91fd1298a69d60017f2fb4dacc6046f509cba61c159ee3ded2424543da2a0bf", .None}, + {.Mul, "4bd52519bf7d655454b67356d1676bab7ce439994de8562f82a1b09f9ede205e8abf812064aa99aeb0b1cff4248c7bc64d6d67ae4c9837714b54976fd07751c91b34c49a4999fb0c9cf682933ccac5397f54e384834ec3d599a1cc6ef218d07d97a518a0782c66955f9bb633a6f9d2ef90edfcee2b53dc87b05ea9dfedd67ac1e471e03f2195820507df1370f7fd63f1928e9d4a970f", "fadbfcd286ce27833b664e7f5166637675b5cc2dcab99dabe6b17e92a9fb14dfc68f51ae5ed6ad44e23f731b1957347749c376f07d875ae003769bf37ddfd1346a5c6fb05245b74eae56e51ce46f54603ab973a313c3585de033fccb1d18ce08d95b9d1b5f3ae4de2696d9281b745356067c108739bf266e91d7035fa685b7d8620be758dec7cefa8eb7f9c2961b45a53adbca679be5", "4a4f50760f53af7c3bbfd74db052cbc70469cc04378986c3656a70cf758f106349316ef8b4fb2af1bd69e8be0de114e58e7a0296e22f404c0d2b9f417a8f1a922c1c9e5dc83418a171cf907551f463b212ed97c50fe1e633bf3f00b6679a2d14d0cdc775fe91b2562f7bcfdf274d2d67b7c03df9c2d61642b0c8f76430d9382c265ece02ddca82b2740db56c657d6cc3f0792f93c03ab51066b3d33bc9199311bad7d7b6a388eb51808e96bbe6aef1a515f8d472644c3087a14da9513044857760e5d7daad0e84aae331ca5eba7078f6c6b731f203346aba07065c4b225d72f32a15feeb395403cc9e6f0bac5db0979618a7cdc76587aaf90a48108c1410df9173e951807ca92bb49b6fa61e191dc308732b93f1085a46443e125cbe2a9e3971feeff907070636d87a38356b", .None}, + {.Mul, "9881dbb9012c9bd63e6353ae5b37bf6f820835488cd239d1eea441d89722d2f343a837a0906bf84d1b1aff3e7adebf673a7aeb9d096fbbf3c18790fa12af94168264fc09dea8f03c89d007204fb65cd8b93370283e281cae5207e3c1df4f18cc9c4616268f1f7629b4832421e409de113d84cf83991f5f92e8c2b0afe12b7d3e82d0a09ee5b75de2b48d85f1fdd97a1ddd524104fcba", "b3c0983599249d2df735a456013898a5edfeade82d9541a39463c1385b3704ca0f06a915ad90053c43c3afe897ac5b32460c8248b528868ce48e687cb060dd0d2cb5f28b5a450ca5ac01465c8ddd731d57fe21ee53f00049909259975576f239d5aa0a5f2c5939ada2fcd71efac7fbbab3bfdca471b0ceadbfebaa50947b38a9bfce26f3628ff8f27592d43690c557b6558a9930c46f", "6b1588b42f26d4a2e6a2ded6812c0086125b13f4ef4176cf9f96bd1f2952e767fc13cdd82c1720791da83bd88f060f28c361891b9373a60586805a3ca33391ebf8c4dc3500ec995349fc4cf46f4b1ae25adea2ef3acddc1a95a731159765ac79f81966bcecb1024e2da704898ae570427e3a53fe1b70e345f67379b7af1ac69579071db447a654cdad44eaf00f98d28011b6ce9ddf1fd27380fcf233ed24cad4ba52dceabd917010467d6c6d51c31db8a5e42108fedf992633cf6a5534fb889427fd2398af317909d9240420501cf1262dbec90860e2c286f013dc999f7dd47d2467fc83f11af1e7d110a780d8e57704c4cb55928586ba429c83b8b981435c5d66e1be6df06abe3fc29ad4aa0a1011b5d632c0698cc57dd211958692acd0f785266df6290f841ab08f87fca6", .None}, + {.Mul, "-70a0dd955719ad2ae112e6eeed6bcb9442c6548c08eb6a057eb292205e95504fe7195e8b8540c916efc890a87e4b56f6d7222669c8dd2bfec72c9024331196ef931df8a745be29af15a2d2ce556cf561029bf7caae9bec7ae665d2b37c051ae4ff8c5a37a792d9a288433ebf77602c533991f778ba1d2fc647a45ef45a70c82fd1d0182dbe19f080eac3dafc43cff50bcdb8d07e036a", "1b9aa4c3cff1a2cfd35417130377c56aae6e65aed5a655b4fddbe78182a1e3c68841f3c2f95f35c3b9425c3a99a63456357481c5f1ef090daff2dcfe737d2af6a12e7b02e836287293bbf172b79e6e4f7f8efecb7d23b14b05bb698441452569652c292d1f3d67e7988a89ee625d05255f3703dc8d3ceecdcdb1a79c06dc21086b42c918a03dabd93d4ae5322da1ad4b4b8d3a52c8e", "-c2500a13ffef1811350c836a7faac53f86f3db44dcb4d0d58081c704db08518f17a3ea89ccfab0c58b2137ca1349929a207ce25f4f573ff96fa89f8e0277e46b44f5144c6286ef9c0b91d690548e9d391e2acdc58f47ff9fd3e791689707b25a19d3a5e24cc02a030deb13d344d07cd13d89bb7c22cb842f2e862805121251bce1673645e03623a0002cbe6475aae9aa0e74a628382f5dab6e3a7fc33370b2281b2765b4b73540662fac79cc7ddfbe598f799db3aa65ed1263b522ec00b770f18b73eb6f493f0a4cf5a57a865e9440f6da44870f80366cfdc265efeb4d27dc26871665a1167879401f52b7465e50b16de1a6a1aeaa301d217ca151ce2cc18208415c340b5f5b846dda6078be6f820b4b6faa0cbf0129b8cd355417b542b539ee134708ec9f1a91dfce1ccc", .None}, + {.Mul, "-42a101f1d2b0cd16ea0ea1a2796adfe7dc365942bc3b0b9b347f96f87d2f5ba5ee32d119978179d989cf482f19b0695d96267c96bf5aeec6469ef8b744ae143a38a61141bb68223c0a1ed3018074f89394d5e444c18570f3a6a695717abe33774d8ed5e13d91a3df2d5dc78388c6972eb688b9376600ab7a2e0e42dc504faace56f201cca3eb9f930e38983f9db3e0c17155a4d33846", "2880f840a9b885318efd589538507e52cc22fd44d5327d5124cdfcd34ee4a34253b803b9db80fbb962c3a7916937998f08dff0d993edbda8993c7a04a57c031bfe62337c28d8f8383ea947dfcbe0ab9b97e6bc4018087b781b4957d0caa6b1809eb41d0d325c9064e91a6a7b8daa58c321f6b64770112acac04c304943cdbf2a3ff1ff013840108924e41e7d6943533b413a463593f4", "-a8ab96b902409aea8da3082d9b7fb2701de9b423fc3c6c8f210667a8cee0b82ac5f529f5dbd59947a10d52a7c1692af036dabb3e0c82bcf93944708c15395efc9b3706fa11db1464386e474634709445057d2292421785cf212317dc6df4d89ebafa2df1e40ff07abe0112f69c90e977f293ba34be764e7fb8dba41101b3f1021a14eb574198da9f31a8c1d79ea252cec30d05c4cf7dc8497e14764dba6ae8ef1d91f80ae8bf8d4c684c502578fc439793e35ba10a47bba093d4c00bc20fa85216a37b139f2f988c8d6206134259eefc2597b33a21976fe3375ffb6154a0f1a280901e7509f7cb873d3122e5ea8148e96991cd2ca7c57824ac402767d65c69a78852ccfb010d74fc557f7ad354941d222a2e111b1ffbdbf772b5351cc31dee5da355b0ad1879a402d1fd4b8", .None}, + {.Mul, "-4bf2f0f9808c2b6f97d3f9189e3262904bef9ff86362d6a279d14b8a5365a4f13027bfc8edefccca3395ee26ba194e147d5f87d2c48d507b3b0750245aea56f2c9262ede92995dc2cc175348efdaa6f2746643e467a2493daa2ff69132cd4d658ac3f3047befe378e1ec0bbfa446abe432031b60de0633b4372ee48b8d724fee3ee38f07c694e41d6c68479c28fc4e138b746aa19009", "aa0bc3826a0cd24da9d2ec15f9a0ced193ac0679fbd160b5c418cb2464c1340b0f41063d8e2c42d6357fc153086f9f4e692d6b5fea9cfb9e4d26276d2a13a2cf6b508ec407d75d28617fd4f7237e78ef7dd64f388f68d2c04f43c01718ceef80d715dbe39a68db5abe25130eab1c49a4e2cac851f968f430881fc75125fbff9718db96819633a533e8298851e685bb633edef831e7d0", "-3272d176c8786c0af3ef844d5f0cc305366263f321848a7104609fe64ab536a708ba2eee9441756568942da1f580387b65ecb4a5420b5765718208a26ace4696d09af97378f03979013ee340796dca417170aa520d8326aa930ba6b4b7a69585256aba2042268872c3e9ac63d7b2b9f30951b7dd30f839d20586dea59bca1898d552e47779f05fba15c6591917d2f6da587f79d34fe1c21957355b338824bd8d0ac3c722ee156534d3fcce112693fca2cda4edc442de2f37e029f6f4200b39f5b62a8bbaff77be4603e7db9bb804fdeab3e2d135564977e5e26da86b5978a2df8e462f4a10baf3ecfc2766eda0044db7888011d0915f72135ffd89732b8941267534d6e260b17d3db5bfae4ec85aa761ca0ab3a614b7c490d2352227d1231e6eac9e246f6ac45d11b5f62650", .None}, + {.Mul, "-9afda424466de1d2bcd073f02ab727da0a535407c9cd54025d1d630c7fc3e3edd0f64df4d76fea6bfa19d5f67d937dabd64646d6f2496de387edcb72dfd566bfcfcd84e8ec97722d9f14193f08f8909b92aaa9c4cc8bd9100b50981120c54b67f0bccd5dfff24a76bb06431a80853cd25e7853950a681fa0b6cf3b04261e05f9a9d1bac7acf1eff7226496a4dbd50aaf2a60399e50a2", "36855a032e8833f3894465374c6126939ca388dd9df2564f9eb26b90285e3e397582b4d5c90c10627396043e5a2d3eacefb1ac7b7fddafc611f4ec4e7ac04223f7a5f9353f13f06d20b4817c49e9455780b35e2952c7464829c62f2023059be4cfc090cf94ccc70a2de29d42cbacd0e968b89c14e3902cda5f7540a71e8a587f94f1f7a4b82dfb318dc00ed3af77d8c15c701eb98063", "-21023ce5068d7b99ec7c238387faed6d511072aca61f0db0a43208d03ecefdc7d40cde445aede0c47701276eb7cc10bcb9e12a1f89710f3cca1a8f1478abeadc9376ab88612703991243ad0c4883bcdfe633538b63282b937d1418dc24ae7e9b0c014008e68005684f5ee0b445025fb5249eea66914dda58e55fc802681e9421b2129004768141105ec422327442e5511af72ffb852d1daeafb607a18a730b85a32886571fb0422fab295939ecacaa1fb157c30a52d05d7d8d3d53661937336b2276a1ca8614e2e9bb4bd7e7eea567c8343d6518fe25009059bfa2b12a862cf364a362efe76b3e2780a0a22037a0b3ed9f93929c719037ad51a48bf7461db53c5cd01ff6674e94fbcb336fa182a23eba2c09a18dbc4eb8ea6358f0da39e0b17d9a2324c731972fc0b19c2ea6", .None}, + {.Mul, "6d6aa99e353102164f2fc45d79851c76415996cd7f8d7d4b22d0c66d5fd6e7ec32311b7fb079a8e05f0c540bf2ac42523c26bc75c64ca3156f28911bf97c94be3ea3258e72041075c8e971bfbf43a83d4f4a1ebf42aff8c19760586b9b36b0de2ffc6f557b5e01f3c38979c942559099826cf5de05dd516cf15bf1774f5557c16a90a4b5ef1e9052adfb9a87c89dbec494e3194a50c0", "9dd3dd31d82eff648135ca9344257ed019ff57804cb2ea7db932bdfc86b90dcc9d64852a2205407e15b7d548e69d683c0fb068a525bcf667bd6a9e7a679f70acea12d8b458a0cfd450a4efa913b470521aff1e021dfb5bf982b7fe4543b8ebd754461f0be7db3fdc33d03e47b342c98760fe11c27bb71d7bc875069ea8dd3ba1b494ebea21a376c7677804ae0b4c5f54b26a112df5de", "4374f77a364306500f49b6ea4e0bf182b0be82921946741a2914303c7d988d5e7a0ae53de6b5312ab814ea695a5041346f9be9d776b666e5f84962897746b6b08648a1bc3bdf3516e6b7e76850046e54f59f5867df66538bbc3a4bc0637362a8abfeca6cbf8ab7827c974145d577a33c1c2f381e7235cd776894ba866beb127b0d4d2cfd61e7e1dd97c3d37f0476c5f70558ffe017d96fe995b3c669a6912d6d828a6af6bad7568bd09115fdc24048f7491e56f1d887fb52c88dbb45c53412fd88cd173e248e3e35f02c5f868e4cdd977f8f2b96320fcd0a619f85813283f1408a568dee6308b5c6b46bbe9e5ed6d753185e09b33f03152bef1eb5483ad544c96381c136ecbc632e7299cb776d8ddb87032094cea2464b6eec47dc2d300b8e4315ff2dc6b57ac510ff79c680", .None}, + {.Mul, "a11f3b5c52865d2584266e87467f78f5cc8880a69d5a9f400927cc76152a5f814fa098f84a40c9a9e8b2bac123948c22fc7a8021b99365e87bdcc09ccc8738d6a823aac541ede21b8257593a1c81247f0bb90d7a37272f942898191db50b290af2d8efc950e0a811d3010c683015d7b1c716160a246b390b4a2cbfc12addf685cc5d285adb23197cf377c6d4b20244e5ba76de45c3b6", "8e878d1178abff65e0e580296a95c9d54c39a9009666d4e6164fb08e8bbe6e7678e63667dbc388217e19566c05638ec71e238ef7e6ff011d863d659034b66843a17028059bfd90d52d52bfd47fd3e1e95d208a15e15f3a90ccc66158768efb8291088bdc05df31171826b4f345c1a8907e1bbfb33a9fc710f6f294f3265656cf68730a0243e8fd3e9c93c911d28f1a19703682530377", "59b4a32eb62dbb8992a91d6f083a6693c594cf42f868af3556878db67a54d29e6f7a2d9499c14453d7b8d7f5ad0f81ba26dff8ea2a94aa1b49883e670ac9eb1099184a82bfd02017ed1afb0016f58b30c0f905cea07eed3300e13b6ddf90a5c4c2259ddac0ce141cd49097da804a35f73c399ec8840dfc65dfd620d79920b22c2451c93e02604e9f8b61993738b539e825d01b073a28eb99e7b6e30cae60ec682fc558c72bae5a54e73af1d395044dd08b5385daeb75382f9ee234b3028224e94987bda8023f3e0a231794e6117855d706b5020e2620e6ec5d7dca40c2c145714ed70b61decfd5eb0714bac034fdb549e5889fec92d1ccc3257c647613b4ac1ab138374afc1e87f28db6fa4637f1adae9ac8fd2b48c941f257d54b43bdcc24e4637f84b48a7f784103bb1b9a", .None}, + {.Mul, "3b2554dc89e7d517c84089a1416c78f5927460ce496462fc7e3cc41252b18fe0bfbd11ee15ef5d86c0965a6382029c60b5b455c4520a2f81151648fd90f852a0b8449459cef87c838b78cae2eff0fbbbf0275f2958e6d381e8c49a9b647a4544f46c3030cdbc0958dbda73d0eef3f65fe692cef8b9ac6ead9f59ab752db95a63ad6510ce9dbadc6f236bb718c7fdcd3b806cea04a5a7", "c25d02382fdfcbeb7474d6ae178288b01569956eeda8c2d0f773a688bcdfda86b6ff3b4baba92c95bd00418cefffeff3ae39c59577b10687f63c3a0ebd76f636208270b152e492497eee72965bb1bd10a7b50e8d65a01b8e19302376a385b0778b278689b2911ed284b4eecac3f2b5a007c9f5c40cd16188128f13412416720243f5731e8f5e6cb2af8db7ab1774b79b66b41c9ac5c9", "2ce7c7623a83a13cd3aad659bdca2de9fb0768d40776f4af9aa6f7569b2d2c9ed745b29e44e5eb2ec1666af365199c86fa75e4068357ce3813a78b6dda77ebd03dd899821ac2aadb51f1ed68a63a6192f2863f5553ac2b9e541e86d1e391b5afba2a51f4b391e6c40e72de3ccdcab2728f0780d12cf32602f33a5b2dcd02d38823c31c3f5495739baa86f74cbfce8cdbd50c96c70b5045edd00dde320bced1ff903c189124265dd1e865a7b6c0559a63053e97960c96cfcbebb96e9fdee6bd3b8b088d38c7f3c7658112d5551511c4a54728dd7a4dc53364d0e237a7298c5434d35d2d9f602af6b44d13f2dd52b6b9dc0c2fc93ad10c08d5ff00989857ee38443bfedf78b14a479ecee7658c77f67b3de02cbee31c8ad6905bbfd11f81481c30024212c52b0af1ef3b95931f", .None}, + {.Mul, "-cdca214817e810f835760540a74ae69cf31b82b1a63c499d6f39a1dcaf3e9a648fe8e30b7381df412f997df62c2c21ac6dc6c088b6b17952f6ba53edf5463fd0c84193bbe45cde83a258a11626522f9113e27d90ce5a069c339f4117baf2de8cb8fad7b63891ed43c44654e3cc10a3367d4b525249137dc758b0520bd260681afb439afd3a0c03184907a7d61d61fedfc075f1a2f174", "6277f38b34132b926247f3188814392c1fbe24aa39c9f7a2bf99bc5c4f86f23fd7ac84ca5874eac2d8ad9bc93ac3103e07506e7398824e2db8c06d293122b4762e473558d4aaa4fcfe718173f4df9cccc0dac09dc5254ce6d49bfee2cb99167788d85118e60395e36c450f0916f515b98f7c5a1030c05697f487cd74b08a3478da7c8ac238501c58d4058213a14cf568b0c606a0360", "-4f27cd79d5ddebfee8091167f3b8a11aabbbac50c3efe496450471a3f41be92034d7b7ee1bc7da1654be23613ec15e6ca134800811f9aa4e6e8a1a3c40828a3d2e2a0778a874bef1d2eb96217e72dca5e3e7bb3ffa821fcb1ee7863dab5ff4af8e2dc0265e7d78ff3822e09502f6efeefa028c55023e5664f7c143e5e55cb0c9b44963127167499aea7e2984e28f620c7cc76853ca0c1878c11701663f805806924d870370126d7dc854ecaa7bc2850323d6896829bd9d11c180d06f6f03ab6c986432a1045d0cfc6da53e3d6e4d1d143de541a69b2153acb479c8efe96faaa1f426edb095b0a68372d3c06e2adfa20d855775823bfa953befcf6a57cb60fc2510d859b4fa2d31a349c06455d54845e3ff98b3e0d613d79f7ba9ebc2969913f9e2cbe52d4520382fff6e780", .None}, + {.Mul, "-7a5da82875eab9175866f210e84b343a8d74e373f9447e1b5be20456cfc9634449cea638c22eb400b135e07915e0eea568445f813c8e4a00f892ec6ffdb0a2bc9621ec811c40e029927c96d2b8049782fd99142d75fecbb7fcc557ddc09a79d865a927acaa046ba9b38484b1fcd250b9ca25e27dbd6436d93b73237912ac289e881dc60938ecd043aaa9d2074c3ebd3f2ab2df0c9fb2", "a957118fe42795844de44ceb8b6f60643bb0df90966197eaea5d2fc7c329ccb6d9c8a1349d898d0c4f72e54629f4c8108ce634feabdf943a6e070d2dc4d729487204e5f5502d3cda6fa17f362319d6a858cacc447fa18fc157ecf1b930dd32653e3fde2b7b3116229afe9269cdf4ead931bc159738cf446b9418710e0ef697df78c31ad0576f42960fe8f83677eebc1dbff2db48ee98", "-50f1723bdb21fae42c47828e60c531874cbc6c5851fee36af68741d3feeb880f64079b5c87caaa3773d17dade0db6d3d2cbdee8baff42c72aac2c3b6cd614a85977fb77539a703853bffc6667f7a80d41f8d888a63facca01e24bef025d41d691a98ddc8d1e32e736352bd26c2c37f478d7ceda4c480968ee81f1d90a4360981d3e8b284912ebff3539c2280eaa9d9ddc52761ca888920301522d8b26ca691b215c9d6e1c27716f9770a285b3080bf15a082aea4eb37a281b3ca29ea47e25f44e955609c962fe727e70eab203d3f3c188e95f0873628e354a5271cd241227ad10d30c2a151fd4f663476e7b5e70fede3f5baf261ce0a094a34d366e16f8e02d30f0e2b979b8cde7635da0f47740733f813bc2fb234feae9fd929a037789f830b2ee86d2e3290f2005c064db0", .None}, + {.Mul, "8cf0fbef0b0d0c75c93e99f148831375612ce0162bbbaa7d3a9e873914ba254abfc41dd7429acc695c184921ce3f4a181906f07077b679ac904313601935877f7643081ae4c79457d118c2d1bc14da836c7156eef3fbb6a608c91b96f8697d077f2b4dc33061d7c4e6d8769a8a1f78fee76fe4710f4924ae469b7c3952f1fdb0886b48742443fcf99d46ad70243c0bd881f66cd37cbb", "32574ccfc552b96c9d2f33ec277fde6886fd8d16e6be9f7569dc0a6805a9fe612f1b5943ff15646c3bb0c8d4d1f54e68e60e94fe8d9d7c677692cbab07f35df5e7bd1391438efd110d3be37d5707d7c9bbd3887caccf30800b7a0a2d4646494e57d8a760fc865be52bbc46d372fd15f4ecb9e65aa745900662d0db56b5bba5bbac2d03dd027556195a898dc6af4b5fdded8d107a206d", "1bb721643caef895a4ec0d435a57609871e5e948dc80c456987d6be733c36b51297d1096315f5d885523bf9b901e7573161836573e0382b329cf236cc188b4122892c2fef22e5c63467be6d5892a013e347d4e4a76b6c73eb677da06cb3eac739bb6c05a13a4d67b269cf8c70577956674438622e7f4b73338e793ae75bf1bdd54c5fc8464761645ac57a3c6f17d83308b3f0ace6bcac5218f8cbcd5e866e7821327057b41e92ec869e0a57b4be96cf209df8776d0e9b0f39c389e789a9f0916c4e8a0a3931d49001c54e064812152f68031456add1a70d39bf3f8205fc2da847cc7f3ba04ff78ca3191778616b667f977152e236c65f28ecfa44447cbe544c7fbd0594679f20c793d1b0aa81d7ba6a72349ce9f15f7394a147de4fc801a4196692ca1783f0f0a1ae6c17b9f", .None}, + {.Mul, "33a349b9299f469d988fa36f0bc95de465681cffc0e3b331299db2a8f5c0294d0d855c6fe7a53ab7ce8f12a89e4e60fec9a8ba62c225b4d24571115905f71b45dd3bf3ba732ec63434176dd92632389abe6baa31565433a92b0939e02d38d9b01f020b03474813e890a81d2e7578423cbd4fb628853727979c4ed635176b5298a5381780a1843b3391834c02602e3e457841a799e677", "c7ba457b946c207ad60aa5e08dc02421629409748c5bfd76e8f538e905ef2c95b474b8aa9795ac714a6e89f0837d83d657f72c83fcd05eb41fd7c00459233ddbe7314d5f475fa8a387b86962bd19f2828bc290f97d763030f93bcdae670efd1ec0d33457440fd37ad580dd5134fbd3ad59bf9e2b8e0a22011c56101395cd52485192ee4d113d77269b00da9c36af6de3d9bb0e13dbc7", "284980f6702697dc140a792cee569e890e09aff1aa0e4068a0f6cdd500d4720566204716a0a5681ac9158814e40d9c7cac822bcda5e8b142e565d0fe40c56f396e38b8e493f05c21936cbb186a4b1467da957cad2006eaeb9a9cd74aedc541856e32a44ab11e2876a5256c1e3ffa5f91f5b2d43759a48d91cde902c27b897d5a89a4f79488ff3fb7ecdd3ce55f5b84d645b2a0dbca100662053b5415f3135ff6edb44577eb5e1f2ff58f3f4e54ba916041c7343911dfb4c8a9bf8472e4213368f26ddb7798d95511e04cd515020394e2823c19a7504c9fe4d1a4f90b2c414b011280e9285861fbf0c12cb670612ed21cb8828bc4bcdb76e6fdd837960c3a56992cb5c2cf2a153e5cdb49ff7d40a03cc198c96c32c1c45aca685e7ae8bf0ac0298e8f07eb4235b85d8d9ef381", .None}, + {.Mul, "ffd42b2bf9b4591e79ee307fc3b3bee0a56dc6768c094680a8b09cfd8971986380c166fd4dda8af198fa1b20350ba8a5510dd54095e90f3b9619d3cb3bc0831808d874a1e583a5ee266032fd0c4190dffb15d4c640b4340fcbed1162b37c5e7df0a989b2e9247f15f8fc05a05e16879804685e96a8c61a3f87fcc83733382258bdbee44597ac557fe706a929c5814c9d094f857b64d5", "115e307d5e8d0b61eef0b158c7c0838fec74cc0cae9040740c5cbe04dc4cf833a8e4bab3d7199ff550b44b21410ebc2cad6fd86b91639ad40374e4efa699af1bfe7ae986dd38d9bf7feeda2f80f1bfa86866b4f1c2bafc49b3a0c19e9ed8b774de02ec7d672f8d37edbc8e3b06c1fc4f731817d644db85df88a9004db8a55455068a403f93f9ad8875e8cf3b8e5a28333b8dc3fd7d13", "115b373ad6e8d88465fe9a24e6cd7364b320df019874f8c4e7709d25e0d6fc97c6d6b0538de4dcfb8083d1b3af24d4d876edab169a5db90ca84267a20ad45f427987ea1190f863e4872e1866c088a6e004e512d7341a086731974d3b56bbc48935cb7c47528533e23f1ab293e9b17381a82bef5c51c29a63c759d9ee2f4a24b1c966d913e74ce41b3087e715c901c6fd5738db364049c340631e30df434683356120b473b51e1a6939936a1fcbbc61b19b1ba8c83e405183e566ed5ffacde4c595c343d15566cefa3f99577bffe0a07e4407fa672f29c4f344902eb4c2bae30e44679d204660ea14e8e77a8db78d69b773635cdde6fc1ae5e89543c54a96e5c80f9bf8dd776b273750bb87087e8befdf300263db216584f11275975ee5b06d6e246b0d13771a0e260de57ccf", .None}, + {.Mul, "-7c5fed386943bc1109161f07c293c2f26f1d41bed792a0d3d05bbe52728c855eb4c43f39d82adf20bbbfd84496b7bcce49aee6e0a612b159b5cc95baa6cc9107a3152812cd493c4840fc809b55c33b2f363a4426b2a21a09b8847e8978302d277e0e3e8fd07c08fda7068c088e81756fcf76527497dad72e596e47a17c4536f0a2de353f9217d82708fc398b2f5a7e8cb4db2e8b4ca6", "bed3fe82555ec696bc909735b6ac427c69c6a25c3161aaca028dfc1aa478e25eb1d93a888a48a72a211115815cab5d581a20a5044e0e942ac103c554e8a11ee12d8bb9afffa8985c011fbf2930190d6c4d14928adba16857a0e8c399ee8da287429077af3077acef90184625f39eb14113f3b6548d6cdb3e26293355bdfa1676a54523ef43203c05702e263a4aa98afc4a9eb703fd75", "-5cb630c6e32d5cf792bcc65837d0c74a231f0a74c360bae539f2782d8ad88c315155e35082911a3f70291ebe653990742d2920236f4b95b1dbe90fca2bb7f5a10795293455d75e01dae7de8a73b05d6c93101505e3a1e2aa6e57e3cc0b5563bc6426afc227a92c8811c7d0351c7baca109325fc644cad69044661e7a2a14debc475424ce10e728497435dd498791327ab53817aab4f6a09414ae1c20c5b3683c313fd955cb080af5b50b866cf1481f00a9a6558cf74543855b62c13338b4167edb11e3954a697bbe57c7f09aa5ccfe0e1b9d388f3b06925fd287bcd1d6af3ad5b680855e8e23e1e78481f58f7c13ea72b8dcef842278571eff6a6e448bf3f6c69e6254f52e37f5677d708543e81de6f53a9ef141c8a531248820d9775a3db8f90ea09d1d9f6baf0c805c15de", .None}, + {.Mul, "503a05f4805cc8f0aac2caabb6003b15e26dcf90b18f8cc1cec1cb8de7aebe859b8a453f1af6cecee682b0bab629d929ee0646cd310a4cedf14ba74200d75bfbe5e2a93aa1061f6a73c103920835d59907bd7275bc5a425cc2b9d092f2d6e4ac025ea4b5aff702be69c6277eeb248952041a4e5524fca079a7ee976d23e6bd99775be1c3d25b03203b871b35a9d13b5c19efd24bdc6e", "a29cdcfebbd06cfb205318a5528ece96e56d010557d126c28b99aab46d075ac98948c5acba692fcaf1e59f8db72bbb31f492e4e12494a3b8629a1377e2e95dd08e458cf04ef2952ef02db4ae4a12c52c978045563590c2a78a312f0965c2d3d802290d8326eb767790302e7d150e18acbb83b74914c7df80dc12cdd3fae03d321ceab57b3750eac602619a4a7dc38843478a5b17f040", "32f5e0620bc4aa3f7569ded0cb6a994899051b67af06f22f50575c7f9b8673bf615b31282c8b06084e3a951ac4bc14bcb1050e88c011f6ef02c3c1ee63090a8f53dd6e0bddf2c964029edd1e55e96911c77b4b6a51a1ef71366b93126100155218807f94725562f9e4dc15ccd22920fcd4f50663dfa4abb0051970e789174178f71b2ae885df2ab9887cd179463519c8646e2841239a40e9840be091fb87df936c708e336559d9b4f9c0ea9e1cc8f43f23586207c870960fd5dae91ed8dc07ab556ccd812b4e60f7ca2812b86b1196e5941f6935adf5b297f9c412323c9adf17c11e80d544bdba2a6ea07a226a04a0ee24c04ac435a90703b7086ae39f2e3ead4fab91fba5b39bd9b30c4f29260efec251068a712524cf8151dd2202c930c32d990f21cd4b75829399803b80", .None}, + {.Mul, "-bfdb8560a755d4926d3c6761ea9a48ee97a18cfdfa5e07a8f440e91decfb2882661784b4430089a03cad604f5b5d6b7f751558612e71c868907f74bee634cb0f34a14bdcc2bc0f2e69a4a150ad6671472a5712bc635c30b6116d6038d61125060230b4ab827be22dc9e0c14fea6af7b83f53666b002dda44da378da00c48fcbd42add04239a7e343121639dd502d9276cdaf657164b9", "a1955fe2a9423f7240d78d8496c50e21db88dc59aaf87609a3b5f152609ea67ee7b9ae70fbac038b34d7ff254bf540206d4940038e8f239b05737d5de055aa547c533f13917ba61a49b99f66156f631b2d59bfa58d310019eb290bcdd3a5a0c162069fbb4d51b8da532640b1340151c843f7042b1007510c00d2c07b518c798659190daab39dd6d87a9c56fe66246538cd8bca7f5592", "-79190182bfa28e433b23f96d2a4638fa0220402d4966f2ed04dca3b675204231a821eef0aaf7224530e2bdff747c45079453b5a7a3165b6e70069a75254ccb1959bc757b2a4664559223cc3f9cdc797b4d75fe0da53c31c9c3578b5fd9e4de53d75d727b98480b18bfa6d79d6fcd145cf4bfd7024045777bb8e5ff0561f63a28692ad70aa3cf213cb7d46bbf66a815f465a66f25228aff93d48dd1b885c5783a93d8469a9326760d6a06aa9ced75ec5f5c128e1cb637f7f1a2896fec6215712d93583373efc47b15cf2cc25723c47fd78689f3864365e60723e46adec5eddc4667c972ac554c1f2a1e9c8d658e1892e4a06acd879805dff18521801954faa94eb8f6f0f3b2b2488b50f59adefaa82b0b9348344f9e77eb01a9a1fb7ef90610469a4132e251cd2ce472e3de82", .None}, + {.Mul, "75c56c9929140cdaec8a19f918b07b5a7b1b221f61932f1a8b1441572733922c553cefa0343025324cd57df6257b42a366a5d3528c07eed2601a389230382628d082b698dded8d34dc58f7731f9c41542569105534d558448955c3f246139505467959e2d58ba49d7141783c5f6dee0bb265e3fbcd04f2459c87894b4ccfab299cd7f442765285d662c5668be54433de397ebe47aa08", "a20f50e966d97ffe517d0baa12648fb3c58713b34f3da0eff2140986bb309b9d3f0ac0f189b58713a396f7b4088a6e89f922625ddcf3aceba4c2acac757e4640f1a7ec5221504a134b89391a0ddfaca7a054ef0f7f28cd812bb15dd214497d972e1ea1099e1b60609c7c6037bf46f2fb462696b45f57a2238e995ce23727e9945028b64d2f3ee96a20c1ce33767dc3515b2ea3cd2d6c", "4a8dfa835ae8850bf637e649a321bdff6f2baadc298a0fc8cd7bf28ad8e6c3df606498f75bc842dd13469247fe4ca95b70b5c7dfdc8a9f2608e3341766f31d364b19f828fbde7b46ed7a8e610e72b09333b6474bb2ba36ab1c8b6107aa1a7b0f0acd43f70a3744ae856460caa91329f9bf452106fd4b825cdd753953f2cf1e85af21bbd1c762543eb18c463855dd43f30967a1ff8b4979f3dd9dcfc7845abe6275edb6b45e5f041b3298326d6be78c8d9f1d413fdeb3d3874d715aff7f60faa5ad08e1253022924f343a45ac767a19031ccac0cec06e3cdbef532d488382e6bdc71ccc88e4ec16a81c824e66b87868493f83c619c6beb28df1b17c476199d21ecd39402fcfc68bb76aa3b36844042e212e5b528266000ea61f046a2ddfddf0d52c54a0f63e5aef011f872360", .None}, + {.Mul, "bed73fb9913c0b32e233ef3cce71eb4aa6fc4482464afd163f3781423ec916428c3da8de893ec7d5801b201ce8ada44c0800f9791b68246b514d1e9ea08ec27c8fcd6b946787ff6158958fdbf17c87a493b1005af9fe8290aed60de21c8d900f32e7cb216c269e433922f521ce4114a37c62bcf9f26adae8355196e82b5da0c93bc5a7e7ddf47f47559b4c29ebaee8d0cd81f09d185d", "1b52e0fbc81a969acd4d4e88a28b1cde56a5650738994afe5909cdfefb00169d05d7b14d1251b74552e76941bb7c8583d7d9b902c840980addff0b8cdf9aa5039b89a50038dfa82f7382d4a07086a0c56f3a19a4910164ea240bc49b954f988ce927375e2d3184a7fe92a5283078e0248d351a5a9a1c08ba0f46f5c1cbb8cff6e5ea7f0c07115d333010d5177464a41ac72e4b0e76bb", "145e7c6305bbb05adc022893eb211679869eb85f74a1e98394f0d3f8034a077412f0c4f6c8985420b91585263baddc417222fb66252539a264919f42835f12c1e3863bc9159e27358055c1a3b8c37859e17e39007723651b6ecdef04b742fbe603906dd1aed1278fcceabb122b37b7270893cff17a4a7f3db4a75ae7473f9656bde7d04e5fa5d448b0b79d82a9383a3587b21391a7bed3fa3b96f25f5e3deaf5ab576a23dc5e60502c53404d179ed39d43884c5b1de9c9dc48b9694f3f1dce652215b7057de0fc95c28377441e1f9abd836dbaa88833329879a64a9e2dd7b7f60a9eb46168af6910f5f182ea2bcd920301b6b84b0c2e365d4264793ea39ab640df32522d46b15f841d14bf19d8dce5f6ee9538cd5d069cfba632b8b98f7eba2317665afc0575dd43c011a9ef", .None}, + {.Mul, "-ce42a3a7eb13a569872176e56e14271f4eafe74e93fedb3d0adc23d9000345eae610f9c35252d92d8805ad0e77201599c1bbeac0f8635c9c8269c23a6efbc841f294f25a98d5df6e34edad73aed900ea679cf2d24ebeb69c36702c0dd5f21d2da362d901a939750fe6e07a2e947397b7d40f772b0c452148770be0665bdc72fad146164604b2f5224f093a438dbeeb2bd25794ad1bf0", "c3e25036dd42733c752daa90ec4a3423b14407f5d2873a8801fb16e6a825a305b2a0fde602ad108799d93d86d98d0c3ed22222756fa066d8b17ed2f418f9731f6a0ec82a621cfd6b88b2b917b9ee43d6fe348df6625b9a72f40be3a08f2e65f727897abf7968ecc5c13ebcaa6aa33abcefd3cad34ab907f51f7096479d4666f72a198273ee4251d757be4ccb662247eb31ccd233ae11", "-9dd31a1e69c58e87efb44259e1e04ad84e1dcd5342941e879c2467a1a38cbcd3f789775349e54aca4dccdf322ff9cb60569860ea3c0545dae2e05aa1c12e41ab3caa47783975b83d3b116aea651aa073e1bb04c64cfcb4b0e3d988ad66683910d0d3c1cc968058347d0fb2f646d3e42feb6dff6f50f7d9dcd47d353fb7f6edd37f0ebed80391aaae15bf305ff963310894edb88335b6b27fc8e981f6b921cba2de1f1f1d23d8c760bf93184a81097e8e65826300b6eaa800cd5880c70d1eac6f1010acbc2894b37a3bd6a8a0a5df48344db9059387e1dc4c6b1553ef34de3f05774a49b77828ecc5f3447d5a713bad388d32f6ed0175b6559b8aad166a73fcf2c0882d650cafd61651a784deafe37fc40837548a858e48cb0d5b1fe067d37d38ed062e93f7e45185f94bfaf0", .None}, + {.Mul, "1cfe8c1149cd468f8d60c369d6c3fb1ba73f0a857549681a9c54a19b19625e5852f39edafe1118f7740da301080967e7ee218a57e96f35f12ff027658e6a1c089e4428c0f3b0d4d84d38193393e898a83e8bedcc0678e44465e3ed8493de1d0cbc20da31803fdbb94f5c05fd3f2efbea2445b2e8ef08ee8412976e762e3301b8b942c40d4a74d13d3cb13b1914dd38905a43a9b362c6", "ba40d0f1042ae7af9b800a8109b60b4a479b2b590c3ca74ce5b8db2a08919cad2f28d316965a781465026ddc9977b06277374bac72771a40fa3d56ee4123f1dcd2d1e073cc2b0d0b414fd66b189ed94b469f00f56f1e72dd372e6c7f774488d5cfbce1e673ed7c9e4fddbcc655326647e766f64741b7e8719dbf09bffb21b00ba2e4f33326663eeb312e77ed91e50fdb0011e2c66ce5", "15184911b1da5704082effa5064a8754e65063912a452bab5cdfb7ec8d5fde29b3d6aef37083bf8c1d735f88c998f35c2c2cb4d077bf48b109c82857697c231281fc8a0eba323bfdd5363546a0d9cff558d78f0e57e913e39d0d443408b7e25955f2bb6f189363a1925d886b8506b67e20f633e7e694cdac997a5bdfe9f1505a4ced72a737e4b522c63e1309aea7eda11e3f6c021397da1d87912178190debdf473d8ab93c7f4c849806401d399bb5350c0836bf416bf1a2aa53b1579045cc7add61cc9264088fa4d31c93f8f05be94d9ea56f232931566da82e22247872397cf1f008363bfe68b1ff92e7ec8ffc27fa8df52db6fd84d22246e3ceb9c16f07f775dd2c7f1f20fcdd25e5213f99fed891faf448dc096c2b0305df68cef98959f7b5675bf169a67735ac46e31e", .None}, + {.Mul, "faa5df3ed12e9a7190851109572f745cfc3bade6dc0f301a1d512bc87a31c465d9b20e94cfe6eef5b7dc33bbf2c79257dd2f3bf63d2e7c44cde4eeb33500b75cee4af5c1ef49222865c7e48eb7420bb2491f1d97cb1d0fe1101b7d4ada1309eede888c25d6354ff16892e82cbe213f52aed48a1b4a54011025cedee2d1d6ec0cc7562aa9e696575b602df5a7c1351c247c892ab4604a", "4ae3f88cef99f69535935578a71302af9f64d5633658a4cde4ed56dc86adaed596ee47ad492fcbbbc00ea407a7920fc8ae487db82c04ee54523af5938ffae1f460e96b3d64f83e3b034cb6dc113775df0b9ef7c697e832338a0fdc9f6c35dcc21790aec8dcdb0f634c0a08fadf4dc873413671669d001ee0bf63c75c1d75c45629c608e6fd761adeef170370bf2681d8bd8d6451fe12", "495326f7cabd7ff2deef82ca02ed19e61d6956eb4eb1d1ae234ec04cf1a4f1f102676a6849ab3b54c22269acf2ccdb056b16a1cd3b7cc9f5abb813b44a23ccebd8ceab2b0c9d0af5bd82fad963082a44c50cb9a34b52cdf9d46acd8e853001e2365ddcc580457eed44aa2c0aa4ea5352b0f5c046ec264343d1c954b579c12c7c77fb0ba45b5e518748b471d03474d387b9f6eec5b86d9f16b63f388964f8b286bdee36ee86491ceceae8e9688c841b940a680a4aae1362605ae6e119ec82a754fbb6902fc5079336a6cd0a157bbe20a539e564d6b2362001289b8fc307cb3f6ee8408214adf49c8797430ff74c561dbbe54b5652370429bca4150bc028af9f1c5406d27a420f80f2175bc10628bf07bfe65f16edc43879e8358f951bdd7fbc002392b99f63157d7557a23134", .None}, + {.Mul, "9aa27f8c6fd76972789f556ce0375a9a399f81e758be46155da9f2e07095a5f594e2cd94cdcc15d70319e274da8e5067abbf294103c593d1cddfcfee2dfb959f45592acd9cfc3b260fdd36480a196f160e69fe0d83d5f8dfeaecf79ce974f6a615132c246f1745f138ebd19d452f28fb44872b929f772f9de122cc999d8d7abc55b8ae4f271623424089a7c30071a5e9b8bab2fc0411", "81219cda980c46c885348bb9e636b931d1d7bddc2c4ec86f6011ebf5ebe04d86c1edd49a144843740ab8ae8e655bd6944d148fd790a0fc90bfb13ffcc2d019cc560ef5ea76bb8786fa34b9eec002f33f52ff6dedbc2fcf2340a79a40ebfc845b55287746fac48a8bafb57fe914fb9b12c2f6e3c0744766ef43d446fd513dedbc4bbf9c29eb703f760661078135b9f504a617198afe18", "4e002ff745680ec0b382be3f443def3aca50785b36e789b77a3189d6d65075bf68c1ca22a0f100c8abc3c84e023c0947357720aa873df5abf3ddd700199e4a10f3031dcdf1d31d8f2032d49faadd7b0dc959602e2f6ff7412203968043f768910b30d0aaa32aa0d23aa274ecf58f8168c189c55e5587e6621a03e9a16d7db0575d42351e83f0ccb05a2637e120b55508ccac47bc1a0740598f960f05c0b9670d978899010f0babad34f1bf4027d5a2512a84530631d8d864dfb3aea0c7a601a7da08166f858b3bb08f0b720536efa7ebf19790d66f3dd1aad55a2c70afa9cddf2f914dabb5274541faf36c0e97c654f824ce721fe6c1aca3715604b209e57be19bd49a4b32c1801738a0d9272b6ee507506b2c60c6a31388049a8789d2bd484699b62a4017dd0addadd33f98", .None}, + {.Mul, "-b278343da789ada916692339fce673eaa553067c4b384a4aa5822be893689bcd33f20e0725f5046c24474707e500de7281c3d882d3a28c363d778bf63bd7dfb329c319b0ac65450ed9046fdb215ad9ad969c4fd70a4961f91d3a21917b45c20e39a5aa88397e2d71e5626b01febda07ae07da03f41a78d77e3c1ecd88331fc9042847c30a2318de184ac78e26c17628ea120c5eab7c9", "6e42492303c32213f0d9d2b17f4e350dd26206cd3e67634136727864aa88f6195854c4ebdc6bc1b4d5edbd5bcc2a6bfce90e16fb57bda57a3830fcf7a9eaa54a1be0ce89f524ff408ef7718bddbc49551ecdcef0417654eeabcd250318f8d0cedccabb48d7e974d7c580210794f59586d8f84c34bf3fb2bd2c863d0d8bd287e6cf385696458a3b72e935482e3c2e96f3032e87c9274c", "-4cdddc6ca5d6853ff942c13c746c2963aa2ec22c072d478a4565a39319a5f3609fb6cf95e063bd42f04b052916f940bb851deb395e44a696c7a4bc1abc96351379595e86b562099275c8dc8ace7fbd028b598b5a7b66b93888d0fb3fc002b58b948ec4bb730cfa8a8e17da647831f28918551d27005e7158026c1e976dd6344541c377ea0718dce55a9c4689afc7579f13f72f968ccd810244273439eb650377ac7d2e1afbec09910a93395a0548f5dd0c9a648b442d6b5b9d632c8d751048f3ef093dc460d58f6fdb383ef2471eeb8a11d56da6d33ed75239957a42ab049ad4eaee1e807226a0035f363822e5f01597d39afd3345edec74f7de244a4f8e23a76d4b3379cc05cd8e8f9e5275e21878141b6f6f5772d1f4315da9b16c5b8c004e3dfb1db9521d6134cf7f2eac", .None}, + {.Mul, "-9d2e0af5c2dfc4f85ad5c300411ea18a1f33ae59566c35f7e4d65f37bea7a305ca27b007ba256e587c2a6a6dd16a4ba903bdfb770a0a3fd65832119806612dd2b0916faa180699168a41e3611af8b3978ad0a247ae0853fd72b3ea75ce49d10640a113c116532d6f6b4d9bb03dec6099d66ee77acfe1037afe2434f1cce701fc4cbd7d34d64a5eb1635176d2bff8d3a1149af17df8f8", "68b202ed003ca8e2372352509965bd565a3e31c868c9af1bba3707fb30d4ef8047cc9964bca4960427c31ed2acb7aa40ea60f983aba790af03232130b3376d2c2f00bf6cdd7af38368ce201e279d3228ed3976f9ca843448fcf83211ea71e58879547d9971248d34beaa832a22ba1704d9f9831f3bcd6f2bda63bda079c583c31d2e50f4c4a1d72dcbf338d1ab35d019759051320ece", "-4048004355e7b722af947ff7099e42ba35f576d98f725922c90591c81c2dbe16d8ddf46e00d6b61c24a8b987a946aa37d2b51b5e56b0c28de02626d7d70c817c365270eb34b1954d9f986d97f5136eaa760d9160b2c76d1a1943123321fa3e9569424093c4a2624e92194f51f05421bf5a985b85d450a0fb6a4002e8885db30656b763e4dc44abca15e977b8863afb6148aef363a269dc9241732f4d576891610c38cd446f6dbd9b3de17613cb3eaccc82861d22664fbb43c7f636a79234d5e89a6088d533afa70bb6953c4b73d654e9790e50fd29c4f2e3161a38ab95d6fd646864650737dda3a545819ea27a5d3082718a32648a8609eded64114b564a1a1a4a1b493a202131cc0e2e509712d259e6d2d2548a96fe404345342673713df93694dded3d614877c44f6be790", .None}, + {.Mul, "1e8f0b4d2e387dbc0141b2b0de380a0d8344ae56f775c06c7addd2e341f35f08761638e81aa5da0433301011469429d52e9d7f3e04d7217fd9fefccc2f7fa05f6346c0d39586d131cb54093ee8689c827219c022c714170ca335ee04e7a8200779c3637df376e09fce19e563a690f426a9e6f045b3d606a98d8938edc86ba506bd82f8d91cc340d6f39d195f9c910251683a31cab04d", "2bcbdc2e0eff472828f0ccafc00e6878dee9042aacdb026e9a879f53521f725beb2fff9db7bdfcec494c7ae752e753841376bab529de115e5d13986b2267702486e7b018ca20af87dc1512a2a5feb6cb37a725cc98297fbacce168c8fdf134c212571880f03e37d116672b3be0853c766107207d9db1229464b0aeb9f27a2f9f26cbf07f78a5959dafae757461d96c95534cf18c7658", "53a5c9c5a2bcb1a1446964d2046c0c852070e7ce41b1ae10629e3e4c06cf944b64d142d74d5bb85448372be63a4abacd31d0b66953bf8181df91a8efcae13eeaa53ffd1322cd8c9ad162b5b29e1a8a4c595fbc8b20205487b987273a7c6524e48620498e8417ddac87d552a429b533ed10aa5f95f106d13b3136f6ea276a3494214b1cc2a6d0e91e5f72e89d9aa76ac441e41f0a20b43942fb6843673f338ca45f39f3c778d3ea127c06e2ee0f02cd30b0ef25b983dc1945cb38417285c64614d47edf04303643b29024a4059cc984307d2b20172a0100338c6aba9ef3f9a57954bcded8802eb17bd449fff01df46641856469a14ff4207c0ceddb2aac80eb8f8902610c2fc417751ea03367346fd6160200410e5863c8ae383d5eb4ba24a7b4edb7b97b2dfffa1720c1878", .None}, + {.Mul, "5e792299720a5d47e7753aefb38f22922adf89dfd73791c5732b5761ce0032e3691c78076f069845d6640571f57325152d2888a6b0e7a563609386f9f8f9c8c09f5b7d1d363b095bb639decebfb3cd06d39b54ba33c13fc8cb70d5e657d62d85634792a69fae312664e35bac747ade26e1850dccc1e4d6347fa8d9d5a43e9c6060e296bcaed37113e2d5b65a7065a513e23229756daa", "e30b57d3b49a9493a28969194db9d4db9ac0af2a7ca8d98ea53c202229a6b97b1dc13b2fe45a73392900505e94ff9c5301e7f15e6877aedcbae75370a349f7b61bf17d6fdf14b4ce9266756cf37bac41a3ec5317464e5b49211e82ef12c3d448861beef29bdf58a6fa8f4db24a8a563c14101377fe7fe2dfa84573d092be2d0c82a9addd17fa7c73bbae5cb9c19fb77cca780e4a987f", "53c9994bd7f6f96a809b0c977b096349bba82250f93e7c232ce52a251cdf226813ff343fe14d618713358459739fe535aa37ad18c599c3eb8a49aa21d70d0792502c9ee00719151c63a07cc2e0ea954fd089ea835ccccda14fc617f87f6aaef11bd50882af245b3a05659635eb23a4abab1fbf1424e05f1bf6509cc938cc1a101202853c151b42b3b4c025722832da0dfa81693d67504b3c822f9f1ff89a21e853f73aa24cd52c4454d01c623d87d9689da55089a6576e568a6ff325d13354042d83969cc7f6b180062529745dc32f55ac8770e82244ea9a36e41d253ec882bd1eecaa1c648f14b215f6d77c767eef08533e337e94dd2409407abc43c40ec3461251d244ae848fd839e82de6f4e0124eb26fa8d2707e41aeab391ee9acef540a5335d3a48fdaf32149825756", .None}, + {.Mul, "ebe2cdb220f2f641710a3d0c9773b7e10c52048ce92e6792cd7c6ac94dd270d5014752c84bc6739b78ddb8fe40b3aaef919c3a315bb76a67e18e45bf76d220d0f2938d27842a2bce25bd605c1c10d5efbe27d66188a47668a9b36aac7883d122d852aa8f915b796c2c5f4f61ea516a9afb0edae4211fc37d382d6302c24678535699804e29712207d3fce7c96d1714d4c403b8a39087", "7df192f7b5a16b5037dbfd32a4215af675f6504d5669dccc1ff00bae65ee509ea4c7b7757cc779c32f3a6af98501bff1b233963c650688b96419d8d4b3537dd9f06d40bd97f350dd80dd2d4763fe5245a2e8211a6b4b7442e4435d1251e520bd5b5b5cf6466d27830104ff5e9c83254a4dfc81244a7b4af4637b0bd1afb19e8d3dcf123b84fd343ef451c49fcf7d19b2faad358d7230", "740c565f3747cc94274f00ec8eb66f7ac03a48c44965bba2987b760878302a0db71264caabc5dd9ba21ae8fd12b7f8409687bdb3fd973e46c46650e8af6028e9fc71cf57862d589dd47feac2e769c06a4e26e72c720977548139872ed778b61f850cce6a68b4bae4869ffea7b8e440e9103354ec867226b135dc93ab458651d1d11452edcc1cd1099dff007925d4abf9041c7f43452dec1e1f3eaa29bae3b2471bae70f3b73d9ea6d76ee61ad53329ef254934f54664c3b7060dcd961a024b7b04fee5e7ebebd58cb7c6c7265b733f4dc36596467d89ff1dbdfd7a844bb2a8165cb03003b11609ee707bf06891da1a02820b180af542d923609d5c8e4542a78cfdf93d2a70a9e09191d46df3b771f1c632b756dca61d0b518cf14d6bfb26494211c56ff590ff792902623750", .None}, + {.Mul, "132ab1a37e6ce3e7f7d83b12cd06af5d9da4c416ab893281f810f924184d0ffefb184516606d435f6e8961f8cae9df95ba428072b29f0c9353300549691f0181fc26a6cdf6ab242aa64190f848eaf0b0f828f25b2bab7d349444514d38de55a45e8706030aede8f4566625b6ccbd38770a93efefa0823e92a526cc9f212ed9fd406e303978f1dd0a5edec0225cf5bcc9a9d0cd60f1bc", "6ef9784127e807d46ef68d8bedda4fff12450e00ce38c863a950f31dd82e627ca29a4624fd5c4961d41ce94965ace7e5241ff3579f29470cc77d9c730c292bdaeef58a8d07891d4ad584f1f9d78dc46873b293155b0b6dd936997e8fb7450f552fd2978af6df599b178dbcbec1e0e16eb84bebd224a096eb98b28afafcfb82377c87630edd8ad5a34a1d412591d1a99bf9aa10d50e48", "84f05dbec715ff4748c1ffb519f6156beae6b6487b166310a3ad0a1b6dc55a8243d58fb3bc652ff42040359ce3fb94819ba349991bf297753e78638a7600703ea0b7a389506c1c2986a177a3fa1ad1f889b8fa3a28dcfde027a60858528d238a92c1b6d48c50c03f329f7441f29004a561af8f00f0e31c45b8c24775aaffbda295baab17bcbaa53931cc97bd553ce8b8ee9e031fac3a6972e0175a83a7dd276637abf37c22dbb1d409a7f3d1659ba3dc82ef0a3529ae783e96e086cadf9b51f672a544814fa09537a2ee0a06636db1536a9885666810d90f7d68befb55b1d7def71fa2c436ee9bf7037e45c29c732e3f4c57107acf279a91e0cb3d17bfd0ac984688b4fc3bb011cf538b8d9c02decaa88f14171fcd9d6a8d3d8adaea6cffd0e0d5750069de68191f1e844e0", .None}, + {.Mul, "ce2fe60058e9ff89ccde53b5b3640a1d38c50387c218de026ee74849a264f722c93467ac51bc2d26bb974ab07d4d039ffaccc8416be69ebc81913965aa17a705296e96407f71d9a44a5f49e1064bf9ce6565e349947b64d336905c8bf25257aebc3c9f79bfa44dd9c79c332e505d067d669686530c04494d544bd9155926acac30cf56401fba6ffe332e94df2a657492d3ba5ab860b4", "d556f8ab00bbb88980ec2b8c69f0445521bf9deacb9c7672605e75a927991da015d9ac62964f265b0ddad0586acfe1125bfce08078d7f955ff32014c87bf40817dc8ed994bffd92e1e6eefa947095e1682bd6db50114c8f6578a0149b741062f41b6ebddc2f72775a9c21ec715701ebcea347e98fc5fce417228406284dc0cc21f80e6592c6ceb78f347da2e3b6299b5f2a55135e76d", "abd3e6bdaf7eba35c2a4711a4d61da767ee0b5f682750033aa2119491fe9268d7ba5fec7caff01e5a572172c14fcdec0adebeff633acee5e9bd30b7579b69eb8ac121096f906f3cc7f37c50328cef86f6cfc1745d7c89a16bb0e1123de435712b4d29d0b76543a485cfc11a140258adc473e040948e7f96f6f4f93b36ee2c6d23117d2aed008aa272a32baef89cbcf492b92c6b13e5db8830ba2472747cb281aa47e746009549cd96cf46ef8b55019fda18758a3d8ed02efea6c92d72a2c14eab1e20589b2723ca565f92bac547a4e49f3ff42b0d23d58de07c003b5ebffb4fde67ee48dbc2a9450b78de840af47f7b30609a219a85e2d1236204eb8208eb9a972ad1550908aff9d8c841ed9bcebed9499ef1d40fa891d49681cba74dc87a75f8623a8b5a35ee8fdf90798a4", .None}, + {.Mul, "49826afc6110f3b30378f09934f217c40ae45587020d6492ad6d5ba6f486966baaffbb4942cc1929378bb99eae474d84cd6e634032d26e3c9e7dbc0161f1c3c820771b41327e4a38ed84968fa7b2fce0d84927abef551f54ad7d6ed78636cf87b2f8f225fb68791826c3d6470455914791c95417ee127f90ff7a20e6a56aab22c6def2d2157702710802f6c7a0118605f94f1c668835", "d357fc768421c3ef9f4bbab8cecf0f55b0a62815239f1082f3c07c0f786febe402de9fe88f7730e8d955ad2a7b7d91e22d91f65e95018c139356165dbcc1ded2dbe29ac7c5bfc71d4482bd470cfcdc76e1bf61435132b4b73c83fafe0cf5dd8aac2a6872472518062227ae7a3ee0ba5c3b374b1b9d411b35537f140340fbb2dbbddac8258724bfe0a5bcf5843ac6d56280fd24c0bda1", "3cafc1fec924a6bdddfa8802dcb18f374122f9fac800aca317d1d1088db8267145eae44cf9f5c515facea32b1f367b341b4e33a78121f20b16b795c4f9527739c888a1467cc15698b1fcd372396e600879633909b21bf2308543dbf7c077c36f41fb96a990de20667bb3577233c4cf569447051a92d5ff2837aecfeafea1649758f6d7ed812e16a91375c02fbb0bc9b7b9b20fe615625dcde690f0ab68a871079a875d2c8231587faeb3ef1c897b20d2ead0991c0be1f83fe4bf24d302a1899240d0495dfa637b5dc2d0025a82825d3ab66fbbb0d164e9757e84d333f5eeab9998fe74564f37f6381b992e655900a2feefd0a3421af637d50f11ab0050d2cfc9df84887f83321d892769e94f9e4b69de41dd55e2a52ddd1d1c1a2d41e8015219f2ac717660de07272acaca55", .None}, + {.Mul, "-daf97878e97f730c49de7799544d33b779ddd7cba65a2aa5c091d22dac8da9db478363e6963ffa07bf20940f36ebac677661822720f6afa1cfaa003974a8e6fb025f588c24834f0704e764f3a0d70a6f400f77d5b33c2afb88b53f2fcccdf9ff11abcebc119c02000c76d53914343dd5b540c9471b6b05a6a51b30fe38befae453398283e17ccc9564c0a534bff3a8f7c7d0cac47dec", "a2a3057c377855b0f7564a68a1c4c5c40bebc5bb714a68a9702e76a24074891f41750bfb933d73bf0caa41fd9d80331047372ecdb70b2084ffb0725a5f5d7c96a65073dd9dc168ef74e2a607e796da66c809f3abc343315a29ab75773afce13d83eab536af880fa75bc7359d8723832dc6366e946125e2227a620ac71c0d4a8c36a3445e7938b2b517147aed72419228deaef1477972", "-8b1d4fc5586291334578188876f8901d2ebf33bf12af194ab244f374c50878abf818661193c6ce21090d7a21ebb2818c78707f473b62659c6cda5695f51ccf8899e742756d00c1401c85f4f6adc9240ad5a84476ab79468e4bccb60182e9a5467f1eac98ae7feee60bcd469d9ad0d4e37e46d5bbb33f135386835aa5542b6b439f0e05e38779c1696d1930caea1a1c3b306dde0f22bc682662e1f14aecd0931a5e9202aa9c979724ebd060c273a8b1162a4343d8f320fcc8b57eb4f101967b3bc8cc1df20f492fc25c91c8ccbd2b3b31807c38bfe6221be422ae34f0149db6e4f2415b5238ce5b770ea25ae7b65bc0b5fcc60c124382bd82a41770d9d08060446b9c100850d13e39444bcc320ab007362a3b60523a1856b305cb6ad55a31fdaf2a447462d134204343789f18", .None}, + {.Mul, "-4cc85cb43ae57a3815e7b3eaaff3a07f0258ef60b88f1970d3293c3b20300358e316f144aa5b0dcb27b667b066b45019519d894d9149fb4b2d38275f46332db6e4682157480ec74c9502a673eb730f4578736c38b51cb3d469b0114987854fcdbfac6bec313a5c96cfe5498c339f0288fc4c7575edc44c7f7a756b79055295aad42ef770789a91f15b6cc9431397442336ce79688046", "65114e8cd1b4a0f703e5160ddbdb54bc972c16f30b7fb039c644ca93c4507d92bdfe488e361f531c3826ea2b09b0adcbe3a4ec931214ba8cd2e56da2a4ec849fcfa542228dea3481cb20b90e2f16895f76aa80b57a142957051548c1238821b5c858c32b916cbc74567655f0e1413a86deda48e7cbb97f88c6387b55a3afc97e0dc1aabc9b3665a63b7ec97f9130246e6a2fe7818182", "-1e503d708bebcfcf0255b37b80a5001ac43640e92a4a1ee71bd75bde6d23b4fd55e80ba63b7bb97ed36ec2d59b4dfcc0e985f77f5b50f664936f2cbe6f0aa1f577ea6a00ca57b0a2a188efc6bc1e444a3741d564655e6d1004d26f567ed121e86f75b71669755f6ccc0394ece52a165a75b96c9850db5a7d7d521f757c4623d61737314725d6f8962f654c815a8fe3c6b5608e9973508a5f2de723d582f9840acba7cedca2e3e26754a959f0ddb72e69f5571706fdb30a0aa642c4e76ea4db3c779b2a7dba39027acea9abf2fe0f5fe356586381ccb15edc23dd85bf4fe1c05f83262d8a5b69e1c223dedd925e77ba6791d10c4de8dc3eea2b7d5172478969894704ea3808d890b4b49be635d8bb4ab49b7489d3ab479fd552c1f63c09da6b7398916697cb78e2491cfa698c", .None}, + {.Mul, "f1e5ebfff8105f55d3a8998aa119d89c1bceb277d5274f64d8ed760f198e433bedd35b7881f610a09b4083986d2a62486e207e39037329bca4b75b9e190913b8e6914e7421f83c9fdf664f10888388ec664fd340c51e2ea2aebd6bff4cb5fe592529175e5d5a833e061dbf83f6aaae206d15ed7141d1d0d4aaa2abb69523c040b014898ba38b13e9f9bc7759904d2e2729a7b7a56222", "8e9baae3e1941a8fdf3a5c7ee4735306ccaf060ea9358d2f08286053ffad84fae4f534e96a7db74313d1b723a73d84c1ff9f92a14b82002d86bba4991afd24f4eda944512ff6645b646d58517335ba5cb0e710e0afb352cf3553d5682daf788c6af27a4c422abafa8a02bf87d326b80746f7d3a73d7ac1eb4d4326bb539a75b7b088c75454802b51ec700ef87b4f148b19a67068c936", "86c0a097e2538bf0df8942694127f5610495a70ebc9ee79847f1267e280b8b38798e8b5f67f55cdeb1cadebb7b66ea9a85ac299fa8a64ba9f02b827ce8c5b779e68f37fd2afb53239604993c5b4290725d6e3cffb01d096f8fce59350349f25bc912fe633f7915e7439671d22e6eb03059dd54108db87ad2e815e5226523db087c7975017b14de2a3cb279a816dd1111cb24033fba04bc46367c8af63a2fd7fc669bc4d9cd7bd68ccf87fc14a27e6a39b6c931bfe5e2318e94f123e3084f5dbfa84e85d8eb781331ade21274065d2974e842cf3ea2935d88c5fc3f56826c170a388eb77784d65d9242e85268454363d86c7ef20f8d7f45d60d3d3587497d44288cedb79caf272db0ce2b9be47a1297a5c2c84fdc7a5abee04398b4bf7d1837806abc904bf4bb62bc54bf652c", .None}, + {.Mul, "-2219757bbc6cea2601fad010629cfa8ac43a77023b60be3d4504c1e80cf44eda7976507b9ead6058b810115f836d9dc2e3fcad78a21db0ee615e90cf412c0f3e0b4538f29924a4470ead0221da78fdae3243b02077209c3e84e936b33309334e5246aa701e7f76e8c6e1aea862e1b7d49bc279db6cc6836810287e7adf4ef5113417622c37015d9148d8297368b0bbf749c2116777a2", "c7a58c4e69fcd9fd8397d6901b88e68ab7f2d20cc4a149069c27670f05431556a167e201a0604e9181eb433129485c7d1f7e977c34162e8df3eeaa3b5ffb6de18a4ecc8cab7069d4bb7bee9d675aedad1f8ca579de9b566cbf44838f4c0efd9010e12049795cc3b5a1a542dceb668f616ab91936729a8c72a733a8baf89c22e2b969869167e52413148e2781890c25fb73aa99e4f730", "-1a97d76c4658b23e2ea1c507515db320bf73bee013206486659cb690351bf79efc1302610f3792d1151d6baaaad76aa517bc0117c487b5a3f722ee14c8ce5cc5b22e663f0322622db1f4a503fd96695f0b20d3a9812d883cf1b02d585af9c41f62d74754a90df1cef62dbc3475e759105cdeead2f50b5172f8db93d15f6d33f203f094c158cd18340e55306e82c9bb834b05ad76a20c133d2f78afeeea2961f094b0058f225e3d7d9c71ba53e33309d7f9bed62d0579268ae6b12be5ae0e1b3830d408e119a9e1718957732e98e5514e8b8546248cbf62ace79e22716bf5e6a5568aae91d7302866090294aa61b3b6883e5e2457907140aa231b89d76915d5c5743f9b6422135ce9c4d44e6f9bc0548a96b0a2088a8473686bfc950fa033ec6e6a09d4d7430fa168761bbc60", .None}, + {.Mul, "3e9b62304654d7f39f2d3f744e883dc51db2a72f2d80e094deb0e49b78a05cb7bca825f54a6822b486dabe4b34006485d5a796a5a829c9374206d1f6ad69c4315b0b8f0424b36305073e7e56f8d5f573172f4869dadb9eb87f657da0309001f86f59c1e39a48bf20f54e1eaea878d3cc2a19bcda69ed5b77b75e231d58b16f47041fcdd5215f81021ad753db8fe8f7d492c837a2103d", "55512075f32478ce6f8b023ac64c6c9905f071ff0e854474df84d50471ef5a97d1de41181ee3e901b648f4b70b29fe1e97b1128ef7923528af9897d03784ba63284dc17365b19c5d9692c540a2f235b2276bd302f09a148d76a088b9c90bc85742891bbbc2d1fff52cfb03a81720535158cc40c7c19e3c526c911f38e1875279940261c65f40e78cdcaae4cb61ca2eecbc4abcf52175", "14dd6eb45d60beffeb97f8d7ea8365a87bf2cbc1f0943eaa6fb9b65f95f08495fdb016e7690b47a491f2b8c9724162e7aab7d85c795732b1cbf5224eb6770c4de46ddded0d90c9b40db38876bd09a01b4f102943063f4cf07ca4ca1987b4118010a14657aef9ba380b8008873092bde6f80f306deab38c34e36317f902263f05a6b8abf6528c89f11790cd1535f167b14ba976c3d05de9b91464493bdb19a994609f6c937fea684ee560c40d742257e0f01cd2ea376017b63f97513b3222e1f15956edb6dacf64750f55833181b77e395b095aace8f5904c505350fb8f860d194f33b67873ba04ed87a34dc9d03a3c561972670ae556820b27d0c908d2a3aa799fb1af621cb792803b91f119a87138cb140322fec6bb55acc5b2c96b03213642fd11e3d6348ca455a78a48e1", .None}, + {.Mul, "f280853beb4988c552a479b9337f4890e2e3cf91fa9ad7f113ca07ee6b8a5961a9d5b2959bceeedb36900c036c1e3b6e1336ba111fb96017f09ecbb347b2b95cc91ebf8d47edb72b426933cdbcc6ea68fd7531119a138fb7a90fb1c61a34e44e9a939629dc42b19eaa214f3a461ac5e233fe950cd0187271f83ca7a7cb3b8c5656ca1d50e8dc0465c12a3bf4ab434ec2866e868ed346", "37f40d09eef02154d4f8193c1ddaead8fd1e027f6d2a271116cf8ac8141ecb570f01f3f62d55dbcaefbf63b2acd2e465c4d6ec849f46421d5e589fa6b1380f9eb145ec5a5f31610fdd49384f52946cf64b63784395ae947d430067ec212a0c542fd70072147a41b8af51a730994207a4026453826ff6a2e3efaa09d93e57a6ff4ef94382edceab4e185166a6d59bf30b641d2791b0e0", "3500cb78cc48bc744c5cc4e09b6fa850ae0571d59b1ff80f6055f49573b5125f8e39497f6849844412922f56ad66f774ee777ab591609015a31d0b27729c03088036d698a8328ea73c6d92cc9fb23296175c738662646e90ded66f04f5ac3d4093640f801680fa8f07b737ff235ab822594db96b7c1e5a04910d1a1b680f3b79b51625929244442b281821682a03372b9b6e5c5abd11f30838d6627296466ee1ac7f094514d51208cac0151e24645a165a7bcb3f24ed7bfcd4edf12a3ab2e9777a9e28c1f352ac600848dae3b4bc777cfc8fd6e36afd56396651907658f1830bc781128bcdf819c301792f0444dc9482debb6ea73fa63de676221e8cddbe10eaad91c4c164e84b3af60b6fda8e722726d40055ea3a73d9301f52976c1a65f004b8a04ad93072dd3b42defd40", .None}, + {.Mul, "b4ebefe95562f698cfa76676a7617d46cd2ddde99ad84f6f287656587ac90ca77e0001691af627f1e05bdf9e1439bf79ca9c9fa79f2fcb1092cbe6b83d9ee1d7f1107132b979c2d218ff225eae437a50c26591d673102b3ddd3133bbb607c8e5779e50793c4b99312abb8730ca8fec671224ff47215ca27745bed5ad554cc30ef1d94e33c4cfa112e76017980c72fbf0f1c1e6dc7105", "5175e9ae587d51c311b02d9ae3ae272054d5f8cbff877cb055b2e9365d09402b460d5da0a8b2b5550d7bba348b992eabbea87e23b8108886a611af4226c148d4894e61ec63415db42659d494252017bf25423fa71d99d7cb9e32931d6ec12a00ee356a7ccdfea8c696b03f831d600cacde328d2e097b7bced8ce794f94238c97f28dde2f0bab14018294d6a51144ab4890059f407d01", "3991fbe36dea710506a905ff88ba01c850ffc054d37ebb43c3aaa59daf3cb95f970b70cb4db946f4adf9f67d2d591387f8dd19524c65bfa8ac25f9a5b9ea92cde94684d0685e669d8a93f9ab0af46ec901878cbd9073870b7b6a0c0a767e9c7b6bb4b4cbcbfa8456704f24cbeb407cd9bc680847f69d38da5fbf29e977fe3c2e2b5ae5098f8960f4fa074ee5bf8436872c7b584a2616b0ea99c91150337054717291630a23f59758e6bcd6ef42c31e3f2b7cbe771ecf607d0b7848a61fac80e0303b4616b971f584753d8ac767ed3d5ce6f4f77465fb1217dd8a968df1d9b01cbc8fa210d910128749692fd08b51404bd6c899cb6cf598de8780ae7501b62cdc56e3757761439ac0b1f4f0e5e1246f5453dd965cac7c3528285dbc25c132ed23d09e2653232245e2e64be205", .None}, + {.Mul, "-a1bfe97853a40779dcf6f9dd8e79ca1de1f4010940f1a5fc4726695493c1763a88ce459458bbd9eb5dc7e6c2e3d7a1d9a39e05bdc0409b41f6741e9c5f04fbb65c3f2ad83c948231d08d7d770caced44a5c692203fe6c0c089e8463444ac6383208f67094b1be2110b620cf7a9a6eea120ff3102862399ab3cb22b8dde62a6a1f04092c187fd4066bf5b7e856f12490af9925f47a5e0", "e6859234a5ee17ac0733193b29d6294117c255daa71512a9eebd65b9ae01224c45b5dd9c50a0f2b60f93667b6b13099b2dd108a397e97c5663a9afb6758d41ca0dc3049d203a6dd1a2c31eeafa5765333616190b1980bb795c9c4691fa1856961b36aec39bd95b3e4706c1f536178f80849dfd8081751f5af37814f68934f2776db6c6a2f34d6ffdbddd5f7e1c991cd9e34a1b1f0cb0", "-91a6d0d71da1ffee73a865cdf517e42c6ab29d6781622a1a32ac725baae9a4849c44e55eacc2ae8094ba8b228375c532237e980b2724bc6371d315b850a23db32d0213865fb8e9806eb51a64bca2990562cd47f5f7c970587badb3e2801967855f43bfbdf4aefb1e0084d8fa28829822c1f3902bc22589478645fa7a270bc558c424dd3319549e790bd0559e83d0839b5f43f3ff14a0fa421ff2059aeaa248317cdb0ac8a92db62fdd44432b62adfade08593f644420c02d98a610c8202edd9e157d75c8ec311c002201633fee7e723bdbd6960a8a349801b8fcd449445d1fb1b7049c63090bc571b05cac54ce8e75e8c8a2f19ec4fd6880feebb16784a16618575c5c3f43702e3e8ffd01b34e729ca725d54cc0fb9897ebe71cf3632b86e674920a643191b01c0493288a00", .None}, + {.Mul, "f32c7365d4869aed370a90a7c280253415d44b110d421b738ed3e5180c27319941150280c10ea7efdfe70dca81bd6e51abd148f9d3741920d80e2bc40a4263186195e3e1ca9e859f3c22a17b7fad8fda5652565795949a8eb910100e2b6e56a9a698aca0a8a7a7fe2faf3c95071cea131146d8f40be5fd562b825ee8775f3350a45095d5d854778cd9ec4e3256ed43730015a6002e2f", "42f20c8ae6cb67b90ba687f3a0482924bcb6645b3b8d23c02645f997f2c49c415a0bed9b51ddcfe7eae2d2e75a6f767c076bbf7f2c18d32cfedd487779a3bf099bfad579b1bee754bdfe07aef478abae804b81a03b5f55be0a426eb644662a8b34a950bd9f2bd7586a1f7338e3c1aabc8b3eee00e86ea3c75e4902d394a54ea25be40ba385cf3291f9398b2bdec19ff52243094cecd8", "3f9761af5da7bc7e23904faef0d470926468e4a570350b5ea75f2d01c07f21188febdb18e424f0a4d2ea30969ed106e082a9c2444befa49ea1eb0b273b37a5e717c608708e580ce8f1576b7b44fef8cb45cdda110bd1a11d94cf0df85ad49e170f5e1d446e6cbcd7c4b566c7ec030e1a81bc3c30c17fcc65d859e9605494463377eb98ae87a8479d5090bcca36b92da70ea29c848fa7090af58fe32b8945901645d322fd75116aea682320e146ff3be2b917bf4ada3b475393c1e4cc030a201931d06829194b472353a1f8d81f8d29a1e2f2e934d36c8b1e0923980634ac581277ef84ee147d55be186ef76c297cd5268c395a7c130182fd3eee501f8e4a3d4c40a3ad4514541ca423fce9c5272525937ad91dbe3967ff4201e9507d3f72c17b916d97849288a54697ae4ba8", .None}, + {.Mul, "70139c1475031dde25bb11c1e46d841da1c443027e61ea7377e81c3fcc3610d02128980555280534b4c04c8fabcdbb30a962db6aaa0870f153701c4ed24d66c45598326b51c4808f9c6dd83ad0909b8010d9ac9a811509c05fe1ab52db8e46bf7503ab493c5de6990a862d6855d3941e2d39cc6ae5a26ae7bfd43cf8ff63313e6684716b5cd509b03e2ced27f3a85ef3d8deeddb0239", "f118ec959fd00102780d98bdaf4964eaa71954882d96ace0392328e95a0aca09d60d6a4a5848d45a03d6adfb90fd9b52c6623ef11469808bd1fe486fded50ec93a7d5ee4fba6371901388f77f373e9a5d68257a15bb156b4b96513aec311a81a1ca6008f748b4151352a22658e3606b891052e1c07ae1e285ffe584da29f85d8bf22d5757adaba606629577b789a00cc56618e73286", "698d5f597956d9809650460ffb51db2fd76b3efd944932016081ab46e262cff5c1a1991d40dbb64702f34740335f2545be98d2b3bbf3f409fc0ee8dff0aa769d2dd1c6c747e46c71c06e55410db9c674448834199d9552cbcb0c6e8fc3b718d046def309777aba1ff111d2e88e888fb4a5fc2d19d96580515ab6d222ff4c1867e320d1cbc7d932139e0aa38d7ada92846cb355cf92cff4102cbec0d725000dd2081adc59e64e14c3bf924be22bf9335c01e683e34274384375b4f820567c3806a732dafdf02de1c1e742150ed3f7ffd73c6d94249e7d33fee59aed75b8b7385cba6566c13ad0c8fd018e6e17791f8ab5bfc34f6d3c0d169f2803ec67c83e1347e2e1acaf2c4774f0abfcb3e0fcb3d3c27e36dcc5160ba53d4f35c501745351b9ec6e40ff418f7afa0814bd6", .None}, + {.Mul, "77064a6f00382cb3ef7b8795663a6c742f72e6d69e04d37163df78f360e038d0cd8f8832149c0e54336e33b86c15e81a974ceeb613f6647358679e7e38db6a1a4356cd89bfe7b0bd456a1bbd39f23c8105b6675a875baeed967ec8c09cfe9283590a4eef6e924cfd96de7addcdea1677934507d6758f535b3e5dd5c316d24e333366c9eb16ffe1e4dff3999197b190e68b0cf8e7a844", "7253ff5f04e0d2a0ff1ddb909f7974fadb49bd062d814e7e3f095ac8871d1d66959f8b845db0dc6ed89408daa44c54959b1865572812ac317b1e703b694bf54d44a0011dce7ae90f4ffd61f233738a7de88cc80933eeaaa25a55192041edd5cf6c54a1e9df0b778932ea46b457f4ad48ec0b7fa9f4b862900fd67f8a9566378d9998e1ac9f77b3a6d8954d0972f663dfb941858a1a1b", "3527daeb01d4e720891745182bf97ebc187514c6d1a33831bfe11b1a710bce2ce14b42d75390bf57253a0535c053ed6d4d0a6f43515731d5b97b921a413e4e174cd5e7f194d35abb64c5c33ff6d0d8551124d5d2c9307c678421c133ed105e27e53994a2d10f82a503d339ca9381bfd92d72320b51bb3b120d24350729a59c1c7578760e0dcb7bc4a3771c50c8151a839cec1c991f6f34ff019fd5a0f471206346c3db2f852ab7f4c31dffddcd9b6cd2405986c6526e9216a839b40d63ed1e8bdbbf2991b7f3e06175b8256a0c08db71b8ca9b9790641b86a97c5be84637831de2799fc5c691a513c22dfbd49734b30053cc477af9c8dec812a1769bf481b9f7221927cf4ac24ff85d5ff68d87caee4d5e4f54c97bae1b4b31160e1a0bf7219e4144fa56df656035d02da72c", .None}, + {.Mul, "-bc57df80993211e647ea8561478c45a2149e482122ff90fc1bc30526ed07653ccf97a933964b843c71df1931bfc58d7f72604fded989c3b7f3f2f5c835823643438319af7610f0f610faf679393e71023112b9ab6f10c5f7eec6b2d4a5dc8f0aed3efcbe4e501911f570a056873fb5baa0c5fb44bf3e3922a349bacd8e72707ab1fa4fb9973aaa681a09c16938d03148e2cbc4fea752", "cf370f8d2b27f2e76f32e40237bffaaaa05abc5bfac799566dfe9ace2b9f30ef4011d3f21f2535a195ae1ba7a3a6d3cc87a2820ca46966783d361bd46c7b87fa904e098d83330c4657707a622180c452a089ac357d5d21e92869c3f597597d7bdff2c2c0dc97c26fc05e56a15da3d05804340c7b3c09c824b783c55083b3430ff6f978da70abd23c2e6a26e6621497e8978f10838351", "-9873900b02bf2fac58f4f798f24d2d1ac151be242fd89aa878e5959c7c2b7190b26956f22037299f0c576f4dbfb2ad342dc938c1cfc870bea50f697948ecb9d8359a589178fe57018fd3246c4cc79f043a410fb88622db2daad27ad61dd11de8d6288944be75cb3ad5b2c60979ef07bf160c28330d61f64b24ada37b4a0cbd33ccc63f03b1d54593027733d73c9e3943615221d717c94c23f887e5a7fae2c2377a3a58e2c365a917453d1043e7784b6cda2e5db5de82ad0d5954489f26dea76d14c30eec4c821f0c73c5b82d0dee5f935c57649027e4fd26a0da3a8c00eaba948bf1ce1e93fdc463f25cca35231bce4741e1bc42a0ba104155a55c24dc65d015bd68b6d2a8759f7b0f412e47f07e30d2ef315cbce22572b342f6aed314ee7f8ebef35c76edf495da6327e6f2", .None}, + {.Mul, "bb3c65e06be56e3275b9f8b8629fbaf5c295d66748492bd1cac65c014e4cddfa371d4cfb74220e5dd0807a4ba6d373a60cc7fb019f63fee16bbd1796c0d56a451705064a51a62973abe2ad04181067dbcea282b6b5eea112540e262f442cfb03c0543e46a7e29e3db361616519d743ceee20d30f914120750fcd8488fb8eea0c0e3af7071261ec2d28669904c44084a49caa079e9a6e", "89b4e08308fe8e93f98be4a122599a0be5bad08acf88c833d442d93261d5ea56f9e00065e34d1b23d00f267db9efc3ee291dfb3239d9b5029a39aa71aa1b4f3ebcb3e561c4611ed896eac9b3f53e11beef4bc38209b54a66afcdcd4551c395daa38e53e284f262c096f928ac24ea0003333f94d51de739d07dcf193464b6f4d0a78ad713862fe03fbf37b98dcfde22a513e162b8376", "64b79d316b2a36ee460e1c98e67990c4dea1bbfe367787461684c27bf61302394af890de481779baa342694096bd301e2ad12ffff546a8dcb006c3ac32c34a9c0b2d85f28ff5caf1528f6388f853e77431252ec419daad5c5b967b4eca0b1294644e80dbf6adf011c179b3b3fc049aae99371d9838f8bcc447f5d8643701b20b564e013dba2ad58d3c975ed2c870afcda7848521c1e2e806d7ed7504100408dcd7aeaaf30ef37cab40564492d2d49295c8c08f6373ee0213efe02fec7ced2c13058a3f762033acaf849103cb6834169d2c529637cb4f9edcea41806f5bbdeb78e8df27879a0d9d96905b8ab1b7b690bc73287b95b452629dbc01d913831e8af050d1061302c3ae2cfc7324b9257c354a4858302861bf23e79e9fd2b3ffd6088deb00f61c69455d3109b78b4", .None}, + {.Mul, "-cc184e56bef73aebe4c8755090f65cce0b7374d3b71f26eb9e85f15a5f63f26b092aafa18ff38ce5be45a50367f7b1aa7686f13301e1fbadee7be450f998b6ca78a703be0eda5a21d83680c764a7eea9dc18dfe3bac3cf55f451fd20624554cb5e1f461d3ca72474c37e9a05985376e34ce30a584b0d6785999efb5fb2d733f33152543db5f5bd45b41a37017b187060787c5f8ffa8d", "bbe2707316d1675887d67e98c8f1bb2e13f0c6d41b52c2d2e64f3c9a0ad5fb0134275b3a920f73d2719a84e745616103bb281eaeabd308686b0fbaa050b46b292fd5778cae092e727c15cd0cd1327cc7e06ae590d016cd062d71b0e25aff0888be4e079e65a04a649e370358469138862373a2d17df7619d6627fd3785b8dd4b86e3f15f20f110d0212bfc690702b64e9f2bba7a0200", "-95ca4854e9755bc80c9be0d662bcfb5211dab80960b3c7e2b76e9349854ac0fc713045685f533dcf21b8f6fabf2b9fdee0486ffe5a46a461ca59f53db647024a7644353da279cde18658c078ff20ec63f19f84b989d8ea5f3af10f275c17da117826a73cdc2b1cc505dbdd4c1498e5fef1c13872320e516720f51e9d1ac1b255f5bfce3d448453a0a15c2b091be445672301916f8862c3c6898e2988855bbd240aada9e1b9f61583a2ce5471b1382155c70bdd4f2c72aa5cd317d2f44ebf2893777d64be2a78a8aecd7c61f87602c0afc45ae4eecf333f641e7abf8c7dd8e8f7787258aec93c3a94200cde7e364eba7f3a591c19d486582f9b062deeee5dc4a41493cec3fb0c4800d1f1de075d6879d96b83eb38c1204bbc02ae341bd214b37b99ef9cbb9867c815f9271a00", .None}, + {.Mul, "fadfbe0b2ba926d39a11878c8a305eebc50596e51feeef74e2749c21ba1368f4fef9b33251f2fb861e7d893b6ef6e620885b64f4b7e32c614dfef397bc14e5abd4e61323c37ab90744c351cab2eb1b436e641fecac89391610675930d5eb09d57da0f62371d126093ebffff4dabc49963446a4f40353238e31beebff7e02eda11615f8d376ea7181de61f869071c47a87c1d22105c0a", "b928b7828f3f0893d23b18524410ba08f3db314e5233ed5222ce7381218d38a268b25de1700dc921b704d60b08975e49c85c44395324278a61f2b90dc4ffac35afd0de386fc62e0cb9d1ba178cf51172f9c2f9da4b68febb8544ada24bffd8f5d7d0dfb9af5039fd36ebfd0b9e80531eedc00e1133cd61ae71563e3fce74b39764b36532552a215ec4444e07ad1386249403b726afca", "b5739721a7254dfeeea0e0ac2dad05ef6506e0f54c386cbc949a2bbbc01858c678bcd85dc8e64ca74000346106435557dfd51f80dd7483a5862e0caf611b576ded06dca36f4048e4905f2943d09f1f2926167a8c1a89731a1b368b4fa0537e5d098f03f19ad5881d6fd4cf135fdbec2e94d1b80dc198ac6486bd69f5844eeaa2511539fddd79cbab06c5b5862cb0c8c6e707e74b62feb548eaae6655b587097ecebb4580d72834c9c34159fee61fe4e7eb1ce71830cc6885bc94ab0ff546428dd3a657e42363b8425449adbca4504f16ff38293bc654c2b18a82c3c371a12c758439fd563ed789cbf3068dcf5b6702e4fc562edaf578a25a01fab34a78cca50f35544e8d903a6479958afcedb2f4fc057373bb2be877e5dfa0402d5bec7a04892c7f42490045759cdf4f75e4", .None}, + {.Mul, "-be4cca16b684c35f392de10b574c3a687411349c39a56c68d47e721e29ce29ec81ec5bfec0d47ad762e45b293d0929045cf8f4e77c5690891a0087581642215a9b4a77983b68ffce69fbc32b7904a6131b6530d7a9c8fbab60f9569e9c588fbb1ab9cdab8eaf4980cd01e90597604c31c4bc79b870a4c6a82ff1c633599d98ff2ab81c5b083f3ac5d66c2ade2ff15f35c5ca4805af87", "6748fff13abb37bae2d760c54c3d4315afd0af30dc96f25b5f0d766e4d72d31435c57734806c5d54c2c8df0ec8b0ae28c16cc29f7e2c2f76a6a7108893db44130d1c5fdb59a0dce72daa443531eff1b6524f9822f1a6b3f39fd86575c1dc1956846e336e9dd57aed2982e64d6ae356818e6c6a1b32d632fa734406f1465d99853a22db23be01300e405c88c80c2effd98ad65fe6d253", "-4cc72929c9123070842852d70a5ece9a6d2034d27dfc60ca89c4887cf4e96dedff7b2d622431963086a1274ca8f3cf32001dcb3c775983b1f13582a8ad8792318de6a92a22a2c674ba291ce6a675d3d40f7a1829033db2014887add94d716d81e897d7f461d3a2258ab3be9a82532439c4f0f7dcc74288ce381d35aa231e3530fc3ed83bae17669bd4bb696a55e6bd3082b6e04d0be3f9093256aa8b70fc36ebb9b3e438e7fee1eb2e0e783b099a9384313a1cd1cdbc7ac55fb093096d1e05ab80d515e4e544177bc88e7b60c2d303679d735b9e98e08add626e5746247f4a737e846e1f17be0989e6b616b67128f8de0f1ae6d2809d00d84ad0696393eeb2ea4330a119d9162a9238bd44992dd6b4b02254a9d71e177fcd36ab6305a2add145970d00e846f461c2d01ea6c5", .None}, + {.Mul, "-33efccf6e853c82ab37adf0cdaafc6c3471a5426c2a65b3a584537738060518e823eda10edb8a9ef854373c740e721d1798239ef33f05a67a0bedaa226e2f0622bc2da2398afeaa0398d2a139f9a3b42f02015e855ba333e07717c0c58631e78c87ee5959d3a5ee68d4f90529b2b5e6a640ccaa50018d30bc7a4cc7b6055390cfbfaad86115701f2e8700313b9555f8fc7a8f0a373c", "3e0b26e3a2013a852c40c977b377884bfcaf7c41a0bb92ddaa54ec54512cfe7aebb5bddc4797d04c3b6697455634bed7390dbbe55bc3f8ae14ce11c014ad1713aa537bd963805a68994ead7a8eac8bc69e680bbfefe2bca4fa13a1fa0207576765e7e919f8f00bda9eb05b01cdc3acdc4d31bcc038d36b453168ccfeff0325462cfa842d3692da2fd1e8f5e04a746141170bb068ee54", "-c9656d561cdab03c84a02c3d0aa52ffd10b8f4cbb49a8bec351d92aa86d55e87003a4c4b7223e25af0b2db0384dfd3be4a17a0cb133f4f1bb3470026dbaff14eaa9527862cecd84a40c00ea2b240390d09e8f2aa024dcb0662df8f25d90eeaa249de02e358f55a74ddf3441c01b0dd2be2039a20b57a8a539f69bdd2299a23009b1af11c0178a292f3dba601609d1acb4088332afa2182c6b1953ac2dc4ca3bd37773ca3a5bf7b0be3735b1069ddaa4e798d9b1bfb35858f08ff154f2fc364bd5e24e85b2972986a3d2c35dd13fb1637f068ed365e9ae2e9767ae41f3cca9e3fa28eaca857babff14765c883f62cb0f36eaa88291501416f7ed11ae4a5806e4a17b94f0ea9e827d4a81108522ff6d561a5c7a05322886ba58044cffbbaa885d61de97c5730aee61f13e7b0", .None}, + {.Mul, "-1781f43f7f8e106b97560c2699c2dd6d57a71a6fa1f809426a73471be5d52ddd39aca69de03d587aee207bc9cda225d55cb04bb0df38b8424e9e3bc8d1c263311bc0df0ff03c55ead4b5b7430559a72cb946f6cab1b2564c6ff4cb4ab513d8aeb58e894ee0ea774416f3a5aa05708b7601aa32fb141aafb70dc3bbd1e1280811acdfe15537860dfce2cab67f268a37890141c55b3eff", "58f6a2d4dddafa93a37dd02f0531dacc4b077bfd27e742f77eedd847db87b63ab3992f99b1aa9fa8c7b4c67b2f328df932d7df654639d3fbff024990c50d6b3036b8fa7098f96c8b0270892d437bf881758c1476ba102cd46962a457d0538b56166d8439aec3e05ed9a8aae4c4a62dfe8f7184ec577aea91cc0b4f4d6aff67127c54f59a68367d460be5dadeb661f751d3d4e7a6f67b", "-82b51ca516b26fd91cb81ff29c82bd364fbd6cab1b066ce0dd6304a61c03fc72cd46a3bccd7051b68101ecb3446e3fb4f3a89a344a299c40d9f6389c8d7dd4291c43a2770afd2713bba377659195bb945d2e9ae980de168dab48ed233b0fb1113590f932d721d9b5b02232d92c09a503a9a02aa3ac0df91b35d596f5c1bfa8a93c1dce93b21a032cb97d1d69b68d6b42d83cfb674cb8e42d681a56158ccbfa14541ab27a85fb073502f3ef1a868cec87050fb758824208585bd45bbf7ea2b84c6a3890fe945b836530de59c0b1d75fd7fc1d4eafcb4c76a2e034b3186c00338436ab1f56d6015a68bf57a0082869af6a3a408b0525dad5378cad43e8dff2311c73e4b52425ecfc5e37785c9e7e7815466466d4de7276578cf571db9ede4d1e4c613dd271bef756e73ba4e85", .None}, + {.Mul, "fc7e80fe7d85a5d19f46a30f37a9b8d8a026b6bd8cf3c9773805054fe2ffbdc303ffa3cda3e747f51e9822a8a8ee88806a751dcbc30a75452a609397ae8074883b5c284cb2eb3a1224efa20055c863ee4db847f4f724037bd1e8643b4b8b822e65363ce3ccf41e15beaf8d4e2a6da9ac0ce8be6ff82ed1fd25f69c21ba132daa19e09416767860751a5ea11453e1e83e5dea3ca2028a", "bda1cc5a5b12a7b514b4df4520f6fee7dcf27d4c4db5a433c0748628e923b89e6d254b5d7ea2bdf8ee3162d075b1207907514d2780bde8f9b8162b964b1ef4edc91dba573f741583e80dcb204b1baa6a72853d5598c4733aaebc364d921c26245da8cdafbb9622482bb493308d799a7d26efe2276326e987cc6bd3faad19fddc0925adc3e4bcb1c19bec0a6727f01dab9ede4a3cae60", "bb08fa58efd0202055127cd2222da1eac13547c17a775204a5519eae8f065d619f26a18d2599468c0ef99ffe341102c1858e065caa44fa46c429c1f6160a842e416d9aa74487ce277cd28534100550f187dfe69ee3588c6883012fcc296580ad0b05e824af6c1f39c38e4c45f2117919767324cb5a18da3b91d40460fdfc3de7fa34abf1b16a2fb8000af230b75ced9078c33887e68e4a4960d77ef1451ea84605c8f467b639af4100dc2813090dc935f1e206246b96cdb528cb17a0c1ea6b29e347e996bd4f2c3062c070992407e579c35941c8aca83b48bc8d803212f484195c53f6d10fc661dc21c2eb03026d47026a7f24abf2b022438607aa7172e3df0f267f3e202fd117f85ffd8826bbee7c813b8576d88a45cf21ed59b425a2808cdb46e3bac319e2d76d56d2bfc0", .None}, + {.Mul, "20fedaaf5df55c45513a89335f41ef0f1a8bf23a31bfbb7b0b07c229f1c96fcb3c99ddb5199baf7e0cc86879b7e1203ffc985047671c9dbd1aa4a9cb13ed999dcbe65f4532ceda8709fc5b2edc3f74bd6bbff939b5a8960d3c5a15c44e6527c150724963fc49a2e0ad3ff44853e03cd5809412cf6ff8ea2c7b7d3341b17221e030ada55937774ea89f731e5f711f078976d95bad9647", "da66a0990ee779ade0da2fef31144095d6ae77e92debf557fb87237095dca664a6ccd55d9d358980958d7856f648b037826898b01b4093193986b9ef9cadd1bf121bcad54d4ce47f6d743e2fbf45323217934c107d141704d4b69b124795877a0bcd6ce104a2aee7fead55d556c1fee4a33431d03cce268a8dadc0a7118b3e094e0ff2ce4ec84aea4cbe6708c0060617b8022e064883", "1c2640777acc737a160cac4559b0466217e1d75b1a412ea838ab795c6b89cd23a8f5099643351fd5a43119b29c51abb8eb1c539e164690b818af324fe4e5bc207644b0342058c0b959be64bcdf38c0073196258bbcb5e8a145e81b1c0555543432b8f40139fcea401271b57cd27635b7e80b0f0ee9d576f291701245b44e01e9f209d341dce9087ff04f6c03da7b67ccdc60b678376758066b4ca67ce7bbefcd0420f5f5c8060c536c3fae62286d7b81737d20a24f4d3de580acb8b680d10f4896cded0629db409218c08c01ae41579d5c9bf8c7dde887e132175d8b5ef333f02ae8960ea6a4d2b81ead2d3ddf3aad018bff221834f049508b6429b97d9c4944cd948a3c62d360a5e712c677e0005c6e1ad7ac47674475ab04434057bab00a3ed8e7b8f302157ea303c1de55", .None}, + {.Mul, "-4af207db822fd84f4b8909a6b870a7316eb0a86f3b84025a66f9691dea7e8e8be2ba30470e39c29f2462990a023714d4626d085e43f43b24f849b2ab0b51178ca705a85fb7546ca0440e2012474385439295d32fd197adfd0f411447cf317dc7e3996ade4ec08dbdb4abaf00688bfc74467664e6917ee5e6bd678923b875c254c2d649b54d7550a0d961ff010e8be57da9d3cea9edb7", "53c0e2ac230751bccb03b9257df9c9c1a6db890a89c8a349d0bf1b38ac670802ca4a533f23af5856bc940d8c8135479b38c7c292cea08f46400c92d892749fc18890e32e6540c4ba6e52f4ee547fcab95556d81e6da55a0472fecceee5d7827f13030b527afb1acaa3e754d68f0bfb7fb2ec103ed3197767d3e7cd6c01e6a5417edade9b8e4970e353e7de7385a5614a7e4345be2437", "-1884f06e1fa5730cb987c1698ed9ccf209562432e653ed22a3782d48e66fac4a8ad872b79c5bef061a6c5614772f8d79d37426b6efcb06edf1f9259623f0d0116b3208056de8b11b323b0567d8bbd16972fd0260567b39185c1bb4710c5ef243afc8e56f3a5bfc7c355878a1e97deebe761e378d4a47a19bc1c27fa9b08a9bdb23749f366280f83f17397315e255db89b665bb8c8ab62503acfac8288bfb289bf9b57df0bd2c62853e0e3cc7ffeb033072fb538e021e020884b14110fe0ae638cbbbcd6016b8aadbb1f50d5a3d1a636948138e80812b72d0359c0c0856fa49be38205420e45df9e6f266470ac4febc53782a93aaa5d6da97c316a9e1c890d0cd1c255e8d27e958ada6f3c5fe339664ae7e9aa33fb11b2e1753937f98c1af2c59a9321aa8e327bda70cc1ce51", .None}, + {.Mul, "41388e184aa7c4e618c50be3c5192f57c8804c5833d5f1893fcf9530981766d7d72576ffd982dde4af2c16f7e37983a7c2f0070ccd47cfbd2b335b34c5d5a5bc535ab6f4c1c04d414fbdc590d3cb1b301849bd1f83250f857b4f66b6049e923ae299888af29e0bf5ede07d3124619b959a4aa1fa85ba7ca5c39988bd6b0a98391cc29809b12302e3db7d362c0f36ddfb8b39a23a4a7b", "28d126a8917d3411890c1189f55094cd1396651cedbc7fbc0b40041a0c32414438e9a4329cdb6e2d59fe9efbe24ed639f2f23b89f78dc75a63cdc18e5e1f6a8cdc1bc91264dde47bd99496996fd6e0165a41d2f59d1201187e8bc0f02b7eaf9d9342e15b3ccf1489bbb4fc57600ca5dc271f9f9a1a835dd9f49f152191ff7c9a5b48f2b020bc8e000e8af299b9ed8d15ccb20697567", "a661f3924c4f31eb1ba91c9dea291b6fe44e49ed320691b6dc6be99892c5a2bb337f6ac0de41db35419040b061b29bf2ebc9d184628fd519e3ad71b1da84592261b09b40ce9f778a811f2e3d92ee768bad382233fe04b2155bffde1ec067abfad86bf0b4c611b2358df14c6a5e8f3e001d0f5e1b3d5a2c0a16789aac61c27791669018c02c84310ac646c8507167be8a23462cc4ada394b2cf9613b4a6637bac21c05a9f2ef8cbfc8e032212942456ab240e2f39fd488fe1f0f5f5b9d92855149d2193bea82b4f9cd45ed1180938f9f2c29cc0ae207eaec9f1795ab895ef7e60f56a74a4b2d7ab7a0636f0ac83f73627a0e7f1651c2b6ce3f3c846625eb31219d20f71e0b8679e48ebde440f7e889635ce92b24e0a3dab5de3534cc4bda9bd2d22de73c3297215d5f12e7d", .None}, + {.Mul, "-2dedb991c08d8a2e4a9203fdde8dcf8deb2dee030f7280d50e15dac8e07df9c041727f392714bd744f9d315a2a3e4dbcabeeb0263816bad1d79e63e3a13eaf49f5c26331941d8980dded14b598f8cf36940bb1d30579e88a9d395d05f24a0f5e399d0a8d34bf41b7f7705f06d572f12d808314f6d017b5c8df0111d550f4ef606f0e4f7e0f83faf9ea894102e63190fc83d9a9e6b2a1", "55e09e29f450dfb67831b5edbbcc3d1605d091863c716df8960cee5513774a44c216c839c95bc4b09fbd466e3c0e15b27bf2d37beddbbdd7ea2c4e0d8ef9bffa1221698641b5ada042f347d8969f2995e02ad63c53f1e30e5740f6607c94abfc55440663ff428ebb4d1107fd15ef7884af476a121f6f8e927abbe89d45893d7f14387196e7815f2e085957038ae6813bc619086f37cf", "-f683b0003e73f353382c0f0e88c8634bedb8000c31e37008489f4240e65c18af308c04d9758b4250bba320fff15463d38e859baac40a3c81ed9be595633d7e2ce84ec1c54744477d5941366df77988c7ee4dbaa6c701b59b6027d28163d0d7e24439509886725b3c53c7c8127367c383e38ff45a161227691e924f0a1d2d43901c9cb69da4976e61f8271bafa2368c5401f8d742e21ae70e3cecb5dc134404dd4fa39d39f2766549245cbe0ab23567755daba79c3878814a14aa9fd881e61e7adf07c627f30c3c78b37e69bec0876d3bc70ee969ed1c579145479d467c8f4c708879720496f524944dbe5ea4fc71f56b3b85f66daf9516583f6c16f32059ee426075819896bdff601658ab1adc41d55bc416bbbb057528005eb27fd40c5348ae5af7254c6fd38d66dba072f", .None}, + {.Mul, "340d4ea529c7f81fcde8a5d0d85f49ede256a2b82eb24ffa8b55222e4cb9828ad35a52a981fcd7f717576fe6d5493a92c05ff0cefc7b819e7dfddf52026a17b662ca19546d3eba1d448c2ebf2207f709f696c5e9b763eabec691aa388bfb48c79654a6609881a554fa3649c30f2823a144a819d6c3015f755c063aa4e8178cdcb5307a17dd726745c4d43d6f62d2d62ad83ebd389750", "8e81ce72a7109118638262fe0b08f2e7af0e0258d69e4a032e231c40871d8f1deb8d02fc6d27857655e8d88bcae57bd4e2a3f7eb9da35915f4b905a528114abac1d05aa29140ed8ef31228ad8260653138ce92ba360351b06d15010b413eb428bda1c1f623b8b75e645e877ad749b5b6a70376dbfe1cfba2f716eee023e01d42b4b164109df7928cb3690c562fa5602d7dfc783736f7", "1cf9c64e4394f334588e87df4b77e4027658ce5947d9a44c138b377a2ca75cdeec95c7672b27c361e5db4d2d74545b10aa993ea66febbf9066aa96fbb4f552f8eeeb1b6607ac93e6ac9f75777a97a6bda238a4d8d3ab97eddb3c05f0c38432ce87ea6653de16ebb5c3f09de05fdf70acb278a4e4c17f4fb06ad84002da69de2f9eaed45fc2f830f2b3eec9fc736d8c13ab6111d2788dd7e9cda805e7a5fac39decc42f817d29e59db78912d54dc97ade0d402148a06ec14b18ef63393852bbc2f411633b67c38d81790cb864efcfd0d39ab37d989b5fd596b594d7cb01596aaef0be7eee618701747017b341782eaeb404fbb62a3e1f49a1e184f96402bf2df69e5473d25e2933377a3702dca2769fa9a43ff11338b8bf37e70f5f30798724d30ae21d9309c8114883b4de30", .None}, + {.Mul, "-58bd815d5702394a8fbf5fd6df641f2d57aa36222f512892a193f60dddc7f6f8dc1b11556d5a299147fa13a238a25e924997eeadb8c5c90db8267597b7b6a4feb1a156430ae7911f5a43af94eea2c0ab6df2e0c2a8e352f385d01e542375994469ec51050644eb63dcd3b5f4f043e43c240c9b5871bc5f44146c6502028f3bb459e2d27e93d8e93ad9102451f666a6dc159fdc79fb18", "ff4f9b711e30d7c04fe4868bdb53fd56ddc21fb15668c87aa52d62e8cb0dee0d9757ec35300c76fd7d62b76706182c16d93afa6ed7a5e0c60574d92b6ea30766cb496395f7b1df1308e0d9ca2ecd467e901f496f2dcd2f1c6b566e06476cdaaa537f926f82a3be3aab81691061a8961367b0fc67f0d1d4182ee4337cc6ce079dffb67dd7f497abb44a0459a37e0799ce4d7f29acf61e", "-58805c38d8e9d21db7081b043a8e8ba053e9b1d5020716c7eb69d8dbc9f0acfc164c1487e9c684f5d2020a144a4f069f512ecfa24f134c8e07b200598b4991652d7022b643e6cb22d02ffa095291b2f5db0976f761337f1e5b0fb9c9813e069e2c0a615bda0ff06a5b23514e9c1015b166c103823e952d5865783702ab361f3d070449cecf4a754d84eb3d7b3e54eac7be07c9ebbeb1d701b14f2caf1c94670ddd7a3c7a85db27ea13f97059c5236793a5eb271827cd3513cf4fbbbd1fd7af82227d2911f83159010a776d81877ef809cdad96457646d942c6e0e056a518ad7ee57b65d5c6902afb656486ca45bb7369cbbe1c9e6af20d48639217ea58dcc538412cb75c616231ec8f53404dfc6a290c19f771a4ac3341291fdab0731eb451af365eae34a2a39aac99b47cd0", .None}, + {.Mul, "-70b697b5d73c10c1345d1e83758e8e4b132292d8d90868675d935ea3cf4ebc22df6b5b78ca34e2dcdd13a0894ddcea7e75495893a8f453c8143d7a989121e60811a3344cde8c1a0003a2ddbfc278ce4689a09b1eab0021c0417a52988f5f86a299888836205e3bba6f0ffe47301111a397f02521ff62c88a61303901435c9dead990552bb6fec5d27efc58d198bd4db008c1f45047f5", "2a07ca0b7798c1adc0eccc8dbeca4040783ae1a0f5cf7a52957df2c1b35db3e37816c96488ff26a100fab82f515af407a7c789a98e92543ab9bd16d459b33ca63033e047bff0f56e4edf52ebb177cc78a83d409d726de53386ad13a5b278eb58e5ef2a924b7a797d11f59a7604375f665a0336ae0a3f43f47d218aaa62bc256776bf53d810cb6bf9e9e979026eea22ef120cda460534", "-128162d71b7ee03f906769f2c5c37fbd05c8f5682a3b59975b336569ddbbd7db6b836efa25e8929c52812fb908d47ac7a066742d8d5779adf4b44a717fa0ebe189a11b8c94b2b862e90f91187242105b67e4bf4bb3804b25d8bc0f28753e15180095c0376e82950a1f01bb69eee40a625647c58d54d2b5d35a6b887e5e7cf6c1ec6d072538cae43b2accb88f26822763638182dc33ae99cc6c20287088faac941ff07532dd6a91b505652b59a6a1feca60f4cffbfb0e477ac6692a81707e5835e3c7474eeca33a7fa0ca1fb52513836a52df5b5d7284af651c6a888a348144e9569158e2bb1cd0a7d7a5e7138c3fe4834d1ce5f208a07863ffc902a35e9f672ca5621b65282e765c1ecd4c26df350f20a422654c28ee3a789d00c49bc3028d1b3c14b748979055e180b466c4", .None}, + {.Mul, "60b217c19634aa566e44f2a605275f31b986aef3f9d0c46612f95df85f8c38d67c34bf1e2db435d3a6f328dc5f729e16c42e3296172f2963f6d7325c92d8d1880e84ea59147e382e6bfd3e4998bc804272a40b11233feb9f93e479f2e6c170a1de318cc417eaae02eeda80c49f62039791e3a08d6cfcac9208440858983ca474437772a4215d52a37b9aa3de3d4eb1bcb1ebe9ed2c43", "5c1da26869342d38bcc4ef44213ad07847ea2d86e2b77455fd73561d69987e9a2976be8be310defd22c98771c1380388b6b2ad49b4adb143ca5d2068e84d1d180aafc20d49404d0ea0041ae7aa6d65d8e633ea07555db2a78a3c7a6d9d1298956902d0215ce264b54c82e696d13718f59951ff1217211529aa1326260812d466f673a78f51cec80eaf018de7d0619f81b8f2da571838", "22cb320e6607d9e0aaf8ac641906646ab5731a22d3a66a589dd286437378face6b9454f068393ec44167793f000a684d07917e5e0af371af9f2d531b7fb2ae90778ea4429857a3f250f285eb6de9363dc8e9e05edb75513e1711ea3e4350565045b5bc9f01f296495785b10b1d94a24b1d6a9db153211ca176388dafb83a15f4347ac76a93e5bb27f726d90919503be425b5284472d03d9f1cbabb925b32b76e11986fb1a9eddfbae92dcfb2f0bada6bd3b72d6ed776862cc088d7b24340539151337291cb206f729ba71282b97d7fc73176e19fdd902d776887cbb5a2732bfdce02ef4f32e9466bcaaf911e193484c1176270e75a299a60927b9fa22ef2009df1afd0fa7d0fc83b46db973a224067693b5321d2ffdadf4efc6d49cb754488c2882c060d731c802a80ccf6a8", .None}, + {.Mul, "-32c409e64aaaa4a1a172321fdae99b5dbb7376fcd98090c1ae3f9b51908e62bcabeec063e88c76e5f02c7062d12bcea0b5ffcd61a63952080fffef52a3166b12f44fff9c4ffa8bef38da51a6a43a99b6be6c87f52628a14f2ba0b3ebc046909161aca484f12725b9c3a4724fa791c46a47afa2840075aabe2985b472978e81afae76eb651496b370fd6ad85f9c5d30b6f18e8ecf88", "f57a288e1498c4c4f33a56971141427a08b7e7e1f8586dca4b548726822b034de7e55cd1442276e2b2f8b0a1667c644e81c8a92fdcefb67199ab9d2c0ed293b6d9ea63607fcd8821adc4347ebf59ac017dee341e65e02dbb4bcd984b5d6b3f0fcf970d1a550fa8345652041ac3cee4c8164f2d85045ba1eb314573d74bfa2b1d7acec81f798c66776669d093bc559be6753f67ff5222", "-30add6f0eb93fa7a3d6303eb9d914e6f99b502bb0392358ad2324c9a80946e991148b796470040206d31e80ef655ce21d3405153954b969c8cd271fdd9548c5c480d4a3f351a8ebb0994521ece0cab312b49d141563344d651ca8f7e6bcf926027928e953502e0a81252efe493da7ec1bf53a0801ed74028354817a821add08fd87f45f662accbd12da4fd9aeeb96f736ae01f4da97eb5e371108dce16f0c8123d4169843d125415af8103c545cd6e56970dd13265229002d7b3f1204b1af564e949ec5fcda02d6bbe9a3500894cc1698e38b4e6c8138616bd02202af8d6cb89627db7c19c9612e26ea2f010f78c27e6d3e85382fd1de018fef0d0201acb26b5f9da6c6df1d4d926bdf555ca2a95edcd01f2b2257f97a94b21d8fbd1d536c85776f5768c385bf71de92010", .None}, + {.Mul, "9f1d5014883e4e334fcfd590bc4b295d279e114f9c1a6d5b98604e2a7d2c733755181d3925b14bb456f45e110502798f5819f27b88663050b78e6f77b2b00989157d2797a916437edca5ba7c3572f50d87297346c0d05cc27e654de85ac3cd79c0e8ba6a59b72c655782ff54cbb835f8f9670c34bb3840acc99cb23060bf7426f95205bab2639c969aa8767711095f2fddcce7e61c40", "8c64ac469e221d3400b27dee2b2f32336cdb886ef2852da8e2a3397ce76558beb78812c369ac8a1947f212e684114fd38267b69a888fd64ac8e7d7e2f19809600893091ed9c1ea06a2de31038e0688d351d97d9672eaa5eb9a57cf50eba455b10d33258100692d23b20dc4958df097d5ca0e8baaec82a4873fe63881c0ca7ba41523a9c81872ca91c1cea46efbe6200c503e9697f5c9", "57429a5218a247b9ac8ac66dd9e354e9d5d27fa93ea95f447c7ab2029d646d551b4e32a3a5d764c226cda03f7d0b5a99d79ed4d7d5c10fd1aab1913662935c4db314b714366a66ba2a4c5aa62dbeb01cda433ce5f2d6dba8485573e9c09ff29c198670e3910a3efbba2d9ac878d69ec67a5dc3f6dbf0a2554bc22a8b6e643b1eafdd2a9f0f9434588aa12f9e2ee6395a6b4527207945ba5d2a4af06683bb043667771248a0e4fcb16fb1ab0d3307ec977064ea146a770096fe1099e0bcd83d692785668eb5d84c1ff599471b56da217c9944404ed47de76f0dbe06d48e741ba15c32db3733da873e2e9934adebb87992bcbaa4d0331d9e019e491c10bb5964494877eda3b9ddef50fa7935d69a4fdac222205745e0817526b5e80f4d7e5503c7a0870d8fd526b49976756e40", .None}, + {.Mul, "-af2a4bcd5ddd3cff35bea91252a9e9358df839f80db9f1d2a2ad4185024032c6ed037d2ad129749d37d048dcbe4fad62dc72f550465ce73763a1c6643a2708c5837872fdcf235b6f22905782bca8e1c06e14ffd48f8fc7255a28e6ab25b2a39ff50e67f2d6adb8975e6ca7c42f8fc8f7db0ec5305610dc423ddae7a5680906a848683fac27bf7cf82646d3e2f1b7c5569f0edda16b2", "4b76741065d99a152418661db8884646e84ff5da81600e3211250c7ebd63c7ebef696b16d88c9b45c6be01661782f54a4e03bde4b4a00a1e96ea62af2b7d9fa6cbfb2dacfe52e30335214c62a2bca4f8cc3e7e14a004ca7990d15c5759d741f14249487ad8cdc3c45994087307f094722f6c5dff498cc8bb10aef30f5f88cbd71098e7201fedcbe4877593ffeb0f012064c2d4411b7f", "-33a2711e7dd774672fba5620684706d956ba407b84fd306aca35f593e0ffe23fda61e77411be0c2a7fee5ce0db482a8d16241e4c14ab1e945248f59784d76d0b1de13554591a7f8341c2c12eb754c7e43f829742ed3e9989b3a15c7da1063cacd41d3f190fdb408d0deab3dc9f8b8f816d02446022b8e1917025eca10c28dfd2de44d2f770cfbeea669b119ce3835fee50c6333a82b7363d244a2e68dbf871daa7938b24b3ff83ea73cff46fa181ec53bd65d5a328adfd75f097f845b39743d56965202548834224e0e6dada62fe66354ed2c8e0fc428e0b9bf6f3cf43ee068b84a923c0ed7755ff6e510a57cb2bc762900d254b9b0294dae1d5c343ac4b6cdc6095b8434da3e81723cde883f91e9aa6f71795fdebaea37076cf542cf1a96b532d547701413b1ab2ac8084e", .None}, + {.Mul, "-103c44a384efae75be7935f1e9fbfcd84aa753cdaaaa89917530c94fcc28f092072b607e9e36c57cfbdee08189093528773d45d11f7e3e59d5203a8b799c17a0382e7f31787e6c50ed714625f2be3a6de66e563cd8b7f584add1f1fa24102bc544357f5debc4a00b7419e655d6de1b5124dd2bfb820ad3015d7cdc84459732782d950121e342ccbaca8b896406447a8930bb6bff7e98", "b666c6ef2de33ad82de4ce91c22ba6a5f860c11a262b2deb86293e5ff3c16ed0a99e48a2654c9a51e1c7a27bb0c6102829af241dbf24794b2efa625fe0b5e9cdabee807e90e9e63f672b839a802b4f7b4a2b31558effa4c82af5f56fa414123c2d5a36a2b21cb8a3071762d7abbe2239a2cfd70d9c36358ebacc7e79ce6f46a41f0f557d61d282bfd83dd847dd3e956385146d20a354", "-b915d6d61ecec3eadb4150487f359dfae0068bb52e40708191024f319cefa8932b0f9b051b088c0353b530008ffad6c0e0e4ff7f94443b50fc80945cecca23a6e7ac46579213ec6869e336510813688681cfe173d3568aa2ce97a0d5bf4a26c52725821957864a2e0524bee7cb41bdd7a5ff40a4298b896cfcca7aa2e758f3b22a8f725d5bc30ef84451cecfa33d4c3d6165d9832c9916366e4068e97d5ef62b6c3311f46e0761682ad2c841f39de21d588c3ee026b5987725773411f47989c378a13c05f636f6b28a9fe05c1641f6f92da996722ef429972167f8092900704a5f0f3a47f3b460f12de0be4571010df5fe63ae3b34b3ada3ed33fcba5d05e40061631a636e88064e8219f598838428a65fa616a767a81eab05cc6628790e961913cea700cf777f9a87051e0", .None}, + {.Mul, "56663722c59cdb186f42ad7e0754da6ec2bfcc60b376c19dec701b22214ada2678cae9ea789aed5399b90ba1a58b97a44aa3b4633c5299d642020c0c831617766d1628f7829e32b56756479786b50de78139449b388d7e39e38003dfdaf0fb7d18e60ce60f573cf2ee4eeb48a306e5105e3b01db8a44ebe8c44b8dfd1a1fae0fcf8d41febd0920e70b20ca7adc76820525eb98ad5582", "3bb986a18898a6f0285177a3152d094a6a511ac6097de8466e303eb9eecf68c17bf7c48f0134e8d3dec9e14431c0eeec4565ac58375a5724fe08e4c153b247352599c6b6d5e1fddaceeb178bd58bf71fb5c09ac02020879bb2a9b5c1cb78bfe3e35b3d397afcdb03fcc3d55bafd800198df888ddab084084b0bc2a49d4f387e470981c41bee313ed990d8712bcdd1a4ca7cf04728c5e", "14282c02e0eaa779e371b75fc4fc8d0f0ae208ddec88ebe2a44f9dfc315b6e41e61c852d17f79ef88d4177822c662e54a1f52ab481a133996fbaf0a35f51dce3b1bf84565155166f2e20c7f47f36aab59d2c53e13c68ef2e89c78224fd515a7bf0802304767ee993e945346bf8fab6bc9c42849f572b5127280fa851a1b6c66a5abd7830b35f2282cbb57f511489d2de394b1790bbe1d2f48bdd5d523f0251ba98710df22a415b110bdb7e4493eb2d26dfe0b96045afd5e9992caa6b14ea84128578e1776d52f93af7951e66dc6dff111645ca51148d8990fc26c87f6fa9b664835d84c891d7c900a1dce6d4689d2a90e088af175ef9b2a5ffd3bcd3f019901f74016b0ab4c39df968a6318c8dd1c1caa7a4b5ba3e0035e61246195258ddbb56e7674ef93d7568a4f64c7dbc", .None}, + {.Mul, "b129c3ca16a280b796e5cfd00865064b5da1c6ede66e1333facca27457e3d6896ccac74b3ce33f3b6ad4af24bfc6bc09774a7b21fb464199c5eaff8892683f76b5c46eec28064d480a0dc2f80b44772a04b98cff6dcce13496ba5f76f1a1581b9c8bed699d40792387835052f93234ab916ba3aeb624875e9c4e1b546b2741865923b2d134e74c0d49a39469adaca044eea5c8013502", "f74ecb44909da689c8dfe1fd9d48a59441a60b37012a9e2cf1621dc4dfab39c45f152c90b84cfea37238020173f39855c87c3fb7076a3755d5c9f2ff7ecba9d8441ded9e8c74bad8e1476b7e439a77fa9b2f6548b67b161e6d9d02bf7c15796e2bd327295a26dd10a100631f9b160cc4ee15c5c531698d5bee473dacad6e1edcca70d48465bf42fd46dc7f0136d43f4838cd90c94761", "ab25d34d34d7895468c12793b3249bd67b33abfcf72c7c09e11dc55e3bd32cbdebec4e0d9176c419218e06d15759ba4c724090d831254e46f25fd41ecd3bb1ffe79170e5c5c1d35328e5282af208fb33987899000a5cf5eb8c1da2983e577b9e66b4f4fd1743187886550472b35bff7c643bb1e7976902b97cdbd9a4eb6b000b71bd0377a9ba1ad2104cd4352d926afccbb3e200fbfb24b45d68bea64d5e47a43611e90a3840e0cefc62190e3ab2e9720e48fd3d7dc3217d787042e5130372a97f43e5e239252a673e0a51ea7386f011d0803335bc0be6e93eb1b859c1b3d6dfb38407d2b3de3168725558436bc46d00cd42e7aed4dbb5d36a51c423245e94336bc79984c554022a40dd0e8cd6582bbe9a30ab6e12e8d70290adab702cc932b76d5687c44c1900a6dcbaa3c2", .None}, + {.Mul, "-a507e5897315cdbd9b32e3bdf0c8bebc82c163fde3082edbf64ad86525911e9cb2cdfafe1ddcb91f1ccd54fa20534dc70d2e144e8abd8bb8186debfc06556c553de6b7c8498957ae357358b2a84f130dd0d8acad45af6e7c8df71fb568e4f2cf809753ab88298adf2e0299b694ca3b2fb37a2e7221426af2b828abecceba057e7d8c5f5711dde8259bd623b2dfc11f047c4012a6d5a2", "2968dc20ac8a399153289f032989e8504f991cf6634cbe654edff4b8c318aeeaa5dc45fd8158346211d28cb7b63d590a231d678bb9efeb0b0456be1a0867c30d6dc0294fb0a3f9fd500e091e2fd0aa0b8d0238c460779d7af71d1f25d4aba5c1a8f6ba68d78c3f6a249e4f3950c8987687f1ebcfb6946bc827d48fdb85815919abe9d521f89aba89a1e1dc186b96ce167fe48360450b", "-1ab1dce01cbe787a9905e8d8c8ab8c1d3400559175fff89e88c4973093de5ab04c18b23ae8f6b4ccc17e0413b605dffcbe0f66a485529e5f5bd3d5255df169501ba9147f1275e514dcd8dbbf3876ec75f3c9c1280df1df4e47fc4b813ae2edb4d74eef805a0fabfc0d93f549a20dab5fac6d536e445b18a35968e2919adf3df6a6524c49ad7ab9fc8e4df125a442ac39ccb9dbb632ee2b52023fad215dc8d95f6bc6aba4aae76bc46ec7e168bdd680aadead69fcffb9d808ab569450979cfe74347c8268d462044b5d64972342ee6be23be41f70505246335e25699ce5cd93065fd4f852efa8a675e25dac4190390f4d9179a86de856fbf6b8b128303a82e5d4caba4decb5684b67f08c6add9a2681eadd1a78f0aff148a3dbb7a51f66560c1b78abc76804be9bf1c77fd7f6", .None}, + {.Mul, "-32468844cfe1c05680b24ee7ae11b37c0580846be4f99af278addf4c79ffb9b4dedd9abc3370c1f72af6259f22725f893c52c4317780652161563d36e86fe40e9ebca25fd8ab2c86dae5cf4d9ef6e4c03c68792e8a845f8258ddbd0bacc091223f3f2af3ff7a0943c24eb3c7ab15ded9055a67bb52e09fef9456bca1139546f46999c83a42820888ac34ee43bc31fab84098e2ac5aba", "adfa67bface36b59ff7bd6553b712f1a436b54c719e46f114839670c389fbadffdbcdec6ce4f5b51165cdf32ed807cc56150b5884e8bc864601baa5b7391c9d2c69a5a517f406aa6adf03f80cf4d4566835692aa49daa826533835d4ebe785b84066d319b98134376abfc7e67b723a1f0156499bb8beadabf6b803f89216ff1c5af8183457a6b338f300780f58d06eac39ddc3b1ce8f", "-222ad7579915f9996f9a34b464d8faec68cff6d283daa3cd2364515f254ceddaa46cb4e4f899f4d0db1f3b7a18830563b847a65dbdf882709d316fa43fce81075d7fbe7127bd819b6f56cd9d1f5c46aca8c16cc668d10010ccee6820ac28cd9f589f4fd12b40233d3fbcc0a8a8d597443fe5d6b69c1e3473366a9d737645d2ce907a8559a18cf33f122f3f365045357be08922ade6911d8f24c6088efde01b787dc933387352ba85ed5620be165018a047ee20458f5ee7be49f5d9898c5c3697e325026f5c6f6550cc21b523164631bea1b7cc2ad7d0d3594a88c67bd2290f686eb994814efd8980160a098412b387272cd618cf9f48f1025b20f2e3e57a59e59284ce6ca95483a8d6dbb2e53c4eb671334f2df51955a65eae8cd712d19f00c4457edaa15f3adaa5b7e259e6", .None}, + {.Mul, "-3e28bfbc421ccbe346270ed3ec2a758f5ae9b280cc5fc08fdab8bc5c503715a0539c40ac9f2e2f9f74530347e04c45dbfc0fdda94a16e9ba16a84a1ae6aa8756efdcefe9cd49bf5021bf74ef28af4be39af5f5f1da5ab0c14303023f35177e98239131794b387ac20f00fcc0bdf98050f83e459fe207dc5a61e4f12084cfa11cf79c1adba23a918f4d9931da88a804a723932980d942", "37bc165061816f497085c39fefa25b4f5ecc2800c30be0e4813ff04387a797d0daa91f6356c8242a68b20b11e5a9d69fc3a5286f5eec50d9b3aca78795a909fc5a6b8733403023bac26f52e878e539d4b2a276a46fc1c5fb1b4e0687fc74937b45b4c41f1631aad540df7866bc62d6dadb3c9331eab2c0371fdc499612074628ac6582b70dcf52ac521bf7e0f50a19b6ca424a1f044", "-d886c894557b3ab247cfd96bdd821e47e94de7b9de59e62342fa0c6d431c738722ad43651e425f1338e1bffedabc76d82d50751404644290503497a3f92d07ea54992b57f9ceaf248a2fff88903cdf737c105ccf84b840d3e1e8bf6712770ff3abb515bec552a0e8054c250fa7406489a06cbe1ba2534d41963a979eebc1cec7e3d11372ee03d8b0beea7cf495a6eb0c59ead592299db638444583877953c037c0ec075bff9c6f17622ac5b08785e8de7c677aa249013b2173a1853bb36c59ec25681817832810a3a87e3848ffa8537f23db430d4a496e90b7392ea32f4472d4e6d4dd2b0cbda934d8e74737f01c694d1b2898d53b0a3b12e6218875b6ec42d0da69c291bd9408abb13993a7456979864891870e6d1019737fbbc2c2cfc5b1f7400b2afe4ba8ddbc699588", .None}, + {.Mul, "5715a0ecf738a3019e79a36d86a172932baf361defff391df448eabf8a172ca74b67251d92bbd8a1b70959debc77fc726834faa1ff8a86e07459b9e9cb1267a418b28a3c8e67a3bd186ee0ef8a4d4b92b25093adc032f1d8bd1efbe3557156de7ca7628c41b1d855b8ce29149696d7efadd9f9689888a2adf39cea3e434013489c28decc4f43001c29782020f3b5844cc0ef279aa5b5", "6066cb377bbee4e99b4d2570e9410a3622cd61b384b6ec394915002775a1fe8dcbef2468926af396757f6b0ee82b284906cc3c2759d433b115e4ab0212f68a1abd0d8a1d97c759072f66c65c60317116208b10a3fd9886a0f073c994681516f0bbe69d2632c736644e305ae628e509d1bef8700bc0ae3f403d0975d974a96becd4d822bf7f54f179e48c64245ed46caf69f2dc448e7f", "20cb141801798ce299fe9ca750f320906d70554a63c7cf4b8bd712e243af5d42be1c2eeb9e13a86aeacb10f61df97abbc24c759577a739fd8b4a77efbb686094184ab88233d617bf50859b59d44054ecca74d87cb28c115ac976b0cf57f71aa5ec0fd173e54db07abbb0482debc11eff0ec514f86fc203d5fd740017f82ae9d08b12cfa05a79dc5110c8d65e7cab8829604dc1c0aa24682e200315ef90f62a576337b8e5fe3281237d41d9b90310ad1cc9602180dbc5023df71acca6b5dec5759aeb60641d51eadecc2bb32f997ac9a49dd3c4b2596d7ec6a31364136a0fd25795b71b75db725160de00890c1abb3fe19506ffec536c6beca714a86f1d164ea6c589951a2ad0c6c0a6365754a22dd0f89666bf11940693b67b9e171763b6195fdbb02a757b8aac31fdb69acb", .None}, + {.Mul, "-26bfaecba2beb11f211193899f60879c66ea88a2197d56eb72952ed4389851f8000fc1226b5dbe72e028af11f2061a82f8782aea74de2ddcedc9d41c7d9ef3ed5bb0810c6183a52b8ceee316cae6502543c28ad7b5b1e513ea64a2f78efe2e51fe5c9fbf0565e2849d6b65784ebc6f3950f1df05ea5a50cedb4a6213194678d0031ab73d303c4925e8552358017f7a7be9da3e019fe4", "7149dbd99f74b85e53fa8287a7dbf95a2af34968ca0f12ba97ed9771448b5940afe7c0e4820a7dde9cabb506bc9d714b4ffec3040936df07beaf38d215c48cc4ae6f7335377ceaeb9172d1e67135c21fe815facd8e31ee0fb312bdb64de98cff10c4c844388049598fee49d4ddf74a7a2beb4ba208fc6e85889859695b4e471473b1a5b631e66f34336001b62c64c073fcd1a68b4325", "-1125ca17a60dabb90fb7bf97e38ed79bab9b7f5d4ff1e62dc908abbaf8487bcfedf9e9861ed37f2c204e734d15050b5559b8a49e5d4ecefdee5c913f5ec402179bffbd4376b877c27eb7f8fc832def961f6480af0fdc084f62d78864c2137f522bb521f6a697f11e36a97cd1c4159ad3d92ed80e15d2aa751b52c01014dad39db1efec12746cfd7ef5a3b185714552ccd0da7006f705c32e007ebfef34b439866ccf2ea8a07e6800cf4ec23ad45c571dad047d92988f4b5b156cefdb34f0436c5a3f6c42c662d081271c55dc5d9eadfda6e7119cc9b715be3c0dc745726c0c743abb3a371c7d09745124519942b043fae8e8db25b99e98879a081de68ff72a6eb9d1995b6c20d0240363bf7aa19fcc4c6c7dde919743064aec353c99c7a71d3262dde752abf59c790be0c7f4", .None}, + {.Mul, "-ed8774694b5238ccede299d32d4c2ffebe9176aa8f00bbfefb21f31ca98c40a6668ab855de1345e6c77ac9093bb81e630a7b0dc508589471e8072dc5150368b80e0fc49ebdc46f383655916c29e1d7210374d5632b4a687f786cafceb809ab2e74d73b10c5b8490a18590c74db02b50b03125897a2e5eee6f0e866779a169d53ea0f0ac1ea0f37621079382d501906ab6afe7fbdd2e6", "e9921f09c2a30963329ba08c40b0f89e757e614585ab0c64a2c2d50066a683a623161a4b7fceac7f9090ad7eb707b76ab9701ba5ce6c696c51fc3d47e599d27017cd6ec8312aa8820834c920d34dd510c460c010b5b3dac5840c08f89dbaa3dc021c21b65dc484b577e0c39f9c02a9dbd3de23f88f03a0b459b876faebaaa42ae304e599cc349d467c3dc12967564b4799ff2e2bef60", "-d8b7dd00af0e8e963bb590ba0f20b6f395a9e4efcd7855e15fcb9a6f7be0de435055fb169fec46ebeb02076353410e0b0bfede0790235ba29f790b54f33e82b394199e109e554938653b5f6bd13944baf6b6314fd24b5c9d24a91ce9cc341cba83cfe6ae51ce62b1ce68819ff7bab90cccd0f2dee96f9b2ff03fce496a307e2b0cf9a598764af17d04c4e3f5428071483d4ee171cb988a90e2e4bef49191c80f9818c56bd15dd9231d475dc144d13307072010027d36c8c8cf1845e635e6d146fc6f09931e526fbe16df66063b433ab91f84c1c8c05ed1a0befec0d8dc5e1aa56bc0b9d3ca79be2b737528df6341cbdb92f498578d06e6033c61033911dbad365beda7a1c25949d30030e655ebef1e82e0614c31d3f5586ebb831fe2c67c4dce1c556e2dcdc9d293dfb5d040", .None}, + {.Mul, "deff790efed3e6b6223461ec5d41e23b0917cf473ffb1de81abe3068bc03f18390413dcb7840bf5dda16360135f66aac889fe373cc80ec68cd8468441386178a8742ce22138a696f0243f3f3dfe3828c7f0d7d1029d7bfc749d40014025c273557539dca81717bfb31627bbe86ad8500f55600d458a5dab5b11b47b26b1a7e48c59c368d101980ebd48be24f711ab80c616c5ccaa1c0", "1df4099758356da2c9dfac8e80b39964f07ab748952f88125f17b968dbdfbcbe39abceddd2cf6ac1197dbe40e6da5dfdb3c1ec536cb11c7b02ad5a98ca08da8bf2be935ac27b6c87c0b6be3ed7f739beecbb5dd13085a57568db7643d83a195fadad5e9cbf3dec55576ab2eac95d2475649bf91efcb75bda9aaf51a585e3931550b62bad94330e8d910b0076abe48dcc20970d040f19", "1a178490e5f12dea155509b8fc46d07c8f877e1a4052b1edeb0ce63c7ac3a9efbc5a6582ab7927a094117d2311a00745b0f90da4feaaa43a85c4bb11576541c8970412865859a470b3e7a2b846f8852781b64da6cbecd4bc7fc2398dd0ddb9cb8d7ea7d32d1b21afbe997a4eef7ffb550515495c08325035b560db8d4eaa0e982e3a0bebae4e02c6c50f663b2c220274587a201a1e3d04b41553eebd9c73a221b86a46496805965cd67bda759b471514113864f8b6cff0940ed4b7dbf6c9c59d5204343ae7ec43225a7ed7a121986124a66c4f5d7b6a6b4baa3c3107ada62a39918703df4e66f6104ca1c45c7beb8443fddd5d967b0f825bae1568b389c01db152118307b365d722df452f5fe1caf0bc0dd4ca4ec526a95f882c664789f1ae56db19fb9c6e1002a636440bc0", .None}, + {.Sqr, "-c12abad02eb2bfa25fa8f426029ca327b10ea87e5b272677c71903746db85c7941fdc764b90fba98d6fe2bb160cc19f6f01653538c6696b15c111ec1c07fa798827c365568ef766c7b27dc6348b2b8a800b69327200d866d55263a28a30343b58e4935935d456be5f73dae55f4b68d822217195b8709d0d0a8310e78b28f04a9bfbc95d1c6a5dea512b347e18f7527cb91025d1b330a", "a23e6dd193e5094f3ca11c1e8418037192a451c10230d2d80d031c9c5c5ae1dcad0d3906f8a23e11e771f9847da0c163948cd1b631905da77b2bf15f9a205a71e2070e3d72fda147417456a4f3cc14f7a718fff1e1d63726cc47dad2d321cd38be69d2ea0c885a164bf0c639b0ee690c821b0ec4f3204ef18532c15e3098ef1f2d9f5a934a0fdbec0c1b20f0a4a0e92180e11f52dd3", "91c174cfbb0c04c15ef8381bc95e7363bd4d79d294c3b94ee2846b8e32893a99d23e90c126e90dfdf2fe8ae14dfced81782846e24f2cdc11ab6e0c080a3e2cdb732a35420bf46676250615233fb147399ada40ff3fdb4e2b6cc26cd79bf35ad3ce75b03203b63d6f7572e00ed5d6962e5fd7cf07c18d27093f5f0730d81cedf5e929570ba09bc31f2b29ce6119236f95241cede535d640207b3be29a38ac1300ae8539eb5feb30665c20dcb270d0280ce8c80aaeaba98ee4b78b1c3489b48ef401d2779d8c237e7d71c6777fb4f4a228ab8f4cfd69ea0db745be034eb90bf8bf321570ddbb0d97949344b71a86df4f4b551e3a3429fb44e479717f2dfd8b9e465481087d39ecafe74f60a3ecd62ab83ec390e014301a7f3cd8568936322a6056c5b7735263f6e6211248fc64", .None}, + {.Sqr, "ca1633f8a95c60f56b9f535f8d919fc7134165825df7915a2dd12d5516689bafaf1c6a4ad1846ba2f4a53b9311032f590cfa7f4b767548d8850c1fe64e6c1c4a5ab8a31859da292beea8024306ec9cacafe331949c13276254c80361aadebded13b6e85e7c54fc081b264e431167497f4c1bef87283c7124d4e281183184c7a6140a7e9f233bb338011b32dc24ceb9325e85909fff96", "926d4677b47fe8172d3b3472e574d3017aa6e127f5213989284994253bc06a654d4185d05907f8cc28adb5af0fd26c69fbc208612e879d931e9cbec097e4e07515409fa8b726a59240b4aaaa7a617865b65eb4f071c362d3a2b990b17822971430b166d43d4738d02d2ff74578335d81733a94b099f2379ff630e08337b82fe751a78c6b1eccb7c2ce140143085a490f286d98389682", "9f870bf1648fe9e759aeacb0fcf6734eb0bd3e5cf71d7664add0017eb4cfebf99917334ee4eae309030fb52d3af0462ab01b1a58716062c4e1d804cd6ef9965b66760dd4f587c488ae775367925e0ed5d98bc7836d8844abec7507cb57c5b0a694ed83832c76bcc7a985a2fb7cdcd2012d9a879e6b909aafb87964824649ff81800f6ad45020b346d9ea86e53577f80c2e354a097f17cb778b155858a11de68674cded863922f9adb382acc6290c3be6ad928642b21888387786c0f105e5da63ae43099602285c091a894d2b28aaa41b94c632a98625bcb98a44f3f6460e2525ee901bd5a5df0e5782794b86b8cb02d3c08328bf64115ac85854f3e807be92394a30f37aecd5cb4654a2f9784f5388d36f64032fac9038212ef39a60b70daea1bd4b9f33ba3e1d643b802be4", .None}, + {.Sqr, "ad36b8ff424a9efc4db7c5756653bf4f912e83e0545a8f5ad8c9808988c71678bce9e70d53e92c3c23de25136453d9534d59247bc660d1baf3d5b94f9b8c2e9b4ed425a061537c82602d27b4aa788426c321e48be711116b6f5b1cf0dc7ca5ad729c523506d4ef1b03f7dc96aba6f207e0b9396abc5d3f9a2198c12b7902ea2f3c4f85287f033866a516f5d54d7c18a28503dff13a5", "ff97c4403606b1c45e14ffc0153db9505a4feb1b6220887b2b9279eaf43de01e9d570052e143ed89e7a1fc563112b32b1e7ac2e0ec222e3491e86455125d5cb52b477f8ddbbe08b284693cbd3f6fbaf9b698e2a7834f8c1b7660eb41043b29c0906f65d4c34a1f360579d91035eae56706bbc6b0260f87ee530773834701ee1e8d81feef571ddb6349e038494115b42be940b804d211", "753301bb90f8c02c79d9247d5e7497871f67b047e87a87039c57b34007d61166cacf7291768d0573d904a81bddb285d0d8b9dac1245d513a1c7f6dfc75c10093e9f8d321f0238417d1b9bcd75771b0c95e617bf831a6c680c76e4dab0e0f2dc69e36e056d9904ea1ee03d3fb570cffdd09fa0f4960bf84177ad7cb8c4ae788579d6d1b797a9cbee3528788a408cbfab337ba3e80bf8b3cd78266d0b9df394e92feb18fa8812bc0c2cbfb254844bcaaf1e6b9f3da7b3fb8f9039e8f6d2240fa2cbf8d85d1d95dc8ee83126775093070281bc2e1ff251d52f3c6a6dc709f2bfed6f277451e3aba24dc35a74e968c9bf530e25c5089c23dee6ac82e115f765f758a4b04f138e848f95771f42ac4e2cce3b3a1cf00f88b8f1274ec148af9514b975d8fe64c7c7764a4c637e859", .None}, + {.Sqr, "14c371ce79c3a8dc208a40147a79c0446d0c74ccc276d17ce3c6da52d1fc58c482ad7f83340c77c8154c353e4567629cc464f8afdcf945fdb5d1d65fab4a5eddd2ef00247ee4d5605ef88a537f590f1f5ab097baf55b87e3ba62586db328db91d3363d12732d9a8fb44ec5e5f13a240504f9ebf7aec364ef4051d823eb93b81bff7deab8c0bb89cf71d2238b921681216ea25c1b4f9b", "f32bfefc6e6cbefbd58e2ce63c16cb7b97fd47cfb984534d3c0fb9d341c35978dc427e54136c7689ef6b759bb2e95e53d76bcebc3865c701a04a0f31ba2044eecd1d324c9946e14293f00ef4b7f558b820ae7675c7cb5bc8d20fe753a36dda20cebb23571cafa699ec4acde1c4e56085ce1fe30dadac08aa58e3e64e2283b08eb7c73aeab1e4bfc4def883cefe37be0b92b2a333d8", "1af1efed62c007c904fceca02e4bbc891cb757a972875486d46c057f93e6c91475b4310938df4bdb71bdf0ddef3352508f7c4b146db07156fd2af4906ff2f232e853d5443662a162d2cd782d975de97c97bfedf174c565331c9675cc9dc8a8af6b154511e0d089c6edc6bc694bf2304a79e4c79aac3e039842c44098fd61df981b5956a0edf234464a245295f4cd7851418ca31603253f209135510fb8d74eefa64a61a6ae0f62e0adec0682bee60ad421ceea574780acc4c2dfb5775c49895d4757f86d018f0497b822ef74fea21ab4ee1b91594854c677ccc9e3016d124721876c3a625bdbc9a8e6f290f847767eff2528b350434dbf00bd91e08257c4483e92846195392e49adc7266b9149482b54b8a27148003a4f380e6df52fa51d88d264fae08e813984d4b7307d9", .None}, + {.Sqr, "-a67190e82ed7036bd3e2b71c03daa513c384de022c268d590d5cba21f0634d1e0d532c43da5b949301d4a096273ef75777e95009a67b82c3199d2e18bdf57a18b3bdcda4d26a79d0dd4efc028f38314f4ebfd221b9b9c4f035bb86a9d7776e02710cd30b9910b515ab98b2d975905eb1695bf3da88eb917bf5c1a1af415a9bd73ea7061fe2a2b134fb66b8271dbdfc93c06cc33ddbe0", "1fe2c3606d1c1b5f1ee9021e1582a62f0880d1081d3be363b226635ba5c78289134943110b7e4464291445c502dd646518c38ab8404f73c1228c80a23d5a543c26fa8ae6add024d4cc96874cdc90bebc8f579436545ec1fc941bb2d3bb5d5fbcf791d582fa85064b72eaf64f5a2d0e629a6912d78c4044442c34f813374c332f702e941dabb2b669fa91cc5f4cd0a45cfb45576d5153", "6c377a4e5bbe3987ae1c8f3e93f5713814a4a3b562a6b7c163b7891e6ce052bfd5914952903da52f05fee0f9388f74f8278e91e18d923cfb0fbc239fc354a5b6ec0623f24a24475ab7f0145c0065dfb3b433c986e31837a1f7d520388bf2f3b5235edd70171dc15218dacd2d46e03ab0a2fb963fc2226f41e8bea4435e72fa252ac4278599d68987bf69e16dc819418b35cb64cfc11e35b3e0c3627cafb622922b9412677000906c909b9e67f58082ed673a8b1d790685036c5ddcb73c2a2fe74732620b7b50b84ba0351d7af6bcfa63933afdac0cf3f9696b5d59d355b30d2323ac8ad2897f095a4c231b5a8a8168fcfc9de95239cf6e33fd462377ca53c0ec4002bc37e0a927c4764bbd2d90c7d488739f9cb0461c8d70d46b320d5436dc5bf954bdbd9e28d0e9c5990400", .None}, + {.Sqr, "53712c7153caed3bbf060c6df36117e4909aa26e8415d54f2ffa5c610a816fe4e5549aa2522eef02094c886ac3348b17d22b6af8e095e97b1226277260b1c399c51954891950e6c9c55dbdb39c0f89f58c1f07428f1e027d69ba8830e94f347fdc4507f3d8930860c0321ac43252eaf54edc583058eb8a36706057069f6060b79557753efb9e2cb53edcb091fcf99ccadf7c89d7ee01", "f9c6b5d905c307a6666d4a226acaf0a68cde3e4bf398b99cecfec71adeb7d18e840cd459de3dd7ef92728dcbb0b036b762e158a8b736fc3a7179ea488271a5ec0ec2f48683dd8fe4cf7b6afef746b5677576f802b17419a25e5c75683734fa18b9602f0bee4a47c775983b1bb2e7309860a8231ccd2c6221d435750d9877bcf672d31dd97b97b7a41668c20db77485b9bf0920022709", "1b3294d9c018b5f302bbbe7ef87da52d4125f80c65f39f432e7f199b5f8095dca09f849d9e3a3c6e5800573037d4c9ae44863f2a6518737e55337821facd558c9fd376191228d3fad87d26fbdd175db01772788285ccc26f436769e6b25a1be5e53168f7ac78968aec5f0ff9d09df30942978029fa8c365c9668646092867b782af4a714368b97706569fd8acb79c5f5f0150484019b652dad3e66c1ed97f498a360fc4f523d17eaac7aed3b809d07ed089de8e2a112177d5b0f59de713fc062d236c363b0030f7aa404ef18d898f2f219d2727befd7caad85ddb6fe36b741078f662c03e5f703e867f82093dd96082e18f0cbf634a3c9ce4b4264475d895e875b842fbcda4d2d9e9866a7922b2ddfa3d3d0445db6555e9c208046629b1c6c5f7b63dd82d5a121d6b4f3dc01", .None}, + {.Sqr, "5ccbf2f8ba3d9c3aa4025912b2cb5d32445ca1d426ef3d6e2213cae31857540155cb26eed006e5962e4475c36135ce01eac877857e1a9f4e9feb2aeb333ceca19c596d4998d82dc374a20e2c0c3992f03e7fa5285c627fa8011d736b387036c2099737ae7b9a5e2c2d95aadd345b97389e23840ad745d2ac4c385a5dbfaca419eebf9abb6f7fa7c92c1a0f149d64ae11c8e23967ac96", "1554e1169bb8a1f81badf3cc6f13e165b8d59058ea989c64f78e80f3f4739ea749520a8ef7b8e9b26d3ab05128fd5b883cbc8167a919be7d7b5ffe98dd535996d8ef23b975af70250f2aaa226c1cbc3e844b50b263221cfe1c8cb27d296220918e2354c86ed0fdbb1dae68078733f8efa3ab4c1741fa4b68477944ca6e92fd96f6575928318ce6d2ee306b370f8c2dc047c17f4c3d8", "21a3391e02eed7c5c51cf149f2babfa40a7d7aba834461e4805ad86e2c53136c57fed026daed7f0cb4ef0a04c9dbb28bd6aa3051d10190a7790a254c01ee461563acfd59557d0c660023bf2cb2c946b3377380984f95327b430a9b855ffcc76560279eedb0b5c05051f3553afb66c6826b681868499320371ec562a05fd798014db2c00637a4405414519fb7eec2b92698f5243e38eab02d27267f64728264c595d1777693dcac30fc510c3f3e3f483aa6f6fdb845d19d809716db141e9fdc05b7d6e77e8796942afd68d0f03784f867e28c08fbb5738248677fb1c3006616542d6f0553999e03d96c20c435ab07f3d05b0fb07eb646d82dca1066f0f2bfdb0c8e70d7747457a5255259dc4ed9e8ccbccb44e550c6b313944f5f37e82ea8565a5fd5a12c39826daf210de7e4", .None}, + {.Sqr, "-490baae2624cd6bed6cfe1fdba26d86d1bce18935f46c4cec4046a8f0be9c4acb2208f3a0790652fc91c3894740f8a371ab3b4869aebe28bfe7a5bd97ae3ce8430c350f810a24dcc40867e62d7bb72c8cba686d21040169fb67e3e3ad4910ecb9b65cc2e4f5aeb9fc586432ba2ff2360d1846538a97bb9f3980c45bf3944dc9ccd94dcdc571f5becaa07537a4ef041f153f5605f9fd3", "f43ddb9187790e4f9311d1b26809466f3b8d4dcbfe4f584d17db468ee2d1e2717b25444106401b6d0a7156b5202daecfcda2bd0f895e4dfa82d03b495d05d1fd87bd9422379b14adb1accd56d522787efc552c0e7957cc9dba130bacf84a962c69de6823732bd4d376b8f7dc492dab54e743a1ad1dddde2e5ac9948959c95edc3c7ca62ea9b36632ea04c037fafa6448215fa9ebd8d7", "14d7a7fd3d95b7d30d888e79d11277d8a7171a8dba259e0c7adea89c7b48200ea34492856f43d36cb2231f429b1844a7512a78bdd419b567513a1e8408cbdd228272f0b1cab4a3e1ce96d65fce2cb7ed135c241981a1c4b79294dd23b664ccab1607a9cacc24fc277c96dfa517f8cf6bc3ed5b02b4c75e7689fc3bb3517ef52ece30cc32fcd31c76f51c5f22b3c82b65e1f8b92bccfc25c2b2f8f235fa26ccd4e10d7fdc09be6460db24c06701f85e0eb5a59a1b824101865e80b79e9104d2c68bf41d5ea8f0830f8610689353e654379255f6126d6b67ed029e34599b8f85c07e37173709871ccf8209f798e6cb374ca1a95da928f11a57d441ed48f2fd3da387e1f9029309989114c16155a6f9f1cdee5be0328730eeee2e2ce692db883941ea454a83ae3897744261c7e9", .None}, + {.Sqr, "f3583386b751934c7497500b7673a2444027404bbfb89b19ca4676099b7d26744717bf8a061802f911037b695b65aa1f884b17b4f599e50ca9643df4ca685fc567db63eb4a621887d92ed487eb27edda50ec308e07e90579f8fa39cd46f52f121df4676ff63842c1a6ced4043037b07f35c96560315f28d6e815434c95eeafd04d9dc24bb579640282b7d8582e4925e24d08a5e6aa8a", "51fe16e59dc88a6d3243d3dfba55e4da0e0ac47506aaa44fb6ba4469d720b6cb6415abc942983085c940c1a3f104727f4a206dcf2c9d957c1ce85045687f578e2b2064e505674e5e24e56e7155ef20497c3c5d075d38cee3540208055046de6f542006c9ca6ce07fa8d4ff4539e6640b935db386847b358e332d4a8fcb5f6c582fe12134654b4c132a5db66dedfc4146cf28819a02d0", "e75090353701d9a75743cf10fce053ab73e4220a1c92e606f2ca8e32bbcef29ce4a90514be81ff05117601b4477ba9afbf7a022a57e2e9ee175a36a4f76d655ea31c21f0c6bd8d7ae001e53dbb9fdeb15fe116ebd489ae0d1d6ad519992c0bd4777791ce272f2eaa5485700d74d8b4caf5b56c8b1c759e0687c2d08a087db30783afc5b0493d18b1d70f2b8f9767be03c5a0beee064fbc8426a529ba4356b5f1d1ca804f2050da6f272ff8b686241f2bb97713b5a7583a5d634478086231e0ab04cf22d5aeed50c40091f8bddfd682a45a11c5e76cc1c6debd5550642a2a4c14ab0948ea991e2bfebbb52f1deefb354f646fb7397bac0bb5edc32b224bc523e77f898daee9ce28d48dbba70fc8a84b5133dc425a8dc8d4eb562c5e3d716584883c1ea75c8c2cd44cc5939264", .None}, + {.Sqr, "17d47ecfd9e4b2652db61ef622590e2cb980fa723b9ef3f5e82e82cb4d698e61b01ddad91302273f7d6d93c07e7bb9a53930ba36fe021af9d6eb4dc8b39fefceff81e69c317158b9c8861494382ec62bdee1f2f63ef984d6d24a92adb00c61a5c4cbb6af1a3cf953f926c8d848ae144cb93f3f2a15104e2af913482263334d70183b6db06bd8a3ed0d2ec0b968439efc671271bab21d", "5fa44389c49e6e19cb2bf20dc3baae637cd31d040c1b8dcb0be29a5e5fd5011276ce6d05192bfd0dd45c8cdf42801f812b95486bc9c315dd5aeb6fab38a6dc80a4fb4dc2d7b775cee3280c83859423dbc87b33383489ffc4235b9cdd473baa3e59b7472eb379c0c39cd79ce079b5dd1c61d8f2fe489895190624fb9c1d59b2e0133d317efc7fbf292b8caa57ef51c5199cdc6a1df8f7", "237df2ba0393e14deb40a907cde485982f5c4a4def4006b6ab44227b40aa27e0b9d26caae3f678eb947976f43e434cf8ac35303aaa4a5ecc05d25c6f1ac6849799fae6a9dd6a5b9e2469f0e71d2a8d6df60c5c06f1f3bcb536ea6e8f15079266df5a6c26ea67b881b19d7e9c52634416e62f80f68d9615d7cfeb5fa3ef29cc4dc048bbd30056ea86fc412dba356aef4b71477665d48a03f33f5fbf50bf82a25c6a40eda301d0e895b3ae50397bd3b7baa6c8ef33709bb3fe88e496c89823b58105356ea6108dee8784fd37536598b37ee36b057fe9fe7169cd12c8ef7afda34e47219e2597257ab18018bd62dc7bb742c7e4345e5e9647ef40d37c11cd668388ae8e2f4f2a0aa0dc2cc6c81231b093f5522ede7411903a9faa5720edebad792008cff70e132bb78e8105749", .None}, + {.Sqr, "-6599d2b76f028b4ad4d20e70e16cb4f95eb83317ba5c86b025e0abdf66d4b40e1103466594a67fbed4cec78469ab333ffa36df97ef14d667811c99d9a9c66f0469b22643d3c12b340065076d4df830a1a1f63988244111e89f54733595dcaa01267014f2f510a19109e95e57d0c7d1b1015e054dd1e4b0c412c001e4b0b41ed4034d9bf96f93e5b9f574699d9119577889ad0a3bac", "5aa5e9e360a2af1c3228a5762d11bef1b12592156e75f0f23a5a00e70ea25e8fb87051c67ec2b384bc5f36f582dbde55941bed8d0fd648f73cb3438fc31ae3da4e6baba264ade5b0b94414a4e76c73b176f0535fa9ffbed365073fd48776c818cf84ecc9a0cbf274895d3b3b32a2ee352b979f0281bba04d790dab8a3155df2f1e9440bb54379b83f94961e2cb76c6f2d77fc03dbcc2", "2852bcb24a4c28839dad41709652e6bfac6fb961855ccf463b10f0273de9334fbf2f406bfa599285ae88f67bf9509c4aa75ebff81379a4e6050b067d862c47e683e8e8f8ecb6992b51d4e31c53882474b1aabeb6d319d341f007595b7697c89ce969150c56291fbf87e47b45b787cc7e6c085c8022d42ead616aa89e1d9dde66a6e2be00cd17c4658321a8ee22eb444c07f575d1e4acb6c5912e965bd77717183bc6d3b670b88fad3748092ff0f1eaeba2eb85b01f7436cbb4e732402a6292dff38652d627b1bebc5e7d3033688978ad08c10c6a85897d7faac0ad5d32573e4638d4ce591b0c9bd6e4f0d2b812f914c0ff079129da9bbe359a1041d8a9e5c11a199a2a1904aeb87f92f47baf48648df6abb2fe0d4df882e2b9ecf0bfa553700189b868c3f3272f58bb90", .None}, + {.Sqr, "449c67d89b619ade753dcda1db202667c2b1b0d7c904c770da79c161b8abfb62999a2605c48ff6c83c78c91ec3202f5afbbc51ba1e72ac20f332fda1500173d5fdd70d9bc04edac9ba33531ca6c7b940e57a82009beb16220d63bea61c4bd565a382a22da552a8c251f024a02fc89ab76f4ab05928cfc365059f524b21ad3dd17de8f417e87cc3ae8cbf5d1cf316d6495762b8ad1a9", "8b73039ec05ced44b293f3f31a907dca4bb3d599c6a14560ae602cf911fb4609ee9e0f2ec36e82da8a6d55aec307084c010057f8edeec4709850bfd68e330a909d467449ee3a36bb6d8fa7e89bd1cf66618fda44da7cd7037d8f20010133f13dabcc6973620be8db84e5311395ebd75fa8d5c622baf448da4cccb80f63c125477f0ff7d1fe1758d465611b7dccb370230e4e644f91db", "126376b9cca93d8a0b0b690e49ad79414f55e660c2e63060d8f87b0094b7f0782c216c363a250bb428903088f179f8faac8d25d0707c74771261d67738b0171b831c42e16fc6c9b2c7f645f18e1f324abdbe0f64714d64fe27fdb482afb2fb3b7cb8a3ee9c769b9571712bdf9fbee414dd02cca9b5fe7af57c9f12203489e9beed6b4adceef1d378e5723de72c4ad1d4e248103739366009772254b89acfcb1bdf4f202b34a87eff3700d8bf3c3d1beeb0ea56ea3247352de993414c2bfa2d8b875b19a55a5374622b21e9586cf2ad0711a5fbbb55f23e5f1b6dabbd6e44cf8b2c8aa6db365b9f7719ac956bbf32fc659e20b48b600dba6bf9f823a50dbe38d19d8cecefbf76ab4b91cedce0ea6d8496d741980f28784e45c1ca62f5fec070b6ce90eb7977ef817be96191", .None}, + {.Sqr, "ae0962f03f751d805693967e00024b43d55f8aaa4b4dacb2c3cd91e94944c713a6858ea4ffd5bf8ce7daaa3a0d21e2d2ddb42f357591e5996cd5323bf02bd46a48517adf5a4bc50a7b376b9982a10ae8e5718a713ccc97545d2862786aede0190e3298ce0640187938edbaa2b49d1a685c7afee3315d9e1a705898fca3d38b5d3b720266274732e9fa163f0f9cc60366f2a302624690", "2cf7ed5fc31d60638acfeae38e7be18c4e2c64d78a770cf30f450f8de460fef524a2f9b239500c648009e915421e063b7405d088561b6b54787e50ad67cb1465ac5f65c520f9e2e59b37bb54fdceae7fc95fcb7f3e27a4c4a18ae0f1b7b10bf018d5cac9b046331eba7a87f155827b7a19d7f38ad819b5787382d558992ee2584ad6fd19072d4256d2f9720efbc6413fb3fca092deab", "7650c2d6b1647c633e9f23f85623dda8fae39b1c0331682a1c0104fb93a3136a70834ecc78c09195ff53f396dd74394ed756897c4590ace9534a01b952b37abe7fd586179b9a6e9df5c3e5b6ef0f279c3d082074f662fb0a341e410b572b231e3229ca4ba203f5c7399a644834568cb3546e8a9f55d03cd939102ddb9fa668ec2a60594ed49e8a4a884b8aded7750d8693370d8f5ea7fd4dd084b1b038ff6d260c3d6ed2cfd7257298f3b89d780120b4da1971e9f714c7419f7d8cd0485f124aeb665155a961a3aa0514bf26894ba3ef51b58628e89b049a4f422386eed485fa8f634f19f1d4fa4d79205d98702807a000fc7566fcba2e13a3ea73283c24d103e312ceda2a316826460bed8a2f8cda366d9f572455d5b1c7f4e6d1cc721d9924acd173057153ca3459b31100", .None}, + {.Sqr, "-5b26a4bc853c4e14cfb4662d3337fd76b72b3abca0b6f878fbbb08a9f56ded737c1e2bb5b1024c5a3bb093021268c5d857303cf86600035ca3995c6e4c18271576a9d2d2d2f73f42aa3167f4ed7bcafb8f999181cf9e0884ea8bd4a22125a2db88394d2d2642ceeabdac5fe5db61d9ca04773236d478655bd937c230dcbd53d61e53acdcd219780a224155a8da9731388c54db1deeae", "f2ed13eecf1c4d4faf6066b4c2abf28e0c2e28cb2d375aa2489e8b7dbec76d7024bd0477b35cfeb2a3c6b217d9aafb010b19ee5027533482cfc526bc31347560b6d88bd16822a8154b7b57de2094b2ee9485f8a3706e7d2956f86411ff290f24c35bcff37f0b47198f6fabbcfff0eeff19fabf1e4bc88a50fb2ac45b69f469cd32bb9d5698ce2970e40f14641b8ccd086c4aba98d55", "20747ef358b282f333ccfa38fd187dd283d46be32f5b16d2d501c9fa3d230b18770d35a790560b3256fae3340605e51baa24518f7a3840ca6a1fb24b045ed935bad5300791d81a4f7df6082ce5c250f3da60d6b6a87685b64067a7692ba782f530fc241cbb1c53e86feed6b1a63808098778a0889a0681c84d8c886e624f9f7ba59101384646a75965cb2f43f4944ae82045512199b939e0f36774653d004780022a29563335f988e915b7e11da0ba14e06631525e674ce112417fe7c4f90d851eb5a4a095443c53f135ba39fbfc041ac6c98597f977faf5347a9f942cba2a599d44f7186d58d4e3076bab998ce529771933ccb531bd70d87c8eb735ca40c00950bc5427d3e9485b136a3fd18f17c68396c9dbb4dc3e976c824f11e8f03fa7a4761e27844c5f2c0da5f3fe44", .None}, + {.Sqr, "de75d46bb1fc2cbeaca9e5c7f596c76b67fc53d81a004c46adefdb55a3f89c98f032fae1f8f5aeccee9252aa19235eb8439d9bca672856d5d5852f84e5d6cafe29865bfd8f12d833377d880b96d6a156003ed1201ac5627bc1edd20c0e29cdbe5195243e1c4f61bf1c7cb7c0870b4ba02c6afa90503167483a0e76536e62e33e546485d7d990fb78db698b3f56fa943da068a0790d41", "51314e692d9bc7dc54342fbaa2f2357a4c7216a0bc4e97b1e2e76152ef7fc47c7c47a8aeee9f48ce14f25dd4850d4e8e28f50788fd2295be6137cab8e603377da5b50d1c45ff3d5d273675ac916120caf4d6aa52ec2d0359364da5a1df8b2a2e4698cf7d4ad5c086207f090928d6756217a0f648ddf836ed2d4688f3bd33fb9aa1cfda9ae59a5ef40c5bd705d263b00726a0ad066e81", "c15092a6a3649a33886861785b4a3933a1c3d56fac4d14c4a1f6a7f05994948502dce8f741bab2ad0fd89fc5774b49e42996d96edbcefeb395df7884fba49d3181d9926b35f3f8f5fb00e0f433a1d5911245ea1f3cb4f5dca80e4df1698b34946ffde51c3043b7e96348d63c099259261aef095889b2e772c54cbb6e1af17f23c1379746ffc4acd62c8d0321bdfd42d9baad5e4f56064fe9a407754a1a117667c74f2a5a1bacc2c3e7bd69b3508f07702dee1d853a867f6da8ded1e93b130dbd15d661e56172ec28da8e3456c1b98853674098fb8e81d77ee34eb31c522665baf6f854896f79fc2294c876f43cd9cf3f7f66f27c98172370cf03cf538b2d6f80c4e99362af15bc4effbebd10ee627616ce98960eb4a1e9462f76b8627aa76dc4ad3ef351907d8e9ec821aa81", .None}, + {.Sqr, "704cb4f62e1c92291424a3ac9bced944aad4a78bbc46971f8c52543beca01bbe0089169e9bc298715fe8b932d82051187470534f7c9d27adcc0f9bb03fef1fc91436cca1750351a7751b5a834947c09eac3c3d86138e46a009a9b9fd63e5435c4938aa214af461f37ff628f1046a459dee245ad7ea6e48292cc25d887bbaba9f0b908f19561da91175070e4b989fec66fef2b8a20eb0", "54bfa64a9d2413b92e428f0aa32b1a6ab8f29df37a99f71dc7568433c00404407e3874c3eb4b7def7d649d7308b6c708b5589f35243fe95e3ca4d9a13cab27325af31462eab5f477dfc340aadc27aab2a2e01fcd06f1a6164fed6e4b7ccca8e6949c3a100a92b8e62a9175562415aa1b85729941429a9fbd50ea42a17dda00bb297525b8df99a9aeb89052397ae807ea72caa984037d", "314335535a6f7e6f8ec4f7f58313402a7f151a38920b2bf5929c91d7f93a69da58967fc9ddafd0491667c626845932d8ceac7103816a69687f74da009545a163fec2ec390296df7d59bc9bbcb48ef105896ce0d6196480da42b291a8b38eb3d058c23c0ee81137424fcb7677dc48b11f046673b20b02266bd8028740569ea8166acfa43bb49727bbd5c3bf05a9d90dd739f143e24255286f65b9d7d7633a0b68ed3eedab0622953fe494e73026d1472f44a042a620885fcd9cc27d6a1bbbb686cb7ba41ccc85daa3e14f062099babb614d188618538d5234dd769fe13d0694ba98c1d319631d18e137dba96e1901156aba3db99955006a173f2378e0360898b1ec0eb13a743b4dc16a285105bda9b68e46816825a84fdd3de231f3b24d129271519bb75b60f260739797b900", .None}, + {.Sqr, "dcd67358cd71ead402f4bb48bbee485e03b52394d366b2dd4c005063f841b770e9f9b76a258b978e824a2e1437f69c1d81d8aa23e3d674f5ace6db6b7c874e932b5fb9c02d90c16c947fad0a62707154dd653efeea96e8741f94f622894bf7a07bcc0611a28ec80e2d52548ea738ea4d0c199a58fc516d4c474d2d82a3d9c1269d3ec8e36069e7843e54ffa9a80f1c9ef24dae317697", "4b5c2895acae614fcb747140aedaff0bb5634c82ed75d997c211d415d3196c6b65ba829059cceb539477dca38f1aac807433979c465f50985230ab87edcca52f1c11f1975922a184ca88b504eac0a29aa86fe0ff195421222d69c5b49353b5f48c995661f06d3d48f9edc1ba60a54e2012629f9efba1fcaf0d20677b8b960aec46f562e0b970e9a1590a9719c019d82049452c148b97", "be8149e5ad8c2d733bb52440bc6eae97fb552d2295268955d5eb70dfd1fe0ff19305c0a62005699f6de04b2843d32c977861f017058fe68a0cf8fc885ada6e780d587efdc23ae05d95033538fe9d41133e40c1215ffb4a566644b879ec6a8a2f5761df2311326b4734111fcc76b04bb312c7ad798d4e657166ffd35ad06aa43d8ee06b6887b98db353d96f25a0d384ff62cb4578dbf988da5ab321054c33f9c614635366db5ca3dd6a6823b3fafbbefc6ba134e9d6a3b232b5df6a919529a8459760969b1abf6ed07fd24c6b48f9bb0652e0596974c24ecf12239fb148ba39e30915ce9362a4fa9cfe254f0ca808241022d9b2d15504f3131db5cf1a7ae96296318120e0e32cb0204d36cbd66e1e7efc1117b16d3d9948bd80c05946bb0f0013b624e1992ee21999e0bd8d11", .None}, + {.Sqr, "-9e80256b77eb2e23bfca7ec5a59f56cbcbbb3b93edb6aecdbc14a0ca9f9de4176ccecd3714e7dc8f84d27267d9a6d3e6b2afa65a5ddc86501cc51faa1f6a97bf75a4b84497f25aade37200ea39c1054fc4b9836efa59a913c5e7a7b23eb712ede62f3ff36b4eaa2b2a32196711392bc3f6e9c357026e63744fcb4191f4715676f313e68a6a0c9a170511a2d3a261e6cf3c2475abbafa", "49bc067387576712e1d3b848110ccf65a22998bac642353d31e43dddd743c312c1dc36be0638c695e5f3e64a4474d39c1e7e7a2ccef96b2993dfe0bed15d0165c5186d220400916faf314e4e2e1bbc05910f54ee7a8e9985e60f92ebd2410b9e55e62c2e5591fc113b6f17c0324b865318173749ff7f3623885442887a2db8a60fbff1f29f6333ff0d58a6cf88159174f452e3426ccf", "62226e5618f675e9b69923409442a71e23060029353f25826dc6bce132e4bf7845526a1d868405620cec7bf567aa769e82348e5e8fab832a44c2186b11a31ddd178572dc08ed4833e9ec42ad7afbcc38c5873bc9ddb282286ed08babd4e9d60b35cf01ce7ec4f87dc0329546f5fffd063f18b43cfc1a89fda7990caab172c4b407b0cb09d3f83e80892bcfd5314e99127f75dd168ff451565835fb35f62fb7b70e76e9d57d36000dbbcab945784ff9365e2d40dd4e4344c69994bdd4f273a58c95c7fb659419eed581e5fd72b08132015ec04f59983c1ed5eff312cc24e8b43c364ab31ab979e9a2411cde1948a65331922b93af742221d9004b491209af2502a16d01ec76444a717dd713554eae853e449cb839b2345d2e74f889fb0152ab50f96c157f6654326bd68c3c24", .None}, + {.Sqr, "425d13ed5f61da9d8fb4296739d281badc195d2cf093cf9d0c2afc1681b2f37b0a314bfac8b3ca5dc981fff91313f4aac03f736ee90a648cd98d880de0846342c4b85e42134c41f9a3c1c468a436734228bc468fdfe5b44fadcd878265c9e5b229d53f0927d8437964b1a4d49e5c5babec46fe3935ddb78dcc1ea4691292ec74703da9358ca0362bcca99f2cf1343e8904df115e817f", "bf51d5112adff924e7594676cacd180017a3cff58d8db0ab58f2d4bd71839f43351fa1cea26dd76c9c23ee4934f547de6ce3c520f1ea7e7400c5376602161fc705403e21e09529f7db1072bdfe9dda5dd05737f578cbf03bc324d9ac6e7a6a7e8da7e25a2b7b131cd566c762ff786da75d00685e875e21baf89eddce7891418ebcf4878fdac226fadc14714726e6228f3d1f14f9fca9", "1134201de132da1459bf3ef87749e087519459122c0de6e487f5144129b6e9da483fdadd46651a1774c752e61ed3179f8e4821c2632278d7f9c1a49a6183b5fe05df0cc7caa6453a3aa2ae98d0eee248b7803d193ad67789b4254b7d0b128f28132fbc194a3080c36c7d76235bb6ab88d668da128827dc6166741afc0004ff03963aa5988006d2e4c3bc7ba478319d85a8854c74bed32fc27f0fa6fdb7601063f6b7865be908880cff5508b755e3d1ae1073815250c24f1da4de14ff79c327348baabd57e87eba50b11a32d952509ee4404333cb6496146afb1451bfea9ecf07d1da01d9435884e6b72c0984599495e6a5c1f658858ff65d733a36e45a696e81fed57b6acfb5d814363358efc43815e45ddfb6914c0046b3c23188e2d831600b871fd26255cd435838c53d01", .None}, + {.Sqr, "-23233b0e31022d1ede0dc97c8bf9098d04688cd658a7429f96579c64e5ef1ef81e0a4cf0e4d4f6965c292f2c67d78375fe49af940df50ba9e3f4a2a9c2afbb5f2450d92cc65ad0a1eb5ac8490f9742a2b27c26231a887df335f0556047192a16369486b6d91ebbcb8dfa972ee372c5a951a5d67cf36e6c19f0c07c5420c27562862433773bca8ca74e347275d622b2f3f999c50bb62e", "2050763c90b3c97faeef17d19170dbfc2d56161af698c6050a9cdde998c81603ec3570d29a8e33593c26cbb3adbdf411b57e2fa7e02adf0bc2b5b690254be7ccabe97eddbc176d73cb4cacc0f893d1c9b57d52b71877f02a9be37a7921a99e83384b82ce6c5341fa8335ebd964ba0bb27dbaef2c0d86e998341a129f3bd2735a69a343cd81e79575ef7e76350135d8d1c3d0e3b1a4df", "4d2a6ff14e78a4f2d937be258266dfbbd9c48b260d10aa933ce8c0c1e3cee14d19a24ea37e3cbab80b9ae41cda4973b4ad27ba4b97fb649557bd0dea6fb24ab4ec505f8ab5e9426dcb76aa66a9057f75ddb1b6b2d118a76e43aa82ee41d311a0e01847783d14ba4a527a6822bc19193882b8d40f25482b2490638c164b6d0a0aa8149bdfe994cebf8580741dfe13366fa5f710a799b8223b445409c6da7af6bca6f59d8926b5de590886bf0f35341575ef9187394250e6c0de43125ec65d7e0fb12f8ae3712a8ed07b952ad06c30c1675850a949e87913877bb6dbf5fafee2f6feaa8ba621c811a040ba679d33210d958d58226088a3f088fb956986ab77eca59ad9a8db79b05504904a5351d49dccf6efa16b33b4fa7519aca98e0350a278b0d0a2779bb6445e7f5997044", .None}, + {.Sqr, "-3f73f25033211eb1f9ab19550b6a03902a8983f4eb3d76d2420f9cbc87955d4db07bdc6b0649cc2e71a00ccfa355613afc4e4cdeb72f27cf1fc2a9a3fa94458d64cfb624604baea4451a77b0b9ff9adaf577f034781617d4e1fce42f11ea298faee881014c6e9a42c20230247a5bda22a312e5e515ae6b81702c95470d3eb35e2a4d9a2c38bfeb76dcbf3a0fd7d2b44b5f744c722e32", "f79b3749aca7e8465a2a1308b5a7428a09407b2e1ac01abeda67e8495766c48da23ed249af22c2539e986bc18f3be66a5f24301ca7ca4bb9ee9e68e6dc1b0d418053f231bfff6d27709e60779d5471137579df6ee58b98be35387df467327c33dab4801d2c43120439ffe8ff2997deb26d991ba60cd2b32ee5eb2e172b961a34e98be8b4894c77a62de553875fe9e3e648d696d1ed33", "fba45c71293f6a7c9ba67f7fbe5ca2f6ff51faef520cbec9f62f923b2919a3d22b265c329d1ed2e5006528ddda8f4e9ca24975ce36f7e89f7657a8c4e650f64a5ba9b2881fb33d9e8b96c7dea59e578fb898de95219f979856818a8b2564ee9c47965f83e16259b32da3e9fdda2c5cb07a810b200c9ce61d6d3d7aff80040a1285227709edb341b484d6d907970584b1711bd7bab46ad5f4c9c5df83588b69cba47ee1cc4ea8627a06874ef10d0b4204e714d39fcb7db08a83f02343a4891a1aec4811ec25c5ea3f139b753ec42bffb5ec8f8d06105b4d7fd7118dcd4c052cbb663916b6493f17e18a6c10eebd0699f54d20acc8cab840befda0015e89c6b793b8fae85306bcbb1748a8eb249154976f759953cc3c121b0a2361bf57b1b988de404a7777de2f7aadcde01c4", .None}, + {.Sqr, "-626f1d383deb9d22e4abd638544edacb189d7990fa7431f7a5ccbdc5281cb5b7a0f81621bf4abd33f36356b0a8da536100f3829d1b0ffd7b2feadb5a2afea115bbfa0ce1441f06f263e84910c9250366a1d3e57772f8b5bee1d7a4a11a065e7fd944c227003a24555eec8c613596440df187439fe2476fbfa35b2efb8339bb7a8df35e166c9d5850f56e033849ec01ce8ec0a8377258", "9de72524de5fbe59e1705a6c9ee1a0bea87694268923d186a1d275202f9a24f4eb8448cdaa12c6e60f8c808bfa00548df6107ea4d35e1ead6fd606bd4bec09133c0c4545c19a93237dc1fa42ef71b7cd204b94204cbe2e727f468808d2e800cc91354a079013b3f7e2d534e1e55c56de301c2685245617b375c21d4e1ce7d485e2c4a3afd42ec452391f0bd35a68a59c0b6bf15c2b8c", "25d942996983e10382fea5d65e9980726d4a8a66ae82f6cbb18c506546ef7604f0dac699caecd68c97bc75cb75dda57d839b088624dda232e6a74d68982e656ffaa20cb57b252597314e684afcd544127046dfd9085ea812b04de24171782c097b9eedea43049f0e4aae725876dabbe67a17116484687df29352cc97bb5484d443729797483d3eed459b9dbb1f282defce34251fb9e45ae97c4bafb1925857c3bc597ae376fa86a4da647bf77419b59c484d74fa21cee05db954514b50c9e3c4bfd103f1e71b4d4ff4fd5fdbdff828d39b1514e9686f2b67acba21243e713066351fc7086497d56b3f7fc141c46a59b59af835c8970a02793b00479ef9ad66e63906a3b1d47d663069b5249a98a931bf669dd0e974320e6def0f4510c201ef7d6aea75fafa2df615d4e27e40", .None}, + {.Sqr, "97abf2daadf3f930134231f17ebd36a7f954f8be763ca5d7a710f1928526d105704740f420f6bad703cc993f204af475be26bf02fad878af730a0dcb3c280be904a26b11b487fcdb31dad635ca50e747c23ed0d45fe04b66714780674a793f6d5bcad09d965a64615cef49ee80605260054764d13b67a570170e37c3dc82a7195060d6e230a270505e7311ed0448be0a54b355a1834c", "30e8a0d4b5f51e6ab2eecad10574c634493f82449b5a33f65aae9bb0c4417de88491d05aa94053f1690954c88e0ce567f4505673f5ba9386b6fe1c26fd2dec4e76604c5519dc7eace7ae4573ca8e460caa7082630fdb81cc0ba1410c7095137291d5519233f1fc8b5e8a5fa431ea0b885a4f2711ec0fec853602b8761792488ce2bcdc45ba5fc29a57f75d4b3e3ce5cf3224afd8c403", "59dc4bfc4fbc5f9399c8c2f18d26bfd3f74fbd265128741ddab2c1925f0e31bb4b58395d5cc8e7639cc0f235f40346b43778532aa10764ccfd3256f6cb74dc710f7fe5b56a4478933ed7c96e8d4e5b6ebc1f98292cc0b5124d48b56579d5300b59b0b63517cf6499076e826353b89d72c1ca2c2c063ad15d66faec824c52d5fcc08264691fbc700c1c92e074aac050dc22757eaf442490d9ae81170c1d72cb6740201e067d6968fdc609410c23e154dfe2aa3f0991abb2be8dd93e695172e0f544b46da1ab30974e07ff6c1325675c31bf16c415b003a9fe79de03cd794f6e3da476a8d0f230414db8e917ac19b0d47a995ab7d6443355e1c87d1c3fd57edec8ad2fb08f53be5944edc81bc30bf86bd55b1bd8013bc610429a54e90285fc5c7756d0d815ec9c235ee0eede90", .None}, + {.Sqr, "f6716aff74cc264ed776c0929058957b5a3c1ccfd8e9ac756bca27999a3237beba9dafb38c405d29576b7ffe06b660fe28200579c6a50ca29cdd131380f213da460b11b604063a5cab611b27b45707558512a4645063e9c9576af42b76d6485d4183d9055e275b152710b3b8748afe13bd920e1f89119da552e46d4097854e6a1be9935e669f5def8ac8869b1cfa9b8ea31a056f1286", "3c5ace92f3af0ffde96fde649e7316759ca51067f3c81dc84dde7c4108880f9349888e6a7ea9061148be5a0b26a48b38eaea34f8cdda732b10d4f88659520a86eab22fbc92459833da3514e948cc8a2f266d3156d60aac490022d507dce0ba4916eb2fc3e782924a683aa6dc5684a6f12fd1f48461a8b3d320f29f062f784c9c4b68bdb076a448ab9dd1253ac55495ba26d3d3816aa6", "ed3e2be296b6017c4b69b1f3cb813508f3dd0244ff24247b821cae33c93b428c2547871691014322973e2e63ffda91769c2f0579eea5087ae72d8d6383cea91cece2d5ddbf75ff7b75442595c513a3413c5f2ca695a344f9fb4b9c5ba6c08ce911abb4ee3b05ea1f3b968a52988ef1b873e1778737544c9071b68dd620eb93b3da6b6d46c5f03728a35b37029c65a2e750f89e15f6c51f3386ac3034205e7a2296140f9408cb5b1726ee732b4981689de87218c76589bcd544ed9524d301579cdac9329798b7ea7197f71de1bc40fb6bc2b9396698317b5a0263f0995d52768723ed04e08eb888499afbbf118c46661886ee3bb2f70af6dd1bbc31189160ce4b5cf221c45a197deb5061b2880df6c27a3f167b36e4e72ddb7ffd02a653b68e427a9e2aef5cebee224d8b1e24", .None}, + {.Sqr, "-9fe488750693200caf92b01b8d0bd010ab8951173defeb9c51978713392c8010928cb925550c10168999b576040d5a0e14c1db0abe03a42d813a5955b7a91aec0e7bdbe71758b0e6761ebb9976d390f48aeb323eb5af8694e0f2ee0be5122d5023dac2d4ffd55728a5b63319c49b00c5ddc53e4b5b3f2e4c9a6e26e7f653012512e8f9b46126757d03fed8c28ffc6a26bfa0c5f148af", "3858416353a4e05ceb0a56c1db28f06a3feebeb2b2aec1bba063646bd7c08f2f847c95e276e58585aa6a481c2f8ba3f7bf1686a293791893864ad8d97d487fe45032ce105435cd4d451fc377451d2fbf1ddffb537698724b6a61dfa596694f086e1532611c42f09fc444d9246018b6b3701563c64d9122514ed5e59f7224acedc9a04a201d76e143e2127b8815a8eecea06a2cdc4f5d", "63ddad84b75b045c2d64f43eac49d7c7f115d4ceedbb33df6e010620ed2dcee0d190d914e2d753c0b8d841b5dcf1df1984763450038ad6557bfd0ed45c17118c72b8f8b63a4d5900ce7c61d410340f8e1ea2f2d2ca8ebb572198d72d29f391006849679736be0fdf30140fa938360f02003595be81a26bc3fca21dcb8d26cb402c97190aab2bd12ed987f773e2b6fbe1aa3f5fae11d661b4c71667bcea517f4ad338d2c330458bb9a0f49b87a6d83e0d6f039cffab1ba7d48c99406ad5e21391b03442fafc21000601b3e0939a29611a9e18846bb897f172ae564dbe99385306f3fb38bb91977eda0887d6ee44054f02d5b65a4544a37fe7fd60d9be85371a4ce1245454393c00783b5bec7a57d1b188d690aa10ee866cd664ce5143937c7fd5528e7ab091113a074420e7a1", .None}, + {.Sqr, "-937113b069d51f1abf0d47ab3db7ce54e3afbc7d5d699378e556a08bd2990f4f66c8f7c55c1ea1cec6f0e8776a55ddddffa79c0f6333ad66e5809894bbd7f53585c54734a7e0596543d094bb723d7ac32dca87aaa0638c12ba574b7653acfea42671fc17d7030866dbbc5c2fe9667265d19d49deddc6436589170ea6d647a0446b364ca8ed45da6c5f91b9868f0e9165d9786f3f97d6", "7aa005d41b2e8ce10cc635639c7e46e8babf1ce044beb22aacb70bb74d9a90104b566cf8a3645d79323a22dd3d37801decde712caf2235e5cbb4bdc9ace6630b90165fa5c12622ef4082913f1dcfab5f14156712bf742626bd573356d545dbdb348219df67f8152ebf9028d58c26fe8a3d73cc83d222d4862086d823ee11a1821f46a09fb9967f093b242341d899b5cdd9d264d46d40", "54eb0e8efccbd925806f2c1b4ff5d7cc1a01769d7275fb958b0290fc965381e7690beee3a0365ddd17a9e46232cc390c568e74be8fa3da09e629d8e04442a06efbdc4c2b1526a9e93da5c985a4723b7d6506ca4bfbd13240e7e18bb9e32e2807aa97fab10b377d1a3cd1d8ea1e79644c5391c66408865cad61c7201db3b905ca1b1439375f16329c7c662aeb83823b759a0803a682b900b92070a67c969344fc6b450d7e9754e1bac03f9978c4194636904c7900942e1880287921b7b29ef892ec9201347f62fa48e70b54df67fd511af1dcb274812ee00b5b72eca73d2397f258d53271dd0c9f4dc1c4099c92b72d8875a9cb56c1b0a43b92bf55073dd516c97166dc3868e73ec976d525c7103a1c396ded99c73a1bb506197eb0cf8ad612c73668e6d8863b5a17a96226e4", .None}, + {.Sqr, "-77c92cf9222c5a467f7a821003da9d6040cb4acea736edf63f6e4c5596c5ed2cd45bd0772c6a6747adb3eb1bd886fd4a794306398d330fce3acec729d8294e3e9ef975a00f17fe4dba771dd83ca3aa12031f5628c60bdbb30132c962c7cc527632356a23d838e8a2abff8d176387d2135237618db8702d089e023e795f4ae6354d2322bbfe413f0aa827de508adae24df6ef47598ac7", "54d073ec765bd0db74b31a965115d38df13845d707a536eedff0f07dcf1b4dc6f92423b3613d487ccb0a4296f38cafd05bc7dbc6faaab42849f13672f8c31ec40969c8b6a715016b921ae8a32db8b019a5f2767ff059ead872d83d8dde18d400d8eda4f2d2dddffa73bdf47fb6085225535992777e781a177bb9b1b4715fb71e6a60d812bf4c3d83a6bd5de857097df8335e6b7ad9ae", "380ca5e744e37bc60b17bbeb1bafd1ca53368a631ed31259c4c9bbe198b07edac0879c2c632a3c7ae43d0a64499376c4e858c0d598b3091037164c84694920720ae46bc55be7190adaa1d141f8d67da116ef89962bbe2206d08d447f41d8d129b99a3167ca86cfb323f7adae7c2fb850485072b097a5910ee5d5090702d9651020b6996afc5d683ce28dec46a448c4336f2ac1bfb0bee47cd432532934c8b68ddb33a651bad9a55cba1b7960f7f20ac8a21dfd24776a553f2b15e690dcc6e4267e485878f8e32455d9065877fb8393aca542c7ea8b4450288a941a12b0435246e057dbefd42c50700b32a2cc4b6df719be56e204f24900c19ceeaf1e9d5da26096ae3e93cf59fb0f6be84796d2fb59672d59603024d354b291ddad0ba555a578e29aa8973b805dde2b9926b1", .None}, + {.Sqr, "-6d6f7b528b91dfb2643b5dd83047991f6c4efca9ac8f910d943e10b4dd4a8ea78c1b1820faae0b74b7ea4b9af8db6dbf7f196f7c132bbb2a5d7b1b34e2c4e85abb8ca9818f480af8cf3805e15a1278961db8c8915712ff46f5872988f0f47f962e47dac1b0221d09b02cee64ce898beaff12984e56abc6e0e350e5f0f935630bcf39b7944f70c5e8019df1db4ca90102d6a78b51d41", "86488fe7afef344004fe747a6b77953dc09fdafbe2d0c046aa553bc1264b6bc86a9b2dc6534632251586432d903a1036135c593363a355ae6fbe08d4871c27493328dc969e1b839bcf2703f08ff4fdc1dfb85c5febfd57777f98afd378cdb2a4618caa1f9149315902ecf8e338829a19e5a9053a320725db9a440d59ab391fb7f5cfdb491b7c99a417c49600a1f68daf4d86bdfd88e0", "2ec81f9077d7adb9c88df009a132fd77511d7f15a0cbef0f374782e785583753fb94b3a74788a5b990e3d36c09a8403012f7510dbc6cf42a5cb88be1b0a93d2aa9162332ec7ebc6b163f72692b5c2ac3e2a2c3aabe3347c4c0a0186ff1a4d2bffe86257c0f5039766e56cd32e63c773f446178e61847dadb47550306a9dd923f6c675cab1f52aeb8450c0936716a194645335a6f81b74d075b5c1e27fa36c4cdffda4bba94235bc824ec15b295fbcc85aa93f1edd04cc3b1674f01d4803d9a5ea8c82f0ed08328e8de0ca9b57c2e6866f83fe85f98ad59d5c873fd685232a248186aeb26699aec74584abd273abbdad6eca1b3fb5d30800ffb2866ef5d6e6387de3314de601634fb75e313b081b409c36f89d710a695cc851e4056773f32948ad904d8a34f5f635141ca81", .None}, + {.Sqr, "3e52f8bbb514b81950a52b778867360a7ba5239184f6baf4a784ad398ebff6f754765919899cd603b4163d32248cc2172cadead17d53e759b4bc7745b2dc9aed398f7b1d95e49ce8e7d66cb1e0cf3475022961117670e4d14107dcfe5371c7951551645a59aa8d83fa4c90c6a503b63ba84dbba1d036fd2011aa8f4cd64003ec870fe24a2c0ee6e0c76a87c7208917c554b8283d7783", "fa0f9d12b91bdfae70e940c9fb8b0afc4385f08c31bea6b07d5b2bc820d5d01be82157a1cab654c2e379ad3088c42022bd9456f59d31b9a9143476eb0be65d99465180c92531c388a90e7fec326f7ddc23b600a1dec1fd48eb8c237df67b9073ab4b2e05b45505a2d304c8af1da7373d69d6b8ba5bff4617382a7fc360c5307b79dd8e77efa739b3d383b00d2971733f12ea284f1aca", "f2c4b5f35a242ec6453fa1aa88d08e90bcdaf99e8d6c52c6a46b6c95ae5f3a998560bfd7363a8eda9ab095839beae7e83b1fdd94a78bb775c1cf19832b2164897ed89f9d81032ab777f038b998768f034e63b14d171f7bd76519e24012ecace0e3876fbeaa7746e0004a0f75b1798112124a40c6e25e5900ea69f30386661b1c5f3baad5de4cfc7c6da389107f5457afc2ac0087c62894224ebfaa1e93c752609cf6f3cea8c2303e6b7ee1b47c7d1ed152497123cde04355003be92a2ec18abfda973b1a80633de96623940d3a2c60f67f050c5c69c7a6ca7d1065de5f47267fba2aef9557b61924fbb687e1121169db0e3b0bae4f32c95c6c25d6e037ac83539955e1d2e68684ee9d612c01882f8e2cb379cd71b20691fbf971335254bca96fe07032baebb086b1c390d09", .None}, + {.Sqr, "13aa13e719727e374d07e4ee21c8543159fc036ad05ead7b448038b5994df6149b45213540a5ddb6e7b0438fec44674c6deb3919fe3967cc73e3c32cd97b2b89e7c0a7974225237113de40d5b34c709a80ebe1ca960853e0cbf49e2f6f8938bc89d155c4c48e78f12fee2049210282499023e387971348a28612904b03fa3bdfb838a0bdcd3437987b7d58e6f0af5cea9f1babe306a3", "523fc14cd15a16af991901577e76f1e58d43e84ca5bbf8bbd0e452596130536a54b1548a574a22aed718dde53f39d019d962a5c6e23f37c18138aeeb2648b7008f3c94492dbe703eba27accbcda9ec49c90ac2d5ae395da1da4c64cbae90c564b142bcf7dc8845b452033d6b88a54b1684bd91decd23cc17f13cd67134855cbb052747597b9a41c939f4ea3458cf4074712fc58a97fe", "182aff2be40e931c4c5078f0a09bad83589ee081aa8556167b84ee9483d60bf4e34228423937543e7c93aa8cc1b25a12d8cf1edb6d5a883fcf2bc80d80e1c81c0d86a109fb2e3f780ad6d2883ee1cf6564638428bea0a06ccfa919ab83055f2912c2bdf9ee2b58204a755130ed95e5c303a26cd44138a6012dd505cd11aad35a80f5ece0b43618819c5b6747991b3d1b967a1c40235381c8ccc04b0f64ac2be23d0fd9c83c2db00d7bfcc38a74a0d5be9e33ed732230f5b3ef58b0902982568d01324950db214af065f169377d9f9fde9cf773e3132471c80e667decd167b20a4a3859905eb9b906efa9e6a7726ca0c3357c1daad5ff85ef1312b2a4d89e1969f042bbd616a2a96bb5b5d5e261a3ee97adddff84c8c0caded8aec2cf05cf12fcebd7d290186f494873e0bc9", .None}, + {.Sqr, "89f2459f06b35c522c3990a26a0584c6c7ac4f114f4f017933089b93bfff43c5b817f70d9fb9272fccede71fcc9db27d2551450c746d8e6597e314a5b180c6c9a1473726d34e28aa65b1e3fd195f9524bf068c611f1b5c4359a265380fcc56b9f3f53b921c49ed13cca02ad43b89e180499853fb107418630661e5689128c6e284951602aaf3090f33fc6923e0e366b683fbea8c76f2", "7745df055f63986b9c9fcf275192793f201aeef317bbdc1104dcc6c04776cdaa5c9f43a5d21c968d8a87afc29e09e007140b13a09f07d89399e52387936a92c07b59282aa40501bef1a6f403cc3b620d30d674c65f9ab55cce92f8d303e6944a9a9312b069f90704b5e3e1e9ddef62f3168c0475302fbf4e517d1d764675bf1882a1df1908591ae36f64baa4e393fa9229d91697ebf3", "4a5533cbe8c3c050816f198b564b46e41287c5cf5f118524c742f5b26eef0b1f64c2b743f47250ea1da1c73517234e1c5edfb85ca27662176c26cb84bc33414dfe1d0e10cd9f6e79dc553bae7d2de7752c9752213b0a71248fcd2bedaff492b840d172ce3b76271ea80d79173b730d1b906c12b8dc2e5030e3a2b18cd27f1952706e35e58fbb7ae7c5e35bef47ec198b6d3dc4c869183aa8fc3f5e565ae92ddaf508a52dbc5105363b9791e01790e9d7284240aa565b93649d228a95c0693d78db8792cf316df009c198f3b34c1c78da0c1fb3816ff3500a2caa5eca3e4ca5a16ec8ae7368805d775e87372fefc0414a2be8379b7163e3786c75891a2963a646f8585a3ffebb850265a3df654a5bc0633ef77530ccc7a4e5345757942570d2ef7c93a99f802a0110b7f3fcc4", .None}, + {.Sqr, "153bae001a1fe33895a38cad01b6ee0cc5a1f329c7673ad5e7e770f13988b76308fe67df00cf6857567e969ec811c4ec70f0e62f37999121cff719a7ff7ed9170a43050efca4b9ac8869cfae941a1ff12680158bfab8a46be9ed3999da280b13d471dd1e67499fc83d8d2f55aaa4aea80ed62b6860fbe56ccfdb2ee2f8eb2c2e5e74559f536cc6ccbe914580b045e3441815d77706c5", "724f36d990363f4e7e670f70db366867a4402d711933e766f9835f5877c254ec3f807a91e6e933a00d3da308e336f7bbb281b91dfa20d96ac8f9d173ddb17b77d087e929c13d65dd93cb51da05242c93a35598de3bcb7e2e8bfbccce5c1813e9f3dc48983a31fb46c79a8043e4ca6a70d078cf591f4e4bcaeef882e44d003cc26f41ac97879ba1b412d5f14df6a1b41e2e17c08370f3", "1c2d875ae99697d602d3801dd08d7c58ea8c0d4559201d6ff46389a3bcd97f38b251807aceafd53431adbdc150804162784f48e25efcb54c8efbfa1ac0631465013c104b3dc7e51efbdedda9c41c605d2b2663ea88a1625ff638797ac963c551fada70c1bb12ca345a82d3c038240473c3ce43c38f57e5e46bd124b9879ff5e131054c9562924d8cc765180644b3089ce4f83ffabffa2cfa04d0bcf9cc980ed727d6ce146094726218bdc79fcab41e527786096c4662904b2c027e20b9ca65a04f15f6bc1d47b4a69275b52180defcd9f8d8829c84574aada75c83014db98eee3834e4621a3891b12e236ae3f3a1633fa066f2bf6123b6211a4c15a60cb72337b30b644cb24849304b04bba011e3347864bb31908299109544cd19c126c90b450742db256cd31083153d399", .None}, + {.Sqr, "-2e539bd78cc8cddfbdd95e98c7be10170e954d769cc8997e5f5dba4b01afd69cbcf35b386167f9741766a1e4d7740a423ab7c492a8fba292bd194c8b5ee867a05078828b8efafc2b00e28cf90850fe3c631e7e8108d662c1ad34a76d78e21059410b45ae84948a5b5ac19c3b507b03353916867d20e3e8f896416cde5b3a2a979217e9b13cfd2be4f78cca6ec96646e70bd256fb0d78", "1ccc91e2d437193469a42b007002978c5ac49a922a8ab28102a1275290780d882bac63e4a30e33d20d221e99614e1817ddc86fd9f615afaaab120669782bd6f4fd29190d52dadcb47c119e88683580ad6cf352cae43904f8493297298355bb4a1ae6f5a62a79ab9a6c8d7d88f7a15c42daa3f1411e1219c870cd8ded0fd898f5faac393252e6c5dcd22c2bd1e68b0e9f7ac9c0efc13", "862274fe33c2e2ad75235576552363bb91a35edfd9c5db33401ee3f12051af29e9d10733fead1ac9b2501b2dbcebf7de103692379e305b78f455664d57a4680500bb1fdb0ff475359a30bb6e3399f82c6b04789ab8a80d0d19476e599b228bcb55d68ac79783dccba471e3453abdc061aab4206fd88e04e1724673c80d08114972c2808669dac15196e1b7c2af4d33884b0e9c0339fc22d3760f2643e2ca2dcdc61b769fbdc0b8828de7c42fd12dd9fffdcea74600c8a1f818580db1475d4e239d3a878f5c58b27da94d83e7df28c7992620804f5d567b3ca66628acfd11ed4e5d08803194288e24ced4f358b8460c5a5aaf0e336fd3c9bfbf958cd27a039cc86232dc8697ced2e514732fdefecf37da72ddf6dd9551bbee21c483762ac1f71dc0b305c53280c200a056840", .None}, + {.Sqr, "-8475f6f7af2e03f165d1e227d77cae7781318f9f7459545a3be692c9a6934463a12ab66792129c5f7dbf0d8f1deeec6780b708dcf8e69183e23859c142b268542d0775ee27c087824ed0cc433a9638a1f2480efde469acbde4ddf626a599891b69fa622638ebde2e051d3ed6bdf486fbc9488f018ad22a53ebde8ebe961a16ae0f4483d505e0019e5604d14242b381eb87943efcf9a5", "ccb1215c159d31fa707fa1f95d73a63c6cc84e1d1dc3d818d7635d7a44c818a1aa9d48cda6fdb9f975f2b38545c55b5323942d7ccba1141c21558c52c776e8b5796b68e215db27bdedc0d0d35212da0cb7fe80d545998b6a35cc83a0f7502654ad3eaf68098e1cdf32730666c95c24192ddca20aaf3b22801d5276c94802e785ddbe44c3d2afa828453c12b12371260efc80956714c8", "4489dd0b194e88707de7003d1c4f9d8bb043783d7cb226110e49b24d1829765629d3e7ac860e9cae8087ee51b6344ce07aed2ee50340426b52e26fb6e5342458496678f8dc69ae219de9877d287dfb2bda4115e2d7d0b7649530463b4e6c396ecad8db303f949a07751aedb3679bb01c84ccdd01da37719f34ee3889425bca5e1e72b9c8684c0f4a288241a9d41dde5a593ed691c7f792256fde339f43db718a1f27aedee8ab0959eef699f01df37831797fe584d98159e0d90f12899e2342bad48c00ac77a3fb4dacbdd7d8a91aed983a890c1e42b398989756cda783cb368a123ab15736d2cf99d2e671e1ec08b724cd68c92b5b4b680955349f78297d24a7bf662dc01b316aee2f280c5b5ebc405b18f19d5a2f1ae4c2c9098199bbcf745843067910523a2fb05c4a6459", .None}, + {.Sqr, "4a8beabad217ccc3322c783517ce0eb71e98ffec90265787ad345842a8ece9c5b38d861a01a44400d7f35b7a731a74e349b2c2060e123008eafad47c9802b72e5841beebb83c5aa43c89b28d9ca77b7d57830aac90fdcaf78c891b3e638f8e75d71f72c12a7417b496c88c3038588cd60b243ea6796ebd2fac0301954f748f082a0986c35517e54970d6a49fef75ead880368412b54a", "ac3c6fa52d122a468d1b4edd7d57f63bc649356090b3901b3c003c94095e1483a1a7dc79770a6d76095fc18300e476c6b4d190057831284e341e56939eb09fc28d41fbe5268a64f064703ac7be38f0c75189258de1f7bad0506fd1d39c3ef3175da3474a5dbe53969e1bd292bcb15b122f985adc67411e9fabb9d855d509943ead7b47bf0677b7a9d6a21d11476b88d9727c376719ba", "15b5302cbf8ff8a2ae4fa34e1cf65cf230a150cedee254883d6603dbdfe0a811d8e5f37ca355ead81ae6ef0bfa3a6b7178187017a82c7bd571e8215fb438a2338057038a642cde404905ac35900fb62cf3f48813cfe49c7ce5ed588096c4e4aa4590f11dd04b5bd9732d4f12a8a6de4b64d1d666dba32505ca28739f36f7318f10310737ef44505477664ed4733ffbd1b79a2991d5196df452ba979dc6877d4ffdebe60c42f24900d1edbb16df3d17ba57d11b2616968ae7b1337f688146df70aa63245798cb4b9c308f4ffc7738cebaff545f79be101bc4ed7260730fe038b95992add2af395ccc9ecf5cf51a6748dbcf5c70f6315d7734b0fd59feb0aef488865c8145c3aa459889e360db536d0122e92850c2e8f92934f15f1108d3c75d27ef2d844fe631c78a4ec9b964", .None}, + {.Sqr, "fad6d34127152788957d59aed4ae5c6608d0251c0ec73eb182da5f79d9f17131d6ffc688381cb0133b797f00aa5cba08edf26d6436f1ccb64636f205b4874ba0b583b1c73a8e3cba3d456d9df577feb38b6589207951e9015f406f9296270f6a421663bd30bde257f425e8dba8a10533bc3dee6bb8314ad5145a441f1467e3e5c2cb3502818548df0e29969f12d00ff9ed4477d23bc8", "67348bec215e512977d86605cb0c4b0aef91ba9d555d5fa084b79c8ebb7ce66adcb70d8aca354eb3d2b866e1ac40baafaf67fec64a6e75ed113068eb6236a3016e821c943e085dfd649913af439bc492948d3b384047a6787dd58ca71d0fdd17806ab658f3f25747076933a68e271dbcee9364feeabce05c17e5364c7f38fcd46196f6defa85c3933a6092dd1fb5eb66a5103b0f98ae", "f5c848e11f971f969a336e4f133d7ba889f21de7ff34c5d4ee4d8a9b277686a9a786acfac0e2f6b38121fe23dca1142491a14fe29a5686ad7f6f72ab03bced951b6442fc697e3f4d1e1ac99bcddddd5824b77db6ed5e5ed164c947a5d7a966c952849d9c0a36ed591f42112b56780a29faf2963da6e5358d4ad59664c01af54dde29baaf48433fd316a1ca50e1648251a7d843f396524af8a1d270085943cab42b1e6fdf8ec6bc16a9990d359b2702205d17fbc23d4b9e1e30939ee4b4630569932f90a06c701ef65b2d120490978ce7ec89d8d0680a975467b929662be2aaeba2b767089499a8dd8d31ddbce23ae831826798cc4ab99dd5f6c1012087cc8475a091cb5aeb71a7b1f7f54cb5998faed25ffe0ea7a46e654aa710d2981a46a92e599cd724dd85327a1215cc40", .None}, + {.Sqr, "d057fdd180074c110e967de5b56394405005babae0f4f5c69a1106e798729c4303349268eb541e4f0f70589450258974407dace97769666a1547582b1e700332e4f40ffb81e545e57300cff48ce8ae55d567327ea9f27de45bc261d808a13cf573d40878be641903ef97d3a3e6b2555eb76346e92387b31758c03fd16249c3750ce5004129b10931e4c1df815fb5136d792814436025", "d00afe1b5906cff0fd73364657e073b12d128a5334debab7a0893fe8c9c35dfdac423b5aa23ab66afb46588bbb34e2240e5c32a390922fa730d257221db849a0201a8e45a0372eceef2e296510d99ec01bc0a3a59859eb72606beba2f15462c4e4c372c1077936ccbc343ca6758f0569c69519c6212e83c58e1d679ae756ac86597d4ac0d158ab667dd24398d907ce04c89136ca9f91", "a98f1ab2f018a3122397add46d94201d28e44ca71ebeccec6b7da9de94f0501df0820d10f553d072299b40bf81d499e069405dd613b84fbd682864c861f83ca298895fe4775ec0b2f4e3b0e3f73e00b92dae819204f45e37608a028ec141f956d5f25e739dc5ec546bcc7552a65cacd5c1a44e6335fabe88b04b2354e47d33674e7386ec486e25e16705d059d1d37333592cc6334af3cf4a3a3fe5490089e136af66e8202fc06e14c319a487cc0207d74b8489cbc234d7711dc511654cc3a96c740bd457ce8deed5d6378128ee4aaf5111d919cbfb702d8d0b3204cb5f459a9e1f04806059e2325af037dd434ef81b5a4abeca785c5a470c10faeb7e164fffcf5dbeac2471698c0af5232cbb6102e4cf45059e2adb48c680fa839025a0e72db45c659565650d9e513f79c559", .None}, + {.Sqr, "-be26b97cf43cd97e97fd9a7700d025fd9aa50b1899dc6a771d87d4ddbfe4cb198dba993a671a445e3d22e759cc4c0a50a1ae6396fd3a6bc25bc3b3cf8524fd55aa6121503b50363264dc8fc2df0167157c319cd13929e945fb39fe12a5438a3b6719f7f9b4d1640be7c677e3e920e945b917347d9f557bdc7db8fb8e4ac430eb61d4fc32ba2ed60df71ab85471ba9744070c02558dec", "21e1c8af3169f49716104b02ef116ff386f802b3855a46b14079122e80d5938aa16d4364cc763f39f7990032f33395d765c82c1a75370dd01b044644d9c10cc41e495d99acac4cb167c29c23620fe19808dbbb98f2c2c0cdf4529d7a7b50561a918faa4dcb0b35d30ed52ab688fa01cf4373936bd17d1e811c0a904587949475fbb2ab58758bea5ac549084d6917615c784ab1ed8ddc", "8d3d81311208aae5f18147f24551623e82785a9e23f6268a9da012146e2d71b497954158d0ab3938898008e0cab7e4ae71faafadc61b252db9615125bd790fbe6fe7896f5bc9cf1bb4f4a5c119e7d8e89b48350e809ec1778fa8ad1a8d92fdfbdd582b4eb11d920e8b7f5b17d76ae59bc8d24226ee86f786c91c9628b4d77f83ff02474f3f905068895dd1137900ddca9547985625cafa404404e520694a169ec24d8667fa4a2b854083687b9033a206926603eb063dc9b6c218f685e9063d2644a1acec6d77af8a946c6f232bbf04e82318548747a79ff250ba44d631bad0b00c6de2174e734fc6f86e5c159a55da6adbf2dee58706570be3d2207df8d3d740fedcc7b9f7fe30fd397f83530b18cba5378265d7c9b0fd3d121f2208a4e6e9ff37d06680b32da8ef3d65d190", .None}, + {.Sqr, "3125e21fbc629b2a5ac2ce8ac9ce1e1a9260df459e331e3a19f770d1cb55df77a16f499ad8fa077eda9a5efdc98fb4bef952cbda60e5fe295801a5ef59d94d54cdf46a9646a4477d41bb9782ef85b63fecc90eda00cd0737d2bc942d44cee7311a2c1645e19cbd902e353f64896558231d3f213a17dfbda577474b648dcd9ad56c093b866f0560269dd1b67155f2be82e5e5ace6580", "70c42cc64f080907c4aae44bbe2cb518dc6df6a5590559ebce55a91e6888a04c0853ae75eeef825a14de5915f1e9eeaf98b70ed49fabfe9b288d3a6a49922ba41d3c46b8add0806added34d7c0c5db4fbad318bd8cd28feac3e6154396556b12f1c5fea8dc8d2102ba5641af1c12259790f2d2860436094395b901bee90cf69e1c202827fddb14f3e1b1a44c79227e498866829547aa", "96f862b4b064074557625c425023c7375a83bc2d8ab24304d3e67d7a44961d0d5101871fea229236ce4049c6c77fb125d3e3c3a2ea0aca277f0ffd28635853689cf9ade7485d4fd3851cabebde8ce8ac4d5261e7dc50aff3e916b8e902368aa14cd5fa27973e79869fb764673912c156f273aeba4e780a96b68c25102eb13c537dc4b140a6bb5aef34240af56bad7ab387375c091c899fcca88b9b0a575501aa04c7d0e42812a6f2a4a1a9f678df092542aff084f0774ade3a395160d9025109c64a5d32c78677945f9762242bc18f05415a4db6c8ba463d871899c61333d8ed746cac8a789cf1cdd2b0068908bf74a45e0c852b6957f725a2f4c0ba46d813758b4c95e8853cd60ecba0df4c6f7aae7ec8570966e81ac4ee6ec049a289193b4c24c99f4424fc5823e4000", .None}, + {.Sqr, "9d39701f85702ad218194a9f1558680d18b50f8d92d2ee96a3720820864dbce56cbec6f03dce47ae9188550318de77229738b136b9a9e8e9b82da420a62af7367e91614746a4d2e64b49955d108478fafa877bdc0783ed910870bdf0d79e457425bee09f59441e1f8da5e8f11b864305bbf3846680e8fb824e7ad57395e56c42f22b1edd196fe2221125f72c5fe8c6bd0f3ad1f2b9f1", "199c648a413a88d09184edf215efc0c36409338ec8aacf02eb9c5c087c3f79c36eab04ac2918f62619aeaa5d0cecd54f47e03fadfc38d9da94e986ccf267c0d92ff53316230f2731cc66a3ef879324e408a0da0e6a5ede45f6b46458f6744499d26b60396e6d282d7fb5663b4ad6de47e0b4b7ec29cd2c54efe8907a8f2b54dce0a62585572b1aefa308f45c8926aee2d7f7fd2527ae", "608f8069c8d0991c7f4db2661e7a30315c37a87527bb9b7d34f113990e5cad264444959f4487f8bf795aa516185172a1d8bb054184ff691e70bda1f66512e6f2e940609959c68f3f5e8308ef3f29c06563752d48be94533930f704fcb9d1438039cc9aa5bf3bf27ffe6da8bcc47adc4986feaa73339d1e61c5b164ff8fa0f94b0d7f9b2e889628ec4abe4e247aa17cbdc2210a104986c8cc960b8a3b2e81e914f786891d55d7b7677183d7995f1176650e47bab0e1e97853639503a7bb8fb40dfd1a7c5b40434b8c4fd7d1f35cc21067c399a965c7ad93ab7003ef6ee6ace6b1954b342ad53ae2edcf666ebb60e7b5076bc81ff1e6a701222394a2a2aadff2f78ebeb212e0ebbb4b306b2eb879ac4232b258ba27bffc1331bf589831b47c9186214f4cf599ceb8f394b234e1", .None}, + {.Sqr, "-f5addc66899d1420bbb5e46f394c21410e3a00a0fba1e53969c2c2273a98929d1edf41dcfb0cd774a0dea6a27f9f492e785415a4e4e21416ee8e263b336fa8ebc973affe67edf6dec53898fb7349c99ee429300856c2733809b4d757061e720083817350d8c2d9420595768a78c4234bbb2397ba59255a95cf53794321915990715229fb7500bd93a55cdd2a162b5b668acd1aa2bd2a", "3ac538f3b968d3b50b03d0bd3a9afb145beb2f39cbb89b9d6a57d3cd11ee6e3b03861bfb8bde48c262435dcab19fd4180d3925277d341e3e7e475e59d3389f69a4077e136ef3ddd9439339420fb1a34e623b3197a07934b402d57c8e0f116e81e67af6f9984b7ba8ebdea9844ace18ba2ed3ff728e6f41a5b988c6be087672d84e39a22b2ff609632a08d06002e6e93cc1a8c3da72ac", "ebc63defe3bd0c6bc945a7b6923468c517880c95f497b9429540dbffc9f192eeab52a05c5de3104a3c534d56b2d1014dbaf6eb948f231a2338d0b2a62101ce84d4f21291c4cf2348445c0db4f062573aae4fa60ca3465e9dcf227ee9743a964ce7a0291b95531b54ab1f92d34cc1732e83203034628f18afc21897495138ff5de012c51361911e3cf1816f5c83c326cf935152508c312817a5dd7fb55ea81bda5cfa9538ca501ad18e4c0cdc9055fc9de8a83b62f82576a748969d83a44f5eb20c66a82ceaabcdaba7e0036d16b2a3b8bc2e34822c6f8c2b5479594117680a3df367f41e59fbf9e671febd2eeff671e5cb2b119b3c822ee1a8e2ae046e6858bd69acc4acb6705c676b00c980242879e4f72ee807cabffddb6ab9f24f4f45c36c38997551b8d1b3247cef0ae4", .None}, + {.Sqr, "b1d233bfe62f294f40fb000ba5847814b92b87e0c959d7eba46413f2308a69cb5bb95bba94253ba560a5d5dfbcabe2b0195ebd15be0c73fbd039839cd2c756278b7e26fcec7a3b44ed90f00946b8341b7b238afe72f74b502cfaf29e421eea8cf4c0bad0d321ad138e33ec7f6c1b2017254d1bb66e78ef31186dc98274369464dda4f6d45df60aecce335a5fc1280fc35c19096f2c7d", "94cae9819b86b76211944bee7381cbedb684dab1e508c32353ff7b812c38b6aeeb5f08d7cbe829346cbbe99b6cf7a94a302ec71c2530389591b0026b4c5789dcb3935ef0ee88c25868c8ee8857b42cf80268a8ce9794862a1c589f6d407d1c021cbf8d8a26ef600c82a893596cd47241babbf9bdc4762211b3a7e2e11bcfbcf22d2bc2501a500599c12abbc1dd3c1657a9ef8a8d2b99", "7b8458284d98e20f71afb0edc112cc4df0ae74c03e78aa33da5ea18413e02b9110f4700608b891c1cc0f34a2798a491e4119ad1a427072f7868e112713e2b3344a4bed168029b76523cff9424333d505b0fa211aa54641fdc853a7b8f55bfd37787055ae69a618e6c05537892f690d9e8c7850bca48eae5cc0e97c2f144084b0e58b3070d69e599415bcdd24a11207020142f2ce41f10b37a9b60a0cb2fed04f90136d1462d77c71120939078f267787e5db3268afe8ebb1bfe524702c3ffa31ea550e2988c8e4c7615b5eb170d5f0312b4a0f67601385900a21ef30935bbfa10783c466c235540a6328d0b02a10844a62a08e83eb0c4f83ec256b90c4d952a2d4beea94a09e787800f0190376d48b519ccde1cab6e4871c5e87e1a1ec771385daf9c8df2c7789d266213509", .None}, + {.Sqr, "aa21f6e2b11814fd043a649843f09d31094cef0eb3bd6856be8c4febb8ff6cf53240714619bb1a26f57180bb04e752038c09cc809a8e6c77087bf33f1fa658f1fa23175d713ad06884aa62df0e7c159e90ba9ef1987c260bef59dc0cfc394c6b083564d9ce906ae8998c9af543615053d925de40215b324caee76fd1df6dd599d5087ae67cf07b42c27ad366ea32dbc840e782d968f2", "304e1f17fb54ef791833cb9bc97d15bed83b96b303c702f7f810472a0e6feb3530f288fb7747e1e1ff966b703001f53d5adc426fd64d741bb04200a2b2da4c1ba9c67efb3537990697ec214c6eec09a318c47b73baf680ef41b3a4fff7381546a9b78212461d42379807f0da1d719f4beed3eeb510f3824aa8dd6e37e98c8559b9995968d2c0cf1add5068118db36fb6465a19a2d16c", "71112066a7be192ce43646cdaaed60ffefa2524f18a257c2862e42e2dbfa3b81088973ab6e347d197cbe4d15a0d4011730033fb9d666d3f737865e5bc2d395e04cccb3339616697369e4afa46edc6341b415c606cbcdc35ef41e43df50b9fdd7b4be34e5dd822174f0c75c7d74e06326e344038c4c8d6895e9fb5970c047ad082e41669addfad64d965290ca57f29c8e99791a369c7a80a7001494196c48e7fab8779441f8055c7d94def8106ec9f665b84b8d89b3d446a6dcc81279fc8eb9dcb6d4f7ac9f526b6c7bdfeaa3cc18e373aeee058172b4b0104d11171c80ddc34ba755281ecb42377484e90ef8901a1ed51f7a5a0b04ea8b40fb5ff3701e75e254c6a6bb3e350c5e0085157a1ce3972da77908f0374398714b69949a22eace483cb1b0669421d5ebf4dd4984c4", .None}, + {.Sqr, "-527f1c69118395e1657683d0d91c73c8df514813e39d014a31a18bb3882e26077513209dc69fac0f03a445804df34a6e120874045dac739f4b5ad5a79acf3a2deb454b8b1c46b8056ba346f11f8d6fadbd3e4d90d5ec548274b56c9a5b3478a6d073c80eb1319b655775877478fcbde8f6b6278ca99d801c243ebc316814a23b7db25c30440d78f6d8d3bf0e8a59a2bc5be902114133", "7cc9f0a44df5197a3f7e26fee342c8240aa3095f74289a4320c73875bffa03bd64b0f855f6c1561014413945d472cc49319aa05cb776d116f9c90bc581121ec715529542c662828d73abf10c446d3fe7658a0c113b2507becb4ffcf8cf656eb685476c87e2cf9a16af27a31fd2ae815c12a9f197e9b42b74b6cf54e435ee485e00413cc03c3677e86467723e420129a3af3a3c78e181", "1a95ad50829ed387428f96aa68433093ff9817abbdbe9ab1541aa88001255e8aebcbb5fd35e7645ba259674e577acecba76662502c64386dd256ff2f47f098b59026364c8dedbf584134a34e42224c26cf7abfd54af4101fecc8b7d568eb0615022df8c54cde2febfffcffe52c428dbfd071f38491adf287ed1077d314912498218466cf8fcbe6c0530f7ba802a45df3cd37523cf294b7ec7641e361737804eee7ecf8130a2f8d14136a925ebf4c66e5117cb4fb368fef87d568199576551872ad22a5b98abec116bdfd87d715b828e6a4bb91793caee8bbd0e33acc94b14c415a64538c9462b62d056db4d6a2ea307c7d118406361f2d2480a676244532dc86e577ebe948efe83fd9ad2e8640f207111a2cadefd2da22d4dc4433a3048f90674bb6acdf56af37048560f029", .None}, + {.Sqr, "-9f72aa5b235fe3b66610c7f4ab9b55ce5e02bb3dbb43d4fded9b08090a82569cf38df0e72d37b85e3b01af8b71046fcf0526a9e8d5c0acafd95fe02d59fd341106cea2de5ca7e3b8dd4c8da6b09eb75fbec958a30953ed539b3c73fc0a0f34666a64c85d3190e8c154159b96986df5261ba91c97b8b3aac94a1a37ae76594fe760010f4f27435e2e87c091f77d3f0e6ac4f223c65448", "d1904575b2cd3671096a4e32d711c0ed34d4a8c90ed65fbdac3059254a3f257db128dad783cd825c378df88d8f51170d92163de7593a03d3969440006ea5a26ed73a5ff4c0468154b4844a31f1a93a25fb39b5c742da68da5d66dc94bba2b4564588e5fd38c95a87bc00909c2f4657a1ce49d11765ee8428def7b8ac7093a2ddbc894824faa287f9572de33caea2816741c361a8b8a7", "634fa2f96079c9b0e6b93ebd886838e36ca5a40213a42f64f4a154980d1b7101c1ffebc9376ba31cd844d7cf68a9de75c143edf084771e44b74314b8e6627c068acd32c70193eb86b2570f76e44995834c88182a8f9260e958133e66d4414cece85cf2a5cc4d9ea1041f737475309400468fdcc76f82935fa68c5e4cf817594827dc5dbb4029ae8e2f4a1115d03010124249a47bc72c9f0751c8c6c296693c395c568d3a6e7804bda5f5359618210d2df972df84ac8e50e690e137b26d07c689c438fae5d02e3ccbf62d21bda9ab41050edb9843992825fcfd036d234572f55279ed4143c1ac2fd778c2d009739e0a3303d2dff86246ebc06e066ef743168198d0bc48fe966e749570a076ccc949f82d43c824d330091a6ccc60c48ab5bb505fa8cec8b504a56cd22b1f5440", .None}, + {.Sqr, "-b5ab3b548e43c95b4de0879e0b4280ecf4b1a5847dbe69c8f557022c3f82efeecf2fbce5f80db0c2bf6d01d0cc3054d4883ddcd77671733f2d995c337c0b7a464c22cba4d0949f2552bdb44c5b2d39c7ea3354be987b16d4afec1d8077305f45aa22b98488e129812fe3ce85313c0472903d1d04e9b80ec85291c70321655b45df18d5d7f73a86c8e847b9fa3868cad3fbfc07a27ef9", "804c6bb5dd5569effbe79d9ae4bef8944ead4c47213b9677836d971254296d635ac73b477f62e997d8ad87d71608f488d41233af7e753b5ab604febf462ba867d7124ecdf330da8ebcef6d99c821d6ea535a30d1f947434665127ea049cc006a4a1f6083a134b1bf260ec514929779c1c8350ecc4aa8db983f91f7945d60b79eeeddb3377674e16540f3c6b52e416b232f9005e245ab", "80eb946de1e1fecb067508df917b48e4b523080e6a199f92869a8c53275d6f78095b8d7cc1e9dac5eb9a6f193625a61f5fb88939ccb84c993327229a246a47a1f2964bf43c010e91108f207a5462fd493e03119cac78648a454ef3c3cc2d0282bf325246716ed536a75609e5724bd10894754ee689c23a021ed6827fc2e695fca03a80e2963989c39787a76b3480a2a97997d9fd74a24f7a56644f251b472adfcbd62e84025829769ce7ed7c264bce5a27a4310dfd6f0be8e13be8f5bcf6a4dcab37e53fce6516229983f840ec6bcd5cec36befe3466373c4e49f4a31f51afc6e06013983d56cdea1a623cfd9b41772250ecba422c7762e510f056a18191c2ad4608591d5707e111990d9bbb128e86ed7820325dac7706baa13d312669cbbc5241714fa5ef968a4e901e0e31", .None}, + {.Sqr, "-98f52a729e32cdf228f14e76467a8dbf4292e4ef1ed27e03e81bafe4841f22652650f00c5b7ab9d6c111438167229e2f4f1f8a6442770fac3a59c96acd5037efb439d81eb663ebf37141ff47251b2f58aba59f109eec0994a26ac4df878d64024611b3478cdd4800d8c46376d3bdb89b5207dc9a5311b3ad51c93e05f67deefafde754f44683e648fbf3552a2bb68500e1bde9eaa1da", "a3aee67b4d10278cdf5e3a9ca8b7021891b2bac2c52440caf9b5052d588b7b1db5fd098b814d79756decea9accde63c127d50d84b8a05ae618bf483a267203b3c7e1e8d2e894f52c42ad372e1f0fd1849195ec8deb68ea91c11dc668afb3aa3bd86e17b75073832632406bb572b2f3c1a88cbbcf897976e807288504ce8ec76ba3e1e4bdf7c5d127f4c12a2026ad9e48e6809498e1b9", "5b640d326248f107b4b68c74498cb51df66dbc84689c3a72756c0bebee7172b826b5a5ab8913af196c6017aac2a16ccd249190063a536ea9e49faab451122d6cb2748c19462e5da44da71f2cc92c50176ab349c1808a04756a2a261fd19a7b2d78c4b097b8350cd99ebab5d6cbf97ccecd29f1271c44b5e353a0f8f80c4dfb4ea24311a750bed3e5e0d4c670574703c280943d6fd075cddaa283f1ffd09af82c1ca14292f082858fe47d11007a9ecedbebecddd88fc98b4173f8dce49d8fc9238d71dd25f9e1110e269674d965e56603a91760b64fb365e16acf1a241f972cc8b01341635a9d4298c4a64ca0a314fa3f75f21c1ddcc9517aa1ce3c692b6e625fd9a62e088c8f98ac807a8f60f89b92de5680591af6c8149b575e1028cd48018167a28c362eb1218f1cdbeda4", .None}, + {.Sqr, "-6ed195d98a72940c331ecbcaf5452992d81578b743167606aabe85d7009f14f32d4934b521ee4ef8b49958a06dc2d9c3db1e8fa38f32b82d43f9bf0a10158df2ae69c1c12c228e496c421bf6aeb9c8ef1012084cb2879f23b4a02ab2f5f67c4a59564faeecd642c46a39e1cbf8c893be287d01221ad9e9f40e8ce73ca711b2f6854c2e80017008a6291107695185124fd7e155c7f212", "260f219b612a13b884033f406640f5bb3307bb4c40ce1fda926efff3d9666efd60add7d9cf2c6d796d97e64411593725118a2093b09af040a194235b749130204b229f200af565300465e74de68949644e0a48e942fe3ab3b7263e04c705f98829cfebe665058510b4887f7f04cea837dff724c89c31b530616e03b62b6d95269732e4f285cf362759a7229f5653b86196f798cde836", "2ff8c85cf7e57a55994eda81073481132708c3397da2a86e6cceb3fdfd80eafa71cd344992853ac5e917b782716b2a4fad683d8d1fe200024ef4f22aa652556b979dd2035c2939063f280c5172bae35a66f9e115691f5ac648e90a7b80927e1273a3070be16223017bf4fb5cd35bd7897e9a8b63c67db809ac83b4bee9b731256f8966a26862a3a5361ba3443d6c3cd5fe33222669cce8e41642b3d6c38ef7984079fc4b0653cd4f5dbeeb943cf7d8e638c100c56fb9e9e08a84ed4bff74562847be64364876b41860e53d683e94d718b2cd247872f07184d168f107249d88bee56de543db6b2ca9e8cf48d1ddfb223fc800e0579ef545633cce80e1569a7b250aaa8bbefec281a1cad69e55f85179cd4c78e3683695d7d4784f69a677db7353dae43e93adec228e30e20944", .None}, + {.Sqr, "-c9d3c7d5370475596e2f572f2b97a95e2a3abc9227849e637daa855430bae4a1ba2e531e9c01ce70c60a00f1a11dbb97453020df7ec88321c7f5b17a8a90d02e138531435ab507c069193cbf0c902db00d8cd9716a0d4655578c95127da155da43e17ab44089aa88dca17f18c6801483c502c233570ee1ca57b810e4ebbda7795453055f2a3ba5f89e84a2367b922d7398138af158fa", "5fd572d34b1a2796ca9f55ac11851e01d6a8f3312c1c3df761ec2de2fd2be224c0026430460936d77236df77b7b214e80f9716653d6e878fc6052026d0e3310547cd2465c5e1deec0e478b15a1e6567e9350b8134dc071b3f77016f0573598e3acaa54f82c81d0d56c066fbbef984a61b9508a4fb367328fb0c06e5ddbd4399b034d80f4d38888556cfc07da7464ada520d7ce6e2690", "9f1e3effd5dadebd682133910c771521737711204db83e7a3e1e92fbc120e7fe890f7247f5f4bc0c81b13204409d0e6213c243222b5bccb56c5c83446baa40048b17eadec723771f53f7ff65695d3094b6e99546857d709e7f86fe06f61213ce26d4779276c0832e47d41069b1416d3a4e8e43d2f7c5448c5e01f2921d92ff1b2abeaad7ebf09051bfecb326d846709b52fe9d26db4fda8a365f71150e942529b74d16d62f1d276af8c831306bfd42fd8a49abca2357744ed46e71f04361fa43f1e2244be3fda7b7f633af670f67561219bbdf57ed7119397b9d8d965c2697d575eecf8c87cf96fadc1c33fea433ffa63334c4069fe1d5c63ffa0a1b4751b8d338686d8ecef71ae02672139b1ae74a0f23b3b50e0fa4c225ceb99395b33e81b533009dc259812c922da0d424", .None}, + {.Sqr, "b4c40cd3ccd0da3570ca7c83cf695c437e8a7eb0f7f1bf4be4d69565bd125eae0e3addef57ea4149c3a4a73e57e7df7bdd340494739121fb388e736fa835b06ca2a4b24437f083793b1a6f3c3ff606cd7d8b4d204adb4a6dcedab6300d295f3f5183f8cdc9ff5e919cb6bdc2c1af687386d4dabf646efc15c670af22f8743039329b1a17ab063185c50a7b931a2525af86cff28ce1b7", "cc06faaeacb8bd1fed8caf3558d02ea33b8f2927e4c16d0104ad1838ca4f91395b092bf74149f844424498fbff39c1dfde91672747de601f45d11bf992652e69a583159ec23cad8e05c927cf5aeea0e5865a490de7580cdf6e574e61eade9107e8fd41551e24098154ad0c6ec897ae447e84a09097d95bc02408a3f7eb2bf5d0407bed4b391052b650522dc44e33d6c52df6013f6e0", "7fa4482d7cfbdd18210bb1fb6b906e8b23fbc08b54020861e0ccec27cd4dc01da89f4a3f529c3545ba45149a96bc3af421827936ae03a548e50d5229e5d41a896ee20935a3800801180afb7f177a80672fd27882c4a6ce840c51e0e18520ff122ffa85ca0609853ed2d29d51834d4c12e6d2de1463600a5d260da96544e53791cafde33b5a0920a15c785a5a19edc30c1fa1258ed84bdf5d69a3677033be67f991dd6781b7d5dd3e1f30c692dc116f970c1717e093655e9b621fe10d613294ab4ad4d20242f858536e50c70298c43d1b5f27e2f6cb248ac9f1a8b1019f411d4292405d2fbd514ce2ef2032a9a0d96853f75c8c5905ee62950c813e753ee473b45a618aa3b13b0feb0efd9e2b18a7459c0863904447a16316d0b11b16941aa1af80251b9720214237a32b30d1", .None}, + {.Sqr, "18e856af2ca92bae0d927d072a2f72fe89a46cb6394e51ef52c7de632d9943f780400563b20d1f2110f68e0763e01ef69930a1ae176a2457a101754c0442e53fbaa29cc30224fc54bc4e0c825a3aca51f8e07f78822fc94c068749f20c54a772adc65b09f66befdbd4b5a763b3f1f963f35e3e6472915d6d28f774ce001920dfa6cd0f1b4332f0a0193f699d0451ba4cd5fb65cc5f89", "83fe1febdd424563bf6c5fa7fd12d15e58f2f5a61b0bef76e7694e01f0c96e22f22938c4918eef72babca92a16d53550e6e79ec9abc53227573b4720b3a7be5ff429dfa35e891db39d793d5e64dd1555c403f474cc91c9299266d3b48ac30bf015852708195fc54f0d334369ab400d6bbf58dc885c5f251cd5ce2fc7c3c3f7106767bd147c7bae5ae00fcab0cf3a84225f366f6909c6", "26c631e133ad4af8e7150d7771950fce91b1f7e0ce6a0dd8de812c358853d8b41614231238a383c26576a83913d5de1085fce49082daa238d5de53de3200a71b5a218e0175de3be51e8ee2802f53d0f65fee2a957e25c4f0438c4d8479b32b99b2800b38dadaf47ac0a433fa1b95f666593db9b347a757c2edf0567b19fea8fa136255d8c0132ca0a71d40a148a059e74dd93553b02bdbe171efacd41a42448f043949753b3ad32c125c9460adfccd59179c01872da3d059d310bc0f807eacceadbc1957ccfcd7c65d22b6dd37dad551a55d7f5205447be1b19a49d605c9943ecbb1dd7962f80e002157b67a3a43b643135ccf299e5f053fde7f7f29fe4744443f05ac4f3afbf7c6c765917f676fff5dad87ac6d20a7cedd69c176ad33f4cbf6e687724ab9037307ffef751", .None}, + {.Sqr, "e5cf1f4e68db5eda999327aec184341bc4f2beb5c5393efcf063a04a1151f2bc01095643c75dcbb9640bfb27f6b326085d2ae6ac2bda46a3accb5006bcc70b3683702b12f2e17406cfe6e22f3fd1950fd80f506c0090a3c90ecd7a97e98e57fb55778b76a0d7a78ceb61e9d1e16d9da9246038580d522cd6ef3bf76e8fc3ff6c000d3de88fe082046caa847ce4efc6047477cfc643f7", "527cc5cd0d4264a30d9eb4c80d70cf99af98f3538c6ce0c2ae38e4287226b5c706d34775a2c8141d9366ea9c5ae3b56929e0c50610cb6e6089e83a13d8868134d866a12522cad3f38e8c809af5ac4659b1aa24700d7cc5ba385783788754f8f6d4b91d1879e32e4bd06c315ae1a75468e8f46f19efd963026ae13d637b138faca75a4c1ee4f2efcd231d48d20026ff7ea84c9f9923e8", "ce4c3595ec3a1fdfaddf586d160b8fd7c290ecac4a07ea5f0f291d1b30eb774304a9a84fcbef5aeca455ecb0e5e2a4029a3790c52526161a6bb403f9beba3bc86578dc9332b4037b234b5d97fca65a3277041eca3640d7934f60c63200a43de68ef1ef6fd81966e72bcb6c403d1d41182e16468ef6d423606ab584672062dc77be4bb7ac1df4b8270087d4d82fa8af1591df437608bd3009f78f429340c0b322d2ec6387d84871dfbf6057f233c348280b82bbcd29d26dade9551ba88a17f9409e820b6c44331555f816e5c8b4f9266d8c999acdf1c703cd67fac8da83d3680929863fc9e2e9ebadc544082a411a154b1861c8aea5183eb6317574f88a4b3a5c4c6a734afb3d52a30130f20faee8f8817f02735480d7c399ecc0e99fdfaa3040daacdae4b4454318a61f3851", .None}, + {.Sqr, "-732af687b9898705ec86c87c2b7c5b59c5effda4fe038b679d696981c1edf713247fd6077449edaa1096a277e79a1e7421078baea475d05de89af64f1a39b2747c126bae9378e0e0cea078dcc195fa6cc0b1d190028b9d64555669b7bb6b391cca97f45b3603ff085d54597795755776901a0a528579b7d0fe2b717d7d7aa8ffec95a7270d76f0c30bc19a83f8f96b37e35e7d558de9", "1344f224f93b1d5a7a5f364b3f21ddd3510c021912ab97fc342f4eef35d3f766f72e712ce321f081b647cff2128eb6099fe68dd968a16fc05f4bc39deae08e8bcb3aaeb9a787d6f36a2a185d44a1127e1ece63ef87459be9e42da5f596ee6430866e55478a9e8ec2ab30873eaf0729b147955d06430df325f2a80eea41c08a9e0d3b1ecf964bc1997a0eb413e70d9aaad1c88a09a2bf", "33cfa0b3c2a390f925768e3432af4b08c9034c2d457d2b1ff536eb0db044f06184d2f01f2dbccf06a72703a05989aa103d515d8b26d98e9e41f6dcd80474693ce8cc6d95404c5f50483a6eaa3de44b11ba26b89dd970d71997b00ba5f186fa7db7da7b2f6b7e803664ff83300680ba54cfae4bacf9fb7783131188ca807003ff5003217358f2c715d612e6d63f9b716d230b8fd447330dee05dcdbdc7d7df9916673bafdeedb722ccb3ba200f1781d8d4c2b5711443e3aa4a634c335030bda685d29c3d97ae2812fb6e4d95e7be97170fee0b39ff7646db84a9c5b0718a874cabb781cd0130896772bde2de325481507788c51b79cb91cfb9c3a3b39988ab607c6ab67cb9d74033125b9d8c9337fa33528b527ebe0ffd09c516ff5f3cfce58879d2793cbc1fa164915647e11", .None}, + {.Sqr, "c217672091c9cfb60d1f24f528e6f8c0a336e38e5ca7a1e98a7a875998b49453692ccf058ba7e3e173f97e8ddbea1308549b6c23b8b1f12e6345957294b377b68dfa2c1acd99969a67163f6917a80e8481f9fc45ba99ccfa28a33700e49e74927f37392d03d9d4ed9446ad697cecb9240f85b075a68c104b1d6f6e1cc15c74c0cde6e55fdd44144f402e6a88d6bbc9c4959a98fed74b", "e8a2cb2776275b771391f75afcb13a89026a00eb7f669e21113e2185f742b11c9dc627ee5034019ccf36be1ea7f7c239c196a8a05af82bbb11be34e1eb271ff1e939d0077309e1d2da8e30ead035794678985d650ac51132072dbd7bb3594c755a0d1c2c886b03a9be96ecb280e5f9db4e448504930c34b2ac82f0915f32797256ecca9be42552cba36ecb11bb5e3bc502373aebebcf", "93277a710e5b4a88693838129cd7bc2d87eecb0305cb18faa26c930a82b282cc06bf450baf67e197bf8c2ce99508f60d07f41d39419cafb55658a9863703800d33ee39079fd28a18f1bf09a77d8376c1fa65881ce0c38230ed38666e85fc69b2cf14637789ac09bdac0869b8e41ea16451a4e6c2b46e456e832ba02b905a36ee08527642a9e54de38f434ef7fb7729490a1bc003a4aaa6ec4b21c37c5eddbc7c49557949d92e1e90d9e92aad6fd64ec818df59ec224ce9d08654f4f1a5c58096bf870036f5429f1eb5c46fa98948a6620da80fa3b89853d89c617463ebc90340696e5ea94dd7dbf7d8743bf339ed8e7783cd93dc9a8af32d6bec6fd0685d06afa81023878682fef904a684761fc8cd87cac2d178f0b8c368e844d8ab08d1c98aa057b354857ff194fde30ff9", .None}, + {.Sqr, "-c5470743a6e3c5f9619ed17ff9e5546f3085238fd474ef2f362ae6ba56a1ce2493fd8a4b5d282117a3e36567c7b69a549b622462ba792a9c049bf03a1e7be3eeaab9562282320ee62b5d7f4c8e905e908bea9d71773fcebd80db4103f6f46020d8047afb5992ce2477e26e05a279d9f78f3c580e4a533ba34c5eeed39064bfd94aa204fae7ff02dfe464983c2e86dbdc0831959d8aec", "1cd2272b35f0374a76fd513916e96fcabed417c83724fd9c90379a10858297816deb90f81c7231267ff01a0abc383c8bc2becc8e6383558328b53beefbbf51acc9a351ff4587bcef371215effc6c3fcb9360c192e6d65ae37a04aedfb825273ab23e58f01394054c8cde089995a3df137874948023d88fd0f187d746acc5d798ce850a11a68df9ca392ec1df1065ccf002558d5eb5cf", "980664e32695e60add6c07cf102514564aa8ee7d095eda2aa988db730733a685b9e415250d81441ac55d54741dfc0a2eb87d391ce83768e77799435fc95fd86d6be65827a800dbc8c0d70643c8a0d4fb619425b806aabb3b2b57b1a2f87a1e9ecf164803734cee59a9e3bb1a6b89a72c116448796e9c887531833a5dea7f6b6267bada0fd2f5fee2e0861950b9a88bd65c43c31a1e2fa626541b7aeb8d5d8d08ac9378881460958f18e9ecb444badd0b7779c00e2440580ffe68eb181bd0a8fa901fd61e8b28e7f48adc20201f20d5298d5766ddd042ce62a04d5b44070db88edde92985bf75fde6b279e6e354f8344f4afbf3681530902e37a532b1fe8461e9824fa2c6da2e55154ed0a7ffb0ffd2ed8873a7ba6741c55dd17998f5ecb6b80188f2147b040eb30268db4990", .None}, + {.Sqr, "-1eebeca1af2dfd2cc8b0bfa6be310e65112fd6f91877152816a42b646fe4c8566e5f504b356d716380b93462e3880e5cf7c038bc61e67614a462b902e465a94b82c2b734f197d1b8856e88e46a63357644de3c7c491151fcc79ba2b6922bcf8289fb27b2cd404bac16825da0b59a3528f919146d39c36d4824058278b8c1bdb1539129dadeb3b2099b337d823ef655964b6b27c36e67", "3df33cfc9dfac48603abf5a5d283c6a3f0c978f499a7f73472c0ee0da0e303f351a769bb46a4075c02e112d7f5aae94cd298e39fb81fdd7f599e43ce4da34432b7cdf099095d7780d773c6ed8f651671cf8af6b46a5210de72caeab099f465a8898613594d168ff8564830266800dc36e4726e19876e19d85dcbbbfeb04a8a1a656bea5bc85f087cb2592b0903c94f57b99677ef5f00", "3bc24e230a0e6dfe9c4ce2b76e2ec82175f40af13db0dcd4a4af1ad697cbabc76c52d0f757f53c52f6274bce3b7471967c03f38189377cab44067a40e3b19172b337f82ee5842410db6323caffc90766c16f0ed0ddf941ae411d73281966641adbcbc76e7395978806d4684fc4b01020322fef5d61e904903e04583bea945b139a6eb478223f3f91770ccdcc6bdaf63507356422dfc080c4fad8eb570f47b2834fb4b7efcd07469696e57d25d1cc7e861a6353db6cae031311f968a8b84fdf5b6aa351c4a6dd14570a7fc3de2ccac72b42a46de334e87c0c26216b64a58a00e169ed7a0ed09652ba7aa7d647e5b3839768e8d27d2f405bc2b267199503ff17232ba50c9cb43cd38d76d5ff654334db35a8787d799a258b08f7d58f02273f2db6be068708cefc4eec286ad71", .None}, + {.Sqr, "2b98bc0721949b919fa72adf4c37ecd48b8d75d9bf68df782fdfb8c4fd27406af1764df773ed74f69ccc76ea096a8360c8332ecfaa47c35cd7b1a7fc79d07f6e1322aa4434bffbc80a6a8383fffda2fa7137a4698088f44e496ffee7103562cc0f66f8607c90c76cfe3c556c5f3c935462fae8ab7150cd759ba29743f3098545d7acf79165e384e013cf2c1b4459a4c127a4072da427", "4783f0096ba5cb0c7cb982049e9fccb4b736765d497bba332772fa046bbfdda6c9336d9d5ae6e37a6c6b97f187a69b74d420a87a49b2f5ac4387937d9f6cb9a2c226cf487b521fd6b43bd9ace5c5e1d56d5c5bdbb650deb1276e5c1098cb22f5585faee4fdeace66275597b75e32ce1197a5465b71f3ea8c481a5228251c2e1e88c803c2acfa80f1053aee8aa1b212e8dcfaa2d4320e", "76caa4a37da4640c795c9bdf8f4f8a2c2def58d88c5394b4553add3999040626642fad2dfc782871f7163d89cff971cb8ea261e16f0e799e424322efb25c2740740a31f28a608e37ffef481096e4175ace5b716b1528693129013146a901554d4a40da19138a7bf9c8a01b3e94d39b8413b48f6743acb5abd7a1850b2ef9b2b84310262b5e5d4e69f9325aab523b2a3e551273ba1189e4a4ff3dfc5202686b4eabbff0891376b372d4c76f4200f4ac2cc6c84acf75cf01d1a396e402f2f27d30fca42f725f8b8802c81358a30b24c1f8329f11cf2e6920553e71bbaadc18d085c9dec23fe078abb8039d6c18a5541952e7a8d0c51fbd18f6711f302c58bcd456aa783d8c7d6bf3900f9858a6419ba1f2e9aaf11ce30c227e524ddef32e3358439d38b8a957fbb1540f7fdf1", .None}, + {.Sqr, "-b70f1754262fbec851453e67a1f8b26b9dfa227d4eaef7674acf99ff03c47ca944580bf85739da0b1684bde45910e3b068d2cdc6b3edd230bf4923a1702e548f5fff2e8c34d972dcac1f66329a88b3c75e17e31304e29289b792938d73ebd1d0c8d353bdea86182fb71b9ce3ddbff53ef616e9bb8124e12ea032729aca19e5997242e586f4ea49da94e8c3bdcbd5b00087afef0b26cd", "317e4211a6fbc31025a5a37e82a44e46dd09d28b17ff0ae5ace2f8e705de42257aee7b1de07689ea78a75cf6bd7070efa9411e056e33c15c8fe340b4fb835aae60385b0b47bfda39b7d49d90535202c408dd27b1c89eea0d71ffb0cf3dde1c246db9ab8cfabf7b09599b9d340b55ce344eca757775985e7d7a0787d8cce9fdc89e83634de7dfa7b7a9faa072f8f8b0a32e71d4cb0eeb", "82e6943e0c94f6e068f9ecf0543a78ad4c80167dcaf25cb238bf1fcee8d55a7034902bc7462ad489d6d7958ce6d08b759c13fc1ee08fe918812924302f512e05a0da21c03e0c3c163e4bf0d2701af2c03b92aa9f50bc363c5c73d883030d3daf89acd11332c016a4144fe8337a5f32a3ea4f07aec64bcb2c545500874084ec78a90fd81452153d3a8a486ee6b56292748e8d519b3ed5f7af1aec11b2562cf48063cef37cdeb24f2033c26bfc6a3e4888d2412413b26d1161ecb4e1eaba3285634fd1395696f3d9f2a131f4681ee5de74480a5aa700ebc73f62d04a81f0feac5d00eed936cbd70254eb4b3cb6b390afb804a9a8623cf2c04d8590d84a2c2a55e4c98cd7dfe3b2868eb504a4b2c3aa9f8dbdec2f51bc7b7c70d4b9d426b93cd99541640b8253611535217f8029", .None}, + {.Sqr, "-893e4cb7c5a269f7a32a78ec4d05b79386619afac69606558523e6486b3f90a74818954632a723eff66a8b8ad890bf2fd45b5707eb163881c4d0af8c2a4d44a5f000342f04e99ebf83f7d50c273a1a4910dd3298b0c70ccfdc172af74cacb6493d4e9a295b33eb484c28adb45427d57ae332d54928ea8cda887f3ea41315aee5f02057be2b57b0559043b31029949ccd0910d1f18131", "cf1775dd624b8c5b76f6c4813817f033f3abb3083a3b9587089b8ee05f8f876cefddf6142adda899b78f1c025a4847e2e9bbda023b27534a01f9f1c0462402f11a0f331839e1ae08af6fc49b1ff9bc07f9c7ae152cdf7c6caec6bf8d7d741c788ed7389ced4b68d7cf26349753020206bfad7474770f4a6fddb06bd165a9ca7524b92596b63fa7dcc694d28e6b7974a3071941a301e2", "4993bd45f189315af648650d65d1901429382fd51379bad4a4075b8d886f9cf14b78d1053ef323300d274f975a5d9747f8574637e58a8d8ea2cf3afb567be14ebda36436fedff833415975912f4a9f514fa770f880b2875c1437dada4ca5434d04e55cbfaa027ba6200ab3ff075ce34b1849fbd7e3904ee7e8d6aff94c2a8854cf61b968e1196ee0a70bf02847f2d90c8200415114e26283fbaad60b4eec967fe262677969fc653356f4be88f8b99b5f5d295606ec583a0c787b0798efcd0ee1fd8c6a7243ccf087def954d3b873f481a914e6d566f79d5b7aa8520eb389de238115e75c27b19e36faea8bff0e213c5c027d663eac990ee749e7bb6d7a057102f6274defaffc1661661cf72427dfd43a59e9d506bf1e607bd640b11cc2011e76cbdfd4c285ebd0e681746b61", .None}, + {.Sqr, "533905e392d53cdeba91775ace597d7c92cd0895fb8e207402820f391907ffb162346a56e623df6e184e809675cc70939da2cae21ae4072020087856ba8e3d6c412a14e28ffcdf7eec61aca4a65846304edb2316def78a53ff5777c89ebcce760f301114e9a00b2c48610f8b071c84576b899b31a31816e91ca3bc3f62ae4ed14978dd70b5502c1cb08c3cd5418d40eeff8727db12bc", "63220a4f207241eba69b082c0ac0ee25aa0f1adf44c18685ec5dbf51567c55cc3101a5c7a5d27ce0181814f57802f317ff8b717a0e38d288c502cf98cae83540e3989b53561dd6434f28e5c3c995670d4909777f595acf82fc69043406b47bbb448cbd1fa143121996744a746e73800dccfcb4a31f7d55e03985103b6ede6589dc3d6e537a06fb5dd97414b130b39e4cb06a312027c7", "1b0e068530b0567796ebf980facaadc296f475e48cfecbc58919e13d0e80a79dd49b7dcd5e1dd02fbc259dd43eff8aa2c8023c792dacbc7017d943ef159822dc5c0a66c681b159b1215776f53b950ecc3074873975f8f22520c9f68718710711357eae7861c1cf5cb70f7db133dfa9b6d41b4a5ab5e0d515ce1f2ebbca27db669f279dccc596690330a498b9832565b5fea257037a9e63421cfae6634d2f396dac3a97f931507d483a1ef4f2aac19b4b3ea05c41f5ae219a787bec1f4f6b3d91cdafe639e3bf99033707235a35ef365b5248bb6a3f7061d50bd0fe50bb6cdf51898cbda30262c452d6d8f8c98d1d940cee15034e48e722b60e0428cc10e70c4f782f4cd27544f4c9555db47b2952d3c02478882fa7dfa9640a3604e411967cf825f8488e5424c5765706fa10", .None}, + {.Sqr, "-edfeac9cee7c0335e39de968a220b761ef4df2efab8adc3045a61c79823ddcb482bb081b2d753f59c4c7eec7974f74e9dfd6bb20db6c651754151c7f446a3c13aa6ba6f110611e4a7db97516773f5184fd8c3be5a09c7e6f73edd179ad27034421e83f396ab283b57ee9aa93ffd178e2b19236b87f30decacfa1e1dc157087350066267601ec887885adacf6f2fdff3abc008294f3c", "f18f5f471fde33b3dbd12504ff27bba8811a64c412b803b0af536da793a767c795945d2a6ffbd3c561a9d33b47b5ece76f58e73939d67b4e6504a3bb8d94413e9d54f3fa5b8dbdd12759b32c03bb29999fa70abafd904ac325cfb794c0708e2721562bcfcb03b96a97c6b9e9227d5073ff141514c772b376c2e40aaa63cddbc9805dc111d8401fa0df7e6e23dd34928c5391c52b312c", "dd4188f58d5e1cb25001351bd163cb7f31c6b68d910326782a9007dc945d9458db07e95779bf7e6b15abe8440c10883da586bfd060bc6ae5385a1854365de2b8bb6f8348eb36ecff7958f4a7b1b76d52f2fd9664612dda1581052dd304880c205feefc97df0af9544b5ce8bed18cb33de3820a7acaa12666b9a02e445d062dfe88e46a1dbc9e444faa9f87931d053277ec60140a91d2723a60fd79faa124ea400949959ba176dd3268e88679ddb3e5d9279c23b9aab3477d1699834dc69afceb1a9a307424666c363a8a92ca9d9b721607108132756de6aa285954d523d072920686e9160836b39f0b4dd2338b8e2cf56c931a3b2b1385a905c9eb71f976c5abbacc5ed9d50b5ef6fd01b683c1ce12fd4898f2a97d9c42af9f3edd0f4b08af34eab17261fb9d9e39be1610", .None}, + {.Sqr, "cd0ad78deed7219c5ac95e2c1412ca39581ddd7873ccb843f11939712caea9633b03b0c918ba408c66ce6d8ad9068bb1f648d828699ab90a0f4df36a190d364b989647951ed49d409db8e377c158337604b9a345891c564a5b9b92bbfa40a246da2c7cce4ffa7ceff867ace293719f06d71e9fb4dcfc5d575e7a90d617dca6eaaea2531ec9f1bf232bfbbdcfd895eed59114b78e6990", "f9a86d36526b2ca55b72ff86258d010161396d3db556773c4aa4958913a266151c6c824898102762c94f8db8afa22058e0120aa72ecbf76f987a8e69434507a545a903872e6d7fe2369249a76bb9c65a26f2f88333f76e658915c8883c6115b6dc7877153613e0d33ec610c8a81b49800a170e0343b9ac0752a5190ef5a5ac8e3a6949e88a007b1178ba4a251fef3b684c65ae4450ba", "a43a5daedd1aea815be1f690637007da233acb490ef11ee4462466f0292688fabdfde3c2aef1e212bb2c6f290baff4100c5aaf427791cbc532390453bdf1b2d6489e959c92eae719975ce3d07cb6aa9e052fb37d4904e3da5abd4c0a97bcb1ed6bb1c22d844d82bbbe7fe1ea1d0cab97d01134382376665fe6b239d23dd2dee4a70a0aad575bd87dda9973a694ab46cc1371ef34aeba5bbea4508aeaeb5c4c5c943f77854fb4e7250c5f1e082fa35db6b876d4357d3a16527ff59c1f693a296932a27acbe5449534801675fa253bc89832d42c02516442cdecf3eb93f747568d03e7686505c8e193cea8f99f9f41a49f032a9e31e849536a92bd7bfc768a56d57dd38c863611260149f35b1c04ccf35cb3019f4ca7400901611bf85104e2245898c89a7fef1288a527477100", .None}, + {.Sqr, "89c6268a7933876511e7601326b11645917e82d95ad36558fab235521ee1874a724e90e984dfdec26a81a7908bba57cfd649b5442a6f4b8d6c74e9271788f8a5ba19103ca981021d5dc34471a09e1093d7e481664173e4a0281caec2d352a46d3610b6aafd85acd8039dd837f4cbb941356b2f4e0aa663bc1c4a32b3841619a438a28318c5b40f1d402e852460778e5e7f710cf91659", "efd6b2afb862aaa5851f9509b493d0b247684c25899d3bcb815910acf37110df2208bf7b15ec19c88f98b6f244eea31f51b9caa85ac987972d9988ff0835c41d28b83eb990be12e3c0b8db589b03f09cb5012e6c87017d536cf068bf394e632bc6f2a6623262d141d003931d79cbc4baf67750337d80892a18de43752f9cf139f8587e84df1583eefc5d5c793e970e88cfc10d73ce3b", "4a25ae9fd9ba0981cea31161dfd043b2be3a815a78e8943789f6a2aca0be64718fbfbbce50d8d4d9f341ebd60cb3d68f3727f984ea36a383ee8733af4ac26ff212d570b8cd058a677f2defbbb0b23c164cafdb0f487cbce99009b047010225fd69f9a874189f10555fbce5e10ccd6cc948a77ef94b5f27af5d41fbc29a86ffda9b5b4d32bc5eb843ebe43fd7ef761924ef37fa133090f2f8cc9577a007c18fa488c69e8f75ade6c6e00c9c13673001c209dcc6a4e7bc85ae4ad304d236b8045c662a7c20d774467f54ff493c21d96064f7051697be7aeb93f2739f627ca74daf1ff53b3d712c5cd39ce88142d4a880298b586e8e5bcc6b78e7e88e8609e9baba421871ce6b96f6bd5ec297b33d7611a2bb086f84d2e2610eea14f8ee8cbd3c5ae438bf40be165506d3156af1", .None}, + {.Sqr, "6eb6d167d39d5679a6312f45419c162a9af477f226542ec5ff8afe13c24ef140674fedfd66780ffc90a9d313af5f7c1b27d58c59c4560768818dcc57e542c8002fa556c4e08b818ab5d982dd23ffd3abccf52f813d7b96b5fb9e4d7ec0ad9b5324159b2396d0db6d19f704b6efd28b9ecf1113b2f58bf8060bdd57903aad09fbb87f7680de3a525833439014de7bdbe11da20f04080d", "e6a9881a7d49da614d1f427043972b61c804fb5b1a153ecdf7aef365af54c68faedcb94a99eda5aa70c2069d2f729a6ad32a210414a4c3b0d7d2fd216f0211cee9dbcf2e8cb35db5a0f81ed573d643febb3decf49f6e4ce007d504bf07f372f39a8da4714c6d39900b89bcd2d4a3b8f959ef382ab4ee4f15c0afe877fb88fc3b13f8702324936bc365513cf64afc06a80518adee483b", "2fe19e83a4c6cbaa5e85870e7bff6d8f80c8a245c4476c9f777e2f0149a868fd6f6845df13b7b2266e6840ef05f96d3e5c5e7c5059d57e46971f8b48471e7198684ec81c5dd0622d5457421677fe34338e0e8dae9f43ab9de5fd83914d18e0f994a8738463246ce4e90c887105928c4b5b503b24c9beab327277ee1dca4b7daa75e74d30f249da4f9d383f007fdc59176962edd8c82a1469adbc4c615f7a5cf588004b1229071f74afd71b9115fcadb9daa26d9d13fdaba65971c35caed2378e55b6503b7ad50663b1a6b70654034155aff8d06c0bb4ee35d3e645d999d7a148d8e8c224385a1b121d3c7f3e533aa4c4f7320b48eb7eedb0d21ddc408d7a13fb8e660f173a0c6bccb08d45b66316467bff6c5071d90a9403ab89d86bbd0ac0ebaddbb15850a89b75c6a8d0a9", .None}, + {.Sqr, "46b154f93ee77d35a455bc7c0b499b4788888f9a6d027fd69f5caff8d45cf6cf708f7017f5be11ea2328e2b3d1b9e59580ac7e5b96f303783126e18ac74e78d46fb90e936c4f0476dc61fd1982f7ffd422f49ace69e509d344a365cbbab3f0597800e2e805300bfba6ca733dd1718a0c3c16e28c5ff59bb906b9dd52dbad888c26316240178262090d0f657e244606c745d35411a27", "a46121209f61351968ad1fdbbd3fbd207c8f8a2621c91e74f769af9f3183992b26813c4dd1a6856a02c99e33aed5da584f9dfa4e6f13211942c7e8b414050a0d7cf67e37997e3450b37a66f34523c4af41f94aa114d77bcd3f64fdd0e1e22bad80df9c6dff8c1f1fc34c394bb2ef5bcbb3129a0deb98e8bb7588a9bbe0a5ab373c79aef8486e068141fe7b030ac526274d0e71421fd4", "1385754eeb441887d1fdd9cd9bd37529870fa8c55201bac983455456a08bf4a62a288f47d0d705d47e6dafcf9d3b500893f22d0f5eb9e07688a8108d1e41e7525996c95a71df6871834f6ce9be46b703592e5372fbe53aee241113e8c3f0080c642e02e96d263a91314cbb06ad24befa8b4a4c712d439bc4af82c07a65ae166ff341991805a3bbe38a422996afd07ab22387a814bfc144e925631c8559aa43de05d6f3f0144e723b0ff2ad8140d74fbff14837f074fc7fcd47f8601b93552326b7d6524906969439ee7f6e0cbf8e800f7c1c58b78c9e3f79f1bb5cd3300cdd748be0ed9eecbb7c83090f66ada1ac3cb3d92e8016fa8725d8d52b7027b9aa8ea5bb1d7703db974d0ef6e0337a79a45f171944fc6b83410af03e2fd6fa0d98a642bf1d760cfc5db87079f1f1", .None}, + {.Sqr, "d98ec57db147e081b9405fb507721a481bcf1bdf23b4c10e98afd15d8ef600ea4093ba1895c11d107909f9efac4c71074452fe3548ed4431dfa64f12104c960e6720790d06f67e059ba849af41d03f08f67fd98d19441cd9840ee1f78c277a60178da914ca3abef3228f4e027a7698c220b0474d300d2aa58edc4858fa06717dc9748ef7aff243c32bf607ed5467c4ac8ded7ee66148", "d2464be11f5d1be47d164fadfae4ff26a438306ece214708525d98e6862f7f6629687c12ba2480af5460a7a7fddbc8cab375adc67e128d9028c29e01f61d1def7520d5329814f0f6bf0a62262a6ccb26dbdc239b54f7bf724f92e70eb34a5f366a85592260a1bb642fc001c0eda99e60df708e959dbfb23e8273571301701bb37a492db0f52bd28bcdb593ee9f9c0adb6394da6a4b65", "b8e35a6ec65736e836760418bea0d35c9425e1da3bb9ae040aa82690fe7ef82e74e405ee91aa716c0a0e76adeea9310df9d0a779dce8fbd735b71fc41923c7725631f2809781cf0c042fa446586321ceddc379fe39ad5605799d67b4625dac3d26669ce8a05109034bd4cccb8d2ea26e795b678d512463cdb8f180c684df0746d00070a7373702cb2452732c325e7ef727e921f230c69cc8a0560139269f297fbc7502b6066c0fd4774badfd93be1bff8ff1895974d4f50e30c971f910bfaf47b79e21189a94e7a538688dab40709f4d6b8be4ba43d4881590b058413256b0e77da775047a70ebcd85f646edddbedd73db4a01b429517e7853013351abeb11dc235d26da17b14ea829b835a2cfd411eefe8b55184cf4918c09c2ad7808e574480cac4c96f5610665d257a440", .None}, + {.Sqr, "-aac5f3aadacd03a7162e830bd93a72914c6127b120cbabfc3235b4e03c2ca5df53b49329658516e6a5ae8ecc9c1810b0e9572f798a4fc329d714627974673d4308c424fa9349e0d65c909789198f8d48f887e76bb5edaceed1d5e297e8efce1690d4f6c1772e4d66e5a1abf6a3661474bd8d33a5d93a310f24a8e451c12f6c940c311324e4a70bad811c1f1831fae6d0daf279b2c053", "29c6fe3aadc9da5e3eb18d99695a9d5a3f09e3511aaad4f33bd03c4a03d95823acbe7c8272b61b4221cc31b0b84b490f72d2951e2de03dcf01f7f9df61b81d5f624750b7ba09078d159247132eaa691dc5c1e1149e346e1c31fbced9946507c360a510c1e8cfbe808f5894ae213397a9fcdd7b4f7ecf4e8ab70fc305d93ed442592fbcc80ce985b71540a9d632b430cac86e7d6e6615", "71eb80afd77ad5ca10d7c60e9aba937fdccf507958f5df836101fa1681c88ab1c1d7707623ed17eee078fefafddbf395104d247454365138d2aeaa3da097249becd6fa018523203bf74fcb9b9ff513a47a6c7f0e1a5b92cb0d8fdd6a8520415be6aebf3d07acf17f1e7b42a74f10b625e8c6c0c7bff7a821f75a04bec166f2328c5da5d33cc8ffadaac17d472bab4b6b7d8db87d3accbac86905df76583c222403e9fcc9e28c3520dcb349df1801c2b75fcfa409b2c4c5a0c8db321fb8e6174b8401020aa7288f17eebcfd5c26359d1fe434e2477659b548263e517bc5e15c58c3d8ba210e6f455bd71b6f0acc57393d9c99486240317de234fbc335dfa80205ff9b97911a1c20956f1e4e91e1ac301094e35ad0cd904eb7805cbe8d31e43c3c804439186a3b6f8a79e89ae9", .None}, + {.Sqr, "cb13d730480826a4f95c87170cb403dce5087f403a41507b68419831d022871caa264eb2cdb554bb4ec1ba1d596be423a079221424d0586e25c82b4251946bf24e89ea78d980fc7cc10f05645b0313f29ff14a58313df1c9a05de7237bec3a7e7879a061140dae319e20003cb370bb6cf2133c2ca78272bcbd83262f07a96a0ee07a4e903c5a475ab95038133cb2c8a4c8ef4d3a3fa4", "6282b5e6f2bc447714667de3c488acb83a3ab16d708075eb88d3a0742dda565f7a8a035067a8d64f217212682b9898109573b24fe6c454b89878e7de835db8e0d49cfbf093616bbfb0178952aab59a6aac0e0c0707de931cee3ffcdc10c10c7fd711e99bd810231a6b64db21bd512747a22d1808e877c6a7b8b043bfc0f24e3e22e5336abb9027653df243ff335396af796f5b956c7a", "a11878d03849c0982831f0b0c595c6f15a270f9355d816c4e625a54a010ae4cd07d0a9409d21acf022884f377cc2f22c32fbfec399af82c5f605819e66d529a9d5e66d8e9d16504f9992a938acb8bee91b1a07eaad94383e056672404825ddbcec1201957c447c747d5a9c4623f2d1437aeb689de3814e136546a6f15ad2a64828bdf574e3b0e040177da93e8d47024bb032621a2a63bff8bead6cf20d1387f436a0ef8b34d306e19b834d97b62036d33542af8c401936d47054557836f1e373a957b3c1e64a8e6b244321e6bce7b1ea6f5f3c4be87f015159cd298a1c8322f7527a19c4bce8299561fa1847274077beb055edf8c671e82a56d49b591d96f753d9c051a6da1b3aa0fd587c27450a9c83f675bbcd4230ba23027fda07919b3dffde2a1e7e179f2bc18e222110", .None}, + {.Sqr, "-6b953db03c037236c991ce12c057f2d0fb8fe825ac7f843e3453f82b635fffd666efe7271145e230d8ac7c861c8a9acfe0935d078979874d4dbdbe81ff58771fe6bf31508a76178b6f6c0222e0f30bbd2ce7227a3848ae17cef25ca27c2d6ce93fd33fe12c6ad695172ede2548101d5d12c143524465b7b1eb16be42e02b44f8b573e137354701f7c8b684ccf4f707e01731653210e3", "a4c3b8b6939ada28cebe7984684c8c3003a11dea8e0258f3fa7bf15f347cba6be1afe14564a100ef03086d0c825689aae7cd1b83819ba955142a427ee7e7bf3c4341d491c0ca4b38c48898a1eab9679c25bcdf0d7bac82e9bd4b5fffcd98104ec8c8bd6bd74012281fc80d5a07eee460d3b0c528f59cb2e5168f1ef1319ce6a6eff7fa9bba3beac5572201cb6dbe5a4b729d454b96b0", "2d361892302e3368f7834af7c2079e10de90408ddde6a53fad275c6b3ff7290b894d53a0ead9de54aecf1348e0d948abf7bdb22616422e1e6e31f1e78abb00e3c77aa1eda6afbcda9cc76b0e3dd0c7f8fc2ad8fd8cf5f1e6d5bb38f7cb868f3a2660cd6ad719d318eb812307fd7583a8bb123dcf4aec0e21268df70f77dc4a376d19ea88fd30393317f072f2ee842d73326d5e7a75eeb4462627c8e94afd6924ba8ad4e951d7febd0321a1d732d3117e3db70b5bb792f6812b0798c20736a588a7ed6e265e8cb84fcd2b48249246a2734d9523952a547eadeaa3b35554397fddcd4803f19b45f9924eea6233cd8d73689899984cbe083075362bf96a937d4e394101701a29cb39bc9442e2520ad43774c6b94a18f382374fb382a975bf928b9f04a90c4adb73cc03b7c92949", .None}, + {.Sqr, "8b220a6a9781f7203c1e2a4de576d5996faccccae370aa444691c7d400a7199348683f741fa77da3f699588cb10bfd6adbe4fec43ffb858b36af2647044b3c477fa6e5ac71c0013d017960f0e8d0f2267152f947f7817e8a3ce53b0a122fef81c290b871657a734c9d04aafcbdf3ab6de510003f3bca7637319bc977ecf94b65c0c84cae0fdcf61dbe65bf8dfedceae6cf17a42cba9d", "627969e3e84047018bde7b70dc4c7f5e64b75a4bdcb2ee58eec031b82f59d636d9e11c2d3eb5886c7fbe8409545b70735c0e77fb0aa2dc72678e812427a483eb7e5fbf12d018283766350fd877b3ef50d1ef2ffd826dfb6709f6a1afb1fc4f7efc7d24795124715465c1683f9604793dbd00a2c4e23ff9e514107c4021d4de6fe24c32d32b59a2b821b390e94ab47874ebafaf44feb0", "4b9dfbd68543e11a9e7278dafc2082547d9ead7a1d0d392e721a0e8aa2ebc40e77549ed3eda30830e9acd2d73b54c555b2c5f2f8dcccd5ec4be6360c3779b0841c09973ff27375362ab139f1dbfc8d6b16cb9d434975b2b0751efa71366f458aae1633a76ebb6fdbf2244e28a8a48e605abe02d4ac81885266f56947492ad91078cdf994ebbc6828e01758cb5a5fef34402f879e5807d3ce942d0f7b90e52b83eddf5034119e0a491617dcf7f206d58164775fc11abae22f47024511c216a1dc939cb85321d57b3eb1b14ab93a21bcc818b9a01d6a6e0d26f796f3fdf9910f0a8fc0871dbd86d692c57620d8a79eb4369acfab83397965d9cf0099b2cf64e730f1c989c5171258b7389ebbdc83e2a37c1dad11f6ff788d27042d1905f21580b8c4464d0d9538c51fd6008449", .None}, + {.Sqr, "261874f4663e1c2c910ea9e7fb99629ccb23c8d3cdae1eb9da77e8d4924ce9c505d7322ad0250f8b76ddbcc5c2312e5025bc4541632beb2f0090ff980f34f63cb9215a5780ac06db10cd0cb7aa037832a85cc35e0bb448ace6f998e5c774f6d5065bd868d55f14be1ac3583eb43a828cd53ec5d8d01bbdc2ef67b34a09fe827c39e3aa86f2ca7004e52d87ca5a47c502ae0c7d239e0e", "829c18de14744ddff4fb6ad7e6e6d559e37d9d0766b45f78d7e095a9f35cdda8aeac3c10d7db39c14fd35e7183c34cd33f99a2c65242f9c6e0b75daab63d84aefe682cb3a7eb3881de534fb3e7a90d804ba9d93048953703dcf9fc3a87d20935482a0d1218750eac3c40f4127eb3ff9467b71c0ead3f488a22d67510ce65de49f4519fd160864bffa2a0888501989e5dbc2aaba6294d", "5ab450eb19c01fddc2f331fb4668e4034b9a648c443868377bf2e5be5348eb6608464f011e63ba9a24d04414d7bc673f01bfa8f6fc8eb010bf6a295192c2e4f318dde8dab945962716b5750a4bf5e37495a07e6504b990ba2efc8558e89689fccae06a006fb10eef1dbb083a129d995bdfe76f4ce2168e54437df3310f56f9cb2dbd2fd4e79bcdc903d28fe9756a4da89976bbc8eadda4462e16cf85284ef7ff565a2d768afd5e6b00201582c7c00e330b89243eaec8ee7bf85c4353ae1aefbb4dae03d6ebb0d677f1cf14585bc1788c6feb6916fe6c51bfa1b12e728af586266133b7ee9267ceb405ed3c2249a1e48beb2507b9c7f2a00ba94b346fea2621ebb52c49946ad3be9956e758a897e51ca278e02bc8cfccf9198c8c83780e61ca50e1b444c6795a69e456948c4", .None}, + {.Sqr, "-3624dc1567c123a602e589c75aeb534b3b170dd40730479ecf9dc38bff9f126183016f7ed5428d9ababc69f94ea134943affa7ed72d64ef1e02da19faf0a55b5668e3073cd8f984ee97ef094a6841659cbe225b4df600426c5db06cd1d3c08d497e429c8469e0379671a54325aabf04114615cb7533f5055edfca4319b77354e80c9311548ff6b9d6b0dcf10336be18feb749ca7ba8a", "fe715300c29523d01059facdb66aa93add7f94007fbf943811fb5a1a24ef492e983ff84a6dcc6e7263de47d3dcd4299c78fd28ab53a95878fd636cb9bdd59e267df52edbbe97ace4980109cab3cfe33b8f058ef67d2da7ba45c7e7cd33ebca1884a2b78ecbcb3aa19b3833f96133090648f27ef34025de58c9d389f151c1896d664695021a4d1f634846a0678c87bf329bcd329fcf5f", "b739227aaff757a34ebd14c347ffbb73aff596ff164a36a3f3fa7af1ac4a0121ac2f97792bf00f14cf3dfa35219a2ecb5eb115ce78f117ee344be1c9aba05129edefc2c9401c5559feed3d090271588781f18da49e002e35eaac18e58817900707925c168e3ef85fa55250d85f11ee03b3a8752a412253b74af46f95786d6a6a8c439b4ecefee95be03899db56517bd90df4e35649e4c8e815e9fe13cdfb52caaca299cf02e0ae3c15ebee6e7ac1436e56ab3310b7ca5f6e872e1147b4fb89c152a2c8d74edf2722708e9d148306402b40713be764da9f5fe55dedb0503d2ed8f01df6f2a5904c2d5adffd2e9ad456b977c2d5e145f49f61a7e674a262dcdc375e4a991657de887c36833d4f21d99ca3e1315c19b45151c4bbc197bf904b95825fe115f4283424d17f8d264", .None}, + {.Sqr, "-e920f093db13d143980cd28c4e42f4f26cb3c0e84ee19ec151b77b458be8afce1a96504d52b37dcab66a7839b42f7ac0988ed2c3a0cb78aebd2298e9367662fcc0e91ce4a028aee05c2deaef490e219eac5dff101a6f10fd80a050b2648c81c3ad583d1f4c33c096360596400267a24d21fa1f66aaef39f479bba6872cb10cfb2f1d596a090182af39fae93c667500c06bcd51576b9", "cc5b216e8ff330dcbc02b942b9fe2bb82650f8510c1d32b3dc448aa4595f92f3c0a3c03a301b0140f8036ff5274e85f34245de13bcbd2131038615fccd9b66221c1d32b72ea2138b192756131ad52739be2e2bffed869ca814269e8e78181a86dfedfbd046993d65d816ddc8813291e7d14139fee7c3500178d6270633d78a0fa186863cc63c0d992d7fe90bed4cbc755980b37f4ad0", "d44cfa2a2bd6680bd84954c3144844bf222ef13d6e069ba61b356533fde55d5a01c7cb35df0b367e5cfdae9e17a05c4a23cb277dc0156bdbbb5a4164adfb075395603be60462ebf173219de04a221b55013d0ce1bf3b21f04a63d581e861702c5e1722bfe809a928596c50e58ac439989dc1eeb9458acdc25980ef7f7da2414331e705ecdb84c20d03b1a1907a84290489c6e2451fb5aaa42ffc061ab6eb8b2fa77002bb2702203e6d7bb7e3b9f6b118dfc6be2b4ffa7c018be1e5d8d1d46938f325faca646f3ee924f9879aadaf9e3bb5790c326e4f78a226c90c591d11b222d9da1a1cee7c70932c60ea25a55737cd921bde34fc38bd2ab986e2f083fd934960be4747d275841541e55a39c5ff709b9d4d1cb6b22a574e37dd01a0679e2f26707e5b6bcbc5148b6911b1", .None}, + {.Sqr, "-d7b4e2404b0abf5ad03711f00f41ee278ee5a37671cae2070439fd39a06d29ed79bc8290d2dfb7089a56500ebc3f22e57dc5979e0df1f4c08ab268478e7f5bc99fb1c79563a2d6b5b71513abc1c07d00a8a578d87938816661c625ae8a073c59ddaed6557cf931eb1464a64fc381a039cdcd56d6000da2eab80170948e46989cffd2c3ed0186f43c8df4cea748c48a758586b54fc2bf", "8d96780634dbc94e34db94c353f990bf3a8f04ae769da76a7ee8c046bbd1ea5c8164224cf131d87dbbad9d5a4595c0bb6feef4cfacf16767f46e626499aa05a1c1d3e68a59ffbf610abe1e1b0744ba9c7dbfac9aa28cda03307d5851b84188eadcb186fe0800cc484ff21fea1fbd794a043227af596cab196c8a7bc215878fafac455bba6013484db5cc361ee46f5b5f8b95986153ce", "b5c153d6f06b292c36ac9f2e828c316eafa3c6d36ce150540a2957907e06e16567a28fb986536f9381fb79846c169bf06e57a3dbfe6571990a4baa552fdb404d79ed4dfd66a6f6221c821282186e079b45265cb75ee56846a84742d70ba629d4df4fbefa552c18b0953d0d334981302593f2dd6aeb6ff97fde6246ee2f68af583971f2260117cae066d4e6e2261c6af4890b7ccc2397eb9ce602baf7a8f2cceb090ab58155fcf338139f0d0589794015d9911aba2cc628cabf04d32b58239bf13f039c526e4dca018416a57b29ea615af89524353e0ca817483398f24b3eb751a80dd294c84b8d97b0e914ea4768b659bb0d4300bd1632eb2c50564a1086e6c1f21b5e1aa8ed6a8220838a3b6b88b46d3cbff7dc773fdd63187e40164999b3be87209c9d1eda382fdc080a81", .None}, + {.Sqr, "d3b0e0563b42f06a23f47ac22310e25a537dae2a1dcae9aff41164f535807e41b93793cabab3bb91950821b67542625fb10a51e173063a8bae702fc662bebd677780a474c13a44a4b5d0981df8e21f270edfde06cee8561f650ba13d2f935f4d567244cf7064531590a9978cbab654e8e57689c31fa893739d82ad98fcd05816c518f11016170015da2f6f3879287ac5adda47f722d3", "3d4c5b8b3b616e512ad0663ee7bd6a0c94b96eb420cbca6342a399daf64d651e25cf0835b6aafdb3b5c686bd62cdf9d0080560465e0b2b9679adcaacd179201df5b0d3419febfb20d3832f452617f0b45835c86fe2cebda9d0de6adce771e35ddbcbd9346ad8e4000e4c16030327618c2867e22a01f608a9c82c77790fb919e4ad56bb57ce9a1db0f62ceb522bd50e5fc4868f8cc811", "af0d0c0360d8d91a8ca1a51294e8ae36373c6b4f4e3b09cfeec99571ce526b92b4b4fc591e7e05673b29da2ad30dd6c04b87904694c3fda7947742c21a4555ecd24f426a75ff2ebca1eea7a9ead53c935a0785be7af7ace5fde3f0754b0dceffc1bae394121b39160d09b6753dd2ac349d7c151af89306994111591150d74a16b55341b7e43eed97d680c2a9522b86e803b60b5022a00c468fea50e2e5efeb983d27988bd675f91358443904bcd95de5f5dd4a606dc079b3169a220681776790c3a3b5bb84680f2106bade89bc98d5e2ac0083ab782397e2e2fd4ca79f8dd794ceb388e8e9a09a934d3106462b0146ea1e6a2e29b9cf7712209c593e05fef872ec6e3b1ff4c106d590c61ad1c27185f3cf4626dfbc6ded87a4c65ae1db93a063671166df5ef1814141e6b9e9", .None}, + {.Sqr, "26ffb67f47cc992e053ad6ba37effc5455f2312fffc5a606443919b2a884a1a20cf7badc5f30773bc2e4f5da2e1169b3df94eb30e97b3700c71876eef15c2ad9e0f4d1fc87175f02c019e0d88da4f696d07b2e33a5998509d2e7fcd76e75aa9fa847ba3e1f91e8c03a04291c39b2f5f2406263ecec24928e7ad0fd0f0322a14f049c89c3bad1f6be0e52b05373c73ca68bf025db530a", "9b63d33da4dd1c63a9346ee05527614788ba76c60cdee8efa17baff438271567df33082498847cf69b8b9c692ac09f43846783c2b178596ea7293a06f9d01ca8bf90d3915938422354b8f5ba2673c4e08b9ddc7ffd2aa1bff6c1a983371a222ba1f115270db2f800d2bcac2166519f9f61da0a209b9a0792be54395fe7a3b19b3f357f2b7905e43cb05a1b52c060eb88b633a718ec1c", "5f0e99adcfb00720e2c6e8bed2f86b62e26c51d0c68aa3d017fe3faaf7a35e61bfdfa2b2c33a6d936b9e17fcb73266331733ede75968ac94987ca08436908bc5f361723af052a40d27a69048b9522726e960dcef56879bf391a72cb693f865c4bf4d48c69c55e229fbf684726565285fd98037749499ce369f6928344c7de81174c41d185a629a2168631b88d0ddcf2e9014a503a76972239e1ee7b703fff3f327a40de9ed2f7b78b1f7c05dfaaab9d1de8cb1b7ed02d5b2dc9062786fd1cd05e0d6d336b25b244070a0f1635a7bdad652ea5b1f7a2a2acb19caa870c362c1ea41f20ab30afeccb5ce8fc2b6c7a73327d5c1d831e6725f57bf907e4a52fa7cfc5538c7b3ee972cadc22e4aa0b5cc33339ec0fa9699a51264830ad6ca53a381dd9c0a74b8df9b0a8120b7c64", .None}, + {.Sqr, "-182f5891485d0d44d1e1a5d0c75917b858f38ff2bee0a5aa88e317f02d4b5ae355afd3a5206387ca588a402eb3e7d324236ea2d8ba261fc047d2e4099747c46c8c0d0930f9b4bd388c914c7775300f2787e4f0ff93e5f820cbe2c6bdfc91770fa757903313b6f8b9ed67d894cdceb5db67c7e44b8131bb265a6d6bed53479cef2b59a5e158174ba0d8d0e23c16ae401b2609afbb9a53", "2cfa3f54bba5be73877900f297ef67d0a7fe90fb99ba170752919c8ca992776a8c771f5b6cccc3cf4553936c519f3b7cb5a3f0aeebc652fb253c049175dd9aefb85174d87a2cb07832ec97f3b9445480410b60c9e33d42ca9b9f2798af3fa27d418e0e7209d93b6ba5b8bdd7aefc7bbc58960e216b41317d0e530c64b37313974738984891b7923b1516389416fea868d7d81c8eba52", "248e95ce18e38dacd9c317c4666c1c15a3667484167cd3eb249cb3589d9d8ac0cc36c4c392675cc6f62ba2ed6c315d20577bae24ccec7944567fc03e9e960d1aded0268e712aa94ec82eefbeb51d45d8ba53f9408e58bba995e71e14f7894c84486e4e21b144c328bb33036cbe3b35b421292c97566e80804761f7f5fc4cf9ca1bdc9945b1f497141703f821839b0901ab6cde58142471c69618ddf6bddd3373070955b35f3688d6fadaacc5d555ef483204dde20fea003088a926eb0f68eed6d29910763c0f187e4a2e0a357b3ba73ffa0e133c22421af3ff3db53164ca38772e76ff09f1f4f33b9f9d6e075909867a44e69254625f956a762eeb9a9cde76de066e868dee81ca1dee406722b77cc255a589aee511282ae53f6efa47d57688fe803cc199325844e4c49f6e9", .None}, + {.Sqr, "c17ce975a280cb8494c238e443e6d0a8d25607c1ff88d9ff14819df8a852c48c49a69a01e9af728ce827a5760822be2b8adcf7d9281e51e3ef7c9039dda77b52b2fa3fbe312a40574643895c8108ee4391797087c0a21f40cdf3858febefb9eb85aee829f5135c130e837671df2d385e193689e5b09d9e5f329dd97d482607b98caf8d4263bfcab16f8d7f62b2ab16ac29cf3304445d", "d0e2ea02b242e8fd5c0a4193bcea4b14cdd263ad9e814c9dc8d5d02c51d45b17ed0b5a8c13132f1bbae3bf5556c221c4d6ded1317a5b73e438174338e3ef0c33be3fe6e67cb92c9911b489b664a8b81f59f366ce82f1137aff151f483f5e5652843c7dd42541bd852d073c21e947cb3715a1bca934372d5d6ede5551334b853e9917e595411e4b51034f72668414eec4dddea7756822", "923d94f65de2f77f74159648c3416d4878a95f598116b79c91e1b9be6042c3f4406c40c447a5905e6e7763e91a1118ffba42708729b8704a7a66ca8c76ed267ebc2e181e5911fc1cde5547c9bff4c9a74c1a6f76fa3d1dc2b59f87ab0443d2e45e48336b48e22ef16947cbdb45539f430d6d7dc30a948fb23b5b8ccd8fea4ae27cddcab0c989b6e729017b09abcaf758f16e8dfde7bdf11981b9fa65aa67de21666579fbbcc746e3046ddcf5f200b1ee3cbc486ae13138abfb1fbd9c90bbd33c6a695820b5cadbc59809adf960d099612c2d371c824698c80fb80908a205b6a9b8a5b7d1989e09a8192bbeda1de166705e7496b55901ca2ae8195601d5e1e30c2e0bb7a772e1c8ed044d0647da1c9490c9de8d5f52b422cb3a4f80357ffd484285fdf7c4c1ef0bb5432989c9", .None}, + {.Sqr, "-3374864e51c6219e4bd14c4816142bc42959edbb81bd0ba22dc665d91f3c0ff0149897e31a6ef7ddd04b0c2859a95d10de984e8bc83ba13e990c57b226bdb55dd346a251bda328ca3c2f39497efe3cafb03fafa90f3a121f792f5bc40e25ce106516b86d9d444cef4f67b721551e8ef4d790aa3a8554ebbaab33cd3adf3b09064a5bf500c6f7b26dc8f7eae89d15332cec04b496f73c", "72e348511589e6db840e8e570d0b704ec2065d3548ec11e7bd8873a06db12512fac56004771efd357ce2c0dda5ee17a565a0710d1ad2b1363483abbb5792a92a152bf341667ee31c05ecbc7ab59a4ed5aee6f7498112c45f415df5b148cd3e54a204e91c47b33be22573ca0a427b0b6692621ba13e84a8b70c9020c308526a47ab42ab1d25b3b6dfb9b4546867bd7959761e2a13ca3", "a57a28d32052284e3b748855ac7ea37a44f4c6daa74485f8ecc49f53015323cc89011bb332de43d7a3071d4d6c8d4d3daf5e887f78915a38e3c177a8a34cea89cdfa807a79f644502986f6b81ecb855c7c7c4efe9ce2629e9dc31f8bab3846d289ade27f1b9f56ad29ce5df5b9d06231a395f588eab93be15a1fda1b9e675128efea049694a20bbc4215276b58ebc19452d215ca24258995066b0f0a9e3dbe7a20f66da89af1add0897d61cfcf6b57ff6b7d2ef8ab2ae2cad1821750b37695f865ae5f0b76952bd32f767e4ab25a0d5929be81a615a0032dc9461a9419e786b19c61c9d799d079dcba7ea704091f6d6fc93d62f3ec063fdf1b3dd2e39229af594a75a0080fb8a47a5bcc569e060256b562bcf5a9198802d2aba4cd142798f9473ef0f4b6092fe930914d610", .None}, + {.Sqr, "-ea1384ec1edd9af205a7f38f69b9f6886c2290c6428d4d03b7e76f0411c640e745f9c4d27c2d955e0ad84b100b6a8f26b9f1c76734c1b27cd287708f49a225348ef3416a33d1bae484bc343a53429f6abf54ee111fd57b903d620fd3ba7b1333dca31a4bd6550e8c17ebd978ecd28f62f648443aa669b7ace846b5870bc23ef5cac2e2becac2c03a3f0ba90c428b30ee287ce2ccff81", "84c22531aaf411a65dd306a3051a11db14fdaa8d31f383707a298229ca1bfd590f7f3f4a6128f422ecd0e15022a1962cc3dd3103dd613e7f1229d999ac87b7dee5eda8be042151510012a0c4d624fe0a9a666a13eb7069fe495097e60aed39a2173511808608d3655b2faa2bba6122b4b1bb189bef6c05563122190ef0fcfdac602d3347450408aefb5cc25f801b64513b38daaec2fa", "d607b07ca87e0dc4e65bd465925fd26b981f9dbd7c2b64e269cb688089a3623f06e9506580bde22580f9277f76849832bedb5c23390e25a4b35bf374401cb154a2e047eafae84b575d70d917051eb26eb10e2b9984ab6a78d451636231008acd88a20898d4e1f58af3d48ef06f4da4d0c306861fdfe57c31ff2c1a83a23148ceed216ba63311de27fe47911d07fa7f88ca6e0ba51855e6467ef7b9d9dd278ed7b56057172589a7df62052ab68d61eca270f85494e11e744f935240a7634352bc49988085e0938909cb35122c4adb0d98e7c9a705eb31a376768646e6bca0c11a00918ac164e6be1bbafc1da091d69755782ff138fb30c1435d03c907aef3f52c3748477b5f47d074e703fcfda108346d757191245568b545778922b751d5e8f4681dd2de033a6c3ff89a3f01", .None}, + {.Sqr, "-81140d03f3e634ddb98e856cb250dccbf46b246e3fbe0d541730f5e5493d4924842c33e53427735f71fdf5b5a9da2ccbc4e4c32a7c67a75ba95cc817762df80ca0f1bfecb2135939e678749bf107110e5f7e9cd3b40c7400cce00329ee3dd4ecccbab0b98eddb5da649e277b2610bab4375cbe7d98569dc08319bf9b02798eeb55194c3eabff15dd6e81574196390a4af523ea898c9e", "d4c6616bfa5913d4fed84a38bf126a88e59a1c4614cdc2f7f2b69ee3455e99417c59171362ee0cc1b1a81f39c2bb1fe8b84cca06534fbbacda3efbf0f8e4637e9a1530f95702dc0765c916bccb8d0903e4dc8b73f16b00b3d241007c5acac74cca47d762b8d00ee2b80e7ada9cb6943b688075db910af5ec9dd0cada71b815e87f1617f3ecdfbd8fe2692b8c022449d4b150f425f316", "411536b005158414b8c93a272f2e56a0571fcdd3775507909a999eff8cedaf1297b332de0fc17e8494d59fca4d373d998d4f77e06f82eee2aaefa2db712799bfb59ed26fb6e22f5dcb0c4f75b57b2ff42299ac858fd7e2f4117260615bdc75b9c422a6b3cbbde00aa3759a28b54f756830bd19e65f0234ce50606ef0972e8341eb1e1b315fb77570d2b8586502919db621f68af2db48ebeed651b9fe20295d61fd877570b21eb2e82f67f494175f941d0de9454d20eeac2f2859fb3e379c883f2c15c06d5950fccc717f99ce255b9c1224aeefbe0e44f01cdaf4d434a460c544e8588e7ee4b3416ede4eb277d051baa1c533baa3f6c9f342fbb0bcd54d3f8b0c7ee1dc726a82b032b289bd2d07ba3746e1881a1d72e822bb4139b6879afb4899e019e0d2e2fa9e2ca6593184", .None}, + {.Sqr, "-8f239ad49db02b2db218f930cc144d8ff3be9f8f3a5cd174d4c50ada00db3c92e1f3c553b4de44873c17aca822b80f14e1610664441f471ff094c4f0f3c63141008420cfb6c9b0862ed1fef42d2b6febdadf7437a292cb41026ab4dd7c5642fd23f0447679b440d219de4e22075f1eabc79ccca869bf9e9d9b5763bde5553df2d7422f62a7a0d412023a64d6af664badae7a349c8727", "a545102ed5fcb8928adaeab4145778cf540d4ba24c8854ac44e3a649d86d0b69f7152fe8736952711bf9846ef5b53b60e1324b1958211ff45bc4cf60faa2ab87ecc8b947f6284499ab62111838343a1cf970513283c317894db721ac70e5e0b0aa6a40c4fd082d256890646ecfef35667af7877efe0bd197f0d369dda28dbe33ce240d035cdb212b8efc206dca354a719601231dea10", "5008cbed3bf26cb65c52a55f1f11d087706b83c9ffa94b1851a85cfbf0f0d4176ec6eef5cb9c73c02e0dbb94c208d4996bea13099fd9f8dcb616387f3fc28f2e5fb0ca2b13e2811094bfe03db286136c2006a94921942d1b0bac4cea532f856c4aa0966389ad59975a32c6e7d68405267e66f4c9d627ea339ff8530f27fa51ef94bfae3f3fdbd67387b55a5a4822a7cf409054ca57b4652f6d5d50038ce63eb50b01ba3c099418e96c4ebe17def13fbb56cd11c631e1ae5b6c76cc36951ad441239ce0596b89ec85853e2403a73d14376fb5bc184980fd920c285918c90ee24f2bcb06105b1121c5ca9368e989e741dddeb99ed52f6e4f48a59e978532703184f035b07b7f39231dadfbf1cdba1f491a969df6dd1a8c4afb5becabd4e94170553da031ae7c6fcbc8d6e227f1", .None}, + {.Sqr, "9eec95df0af6597cbbdcbe6efff24c5789df6cddc7f39315462ef3bc8a666002054a9582ec959f7a619f9fa5df21e42ce05909821cffba07529136481bfc6ef90223c63d43b5bb125bb463454f5f60cea5d62962c83aa7662f4d9660777af22ebc0e2361905e7781274720376203e813519964a8c3dc2d8a5fdfd8b02f561ff5745e3a09e62b6cdea4a9aef54d4477f02a9ebb643836", "d509e2d835cc88ff45d411d463931eab000efa4a7c105837d2b096419806dc9d8473810c171582ae834a365a169bf5cf4775e81608c5d287a6a329d165de7f8c81e6a8351ceb5089ae9d1f70c25bf0ce6e4aa1a4269bff3a67c3faa9dc11b19ea18d548fae156440645d4494ecf784b110dc67279ee661214e42204fc8069446aeceff8d64de19dbd9b166f89b7abff8d4d634152146", "62a8e3a3fc81b1c1d3b2201c3a863acf72059f00c4e1406284bce00a846d9f8a2da3b0a0d3a4b5a63e475ff706d17fa06baddb10e179c99a1cc67e0a0b4103f8c450982cf80c72fb0f86e70da8f8b9bdc2f3c1447d14d5f3b3abea1bbfdfbacde62f81396ea49998a46cfa88d446044cdea2e1d813db61dcd41126592761acb2efd0d3fd65aaaa51c14967c287e33502056fc34139d94e581a7528dd2327fd40f1b670151a7590a5a1930f68bf78e22674d682f8745c4c81e315949c0e2475cf144cb138a45d06ce9351805d5ae0d67ecaba0dd667b5c857df444599ade9a3d92ef761bf599e8e1e0a6d978bd4c7e148e4783dd87bd7975ef3e4da1b7154d9f4b72e5d7c37a27bb4bec30b19387a85640caa341a69a11edf6eff6f26a3f99b86595958c45492ac02da87ab64", .None}, + {.Sqr, "-5b46f79c8d8903d6ec891f3bb735f94e37b8e224ded868b17ce700e62346bffdbccf0c020364152405e196593fa2997e347500abc1aa2b591c439c704c3d53f765870fd88ebd3805c34e43f1c6da3df5c253d8ae71c648314067d0b363971b666f1edfc46acac6f034e7660a47972727d2b63b8b2d279f54483719a9a252d6bb894235cadeb9d2a7cebd26490224172d91edbbe9ef60", "737483a3cfab7f0c30586d34c2960f278afda7d4e57190e6ab6c6b7cf8be571881e0ff9330eeebb2a96819553581413d03dea4eb9e66f933551a6fb06917f2916a62620f527d66f522585f28d3a03a5964a9e4b1d94fd748077950d7753d40c6a397b075ae9a4c4f85d01a93725f3373a83e7eb53c8cf38c195dcf88980727bc2d0d5c99139fa61d0e826a4e7396f9a66c52ba87ee0a", "208b87b5a5bc48841858792246f2d23a1f84f64bad018c88ddcf1050cb2f756c0d0dab11a98c7779e88851db71cd9cd4063d039a3741ab041466a0fa0848efad5cea6f3be09e57bd7de715033cd002de3208a75b031341c9b2434d153b72f9128e1fd56b7fd71e9ae6cf51f746b65bf1c48c8c8b4baff637a7f3dfceb73ca2fd59f1d7701ab279632b3d36e8c2651a17328560bd28f963e646603cd6a13f16cbfaf9c80ae6ff523762d6c9ea438b6225b34699cb360d4a158896a424a725316792228a3d984591f387426a5070f749b51ff94883711b37a04e20861d83fc191c52e3ef90f7462a049c2ac9fc2875328aa2c3b30087c8f41b075a2d6baea965ff2db2b81a45f3249ad8d75a8168d80c069f140203cf1ad439c2dcd8e6ce7a8c5cded017e5e1ff913bdc946400", .None}, + {.Sqr, "-30a4be6948f7ee1f19b30fb875584afc037781709434eb313cebb669002d6440059d399c373b4a6fa9db1ed99b141b4e7128e685e69d7f4b5f2249d65b06ea90bde47cd4ed96473616aa12a21088c5ebf3fd8b1e132aa68bd01e35d48e3eb70e4990b380e17e58387392bf1b6e6f7e5406b90d66b65e479d932e68a88bc5038ab13d1a3a5e28e7c55a506aee70ffa0d521d383f372b7", "f871e535b68f0833ec3c220706980ef09fffc31e5d4a6ab20fb30ccea116cf7ee7cc8f24db175b216db80fd3a34652500b33d801da0a74dc610ef5ae612ed23fc9eb4f86f13b9e78d18dfc9abb9e77cd3a5d5f4f62e1d9d15f97f3bf9f99a32203b382e0fcd8613f4bc5af27aebf3f5a417c7e98de2f6b97f49df7ad9fd97cb8f6447802dc5ceafd9b1eb994fb753bae13b352b72a1e", "93e316bffe2ea91b71ff9090c8650ae2b0e33445ae42a0567483c8cc3dc8a83a490005263cee24c536f5f1b9efc80dfcc6fc424fa58af2a67718b66305bdf54c1986ab648a5765b5a3e56671107608ddbb98f6374d64667a24f402a4ebb8e0538577e0a079542fd91801d02f85b5c5baaa072e5543b69f16875a90cb266ea1e4e60d3744fa4d524b46b17cd4d57ae11cc77683608cd1dff93059d97e9c69c9d94efc03fe90d536e2cfb61112b13bb62fce4c20b066d51fac2ba8ca88547c34c7e8fa0bbfaa11ac9eddd202f9dd6ab4556aee2198d4d94ad16f58dd5a891993590fdbbee8a5e4bc73352733c5e140919141af1c11247897c49e079090fd44ecc38515cd76499c5cfac0e75e66285c7e8658696dc76dbb9695246c028ce42e4986f04c1db2f6b569444d17ed1", .None}, + {.Sqr, "4edbd5b1501cffa3cb355f313bba606046fa57b7fcbc52169e0b86132ffecb34de01efacb2da4184cd5cb13967f3681341df536a06f9d628433fcb0382edf02bc707d175e233be2ab8f7b7852c1a63e156b7ecdef08428f6316ced55fb4ccd4e3561cbc684a30eb879ccd4b3770b8a03504955399afdcdcb0529e78187217287a20429a61740fd55f89d70fb67f790123fd06f8dbb0f", "d74d93de97190ccca1b7fd9c58ca7bc8a15e3aad278cde3bf1c1e8fb93a165b84ae8d0b6e397caf3b9d43ad98de9b7fcf39244ac03a80777d1d38c719e546a5b691fa06488b2030eb318ecf6db8222b4933db53a452fbb27e50066183f4fb4666cef0674523350481aa9757e7c201e337eabac6f73ce676b139a34c12a251bbc7d6453f0cc6afa946e2d3ed5ab26be5be5d4f392849c", "184ab2ff5c91478554a46707f8f4d9e09f1603ce2e370c9f3b040267910a67f7824c53df4bb5e31ac96366d5f6f86d0cac1fef0ffeac60e6ee817745f41e43c700e3a97e136051e260f95760dae1aeedf13d7c2c36f8ed9c6e14e47fc70400533b9a8849139f5e5eae6fb9b1158d1ba9611c8bfc79eb5debac7bb9acead7829ea4a9a5ed8396e1fe4d21193d25a39396d2efe406d3eb15da6b6aee0a5c304bd9a0373c0f4a91f8a11fcb43a0b472a8d15db5d10b27c633b3f6cbe8ad1b1ebd910eb7a5c08a530a897dfde64b8e381307706d2767a7c2276b82458a45bcc7af2c15f052522378162c8b72a4cba1860940713a60debbd384687b119e3fd06fdfdd9e5f7608504c86de22f73b469f78756a665e3f9996761f5cba9a301ad436ab12c6266bee6719910e9934eae1", .None}, + {.Sqr, "a6d3443d23252bd56d470d5f33964bb36d4fbab18daee7bf0a760a953e45b065940c00a79bc37bed32ad9dc943d9089cfda106641047dcc60f5c8e47cc5fa75a8f91b2596ca8e4c0f224083e91ce174822abce947ab1678895af740608fbe80afcb9e6e4c061e4cc3c5c0edd99d1e63223cd808850012bb996be58b76940d8970534fb21cdadb43c924f6dccb468e5de863dcc83e33c", "d8bed5b2b7053d60f4f71a33bec5228a6701a48634ee376bebffb04ff34165aa40c9db21e3ee377ea401281ac57fce1a25346d2c4d3969d913ad9b6633cea767c49846bbaffd5ccbde9962f108eff57d4c91f5be116e2b00a139122d0973a790103cf4038f7dd4edbab1249fc99d47cc28c593fd447df82133d63bb20022747057c56fc30ea0b0ee71cd2e9386d730764106fd1943b9", "6cb6aad8d88cad648f5dbd9d63e14f8ab460d0213c54bc9ecaa785c4b71f187094d3ff1c28be761ecbd7633a41dc28ebb5023d014b706d8c364d54bc3d19c054bf1c7082f25766d2c7f77f2436b1190f57e57a5df834ad99ea7bbdfd667ad61657122c35592098e1761eb5526091b7bb59402b31d91e2e899c3d856f157e42e6c4a12460660c472177d7247492485349036f60c4532862e960c00b537b9a36e43408bf528ae7ffd5b1813b6ca7a2c2b4e1122a2a3afcac4a30c1b039f9551c6bedba47e6aed6d99c0b2454ab862366c99649f4c251cdbbe9cf35c80b2fc608a6aa065190a78eb543c3162cacc9123060ff4655424c482b7254849829695ab51054480a86014369ca9d9325cc9fda7afa5c771836ef9a0c60c0bf6b149f58c8228bcc6b0ca02f90b1f91b7610", .None}, + {.Sqr, "-f2ebbc7de389c362ad0da0465b2eaf3b7f3411bfc547fb11431e5e0bf738bdd8a88e3e464b174828e92441a4cff5041bbdb32af9e848ca14708b5ae7beb971bbcbbecf56b773df2d3d100ecbea9978f5248da05cfc4b36ad974a6be69c55577762aeb4754e272610ef4a4fa82cbd3e57f79b75abdf1c3266fb7ad8165c9dfbc3d379c3f4bbb6db1b8645ceb813db7e352ec3f7338725", "6f2c03fb95e2ddd61c1db4a2934abc17400713e8d3ae6af1328d1a9407ded172d0aa8dd3be5ccf292dac9946ed87385c4c11f955ebc4b64b513444da3cd53b457cb8151b11cd01e82208a27071a33dfbcbf1f2bcbef582eb08d9118dfe121ad9f77b4fb88acc9d1727333b7283ba44f44ca56fbb99e6d18a4e4629c2735a6134fb3a602501717336ab5fa8af1cbb3baacd53c83d0454", "e68289719c19586d9c16d135fbe86221d74830f09cacf34c52ad7092dacca9d6f0c559719f9fd71411faa9caf34e86152bb6d57c514f03b25402f5fc4deb9000c0606fcfbbf2fc1f1f121df77ac5d246bef3767eae94245f1d6e9dc2a09cff91ed2b8a1d7e3d1c391a6b730b60c124b8b31a083504c46c7afd76383e6aee00c81afb9df2c054b4c30e9999e33ec958b92480640cf63facc270dbbea5dfc7b6463f386a97c88c0929fd7ba439637b28073c31e5de87f9e9de2f27cf15180e1bc91221b1314381031e97d597d636479deb93f3095d3b92e4c4edafebdfc4dcf415d0d48b5ad117700a2f7eea9b42201a911b84f7546f656e93fa0053e16ce47036f6c5a66c2de7249b2719b152deb9a994879b72fb6b2020dd695235c4b0c15c93b66ece856d17a78686160b59", .None}, + {.Sqr, "1d4b8df5ea2762d720cc3871b64eb87268fc14586fbca275247ba0809e05f7dfeb564d1f1f2675bcb7b746ae0b76705d924b59ce4310245a39cc25470a12c6271d40c4ae1d6e848506120f8686fb4715873046c34fc88ffdc5538095f958a06156892cb28ba63732fc0f8a4aa14a01eca86657989dab3dfa739c6562a5e46390e79c03d2e19984d2efe479de8aec7cea909400b8072a", "bdeb3cf136a45e04b1bee4f797fefb72cac1f8966a9a324311be9af1282ca7ae1175f02c64daed63db58fa33b40aeff35d4615924d0d0a32a3aa4a024d343c4660e4c624f8afe45a3e61683a7eddd75d2863bdfc58e5f4ed6d21f2011da78f87172674fae7e4b392e1ece04d3892a578e8d1325d34a1945dab847e28f1a5e1f510c8e20bcb3244444531fb38a5926f94788c91f52aa9", "35a347633dcefa20febad191eaab3b1330cb7badd84fa160fbb68020c6b7a7c869abc7908d7b689075d053d77d337ebbbb3beddad9557f1f5dc082a977432b46b5b838e24f7f01ff09eef162022f5f5512ccc58a4dc05cefe7f5b4cc318ba191bbf8d0a92496899940ccf5f6d302e36be3211ed1cdc8598e93de0968607f7714fe767a094464b1bf1c7daa294d50c01e3323485af005e4967995bdf4a15fb6f13df79fa73da4f33fb3f9e2863972025c55d806bfc5dd1ed54302fb886b8dc12eceb0a92bbb1187468de863a8b97d0426d0747705c993ec84b9ac2ace35c8c6f8663c9661fdfc686211246d1c304b53e0169052a6a649db20636e73fcd713f1f4c6a90773f96edb031e66559abdc528a337d63607870fca6306f6f1e10c29965dcc8eb2da5a00cda4c9352e4", .None}, + {.Sqr, "-72812abc5b093b2bbf37ad12345007b27ed762d43c5f7ca1048ee8cfad2d778169ee517d6fb3e43095a7e0341f105ad3e057668c78870c4d309193d78ed075964db2746f2225cbf83f6af278b7fbf9536bd06c58cf7f165b2d6278fa85b02decf66833563468c5ed3c474de042382d39f05445d94fd113c19c9d6add1527da523285017e2e3f8bf9577400b6baa82278a5e179834769", "1005131c5ff7e1e3912b3e02ba762a5b4a2ba8b565c287dd5b9c5ee5b844809c230932303b30acbeaa053f43ec39ede43397f8aaf3aaccf7a273d8d629c113ee631a4573681fa4cf3d099f74ee26ac7ece6725c4d47f94ff9eeeaef0b1a854346db33ece58a2422ee864afb7542dbf13a5c846b1e380fdaac29933d816cc2d975328357c40009342b0e73086b278a09bd47cc33de50d", "33374b3bda0a507575bd1fa6123263fc64b4c4907c7d1877f58bc08224605076289c163372019ad7f727f7dfb839e64c6753d5004bd05341414c9b91c5b43ec74938c3c8844e5b6b086db079c3fb6c24bb3d51fab1d6eef5d20353dfa3f0f553a4fbf3645e1ffec6c0da959dd8dfbb3d6b720c5f67bb858ca8455c6d3facfd0e575767def87f956e37ba538f08d4aa582369fd8b1a2ae376b80a3e7c210c096ed81efcf5c7618e26a69e8a2befa03fc7459bb685010c2bae9d32bfd3640c0424c48a8f6aeaef156a8fceba715d2349ad089037dd0775a9d7c62a1e1cf135a2bf744e2610fa8ade9cb730790218f26acd48717db58a6d9b8a865832e469dd84593156e5fe67a9ef5c3282bd2e905a5fb451a9e3e006708c98d1752b98ba667d3f9c838514e2ee3d656b616911", .None}, + {.Sqr, "-baad570a3d9cc9defaa238878111de7f2a5de3f50a34bcb4ad3867cb55cebc7117b2282f5fde3cae3ae2bf8f63240617d68992c93ec8a9df6de189009f8ab33a6b30c0ad0e5fdbf05c0da146fb7179937e9ed73690317bbcced0d05cfd5ec763b2c9be2c82eda30ce9f6b8ca833b55e1ec508050f32d4e7021d90388227261beb83a28bb94c33f143fbbec7fec66295d9980473e7417", "2e8fce69ac3eea34656f45c48fb8c9ead7b9a62f658f4096bb536596b043b0bf4e2bf624cbab9e5e62e1bb233b9b9811274254d715da8b3bae2382a194cf82525afee43f0ab1aaaf33cd09cafdea42863b89fb98cbfcf3575bcf746a04d263d09a8171ff5bff782e1053a9b5315c5e996b03b1df63870282e819a54e59f7d6e33c1f8d445895747375279e625a1ed5cd7f3a0f8559e1", "882057d9a2f7118a4bdbe566102d9a37983765973bea9116eb8daa548eca4c1b569300fd8e8e816954a8ca284867d5f1f4f423308dd56bb1761018e0724c86bc6e1364b3a56656027611a60f65608fc507f160168d2a44417436c54c72c359d878803e1b6440d9c9565d34007ba24d00b34a724fa2e2f27957105f78b901a844ae13199abf96709d8ca4453b9060a51d6f5258b5fb2b09fe2ce9bf4fc99cd991c57c73f4669471acc5f02d13cb510c6a58b1ddc1003c3fec2de0dc080aa85166408889c8242e0db32a861c316a79a5b68dcacb165f7610a4c2813188fdbdb5d07e40fd6fba0dad0f64f8f8fa8b348100cc20fa5f63bbc783ed1c2e553e0876979bc8399914c6f23c7b3dd5d61159d5bc4a666e92f11db94fec4ed954a8e4b4937cb14453afc148a131c8da11", .None}, + {.Sqr, "-48a6df763e0d9a6b285c4ed95288576f20f2c42bbd19715143f3b589ad34a6ef9cb621f247a11e6c6879b1b30174596abfdd260bd316527eb8f34087eb74bcd22a7715bdddf95202cd428649dc4237acbf9e188f9f78f709bd99d429d43d9b16f2c9a0fd6f13edbb76b8db2beaa7b99669a70252ce3c4e80dfc09e5bb0e2941e4fe4a73781cf0b82c68ac8acfad26aa97cd9efecd2fc", "82fcbb879ce1ebd6501b898f06bc15ca203c446145c7093b20eb17a6b1cfd446ce465e46fe483d51b1c3f5dd59571cba2eaf6309fc4c6fdff87019ede66591602107777bfff674aa7e15989dea2792446fdf49d82e93dd6f0aabf01ae4fd5d5083bff97d0a26f58fecc1191361f9a7edbe3728c5e1e261b7c64e8d952abc3a435cefc8d08d00df2c9d4a3980798d1c4ae9daf3b3929d", "149e4a79134f57398047e6af7a4ef11c9d1c461ebf5966d1baae83ea545f3e8fcbd4cd5098c43250edd1de1f658aa8f32d0e826f75d9b452f33d44a0aec0c1cfa24cc2a6594fd9f45f3db96d49687d66694ecd6c18ca1a05e909a2a6bdbe97bb513b63d5f3ce948841ba710fc995a18c468c5f9d88e4d0fc850e59e18148bc8a29d4ee7fc4652c3de6f3c3f548e2ee18d445610a451afc6e0c2cb6bffe0cb5a727393c8da9a28179d05a246aa269a1969eb6020174f21f1070ddcc4db669e8c29bd3e5bee5744f5f241140f5d654e9d54225af86c82407f853c38453149933a41aec87a0ed26a9a8b0889175ad882ddbca76fd0ccb12ee7b9c3acb3af0bcbd44c329bacf4d4b5e2b3b491f1a43f37c557f204711046081a798e0b8636fb90157fe9114cd4d75dc4036826810", .None}, + {.Sqr, "-f760921be163bf54ebede8abff70b3834c7af897cf9df465a8e8cceef5fc4c104e324970fa168deb614e7870a15c52a7c5f96b28eb9ec0eae2dce067f95f77109d9472a6da43149ebfe5ca5f18325720a784e5d85319b0414091de8256c0e60a04f2bd9f331f712a43c15375980f1897984b18bb9ecb5beef1e3eb842ec5da80e33f9d5f4bdb672a43814b2de9f8b8b09e29ba55b192", "2b69d8ede109e6cfcefb653153d2776dbc14d5d295b2249798bc7225fcb2709d2c33124c9c4ad07b29c3b681154e4b24466e701b2c217b725b90b43e94392d400b9ff511fe79e43424ce48f86ec7a44b3d9561583be4a54c77b197b46d37e6bfb859bffee4206319732e78dbc11141328282969332bb696fb96713fc9dfb01aa14f6a5ba2d3083cde1d018ee8ed89700d78834f451a9", "ef0b7e5fb53b562476adbfa05ae4d3cb6961f3e3a4b53a15329e36b8dae187730e025981df9a2547469809e5395fd0f23e553063dd8400e4742be982c8bb9d7cd703546b2fb440e942b8e4d903dbcd7435549b8ee9a33c469d6e81907046cec15db1782032610b60d410ed562caa206e9473e540c2ad849772f2d3391c9d85aced7c5e0722eb3b192873c40367fe8378677e25cb7b2c952140e5e9cfbf152ecea6a436a3a58c7b57c1671715a40cf22bad076481946cc9312843125e403ac15d8762e0701080f85a63027ea86842547c16e41a443b3fce4368f024cb1a0d089f0ae92e13453961155ef76873899451fe24b9e75d7ff74a32b50561bcdddbcb7b2250058b90360b7ff97d13a853fbda0c9c4430a5c2836db9c4efcf004e69dc8ed38abcc50703bb7b8e1f3744", .None}, + {.Sqr, "-3679b97a7477fb3b599cd32a72b9075d1084a2be72567abeee1829c56b9bdcb3810a4773b5b7c241716ee5272a0bf44a8009841cf4391bea284e89588196e64c7f354807e0618d051b3d24ea2fb44995276804e6d2dcc3a7d54b95c84384ceabf109f37060695c1233b327765686352941726290efa5d47b63c3e4f59a72ad860f8770387aae5893aab63cd9accd9a8874741b872c9", "68aa6154e9ff5c820a6c50dac2bc1e5008c5bdf0ec3fc83973b9a33d80469a52345e10eaf8cfba1c45194c1c3cefe3ab4365b63deda67870701a63804ea70ecd14e2a2c4f5ae9569bd64165862584c4500b63f8b0adb2017ffbd1035d60e2a865740006fe52edc78f36ad704282fa0ffda47fff44006db53e1ca4676f6c0c4f11aeb818ccbbbcf809b1e46a8cfb82713832c74c76103", "b9794208546ee51285d0f54ea23feefbb1c6cbc14cddb2aaee0d90f6a17e67296279000bb79e30950a2d0c86e173aabab06cb7e16000cd9e710afbe67b81f666c94e9e41f154ece4569ec9fae57c228db2d24fecd01a30ce9660563faf3cf1ee79659718359215d2d0c95f9b58c984cf3beeea231fb1b3c3df0a7f627e7547e096cb02c42b74dd4e5cc274e01d5b6f0aa3e5abbaca648646270b57e32a337b850f4fabdb7bab54449cf8fb18c0596457770965e367c18326506e3e65fb9b7df91b0a28bbc5518a960140422556f7c8bf733fad80868890bafe5b0710f2227c0841a2f626fec4aa08631c438358e7e7f16e625c0172f69e4b3e1434791ba031135046c84c0720f9ab47be30f38ad63eb3caed5624dbffa850fd307faeacfa09667f42d780ed8ad4667a1d1", .None}, + {.Sqr, "-bf80beccf5710eb7819fe0b0e61e73a1dd568e39fbb3dac9beba1ddc1269b910de8b3f73fa70b33291038b6e5b6e377cc5cbcd43f8f76df7662ca445ba0f9544a2d02bb9ae81277a30b3783c7549cb465a1fb0ae67fd2ac9e7bcff98469d87ecf80f5592ee3f72df62587973ef7fc96c29e5d96167e9849eee0d1a8917cd5c2d32aef0bdfc1338d9bf7c41c0c29ab9d0e0b53e21b4db", "3fb0e8e3bc33c656d19772d3bbc7d6c1ced2610bc1238d2c419cd0abb7ba65269efd0cc2ade60bc65de0883351064aa60532ed7427eefcd388f018ddef8b928f443da19d629f2f40911c0b7b2e4ea6d78d38c0c1e5e5ce5bca81aed898f15b2a7931591d521c6a010f6a7470df4b2b2e11e1816aacde3388c6869061bd088b7dc377b4929f3ffeaadbc081c71a48a3c99357fc376e6b", "8f415d75316905707447a221cd91477223bb97e3603d81efaf3be974643717de83ebc9023b7a8588298866cbcd2be48ec09714318d2d3f0807d62b12307465dca910eecdbed80d8990e098a3d26ea1964e53996ebf11e7fa62d91f65ea78d01c9e082a5266b35059b888e12928bd98d6226644185c0492e985f8eecc7c92a343e671e6019ffb8e45f6cb89304b050b4751e4bbf7406ffe8c528572209cb8e09ad72b230eac40c9988bf12ab47ac2bdde8b4704ccc0aac128e6dab8a39e2e60377fcbde6cf11cc863ed745e2d40238f31b50e048c1f8b8a8d00c29d3b784a3fceb102bd10a7f01bf88141f51216bbe8015438f936fa1307e13d13201e9a5e30796168205059010576eda41140ba3d5cbc563b4e200e95c55a3ee9e1a2abf6e9fc34b8deb2511d55b8343ab359", .None}, + {.Sqr, "248427639d1c8aef838cad0d31d93413ba6d2237745cbb2eda0166f4d2fc792296afac2bb97dab826d702cedf9f16b32b190316c32f85d2d29de2b0c601e6da97e2f207e55d83d0d1c6a310add83d8eb396cde970629668829bf3a63cc461b576137724250d4699092625931703796089c4c5863e133cb95861b7e52da4edbe64fb99a87977ee777ac714639afb4a72f27c4eb49c580", "4517e01c899380be8ee27fd04d202f196993886e7c1642f0f3669d77aa33b9c87bd647d6efc0898daaf25c14cd0fbd4b11f76f76678ca98ef14000614c941a8567a6cd9a9d463a50b2de9c0c731756d30d59757ba7e7c9278652f282b75c89bf6acfa8a8bef88ca4c370d5c2c2498e0c83f1bd8bc22ec38507938071d8745d2c08f3e0f046126f4f3ac39c7f1e9352d826c3df8cf586", "5356f4ca8f98d243ad3aeab3e4ec8fa95812c6865dc3d34886d8c833958b072bf606795269318286bdd980eb6d36056ed53b5e58b0b16730e966bd7d106c9a7c9f66b18059d04aad51368dc6b7ad498a7b9dd773ce938ad617a839b0f2d4057506e08024e1fbd129c8f5e68793ddcb9b65bc022dc49d563ec66145a1295b4d9037d0d2a6fc039c8a440ec00a5b66b3dc06c79a8a21cfd1805b385a8a6b373f8003b809b015a78bad9e2935d34d39bebec3a980760b066d6defce1538306452e80b6bbc2ba184e553686d3a3f725b0198d614f745023b9c172db2fe051d0417b7c8eda82f022a7e4302c8c8fdc0a5a0aad38cc199acaf7e73a16f0862a2508603009625e6beeaef6b74a791f2e7f3230b25d4e248094ceaac1d7bbd2dbbf2f083a38f7ed2063f1db3b5e4000", .None}, + {.Sqr, "484fd65cd325d938fbed6eb291f145d8d7b3761be2b524e3cfaba3512dccafb9425faace0c36a700e67cb1c81e612729f30ed8f1fe144e6acd61ae02c71eb7aafce0614ce00d9379039449dbf3ad8d2d7468f0c93a56f3e106377756870aec84c037279cbb2fcb32e564c9ce8d1ab86c6a12d954563ad8a1b16a6fe2e2ade5d4d8c6f4e0c816e4f4d7f5b24b3f5092c67ee1350ed81a", "4a2528ca87bcae102f48d3e6039ad1a9df4a7fe39ed24b2eb041dd51eae4ddb9094d39035fbe23d4157952899adc8bcffb177d95fc7f04072eff0d8e8479ad29680871f380ada533ff39ab79be32f346dfbd6bf5e6b6efc2134173cccd2391615928fcc7050279fdf66b845c69f3a935b2c356d10afb968d011f9b969dc40d3eada367c2a1a34d095181087db3e2948e1fa1033f6715", "146d017a378eee37d767daa13e1bc56f6d0355627e16f86a97072bc4ef2f09a407ba04df07f7f0a97b6df6eb89715b88d26c234b334344214392116c105847cc9b6ebd2e689deef5146e278e016a794fed820e73e9e9f9570a284b04f97f9f5236d4ab364cc1f294339c55b6a7eee38f6cc2151290e27b1f7900f08d6ff4dc761c0a863d2fc7f41e0f6c5643e301ee0707ded19e39770f4c9097e55cccfa54258827c0abd2beb582275bc17ebf263a5f17bcb201f98ed179c860d150fbc06b4b008748113156f4e8c64067cf8b3d3c1317a76495f0284de38202f159d505a40055f19c9b4e138da7498dc4f0f2cf2093dbf34ad133eeecb7db22d6de9024c6c02913faf336988a0410a492511f2e3951b963422ba1e79d0f9f8d463a075c307aa2a5540cdc089c0b1d43e2a4", .None}, + {.Sqr, "485f1f180ac4d560e0ef1b0336322b0764ff4a4659d6b2948ac81e77dbceb3cf9025f7c586c42a1231d29b5c02a66c7b2f49c2639cdb75470b200d18f51446f2bce7b4ba3dc0ab9ae45ba4d099fcff122c480f5a191f7c15c5e57550ef800d3b0d8eda9efff10d4b6d6dfdc92b0b10aad2913aaae743eff6110539bab328b538521e8d39c65f6578cec6a891c724f6fd89e3c1e48ce9", "2db5514cbbaeffa1137a049d1a676e4eda462d64fe8de7ed78448224ea08db4df0385c81a0314b14f9a1eeba40fd09c609ee311fd782da07ca313ac1edc5c7ec6c9374c1aeb4aee7a530bfe898b72b416652b504bcb5bf806be386070898a167c6cb3af108206409552f5a3b683d1effd53a085520d21b24cd8c618942fbfda8c1d6cc0950125a547be21929bd18f54fc57090166279", "1475a4d59dad8afa8d76e14ef003c05f61323c7920bc3f84e9e7403632f2189e8400052f2ea4840a901fe22dfa2b438a9e5fd213dcd8e7d6f2606807eed3a3596a3df4866e8366db10d9fd9b756a646ff9068ece0808244535505737eada78d9159f390db63bab1ec7cf74f6409d3cc301f605b2cd18191a5655ffb13176b64e3bddf26920c3e878ab394f869d0ddb0780b31dc028a87df4aa5d16b1089e401a123914d986205ba626d9d8e805621606b7e457b636a6af7b520c4acffdcf1bbdf46ea863add1989047640d55f646f9abf7738fdefad29387ae3b5f19a13055b50596c55080cfca1789a840f161e9496586209cd7f5644bc86976e5d17804aaf669268aff7238c5f43b2497c1e1df77bcb1afbf3472cbdc23a8f204436939b1e0da61ec3e5d87afb89e97ac11", .None}, + {.Sqr, "-b624e3592cc6124faef08b74e27c847430446b0c4d50a2934000156ee36d5ffcbfd766428735d5855edef437967382e4d16a24cd21071146a9c99f293b3a3ef6e14217caadd39d0f418d5ef82ad4878c8f50b9fe9b15d680fcdef02bef76b6a09f97cd406935d6ec5fb0c224b7653f2d0a5dc01224d61fc2b21dbf82a87a9e201d963907030a0b0805b3596eb2411486683b143000d8", "549ea14d7b7db77c281d8f93329d1b2fe37a5790668f433b8988463a7fa639175ab1c8fbacb674c521890978ba8dfdad6a32f15c2c0eecf2edacaef61e987d87a85be9eeb695c9362ba1af0744c56ed416b223eef540e99cc7ad04c8db64f08577d6e6984d181316eccc4162d65ac0750401d06d82f813103f758ffaa68b73543a01f0ae6f368382081abaa562ef8a0dfd89eef8bc26", "8198789386a57e35e12df5235e2f99b7ed108991499cfb7aa2353768b5c3a625a58d79413b1a1f865373f6fdf639943cdfcc217076c063e7e18015f61be6ff11fa1b070b9b2f55c019ca818414a07c8a27793add01a1f4cda9183d72516b23578eea05c77a7735f275c770c266015a5b166f0091092e33561cb27e0cb7293a0be0bfb2b1afcfa67be6bcaed5b99407323212aeeed201e151b3182f636ee58c7f1bcfdba25426e54d3260f80c43bf9f1fd6046451e9220b62868aca1831aa70845a2460d2630677f91aea8d2bc46b04cf7bb9c414526d08040ae597acb3929474d638383571973b0faf91c869efcaa396b182293fe2411ec8922e594d4b5fe60ad969f748a089373d164e9a52eb0ac936fb98296f6072be31675c3e6bb650b4d46e9d7e1bf2876cb21100b640", .None}, + {.Sqr, "-85f0f0778bc2a1c9c9e2ba934d41e88340c7ff3e0cbd5ac62c3937e6e60861a87283bb600fe13a51aef5644443cf88b902680f6842124041a34394936dc8eefb287d8d5dbd51487ce6a3a2fcb2ab9b65380a25e4927fca2fafcff9e0ebe433c6c4ac448a983cd0ef8abd920eb526ca8d17f8c9fabe8d2d6c39ea880270e4cda901670f5245ff477ac777dbffd595bcbc1dcd55bab1fa", "7c01d980d504da703938ac89a465caea4b7ac2c253383a882b034f1513f514137cc64f2c99c4a8d56804b4b58599bc6939e91f250448694c831f56e5f0eb1f11e0dcd2c7de849d9aba2df9ab2691337bed127a92c200ba0a889d61369dd5190e21db586188b22ab5a4eb2450903555e53be422c3d8b52c09abac53d1fb738f7d62fbec2e18de2237955f6deadff5d49a989f610b14a9", "46143c9ff93ea6eb30b9d2c86e669e364fb8485ab0b42354bf19093210d065dea53d0191eacd1f1c48c2184aaf909d58f219391f77b19a8b3b32690ee7933976133110c749539c77b46c60baee1e8770fcffbf74c0d5dc0f44258fbe3ebb908f12940236f94ec0a89619186913c917213d707a6b28c042e5ef56e686e04cd6e946223bc2b3f9a4e52d06c3f25137addde8d7cd8cde51f4563f7fe73de0af0734dec6054c591be52c83ae3a530e76bc71a8c6242fe499e2392851abf8accbdf7c3ab92e86f133b4e2ec91a2e910ae15477ca857c34408e38212f6383cd23dc8f301fee7e1217f61c090f0cafd7c49fbb60f119c395b6a4da458be1f545dcdfb641d8accc971c6060aae26c2a5ad1ae5b5cabde143047d56785bede64b3a01908c22817abf4d3930bb1f03a824", .None}, + {.Log, "362e8cce31ebcf0b92e69c330db066a38cd732999b0b8dcfda9a99c921e37742d1b241c5465d275686f719dcd9c83cdd0a5da6b7520eb86a30dc0cd44f4d19ff9e831187b84a30bcb14eb2ab0be7053d14d8b054b0e58faa761a6cf7c45fd7d3c7985d6435630dac305ca7ee7861ba925c83e6d8560b9dec49cffe8d8aa1494032add64d8a27e040be301f9eb3b2a18b18910bf2f073", "d911edc60028fbd", "14", .None}, + {.Log, "2c8cc523fb2f5738ef6d7804c41dd6c131c043b15f2cbc084a8217a9af4c29b0ad69833733c9f90482ed4d31ce2df90f1e0eb2cd396d921c7ec82728cdb2215661f536f54b7761e684d6ed7d0aa79b1d9367a8a08cdd397674e5cc5d943f701ba89dea3536b37e7f8ff27d0e28e7371fac5d8ce03fa0bd3527fa8955bbe4f6aa7bbfcbb63d83c63c28eafecbc1b25343958a315e76d9", "123a8eaa9f84538", "15", .None}, + {.Log, "affa59b596323e1a3bfa3f18eb6dbdbf1dd3a89e0a77dab81ed390e86da329ab91582a07955b0f882ddf10ac59e116c60ae9a9eda1c2c2693b82cdb9c3dbe4a8f37a7f3e43d838f503f653bbabccf7006957b7d18c79a712075352426735c9a927ea89f6cba016a92bc05a4e8dcb7f57b241a3e6e23b38dfe0b999fed37da9da56adf8c740281a05d7d41f25b3e5e005bc6093882b36", "ee95780f1cdad96", "14", .None}, + {.Log, "4fc95d596e7b4979e7b4e5af98c9bf95e3a05322d36c6c6005ef6b0b08538f4ab9f3754f71de963f4ae481cebc5eefc824dbdb63b81d7d9ba723f876dcd495cfebf90825c2122cbb6519e513e3eda1a7c88bf672f3ed00534f9ff25131e8cc139081d3169a05f9acd6015463042558e3a49e635d579b2703096e0b1830a3344125ad6149964770d07c4de25929ef6e6f18ad2770df4c", "28384cabd2604d6", "14", .None}, + {.Log, "c6c398dd333b8ade80b6f2de0644b798a1d1d88467aa88f788544e8509c12f8a8e1ed39d059ba3757e8339bb538d5e40dec6b8447ef3b6aa90295e415245cde2a411d638eb480fd06195e8f4f73993b50bbe2ea04f326e698f366f1fb38631c1111701f660cff86db4050bdd4091eba7f724777aba294d145df53ac129c739520187ef295626cd173f2640f0dd86360811c3514097aa", "fd0f7f44f350557", "13", .None}, + {.Log, "ddacff76d522227e1370e0d850a24fcc015350e42100effc8e5ad0e6d6fc18652eed3b5d69dfac14cd627fbf051f438e51d7006fbfa08e0b72d06edc28bfc1575e89486dffc8858494fe24195e471f97709f30c9be7a6c83e5a67ea2770dd9666312f62b6bb115bb3b0e8e74839055beba60f2fa21ba9b1a2eb9597838b6e46eaca0ee404373ab0045f361d6ac093cf0ed843506b369", "c480c460682aaec", "14", .None}, + {.Log, "7f96274d6d68095da832036cdb7ea69b493ed21a8193fa7879984d0282152bc162af01fcfde995a38b50b53f607c612081938df510a7fba5f2f2432bec0008598e48655248f8e9606c2af8632093ea4c89ecc830a142127ff5320d89d115e8aef3f0f4bee312c4bd2c867435aa36bd4def544f4f46db4c8215c0ec2f734c617702b78ee10415c2df03c4ee6bb7f1c49b149fd121c15b", "768a337250e7310", "14", .None}, + {.Log, "4f4238d8abab35218031fb7c3860399c4dfe2ffdca1d201c869f2e614ea62a2c7fc94e4c17e0e76f1521ffe5fe51ab36211b98d9966c3e5a4a9f0de13dec925a238a43e766f5c56d947d8d65c5959881059c6021aac3e20fe1c61b7ef25b9d29b66507df92001e523f1b4b3c2447106cb0aa7baf54abad58bb4549fbef6344880aaf8a91e1ae9ceae056fd142e2dc4435df86148ef49", "89aab7890312729", "14", .None}, + {.Log, "6fa87cf2af8a85592ec271dc73163764c8a777320e2c4f09e0b3ade6d1ee1886300fab8083c0e2d18032b32bfc4f20a0deed99f58b0160272a01bbd60507f0d7c8dcfd801274c0f9113a58dbbc572063d32ff4380962515ea79c7043345f1a579f13f319b130cf12e4fe01283942321ee97b7c2d3e743395e3e5b531b4d5daa6580bda094114c876b02d98301da8ca8654c082cf2eca", "7b4b533c89b4a26", "14", .None}, + {.Log, "5371fdbd51d95020da167fa9d4efae24792328bd8ea7c0624fcc59e89bcd3bcb44361ca87f3f7c4e4cda1c16647ff92c9590abdc4edefb43990040d2eb9d7cb3374a69ae2d002ec5cb2bafcd088a4faa71f805903a7fe29d43c119aad7a33276cfc32eef9333bc595c7e890cc345a6ec59fb0299ee21f4fbe3a20ac76d89927415556dd54e6ced21a1c8481bee79b3a741f5bbb63a33", "1226c4979224512", "15", .None}, + {.Log, "8bea45f6988146925b49861fb4fea66c012a0ecd023b4fe998e906542e0437172a2b29119819223f91a1505d20351bb76eb0cf35780f4a9d5c533f6e671934c43e92c5b366953d8848f0c37e5ea4a9d362fd045a4e023afbd199c67eea7322d673038de80763f8b2e3b5e05c38b228c4ee5b83c55f463a3b01ce8f19ec66dd5ca1f1eac337b2be4f2bdd34bd95dd88d29a07856ee9b8", "dcedc272e55af60", "14", .None}, + {.Log, "8116de1ae69f519fe45e6fbfe69b3c59d4148cb2250ddcae8dcce411fd4cd5ca706a6dcf9175240dc303eb48e3b251638de3aee5fee2d30f75983c761799f7d641e36ad7b7fb3e488c5a5362d0b16ae7a37ad6203362b8bd7678ac647c60863e0f22b91d91989f3e8ab0756768e9234a525b6ee23e30cc49719fbe95264f53f5fd521823fef33bb35741a4951af732493009cfc1ec62", "5c309576349210", "15", .None}, + {.Log, "a481db0c826a23935022e7bc85acbc4745af3302dc551b7cebde5d155fb86dd3e8c57e506b2b42ae50ab208b90268359ef9ee97a4bbb37a8feba2e39334d7cd1b482a30301665fc2b50881ce776ae7b10a6766ee867c3b401b1533abbbd64ea689aedbe5357c1701b0c875ef8904da179373783f3d627c3b806908fc7cb455fe6a6205bda6f5616331fb748e2aafb9e912136eac5635", "8849843b311ea76", "14", .None}, + {.Log, "6d91ab7ba85e51f56ed4b5154fcfb419fe0135c736305f11b86568f0b9887d56ca26ee5b14438cb137030f6d085acca567c79a390495d39dc1baad8d153eb5888fe877f4aefa732d36d023d0d6524a1c0a6e510612a9958a8e0e488bb2a2e49511d12b90589893247e11fe355a3ca3f843d538e82c13500e6889739277b40d5b629c44dde2f239dbe018f586949624129a4603501f5c", "5d66c3566b4c15c", "14", .None}, + {.Log, "443bc23cb557718d9128854e8fd65bcccc7515a54388f7bebe5d6cf3b02bcf6b9be5aab53f681d5f78ae717c572739c847750b512617654667ebdcc3b5ff52cabc7370531e6bd6c411ae33ff71fe3381d5d3059acb447a227a708672f2fce59bc9c682cd96e7b891d5fad08d77c1ebd4b54fd9d48fdec22b8cf6ef95204ab214e730f727567c76f328b767566ca6d63dd9ce501db43c", "c43e11283381a28", "14", .None}, + {.Log, "d49ebbe08d95a1ea0fbbeca5359b084b92e737e880ad005f2d5b58d1057f93aded785ebb639101aa77ca0bff68b9792242d8f037e78bcdd2d988d1d563522d74470a2c47e0a0bdaa47d847dafcb8dd77431b157e587cd3299e9704c350520b80d1136af24c267fef7eaf7587551dcc1260424532fe5c2ffe286ffc99ea455c2a2cf1317aac0d3124547b4fe289bdfec84eeba10420b3", "f3852f0dd5e81e4", "14", .None}, + {.Log, "7372e45d8218688d70d5d40bd10fdd145cae21652b9f68bfe107d452d2bea769310d117127bb9630705454291191ab11a18207d70502a43926f8c4d1b522c9958b4e540f7d82686e7eff8855e76c7112f8c0bc19c7252eed9fe6beefe17a1d93c9f9322735e520cdc9709a8535ef6962cf32cc2737c32fb89ccd3ab2c283e05634a7dfd42688083d0cb2744609bb7d38381ebe32ead7", "fd4308a9a1965a1", "13", .None}, + {.Log, "6b228652f5dc8db119c97889f3c01b02ea27fb5792b70d3ce2acf3f3133744998e1f9d88eb85dfb8dbcd0dc79bff38d99509901aaaeb813fc02da9c3a42f2b0b15561c3680943f6087f623b64fd255af69ffb74b5f41746bc93db69034f395a2e098ee4c558b2a88821a64a711d4d404d173297508dbac00d070872172a4f7145704223cce2c28c870950db2849756e4b4618c65089c", "371107fc6497cbe", "14", .None}, + {.Log, "82112120324a6f848ab3542439392a95817176385362116ad178c9a528e30768866c74ecaa6230c1b4d5c557ef66e5939064d97b588b2e4310f87ea7050984f8af94c795aa1af2ebd75665ea2469961f6aea80eafbb80a76672e3f847cd425f227a57465423004417a3f5e9bf979d7c2b019c628bd7862166c487411a3996ed633b6371c9e75c69ae8e978bfa568d1491bbe962af781", "a1bfa3163b3a13d", "14", .None}, + {.Log, "59e34de2b7312d5a5fd1ca72c00e4f4e2c8abc50ce4c1cc41643614f53dc18f180a6b7ef58ce604af4500c0c55e42902b3d23068f173fcacdd9d4fc7ba44f4740d115e918a0d3d08dd62ef867da6758982d56f5e10b0eb7fbc900d50bce928f545ee03b98a0e3634db3b2200bebf17bf8e6b9b595efa0cc8592b8825bc9025e06a8c7551aeb4888fdad5b52524490f642683537a0186", "26f58159e496778", "14", .None}, + {.Log, "bea2397236a4ce2c397e83892fee75b4cc5c10ce14e9c919c67fdeba13f7f56d5702d2e2d66b2378a0b4b5a992c574acefb51c79de9473c990aeb8f5dcc60d9438670533c60a7e69e47b7bcae896b5e8f970ef78ba7315999b44e43aa366896daad8c6cdabe74782650f0b2d091f047c280257cfe90a475b0d0f29df89a58ac9c113f2916e00141bbabfa6c026347cc42404de815ee9", "af398d29553801c", "14", .None}, + {.Log, "7d893e38959cda15ecfb4ec0e975f504794f60bb5585ce18e9d172123feb965113382d03d3322e276806843c4aa94f470f6ec63e1f03149163fa59cc5b7774dda38fdb8726f853f9db76de31ac3ff29eddaed72514a62488fa9b247cab2df688043336dbbdc8c5a8f6c3bcb903a58bf8c0d2813e09cc1b7805ef81e803578be045b617960b1267b92a44df940ace8eaae009eedd997c", "e6f0990527fbcd0", "14", .None}, + {.Log, "a791a94a3dc869327d76c2695cb6178de97f2deefdc99f3f2c876b0696c01c6f428223993c53236018f685d4bab1c74e460108a154a886b7cb9bf87771d2a5b15224e5e1346c8f9ffe17f141aa93971bdc4206457e063630b40b557273106247fcceccac393132d11b34d5539ef87008d44babb9f74a422e5d4df2ad9cc79740c341a0d19e83b8453bd915676ed2f96207e6ba1d93fd", "479c58e2c723a4", "16", .None}, + {.Log, "94cd2f0225136aceb9ee05a16fa224f9f6e8729794a4486def97239a31ba8000625f3e9fa165a5d6415c514994916929cbb63cb6e55c0e0f0eeca935b24900ab209f4dc5c6b49f48b9d10f629452a3dbe97e48866247ff4650030e5e3eb718ef657c4722fb5ac6b0a08917e08679bad633606bdb18f2ada3ceef5e0ecfdce42964a7dee7e1bab922f4ffb85d08c05cd0514d89059812", "b1426f4562716e5", "14", .None}, + {.Log, "1f5b3cba20f74a081a8d59e7100fa476bba1b951bde5f710ed5c1a5edb028ad724361d22be1a0895980c05e2fdf9052c5192739a6c159c86b3f7660cd8a2f65c359e1644a68e9ea10a9fe8eda157cf6f6df5a65339e3659b4a9d2f3a1c3f8a6679443bbd1530de7172e36373a195f284af466e6e80108522a06c48f23d3ea4c05f35363921cb11b41e58a80f8950bc427ce9095691b", "aec0d4073ef1d42", "14", .None}, + {.Log, "f5ac3399d2eec09724db2c19eedd12393abae23032e4aaa03e2e8744ad46d605ee2c4679558d2c76191ea04a396a95fa54469b56658fe42753d025f210fe9c8bf77957ddbdae45cdf9332c0f36fb4933f75d8a44072b0c94573ff2c1bdc2bcaeef8ec55de63e3e8e2b66788fc15cf2abc8bc12383db1df66e8921c316a8da6862812106715bb58a31a6c781997efa78b2229e77d2edd", "3c8836fb10be129", "14", .None}, + {.Log, "77b35a7e6238f542a32de2305b9db77fde667bca9d514ca8a7e3f52ab201d9923f128b81cf9b0c17d37167b1b2a8a096ad572c820dec7e74497a58da0dd5bf7937361bf1d4e62627c03162c7afd1c53f1807a27a9385d049390c72e2bda4ab7e6f663b427d0cb5dbf288c2077af8f2b5b13b46fe233b3f515264e6c21f3d7568ad72e400e11c824bf657b5d2fa940230737c2fd041f9", "f23fa09283c2219", "14", .None}, + {.Log, "6e074bd0fdd7000f9244c7a84377894eaecf08e87b4dd195af10e32dd1e9170597036e5b59f2c95cf2b83bb1c143f42a57793941f8135ad726557fac3daab3c016366661e2683c33a5fba8cd0aa8805e0c2f6f1d10bdc6b69a61de0976b74ddc9cebe279ea972dd9547de54771791a9c7ee308c7807c314a0dc627836ba062da28d7a672125b9fed373cf2dcfb6330e150aa864c598b", "c76b83a80040378", "14", .None}, + {.Log, "2f215de75baed70506781bff76033a1b5d8dc0415c2395ec0dcce6fdb76d18df4ec9dd0281426c3571bf9d647180ef4789459bb8149b595f33d1e946767851dd6dc60f17f18161abb2f5f8e6086d4f14a71eee31be4686b69d5450e565f5b7f7512af2de208bcd5bb8287fe687e36875d9d3c04f01be8bce892deb03c4c6e6ccd4e7ad5f782af44cd0e12778138d5bccfa50890f1ce3", "4e32b3f91b554c4", "14", .None}, + {.Log, "517b0c89f9c6fe1b3bfb560059e711441bfef41558f2069310077e381a7ba36d7421f0c667fb42591ef7a30591b5de902815b9c5d8e54c91ab42b06ac3b84b22b5d70307bccbe4aabbe0b136317928cb4dd4e39058bd5df0a0f102844fee4d75ccb797e4b3e10d01e957c8cd69dc4c17c38343341d949c263728f5e68e7979a39e462ef52bb6c84e7226ac2cff47c2cb453cc0eefeb4", "3983bda3e7c2df7", "14", .None}, + {.Log, "b504682cadd27e5d54d54f6feba0c6efceb0fb977e459487db9f4ed80460b80ab38896a2fc4317eaf52075bc0c87f9dde5d61f2224cd756ffc5945a36926ba8eb1043fa4daead29dfdea76966470a7129fd150d33d9a57630f3e38ed65f173f30af52fb6090d0f1a37ac0ec316c9f19a0f5d361286361df7ee3bef207dc88b365681baebc727b76a9ab594c80f49ad73a39d6cb87808", "fc95736693cf14c", "13", .None}, + {.Log, "a6e5cd05a734e887d48803a8da2041ff41b229142b29558a5fa73f76cd3f42bb3498feca67f34a7b4b4569554a22fc91748112b88d16a26013d04821d19850d09b8bd6f126b51cc7d4f5b584e88c1c8dfb2e455687d85fc0f97dc39ef6bb7c3f1fe50ed7c7ff3bd616d629895e774142caf2c6abf888e822214263fe935dbce415cdce87f435e3943e585343d0447f0a62310e544348", "97ebe32436f4de8", "14", .None}, + {.Log, "138a27cc0a0b48af26f7f8f1681ec927cb9b97d989b0144edd8283bb61e178ecd31fdd4ec019791fd6da83f12286e458c2a5e96f504ee73facb2c1aeab84b669a18a605ff4a6ce1db1cd4e763b13f3084597be5e63e7651fa03c0fc9e58206e70e36df0845094308830a0d8914c02152233f3f9cb12d90e71f76d07c52d363ab7ac7739d22b379cdc124dd726e950103f24f71a475ac", "c6616f50c45a94e", "14", .None}, + {.Log, "df4550b359e8abbb89885341583a21e5a8a297111f7b59e26474ba1138d2d4fa38961755185dc38efcbc162c5ee63bca064a0ae4a1c1bba59e81272edc88c720a59fef19f43c7328c3d1cfb1328b231e35602f00899f78713113feab2195a9d7df704fd437c29742ecaf61f72d6dbd69bbbedee44278bb1f01d3f79e565bb7057aaec3fc0e0d949875a9e57fb47174139b45ce765728", "f3caf8a66583e96", "14", .None}, + {.Log, "18f0c4fbca4f33b322f83eb8f5a5b5cc72248fba512638d4ff5eec3ba65b64fc2548f8e4e8c783c80d1281bc9c0a811178f2f317caabe68d5b304bd2ee3666f18b2353f938bf77efe014b7d20f42c83eb9a87a7b602bc39f77be3200c5df5d23d0df84ea964a9f035a8f16093b85afad1106ec8a5a4cc43d8d793245ad69033c7008357c2d74f6cccb8945365d2ad277a2207e8236eb", "c5fee97da0c6ee4", "14", .None}, + {.Log, "a208e433fe7913dd07ff925bd057993276049ca56cf57244b04d3df3600f5fc95fe070486174e5f93050dd361038085bdddfe2025345b14f6e964678f8c3efe60545272f3561e12c448812a37f30ac55832e97707f958ade478912470b77ea17149cddecea4414625d4038b8c8e4db915992f3e9e9ac4c0f6373cc834cee5c5e50d3e5b4024331158c78c369f6a000c7fa120d50da6", "d57f26f6c2a30e7", "14", .None}, + {.Log, "885237a8372b1be40500e2f980ceaab295852630a4b48f53593099295f2e2484a7e13781d8ff324473b55561613a4d262b6176a7a015aef493817f2276145a3eec0fd20e2e64524b0b6fe3956d9f5bf68f767dcb1175c304879cf4332b8f1e9f9bd64d3076bfaef6e1dd08ac54f0e321c08926399cbdca54f829d9f8c9753b84be98ba91316157d943d5be3c03b1425161d77bd22552", "1cb320fd1659418", "15", .None}, + {.Log, "4721724b9818a8da9ae45263cf0f58c5fe57327ad2fea0f3ba76a27d958c8245617ad1d72980b6454053e80992c7de88a05909cc15da0924fda55bac7a47481b1e387d80986c06d25f1cd39bc14a3ba227ad44cbcd1db23ab77c1ff3483b5a90bcd8d3c350921123a81abea669a1d8ecc71e06577e36834dcd58553b422840259122776d9037bfef77a87ead7ae107f7c62ac706e17", "dd4efeb3db66961", "13", .None}, + {.Log, "dde2a2c0d5c69b862354cbbccaaf43c30c8378a8150a3c39ed539647fa47fe7deac846a06d9501de0b9ca3c442535eaf44583472f9715e6ec2b5f39bd1c15fee375f28bee76fed41f6c74f3b19d1ac8d3e69aff045064f28a290b227639a0cff3f53cd7e6a20eacb24e55914a5221b73ed4a5b9aa73b8a60625acff1c0e29f4857f1f735664a0b5b39151841d5ce2560471feed73b65", "dd9b8c7e2aca240", "14", .None}, + {.Log, "812d4ee1f782dcbe38d18920cf8d50a6417be44ffe59cb015cd09708a9587286db79bbf67e440b425097f7eea5c8a69de5052ed510a473b363d568982e1612aae26030e8efd4b7fd914ad9a3ccca7bf3957c6f738938c4349ec94f8a6ba92104ebb808ddbd104696a9bb9762cd106f8d9bc84c500e2fb0998016125071d763e31a9679081e1dc0bd4c65b48ef21fe90e16cc70240fe8", "9dd4cbe49400502", "14", .None}, + {.Log, "6ca55b0676e69f12a16b112a10e4b3eee5249a2d1764348e297e806deb9028cb512945d2a35174cd5fb19db4c601efce99e6f5d46299684bec2b7d39fe7d2b7a6da5ca962c326c590955216b08599c274bdee5f354f3a08c0fe78022868438ceaa6e38506d8b1cbda021dcb0c91df44cd7dd3d0b368332f97b6610055616ae9fc0910b4d8478989ce5eab5d3bf0c182f080be4d51c34", "9730a826bb74fa4", "14", .None}, + {.Log, "5d1a39dbbf44f47622de5fb42b3a965421307bdfd10492d12acc797bd7414a5b6f55a09a4b4ff8d38a8d6e96e70da7fb005298e8bf7eac42205a6dc19bdd678ad769e78460b7ad8b323ed50def8dc37976d337bbae886bacc40383ebcc07697828575a2ea72d1a941af86479e7ab88cdcc876d7a58b09fff14006859d82956cac73e1ae86ba382e1c24a0257816200987fcf5f728a4b", "89573134d14918d", "14", .None}, + {.Log, "b20f7a4d032d98b69adf63f0ea87c343d1b971ff5980cd64db7b9481ddec80335547b9c6cc869f200bb5ab6974f819c460fce845ffcc817dfd676cd35484a016753ca4ec8b812816c0d57601b831b5869e8b3f6d9ac7fa1b32ab325ba298d0036c7f21a996502c99736f2aca8567572ca361a4f6c3668a810ff8b6d3bacb6fc75534d98ff1a87c3b5d8a8478e476e35f1d0695e0b75d", "1edcfd8f587746a", "15", .None}, + {.Log, "38c597cce212a3c488fa4071b15c963be80d3193c2c6bf199a2e857035b6731b0e491f1dbd937102bd84b844a9b719cdc0d7d487ee7c4f8451e28346cdfc037810e27580ba7c0bb4b5280e590a6946763fe00d7ad66b93eb6be094d63798b38b39ff88a8ec7c971067faac9ef2ea161e636904aa655b03e5d167df8d77ebb307acd7cea37e818b73370dd319f08ba00386dee5be12af", "9c22e1d25840ec", "15", .None}, + {.Log, "b1e3029f05149dff18a91afeca82a8e8aef0b04673dd33ce229ce3984f3254ebc5340a79aea12619bbd3bd8fb217b3c05550e70efcc1e6727015f1867a8b1c46df99f109725a9cc9b69c62c3364578b00c9ee7975e41355cc66a6b7cc9d81afd46feede746e4161302747a0e648e7053720588a68541d68aae07fca8615c0cf738e15d5fe4b9776290948e13f2b6cd605629d5e956f9", "7a78ed230a70cf1", "14", .None}, + {.Log, "4e5975c3bfd94570be54976951e42769070e9e4e8d6511e6c74c7e6c4fcc943130aafd4ec14f761cb1081b9ae7365f721383a2ac0b5d617af3ebf5aa288c52d0533b8ea097c6debd3b1028f2310134b4fda929db3219a2b494c615e82caa27b4e2e58c5d46883c30b7926d274a97988e90ebc92b1ccb524c337a38cef1a191c5b134a6e6e97785b5ffeef2ab49261c98ca6ca5d08b16", "fbc6db6c4aefce2", "13", .None}, + {.Log, "f37a53eee2f146ded13b82c8dc44eb1879e19a5b46f8e30ac50018f5b6030253bf6a2549496829e3614f9cebe4c66679d948bf0fdaecc6f676cf13eb2def35f5edbde6e685c71774731945226a52b8e8e3141ea7d9e67a795600b349e3b530cecb4745fae119e7b2bb86b9135a7d024ec830df5f24ebdcbe836bb6ff80cdc356fe6b7ff3925b2a838b55859a650a0304719a14e50648", "d4caef323ce862c", "14", .None}, + {.Log, "8f3955ccfbc06d19d5c2e77e42d426c02fcd2d106b57e83b1ba5d8e838087227ddbbe38c20216d632ec0aa2a6d27f7cad3a2f5329044ae2fc12a69103bda8688e6491179f333c443b789c52458b3a37ec5ee77c7e05a071e983821164840a15ec52382056ec956787947042de5c3117486c4ae8b987697674c5f0a36b5d4993b7b0b9c27fc68b8a02087e77b96c8f3bb55a36cb16673", "e5c8c83167f4ab5", "14", .None}, + {.Log, "24c7a961c1dbfb6f922458526b4a5f832ce4d7d397cc4ef30a7d23c6e8addead3db7d81ec47823d3630a14ff1b1090afe9beeaa4840cb187995f18a230cb62e2c50d5fbe884818a47da25c56b413101de325a521bc970740e0e76fbc6f17ce216f93daaeb6c4ecdf0ee58005264cf1f828ca2d3217a6380075383e6c12c554241c0e2d769c1c9bb46f2aa0e8a842cb7b94a1a42e8803", "e854fc9785e26a4", "13", .None}, + {.Log, "3e3673afb47a1a09ce6ac3d7d4ed7cb9f5d02c019ef369fdc9e3001edb265231195c0fc28e69a8d6ef67a1da5db2ead08fadc08e23cc21f982fedf4f1a3282befb3c48e9a167c7f0c220700c2a069b7fca14da6b00461355f0e72723a138f52aa82e786c8a20da2c7239dfd5b3aa63c2fd3b0d9017df9452b21e1652464b1051d468a70701126ed0450ce6e35e27de9b42017abbb5d6", "f96be9c486be355", "13", .None}, + {.Log, "b76c67c91866a36a85f2284b3e3c294dda5838926da4ce3f737a3529985f11f4f2c957a81271097ea691d93abca443001a972eb4cb00cb0f34d9c703519d9b2b68ea1abe76711c94f4482df0d32ad368a6e9393983accf599a28a4ddde14f5ec099437fba021b73816c0410da173a41e2eddde74ee22e0d7794b40758809a4028cd71842690788197ec3ba5cd2917056c77d4671bfbc", "df205bd268f0fa6", "14", .None}, + {.Log, "bfcd544727ce86345b337a59cf481e83182f183334fe998cabea8b1c854bc346e78a2a34ad7a75e54914001dea4a0f64b86b9295b200a72a5fb5147cfa522db61610b2aecee3dbaa8a4e6d1542cf60ab522e1062760179aea41ae8262fbf9e2eabc2eac8f0879138de3fdee23339da404d91ee5567455f2a52650257fdd44e76ae2ec315137dab048e307a5e6bbb5f4b6e0938bf33d6", "5df433007442e8a", "14", .None}, + {.Log, "f1c6df76ed43cb2638ab38af5dd916e754c24ae247f0a6447e8a7d7a8fa31f2701be9b450204445eb62fb4293bc82af7e09c6a47e8d057ebd487bd13ef5bb9e72dae916e499147a58685bba9fb34e3ccedcf01ec54f5c50a5464fe9bc1cac7bea29c5eae8ff99e069a5f9f9e38c29fff4ed644296a8b43cd970ac9f29a255e8f0f81b5d65e71c1eadb33a4de3db652dcec794274b7ca", "5de9c3a8211de40", "14", .None}, + {.Log, "7b55a6f2c6c46fa49f79bd95aa3f9cd0d9a4b1cbcb68b088410a4268e427275e579a389b4660cf7e16764d8f8ece2ae38f987ea7ef69d7e4139bd7cd32272a3919e44db8c07eb68b291650908c453247c73d919cc173836f99fef2d9f9e120489a42c5217978d5012b9341b269ea6794ec395077ab183f6a411b75a6e60707d215c44f1235f1fe398cbeddaf0632d475e74641548bf4", "7bade112d557529", "14", .None}, + {.Log, "3a7ccc635e5dbfa85ad3e27bb531b2d903db5055ff566b695edcbd818ade627ddac089f670422c766e92d4aea04cf0088e28e24a8de633cf00b99092bf4390db69e9561d99261f8ba26c68bbaf04d5fb1dae6ccfe066fceedb54b7df1675e93b0cdf9922b2f198bca8e19f4051173f6eb68fe93cddd8305a2135c5aa1ae508815b8088f5d3d4b829e2101c7c069d3906066090772f0a", "b7a08edb3912936", "14", .None}, + {.Log, "58c89f1ae532ec845e9d5b5c0beabd1b6c3132f7a6517fe925f82bf32c9021419d1b931583ec68a6172b136c19e9ed123d74b98e5df6cc160455c6323cf2c5bb7bd806bdad04fd87b75be7af8ef5c9891cb98be3e40017d05613401f29f03be1b10c4fcad963285eca78979991f5c3e20ce7bb988ba9f64cfb076c872e756ef97a52a2fe29b47120f902f805746de8dbce6c39326bf7", "55a70c00f0a796", "16", .None}, + {.Log, "3488e633f95086fe0d3f12c8de6627223c85c28eebbe293970e7e1bfc19e2a6f9f4b9c0a0d652d3995a67ff79c696099cede1f9ce464f3f1d7139bfc987d1088d72201afcebcad2362e55af1ee7234fa278411d71c5291a88a405a089d18b885f4e8ca8267aced855300a47dc3ac2d7170b867dc40ce5256689d0bb7713c0254087f6de4ec37900d0c251b2642fd1f674af2bb405922", "22a6f21b156a6b3", "14", .None}, + {.Log, "550f0d052947fb277b701c7ae3fe1508c6d065136bd4e6ca4666e1f579ec7050412b77f94922816d865efc744947a3f3a45fe2bc0b331d7356d598379233f6ae3b54b10c99c72739354b764388c4157fa07bf7695ac444b95c67cab682d0f0af2c95b64c5906eb29212a051510fbd947647fa578d3741a5feecbd2f1c7f1b63a2a300c9aa95e91217826e87227718608531e53591f8a", "9b12d58226a9f24", "14", .None}, + {.Log, "9c26731ab02abcb5c529c238f9b4905b21ce43c43fcfb15a30203a279f74ac8478b3de115cda81a776d10b45760ab665ca3304760ef0f325aaf7cc0b40edef8737e10f8ff3d482c14b3eeebe3f456a7f8179e17b6588ef96f537ee1521a495669faa7f5a4f14b9a594f411ddc72c3ddb6c022731f918b979df0d7d723b99389635bd12e8bb6b6fe1bbc7c8b566c5ce3cd6e5471c1674", "dfb10242f5f7b1b", "14", .None}, + {.Log, "5d1edd0827feaf8f30cfb53a6e4bc31452600fd114782f855062e7aa6600a51d936908c75bf85596d1230aa4363137e3fabdcc0425f79d3695a7f015b35e22b92b803b244d6b4b9ba2e37e90490e7da80279d787d6bea012d79eff61096506be91f3dc8e2af70afdd96465d57b55aa47c17be3f35737171bb3af56ea9b20ce5c7d5b5c4eab9027166a44f48e957e578c3cb78a8cc4bc", "307d2e582c3c4d8", "14", .None}, + {.Log, "afd9ccdb5d839b822ebea68881937ca15592233d76643d4814afdc15c2af88813b28c8401127bd243576e2bf1ea675e46de3a80f67cc0e898dc69e94928d086674d1d54ba6958947d20615e0d85cd8dd69e55356fdecee73f3498dcca154ad7db16ae99cf308c65eef7cdf711c6e8e5382eedfb70ddca6a45d19e63c60bfe2d3cad71aa94902497a0bbfece5ddc6624eef2a199c82ea", "1716ffdf1e9ca9b", "15", .None}, + {.Log, "e274b428ff4e37b22956d38b2e0135e72a10fee09a504ba72a4d6b432999adde83ced4bc3a50e708695a834976a2c26e59a754ff72c10881efac106ddd0d5ba8a679cd71f86220e10dfb181d2b760808ccd9500408ca1b275a7b83948c57e342fde97d23d1e582292bfee54038a7ee8641c75ad2ca81c56bb14c0f88ec5126be124433c726fce2aa3a9f4fd02a5bc24abdb58a8bd177", "27db3a77c186174", "14", .None}, + {.Log, "7935f14426314d3f9f108e666ee2b7eca2659582d5d0e5df07bb81975394a59b20948ec0944d56a42719ec2c2240316490cf10c5f1a4e06f3f8482db56dbd55ff7f951cd735b3c407dfec07ec048c1c9de74375c65124da50621975fdc91bcac2da0c6fe1b76947360a03a0deedcc9edee41fd63e47f3e3b5fa4df475c2cb6efdc0e4898c4247c2f76887d716f1225a932be3adf55b6", "ae912a76468bcb1", "14", .None}, + {.Log, "50f53827161112c66c6086d5eca2a10809c5ed04c16e3ea785efb01938ec4135e43f613be543e5c8954e2a9419c2af4bf46d49978c617e9b7b58b62112c9800f7ab17101dbe9e57733b16a7338ed5892cce4029d1fff2f202c3b23e5f8cdf99798a4213eb614037167ad88df75a6cf564bf26664f9e805250683878f14172dfefd088142c988c888c9bb55558fa0fb2aa85cd8bee9b8", "a8f50064f556316", "14", .None}, + {.Log, "e5d03bf83cf884b3ed7091746e3dd64916a55c058baa8139c498dff9a0a1a90e08b6beff1597a11953d526c73496b85015c1e4b12ed63ee44b00eddcc269f616ddcb62aa7d4b46a33d06694fa31a6898a326dafc44b476b5ad459f78c675448545ff9b818bd68e89e21ca7332c9fcaa0c5152e0fb92f76b9117fdc0f40898745da78891ee230ee671b90f26b975c72901e5cf05ade02", "761c62a3d52c39e", "14", .None}, + {.Log, "f7a7af3aea07e589c4533354ca11dd6989c461616789464164eac75a295b57e002d08c99c20e1cebbabde655f36bf407a096458f720643eb51e8193a125f601a89de6388594de04d4b011fca88fe19e31f12fb74c7aec6bfcd63e363516438ac9deff8b3cb6700f97fa745de62b2324c39339a5ca7beb76baf0b41ba9452a34ceb5c36aeec3c272cee3d1b35db2b29da9bf8b3129c68", "72b9cdbfff5f825", "14", .None}, + {.Log, "2dbd78118f9564b5165ade64fdc297b3f84c9c64063d464eb2457a9cbdf9ff58d39386678f208da9429bd4b781157f47ed58bbbc1eb00bf1d63bbcaeb95564ff0ea9b29b751772590e05b977bd929ca3a49489ede651338ef6fa35a8a9ae9a9b83b8a9ed9698521ea54b68742b30b3f6e43cfe2592b550933f7297a03f7e6f15285bf0d159fd0d095162e42e92a519c5d7bb6df33521", "2c00809ba3a1218", "14", .None}, + {.Log, "c78023860f49143811ee04717fa62e99e2e247da7f4f48f9f499f2ed75cd6413a70a49450142d01b17a1b3f1cdd4f34d7dc2af06aa48d0306ba07a03ce1471e0e08f04718bda21a5079a2ba8b03720f454fad45bcedfba82edfebdbcfe7b5db9181d133825ccc3082284a3e62b0f8163005a89f6e2f0ab5c5cf8825cd14cb672bf06e77892b46c0850757a6acb3972fe8a9530636d0d", "24738df5b7e9c72", "14", .None}, + {.Log, "8b57d344b8402c45b76a94374e9ab2dee42398ee14b6d7453c550726f24b3ddd0fecced7227d9f6407bffa2014ffc2d45008582896068b1da2cad5d0c7f5e262136669d466e9a6f37e4da42af99caae37d8ae7ece2494093d0f1c8f75a9b8c487ef88a4b26a028e94d8654a8b34327ba0fef0bbe954868a80814546a0817c5be93f82e8558de8828016119d7f52a1232dd79071ae174", "fa31ab21bf469b3", "13", .None}, + {.Log, "ad292ee1d91fc802ec59d524e2fa56c26a440986a755ed43096ccb9202b006b50281827f79f701add35525f3297544d8125f5dc366ca5796ddba64d42fec79fe88c99c53a9fc7a13d1994aa3df29df1e3f4bd0a9de650c2e2c96f3ae2c8fee1bfd9f926492be1a47b1cbd834a5ef63964525c917d5d1bcbaf3c9467d34485cf5d8590be2cd8574865044e55ee2aba8ae3c65874f6f69", "29ff48636342b2f", "14", .None}, + {.Log, "9d4c2767af86d2cefbb539799b37d79fcc40d48d49f5705156a31cd4de42d2b3ef503aa51f40d99c4c00bcfe625dd163638b246ac65df62013050405f163bca5c7bac1e2521284d599f278956d3cea56587e1ad731097beee189c87e25671e0074e44661aa34512bc5d880c3f5f8a47ba7b96fea6aac0cf8f53d4b80c851ecbf3bd48569ab88d6758cc7aa6a48d34d0884cda1d8a4e6", "ce1852094281b", "17", .None}, + {.Log, "175ffd6c8c69872c9d9c9a5cee272473fedca98edb61eef277a4c0af085ee8d0189c57ec7e8cda850667cd0cac5925b348cfc61196ea94dcbcaefadeb65449a0e2e63ad028284ac179a24428f86e5490e0a73548a82292906b70859f0fc81ca7adaf515ac6be09ff99e85be50f1a49bad126b098a564e660e850ed61d7b77bc135426180b2d8e728da08502151d6d45ff3916b11daee", "beee2f8c1363ff1", "14", .None}, + {.Log, "b82fe6892de28ada77b872acf2689e8dc1d73233e57559b209daac3fd205878343821d6cbf8736c7eed184a287691e1d0b2d8e2c1cc4ce48d9e3ae16d54586c48e121644b1e4bcdea70f585c0aac7972c5b6ccd64fdfd85cf010781b5534b66f11214d97a29af9a27a223666699ae32d55f409b50fc4b0ac55e92f9ab0df5a93236987c8c9c9fa12aa028645ee4948546b1902017e37", "7c192d16ee2a0c0", "14", .None}, + {.Log, "6ca692b2ecd68192dde72d241fa8bc460c9f7d799a130bc57ccd1a84556dc2abbd2523cc5529a211fecf4204d0119ac6164f3d78431f978d2eb4aaf6de7f8cc703c63e302070bd5a5f6230323867e7c7807852d34d6ec968810f0fb39a2cdca9d38dd63081389887d71b3fd091b198b8a5a9be55f0cda1cb01badcee7cafe7e203e5994f22fee71aa33cca819fb43bf4a4ed16234cac", "baf0619bf8c1428", "14", .None}, + {.Log, "3427ab305314d673bdabd0ca93e771f28cb701f11f37abcd671d2ec9500e081766f88e54a49b49edc376848f1ea1fec21568db406a71c0b46cbf83a3051d7690bf07e419465c51527b0fa0a4a2786ac21cea3f633b8ba73650bbc78abd458da53db35e917eb8e4e39f6458dcc329e94283c398d3f559d66aec1e0e956e5e6ca2065739ac8bc570671cd8c13ed9faf7705264471f28fb", "acdfb76f43f1338", "14", .None}, + {.Log, "c4b4c342aecfbac861a5e11b45c0f7a5c3938c20a0384cbc9ee67195ef3051ac12daafbb9cb96abd118acd368358570a5809e123a9354216a5f2e3c8eeb53ec5856e67401b6e87ac870aeeb175d7eba6319c13d8e373c509abe9440188f3752d65cb58b0da4f9a05a77e97719e9335d2ace62f69889cf5e4cfb6af00bf8a3bedaf5ebb523ab1be9b2dc6d3533ac6ce93f1747f838d6d", "661ca3093fe920e", "14", .None}, + {.Log, "b66c87ab896d5e0db6caba614ab2ee3def49f33e4b8094430371ba87b3295901247e0b138b02462f648fb5066dd40ec61f7df6b9e1f8cc797323aeb317ac708a25b079af606d0277ba0bdfef5a7a0ea92245a9152dc153d273b9e4c05ef80ee048526c9d300bbed451fc07d594332e5ad7e8b46795093422232643e54cfa51ed561e0b29b81b2bd22915a838dc70ded8316ae6e03e7", "49cdf33e32e2153", "14", .None}, + {.Log, "cc3add39000e679586e5897eebc77cc4eb5035f522dd714a805cd63b8c1919493a81b147e3535e35361817cc398811f72d4f9b9fb5175605b76343378f5cb48b4270ad00a044fbf3c700140c549f373aadf8bb640631bdb491f6a4955211cb5a36442148164c211e155f87dee5a5f0ea57f7ad733ca2329e4f6e8674624cee8b1a98e9887f2585283f87d2992876db907bd392301ada", "70d0f568179096a", "14", .None}, + {.Log, "bdc821b3f623775701d12e3317b61f9db282b7ba775b1de0467893548e4f557fb18535560ec8e60c11faf9f0c63bf4e5603194e5f12a5e768f3d4e1c5202e38be12f5054f8bae23375c81ec68c26cb3cca0a9f7861cb954196d28d7a3da989c58a115b1eb65faa208cbe44f3f2854c2373dcece407cbfa93f614def54e5889f640eca27ba90fd1bd281804823b8bf510a44dce9fe1bf", "f74dc674182cc06", "14", .None}, + {.Log, "17e8e8ad52f4c4e12dfe6ff38377251b9602ab8476c0068033cac5dfa94bffd887817631f006678adf2e11256ed08c8e3fb53317e19f64700d9f1960e354289d32ceccb71a189736a00f43e856db7eade10e7184e7fd05c61ea1ddb7b94e0759272915ddd48cbdda12c4c9b0caf00d358ecea333bc0049bf080c41b2caa399c4aae6604efb8ea5eb1012218992a80a683a5fcf3e7690", "156e92827b05e47", "15", .None}, + {.Log, "82c702d1ca7b0a369cb2c798f2e0250647ea10e6f50a93703d4ac2da384b545503ad702e112ccd6876c4bc27dd3e6faa8147316202c97f348bc70494e19c3d1cb02569f46bb1cc2cef82d189ead52c4d8d5c5b9affbdd98eabf31c06605f31485f256858cc38261cde0a13ddd4f7eca18ad4333625b7ac9010d859c9b9c060ebfadf55beaa6784347c28d9ff87635d2a24e5afcc0b40", "760f2f7deb1295d", "14", .None}, + {.Log, "ae0e3738e2afa00a3162f91b1072968a9db01db86d82e68eb708f24080a5e972ae0d8031df1ddfc1cee145147850faa9f5022b9d2d16a51baa2ce927890d21a161ce9ea83eac5935cb517c7f54c32d745ec69b8fc9ea4388093c2534c3f5a1905ba928c4d6c8e0d4f1e76d2f3c1d9a2c47530d9a2eaa3e254ff40a4900de9ccb6a910cf28776af8716f7149d898f33875d002ccabc1d", "f3085ba3fdf59f6", "14", .None}, + {.Log, "a77d25ccf1c5d77d9865685f6f118e198223a6389b1c6ef3fda7162a9b0bcd79a8c2b8597971d2946c1760dd87144674e7b96991783118d1363968866315c5747150934d0e8d9e1e8d641c7cd7d3cc4c83799d36986f2d3592e6a13bc55eab28914f10b7d1cc18d90a77f4c4cdb41fa8469a05046892eb4ce1e58733065e4fe5ad1567766bfe7674d65938f0c7a770226f93d41566fd", "bbe5e1c2b583433", "14", .None}, + {.Log, "aab6748d6c2543938fc63092736076973a8c17fa22ba868c8f32e868262e740011cb1bb166a0174207168eb25291605ece64b20678c76be6b6fe33c762c98f73ece243b887681646bd03ce0f7839bed560ae67cb7ad6bb3cfe29b6b1f869b1cdba4304c54cf2d0280a588162852c5d4684c47aebe8697d7f90ead87c5968e60d8f2068c601d4dc3ab5ac896f3250a9afa299ba102c6b", "7b78e0b8a644f3e", "14", .None}, + {.Log, "455a45b13ec262dc750a5cafb1bce55eebcc5aaccffe2ac4e9f1fb1646068de1405661a152152c1e84497f9e6c51fc75e1a05b2b771bf7715432cdedaed65a76c7b8e1158be186c9c1dc9a2a8ac8b2be81b8dc6a0128ae55929ba18fa29754c341cef04c36414ad2b0949efb825ecf1c6d103cde51eef228c0860eef073d5a0e2070ed3a4560e004610566cd31b9ee26f2122112f408", "8f592c64a622c3a", "14", .None}, + {.Log, "86cbb268a43b82748691df7a37d882dbed4199dc86c93ed4f24d563beb4d6df7d6953f675b1582939f6ccda86c3f249cdcfb92b42166101b8b0ab9646f1b112c5d9e1b832ed3229629dfa9bb5c099edd1a45168c7300d13470712045c79fdb11d302a17c5441ebf7529adf34459efac6bb1bd2323233ba5fb51276b879fe779024a1ad54460027a84b9b495ed8678f42811520467076", "1464d6eb728283e", "15", .None}, + {.Log, "59ca6769a9ddd073baea636f0ba864049ac1072d5131b8725db0946a885ece7d27f22df28df31f5edb4a653f8678a9d1ae5bcee2aef192c201cb8f109d2e5a2a3738e72b113eb6e33d39434e7b80987a1f33b271e08229ddd637a649aa57d00d230593e118843b2f6411038a15b2340ea0ccd4d9d87b6f1894cd64113f8369feb3307bc4ca11d6b4d788b0beed8e966a35044c6947a5", "7d82678f0564ac7", "14", .None}, + {.Log, "7d632bd0a3f90882fb3d02436ab9bff5708131540dbcc5ca0b360484d78e2c82a2531c7e6ad1dd1af2c8f39fc3404b871504771a9b1b6f088cec583a8356e98bc8c228275ac09c75dfbbe3d96646769eead58f7f44f10285fc7d2d623eaf099fefb21775a5182e93bedb9185ee2e8300bdc6050b85322981f522e2ac6aa0a90f04a2f96cfceee2e3cd3e0fe519984eac874aab80dbc", "37e12bc40ab000d", "14", .None}, + {.Log, "38003e3b5f8b4eff854c38bfc5405f53eb75b1a855fa5b5666fe6329c7a5b47c7325828eb9c5b753b1ce48b1721854ca785f46b5e8b6f5340b01fc96a54899ad2e7d5ddb780503ee09a0d6298e7c19335a71a4c2404fb71b93a5ade943fa5e0d14f4069af5b602a1b49d828e7d29da630f9d23c38962776a25f7f0f51db74b9124c49876363585a1ba7cb71e6f48c94b163558e37131", "22241ede456c223", "14", .None}, + {.Log, "c6b72488e7e66d50bf8cb1bb00e1261e4ca285bc5ff7067e88b405898f4b1eb8183a84a0fb095ed39e2c1cbac98aa2561d7cd3d0691b5b8176ddd4d8c52653b4a5af0bbb21080e9725c8abced5c1b5c3190dbb23aa4ae4ee3ece049da93ded3679f184b801409c5250cfcb9e4ba3af2f03664156f0e7a953137d1a753d8f0a47b0d630e21f986c138c03bb444ad994710e77b56eb4d9", "9f40243f35a00f1", "14", .None}, + {.Log, "9500aac38f50dff51c86317f17157e0d6143dac6a9c1ee2825d4be685bcfe9bbed6c028edd461b2c5b5f67d4c57d3bd2a9984d28373c3fc82dfc3d95d9a27850c98b98e7ad48269f59626c4c5c98f5c31c0bc543462c1636e6653d1e7080341ea5574d5cd545866469c853ab0badae4873a9ba45942d45a9518d881274268c4b9b039ffe211bcc982615c719807e2a51e60868c4807", "23057dce88fd236", "14", .None}, + {.Log, "6f029b43bbdfa3e6d9a81f3f33e20edabd191a8a090e9dfe1659582dc4b3809c705bb90047b8633b07b29105e8ac31fb8ad609cc6ec53e040a007abb137d6c7f40ebb996e0c7ced41c9ca8fad6a02874b93c1fa60d2aefa6aa5ade4e44dff148e108b808f561ad32a7302e1caf07c868aa0440d2e24f4174073b5898ec549d796fe71e5dde4932c96e93e3cf2eebe7b1b1c8f9d36e97", "8a8e1ad14e9f433", "14", .None}, + {.Log, "d9a3f8b7f1fbaf4b1bd3c81cd4867fe58f2fc7d33698460dde908095cd5db37d1cbd30a05024be81285cdae786cc642e94dee2cab1a81f3cdcbd58d99dfc273f72d1d42db2fb82c40b66ec70d0bdffe39d59ab8a6002e2ac0cee0034a19eb1225c85b6fc94106bfed56f5173a3b0855ee671129aa86185ba37454b698ed1f9d1c7bb469aabf0adb462ddf739e009aaab16ad09470777", "140ec7bd411b8c2", "15", .None}, + {.Log, "9a999ff62f80dd2f9a5d94702fc9ff617bd2ef1188f039cf30bf5e539b45d6f517f805afe9664547530b83fdf2317cede038c5d463837cf4e2825cfb704b6b024d24460e69fe6bd90a2da33cdce8a38768effddb79fff8e089ff018cf8abd5996f87f7527515d03b459dc6296ad8ea905d3b94f3ed2d9da0a2231ae562e2a0f15a640c550f31f895ff01dcb3af771fcee2a20c406da5", "c76464d0b3ba738", "14", .None}, + {.Log, "3feca8b3f114f254343889cdd75bf22cdf1ea380e881f14c2ea44957bae690018f4d2b34649b0153c8db75faf564dbf777ca48ba34ba7127d4b18747b8a489585aae404f989fee1bc551d55f089734669f8dcf192e76e6dd34b7372572a2f14206b2a06ba4d5d537c913c902924af2ea3e0c6dd5d1b3ddf044ef24424fd3c3ed40519693beb51c05eca6c203d1db5cce9de9f7cb3b8f", "478829c9c73762c", "14", .None}, + {.Log, "9054f75fdf67acd1b50b696e76d1fa0b7eac00e9a46a374d6c0a77830381ef83b8778009656b6aa78c9e9ef300f4539ac8a94571035c4a371984e7803b5a36df0e0c1c8d1325af9569d6092c155d804cc0353c549b5cc4d6985386ac85b54e9a7c4ef0be6ab04d6a91d3549c3d97582451f94365bd8a556900567c680cde39b4413ab8f0ef8af291f7af42c9d00a4b7ccf54f04fe2f6", "5c903b102a58c57", "14", .None}, + {.Log, "ca630e784f485f1243df60a136070ed8f5fda9fc875fa19e8a171dbcc0fab66188b6735a34eb47e389036e9139b453c327d4ca097bdf9b374de18cfb9f08276a2ffac8d6c53581550e8fe8ea4f8e2fcd0af4b2aa89b50612907f2bb792ae287511464fad131f640b45f1e0d1513415269cc508bddd7a52aa72dccdcdd2a07b991ce4266ed321b02914ca68ba7acf5ff205c2e8436fb5", "51edda0a0670305", "14", .None}, + {.Log, "799327836d22a9a2c186065b81525d63f37a5ee91c7ad77351e512402e11f50a10d204701950992abb1d951e1d54a97d786e8ccf9f76946f3b2ec3e0bcbd66100b50038fc07999889f7bf30d094d7968888c8c938361b314fe393d3dfcb9c407d5fc6d5cfd566b2cda297b6a1f55ee41b6db2a1e3dd4f72dd9d5341bf5df76741ac96b852f89bb3f5db2549898b6fbded423fbd8644d", "4174f5c49ab5c71", "14", .None}, + {.Log, "b33721bdfac935451ab95e7f9fe26f5563b75f3a4dd53a0595106ac1db30999476686ad1dc37cb4174712007b2051d73016e25a1bb4a1dade88c42d62a8dd5630bd9f28f7ec5b314eddeb840355fec3e7f1233fb32a1593710fe2f1cb9c1cea4ecd2b10536f60f53a14b3c63032d207efccfc938d62a91f26ba7201dcd62d270f1a9b5bad58e54db503a376d6807d2b77eae6d2b295a", "b7e00268a2d0c79", "14", .None}, + {.Log, "4168ac0799ed546d9d7a9cbad3381aefc98bedfa42acbcbaafab322f28fbe74d43fceec7c9a1835574f0eabc593da2639546de8e7406823980c9db1d846abaf7c3e564e26b2e0109a9670010e392a7767f911bd539a9a32b1ed255e26779e6dc77c618ad5cf173e6c372648072d95811635fccdda880cadc88d65ac22512078dc2b7f7faf49761079d52c5b42021f0dc7bfd78dc086d", "b7eda4572dddfd3", "14", .None}, + {.Pow, "-9369df47438e794b51ecdb09a896762c1ecb4caf236191d16953140f2e41a16bd54c749f9ff7306b8640c99d12fe66c89f140c373d1dee4e6a57bc4775ea26aee45729ed8144fd689435d50829def60aae7308486e99a5c621753548fbe8b45b8021ba6c6b159fd5e4db2c79ffef6264c599df8cdab55cbeaa05e7fcc8df7a64a18e26664ee314daf6734f9ea04a9ae2767043af6a6a", "a", "106b25edb1d18f454df038dc5e7a3547c55a23bcae7f1d39fc3e7f1e9c0e13252086035a299c07026efbb5b39299d488ba935fd417d4277c9409dfc1a3cd044c4f0ef9a65d712115cb58dfc6c58afbc1d73b6393ab96f10a5073604c1dede4f6f94b1e207d4d5cf0c930b10b2b19bd35eae940aedb1e14cb5fa434a05bf760ae65a89e64ba5c43dcf85759003231cd040bfa95b5b323b3e0126d04a21392518a45d143dd0278974a480b91670392986a152680cba49f17c1f8592f186f1f19541dda0d1a0d5f63170c49e0053a05049198e9aeff0adc144eb1a5e0c07b5357119663667252f756724fd81e238c6764e6ddfa89508181cb027b8e54a0ddec5973ff9d5e0fd7379b8b4fdf5562a0c1bc928bae582254bfdd8a940478e7430773464b97836625ad77257d22ca2534579430c7becfe45bf53da487300b771ff98e02187218df2fee9c79111170bb7e0328da1e992d31412bfde94dbc0f23e076f8b744e06f4f9c55e922d2ee31b8b0ef798f5b0ec305208d2a1b8ce0362557cc732f31d0a4097cc47db96b21b71e8e277129a0e6c8f0888c4fa5f45f8b9e9909e5b5c34ccf15dcd334ef8f028aa88ab14e167a95346bdf8df19b9702a17513c5a02552c337583c12d6665278e8f0385a5448c9feac758539e73c1422179c3186be07932504a145c2b002f0225b7b4435b85784c1c3433bad4424ea66e7e54d618530f40b79c822cbde3ccc02862df50fdae3ccbd22aeeebbd5b76164ac45948038a3fd14cec6065c2198886df3b4feb5770dfd65a68a25f1c4811bb89492a3b9543a2a2cb67be4305414f12343b04859daf2a55f9db44b02a074b9ce90dbb2d8355a033ae3b86af795f39d9cf9ac155f244aba4b4d10d1c53b745d08c98ae7086852e577e5e65460e8b2e08ad1d2cb9c17ee9253d0e8cc853c7406d8b3158085b4c8bcdc0b77be7180f709983c69588951208fc44cf512a90dd30dbbad02ec3cc5cec6d6d7f0d92f2ba1166bd8b3d1b620c36f4d68955bfee7e5ded004f0d45bc0ea349ea6b6e0f7897be49290435bca3a628b31aa1700717c070008e60b415e858280035313f6c9c03be9c532a390306d12923098923326221198fc05dc815610163f66b07444eadf821bd7317c9ce51171a135f8101ee689d8b4bf078637bd4751aafba8c742d3854ba72f0d307d11985fddaae6ec6d916eb954b7f6f08ba05fb694b73e4be7b855bd2478258c055d4076e4a5304ef07664dab6e7eeb0c40a82b36f10371e4f464ac0d81e0d1d826c272ab8b1638630242b3b070bd45a865f340256dc5006d6dc66f52d0445581c0d74e70fe698982af0bb6dea9a5e610d592034d98aa70b8017710c28e958492507520acd8f543e76f6ec5f9ae25dc63a8852898c6c9071e299378217bb54e3c138e57b566704d9942383d6719c46cdf30cc77718b4d48172fe8e98abb66cad1afa6339f5d73e5373a1c19bc340a3767093ae345af2a1eca12f02c7a6fbe10b24305e1d8acbc096b06ee1ca58e7dba001d1b347c5780acb686154e35b4409d814a0e00f8b7afeaf8a4e7d935ef9aa3f1a8c0e1bfdcab0c5fd4d27a947922f0d19a88143f15440d3c765d94b87d20be4d9d99432b8026fde0bb34396b2418d9f396ee6272280c8bf6412fc453db731ee432d3fea634a880ad952a8765dde6b607842313e47c8d93abf69f43aecfd0b0d53c7b21dd171896c2b9404deb9ef62e7b3fbfd2a101d9220e036ae6da83040d197609905c6f4267c7b40187b2164af4bbc99c968747812716e61934ee55540bb5ac578478490991631652bd69f0efa97fd3d07cc169055d1bb4abc319d84751a20c359118e8691999abdf0c58324a9a20d6ad25036a9ccc0fdd25560c9a017ae7c10d6f2f482c3c1708a144897d99d81097ae321df05ec0e9d9f8d29cccb4a3f94d2c447d57610ed2cc2c37e71091e297c3eb9b5f0982b7aef925d5430a80cc9ef5e96fe606152ce91768e1fc84806f2e6616307d2c2916845ffff12dcf160fadfa4c0a84f8703f224f2a04f13230df958f4edc68edd84ecbf6b7b70da7016665e5191e1f03c59dcdc8cdc613d4ade200bf93217a9b714040c103703c3d6400", .None}, + {.Pow, "-1b501ea75a42a914c6c8ab785815097b39f18ef11eb23fbb4729cba50d9b21199e7b74b2fb3fa999823065bf6126b6b0e7d22a5bce52a95f2c6c95b2307e1007f6a1bb02bc20d8ffe6da7b87f31e4029f6e9f4cd7347d3593ce01d1d99edd9eb288926211c27b5e010904b51f57b754f8d9a0ad419e7b447635f70563914d418bc78700b5a6aca84bd2bc5097fda1478a862a5475c6e", "9", "-7b184da1508c29d83940746586a3100eeb50bad4bf8aa32400fa5b31d71128532e35f28896602b81a8eb5c64bfc932780a228cc4cbda689bff7bfa4d15a73868bdecfc19f97b1d6c2fef587133bf619ecef4e94f986697617a7f0086a808023c4859527336b9c901a9aabeb038b0d3614a47a9b0a1450157e3b2fcec8d06331f3075a6aaf8c925583c780488f04b9258b6e65af132f8bcd0f4c0473288813b880e6b8019dbd6f1ba3083e2c88e8c2fd29d2b40d286de32756367da9bfa1aa57cdda3a976c5a69ca34c5f14572de2f41497cf504273c95b107f50dedd09fbc785ff9210276b60ae0952e18021d5e2ac579525ab6c81794a0545dca7856a62b1b085ffcca5880305ce5867f265994d080f0f846f71c5a8afa2851250293555ee0c85fd4939cc837f6d3c17bf913dffc6c1e93e213b619f0479d1493e0ce247e193ebfd4b8f95767bada136d78138601b8a8373bcaeefe4c62df134799a6c40f3b1b53eb906622bddbfabaa5b8684e9adc663dbc05a0e804dda05f64ba869b0d817dd9ac37dfc10bcdfb506b748789f401a2c8939ab5b8feb1a592628e9469bc71299658c19fa35be42fbe879127a83232d72feb1128ce0caac70e280830960d9d40011c7577802dfeb206a4759638161b8b00267c9b76ab9fdd1be89f379a439c9a79ce50b70116dac5e813ce5bbb9fde067d16075a1901b1d9bde992078a564bce34d6bf50b051dc0efb3726d84a325e46ac19ccea168876ea9acc968eebd24aaf35a3ab3e25ceaaea8001ed2a8fea6e471b03a0e61205943f0d53e94dfed2fc03184bcfc3c567c729ad95b285a5106012c9db56e9ba8007e8253fa9bb86594113906fd0ed108a0e61740f278092aebdb8880fb389bc2ee37c85ce0f9a0356f5f8dc472da33e0a88c7335ffd9c7faab56c1480ca4a154d958d31c1be9326df36c971be2ce54ce0dff04948504dcc3299db04a85ef9425b6fb1aaeab8371209adcb006b42ce962af15b8dbaf10246434b6e8d8585bb01ea036f215de37d6a580164b789e526a702e62d3772df92cc416730b5aa93df92f0e95e2ea337e2c48394481b922c938c6ccc6eeff15c4fd54c7702e3ed0e26857b755bb4bffd31a73c2e55ad09e6196243277f2cf10b2c49ad8f8dd2702e47c5c98276796b6a68447b41140594385ee68f433e08c795d064a3e1b2fa8786fae018cdd7e7c864554a1d15c115b6fb74d3bb24170dad9105b762fed48f7136872d9b1d28dd69168ec7cf09cca97a35a21bb14d05cde1dead4309826a59947cd4f8a877d05f425fe24a4a0577139995033bba211dbc5fcb0c923388871718c8103f2eb0059babb43b99d0c6a0ae4769971751eb586e5c952a626862d56474129dd501a3ddda900e64d1749f03cb876b7167f4bee0bb1fe5b151b824fbeaa07b854e42ea9ae0a4c06ab4246f2c6af1b9d6328f2478760ed73330315f5fe85d518c28646fff6cf678dd7b0ed7f3718dea035ad77933e553b5085ff385d4f6b44bea8a10ed909827a3de455b7be3a407a161ccd19777b2a14d8f7c5e2f4b1008ab541173783547b2f0e02442687605757c2b7a1c7082f68db12d7ac307e979f4b88175aa80c7d8df659b7a521a933e5b43d24aaeb29122fa0368d6d4f7d203f4904438a7784fd2062d464991d96256706622a3901fd2f6f571b557a05f7409d9397a10d3bb316a04cfa4ba39fc16a6502eeec35fc63a4f00db0c777812b118348cfc1f026cd7cfd775da8f080faeb8c81a2f5e5d9c37e940f1868916f6e06be02181ee7537c655c453daf23c77e96cf80f87a90ce4873e931b28653b13d26fcd00aeaabc366195685d05e0793545dcfaa4c08fa5d66d34769b360358a076fadc96410a25a7d20ca616442dd1363dee00", .None}, + {.Pow, "-c0341bb60c4553b074799bfe4d94b1c52e0d78f0751dbb8eb8e3ecad8e14cb346720829e7f5f2e7115d17791aa030fc6aeae7c548a03fe0f7256f19d73dd760b0aee52d731fadd51684161044d868012c994869efe7d743f8a34dacafd52e7e34bba8a76cff40bb351c7bd512c84973bce5a139649430df3e00435474dab58ff0fb2f8ebb6d2eebf70f5aae7a83c7b612229d882d80d", "7", "-226d203951df69f0b00b51cd57e2aee02fce7c5d5fc5ac3b7267844dd0f84f0afefb33e5085ddb686ce341740812d7d79abf136219ab982430d2d9107b2c2067fb81dae39920c8cbae4b43cc04513264e923654a1a79bd00a44202fcdc5e75dcee0d828fe7ca2b05cf7c851df311252763d7d25e7149ffcde6fa3c9b726f2577cb7cc7eb9e89d1af05bfc72a3d2873058c4f2b9407200d95bb357aef31d4a3583baebf4f72d6259dcc5fce782ad9ce61285fac08b1bff1267ecc32aca7b28df1b83d09f13ce9b6421e91a555808ba95da94c00dad7e3f42284efe733dc7e4d0c349a6a045bbaa27686267b3ec437accec10b4195e6c2b06822f316cd238d56ecd8b57b39f9705925b6c93131359156c70df8152095e16a656045124d15002d290cc54193d154c598929c1b6e51f8b451465a833fa96c0398e741eed9d9b3c94e4892b9bc954c14c373531723b58dcd3926e4b48487b9aef098a74245d39d724ef4184c9fbd159488dfd95aeb061c41e616e80b7b094ad5e74ff34f578be1a2e77993a0442939d1a6359f700a125a83897985048b2578af19ad534dd39ec295f8951bd8108a41d4323af52b26cd0f365d40e61cc71abd57372dbfdcc704206ff36144b53f4fb1aef6e850dd9d28b7946aba27114243d0b11e0952b531998117ebda221c65d33d181a6be5b91711ce2857e5d6b6dfbc652de5b577683dae6c529e61600a48b9898b42458c7bfb2ab634544c48aae27313c02e4c9ad4f9148b91dd391cc4396095f020727105d27d6a9fbdd14401fa6443ea9e6790e47b031a040a544c78002964a09d2f67def4908984c13fbd030492b7361a8c8563ca691d4b0606eb1f9053d853b686ade8e26dfca9a3fb2c9016534be9765c19de4bf5a9f5576b05b25a10da5b16c4572fa5035e8ac6a8e36c9b08dc869cca69a010f8c3a712d0c3d1d734db2820f00995086f36923fd0fa4c2b4d4b58496a9bb728a44cc7eeff0dac44b38aef36b235d995d9ea8e7d88e96d6e668cf910462b36a63a5cfa1ae6df6308bf2a6fa06ed6b69be56de5bff89a0bbb2cc07eac89375c2b93c940e47689d319bd68083d20cb836c2d35f042780a2feb73ac67a382525c4bceb137b643307adac2a97fcf84d76274706cd8d9865e95ebfde04171c32457e4d2410d82ce071a498c82866e0b0783755e02fb07cbeeee634e477e28d74103b8474a32e3f8b10dcedf6e6f247615bd76364804490483f430187b62b9c35d96f412f3bb421c1d71f30cf97af66ca1e8175cd86ab221682a678389c5629e49c8fe10e752f6fef66d782539efd4a1e216d364201e4ee67249ae5fb19b5c4ab3f65f37f2ac207a23281c8020ec67bbe927fa8d3e1353f7dabbbf9cc55b58b496787ce7f29637fc275dbf9435993aa8170841621879349bc569e7aeea239d57fdffe1bc8357a2e2c60b6cd11c0d02c8439d812c4c6ed5d875406078e190501f65", .None}, + {.Pow, "-dd315ffae0498f56ea334bd35179ba987a0649f6a420f1c89f289d61678df41c11151ea0d06f2b3b8d0f30684b236c565428b1945634d40232ef8bc7671630b4906af563281ee5c079b062f4ebdbce33df7f9b4cb85e4f2a950772268947677519121a4c017fc04aeac8ae80039cc9b2e02dcc798b370d878c4e082b1fb4ccd4c040c5113e8cadc9ac00bf4344ba57edbfce4fbb22a7", "1", "-dd315ffae0498f56ea334bd35179ba987a0649f6a420f1c89f289d61678df41c11151ea0d06f2b3b8d0f30684b236c565428b1945634d40232ef8bc7671630b4906af563281ee5c079b062f4ebdbce33df7f9b4cb85e4f2a950772268947677519121a4c017fc04aeac8ae80039cc9b2e02dcc798b370d878c4e082b1fb4ccd4c040c5113e8cadc9ac00bf4344ba57edbfce4fbb22a7", .None}, + {.Pow, "-c90d8f31c36056ff3deed4e9fa93820396c0caf6652ba6f96a18a4ce989db69479967f51ea0c773762b6af698af8c857b8fdc0b447122ffe7218d8c07534a1660b4c0d748035e750572c36a0088a6f1d0f09ea88ee6eab0f033ed3c71f03aa51cd22297a5733e4b3418413fafd1436f03ce09011f69f48e154d8366ac0e4a92f072552f5e5759cd20c8ab11fe206f76b90bcddefc473", "9", "-1d194907da85269cf44a9e9bb1de9004f147e7e7efdcbfe5388cb263caeff9f4b5d3670c3a61262a5f7ac0ebf5f21fe0d9ef3f9ef06b066be5424e9ab0054fe3c0f367cd5b52e0185d532779a2bd3ffa3c1080096f5c07adb58a0518d234c70481ddbe43971bf8235ebac9d6d83825bd23c95b3ca3c578dbdd66fc3d72d8c1ae5f5e9b6a07ccfee53b762eb88c610bc50b1ae9699c5fdd906963e2f0bc30843b6eb4635aa20d729df49700f0c44af5e62322be1c817665a985755ee4b4a9cad3626a9071f69f168afe55d35a0aa090e82b0f61a171c9c673f012ec82435e1c768c6b158fb4658864f3905e4b2d1544b572ed96e38f80fba8fba6c78db436d3b4da8351d619c537d1c041e1b0f66f1e2ee44ab5c1479c3d8c34fc6570f41e1ad26595327d1f050763c606e3f2a5858cc2623379f3c01b034e47f5ffed7c39fccdb3ad4bb6bc2ef2e0a10b23f93f1e2a39998b5fdf01a661b03b5bfd9bef3de80ef62a635b6930f8d90a85b3aad1f82f1b89e37ce38a4a59beeea1864cbb5d5eb8b40810e1dea56f3a241e32d976c671b0246eb668021896eb4696ef6ba49972f8d5f5a9b53f5072b9999a3356c96c77236e8725d6b1264c4c2b2dabcf0f301bf733c71cfb5542e0c351ac891c1c3f7fba470e38e90f53f53a8e6b216eb97eedbe85cc58d8c8dcda5d9c2a3ee7addb64bb6631974bd2113f1dae414ccbaa585eb71d570624b7e8cd12286a02152da6471803f93de4f6379de223fba0c66b3a062764da8641d4511ded9fba0f52891475193641a262017e9ae7e86e60378b885eb1148d79d292ed6f6aae25560a162ec8f7515c5c54514fb7093819fe13a71f140e0bd6d0968877b42b05d783e217736bb59d4d82a7b79fb847b33b8f63d2534276a8da776c7a2bcedf4c7b33db51001578af63fe40c982662d2d647edc7c29cba6c4a70dcdc7bf47fae894a2bb0089da26bdf8d9bd19e58b39351d9712946d213d2c5088b7aa21e8a027c8a852db67b71169f527444b14653c437521a25c0929c94c7aca935c783d3fbfb900684c1b28174401ffdb79cdb0bb719068b53d28e3771d5747b4ecc51f1b5b3093c4855da1acfcba7f674e0832ac44a9b982218bdc4aa227fab5a3e09cb05553678d44e08ddc74f91fe234da7213113626720c29d471c47f029af8bf527b0b834800c5ba5a5f17e09bc305a792cea5ecb93b1b5881758908b5c301a46f95544b852f62169e5328b5d924b3f5fb7d4da6da36ed00478de34ce9fe5df0555b8b388d3176370be818aa11bcc698ae783ee38c512b022d473f8033e733a26bea55cc0181964ef24e0f272dd9de113bb77e95af43752a749d29e6123a5ebd917791aa4e59d21c7aa314702fb22c8be45310f62030ee72ffe27e506b8975b928c6134b94b796bc5eee07638b62a6f4417ea1a4f7bcb8091f6cf3ed3f49c5a3f95c1a65e990ff50bbc1cf03c154e27581d529b1a850a59af67ace58c4ed51afcb78b5640646dfec65f8a117b9445c67c9cdfe9a63b7f9eb0c514254ebbd343709cda314bbc2ba2dde0184424c6b5545edcd60b509fee6c9daec92e81573efcfdc4b8beb9937cf681942be2f651fc4eda710b2b8cff848fa83830e84cd4baae82538b27dd1da385dafa04aaede5154767be5c8b07d6e06be1469436838ab4f2472bef3aa1b9fde62c87c0533f5378f7c9a4e0417d08e8f859619310ece2f77faaa3c4776a364835b9359a8e9e0333e1defa2960380cf68805944f4d2bdf630004fd9a380ea7c1357b25d956adf99bc673b1eee4cfa8dae07645870d3769d84e655d6446331757e855944070104a8a07d95b28e4b9bb883ff4139590521b4d46a2df8ac3ac0a2b2cedb3e5e18627a2da1f03b380572b7ddbc4f1790b9b20226d3", .None}, + {.Pow, "-b4caf2e1697dd2d08a65f37076b87ec2b6da9caa5357c7de55a0ee9ab910b837743f263e6f68d45f1f96e0a4e652cf4c4be9a21f64135d5cbf59717433fb8e625c12d3d04ea0d4cfc286dd4897cfe3d2c1d28c1a0edcfb5558d349f35ced1e6fc9a3d7a5c48831a3f64f77f7c83ed1a0b37de3a28b762af4d0d1fe435ddad787be68a23c539888a7b92950ff465253acf884b49f715e", "a", "7e682be3954c1ec3c46f7d452a1993955cc0642a1703db1d891d8bb2a537f89b3f05b8c3f12b627548dbdc74482f48d1a1e884a582a12090a660360ea7dca3f926e1524665fb6c3a501392e1ca06477737b3ecbb56c50298d04d26f799a654d23e21f75a09d86d45a2da0f5f0f1de6c73be4568c1f6f4971b0bf33bab2fd2aada299e1d380905d65720a7e40f7d08bbde399b3433c54566a8f8e62f37a44fecd27adac6cbc86f82df53eab82ed2e4879d4fb7b7accf209ebdcdf368c84c7106f9c9f9616b8d1c09d0de3cd6ac40e87eb29fe8de07835431fc9537c81c74dd786d6ee977c6426b1d761d6574fccd7da5cc5dd8e90c5b2a8f4ae93f2acc70225fc779067afbdd5131b1ad68cd2468e0811e7c94e0497a24e504f8845c4167103a1af12b606c565fb3fa77ee5c3274329b824f65dea557e6c09c1acd5782987507039f68426e4bb13518b79dedf2c0fc409f7de83dda5b186403ce751ab278c87c2b21511bb73448002e0bb88e260ca3473a43928ca034376f197f96b6785fc6e75040ba27c7ed3e9644496744bd1c65286ebf43bff5ee965429decd508c7aed10fb2ccb8b8d6933efe8e154bd05e477147930c34f90087f8ba6983c5f06d8f2a8e7888587bf3c34d103ff7047347c9de2f601b813713b65dfb977b2e21a44cf8a298b58d696d24909d7639cf62d8819f6eed0c6fb6c643d06fc3503f47fb231a1c3ea98aaa33c404ed16ff391a5ed1a39e30ca1b39089df299ca455877e4a1ee88a38cc08ecea890f60a92d6ac6ee53a319b137b8ff336a3f2298add4b30cc2c7881bd1dcee89fe4638688510916027890f3d354b37784ac134630679750f64d89bcacc9f4f4edaf2fce3752cd9b890f0687348927ead952e47bc33cb615a5c9f7c9f390478023933ea6bbd996501c6e7b89af27d74308b06e8de7fa1551e9f0a1cc653f3b5328d2427349bb79290cda188935ad7a934fe6257d31e58388c9f3800d4c9dd6305eceff6666ddfb21c964db2b10035464145a2a5689eba2157ebd0c04c98ab0e050efc1e856958af61ae71701e7acd86839315ca9b51ba509e194f46717cbfb2a8d3a880ee0d3a2e82a7cc0465c7d255ac4d3293ade3668e46efa640e0c244176f543b05d793bca6f60bb031448e93eb23b6ba3f2b462e7302f82866596c8251401a0c101fde92cf6ed32c9d08273828503102acedeee72ada9599bb60558eaed1f481329eb2fc08ead23aced7fb46295b79e71de864e17bc46945354540c5b065c72090adae9da7643c628d5b90fa5320adaef10751447b53e199baa9727c75b28b45bf176604eced7ef5b42829a8275cfed1299eb1e0ebe3273251eb10ee08acd3c1ada72d526a743970a0d4b51b2b1bf6adac8c41898f27804c501c20b5546f5ccbfec3a103872d93c4613a8a78566119448b8c6889065daedf18e3cf87f063ccc89eb9c52f3441c50802d832409a8131438684236ad9e42c0a2327a5a558bd033e810c253002d53d422b44948ac07ab5a92fa542d767566c539fe89102e7f1a2eedfb02f6656e35bdafbbe6e588b92b77a2af34aa9b8118b5c17f0967c04fd0459f78f9ebfa87440a7ac539e5de319ce7282046a047bb5e7d5fc243fd2d149b68e27f75dac8c12c749bb9fc7a95c5dfa97fc8660a98ecd521f2bfbc92b3b9346c366cc348c1a87d7dae5a53fda6054409e0084934aaefa1fe2d3c60767c94065181779c98115197432c4f25281c3cc190e25d2cccd27a92b394ad9ceb3cf6a53555ca7d81369e36591a79c86d357662da89b4c169b72ce84ad804db53337becf63819e0b6e0d95728e4d00c656973ceed38af1719da346d5fe4d08b512791257dc0301db3f636fd612c2ef8d15847a9d214d7e6f17c0950a905bb0af597780360c15841219dac7f58d169c20f4f27422b560c277f6c30bd63716c85ddb098a34e4b4bb794d295166e0e43e5194cb06fd442bb635a0b785609d425a1c55b34d2b76b713e35e56f1527555ab12053907a5fbd489458ad260f480f5f1dcfe367e386c6b3cc8accc494b044d37eed1bf24c8b9768391e8829868f14823ad9ac542ce029e6b4ec76c246390766c86fe64c1056012388400", .None}, + {.Pow, "52196e96de7915f48ee4bb54f60b85da79ff064476aed3c7bf4bb0e16b1ab65239ffdef701967e50f019de7993ba2ae1bcbb33342eca293dfdf0e1f049cab6eba40c942933991146e32329e93beeddcc98c67e268e5b7938c92aae5380c05f8727690231ef8eb229638af927f1938f8ffaab1ef7c48dba26f9f68730dd0b4a164e847c6f9b1c59a62bf5d33330f4f6a05529cd02b1c", "a", "c1122e8caecb205efdd18d103753661d57fc4a96205a1d11c0acb6fe6427234b6b501640c0a4b4b06a7d4859f2a41965deb1afd4410755160b35b895724e723c0615c4e8e8b962316709786a54fd6b2cba3b894b8bf59e61119250e7a3e88e3b114266335f0346174f00777760d94d2eef48ef9e0c59eec94fa749cd154e1e34fd29da687d456c123e54e3e4dd8cff320ceb86c7f8f9f5b9702445d5bd48c2a693e4c6975bd64e63794686f26410d52ff232731aa0e50ca96ac62dcd6182a0712f46130c1480e44d88fa7c9f4ac89398cbc0d441de1bc2dc4427ec9f44daaf1631ab3780c8f20216940de33434ec0dbf3d3b48e92d6a14552cf2445464c9993aa34fda235aff6b34c27514c4bbd37f6cca9951d1dec3545e4889cd861e896f50d425bae85d5c628cd43bb2e2c5d9ed878af1a5863339f057f68216bda00a88d1fc7f8e9890618bd467d427c4434ce50dfa38a01a2f2e628aa3494feeb91518f37f6415dd9274d65d61a618ec5576f97f00535ef6919cd15f3f5f94bc8305b3b23f82eb69bcaa328a08bc5f54d2be5ab9190226e1ecc8728452950436932793d1ece4c8bb9eb832a8f50933fa3cd7017ebd07201386db9963d0b1cf06b7d54a884256d38443f7d7185b6d3502dbe95b262467586c75fc6d463411b6794c628bcfd2f521776fa12bd69057aac39c4d27db0919ea426919f8450c0954367bbb11320b3d079db409044a260daed9e644dcb619d1583621fcc071c1643b596bcea392fbff0440e6c079d148952debd2c4bf4a58767f9901e3c9f3e383a0d84e61ec1bfd95a8259186f7a5f044830a2a20112679dd43261d8558b66677c042e127ca5d7059a1bf2abab3ed08f8e0140be030314c7cdeae640ef1ebc6a67e60923d0619f42da483f4e09ee4cfb81c5a0098b12a5a2799d4e0597160b17b63f6bd0859a9d8ffc915ef0899d8505f0d6cd08701fbb5d71c4e02ea7676642980c23a539fce05527292de5e187580079b74abb57cf93ebdf50c19a3c5f4a1754533c6c70618605f511b2fd597ac1befbcaa2586059324d732cf8d62a09bf7905d130f2e481fc50234f131993afe9f20ddc2ead9ce4b730902dff4ab6decfbdda7bae05c04f264660b546a5bfe68b562da7ebf6a142b5fb8d74a74630778cd46741401450ac3717011ec4638eba912f5917c114cdc43795a3bb691c916bc142701f1f04384e23568459e7d5787061d78a44eb21b3dfdf65ff73fc83ed7cdc555af7f305c912307803b3cafbdeae881e15c1a6efcaf7254ec74b49fc9f26d48cb3a03861d3cbd2ebbbf6efe8ae448a779685d590b937bd9598c34ccc9285ed7d5d890c795a4e01df99e8e529c9c3ffaeaa61b505f5c5da38da6f58d50afff0b144d3c66aeb8da4288e2321d90cb8582b5c2c86eef0d59f3680bdef31a6802a94715e3525a5b4a04d88e1636559041ff15e99eec8db3baa60148374b39784e83ac90cf3067775ca10a6e7d9081637d0e23a452ce00148123a8ec1723ae5361316e659ab3e96555769e84e1d21ca75dc705ffd2a2cc116a0b0a49cf95165dd668acaddd42c8d43010bcf6bd37e77c1aed23e54e7e5de34fa6631dbe18db01a127a397d45abdcb4f8e3c741f5d08b690ca69e001ef61f515ed440478fe79bfd72c463812770f94b49a420377a06054fd86d14d02535a2547c3b6f0bda4cf175c06c6f6058adbbeef1c12acb7b26e905ac327e0de664bc97238e920509eba676bfb1425284d74c325072ca3527870cef3502fb3a72665ce266e1951860d8abd7ff9401d27c477ff02c54c8298a9b9a2b758a332569119d10934114018dbe7bcc28959d170fce09a8b675c811073227507bfcbed92196407ba0aa9edb14d47f924dcd5450531d6391fb3017b5886edeb98505bb1c815e3c043da87ed0801d7e54b9596cd8cf73e9d1aad2a34ede303495e567904312f522fb89f31e614950597d70c45c4aa4304149a69c16765cc11c17c2089145fa196c97a509123ab856fb6012d986d7b7e9c09abc9b22bcc17883fd25b17ff7ad171316255f385b5dfcc2a84d0f6241df839136122165c431dce190b01c7dcd2804ee88acdb7100000", .None}, + {.Pow, "-824e9400addafa1817f49e296c5dc6551792b34844b1562c252fb40b62e32f83d30e1b947573624b3e932f4132ae0790c31eb097038cb098a94282bd91669f0c0ee44d7914ca469e9b462f41d193ec24ab1c164c7469a092eebaae402c23126ae8812882fc0f81d07ff101df673c1c1e7b016d8789abf4de1c53a04d29cc41605899b2d8bf144d49d40d5131d4d9468b2fa004941e75", "7", "-24431a14fe16ccdfcbc8925823e086436ab8a38a1ef06ba131a5ac8e769ae0e75a85563e2b3dca1557daebc0f81c8556d67f53e648cc33f0eb816231b0ac0abc0d7f1ecc0dce886f00b6690df38e23b896e9c5caec4b2236e77abd7f37bdc2c1d13d81bbf595b4a7c5292fe73d9f0ada5313de2b9bf6f12e92d1cbf38ad8293153c573314dc3864758c6d3a51ec654a4d5dd533a01b3b7022afc4e4fd1cf43bfc1190c008fb53fc4e479dddefccfae71f4b6cef5d77336076311e2c63a1facc3ce7de166e1476449fb49d250ee1633b34cafb38ffdd86d807dee33e2b4f8d5f992332c960732e6e7aa832c5c4d721fa6060be9ee1d87c4ab0a3c82c06ecbb1754187a4473af863ec91fb373cbf7360f3bc753197c7721740b08a712ee95eeeb71e8482bb65be1c785aa79d8b671b390e5ebdf75522ab92c6466ad76efa0a93d219c35653b6c9c51b6c859f0cd6f42de916f2c825895988f93462e33cf4f6317351950732217a09ad0df8e737938f396d7742fcd9ee6f174a0b55963d98ca533e7a2308e821cb36519b426692cf73c14d964b7b81b157e33c19f651524bc10da7f64d309f1adb2a54e4f7e99175e6fe46f88976ca6fade65bc74d25b7f44ee233453a6590a1257c6fb880d913da998172a6544c58eabdec5bf9e7cb78b0da9672610968c215331a9e0a265102809150247a6b1a8c5e0eeff23f8da085ccfe6abf3db3070b1b83be8bcfd13e63eda970f7638780d71823601491492814c200c3691cb7071b2256e7327ec48e84e132d064d4d0cde4eee10e1f2a4cf5859e332fb616bd018cb915a629201bbea77659320d5de43c392d8cb17950eded99f1c52b6f5a42a86850be85d979fc1bbb6b97cd2f0ef71ffc305988edc7358fef5eb7c3f735bc92d7eaa68f23df5171cf593f8e0f5620b029832b89d852b2fa79e3ab314723d2983cc8c408a79bfcc1aee907ddb59a2d04fe02ac923fb4d0c05c90c052b6cf865e61c668a2c28aca33f098d1f38a2272fd093fb8959b4af0777d074eb33a31639dc71e52eb692cd80ac3eea01afa0a795a05b81e5fac4dab01812f9ec676ac7a7865ff941cbf349a713f777b0491524f398519dda0e7c3ecdd5ec3e449ba8d2d98d200a913619cd7ac7186989009703e8219f9dcd71b42faa581a212f4c8c20f0d428689eb86da0f8c5b402b58e5c1fd0d566d4a70fb7f5264c86e0bc5b355cf7a5404015c1c53d5a2003f56113d779a3ba644725be4450b50b1284825ad5c5c14ce1e514f33ff81790c650ecb3610db7ff975eb3cdb5ced22979a80ff2a2269b29a4d2ad07db10c7eaf4db6792fb828d275cd616aa2c09dd8ca0916edf6e3eca5afa1d408caa558b465e3e9047610a5014a027c8202af15a56a8f204bb4563590b7a2bc237b70f386810b0845851fdaa6b07cccd57044403dd517ca98ff5c3ed5a7ba0fd3595044f183c7b7083addd2e4f74d3675517bd", .None}, + {.Pow, "-316664412f2732f074bd003d3a71ee72ee28d0985db924eafc5238668fa90d8c96c1febad8f75b1e0fefe6a51a792c6cc8ec29151a90066aec20906c4e3ce6c1e82185a495f8298a7d9362586cdff8517c44ad9ff7ba5b5e99cfe117ca35739503c1e7145d9946a8f4fedfaebe4083cfcf985a5559e8d065a4227bc31bb2666ebba387c5fa941d44c102acaecdb7875bd808be50e05b", "7", "-a728689b9448eece348d06d2c3f3d0a2589bcc2240acf99a9a5ddb68308966237e411f6078f9149b684fd67cf4a25c36513ee17ab6b82573dc3e63a34ed6cfaab8ff713617949c519330bafb1fa6991bd0df6a64192d5c5a7e0a6f3db3655a64b6c8372a4189f8e8f4c741a8da3fda18b46b624aff6c7d0ebc04abfb9bd59f3837f00a25f73af7612cb7e8c73d2f9e35cc6c1d36c266413f263130c2f60db17f1c0dcc63b32f8c2d0a476d1d3a7c9927d049716b5ac2252e00550f4b544125ee7e4a643678ce4691c60c4049fa7687c875b73e4d4f1cd7e6047a30e8cd21d657c9112584ec194e0721e4b6f3344d1126e6d7fe299f1a9f0ab09bd0b4c0ceb798d40bee5f6025b4008febce1d4149b4981d29ed2ac9c5abe84d8501f060e10a6fdd54ff545ac0403a1e49c99955bff360c10822d7eab459b69d7084f8ddab9b164ef7ad27f135c50dc09fae46ce61934798e86eca2d5a1153ef7ea229a46fd16e4f8c62ebf15cd1d13a568f73e23674b1934709ccce9a90e50cc7cd3ab5108504a71b62180ccbe1e4bcea710a8de44f72c293cf9005c7ce4cde3d4e640b067de29f7e8615096f9b398d66dc59045503cd1c46d34d41bdafbe3582904d81183ac64565e405de133075fd83b31d4b3b3a08e8de72daf8b8d82e47c681f9ec708c1fb84f6e3be621b17683d30b52ef3043b04cb0ed97dcf6ecdc19086a5cc0f16b2863ba88f4dbc2b86ea472c6304e6ba0f37e55f97149c6d7634bfbe20c9d2a526f54a7df2fcadc2f2e2599012278dfa908331de281dd5da0ecaa3c55a44a345c4a621eeade9a6ba9ea9a920f7cb9d6ad066fed2ede50977e4c7920903f06ea58d85a528bb0bd464a218ea509b6c75cdf5f199b7a498fd5110ab61bd51639059f26530ae4f31c259964c38664b0158c55f7849ef2d3450ccc974aa506746d055f0893dabed524a67598b2cf95480d9801910dfc77b5a22405681e50159eb2833a641b278351ee16f527479fb6db9c7d336b22660c2dcc6e84951e9352fb29e3c83524e14643a1c1201dfdabede1f5a47e9f9b0b60504f08b92f3061f31557526984d97722c6487705d818bb7da6e722b32344ed942ca5b2a525e9cc7ead5e104442fdfef920cea8d9e6befa382dabd0326e0adeeec8aa5610563fad8f6f2af90d065b1bf50690ef3f35ab1db4583250733ffc05d04ecaac405d3bc576a44ec78d2285fb8f202d721d6124c29ed6742fd480b041d97a5424e1c3050954fe198cdc0623ef1fc5ed45e6126a47b3e54c498721ff3cf96d22bab7c1f776ecd79884b54fcf5343e952b664ad169c39aefef0877d312f4fb054f1c7257ed465c74cc6c2e1441fb04e1108593b0644bfcb8eb511397aee384eaea2bde151aa9c964890b70c3be5dc304f4202c7bc0aabbd9a69b87ab8a2683e85698c74a081aa853dd3b5d723e13a8cae25fa2beb7877368144f8dc69f4f908bc522273", .None}, + {.Pow, "-106e7657554c4d87feea332fec11b79d4a5e9f649417bf5caee357a937d041285c24fccbb2eb6590c1ae4217899a2a2ebbadcecf93a33b3375162ef8111f436588df33075a53050b9843171ba6e3c8799a2137dea4c21bd478107eab874a265f22c59c955d90df53827c67b7e0d26c1d3fee0f11c91597cbf442555c9ad0ad175ba131359e364bbd6e76bfd6435dd8fdb17a6670859b", "9", "-14546ec57de86ce49b6376464ab7b721c7febb9d542cddfcb392b970c7bf218407942e29111ef53624b7d368da76dfbc2eede1a60d5bde678675ec36e7cea566d6ad6e326320e944c34e3f4cf25579d0b2ed1ba570a8350a864956afcc62cece57cf0fa8cdd4a9f09f38a4eeecfaaa5ce1a2911595af140bf26613ed19533e5c5f9b6c6b07b519e3bd17f4ff035ea31e419bf3240854345537582fd4bd5554fa662e134d6cd9951a909e9af04b0fac3af0fc84000651435423913edca6820142fe5aea3c9a6cb3bee24b12f7e5473babdfbeb1f7c94d4f21196aac3e6213291069273ecb7cbde8e46b4a867579d76cf418f731d0fff6a0f5a756690f9d1c0e1e16625c9483226f2da86a39ff10fa0968f217d4740520634ace0b79dd4ccd1e91dff940ba592c8d6c1b2dc014dd92c4d5161eeb445442031a60965759da514b6a3cd756c4add9c6a27fc711efeb6103830ad61be18f1a6f53235718ef2a8e74926bb5e2681ee1b3204b31c4059a1f7f490c5d1d4d9f14b2d7aaefa0153fcb984144ace03d3d6e62c41069191fea846daab01e250836fc96b3147a2fb09d8c0917d63ec4f75fdb66c20dba92d4a2ed6375406125c2ba95030e3d0b7172ac6f36495411fd0434206ec992c6f4c690e3d82b3877120b146695e07e6a29467131316db2bbaf2cbbff1fe1145f618dd6c7dfabc7eee93803bec1e3eaf4037eebc6e44365a60c0589af66040789a4d701c42c9c8176e188efd3518bf3bb0febf68439393c54679cff8314ed62fd74ad152218ba27d590dd61a242bcbf03fbfc62d1358f4c911f3f6e48315b40b25a6becb47fc186fb8d4839f4b0519152b703d62732247ede7593dd5444e82affa3368aa640dbeb9dc7ab286993c2e0abc3d7d8f62fb6910c936fa8dcd8315522b3a15c965e42a93d4b546cef2467451aa93ad287dbb0d9a493cecd1c1ad4f9f105b2b66ca874c42bc91a72aa2b8e42da229c4246bf41d697a330315ae6bb8dcec1dbbe697cab6d6541df92d5e522c1bea8f1c3617a49e9a5dd299a82e13c6263df2975ce6eafd44860ec5dbd32403e888fda784734dbb60f9d8427ce79ff949ce07e9ed6b2a7bbab1712ed0740746ba86eb80235257b30f52e1b1f20cc2c2679a4f02ae91700c8efeed14861aaa879e3bd73a81f5813b15f6b4431fd03b16311468b39b1e09d49ec4d88435f851a63cb7830cf713b6fc179ba367837c40d9b7be7eb3630efa53ff1fdd6aa1b251fe59f368dbff6a81b72214c6437fb89c058a33b7a1851c1a1b5cccf0a1c8fa3f39615dc959e1003741432bbdcbafe6c9cf2a763005587741f8680370ab845ff761912bc233bce313b15986cc5400d87ac38dcb191dd3e66425d7c74e8b8b62e15c625dfd95afdaa831689ebb3e88449b6ba164a0bafd11e7e6c078612e39ee633847926409e60f344370615bdfe81d6ed2cbd9ede96d449e3af6de548ea36d849e60c30f2884a94faeb8437037fc8615230e6b80cbd1194a785d306421ab12225216de4862091a2b4f43538a4303534cb08d9b3138e985a03f927a037901be49026dde5e6c6ee9e309383c2602dad6bd56ca75c287c626db6edbd23b22a2cf6018410648d084ff3bb8d0a956fa1a1f9ccc84cc0a59b8c74a89bf9a203db4ccc59f94b374b73b01a6a3695409338abb9f140cc65c334e5669ccff3f89d87950ad03c2d3d6223053ad08310bd596b8db235c490c06dc22e0f08108eaf39608e2407769c271f6a214d20bfa2d7d7713098da5f73e02c520cdc3404c1c647410afa9acf081eb5542517006ed2ba83968c8fe9312cc37acbc1e890314ae3cf1beca207db06bb36ff02d10c6d987d94af78f264cf17013ec7907335bbfb744c9ee6cd17c864abc6ff33e39e813b", .None}, + {.Pow, "-d031b9ccce4f2a9c228c4b5bd2a65a10a98f0c0f86ca8e0cae3292d4ca3ac5ec69be91a992fcd43da53d543b4101c34c5c5c9e454d8bd1c6955c238750152fd76adfa7b5a83fe6e558d5e206cfe569543adc3b2604afecfd5274a2fe2fb0d0247b2a897477a34e82e57b38b04f187bb5f67b0250f9fd033294f8760733cd7f42515f195ebe227e4c9f0ce76141c84499ff1f34096495", "5", "-5b125e7d568c17a7939f205d2d848f4f8597abf9ef54c55ecc57ef9b33e8d623b387df15e6b35bdf16a5adf5c9326bcb2f495113e54bc3b72e029befd246f55bbff7e3cd4bc4a0bf5dffc1ced2f4220cd61a3a196f0cee307b0583f48fead6c5738e6b8d0bb4cb33e7a79d7528be6bdb4a5a9d32476f2d1fb8141d38a688e3d484d2ff95f9d3e7b6ce457988131b74fb9542429f84bdb1e41aeddc9753ab195a4805799bc9721030f7157aa8c2b98c7911723f3ae44ac12030a8026e0c7d3767d7ac170d28db90ad5e6e8d786ab1ba05c3cf9ebe860f436ec8fa52ba7a4bc01ff4b5fe4eec862d32cdd437eea87aa86545879336e5582381ab6ed983a7a77417133ed51f818f36ad3ccea329151b1da65dfe7822ed857a25c1f21ebf389b1554827bf96b843b22ad0edbf774e5fea4779eabe5df341ef76d601dc54409973a3ae005f5a1c10052d5f5c4edcecacf9fa11cc0989869f0257a2e348146838feed099c7a102a55f50c975984e66d38b9ea63cee4b5dc96ba21209b232fe0b70b2a7ec67ba782c7affd9320841ebd14134fcc3c36f84a83f0b08037b9124d9bacfe9f3a1b73bbf643fb3bfc587a923105c0bbd2744f280115c6703e72a807dc431acb26cf2f66c9d93fa168e9c7b2d2a1bfa613b327a2e799491d1347b5461af81007726bfe382a688357d951c7aaf3c3a6fac0e1b5f9cbd2075d495abe50cb99d44e1cb87eb70580765f358b88e56d316ac75818bd7efbe0afda10e6a514e07d127b1f62764227c50b7ed9ce47dbea216fa0ad72f2fdf0876532819eef802e878a681527bd275bf094dfa7ce6bf9907cf3e0f95da95914c25d456f5ab73791d79dd6d23af0c33d0c7e2d2dacf248e9383c4cee44f4717b6e75d0db7dd4f01c1c56ba24b74ff1e1d761aec394838f7333cd7e4bc9403ee199be7f8dc8d3eee61c08bfa1d9b61eb681967e8efc55458990a0ac9b400dc01837d9e6962912e337e43180e89e0473b79dc328d8be74d5957b2133834768faca639d27a0cb6817974e4db4f42b10a980f8389691bfd24c005", .None}, + {.Pow, "-7037330e4ec6b192efe28f2992f706a5e2350775243f75e4f1ed148ad3c842d3758597ff017b41dc7c4cc1c7fcbf2f305daa8c1aa73cbcb08cada1d704cd6d20eb1c5b274dc77081ced2eb360ab60b9d0b0b9c7d675171dc6e04f73ae26a81ba789d0bee3f9b5f9117abc7c19c67b87de84a580c917edb1efa379d8dcfcf455535e42576f2531b154b440b2820ee7b27d6d0c34e1e52", "a", "1129eefce510ddee3a9b9154f68e379e1374caba940fa36ca4268a25b94097939b9e7edbd80071c4660ab00184a49bd5aa5361869021eb0542c31aaa303c9b71630be7afcac75152fbbfb9b8e634418a07fa95023078ed3d93650a4a50399170f35eadc3f122baf99570a25b7cada47e192f143aa5d8893945c6fd9bd5d12a3ec314de9faca820453f9433cf2ffccce9e5571d5829bc8502cae9409826eac42590f82022ddb3c9b4a029bd13eed29fcf701bfe018b3e2d34b1c5e7c7b1dcd0d6b18512e65a97523fcb0359fd495f7039a733ebd4af532b91eec82e70f1f6f8897066539344b326b6cc80db4a6bfa5a41b9abbe3fa8265c52faf5a56e26d9961e39b49323839872a8c60e499cca77f65d18b7cab95bcb3b889fa8d65a21eed7cfcdb4229da2059211d429a7fb0ab1c4f4a13b1059acc29ea8b3f56891c177988486be5e09c4513e6922f1beec51ac418d4ac50753d4efdf800fed843950d56ce72b7d129763e5f19a6f4a5f5214a4241e26d093bc8f409e6ccb45bb63ab49f14f335b086fec2478b6630ef92df2ab124369d63010d9e86f1f7b95d375817231c5b9b23dabfb8c23b279b6918381389624cb8798c967df8661946751661b27a7627873b2249e866defe68e12011b59bc479eeb8cc42305b6a47829eff104e90868b951eaf8707bb7ab373a5e0f7e86a95232b8af2fa55147fc9c11806d25c7530211a2b658e594df1a55452c3ad026e8e19489f16320161cd3058ca0bca3debba259ada2c4b0fd241ea4eaa1f755c62587fa02e43e823bc066c4591377ac6e61d692dda41f1cb8ff02fcd72fca0f4f5cbefbed95cf7c69ee52e58ab7593f41f000ce73530c5378a8f7a166bb7faeda8d6cd6dddb4d0e4c82758b6d029ec36098359372d826d4fdf004af06d213d8d5c62f5c6305f4ff49f8b64b9d13e827225b65cd871d45df6ac3482cc21bb40b66360e39f01482df01bb5c2e2c2ee8b9c9b9d722f398f7774be86166b750717bf5847cddacbab8fbc517216cbbff9d7569a35d13413bc83a1502d4b3eee09184a644de7038df3507eca3e8c7feca657f2777b364d03a29dcc9d62b0c577f68bc10280621e38b932e51021698e9c0e3c4bd9abf5cad0e69bb548bdd3ecb8cc5263cf79e16e0643f23952e4f0ad31002a0285d3dc04986883433b0b75aa8f2fad732b39017d35301cc6d67249c79affb5155b9a7e3050cf0bbc596444d1fce47591f632eb35d866d711a88430a027837e4a3640ca5f0521a1c4ed5d63c0c71b19d8cf0ac31a00983c90b1def68e81ad4f2aa27e405ab9f6b8c782a08e3fd017b269d56a768ee01b916e99be9f47a95e6a604c0b726eb17f106dba36fb13c02a836062556194c976db672c56be8ea3ee587fe07adf1493901f0a157d46c185b1c3460792bd9c68ec43e36102906d525ee9a8ec0577416b94da078d0dc79c10a894815b14d643a7b02cba4439e14e4784b96358b1b99f1e568ac78e75552bf121b3732a0cec5ebcc9b7e7cfa9d4e9818f876bb56c20ff7915e04d0252e7a901dc5972c512f9c3c9b3adbcd9855a3c739cafe6ede71bc1a25fe59b3ff2ced16578f8f3c5625b1ace12a6d075922dc5bcce1700bd385f0d76676aab04ce7bf4e8e6cfc74eb765c5461edb9621cce74ec1517185095e65ffe0aa1a72a77f696c93d76722a40389db1a9c1a595331d9c529cfff9571d8a1e660ff9da905f5e83cb7341b3f404756a19a28d8363a978ea7ed2be8b199c28af4c53f26b74c34b59a390ef93dcb8232f1afacc5772cad5a2c3101f597e17ac6c1e9cd3dac2904f3d5298efb1cf3bcf2210712ae8d2f10da1409e98fa73c86fa1a05b0907080ac6d58977ee5a8a66eea9c8052f092b9ed0bbd83c6e2d95ba5e32e8217bcebe6a6f60a8e4c51758997e0fe98bb11cb6087ce8b4edd6021e603c394269f8a6cb9d951c5511f70a462986d1ec961292e461cc0b879cedbf28548ee321efd15070f1ddbf72f87d07a9ffb81d7cbf795d92d1c5e23ea9d697a9486b33e9d5614a894328158381844304a4ffaf612773bc5cb40beadff601f4fd808f734fc6d254ac211b50ee78f835845477f76305f19978e1efc34400", .None}, + {.Pow, "1faa4351fa9859bbdf528dd8f83cbddf785c0f2e04378582e83b2cc557e31b4423a220c59a968e287535a718688aaf89ff8787aa9ab44f8b0843cfd0d4eca72192a1bb4ec3eab515705dda79afd7f21eee38374363d83376f6c949eed20209d6e1079fbda7ac78930d51ef34eb852ab3e0d81422e15863f36b83254a205f9e661f2485049fa25864aedcc5900e7a8b45b3eefb73a617", "7", "76e96fd575e6d8d54670e4433371a2f3238b49f0fd8411fb01a95472a100df492ede19661fce6658639a233c8bdfebc46ffe8714ea251e019ac4a830d170121fb7e3d6e8cffeed0dc36b75812bade55adc46faa7a14e618813aa00e7a1db7a3ae0d135666e16e438249fe45e61330a3c02f997ee9430fde4cf42a89f6a1bf844e2e9b4181aaee0ac6db04e5f2d4b055a42896991f426a8c8c794421e2e9193f9a738a543183d90be87a7eb65d5e302dd9bd3d530f8a60cb55f3cadc129742dc657b9adc2c5cf93ceddcfa612c89a37bf0c6dc5d417e91f86b320427735f523062c4e90b2d060df6a548b5b22acc660291d872ccf194e0e815a2ee4a33dabab4c4a848a7a263ada47906483223e7a82a261cedfb7dfbf3f965536f1397ad9442b1368ec6600e8b9247f71302d1cc67054b5f9ae8ff1598b0fcb40018409f013252aed8663463fa78c403e1618821bdfb805372e6cd80acbf612369ac25d189e5770fe258f90400687fcd6914fc897c77545b8f0440b86e1dc7c22f63eba3555a2599a16fb527de9b430fc5f4da5059ef45725f6cf9954bae035bfdd6778809dd5b3a24c89acd5ad2d3d4f7915428e76fc86e595fb92b23f4eca123d7f7a7fd963cc36f94e22c9b55ec5a016d1377970d32698b75888ae2c6f16841ee3d9dc2d3de4392fca03df7eb0d8931192c15108065ffe16a6de57dafcbfd7c4af106936b0a0076dd3296103eff049e8d2c5b7e19a1d4c6328b7976c1b6d4b11eeef053ba73652c1509cc35a3f819c7a6a3bbe8347499e1b2fd4daa1ddba654ed257293e31ecc9f376c5ac942b14a61b8ce658b853bd7a760ab81e737f678ed3639703521478c9a2c0630a060529ae8d02d5134014fe8f5e544c37802be90a5e993723c2c375e7ec25f56cc5e607955b0389c168002aa8cc77d249f8ee0bd4574119109829d0f534e36209bf2b8c60e1823a59c79ee2969caaeca9dba23818e17d297ce492fd764fce7efca7369356816bed569498bd121016ea40cf1927656218e07878afcdc9ddbb8ea0aee3623848983851fbc5e42b6453daa37e134b056619bc23182081d83198b326a8dee7bdf695713613d81fb3ac576ca94c6ea83aa3941ef777a083fb1b3d86bac1894f498bce0435c80fe3f439e972c3da2105ee28a0af8fb0e309f8764476e47d3691ae243eba6a28d44a914464a1bf0b9b3ea52a059d768fc51e8dae3c048b78a7d7c9bb0f4b4ee2087d1c8d6014a401a7ec70c48f1c296f4dd85377330afc66e04e3514ef2ceb562e3d6b55285a609950ceb4d974a586627ca39eb04959188ede74b24173468f04bb7b56d92874dad9611c272ab1a4e09568ec49aa6cc2947c40325cd4f47b92000aad840c98bfc84475db283718d2744db0007b5a8091c1c0cfcbbef009c26df410abd0575e6db4dd14ebdf4d26d24d4e5959ced266a294349d79b5b9d81efc2b2eb1d8f1b90caed67", .None}, + {.Pow, "a4cd02610550b69281298498ca4c2f2b5b24d8d3f6d509a559ea332898a554335978fd8036c1a8bfde9caf89162951d017a5aa51fd53c074a2dcc08fb1226d7c80b58857100b9cad6f39def47a27366bc5662c09fee82e9466f45f8c1c0b2025862cbde364aede8d128d388b74533834800695ea4d3f1404c84f9ac8598723856bc4aa6e8cae218538dafa772da54a425ab83225b63f", "8", "78d03b3a55412b4915a0f9dbc6e7d40799eb66fb001987944cc88397c046ec37a58be1a13784589a24b896758b72341246f5dcbff2ad33c0b1ad42ac16853fc8a048178496fc9250cf078e8d0418eb2a589297f5db4a0451c5c6ec3ab702a132e4959cb932af07d10f204d278f3394754a9d1d7a80b782713434b8ac64eeb56a3c0fffa0a35d4ba67d670a5c8402e87d34b574f18358270d11c036e42909aea95e66ec7d68cf50db8f40194c5b3ea6507626fd471ea05e71ee4f9a6a464cf6869ef196a90ddfdc9a4e56adc4098b1a81b7c4aa1f6adeba4759f70b47dbfdbc3750e3c5eccc48ed968c5b6a55e62c306a4d2233aabd3cf169f7c098859db6c2a5b165b14a22a28a5788e8fcc3fc5b91381ac1c0c0fc0421da3a824aaeb88b6d106f7a6e7e9769cb6154d428bf15f288530d900b366d584dc058cdcf43b7fec1791970b79edc2779e1b230bbffcce4d620e8580080fa82967e6924bbfa4c8e0ca2d2ab67b1ebcfa6204ea0c73bba8f363eacce4cb5ed1a89aa819411ec5fcd07f73b2acd1f501590b145a6d1353b963ac875869ea5315176475eb2841ca31f0236ba589b6f1773fa064bfc6a27190a9c93c32abec49ff9b014e5437bfbb3e5f522160968f01656bafb878436c1279347e801fb64800d5ffa65524259cb7a92379b40227877bb1aad04f16088367957f1da8b9dcf533f164463a8c702d36d614b808a6dea05225023648e0ed097bb7b44fb867cd3588de0095f1611f166a7f46dbbf02d1ecb81d0705d15b046d7358bfb58e8bb38a1947e5d9c54198e694751cd1d1ca55502f6849bc2d0ec2b5269b3d322d928a6a8cc4cc9a2dceac17de7404294f6a83ba76ea28a7c47a6e7229ee53b183847624e1f58ed1c2efba9f5335e86844cf6d49cc36c18b2ba0a76e702545edfe7bacd42a88899dd4cc59fa9b949c5bfc7ddf919d5172abddafa162e886ed23fb231d73443efdc38cabfe36874db8ef7e502f2f4526617f7557a9f9b0ec8a556c59b531d41a02298d73df16c6ad871b4a27abcf775924ce8fb87c08718e378f9c2246b6a47c138234b84d515f138b6ee00ad3fef1ecc62692787bec8e6c2aebcd2e5d287f641f34f204e8a8396e9fa380a8f5bb73c91f08d093d449c859e6b3233670fff54012f5390551455f1502fda0f76c3960e478e5a5a04b4e23d9436337dfa4c712fdb36e13c1b72fba61c7f63dee363f440171539bcbedf53032f18d67cb69f12fd0ac2309969692d04ff7de1743cbbaa54008a0e4d93b94884041ea99554fe6df7bd2c870db022c1cb426403f128da891c3bc91b71aa641c947e8f590353c3a7f0c593a33498ad8a89c4c427a43092c323a499e1f1032df300e1c5b0c57a0db9e37195f655ee5dc39f295195660f416754c07b28dfbb03b3ecd7b145542da3a0ec413899b61e59ef66a94e916d7c2cd0d6f5b0fd885a0add8c1064173d75ff9d404803ae572a8c70ac8167686852f7c57c4bda0f5b6a9013f76697289572f89e586cf7dfbc10a0bdad21a235d57f40eb6952f0c9c49f104e41ad2f1ba9ef7117ee4f3367c814d7d2c7c03a2229139af3f65a30c38ce16ebffc80c2462bbaaf4ad4f15e3eccb49333e1833cc389cbc0942c5703759ef22e5eee00e40fa7b922186f6aaca729cde3ae5a159830208bf1f0feb0be479300b5b9bd80e01", .None}, + {.Pow, "-9e3320a2ac2f1ccda35121aa6cb8677afdc2907663a48e1ed72b7d938d28dae9dc7af059b88eb328e7ac415ded09b78d62c410f61b55dc2a02700213ef6a5f6ac104fae7bdd651655891ad63d7950677d53364fc7e1e1144b6cb8e7e739cdac13b45fbbfc4e2966bb8e3d0dcf816751b37c22fafd7c4cee4498b07de0a8a1452ef6edd2e2da8d69caecd401bb7910d960016b68ffbcc", "3", "-3c69f81974a26cb2869801b51bb20784ba95e35a07626a9d522e5a34a2424a843e1dfee0136dd4f5b087a63927415261a70efd50a96edd8674276927ad0113eeba6ff947f5c18f671fe7201fe1c19c0948fb67528291108c46c2b74ca12c53584b11ef402848bbcad1926b8678f42e3d1d986fdf881faaec565b7d278ee53ee362a558485ff4919bf0ab7a87837b0928b93cf4b8852ebb95f58c1721f31d378b7da4b9ce6a6385d8af8d664f7e9f234fb754ad82ad9294fd0ed2b801e90a202e0ebfb2d6ee3cbb0e4f2ad07c7ff3af525e0564a1d5bdf15a2f9d723bc71c60e017d99ffe8cd756f0f55d53711e3b017677ad31f08f8a5aa73a3c10361b07a532810bde99bcd14b290b17e6234ed3fc1b9ac5cd8bb6afa1179a2477eadf862767601ba197c70a3c34bbf229d72a8c0333cfe4c73650296236a999f1393efba5ad9775e33fc03fe704c871df039f92b3315e61ca8e06a40636db647e7a6c9d3437549ab28c1f1f7be07032976206dfa3777ec90cdef46f60040d9b87960235ba9dfc91aa915f3473aa6d1d12f9fc01603a32c494230953d7b83159768695f5ce8b18a3e5da4838fade6adddd3eb18b596df21bbbed38af0d825467be2168b6a8bf1ac0", .None}, + {.Pow, "e5365cf9eea87cb8e2c181875fce10ab31953fa58697744f91719dc32dfa5ed8fa0bbd5c43ec3056aeb262018f786e87a13b2d732d790f86a0b3cb0fe7c30b70b825d4f6a8936a036a3c0644c797164362bcc8ca40af08a189094ad7329d2ca6930a44d9d24f41c78f135a92358b6917a5e4a73d4f3ddb854cf1505ceccecd8494045e4984d3ba676c5cc910a1a432d6a700dbf9ceea", "9", "5eac15d78d47baa363089b8952119bd60c230e19772650ce9adac67e446f669a977bd5f237a7275a5d73e0add9341bfdef82fc23644728676dfcd59f055d12819b96c3bd4d62e90cec001ebf31ed348ea6f47a720219665c8743d0f868c48e99766a20eb030a37dbb9863b0faf7e97f95000dc11a920f94a05868e5a70fa49d85527bca38eeb564815c48fe974346a98654211724ccface443962347598b6f0286e79d9f44675f56f45ebfd213b02c057513df8f142d5c1f17318f0a25792166706c2b271f5318d78b50ce26a2ba02fd773610a83b95ab0054a80ae48a4894479f55b4fd7fbce962964dd683672d0a9828d89e6cba08fcdea3404b768f03d932cb89befaf9de324e98813ba3c4743a5b183ec96ec6a5097f6c4156c2b929a94f20b9a110ed3eefa723949731e0f18f5d1bd28ef830c5b531cd6706488d198c4b22281309d2630a3c801e99da12816685bb66c9dc8c545fc1b1fcf3bf14e0f7b1294f81d9854e5a931ba842da6d931a8a6ea07f1596c87f85a3cf0abf1afef3de36a5f0654590688db3cf0ed1db707cf088c6eb65883f839dfb266d1949101b07fa74d9da9bc851b0d9b1508638cd877d14fc2f0f82f958054dd3dcd52a945a645d2827abda83245b6076763dd77f31cefdae20702406fec217d84f0df0a4f2ccc3f0b3d5cdcfb77c7d1bc4cdadfaa211c33d793f5194c5374d66cf9ffb22b4067bf4b5699547153af6c06efb88810a62665464e4b160797c6268848d818d060d53fb99671faee51f95f36df64388aae30f97d86ea3373c31896b697a395ddf453b91abd766fcc389891263bff8fa9df516beac774f3adfcccc7ab4fb3745b66917fbf53c785b9d0c81b9009ed563830713049a852c6d7f7eeb1809114e2e3fd45d456dea55974e7d59f22d9ccf811f227395b6d4918553269b7c8a94587e0736102a51ba93ada780b9cde8f78b6f456c693b95f9fe8c42bf8ba6e1b9ad20769fe172a087b640afbba76dcb0529b9c9ed6c557560a4ea6456b022c5d79f70d6eb0dd29dfc389fe1a152be4b830e659774303f744e0849e42d0d166738b1176e1701ef83e0212a10777e0a72bb6a48e0621dcd79acdaf6ac2e3f402581bdf9e4876b1e160a2308135dc1d52631b74b1c1a063238908e8f14fc16a47be98938a775b74006de049a283da052cd433f2eed7b3bd9521c38cbd72fc6b535117289e5d5ea7288a68cc576a23f3402449a1a6006973a33bd91c5558c27c43a438259d070b69f6224211d8b44c39e1d39acfefd77ab9a79ccf37e62dd3bdc28e2e3d7ba60dc3a30f557fa29fe79b8f182cd9cf32f0541d19fe55af61c01c5fcaa16734db918a0ad84187ae906a715fab50c0875472671bf064bcddbf21f642f79d22825a1f0295a6977b7254b638e365799102cacb89378c5983543b4b3046faf744c405f2450836f70a3af0898e5fb848259150982c0c0618259ed38b4cf1d28a567f0649629e41c8056d1016e7447560d62d305bbc699d143d0ae5dc02b721446df56c3eafc84325ffe30113390110275492a24e86cd907a7068e1288c27ace6a3698f7880af70b38e3795423fb35bf82945403ee1bdba7f5585f737e043e59834e6d405036b4e2b519ca45eeaf7a44fc1e968652c6ffa78bffc4847d81a7e45a5aa21eba2b104cf2ecb66cdbd08b2f6ca0157293c70101aee0c37ddb171fa9eedd4322cf5308db30afac9aa69bc3bc92464f73908ed61c3a6953322c212931ecc6dceeb036e966b0a63270b910acffdac450f544ecb9fe6faf732d2c97d70ee815ad59ee5b6b1a8772036c5f486e450deb13ae38723812815d7d2c6968408ffa13590f3a48d0ff6692895ef8ceac869c1eec7b246fad1e1493b1487d96442383ead2a148bd930caa00", .None}, + {.Pow, "-4c0467915263878b73af42b4ed69b9edda4007ace9ad01a50c50c468c0f1b1367d1e1a0fc1753c3bd324058945837f3e13fafadcd411a1257d1a10d027ee7a17ecf4cbf5c67d321e1e63fda193c80b3427e7fa7d82ce1d41eacee47125e3be68667dc72daaf1a614d3aebe650b7486f80ff6b87cee79ca67585030e490e4fc73ae9689f1ac17cd71e3131e3a862301f58f755846a225", "6", "2ced6bc47d5e3d36b8813ed5de2b853a9b3025aaf55798b3c90ddd1d8cfa0086baa3b9085eeeb4942e589a690199af5e367db57215ce557b1531a9b621bbd9cc239297d2058012a40f93452bf842bb892beacb2d12be8e64f5610b6ce200c8b74c983d445000411aba0356c534e10d20baaad6f8a7b963d5641d122b1b7c44e9ddef802cf30a034b05413459ffa03dd85d26a9c34b3f2a48c9159c2e00d1c10eb2dce724b3789018eed60705ba5ab6db00f32a638a02633051a328c258656cde71857ed329b1d3049b422d6daeea22378e8b60e62b517504cb69cc40b0e8dd80675831af94de8dba499baffc8f86c2856f9a19552cc738381ed9c8fd6f8c2b0c2ba639a79090cc101402b37ab910cb82e8b96407a10b09dcd1d3c737462bd28b2135e351901f3010b0053caec2998fee9ea129e3fb88fe0d596f2a90e9f1a04e167643bdfae1d1f0c5e5955a293fe4bcd1aef342c69b3a1a9e62f9c5042eed1af4c1b47163e549ac56fbfd3b6260f27bd8f89d60f859850a214f44ec6922dc751eca3723e0020910adff4d8eb5bb53cfd02d80a133173228f15702606183e6213a0a51afbcc2c25d1b430b7fa0fc82de2c99379d6e40c235640d03da7cad99ad0f63c0302ab05cae4bd596b33f95947f0c4121d8e7882bc8a51b0fbce3460944880f25eb5f27ddcffec044b25cb5b10ae468f06d8dd4b04a1f20bfeb7af5913a2166d5f370f5fb722af38399753c022c5cb315394d1266e8c73f074e5326fa1f06046084c1746914dc05b76b7a5e4e2c2ac5319402b0bee7705e042e30a3e87764f1c880fa3e7f46ff45a81abc0ef7b472236fdcbe8fac278ddd543a4a7b43a2d8988b6f2fca4217541ae51cd364ca7127811c2944fa5367b1bae6fcca48df653ddafeb95170e78a5021d712797f9e8314d9b10bdf0e9d3895023445cb988b889297eae8c8e3a1230678f9dab9af1e860a36dbad35fb5c7999a17cd659c703f9e0ecf9e5407afe83951e0e055280d557f5f794090757dda2db4e8743d911ea9dec98db2821bbe10385d49104ab5f45ed1d5adc9acdc0b691bdd675ce0b2806127b589e5ad050e412d695da26c50f236fd119d4df7bed989cf6989e465a205e89f0c64cb2437efadf57ff6c889ff64b71801ae567e0fa998edf2687b8ee6d19646944538bff259735b0fa256a7598ad11e17486160904b26d26533dff77c62c2278b5fbf4a28522a9bda23636ac1eba32f008ddc6ff750104f42f705f683231363e9cc9", .None}, + {.Pow, "-ef5a22e0aae7eb211d95e66232f05981da4d165413270ce749e82ffa70ff56a9c860bc2dfffd3278e05531336bc96058282b3ba38f62b30e702ce60cd0e56dba16ac58c9e39b29118f62b981c344485eec1ee9282aa42d1e540728dc248dc72647cf500b8847414f9f51851ba2a71b63cfb76982db50e037f3fcf0f0b63646282d1a8750293f47719893ff86c72c047d007ea38e07e9", "8", "957df71f012543ae9d068000800137ce5dce7e626b379ab6f3ecf4c0a1bc8adc2c3917ef733d6ff5d328ef0360d804cbad960a2de1b7f172e15f59a59d5daea59c18d4994287453d863f9e81d1181f70cfe31a71720ef72349568503728600bf3f4c4f6002001da984c77a9bfaf7cb3ecbfc6e6d5059a653d2573e52489c84f1cd6601a92ab8c0db5103d60ccc325cb889ff282fe25c4713951f5684519baad0b4020f6d7d1dac0ad6097fa195e3cf78d85f6adfa2c076255754068260b0c143857af1eea89a097088481fb6882310d41eafa88cc8573613fa8e2bf9b8001d6e823d65292b9099738d1de4b927945f64dd7343a0955b734bf142aa04c3e964b9712c656b4045b0afc5d60b7093eee2f7f84d5c3d2204af5a4f30fe36a35692e649eccda9ebbeac93c0cb5ae4c87a09c891fbda20748d119dde3248a0b61e434d15716703fd6caab6a7d10120b972f1eb09e78b8f768936334db6038be01f3855a13c55981ad523676321948d3dfd54824a6291c5f8c6076caad2dd12fe392b5bf1fc0d7681cfe14171952da7f7bfc98d74288e70eb2fb8180fbd63656aafbecd9f9a1d551cb0f50c85ea508d59eee232b12f68910b81089771f458f84b232a39baa64e0009d35c79069b1cedfa38126e7d26cc7dd76ca3b0039a67926e11f6e19ededca79f74912d44a46fa5b2776ab39ec098d0895e81fb1abaea843fa4c2c687d946b720a0b751cbf4760c520c5ab0f03bc98bc8e4852df8018cc7537f409f1f0d6f20863d24fc27ebfe9fb9019c8c243abc9bd92ebf0779b3a094d8fb523d0405c4ea61cd8b86fb047e88c4d3916790dadcdd772ee9c0fbdccdbb8d474add785acf26b5dfa450a85a9c992f7a99048f23cb9ba060a97d10ce030b45873ff4eee306e24c10068785ee49faca41dfddd2739e18161c8e39f3b99e4bc4c102d5c2dc9d6c3275955b65801959f7eb29932d30fe261be5d26a8af6b9b73d969e21ffaad47ac436f2515768d1f628d87f7289890c81c5679302418dd2cffc9000b97810a2b62847370be2ec245f1b7901a02cc5e1f0bd65a28eb98ad452ba170852ea7e421935ac949f9d6639f1a71fdc2bef235153de4c3aedcb7ed71e275748b141f221814c91961072cb61b664607b5df724c1f44b7e7d008b6efcb9c07ce7048d691fce272901aa67eff927fc0a40ba62ed139535538504d49d71c2f5c9f76ca6c76b08414af7a27cc334b28763c5f0feb36e0636a7a8c3bfc090f9eacadf76b70c41756fc47b31d058a3d845a6d06b61e21f62ac4754d761c07bbe229658aeb09307192cfd6dc109a788739ec6375da83a40eb998170419b4c3ba5748f828031dd3418d04f69b1dda1bd0d614534b7c5541b02184a05c799036064a231eaf6996b1334020bacd1bdeaed596a7bf96be610ebddee46af0f1e86d75156282f419bbb7cd21251578e1d56e09d1f5c288b83de982bfea4b70c22228058002bb2ede99b3bc45fef8aaa38a7b44d9223a71c0a9d1139cf05a1ca9c9b08069a78f69949a885d9ff9811434e5429036443460c3826d412029662faed86ee8b87f11768280cbc6bdc717c993b0eb11bd39dca5f15c611367a31db2c1c95481cc54575437d5551562e5b4775fa4972218408910d149398ee909285c21568a3620db094a4c78284457576779bf0f3465af0c90e41", .None}, + {.Pow, "f6dbb334bc2c50fefc0255982414e2a21017d8863237ed296cd99b283808b35585298488783ad5bb079eec1e58ea7df989f60f72a9bb8d3061b2585cf9868e8e8d2e38f634b7ad15c7fb06b23d811dc63f68f51bb7ecb413042bd18f03d9eb71d03cb4dee0a546def6050932c038832e0df51d6ff9f9bb8047b919e7a92dc010c3f98ec474357655e41a5a5b79ef33a26d83f900ed0d", "9", "b88c2e130ef83482fdb0101ae9c92893cce954216d72be3cee944c3d9f103f1ba3b97d05e6b89e667e8171c51031aa92fc50c6a30c06a63f61be6ddfaa4252245a2e30d0a06f84523cd53a8dd24256ba7f6ecb479e5001ecd8a44a5f1f7f0fb2788806e477e85b7200c0cfb31fe7df9bb4e4fc3a46aaf0b4929024086d5655ef13cba8b5a3cf3e6ec8c2023022a2e3f7ddb37ff5f20ef88a8b3c6314b9d58ac0999b19024518fdebfb5eac5c7fa910b03431ecf0352e32e41cc8723ccd335fb19032cb5896e6ee63b25f2b86e33e319bd4f18ce7514069f77878221a53f944a6d9b4acc3a4228f93e69d0564624396ab8c5a8cfe81e609175a78b8b5f7f4457617420156084c10ad49251195d45479625380b12b3ed99b155c36cc6d65a5b5f602982ffc80bfdd640a43861a7ef503b3b8f4981c7af21f5cf6e24a9bbd0b7e04d6312c6b1113d0cdddd87bdcef19f8e45aaa9f9613b7e8025cc288d71226a4824d3ac7164759d3a7d1cfa3d673750aa2a32214303ae2ba03f61b92b88da8728a2fae462d93ffa43b5e4e34506ad8156bebff33e8b6465c948418a38ccb44de414f114a513bde585e863491d3634286b55c9f5ccfd1b78fd0af5851115d5cfff8fb44fc40771e7982db8b1d251dc63ba282c49a16aca330e6fd35c6709723efffaa44422f6498ff49b0f443ce7968078edd38c26eaf9dfe258b31fb89d388ce1aa7758a100ac7c99340d6ea6bc923f809e7c6da77907eee52bf24751d84f7e464de6ebda2c578e9200fa24e8b501a26e38296148375c4f622da873ff4117f7d2d48d417cf4b54872e1d222c1bc24d323f0adaa60e71a5d80f5979f010ea22dca956233dc7876c0e8529d30d1d49eb5c09f41a028e0ae8e2352a72923d772b66bbde16e2fc0169c862c6259b5251720bfee0e38bd5a4bf70e320e8955a9527c92cf9224ff1d36aece2d7fb32fafc43c38d6796fc111a080aec77dac932378a5f06a4178cd903f6ae35bf7fae4b2a38af96cfd0bffa61b8f2fc5142328005b4154fd34cec32cd94ad42631384876432a84f3e75b82d5ee47bd1ea118ea3b3f9788f3acad7f5adc8f5a0ce64f4c02abf4472e3ecd45cbf6a1816df87fd6a3c3d29cdbe1c0f51cb9ab938c5d7b6f4277ffa4619cded437cfbfc77f1b33a1cdd5ab6e9a7f1835764f8af88b58eeda3016d4d2d66211d96ce98879dda3227896eb9d84f33321feea77ee35fe3bdf8780eb6065f59e18d5e8bd42bcc1e78a86ea4e39c1fd99039c28023498a829e967ce011f72562c1968c4f27d290d899ec1f81eac6859cd501d41ee637a1517e8535f4a50eb43c8b90bfddab719788cf012ffbc00a3f5b1f9f4fcfaf62efe0c347a773f044b004ca291c09b497f16f061f1ab2f879e1502ee76802eca624feeb9e498fc05f80b5197cb45fbdbb93432dafed84c5b1887b0f3b36addf394886644b5cdb0a29cc1900bbe57f07de11aa50704c6acab96fa03c6fcbab21db9ebf2f86845a65fd45265f62b93b7b86dabcded0affd02d077ce62cdfcbf5bbb1e341329cdc4ee60823625908ccce2eca79fb833b6b38dca27b2f1efbe4b4de2f41cd05f3c8d7c13920fa0856df41975d72161d4cb270ce42cfb84fcec8e82a3e161b9d5532509599d25034c3a993ddb24cbd0b8d5bd81edbec06b58dde529de9f849316219bbbeacb262e9ea7d51ed53f9e5f898b99969c7dab709c91492672e6fb3f9b65abb04260dbc2cc8ab23aa9c77ba5e566747c90826102ce85fe95abeca322cd63e66c77e6bcfade9ccc6f3d7d314d092ac45f3116aa4d0c316a5de99d9899c99c79f3cb1f20907d6e645ebcdc7036ccd1d7ed1c39af86b198e6c39990045ae633aade81885d132302d72878d93a1022b0302b3e709af459cac6ad", .None}, + {.Pow, "-dad6bd69b988f46232e4d0c9bbab29fecbf471b88af145c603d66646561a333c25729cdc9a887bce73ab59b966a0392bc56e9603fae1dd89a12d4431b01a87434998fc0649849fd53034cbfdc9773f1751a54a996420e699febdbdd526771e168deadf6b4f0ff75186b08c64a949c75a0e265cf6d55447987a36f5c51849c5b860d2b9c04201f35801b2ee14252c3926cd207013aeb8", "3", "-9fea9e1c34d84fc5837dc2570b4e54c5d7bb059d4df0616d9222b216de4e03f5bb51c0667968e0494eba476c25088f369ad2352829347f5d0c8f5e150d4c7004f71e7c0f96d60e0225e4112d6390c82fdc0f1ddb07f66b72531e535832008441119311f178df1508777661ed5efe0fbf09c66ea9e5a4f91f332d4906f0ff85f6438310ef4d4e849c872c754b797d45bbdbfd552b52045666fcf8609c0fd87cfa09e8a7f731d4c303005f2287ac2052a9a4b76daa794e8ad4c16ee55ea4a4cb78f94e599312fe884e563b64147e29728dce39fa94fa31d0b91cccc029dbaa3775562d06d10841c7e2f655818e773ba4eb51dec7518a72dc776ea4f0290fe8ccdabb6792d8d74676c194554e0edd576c265fc4730872f9dde803a56c91e5e4bfc71fb4483f787958b030d4cf528a0005166490c7a45f085dc8e0e68fa9edf305dc2376f399bc11a498fdd4dee83ac4bab7028c05c03b1f3c8a04380ee6125327a29ff38a701125fc289db89a724a3b7d52763bc4eb40bc672807bd5f5839acb0693b17732e0010debdcc2a9b627f5d589ef76b0d5aa0a4a1386a5d1dc2c32a07042f34cee20d64f87148c102cfe534c975c72a53be106733ce6b9342f79250dae98e00", .None}, + {.Pow, "a96059b27fd410a74eb40c47361e4cf19ba31a6c5cbae6a3febb4444a6494abf4ec129337ee287a9275e222d98c9a63bdfb6f54648cacf39068ec729c28842ab841cb08f39860aaafdaebc4b3e45160a469e10c477dee118b9224e3ea40a3caec7c55e123d3bd7cd9e20846ed902f5b2a3a7e7197a71791d3949665f6f4fc219f936ddfdcdd2d6c9521eb4c3b5140ecb240b83fa0407", "5", "2074e9a1ee2fe6e7208ca41b083bb65d62b1fc8f223447c09539f593b00e7840b6e90d8bc7a7651848ebabfce2247fbef1008659e9aa6fdf8090228047d3f536638df1ace41f0f6014c8ba97ecf5e6488625b3c37b663235aca75c7fbeb4de1f1ec311ee71bdb7202d73bfa74c68cbab1a73eded103541d71b6bccf225ce61a5cca6b2bbc3450b2245897348d446e6c055549f3cd2d9209da73aab7d17522eb4cb9ed600c1b07452369aa4180921f98eed46b26562727fab34d7a8f445c97585ddd4c01a331dddec6dce85d8c446d980a065e30ab3b938863d9da6ba09b151fb58dc0e9bbc3986a4bbbd1917bf77fa494dde644fcd7aa75164bc6ce057b408ffecb801fffada1eeb3a473e1fb7a224154c9c019e0a33a467e49d425772b14c31a262484c1375a870d6c8d5fad7fdfa0c7429fbf45311aa85442374402bb1548675943ea5b6ae3369a86451b52f7db2a04fec8775786be034b367e37a39fbd1751478887474f32cbda9e5f1b46ca5824ceb0e2bdc204545fcbe9aa5f6ff5d3ddb7da0c833f855cb0164ae476f26a9a30e2c6748f467c6b512b8584ea751fe132d1d8e02dc49d2bf65c37a3b56587bb974ecf55262b06941b3ab261a88a986f497b4e5773b3c22d56bb8e4d2257be16284e25cc60e02fac8b6a97400e6c8c07b691c11b2b541a940b8485c3b199ff20251e7ff72f353c34c83e1ba82fb91ec6770b3e1f6a89f1d6c8fef13860a449af04e9eaea8dabf6a372c9538c44e3ba2a2ca23ea443fe51f25594a91192d84ad13a4f0b88cd675fa83ae21c5117005593a5a02ee5c9b861560f9e3e9aaa8e72a05422c60a6145fb38ee5fe7469bfe239479194c711cc9f62e1f10f643db5cca76ba69a6555f9716273a350deaae25a0be97ec85259b11eb12abfeff3d10b663f547e2756eb15e91f77eb2bf7ac061ecdc38ca46f21128f5cdb4706cc3ffd25d0eac9803816eb98c3db1cb6cb74d818ea8b005102e3a174d95d970a9dea1cfc3ba1556e0cf5bf82a2728e616e53b9ab5a7d882c603842912a35a0c0d431bdd5a7", .None}, + {.Pow, "5cec42a42f2d1febd00c0e9637b690ee4bcd25a0865ac27d1d7352581a4269dc4dfd40614c6262ead21ef6af92a2e12ba22d96177b35b96ff03bf57ba1b9b09bf419042f1c50e8e9f04d8d4abff3f8231a326350f86ea16f84c5bef6f7169948eac2c7cf596b9c2dff586396d55f45ae145d3e26e77738f92ae15a6d4ed75209b6625ca94d16078b7e729036b0f92e97d5d496d9af18", "5", "19cf247968082da02522b5aed788ffde57a1702bac0aa34429c573a2cf6f8ed206655236ae5a2d81d39ca3a4e263843ff4f3f3f4fe7be353f342bfe36b3856b444e4638550450a18207aef993a77d9866ee337746a641904d476561b7fd32a205b8a2e1c27c7e7bf3fc0105be200ffab98d57e7ebb4aa527101a0209202eadb32288fdf2a63467f7c54e98472dba0478436e17c47a47e7defd3cb2e2fb4dc5c3fadc1a0906f530cd7b1557e56a3d4a80a37c0e1d71906563929a40ce6536305825b35527f68b27ec0a78e8847c6150420b64ea28833ddd0c475e76a1422d7af943ee780c3e3b4ef385634addcae442ce5d65a6aab929579e1917fdb2df9073e4188ef19be527217b5778c12014ab7203d0a6713f39579d209f3c7c0d26f39e33880193b5d06f5918506cf3bd613086f4a4fd147db683caa82b4aa8462bf3805ee5ea38ee92761474aac6e50094b9a1b38f90e8c2b9816ed1be22dce74ab42c98b06d7d882ef2c1d8ce77e242d0cb69983addfb6af1af830602f19b53d8f126f79b137d344a84db29f9c9e6c8638e48c54c203efd732e8cf8dbc1baa445de367f30ed5fe6d81e7f2d6ebb0a64ee994a3d93b5e1110e36c3807c6935c2ff232c3fc5696a93568fe518ab5f96b4a3eb1e9e6dd6b4041b881962ce7e55e9b2781ec4b11ecb1ced4af0e6c9f8bc517b840cf745c775bae875ac17fff0f2677de9dbc2bdeec300381722f0384d13fe10f592b3e60d3d8ef041c00c16075a69b7c7acd2ee68dde0a5a593d0d8c8af22385620bedb11123451ac30f8bc1dfa7306b208b66c66d2c79069fcae64ef7aca40d21f1b21dec46a50f657e59315c0273cf36092f255735154609ee6fb06cd5840fc09faef94f421c5b28307103c57b9fe2cbb2e1965d95d7bea16e8a9e3015bfec1e00b432a7d8241143f37fc433f0a4d28a6558949025136f1349d4539d496e4daca390e9634636ea07eb6566bc1be6674617af59c6d7b26415722a6aa341ddd1dcfd21fc29849fec6a8baebbcfa5005f20b9226cded9f464180efd8f3a298000", .None}, + {.Pow, "14701ef1eb1a63c3dfce47336b781f5f36fd41a1c43aa3b900b091ec456edb94c7153e38aeba1b51c2b1115b38f30e3f359343856a4013eeaedb1e1127ea3f29e2077659df2249e1b203ca027316ab6cd3ef856b597198c703dfffd7a8907661b486e7464f66422a66e5a440217af4ba94bb4aa222a4186a2013e8cfb3049fb7f29a2356aa1d58b92bad01ae693aebb581684fbcd0c3", "4", "2a9923c15cdc1fb0e00c960eb9f7f14aced5e1af824211306d4fefaae514c854c4a38689cc0d27a79d674fd3f9fd94ddebfad68e7e38f9c3cc55bad4cde302c15d9e8957f78c5b4a0e51fc7b85604a298d6e2423639ae3229a5ac68d86bc60b910fdc7f877ac6774b6184bdb52a58add82c59e554c7b59c143720af496c4a188d6958380b8017ad440442bf6be05192b05a61ef8eb27c78ac7e611f0a2aad526ebb378fbfd080e6fa9c2411f93259a1ef57ce65798ddcb78210f15d66373bf65329b9c61dab813c3cdef475b8a075835f1c829bac8abc276bb6c4cec77d672d3ee742cce465eb03adaa5b7d84133e44b9edc6ef2d8d5adaf02ca0072dbc20d230d9da5d0b75ca09769d8372fd43fcca59e05a641625299cabe65b1d12e7e7f481d27543b9d4f7d2654f16168a835e1ac75bb377fe356d7d84cc5e16bb8814fb674997d5a36b66af4bb2be1b71549f71daceda42bd75bc3d1e0deafaf285653e7561406349de7af4015bc3d1fdf2489e574a1452d52a4db7f835ad8af05271dd8c053ca153cfa749d1aabcd761b862caa3c7c024b1bb56b331d1c2c6e99d4076c92b4edadbce8e7d10bd7ed2728241a3bc2e933ae16ee5de24342de3f4f8a1a1224c322ceca0e17b44b0ea9680b2a17fcc39ad9786745ac8237f5c98b76805b1bdf3d7317ada477a94a5644b91dd97e1464b3620d66c88a7a2efcb176c6d5edf7d32b05eef7a68eb70f60fbe0abc187f251fb3d73df016eb5c8e4b5d7eea17975c295a37d57d69ab62a95d3e734870ae7e1db09816d8c5c24a59506da02466661f78a09190615a461c95425f7ce01486e24f32d1a67151", .None}, + {.Pow, "-a955f2108d73128ca8be65c4be6eeba55afa8f212bee558c37296e9faf445fb984dda0214b544e1a9c4594718b626cf2ea8508a1ce9b17fb5db3bf748a218063420220f04083603ffd422d850969dd1ea16f8e13e429d3e4e6f53e8278f27634265c179ede436ff9c423c21594a4d52a15dc173ea96cff4c630073ccbbc7e96d36a620567fb1b1a57abce4a9dac3eb4c9d287f6077a4", "8", "961dded363d7ceeaf55c5459087a714e0f89b9c148acebaf2c5a2d304af0945d4fd827ecea0375376bc7df7d7dc380557cb19467a9372c9b30d1158750b8ac2fa9564b3912db640cc2ea744da99fb4eacfa83ce2491cf2a3921d4e2e3a6759f6e7859d901a037b133970ccd722e3472a0abb7eabec3ea3391558577c02051e7691c9cf77fe15efaa69d76bd858e474482324d7c3e138052d415d3d016e7e7313db0d73c7fe0e2dff9453a8ac47b4190f057294a21a69128424879d7530579c51c3ba33c83cc0002a664c91138d0a4a6f9d6c063898b255b733dd6e43025dcdb802f1f66d7f775fda0c6a9eb6addfecb13546bbc677817a5dfa00fa4824893c631f70dbc15cbf44cb31a5e7f6141b7b6809e2f8543537678ffea6b3b598cca5fa85cebf1fd729ff4c609fe18bf3158d14b884b8a9eb6d14ea0e1b9e08adbcbc925bc8b0dd6a0205e6e84d6885731ff05b709610aefaab1bb87e6f79cc6f01caf2ce966e01e9de11ed739479b002df46dfcd9662ab839f5cb1ed8a46d67e48aade591829937b1de8fe4bd7a49a59eaf57b72c923311705645206294aa2dd22238aece8a6390b105f3209b1aad9a31fa9e6954be72713874308b53da91017b27a7650dcc7bc76e7c496a7c9bfaf95e6a5ccd0308ba2c1e0b6aba01900e805a86ef0f599836b06b17cbcc2cfee1345d80832f0fe6a0e57f39d6c05d0f9034952d37cf06dc6a3c68dc950698821fff3522970af8022cf2b668c8229f9b34dcdf461f8048f04447139e2a02e41b2a7d5bc3e1cf717c888812f172c4130215b3c17484a04a7c891ef853bc58a55a58d8be6b1e7f18f9188f4b1138977110fc9fcd3885e39e4f90bb6955f1bca01e02c5045b0f361d0f18005d3c47788985d88fb324efaeb214e449dc90cfbc6dacc86a6b5078c3f81c27cee02066eac44d3eba826b80eec7cf330fe96e6f9a9c867c6fb750a24d18390d24f106c3bf2beaec978061e08f9eee35f54b28444ba86e57069e417ee1ed9fa29f19474426ca5f627f86c8f264ea8ac9d68b13d9816f09fcf7578f56efbd1d1b349a11e53733431a826c278bc84c3ec7cb8b88493e24ed4bd25c9f045866e674877cccfa9551fb95fe8f24eb4c88be4c0537364a6a84bfc6641e95e28b0e0cacec1624b8fdef71ade696a3e92a2bfd9f134ba3bdb391d73746870593b2bc503fea65625425013a3366c4e4d643b9510ec156d23977b14b4d5bc1cad72684f62356c3c7982d46e73832130a780224e0fea7b4d265e84d59b4c12e605cfaf558763150f2454987ec858bd65b4a89b50ef7003d8df9f67a54eb9386cfbda7aa48c948be9d2b6a7d87dc8bcaacc7c8ecda3ab2213c6499e062b8718f2f2271cfda9061283a6831fb56bbaa1410ba221f5177d0fa52928a9bf4700884c1add2846c49522320cd352cce62413d70d0dfc49bf9edfb4e06c8ddc4c0cd496b0a64f2d22f7db3d29125269bdb6bd7834cdbc6b147ecbf4280ae418279555961a34fe0a2088cb1fb8c199ab08cea8ae74fceeccec278447387e86bb1bd4ad29b2da8a26d69c813383db58fd5338dd50b0ec01c410e0c3fd12cd01835abfcd4c4672cbbc9a8c6329e9b1508fed74fc7b69af85c5c58da302f97f85bc2973e7f10ee9e546582d641ab33e986166c4a1f3bcf7ad50a643b07e5c6b34698b23e410000", .None}, + {.Pow, "-591a2a0be18692195bc7d09f916fe5bce929bd2186cab668c84b476180473e543449c1457dc46bb2b31cde4bb3536d586808448c49e361589a9ccfc212be581225b5595db8ba507a2514e2b3ceae30becc38e13ee519921c0cbcde76cbba58e9fd2d79f804e84ec5c0655f5d776d3a8f15ca12674c5869c75bbf5b47500e168a46e2c1dabe6f3b628a267c367e6c879eef1c30b9c3a2", "7", "-288d7adc4a4a909112ebdb073993cb21c43fe7ef30ccb707c457c857273d8c747e201422a13b6c4057c0da9b8aebb88ea9f6e18c7e4d376b0cdba18c0a389882a64b1d7b000e863131c92b11beb57c4dbc52357c94a7359bb245af0562e9d35093c63adcbc67bbdf1715be49587bdfad745b1d97ced227bc75f1328456d854304f4dc1269e5ee3de9dd434fe97f808a6a71b4339dee50e5ae6b76816aec38f981c40503e4d92e059ab52dca83e4613ab933bd5cc3d875bfb0963da62906f5a9b7084c4245313b157fd2a0e604d2e02794822d1857a2245d122d27e0d8641b7f60e6dff2b1c471495362f356c8b5e43e1ed59c02db996fa4bf9990e4ba85f76ae0e6f59f3d6b0dbd90e140f0e5aef53d00730e8cd3c2297ec6ecd35d8843df4d0acc7d2992cec3dc5f7d436873185a2c537fc12a69feea6f9806926b1d7a619f5ae54cd834244ef4864243a12dbf12a98a46f40c737aa3520bb95c6ae9fea0871ee51ca1ad86ed2f25469852967c6173c5dcb841ae22734382f47f0b36a8e15b74a6a4e28de4139c49f3094ee3dedc8b89a4b5df642e3e2fc078ed90235bba0fe64d2b5d79d979ad0667eb747790ca6f9215c99bcbabfdaec54f371f81c4903be77ba5d111ed970c2d784be85cc271e1e4f08a3d9726ed345a50ffcd72c4fd4e99d23332f66f431d26e624af57f9f9a779e0b4c1702f27786e3422007dbf860b44f7a3c39d93f7f8bde3c9c1036b5d03048b2eb0f107697d6238a55f3ebc5e0969f1a81b6028c40d9ffe10c9f1b22dfd47cd54acff4bc817e68bfb99201e48789e8badb562880d2ada99bf9a9b9b19546154d3fe4f9630c35edca646c31e43e358596e1c0911fcf6f328aef1b13c49f4d8b6e4374097112ef5f73ced29d930645dd3c4a41c6e956c5aeb72dada854a0359a2d76ea6ef33eb50dfdcc0854db8d1b272a386197b50207fefdbf9525f204be7a1eb26898ce78dab3b5dd9c6cb516aa3eebbbcff22e272122583c1e4caa867791595af79c7e8847db5b14f3759487173774b824abb1a0fb6bc2ca4a2d7bb1ea50546048e252c80708e6e5af38d6530e805a4ecb6b24fef0ac7ba0961e2fcf1b7aa2e8cdb939381092f245cdcbccf1f303d9efdd983b1e51a844c0bb47260a594606a32650962230ef8445f53bea3f62518ac00acd6edcee9026ae55397b1d8784b6095bb853006db6b59b317ced8c6c4da0454042c0d7f5f86e7442384e271125505ec93f31f01d493ca6f9135ad895376628f1a0c8c1efa99e8c43e252c378be41b21742511d69027b7c0df05a4b79d186a5c940f0b5489a2f02a4cf233f0010f0214a7d9e0db72ccf6b031cd929fd06e51a37d6f0ed6e222a23f84845f9caa4c1ebfb4ab673aac1d878e6a8be34aac03cc9f9b1ef1aa318d8e8f7ef575b763114dda940e4230ac502371a830bfdd59a3cf019e7bec8536f629c9596d9e5b448d6d1d7786a8cd880", .None}, + {.Pow, "48f8d26a41e8b67c76a19b6183d8ea2d193639e2eb0d93ca377dec62e4c8052000d7290eed5571d07f7415ccdcb504328160f2fded6283dd7bff2065f0dd3711a5619f21068c6cb065e4523c6ffb940d805073e97cc00f4806cfd57d2c3969d41d59a11a238bbc657e6910d7ac819e95929df8c4d39eb6dc0a275d471135be6d28edbd9d139adbaea33a103393e8a084757dfd98884b", "3", "5edd8e854252c6ab09818777b0ca887bf50d9c99416f3e7b30a91b4ec2bbbdca0f4eec3f573204678c6852600563610940bebd935299c0ae89eed27068c104ab51080dc362ea4a5a5a69857788fa509959056d4d26afbe437f2393a768a07cfa098d52d83e0101335e171061155644fd1ae03bc621ef154ee9df95a47a9fea8e49400f9b012356a8febdfb9d167333d426644fbbd03610242b0ee1c28acfcd7482d8aac97be511834c594e7371540dd7ae24f83e32996f0821ef2743a10f37e9be7cc2f1cc005023206bd6906932e147640c74f1395333633e97d736329de0e3c505c0ced543e561c0ea4c287f6938fa2bc34564ea1b231d40b77e6b5573aa143186fb9979626c1560620b33ebea5962c9ffe9f027e04909420f550111e9dd16c8234f9b987684c64edde0d93c227d59189334110a949048a4d01db53b9bbe6778ffd33a809c8970d465b2a5d54c6ce1d04ca8d12e2d30d339995b0aeae19cdd446f3470fec871dcb69c052bcaf4aeccb8d6c3f306be6897ceef5b53fc140872c32214d1f5674045d278e359d6a4b2bc657e4e314d71545fa3d8b01b157da19836cda75052c1d4f4bc3637cbe25bc1750b370452ce8827fd978f2e7d3ae85d347f3", .None}, + {.Pow, "-19f5304710afafabdc602cea98733d7ac913a5a62e93d500dcd4cb9f618f1a5e24b8fdfba5c75b6cdb9354fb05f7b686996c86d6ad68b60450d1e53a6e7748cde9e6043ac4f67592f7f57f48bb86d400f66c74c5702965f20c1ae3cf56c4ded779e9af20bc429a0e2fa9620ec6a6a43b1e4646b6f05e597041e81aa693ce049fc8d2a49b53a56c11fb0f44df3e2813e7e1bb5b3c17ec", "7", "-1d950fd33bf1d8d686c3b747d07c21e698241e867e510814832ca9309fa2ae5b00a9aa9a8c3f4ae9829759c8ea303ee9b413a02c08d4f51c673b74ff1d25f17c296e8d5b567f659099a689669ecd0830b2cf43f0c6f8b94f61b5ba1cac568fe9486af4b35aef1749acadfe0524143ca4eb58094d141b64f3d20421686f08526b69b953d9e864f6aa8ae076d6f8e263f9c08968253db2b37898c7348767154fbff6fd2fd44fca94874b74457af2997697719a8af4179b4c4a6363b84ffdebc8800970f310337038a27b8e4303d24dfab0099673eda06dee4851475340a2d1b1bf5723e9eebd58ecc64cfb60f7451b049fce0a490ab6dd30362d3cf6ea0862f25daab2cae367a03b9766df2f258ac9c32baeed2056921e736b708f12045cbb89743b08f4c7bec24ec4fe87072afa1f0e8ca8a21dcfb13f531cc0c68229dab3c98239fcc2c9658928822a9db476fa794d43d78802f885b38cd2474d989e2d9d5b0e0cca4004557e0b9a40d038308f748b67911e59ee0c3a9fdc7851a681a8112e686312aa692c9141b18ba4f2724a1db9a4e7f0386a6c4c8d519cca0884a276a022e55c2edb316dc1a30630dbf46894bcf5056e23a1e1c430c5a3bab531cdf6efcbca8076639f1a120c366354b24beac13a08a7f4e4395ae6d12169f61629dbd85deb21eb8c4cfca1068561b136025f17c001f43d6470f5c9cf150ec395eedee575ad8325c2659341a44a67bdc5567d10a462b22cd04744bcc99752ab263ca409b129b5a4481b79da6b9be34f71a3aa8d9c552d2953994d765fd4b91492b9444a57f8ceed4d1a15abad8b172ed72044b53a4a29989ee14860d126c7e0124750897582009891cf5fb73ee4fa21511ac9b6d1c643e783b759ea000297388bcd38a51543cdcae95860adfa7909bcffb6e72f42dcd05d6bc291365ca28e94da4853f44951a4e4c64018e354ae5360efc287a274cd21c175a2217a6595ca496b8a11de7708bacfcae8eceae2196ba194b8b81b2bf1e68feb92942c6b090e9084debc08c58cd825ccd4aaf40c3a297f749dc4301af1f8a0a8394d59ec431f9cb96602aef38e8d5c54afe865db50f43e2f66f204d04e0fc0e04072e64fac2c5a5e715c53d0272401bd0b59175ce2c75186d77d24c9acf75086de12c5980b56c22bfe51ad5809da120f8c1a212990bf1278a74cdfc8a303c6e1b8d49acb030c965ff72cf672d8556ff46f8f3c568cd6a7a40f7f93a1adcf486e3f142324c11963628d073ca91218e75e9c28cc16f006ca02a1e9a973de8baca0c29e63a90d2b31117e4752eb48fdff3da66db61f74fc1628f1a1bd4ad5972de9cdfc29a548494a49635dabab48874b28052cfa3301668b1dd5242a25f2487bc7a946540e5e043053250697cfb100b0de531bd3b133cad56db8228dfdd2fafa0ed3a696fd85cfd0d768abcf08da78bd398f4ca7560649da80cd8ce65b4bca4dbd234c000", .None}, + {.Pow, "-f8056aa46266330e3fcb2409729ffa4b438f6252865b9d4a4b688820b11bc5ad36b7024b3e6a68f24451c4aa2984e0de73d0310317404b400199ea7400e5cbb6f34267b3fbaa51c970d8c3d659c5303be7c07dc76aa5673a0b2f6bf889d26fdc220f6ad3c044e2088f289dce168426b9cecee5c934d0c70f8acd7ffc7a74f47af96cdb33f1e596b90ee1852fdcec9859e8aa05086d2d", "3", "-e8cd4053950d07168845b7928f46d5db194ecd6691adcd773d64b7ac4efd221d8bbb07a581ca6cd4894e447533740620c773bce1b45130e789e9f6a57a949fc51f2fd94abe8f9afdb1899af41eccc2a2c1af9c94d2bfe6db1d8a0d78c90ba54b33a6b543d24872bd22a3cc57e59139fc36b4e3c704ea7b1b3b9c9a7562be8a46fc3233d229e4aa6d3532a7a14e0017cb80c41b7b2bf82995ae7cedd8d3ccb44c1d734ef3385a128b91111645c611406ea8106f4ddbf9c59487a4dc6142d031c5a0fc2b9fe766d834c8f9aa591a12c6e0d68d5e3de5f8f114ad74a814198720b9713a039f153cbe23904e83c9e3e0ff6a2cc48bbb8b5d29455773432993f50437377cab1565810acc9a893cb632736c819c606b0aaddab3dc60314864159158c5251d948243d224753aed49ecfc721eab01e681155ac5462f5e296c601677d3f4fc9889ec2d7619b0cec4d4a2c95790954f9f60a5bc7569a3242fe021c58c004060dd0ba7951375d1def92588d1ac47841d554ba1c8035c412ae823184cc2879a2e60cefd2fa15f66cca388cc8497335b4147e22df5a9e88f32d0108057df0e2bec1c3e4c7f6fbcffe9288d99bd15a1b21b5c749966b3a739cc526a037f7e4d5302f5", .None}, + {.Pow, "-8cc65050addf8be8779f5258dfe6a2d30ba916267b89ee065284ed8ca05ad13de69c69eb085bb876e2cc19ece958b1d435593ba3234733e975f981d3297a2e0eac6f24312a3f79a520a843526b2683a4aa7baf7e57e79d4a0230af0bd1cdb824505752703ada426e7e5fe00c33b84ffab41d87b04dbc08999dd6e26954c3a422a0e0adad623d482db868dc96075a50a4b23e0388c2b1", "5", "-cdf5b9dd617e7fc42a4624d9c76079e7b44f9114ef908b4df6fe3d978fd3e980433769c0db84a0b787d72193626c6388d6ef0582c63700a98522324b179477fac4236ebf6c01049dd89cec46195643f7bc826a47babb2d32b629b3e67b4d01856708700a18227e99bf7bde24de3a1bbd10ee83bcfd506e3f0d42f97022b78d2ccaee73056843651eea9a37fe2ed92859f37458b05f8ef16276136033f63f7dd19c9ebfd4d31b40aef4be174f5e3fe9308c71e8ed6ef26460a001ffb6b2a77625ed6edc9a707ff7051afc0d03beac2808cb30789cba13a8bb5da26783086b5b7ebdb6a3220ab9c0598082b26a62442c5132e0961e3bf83414c12781d80f47ccb595c04f1ab38f54c774c1b7c7d66755cd7a752e15c660a39889b2a5c256ba223eac34390a93438ded385096156e3b28760ee4882894b1187c5d6e577f830ff60e389fddfec599774505e8dd1088dc92110aa246e78f18e74d747edb4305b7c537cccbdbcbdd41d2fd95ce176ff44d5a8aa5f484d27ac5510272e0d7fa3ca117f62a22f628418ea7a4536029ee9ddf418280c2384099272924649f73df217e7793f6c98419df3e52381e34325e7efcb69def49b242de8583900f1d32fe5945bd9f7a50306548a1ff912cea2e1409fa96338c1a1e640abc5fb9d4a77ce927acd9e6db2214497d9f8918f4a0cb9c8c9d44e0d852927c160d4049e723cf09dec9790562f64eac97f0ee480688140861fe8d7e51a63cfd913bf00f61267d28a1f40b1d4c8505853251657faff216497e2e6b1f2d54da2b9fdc08f8ff9d80e0074d48db1978b754d48e9d3aa4e8b80de3c40db9a4f34cd8dfdcf77940e12d42f68103e7811178f7bcd152981822d4b4876dc6a82afe0c918ae4a97c5130864010d1e760728a61297894e24341b2de434cbbd80002c57eeb71a5fae73f29aad64b1750231ba5ebcd342820a3b78e2b71d613dc6b67584902a4bab2e67ad7933bc9c120149e4d9559cfa55b2b8d3a7c067adb11eb91b218ec1ae925ba02f58392c10fd8954b4f31ca152b26c58f47e04e771", .None}, + {.Pow, "2a633448633ff64672065f568215a6afb59f208eb20cd0f74f50843da851743f06f93c43a693cfd247a67c724e9fdd5b5aab8a1ad27077e9cc93932d8ea4aec51ecbfd5142c4bc4f83c958109096a9bb7194c73e8708c7b2092c309cc6e05fda67136e29b3c0d5f169737999354b35f20547183366cb5b77fd8104d0dcdea8880325732373d1364e3ae0d9474834a4230f357ecb1c3a", "1", "2a633448633ff64672065f568215a6afb59f208eb20cd0f74f50843da851743f06f93c43a693cfd247a67c724e9fdd5b5aab8a1ad27077e9cc93932d8ea4aec51ecbfd5142c4bc4f83c958109096a9bb7194c73e8708c7b2092c309cc6e05fda67136e29b3c0d5f169737999354b35f20547183366cb5b77fd8104d0dcdea8880325732373d1364e3ae0d9474834a4230f357ecb1c3a", .None}, + {.Pow, "7230eb191b623f8dce126ec7109a004bd92125a1b224eea06d15df433fe1c3a08cb20cc85b27e10e7db339ec5ce7eb8f10f52fefbc801ce2a5f5cef155d1952baf63a5222a51c7e90da490dd1096e93e83446e6a205d724b6fe2c1b6edeb62d8d25698642bfb5115192fd88039117f7d8e0f8fc1bc53bfb4f0cd8e4c9f56fc3548af92856483bd7298175aea6c53d28445c0b473d0d", "6", "20437e1e47b915fd464854948f63a4f071ed60ef040f3ea0b3974a0f916405176e418aef0db5242ca3019477e24360c7cc6e81c32846886d97d0b40094773c499c4dddc2b692237cc19fad4f3669e03e737cc5cce2b9af0a3dac0706ecfb2e021f8d68ece59330c41c434930c9cc848915ed7e8b5999ee0f0e1a2bd860047727e2c39f17eac0815a6c02189023be179401e488cbc3653be7b689782723406165e0802060cc0215726ea04732e955d744925aaff3b9dd4595d4afb037dbe182172cbc12236f0a32a118a094e61c5c16b209b45c9dcbd44e3cf9aa877d2c148715bc0702da811eb870e4b67d5de31b7ba1b721a7b4edfea440f7cc0e4efe268decd93d0de5f071c3f1845f37ab5a5ae507f24ac8ed30cfb4ee6581e3f0670446f461e84a07bc72b2031c484ebc8b49f8611fc818ae03e72624ecb29988e6c002696ce8dce7bde451d4bcd81f8da63505485c8537988252b4a80a1ab60d5ceddd43bd7494849d874d2cd964f7bceaa0f13d49cab27aa73b2060a1b6e75844c486289ffd7fbd12dc1ad39d03f8adf9b190fffd77a58f7e7c87e931dfdc3a148745bc9cd1e32b40f6c54d891e6279c1da27583d0bddf92c4b9a82ec4d124b42fa78340153d31620db49a9b995473f307ddac7e2b03f9014551c222c890c4e2fbbfa8c283b599f9cd3dbf37180f67017fe2f14d01447e7789dacea75ad8b488829bc3977f57cb094ab873fe1eea1b2e708425a41bfbb14d1c6ece6f368db18d73daf8e8287600afa5e2384ce1c7d42ed28f7a2e12a4f65476ffab08a36883c9547b4250120e5879865386784c60c7026e9ed4c021c27494d46cebe96eda61326fbe9f92fa620336512b7ef9e491f288023e1362c6d33257aff9b229df49ef78b5f9779117c92f1e661b08eddb158685da72d61ac28ab6852a57139e9c8c7a4b5559b485a79cc3dacb0035d26d1e1d43b2f43a4965a04f141e05dc6ffdcb62af9cd71a9bb4455776f63a4ca49453f09b250caedaf88c0bfcdb197bf71467ad9ecd6411dfe651c4ebd4c71f3aa515e36d0840a21b6c81415a0fcb88ed77c44e5b713d1635c985948b7bb30a5aca560aaf31794b6a1bbcb16620636559913c426841d7fbdd74077e02eff901388a4178aac8cc8de7ea573b5ff3225ccbd3f06dcac4a8c67268928cab2e705b42f7eafcb7b9b81a161eaa2b74542011c4c3d6288fc2f2f023afbea0b96007285d07d4015ae96d449036fad0927e8cde2c96533731f7939cb9", .None}, + {.Pow, "c725cc28d5085e040f1caf27a6383993bb3fbb5390232aca667c2665fec13255f76663620471b68cfbe0a9dba843dcfe8ab0c065eea01d9cf36f56ad0d064fcc10b0a3f865066b658b6e1fc46e6052e079d4a7884c377f0b806969a08cd6e2e0cc876afbd7421e3fa2edb12c66a502568c29d5dc3d3af9b7d7e5be9755891a6b9ac14fe11793aaa34b7dfe0d9fc7d902affe12dc230", "8", "225572dc5a636492486744893d962937a6fc42c85a4707f1adf374a84346fa3aba16721f0e96618ae0b52bd58daaae5e41983c6b600fa7dd5747decb120f87bf14a1daf7572e9d931dec4d47a61174cc923d46c534f936cba757e57899117546c81c9d5da8d9bb6919ddcb3a6da7c59d43e28755519852d853bf89a54515bb45495071786fa828d33549625a51edeccbbf20fe989393e10d8889535b29ff421e10cecc60b5b62220d60232d330af73bd466c019f176e10a2dd57c73e5594ebc06f0343a77ce6111313a2977744c515143cc789fd7847779cd23f71b5549cc4032353019d855b0dc92f0777133b787efee1869485078af3c3190835bad5d818dc9b5660598ccdd6b09ef01c5a5f7f1be18c0ac56e3cfd7e31578253166f6938d6f80b27467fc86ac0fbd3309e394151e15da7d5f004df29deafb46d09a73a6644b1b5cf9ae7b23712d1d6194018220c34023480df15690ffde96118e8c0dd6d55f9c52f87d45083d5b87f7db3d581686835e8be095c4ce690549c53e53bbfea429be64e659c00bebb63d650193b19ebfbe1f977ba0f0e24a5559f55e51727b686dfc71031a668833a7b2f8bbf10105a5c608ff6a90dc3ccfab9b77f5873216e5678cb8d1977616047a27eef79148683b618b75950327d58d0522f8639a6bdbe8536ba1f2b6862e46cceb34eddf224a980dd4c0a67e08b5002af5c75919702968493e21682538bb41c89d50f26f721697d274286a59cd73dfa73c9f900bff09c5a901e95ba77c9dcc00265534ca305aa2888e545962ed25b93544707b0ee067556d793ed4b2366d1b3c800b90d5a8ce2e6852527ab44decf8edaee8b1024b10ae336143346cff170db3d4ea6bcc51f4a45e77a974cfba4200e6c73346f82f93a07e6c94137735a5f6e8ae059a98a4f80268f8105b7a7408547ac55ac472b3ca240b539af7945c89f2c41f7ed06ae9df273b89d9c5aad605c73dc241063eda5424bfd2560e041f0d61d61d057d11cf8b08d3274a76e902ba7751f08375e4ced33bb52a1f87deb4a9989ce05fd73e675b4120b5ece43c8d62a81caf6a42fd5978bc940e2b736b855ef8101b55dff4657684cbf1e0ae5a09929c713967ab147bfbb0c4449026d137157f7a7cdc339b1a8d19c1d511f2c83366e24a59e7d6f6d6cbcf8c0e46008fa21ea0a3d36dd8c28b629742da2edf900de2f02e7b41b62b18e11ae901f65b4cb67ddf3eef71d022db7d5bac06fc32f7fe466e0745bdc39daf14642e8187adc9f3f9b01f3fd7b4699ed00c9fef24c8d9f75141f6472185c31ed2d58bacd4cbe6975d19ec41b38e50b66919ad745673b66e16cbbbe1729b23352ef1b60deb23caf38af11ff3ddc779f8b5f0c9b2e76db06376825caec76a4577d81337a7a97dc4ccf5754317553586e05a9a6ebbc154bd30a83650622c976d00a176f37e3d4becfbbbb902cd9698c5d8dac1c3caccf408c09cc7361dcacba08471f934474b0b02190fcdd40a5371ad80446836f9d6363249da91328c0180b6585d67ca9067f32325b8c3c824072ae2f9a8146b217f3bda5f4367648bd1c24c60eed283e54592ec98471c640e0eeacbb33e33d84d815c1e36b7a90fc9b0c632ca370ee2ec25b57218f3178fa77a150f80ae7dc9e668f5fa50d350695b5dbbf5fb01b6630734843cacb34a100000000", .None}, + {.Pow, "2360acfca22b3fd0f0b9e3767f045ebde867c6489fc9910a00137d35ad09e607b14bc0ed40af64e2ad2a0ca8732944c319a062e63f0977ae0c3a46941223001bdd4d19250f5c3ee98c8ba79dc0b075db63fc41d0baf4110bf1eb6756d322fc5dddace05a531287f56735737befcde94dda1d039322055058e2b6b9dc4cb33bb2fb656ccb9996b09341f64ce7d0eb268ea051e565c62a", "a", "ae91d40b2a55e132056e21e4a582abc0472d062c5cc42672d5c6357248c5f1e70dcfa62163f72528edd257220c044bff082e0a41bf8747137d18307b813a7d7839f30b00301f14d8afae0d7c15046f7e938b54141044b30c60078c6b4678b9eb72f21af4d97860a51602b15877e03c9c483e586070e4f938d5c91b7a6ad103a7e0b3543b3b2a7f3d69e84fa34ac06dfb8bce83be03d141877e79623da930b9852d5def93d7efe470f0eb324941ea41c5442c391a9afb96725f60ef169906545564a41b74b868df7aa09c73b95426e6b4ec3831ca22b74486223cfa12a7139274278469030e6f7a906d8dfeb7eb152018b98a525d1afdb7a3a092ae02c4504298ae8c7a75bd85ecd04e7450b7503372d174eab8de089d570569e7c73027c2d2f8cea52da4aa707f5ec8523c9b8088741f425003d83698c5ce66c8bbf152b8cc354e625ef502b7db3d9ca40c2435ad3a46acd4084d1153588ad0a27fb9b9e53c20ac102eab92a835fd8bb9ee6ae4c2c85d9f7882167a7ab96a5408571027ad4b9cba39ec40c9459beb7ab3ba8c6fbdf61ba72f344e802ef043cb18296d242a4a89d309f611d77c69fa4914720cea7524bd1becc15f0525a8142a64011c6ac140ccb12a51a7631106c6fd56f65766b3538016e6339b12dcc96f3efe367f8d9dcc5706d99cb672f7778ee64b97f3a224bdc0f582d764bd4866528bf72bcb5d755c9d2da0d7f6207be0933f29db743a3eea641795e112b2b8f02577b7e9ec3726ea4be08dba0c62b55169e8f4d005112d893c5fed881fd5a548521db19dbcdb94186ef6b70ec90b0b96621c78e2e461bbf19b59d25f0d478eb96a1cd1e479dca0ba87457541120ace2b66a1a91f6d244fd33d30c0aee1e6812f349b13ba02e6b90ef94f338c0f61f119658ea848fe1cf8718f0d0a03dc22b2379320351ef55f016ebbbbc1b6be9a66a7bfbbe9ce121af480d6611d0657c1dcf7ee7cd754a9ebc2085a80a4fd47dba8eb258cabfe22290a4d4d13777fc4699926febcfce7e605dfa06fd463b780aa7e0eddc3f14d4930099bddf07cec58120ace80f33b627d9b9d538c7bb3c331fd750aef61ed255dc18fe14c1bd064c62141ec0a1d9005b5520f01f0011445e56518d30e562b078dd7791ff82600e6ceeb408e5deb7e517f65c996e5f7388a57d2a7ecb28d902b2e11db64bfce33a1cf619052c4d7d4f9868c4147b1c43de00fa666fd2894eefb4857f4eab8153c589f475f38d94272769ee2167f126bb4da9a696bbb31a4386f416e6bb2b3a4babfe5751142e442fa383e083a835a5e4da596a7a3ca0fa16553b66d5f793e7aadd8a655b927154379942bb1dc7be081c6f2f88c1a398d8eed709c1b65b9e2798cfc4a9422f88cebfeaac31fac779519e7e5aaa1456cce2a5740965dd4ed17eec7a22cf555fa3dea1ee3d5b1e8257fd51a68476c95d9d454aeb9b6e40aa5d80749bfc5a8d373cd174532cd4bdf4a13cb7b29c81e67f514de9075697e564ea8ff63f9ae7cbdba76766b75d936729b8f65af0382003862e025bde876c54094684f9ecd2ac530c1e8b98db979a7f80d0d86d7a156a42ccf309fa2007eff1451d99a12593779550ef231a940cc04e9bb2488e96e47f73dc5dae7d2fc1140e2170d8606a294d5bbf88998899a7750a0ce76e95c663ac2ed374851a2e39dba3856f6156e51e78a83a3e16726731b9f9c42741ac398709c7e902e22e85e7c43ec74fbce2cc199a44e03ec5ccf97478ae5a86db831c6a95e817c933d3b21d8a6a97029d910770ef3238e745f1ddeb0fca782983dba9b914dce54eaa793b03dbeaf8536d3b12fbf0de07749d8537d8de42cbd33919996b4150d427451fbed80042f24243fab2213c5c0c98828b5f6feaaea1bc50d3f9409b837cfdc15aadb79cd66c327c04410a104534c7ab5ce35f32d0f1329d682aedda413adb28210ffa278d250022e68f67177db871e60b7d899ef91dcbc566b0cbb0f94f0e350a063bb2c5d15ae9bf28e3db7520ee03ad7fc9557f21b4652463c0b5e97d762c09e9642a8473c1588e1b3b139e615c66dfeffdf00dfc1ea09d59765f89bb1ce6962a5f725cf40b72d14a3cd763946400", .None}, + {.Pow, "-6265263051bef8e701e259791b8390a943e9f4861b65d1ca4d3f0e7f78d5e6322fab355ec35d12d24a38463abd429ea10e75151dad9a6514e4d9dbe7930b25a07ecd7974ae5df2480ca7b224b6dc150dd2c76a0351ce677f36e06b5769904f5218becdfa1bbb7a51397e2b21a04944e7bf414232b229fe0ad4d3f5b8bd842b9c06a7ab4c9e449bf167a260534b0f5e8afe16f5f0ced6", "6", "d34a89c607c3d78349c7a717a504723b41a7b94e45ded79db7c2c3cf127c00b39dd57373a88b6b5672accd955a76b20e6a5184be41686b96a898807ba2773d4652f7ca3b8eea1b25d94256aee9b7e4a7a44c73d6e68fd24e846b424ae2a8da2de5490e50c41c84d060c0e2ba4d7863d7b2138b2829c257af72c5618855488463f3db1fa144b41ae3129bf1c19fb4784ccaed4c31089158216b8f7955b5c1d5482673c2c2ceb40b44ece45eb2d6bce01278682a7cec2bda1f601b983ffcc44527bd7caf3a0bea2c2b8c5a9ef4fdaf27e648ffbe96d5bea38023abb7c2b7a146f4e8367d3846ae395401cdc1311e02228b6355a5273ca6ca8cf9812c227ee461b3b88c0c0dbbe4cce5fbc171ed4bdf6e388ba0e36a285f71a881e7372371ef8cf752b6836e88c6d8d6ec4bc623847e4b64cf4f1a6ab2de031fa7a675cd20e857f39d1b4cee96c25d6f7a3a9369e453605fe946be16164c3974ee83256cd1144b7b626c64d2d8394691bd8e55e62e6f45e31d6c684494c3a061411ab5551b5c95bb5c15d8992033cd50e832adb38ec84ec660b2e1414641f3aa57608e70135f3d4ab19090f3b508b9f674418793a9e6729fa1fc3be50dc5c3ec4dabf260dbc6ca9967331c3ff8ac3255950946f5e8f5e7cce551b9b7ab68f79a49f28de151efd19114562c6cc7de52fade985d968f4fe24ab14acc24546707ffd5dcc6b38a49bc0fbae6ee2c9ed8d80a3c177cbf4adf04c5570589af428f3de32803a943647dfda9a0043161ef5c8dbc1aa06ecc4a118b0df257cd25e66f8fa70f3082885a808a63a84feaa1346bd6664ec58928703ad9ecef823219f5f18273696525ca37803607a17ec69f6253fbbdde53605a07a80869e938aaf67f511fd1b5152279cb674bbb33ba3a47a26a4543a2105ac28c356bd037694a65c13eb6a4138a2ce6b6383faf8447dcfbd5116b54df36256f55248b821c23e053401da5de1b1d1f440e1a3eb6799ba7d63ca8a3134a2614918e156fdbb4d24af9a3cfeada935cbf93c964645d5038cd72639f49f7f206ba3420e09ae6ce48a0d6713e5910da79734877ca368897cc281ae356fda8175a35600a0f954807fc84fa89be9553f70a0ae4c87743cc1c906597edab073a7d16da10cc58638c1271d47fc1a0e911c4ef8aa7ee54d51ab055fd8b74304b7559aa56ed8111566d087179fa13c2f3fb3883d7abbb1cf1854e367368e98ae443d90a0476285408a1d36a129263107225c18b95bcffdd223333ba40", .None}, + {.Pow, "e1a2478e76db4ee66793679a94360e5a2a06821fdf9e3ea21e1094a2994924b1da7baa1d8d3bb3af4065463e5afcb62bca1c4bee1797238701401a0181f106ca1bd01d4accd8e8ca5f55f48826cc8b822448bb1066aa96ca0a1ea97d61e51d975affb569779ce4ab7852a17197c64f005e0601a8d745b8addd33deb8abaaf4c9cfa86cc1aeec9470ed9a0c8eb7a524d3fafc9df11663", "8", "5d3ad9362b7fdebf6c5c67ea210f74fe7eaa77db397dbc990cc68bd9c80c090ca83c4081332b24ea9b38575e3add992fdf8066cdcabb47822c6e4157fa5c7811776a917592a2809381dec824397ccbd8be33e1aa96b830f6f75c57a093a53cf7df66021d874911a1b4f2b632ce8b9e60c390030914d38ad2386b6719fc0cd57c209791aa7da89c014510cf2e040d452293cd4c9e0009add7b383945ac9cf91a212fb3a8249ef068804b70d6e895309b74df5dfc38c6d10758cf4ec2dc5acaa230080013771910b09aa1c1194edf5f40d1b8723bb55ffef9c6c45a8635cf8fff6e2e0be3aac018fb14e1080ac24484699a18e14aff234a7a36c0345099b6b59d707e04c85e9c0e2551d7fae6c84457a4b7824c54be1ca6d013b9b586a3df4a23a15f26a17fdb57b3c440206f28b2aec428a8e3050a3cdb4eeac87696c214519254a64d3838cd9ff53b99b0e5217e0a6d2cb97680c108b3b8d83a9ebbd69d1e7f472c93407c15411b81f7bc1a7805425d2ddebec52bedbd669e554e7c91b7dc7f8c1a2aa99eb4661be525d8a3f3343e4fd85f1a2005ec3cb9d347957ba804972e8a96cc5cd617d7ad848cef3df01d28ea63f1eaf05a9baa0e910c4382e8e0ed6035fc4afb288ddeedbfac245f5b361db36791627cba1697d3cee63e5cef2d4460b47ec8bd6f412f37ce2584cf4e45c825388718e64123ae0a592a0a029ae825e041baea41a22ba2b6468e875a7c827611971da21ac05e011b048ffd5a93473b4e320546941ae0c4fcc02bfe5d043823b4b3fe9560c5b5be1663ea64fa64f68b2b34cdfead6662a7b571df9addb06e74b9952cd41267a1f6b14e00c751f9856d1bdaac5b32712ac006589f7f552c9cbdc698cb82250e22afb5d44a4c243b2daf1f21a8d3e96a37add545c1e19f12160741d05c8aac4d9cc289227f89d613a2819eb62755446b75d11848b321818dfadc93339d22b3af538a6275f01475a9e57ee54c2e8585ea8dfb8ef28b7375d38ff7de62597bfd73f562cc443ecbc8e03b71e5fd07b2c07095c5778f1f17ba90a4537ee361029a6bd262bb94a1d4d4448eab66006ae61b5978f3305ac37ea348e8774abce2fe77fab616e958b247c23ab347cf5c90784218c7d873309b504d4899dbc0f219a7ed8175f66df0d0d57fa97ce6a60f20394dd3d8ef7f562aa68e1e3b58a9ba50caeb2d17f878dd4862bc347b817a2d66122318064a6cfda6a09d501b01dbccfbe745d56f3052d6210dbbede6929af3a6f5f82fb0c75437e877d20c07684fd3faaa14a39c3d908783cf25e5c564dd743dbf0051a88488991d7e387aaec02567b44e4771163a57abb109b6b0eebf7298b239df9a4e89a0cb521cca8bd7401eb38323ca1d0da05de4460fd43c290d04d21ecfbbb8687a72004ff02e103f83da40e1b174916e8a5228a5d945599cef61415a568aa121099eb230164633bf6d5e736a9f0a8b8c730511905b0c0213cca0468b0f20773d7d2285a615a592821d6ffc9ab1420072c42d231de5f49bef2b12ad72c9d4c189cef45a295494c0f2e4a739c62bd9ed5a46a26e61b344976edb8cd405d89d7dc018b3b0af358384522aedb110fc7400487cc36f8489e33ea61d86e870e47dba19e24a74e303050b79eb38d06956b5882dcd71e688034d56c3b68a3748883106af9b086dccfa1e41551baa1", .None}, + {.Pow, "d35359c1acf428919aac2f6fa0b5190aa0fc9349330883f816f84dd23146580bf28953b1c2a54526bd67509606564dc063e5702c4eb4b7bfe8d48a7ee4c2710950ed3c9db4dbc90b810abec574a13135645c412f5153580f39b8049f098552de0504bafb9959c6071cb9455b265a6ed0221f8120bc6e2dc7c525fbe58706fcfa30692cd258ea3c632ff076d748b6766907b0733d222c", "7", "42de76a617d685a0a83630083ff91cfddf2cce5e51a6f79659b4fda0821b2d0b3cc7ebd53e9c889dfc376126968e37c0d779bf1c9fd56a6f5fa91080050029462517ba7659b9ab873701d59c8a8f86d89517ef9b4f4e0fdb8317eb8fe4abeffe8b93242ff2d66f96e0e1f728684a1669083fa4c1fafe173d4f6d95b8748dbf99e3423068cf2ccff55584684bb3031bcd59e412cf6fcef316ae7c8d336cffc2752124ebfede215b042515e20ba7430c13f768ec2461ea250ba64a9c727a4292568ce581df5bbf7219d145cdeec4298bd0d60ca62146ac88d8b19b4ef57e5316eccbc2dca49c1d72340025600146f093dfa410b583b9d2a17f491e0bf77bc99de0ba7ba39d8bd38d679ff8e1aa9a5a3e9a0cdfebe94775d67900b7d20484442faf2c47d91fcd7a5c268f48b740da20aedf8ce0db03eaaa65dc123c894af2eaee7d8076bfc1d91ed0b64043380f922cb6872dd3fdc660b22705c67507e95cbae2008a3afeeff6eadf003f4209ee11a7ff09a988062e8f1d751a260dae0b10ea9dacd3c13ac47879be499b56dbe7a7ab39c942e10c655a14739e2a4ec47193a310a4125438aa38029bc91d05773e425bc5b362fd0ca8b0c1d73364533d1d392e3605996e9f1c4f0ae8cfead43664b4ad75cae5d4f1cfdec93c0ce74f14bd331c9963afa8ee98edf720180bc9c5373335829d5a4d2c396b03f9b6c9cb5e8a5d01c6fdf5649119cb399c289cc1d758078785c25155cc6d757ec3bbe7e62080512f3ffb3bf65d3d2377b07548794fef079e88fb2c086b5259969d2468850c8c1e42ab61fb582a1be4010be7d8e2da3a8d90f8be30dd19e3aa7ed16d4e81bc104b4a7e47901d470a0f37e53a86e857a2940cbe61a04316efa209086da193a6c706c78b303576763d2a0b00d987269b85629ae452487dc4550f7e97566cf2e67c88707424f5eed3141838c7defd0dd0fba2111b9e855b678c9a2e0ca0285ec4fdcf7d94fc584f23fd32f37d44715f0a08a26a56581e90e1284a7b1bdff6f3cda4e90c44388e453211c23fd3273a7cf3aad85709d5210fb50561d11e94d237db0330f9397fefbc791e266552fa19a807c31669b2dbf81347d36b5a80f724a0b1c948bcad04b4d4b2274c22ccb9be0a4357ffdaa14d0409d0318a24710e6d77df20cf1e21f7b2a79524986998eee93cc2639edde6ca7af47362b7ce39b2d1aefca096279ec06ae9ee79c84fb55c504565a2d63ff4c6e7258c3bdfe35ecc0b9855b7f27ca459e6a3d3804a769c7b2067b2f4a3f5792c45726edb4db8dcb317443faeff23775e93e074b9cb3883cdaa1058dbd2526330a2881dd1de8577c52021f4f8b7a49cfa8a75f4cfe54e25d3a9ab541645343f5b1ed6d222ebb52c1f2cad162c2b0c9e070f1142d6373ca5b38d7201f71c845ec362465b948939f18ef0a0893e0a867aa73a14b6ea277457488c3da8d9af921e890a468dc331535850c000", .None}, + {.Pow, "-24cd5197d865e34b9aee1ea0dfdb6d81045017ec4788f933a6c6d72bb13df3d4eaa08aba0db568695a656372da7b0e8a397279f0c58420a3a531464affa209f044b168febac56d29108c1dbeadbc58715a39fac6334bc291bc6c6560093a3cc74205509cad818cd19d80f7353918bb6223733b8abedc3da1fdfa97f24bd125622324528f0bb7d6430ce442feb0b169b3fcb371f8d46", "9", "-70a0ba0fe4bc5259f663cd04d5ef9686eafa01a472dbd5ebf3722ce8622e57498798d2451d8aa59ad6dd92cc19c38421bf52a1891d2cc152e8596b608e1e53789e6484297bb73505f983d1a0b150c63599d7fd4bf95d6ab1fbbddd2e0d80a6799edc1e250caff0c645ad8cb40237ff22ce96f77a51c644304285474129137c60f4da8743f4c0aab1f30f44662c8b5c9f513c7f1cd8e2878322a221849758e9fb9be0c35a747ddcf8fbe0e358655cdbf9e5499c76a7298677cfbe62ab88d31a0a0e19f390cf91636131b6c67a65cc438b2bf87e1b5202e0e121b98d573d48e78e6b07d2c8de8b59ea31e3e03bc041bb1e3590852054507ecf6a6cb9d4f80357920914f920bbe167ceac15bf9d9066e25387e36dda96d9693eb546f0b74c2c89b2e2a76333752b6a17a02588725601310100f893e91e60dd5441c56b895641f6a03ccff8b04144625935ae7fe6ce9ffe07cd543dc210a35c54233f125484ac4f9e92ec000f3be7b1e06ffd8cb9e47ef89ace41f7a84541c57fae03ab374c4ba20fe03a170755fe7020db113487d25b489b16e9f451f4621fcbcf5066c628fe5b894b988a4e3aa697cb8e8e9722c3cbea112e7c16f402841974d61ffaf13e3318072699f37666db3ae322927618f7248e92de014b4b0b13b09e38e33548f64e9d555b4c41ce4c480b93c472902fdbf45651d11c7ac9de8632f7045a6f412b9683e6fb58c4c5a797124c148b3b7cd1d3d5cc49747a8a630f56883beeed8eeef497ed11588f482974bbeafdcf3414583120bdcd5618fc0fcd6c90a074abcaf3d01e8eddc713dad3cef0f46599c6b0d4057cfc528e650009f7bcd74d91b58716da1e6c67288096b74ad5a626387a41c58f4a5f82dc843b72088d91c034d316b353d7edbb8381323101b7e9d00bf1acd8c7ac081b867a72e29e5be0d652f726f4832bf8c7266cffdb30e12d19752d4856bf80597d6fa057e53597a0b8d1fb4bd69731de4bb5be48863e2155bfb4f2fe8d650e1449f16c634b0257fa6497a59f35559ddcc709927603ea7276f0f0e6585b36d30517ed8025b5ef6232c4defc077e0f665893d59ed04fc1f096662fbca7d2a9a49955ec8c255c2ce94cde7580a68ffde4d9cdca23ba9bc1e65b319ad372900e7f3615a76602a980b4250aa24601a1849e05ce8134aace92eb6ed0ccc793ccdc9e93caaa669103d692f606333cbaa24853132c952b75612932b0ee2b291290ec14313b5f12455d37d3ade20ae679b64375a5fe99681d81eb0d88b6147f7805f1784a444a6b97fbeda3bede0d0844ecc4a8f5f9920a08740c4c53fa0d7e5510a1a3fb03bda1d1ead1ce6c8097c2f38bbc4fe9d627f228b9442b176d5df3b04bf3f64f6b1301e55a5f5c3d5cb7c092fd25152ec320a7950c86c49f42fbc845247f28f21b337cd2fd6668e70c8be05c0125813e0b60ef45e3d087bc2f40868fb97de312f7ad455b39fa518071f5312c8ba7521360e30c4af25a32f678122dd51428b0fbdb21c9907e5d35318adf6a3153239f6bfffe2f8ce91328ecb9e08eede9438314bb941cd13a96594242230a78e48a153889b1ba9a069c1d2d0591aa38013237921438683d55fda339a1a64b09db51a7c5945a3be9936a86f9d1f19fc8bee1b4cbdb024fd756f2066cee0da7cdc8b39fe219670c91176c68f940a0ac6cfd29ffd8c549b274cf4a462b1c3b75d6f715131eb6738ad7faeef75f572e64d24b11c50b1b5fe4148e8eb20f7125ac800d2babf4651aade792896c1adae97c57b7c072792826718c4acc096ae1bf66cc1e4e0b57d37f809f09787eb4f01a1787a12411ba625f1921748638ae6e174f057f92d88b9baf795c3768abd0136b8b72910baa86fc0202fa52398142cc5c4f9b90600", .None}, + {.Pow, "-49deee9412bd3083170518a620890be3a84048d98703989798dfe1c48d06d439dad9f91642b3026fca5ce95991ac90fa8a268f3e86a4152dd7873d3edb681c4c145dab0cc363dc51babe1fe89643eeff915725dcbce50654ae6d92cb5f7c43c49effb170144cd0960f4345df7048bd05983fa2b53bf13ce71ed2fdd310b747cd7abee2119b36e42f98980c8a0ea608a8c338a2112e2b", "9", "-e8b603e1c0f6e559c3ef86925cf6a6d83cde2ef5307297e6ffcf81e3cf911cc586fc5cd2f7062215d885db8903bd307d646194cac2eaa865539c927b44d23c2325629574db4575029921b92726e980cde44d353650180b90ae05cc1b8637fac62d4d64a5c34b30cb6d25c9c2dc5430fe38fdf5b51f353e1d7671b331d9584968952a2fccf1cfc3494e4386e8aff1639286679aed47856e2b651b1a63abc786e3112612b2e89723fa2aa6c858c9cbf5959376774c6fdaaa6263fd9895e119d1e342b06118e46725f72006a4a56e9b27fb96e7468d5c667dde076b75b57c46b62c39b3ee9a669f26d878038906f0cb509364a9e45a24a86b12693bc30fa533861faa2506156dd69ae105ff6fd1112b181e442d7124628001d2fe20f09dda66aab658ac26a75a8f50591ddd2b70e7d3b4a6811b00aec8a286d90a25255a48afaa45566cc9493eabe161fbee65f5f37421e2c70c8543ea63847ee2548d2b313a03c855c084e7624481671eb48485fa85c4950deedb23f9c9cfc87542b30a38ee1ae6ecf7cf07788cbd9ce6cb89a7f64f9c22441314dca3e4e8252744b425c89c9d8b4df901338d0a765e0ca32c47a44cffd5a06c7a5ffb95012d9528e4d8c260dc6414215f6161ccd9e4faa122d46c0b8abb482697f846711aa06826f1b4670bc4a94e0109233bab5e82efe1cd4b3729c903a99a93434577c164f7ac779ff4bfdd88e7c60eb0f6cc78b97b6d71d2af918e6a263c77a40af64869e4baf861f232897a43974cca3c9a5a7ba09cb8e853c55580af9ad2e51b1529a1b13700cc95c44b542116e84bb0eba8243476771dba92215577ed14c59685359c859785a9b6d67b8f941b7ad4ed50ee7277421cc3c52243aa017996dbcc007e604f07bdfb2c4d9fc25d859242856da1f301f63ad878be13b5959a797c76ecb2ab384e1787e9b2e0509eead2187b594ddd38bc93d69460c666bb29e766291fd2023b26b00b7a70f26e9db99e7465b933981d5ef5a3081ba8862a65edb3ae2483236e87349f90e974468e5045113b90ed0297bf69b14cb445d9402a55eb85e1754b45e609bcbc2f9a2dc888c53c0966f931347b927af9b70c2c22224cf7d010045e3876bf279ee5d01a76f33cf87da73bfc3675a19be65cd4c990b98539dfe7c69897fef690609bc2bd0359f3b8bdaf5924f43f769ed09a5f0806ab8cdda8cf721bd723de2220a574ac2ba7646ef0bdb7b1675fb7deb21f16f5ab0852bfd57064081f2a1f5d0d97eff66f3b2643fafc00aeeb3c446f3884144ef1a04c9a257b21fcd535440b1daba642048d5031cf8ccd37116da25c14e9af6dea85f7e8b1906bfca611f2283e654f16934e4dc84cca64d25439fe94992adb92cffd0d820aa4a9ed13d764b2228fd0d1533e01c928a51c5a4dccd88d416ed0940adc87786255701681ba2c926640c73d8e8c541b494b2322940021ce959c08e1c8b41f51f01300b7cf3d7107b3552ee34fa80c47b4eaa3b348aeb7f2dda89ad95b78d62b6f92534434e63219f54f03a38ea4cf46b731fd2d6a175991f3483dec25512e618ec3b8337233b1266ad2c73aa289bbf925b75d050e6f8c35a1a3c74755c22fa75f8c5f029b7d219a12e3112dd42c4aa9f8d62630df76e9c080c914defc42219c82eda8482f5022863f498151ca09b0173cd1d6035de0c861f2903b102a2096ef0e47bbd8f66ad85c108ddefa6fd5d32b11c772e4f2b0d0b890ac208ecc8ac0fa9184020c12621d4ee00398dd601a2d13938eb04cd5f856c5e28b016e1720840335adf6d4ebcf86a60ad1226dacd4223f072f5d9a9ae8f9625eecc284cdff2af4994b930c55aa38815bee1d58130cf2a280ec33352b325754455bf959e6077fbc5e735a96a7a48a6fbc434c36d103c84b", .None}, + {.Pow, "-3c92b9d91821cfe4caea5bdf043282bd48c983cd6f408c0236f9c2c1e64faf45a7d76898eebe29ab4b8dcaa110dfff8f74973db0c17e03710921537ae1c1c80996ce554d76bc1b70ee784405be3b0a63f7a2ab961cc8bcde57e3b85c9c63b826763d6291bcbf464af532e8c64ea68e3cb3a8d2241a70388fee9b7f4369e50a8f84037ed551c82307446b7aec7921edf84320a461cd81", "7", "-2b8a0dde8a444d21cde3bc3450c334cb8b5de4d9cb6139634dfe161e7fe4ba450e5f06c28b457df4bdf8414ed31b03b05cf17b36f9960bc270a390ea49014fccc385cabd47ae31753d77eaa85d9c9e1945f9908b77ea90dbebc7129f81aba99ad3911e9ea84e41bcb96bdb26726ade053cfdc9b48bd57dedfba0e60001da119938f561813801cca3be8cd560f318be9b37faa1ef25c586879020f388439e50c931acbfd80e09544d51ffba81b5d9c88609e4193a4b2946162f4c647fc3d2796cb8c21326da9f5e1850bc88b3bcc798160086c904e4480902c8f680228313da76ab606e4695da7bd9fa8f8ca09665ff456ca3ad0f36796ec0394bed8d9431e2db551afcc191bda392a964e634cf5a6aceb4bdf93d73584d07941f08f18ae6cbe03ca86ec94d6153dde3da93e63de8f49d350a077db7e338e5110ea62b1f12de4f032c384df9ae5139b638f8c7f1d39cd13154602c0086e0657ca8ce6c83788b0d9b96d24b7f5950e1d82875a0e5b4dd22600d1d0800deeb414d53ac1ae1b8c295e160b284e33ecd6c0f98812f4d42c526b5054f70f5b81c4b52ffdfdcc4abe90e47b7c5a7d04d5adfcb6b4835fefab8f3a456c22a9fe120da87e4a1b0ed36b0e8a7affbff988e300599f5d84a2c1567baa78a5a71bc814af764bfa0d772afac7b23af6f2097e2f0f63199b4df6ac02a11a7f28d1a17021f8119ff62187349b4cefb382fd7ea6dc06341f6f3b7aa03b4dc7ed6a2635295e79b89091d35732bccaeb7d00e54d55f44813be77fe885096aed5f8ce8979aa350e9900fb45bf3ac839e8db8bdf99967718c54292f854447ac01a1903d352c89b3bdf5d3d1c827afe544ce28fded384e375c3f26bf0d1d8f9eb3d6045afcd004c93fae4b3c07ff933e3acffbf52e73ddfa89edc793022d6f82ae9f9537216dcb0956d6b267a758690e0fbff3117ebd37510d271fd03638b682cbe376b296e34d64f333fcd3956fb25dd0754e39ca822b93b989d8cd3eda184b60461178b400c538955cf476c109f6fa98ff62cfa9f7249c3c9b6a0ce434c20578c3f6d1d1e7fcd172157c2f5d12fe09c856abe16c3b138b83a968479cfd122f1fa233cea26b1b65ffa92f25b58b4a93b58f06dafe1f4e5b8c0eca7196cf03bb2cb55f2bad772507d3a91446432ed3b3bcdaef7e14ffd702ba40c64601038ef28fc43033002fa7af30fe12c9b38e04759ac7f3ddc4ca17901ad59e6beac098f41db8adbac594697b04340c1980484338adf5ce5fae6a74f3a962631da2b7c985b8e87c1410ee9b38703811cfeaf8118365e624d4b956fe5a8afed30ff5b91f64289fd4879d40a3b11fc88f3d11013d235bf0b1efd2048694c5bf9ccaddd494ebd341edea51bf94ad1193e6de74a39a9ac43961e93798a82ac470b3430aa4f43161026df12442204f8d5cd8167a1a998a6ce7aa1bb125dae17cf33bd858130b952b147a669515effde81", .None}, + {.Pow, "-139a8e2b57624f3cc256b284d82676c9cbedbd4c417c1f72691d3a4671ba4f5de7abd59edf380821718b85a32c4ce1a19196ce3ce03124f34086c0fc7739f5d7062c28f3e8b27843d68129f72af4e6b1c45a5131949063a03564d7cacda48ac115e3466795e45503739f08a64aa92a9fa5d01e91c17bff501eb6b3accede54758d10d64c4ed4ff296ad1c067fb0cdda10316f365f238", "1", "-139a8e2b57624f3cc256b284d82676c9cbedbd4c417c1f72691d3a4671ba4f5de7abd59edf380821718b85a32c4ce1a19196ce3ce03124f34086c0fc7739f5d7062c28f3e8b27843d68129f72af4e6b1c45a5131949063a03564d7cacda48ac115e3466795e45503739f08a64aa92a9fa5d01e91c17bff501eb6b3accede54758d10d64c4ed4ff296ad1c067fb0cdda10316f365f238", .None}, + {.Pow, "-60b543fedd07f2e631a8ddc39f064525476718dd2b3a695979b106821edbc64a5dd801e92bca288b0938b03f32e608682cd1678e66703967bc6e9a2b9c9734a8488b3e25f1ad4de4e1f5af18ffb6cbe157f8d4d975abcba56d2647d376d5b1a6ed9ea99d07f763808cd94f2d63ae67cea00bf7b8a1c36f0d9f143b5688a33d701953d85a34fd2de2cadf9fd729987100d5fbe41226a3", "1", "-60b543fedd07f2e631a8ddc39f064525476718dd2b3a695979b106821edbc64a5dd801e92bca288b0938b03f32e608682cd1678e66703967bc6e9a2b9c9734a8488b3e25f1ad4de4e1f5af18ffb6cbe157f8d4d975abcba56d2647d376d5b1a6ed9ea99d07f763808cd94f2d63ae67cea00bf7b8a1c36f0d9f143b5688a33d701953d85a34fd2de2cadf9fd729987100d5fbe41226a3", .None}, + {.Pow, "3d958ca316cffab9a26305af411ec359a7649facf9f3e6ae0be04d066fb95f06319ec991dd14060cca9c9a9b8860555363b5dc935bd09a169e0ac7ac02f9aad634b0769c89ce38cf7e306964b6239d5d4e2900b72dea3adb7f600656eeeb1d9818c9beb7e1ddb6bb1a14bed58cf05f979845d3300a00a8e6560874a4684169c46606f390e8a74fffc128af60ec3861c5fc24bf43edb3", "8", "bc2bd87a4506b2b13f2177a37932051a3166500d23cba1b95f459e4ba017b5a8e9546abf85eb54c111fece29957e441d7ae38b554bccb6bf4326d5d486231d9f9f4bc92743a1d2e43f5ebaacbf2de64897052c63a01176786fb5e815170b833644beb7b3200ab09224aa460248869e60e23afc723f9e9210623aea7fa0bfacd30de6c3c91a80d65ed32482de397f33d53449bd03a218a89c828e72f4c2b287c7ebbf8454d7495c3c4d6d26e2ebda4a5754ae37a67a76f2e0d6490a5e03d03dd607e9d7a56a33b6375a6c6787a0aed5670bd651b70bc16bc14dee88b7aa7d828c9fa9d75c11a0c6b6c113e55e86f94f40e3f07fb0b161435abdb7a651df6b1c4bcad558826b1e9efce6868e3f5986fd1f6145ab306e02607b744b3096db0bebdf81e31f4b1d7f76405a7fffb08eed12624eca09de9c503f0b336430b0287dd011ef46d28fd9da54376b615dcadbde022b439eaa42127d802e970c7e538d47624ecbb30a29b3779ee5a683eb1bce274310e53d4056553a8f20609ae5c50bcebf840e7d29ef3b3e93e147e6a86ee3e77ffbea99c7c62dcba48d18ee5adeb41991c0a1db22abd741b213216a05c4039a1d8489f641cc155795e63517b7da22a51d25260c3f1b8960503ab557a855b572dd39d81966fa4b91e1bbd8300ee8fbfced4639cc27669118b467eaa13f75c240b52e394843f38583c1dea8102a2f4ea9a074d76052023cf3eb0371a8594cc3bedc63761b55ccdb13bf252bb5a13e5da6e37f31f4dbe7758521edc20c28b861bcc94c9618e09dd346d4e6c778cf9f03f0b9f408f83fd23bb94537f1bb623da8233ef672795cfc0da39aaa3a40bb4404533be720330b1e68f01a2fe0eb2b7ad8a8d2d0b9858a17380d8e4a06e58a7ae78d881b5b4e0a564ea628111391b0085e6051a7ac012b395b45ba8e750cd2b31be2c696ddf33f366ebdd0fe1e8bc3494e171ba0a9b7c9b7f052343258cc78aa90c81aa5adee90ea4e4e8ad618cae82e29684aceebabaf50810682978684165aaf5437b203b08c39553a13c558eb70cb092ae540449d17978fc0c55f3151028ac43b0d9303ae22f285237fe479edfbc8f95f4c105fb8cdd3d28ddf1d73dc1167c548095822233fa7a70dc11fb21b9b49ace9892e52631937d4ecf77658b226a9e791e9abf3063935d094e128d1e551c94cbf82f17703ea4710006487db0411f3129e0252b8145067e00545fd3713ad4c7f2c800c35940f15c74f1bc88ac7de7c238c857c3ffe14eac13087cf8669e83a989846adccfc0297b06cafc9421c0b0c3e6b16bfd1c14ffd7889d2d1ed73bfc61745f2066f53ffd2278a2866003a964d26aeecc235acc1754e8061e5cfff401f05f5612896820ce8a438727cf51c48eb32fdabf7621feec2e5d362fc286a32d683a5645c6eb5bdf9fb85f7488be03794cf2a099029c2e64274fe1f37f2f63636dcdd3ef49bef412e95332131ed739b75ccf3a03f68025fb9f5fb99acb4d41743749cebcb42834f116755450d10b2c6d3c857a09425ef572c952fd2fa8fdc9aeb50bfa7c896a162df136ced2b86536eb6e834ab25501e1a4866c2b7dce8406350965c01c8a2d654215c02c9bb256e669a302c99a2832f566be94ad7bf29154a9bd99029d5750ab7f0a396cf8c24b4fff217234cb43574a4798032b2ea1db09e466a21", .None}, + {.Pow, "c02ed8f74fd7b89e324074a7fd28d4c18db4725e7f036a52cfef4f27819868161cb57159c540350d1038ae49ed4b35cfe4f8b03ace9a6252e3832f43709b19fe31647361ba9907e253a90f5624037f5898ece0c665174310bc29be4f9fbf0aada5e9ed7dbb5b60af023e43984328d67c56896865d6534f33de534618e1d5f2ea29d28036a0b0cbb6be55e9af55dd7470a0b380f62e8f", "4", "514f2b152076fa04d211671a31be42a33ddeabcd232aab1832b28a15cf02322a0041b4936b3dce7a9e2cfedbf5ced0475113c2906ca4a9431bfc7fd7022cc8d435cc0d25fc2783cbd811ac0de3d306bab9a8fea200c5b780f1b81e972c0e10f70da00259895cd8e1f60bbf75f13f79a898b11730eca1f97a89b16275a59fe478b3bc6d5cd22c3ce77aca431f6e75cb8b16516c31e10b59eac59bf4a98f1da39c014619d5b0543918738b0c305a97e76d63075bfef4d9cf1b1c989dc8832a123a11c3ea2c82153633cad37f73cd9737473d16f1ad4a24d49068579c8bd532c46721deac2ce584e5497dc13c861d33458c775f00e61a670c6dc06f9a69abdc83287fc2641b7812927e1de2be7adaec90ae805ddc864fe033f108e229aab57d04d3d2c857b8676e97a603ac3640350d793dfc87f28804b0262a9602877154ca1811af38ba973ccb5061978748b74da09cf62f315294e73e6782a0bd67202e31024b65ee161470707b17c26fd6b66257f483c9868daf7639e1c4475cd2a0d2d754db8c8ba22fe608fbb92d0237a5f3b3354595ea07064fa3bd058a18ca8a14fb09a524ea2421598494c246b679b9d3d03639b2981a448ae8394a679643ad92a81305897c2d6f25c0137f7878270a5a24d1d4df1ae7eaa48a2bc916bc8b3d371cb62b60b86a376ca170070645d8b0dd84fa0341e4df854202f2b4132340e3564136d79c2590e3317ce80b10b7a8b07f628e18f80598e757de5f12814ece8836ebf042fce38e048bd2c3cd2e375909fa3a0b5de7965da413adc39c9937381be7c5942cb277de28306752f83bf758f856d9ffbd03751d872a3a6bc1", .None}, + {.Pow, "2379148c426421b07a268daf2563a6367126b46109b6159c55bf5f534899117eb2f1137575c11b48e50b1c705eea7daf8a126317ec277bb4082697f2045fd15b062b87a904d64dd8761363ee8b75b5bf2eb9ac9c031c0c1612416cdcaaed9434db305b987fa6e7d2ccd44d71daddb0b7ff1ae3669373d5eebddc54b35ad5c9f8f4e226e23e742d4b256147ca228f5f450be0f6ec2fa4", "5", "3590da2da7d4cf2c8945ac0e55f49d8b90211e757caf63e7cb0352bb2bf7ea1ee2073261a5827ce05d5caccace6f1b176986c958f6dd03a410ef7cf03b742ead49567195aa9172db6286e2588561b591b06cf542a35b8e1b4ac88a7270a251a41842c6acde5bb971e43a5f4bf6e9d7d9367bd6a8e58ef9e54fc95ddf6029890d08da9be7cc0a0337d206f4c020955020d61b9caeb88b1bdce78525ebdf465d1c964fa53f3f9d31da21369a973b4bdf6f02f151798888edf587a99b9fc181af4af97598cad40aa658ae55c758e8447904427aea1cd36689cc91ba65831afc750f720b641886695860c440660faef6e4b984bdb622a37377c6425a3ceb75821ffe761e3fbe2b5e54ad58311afe20069bde98f63e00a33ad1fb9aa630c5ac4761077a729fc8bdf9d2bb5212b858f9ba3f33141b9695b77957221fb953e312dcf068f7f73892d201d8ea62930bedf2676c0052739c63db6a627b7f568f6db58980734eb6ed8e06cc21ceb8d25c927b3d800be0d0ad570b391549bab538bc0d3d9253f52cdbe53a95474f357b32d2a6cdb34ef35c845b5ad651230a9d19ba7abb05e01deb92dbf6da18c39bb30e644f5890bd0fbd78a918996731382068818f79a12281628f35b94a0f9e1190dbd79aec6fa30409bf2897bd29ccd534887c0ad3c5b168bf25ae854f2cf3b7dc4bc0add4ea3889a20a9490c63af23b4f9ba118bfc9c046302d49fcf34b4f65a7acbc75c4ae21340b8ba7d577c17a85139391f957421775b97c7c453a9da293393b465b8c527b9dd47bdf7cabaf29f079dea5024869030c49191052b1b83c9dc6b363825349a72efb7453dff06c4269d985c8bd86ebbb4474f549075c5c048d55b202b73b259e70014e95853e77886bde451b0460af5705aea61b0d2bfb74cfcb3d87082fd3fe9839760e081892cd17bd5e2444b099c17927183b175a0259c0b453060712599ff146e4dc551e74660c68134ca226cfac1ddcbcbc20ce8c3a78cbc74b1863fcba821485c2db788c11db0e1a1813ec23611ecb88ef8743e5313e2182400", .None}, + {.Pow, "-3c90ff0534f346082fa6d33ef5c06bf30e6b4a888563926059fe864d28f804d15bd2efdc4bcf4fe4cf01f1e4786aba3de90340d16155004c8be1fd99237eb77c9e3d55461d05a1bda49403e6dbbad67f9ecc44e2398c117fb633c44044b692b90ad568af59377ad2cb29c6f833046ab9e63afacf033211ecd1b6d364c042914768f3f15f1c1d7dd87878e6bcf446e6a53906f0cb214f", "1", "-3c90ff0534f346082fa6d33ef5c06bf30e6b4a888563926059fe864d28f804d15bd2efdc4bcf4fe4cf01f1e4786aba3de90340d16155004c8be1fd99237eb77c9e3d55461d05a1bda49403e6dbbad67f9ecc44e2398c117fb633c44044b692b90ad568af59377ad2cb29c6f833046ab9e63afacf033211ecd1b6d364c042914768f3f15f1c1d7dd87878e6bcf446e6a53906f0cb214f", .None}, + {.Pow, "-c825ca790ab1731d9a7e9dc86921c4856af09ccd4b7b9f76163b67e1c3b627204089b9b94f5bc86e3271ee4a9581479a6801ee8bb6854101ab858a5eb9b42687b926def5803a9a6651f4f2bba8ae5d126e5fd3aefb2ecace07dff61cba0f7e1d6c500526dd6f08fde80b3ad3fd7fc0262627826288b3ddb22253bc55120a505db8013c650b7081633b2662c3c5349cdaca8cdb9ba1bc", "3", "-7a573f9130db657e83ae6989af36a92032e7dd8636ba2c63c205ae592c60d84a766be2aef76bf698687c56d75d161d8090f6c1dc43ac6c86e1020e73004830b222842de026321f12b62f99d1378b8746621aae86f4d0b021539045cae7816b63a19094bb212378037dd099b12055aa8a39401b4de0a5b1757e361a7e6fcd64824c38e0337ff13ac776ec20357b8b20768b91c3a59bca0eb2c517528a81ff0a8d1a1a525342f1f08534ef42f333ecad914230799d5c339bb874855c133751c81fcf0ff68e00db505df7320e3e98e3fc5251889d3f8b144ad7b252259b0bb6b50f1c0849128dd0fc1a8374e140b59f4faff96a85154a677d3a4b70ca6d9a55f0de02a5624011411ceec39d847643a3f57cf537819bfd7e9e55a555abc8f04ce2880ddd145b5e3c16abbfbd5a9a8a271dc33207b57cc6382581ce029b397725f3226bf08bdcde3219121e74b7aa1859fbba2ab619530dbc49c8f0014db10b4639ccdf2f5c97530670e3372f4fb3cf307d4834582f21e4f008df728eb84dee69402b176ab978ca1f156d54a09e7c54bb027c5f8b9eb94f10e2de988b928e979f69fa465e253df68e498ac540ea7b622c17cfdcd7d5917c9c0e3ad16139c184bec82593c0", .None}, + {.Pow, "-55c4aae762e4ffbfe5512c00b39b0404ad926c3269df4ab69145588e91e9f3bcddaf93cbcc5327ba68d278b0db091c76fdfce62667bb104685ae9dbc8e6ca265b32b77485f16bcd1575c7fda53a04cd8d6cc0bfb64f12cb45365ae8b517a70337265433f88dac962f6a6d5479870cc5156ca1d7f510b7ed0997dd3816f9ac389491de2d92a1c41c8ad6fdb3c9bb4194d1d27caaa6f28", "1", "-55c4aae762e4ffbfe5512c00b39b0404ad926c3269df4ab69145588e91e9f3bcddaf93cbcc5327ba68d278b0db091c76fdfce62667bb104685ae9dbc8e6ca265b32b77485f16bcd1575c7fda53a04cd8d6cc0bfb64f12cb45365ae8b517a70337265433f88dac962f6a6d5479870cc5156ca1d7f510b7ed0997dd3816f9ac389491de2d92a1c41c8ad6fdb3c9bb4194d1d27caaa6f28", .None}, + {.Pow, "-30de7efa00159fd2f5fec0c584e0a2355e43b4b5475b7f880d7a2d9ce71a1a8795ad6b07b7d85f254b401d0174448b230759480f4bf3f0e6a7780ad541680b5c8877dff9e3e36c212098d7ed914b8055bdc26086721e005445240efc4aee62c939879bccfd21dd3f9d6384fd7bb550406a0858d1d78a7b9dcbc9c70586b348eaaae603a7e41333cfdfe1ff1df5338fef20dd82ab7623", "6", "32bdf3181b88c5b5d8eb9164c25a435459cad4b8f587b162a973e2d872fb49d81ecc339192b13fbc6b34579c9db89f1b9ab67544bbe467bdfcdd5633d1634a90f894f9014185607e3dfa444a616ff2802aae3b1e8c5dc0bcb787f630d72ff1d025e99e3d93cf524e8b879acb22369bb759099781b204e030a9971a219981e120bc49a34e9addc8a52a9bd777740c226ae6c130e98408ad400cda4f6f58b3b99384eab2a06cfd2e6cc052bafc7c693bb6e02187e13ea42b3dbb67253952f965968cc1b1ac22c0944ee34256bafce680f8b8d916a6273a0b1682cc5326363efb2e7f99969d36a543bb5c9fccd9606568a4258a62527d6f419915efa9ce9a45664089958a6436b1db9cb365024d60802241f01cd7435204caf8f4c660f7a6d36b5121106c2a6353a0b6b3803907a3614fb6ce207740af0140e63bd3eecf70508afe73c593cfe5e37590c081ad32136b12dd6326c95c6b285cec450b26295fde78de2a44caba322b15a41f013ca7964623b5b5488e809f7fa60791971cc1ff6208583d9d2908883350062059af6ef9de5c03e9af2ffd06df7dc16d01a9c220383703842ee742fa19ec9db1ee8f9eb88a14ff515db07a8673e6ce67e63c1675c9ab049a6c1c368de4efa5321fec0645daef803611ff765ddb58390c309685626b4da9ac00c3c091efa0cc696240d54b851a00758f022101444a75bade2405c88c53f36d0f2004242587f5c79ae27f02872b74c1dbc3f9512a335671df9bcc2516ed0aa8ff04824e0dc8c44a37f6ac82cc6390a1be90c1a3e6a917e863d1846578879e8539c4660480dbc2b0dfa7080f83b32c0c376d52db763f6db2e756031e7ff88af7ea780145e51a4d5c23c484c58ab0a853fde63b39fb1bac9d50465bc41af04fdc9dcfe714a6ebac7c8b50e458139d9cbfcff53b678dca72cbd970d3a23a2cc2cbe7593f7bf07c9826df96089c73c5f8fc160a8f5a2b2a7df1b8c4fcc4c144ffb18629faf8ec8ef2972b5192794a92c078e322dd10974953f5af17e7b40c055eacfb97669479b83f31f206c6ca0443235d77da638d1e508d48efccef6b524c25920a8149c64f6095caefc383f4ac37b82e3f3387509531b54587c2e37323b1092b086a71241bcaf0307b3a2b46a6d02acf7af11c3a3fccdc597c09649546517a03ca41e476bffaf157e5fca09f27ef33bcb71f61764dcdf82e18ac9890413f6e39dfa7d0f5fc7469132638d112d63c32a5e0cbf4575adc97214ff8a4aa1aebcd64119", .None}, + {.Pow, "-e44f4a54d9509d66c629d3f66453b8645f59ab7a20ccf8435e6aa8ce27516faec60bb3d6a04ecc29cce5cd1d385743d8be22206b8826f94d3308acdde7803bf3fe28634e55cbc12404b55e9f798746c9d578480971881bcaadf72683e062942f63762250b9a43d7c483e2f73c4953f2beee1b51a870b110961e6913fe389a1c1c9292eac2ea95aa8e4c2234ddc6a73a32a2b5ca6aa50", "6", "80cf23a59a17329eb5035a0370de4a59f422649b1433fe995f52d8d9491527aa1e24f7439ce8ff40888fee1d26cb0509cc303e6af03bf13b404fe41d8af0135a5770f51bd42403989ace9af28736b43c69c768ebad290e6599671ca9aa978a05931313c0d21f989ecb3d3f8d86a9cf45c2825ddacf1d614ae0d003e6ea3223b4cdb8fcbc0e51ccdbdf2908651ecf674ff4bf889cd59da60e9f63f95f005de6cbb2c0046316c6076f19c019d92066b78069bcdf607c372264330ea579c099bc6c9d6cd382b0bd3e764202d41aafd6dcc226f015725ef66926422b23381818cd0d6c7b39198e97cd8c70d9a8361997d1e57eb9b9fd4a4e2363f64fe5bbb98eae714b7b205fa6ff9a1e822bac35abaa6c420dea0bc126ac80bce809a05bd548101491cb8081f3ae7eab25c994fd59153d918279773a97507df6cd36e56e329db25ba25e1c7467309d64ce1e8180ebdf1d5bd13dff653f9c76150b5877a734bf66bec9b0400fd429da2971a86f9c85ab88c123965b631a7e0ad7bf2aee082a7af384a75ae1f2c4c0c28df500f044a48408133fed92abd3defbd2649872441699d20005d26853dad0a023922dfb00ff1a0f999cb69929ffcd02d79809fc0ee86d5d0acbc1a4a9326cb34c33012887fa4f8a3c6645a68f46c0e7f39773c49b9d761ab9596b64bbea63819d629f1f140e57262a19147d7d1911a85f2d16d81009bc4ca595113fa10472452795b65dbbb457aa7b8919919dba44c899b18b2c2d4195fffe9f925efaec9afa1338ca55fd48f2379caa78cb99bddbe71d2132806dfefc9276a28a8d5decc0c6f01ff8944b5ee3363171d558c974fe4411270bb454386bbc8463c4aa2a81066a7b49a8bec2cb29247e1928fff69e776691eaabf6e13df19f2a4058b7c2e148c9b7c002ce0a676adb896c6416dcb9036925a95c9b69e82ccc6c5784099ee5eeafa7206e453d7db6e7281e0e2d656dc59049f6452cd0e2f488dfe6c11e2d8235bf642f913d7a95b09867099961de2e0fbb5b225b05510a5c8e5646a7536f52ac3e8019330579079eb8e98f45e9dc6212b15ae8428440945c52b2e384a66cd4bc9bba9d3a7d3145649964b41ff03249e8fb482aa3c575ff83fb647a926eaae6250455536f4d7caedea1dcd59e054cd0124215add88d014d8d99d6522163f0262d0f1e95383e789aff9e4452643b8b5d887431d321893396ce534d73baa44230afc96d15f965b79c9217a360f51b7fc6875b94efc467240343cd4bc9000000", .None}, + {.Pow, "6c39877d1d3626266e958fb28e14ca88af0b673343cda50d6d32508b06c716ba98a867597591ff28a6198d208eaed1ea5902b84c42d7a648f796f761f817510f2acbb3f50bbc9d4c30e074e83e2c84ce4f63a1e126a08f6f973faaa71c078685344de23d7d535a50712461fe2105b672140b63ca2bdfe5d4a68e5d5c0d3d79de2a05fe0348e1123a7f433ef738b02dc337703346392c", "1", "6c39877d1d3626266e958fb28e14ca88af0b673343cda50d6d32508b06c716ba98a867597591ff28a6198d208eaed1ea5902b84c42d7a648f796f761f817510f2acbb3f50bbc9d4c30e074e83e2c84ce4f63a1e126a08f6f973faaa71c078685344de23d7d535a50712461fe2105b672140b63ca2bdfe5d4a68e5d5c0d3d79de2a05fe0348e1123a7f433ef738b02dc337703346392c", .None}, + {.Pow, "3d6e44aabcedf94afb8148ee0f616d0e985a6b9a59a87ca88340b083fc5f2ca9d765be17088163d1bcede611e2bf89db059ac29e3b102a36abb451921e2677c415d87bcfeddbe60261f1daac0bb15d6f2cd470bfd6bf27fdbc51986c2fe8c29c3fbdf49a2f85ca3de3f6370090663b878237e0fac0e0e4c64bb85480a26c99046866d240e993ac3695b7649397228d15ad1cafe02ac0", "2", "ebdbc38732eeb8ddc39106c7f5b7dc1698e39b996bfe92bdd510cc5fb79d59aacd71cd16e1141f222300923c5d59e4262c1af3380da82ab93b7a17f9c51e56515bab303924eb3ad5fd7afbca8d59e1e50dc76a9ca5b593ed7341543936b8f6451e62d5e0bca27b0b3c8ff01bb49ddca1259e5a4b40c5ed2109b875458e48cc25f4e5e833b077d098ee12d109b914f1934f090f82dd8c3b99e27ac0a5988a3fed2b7a3c356c781358363cabb8a74e336eaed0dc6325d5f666a680a92509c77a1ffdf0d7f87412adc2faff42555a7eb85b9bc1a7c750f8396f64f6c3469f7f6e73dd1bd2a48e6d54277a0d203c70e68daf71a2f623db1d303fbf6413aa9e319a87fc33c462cb6aa1cc1320ee71fadbb0cf3ba17052ae162ded753a57eff5470f7b7fb6dca6f2518bd57239000", .None}, + {.Pow, "c61c83ea4e04d29767fb5b8ca43135e021a6714ee257f1c04d4c744603ad049b1d4b099812da3e7af91586db1852f17d46da74295839b805333416479d7060ce5c10847649b144d338ad75cc6ea04e1394d79bdd469340563550c7100afa63f18fef8ed63e90d13f765aa7fec1b6fdfa50f3df7c7eddfae8b3ce7ef8ab7e4db324c00d82105cb5b7cd011d236fb5d716c29a4057201e", "4", "5bd0de68bb0f523370d6c936cf9af78943b72b1801057a6d70ba19bc39e912d4261d588125693f4afe989c53049346f5987955d6583a006db487464eb0e5b40c1b56ff8bd47beecb6fd150d1e5bfac11d96c43f754197925aeefd57be97a650fb4debade64a24b77c387a500d805946217c7aa2f1f653cdb1306d8045c589142d5445effaec371f3611686824134ffef41134b0b89bd5a27341fcf62e108621fc212e76ca697e1f1def3931e85471e84638889b376e2e274beb7f0ee9ce0a93eabbff0dd289cf36ccba9f3a548f7ba0ad15978785a2f3a9277409d7b83f0947afa46eac7d9994b7253dfc1c1abf4417048db985ce1b1b6deef24743c4cbc3265a9fffd98c2325aeca66d73986ec2442a53d5110f65fd4a86a8609fdbef3c48b39a4780d5a328f9cf082787034320b5eb67c2bc5a2499dbff62b1879cc2dddb27d3d5aa588c73669ffe985363c308228e985e7e01c858f6a674c6d897fa8b5bc72db02bbac2ecfb7e420bcf82ea80e7d82f60fcdb8ec704b494eadbfcd0d7472a3147b2b81e91380ee709bc064897cc1aa32046847d1f6068154e3b0c624f98b4b72731c1a1b60a8bbbcea125ebd24a3ac958769bd3baaf0b96652d9350fb4303f41d0e60da06a08db73beb8b7a79eb2e8b0c322079a8c2d70fd3e3502909678d36ba17b753c56ffcd23615d0fd0950a92b6eed21d33c4b1e8cc7ea30867221844c0b63a3497e5457ac9e01139b7d70eaf53793a0c6726862dee04f338dbdaaaf65abf3d1504b1cb963c6fa53a4a8722f6d9d5221f256012fd7c31778fca45f1f7b070251748bcac71efd021ad89983056343847df3e85c10", .None}, + {.Pow, "-d8eba2457fdfb048a944d9fd2ce08f69cf330b3a5dab263c1e6ad5a961b115ba1d1516f1d4775725f4159889c0d10e3c8ad32b9d83671820a845109aceb19fb19aa79c49d6c93e4df1e7af40afa6eb1ef2b4b7fb1f32a1acd08abdd6033eb151905b9e0abe22f03a52b56103f5757598494863c2255d7e5bf339ff05bf56ac168b64317cadcb385f21aee3a7397f044c9813cead1a0f", "2", "b7ce7ab89a3e46dd8c9ba606857a792b8c7577e70dc0025947c2abf6c0ef4c74634ab10367df71dfa672d742ff6bb89f3e3b0c93112acfce6996ecbb38a2eb2c7acdc2efdc29cf204bcd09c669c8b76b609552b41ddfbdc85bd3617ff2109abea60c1da99f84a7bc2c7fbab3d9bf8e61d82f1e448aad6b61090807bb61ba8b18eb9a25d81cbd57de1dc0de9de36cf95bcec77534c11dd0ca449d2f1c927013fd3355cd07a40e2e0d2c23f1bf7dd31112d33ff1e43d647335464e3f9b33a7d3743dffd0442ee34d1ba8cb760843544fcd31622ed49a3a452a49ae2b7f208831dffe452dd243c98235bcd25791a5ccaf912864914d775ad0429ff52593dcd16539c65c7a480e985516c55c3ced26315ba143535bdcf02cae7d2afbd07065521dce037c2f6fd466b9365eed0ce1", .None}, + {.Pow, "-a1a23a78e07ec9bb39bea04be395126d613c2e046eba6a00a8caa78a7479bf0dda1ac3914c34eed4bec1cc2ba70d70bc44808f64f011992ed9f5b50f11b00580edd91379eb36655105ea7f7ef2c4c78f6c0c3ecbc65b66e46e0fca64642ec488178b80611497a8cd31fd50c8f1031c19e51e30e268df54d13c0f20c4be5d75f574c7dc47c2153256bde0b4e97b716232875b61794174", "a", "293c7d64251305e9ece5f671ad7214d78fd39f4376a795d4289b965e89408195ab39e3f1eb785e7dbfb63e99021625d88fabc3868e5b373a0034dbd594c2d83ded50346e6467e933d54e456cd8412c1a867fdf4e7599a826ed64da20136711aefd3182c9d5a0aeea5502c9bff7506c968cbc151733c90e193cac3c7ec90db74270d6e35ea4072b861a235e0dc27b12c8a803ebeb0b54068f51456ff4e98ef117fbb2d5602a7b34b81ddafd5b4bbed8a6d305956aa66b40aeae9ea15f7dc41eb3aacf16e5ec9c96cfa869ee189e130c17197a37e1c4a5e80a312b535ed878184bf54b3588146467faf9c49e9a10146c725b4180cbbd2aab4c246a9917bd669570d323af235635c8e7b26bc17e557e7f488212f7ebbc1b2a2a085c167f6f809fbf5bc6b0663cf6344e93b83eaa51109018943b2bba2f13d6bbbe4e7e877cb5fb5a5a8722dadf44c730d12079e46a733cececd43af52468d998c4c533388731a18dcbcdf844aeade2f960cb6a5529dbb3d9a8523469bf5573e33cbc554985af76deaba0c7d028c89c5134943016b1d3c508fd9194b55802d4dfabe05aba91624df8bb9547635fa49b78db03c31c5166feb6351295ea596b94aa23346f117f83f2dc6c3dfe803f238d1f9047ca8e2f0803f7b8c4d4bdabbf7429476966753ab0d75e02dad28e38019731bc59fa2fe363804830e60d50d4fd813a3be92731f2e33d25f940e0bd4f93bc8bb84500516b6ba1acc4d2c8d8c3321769c09f4779c16bb1a0ed79ca148ba31e93b284abf3b3da1c7a1c5a5cfca7d0cdcc7d13d55f362f11208048d15359b263523f9b04dfd85af38f8070c18e9e7fabbfab5ab9edfce639ff3d4ce442b0a5d76c982346517add85e54b0dbcb51f273dea19ab68b08ce2a978fd7950dc368703082a9f19e75272ab56c3b0cea0d45eb191e6116132ee32f9f514bc77327556c126e941ce7448c5550539bde7a8314d2517156503fa300560091c5aa4d9d72a0d86a6dbf10c846f6aa0018bedd850428d63c0f20ff88d9b852c97b5ddc9b990b25ab57f514553b8249d9a84c924709c63c2cc78a8dc1ead20b413e2666d5db2d8b0650047bb68d3eb6609caee098d972b31aaa88f1ee9d0333255f59428ed9c3499909b591dea9dcb3be902090122ad04c5dff874937a839e121493f3c4b91e8b7da94db593c6db2037d6e784039748348af471ebe412ace8a2cd086fd537eb6ba55adeea0afdafe931f2e09ce8cced119405d64318b73200b9343d96b94eb338759c8828f0545efaa1c9aa5ae08d2ad9445733f8197be49067aad7c7c576f8fa3c1591e867689a7b6d8fbccd64111fae0837c966cd85559687165827e7eba0ba2cbdca0cf01e5d33d3955feee464375fe2f8e53246bf5acb392b76576c2f6c67680e1485bb2a82c2e14e3feb0eb52d701b3a22b0520c364517c265e94d2316d84e36cfd02fec9afed229bca5152ca49a19c6a97eb1a3ce0dd21ba37e35936a6d137596a7aae7268cef51baa9bb195c11b3e17f7f35ab1ada00e514c4d1726f309151a0ecd999aa797f5f01b367d479745310b033ca224df27fa02f96c0def1e78f73aa9a0a40e0fd0c0397fbb641a06bb1342b84ff518a4dcffafbbcb53d1846fd97722eedf4a1531641cb3f856d18f1a0c4688804cc185ab46f390df659800080d1236ed879f4e0acb027359b89118f5c055fb0cdd191204debfba629970b60fdcf481296126792decd21e52069408f807b2bd48cc21608f0cc54f5fd17ead9c55ec0ee26050739feec770b0328d48ece3bdccc473466633d1232831df4abd5604cfc7b80fa8e6b3b3942b598b59562ea0426eaebe8e9ff41c29bb72b213221cb200b1b75dfc7016b881220d6cd3b36b2fe82ea936cb8fab0bbab7894720c5b2c7cadc5db626b30a18c573084204ba2e46da2ceafa881b8d90bc12802188dde20e08eeb84c86751927e7c4c6cfb568f921576bdf9b70cbed27f15c11d8da92efd57b6ac7ee051310b0d43bfcc24c060139d6d6da8c97606958019613a670a81d8034e1bf447baf7bfb286c4014c30f41c3199ceccb8c30a28e6c65054473326e3405c0382561b0f4bbb245f0dc2f356076900000", .None}, + {.Pow, "84d4d825a02160d2e56e377a624a219c20dd055fc93b2023ed6914657b59173ea7f99d7c25ae683d2cb3e5e850c44e46ff0cd3138fb999dc38879ea200821708d9f877db6dd98f6852599547030ae41b6597a5f73b3f8cb1ded2fa455abcef502d0032c7eac0a18ebe921ecea50cb4eee4b2abcf525d2defe693d4030684aa5fcb530728819ac0b31abd36e31613ecf98b9890198842", "8", "15852d8a5243c1cfa3d3581faade6f1ecb02327cd7f8159fc84d8011ac52ee99c9c7aeae75e05a15dd85eeb67a12b4cfa5464ec4cab890dfff725d41f18b91e1c303f866726478852a80a543a20d41ae7de05b4ebee1d9459cc9a678f71f1dcdf6e1105cba0856897d7c349d7287d3f29828b356e42a71befaa913b246ee263dbd08a925492922648c34fb38f8194fce50bf74acaace0ec223ce1037e2bde0c25bd382c41913b2f2952acc2c4a8dafd71b5d18525e2d2f001a93ae7ab8329560f5b3823a7eb22b776bc41aa57712f81b2b3251d3f7f88be2be5f6a5b5398a54c43273ceca6dcdfc78eadffc4154fd14dc1f247b19b498e53b9dbc09ded8d274cd206e2354b2e960691200cebf12a356214ec70a8662ac56d5906b1966b6fa965a159da284e9761c1237b0cb31dd766d910e1be5988a6473a79149afe7467066b237f59a0d7de21e06a602f7ddac69cbe698a21a6210434404e9783b0277055509846e6b29614bb9f69492d1de04e6cd5c6d5c36d5e2b5ce5f5de83b09381095fb8e4bf0224bf294593fd483753382dbe8e5f01a244b140a355bd6f5871c668e7844dceb5bd9ccd2b43323a36a4ff309847e881683ef7f38e07be8e11882e5b6318bc7f808493afc1bae3b0df8ebf570b462f72dc839b48ac10d77e7c0ff41001d2fccf980788356e9151b32cccf69961725e7e42170791a002f0a3a32c2a48fbb18647204c7a4f45695154d064b74e1f8c057a4be279ab16ac4714941efb1c38a25f0768c2c432cd0ef34d9c126ea5902c8b70c01cbdac5e61eb2ff950af0bcc6b439bfa9cd2dd5128eefb90302bc96d09c30891f2a15b15b34dc0332b2ef814cefa0d4bf5c5ba46ea5e5a037aa15e92642a4839772ba6a2bd7ad7f8d16c865e6c14dbde5dddf315838749e10422341d5596d2b9abc5aed8367869d0a5d38c4bd80f6ed3fd68f5de1932ab413a86d2aa1264d2e3a3dbfbb46b98e8ce472b6eb78821b33601e39eba91b59393ca3cd4e1777254fa1c1a0defdf079060ce091a281931cff0fd8d727a68bfbf767f717f7422a70b48c7edb7d2b2301241ed969e95cf55ded3df197ef95e56142afb28c2ae64fa4e5ccfc0bea32bf43b8e39f28561413ca00a3fdf3994b7f66cbdcaa4aa1814a29b7811fd45b1bd10534cb612ae4552cc7b643005904d4b47ac08db5834057f31f95b8f6feca827d990f221aad8d730a4f446835343bc5f14b36896c2c770bd28f06023169111ddd355224472860588d183d88b2fcf10d9e1f1b949e4056acaa4b978e99abbd65621c1de1d8435458ec0db3c14864b1738e0a65be41031c9e7963d684abba6351b54cfd3730c0c63347a96d27c5dd01f1f8a6d67e1279c6bb8fbeb2cecfe2d8a28422e8525b71d87731a010699404b3cd03f6fea56010ce969465d7196f147b0f31c2609857da7e0ec1ab9190ec9217198cc5f81a6a5d640fc65695ff21722b370a65f3b844aa50b79d37b0f4051dd4d5cc22f33c8b947f55cf1d7e01158bab86f5809ac35cf693d168730de264d580c241d99302f9bd0083a3137a13eacc3e3e2aee522fe4665bfabf2a72a4fdfbd868cee233a087cf153f5fbb3b579bd629df942477f62c6ac25aca7cdfd291954fe4e064414a1e250b96049e7ca9215adda5193d64bc4dc9b66c1a440c6c07c1a3e2805dfa7e910100", .None}, + {.Pow, "3b41c70505c8f01c47dd7d839081b3b829e5c120aba4bdb3c425224dcd86e1978d64b6a368670fb3495df9b48fc8d4e2552901f210a366700674cfff5c9b5df2564401cc1abe88930286499ab0c1d6cecbe648fa5ee5a59de4a90a01bd2c5169516bf7930ed6668244d30567497336f8ebc01cc78545d5edb039faf4fa289821e1860f760aea7e2e83b6b66cc9bfeea3dec1c17ec58d", "9", "20013244696e361aafa0a4ea46bb7a2f9d70d9f0889a3386bbed9f158be1b671fe6d91f4972e75de366f38ea6b2734d3d4d8caefd7f84d8c536f476cf3ec23d38d73d1a3ea3f3e0bbbdfcd5e80455e5c00fe41eada523b34895abc1250bf6566dc72ad8228ee397be03fe684b447ad41b49e24cb23fa33ea45bb66cfd1a16485581010521a3619829a2f9a997685f2b1bf5444c96c284871038d94a1bd7dbc4f4fd45adb4af22c5aa8843fb6a4fa4a5edaed0a993346e6f0e0916079e04cc97bf08544da0515c0bcab41d9ec938f0b79e93d08803342be38943cd1c91f3a96bd97a3c9acc91950c0c6282c1f4f7133f69e30716140af2e23e064e480a9ae28212a645093bfcda05ea2e871d1306bf7f49a7c7972d76ed9df9662824fcef682985c3b4469727ab11106f90392f42ffff50c49905bf4adcf96c55ec8762556bbd66de0cdefa71ab5911fff1a2da439813098cc8c09720e1bac79a2e453b00f383f57e3b5f0b4ba951c6abb6f4d3a6c0602442fe2913fb21943bda5bb27eb900695afd4a8384188dbab0964808152f45aa0fbdef6c6fac81336bba54edfafa9ee2fcf03c704537f5941236289d1bef12c609ca202efb693575bcee9cf28dad84e7a38fc4ba63dd89b58f152ee43aaeba4b7793328e272b4612a4782227880e1f7ebce56d619a305ddba23606290d7710e7520c7d55e7d8311700f0bee60f3ee05540f8a85567f6259ba170bef7853b3fc8c2a95125c5c0a89c9f16e32a3a435872441ffece22653c4b463016c45845128b9d6c81af0cde1816426011fbe87b49119ea051d293726f17ff67c193f62d18b4869d20b3e0a7f70d74dcdb4a658e6e9c2896258020b674187d30292e0cb710cb5370d1b5ba64264b34db6062e1e2fa1cbe62a157c5482bb1ee459bb31de29e5f687ba564664c8962af0a3f258c8c2848b8770ccaa4447cc96d7a56b01af72f7aa385ed044c2eabb971eab19f552de342345561076e201a49b5ccb636b40ac08daa49e02f24d480f40c5b3f81faa2313e3dd352e5ed0c974bd3c63c22c00578786f03266256651ca19dcc4e2d7a6bed05091a956ebb0a002d969b7eddfca408acd0ec73b8e27a4a4235859ab39c27c8cfe7fdd1e58db37fbc31b89827a1bc80021f7c8deb2e2a38f44f30546c33760ef42f1d8c0b3d168125f39e929b2ddab9c19ee4b5b33e215c866d0c0396f72e01fcc8d1f2741e147d78ee7f1ca8a9cd4e4442a8a6a39e3245d4a8e3c9853caaf994f186c7a751851aeb9f6fc53bb87cb9a5c8c706c9e710171e7731b94f7aa68beb49d5e1e9cff8d6e6d76f5de2ade6164795558558147c70236e3a3dcb47b987d0da3fbca2980913d37a3a440b8fe6c32c87aa73ef2801d91208acf8afae6fb4962b4cdacacd9e1ac948c1e213ebd77754660027b60d738bee1a1b9d5b902954917f619463719c201ef615a6f603188fc5f5189811b3325f81ebe4043e0176cabdf560cb0c19d5ab026133c0bf64b02b7cd4694f76ade534697ec7e2faa3264430781857b268bde34850fb80626a18c8e7e4a57ed5d03354e24015396ad11eabc17f77a51cfa71593ed897d89721e8dadefb05f0ec58ab542988cac3e053886429a965140f576f6d1310e7cd401d8876f81fc47f37620ed6ec6350dbb7493bc688408d8a6970b6e1006be39be54681df97eb7ac53b9c6462cde28f551fc119c1b3b1ff681e5c3ac22de1abb072fa240a52f08d5998ae485447549ee39e9526af7a44543cccbbdcbf4f2e1d9e2b57b61fb4a652ea4104d488b6102c3f910a2cfb498f4d5672cb885f193c7a9b85f7f076feeb893bb4844322fdd5f77ff0ca2588947a71c53ace313370b147a13a6fbc160fedd20f899548f54891fc068b88a47582136e3f32d", .None}, + {.Pow, "6bef477eefd9cd38e9ffd4b45752f33dffa6fa9aa01dc17296ea3e74381ee5a688df3108c9c5747349ea9329c8592d7769daf3533939cd75559f1a41f6845d5934cb6f9e7421e5d6fb06c48c92c2ca782d50463200876b508975816a08759e5c4f6d687fbdda1d08b2c65a5106aa5ff4d8e4b836a186b4b55f3dfe33d3993df3845d41781aa7efec7b8f986f994102a65024e31ac9c1", "5", "3692489a0e707762d86c69af8148f3f85adaf1e799c4d65c571caeb9bc36a571da84b7f81369a9684982a67db470aaaa95857097b955fd7bd4d3ca525aa4c10f0064f0931b711dc4177edf7fedec266b8304f313d888a1a9a03ea667bb7dcac6b29b22faa484f9e934f118b74af6544304170f1bf7319e14d7be12e4753a90f1dfd32030dde468dfaf631f13243fa2106e97d7fd4dc324f1c66dbb961b192557832fa7117f09ef70028cbdd4822771b554a3997de1592ac0da15b600d7a37e6da10fffd0eadb07dd606967d9d94796c851049c13c8885d57c431b4acf7b4772ee9523841212f584c8751d001adb68a0da5abf15d06471542a374dc4e36bf1a1b2cdf65ddb3d0cd105b156e2c4c490bcc57c60bc0aeaccc97174aec9a8a137364a110778cd5e08c13345bfd840e8c373d9dcf24f0a1e346e0f16f62c107daeafba51a827f53e20e59c0964f7d86f3df4822e9274c743af54fe4baa6deb2671cc5cfb0ab2876889d7cb692c3c1b6c1926d5099b106a87d615eee2bc63528d2cb57f1755d7c562b48b21f299634e7867dca279d9d3a120db1fdb70d887fd69a597499691b9e8d762232faa8aa888cb80db2ebde126a8e64e4b54d876aa1d6e0c9d4d75c0fa100a22a41249e79354ef648b3f0f565ca3abf281857523db22148f990c0e06d9e41b18c1b6dd86814f5d71f117a19b1f42085be8b9bb00c1f71d9c647efd960c538bde3ce3303898404b56f21e07aa6560177789d4ea729e0ac0dec3fba8659180082583f612ec07a334bc5e6465049f2081f9c9aba8d619dbf3385339e876fe16b0e76208416b4c996a00a9ae9d2a661ace0f6442714e7b3806bb65a3a0f844304e8b981b7f785c1e1793e72333cc2ff57684c8c169acae600003e2c3bfecd46b3d8b66572c0c157d5766018cfe3605b3dcfef079edee98958b0f93e4b8cabcc0c6a3fbffc41b997574451b181c66cbf1e0660a3b369f46ee334f0ff47f6d033aaeecbfcd03f4235c727287a1302d5c50f25d3786dff92013281e89dd35cb68be1a950bba0b751490c1", .None}, + {.Pow, "-91f2df9d02f36267013ea5c5c70663a1b64a297d8e208c601c44ce8d87b22c40185da15f2ff5403cd9319957409faedb58e196a2c6a65251a89b744d1ef9c81b71a20dae2ae802f935e4ba977ba76c15fdf54dcafd5bd63814af666ce2a156c09a60b3406bc1a2c35e3d6696230d7e842647d7b734c7353087812a88d18191b993a38f33741cda92db2f1259214a3a62cd1ac2685de1", "9", "-1a0fcc93a174b16c7f198e8cd4372572070d6fc471aff9360bc8c73354eb04c3517581eb45aad02f22d371c4b953593327a031cefa44f09b6832a1f003110f0fd42b1e8901a5e5dbda08c7a9fe899b4c9bcbb45da4e3814a318cb713e97a5d7bbe5bf4fea378021378213ecd8227e6bbb439bcec9017f27d84e81603a64ba832ee17a46c91de3cbab9721903613d96112c2273b0199827f5f495d821042d1230b4e24c35f6dbfb1d7cb931ed1a3241528d38f1df7f1a06d8ec3fdb9e4f1d83a8f44174aef4a5b711e069a9a0d01b032754bf6c719868a1bbcfac6950c727860f8cff7ab7535e2f0d505d4e643f10a26094cb63c4845f8e9360d5b77cd2ab7d3ae31bc0c409464f3e338584daf035de1e78f404421cd372e74296ad88e25334bd63b07a4a111efba4396b945515350a140418b5a8d59bfe3ded54847416d0da76f03b9b7c972997e75d8c22e4ae40c29a6857c603ad9e4db958ae8274adc833af2eb661f63d9ccc5cfb60e8e4f5c8d35135f2b75efe0f64966a1e7e1f0f50fd41f356a61a7f64370a5cb102aec3a13bbf8db947186dc64ca93f92c60f8ae37115308219dc624307aaa3f78b0d311a24bff59fb96973c0b2a76b35d4310c97329f80e311f7abcea4ce41ad959b55ca72694acb9df14621f3b1558c6c8919c947a560dc887a17918b6c3432f82a9fc5f879ca65132d50cfdd01c4438f90f5aa3abd35702b0c59522b21c7f58e071458578a9196c9cd0770a95ba9944bd79d9922c124cf9eeac7acbba543ee0fa60610f17e659bc1c1f7a3f2a069e256fd858a738b3e7c718ed5199e04587638b924789a85233d3ddd3fa1dc397c3ab5335b39e06a362ac2d5a241d1a68d4cd91e7a43a080c7678d7a01faeaa931bbb6158dee20392529c61967f514b2bacf8b77f04e3b002f327600d6535069fbff84d89f13617d37b5f75c8fda483e7760dd38b5dc3546f3fcda95b0b2ef596752ff6414e99b19098a5aaadf8f9cf9a66bc2d233b7843799bca33d18ead6dde5a45647134ced994f127e089510114ea31e16c1db49e527413d301d9b90d0261825d15a655bcba8494fe8ca350ba55404ed8c11c8ff1d4100f033bf1846205f178a397b879499f86cef1194e59f48dc5791f5d548ce0c34ef7ddd8ee7a4b5842ad44f2d552137de0bf9e996764cc646e8e18cf2ff0c9046d9c5a2ecffc7cfd4465e9d5fdfe310adcef389353dac88dc52936168fa0aab61d02db5b7e61ba7d56c17653a4f46a7cd30a6ab4bf0af9867b0f9c700c89d5ac07fcff612d952fd46cd8eb50247462987cde6df843788b3eae1f18c463dca7e52abf623692af88b899dc78f860e8393b56daa00b387d84761723c94475c0bef50f14aaa3aa54b925a04c3ca452e4835a930917ca594a6134b703a0f7f3531052f51212235283cf4e3fb74411ed3c747187690759d1036bfb0abbad9c281045a48aab78a5e9e134c23bef51fc03b9c2bd9d167b3f7cf28e38ae912891ab24e204971b70522c1921b3ca3720ebc803e2bd0bd48d69a369b23a539c61108772aa3026d3c76b48af811c67d95fa8b7f22f94db601080fb0705d8be545effe2838dd176543bed52d9aa15b290bc71b360cadbe8562c427b338a8fa4d739c6e6d5a3a30eb25e485f631142a8488c0d61af0e962f7ad2fc368d7939deb609d767cbb680ccd7c998b755b4a0d52db9b275ded507b6e3d93e53673ca45fe547e83c30fb78c86c0a9b64b869ef75a53d65a5cc31b5a23b19959f368627af86d531ecd069afd245dc914bdae83592bdc458915055356d65d9ba6c8d0ff1584f1111bd57a802d508c5c03fe3f62efe2a0470e8a6f221a3d0a74e0c23240af49cc3ef1e22439fe7fa11566013b9ebb63b2413ff6f8f9d7e849cc3dce1", .None}, + {.Pow, "-ff04c50e34c99da12d0dc6c2f0e1cbf6f8bed4b83d3ba61c3fe36879bd84ddbc467662283e7286514344979f7ffb01468e3adca517ba92f2999fa8108f4c4adfeb5787694aef8223e490eed8dd2437ab79e31c19cdf0212adad58eec9701f8f0dbd6e1a76f99ba6aa698a792e52fd70ad4da41d47e843a7541e20f2eff33d253faf92087d38409b9b35b074d53a6b6c9c101c60f4292", "7", "-f9357bf8cff4eb7ab6dfffb6ee5a06e4a215be913c5d1428a72ae95af5b163bf535f7088c70dab705d1036c9e3ebb1bc0afaee376926c5d4349f0d59c1d0b54ae611c03666b6bd2d0cb892eab543486fea506d1605c4c20aaadf010b21182281040a21fd4116d50e9e81ebd12e3549ffa8cf7421aa13b02c9ef4b1bab2ebba9fa0229bb70fd6479d6a8be75db978ff6a8705159791065fb33aae39f9039460b8776d9f957dc45bd5d6fb4460c5f2db8a7de58a994f662b71eac2c31a43e9db0e8420ed4a5cd08908a33cc1d3ab3cd8a50a9a66ed07d5495dce4ce0a20d70fe9953af93e78f05c77cff5af701ea3354921459f04ed8a02a5fab8d36afeaa1880b59afdffbb47d15727849961df037392ac790a212060656d1e63ec9b1b3ce3149996f3002093019a6bb1d68d4d1c289b5766eee6a1f9f0cf75b1ab3d1acbbd64f9a5c5fd5ebbdb73cd31ab9894ca30d647eeacfccdea3530ad5e84fe91cc380da31e9a5862f9c30749b57a8b598c73f25fded16a211eb867103b6124e2443b8110200ebb4c7aea24a2ef6734deaf5ee255043358a10d40af4f90b05798ce40871a94610fd5dcb809dbcd880b5ca0689d35b51adcc3026c7fd79b3aeb3d2d6c4ef727807b92a4380e54fd63edd23cd5ba55c9dd642251feb603daf855335d70c163989c1842b9e62d7a36f071f5e0ea0c09b2b711ed69d5d40eac3626f0839a40053840f1d1b94328058e2b5ecde4326d574ab5c0be5a2bb5dcff5ee0fdc6edbe6126475ddbe47aefbc739c1dc5d5b1ab9651b46f0e951bac3fbc311a26587b39e96a6edfb18c053d51e3dd01371603fcaaefb4c58d7f2d9166f2a5a02ef6112a882edfc81df708c3b344c3677311d55c18d5fea0bfec5ff4cd281630bc7e1e98325ea409efc582ea7043e3b9a4283f72cb9120501c0d44af1c74b525ad52f3e31ec60bf39ad10825686293acaad272a1fb700af8cce10709d26f0ca5f6cf91b6386318a195ea4c642933e30c0eaedb1939879f5a4fdcc67acd4b316b47359bf18b32639138cc55d3d08e7d31d753783fb5d778b0a8e2a2dfeca44cbc97c15054a9a822f823d818059b1f7651ec478a550a2651af0f1f1e894ecfb7edb4798d69963e4e51f7149baece17fc7596aee04257ab514331d62d09fb3cb4e0b68991b38ab2b6dee44084e83e3e55201f1670c5d075a672386e3889c599961ca47bda9c37956b9e2c75395866b1acd18a0d8af1c022faaee5d683a43ed2a4223dba6e518bfb6c85e2f10efec5242020f4a4a8fdacfdf0a2fbd9f8e9e149df25e293029456098c1e14b4d85a1d0acd1147eb3ed82ebeab7090dcca91abfb45d65b95690b9144eb2c64312652df6608338c31c359e9cc65671e7a5ce03ef37e9be6a5d4b0cfc6d911897ae4069077711105a40574b2c6834205d4ec642aa1202c92bf23e83a629839b1854766151ab5156a05fd103616ab1e6079be9141c80", .None}, + {.Pow, "b8d1732d81afe32195f42a59cb2d85adb55a41623b6eabfd92a39a53e1fbeca95a822e931c3beb28563131dcd9ffcb8a6be9640090a12ac7faf08e142a7f542562cd4d115b65945d44cd55f0987bc46a7d49f5dfe2bd5edd71d93c7acb5478cd13bdf4d1b0419aea0654f92192cea4088195c1444682589b90f58fe2c5ddaebff0b4019d3d170c7b01c8cb319785c6eb45cd18518563", "1", "b8d1732d81afe32195f42a59cb2d85adb55a41623b6eabfd92a39a53e1fbeca95a822e931c3beb28563131dcd9ffcb8a6be9640090a12ac7faf08e142a7f542562cd4d115b65945d44cd55f0987bc46a7d49f5dfe2bd5edd71d93c7acb5478cd13bdf4d1b0419aea0654f92192cea4088195c1444682589b90f58fe2c5ddaebff0b4019d3d170c7b01c8cb319785c6eb45cd18518563", .None}, + {.Pow, "-3cd7a84397006cd2ee14512e66b484ae88d209baf11dec5d366f73045480233d6e9f49658a89e186971fb2e0672e53f7afb5fada6747b42cad61d27938d14435e62102276e2539b0550ca862c1fa386d872ac600745d2db42ed3916bfd97e58d78d26b9a0060dba7faaf082d727ef8bd0614f267c6b8f0531c5ca98624d3f4dbc016d6047d7f439ca63b3f61499fbee38186cbf6a37", "9", "-28970394719d8becb23833d6435c49b1afbadae02e0d17967ed0f36e29b57aba5b5529c4af86fafaff2f420125d47cbb7fa9d14cb38375491161ee00e2f53cdc5a9fc48fd0570dd71fcf686169b4b084e7edcdada8fe8c37a82f70e59bf0103f94b3843f85f7641bd9bbf7d8abdac0fb0333a9dc2ae03e65b791ba1e9002a7b9824cffc2f143458f008b83592a22a97962a85ae29d83b5648984cc52cee3a20ace9cfb0ea209297e72e6a62ecfac79011d265c44e656a8d94fd64fd1f5a4b2dc36f97e957d402e435833468fbb8d220d2520b36a9e9cf55a0b309c7b2899e4c8ff6c98780d13b0d232074278e7285f3d73e6cbb9a6b1d17b9daf96a19896062edf578b47f4cc4bc96ecd64c600654621c6f213a6d3efbcb2ca0ec88b78b684e13100962db74eb10662fd5d71dceaae62cb88f927c75844e7f1e50caf2ae5da24bd5165773270c3610300835b8fa5a71619c2e06b19911df35c42fe97091bee2f3b1637c2fa513b0229f9ed1eba8f3cd2318654b7bad8511fd43ac60eb9cd7b6e897cd9214368e7b93991641fd0f5835f3898669397423939b86455e0063cd351e28e9c7ffc37b7138ff077a60e12d811e98e40b1cbe731621e7b33c622a7e678e23dbd0d578e10f0ce66d7cc8d80560ee75713a42104fad3188d13b06ec977d2b08615afe208e3c13783b5dc72b6a1772031eb903781b70de79653fab8b7682e8f62fcfb54ddb9aadf2fd82d0832cd4c0eaa53c4babae9295cd0cb04d19ba85b119e81f369b6567efe9cfc715ea368ea26a3c7dfb827c2f148332e8f1b8b07497084b43a5098d1d44ec31e464e717b631ffa7184fd43e07d1cba58408f192e5b25dea4c14e37c76258cb7492dc61f9c0293d9aa112aec70adfc3066c12c8cc0cde64697a7719327cc28b9f56eccb7731388c68f3833bd7e3c279c2cc7fe8ab184c8d7ea5146245a4fda7ea36a45e3208bfacd04ed108d916b72cd1d97ab215ff2f5ad91586684bff11ce56df3f0700e4479082c8d46db544ff9cb15b8fd2808abe85cca0d35bedcf8fcdea9fe2fd5f57ae06476e6e413d3ddc09d1e3ee33f07822a2deedcecf29a7e94054aebc5c14c93bfa547d51ef67fe394850828fc58b5883146316d1525157a68b738b459fca08c76370956ad76dc2a7405ef1d01b0e3bef248800cce2a45ddd954e15bdea1aafe284066d464064193118783ba2fd2b65c2415016d4e973925191c64f0c35b0e6ab55dfb4c9909ac97db9acbe991bbff7f0363ec67311083e889744bf8dcbeeacb49516ed6f3fb390409c75129cff51e32cecafe42bf26d98ac0d7bed945159c78784e9958ed6261a0ff74b11b325c12a4335975b608b7068832aa52ace7b737f287a8c406752d4f6c54febf06ec659ce347c75c9dd388d58d6d5d886bf4eb255e1948d95b70e672a06922325d02ae0e182fad900a035dd1364e3a911f0967c8d16edb2858b11f06183d3d56d818a4681a3d62f8584333e073587683ce59384fb06167b9c253e28786d2d1b045b4df726a1ccafebbf7c5eca281d1aef8bb7e4d70622e4a74848e479832f9f419aac0bc217b2238fe3be0c54f44e1e270f7c36164bc3139068cbfe66dceacaae58110152e2867bd5eeb62f3b2ca3e3feb82756588f14a03b7c2212b3a9c6f096cb3ea6d2ec2af674d1bec4a98ff3a7aa5aeb237ecd0e9ffc67a99cae8db038f79d1c63e4f1cc0a47688b2ef7b39972699954f568fbbc3c64de36b5358a7241dec6507e73201100bbabb41a7b967ff8f372e5f28afa92ef0335afe6dad5d1788a496fe8659b708dfa1a3c55e0a210399e27d4ae2e642a06aab3749adc07f6d22565e8fcca7b7b17fdb878de9675a8a5a624a4c0e2daaadf2753ba41a88112c542107baf7", .None}, + {.Pow, "-6372dfd3f11298007b7da74e8a20126f398868dc21b70997aacc96c10878dcc8e55c90e631c0cbdd06c91ff9df4ab6440f700b9cdad2b5d6da6bfc3791b18c6fd9e1ddc230cf2047632ccf1119fb06325127d1d8ffb449057045372bef229858b986d14cd6f4f75774e1f10838e3d52d182925fc6a51a38701b0a599cfb9bc3fe271f7fb6fe419aea08b078fc199c797fe09f8db2b1", "7", "-577f50f91c74af6b28dfb81b56a42fbc72b1f84ddf17609af416de0440ff6214390e50cb289694522a9050344181d43e1f58a0a2b2414d6a496e84fcabccdf9830fb823e50fe46343984aeb26da376ab6804b9db6f45f0ebe4b1a9cd949fca2f919a9fadeb6dbc074a03df4a3d280b1748f4745be59b782c6529e3da805c1478a8e7efdaea455394344d2dce1c29ba7f45d856d9a5cbf5335b74bf41b5fab1287c18872c7934ce00de47ec76709f11c4111012e1a6dd7fec49fb520c1a0c3a0dea9114b073ca2d656f9f567daa10b942e9731b53b65938421660d22071bbb22210f51d1926ee46ebbd0e197e923ffe59ca19e2b9dd2fed0c471aaeb82b964ab2d690849f3e7056a4f968fce54a2331810e0551cc382dda636229bdca23da840921b27b8764f01e3767a749b9ff36dd514912ac9660d43c3c3d38dde35f381962537c76ae0e255b1c133f778921a493896f4ca0116ea7cd30bd800e876678b2213fcd6000628df4fcf755741175379f95e24724c8ce49532cb8cde484a5ef19e44f79e64c27f7a4bbe03b88f604f18a8a3661838b987ab32850f879f5790524f6bdf10809ea0f8dbccf5ac1c939b61e7ce6042945bdc022197c2e7798733a4008f1eb4793333d8205b626b2110110c07ac5ea9d6771784464367f13b977851fe2a43586cb3086ac42c69b4ad59fd9edfdef37f305e52a099859269df6bfac684f39a54f067332adea8722008c559a68f51349eb6b8f438201b137da4e832acf57df875dfc3e257126a2ac123f6572163bdf95101c6d96dc10b7001a3a30d39eba5bf2b4fec02daa646c40acf70eb5473b8e1ec728e3caa662f7ee9116c35c28ad601ae13b73d965b153799f117f2140262f04c06280cf3ff4bf5d1ccf028a9eaa397a6b51735259f198dbe4911c94c3ca6fc1196cf706751b3f61d8df50f198bae0f15bc7f2b5bcb447994e2276fc9f6caecbc30ce39b16beda3d205fed681d6a061c36fbee22d8c9fcaca5fac40525e18de1d080ee193e0f59ab1eb7f86cef94ad41a6a426acdd0dac729639404411c60c93453dbe8dac0558b6eefef7ad8bc4fe2e8b40a7ea6b2726aa8a74b7619663d555d7dfa56981a69b2aec8a99ddde06fe80187633759d79a801a9578e2db46fdd308edbe9f0c74c6393cdfafea5feaa584871dfbc1657e7570db4823a5b7af232a7e4b9ef9f8592c57f3a55792194b95c6dbb88069caa472d0eaaf23d9a69a4873bbbd54e7ccdf364f94b87cdf1ca497a088c775e0008636c1aa7bc6cb5a64ec5dd4ad926b5d084ca8c2a898cd7f1bbb61a75438d24369ec36c630830cf750e7597922acc21b7e7ef61d4ffc186d51c3bcb3522a5631a82956d80a01fc10055cd75c0eeb9a4501b71154a1f08caba8fe1c53b185534677f4554db765fb6eae3206f582a3ac349411f1d80b145fcc36c796577229338499eae75c1c7e717658477d71261fd1", .None}, + {.Pow, "-402ac76fa51be265aa0d69110c96d26e32a0aace4bbeaf66ec4f67a70ac2eb254ffa98933b6e84e0c37ff59c4eb1a66589462253fcad3dff15b4f3833a3a9553c711f9791f3751b5cfd64890f161ae3867454ac1271438e59a67bde81934647ec3883783d472fbcae76caaaaf50314121b212da188d7cac7f8af63188bcb32fdb05ab8c051ae4edfc421e568d5bcc7e0481a20585ab5", "8", "1056581510114a893c2e770ca05bdf7cfb389b0d3291dbc91b9ef43e7f9ee22060942fb0702cdc6ddf80a6b7aecd2bbf33b2c116b0aaee225c3c25bfad2cd4939145ca554f1ab5c668aee5d4539042be0804837da20594bee1729ab22935d4dea6883c40036609804fb59880594e73341d0322e5c0a0573e903b318c0f0869f5e7b2510543aadbe6f0ea1cd4c0c2a6da17c813132ee57f3844f936279f087ad18f9fc0c63e8790857ac9d9321a94e959859a620de62d20ac11f1cbee0ffdc0aa408d8b65ffefec9254f0a4d6c1717e5ebb8ce972478828a13902aee7ff872648e305acb5556bce8e827e3f853a944241e9dee4e566fefe154e6334dce5c3eee82cd7a5a0cd9f5bad0e10704def7993124b751b8392632bb5aaf67f99d5887cbed1a7d8d9c07d57ecdc47d4097666c22dfe1624ef177b1a1c2b4a036f603ef8aafec84cf2ac5f50d8f0a463d6e3a837f8a622f1aff127c955848a813edc102bd941e75617e0d6d219789380b1a5dcd12f81e93b9bae4888a82d126caa1ccbc70556d0e399472d9795f6130f171fc0b02ed7cfb35694c5d7c0e7936a775ef20777a3c2b87d5feac58e2a26685af9d199584e6e91c75ac2121d99ce03b9e6e697ec6c62dda713991b13cf8034b9c44e9732ff0e8af47f0feb29d7524e5ed6ccf89c4a537daa70bde0fc197b5e6c41664f804721a9daf12e44d493af73907c03fa303f14fb2f08d9af360fb41de7e4554a0fc211c7d3601d5ef93a28cc804af62d001303854c56c916a4d7c0ed595d53205f3c67d50c468c9f350d9dda12f8784c49d4103360db0d9ecb8958ea59148d5dc8dc9aa0a741dcd17067f9b41ef0c19985fcc0633d9cebf26ec8251224a1a274fcfe12a91241f986720c76d6b6a5a8ae2c6ba3d0e07e2bd62ad28758f44e7c8dfaa37002716cf5694c9349225538e6fc0aaee5e12ddf25322f98c5ab1946d5960f636fac0dd88ce76da81be6815397d9c46ee4fc14bd716f6e0c62748ff7bc586921356679c100018d72fb15a6b6faa2885595d7ff02b9ce44ee9c2c6150cd807b9ab70325cbdb9a01f160326b3f799d95fed67b3ca724ae099939372900fa3db79bedb05b08a9b4a3b8124bb65137e83281732e6a85c58f5055baf8a779dd69bfe0a1a9417079e60c61d85e43de0cbfa8544c453634674d28ea809903f5b1bd9fa054c3596b6f50747eff70c04cf112f02008d1576e9a448026d9d0f5514a9f5bc22b208299b481d1937fe4b1c991cbbfa4c4dfe881eb819dea279ef78f5b4ed56040c8243b17e3877e13481268c9f8e5672bddd1fd278394dcb0374cc317a63e2a80fe7070d8be482318a64105d57a15f8d1be9f2540abceebafb6676d5c97adc8c33fb24692e5535de2a0c41fc3816c3a34a149ee6b926694140d6fda8b6dc7c7163695ceb028d55dc82c13f39e74dbf4aeec5cda2ddd97ad1f7d72797e5697a3929d7bd911f05c6253eb1994ab4e9a5685f9198043c272945c00c832b3aee43422ac9c48f359270ea04b2ae8d0139a1f10e652c8d72e92213ccae39f9e7fb11465b5cfa295c84db1bb42f4df7b1b2d2a7b60dfea7d10793bab14ca108b9b630b1446938a6eddf18531f941d035d35b3f338b5c632caefb2ce345d1d7837176e6691ad69e1773fbbab0e468beeefc6cf905c88ba8398e36462763e719961", .None}, + {.Pow, "-3e3e6855e09f89532245ecc6d269095634762192a61d4aebb921de669b8e56b01dc232d6c889ed2fbc03206d564b9d19d6df643cd6a9371c26dc4b262c38446ff1566296311f4951e0eb0c6d539277c43ad2bf9242ee893507f3800074c244cb09eef4aa431562d0b67e080700b3c3d4cf01e5fe19b5abf633079576898e0cb5006b14e9648ddc3c19f85e8e42b3104cc62cb108b23c", "3", "-3adfe5570d3d20a33e5d570dec187e430413b4521f473130d62476b607133c8a52bf0293ccad247a7c3d777486ead5ac05b05e8169034cffce9fc45373afea2f28f7c2faca2322881446b53e4c3966998293a3dbedeeb9b97bfe220db6ecaeeb72244b26ea25a1ee8177b7fe0bccc945678ece83391d7cea8137d6897ad390f8fef1acd46151016db01e9c9de08128eea7222aec520e3ef29eaca772d75b6a190ce4e1f25840680cca2d71fb0823b9b9921ec1da7ee489af406f026e6d735aab076c8c8dc47a724feed2a807f8d897b1d702990b84392a4db944138641606d0a9b4eae830c8cb4117a308802c21a1e85d2c28f2442c1024048fb27162d0632c5b677c920eec6fbe4155de4a257db521aadb9907fc7d393736b45f1aca21c11b56ee8de125481fdb1e84dfd1c34997497b3e48481be72e0763be34ffb7c9cf5c5d1f31e487e59aa8324f64a216ad407f8ef5d96bfc16326bbcb96173b67f674c7922af8eab32e7b2200b541d16a2a19c9e1640763e7ecfee12ea6d0e0b4c2e1b4f6bf2db769a68f9fe910083b696fb57058ca3ff98e8ee38f538dd299f4b1b7e4def72c3de5fd8f6bdb856c2b893272da9a59dc8156ac7d6ef58d52fc0546ca8abc0", .None}, + {.Pow, "-a2ef2fc81c48182f21dd295680ad7ed4ab14a70c701dde364ebe8ad6f5ba26486f1108e6a98db7c20aa1362c63c4cf8083114516b40c3156f4362f58f665b52f2e485c71f4eeb1ac351bc389509f429b9479314e9cf06f715dc43eb8db6b87ce8c59a84ed5dc19f7d11d14c173b17fe4df71872c110844ac723415c96fbbc2d2d7aabf4ec378942a2475fbb190169a4b112b59f9c009", "a", "2cad5df9923753141c13bceb017676a9813e93817adf7f9c56778b5acfb1acaa0ddfd4413100dc3db421f61ea5fb9876265bfa1d9bdb1d71eedd1657222096029df8d97fe280aa9228e8fc02121262ba22772bcc0a0a60904b2529bfe48e192f690c0f61de961276a82ea422ddac7f7b860d2484e9e5539a7695054e46b42a79390de31c6d086a91d9a577869f4e0227348c8787cb7af33e9695cabfd07404d1393adeaa1d523a6d2093a0e3e9ae226d2a49b61e41486386c3fc4aaef0b099f623f8d5642dc225747ab8fde0141bae545037df3e46273344d094b1a09511ea56eeba31ae66b02b07e3bfbee513004031dc20aa514bdd7754793bb73dcd5be7cb5bdaf22af50642d2fa8e02111d467efd680036faffaee8de0a583652eb0248e56a743541ee398c7fac9036ddeaf5847eafc80762407e42828e34370dad06c579b31328a64369c0c1f69d3c3d7ad9130421a8a2b71849a245ff023447e75384d3c2eab3f15459d84194adc1f9b29a0c8e09c47e566b5787f67a7c1fe9a87ddfd27a7776608001be167226341cb1afd65395b608f754fa6a4491ef7f5348da91e0bf907d096871b6784eedee85cf32f33d9e1fac719592ed82345d33fbc2f1c825cc8591eadeaaa52d677851b8b0d2e20fad49be562ccccf91cfd3cd79e8c48fb150cc3129c7b705985ffe0b5ec13afadc7519a5faa40cce232a3174ead0f77d677c24c5e5d6288fc92140fe16715224ac2f5dd42c21f88aa3be78096426cd0e6b4f1340c37b479ead1e4d01603df45aa0bd90a7651a0c293bfa3b35c39f62b589a5c9a3bb7d6c5940c9352365965d1993a67ba41dabf5d04561f4800b2466ec579ac4f52b06720b209259fe19c8be4b3f38a1ca4b01cf681caf80673270bf07d6de0c43cd98e46b17b919cb7045c3d3d1880b1615db1db6d7e68ce687ff7e28440a97a2ef77721b955e7f92ce0004e35a232c2df3aafac489c1f26d74c073a4f9cdbe3347ed283e5e784510d27eed28c263c60473c1f911c4b51452a66f9f78120e4f7609d26e31fb8d81dadf3267a838375eb13ffda88c63aa035d58d90e4b633060ae780a59335c90182f369d15443c110a5071431af2d5182935fce33500d3c8ace31926ebe66d080c097bc00d290b6be889f43f0198ce077be005c197deb5d0c4d9993483524e5e53f7c67f3e305557a1bf51521129c2f482a11103e0d13cd9875e9d574999b4e20a4cf79c33473d2e1cbea2cf9fc4339a7ad17f6e597225f96e130b423705db0d43dff5d7f7681562d7fa1e2d0904cf1fd4b75220b10b212989c0826a41be4316e6c39ed5689f460fe03be43bfffcc2f04d9cb61862da2445117fdfbd51edc7e5e9e7d5a66bc09f950eb0a17bef1e09e06a1e1bccbee99473b2b163998b9e6bcf5aecb9d6a33bc6179c2dcb65636bbd00e3f9bb7f8866ee11b3e997e020a7b029c2661df29686b2145f18ac932c9b1b69ef2251079b42fd201da84b972c74cb990269142702fad64f92cf71d9d84c8c334a2dab8b64b46b41981e42ed53acb1428b822f45c624b6eb7bb79a4f421b241ca0c08298871894f358bf19d61335e475c28753e98cb65ebc3616ddc0bf2f99504d8852fce0eed13cceddd1fdfaefbab6189d3ff2053c46bd6c8b29642b200ba365f6626ed22e67d14898c5d9a3adfd7acabf9e16bef00850697ec655fb551a8901ac825c1b0f9c8f72eed4d3c15f2e9943570cfbe85734d4f1705c68a4fe2a8492f361cd4bfc0b0679482e35da37502b8a8748de7533859f7abf47d472b48eb556d835ec0a5a72ff5fc8830043baeff8bc5c5695fd19e09be0a242581dcd199118392257185a6b895813a6dbf2d0b079a47e982f74d749a39e8443f2940a00dd2fe7a4334aba9a42cc15c9b396c9e45713e2a1119d4b35c548c0b828041b1b9fe418f48b9b99e4ac9a532dcfaaa17c873fb81a1cf0fe18e46c49a22c18786ca169dcda047a4126d82b1e4bf92b2fc7f08f4f16251b341eddc81237b26baf0ee31b21cc411901f8983cc530c6e3a8b5214807f639e15d182b36a724c0c9040ef01ff13e91fd86493c0f9e40a1e94efd68d79dd165986a728c652c27c7461244b819b91", .None}, + {.Pow, "-e495efc303a5544cd86690d661cdc807f694153b0b09fef649a9f1b5d8a286a5bf532e0a1dc7c86ec1d8ae8c1b22ffe22b1cc6f5fae241fbc17d935df2e40bfb1ecd01e6d311d31e1874f443398ae41e0d4331665e7ae8286017bcfaf9b530a51431c17d06d6d89f9ff6a91af9cb77ed7f6f3be7e939ee74cd5bb872b12d4ffd4af132d8eb095e731af698e69d448993ffad4b6ca46d", "4", "a2bbb54ba5237d4bd5f519a5e646a486f6db93861ce59e63ca6f709b096ed4e541918e02ab34325572dadf708f122c42cb83d6ff12287ff76774323404432383cbbc2e5b478f137a526eb1d2c6356d42771f07a70106e43f493d21dcd27f74f3e6bb26c89d93c6c71941e9b6781719b648bc913d8de1e99458e33ffad89622d7343ad2c14a52dbb0a5f1e958ade11ce600a727c96fd07e09833de9db25115e5ce07ca2b55f89c099e33470cc48749c67d1471c38ce7f0e9aae575f137b65c54af7091ece2397fa4b7c6e218238fd4a5f108d76a4c44bce9ba5c0ae4d94a201d1a6dbfee8e5d637838ccd1e22f1ac4c6833025131fa7aa9b97d6f04671345852eb9c3491fc8aebef4c4746b94854ce0a48e61207233e44928c4270443e1e43e3a308eb68298ecb71b55330cf38873cda681aa40993c97e16e10d24b4e5cf97620d138ec9fc1f78f497992265132d5802b000268ede664e36617a9eadf3b92a25b77f829729db46795c973a71b7a37a90dcc92c672fa25f9fd8826dd978895c7ec09f2fc05442bf2a9ea0ebaf379c91e068f177db57ac24b608a4e821bd2c2bab5054e399ac1fc5b608f2e0792852e5ece21ed9610c60501504ef77417c9360033032c839b6a4bb52bcb2be37ffb7b3877dc1b7049090097a5342fb8f33d8a4f9b6096cf9dbcae35a50e56609d72b39e5fabfd988955432f7aa2aaa1fa9d6faebe8f06870e160096163e6514dc65ea238b590e935d72ead092cf42c6b56ab17696e1ecadcf8ea6281dfe63430042c3ac70df225c9c56200f694e563ed4e36cc7fec29640410da5731d59ef06b3f598a90e12b1e8006629b711", .None}, + {.Pow, "69334b27ad3c5a8230790bb6b9398e31c2da1a73effbb57eb26e0ddc29f00c6a34298ae1786e34c746d57c96e37012d226ed44430c474b51860888f3e2d0e87f5c7975cfb86f0f0e5f537f96a4849a328342ba9bf4ac0cebaaa074139fcd08964d3f77a3e060f58098bf2f36832350e1d2b23f946aa0c3f6bc92fce87b4d066b8477d19fc989d3d5b51a582a4c692ee7b51605426b0a", "7", "81b1be251c67ed4d6211a76cc2878ea344971291528cba6beb28e6e502c932b374efbd1a8303fae3ee35ae89040997fb009e7fda106195c908656cd4200735377e2d3bfd6a69b19a15f10a9d51d7cf93bd026ab3aa3d9054020934731323bf2ba440e3a5e09b9149e20a5c2f01934a7c5ba509a9ff8b9dd71bd99fe67e6e9f83acec652002a090f05c64c37476d2f384f2134afceb130b947137bf6f0bb3c008ae035d4adf5d179e637a337ee26eb7c083943662c6e502ae064dcf74779f83e326a3ba4b1c492a87aa3f2db8d366b018254e2468fc609566ba731e0bbc200ec9495e9ace9166e6b9bbcfda81175cf44d72c728ea8e918a756f4df13c2bd2d6ecec94f0c1adcbc4ebd258e26401f5d11d3122908205bc0bb72a8b1508e6f9564e7dc4eb229a873167ae2b547e97d5c081deab55e580a5bf6bad137845eb865b3ec874c54af20430618e4794c7de5a1f0cb5ae1c4335401f56b666e20bbef3e9f3c09d879b207e60850c3e17855b65e50fa80b5bf9a4ae0dbcbe951963db7d3657c83aed100e7d28711a53a8de649083a66aa8ce77ddfac2237c2b6f317435e3fa561b1ba24e5259b0666b90a5f72407f2bb6fa705330bff1c0a230d570546ea3bc31fcf6171365ca70c245cbde8a6864dd20ad92db4881ae353a40752f10dbf0c277bb316ece5e0aba604cc655529a00c515eee6967a3839485bed2d836df9ff0ea4f70598a3f7fff2d612daf3df5c2c9cbee3c77f3071ac19c0a5da6790a3313652a001c90727ad01baebb5399cb5c183eb85f2f1d37a0c924c8451e7f08e88fb5012984e8532542174852928c59658baaacd39fd156f975e0f6a43df37af42a969e608ad10add132a3ddf48f9654f9881ea6340082c84aeb5f1a93b4cfcfeb7a91f6245334515169f0056b4f59a955a45e45a65bb87adb3428e950870dd11be6759aa0f9c16ee246ef42ea0eb3502d87188f716c640b1d0746b769e462c60917debde7c3e3b9b51f0d3aff5e4dc4e24cb08afae55c31573fb4c87bbfacdf92eec600a74049513f7618bad393ba5630c17841aa20148a2d3a2fbdf9e793ee228a71110d0c4d49ff227679139e55352267f8819d035d014508344105c1f409dd72b42fcba74398d1c2c3ecc298cc5cec8dd130ccb79821c6f799b41af7e2c0a78636f1686ddd73edfd3482d82bc119c3fad874ab49dfa3a762e06ebcd2547b13169b99aa1648d3a48b7f8dcdc3a9e8eb5424f093c07f8c3c8ab388391f9ef75fa3038373017b77cf87c5e1c5133b914b35830704db00ae93da2c11f97822e79f9e767c641ecd409eaaa81d06c11dc4be61cd9b91e3023ce582815783c08d0638e252d8614f7a92c2bd171156e606890548c8be76f891730dfe8eead7f120c0656137e473e91fca4eb09c97c97b110444caa5d3fa6bf9fba17078ce9bcebb2f8d3d7b9f3413e6dfe91b04b291c94df1c1a1a05c9f42c8f0dd680", .None}, + {.Pow, "3dce04bacc7db4cc70da27f62cecd51edaad71e8087c4d9b8009b4e35c6ac5d51ffb94ce7d75b194da0cc7776d423b7178bbb080c4adcbc06697910f6b292179a40043fc613525e4c79fe5a6314536486dae0c17f3a28f70dd37b017c59da086e4f1c8e37f5af489f98491406a932bc3f80601b627aad432e5d4d6e21c9d0942b59e6e583c01ac11efd660b53d5cef441a725a468fd8", "9", "2ebf55ec19dec804c130ebc781e9e0b81606eb5730a758633df50042a0817ed49134cdbbc7ae13ef3d6e706fc6e02afa19754ddc7c5752739ead1b6b3cdbb0dca40cc8648fb1e4b383a176155ed26eb5b7cbc9528908e8a90d9081436c72d58f5d90d123350ad01f629e763982c2ce16f353c57828185e1461e311b2b68f62f013483f1a264b2466f64a71edddae25bb92b0228af85d1e2e5523e0a2d727165125eb45a1060062194b1a2c6c3a1ccdc5ecf681cc3f05619a53019f738ad9243c7a781b34a3e780e1e91ad497455772db4aac792ce16d6b33ea50de8567438ecdf21ab56c05c5931131ec3234cc3d188904f5391ca1fbf723d8e794fb91d18354b2f833627365bdffc2f63b3feaa26ffef61d03f8cc46a9ba440a603a86c2a4d702c9d7ad81c3b074bf06e5c9221fd28a901fc1afb7b015232c69a23492b59d6c5ba041acc0a5bf40ab9554587f6a3cfab13c84f48043de451de0f28637dc5f55de45e8f00818023e30aaa613dde571a5b1a2d98770a9a5849ed4f1cce12125e654431163d60f15296dbc0ed311e7580e885b52aff50dfd50d4a870225e74598a3c7ea1e915e4a3e9b42a5f1a79f0a9fc5bce30cdb11c8b6efff08c3f579d723e5f01182b3b4c964fa4ee45a62d721f8abf9d73846e32a3876df3f352a2aa8c7562487048ec8913ac389f5703e5ecab841fcd08cba1dbf6f135e9fd39bd309c33b42374d8538fbc4abc2e0c1e2a440b05990bdb7cd454e7fcaf472c2db30c34b58b6d8656c1a3d24dcd97a7f49dffb259e408e8a8e04f2c5ffac665026bc9e57f4eada13b64452e0912c6a5615d7d079268007d1ceabf967e3e7957f5a59738dd67a4f0a7618a33bc55a7bf65007d2749577ed96de9e9b672363f2eadb6a7bca6d5b1ddd3eb4b722845b7b4771a701b76e76a8899e35369c6ee44b52c5af772f1319f482dd4220d153aeb5390aa80b4c6f6ff8303ac0b8ca0601621657d6a79d5c6fd37f6c5455482e24fb15dcfc7e4461cfc64df837177f08a35c031e7d790b7aa925c7427826e39285d88af900125665ad6a613427c1ab4bf5e95fc7f6a3fc5915ae00f5786c5f0ea672427c391c15fb85662d8af371907fffc5c7038fd69e30b5a0b0d7be77fbf1a6eb81a62cba2bfe1be1946d656aace8ccc55efef813f31c3f36638529bfe934d0cb1cf4494ff46784343cdd740fbb0970c94e9e86e82ba4e1e70d0e2a59b55e65899a4b27668f63f69a122aceb17be166dfac05e85a1e9151b9a5f37b9fdd2ed4e13896e4f27847de783116a1fcae04bc8bbb5e310436af316a303d324ad65dcffdc4f49679a46ac5d4cc6e13e8e2f5e6bbae8739019503b5147f2127781563428fd0f88c9e4791b3789973e71c4b0c3c8446fd626082250af22f295440f1e92bc36b54966d8528433c6485b639631f0e4f3141187b4e8c15252867e8932b948d2ee8eb7868f06a00c31ac04119ff68c26dffd777242cd8080f1be1246e2473aaba48a2816ca882136114508631c453414ed593583fdeb0f6e7b08bf4312915f5e927a13a6fe6223f0c26a88183ed4d181589fa7e3c9e8483a02f7204c31336e4f9a8c3d06065981c79b435a427156f9506eabaa48e577a4474c199aac2f5460ee148d5e16f321babf271a9f41dac496d44965fa84c550c4454fa238e349bdddd051e2267673987949e37806ed7d249ad5f6a4aa606db6f04dfc2c3ab57811d5f4f3304047c50188fab995e2c055e0af195bf80bbeac4ca2d7fa882270f4538d895ef99e9d7c8748c3d1e84b88ac3e58b685c2542be6ce64282606dba9be2e05b3df2bd29bb432cfd5596f400de0faccf5dd58646652d6430a4a5d73e00c53bd04d8839759c2e59953dca7f48840735cd64d1d10bb0aa4d8000000", .None}, + {.Pow, "-b610622509aadf14844dd9644812f7df9c4e7e10e653294a69dc7ae408389bc6e57c0764dd57d335b493fbd6bd9d2d4fe2419ed4cbdae79f7b49d40897c1b3504784ebe3d5c72f0f15de3c55adbf732cbae54ff41dd3e95a592df5acb4f3f33c900818b0eaf886daa46c20a22dbd0749382419505e4e842cf8e4fc132c6b1bc0a52deaa628f38c74032ef017ea23733cdc9609b3cc9e", "9", "-bea42a72ca767b052b1bd5ea66f85cf09fb99129881263ea81f05b14be0a9cfa295ee09f1c45403262fc9b1ca0cb9d866ecc564dfba451c3f3164dbcfe5352bf3281ecc689667aeb04f63316d84af66bf00e013414cc266622a4ed898ae5f1746b7383b2ed05b2d5eb8ba57ec958a88bcb4160ba398286e2dccec03084c1ff5114ff6fa0bc5b21254b1f1117c3b1238280334487c9a66f90e328d2c088cea4f5f316026126b6299d4ccca361301f1de227d8838782ea6e44fabc0e5e5b7248898bbab6b6b99fb792f5d2c9325a659e54a73f051129711d42b79f6f5ee715dc35b052b0563e094d4ee1f292cb161d088119db6d8476d5de6607d658b59244c747e2390947f14487dccad001ddb00853bdf91288fc4bc03538f09697308bf18bf35db2f7bc073f9bfcd3f17b3740853e076842f1feed40446e9e33a52fb41441260b9a42affa8743d8d74f9511c1193425eda9531cc78817d070277d159894b8377cb667cba34193678bc14abf2cd66b19618dbfb735844deb03dae7fda82b3842440dd58a366e74ec0847822043f749282fc86346952a6e44bf911d6451bd204d00b75118a1f20f10b6a42b57c0b044726e8f32b565f6a4224e3e9907a954cc54a46d6163918e7d9da741dc7a19699adcd71afb2188b442b80329512ddad42c1887fb6b85195894d080b82423b3ad347e41bad4abaaa9744e95745b03c478881d7295b9dbc2fc1abd587af70e5289fd8f82789ecfbcad0bbd27054272281b6c39913d504bdd7873c0380d1666a6d556fdd81ffbc8dd19453fa669e2bfba6b8b697e01dcedd257cce16445c78419197a188601a10f46f9785e6aef3ee232dfa532c2c2755ec321a9d3289e9ce9459db2e11ca09f10a9c5de6d578fc2d811481a0030b27c9b5665019f566372785ffb13c38b1d601f12c0d3370f27fc6c8ebeccc7640673f97a44af72526d234eef3f1b6f238b707206975326740d7379d1b553f4a48d19d5eaba197f19edb9254da36c83aa0532a54d98a5dcb28a8f868f2c411505030fc59d3f1657167b3be766a424430e8cf68738c40b5d2cf3c3c812eceee03eae8f639652158b04787bdee356ae5c95e5f849afbed80f45f79f5a866e2436ee6fb6d09de93ce188ecc8420abe73108c7b3f746721414a4b91e9732b7ebcc1aa81cf3cbd810ede2746ed492686e1142e20f93f524021c69a1ee1d4fd0faeea67ed8f04e154522fdb89e4383b87bb9d1f5eeb7a60ebe2fe6676dffbee311527566c38704d363a1ecaf3bc5e8311a091bad5079220d24418ac813056689675f2d6c253ad4be7b503784bd89a7751dee0a564b44f93bf512aafae9e8604d688055ad9f3f003947f1e89e5f1a5cd783c33999decf4f71891fbb087b5a6213366d6640b11f9769f70c68892a7a84fcd7d94eed4ac032d09745692d9a17b3842ad257459adda2aec713d9f4ac449ea7f3d7fd915f712c92408d287866e0c4f12136ec0ebbcce1662c2e71adcb9c75afaae6ebb64f255b8eeed08b558420e8f2681da1bbf33459f62a568c57b6a783b9ea55b11610be832894a4a8a336305b52f7e38b63d6a07991d864e450aa5a4b79bc19083569602836a1f15ea52797c693ff35fb208f7a623b075481d73307481994629592c9a38c14d7092a20f32c39f76610e302b3f2baeb487c3cd35606db1dce5168b3121fc8090d38e1ac130d448157fdb1794f1a10580b9d5bea2754de090c00bb6d504af2e4225c01812ad95acef8044073b9be14312b52abb23e1480a962d9ee277e1000f8042981dee890e902e43f3cf6f080a4d8b4226568cf9739b7f86ea1bfbb0a3b9f688fd9bd3d0d4206762a5a1cc2477017ea66aef09ffa0a63cc145dc45c7ab469688884989b6fb127a6a6dc10b1a99e00", .None}, + {.Pow, "-220704f8ad6a8caae326a3e72731f641e7d8715fe394a757f6e5480526a4a1cffd00351a4ac4c33a5dca14b780e75ee1c43158d305f76f7845bbe859dd8d2400dfcffcb30a6ed43c006b445b28d5b82d3dffabc358e21a66d031c027263a9a946de5b46bdd43269369eb9f54b8d6bf1171e89b397b4d4138d59393391513903939dd1e9c78fa5d693faa6fa23a46a5c529ceaa4255b9", "2", "485dd8353c2802cddfdc04f6edbe3455c396578594caf3f9c977fa52bd7b0f73d8e3ba95578bdb577310c47f73bdd3cce5224a73929de7ae6f9efdba4401ed970caea6aebf3a0ce65dec4aececa7a05e66dc2abb3fed2d5228a1ba07bb5626344af0e67f7bc5a58155c6b0d2ffaf3d8c165feae73fdf98a19dcba06798be6681f0f12b9730c663d7431e1903798a62bd4ab94eb40459b01867e3d1a8c704f388cd68dc060ddb3e0d8e07eff2c9b8b53ab8a724daaac654c808e13824accb6e8337648ad23a9ee7b0f3363335d343dccb7b8fd9e425db14f806519bc31675ba046703e52da64c5c92fc7c6c6cd5b6ed7af33bd0b8ad8f792e65b11754c0f333314fdec127c469032ecc425677aabf620be16cd653c5c547b497ed6b40d5e2be7dda21b241c2d62c604185fb1", .None}, + {.Pow, "-cdb965baabed70a74bf4064fa62820d5050f465d1bb0ce85914f49ab70d31f69fba3b5cf2400e3ec06977521f489eb338ffabab1902daf890948ea5162ee655766c2132641c9cb7cb4f86b214de9de3778eab2d68ff9eb686d3b5c300e61c8c975926a6e4c04af9c567234d4a15f58bdecd9c80ef5e17a8c10dcf7806e933f932e4bda36369f04024789e027974cb8c783be43d7ed88", "1", "-cdb965baabed70a74bf4064fa62820d5050f465d1bb0ce85914f49ab70d31f69fba3b5cf2400e3ec06977521f489eb338ffabab1902daf890948ea5162ee655766c2132641c9cb7cb4f86b214de9de3778eab2d68ff9eb686d3b5c300e61c8c975926a6e4c04af9c567234d4a15f58bdecd9c80ef5e17a8c10dcf7806e933f932e4bda36369f04024789e027974cb8c783be43d7ed88", .None}, + {.Pow, "6878e870b5649e08f920698312e19e6665ef9be0d99a43e8064402c76503b27d519b99813318ec8bea77986fc54679cda13d68f1d23c0cc997dc2c1caeca3677409ad90aaf089be67c9522cfddb95318772feb5c650dcf9dd5df97f1b8f79f3012a95ca54dff8c0fe0c17bdb43218beb330ec4184e40666a5775feabe2c3ca3efa4b26ea3c73bae8e339aa68a97431b39a7868504aaa", "1", "6878e870b5649e08f920698312e19e6665ef9be0d99a43e8064402c76503b27d519b99813318ec8bea77986fc54679cda13d68f1d23c0cc997dc2c1caeca3677409ad90aaf089be67c9522cfddb95318772feb5c650dcf9dd5df97f1b8f79f3012a95ca54dff8c0fe0c17bdb43218beb330ec4184e40666a5775feabe2c3ca3efa4b26ea3c73bae8e339aa68a97431b39a7868504aaa", .None}, + {.Pow, "-3ecf07b9fb598c4da7e72262d9d2cbf4193793600c21de47f6c44d24196fc502a4fc43279e176a67ac4f9018eac32c05e35e07854bc87188ae27b28909847fb73370fb23041491fe0ee4ffc379508587927521111b90e79612ac61a8ff04980a4cc55a790d4a1a09a77ce69f668c3ce88c8a406527212dd9f0127566c6c697814dc27e86900a6a7e92505a1c6bc68b02c7fbc89b35e4", "8", "dc45a06f89ac998ec22a2b41486d2264ac5110015cb77fb50ea21a76c9e34b1d8a5a86361f346a98b5d1ba5eee8bd6a201f9e196fefe49fab13dd87ecf59d5aa7913b13af2f7eec769003f905e5a75e1a2a21c43239c47295066292628a7828a9c95bcd977967adc21cc29aa91438432c46438ca87521df03e3b52ab504d0184541ef0af27190bbd08ab57ffc1fbe6b666add0d2822bc25d62aa7a8e90ecc379f5ee1b1b8dcca20e995f5d25acdb83a15ca1f042fc4d2b42f291fb0b6a84bb267aa2972a1639a6802936c08d42bc275f8640caaeb007155a2ae344ed241e86df3556fa8370f083a57055bece655005e500a2b468f6a3a72005b334f36914d34c3aa26a9fb93c152b79e0902a7d07bade929e1e654503b19777c4012ca19c549778d537732501854a1a6898b06bcfca9aaccf195795803772b421890b559c2825b0e9880f46a7f03e9fd9da07ba3b2d70d4717895e224c75735d967c5f647aaa7204b3c85864110cdaf716ed70753729f214bce707e1c291d0270e6b3c2c8c407a2c1247912c8be41a1d645d806fc8b46ea24db7b7900a671096f084dbed4b4f75b7b1b50ce994c0cf35860eda040d55976fea3a55062568f5049ca8d5cf4081e663b8adc77c221d7628957938aa68c270fe42a125bcef0bb93109ed87f37a9143a868e27f87e1b9ebcd4e6eabbf9aa1a04c7be9644da0e8f89232bb2effeb34b3b52212b0a9c956e3393d61dcb5223e575e60e6c0e9115e24a5929d6325bb1cd563457f2d6c78d8e0bd65f89716be8ea9e9e0f054558c4dcedab28adabc3f2241213dfabea4205508af4a57f40a1bab0c778dff25c4a6af4e1c6f0bbf78f7a06565f97de8f8429dfde485d0c9980215688ec2ee0292219d9db76ff2020d877e1babf6e3a694c004985be65ce62a16d11929d132804f532fb626ca3a5b1a4197f3e7fee9a9604e1d3b7bb395e19bc9c4f462b959c634af01156989aa5c95825674abdfe00b44bd335f2a1b0a4fe3a94f190f6ceb7473ee4834f6d32aa392cfed14c0bd14f91e6025f97244e29aaa6ba47d188d43bba85c23d3970c0a9b3c7648ec2d7c8c7f8ec53cb2358f9129a898075cb9c2d7088f21012e144ec29c3eef0dbd04f3c874127d1da236e939fa7e02506a3154024d1d3930159d02f1cb938065807c53e1cb0c57f7fa8b7686ac0412f737416794f0d94ae9f01e4493983da79f69b1fe5508550458be0c79efe8a0debe4ce6667011c7462404605443941e6149b7cd39157f4f217a0d1146bc85d05a586f9d5757852b3bb67f0567210937485b02dc92f8db41b623cb8624dfb7321ca4a07e9b483174f585fbe857abe198fe3f9fe68a245e45d3dc2006e66f8cf0e9f058ea30fc249344da50ac81ef06189946ee23a1f7941514ed9cd3886131696ce7b573c51066bf18518d2edb2e2ffb671845289a957ba12a3953c2f694e2170ade0b6cf8defd0cf8c2ec25b1769c33b432693c4fe764a025aaada080d5d1fd056b303ded66967222f22826f37da85362f06562bd6b742961007be485ab4350bdf26c7af0dd7b81a3cfa3a37eb9c1cbb6d2aa7f46d5470a2d17af80201bf912542ac3c1f6e7af236c4c44a9df413434b65f6860537e7cad406f1783b71024a874215807ef3f4b85db0484d28e13c15d5955e3bb195ae7b442eddf374c2c10000", .None}, + {.Pow, "-6f2dfb030a5f21b3599edd687a4ce3c1d87fea964cd068e0a6515dffc1e80546446c6ed7520c6b9a73c83aa5dc735017faa302cd69d2aa801c7811a8dc871e897981db57611fbfcf28fd931ca8bbacdb6fb8f11b731db2a729d4be4568d6ebec8dc5e9dc15df472c9b1ab9326f45d252b57a154a0c1eb549cc2becc8dec9fb0852c9b14d90522f8bbd1bc6f33fe8a2150ed2a3051694", "7", "-bef9916e94ace769e07ea3eb37f03f176d6d260436c143df49e8cf40025df03630ae51881b9c5d91fb5e3fd4090018e28fde095537f843b3803444af94af81b78ab75090e255db91b4e696edcd78f926cbfc655a9bef97ab5a4c42570490426b6a7161551ebbd8e7a89cd9db7b688ff5a030d2b62dabde971c015080652b09f6a03658c905cc1441a4b7af113fa090ea3309ae37bb69187d3a7ffc25553988eff7d13c5535b6afdee366e1c526be5e7340560b3a666d425c77ad837ca14db1d7f137bd2ce4487b65d482682584b1aa43e01f8d4469eacabcffce55ea448beb0e1247aedccbc043ded207f7a27c630c78d7805322912b488c3581af5fb5e87d9e8b1f667975278f44d76292492f7c46b8817dad7f46054c83f40d7f1a6352cb70bf08653108ba7db270274003f1e86cbb7669f05c0ccf19c9529d55431482d6426c33916a92cfd5634c73cf26363c015bcf6929986cefc9b4b98f952abae315ce59a6a870952633b97fe7feca7d0c4b5a7990a879a6e6b39cbee04831984017dae1ea111889f31ea5b11c2c657e3a52311a4d57abf4f98c07e6aacb9c989f157581bb185c349442fcdc803d88f40a47e77377e64634a204ecafc238c57838d772c7e085b8b4285ff499278b65295098025f25c8ff4766ac17ad77f790b0e6d8a91a02a2af7b7ec0d433ce298024df829a921c95ade03138e77ffe6df2433463c50a2ad4fce97c00d465d3808d41c87c9d9fca83f4b6528009aa083e0768746d3bd3e2ffb3f709b733557998b9fb4bc44ca18a8093b7befcf5196043184ecc24e2feb557744a9ef5f72d18f2bba39727ca7a751b402523afbe4b409ffab79ed3aec8b33a130f732ce606c36421f3d743e99ef48c52734eb4fdb4e883f46b8a7ff2c94ea6f2a74eb505c291e6f8910e556193f70196e2c2398d3ce3fa2ca19497de58ef6770b949ce68b49e7dbb6948512e1d458c9fc522c2d05b7c97a750336913f4828f90e4827bccb69920b5037c204aaf3d683ff6553aef8cbab70eace87bdfe072cfecda3527ad4807d71b3660e4d9f7ae567f005a8a4a9f5f08f49e673b74606ffc8b132b5b136511ada750ca09bb89dac2f8b188592b91f2e21e1f733d74d67864a3c3121e87e9e03ea761e2c9f2df89da5660b437c035bafce1fc1288053f127e70285c6045a8e9bd2a2ce8dfaf004f47935fe473f51d6269bedcba7e7002a93bfd2a0cf500f38e7830131432c58eba06d80cc9102ebbc581de501b6acc5f2dd80f436e5cb30074ee58f1f1eedf9dc73b7fcdd4d66b4c00f25f3e99f41177740bf07bfe73e822bafc4a22d5d90efbda5c52f15214f4e8b2f42cfcd8e2dfc22a6cbbbd4b25ca6dadc973952eee93e9f1e55e9abd58a982c8f36f1e0c2e4c44e44888eac0d2f80196e886f1c5b2570944af3fc390f41a94765080878dd7360d5cced1aae95675a2b523952bd57bea1956f9662eade34000", .None}, + {.Pow, "6803bb405bb976096b7240030a5e1424162f12d48811683a161f7899081850ef5c72028928694e931acd3ad4f91b45dd46e0655786c8a57f49b25898abc80cc016eb3b59bfc7a1a74d111066ce530d817df05bff7a996b28b8564ef41334a573e68a44448b8ada6fa09b530e780b20c638f332d74b6f09a9e98c188374c725cf97088ac0079bfdb42a8a5fe8b345f945ccb0e3bb1e8", "4", "6fa103dc497f0d3d2e54c241b0fdb48f2937149b2f79417e100851609017b6a4a5946982b74f442fa2864e2218b568ba3e600412f508086b69de91df5b05c9a9a3dda1b43890a9be8e57adf0eccec133a7f02a6f96613453cd7e50f9cc60aff9f4068e00c47c60a1c0afcb93da8d7d4bf7da61311fe0dd034b022f42f5de545f2e69a2c0132de09cf1b7008923b42ef141c56f9802e38cb7e5b8b9ac3722fe6862cdb46c86beb47b90a1697fd11140c47b1dc728871436b163003ad40c012a46bb471005ae6c3685677ab072bfa2cbb8890ca000638262305f190cfeb4b81c39fbf9e766d277d9fe3f91ea5edbaccda8f9e3618c3aa82fdb4e1011973bc8d844a19c8b21de117fb547b0b71770b7cdc3daf4284bb9b240aafb7abc892c34b1829d218f2d2e804f0f734dae93e473ac6b2de87dd2a51f3128a2140ef04eafc2c56927bffd9e969629d899299fb6c492467ba3f2be72d14e75e94b3501fa35b9b4370667bff1e43dfe2a072c731bc873306cf743cedc89ecc92ba047fdb1053dfab73863f89ae49647580b35da50ea6f7b81d05ec713f44a587e95e4e8c52fa96dd1c28a2c5b435dfb76d0c76bfbc054df7ad36c2f662cc1fd88fdaca2bb964bbabef1603335098edd77d8c3adf778ea5fe1dce9a16a60bfd156eff529f42ea8e9738111f3a3c0abf2481485c6976616b0cd4fa631c7d56b72d0cf02739e371aab65c1464151c26da94d11511efd8ef1ae441945794bc986f29b41cc276e9ee74296258f8834861f7fdeecb06fa425c1ea37f396bd8a75ca0d51a4f5f1b6df6e7101f47fa698c979199ea679d999be01b42db77d51000", .None}, + {.Pow, "6408755756c358c1dcf6ceecc579af683331aabc724b59800ac5d47182d97f0903dda05d35d797c45f3149f444eae9a58bf0ae82d690df81a396b15f26ba67c528689e23a1b41ed5df8e7a43ee642dceb8c8c133d1ee2bc781149d4ea78265f9fd73c793d695f3b3101440aa90819ba7e39b74c7de52594346b43b2e1453ee19cbb6887d83721ee3d5cebe5c1d8381901be70c8d36a", "a", "5705ef2d0db67bec6b9f840deefefccffe04c4ca83fabc2f6ddd0300b0dadcb76e70fcff54a1edc898eeb6ee2c96d3822dfb4276ef3efcf7ca011166bdee03c482e7e50f83d171954f6e66db04a262dee64a6aec4b5bbd1010e88efd5effadbc1c94c7b203683316d564d4786a1045e0e3b28179c1d7af240837260dffd2715d3911b18a3ee8546feda9ff9101855af0a4358ff0d2d4e637336f16e7a2f8a944241bc9486ad190345d0c9bd9c3699642abfac0e3ad1bdd9d870d929e850d1dacd7f96f9d8f84d37bf430c12db2f29361f05acb4c84a83a755d00eaccd004bbb07b7ca8587ad88dee24a3b9618bef169783189ad0da8bf394934058aa6468d4d05ac201a5c3b4222c6f6b7f1ae0e8668da04dfa53a9df8e8fbfafdd4e7eb40676ad31eb78e5e6644268958368e1d7aca99f711f627a8a10592d09338b859d5cb528e20e937015b56b77123d0803269d2008a18ced822eb8225f68f581ca76f1358f72aee360e24534d289e929f1373231d80a9653f399b37a48b21275d059d70073aae503c3a4bce0ce8eacb137e96de873bd072c2924ebfc04aece7a2a12aeb9266ca2d79aefec5c7d36fb80d0b7b4627c0a056a85cdb1de6ea30d5b415b0664ddb409d6648168dc49862b02f51473c82a3bf58a0431161acae9bc661585fb330037342c9cce5e11220498f1d3a1be3cc3b7455e3fc3fd32cb215eccf15201884045d5804ffa2f4baee80387a735d6bb3ed280438e94d8a0f96e5de428b8678decc56f4cf09f1ffbc8ad8dac9028affdfc5a1c605b7add432714fe6ad2fd44b273b71785a37b7c5c608628ede4f9c69a679fd1cb3a1fb660060472c6887e8af6a85077eb27172993e1a4e1bf93c12e9db37b889cde2bafefef4fae4f5b814a0f5e5383e04e4faaf3c8a02787ccfd61d1e463d865d7d1c0805cb8bf571a30450a546b683dfdfb36a29db3ffd4483667b8aada8bdf392b6def5885a9cc66ef424f7324fa257687714ea981b62cdee90746c0eae1fb6bde3b451eef3e98ef565c2e4cc183ee98aae7bc49de2bf541647b57bf0aa0f6b7eb5d7b57a8aa518257bc7e723fcf546e82f7baace76b167f608d5be767d54d8d7239ed08efda67ec68503694dd358e7ba0762e9cb24b39ff8559efb129413a119a57b87c08636643edd875a67f3af7126a3e9926eff1005660cd373d6b792c9d74c8199f3e36397ecae5dc09dbca6795bc439381ae4c87ed27dfba7ea5d7df3edca2bed62a10f5ceb4858558868c85e763db8241e211aca36f2f11764d6d2640089a846c051a7b96e388d04933c4bcc3756b9e28cf7f7bdeeda2c9e5efd586d84e1ed9da4a9b3884de8b48e5dc2ecd5c972e568b77516f92b6f99300b6bb33e35ddaec9e0244156238bc1c4031ac53f336957d1d611a3129d3b9508c9ca73b02d411f9a43680b4b6f14620cca6d00bf51e6430ce53490e9a2e74c19c74fae4dcb107cbcc590cfd8eb541eb8572d1b574bf3cc259d71ac27fc1b827bde890096e4e2b2c5fc126d2e606d1f240fdaa8a01d98750a72291a541862e4883b352b0e40052e2ed9bbcfb48f107888e61a11031cb448e48e41fbdecaf6cfd8dc244eeae2e3f6e1f05c9b312b4e249759dd2332198909bc3341bad1de1edc9efe17e6844822bb17d7975d94c324ad610cda2ce4d117294feb2c5feb9c4f2f46cf0876b385f311a00b7d3e26988763b751b10f0aaa492131f06633e169f33de4dbf406e30c43e99df468c05a07161a4d4de0e4446408a391ce5bcc1e2e34a57ff37d865b4c4068020faa4bf4d4436c0ebac52b4a1817358770300427092cff1940eef3d5612f72fce65a124fdd2620f46672324c0b4c18d23f637fde4ceb21b8d640e5cd62196d8e04150ca87b795e8e45ad62b3be93bf7e926f04fe6581e5cd2a9089169ac6ef1f7c666f9074f59cd3173cb9b06995a161272186977ec691b9f88247a73a2588b5c18cb3116806569aa5c283a9079f4a54a20f16ce7a9c7520cbf193364a1bf98c5d8e0ffd4ba3b77e3dcbd1ca2b28405564d9cf85db6d130c59d8e155b8bf29ba56316f1f4f0e762a9dc582f86c1c6a1ce6cdd5e2bd36dd5b0851816400", .None}, + {.Pow, "f3ab556ad9c3409650f2f50fa96f9fbdcc6990b184b712ab035980992ad8aefefab40b9c993554b68fa8ea19478fe073e110a18b287fab57fdf1d20f34ed29a9d7f3ec642eed8987155b2934f874079f7b829a04d59f72dd95a181e2492c1b1932f97780cc544e5270a2f05e00fd320942b69ba8645a26b0ae23eaaaf098e7df12908b46f13c0679271cc2a16647ba6ff091f3a419c3", "5", "c801a5b7ebba06b643d8d84f8c37dba6027b7d3e82d59e6a4501ab57ab32b004f0f75ab4beef3e9504ff689491aab3827ad347055b381ff72424e0458b34ed4d606ef6efaf15c2e1d3a9249e2bf7d3742f49750021c771187de72d06eb81a65aea27cc977db42b109cb2b172e3b252680b073e8e9ad55f7ed3cf3da8070967794fab9edb69dc97bf2b2119a86f669d929af204bd9f41c8d5c1fcb25ad67e51caa99a7e34a3c7e195eb485c937b47f4d82477d6e85f8fa834b648c342184ba5ad6eded4ab7cb2514203da9b895bbe1911531fd6208dfe7dc02bbd515c49f06d9078b9b948db2856d444c67e5bf4e33abdcbab472aae15c167ea007585955e240e6770271dbbea23ecae4909114fc97b769573785cb9e4d904dba6e556e67f74213b9677c3f9f3731b4e2b568adcad4cf23396b51bf95f8f9e3910561b17b11ee798a6cab005f63264b48c3541b8ba16eb811bfb2009f1f9b9be4695797cff9ce95f51d8a793351db80c3ce0a5d77dc53137101d5776856ae287afb1772922f44e7d9880ee427493f1d031ca41c8134e29edad2fca08a47011f67b6de4767e30132be21dcba189066f1c29f940f5c7f0623f4ae7124828b377b929a6765cb581a9331dab18959e049362e1deec1f063fa03b02b93dcbbc06a092efe4231cf30981243d6ef24f922d2b7f48fd5d6421b580504e20452b118fbdbf14623e00385010dfdb47ddbc0e4448832fb9249d9fc910073abd356869cd030de770a3327bce39667696b33adfd5820de700e8e4bb008a11d3b47ec9031064401a57608bf0ca6e9fb2e277ff3a1aed413aefa4a6c094a3a78af7ec55b4f5ad9d250dedeec343959d71c29c28237f5ea753658fa6266f5d91c7b6ae331c51cda64de972792833d2301d510184d08928ce60b4b912d3b6af439b79c73959a42f48ab5115e80092b03e02b8b5ce804ed5d12be0e3fefac9644a3f7992a346cfa65e9cabe72d88f4a71c2430239568217b9a0ac64b227260612058b18ac53a114c1f53bf08ea87b0af3d03a5fe6a01ebc9bc9e08479db3", .None}, + {.Pow, "6b00dfd5eef186b7a65659ea523ee73dbe8a04b05888ef6cfd5e422e41fd0fe530094646143842ed37740d1c22af26f674ab170715e75d5d1076aca28ef80a91bc2a458eb14b9d405277e0ea587461fb3cfeab757a79e026bbba3b553b117b7da92183c74727f84e0a6ef76cb925dc9df59e2866946a953361c07c9214107b0ea9dffb3113d8574285591c439d580a3e8b68279476fa", "6", "15d7ba1ef6edadd2c9964c43f9420d401a54939195cc87904bba6844452c290af02034beaef887de1f3debda60fb57845708c3f41538e71fd7bf59ab6969fca28d964d8cc587155777df81179c57a49a773db5399b44d8719cff39e945afd5547bd6b2d552dcbe88686633d8250838dc22fa44ee4a0a3385e11a7b1cbba74f92d25b4b1b9a7e0d4607579fdeecb92618fa0a5d5dbd5ec727637d2f894944f350d817bb3db9260f9f08cb8ed76bcd1ade9c16fb68e44a1d5e4701dda079576292269c99d10b594b490d40cff57009bee66048e5d2461c9cdff82e5aa56330c4cd40438ce563af3b7aab5d2d4bc1a45af1b16c8cb61176eef962654ec484fc31cafe746ef756242fb7c96177930fe9eba8b35ee94c46e6a25ca5c5fe76560523ae56b0ac25db5deffc3b2f857ea74e397a934ac862bff7f21f645e9ccf83d009a74abf6da8de019ffe1cab5a6709fdd8a3aa3e539cd7ec6878eae5ce9d461831975d53dd699a32833afd1b2401dce6a08d491976489de68d35bf8a4ce5e1aba4f8064de3d848ddc38ff295b6912b7b03e0463a00d3e1dfaf544b5330032c553dae1a9dd7378946378ff1f48326805b4fbaaaa224ef3c42daf3b46cec71ebd85f789f7d8e506ff1be35d7521e4bd0a01abea5961ed494a1aefef663787db1b3e2c98c8f9a76a5ed228422f7e41e919522d0bbe7d717c47f1c6400c79149e8295a9f0871b34b6d8e14574c222fad3d2ac5301ac9d89d1634ec3bb62152700add6d9049da9a77c58120a641570b00c582c2dfc9f781fd1749995821c0c41b31ed8ccd02056dd20fb8de1bc3a234263c3e58dd9b0f587873b78d7d04358ad7f089a37d287fd86ea26967adfa92387130acca7969697b46e73f15a26b4a40bd15918115b316097c38479d261161b3bea728017af604cc62b089870023be700b040c08b6d31e1cb7ec9a2c74c5337bb7fde4ad1e321a330684de946fab4bbd9c2fcb6206ec8e7ea2aeb8551da0b56204578ddf2b9b83c2eac21ef10d39554686befa7c6c44ed542f777993b086eb051f1cb3d449a3c2e2475474a866bbd94942f0bab31f891e7d9bad40e7bf3f1e8b3060844c49d9c1c3cdb3571d5b2467b2a62e2f1dea8bed4383984e391872254717646dc3aa321ea3eca53b1ff016fabfd6e77e746d98c6bed88a102e6a7a4a2e7ed8e5bfe2823a92adbbd232a2458f191433edaaaa457027849baaa7672b8edae62bea1c91bcd40c93717d959f8c51ab9070a5a7b8538f640", .None}, + {.Pow, "-b5ceb415f5e389fcd7616aba891de1dfb1ba259b33547e23037c9a9207932f8a65c6c2a19b4c0c04f063c131c634e63ea03c88b12e6cbf302ac4047cd2efdf5f2af8f0af45c74c0b74b27ce630a432879a9149d7374f56ac324872b0ebab0ad1fec1c4cfb4d72f2efc8acb2f163dc140976f91b8cf493cbf147f7eaf150849d2a7da887a3b8e4bdc79dc434f4ae679b4ae2e864a3e73", "8", "1090daa7522690bfdf5ac6e1706a610ead9064ab5f4bee45b5eacf118e76f132b1d720bca93307b71a8505d784dd4aaabf2889ee37f3191e91dc92ee84ca4e72a9dd05a9fb360d933917e432b0ccfbfe445feb58dbf4e4b32bae07a1f4adf64e57eb5808986146defc827a43a6548504b8e236fb76055c70f2f9ca0bb4e4da4ceb753d3b211ccc5c1ea8da4fdc23a1bc21bdca73ce8d6dbb7a22253a734c1aca7fe7a0777a3bad12002bf9d89f0feabadb73b7474d1aaf1ee1317015a22470af9097af278866872ed86d6763704eb5773b74933938b5b86cd1b3cc78a0ad4d83200a088e5c4941c35ee2eb3236e230bf0a47da8ad64fac667ec26cee4a4fddaed043b13b210832f20fe8e488d5a4bb91a421eff60e90409cea2ba54d685018428fb361e38d8c1999e95d560da2b8a996ede8a230ffc7dedef2ba1a9edc46620de5011b594052d13a38298a418c7c062e85341f86fba371e54afbc4b080ca80506e525cd501da5c107ab23763badb917230143cf765a3f731515a3e4ad0fc5212c7215be1dc76b3277dee389143b9333bc6b9c93ce17e77d77c2e7ccbdfa8a841c4e165b494c4e17d91daf9aa6032ab4e1e6e99b6bc7e7cd6fcd4b7ace1cea7da8952ab7ce97aab91dad79298ff91bd6cdfdfcd885df609caf6130ebff1d356df25af9f4fca760524cae71ec293e30480595b19f51cd02a1b2a6d434b12cbf9760f1b8aeb79d060ae6747832d3629a63e3a891f0958e94a20df9f836fbb4b6f19f4847104c1def63a61d4fba532c5a5ce4abb1b219c903f53cde3f9f3bd384dc13bb386dba17dea0e730c7640fa1ecf81330f0686bef9fd8e61d1bc5294886b8889604a6471825d7d36cabc4cda04a064b711be3d2e918f0b5f30f7950c1eb6a81455640f2b71ea745efbb8f5b9fbd068d20d4373fd98717c6d8bc37c9240fd9b8e039769928f8073c9d6f1f66d0bf1d10dbed4cf76f1b51dc68d9b9d0a67a4f3da0db7c4ac015133fe93960484c2dfc16aa4f29a9f526b6133c7bee5c2d4cfa3b6ddd6d7dac00fe85b3e09b84e88a2d00534776228769650095a84223dd1afc3434d87b8e6de989de4a36cbb35405c70e38585ba5affe8b5978cab20f662427e8ccb53650096750d2bb918a88ffda6c201903e0b8340269cc08a70cb6095f60ddfe96f3cdf8f031a475b16074fab8764e0c83f858f5a438867099f802abef8c9fa53a332c17f75249e4091b68df543eb72cb115d650dbc6acedfdb91765b5a66818db150153455d8e3fd6036bde2bb409abbaa730bf8039d1b22f03d04dfcfb98a32402a7c4c6f381122c887b192c97e8efd2360b1e06c00d154a50d93a7d98168b306e6bb68dde6cce910f4db996eeb7a49d6f69cf13d579364443cfd8a56ec71060890b3717be07e415ae4432df126c41af2d575241ad9c12855f2f6a4a9b76e2307e5e684b077d7ef5c7290172cf513ed00b12ca12180a28cb70662b5f0d8e0bb39af3fc439bbc80cb7ce4f999baad414d84e4b8acb0b12192264d9c97c8fcab2854bdb2479e982cdb09cf4533c4a4eec375668249630082732732ba6360d3813636b017d550c43e9d21e51c45d7e288ad2e802fba844382cc2746f6fb4709b191d68b8536ae8d52c0ad6471f126e94392bb4e8eb48bd36d78bb1f7b43bc3af8ecc3e1ea41e3db72dc11c3564cc21", .None}, + {.Pow, "-8de1403d14180f8988ecece6c839bd3f398b7e0fe13d95c72c879f97698a5ef9683728bf68f4c392c42bcf39760e5dbaa3b4704859011610645b95c02a0511712b701168c67ae6be9face9d36c8859f1db7b959570dddbea6ad7e5005b7923d0fad966221c5c1d75eec4dd88b8ed32fcb154254c1ff1bdeb8e901af2e3763b378cdadee83b8a5b54861502e3941a13b4f76f9099ca30", "1", "-8de1403d14180f8988ecece6c839bd3f398b7e0fe13d95c72c879f97698a5ef9683728bf68f4c392c42bcf39760e5dbaa3b4704859011610645b95c02a0511712b701168c67ae6be9face9d36c8859f1db7b959570dddbea6ad7e5005b7923d0fad966221c5c1d75eec4dd88b8ed32fcb154254c1ff1bdeb8e901af2e3763b378cdadee83b8a5b54861502e3941a13b4f76f9099ca30", .None}, + {.Pow, "e96b5430412b7601574d9db7d142a38765206a5ed7d10e1cd22e0388390281b86d1892cdc17baa77a64fbae4e367d8451f99ea78d564da6d0ec18d84db149da72e256bcc7969a4bc6560a0958e0ca1832709f0ed2f4ca38d836b3b7ddf2f4579f32dbf7f94639a8990c2ca00f972cd5949f21de64a3f53a7f7cbfda43d708250a257eb185f3729fd1388b5e6f3090c863f9a63efb293", "7", "862091c4baa00b2e8c28f47911da5802fa50b721297f974cd022f1fdfbdac30fda56ce905a3839339d8bbdf5673a2f26e6de2426e1c58c98c83e168f1abdd4f220d440b5ff018824d9592e15a36222661093d322b05102eb8b02cc8a2e6d3631ec8dea6d20e5f3852eb23ac0bb81c36a39f569fc137a676b1075a31b4f2f7663218256bcae0b1d4f334187c79ba5771b59f636acbd62a6cc5d31f117b9cf6c585a36b7080ecae1ff685a0b27799f60f29a8893e7205c30fe300512e65a34cfaf11e08b14e6aec06ee0cbafd22e2925853618e08e836a62b88db635b1a2be21a7de3f602c379c8936fe33761159f38c7e35c8f484cab2ba8eea6b7058556950860ce6697f1b078b02adbe2252a3658300560d31cb8e4e0703b5860d812e1dbc5c8021e0d491e4afd871471a4f877df4a7c968ac47debdf47c68a0cc318e99c31cd6d49f5133c657e6b26514641e83cff92bc82cef820a5d89877ba3370bafcfcdd1831de4dc4b2210a4687eba4bbc760f2fa01e901c4910edcc6420cbd088a46cb8033e4b726dcc7ae983966fdf2c3f92888bfba57b35a4a0c4900562f7fbe378cefea388617de8689af993145063b796ed30a7b9811fb040ea512dea54ed02fedd045cad2dffb39e8e063ce1e045795dd84ea41e6e2d123e46ba4edd0a047fe17087b72cd41040ce77f839f5dfdeb627f80912168f26c9cf8becf2a0cbff5725429fa8be65e08ed67b42539bea82cb738be8b506488d4d902d1bd64cbd7b15ee64fcedb05aaf044c493ef0e3b1bc1df54c9e336b99fccfe5184349b5a20c2d889e7db76edc7b386019dd954e01e2faf0bea8cf2646b37d89058884a6564dfede02c919aaf581e020ad582f675b80fcd72d34bfa6b43149ea679edcd9de1576e3d59c8077e87480f415379510d26d29e0a9b46cd4c9cdc7afb94188d111b4b3d032a59f7a96cdd39ed178dcb66d7ebbcf06676e2d2f52bef30063751b344b316295138ffff05c784c46198678a176753f8c4735131a8f8eb632dd9a1cf6e62d52fceb71dfe3caa9de733b8ad68ab53b12d1b8a6985ed39d8d65cd606d50ee26756364d8addd04606c4d9902e1aeae34ac324cead0e13562ba12c1665cfc248b93f1e6a83dfa7a0eaa5927b4d9391caabdda7135c69a84b85af8fe96d9056eb6019d81780521ca6f752de8dd1c653350040894480f82cd9d92d8c6e68a57bc1b0d68937a73d5d54d5e740525fa838738bbd4778431e7981d7ab0969cc2122d6ea81567385b2ec92662db7957a8e6466acbca3032f6128a041c19d0dcb42528f7ece5cc0f53e42ef86b11dc227438fc869936126d98d19689939ff170d77ba5c807f2dd64e1129c4afc42229513b5f432c04d769f4baa3a8c8761878b4f54940b9381110d410b3e7cff969e30cfd7844c2374da3989af0f1b31150f82160c51a400f4be968fddd52eb995087dc25ca1cea2ca0c78ba910f9d5b7bfb", .None}, + {.Pow, "213b3302f9bd49b7da192448b72260adc3349ba344f4de1a8cd285dfabacf2be3af2367210478486f69bd6e15e754d9cc6acf46ec5e191e9868f9c85a38f625ce11cbcb8b4a5b44c59377d24f86e23dc0f14ade1fdaab61dfa31a6c19f8208cd1171855ce3ede9f6779666f141a3113c4ff00788412635aac5d4d28bf97aa402f49ee5faf356ba43a4ced6c877b0b8b959df1a96f59", "1", "213b3302f9bd49b7da192448b72260adc3349ba344f4de1a8cd285dfabacf2be3af2367210478486f69bd6e15e754d9cc6acf46ec5e191e9868f9c85a38f625ce11cbcb8b4a5b44c59377d24f86e23dc0f14ade1fdaab61dfa31a6c19f8208cd1171855ce3ede9f6779666f141a3113c4ff00788412635aac5d4d28bf97aa402f49ee5faf356ba43a4ced6c877b0b8b959df1a96f59", .None}, + {.Pow, "13c014bf5f2fcc131eb90253327bccf9b84560e903cd8031605f35a6df0d18f94dba7fe461fdba1cf213be72cfbd66f7d8a86e47057a28893d2d61d669bac60223a4343b3af71425de9712ba8a67da519ebfd17ec8cfd8a2be4e52c5fa67bc0eaedcb075a4984affdf19ccac5bedabee71fdcc4d5a7c0d49f8f010e5de72faa20277f1d959672477965ff44161c17b83e2aa9c572a9a", "3", "1e181ad6e88b3a043f54b6bcf35492c5c2ebb7c1e1c4c5b7aae194e6c08ebf885ee2fd86786fa4164a5b4e8d8a29006356195f1ae3decba6cf0e2e390da591f0a3d0a44c6a6e5dcdd8c8034f6c49f10a09f34bbdc67c55d5d1214a38fa39381e2a28bc6bb887295c815bee80d660902d24a7432390d6902476281fa51dc17211a9f3268430ff8c88c09f7d90d825114184d7dbefaed3b36855faca4ddd5ea918a4219d7ec42d898c4d2c60f31835649715a470ec03fc95e61ce84cd4aeca942036b029b31f235dcd30d0e34f2fdab393134eb0ad761b18f1bf2fec9ca82cc8df8c33d2341cb75fcac0b76ba038e9b660845916f5d516d1a6351d4f007d8a8204e72d282ae1e105b9eae3f54d54059728ef358d2278b190d84e24bc728343e32f4f9d131022993f4162f7283f180314c8d5e2742180036d58a2a3d92432dce1d96d3cf94a92c30e84965816df631e65a8270a6abb53b2965de2f02aafb4f599d00f6458570649c0d60bfa8fac58fd595f5d291081e99d307d43d65ff91f37b8d7df36bd8586a4eaa50250567705112964529e7406f28dcdf1450ebc0ea3e8c9acc5f26f894bcf7bd4a2d84347b25e56d68a85fca648a2a4d64155c315e6f07c72a8", .None}, + {.Pow, "70e6941c9b84dd35b43713bfa30d560ed9e48269ea2def06772d18e7b4a7f72f028aad7af07f57e9e631daa3be4413f7d7a9e65539178c4728257189c0761d97ae254b3988e5a5befb4806c51da62bbb5cd5637584ab4ad2df1d08c9fbb813ca1fb40a9abff5f0150eac2ac5979a10882361d2b8361a8babc21e07781182d95c1dc6f166d5f17711c391b30e9dd64757f11ca327fc84", "2", "31ca9147812ccb507d80a9322ca8dcd85a9a505b246f7bf58c38ed671ad93bfcc20f8d5f00e3e1c3cebd32dd55a9554971df939155b744ba18c4800c4229fbda7b596eaebfabceff3c06063f4ac3df455edd418ee596e9b5fdd2e4d7d6b860d1844ac03cc76f880137d25f801028a414c710d09c388057f902456dfbb50f34ac864112ff81f97714fdfe6e46db87f82e03b93460605e28fb2cf3e0bff53e1f39d2f008128939df83a4be2e501545119b86c9aab31cd063090fea7cc5210c39480cb988cca320782d4fb689f5eececf6b8c2f7ade1b2f0561afb45db9d4237eb4d04a531f03b3d53b72ef4fc39ec44740b163342630d59d83e26a61b19b05ca47e249f18f8f67fd23ddf1c77b6a608abeca3758c235cb5bbc39a00343a3770afbb01216543be3b6af014c2410", .None}, + {.Pow, "f98be61322e857015de10acc415c002a80bb3b3a86282ae5553020677c04a2e11e6925e36e58bceaa71e85332674efc1aadf3c3250bca63394d75c80cb6499e048971dc08706fdaaf87500a22a080b2944eb54f7bf1516fec363b76f7e61db9091e8be6ca08b4712e6bc0222b828474e51dd29fc1322b9513ea17e8dcd8793eed7e883a573a15bc59538ff659438e9268856ba3c92d9", "1", "f98be61322e857015de10acc415c002a80bb3b3a86282ae5553020677c04a2e11e6925e36e58bceaa71e85332674efc1aadf3c3250bca63394d75c80cb6499e048971dc08706fdaaf87500a22a080b2944eb54f7bf1516fec363b76f7e61db9091e8be6ca08b4712e6bc0222b828474e51dd29fc1322b9513ea17e8dcd8793eed7e883a573a15bc59538ff659438e9268856ba3c92d9", .None}, + {.Pow, "-ba5f9a8930f4302826fffc9aea62bdce48bf6098a49b1a4e7499ba84d1e14ef7b10b2b6ae42f182d5de0fb9d421a792bb16f544da593f8d622994612a6e5cee450e948241478d3f4cdfe73a3d4cd1b7c7c5a42dc3f61a4ce14989e2e90c0097e4427a1b311e2d8ab47732a8351177d67794338e26bd8ea159e5118f12a8303779719f0beeaee912cfd9404dc9b9ae657911399bf6075", "6", "261da1c52fccb5ce23b5e3b3875c2c95330d4a3768f32dcdf56693f192274a8f662143a01a8bf3105d41eefe2c03e72815efe1d8e23528280014eea7799869eb440799f84bee1a9e0b73d457b610b4730f3eb06b25c2f28a696e309a0cc93f2e1910b2b9add61b734f13ae50f37bda7b61cd96f8e3326ea6a48bc198819b41aa77c51a7810ee406b9a1cce59e6abc39d25e1a7b407a656e00d7f02b694104fb4120a62a515c099406196aa73f2acc0b9e5c18353905b8937d773a16ea522238f03f72f89ad4ca7b909175e69b68c48275a3a9c94281a546f11cb3449f14c6e6ab3923c6154cb2719ccbad64c27e465ef15ca8c8c931ba2db650ba8af9f33808cd3a7dab63acf6a2c629175f0f21ce36691b94a81daaca18650b574fcb519770eca87e5b5805d4f7bc30c274f596fa735cca88dd2bdec74da547f6bbbe56cbcef83f056853bf00b9305b3856030c786dc471c074ab04c3fd4f9f0b6ea50ec99226c65c0f925c408ddc91aaf769117e762039ade4d4f68a9647905d9232be1de48960c1b8c9d2f25a4e429302ee241d62680286dd2c0a3e5e48aa1b5d6690c38576223102a3d24f82b42851f59e62425ac44d5a9317cae282df04ba1a97fab3f6b62b225ee1ed06ff5d236a76ec8edc6cf0289e97ce7a0ad68272d5dc51a235febe547d8607118d877a02b27b9f87ae3a75867722dc721cd9ea8965614847e6ed939c73fec1db50f06bee5e473e61a586f578a51eac0d4d97c4a8a5060082cab2d248ec92c9efc142fa6efdfa515c088553483470dd16d065e11d0c6a877b83c5f66e3f15a076e3e8a3573683abc39f1993c446c041672490f07c1de1dd708a48361aafb62ad61c9c92f8c148bc94d20fedc6bf21235352c6c68a11e6650b4730cc852b0af54fb39696d8fb5cb7fad41c08ebee7f3385f2cda1265c34b013385edb5dfbcc7c3ace53fef854cd6b03c9b46b55ecf19652b79d0f680f8ce4cf866dfcd1e3bf6c1151dca3cfd250d5a3a0740bee92ce1cd23d8b9504115dfb0784b8011ecfea0b9023a891b88b9f65227f1366204ef6ba4be23d6a0b528cec4e862bd5e13884ea3b01d5b78b01bc7434cbc0a2f30ff0dbf8da5b715d6bbda5b1b5cc5485d119dc84722eada44f85106b318d3f334bb971b695cfb225872415742ac74ef9fee796823cae00d2ef4a639f112cc81426dad5a14d52b81965dc0939e5cb8ce94fe553af1b686dd6a4070a60c906cde54b1fe22e263f309c3614749a7a661fbf8b729", .None}, + {.Pow, "-bcf58fea74cb3e427cd96694ebdc3bacdb1c918fa0872d5495b8e99ef03ec857973339c64b9364a66eaa79f26a7ba1dd87c2fb18e26b6e2391fc591924b7e0c7893b90c4624ca3af04bc6496578fe4653f9e04253a89fa658fde628a891594aa397488ab030fa475a67e6514ea594dde34a22456d0db7d361ca0c23a32aa70dd574b0cd503c07ead52a4c264c2bd05360d638a3f3133", "9", "-10a63194cce2f50245243e7f45075faf385c79bdea68f11d7c6234639f3a7b82fd81e5a4b546675499fadc165272def4100252c96cc3a51475652bbe8290d888f04502f08dbea27979e225373b8c8cf4756cc7260e4a17fe2cb05b97ae241d8599627cffe23b2ad24b47835380f8667041e81aabb49ec4d898682e763bc2b7a26864cdb467d16d6632ed11875709ea02df7c437fc4fee3c13d72be41f201c0ac4e1b5d0973fef9dfc33276c7dafe23eb4871dfdccc6768cb39c73e412bd892a6b8de988a190ca1f79b0067187ca6c7ca3fa8bfc3b7320c2074523adbeb4b65d41db000b3b0405d60ecdd696e820c6712e3d944bf7551e2f30350982d0f7d867d6b38e48bece2735e7be399c85c2abbe4c46762c2e34f4dc73b414688a470269d97b8d4a860f5a1b986d679112162f014dbb482ab74eceb43af48ebcc0198c33a764bbe6a1df13bbf9be52e4a9b80e6201d2688b8a60a744f030cfa39aac0d5bacc2bb483570e055ee617a16e041af3205bdd236a770542e4c099641c43d666f0be96ab037ae8a3f60c40f95efaa2f983ef4dfe978060abaa71eab73a45e850996ecf2472a6cd5e3110602a5471bc5b65c4b69971391e12b7f65fb802fe677c7e7f4e0387e167d9956677bfc6a95c5502667b735265e124dc48516a8a4938fdd9583e1986d01b3768cd69a18e39a64591f80a5dd5f7e676b2077424b69b44d7a5eed8dfb949f8092b4cec2454e551c610e9271cf4455e1e6dcbcdfa69396988a4b37b3f5229e7455bededb926bbf6cb594fa74aed05adb24a69585dcc28a18b68b5a473bb9f6dfe890edca78dfe382e70f455d06b948b35b2e936679f7127ad831115b39c22e8f0796b0bd7645ce903d727cacd27b744e2f8e4b18f4890c9572e0dd455dcad6923f410f4dc2b5beee242a7c33f3fff2441a8131135c9786944861be326e9f8c3a2523bcefe11b0df82b7938470e71c834b243c628181b60ef8ea687a74d67df011c15067d2ebd74609ae231f70445c9c0cce987d21b9264452b247aad10d826c575ba5fbeb5c45a0e095c3d07ee9971ee2437c3cb2514a4136d7c7abe70e0ec231f9be23255debd437479f187f34fa37bf37326d649b2a8f6f41d29a17e9118072ea9c47212665ed72659813e75d933f0ecf4645f5907484b35be15ef68aa1b9948b89c463c74bd617c03ba85484384a9619d021a3011d5a7d64dd07a73dd8fc35c90b90b1f4681087cd84c35420c3cbfe3c554ef077cd652a1fd365b3c5b66c3eeba6d1c29c7cc08e2a1ea6639fafa0939f8095dfa700f311da2b85f86dec4f7f9de9e150920053cc071996a70ebf3ce0e8c54342029923acec8ab504831be1ee288b1f54bf1a44863c8793b8d2f0049a67b459ec65b2cc6ca2827ddcce0ff0ff07b1970953c5d48b7bc06442bbf3bcadc60fe268501a2844a3e17b6a534b1f8ff99b5940518b82fbdcf27068d2cf0aadcf70dbbd10fd14a87c1576d48cd12c566298fab3c52678e3f329d367e9a985f5ce06c62055d7bfb857c5d48f48643b476b592e81ffe5ccc99adf2d18485bdacc157146c6852df6c94295bcba9f08f29618f3ac8e83f5beaf46b904587d314bb4133973fbdb7baf45c7479d6f290193745b1d35406a7a66676e04245062bfa8fecad6b3e81b54690fa1757062074324a5b693075834f95254ce28209e71f1f573124fcb147352a2d19d9b307a4e79033806c5a52f8e43dad5026bcc373fdef573500639687b6287c2745db085028205f42071d7391cc3b92f661b09cd2601ec54778dd6445a4d07d57a2fab7e1d896bfbc7b73aeaf7cb02ce06ba8de6dabc777d4ddfe701fc82e1e96be9e7f251dce36b3dfb6372548b99ac8807106d26a1dbef358b7291fc1000505953feaaef1193", .None}, + {.Pow, "fcd62b335bcfdf254869fefa89f972c2789ef7781f87452b5369e52374146fc386063d8b40036711c183095437126873be25da5e426cf47610a772c13bc10d4029ad30b570ea8704640dc5b626bd55e670291c53980a7eeddbc4de0892e746d9201289a38e8060002ac36103569ad4e738a0b33b615ee31635ccaaafce2ca63d4b566dbdde9ea48820f3268b4fd7fd29da8497f8888e", "9", "e4e593f64aea42c2f0c7b4ff3b531160d8e106236ba52594c9afe110d1622be6429f6113bbe3d67995daf789274ab62a4c003534ae095590ddd15bffd1cb2e2f38add197247ae6d11c9a548ca7cf0bd670286cbbff7910a32dea3ed89e80139986f83d6eedb5f118c01066bd1504528750593a67d9863f0458a82040072e503d004b2b2bf0bb4b9aaee35a6364cd8f6808d5bc7d8dd647effdbfcfa18bb42d9a332786b7bfcfba70579f603a7c2b3910f86c514612e2526c92a029dd3516448178f26b6cd35a806b4a0feb30058d2d1596809741709f010c712f6bb3be0cdcaf76dd8b25864b7f713d55c01d41c43e8b088d426216b6dd9f07645b85e36f50952246c4c92a11760af575b6a20132def3353860784c3f718822da6b16f67a437a83a80536a406f5a7851c947c9b5645cbaf53f4e15ef2d9505c00da290037e87d315859dd5362c9d29c3a2a0529b1abbd81ee85e96545525e6073e1d0ed577b4fd1484f8f47a3ee53692b487b321c4dab564eee637bd92660b40410e6af6d138e164fa47fbfb65f713524a3d5c72a3588b378e8bde9dedab12289586c1c9dad73b16c1dee21dee9ea3fc3a1e0caf16cefebb3e49d4d632623583586a916124f478903a23a2ce3fd8d91d53a4ec25d7aeddb3e559df6f47549f527736891505ac82464096d35b81f776647d94c52a5a67e0840153705dc835f40078f48df305f61915a237c98e40a846ed66ea235eb0bf5ec5b7a933634629de9571371e30bbac5346a8cfbf77279bdf59dd5e3e29b36fab55984164cd9cc6a3328a62609a7dc0aa66f178c117e2ee5a30bce8b1aed661629e503dab19d4d5a4bc5a17138e8c5970687513622bb227201b358aec87ba9d753378a8e0b2a8ee6ba3ab57e8297889eb69f834f907b9b1f705aa0d494d3367ad8adee1dd289b14cf7a8238a7b9c7fad32c64fb0ccc5961eab116f08e44eeab1c0525ec3260e52a81f5c7b7771f16fd67119162e3f750c1551f427b96e1e503c3133d4ad7884bbda67d448a708562092259c30ce1e1634fd99b6f54344028ee9579d6073cd3f29620e23a48915e7e72be26e57a3f3dadaebf34cd606cfad431bcee4b4a291286cf1adc9c7fb30d52d01176968ae81e2b85640c02525a6743c9d6438cfbeadddb87132f624cef1c42f099aad175b6673d3c4fc60b58f7722594052607989f8b4bffe88de7a197ac9c1bf1b2f02811cc493e7517cafea38ce863b9f83b3e2b81b37d821bd979f7f310ec1cf716e2ab686c6f26a5258d0f2096cea2be6e3c2b3df6e014ec94eb5f1b6d3a2e1d48fd5cff39a628d7024194939e9fb9f576f6d3b60e892fa66a1b268c62cf9ea83e7ee24518d8d8fac4e10ef2b00d10d89e21c7a424d4668540d72c084c3b40a1e7f332c63b75be7bc5bafd787a1bf7bdbf1b12f5706eec87a6cc4f046a58970884d479fb7a21850f1b5d4ccd7896d4154936c7e933ea0f4dde98a99a59661a17a63ac47e5e5924d9e17486519d8ba85a89bb456c605dd7144503bcb237e6f2558689e804636625514d2e7f95af2fff4a2b63a842ec61908bffd8877910835c9331483d2ba7f29875fdfdb8449ebb7ce6db4ed4b8a367c442c6c9a5e1bf9c5070674e641379a709fbef4aaef0477d8849206b91e8f089deda8ec5e86a121d0fb259b5c6e2612966f3b2a70996871eb2c262d5c114dfc209cbc46fb9826c1e0f8a89c75ccf99989c012f736bb2f6ca32232b1a0b4f48a34791565776f97d909cf4658e4dfd671c86ddad21c9c787d68919aeacbc72ace559985f110023bfb67159980f8ad7cc64b2519407d78af6e04c3581727004284e125e6ad2dec979e2258e306febe32a4d3ee1d5f4451c3dfe3ad6f60769beeba5d52681cae938efbac0792902b0e00", .None}, + {.Pow, "e2c7e90e91fedd9e9313f8557aa05bf145545fa83ab73eed85d54e6ac0902ab429f356ebf64135845d21fb6ed8c1b986c9fc992595c58f43de0d1e910ff3455d27f1a20162ca17a6fe7dd9123e2825c985b09f9107900bfb206e46be6bc5cd7ae39b865c28c82daa68c4c3325f2938c1322f02f866346d7c8763b8c26c497dcdb1fd3ec1bae8b8771c4a63c7efb4d90d17494d080c7b", "9", "5602085d4c5096d60e8657bb2115f0d47f7d09d2edfbfb52099bd58f117f641e73b9927fbf440c78143a86ad3d3d343fe3f444c2b2eb36df206146391a83dae09c58d5570d2956a871eaa2a8831d5003af31a6c381697aaedb9cf1e3548c217440fe4c6c9cb7cba0e13a1003f6b639b2d91e4d462d17ae83e0d27dbd2d3bf127cd782fa2548927e17e680584f1109a24295466ab9ca954afc387479076c54c2bc8b05fa701e4e3edbc715182372bf946f490c72c3a10935677fdb3420e3fa139a83342d8a72a9ad1cca4eac144652021cbcf80edb5eb1d298b626d3778517c75b6b9a758f720143b422918bcabc483613f0cd89bb5e18210ff67506672ff010cae477365e4376f465f324556edc44d61ee62f931c6d88f115dfa47b11d53a99e8c071b95ef31dcdbad67362d26bd5730dc3f1042c171912b6b77abcb7084c3b5b1443a3149f5090f1f1e059767715febed4e23448a0c4d3f29684df79d3dd7268c93c7481ec74d8fe0286b6805dd6ef45ce80226dbe2312a893653cb2a6942941ecd52a97ecb44f3500e284f36615dc4e8c4d5cb2dad12e28c0e24a7f0a302c6b3863ad3ab1a384e9ee20a54c5de4e940ee3615aa1018301a3d264c0acbeb19d5c69c22f9bffd88a1e3c24972bc4b112d43107cf8eae31b5be7d00a66d162a051334d4f005e05748537a6ef50faf65ac69d90305bc3769fa20375ad30e780e351ac16e72115b1d11f933a01199e60f099e4942b02ee0e699fd2160337358a4e5ad4ab15756bb13344d5d185f5946f1c24d0260ba4c0ba9a08d98b93a83eff6599cdc5975c50616e8250c79300f340007f51e55b1a238146e9aa80a5852b969a4e99ae5643f4114cd5c976b3cacdd60d74c1033df51e182f1a830d9d980b7a440b84a0a01167c40cbfbac6c7a61021ca5c24b874b7ea666bcd68b4d9d4b97eff88fa8df543a85516f6281362d520596c6a3fca123dc1d28ac891fcbf0572930373fe9fb84ada7c8c3f44a1422c6ae418f3ed22e8edceb334ce4720b8dd42ac15e75c0c2c0b760047008533c87ee3d07eb8d76aba7a6fe85d13ab75d000893e0aeec0ba0fd4f0191e1c5cf7fc5f6eb8963dfcb88cfb54f81cc4e9a14e0f1bbf9c81fed329632d46416e8927dde3a3aa1521a5270b4567b1e4bfc3a6c73db9168628afe76d902fa7a28c136241a6826fa45bc90c5413d70dc1d0db4fe625661e94dcf43e1c1201e85ef5bf1510f41437e7cdedc077ac578be05c3f6c3e2ff52fff15e950812451fa5d95f3c0dc1ba6193266bafb4ab5f7d9749fb5875a00db3e73fd350d7001b42b8be02d8f667b9704907d846609f5328264c89502567e85eada1cebe3d5ed84eaefb9b496653cd8ee0e3e250059fcaffd6284e16143f8ef744b13639f3bf3c14d8d856866a12c50b5dc93e8305d5eaf3a4d1a0a764556f0a8e9f13c102dfeee40375ec7d56c80c4363e5703317c55b44bc3046fc4a86cf1d2615600d86c2006d5f640e20f6e7e910dfe228e38b4e2d9384ee3c3619c8d4b4104a2988a14d62568995f31ff7758a4acdc9d008e049ff96eed4cd5c890e42aa3ac43af71d78b368d7e4be2d47e204a6dff1ae1abc0afccf2027a102496011244cf87f0c481089fde0287d15e8cf938936c496499a160592f64ceb915dbd7e9eb497ec126acd04a81850e677212c650b2afa3019842916e6dca6c68cf713b901308e11ffcff42624d4bb32b102bc2ac7123254a7cfb9181d15b90c9dc9e8a83a51a59a289e06b5eb4be4a3e6906dadc60084fa01493b8c55d251471dd140c5e1adc7b9d373fa90d99ded975c5a26145836dafdada95bff3ab06b6f95b6e824bf9c5bd49d16ae49494ce50ec36c1f22b04595e9187725d508afba0ae7ad505255b13e55d2a772931b", .None}, + {.Pow, "-4b424a9a7e68e12143936c35a86831965cecc4254c1641953dda84a6f07725a8f557b0dbc6bbcae9ce0128ff3639794bfadc6f333caac5836e411ed33a0cdf7f39ee57d4f4a0c2626fecc0f1cc7f337fddf03dc5f63703b55661c57c1a6cf72737ae9ca5a3b2ad604d5245dc4c0f2c0f8d26a8f4197883c520c74f4cc1334b21450a4756b0c82c7c3aec93462b8212b7758a78497e1d", "8", "3a7fa437dbbd00304fa898311375bae52648fa2d0e711bd53f81e25eb172cc109461a037133fbfac0ca8700c6983a7d8ad36c5577ac6b50eaf10bc9a4149e77b39ed0e6ce2b07c362fe1b48944101677322920ef6323a06e3d06bd382956e53096752fb2c8faf10e0150c814997183d66438d5f0041ad14455687c76674539f96967aea323d0e4ede4ee9344c6517f412895bf65530a9299934118bb6689077ab4f4c846aa5c73072d8066e6032446b14943799f8b518a807310ca9e3568cad22a102411b462633256202d9d32e74590e8861636d1db66bd75cab3ccfd4eac375b183ea6bbf4603271d279d4da6ad7b163b6773a1c6e6c23e8cdf0f5b838b826bd422b95620a925a413c783c2b6b9bd58c54d46ed7a0a0362db5e219c4e6531d164e39fb7b83c475f0facff54637d72e2452bf57f080489ee15eb6c06841631a304ee28871f8eaf656da48e6deadcbefd17a82ceb75e86828fa0284593dc7f5c75d681d11515404099baeeb3cc4bc75a0f6ac8ba780556ceae3ba999b17b69f0ad342518e51abf7ca590e69c13529d953be8a5bca0b6228afeb6f740dbbbfff0c8d0a03673b7aa11bc85d9b9ed833fa9c4443cb6739f29e4318f886367651de8e2a282eb448273c646d87741895f1f04a4a85cf83f26e4d540dae959bf4823c5abb6eb803861eef60ff8bb365dfa17d73de97b8c8733d2f0e71b5cb8b3f789a13eb9e49cb8681d8cf5c83ea8b4b1a36d35135f47d7451ccf2e2b00837e39619eb96783d1c04f717d5a68ab05ca77308b5ce39589ed9b91c2ca2a1607114213e70c3843a99098a451c2fb1973337b3c52c86c8260584a7cf9d08cdde3c2e2926e7ebe8cac3ef1f674b2c485d70b130d2bd67e9966ec072ec1e9816fa793ab671157fe459b3908f5ac04f28b581dd585f3375cd3540c2d7790e9071304cf4d00495c07b29ce982ec8d7411a999a43c6e7d6569dccbe9eb6cf10b9c6f9e72091ee101aef29b0096a5d5150976b984e3526394a40cd54488d2ad545883f9b1fa21f359626e7a079656ec384227e14a39cd992fc7ebe661134790afbc03bdaf733adcbc7b050f198eaff92b4c2db10c21a231b5f2a33c173de59ea652827cb43cae18b3417addfa5047950bf9fecd56a30aa46f1b899f147f851d5bf55d99ff800ff8708aa1997bce52c4fe3c7a8a4cfaab5d663950783d88d6fc17c5cde58a7acad822b240347804453d7833383bfd858c5dd5352e02d0698b1de82c629f3bf9cd15e4f4e335807bcf5e981178bb385b37737ed3d70c9da74003b1af4375ec5da198717a3c096be95eef1c3b2421bb1566afd1c595b5c1612a71e4b17145f63c96c29a715816e4d01e43615ca5e5ff0f60f014b5039114751476067da8f8ca49bfbc42d8417336b4158b3a8dd076a268b2723022fc9c06be63f1379e7daf9df367e9cc1fbe407ea0481738a3a612ab264be1c060fa83776a499f5ccb10f560a83c5fdd374005ad3570559c0a57c99467ae195ba94c3a6ac009e6b4a9fe5e7de4f9737f6f85f90f88dcf6baedccff620c507597e1f3a67e52c5b88fbbcee92f83920d6692962d7c202ef6aba46ac54848aab6491d32d72aa442244458e706f3bd6feb9dd5973a177e0ac390689d4acbf10d252e66cfd25dc033dbb72c53691b40b34d6bbade73f7e565e2dde243f992ea1", .None}, + {.Pow, "8f0ffcf030985448110868318819f67ea7713653b1ede71c73ddc260f1d452f7b117174b92e0df5fb321bf8a10669ccc00070639cab45fd3f36a1de357a96d135df4d608792933a04005fa98e0af1f7cf8f680c0c85a7d8d5db58c7d7c23a7612d758813b37ac677b27f4307aae2b6d242bfcdfb6a328187cb682e7d080900cc55da8d41d989b1ad7b5f3e2939a5f92b8d2738d257fb", "9", "15c60e0bb744a2385cdb136c2c2bfc1d602187bd4c6aef683eb3fddd4f30a9070084cc4e309b31504553daae3db35d6d40f89f6f486fc4fb10ac13fc772223c423fba55f47b77032dcea3eb3a10e99488b264ae782f92b1bcd36ffc0d28f4276687171ba4ce7b75cf4771ee8962fc139b3de23abf5efeacc4ddeb8903b99a333d26213525cc37e4ff992bfdfa6effa144ce1f603c8f89f10ec20e144169f64facba63ff5e6bcb5b6950d28f87a51daf0d9162a6d32c721b4400d1475a5d2f088e0f4fcdfd80b8453b1999c604d1aa25ea080477814bd332a227cf52d393ccd39998aa26f1fa3bf00cd8cc719a0a3fcec0996e8caab7a856f16924cbaf26823742ef864e9fcef45597e1e7aead28852260bcd204401e028a1e84a7e13bab6819005d031649314b14475a35183810efd91a27e0d8add47a709e418dcbc9b38b7a42930b3b2d969f36174591e9165012b71ddbfd222f198e65c2048e145b0c51830a801c8f98c4d5f4a35d24131e98943c8aae44fbfb4da00fb2f5ea03f47b10ba10510a960c3c31a05d52ff4969a540d23e01bb01461dce8141c9f8f6d2855a540a74451f86d90a2e0052277d18f66edde6f4f5e2288fdf429957ad3c76440a55615b773517d31b7099b2e2488736e56e30eec9d51d9ae1de6794263f83be1af6a9521dd467686b77655c6812608ff70d645076d902ed49f6cf92f4285601e5d10262d45f895b70a2f3072814b93e3cada4ada4aa2a6418edf6679dc330e816a8d942d8d6393999d813ecefe9aeca8e666d9e89c136edcba29d703e9a956294918c3b19e0277211013481f1a73d565ce2a4c7cd0ecb7b7c2ba0d5c12828c8f2c5737340ffbe9301e0e8b487ae55fe9512ef134ca4a4435f751b4212c432b39b648f7a0dabfb551829caa36850a2e6ec94750fe3df8f5072753526c89d10af4a887058c7d7ac8ce41be605ddef96ecef5762698fa1b54c411dfee1bff2f9639e60b01583f06ef33173fae1e73fbb85c83b04f09ab87634a4a920dded1eab62326b998fb6c3d07ad1afbc9a28c83b97ec3d63311c6d08f835b36a568c2c1fa80886ba6192aeccb97b554f43c2a15f0f60499c247f50be059bb5d857ac8ead115a249acfadeca14330b2dd5426339f05d5bbd38c1b71bd2be1ed4aee0e98f77b6dac8585fec56cb3fa9ddf8ea8531c592bbe081bab1d445deb140d6098b2ed95c6396a76011fa1af5dfcb785b586136a8d33e089d23251343a3463b4e8cf069f17589407e301db5842a4393ca36e2c9d42e2d3a510a66f8c7d2496b2bcba0f7c16cf3f643d144bb33cddbdcdc05fce60ae85f83094d37cff86080da71db72f596da7a4199c8c2869d9f8e3c2b82e7f1f3e9bf7246efe6adb84d8ab7e39d4aac37a6f6dc164bbd5370842fd629bb40e23952cc83f36736e663e6a2b8cb9fc570da72c055834bd7e9770529a7623635982c2e0637d5442108d8bc6663ba771137dacd2f8ce95390cb16a29375d8e7dcb81d49ccf0904df1314ddd69413bd14c351f593d85a043ba2fe226373e0479a63e66f842d96a0fc0fb5c8fab49a1bd54dbd020e1542e0e5edab4f4b8e21b3daec04685560b6592fc874fd49868ccb3f6f604aedb72a2790829acf0ddb717a80db7dabc2f4d6d30899751912b89d752aac96b4df0984ebc2cd595ddf763b2b5cd4a5585a1c106bb11d145bb6735aa3a1f07596bf7fa0fd72432f792d44ea36080f883c8dbbdf52d956474e454aef02c2f3ddde3896de6394ad776188cd6cfc4c92410c2173cd04d435ba6377540377f69ec9d808dc5917426bcf23a978f783d9a2d43bc7a6d0952d29816ca3d3d610dcc3ada4c0a12135bb22c82a1dee6c6ba8d1b8204095a9f3f42cd5881e5bb2152781c88818ee3dc2b44a9b", .None}, + {.Pow, "-63d548331da922025b7ae6c092a8104b57fd96eb7b99a7078b1fb9568ab43a56d9091818568b2e66d690335d3715e8a0fd4c1ce6ef2be44748878daa932551bba550ed52d2d6782dbedb859b75cf00a0beaf5dbe076c9bd8142dc656e96ef1e4d63c462fe229bf30f988d575448cb8a7f692cefafda8c59a7b2531324ec930a6772b06648b31038bec2424d3d4af2d6d2e0103868e9a", "3", "-f2eba562d204356cc21e3986645de2758d27d3c44becbd8be8475de3cad7469f5b5d761f1039d6304805138ad1c81629f27665b2eb067dac318fbf0290f584597b2270b77828b6e3de41415cb8a13b04d0945ff0d339c934b6423ba5d8a6ade49908b935005d8e5924e7bb6702dc924ce0d4cc09cfdc75267dd545f11d0879342a64b9bc2baa812f63c23ef08dad8da662fe7351b6cd2094a3031e93a1ec1e659f1e0e8a1b6a65413e897aa370dd9c0d351926b210d25f9e23360bf4b41a114f08ae939caf7bbd01d1653faf57ddd7c525ae076bd6fe0b82066d9f4700e6c8b4db4ef1f53f31d9435c05966fdc459cd066b9c6d0e699aa1760d0f62104d0871b2e8485a87a1c43cdc48f0ac0952edabfc6406552dbe59ba20a5e00fae3c414322d58f3c745966ba6b74393112f3f1aa4cd2d3005134da2a2239e8ee02673a8bc52cccd0cb861360446a662d2ba2c09aa9601ff1549b620e87f8409f740c344e962c4b4d88d5f74058ce2ea7e6c32a340498b3b330daf6fc61e1c02641ea3449e27aa267c196e1e92e2509c72f84f9ed1b90d3ffff4d672623f1ad9ec39ef3122f19a13a70961984a77d0ec251b4d260bca3be8375e169e142e136f94c9de5a0a2a8", .None}, + {.Pow, "c2e4bccdf052a58cf77a0d234ba801743d7cc69809f9a0323c7a23fbf1be0bc394e9c385c4ff892181a2c6d895372299c77b5c57b1d2ce0332b30b6eacc04bc749ee6a5db32e2d6a2349bf8393a6756e7087b6e30fa3bb3c3afb0de470d65c4f8fb5ca4015c5d01ef2dee3680600f5dcc833eb75155ba556ee13a5ede147a1d22286c957b1c7321eb3dc21d35c05bfe2a4842bfaf662", "5", "4177ba28e03109cde936602b83d05f9f5aa259c1e6962828792369cd4da980c2da187d6fe017cd30e439a5431dc1083c59c3c21da19a3dc0dadfb754cde5991ebe59509e2d5a93463c3f8da918724b1270487e4c12d6fb5b532d5a4c7092fb86e5d2b6922e749e05176bd61cc67a717b1d16c06953e163aca520278c99d1e4f935214f69780fdcf280278de8e8f3c1cefbd2c54c407dd90ae96c2ea6e173af77d377e2c3f3d04f966997fe362311808f65caa21a713901634e9e5c3901893c764f91b28dbc4aa1190120859f6e41b7ec7c7a87441dd687983582f5d766a711591f9f2c5c1a2dfd64ce65eeb53963dc11755da59707a445066b7e47b73e7497b25af3e892267718ac90a8d28e7877f35d661c5cb9c7c240dca385d91cbd82f17e04d0acd3d9128edaf354af63785f6ee23306b1dc9bd6319803b0c3aa11270301ae686ae68fccb962b4ec1ce3a6ab071e8d8914de88dc2596ab8d46179b95c583791f487e4db298fe3488809bd966fb07f6baf46829a79063b849f45cd17746fc6fef544464e7fd18d5428523f4b0f3ce2debe2f5d7126da7b0c3c269428a4e1791191321cc58087563079a48863cb4a2900ca7002b8ed19d395020be7e1bdddd4bffa5f98f6bc0d40d238e98d435474495979cd7f3fe51f0f53811631a4870c8d03b4fff866ed574b482dc4ef11c32b31bef2bfe4a2a37ebab0e8b6b922e931b45ad7f4a7d33b8c679202acbb9bb5039f3e13270483b33ca48ab8b134842578b1aacc070b0f0ea78529771d58bcb4afada0f486945f228d88dbad91d31d3035fcb68c5122e1454c255f9f17d4fe5b03470bb233eef1a4e65347616c0fcc7b5de972886613a45734e77dbdeb5ef9caee3905dd24d511057d4364b82e1a6290c8629b67b33ce144cee5a7e8b86fd1344429ede19d806c30499afa38b66cde6f5ce41596ea146e4791bee4a8a669f20ab960fec7c5633d2c6600ecb3090570e6786498e848cbe6b17ff18563e861b9063272d927a58f6ce62f4ea57c1b9b9ef07bf8df069c75b43e8d707c3dd5c3e20", .None}, + {.Pow, "e9f741972ae36c2b00de4d2781e2f8ec04292b676e544b0a0636878be6535c5831744c6039c3721446f7d2b04dc1ac279611ac5a8903e3f1b525542b5cbc4943e68c49a1a7db018123dbb9271b4da2e267e7667eb3e324b3e5df60b6bc23c7410e5e33490ae0d2f56537427616227289b43c67c021d7261363688c741557d88cfd4acbdeab6310e460e89278ba15a49215a16ae3fce4", "a", "681455e7bf42afc094d1a0db6639ac946de86575b730c0aa6bdc79fcfcc8373beb23a2ced31e3bc82e2b4617ec0dde41e76a60308928ecf51cd6ab810753bd676bf78fcb57c8b1afa4fda12d6b30818777dda7398312bb0bbc1d77cb3a05637f5c75e67ddd0a3fe5aa57c700ad40b0aad91f732a739ac752056f65481c022804ad4417ed5ce60ec43740a33dd2939689416259640a9964532c2b48f0a3c6a1146a02413855dc52c4da82d35b46a92f3561bbcde30d2d2bafdb5c99134072c22f909d0c7ad281aa75646a3526e7af4cb5d5255a7731944c821433514f982fdefe236e47f53358b41e17daa79fa0e02125e2924fdeff6b40b3ad188757f903326e402e245e00abb613a260aa4943d888e0494c9fd4335107285e9486a463b17e7a411882e179262f12ceecaf7d651fbbe6e2606a1eb72f062df968256f64cc538c2ec691ba34e46f487943955fcfc66956257802978c469cfe5de5ecc6c46a0c80b81015f77370b3c242205a35d2fd4effa0e9c5c9d85152c6c471c10552f47768dd3eecafea5923da66944839e356c49657ee96f3139accfffe472d8810b0a888d5b01dc50a107d8eee9d8f313a741f6e6dced1b3967901155944c6a06062c791a1f537d542662319710a7ab3727c1ab329e3cd5c315613e9c6d112fc462449300b9af93acdf013743a674c856ee8ef72b92bd6c2a5acefad73c15167d3a8c3ac2432718c50afdf40a84772d43b6550393391eb3e4578e607c79bce4864608c39a35fd7ec079b5e898a4405595e6bd3cd4885c7305672c8704b7b5f235d6efa024c9ea1763e7d11cc17d59236f622f14ea8a42f54ad65f2c865e583b7118121a2f138a45303f751e4e89858c71e426388f4f4d44c26e625b4426c8836d4f149d232e0d126cac8cc99ba11fee3e2f179bfc7c63cea163480158d2f4726359ee049a6035e4242d8a2837b35c6662bf4637d5c3374dbe2b20da5ee42b74809619e74b9aa72123898e883551195c0da453b36334188763580d4377547516bf7eb9429723a0f3493236d1d4c70ae60c0ada6e8c2becfcc8e864bcb04c2aeb04f9435d7189bbd044b4fd197ef631d3329e466489d6912ace1646d70d24d19db26d3f7bda4ad7dad0e6595bc79ae57679810ac8eb886253d2f99a29f40e4e5f1c37c2ab9c7c183ac9a87f26871a530f0ac4a06b39427e6bbc8b3883f9d0209b41ff4b6d0fcd98c9d392af3ada28d2d1397ec9b468f05674d9dc39c6fcaea47184b676392e566b8746d8884c3b685e787e1e26dbdc0d8acf68a222d6d632fca53a38027b4532f3fab7f07dff5992a4edc22d3e80b4320caca914b6299122c3670cc2f9c3fe14c15328c7ffaf7986056fdecc79e6d958a67c516cca0762af0869db15c32c73686063825ab809211a9279e5f0c3202aede33c63cdf949497b8a5bb35f838ff169f60ad84fee081c82dfb54704ef2ba70bc63fdf10d83f4e27a7f1669199031b691493fa50024c7c83de90ce46942892be8b45b30cf97ab4d79429cae7f671e19be2a5adedb86c4f2313aaeb54890e3cea1f51ec3ede1c150b52f5b208d17c18d067bf226e125615690ebf6646e620cb5dfdb6930eab09fcfc23a7e5c2e7ebb639414f2a7a8a41cb2e0736e1b57ef8738edb3d4deefb778a50aa9be01e45e399596bc46c4d5e5531fefccc2771fadc6ad6070f7cce7c04a5ed6ab899bd19928c967d5521312eccb5a875b28f969f779366ffb8567c5072b14e591486d1c61ccf881e94828b5eabcfd89917abbc5d6ede23118c61da249417b73dfee1f510ba13435ea7f7bc7cec8c79dcb379253b9ca441734be28e168688df05d1672913322d0f6b18872e052cdfb9126dce846c34879f08d84f48ec52ef3bf15cf81ad140130a587b1a7edab2d0d4b74d4276221913aae237eb17db03913367c886a87d9f4110eae321dc8e00d9046064c6f7a8f5ba17e32de74f7ef4b508f7db61b7e3843940645a92e0a7d7a9024723aa77a1db3e0009946ac8960cc1b487b08077712cdc97d21d23357882e7334355c903acdd8f7f56eba65f786d75e474a24b5cc2dea2e6f81cad71da1fd311f4a2092a000a31d8d6a1314250b01f7100000", .None}, + {.Pow, "-2118feb0e719092057b32671a0e1119b89ca6682b70678b0fc0bb0438972524ed4a7df66818c9f0e1359c09a28f7720d2521cd13bde401c44dabe0a0eaea1ae180f3a634fd6ce66f9d827386021f577175f4622ac33289651fa3bdb456d87e191b4ff47649b4df157f85d55ba5d7b4250a3747e1f2e834636b5e22707affce682464f1a5530328d4e9d9c9924e88665a67e731dd3d02", "3", "-8da0ec2245dccb61fd08ab28b2b074dbbb7e6c2b0649b5e90dfd85a0b8562b2de53a12e82ec7cff53016f89088ad0a8a8d2197c9dc73fdc4555ac3fc76f9cd9f6bdcdb26decea943d8f3e84253c1f9dc164b545da95d72c4e453f1fb645aaaaa271bd8a22e2480c74e1b7e98143b8786a35194e526488d5df697730937878c1eb6ad43c386fe816ec21779ec24c0d3b7727220d372e4112705b40361e4a84eaf11959d88a436d9a4f4caf165b8f184427e3f0e5e804f10d986f2cb35256d85f54a37cb7098f119f2edaa50e79c1e8be70f50544f1596b8c8cfea1cf9b69281f00c8e1bca4426833e13f5c0bc3b2eaaf44364aaa546f84a0535f937829de2c3462f101054a9e449399a9b5d854924d10a1b632d2484e62a1beff67e09d877937da15e574f775369ea5ff1c86a7d298f697e706681aaab3e023521ce3e848045c010d22514bd0d21e2009ff9710431405076ec2f48fd345cc39f2f526d8e88b4e72a1990ddf4de0d957b5181faefc45214859db6cc69eeb9d682929f43d3aeac96564dc46b0241c847006a3d031d97e294a1c51451272bbf40d40cfa1b1096cff0ef7d32f0908441d10c850ec53cd9acd68f2b3042c2fbaf9f47a8f808663e94dc08", .None}, + {.Pow, "fdac259d1d5a3785cb55a5d9ce2371f46da1fcb43ed48f5c9e02e8dc77e824fa5ba59548c6545ff2d687d0bb48bf4f5e3a2fd2f480962398cdc72edd476f4c72d1179cb0cc60b6cf52c89e8abdbe9a29f73fa36347f114f7739fc02f2f1b97dd4a6990c4f61af24268ca1db3ff5ae286d073ad257be1df72d26581896f411e6453ddd94fab38a48774a56a89c380dc65702b7fba0c1d", "5", "f4926b549343a38d946bb6dcdd25d4e656f8e238edd123fa644f1bc4ed9729be751bb3479c178ad2053fbd5192fdb659c5959267d54ac02f7cd2eaf9cc0414b277c29eb871b89a10bb457c177c5edd15db2f586bf9d001897842b854eaefe4e2f279e119c107a8d3feca365f8b465bd66fd8aca196ab7fc0c12c01e5e2ad8dd533fea25c095e5e96370ee23c7f40f6a707d6ba856f486876a1c2929b3852a5e3f2b9469051b5d142c0b6b8a6b5a3a3630b765b1893f7c9b5c66d06da17ba1c3eb4d13582f46198327289fee32feb20e0be346fcbbfe6a5fce2c30dd10e5c0ecdd03951f2556934c8c090088e0cc910050982220fc3b8702210adaeadc2f40f4ece125c9854c9cde57f5f1ef06bb8e9f83a3927f2e7b5877b0b53db54237d77629d989b5c87cf6bcc165923b5c71ae66644a0a2494053ef869e20348aa50b7fa133ebc62d1eaf7d34d08c2e97b69946ccfd61fb7536a33cd1ca1ebe680dcb7d4fd0da813ac9d9e82f9d5b2cff53a8a5ea70916c6e8e13666813f9f94eaad2b9cc6545658555c2fecacfca97f0b665bef1d47766445267b406c9313a88468d4543897b5ed96d9861f6eda7bc04fe451631648a418afdc708a627dd3a8a9a1fc141203d91918017c67b4907b4f0af27300f1a1c53b91b1fbec6ede6e49b84ba8b057aab8c34f8e3c1d7037000d9a630a213f0b4391eb5ea3bf7416c08cfee2fd704fea68bb7e64dce99e2467bb5072e14f18776caf8b68a61d38a4dee166742da0c84110f4c55dc2c22c3653057516c4793be4af23a6527aa2f8d8aaf8e2899a448d69efb4710a21883ac7f5d75784c35313bb9169216788a748207fa695b95a19f1af4056cb35eaf81e9b5531fb7ca4d2bb69b6e3587e92925a473df17cf39c08e1e67e88cb81e359d7847cb5d86d158d40dd1fd448f675bdaf61e5aee5a540cb26e6fd86af60b6886d903c7c397913425340a377d1ffaa9a72a9b484e187df3c8d363e2014dd2eedb499f628bd2afa67e9c6ec55b66d9161151bb7b79211b065939d296c05323a139e6620323f5ad", .None}, + {.Pow, "-b38ee5c7b237346c8d6a98a8cb9e92796d6a6b68ed08b1778e0a18738e8b61195c74be9834538d6ae423c87205614991bc262fd3082805c4a0dc820ba5d701d4ecb8df1e73008f7911659fdfb18c85bb900f64e4d632747203419a4fd9417582bec92c8d013d711235d12e63b1d733e1220c54c97daa949fb2238bb006ee4987ecdaaae42b2dc0eb0d65e44f3dc032f483b51f66462d", "1", "-b38ee5c7b237346c8d6a98a8cb9e92796d6a6b68ed08b1778e0a18738e8b61195c74be9834538d6ae423c87205614991bc262fd3082805c4a0dc820ba5d701d4ecb8df1e73008f7911659fdfb18c85bb900f64e4d632747203419a4fd9417582bec92c8d013d711235d12e63b1d733e1220c54c97daa949fb2238bb006ee4987ecdaaae42b2dc0eb0d65e44f3dc032f483b51f66462d", .None}, + {.Pow, "aa08b38d0874495461b1eb38d0bdd31a2e59788290abe8d20a5eb11fc3c98b9f462a09c4a18ded2e63f7026c341a2b1b4931d8e7f40859924e2b41fa9fc34d9aa1f3c7d2cf07557827d18b610b201ce0d88e686a655b92ffb66bf8360dd4f61c7d56ddb4758603de67c7596ee30dd0df6f029ffe58e98e5c6b82bd6985bc85f6f9f485a7674f5dae694695fe1a43e21c9c8fa014d874", "2", "70ef8ec305f9802d95f2a880654c9c33d03cfec379db9ea458d156f6433e195c2aa5aae6ef8e0a549fbc11c89fc52e015ad53da82d8507aaeb8c4575a342624bb02e07073ca90a1fed88a1f24182c002aa12c4bb4fc61110abf3de87c5f767fd603fc4ec8840b1cd9ab18159895bb44a733c3d5537170e7aba883391e8dc05dbfc3c0cea425ff090e79e833f89c2e63d48c4745fe63b1655ef9769c4f90a166e14fe0f8875f9b210296e98312a02886846a672d55e08ad2c002483f244d04b82220cd335e129259dac1eb33e13176728b1f94f099d829939bf5966d613394754f81286147cbc3b74a8b9e7acc39f49c203799544655ec263fc874d1b6b9c580d1236c71496071d70d51c8e27d7d82d1ed7d8ab66260ef8bbf69efc02fa7d1c16cae00b21cc9141db8923f490", .None}, + {.Pow, "ebf4e373e61acdcc800ef5392bd2962914cb1808a8fb11d281f04e12088d8ff104d6135f64b59f839d37a85accfc3d5c8a9ffd0b4dc6cce1f6b146255dc85ec47acfc7ac9679e2df69c56284f0ab54a12e5e89dbde66bb0709af896f4ebb5d52577f18179c8a350f7180c7e9c64395db4a4e82ad68b7a66557253b8518375086203a3cb172cb5fcbdb9a60485e6660b618fb5ee7dded", "5", "aa4b67906e509677d0838172d48b0d7b54f5edbb0f0f434f2914d73b7be90c233ebd18152d8ed72014f5b922e1a2c25ecefc9abf8badeca46693dbb4dcae907d5ff8ae8a5751fa570563387af3e90ed01d1e636d94c5ead894b82460434f98fcb89b593b8c5196496b1878e9cacb4e325593e294bd29706eba96cb7e58332ae5246df73f76baeda23790af0a0d47ce9e3cda0c16cc75a71e8e2a869ed1870ece4a6caeb724d949e08f05b403023d1175a7147a7ad3c6a6695f7dfe14abcdb67e8102b4058689e7a06966e55c3c898e21e3284c66d97926ae7f0407cf01029d68295e2d94b6695e2a808047278bffaf3afaacbb1e628193864b110463863f70c2da743f15aca4bbf925c206122b9801c901d5d89798b0a27f55b26d853322008179db4da72b5cb592397399f8b9ff7e7f24a742b8f58a2d0b98768a179474bbc68e713c46c1b1ed33e73bbdde0b070d12e531ddb05401ef9ecb0c07df69bb26acd03bb071e4e022ccf61d3d2e670d2f544e643d6a9965709813ea7f957efb49d259a9b9c54581feae36054251b9d8aa94fcddf2910f5ae3bef941b1b869f317baf40da52ed76c7ac5ac17c1fc711916f403b71de5dad5eb1bbfd355fe9db60d0595ad9694d9e3d30a879e6ede31431c7d7dc4ec87ba49eab6f8dc0b608d7c59fec0d26d78add3201e3ae0e1f310a987f2cecaf2aaae468eab3e132e7b586fd4bc49229d5b23b4d4c834be8cc3c0b4fc901355dc4d06da24253cdf889a8cf42002887e1e34d3d99dc99e255a6b8214e3edc29eec00447d5f252cde43ada0001a202257f79f16aa8634dd00478a6785fc90bc85510fdcef444e04d1446a71d3b03f07453c68403f2573c11e5f2b8b909faa2fe2d6956a3e3fb9082f072f64b99a519747c12d5429020389c982d14ff7dc8a39c367f3c426e930167fc7fef0e820e5e1677bbc77a20659b70eea65e8c6cab09c105e77fe778b8f4df73309a1be2ea0e65d8b722b30e2a598e2fee0a69f702feb21df4ee06c67f9d006861ae999c808c0dae5b150be5d165b3eaa1cedbd", .None}, + {.Pow, "f534918e9b634bb6d264efa0674cf9156e9852aaf5e2a2c20b982636dc7ce6162117d57ed828420d248f0ab6e146a95cc195443e7643fed658b35c577fec6d988387c680a1aa9ebb73c52c81487a17fe1b9680da9ecfe184cf750d84c123118587a3f7265c7cb540510c8561abc255ef64f774be5bdbac49be8af14a4caf083ca80676d2e522449d7c7b1f34d4e5ae4eb4080849cffe", "3", "e0f65dafced296082ea23fc479c018fcdd1e07be554edf3e594305d03e5596bcf9051eb7c0c7101dee0fa8fc3432cf446f7a56c52ddc70f7ede89361591275233dd3282adc6c07073d88464415176cf7bb12f7e3894f31851c45dbf6683605347ac1d4c68f87596b5270439ae9bfb7d02658363ceae589fdb788da080b5c7636e683bcba6db926c9506e9d93fec4380f6e174677c56b9cc2dc8d3cec92d8330fb3480bfeee3811d9d45fff57f63e819c0c458f582b7b3f16582b3782324d439cfb1e5ae2bc31521de0552f0c0c25f31b6d9f8638aab6f624f02b75d0c6afe811b5b0d372ffb6db6e654d563d1118f8d344bca380b78fd82523eabf09d5e5858de02ea2e63b39df30ba84a34bd22868e62529db978e49a1e98b3a2f13a63a5ed344e12dcac60149bb3c5007c8f23f159d1574d19f36e84a70eb34319f9cb5e47cfcf2839d7736dee855568a14d3a086912728b02d2318b43b130796b22bc017c78d6b569edfd4531204c2eeb229c05599b68c5b1482a2f225e5e0731b4c1c2814fef35d0809a76bfea77b942ccd697082a02a97ecafa6372b2ba9925ba75d4b01c1cbb26d7176be5eba6b85b7fbe468dcb297e39337a2d65541158525cefead75bff8", .None}, + {.Sqrt, "3d5278fad55ef9cfe9ce2487f81ac41cc6c6af807a3cebe60172d970f37f73a8b0c104551ce114fd716b58dfa2fbbedaf8ef975d1ae6b015401a2b2730b98a2d719b19492d47a40384bba43270ef1892377a630016c050c65faa28de3324dc9e34942e3eee5691566ccbf5314566523713b52c46f678bb707d4362d22efac79d01dd21b475181e63ad19f20717512a39312430329dc2", "0", "7d4b25ce7fc97b226c8a22e38070a43c6e45be4d594f06cb51977982965be3fd8b6b43cbdaa5edcba320c852e67bcf49d76e3a758a90dae5cad996e7c8c2e84b155ecbd659f989acda4f69", .None}, + {.Sqrt, "916261d5dc7aca16ddd77ac0b8249772875ef9e4bbaa5ffe6913fda01a7141fa11fa513db06f5dd4ed30420de878978e848aee43346ab4f9d9e92fc0a66afbb48b669f33234d412a9e72aae5d16c4fef838f9c51f8da430eb9d1c1b9cf40e9fa94952ca1a6a403fa424c6942dabb2e32e411a2a33bb24702fd7d38ffc91ac45eaa51c81730c01c39c70367fadcdac1d0cfa25100e060", "0", "c0ebb09026b37977ae39c06cefe87bc58232c89ad76f415d41451162b018bca2e7065ea966318c0a5ac2adbdd5167f9f7b26ac8837ed392cf4243613de91bb37a8682b015d6b5bf740bfee", .None}, + {.Sqrt, "b33aafc72be7cb2c8015e6d24371389767b4618794e2aede62d38fe44a7b1d75fb8aafd1ad76080876af9b4fe246d2f5b437fdd5e3af7eac367e4fd3772e20db1df392a46f257e25d663a67de13c0bd095b373d3a424a494b142cd53124000742913071ff7b9daff2aa112a9d40b5365ddbcb972da81e71073cfe6908e19809bc6c54971bedab5594c55ebcb21380a3fa1ec5023ded7", "0", "d633d34fba723b8120738e71d3b80e5b20d1ff313cc0bf908cdc36e1b60cc8f5e69512fd0fabecba9a3ae8d93142d320a7c603c0c48217d0b8b203688b806ae812ff139957669110f50e76", .None}, + {.Sqrt, "1a99962215c83c3a5583341d67045737ef0947cd7733abcb800c62422efd4f7473f731d2c77f93dcb68689e9406381a469ed74c3d106729b905e2ae9252ca4a0b3e423cb2bd8f170bef29560a51500c229bf0b841c4cefd8af716b3ab9320ab5f3ef9823eeea47cd470db27028cd78ae51d090789be0e52e60100f207dafe403e76f4c1d88d8954ab6d62e2d15dc92ecdd3ee9e8a60a", "0", "52852d09c43b2ac121243b76c383fde6beb682775ac3a25ec8c83b3eef7e01583502641ff524b9979815f871832411b5c894982b9aaff69aee837ae4ee3ef1d54c888533a0fcbc22700539", .None}, + {.Sqrt, "e26e32ff43641dc843dc31cb65e17c4140d3bb6a17afaafa6ec4bf980472293564cae8fb2366dc8c21be13c596e552b0c40dba76345b8ad5c90a43eb5cc2d90671bb4f0028288b946cdeba1e1b33322537f0647dfb381f60bbf58fde941e2934e72a762b5435e7aa7323b392712caf49543a523a2d20facb1b845559dab0539aa464b6943d6f5f56bf5b8273311ecc32e7a429b85811", "0", "f0c2ff2eabe2fb1b5819086dfe744ae334e9f44090a7782f2c1d827d45078bc0e1e4c4f24694ea589dbd60b02ca25b37abc2ec3309e0c5e4fbff10eb1f4a7af6b26a7e586025fef2dd69e8", .None}, + {.Sqrt, "2a64a11e85ce3cf0b3ac7b9f74531a29e8b8d10b417a209805059c11039c47fe550e805b391ad97ff18441f789726c4dc160b804fc2eba5be1807886c0546d0575a001377519315dd51705886e0d0b6c2dd3c9b1ca943d42737d4b4a807978a50df539857fece57fbdf114e9769694614f70e58740b84639bb50f141648da6e5e3fe74e6490d73fdf4be08eef8de97cdd73590e2ecb", "0", "1a0b42d42ac0a448a7c024fc0e048d08c2460f0513c82e649ac7d0a02e52348d3b7b8980c4b93411eb1600d0658ebae689dcfe7367b2b50a4e00859e8c0898f234a9f573048a86320b62d2", .None}, + {.Sqrt, "85fdf7b9e1dcaab9addc9930f452f9fc6ebe8e64bbf3e548f411d627ad5555a72ccf36d4aa35e2c826c2d3b550a66cef1bfeb89a28e3e33282169c69c440c42f3129dbd4cec7e7fbd2800d11a8c0ab4488af1cdacc70f2a745854bf78a536c6c2167983970d6939e8b333481eb8807e5d5f672f5c822aa5cabdca36c78ad1ff38cd2597ac51c7940fff61a0f0da2ee28b9e6da60ed2f", "0", "b93539313a9a9902c31a029f10b63e98ea47f43e7ca800ca032e5c9e7fe438eb300fed83e47bba2037d73b0427c0d16a8dec068b8d4f82d72a03ece752be1edd622c356a8598cc8ee5d7fb", .None}, + {.Sqrt, "d7992e56735b1938227b1fe8ac820b04891df59cc15a841cfb0e769708e823f1809a1bcd77b1c85749e235136f148331264673169359b7a32b113d427a6682fba148efdd9f0a061b2d5e2c861c52018780e410e568b34f431aa9e14c856fdb0e4eb43eb4fae29e2f6bb66f1286a3e084860ddb884f4446915b5cbe45ef04c9cf5f22a5a03666e342d54e0f810b4b7b3bbccd71361388", "0", "eaeeaa930f7572c7192d73f3106446b366d319e6f9f7e2f2dbb008643891253a6e1a0f861a55ba8721ee8b1596affe59f94b3ff63042f17f4fcc81733883f8a2df8cadefa1ab35407fb781", .None}, + {.Sqrt, "6994fa81292953bdbd2881cb0cf5e1b485cc52e1a7e40e4310768a6ee80e49b050e81a68da29aeaef58d311ed4c041a43a51e7ae0698bd1114e8d54804e68e671e7d431ceb757870b97d1786c8229c59e712ec4f3763b41c72010fb00e6a2b1e47492d58d234a56391e8ce59fdcd53727bb1f80d01f5e8815d6c4452208d22daa30f634d8a6f882d799b3f1bb7feb383e1f31c8255c7", "0", "a467a8ffcabe0405ea26f05cae065cda28d169ff8a50c28816dd6d7e0ee4f4ad6af8556bc2bb23c999c2faf6604f3688289bf49db1b28ad7ed1d6b79f8608b1713063a6432a081b763bd43", .None}, + {.Sqrt, "6b38445de28a0d1014837d8fb49251cbb5b6d20d44f0e01bf93cc1504ed43e49ec91da2c218bf43d869ac442f2020b0bc45ff39884ae7f9cac0f445f1b53a548ee6aeb0144fd85fb9025abbee4bcee14382333ce8dcb916be1e977f24ff6c3c3b9cf4b99fadc79622e91bff052ad821e8b1053c651fa49b7dc21d5b4c4efe8e965d40b5d40ff48a0e6e017dc0fa7b73824fc2c77cea4", "0", "a5acd8f34eec3a56fba53cab6f0691078c39353c7fb655b7f801451035253ab314b948d8e07caf133554cae09ba06ad077a8c8f1429f18cfae1b296c4066cde2b2b4605301c8ee4c071798", .None}, + {.Sqrt, "beb080179fcaeb8fe03901a0a04973f4401e5954bed199e3461697faf189d4050f58acf4f5989ed571107a69a866cc427e2090fbd9cbbf84738f7b1c2d0383a18ec342f91a386af7c40715de9f37d632bf97d8222610733cfa10b354d8c937216a8ce677450cbe5f4041d0b263d938ec6f5f5f18e669b3061127a33a95fc439749b6a336f455f7406ac48804a2dad91672d736daca20", "0", "dcf1cef23a6ea53c9bb9e9b500565985f0bc1e7d6a31afabbba92bc5b45b081809c7054b6abe7ed1a1ade8376c3066b5e7bb95d176b7004aec13d17bdf706778b6add5b736602b6e7cdf72", .None}, + {.Sqrt, "90d50f9920fd5ce0666adc1e6c8e0501421bfdf53cf31fa8e71441c06724358929a6ab4c723d8e0e92e0622b76acb943cb111d8f50fec417197c93e8bd2c9ecd58723aa21371e50b14fd450aad20b4df01e3cf4cf4bdeee8e591da8df92bf6af6d1c423a5de87c38fb922e7f9525cfb665778fdefb70bc828b012a4c0db4584065e416ca3a691dfbd1fb9b2b431aec01754569dfb865", "0", "c08dd60274eaf9b1a42393d8bcaec4094172ea59e31ea75dcb57784a526997db37b697e18023031d819980c6000917bcba5565f29a2ac5cfd20a66fcd35b46bb56e635a10006a142337f03", .None}, + {.Sqrt, "b2643f1a485aba731cee8b229bf7b7e02376f8c2f37319d90a4c793b89f3cb38251a52324e342136a8859075a4976ca68f63d50f07214c139efa73160e002876d3767353d37bb9d1fff0d6b69c8570a16527b489364250f81b50076415e127ccb566592e1e2045529b17e12c5d89142afcfa5bf1cb6fa747c4e086c65559b0fdd3921b0395394801ac932d3f0d34e4564a75e4af07e0", "0", "d5b38887da79bcaf532fb1d08a96ce7c4ae5113b44a1effb7a5d5fd8ab7b68f98d7a4e6c5986a38ea5c00c735230e799a184320e00914d5f0206f6fd394924b136f8d9fbf84f3d245fe148", .None}, + {.Sqrt, "23e1bbfafe9ada939b041c34eb4181494ac9ada01be37fbc4d6a337cdc966493c0f32840e237f41c08e2da9931bb4b8a34c93db0145e0661b0f5f773e8b8a37e8e5ae12811e725a91fef1d9cff55953e5e35c2be6238ce13546b64837e2f4b89fc1da5c2c52f6e65e4d7a9a8a5d122f757f7fedf3130a44218b88008b1c7a34bdefe3e4f7406ca89b537bb87e3a7bc866a3e7b542c34", "0", "5fd79ccfcc25c6ef571dd5348c827534674d89ef472c5e0b68f3fb57ef526d45f97f21bd8f6ab498abdcdbf11bc180e411251cab23acca55499576ef84bc118ddc5932b2f9b44250ebbc70", .None}, + {.Sqrt, "cef6e38111e678477f084d2435bfbbe3823e2f8a1c5d5b4a3733f20fb1ed142689c2a41474e5da7e6a964564b7ccc9c9c71fed9c144885edbcb041b7a7a30facdc58ffae2c60fbb1ced8a68dd7e6a64c921795ab303a2659fa40a185891905c36f4aea06a6589ddd558f54bb4285adbe47be5858c3f5a793b5be231c3d45283071cd12e68916c1ce6b2a834b426f363c8cf075b6f320", "0", "e62e1c7e3aa35ca99076e63625d21a1f02816f1fd2e0da8019f1c435d355970e1023e95f12a366c48c6f17d902350dcb18684675a4f454bf1efb7b51b1a9d527bb7061646349e8f7d455fd", .None}, + {.Sqrt, "f58f6c1d4bcae9502f92e3aa28d25aa5a780f51b781b8236c5dfe3dada4c27b4104a8e4de51f3e9159d93b0327ae6efb7adc754896ec94fbc4cb5ce465c7aa55fc6f5054dd7ea27a5efc0c383bc2ea61a224a25a4cf5fa7bfffd5018d4740ac1482efa8b27658558a9daf845e0aaa5ace54e810c62c2c3f9ba26ac364e55dfcff40eb0169ea439f23979551f8f857369908f91312f45", "0", "fab9cd72083f0f727127112e31e060911bf56c6fd8628fd6870820edc641c5c0d8ee82c33735e63c768a92347e543a4593cab5a2d0d904224a393b850a57fe8062de4d60709e650871da7e", .None}, + {.Sqrt, "dd34e5f8593f7008a9141e03dd835f00ab4036111f838e67f7390351d499843b0728b714c032512da9df668314088e9685f39b329c108f956cd348d82580b4d68774d0357c7becaad68c6e4287b0a92d4d6722f50004c36aefcefd013b4673a0cc1e84cddcfb56f115210d82d1453d47c86ac5aea4994840f7db8f5da1a987b6ba407569e10a9420ed0d2da0504fde62875a98359f4", "0", "3b7df829bb236eae44f7600249f7fb7a1fef540e4d0680e3d606a5af4e70f8af4b55cba6758dafdc74ad82224c47e55097e9f9411847b896f1833deb483ce35a939e6f602fa261ecb437ea", .None}, + {.Sqrt, "277ad6853c6dc86036f600012694ea62aa798764af243ce96cb56c0b7475a37508d4c6089ac2662485b751892c9b3968980b750ab93769185659c161eb6bccd9b0124c5e7d7e07dd88e1e11e6fc57ebf4ede2f55872f0a388677b834c07876b670fbbe8556e785769c90d96c072bbcaecbade54f46703a59e825848951815d80b7f00e2ea2cfb6a0fef79752cf4a32dce265da7720bb", "0", "648863a7ef9e8d55a5c251471b61244b040d31f9b650aac929900d015c50dad04a271289b8b45337373985be6d692fac8ca2ec17556c17c14548adf7acb1751ab8c11cc7bd22a32a76d33e", .None}, + {.Sqrt, "1e3dfc55b87ddbcfa0308658b8b8b2c7436fae4813d7e2df53d61e8efc6ca5f1ed77fd1fbc60ab58d1fcce92a3fd7f28a901080d1e58a01c6b1073690b6765049c03ca410a5ebb5eea29d1366001deab057fbad34856e26611635e4ea15473293ed9e5e3fc067713245cc2d5bc63a5bbe1f647295c6d42883e629a52981be1afdff14eead64dc557b5b8b28fe49dd80526595d30724e", "0", "57fd11e48f6a478db1f805ea968324269072b10ef40a9fa71fea294717be2a8de5b9698524363067c46e669e6d99578ed7bcf2919a089426e538d7e7c34f9c39d19a2c5a0a951b7744ed6a", .None}, + {.Sqrt, "2764b7de009e85f790e9284707ad2aaba325ee9d70055a6e3ec4630c17b435153e40daff30d2f1e3becc87f831b7ee2fa14d52a88c148d94338dd492ddbe10c8d3e6a68a5f8b1a97218eeda3f1474abe57919e90e3213a00c4e0435c56506abd7a3b761f8ec099813a2f30498df1feaf0312af2cbc2d8b69d158939c68b1345e7ee211dd0153fe8e3b6b36e1a0ae3471ac67125a3169", "0", "646c35ec1c372b7ae1c9956c49350a00da374a110910a0579d0203a67537ff3d7e8a1128c21428d254c7a01c1553dd929668953ce1c08548ed5919eb2d57de8a880a831e6bccd5254c383b", .None}, + {.Sqrt, "527414d68c36e26aeb76bce014df88b0fd12f44dc88b097f8088b1471098c2262299f9cf1a3c4254ca3728e46dd9c32eae7838312c519c3ddb8ae80428cc9809f525d4f3ec2f01ecd0ee82f26a1d691487abafea1317257ecf10bb1d26895e07b06a67c3921c0fe6bc4825d36471fe58a8810323f79448eb89b8263b30b9005886be5b9eeaeed29f9fb153410a5ae306d0a633759b8f", "0", "914944bd26bcb2b9d76e10dc7481c95c8942aecf8a0060219c5db4c10858c611fb69a482e2d48397f3b2cd66c1de462a4479aa6a7c16ee92d8d1a7739977c33e13615a804b0d1baf219439", .None}, + {.Sqrt, "6a2b237f17adb53c8eb222d3e879fb7627408a6a6af4c64a46c3f29e5200c946185727ea4f5ba7de813633bb9ef63521f53a43eba66c1a57356111db05383dfd3f25268152d74bf379a0dd09771d87147b3920e3d868fed38e4b31c564a5769938f43b70062bfe983fe2f63005b5b7bf1f006845539eeb9ffb015f073fdffb1f7d7e516a468d1be55d1c62468738df2f351a241497ef", "0", "a4dc686069b00ff592b5873bc09598c8bd2c51fceb351e3b6c14df3dcdd3d321ba515657eea045f11652bce4f3201b55eef50c2e99f860b82d44fba2cb018d65f338bb6017321977605d65", .None}, + {.Sqrt, "702f9f744f2b6012fa08ba0694e4384d3098285b71b873580a9b4307d944b522d16f7e0b52c156d3c842a84674204c7302fa43e0854120ac5b775dacafac410fb26698d6cc22721490aa066c3c68d18de67d535d877b900e9c90b3c302b41672be6094b6832dc907a4ef1e69644d7dc6e02f6f4d647c6a6cf0329b2cfc42db564b33cfbca060c883c4b69eb327a7b663fbc6afa7ca31", "0", "a977f95b4b4ab87d575da69e1ebbaedfe8396f4e1339516c69a9b916e47245be67d210ca873cd8df582a010f33260b7bada0da68d4ab13377226c83c531e44943ab9eddb05c86dc3c586ac", .None}, + {.Sqrt, "d400f6a59c06d809b88fb6560ae6b2380343cfd271f96660121a13e675fe5e06af1bd3ae4e582c3b39b5df3a937cdf77f1a88fbf62a0a4a0eab67b5080d74bdb6cd33ca573695ec3e405175c7203cf8f85b022d101d329aefdf7968681c11be2d8e689a3dc56327ff61ece2a79f98eb82e958bf69d1826cbea56b05ba26fc7678827fd84705ed7d941b6da0694dea16de5b1f587ce1e", "0", "e8f730883b8d8c2c970243e884e3b5a020631879284dced8928854b57a7a87be342b64e765753306a0d3a7c910ac4a45896ec424591f69ec326aa41859d9342ee85a7279ef738d21dc240c", .None}, + {.Sqrt, "e5b13a33af06517d4e3617c1d11d2ea16fce6558165bbf412731fa3d014ab9789fe60f6d792cd47a8303b978798a3f139be555c64e5e445e450d24828272080ae6d02100d46dfcf61a01e5584d3d4506932bbf493f961c3d639455ae9c8f3344201c5dd721578a9548e408b1f7a4e49ab75584ec06d54c0a612098011158341857cb076846e24ceef8304686aae491b0e7ebada7ccdc", "0", "f27d594bd37ab3eb355355bad14c010da1efab7e6ab917928184eeffcea12ae2aac9c9e1ec33dd6894d694fd5c33408d0b01a114c0725d9051843c3fcf487dc9a5a9263336d0f18b3716ca", .None}, + {.Sqrt, "17e4cb0a52c3fa4bd6c11b054860940a4aaa9768b8a7665f7f60e8b250f7769bcae96257e2d4591e75f10f4c027e2ff8c222f82fcbccfc7af8a0212547e0c8b476395e309b4e066ba6293d25392ce0b1a66dc407529405d505203eb6e2a81fd74e50288d08808510afdb3c3dab6f9176c9e4e9e188e76a4978cf5ae5e9e28270aa53be8360dd238b653c984db64b0ade78011c3378ab", "0", "4e35bdf6584b1357408af4cf60d933b20012a35251c614a38e5b2630cc2e7ef2c4cda92d8ab1cc7f64555c1cee057daa58ff89e74c5278edc136d2ae5ec868c2590472c554da02d583a2b1", .None}, + {.Sqrt, "f1fc06cd0319eea092fa61657f8d644cf9cb5536981e61ffd3e77f646d74c8c4a638883704aa10a4324ae504eb185d003cdd719d3ea3a6ffb3e8856990caa3d471312f05df37328bae55d006b460acb6c1ba1b863ec5f0b46b795376010761a4c8ee18ac5e711166a4aafea6492f12fefd45c02f8f4b7b5486c6c66121e7d77872ea46fa1a733fd222b3e7f1de444e9428613aa1eee", "0", "3e3930d2a761e17ba01b451a4719cc7b0affea5dabaa1ac854f433fffa9d363dcfe6e5536b42523bf0c579fc3c82b0790145c04ab3e66f13d697ad06fed47cf4fa8b6df83b1d2dbdb89e40", .None}, + {.Sqrt, "2125149018a324a327ad63c64a5207604c98632c10eb6b3e9038130fae8f7186ab24a7f68cd64fbf44c94a8118c05d944bed44666470e5d1c4a68274e000f719c0bde27a6ec5298af47a39a1734a0e07b5241a89fd95ed961030043290f235bd7a45d37d4bad8bd8a8ab361f4557fc4c7a504835a775dcbd6ba88a6c8e1c56f136e145193505d125ec191f4e6b30fb31fce87c8d7bb8", "0", "5c1d4f979b30c8604922a5ed7a0e0b8e23bfd17d742c12d5af5acd94da5bd36fc0c2f738b2649f1042f1b5bad86d0b6d8f1c09dcb50c9414021ecf9cfd1138ba0a186f11490af6622079ae", .None}, + {.Sqrt, "83adb0e0c38794dffea03c4f944e77c417281332a4f66b7e5046b158d4c33782a0a5880eeeb9c209504112037853efa75e0d8da6560ae95e49148e2a6d037db140a98399488f8975e058eed2f8fa962887dce33f2d2af99e12507f6b20ad7e85bc9903753288985d95345526e5909a076a40e3774717170d35f5f64c4cbf5478c784b59418abf26c5aa7e9d327b031281e497178d0ef", "0", "b79a1c0d4a77a937a9d839132edab0537163a42955927ea76276caaf5d88e8912ef1e0e06dfc1eff4ebc18ce68bb2b4eece6e0ed7fb2d001080c97a979a0473951f0bd785def745df97bda", .None}, + {.Sqrt, "430946d33d8ceb639ef85756f374d90510269ef17cf93b9c9ef4929b243f5e849a265af459b4af6ae00a3632f3e0cc3884cd976e4746cf41cf8dd7d8d6321e9d965c6a860d244da3da92de5ff3abbd53d4190dfb1fd10a30d2e056c74bd4d49aab0f3792c2a2ffb6d9ed58aa03d50fe30e1ec310174d2e1ca5e33a6ab8913eb0908d513609d53d8b7160d62c88c8f838fb90c635427b", "0", "83004533f32501bc7981bbb318d6124c063e5445fcccfd2e9fab493599e6c8af44b2386ca03a00a1e70f84fe4d2e532d9a7fdf6db396e873e1abae17cbd984c615cf52431046075dcdf3c1", .None}, + {.Sqrt, "708b2c50f578cb031eb7555ba493e35c8b13378c214ea8f2c939d33e1ab1d4fa35a25051daf331b09ccc138f2221b11ba9a567deb573dd882cdefa8322eee615aae107b46db164fdb3118d052c961f859b93245c418f879f7e5538d25daa374109f1afb0bfc5b8ea31767a0ef54362dfa724251501f07a1762c0d1e7652dcca939a83f1cf8824109e0a863559d72e3dd0a408ed08f49", "0", "a9bd112de3a4c2db6a6ac105d18905189a1054b3a0ccd9bb22b83e88b4048d95cac4516a7f841e5317c1c77e5ec25ec9c566b15121f5d4c9fc7a18d71efff0049bbcf4f50a4342d881fbd4", .None}, + {.Sqrt, "a0fbe14248f779706d06ad49a4b1c1b50a88a2237ece47d34e997e7128a974aae3b6279ae5d70a2ab63e08a91307c0f674816a17bba361cbc39c130a85faf2c24ec902731557bfae9b946ac5064ae3402e1381f276be4071a80545721d2746733950cfba6fb1ae81e3040c27164558408cc5aa686f790ca5e5af6c9ceeddeeb5e65d8885c22c8b90f4c6942c2fecec60eeff8f019e13", "0", "cb01d0dd4ff8bac700f6c30025690c2a0a86b07efdeae9bb93bc1400045bcd9dbfe5e174984c7758a3516c85f2ccfa83051e875dc1568fc06b1fafe0d2b35550c933c14ac79be92330b4fd", .None}, + {.Sqrt, "34caf5fa616aa55dcdce038934bacbc35d29526bf2b7d7a26ad1177ddf7a9ef38639479977979961c682cec38305ef6b40bf76c4838f1f164b2092074f98d963c6649cf2419defd53ef86f46e73549aea175220671086191935a074445f9eb741499c7d0d3581bdf78958f25f22758a7ef2de83646c18bbca004f68c4d7c4b9dc0229cf9a454969d24f589c52d70777d5882e432f65", "0", "1d103f4e0303873b14e42d005b9388860f50dcaeea33f63ae0af980619178b2f1035e734491606c824849b6fcc76c85ba1cbb0dfd50d9d9a370b4f0c1ac3bc90abdde681c52b04232ec7df", .None}, + {.Sqrt, "78f75f8dd5b885055ae705402b8e6642b5b7138f1dee2cb1444bda53cc3e38f39bd9e45f815f78061b7bdd606bf377692b31c55709ea8f560a65de71e030f6d163e6b8b094ee1df7eebc03ae7107ee882a36d2868a422fc0c65f2ba8c88a1a1296535c3752d8193ac9d4c09bd816b7bfb18451a9488f8909cd95aa8cfee95de05b87ab68fd1bd27b2e3d66c2376d1cb6d141a3c0587d", "0", "aff9b9bee276e15dc28cbb401b0cba34879bf324f06567bd2ab60ec7edb1103ae740340f3a80c51a3359c913d120831b4c96a5ab413ee7ef5083e544bed0bd4caff7e54ee1decd33ade3e2", .None}, + {.Sqrt, "9948fc1d7480a16ecae542535dcf45d348303653998516b92715c061939c0958cb0c270b524dcae24af51aea63c132483dcca0644fa03d25accfdc581dfa0b29c486b73311411a793bdcc658fe2de0fff537b5f6afec0e03776a4632d6ee876b0a4a5a7fd26f449b64fe3a3272e817c0017daa6783880f640dc50d5d2c3f59acef3a9c8bd70e4444ff14455d50151feb04b7279cacf1", "0", "c617e75bd737016cf76888a3f654115d8b7026dbfe2abcb70746d608469e2b609389c0a1ca8db4676c29702344a74716fce9f4155c5559a4cdb0810da57cb64320711ab8862d422e7379a0", .None}, + {.Sqrt, "ca99bc83948bf7bb1f99c109d5d0122afa40fc5e247b2a48095ef08bf6e1501297cfb9ba973e4a2cc2e19fab4957f298a2c592e1459f9d3e92b3f6a1262357af72421e27c31bcd3eec945014c53526569b67c8e26f55a3aa95a9bbac87135d65e3a5de3cd57a43fafd88bd94694d527c9394ea8875f6031e1470a893b7acf90c4d6f9244b8ddf8b752a011359b9f83112b48156f6bd2", "0", "e3bd918ed9039c1cca05f0a48db0d20609b09a053d67538c2563291c895fe792faee3ce1b3aac486a35d76c4ec087295594a6b9860566b26a7c5f5cad7f72d839704f51ae24c98a9af46fd", .None}, + {.Sqrt, "e3b89f1c71d0bbae5d1cdaa0906a528ec6e63bf60dc71e5abae6f4d38b1a2f4a417dd474b67a9f4fe40a5b7c5abbc532f0aa22c9e1271999168c15165bd473fbb020dbc67ec88f22ba6a431bbba173ed52ec1449faf4d082378414d2a9e5b6a676d591ab82ced7eeb2b3799980b027c710ddd4df7d7ed4cdcf7b7f7190aae60cdfca065c615cd3ff973fd1f349e9d1cff8dd2369dd72", "0", "f1726a3600e0c31fe8c7b6466b400d37ead97d112421c358859294865832d48d8533a2d1ba492274e45735c81dfd33a9e8f9a2d51bba9a7afadc17f544f2af3c7e4dfc8a53f1d77025381d", .None}, + {.Sqrt, "bfe829299a9f4ce1081f5d7887d699b8886f50e48cf904cc7020c545028019b65fab3d18d38003e5549bf1574ad28dfa5b5e1df9c71bdfd86b42f31da63a6b47ca5e55f0f1c948c60afd0c0968111f43ba7f8bec3cdcf551229acd5b7d11306d852cb69ccfcc985dcdc1b809b69c6de2e857b1b79e2eefb5ad334ffe216fedf05f059c849e74472b20377bf1d0e4af141d2a0df28a0b", "0", "dda6135bcbefd20e2165034889b561efdba7e2bc5cc30851227d8f268c9e4d7a058bdbdef9b8987f0d9238ea57e1fb96ee07ab3c63826d6c697487bd8df84b30c1eafee63c3cddcd77517d", .None}, + {.Sqrt, "680b9ef3fb575d5fc86e0a5198315dd53640daa649de38d827b4fdd196216692ab757267a9593219f1b3dbc587eeb25e14d2302016d4446917e2f147114aede7b7a744093d37b04e5fa1dc948fcff38a47c5de8f0d61bcdadbe3390b5ba5d906e9f9c960cbd0bdc4e845f7e6c7673a978b8e54edff58e3c04e38cd7ecd774803f7c3a332170dd14d1908b67ed49da663ad4c00ebff16", "0", "a334487627ea624abffb651a51a912a6c63ac2302db37f9ef2e053f60bfaa6cb7267748270e4916260e7318e1852256550642816425abce0407109702fa6a9b4642c8024a14ce350fb890e", .None}, + {.Sqrt, "beebf941567d27c10dfc492594115cd15a250f66ffdb7bf710bef9dc1f0c6e1e15ba30781226c8457e40c867d25f52225ac418d7ff5c9520b8e173d6faa1ee28a572e0b5a21e27270f40930d594ef00052eadc297dff5954db07c401727a2ba0ec4564ca3a108e78d8f577369fcc2a69da28ec3c66e9423d75ddd45740f70b2b96eb3ba085f16f0f893a07c545359ad9afd862865ddd", "0", "dd1440aaf5403cc562becdd32eb20c5ac05be5e92c34faf6500d7aa817663c84abeecf9272ef7f355e432a6b003976c5c925d443ee5d0126bfb2fd206d2c191e902f8d338c9ae57456d831", .None}, + {.Sqrt, "d616f383ad5a535bd3bf55f467fd47ab8307e9fc518bd82fbbea882157ccd94b1705d4621af80b131e59d1e864d72f403fd4354442f58af1ecdc0620cab7e2d975435f5d5ef15e6c9db64cbd7971dc0a5c6c0a17fdc702569adfc02910b37477b74a5d85530f077a5ac721b1707645899afa70a6d4b7c88a37fb611586bc194534ce3c3c0991c5ba9b12386efe15165fc5dd15dce68d", "0", "ea1bdd413c5f1eded5d3bde25a8c0915ac3d6c0d234f5ce497f83a9e43727111350b14d2986c14d21800a6efa92267188e39b73cb8e1dd7b185d3f7fb5c4775da7608a507f50d0d0d13632", .None}, + {.Sqrt, "c34c312fd7e87b68e0e5a105cf97601872b36ce14c379bcd9f7b9b3e274ba97be588aeb98f3fd41dec1bac1c1992b41bec2fb7f26bb973af054629cb5deb74ddff21d74d5520051bc7644de431ca45da3b7ae304929b49e37f27bae281137cf7662a665f8387e851084b656c8616ed875b6922909ccb799278fa5164a0ab0487e59bd48c7b34c0be27c9e52ed83fabbda1d298eb70b2", "0", "df99291235b2c627b2d68a3a9d8767fcb87c31dee96fbc5a08737ac4867e119688238ac0f437ac99df0aa7dc313c7f6a055412ac931ae668809ac9190b03a468a741e26d8930c9117cda1a", .None}, + {.Sqrt, "b8552883e976498bffa62b6b69a5bfaf1ed9eca20e53f5795b7b66f22cb75d350d2666ef41eef3f6d0f757fd4eab1950419c60671eaaf66f7ec5fcc72e64a87dd0b108299b8033d10f3bda67e5a31f4de15edaa87bf945d70308b5fd2f9dafa7cdb7ab9fb01b2a9f85afeb315a4a2ba8a2038afd4898126a7a4e9673c25354fc3a59856db799f3e9e7d201e41d71c0af3750890b7119", "0", "d93b0c534e2399c762263a30a2f7e745f84c582086fb17a53a3c8b17a0b606810560f9dac881e616109ac8b60f008ec8a58d7c0aad0f82a1249a6c40fdb4bd7db00f2abac5f23394f315ab", .None}, + {.Sqrt, "4136c41b1f8b1fd7bec1ec53e2d4f20172ecdb1e41871b22c044716575a58326e06fe6b9ca58914ab92cdd7e3ea3b7e6eca9c7128f7b47d995463324b4d4517dff931e65f1559d011e43e566434b25ac3b4ac49c1f1cbc6293b98c27e473233dcb2363052f979d1c48b060bc4a28c43e075de1806e77ec1fe2b1245e49db21ca1d5b6a7913058a65bc19635fa50687a8721d43f12ab5", "0", "81354e64c83e2818072190722be91ae203471a8e3671345a469465420acd9713fa33753fe8e0066462f4be9f7db2d36dd51b357cb2555e9d8564f1abbe27a111aa7df34f8c01ff7cb1ff18", .None}, + {.Sqrt, "292e09aa83f8fb4e028bb28800d45df43c63856eca6ea88f8ceb2f4b290789c25b7eb1dd55b83ecc276f13f3b599fd899874f0b46cfc96d649a33084ea2891c1a5d6ff1c763a609890f972a73dbaad2b408845e4a10b5184b6c617cda5593e147e2085cfdb9f2b437621d1c55cc3624aa4ad739e2b3ed967eee3aa2e5d80f68e67be2c776f20e41d3d0cbfaa5ec8225b37ada358fb76", "0", "66aca72efa8f048571d20b6ab4338682e70725da29fbbf9ff02cc895c4b8b503ddbba30be6b330567b3ca45e096616f0c4d74e74aa336b1f8f9638de058f9e97dd4282fc203fe44134ed78", .None}, + {.Sqrt, "cb042997e1d1ed45af2f7b5151bf7de701d3634585696a7df7a883fd9f24edfcd95e70a33d0a510a4e9c85e69bea3656895f5b3d45ef9f400a6a382d5edf0375551402084e94f747c6f98aa150123135272bace032bccbeb01c6e93cd36bf5d210ea45d74f5696d6ebe30f2116a891e7b2ee88a7c456e8c27fe594b8fc1360e88f78b3c8c11cb9ea18c5ce1f84d7cfc52dcde58aea64", "0", "e3f95a9f46fd6f397011ad25730fe839846f768ed31fac0b06c2bc15b421069547ef83dba6dca9d46332bb1509091241349638657013d0a2389c07dc79e008de615ab7e2b8cfce0135cdd9", .None}, + {.Sqrt, "2cea1fa57cb49200a0329dd3dc16003f6fdb9329ba08e4579ca7c7a135d9a0e708090b9f5db857d3dc0032b229c33d08974c6b12a9b858a91dc9319e8e6a798a78012a9768f93d5a10131e5c0185a2e1f782b0f5d16a25b451375b1bc212d4f0d38fe0c6df9b54a65dc39a7e4a498d0cde8d54e058be981d7daa74bab4b01aba2c4577372f94f7c8fda4f2589f496ce93ed78a112282", "0", "6b3ab3a95f8bf05965dd3e75c084dcbc4804c6e06d34ec637b550663dad769daa301fc4881959b18aa478d719fdddf649ffcd3495346ea64b5c3feda0173ecb7980a50cd01adb6fab41bf3", .None}, + {.Sqrt, "d2be3ef72fdd26d8b81bf32c2060b2a10078c8e5249510bd282ab3d1b8e65f40fc2cc1192a5c918028eacd16f43cbc71ecdc7ce0ab705fe4764b74d98d67ee141231abc263418c37cd3da05726e9a80d651ed52c1dd9ded358bfaf798f3cf4faacf2ab3130af54dd66f37ca8c9432c86d958ffc0c19c69c717bd14272f772858c556d28510057e7e216b65a385acae8d3576a79e9a46", "0", "e8459cb5b3da9e40a2b3fe0abb0b87e54b17f74ae6a691c592dca6cd17cd27841cde1cfe4bb1e9c5ab344929c1b99c66a54dae519dd0a5b96385ae29f713dea572193e58db0db83d5cbf25", .None}, + {.Sqrt, "141f9d6ccfcabe3dd9ff33ef6f322240a8e40ce2ee2940dfe7cc858ac4773fa834066d11c7a02697b6978f42b1870e72165298dc08f3dbbb65ab1ec568c834e6218d46702452d957d1d4612edae4862487e1e141606a39ce3979135727c8f660c34fcd36eb0a81658e209d8fe4b84aa512d0b64bae9da1bec8717f578a8d61855fd1322c8dadb8ec43863c653153691aed75e4a6e0d9", "0", "47c6561bf0de6759e3192885668a873e0a2db94fbffd77c20592a9650e42eea0ebd6c351c3a5d77185aac5b30cb0c449458fd55f0bf3e667a771e28a37f640fc9000b2c872e65064d2124b", .None}, + {.Sqrt, "200f137c56911a0ea8f1daf813ae02d4875c2261649b788a10a2dc43851c79b2a282e843f59973a26a19031c436cdeaa14dc2b1c5a7ef01a163faf03d8d623100e23ba2b22a67e2cfd823c78db0b21373f65899abf60aef9e1b15db488815dfa8c50ffe40ccb95d24e76a776912d0749f36384531844484fe5d5ba535ced9fb4190e262c1080cd28c16b569a3de62b111da0871db596", "0", "5a97c93ac898524e07bf5609bd60d3154c0edddbadbfa86ac0456a95d80b9a26ea3798a55f9a7ee7da8d1ea88a6f73468a719d90985d1a6136f86842df81c93ca1d4b6f53279393521839a", .None}, + {.Sqrt, "32be06e8cba7f67df093ec3162c0aaef4859bb6ab5ddf47bbd42718ecab364c5276dc24008eaa036363e70886ca8ded6a120f663a9a745c7ff656053bc04806455b13d19db72b57387a43a0e906beb35c1cf2ee2348f450bc4b935f97c0ffeccade12f12c9b249e3898dbddaa9dfa7311601873946ff58dc28529e579e76dc17d2713758e7082ecea2f5ef75b4815d4b94c381a46db7", "0", "71f94aedd1a9a144494df92d591bf35fc7c84db5239899185a1f362449574acdc8de6ebc888ad906290c9c8f0a90376f6c728a5b85d83486baeec85eb833f6d45860b0763027f5f0ad8a5a", .None}, + {.Sqrt, "d9b3766faea3d60b99bb16bf768c61a9800cf5efa085e98a8dc702fee1209fc3b968cdaf5a7e2632bb369f92d55f956a9240c940653e246e39e6ec1d3e12f0cac4fbf6559e1457670223103c5532fef90db664995c37456a0921cb9655e0932eb0a708cad4199844ef4498cd7140f6d330a5fb0e1ee220b729cf72a9b8e32d5530d342e23acfd204720df1c549a74fcfe5205a796a57", "0", "ec133b1d3581da74269ce8b0bddb2cd0bdaa088c938f5c9ae09761a1431829bda955f1af9ad4f610deb9276c56da68ca6388db6379158c8f1c3d040f1407bff8325a9591af2c8cc9afd52e", .None}, + {.Sqrt, "83a4c661bd761b54661ac8c282c4b284a2a98958644644bcde585b1c66bae906af19268dafd0b0ce77fab9ab149c0c69f36bf28b785654a75523bd8bc7398bc3524feb7b5e82a5e4f35c3265972db7bf3aa686bf59dec2ce0e9925a54ead22232b572ed3cd969b55edf5dd623447292b7c246e3f252cc44b215bb83f76d24565d8995ef45d815819c86438c27d3f9c9677c3371dc75a", "0", "b793e4ae628ff75ac22f1721cecc700eaa15e305e1d3ffca784df2fe7f136700d2693b979bcdceb1b5ff46655bc4aff833a99456e7bb15657269a5a790a4b4b8b4f1a9f876668adecb7e78", .None}, + {.Sqrt, "1947f1ad27d7c6d854e22181b7750ca60891000e5bfaa566605268f0bbe63d4ef576e68dec4017c354f4fdd85d26f5f330bf9c3d08023792f2f34312a8be906431f4fe4108a19e1f39b8276fb70dde20fe1b89ab59f0a2c57ecb95c08a389c69f5d9ba2eaad2f6e0267c9fc265218bbbd8fbf02c4a02e3eb8c78e726a3ae4f514bb457a0fff1914fa3e388606739100e90d370c2bedd", "0", "5072c9ede77d0e316925e71c3a4700cc59cfdd64e35213f761d06bf1188efcf41ec2b6b6515d6e57efb91bdaa17cb81468e34e64d81bd57a779c290d4363e05abd3c3998b8b5f3adf61739", .None}, + {.Sqrt, "5b94306e1f3db7800ad3cfdb340e7b3a88ad26941540de141188fd3cea5e3356eda1b10ebbcc702fa90412af022a70588d1bb3fe227d9948f0608e1edd446f097f312400f38481c6cb67b8115fb79e5367a535970e0f423122cf889ec770fb82dee8338490c67feed2c9d2d6ffb1ea13f638f74f53a155c146e7760ee067ac588ce655202b9494cc90db6e5d76cdba7463777aaed933", "0", "991d6da2624cc4eed7eec1ec26fdea29f56366af1f43331f64d053941d0b5cc224b42981ccc17de5b6c58e9f6a64dfab8829979037a6c28f851561c26080f63232a6d75439cbae50eab93f", .None}, + {.Sqrt, "d4fad1b8e7f4d3d468eead3eabc0f9a93848c9d645a69347d22180e37bd059759ca7df506c9e5fcc10a6e36053f5a4d6f89558c263875b51d7a9ff777fe3dccd755fd80091e28deb20b5ec5e7e1048ff699aef763fa78cd42645137ad7091be4cae252f6e7d188b6c4c2ed812cacee714bcbeef86a246623ba0c9f93d0caf72b778b3ad32f3c9aab0ccd480b39af2ddf10fd222a7fa9", "0", "e9804fe1bec87b593894541612cd13d9ea75b22ce287a7eb856d2b4de476fe70eb681bb91578698d8c1bda644ce1059e7c01e7e1c751a9b8b92c7fcce40619e0a409116b0a9db243108c54", .None}, + {.Sqrt, "1078cc99cf195615a0098d8a1c4466fb8a3de7cd8bdf60592c312299417bb00f092977107ae9abcbdfcc7658cb309fee24096647f02541c0abc73c264fc7493412cc08cf9e2c7a86b5a86ebaf1eb0aebeb42a919c5ebebf1d3bfa6a17948de5af1c031836bbfb87efbf5bd264ef187907d406453c7e7635b03ed85d1a7b92728573e251630717fe1c52e00e1661909c93372a2c78530", "0", "40efd7ca5abcca6e6f6e7c75621ba41c6d44d32e7beb54212d667f1a6eeeb643dd4c720e78d87667ca96f92b72bbf07ea3e1c64131ce201bf50a3e4c8cd9c084f56a29d7a14c3cd2fa60f6", .None}, + {.Sqrt, "a6e9de94d12ffff4c7b96987e038cfb653871ee2fb0774901e5e203c0f4d09606f11fc8fcad26e28586dd4720e9c6a90f2426837336b8cc32b7b174524bec012bb7dabc89ef45594b84a402b4de0980763e048b2d526afd86b3505a72c21d31ed61d94aa2416f0496317412dfe0a390dd6d8604212f508cdb0b80602cca554392953e63300cfd8918854a5a862844a2f3ea25cf06770", "0", "ceb648911f3caa2a708bce269bcb3515ea75be583d477078ac61fb3e942aba744841c024e4f461846bf3b4400ee89eaf064ccfcb3546f60c493462d213dda7875b818c6c8382248dd65652", .None}, + {.Sqrt, "80a9926ba1cb692592217df87c22b19120d42863fc0e033af6b5c8881013a8b28a15824db1f75d2f362368de7bbfecb09162bab1e3e834be0a099890957ffda84613dffebd9f05441eee43256a4b9ae9acf814bcfe628a148d7eaf4b519a4b6bb8fa17b7fce214b5609eb1c7e4bc1ed63ee1caf93cac388a17ff76890da10c29a0beab2cf7a9c4764058003d7e5bef05b4aafb6f1089", "0", "b57cb3656016351f2eb51468b65a557756dd25338ba0eccbc8d95f434e73a8a0a9e14222e3e7165a45406da9f693260c8e6c54c62e49d3f31674babac342a8f5a5b0a7cedb25bd262f0bc0", .None}, + {.Sqrt, "1dac0a4ed6e93c3d2825c86c71339a98f1239190f572ebc461c3baeac651de5eae0f47492d66cda461f8040ef55ce183477260abac29b511768f315661550480e59ccf13bf949c8ce06fead4ae2bd5b38f24966f6120fbbe7a6b985bcddd0ac59e0bd3f462053b81a66dacc7ae1c2501d6e34b20770c14b22dae6b449b5bb0779eb656f57882f2a054f0fa0c6ccef33208b3968b2f55", "0", "5727bf7716b29cc3535846a17f64addf204387565887f44bc9da51e3d1e4245664ee00522ebae52b6595d95d5b9a951bf7b3c9575e4e85bb2c09df6c9066531c5c483ddb44cf1b6a6c494d", .None}, + {.Sqrt, "3e70371db7dcae99de7a0fd53838d711d8381153396c86da6d91999e2abf41e3344b2cdd9ce9043c6375077de705440cc0037a97c3e17816c866b05d75513e259c0a13e49287a3922f6966f3da94bfd4644ddf1cca8ed78b84f85d2209da0106b393df923e79527c89f93cf4550bbca67eb20839318cdd43dc2e7fd4a848427c8e914426f6f65c698b776fbba6f25d10734bfa5b6ecc", "0", "7e6dbf0dae5a33b2de95f59a9260ff5d63c080a64611f6cc4cad7ee583b4dd502d694c946476f17377387d3a9273e2a16f18db37ade3b608150fb357f1d0a1bd45e4dc302db5a28672ad37", .None}, + {.Sqrt, "31b4801768119867e07778a719ca7453487f5ac6c2dd63843302e6426dd8cb92810d651a945e570b3feab31c83ef497073dcd8332af60b0fbfabd65ec725227a28d707850ff0c276e6356e8d871d1e6d92aae6d3d14fd668d8826c55890a40e7a7c10ce490dd2339797b8cdb913b8b57453ae717c16469168a4ca08c12685fea85f584ee3df204adf1315194271c6b3abbe27e228054", "0", "70cd8ca1011865927271334593b4a962bec17849fbfcafa20c8410163612a146f56d61391959558af02dfd1cc4aef8870afd1dd63fa74c42c9728f55b2c7d726a3ba9ed25a54e10bce23ed", .None}, + {.Sqrt, "da623335d8db2a7dbfb0bc6ae96e7467e72c9c556e6438cd96a54b68f804765bbe789629f129ebe951c6d86a625431a30eb8c77612389a8e7c6f0a6dc1b454dfb113d26b403b646be0ee26dd95e73ded4e4f4320071d2a59428876e9086978bd96a3df4dd2fc3a9aa9802527bf961d500f7d0b5ba1897ccbea2afcfb9c190404545ac71a3b1ffad75929bddf27d8d896f4cb4b702f7e", "0", "ec71e6417ff6799aba48b158c63ef772a14d11fbfa5c2149ecc2e219bf87fbb3fa27eadf48fd3d30fb44fe3a0be8db2352380cd3335b35705c875ad62f505b3f035c1682716480879871c9", .None}, + {.Sqrt, "a65cc56bc1041a35516d4a15e52c5634af2424346fad82f167293cec0ba0340fcc143d9b54a8b1d86c1278bc6220404764c48f044d1c45851e8c94d8d7c5611518bda08ac28150ad4eb5eafbe1758538f3d9f4bbba94f180b6dbcf078b3da13d3abf6c942d40248ce6d5802abda98d71ea9e5d32b593b56c6e6b69cf0ef01a5b02d25dff0e7f7adb47ebb428b7ab3a9af297cbce4202", "0", "ce5ed72ae51322ea9adc758dff0acf9aa1928935f5dd424cbe92f9575373ccd42b1331f40443fb24460962ee26115f138c761e1f9ceee2fcf11bd95c8112e244ec0a951cd5e5ba34f73c68", .None}, + {.Sqrt, "dbd7e8b768401744414eef186b9db2c3bd63c52a7e0de9a77904db6107b587367d4835606bf1273ba09264f8bb6a55db29371696d9480edea159d57f7ca3aed9eee6b4cd3191b1a84a785b08d94f22fef59eb53cf054aee37c1724ab3d5fe2d525ea075756a55ee3b65596cb39dd666538b3fab5974f6bc0fbd911f7cabc6d749e207a49641f62a15550ef77ed726eba3dcf1e0fda1a", "0", "ed3bdee690af5de31ebb1571548623171bf57cc0adfe82146624996fa5bf477d8c08e5476554903439b37e90f41045265dda2f741746c1c36b00f365978cb5c59c3a1d99f9a803ef751bcc", .None}, + {.Sqrt, "bcfe7aa47d73a7960cf0809368587406ef51e27a31b74aa23c63eb07bbc70ddf17495e9606b73eefaeaa066db3ce49058f4c576a7b45816f0e0fe16e018a68d02d3ce5b806f766475853784373e9bba3e3d1dbc9cfaa0294d31f58cae9589e6cb85bd7d75cedaf9c523c86cc61b22c884fd22931d91fe37034a1f4e30629dc39597d671d70ab37e17fd37e26ea5d490ae8a6829513bb", "0", "dbf5ce19ec12be0bc9bd334086d6f7bb50235da6d69a956f178536b90f589859c6315e97dbca50db883badd164d1cdbe1eff025186c766558f5ff0741669c690b77f68619c65a58f2e1bb0", .None}, + {.Sqrt, "3b3f60bd69312dfa72f044549db4fac9b8537e9525069a558580496b67d6dc0498d684dfaea5003f5da8024c55169e64d774bf41b1014e0aa11e675b3f65b802a39daff3ef61506616d18ff3b7fbd5e2b9e7fb645b89a9680b4103e954fa634be9d8d7e8b8c95d0cc05d76270a6652ca3bbef8d9e7fc5e32a8808176cc323546822f36c9eb77f43fc8074b5b44deae2bf63d03e034d", "0", "1ec9fa693500d05f4849214fede26b97fe7b4eec5d481f5c7fa8ae7528c6b3b6b949a50f08174b9860e7a03930b34bbd30e5aacbdb6224b4b46b3bd46625748cb8dde284b463f1b33ecaa4", .None}, + {.Sqrt, "1a7564e991afdd6fde8fb0ef0ec2b862b39b5383d0c89f8f6de14ae1df92406e81cbd9e98f4248fd6a775a520a1b06ea3db87731b98ff91960a06622799e88d9599e9077294747de28f440f8682d6d14d37169a60aea437848b5edbabed4d979d4cc0b3cc54905366bcfe0ff75867c19a16ee92b6a89a00deabe1f3b257bcf960f34b110efd33a0121f1ac2e1f0cb75d4c1be8e1e3eb", "0", "524cf64873194c080f1a1dc0d23a5ad5a3557ac5aeece53290e3149eb40d8a4c28c1d1fa1317bfed54c742845d8f03f7d1f1912f485290a616b5e5c01e92aeec401c037b58abf6c8fbbbb5", .None}, + {.Sqrt, "eb01cef6d95b46404c4a0cff1091b1aeff0e7325e1ed991ddff5c62dc957557a26d3b4ebe30662fffa5433d641b2cacc9e81c2435ce1cff40d7aec4aa5fc8c0ac6e727b704c33e7986723913045e3e8cbe03cbcfe7b38e82697a0a4a13a9b04ffa28610e19e399589265e968ed9724bdb31981440ff74fbe053bb68daeeb020dc9f0974ca5c5e615fc0c20050d72741341b0425bb623", "0", "f5476f4c3cf5afc10bb49db59ff529c22d2be1afed8ab7e606c249649e6a2be42b314e53706edaf2213de860546a05aeddd922d2d5c8aeaa58eda216144ded34c5e5158427a2deaa186305", .None}, + {.Sqrt, "fb3dba565d00c23ac032aab0c542ae94c9c0bacbf1baa76f0c0093e521b5775e47cc1794262eabfeacfd1dbf3c8f5d30f0f804abd7dd0a17831793d47cbb4dde032b0e305d2c44b211381b7fd0db709c0aecd741aeb1f7b9db889443cd7bb4b932878c482df3e4ce437d065081647fc3189da80f41d001a96b8fbdd6eedc8129354973ad8fb33c50c71f07040eb398e744187dc38367", "0", "fd9c01a7220c6917d8553460f83d804c5abb0b9048f29667e72b6020bc327d725d83e24cb61cc6495c0bb243c541df7c48e3e9ac80347e59a6d13eb12bf89b64f2ab52dc7431c79ce4ba07", .None}, + {.Sqrt, "3c556871bfcde51b8b7dee30e9c801f1ae4138c8f20352dd6d83bcb75cf9863c2abb18713245b8706376aef0a711077752000a1f17428007f571ce65823a47c0e6463ef7393d7627f91dff3dec14b68e6cb30726e8543c496e241d5fdee2a89ba5c1df84d9d2cd734c605e95ce3ceea2088cd46be6a2016e0bdcc9b50aff2eff209098f9ca8e833a37f649df4790635ea802343cb480", "0", "7c4790f7c25b463d305b1d15e63957affe50c30544f1ff3fa2fd0bff5496a804759235baeeb502f6531d13a39133eddf1b3fb7cf70a24e66bf7b64a1c068ec5c35b9b65ff0c5593ca1ea32", .None}, + {.Sqrt, "9a68805ed30270da54ef718a13c7e858269f604a977659655bfa7659c2b8ef89cc7f304a333dda6a9e9ac39961bf200fdebbbbbfee03af9dd189180202bfd8c4386fbd62397f65c37379c2bc2d2f7e9bf718e8adf913bea5dac51aa4e24d3c3e9bbbc7a34a788d7caad0223a5c7df3d89d09b810b7820a874b39da9f0e297fdf39c7e6fd9952897bd4c5dbfe515e13b168353075d966", "0", "c6d158add6e9bb188cdd25a3955149d941dab250a3f5ac541b8c2dc1b02c4d8f89f2370a3cd0c9b045736d24bb7804b609e539dfe249fdce045acb94f94ee151a57d13ffd087e2538655bc", .None}, + {.Sqrt, "ee77972fa1a6f7eba7305c002551155481dd0eb91614a2c0a222e55bb7c3ec7ec85d1b5347d52be89526640ec27c2c94cf744022f85595d96dec30a88d5f4014bddd5a9dde4e3c3e75d565057b3b0878420f7b5fa02079e0a3199438c0c20e5b0081ee3a03a6af6b260c42f0a193b8eef0de294c3077276650daf9023c49e5eb4cbff3d5c47601691626678d11533b35dd7c3a804be0", "0", "f713fec4d4ee79993446c2a73d7f315deffe5c377c66c65a9beaa468964bdff505bbc130945c3553efe1d77c8d8eaf073cd942b738ce69e4176ba4853ec47440d95034cdf843e460943e1d", .None}, + {.Sqrt, "8b487adcc28040b95d3404e37217a8feaf6dc47bb54f931a9f854174745e190174f96c59cb278c4e33e95084c414582f91450e87e7a143dc0361a8fe4cd556f15efcc429eec67920c5c1278aad4b23dc0cf6e6d544bbb1a505cee68facb87ba7bf1d1fc6d3cfdd88137a3f03073a535762c78e45d45e85442ba848a59f3a7a14cd9c073aaa073fb2466b75a5327a4334d9fea79c5648", "0", "bcd448bc0f39ad43cd7f7a0fc9e0ab253288c9fef50da5bda8047079b19cbf87509647a8e33e4f7426faba0ccff41bcb9f0df911784c9e800111e23a38b4bb955de7feea3c3ce7682555cd", .None}, + {.Sqrt, "24da684fd76c0356a57c3400540f798040e3fbd8da762eb0d5499e7c720df51ef72c18e8ffdd10df408a9a86d9647eb17fb7ba0b0b0d74c64bf25138f19875f1110f242927f78b2eabee3aaf359ed91d5008b7e6ad4817c2b0a679bee90d333c0033014cbdcb880a91c7522b897ffc8dba3072614e5e6a50052df4949504ef26ea9fdabe3f1b37428b5345d82d370d7c2836dbb230e4", "0", "6121813919b1decfd28fdf1495aec0ab00767e3b53000e838e05b0ba9db0cd082e1d931f665c319a2e8c902919ad4f48916bb3b023287043f90e1acbc2e2677cc9e0758e6134b656b29ec6", .None}, + {.Sqrt, "2eeec571154e728cf8a1daaf9aef56d6e10739b054a7c2b816955de53a2549fe914202e62e999be01e42d00a569d828fee31b85d383e34ae3cb6bb20e10356b60476092a30d2c391e2982808c0509b57b5b86393db33ed7c31d8e5981ea0210132ecfeac988ee585b8ffb6e710e3e52be92fd3f025f608b6ea38eec621f51a63ae2d42b4ed3c364b73bbe10c7cbf25733ad7ec472028", "0", "6d9ca644238db6b6b816caca665377f75fc4b812509be9e962d97743f1b786b570e0ef8b1363c2ac13f43eb26d4c4ddcbe2cfd3d47ab071dd1773045b3556b53478be9b0c593914d7c4692", .None}, + {.Sqrt, "fe1e95eedb75afb13c169fbd0b266e1f8d06140a72812f0c63a1b291bbc4a8de58a9869986df7e2e093570dfc2f32e5bc0173421834a264837e5a60cfc6e1480341e25a84039f19a29fce0cdfbd38ee031bfdae9983288f0aecf7221530d519ae1e708ddab020e166caf15da04d5ed399a41634807ccc3e1a3505b5a6f110a7c4a7859ae85dbb953650cb6a52a48b806db2709ecf403", "0", "ff0ed962909b6b36b58ae6dc3e3785d01f0f402e15a4c7e8d69e4411159db6f4c4af4c75692b2ec3f39395f00126623eb17f490c719e335ee078515d44e839369be698a798c4ad35cd220a", .None}, + {.Sqrt, "737878c84f679335c10307b495e9b0d037360e36932e5f11179a27d62b90ec1297abaaf0bb641a8538384df12b2b35b34f770528c3819c82dd8995294bb9d864f5b933e3cbf6520a714f9feb5d47b774adf76d758055a5a58e0d8e5fef16674ff8f6598c2beb7249176e35b247489efc31331f48799e89a7c46e0684fccece1597d06361e448b1c7c71c049d227309c38c26442c5de", "0", "2afb9f2db1ed09c837c6343a264ecb8d06b43f1f46b92abdb7d4baa9683a4794b278079d7d6d728e4644cde29895b70278edb8ce1d8695f2d6c6e50ae5d7694e84776134502f07b4bc3816", .None}, + {.Sqrt, "7dc0af4e4bb849928bcd264fb95d758d06f1d72f6bac636e80b395ff66f592f65f42d14538a05835229f9554b8aedf017407cadd4c97ac9dd749b3551b3036204677980eabc5d607a43e1a3474504081ff0aa8fe50896a542789e4296d55749c49f94c6d86b8811e5cdf7a9d107e71e580926ddd3bafebf95bb84ae9aa34fbc5c5a4cd8f38156cafb1c39dff434b341ac078dfee38f4", "0", "b36c56da075c2608960f9ac7aeaf39051dfb6e715d784984e173139f7bb4537ed71b39518cecae816f55cf92eddc52514600429a24045cae17c06e42621c64fe92a932fc28c37b20bbfed3", .None}, + {.Sqrt, "87a3781b3dda274edcd88ae97625cafa3aade7e9bd726c4bfffe03361fe462536dd0f33798ac4685e0137e1412434e8e4417249ef4db38eb7294d50a1ef3567f61fd0d727dd210d35255831ab9b3d2995c6ed682cd9c71e696125afbdbd083ea7ffadf98d8c4f7bb00da7f41bec736e57afc28f31ce3b572529d659bc626a2299f4b59b956c02afae0dde6ea3fba4b30e2d7c7463087", "0", "ba57a3db27ecdedddf79a5d2bb7a3f3e1fec10a01b0b543ccd6061ea8f0c75640127b6814b6008cce5a6c4f23dcadf44203d35563daa1434a799e8be70e0c9bdb3f8e9dacdddd71d38f383", .None}, + {.Sqrt, "78a2736ff9e88c6dcd04a4c089526b809848b9834af52f8e5b81ba56b2f41a8688bd3a05c98b41a3b3f09c39bc5d51d78dae40888ada4a6d60236fc83a390dbebffd71eee3174f3b8c9606119df91c8aaca52b0f9a8b13923c6e916f2935222e0ba519886d85bd55bee7c5e9255fb875d29236fe5db1cbd905d90b524402dd5c364d26375ab050b720b53b1ffbb81815e95082c0b0ae", "0", "afbbe9b18a634390a2da94f1cdd35a08a048fe57cc5f27e60f15e8866f95520d00ec09899c2da09cd5beb5a9832e4fedfc6daa37fea70bbea573e37a51b9256f30b3302ce600055a7dbccb", .None}, + {.Sqrt, "7f96fe10742046aa5c6b6935ccbdfe56444c7cfb0cda6d13c708ae732beb9c158025193ca69b9aefd1289edb37269fe4d31d8c17bf5790655214bc78946052ca8a35365d5c3f0675347e6de580886bbd99daecfc07487bce1c5aefc22f6e652ccf21b2317bb549b8ff9e40100ddc5640e3d7cd06a070b77ec9e7938e28d663ed9f7630c76df1b39cd0a99128a0e2c385f50b7179cc7", "0", "2d2ea8e344bc6879dea1aa9b8992cc1884b75f0489227c6ad77714eb8dcaa38fc67a742c200438a19e1a5aa59add9fd31ac1e7beb075b726798c0510723809df319718df995eb0c2438333", .None}, + {.Sqrt, "c90e68017a5efb16f5a0c1cef242e108378fede724ab91e63e8ad79d8c2c03eb15328879875159843bcb93f05a0dea1f7f99e2434759d93a56d8e92ae2c10b933cb17370c967181789bb8f2fbaaeb5d89b0e87c8e95ae2f416436a487a72d3fbf0a35c0bce02bdb7838e1be90b2a951a7f076cc6c47f435bc4e6aa6be21f1a5da13818e4c1c94944d08d3e04ddb7cd8c85b7a58a8da1", "0", "e2def3729a1bb70665bacbc8c2f6ce15930f2e661b77745d5b6310ff18ef906f21cae85bae57650f3d1117b13e28291119c0830c5b39ed0ba30bed8cfd5f660d78f848f6335cf7cfe212de", .None}, + {.Sqrt, "2adb17e6e29228ce1068d8ad4e53ac23f4efddffb7d7d7fac85c471cb328916317ff2ad126d7cfdb3ccb950f331db5c92a3c21bbee8d13c5e0a018b6d2e7f9cee4f96d8ca8edd4d16fec385406251683228ec66ad8e3af342a77e464b75dc1759739cc07f2788b631130007f3126c1b928c3d19f4ab9e922a903410e512e2d957b4e8918d5e9da229c8daded1c2d1c84259fe8afc68e", "0", "68be3468ace10bf61bdbd522c60894c60a720ff1ee102b00333cabbae844c0d92987a80af1676f487c9efeb78fc34bd25da4e3a33352880ea5f1286ababaecad1b9b1e9229937ef6c90a7a", .None}, + {.Sqrt, "ef51f4af8b6e55e857869b17df3e96bc1166281ed6b3ce00f91b134b8958e8331ce57e662a6258d4f7740d40ef316e0e1e0f8afc76b2521c7b873b4208edbe448481e0603bcf5c66e55a875a2a5fe99bb59d0d7c78b498dc911df501501e8c5b16df5b4640471eedd1516236cfe2dfe230dd9dd945670431c032542393fd209bcb2f4f57bda69fe75a8c67363c15059d908a6a5c2245", "0", "f78504f5521a23ce496e285c80094215df312a5446b3e8c001c6bdd655f5e4ce873bc385e4a8f1eda158e09d71c7f18a8d36e0b741a4fe59cf7c49a47db19b40beef107792fb8201e82fdc", .None}, + {.Sqrt, "49ccfb703421552d607db6c6061539957079309d59b71cd2055663089ff3365fe5b7287128e6d3e1d6378338e9837b8f7a5537a4af2a22f8bd27a722535e6185c040340c5a184c9ad79f7f04c9407663116c0f36727ff5c077c583d23ffbff4df968c9a46f6923cd96239a4912ec5e0ff5f3350a373aa478b78cf24f789808e91b904bf6986638b4fbe4ee9bc0797f297670a8185913", "0", "8973a58e0e6c547d07b6fcdbdfa401b9531c5795273d09ccc29f9e970c5fa60f7e609f9a0eb9b99b9e07f790e2cb28de6bba96fcbd999537ddc2835078066f29ab9416e3602a1027f07391", .None}, + {.Sqrt, "cf8876980bd21e6873a8bd1b68eee0013fe297ff9132d2e51ca5b14b60e1b908dba311738a5d3a186f5e651c5ce2a24197830c9c7c686285b8b650afba34abb8086887946cc7cdbbba1023c3ebe438406332927393d8ad5e8821a9cdc992cdb9168e80c8b8c590a6d6a6fe88e026496d3987a2fdc844dbcc8097f15b3f3bef7b4471939d7d36a361a5b5947e4406de1e4edeb7919b92", "0", "e67f01fe5e49ca69a174bfb6206448f41bff99a8542b2a2d535332479efe25230f57151f9870696747eb238c9b949cf3f92b108fd16061056dec27bd0102180100b0aa4b437d48953d1ec3", .None}, + {.Sqrt, "95ac807764faea0cd659f40ad28999554fd42e5162a56e66d28673a7ec6b6722f43e8d8dbbad48b756bb12a12b535c11c4941020ca539dc16558a7f3fe6523996e4ca8c3b809fa727d262436665097eaf555a7add2c756d269bb96f862f1d2f252542eaf09888b730f7bb252b1f1237b365048f661685d535470e51fe7ec11cbd0343094087838d24aa1341460c03e8d486ed99f310f", "0", "c3befabe83ab33d72b3b05f1960070f6a79c382c7276bdec57ff7ce07f12e04ac5f0f377fbad9b168e35bd126898b0513edb25ad7290b07300a3b6af4ce950b926303f3b7e69fe8c72dcdd", .None}, + {.Sqrt, "7908d87667ca33aceb5e3fc1ee581ccac093906a5ee9a759f49abbee6e6025a6887de6c4cf165a58feb68097de6392d209087ee15219e40bdb156289107f91cbbda832ee5e079ccb7d81beb642f75323c9b45b10b3017f869274ad3a66a529b7def842f74c2620cd755f9962b052aaf04ffeb31c81e322b6b21ec363d141246f9737b018f5fed55d8007d5451a39b7c2dde8fc6afe41", "0", "b0066ec3a7c6fd8c5cefd6ca127ae107cbdffd7bad17c093d1a656abd0cdc83596226509d045c0448c88f4bf1888b2a2a80f0ad633d2e3f5a9b17458f53a0ad9a95ccf70ae288dd0bb14cd", .None}, + {.Sqrt, "15e8b8f6d6efbe453516896843f47a617d2ec760ace891c60a81066d457c146bded894a5bf8a0b1a6d7711833d5e88f7fc151521df5df939182ea85c5b9b5a3c8f0346868ee8abbc340fdf9c584f97f9f01ca66b0b4ff5356eff8121d3b502edd227d94d79c636375f56b1f8321be84c0bdf87717a5294343254d85a61c3384d293b92bdcbe137ff4809524db0e1a13f16aec443ef6e", "0", "4ae4331b4575dcf73908cb3a5ceb745fb7c4550bf3f27782443bacce8c313edd7d49fdbeacc83b3995a9face8c07dac99c55a083d64599595435d0cc3f61bcdbb94a6875c0beb6472b6700", .None}, + {.Sqrt, "3de70294125fd84f3b4dfdf217f7e720b5fbe800a854d726141988ce2995706201b521a8a0006ec3d4648495de102c45752c877d72925db066e6e6e985b23795b3aff52582aed4e5c52b66734343ac16057d775a3c03b432b2ae57975e6bb1256b0570b2bed271371ecf7bac4c81261d360350ada1e849e0483bdf26087f75aff97c170a8f7172f1313a08c4aa60a369f10f11b0d74d", "0", "7de289554de956891478499c5a43e1ba24c26efb782056010ac11389c8046f853674fef95c2f2a75e49142ebdd349807a2b8a8fa6612385f6f77d4f5b57557af264b1a0928e5a53864a080", .None}, + {.Sqrt, "880aaaef1bd4e3114e1f2fb8acd86f7ac5e4d3ec4ae8f54988771a0f2b74f93ea05ba80480a6ce64aa09bd67cdcb5d9e8decf558bab4321dd2f08535a4a3bb65bd877a2951bae34243918d8684256d07073cf30c4c86c914d3567cd783a43bd7a345e0d3b73813e4eb0a71d91d64255496b44208475fb3bdce56caf24c3bfeb75d00ff6de0232b0600e95be4a695fa610f348d6e91a", "0", "2ea79e6c289816276d74999c692da7a6e3b33b2d5db13b9fa39342420bd3eaabd0153563e48e14255e9bd26936a8515ea6d26a6d757e067533ec1c3c869ce18143b2de5b562956dcffe9cf", .None}, + {.Sqrt, "91649de2ab0f5eb5dafdaeb95e23811af1d5a674eb15f1c591266217e4908d94264847639f8e9e3d1a755ddc0ddfe1bfc022866fc296256d221afa1978831256ef2d926a6635591845f26d4f776c424e9255df8c967817886a330e92e5fbb8ea0714e2316ec58fb225aa22af3f3490a6752841a25dd87c861ff082e84aa9907f164c3de1628fa55f84d6186cb987833fe9ef3360eb36", "0", "c0ed2c1aa6be4ed5739b41a209fad9881ab6d7d7fe19aeb65b6caa2241ce21e079093632d530ac49b3e48e14d20ce9d1b6bbfcb567c2ea85f305050b7e8a685cc331f1a3717b7df2fe053c", .None}, + {.Sqrt, "4d463fe58acca5f27113e9f96779783e61cfefdcadd971a8055c9d1ef782a44292f11bc4a7ca8930246531daa1680045f3c95549eabd5959aadcdd8a38a6ff1212a89d8683e7ca25d35093d40b747932cea4c902fc32e7b67688e859d52b2dfaafdc4904b4aac3f504e40b3a695ca597e149698a76e091da6cab5a33ad445a50074faf23f9e68c5663a48a0227506eaf45eee6604698", "0", "8ca63e1e1a3a8c97669a2ae30506920ed8373603fd599a1a89223879ff1341b81eaf6c33727ac751887fd69f3267b8089ca1c4b0b4bd4bd0525b8fe840274592d37d20a785644145174e7e", .None}, + {.Sqrt, "fbadfd83ad6c46d67b9892a23dff7663c46bc47c0a66e8e17733ceab270534c0d385c8f2fa06dca23132e3d8aea5fcfcda0b74cca19e02101fb2f3ac2c3c227b983d396f38a4f72b7397e1afe2c687037725a0c43295a2de321dd94bf6bf5719e3fba5ca5fd4264c83f6d5a1582d171e53728629e94cfc43b73d7508ea0a39e593a6abe3fc6ad5ed5964a707d04d9c43bfb53a606e20", "0", "fdd4a45e9f73c3344c2a062db09f1ec9476b0755a8b0d49761d6cdd1dee380e239e42076b563771b48cb5b9d7b54f89bf206b0670816ec9dd66d19a10c6457033a2b5135d1fa47288fd30e", .None}, + {.Sqrt, "35f0916917a6e5d37144c9998a1209c10dbde3a5a46d6cc8196626a6fefc7ec8469c519598cd47ca9ac60983fc6b18d6918cc926eff13d4d52996f2cbd20859a53a5ca301be4c2fa005b721520739d6695834d2611eff2e30b629846e04e3e6f3fb5647e283615cb3af21468d56be5ecb681bd517997fbfaf8b180412b1b6edd37e8ea1808e4b473935dcfa0426cb0709c925dbdde9a", "0", "758286695bfa8bb886950a513d7121288836c58b132695be7d0f334114761fc32ffa26513546aa33d39d8c08f0f5f9aed041bb7f8b596fbc5a60fd4fe3f3eccb2ef9d7cb2b4c2d00ae55d8", .None}, + {.Sqrt, "4a873b3038134e82914aa942ff2099656480f3541c0af00c80430a1371d4333e362f65736a0e9d12a39f779b8df159668e26c10f55aefd54cc7c162e774bec99a861cf40cc021fc104f00b0f7e438ebf5b005e82d7668ca6be301c179ce8fc72a81dd4b4bab639d11892ba058c91b59ab001238a211e5dabf48e0b022a1f5b90aae05ff2d5c9ec00e9a79fc53b7bc333f133a9a9f988", "0", "8a20a9c22b8f48421c8e2a1037db69da5f2352d3efb688b3222693085485d6d24665d2d00e3828447fe59c41ae3d57f149c5f116ceb99fecb0b515e8ace42090e3c44dc7745ce81ba5f91c", .None}, + {.Sqrt, "9931df74e92271a3c255ec2b8d5b7e3caa1d14b9be4e457985d07f69ba3f29f1cc5f4595757864e7dc73e9553378ce64135d29b6dc78ff171b0ed26c93f4ed23afd8b27922295c3dd1b0474c501af0a924a6558918fb6fed892e94e1f87d4c4a9fc1df92812fb4959399ff988e570229c2c58e572bafed00beeb01164b76c1d3ea993b1f7aee6b46c7ae3e6055e7d4943d2d18c4755c", "0", "c608f7b02863e3b5cae38944a89342efbddff11b40da348d626b23771072fb7f80ed403c5a440e5c6c4f5ebab18e78e3c9b6c9d8e908f2e4370ed976e36060f5f0fda5a8a95cfb95a55f8b", .None}, + {.Sqrt, "b005136de68cb2eefdb7eeafe71c000a2e31c84cb70fa1fc2ac6db8c143119a037a86b78e05893aa76a2ab111682e19d73aa6d8e969ac70dc738b4aa0e20773b8950790269b59bd0ad893b2bc873e84b67034cb1b40eb0d06fc80ba87cc1108febed7cbc88e33e65e417f847ac9430cb56045858fd7d1a0d48a19ff8e1c5334652898f9da6eb7f4d723798d621ca7994c8ffe55333f0", "0", "d446a4301ec01dd78860db29f8edf1a4ca3aeb0008016d35b6ba4f915471be26ea74d11521b029f18688f401b03ca04c124aa74f3999a9fe2449ff64292f33a3a80cd268c6ba2a452f3155", .None}, + {.Sqrt, "59efbbb8096df4c25a17ce95a7a3ba58810d3d7f7e043c281369c9e00e071b1f10107fd13eadf79ac97431cc935f60798f1a2a030e441c4ebbfd9a885f858ec936532b3f5c2b710a8288e93afaae8eca899584182de398e71eb2e549d8ca2f7bab2ad9c5d37b18759de420d9853e46262d7ca62e60ce6152ee6e84d68c4ceee3c24d0f1e6741921787ed1e79d3b1197362a7016a1d8", "0", "25ef16484433f986768dd9b07c6d94a09e088289464453d96df1b5d6e9a79dd62325f0ba537201aec988d230bcd278b339fe6523b95ceedd1563bf9e05bb04bbc33a0dac4adf596773b907", .None}, + {.Root, "ff4c1dd9111a8eda08d5dcefcab688a2f5c66ed6a59d52a136ccef8f330c4dcf2d82cb70a4ff569df6c9536ae214dbf77f3d11f11f38442e1183b01d6da7ae19c35efb5c4935a587a8bf1e3ccbc3bb1911fd378f3e5c0f83f6c707873e5138ee7fa936d09eaa390bfe4e7976acef15f2150377b5acb2f349e7881f72ff3c65008655c6bbc589541ef01154ddbebeb940789b87589925", "2", "ffa5ff1a37c47b6078c93bfb32ec6cf48d3c26fbe5b1574bb6a7a01938b5a0ffb8aee18aa9f4bd62d7ffbf33a1638fe4769c33319734b63478e2c74deb77bd4f21a5df597bc41663955602", .None}, + {.Root, "288aae8610294938faf6b69d984d3d39e032f08972a7c6f432809a2ec9706a5d516d807e0ba3435ffc583b2b1a84dbd8d0b65762e42e2e6c1b9d7ea89897d6ea68e273998b54db74b11364086d584660581f255b1c9ecc04a57ea83081cd94bca0ec2337a63ce0a004018684cea0b347e3046f95f536b88eb37259d80b90963f2d33e21052f52c0296f58845f3fe691b47c05c2b3cd8", "3", "8a80e4c8a74e499f3eb264ad1043653f86ff4cfe62bc704b754399fb9d0378aea07f08200c50fbf19f385fc5fa4ed3aaa090", .None}, + {.Root, "f43496c2d235b52f512a8c441b3324d30df904c2e311a095447035fa758885dfc43ec449ccd75311e1d036233d0aa7bc2bbf2e45015253f37169d7f5c2e95556694925b39ddd59de2ccf5ca0edf27f6a9bcd8bb8ea3f4dceb1b38331a67543e83a4c91ed115c66cc4d6e0abfeb40cc97099bca27c059bb891fe9745efbfc4cdc09d84fc1f173086cf5e9bd5b33aefc89362f12a10644", "4", "fcffbe5438086ad7c8274d9b5974d572d94b49a3c1b7feb6969f9a9d442b4415e4d3a591c28", .None}, + {.Root, "e5f630ebe61ac231eea9f543c006788dddcb59b97e07d8517817aabd2a6f9701d9a3891153e3c2d1350f497e97463ddf9e0aa9b57b6ab1277f12aff8a7b070f2083ba458a67eac3d198703726ed1925f44db13c399eaa9a48fabbbf43ca8ea7e4bdfa2b7b3e92d89281f940a40251dc627d6ef1fa98eb4690d020a50ce6352c5032bcb12546f41c5e66d46c9b34439aaceeebf9570c0", "5", "fa910879a3920562a9c452004dde25546513bc122575ec42059cfaa7f401", .None}, + {.Root, "a99bd40e9bc013ae1fc062e957bf20cb35db4b07f675eacc449a762bfac8c10ca15b426a772a263aa3c31b999035870b3bbc25363227c78957ae786b65782a9f51f94a291516af904680acd60d5d8d72cc8afee535718d4dfe318e33ebe362ac3dafbc2330715c15c3d97beb5e9f3afc7aa396a04e22a3d65a37401453b47116ddff35386350c4d218182c24f915d058cacb9d3582aa", "6", "ef061e466902eac16f80e281de452312ff29858dbe1fd2294d", .None}, + {.Root, "af64b7f992a9d0535ccf0c68fc240cf705d50b8358c27d525e814bbb0da766bf31f1151879cc71cd889031fe4c55458affcffab7940cfb361d86c98a7922a80bef9cc79a7e0f0b0621951ae26ca544525049552d1f5b6cdd884a9cd0ed9de0c2ab5785c6d7ab5c4802690535c726175293abf23df2df57e16b76a815900d0ace9731fbb51268f799ee34d04d3300c3358167078843ce", "2", "d3e5dc8fe9a781e90d750a948d508bba45bdd9ce33cf891d2501ee116f9c94b3d1dc09428baaa6326a95d9cc20088c047e509bd9a6908d003cb511fb85520f2f3d4258c0827b8ac5ccac79", .None}, + {.Root, "50b5d7e3b5a0fe4a6b92c16973d8eb0628e1b62761c9b36204bb080e2c9745daa56107b1f1e3f37128e371ae8fc5e7928ddeee101bd9029b30f403e10201af6766ffb9b3a707d9f1d1a9f60261139cc3d4c0ec3c00709ac6aec8ce4bfe338efbea79b00802ab04eb329a07050b45ae25dda78a4876d8cef15661786fe7b9959c2b87654a588c1259fadc53529fcc73cd69743f1e68d0", "3", "ae3c41c3819704f7a7b2e74bbddab2caf4bbe81e84b919f89ae3e89a2116f746568dadabf6a4b36c5d2a847a3ec3df30b17f", .None}, + {.Root, "bd26e4e6ccf3d02e64dfae3b6eda8b2104cb085e313c32b052da8fc583105e040684c30357657cd1e9ca77ec27ce5013fa32932d448ef38659ad28333b1190789c69b3a964450f770fb565f9ad7d08dcb113694f75c50a4e4e6c810a6246985f949470247563de4b2b2448289adeed89413e50a642e4030fab6d82f61186fe81d8c79cad2e3307f2bdfe429045b1ce14b0c49019e5ae", "4", "ed58ae5e9153593f6c50610dae79d771268dbd96d661fe948281a45d5ad8b72035ddbb454c8", .None}, + {.Root, "e7bb6dae94f2d779b1c3083cef2613a2cc8cd84841ff6974f7d5f624e78e3b801f18d87123f030f918b915c267073a3672ac0380e3079cdd522ff945c0f68e4e3fa7425d3c2e865fea1ccdfe61f47107e9e2bec82aa3461c714355825a3137608843151aca1bfea2dc68da55839465e56747d14468e683a7c6124a109ad5a527b0d0121dc376a8c27ce2aaa9001d45deceec303fb2b5", "5", "faf37ffb6cd2d1558ad658b1f2b15c7f24e5d85baffe3ecbd39ca32121bb", .None}, + {.Root, "b177ec800f3637dd63696c3858851948dca4da2822976d4dd067e047b9de2d85577d53e12cdb4078f87a49925e96aae05f7eb5354a015039b3241357c236c7e4550f5f50532c3291e537edd9f90e0a534e0f00cf25cd783d26b862e1fdc94fd0ec029cc54b4802cf734530c83437808b6c8b807926bbf64e7dce75afe0477c6112d71daa04715bca15ac6a54e8d1fa8264dab0f2f456", "6", "f0d5d701a142852857051ea3d3d7a4b081d1d50bd170d55e6c", .None}, + {.Shl, "6abdb2087013cc47e27b87e2216bc2ee440680c546a55282ca1713ce20b897a7690738011017e2b35ef28f10f39c4b63519d63cf5e26d1f45bd9795d08294872b6b6c2c1df410496d237358fef30c8564fded35adab78e97fc73cc29d1b5a7b1a7a4a3b0e106a98fcb13c345a39002f6bd6d47dae3b81a1cc7b53e8b19ad4ecf99f7d1baac800072ab59861408bae4b3e89a108d89", "168", "6abdb2087013cc47e27b87e2216bc2ee440680c546a55282ca1713ce20b897a7690738011017e2b35ef28f10f39c4b63519d63cf5e26d1f45bd9795d08294872b6b6c2c1df410496d237358fef30c8564fded35adab78e97fc73cc29d1b5a7b1a7a4a3b0e106a98fcb13c345a39002f6bd6d47dae3b81a1cc7b53e8b19ad4ecf99f7d1baac800072ab59861408bae4b3e89a108d89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "cb39d45f62cfc2d893e1960a341082cdab61699781099b6653538461e44374677d4cb837daf9430a4cf7b84d4fa38b7aa9524fb328a8d67fbed4728f7c6589a829e0711e07a2d497a35b05fa87bcd8666d6a01da920e5fbe46d474dc3584497b7ba2dd3f64104b8b2eb7049b7faa7b876e104c83d4c5cb6c4bcc0f9faad1cfc093fcc86ee3cd50b63990b68600e2860b9a30378bfd55", "258", "cb39d45f62cfc2d893e1960a341082cdab61699781099b6653538461e44374677d4cb837daf9430a4cf7b84d4fa38b7aa9524fb328a8d67fbed4728f7c6589a829e0711e07a2d497a35b05fa87bcd8666d6a01da920e5fbe46d474dc3584497b7ba2dd3f64104b8b2eb7049b7faa7b876e104c83d4c5cb6c4bcc0f9faad1cfc093fcc86ee3cd50b63990b68600e2860b9a30378bfd55000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "3b70dfabc9e534abd735d9174a904c6149762cc503eacbe50bc1b45b23fec11d5aa56030ded51090262d808223a97b9a0566e06f8fa549298e92b9e1117a935b9b7d02eafd073cfa80fe27cd0ccb8d6e1d07f238816a0e0388fdad531695179beb5fb1a3adfd8d735c3f5e907c70df5a214fc403af0fc0831adf399726f3b20682d0296f8ed26fbe26e513b06b31fe422b08781e7ed2", "12c", "3b70dfabc9e534abd735d9174a904c6149762cc503eacbe50bc1b45b23fec11d5aa56030ded51090262d808223a97b9a0566e06f8fa549298e92b9e1117a935b9b7d02eafd073cfa80fe27cd0ccb8d6e1d07f238816a0e0388fdad531695179beb5fb1a3adfd8d735c3f5e907c70df5a214fc403af0fc0831adf399726f3b20682d0296f8ed26fbe26e513b06b31fe422b08781e7ed2000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "37b0d2973e029d19c9b59ebbedc722d9d4c6079efc348efa21c95632960c85ed6539f8552849a5a54a081106f506757a450a41e9bcb51cf3cf1123f4923b12cef17b1563d7dce1d39d9b7db6382935857b8b94fea602b199c9093686f47ac4550a0c686cb39db9c1e90f7f945c913978dcabb155dc3ac572e453ae2eb7e00dbefbab2f27381aa82523c0e2ff7f2786f2302f023b709", "258", "37b0d2973e029d19c9b59ebbedc722d9d4c6079efc348efa21c95632960c85ed6539f8552849a5a54a081106f506757a450a41e9bcb51cf3cf1123f4923b12cef17b1563d7dce1d39d9b7db6382935857b8b94fea602b199c9093686f47ac4550a0c686cb39db9c1e90f7f945c913978dcabb155dc3ac572e453ae2eb7e00dbefbab2f27381aa82523c0e2ff7f2786f2302f023b709000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-83381d99ebacf248d2b0f2612366836fb9e302bffa9b1ff86b10548b15f224f4866fece80b932150038b335849034ff76deb57567084fe7d03f19629b7e715fe8db1d1fbbccf0d82987cefc3c80231b038f118770f76d855b1c8ccca8f8b4cbf4f5eed389c0ec97f203f8d57392a620f3fbd4c81b3c8d971da0e75c9aaee5080cf9d6fea0b0216f945b2af8401de6bda2038de74ab10", "b4", "-83381d99ebacf248d2b0f2612366836fb9e302bffa9b1ff86b10548b15f224f4866fece80b932150038b335849034ff76deb57567084fe7d03f19629b7e715fe8db1d1fbbccf0d82987cefc3c80231b038f118770f76d855b1c8ccca8f8b4cbf4f5eed389c0ec97f203f8d57392a620f3fbd4c81b3c8d971da0e75c9aaee5080cf9d6fea0b0216f945b2af8401de6bda2038de74ab10000000000000000000000000000000000000000000000", .None}, + {.Shl, "-768a09209e51665bf179fec89e21481a4d83df997345cb4d46569c7d7009478ce70fe140243e9ea848d5b44774d9e2bc28ece95bc9bfd9df41fffff35105ac1457804d4c81992292db9e29a38e03cb0ac8b149293c9c127499b94bec9946fc017e978822027aeacbcb1455cb10cc6266fcc9a57c516bd284b2a362d9106963f380733c22111d3ce21a128e87c16e591b4d82e676585", "f0", "-768a09209e51665bf179fec89e21481a4d83df997345cb4d46569c7d7009478ce70fe140243e9ea848d5b44774d9e2bc28ece95bc9bfd9df41fffff35105ac1457804d4c81992292db9e29a38e03cb0ac8b149293c9c127499b94bec9946fc017e978822027aeacbcb1455cb10cc6266fcc9a57c516bd284b2a362d9106963f380733c22111d3ce21a128e87c16e591b4d82e676585000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "31e255323ab69146a1e8ab5324bf2a69910478a030d1e26606770d6943f7c16ab062c989f8e355bc41eaf9e54cebbdce5bca441de5fbd513fba5e41694e092b32e57bb8ccc04142645f1662da04a93a95f74643a3bae3f14dabb017f26139cebcf058d2d18136763e0271253583a5a687b34e231cfa732194a8a4cbc2d6b7d64b9612b44310bac07079f138b368c92b4b85e800b27ae", "1a4", "31e255323ab69146a1e8ab5324bf2a69910478a030d1e26606770d6943f7c16ab062c989f8e355bc41eaf9e54cebbdce5bca441de5fbd513fba5e41694e092b32e57bb8ccc04142645f1662da04a93a95f74643a3bae3f14dabb017f26139cebcf058d2d18136763e0271253583a5a687b34e231cfa732194a8a4cbc2d6b7d64b9612b44310bac07079f138b368c92b4b85e800b27ae000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "b416a18db6dafa15b4cb756ab32993b87f080a99524c888a14ba685917440e463e63584266ef7f71b3968788a535611d72b425c31debce1967bff658352c4b3aa9d320a26da4eeb0d5a01faf7d98352a003f0744997cf6899b1fb7083ef2c9804bed8cf154a52d8e7159ca2de8903353279afc78328599a2e2237a0ee05dcbe13b4096baa0b5fbc025abf0a0796b6e3f7f7d1d7f6058", "f0", "b416a18db6dafa15b4cb756ab32993b87f080a99524c888a14ba685917440e463e63584266ef7f71b3968788a535611d72b425c31debce1967bff658352c4b3aa9d320a26da4eeb0d5a01faf7d98352a003f0744997cf6899b1fb7083ef2c9804bed8cf154a52d8e7159ca2de8903353279afc78328599a2e2237a0ee05dcbe13b4096baa0b5fbc025abf0a0796b6e3f7f7d1d7f6058000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-9048e68bc6d76bef13c38d4ca89abe1e63fa910b5479b4404148b5599c0f73b95202e50153bbbfc732eec8c1bb29834faddafb261d5844eb83a9812574f1e69201cd06ca8d2dd12fdb0f7ffe734bbfe0a313804f14d6b9241f328907fe1f6cf343efd8a5b7bf73b93a913663b1a8e616a1414286603cabdb600ffc105d5f4cc9b2caed194e98bafa88152fc03351a57b9f83e0dda363", "168", "-9048e68bc6d76bef13c38d4ca89abe1e63fa910b5479b4404148b5599c0f73b95202e50153bbbfc732eec8c1bb29834faddafb261d5844eb83a9812574f1e69201cd06ca8d2dd12fdb0f7ffe734bbfe0a313804f14d6b9241f328907fe1f6cf343efd8a5b7bf73b93a913663b1a8e616a1414286603cabdb600ffc105d5f4cc9b2caed194e98bafa88152fc03351a57b9f83e0dda363000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "6ffbbe3caa06ea7dc454c1365f7d949198b4b1917d068a85ba351de2129742f971d93cf4e38f2dc84009cd6f8119c1f508846f86c1dece281575f7b9467fd2efbc7db7e4b224926fa1addd0bb275256751dab72c21221ea7a3e75d327cadc345f5f3bc78d655d4964b9947021bf6dbf49b75273f350b0a9af7a672654963626fb342a66d041cfc5588363425d2a1ddf427a20203e78b", "258", "6ffbbe3caa06ea7dc454c1365f7d949198b4b1917d068a85ba351de2129742f971d93cf4e38f2dc84009cd6f8119c1f508846f86c1dece281575f7b9467fd2efbc7db7e4b224926fa1addd0bb275256751dab72c21221ea7a3e75d327cadc345f5f3bc78d655d4964b9947021bf6dbf49b75273f350b0a9af7a672654963626fb342a66d041cfc5588363425d2a1ddf427a20203e78b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-2a3293db39a513bb492a3159066bca38f5cdd94dd9d95938c334f88e359ece5a44ef55a2f1b597d34a2b2b58beb11ccc67c92d56c10274713507251e6f9d9109cd919b0ba051b81764ff911dbac7dbfe702f5f463f8c301e2e5c7b25b506c07bb7783540f0c5b0484e969a413d544d95cf45130cb11065d58b502a140fd320e8a4e1eaaa253ebafaf80b807c51888f9c771f5a2d1ff", "1a4", "-2a3293db39a513bb492a3159066bca38f5cdd94dd9d95938c334f88e359ece5a44ef55a2f1b597d34a2b2b58beb11ccc67c92d56c10274713507251e6f9d9109cd919b0ba051b81764ff911dbac7dbfe702f5f463f8c301e2e5c7b25b506c07bb7783540f0c5b0484e969a413d544d95cf45130cb11065d58b502a140fd320e8a4e1eaaa253ebafaf80b807c51888f9c771f5a2d1ff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "653c27254855b2cc0647b2cbc049d5c4b6063eda54f98c7f2619ed0b1f1af31977b206db9be44402e0e3160d925828c9c3ec9f34a2a4423f497b523c993eb9025339949468d46e712308e305762c1237bb2ed6f0d389f13df8d22d671fb66f934611809d19fde832fd8b48412f2a9dcab27680ca1446c9b1fb2ab35a61424b66484b22710a82937b8d73b5d76e238b4c1bdb64fd5798", "258", "653c27254855b2cc0647b2cbc049d5c4b6063eda54f98c7f2619ed0b1f1af31977b206db9be44402e0e3160d925828c9c3ec9f34a2a4423f497b523c993eb9025339949468d46e712308e305762c1237bb2ed6f0d389f13df8d22d671fb66f934611809d19fde832fd8b48412f2a9dcab27680ca1446c9b1fb2ab35a61424b66484b22710a82937b8d73b5d76e238b4c1bdb64fd5798000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e0f02ea9a5b8da1fd5d96cd07a86b78717e047414c7a437d0dd05a6d20397e5190f6da529737a9e06a76bb3513a8f6dc9ce9bb0660d5d3d55eda289ba82f643a1ba54c8aa8b3970420fe19c4db1d2fc52143e58fcf3c0aebbe2395bf725151b5a44e826c4b222c69cf1f070f88235b31932f28b2b4f3e99a7c8bffe1317442f01ef7980776cdbf88da534bc99012f3d49d4243b6cdb2", "3c", "-e0f02ea9a5b8da1fd5d96cd07a86b78717e047414c7a437d0dd05a6d20397e5190f6da529737a9e06a76bb3513a8f6dc9ce9bb0660d5d3d55eda289ba82f643a1ba54c8aa8b3970420fe19c4db1d2fc52143e58fcf3c0aebbe2395bf725151b5a44e826c4b222c69cf1f070f88235b31932f28b2b4f3e99a7c8bffe1317442f01ef7980776cdbf88da534bc99012f3d49d4243b6cdb2000000000000000", .None}, + {.Shl, "15b1ea0afa777a7074d4f7d2d94e870259dee470423a8cf3b26067731b9d0ebcc7b189d932193988fef0885f473b605554372090b0e5277958be64dcf84f419c882d1ad2a225b2054246631a30329daa724d34a75b3823dff77ee2e204322cac1903680536bdfc54566423232677535241152d2b296854f8172f183395c5664ee1c76ca06e62559ca01937c51c14f7d4186843e1603c", "21c", "15b1ea0afa777a7074d4f7d2d94e870259dee470423a8cf3b26067731b9d0ebcc7b189d932193988fef0885f473b605554372090b0e5277958be64dcf84f419c882d1ad2a225b2054246631a30329daa724d34a75b3823dff77ee2e204322cac1903680536bdfc54566423232677535241152d2b296854f8172f183395c5664ee1c76ca06e62559ca01937c51c14f7d4186843e1603c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-3aa41e0940224a392c82f41013b68cdcd3cb6003bdeeac0eb5e4530c06c56dc894c7f499d147d9a7ba870c3964079955d1fd9705ed247306cbb8d4f706309b30a45d64bf61448be3c67020cf9b5b123f36b7d727761b0c8234f28b226ebb3b00eb6bff2cd3397b4c18f6104ab98c77ab1e1826b9ea04e65a28c769017f6447b1deeac853ac270ee5fefae06aaee4952883f63108b477", "12c", "-3aa41e0940224a392c82f41013b68cdcd3cb6003bdeeac0eb5e4530c06c56dc894c7f499d147d9a7ba870c3964079955d1fd9705ed247306cbb8d4f706309b30a45d64bf61448be3c67020cf9b5b123f36b7d727761b0c8234f28b226ebb3b00eb6bff2cd3397b4c18f6104ab98c77ab1e1826b9ea04e65a28c769017f6447b1deeac853ac270ee5fefae06aaee4952883f63108b477000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "44c9f81026215d076a7be5885b959b09a25284fa89c96ec5f65e8fe844c86e4628f92cb2ad21e8195bd8a0084bf336db1a97b9520919676aeb3371276bd60efc7af6018b6ea5da254277c481caab6a6b84564b5c952e1990ce08c4e5cbed049ca294e1e7d834dfd87f792aac3160330bb9ce4c31da211cb82b81ee94de7bf972834b3e7818156e351cb59b918648c72de7ea159117c4", "1a4", "44c9f81026215d076a7be5885b959b09a25284fa89c96ec5f65e8fe844c86e4628f92cb2ad21e8195bd8a0084bf336db1a97b9520919676aeb3371276bd60efc7af6018b6ea5da254277c481caab6a6b84564b5c952e1990ce08c4e5cbed049ca294e1e7d834dfd87f792aac3160330bb9ce4c31da211cb82b81ee94de7bf972834b3e7818156e351cb59b918648c72de7ea159117c4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e902d1c81ec3f611449bda52693d6032932de9c4e47e58525602a1711857175eaf93049811edd57c2cc9ff55fa0a2d5e5743373b2750a75084221a97d6607c5df2968751680676a62d65f7d1c1e23f349841c6262d737c5b368a8f07aee4c5a8d4b35b989d1e6605c4dcc525654ff883db0c3f8827ec432303e76fbc759453488904f2ab8ffd33ab57635b14d36b2e3654d0e8c8b9ca", "78", "-e902d1c81ec3f611449bda52693d6032932de9c4e47e58525602a1711857175eaf93049811edd57c2cc9ff55fa0a2d5e5743373b2750a75084221a97d6607c5df2968751680676a62d65f7d1c1e23f349841c6262d737c5b368a8f07aee4c5a8d4b35b989d1e6605c4dcc525654ff883db0c3f8827ec432303e76fbc759453488904f2ab8ffd33ab57635b14d36b2e3654d0e8c8b9ca000000000000000000000000000000", .None}, + {.Shl, "-e4a22d3ef72ac8945cb26806df47afeb755b8c7d24ea0b3a6780858cf6c3e510bcc7dc917960da3af5ce0caa767f03b8386514582e0dfa1f036a6a2cbaa282f4846be838ef721e2eb72026afb024ab7efb71d8293612123e9b3a4ac01e01d98d7dce8a52b9a46e52dabe800b83f8ae583f6711ceb309ab9b3c9eded1ff042e99cc1004d3cf79cebb0d0bf0de11f34e8b9da2fd3f49a2", "168", "-e4a22d3ef72ac8945cb26806df47afeb755b8c7d24ea0b3a6780858cf6c3e510bcc7dc917960da3af5ce0caa767f03b8386514582e0dfa1f036a6a2cbaa282f4846be838ef721e2eb72026afb024ab7efb71d8293612123e9b3a4ac01e01d98d7dce8a52b9a46e52dabe800b83f8ae583f6711ceb309ab9b3c9eded1ff042e99cc1004d3cf79cebb0d0bf0de11f34e8b9da2fd3f49a2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "894433c93d8a7af3001f6f07e7ec580145f5bd5474b5d8596bbecf2217293ec6d750a3c74f688d2d941113b4e9a48f6460032b1e2a52dfd1458bcfbe5cf12c90094b5e9fda7b5d773fe422312e8095805659cb28eff4c87cbbb8c607c14a681eca8d478c7466b24d2545157693fbfb09b30b4f28d6a040286076202de6b9ae6a5ae8bfa403ece96fd2dbeb2bdde759077cb6eeaf681b", "258", "894433c93d8a7af3001f6f07e7ec580145f5bd5474b5d8596bbecf2217293ec6d750a3c74f688d2d941113b4e9a48f6460032b1e2a52dfd1458bcfbe5cf12c90094b5e9fda7b5d773fe422312e8095805659cb28eff4c87cbbb8c607c14a681eca8d478c7466b24d2545157693fbfb09b30b4f28d6a040286076202de6b9ae6a5ae8bfa403ece96fd2dbeb2bdde759077cb6eeaf681b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-c354c7bb70f1d897c3df170cc1b1db94fde731901d4a55aa776f85881335899af60f8d4a3f4723c715a558172b7e78398e4f8e8426353d1f79c66d629cea59d760688a76c57391193c95d7d4d563e4e0c82fd8f630c46b5a7069ba847fa3608ef6b1e9e399d7c72697c7516cbc4ba1bc2bc23bb6d285a1d367697b06efbba00a2903c865cda253b5e0764aeef592f567d7d377318951", "12c", "-c354c7bb70f1d897c3df170cc1b1db94fde731901d4a55aa776f85881335899af60f8d4a3f4723c715a558172b7e78398e4f8e8426353d1f79c66d629cea59d760688a76c57391193c95d7d4d563e4e0c82fd8f630c46b5a7069ba847fa3608ef6b1e9e399d7c72697c7516cbc4ba1bc2bc23bb6d285a1d367697b06efbba00a2903c865cda253b5e0764aeef592f567d7d377318951000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e5b99f9b8a29822ed9ede436eecdd477175d8ee3bc52ad07aa575fc6c8319972a750a302bbaaa7e9f1366209f59453db8301dbf834da26db890afe9d9f52c502b248fe5f3b9f87b2c50a59e315534650d50e3beab8bc934ca7387f52d4acb1fcae197bd298952b18b5852f3f9a5bd6cfb92122e2ae2459f04dd49b7b33c23ef99de39bf03f914a3a813afaf23dbcf0046f78ac82ea1f", "168", "-e5b99f9b8a29822ed9ede436eecdd477175d8ee3bc52ad07aa575fc6c8319972a750a302bbaaa7e9f1366209f59453db8301dbf834da26db890afe9d9f52c502b248fe5f3b9f87b2c50a59e315534650d50e3beab8bc934ca7387f52d4acb1fcae197bd298952b18b5852f3f9a5bd6cfb92122e2ae2459f04dd49b7b33c23ef99de39bf03f914a3a813afaf23dbcf0046f78ac82ea1f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-a12094a29139fcba84fbad660b895e614ca331aaed6b54366f27d724433818b90225b475bb116bdf2b0bb392c7945797ac1d9264cee986bade46d5ceee52cb5dbf229ce9bec7f87b211abdf964d29f555c85aaf821cffe8f5d09622322f7c3378ed95c05d9b7aa049e2ad7519ecc3872f4ac5a8ef50565df7d344619f94207ca021080242317c9a17a99d793b67ce31797838942f94c", "258", "-a12094a29139fcba84fbad660b895e614ca331aaed6b54366f27d724433818b90225b475bb116bdf2b0bb392c7945797ac1d9264cee986bade46d5ceee52cb5dbf229ce9bec7f87b211abdf964d29f555c85aaf821cffe8f5d09622322f7c3378ed95c05d9b7aa049e2ad7519ecc3872f4ac5a8ef50565df7d344619f94207ca021080242317c9a17a99d793b67ce31797838942f94c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-a8c287981ed6987c299df3877a6ff5046df9ec5b1d86bca8504b92e1ed240f0f7df07b5b1d6dc47bf961086708b5d0812d956c5a21263736918bfe49367c0669744d9dfdeac19dff28cb4e0b9db030fe97585431b0ad3e577111975a5f3db76a1011ef826b3f80d3cdf9e8c6eb238640135b84c3e0c1ba906de87c7e3787826a21455a858476807f1eca333d8f05bfeba175047b2cdf", "0", "-a8c287981ed6987c299df3877a6ff5046df9ec5b1d86bca8504b92e1ed240f0f7df07b5b1d6dc47bf961086708b5d0812d956c5a21263736918bfe49367c0669744d9dfdeac19dff28cb4e0b9db030fe97585431b0ad3e577111975a5f3db76a1011ef826b3f80d3cdf9e8c6eb238640135b84c3e0c1ba906de87c7e3787826a21455a858476807f1eca333d8f05bfeba175047b2cdf", .None}, + {.Shl, "285172d51737fefcccc494e11e91a217189dfe3a482fde16fc606f47c8a2968b04decf675d067a3c7aa045012d3dedd3f7cbad0102848bce0c1e7f5749d8c0d1e6adff5c387d8818046589b3b33123cbbf0eb5b26106a1ff177cffc010d69a073c915d60f269f3079253bef24f35dc714d1d92b1b1448d76d82bce6b021131197f02f99f5a5df0f3033f7feb519922f9ff2fa4fbbf5a", "1a4", "285172d51737fefcccc494e11e91a217189dfe3a482fde16fc606f47c8a2968b04decf675d067a3c7aa045012d3dedd3f7cbad0102848bce0c1e7f5749d8c0d1e6adff5c387d8818046589b3b33123cbbf0eb5b26106a1ff177cffc010d69a073c915d60f269f3079253bef24f35dc714d1d92b1b1448d76d82bce6b021131197f02f99f5a5df0f3033f7feb519922f9ff2fa4fbbf5a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "bd583f9f89be15cb4c421fc2b24d1fb42529fe739feef562155c6be8cd18c44030549b1c3836c319cc4621e11c1e983c10ad9f55e14f32d3af8d674939afaf001e5042fcc4dcbb6789a17298266062c9a94b1034d614d44a5ded4427a3624dd2cb72412069e122697c4f4b7a2c9a351931f9abcb1cfd5f72a99ea01a300e85f33f203338e05be00a688df44f4f60f8a269f1f78d1be4", "12c", "bd583f9f89be15cb4c421fc2b24d1fb42529fe739feef562155c6be8cd18c44030549b1c3836c319cc4621e11c1e983c10ad9f55e14f32d3af8d674939afaf001e5042fcc4dcbb6789a17298266062c9a94b1034d614d44a5ded4427a3624dd2cb72412069e122697c4f4b7a2c9a351931f9abcb1cfd5f72a99ea01a300e85f33f203338e05be00a688df44f4f60f8a269f1f78d1be4000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-70b6ea9277d17901da6b9e0d8e94dd22aeed3f758dae0d20b6f9dc09d92ad374b2142509df9c7e5f1c90d8daec730178400836570d57a949749ee927dcbf3ffb1e18d2f070e74b435d0615d6f00a90fc68a19b93bb4546aac27b2d100f27c7b23d714c174bc27b55aa97b54559dba85ce426956e2601c60dc1bfecafdffc565154752234200e0d748a6829f94bf70e7c31e6c1adbb72", "1e0", "-70b6ea9277d17901da6b9e0d8e94dd22aeed3f758dae0d20b6f9dc09d92ad374b2142509df9c7e5f1c90d8daec730178400836570d57a949749ee927dcbf3ffb1e18d2f070e74b435d0615d6f00a90fc68a19b93bb4546aac27b2d100f27c7b23d714c174bc27b55aa97b54559dba85ce426956e2601c60dc1bfecafdffc565154752234200e0d748a6829f94bf70e7c31e6c1adbb72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-d651e6ef53d642b97b4e4fa0ec9a5709f17acca9111fa6236e0f20558f3acd4e4486766527f2cb776b48126e49d45376e9935dcf7804680dba1a59a21a4a064c37196de7e1fcbf847bf411375f869468113781b84d3937f412de916daaab01988db6ce99e3ede4b4ec365351e6b1c1de690b8519b20de48d13238e107a5095d0fd93ca4afabc817cc44ede50ba327b2a8bedfdbf8139", "b4", "-d651e6ef53d642b97b4e4fa0ec9a5709f17acca9111fa6236e0f20558f3acd4e4486766527f2cb776b48126e49d45376e9935dcf7804680dba1a59a21a4a064c37196de7e1fcbf847bf411375f869468113781b84d3937f412de916daaab01988db6ce99e3ede4b4ec365351e6b1c1de690b8519b20de48d13238e107a5095d0fd93ca4afabc817cc44ede50ba327b2a8bedfdbf8139000000000000000000000000000000000000000000000", .None}, + {.Shl, "-1d8c217a88f9afad8f3e3c9a0afb54e67bcbfed19a54167cd3fe8957fd31c87b72b75b605b34f491e34248b5396a033c287595f1c8662ee7b8348b1d5c9fbdac8fd5c3870b4b0e681c0075f32014be18d0e1099bf3dc427757d140d28032b99201c1b52f5a2991e057de7b41b20c4ebae57e737e16b5eefcf9881f1c35aaeb2060231139aa6796f06b0dabc1af98cc8dc2299a94ff9d", "258", "-1d8c217a88f9afad8f3e3c9a0afb54e67bcbfed19a54167cd3fe8957fd31c87b72b75b605b34f491e34248b5396a033c287595f1c8662ee7b8348b1d5c9fbdac8fd5c3870b4b0e681c0075f32014be18d0e1099bf3dc427757d140d28032b99201c1b52f5a2991e057de7b41b20c4ebae57e737e16b5eefcf9881f1c35aaeb2060231139aa6796f06b0dabc1af98cc8dc2299a94ff9d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "9f0629a8fc4b4cc4e482f782ae2a13adaa83852c92f5f6b02a90dedc66646727d7830a986fb0f971c0a3c15e944eb70ef093b574fc150a62eab051256a72f60ff8092c44bc47991dd9302fbeb9680d0e04f1a6c8a5feef842e9b34332b3c923ce675964e7e565b8e3895b3c7a2709e139b4bffc2114f20a511be82989fa9c786c327dec887e1ae140e419b2e7418e5a6325ba2eb8ead", "3c", "9f0629a8fc4b4cc4e482f782ae2a13adaa83852c92f5f6b02a90dedc66646727d7830a986fb0f971c0a3c15e944eb70ef093b574fc150a62eab051256a72f60ff8092c44bc47991dd9302fbeb9680d0e04f1a6c8a5feef842e9b34332b3c923ce675964e7e565b8e3895b3c7a2709e139b4bffc2114f20a511be82989fa9c786c327dec887e1ae140e419b2e7418e5a6325ba2eb8ead000000000000000", .None}, + {.Shl, "9279511fc2cba2debb66e9db31044198a73ea93e57dd0b1549344d3fadbd0ca640c2a83023a57693291567910fb0a94b433c5981d665546824051ce1ad9e5729f67725608b91814d7421076e754c63afcde0d4f72af2d612eff8c0ba6aa9f64fd224580661597edfd7ff2099145ec441daf42b6a70d4e76cd9f85f540ce256031ad0c5d9fe145f85ef55fa2c306ac9af9c8fc849e67a", "21c", "9279511fc2cba2debb66e9db31044198a73ea93e57dd0b1549344d3fadbd0ca640c2a83023a57693291567910fb0a94b433c5981d665546824051ce1ad9e5729f67725608b91814d7421076e754c63afcde0d4f72af2d612eff8c0ba6aa9f64fd224580661597edfd7ff2099145ec441daf42b6a70d4e76cd9f85f540ce256031ad0c5d9fe145f85ef55fa2c306ac9af9c8fc849e67a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "c7f250f2092155971f30a04b967a2c251b664e9c6c0884d8f1c77b3df71dfb6720aea9e6f23d80cc6f0d8d0a17c55dc696ef4952e6340f4814e32d3a12e7ffedc5c656db793579a87e1fe0e77343085009f206129e5d7fcb30f7381d84eb8ef901dbd999646c7e71e5096f9a13dd035e9dd4decf9dc351dadb796df3c55bc91736e327e61a9bb3665ede7ef183d74b62b1cc192b0647", "78", "c7f250f2092155971f30a04b967a2c251b664e9c6c0884d8f1c77b3df71dfb6720aea9e6f23d80cc6f0d8d0a17c55dc696ef4952e6340f4814e32d3a12e7ffedc5c656db793579a87e1fe0e77343085009f206129e5d7fcb30f7381d84eb8ef901dbd999646c7e71e5096f9a13dd035e9dd4decf9dc351dadb796df3c55bc91736e327e61a9bb3665ede7ef183d74b62b1cc192b0647000000000000000000000000000000", .None}, + {.Shl, "47847cee268b00bd10624eb6cd59a68909e23975511fbe2abfb5759262f9cd08fdb6d78737b0f64bcc7cbb6193eb1b8d9fc3cbf3af511e83e768ce8cfe7d115abc487b21b627c9c2606d3651b7400837fd69adea4f530e69c6e2d0df3bcef766f84e1e97b79e5df8e565f06de9ca24e2b5a2a0fae2198047abee9f0b3c7c2dfb87f3e743f27927b2cfd77874598ab63e3216e9cf9c16", "168", "47847cee268b00bd10624eb6cd59a68909e23975511fbe2abfb5759262f9cd08fdb6d78737b0f64bcc7cbb6193eb1b8d9fc3cbf3af511e83e768ce8cfe7d115abc487b21b627c9c2606d3651b7400837fd69adea4f530e69c6e2d0df3bcef766f84e1e97b79e5df8e565f06de9ca24e2b5a2a0fae2198047abee9f0b3c7c2dfb87f3e743f27927b2cfd77874598ab63e3216e9cf9c16000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-38fcf7ac8799b4da94c3a5745facffd71161c73f48885afe04b0eb29bcfb303dc7212a712e2d6e7a1f9f66c67eec9c852ee744e5c36dd3498fa87a43be81da2ede04f583ceac4ce2cead1ce555a0aab93e3dddcb4d6dcaee3aa9809cbea8d03c48f32108449e3b327171c782c36f3602226a3ec18eba294d582a33d55a0aaa2a7e0acb0b3d0a2b8d86886990f0d1603600507aabfcbd", "168", "-38fcf7ac8799b4da94c3a5745facffd71161c73f48885afe04b0eb29bcfb303dc7212a712e2d6e7a1f9f66c67eec9c852ee744e5c36dd3498fa87a43be81da2ede04f583ceac4ce2cead1ce555a0aab93e3dddcb4d6dcaee3aa9809cbea8d03c48f32108449e3b327171c782c36f3602226a3ec18eba294d582a33d55a0aaa2a7e0acb0b3d0a2b8d86886990f0d1603600507aabfcbd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-17009c5206aeb56504e1d3c2cdbfa7cd7479b9c13b68082d3d150813913582ecbe881caeeb0c89e3ae3f7abe477106b3ad1996e052d0af21ae15a32622d63986f437542273d04a46d0b0c9e8b0a14c10620bb6cc8e3c1345ec9ef65779d3d8127a9d06c4275cb70903beb28e21cd4bd1d2e3e70fd9fb882b3fc0e466d5b9e26e5b770d2d3e668e9834ee08afe65aa00b0efffdda852c", "12c", "-17009c5206aeb56504e1d3c2cdbfa7cd7479b9c13b68082d3d150813913582ecbe881caeeb0c89e3ae3f7abe477106b3ad1996e052d0af21ae15a32622d63986f437542273d04a46d0b0c9e8b0a14c10620bb6cc8e3c1345ec9ef65779d3d8127a9d06c4275cb70903beb28e21cd4bd1d2e3e70fd9fb882b3fc0e466d5b9e26e5b770d2d3e668e9834ee08afe65aa00b0efffdda852c000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "21c2b3e2b92694a4625d7f3644e4d5e3e86967ddcdb13e514d143c9b799e82c7c91cf56f2912d8570844acc5af2986894ac8d2ce2755bf882ebecd4d02a6971ce16d9ce9fb5ca4d00b543a583be4fd7447583bd8e9b0c92c110327eecefac75a09f8f001310cab3cc3fb57ea3606529af95564295e6278a195efadd8c40cd7ac40618486d56016cf1f0320b9c2ca8f4cb520bd9e7595", "78", "21c2b3e2b92694a4625d7f3644e4d5e3e86967ddcdb13e514d143c9b799e82c7c91cf56f2912d8570844acc5af2986894ac8d2ce2755bf882ebecd4d02a6971ce16d9ce9fb5ca4d00b543a583be4fd7447583bd8e9b0c92c110327eecefac75a09f8f001310cab3cc3fb57ea3606529af95564295e6278a195efadd8c40cd7ac40618486d56016cf1f0320b9c2ca8f4cb520bd9e7595000000000000000000000000000000", .None}, + {.Shl, "-7e039d194389a7adfb23d4bdc275b38e09133c51bc8fde698e1d230cc124e75cad424f5beaf83576023034ec122bf1370b472725b7bbca20aa75fb78de37d2a68d4e077e4c1823eb81e2049a42dafbe6362d3f3bade3705cd597b01dbb4dd8f6ebb711a9bb87e295c489e17a0e19fb6a152e8eb93aa83031063a8ffad8cd64efc5b77b65d0406354087ad2176192ac63d8ae272fd825", "0", "-7e039d194389a7adfb23d4bdc275b38e09133c51bc8fde698e1d230cc124e75cad424f5beaf83576023034ec122bf1370b472725b7bbca20aa75fb78de37d2a68d4e077e4c1823eb81e2049a42dafbe6362d3f3bade3705cd597b01dbb4dd8f6ebb711a9bb87e295c489e17a0e19fb6a152e8eb93aa83031063a8ffad8cd64efc5b77b65d0406354087ad2176192ac63d8ae272fd825", .None}, + {.Shl, "-f33bf46a6828ae5404f8d10a3a2f0de7368caeac1ebccc3765fb17b8106961963e33119ea914056e6b9c31d31f9dca9da174105e3c8e6f4fac5377c0af062c391fa58bd0f1adb20e0db3b1609733eee30ed23557d98d9b5133b3fc4bdf1aaab753a7fb16489d85570185debc1b358fc7024f9d8ea58ad6d6160024f2f91d42a3dbdf1ed2d048381b8e4ffcbd1bfab7c1825c69098dac", "f0", "-f33bf46a6828ae5404f8d10a3a2f0de7368caeac1ebccc3765fb17b8106961963e33119ea914056e6b9c31d31f9dca9da174105e3c8e6f4fac5377c0af062c391fa58bd0f1adb20e0db3b1609733eee30ed23557d98d9b5133b3fc4bdf1aaab753a7fb16489d85570185debc1b358fc7024f9d8ea58ad6d6160024f2f91d42a3dbdf1ed2d048381b8e4ffcbd1bfab7c1825c69098dac000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-925f10757909ce07a064c976779c1b05b6309405dcdff710d4483d53a933c611af7916bae74327086e30a5c187c3fc004050d74734f71ba379e8d81e62601b434e20fccc767157bd402e3f4af7b64f27bdf51a1422c71fa54692a80822a86b2c8d5c6e62ea6950f5a6a263f86bebcc69b6d0561cd652bf7104cd714913a82641792959a3401fcb37232ce03fdaf20e5ca0f4939d882d", "78", "-925f10757909ce07a064c976779c1b05b6309405dcdff710d4483d53a933c611af7916bae74327086e30a5c187c3fc004050d74734f71ba379e8d81e62601b434e20fccc767157bd402e3f4af7b64f27bdf51a1422c71fa54692a80822a86b2c8d5c6e62ea6950f5a6a263f86bebcc69b6d0561cd652bf7104cd714913a82641792959a3401fcb37232ce03fdaf20e5ca0f4939d882d000000000000000000000000000000", .None}, + {.Shl, "-bd4043d3e5066096f1a6d65eccb875483afad0fac1c8c570ac908f874c0a0c2efd57f5553cf9bd344b73ecd4a1ebf4f53c82c74121160276383d748c93d5523f0847b68b840bae25d5885aa77714e74c66a4046518d95337c59a95f64f535f61999ee29d1e64eed61b1b62c7b2bb0b1302614fa4f530579c7b226b6bd5487984a9942ccfb69ed63511a654783ca9f20c7df708695ce2", "168", "-bd4043d3e5066096f1a6d65eccb875483afad0fac1c8c570ac908f874c0a0c2efd57f5553cf9bd344b73ecd4a1ebf4f53c82c74121160276383d748c93d5523f0847b68b840bae25d5885aa77714e74c66a4046518d95337c59a95f64f535f61999ee29d1e64eed61b1b62c7b2bb0b1302614fa4f530579c7b226b6bd5487984a9942ccfb69ed63511a654783ca9f20c7df708695ce2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "a78694286aef4286240c9930f67030aec124aeb544b5e2fb71a419b7362529327d37fc534c92863f5671519bbe1b75cc30b4b9e11c0030c2bf25f92cb63793793f6576ae15df09db910c8f7c4a066c46806845e01c61d779be8e1acbf7645e976f35e99b3ac1e7e6286a44a14012de0441c17ea94cc4ee1661446667b1b8e740ea18543bb2d683e98a3c1bdcd45062447ce436e87afb", "1e0", "a78694286aef4286240c9930f67030aec124aeb544b5e2fb71a419b7362529327d37fc534c92863f5671519bbe1b75cc30b4b9e11c0030c2bf25f92cb63793793f6576ae15df09db910c8f7c4a066c46806845e01c61d779be8e1acbf7645e976f35e99b3ac1e7e6286a44a14012de0441c17ea94cc4ee1661446667b1b8e740ea18543bb2d683e98a3c1bdcd45062447ce436e87afb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "f4ef97adbb2fdc0cdae8340554f132b83fc8d494974db4045cc3cc8a9d4d7845daf8d9f87572cf8b0a8fcc076d9fee480885fd48192014f9637c310e81369c94e683ab0ae8c792313c6b9d4a833df056ad9c44a8de00ccabd310be93543d1f3021d0d555c047c7f9d6ffe75e1f1783a197be6e85fa662f073db8678f1a07fb6a59c57c4d9bbb05f973e9baaa2b792e63ad70e14b1cc5", "b4", "f4ef97adbb2fdc0cdae8340554f132b83fc8d494974db4045cc3cc8a9d4d7845daf8d9f87572cf8b0a8fcc076d9fee480885fd48192014f9637c310e81369c94e683ab0ae8c792313c6b9d4a833df056ad9c44a8de00ccabd310be93543d1f3021d0d555c047c7f9d6ffe75e1f1783a197be6e85fa662f073db8678f1a07fb6a59c57c4d9bbb05f973e9baaa2b792e63ad70e14b1cc5000000000000000000000000000000000000000000000", .None}, + {.Shl, "7fa484648e0149ad1acddb2d02f089f811579d24ba78345762fbeca4d95d83252df06db5ea0d1932cb9b13197567cf0c9e36d3edc60a72d7105e0c3573a44fc1451db748c30fba3e8061f7c24c47314ea26e454967c2cc74e7bae52ade39f847de759029a2b25b135f6231cd0820e56b31bea967b53eb63070ee799ad92d65dde20aeec09b34b7763060e8af7052af0eb17276f52853", "78", "7fa484648e0149ad1acddb2d02f089f811579d24ba78345762fbeca4d95d83252df06db5ea0d1932cb9b13197567cf0c9e36d3edc60a72d7105e0c3573a44fc1451db748c30fba3e8061f7c24c47314ea26e454967c2cc74e7bae52ade39f847de759029a2b25b135f6231cd0820e56b31bea967b53eb63070ee799ad92d65dde20aeec09b34b7763060e8af7052af0eb17276f52853000000000000000000000000000000", .None}, + {.Shl, "-c84b0cf269968ceaab02a9ed4544b13b157d164000a41d4e2d680e212fa3129c31d1de2f1e1e9f4949cb8afa995fe258faa6352c38c31f43ab8d209d37a090eb569cbbb358b53e9cbb5332760481ffbfb3562e5422c59f1de5704002471c951937daad54ffe9dfd9312dd0cb7f2ed47a1816c845ba67ce15d168404e857d710e6b23ee59e18d9457df118dde7e62c82ef8c09b9a18cc", "258", "-c84b0cf269968ceaab02a9ed4544b13b157d164000a41d4e2d680e212fa3129c31d1de2f1e1e9f4949cb8afa995fe258faa6352c38c31f43ab8d209d37a090eb569cbbb358b53e9cbb5332760481ffbfb3562e5422c59f1de5704002471c951937daad54ffe9dfd9312dd0cb7f2ed47a1816c845ba67ce15d168404e857d710e6b23ee59e18d9457df118dde7e62c82ef8c09b9a18cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "e08c0ceaf6cdd8c40a50cc41aaa0497ee9c00968a9298abb40fa01518a48cbed524e438d5fdecbc992a83b3e22138393a581a48ffbdc6016dcd3fb0bde35a0e6689b3f9f30cd45b22cad95997ee19c5ed529a25d02e786e5295460c1b2740f37b9f354ebb570ca3d5074de03a53d2d02f601c877d8744eeee92d9513f51619e8fbc9f82beff0e85855464d7e0bf2b9abda22032f2a61", "1a4", "e08c0ceaf6cdd8c40a50cc41aaa0497ee9c00968a9298abb40fa01518a48cbed524e438d5fdecbc992a83b3e22138393a581a48ffbdc6016dcd3fb0bde35a0e6689b3f9f30cd45b22cad95997ee19c5ed529a25d02e786e5295460c1b2740f37b9f354ebb570ca3d5074de03a53d2d02f601c877d8744eeee92d9513f51619e8fbc9f82beff0e85855464d7e0bf2b9abda22032f2a61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "5cccc8c34716a29dcfcdb7342d97434e9024be933218d9e273ca7f1f9589b74e9ea336e94359d060882c9bbe1965221db9858f17086543158ba1ee531818078256e59ea5417b85ac23a60ce67bcb609fe4b06efe40b97805549d0c59c7dcceb84c38ee5090d903b37883630166257fd269276a71a64b651892d6c9649b1aaf4c8b58cb51a4163875647388ace0f627e512a10aad73d5", "b4", "5cccc8c34716a29dcfcdb7342d97434e9024be933218d9e273ca7f1f9589b74e9ea336e94359d060882c9bbe1965221db9858f17086543158ba1ee531818078256e59ea5417b85ac23a60ce67bcb609fe4b06efe40b97805549d0c59c7dcceb84c38ee5090d903b37883630166257fd269276a71a64b651892d6c9649b1aaf4c8b58cb51a4163875647388ace0f627e512a10aad73d5000000000000000000000000000000000000000000000", .None}, + {.Shl, "80dec38bc78d1c110be1f5a54dc6cb484088733138be402add421d019e4f3fc009a1cf4c3d6cc05ea821f6fd38c6a72e2094f033b4f950466b9613e32c0bc185efcaede6f212e0ef45ee284d559f63c7224d51d44061c569bf6c3513db161f60af53b72e76ce8cc259e602c9c75d2455dc898d57b38c2082a12e17b465109a98d14a5b29b2d590e1990394e387f5ab1b055a1a60942", "21c", "80dec38bc78d1c110be1f5a54dc6cb484088733138be402add421d019e4f3fc009a1cf4c3d6cc05ea821f6fd38c6a72e2094f033b4f950466b9613e32c0bc185efcaede6f212e0ef45ee284d559f63c7224d51d44061c569bf6c3513db161f60af53b72e76ce8cc259e602c9c75d2455dc898d57b38c2082a12e17b465109a98d14a5b29b2d590e1990394e387f5ab1b055a1a60942000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-a8852d15b627554e85417e7d423f36270cc5c3da119635418807efe3822706e171f6b8f709b5cad78d272ed9e0f3fb6bd4c67536c12a35961ccee263f2769eaf02111ce74a405577c4e876808b97941670607de4e0473385c909e28e59160eab7d74b63644adae78c1dabbe6e7fb18779babccd118f38aa4aa932626d49ca98ff482936fadd91937610debfdbb9552982aeaef07c765", "0", "-a8852d15b627554e85417e7d423f36270cc5c3da119635418807efe3822706e171f6b8f709b5cad78d272ed9e0f3fb6bd4c67536c12a35961ccee263f2769eaf02111ce74a405577c4e876808b97941670607de4e0473385c909e28e59160eab7d74b63644adae78c1dabbe6e7fb18779babccd118f38aa4aa932626d49ca98ff482936fadd91937610debfdbb9552982aeaef07c765", .None}, + {.Shl, "-cf698596d8e762216a98391d71caf3995548e51e538b5c04c048d01b6cce22963c3463f591385cc7e2eddc3077730037e974abda17709f0a3732e966835e22534d8570efca3b9625b2f9b2aa31f4430cf175ea6e7dda13dde400f490faed8970e0dfb45b0766a754e87b4e9b26306dd883016541e05addde247af3ef1e83c9d00b5f2e44989754b94d33be9d5aadb3b24b3e7dc4db94", "b4", "-cf698596d8e762216a98391d71caf3995548e51e538b5c04c048d01b6cce22963c3463f591385cc7e2eddc3077730037e974abda17709f0a3732e966835e22534d8570efca3b9625b2f9b2aa31f4430cf175ea6e7dda13dde400f490faed8970e0dfb45b0766a754e87b4e9b26306dd883016541e05addde247af3ef1e83c9d00b5f2e44989754b94d33be9d5aadb3b24b3e7dc4db94000000000000000000000000000000000000000000000", .None}, + {.Shl, "-3803183bc176c3444c0bd91353e08c56716470943e44f14925ed58698a6de9ffb6e09f16730b76aa39401c9474eb894f28149ebd9a501c441c301782da220889158bf5a3b0036aac5e447dbecb368a564b485be0810d2e99e22887f1d94a8b03730c7ca80bbb8f2eca44dcab9b8f724808ff3cba848a1cd178d62809fb74f85c9fe79de719a5768b208c5601e0d7ed3fa7f7a51dc50c", "b4", "-3803183bc176c3444c0bd91353e08c56716470943e44f14925ed58698a6de9ffb6e09f16730b76aa39401c9474eb894f28149ebd9a501c441c301782da220889158bf5a3b0036aac5e447dbecb368a564b485be0810d2e99e22887f1d94a8b03730c7ca80bbb8f2eca44dcab9b8f724808ff3cba848a1cd178d62809fb74f85c9fe79de719a5768b208c5601e0d7ed3fa7f7a51dc50c000000000000000000000000000000000000000000000", .None}, + {.Shl, "ff8ef7310b4271c79c08ca4bcffa7a0cd8297d456b864a2b6a05036f457de0863b9223ccd496ee38d6d07d6fdde5c50a1ea50419ae4908abf5225a2747a0fc2e2f86fad1b2e90d3b69c876b44ca27e018552244497cd01155148582b9efd7cf0be044df9213111446c046191198389f34edb138f2b6efa541e1d70ef272df7db5d4ba4116aaa41126ef97ed0ac2277b17b0205301a63", "1a4", "ff8ef7310b4271c79c08ca4bcffa7a0cd8297d456b864a2b6a05036f457de0863b9223ccd496ee38d6d07d6fdde5c50a1ea50419ae4908abf5225a2747a0fc2e2f86fad1b2e90d3b69c876b44ca27e018552244497cd01155148582b9efd7cf0be044df9213111446c046191198389f34edb138f2b6efa541e1d70ef272df7db5d4ba4116aaa41126ef97ed0ac2277b17b0205301a63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-c087ecd899d5d1c288b018c1d48f1ad2d0ebc6db3ef523c2c1fc2eb7781cf240e0e8b5db9477fb4e727fe52f3608bb24022f5568a79c094aaf759f8baa08fa89302fa66971e61de64cdbb8e9c7d125a48296780942a5445ccbcd0010bd3d0af6ed0e33705d301c0240f7f23e8f74ac82df1eedf3b75ea3765bb8e1e96c72712d8edd0cb67b6e33a4a1596d0745cce42f700e694a128b", "1a4", "-c087ecd899d5d1c288b018c1d48f1ad2d0ebc6db3ef523c2c1fc2eb7781cf240e0e8b5db9477fb4e727fe52f3608bb24022f5568a79c094aaf759f8baa08fa89302fa66971e61de64cdbb8e9c7d125a48296780942a5445ccbcd0010bd3d0af6ed0e33705d301c0240f7f23e8f74ac82df1eedf3b75ea3765bb8e1e96c72712d8edd0cb67b6e33a4a1596d0745cce42f700e694a128b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "c5ef326f34f213ab86443e07cb504f3f43a0c256a2d7f37ad91e4462eac4b6b03aae29b5342ad4ebdf5d4e7ea48e33b5f5817b4b360563912f66a50bd56e98173e050dc6ae9fbf7ff97a4777d272b4291321570ed5d8c2c614af95a9fee780d7fe10d059f9520cf5761dc70ec82fef4054046fd84c2c0a2c402cab0b47fa4021e199992ff56347627f73b2e21f32db0647a58aad1bbb", "0", "c5ef326f34f213ab86443e07cb504f3f43a0c256a2d7f37ad91e4462eac4b6b03aae29b5342ad4ebdf5d4e7ea48e33b5f5817b4b360563912f66a50bd56e98173e050dc6ae9fbf7ff97a4777d272b4291321570ed5d8c2c614af95a9fee780d7fe10d059f9520cf5761dc70ec82fef4054046fd84c2c0a2c402cab0b47fa4021e199992ff56347627f73b2e21f32db0647a58aad1bbb", .None}, + {.Shl, "-cb9d982cb531764f60933b8fa22a7dacb57c8122b03979b710ce66e453606caceb0e8c6ef4a37ac3dcccff459dbde4a168ca8884e5ba5725dca82ca1ef21ec4440f1f1a8998f7c657448e1e6f2078a042fe65cc535f1f27fa576994c25bfbd56954569c3d4bfd7f4032d38e36713d310623962d6b601c2ed3f67e4ae930821ce6555a5a3d283a8fe343598887826a01291eb2060cfca", "21c", "-cb9d982cb531764f60933b8fa22a7dacb57c8122b03979b710ce66e453606caceb0e8c6ef4a37ac3dcccff459dbde4a168ca8884e5ba5725dca82ca1ef21ec4440f1f1a8998f7c657448e1e6f2078a042fe65cc535f1f27fa576994c25bfbd56954569c3d4bfd7f4032d38e36713d310623962d6b601c2ed3f67e4ae930821ce6555a5a3d283a8fe343598887826a01291eb2060cfca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "16d28ed703e234dd0e025f4ee2174483154e6ae900d109b7a5bc9ed30e34970708c38999b7de494078a6ffe827c71f373a01946051be958c3f078af18c88546d8f6bf4cc5147dec029e4563626fdcbfe033c22732214f94138f52d4a664f5f3d13c55492c16c8a5aff9335e00bf4e268bc493a49cdca8f2d604832d64c8b0a1e4c3c23211125f8dd32dc192660a93b29fc50b191cb20", "258", "16d28ed703e234dd0e025f4ee2174483154e6ae900d109b7a5bc9ed30e34970708c38999b7de494078a6ffe827c71f373a01946051be958c3f078af18c88546d8f6bf4cc5147dec029e4563626fdcbfe033c22732214f94138f52d4a664f5f3d13c55492c16c8a5aff9335e00bf4e268bc493a49cdca8f2d604832d64c8b0a1e4c3c23211125f8dd32dc192660a93b29fc50b191cb20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "a1ed5e6501a54bbdde148555b71f748a7d7a293b13943825c077b9027cb85b40aea02f0c214c671c2048eaf10a547848dbbec7968f0a4336982f332728418bf85ff024fd6ffd064397c74dd18cb6fd12106aaf5879166313cadaff16d375f850e67534329a62df11f5d04ede2d6cc2c065398b63181a99e906bf772c378273fcd1537843323eacb1ae3c4344f6555d39fe887d3dc1ce", "258", "a1ed5e6501a54bbdde148555b71f748a7d7a293b13943825c077b9027cb85b40aea02f0c214c671c2048eaf10a547848dbbec7968f0a4336982f332728418bf85ff024fd6ffd064397c74dd18cb6fd12106aaf5879166313cadaff16d375f850e67534329a62df11f5d04ede2d6cc2c065398b63181a99e906bf772c378273fcd1537843323eacb1ae3c4344f6555d39fe887d3dc1ce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-25059e993a7e22f4719c9d5a3b440c7b559029d0f03ee6559fce6641f034c3d109ba46673cfe8df8b42da0683b7d1757d485db1f2c0394d90aa3ec7f5c355a476752a7ca80d63532b84102589b0ae8bfda0e7c030a54628cc2ac2d82a3958dad0abf261ee0f444b87b921de615f383ae7d39510060883ed4eacaf70584a17a8284e8cba82225eb1d5543de3f6eb5fdfc539f92861f2e", "168", "-25059e993a7e22f4719c9d5a3b440c7b559029d0f03ee6559fce6641f034c3d109ba46673cfe8df8b42da0683b7d1757d485db1f2c0394d90aa3ec7f5c355a476752a7ca80d63532b84102589b0ae8bfda0e7c030a54628cc2ac2d82a3958dad0abf261ee0f444b87b921de615f383ae7d39510060883ed4eacaf70584a17a8284e8cba82225eb1d5543de3f6eb5fdfc539f92861f2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "caf7017ace9b96672b926c48009c38b181de36180d176172008e60f537545c68c9921eac469d3e8e723054b5f5400410cfd434d02e0dc4b3d37110243167feb4b185a9885b58299a8ff78ba3a9a42e73629459523da367dae1dd1efa1c4157a72c5addd378de36eeaebcd2fe4c286c09030f50534ff3c28810d60301280ddaa16b434be016cf73c17620e139d5f4dce41f00550e022d", "21c", "caf7017ace9b96672b926c48009c38b181de36180d176172008e60f537545c68c9921eac469d3e8e723054b5f5400410cfd434d02e0dc4b3d37110243167feb4b185a9885b58299a8ff78ba3a9a42e73629459523da367dae1dd1efa1c4157a72c5addd378de36eeaebcd2fe4c286c09030f50534ff3c28810d60301280ddaa16b434be016cf73c17620e139d5f4dce41f00550e022d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-fc69c62e66102d58da55450dd5bb33e774d651a48c7f81d5da108c706a2659ca0a37c2535efa992b6f96f82e814ef62470a42df2a3f9658db964bb4202bc58b547ae41ad00e8a890787049438d87ec33c4126a36dca42edb7db9245ec5829f91ed23444464af7cf72a690078f5b743382368709537b62eb1e159d6e07911dbdb1ac7d23871c8246393e5ff4f72ebfbecc8a44375f19b", "0", "-fc69c62e66102d58da55450dd5bb33e774d651a48c7f81d5da108c706a2659ca0a37c2535efa992b6f96f82e814ef62470a42df2a3f9658db964bb4202bc58b547ae41ad00e8a890787049438d87ec33c4126a36dca42edb7db9245ec5829f91ed23444464af7cf72a690078f5b743382368709537b62eb1e159d6e07911dbdb1ac7d23871c8246393e5ff4f72ebfbecc8a44375f19b", .None}, + {.Shl, "e8df231efb5250778534699e63d2676a9868f6d8fe012c60ec47f607c260f59a7960bc00b9b7e8a23150fbbcfe65e9bb491eb3c15d03ca8bf1a3d0fadb9c3688623ddc54381ac8f7cc014e1ee461147c455740d6a5ff2daed273d91334df893c69a991f06898097bd6964a23670c2b3acfefa6e5d0779306d5a3fb0f258a7776c5da41093903cea71a3875b5e796680af2e5ba0274fb", "b4", "e8df231efb5250778534699e63d2676a9868f6d8fe012c60ec47f607c260f59a7960bc00b9b7e8a23150fbbcfe65e9bb491eb3c15d03ca8bf1a3d0fadb9c3688623ddc54381ac8f7cc014e1ee461147c455740d6a5ff2daed273d91334df893c69a991f06898097bd6964a23670c2b3acfefa6e5d0779306d5a3fb0f258a7776c5da41093903cea71a3875b5e796680af2e5ba0274fb000000000000000000000000000000000000000000000", .None}, + {.Shl, "-99aa2298dfbf12c3d3bd33b8e5143dacc06488cd9ff215b7f83860f9c83d602a0d5890ecb5d2482c43ce675b10b7888cd73dc591f8fdb31be57e94cbac1fe5cef8021611ec7367c8ed6d5a8627506307bd1982df1705fb1bcf7a23bf49956fc982315742f906bf2f643a5eff6ef4962ca3fccd2c2b32298428fda297da3f8c1ac1806f789237ff72a5893bed81b97d526b8027ad319e", "f0", "-99aa2298dfbf12c3d3bd33b8e5143dacc06488cd9ff215b7f83860f9c83d602a0d5890ecb5d2482c43ce675b10b7888cd73dc591f8fdb31be57e94cbac1fe5cef8021611ec7367c8ed6d5a8627506307bd1982df1705fb1bcf7a23bf49956fc982315742f906bf2f643a5eff6ef4962ca3fccd2c2b32298428fda297da3f8c1ac1806f789237ff72a5893bed81b97d526b8027ad319e000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b313030a8e626ea62ac0a8eb8f2bca71aac17b6d759608e8631297c4aa9cc830aebf5654cee59c75f5d711b775caf059a771a55c482f28cef81ae731c45114f68b5fa220f2c426e76bdb6c4e5c13aad1e18758838d054067d705d2c17f4616cd3bdc23816518cd253051a917b60a7fed89955199f54f77ce9e344f60d3661852f88158367568d61f71b3ef45c18ed3fc7ac91241df01", "0", "-b313030a8e626ea62ac0a8eb8f2bca71aac17b6d759608e8631297c4aa9cc830aebf5654cee59c75f5d711b775caf059a771a55c482f28cef81ae731c45114f68b5fa220f2c426e76bdb6c4e5c13aad1e18758838d054067d705d2c17f4616cd3bdc23816518cd253051a917b60a7fed89955199f54f77ce9e344f60d3661852f88158367568d61f71b3ef45c18ed3fc7ac91241df01", .None}, + {.Shl, "e8c8161d4be564e6caa2238df86437f7b83ef6bd82c7d4c3856f4cd2b7376783c204380ad637cd83abccecf32c0c80f8cdf864b049f383e62d631e9f5c5985993263c2540b0021ccde73924a7504174f6ccf0e24ff1caa299bf79fa1f7974613e5b41be357d4f66172d0472331899a5c12ce8e163391e1c795182b3eb0fe456659bfa1b9c2d6c51849816bc924a28c5b7dd95c384807", "f0", "e8c8161d4be564e6caa2238df86437f7b83ef6bd82c7d4c3856f4cd2b7376783c204380ad637cd83abccecf32c0c80f8cdf864b049f383e62d631e9f5c5985993263c2540b0021ccde73924a7504174f6ccf0e24ff1caa299bf79fa1f7974613e5b41be357d4f66172d0472331899a5c12ce8e163391e1c795182b3eb0fe456659bfa1b9c2d6c51849816bc924a28c5b7dd95c384807000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "70d06cc5e00bf5afa87090d30f6c9186ca0f522fc6607591d1352377f493029e43345a0bc432fed1267356670d401f016c5701e02ef611f6dcee43d7bce5f746d65f86aa53a1fbf83e8cba23b1e903550a242e867ae9ef5fc795ee1ff61298c55964a1d5144f1a172b41e8220ff77ea313c2b51367997161ba8861cd3a2ae134ed746627dfb3a71a00bd5284518cbb2ccee16f328796", "0", "70d06cc5e00bf5afa87090d30f6c9186ca0f522fc6607591d1352377f493029e43345a0bc432fed1267356670d401f016c5701e02ef611f6dcee43d7bce5f746d65f86aa53a1fbf83e8cba23b1e903550a242e867ae9ef5fc795ee1ff61298c55964a1d5144f1a172b41e8220ff77ea313c2b51367997161ba8861cd3a2ae134ed746627dfb3a71a00bd5284518cbb2ccee16f328796", .None}, + {.Shl, "-aec26ad426d58f990f84317c7bcb5cf47b239f51c07e1b6eb3d0388ec398bb4e74f78e2ab126711e4f63c9d03e6b09f23849fe6b74a6bcfba67594e5aa310d633272a6e88fa99105c21a0f55d706a49ad487d3088e52637e19d179da67c6296bd3748858e1209cc8481ab536f9c1589375f7e9aed722c26c4e39ae51d40956fef13a9a1eb688d6a138ecfd2fe8ad684323c06b962816", "f0", "-aec26ad426d58f990f84317c7bcb5cf47b239f51c07e1b6eb3d0388ec398bb4e74f78e2ab126711e4f63c9d03e6b09f23849fe6b74a6bcfba67594e5aa310d633272a6e88fa99105c21a0f55d706a49ad487d3088e52637e19d179da67c6296bd3748858e1209cc8481ab536f9c1589375f7e9aed722c26c4e39ae51d40956fef13a9a1eb688d6a138ecfd2fe8ad684323c06b962816000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-9d4a2c523d1523bc7bafee7926e74458f20f204e3fcc96e74258d56797a80910994ee09356bed0d726c1167cccff23915a96bdc1f97d412a2166408a258d686d9b936cf87d928dfaf3bf7feefe764fc800e2c1553c5634b8eb558b6b9dc4da0c8cfd8cca4a85d50c918583d6d5f78c7c8d8fa24c6301c296c44fe05259b602472b3a541f6c5afe5ca4f1a2c4373d086cea65ef4399eb", "12c", "-9d4a2c523d1523bc7bafee7926e74458f20f204e3fcc96e74258d56797a80910994ee09356bed0d726c1167cccff23915a96bdc1f97d412a2166408a258d686d9b936cf87d928dfaf3bf7feefe764fc800e2c1553c5634b8eb558b6b9dc4da0c8cfd8cca4a85d50c918583d6d5f78c7c8d8fa24c6301c296c44fe05259b602472b3a541f6c5afe5ca4f1a2c4373d086cea65ef4399eb000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "684cc85b99c4abab16a1baed0bc6e5d89f52ddedf5e1b1b6cb8b2ed8b4429afc0f70dd737c69c251189befdc6523c7454ce03751a644f586f2b0a33d49d216ced6ad772ded495bd52943f318d1b3565132dbb8412f05e40af497a3e3f340c6b469ced53ece87f57f2cf6036d8e87258081182317e60d4c004981acb9d80602bd00c162e4de39461b436b90259b8c87d303ea449900da", "258", "684cc85b99c4abab16a1baed0bc6e5d89f52ddedf5e1b1b6cb8b2ed8b4429afc0f70dd737c69c251189befdc6523c7454ce03751a644f586f2b0a33d49d216ced6ad772ded495bd52943f318d1b3565132dbb8412f05e40af497a3e3f340c6b469ced53ece87f57f2cf6036d8e87258081182317e60d4c004981acb9d80602bd00c162e4de39461b436b90259b8c87d303ea449900da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "5bef6cedb8c7299776213bec5bb63bd905a5a75a66160f57937120638b6a75f8cc82c587fa5cd54713f6382d80bd874ce08d6d95e95b260f4d6ec5fc6ed8b0e44cbbe612d0fcc23e09ac1dda309c74b4512594e5052c580dfab28467897cacc4479d3a135a118bb872672b57f8c91cf81e63754ad92b718268bd4d7378840645e56caaeef3eeb689ddc386e7d0fb445c306ed050c965", "1e0", "5bef6cedb8c7299776213bec5bb63bd905a5a75a66160f57937120638b6a75f8cc82c587fa5cd54713f6382d80bd874ce08d6d95e95b260f4d6ec5fc6ed8b0e44cbbe612d0fcc23e09ac1dda309c74b4512594e5052c580dfab28467897cacc4479d3a135a118bb872672b57f8c91cf81e63754ad92b718268bd4d7378840645e56caaeef3eeb689ddc386e7d0fb445c306ed050c965000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-db047a893690d39479869703998efccad57fa39e2e7ca1edb84223a1d38cb2f02e0fd9af09ebba432aaafa96f4b5a7b0ae6510fc49a9925eff7d7c77eae9050ce7d9b285266bba9387313eee723700730d1a68525656824696f536fe3947cfcd4d1c78c2f4317f790e36277a8693c0e3e00d9aca8628d14f0f88f485523d5007bd6cb9c1f2abb91a54816091192fdf61d79b77bad052", "1e0", "-db047a893690d39479869703998efccad57fa39e2e7ca1edb84223a1d38cb2f02e0fd9af09ebba432aaafa96f4b5a7b0ae6510fc49a9925eff7d7c77eae9050ce7d9b285266bba9387313eee723700730d1a68525656824696f536fe3947cfcd4d1c78c2f4317f790e36277a8693c0e3e00d9aca8628d14f0f88f485523d5007bd6cb9c1f2abb91a54816091192fdf61d79b77bad052000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-489d875e5005b319f2e1a2b90fe951666268ef4079d55872b875999b1479ed4287f347cb4a38b7894fbc01bed8b03595a0dc25494b1bc9243dba8b5b112dbad3b3d416395327cb2fa60c741d6323a52cf1934dbb34a21111cd8eb93aa5cb099e9a33a423249c763b38a6caeba45638f356a0dad7acb2f83d5ac2d240c1900c2591de54443d8f55ad4c80887278608d911b7c0d8d9297", "0", "-489d875e5005b319f2e1a2b90fe951666268ef4079d55872b875999b1479ed4287f347cb4a38b7894fbc01bed8b03595a0dc25494b1bc9243dba8b5b112dbad3b3d416395327cb2fa60c741d6323a52cf1934dbb34a21111cd8eb93aa5cb099e9a33a423249c763b38a6caeba45638f356a0dad7acb2f83d5ac2d240c1900c2591de54443d8f55ad4c80887278608d911b7c0d8d9297", .None}, + {.Shl, "-a91f21dc9fd87b7af4423eb82c6945990c6924a611109661a2510c727991cecd98b63960a69fe338da6026b9da7cf5364be860c116511b6ab7ce592ec005776fb9a1423c20b23c2cab8b618cd1f57b54b1b0e0243cf5e0fe34d3b6b4e13ccb44e4126a876da50fd3e699a660d722ee52105f55ef4eb1438872f66df4f160244fe29d5facd4abe76acd74c0d02fd254d22aa9e47fa27e", "78", "-a91f21dc9fd87b7af4423eb82c6945990c6924a611109661a2510c727991cecd98b63960a69fe338da6026b9da7cf5364be860c116511b6ab7ce592ec005776fb9a1423c20b23c2cab8b618cd1f57b54b1b0e0243cf5e0fe34d3b6b4e13ccb44e4126a876da50fd3e699a660d722ee52105f55ef4eb1438872f66df4f160244fe29d5facd4abe76acd74c0d02fd254d22aa9e47fa27e000000000000000000000000000000", .None}, + {.Shl, "9ca15b6953c7671a05525af8c1d94075e883d5f0b90886a2c8cb5b95b0c3290d0ad7fa9a77e769f1bc5772e2d5b6a719f1e32341774fc4004cd5621a138b400cc0f07bfe9328628612db1d31a4b43ca5d2fc833b7f4ae17437bcbb5b9d83071ca820bd2443f2bffb4643132ae742de9153d7fc7ccec18f3b09864e5a5d0cc90f3c0d07f417e3dc8ef544dfa662d4c6c2b5f189d283a2", "12c", "9ca15b6953c7671a05525af8c1d94075e883d5f0b90886a2c8cb5b95b0c3290d0ad7fa9a77e769f1bc5772e2d5b6a719f1e32341774fc4004cd5621a138b400cc0f07bfe9328628612db1d31a4b43ca5d2fc833b7f4ae17437bcbb5b9d83071ca820bd2443f2bffb4643132ae742de9153d7fc7ccec18f3b09864e5a5d0cc90f3c0d07f417e3dc8ef544dfa662d4c6c2b5f189d283a2000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "a4712474678afc603ac0f4d3caa9bbd14d924316a7fd331148ebf37a65ab6096094e46f2f44fe5452acab5b73309ce090d1cd5bdfdc459e830fe78cbc532f0bccaf7ef4a6434db2fa299c4159da9c768f0bea997f1669774e856278e3b9e315b8bc093d13ea38161c2b3c92f18c2e65dfa7d3021c6bbee3245b6875f3bc6b3fc47cdec3008c02951a44c623f8b90a81c38c781b75628", "f0", "a4712474678afc603ac0f4d3caa9bbd14d924316a7fd331148ebf37a65ab6096094e46f2f44fe5452acab5b73309ce090d1cd5bdfdc459e830fe78cbc532f0bccaf7ef4a6434db2fa299c4159da9c768f0bea997f1669774e856278e3b9e315b8bc093d13ea38161c2b3c92f18c2e65dfa7d3021c6bbee3245b6875f3bc6b3fc47cdec3008c02951a44c623f8b90a81c38c781b75628000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b7b1932cea63ae61cca8aba28e02bdadcb7ddf26c5cceed1195d4f5421c77206104848e65d69cf0ba1e9c89661eb39a3eab73e53621dd43d0c4d118cbf440704b3aeb3877836d1774d7cb20b2c1d6542511941d175810edc3a674925c74076549b030c21bd4c331c4d48f83b772fe277732cb22f3ce98b2a78fc936d4b24d4954924f646bdb860b812dbb628d6d80a5b33fa501cfc0d", "1e0", "-b7b1932cea63ae61cca8aba28e02bdadcb7ddf26c5cceed1195d4f5421c77206104848e65d69cf0ba1e9c89661eb39a3eab73e53621dd43d0c4d118cbf440704b3aeb3877836d1774d7cb20b2c1d6542511941d175810edc3a674925c74076549b030c21bd4c331c4d48f83b772fe277732cb22f3ce98b2a78fc936d4b24d4954924f646bdb860b812dbb628d6d80a5b33fa501cfc0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "54b2e4422be21d5ebbb067b712530a250eda26adbf94bee58f7a97b4825be85c327e1ca105be6cacc636abfbc352d78321a59a74011e524f94f662320fa74ec97ad0aabebcb94d7a6f9360c122f1565bf63d11538818aef4a9b2aa98fe287dc49ac886d43a255ab4618f105bfc2fcfe997083d51e95b0ac8911c8097629f131b5a7e03f96f287e259db163fe34f11982b8b39d7707e2", "f0", "54b2e4422be21d5ebbb067b712530a250eda26adbf94bee58f7a97b4825be85c327e1ca105be6cacc636abfbc352d78321a59a74011e524f94f662320fa74ec97ad0aabebcb94d7a6f9360c122f1565bf63d11538818aef4a9b2aa98fe287dc49ac886d43a255ab4618f105bfc2fcfe997083d51e95b0ac8911c8097629f131b5a7e03f96f287e259db163fe34f11982b8b39d7707e2000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "6f56e1943cdc6c995f2a21d1c436570930dac219a6af0535e21bfbd2da152bc3e835672f9e60d147264f9931c99c0f1f7920783b84e52de17ceabb5a9aaeb3802bf044e24a0697db096aaf4dcb0a1d43636e516b8a515cdd672a756e6d69966dae0aee255e1c411cb9305860f1aecb848522e318ba64da6020847748106948e273a1abc1de49607b61ce3b4ce177a5d98702cca28adc", "78", "6f56e1943cdc6c995f2a21d1c436570930dac219a6af0535e21bfbd2da152bc3e835672f9e60d147264f9931c99c0f1f7920783b84e52de17ceabb5a9aaeb3802bf044e24a0697db096aaf4dcb0a1d43636e516b8a515cdd672a756e6d69966dae0aee255e1c411cb9305860f1aecb848522e318ba64da6020847748106948e273a1abc1de49607b61ce3b4ce177a5d98702cca28adc000000000000000000000000000000", .None}, + {.Shl, "5b9e6dc3397bebedd093cf90cd6187db58f983d4b192752e9248f5d54cb44cb5d4e40a82701b7f23007718424194dd4cf904a681c73acdf4af6e388ad4fdc0fb8ea3c3d8d2a3da0c2abbcba0fd1590d80c50ee6d35d786fbd536a764867197ec4f1f44b3ab31f74bfc7b5d0102d1b012a9a92c81f83c1e59ca30d0269617c3c063f02147efc4f241437b692e1630017c791bcd4459c8", "258", "5b9e6dc3397bebedd093cf90cd6187db58f983d4b192752e9248f5d54cb44cb5d4e40a82701b7f23007718424194dd4cf904a681c73acdf4af6e388ad4fdc0fb8ea3c3d8d2a3da0c2abbcba0fd1590d80c50ee6d35d786fbd536a764867197ec4f1f44b3ab31f74bfc7b5d0102d1b012a9a92c81f83c1e59ca30d0269617c3c063f02147efc4f241437b692e1630017c791bcd4459c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "129605e701e2049fcb76a85e080af544557320cdd82cfe4f22ff3d632e32ecd0346d427aab99f430b4fa150de69859240a9bc111e57281c34cc45bf0628fa5bd6a38528d8cfd12b09d24e82f7e73d3125ff55ef67eefe601e95b34cb6830d6532eee8db1d941165a8c990e8f2d583d922d72034ab791ad96f035a52b61ac082105a0e8774a18565de76f9fd5e130eac00c23324eceb0", "168", "129605e701e2049fcb76a85e080af544557320cdd82cfe4f22ff3d632e32ecd0346d427aab99f430b4fa150de69859240a9bc111e57281c34cc45bf0628fa5bd6a38528d8cfd12b09d24e82f7e73d3125ff55ef67eefe601e95b34cb6830d6532eee8db1d941165a8c990e8f2d583d922d72034ab791ad96f035a52b61ac082105a0e8774a18565de76f9fd5e130eac00c23324eceb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "878862bc699880e255e4cb078173f055901bd9b9e9a87286437bf803457dfef8738eb1a323646b768abf63cf39288d44317b204478e486224fec9496cc735b5608b9a0d6906e85120dfb80d857081bbabe56940426c9765730604c6d9bcbb75268a3de559e7b596b03f8913c5107689eeceb48f09a97d7c30ea4bcf713e56e2cc89df0b39dea9ba5a8832802152f5af444cb3ca1b0a", "b4", "878862bc699880e255e4cb078173f055901bd9b9e9a87286437bf803457dfef8738eb1a323646b768abf63cf39288d44317b204478e486224fec9496cc735b5608b9a0d6906e85120dfb80d857081bbabe56940426c9765730604c6d9bcbb75268a3de559e7b596b03f8913c5107689eeceb48f09a97d7c30ea4bcf713e56e2cc89df0b39dea9ba5a8832802152f5af444cb3ca1b0a000000000000000000000000000000000000000000000", .None}, + {.Shl, "-bbdf2afbac51f95f49169e50620bc46aecbbd2e6b9a73996f2fc934ccb76e77902cbd3ae415f5755fec869fd29fb135bb5b5be47a75ceee8e13100478fd257f6b5b4d494e1a4eeb865c6cd41e9609a371861cceaaa823863d804b05a735a09da787d747d86c9f120b5538edaba995d5351fed9201f2c1d34ea9507c285562816a652536bbf07a125994da912cb11a2bd494fef639259", "78", "-bbdf2afbac51f95f49169e50620bc46aecbbd2e6b9a73996f2fc934ccb76e77902cbd3ae415f5755fec869fd29fb135bb5b5be47a75ceee8e13100478fd257f6b5b4d494e1a4eeb865c6cd41e9609a371861cceaaa823863d804b05a735a09da787d747d86c9f120b5538edaba995d5351fed9201f2c1d34ea9507c285562816a652536bbf07a125994da912cb11a2bd494fef639259000000000000000000000000000000", .None}, + {.Shl, "-a1ecbb163431ab2379e25c82ff24e74c8a68935b134fafe4457f44c8d2031c8a9bac846c5ebd3aaad1ae7cdf05ffa10cad1b165857dd7bd26e19f1d47221f5f0b44ec73d3eb1bef4af6b354e685e3201ab75e6f4ac7ffc03d5601d26a63ff21cfd952409e372b89e28b654cfa5b286822703d5f5dcfe1fed34b213fbc38b720e85765af498cf5c9fa5c5911619e4eee1dc3256d75fc2", "f0", "-a1ecbb163431ab2379e25c82ff24e74c8a68935b134fafe4457f44c8d2031c8a9bac846c5ebd3aaad1ae7cdf05ffa10cad1b165857dd7bd26e19f1d47221f5f0b44ec73d3eb1bef4af6b354e685e3201ab75e6f4ac7ffc03d5601d26a63ff21cfd952409e372b89e28b654cfa5b286822703d5f5dcfe1fed34b213fbc38b720e85765af498cf5c9fa5c5911619e4eee1dc3256d75fc2000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "e350aaeb899d3dde1737e8864d4f94a0535772d1480ebeb04fba17a4b38afd19b63fc4d700504392e3c6966640d8651e56cbe2d23f0ca27bba62b94dd47348f935ecefe5ba946b8e0cda411b1e464aed7619bceba392701595771cf0a7c94d0c9031dee20c281f71790f0407dddd176ad3479e84a50861869774c9d88950e216229233ec710ec2887321e35698a1efa85cd045d454fc", "78", "e350aaeb899d3dde1737e8864d4f94a0535772d1480ebeb04fba17a4b38afd19b63fc4d700504392e3c6966640d8651e56cbe2d23f0ca27bba62b94dd47348f935ecefe5ba946b8e0cda411b1e464aed7619bceba392701595771cf0a7c94d0c9031dee20c281f71790f0407dddd176ad3479e84a50861869774c9d88950e216229233ec710ec2887321e35698a1efa85cd045d454fc000000000000000000000000000000", .None}, + {.Shl, "-283a4d2f5cc7f45d9cacb788a8c4a24d6dbad4cb2543e7f46dfbce23db4afd624385e9128c1e3f05f8572a20c2a2d5b879acfb873e7e7d081f5218ffa1078e6a2077139b72840b7d1f1048dffcd507d196e502d6e320fe541332522913e98e9c180a29f8d5b3410204252cacc114655695a3754a946b0cce46cc641af75ee9615d2e481b3d046839d1150200e18d14073b005500ef86", "b4", "-283a4d2f5cc7f45d9cacb788a8c4a24d6dbad4cb2543e7f46dfbce23db4afd624385e9128c1e3f05f8572a20c2a2d5b879acfb873e7e7d081f5218ffa1078e6a2077139b72840b7d1f1048dffcd507d196e502d6e320fe541332522913e98e9c180a29f8d5b3410204252cacc114655695a3754a946b0cce46cc641af75ee9615d2e481b3d046839d1150200e18d14073b005500ef86000000000000000000000000000000000000000000000", .None}, + {.Shl, "-242d4304153c0a713c03f3bcd73bd6cac7c0dadc2a0ac390f917611ae6b0c09f08661aea64ca64fae2b5ae06c5ed926330c50815f2b914ba4e2948ec35820cc9b49fc2acaeaecaea0815b0b48f66b5438513299974fff396b91deb751cd67a212ce1356e7edf206c26ecb5c5ad7c157fa8278f2f771d99f55e271bc8424f6e11b5af1b8a080274cb6ff037cb35a6ba2c699472960e8", "3c", "-242d4304153c0a713c03f3bcd73bd6cac7c0dadc2a0ac390f917611ae6b0c09f08661aea64ca64fae2b5ae06c5ed926330c50815f2b914ba4e2948ec35820cc9b49fc2acaeaecaea0815b0b48f66b5438513299974fff396b91deb751cd67a212ce1356e7edf206c26ecb5c5ad7c157fa8278f2f771d99f55e271bc8424f6e11b5af1b8a080274cb6ff037cb35a6ba2c699472960e8000000000000000", .None}, + {.Shl, "-752c725ed8b55238f568c74d6360f8ff857d7004395dc2fd7522c4eeb8ee12dea42ba0e24a24829b67077fedff3af70f7d15d151438d4d52d008d65a384d4ce67ac202c87fcbe4bd7051783de20fc17b2ce0e717a137e54392443664a5dad860431afab406ce1647db4dc52748b1748a8746c688c32bd2d36e180c693435fb8e5452397822db3eae3179bd6452ccaceae207f7996079", "0", "-752c725ed8b55238f568c74d6360f8ff857d7004395dc2fd7522c4eeb8ee12dea42ba0e24a24829b67077fedff3af70f7d15d151438d4d52d008d65a384d4ce67ac202c87fcbe4bd7051783de20fc17b2ce0e717a137e54392443664a5dad860431afab406ce1647db4dc52748b1748a8746c688c32bd2d36e180c693435fb8e5452397822db3eae3179bd6452ccaceae207f7996079", .None}, + {.Shl, "26b0b769569cee29836c78e5d2a3ddd209204b0b1c078ff9bd70b1a78bef59f51e20ede042098147045477416b647f49e907da0592d3e1924ba64b650e9c779ea78576583ad53cfaa09441ad0be6a5ee82eddc31d5ae493bcb3c55398d537a1488685bb8663af881c6c4c177047c67d7240c4deff002defd8dcbe6339eb67c1bd214716d1cd9e567c3a671685ff0b775bd164ccaa302", "21c", "26b0b769569cee29836c78e5d2a3ddd209204b0b1c078ff9bd70b1a78bef59f51e20ede042098147045477416b647f49e907da0592d3e1924ba64b650e9c779ea78576583ad53cfaa09441ad0be6a5ee82eddc31d5ae493bcb3c55398d537a1488685bb8663af881c6c4c177047c67d7240c4deff002defd8dcbe6339eb67c1bd214716d1cd9e567c3a671685ff0b775bd164ccaa302000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "9d4b87d4be552a7dccbe60079a3c51d35b37009baac13f15de6358603ab1334b82bcbd9a0965f6f31ec979c130c91c59a7843bd8e7cc47f633fe0b5bd41cd1979750dd7b52023b51d473ccb47f30d215af17039e880230d51a854c3b88cf4fcb7e946dd436c52d718e89f78ba9e0cba464ac575d86f159214c26a50de10c9f235758d47ea980e6c135a897d062993dd2e00765c0627f", "1e0", "9d4b87d4be552a7dccbe60079a3c51d35b37009baac13f15de6358603ab1334b82bcbd9a0965f6f31ec979c130c91c59a7843bd8e7cc47f633fe0b5bd41cd1979750dd7b52023b51d473ccb47f30d215af17039e880230d51a854c3b88cf4fcb7e946dd436c52d718e89f78ba9e0cba464ac575d86f159214c26a50de10c9f235758d47ea980e6c135a897d062993dd2e00765c0627f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "83ea2cfff8611356f4ca46ed0235384e0a5c904dd17a250e47d8c296324ddbcc1a74ac64414f0641554f47061af4cbfe768f774c25e4b68d0396508bf06bd4ef56045fee57a905081af79a41d0958064b696dd7c4844d7d8555db9900e8c4a34aa9c6e8190180949262c167b410d38953eceb126a30e7a2804f14a70729a25cc5989c2c250e7af1b434ae5bbbe82b3c211268ca57b32", "1e0", "83ea2cfff8611356f4ca46ed0235384e0a5c904dd17a250e47d8c296324ddbcc1a74ac64414f0641554f47061af4cbfe768f774c25e4b68d0396508bf06bd4ef56045fee57a905081af79a41d0958064b696dd7c4844d7d8555db9900e8c4a34aa9c6e8190180949262c167b410d38953eceb126a30e7a2804f14a70729a25cc5989c2c250e7af1b434ae5bbbe82b3c211268ca57b32000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e67b3013880c14877714a79f3a3f1cd6d69dbc73740ad68d5d71b631f6ff8b9dc1feb2671ce7c08b0103ff6756a90720962430f5b330b616fb8176eb46d72eb0a2940dd079210378a096e5ae560711395a907eb83328e186590434a12ea1467c036f8eed2ee484b5e66d5e615f605724634f38733c34f785a62d71341c97e485aa567759545728680994160170b066a29c398675baea", "3c", "-e67b3013880c14877714a79f3a3f1cd6d69dbc73740ad68d5d71b631f6ff8b9dc1feb2671ce7c08b0103ff6756a90720962430f5b330b616fb8176eb46d72eb0a2940dd079210378a096e5ae560711395a907eb83328e186590434a12ea1467c036f8eed2ee484b5e66d5e615f605724634f38733c34f785a62d71341c97e485aa567759545728680994160170b066a29c398675baea000000000000000", .None}, + {.Shl, "-d0b079291ccc8cfe14590687b055f674279e5295284fb95e4a81d4a0b427164693732fc5d6f661e30a4079650f20aba491c2ad95a262f14131568b4066a4ce562e0b4c5048d0600fce229fc36a8dc27613124e40da97000538702de500869a93c79fe30177540db370e24399ea601c0844131f92637ea2c15f44c4706ce7a9b9b7c4bea2c2d8cd56ab5ee2bc2d26d9fac89737795aa5", "12c", "-d0b079291ccc8cfe14590687b055f674279e5295284fb95e4a81d4a0b427164693732fc5d6f661e30a4079650f20aba491c2ad95a262f14131568b4066a4ce562e0b4c5048d0600fce229fc36a8dc27613124e40da97000538702de500869a93c79fe30177540db370e24399ea601c0844131f92637ea2c15f44c4706ce7a9b9b7c4bea2c2d8cd56ab5ee2bc2d26d9fac89737795aa5000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "c2a7310cce14c9f8c2a1a03d629a45f31f60053ea0ed9d3a4970e9c4a584d39d7657cb19eecbf84a9992fdd6db2e4af7c3c55ae2e44b5499aad204da869480e6956455332f30cdaef89dfe1f274c872fd2e6fb2972e4465b60c511983d41513fcee2f492d55ccc06a586e365265f07c8c06a1280ed6c2d016c55a9da7cdaabd94fe8d28720e93ed50fa40e7aec724396f6ec8bd15dad", "258", "c2a7310cce14c9f8c2a1a03d629a45f31f60053ea0ed9d3a4970e9c4a584d39d7657cb19eecbf84a9992fdd6db2e4af7c3c55ae2e44b5499aad204da869480e6956455332f30cdaef89dfe1f274c872fd2e6fb2972e4465b60c511983d41513fcee2f492d55ccc06a586e365265f07c8c06a1280ed6c2d016c55a9da7cdaabd94fe8d28720e93ed50fa40e7aec724396f6ec8bd15dad000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-9a0585a3faac31552b56f2d77ef0eed4da3a7460050f37eb1957b7c5a9bc43abe3d254dbd21c4b70b9e2d3381ee8b005c456f6f6463f40182810befe56c9b7e4767d7f5f7639555f5a67c431b52e8b91f5fecfc6989e28f45bc121262a1a52262f1d220009abe8b6a495716ba1f72e4bc114ccee9be19d9afd67bb422489b23c11e0f3b8577ea18bac73ca036a81f411421dffb3412", "78", "-9a0585a3faac31552b56f2d77ef0eed4da3a7460050f37eb1957b7c5a9bc43abe3d254dbd21c4b70b9e2d3381ee8b005c456f6f6463f40182810befe56c9b7e4767d7f5f7639555f5a67c431b52e8b91f5fecfc6989e28f45bc121262a1a52262f1d220009abe8b6a495716ba1f72e4bc114ccee9be19d9afd67bb422489b23c11e0f3b8577ea18bac73ca036a81f411421dffb3412000000000000000000000000000000", .None}, + {.Shl, "-88ceaefd36dcac55c4542a53537cb1961645b1194817c9646371e1b054e1aea1afdc9748367bf7c1339b842c53d4b567aecb72e56585436cbb05499f9ef979b771f3bb0056d34dc33f0469f0c6369643815e994c118b51c25a7bdb17c4208573f3e8ef49758e8981f8c7488324d67065e3ae439e7229c76150501ff59057415ec4d368e087ae55e5893d97a08e9adca45db915bbe86a", "1e0", "-88ceaefd36dcac55c4542a53537cb1961645b1194817c9646371e1b054e1aea1afdc9748367bf7c1339b842c53d4b567aecb72e56585436cbb05499f9ef979b771f3bb0056d34dc33f0469f0c6369643815e994c118b51c25a7bdb17c4208573f3e8ef49758e8981f8c7488324d67065e3ae439e7229c76150501ff59057415ec4d368e087ae55e5893d97a08e9adca45db915bbe86a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-eabcbb2e2a0d73526b33dad70db2ce51873ad528454ca3e3d430f109cebb3201ea86e01bbd1a0fe274f149918f828574a6d5cc62fbd0af2ad5d6e0048c5deb9632f1edaefe07d852206039d0c9f9c7f184490f17883a67cfba61877e90a2daf2aeba30e12fa8f2c5f98c3457a46227e2efb5eb86f986d3fb53adfd2fec7375adbde1680bb555c290788bd4340e5c208129cd2ac61bd", "0", "-eabcbb2e2a0d73526b33dad70db2ce51873ad528454ca3e3d430f109cebb3201ea86e01bbd1a0fe274f149918f828574a6d5cc62fbd0af2ad5d6e0048c5deb9632f1edaefe07d852206039d0c9f9c7f184490f17883a67cfba61877e90a2daf2aeba30e12fa8f2c5f98c3457a46227e2efb5eb86f986d3fb53adfd2fec7375adbde1680bb555c290788bd4340e5c208129cd2ac61bd", .None}, + {.Shl, "d1a87885175d14470f358e3298c7e9b59241c972c79f1b33bcea3e1c078566e76d6fb306297b79e21114bab2ae528d4d767eb9c92cada2f143cf7cc3e7954c62c6ca1b88f8145a0923dcee66eab5a7b1798de135467b92f0cd4a924e06b0394f9409892ed995c7a25c41a6167dbb1b0d125ec67feedd6eb7f15c14180ac116df18dfc48c88c5c408b273d3755126a8113c7adb12af41", "1e0", "d1a87885175d14470f358e3298c7e9b59241c972c79f1b33bcea3e1c078566e76d6fb306297b79e21114bab2ae528d4d767eb9c92cada2f143cf7cc3e7954c62c6ca1b88f8145a0923dcee66eab5a7b1798de135467b92f0cd4a924e06b0394f9409892ed995c7a25c41a6167dbb1b0d125ec67feedd6eb7f15c14180ac116df18dfc48c88c5c408b273d3755126a8113c7adb12af41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-87d4503a248b178c7d5538a43dbf3b029c31156f162e2df94b455d7c591dff9b367ee829bdfd81d4afacd28e9254252a2baefe961ba328edf3207f3f5944a31ed400ebdb73a55bd35f93f61883911b1f298c3baba071a3dbb5fcf8540788971d175db449037b148db57c4b56bda1c5385fc3f432eb0a4a6a62fa8e05f8813e6eb0b4489a86153d952dfac0224cf96700e4b28567ea72", "3c", "-87d4503a248b178c7d5538a43dbf3b029c31156f162e2df94b455d7c591dff9b367ee829bdfd81d4afacd28e9254252a2baefe961ba328edf3207f3f5944a31ed400ebdb73a55bd35f93f61883911b1f298c3baba071a3dbb5fcf8540788971d175db449037b148db57c4b56bda1c5385fc3f432eb0a4a6a62fa8e05f8813e6eb0b4489a86153d952dfac0224cf96700e4b28567ea72000000000000000", .None}, + {.Shl, "34ff3e9109b6994b56632e0dde9f78d4d48fdf388c80d2b14ab778b5b63db57ef4a2fa124876833d45fb70c15243c809f85de4096caa1a9dfa96d61ebf85730da5e22a26c0cd118086779e740159de6f10fe536705bae602501d04e0dd8c7954673f32ea41368283ec6824ae11615a48c8e3861f3dc52e783f25dd78b52b3d99dbdffa5566d63d9efb1ecfe5b5fd7a745bd83f400250", "78", "34ff3e9109b6994b56632e0dde9f78d4d48fdf388c80d2b14ab778b5b63db57ef4a2fa124876833d45fb70c15243c809f85de4096caa1a9dfa96d61ebf85730da5e22a26c0cd118086779e740159de6f10fe536705bae602501d04e0dd8c7954673f32ea41368283ec6824ae11615a48c8e3861f3dc52e783f25dd78b52b3d99dbdffa5566d63d9efb1ecfe5b5fd7a745bd83f400250000000000000000000000000000000", .None}, + {.Shl, "-950e5a4cf31cd9b86bdd7e2aabca436405aaeb671119f7994abc7c1745413296537d68a085a43a1901cff668be82fd340e8c4a86a97b8a6db617f795711ca7fa5ce07c7c4837da7be653dd16ae35598610a140826f2bddc23dbc6f3ccd7d802173735b7346e5a664e1c658fd65aca15bedad671173cb6830e83b8817075f3359fb93e22e021dc0f1b974294200b6d800835ca6c3a31d", "258", "-950e5a4cf31cd9b86bdd7e2aabca436405aaeb671119f7994abc7c1745413296537d68a085a43a1901cff668be82fd340e8c4a86a97b8a6db617f795711ca7fa5ce07c7c4837da7be653dd16ae35598610a140826f2bddc23dbc6f3ccd7d802173735b7346e5a664e1c658fd65aca15bedad671173cb6830e83b8817075f3359fb93e22e021dc0f1b974294200b6d800835ca6c3a31d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "f7a12cd63e5b1f9dc2e527be1194dae9d37cc37871c006094f456381c9f7fa6fc5b56849863e325cbafc16b5abdb931b868fe7c28509a47c5e59604bf28ebc898cba97d7b5a57142abb5624f792bf96cdcad1d07ca05fd59242e12dfcfe2f2a7c6da50d3f035127b2c5126da329e617a5a3dc88d87b3887ff5430ebfa1c85c5fc0fca09a52be1b17b6789c12f37628922c8bfa39282e", "b4", "f7a12cd63e5b1f9dc2e527be1194dae9d37cc37871c006094f456381c9f7fa6fc5b56849863e325cbafc16b5abdb931b868fe7c28509a47c5e59604bf28ebc898cba97d7b5a57142abb5624f792bf96cdcad1d07ca05fd59242e12dfcfe2f2a7c6da50d3f035127b2c5126da329e617a5a3dc88d87b3887ff5430ebfa1c85c5fc0fca09a52be1b17b6789c12f37628922c8bfa39282e000000000000000000000000000000000000000000000", .None}, + {.Shl, "-1dd769103c1eff338e21b7eca4912c5ffe407f4002beb6aede180dd54c19f245f0fb439e75bd0ec64ec74653680a11c2302f0e09e0f7147b5c1ef2d66bd8d7b538823d823bf72e27cd47cad59f6b1b7fa9ff79a4fb0e3a2b9d7d6e9637b4a502eb3db0fcb5c2f7224df1c47053bc3c700e2ce6341af69fd7e798e58cb1789765934060cee12e7dc42c8fb3fc8c4da04a1be99a7b0b6d", "1e0", "-1dd769103c1eff338e21b7eca4912c5ffe407f4002beb6aede180dd54c19f245f0fb439e75bd0ec64ec74653680a11c2302f0e09e0f7147b5c1ef2d66bd8d7b538823d823bf72e27cd47cad59f6b1b7fa9ff79a4fb0e3a2b9d7d6e9637b4a502eb3db0fcb5c2f7224df1c47053bc3c700e2ce6341af69fd7e798e58cb1789765934060cee12e7dc42c8fb3fc8c4da04a1be99a7b0b6d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "7047b7bdb70e495b1b437aa0dd832925a73205a6c25c6ce6a7864604bd244782d2d16a920deaccbdf54b707ad6b9975b21d0dad9d718fe690bd9d8fc43b44b4c973976b1317105f462eb3440cdd00ffcc90a906c879ee58a86968021daab879b32d00a9bd131c1c556bee01b4f113a0c3e231fa4908c6378621d17019ce3a60267f6d3819f8e7b624d37aa4b2b19da3e2e78aeba1c9", "168", "7047b7bdb70e495b1b437aa0dd832925a73205a6c25c6ce6a7864604bd244782d2d16a920deaccbdf54b707ad6b9975b21d0dad9d718fe690bd9d8fc43b44b4c973976b1317105f462eb3440cdd00ffcc90a906c879ee58a86968021daab879b32d00a9bd131c1c556bee01b4f113a0c3e231fa4908c6378621d17019ce3a60267f6d3819f8e7b624d37aa4b2b19da3e2e78aeba1c9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "1a507a041f8d14d77f7ec6568715c771af46f881834a93db69f2c3869dafeb9eb4d524b5fe209b2462e34b6ceac047a8e7b24580b4dd4e6af05f2e50a66db00b8eb27d595a42f9bf48ba1b4fececacbfed874be4e0257b3ff9dcc0f4f2b23dd4bb15a52c8ddb1f00c1aef38a5cee77cb5df859afadcc0df870c260bf5ea5c960fe8a3b08f002932527390306404e2a9ec3c9e8291e12", "21c", "1a507a041f8d14d77f7ec6568715c771af46f881834a93db69f2c3869dafeb9eb4d524b5fe209b2462e34b6ceac047a8e7b24580b4dd4e6af05f2e50a66db00b8eb27d595a42f9bf48ba1b4fececacbfed874", .None}, + {.Shr, "60b77fd652d876948d45c044737e06a6583e05862aa23138e26a1bafb7c4c78129e68a787c91c4e9d32b51eab386e52ef5a930bf137c50fb9fc9d41d98b6120381a2b7141c5bd07bac642b03b49a430ac624ed3670a050949357bc108dcccfb93d3c75e0998d10f56dcfe987299ba7397bdc11df2150ba88740ebebc879b6709074b19d59e08db3a7b8863f5dec74ada32a0ed3976f4", "12c", "60b77fd652d876948d45c044737e06a6583e05862aa23138e26a1bafb7c4c78129e68a787c91c4e9d32b51eab386e52ef5a930bf137c50fb9fc9d41d98b6120381a2b7141c5bd07bac642b03b49a430ac624ed3670a050949357bc108dcccfb93d3c75e0998d10f56dcfe987299ba7397", .None}, + {.Shr, "178625098edb65c8b3e9998b1d8896957c7e1fc7db94beafe23da53cc0904f74ae971502b6e297ceb37d59d0e479a07c23b21d5b4dd94cb2e39a5ff0dcd6ee6a45503362ad64ff019125ae4e4297be8cd00de4018f8ce38b3cdcc610109db21f5e95e21c57b83d5b186aa10c392b68794d1f11707c589759d0bfdd72ae87ca5ebd84845f2471fab4e116d1da5a3ad90b8b5a92c4d632", "f0", "178625098edb65c8b3e9998b1d8896957c7e1fc7db94beafe23da53cc0904f74ae971502b6e297ceb37d59d0e479a07c23b21d5b4dd94cb2e39a5ff0dcd6ee6a45503362ad64ff019125ae4e4297be8cd00de4018f8ce38b3cdcc610109db21f5e95e21c57b83d5b186aa10c392b68794d1f11707c589759", .None}, + {.Shr, "efbfd55a38b0c9972db2d78bf01503c9fdda76b83c791fe34ed15776310d04ff9296057a005f56adc968a5dddb37b44c9fccfd8c8a1fe3e97b992ee7ab44924d540f43162b610ca17c836ad59b1d447038a61815bae697e151bd9a6bcd447cfbf6d4ceb9818d4edbc5f2ec62d040463fba60a36ca657e1020e52b7c08918adb3209b0a302a4ecb7c193ce9e87e99ffe2de76aff00fef", "f0", "efbfd55a38b0c9972db2d78bf01503c9fdda76b83c791fe34ed15776310d04ff9296057a005f56adc968a5dddb37b44c9fccfd8c8a1fe3e97b992ee7ab44924d540f43162b610ca17c836ad59b1d447038a61815bae697e151bd9a6bcd447cfbf6d4ceb9818d4edbc5f2ec62d040463fba60a36ca657e102", .None}, + {.Shr, "37a97651516b27a29e87bbb018ea8307e0d6a1e838b36299f1c7d0781c71219dff735eb74953903fc62dcf9e92778d6d2d966a9b218d59b602161d99b884ce1bc77aa711910b9156fc399a84abf32791ba562bb0f7bf9d05ff52be4dd169889d0345a4b83e0bbe871367f7f6fad32af36508269f21b509794db10e2612aa32888f194155fc604a72b4575c97f119096281e78ce3fbd7", "78", "37a97651516b27a29e87bbb018ea8307e0d6a1e838b36299f1c7d0781c71219dff735eb74953903fc62dcf9e92778d6d2d966a9b218d59b602161d99b884ce1bc77aa711910b9156fc399a84abf32791ba562bb0f7bf9d05ff52be4dd169889d0345a4b83e0bbe871367f7f6fad32af36508269f21b509794db10e2612aa32888f194155fc604a", .None}, + {.Shr, "a39d3f58a9f65f88d29e83602d2b78cae9457bb5898280c1f3dd602ce069f36371a6c77d2be7becbac87afe5d9d0be467009f795a66da430084679a73e8148a7b9747fe9d9883dc830521555a69349e5e088d42807bcce2db009926de87bc3efd7c8ca148be0fbf4d5ee4b86a41ea0f1ff58fc15d11d7aea36e44743b1db6c513c0dec67031683d57cc32052fa77224d28af3eb3fdcb", "21c", "a39d3f58a9f65f88d29e83602d2b78cae9457bb5898280c1f3dd602ce069f36371a6c77d2be7becbac87afe5d9d0be467009f795a66da430084679a73e8148a7b9747fe9d9883dc830521555a69349e5e088d", .None}, + {.Shr, "7d055ee58b307c72a57f0f015c21093419cb630c55c1d600fb1bb7a3aa688bdcf254479b4ffb819ae8469fc06317063d367b67e382729b1a2819331fab27cbb7ade5d1626e9924f8a4c24a9172347db78a673a7bf270edc54d2820d6f708dbb5d2f4f818a24f1550b4a439e71a837675dbfde6fe7c3b94b39f731c8c24ba156ced6b1682cb53ae78d70ed0cbc5e3ba8f9d0f32496978", "78", "7d055ee58b307c72a57f0f015c21093419cb630c55c1d600fb1bb7a3aa688bdcf254479b4ffb819ae8469fc06317063d367b67e382729b1a2819331fab27cbb7ade5d1626e9924f8a4c24a9172347db78a673a7bf270edc54d2820d6f708dbb5d2f4f818a24f1550b4a439e71a837675dbfde6fe7c3b94b39f731c8c24ba156ced6b1682cb53ae", .None}, + {.Shr, "e7b8feac688f1d59150bd06fe345ca648e2b2aced515b3dbed9d831925c4b07c9da25bd41edddcbff58d9ce4b14526f55d8a6f42cf40fb2e042810217bb28fc4443afadb91c6bf8dad0d2fca0b1cd10aff81fdb776936f3ecc5d8e731ff92bdc5eec2bfcb15b33ced058e00ac831880374e29ebdb49761b0bbf074a0ad6046a712ddaf474e27cb0057aef1a382a01cad054c37be686", "168", "e7b8feac688f1d59150bd06fe345ca648e2b2aced515b3dbed9d831925c4b07c9da25bd41edddcbff58d9ce4b14526f55d8a6f42cf40fb2e042810217bb28fc4443afadb91c6bf8dad0d2fca0b1cd10aff81fdb776936f3ecc5d8e731ff92bdc5eec2bfcb15b33ced", .None}, + {.Shr, "90fd773dd0d300a9b06762db765ca4bca6ae792995e7e4a504d069760e9d36d3aec9071ecc424828d3575e71d918bb2588a975dde5862d80f87c9cd39953e20bb72b4eb37e31e3f0a80f9ca0c6462ac50400ea0d6b6fea89689fa1a97ddbdd8ab7644637893deb91942bd345232bc97d33dd5073bde8f635181693ae982325985f187ea102a30303ecf59e54aeb51f86e1d78a5c5329", "b4", "90fd773dd0d300a9b06762db765ca4bca6ae792995e7e4a504d069760e9d36d3aec9071ecc424828d3575e71d918bb2588a975dde5862d80f87c9cd39953e20bb72b4eb37e31e3f0a80f9ca0c6462ac50400ea0d6b6fea89689fa1a97ddbdd8ab7644637893deb91942bd345232bc97d33dd5073bde8f635181693ae9823259", .None}, + {.Shr, "17e318dcd167175fe1d0cae0e47988b382284e07e3c3c6393d84eb9b3e08dd23821b156c9b9572241222c0b687ef7df9b7be12584842a391a97fe3b3aab4361bb32f310419f1f5ac76bc3e1c6ef6bb273ad3d98b67003fc2e576736d05bb6a84b4aef8cda9032da715fc0e1d16fab097b7b21ad2dd1e7e06e2fc2f3171612b8181de5dbb5d5126847846cc94c5c24c5431ec083a892b", "b4", "17e318dcd167175fe1d0cae0e47988b382284e07e3c3c6393d84eb9b3e08dd23821b156c9b9572241222c0b687ef7df9b7be12584842a391a97fe3b3aab4361bb32f310419f1f5ac76bc3e1c6ef6bb273ad3d98b67003fc2e576736d05bb6a84b4aef8cda9032da715fc0e1d16fab097b7b21ad2dd1e7e06e2fc2f3171612b8", .None}, + {.Shr, "fd4a645c2b7afb161afaf18516a6c8e58d92a0199dc3040e3cbf5c656f3564ce85c3c0ca182b57a4a7b1fe9d82ca90f4bef6702ed0b6c5ecd17ab3cbeef1129811d30c04d7832999dee4f2fddb5e05778dd6fbca702872265e53d727da4e55cf47b2cd62a78b25e5df0f5c70bcaf9b53eec3b697234a78d9ddc3ff7868e801e5927eb8e78215a27ea557afe9e512d4b12e255cfd78c0", "21c", "fd4a645c2b7afb161afaf18516a6c8e58d92a0199dc3040e3cbf5c656f3564ce85c3c0ca182b57a4a7b1fe9d82ca90f4bef6702ed0b6c5ecd17ab3cbeef1129811d30c04d7832999dee4f2fddb5e05778dd6f", .None}, + {.Shr, "1b9106e3cba598fa78335ed23c649eab0a96e7f36a0f9a7244ebc960649a0e82634c7648560d3b67452bd7bcb600a41969c4138351bbbd2baca87b2149a9ef96886f32620ca6ca0742e3fd5ff75e9f639d43d9e1a3ececdd7cbbfbeb92a2c7a9e417fbac246e17279878c06972494ffee756c34b037dcdab9de9c1d79392fab575ac0ab6a2bde8ceb65245175793a37698d0a3e79d16", "168", "1b9106e3cba598fa78335ed23c649eab0a96e7f36a0f9a7244ebc960649a0e82634c7648560d3b67452bd7bcb600a41969c4138351bbbd2baca87b2149a9ef96886f32620ca6ca0742e3fd5ff75e9f639d43d9e1a3ececdd7cbbfbeb92a2c7a9e417fbac246e172798", .None}, + {.Shr, "2f421664f54a2e62e9de2b67c978fdcbd40741a2ca6a45149bd77260972a358fa19b53fb3db385a372feeccd884e2b90387b93cf5e88d5c07d7083a2cd723a0ebd01d76558c8781f20fedf0160bf94824e4466868c9f74858d4a7eb3beab7a0d998ad1d74eb4c5486531dec36ce304593423933d32a5b15964750c7eb5b47d76390f0c03ba11904d6710acd8d580aa78a9d160f616af", "0", "2f421664f54a2e62e9de2b67c978fdcbd40741a2ca6a45149bd77260972a358fa19b53fb3db385a372feeccd884e2b90387b93cf5e88d5c07d7083a2cd723a0ebd01d76558c8781f20fedf0160bf94824e4466868c9f74858d4a7eb3beab7a0d998ad1d74eb4c5486531dec36ce304593423933d32a5b15964750c7eb5b47d76390f0c03ba11904d6710acd8d580aa78a9d160f616af", .None}, + {.Shr, "6893682d84afb1ab91e526c5dcf69b42356787a09930a9037c55f95ace20ee99be2c62518ee39259eabf958ee3efc3a76ac5c04b427d163557e01f880291025a34ecfcad598b31dddf6512d8643997a6b2e721acf4ef336209b1049626b37795a5fac19dbd8443b2553e10b386dfb0d656e02614c74e8df8d3a75eb08fd8169f68dd46f8ee9cc079ef6872af7e9453088027959ccfc5", "1e0", "6893682d84afb1ab91e526c5dcf69b42356787a09930a9037c55f95ace20ee99be2c62518ee39259eabf958ee3efc3a76ac5c04b427d163557e01f880291025a34ecfcad598b31dddf6512d8643997a6b2e721acf4ef336209b1", .None}, + {.Shr, "449d6bea693ffb2d18c7060117a4c890aa78f95ba4edf2d5a439876cdfb1f7abd83060d0a0b572b01cfec65fd50fc5829dee767e2f1bf9bbedee1aee97320f15b04ed0967cb7e76d462b53d63bda0d2cc19e61e8aaa049280cd655ceb9b884ef8f0468e5e7d2842df7cb7cccefdabf6747a1eca79541e056ca7e0adc57edf38c3484867bfc72e25663045dea292de2b61f58d63160a5", "21c", "449d6bea693ffb2d18c7060117a4c890aa78f95ba4edf2d5a439876cdfb1f7abd83060d0a0b572b01cfec65fd50fc5829dee767e2f1bf9bbedee1aee97320f15b04ed0967cb7e76d462b53d63bda0d2cc19e6", .None}, + {.Shr, "9740ecf550d787b0af6e699d06f8a46b9bfc191b7e9276fb59dddf05fb392a8a9810457af666d97ea8aad835455c1ea59994b32782e09959a5c96ed82df015380f43ce8fd5f306c25014ff09920349b54679f744434f24a499d29e248a681395a572b89b1e8ed8c744c2b73c8d5719a1c31e7c8d698de8c5c930c9d04eb9bd7a43f3403804a445f144d7b73af2350c011962dd10a4ef", "1e0", "9740ecf550d787b0af6e699d06f8a46b9bfc191b7e9276fb59dddf05fb392a8a9810457af666d97ea8aad835455c1ea59994b32782e09959a5c96ed82df015380f43ce8fd5f306c25014ff09920349b54679f744434f24a499d2", .None}, + {.Shr, "b818127a903d16c68fd4cf9c7d05cb350e3d9a1e73040d4640e09c021660b51655bd714c1271d459ca6cc814630e1dfc7ef70d884ea8b860d4342e3388c39a6816c0ec7dcae9d280d32d0fab13f3d45c8f34426aed9ef214dce30504d2dd3fead99d32e740ab9698afbdae397816751abb8aaf2b2dfbab702545a02b190809295184ff56d051977b16bdc4211083fce16894302e6402", "b4", "b818127a903d16c68fd4cf9c7d05cb350e3d9a1e73040d4640e09c021660b51655bd714c1271d459ca6cc814630e1dfc7ef70d884ea8b860d4342e3388c39a6816c0ec7dcae9d280d32d0fab13f3d45c8f34426aed9ef214dce30504d2dd3fead99d32e740ab9698afbdae397816751abb8aaf2b2dfbab702545a02b1908092", .None}, + {.Shr, "69e6df7a389918c3e57364768645bdf8ad8343c9c6f0444e6728e4eca0cfd8213ae91af2a9c5ec4779c3f8f26b36d2bb04c10569ff1ce580d72569fd68063807445b09bcef698110f2d573bebec609031f39460570b24d0158879aac7c9df853e35566148634b529694c770a83dfa14542c9c977c1fb954cac8161dc227895075ce1488deec1a7d35fe3cb205e0740dd036c748d4e89", "258", "69e6df7a389918c3e57364768645bdf8ad8343c9c6f0444e6728e4eca0cfd8213ae91af2a9c5ec4779c3f8f26b36d2bb04c10569ff1ce580d72569fd68063807445b09bcef698110f2d573", .None}, + {.Shr, "4e87de8a82e441d3f29e4fdcf7d3ca0ee55735cf0cf27a496e9e7540d729c625450851177b0d9fac429576ad521d4a57add8578f0d99c5f228ee53dfdc9ca505db571307cd1aad88d83bd429805445f9791c5218d5bbb5442e72698aaa205f8965c299de3dd61fbbb6befb6c6febd01e9f937e0a55fb8a564a6e1a9e7476c5a4e1f3809e28af72a639d35de1bb06ac03f08dd583a228", "3c", "4e87de8a82e441d3f29e4fdcf7d3ca0ee55735cf0cf27a496e9e7540d729c625450851177b0d9fac429576ad521d4a57add8578f0d99c5f228ee53dfdc9ca505db571307cd1aad88d83bd429805445f9791c5218d5bbb5442e72698aaa205f8965c299de3dd61fbbb6befb6c6febd01e9f937e0a55fb8a564a6e1a9e7476c5a4e1f3809e28af72a639d35de1bb06a", .None}, + {.Shr, "44aca49193d1a7bb20246272df234320ab14080633d7ae1e46668daa82d0034ddd13f47b21172d801b44a532080cf0df5fa41758e109665064a5bdbfbc00af112f4de2bf48970af20d17b11687291b638456d7de6f75908d38e5f3ec371e82750ab92ec34cdbe1853975e4d501b500ba496de80999f5bc128a0879fb9942bb1adf03e9be6c77579a8d4fc69088329f2eb15f812392a2", "258", "44aca49193d1a7bb20246272df234320ab14080633d7ae1e46668daa82d0034ddd13f47b21172d801b44a532080cf0df5fa41758e109665064a5bdbfbc00af112f4de2bf48970af20d17b1", .None}, + {.Shr, "c9d465882b59c0167e86e7b365a9af61af459833f6ae4a0d26318625371d0d69c4a0d983c603c41c23bb147a73b68a18c97289e118359b97fbf8f5040153ee81c18016228cc52b13a1f2be457c3162c0a83ddbc0205052b6d33bfcae3e2d2ec9658fcfa656cd89e8c57bf2ed4af02c38a1caff9b8abca6173d021e638c5b68c11cf82468bf6941530338c8dca0e4485d45b49ed1f6a", "78", "c9d465882b59c0167e86e7b365a9af61af459833f6ae4a0d26318625371d0d69c4a0d983c603c41c23bb147a73b68a18c97289e118359b97fbf8f5040153ee81c18016228cc52b13a1f2be457c3162c0a83ddbc0205052b6d33bfcae3e2d2ec9658fcfa656cd89e8c57bf2ed4af02c38a1caff9b8abca6173d021e638c5b68c11cf82468bf694", .None}, + {.Shr, "9d3235e7e5f6dec4b97d1c1d8ec2e6378d0c073daa4db239eac4e30aa8cab75481aae91d38471d298e0902c3c23f5cee479a8c9c138919652b7daf19f6c282e7504a39d95023f40a05db9b7fbb68cfaf6d353663acc015b653877f809d54f6a4850fa9c788e29cc6f045d4eba04b75bd9d589032bb85f4f86ed2005c18fa4fbe3ef22cb01f6e7bcb94af0bdbd2809e4941572e9b9b2d", "21c", "9d3235e7e5f6dec4b97d1c1d8ec2e6378d0c073daa4db239eac4e30aa8cab75481aae91d38471d298e0902c3c23f5cee479a8c9c138919652b7daf19f6c282e7504a39d95023f40a05db9b7fbb68cfaf6d353", .None}, + {.Shr, "61a5e1803b518783df1eee710fa3c98cb49afbec1f0100c760d96679e093ac8d99bdd067154c7ec439d9f5fb8d91d0df774e778c1275c1ffc693e66189a59d82530ec34e24468a3ec1b0477b5f237c5cd01cf7cafd61c1a5b97ad311ab9029888cb45a74787975f7c5d925eeedd136849eeb08a64a27aedfecee3b80bd36edcb82dc02291d692d9d688faac44937153c51acd928d0f3", "0", "61a5e1803b518783df1eee710fa3c98cb49afbec1f0100c760d96679e093ac8d99bdd067154c7ec439d9f5fb8d91d0df774e778c1275c1ffc693e66189a59d82530ec34e24468a3ec1b0477b5f237c5cd01cf7cafd61c1a5b97ad311ab9029888cb45a74787975f7c5d925eeedd136849eeb08a64a27aedfecee3b80bd36edcb82dc02291d692d9d688faac44937153c51acd928d0f3", .None}, + {.Shr, "de2480ddcf32d0455d9f7b55ae0db3bc89ba48cf31fbfe017ce7156495b887a30f30f1247733c52273c5dc7797789cba14b8f9bed297d6042b3b89f69ef78821019d18827140c06b8ca32f83dfbbfc0bfc156dd90357d020e7fa8d5365e40100f125802711f7e60de556303071afe72a313bffee914612f9c6ef370aa712ea8f47cbd6a36d995926bdab06e0ec6b81ce47fed70cd222", "1a4", "de2480ddcf32d0455d9f7b55ae0db3bc89ba48cf31fbfe017ce7156495b887a30f30f1247733c52273c5dc7797789cba14b8f9bed297d6042b3b89f69ef78821019d18827140c06b8ca32f83dfbbfc0bfc156dd90357d020e7fa8d5365e40100f12", .None}, + {.Shr, "f2fa5db645e05d1c11ebdf9e1c50d0ba5c63c3c74f1455b49cc50238be7d9639a9f6f4394ca06cc60cd155de3f88a019b95c81f5a4bd4d3db5211b7073e1d5cf83fd374bd9a1bb66b93ba880b903a3b233ac0b5f744c9ac3804bcc357930cc2fa679e9d0ad3378587b00ce7fd9df10f02e9c175d2134b8dd30a7505d972b45c1c55f0132c9fa70843800633b7c1cd9d540443c80867e", "1e0", "f2fa5db645e05d1c11ebdf9e1c50d0ba5c63c3c74f1455b49cc50238be7d9639a9f6f4394ca06cc60cd155de3f88a019b95c81f5a4bd4d3db5211b7073e1d5cf83fd374bd9a1bb66b93ba880b903a3b233ac0b5f744c9ac3804b", .None}, + {.Shr, "f59b58a8ab662d9b5e61b9ccac42590bc96dfc1f2775a1da48f10172ed6baf0e2171dcafba52589843bcef161704ba411add42280da75d491072db04f4d684e074d4fad41b9992588bdfe81fe96670dd8f39305b8a3caaa8bdb5b70417ff8ab4191e9ee134c12771c4468e8d7273487e9c6a3bd2707172605b46fcb332616d526a1467a852f03d3e7dd96320cff60ffa9dc6f7fc43c2", "12c", "f59b58a8ab662d9b5e61b9ccac42590bc96dfc1f2775a1da48f10172ed6baf0e2171dcafba52589843bcef161704ba411add42280da75d491072db04f4d684e074d4fad41b9992588bdfe81fe96670dd8f39305b8a3caaa8bdb5b70417ff8ab4191e9ee134c12771c4468e8d7273487e9", .None}, + {.Shr, "ac824a97848004bcf4374f888e5215cc2d3cbf75fc5eb1edb38bcbd56121274844df0897509cda63d5ea4cb9d62d068b60bb393cf3eea838b235fa18ee26c6c10f977c2f3549c377ce0590e9799b104fd4a85d2917639a81b039627f25c9a8acac35dec9c345802778a18122e69e5e3f9c6758c4c5f5b795c35cdd19782a2b744c9ef8a288f1187e315534e28cdb27f75bd6301ad89f", "0", "ac824a97848004bcf4374f888e5215cc2d3cbf75fc5eb1edb38bcbd56121274844df0897509cda63d5ea4cb9d62d068b60bb393cf3eea838b235fa18ee26c6c10f977c2f3549c377ce0590e9799b104fd4a85d2917639a81b039627f25c9a8acac35dec9c345802778a18122e69e5e3f9c6758c4c5f5b795c35cdd19782a2b744c9ef8a288f1187e315534e28cdb27f75bd6301ad89f", .None}, + {.Shr, "5c3e0f7b7d9005357f2ab2f0c54387ea27bda76cbc22df05f5c47695a8ab4c29cc321a20c80400684f977d38ce26ef237e0d82538aa8b0193d1590955de4b95ea0b0c901798665e8302836cc2af6b3f0d68c32d9c5f60468abd42efbba7a9ef0b8d9abd53988176e64f50652d25e9b98b85f2628dd0b4759a310f693db9fd52dca8d3b4d2485b9ff918e90ab0ed95f5020bf309efa0c", "78", "5c3e0f7b7d9005357f2ab2f0c54387ea27bda76cbc22df05f5c47695a8ab4c29cc321a20c80400684f977d38ce26ef237e0d82538aa8b0193d1590955de4b95ea0b0c901798665e8302836cc2af6b3f0d68c32d9c5f60468abd42efbba7a9ef0b8d9abd53988176e64f50652d25e9b98b85f2628dd0b4759a310f693db9fd52dca8d3b4d2485b9", .None}, + {.Shr, "1b2372056ce329ee8b6128ef62b60c5e566667e241e1ce8371aaab68be150800a31ba9f02007886748b43d7e548c804a28df5b4b00d2b3149feb6492aa5dacdce52b480d68000e3c2ef0a959502e02ed02fc747644e2d2329d1bbf99f23bb711915cbb47ccb23281253435d77f97298f1dc8a3d341685ea643a541131e193a320bac6e8c0af46d8c0aae81c11fcbfed290940e1cea4c", "b4", "1b2372056ce329ee8b6128ef62b60c5e566667e241e1ce8371aaab68be150800a31ba9f02007886748b43d7e548c804a28df5b4b00d2b3149feb6492aa5dacdce52b480d68000e3c2ef0a959502e02ed02fc747644e2d2329d1bbf99f23bb711915cbb47ccb23281253435d77f97298f1dc8a3d341685ea643a541131e193a3", .None}, + {.Shr, "c55821838f29cba3376060145d56a50380d69a96d0688536cfa952c4fb74e111ad50a218852fda9a52b2a66b4f1ea6eff0316e31f949e60c8e2fd915aa8ca1495e6b6c806bfe3deeeab695872d84e069da42e8e92d33c7c2e11e9fa429e45112772f0718a1c45edfc899ab9307ebb4e8fe00daab2d1ae7e3d884293c99e635344e10eef33edc0c936955c31a54319989a6d54d7d4319", "258", "c55821838f29cba3376060145d56a50380d69a96d0688536cfa952c4fb74e111ad50a218852fda9a52b2a66b4f1ea6eff0316e31f949e60c8e2fd915aa8ca1495e6b6c806bfe3deeeab695", .None}, + {.Shr, "46bb32b75c2d3e2b1c8c6a863651504f17877c5344e6b7e1d2427115af122076adb8a937a70e5481f8de29f1b5b1446f386ca35f4572f9cd7bddc0164b4a79b784905e9685b4b12bfb1f199f22b4124a5d9d263813a0674e35915dbf86d9b767b04e39afd739cdc6a12cc4bb59165309584958f5e4a74420c682f0167fe157cedd6b0e0877a0fe5bd067b7da557a9bb8fe93304e54be", "3c", "46bb32b75c2d3e2b1c8c6a863651504f17877c5344e6b7e1d2427115af122076adb8a937a70e5481f8de29f1b5b1446f386ca35f4572f9cd7bddc0164b4a79b784905e9685b4b12bfb1f199f22b4124a5d9d263813a0674e35915dbf86d9b767b04e39afd739cdc6a12cc4bb59165309584958f5e4a74420c682f0167fe157cedd6b0e0877a0fe5bd067b7da557a9", .None}, + {.Shr, "b162f2ed306acfbdafa77e13f3540008c169cad1b9ed554ee0d612fce0ccd758fa87a304ee34e81e3f2ed6cc3345acf8a5924a08ac597ffc14b2e667062f7e1bbaf606ea771e6bfafe1d3a0c6b9737c5483be78a6bf123f411f83ee9f05cef3b62b7feba4ac291a7b6bd86c8c239c0e64bfa9ae01378fbc35592d7bf4b98fbdd82a88f4ca1c9dc68e2f1675b08fd327d5c3f0fdff040", "f0", "b162f2ed306acfbdafa77e13f3540008c169cad1b9ed554ee0d612fce0ccd758fa87a304ee34e81e3f2ed6cc3345acf8a5924a08ac597ffc14b2e667062f7e1bbaf606ea771e6bfafe1d3a0c6b9737c5483be78a6bf123f411f83ee9f05cef3b62b7feba4ac291a7b6bd86c8c239c0e64bfa9ae01378fbc3", .None}, + {.Shr, "4225e77cf1fa09a2c5c9f4c7d09562b52f301464725d9633278b093a66c5249b0821863c8f8ada1918ce7d45456c8846d42c7a015ba61d72d70de8dc8ac8668f589da9cbe6dc6408246943342a51af4617ca913cc171b697ec96d24cbac9d8d0cb5ba2af384b63e08c6d93577d0707fd0f16ac55730e2ccdc4518f4fc46a67291cb127035cb170892ac98d20b67281467ff08e866c06", "258", "4225e77cf1fa09a2c5c9f4c7d09562b52f301464725d9633278b093a66c5249b0821863c8f8ada1918ce7d45456c8846d42c7a015ba61d72d70de8dc8ac8668f589da9cbe6dc6408246943", .None}, + {.Shr, "af92122e12f8b4c29a8d56c982533b66e58964f8d4cdc5626824afb8367e0550dc098c6988d165e1d2f2de3908c480f2f022e293e6296c46da5c2e78e5acfce4f34daaa3f4c2761eda246f4ae8161c9b9219b963f61cde5ac5077e0fac89d9d06ae4e7fe2382ed1f8f21980555039b65a3dcc11baea64c23455012b0a2a398b7ab5e3e2c7c3c1ddf004df90f8dfbb4dbb8490b85cd1e", "12c", "af92122e12f8b4c29a8d56c982533b66e58964f8d4cdc5626824afb8367e0550dc098c6988d165e1d2f2de3908c480f2f022e293e6296c46da5c2e78e5acfce4f34daaa3f4c2761eda246f4ae8161c9b9219b963f61cde5ac5077e0fac89d9d06ae4e7fe2382ed1f8f21980555039b65a", .None}, + {.Shr, "8c7b0d2c5db0ab2ed8836b8b1658859550d415286c5875be834de9ef7562888422802d43ca470b76232203f86fb44718dac128cc18f417048a5debf05e05bc6be5b2996bc2d1c969ef04dbbc2bb3c9367a057281f23e2e655049b92ba51438f920f251142b27894e04ebfd0e6a6e9094fed49fc1b9371647c43e9fe860ac8840c15948408ce73e535c5252922700a09341b5d4722826", "168", "8c7b0d2c5db0ab2ed8836b8b1658859550d415286c5875be834de9ef7562888422802d43ca470b76232203f86fb44718dac128cc18f417048a5debf05e05bc6be5b2996bc2d1c969ef04dbbc2bb3c9367a057281f23e2e655049b92ba51438f920f251142b27894e04", .None}, + {.Shr, "54c83f44a8bc9822a17b3ece8c27d9ac5bde03ceef03ac6c05ce4ca26ecd7135d7abf2492e8d871d7ae21d3319fe030a34f12d00e8898aba5eca10ae8c57023a3df72b2fe9b2083bd8323f970113da8ece7e1123429e1dfdfa4be9e4b47e21c1740c1ff095a2b78c88c760053e32af8156fc045b4b5419a5424a61b9a51eddf5387158a55bf3258d14dc1d85b9fadf9ccf23caf87f50", "21c", "54c83f44a8bc9822a17b3ece8c27d9ac5bde03ceef03ac6c05ce4ca26ecd7135d7abf2492e8d871d7ae21d3319fe030a34f12d00e8898aba5eca10ae8c57023a3df72b2fe9b2083bd8323f970113da8ece7e1", .None}, + {.Shr, "94f5d2964b25f3812246356089a0f2028bd875be21b6a7e746c07f420678c3a7c10cf553f66b6e04f2950d186362e4ed013dc7fe69f53e88afcd7a1470dd1cbcd41bc3a5cf4420b157858d3fcadd5eff5aa99d7f5fcb7b49a6d861c82e5ccac01bf275435a09af06644938c705bd6249663ca02292e431c23584d331d496fec0b9210542ef35472f0ffdcb125fc66f3f6474fe6b85ef", "f0", "94f5d2964b25f3812246356089a0f2028bd875be21b6a7e746c07f420678c3a7c10cf553f66b6e04f2950d186362e4ed013dc7fe69f53e88afcd7a1470dd1cbcd41bc3a5cf4420b157858d3fcadd5eff5aa99d7f5fcb7b49a6d861c82e5ccac01bf275435a09af06644938c705bd6249663ca02292e431c2", .None}, + {.Shr, "48314a845147701b1e14c9cb3aba2aa6fcbe1ec3580d78b253a602ee6c0cc83afa48aa736cce68619cc4ecce61515a0beb7e8c2cdd50af6886494d43869555630396fe1d36a0757683113d6121cd96686079b4ca66d37c9f6cd94d2413ae1bac9a3cddbddf3d2a2af4cda76c44d1c5041336a875726c0e9b3eb4e095f53be600578dc1cfc6f7a2304c21a70d30d3e875ef961e7669c7", "21c", "48314a845147701b1e14c9cb3aba2aa6fcbe1ec3580d78b253a602ee6c0cc83afa48aa736cce68619cc4ecce61515a0beb7e8c2cdd50af6886494d43869555630396fe1d36a0757683113d6121cd96686079b", .None}, + {.Shr, "bd523718451c676accba7db9cdc81d9a87f1d9f7dc74bcb5e8c672691556890671a19ca3898a6651275a27aa57eb9ef741a46584033ff9f13ceda41cb963ab123bbe16673ef9d3d03962ec83477a4495d981af4bc0f8fcf73f101eff973b2105b793427d5a7e5abecfa6d724c03aebc2b8f1b5f388f9a4830b3681b2e81c2dadb3336da767380862b5ceb9e2844bd85f254d12f90e44", "0", "bd523718451c676accba7db9cdc81d9a87f1d9f7dc74bcb5e8c672691556890671a19ca3898a6651275a27aa57eb9ef741a46584033ff9f13ceda41cb963ab123bbe16673ef9d3d03962ec83477a4495d981af4bc0f8fcf73f101eff973b2105b793427d5a7e5abecfa6d724c03aebc2b8f1b5f388f9a4830b3681b2e81c2dadb3336da767380862b5ceb9e2844bd85f254d12f90e44", .None}, + {.Shr, "86eb66551f35394c1947c3480c55601e490406017598ff31dcf5aa059b77b502c2d6d91f060b0bc57aec6fa09eede7571b748e3f84bbc90e2c29c943fe53c78aa4a3b3a3cb36455fa7af67af9f1ff8bfff63435300a2e3f393c995f9276af9d88b5b279680df36f27732f97a80a566a614da811d0bb53d260964e5dfd1029978cfbc8da921f3401c4798ca9942aed39c73f82226b679", "12c", "86eb66551f35394c1947c3480c55601e490406017598ff31dcf5aa059b77b502c2d6d91f060b0bc57aec6fa09eede7571b748e3f84bbc90e2c29c943fe53c78aa4a3b3a3cb36455fa7af67af9f1ff8bfff63435300a2e3f393c995f9276af9d88b5b279680df36f27732f97a80a566a61", .None}, + {.Shr, "2617701de71fbb17d1b72dbca189ced13023cecef1d9874582aaee1b1b6801a045633c0e5e87ab6470bd18bacaded760fa01877b93e7cf536a529fa92e7bfcfc6d47af25aca861a3fd416912b68c258ac2da26d18e5b7bf4576d945aecab679048e1b1eff4e1f9969bade6294f680307d69b4447fca915737529cdecd9659a748159617c545c40296e2051f1b06a2014c8e53e9d4bf9", "f0", "2617701de71fbb17d1b72dbca189ced13023cecef1d9874582aaee1b1b6801a045633c0e5e87ab6470bd18bacaded760fa01877b93e7cf536a529fa92e7bfcfc6d47af25aca861a3fd416912b68c258ac2da26d18e5b7bf4576d945aecab679048e1b1eff4e1f9969bade6294f680307d69b4447fca91573", .None}, + {.Shr, "4378b4cfa1c3dae807c9ffb64fe9da2a3a9e7d7bfbe2fd63e3828c03e6f590b2a6e573c12cb126e2f2f378c483c1eadfe6add070a62b4916af06149e885cb5e95a1fa046a865d6d84f28f2db325c7553b6a3d9b76f972f5ad9168fc40abb9bb84f3f13a5b4fd76eb27015d9037b27229a00b63dbdfb036282660c9ebd0d3705a8ebd15171650feba4269cdc3b6bfe1cd91fedb2aca71", "f0", "4378b4cfa1c3dae807c9ffb64fe9da2a3a9e7d7bfbe2fd63e3828c03e6f590b2a6e573c12cb126e2f2f378c483c1eadfe6add070a62b4916af06149e885cb5e95a1fa046a865d6d84f28f2db325c7553b6a3d9b76f972f5ad9168fc40abb9bb84f3f13a5b4fd76eb27015d9037b27229a00b63dbdfb03628", .None}, + {.Shr, "f3c22a2ec401f766aecdfcd4b50f76497b0719764f5299199a00dafbaf467f58d6c14fb4d785bcffc578f57ab58ec159289034e8c17df8d715bc43582b8e1badfe59912f0da7c33215deb7d403da3c28b86c9afa4e272153ed8d4c69d7a997c49b4e448a0b74831712232462ba1ae864b866b3301a0deac93f8b779ff958238537643ba9dc4a9ba2d09da90acaea6ed042fc64f5830f", "12c", "f3c22a2ec401f766aecdfcd4b50f76497b0719764f5299199a00dafbaf467f58d6c14fb4d785bcffc578f57ab58ec159289034e8c17df8d715bc43582b8e1badfe59912f0da7c33215deb7d403da3c28b86c9afa4e272153ed8d4c69d7a997c49b4e448a0b74831712232462ba1ae864b", .None}, + {.Shr, "16384db25f717865ebe1de5933e997d5d1436c629a86837d1fa2a45607b90e7d4738f69410cc7a5c1a4eb625a7c4d6c0c5eab4dad5a25347082bdbe3118de53eec6f5592edb5e9a97e500cb1613b7161c6ee728432126e0c3eb6d0fa1a6fd8947fe45a62312bfc578e1a8f43f860442fdaf658cea97af62664abc064761417750c4f7e1bc9fbf630be79857b5d9430a31d5bfe7964b1", "f0", "16384db25f717865ebe1de5933e997d5d1436c629a86837d1fa2a45607b90e7d4738f69410cc7a5c1a4eb625a7c4d6c0c5eab4dad5a25347082bdbe3118de53eec6f5592edb5e9a97e500cb1613b7161c6ee728432126e0c3eb6d0fa1a6fd8947fe45a62312bfc578e1a8f43f860442fdaf658cea97af626", .None}, + {.Shr, "1742d53a27953a21687ab468ba345e77af19f2418ae2b2097a09e660191976ac039a6ef8853213800d42ce5873e78863b31fe2291cbc89c9f54f02d5c07170b559695ab07eea2929cd77dd967f61ef5f3480d950932a10ade460fffdee2b64eb4880af270e61ca377f7e8a9c90195a1544b2586846cec2189bfccd052452cab28aabdbd1ed61e2470590605bf0daf5672ff79d06024b", "1e0", "1742d53a27953a21687ab468ba345e77af19f2418ae2b2097a09e660191976ac039a6ef8853213800d42ce5873e78863b31fe2291cbc89c9f54f02d5c07170b559695ab07eea2929cd77dd967f61ef5f3480d950932a10ade460", .None}, + {.Shr, "45108429df237552708fb359edf6630be290613927d94feb4553cba6272bc5cad1cd21aef7fc227ff7ce0ce379de1984c7c78c9d17ed74b50dde2c625e2a582020af023518c943d90e238089ef5fccf2c77728d9b26baaf438fdcfa85a279caede3872396fdefe259c04a5da6324ff49adcabfc0a8b5425edd6d6df48927e7220a927aff9215fa96828619a601ddb1d97ff4238612e4", "f0", "45108429df237552708fb359edf6630be290613927d94feb4553cba6272bc5cad1cd21aef7fc227ff7ce0ce379de1984c7c78c9d17ed74b50dde2c625e2a582020af023518c943d90e238089ef5fccf2c77728d9b26baaf438fdcfa85a279caede3872396fdefe259c04a5da6324ff49adcabfc0a8b5425e", .None}, + {.Shr, "fefd807d7523f1fa2f510bc002f788afcd782cae2c099163390206ad1332ae9ed9546656bc7334b3e3be4c8854d1350682fb05e1c0055fc30ed67b2b0b5621e95c37e2789a7c6fb1b7a540ef2647724e48473d5cf0b95a2cc31a3b6e1eece8c0a22c33a7d63fd1e2f2ceb4db0d371439fc3f0c9a1be8ee9e9a3e3a72535c327681d8eb54a287ead3c3303eb704b59d7b96590c4a3f2c", "0", "fefd807d7523f1fa2f510bc002f788afcd782cae2c099163390206ad1332ae9ed9546656bc7334b3e3be4c8854d1350682fb05e1c0055fc30ed67b2b0b5621e95c37e2789a7c6fb1b7a540ef2647724e48473d5cf0b95a2cc31a3b6e1eece8c0a22c33a7d63fd1e2f2ceb4db0d371439fc3f0c9a1be8ee9e9a3e3a72535c327681d8eb54a287ead3c3303eb704b59d7b96590c4a3f2c", .None}, + {.Shr, "44e393e3d509df2211495e3c0a67b9ee1fd8f66b5c03fe4fc61599f6985006a23e73b43f3c276ea9f4aa5ef3bbca96d37069d636c9a0e9fe369564abea068fa8ecc8928d8643734644355d8d1c7f6a9bf8acd366163df2ee8b78303a63446731284bf1625d042dd26a16a5e2604d4cd664d483b0bd693c359399d1d9998a167539b6e49b7f19e4cfbe3b638992cd9dd957fe82e99a00", "f0", "44e393e3d509df2211495e3c0a67b9ee1fd8f66b5c03fe4fc61599f6985006a23e73b43f3c276ea9f4aa5ef3bbca96d37069d636c9a0e9fe369564abea068fa8ecc8928d8643734644355d8d1c7f6a9bf8acd366163df2ee8b78303a63446731284bf1625d042dd26a16a5e2604d4cd664d483b0bd693c35", .None}, + {.Shr, "c398cc6acd1619701fa4d036975ad8fd262152df1f8cfc8a08095bfb3920899bba9daf6252257d7a8675e54fcc03d7845cc9ab9d34cf6b9ae6df7d0081779b5af387794919a551323f795e80703a8bb1b71e5baec82e2a3fd67472783e371b84d5b3e3fd048b50b11cc700aa6f0375d9616f4e72bbba82c2b9b0b60b6dda73fe37266f7114f364e3bf6c043e57c59e7884bb2e63067d", "12c", "c398cc6acd1619701fa4d036975ad8fd262152df1f8cfc8a08095bfb3920899bba9daf6252257d7a8675e54fcc03d7845cc9ab9d34cf6b9ae6df7d0081779b5af387794919a551323f795e80703a8bb1b71e5baec82e2a3fd67472783e371b84d5b3e3fd048b50b11cc700aa6f0375d96", .None}, + {.Shr, "662e35727a2e45c38ddc572984ee252078662f5e87c22e0c853c002d9a8a56613ea9c8ada259535ad8949ae72c14b2fc6707af3e56f4c2b003ae2a014e56b1f45aa1ba3b4c9e5040cd2879c669691a74f5e16a7f50ad3355c9a13f6a20b6c7d7354b6e5ecbdc800dfc65cc0b4792bd13aa82f96faaee3b97c42df67cee2a15b1952ddaa49ab3afa44da086e749a17ed3f30685e4fbde", "f0", "662e35727a2e45c38ddc572984ee252078662f5e87c22e0c853c002d9a8a56613ea9c8ada259535ad8949ae72c14b2fc6707af3e56f4c2b003ae2a014e56b1f45aa1ba3b4c9e5040cd2879c669691a74f5e16a7f50ad3355c9a13f6a20b6c7d7354b6e5ecbdc800dfc65cc0b4792bd13aa82f96faaee3b97", .None}, + {.Shr, "9355e3c505485908dc75eb117fceedafed37e6a852a6238c06e9030de05b0584981ca06f11f9f6aff8525197768becd0ae3d22dd67718cc11f6e9d22ef6a1bd3556a71013822f5b24f170b54dd81369b4ba6badaab67024c9488ee0d3908b0145c1133663255dc691b9b0f42db07ac2b348969298f36c2e0fda63d287133b92f6241101b358e18c47d4b3cf91821b488bc642353840", "258", "9355e3c505485908dc75eb117fceedafed37e6a852a6238c06e9030de05b0584981ca06f11f9f6aff8525197768becd0ae3d22dd67718cc11f6e9d22ef6a1bd3556a71013822f5b24f170", .None}, + {.Shr, "b18897b76ce62ae13b6cb6636b926fccc2ec9b3068200a14f330881074ae513b3168be746bcddb8dcaa5caeaff319c36dcc1fe3843ffaddd641afc63a2a336b6ba3dadbf951df8f1852bf677931af77070b57b80dbe3331616b23f65da7fb0ac140731ffb4dab6edbaf5c91d6ffc6d8ca42ccfc8980266980cbf3fedc495411ad4fdae8f7bdd69a87dd98bb26f7c0c6641830ff2d924", "168", "b18897b76ce62ae13b6cb6636b926fccc2ec9b3068200a14f330881074ae513b3168be746bcddb8dcaa5caeaff319c36dcc1fe3843ffaddd641afc63a2a336b6ba3dadbf951df8f1852bf677931af77070b57b80dbe3331616b23f65da7fb0ac140731ffb4dab6edba", .None}, + {.Shr, "8587edc448d83b9cf1bb3865192aa5cd801fe9e5493f4bcb97ce4057dbe3a5fe33882fc38e808dfdd09392339ee85492fb4131d2bb587e6859498d238a83b4ed049163c28e8db370213947558d4d0b5846fecab53281e082a94a1501e20509fa16a468fadf8e105043b8c68cc64a61e620749d11d28192a941271f705dd250fec564434aa9d3c743d96e9a858040f6094e62f7e39b49", "1e0", "8587edc448d83b9cf1bb3865192aa5cd801fe9e5493f4bcb97ce4057dbe3a5fe33882fc38e808dfdd09392339ee85492fb4131d2bb587e6859498d238a83b4ed049163c28e8db370213947558d4d0b5846fecab53281e082a94a", .None}, + {.Shr, "4395b379d7fc7a37802a0a1c853694f65028cc4efd0931242a27ff9b28ed343e1dfb577d61d9d57e0a04ad7aa9adf3f41871ddea4452f24dec52b21e5dcddd93071a19d00be005c28ce5cdd09abb5b6c738edd0d8e86ac2cd344a7147fe8ac4db25f35fc36664d6a4fff008f88dbbc9bf05b6cf34042deed42a9e791f287d67bcc7eb1125fc6368fa5de214af13131045cbce43c5ef", "12c", "4395b379d7fc7a37802a0a1c853694f65028cc4efd0931242a27ff9b28ed343e1dfb577d61d9d57e0a04ad7aa9adf3f41871ddea4452f24dec52b21e5dcddd93071a19d00be005c28ce5cdd09abb5b6c738edd0d8e86ac2cd344a7147fe8ac4db25f35fc36664d6a4fff008f88dbbc9b", .None}, + {.Shr, "e3e6384de09c49b4a3f25ff0538c2fd06173933e0ef6e4ea0f6b950b33f99460d79cc2f582a69ce8a2849a38c5cdaea628561a329bee0d31b346cf1fd092c4c5ed7328b271cd7f32589b4463e9fa6cb097cf561be2baf7b7fe556759ac92aef5b3e9ac86e4530fb3ab2e9ae613be62de6b74552e481e6ebe3e3d09be24f0525c7b9a571fa30c970e78507815a255a3aae5cd736a4574", "1a4", "e3e6384de09c49b4a3f25ff0538c2fd06173933e0ef6e4ea0f6b950b33f99460d79cc2f582a69ce8a2849a38c5cdaea628561a329bee0d31b346cf1fd092c4c5ed7328b271cd7f32589b4463e9fa6cb097cf561be2baf7b7fe556759ac92aef5b3e", .None}, + {.Shr, "968234eb85a3e4ec048420566ba5736f1a0682707f9f42d0983ea75fb61dbc2e6fdf983b9ac5e3dfddd2733ee86a6b373ed8176ea40ec23c04157260f315cf1084291125845dc2a0e14b819aa882a3d779c7f1d479a85d13c648c0d59894b8904bdbf42410f2bb4d92f7f85d5aef1aaad7b0b5efb2df4883424d96e7896271b29a871e0c28e5914b9c84b0f2ddd6d8958fcb41a1d2cf", "258", "968234eb85a3e4ec048420566ba5736f1a0682707f9f42d0983ea75fb61dbc2e6fdf983b9ac5e3dfddd2733ee86a6b373ed8176ea40ec23c04157260f315cf1084291125845dc2a0e14b81", .None}, + {.Shr, "41eb947e0ea348fb7a45df8041a2be8ddfb34330dbcdd30a0be8ed0384a140059ef4815b5c13c609aef590b6a8e4b1093b687a4a4f3ebc1ceb92ed46fc259af498a4f73fbf8d47a478bac97dedb30cf429b4484d5dc9435e6a2c6d78a96b95769764ef01a3864450942820036937af57c086a3b9334abfaaec171b183c5c73fd377c24becb4e917b78916a0b283bed3f5e55af2d9797", "f0", "41eb947e0ea348fb7a45df8041a2be8ddfb34330dbcdd30a0be8ed0384a140059ef4815b5c13c609aef590b6a8e4b1093b687a4a4f3ebc1ceb92ed46fc259af498a4f73fbf8d47a478bac97dedb30cf429b4484d5dc9435e6a2c6d78a96b95769764ef01a3864450942820036937af57c086a3b9334abfaa", .None}, + {.Shr, "1b5288a3b04de3abeb3ed813e07f2d4a2116b12a86c84834f88460fb6cd25c9795e5770b75f9ac0aff8a89383caa0decb2b749955c34d14ead2c053d28fe0d97c314f3564cc7e41fc9020a1b4e26cb17b95966e61499e97c14a5a04726d8a06c9b785e03f4818449f010c34abb76ed5545c8bf4f95c36774c5087b26bc7b1881fe82d4da55ac56fc8a10435b0c9de9c0d36dbd9c5b30", "3c", "1b5288a3b04de3abeb3ed813e07f2d4a2116b12a86c84834f88460fb6cd25c9795e5770b75f9ac0aff8a89383caa0decb2b749955c34d14ead2c053d28fe0d97c314f3564cc7e41fc9020a1b4e26cb17b95966e61499e97c14a5a04726d8a06c9b785e03f4818449f010c34abb76ed5545c8bf4f95c36774c5087b26bc7b1881fe82d4da55ac56fc8a10435b0c9de", .None}, + {.Shr, "d1fc5e25380c577b3540761b2afa178ddf22049afccc81268da869d49216b42e5dbd8159f62d169960260ae9493e32cebd31e5d680e81cf0c4f6bb7c78adc75c23cb2b952a99cc4d7f9a4226d4b0802686095d6dfd109cc258da2ea484c2553b43a8a235ec59ff600ba5dba15bdff009573553f7458d1cc10247fdaa37cb423077e399789672f6ccb69b298fd9d750a96eadfafbd08d", "1a4", "d1fc5e25380c577b3540761b2afa178ddf22049afccc81268da869d49216b42e5dbd8159f62d169960260ae9493e32cebd31e5d680e81cf0c4f6bb7c78adc75c23cb2b952a99cc4d7f9a4226d4b0802686095d6dfd109cc258da2ea484c2553b43a", .None}, + {.Shr, "de145145496190c6905325fd5a352ff3f2b8b4cfe70f0f1a2c76335cd7387daf151dde4fcb74d69e7d4e90070added528b3a14909464ec60e90964afd886cd729d3313ce951b50c792289a0375756f0b3fc32d836142233c792d26c5b50c14224381e68eff0e061609d78a94c749c35f23df8f9067e970aad33b7a7c26bb3fb79dec31a30431ff46db50d5cf8f3d6b8a4f1befef0be2", "3c", "de145145496190c6905325fd5a352ff3f2b8b4cfe70f0f1a2c76335cd7387daf151dde4fcb74d69e7d4e90070added528b3a14909464ec60e90964afd886cd729d3313ce951b50c792289a0375756f0b3fc32d836142233c792d26c5b50c14224381e68eff0e061609d78a94c749c35f23df8f9067e970aad33b7a7c26bb3fb79dec31a30431ff46db50d5cf8f3d6", .None}, + {.Shr, "573fde1be7ce9bc53f10d6ef7058a660fd70f0efd46ecfcc36b492aa8e02bdae2db60ac21615894a9eb720b03c680e6568c21a00b429f41b0131783e5e36e5315fdae440bed255d65a9c1020cc8c21675ef014e216d976908f559aacff91b23ee48ea32dc587fdedd6d991ebfb81d84be36f8971a0a561bca03223b773073154a46142c953d9e2bd778ce0ff0e4835310eaab086bcd6", "258", "573fde1be7ce9bc53f10d6ef7058a660fd70f0efd46ecfcc36b492aa8e02bdae2db60ac21615894a9eb720b03c680e6568c21a00b429f41b0131783e5e36e5315fdae440bed255d65a9c10", .None}, + {.Shr, "6abf09cc17d7bb234be1fb3540c1797163633d88f56214a63e41342982bdf4f878c7c7565707da112596005b6163941d03a1ce0ef82f57dc7e655daf957fc74606415be751507f74adee88dab30225603d8242f0f23c04802dba0c2a435a0c5a33c0b0aabefba970e78ba91964c319504f7a58e623c63a3bbc8960ac0c5c39cf445f7f08978f178f3aad1908d271b20610c4a15992c5", "0", "6abf09cc17d7bb234be1fb3540c1797163633d88f56214a63e41342982bdf4f878c7c7565707da112596005b6163941d03a1ce0ef82f57dc7e655daf957fc74606415be751507f74adee88dab30225603d8242f0f23c04802dba0c2a435a0c5a33c0b0aabefba970e78ba91964c319504f7a58e623c63a3bbc8960ac0c5c39cf445f7f08978f178f3aad1908d271b20610c4a15992c5", .None}, + {.Shr, "7a2eab4559abb6e7538553b405ea8b2e18fac4b1565cdfdda66c311d050d12adcfae485af59be3ed7899bf4691d8b18f2cbabe4344663d079dff6c633bd2dc5fc0ce5a26f42d17da5923049b9e74e7ee34de2e0a4108f5b63520be7e59d4baab32ae0ed9e9cf5a66bc2dc1e45d34e5823607bce48bf4fd6368502777ff682c20a80cb943482aa3f20fc3dda28f6bfc253b26a70cfc38", "21c", "7a2eab4559abb6e7538553b405ea8b2e18fac4b1565cdfdda66c311d050d12adcfae485af59be3ed7899bf4691d8b18f2cbabe4344663d079dff6c633bd2dc5fc0ce5a26f42d17da5923049b9e74e7ee34de2", .None}, + {.Shr, "79ccc44377b2997eb33c3d82ad7169256cef63838e13d02d1936999e98a93f7eac11cffd02ed5cce4af2f1d8f279ddc92c41a690908c3151789b1b6129323d19ddc92d21f3bd60d2e5f3f58b9efdfc9f9681c2fb0b5a4ad11b816d403290f82b24307223e73655d993e0d1356e20a71f7fcef2d7c506a178ad5544bbd5d0b134f144bb7a5c62ad6ca1fa34a793f03b9dbc1d084abdf4", "f0", "79ccc44377b2997eb33c3d82ad7169256cef63838e13d02d1936999e98a93f7eac11cffd02ed5cce4af2f1d8f279ddc92c41a690908c3151789b1b6129323d19ddc92d21f3bd60d2e5f3f58b9efdfc9f9681c2fb0b5a4ad11b816d403290f82b24307223e73655d993e0d1356e20a71f7fcef2d7c506a178", .None}, + {.Shr, "26d8ad6c6d48b5a16edf6b0dd4920893478050c65699ec9e118ce7a965267214dffa122382a8fc1efcd7db1919481cb7562eaa8bef98e3e988d0ccf6601a4dd9fb6ef44f37706455c0cd909759b9ad9d1462514ace15c251a1457bcb080bd7fb47361b736ea8aabeccf8c95d021e1f1727d4712df7ddcdb580725cc8e175a65cbb905bdec73bd4882821836a5738c5b1590770ac3e10", "168", "26d8ad6c6d48b5a16edf6b0dd4920893478050c65699ec9e118ce7a965267214dffa122382a8fc1efcd7db1919481cb7562eaa8bef98e3e988d0ccf6601a4dd9fb6ef44f37706455c0cd909759b9ad9d1462514ace15c251a1457bcb080bd7fb47361b736ea8aabecc", .None}, + {.Shr, "8b19d5b917a7f95fcb0635f628bb962faa003f785a3ba3bec0ae8ff2e3879ccc7d34235bd08ce04b335f558838cdcf2d96d46a9ffa7004558a5abe22fe6882a1275d0a68b66b0ee2d98ac357e3547190cdaee15a3fa2b7e9568764570964a48ff4328d7d2e5ff806bb0d4ac9d411b9d641956d801f3066f8f927fa156a9bae7614cbdc0a747a250dd9552f7bdb0175d9943bb0c22ad5", "78", "8b19d5b917a7f95fcb0635f628bb962faa003f785a3ba3bec0ae8ff2e3879ccc7d34235bd08ce04b335f558838cdcf2d96d46a9ffa7004558a5abe22fe6882a1275d0a68b66b0ee2d98ac357e3547190cdaee15a3fa2b7e9568764570964a48ff4328d7d2e5ff806bb0d4ac9d411b9d641956d801f3066f8f927fa156a9bae7614cbdc0a747a25", .None}, + {.Shr, "3c005ae0ced7949737aee7bfb831491f8d4f07eb0a0baf47e5babed004460cac9b19143d91e34d0eb21c00eca94aa2bca344181faed512e8ead07a6b6e4b1f6d3c14a7c11728596a566ecdac7c3083a7efcd856f08da3e10dd5200fff94011f6a1e3c08ad333160caf316aba98ebcaa787e16c4c6723aa5fcc0c6c7b3adb82278e60a9d6910583554b35895a25b5357c1bcf32b79484", "258", "3c005ae0ced7949737aee7bfb831491f8d4f07eb0a0baf47e5babed004460cac9b19143d91e34d0eb21c00eca94aa2bca344181faed512e8ead07a6b6e4b1f6d3c14a7c11728596a566ecd", .None}, + {.Shr, "de4db608890969a0279860174b39e83958f10ca073bdb5788c1971b062a766a5ba4f57560ace5005ec5c7f48b6924899802829e9c7a4b49fbc7eb345b4e1c5a2b3f9db6ba6948ac8d1503529993ad934ab3a67a198a5e0b90b518775f36ed1cd1bb0498b0bd2891d095258954507495c24aaf28415b486b36d7e084ff448dfbd0c7a3e2265aa0c59cf29019a12612279459892a3e114", "1a4", "de4db608890969a0279860174b39e83958f10ca073bdb5788c1971b062a766a5ba4f57560ace5005ec5c7f48b6924899802829e9c7a4b49fbc7eb345b4e1c5a2b3f9db6ba6948ac8d1503529993ad934ab3a67a198a5e0b90b518775f36ed1cd1bb", .None}, + {.Shr, "e9180c0dbd9adf5b2e204a1a603b07f111f155c21c8c7dbf353d241f30937646d46a81a9596f02b94102e11933bf5b7cd9b2995869a4b0629bf326d9fd161c1ed237679b73ee2891d1b89b9d7fd879b6eff258f6ade33bd940d7f60b3e5f5acf1f399506aa55ce42529555a99963c321bc0b73580e85b321196b420263103f79a10cdc4929ae0a6ea413a366af64e04738d457d1e31b", "0", "e9180c0dbd9adf5b2e204a1a603b07f111f155c21c8c7dbf353d241f30937646d46a81a9596f02b94102e11933bf5b7cd9b2995869a4b0629bf326d9fd161c1ed237679b73ee2891d1b89b9d7fd879b6eff258f6ade33bd940d7f60b3e5f5acf1f399506aa55ce42529555a99963c321bc0b73580e85b321196b420263103f79a10cdc4929ae0a6ea413a366af64e04738d457d1e31b", .None}, + {.Shr, "b98c8f1b67bb78d24f8008a94f3a0a7432917dbd69f587a253864e9ee8c4ed870ab24c7130d519a349d90196e080721c2502093baf8e5036af5f79a6ff8e2340ceb1ef5aff50e06e6f95190e74e2f9cddeac4a58238d2c4967daed7c66234123414794a9dd5a7f82d561c6d10d305ce74aeda399432962e47b1b089948c82935965ffa988248906ac0c7cecd593dd4dd4d1fd9b8f895", "1e0", "b98c8f1b67bb78d24f8008a94f3a0a7432917dbd69f587a253864e9ee8c4ed870ab24c7130d519a349d90196e080721c2502093baf8e5036af5f79a6ff8e2340ceb1ef5aff50e06e6f95190e74e2f9cddeac4a58238d2c4967da", .None}, + {.Shr, "aee5b2cce40acf0825c477f34c40eb36d8f2bf118b4c626379cc8937d5880ea91afb266c489a6373f99cae3af3f2f622266cf02902342a57867d78306309e20bef783ce59314dcea479e2c39c1aa247feea1007aa990876456f4b2364ca5c762809b8d88057ab9f93c4b2274c5b6a6c328de0fbacd6cf2033bac66bf5453873bd502ad508ee0de7f551fca02779bec5bae7e85015a93", "1e0", "aee5b2cce40acf0825c477f34c40eb36d8f2bf118b4c626379cc8937d5880ea91afb266c489a6373f99cae3af3f2f622266cf02902342a57867d78306309e20bef783ce59314dcea479e2c39c1aa247feea1007aa990876456f4", .None}, + {.Shr, "f65d71f81deb7615cd77ec4dcfa8cdb7ea8061a02d7b4f1822780fa97d3aae09996df817631bb5e0c218db61401364d3a4760dc399d9b14a4d9f78ba5e74fe34305972b0c03acfd35c02d51a1272518c64d7848e259f446e44cba97cc9f440766f70ff9bda8d2e934eb79e1749f1a8a9e29d9e0195790d090e2a3a38a0602cb7cea6821eef99ee71d16f170deeba87c249b9ad0245ca", "12c", "f65d71f81deb7615cd77ec4dcfa8cdb7ea8061a02d7b4f1822780fa97d3aae09996df817631bb5e0c218db61401364d3a4760dc399d9b14a4d9f78ba5e74fe34305972b0c03acfd35c02d51a1272518c64d7848e259f446e44cba97cc9f440766f70ff9bda8d2e934eb79e1749f1a8a9e", .None}, + {.Shr, "c67577cdb233273d615b3ce4e2627217fe82625923db7a1b31b8cf3892b22ed408dbc356959585f8d5ccd7dd7465cdf7a8a10b13db662a0fc9ae93ba5dcb6267be1b47ba5e6dee800df2a744d4778ad5a4aa29989348287c997515c535fa1454fa63484a16ef9f8ffe03a048c8b02ff020bfd2fba7fa7a489cef5dbb75db7605184440276b651f751dfe1e655ea020abe996594628bb", "168", "c67577cdb233273d615b3ce4e2627217fe82625923db7a1b31b8cf3892b22ed408dbc356959585f8d5ccd7dd7465cdf7a8a10b13db662a0fc9ae93ba5dcb6267be1b47ba5e6dee800df2a744d4778ad5a4aa29989348287c997515c535fa1454fa63484a16ef9f8ffe", .None}, + {.Shr, "16ac59faf630f03a71ab4b04f721a79781b3c16c0367dcb8562ebdb1ddd689aaa11c16af0dab13fb12113d2b17dd4f149fbbba8aef81fe3ac45a7a56995832f0d996778079e1ac02345e87480fa4b0f448a6dd6747b6fa7050e94647e5af0faebb660bf74b3bd208f93ec9a871c6a9541be0546e2f4a0a6d23c82fbe4d623890322b625848e21e6e35001fdbf8f278efcd5c54ef57a7", "1a4", "16ac59faf630f03a71ab4b04f721a79781b3c16c0367dcb8562ebdb1ddd689aaa11c16af0dab13fb12113d2b17dd4f149fbbba8aef81fe3ac45a7a56995832f0d996778079e1ac02345e87480fa4b0f448a6dd6747b6fa7050e94647e5af0faebb6", .None}, + {.Shr, "8d705a76911730d0a04befcba6830b7d324a9167e073ef43ff20009de4f3afcbc3374a4b25383f194da89b27b109e10d0611366e617d5c2cedde8dc9fe9fa4c1a9a2356612d754628facd9de915907c622509b610a2a7836139f0285585f01abe639e6990d7e9f6b6bd43ae287a2592b806141a7e06bd783f27ec13dee81a73dcec50477645a4d468302755c10274161d9655b21b00d", "168", "8d705a76911730d0a04befcba6830b7d324a9167e073ef43ff20009de4f3afcbc3374a4b25383f194da89b27b109e10d0611366e617d5c2cedde8dc9fe9fa4c1a9a2356612d754628facd9de915907c622509b610a2a7836139f0285585f01abe639e6990d7e9f6b6b", .None}, + {.Shr, "393924036bee2d7945431d43eab7f53c7dd65ad3357abb657af0c650efce0cbe8c8e8482958d9db7176214a6961c4acd9b212296b75feb587b1fe0fdc480737ae0724be1e385dad81faebe9d923c253b1857202fe95012ae960e3c9b89aad676f5555687c328ea391192e7eb657de284ff7bad462cbdd1f0d0d3a63ff8d84d331e1333db035c082cb88cc5c47ec0a12063f19574daa2", "258", "393924036bee2d7945431d43eab7f53c7dd65ad3357abb657af0c650efce0cbe8c8e8482958d9db7176214a6961c4acd9b212296b75feb587b1fe0fdc480737ae0724be1e385dad81faebe", .None}, + {.Shr, "8588aeaa506cd17fb6da9acb1d90ccdd4c8341aec376025808a0422c17964d0cadffdbef5a7a30a72bf9da15aac1f2246f30260f8cb9b53f1fd30b5032ac16b8f2e97ab21829879e0005b15f43f618bbfc70f6bb435f7a5ddd0375542da5923bde280b0cba7c55b8e70f353600109d266450aa72a1757b3e9420a5a80c593695562d4fa09e7a30d094b1a3677dc5a6606782587141cd", "3c", "8588aeaa506cd17fb6da9acb1d90ccdd4c8341aec376025808a0422c17964d0cadffdbef5a7a30a72bf9da15aac1f2246f30260f8cb9b53f1fd30b5032ac16b8f2e97ab21829879e0005b15f43f618bbfc70f6bb435f7a5ddd0375542da5923bde280b0cba7c55b8e70f353600109d266450aa72a1757b3e9420a5a80c593695562d4fa09e7a30d094b1a3677dc5a", .None}, + {.Shr, "d288dc42fe8a44d7ed3a2532d14a382eda164656bfd1ae2c3004d1a5ce8843b8141911034ff43fbf86ed3fedbc60167cd8bf47e67f88c1608aba766a0ebdf9dedae7d76240885bd352b051c743c6916b760b5347e775b0feb2be951040c3b81347685505e6553012b45a8082a6d977ffddfe28fda11cd86915b572ca814810df8d515befc7a330d9fe035653d67a95472a54d2e7001d", "f0", "d288dc42fe8a44d7ed3a2532d14a382eda164656bfd1ae2c3004d1a5ce8843b8141911034ff43fbf86ed3fedbc60167cd8bf47e67f88c1608aba766a0ebdf9dedae7d76240885bd352b051c743c6916b760b5347e775b0feb2be951040c3b81347685505e6553012b45a8082a6d977ffddfe28fda11cd869", .None}, + {.Shr, "bfc32dded129ffdea2e579938beaa0ea8163df869ccb6d6875fd6365d3e06d2537de13bd2097029d91a3010356640999d30a3bc03964ada4e5ef76454afe685a81d8fd19888d1aede2b4cdf18a3d509ae2b1d5744047d3bab91302ca6b729221e622ee5be6b15317555d3284fc652f72c5ec160bdeb78bcfb4296a9c30bed91b5b03ed53edc11f075fd1e08835f1e1c01cdf3abfe1e1", "78", "bfc32dded129ffdea2e579938beaa0ea8163df869ccb6d6875fd6365d3e06d2537de13bd2097029d91a3010356640999d30a3bc03964ada4e5ef76454afe685a81d8fd19888d1aede2b4cdf18a3d509ae2b1d5744047d3bab91302ca6b729221e622ee5be6b15317555d3284fc652f72c5ec160bdeb78bcfb4296a9c30bed91b5b03ed53edc11f", .None}, + {.Shr, "e435a11bb6f8722ecd2cf7ffb0f93b772fcde4dc42288743d1e872faeeda3a5d0051e61dbb9c5b5036aff1d23c8dfa775e252394810efb4cb3cf2817e64fc7fc1319db70cc4f61fb60aa4c13ce9ed2db1be18093aee270f9ad498fad5611187267599f39c5e1317ddd89718c83e321f0472ece8389e84297801542803042b7447cb79962e69706769d84fd3fd700948c4f133e4f15c3", "3c", "e435a11bb6f8722ecd2cf7ffb0f93b772fcde4dc42288743d1e872faeeda3a5d0051e61dbb9c5b5036aff1d23c8dfa775e252394810efb4cb3cf2817e64fc7fc1319db70cc4f61fb60aa4c13ce9ed2db1be18093aee270f9ad498fad5611187267599f39c5e1317ddd89718c83e321f0472ece8389e84297801542803042b7447cb79962e69706769d84fd3fd7009", .None}, + {.Shr, "84f693519293dcf588a7dc21ff23b1218e9eac9871bc3d722e77184f535f6e0e35c20844f1d5d8a6788e41f6568a90c691a0bf119378a87a6841e81a64572033a8d41b3153d107cf175c56d1cd9f8a5b8a0f1ba9959ae529919862e33f2213e06538875b859b5eb7edb92099d03ee82f47b8f6ae6157bf287ecd2b96b04cea76c39ce103ab209989533eb08e2fd01b01f4ad4b5fcd63", "1e0", "84f693519293dcf588a7dc21ff23b1218e9eac9871bc3d722e77184f535f6e0e35c20844f1d5d8a6788e41f6568a90c691a0bf119378a87a6841e81a64572033a8d41b3153d107cf175c56d1cd9f8a5b8a0f1ba9959ae5299198", .None}, + {.Shr, "562f28fbfc8b5de271a3942f8ee922bd7acffad4be01611b181b46e4499796dd328863f3ccb733b3682894710de7ad7215f4ad519248e545e2a5923612503869ce873af8d927be8bcb96af959091005eb0088c8494cdf45356c74dafeb9ed62f9a35772fbe1d7f6d139e760b7c3a9814ec1405b62d68144fe77a7145566fee325f7d504c85c8215e2127299b64bc5cb07ee4d22e5a26", "21c", "562f28fbfc8b5de271a3942f8ee922bd7acffad4be01611b181b46e4499796dd328863f3ccb733b3682894710de7ad7215f4ad519248e545e2a5923612503869ce873af8d927be8bcb96af959091005eb0088", .None}, + {.Shr, "a91b3ecdfb08944be8e9c43f72d6840658ae7fd470c00d18260ce48fbba353c3c193987bc2120bc6a952bc484b74384759a2a4c0c596cd4fce4dd83aea23f73f9d6e3df979a7c86ca27c5ff9241b0353ff395946ca5dcadc9a687123b7332cdc1cfe69c90c7018a6a52f8d393f85175f338c8ba8418552bc59d2f5696df977a78882d0ab4d1b91673ab6bf801ae0753b57b644d0108d", "3c", "a91b3ecdfb08944be8e9c43f72d6840658ae7fd470c00d18260ce48fbba353c3c193987bc2120bc6a952bc484b74384759a2a4c0c596cd4fce4dd83aea23f73f9d6e3df979a7c86ca27c5ff9241b0353ff395946ca5dcadc9a687123b7332cdc1cfe69c90c7018a6a52f8d393f85175f338c8ba8418552bc59d2f5696df977a78882d0ab4d1b91673ab6bf801ae07", .None}, + {.Shr, "3516c9004f40ce4bd8770a8fede9596b40a139f608c7ffb807269361b42001b571fb5e52d9e54e49e67fc01e6a8bd5776872b3b3dcb1560a026dfbf756ea489364552a467ee038cdd70ff615cdc85ba2a89c635a1518b3bfc760814f1098f9563fedf387e1d505cb1f24f20220bbbb1290b9f7be1ccb44e5bf8207fa296dcdbaca152116796f88b6b72b85cae065ebb70df8bf3488b", "f0", "3516c9004f40ce4bd8770a8fede9596b40a139f608c7ffb807269361b42001b571fb5e52d9e54e49e67fc01e6a8bd5776872b3b3dcb1560a026dfbf756ea489364552a467ee038cdd70ff615cdc85ba2a89c635a1518b3bfc760814f1098f9563fedf387e1d505cb1f24f20220bbbb1290b9f7be1ccb44e", .None}, + {.Shr, "7beb310e786cd36a1c1b82fb8fa6144b07e0b398d7992af81915b76134ebcd6970bc136189e010456707d6634aa4faa6a2bebdd45a2f61db4c2cc81a4a31386c31048e85cbcf04211fb90a4fd54337cbb8bcb36e8d6c3e641e1c03f588215cd46a3b76b91781bb6a16d1d611f43e93ed5887900b2145283dc9bdd1c587998634c583ab6cd760ef2fabfa0ff515c2600586b2a490c1bf", "78", "7beb310e786cd36a1c1b82fb8fa6144b07e0b398d7992af81915b76134ebcd6970bc136189e010456707d6634aa4faa6a2bebdd45a2f61db4c2cc81a4a31386c31048e85cbcf04211fb90a4fd54337cbb8bcb36e8d6c3e641e1c03f588215cd46a3b76b91781bb6a16d1d611f43e93ed5887900b2145283dc9bdd1c587998634c583ab6cd760ef", .None}, + {.Shr, "41a2d4086994b5c3c4d225ceef0d3070dfc2c0744e907a5299c7a8cb8c986da98e8ae82125c80c1e241a41b5b4f9e081b27923eb5fbca16cf31ef91d4c4b0deaec8eb9e23a52ec07e0fbd1fa6abde43ac6fa2728d66c1bfd76116965fb1ef55f28812013e1fd413b6582f1cdaff39b364cc052b8be2e68318d0d4e124f368208465558fb7d768836f4c1fda9707498179bcd53ff7d08", "1e0", "41a2d4086994b5c3c4d225ceef0d3070dfc2c0744e907a5299c7a8cb8c986da98e8ae82125c80c1e241a41b5b4f9e081b27923eb5fbca16cf31ef91d4c4b0deaec8eb9e23a52ec07e0fbd1fa6abde43ac6fa2728d66c1bfd7611", .None}, + {.Shr, "8d71a0b28c8734f11158c0eb416cc5cbe45dc6bc164580d27e80a76419b0b1053fbdc6e265502c7a085230e51baaf3a940343a5fcdd38ebc577caf8f375dbfa8f99e1535933501cafd7dc688b45d9b71a560998d69419e9f4748fdeb17af5e58e55597ebe2ba112d61d7da9bdbb2fcab1d681f314f8f13fa0c517d1d56747d5b1f277be943d50a71adfd7f1b742e01aca29ce4322c7f", "21c", "8d71a0b28c8734f11158c0eb416cc5cbe45dc6bc164580d27e80a76419b0b1053fbdc6e265502c7a085230e51baaf3a940343a5fcdd38ebc577caf8f375dbfa8f99e1535933501cafd7dc688b45d9b71a5609", .None}, + {.Shr, "b4bfaf6b3e33faf32bdcf88d839d1bc58b71d215f92281527eb67298c7086888a06f2885c2de7ea90991c9893704a4b4d329f822cd8326de7665fa8eb3b0c0b41acd9f0f8c64410d3fb045fbb5a5714bb88d668f4b28bfacec5a78cda9eac165a350d93e8702efc82ef52dea3fedbde27b8de59872b7beaa8558f44240659da98ed0adb46207215ee51cc0afd2d1d5418e3af86d9224", "78", "b4bfaf6b3e33faf32bdcf88d839d1bc58b71d215f92281527eb67298c7086888a06f2885c2de7ea90991c9893704a4b4d329f822cd8326de7665fa8eb3b0c0b41acd9f0f8c64410d3fb045fbb5a5714bb88d668f4b28bfacec5a78cda9eac165a350d93e8702efc82ef52dea3fedbde27b8de59872b7beaa8558f44240659da98ed0adb4620721", .None}, + {.Shr, "c403a7ba0ac0a140b8b9764b2fac217fa489d90b4993f6118e6d68a26b695f9fa68aaa5043427664484fe6b196252c2c577b194c86cbfc8c5dfc7d18205a7519b63c9f18df9c83303aea01ea6634a713bbbf718ba3795741b64707da1b484ee3e07ece0a19a06e41a1603f7c980bc17c19f51a645b63b5664a9c704d9028b24f98224723ac464074b17c64d624b966cebaa94fe62eee", "b4", "c403a7ba0ac0a140b8b9764b2fac217fa489d90b4993f6118e6d68a26b695f9fa68aaa5043427664484fe6b196252c2c577b194c86cbfc8c5dfc7d18205a7519b63c9f18df9c83303aea01ea6634a713bbbf718ba3795741b64707da1b484ee3e07ece0a19a06e41a1603f7c980bc17c19f51a645b63b5664a9c704d9028b24", .None}, + {.Shr, "75bffefce163b91697770300dffa926b73ed9cd4a52aa7c84e03ba63daaed72782b432f34ac142e97f5d556aaf3ba37a93efcb3f7abbfc9362c75f76853b1b35adeaf999a518956c1460da4bf96e3ecb2f60febaa6067d94a698fed1e0c7ab09dce501205f624b3a3ba330a1001ad595fdcb910d0869de2b8f7f7d20bbcb5af5f96b709ba22095119faeb7b9ae378e33cb56cc39b67a", "1a4", "75bffefce163b91697770300dffa926b73ed9cd4a52aa7c84e03ba63daaed72782b432f34ac142e97f5d556aaf3ba37a93efcb3f7abbfc9362c75f76853b1b35adeaf999a518956c1460da4bf96e3ecb2f60febaa6067d94a698fed1e0c7ab09dce", .None}, + {.Shr, "358259107b71cbb8adda7c9651cb110eff48ef6d5d432e517504dcd423d85cd23e9bdf3eeae88ab92d4aec238ddd0bd3c71b723bddb1f041c534629d83ea1153c005f20c83d450df44e819c801c0f09bc97341564fb04c39307297a995c7370a147706a0d0ac491d149414658b717a6c6a3aa1cf21d9ca650adafdd6a54eb4ad34f1e4717016519280bb42aa07ed1c95d009f480e520", "b4", "358259107b71cbb8adda7c9651cb110eff48ef6d5d432e517504dcd423d85cd23e9bdf3eeae88ab92d4aec238ddd0bd3c71b723bddb1f041c534629d83ea1153c005f20c83d450df44e819c801c0f09bc97341564fb04c39307297a995c7370a147706a0d0ac491d149414658b717a6c6a3aa1cf21d9ca650adafdd6a54eb4a", .None}, + {.Shr, "a61af3548ab822d7290e9ed98ff8ef7cec34dd8dc60d176bf1d6e1b2dedb3317ad506a2e71caf5b0b94ba7bdb0d973435e8ec9aa690cdb7ee93451a0cac68f012cc192ca6eae25769e7092255d3180d201fa5a29e55f76ebad4a46352e8b585422ee083d40f2870945fcb20c19122d26be4765efce2d0e41739fd939a3ae7a21fb7045813d755cfc792dfcfbc6248b9e3c0f87d37557", "12c", "a61af3548ab822d7290e9ed98ff8ef7cec34dd8dc60d176bf1d6e1b2dedb3317ad506a2e71caf5b0b94ba7bdb0d973435e8ec9aa690cdb7ee93451a0cac68f012cc192ca6eae25769e7092255d3180d201fa5a29e55f76ebad4a46352e8b585422ee083d40f2870945fcb20c19122d26b", .None}, + {.Shr, "170beda631afe97bb37105f6a260ceb49c1e1dad3fe8a420e47cfe07f8c3d9b064b576171239f6dc016a3410895c1e8a634741efd5e41462cc6ceb31c633dc91ce29b6e846de1e6e4e71e9c10e0b0b2c468d4b9a92e2aea7ce8fda29d14f4ef26c7125e6339e51bf2b0db6ec3f95ca177ca3ab677bb8a25d3686a8be240f900a6c43ba0884534e34bbae0c95d720503cc5a7ef72955f", "12c", "170beda631afe97bb37105f6a260ceb49c1e1dad3fe8a420e47cfe07f8c3d9b064b576171239f6dc016a3410895c1e8a634741efd5e41462cc6ceb31c633dc91ce29b6e846de1e6e4e71e9c10e0b0b2c468d4b9a92e2aea7ce8fda29d14f4ef26c7125e6339e51bf2b0db6ec3f95ca177", .None}, + {.Shr, "a100f2be742808c3321e8bf51feb56427b633c587a29c50b3d22b1751cbfac49ebca09b4979f897063eb29769d8a0ad55f2ddb0bfdc7c79b3c19202a01152523824f8e0f74920d3952798a6401ad8e4542c8b256f4a9d9c67055a958cb5eab9b973e87112f1f37f7f550e5b9b41f5348f2cc28f542b9917e555c720b8bb23f887bc5471cea35fc996b777380f9d719a9ea4dfc42bedf", "1e0", "a100f2be742808c3321e8bf51feb56427b633c587a29c50b3d22b1751cbfac49ebca09b4979f897063eb29769d8a0ad55f2ddb0bfdc7c79b3c19202a01152523824f8e0f74920d3952798a6401ad8e4542c8b256f4a9d9c67055", .None}, + {.Shr, "cc7eca3045c2acb29e0ac282e3a6910104d36806ab746522bdab7779482db0e55b55ba5500c97ac6cb03cae954597873cc66a44d1f6b6fa796f74bc3ff0b98551c313fad2cca5a7d60a9c7a09149b5f41870a808720dc3296148af6c9348009e59106c5b2455eb3018df6566de08e763d079a40919981550c546233f8f683060a7fddb364ccf5cfc62128ecab4182cb00398a923e797", "b4", "cc7eca3045c2acb29e0ac282e3a6910104d36806ab746522bdab7779482db0e55b55ba5500c97ac6cb03cae954597873cc66a44d1f6b6fa796f74bc3ff0b98551c313fad2cca5a7d60a9c7a09149b5f41870a808720dc3296148af6c9348009e59106c5b2455eb3018df6566de08e763d079a40919981550c546233f8f68306", .None}, + {.Shr, "92c6b58f327ed191d58f95d09828b4d4a0e09b546d31a6f98bf3dbdaea800c1ef26e8bd58cdbd9d367d4ffce941187dd524bd18558c28c7cd614ae37f400c07a887894107587e14f92ee5c2b2ce661d8a7a17bb97906f09a42c500a1b5ca3e4d097d2e0ab344fd67e2aea00c88e67be5fdcba4cd4c7712267a5e93a53c7640e3621754f187fc05e1ee41da0520a7b14782dc23eb5f9c", "f0", "92c6b58f327ed191d58f95d09828b4d4a0e09b546d31a6f98bf3dbdaea800c1ef26e8bd58cdbd9d367d4ffce941187dd524bd18558c28c7cd614ae37f400c07a887894107587e14f92ee5c2b2ce661d8a7a17bb97906f09a42c500a1b5ca3e4d097d2e0ab344fd67e2aea00c88e67be5fdcba4cd4c771226", .None}, + {.Shr, "c9a3dc8c6badf758540097c8c66c7a7b503e22af40d7d736e38d1802f51d9e1111beeed4576063c34577f3a4f374b8f7b02448addb8d8a183aab809eac9ca3aeb0bb4d4170671f195591df561f7519c67a096d23c82f9fc96440aae8eae8c087c4087807bd63ccd742f9bb5ee24c7645df63c64eb982d6fdac7a18177c4a17afb60bfe9a24f6eb26c42adb796555d3efea008c5ae4f6", "258", "c9a3dc8c6badf758540097c8c66c7a7b503e22af40d7d736e38d1802f51d9e1111beeed4576063c34577f3a4f374b8f7b02448addb8d8a183aab809eac9ca3aeb0bb4d4170671f195591df", .None}, + {.Shr, "b5c24d91ee543ced35f694d6493498109e45867c574aec11d18106092be33edb5d40e7deabcb9d0cf54fe948fea4e68a13300360c7975fe26b5bb7b7736543555428ddaef4fb261b8244351fd4edb402437d3ad862197ee5c3214d20bb20aa1cc403cd89baac9c378ae4d8b3a1d46ebbfded96c06a679744a3607ea5c4dc502c0e02bd58e740f324add1a6978921509f0b6cdb84d77b", "12c", "b5c24d91ee543ced35f694d6493498109e45867c574aec11d18106092be33edb5d40e7deabcb9d0cf54fe948fea4e68a13300360c7975fe26b5bb7b7736543555428ddaef4fb261b8244351fd4edb402437d3ad862197ee5c3214d20bb20aa1cc403cd89baac9c378ae4d8b3a1d46ebbf", .None}, + {.Shr, "d982d887657219736eec9e1b9eae8b63e122e1a9f0e75949ec1ce25f20ac59a7334c7105848e5a95dd3627a21793f1f43d68919b0df3881ce2fb3b7c450fd76adedd44eb80cef1a1ec1e973d3916afcff79e22fa6312d050c135db692c3d0f4ec6a8de7e683ed26e52ef5d475abb2ceb1f49429079e51f54de4360ae13376ca508f58bc9650548923c376639af3f3cf68eeb204d118b", "0", "d982d887657219736eec9e1b9eae8b63e122e1a9f0e75949ec1ce25f20ac59a7334c7105848e5a95dd3627a21793f1f43d68919b0df3881ce2fb3b7c450fd76adedd44eb80cef1a1ec1e973d3916afcff79e22fa6312d050c135db692c3d0f4ec6a8de7e683ed26e52ef5d475abb2ceb1f49429079e51f54de4360ae13376ca508f58bc9650548923c376639af3f3cf68eeb204d118b", .None}, + {.Shr, "58c13880a40d5e33cd1bd9d007d3708d2b0cbdf249f301ecb9cb4f5677ac6522965fc67f840c9ddf69fa8733dce5606f51986a21074f0b5d1566928061f29a504047be681c632802ea3c31cf8ea68f4310ea8bc761cd232caccfd2ac2750ad6138fb344f91dc310bc08e17a5f985f1f2047f90a3545b3d963e49136248e8840309f66b8ef6301647ebc066d0c30061860f861f5f36c4", "168", "58c13880a40d5e33cd1bd9d007d3708d2b0cbdf249f301ecb9cb4f5677ac6522965fc67f840c9ddf69fa8733dce5606f51986a21074f0b5d1566928061f29a504047be681c632802ea3c31cf8ea68f4310ea8bc761cd232caccfd2ac2750ad6138fb344f91dc310bc0", .None}, + {.Shl, "2b0303d0f3e82fdd70ef51b02c3ac92ebb5d2c93d85b1632391778ec3540617ec8ccba10f03c4e03c190403beb960fdaa9c1eff547560f02674cccdd9fc1aa08702cb6e46477aa9ac926e77d24334867bc0fa87c66af057a4d507450f819c944d768c7ec8649b1b6208c31022e41b04414e6c405fed8315c9485855dcd0213fd565f3adf0ce5010a00b1766f33e396ea16338c9a3521", "11", "560607a1e7d05fbae1dea3605875925d76ba5927b0b62c64722ef1d86a80c2fd91997421e0789c0783208077d72c1fb55383dfea8eac1e04ce9999bb3f835410e0596dc8c8ef5535924dcefa486690cf781f50f8cd5e0af49aa0e8a1f0339289aed18fd90c93636c411862045c83608829cd880bfdb062b9290b0abb9a0427faacbe75be19ca02140162ecde67c72dd42c6719346a420000", .None}, + {.Shl, "c536020927d3a61f0ced78e8af7afa1867b9e410e03c413c170c33e382d346270bce3e8cdfc1d045ed2a5b6654ed5e6bc703a3ecc837533efd74041e5974585e3dab527f16fcc4ee09b3ad5d958e8cd8d9388bb3325c75674049eac9849b01591c88958e142f6879fc33e8449d27bb6ed01d32900abb0008a796385e271c857879d4214b87845ab91ef90641eb8e732367df22c99d3e", "8", "c536020927d3a61f0ced78e8af7afa1867b9e410e03c413c170c33e382d346270bce3e8cdfc1d045ed2a5b6654ed5e6bc703a3ecc837533efd74041e5974585e3dab527f16fcc4ee09b3ad5d958e8cd8d9388bb3325c75674049eac9849b01591c88958e142f6879fc33e8449d27bb6ed01d32900abb0008a796385e271c857879d4214b87845ab91ef90641eb8e732367df22c99d3e00", .None}, + {.Shl, "870e30cb3f35c349a01d6e2dd6ec930669ab27d8d89fe84324422a20063fc69f06a0bdb2ea79a0025372a5fc04e69ff0b8cac5d8c58578f3a9c767ba16e5c870d7069cf8a9e1d3d33fbb63e8572a6ad615856c87c56ef612303d93560d8df21a99d6d08c2ea1bf0512b279c59963c87d16bc24d22bd9ba2b97650e97720ee84f38053a9838f98ccb69695ed0d87f7ab5444df2f0b154", "1e", "21c38c32cfcd70d268075b8b75bb24c19a6ac9f63627fa10c9108a88018ff1a7c1a82f6cba9e680094dca97f0139a7fc2e32b17631615e3cea71d9ee85b9721c35c1a73e2a7874f4cfeed8fa15ca9ab585615b21f15bbd848c0f64d583637c86a675b4230ba86fc144ac9e716658f21f45af09348af66e8ae5d943a5dc83ba13ce014ea60e3e6332da5a57b4361fdead51137cbc2c5500000000", .None}, + {.Shl, "-de79c801d03d9b038e8f0512c4cd83a14cfe738d54e93d7220dfec6cb5a11a8bf6c579c26e18db0318abfefe34710c3d4eda7350973c3eb30d44eba6907fc230e3b3fd16907af1d1917a5930a4c47065405c17f0add0ba56be2828dfe4bec91ff8d8ed77cb82a550f6fe4072aa560e148a6c2d250256e6c6aa9c155ed39593736c02350ead06dc62b1730e5e5035bcc0345cbd5545ce", "75", "-1bcf39003a07b36071d1e0a25899b074299fce71aa9d27ae441bfd8d96b423517ed8af384dc31b6063157fdfc68e2187a9db4e6a12e787d661a89d74d20ff8461c767fa2d20f5e3a322f4b2614988e0ca80b82fe15ba174ad7c5051bfc97d923ff1b1daef97054aa1edfc80e554ac1c2914d85a4a04adcd8d55382abda72b26e6d8046a1d5a0db8c562e61cbca06b798068b97aaa8b9c00000000000000000000000000000", .None}, + {.Shl, "-ac8b1c4d5f712465d49b63bc63434aa729146ab26f7fb97cc2c7b957ab8c83e5b2fbd62b480a9a28a873b956c924e37aa920fd1549cd8ad416215c9e57c7a5019b6388e504da8cdf221e0e697f6c72596b045ec071e7de513ba215643c9030b6d8de4ab35db333f8f49b7ed015cc27a9869741a33ba0bac8b9ce06bf0fbd828ca9ff4614f3189822561188a837c9ea1bc2b0e45902c9", "1c", "-ac8b1c4d5f712465d49b63bc63434aa729146ab26f7fb97cc2c7b957ab8c83e5b2fbd62b480a9a28a873b956c924e37aa920fd1549cd8ad416215c9e57c7a5019b6388e504da8cdf221e0e697f6c72596b045ec071e7de513ba215643c9030b6d8de4ab35db333f8f49b7ed015cc27a9869741a33ba0bac8b9ce06bf0fbd828ca9ff4614f3189822561188a837c9ea1bc2b0e45902c90000000", .None}, + {.Shl, "-65a022a864c11126e0b334f69f2ff46d937b2579c9de9cd6db99846f298c3606858ba5f2bdea4cf83700e50b6ea1dc83cf432a67f2065793f5339e8c42ab6efcf7fe82a6ff06511156dbce40a7729542439f4137159f7dcfce746f82951a25c20c0657f99942e0b3731a60cb651e7169141d3fde337399422bb69c7c82ff8f2503e9bdffddf76767440fa85b51fb3b65b56091bad6fb", "63", "-32d011543260889370599a7b4f97fa36c9bd92bce4ef4e6b6dccc23794c61b0342c5d2f95ef5267c1b807285b750ee41e7a19533f9032bc9fa99cf462155b77e7bff41537f832888ab6de72053b94aa121cfa09b8acfbee7e73a37c14a8d12e106032bfccca17059b98d3065b28f38b48a0e9fef19b9cca115db4e3e417fc79281f4deffeefbb3b3a207d42da8fd9db2dab048dd6b7d8000000000000000000000000", .None}, + {.Shl, "-2e4d86038680ca147f044f9845ced109abb46b8189f6135cdbf3594ea58c85f579bf19d81e28cfd4ed61765bc50eb87e4785605554567abd4642ebba0d78c310abb2842e6eeeb833fde1f1069bde2145c9e7b8d86c944e46d33b5ba0642e52721301589d763bb41352a7c331aa5f13ad73bbfd9e57b8553e3f87368927e4031146c828afe1ddac38f5bcf565666002bd4be3b514c28a", "40", "-2e4d86038680ca147f044f9845ced109abb46b8189f6135cdbf3594ea58c85f579bf19d81e28cfd4ed61765bc50eb87e4785605554567abd4642ebba0d78c310abb2842e6eeeb833fde1f1069bde2145c9e7b8d86c944e46d33b5ba0642e52721301589d763bb41352a7c331aa5f13ad73bbfd9e57b8553e3f87368927e4031146c828afe1ddac38f5bcf565666002bd4be3b514c28a0000000000000000", .None}, + {.Shl, "-537ffecb8e9df06b238367d2a3ff6d15d52b284b73dcab109425f10cd14d5334ef2910daa199b0c9994fe8c6d58941313be44521cf7f76973ec8d38b9beac58320098a927066b254636eceee9cabee62a73cebbb607eef10a13a8ce0dd2d5a51679048cec6fe56bf988c5fcd23e70e9f1595ec6b2d6b27008978d9d11f1b1ed98fbe1a0c08c55990bb132b6ac20ba5ca2617434787a3", "63", "-29bfff65c74ef83591c1b3e951ffb68aea959425b9ee55884a12f88668a6a99a7794886d50ccd864cca7f4636ac4a0989df22290e7bfbb4b9f6469c5cdf562c19004c5493833592a31b767774e55f731539e75ddb03f7788509d46706e96ad28b3c82467637f2b5fcc462fe691f3874f8acaf63596b5938044bc6ce88f8d8f6cc7df0d060462acc85d8995b56105d2e5130ba1a3c3d18000000000000000000000000", .None}, + {.Shl, "-c0d3fe71a5652406b293d26a67fc786cae984abf7a565e72e655942a570956a5f2e809e93851adbcc320201233d3d6ed1ad52847e842b2d10bb4a10ff2180ac48da80e46fd33e6a21b5dd27129a1a994f3d246ce2938cc743216093f78027ca0ff0486c10b887478adb25e2057910764fedc9d609dd68300ed059326476bfa3b23d6a1397e9f7412badd2ac3f94b4d5366d0644a3194", "60", "-c0d3fe71a5652406b293d26a67fc786cae984abf7a565e72e655942a570956a5f2e809e93851adbcc320201233d3d6ed1ad52847e842b2d10bb4a10ff2180ac48da80e46fd33e6a21b5dd27129a1a994f3d246ce2938cc743216093f78027ca0ff0486c10b887478adb25e2057910764fedc9d609dd68300ed059326476bfa3b23d6a1397e9f7412badd2ac3f94b4d5366d0644a3194000000000000000000000000", .None}, + {.Shl, "4686f45d2e068cdb4c5f8b86bcf022ffc7809d08c5acb9fa6314e4aba67cadb4ba03a16c3f12bcf8a0e7e20305c7c02786b37061d93f3aefd91c71a17c893e0f4e5eeb3bb2cad389320e1d43dc0debd768e79473b6b1a71104c08efe770fc64a5d7ea14b53cb1c80c448b49d3b1a8c6f770f9317bcb80f770a2a84a3f14b166295a0b464c49ab51fb3eb7f1f20b59fa4c803e58d994", "72", "11a1bd174b81a336d317e2e1af3c08bff1e02742316b2e7e98c5392ae99f2b6d2e80e85b0fc4af3e2839f880c171f009e1acdc18764fcebbf6471c685f224f83d397baceecb2b4e24c838750f7037af5da39e51cedac69c4413023bf9dc3f192975fa852d4f2c72031122d274ec6a31bddc3e4c5ef2e03ddc28aa128fc52c598a5682d193126ad47ecfadfc7c82d67e93200f96366500000000000000000000000000000", .None}, + {.Shl, "8c5cfddcd95406e1b9d5e2ffd5f7db853de7289ae87636ffa2275188525aac760262f3d7aadb1699ed4400db3182709f573683c46ef787a7c3bef01621203c082b0f53c8ca5daf7769338cef519e56b197aa1d22ad90185cdf1b848c7f23073d239b73061b58f2f6f7adf29c1576936f3d0b9fc1a393f4e7cef2249f8270d8019d5fa4dd58e83b757c1823e0bbac0106647aa54306a", "a", "23173f77365501b86e7578bff57df6e14f79ca26ba1d8dbfe889d4621496ab1d8098bcf5eab6c5a67b510036cc609c27d5cda0f11bbde1e9f0efbc0588480f020ac3d4f232976bddda4ce33bd46795ac65ea8748ab64061737c6e1231fc8c1cf48e6dcc186d63cbdbdeb7ca7055da4dbcf42e7f068e4fd39f3bc8927e09c36006757e937563a0edd5f0608f82eeb0041991ea950c1a800", .None}, + {.Shl, "e7f02f01c462759096000ea541854ac6df40d1bf8c67829750fe79f4ab830f21430aeb8671dfaae7a3d32b2ddfa77b549b534beb9fa99823e473d24d99ef167dd7e881d7eab2ac5c93d953fed270a2e5db06ac92465685611195a414a10cbc815db697bdd6cd734fed0041a7cfa79cafe430af31002ac2a015763b33ad60b3401eb0a415be9e20b8d31111029b06831cee572d25b905", "28", "e7f02f01c462759096000ea541854ac6df40d1bf8c67829750fe79f4ab830f21430aeb8671dfaae7a3d32b2ddfa77b549b534beb9fa99823e473d24d99ef167dd7e881d7eab2ac5c93d953fed270a2e5db06ac92465685611195a414a10cbc815db697bdd6cd734fed0041a7cfa79cafe430af31002ac2a015763b33ad60b3401eb0a415be9e20b8d31111029b06831cee572d25b9050000000000", .None}, + {.Shl, "-1f3a5271b5781ee7f60a123c12f4a3dc25a8620458f01d242fb05033ee2d91211975d4d624fe0b3ac4b44455d9a8c9b24aad381966a06ac0fa0fffaf39bd454fdcde383c98ad9ff2dde11073807a81e64ae450d8b0c77d253f6bb0102dbf6ac9973bc113ebf5a9e0b4930d08545f27ac5a13c10ab3d19adc2895bbac84cbaf3e90a8b780c0b52ea243cde06073378e4b00f3eef552c1", "f", "-f9d2938dabc0f73fb05091e097a51ee12d431022c780e9217d82819f716c8908cbaea6b127f059d625a222aecd464d925569c0cb35035607d07ffd79cdea2a7ee6f1c1e4c56cff96ef08839c03d40f32572286c5863be929fb5d80816dfb564cb9de089f5fad4f05a4986842a2f93d62d09e08559e8cd6e144addd64265d79f48545bc0605a975121e6f030399bc7258079f77aa9608000", .None}, + {.Shl, "-a57bf5fc66ac74dba87ed55c48cb0222bc7fdeffbbc451d1844617f7fb30c2d81ac14563dbee873ad873d19c5ab89f02e08799a1c2653d0b7f5e6bbf5ea1d05bdd10e91d8efb20f3e1b44f56d1586677ac844f1b9ee774b5a46a917c4b10751ec408c0609609705cdbbc4d0654eaac4694364de5225a5f95ce3f6bb234d698551e98238565b6ac90c273c96d0dabbdc80b7046ff9e7e", "68", "-a57bf5fc66ac74dba87ed55c48cb0222bc7fdeffbbc451d1844617f7fb30c2d81ac14563dbee873ad873d19c5ab89f02e08799a1c2653d0b7f5e6bbf5ea1d05bdd10e91d8efb20f3e1b44f56d1586677ac844f1b9ee774b5a46a917c4b10751ec408c0609609705cdbbc4d0654eaac4694364de5225a5f95ce3f6bb234d698551e98238565b6ac90c273c96d0dabbdc80b7046ff9e7e00000000000000000000000000", .None}, + {.Shl, "-d2b3ba293a041b25f63b25bf061d4e50d0abd35398294e3404d866d50a41d5ecdccfe55d23320cba74f2c0dba5df574bcb500d6bbed5cb3c46b6790cfa2e7338dd297577625cd297a47daea25be837c6ce5b709e683fcdf2246181a0416451be09e05a69699302e7d3f5d49a312f58ff3dfb636555a9b3b9fb5713a845f1618a4276a376048db5c8b242ef6827b825ea2118d8ef5146", "76", "-34acee8a4e8106c97d8ec96fc1875394342af4d4e60a538d013619b54290757b3733f95748cc832e9d3cb036e977d5d2f2d4035aefb572cf11ad9e433e8b9cce374a5d5dd89734a5e91f6ba896fa0df1b396dc279a0ff37c891860681059146f8278169a5a64c0b9f4fd75268c4bd63fcf7ed8d9556a6cee7ed5c4ea117c5862909da8dd81236d722c90bbda09ee097a8846363bd451800000000000000000000000000000", .None}, + {.Shl, "5525101d8f61070f95b3628c74a12113575693df0bbd128a9d35a22f5f8b35b770936c271e5511dbebe59d3f6a01e6a3d8a4b090adddce2523314ebe13eb9dacd9e0c7de3f7bba15d2a25b832512d65f0a4346bf0bf5b7838aab76287aff9c2e0a0de18ea12de9a1e4721b9fa0a4f75a13b8d05a3130df5c8738de88d6a6791820193f3f9f218077031d6acc3534f4f7a517f7ee6c", "35", "aa4a203b1ec20e1f2b66c518e9424226aead27be177a25153a6b445ebf166b6ee126d84e3caa23b7d7cb3a7ed403cd47b14961215bbb9c4a46629d7c27d73b59b3c18fbc7ef7742ba544b7064a25acbe14868d7e17eb6f071556ec50f5ff385c141bc31d425bd343c8e4373f4149eeb42771a0b46261beb90e71bd11ad4cf23040327e7f3e4300ee063ad5986a69e9ef4a2fefdcd80000000000000", .None}, + {.Shl, "50efcf20dae43a8b5431df8b7fd3bd1927f769e1276a99b3da07109a8d8b117653405166727edefb0692a1936f4d78e6b39e75d589b41d6d2e4f7174a75594c2bec99319bc0959e6b7b69f817ef98ff23830dc55f45044568003b3bb6210c4cf324d873cb596060a6b52c0335950e6384a5fbf783a2b16e3f64ba0e17369d31ad4c3e2ad8c5efb2d64aa5a889ea2e62db26cf80f5226", "4", "50efcf20dae43a8b5431df8b7fd3bd1927f769e1276a99b3da07109a8d8b117653405166727edefb0692a1936f4d78e6b39e75d589b41d6d2e4f7174a75594c2bec99319bc0959e6b7b69f817ef98ff23830dc55f45044568003b3bb6210c4cf324d873cb596060a6b52c0335950e6384a5fbf783a2b16e3f64ba0e17369d31ad4c3e2ad8c5efb2d64aa5a889ea2e62db26cf80f52260", .None}, + {.Shl, "-f1794e25b0d76f48d960371bf2e1deef93b999a140e6f99f7058948b9d217f7b6e04a3bb948bcb3f0e4ea5fefd40c5e8a0d61266421d4588b533bab2f48448cad398232244e0b03fbe5119b98c67bf2e07526570b210e34029d7e90824708a5f1f85ccaaae980fc91e450a6a1c7d420d7962c7737747610d07988005963cb5c13139dfa57c75dbfe5b23bcbd31a9f564e0bcb4780314", "31", "-1e2f29c4b61aede91b2c06e37e5c3bddf2773334281cdf33ee0b129173a42fef6dc0947772917967e1c9d4bfdfa818bd141ac24cc843a8b116a677565e9089195a730464489c1607f7ca2337318cf7e5c0ea4cae16421c68053afd21048e114be3f0b99555d301f923c8a14d438fa841af2c58ee6ee8ec21a0f31000b2c796b826273bf4af8ebb7fcb647797a6353eac9c17968f00628000000000000", .None}, + {.Shl, "d49cee3520b049e8794604133041c0148a0e45ad9e261ebad43b97a865cf9290cfc21802eb0331dfcba8ee8294a0c4b7b1d550bb26ead7bb73090fc0d514cbbd855636510dd44d1dbca1cee700ce20165a04d0262377742ca7c16f41369b89931d73a47be99cb9483082491e1857481deff04fefb2683d5cae14c08847c84cc7d98c0bc3e8629cbfacc1e7a0198ea364710a6f34cc8d", "48", "d49cee3520b049e8794604133041c0148a0e45ad9e261ebad43b97a865cf9290cfc21802eb0331dfcba8ee8294a0c4b7b1d550bb26ead7bb73090fc0d514cbbd855636510dd44d1dbca1cee700ce20165a04d0262377742ca7c16f41369b89931d73a47be99cb9483082491e1857481deff04fefb2683d5cae14c08847c84cc7d98c0bc3e8629cbfacc1e7a0198ea364710a6f34cc8d000000000000000000", .None}, + {.Shl, "bb8534b24be2c558089c55fc508eafc75952bf1417c23072dd1694e9423dc87b1b26dbf4dec035d5062c4c2e45c212ea25316b53de048529f0e69d40078c168bf047f2a39a020bf59579973aabcf4755bdcb9ecb5523cafa6d7673392023272b5cb71ee0cd838019294621fe136f5016742b386b62bdfaaebec23bee17e276b65e8c52b7eb4ceabc62812aa649a2065ac1476e86b5fb", "a", "2ee14d2c92f8b1560227157f1423abf1d654afc505f08c1cb745a53a508f721ec6c9b6fd37b00d75418b130b917084ba894c5ad4f781214a7c39a75001e305a2fc11fca8e68082fd655e65ceaaf3d1d56f72e7b2d548f2be9b5d9cce4808c9cad72dc7b83360e0064a51887f84dbd4059d0ace1ad8af7eabafb08efb85f89dad97a314adfad33aaf18a04aa992688196b051dba1ad7ec00", .None}, + {.Shl, "71f3b776545f41ac160cf52d97e73c25f3631734ca9b4add8f0b5fdf04ad88b934fd7a11744d4292ecade913229ede11f5afefe6968f74bee202bbed58abab02c223c6f98cda2717f82e5a6cbc31ae0ceec40052d553ec179c80bdaf3babc6bd12441ab6a813cb61f6ed5573a21c8fcdf57602d3813d34bc32d881f5c72f7c469521ef7ce3ca3c4f80b61bc2f59322cee48d74247f75", "38", "71f3b776545f41ac160cf52d97e73c25f3631734ca9b4add8f0b5fdf04ad88b934fd7a11744d4292ecade913229ede11f5afefe6968f74bee202bbed58abab02c223c6f98cda2717f82e5a6cbc31ae0ceec40052d553ec179c80bdaf3babc6bd12441ab6a813cb61f6ed5573a21c8fcdf57602d3813d34bc32d881f5c72f7c469521ef7ce3ca3c4f80b61bc2f59322cee48d74247f7500000000000000", .None}, + {.Shl, "73ec89b04e5156078abcb963d966e9528868a81b48ca05636b78319f4f5203e79211f6dcaa87d068b59694e01dbebe374869c09dfe3fa1b6d8468d742d988e6a3f2177d532018795149ef5976df55ef4a80cd09fd397486deced00b6f2fe2b9e847938063d1b45aae3691cc4cab7308e753e05c3f6bcd0a332d0fc9746c7edaae5ede4e7ee811a414208b4d06fceb36af0ea87500812", "33", "39f644d82728ab03c55e5cb1ecb374a94434540da46502b1b5bc18cfa7a901f3c908fb6e5543e8345acb4a700edf5f1ba434e04eff1fd0db6c2346ba16cc47351f90bbea9900c3ca8a4f7acbb6faaf7a5406684fe9cba436f676805b797f15cf423c9c031e8da2d571b48e62655b98473a9f02e1fb5e685199687e4ba363f6d572f6f273f7408d20a1045a6837e759b5787543a804090000000000000", .None}, + {.Shl, "-1e2409141582682c39939fada23b664efaae3c22ebbd750db3355767176242862a2e79420afa4c30bc17f09bfd11c1b8e88208351fbb124c63e0652f9f36f27a4ee6207ccdf7f3d227dd4a7aa5b13d3f5841f7ee1da7460977dfc478d34d01cb79e3f5b75f67bb461d5e1a1bdc2bb93c70f3a532344b83bfa0b39bfcfeac37f8a6261be4f363fe8dcabaad64abda3f4daf4af629109d", "7", "-f12048a0ac134161cc9cfd6d11db3277d571e1175deba86d99aabb38bb1214315173ca1057d26185e0bf84dfe88e0dc7441041a8fdd892631f03297cf9b793d2773103e66fbf9e913eea53d52d89e9fac20fbf70ed3a304bbefe23c69a680e5bcf1fadbafb3dda30eaf0d0dee15dc9e3879d2991a25c1dfd059cdfe7f561bfc53130df279b1ff46e55d56b255ed1fa6d7a57b14884e80", .None}, + {.Shl, "7daa8e93997cc034c8a33dfd4da3171e439501ab4e922708173ae7cdba19aefcb75840fe92b012a508c0c8041bcdc33be75797026891cf7ebf6772f6d4c9b8539cfa7255438a383cc03038b436747cfe7982b3d76132920f918ac8500e569789315b71dc7d00096323754c86890dde5cd02d7784fcbdcdfe21217d825e1664278871e028971c3408e512cc279d1e94e1278f74fc38b8", "6f", "3ed54749ccbe601a64519efea6d18b8f21ca80d5a74913840b9d73e6dd0cd77e5bac207f49580952846064020de6e19df3abcb813448e7bf5fb3b97b6a64dc29ce7d392aa1c51c1e60181c5a1b3a3e7f3cc159ebb0994907c8c56428072b4bc498adb8ee3e8004b191baa6434486ef2e6816bbc27e5ee6ff1090bec12f0b3213c438f0144b8e1a0472896613ce8f4a7093c7ba7e1c5c0000000000000000000000000000", .None}, + {.Shl, "-266a4ffc612280ddb01196fa57522fb3dfe1aa05516ee230d06217bc09915beec251660532dd59cd2e2f9cf99ecef9049bb0f7a2a14f72b868de7c942663800b12077a2c4b407bce119ed3fc2f66a1eb48f1091d9185e9ce9978cf5efa48a4c57e7117c83832f4f3b463080ec6bc59778ada59c51546419d6f9157315e496f2e04a549a29c27e0a1c3180ac33ca83a21bef1af8c4394", "59", "-4cd49ff8c24501bb60232df4aea45f67bfc3540aa2ddc461a0c42f781322b7dd84a2cc0a65bab39a5c5f39f33d9df2093761ef45429ee570d1bcf9284cc70016240ef4589680f79c233da7f85ecd43d691e2123b230bd39d32f19ebdf491498afce22f907065e9e768c6101d8d78b2ef15b4b38a2a8c833adf22ae62bc92de5c094a9345384fc14386301586795074437de35f1887280000000000000000000000", .None}, + {.Shl, "8029a64936fad39bac99903a2c14a7ae1e329214f092a3d119f35171aee4d9b51713d1986f60682b538e22a35f2836d684a8f65bb92a6a3f0f9c11e6a4824d9817e8b2681681ee3d8d5dd2aa43d438ca3c0b9b0fa8bcf958f3fdedaf86303c1e838707744da97bcaafad3075de1b5a7086872af5bc942299e5568e956d0cc7b70813039ca3a76a4745044b6f9a33d20fc95cab22b9a5", "28", "8029a64936fad39bac99903a2c14a7ae1e329214f092a3d119f35171aee4d9b51713d1986f60682b538e22a35f2836d684a8f65bb92a6a3f0f9c11e6a4824d9817e8b2681681ee3d8d5dd2aa43d438ca3c0b9b0fa8bcf958f3fdedaf86303c1e838707744da97bcaafad3075de1b5a7086872af5bc942299e5568e956d0cc7b70813039ca3a76a4745044b6f9a33d20fc95cab22b9a50000000000", .None}, + {.Shl, "-3a8e11bd8a39d45f7582de51c5fedbf78ca51a6f116d044723e6cdacd0b347ea4147b61d7de4c8bcb316134fe58139b5f6dac6e35608674b320c2ea477b37ef5b1c1a8510a09a78a85277368d951b8dccf3bc38e9318f32e7606dc7c0692e045eb06b0f0bc1b2fb03b9e2baec45628202b9c6771ee47a2682388f4cc12e436b24936ee62e7ee164d8f65d89c8bdf515b08c9343f28a0", "51", "-751c237b1473a8beeb05bca38bfdb7ef194a34de22da088e47cd9b59a1668fd4828f6c3afbc99179662c269fcb02736bedb58dc6ac10ce9664185d48ef66fdeb638350a214134f150a4ee6d1b2a371b99e77871d2631e65cec0db8f80d25c08bd60d61e178365f60773c575d88ac50405738cee3dc8f44d04711e99825c86d64926ddcc5cfdc2c9b1ecbb13917bea2b61192687e514000000000000000000000", .None}, + {.Shl, "56ed254629e58148ca6fad296b199c53f737bc47933e4a4c862bd84ef31930b34d8e2ac8426e0b98639f177274aff3b3eda5c54aa95fe3efa9bedb74bddaa7972c76fe071e0c04b5e1609f14937b62fea0102367fdcf18b5eb2e57490e76a2ff93a9e6443c1d7e0e6f417849cdd46c8c65ace3b716cf06632febc7faef71adab9556fd07b7563aec6a31df4dbe45cb8049d9dfe767ca", "65", "adda4a8c53cb029194df5a52d63338a7ee6f788f267c94990c57b09de63261669b1c559084dc1730c73e2ee4e95fe767db4b8a9552bfc7df537db6e97bb54f2e58edfc0e3c18096bc2c13e2926f6c5fd402046cffb9e316bd65cae921ced45ff2753cc88783afc1cde82f0939ba8d918cb59c76e2d9e0cc65fd78ff5dee35b572aadfa0f6eac75d8d463be9b7c8b970093b3bfcecf940000000000000000000000000", .None}, + {.Shl, "5fbb1b73bedaaae2aa2bfa291cb4f203c3840a219dff8a1d5aa07fd7d3b8ba6b5e21db6f084c97a5c6988a03c88048fc3dccb0ed675769a7e5473529eb05da3959a1c6099cd945c9a693df9cae2ab2d30254373ab541c91c78d87d4611240405b63ff44c907b99d278e795e1cb0f01decfbaa5172b2b470927223415ad2210acecfc074eae1d73e414d5ee45da7059e4934fb6c8c53d", "7", "2fdd8db9df6d55715515fd148e5a7901e1c20510ceffc50ead503febe9dc5d35af10edb784264bd2e34c4501e440247e1ee65876b3abb4d3f2a39a94f582ed1cacd0e304ce6ca2e4d349efce57155969812a1b9d5aa0e48e3c6c3ea308920202db1ffa26483dcce93c73caf0e58780ef67dd528b9595a38493911a0ad6910856767e03a7570eb9f20a6af722ed382cf249a7db64629e80", .None}, + {.Shl, "-12cc38f066a2c4b9a8709b0bf64a94071ea26bdb1893c330128b44611301dd42c1b3e1f4b15cc0302541f4288880c359a5fe26de0838aed47961979cee0eb54635678b5e5a556ba0ad071112f1189e5595085e0cba5ba3517fbadc6ff888fe89d18f2731dc52a5f7d4912ac1851e03bcb54a6e56e3afe6d02bc6dd3c7595421cf13e0b0f4f21a9b5bb3e08e81107c15f86b81736461", "1d", "-259871e0cd45897350e13617ec95280e3d44d7b631278660251688c22603ba858367c3e962b980604a83e851110186b34bfc4dbc10715da8f2c32f39dc1d6a8c6acf16bcb4aad7415a0e2225e2313cab2a10bc1974b746a2ff75b8dff111fd13a31e4e63b8a54befa92255830a3c07796a94dcadc75fcda0578dba78eb2a8439e27c161e9e43536b767c11d0220f82bf0d702e6c8c20000000", .None}, + {.Shl, "-b08220a8a5288667fe011211e2e5abb2dc36cb4fe5898eca25c5134c7066581d45e819f285117cc4b609c614b177a7690b423bb6f932eaf356eae7b577c4822a2e2b41eb5e474f2a9b3b8b8e12d0c83750831bd4602c28525403d98aadd1803be681e1e2cb2779be60e15c668147f7aef28506341ce52fbb71781d9111393369e433f05939a90c46b33a1fc25ba2b5c1c515445b8bdf", "1", "-1610441514a510ccffc022423c5cb5765b86d969fcb131d944b8a2698e0ccb03a8bd033e50a22f9896c138c2962ef4ed21684776df265d5e6add5cf6aef8904545c5683d6bc8e9e553677171c25a1906ea10637a8c05850a4a807b3155ba30077cd03c3c5964ef37cc1c2b8cd028fef5de50a0c6839ca5f76e2f03b22227266d3c867e0b27352188d66743f84b7456b838a2a88b717be", .None}, + {.Shl, "-2aa31f64cf3781853bc503b46b94e363e51fffe47f035feecbd54441dbd30ecb86fc12162e5d85e743f5a9351e69dd9510cd4090a7705bdbf218c28400a5138b95b5aa1fba7416ccd70a04181739f65d8bb76f454549eae4dbb4fbc68cfb5122e70ff6e762028b5f92082da97061dedf909ca483bc7b4bf6235070c5b0444d52ebb85d16dc6b50c43150be1ff089780c9ce25b447112", "51", "-55463ec99e6f030a778a0768d729c6c7ca3fffc8fe06bfdd97aa8883b7a61d970df8242c5cbb0bce87eb526a3cd3bb2a219a81214ee0b7b7e4318508014a27172b6b543f74e82d99ae1408302e73ecbb176ede8a8a93d5c9b769f78d19f6a245ce1fedcec40516bf24105b52e0c3bdbf2139490778f697ec46a0e18b60889aa5d770ba2db8d6a18862a17c3fe112f01939c4b688e22400000000000000000000", .None}, + {.Shl, "6859278728467ca44b2ef2847681c8d234625c5737787dd633a069b86941c6bb991ba0dd7f245ecedf59cbdd92e7cfc5eb084286da58396d16ab1311d194f9c4c337fd873eae993b68d80d16a4572c25a8b92869a36663c1f26deae8d32520d4b2c591f5eb8fc715b9951ba66d8a3b14b47f64acba1714ba6b7ad77242f5c509cd1c0d18d74e6d2e64f0c62eee773f0d84f07c60ceff", "5a", "1a1649e1ca119f2912cbbca11da072348d189715cdde1f758ce81a6e1a5071aee646e8375fc917b3b7d672f764b9f3f17ac210a1b6960e5b45aac4c474653e7130cdff61cfaba64eda360345a915cb096a2e4a1a68d998f07c9b7aba34c948352cb1647d7ae3f1c56e6546e99b628ec52d1fd92b2e85c52e9adeb5dc90bd71427347034635d39b4b993c318bbb9dcfc3613c1f1833bfc0000000000000000000000", .None}, + {.Shl, "-27036e37e1456f94a160d67ce01e632e8b80f2b1751c8ee5ee32c54347fe6336f45c82093f92b6cfc60cd7440e187067299bb15e30e56cdb3e0bc20693688cd51a5ccf77852e277f67e0af13ba9b71715720ae308a76dfad1e60c4beb2eeb34228d5cc99c5e0f27fa92022667bab577616841ae2b9760830c2bf4a727419b215e5908b21db5f1cc462aaa3ed34965bc0e77a67c16a94", "8", "-27036e37e1456f94a160d67ce01e632e8b80f2b1751c8ee5ee32c54347fe6336f45c82093f92b6cfc60cd7440e187067299bb15e30e56cdb3e0bc20693688cd51a5ccf77852e277f67e0af13ba9b71715720ae308a76dfad1e60c4beb2eeb34228d5cc99c5e0f27fa92022667bab577616841ae2b9760830c2bf4a727419b215e5908b21db5f1cc462aaa3ed34965bc0e77a67c16a9400", .None}, + {.Shl, "-2e63cba1a743454a83a645019a53c7235a8f0261301ed43b00338292184f4c8dac73d6f490a72b532c17d8e42db6e1cedf864d00b0c711352ce658f39113448801df98874151397e05cf60ff6d7b37d7c4feb1845842837b709a1a8df8d5dc292a5361aeb8327c6c65e8da93e82e2fa411f54a40351303df9c5108c334f31368f68fc57742743cc298ce7305d486d6effdee72a8a7a8", "62", "-b98f2e869d0d152a0e991406694f1c8d6a3c0984c07b50ec00ce0a48613d3236b1cf5bd2429cad4cb05f6390b6db873b7e193402c31c44d4b39963ce444d1220077e621d0544e5f8173d83fdb5ecdf5f13fac611610a0dedc2686a37e35770a4a94d86bae0c9f1b197a36a4fa0b8be9047d52900d44c0f7e7144230cd3cc4da3da3f15dd09d0f30a6339cc17521b5bbff7b9caa29ea0000000000000000000000000", .None}, + {.Shl, "694c1369832a42368e51b2e93c2552209c7c877a12e136a4d4893310f1be801e47d96055b1d937326d91368329a3b3d96788d80365d6dc5176c3a9efd81b09de16ae81c2a754ee5a2a12f3092aba7ddb44f7f8b5c96f1dbc08aaac0b8ac40431381bc72b3e1951820e83fd350c8e273d0cd3aceb41c8d66d8285abcb53f7559aafd905d68e0cd8160d791c55f33228897065555722ec", "3a", "1a5304da60ca908da3946cba4f095488271f21de84b84da935224cc43c6fa00791f658156c764dcc9b644da0ca68ecf659e23600d975b7145db0ea7bf606c27785aba070a9d53b968a84bcc24aae9f76d13dfe2d725bc76f022aab02e2b1010c4e06f1cacf86546083a0ff4d432389cf4334eb3ad072359b60a16af2d4fdd566abf64175a3833605835e47157ccc8a225c195555c8bb000000000000000", .None}, + {.Shl, "-a571373e15cb4b10ad8b75020791896d0c76e6c2c9c39a6b444a8b2e660f401e482d208e937aa43a223ac4c00bf0f15b65381c8e47e8db10667b98df6c35c8debd79cc488d2901816aaad1846e04ade9e80ef6fe8eed69ed30bed472fb0e3093568105b323bd9e7fb18a2a93b1738e158907ee033cb3b382bfd993947fbfb1e49b207a7eaf6af95be627b65b80097dec0b275cf0be9", "4b", "-52b89b9f0ae5a58856c5ba8103c8c4b6863b736164e1cd35a22545973307a00f2416904749bd521d111d626005f878adb29c0e4723f46d88333dcc6fb61ae46f5ebce624469480c0b55568c2370256f4f4077b7f4776b4f6985f6a397d871849ab4082d991decf3fd8c51549d8b9c70ac483f7019e59d9c15fecc9ca3fdfd8f24d903d3f57b57cadf313db2dc004bef60593ae785f48000000000000000000", .None}, + {.Shl, "-e4a165978a410cbb35d028184473eb67fe174c6abf8b46622fac6184d8a0016b22c69c8a516f6af73574f1df0fe829868c49239282f637bc1e5aee302c1d503e1001b67af71b40789f8269003b55f6817849600fef5c98904bd9eaee816b78dd608e8d6800fb7d37b81ed8b8d66b68f54fdc717abcb815886aee768e7a9df70202904a895d4af35eab2da9a95fab34fae21e29d1e9eb", "55", "-1c942cb2f148219766ba0503088e7d6cffc2e98d57f168cc45f58c309b14002d6458d3914a2ded5ee6ae9e3be1fd0530d1892472505ec6f783cb5dc60583aa07c20036cf5ee3680f13f04d20076abed02f092c01fdeb9312097b3d5dd02d6f1bac11d1ad001f6fa6f703db171acd6d1ea9fb8e2f579702b10d5dced1cf53bee0405209512ba95e6bd565b5352bf5669f5c43c53a3d3d6000000000000000000000", .None}, + {.Shl, "99309e663a305fb75369fa13c3147f301bc3cd985ce1dcb9f6bc96341774fa765be19894453d901b5f9ad5cafcd6a64a467e54e12f51836103f7eb1b2d1de869b33722c8b1af806b95aa7d5b5d8d68ba360cb9344a3345041d2536eeafb6dd5d8b4e0034bab3add7ff134bc8798628d2f48915aea82848f7d745f5110061679bbe43a13884bfc6bfdb12b5fe6ebe4bc3804914638504", "6", "264c27998e8c17edd4da7e84f0c51fcc06f0f3661738772e7daf258d05dd3e9d96f86625114f6406d7e6b572bf35a992919f95384bd460d840fdfac6cb477a1a6ccdc8b22c6be01ae56a9f56d7635a2e8d832e4d128cd14107494dbbabedb75762d3800d2eaceb75ffc4d2f21e618a34bd22456baa0a123df5d17d44401859e6ef90e84e212ff1aff6c4ad7f9baf92f0e0124518e14100", .None}, + {.Shl, "4800e7047dfe4999506b80946f840b67bc0b18652a3157d5603fec58bcb93e25089f342e2cf832f6d0d72bb1e942ea22157c95e45795d93d8a6002981cf00cfed1478dc76f603619592f23fb507fcd9d88ac5a2da463bd44322a05ab98e6d924a5aa38440fa2e43612250e3755c28f63821e5c37b13f06de929a7b873923f15503557da76bb76d2dc8c69d9ba24732e84970ade7add3", "2c", "4800e7047dfe4999506b80946f840b67bc0b18652a3157d5603fec58bcb93e25089f342e2cf832f6d0d72bb1e942ea22157c95e45795d93d8a6002981cf00cfed1478dc76f603619592f23fb507fcd9d88ac5a2da463bd44322a05ab98e6d924a5aa38440fa2e43612250e3755c28f63821e5c37b13f06de929a7b873923f15503557da76bb76d2dc8c69d9ba24732e84970ade7add300000000000", .None}, + {.Shl, "-7831a63e4eb687bfca088442409b1b113b1badfbc95dd9a5c2d0260d98c6517609e0228c9f0bc476945a52298e281f8d49d87e4468b29f5c354703e058d1d5f0eda99e18a116cc16703fd8a2eb21ffff728e79e49f725beb83be296c0f76ac9b33298ef119a1a2638d48ab3a3f0c271b802fe40c5769ac71a61f99591fbda75e65f7ce1d33783ed773d8a03d3ac8e057b17c13230a4f", "3a", "-1e0c698f93ada1eff28221109026c6c44ec6eb7ef257766970b409836631945d827808a327c2f11da516948a638a07e352761f911a2ca7d70d51c0f81634757c3b6a67862845b3059c0ff628bac87fffdca39e7927dc96fae0ef8a5b03ddab26ccca63bc46686898e3522ace8fc309c6e00bf90315da6b1c6987e65647ef69d7997df3874cde0fb5dcf6280f4eb23815ec5f04c8c293c00000000000000", .None}, + {.Shl, "-14eb27b2add9b866c70117dd0faa9da69c73e08520c8d6b01e8ab09e0f58aa1b298ea3c5e89d9aacdccc5f19a33691452a5f926329f5f85b3e62bb75c6931f1a088ed6ca6d4bdce0c350ed966090c0548bbca441982c0362af19c6d7bcacfcf3c425b71c57cf3792101410b8d9c3ce761dd261de500734c798cb6da9afbf6516c61622101251d66e98bf3865545ef805b4d7a2d4ca40", "77", "-a7593d956ecdc3363808bee87d54ed34e39f04290646b580f45584f07ac550d94c751e2f44ecd566e662f8cd19b48a2952fc93194fafc2d9f315dbae3498f8d04476b6536a5ee7061a876cb3048602a45de5220cc1601b1578ce36bde567e79e212db8e2be79bc9080a085c6ce1e73b0ee930ef28039a63cc65b6d4d7dfb28b630b11080928eb374c5f9c32aa2f7c02da6bd16a6520000000000000000000000000000000", .None}, + {.Shl, "29f2d6b681ef6099d82fb5614ea7ffaf2d2f8ee82a17a34f4eff1b1cacae491067b07c1baf9a48cf5f005d8ae7b4a6145efb61e1aca0588cd361792c8bea430da40ebd342cadca77d63438c2ba56681c49945b24d9949b8126c9f138b4959106e09c14fdb9fbdbc2e3b85a7b1c017725ad9b051662463098adc2663f8c941e2f5a5508a3d4ba1e215eeb6fbd5cd80869a134d17ae09a", "57", "14f96b5b40f7b04cec17dab0a753ffd79697c774150bd1a7a77f8d8e5657248833d83e0dd7cd2467af802ec573da530a2f7db0f0d6502c4669b0bc9645f52186d2075e9a1656e53beb1a1c615d2b340e24ca2d926cca4dc09364f89c5a4ac883704e0a7edcfdede171dc2d3d8e00bb92d6cd828b3123184c56e1331fc64a0f17ad2a8451ea5d0f10af75b7deae6c0434d09a68bd704d0000000000000000000000", .None}, + {.Shl, "d8e8e4992b8744e8d9992d97a9d61269a6425962eb409a1d4b8e17a45e8dfc4ad8ecad42b8f7a8055ff6b96deb8a5a8e21e08b5b2a09d437c2ac03da99066e82beba0dcaea03630cf6f2748bcefad02d5cb23ad5900b1c25c8b2e23fdfcc77d8986283fa6d46d6e8f4188dd2495e192bfc4c619686f5aea16cfd6d9f130644d766611697c7b88d9f2996bdf71b311840cc6d6f896358", "29", "1b1d1c932570e89d1b3325b2f53ac24d34c84b2c5d681343a971c2f48bd1bf895b1d95a8571ef500abfed72dbd714b51c43c116b65413a86f855807b5320cdd057d741b95d406c619ede4e9179df5a05ab96475ab2016384b9165c47fbf98efb130c507f4da8dadd1e8311ba492bc3257f898c32d0deb5d42d9fadb3e260c89aeccc22d2f8f711b3e532d7bee3662308198dadf12c6b00000000000", .None}, + {.Shl, "-7ca70a2e04a5816fa086fe2e88d2b670b4bc12a00337eaa99921bb9a15da9ad656d5dd70586ffcc1ac03bcd0a41135ef94f68afcec5d44e1b7702a980eb6db8b87815407da59b7ad037ae9d9cbfc87ddd45a2c5031280cbb54389a14ab081d882f642498e7d55f6f97705251afcf2063038c7fc93534bde79960a8a8ea22d34ccf42c4a8d6de186bf5479d67f6c270ccae7866a08573", "26", "-1f29c28b8129605be821bf8ba234ad9c2d2f04a800cdfaaa66486ee68576a6b595b5775c161bff306b00ef3429044d7be53da2bf3b1751386ddc0aa603adb6e2e1e05501f6966deb40deba7672ff21f775168b140c4a032ed50e26852ac207620bd9092639f557dbe5dc14946bf3c818c0e31ff24d4d2f79e6582a2a3a88b4d333d0b12a35b7861afd51e759fdb09c332b9e19a8215cc000000000", .None}, + {.Shl, "-cc52ca5a2f955b5df31f0730a08b76e588e0437e7d4ad3b7e19e38809ae6106c84db0dc9f47ec90457f75476a60db70f61ecd3f42a227e0aa5e13e3c4a1bbb11f61b081f9c6f03bf2a8d8646069b860c7e87fc1ddfbcd070b5a216e3df2732730ae083d70c27233a05efd17bc817c0a839443341d08a94fb6f90280dbd952d5f7bdb29197d50af0e05dcfc4e7d79b367e933822a704e", "3", "-6629652d17caadaef98f83985045bb72c47021bf3ea569dbf0cf1c404d730836426d86e4fa3f64822bfbaa3b5306db87b0f669fa15113f0552f09f1e250ddd88fb0d840fce3781df9546c323034dc3063f43fe0eefde68385ad10b71ef939939857041eb8613919d02f7e8bde40be0541ca219a0e8454a7db7c81406deca96afbded948cbea8578702ee7e273ebcd9b3f499c11538270", .None}, + {.Shl, "-3e125e5be08f35000ccdc8b37990bed0dec9189289217418f860449d383b2c2d2c2fb547111eddd771e95646d5290dbf0a3d6ff3339977c455a92120aeb857a8b8bc194c710de9a0e5e49960a7945de63226acc39a80dcecd7a78ce6169d12bb36a9a6b471331549f39f1297d1be01b474c9725ab85d5a6701e49360818e103bceeccbebdd2a0686bd3ee35dc4d6e0d084061eb177b0", "21", "-7c24bcb7c11e6a00199b9166f3217da1bd9231251242e831f0c0893a7076585a585f6a8e223dbbaee3d2ac8daa521b7e147adfe66732ef88ab5242415d70af5171783298e21bd341cbc932c14f28bbcc644d59873501b9d9af4f19cc2d3a25766d534d68e2662a93e73e252fa37c0368e992e4b570bab4ce03c926c1031c20779dd997d7ba540d0d7a7dc6bb89adc1a1080c3d62ef6000000000", .None}, + {.Shl, "-27b690229ec459cdcf0430e55c02445ec5cfd077787e4a0e6c6df8b30644cc8eda8f03e9b3e64ffb9126029cd16ace69410a9d29ae226047744d6cedb7d26f4fe160cdb29d452e16995a23cb95735c2aedfc68ad63d252bb4dbffbc27b820d52b822ab77b016904cfcade0fcbbc0bcee990cce5cdabf811eed64e8f275bda688fa98598ec062bbc4189d2900bf7d39efb7b232f21a55", "23", "-13db48114f622ce6e7821872ae01222f62e7e83bbc3f25073636fc59832266476d4781f4d9f327fdc893014e68b56734a0854e94d7113023ba26b676dbe937a7f0b066d94ea2970b4cad11e5cab9ae1576fe3456b1e9295da6dffde13dc106a95c1155bbd80b48267e56f07e5de05e774c86672e6d5fc08f76b274793aded3447d4c2cc760315de20c4e94805fbe9cf7dbd919790d2a800000000", .None}, + {.Shl, "38d1d203efcd5c32a7209c61e1709e861c1a812cc082705757252b8699850283204a3284a7acecc685184e2cfe4103c346eee21e5474e8f99b18a8f09e61b041c977ac5dca205d3be55f502d1887d42fc4e5ff251906bc3a11fc1622f79952a3b5e9aab92055ea9ce1e73c787f9d654c1e7231a1ae3b5933783615815c4bb096611a80ef64f6c21895861e95be4309d4ec1573564e0d", "50", "38d1d203efcd5c32a7209c61e1709e861c1a812cc082705757252b8699850283204a3284a7acecc685184e2cfe4103c346eee21e5474e8f99b18a8f09e61b041c977ac5dca205d3be55f502d1887d42fc4e5ff251906bc3a11fc1622f79952a3b5e9aab92055ea9ce1e73c787f9d654c1e7231a1ae3b5933783615815c4bb096611a80ef64f6c21895861e95be4309d4ec1573564e0d00000000000000000000", .None}, + {.Shl, "49dbff1ec28a3bb5529ef8c774c4a1310c6365511ab50aed82556b217fc7429dfb312afc4c0e82d9a01fc351f8452825c84e48af4fddd57ada736e61d187791293947463f66200077ff99499bf3a8ea2d3ae9324f26b4f0cc9e406a94675200b666920e972e85d08f5efb2264cbe1af8095e80c10bfb15d5ade1c77420c71727fab84eb7d98aa0e36148e341d5e02fa8c7ab37916e0a", "4e", "1276ffc7b0a28eed54a7be31dd31284c4318d95446ad42bb60955ac85ff1d0a77ecc4abf1303a0b66807f0d47e114a097213922bd3f7755eb69cdb987461de44a4e51d18fd988001dffe65266fcea3a8b4eba4c93c9ad3c3327901aa519d4802d99a483a5cba17423d7bec89932f86be0257a03042fec5756b7871dd0831c5c9feae13adf662a838d85238d075780bea31eacde45b8280000000000000000000", .None}, + {.Shl, "-532d98b7cbfe2aeecf05e627c4573bbdb8c15d1a9184587176d9e99d0bd3ef9e09d3ae0c2856836caca133ae375e5003a79d9d8702498e63a99f3bf4c18398d0b233b924c32a5e4f6e9499bf1b594d82aadc751214f1e6f21137564a4ffb40a1026aea5156507dfebc7d75b09b60b0fea9d481abeab273efc78b334c1a3275e8fdb40e4876fbbaf09fe80f183041a3c4732191a7ba37", "f", "-2996cc5be5ff15776782f313e22b9ddedc60ae8d48c22c38bb6cf4ce85e9f7cf04e9d706142b41b6565099d71baf2801d3cecec38124c731d4cf9dfa60c1cc685919dc9261952f27b74a4cdf8daca6c1556e3a890a78f379089bab2527fda05081357528ab283eff5e3ebad84db0587f54ea40d5f55939f7e3c599a60d193af47eda07243b7ddd784ff4078c1820d1e23990c8d3dd1b8000", .None}, + {.Shl, "-925b0dc9359fd45aea16be1e8347a58890534f5ab2009d04c6a5a5604435abe4d7200782ea093dd0fcd1f35f2fbebaa74e069eb05cc35e1a4a41e8fc83ac161e058c55784406d82a6a0378a689d29a62564bd6a2b63fbc302dbb351b4c7411bc4bb8591cdf66769192a1fc39a0e40f449110e026bbf3e50acbb5aa61712f1aedc11e8b0337435bcd1627cd693594444e45e458d33602", "66", "-2496c3724d67f516ba85af87a0d1e9622414d3d6ac80274131a96958110d6af935c801e0ba824f743f347cd7cbefaea9d381a7ac1730d78692907a3f20eb05878163155e1101b60a9a80de29a274a6989592f5a8ad8fef0c0b6ecd46d31d046f12ee164737d99da464a87f0e683903d124443809aefcf942b2ed6a985c4bc6bb7047a2c0cdd0d6f34589f35a4d65111391791634cd8080000000000000000000000000", .None}, + {.Shl, "-ea79d96ca3e69c091eb8f070ffdad303a84291b4ca5b350ccd074b1324eba2d2c769668468c973e6743ae6b9c2b9794856ba6ce894176b2f7d6bdd1c0136f0d919885b173e4ca29ff4a7245f8ec05541d5c5e93ee197835346233a0270cf12927f2b133522dbdee515da8a42924e2e1f0da9718c0057c241e4d2392d2578276c418ef37dd92181779430f1e36bb36190a28b1fed6678", "32", "-3a9e765b28f9a70247ae3c1c3ff6b4c0ea10a46d3296cd433341d2c4c93ae8b4b1da59a11a325cf99d0eb9ae70ae5e5215ae9b3a2505dacbdf5af747004dbc36466216c5cf9328a7fd29c917e3b0155075717a4fb865e0d4d188ce809c33c4a49fcac4cd48b6f7b94576a290a4938b87c36a5c630015f09079348e4b495e09db1063bcdf7648605de50c3c78daecd86428a2c7fb599e0000000000000", .None}, + {.Shl, "-33e57485e39bd6d226ceef8faabe096a889b60ea5537db0d892404efc1cc280f11d43ac8739acae97945257071fb736e4b0cfc243167c01408e0a8cd560cdb3f99f7c94f44f3f2b134a73f06df8b99ceb227547f29cbae74e7f3c80fd332d47d0de290a93720234500814e4fd65dfd9cf5efff045e4af9fca7f90f8429b214f23a9b1a56754443c71ad873b761d21226914bbd3f6db5", "13", "-19f2ba42f1cdeb69136777c7d55f04b5444db0752a9bed86c4920277e0e6140788ea1d6439cd6574bca292b838fdb9b725867e1218b3e00a04705466ab066d9fccfbe4a7a279f9589a539f836fc5cce75913aa3f94e5d73a73f9e407e9996a3e86f148549b9011a28040a727eb2efece7af7ff822f257cfe53fc87c214d90a791d4d8d2b3aa221e38d6c39dbb0e9091348a5de9fb6da80000", .None}, + {.Shl, "e9b64f29cb38a0468ff874317c5f3ffb7ac7dfb5a957a556a646edba1ae5de16d43ad9a2c9b0ae037e90a232ae2db6b44e24ee430c74d3f1a5200074a45c721464c17ba099eb9c6027aecb44e2727167083732bfdabf8bc7735a0d8e0433403e935ee483713ae1d24032a9880ab63a596e467658847e9ce4fd848ca6eceaef77a160cd2751438c85ad72cd39a2d10b6e7df4bac81d86", "2e", "3a6d93ca72ce2811a3fe1d0c5f17cffedeb1f7ed6a55e955a991bb6e86b97785b50eb668b26c2b80dfa4288cab8b6dad13893b90c31d34fc6948001d29171c8519305ee8267ae71809ebb2d1389c9c59c20dccaff6afe2f1dcd68363810cd00fa4d7b920dc4eb874900caa6202ad8e965b919d96211fa7393f612329bb3abbdde8583349d450e3216b5cb34e68b442db9f7d2eb20761800000000000", .None}, + {.Shl, "-7de523d73f78a7202ec344e5f2f2434edea54bd304b0d76746953106f7e446cae9186f0db830568e850121900064275c620bd744a902e58fa668685ce61932ab79497a398c2642f5ac5971dd2574e0a1b3311d8711141b330442b09821592711c73a6e747e07f928c3943f2444b66a1ff458d11972f5e439e39e31f8f28fc91cf06314f95945c9e5567ea06c92ee79a032665cd08a93", "20", "-7de523d73f78a7202ec344e5f2f2434edea54bd304b0d76746953106f7e446cae9186f0db830568e850121900064275c620bd744a902e58fa668685ce61932ab79497a398c2642f5ac5971dd2574e0a1b3311d8711141b330442b09821592711c73a6e747e07f928c3943f2444b66a1ff458d11972f5e439e39e31f8f28fc91cf06314f95945c9e5567ea06c92ee79a032665cd08a9300000000", .None}, + {.Shl, "f2abba0450ad2d7ceb270f4d3d9840e2b61c03caed3311ac1c8e9fb86335b582554901da24464757adce89e43fc90a58a0c27772366c44f3de1070ae52a3cc562b37fa5eac59dc76b7ee6d7b6ff3ba19eb0716ba762b3724e1c1ad90a26a9b0cf16f1e30378bec6ccfcd2b6e9172237ca642ed60f56cdf5386b284988181e87f9d85c9a9e6d3b6d06b0b1a9e3ab1f3a4765d52bf7886", "49", "1e5577408a15a5af9d64e1e9a7b3081c56c380795da662358391d3f70c66b6b04aa9203b4488c8eaf5b9d13c87f9214b14184eee46cd889e7bc20e15ca54798ac566ff4bd58b3b8ed6fdcdaf6dfe77433d60e2d74ec566e49c3835b2144d53619e2de3c606f17d8d99f9a56dd22e446f94c85dac1ead9bea70d6509310303d0ff3b0b9353cda76da0d616353c7563e748ecbaa57ef10c000000000000000000", .None}, + {.Shl, "-e0f5e95519820ffbad25e4231e2ea406615fc28bb4b9ae0887c62e2ed0c9c698e5f5413428f134f2dafaf2c1390cabfa8f1f20efa8c01372b895d5ead1ffb2eaea883a78678793ddd55bb3a3cffcb7140f228e6feef75d7584b1bf0717180665ec5a7a7001ebf7e4bb069cad0a9f768b21b12062e44bb469247657392b1bede5885bf58a97f4fc171c0b09ae29708d66a02d746c11b7", "74", "-e0f5e95519820ffbad25e4231e2ea406615fc28bb4b9ae0887c62e2ed0c9c698e5f5413428f134f2dafaf2c1390cabfa8f1f20efa8c01372b895d5ead1ffb2eaea883a78678793ddd55bb3a3cffcb7140f228e6feef75d7584b1bf0717180665ec5a7a7001ebf7e4bb069cad0a9f768b21b12062e44bb469247657392b1bede5885bf58a97f4fc171c0b09ae29708d66a02d746c11b700000000000000000000000000000", .None}, + {.Shl, "fca6ea9394031001be7d213a534e52831685b498a903659aa4807263f9839b2969350d4acb2583cb698a6ab47cee1b2f48d23b198be54486b131d89abe5793495ba7889007d06e99d7abec35b1d367fd5b9ebfbe9e4fc1754b22e439027aedfd236047ab943c75833191a6d19b8a0ae881cddb16e201e149e57557dd575f98d0792f16d5887055799ea4a903aa3860a863d725078f59", "3d", "1f94dd527280620037cfa4274a69ca5062d0b69315206cb354900e4c7f3073652d26a1a95964b0796d314d568f9dc365e91a4763317ca890d6263b1357caf2692b74f11200fa0dd33af57d86b63a6cffab73d7f7d3c9f82ea9645c87204f5dbfa46c08f572878eb0663234da3371415d1039bb62dc403c293caeaafbaaebf31a0f25e2dab10e0aaf33d4952075470c150c7ae4a0f1eb2000000000000000", .None}, + {.Shl, "1fdeab42a4d28688edd5a8d0a10677908b8ffa438bd1509a56eb9f95daca9bb9d8df1c20980f0e8a80fd62c6ed730610c2af102f57243f53870fe27fde590e1096b8fd9a8b575b7b890749d3073353f99d3235d77e043afd16dc140ce98c4d5ab3e8208b69271fbae0735d45e40d147ccf461ef03f5d5dd6493d6791abbaf23f3c27200d783c45a7c2b5c0752cee0903346d210fe55a", "56", "7f7aad0a934a1a23b756a3428419de422e3fe90e2f4542695bae7e576b2a6ee7637c7082603c3a2a03f58b1bb5cc18430abc40bd5c90fd4e1c3f89ff796438425ae3f66a2d5d6dee241d274c1ccd4fe674c8d75df810ebf45b705033a631356acfa0822da49c7eeb81cd7517903451f33d187bc0fd75775924f59e46aeebc8fcf09c8035e0f1169f0ad701d4b3b8240cd1b4843f9568000000000000000000000", .None}, + {.Shl, "aedc339fdd2787faba971ff6e3e75f70073bf39d8dd6473e60d7aef1ceea00130c48b93143aa059be6aa71fc94a77f74d00b64cfdfcb5e0f3fc570b7b2ea2f664bcb2e876d21062ad84676e534f64357a12dbad2eafb11715af0cde6bd4598ef16275e76b8493f2932bbf8b66edf725bf5990f875a8e487e9036d75d2d843c7657341d429b439ee9b6cb51258a273bba37f61322b4d6", "8", "aedc339fdd2787faba971ff6e3e75f70073bf39d8dd6473e60d7aef1ceea00130c48b93143aa059be6aa71fc94a77f74d00b64cfdfcb5e0f3fc570b7b2ea2f664bcb2e876d21062ad84676e534f64357a12dbad2eafb11715af0cde6bd4598ef16275e76b8493f2932bbf8b66edf725bf5990f875a8e487e9036d75d2d843c7657341d429b439ee9b6cb51258a273bba37f61322b4d600", .None}, + {.Shl, "-346e1df1dc58b56a9abd10e11a9649c2f0fa7d86f1c280f6ac503c03db1ff889f274b14c747ddba402b6bd4b7157d7c6c73459358bbc1bb045e530f721ccbde0a3fa242f2399c1bf1ea3adddc9e6867b2234c5d4fd838cf6140c2a27079a51df1fe4513a786b4fedee53cb3ce5fc98e7beaf5447c89a130703f58a2f81bc52a5b310be2e0e06f2301eeb86c0454e0261944d9dc17204", "35", "-68dc3be3b8b16ad5357a21c2352c9385e1f4fb0de38501ed58a07807b63ff113e4e96298e8fbb748056d7a96e2afaf8d8e68b26b177837608bca61ee43997bc147f4485e4733837e3d475bbb93cd0cf644698ba9fb0719ec2818544e0f34a3be3fc8a274f0d69fdbdca79679cbf931cf7d5ea88f9134260e07eb145f0378a54b66217c5c1c0de4603dd70d808a9c04c3289b3b82e4080000000000000", .None}, + {.Shl, "c5b0660ce03b0c1856f86b5f173a03980797b67543d0167a3c68f18dc4714682a428fd5dfe4a427528a0b234de083c0bc05bb47e3b5a55e2a85cdd8f47458c38b3a397a13217b242f2582126db69d44067f97a5a6c29f911ba4bd7db467958a2d38f7d6c18522f678113ac827578c197c40a52070e4097323c5bad9cde3fce15b9b234874659781f05335c4856053db65c09efad3756", "4e", "316c1983380ec30615be1ad7c5ce80e601e5ed9d50f4059e8f1a3c63711c51a0a90a3f577f92909d4a282c8d37820f02f016ed1f8ed69578aa173763d1d1630e2ce8e5e84c85ec90bc960849b6da751019fe5e969b0a7e446e92f5f6d19e5628b4e3df5b06148bd9e044eb209d5e3065f1029481c39025cc8f16eb67378ff3856e6c8d21d1965e07c14cd71215814f6d97027beb4dd580000000000000000000", .None}, + {.Shl, "-c52879f49b8a3ad936b90d8fca4962c4ef9af6a3ea42cf2257be2f752ad5def2e37d138d83eef773ce47c5265f6172dd6fa2a8a092e26581de24eca2297444a39ddde250895e8b2ad09c95ac1b114f1531baa29521f12fa4b1a54848c8916041d455a8e1bf0c55293746a42b8e29149f01bde6e45e0d6bed03ed5f7b539e86ef8b6812e530d1c67ec2c0382cd665385960cdecc56270", "4b", "-62943cfa4dc51d6c9b5c86c7e524b16277cd7b51f52167912bdf17ba956aef7971be89c6c1f77bb9e723e2932fb0b96eb7d15450497132c0ef12765114ba2251ceeef12844af4595684e4ad60d88a78a98dd514a90f897d258d2a4246448b020ea2ad470df862a949ba35215c7148a4f80def3722f06b5f681f6afbda9cf4377c5b409729868e33f61601c166b329c2cb066f662b1380000000000000000000", .None}, + {.Shl, "-a055bdc8d1a3003cc8b199c098f58ff409af5d1f7379b0d4a7d157f1cf6bb93cb02ceeb266a61ef26c495f793149b5fe667c51efa401baf0eb9ab97ec3fe42a1075d83441dfbd870534d874018292731b3932c9bc4f33f19a366d8ff102e1ec3b6f18b22eb02e858d4169868bda4b78cb2821de5e3f8a8c820b325b2d2be36c6c79e2f5351242148e011dff1d39ae3a89657cbab6c2e", "6e", "-28156f723468c00f322c6670263d63fd026bd747dcde6c3529f455fc73daee4f2c0b3bac99a987bc9b1257de4c526d7f999f147be9006ebc3ae6ae5fb0ff90a841d760d1077ef61c14d361d0060a49cc6ce4cb26f13ccfc668d9b63fc40b87b0edbc62c8bac0ba163505a61a2f692de32ca0877978fe2a32082cc96cb4af8db1b1e78bd4d4490852380477fc74e6b8ea2595f2eadb0b8000000000000000000000000000", .None}, + {.Shl, "25ff8c77bc04a276172e1281f81bbddf14a3239017a66fb9305976cc28c55e33e8fca01c8fc1bae5873aa7f7c56f55e75630326069f0991bd9d5278357b7e5fb226b526e9df7c6ac5c895036330370e96f78bbba70cbf2f13e6e0480c65bb9cb2a050b9850c118f4b29869d15314bf00fce09afed9e36547caa20d5a26bf3e9c30855ae18d644b8e5fbb24b3dffdfcbed85bddf8e63f", "69", "4bff18ef780944ec2e5c2503f0377bbe294647202f4cdf7260b2ed98518abc67d1f940391f8375cb0e754fef8adeabceac6064c0d3e13237b3aa4f06af6fcbf644d6a4dd3bef8d58b912a06c6606e1d2def17774e197e5e27cdc09018cb77396540a1730a18231e96530d3a2a6297e01f9c135fdb3c6ca8f95441ab44d7e7d38610ab5c31ac8971cbf764967bffbf97db0b7bbf1cc7e00000000000000000000000000", .None}, + {.Shl, "f820074502cdd4823f44b939ef8982a0bfbd01cef73cc1dac8323c3261ded35c03c67c9641c90813c48f4421f490ae7af405941059f1ae5f394079c7bf69ceab35042db2e913766a39f0227f4426d2653260b522d442eb3169e0bfa8317a9462e23ed433631ad672eca78748b3a3ff625336c60d21ac792b65d93f88f27da33da1c162965eab29121e14392e3f636d96a99c2e382e62", "40", "f820074502cdd4823f44b939ef8982a0bfbd01cef73cc1dac8323c3261ded35c03c67c9641c90813c48f4421f490ae7af405941059f1ae5f394079c7bf69ceab35042db2e913766a39f0227f4426d2653260b522d442eb3169e0bfa8317a9462e23ed433631ad672eca78748b3a3ff625336c60d21ac792b65d93f88f27da33da1c162965eab29121e14392e3f636d96a99c2e382e620000000000000000", .None}, + {.Shl, "-50b040fa6b955f281924b6f1e3a30c46bad1d05628d38d2d5195dd0c3b1b8def7b728d7329c812b07d9e9447707722069a9cd52e9fe1338ea2b4871906e7f16c22ff789c2833c21e674f0aa755fff1f939482b43eee839bf238d981d50a2ffe503f72bdf325d6c20fe438d7a8dc160defd6effc6d8b0c956a74830b48207faac429540de3e1584fa2628464b9f40c9bffcf616e151da", "3f", "-2858207d35caaf940c925b78f1d186235d68e82b1469c696a8caee861d8dc6f7bdb946b994e409583ecf4a23b83b91034d4e6a974ff099c7515a438c8373f8b6117fbc4e1419e10f33a78553aafff8fc9ca415a1f7741cdf91c6cc0ea8517ff281fb95ef992eb6107f21c6bd46e0b06f7eb77fe36c5864ab53a4185a4103fd56214aa06f1f0ac27d13142325cfa064dffe7b0b70a8ed0000000000000000", .None}, + {.Shl, "-4782c3fd1f8e811a33d1fd36a2aa0067c191c0c54168bd21e3dec443e8adba629a26ac22a697e499cb23c4cfd05e72dcd835f5fb5ea1c22d27884a7babab780c986929d8d9fe4a2dd56e52c8ac13f787cf48b4f1b4e02e5abacb7d32702efdbc0e2e25dab073360c19c7f67a2f06eec042248e3e64bd3e1af1fa43d0631820dc030aab44305c77ceb42aa6f47acf235c9a1e00bcfaf5", "2c", "-4782c3fd1f8e811a33d1fd36a2aa0067c191c0c54168bd21e3dec443e8adba629a26ac22a697e499cb23c4cfd05e72dcd835f5fb5ea1c22d27884a7babab780c986929d8d9fe4a2dd56e52c8ac13f787cf48b4f1b4e02e5abacb7d32702efdbc0e2e25dab073360c19c7f67a2f06eec042248e3e64bd3e1af1fa43d0631820dc030aab44305c77ceb42aa6f47acf235c9a1e00bcfaf500000000000", .None}, + {.Shl, "-291b2ac6ce7b1af1e7f630ecfb88b1ed82e0d978ce6362d8e75d8af32502757ba50979c58326168a6a1c49c89e79ba1d27c7fb5c90e7c019e0aa7ad4d451422eebad4937190610b2fe9268a654a797fe022c1d3291b333ef8fe86adb7cdab65deeccfbc1a349ab271b1300a90effb1e540609af43ea53414a900cf979affa074a95b1fc52c110609d57cd745f21ae06757253ccd381", "2", "-a46cab1b39ec6bc79fd8c3b3ee22c7b60b8365e3398d8b639d762bcc9409d5ee9425e7160c985a29a871272279e6e8749f1fed72439f006782a9eb53514508bbaeb524dc641842cbfa49a299529e5ff808b074ca46cccfbe3fa1ab6df36ad977bb33ef068d26ac9c6c4c02a43bfec79501826bd0fa94d052a4033e5e6bfe81d2a56c7f14b044182755f35d17c86b819d5c94f334e04", .None}, + {.Shl, "4367438e9c1f84f4d399683e4a85c2cecc47af17854379911c0a1d04c655514393406bd1946a47a9f8fa9e344cc07f9b6e872d7641fec3b1ef5c2124db3745d47677f83331763c2d7133bfc69f74ea1ea7f0d32d2ca3af95c2a125e622d42c68840b3e4a3d4e07d63853fda7098abc151f97edbfa3ba04e340dcdc7a19dd0bbcf6e286a6d5ccba77d6f88ee9e92db1ebbfb84aab460a", "f", "21b3a1c74e0fc27a69ccb41f2542e1676623d78bc2a1bcc88e050e82632aa8a1c9a035e8ca3523d4fc7d4f1a26603fcdb74396bb20ff61d8f7ae10926d9ba2ea3b3bfc1998bb1e16b899dfe34fba750f53f869969651d7cae15092f3116a163442059f251ea703eb1c29fed384c55e0a8fcbf6dfd1dd0271a06e6e3d0cee85de7b7143536ae65d3beb7c4774f496d8f5dfdc2555a3050000", .None}, + {.Shl, "-80b861c91513357f6a1f3618e99b22aa2478018b65f909d5ad9891b16893cf504cebed05d87a512b3b9480859839b4b4d376d822541f6cb6b15d44af43d723bf937619b4169a79cae05b3b08bc6ffadd16422079085063bf1ebd664dcc39279967c21efddb7a1cacbcdc62b5a441f675a8e047e5a8bd03e6ccd1aedbda288c034d95b96ffd0550f31e0d371c1e81a52fb3a95112cfe7", "a", "-202e18724544cd5fda87cd863a66c8aa891e0062d97e42756b66246c5a24f3d4133afb41761e944acee52021660e6d2d34ddb6089507db2dac57512bd0f5c8efe4dd866d05a69e72b816cec22f1bfeb74590881e421418efc7af5993730e49e659f087bf76de872b2f3718ad69107d9d6a3811f96a2f40f9b3346bb6f68a2300d3656e5bff41543cc7834dc707a0694becea5444b3f9c00", .None}, + {.Shl, "-ddf19ff05a4595680227eef3b2fde008a30af05b28335ba74fc1d610d594b8f0535bb4a0a9e3b0864fdd23273071b7faca7d428946ee07014e927e9b5f391987ddd23a4f191668859c05b6af13a5892e933588ce38708510f04b54fafbe4f5cf7ed8bc8c9496c4c660b4da25ffe449e6652aab3aa87d59127cbe464bc7dbfdfa498e1729cff67ba2ea4ca385f3ae184726da82a0b4a7", "8", "-ddf19ff05a4595680227eef3b2fde008a30af05b28335ba74fc1d610d594b8f0535bb4a0a9e3b0864fdd23273071b7faca7d428946ee07014e927e9b5f391987ddd23a4f191668859c05b6af13a5892e933588ce38708510f04b54fafbe4f5cf7ed8bc8c9496c4c660b4da25ffe449e6652aab3aa87d59127cbe464bc7dbfdfa498e1729cff67ba2ea4ca385f3ae184726da82a0b4a700", .None}, + {.Shl, "6d29ccc0bc3acc49e433e7b0e15075bd9eb7c2119ae3dceaae5db15e8ca2f0566df4400844dca4a3d23f1a84118ddca3e2ee3951aef2916781f48a2f952dd3fd2e460fb33e00193856e4eeffdddef214bbc509a64be9fc59bf89dde20b71545d1fbc7ff1701eb1eaf3702a8c5367d8c9e189b30b59c3e75100980999e855055358c14efa37fa08d1fe0eb3a15885efd8731c6a99a289", "2f", "3694e6605e1d6624f219f3d870a83adecf5be108cd71ee75572ed8af4651782b36fa2004226e5251e91f8d4208c6ee51f1771ca8d77948b3c0fa4517ca96e9fe972307d99f000c9c2b72777feeef790a5de284d325f4fe2cdfc4eef105b8aa2e8fde3ff8b80f58f579b8154629b3ec64f0c4d985ace1f3a8804c04ccf42a82a9ac60a77d1bfd0468ff0759d0ac42f7ec398e354cd144800000000000", .None}, + {.Shl, "-3feb0fd712a20fe3b38b71a848c3bb9989bd27fdf8a83b513c37b291b1a7630f3cafd52699da510f76167878a1afbd592d9ce4171811ce2fb43e791b9fa3faa88778bfb7c6f5c79da98ca7702eef3c33e966e4380e5b238d2262df6a429e0546996a1e73b3297fb3bd67e2f340256d53ba14cd117d4e5c696267b2cb401d2019f21d416b8243fab524e0441f75455e68d4420e000516", "2c", "-3feb0fd712a20fe3b38b71a848c3bb9989bd27fdf8a83b513c37b291b1a7630f3cafd52699da510f76167878a1afbd592d9ce4171811ce2fb43e791b9fa3faa88778bfb7c6f5c79da98ca7702eef3c33e966e4380e5b238d2262df6a429e0546996a1e73b3297fb3bd67e2f340256d53ba14cd117d4e5c696267b2cb401d2019f21d416b8243fab524e0441f75455e68d4420e00051600000000000", .None}, + {.Shl, "-d0307f04ca283e10f2586a0f2ce7218233142da075c54d202b068442d59cfdbb3056de84d2b5f9932f3631623f597c413cd2e9c45f74b0ce3174e50accbfe43f8b96694ffd49a2d9e7fb289b8bc2da3c6365533ed66f5f056d8fcc4b3d0a064ee5790d3b83692986c670e867dc38f1441af678aad0ecf3221a77833190a9f55591b670113893ac07f328642ad39c7fed08beef73f0c3", "3f", "-68183f8265141f08792c3507967390c1198a16d03ae2a690158342216ace7edd982b6f42695afcc9979b18b11facbe209e6974e22fba586718ba7285665ff21fc5cb34a7fea4d16cf3fd944dc5e16d1e31b2a99f6b37af82b6c7e6259e85032772bc869dc1b494c363387433ee1c78a20d7b3c55687679910d3bc198c854faaac8db38089c49d603f994321569ce3ff6845f77b9f8618000000000000000", .None}, + {.Shl, "-9490fe1c9427a8e0bd56d86b73d2379790fc2139a89148af932b94e3224d67c24bbad56766e83ea88921506f1912081efb60a6d80be2e409ad2c354087b469ed7d0d604922db69281b00313aaeb3588d7894b9d89d140151b33c73841c5ac56e801caa9c913f4abf82f73a165f11d20e1c5d0c0c44cde8724b49eaa6bc693aed869e763dd48e4efa4e1b9e864293b83ee2339dbbd36e", "19", "-12921fc39284f51c17aadb0d6e7a46f2f21f842735122915f265729c6449acf849775aacecdd07d511242a0de3224103df6c14db017c5c8135a586a810f68d3dafa1ac09245b6d250360062755d66b11af12973b13a2802a36678e70838b58add00395539227e957f05ee742cbe23a41c38ba1818899bd0e49693d54d78d275db0d3cec7ba91c9df49c373d0c8527707dc4673b77a6dc000000", .None}, + {.Shl, "-a2e00cb51fbd19581226bec7d415ff73c18235fbd84cd0ed91f3c78eab4dc77e7dce4a9fec6c498199b937f6dcc11ec066a07387ac5e51ad9c16f45300d80887e50ceff7f12fccb1b3342ad3e1edfb28ce228ee69ee07e9c673433ca3de9d38b1083aafe81debf6f6f817d7db0ed7aff8d5225b21279e61071120000361e5f326d8032b1af655e561d2af20d092b8ac9c3e858bb30bd", "6a", "-28b8032d47ef46560489afb1f5057fdcf0608d7ef613343b647cf1e3aad371df9f7392a7fb1b1260666e4dfdb73047b019a81ce1eb17946b6705bd14c0360221f9433bfdfc4bf32c6ccd0ab4f87b7eca3388a3b9a7b81fa719cd0cf28f7a74e2c420eabfa077afdbdbe05f5f6c3b5ebfe354896c849e79841c4480000d8797cc9b600cac6bd95795874abc83424ae2b270fa162ecc2f400000000000000000000000000", .None}, + {.Shl, "-afb99f56f846932399cb23683a3dccf18585c35cb2626e053476c5a45a54698435910aeef64681addac2a956b200cb7e69c0505c4a796e659c0685d25776a611e5bcca4e55eac13c8ffdfe6c653a5f29e8ede0cc7a176c0086de7da30409a353382947ed034190114a7bf71089d26faea47781c56eba38f0573c96654fb25c10c90ffc2a039597553aa25a266fb258520c5d80160b40", "3c", "-afb99f56f846932399cb23683a3dccf18585c35cb2626e053476c5a45a54698435910aeef64681addac2a956b200cb7e69c0505c4a796e659c0685d25776a611e5bcca4e55eac13c8ffdfe6c653a5f29e8ede0cc7a176c0086de7da30409a353382947ed034190114a7bf71089d26faea47781c56eba38f0573c96654fb25c10c90ffc2a039597553aa25a266fb258520c5d80160b40000000000000000", .None}, + {.Shl, "-eaaeb9845289c656b3f68d900a79f7668bf1f69ae4529157ac9c17180a6a9dc997543ae1ad1cce04cac1dc2b8121a37718dd196e6ccdf959a5ec48fe696b7a5ab6022940713fe546a5e11e19d2e540c6449981da14c0b268c0e020d226aa0f367c9729dfcc09e71a32cb2b300ddc10762b9f161d41d419ef3fede72dbc80918e83b5e13694c49529aae41eb3b3b16814523584689135", "b", "-75575cc22944e32b59fb46c8053cfbb345f8fb4d722948abd64e0b8c05354ee4cbaa1d70d68e67026560ee15c090d1bb8c6e8cb73666fcacd2f6247f34b5bd2d5b0114a0389ff2a352f08f0ce972a063224cc0ed0a605934607010691355079b3e4b94efe604f38d1965959806ee083b15cf8b0ea0ea0cf79ff6f396de4048c741daf09b4a624a94d5720f59d9d8b40a291ac234489a800", .None}, + {.Shl, "-7eca7d013143c5857b800e3989b82ba214f9a2740fbb41b81e2b6f9ea77f5897e79b496e476c8b0273d7732ededbe572f9c84dbdb96e8fff1f7af44dbee07db0291c76d672476e7a016dff2c3c0731c203a06f1bc3f70f2ae6eb13cc629ec62796a3d33d914f254c4cc8cf5e110de29620b90cbe4e8aee042522ee1476575b9f9c6c52cb7bbd9ba68edfc45adc3c0d5ce9e1b8a3e8b3", "49", "-fd94fa0262878b0af7001c731370574429f344e81f7683703c56df3d4efeb12fcf3692dc8ed91604e7aee65dbdb7cae5f3909b7b72dd1ffe3ef5e89b7dc0fb605238edace48edcf402dbfe58780e63840740de3787ee1e55cdd62798c53d8c4f2d47a67b229e4a9899919ebc221bc52c4172197c9d15dc084a45dc28ecaeb73f38d8a596f77b374d1dbf88b5b8781ab9d3c37147d166000000000000000000", .None}, + {.Shl, "c773df1157cf00a8a40016a16fba9e9b5cf2463fe90928b2eed810d74bbff52e630720bf9162db243506acb2184149603bbcf0272f739aa781fd3ad87f9616eb39d4dfaa7269a2b27255721e88ae2a87415ce84e149385324bf0a2f0839c4d9223d9a66869f1f5564bcc378132e09a037fed7ae7dc65256a30e844bf1a4c1100c749e5eb58b7319707ef236bcfe1e8bb71231547781f", "78", "c773df1157cf00a8a40016a16fba9e9b5cf2463fe90928b2eed810d74bbff52e630720bf9162db243506acb2184149603bbcf0272f739aa781fd3ad87f9616eb39d4dfaa7269a2b27255721e88ae2a87415ce84e149385324bf0a2f0839c4d9223d9a66869f1f5564bcc378132e09a037fed7ae7dc65256a30e844bf1a4c1100c749e5eb58b7319707ef236bcfe1e8bb71231547781f000000000000000000000000000000", .None}, + {.Shl, "55366899a50ec665fc04f40a5e3950559e79d1c8ac7b3e34b05dbbe3c0b1359f76b7ef8fc298f2b1c8bd38e552b524ba15778bac2ec398fc4344f9788ec03b9ad7e6e2ddef2fd05ccdcef0c1c9edf5b21606d0bd5d92dffbc9eee135b707233ccecceb4978e56dc1cbd3ae5afe4a494ca02709987c8d02c1eb0ae2cdb35c18f5dae566b8245d42cc3dc6247a60882bdd6cccadf3ec43", "4", "55366899a50ec665fc04f40a5e3950559e79d1c8ac7b3e34b05dbbe3c0b1359f76b7ef8fc298f2b1c8bd38e552b524ba15778bac2ec398fc4344f9788ec03b9ad7e6e2ddef2fd05ccdcef0c1c9edf5b21606d0bd5d92dffbc9eee135b707233ccecceb4978e56dc1cbd3ae5afe4a494ca02709987c8d02c1eb0ae2cdb35c18f5dae566b8245d42cc3dc6247a60882bdd6cccadf3ec430", .None}, + {.Shl, "c7d44c6fa7509e4b2b2bfbe836edf783b713105dbe121206dbb1b14e3678e30843cfd2197ada73e29da7b0a77ba67474065e62994d096a91b6ed7e350eba85bd7f9ef4368a125906c916719c3495c9a330fecb14d0842e836a698fb266aab12982b328d97417957d04a3c8f21287cad661e49a2164e695308d741c9fd1156a86c690ea842f3a152831e272a0211ecb6fdcbbfcf943e5", "2e", "31f5131be9d42792cacafefa0dbb7de0edc4c4176f848481b6ec6c538d9e38c210f3f4865eb69cf8a769ec29dee99d1d019798a653425aa46dbb5f8d43aea16f5fe7bd0da2849641b2459c670d257268cc3fb2c534210ba0da9a63ec99aaac4a60acca365d05e55f4128f23c84a1f2b5987926885939a54c235d0727f4455aa1b1a43aa10bce854a0c789ca80847b2dbf72eff3e50f9400000000000", .None}, + {.Shl, "-ed184f9f2630d93cde2941613612ee9e6c30a0ded5df73a2e98865fa171b691e234bf4e377cf655e0abea5e8a462d743f468799995e4aed16356b518c094a151903fba9c8f1c7ddeef62ef2afc03b75bc8f345fcc699d8186a9498bfc40269670aba2912fb8a269e6b03f815e4b2119c6c3f0db0918c8f1e5c56a3f6302ae6211c5044808869e2c07065799d4e8ce739dc92a4690f73", "17", "-768c27cf93186c9e6f14a0b09b09774f3618506f6aefb9d174c432fd0b8db48f11a5fa71bbe7b2af055f52f452316ba1fa343ccccaf25768b1ab5a8c604a50a8c81fdd4e478e3eef77b177957e01dbade479a2fe634cec0c354a4c5fe20134b3855d14897dc5134f3581fc0af25908ce361f86d848c6478f2e2b51fb181573108e2822404434f1603832bccea746739cee49523487b9800000", .None}, + {.Shl, "e9d598550128bb56b1ca9c54cfedc4d85054c93ea3e076dc4e53b05c11d4a81baa0529c71f521ecc68552b5337b2fad3676f090c3727cb3f3235f7c854f404b1227d6598bb57756bfd7774f304ffc86204ac99730b07bba3cda2d3adb310a3d2133f55c12a42ef6be77872821269e37758b118dc2c94846dd60297e482f420e2871217d1e562198305e6966f2c197a1df76c3b84f44c", "62", "3a756615404a2ed5ac72a71533fb71361415324fa8f81db71394ec1704752a06ea814a71c7d487b31a154ad4cdecbeb4d9dbc2430dc9f2cfcc8d7df2153d012c489f59662ed5dd5aff5ddd3cc13ff218812b265cc2c1eee8f368b4eb6cc428f484cfd5704a90bbdaf9de1ca0849a78ddd62c46370b25211b7580a5f920bd0838a1c485f479588660c179a59bcb065e877ddb0ee13d130000000000000000000000000", .None}, + {.Shl, "-14c9918d2e65a819487e9d603bcf570b602f39709d1fdb6d77b325a04267e773187d5ad4115ae8707f36bc5aad941f204af6ecbd2e1b313602f2bad342ed60d7a33fa3344e457f00f7bb7e24477ad5992098fc645397b27724adb4563c005719f13cc8840038f48062ce415566c6a796382fa9d94a8f897007f7a51d03ff44d2f8d8744b48d65caa421d4c4365ca6c57b5ee4a0423ba", "12", "-53264634b996a06521fa7580ef3d5c2d80bce5c2747f6db5decc9681099f9dcc61f56b50456ba1c1fcdaf16ab6507c812bdbb2f4b86cc4d80bcaeb4d0bb5835e8cfe8cd13915fc03deedf8911deb56648263f1914e5ec9dc92b6d158f0015c67c4f3221000e3d2018b3905559b1a9e58e0bea7652a3e25c01fde94740ffd134be361d12d235972a90875310d9729b15ed7b928108ee80000", .None}, + {.Shl, "33af503e7433916b09542c018bc6d3ef86bace760866eb81bff265b6bf559080d7cda6aaef535e395e0e5544b09234dd68fcad85f913fa6cc9653f4afa764548077903f613759fdf44d94d6567321622136a1a4dba25f321e80d8f009f43c08002022aa35b51764f49f221e080cdc567f48e7fad1ac760de1390943e7d3c422f147bd8e62339a66fb62484e4c241fc01d38667d4a946", "61", "675ea07ce86722d612a85803178da7df0d759cec10cdd7037fe4cb6d7eab2101af9b4d55dea6bc72bc1caa89612469bad1f95b0bf227f4d992ca7e95f4ec8a900ef207ec26eb3fbe89b29acace642c4426d4349b744be643d01b1e013e87810004045546b6a2ec9e93e443c1019b8acfe91cff5a358ec1bc2721287cfa78845e28f7b1cc46734cdf6c4909c98483f803a70ccfa9528c000000000000000000000000", .None}, + {.Shl, "-794509acf09f3e04d2770436e818512363c63f90dffeef055d388839a57047dc6829bc7c9fcbfe9ebbb5aebe0c46df02b5f51cf629977f50e90ec719ba6858ca07a6445eac3ecd1e1e1cc1a70166626989663f6c07de227945642f4fa4d340f06b133068453a2e0c6140f39f7ed5df0ab4688becf615a5f3040aabc97eb424e53355e3e17993e7582e8dab0e1eec5e00d8779bb461d7", "22", "-1e51426b3c27cf81349dc10dba061448d8f18fe437ffbbc1574e220e695c11f71a0a6f1f27f2ffa7aeed6baf8311b7c0ad7d473d8a65dfd43a43b1c66e9a163281e99117ab0fb34787873069c059989a62598fdb01f7889e51590bd3e934d03c1ac4cc1a114e8b8318503ce7dfb577c2ad1a22fb3d85697cc102aaf25fad09394cd578f85e64f9d60ba36ac387bb1780361de6ed1875c00000000", .None}, + {.Shl, "-2022594775e741fdddc249e3ade53df44c561fee0c9175266d9d1c6f132b5df80783c4126e7db0f162fda3c46a9e1768970ad73f5ceb95b3338cfb2f8575778b4d89e910e044d3bfc89fb250a757ae4840addc091979a92179ba0a389634a0941a9e27e5fa21b6d0226cda7a2b8c7d56240193512f0c47c372151d068913575cb7abe8bbbf3567448a29dd1e4f55fe3c42cd32c3ab07", "35", "-4044b28eebce83fbbb8493c75bca7be898ac3fdc1922ea4cdb3a38de2656bbf00f078824dcfb61e2c5fb4788d53c2ed12e15ae7eb9d72b666719f65f0aeaef169b13d221c089a77f913f64a14eaf5c90815bb81232f35242f37414712c694128353c4fcbf4436da044d9b4f45718faac480326a25e188f86e42a3a0d1226aeb96f57d1777e6ace891453ba3c9eabfc78859a6587560e0000000000000", .None}, + {.Shl, "51bf53220729fde68fabfa209707217a41e5496f6e3d9b05e0e0eda0ba3416326f4bbb94bb2ec4c7b82222e8603a2edb2745302110e984a2c02de63249184ca496ce1f126b46738c03f83214b069e96baf09f9d546e9d322d3351d9f4a26d83b6863cb28aff76238d1bf0cf797d7c280aa1e7b96e0c2d6fd47d89c590befc108ea5056f22a82491572078b028061b28bd6c85f655cd4", "23", "28dfa9910394fef347d5fd104b8390bd20f2a4b7b71ecd82f07076d05d1a0b1937a5ddca5d976263dc111174301d176d93a298108874c2516016f319248c26524b670f8935a339c601fc190a5834f4b5d784fceaa374e991699a8ecfa5136c1db431e59457fbb11c68df867bcbebe140550f3dcb70616b7ea3ec4e2c85f7e08475282b791541248ab903c5814030d945eb642fb2ae6a000000000", .None}, + {.Shl, "cdffaed1c25fe8228dfaf4e115cd415e6c753926d84c386f93601217867dceb8d3935e4f0fbcd4fd343535b9e943f2d82d002cf33412252b892822115678e5cb9616f36c2dc58b1236c64b949d4468616f5611a5769d934314808a5a6084a7dc718f9493a6eaaba193e3a00cfd149594d77cd9bbd50b61264d403ba4ff6f7b33d27b5ba8750dae08c380d632989e20bd58441bdb6421", "21", "19bff5da384bfd0451bf5e9c22b9a82bcd8ea724db09870df26c0242f0cfb9d71a726bc9e1f79a9fa686a6b73d287e5b05a0059e668244a5712504422acf1cb972c2de6d85b8b16246d8c97293a88d0c2deac234aed3b2686290114b4c1094fb8e31f29274dd5574327c74019fa292b29aef9b377aa16c24c9a807749fedef667a4f6b750ea1b5c118701ac65313c417ab08837b6c84200000000", .None}, + {.Shl, "cc4b93e921e2916a4bef59d1309b9a593308d8c295300bdc88ad063921f154ce440b79ff5aab84d646d129dc462248157cec269a0b7d0ee07aa9543ecd40c486bfb0555dbd4881c33286d7737bad0f962374ed5524973220db554c07199b8b2dd8484ff30cf42ad490379e02f83d95302d6b0d256ffa7b868a5e4e1e78ecaec44633345adb433cc7bc0a1822bb8d6cbc5c70cd38dd7b", "11", "1989727d243c522d497deb3a2613734b26611b1852a6017b9115a0c7243e2a99c8816f3feb55709ac8da253b88c44902af9d84d3416fa1dc0f552a87d9a81890d7f60aabb7a910386650daee6f75a1f2c46e9daaa492e6441b6aa980e3337165bb0909fe619e855a9206f3c05f07b2a605ad61a4adff4f70d14bc9c3cf1d95d888c6668b5b686798f78143045771ad978b8e19a71baf60000", .None}, + {.Shl, "715e2c51fefb3cd988fd3da174490ad03a373af9dabec597ff3ee3a98a66616d51847e1cf53eaa986bbf658474f5c9804175f4f46bf5a30913399972efdbf72ce5a143b7f525d03d353cab8c48ddd1ef2c5d0a7b4ab66dff103466d7b69dff55a18a48185b3fb40563f4383d9050cb7f7eae3c7ea55005a375f0841d246f6b66a749c35fb65389eae8b020e01567ac3d5e7d58df0377", "39", "e2bc58a3fdf679b311fa7b42e89215a0746e75f3b57d8b2ffe7dc75314ccc2daa308fc39ea7d5530d77ecb08e9eb930082ebe9e8d7eb4612267332e5dfb7ee59cb42876fea4ba07a6a79571891bba3de58ba14f6956cdbfe2068cdaf6d3bfeab43149030b67f680ac7e8707b20a196fefd5c78fd4aa00b46ebe1083a48ded6cd4e9386bf6ca713d5d16041c02acf587abcfab1be06ee00000000000000", .None}, + {.Shl, "-eb60e17338f8843e30f1d4fac770946bc327f54404ff21c1d9138be01b2c05ebcae251cbe140da5028c4a09864bd9875fc241283a67e667ff2ea31f48d8242efcaf30866c49ad8b372bd585426878842b0bf204ae8e9311f8c6c908a4242a5521245f82b1fe5c8410b9d560e10c6845b5f2bea7f9fda3b2fe6295eda64f5d9db4214fb75c58db28e1526fd75c336c72f9fdfad3d9e55", "2", "-3ad8385cce3e210f8c3c753eb1dc251af0c9fd51013fc8707644e2f806cb017af2b89472f85036940a312826192f661d7f0904a0e99f999ffcba8c7d236090bbf2bcc219b126b62cdcaf561509a1e210ac2fc812ba3a4c47e31b24229090a95484917e0ac7f9721042e755838431a116d7cafa9fe7f68ecbf98a57b6993d7676d0853edd71636ca38549bf5d70cdb1cbe7f7eb4f67954", .None}, + {.Shl, "ddd71c59e7192f89affec6c09fad10577e12b7804af847405aeba3efd845395af6d06240c94bb970f456e2125ae52809c921c58ba67797c265babc7ee8e93089a810a74ed79807c739d094cfa51823a555e9dd68592f9e6061d53ba9615d40b0abedff9da3f4c5306fe1cb39819567d9e9209c2c134b0618b92aa6061095612dced44e7f055ff0b5e2c05aab261e42a7279ce6148b46", "40", "ddd71c59e7192f89affec6c09fad10577e12b7804af847405aeba3efd845395af6d06240c94bb970f456e2125ae52809c921c58ba67797c265babc7ee8e93089a810a74ed79807c739d094cfa51823a555e9dd68592f9e6061d53ba9615d40b0abedff9da3f4c5306fe1cb39819567d9e9209c2c134b0618b92aa6061095612dced44e7f055ff0b5e2c05aab261e42a7279ce6148b460000000000000000", .None}, + {.Shl, "20ce3278fa96a58420e27c69390d360d40288b7476c27311f1ff8982424099f4063c73ed0b07d05f52ca1f8131f40ad3506e3755a9ef15490415aa1be78e4ef4b3902098f6b7682a1115ffc9afe7ea5b0e93449911565bf97eea08c416c7c47bbc47671621e4df74394b46690979c06da777739d325219ae40fe2f9ae070c472754822379dc1d5cac234aeb6efc748200d4a024567a4", "53", "1067193c7d4b52c210713e349c869b06a01445ba3b613988f8ffc4c121204cfa031e39f68583e82fa9650fc098fa0569a8371baad4f78aa4820ad50df3c7277a59c8104c7b5bb415088affe4d7f3f52d8749a24c88ab2dfcbf7504620b63e23dde23b38b10f26fba1ca5a33484bce036d3bbb9ce99290cd7207f17cd703862393aa4111bcee0eae5611a575b77e3a41006a50122b3d2000000000000000000000", .None}, + {.Shl, "f44486c002d112c1fbc0008fd122263d7cbf641f0c0f2047fb69d2e796fb3ddf78425ee3561af2b88742c556463f565aa2ec44a4f1740c6ee841d0ba24d7a3d882e22c42db3e92cbdd8bd576b8d78460fce23ef86da397d60d7ff2a67cfc2048f26fee28f4b7594ca59deee0196e2673e9e498ec34a463d5cdd373fa91b98b3db902f59dec040a4bf253c778bed877441a48a20325e2", "1", "1e8890d8005a22583f780011fa2444c7af97ec83e181e408ff6d3a5cf2df67bbef084bdc6ac35e5710e858aac8c7eacb545d88949e2e818ddd083a17449af47b105c45885b67d2597bb17aaed71af08c1f9c47df0db472fac1affe54cf9f84091e4dfdc51e96eb2994b3bddc032dc4ce7d3c931d86948c7ab9ba6e7f52373167b7205eb3bd8081497e4a78ef17db0ee88349144064bc4", .None}, + {.Shl, "477dd246ac66bd3d9a127750764a8993883d2eedc036b9de2c659c5f58c4cf232e198ade26108910dd85dd28dc952a7c1cc8d8acd43aa8f8eeddd31624b9c01ff96fd0c8d8c92961ebdb9b3449df68a4e2a55689791f7acbf1b9a60523a2be46f9668a2fdf6078cfa91497c244b07b7cafdc2533ed79bda6fa78b3c8bfaca4e4bef1c627d2bd55ff6dc61fa3cf37d713ac4e026a906e", "64", "477dd246ac66bd3d9a127750764a8993883d2eedc036b9de2c659c5f58c4cf232e198ade26108910dd85dd28dc952a7c1cc8d8acd43aa8f8eeddd31624b9c01ff96fd0c8d8c92961ebdb9b3449df68a4e2a55689791f7acbf1b9a60523a2be46f9668a2fdf6078cfa91497c244b07b7cafdc2533ed79bda6fa78b3c8bfaca4e4bef1c627d2bd55ff6dc61fa3cf37d713ac4e026a906e0000000000000000000000000", .None}, + {.Shl, "97f74429b7bed13aca5e569da5ced94f27bf00ecc8c225ee69fa7f7f72504b9a227f914f467a439853bdcdcad73d57bd018deef6ada53915a0c5128df5639c4e1d26897bf3e30419210c93c99d649ea4595870b9234018ead0552ec4f129a6811db06b5df04298ccda7adf85310fa9f473917fe7d1ee74e2ab1637b85f33939783fc18ce6a3db87cddaf8149d727864a6d1c3d59aea", "14", "97f74429b7bed13aca5e569da5ced94f27bf00ecc8c225ee69fa7f7f72504b9a227f914f467a439853bdcdcad73d57bd018deef6ada53915a0c5128df5639c4e1d26897bf3e30419210c93c99d649ea4595870b9234018ead0552ec4f129a6811db06b5df04298ccda7adf85310fa9f473917fe7d1ee74e2ab1637b85f33939783fc18ce6a3db87cddaf8149d727864a6d1c3d59aea00000", .None}, + {.Shr_Signed, "-c5383bb26b02e40a4b64a9a55a5a6612729876436afca1e7b09f8a912ef209dc279dfa4a0f175dcab6a3a33e5ecfcc70d3361b99f8d2161424e07eebb5996b96af1c5dfc1d7db87fa3ba1cd26e098bc05d5a1a5fd1c6abeabdf6cca934926169709cf02d248fd2588543274bbcd360980e8b3aa78c29bb702b59cd1206369425fc11ef9c9e155033b7a7f1f4fe386f86561d334cb5ca", "36", "-314e0eec9ac0b90292d92a69569699849ca61d90dabf2879ec27e2a44bbc827709e77e9283c5d772ada8e8cf97b3f31c34cd86e67e34858509381fbaed665ae5abc7177f075f6e1fe8ee87349b8262f017568697f471aafaaf7db32a4d24985a5c273c0b4923f4962150c9d2ef34d82603a2cea9e30a6edc0ad67344818da5097f047be72785540cede9fc7d3f8e1bf", .None}, + {.Shr_Signed, "638c79b3ca747c025610274bb90278dfc5acec68e1944f9addb200ef1117e5493cf22a8aa8a39f3b8028d4ed696f185cc4344493d458b419bf7f718897bf6925c36df5bf5d5f4181be187e151ce1bbea58bb7d830ac787762e6bde31043b0d4ef81abef69d7f94948d23b0513d7ead07be90b1dc01e589fc77c9bb642a67990f1b727f4cf45877e11f30d3d4d1955ee102623a29d4dd", "6b", "c718f36794e8f804ac204e977204f1bf8b59d8d1c3289f35bb6401de222fca9279e4551551473e770051a9dad2de30b988688927a8b168337efee3112f7ed24b86dbeb7ebabe83037c30fc2a39c377d4b176fb06158f0eec5cd7bc6208761a9df0357ded3aff29291a4760a27afd5a0f7d2163b803cb13f8ef9376c854cf321e36e4fe99e8b0efc23", .None}, + {.Shr_Signed, "-5359c5316fc4fcb6886effb102d46b52cf7e1a0567d62bd0d1f0d006c258cb831b7551f62f6fe0d83986beebbd2f763379a732b5b58fbae9fc3658438925b769656f52a1037778d331ab20401e810ced4e89f203b9b05caf054e6cb5733c4c9e40e0fd359bebf5e1fad98ce5d4eb96d27abc0125653d6acd7761acb9be2fdc0f5fd6f6743084f97d626085a0b9c62e9bde649a5f5854", "20", "-5359c5316fc4fcb6886effb102d46b52cf7e1a0567d62bd0d1f0d006c258cb831b7551f62f6fe0d83986beebbd2f763379a732b5b58fbae9fc3658438925b769656f52a1037778d331ab20401e810ced4e89f203b9b05caf054e6cb5733c4c9e40e0fd359bebf5e1fad98ce5d4eb96d27abc0125653d6acd7761acb9be2fdc0f5fd6f6743084f97d626085a0b9c62e9bde65", .None}, + {.Shr_Signed, "-cef57e8b5a7b70088df176a1c2ed327142c19b66df270a96ebae7e1b3ad6778a05432fe8af8f2ddf46dba724848568e2fb3f04ab5bb1a1cc980227a6af6492b397af6531e6c7388bed25df578e503a0842767d97801186905fe441d5d6b719fa51950e955d073319bce8863b64f887595e9fe6093a53ad7578890e936a64ddc0cf465f8b1f58870d1a7c09b4380059507d4a711791ac", "4f", "-19deafd16b4f6e0111be2ed4385da64e2858336cdbe4e152dd75cfc3675acef140a865fd15f1e5bbe8db74e49090ad1c5f67e0956b763439930044f4d5ec925672f5eca63cd8e7117da4bbeaf1ca0741084ecfb2f00230d20bfc883abad6e33f4a32a1d2aba0e663379d10c76c9f10eb2bd3fcc1274a75aeaf1121d26d4c9bb819e8cbf163eb10e1a34f81369", .None}, + {.Shr_Signed, "-68f391abf261ebca8277feeb4b3c20b3c9d56028b7717642b35ff420c358da07f5b7e578c189797b658e44e55da668c7356d7ed6f4f70bdfe0c0f35b7ed2ab99833e0da8a61b42c1e1a9ee0cbd689aa3b0af5c26462dbb10b11721a175d77d3605cb5c0aa8c9647d3bc05359fed4a5791bf647cc53e1e065be9e9daff1b991a1d986da8a505d542ecdf5ac2cab58d99d49982c3b714d", "32", "-1a3ce46afc987af2a09dffbad2cf082cf275580a2ddc5d90acd7fd0830d63681fd6df95e30625e5ed963913957699a31cd5b5fb5bd3dc2f7f8303cd6dfb4aae660cf836a2986d0b0786a7b832f5a26a8ec2bd709918b6ec42c45c8685d75df4d8172d702aa32591f4ef014d67fb5295e46fd91f314f878196fa7a76bfc6e64687661b6a29417550bb37d6b0b2ad63668", .None}, + {.Shr_Signed, "-c1900b3ce119b6a3a19e9b440228b42e56d47838ce0c3630f4cfe123995fe69322b7abde4f7718b8d9c71ea7035d632a9389a4d538fc42aa9b8d0d353cff9a3d8bc6fcd76ba6d6538062aad7377b09fee6965cd0867357a1e4ae5b70250610a21acf426d8c4506ee7d842aa0a3825d08315ed87f4baad2c2e5fc2be0042918a5aae1f2d7a650d67603bbfd8dfbee16ab0ad0311034d5", "4b", "-183201679c2336d47433d36880451685cada8f0719c186c61e99fc24732bfcd26456f57bc9eee3171b38e3d4e06bac655271349aa71f88555371a1a6a79ff347b178df9aed74daca700c555ae6ef613fdcd2cb9a10ce6af43c95cb6e04a0c2144359e84db188a0ddcfb0855414704ba1062bdb0fe9755a585cbf857c00852314b55c3e5af4ca1acec0777fb1c0", .None}, + {.Shr_Signed, "-c7bb88869a05b0498d29fcdf65a920a44ede769a59124a6af9924eb4460523c4f58685cdd92ec343132e6441eaf8475b9aed98cf02675bba83fb62d4490b250be848f564df5d5851c5533bd1dc759a798911ca1c5730861c92299e72560c4be5004320b862db3591e647b225df45bc25a5b906ef7b10d8d14ed0837fffb159e0a15b824d2588aec4879b9601cecb1d654bdb078db017", "1c", "-c7bb88869a05b0498d29fcdf65a920a44ede769a59124a6af9924eb4460523c4f58685cdd92ec343132e6441eaf8475b9aed98cf02675bba83fb62d4490b250be848f564df5d5851c5533bd1dc759a798911ca1c5730861c92299e72560c4be5004320b862db3591e647b225df45bc25a5b906ef7b10d8d14ed0837fffb159e0a15b824d2588aec4879b9601cecb1d654bdb1", .None}, + {.Shr_Signed, "7d3ceebfd81b96a24bc95e03841c73aadece897800cbd9dc7aea1eb8c174cfa55b3d67416581e36a2a2f78dc10eff907bffd3e6db3b9e9bbdd64107f4641f6256f966a288c3dfdaa8866ee896fa412aa02688570f6a1603f82f13e0afb4e237d86ce3fb4842d5260adb699dce351376470b23b0348a2d110c137f033e02cc5cd86201fef362e3186d69035807a5ee342bc5e99c865c8", "39", "3e9e775fec0dcb5125e4af01c20e39d56f6744bc0065ecee3d750f5c60ba67d2ad9eb3a0b2c0f1b51517bc6e0877fc83dffe9f36d9dcf4ddeeb2083fa320fb12b7cb3514461efed544337744b7d20955013442b87b50b01fc1789f057da711bec3671fda4216a93056db4cee71a89bb238591d81a4516888609bf819f01662e6c3100ff79b1718c36b481ac03d2f71", .None}, + {.Shr_Signed, "-bd8323037c9dbc89753887b5083cdce660c18e96023ac3a6cfd82d2a8b948e474404c46adc1e77a95210a5aac03061669fadca9bad9da7bccd8b714f83e490cef7afbfe3b5a29cdcda680aadb2fcce36eab00e711925e5744f90b6bc55a893213128766390e250cd1bc991c7f4fc03f2465380519a2b6d6983cd99075de730c5f84ac8562ce697338cae3a3950efe33dab3119b61cd5", "e", "-2f60c8c0df276f225d4e21ed420f3739983063a5808eb0e9b3f60b4aa2e52391d101311ab7079dea5484296ab00c1859a7eb72a6eb6769ef3362dc53e0f92433bdebeff8ed68a737369a02ab6cbf338dbaac039c4649795d13e42daf156a24c84c4a1d98e438943346f26471fd3f00fc9194e014668adb5a60f36641d779cc317e12b2158b39a5cce32b8e8e543bf8cf6acc466d9", .None}, + {.Shr_Signed, "-7c134179ed6e1b175a544fc3659292815007328f874440b9f28130d963d68dc5a1f66fbc1c6eb9637460bd4b3ba214917ce02ef03801de1f59b98bef67c469e85bc09a433a05efe3ec1978ec37ced181e5f56fdfc821f3b3f696d4d68b155a9079fe08058e1e6ef0346f6b468a63e6ffd3e9189aee97ce5bf06d339832993cf248d4569029d8b5c24dc31fd3d534d563aa3cb7c0419", "36", "-1f04d05e7b5b86c5d69513f0d964a4a05401cca3e1d1102e7ca04c3658f5a371687d9bef071bae58dd182f52cee885245f380bbc0e007787d66e62fbd9f11a7a16f02690ce817bf8fb065e3b0df3b460797d5bf7f2087cecfda5b535a2c556a41e7f820163879bbc0d1bdad1a298f9bff4fa4626bba5f396fc1b4ce60ca64f3c923515a40a762d709370c7f4f54d36", .None}, + {.Shr_Signed, "19ce7a82806e920313bffa559f0e6995ed8ec03a7611f54883f3a4235a3af574048cb140ce00ed785330ba38e1d6fefc6d1dec598b6c5e3c4800ad4803e675c265bfd1e42906c0d6ef446695a035ca80ebc74d34796024f67c20a0489a1ffc5a4523a73e10b44cf6991a6539517d0a60ca088e5c8d47409d86958517f5befa9b8fc202e9b8ed049fcc789edbf5d48248317c2bd4cd0c", "30", "19ce7a82806e920313bffa559f0e6995ed8ec03a7611f54883f3a4235a3af574048cb140ce00ed785330ba38e1d6fefc6d1dec598b6c5e3c4800ad4803e675c265bfd1e42906c0d6ef446695a035ca80ebc74d34796024f67c20a0489a1ffc5a4523a73e10b44cf6991a6539517d0a60ca088e5c8d47409d86958517f5befa9b8fc202e9b8ed049fcc789edbf5d48248", .None}, + {.Shr_Signed, "-3a3b3747c20a42bac04733fdde8a2fbef6cb392901cf2650e949d35de64cc5a73f64901493087afd3631e2f18edbca9725d4ecea9bcebdfce890c1e7b27674244e9ab5f9bccd697b81e7a5714751ebb7e13a157851caac54f1f8786d8471f704b68d570e6347f7b99722cde34213faedc3f59640aa7f573cc9d02ba090820e7682e43d4240355e6ea0b1ecfa99948eabd31636da22d4", "57", "-74766e8f84148575808e67fbbd145f7ded967252039e4ca1d293a6bbcc998b4e7ec920292610f5fa6c63c5e31db7952e4ba9d9d5379d7bf9d12183cf64ece8489d356bf3799ad2f703cf4ae28ea3d76fc2742af0a39558a9e3f0f0db08e3ee096d1aae1cc68fef732e459bc68427f5db87eb2c8154feae7993a0574121041ced05c87a84806abcdd4163da", .None}, + {.Shr_Signed, "-96637deb9f2401ea9721a1af35b0b8d097dcce50de5fd381a239906a1c0773336dbce8b9a6b7e9aaef4836ee5821c9b1284a2377da72b6941be4fed006ede2c39ff246fd74d236cb6c6796d05e3c496c11250a600cd7a81d062f48f0c4c563ba196a9a0928defa9cfda52bcf1b393c2df863e7abcc61198aa9ed913bbb00efe550bd2fd398c92fbf08798d552b5a592bf044a7be5469", "31", "-4b31bef5cf9200f54b90d0d79ad85c684bee67286f2fe9c0d11cc8350e03b999b6de745cd35bf4d577a41b772c10e4d8942511bbed395b4a0df27f680376f161cff9237eba691b65b633cb682f1e24b608928530066bd40e8317a4786262b1dd0cb54d04946f7d4e7ed295e78d9c9e16fc31f3d5e6308cc554f6c89ddd8077f2a85e97e9cc6497df843cc6aa95ad2c96", .None}, + {.Shr_Signed, "-4f94703404330de09af71e87df774a125decc771707350b49322d0fd0546b15d4e6cd8a37ad9c98aa7d240264b2bbc2e12c9a4c568d182b12c7857092324ca7d6dda37053bcaedc0433aaa7517adbeb16c96f99db4ae14ef4eb0976d3125d303d4fca62b150e7933b2513a30101c0a83ee6cfa79944515bde707e796b2806bc1695af9d63934b153f15596cd35e41c895e261c461a1f", "4f", "-9f28e06808661bc135ee3d0fbeee9424bbd98ee2e0e6a1692645a1fa0a8d62ba9cd9b146f5b393154fa4804c9657785c2593498ad1a3056258f0ae12464994fadbb46e0a7795db80867554ea2f5b7d62d92df33b695c29de9d612eda624ba607a9f94c562a1cf26764a2746020381507dcd9f4f3288a2b7bce0fcf2d6500d782d2b5f3ac726962a7e2ab2d9b", .None}, + {.Shr_Signed, "8bcc89e231e2d00d5d88523904fd1c6349a7cc84e3285fb71095e6bb99a162eb998c336349e3bd5fbaa73e74ca1bf407fb856d70cc773e4e0eff5a1252698f82a70e8a755cdf469697ed2d064006fd57b1583f93f914914ad70ce2568d51f48c72d4e9c0dfdc05f0247e0ecb6fbbae55a5b21f406ab0868d66eb5195a8f5e9af095e9b2189b136c047e43b6e308b1da1223e18c73f52", "19", "45e644f118f16806aec4291c827e8e31a4d3e64271942fdb884af35dccd0b175ccc619b1a4f1deafdd539f3a650dfa03fdc2b6b8663b9f27077fad092934c7c15387453aae6fa34b4bf6968320037eabd8ac1fc9fc8a48a56b86712b46a8fa46396a74e06fee02f8123f0765b7ddd72ad2d90fa035584346b375a8cad47af4d784af4d90c4d89b6023f21db718458ed0911f0c", .None}, + {.Shr_Signed, "7ad5bad19778f02fa94c61d23c3bde577b11be4bd2f15d173b185ac4e9dfb2aed6d314b5b0766308e08a490c1c7d6ffc021d6fdd75b742d0229ec7c4e8a89d67a5c5056b8072059cfc937107d739e37b577cfc7c5c614d67a4025854bdc4b00cb37d5aa54ff622676222ba44715ab1d97942e4f8ffeaa2010ad224ae1a8a3b54125bca6f4eb918a174b3225bf0cb26bc955b378f3f1f", "26", "1eb56eb465de3c0bea5318748f0ef795dec46f92f4bc5745cec616b13a77ecabb5b4c52d6c1d98c238229243071f5bff00875bf75d6dd0b408a7b1f13a2a2759e971415ae01c81673f24dc41f5ce78ded5df3f1f17185359e90096152f712c032cdf56a953fd8899d888ae911c56ac765e50b93e3ffaa88042b4892b86a28ed50496f29bd3ae46285d2cc896fc32c9af255", .None}, + {.Shr_Signed, "-5c8511adcede1cf728cc1b52eef340414d7faa2f7ead4e8e20ec0c7370e064d9a77748b33f3b795d471dd0b7af6821488ce0ec960f2ce74401985237174c4caa5f44ab6624bf63bb1f54bae5d346f8aefedf6a77caf6be8cc6276cc1d9fb89d9075a364f9bc3e81c3229cf1742bc8fde1c44096ff69948870f3f1c29820ff42be430084ebf4d3b9df6f1c08e613f35a384dfc6261507", "31", "-2e4288d6e76f0e7b94660da97779a020a6bfd517bf56a74710760639b870326cd3bba4599f9dbcaea38ee85bd7b410a44670764b079673a200cc291b8ba626552fa255b3125fb1dd8faa5d72e9a37c577f6fb53be57b5f466313b660ecfdc4ec83ad1b27cde1f40e1914e78ba15e47ef0e2204b7fb4ca443879f8e14c107fa15f21804275fa69dcefb78e047309f9ad2", .None}, + {.Shr_Signed, "-62f0389b63d1849cb456a37147df81d95e9e5ba9bb654f1ef5d68ec67c98ebd18ee25c25948d8c843dcce1b38ca8458bce004772524e92dfb0458a02af08bdaefa258b4526ed60a4adf7569a82f6ed8b191ec47fddaa656056fc2f8876cce0fa39ea64260445c6c051ec12da4faa1d4e65dc354a78353ed178bd6e394a62944e751923d35892687c9713a30f7d74e7a5e76359674dc6", "3b", "-c5e07136c7a3093968ad46e28fbf03b2bd3cb75376ca9e3debad1d8cf931d7a31dc4b84b291b19087b99c36719508b179c008ee4a49d25bf608b14055e117b5df44b168a4ddac1495beead3505eddb16323d88ffbb54cac0adf85f10ed99c1f473d4c84c088b8d80a3d825b49f543a9ccbb86a94f06a7da2f17adc7294c5289cea3247a6b124d0f92e27461efae9d", .None}, + {.Shr_Signed, "5d9d22d2c41295ec9adce6f9ca70692d1551b007e654a411e6c79de005c960ae286011eb12c2e05c622a22665fadb77ad9b99620b1562056762cdad5db8ceca016a585f94c206a3c5c5d814ee08d53b7f3f0c08039f080eaededb77554fe727f510ec3db560da233b1b372ea0503a4ee0011add31f3955e31091c93fe53484f5b71e164c6b5687a2e2d8c58e5aee3752da6c6dcb198e", "3e", "176748b4b104a57b26b739be729c1a4b45546c01f995290479b1e7780172582b8a18047ac4b0b817188a889997eb6ddeb66e65882c5588159d8b36b576e33b2805a9617e53081a8f17176053b82354edfcfc30200e7c203abb7b6ddd553f9c9fd443b0f6d583688cec6cdcba8140e93b80046b74c7ce5578c424724ff94d213d6dc785931ad5a1e8b8b6316396bb8", .None}, + {.Shr_Signed, "-b01d67fdb2ab2f682f2e419a1e5ad344cc3c33c4ac66aa71548518fb8e5796e8b2f01e4ea20fa05e17c2f610b94cff5492c0bebd6b7d7e400fb193b5396e5bb6338b8ca9080b0900b6da7e54bb0ba70fece5db5d04f87a2a7345c5103b2528363c562a22ce26e5449b1b08cc6ae2d8c9d08131b554a193f01d5b8ed1ec330fb6cb72a6c30c9d63b1b017c582a9ae356b629b28f17afb", "4b", "-1603acffb65565ed05e5c83343cb5a6899878678958cd54e2a90a31f71caf2dd165e03c9d441f40bc2f85ec217299fea925817d7ad6fafc801f63276a72dcb76c67171952101612016db4fca976174e1fd9cbb6ba09f0f454e68b8a20764a506c78ac54459c4dca8936361198d5c5b193a102636aa94327e03ab71da3d8661f6d96e54d86193ac763602f8b056", .None}, + {.Shr_Signed, "2c3f06d5b9e657484b6dd315ebe47f7c3fe730dbfd78eb7b463a4f479a751323ed09cc70ca54822cdb10f89f245bec3ca99a1450931ffcac288193d2d975e1f77a5f900e34dd63b562505367739aebb1aef072a9fbd09b4284188a5f5763a8837418c19e0416302adde8df7db9c5730dbfa26488cafb2ac68e4b2c7b9628d0c378310d73cf3df752080d25e20405d72ccd65f4622793", "75", "161f836adcf32ba425b6e98af5f23fbe1ff3986dfebc75bda31d27a3cd3a8991f684e638652a41166d887c4f922df61e54cd0a28498ffe561440c9e96cbaf0fbbd2fc8071a6eb1dab12829b3b9cd75d8d7783954fde84da1420c452fabb1d441ba0c60cf020b18156ef46fbedce2b986dfd13244657d95634725963dcb146861bc1886b9e79efba", .None}, + {.Shr_Signed, "cb866c01ee20c84159107fa0fef87339bdfe1828b2f3f877a6b857fd03425bffba4e0431eda9d75504b32d1ebf9ca33c6b2f83b580a3dfd9f063caa513a09016d8ecef029dea318e5d7e79588600d76164b03afcebc72653646451fbf6fe5971142f10f18f5e103b02adbd1eb4b258f8ccb8d9eb0110819fa09d3eecc64f1c964e565ceb63e60beaa5d64c5dd7f1b2c1ab6a4bb1f94e", "25", "65c33600f7106420ac883fd07f7c399cdeff0c145979fc3bd35c2bfe81a12dffdd270218f6d4ebaa8259968f5fce519e3597c1dac051efecf831e55289d0480b6c7677814ef518c72ebf3cac43006bb0b2581d7e75e39329b23228fdfb7f2cb88a178878c7af081d8156de8f5a592c7c665c6cf5808840cfd04e9f7663278e4b272b2e75b1f305f552eb262eebf8d960d5b", .None}, + {.Shr_Signed, "-a62ee8776aa9f9a0b0ec6263c10670e45d23a6c92cfcd7bd8b149ed7952ba5598fb93c55387d6e85e62b7b61cdd0decaf95263a5e38db098090d5367d764896ee8b2eefb5d00ed1330619b47078b1cfb0aa829ceb9d6c3916d76dcf601c3a358a55a8a51fee1aa551412c6fc639af1dd323031ab433297206d04c2df9758e84983a9c9cd7e350c172a52340b92af687c371aa64a132f", "1f", "-14c5dd0eed553f34161d8c4c7820ce1c8ba474d9259f9af7b16293daf2a574ab31f7278aa70fadd0bcc56f6c39ba1bd95f2a4c74bc71b6130121aa6cfaec912ddd165ddf6ba01da2660c3368e0f1639f61550539d73ad8722daedb9ec038746b14ab514a3fdc354aa28258df8c735e3ba6460635686652e40da0985bf2eb1d0930753939afc6a182e54a46817255ed0f86e36", .None}, + {.Shr_Signed, "fd55e543fd72a755a7da4371ebf549865757557ae33d95167217912191f440c2a70e9fa749998e064e05d62d3ce423e161ec2a342c29da0be8d21d2cde6474a123dd8ad4a75fc3ebc761d4db8008cdf1cf4d6dde8965da1b00fddbafe3a351f6b10ce06aafd387d6d885570b71cbf8432fbac1160ca33f77d5856340c5ea8b70cc2b346361a8d07fad6177426234acb1a30850682d62", "78", "fd55e543fd72a755a7da4371ebf549865757557ae33d95167217912191f440c2a70e9fa749998e064e05d62d3ce423e161ec2a342c29da0be8d21d2cde6474a123dd8ad4a75fc3ebc761d4db8008cdf1cf4d6dde8965da1b00fddbafe3a351f6b10ce06aafd387d6d885570b71cbf8432fbac1160ca33f77d5856340c5ea8b70cc2b346361a8d0", .None}, + {.Shr_Signed, "-63453f828625a6f2c469be45552c6b0eda276f830ce1c6065d314b37f511427eed3f00cd99cb440e3758d07b63ffe061144116fe5db5a9bd71ac268b4f2872a28a8b5d341cf92783f9f733f64ec35c3a464e61cdf2884bda1f1b6432123aac122fbe8722656a0c0ad9e3ef893c87ff08f979127fb3a370e3449821eb0188e6eacab7c3dd69800d2d01884e10808c11784f03c5b5292b", "61", "-31a29fc14312d3796234df22aa9635876d13b7c18670e3032e98a59bfa88a13f769f8066cce5a2071bac683db1fff0308a208b7f2edad4deb8d61345a79439514545ae9a0e7c93c1fcfb99fb2761ae1d232730e6f94425ed0f8db219091d560917df439132b506056cf1f7c49e43ff847cbc893fd9d1b871a24c10f580c47375655be1eeb4c0069680c5", .None}, + {.Shr_Signed, "a334bec75f8a0beb237edd6bb24a8996865df27c96dce83394ecc5413b41b1287ef51cb018b879bc217bf823966efa0347f7e53adc9c571c121132e43e350faf54fdd2eccfb539f8683401af75e1f55eccb3797e603617c24a2b0f420f5ee98e43c4873c59cb2f74504ca1307bfcac61ae17d9360d91744f56a8561b378f94ffdcaeb92c8ac3eac7422cef4d65c43da028358f6ce9dd", "51", "519a5f63afc505f591bf6eb5d92544cb432ef93e4b6e7419ca7662a09da0d8943f7a8e580c5c3cde10bdfc11cb377d01a3fbf29d6e4e2b8e090899721f1a87d7aa7ee97667da9cfc341a00d7baf0faaf6659bcbf301b0be1251587a107af74c721e2439e2ce597ba282650983dfe5630d70bec9b06c8ba27ab542b0d9bc7ca7fee575c964561f563a11677a6", .None}, + {.Shr_Signed, "-2d5b0340393ba105e0c7e0d35934b389829fccdae739b710113782e2fc2c937924267ff77c995a65d3b1e9bcb7327295039788a40283d8254abf80b74708152fe7016d0db7550cf0bdee0e2138daa87db7004a4728d02f75ce279c833b5405e65ab3b7b3540865fda9335d3d5dddb7ac7c16395a71a70e1dfaee5d95314a46643c43b300e009a9ee00dc4055ccdfc4482fead2f0f8bb", "47", "-5ab606807277420bc18fc1a6b2696713053f99b5ce736e20226f05c5f85926f2484cffeef932b4cba763d3796e64e52a072f11480507b04a957f016e8e102a5fce02da1b6eaa19e17bdc1c4271b550fb6e00948e51a05eeb9c4f390676a80bccb5676f66a810cbfb5266ba7abbbb6f58f82c72b4e34e1c3bf5dcbb2a62948cc878876601c01353dc01b880ab9a", .None}, + {.Shr_Signed, "2088c23943c09c589018e6653d07a35da498c9ed6a3b113eabf2bcd43b4d5b498287cf622c74be7d2ff2f5d0143d641a5cda833ef87d3d4e6f2c887453606de890e6ec71172bd4d4a762a1acdcb8e4d6dd1331e63e89cbc56faac608a94242e73fb784dca1acdd36db0010f9e91670aa07059cb410cb8649c6558be48cec97e5a24c4031aba1c3bcab91bdf1df62153ae4167667714f", "2", "822308e50f02716240639994f41e8d76926327b5a8ec44faafcaf350ed356d260a1f3d88b1d2f9f4bfcbd74050f59069736a0cfbe1f4f539bcb221d14d81b7a2439bb1c45caf53529d8a86b372e3935b744cc798fa272f15beab1822a5090b9cfede137286b374db6c0043e7a459c2a81c1672d0432e192719562f9233b25f96893100c6ae870ef2ae46f7c77d8854eb9059d99dc53", .None}, + {.Shr_Signed, "-2f9653e6c8be5161f27bd22c04497aee37590938467bf7834a5d76d8abde6a141c2debd487dfb3b49331ef28586dd326cae4e40ee56ff59d114c53075fae826b14362c022092758b65b464b34ea68615a0a4a382a729980d936d31939c61a1170d3bcf121b1c44533288de5637d48714c1dd3ae896ae73106a2b396fecf5363ee148743ef5fde07b7dc5f748031e30d90ca8a83619be", "17", "-5f2ca7cd917ca2c3e4f7a4580892f5dc6eb212708cf7ef0694baedb157bcd428385bd7a90fbf67692663de50b0dba64d95c9c81dcadfeb3a2298a60ebf5d04d6286c58044124eb16cb68c9669d4d0c2b414947054e53301b26da632738c3422e1a779e24363888a66511bcac6fa90e2983ba75d12d5ce620d45672dfd9ea6c7dc290e87debfbc0f6fb8bee90063c61b2195151", .None}, + {.Shr_Signed, "-a6e83b32fea731c469a40b55ff83a9682973a009970b17e2fe54a0d577f77bae64cef35fa3969a8c51c87599b4d275fa34a7bb5baffa9fe67268cf2a8ece42cf2013c2358f475b8f2e6c7888613447e81c5bc3f983dcb1496b6583d19baf28c4a3e448f54806e19e30680f9fbe67b3cadf61de80dbd1977e90f018b445d5e53b4ffcdce8e33345758028493ac78e2fdb43b8ffe312c1", "4a", "-29ba0eccbfa9cc711a6902d57fe0ea5a0a5ce80265c2c5f8bf9528355dfddeeb9933bcd7e8e5a6a314721d666d349d7e8d29eed6ebfea7f99c9a33caa3b390b3c804f08d63d1d6e3cb9b1e22184d11fa0716f0fe60f72c525ad960f466ebca3128f9123d5201b8678c1a03e7ef99ecf2b7d877a036f465dfa43c062d1175794ed3ff373a38ccd15d600a124eb2", .None}, + {.Shr_Signed, "7427f5738719c6e82247536f90ded922c9fefebbef91c243e7da4d99f6b5d86c29529b92228d31aca5141db402e07bdb6fe9c3cb00e3e2543819c90b81cc770adc840ff0a13d0ee178ea524f17cc5f10467036746eade17b661e7a3ee56faa8e09b7fcd14807a6b80db76ac461a0587ee00bf9245af9bbc60e60879579c3606cf0a782d2080e76cf1743582963ef886aa252aa6f12b", "5c", "7427f5738719c6e82247536f90ded922c9fefebbef91c243e7da4d99f6b5d86c29529b92228d31aca5141db402e07bdb6fe9c3cb00e3e2543819c90b81cc770adc840ff0a13d0ee178ea524f17cc5f10467036746eade17b661e7a3ee56faa8e09b7fcd14807a6b80db76ac461a0587ee00bf9245af9bbc60e60879579c3606cf0a782d2080e76cf1743", .None}, + {.Shr_Signed, "fdc4e04d0632cb2e13ef103ed40988a0d9f8fb3ffed0a0f39b132dec9df17c8dbdd7f4e0e351dd85814a5fde3d6224f0165a9e6465ad13b7e0c0fc891bf920aa379837341c776866b2050edc2112c0696024868dc1d716b5605ba8d756fed956365c8b9271a483ca2070776b0f84eeef07c25107be9d5ce62ca09fc790c0c60b050dd50a9e6dee57afb6d9ef93a4ddcad75a2b26850e", "f", "1fb89c09a0c65965c27de207da8131141b3f1f67ffda141e736265bd93be2f91b7bafe9c1c6a3bb0b0294bfbc7ac449e02cb53cc8cb5a276fc181f91237f241546f306e6838eed0cd640a1db8422580d2c0490d1b83ae2d6ac0b751aeadfdb2ac6cb91724e349079440e0eed61f09ddde0f84a20f7d3ab9cc59413f8f21818c160a1baa153cdbdcaf5f6db3df2749bb95aeb4564d", .None}, + {.Shr_Signed, "-47000be6427a77ed931e6e319bcdd4702649e6bbbcb2dcc5c37eb5d6230c964adb7bf9c6669025affdc23bd039f902716572b1751700388e485322193862b166b09dad39b8d66b87a9e8dc6b496eb467c4cc5116ba0e054b6b5320c650fb4cb45a6b47706af6fb4de44e19b56080ea0d140a35d0f8ffd9fba0be19d195c3b37b78ff0a9c3976895ac9db6f734450f37173fc0f8c94aa", "49", "-238005f3213d3bf6c98f3718cde6ea381324f35dde596e62e1bf5aeb11864b256dbdfce3334812d7fee11de81cfc8138b2b958ba8b801c472429910c9c3158b3584ed69cdc6b35c3d4f46e35a4b75a33e266288b5d0702a5b5a99063287da65a2d35a3b8357b7da6f2270cdab04075068a051ae87c7fecfdd05f0ce8cae1d9bdbc7f854e1cbb44ad64edb7b9a3", .None}, + {.Shr_Signed, "d49ef912921047259d9289d1e7af1e5e51b598f63e9c37cba81db146a3e743fadf0c5526ab45ed8681db6b4248423eca6020146c9ed3a7790a2caee5c1c838ddf606c05e30f5d3e1688773c6f6997bddc4b06bfb3dbfe5fe162870e3426e2794f6d8d0ba6677d991dbf5bd563d310d5a7ba1b69fec27136a7f278cc86bea257e9754f31b89bf69171ee77043964dff3883612f29ddf7", "d", "6a4f7c8949082392cec944e8f3d78f2f28dacc7b1f4e1be5d40ed8a351f3a1fd6f862a9355a2f6c340edb5a124211f6530100a364f69d3bc85165772e0e41c6efb03602f187ae9f0b443b9e37b4cbdeee25835fd9edff2ff0b143871a13713ca7b6c685d333becc8edfadeab1e9886ad3dd0db4ff61389b53f93c66435f512bf4baa798dc4dfb48b8f73b821cb26ff9c41b09794e", .None}, + {.Shr_Signed, "-d25c7de25257ca0129aeb68af356aa2dd9af1bc6a9574be7ee3a372d4865848ab696f7d80537820c10120ec0d9a55a59f056503f62b63c6676d3ce91c8cef6efc546561e8f64aba16df6be710077e5313746ef103f3dcf1229d4fc0e38caea0bba0c5d13980341bb1b41c2a85d9dd5e34003513613678b1c1f50211d67d9fa7000011df48e20ca0299e4dc2e3a53466e340b5d2dadc6", "27", "-1a4b8fbc4a4af9402535d6d15e6ad545bb35e378d52ae97cfdc746e5a90cb09156d2defb00a6f041820241d81b34ab4b3e0aca07ec56c78cceda79d23919deddf8a8cac3d1ec95742dbed7ce200efca626e8dde207e7b9e2453a9f81c7195d4177418ba273006837636838550bb3babc68006a26c26cf16383ea0423acfb3f4e000023be91c41940533c9b85c74a68cdc69", .None}, + {.Shr_Signed, "f802728293ff04cbad9c134d89cd57854b9c963286228c08e534379b9b72c0d720e087a82dd2b92baa235be464666b7ede30b94089d97c410c715eafc2c942612b296ef42546ad68437cba853f257825ebdb84c385036585c2a17c664d89116e7008ba5b65615e0bc3117cab78c0b6d936bef8c3a64d387156ac00bc5902da969740f2e0632fb45a2110dd7c78694a801edcaae98645", "46", "3e009ca0a4ffc132eb6704d3627355e152e7258ca188a302394d0de6e6dcb035c83821ea0b74ae4aea88d6f919199adfb78c2e5022765f10431c57abf0b250984aca5bbd0951ab5a10df2ea14fc95e097af6e130e140d96170a85f199362445b9c022e96d9585782f0c45f2ade302db64dafbe30e9934e1c55ab002f1640b6a5a5d03cb818cbed168844375f1e1", .None}, + {.Shr_Signed, "-d6ffd41e83df1f92e4965ea569fa48902363f32190367f0475324e8e49eb309a5ac18b67bad583b39af8acba727657cb7efcfe64fe54d3f1a79b475a9e75a63ca67cb0cb00e2855deeae6b3ff746ebdf88e290935a1561f96b685b5b97e47cfd35570644d79b20e409f47797a2da92ae3d3500d1db472d22e078670e45b02457220e0ceae18b1aea9f37fe24a78c00d83bada8498a1", "30", "-d6ffd41e83df1f92e4965ea569fa48902363f32190367f0475324e8e49eb309a5ac18b67bad583b39af8acba727657cb7efcfe64fe54d3f1a79b475a9e75a63ca67cb0cb00e2855deeae6b3ff746ebdf88e290935a1561f96b685b5b97e47cfd35570644d79b20e409f47797a2da92ae3d3500d1db472d22e078670e45b02457220e0ceae18b1aea9f37fe24a78c00e", .None}, + {.Shr_Signed, "-98269f8a6baf693cf1b0ec28c95d05d2957cef91a70b478bb2a4eadf4bf2f15629665655dbdf60633a26703efb7c037d71a389c5480d7609af05b92b29eb5a1ec373ff35b5a98299fc4fb4115477d64c2426268146cba0ff36a6365f43f8bdb6ef5e487d850b96005c2a0f2ce470c918bc86058b742ebd7934383936bcf0a9c6d1b262885ebe09a11050edc5592a1b6fec8372f5d9ca", "e", "-2609a7e29aebda4f3c6c3b0a32574174a55f3be469c2d1e2eca93ab7d2fcbc558a59959576f7d818ce899c0fbedf00df5c68e27152035d826bc16e4aca7ad687b0dcffcd6d6a60a67f13ed04551df593090989a051b2e83fcda98d97d0fe2f6dbbd7921f6142e580170a83cb391c32462f218162dd0baf5e4d0e0e4daf3c2a71b46c98a217af826844143b71564a86dbfb20dcbd8", .None}, + {.Shr_Signed, "-370234a9f402c347f5cd59996865e829793ede57e579c758da7aa8bf339e3a4f0f2d764a6198c87101f1b13a91012e38da8728d8e2d6d2d2710d2b267a40aac03d7afdb3e58857209799a5338b94638828eb14630e758008e0358b9f8b8067a6d861f7cab5b24ac46f34682e84782c126efa666e8f45dcadddc4e6f5d2b984975d6b0f7af1d3f6a7bb111b2fbc2c8bfd20633c9375cd", "51", "-1b811a54fa0161a3fae6acccb432f414bc9f6f2bf2bce3ac6d3d545f99cf1d278796bb2530cc643880f8d89d4880971c6d43946c716b6969388695933d2055601ebd7ed9f2c42b904bccd299c5ca31c414758a31873ac004701ac5cfc5c033d36c30fbe55ad92562379a3417423c1609377d333747a2ee56eee2737ae95cc24baeb587bd78e9fb53dd888d98", .None}, + {.Shr_Signed, "70ab9fc6aeff2c1b1db785e21671b7139c4640ee852f6146b19877b2e0d2ee4a039257cdd239367eca305ee6e0513fb455533b0c46431e640a8ae668523ec657c4d59da206fb8f385d08624c9f20574bc1006745ba66444175b00e5390ea73c76254b258979315f542842162152d49df453b8cbc3f5c4c644f0caea9806a15b55269e29cd03586f7d9cc1c19a7867acc6e10b3ba9d05", "6a", "1c2ae7f1abbfcb06c76de178859c6dc4e711903ba14bd851ac661decb834bb9280e495f3748e4d9fb28c17b9b8144fed1554cec31190c79902a2b99a148fb195f135676881bee3ce1742189327c815d2f04019d16e9991105d6c0394e43a9cf1d8952c9625e4c57d50a10858854b5277d14ee32f0fd7131913c32baa601a856d549a78a7340d61bdf6", .None}, + {.Shr_Signed, "-c25600e5eb63ab6afeccac02cb20b6ae88d16f82c6f79f097d0e62a11398a8008496fc06ab996a1e31d63f26ddde2801c0e4c6dfcad97be1f5ba372c94c8e0ad8e03a78b3092ca03951947dc1e5cf688494990a3333fccf2670be1b79c47cee812ee9819c304f1f8c99c397edb95e26b7b6df277ac9f846f97af3dc77bdbdfc11821be522b288b27ca1869a943b6a3887a0a75d58cbd", "1a", "-309580397ad8eadabfb32b00b2c82daba2345be0b1bde7c25f4398a844e62a002125bf01aae65a878c758fc9b7778a00703931b7f2b65ef87d6e8dcb2532382b6380e9e2cc24b280e54651f707973da212526428cccff33c99c2f86de711f3ba04bba60670c13c7e32670e5fb6e5789adedb7c9deb27e11be5ebcf71def6f7f046086f948aca22c9f2861a6a50eda8e21e829e", .None}, + {.Shr_Signed, "b745da7093dd87920c2517b7fcf5e9fb42de8af692852b20541b162fb58c1a51a95f5ec2a28925bf1cdd1fbe1d522e95cc7e5bc67ffa7dbdf60125e784f539437454b4b6408e0444601eeaf7abca141dbef2010394b4a3118269cfd35225462fa241a177d6d93dfaed5354e071a583f7482484acc16d4b1b9e2144410da70bb82e178ecc5048cbfa8ae0428db875af3cbe6a62de8b4f", "2c", "b745da7093dd87920c2517b7fcf5e9fb42de8af692852b20541b162fb58c1a51a95f5ec2a28925bf1cdd1fbe1d522e95cc7e5bc67ffa7dbdf60125e784f539437454b4b6408e0444601eeaf7abca141dbef2010394b4a3118269cfd35225462fa241a177d6d93dfaed5354e071a583f7482484acc16d4b1b9e2144410da70bb82e178ecc5048cbfa8ae0428db875af3cb", .None}, + {.Shr_Signed, "a42697fab1765ddbdc88193df2cc125fd5a55c9c76b703b005096992b34f01d74d1bd1f34c4f2ea45871b2a0441f0bbedcca3f8c2579b2ef3ebe55bb5c0998e4e7fce2933ff397dcb352329405f04165ff3f6c6a8dcda1156619424ab743d267f496c2d24d37580fd3b1a1e9e5c5526a12c0ceee4aca3a14a7f3fa42336f7eb7b790c62cf089be1e165f8657192ac95e67a9ee9fafae", "21", "52134bfd58bb2eedee440c9ef966092fead2ae4e3b5b81d80284b4c959a780eba68de8f9a62797522c38d950220f85df6e651fc612bcd9779f5f2addae04cc7273fe71499ff9cbee59a9194a02f820b2ff9fb63546e6d08ab30ca1255ba1e933fa4b6169269bac07e9d8d0f4f2e2a9350960677725651d0a53f9fd2119b7bf5bdbc863167844df0f0b2fc32b8c9564af33d4", .None}, + {.Shr_Signed, "-6c01e505d2a169992ad36f4a411a9b4d6d2482b7286a25881ead211de9b4af7590a5233109ec054c9a3b9fd102949b21002139152530b0c413c732fda05943f66f9774eb8fe00ef09e4a599e4a5a042c2827aea01f17a5e822fd7cc9a99fa4bd96471d870689840da4f3a48c585ee3846b28533312738f760f8ce689678b5f04302480ad816495adb61a9e8cf8d11063638a16f3988a", "2b", "-d803ca0ba542d33255a6de948235369ada49056e50d44b103d5a423bd3695eeb214a466213d80a9934773fa2052936420042722a4a616188278e65fb40b287ecdf2ee9d71fc01de13c94b33c94b40858504f5d403e2f4bd045faf993533f497b2c8e3b0e0d13081b49e74918b0bdc708d650a66624e71eec1f19cd12cf16be086049015b02c92b5b6c353d19f1a220c6d", .None}, + {.Shr_Signed, "-bcfa3da7c3cdf446831afce4c2ffbb08f49e5f811cb297a035663fb2e3a4a1bb2dcce821ec46c63e3d188bd7ea0536b5418bd17b0281fcbaaadc85aaccc24a02a5db0938bd9ecf6d5bed5fa5f99e68966a0c070e296bc31fddba721ea8f53a3ad412979ae1d607632f5cc795cd929a84ffa5326f837171a893454da03c1161871a680d9081e1f65c9b3ef07791cb13d78c3a68007040", "12", "-2f3e8f69f0f37d11a0c6bf3930bfeec23d2797e0472ca5e80d598fecb8e9286ecb733a087b11b18f8f4622f5fa814dad5062f45ec0a07f2eaab7216ab3309280a976c24e2f67b3db56fb57e97e679a259a8301c38a5af0c7f76e9c87aa3d4e8eb504a5e6b87581d8cbd731e57364a6a13fe94c9be0dc5c6a24d153680f045861c69a036420787d9726cfbc1de472c4f5e30e9a01", .None}, + {.Shr_Signed, "-c669f94775512fd8180bb149cd4f6da11326178d2f90d2f68c9639884cff03f7bb9941406c6b1449b2323384de26c4d38882a8647750582f31a0f0d0dde91ce3e130d30a86c6db6426adcae339fba58ea4f2aa2fab8efcd95db1f45a9635d5a6f67977e25e52efdfe7d75c9a69a40b807457f0cae3341583e67b27e081ca20e919fa24e9512ef07aca2bad0f5c94017467b9251d60ec", "32", "-319a7e51dd544bf60602ec527353db6844c985e34be434bda3258e62133fc0fdeee650501b1ac5126c8c8ce13789b134e220aa191dd4160bcc683c34377a4738f84c34c2a1b1b6d909ab72b8ce7ee963a93caa8beae3bf36576c7d16a58d7569bd9e5df89794bbf7f9f5d7269a6902e01d15fc32b8cd0560f99ec9f82072883a467e893a544bbc1eb28aeb43d725005e", .None}, + {.Shr_Signed, "-68aaae78b53a04028542729d39a0b124493571801a4a5507c6a6cd30972b74cd1281cc218d798e44f75df1cba128264ddd4fe8fbc6d9f0db480c4816817e3b158260b8119a1e2f428cc4aeabbba14f0963018c4cd81e347a9631cbe02383ff27d70c20a001465d8ea2f01502151d547d95239b0644749ed90b9f1ceba4d9a9aa381edc38d60f634032776e5f847cc046349abacee761", "54", "-68aaae78b53a04028542729d39a0b124493571801a4a5507c6a6cd30972b74cd1281cc218d798e44f75df1cba128264ddd4fe8fbc6d9f0db480c4816817e3b158260b8119a1e2f428cc4aeabbba14f0963018c4cd81e347a9631cbe02383ff27d70c20a001465d8ea2f01502151d547d95239b0644749ed90b9f1ceba4d9a9aa381edc38d60f634032776e6", .None}, + {.Shr_Signed, "cda7b1b8ca7ecc467c619f9804c8c9505fc40d6c17c5730990a140c532ce2d9063bb26aa0af94414ed2009f61ec53471c09cfc793f597ab4fad8ce0b20248616422f32bdbbfee32ab45e23b9f9fc3e37dc4b35f488116178f1f7b17b371cfd526391d3547b572a649ce762efef3f6720e85fd7cc7de81fd4c76a0aa00e79f751cabbcc5a815dc4fe57fcd3bf4bb6d9fb365574ea0a3c", "46", "3369ec6e329fb3119f1867e60132325417f1035b05f15cc2642850314cb38b6418eec9aa82be51053b48027d87b14d1c70273f1e4fd65ead3eb63382c8092185908bccaf6effb8caad1788ee7e7f0f8df712cd7d2204585e3c7dec5ecdc73f5498e474d51ed5ca992739d8bbfbcfd9c83a17f5f31f7a07f531da82a8039e7dd472aef316a057713f95ff34efd2e", .None}, + {.Shr_Signed, "-f3531a876fd149b135a86ef900eb4866b3da4415b5578217f0fa8a8839c158f64909e0b95e4834ff15df9a4727abadde3b412f7e811e30ce925b17f0dee45c7457cf88de54d3434828c53383e7519556b2391f77b78de6aaf3e68dc9a82a6fafcfede454f1e1f5ba598fb505b95307809a82a272fcff13c23d3ef01d86f362e3d62237414954a93feebd56f0e44c8d219954d2c2cdf1", "74", "-f3531a876fd149b135a86ef900eb4866b3da4415b5578217f0fa8a8839c158f64909e0b95e4834ff15df9a4727abadde3b412f7e811e30ce925b17f0dee45c7457cf88de54d3434828c53383e7519556b2391f77b78de6aaf3e68dc9a82a6fafcfede454f1e1f5ba598fb505b95307809a82a272fcff13c23d3ef01d86f362e3d62237414954a94", .None}, + {.Shr_Signed, "414e2dc0c51bf1d74ad1e9f649f6719e7eb93d081d1ed2aeef2d53106e356b2584a03f754bdb279a6ed7e329892416d6e23c5ef89f2959d1a5bec92c32258abe0635ffd54c5409809ed365092bd68a0ef3df47afe1d6be9a1eb60d4ed2fa68a734dce400aaa8f11e1c5bd1fdc7c1f20fe6467551abe2584672d9c2b4963c5b99dc4517823ea30824b1af390fc8982f4b657bf8663610", "5b", "829c5b818a37e3ae95a3d3ec93ece33cfd727a103a3da55dde5aa620dc6ad64b09407eea97b64f34ddafc65312482dadc478bdf13e52b3a34b7d9258644b157c0c6bffaa98a813013da6ca1257ad141de7be8f5fc3ad7d343d6c1a9da5f4d14e69b9c8015551e23c38b7a3fb8f83e41fcc8ceaa357c4b08ce5b385692c78b733b88a2f047d461049635e7", .None}, + {.Shr_Signed, "e7f6d562fb5813cc4565bae2ed6bcec2e4decd3b4405e455d8661fe87fefda02986306b96fccafbc5d79b11be57d0a72db4bea90d9672dcdfb744b8cc8f1484bb182901fb2cf3821baceec08da9da877645b0de15485c23bd3101fea9691cee455e1bdfba7f384a8723e4896763677931e6b47fd7a9dcb636e7eae6af6d77a542b70c6f4b12f98c8263a71681e566e4fde13d27f8a04", "76", "39fdb558bed604f311596eb8bb5af3b0b937b34ed1017915761987fa1ffbf680a618c1ae5bf32bef175e6c46f95f429cb6d2faa43659cb737edd12e3323c5212ec60a407ecb3ce086eb3bb0236a76a1dd916c3785521708ef4c407faa5a473b915786f7ee9fce12a1c8f92259d8d9de4c79ad1ff5ea772d8db9fab9abdb5de950adc31bd2c4be63", .None}, + {.Shr_Signed, "aa678846cc6636bce5cc5a1ef1730ab18b0773d18c63ad7f0d929955e869f78cb8520a37dd0c1fef9d35dfdc2e697d28ab8b3b6c57577cd93f420fb0f33385f09f3834234e74b9974797c3b57514c9c2e63ef7757b5fb537fbec4831c4b9f49d720c08a84312d412d161271bbb66d044713a31cbc8a666693c41170fe88baf00f6155b9f52b8402132d03fc3c44b386ff03f50b17df4", "44", "aa678846cc6636bce5cc5a1ef1730ab18b0773d18c63ad7f0d929955e869f78cb8520a37dd0c1fef9d35dfdc2e697d28ab8b3b6c57577cd93f420fb0f33385f09f3834234e74b9974797c3b57514c9c2e63ef7757b5fb537fbec4831c4b9f49d720c08a84312d412d161271bbb66d044713a31cbc8a666693c41170fe88baf00f6155b9f52b8402132d03fc3c44", .None}, + {.Shr_Signed, "-2cb0f36df80d7a4acd26236cf3febc23048823f751ce2f2d26773aad069800b824fcfd54034c7d74c4c3c0b3d1855c73a09186519855ac6e219c2891751b0b9cd828cb00738406b63c80325580521dfc4b1fe9d09148f2227c439fecf5e8a52b5c7ec99e8b6b15b7b3ef99778adce7f78ca09f6762ccfd824b168b7a68825ce4a398fac177d8afadd280dbf39697be83d4b5564aa7f9", "65", "-165879b6fc06bd25669311b679ff5e11824411fba8e71796933b9d56834c005c127e7eaa01a63eba6261e059e8c2ae39d048c328cc2ad63710ce1448ba8d85ce6c14658039c2035b1e40192ac0290efe258ff4e848a479113e21cff67af45295ae3f64cf45b58adbd9f7ccbbc56e73fbc6504fb3b1667ec1258b45bd34412e7251cc7d60bbec57d6e95", .None}, + {.Shr_Signed, "-316071c4265f0b7f944467f01fb027cc8cddfa08f717ca8c1d174abc428aa2c1f2f93f6e2925d3c3c4fdd288c9900aa51a2f9f1b788100ca6edfedd6f11088ea0172a1bf5481a2bd8f08774e4a8afb77c5bd94a9ae5cbcb940d93c74121a781aaa01f1635f2efa39d72e0f4a3a1be29de6ab693ce986444d5df257f847dd32ad5792aac4d2be351e8b181cb0297552502704cd89018c", "1c", "-316071c4265f0b7f944467f01fb027cc8cddfa08f717ca8c1d174abc428aa2c1f2f93f6e2925d3c3c4fdd288c9900aa51a2f9f1b788100ca6edfedd6f11088ea0172a1bf5481a2bd8f08774e4a8afb77c5bd94a9ae5cbcb940d93c74121a781aaa01f1635f2efa39d72e0f4a3a1be29de6ab693ce986444d5df257f847dd32ad5792aac4d2be351e8b181cb0297552502704d", .None}, + {.Shr_Signed, "-2933bb1327eaa9a125c5a7d286c1c2c7bbb94feb407986bc84cd806380474471b18d84c02f582875b59ac35804e6825e231b2548d8bb7dd400b47bc58b1542aca68e620b1ca2fd35a67bc216e36c8db77c934fc1655db710706d2543f68c87d68f055492454e01d2dc7f616f8c4fcd5166d33f05a44905b0709bcf552c0a8c46fb4227a075899b06d42547328a3e3951dd0549ca01b6", "41", "-1499dd8993f554d092e2d3e94360e163dddca7f5a03cc35e4266c031c023a238d8c6c26017ac143adacd61ac0273412f118d92a46c5dbeea005a3de2c58aa156534731058e517e9ad33de10b71b646dbbe49a7e0b2aedb88383692a1fb4643eb4782aa4922a700e96e3fb0b7c627e6a8b3699f82d22482d8384de7aa960546237da113d03ac4cd836a12a3994520", .None}, + {.Shr_Signed, "6fbb5340e6c7dfc9f9a729a4dceba2c6da3766124784f084fb289fe434ae575f3dad6b8eb579962ee650eda7ec2249a06d19724826c66833801edba3993c677eb884629be57c028943f1b6b33cfcbda5669ca5bfbbb550856810161fb0bc64218c0259c2239220c0e94eb78663196882f137753e6b923374c7b76ec7126bce3b83af7e8f882c38f9cfa79558022afb25e673951e766", "6", "1beed4d039b1f7f27e69ca69373ae8b1b68dd98491e13c213eca27f90d2b95d7cf6b5ae3ad5e658bb9943b69fb0892681b465c9209b19a0ce007b6e8e64f19dfae2118a6f95f00a250fc6daccf3f2f6959a7296feeed54215a040587ec2f19086300967088e488303a53ade198c65a20bc4ddd4f9ae48cdd31eddbb1c49af38ee0ebdfa3e20b0e3e73e9e556008abec9799ce5479d", .None}, + {.Shr_Signed, "-d2017040429cf035554c0e9a1feee6aa35835acd58d7c358f2e9e255dd8c8d23b5b2115be6e9ee10c6b8614e59b3a31a352287b5b5f86cd12db30976b29c71b5d5bb0c77e550463b725cda0bdca95447c735f2468ab6c7d28a00166b567a2389558ed49a34265f91046078da49d32049c720a7905c10d9ed6d8cd33f8c5464067a0147e386db1a0175850ce97fb0d26ec91608d375ef", "35", "-6900b820214e781aaaa6074d0ff773551ac1ad66ac6be1ac7974f12aeec64691dad908adf374f708635c30a72cd9d18d1a9143dadafc366896d984bb594e38daeadd863bf2a8231db92e6d05ee54aa23e39af923455b63e945000b35ab3d11c4aac76a4d1a132fc882303c6d24e99024e39053c82e086cf6b6c6699fc62a32033d00a3f1c36d8d00bac28674bfd8694", .None}, + {.Shr_Signed, "cf2fb403ad7e5b83050a95089c56a53c30c76d89a8d86877a6de36c4424e0b2719c217bd7bc6ee34d669c40bd89efa5e89156b6a6d5a09873c7148f779ea2e5182d3601b8f0d170545c69b302e70b9d83e33c9b891f1293112c4b4ba9c5eb91f11e526640eb81979f96f3bcae6240de2e4dfd1a2cf0059f011c0e93880603d219a022c31ac1a534d023bd797c374c6214cd42240b8b2", "6e", "33cbed00eb5f96e0c142a5422715a94f0c31db626a361a1de9b78db1109382c9c67085ef5ef1bb8d359a7102f627be97a2455ada9b568261cf1c523dde7a8b9460b4d806e3c345c15171a6cc0b9c2e760f8cf26e247c4a4c44b12d2ea717ae47c479499903ae065e7e5bcef2b9890378b937f468b3c0167c04703a4e20180f4866808b0c6b0694d34", .None}, + {.Shr_Signed, "fac753055c8bb5b5bca9354bfdfe0eebfb663c3e16517c4f87549808fbc38919706983d3ea8092e02c8ec033da6d4c6e7b204e9eb895e2a2fa5e42a71a788a5247dde224d8db374012511d4bc89898e2776af8ab87867bde1eda81b1ed87a004fff6448d94d607eb5ce974b913ca6f3d6cba4ce4524c489d38fb67f5be1774c2307e03c6154ff1bc98622cd525f3ef9171b71238a844", "18", "fac753055c8bb5b5bca9354bfdfe0eebfb663c3e16517c4f87549808fbc38919706983d3ea8092e02c8ec033da6d4c6e7b204e9eb895e2a2fa5e42a71a788a5247dde224d8db374012511d4bc89898e2776af8ab87867bde1eda81b1ed87a004fff6448d94d607eb5ce974b913ca6f3d6cba4ce4524c489d38fb67f5be1774c2307e03c6154ff1bc98622cd525f3ef9171b712", .None}, + {.Shr_Signed, "-a775cec8722e98d485ca1e00c4c1dfcc88caccfa6771c258b68fd6a605052ba58c30125f02bb314bd7063f1e5d4255b39717b1ac617047d91dbe89195a6350fbee3d609a3e1b859b27ffc11e75990010b61f949805bf971a7faadce58a9bae44ba06c718d80b1d23669401e3831848ba71b7bd18fff847a2cbed8a4d84a82d81c19b560d4eeb0e94366a86adacc2fc4b315c0d989079", "16", "-29dd73b21c8ba63521728780313077f32232b33e99dc70962da3f5a981414ae9630c0497c0aecc52f5c18fc79750956ce5c5ec6b185c11f6476fa2465698d43efb8f58268f86e166c9fff0479d6640042d87e526016fe5c69feab73962a6eb912e81b1c63602c748d9a50078e0c6122e9c6def463ffe11e8b2fb6293612a0b607066d58353bac3a50d9aa1ab6b30bf12cc57037", .None}, + {.Shr_Signed, "78cbde17f7ff3c3ce3feeeb59ad31062110e6c80c8383af4665abdcf740d00299f967209bf562a10bf08e69d96ac5098dd281d962f4a6ad9b5e25fc419fb446003cfde635fbb04c0bd6380fe8f6a425343e5accce643c42d22f852dfbf59f3ee78701771d5ce65ed6e37eb00b0a8fa06983906bf2a0ca93b8c69ec47061fd88f49f55870a22730fa0ad0bcaaadb0c15674f4e8df1a0f", "8", "78cbde17f7ff3c3ce3feeeb59ad31062110e6c80c8383af4665abdcf740d00299f967209bf562a10bf08e69d96ac5098dd281d962f4a6ad9b5e25fc419fb446003cfde635fbb04c0bd6380fe8f6a425343e5accce643c42d22f852dfbf59f3ee78701771d5ce65ed6e37eb00b0a8fa06983906bf2a0ca93b8c69ec47061fd88f49f55870a22730fa0ad0bcaaadb0c15674f4e8df1a", .None}, + {.Shr_Signed, "b9756084f091a4912f180b27f30dc2f16d7a0e9993943d80bb3b9eacd7a1d9d97fbd27636924773e76bd79fd551ea36c6f6f34e8d557a2b6c975e7a3ac4d1770e304f4019b86f367f6c07ade03d0f070dfad222a1d5071321e375b6581a8d9d1c46a1f6a1d76dc1311e9f377b436b9829349bbbbb0ec9c1b0c92290fe0987ddd276727ecf3921e1ba326c7b56bb8aba117ad6ebf98e3", "74", "b9756084f091a4912f180b27f30dc2f16d7a0e9993943d80bb3b9eacd7a1d9d97fbd27636924773e76bd79fd551ea36c6f6f34e8d557a2b6c975e7a3ac4d1770e304f4019b86f367f6c07ade03d0f070dfad222a1d5071321e375b6581a8d9d1c46a1f6a1d76dc1311e9f377b436b9829349bbbbb0ec9c1b0c92290fe0987ddd276727ecf3921e1", .None}, + {.Shr_Signed, "-48e9dabdb8999855f4b0466ecba0e463aa6a3c89c5410295e7a928b02c8d10f0b05939d9d1fe3913c91439efc5e90ff6289ab36f6466086ac84aa4b865ef086ee1d7000b1c66f9e98770d69a92271174d237b52fc20a47cb9b7168d484652edaea9129f814a8cfd2237fa10a7da3a5a91bd9a3e691807d523c04f16c100e3bdf11fee18316786b1ecc621be9e822905f65e99642b816", "5f", "-91d3b57b713330abe9608cdd9741c8c754d479138a82052bcf525160591a21e160b273b3a3fc7227922873df8bd21fec513566dec8cc10d590954970cbde10ddc3ae001638cdf3d30ee1ad35244e22e9a46f6a5f84148f9736e2d1a908ca5db5d52253f029519fa446ff4214fb474b5237b347cd2300faa47809e2d8201c77be23fdc3062cf0d63d98c5", .None}, + {.Shr_Signed, "-93b5031fbaadec6c237d0857df2a597a1cd05e359600cefa64624eae0a356012c86123d7362627191e647b920987fd0477c50aa1ebd833830ebaeedbb0f880860f326389bae35d04323be5c1e7af27bdaa9439e31363209d5837ca0fdcc182529c33f973cb97e5a16bbd02e37d08a24d08c84917747dea9c6ea7409f143cf7bc71fb7739cfc4f4bfc0b04de530bd9cd643b4aa3bcb78", "62", "-24ed40c7eeab7b1b08df4215f7ca965e8734178d658033be991893ab828d5804b21848f5cd8989c647991ee48261ff411df142a87af60ce0c3aebbb6ec3e202183cc98e26eb8d7410c8ef97079ebc9ef6aa50e78c4d8c827560df283f7306094a70cfe5cf2e5f9685aef40b8df42289342321245dd1f7aa71ba9d027c50f3def1c7eddce73f13d2ff02d", .None}, + {.Shr_Signed, "4d0c9b40710b78b645a22fe6fb0cec728d54fc1e2f3eecdad6a806e970f5ad824540463b0a1432be29917217bd61a4f963ec52203a7c5b9ebc54af20c21b719aa2fd7c88d0dc115a455af4e8bc8b2f7b5be8f947dc9e9dc2958ecd151f15056a0a74011216e10c7ffc463f43d90b361670e622cd530b0a763272911332658bca7b34c2dbb843d8a23c056ea8b5ae5e0de1769ede299a", "69", "26864da03885bc5b22d117f37d86763946aa7e0f179f766d6b540374b87ad6c122a0231d850a195f14c8b90bdeb0d27cb1f629101d3e2dcf5e2a5790610db8cd517ebe44686e08ad22ad7a745e4597bdadf47ca3ee4f4ee14ac7668a8f8a82b5053a00890b70863ffe231fa1ec859b0b38731166a985853b193948899932c5e53d9a616ddc21ec511e", .None}, + {.Shr_Signed, "-1736641c0e8a4f2bce43f2a5f02bdbd3564eb89197d41622b68bcd35f956f72ef900e7e4f6c6a30abf896db6bf3b79592f07c7cbb8a02e842640f7b79e54b568ae1c0c1ef7aa28b9dfdfbe68f44d707634e2955e28d2e22fb8075b364d7faba19b647da6254890aaa6edb35f84ad75aff9bd7232e24131052dd6809110c720b9822f2fe0889d4d94a3a6bb89a98540c405b337d9f390", "53", "-2e6cc8381d149e579c87e54be057b7a6ac9d71232fa82c456d179a6bf2adee5df201cfc9ed8d46157f12db6d7e76f2b25e0f8f9771405d084c81ef6f3ca96ad15c38183def545173bfbf7cd1e89ae0ec69c52abc51a5c45f700eb66c9aff574336c8fb4c4a9121554ddb66bf095aeb5ff37ae465c482620a5bad0122218e4173045e5fc1113a9b29474d772", .None}, + {.Shr_Signed, "84d3f9e39fe712e14cbb181069d33e618e638cd04d14dc2fb0cc6a340589eb0b0c3250576a3ee804f9e70b759c356ca76ed24fea1ade51d36f7bbcbf8d78eac553bcd3f63e9eb5220467c1f02b4f2c66078dc5607f90f6e0cf05dbb53180dcfaf69d2dd851be276f1f409cc23ed4d21a79c121a523e4abbd3f66db20a46a71313d11fbff1b5f0351a694b18b1909b231d9b613ba374f", "69", "4269fcf1cff38970a65d8c0834e99f30c731c668268a6e17d866351a02c4f5858619282bb51f74027cf385bace1ab653b76927f50d6f28e9b7bdde5fc6bc7562a9de69fb1f4f5a910233e0f815a7963303c6e2b03fc87b706782edda98c06e7d7b4e96ec28df13b78fa04e611f6a690d3ce090d291f255de9fb36d90523538989e88fdff8daf81a8d3", .None}, + {.Shr_Signed, "-98d83ebab1a7eac1621832d72fe10c4f79dad61ed44e433b1c0f3e95afb6ec9ba6455bbcec88b99f272a8e90c06226169974fff1418e487de29509970aae231d1522eddc991767925fedbc190f08fcf34985c8a2fb3b7249717e55fb44856bd07349a4d64afe544d6db118693d5b44e3b4b7ccfa6ea521299d28470122075f4c72fe7ad7e0f6ccaeb3f02a8f73b4195ad19b84c448a2", "56", "-26360faeac69fab058860cb5cbf84313de76b587b51390cec703cfa56bedbb26e99156ef3b222e67c9caa3a430188985a65d3ffc5063921f78a54265c2ab88c74548bb772645d9e497fb6f0643c23f3cd2617228becedc925c5f957ed1215af41cd2693592bf95135b6c461a4f56d138ed2df33e9ba9484a674a11c04881d7d31cbf9eb5f83db32bacfc0ab", .None}, + {.Shr_Signed, "180355dc11731f369f1763408bfe8fb38a7869a65c9e16a7d22d9f85528c1fff384051653a96ac495ad299de88c3d1a1602806abcd1b1b8f584bc922eb3b4be31557854e0ed41091628335233d3802120386542b8173eb352da2b4cd5669ad040a8b2e9da95f89e1be2e83b61b2f761365d88e18eb084cab57d114e08814951e008d2e44df702c0c997498bf822f0d168e784b4bc2c7", "2c", "180355dc11731f369f1763408bfe8fb38a7869a65c9e16a7d22d9f85528c1fff384051653a96ac495ad299de88c3d1a1602806abcd1b1b8f584bc922eb3b4be31557854e0ed41091628335233d3802120386542b8173eb352da2b4cd5669ad040a8b2e9da95f89e1be2e83b61b2f761365d88e18eb084cab57d114e08814951e008d2e44df702c0c997498bf822f0d168", .None}, + {.Shr_Signed, "-511d1bee742c454a23464b16e763463f49da5501aed6000e14c07b682c3dc743d057647f6e5f7afa405697cee483378c417b967883074592dfe06411b50ef2b6f56665bb01d291e229537de64466ce74a59d5e931d0456f2c0d72a5e69d236a66cdb784ff4d9dd5d0a448100c13f198a3c707b7c32b3ea7ac3a9bc14ccb3a0a789b882f44edea8c01ac2b7aea124b965e82d6170691d", "24", "-511d1bee742c454a23464b16e763463f49da5501aed6000e14c07b682c3dc743d057647f6e5f7afa405697cee483378c417b967883074592dfe06411b50ef2b6f56665bb01d291e229537de64466ce74a59d5e931d0456f2c0d72a5e69d236a66cdb784ff4d9dd5d0a448100c13f198a3c707b7c32b3ea7ac3a9bc14ccb3a0a789b882f44edea8c01ac2b7aea124b965e83", .None}, + {.Shr_Signed, "-5f4399b93b47d51a16e2206f98167534ed6c0f33eb2553940c2cb9940f85dc1bf8f39090a3f90b6bbd7cd3a45cf99136db31e5aef2d5667d8af7bec38e3b69c579394e41dfddb3b14035ace29906c2497cb1b0a43956f84df9bdbb46ccce81025d5d4073e450da7a7842a6ab3cff688fd5c06e3ac184c524cd5e503cd39ebb37f841ebf344eba03bed2031434fe318927ff53577b6eb", "4f", "-be873372768faa342dc440df302cea69dad81e67d64aa728185973281f0bb837f1e7212147f216d77af9a748b9f3226db663cb5de5aaccfb15ef7d871c76d38af2729c83bfbb6762806b59c5320d8492f963614872adf09bf37b768d999d0204baba80e7c8a1b4f4f0854d5679fed11fab80dc7583098a499abca079a73d766ff083d7e689d74077da406287", .None}, + {.Shr_Signed, "-b96b0f23872efd8354551e4e541dc4fbdf21d4e6be02797c4ac9717116671a6ae02ede47a7a1c6d620ce8a206bc19e9ac5c68381e1b5116f1e677581965d0f4a39f27ad3ac5afaaa476be6185f5d4b0a27f2ea04f65ec5677fc67b1a5b23c94580a4e557a916f65a4153b941413a62b862c28e8e6a91bc311c20a0e6f7a8345dec2b17b6769cd3ebf08221426132d9026df54b541a51", "e", "-2e5ac3c8e1cbbf60d51547939507713ef7c87539af809e5f12b25c5c4599c69ab80bb791e9e871b58833a2881af067a6b171a0e0786d445bc799dd60659743d28e7c9eb4eb16beaa91daf98617d752c289fcba813d97b159dff19ec696c8f25160293955ea45bd969054ee50504e98ae18b0a3a39aa46f0c47082839bdea0d177b0ac5ed9da734fafc208850984cb6409b7d52d51", .None}, + {.Shr_Signed, "-568c5f3911236176cde7877cf392f0dfdecd7774dd0e1a73e1c9d3038aee133b8d4d4410e3bdbda4d8c88b92cb9c6d20b2b4caeed0e367b9dd352e88bd5046ff4cd903d9f73b1e2493c930526cfeb740c388a65478163b1fbd8aadd0c729c668e3a3428e61fedcb5724066e85630b22b1d532c4b0f086965082ec684601479ad7268b93d07eb9bc15c360c53f1796970e7c2b345a2e8", "6f", "-ad18be722246c2ed9bcf0ef9e725e1bfbd9aeee9ba1c34e7c393a60715dc26771a9a8821c77b7b49b19117259738da41656995dda1c6cf73ba6a5d117aa08dfe99b207b3ee763c49279260a4d9fd6e8187114ca8f02c763f7b155ba18e538cd1c746851cc3fdb96ae480cdd0ac6164563aa658961e10d2ca105d8d08c028f35ae4d1727a0fd73783", .None}, + {.Shr_Signed, "9727e1f0c2b78c24b8a5743f6df572f96edd6eba64be410b17db7d60bf124862f16c8ade1d2134ad5f09a1d429fd55c630ead57ebd54a67d853389da1a5ff5dcd15d11dc27c2e41b484454281e710a248c3c685a02162690408e2039ec8e2da8b01257508571ee0236c5820d71c8699032439a0924fdabff98763343661809a0434d244aff77b34e0f9cf2aac2f420e22fdd027fc87d", "45", "4b93f0f8615bc6125c52ba1fb6fab97cb76eb75d325f20858bedbeb05f89243178b6456f0e909a56af84d0ea14feaae318756abf5eaa533ec299c4ed0d2ffaee68ae88ee13e1720da4222a140f388512461e342d010b13482047101cf64716d458092ba842b8f7011b62c106b8e434c81921cd04927ed5ffcc3b19a1b30c04d021a692257fbbd9a707ce7955617", .None}, + {.Shr_Signed, "-d3f9b1410438326fe7cc44c557ff85249812334a4dea398b18d69d707558bfe91d64f4934a2dce1a8be0004366ea7730ce76ea692792710a84f4c0a4310f4efef76cb18032adfd5b365153079517e51065358c0bae886224021854fe898afef90fa88b027304bdb57a60e87bafeddaf8145ee87a92982bdc551867eefffb9976498b728d0a301ff1f15969990ac15ebcfcd7b02d30a6", "52", "-34fe6c50410e0c9bf9f3113155ffe14926048cd2937a8e62c635a75c1d562ffa47593d24d28b7386a2f80010d9ba9dcc339dba9a49e49c42a13d30290c43d3bfbddb2c600cab7f56cd9454c1e545f944194d6302eba218890086153fa262bfbe43ea22c09cc12f6d5e983a1eebfb76be0517ba1ea4a60af7154619fbbffee65d9262dca3428c07fc7c565a67", .None}, + {.Shr_Signed, "d50ea8d7da349413a66e0a971510f6af57be9bb29f6c2f1ec6fe89e8cf1a57aa291bfda08f19fb078f1b7c72fdd438e4faaedad2f05943b441d96c93b7c4bd1d15cbe2e7ecec6a318bd88c65bb6d9d98f99f7204f00a90ba02d2525a4e886b55afa0a55c2acb9f2d21bdde631d26f23c03d7376ad6fab8eab1ac1bdc74be3252b8d910dbc41b87e94c3ab698ff575ad58e5f6cba99e3", "62", "3543aa35f68d2504e99b82a5c5443dabd5efa6eca7db0bc7b1bfa27a33c695ea8a46ff6823c67ec1e3c6df1cbf750e393eabb6b4bc1650ed10765b24edf12f474572f8b9fb3b1a8c62f623196edb67663e67dc813c02a42e80b4949693a21ad56be829570ab2e7cb486f7798c749bc8f00f5cddab5beae3aac6b06f71d2f8c94ae364436f106e1fa530e", .None}, + {.Shr_Signed, "-b06ad71a6bbc06ac0ec827d54c6ff4aabd115349771b62b482d7c3f7356c09bf7fb5eee2ca90ced6122447d92700de663a0d50be2c509826acc8887b712e28cfd4e29ae7e9d08b724163793f9bd1634ce960fb03b9a5cb4583194cd0b6fcea70e8a60042d4477983c210f8f155e0227df9477631e179355ad9faf23cd9b5aec75cf383f078700296ca7b368feb19f198db00ff663d20", "61", "-58356b8d35de0356076413eaa637fa555e88a9a4bb8db15a416be1fb9ab604dfbfdaf7716548676b091223ec93806f331d06a85f16284c135664443db8971467ea714d73f4e845b920b1bc9fcde8b1a674b07d81dcd2e5a2c18ca6685b7e7538745300216a23bcc1e1087c78aaf0113efca3bb18f0bc9aad6cfd791e6cdad763ae79c1f83c38014b653e", .None}, + {.Shr_Signed, "3d4bf881aa6b28dd1046a097871362733e4d2431025cf482be1c25baa933869142bbd193b8d2859ee604d95e63eede081881c426d635896615170e580954e1de98061d12ae8fdda5160643b8d0a7d1839cabd23ac2a408f132601e60318550f79f78f06c1253ea16f8c22b227c54351116f329674050449a37196fc47f35dbe8d0574a4313e37dac5cb92502d0e351cf6e2d08425e5c", "15", "1ea5fc40d535946e8823504bc389b1399f269218812e7a415f0e12dd5499c348a15de8c9dc6942cf73026caf31f76f040c40e2136b1ac4b30a8b872c04aa70ef4c030e895747eed28b0321dc6853e8c1ce55e91d6152047899300f3018c2a87bcfbc78360929f50b7c6115913e2a1a888b7994b3a028224d1b8cb7e23f9aedf4682ba52189f1bed62e5c92816871a8e7b716842", .None}, + {.Shr_Signed, "fc4f2067e7226babd6e51eb89ecc636af0062872663c61af7efb925b7537beefafcf037da6a3da530bb73b506e48c98a50e45f3549f0a566f57ce5318ebfc3ce4c4a5c198ee14e9383dd9674e5aea4295b029ed28e98dff837cb10d11365ff018f4c3cf18671d8a97e727961b951838578baa0db9879c007dd81f96b618f5e5a25133db1db472d0603e683650f42dc97802af6354950", "13", "1f89e40cfce44d757adca3d713d98c6d5e00c50e4cc78c35efdf724b6ea6f7ddf5f9e06fb4d47b4a6176e76a0dc919314a1c8be6a93e14acdeaf9ca631d7f879c9894b8331dc29d2707bb2ce9cb5d4852b6053da51d31bff06f9621a226cbfe031e9879e30ce3b152fce4f2c372a3070af17541b730f3800fbb03f2d6c31ebcb44a267b63b68e5a0c07cd06ca1e85b92f0055ec6", .None}, + {.Shr_Signed, "48cf5d84776850d92d990c4ab65d89352e2542a47154c0258d0be4fc4df79a97feee3402269d8d6a1651468a01b6ab597eb12faf048669a3334a3361e8bb02a018ec8fae3605d18fc374403a7bd6a35a28400c49e0508a497b69bd32ddf3f54086b4f7cc4389556fa0f2d79c24eb2673d71ad49dac2179dba2cebb97fc9bf50c8f8adab0d115f12b6d2f43c09c83e970424f8cf72a67", "17", "919ebb08eed0a1b25b3218956cbb126a5c4a8548e2a9804b1a17c9f89bef352ffddc68044d3b1ad42ca28d14036d56b2fd625f5e090cd346669466c3d176054031d91f5c6c0ba31f86e88074f7ad46b450801893c0a11492f6d37a65bbe7ea810d69ef988712aadf41e5af3849d64ce7ae35a93b5842f3b7459d772ff937ea191f15b561a22be256da5e87813907d2e0849f19", .None}, + {.Shr_Signed, "-23b2d4d0da16305b1d90daf8ea6806aeaee1d2aeea8161364b0407ed58bda620899a82ddcf407f23da0c0b29268eb915e88d40cbf7e70b44f7a31ffeeecf10a2f8ad550a8e80d62e900c03ce5b2bc2af2e400a7092cb44d9c76eb67204edb9220010df8477f9f00b7a77647639c722de9084e4c526cf4e032279f76cf02f0acc17d3736fd6169ac298ce8ea23739cb3f87a0bfb908ab", "4a", "-8ecb53436858c16c76436be3a9a01ababb874abbaa0584d92c101fb562f69882266a0b773d01fc8f68302ca49a3ae457a235032fdf9c2d13de8c7ffbbb3c428be2b5542a3a0358ba40300f396caf0abcb90029c24b2d13671dbad9c813b6e48800437e11dfe7c02de9dd91d8e71c8b7a421393149b3d380c89e7ddb3c0bc2b305f4dcdbf585a6b0a633a3a88e", .None}, + {.Shr_Signed, "-5dc1a498dccdd33e1641781a15d451ec7c2d0bf815ed2238b347e7fa476fad74db50af5543e9fb0f2ff2046e058c9d4b91b068b0ff08ceda310b0820d021ea46fbb3433de8f9d22da4be1007ffb72366f589408edef2a17d8a3a019cadf457a16a0c3dd8c836509f69860ae023be1399bde4035f7551e1e778aaa9b6dcd75c595fa485883f0a8d58f432eff42b49a1d63d94b4119bb3", "2b", "-bb834931b99ba67c2c82f0342ba8a3d8f85a17f02bda4471668fcff48edf5ae9b6a15eaa87d3f61e5fe408dc0b193a972360d161fe119db462161041a043d48df766867bd1f3a45b497c200fff6e46cdeb12811dbde542fb147403395be8af42d4187bb1906ca13ed30c15c0477c27337bc806beeaa3c3cef155536db9aeb8b2bf490b107e151ab1e865dfe8569343ac8", .None}, + {.Shr_Signed, "-8589cf8ecc67022e1833124a9d8cdc3d47430292f18a79a3aec6467a6fb8a0baca3a2155de31457959f414cdd6b4a93f9ddfe90ec1c9a5766cb21229c56612b666d2e9ef040e0c86ff437f0cb34b020570d570e5badc4db4e7ea9b5ac444e35528a249153545d942b78e73980d986ceb938d2f382f2c8d024821fc1193d9b632204eea5b2f91ebdfd11dc367d33bbd92914253819b50", "18", "-8589cf8ecc67022e1833124a9d8cdc3d47430292f18a79a3aec6467a6fb8a0baca3a2155de31457959f414cdd6b4a93f9ddfe90ec1c9a5766cb21229c56612b666d2e9ef040e0c86ff437f0cb34b020570d570e5badc4db4e7ea9b5ac444e35528a249153545d942b78e73980d986ceb938d2f382f2c8d024821fc1193d9b632204eea5b2f91ebdfd11dc367d33bbd92914254", .None}, + {.Shr_Signed, "-b50222c1206e4fd6eab5a93d30b004d7ad5101bca1ede08bd47bef7f09d8fa87883f3edefd4f3e2e68db8baf40891d724ac71a0b0545a9a8ed0a74032c1e63c220aa50f48fc7dec76e39c8b612be2c7b651911b05efa1eca73c404ae291669218cbddd0e5165728e944a077e2e7915174196b59fe90e9f3f841f5a3779128c6525c68cf6c4a8546412bffcf2f6de75e67354f802a7a8", "78", "-b50222c1206e4fd6eab5a93d30b004d7ad5101bca1ede08bd47bef7f09d8fa87883f3edefd4f3e2e68db8baf40891d724ac71a0b0545a9a8ed0a74032c1e63c220aa50f48fc7dec76e39c8b612be2c7b651911b05efa1eca73c404ae291669218cbddd0e5165728e944a077e2e7915174196b59fe90e9f3f841f5a3779128c6525c68cf6c4a855", .None}, + {.Shr_Signed, "56e6788d00f86cbbf1db32c25eb96c41ac62297d613f5d45759dadf762ab4ad82926bdb76a34548577b4a8e1f8d5c46f7c849c204253b7a767a6b362f8a9f28997274eb995e7c74b03181b982b946971c9fda8661cc6c58388a8a2b895d3745f79de295baa3cf63a9f7ff00095b522322d7173e47c090df98f45266e17269f5244fcfe98644b12d88e24145e0c6102a2fa95c4a19523", "6f", "adccf11a01f0d977e3b66584bd72d88358c452fac27eba8aeb3b5beec55695b0524d7b6ed468a90aef6951c3f1ab88def909384084a76f4ecf4d66c5f153e5132e4e9d732bcf8e96063037305728d2e393fb50cc398d8b07115145712ba6e8bef3bc52b75479ec753effe0012b6a44645ae2e7c8f8121bf31e8a4cdc2e4d3ea489f9fd30c89625b1", .None}, + {.Shr_Signed, "a64c93f9249d0c02cea08a3087bab44964989abdd7fe176ccebfef4c52ed1a57c2052ca138900016612a0227ab2c01e6c0888df27797bcc35ef29c3fbc04a08a5ae6cabe49ce7162034c0b75ae2e8d5bcf71643de85ec3c82755c35e4c621c588d93a4392fc8c34bce34a988b1e81659825d8b9343f6013fc094d3e9b2fdc4ac86996c2e8cccdb2390d0920b642cbd3e44bc5f20c10f", "71", "532649fc924e86016750451843dd5a24b24c4d5eebff0bb6675ff7a629768d2be10296509c48000b30950113d59600f3604446f93bcbde61af794e1fde0250452d73655f24e738b101a605bad71746ade7b8b21ef42f61e413aae1af26310e2c46c9d21c97e461a5e71a54c458f40b2cc12ec5c9a1fb009fe04a69f4d97ee256434cb61746666d91", .None}, + {.Shr_Signed, "9abbd282017e94dad95c37dc37f246dc193e5ef5a33e92ec4c1ae82bfb305405e1d7b06f15aaea2ccd6c69c50daf8ca6dc8a743b6356fff72e4b2932e642ad3ea7030a8ca60fd3cb25ce6981fd9633ad4e6e4ba97616b97db63d04f917773393087921f78e812b7f52aecdfbc43394557c45036f9802e3b5f0b222ea6b544f40e8fa8c9dbc1df694f5c3ad4b2e134318831b7a0b04f5", "6d", "4d5de94100bf4a6d6cae1bee1bf9236e0c9f2f7ad19f4976260d7415fd982a02f0ebd8378ad5751666b634e286d7c6536e453a1db1ab7ffb972594997321569f538185465307e9e592e734c0fecb19d6a73725d4bb0b5cbedb1e827c8bbb99c9843c90fbc74095bfa95766fde219ca2abe2281b7cc0171daf859117535aa27a0747d464ede0efb4a7", .None}, + {.Shr_Signed, "-3e22e1c410863beea4753065266c625c2fd63edb22132dc06d7ab4dfc8a60b0f36e9fced05d7aa6640bb740a63968b41fcc39d6702d8fa203fa15fe8897aedc8875c9b3d34be48996712ee89f96d31d54d9cdd4f02d302b5204bec6fa62c04224a649cb45c418a5f5ad443b9fca7d5d6c2faa99ef24b411e465b4ec2ab09ffc8b6db3bce513ddf2bfe01b9e03f15a3d99e2ab158a04b", "48", "-3e22e1c410863beea4753065266c625c2fd63edb22132dc06d7ab4dfc8a60b0f36e9fced05d7aa6640bb740a63968b41fcc39d6702d8fa203fa15fe8897aedc8875c9b3d34be48996712ee89f96d31d54d9cdd4f02d302b5204bec6fa62c04224a649cb45c418a5f5ad443b9fca7d5d6c2faa99ef24b411e465b4ec2ab09ffc8b6db3bce513ddf2bfe01b9e040", .None}, + {.Shr_Signed, "-8b989963d9db9935ddf029a547415d7c58c391f45819363d9d0e1d893073cd3d8c99ed3fc53c61e9892c40f56fb9a4027529006a8138df459b22512350e15b1f0eb70bbcdfa4fa1d7e2fe2a6d710dfa55f74814a1294a3761e54f0902b3d9cf551c0e9664f7639e3aecf6d9aea14a275e6aba241fdce5b333d571f9240fddb8e4c47edb0f9e76ffaed0ddc280875759bbb3c2f341f84", "4e", "-22e62658f676e64d777c0a6951d0575f1630e47d16064d8f674387624c1cf34f63267b4ff14f187a624b103d5bee69009d4a401aa04e37d166c89448d43856c7c3adc2ef37e93e875f8bf8a9b5c437e957dd205284a528dd87953c240acf673d54703a5993dd8e78ebb3db66ba85289d79aae8907f7396cccf55c7e4903f76e39311fb6c3e79dbfebb43770a1", .None}, + {.Shr_Signed, "-ce34f77b7d2a4757bba06c8d7d95aba3715ec40516f5d234d8c586fe72da59ce3d61959b0262fb931efce0c1937c6de52ffd613b27a9cf672689024230127d00c5ac39f1259e9fb00dc808f3c5b37961bf60def746e6dfde9940999386b1af3acc26ed97bd0c4611bae2cc6ab688dc326cefc428daf8668305b7be4fe0063571d7e0cce7fa89b06591f178230b48752a9946e19cbdce", "5b", "-19c69eef6fa548eaf7740d91afb2b5746e2bd880a2deba469b18b0dfce5b4b39c7ac32b3604c5f7263df9c18326f8dbca5ffac2764f539ece4d1204846024fa018b5873e24b3d3f601b9011e78b66f2c37ec1bdee8dcdbfbd328133270d635e75984ddb2f7a188c2375c598d56d11b864d9df8851b5f0cd060b6f7c9fc00c6ae3afc199cff51360cb23e30", .None}, + {.Shr_Signed, "-12dfe1857c63f9205463f6d569b2c226ae6cda296c96ce938198a1855a48195905a57cbb50acc8f75aa1b34ee3e35bc170f0e4e7076c944dd27e697f0a816621812af9c1f84144aeba7bbea6c1e355f2f49f5a5ef30f64c225c96959ae21ac5e91a7f37389fc5fe970c18316a794d3dc62eedaccaa0a428e454a8b8ff8e991b51c7ef0406e1a21615a20e127df4444ed831564df5487", "3a", "-4b7f8615f18fe481518fdb55a6cb089ab9b368a5b25b3a4e06628615692065641695f2ed42b323dd6a86cd3b8f8d6f05c3c3939c1db2513749f9a5fc2a05988604abe707e10512bae9eefa9b078d57cbd27d697bcc3d93089725a566b886b17a469fcdce27f17fa5c3060c5a9e534f718bbb6b32a8290a39152a2e3fe3a646d471fbc101b86885856883849f7d112", .None}, + {.Shr_Signed, "fa93fa3a4d9e74bcc1e0506553a9f2751d0f8828ee1a94af3665dab70b29f9130e3eed89ac998ad6e7639a2fd5a2ddbbaf200d63b1f8de07fc491e2fbe67edbf4c865fcbd2dcd58e6891fe9a2f2496270bdf0321daf095f11732304b30e33893b5218c4c99cfd70e5d33e4ff2a94ce2ea62f22787946b1adb19dbb9b7488d6ba4a7ad859c792ce37b15ae6694fd6691993dca1ea4fa9", "1b", "1f527f4749b3ce97983c0a0caa753e4ea3a1f1051dc35295e6ccbb56e1653f2261c7ddb13593315adcec7345fab45bb775e401ac763f1bc0ff8923c5f7ccfdb7e990cbf97a5b9ab1cd123fd345e492c4e17be0643b5e12be22e64609661c671276a431899339fae1cba67c9fe55299c5d4c5e44f0f28d635b633b7736e911ad7494f5b0b38f259c6f62b5ccd29facd23327b94", .None}, + {.Shr_Signed, "475548682a5cf974c773e5ef26e86b47afc552ac55f14b7386069b134c84e24a9470700faf5baa9f72c45907f9037d585d5cb3fda47045d36cd53b7fcb6af70c3b8fbaff9975bd19d702636ea6fe35a3bb9c61229931c2be137be606467e147e20fc665a629d2861ad979ff5d74351a55634810ec27649c0767eb95c69053a29e3f62cbf7007b2f113abdfb6a55e9cb40d01205c7fe5", "50", "475548682a5cf974c773e5ef26e86b47afc552ac55f14b7386069b134c84e24a9470700faf5baa9f72c45907f9037d585d5cb3fda47045d36cd53b7fcb6af70c3b8fbaff9975bd19d702636ea6fe35a3bb9c61229931c2be137be606467e147e20fc665a629d2861ad979ff5d74351a55634810ec27649c0767eb95c69053a29e3f62cbf7007b2f113abdfb6", .None}, + {.Shr_Signed, "-c4de54b4a61ce530e5d4ce5b6cd20f5cfdaf655dcb1e250a8738fcf43b279f99ec73629fb5e749099247488313071e4c09a3af5a4f6a611a189dc636be3a4272eacae1d8b53b5c872ae31f6e7e8eca3dda2add175857749236db58ea31d2e0aec7af9b976204f52ab7c8f54e84c8937afba43fb30491d8ed61959ded29d1610bf8757e9e038a5e1bc4fa1030a61b5d14bef8720e6f34", "1a", "-3137952d2987394c39753396db3483d73f6bd95772c78942a1ce3f3d0ec9e7e67b1cd8a7ed79d2426491d220c4c1c7930268ebd693da98468627718daf8e909cbab2b8762d4ed721cab8c7db9fa3b28f768ab745d615dd248db6d63a8c74b82bb1ebe6e5d8813d4aadf23d53a13224debee90fecc124763b5865677b4a745842fe1d5fa780e29786f13e840c2986d7452fbe1d", .None}, + {.Shr_Signed, "-e271c3d22f37b8ddf57ed07c81e2fbb9654b94a6759c2fd653a8455b07e45681bbc491adfaa994a9e54717f1192e9111f6dcfa493ac277572b35cbe369763464a171c763acbbf43bd417b9992fe8242e2c62232fdd1dad8b533dfd83ad029f93d8be86d33117985826767b2a8adad3d0a902f54393815e5323b60e543239ac75b3bdce1bc5bd1e8b7fa4a82991b47057c1c143a93006", "2a", "-389c70f48bcdee377d5fb41f2078beee5952e5299d670bf594ea1156c1f915a06ef1246b7eaa652a7951c5fc464ba4447db73e924eb09dd5cacd72f8da5d8d19285c71d8eb2efd0ef505ee664bfa090b8b1888cbf7476b62d4cf7f60eb40a7e4f62fa1b4cc45e616099d9ecaa2b6b4f42a40bd50e4e05794c8ed83950c8e6b1d6cef7386f16f47a2dfe92a0a646d1c15f1", .None}, + {.Shr_Signed, "-4593a4ef9a06081c2140927edeb948efb4cabfb6efc0983269155f0c934ee2e64d609d99d2bdd201513b75fded6b3fca2673293367cd2627a8fc92abb8924ba64fa8f3e5e4d1c8a81d4f14546647f90d7f621d342d3484883f92684dfd58b602023c3f66b779c58ec66aeb9b8dc81dce0ca36b52c908051a335b245b087ee6c95d8820320078a5179bd3b4bf67cf2a96653b4fc8eac6", "22", "-1164e93be68182070850249fb7ae523bed32afedbbf0260c9a4557c324d3b8b99358276674af7480544edd7f7b5acff2899cca4cd9f34989ea3f24aaee2492e993ea3cf97934722a0753c5151991fe435fd8874d0b4d21220fe49a137f562d80808f0fd9adde7163b19abae6e37207738328dad4b24201468cd6c916c21fb9b25762080c801e2945e6f4ed2fd9f3caa5994f", .None}, + {.Shr_Signed, "-99e6ced373131cccf43997a4891fbc129f9d77fd01fe9b8b4383aa38f208384c647a36c9374702d7ab60162f60415bd23df89192c5cb76590be62152d537b5710d655e9d4422d38795afb874d13b9529ff4c3eade248b42c723f126b5ccf9d7b77bc44dc24f6b95c6c5afc3eb3f53de160e451d1ceade2beb969b08be4d62624ac3104cdffb5f507f4228759c6b1ec520be1a64a1b00", "56", "-2679b3b4dcc4c7333d0e65e92247ef04a7e75dff407fa6e2d0e0ea8e3c820e13191e8db24dd1c0b5ead8058bd81056f48f7e2464b172dd9642f98854b54ded5c435957a75108b4e1e56bee1d344ee54a7fd30fab78922d0b1c8fc49ad733e75eddef1137093dae571b16bf0facfd4f785839147473ab78afae5a6c22f93589892b0c41337fed7d41fd08a1e", .None}, + {.Shr_Signed, "-78333eb735a71c8cefcdefcafe66c7b644b6c0d2cdc68b4ec7ed9862041ce42abc3f7dfcbdd313efe15faa9f65ca34a2e007023438ed7b4deb5e8733073354e043f7729aa2efcb80ea735289b8432f59aa1aeb6084ecc21c30a91ed0a4dbeba52c14320c71c4450df7117ab040e675c438383205ff8a8f2b34e68c108515d15d92c67f3e7feef3f8d10fc8399b96293ebc6d6b85a317", "1e", "-1e0ccfadcd69c7233bf37bf2bf99b1ed912db034b371a2d3b1fb66188107390aaf0fdf7f2f74c4fbf857eaa7d9728d28b801c08d0e3b5ed37ad7a1ccc1ccd53810fddca6a8bbf2e03a9cd4a26e10cbd66a86bad8213b30870c2a47b42936fae94b050c831c7111437dc45eac10399d710e0e0c817fe2a3cacd39a3042145745764b19fcf9ffbbcfe3443f20e66e58a4faf1b6", .None}, + {.Shr_Signed, "49609479001d385e69ca0851a00f2e5037b2c0cb75aa5abea3ca320cd15e6ae49b8b8febe82af566ec9ba70af397197cef1c4836c683fb34cede40291b54d214e4c16665a5010c73658da7fc9f439699b7747b71f384f22d27003129321294ad53a16121d60e7e9ff0c3e8371d15241495cc07e5617a68b3022c9c8bc3a1afda4305d0292958718901e5ad8c57794fba91a82e1140b1", "56", "1258251e40074e179a7282146803cb940decb032dd6a96afa8f28c8334579ab926e2e3fafa0abd59bb26e9c2bce5c65f3bc7120db1a0fecd33b7900a46d53485393059996940431cd96369ff27d0e5a66ddd1edc7ce13c8b49c00c4a4c84a52b54e8584875839fa7fc30fa0dc7454905257301f9585e9a2cc08b2722f0e86bf690c1740a4a561c6240796b6", .None}, + {.Shr_Signed, "-bcc96540868d8f7db67f177f054355966fefe156ac354cde9c230814927454f10be4384cc205a8c0b8b5097c10d1e24ae3e73073c47b7016e10253bad456b57616003cb37a93aad82537f43492e4992d0e555ce4b91295fb389e863767824adf5ca5f04018e481e3542d8d34dfe6559d425e8224a43b5be1321a94c8a58683f586a47756c069a6ddf910f923905f7df0bfc4868cf55e", "5", "-5e64b2a04346c7bedb3f8bbf82a1aacb37f7f0ab561aa66f4e11840a493a2a7885f21c266102d4605c5a84be0868f12571f39839e23db80b708129dd6a2b5abb0b001e59bd49d56c129bfa1a49724c96872aae725c894afd9c4f431bb3c1256fae52f8200c7240f1aa16c69a6ff32acea12f4112521dadf0990d4a6452c341fac3523bab6034d36efc887c91c82fbef85fe243467ab", .None}, + {.Gcd, "-dce27058ecea31a6d3ba6b1249c3e7f0233751e474863da74f911ccfd323094be15561afb0ed72fa2d85b3e15b6e7810d5c67ccfcab33e73548fe3b287cea2cd2329715da0ac07f9b01a1337d2f10f196496c625aab4735a17d06c06335505dc77c5600ce1de730dfa852d46baa0d2fac88312b243a91cc848f70ee3252f7e573d33dcdfcc916dc734dd544b603e907ab57045b3f11", "4213f99f4e9f8932736c87158f4db27a877f205e640b5c26164395b8fc7f31424968e2b6c2bbcdf87d23177993e5ccf0545e0611ea6972b70ffa9026b67b1172a3cb245c4a7ac8045e56f032a9c11cb15528eb422e516ae5f8b57733a1e00149ccef51ac33c08050cfb185eb9cfe44f47151263bbc5410dd59c549765dfd2cd015fb99c38cfc826d7e06cc36e0fcfd35843c7bf2bfc7", "1", .None}, + {.Gcd, "-30fab377171e64bb7b931906247097c3ba0d6a124e639bca5514dd79d126d5cea1e4d7460b5a7a48781ef9302c47492c8db7a9fc0090a59165f4396a70816f2addb6b8e80b846a575d8c4df952276858702d545279fbb0f9ce09bfdb5a07479d480db71fb20ac54dbde6957eb39bf8d8d6762b33e371bdee134ab6af996cad011e0195bd3f43962204bd5a2ebeab6c7d7548b9a9dc0", "477eae4387c95a69c8775ea116065918a63964cee4724749c6b80a8637b2e52b441c5d675c794ede19db2264061a886c8dc8d06d57cdfce18ed5cece2a0a565170826a3aed3e4540a9869a69c3b565651d10ca7c759baeea0d40170e9df92e24a5be9f090a3ea83ed6811ee8477ee143979ab01affda04c3463a6ea83f719abe73688050bfb92413311aeabcbf6fe129ce84e47dbb9d", "1", .None}, + {.Gcd, "d2fe4cc631b0a04acd7b38836d9fc3c5b03a0723de22a091f8057646a853bda21277b516f37e0e95e3206ecb2d4b10d719ebf15ee68f37398de5d5888655fe3a05fd1539f04cf2019a72ee7327e2817216810e0971342dad9c697346115b1adea9d4ec23ca206b32af65f5b0e99115735b9712d8239514ebb5a4d87897dbb36118438ea748e28cdf7d468fbfe6c0d2f5d2c5797acde8", "37c4582f6c93c40c3ee2b690637de4f8b5cafb69d65042a918eea0d7edbc6239b954edec76563ed135f2d83c90acf9f87e783dd1ff205fcfe6cda3b3ae642472b6438b2fbf23f7c2bbd445523816a8605ca45ed7ae191e6889183396e60fa3e15b0125c9dce460f605a22229e2342c59800796c459c5c99cc88c9e1ed1dce3a8ad98e29e1686d29f5d918a28941934895ad09db400a1", "1", .None}, + {.Gcd, "352eb8a645e374a0c280a31b8778c536a620860dc7950c83c4d42dbc5a024bac648718cfab2706fbec2f43537295705de952f1f583c5b84c2ee1f7e285a0c1457b2909635876e4218f427356f439e4627840fdf4079e41bab64332efa927f24b1cf65d48b4671e059347e3f81842fc806d35fc7d29759331424fa6085b425fe97edd969c8bd083fdd1e52a69feae36bc298ca9914f9c", "71428da161651bc4a2bb3fd9b619113ec0eaba47376a94d12682e015fc574673239bdde2a3a10a99498ec20e0ce3ac1808da41f673b666c46cf588c4f4df219c55fb522210717329c72a5509f7c7ae23d54963ae2d32c12c8a110a7069b7b7b4747ee95f20611fe167edcab48f49c109410193c45a7f9cb89535bb5913f19329c64156df8378c3e843d4ceded21cfb8f018c748ef7fd", "3", .None}, + {.Gcd, "-1e12cb15f32fc005409a920ba5055e6f07707986a53b6c76c941c027562a3102d70c6b9658293545ea3fee68dcaa9699bce59013f8f478eba648830172d4bf6f25e3a3450aa2f2cb421cd70d4a331cbc6e33a45b63707ca24f6cfbe63c11bdd5497ef7de6cf2c5151e78b02b60fef24e65dd7ab04e1e961c6881d33a53b8a9d25e7b9f1825122445ff397ed2665aafa12d770fc8f43d", "cf70e40a51995f0b04f8ebcbdb7adf14e8cd46066808818b3243fa5b00f60a23899863521e2b7f320c4fa68f3594b89ea6fd70647f5c13b01e9cd1eb9032e355458e6cc9cd4a4151bf2abdfb4027deb801ac713a05e063c189b74f2e89176b9c05b5da4cd493e7e4236fb96586ec08a4fa376381fade441b76a0548ad3f3ad39c58bbaa1e0daf8c143be236031b8105ed45fe6b3a7fb", "1", .None}, + {.Gcd, "98e6c94741fe4558583895f3bdeb74add31fc190c172cfa931081916f30cd5234c124b0b6a924ab87e33e7552e9438dd3fe6a985be3f6211a32f4a493b61cc5809b9e0bb731b6ec378cd2d3da33a7e3d1fcc8b61d6a860b65c57720669f11d99393570bdc0866302b2095ec7a4cda5d9e61c365d091e476fd4bed400b56d5cc389ac11bb830dc6abeee44456d3b9f5dab94fde1fea87", "244cbe2b4fcc9982ac983a66afd48f818ce80e284162fd5ed355188c67a302484633cd3ce60b590f34f33b2a345cf29c5b2934cc6baf062d002b8f1e9cb0f354dcfde1c50d3875c624d4f33c748f50d7e8a8cad6d47b0ae93c70a27a3b1e3cf5e150f2e0c18e9ec5d26b9c7009ed61d51ad47f06ff9d89826f5463aaae351037e04e2c81d1db44b9fbed9754417afe248bbfefe08500", "1", .None}, + {.Gcd, "2754aed11d65a480fd309687bfca3e6ae6658bf20f529a73b7b85989e2384180b96c9755f78b6e2c60af84176617cf4b9aca484c024016a055ce4e41e10871cb126398fc6dd8e0edea54856da041e5fdd9e5b37a588df755aa1c5191c7476c7e6de00395fb00a26ac456519e56bd816ebcb16cb5900a849686984785a89b3bb127a8d6e0f86f3caf8820644aa158f1c48d26f4a22f79", "17e25a22ce94b4e600946c95694dea26c8b8361722df5a59756397c9ab41c34fb2ab01e4ec541f8ad9600849ccc9df47ec5da332d5539f61de869737fb4a5df38f77c08447d829eb2db09a827aaa15cb15e5bdbcee569bd15b26b91e05843a0b6f13770d3497bb7b7b53486a71745bf1acbdfda003d1ec0b817d297f54342f5a2efb8e7dade21212e43c357a9249e954bf3759a3d0a4", "3", .None}, + {.Gcd, "-bf841c6911eedd977bdcb0d615b0687f9821fcd898eea1c44d94734d9551e20fa01fc101fe9bdc4cdaba4bed7effcb43ae85d201a96a0d1b1d8cb4103ff500447904664a4dabddadceff57042fad02836c578c0b4865e669f2583edda418c553d7abd092143279e6d6082247cac763bc97b14c4e0d0000b61f1ee4dbe04b7c2e16971c972bd3f4c4580666fe46e5250ee131c47a8b4a", "fe6a15db9361d901442986fd413008b8c6a86cb85527278885d056d787327d174758cb7b096eaa3896f01bd48f6fdaeaab34e7b4f3614203534f80bb84834f4a650bfde12a6f6c1ea3a92076447392f33eb1060676d40a73503737340f193344d65bf94ecd578240ed3b8b5df98bfb52851a2371729fc1163de86a9991403fb7383997b1e860adf3975e61d0ea7400adb004ae822203", "1", .None}, + {.Gcd, "-e4b5787cbc3aa5e9477d4cd7308eed660723dedb915bac787fa796a912da77b246db8f272440bcf830d87d64b4fc7091606a36519a2f65f600e75a3b28add49c154d72649922ba5231352f01bfa5859589b7ca4a560cbab265df55cde5689494f5518a9c559143721bc0c9b056ef1f280f28b4069277db8bcefb7062c77e247fc3dc3baa4bc9d575da9fa590430b493d9d0d1219f7b7", "cfcbdb39e0d01e8ac8cf0439fc77085281e4ed11ceabbfb54b0a7d1ef5b71b116afa36c067c366d35c7499ebc4a08b9a3042232a017a69216e3852675e76605067d57d784d3b59ce2a79974c0c35e4132a3c7e61cbffea297fe39c8690a818139f541f735c5c12d00b56b6c11001fd4a8b1ca03966066c7ad04847479c4ffb77b9b93bb6e1a426d19fe5229557cc59a3f52062cbc3c6", "1", .None}, + {.Gcd, "64cd59d816ee8b6ada45a4f837beefbb0700352e3be7edbe76950f6c209288613a97ca5d07d7968c92a548fa8b0e10a8ceb62f3ef24baff353dee71fbc668fcf0fd6b577b167e09ca0d3f23e823ccee47e68e59af45e1753429087ae6e81f3eec72c8285b966894b4733e12e97a0fdb9024761b86c4491ece8721abd64ac0b463b6693c9e7dac4e587b1e0b384ebc973e68b6235b0ee", "c7d997dc1dae0e60b3e65c4e3365fee2687ae17703b06be54dafa67c65fdf39d747968efd82123a1afefdb5e0e6af01d2c889155f2f7872f7d0bff85800abca4ab8dab7a9fecc0848974a534e5883801713f85deb2c08b2ecb700535d88fdce5efc305d3555bd474c1052a5f83fa101abb2870d6ce331469b3f7e65a9751afe587be0c23790d48dd840e6789c0257dc0f8cf9f9c6d62", "2", .None}, + {.Gcd, "-178da89ff100107a3fd9580f11d77a49095eccadcd385fa2091ff49d34f274da47587926a4d78a202090e9fe95293c05bb3f275591ce5902556b44df8440ac4fac24e7285e5ff5b3abb2234647933759867eb5966555ab9b44e3811e75c6b1e76f95677a5fa23a39a1d506b835067442470c4bd64584ea9896bec0bd6dae0a66323d025610fe98a85dfd0529fba31b285ae1a762278f", "ca77223f10be6d09b27888a10183fa1fc46c897c244af355f5f80214000a4f03ad9803a760b28b8934034d5c68a6d81437682b3d832314919047caf725fd54c83b3b842efb307fd4e55c4088b1309421c6f6db7b48fefd8d1e826cd9d01bbf41c712745a098ca95a5f791eac53bb6dbfa84b032bcc2debaad850d96d8ce2abf7662db1c2c73f5a1c0d893020a5cd0807669007d0582", "1", .None}, + {.Gcd, "a7e707cc26477774e04a73beb70fcef81aef2a9ecf36508c073b953ca31f631de8b0170dedbdc3603197741e05558819257854ef4b23169b7da796019a020799e82f82d058e1953eb6141ea66f4c4e3645d33dcc012a15c16388c6ea4895c9f24478e567bcb7b4f6b461477a1ed94bc8ddb4183b799db5bfdb4423dcc256219b3ad7a2bb56c197207a6559e7695be671b1868c28f9c6", "875ac541d7e3c696cc5497f599eb5dc89d72ea2c0cb93bc62d635dbe6c40b0e257b4bfc871f646be5f23f43d0e59409b09017852d8ecfe2ab5592a8b2fdfc24c2be12dc9f269103bc2494ca1a3eaa84047f5d42b8a91b16533017cca1190807f9366c08d6c45b4477b5dc3621983cc301dc00ad1bb680565f92067a281fb1eb569bdf52a7f633089045a99657c2e3f21ab2b77dfcb9f", "7", .None}, + {.Gcd, "c9d5cebe5815f2893834dda105fe4f97d5f2ce2aabe4998b57298709d5665843f8f47b0537f7715da537aa1573f7ca532b04fd0abfa0d029c24c305575101f26cf8a9e32530df07ceea26e289721e17945481e007ba992e4b03e16a08e1de5594470da20fb4a1ac101dc4e46eae7e546d96e8882269b4fc52df62d142601ce03448608d9ac5e3a81771a23c85be44c030a7d59beeb83", "8b89895ca471e660c9e5e4c6cd5d3378ac0abf5701caae4e31fa0cefe67402a03b65208ebbff165c4b1aabff1eed0a874e8690c3dae8a0d12807c8beca8a7c790c93cb17a8dfcade73d9d65848fcd463bb0aec29db384e03b3524b28a4e9335de5c5219410dc3fc6793205526bb0ddf67d1d6cd63c647e43d269e373eab21a763fab62c206350662cd2af83dc5284c11671618a3297a", "1", .None}, + {.Gcd, "db6cda25722f5402f1e4b301f8bdd7a03c63ecb7c023b323380b805ade5afde42548ecbeceec942d4ea2dff19df6221578689068e03ad1e2d7aaa1394730a6e7d0983e87d4c2df4ad3c5216c7c5cfaa63e26b71490cdcea6ccbbf63ad51b8faec5d6c4449335fddb82124380e91c375a09224d4bce91d09719fc42d3d08e37bd074a8b3cceb79ddfb11d3bdfe4545a8c690308189616", "d64321fdca952457ceb06151757c10ee9cece495e2c8b605cdd25475e03b732cd21f0217af0b7e75b6ea63c0bba96266f0440f11e4699a90c30e473acf4eb244c0d88f8223377fe95bf90eb34d2fb862614c6259f2d5ce986b267cc991207b43f6d60cb0e0bd56c133415e86cc966ebc65fc44694141c780d0d52ac68a00cb5bb760530ce3244aeff045f527d8240e2147fa7373cbef", "1", .None}, + {.Gcd, "-253181ecbf9f80f23cc283410daec8602aeef4c5cde944779c36e28a16efd58cabeec2ca79f1e3685c0ead5135bc6526eddc9a169b7c13c545e6622b21e2835b48d3284df2ae0976e96150bd6a2e533fd7083312ed28152fb9f7670a78d5d25f82c44557e0c1e1d09a8a13e1e2e09385c0ef4152987ff89394b1bd07c2731736c5f21c6ac1242326593a08668ca6f50f16fd3da04656", "ce2aa279dcb5acd9249ef6ddb283ee9933819233b274b46ce9193da41eea493abdb04973db9f797b37c5b3fea455b1b4dc6dc70c857e4d93b1ab0e363b10785454a86ae929cf1aef6b329d6565c08943cdd9610bce6a00513c223eba983e06855a8b2af2837b5b7f1fc4061a0ffbd1256a0b0cbb7a2da9b20bce37367909e25ef8e1eaa3d1d7c004b912f83589f38d009e2f64e61253", "1", .None}, + {.Gcd, "a1409dd3da90b28f223217bfb76f7d4d07b61565cf8ad88bd1abf037f1fe6d28140be5392e700cb3af9d977850a2407c030645475b0348b38677c2555b6be35dfd614bea4939550bb1ea8dbefa5fc75c8d3c18f11bb6f193e671c703c4c91b12a594e53ab1f1a12cc39ac2f724ef89d36a542bf56076d2d0918f0be2c5dbdb022c68c88392eca2258990fb43c3a8edce2820edaad901", "819532d46c8579d2ecfa8eae92f965091aeb3a14f5fd66f05fffd022be8e7f957180b5be491224b687c079c620182998f0328f05ad8e8f2140c2dc65202cc3f14463795bb04f94e32c8e3acb8cc25743c3ce993f87b23540693f223a4eb14f83ec2e9855ae8d32dd5270b93a5a9537c0f4d5c57a6881ca726561b90fb5b563b34b3db22ef67ebb9e81d9965e8c393c68440fe4b09420", "25", .None}, + {.Gcd, "-52373aac920e3373c3ebc8b2a9669da690137d2de38feeaecbfb6ea7f7a79767a1bcb1c68946729cfbff951c81b87f3d5adfdab9991c89fc02ddce8ede077347e6fc466abcc1d950ff9a3631570f5bff8e3f9dfe4f7d6e1dfc0c3549481006394a10ebc89b1eebf4d146a270baec1651d74f885139c8e1467c6244f35f959465dcadd14f81a5e70a0a2bedcb23e648ff5fd4f09fe45c", "b4e70408a8339a40da2748dc5ab99cf3639d22f836d4dce144c6df18c55a22b922ec04a7549392cecc6eba7f4be4f09400e755340695fa1d9d41c4a5abdfc2c7c7a02a199d493cc88a7121bed98777fd70a53a8b273b3eae392f62879dea96cf6710bf4c6bbf756e18c1acc9c2b4563ebe5a87b401367aa3743c9dbaa29966b356c2091c212144c1dabd628d154655ed8af9d151eda", "6", .None}, + {.Gcd, "-28443d629daea3ec6a3bc189e5684d6ea8d4d20bcb3f1551f4ccdeeb1f97d8b69edf6bd2e2e965f40a22a74771f1dae3dfac4b71543bdda22d80f1456738b47db6f9c3a29a106f2d11ee9f676ccb8d549766b36570f575e18c1b7518afb8fbb6690b3f81dc93e390df9630de881d05986a3d035720ecb2e04e452273192d0b15782cda068676bb7c8176691646dd31a60a6f0e51b133", "d19a673b82b510adfaaaf211763f53336e1d69c32fc50ae49710961b8f2ec10ecad408dccfd11417a88971226fa67511a5f9410bc1f4ee3060d8b50f472127cb0f955e1e8c918bc4cdbbe8140d51f42e4e2ec26db8c477b934eab238b00d6927bd5b1b30d87b4cc30f11fe4d364ee063667d613dc9fd4b328ee34179dc63235ced7af70d3991d413e49689dec606f80e3a07c5d380a", "69", .None}, + {.Gcd, "-20e3ad61e323e97d467a55539d9e2e645b60586a94f1da49a9a2104a1564d0b48efd033bc2069b32b17d178e1179efdc674806b3d69a89b28ce592536a4cc082d9ca6e3f22ef457006867e53c14b52a4dc894e5681d09cb43362768f13d8eda4be0b78027919bae9d7d7633f6fed97eb71ccb002570aafcb51350acd01ce481eaf144ba9e14cf131623d10903be6a191c60a978cb899", "b07814d1ffd8f1b9ecd39befa34646cd8bc26023c01f5c6a53dbdb4d3fe56f64d1bf3ae7991e83c90cce635fb29398206fa5fb3480830a19ddce7afaa919c15e09eb4aeb82e4a86ac0692715dd1a927ee3855d2fb3628699b3f122e202f11e36562ecb7061b870dfaae9d9501788005d6de01e34682bf44e0f4b5d1b76c2c5a3350b2abc2b9cbcfdc4c00769d1016b7a042b79da90ca", "1", .None}, + {.Gcd, "-c3355ac049b7350d0617d708de886bca77cf8dcc4c2d449892703e42cf9a4dc7e9551fd5102c637e74112883cd0ceaff77fd5541d29087cf0c91fb39f8335d5f87d5a9a2062a000eea83f96dbb92531c03031085133c20d05c8d3b211d732f345b2907bae9c17edc80e33bbacf7a96b17e65ea1799bcf5559cc9c186e276273868ecb1663bb8bae9c986e1939aa6ea417f311d43fdcc", "b911bedc8b70626be09cd15f3e3cc839dfda24ecc1b8b99c614b7730d3a22f548ccdb4689bbb447306d9de62043355883df8b100a696b90522e8f82a42f530641ed52fe9092234c82048c56361ed00e55f67155c237bacbd6cd6cb66bfdbb7f0cffe43e094a24e9f42968608f2ceeb2a5623e20a4be901ff192f8e0f644dc19d94e646042cdd95045bab95a1e20ca058fcae99f25642", "6", .None}, + {.Gcd, "94d4299123de45d074aa5a894b8705ab5a2e0feba2f080eac29399bcbb38da712f30d4f7113b0a7a6730e898b462288159b3533d7c233b6127b5f1c0781c8487ea184b587275378f84004ec687ea91e35812c77270b6679d12197c82626ea35cc02c74108cdde8a7e6c405d9e027a9a880c4c874df34555ccf61485bcdbdbdfe8de71bba4cc84e4db6649fd4468cd8011be34a26a997", "bb963d80016eeb3eb62283deb55e58b63eb7a1b22c83e30c58c70da0750b65fb2258a2c5cd27a74bf839fb4f6fe8a54570501ef76c2aaa7617c89f1466b9e00ed57d5895c0d64df870c4642a36f7395edfa9e8d41133072cb138e408f211ac5979119afd3cd3010b562ba258d9fa5b44e7deda0038d8e898a5d72d07866c4e0c1ce51581af8ecfc61aeadf1dd372a543b46655499452", "1", .None}, + {.Gcd, "44813f0a07384409988b54aad7512c4c345334da5c111f3f92fbe3b2c9f236371ccf41b0862e4fd40d03535b4a48ef932fcf1c30cdc3ad9a1f8530258cf4b552820262639230909d2be6734dd24fd00031168a862945c8a3da0dc7416e6f3a8a2ea7b293a65ea962ea64e58e705b7444c2805aed227553ab10190557deee8818677c456c7aa73d16a4a27fed6929a90b35aedc83466b", "520323b29ba68689ba93ca05e1b6a346e6dea49e42d29d31090a53a4b63eea044d69c8517e23d5ff36b2af50f35ba36a88cfd4f78b6ae19c9f5972e98ff327ccf7907add94ba3ed6831ad474e78216d1c64463b4a1bdc6ec3f1f42aae17f210bc72e8d402c029d8ddea3b8ef8fa801152865dcba0df97d86f29387596f407c836d84544906937c8946cb63352b5151645b5e89d0168e", "1", .None}, + {.Gcd, "9461495e5708a82f803d20a7e9b7f850a6c08f913a2357b6f460f53f055847eb8787e3a23dda36dd15ec86099373e2a60df8b6751cd17114730b660ab8f9613545f92de920305a0123c719c2fe0bb405a58b94ef2c611c6992925ad40963aafb0f17b12f47dafb75a35cf0b4ee3275f058c83906be91925caacb4af52db98b31183a3e8ab4478d9583ceb44b519cc04dfc6cd02b6e93", "8bdf6e7b2b92f74830dcc3fe7298bf54607c67ef03d07fdbed225e8645fedb5c3f53cb088d2e1ef9bf03d35ce5c3ca955b332f1cec681874519e251cd4c09462009df48a55bc3ad152828581756a2d38ebb0b39f487892d630fd35a7ea910bc7c2babb6ea6a51f5feca1329ce1a11b39e0a895045f43b416209b5ad6d953af2059a4be979ff61d0e73285f222b0411e49e3c8810a5ae", "1", .None}, + {.Gcd, "-86910d0ce0cb64a90223b78153bafb559a10bd0317b03ba733e0d04b3ec1b3139461c24461f26a92f6aa9c7960d6c0300074a4cae8c9c57585dcb6320d34e80fa902c84c2a40ad5fcc2b2b9b33eecebe175577a86347b16ddd0ebd2f82fba501177ff7c72b54ade293d69bbc74ee850f7789b316f9a6bd932d64ee3c9521958ec159c8db9986b8c34038cd324b37c64caf494703345e", "a6fd3be8a1efe25248ecfd03ad83d52a283700f57c491f49093b48af0acfa9a9d9492c9b49bd7f9f63af586c26b89236de04d9264f68e7510df04adf96e56b83880733531f9d303008156bc33cb43b892570ff23ad1426491c52b7280fce0829f4594d3b59b33b53844a15eb40ed62a76cf18df913b37522a83c85992de237a02271172f7264509dc70c04bc4c1e13e6a0aeccc1c232", "2", .None}, + {.Gcd, "f70e3a10d99f547d0e531597c85fd6ad3efcd19c4e0e58d52dad789ae898b9adc063748174311817e62769d5a9e8c7184954acad681f90b15a4efb4466bdf7c3bb25c11fa1a947bdd3ed0aa5ede302ddc18dbad1e0b578466a2fe8fb4aee18b174b4c64e72211e6832d6f8ec0dba14bf29a41cc642e39ff3c2b4f7b7585985d24b66d84bd13fcd68b2e7fd63a1552aadfe3fc4b2153a", "431308e643369245c23caa98cf853ce624d70bf282fcf14d148e2f745c10103661fc0aae75d37305a9638ad5803b312612073112b3e66cb5a3f7ea831c0fd6bc0b950517f2bf21ea01d20e2afc63ac35988ba49fc36b9c63e5f06d6e8e0338e97aafb88471c6e0c0bf87b8c2c510ea2c15798bb4e7cd727e4d57e9d96ecb8a3312b090b005f936d70b828a3cf9cd32d68b6c27104901", "1", .None}, + {.Gcd, "28a0ba1c6b9312e41b560eabce12eccd1fc245a4757a61d56c09362cbeaf9c15281b8b5dc220f2c705e05166f52e183816dc132af2a4623e6c61e9da9cdbcdcfa5d4f4e716689bbaa95860cabfcae4cc09f89e26fdde10f8457cf84717bce38fa26f248e408263e948f5d03b2c22fae2757622e7d3581109042a36231aa0ba8bd24cf35d37b7011968522043ef6f67ab8a53cd668132", "79e3232d22a8245c6954a98ad2db1a45f09d181b9862f62f31a7a9f0c789edc3839d3a8022f0a2f6732b44d9a18c75125894b76165bec4cad4a1f83b07d5c5971fb998bdecde03fc7e2f6d6446d1416a96dc5715c10d9c92d2aa4719c418822a91f742fe26b53f1c6c23de0c8f27e390018f468b59bfdb3ff9381b06f3d16ea1ca15d62064c11d4a03c34b48f431b6d224a80a1b550a", "12", .None}, + {.Gcd, "ca782e2a42d712828eaad39faa2a1c688eb0f172e3d713d6459596cbd850b0967432c9d2ac024012440cfc220d675c6cb982eae50c5eb712dcf531a3f7603bf65e6269093ff607cc440d5bbdc8021947d68173ec9a64aa6418fb95aa77ed9ff7d5b994aa5d713758cd5b38fc1d650627bf8264d4d1cd3979e9608daa6539570f8af5670466e8a7e60ab59ae89ffc432d012417255844", "a262d1f941814114c3c205cf92357275b34ffaf739f84480a6638933d480b86dd3ec81248204ec3d7a2887174fd5404e92eb94ddcecbca2b26835cfef516a9c4b4e85ef6bfa4f9db0690a345021d9d34301d5f6cf6b6e59a80e6695eb45dbc1af759019a5d3cbf726e7a35bb20a73248b8c8af1d339f44247698377c777a7c94ac7f5a77df76c8af64cbcad8d02c5005409cece4d0ad", "1", .None}, + {.Gcd, "4437b965190acee31edbe62452021d28ebeb45e5e18757a7d86b1bb7a55b74126c8e4f7d03cd9d11f46b04b0cbcb17ebbb5cb746c084db6a5654e3ccbe2f9d4ad6c9f6c95ca4e88585437ce282114928f7a87d83c5b39b78b7ca64020a11cbfe87fb13dd07c674e3bcc2b15a9f253a91bec405a120571a387b04e95a99701a13e55a43c5f4aafec585401bf08dfd0ef9ee28521b4332", "dc787203768020d421e549ade721926fbf303e280a1d966f8bddbe9b778767ccadf4e400c9830fec0989cbbf94608a9bb307566a346b3d4bf0feaf39c1787066ec6d9d0d537011d30b489afc0be65a3132a1dbee4e6a3025e5b831116940801efbfbd630c26205bcacd14966e640995642d82a2ac4ec579059635bb06479c4a55712b693ee8c960eb25b30fae6527b53910a2853db01", "1", .None}, + {.Gcd, "a4cf46fbfe586c0e5428ae8490a399384573e102ffd0c11f2fc6a421cdfb8f32b50115f0b6b04b888fbecf836e3bbea56ca166420c226c837ad56fd02de271172395b1fd9796ae7aa81682c9a1ddf9d3a371bf73a670d5c86af324f17a3f9fc4f3dd61edddea2b5d0f5ab95797b551693659ed1525bc2fe173be963b8796813838a848a739ff76d2e0f7ea44974d329b3d40bd371b51", "e14fd8321c7927eae750379de834ac0ebd3bbfb0749b94c987a96f09d3a41ea8bf1569cd73021276c436079f9537ca55f72d38b017f1dee26d1882e4cace615c60f51af64847e1ed74b15310813dffd86eb1897e3452f161eba75fce3fa19e8ac00c4dc24d08e2faeb8f2c2a0c5d1ec670c06048995880af892ef0585d1afb652a5940fa000a0f584fc348f1da890df4bc45896ee5c6", "1", .None}, + {.Gcd, "149480e02284e5aecc1a0f782bed06cf19cbd8e0ab09c8e1f407212af65432bc84a386fdea1cb43bc3bd217131978e350b40761b57719782040b51fc57671c6a13b020514f12db50e60730a9acd89344ac2b2b18d090a3279e180eedf929e83134a772a56fa58ebeabbd14d60f1430dcbdf05b2c8186812875a1f1c428ba0be0801f33470f237c43b67353ec99b7a7ea309a4e96775", "df631a9fa86c3a9752e8ce54d52c5decee7a1824ad33f41228580ca4c576678fa42c4e8b3d9b8df430b58b5e02dcdcc50a32752465c7d50675754add4e61aaef848ae595efbaad44320da8025af94d544498da0a01dd2dc57337a61100aed1fff804728c51b968464aa5c2fdf5d57c1b37a6e5ae3072d7ce45d8d03bff97d50d57c7e048ab15e03215a4bd9099d4252d63e6ec9b7c64", "1", .None}, + {.Gcd, "64487b494e4e359c07504955ae8783c936bcd64d7c93f2384b1951cf6e2b030b7025b861586c933fa066cddb5fa0efc68a58533511452da23aa3bf9c2b02703f3b22710f35c73d70874b1c898ad0114d6123ff7c289a3a410b0e85fa60f7b8d034105d51d8f9cc5b20040301a5d128c0ff85646190411dc79914ecce310dca6ce6b886ad293163706ea9a1eb19130f0f96c113eec4ce", "232084517d58b7a3f28effa0075797081bec9d5d7bc9e66e34df17e0fa207c01b9de440f9dd176e3e76515e90c431246372c5b7057ce4b387936e6d8e2e552eda10aa5c13b9c0e6555e380ba5de0724882c2f16845659a827cfa9fb10155524667c841f9a51eb7a3181847ee497d05a8034f9fc972776ebb0615b754dd4ab24611b6919c511c1f5ce1ef79ceebbb9891dc883448578d", "1", .None}, + {.Gcd, "3cd4eaa0141277c2f0ab86f9b76d08ab5336057296426f6d88e93e89772f683d2fd20e0faeb23a45f796b075048aa7415797f248e7de875df2a3c52283b62f386b12ae6ecf3ecd644c12a240db69f4c421fea4bd19c4ee86813458cc8becabd34d824b6baaf779db780fe16f1be999120ec0ef05ede72bc946f5a91674e39b3618f753b6e3e6cf842641ebb9350358090e38fad3a980", "82b2c5cbea29ae53b96ce2a0a462a92c0448c0a55764497364845b1478f728c9f543e41250c42c78b4f0233af7cb51b6be76baa95aefaea3afd621d4d64fcf724c40286715e86faed95476599def71d588a18f94ae29fbddb40f3579216ea0e1a22500d498ad8ae3da4f9c2199780b56fc86fe8ec5095d5e2777bfeafc2a276c5b5b0e488b5023f1d37064ca83760f5c04f76ba7206a", "2", .None}, + {.Gcd, "a8e5dfc6f3e736be0d90100dba6d75a1f33f325f8848d7ab2d68e66a3339b5060e2f6c3df034b67b435de4c9f4d4e343b0f910c85788d6f622851546c0c91a4dd0ed4e7e395be6868dcd85c27426db9caf7a3665a53888e271a000fdc8bcd58ddf9ce92b55104f1821d55eda1f4bc2a0ecef12803aba12dc730e692de3d517aa1527fc7ebd0a951559e406a20c2f2a901812cca2c4cd", "d049fad33a5de3fa9695b23ad87bec22711da49e45f6a4694dafbc0ccaca7d49aa9ab74f8fe36cbeaa27f04a854c40ff48d444ff869750664c7790c9da3ec141e4a2a6a592fe31c1d6ea40fadce697d77aba435500bd381c9ea2e7067ed409ca9d45add3b60a8018f24c57cb4418e24cfd76129109668fd4a299fc19606966f7a21fd876bf1e73dfc9b390863dd67d9fb3961060cf37", "1", .None}, + {.Gcd, "bf2578d2a9c35116fe6a2bfc838c20f282ee9e290b33261fc8f234725a3a4780f0631fe0149bad4d2c323d051b71d884ca839fb7f56a08f5e1cc81dd2161a21edd54c80df972d29ba2915cd43248382f442cc6b8161d670462d494a38fd04a34f0d8c7a0f54500db8bb85e6ece865a75b1bbf946a2ac1dc63a894d16c4d12ee73821551d2d9fc60f633953cd0489d690378882468e72", "b0bb2e20682d55d10c82e06e7efc96f8479b3828e053ca798a0036deb1b4169139d67889a53d98bf9e87c2fe252dc8332a2875c22130369f196439f9795a0585bd7724c6eb0b0b1be88fb4395a7cf3541a22edcf7efb3bf47e263f277aa801bebb2776fbf446158e1af8f2b5e3ee3b6be4e23b872c95353ac4fc5a1da0254c74c38bdbe7167fd9f38c937b4bfd7f5849da30053fe73f", "7", .None}, + {.Gcd, "-662132bb018df2007ee1620c7f3df2045a92a1b8a564ca39fde90d0aa75670f821bef9d91de6efe1b3423716aec9adbf2ecd2080a6274120b263a4ac91b78f8e258673cbb95aada35483691138f412643a2108e204d4b89550eb671b3e6abef2110d625fe534fd457e5f9df1abedab92496502b18d0f31d53d35f864cab9ae417ba34fa327d0e377a16dcc56046fac68ead9aade3af9", "f56c4fb6a7af7d72e538bef7418f6d5f2081d3991928bb67bd6d42e0cdb247d7f9cc8db0687f242308846e6036b92ed0e1d3fd124568862f5b6825be950d66d9536c9bb3f151581a130f5c28a2f40dd3bfb76f7f2618de0b2dd63354d91acb389a12a0c6a9a3521c4fcf4adab028a1e647fb72a526e581f6e10ad32a01fa6c6aac45bffd9cdd8166b98303de33be0ed4c0357d66fed4", "7", .None}, + {.Gcd, "-4a2e6400f62075fd351cff30ebf58b7bb80d22d74a43b61ff451030ed902373eed72120313d7e636baadffa0bace3344449c4d265f1bc7451dd37fee71f5b8095b98f824f9096884f2f8e4667b44cc75351fba0ae46766650c482189429aecb42c79af8469389dcd10135730498165733f3e336615ceffa09add63c36efee942faaf22f330f56f853dc026d907fb44317251d69a96df", "2f5a64debdd829f0e1b9e2712fb6c94841a56bc29e2ea402ddc0a5c688c43aa40b07536a18458075e9ff48e08714459b6446d422601228f37b2a387b6e817ebdad5a5f30bca860ac60ad1a945adbd3e49a9c3bcbc1df8ac39e174af676487a47d25287be98eaadb22ae68f8a15bf090cbc0a7a79f7521a68bb2ebc239304770f30e2c7291e1168a45838f8c4b2c545159d6e1a2d396", "1", .None}, + {.Gcd, "-1ad752ec95c86ce1847d7d5efb362842d55b01e8b83f4e6eda06403d616eadc4a5e3edaa8a61557a5b526ac8a1388be61c29853cba2003fb092e28218280c74531b9e4bd01db8cf7c05ec5c71b91a777c2c6a94c523bfee5a4a8ea9265759ea49e2c1e2e05cbd31db0ba638e66602f29307440adcd42060856038292bc21743711f0a639de4a2ce69c7873f2f92710f26b0cd7c16d46", "83f484582d808a716cb6ad09eb3616b7c9fc866cff964773309e651044160aef3a59a828768c86dd8bebe86e481451a7904b985d67c59f933c350ac4a5fad05aa4b003372f36e3a816cfec9b51bfdd5dcc2725ee72dce679d378d14a08fe761922d5b4e8cd464ff0ff467a2e13eac466c3be5fb8d3f6dd34f53f971691779f40225f1e48aa04babd818ebb63a0d706b4f2da179f87d9", "1", .None}, + {.Gcd, "54d58cb61d64c13d101be2beb8d128c8a38df8e87e7ae72b670803ec7cdef0947e37106fa8088e61776fe74e7cbc0f93ce20abf3fb66f44e35b4d14666c2dc0470e593e2ed118c4555c60aefb46b5112f54b8381f6eeee32ee5175613e0a41d565b7adcef3758c4788b31e4312a63f31a45965d88a8d4cffcc8bf052bff885dccc32eece7c98b61ff51ac14c775f55061202dc92a2e5", "88d6c2bc186c96baa73c932fc2126e1b72db4921644dc7600b619f9adf082c78fbdc3865536dbcde16eccf82e71bde968371e94d202c5a22ec155a510b1ecc17107629f80873cb5cab002d17a08bb0c56a0f1ccfa594d79feb96cd7ec425b249cd7fe05069c820d41d5e93477a11e85d949ba827decdb810b7c5a8d62691fced4fbb03f2ea4e7d54fd06b720a508c9cd902f400eb31e", "1", .None}, + {.Gcd, "-38e584d52447f6cfd6b31f520974a52837dcbb9f70de88119cf9e5cbe2b8f495a3a74cc6502a8516b2f041bfe17fdae50cb3b6b4a8aa7db5a6ff708c22e8a1fb9cbc0ebcffd68dc35389de66dfcaf1233663477fc58b1fd5a0b5d2d93668a675803f11fa2b43e117a19a10cd9f509304e1e8514b236114d5b88d24b163ff2d6ed0f1a44eebb5a895ef58b1e74d4203816c651254a797", "770f8e7204634841ebd6e4f069de66463859f52027d0d6d1410a29624b0ba85721bfd8e8a2d9a52dc7d3288f318e3d3b2c0cbf1a900fa874af6eae250588dcc3f10dc056967c66ec6e97543399b299b1b9f0f71051c7e84134e45eeb58ec91989514738132ee70bdcc72a768b26db15e398cc20801e85809c99c5e0dfb5894cbe39e78c3bd462fbfcab847b4409866de65c4543aecc1", "1", .None}, + {.Gcd, "-e8df61c12115a1cdf860d6195c9515d115bcf532ab9201c48afb3b62088da6d3ee5f179da588372556a92dc933703ca787e4beab4b4abf7a1a3e1e03f4f6822c3556e6e2363c545d2ce051c19a6e2ec59c80052b4496f9f3d9e56e16f125dab62567c738066b7eeee66dcc95cbb608393b9734a3275d679375e005d248e6a1e9a97f8eb532fc5f92a39e5c4ae0657252055caf5f7552", "dfb5fe60cb769a0992c0c3c1309b607bcb4096af05f1e22b0964bca91c84f9268e814719094daf735cc441d3d1d398e2069b0b39496ce81423f45dbd559b11dda52172600e52c7982f860947cbab714e02b58dddbe7c76d864157d9312627c00f7b9ced748039676aaf829f53a098d84f5e1bb5648e1fc020f63ff2898286de8b507b8557401e1e9e646b8b35f1dff06f8eb0f408e60", "2", .None}, + {.Gcd, "-6772861f5769c2bc8c22e76d2f0b8694a62e521ef8299b6bd2230dbbb539fcb95bbaca62bb9aa9996399bc2f9d96cf0adc9bd3b13105295c1266eee6a25ce5e3aa919a7cd2302c82864fccd5337491cccc768d4c51682e9568e39b7d7e86e1882417f0ea2edfe539b6c520a9c8c962fbaf3ffb31c4d1fb720fd8234e01a9f069346a9edcbd94bbc0676861f8d229973b4d9925f29191", "16cdbd2766d56ec89869371bfdb8d65b951418e84df8c6e20ec8e4ae6b655e68a5927809f29bc93cb01a9e7829a94b888634db0ffcb49990afd67527566434dc0e6ac8ef7638b3564385d7b054723ba82e0485fa689aff57a6d606fb4387639077a06efddab2e72584eaeea6f140e78df8197b72ef9d0c672e2c0f39fb8ef71c831126426a705d7a903f2ca171e9ece2927758b7bf2b", "1", .None}, + {.Gcd, "f2d3b137c7d977b90eb113b57013acf4c0abf0e73183ecbdaebdc9be6876f2c075e1b312654a9933b14ece1724e92ae739ccc251081c9a0c607a8ddb452cc07e50e738e4333c97c34ef771feac27c64130ace9b47b6b52e7ba42e34d731f74b1fa6ed7a7c6e363533911e5979f61d2f95629c81fedafb0cd8f4a677814b532b1986899fe265e9805dfe8a9c0f65011979fa8bf9c3bec", "ad707dd4b9320b9863730a1b3a7b93b2d2ece324cbce6ff0e6edcc4ec2f709bc5396984f6ecc21bc3f11d61f4da657c35d02e6013b6ca44e2f60c2da4bdc38dc2301d7b123dcac128502a970697fd795b6b3349f38d8b6999e16fb8668331af94880a1e336ba873d37c5e45b95fe3e9c374caf06cc934de3cff36433e140148001bcad76aa291080adc9e39af4294e72a5cc2e42c7e4", "4", .None}, + {.Gcd, "6423e74c8dea39a6429babeab5954c9cdff91d27fd995e51c38889ed46aee1a2ff09e0e60f80b08cf400836a1ac4180aff499f77f33a0a06d159d6b6d48353f0b861c68240f41eabb74a8478978f53e105f8fbe61365696da2b659929698bed6fefe1309b2bbdcebdb5de9cd6da936dadf4cd88caebd1fab74291f4c50a6c8f7fb2781b2607168573e6283af69fbce64e1116c2a8010", "d72fffa7784cd7eac7178ada08ce970c4cf3a84e1323bbe980809a5b682f219396261b9053026b419419332e2d124fc55576e1e2bc3513d6bbb7fd8b762647d54bc1e5b9b9c935c52a50f01a2a89930fa55aa8d90084adf953fea17174a6a4cbeec4aa6a2a6a21d0e06eb6a7af4ca0bdb63f72c5bea337c2a08b29ede240dd2c8d41a0b6d45fc9d67650a049392df395d80b966fc773", "1", .None}, + {.Gcd, "20055d0f11850c76a7ad442ce5513ebcfb21fdeddad4eec0fad9fbc16dd61b1ed277d33df6b74a660b77ec78e08b257fcabddbd0f59bf86258957931a5b51b4add9e9adfcefbd996e0ef3119b4e43d6e7541cacb8b2c4e482a7e2b129fc31aada67b0a29399ae9c747b8cb65d434427a8e25c1d0dd8377843d87e85f6ab93d6489f5cdf931b1d551d2cd5a047d9311beb0eb423f9985", "755375b3b1f933348f9558dafc558ba1905958be22de0345b39c2099126a98bddd41522bf12638a8684fc09b7c53296ee22539fd5955ad06f2b6e36e4f37349c9e34200db88833a490eb68281150ca6197c7643013de3afe84ccb38c9d7f61028af35470caa04795f8c940c6ff9d0a061353446c17de89259af143458a6c751d217a1c3798240d39d750bd44d54ecc8102eec730a4f8", "1", .None}, + {.Gcd, "-9a24104bf2387a0305ddb3d856078e6cbe18491d3a4e1c811c2aa74da96ec7be4e6508d75208679fb0c6da2372fdb8fecceb92cc065084253ae0479f1d1f7fa962a6f268d0d64fae8e7edaaded6b6e835cfa831132e8230e418e26d1b7345333bb55ea1b8ad6a44b81567ed33fa2aaed87d86e0423467ccb61a03294da8cf31b0bf86ca751821030719d3c628eb5a94acb9ce7a36a34", "a2d847b987ac6e40780ef84e4570d17973f21f6d1da3297ff3bd890a00a53bff31529eeff6339ea131b0d9795bb1950494cf54b67afa7150740ad8e32499b296a5004a266edc050e74381093339be23cfb4bdd070aeb6ea79960b42f0f200bbb49839935b092b15695e0e2b4a6bfd56e84cc95848996aa6f55d551e505203f5615a269cf5460f24b7eb0bce5fbb8e9a55d67cc147f3", "1", .None}, + {.Gcd, "-3a67680518dd329ee2def0b0bb9964b59f4cfb1b51011e8f98917407cdd90c1c1f1e4fbd0ee462e6c6b174f5c2ee66f559734f6d9ee8e5f5bfce688afde414c88de9faa9d6a7633a2c535636621cc5153e6de22932e70d89fa79e43a102b4c7509564e85845c6af1b89d321a1c05edf9b82648b2bd694ed0de22e55bd787aea7c4aaf38e9a9453b7b598861e1cbcbd29184045abf5c3", "15ed2f5b1eef7a8f168008b088855f942900a47e9472109ba934ca14d4aa3f78a30faee30b29d937d8a493bca98d93bd6ce6d466d7eeba03a5f0b10a883c5282cdd4e1464b19619e1f031f4a86e6b4659979142024d1d87b3ddd912fe4089e01a7345ccfe5e59b62fcab6ba55f0c0797a4cda6264d9acccc61c36cb65ac8fa5c071118172c422689668f5d19a61bed38b285013081fa", "5", .None}, + {.Gcd, "8c970403f46d3db44be296373f6041c8ef2b53d187ff22c7d0957422e4e9ff5528ae930555bddf55609a1595d0edd2841cf9757121b86498ed442a95b9473ee226d2e71a3ce59581cbbdd329f744d116357e53827d8fb59052d4dd930f245ff3a7a0cc3fdfff707c5034aa544320a959a4024b6ecf9ea165f3fdca58e89a92b86288fd84a501aa19672362188ecda827e001a9c2d4", "b7a52ed03ca6378b5e762840b9456536f77ce18f3e8a8dbf6f0651f60e1c654bf3431401584432357245bcee26a9317b08a901e27073e53d37a7b98c00ce99b53d214d8feef55f13e08de8254628b8c2273c3585e482f9c86ec58b06f1552f0e008ac69224fb07c7bbd520877e0109bec7a086ca6c59642055b62abe70bd37a4173ef812b8b97a1fde9fce892843d0d6cd686ae63b7a", "2", .None}, + {.Gcd, "6e7eb1b6930538d44df3bb06728596bce5f56f6381e4897b2a7b670433140c25b8977ead36e321737e5fc2469a1cffb24ebb9f6d7c3faae8d142d7e2aa7fd1cff7f33578b57bae39f3e11bc4f787860a8eec720a388083ea9ca315cc0b23d7e6e4b49454090d60ea6924a1671e62611ecdeadd2959f9cc3138394eea6e8a3b3108be06766cb78ae79f84b22f381ab850bb543027ea71", "336d1ed5d79b4b00b3d09c1281478cd6c6a8b74e2022762c8dd6b428f57c1b2316fc157deb5f2e5e242578a420271c315a6a3ed9174ffad71999cbb67ca1be855641cb275766c1ad3a303f55955a9bce9230f1f1cafc0c83f35554b5d514866e27ec5cf1492464bca1eb8c03c3d60167c4805023e0415c4dafb4c1a5e0782461173c853b10539ec6a0410eebe947325eb7284af278e8", "1", .None}, + {.Gcd, "38358d84d5dfc2ad33028e1d841bc4978f3534e6fe024c8fe33d23538f3ccc618d8a0348ef0a2db3fb5be6e01b3b8bdf3a3a4c5761864246a3dd3c07c632780af0b23c55ea0b886544c5b0a4164b97ab8e95020bf5269629f315c75fc9c73a55a2cda5c83d928a617775b56a4e43fde67a3feef1dd8356830015ed1295b408f8d12b45c1be73491983848ae0603d7693baf9e5a11004", "d7b1ccd6176c4d5066d004ca88f49dd309d6f5af8d06d35a2a36d5127248a0316613310d8a6836b079e68d6c89bdfc0f4ff8678792ff066f67fcbcf3b966864e54d2899f69e728ada3fd6f1ee2108c4fab47c0c5df0f18461a4cb8ecbf76448e2427f5091fd5bcbf34349398f45964e6433b04abc7406a63cb53b9f00a2f9a1f2915cee1f0091de9440b840a279c47381f22a4d2807e", "2", .None}, + {.Gcd, "-5affdd6bc1c60087fa59d941f9bb4a022dc85e66ddd49403528d8ff756ca174b11b0f508905ca90cb70ee422c613ec5935885c2130238b8be87a7a0b3e8b2c3498916d424f5bc7b632197ffa1cd6cd0c03b316987960553d68fbac1b80f6aab2254d05df7bcbe84441d92f86fb0a9d0cfaae06e3c977046033440139c89eaa9b45a2d151bf68178c24c470279722e3bcba44592023d1", "47136ee9582c66053fff488180ceded19c61bcc2df7ecf45d735301f89b785cdb1f9a8a4d8bfe3858dcbf7280e0fe010b5b6e64b423e5fe6fc554d61c65dabf48db30e9a13bb9cdd9f953b9352f560942d4eb95f97a1e8451cc9b46049e145f76510e7f2aa0cee4d8a1cc57f1ef2db6df1d0777bc831fe902daeb789a8087a01d9acb384457d4da6009e156fad30101f3f298f9c6b64", "1", .None}, + {.Gcd, "c0e62185123055fd5d8597d68c0a0a57784420188f3143ffa8aab8527a09ce49bc4d31f9720f6beac8ed843a6dccb81fe223caf12c1a98a47bd41e530005937608b86b6443b3055c923adae9b4a0da81538497b69bd344230ba0e1704455f151db552d3da04ab14f031c69d29660f42bc892cdb606381c70089162c80adabbe79d0bbfea0e6ed1cb82e1f40cbda00a991daaeddd7304", "6d52a59d09cb9ba04c2083e581c509e4f3dfa90a4900fca25e07f78a8f866163792e08886dea4546ab171b7afffe0e2f47e2997b8ce69f16f1336373fe31fbde6046bb2beee3c57eb86b788de042d15cd4a58e2da4349764497dae6d8a3ff0d72be6d27639b1d46b083fc25e9a1b58c9419543a3dda590b500a72a98e4d8562467e0a05ceda1d13799a08d203b2fe65ff883671852d5", "1", .None}, + {.Gcd, "-91d550a9f870e1624212e77564d0bc21b68568d97b992c2a5ebcd5d4f205d54db266f4ec6b025b2abab73522b71975aa2675d5f61acf2a73baeae05c4d302b47bfd87d556c893c72e8633af03b46afa5e7fb3de165b520ee993967fce7e5aa01d63afac9eee3b5b790ef754ea599f1dfb2066531d1a82b071ba2cf6de5426e3bc69cd6a32397d8367b9b80553364db60fae53f5607f8", "f347d00e7bb247f8f4923ba1c54bec2a665457643555e417e0589781aae853cd9f71aea5115dee69c0d9fcc76c3a13eb9845fa865749c2d661b82f60b042edd7fb71422fad73d6d88d4ea1867cad51e2199f6afbc43a2cae88b135efd231c75c0c490519410b631dc81195fd41f7051ec8774b10b193370c3dc36639106c6052baf93e02ee9580a0f583bace587be5f31ab71d510114", "4", .None}, + {.Gcd, "-f02e3e358e5aa318fb104343f660954fd1cab7dc70022026530cec4b8837f297676443f9287bd3eb129d206d0982e0e9d7976870f6b58884cd7dc5016d186f168bc379debdfc270ac7c922aa768627c9a414c8e382f69402d1019a31c18c530bccb4b6808ad869e02a034a33c596f3bfb01aed5f571ffa2194ea2d5098f8e904d244663bee39eed1943162cdf198aaee6c8c9d9e61aa", "88cfe99f2cf0bb80f16581cfc5234f5b85a4eba225863af97cdf8df1e59efc76a76e1f69dae62f1e6c709b376009d7a54125783e04b70c45ca01c48eda3224272ab8035bb206013cdb5aa048cad0b81cf2561d4bc9ca2d37294bafd961f2ebe64dfa3c4cbec1d3c92c796409044ef1b2feab17155e624e6505f10e745657e1b3ccb7dbc1bb35a5115005bd03fa89aa74bbeea50c3096", "2", .None}, + {.Gcd, "-ec9239c0736e61a2716253f532637ca4861388f17e48a7a60460482242ab136812bd6fb6cc01f34d4b3151a1a7f264a5f24a9aeebe835762c920d2a8eb68be31b5ce49ec70afa8cdd0eb7da199d1efbd6c70b76bc4d765605107ea2aa5758db2c2bd8e82fadbfc90d5f09677d9664f1d381a7984a88eedabbe8c546a929c7aa98a26d8b4844ca2897c557bfc407096d47a51432118c8", "c909512355760ed590dd5450ce8897f56cb15841c2684da4ad77ec00881beffdf63b273348dac66a64b3ade4bc998baf64696e3076083b4fdff86d92fc7aacc33452d2848a45e9e7029f24e783ef62b6d871bbfa6c1c32aa973ec269d3b34adab8d1b28873689fa643dbe780a1f0bac2d23d0cf8262a35cdc0f1a19392c4f2c35fcb8af1e5a25fe42f712068aaabb4ddbfaf0e7d2726", "52", .None}, + {.Gcd, "-26b016a38d60395c7498d811f0958b55b45763df2ec6ca9ba7388c2ba3cb7f17dcc2bbc2a0d0d734da8428c75893aac7cd5e3f1df70feba2ad13d4e2262b617d18e643fb7c94d25fc16c052805019226c3b8cf7b310d3ed4df9413621b0b4d4cb9a8940f512a0a2cdfdc5e289143ab3788d08075f89dfc8aa2ada7382470fd5ec5fc337585c895e1fd866f7c586c45a85369b6cab2", "6f5c264766fec73698f1ddac334127522a1e1cbfd44c60f33fc7e3432257b7bdc89dd2781ae12517c77f6180ef61c845fa44bab11828be792becb1648289369464062b3fb5aa2bed575f022296f3b568847ad3e72c28719a23d24f30ea892c81385a598068aea4ad76c77b613a2c87da411fd7a40d28f750177f09f735f7c4c5a10ba8a62bcdcabd80a8a52f93b988c9569b1fc12719", "1", .None}, + {.Gcd, "-24e5c071d53c0bbbf86074df83fbeb64994dd8fc2f84ac86dc1587d8109174b94863962e09152d2b0adcb2452cdecfa9ce6d8c658d0cf3cc21d785fef5138d80ce42a9e12659d72c5f0cda0e9de0f06153df4548f95ceedf591fc439b5fc694260d087f3898a70d0b3a40fd302e6cfb94d54fa218d18664ec65b67951307283e25005eec695e37407c50ce3bb0f2486ace0a508091f4", "a217def39c23488d06208f63303aa22c8c1203e8b828ae5a87eb97c1e32b49b21134a9d3aed896a6ec03ad4b9fe7178f12585eb00a8599c93f99fa78b8c974351e6be2751ef9473b5c9f373a25fb4ba462448498381319acbeebbd19f539dcecfd42d6f974f5e7c02267cef95ede13a14684eb320506dd669f3883e39a8077e17484efb3aaf81bbeff21dfd3d85bdc65553993819878", "4", .None}, + {.Gcd, "-77b5d609c5a2e531ded5fed6fa58d0dc452df9c529bfd00418f0b6d62d9b15adb4388eb8354f94105eda351aaa47a259cd682a35e6b6c69ae3b390657beb0a8409d3c5edb8350a645c306d4395102fb787bacd2a9efcfe660bdfddcf3531440074fbff406536cedfcfdf168c880acd58c5c2ee663c69b4ba42376303eb3a3fde4feb08b34a6a5bbd0e19cb06b09df4150b3a652cd9c4", "249fff44e785b8beaa064e76109971ef4303d2b6791147eddace2de282273f1e52f50a45fbe1141afa74c66c8775a06fe7b37e1a44e59782fb9c7875a5124dedd077a12bfdc59131deac2d96569f8c81f76febb82dbcb8e9c06943c48f675658dd64f17c7dd23834106c93a7529540c845a9d534e76b3003a10ac5d15e1dfd9748d36d240b82bb0bed3692cd252ec70da750a9b5d86f", "1", .None}, + {.Gcd, "-ae3d6da3796ff86efa1895c85fce9c805c78044dd4d1365f80c4d9a872717c3bc8b5ca3b9973dc13cbfcdeafd08c301820ab54cddfd2c2239d2aeb0085f40645164c29d0b1c697e73ce4237687b76462dfa6ec15b6a44f8b4a1ef388b0d77b763880eb8c1d5da9791ec8fe14580700a4e27a8ced53a0e05024af6ad033d2640fdb046662bc15c1fedcc49a9be2c0347308458101dd74", "b296e134857f88b94b1115c58f9ca3257e7907f2ee60dba976dcf09a33bb3c08bc510b2146d765fd94f72aec23f1889c982eef506f360e70a26079ed32a0261b93dafa19296464cacc62749c022330dd415af83f0e7ec0cec27d4b398b8f41e24a63d294d57610dd7d19519438a5e7a22418f254f2ffca32058afb172bd01adc00a7872e96d1fa9535634862d54a965de62d3cecc68", "4", .None}, + {.Gcd, "-df6e99c23ec21047f1f7096c2186bdec94afdbe5994863124b4537862212df1b631725e2701d4138cdca6fb37e230e110a2ce882a19240cb31c45d6c33a980eedf776fb56f0911b06a294c9f4c1620d5f4f036db059bd5dc9f9338a74c29723617cd00dbba0869c14a93f6848e99ea8e494679b12f3aca16cfc144636bb0fc1f5bbab6a7c95fc2cb1bf50f638733260717e7447fa771", "69fe9cd5385605942d4e638b1d9c214ddaa6785bc7488ccb31888d37b585c620a2bee3fae06106568a1db7c6cd0cf16a21edfba538af027bab79737f6873f65a909133e3a7f51803d0ea4d46810cd3a126d0a6625e29661971a55df642ee72eed75566eb327510cc395706420379ded0a69a134400159bc9eafed65937948a5ebc084c11721d915a3c3848b2f0370416914028453ed", "1", .None}, + {.Gcd, "-e6960172ebbac0a9f7fffbdab3d230b2d91104eef3d04210e36ac2c33957dcd4785347f41a35ff20d052b885e1fe420b4b2adfa123beb48ee85f19772b3dd663156a7c3a90c51a1dce59554d871209eeefcfe74c1ee2429fa35028fb85128fb39ac7a5c64490999ee60e47159f01c1a3d04946817c714aded6cc2b1464e54a1d0e0b59ed86b5098bd5715c48fabdf4f90fab11de52f5", "6506ba04035bb0b4c0d627d0db7b365e17f497d5c5270d2150ffb68f7344cc6975b7aa27fdbcd8ab14e6c6abf480ef6e2ae41768a506275727543fd8f508278cd97a36518bac5d5bb5fe48195290ac764c0f947c2553c9bf0e8c213019d37a5d653d7de67a7a6dac4abf7f9a5b65dd4e7ab351efbfc602539ae7f4ec30c8d919059cd594d5394a5178c9e14acfbe8f570df53f4e1193", "1", .None}, + {.Gcd, "-42759fc85224f2c0888bdfbff5009a6fa497cfbbf23f8bb310d075703666394880bfbc8ab81ba231a172a9625a0ec8678e8702235f8540f7be6b17fae8b5c514fa0a34e6a6664c4b6a4ee6e34e462d70b54d99e1b0a475983d98e2b917662a3cf9e2783a8112d312fe278a2de024ec05900ad73c079b6a649c3dabca57abe88553ad364206cfd06c31f0afcad66e186b980ca8d14507", "74cd487ebb25ae8bfd06d634729df459c968e131a02b87fd6d78e2fe46f1c19c4f14ab61d1959d2f95a449110b0b412b80c963b63188e3915f8b94f784c96ed943a948819338adc06fd45d45aa6ea92aa701f10034e210008562dbc79bda46b3034dcedf041a669f942540ab85f5b24bb701af48ff51d64b13fa744e656d2c635b68b0d953d6f665bc8c82dd6a8c900cd6b88732d315", "1", .None}, + {.Gcd, "-ef9a7fcf2912e28760bc5e94068b406fcf9b2105ccd4a4757e42c352c7a5e8a1b2207ae1eb6b51767cb80ec559bc6fc6bb9ae225f665ab7334429b4cb769d4667d0afb2c0a297734db4c4f8b094ac12923a73901b13e05fd32d6dbaaf8fd98e700828638200dc64e4f937846135bea364b908385837f60dbb1f67213f482a88649e9e93a10b52f834037870b10a0f177942603b7315b", "39df2553970a143cdb14dc3dc0988405f05505414f8946f044bf9c987d6830576beceac4c1c242951e52e6bc40920a6d7909fb72d8c6f70cc148b44f202edba836f4beddf70d95f70d1eb1f9a9eb91e6a9f1e2f2b3a6ff984c2cb8776c154284d87d2a9c3992578b729d78c56997770f34d1890c713c58628d46fa5d7a574180438b6d163e8a2a691f2f6663af8402e3e1c7ff52a007", "1", .None}, + {.Gcd, "7e0976f4a2c7aea57d024c3ce0a1b7d9b85f40a490a54d96c2182e59c6d250d880c6102a0df715d94aacdc37a0f0d8017020b6f8877d2ba3f4c1d832a5a0d10e13fad4bbdc17ac1acca0bf5350d3e4e12eb248ea110d0644204dfd03d5477d3bbe1e182c68c16902b52d1a73a9a7bcb9758b16dd26476771f7a0b40f270cb564ec6e7a315d0eef2bc8433d0937eac455a5476effb96c", "94cc98f3e2ea5ace5ce7b5b441155230fdd882a9bf813abb1983fd9d2f768f6ac47976aefb63e897f28d967e984c6cbbc8d832c037038da5c35434f5262fd4a59dc2f4b5527e4399e90fe31036eff2fe180873893240bcd52fdf2df779426fa70da8c428c1215cb2b6071c7bdda3c73ac2db75d91b975b7c992f9e436a1fa1e495049fd874839d97ad4377de60e19a8fbbaabd9d668d", "1", .None}, + {.Gcd, "-e9d144e63fa87830747e5f3538f7283f772692f13922e946a127bf7c90df6337722c97fffdb98897db7b8685bdf64daa7d51577f5f6a63bc298cac0f936cd41ed372ad543be3e8bf9229e5be81516582a0f98cd3dd3c24d91dc1dfa7a7e361e6d710e2463988855bdc3d380eab17158060b5f8ff206b1d85a86228af9aad935662fccbc89b266c7d50e01b49a97f50f444386b151e92", "4e8f43e5b2180378c1fbda6517b2461d066370992731fe23ecb801359d6060c3473275ea2a9e0e15ac39fae48dce822fe053bdb189c6a00737c2d80504f10fb6954c1593dea1db48b6b8b8893c4804aafe9fef3969b0487ffeb4000e2f139ddd1de0dedae6794f5b0b98af4ce31275350de3aa4bb783a4d7952962f4957217c024d61ff9fc8b9069a45daac4f7be525d835fc20da135", "1", .None}, + {.Gcd, "-b64e6f214a8792981dd2e583dc4dd8519cafc5f989e0175734656c240cbb16b5f4fc714fe866aff701a9374cc9bfcf9f0638308d17522427c13f93424849cb99e169b5ffcd001131ada96eb02fb94c009866fbcb5a79904bdb64dc3200ba0476890acabdeaddbe4049010095cfb8c5e5619ec40df3558c5313e7c905de3ba5abe0438f00a55e451345f7dc28b474cc09f15d6cea5402", "69108a0934fa0b387e5cd5ff148cc83a99b2026eef701746de4529020559ff47e0e1949c6b7d4ec2bc0b8c9902090fec7d16cc4b2ca8b2414c33dac04b9afd220ca4294c47ac4978acda9de6b129a8c40572f4393c530f45eeb7d0b9ab146d45a8e71199cfdca6694a804cc53af0cebb2d6d64ea6139f6e2a9c5b01a1672f116df7e72992866989217c8c5d4f72de88348e7f27a0eda", "e", .None}, + {.Gcd, "-da5f644924dc0e9b9fd224e78ecf349304ed4aeb23120c8275f8b8d8d7fa191c96388a7ad058380311e40826253db32c81383c9d8f1fad1aa74c0861ce47fcdca4be954bd87e4d29c2f788be6bd7a3ce44553f91fb1a5ebba23ee82e9715804b8ffc6ae08aa66027d13e7208bc02b8e569436fd55cf6a3a45616c341c3b18631a567492c6c3e553c316d14ac9d470a7cffe27092d97", "c9ec35266aa8e019da7600bd4d97067ea98e858d547bfad32db3a19c81d611dc4d31ee4c98989c879aef82c601fe68337c492c20dd82fb8ff2d47ef3e61d1c1c286d954869d7ab88c57faa7b2777b01cefeb88caed013f0108624e7a17c3420d5852ccbdb0b324c23dff02d9974f2feb856e0ee82ae6e3af39e9b31856e3b35a808f06d72edadb68083378956efb77d28ab5cceb49ea", "3", .None}, + {.Gcd, "-d0b7d4397f7f48ff0b9386afeeba7c6ba5f7cec57eec110de1de70ab9029e860d865b6aae3361cac8deceb916d273d0ca13cef8b66542e4a91ef32c353b335eb9ea6468d0dcfcf5b678f1dc29c07e6a8c41e97de10e0b3579d66ddc61f6a0c7470c9623054c804c92ac97dc5ad8b559702da0b30e3dfa240a899f1160c3cb46bc148023ff7ba4fbe9049233f51f78aeabc79fe60b7cf", "3f8a8618de09b02f410e69122d94c640cf5d45299994aac120aeaea0cdb58acb48834c195bb9e3560e0401a617bed6fe52bf3513917000aad601435d467a34566456f600ae5bd28abec600ff618ff04b4b74b3860f48cc78305f172f63d7568abf8068191601eb0139f3a5392a9bdaf69a1c8ae86925378969531b89e56db4d95f10742f26b2249c9ade305912c79315f4d5f2e76d33", "1", .None}, + {.Gcd, "-88ea1f6d345affc93f1c9f85eadf20bee418688684ff3f13bb60641ab582f161e6c6c32676b47b9d513291c71b5b814726f0de5121fb012361a492d5a8411cbed8dbc119defe864a76af34c4fb462e84f7aaa04c13dbbefb4b7335e162ae1751891d6fc2c9ace7dd09ef2a27aaccd0198d88609475b9c3c98f1adbe4d202a3d92933329840d1c5a0f029f9bb6c4119c7400b914fe397", "60bd8d978ac1b50c5f8474dca929be52ffcf76b89b70ef60e40085f8939163ffc2a77b1cbd71cc322d29de08aa4d0f74d690413f2f832dd757212d3f358b4487849faebbc1ef15e05fdb96012209e59c4b669a792fc540d54e7f1c452bf50fdd39029649b83009a75c5cfd430b173f1b801720c2fda94519fa3b1ee8930a55643d09ce3f6bb57f94cb479fdfda250fc121f47b93778c", "9", .None}, + {.Gcd, "-41d6118d55d0163e413f98e820347f2d627a27188523d7485dabf4e7581467fa69b7e8c3245a9d6c26b95856c080bc193c716d21f6a0cfc4a64ddf9956b35fb75433f5515c03de1c1b75aa12d45fe94939877d0400845f522916048ff608f3a346294fd002be1dd6cf87ea331d133a195e60b520b0fdc3633c84faf5a75165c5aecae09c3662a29be7079979478fb9dbb30fdc947abe", "331781eb63b3b92ca404faa5e80a9f2f948358accf0192c6b041602982845f73438874b855e6d40f121bc97ec73b28d178a3d2da8f410a607e7d7bca56a0d36d99c2a836b9db2daef155984eae905e58cb19be0f9c4498f28e83cd116d73e06b12312a1cdf8d2ecf94fcb6334ac471c14077b50b5d5ca269f44947472289f692c91f5337141bf092cfca8b2e8691d756a4a6a3bbc46f", "1", .None}, + {.Gcd, "d1ebbb18b09222b01babea5a2062d3ed3344b9fb23aecc5ac7bf301963184e7748843d63cb87b02b37ba6f8bb72aadcc0137747afd1500337708346c8ae83481fcd30d3a6c273e4c86e01e0c4c7433071bad28ea596e101797678e3c9de5b34f3c1bccb6ed9556929faaad96f89bdb267f20c17fcd03d03d067a48c961fd2ba2492fdc32435d639db2094dd68773742ead251fe59ff3", "7a732bab648f084db0447f8bd7d9bc5a4e7d84d1dab234b466cfeff516430f96fe3412f08442f4583cc6e7eee52e8060ebd27782cb2620e79032326461d66e15b3d1dc753c721b15b8e75c223c866b82db7c6f1170dbfcb8484933211ab9e022f3b3b36965c4becd8507ee5f819050ce892512cbd5eeb11316e526a407996bb5e9a67cd5b0fa2aeebddd1c20e2081bdfb9c047b53acf", "3", .None}, + {.Gcd, "67c853c2bb418782bdd8657f159fe50f1f85135741b7150e4b7f662005b34124e40b9e675d26811509afd8f3a435f81cc06aee3aa6634223698a8cc3938f919ae551c84a8f4569f2a5ca15a5065e6d8073a27bf870cf58e9c2b3e164525d42ccf568fc3107e590bf02ae4d6f5aae04b6caa637c6aaf8fee1b821d74c4b6447cd7f66184ce6135c92248df5e0f312fa0c9d0465d994b6", "2bc5972ee5c7f8f2b97bfdf228fdb566a1e343251e252a1f792274022f7d9a3289e91dee9236378ea718645b73e849672d284554801532d267fd6a8578039fdc525dda80e869d08c5feebc0a441e99594b757bd5eb100fc94ba4392acb34b3f788e2ce4a3b68ece660afae12ce8bdb1f5867d4f41bd90df083e160b29e8faa2edbabfbd033e212321a198bf002979bc6ed5a48dbac2d", "1", .None}, + {.Gcd, "-45516f004286392cb20e560fbccf176e9831935f4c6fd16bb52b2b24e94e3b6af1ba3a844e7cdc4205f6adb44fe46a96e6ba4d01f0c01dc7f906df46f3738aa5540e8bdc88df2449e6258029d8c5d55789b06c6ecec17e1e20c4be71f4751f4189396ede4a8b3bcc158b04776e3857236d6139b6739e2c7680d398a50bd318cdace0fab947b7de2ae17195e7bf12c2b53efc91f060ca", "e1891c848d54b88655248ae02b006b41a76967b56d10d46dcdb063f1c1c6c8cc66b030f3fe45f790e935e286157e8053ab3503e32248c0a5d278e6b313084330632a88f53a7552014447334546edf339b5c66c6c04844f00c33ae16821dde6a2ff30e9a85acb2726a7f6cb89981e25c97f453143dd96dd9cfd691ba16b0ff42c5625d896d0606bb9939a8072d940d801697f1fc8e72e", "2", .None}, + {.Gcd, "5c9d66b33166d7774e953d31c595de7fc574efda7c2709701afdfdbdeca36e80af77cec7106ab413875cf4c264c251e44602c23ecedc5c10c06996b496f3dfea35da43525a1b72d8ed76782284845d786cc21262b319fb06c6cc3d0aada6832ed47cb7a6a9ed40f7b1614c7e3b456c4dcfb2e25e49761fcb6b278f0ac9d08827d219ee19d0c05713d642644f6a3e753f5356ff1609ca", "2d812fba37c7ea58c31c84434c9e1b02d1f8677e02271ff5556be577fcbe06571db93dab5f1c2dafca2a986f0478ca2847a6cb05cc1ab301c1bcd02d09b733bb0d14b65bcc5b8c3a39939b0ea23e08e530266a2e6911313517cd77e7c546509c12cd424f954e2cc8c34b718e86e9ecd54841cb755359216239883978f3855b260fedcdf0afe1d0f9920d06818b5810c4da855aa2a80b", "1", .None}, + {.Gcd, "606adc5a09127b345fae9a7ed3251660ebe52a0c5952f51bd47fe8f1c19569626d6db398f77a0176cc144819228160c91f8562556172e0a2ee67da0d0005059f9df8d825b8d5625ed2e82a1e13cbe3ccb08a5ba06d6a4f27f26100794ac70224eb28ab481f3dbf1de8009012f521d2795ddd4228571d8194a43c5489772ce66702ddf2e99a02ff9d8efb6ab33799035b7a7afe580ab0", "bde048076eb734cad46e805af2875dfae51269f87b3c41841076af0a7723e799f8c9879b788f71f11845c3cd618c6d795794110620549cfd3526c91a45421c4ab8b14948306aa0f3a69ccf5c5818c58c9728d3e307a8b6090c2c72d538fbea95f4b3525d90c7b67b5dbee20168e20b33710a62cd17a3318c6fc2c3ddbc51209ae24e8fcb243fe1eaaf584a347f1bd21a66b69d574484", "24", .None}, + {.Gcd, "787f34b185d5a8e8a3452118747a9aed270fa57c7ce22835184ed72c9eb444e64c86c6fb97aec0c4a234a5ad1a956d125cddb6a5317a2cf75cb5669177ec954288d68590905496dd3e1939dc9ec6a5622c6ddbb0bea8766a52895c35d85ce29449b5f1f85c4869eb9dda604c2044e8ce9b4b65bb4e2f460c1b72e661ac5599cab7b98a29f9707aeb2ab9d0145aa2b1547546dee9751d", "d89016c82e2d8749f78e3a11452c3314c548ee65e930334fac8cb6e431babb6ac73e8bd34f89a5d3d94f3786282e843ef0cfd6f8f24ec252bfab4f680c5e4763c0718a020110c7a2991ca471629fbfb77c648abc7bfadffe5527b0493f0daf4264a88e9a36257c43e3f85c54c5a39c7716f2136ab408324763f65bfeb8a54b81657f324011ba2e8b2c62f031c1bb4e65d8329a53634a", "1", .None}, + {.Gcd, "-e37f059e54591aa59baf9397da0852018261e912de17b24c50391d23b9cf4252afb7528e21880d8d5bcde9946fae95cf8c1956a87e53bfa68178465a0b89646af33658991acf175f4ccbdd2ba985d76fd8ca444b16d91f6bfed938e08abf6eeb2a76d59a31710f6f0931b1fbd55bbbab4c77693c2fe058f09ceabf14f03d00be10fc1b16a236a99d52560565a298edd703c76ad91d11", "4352441e894e13489fa32e99db47ad2bdd743e52a2b1845c33062b5069327f078eac20ac7a4b5ce79010be6b9894839a458ec6932e8190b94ee1d7e476ddbae24bcbee6e0e063d53bf00fd0bf8f76ec4bad322974538d629845da0ac570de94b52a6e181444b5d3f98652c73b2416f10279821134a2d4e3604f4671ad045dae58591d8f4bd7b84f60761894b89be18cd4b18d804765b", "1", .None}, + {.Gcd, "bdc028bf20f2c96c550ba10df8f32e73bd9efdb9c4bad45f4c05fe37cebafedef01cac32bcf6a12b4b1f46ad3b26d05c75475ed16ff62836c7ff7038d1ba08b868b61a2de005d50606f4f94b2ac03a12ab910d096f4cc4467080a64fc1751a507447e6ed017b6a30dc950aa5efdfaa92b7341acb28e46137829af5aff0ab46e3bbfbe8a9af503d06c243cc6ff8bc60d1451145089707", "ff7d57e6c7be01949f0985f76560d36101e3e46f422d8223e8f7ed251f81f538772a31c9ea7e2e888bbae4359198d267bc945f3adaa2372a99a49a4f855702adfd7b50971f8883467bd55de15149fb6d47e37d7752de8e4aa817e1f50bce8d42138947072d6a72235bfd48de612b27621351be8eaa30ab18c142ba588a8e44a88fb5580c8cca64a21b8fa2043c28f8e3006d2b06eca5", "1", .None}, + {.Gcd, "d6567e025db029aa7af668991440fc19aabb0eb02dca791c553577e1e54369e5c6c8e4840eeaf12fa9f937eef87e9d96137102a5d775a83e1c284577b0d4861f0993df36686319b08de2a1eaf2d8c5c2ef90c58ede5d7fc6c0bdf592d3106c56c521cc433f199651f383aa0f323a6b7e42c8af12f49b01724a0bf9f4d836e1082bbabf0ae3bab00e6455ff4d31268548eb9d391261bc", "fed2ab619a10c19381f8d0ea8df264acb7d276289d5c3ec9943dd68bd5154241d2ff20f13cf7053a505b14805dfa87b7c8c8bd6b424dfe6d7c916e2b218c3f230b9f32e00d86033f51cea1fd18997bf29907f91a7eebda414629f485c2fe6af0c805ee75144d065943c1d795ec8b9e6843a89cda310fc92d28b972f18b0c11bc18d9a25888c9982f07e030825ac1dfb9d7efa37e3ae9", "1d", .None}, + {.Gcd, "-7bf2ba320678f2921f07e1688c25582278d0bbba2e9412b3474c3984604c82cff75baa3c14aa675012c0f9352d23c3a9cfed1f7aa35363533e024279dd692c2059ec637d3f93f8efa762adacc9d49b56c866baeb4561cfe8e2413a086cf092509da1b9c4d5dfe3b32d0569a5f8b7dd1102d190fd2c7f5e685c3913daf5226edf4f28fcba6b1c0b71764d2ef445f9e0e1c132721a65a8", "163155cced17bc605ce2751a6a88d1ed5c8e49b7c82f6e86009c289f6e2c0d53dfc91640354fc7ec4d54122d5f20cd3f0182265b7ea727cdb06f3a4a01fbdc6bfffba6555f66a1c6424bbc9d32bf05b142341fd9d9dc795cc711c1eac28558ad26afcfaa0cf49969146bed6cac81f8cbcf3ad658391fbfc06468963e3d6ea3ccdc8c8d3de9bdbd86af3c1d354a64cd33bd0feefd348e", "2", .None}, + {.Gcd, "dae58c4c89a385a16b7f85085577df7ef456690bc704bc4d7733bbd6f65869d426473b0b90d97b6d6249f727e0dfc8788994854a0fc57de9f2ccadca44059f0cb26efdbbc9992125fc1a8528f3e073c4806572a8c781df74762868f5a3a0bf88583b275b3fdb4171732bea620903fc4de68926a2ffeb095f4851169c180d7cbcc4e092ead9fbfd0176db68cb7c5e77eea0e791228d03", "49b94653ef7aa0bad905ee5db4b6b463d63f377553990e0425fa49ea95182372a6a144aadfa75135a9b467a4d94eb6af5702294d38504e067105e623cb9c43199e7459531b7617116ae563a049221771257773d84d66472ed0227c7a6982f694bd6217252d41dbc4f098809f5b6482f892252c190fc25cd21a61696c9684d5a1c81e6868d49af4b522230b837eff34ed444d4f7526ae", "1", .None}, + {.Gcd, "b3a848c54186b45321f072339742ac69b5c7dd2842a5b07f201b18fffc0b011bc720318ea2a70888e4039db176d0542437beabc17efb803df2fe92e156508929d1a60f5c885fb6783c379635636deed53b55b02043b5b2b58281269b60be43d506eaa524b1c9c053c363365d042669bf344f7abe59b3fce15592fb44ed35966e5d212ede077c8a51f110c9e75f6182d987ce0cb65d69", "431769b46aaf1c7f34d787ed0d8b4c53a812efa2808c07e3754f42a7dba4e121096419bf275dafd7bc075da9b31bf08330de44b544d058234314bb9aac4d779eb4a1452ff200762d639900e2d660ef6290f8fa3a0c61c3286af6c6a40d10c31fba7d501b4ef899bad61ffb58c5d9916f45338e3ed740e58e913a490695b4b88fdd1f7868c890862de2bd8181502f6cc6b5071749cc88", "1", .None}, + {.Gcd, "465383316b54da67fd783ed31ed9e1bc1252c6cb651be41465fcbcf4426cf97dbb0d1de0704bda1daee247e9633071972da7ebdbf391b4305e5bf8dd5d3fcd8de6539580f5574b05fca64a8fcb3fc6cc4463a5b62c848acd9cdc7c038a31c36f15934a5b53474b320fce88fbcd7e0f9a2aa77adad90a87b4abd44941ab17b3971694d6b61f72e639b2351e005e770ad342f726b7eb46", "ac1167998762d6500cdde44bd887d947fbfa9a873f23bde6f3e932ede949b8b4810231cbd01d55aaa06581283e04d159539bd17e9723872fbb236bdc1f3ec96ce2a9a0033ed051bf791545f590d9dad6c13d1e1a0a4d93f213ed0dbeac91e7d7022b3841e6e2f108fa30b224841f52ccb710c450431a1d58567b3a1ffb92fd24769bfbdeaf00cb18d3f1bd6d3454b4f3dbd75b444a02", "e", .None}, + {.Gcd, "-9826dd3ff4a2882c8127ebdd5fad16232e48a60ac325dcb8b8328c983a672efa640512e896c11c56a054488f3887eb444b16436b83ed244a768f0853db8eb47b90319e228c1f208c630633306f9428dc82f3ff6933cfa3af2f04bc5faea8a62587b158cd1f572a9d1c19bdc23ef7310603ee0992555c8402f95d1e3e3941feee046a48974f0e1ae09338fd60b7cbbae02b008bcf3ba", "5e8c95debbb83a086235786e757101485aaa3c7e0c9498a8f69c5c64ad0269c5271ccf87d4ec1e41e7819f2f7eb3a111b74116a780c1c4abfb2ff0e5987208dfa28f052665062b964f409d2e5d02b5d6241bb84ba7c38fc38eedc5301eb79628f1baf43308a6dcbe38a287feddaae8a95965e9f5f52a6b12dd8d48e764ad4a369f35d53ed6e94ccb14fdf0bb9476f3f3da2b7f057b02", "1e", .None}, + {.Gcd, "ac6e4f0ae1bb79ba7067d4db99a25aeeb91765156c9e5437a3589500f28fa7a9e9dd490b13a27543ad7f536e25af7828c8dc139329709cb4e2df1daad51e6b7f0fe4652a0c2c38860e542696ec1d4e90608c1201a9fd784df8b354439f8e0d8994cc4b1a2180e6263d1375af86388a70b591c684a9a4099a677f0731ff35261ad022dcf0b9f199e70afe74ae22630c08fcbd9b39b2d6", "930ad98fbaef1dfa1e800bbdb2b6dfd08324bc9c51117b3733b689b374bb68ba1c03af8a828c272bdb50b26ba4dc56d947b79f23568f6cb825e12d7fad7d1d682acc4ae3e1cd27a8d247389169849c2f4e63dce488bc2051a8ad8d76dd741ecd28f96da12e194ee5418ca00df9e66a69e4ef0d2337f07d2ad636034e1c5c838d692da64aa8cfddc25629bd56863639f74aef852d87bf", "1", .None}, + {.Gcd, "8c51aa8a5b423e5f9a55b4047cfdfaa4ba036a27180de4590b5042ee6bed9ffb61ffc26dbe235287962b9c1844c106b686947641f9cd021f117acf64e519d836b05be9cbfa575c1babd4a47d0a3609b9e5df381d255abf68c05a4dc00f0e9b28d98c7a8e8b3791580a3c233fd8446e482327e3a5f5110c49f171dbd270744a2855c0699259642e5e9b3d6920fd27f055914d0b201cf5", "e6a1db7647c3a28e7d1e70e45ce90d7459b2922fab803eb28e3b22dd514f4e3373f996046081c6222e0dcec52f0792c855a262c19a6edee6b330bf32644b53b60508b84be72a175cb97f8f0c10c97b41b8bb5e0426c0219abd77d41e3e728f826881b92a05b4fba7173962a0273e4969182323fc7d19b21f1758552956bce76e9f2d1629fbd695cf5b496860e69e77747f1a612f92dc", "1", .None}, + {.Gcd, "-8edf1d804738cd29d1996ae9a74b4aab48c39b0313fe78e77743fa8817b42b70840cef06cadeb8d628aef2088d8cf7ce275d4b487f2da8cf632c7a3e4cf78f820355d74f7657704f4a1063f4f3acbec856766682d947c95a17075e40a00e71139e9d0c33d2981c9c3f868cb209739e88a365a33940e99581841c48d012e8c1d8f17974d34e365ef3b149a612d7ec3724b0127a54b790", "a4c7305131f4d2254cbf7702e5eec7aa0f90bedd9839b77365c830c80352dc5a84651e5a2e44e9c1b9e5060314d166e8da79113d168e555c7255c4ab148dd5e6ac1246ab364e671d4a6cc51196cf2131d1138c492c6cfcb6ed53d6b65e457ba4d9d06cf1fc5607753a5844a35502d257fbfb89c9543dce6536409f5854881c08d0f2dac3ef075366a1a3859b0e8baf6931e71a3ac352", "2", .None}, + {.Gcd, "bd3d75d47ff102093f727bc9292889ae0c837583d76ca2747c0797e24bafc976adfca776d45f6e33d07ffeb3f808f50f044168a91899ad08fcdb5668822410054dfe0e4b1f1e3a0efa6064f5fd89a71840625e83a2d60e34f27b46b70e3391453b646332f2edf8fa93512c0327afe6e3fd1a89bf2a36643cfb988e7d788d477e42127ef9d9c80eeb60283c49691549b61430f438a672", "eedcbec160e660fe38dccaadaa368b66755bbc9210359e8ff033877c9e8efccb03835ba7966a2e2224db9195187a95bc99f0bc64f1127e88153dd11636586b01beea2bb37971d9e7c8b5e887bd1fe9ee780eeefbb366d8884c159e4f2cd062c7fe884054119fc862d82b8dc34c95a22e0403c646b7e3166b78594a91a5d03c1cb696da8b78e9782248c852f7734bc316d6fed725d4c", "6", .None}, + {.Gcd, "-75fd9b631b8269dabaad0e88c4fecc4161d7e1182aaee23bab22952659955d6898c3137e17e0bba23c59463c865cffb6077977ccb24f577e29889e059e0287f078ecaef0f8c0dc078dac0f82a14b8de0d21884796a413e0274f9503b406a2ed429d39a5b3f0833ca0d800c4974401eb9e44fbe25c13c90b3e348eecc8ed01e7fec23a63dbad311ff2c1e26de3411b4894cb5bed66ffe", "90656f9fec4a33ef23d1841b376e8374048ee713d2bb034dad58023fabc92428ffc820352b14910c27b242d66eb2980b5d9b50fd22d2b4dbad2900d228e7de0d79e6c1dfaf821d155489e09a32080666f25db7fd5cc2c5861f7bfcbf166abd520215a267fd6d819aa1beb85710c8cb4617b7aa9b0d0dc771204d0c95f76dc65831df4a8fd55aa673300d697cae52bcbdea496c2fdfb2", "2", .None}, + {.Gcd, "f96a4e9f613db00d7dde91f3b2cb29eb30fb36e921619596795c92a3d6d321ae538db75dd10544a2527afe5feedb24ba6c206ea864ea0cda54cae4b2ed7abf08ebb57697cc6a50cad040354f15674c4ee241a96589235004b388ce84d0ca53f6cdc6e64a298c7fa586e11969c45e7affc0b22a432a6c48282918951fcdea931b6a8c46ebd20d1962ea91a6e3f65684cd03d98e536021", "950b8d428df5d7b5a6a09503ac3b2845fc4013f582df85e1a3dfc0e176da5dd4c6ae7d5014b3e67ebac606b0808a4677c1d57f29edf143ba9f3ac09f100a2a204e148d79ec32215ef941607a1fe7e2c053e94360d5acef259bb7ec21716c1a8f0f841060660b8b1840e5bfe624f5e7bb40ff4cdc8cf5511460bb2d51faa45dd7784b4b79d9c175404eb652d0e10fa053da83f51495b3", "1", .None}, + {.Gcd, "71e9dd8f0668bb70975fae6317bbd143d263368873c54d0dae88cbddd7aea5350fb72b47db17cfa5927627a28d2a1c32ac6864f103e7599ec867151b5a79680ec5211570dd4edd62d1a573d6ea75b83607c9c87310ab5f4d809484d746d1735ced462c4d2e50a5c4a307b760a3e2d0e4a608cd974f7a324274e1674fc69ea7c95b634e911362e63a424a0722c1a19d92fbf60306e3dc", "5a144d1562a4221279bed809f74d6a8ca91df6df345c17b86b56bf885138a7a3822a4c2d4ae084e0368beeb728a41dc7c994b2f6deb872894f13a7d61e262d0552c898e0bbf5a63d427800534e70a6e79dcb47096ca56bdbf252d3a48aa5be498f51c8c54e568d1efd70cf8320acf6bff41bcee68d65d504878f20d4124ab8d79e6924475bb366ad3052f7479bc45d230e058e0a2fc7", "1", .None}, + {.Gcd, "b158570294f7f9ba3ef64bc7b346c1658899a30cad76ebce719c38598c04c7d1ea22d03bede5b21a90172dd75ad1a0a89a9aa8184571e3bc2d65ff88d2b93b393fe8d66f395f30b957f4cb43b2b5250613265190b30909b208be68430e8a0cff21b82390cbd9bb96bff3fc4510e1d9cd89323715ade70470b4562718a6cf8a07fad8eed73b979d5b75ae8da22ce335ef41950513252e", "1ab88b08e133278b89c141e5c95ad97f11a767c0a5130a4b2707d3bc6b10b06806949208ef1efc0ebe47a426ca62054feaf9aedb0afd081bdb837f54ff434dfa090185cfea3301942c8f81dea0e7d7ebea229dafa79b1eb39086b43634f625cdee164be008ac8fce94fa5be4ce5baffa5148b5accf319e5ddacc124360052b99451a0b6a569249eda3b086c7f2b0fd5a27cf3ee2be4f", "1", .None}, + {.Gcd, "-b9474a4556e0bbb10fb03d7a1c97aa7986a3e17799dbd3423978f551d7e995956b268240602be369f45709c164f1c80a2a3907b99f4ebd1623795b1ffcaa88ceff32dafbeb4b9f060a43d5e4ba16d30f3c361570d50e9ed29a89b61ac18845d1233cce797d48d5b29c6cf62b8df3726eabc01eed77c85908a271ad71a062cd4cf3448d5f9f690e557bb51dd7d3bbd9d1e7cf03049fee", "101fc35abbabd48a4cf404203be0c0bb899ad6191c0e9e276ae4097ee16390271e8089aed382d57060d536060c59ea7477d4340c3c5423202f930e268f64dbb7fc0c10848471e260709f6237cc3084395c15d6dfed3d14d0772f4b912bc9e9809b5b131082c8c84e5a56064c94892fc683f64999c9280d48de409547fa8e2418c4d547814b8ec4994e6ac156dfa3ce0ce60eeec93db4", "2", .None}, + {.Gcd, "12537a328fa9fdd0a89033b533eb31a67d1a314595aeffc9c001e0743aa9993a481efbc32f23a9ad3327c52c6fe14dd57e67b2757fbe5609d3f7496cefdaf2c264fb036dbb1758c6be5381e9aaee0aa89040ae0f9ffd1438fa96eb1775a64e5fdf29d4fbb36b1c7ccde799c9ae645b51ba98cc6b5f1dbcb894b084fcf06de175521f6830884b9df467ce25d24f6670fa50b2fb5ecaf4", "be7d869c45da06b90c32d0396dd82184b680a32fa7a9e04c0fe01c5deb9483a08759e61ad79526e259e48517e49b8b0657e4d066ea4a559cf4283e16e0b51a6f5bc6ca88e33e4d6458a6e2bc86393489aae215439759f46eadc654578173d53509f394f0c14ca39bedb0be647cec57ad3026a599c528235bb51ba38cd831ff47a5ce86715c1565b13383f980db2f692edfb77cb82e45", "1", .None}, + {.Gcd, "cffcc4212d62d267101c2a60b389f2ce67fd1a4a39445a99a668117878b8bb1ea907aafdce1dc33c393652fa3636c20bffb07950b6d4bcd719bb80d6b964e06fa7d9092980ff71df48d6e2efcdb5a5222a1cb2abb64ce9245e45f89f837407e08fdec1a9b551d1fb5b379209fe39eefae04d69e338d1b1de381c4cd678e9cd3d8ac4006291fa88d60728d8ee2e1dd4ba66426f0f1a23", "d1a07b4605c10a6e6a737104350fdffb8deeaebfd619dac34a0edd5df5821e4737d8a07ec14200694f999de82ab83f9e15cc61d5e86d88459c2c92b45dc1e1155e27f743202d310038e0084ca87f0466c29537af703c9a546f63ff02059e4c2b42876be45f994e224b8e9ef0dbad1436f806c9e19dadacd2f5308cd13afdf344e3d2216731ade957878a6fcbb0672f630eb3ce5ba7c", "1", .None}, + {.Gcd, "-71d751ccab13a80bc9f02209fb61b103a2ae6f60cd3a0ede7f396f406b4ce8a6d413fc1c9e37fe43678ec368251fdd63ebe59601e215948570f219f75b644ede5d546103c98c8d42550e1f179acd94bc704fd4d0fe6902c1021da20d9f160dba2fd60767cefaf14740f063be25523456c9c0c2836d27c6b004794e17ae1d52b4337ea40615036f64e05bb4b840c1e0047a0aa6f81aad", "592694a6a7b1f6576fe233397c2b0dcb3a32b52f7035b487b3c39751e74e2f0d5f480eb1f8a5f07ddef95923d64cead6c07d062f8689393ff9a8073d5e176bcd32556a9da7fda105fc96faee7ddc817aa75cf6a7cabce630c7f138dfbb4ac1f697d6b0d517bd12dd9dccdc1c49b87fe4698ea501df99bf275b345fa19100e97693be3d143ff896eed28b3994944cc7d046c0328b8c4a", "1", .None}, + {.Gcd, "3a0ee3051eab1a012949c411778252caa789c413d0338ee4f028b9e1d9b49129d307e094c3138e6fc6a01acd75358de164a4fa928d6888e64706f74fb35379616b62543fbae7531603e7c60033f6d24261c1c06085552fbf0aaef13177b71b2862842cf4e4e04d3b7d685b491d35289a4c0fda265876eed11c0d74c2b4bf8b1bd2e2c032b2811bef6a89909b5d539fa4a17d70757c59", "9390640e1f650782dd26fc0065aae8e142cde8b8b6c2c6373e1d2d4fa6de4c941f5f2c738c1d1327238b65260139edeed46cbb003fd3a8d8202581622d05121f91abe3baba6201d88982f822d0d3dd270920197e5b865d24f2710dd4f7513f2892de65d65a6a74fd0f34a92a85fcc9399baaa87bf68582ec23731c823b543a5e45d02af26a97ac7ededf66c1656d736d00e40ee2888c", "3", .None}, + {.Gcd, "d3053519435a5d204d9548467d56093ec23e307023211be2d11691821702630fbaadb20f594c96ac3b2dcc2f1959b8640a000ef657d33bb44434d7432aae97d4e7fefbfde9458210e732c17cc7e44cbdd826bbe2662850afbba52f7bfc98d4731c8d1b3be147686f6a9cdf26cafead9fc1c89ec10635d4d828416506ca8a2f255f67d71c75de593d0f9ff1566eaff8722b7c9062c898", "f40b6ad067d6cad8aa47a0558de2d5015e44dffe77547373c18516807893a3c256e102a4b691731686b8e73b4bcfda3d234123efa18b6faeb2c5856ca77e6b4cc0d141df4a4fc244a6dabbf9e5a11fa439e5d0155f59cef51413a5e4a1eaa3bb0e563db35f3bf02bf76502428b067038b6146c94ac1ad4afd9accf3c19053842c2fb73af13fe863f5b59c8971ae9261f3157e40fc15a", "6", .None}, + {.Gcd, "ba34edf81c6a88f751f1bfaa9f269f82cd494897c2f5fb8f65cefea7bff964a88476085b8318772a7f93a62ded8794129ed0ae08c32c43fcf136fcfa8d2993c7ac647dfe82fa78a2fd96fac15e1d79d147942668739722b1206665282b07e332b070812538d3bd796e0bd51d7995df14fa17fb87ce2094b022e17805614be581325731c3354be2883fe719c27be13bcda5ee07c2a7b7", "8f7f2b8df82e11660651a137188f9f1b41fcda4e8d6d50976d1cefc87f2d9f534fdfc8c084b8ab08924435fe7cc8e93f511e95565ba87aa150ded73b51cd3987d2fc054b908c3ac2552b73677e66a455700360a3c4488048bd2480676cc63851077b3b9230ab3451f8b6782bfd6c11665291c28aa1a3a0f0b94528cb5fc0ef1506841974b2c22ccbf9f2ebba5bcd2671234324654c20", "1", .None}, + {.Gcd, "cdd8a987716341476821d120b82f2f1ce37817403931b4feb66c1eb81efd127d2331d0046701c59c98e43da508043bcb2d2828a5b706399c09e55ad2504332ad908105be85cbb951a6cf24f60852e3393d370ab3f89fd8226138cb1e505e9cbdcfc176a949d0ffc5ddb42134311361b2207069994e86c383e5e27a6684b31dbb7b24b801a4884f32b3d1c5e7f157204257c39819db1e", "7d64a45c0ce3a6b1d7e28c63cc4ed631cbcffe793c005fe1fef7b3bb442eb63256f29eaf64eef3bd276723a49101cfe13859f429f98aad3d40ae50a4f9f17698df9d9b5d416a51e598cd25ae5d2e2f9a5c95af0befa8d28e2205bb7c620fa8c7378758f959a45cc027df2d1e7342a605ebd972c3fb880a730c25f25760b12c5b58cb93089eb882b85db7a655b09f97036c0e7ce41f2c", "2", .None}, + {.Gcd, "e910cb52fb5d8ab7b8327bcd248f6cf093454e360481f6795a6e07437ed29b46f9f10cd9fb1dd33d192378711764a55c14fe46c5bff07db42864a28b6ee1758ae797703cf9e8706afa740cc305482b9e1621a5ff42dc402869c4a35d661830dddef1a32e0b6b57ef5a66a9a5f1085b0a351ffe1b541dc96cce6f255ddbc7f04ee03c4867b5597d1f35b7a19d79c2742d1c7ee47ca84c", "38549792c74240720fd1598d1cb1f38631230751012fe0f5434bc48612e83f1d5aaa4ae04e168f79f82eb092cee30737744730655f04c9a8be69c9ec9f08e6a8a377eae824cca7c8ef94a50aa82c8c8aebb4edf43e5dfac8feb8f8d77aa83b1a1b18848d24aa08dec5679a694deefb84a82851823e0b819835b732e5110c479060e98296722ce447e779cd14a51430da2ae64839a9b8", "c", .None}, + {.Lcm, "aa41c1e69ad54302aa32a34b37664baa9b77e5e06dd62055b4fc8111db31a6be273a010dfe6bcc0e39274d7d99a03ac706aa34d1b3318f860624c56c52443b7127142d8999ff6a2710f73d2c480b5905ab17ac5e96317309d62a059e7e742314d7067abe531ecf2f0fadea1f2fac8c55c6c899c9bdeeb3db94ee914cf82d7c659877b1a3f5f46637d5f3381dc3548b90295c68e8d532", "-1808477c9d3ecd6fb1c3c16d9407fe0ac59307a763ab83cc9e332cd1effa17a3e6648c4cb98c17876375e3cf060f3144b896e68c82bbd7770ac6ce01fecb57177b814fce8be5fcac6303f2fd5b517a0ca74f202ac64e2e42985fbc25a4a570aefa2d89948799e6491d4cfa926bda14fd6c7440c575f31f91adee76dc3a009216a96ee33d79d79f2d78e97fc3562b1cfbf9be5570f87c", "7fdd5e36576e707685e78f3806d703e9a46deb2d2adafb6a7b935252d6a95af8129df3f8dbe856884a6d20a586913579d3e83527d807949b40960c1715711546d74e1ce4c2c57e99cf4e0adeec5f2b788f3504c9971a669af2685bca1ec03e699e811538059f2fbd012591aabc7962344f3eda782f420b67c74141d6980b5bc0905ce49494f66cfbf7f3ad26eee3c49eb2a084ce6774fd8b74c5b35855b0166fc2e96666f87c625104ac6554bc6caffb61fb1e0de5c6b2fbf7399b483ca5e3f3625afb2a1dc16385399a86d26a3e84d426f67dd8d52e692de34efacfb3a29aa73cbf9d1f2702d01682ec1fefb29c3eb5b29191b35f8818eb6ddc81701c072bedf073e1de6e57e5b0fcef0213b6d99a86d54975dc2a4d626f296c345d962b0e7058b7a4aeead50139f97da1c", .None}, + {.Lcm, "92188e73ee62cf9071582e2b631ff5eddc01b0c1536a12b6479b6bb438063f7a927953ff2b74afb89edbf05a8c9fd7cb84696410e57e6fb1a281a065654e27a71c2a566f763d3779899e697c1d72b59243e17933bd522e27bf270456a2da6830ccaabf5d61a7403d638719fce31acd96eda678925a022c3448d6a9d495ab760eca86c294a2c57201ca1953f8a32c1c806a1921c48baf", "2a51c536f0375ef9bff21949e02832b35eae3f9be73e0049426439bbf86a3be0c7ad4c5ab0ea52d52c3bdf9d3ace91d4a7f0ed3f06595e2c715744fc192fb1eaf4ac532f74728314486c39bad93a43f5457d57041d55dc2ca4ff722d3d5dedadf27795186217c96f095b3eb29a129817b9f1b3bd00b828e75d9cafa3e5834286c342fbb615b8adc2e8e0bfdd972ea4bfc0237524b3f2", "1826b1b057ae853e87feba355e061f42069a8c127d330ac28c9221da2c3dc04c1e52f3bae48889e90f1be6e489e70fc95bb26c195ab9c3d9295bfc2bf72d8cf883cb647e0ad205a66c9c0788bb4c6383cbecab3eba02d04ca8f25e623122e3ca62079a230a01760376872490466da780eeb324615229181bfe781a222d079ddebedf5638407e99be9974c539d8bc03463f2070955afa2f3f827552f80911066d05d54955a1469016f9aa941b03cdae99fe18742f0058290992c09d8523b5168788fe5fd48dcea81791b8160aa082b0ce5cba88566f5a5078248bd691d475ad79f550e30bbf6dd9765b0b9d4d77f18e2412876f1dd825762670569ccb61de4b9f67416d6470e08e9bacd57c51e710295439d0bcd0f0093e96707cddedf8369ed4f4a892827dbecac5f913686e", .None}, + {.Lcm, "-7abe6aeb98ef94bb8d0c524f272a591f2994b84bef8a51cb5cdeb94b78037e3dbfc0a108c9b21b41e8d8b0ecfb8e0b5d5905edcdd9ab24d0d09c8df404632b248e2d74dea49cf4d13e8ef808734476eed33d106e0a56fdef1ce6979bc65723e6b28ba545b2e6f8ac50f74941fff4c474fb2364f7ccb2ebd79379359c7254ca6a6e1d3ef9f5cd37978e8ce7c5435d022b47bfd7b7294b", "-f8da8c801413a532e1c2fec73c8826e0866a09fb10979e18a759c06478c8781ef48208e44967a3902d717f6b2de63010ee2db78744adada4a4448b60b2ce3691f9757a9037b772ebc9a60c0246b4c3b29cd4831dba10a9f676c9902b825adc245584d9f59d62a6aff022dd6c7c04e20d5751e5a155c9d80654705bb8001982df9638ca888c489cee489fd781a8dc49c1128016a5a896", "77514118d416ed3b4d43a28f90326d4caff7404f7236833bd62c8a734389ee02e298c6cc7b269ceb84cab5721979a8f44ab6febd2c8159a8dbab2670bf87b22d2ccd2595a0745e39e91aea8385305cdf28a34d36432ce2f26f90fa852c2e6d43508565307157b7583907f5d91e574bd923cad604c4ecc63ba7f944f9bbc987af21fa4c0bc144a4fd05dbc7411108aa23fe7a4e75500d2e04603f6f0b384f78e1e244814f52d03e838d3c2c2a7297fc44fc959bbae5c74936a4f81ff3366ffb26fe5b75265f5e192f87f4c878f15297876cc37f996c7cd3d90d05dd5dafa4a26ad04dfdbb5dc13ede53d0d8920422fe1a1a21b723ad0e67f617264a2a985034f16fc0f0849a17df9afe110538776ccdcc6ac756664d8d42d7df29661e35695a52f80c8d62a8a8a212a7c269f2", .None}, + {.Lcm, "7a3167da58990d75c23e6d18adbcbf2e2a771d95144b62a4c93723367108cd91f6030c1ae8d1276a3d98fea812b3ca0a84bece3f8bceb8720a861f6719cc1fe4884761d6dd21e0449c71abf004c8bcb82dc1e5059cde728fa6a1a341d8148da121dbd5773fc6a42ce312e4e4769dd4a1e2f82e90eadde6ce7fc6f4bea8d89a58970f3e2a2f2515739e23825081749e2bec0150901d8c", "fc3da23cd68af917a8076c30a05c602cac940a41b415d070ea5b5a0829e25aa06208738195202222b60f05d591381cec2c6820e2cd6370770bf65cb7f67a237d4a9154598cbcd0554eb2725923cbe749b288d6658063280dc894816f34ca44fe2746471a833f5b2effe64663c071030aeea5fdbbef78d44db207c52e616f829aa7a16953034097b984bf1d001fcb8a2287eacd8d564a", "3c3306b87df8f5a6cc89e43d830039149e8019d8801f5ebd83c505e7adc802eee0894f4260353658ab4476d95a47da048738d28f2cd4c3f891e5efcdb88202924a069c7a28b8a3a851ec5a88f3296f1e5b96d096d95b740dcaf01f4a5aa3cbbc74a25f7ab66382acbb3d7ce26faa4c070dfbd1824b07f4e05606b6c9d89d625184a67bbf7fba00a57d93f2b5a90d5700242a25818eee57db1f0a9bedc6f4c15a64258925519fad6f6f3ad14c747474444ebd9d560a831ea5e6526e7342995d2900a7069173ab0036ce00673363e41bde3214372b608be08138bf305443746cf571325506a6e76df4953601eb74912165e9d824a464125c60528843721e66bf2009ad2149e11bfbf4e471fc1412ed7eff3922b0766fe1c42ed1669d2d38c3a0dab1db8965c60fa3398ad8c93c", .None}, + {.Lcm, "2eda975e16f6fc839a5d44d88333103a76308fab2cdbc8a0f119e6a0279f83750c3c30f0efb171527cb27d8fa8d8f0664f3c067f9da1849fbcd446bf26794182e9bd27335a6cd0599cc1dae970dd4123c7e518686770c2eadacc340f42f26acfbe9faf99d9e3b37a80c9763a73b318cb54ffffa0520969b12e854200017aca51594bb83d649a2e7675f5c4ea150c780b0b341a4f1738", "b1220bba948a649546307dd106a37f8633ba40f3643503be83901a125f00d7c12d8772a7cb92ae4c94f4f9c48512b13d53bd897d5940c465a50e81d5cfd2f924283c711765fdb3406e482c757017b040398e527ce6b82c103544d18b4a4eb40a991038982e0195668ac48b62c415d8be90c9eea447166ca1820342c84aed82565b2e0eb96ff77290cf61b8fa55234ccfc57b7752db45", "206b5dd5b2e28a7e86b4c7802745f960ec45485340ea54cfee40fefff092f29e8fa5a61dd5dee6bd4204abe4c00966b3abff7674468c5c0dc3c0c212485ba3a8189281429e90f33ac8d880637dc97c8d904809e5fae145116a73a9d363a114299efcbdd96c3dbb194221c9b08244da6ac6dce6048a8ba7c7c3d392ccaa2518b8927d2ef656c8cc17df6f0751f2ba41d3772972ec3ee4152cb5dc7efcdea50e5f3576cb91d070cb5a9349257804a3217fc854dae760b7d531c51f69a6dd9c268582776a5aca1284eb0fc7844de37b8c11d0c9028d99856dfcbcdcd8544760ed9a5dfabe2647308158446b53b185fd95b6d13f24d7f67706f3be38978e528ccfca4333a86a6e5acf33522b00b459f86a638e659d5d408fb5f48008be7fbebf6e1658f8ec9483a10895381e2a18", .None}, + {.Lcm, "d39a7f459b3e62ae446cdf20bb0d081ee74f60a52d472b6ff7a917f4cda0db424641dbb7179494cd02fced49d9d0b7265c2e0df3246464a3ceaf1074e0b0106353e5b033799109ccc74130afb94debbc96c03819cabafcd7fe5da013729b97e69712afc22c03aedf00663d62c672eda93287cad172867434ad1dcd87ea95d67e314eb3dca834500e821371351bb0d034fa5ab29aafaa", "a3ed42e714ec58dd28e6e1228e097adb3e010a18e0db181f750246e0d9db456185eb3ead8e258f9eb903ada6cdfcb26f8dfbc804ba893d1d4e08575121146a3ad90b8b0140cc28bba88c1a37f27b4e838b9323abae325ed64561e65b093589bea19f91f256d313c76333c63089dec85e20a7810bf44f130c2f1b954e5868f244dcdd35a56395b87ec18d52977e3fc821c4fbd14787dd", "877f7c5dfbcda93e29dd6835d784c27d5b1f73f0aac180645f2bc6e62a4b2b232adbb8500f7f920010825929f4d3e84403754a9680fd30d52046ab810b49fe7d92c34dfa9737fce5f4a50fa51d7a1dbfc19d6982701c3b0bf912d34d08ee1d595572d62c632ba740679b1bd32ed6e317f0a26b79dfad999b959ad310d569bdabae29f19c765be0f32a9982ea558e81abf5920f50271691ddce3d2475d9cd0ff9c91958b55811a2fa319479b4353a23f52e7095c5251a77b0d321964ba9a385760c7854606e8e01c5e98cee539a34dd3aef904e768ecb6b53609e8ede615c3036ec7ee1343140166a5dd058c7dbb797ecbeb2ab391cf5bf130654ef78d2b78b440281eacbfb6b60b62b96ba31346c24e0b5f49d70ace3de24bbf94e2fbeee1d5fc11dd23429cc2a7a44524bc2", .None}, + {.Lcm, "d23408baa4f7fc4e52cbd2672082451462da680bd988d7385bd4e81db468e4ad101b1e2a6980dc87c039490c865bfe97bcd1b8d0e82093a9c6bcc4e2735c177ce875a7da33077d67e4a2e76061990cbbb3438e9a788fc6b31c602e0627e83ed9b883b55949d45c06540ca20dc325cba49456968d582caa74b96f4831b0d00c0721a8bcfab6599699c99e105ed7f51513cb0b88f8f00d", "94a6393c1e5548e76011b105148f4009561acf0b73e3ea58df77cf43db3b19acad9755ad93b1f201ac394d089408ca5699f83c07f0746c20d0a81af657f55a46bcc4c2d0fea299a3a18548e7928f9654968d7548dc9e78232f8591b7f827fab1b45f0fbf3df878af094eb02144cc4bb8db2338d7a8d43dc88bb1f5921a48e72dc6ef787d8442d14f243e22b542c0348d6238b6b12ec6", "7a0e91c88372114e278c57661de9983a1fd30395847798e93570937abe19abc3b0800fbde4679c31e765aa907dfde09377865113b4af3afde27e5ad90bf36012ae8ec288643ae0c9af81631798eb1eccb8341ce7f6c40265a8b5bb35c3ed59c533d5ec62f3ce1c5f1676b275b2a087d0b8169c4791db991f35f1f6f9532e5d76d3a249db585ef45505f144a2fe31cf3eb71203e48d3a6278ecd087a5b944581ba4e71d2805f33b4e3af1be3e0c4ffa5737e71f1fa59f129bfcef96f8e48411fe03ea0299cf3249ac9c86f3ba00af4e218bfee808845bdd47006f5a9f9316ea5ad563fc2d13fd8e91ca7c390a03784c882f1bad2af3effec7c35cd1887c1560761521cf48d116b43576e052e5cb71d70f59ce6fa1789638dedcd110616061e820fa9cf0f58fa84927e2a9000e", .None}, + {.Lcm, "-dbe7e8e492910165e31cfe6f299ad9abf1c0fda5fc1c225ef97531f5c7be67691c5fbb4b2b0131cbfb3d07a728f4bce3f619ebd0f54bf76168f101239a25ceb7d66d0262d7749af63ec6c2d23fe56043522eceb2a092c546bf3055335af7bb7f793886a57d01adffa5b826b4499bfa947f39f066ffa6ec1c2af2f29e096b330ba3917ab4fb50eecbccb64e6aaeb95c1b9c8a46ad4fb3", "da1be7036a78c30d5b8b5d1b605fbcf59efad62fcb72d281cdfbdf32721c0fa031fb3602d77d9fdd816974ca16a2642de2597fab2e7aec90b86edde1955363a587e2eb4f88e72ed6ab92669120883aaa85da4600254dd5d250bea14d5491f948e2df46ff4ae34028f8230499905bc4cb6fd4535da478409d5006002baa712577bb01753711eb28a8f436bc367a67c7f99325c3f8b311", "bb5b7439673eae1b68c06d56875d9df20f06a7ec6dd0b5888777938aff3dc75032f20d0ea4e1165378c38bd544195eef9a403262e2b0255987142a1ede35b9ab9e9dab34908f31c40c6d5241d3b13bbfea12e382656657857d5f02b5a89a74597f9828e8da17f2d0e61c059554b6fc0be1debeea575885d6ede77b87120f1e7b1e06cfb261d586f136a51d86050e30b4810d77598c54fa80ff5fea7ff6ab71e016df05c80df7a7da2319e9cc2ee9eb7101b138f7d8a87af5a71eff317e6ba5ed7189f44cb812382cfdf7eba79f3f8241babb3dcfa98edd1271f92e11dd5b96e72d85046166565daef535e53f1ac1777343b17f3e039d5872f89945a7d6c0e2ff0eccac898a8953538f5536c2bd25828c6d3794c2eee18e62f1e9fcf7516c85c277c455d0cbffde136ea473e3", .None}, + {.Lcm, "-9520ee0f259583e98468f6b4912b2cfd421a29e33cfbc53246e08bb7cd009217c7d551423f4a1dbf30cf4d850ad8b6919f330673c030537c282057d3192aeb80f229e0b8871be50cc28cfed289b447008eaf055eba697bb6dead54d4400be7e32654b37784dff945d170eaaf33de122e1e0e5de1d3749cc49be43c05d8acde243a07d595afe4707407b70fb98fce32f3371f5d81a537", "-6994d511f375dd43b0107b545f83553d14a4279d46026031fcd5975070bd7ed8c43be4b4a074e3d583e0b9ec1c1d1c5c838607bfe93232382c2292d9a4608f010179698468316976657dbee6ed9051749ada147be57ffc1ba382365cf2caff27c58cbcfd9ff1024be9b1d7aeed372d619e51b882975700c4e2bd9d641c0c79e3febd095f35d7c8951b1b26bca99c95e920a042ecbcbd", "c4d0a8f56d9e058cb751336c9708e225b0e00f976ec154393fbdf6cbad498d6256a3cde3caa19d62b42245d32890a40fe0159cf4ae220979287af6c653245dc73aa0695bb763d0fa5560e90f34309e2520e28031ecaaccda89f06da9f9205c4cf77c7f1f0849d85c172e3f06ec7e6ddf0b27d0ae40b29d4efbd4da10314b765dfeabf09da247199980545e1af88187aedb52f669ea780a019a4a96e11588935654d020f39888b9d4a5c2a666ab540cdc53696cadbcb08f66ffe8dcc9804c7bb0f62e5bf1e77e333ad0e51300a1887204faf9b2fa947db8534a7c3b3e8f20e3ec23c1d11da478cee5e5a09d45461fe35e88b78c9c2b1ab68d6350e6f4bd4e1749c94d4dcbd79da6dc555e8f46ebe147acdfab52ed8237448e85b7e39f968b294ab3b70353b5c4c432559791f", .None}, + {.Lcm, "-906430def979ebafcbf54a4074398020f03520fe89e7fa222e8d135b3fabec63b8013f05f432660a44b311ea0bcb5d09775ddd2e670c016a2428a089ebc077ecfa11a412787f84c84f3e289b5f32dc5bfc3d7f3537259e41b6f403f61ab843018920ecd37768ce0a973ba6323931d46db1e4c139af0d1526df1cb3820c2fa5bd111255d4047374c57ac1880dd9e790abfb5c00cf4a22", "1371c5c04932162ac87e81203078a8a183cbddbd38857b4ee3bd1b5b5ecec592ec855fdc029ed4c0ab96ed12e47720e1caddc9d2fcff9c70285b75638b7ba0c965d60a7877e36d2ab82ae577d184300ec8ce62ef90ff477c46197486d975a3cd01667c891804280b91a204b20861a5c6009038273217dc1b2f34d1f5b1017f7e568f985424388c6f98422e14dccfbc0b6e38c9355e06", "57bcdb1d67c9d43707a49f96009618aaf84358aaba758dbb4ac5c8ac034d7e4cd9ccac458e7c33f5ef5d570cdb7d506a862909f57a2379a5fc2481393e678124bc1c3a4e562db1978df5510ff59679f67b49f86e5b690fcef61bbf4181b5a24361e0a91893d00ebacaef0f29fcba5f6af136d8d93b49d36648e2ac51d12dd449816c85493f4591d19f6303d7ac4dd63774b3d4d05058eed2cfbd94cf93bcf1291b898da4348ce69e18327fb599c95aeab4219ae255f2ccd051010edd9b57bd606cc4176bcbb987145e0de33ea9efd4cb30ec71989ae8563033437e70db817e4ecbdd1fd089e6c2f255e49c09c75cf53f08083348baeee110f2472717490ac15997cbb4110973516177fe9b106595acd30e1a08db1961e78aae1263f5c074b4f678287e99bd5b601968f1c66", .None}, + {.Lcm, "196b311bb8c1ff2afc62e28d99ce547827260a23f3836ed4e51d9eebed687da87bce807323cf687c840d95949535ee9c5425cd0a2929c62c17191bd476483eae74b40fb95bec1032d472ba9bdf6355b8c0f3f6c304b87f2c9268a72bf3efb6a19f1edb096facdee9db3ef953cb086f2f73ff4bb9a60ee06bd102cfd6cbba23434f9cb7d632c36f310f0451e2ed808327a59d99f6d985", "a359a7d3d057aa706cc6fb9a73c3c5542a90a1732aa6a31f8b55947d387e060190877b38de5f6041049d31cc68f1af782e25a44105e3af4cf2382ef36ce8eb1dc18bd04c1b913707c1133a6065b1bfc5543a4b2c35d1c84e0e7a88212bb52938cf3e80da552b8c438c9e80d3cc2d38156813763a042835e8316f81b6961aa3bdbb8eb4b3776150beb5a048543a17c67df7336919df1a", "10382732ae591c8a78d75860dcf54c77e991bc847bda177edfae7959e9f1f7e15ecf44b300e96690f5c6eb42b61c00f1bf7f6a70b7812128f37eef8a5bc633e920bb2c1a7511c5fc8625ed7acb5203feee60058b893cf65bb190296bbe5778cc8443dad6c2c97ad4f05897b3cf7742632065927958eeb34ed974e1db9d711f77b110f89092fe0e48551527c073c807a6f7b3ce697bdf712224af1c7f246f0d02d0ded03268b4f51860a89123b9933053b101581fcf36234892f08b93d1cffab49998f7538ad492feb899a8922d5969a3ac4c0e99ac0e57f292175eb6ea694a7f9e532e28e132f55b3c4515c4a33bb28a0795ea3fe3aadb9b9af243300a67c0559394386c06bf226cf84ceb3248a380be0ff7cd9289d06a9d3e3944cf1681e448941af7c497d30bf17589f282", .None}, + {.Lcm, "7930d64b18c36509d675f391abf3a763b8517092624e848db50c18ce2bf04e2f166fc4e1bd34dda4a9e4b88c7c9a15a7c1013916f6b173a6810f34c95b0ee2048e822323459403e863316f6da03b7a5c841574407a1c58b008a71b0c391397fd035df1945e85d479a7e501ec59cf629f9bf58630a10ff6e11a5b1aff840d5d14239bf9275aeafa5c0777c3bad18c8961a051b8bf5c4e", "-fddfc060d5f271a5af74faa1051bbc72e4cd83b55a4b6d3f821570a94e102cd9c7355e4756e322b92bab7f1da15c61b1503148f4c43396ff7472ee38928f5c59d159422564c8234ce0a26e19bf7f58fe1edfa5d2d7ef45ba0f6c91c90d33290903fbb9f18cf188f522089fac4f73410cf2e2635fa591548402ca30611ef217d115389061b93615c5efa0ebc812f51e122fffa9a7a34d", "782f30655b34c40f9e4aaa5f495f7efe8cb3eb503858dd5430de21f28aff956bfcb991097de08e1b7495995e2d9a926e0e3f0cd134e2a82e00cfa6238c74cc7b30a7001f9a0a5e31c7ecfc827255a0b336b3f4b9b4d893bb034073f165beb46477ff802366201a1824830bafa07c27c83fc906b211aedfbfb7d648540bb9801e14fd0f375fd4d15f2f7f8c85097c311bc1942262d57dd8c9fe9a8ec2044fe727e255d152bdf0fb0cad177206f751dac2ac63085cf62a8cc59221c7d7dd4a2649820df9ea647450295ea03c2d7194c4b9df5c589fd247e4f00e5db4648dd2ecdcb4ffd9088248fe764aa90ea0f8407dcff98397e9424644cecf5af61591fc576229a03a1b9aaf01e69e36c133f7927a36957b6e9d71cf9beba179b0687641d4e5e4a08381cdc25dad1e366d76", .None}, + {.Lcm, "fa19e4dcbabc7e0636ac4e103a89fe75e77c9542c4a3201befebc2385c94c371454b41a9a867a19db810def185eb41158c2dde7c4a7567f0ff2ebff4df8a128a9e82fa135f08057f906e7bc5da564fd96071dbc49a9a8f27c2e5cf007ce0ed04b03c8d292deaef0f84bf9fb7f11c5acfe89bf1fc82b37d6142407a24bd831792450a8a1a782a7b7e114a64e540d523ea826ec0ad5d7a", "-403b1cd2f93ce67444a7c8b86ce7b1da26dcfb3e656318130b2c518739edf754fafdec28b86f1bcb56288d09cb3ebfa17034ac700361f4ade31a021cd9c45e4108ec631e9aea816fe9cf3273fd62a6eb28806f5c777710b65bc3efaa98f0e81c81c3f0ddaf2796c2111ca7589292463701274d4be9432abc61de18021983a85cd78b564019cd8140667266fc7c97bbc630498c58762", "1f601cabefa95ca0caa5d3504f768003725f931706350d212ad058286018456c1db4d20c929a8feadc967121706494218f371d43e957d1e5f4414a3e55a9de2e58bedaf4041494725b8826d8b80498136bb95d4a475e4a502826c0f7427ceac823c04a91c621dc7476249a9dc325d78ad1197cad427498b7fb967d2d6ae24cb1466dd177730df791d3029d01edc53f9af216091dd03d4d226fe1c8f8d827d27cb38b737b833d617bd887979094f8d4df26670a3809780b732cbb4eb490f3e12e7880a19ff9633d904dd682f3b1e5b75b8d1c8ae2ff012c5b8ec32e7aef3d0541c702b898cc33506ad395ca79a43ca48b3008aa098e8ac58f3295ef390a02009513ef01160618e9d41f5395719094738a4109b922fda5ffc225d313fe64aacc8f2fe7e596ed1976946c58f5a", .None}, + {.Lcm, "83c19c81be3225670c67004a4e70f9a99a01803a6da5735ef62b03f9b4e1c71e54ae328da9f71002017781154ebebad7232373a6d5e2d88c0809b4dfee696d436e2fad72db4fed9f6925c2e4381852dd5733d648bb1dc32e4d76192c90f45d1c2be75e4ea15e1449beede8671b784356c6961321abfb242065448cb5e8ff455585ccd1ee32316959e225e943f16f4bb5689827ef3cdb", "d51fd8e62da09a982b46fae7b1273f34726ca061efe183889cb88e86349445e0942be727db483a8a8008c220cf3c6f34839a4dde68ad081df57c6d15d68d6842be9b02e13f45c86195de0508cd9142d9f1706364fe7052265fd99082b338dab8e69377b878b60f4d561f69f121c0e59ce3ab178cd07f08424a3ded4b6161fd6e7183f20d263491b5f068696650f4bcb19edd2b2d7329", "6db07b4bba718751de4f777d670ced77076da0e1a2a3510924401cfe9076f487211fba0136e80b7ecd94da5405adbee1d29e6639d08d1731c59be428ac7e2e7486534326c0f1eb2bc68b66bd2aa34b8969be8a03267bcf72a2614988d293698e1f6f8ee1facf1a7f5a710d2ea6e273d9ed75fc4fea4435a1fc82bdde98f713278b10f93cde09d501794cb11f198c95b52cca5554ff0837ed014d53486f5448a4afb02d8b8a596770c78e1efc8fcd2ccd6888508bc468013d77e0754d9b528e566e31a9f29370163e501f0ef38281a38f75a81dcd6eb81792c2b4c1a364ae7195de27322035814fcea0b5b0f7c367326d2f81bd2cb9d110b812089628c6d705b45c65c2a09f0a67f653a14be3714e1ebe4c26b1461b15c0b57a11df45d9b8a927499b6320980001a459262013", .None}, + {.Lcm, "2ab47cb20fcfb64e02741c6ef2d111dbddeec693682496a816ab8acf03d398d071b023e4095aacfb2e5c27a069ed33aa599a7726b09f21616caed0769373ca75bfc2ccb56c38fd4df2d0ffd0ef78c73e52cb48415bd77340ea1ee54d91fd49769e6aca7fd66ffcb505256b35732aaa1446ceaf3bda557094c12cfef4186563b11730b4b57fe80c6c36d1ab112c5896ce8b9c645533e2", "8f8b32adbb9ef23522f011e4be5f2909ce4ea04368cd71692bd9ba4aeee7196427f4f4a3ee9e2b8be177859d0bf122e56d45129e4aee37785872c0acf5d4d6dcf6d875d06d82416c6c462c45642b7ddce96324da21ab6919b36c0df4e24ca19a54bd1931d95ebc60082894a582100f9cc35dddceeea498638ebe819ffae04b96d925563ca24a167f1b0680be4b3bbe57c24a8a0c595e", "2650102bd83804abb85a0815b662513244c9442a12e0bfe3f12dceee86562a1d09b635ed8c751a241f13ab351369b2e17a707831a15fb681620304a546999434e1f1af7902e7a0b0221aecb530916cf23791f446838f8790b5289e3e9547138242afd03faf5b13e0fc276c438a01d155a787292ae8ad34b70431f3537466358cfcb3210fed2695b2fc67828657161d7a00570533db9ecdbc32b30251898943401e28af56a2ee4520754819cbbe2f1b4cbaf48f91196234e002b33c40d618fd9e40f0a28b035ec227d39eab2741a0e6e9f84454345c63e87655d861603734bfac3451ef2123e7b6bb8d4f53189a1909db398f6c59463b516993ac5d44fc4ed2f79940a2f9ad3daa6b1e99a730cfa264b3581e188708d5211819a7136dd2d4a7a7bfc62f7ff278d8f45b10fe6", .None}, + {.Lcm, "6520a11718b18223ca50cb3a74028febc03497a999561d598c1f9b57a8f2f00e7085c69ec35117ee793cce0c5be7e0233a0314336e1f860d3fc108dd6f98e42446b15d00ce6f3e3c4a0d309a62011a64c20aa3e848018780fc911bb5eec014f410fd5628b8776ca37ecd8ce9afe07fb2891dd40f2b75f82b31e0f22031e278591a960d34854fe9fddefa6f3557016222e321585020e1", "67763cfcfdfb13d65261fbbb9fdd73a25e87c263033543431d2c1416d8c70b16b2184e971cbf35842f26b216ff425a22cc22e3b9bd9c6bf137e31323147e6d86cfbc6a87ee673e430386084b9c08fba29ad763ded85780645957f65800b797eaa62ffb385834c5e81041bd7862248a42ce7d35aadde77a76987c74de1a020396270097927beadd52c7aba21255951ab4cbb4283c16b8", "28ded5f221c937bc26f56ddb9d7430bd33185dbce13ed57272e1dd7c4ec6a29380dc789696cf0edb0d9516139415e2549d2176d2f10928e38d1ac7b5968e93fde94b4a6701c0be4a195b50e650def1c39b55d395be1480c9a6c87aee43bb6dd8facfdb1b75d0d44c08da3ceaf6ce8e4c122c091b2677591594b6a0d8d90808c058e96c5016616bfc7d208ac8016783768bf5432008a9286ae6330cffadd5a994bd4ec3fbd2d2687e32ddd9e350af103cd2a77335cf44ea0604c7a22282c38fa1c10a825bb70a64b2ec48a459da1be921cc51904291c7ccb9ae3f3a6d4e043916c08d9463d6d7e05bfc6449cf004a5ce05ff0338ba3e074003605ae000ac8b78bef43dd7d8a19fa2759ad06878c96c0713608df83d85481f81e7881b6043e0d8193e6533494d2dead3926f7b8", .None}, + {.Lcm, "-ef29622b4a8e8d1b76fbd36ad3c5d912f42ba2ada0932d92d4ad888598981faae7731c6c379f7ae8133a65fa4fc7dd96d6b8701d466208528245733c7b53e0d4d93e9ee7eb1fc9b1205ec100a20e15fd2785f48800a461ab4ae4380b4c6137bec30be043898bead0e2e73cb0277fca147464dcb7104b74f85764fbd06b843ebc7f2f3074bef56452c15e0b1ddc55ec4ce003a4cab10f", "dea574793f7e007d19e728e4510713a990c551f73a32794cfce595f3ee0aee810dd211728eea66490e51259fffde6060fc1617ee8b333e91f999532235ca639abb331e300cfbeb003f146a6a936f00078ccf5dbf80d8b8a9e2222fc62ebfb6067015c3f4eabbff6e1fe34f3178d10e40e0408fe8cb8852b52b142f4fbbe9bb8f1a93fc36314e50175c0be8d2c586146f1395f377b3f9", "d000759dd6ea96797142eab370f7eec7168742fc557fa0bfec0bd392615fbc4c7a4352610643a8a6392401cb343aa2d8ddaca53ee1711c83c469b61378df41c2a74820ad64fba67ba4a56be32bfb9396fa60f920507eb8dd38e13541dfd84046625b96e1b58388c28682a5e50bc8e3aba26969e4230ac7c620eb16f387140a6449a3fff3d3f6e9954282477071704faa35aa15d1a3cf053198e91115a21a6be929f2ad016b7bd87d8fc0d77919619af3a30cce9ae6400e00b3aaa30c2179a785db992e66c115459088d87565c2c53210a34df39ae8cfe442bab56bed5aad3011e3ba8d74a2b503c0a375374b11aeb4932b6f740f32e20ca57cf4f4c4d2a15d4e2648a8fd1a77aeba6e8c5df4b5a88d9c7151a1f818f8295cc1cc0bf2f60f5cbf66d35e1815249ac98decb497", .None}, + {.Lcm, "-9a0c6236a9dcc8c8819e5007ce13f96d8509ca11bb602606227b0ae1142d7c77902665323ae10253644a685ceb012d2e9a43e2c653eb5760bfe04db2b50a334a423f486abfa6bb26d658451ea4d5ea6cfd5691cb2a69cd84797a4be936ad335dfc6e86a3feb48736df2673dad59e2307096dc87679f90d688dea4951724c23e3c1ddb8243d70d94a1c449930382eb0082ecdbbf6cce0", "-80d1701e8f682778f67c2c44ed8a5eee8891d3c4f1295c7fa5e73e1eb423587838f45da4f2ab2e4c0e5a1d2730056f5418eac1b43fe425caa30423b74063f04cbaef88338d9a90c79969e773699be3d0b33409594a5ebd8bd60ad9f99b975621296462eebf0a67d8019938ccbcd1554238ad9899908873f675d3d5704ae82cab575a3cda1150328438995b1aefc706f69a62e3bd764e", "26c21c57a9230b00e433466a9cddb695d4b24eb2ffa91efdf7f472a234a782afa16fbf9b026e93049b7d853ce784301f181e67d3fc22461688750282491b6da9ed33fbff37a5ac96f90a03fb6f4b79f1a1003287fdb26c3e19435742c18a40bdccb3c503794a76b2064f16a4851188c8eaaabced378fcc369a323fca66255c5d78338894a747581bd8026556cac06071f0ef43c9cb0e7e866efd0a782283d4b3fd9827dbc001e7ca4e7afce5b56398bca908bbfa92b803a83b83cf1a7cc15c26fda7e42084f66f8689f0fc07405dc45f3932e25f5a11630bc2c83db14cebd008eab3d98c8af76398e4e288a6d2af4a2fc6f2acdf9073fd5ac94784f9fc75736d50ffdefa6a2c190f9c9d20f3dfb64edd1e776b5a0d014192c971ab6aef75df6a6bb42969774cf0f97480d620", .None}, + {.Lcm, "-2e1edd81ef47b34668d671dd617d19ce2d9ce285f138dd9f824c4292442f21d30780cec52ec688e43ae36ee75cc04f49a235abd58928cce0c160f07bd24ff2fbf6cc4292f65988b39e56c484f5bd252a998a9ee5ef0c793d541e1c01716a2d0ef0e0f25d3bcb9d677b3114bee7dd88171726192c1a690bd601e310fc28eaaac1f6e412b6961486d62d9fbe8807b886eb634dc75579fa", "80d822c4768c087c1d319b479d7122987ddcecfdbb516724856bfcb86080c01b5cb8fdb0368b247a95a384e79b0c2d349cc7601552317db423f71e8b2bab4d0079bd67a63a3aea9301effbb728a524870ec654b3c68bb172cdab0986902c96292a3579f560954549c2748bbe02eafd77a0a42b1d9228bc613e837ebea49991465fc741a0e142e21613cfd3262b9487c761a6bc3efe77", "17365f0f5bae0be78b03faefdb04f0b002b711fbcd8bf8b274591e78a0decd4ea12a973012da4368a0c84bab8634188ec7fc760e902f65c13c3b804ecdd63929d0d3617a1faa0b68607faf02c3d9a4e2f14ded80da6b937d927fb314b5d7d8c7fc84955faf48fd3a20e06b01cc7f33e13725fa0c8011d3b15d8173fcb24001cfcde02174c501835e4995a90269183489c598cc3f35d88d77983c1924515b2bb713cc8d410da42d1724733bac7f5514dc906b900051ab6736f04237981ee6aef0658db35235051aeb03b5951b51ceb91981a20c75dc841ee2a8bc60feb1bda6734e500ec3a48225c2ea817038588e960fddaa8a84d4a648716998a40f9c1fdb5e232face7716072964c914dc604ea6cc78e31425f1c7450f9ccfb5b970a6a60da8f849cd6bb2633519a4dbf36", .None}, + {.Lcm, "-332dff277799c9a3cf5c1c2ec79e317caa39bdf70fe17f4e2e5bbe7109b0f264f21fc4647f9152040251e0d9fd8565aad20e478c0f6a9ba94c0b2c2c38dc68b2bb86b7deb3a522cf1b6c4cf50444f6e488870a6454fe2e3a78190b7e25c51560e5d25a7059f58c9e20a1a47ec4e79c755574ea7f3ce6aaad10ea484c2954ee5e6a495e037e123f6f4cd71c6f930142e063057880bb3f", "-b49fe36162732777d260fc45e045c704d4faa7ede5592419057e2fd4878fc911883aaa0662df3e0804c4872ea6a1f465270fb64c53af408c6637d40ca9b39e461a533b915a550df25c00f8d921f92f72603c97db6fdd480232a7a7c2d11b779321a336bde37fea610f8aa66836d3d74a5a4f692c61b78ac9222e81db5918db24636182fd29f6bb3b5f32bb232fc224de9b8ed087510c", "241c4e6e7af7b887ca6f8ccb42c94a92ede0a9f8453f5d3da977995036b876a69897c92d4d8238b7df4efb72e83d0a25bdd2f45c1e5cf3031db5cdb4e9d60c32467e9a39f9c39151bf452f2b2dba182eaebe77a94bf0dc2db11b66f620bb6e173da712900bb7c929f9276d4dd8de8b3e2788bcc6c6cf7ad5aa21c1e904586d21b23c1712c3aefcf0e7bb206edf89d55905ca460a9a10f3240644419618390ef1f25ba3daa29a89b763ae6a083b5e0a4dcbac6dd6f0eebe6fb88c168155838e71f8c8f6d243ace4c72ec83e62ef9d3f1b7a0140a13923b15d76dad5eb263f0c3b6b8705d5229b8f330ced9528af65926062606ae692359905e7946aa1fa604443f41ac84e8d4916e8f7c08e1d481ac129f71a0a3d4664ab07f064aa085d9bac0359662cb4d10d855a4f80b5f4", .None}, + {.Lcm, "b6f5750c42532fbb0f660bb3dcded85e86a46580a0254d9434ab7deb16c54b6213635617ffe59814524c3852c0d8aad8c280c5dc459bfe9feaf93f757abcaedf0b7aaf8af6207d651bff5898198618710dbe89f99735c6f0504c0749a8cdb2fef2b6896ca1b4a023300470b33a0f0a47b17570e095a4aa0ac0ad55030b8c8af2ce4aa0c45d6f3e774947c2f919d0089efd0c80d0eda2", "7c47cfc4f5300a3e061dbdf845dde192c54ae20c1f72dc9fbdef8bd46faa2f1da00328dd19c5a50dfa5c2a7d4b85b418011d20579090386c900a90622a5b7a7f5dc3b5daec855a7e22bda197cb4558288b4ac792f4622c66788f0d7d4dd63b265be3d70a4ad4fcd373cd14148abf24964251b8d7f71cbb1b0a2601501708b27a74214216aa9d133a7117939b163ad7581649ac9a1126", "ecdb3e0708e13983f4c3af73139f0dd985473001d317f316b2dcee83d5f97204442e5793de70bff902b9a1714cf3a56f9bc61864f91bfb17dac5545ba80c3efa5369c768c1bd73abbba24984e9a189830cb8266104e1eadfcd2f5e94b73962652f47472b09133fff85917935dbe65a479f7586351c26b719f5d13f650aa40f7f40c806eb2e17d1d35c14640f1633dd8e8d24d5122016867fb6aecd1e7be3270776720897cdb1633988276f3369a4f688f3f5d46fab3c5c0657fe3613fa63e9f4870f7143d81ddaa196db2c54851dde304bc7ca2cc829dc33b172020aaa2cb417fe4013fd00ce5e4737efb4fba65628c8bebc6afa63ce15cb7ddd0a83493ddb7e7b7562996ab289b1c8774f5af8cc55e8814f6ef54e1e242b275f627a011b568128190cea606d2d321b52c02", .None}, + {.Lcm, "bccba8d2867e89f4a9dfcbdd2144e1363011616fc60b9cf01f9f2092cc9115fb882313d5cb4c55cdc1bfdee6ccdd83888d3e2e1f4f139321d6b8e5a7ad7148e79ad295107f9203006b1bfb475f598fd229ed4a58c09fc3fec3af67e30b387969e8de048de6febde40c24bf4a558d66193a2926ab81400a578c2d0afe8d2a29ac3d36e2d1cce292bcd23d1366d69d61f406ae4e7ae81", "50ea9e408538159d1308d3f997971368f94f867724f0494d33c954165c640a8667b08530ab4faa9838cafb4c628a3d7ab8bd35e75497d794833aa9f02ed67e2b9e4f5f2998b67f401fc93d25cc93c596ad305621770b4c429b46d222b5ebedd3aca55aa82c716f9b0374ed8aca305d016706cd0535332cab1f7e4c3062b53daecd494d75a1988ac2978988752d7fcecb057d73e41f76", "bef558646c38eb906a4a8cccdeaab5e4d3700f68bad76a806f2e008dbe5c2ac6886029fa5307190bf297e8eb48f13a320dafac0153883f9fa69ce4860556f122a3800db4c55ab0118a0383e72af93e37ef597278f2969a4cea242b977e29f604e6f5490cb14edb2b67b0fe0b73d635497e507f29eacb0515382f9ed72d94e7fd96db3dcbd108f574876246e8d0e302057b447c2ac9e2d69815e59af62304c6235bdc1c7c5cc850ac519a124d8b9b726440a5efc02f1403b61a1ef591d68eea5b3b0822e4e02281564e5b06837e8832f4f0216074d90649eeb2c9e403aecabc255a9fdff4f43ff8669cfc406b4e08c377ddd2a377ede89ae051231d738cd23b0d06dc837d38b5013a2eebcf35c68f67adfbdbe364615a88a30e3936385cce2af7f75841ab69a95796299c7e", .None}, + {.Lcm, "e32a4678a7695a50ddfbb4120d557100ae2608f1cd1f86b7b0339ae278e631810a1703c59a59a857b322722e087a03e6f57984430592424176eeb623ff8bc9192e63a385ca7c41a08469e4f17e99bb3ee923fa850d3cc211083fbafab586c78cae7834c6f149682c8fb3449bad35fd295c97077fbb11a9f991ef13f1f1d699601ee6498bea2f011b6db7c511f9fd5d1ebc3e23842b03", "-209f93e3d29c6c9503a24978bf4b0de303316672cf3694b92d6d53eb5fc88d759e55261d19e66117c25907f45eba8ea9f60c26b75686e46df0cd2067c9baa5470343b7cc3ed9bf37f409fad5675ee42c06196b495f16292309ae65c64961189251953faedd22377d3f4089a98f1ebd4a3edb99ccc7566ebdb8d900b2e03126257347c3c043bda592820f0787eb5af28ca71f5c1b1e0f", "1cf2e34c49b466c320aab6ecef3c2ef9f44f8f66796bdd3fc0aa7478855a5ebfcb5db6daa64983faa19ec5eb7239c25ef4d4a6ffa05d1130a17a90e15080001348d455fabfe4bfde9e5b698b68eb4bb8985d650d582ac54fe11385e496164f003e7a192889e0af8c231ad2052232b3685e1ef1d8e2bd146c97e7b996036e18b4ea3727a439e7b36c567af1586b0365f1a17424b493368e58588ff27414f5d71e4601d989bb5f31e2b119c03873ad1040861ff75a013fa56aab44d783b01384a878329fb22f18b0efad54956436aeedd3d5a98ec1a1655e89b80830e522f1652dfee62cf4536c80458f4429d7edec70743a6d9041fcd50cd3b2bea10c09d3663d6b76e3fae2cd9b77e04faae8545be2fa33aae2e324a320de6a731e1149275947a924c6561ee1b8902f19df2d", .None}, + {.Lcm, "4047fe322c0588da3823ba47cc968f7debfdc28be834e0c6a88c2a333ff7058df926f1644d30d8c747d906ede36d6bed8fe23090f85bdeaf1eb0dd44bd54cd814709daceee9f1b5b11e45703f8090f044b111de154bd61e1b7850aeb371dc01b2d2044c94f3f7dab1e344cd936febbb7ce3e26d78cb2b179615b8b5fd130c3858a73c7cadad70fc1280ef5480bb1ede6b7aa5df6cbe8", "d6cbec05b19e6bf7e3e634f75d25dcce743f122ec003cb9cadb00efbc873fe9e2ae7e3ef436f9821cb663858abf3f17f71c9125173b05343fcc471b7abcf9d4ade9da8d49d6431040f0ed8810a79484c4fde2b19d3914fb159ca141d945aa6a185813b505bf1dc90a5f52ff8a59f78f9a31f980ad6585038b9e52db66a380eafefeb206e7b5c9a13730d2b29604b29f13c7c2124f38d", "35ef62d84eed4ea5cf93184a80041712473c3d337e062a017c7a7cc3e8ba127e642a23ea6a06c916ef360a43dbdc167e626a94acbd729ecd68369104b1ec7a1660ccece1bef6efa88bf0c7c707ced7f02b3cd196e75ba39bb75618f884a951efcdf8e31faf816454c23d7218ba3345f0a096084387fd44549d7c4532c153907f212400946175bedd16373f94cb021346b0167c72d2c92d9329c4c0143b31af6fa3e8fca4677dea909133c6b44b37f26b3798053beca098bff8094cc7486f4ed3af85cd13e361158aaed8ba90e4c097f5b79e35100697a4cf96d8d3b9124ee9b4067db90b65b73e5c7118070b66b829bb1e63a8cb7e8fdde181fa2ed590ec6326a53ce55a070cf817601b61c5556edadccb7fd1f9a09922868abc31855e4317f743a125724b390b64991b86c8", .None}, + {.Lcm, "-2b2fbff7153091018737d727b4b5cd09ba77e2c77563f67f988cd56c5ee0c271efa4e8cebe10cf160634310c22911c554e520c385b429904a4e3af5ea765be51cd6332c908a06264db19ea2d53e04c0c6b5b1269a39a45f06799b94ed4a973ea9051269c124a5b0a40f09d22ef3902f90b1418d6eae611ddfbb2f7917bd99df9fed1276d84aed1455aee9f7d7a7d1492409bdd229a1b", "-81f6c7d19c3dcd56cd9c58153a8e14902f1048f6b56eb04637b072b3cde6a7f91be8082833c7b142083e44e7985faca0675876410b64af386026b5585eca8271db7fd87717b1b4760099d1ddc81400a32a865ff1b175c9be09cc689e0031870c3663818bd02c8ccb936a2550accc413c2a2de77c012c6daa7b2077a910ea9c08fe99173923e464f4d87e544603c507cb642c88343d34", "15ecb15373ac25ed5a364005e2913cd4ec718f940695803bf86c6e678184c7f3342c419aa0b4fee1ea7bca33b1b2ac418db4bf2deed6d3119d86d01e893299380a30c71333bcde39eb963e4d46691e6a08dc0910c535e0692119ae3ec7b58987a51e8a690c6d66e9ab95375ff6f6ccc94d274e79735822fd95bd99a21e69d29ee0c7bdd35702b605cbddc922290a208e62cdd368ed282db9aecc91c70e6d8d1147985d328b90fed47fa33fa43d701124b81ea7f02746979456ee95f7a0c0a54b93d28c66cd1c456482824e48617f107cb3be8d03375622829f3fd57af4a9d46977a705e12c9084454abf46839a0cad07562711f4b4783c8399ead1933634d4890c52a9b479360706935fd23a3242efaaaaf2a3df8b64ed2dc3d9942411639b285bd7c0f06acb98e3cf3bbc7c", .None}, + {.Lcm, "-740ea4beb555998a6858574d3483fe26dd319c7cfcd1a9f558767f6d67af45adec510f1acdcaf4f085b5410e8fe6439ddb01d51a5c2873e23c3c7ecc12f9a3841a2caa03c61bc7b8c843ebf24934721d274c09cde037178d9c119fe78995e2375091ccf13afb9e948e0a12bf454b5bc0d6f35c1095961066f9d464fc303a1626bbb024e5fbe674f776ad9ebecbdaa26507caad6c8455", "-ee63ad79ce06ca7210190bf526138783ba20f7420cdd04c46b11d6453ba00323f56f42f933939b75353184983b1d8c5a5b41da8451ee691fe2049ac041492e8a8b00e1170cecb4a5918913d235e07cc3b9bb6edd9e079ef65dd13c11a46adbd4cf846da365398be0a2820436ecd5baaff8ab76d68499f6ecba6d2b7936391f55cce020af888f2da6ba3a7078ab218aaccbb2047e6a44", "2406447d5fff1abd65fbf1a8886881f1dfd3d6a68e3351612ccfb8e252ab609a7b91753b26b09d4a0e2593c435b6efef386bc414137585c6e2824f5a1c1fc7aaf7b286002b7b454b222d690cf2727abd0a70610962059360190ac40ca008cb45079cec0f02f1b70f53049ae9a28fcee3d45b02a87bfdd3a918ffba9760a8c6d8c19624f8bf6d9691994b502da6b963869d885d23982aa825f62fb387601cc50a79328ea2164beef5feb8e0b6e50ed80947aaaa7434d3ca5f93fa951610fec10e6bab295835d74d6106d64acd1d9a9da8ebbcc7a587d6bf2e941f7f59499fa7485d979e0f45dc6bc31fcc7fb9bdfb942fd91008d7b362b15079b6714595c1a045638b905618173e20c88b333ed9f81effa1db24dcbdf91d705e463f7a982bb399d52eb9451cacd1bdd1d172dc", .None}, + {.Lcm, "333392528a171bb80f23cb2d298d5dd5fd260e1f4d6f9656f05c81fec609e92dac4bfff0fe9bcb99622d742aaa0b1c9c0f66601a58173fdd8b254b59b3150cbc90096954b366b0c311471c012fc35de2e593232a0b7c0a3d015419fe1631424ff3e71b3723382e117ad7bf3cf9a82bc55f4d5d43778c6128770f3f40e333781bcedd5b3fd0431d44b8c2499f0863a39e54374b7b1f9f", "87ad5bd7ee803af9cc567c585e1d8e739cc60ad81368317e7c6cb8e1cc27195f5f71be48bb083805ba3a16e47e74b9bec17caf668e1fabda02fd073af3adbaab1e970ac16b8a4da3fb285e8da8bcc79c944076d8ba4bcfcf476a26f7506b5b08058492582e7bec04bec570e174a53cae6a7a7f1c9632c3cdcce474a113e3c0c37d5d83a0d9d7596a4081e37a62a894dca19437b075fa", "1b22de61eda053418675c1fbaac5c22213410a5b8c56d651f78d55980eedcf9e3db24c4018c77c84cffa187d7921ddaec0ef68ecc429b4a9572617c8ff7112e28c3d973ff76d20f291100e2d7bfca8437365afdd9490db34e2f791f9eb58afddfe1479433974b2776b63e35fdf37a6bad97eae1d5c5d279eaccac985a87628d44a28ee985eadf1d22a12a9897d09a9374d0bb1599165088fc74fdbe1450fbff9e652ca918e699ef00ad36c70c734743c215d21d31614c1d601aaf173b1f4e405e54beb7857f791658b7b47c6bc284d42aabc6a56705b16ddc3f1c955dd0e7329c28fad14f92a5d1ddd1c5af4cad3bdd2e7c6ddc45a7935fd5ea5739add65eeb91f38152079d03ffb6a4aa53697d0363aa483d113aed9adbeab15d2657b95edcafc205ce6170c22dbe2008c46", .None}, + {.Lcm, "8368fe7df2a321e58aec622b9d3c25e2431827a76ebbcef887fb220dd6c06715e49debe6213b361153fa451fc3e18ad0fe072b474c19968e788c6dd386423bbe6d212b24e056c762dd9514dc9062a9cc5bb4d2839e33e842dcbd08ecbe76b99146f8d3523108062353a987c724dc88bcde02802c36bc69da3a5d40256cee30f5dcfd642bb7094913e642577a6c8ca183656d0dfffcc2", "-ec8c07b5929b15f5fea2b98905864d16a1e9b63423def6c8da30776e5608b7a3050a87d659ea0c45528ea826711db491d843f81531e2fd3130373dc832b1457e19a8896cc70560a07dabfb71550a63b4df898c239b1670bc38ca8f66c9a888bc6383595cf898e83841f17091ec5904118b81307483b692f30fbcae9b3ba003e07815e960f98df207aaac387cf7b658bd0ae557063986", "3cb655fe2e00f9107b4955cbea0deb1fca6030babde242b094160face961ce8dd6a1096fef5b7aaf2cd196e6c03d7dd67dd8a8148ab3d5d0fbd692189a2ad259692b6bd0d423ddf20f2ef30573f38c7ccc76da64f09b5354f9fda40007fc4b3e30ee42d00338f7e924fd88a17ab1648e0d4ab0effd23baa91b8ae60f69958a3a448c366ee5b76766f51446b18778010845d67c9b069213db4de1202a2b1c4568d9da9fbdd5f3241c4ca02fd94ac1e037a755dc1aad6ef975183c316b4d038b109efb23c42d7c901a956df823bfbfe11a3ddfcef96c5d0b3aa8b5ba2828d08b18f28aa36d3d14a468387ca72cfb4288f7fed26da8418bde17d556963b660ce3e9ba769eea92b55e380eeb5864786968e8f8b991e78e38eb517398a1a7b6af5b4e160be20286e1afd196e8bfc6", .None}, + {.Lcm, "26c162646e8a562ac27de52f49a30f7387dd1e5565079b94db3beb558b50b13ddc36811170323ad28cac1138ea3a5f05724426cfbda34e986e252a1ffd04885fb0e199d5fdad4850aff15ac32623c1486db0242d7e502b08441b6694223da04882d8e8e345c4f691d50e928679e642f626e684fd544e8537592e34fd5700dad37d24b54c886877ae8d6bd7bd60ff6ad8e1632bffd6ee", "-be4bc94eb66d282c3369364f839ce37412f5fa851290a8af30335c0a7ccfbfc8cc754b312a7e0090b4e20aaeea6d6b9c3188b027d6247dd68016475c4bf180f7913ead4875e19eda61c9e1d3271b1f483e738bb25139462e6841ed78ff11ca773118d25543fbf2b6661777b77a2ef71b168c558efe66c3b571b61fb59b166748b035bc6259d5cf05460889babce9e6ac2c91d941a292", "4cd2ab15a60510a69bcc94235044098ee83e9c2ea1977183613ee76bc1d46802e8c3aca863dc5ee301d509085760351ac4ba8a76f4331d78fe63495844d803533e1c2d5c04fcce982c23f18b64125ba9ace76acc2985e0e3a700bab0db70fc9643570702c94b3d7452891ee58a7af0b1697b60fb3298ba9c353ad95b908668867529a5df069eec53d735a150a254c0001fecd5d197603ed350da0ca138bbf6a471d4d17e92d374ab1f744b13643d3e28546ed7c6e98b9f84fe08be843b690d5678b84fcb8fc0e50801b84ac2eb0fb180e5aab0f15bf1e4f416fafe8516ffe733eda28a88ea4d55272b2ef728152c8c6a3c1a368873ca483e44c2bad5efa9c51dd0b1a8133ec4d4995fade4c5db676b53ba79b95ab67b112868fffdaf5760e15220712f519977f0f0d0edd4a", .None}, + {.Lcm, "7a91211ab1da028f472bbbd25d722d7f68f5ebd3b6913634fcc727e481c1fa4d8a3b9a08a328eff6ed2758fb0e6dd75325b7f8fe5e1c4b64d03bb4af5d9c88726b3f34c41f9ff25d89ef98db429e6045c83622902e6fabea98cf4d0808915a5ffafdb26d244ac8a8fbb8b5874dd4f2e56865e89b9c47c5deea4df1d3a3071d0b329880d81d7bbd959684d82b24949d759bb2549bbb6a", "9f149f7d985ad29ba8456240a983c904b9f749a3eedd85ed8181c733d99b7f009ea1c684e688d405e2c3a886d8164d697a0d795f4a2edacb279c4c6279f1be961a4c3d67595e25d1ccd46a84e6ebbf9990392a2957c229b53f5999f8a4c13958be658f3659aadf1bbb15b862dd3a7c61e3a1acbc4aa64bc1abf44a5c9107080f12eb42ac29859604369b8033e22ac64ef9a792e6aa00", "261501a137f55950c001aaab589e0742c5a8a2f1fa0ea98a575d47f5ec8216ba94d1a27147fdf17cbb40373c399da6ec9a80f4d8885acecde80509db9ef389fd6a9e0c8ecdaf75f376e67e1576d8c1fb3de8ed2df8d780d21a5650e2faf17d4d07071e74e64e58ba6becda7f070b67275f500720e7c6a5f3a61784e860bb212d4efa68a8377029e3ef802950fcdcaf2ff28ce4603af4d3a34115ea203ad8cf2a8093ce6e9b7bea04a247e2c8f856439f5cecdd413c04d81d956421ba5950cf5c682efa583b583be56b5d0df4d5698a93f327a66eb24b5fe06cb7a62917b64e17d212a161d207e27a764da19079470ae478b02c4100497a6798346efef90afbf8908542585ab1e9b10f5df522eb24ceb64d87e35293bedff1db654fa5adb7f5b239556738b8854e911fd83200", .None}, + {.Lcm, "-dd8e21e902844b7b4f94e1949f410bf7752c18fcb2475352884d7c93419eeefe696e1dd2a11ef496f26696bd72901480e61b8ddab85839f1bc1cc4f09668d05fed8c84c0aae337222dacf8bce02f4fee2abc13289c6a45706c3b5446251015d23c1b4f62e92b3c293f197b6890cd332c57ebd89aebfecb012e297fba44b29e2fe7be25fe28b3c815cdf967d4acb1302fb2627dcc8a8e", "76e9bc5eeb11187d84bacebfe319381937f8eaf72038da3debd0dde89023d643da7082733008ae01f10606e0793ec7d0c3ee7e1d50f26de71e9b6d16c4775e221f68ad168f64c3b373a2de84738fb3a742c360c2ba0a33ef826f49aa6eccb1e3d45d26bbf3d025e3ed4b8ab830abbcae56db57da3ec2189a88af48346cba1588ae6d19aea643165bf9a27539556c4faaaec26de948a4", "3374e68265620daf5c14267cb8317ca5034db1b0604e807337f6a9f7f49dda9c61ac11f492d009bec530040e3f7035bd62cd9b1c7f3740f9717d7ff078dce3f439198352ca7f59204c61d21c94bcd05a848fe0ede0d502fa8dc7df477576e379f788cbaa5093d156d78db6e7b5e3eeb42d9ff86863490da7ac6a26af2e80e5d382f3ce6e56a2131ed40b6769b7ba8ba2039b892a066d526c65ac8c82ebc226ff3d493df897a194761a727273bdc34c0678c336904e24af55e33dee8cc46e2d181d75e5bc808e91e84c5e53bbd4f3dfc690082615b6d6e89119595e3133dd081bf1100fc477de690e5fd2db0850fc9e5f66023ff8c9e7e329be9fa1848938f2a4194a6aa9cfa5ee10d5ff8814e6d289e11e199b89d56c6506681b6039bcd1b56f3c908207e1b40a1f579f597c", .None}, + {.Lcm, "570a9fbc3b406094602126b8e1d425800443818a49a71ee1c05ebfab637a2b5b6fe313be6043c08a31ab3702232ffcef959b2acf122ad1102a021ba57b86bdf16247a6d7ee2c6f96f8a9b04e387304212ded33bb3ad297f2b1bb604ded5982d4677cbb95db53f2fb4fdeb2343b7e6d5f49943614b1bc234c97c1eba0f5fa514c205e5e1ad27d35a17e3d7f3cb56e0afc9637c5854369", "-9fd35c1ca26fb9534721bd522381d2fbc7912731540e2d3f48a9d4b486fa59fb125af83193fc46ac9818be6c06eec96560778d624b54531955b1d339765ea86635b1a2c23eabfdb3cdff6dc48cd65a67fa8f29f84b9e2a88080c28e7ccef4a5a716021f07e0bb6583ea04cd447ba1f1b9022e8db79926938abd98a21203d5a831c6110e8d8c1d67d481cf780aa0b39acc65f0bc0c123", "365776491ebda5a0bdec5f113e1efd06ec9c3c4fc24bfe593b8f8f7e0c5604ea9fdbc3789888ae85af45dd1141830b5f7b91cd9660a7132accba6872e6661484c83f3b00859f12b746216fba4b351d5018a7bb13b20e4480fab003d1b0ba074ae41f64c9321ad7e924ca83c20420d7743a7031372166b72a3edfbf1805ebe97edb8599db39c46ca2026066892953d4f7042ea864cc95a69b98a060380e21e76085eb55600d31ea3b9dd19558d0f239cde7d59f30eef8661ff21e0ef5bfb18d0580c6b27ee6f5d60d279d9e54c731668ac454da341d3aa058b8edfd9bd64731528a9ff809507bae7191b8c501061b165b47f074c1b4f3b44d3a2b9d0eb7e4275fd725591ee56b2cdc9379d6486a1e29509442183a39f9ab9c8a3832ffdff373ddbe71bebf073cad588aca605b", .None}, + {.Lcm, "a16556addce05947773271ae303dc1cc78197cfb049aca21107de19528afd7c2a0c6a93b722f5279c6cd6598154fdeef27eb81b6b034c99fc6e7ce40bb1e59d2953494ab932e4b6a1b1a7c3dec31d4f0262431e26fb2894b3cf94230a91660b810a6507acd251cf40a480bc5c7d29348cdc45bc2b34d41f55a437580d2a38143ec29bc3afce984a47948efbb34eead24206eceef39cb", "-ceaf2faf8b30f8cb8a8e3187bb90189d52fcecaf5d4c0dd3d912bb97bc65e2c1a9732638f36c2743698cf073c6e0eed41eea818cd7f5334a78341a8daa6776a3dbe9a763d466bb013cea3f41ee3a2af75256b9ef14a9970b13ac47fe1476e2df30be9027238891527b559e2a3a67c1ee16aaa9dcf2ecd89de51ea491fa80a74b15289cc7079853e7a7a8bc360c7356cc2b3c2c8afc1b", "824dfe166f879786ddbbe43e6c8b71ca8539a9bb060a9c772f1d73b16c3bc67dae7922f7a3b68235a498a43f496bceeb3ad4d52a0a64c097783f453e14823ddf8a43e931f6f658c26f4011a829058ba1385b21ab0466b5e293a00f7a12de33976d5c2692edcc9ef2edcd88fd5d567b27971333effbbd5b3f2dfa2948f4d7cd60e7e4ae2ca8ef5be11e4b48155e640b0eb1c2d74b2c06a752e0f68115c8ae16d17c5bb1b3bb75590ce568fa3418746862161c087cb0883280e1201163613254565d80658c897e94c297fded8af75cea8d39d7b526a3a8b856e91821006816b2d088c627c59a9c50b5f284f4d3c7a48566de992c1020dfece44c6548d88d56dc1e1fe03445743334c561eb7e5683214adc146bbf26dc7ffd2e95e0a8a550580bff47ff07a04893cedb5b8cec69", .None}, + {.Lcm, "-a3c50dee69f0813555a83694d2580b46eff4b60c6a9d655d213a875b771bc2a162b69b6f8fe6e0ab17713528a9791d80e572dd660e47bb9420288411ef8691bb183f6fa0760a781c97b700a80b18c7c18b4810e7b9a7c4440e3d9d0913a06727f7f0a29544907868379eec573df03accabd169bf181abff483672cccfb216838b87c565fe326e5e8dc2716a1d3c695baa82183650e3", "-f792382ca9db84d278ab9e18bf8c4239fdc3662d1be145f1dcbf72bc5a1ffa4eb700ee5a3342538a44f26618e0c1aa033e861306725d0601ca6a1494629b765869390df312a293fc7dd02901c9c778102d33c6c9b668ad11488b33078cbc435c7740c2814cafa92ee5f5c25e2479bb324461fb944b02bc33c1aa91ae46858e5eb8dfdd634ed3aadccc6818d43c9ae9e82e95dfa0b6b7", "34cae39637ebd83d8231a5adcd6d74566f0f42303d3ae2241d6416241d9cdb5382ebc27a077aba1bd75ed8ca24fedc831a0c279f14d736d50f37f41f268b955605cd06dcffe97744c7af57429ede072b2542d988a59daafb2cd9cf915818106861bfc8df9761f7f118fdc4f117546db847d3f58ed21b5012b72650db3930d57cd30cc43dd2b3af8aa131c670363f3bc7b01f519efc5f247bbf1ec91aaf8fcf6b3fad7cd4ffc49cae52e182934c3e158088b4350fa57c78fc527718e272dde69a426e4a1eb4616b530b2bc21da531b0a341b9b7bcbadda3a929a11c63d1ec676cf18f419014bc1a4a14381db7e576722a6d7dc0e20887b82d8c050db1600d003185402f5730dbbcb7429bb385435dcef5c0605612144976fdcabfc546e0535d43b3d227561013ae9bd11bc17", .None}, + {.Lcm, "f43139bea292a6232a1337a426f2263c25df9ea0dfe5096839d95a0da6bac72e787729dd4c34e54b98987aab2c9c938f37f5bae755b9fef41f06c9faf11d6feb90fde8455cb55ce21391a9963ec07921a18029a7e54ff6c6a1063d46c38a09a0ad33032dc9e249066d727388971057b033a86e7fe91204890e91ba41705f04fd17ea73968769f5920d3e69423c6abc7ce1d9f6454ec4", "-287f1415ddf83c214568ed0ac945af761a8bd67f962e9bc2f213d4d0beeb07d5e2d0990a0c2c92593cb25c53b4ab11a9fd8e39724d94c170450535da987f92287f2758198b8b5fdd9ce4e8ab1c292c0088a675681c9f1e4b5c3e974f71863c5b9c85e7c02eea82dc77f23cf7abb3da28f3b96fe51c6b8272b76702b964b7a9ff20057a6def6c425d4b5397630b4a84c49cab0a6f6110", "9a83a2688d05e7c5f88f48f2253bf3c29dc6532e470bd0cb113c3538879f313c888105b6cb7b46125edf88496b0cb090e89b56bd68433680fa663a6d59147abafcfb3e8a8f3dea1de5c73db4e9b38d11520bdd9070ca6ba19be1eaf1ccfbec6e7f82bcf7f6dc9e3e4888ca97aade714351c50d099e45e0f72298083e16165f59320f12611bd2cb041a0f05cfc77395a27d696165a26a4b47eb460a4fc8ee4b7c2d7c4920651f57c92bac4664eb9cae9045cb9df43c7d02a861793e5c33de7c44eba0e32c138be172537979653dfeb7af353261b93432a465a484ca740b0a4bc6cc1d1b361ae4255750f7745a1c2352b17bc8d882a908aaab94726ae921c63caf4d76658804c7ee7b7145b819e45777d0f7b4eb2a963cb83e2ec696a7899221ee572ff03a9374f7f1d8a4c10", .None}, + {.Lcm, "f5a09ade7e7ab10832a1542f5d6e496a28b9af651dab8f1f96fce3bfd088f9208d588ecc9153c61924ade45cc0345bb1a2a251d43ce118d554da63d794e28dcb10af0245d2f87a92b21a431caece17b12b4a6742630abedda3c3eb05f5bf09ea9c0898e8d4fdc27e424305c08b339b4dbac040efbd12f5f3801898b339505fdb6731ead59cc376ddc42409e39cbfa16f403f9f211bd6", "-41bc689d0c87bf3ba9ed0ae53ee28dd4f1683b3f398af8410c09790ca1efc20a3611735570bd54f8bb9eed580aa9a130fb070847627cee3e7e0d3625a31f2236c26f6396dce8bba966ebc5c8de69b9a6301198c869a69f5a3daa1be4962a562ccd8fd2d1758caa85bf72e7433ed62c038f1d57487f01d178c1c4b236888a8f7a67125ec6ef0bacbf7a6629ab5b973a8c0fd7fdbbe9c0", "1f8946d213f896a955f3533bad9da00f9e6268006ad0828f5f671d868cbe400f051787f95227a18cde90dd10730cd70faf75b96b1717e60a130ce9c33370d0bce2b253c8533d0f8dde3d162f64264f970b33ecd52fe3501ffa7eae2c5eae03f4ca9bc65375cd77c6fed1b628123eed26f0e062d8a078337ae5acc4c9ec03638df9ff984c1b0a654929bfd89bfa641c40e348805854ee4de8b37517dab43eb3461ae7b91edacc24e9703232e2ffad93dd19938bea11512f47626fbffe27f384811dd046fe399342e2ac7c12b3c648d6df9b3240c51852b6db188442e147f25fdb057c3039b477d53cffae084e032a97cffbb639d33db4933938fdd14f73b9054383f1e34a0914088d6b25965078df1fd778e6316f082de8c2bf75b1a1221c4f774e27c5e7b70f7bfc273e5340", .None}, + {.Lcm, "-687970a61a8c718b36744383ec7a0d9809b0e39f41e7f833bf54f56eb8d1bc4f319e159b5079729ede91c941668b201280ee88e37e58a7387cb802c556957083e85e9c64b568f4b2f5e1b20512f0d21fc9d8b0c1e5de50274a1ef69726a2cd664bea3e9e7fc57a664819848935fb55bbf0fe789e8598d831d2a292ffde93a0b602cf5c6abf307075f86c439a6b75a7ba027c8438f7d4", "b1994865cf2e71257cd70cc562f4e42ab2e67f17f86acd7928805eb7977071c73f7336f8975e285c42ea8fa27b8467f00dc3979b1cfce7a4547969186ad8effd0811efb3f116ebb297c6d9207ae4fe49b33d2d072d4dcab4175473ffa618a6398ac6f9c22694d3273bd285fe71319319798ac26d87d9310f51537a040470c926f15f31bc8fe62a6439fae76efd5cb88921de52c2f903", "1f579376dd4ed2d2658178313c2bd2d469baf43519e636012d9609f85c5c5be963bfe02791ac26577ee06faa857e27e316a31209a0c36655346939c039cfb40dc0ac061a5d273397d188c453c3ff1036b0f7ae2fa807bcbb0304ff20a1f3611d29ae1ad16c37ce13bc5e79e9cf98867fc48a349bfb8cea0a5cc8625de0c1b4c3ee63bab5300bceb8972ff7cd49c276dad3a7e0361eb4202d459c85d76cbe28323d9817e0adeae1e202ab0c74f4474696a413ccbbbbf65e45203d2d3370f2d7efb76547ade6629016e41e9a3ca66792b4f6cc3f6810fc2fd80c7f36091a057a8b8c7aef623360a48ea11749a3fa1235881f253e112a1bd46f01d991e88838dc19682f14d766367708f0268d26b54816f223e2792e9f4d0880cd13022d33c6f75a5d68298e8ec05be04a8a6cc", .None}, + {.Lcm, "17917e41661ed4c5ce51bc7768d922eeec7cd1c6196433c0572118cad1fd7e86bd8d44e8a52d955850aa398c2f9bf9feab4b98f589ce60f985de4c74e5844c105094015b2bb5e99d3cd33573fa2dddc687948a32137a631d878e562d72afe0414539c8fca90eeeba5cac0f171856083ca3925a8032c0c512054687a2bdafb0ac7ce767b17659eee8e1c3f8a66186723d14e6fe7ee45d", "-a37fe4f8e7f5f9c04b2974fa02976c2a8657de5ace7244e2c6f30bf643867296bc284ee77a06752ecfbf96b641766224cb5eaa788baf6ef9280b72dd04cb8ac4bb26605a49c488c50e4cb2c99440920081b65bbd0cfc524a473895663408fa41d335e0e86f343af1589da8179c3989ada4c8a1e8f1247f46569a4619981cd523fbbe49aca7c1325d0eb92516ff8bdfa6181df66189ef", "504788c97124269a67b5449bd2b978142328b0529dacbdbf9fd75e24da14dd99e67b503a88da6398539afd57e14a215fde7ff626174b084b19d7ff4a5e780901cbd79d2f6a70554bd0e1430b0d5c6c9a39591347dbe931991812768f12ece7c9b8ba4d51458c8aa81804f3bd3d139941e5ebec9828df170966d42e6558b2001a542468c05f08d7cfa75fdf70ca1e164fd99d51046c6d93b9eb3b8e86aa3c0a3cb297d58c9c41651a70bede4cb07f72de14c6c1128b3a23aa3af8bff3ab9af1f88bef9ad30f8b80849910f4409c7d689f4fbacfe7fdc8432e7205703a944faaab7d9901685a9517ddc6e86f0a39e5cb87ae25cf32c1c21d7456f6b7000964f9f7b38555b0498d8a1ea88d4f6fa23dfebdca9b8dd074de17e43d21fb13a3c26317851bb345975b1f821f8a7f1", .None}, + {.Lcm, "-16d6d7f0f4977d524bafca5ac48b8328116de6269ee71ea2cc0c9a3ac64b69fe10c504b23db33de9fff0f7f5e581304960d08fd035f5cab5afa5e4e43e68c5119c8fc291844646a1bb4d0f1e9c4fab73ce48262be7720c2faac922869cfa29c821259e943ce904bad5fc381f3924555cf588e39b53c143d99d3685a88b37d58eff7d9b463165a052a7277e5da9ca26dc3979f04fde63", "5b3a922f6eef9f0dd62e3c7e4205949566d5de5a2805bf17e1deb3201c989ed92654c41082b7257ab616992fb401ce2d1d8f3deb6c66d0aca7b78c67729024a4d234a94d8b07a4f097bb59e2421a564cc930c355c25df56cf1a70ea2d999a88114e74ca81fc1f62e4ea8c247ce1d093d8b1b7378cec13169ad37900cc63075d641ee3d9255f2fd5c4e30485dae939dee624cc077299c", "2b68828c758020d40acc9a8a8aa506c35c4af9c1f3cceef8c0d6ce532329bdadcbdd56c0b5cc4a2938c8a0d4b633779e838ca60e52ee6f2a7c0ca54cd67235ce434a7e54bf9a67b7207c6c03a2c029c1b08d617e365af25c83608b2bb2a9f17fffdaa44e8bf869151d62843ae84de2e66fdbeeea7258bdcc3bc49bae5589c5e29df9b8409f0b639368bbc93c7bf57b4b506f2373c34dde6a86e14047406990c07ffbf2606f4babdff24864db3040946e5b72581d4a777c7127ad3f787e289257f6ba6b762e9f97756a659c834f4296921f9ce0d9d82265afa91120bd11e307543f4294ff3611cde0cb6b83b83cebf55b5f6fca3e64042fbefd8fc6bd9c7a60b8d38403667f532f2aa0e11103a92da75995213a7f41a47e31b7646d642858dd92bd46685d5bc07089e6f751c", .None}, + {.Lcm, "77ea5151aa2eac886f3087d85afba75c70369fd50a9c2e340d87eb22767837acdca30e06634dd910c8812b91762db370e81091f8f71036d4b3770d9e5618f26fdf56579cd25a8f0b7af9fe8c59d69b32d9c8cae24f3f038142293112ea51e857293033b9a646cf731345c14af23ef68237765bdfd3c07d903b27888b403b3d8c61219b66385cc423ec14a4d904a0f4a9edef7ef940fa", "d8da9a71a588b19ded7d43d1d2afd51bf234cd8fd94b56b3d9bc100daece23af247405418b3ee25113b24b93907a9797e9a163eb1d3f06c3fa684d55e8acdd78ea5c4632bdf1c2654d65f3bee5dc904df9a963ce2f62cb2de97383f08016b92bebac7b0c3261d42a1a2af4ca0e05b5f8fedd2f268553e89b274f18c0256f1b5c2318c7038ba360e690a7d5271a144ce0d8f1899d150b", "65941a7e580560d60ea24b44a8e81011c17ebb2f055dc7280fd7368dfbe9572cc3051f55d1c27173ff723f9ec1f96172c3af96b1129efdeb4b463162142b2a7cbffd3a6c9c8526ae3c91f20d589dfbd5654cccff502b7c95e7e62262ffc8d5b63f8ad0f01e2dbc0d906ed840505304b016697cbc58fd43d9451c5e1a71a1ceea3777e065b6e41c5e54b4404f6b532b4b269973f3416a5d524d29c41588f2477166720daf3eb2637170d9efc1b6232944a5b1f4e7ad1191747376fe10f80fbc0cc25093fc473b31008fb43b552b2b10171a26d0b1699de736f21ed660e8743906767bb085d16406bf1989d7ded93a27467219388f933085d658ec5aac869f93ddeee82f34b3af797617ee41e030245a703074e27d0f91ec7986cad7a863cc6bfe007e060c74df3cb18a5c4cbe", .None}, + {.Lcm, "fbe717cd836a6620360d9c2ad699da36250a5f17098af3fcbd3436630653ed71785e02540d6669915dab16fe6ab793793060185968576151fbe3ff82ca80dee40853eb9626230d973d14e1ba60b69b0939e0f28ed68abc761883a606aedcf2d58add20b679dda54926fa87b7e652689408db5252f311eed942134e83603e07405bf34b72aa675a0688c6e0b2caf9eb931b5dda311af4", "-cf196915a537549db9aa9b70d0d8d4badc45737bac585719ebf8ff5e3f11da7d115bcb13458a5dea1226b2ed10871cad4791c3de2682799bbc886fb12e15ae53b0b3792d0732a4bad844a4da7210a37c0152440658ceee8a0de05c9e496049c6eb270aefd3681a4898e807c1af92169f782677f5aacf66e3ae7d576464ad0dce10856a882513632978152819a19bfa478fb1d42efd8d", "cbc8dd37959f80fb0a8d97df5ddc74a8e4d7dfe918ef11f7009aff022bf9a337abf003d7cf9415cafd705d48e5590632d6ec947a0735ba986eeac2d017651eab87d0b9267c440c89d765f9f4a9ba06f3a71ace3fc3c149bb3f29b50d9107cf15e93ec89eeeb584c47100fe5768d8729bcc84cc47acbeaae13b7c950778e5abe42dca02f3e8721015daf1a8ac01a4e3420dc916300ee2eb567c2fed1f78142ec39ef71af84cd5c6f7d30a05a1c853d67f21b6440677c91495e7b221941a0c25a1da42c74301da0ccc50e16a69b36117a26f514f098f842f481fd9c6886fb9fb8016bb3c9328cbd8a25d6e065fd98234e579bf0235264c6fb0f118e929d861bdcec6da1663ea15e13707135c62f97c400bee79c6d61aa0c8e717c9aaa6fb3b6accefae8701d14da12c9c86fc64", .None}, + {.Lcm, "3901d0bc4222e477af3f7d8ec87290240b3c4f32d0ab9751a7368e8a32380761953fb131a4e0b4e93dff047000902d2aa91ccfaf7cb57b2469c9d1460abd12e276c90060cd51c952bda69bac9f9862ae174af022d8d4b4fe481ab79eb76b3734582bf22e81591da4432bd31702c7da1dd6af5093e21d87ed270350dd436589dfb84a325bed844ec1251a4f06b7069f9e895ca502745c", "-a007f9bcb897b7f66fe7e329055670c79d53c72b881b4ad5bf4d8db024cd40a225b160158b7eda95cf9766c2fbf3e29ebb3d8a0f4f5f2b2a7b26bd7fa77f3f9503b9802b6961241cf628d4dcd943f0789f64b6501bff9b8555e3c34665bb88e5050ec35dd60ac548ecdc87d278222abb5161ec94076aada5d49fb9bc4f9d8130c8e4702566233c82d48fd6259441f7847e9a5924f4a7", "23a2e91f28f31b642a1a56432074b92a33dae0ecd90668e3ab5b6f326a9a9f72999bc2979a76125987ad6a1a491e5cef923c43bb0d0d9d2e143dee8fa58ad147262b318e58636af1ed4f6edd7debe13eb4e982f8e5a4e1797f11973a20ab742925d33a64feb88a50a837ca24d2b05c74de2c578d69cd14c105120c31194922d67ccaaaa84377f22ce96d8ed79a2494e001ff4621320326daccfe59a112c9dbd83c984f3eba46612f09fb5b666b1785ee2d619affd2e2d0016f652e6a8f56178a70f231522559f1afa89e787570f57c8dd87ae735e6c005d72ab3be77baf2eeba500f984134578a9b59d0f22c0ceb2ba3751de366c7c335a5ec9b146cf812ff9142b9ab68817175e5774f73cdb545d70612ab8b1f31b8ab2d48880c67c685e0d14c65af58fdec3eda54719804", .None}, + {.Lcm, "59252dddbaf7ae29583c83e93564e19625ed86fe01b9ccfe4aa693b18caaedab265ac00ec021d76848cc5c88ef794fbbab7401c2f3b704a112725ef18aa222eeb7b3229ca04b55877c8204721a91b34b947833e56289edfdaa1689b275d4567767101921ded52c329169acbae11030b273af6ebed56e2ba5e70e508d8e779a18d323bd22538c0fcf1b7b4186196e4ce6ba26b74abdd5", "e0533f42379003cdba6515d6835bc3e23e4c6a6cf1cb79b420a86347d60130d7df332a71957abe9b18abc1365216d42bdd665fab4350872c5e20c98f70acfb5d0d5f26fc2906d2ac62c4b08a4470af09582d0a7d00579c24b2dc889f6e4f1c3f8e14e56dd5daba14a4d8f2663378c106e14f03a04c363f51c05f30b76339caf8a59a1e34f99511337b87c26a751877222802bb48931c", "4e1d853717b4ddf64f6f8e7fe1e4cbba03bf47cefcb71046932fb0a4ac10d101fcf1bae4867fe413f21773ce11f7335b76e85cc5c44731dfc9431cf261af0664579a24004404bfbe5400be3eb4c157f40bb6f6cd082f27637e346d66b8f155430e8149c397f2e97e2b7ed6c649e5018a354ebb162a4feefad7f3d26ddfe90ec09aec76d93da058723833b6176193ee2bab5135325c789fdc144971fd1fa9e876c03f30a4bf253d41d04751d23432e079ebd20689636dd77fd606ceabded934844aa164ceee50ad2c80d18f760a211bcec08e43c2ce278d0aa5df108a63380c367886002bea148910c445763c996a60e8742f2345ccf5a2d8b3286042d7995039ec0186cf7d19e3a957b0a81ca5359297cb78e98dde78fa2825f53398241330fa9fa9052bde7080d5f216124c", .None}, + {.Lcm, "-8b5f09eb2bdf0220aaf8c2a6accff2b0ad36b771fdb11f0095a06a9482548dc10feeac9f541ada42d1d78a7c99bf02c1817af9752371cd4ee4c9335e6199e8885238c33a4c607b6a1d2b9209f5f81ffcc8fab6efb6caf929b7b9cef593cc12adad6490e79d6af7071e345e9e725f821598deec8db56e1d223cd1be0e316ff271354ca8c91a9f072cfbb2937d7a9d745cea50757737a7", "-de4e9058262fed6fd7c11b94745115f05ac6e980eee210f238932349d7582d65c46e981415f46fb2c26e2c5a70a57b839d0b67c640f755e4a386cac3eb540682cf237ca6fefc56c3f870f89a21efad805a6efc3a3495ef42b09b18d1903408505f141636ed8e8d87d2f72ab4eec806f4c44bfdc1934a896c5897f51f65d57460791c908b06a68159b9c099b577957e1ce69eebf8154", "7907302468bca67f1a9d0bd518253e56b6580c070ad215d06194aea393b001d19adaa2577be079d98c0862c7f0ccec75d169239a207e35cf3c7b38b301390a1826ca489c8273ecde673629f2d1b76bf7876ca94a43064a48977887b7281d03f73756fc613ec0ea7f90887cd9e5cc25d7939a00fcc3067261df4ea7dd8d4defc8e8bc6806c0ae1a19f08b4e46c0e4955cfba9f7ca383b60795b3cae2d6d47a1c547758df77728d4860050e78667b6b1f5532e1b316389e554fbdb682cb516c42edaf28bf507a1b5106cda839c9c720ade63a34c4129deaf19617ee3dcfe0675b63ea6c92938461146650110364c72104e19a41fc7209fb6a3e0f0e9e3c423925b6a2771ae815997fd2e2db74e33ebffde3adfcedad3fe72f23d7dc6405728be4df49709d67411cc665c269cc", .None}, + {.Lcm, "-f027928b5cd2fe1a2947e35a1ce1b82f07b94b39d45d6a47b396d7ed1d0ad38e05ef779c091eedb6659cfc68b454ad7af760653885b6faaf3d083508cb1847570f866bf688e2478924b2f7120a4b8d46d155bea1e110350c541c7bd3268543951003e5fe9653b3adb394d1d9eb392a4e1e1dd1e028ca6fac76e26cbe9191a3b642ae7d5d9fff088a3fa4ec7e06a9d3477b01e048fe6d", "7f5811f0872bd2a0bb6ffd76d68d2b7c1d08da5429fe7d4b09fff0c5294e00dad3c55663285240e97dc9cad63af93360ada06b2d07126f3f76b33aee88c97596c508866d2ea31815c732f174e5a1f0c66e258e3554ee38a362bc9efcf5b74305fb0b003fd054bd97cb45e446db7ac96d9a4850f6fec8fc3970b3086a0eb454489478ee2787ad7837205430942c6da95be9ab0e2d335e", "27d2156097dd10f93cc383cf9c9d6fe7064bc80c414d899d59c0e95254a866c0bd4311f63f9e5b535593a95fa42b713442746e2695ecc0e8358109d7a9c0d1903d148a0f1e9210905082a2f5d6c612fe26b5bdb73b54c84c44580b16b5c105ce582dfeb562f2c1639dc00b15284c77779748e2041dc1fc42da14547d2b02311205f40b622a381cafddf365f5bbed4151735f82a66d8eddf09c0050dd55faa5eb589cac95744f930b0084edc1b6178f5edcdedcd6ba8bbb1e6eb2af9a93371a1b0b55c5ab64203cdc91c202c20079a1791790e29205197c45286011af9b3fa6041f33f344be5847f588e4f16cb2b2fcdd4f836f6febfe5003f30da1802d910ba7e2899ad576bbea71dcca20a6f33ee7c98af32795aa1bbe51da8bd455681d6284b516b9d0bb23b44edc376102", .None}, + {.Lcm, "67b20120da59e64a9f0211ab8ec9003ef2a680f6e485331403943deb709a6959e464962371af5522677e73d0639fdc75fc8b9632a82525a762eec2188da3d46ad42a492b9e36325b8831be2e8666c08275af957b1526f37e6faab06e24b2964da369173caf338badf37d1ce6f8ff55573ae181f4fdaecc242cb9f5b638ecfb4b047579ff0d3cfd09033c9a9cd69853a2db934b907c26", "-4e24e045943b0700944c4661af8b325f34d3b8b83842ad361445f68fc47b2617cbb9d396e9d2002ab3c1a10b046473dc8ff7b0f287c85693d2efd82593e6829ddafc90dcbb08fe0dae7c1c899278329598dbd21d804238fad5aff956bb22cd4cc6d78da8b67e3ed5f870120b762fd034cf426b80e44dd80c16b32632f57f70d0598b28d15a656bb03696ee0a21f7e82fb7404722b6fc", "546875eaf3153df54ee39cac72739ba2f70704c683f555112d18aa8cf0d024a8e3013ed37fcc0211679f0475e4570c69c0ac104d2acf44beeb00192b97193748c728a7388dc9ef1cc8cd5e6b7eb3e9271a12991dd1cd5a373f7d585cb97cea0b70c93793b2f4a6361e6e31042a81cf0318c61443d34c5bbd1439771b80485151d4da15c35caf9415047965f271c0b383c59e735f5524c4c7ea1f25a318f6eea362f4330418a3877648c9cc2c6e8f606c7c839a032b5ab6b8b0a37769ed7e653fb8c7ddbcbb38694c55cc8a5ee5c375b864830b836355bc37948a601ac6d3741711417320fde071be66269f6859f66c2889e246ab744032aa599e7d252504b00d3cf45126fb6f96b76dc1d93b7bf0081effc72ede35ffbd43f40fc725afb47250c141514414c074e5aec343c", .None}, + {.Lcm, "98a5e88fd46f2aac53cc687fbc565d2436aef9c07d6f892adc477f8d35a3fc05c8149113d2624882e77ec9b6fb1668935db587f52bf6867c172a3f80c2bc4db8db110d4c523cb55e5ab4f706b6ec0dd4ade6e978a25c39f28022f5d66a690084b00e3a919178f1d2d3d3d41d11ee5a8e769f0da6d9437a5d6fc987e72bceb7229a9cce366b185129355261f4bc4b6a611e7292ce2def", "5a1a6341e814774e6feed708ca306e2cb3448d0f95b6e5a3d8216cc0ea1fca252eddfb0e7926f0aacc10f262af3f7f796383ca810f50fb4dac9b358b9d7560a007a0757866b35d5917e2dc8efedfeaaa6c549ece6e4e3a2212f503bd6b8916398db8b0d5436dd3048bc1850fd06e240b2619a1022cb904c0fa3731882cdab65fb5b937ea0c9cab774e62a757cc520b1df150e43ef0fd", "7acddaf60ad44f99b8c9bd76a36d6b6302a3efe7921d9cfd8dbab53d7ded3f72f8c97d501beded1bfc73e345a174241cde47bd621adba97cc969557944204052696f546693affa5ff4ab649f853027a74789930941b2fb8ab77d9ad996431aa0caa94ebc50ebe2738d171cbab929508079b45802aa2f7c4dd71ace939a7320b98d5998bdc8876ff514ee8b55a00b77d0c76e95c98959dc41016b66956ddd860cae6c0daa75030028be593b99569e831ad6204afa6c5a9f2818ceb441386e44eea8484ca5591c7fcfd119628c33416a1dc9ea2398f3d36fe0c9ee4cf504e112e56ab70b9639d2e4fecb0b60d1a7c5fbc1b1f74fdf6d44f185553974ea708da64227947844ff60053f9daefbf9b6306d00ae307868717e1d3501110fce58d3810b35e02f86f654a7c0d3e7e75", .None}, + {.Lcm, "7582ea3567b65b615f830a77579f918ed8f108d8f40369445fd0168c5adbde27ec35c63599c786b1a32eab01436f74469d2e109dcd942f6149df16243f866fe1722af20ce1804a4a4ba07e0cc8391859553fd244e6b225a831a5074b6929b670ede31294230011a41d73a76297873e0e679ed8361ec4efa076562b334f38e08cb66e52ef3f24634c74ecdb846855902c78592708cece", "-35081bfa6643996771a73c334a7e6c3b794a8d41b9ceb67f4f2d5ee30d0aacda9a1866145d1724673235225be48ae82558d17bb0a46427ebc1310f24ef75ffcf365369a4a7689151cc489e9bd9b7875fa1e57d5848732f35ccc852a5dca193bd9cc880871e1b5f18ae3603602235cfc8f0610596d3356317de3060394f85d0e405a69c9cbfc6501737881204cbb4c47d1635e205435a", "c2be9b60fd0c4da6a541039922079d8e583bdb1c3696a8e646d77c56372449c022f5fcd071df3a9dcc79bea54a971c86f5363b7e8902b37f4472884dbe063ade47f937bce52d648c365df6d4ea954c8431d26c5362adc27c635f0f7b242be4172dc4bfdb3c2ada09b223b72a29694660b2f29bb3843f73f6d92cfef30543a93f562aec2e365c080f468f817f0363cc13d4e7e94e8c1791fd6f966b5e3e5d0631df510a876fc9de15d9dc21e0fb0b344644eedf0e06b452c5a020e009ec013a1ed11b53c2816d66d892f66e499b9f1cb149b46f8507ed761bd1ea19e1784859d65f50af82427b872c0b7b44ee44dabcdc4588b2ee8f32c4fe88acc5e112a6655d6c8299da5c8cb2571a13612d23276812b485fca537baf75e89eee88f9f2ab909e96251bf541d979769f4f36", .None}, + {.Lcm, "86a1f7fc4ca77bfece050d517a64e072e4207b2642aa0512af5d98cc1103d7fb94f72f6d7dd9c9c45db6b7a7220dd41479889b419e7f440d4466f1345a46cf819e431785b59d39b09044d0ffeba9e97285e11ab775bf2eb5d9f4897cfd66533adb3de376fc5819b190b940b3d42f011285a93aab9aa58b0cb99184824cb1b9c8133b69a33f6eb84458f2c1aa009ee40eaac0df28247d", "348de8914e2b88471dfeeae379c5060e3e80f6ebd214e49cd599e4003abaab142c235d7898c958a68771018257c9da670456d37106edc18e6b6dd19651b42515f1adf12fd70b3deb7562e7fd6fae565d02e632f233f6efca9b6264b980ac76f720f5fd9ffb5f4230ec51fd753441241d299f45e8ffa3d7f720915f184ecfaa4c76ec3d6f918638e9b4bbde72c34631fc0d8fc3952fb5", "1ba387e4091e973d3998c67329e8e549e98b486ef6b2d6b8fa3f42532630013ad1c17be6b91c40d3e7658b2b803a4e4037f70f5ae4fd27b7ed4736c223a04dacc385815fb4732a835ea692e87a76e2f6c8e158ed0b5336b99475f597756dd82f66da8b5a51d14a63c042dd3507dde8220c3cc1dc25f7424988eb8252a169f9f526d51de887fb3c24e502f7794c5fc8b32e288171a59c42e4f4df1b7e4adbe5cf13e24b25914b9cae14cf72cd04d5b3ccfcfaedf62af3a5bbd082cc7447881bca97371e42931945682306e4abf62a38103484f03a806678e2d12ec61cd380a997ca71ade732c0bdfa71a4615569ce76da60ebb834daa829f7d06aa4d29796d995bd0d503e782a455a32c7c135101a0b591ffb04191a71ea308317490ef6bfb89de9603d8fc548545199d5bf61", .None}, + {.Lcm, "f297ed6b52d96db4a83c753af93b205aa9755a491d2d8d452dbab65888828fc02e24abfc003027d9ce8c03a12541a124ec25d089f6d8e9f50a2139caa59226e4473c17a9398a812a04cbf82095033c08b18ced123fe0fdc5d863e03fb63ba92ab26383278b5de8016113f1666299824de2440d8ef7291d42789725baf05799e527e571ac6de8b7a707f081297e2b89aedd083209774d", "-a4ec05a4a721f55cb1b4c0267770dd7448b50e7d0ada9600247b461b621ae5c2817f9d618cba9c1b8ef99f9ed84b0a78caaedde74d2e864b193051524442a48367580d986a1fa16fe349ff48e06c5ee90acce63bd5813018c23d4fa000845f21c9fe6bb8e7c084ece74078cfe5850d902f0ee157058cfa74e75d791a217db0c13896bee68fdee4c6004418fb11eaa708307e944ebd40", "9c48fd809f5c26120bd9835f32c33b9126d1e29bf944dda8d1c7ab961cfac57bd82b02b62ccb410101af70d587f20fb73d11101260e3d8ab79539d6b298cff1a91b164c55e1aa81e3fefb2b3c261061938e8d84c92a136b4bc9b0dbf88b793eebef2a83f3564072e1bfd9c82daa439019e3086bb1146d385c7a6f8d052f4303aafee3d3d039ae2192c6d685d09c116bf6bdf0bd104ce3b5ba83087354a99d15222c03622695e161c763eb7ee0e2289223cfe11db9067e3ac8acc9a8754488a5ccf86a98fa014bbddfae8033596f0c05bfbb7c901c26b8db8b07eff6e24f9cc193eeae0a3abe6749083d98db01d2d6e3a1054ff5c50c06f197ef210bfb922fe40a8dcee1aea0c57267952ebadd7c28b3f3a1e5ad2f4a9998d0a15d5137922bdb2e5dcf483f6c22ebe5ce7ac40", .None}, + {.Lcm, "-9da34904a60a48e0b103c6506e9f4c0e41ebcf0395d0bdfbfd746e3952f5912c273397c75ac63e2180b396fdb1f6866ed5cb95f5d0bb5b223b8fa6a2e574d2a84cafc9a3947847d704f87b0e1e4d636b4e08b9289af845317b5ee83a39f35a0563192a75d0f86ba612c58c4362a6d11f856ae8714f89bd3b931af862c658349052e93cf7940d937bce3f8673af5a3f4aa29666513590", "fe606c9d1d2c2edb3cf8f67a58708f1ba815b758a667ecddfee2f2d09a51888d353634776bbf3b187aacb87a37afaccbd532f545042a1a5021546db6135e2b4c7e10031158692fc95b4b043df4657c4dd28770e472a525ab3b9e1ac368c26d289a128eec118471fb9c2e06d4fed412f1e7d51933635afacaed6c48a1ff0301f3a4976f9106e2e711aea60c5e559eaeb6770bf87e7014", "2728d8a3e8193a903679cc2410d4a83384dda1982e86158f5c52f47a4ba5c52f2d3a2ef8f542b376f15b373aaab5dd95db041f53f93453fbf35dd75c45b9eba97c56d401c77341540f25f34d36139bc4ed26f4c03f4a61336733e7eaed8024258e2c03bd1555d7a0a91ce0c9ff8e8c314c5a0d99f49a9f15444cff5db7bbb318d2324aa581f25d49c66839065ef87985e3ebd559b2da1d3e5272e561d4bcd80cb78207ba64b487a75559f48ac61d0039eb313195f86026b581eb29f29f21866eb87944f7dd7fd339f2de5c8185a983ed260d4698765f3eb6e18c5bad31e9f9ab105aa83dcdd54686a7619ee7346f45279d8bbe9d00e30d85ecd850166b0db6ef9709d8e8883a821a60264da44766783015ec951828af386685b77d28fb71e83de6e156015af7b163d8a9cbd0", .None}, + {.Lcm, "-1d00fcd1cb2773ef89221ef5333548a98dd6b851643f056a5df38ff0e5f55c261717051589ea3d6e4df2afe78c206f723c5a80a0e99e7405b3c302f6683fa2f3ba5d202ad598d5869c095e1cfac884743ea3447367f4a3f3ae21f9564471aadc42ffc4eddd26feb868b0bcfb99a9692702992d4f57e4b701b07bbfc4025ba858b09997aac8907f4175aa971e2bbd66f2570ca2a4690e", "44c25cf09bd2e1e2480cefd3af1f967431a00b65cf25caa7b13fa2bb9e27286158f8cbe1be1368e70f30e7e3ce259a675079317d745e1c450dbe0c38dfb1c38b73fe3a61a43f602ff7adbad736bddeb48610ff694af0103874e425aeb7f39811945ff6c7ed9538ed241ce4b754365a7caa0bd6680f3e993ed4b3afad35e8a3b51dfcd7247a20c0aaf64864fe2e0f74b35d1d25840d8d", "298c2cfa4cb71f4035034db71d014e756ea6c533ef96d8159f018172e445c24803738294580dabd921c1afda6f182e0ed3d06d735328e73698c2da5d3ba8a29a1e40dbb34ec6ead7d3404d5ad3b0851d5aaae42167920d433eaa6f8c4cd4596b6c3cb8943c770dd32feabdb12e199bc05f092b071852cba6767b7e10315970812e0799578967fc4c74e1804b1dca8b7626782c9b8b9c42a2a2615f9f6b696b19d2df8f3d77ea684d234a36ce98510ea6752bc7214bc168ba3df78de53d0df9db253069f3aa3753f8cad3a171ad9f6ee5ead602ef5214e9edffdc86c2cf696ce8b871d9baf3312a2dcd01f8ed16cd23cf4d61288dab99c2279e60a28b1fe94c085d9da7fdae2ef000dbdb92dd18567880558aa523f771e4716328dda08df6c70eb7662fe8e7fbb965fb3db92", .None}, + {.Lcm, "3a55be124322f6ef5aefb4e4dba96dd9266a56d6d4a85f1117c54b0190b82a5636d44dffb16615f26bac61b5555a35bcf8afe49b68282fc2dc0c436149055df219e1316d6ffafd08a867b336329078b2fd516c08dd38381eba2d96457b17594ad75e010e260cfc8bc67e818cf49a6ec95c2e342d0720103cd44a6ae467b72fa95cfd6d3b40e2383dd991f17143ecefc62730a15eb709", "9938c7138bb6e29c10b7f373097cee9d2d7bfc5b6f89a6c64d65df0e4333b25d3069f4817c51c7da2c33b498d5852fe1b2b02f1232bdb614b5792eedcddd91f8ee5fbc95929f35692d6ad38c98bbfba99d889829f8b40f8c6870aa1782afeac504b6166cc7fb2f4ab768c3b9503cd67634560eb0b3a92af2551e367dfc4b3b6a694d111d128b21b695ec83ec2ecb9169132f28dfdbce", "22ea2eb799121d92888c7afb57f29a2bc7ea1376cf625213a8596f7db87fd9d4999cedd9967b2c080eea9ec76125571681d572cd2a67e9b412b5d82ff5a1b9f14a09fce91d51ffe8a6fc12989f135370a85c586b0cf5c823fcef6982691695966402f394fe2680e118309899a166279798821b61b5e762728454477eeac549a7b508a62e32ae6904a620af476efcc7d712cde29355a337caa141aeff3737a47cf676fd775372abe0a4a3dcba57c81b764c24eaf0d4a5cd425fe68bb5426b46fd1403289efaa7eff41299470d5058f4b9b28f881a8213ba6a902ed57185566a1781d012a3d4478e24206a513ac1134783d24f239c28943e78592523dcf3a631eb210b4092cf30d5bc1f03c2133b6187c4a8357b886064abf90e779bee386698dd0a0993130537c6efb9a2fc3e", .None}, + {.Lcm, "-cd40f05ee536ca354b0ce8192129f52253d0f824c580ab62ec8dd28b8d6747094e0073a41a265866aaaeb64a1497b1d0b28f3d87b62d253f277b21d8a7f0b1c869e5dac74480cf3bbd090c9dddd26f88f14188f38bce8ba7b31370a587b614af6377f5195cea8fb2d9e6cf7f987757962dcde8d61f9e2934f389793709efff3379d58c78a2053adfab6fe59b02314d1a51f6a04515d3", "-18ff095fa3243f6aad55baff96a5f4f8543b9263e2bbe2eb16246ac83a65375be1b77a2b2876accd9ea7b3e5ace8fd70ae1b4695664aeb6ef608f533fb971297df86882fcd0026c3b55b6907204438620242091c7a2ce896d173881d3d7df539716c131ba401ad2dabfc6b9f3877b5e09e1107d034716c920d380234202e9f2bd5acad0b70b48dcd0120058922c320a769e56d68161d", "140a91bc4a5d66d522de801da8573768e045eacd1fc13f35d4f38dd2ef13cc3221bd07660e2f804cdb3db22213225c8cd3438b5d0d697c5401cee849c576689f5452ba41b3b36cfc02c1e57e66f974933c6e9fbf7c59681ebdba9c12ce746a475234c52c78bd5763fa17c54876d9806d7585c284ce7cdfcc68c9bc70d32803cf4c9c0782d09a94ed6df5cf41dca1f8d7a4bccfc7713833f2b26442d973b738dc87cca98a237ecebe2404e0e93338a6de3933f4890e380771044d1311ddd33b22564e7392ed7f41ba25bc8915b0642041ac62e881e9f2ffd95220300c29f167cac77d800c9c2f93ee01ec1c833d972a8ad0b7e978688417b29f6b95a75f2291414420da29ef46538541239a0ba429abcb1034539aba2067d6d3b19dcfa461f15f552052ab9dda11d0cc6b9ae7", .None}, + {.Lcm, "3eabf6f215d606151c28a8dc40d95815ca501413051f1bded1167937d61e2b6a9b82cf4ffda76781fbc9b3dc618039e926fcbebb0ca7d1cef8a2e5f66d239b06e7aacc6dfa315ea7ce45348dec2881c6c4a23d55b1c3f98926eb6556624eee8cf3fee15a612ebb26d42e3aedb59512117e02972328db62c52572dc76dd1fa8cf7d08f97a772bf069bc45dce2ab6013e03e0da1bf9874", "23a8f411dec55235bee7bc851be3427d72b0dc9e6f63ffea830f771e1f49e7253c0d19d51d0aca064ae804359250a61f7a2c93689228e9ee59580a70e50032c3091a3f93a8df559d21f3efb668a2710c403119f025425fb200e8df5e28405c4dbc107c76763ce570ca48427ee3700a3b411e42d4b1c5d1b8da8e06ba16042f606ef487c93a8db0ee019b03a4e5350461ac140734989d", "8badf5d6f2e28c78660feb2fd24c37944dd46b4319a35f2873057d63d6f2ca9d37a01676200ddd72fd55035e6d7fb9f8d0970ed77ddedb8ad21cf066baeddb56d12a355e1e6fcd6e4e9657d1a5ede2f1874fe7af431e19328f964aab354921501d514dfaeb6540600b933935bfe30f4367a360215a546e55f95426dd51ddcc7e5d268e44709342069ac03b082acaa0eeeb9b9268d88291d5791ac5fea2dfaf879090843d118a746fcb5c08312a8740a93ac22b1bb06a6fb8891fcea9739d90aabbb2a74f9baecd2b1d005d7dee067ba93aa1c0e83fb290e7ee29bdc86362c20cde6ea48ba0487787c8c328f000a1c93bcbacad2bf153b8e3a5763fe6555ce242aadac8de5b5835fdbf2b1420acee1db8f687ff664e97aef1f168a83256fa6cb5414eeb440e9178c18955f24", .None}, + {.Lcm, "c8c0b1e18c3aa201ceb870fe0885213d92354389ee7ef821edb2560d437444e22ab4dccc562e1b1f274c2a51b1882bd6e4dc45d2ddb0d23f45aa233c6246d1e8cf509ca7c610133dd0ff0bda34dff9cea3a70000edb3bc062b591360ea4e1b355b089451a065c254149cabbc00c4fbf5c0020b87522220b0ee1ecf58ac58ae152879c8873192e1d08ad22f1ae9b3f265500d68e8da47", "1a3607c3234c78bc9a6085ee4c13f775922aa192756b419517d9920914494d3aa4c301c213bb87077f580d1d4939c5128cc71072400f0df8ce2030953b44cbed99fac37670ea44bf9fb2bcba3b8e36b4105df69558e34955a65da8da7b248668cab9641211ef3936bbed4a1458b698d48166b61a566339f21a9ce7762e97c26203ed9bdf7d19a54f04c11e03cf4728a131c5e3c78a7f", "148df0ccb92482aaa58d67a150fd03c6e38c206b4d5a7d80bbcf094acddc159eadcbc1a03f68cb01ce526f1066583520858d0e828df074701d15e254e7af557db74b842e9819c2f6082966f9ec6114b6fd05ac573cfada6ab129740869b6e56248cf799c6480051fc4edf3131cba6cbaa169d676c393364b4dd2c66fee6672c32cc00570778b4a35a09db65916d08ddcb888dc31b11dd62192d810efc2a9fdff883b50cc0e3b98c25bbf45271ad19f338e5a7e6d0fc2eb29c49a9aafa8367f66f91594f4fb528fc1753dd903b2d2c3685e5eb622f9e728a8cdb63b6854fcd96000d701a673447657f1954af74b2117c8dd4a44d0b9acdcb64312e6a1a46773f07eef6ba3f3993145fd2ffec8ea6476145f7014f04a3e42515e4e25b3bb14714aba2bae50a77b8766335f8f39", .None}, + {.Lcm, "-ec02a36eb36479183de09de956c897348f8ea090d093b49d68d68a9b7d56ffdb1e484a0b8e6e4c59d820434812735dcb34dba96d77f9dd62851c28e1bab811638143e8bc5610d0d5be025523c5df272ec307f052218bc7e2e0b6a04983c00f9ac2efe8073f2a195f6f2f8c97fb409380800a69a1057842aa4d1cd62f15069d4ce90a17c7678b5475036e4b19c72830001b142cf9c2fb", "47749a646cd9090d40fe708075dde017ca89682d07ee68dde912f656a8d07e7e510aaa6d483495c779791d9facc42dc4c56307a38a42029a4fb9bb6befe8a95ae9d785fa6cdf119a32b149ea522bbbe393c7591d7e844a0e8fa12db90978091da801a1bf543752b45dd13e9dc3275423ec208b57591330734d99bd85b866c572347b918372953c922aacb820732882cb3c6f37b98bef", "41e03adbed9bc9cca88e17a47db73bf7c78f7db5de2701889d59359e266280be7da92496311892e62efb324b65d2e2ea44f62446f412fbde36f96ce76e45f42b2a736ae2d4cc0889f8411fd84022eae2bd50bbf3c3ecefaaa028c8dbda62b18a646150ea1f3d465f227da23f9ac67e57c583313159d2fc9ae72720b47bfd0d29d04c7139a8056200c493d3c0d93cb27ae5375bec0e77213dfc4bcaea6a66bf92eb58f2a2036782e20a4a2e8e412c458f93a9c40b6cb3ff6e8d2ea5f1a4691cea11c00464c083297360dfcb3a9ea12b0316b71f44cd4aaa9a4b10ba408a575bc20e07dff92aaadcd0676706999e3f4216b2ba2b970314b2ac3d273bb7b17abd05b0f9855bebc69b3848303f57b79acb18fe1d82bfd6e4b4a6e191abb72704670839c6a60ce312c4786e6e5155", .None}, + {.Lcm, "-aa1203a5abb686c9858b6001a0553be888879a82b2a4688906a020feeaaaf2ba12ccbb4115f4e60dc323da5060e773e9f7e99c4f310a108db03584350645ac0bb1d15b60cf1a7711dc7257b87f2ad12dd04384f04f866837421920a5328c00ac7bb1f09427b40251ca4b0f9c3a39ff2a90d5a9540424ccb87db04282d3c7aa2fc13d6f010a4d4678c9a67feff0962eae6323f56ad8aa", "-75d42d382fd52ef44f8e88651aa3b829bdc8e3d353418d501625e99ee7cde442ed4e68154adcb44a54e8fa968bf7eb1a4d4dd886a164a744c8254674c067ce69101de92866b4762e6f86c3ecf7f162850a8ed373f7ab989a51c46763ab0791ac5ae4e15a47462f847c092bf3402a90d945aa73e9d5864c154ba6951341ae16c8664e7b8df2c9b9a12428687faf7982f20a9b8d88e381", "4e4730a03b0879085c9612f573ff04c6f1257a6c0d33072bd4b1264d5b42db2848d105a7cd9b1c34760a566727901fe27971261411666b9fd0cac7b2e8adc288082c3c66a5e6a1d61bdebced3cf62a07772fa03c5f0bf3aab1750511e85e7d793f11ea4d38172427c6cebf2ae6aa2693a3a197cf7ff35896292553e5e458c721e7dcdf97c205b98af2b2355cd13b9452e32b73483a677f5cf557574c5f3409d9286fd2672ab68998a9859f8bffe04ef09ec1b7888aa12e8e97b954118f4413c61c0747c9cdcbe81861e7641acfa3b8d5a1ac4b2505531f719d4badd45386784eda7d571240d6beb4d0a27dd79b3b5b0f81eecdb93c0e1072d3c5a699df1dbf4746e1ac5317895889ae27af764b935d9abf5c157c9021dbfc2bbc5d8586c0f29f65c28e0e89eae4c32545ebaa", .None}, + {.Lcm, "726288a13efb07378e5af8390fdc801635b8f80d0e263b4edbf76cec302e534736f4d02062e319e88eb1d126c7905c42c2a3fe8eb46bba5a8ca22dfdf577ae99f183ec64a5b0926a328bd293ba9ea737252e5bec93198a90cf457273b0a5332bf2d227d3fae03a7aa4adb7d4c1639e0346aaa30af069e06e1e398e91258a0676f297efb9e5be6bb011e6971f7188feee96dcf8ce5a2d", "-c54897c0e4c528640886ef6b1b8b26076ac69a9eb2e4d2f064eff7be0d6d08c3f30c3508c9fc59a5794236e25a9ab4e2e00a7cd7d1a881be104627b0f33184959d214f08e03a8c4e541d94ece07461493826c1cd4a8f2c34f45b1b1260f9b6dc41a231350a69af4fef540ba3768ef1009a3714dd6f5abea6ee9bb226af77ff9a1fbcc3c7891015cc08856c0cd093f6fdad7d066659f0", "582642a8d18651cbed86327c69090e7a0ef033f6baa700b7d9f1c98cdf084e347452636c778f7c3f6191fbc9c123f67a06aa5dd1d183e739a6d3da778429ac857922268bc5d34d59a867cb747cf78979804fbc801fbdbc54dc772aa54af6e4c0075f93d49c8f978c5bdf38e61a637716c3f9e45a137ae944864356e36d7bfe996722410d04df92c8d9f471e6dbdca07800568838b83812b42b666a1bcd12682b5be3935222073002113dbfef8ca37956c088758f33f6dda1f293ba2cc99aff735b9c634d851517f594a32561da8a358f0ae374e5222114c2d6d11621548bf1eb467500c2ed7b410172b447fa8b28f8be6e741d71d699f8345965bf684238815a6ef297556e816a15ddd3814673ccc84345a777978c598582424c0f4663ef44f9f24bc01f882baaf6fabc2f30", .None}, + {.Lcm, "b66ff2729bdb4f58715f403e15a1f7a01f3a561ac0c2d198deb47dc3ad2bb3728fdb60a60608a4f5f7519a78340c8a320a25d42b88c3f9098d88fa1a025fa6c5e44d72eac4d87559d9f338db42570ad94eb6febb13564f113ea98283ea8fe8749c78b967ce67b272ddf7bcda7b470e475082aa443f571e18790d9c87f2e46c2e82ee819a8bf33a1fade76bd1969bde07dcdc9ed90910", "f60de929cb9bbd663eacc6b5db6f0dc90adc8514c9dac6f77db63806681c792fe880757dd06a25619a5e0e062aa1cfc9184b7afdd7c84540baf9358510448b1f4de40aaf1310ad189cd96b49ba58aaf69041a73839690ed0d684021ef8eaf2c2224d913a7db2523ab24235c321fbf05c127940f4ddcaf529c11cb86ddcfa0072393fd6976661367ce97fb1612ea4174463ca452cb688", "15eb2f9a63c911d338c0a6fcb95bed68d3bb94a1f5c1538ac924523cd26bf0bdc90371c0717bde17c3bbfcb88639d66df7cc6fedfe486d31244f60eb62854aabe0ec112dd13c13aa3c3e946713ae1ab22d7ad9cf31f03972962d929dd9aa2af8a3e90b128d0d3cfb956ad4e0acc5d7030754a43fc6e778ffaa16d41987be7c964b4e7e811d9b153a131c7dc95c1625798738a3a646fd17b2011ecea9f2e8e58ddf62afa42843adba741cfc6092679c325e737dabb60d444d88116bc5bbb3e50702a4d22e6db163042ab306fad20d14e20b1b4c77ca431cffc59c71c40f80dffcdc7ae7c0890d05f122b0025a2f6cb5cd034677a59e0262fe3294829bceb73c2437f70a294bfe1f4daa2d7fa0e3b908f453fb71fe16675bdec69e7dfd5902c58a0528a23862be0a3031cfc610", .None}, + {.Lcm, "237752ff8b5900a7c3e2bb88e671baefa5a57e868504608b79ad18b02a528c5001b6c4baf08ee99882ccd56dd86c796986dcbf9394c58d05429ea0c0e95d9968a2fa51e14c67b6c8d0a431d7bda900b61dcdfafc34471ffc9c0b2f919e4e9ec049d602cb578373ad16dc8bbc9412031247f071d78f178cc9264f4a1e7751ab49be108c49feea29c90d6ff75b0b3507ebee4d627da812", "-9708c46b5542bc023638a0dfb297573d2440bd595828bda284c183c7afd99ea691a4eab7afd949ddc20a43b4392bdb5c3c6911ff97660a3ac2090af7236453e9ad273e7b8d72ec4a55d4b01c5ce8c240bc6f265d556bc31116d41d4d3ee491e1e23efb05ce71482dcbe22052412b4d2bcddc864dc7b1b30bf39701be093b36a35a9dee4fc74b53bbd016a633c9b2b6d129d1267d0d67", "14ec98e58d690f088b08623006dfadd6a265212436f8f01f79dc5f401b41f2a544efbcd685519955ec223bb2e9fe907715b6d8bc3609b8133ce3c6c09cda86913d31649a2f8512201e7fa2d7c3b597f6f648cf75ae0aa872661452996ca99fea20dd21463d1b03930f20301ca5f384f592e756c6a57a41551c21ed3e8893b12814b3311fd23ad6a3d47824d2c7a036e0a54b50a987482ccef69b56a0d5a133cd2b99ec6e6bee928a9d569e5b67d60205a0ab5153865dc2ded3997d8c8a75e507b3851ca88898f6b83465782dcb25f939244065004d78bca66ad6340d45a880b4cc594cbc79faf9f040d2477eb98b6ac467542a0306217724044f0d5cfa4f5c8bcec986d0e5b3068bdb6b2ac35bf196e673e50d434a0af2ad13fd89ab25f2da069b2ac5da8ea1a622bee1893e", .None}, + {.Lcm, "9d8357453c84e486635ad5aceeb9b5075945c7d027776cda9933a80c443d0a46ab66bc1ff5341c14b45fe2d10949ebc341f65c70ea5e5a6520a6f02d9db4a738dc9122bba55abf6a018493e4b7cfd5d8c214ea3f005d3753080a2c29e1a05cd4d727b4f45fecf37c18f5492a5dce5c3874e4bef215914f4ba17dc1df7e3c65b1662f027ad2188825b8ec1889a20b962b86fd56aa9837", "-418c30466af2cc3b08f56212b9f01cf8c176c2668c66822cbc02039378a02ad9ddbee67c9e16847a179b5a1030e316b8136a85643a24c899d04c57720be0db5ccb6d3bdf6a8be45faa3f04aa8caf018e390270c1f0540c88f25886198c0692d9388dfe60251ce925c380f51e0d696eeec60c0ee8afd3262081f212cd65f014d20f396e5600c43a02da72f466c7e1aab2015ac443589", "d7188e56b6fd1a4e794902afd111225b6fb263c0224ac7fe0c868405f64bcc6daef8a877a3b370810409f7dcba987e1c732bc1b60fdc2bd09df407e6e0257be856278fe4f744f74d458a586e8fc8bbd3244c4395281b186d1900689a799d91264c25afedc52ad64ee0d0d359869999de15fa38aac0dc0e97f3cfd41df9858ecf967864f5886ac604e311fff1331170f12db0b3305ebe952f51105685ae203142d6d24c0fa2a5687921061254cb803523dacf45f142cb57bca411e93c8251dad308f7cebfef01fd6535636847e27137693a67af8f446f3393ce6f2724c08fe0a0cc767e39c08251e0169b160792e290773a9b00a419b4cf0831ce0e2643b0ffd60f1ce27dc1edb39bd46b0ed9fafc65dc6c9bea3ff02516924b4fe4ef0f88b27c49c6e1b681e589b1ce4825", .None}, + {.Lcm, "fb3588370a6fc1020efe57980957dd99e44e0e60274ef5688d0c30e85dadf3739191bb345e277da0fd67fcb9df6cc4d97995f9c12098927771de5dbb83efe239a221cf1f14fa97e128b28b7b3ef6680afa8453ed0d5a028c1b8d78420aa318569387c1f0947869cf225bfad1aea35e5c70f0cf69f010d2e1c24758696bae58be53e3b515184d1cbc870ea7c101de620c325177037e4c", "-c6ef800486a16b456ecf3ed38355db9ff88029bb58eab2cdb787c8d78d477423b3f7aa8cad62a27075a795fead410a27396d3f34e0520fc4b5a820992302931f556d431c091a4b37e72deb11abddff200f4845b7d830fcc9efb55f719f69b8f92ac63e22608fccf3bf17ddf2f20f372c6614ee2940b7321d4317bc7b1176b6605e17f07fe66b4eaf6892217ed066e9e7514af95333b9", "c3366bf3f2833eebcef1e8b411da3748ca4ce6f8b9a6285c3531f3b1221c65beb6f4c90e8fd13412d21a31310656b01971832531ca6ec04023a1acd12c983f8a64d644b03054c688caf8106ddc38fd3358677d41b85cd1e4b7e6e626a5a6ce3ffa3e3c58317c8f0fdef116595b494892e5cbbc0438edb231c1e2fca87ba093bfd08d0192182b93099f589c590b70c75a93367af8e813811c266ee8b7d4737068de59ed4dd327638adb91a4b261d89fe03185fba4a163825124a64193b44dc51c8988ccdff56ab17b046c9f63b1682e286e4b88068cd49e314acc58cdbb2010753e0d8e96fb794db4b87b0739f3ee9f1d929e6c292a8ac9bb8074f87932a93cade4a873598cf5838e7dc9a6dfbeae9916c07c0bf29ba2442c3baadf510bc949038e0244b97a8f2186925368ec", .None}, + {.Lcm, "-8f153dc327a287c0474d64fb5ab1d40458e9f27fda2ec9b7a08c99a04fe78eb31576f036f58f7cf45df773fa7e8c7a7734ba5dc5b1fcebcec6cf40b557699e17d7e2158540dfec8b0ef03e65e9baf54a5a90b2ed4743fb9549d0644e3680bf1ba9b927533b7a3f590761b363367c6721c34ed432d21c752f92d9c058f535612ea77bebcf3f399bea149c5b6a2143ebe7718315bffa07", "254589e4c25cb48c0ca39ef98e8c8fb0c9aec600955af92c8eeb88b71af807fb8c6a7cad45dad9b86fea54b1e220900bf98c001ab7b9295d8e4364457cab6b78b31ce597613b58670ab3081176bcd1abdce1a468878abdbebb4c8832f859e0546763ea3b4f27af3ad1f8aa5208cd62a2bf9263ed1bcf7b27bd38ca01feba63115a1cfadf5ef682fd6d2782a3030f515d7a471a59a54a", "6f1a53db14f8299519a5a5653f457a34d79e1d4d0310080c40c42eca5a504cfcf87ee7cc36f94c4ce6aa019be5b078a65498837deb9bb694b03fa7b6aa6a1f99ab227de80a05e43cf6e658bf42f8f1a47870252a53768485071a40667894c518953a93bf59a49f36b6f1cd341ce66b6c93a80abe41793f301eb43dd627859f225bd1e4f3f146cb4e4fb01e18bf126480c5640bb4adbc9de97bbe8ff44542c2b2a6911e69d5e415e9fc7872aedad0644b2c29f05c356d3f72420bb197044003fb15d07cc4652773c5774a04cffc3c771d7c083646dd520c880b33582c463118f7b3cbeb503a8f84007516b9b36018005b2c4efa35fdd906f325fd59647977caf953b298207430c50d8520b4810765fe0b273bf24a7cc6a5d9e66ef57dbbd2348ab09bf37e6edadfee2b14302", .None}, + {.Lcm, "51a4e45788176d5ab6479de35dbe62f5ebfdf052e68e70496ed5c2643b6acd43e95a17773e0209cfb166f8bf28c61b7b9c702f64a13a543fb004a250352a0ca1dbde71fe767720b75eebd954cf9249c906f64493b3782255d5ee4275f2327cb2b086ea138deca8f026ee77a6fe213774b311d0d8b35126787e3420f94233f0a61d2166b920ea6ca7d543bb0bb8d2bf1619842a9ea768", "7ca74b5f74c79eac5c70d723518a3d5e2d4eb268dda09b15d5cac01dfb8e966fc13939a516b1a9a3c35f1cb3376908e10ba0891c75a43d6dc0a60cbcf9f6b45f7099da317c6ae5c30f8512f7131c97aed1d1624fd5ec50c9f8334cc94511fb4e6e7cf7be1b54456fb0667b8048c3939a8854e73c7e238709715c31af8c5904d75e94daa03c7aba26ba5c1e46050892ebf4f3b5fe15ab", "27c139351b59e2da8b1ad8a3dc6d2126810c728ddc4f15f51f456922106e4163454b1f675529cbc9e6253112f7da0276313247b3a472c9b1dae71ca505e2e03a7d7a946d3c5dc81c29fe1869227b4fe8a3a44c341d026bc324e1fdace1d321a907f9aad25f6405a194898abc0a1901da6353a14a5a9fd02678ff1111dc50ff2bc3a27f80662d69d2ea09134d8f3f7eb9b4e4ecbfeab36d2fcfc74eb66345df36976518626ddcff1c6306d4c5f303029baa96116e24c5d2ee837ddbde1ae8cb6cca4c610c10ddbeb2ca8f7cb14a15aa4d6b83eea2857d319b020d64f68ab7e38201bdd4d1067aaddd8796047079133ac5fa25ab7783d613d218ea7fba049c4352ba3455067441bf05a8238d37938742eb73bb889bd4ca774f3f1bbf1a462e8d3decca05dadfbf60461ce55a78", .None}, + {.Lcm, "c0803e31cf326bc4de269d233c2557381213eb010ace83858001443749b7fb20e6fdf4419e85b46fd090aaa2594b672bd57a53917a242b36ade4eeaa5965f405583e9701c60953bb956c35dc349e27056617f50d292958c62097dc3d6b48261daaa05dbee50955028edd99f75f1075c7daf896e462e07c21e193366d4a5ab13a588a6ca5803c0e3e11cac541fbc53f7d4a630adebd18", "bb0ee271fa5c6f1d46690c1d7d1e0b56814cd20353f882184a5829341911872f6456eef979ade8cb925d72f3734bc79a4e80f8f6cb45400e8c6c4a605d4936af6a3950e29c3eeeee49ec3b077704ac5c5d84bce4d785fbab471b4a35c4b57c32d261ce58a80afba5f5f1663a61b7f6f4797677f3bd58776811c681ccb67f5cac4ba87f6aadd631ac266952a269e50ae5cf44a6dcf2c3", "8ca8deb8b4d954c2481e1f791c5f81c910e7212522ab122b4cf42434a397d31b8f0b319c846b5c022a2ebbe2c7a1b97a4e012c1414055946d09ab425fcfc5983e8146c1015f6ebda6e84ba772fd3cb2862d62ecc36e34c4b9e51daed475e50058c89a46d2a6efadfbcc5c2922285c5d5003ac606edf9215de2f4c4c2003b8ae830c2493fba129fe3aa33ba03f60f346a17dee39c51ce550debf93eef81e7a1e36ad528b8bec8744a298ee63d758ba9b421f19ee27a373627c7c6471730e66c66259f0144c070e0b16612db8cd436ea8f00ff13054015d5d46b0e29a25bf585be65bc679502a33a0670c8f2063a8c685ae24245c678590846db0396ef8e64244a7ee3f6392562201870589c8df61b4d01abd9a9a080043c929184850d1c971b04e9624e5f0773b21fe70ab948", .None}, + {.Lcm, "1c7d9795b984f43eaa62141cab1ab0a8f77ea73ed2cb5fddc3805c791e796a3bbc1875d3dd38bd29eb53c936329ab631e8a825b43d873beabb59cfa451ed0a5aa9e1dbdd3f48f4423b8e5963a471501f125d9305997f8fc20702f40970c67398470df9d220186847c3e0480918994abe1fcdf73d10772f1a375903e029a176e802e2a6cff26e51f9aeaef20193d01c20770c1474196c", "-fa21bbfaca0dd6a42df884c9cf48cd28437f161a99a376c22a39f16a8fcd5cfa962910ddc3a5e4b24e6b6fda1b7b588edb23c47bcb208b432802a85b64f4b216c364fb367eb34c12960e5d3d532d938e94ca8f66421f975604b12f9f3d32d93e004544125e429ea35d416b4fe166e5470fd03f2d234e5dba42f069fa9da02cf57ee699d91a98e7e977acaa8c0ad30aee72cc84b3e2c6", "deb3392342ae5a208ffafc0ec5d48855fa9653d96126e1d8de8c90e2dab96df77246913ea458ceb8f9714f831a01357312cdeffda03137655a5dd61be510f646eee0ad93f7e3bf316649f55ca9680e66ad6df89e609e5d880f2318971dd750a7cd46f282f6ce38c594bc80b539fb6cb2e84d33de79419f95bf2067d879090ca9a33787de7404b0d7385ae422b1f88d0b0f2afbe81696c89a19d97506b43f3d3a3373fe07d922d936a4d06beede17cac8810f34595362fd6b0a8452eeba2cd03f430ea714b2350bb362039254e9062c74eda4943e534e6118bdd11da423452e10e6e7be6110069cb6aed3f7a7e504edffadf2dd3b99ccd4db294de1432cbe895d34594ea104a2bd213016b5ae5cc2f5598c664638e3e1f60c92b874793674f14a1b1b5c6de38a0dfe36080c4", .None}, + {.Lcm, "-6cfba29e8e42a04380b0e3c5b4eb5153302f97522e839b9390bf7c4472c206b20cd79a72e1493a1cae5bf3100941289ce006d055221e8c7eb6b6db2ae4f6600c363d2d09ac42be740fd8e392c0b5d88f221d905c48044441ee0f5e65acf69ea067e6df5c3f17ded2f398e78210eee290a80252f80f881f562298f8f63bab2047331ffac6df5bc32ca8802139fa148406247c63bad798", "-8e4d28d3752d636570256a5849d88ce488c1a2a0ccd244f740fab26776dec24e3ba92b4946d1ec304110e37179ef0d42f79fd37e4d557125bd7bfc421da3d1c4e7ee4c3102f9ce123faf3294c291088b2f535f10e7d597d9e239665e5fb38906e49efcf8123554f38f9e064b4a7953df11abd05786011fe1f91210e724a53ccd78b84afe9e9263777efeba0fa5744b3a3a2c8e11455b", "3c946d45334be1b7db706a9b7293938693a74ecffa4a9ee26b071545a6db33bba1de4d17f7b3363c591b04dd0f92e541e3659f04fe8695e40b0d1376c86981d716bbaa8c852d39b6ba6eb5e90170bc572b5cdf941a914ab1f7362fab3d265caedda180ff80cfc0c779822bf8ea36e987dd5062baf90f7f0f8c13b7dc3f00095377c44b9fc52f3db8566d1050c0151b1c94266d4def592cefa4967241ec80db5f809be3b4914883f5ac715e2274ca82cdcee4a3d0dbc87770c66d5cf0c4c326231c11faca22fabe39842741cd69c2f44e0417515c5aa9e27e2c6781a5438700d905938b0b5efb9f733630efe31c22f13aa84272f5094a110ead57772e616569e47609b5d571a624e1ed41e2260267b04dfba801151819f6d9f551e948666129a1e6db0bdddafe4037709e9b08", .None}, + {.Lcm, "ff14e78bd5998365339ae7b14a1e3af883a408d60ad20bdb00033e3c5ca9d644327b8e79cb63cbaa6bfa1e9c5a35c95a423cf3ff35298e7c60e26787a4f21f8d9a1cc75690f3d6d7d93a1b6764c0724de13003c05d88e75981fe59902b41099cb9d6b4170437c4a7f942fce0ff7d7b1deb3e25dfd18c8975a8a47c92d458eae20ce82af8c50a49f6994e8b0fb2fb9acdd0a95100907d", "f0eabc11c4182c2e0c74ebd1edd36a5590eb0f2286e69a5256d498d90c4a36bd9a4d8c8384cb6dc2510276a39af2546673545e99642790807c9de84c8d0cbf11e9ba0f1f13b6cd19742e96e791d363b90882bc5da431928aa95f14244376e9ea07a4450522364bb1873bd328dc29d5e38ffaf9a703aa70fb7896b797c2450395fdf1316c2abd7be600601bc6a4ae19eee9784769b8bd", "f00d7d93cbe351e9252f1e8d951b81972a58789531a04abe6cda30dc1db53a14adcda0518897cd2faf2bb03b9176a4673e55608ad4bd69f0ddecbe1ca3a9b2a826fdd8d2c03737ba7fb7b42fdd44a886c118f17e4930498d491ba1174dd53bd99f3865db42b5df6c0fcc818c9cfa368360158f4c2c3d17902306b4b036b0a40346dddfa6f2de25a62f4381801569543061c662c92f4014d0006b69555dc4dbac132a33841918122eaeed48f3017dd46b9f1c4b6d58772d38b25cbd7e65d61347ff223e7bb190d8628bbdd732ecbf05a797cf635ed204dd7f24ade13c439718f46e485fbba31ae8aeeb3dd79ed64ae9e3b0576f22647cad55a3c0d4929f9f3f99a7cd8128c55c087c1c9f1b0332bfa7365ce4bb2222cc1337b41482f683e72118e8b41dfec7d1a01f23898449", .None}, + {.Lcm, "-428ecf66cdecd5adcd9ccb3269b8eacfe69e3366e78d1e33c820aa0d108fdc4cc293203f365cfab6c75ca2b5685d666fbfa2bf9e2c1cfac7d95976ec05e0281fdf7344fc8480ade759707ee61928463a849f79148336d2204798cb729b82485456af78946add9377f13e854c5534fc24816e4347ca7fa46c1cf7063f390547c8c1bdb06ae932669d3cedf30e42e8fea31bbec14535c3", "-bf2bf71b62f9fe79bdd0502f00d1433d21cae494ba23109879cc151b54cf513a616b63b43e2f7b0f2c6d6e60434c9fe627024e9c993d4c15048262b5b19e173956fcbe3b5e2b6774e7f5f7010954c839def9eb0595ce6ce2108327a33ed4263037f8368f6c2e1a98ada7b29e12db982c737dd85359c6b46e3a048bd78f263be83d7d540688d77d584f661037070cfc4bba0b2e41511", "31b3faf972d00532393354b8a87406812790c6011f17210da4b815ddfe2986c37bd656d9c474a964a6884ee0d2e1d46f28138a7ed67d38af7f594f6d3b0f391bb577911800b6de71f274c77d453903abffbfa4abb47555b300a7d563ff4dcc813b1292b037d4914526ddf7c056e6948721369077b27949aac28aaf5044ef92b1d28eac64fc73bb3f4fe5a9e3b298630a911e737df5cbb80dc39871d86da7750b526799220f13344be078da862af3c9dba96e045415b0f87e0bf0250d14ad743c3b21a804925059cbe42aa9c89ee4ccb56e3266ef1c0063ecaca9a3a84f522d245166e7aad83bd93cc63c8996578b425a44297407582136bca2072fb6e15a577f4348fbb4eb9db569bd093b850c0050faa5b17a4fd48e6aeb5feae2787e01a7b099e3417d234c96afaad90f3", .None}, + {.Lcm, "-8648a5ac9c1ed6058f2e4d3ffc746711bf825d46bde945fc96d5f4d164fd1a9eb0ee2fba9d34678402375e0740384d6293920bdff55315f8f8fbd2ce5502afe80d35e6e81fa7b1d497d96ddbbe4b4694bd627bc28b6238ab7ceeda019cf09025fa3e1b9102baab453bc774d91472ad740b78ebfb9ab205a09b3d02f434ed4276c6118f97f3d5f0e2f210fcb47eb5c6bb02f7bfefd2a", "4a23a34744de5ef50b31848ad54f02b0bf3b757168b5e59405ef70493d504f5cbddfb068a31e1a7f77ab6a2526b1b18f8727bcd09d17afcdd229c4899fc33c1e485c298a0ffe440f14c80fe7208b736ef93e89c0ca2527547a2da440aa48bbba353404948550061c65372ef0709a062c027fd479547baae385bf685dc7eec29b5e062470215320a2f7db0ef6067a65fda09b2fd35251", "26e3b1782f7d0d2c885b770677ed1115a7d321574232f31874429ab23797ecae146e80bd12a3436769621bda51de76d90b732de4c9c3ee12401265f7d7d00f1a3d0ea6db2ff1b574c8aab84ff80fed39e52dcc088bddc0d1a612805f93bda818cf2a51cc1bb454ebd8b914381d1f373f73f23416d04be2a1f1ec77cb8364b1509e974d48a3b74f92004c3d7ccf6b9a5b965d3ac78cbd50fe91065562c8815393f9cbe3ae1be45bb96f934765d93e84abddb7bdecfe9ef91d475709078b180546a9fdc837fa3d35507cdbe8e3ee45ffa7f823aa28bfde455d31ed3bb616e53615ed94943a01a15b756f69fba29d74a8efb150a73f857460f10f62165eea7b7e22713e73812aaeef05ab14dca2f047de8949b01557c07828266cfbcb31aaa94d05b4a3852e18880d148638e4a", .None}, + {.Lcm, "b2250ca0b9a9043aeb4dd9c5c288ab396b209416685e056c83977ee91a28fc1a22ebf88c286d4b0d7a474321eec8f039828962b59a105d22fd64f48a94c546babbfebbd59e59c860b31d74e10697229e7ecfe37abed6d2bd1f4dcef29c3ed76a7d9bcb0ce711c52f158cd9628b25f9e43632737396863e6e0aa75b634a18b3a32dc65400fcc072508a3e3b48248edef0d9a3ee9a9d5b", "-e2e1e48283a1a8c4666efaeba5eec9921e66a325da01edc81fd211482ff0444f04d58afb61fbd1ff001b65c8715666637446ea3086becfd35c43701048ec7f813e66920d9c574bb200bec602c7e5f17c55c2400c4c2d0f0930e07abb0a8462326a61dd625ac955fa342633145b9de9bb92d5c32e63e5632f3c7d960b53bf33f2c99ded0ff58e438ebc20d4afaa5aa4585b8270c72c39", "9de1e6b9ced36675b7218c145086c9e5f8040bbdbcdd3a7b8e124bd9879e4d6b26a4fb1d29100e24395209bbcaeee053ef45d9f990812f912f54e3416a87d14442fcf1362312b781df3191af2129710a76eab8618ca086cf9261d76eb222137d5560144a2824dff69cb8beee5e52d5feeeaa8cdac73045a981a6887827d6cb43212deee65950ce9798a923f1b23f825cb5248d980bc8615b3517a826756c5f9ad6fea064bd139cbd30230fb874f85f5ba3686dd48195cc14c2117a9e5d3abb6c4fd1ce85794eb5155b5156142d4513f4ae8cda1596385b0a1571133d8665a57567c7148883b3de07aadcae020934a80a043285c3eefdef35d0682b2f572b855ea8ff2b42a149d7cf16d805e7062b1fb65ef1c493a1d8ba5ad29cbbc525c96c98aae0fb94739602c0d535ad43", .None}, + {.Lcm, "-6094e1430ab726040205a673b1a72f7f261608a56fdef6f04867f598bc58da23a12c417fe0a45fa8d3885cacef7af9fa42c3fffb524c5ed47411307827ec57ee38f7100f08e1bd660c4361c010be5a69698673a817558485c21286f720a88f83efb15d5998d4aecf37d64dbee5ef6c98e1659bdbe4ebac1a2df64b9e542e37e5baa1360d2effee8d39803b71c68516db2907b1e26c34", "-dd18cf3f7779616a3a82ce234cb36cda01f0128e81a9aaee0ce52c5f3bb4556d54e6e1fa053c4ed624568d4a58fec03b31ca645a43bf7ef838a47ac922f9fd413a689a6854f17197da2ff70df8bb2dc6a6754f0676fcacbaba17ac168bea7269ff7fc5212d0400000199a613f9ec7d497fd280c506fabe415a98984572b52223db4138d907a1d3bb3a069abc561c76b2093e5d0e9456", "29b4f14e293260fdf0564f27f4a5f45b89dfb20d56efc1f35e557ab9b824c2a74ccd504f15ca347cbe5e0a2d9ece5333d89940c75667fa7f020280f0bf888ada9230e2d0a8d15ea2e8d425ace9ff94a22c17834c5f0f77cdf06e865f3049c13f119bc103d07c43aa9777ba8a95fb465c97d12b47be0bd8b365b8842314d2e285b5b4e12f61a12b034363b975f45170b5cc0088f3c99b00fbcc80d4d24b117c36cd75d8ece3786cafd2db1eb0b447694743c40c17fc2812143933506e8dec422e496b1375126471b01b54e8447f4dd67e7aa47b10c5a6aef4dbe2ea47e0a8e4e139b30539bc5e3ee01c0f458274b8fc5958ce8766719ed936ba9da4323c9993f827ccce7a40354ab487bef6588cb37c54478b6074de1c6ff9b1628bf1c50f77a743de87f6d5179fdabbbb34bc", .None}, + {.Lcm, "4cb938682b344f431426fc70b3428bc8cf5ef989b05bc260924c028518f41281082790ca3e2d5e339d1f2424277b140891bb54d570673472292b54c17619fd0f88c758b107bdf0af99f159eb68d77ba3dfc4aff9d12489530f592f5e381e0ab20152b794b004d88bc8fb2590b085f98bf71c328f2ff324b3e64efc42f5011ae4627a7b329329dad46aa50ccfb7ae8f11a829533e5956", "-c12b74dbbd2bd8547bf55bb012b5224b9203fe3c204201d7c820afdd4dd7cd3f2ebd51820d726903d8bef036886af97f54eec3be1f139215668a25df11e83f63992371512288dc375812ec01ac564da726fc677df5559e04eb0ef9698ba322dbb00bd3fd71f90b645dfcd68a8b0fd6e3303bf3623e5028d06943053640e02b5df7e18e559c5a9ffbfde158e53a8c6016b50d7dc7eb01", "39e4a9a8cac608d28709c8291072ac74539ef0ab892306d876d0d2da8594663fb344373c51594451f929307a8e795beb68f1c80b585dc2e150c410491fbde52a3a123959378b106d57666f741aad08351a820ee9477df5c038faa706f69f266edea0875f33095fa25d996dc7e3372adeaa548fead238e7475d4eb47ff49e213e366d9f62fb42fe91be9df2012d3de5af745fc35b9fc5f9d86414c0f63ab35a43535aafa92864048d85e8a638c7cbdcd35e2d10d32b6d1a59031c202853b089662630840c5c8dadc9b241108af0b79f2ee05482ff85db2e5264a6e5d175d26a753aa558f4573afec0efedf67e709466b86d451378b8eb15d37d2f280e1daf6cd67df3e425fa2aa398b6d2e7a102ef01a486b5fe027d38999cd73bc552c118b4af91cd6cb1e6ed1607ff1a4b56", .None}, + {.Lcm, "-993e1411be78b39bc2a8a18bbb5cbcc1449e7295eba880df6efccd5d2a2563a1b565919bf98b3ef76448673c4f0266ef8b1625f8422bd2c410e8b5616d86318a07bf39a888f4a6f6380e4642f76a5ac9ccb06ab3b19927361d7a03a2bd5c2c18a1bc5f14fd3b1750ea8248e244e7d688823935a4e023f8d4037d8f5f55a45581a46be0e928f59e10d816b3aa7d701094d50df7c33810", "fb9059bcdb4515421d42c3e3bd9175e7258b7a08bd7210bfe2a948e7271ddc38180a337b5e1a50ccf900a14c98ff0366feeab47b2e4cb0875cb1138b8c3932929a8267025c1803abb9296f26c07f17419a88cebef46228e8944b7dab29fa240aae137eb8f609aede1dce54e93bf711eae93aeab1c0c0c37264b37f9183f570f1595ba796faf6c36ea356b3040fb5973bb74f68d68393", "161109dd2bbfcb855371dff10a594a3c501f4c0cb1660359d4f3a2fee88139fab42ef9458d8525fabd5caa22ded5f53eea740331ae527f456ffef9d78c3fb21488645e43162d77ddaf6ab3ff7f3fe67b38fc09b5fffa615ad6f12d8111b7c54577545f796ef407a6c553f47117ce510c605a622c7534733ef7c0f6ef8ffd76fa4fa2c83860860cb188a1ff8c67c26489ddef726ab5dcc0d4fa45da38a6b2c67dd18e80edca11b500f274b055b6208d18d4544f668b9838364195cac83720040e3bdff98aa1d50f784bb23b3d6089adc362d717868e941db11e66dd34c67f543aa2acb38b36b75e837218fe76567a1f02017bd05ab1db6d0ce8ee45e3c5bbcb61b824639cd429d2f19c7274da1bceca844cf322c049c8ac3331e8aac6fc40af62f5b10ddca8a3564482bc10", .None}, + {.Lcm, "-f1160b7ae15e2f51c49434c976eb021222aefb7dbf2245f57e21e3f2a0dc9f32abc1723672bd43e53213cf9cffff54ce01fbcf738839d4c07644adb02a478cc035bf0337887c2fd552b3dfd2d150caf291dec1a03fd56973781b7147dd1153da478f105999f19b2ee1b259943282566c2f09dfd9793476d5154f746ba21a465f9abe4108284b0c4fca3ca04888d27cc1cd9ff9f1a9eb", "-3f260b504a9acc1ea44b5ef54016d41167a1dee6dc9cd7424aaa89b41095999671d173852395b3b68ffe2d651f7af4cee28f3324518536b448a82af98c03ae3407c40133a204237596a90508a7716e695eb2d0fff97ab1d32293d4d3b09a1dbbbda6568a8082f94af797bf6821b7aa5db906c97870bc0d4b8221a9466081cc623576bf24cc7eb11d2bae453dbb34e978d4a073503000", "3b7840c08157a68478801e8deb8dead806a06d2711d4c777822c57384bce80784160ddc67efbf8e2633a4117abc63c7d4488161d5a1ab1c1c8ee9aecdbcbc9a57ed0f8fbe3bb38925785126e669fac235b545f5c8444bddce4b2770e5f55aacdba9a03744ea040a0837bd671226581becca1bfc6ba7c73381b2e633272e4dc3a95e6ee932bc6ab0514ae2c4383a5770685fae7273da345a95079cdef6e139ed810f620ba4daed1ba0dc513a4e0906d9f0ed12e7a39b9c3eff7d902b9649d886ad5528b763bfc68838e1bd3ef83343e009b4d43962b16d089ac23db3512ce36ecff0a3be92470ff34de12d925ddb488cb4d91d4dea35066efaf9f7a41cd724951541255a8d39482f1edabbdadc2bd6f2b0f268e0d7b41161b883cf4f99432043a7e90cbf656bc7896fa4c1000", .None}, + {.Lcm, "-caab36ffbbe70a3443f052addd7452db8d1341a42cf1dee210383b8b98f3ce1541bdb8cc7e90e53dac3e7cc17b9da8ca32161ab27f4d3791156ee57db8e5d236e2e1c4058b060bfcce34c7213521aac3fb2373065ecdcc11bb9295fc06902f534ced476d835e8615fa1860b5cae1d22f14186ac06210f0801dd588e120af72b2b040a921276977dc4ca3d9a55fa3af6a33aad43cfc56", "-9c35db76085d7def128ab258ad894961e88f14d05d2ad39a9139afe7681f472726cf7c8f48b9865bb11cdacf25c0789fe6c4dcaa70611128a7b582b6ea6ea0fb32b3d18ad5cb89bfee377c600bcc10a5f33f7558dcf92bc7da9c5be87c6b51a4cf0a7e91b7e254e21627136a971172a1048588c6ceb658ad900f7fa2c998c91943d18b21af85dc832f9d04c57739a0242df78f24a6e0", "3dd57c5a1185172507ccbbba36e4bb5d62db30dbc855291bf7f60557ede258da285614e9fa545fb9b7392a80406990a7c1c9860bda80b9076c10a9e77738aaa50e128bb9a89778fde049c72c4737f4e1bedf6360ddf8a3151961312a97c88d65fdb140e5e73aeed5118625d390830fabe45adb371b1d8b223a4201ec7f4233284d2672bdb7171ad4a127ef8e96a197b9df0f846b5186a1d526465d555558f5a820ae17888b42f4549e1c082ffb1e334aafe965b483e41a5bfd0e5913a07f97ace7f753e8ffbe9c334ce42f8fc421544adace841dc348bbd9afe326038f65c26bbab61eadf2dfb63d278ff9c530de1d030817196f706bed37a634760f15f491e0dbc27eadf88c41372c5cd1620aba4698336cfff59d409a263e0f3d950ba30ebd517fe8aa63263ccd638a47a0", .None}, + {.Lcm, "-c469cb681bca57abddc154798922c19276bb305b3abad2424169723d8492a83c96e92ed7bef8b52e639d1d525b4eea5a8143c62fdc2e4aca14040d1f5e93c2d370483154f5d9f1c749d2ab01c5f712ae58396cda965559a754f8ab65ef3acb02395b2765e5c135007798df4cb95ad7a47fe859f4d879da2876aa8f210ae389000368fa24cff32ad8ad619f6aa4d628ad6329bc6a0403", "db095c5d4a249e0c42a8da34fe598143e21c5a4e535a7186512b8db3d5297a1df3a063ae6f691c0640b9461f6761b5bbd5bd008696f13c6ab2c9e9a153102ed1eb2de1c57ded4d0e946810853e4d54a01a08d4029db83b3cef472c4ac45c13f54850fd812e602533f6bd4af8c91a881e7fe1f96685eb4e247eedfd77b6a19e38097f7502bfee4eb9fa5f02de747de019b919cc46a7ca", "a80daf97ceda0edb5213cf4e3f612fc155fe5e69b6b0865367570406b1fc7dcdfcab0f8ff69b63b4d211ece2b2920e0f11ab19d0549888393f56471783a42d4383f6b909b7577b7cd840e8c097074571328ed7e7773fc6befb0f853e86e0cff193013754a304ac6947eefe8d5c8605d0fa471b81551a7225466ddcbbbe7a98ae123d9711073482dcf883bd848d59a7d3f3b6c213879a1ca0563d46e31c726041b89f0170b147d72860ce2a8f11b72b8747fa67a39615aa03a773a91b840c6de3ecb16bfaaaf9398a592cb9e2f6dbe8f5457fbb7025afaea262417d377104eb3559baa0884dbe22b1a98b568204be5ecd4d3446c9c68db585d6a7847428c0d6da69f3ee4a720c79222571bee18c0d1e6850a4d3cfa85c924663f098dd7d8894621a5e63839b9a085251171f5e", .None}, + {.Lcm, "29e81ad0ffb5f176fab8ee1cc70aa99ace6d299eb3c20ba2e6ba39e8d6591acbeac36d239fedfd34e26408d7585d7eb8a7f5700007b002ed093ece79efb4d3d6386dd9a17eaa7c10bcf337079f0564900dfe40235ea64efa7842e096276b25beb190d9fc733d69981e4054b328f5516326fbc35791a71f00045021d68ab0a97ba5ff85eaa67f1e643c4df7f32572aaf7ae1b15b38509", "-702e928de7a8894171d90cd68f99816e2d6e636a87ae91b29a195c21ae1c324e776af8f141dc3928b8085b7913f5ba487998a004e714bef2d4f786e5a86ea85341fcd0161fd30e945dc41aa7773c376669b295d5b3e4b596efbe4ff868af3ab95acfab49d7097b52f06d4207d8893ff305010afcc80779e17d5b15040e06132b23cd39bbed73526afda9101ab3d7ed3492deb4215404", "125d2b6ddb7b8a4428ce6ece0a76707b04f767c0afcff1f1b9b784c91c6bf74200a6557e9404621a9d6b9ddba307ed7fbe54a025b956396bf66f28594a46d0013330dc6e0a5084b6ad65afdaea0854af133c0d88846d39d700f181e2bb2f82d467767f4407ced27c04af80f282663f64b97396faea5c8cf294f1678e029ade3e12541ee23c439d4fb636d029f2c3dc5a1e0c3214cbe9854abdcdca387b81513d0354e5bb00535c7277f156310c6b73267cbd72339d81037a5a5813b8d0a43f4fb8f92d05ff0dbecea907f20e253ba5b4530c1dce8ba02beb31152189b425c09b9c4f1cf3879ed46232248e2ef2200993aaf7318a6111908f251937c7d9cb3a988d53cd620dd5e6dc4e363512e688ad68c9ff3c4fcff22019a397b18f4418a618e3747448fc202107b89e0824", .None}, + {.Lcm, "-e04edb95d0e5bfcb936bf1f17c67b4c3ffa53c050632e8df37d7fb0b0ce8f730650734e0986408ac96bd2586df9a59a1e3988d47bdc103a24bd6c4fe833a535f9b493aac5f7e05f585cfc56cacc11be31dc25c5e61ece9411e51528ba2823b788e0bb6302d72c9d5392146bbebcb29956ab3d2b0a630082f1d8813962855b2627f54dce691e492451e7ac8d6485081d848a0ff1a7f3c", "332e9428d4a0cc3d184d688015e8bb735655dbe9db2323a27ee699394e3c996654bb2f88c8e43956e706b986a29014d330db7d98e577daa043c2ba895ed77f31ab8be89bd1405665bf282c62bccff809f4df76229e3100b6fceb54369dd12d5f5c325550c44bdbaaf9626e3c788ce95f6327d3c21acf6ef8e36b24ccd5c117f4d645b63a68472e733557be076ce220c2cd9d5227d24d", "2cd885bbab1c6cc1296c6716b24b4cb0c58d268f969ec22a4960e4afabbab8671585a939ee528cc986a49141df9f8eb1567ccfd47335aa4775b6392a68e12f3a4f6ebf04954c75c9a8f2d454ba87b072e54e2a140e845c781c46c1a9be4799b156c20f0db17a6fede9b42a4595304d02f85bf48070ef2aa3e4d2eea041be0498200241b52f42f54a21f4a67983167a50d88b147f61b5c4e38281698e3dd9e4627956732032d580e15e337e94bc2872be0603cab3bcabd23e3e75e0383feb8f2908bc806934f0b5cf1125cbf10cbb05aea355a5358699b632d5d80d8f82c27da983854be9e4f158b5568bfa3baf3692f775b40b39cbc28f3d7422885278ea212f0900e678d0e9c01cc7f9c9bf6dee1d2ac914eca57418b81c693bb72fc301b71e610895e9b27a5747117b7d0c", .None}, + {.Lcm, "-7e628dd84fbf8c6e1634ba9ed5a0ffb3526bf5f8fb4f355ab8fc5e6457e76d376df6a8c044f78f3add0821fa129c19eb7756848c375b987f26f85872086a9feb1b550fed1a540953100db7b915a2d410b1198e1a149bfb079fb07080c34ac1d39297f8e86ba53351ece0894335e87c1bda72557785c46a0a06ee6c020bbdbc7f5aca4cc351b83c28aab398b213bcfea6ee33f0091aa1", "8ad86ea7ffb5a581f20eebc55ce39d2abd04ed7b6103c6d177763f3edb890c1041aa6537261df409927c37ae15be322f9ace0cf30649b84f3c3a39927149d9ed0a95445fbccf1fce761dd6e5fd4e4d3e652681f1ecad7bf1768e5865664ae16113db5d48ce45ad23982c2d43de5a15e792a12f16ba6b2b6a3ac9bf0fd1d80801262120a7c54c3511e2e7548a64dfc6feeba767866b6b", "448bfa3f92fbde60971daf08f5dfe9e54ad947f54afa30ab8a46a74170cdb750cc06381a34b7c0345802a40c7449f79974c74038dba3675bdc7edeb17fc16f9555eea8590edeb460570e86be48c6c2907330aa69f0b3aebe47c3134b39a943d7c97cd46c4dff4050ebc3dc18c4de177c114bda890f386aebaeef09b871435bc5e50fb0ab1f7ef1c3941e6732b602510dc901e28ee0f2e486941129dcad1b3a0dd5be8e5c6211de2eadf7d3f34b842ff07a47eb5c66342c5803e561c5910e323f97acbad73f807496c6b0c91a89fca93feef4f430cb2998bc6ab89d6e3d4f7ca4639483484f90475301e2fc46f45f4e2b6dcfedf351e4a9453eaebbc268bf70e8585a0c12383b6cea1425e558d8c6d4fff217a02eeb9e4e022f81f355ce2f74e253ee0ebfad38bd8ad9356c4b", .None}, + {.Lcm, "b575ee715c128ea50e5be0e1e26ebddb8e081d8e342bc90288a474bddac895239d4331bc40fee2fcc0d2aac4c867153ebbf42f876b9b06e527ae4134f6ab33dd8349b3229c081e992c055045f6f7f396698de93bbc0c0df1e5db825dcd96f5a87241d2ca1ba39773b92049789eb09d6ecd6d9d828cc3a5d0b20aca5f0a4025c146c77fdddd2a2f5f9f4b6c08f58a4f4d217055b86daa", "20ff453b20d1e96c1abb928afc5cec7f58740bfccaf082a85f9d74f10766137331949645db21920b342143cce2f322e2f3f63af5f69081a9793c106597c6a1beecc16dcd1c3285a74a79459a402c7f3e9214202bd7278abd44986ee0f1ca4f31aa87100f782e74b2d4c449f46c87790b959f3b305736cbfc30e139aaaf73867e7b0f768923d364e054122f49a4af63337a60c0cc82c8", "bb1d7acb09189665edaabb0cc72ffacc609b1340554f6d7e6edf763933b34731be7d8f1906c52c745664b702c1a1487ceef52552119df26c59dd3666b0f13a778bd7a9412563e31294c0b4581cf01f143ed9fbf5f6d5c7542f6524b5ca2055c11a11dd23ef74bd38d528ca9184aba784d242996391a3d0dedfcb400a5964a46749388b7c293742343d8cf36b313cb66b40551c049e0a7862677831730c5a6de5fb195b3048835db4a35d36e27a05623bbbf5b83a1662041f3b5da0129603b1440ee2739daec4edd31ee7f7eb3dae4e707d180e28cb30c2d40df732d722bbae6c4bcfd21eecdf21fedb9320fc811c4651098ad0481d70cd59c1119835b5f314b3284f22863f981bc575a711b00971e06dac397749d040b5ccef83a83f8f865b596c9399a52aaf820c19f0068", .None}, + {.Lcm, "-48497e773dccebfe413facb43cdd48d7d0ef8c72f6be77f61fe0d5b89d7cd27bb1740598987d3efd01f649ed1bab0a720232624cc30cf63cfa9a86b632340cb0afd70f0a6a030047ed5d035e30ad95125de4e7a392994ffdc41c30de35d1eb0e6979ccc2fe8eed11a4322073bf0a1e2e33cd1ee71699a3abcdb1618d9d85d74a007db161d54017502501ae05ea0b8135704ca2dc9347", "5b0e8238d6166f6e842e1f265af796a31b2dcd45d1db298824e9e59d310265b23c8ee327055f78316e921a9cd29c28832a7bd0ba643f4cfb11ccd1c0815c2ff5e3c7d561cd43309a06150512b746ef5d93049a835fca695572afba7caa8e99c4295de091adda13bb250db9132b9cce1df33b0e38ddea2070e297fff831be55b68dd2f9a4b0fc0aace92ce62952182f6a24963114dd16", "19b638beac3d360f7c6983c14a18814f17c0cc40e88d64ee6b87d694486a3d6c7c4f345574e56d7029f2a613585dcb5342289baed80b1a1585c3fcf2e50912391a5f417cc77fd699cf72c8e6ab310e2e3e167d01a5ac43673df1ad869424a853c76c749ba7f1e38f00dd8cf3759550066a360d0948bfb0c34f2ed38d3d6fdfb0800f5d10e19689a487acf9ebc7d71f4b92cbb00a945f0d0aa68ec4082cb85403302d52ef51578783768ee6bb4df5f2678602458d2b2a95f218bcd06bf93ae546c0bd05a3a46879405680e63191ae10d1dc6e824c34a00c4f9d369b3c19d7a9101f63e2e0a467c4f18b95425d68a34b062abf24b146b97925456c1d68d54f295520082d419a2f56d99e68f8b270bb936aaba2096f4d544865e1581703c45fb07da3256d09240d083482a4f31a", .None}, + {.Lcm, "eadae40debf6afb836e768b180394b716c5b9278f6606b1105b526107fe288331b16d427d1cf1c72fb2d6726fb96cd4789ce190c9084736a7dcb16a9f80e888797d37eddec7e3a28de4d2bf76e89d9d3e16e27370cef255ad2fb7be41004d01bfd9071f290f453b87114ab242d92d53f1edfcb76ddb8f32bc31bd2c03d85538d65fc24fa49fa4e4a9a5e856d793f2a81e29ceba540f6", "b78fcffc499b4f8cb8a5a9d7f2c44125e509ded4569e8902fb217d2727532c0663985e7f6daf480365225905dc3df03c3421d09a35cc7531dcda0a12f5704af499371b6df3762467ef4a5c207687d00fc97b78906ecce2daa12fdb5b4f2cc8ae02aca83898b62221a3a3fab1fa793f9596c02e42d39906fac198a6e68cd8e991c742545331ab82cdeaa739d013cc48c9fa68805b41a7", "a8666819c8dacc7448428d8b3a416ab100de145942c2475c0f28a398d52fbbfe5e572c0aa76eea5d8154783463d88874884a34b31758d9dc82b281ddbf20567a9850137ade8ffa979f51b58336998d77346bccf61c456fd488bbad43081d3611b1ebc2177a807faa8c92a6fc4c6a915d73dc7858be7a0fe10787c542d3032226b2c97baf672327cdb347a45e5540fe585cc286fc86cca5e6ef7f12e77fad375c709a24f130410adcda2f51147d24c365463b041e99bfcdda3aabd8be60d7c1bc12ac625c523c9ecbe2d3bc9d05a16acee170db8f065301fd6d283971d77aae2df85c5fce8cd18880114898a750b33e47f24dce229276faa60f65d07bb807167eb35ee982b9a561efeb494394bf874abae64cdf2573516e8504c4a38084106fb549d702660697b05bc5bdd67a", .None}, + {.Lcm, "-59433b5ba9cf9f44e35f6768758daf1d2a8b7ee37eeea18c71cc8656c36983dd84c98d0b61f1d36811d9451812e8253e13e92b851d631cb4c3ff0db929d58dee28673216733d564f78991cd4db2b594266a01ee50c16ed167e7a38e4b3932dad289d221791e9b39f6288bf4019adc9fa181226ab4543964aafb7c01b34f2cd4b15675a9e42555aa5994fca119611853cdc97fac5500c", "4defe87c31e7e8b48a67e607f5f684613d44c2eead32b6a3302594e7c38ce9b1c14f0cb404da0ac2f348fec698223254e55a78b864e70f2dd219ff0e2334ed9cbf50052c26a9c920c89a4111b2b481f9a5133d530b300cee7f04508f12a8b3899c32f6c329051b24c5c158d9b9c288e39bd8b14c1cdeba6cb88d7454277229b3ee22537d8567b193ada39707fc19be68383743dc842c", "f875b3f8df329d3e4159803b4a96b22440029ab2e57f3c7447de8e9b55e312ea6768f12bab9608eba3dc4be6cb7dd9e634d2a7495451299a48337d1248da53fa1d4335a8d4d6a6fd9418ff8bddf67e6ccc4a3061aa042c688a0634a719edb2637c1c4129b6dfd17ef464fd098016c799503944bfdeefc18f807c684ffe2ae560ff5580c92caee8639f8081c3c5e7b8aa35afa2bbc70531921a194448fe9ed961efce737c901b9102614f3e8be61eb0ee1706496d27b63168c058dada410e6378f379c325653a26ed65e8a98e6fc344c484632d2311fac5ba1d044aaaf8cb7fb189a53f849500637c6063ac946b00dd6fc0686a237c1781e2d7a4ea4d397c2bf8b4c770bbc7297f2ffc189b1c189e589e888dd1f37526ab95075840a1d58e7c4f6cec491c4b26d7070db65c", .None}, + {.Lcm, "-2033cd28efaf2f6530c7a37891bd7bb7a2a42ea6fe0a72cb1207fb066dfc7d3ca17676cbfa97f2f7756c462479a33f2efd147620b6b21fa665b0f7e1110ab7c98da04bbcf73eb7f685305c4cbb75e29c87e9aae3c02e1f0ce0eb73df084650182d64943b2b9829c05e46a6074063cbdb268bc4346cf828b1ea67fe166de8cf16c24e66e5e910a7e83c84422fae631ad0ca65ccac3263", "45d41ecf1980ef6ea08905c20a61f1d029cfbaa27e48d72611ca4b18597c48175ac9247eefb74a8367f7bd50dfeb4e22ecddcd2bdef1ee57c89336af7c3dd07d64a6d5c17266b0ed16d301b991da82835eaa66652bbf0d039a9ca1e6d9f9413104643e745f85b3050d75a625f2cf03581a9dcb63d80462af93603d1beecaa94b0c1ff7f38c18977257f58a31c049362f44267bc76c9b", "2ed8c5b59e1395d3d0170b98af50e9744684141d65f69ef12764e5d556cfd7c7f0c7f3e2c344089988a9d90fedee7efd1d43e8483925a0ad066884ef1ee361c101dc2b9e70699c236bd026139e607db6c8de91ecf875742125bf278f2981d3b0d2838d7cba083f08ca187c581e33f3c68e995a53025193da2afa41a0fc79810f1ac752d05a519510765f1b99527b7042c7b1fd91c160f91d18e7c085d5a58bbefac75cdd564d944a5a37061100d0e57ef2df333c6000dbe96d4b46f1e0211fee1e75e3e78122bc1d5581ffa135998de1c9fc016553a041306dba8d1b0f62806ef0ab5b858831fee2e581db2bed6aa85e55de215ae002d6fe9f0c15a930b1ea8985356cf885d5872f63f5e1903cf1ed2ffa936efa68fc52157b1ba20930df7b451f0b8459b21b394c47dc1fb", .None}, + {.Lcm, "-51a57b3eb9a49ad593092360b416e7644d6dfdcac1e78d2c037ddff033b164cdce73dcfc040aaf52516cdbce62aec182a3b5d2f0d5d5b8413490e9ce0f81995918cd143531b3a71c76c8b5111b8c2168c5725028069cbce949600bf8b67b0f1732df9de411b481c8244d0dec39f64ed8ba768e221f5d574201cc9af36e57f3264347a9b98a7165eb6b26eb785db7bdacd76e3cbe1931", "17ab7c435a59a94434ffa44a4356e1b95dff9d06ca28fe0471a747eb0765316190a368e72a9040ce00e3ad38d11bb8ecf4ccdb0d236b562c1a38562b8b18717d964cef9be67d3cee1b5697b858aa6548560350d9837b77c110795547361429f70857a3d40c3181f10941efa41bcc4dc754e17268c1ad79c0b9daf537192a4d0e4e1b161c93f1d20af53772003b4c9ff1cbb7b75b83", "78c8f3d9866340ad33db58a51a315594aaad12220d78d40664b7e0659e87e5a5e02dfa60d5095fe6f15bb514e9cf7d0c5205398a3e069e0b92838633e7011dc202dc2e30da58de64836f32572f265055341e3bba76e4464fee573fcb69d6548536d53ae7753f5a197820461bf6a68ba9fb0cf8a5550604bcbad8fc74b95265cd6963180399cdff2bda2c5424f20033b87feb5cafa93de55d480a7ba3b84a67bc59695977485c9f732cb67aa34854a06206bac103cad3733ae65f00b9a3ee76ab71d1181518c44f92c513ede4825180276fd3540b995dc578b4ab4fc4e8ba9de5ee2058832ed910bc2982f3b44cb32e755cfb28a07f20feddc73451480db25574779a02c56f47e4981f68a2e63a01069e52c10353e8feaa3962d85bae4019703d6fd709f23d7c1b1424f13", .None}, + {.Lcm, "-502d5dde855fa47d0e30d92544faa7c0fc5d727fee19da534b9567ea85b80e5c1c2af70649b6c85a48f0faf341d7378165aee0b92bd03cd8484f41c593d312b5e7cf208e05240e7fba9236115e59ab59870acf5a78e9d650f40b3676b5aa007e9583e33e4ebc653b33cce151bfed05b311729d946052694d9359cb4b1623f221411b33d7c87997a84fede1a01f938e0d9ff03daef97", "6f0c668aaac222f8bf5281c14c1965b4c0fe228fc74a2c7d19ddb2e05d46ceeb508eac7d64c83d97a7939129cdaba9272d6a478b862b6b223b0404e642e4b26f07091f91e98a6a5b28cfdeaff6829252f1fac40b0c3907b3454d35aaca01566606be9c176e26398b81d24d65ace4c38c6a9b4c0d9f99d9ff1709ef18c928f128ce1b7bd0d027487db1a7456b3b8529713478e8f98c9e", "22c78df16398e990c5a51ab48b525ec99bfa8ccdf66c88637384946ef186f7c8dbe429f9ae78457a644831e364f9608898040675351f1c787f0e11d689d958fc0868a37581cb25ddec33a445d2bd1d93eb14123790eae055b25e18ae20d6f5d4a3f1c98ef4d202c3a3c895e91c6cdc6ee62bd6594bd43cfd33d9c5ff3616ed3ed46c3cae759b727941d2cc719cd13cb3215e2b0cda04a62e2c038efbbd334174a55e595f12032f21962622958a93f256455563762578af5cab175a1ca1f52d8cf471d7a90573c49d7aa90f401b1717b5fe9d679a87cba1831d19855ed1dfe15f95e19cd9d37e73c161dc80b19e96ddd349f06e339a9dd06f29826a9ef10d39cfb3d0d23b3561de84484040e956b0428f8d44534b6d536a46bbaa856ce21135ac805a1f76e79255bfe057332", .None}, + {.Lcm, "48e544d76a3f31d24c01b96193c013d739c17bd4526ff7b79567445ea49ac8c3668f16cb50b2941476599e95a80bc6099b508b0df6c35ebcf343f50d87cc40abd3f1841ac711cca57a5d34a51de65b02448ec4838f0b521b1f9543d04fc9a8002cfa1e1097b49e759ece65592ce9cbff1f7fa2411bf8ec075e5ec5fc254830c164101e9a22df08f88322b27dd878fa28f72e0d5c3cf", "-de0f72ef55b45d7d506ffe48c8de35add717b7d03003f68dfb1096bac2a7bd686be2865681a72dfcc98824747435d13fa88517d4eeb3fa66571412b47956c9fa009d232958df89ca181d5582f7a3fb5f97bc7ace3ba9da34e88cf2c24c24c8ed7c4e4465133b283d6faa204f47bbf5f241a74e7e6c34253018d63fae75bb1459683090daa2f607572046c2487705f8fd667476fd0b0d", "3f3b37dc15dcb5038505342044a6c9459f18419f689ff988d500f880b56b5025bcc193b970b02350767132f85e640f80d869795529cff1be6392502092828ecde334220c11c6e4f2a594843ecea02868aac986d0a78a5a0ea7bb9db190e3f16ff7783a44e24417904145b23aac15f42712e671166cc82e439090c889cf5454d17af828b771897be4145c699cd1a6d71d13ecefd30e582c59c30d5589df14a2f9cf5fac0ac7afda35f33a22ecc6ec0c4caef9bce21ca0b69e91c88eca8956f57df64623e8ec6ec6a6ab2831e0fae44c873a343505e6be69402b311a662ad05a408a3e2b390095bb407b5f789c11896655277d4b98db3890a5d510920b2c8877c2fcc2a961bc484da526275a9b17c68b81c937e594d043e7762b50080fae2c50dee4b0f76180a27ce87d7d683", .None}, + {.Lcm, "-7f5ce15d7190ac2d04c7112e48d82ca313efaca363966fbfaefa626d83dd74ee40b67c3efb86a567e221fade0089e0588d29a01d31a2a1afb6054f81453f0b6ec8e819ba0359f32884528895022121b4dfff4ea53388feafd49bcda6d9fcbae53bc7fc2c3114ce71a22767103722f934e8d311a22cc8ba168bb54479fdbc50ffed2782a98fe70fe930e5a69f0669a1c7a748147282ae", "fd7d6cfed9829559af866d6fa8f76fd96bf655deb820a80813e672396127d85454f42bd6169a04f2d6ef6cfc31398c505ced53d533577bf6d41b1001201e046084332046bcc4dc486f76045f5c5ceea6c4666fe1d1c322902c34668e7f6f066c345f6afef27351499a167f87af2d85facf3d1a8f4502e9c3452757ec3b1d2d3ffae21c7bf2dcc67fdba6ee8fecb932acc7c24b466cc3", "7e1d314d5d4e26ec9a624cfb129ae8dbdcd1aca7186e139bbf62d2280b62dfa393a6d34a0f62f8be581dc32398775276885c19389a5cb4f07a493072761ee1547254881b45006b1528c34f513f8a4beeac2f893b7a72b7ecb3ad18e0db19387bb4b4503f2b3796b47a80aee2d1d9f6f76fe332cbd6de1e89648e4ba79330ca8412ef618bc37f01ca452a04efb00f8e66b88e6c8afcf7ae9417de766c77a2847e94c409c9a322d82379994b8152eab5d951db5c2250d7473564e21134b6f7d2806f797c561bcad81c65dd6f1b7f24d7927be7b51de906d8d5b0c032522823232eb96a8aa48624bae29de95244d314a4155b9ecd5d23ede7279e338ca7643b331e0af6c7db8462d103d1d8ea844cec842a4610c2aea0cf504f0332f89f050fbf6e144aec089c9e41fc97eef28a", .None}, + {.Lcm, "72f09cb6494c610c37556cf81e4c7d2e637f04f472183c45584aaaa824178903aaec9158601931262e77fe8f7ff6362b7166524d72943f4ec62e6eb427d4fb2d87409c6342f4952eb55176e0b284814453a1299633e84a5b178cd8b36f4e8743a6eb8a833951a8af6f2a0a342934f3a744fed094aa00b45937c2cf5d0ff6ecef1afe437c65ed71e1aa46a47ec2d312a25e4521cfcb75", "505c4dbdd0706219d4177e4132b546fb78e401c9772179d36ce70b187917d12805d60959779c959ea202a2da456e9068c786bda52786a3f7ede91313aaa9ed28641e54522e1fa578d66553fcf1a87f285d07516b51ea63403db0ee2342236f7cba5b6e4926d1520c14249b89e2afa5da30aa8a431df9f89cae4ec9444e5ea82ea8519bdfca340cc0e8e758ad0d070828ac31675d46fb", "2414a258e0c6b10b2847eb9fc2765f60606e9ce80d985845b0fef769f8225d41135b6972d6b08661a75db070f40a8c27a0456afeb114616abeaa3a44db960ee3517b133704431cb1f718a45923a2324731d9c0331af21202ee225f6f57bcb1a256a07bdcd522510ab895dc9f696017b904d2d58c0cf05ca7ec15d07354a2e14133c6ec0de29767724494f4eda870f3cf3c0b3f0d7d90f76b07d54534d46cdc148914d3ece76c364f70c8185363120d89eb77f4e568f618d97db5079fe44d9da701c37025048a0e47f1d395ac106b37f10c44ef8c6e1c492414e45f1c0097bfa7c1a07f93b651cea52cd43abaa3805f152a2fab6b37068036f810d5c2fa17f65a4f04560063aa8b87605b98684f0616a05c0ae48c2adc37e4ee24a96475971a7561169aef4271c5c4f4df79b7", .None}, + {.Lcm, "11d3d23224bc5d63ac4b175414d9412846412c02a3bd0c6e8ba2b2d27a6daad3a95ae1d0ca22676646f40a7caef2fda3bb19462c149c0d7372abcd0d55b7af45f274ffe09e4c652b2330c7eca5b7205cc481419e52da146279a19dbcd3b3c923c0a52c2f0c49c3bf91c43ac21bc7e4e923038bf5b2b71f0b9fa8f465311e2b23c083f8d898b491274152a14a015640c8782d37f1acb4", "-24cc4bd5d90c51f63e431580397dfb8d8e0b843ee9d04ed84943338cf13d5a1bae72399cc07fbfc095ca8cd59a56c20a667480b1ecec303e39507e86ac6d80a6af4bd6593662911bb047b4ec613139f3ba717f185cb4c53cbd2648ecb788fe9fca9f5bde71c6c314b235410ca487ec9fca87494d10cb64fbac9c9b55ba62cf8ba5a1cf15f0f979eb37dd37eaccd8180530c56d5f861c", "a400e8a003f021eda7be4abfaca62c40bca4e6b91b47346250b942ac7b6e2b21b6830bd5f0a0882b11bde2379fca379cbb18bd94070f54f61f7ad7c642db5158e706a757baa62b7f2838ea2f2b564eae1f0b960a2ac8f902f4d75cd4dd08d2d2d9708993fcefb8fb2634ba14596e5205d76811bc2e415823db01e8c577402900cfdb9b548a5faf65612a4448352082fc9c00a5428726dac173013ca32b0cd15cfd2c86a05488f5d7f035e04453ea4d5d0912e5cffaf2153bebc43f712f936e59562e28f25e00a64001c0924e1518577d6c33c5a8933f409666caea54e96e044659c48b33cc3747215cc85d79b91accf05a67a9c4f8109e1cbfaa4989d18ebacbc0c795bbc8081ee43dbe7a0cc70422ee145df8c4c12ce89b1da465308111953c98637e9ed387fd966846ec", .None}, + {.Lcm, "-36d643d8a959c3e1edc675ec1cf2bc1f9f7f42898829518f7b29af15ce1b169c8c04f14d3450565ce668061a460f057d95f05a685adaf96e3ce98305afae0a9dc70d1bf357b10bb8d7b0ac3e9333ef679740241937b23542cc80c4ed2655ae8fa0907ad632cbadd0e5e91673420477f785943bd7352bd763137f465b3926e4523f68b15d5b6bfc027afc58691e8da4bccc274afea499", "5de3f646d1870d9e8fdd271f833d3e0e80cdc19ada2ec43e912b1f5ad5a78d8ce2b044979ad2174623abb8680cd0bd870f297ae6c850b1971331d8bef19ca24e9100aa15e4b8b6751d7c6accaefb6517950cfd9c1c1b5a74174a26269a3b7101134a4f188da825f28253e4b607d27f7e796497768e1e47f6b7e9d543aa243899af050ccd6c7937f7d10092de8f7307389e3ae9f2ff01", "141cab64ef4e6208d78220e8e11c176ac559a2f574386c1eb5bfd1c48748ebbb57681a3913e9890fb5f349ad03e457828ae1738b26b99d63af0048b7ed54c3dbcfe87abb4468f40501b0571efa468a8fce40ff9135d32d8fde9865bb69901e4d327bd4b915a3edb526086f572db3c80d2395d252552d12f2de25424482b9fdc786603f8b224d17071601b0704c91d95036a1b425b397bdc1508dd35986cc1fb33587f05287987f2e392f7d7f2199ebf3837ed85db2ebcdc850b03610131295e29219622bc5c49ee624e67d664e25f7b0e3d47fa785ba88384f5d28f7df45dddb9d5d9aedb5994720333fe45fd0f9b64cd5b79fc7203f2361db8f7ceeb100341e4c4dbe1d32c8c10d9ab834214b485e4688a351d5e84f8f1df00c18b25762761d5c1d0d0dcc3e510bca950b99", .None}, + {.Lcm, "c34de193b1241d701d23708f74c178a9e266f6e2f203b1234a60f6340b2262f86382f559a45b41fde5ab2ac146a63a0475ab66793da854d390de1ac92f9de9f9af89edae4347a5eb651f6718b6175bddc421f5cb290fc9011cb8e11a1804fe68d1709b9f1c397d9dde63b5ee04d157ffe638ba4753831e6c5f9206e0e023397e4040ec63e324b0892c02932bc4d2dd59e609dc91fb2a", "a65a63ce5803743ab94d348a78baf178431f42312e18807ef0bcf10f1e42e144d1f114a9da6cc55e1439204da54b5f8dc5e1b14b7c04e707bda75b9a89179598d37af05ccaccad258248a03b9f606ca3c12bfee3472e863a7705260887fb5a53a0e678bd65f91eb161c2333f9f5eb26fc2941501e207618e5b53dde3447d6dd0efaef4be54fcb9c032474a871a2f3f982bbfb789a387", "7ee975cb9cd6bc430f9af8ba2b62a7d6895f310ddd18fd57215ef263c2fefa9db3aa1426ed645603a83ffa85393a7f7b6648b6da81c17b5ac2fd7ca48995f748d186516ab7c38d3a05f7fd972c68d3d47c001778659b543ba1b65f14763ef635d092c7b13bd664ba2135c079f8747ab103652564d8d71cb073a1cfbc0fd81cbb89905b0a31848cae31587d319fe97eb45d621341b5574c7534602206257000b0c3d6810f66fa25dad119444ff6c5a7f4d48cc0703ceab652e685c4d915d6851007f59d0d0f59ca8054543e1130618459c2d6f7ce38c90355913cce64fc812a4c0f8c235705305bb66b22ca665bab4f74027a93b703b3a80ad7f442da599e207e2b94cd17cbbb4ad83755ac92cac8906cf1d7f322e2b92404d7c307ef1433531fb7c9544aacde6da4b3613126", .None}, + {.Lcm, "-8dd5e024cda985ce89c7718054daa647fbb4b9bf3d7a7c7f5fe3f3f83cece9bc735178c4e374fe6194ce3d45ca926973d38e2e725ae75b847494ff6d8292b4248208532dc81dac0a00537cae9a2a26bacee9182e98350e4914a91f0e8752ab68eca7d6c318de096cae6590eda755992ecc4a3af4655ac67371aabce0fa44f4a81bfca09da0918e828a53ae3162a2733604bb869d4a6d", "-8b7aac41a29a861576b8c6cede8807a5c40421783d1d513c60ad5fbcc30504da9fd1f998ffa56ffb2d8f115f3e7a9dd9c1ed0dd9b891ddd833c24ca3013d0070bce5d7ca049af9a35988a1709d9e3eb9aa4b443f73709774b5e02db8a5eaa3ced3fd2fd15f9d09fec9eca84096b3becdcc01bc5fe49716f26d517eed4a5031c1682ef245c9dd15b184e8c820f07eea0f33e4ec6e6a73", "4d471810dd32a6c0ff1d4c32a7840161a137b66fca8efb381772deb7603ea94eb11a36ef35c6ec0f989a423e7c761a768b59a6a9ae4dfe924450edb3b284975e514f85329bfea5551a1efa29654fc06c1d899d81630ef8f1d2c3590df7db3cce9c3a7bc6aa273f74c7847c37d62200b3dc4cefae5d6fd12c1cf374b46316e18136e8e395e6d17ddaec1151dd1721c7fa21f31c42c72e5ac0390bc2b119ff2e1dfcbe87f02d4351399f45b764250b3a317cc3e2e1bcec17056907df663aa35866fafbbe80d99a3ade0286af941a05f417ba07c4f7a405401c39b15d537b0b740464bc15c8d6129d75b13f58a78aef2f71aa1d1abf9a7c3c254fc6a27232edfcc7d51821b001c9e63c4e3c94ebe8ebf260215150d6da9341dd1ff26e03d6d5ff1412f0edfb40339e41104f90f7", .None}, + {.Lcm, "-a210c162e0faf829df5d5515f42bfee0dff2bd59152fed7d070c4aabae5c5613fd74b7b5ebeb2527471c0c61ce7be0705d92847a7b24c807da8f76dd7d0ea36d7186c702851a9c568e3b95e05509e72e2027f0471c2db7c4203880d5eba6d17cc5c5ee399b34deaae00858a1409bddd17ddcb80a2a9dc1ffd50ed8a2da8df4d4f673e4770a325bdb60f212f35367b3665a7dbc238b71", "5e06879338227f02f7cecc76f74b76eb7c547054a01ba126ad496a2a457da213a11baf31d4f91417fa513a28efbe908bfba84a67a087a7678124cb6c1a2b7818fa40b0671bed9d5b1413cbd7e1cb93ef4082e1df0902de4b9d6c144c09582f2358b4d785ed2ab62475d55b457dfbf160d6b301b161f2a45c84b57af9fd1e1b26598643eb5ead55da11c205f352ba6cc647a2cceb8579", "13d76dbe4ab05f7413c1d69788620e0deac8bc2f0615d50809de97b2b3c121ae9dc1a1fcfb2ccd0131fc955c60eeb10eb300b107df1588ba384c29595705e0e9f839a3a2898f8ba7505683f396d6adf43afefdc2d75b84d6c58da087e2455ed6c32534b517ba69e0a78c1f31c8244814a8b1c408667584da8dfcaae3a475a187a2c0c703eff8695f51daf616f39eb4576cf6583e439ddf91d64024c7f411112a9f859456c2be65f138346dc4d454501987ca19a1650a6564317e30192b87b2d5a86d4aea95a3ade839d4d0faac67408339ecf91caba8f3422abbcd8f141e4008442564616a2d5bb17dedc5d30aa7f8a1ee14ae9b55e9bb1d990a4ecfec66f297c739ae627a90a7173bf7d331e7eb9211480e91038d1b2774e0253a79e664472cb8e93b7be3c43c247afddf23", .None}, + {.Lcm, "-316f66135baa832ab033e4654f24d4e6d097abb63cbee9d8a52f45f84af4c04864980aadbae50cc6f2a316aaf5de94fee64aea8787db607544b89250219c3c79c027aa69fd286044f311b6ab1a3920363cc8c7725dc43ffae83db5dee866520efbfd44f794c61783fb0c16223069e41221f796654a8353d5e30959f6d698f948d47ea071ddf648bedbdbfff0d47c7d5cb37e633cc7f2", "-45508306260654684c1dc6fc4dbf4433b4283e52a44bb600c4c5770699d3c49fcda1de7f96a96611e7bf3c15e2eaf7edcc02b7c260e1e3b167664a65ce04cfce1f24a67b5a6a9f35dcb5bc7727d90842f83b447f7b52a4c63788e1ec969d0631b68f0553fb3517432a856d0f9913d4ec14cc574421438c12eb10ec373ce29d3abf4c911fe6fd03c12cc10a60ec9037b8f5598a5432b5", "d6292a04ef1a90fdb7511b32792e13da5dc457f0ee88ec8c9e8f4df2e1db22b29c7559c2487878c3ae0567c4e368dc8d351a4257b9c34dfe5db114476d17f92ec6930a312462e166c0e911ee800436d43e048a0056f4f5c577b437dffbd866ef551fc627fc8ed499ff056c24954c8703c9121edde058f4141ced7ec1fec3a6ffd0aef97c2a9ed7b2ca95543be438dfb2a5f33f3a13a691baec0ea5e652439343370a6d1f5bb09e0968852b39c93c0788b63e9085cc5287a5497c35537c562f0b3c44b2d4e61748f06f350e695bf14448bece335ea3e9e36e2d073c68c4498833e8439dada6fe49ab49708ca31fb7817a4a458df6351a6d39b59ac71dcdc95bc5e4268cb46f8d263c096cec894bf049112069633991483c13fe4fcb2700da72c93a2f65c23fd089a186ea21a", .None}, + {.Lcm, "eb64d6c454ea01aaad148fcbce6fc6f04f15de0067396b7a25bbbb03bc558159da8979c5672e9fca01b7ec1e99accb74e22ad56e708966e1424820b50e5765f9b20abb05dc7694f9fcb2615bd3fa35c0712b0078ce4858f7505966ea821498e41d8868e4f6c1b70e7cd33aef6721c9e832f4db627551169f280a23f9763fe7ab306ddebbef0ca12b68ad741c6c2ec34c6b4e860d2308", "-707a8f57044fb4d3a4c7a375be02598dd8b48f8c8414f80699c0e42217f675d0d1fdce72d1527dd4cc920a1e3080ec278de414a0ca7f2ff82c1da8f5fcc34ecf70a77ca00ea28e8729e41d47890ba6143c321cb9f3ee8393f0f99e8d1ebeacf2b8ca626564d670f94d53a7796415fe7b4bdd82e0c3e20d6fa699b047995d962c34a8f30988d01bfcfad9bcb5643b3e6db9181bf7a92b", "22799a9b31f8ca0ca15b287a4c9410618254d6c12a723728fcc7203b5061347a376d82a483ba5791b6e18ad96e324f21522466aebc86958b1ec797b01c8cdfa8c1ed490a3e663ebbf41165b040967fb149c0cc8dce5ab37bbb57962b9d49afa021e6e568af0f59600a9e8cbe07e4216ae9b23ea3ff26215011f1312c787f83604567e46480a80cff6e4761a8a2f2e95962c51eda1e4c8ac0f3ec20dd917dbc75db4483a94cb0c6b952ef6b639e9d2d6b0dbdc1422f599abcfdb5e90f3312f69ca7619b6a7902fea724bb0aabfc08dcb29ac9775ab10611265fae7242552c2f3f38163e552413b5287a4402015a10a42feaf70a88e2c86db5d5c46f321ff3f3df1319a0ab2af36596f7f4a8730949a3b20b70fbb399cbc317abb46278569659a3d44b995453d7e2449c59b8c8", .None}, + {.Lcm, "41f29d70f9c0c435f7a18a15bc60d4275df65fb0f6e67b8f308133f52fbf428c8d55fe6e604187854c83905093b723021209be866f3cc63c2c8d40d06dcb8e83fce8112c1173683837174deac0aadcb51265b9a19ba012fbe6466306bcd3e172601513fa2664118fbbc10fa5935522daf6f9d7da5378b47d190b608ae27d34483d35b9daad08b545d0276c4a08a6217a34b24f76f797", "-364c74bae00d6d9807e2f82e5cdf92440e1754e5d186a633305c15569f34668efafca6308e670d02a44bd5b6a759d0570e42e8d770a543c2a0bbfd7adb3163a676bfde9663f86e9c6c52063b60285f520bab018e89f1274d8e5474e8df34362dc10362ea88f289a7bfc71f64429bed103aa13ad35373a950e60f122ff98e0d4e1bc8301ab41edb5e21a6219dfd704bf78ebdee12d592", "4a99fc4e1da0bba40898c45c4b76683f1996fc4623ef1842ca29d91f9b7561ccd53540df403576fe46b3f0ede3ff97c0f3f1a6b6e20136a890f790f9bdadc80106d9c271148f3e1e3c4c43d1c6a017b3871d191b0eb45956dc28c2fa1015686f4625e54a354d739e833a8d100068bda4b77c7ee9763482635f00eabd5320d4b8afa743ff778936a67e06eed54bc92dbf70b0241d81026bd8fdef71e72e92ec1c0199cb1cfaa3a143e363c118b4caacbe581fca75e856a77119f468e8fab0f1f07eb03b82065a900301dc6e1f9b6d1cf9636a0117d79d2fd9a596caf25959b53d06cc0f04f347d776416fe9111c8913002b27cdcac32faa2d7793402219f54575e6eeabc16d6f9250c90bb0a4b6daea6db05eb88e268ad9f0edbf24dd1e2513e8c72566e029ab79cb2d29d0a", .None}, + {.Lcm, "44303f044caf28e10428097cbf897c6fb9f8c980cede1718793cec601d3b7093ef6ae0349170c19f3aa4e4840e18fe61d682b0e963a595f9fab184d36d02296c558b763b6d84010d660483f27f153b581d5c21d50cc73ff68bd3f1bdf22f886fc157f0fb4dca7d3dce07092ad6976f7cea012557434aadb0cd5c95cf519e04ff4605941140a80d35802c1b74eaa7d6184ca299b8699a", "-f1f7d8064076ac0d0107161c16e68adda1237f3905d303ad20eeab4d2477ebde47b6fe98952fe8ec85ac46ed54224691ca80a8372f30b081e489c629a7926795525129c2959a289b8cf58c728b36090e175b9be62d0d8596d84399796187124da7706a0ad8a96e95ad97982ab47ed5ec73b3b480ad8081e63c504ad73ecd8cd35435a091dfe71ac1cb48896240c13f81337315892160", "2039b7b51c67d48dee6a68bf41f93f116f5ba9f60e7950c3048b8f5e237691b620f63548354e4cffe3fd248f89652f85214d9e8e7604bb42721c0ae0bb64b2964117bfb902bd9c5cc1cf7525d7d31c6e71ade4eca01a1e14846942fdba917e4c3fad5ea2c1fc73d83b2ad2654398373d7186edaef7fad61d7aaf02c8671aa0a8020f993439595c7c538a5f95aaa656697ed2a88a2fe7a55b7a2f50a769e638e17ad67851187234c4f916410c3e0ac9320b686a11a4481f15351f2f410696e91d765b403a34813903bc3a2bc17e2303ae650fd64bf1512b583b8f842105b4fecf2beadbdc552436b21af68b756461358286bb0908ec80161f8a4e7ae8ac3b6e4a08fd4faaeef1f933edda147573e4f2c4fa048a6e7c2097ea77365bc36555433e18e6fcc1560c9aa9481739e0", .None}, + {.Is_Square, "6ff9c7204336d7279bdd07e4bfbd8b19dff529168513807a1fdc9d24c3a771d9506f70ed36fcf3a4368afe46e50db88a42127d941b7eb3a36ec700af096440dd9a95a8c1f548a995108a5c93d6c1c54cd56bc0575cd16ce2a5d978c5c9df88404a34c589339a58f4ad14fe67d5c2635defb742041c2072da15288e6955b016e491621de821cb15badf1672e2a9f85ae166b1e80ef9e8", "0", "0", .None}, + {.Is_Square, "482821cb825d8809b59fef6bc6c769682a9fd80db94a25a0fcabcf9be270ee97f9ce265c61fa98e6e6145bb65f79961b8fda88c1362b041cb5fadd81fe9723f445495a7561df1bfdef24d668f1ccf82df1b6d4851e4a01e1d20eb6babcb47a9762a45770c65502e2fbf71772af63f96d2d26ba816f5597a0fa5dd82b5bb54160fff8dd2ee9611eeccb0886f5842f80d87edf71478230", "0", "0", .None}, + {.Is_Square, "9590ed552e02055973196f228c6496156786e33a16e91ca1cb3fd60654a9180a42a83b333be5fbd031b2d634c04abe8aeacc60b8dbfc53d2bea7ead7c0cc7570adb413bda2273b52b1b490f2dd77fef2fcc2336ccb4f4be3172709ab875f55cbb2e8ba161768daf62a903d4c57dbc492e4e7a873e8e3de2df29329eafc96ea2285f43e255989b01644886bc5ae98236ffefb357a22aa", "0", "0", .None}, + {.Is_Square, "fd23d6ce100d23f1123c60d19aa2e26c8b1ec67eb6e8ced4d2cf231b559fa0386f5ef8feab9acf40888d5d20bedc9426c62e8148091310ea14225620dfbb3bd6027a26b0e9f52591673044f9334fc8282acf40b094a3dfc1fe9acb3bc4e3034988f47ba7393ce2f050c2bbb5fa175dddc631487114041c553fb1a9070a03d613aab4f7eed1a06de1b814b7334807df736fb99f7e7752", "0", "0", .None}, + {.Is_Square, "a72d043c84461f66469400daeec066a1281a4a1681a8d44fdc83465ce30a1688777685831f01df27bf1ed0b3b74f0486f68a9d6e8c7c5b4fd84148f9a3ab2e9ae154596b6cfff41f3a64efc609308d9dc8919eaec01b3668dfb52990e1cc1ad9bef421d126d5ccf4a55e91f31a3c82cd800e03064c47301d73d9681ca7172b18e67b43f1fbabae809f05382c9fbaff4a463eb7a7c411", "0", "0", .None}, + {.Is_Square, "bf42008656f02755dddfafcec18e4fc284630a6fea977763001bd121e0515fa390565151978581f2c6c906059d9e497d05193ab2afb2d068c73c623784642121e87af7e09aa9441f0a9c79aa8bdbdfec4d727b945ad2e5dc36216b60ad153e8ce8aa800f0df3ef32750f9ef7f970dde2d11109493a242b64421d5ba142118e98fa44f17cc3ff6684a4b32a4ef2e1597c223c6fdc6e08", "0", "0", .None}, + {.Is_Square, "e5c9c91134fda852a06845d7dda66a33fcc178605b31483e87ede27cdcedb6b8a75f94fe20b904fabef6375d5130e2c963dec2d6fd7b99dc843b293b43e638b53169f80486a1cb0099288334494f7719425288f365ff3870913b2cbb6399dc9a5a3f0a721ba5e24f5532fd0b30d4e4f580af2a2bb8cc9c94b33351952dfa261987449560a46921655f6ad7429a0a6dc56a4f637659de", "0", "0", .None}, + {.Is_Square, "f8eed9e715c6655e9ea9cb55f812f23fa406719d2d53fc24ec7aa6e97f4692123e99c7a15a1de16dd7fa1edb5a3c68f81e80cab6347fa97df9eb7738ddc2a0b31b368a2634bd89a4d83847d582462d44d23debf5554f3f18aaed1ce8313cf5085eb038149e22bd930b5e20e82c203b45036a5928f21c9e5002ac64ae82c5ba838cac4f55b4064d14a897e03f285254173fcfc0294a34", "0", "0", .None}, + {.Is_Square, "6432dff0806c950e23785a8c764fe2b3102eb313b4284f759442c4f3c24e80b857feaed0d6a9cefe7daef1cf3b71dcc721010fc23dcd842238f0e8766af4e1484504f06466d89d52a50761f09da2266afd3fca19663af11021fee78250ba151f0c691e4d5bad16cb08a28421df72ae64fa85ab16f95f1e0bf8d17ac3409e9895fd2adc783e418d206f54ee7c8f27128301f228c5c5a1", "0", "0", .None}, + {.Is_Square, "748b6d54320f760c2cbeb0c153ae572940e89be3629b2b70544675b2773c5e36a4cd0f64182877430a6c6ea0366888945b3acfc9b440db0e1e0269cdc600a9e02397a167d67d3a7c6cf473adeb3c6859e1a410ec2e8ba1484d81d96779a527375f5f49b0b425e3df220eb7c2417bb981105035b3e742bf660ded6d1d63b0f61e20c23842446321a9c374d13f929b652ce2d70356796b", "0", "0", .None}, + {.Is_Square, "f91a460aef6fe78563dab6e5b33b1928c7c0f08cbb8c755d4988a571ef32eb7039421835c5728810c73ca7f41392867607d3c710a9c3a15f5267adf07d379937f4fc5b6e02d391747601c9dbbeb2a723d7080f11dab8ba0d484274062e94037eeece713dede30e62a1398ca78048447a02674387e54ffbfba80e0cf7e65be33d2b516fc998df4d2fcd18a0d49eba027e437bcbca22b5", "0", "0", .None}, + {.Is_Square, "3eb5906544f6cfa2217431bc99ad03161844bdb3b53f5e98fc7ef5c620d6e603100134f4dd5a1d9ffcc4eee645eb25120605623a247fb05d67753b9e1ad493392c13f298ba68c189477fae9ef7e3962c35b5bd4b718630f9bcc33dad7c7267d7df903af7bd9c4448c3fade5342e4dff9e40c9526d7619a640de6c31a15e8172b59e7e32fa814a2f10050559b74a6ec389412769fd216", "0", "0", .None}, + {.Is_Square, "49dbad972992e0f3fb681870b77d7273397d160bef10fd0ab51116881c45fe7c27fc249960d097c1fdb597a2301d03df30f1eded48c33f447c88cfce10c0bed5a097e4e75767ccc15d7aaafcf6b483d1b68b8825420d46e3eab982ae87ecf2cabc3adaf2805c1cb9ca9b0ab4e3e784c74899a8cee088fb0314c359cd65a24abc14216579d6f5199a0eaddd9da366f5b06c829bfda430", "0", "0", .None}, + {.Is_Square, "d39a984e4814cb09aa2c5f440ad5e8d26b8de1662d9192ad8e99bfe537ff91d6155d6c447439193b36a39da83568f321b93ba893b16f186eef29076bd75cbeba72e47ab179f1a6f0c64ad629f3d3a9f01db5d05b98180d315e7d2ba2899938e445d1bbf1db91a1ba2b4355f25524cae54688d07b119b5e53c8d153612646c3d5cf9ff4721ff9cc1153776791e74c075e96346d21d45d", "0", "0", .None}, + {.Is_Square, "9f1c5ca65141ade394b41e007e6d4ce3cb4d8ada3cda1770e157fce4c87b447a2e3e8c30bf5b5502ccbdf28e74aff22672a584a55f4eb5e629f16ca469ecc9e43db2293f46fd8286a5778b9ebed973b5cd11269c0d18206cbb58c7021b153bc2aa09c294953beb60e4aa7870565c0ac638dbe5c47edc77ba0d796e646b17f4f2d9189f6856f1a24be04782d0329f065c0e05aee4a6d4", "0", "0", .None}, + {.Is_Square, "92e892ab51909c98af72be0edc132a621ebee6b08650e5a3a60e33f783aa2f5b7f1c1c140c6a0d02ec73221f190974a3484c43fd64a51f28b95807c66072f26e794a9da79892a515e8ae9835cb70ac487408f95ccc3f55afb279ddc7f8009daea492122415bca0e8c0424c0c0e9cb1eb8e00e1cc8f0db7823edaaa21b5e1c9da5acb2d4b923a2c1d6b9b70bac0311d1fc31760daad39", "0", "0", .None}, + {.Is_Square, "9ccbe47988e852cab4d763d5ba2ca7ab363d43943e8f4808e49e83dc8d17de36fd91dd365f54a1f35a6ba7a8416979fd8085f175d38e3a936d779c05f5b5f7d0ab2ddd6e657e467dd0fbb498ea360c4655f6618a2e3fa8e20bce4b18688a04ce01e4bb1012bfa6daa64ad620c0b544d12844891aac424a241134fad9332f86f8e8ea42b6a8261c9db27888900ee90abc6a06fc8b2041", "0", "0", .None}, + {.Is_Square, "aa31357aa4cb65524829173c430015d90811cbe389925baaf94df039bc83dcde54922332f539606a449ce76c8769df443f0293aac6ef85255106949d004af7ccf69a8858c7be0666f3157f5fa3db49fd469514575b200f707e7c62e287f1025bfe0116a4a9baccf20a6ffa879066686fd0689850a920f2859b69f4cb4ed2fba1d0828755af183ec2a53ac6be136b32789d13ed482452", "0", "0", .None}, + {.Is_Square, "22b7492b2cfb5cc51583016f7395818915fa25c01ba7f8662df3354e899a46c0232acc876282d5a3384cc666476efe794e985e9c98f4f9dd36e43c92c1a79a0598cdafabc69d8a9b0482c7d527ec47ce2f54e46ac031291536559e12157e2945c66927b4b9224765e89385526b76272b3baee99057087ce4fbbeeb230abe496507350dde7c78e803329ae533da21b646e08e10a7ffea", "0", "0", .None}, + {.Is_Square, "80c317697464b184f58bedf038b0c26c6da43b660f6263d86943e36a8311c93c5f5287776534b0f2174ceb5be46b46c360e1aa27ddb020f2ff4fe3234fd0db9ab5ad0c279943800bc3b3cab01789f3591d41027442c01b19a74a17c6fcc1ae81b40c653fd2614798f38b37d9f234dd166ffd7ad8fc71ffa6361624523b67f671c3748f690db777d3ab8ef5bb4931bfd2346421255c0c", "0", "0", .None}, + {.Is_Square, "20a765661b1a4ab7961cc82b1e0f89703f149f17abcb014951670537fb2807c15a85d022df8991fefd3cef1b8b48ca6a5aea717b8757a5455ac92fa9247d60ca57ad406be8408f40f77b438b61070a7292cdb64a1252fccc0234b70b6bd20db3a4b8d3c133567e75e5b0d0b09c39066e6330c513d3c177a4bc507b3ed76c4415c1c1e432fca3b4c8cc01b744b4672ca118d418fe258f", "0", "0", .None}, + {.Is_Square, "1a8c55bab29817d0bc26364bec2eb671068640d333caa754e7976dd87b76d89800b117e818cbd653d5fbd5089a395dc4f4f661576000f5df3d5c802732c78bf4630f22d3e0d831c11af2f0c4781c55c0f5bb005baf6b9c11b8091196fc6c2f25f7fec5919889d31d56fc5f7742ee720519975ece4bafe9885f157acbafe7d3e688aef6715feade2c10ed4fc149309790faaf9caff93c", "0", "0", .None}, + {.Is_Square, "d03233a594aa8cc1d840181625e9377356ccea3f70db0575a307599670ae7ffdcf166aada68f06dcf7015bac70b2f40558abde26de9f48fa6fd1db366c38c86cb290c96aa6c17ea410ce3cb0054367e1c67b588fa915bf5ca79f8e0d665d60e41f02775652b6a2d01a56073beb35e534a98f911c0f4f2d22458883aef8e066745d259b3603219b7949f18fcd792c3d15e699eb647a9c", "0", "0", .None}, + {.Is_Square, "83fd2b9d13cdbac767b9297014c8686edde1bff46b6d3c3d34330c8432201a0769d998a51b6856386465ddae9ef513ea16a38882ac27eec84776612c25ce7613efcc428b0176b2b907d205975aa730c44613a67747bf783e226bf047682634735871aa5eeeb5a58cf9da9fbde5398b7ea4a814385950bb953d7f0110abd1d5fd97f7819e3e9974ba5ba9dc1ccfe5ae90eefe50de171", "0", "0", .None}, + {.Is_Square, "f1e4033516f827213f8a2a2c4f97945a92a99564a8c5006322d5d7f515c36eeaa31f0bdafafca554ae744ea2cc241331232f585b8fb12402ff0b3f689bd6c20f236bbff2f4217d6b08919208044c127e7c09528b28893ce0cb3a92c8341e469493a930ce02ad3adeea0057a700d14cb1bab5f1e4eb94d82e41e1f0e3ce969c4df861e878cd2aae19e890e7e38bf3f4369d411694c120", "0", "0", .None}, + {.Is_Square, "48c19682b5055d1d31485af53eba488f5f171bab98686153d6ac3d05ff37211a4d4eb9db8a9c276b0ed6c4fe05a10ec02184e26f42b3dee597e99cd4219c3248eb923adc554358ec0f1d780e0fe15e9f1e6546a3af7a0ea99c2dc68632baacdcd70830e6709a54645bab7d025685633a25a5a9bd30536dbb5c4c38ac70796040f3971a03e6d1a5bcc7ccd021c36cd29b171056a00fc8", "0", "0", .None}, + {.Is_Square, "a5848a470ac64c177f266207803edae7acddca884e1070ed17c0bdebebaa9ce50b5849377e670c4fc9045919dce6e10d48048da1941c3f13c2c8f60c347b067377100fbfbfc4c3041c35193228b874509ad621d51680d6beb41911dac61d1b0c0ac9d32b742ee47fb7b10953b79d7c2e55842c9cc577e99790df4b31b36bb683f6a610582900d25b0dc5a152e9d8318e76beac33461", "0", "0", .None}, + {.Is_Square, "ad2d753eaa9bb9679de844bc024164d5005bf47c8f2997dfed4ba3235268e34ba7193334f3c7e5f5fef0dbaaf25d852c13cbc21cc2c14a4b75220d9197bb377007af12e01e82194ff6f09c1427842007f42c40118131599db2b87a7d150d61adbe200c0317105425282eaf9a21b6117b81b66bef12919666dc752f436eae4b046bf583b0dcf2c1a6695ae0c156c44bdc5d394e76fb97", "0", "0", .None}, + {.Is_Square, "47681e6e1fb0d7431ba09e259370961874f84fa51727f7b2c7e4eb7e4b7ab84032bc3b3c960bbc5c4fe70fee167a27e8b5c7b272092b546357a98f501c5e9fdf4b648627bc156acb8e5d47a79b71468435c965275a451c0fb04146ea38e21fc8b7ea2e60f9b5d81cec6499040e6ea7b3a37a372497dde6479fb8652b5af1d3c184b1a3077e1bd4f65c7341d92dddf82425cb41f070d6", "0", "0", .None}, + {.Is_Square, "8aa402fd487de4359ee438cf0098ce8b41589834ccbe5fd92756a2bef3ec25071b28a17f15587cb3d0696a5673e2b67058594682fb24c3a7c28836f07242ae3a97fb013caa38ccc34c6af59dad9fff97fd548c8e00967e7eb7a2e119a41041b7e804c0e19731b44035008732cca7996df09edf526c687cf23535008aa2b8d4a364079e8f0b24b13bace6f4d1ecf216b0533af80e44f", "0", "0", .None}, + {.Is_Square, "e8c49aa76374f32a08b9b96e1acca9c0ce508783ff9c90fe61e252a37b262364b127bf1367aee443b874c2da3ce34bb13a5260f4d3887d23665b1dcab7a95e05d1789cbe3088a2527afd8e8919fed41945f8a4146ce72246ca4cff10078aab4bbec9d40724549a3d2ab6ff81160c9d0615cac9380851b9478cda38f4aa461ba5139192ab6e12ac828e236f80ff371b8abd149e9c72e1", "0", "0", .None}, + {.Is_Square, "5c343d96fa37c521a61b65bc455318ff4a536e48dc8e49085fc89c6603934b125368e04ad7d6891bd5c47df716fa14b57cf8b44c31de399f6d07cbb7ff96b1483e251be2764571b724ece4292a125f3a5dc79e7785c33df88c84770ab9a6be97bf4503e1c73b3c9916512f1973415341f50e8ce5262f0fac77fccdb168cf5ff4aaaabd26ee86b8abb47c7339ed585df218ae707640fc", "0", "0", .None}, + {.Is_Square, "e97509676bac9145b47d1a4d9d38ca0c8eb039cfcce73c378b09d0242445e07cbdbf63090845675f528a59583b7363176371d66a359dccaca5a61171a277848991bd9e5699ee0c1bdc5b59832bc423f3070057344a441601f21b8b194135945642cd2f01ba24bbde4e43ed8b094c7957eafc28db14a481aeee74d1b60969c1bd038a0385e3cc1736ae2950094ffea0b3d9d8ffd1868e", "0", "0", .None}, + {.Is_Square, "9019b34adf90db9c3444420e03d89b37a0475cd2ab3a2b7dc84895f1965275150dcbd1a492a6b95de14dc137c6ee83f652b35f640bbf865f80e9c724705dcee04b14f62f5341da41ae9e698a179217178b4feb5a6cc80ad8ae6be75bd58edee4b58d67d492d9d4a3584dbe24d1281a536e3f83bfc986a2fd3b5e6fef2e8e551b2edf777c3304c2863e22766b561bf0a0636b2d3a4a3e", "0", "0", .None}, + {.Is_Square, "ac5135863a0ea24e5a2c1796b05d760eac8ababc50893458d294969c00b7a39fa043ce0327753101a007db83aadbc1f72d942d3ef9959ec81241e7ba1272ea05268597a0d4c37167ef39516bf1a68c3bfd30418f7c162f5babda24aaf7c448b0ce5c93f17131b1f49c2bbeddda1e1de3a0861816bd23b74a57e03c683ec49e60d4e9813b1896c7862e7b34c87dee96f04bcbeeaf4a22", "0", "0", .None}, + {.Is_Square, "f1fbfaf87fa8e7711013a3754ef11b286762b52379bd2ccaf43f35abbe9bdf7e652bf7e5b93febdcdc21fba6b1810f5f739cdc4168d8b41c66e4b28d1cdf5df93f75e592ba922fcdac5cbeaa39c3397e5d580ed80d69e887b181e8b2aa8aca6dbe0331d7f308368765cf7a7d7893139c8fb9f2ff89f03a06a06dfbdf9e68002b34f8ab140cd8cf5618d4d424ee6fa09fae750878f97d", "0", "0", .None}, + {.Is_Square, "95dc33ef1e7aeabf7fb9633b91351208b8bad4cfc45310173d0619c71494f9252c9a925a9b66105f451bd0d9e9cb334aa224fff386c8701795a445f45d96dc9cd610a9e69b072e8ec0b27d6d6c44f34f79c1488707602509a1d5ec5d5cb53caa18ba48e1260cc5317312713090c212c9a96ffb927c145d7d8386c97b9520d259b54187419d9c894d873128f25d0c9ae906eee37802fe", "0", "0", .None}, + {.Is_Square, "4f281bfe58693cda7009c471434cc2eb242e11082524531908025d1099fcc296c1b0e527ea1fce71f278adcaa3e25dee2950a66419a8e5b410fc3f0ce64c618378222a791b0ce91166f4c1fb908a65578a3b045d42a16d9f8bbc02d79c367f430cc43755e084dcd722217cbc45fb708be64ec5755772485e8cb7784ca0e012a32e27e5587d403591cc5386dc7acf6ca36dd1e5aaa1b3", "0", "0", .None}, + {.Is_Square, "9b324c170612c394e6d75707ebcb069ee19b44ad0200f4c49ff207a62441cb8b37e25c3d3a2c5cf7c444a1a7c33d2592832252e3de0c234bbfb38c0f92dcd244f9120ffa202a92fb2433c68691e4687fdde83aacff0f4a2c0241bdc1478131e373dc294970c2c52c290a56fe3e7df35718920107be90e14b2e0bf9758a886ff9a4b1efb48ac75280bf3907e70aa2d11119d998a6a465", "0", "0", .None}, + {.Is_Square, "95283896b7a2b1d66645542f4a81b67a71522d2f56c5755c4eb9ac4d2d5e3e90d7557d5c359b917bfe0172a6cc2b41101a174385b9c6ddbbfdd929fc0e16b5a2b17f7aa261efd56173088d1fedcf2b5dc85e7b7850eaee8948d171680a8743c562cb49505d824050dc37e81bc0a97fc30e162a4e510916c2cb5916ece97d7b61dfa07d8d9b0702d25664f8054564fb35a4f836f0849b", "0", "0", .None}, + {.Is_Square, "4d8522c478457a5d590bf9e455b75adb2ed741c3ae55832b4ca3382113fd8e932de8a45c3782a47ef7c6834de95449789c6cdb1e009c4d2e67ac719a3dfb5ab75e6b18fdf81ac3be2d701d55e80402d1f9ab090ad17410a92c7bb542346f9a2de9ae8dcc76bd6f1d3050036b842845b3adec695c21a7c8634b6013a11b04357cab4db6044103e72751989e73285f9e6db5634ae9a986", "0", "0", .None}, + {.Is_Square, "2830a0a18a16324094174917ef9aace9e37747e905ecf724ecb5cf0935f4c586c31578ca0784b6a82469bc41c8d285e629956706d78f501b36ce18cc8951768598d77ee72c3c99975811e4626c65d5451a436099d3a3ad29585c3133df0f430a83fe236b741cd836e819042fc06087064c9e909d792ec992a841956d77e3390cc11fb8ec672d5f5e30e6c33fbe825260303a57b7024", "0", "0", .None}, + {.Is_Square, "7ca88d74286e154178750c3271a821285ab8039303eacfc30f61b50921fbf485516388674c99b9f7a6761c64c31828c0ff7d7df67c83b577ceb82d9c6b0f3bd90451fd6c1824b62f6373951ad7228b4b01946b74f8e6a53ea3f325f39da837900b0f6f7167f60951c14f82dd47fe109708348069827f0cb654b3e09d44b95c93a271615c6c345202e1d40cc7567ab751c3a6cd7c86e1", "0", "0", .None}, + {.Is_Square, "d847f54550250b06ad725b69d9ffc0e61711cef91e944366c65514a889d6b457e2680c51a1b42f7210737ea7a82bf5707c5f649b7fc3c6af4bd19c134fce3c3782684aae8de9422b476f6bcc8c37894cc37989cd0205f3be56cbec7b1b6b3f705f16eba0baa48e2958f84be693efdc1209e4d796a4df8b7d9950fa12a7e87ca8c2ec9718b723e5ff744408823511dfcebe3b7bd22b14", "0", "0", .None}, + {.Is_Square, "8a50c5e9467432abc01942870134c40bf2fc2101b2d64d506e71ad1577c85ed1071d24cd9983f8dc2a5c79c959430012a129bb9742b186e07a3cf69e288005739bb7b748242f457b8ba8d06ffa419b0e3eb5dc29abf268b6a9e792900825431aa4ff6d9f219bebd02a8bacca28dcbc980f65c7a100851694673a0cb5aa041d507406ad97d73fe8b2b53a7c947524f6943c1f3d6be96", "0", "0", .None}, + {.Is_Square, "74644fc22ec4153732f68adb3e5ebcb12914cacb590af6b58e23b16836226f07e2faad9957b874cc495d4f53f79db4008829e152a7f9f7e72340dbbd15b8385b5723630134e26457b7a61d9f709e492b0e21b20054ab161e93f97629231acc473db302f2618ca09c32d37d93bb179d1fe364d6f31d3d83b779c07dbb349232d82fb6af7b0a175960e8c4a0750ac003fb7cc75762d230", "0", "0", .None}, + {.Is_Square, "fe903cdd63421dd95b5a2c4cb0909c969adb04fda6aa9b6dafbeeb3648c82e82c3a035458419c08c9bbd932dc74ec41383c439e5fbae089f1edb035295104ea22e12107d46e332908dad2212f8c06e56eabef5b0e966e0ac5ed23d9ad109b592c56711f813ef9b15a6d28e2b37f071f06e367a677bdcb8b8b115a4a804e13d8f9907ada2369b382accbf5d65b0a8ae6ba2062166b053", "0", "0", .None}, + {.Is_Square, "5da4040704c65d597d5c16b2643c998e1e51cebdee97b82daa2527455cffd1ac0d3facfbeb4e13fdf8495bfd39253477952b13a5742ab689458f404b5555a59f236366adeef163b2ed565c1c0a05ec13bc8d415b7c50fd14145a2fe06ac99408a4bc4a0473a7d6ab7eff55b848c7213e15c7f8cbe1eff1570c90dcbf389bca53fe6a9654852a9b0f3625214d316850b1fedd46960e88", "0", "0", .None}, + {.Is_Square, "edbc43a4951116038cfeadbabfba04dd835e1b91aa21935fd68fa75395a4877f296e3f9a47e06443760b496e27681498e15881665de9848ab6365d981d16bb3ec609c00b9a6454813b7b05a426459ca129352769f755f7d596b28dd98bcac5677a5158b6d7db0ce328535a2921ac4ad4f14892f1a4b7a9a815f182e863d8079c5d2aaa9edd952028bedd1ea675b30e53d411f224e306", "0", "0", .None}, + {.Is_Square, "fc2f361467eb1edd249e791aa5f8116581ab4071894a3f547e9669df16eef226d47e0686bb15cb141cd7234f820855d96411a0292e6bc15224cc97e8df4970d93fa9234f25b3d167e3b7f7c77a646de7997d953715814d6d89152de4ba6d303daf1ea613f19bb1cefdbd937836c1bb5a1bd661b930c55797410c7c60c682acf396f1774e72d86bfecaca3d4e00caf03c322af9294b1", "0", "0", .None}, + {.Is_Square, "744caab8579e67b264434c0468ef79fcf04719115fa2026731c26329b22990eb84c1362bedf8e135371c97b2d293dba90f4e6107372fb29815d12f8050b3d514a26656d062b5cfbb4b1cdb6bf5f1365620fbf103ff6970e313f46e1b16ed949e16dacd75bec2bff407f3f086274cd2ac7ff5d169fd84a729dcf3151b2a1288d58cf5af9d70a0718be209e3c8978a82ae2e26233274b9", "0", "0", .None}, + {.Is_Square, "51d4356f4eb8708ae2254a9a3bc17d15648dbc687ae2ba2280a8b5fc2de80eb4e9df377385730d0f4e996885cec8da14d65b177a20669125f3c822e650b98be6da3758a2e1428a7bcad728b54f7907aba2161d8b0e050b7ce7417d18b5b89700805e39a295ad1815b4d64a4d983c181ac08ad2550fe080270a1076ea4219e578c45b89fd2052f46759b613b1000d7c5da3280af793da", "0", "0", .None}, + {.Is_Square, "da00f6e7bf2f1b3f5f402b9a7f386ed38e0299179c5ee7b3879d62a9c4388d2a4183d15064552f2809143eb06086e78774df4ede84a9f705df9fecfebaf044f26647fec640c54ff46492a8caaf12ad188025c2bccdbd954ff15204dd4163a14c49ddef2b210ea23377bcc64c9e725168d22a22bc8d5f64e8300f80e43c1f43f533448be183c34568f9b19c001e8979c3963de151d230", "0", "0", .None}, + {.Is_Square, "2bbca79d957efba0b9ca8b5e46456b9def72b9bef109619543e671e26308ca65bc58b4ed256ac3cae55e03f831ec6016cc6ddccf95d57c3bbbc55fcf435830034f9d35293678a451fe10e6fad7de4e0c87a63699ac0ccc17dfd72afd5d46a30f11ffa07bd764e35dcb115aba68ca49c385d972536588ed69ecf48c6836375d4de3874fab93cdf19456c9ab7c4bd7e9999507278883ae", "0", "0", .None}, + {.Is_Square, "617a2aedec43cb1b66bbe9f1cd50e412531a36dbc5d0885234b183bdba8b94db85e4182cb0f5b2c920c011e00618cc0029c52b64423bd42d1ec0b2e3ab73e5a5f49d44287e35963c45456c2f3bb94ef48d5bb9512f89973c25fddefc168e522d1b6c4532e7256c7f035a6a732d8ffbabeae8b8e88a26425723a4e243ce7889404f2ef9119cb1382d8bab62eaff1b2afb2672c72d951a", "0", "0", .None}, + {.Is_Square, "b430c675a8d7f6cec688335c699d12f6595e9684c448017ac885b49430a736f33028eba2996ed067bbf8f682d51c8498fc46616c9316037a2e244af7e1a729cff0c6f9573a33f2ed457efd409eef0df89e7cef252b590a0a86bebc29d0b8f070285194296f126a7b9e202f3bf0bce508f16dc6ba4169e0707531da2ec975d1b8193cf16d32b7a0447ffa47f861f286fb8d75968a57a3", "0", "0", .None}, + {.Is_Square, "78804cf1016e25535cf02f597d05273864afb8b2411b1cf03cb5c817873c38fe7e71be8bc71bb1cd2fdb58dc5304e703c3073ac77690529259f6c1ebe7ed859f6036468858e8afa19a9ac093ff8bd073df8099006672093da2d544dffa88f8ab8b46f3e7625a1a5dc542245c9f489d0b383ac0098080a7605ef8f16127e36b3a315058fedaa8367ca10d90f1aa0f746838712b8790d9", "0", "0", .None}, + {.Is_Square, "4b43d9e67778c35d06d92abb5caa85a9b224091707dd9b72c0a89c348d56704109e4f26ede0ff2119a85d2f9dc9d096fb86104e21f4fc38658866140b2bffa876afab41f97916aa70ca93e7454b361058ad700cd2d25cb0887db45d59772150b2f18e36ee087e7219d982b327aa2f74cee69788dc8668c4699d40dabe391b3a4d29f83a744c6958efdfa083e802b8d0389d04fc1fa89", "0", "0", .None}, + {.Is_Square, "ae715ff449296496e7bb5543dc07f224a69b836d60eacc110873cadb4ef64530dca78d50ac571f0ea5e31c0c6c26c69fccbc0dccf019fb544c8640b8347c0d077ba8c1f61fde7b1bbb76920ce6deea6d4da75458a5021cd81e6d4ada2ab7035748d6916683a42ff33b14a54c0c9647641645079567d0585668393c618470de3bd903ac2db1de5152796c8c120d609a775515224fa281", "0", "0", .None}, + {.Is_Square, "e06509059ea3351e199f97c4f78083d8f594cfc098a0a391f53c03bebaf1c9e80ba3d082be56c02527ddb3ed7942e6f53c1eec4253bc67f2ba763aedc007600c960c6d001b5d9f1aebb00fcccf53a912b52a73dada4b87884b0a4cc5d55bbc3fcf8ab83d046cf363b7b248e4eb683f1bba8499ef3fa3a00946f03b4673ea2fcd95776f4ecbc3130e75df4cbcf698879e1cecb9020041", "0", "0", .None}, + {.Is_Square, "e200345ff6d1b0873ebda1a453244cdc39d6c7f121f69be49f8324772cd4b76e50a4ec1744e9ef79b26cfa0437d709862210a7af4521e5153e0bc4de28496d10bd2a492cf92a6fa0c9f588a52e738d81694b5737b0807777be191329759febfa507bfa8da747a87551a66036ee4d209a88b845ad78495605f769761e098ce680591ad18715c57f72dfb688fcf6af8b7fa997cffe505d", "0", "0", .None}, + {.Is_Square, "225cef3034fb73cd27784fe86ad80872f5879d41e93d670cc77b7b3e1a1cc93273062cf372b7b0afc591da23f18223eb9381b4d2a2953038b386c6776b9e7f307252baa293ba8965e47fce5634be7ee72538a31e673ba3ddb0dd419d88766c77908194fe233b6925672057b5a9e7e3849f7ba35b2bb077c1a14ecbacafa136a9fc9d634872c9998905bd7e0dbcbdda03aab005c2808e", "0", "0", .None}, + {.Is_Square, "fd39e16ff1bc8195904695c8134046fb918cb179fb69c3b673f778f72bdecf8d6b7def4b3dee485ab5c9b4ba3a0eed168e6068c9bcd66e8bf1d700f05cfefae1b1dd99016daa84d33a8e7f21fb8a7f3df534f850421556f88705cfe6081f25fea988510b29debfa0850e424d2c61b24e51dbdd075e998b3800d7b7c8618c855195bfda906dc6e13531d9b423c89bcc9b20e2c615d84d", "0", "0", .None}, + {.Is_Square, "4515398e3a90aeff02295e75c20917c32be03b80173833545c19924f0c2990e4f9bc73f4a7028757cf69d0037522db8c97d811cda4aa51383241b71cda3b27df4aa60cdaea84b4fbd583fa2ff839f51aeee39ae01f41aac7d2517b3a5c0ac34f36cccc2e5079308ea945e6520cc99818cf19250047c2c7a3aff7d3f794a245c40e48452c352487c59cdab1438ddff41b89b1e7754ed7", "0", "0", .None}, + {.Is_Square, "3f7e0d64d8aa0bd222c19f5aed400ee7ef8c28166c76c7bc00c1e0c135b3835eb9d9b446c9dfc3bfd6c8735c8672fe0ce5653edd3ba582bccc8a1e0352aa259354586961c803944f9901cd3da4f12ab2a2261ed32bb9ffb725bce41bba49a2d705485f384830041745005ee6b83d29596ef600fc8411a2a61f0567927976c741f8a15c5459f62da82ab10ce90aebd1fbd101aa661ef8", "0", "0", .None}, + {.Is_Square, "98b9f6b17a295cabb6b75dd7a087151f870d24223d5cf2c6d5bc3eafb066dd8536072309b59a6ad4366fd9b8e29753bebc330737f038657fb4e3d87cd44b32a0dff6cbfed99f15bf1329dcf713f5c700863581b6dea30a315c6a1108f699fb6f84e794601f3a221f0e27599b3ce61a5a63ed8188a417befb45889cf0a69db42ca5092acce78c577a0779c3e555caab9dd7b83fbb2983", "0", "0", .None}, + {.Is_Square, "fd5f70ba19b7bccee9a5a7fbe77b2d6aaf4c2346d13b65ba7d6d2fbbefacbb2091276e0a10a6702b914a9f7dddc452de83091bc252ddb5aacd832488e677baf2a31577f4458c123dd278f6348bae29a42fcb51ea34bf27a9ed77c29e59e23d5d988e25a57efae60c43ba1689223483ec6cad7ca378dc2cc5bbc0300b23c0048bffb5a2696800125eaa03032e509c873ed2dbb640bdfe", "0", "0", .None}, + {.Is_Square, "fa4c2e5ef479d3f347824b36437fa37de283fff7cc71023fcec29a8f575262676007be525ba29bd91fdabaec26ada490183eb43143cff808c0662ed0e789f59044ce04ca52944793f61aba06649c9794382441ce22bd41d48b1cd18811f86fe35b6e9e5badd2508ab8260c0ce78e74dea1ddd2dd5faa3fd646f767a482c5365815022864e725fafd58291e95993c45e336a7c29709be", "0", "0", .None}, + {.Is_Square, "708d72f38e2ecd3b5002059880d8ed42b88942be9fcddb4581a20ce3fb8c7b302cbff0fba017a0bd8e42b30389b2407bcd6e755d33d1f0e4dd7e3be4121de5455f1e8babbc01bfa76450c80c7701d19342363b8fb9042dbc1769031ae89428da4d2367f09c0ca1d81e48efa6ea796a697e7e2fc9f04299c7fbd17ea52ea6b4bae882c9edc296c7fa957dbd6ed441b4989f225640bc1b", "0", "0", .None}, + {.Is_Square, "acee1a10e79009a8ace296c7ae8342f9f041dbea3b4614d016c1642e380d3751a841f7a234462c1cb5f57ef7e73b4e03da6c3ad3d16ca224500c081d803b4a2eade91ddeb16a8fdfffc031129af8e31bdbf7b134bbbb08e808e9129591f1e7eaab652c1e55ab37287c1ddf4db7e0be1e985c79ba98605b016d455f41a8a3b10ab4edbf89901c4768b675205ca4bb1219be87d628b1b0", "0", "0", .None}, + {.Is_Square, "10763eec02bdeca853586ec1288104e6a40b2b1c92cf26ef6e3b5ea92873cda1bf3685b73c418cf71524386c34927503218d829c4a67acd65cd07c20551d19bd86d621ccf763ded072eff0453abd87b0ac4d8a54bfab09a06b2c1a81f9cfd33445e1e1390c3bc2a10a1fec7adbb10d4ba311f0504c75f158ca0c905b8ca9cb2e0dd826fb92ed889bf91a20fc680d8f8ca17d2e021559", "0", "0", .None}, + {.Is_Square, "c831eb08f746d74bc9c9fe339ad7d04f619910e00b84d088f5eb4a493226df117f95d6e2f9367f875eaeeef34d8470c12880cfb0a83e08bc158ab34885a4ababbc0df02b1ab03a4d0de7d148d5fca60c681ea24dda446832b69ff1497258a149d1d08a0db58d48d1abeb378db6b20bdfbb2350a8c20f86dd74693740c547362b2adf03775ffbb81a7a151196bd29675f7b45937ceefc", "0", "0", .None}, + {.Is_Square, "2e28c06ce693b341399ce652d3138bc954c8362d7a2521a719aab51ec9fd1ee7af3af6c2b6eb34084ad2064f0a604d9bc1b26b35a39840e31589d662a5d4093fa6ce6c546a4862f0edbad1481a48dbb85597317c94b297d12b2220796a21a857f47835d309220237ae3de5fae75740da48af65677ec4aba1fe9250afae33cbcce851a252024f768f371b35cd7e43d6a42a4c460ecc63", "0", "0", .None}, + {.Is_Square, "d99ba19034beafcc03f307ca00adc8a8be75964b24bc1777c0b6d6840e975c535da402134477d93e19ff4d702fc1a8d5246dc9682e7c011917bbfa727aae392705ba73f662cea7e404787e9a67e3e79219a12bee26cfe1012aca99610b742b7fdd1c2bb3640c1b3d69c591b4c223353d04b3d54a96dcbf42dfa17ae070df7edf68884daae210699f59fdc0846e92532ad968b9298712", "0", "0", .None}, + {.Is_Square, "f6741165d3164a21fac07aeb7c8d008348053b2d63a3bb5aa069a9555f5b4d603b16e6b7f390e9f54a25375b3f2f33924b88651a455db27363c9922e135e3641daa26393f4fc3b56e9303bbc7f49eb505151eed8de845f425b0e32a78fe89e6778652e39587c2f746e578eaa4a17290f68c53a649221857f4f9a6adc57c9007780550eba75d97d9887d00defb0b5a15338dab2d0f93a", "0", "0", .None}, + {.Is_Square, "c9300ad56e264b8cc24e0b38909086fd401ad1daa3dae97951f98d4af3686e1503a72461d756a2e7884d36d35816ce62fef0621881cad4c25e97ed967f6e8b3f27e7809d77c7f6d961f1d9dc9caca57bc6e1d82b02082d22a352bde99f0b03c46208131ad6becd8f32203769bdd8dddfe984260bf901caa27db4454b1a9999ed31d0de5a94379b72a71aa82e7956abaa9544eac7d591", "0", "0", .None}, + {.Is_Square, "c44c51259adaa23623a51eabbc6df6cb18d3a9f60be3d45c88d087d1a4d6b926157c7f2a8afe4168485f6847bb8eeb56b83354b5b93cef159783e6d8692a7cf986ed91cfd7ff3a1bfef6cf08afccb01ff7d476c2d2f39d8e07acbee44c7bd439555f926a69d09a58dacff2a3ecd31b12ef9644edce46cb308633ff68206000016353d40bff579203e3b82d20c8d5fdef2f08ffaf29d9", "0", "0", .None}, + {.Is_Square, "d1eacd12f00bfc4e832f3a820d0c3748020fc72de3581da4c9485e90729285e66fa025c42429cf4676c3e8d1a04ef3625664ac55fc5f38d748ab905b4a6c3ec1abf1803fbc38c91ab8e9199433777b688c59a4faede1f64ce0d89d75b195f29a921daeaf2d952630bc2302d24dbc2d3c99454db213b706738f82c522ead616af07ab157b343e7a8cfb5329af6920fb5c9afd15e91cc8", "0", "0", .None}, + {.Is_Square, "c6b250d22299d587dfde8c4c72170e7d15fd8b8bc59e989df03a402587f3c4f5d18010230e5b6682f3b589155f8b66b62c1a8de09e7b319897417bb6e200a307511f62871480550c088cfdd17f66222e605d3e6900e328537d4966ea769238776a8828a15efb62dd632493d48ab32809c9001a4f070fd8ea2216f2ec12b8b453dea717259e2944322518f9f31be9baf9891468da0b48", "0", "0", .None}, + {.Is_Square, "7882943eb26e53aec894fc63604b8c3ee0855642dbcb8546ad99cdb7512f06172e8bce7c31efedb6658abaa426b7fee89cc294a70f0c072cfec14bb4faffffb689b80bb7cfa6a71e182cb1b50ecd46449aa5bb97afc73cadb4138631c3897357b8d20a6fbe07d144a2962ba3ba89d8e6da0283c3400d6fe42ab80278c14b5494cd798241dda22238a7b200888be0536b3dd6c3698994", "0", "0", .None}, + {.Is_Square, "9ae39f912f82e8f95abf8973dce065e4490eba4933b8c85c9c902e465486538e96f06aec07619e3a883413e4e24703f0760657f8580258cf6fcea8c44b01d76977e319128edb583d4c9972aa9e8e7d426ea2359f9c327cd40b0ebde117bdfa941c65a9feb045730d21fd4846a17679b9e3ec8170f23259c72ce7e46dfbaea369e418b345d133790671b6da6bfa7dc8e9fe8494a13ab4", "0", "0", .None}, + {.Is_Square, "1e66d5a0bd776c12b116a731b18bd05f0f02fc8c28f07238f8a8bc00b348a717abdab4c2f36751eef36491ab51315fd0e458581d4249e9d99b8da9bbe8669dfa8512321ffb4ec5c70bcfddb64db4c7167da243369caa778a29470fda8dd7ad0f817399cc9f77829e068162485f95d360adeb10c2ed9b463b7a97367e2ff03714d4a61962c0a65259d853215fbfd96b84ab3d1ea3cb9d", "0", "0", .None}, + {.Is_Square, "eddca602c5b5c0e9f9b7b5c751d9b7ce411ed8dccabcb12e085c6dda7ac47cd03276711714f5827d1bd8d5f83e2c2f19af4bfd4bfffeb5a4814066b5e945ba27720362971e423bf2b680a6d394ea04215d4e6ce55e27db81450465910572d6e1712e9f6ced7d794f7b86c42591f49a8ad405fe6211e7e59e9ff34b87ce0db46f06e2abd3e0606fd169f2147b8df478771ac58a7b489c", "0", "0", .None}, + {.Is_Square, "35dcd09f053cc4eb3b559668d2775bb57edbc9cf8b9d21b07dc9adaaf058214401433e1c4f5bcaef1901aae78250ab9602559dd36caecbaff7521f686f881ed520e3fda917e586e0e086ac139b72280b452927afbbe2349f9fbc7c2ce649fc3b4cab6a780889d335dc9d17277eb77f26600b68d21288a1c8053f7d671230799fa16cacbe91ed49c684f4e8d96d20140ea41a5b5a74ac", "0", "0", .None}, + {.Is_Square, "ac2e3b7b04204a04575f7c8d47e6c50ab5744b63bc17c265ec2d3728e3fea24c1bc60fdb4092b3d4c22cc45b0049d88e02cdee86074ff13cd07a13734ad1d60cb8c75e86dcaa3ef40b10a88fb228b68823431fc7623946c9f6a8e44d0da1751684eb65795e9cba16187ec0b11d75c648d6d6a02c5728300e104712075b4178f735bc8ccadcbf9cbb5565e512b2ec216c41d3fac65a22", "0", "0", .None}, + {.Is_Square, "cc0f0a71b79ece1b3a3466296aac99be72ce32f4d3cd4632f6fb53a61dabd079381e840ac496fc016fd63e5086d01acfa1ddbe9178c734ac907f47d800c3188a51ed4dac436fb024f660fa4a470ce54e05eea61fd653684269547ba6b2ecdd7c15863c6c8aeedf45b9f2279751af73966c1df05fef217eaec8b227aea89fc18057a9632b799fdda4e709e8ab2aba199a72049d516268", "0", "0", .None}, + {.Is_Square, "210c86503a9ecb22b48c189f90e59e5be20d73a3696e54dbadb08ab07255d276f22ae6fedcc20f6dddbbe7dbbcbcb111ca1fb2d7eb7012f0769987a6dcc54f756c2e54d52fa11a57c1bf7632553470ce7b5466e77ddbda36859c65d5324c58070d74c97d663f9f5022a310d333c28da173805b97a823509f02e8165ccb55262ad100d0369f808a87cdbb10deada55a28c65dacfa9a80", "0", "0", .None}, + {.Is_Square, "ec70a1e223a2f798765a4b7a18ad7847ef1cffe8f610d56c6dfb5921b061e5f9139fa22ef8b95e010868827ee3ddeb0ae64ba0df18e293051fd3293da3a2e78a4b83988a4794076eb86b9a9ef7292beb45fcf3737f76c5637138f6a59496372aefeadd37d8da9f2e805c8bc88dc6ff0f7d17c2afe552f1ec1e5ca15c32258f12bc8b238e4084debcd89c7f09a63dd3a2d14b6206bf91", "0", "0", .None}, + {.Is_Square, "dcb7e12a2abf233428c4a75b0adc7a3ab7c8a96fe8c524788719262d04b5ce7eff64adc6387b2a55e74a9d923ade48168266d313194496896c2be61be02e15c6e24eded3b3583b4d236298c64b336d73a818d072047c61eb8ea223b2f988abf7e4a3e8ecfb3b95028ace63cdcc549296819756f0a168c33bd3c6a7762a0aeb190e7c409189a9c2a31a9cd3d0b83e5148be10cfb75b7c", "0", "0", .None}, + {.Is_Square, "472814c670ff9be2cc3415d8161feee7a20deca763c52404cebb155986500ed375f7411a473c6a11579ab1d57cdb26840a004078ddccb939f650b8705395250b74bd34fe2a0e3677a273758a1b0893b66f059d087d11fb151fc3a325d581e1b863bf063770a24c7aa569e0156d0e168fae344fbf266333cc02c37c5feb8152f5bbf5b0af5d9781662c772d043079d6e36312354d91b6", "0", "0", .None}, + {.Is_Square, "f7a58ee6c6771536da75a44f752223a2a99300a73e0755f2b6d01eb6a8718a9682b51cb3ed8e5dd768c203c596594da54b9d19a9098b2d1ccac6d24e99f5d1be775d877a03902856aac8c96ae91e3af5829176268da1da107ba6b479794ebb9a5045a20cfd1cec0eb955b6f51756f52e53cac1bf72c13099356b1a86ed2f3979697d5b08660069154415e362084452ab4fb6f6803068", "0", "0", .None}, + {.Is_Square, "787b67144006b54c282d90f158421faebc8ffa0b75d88b8feacbb8612ffbea8fa926bc193713b914774f30a88eeda6f623a2b9d540e25f782eef571f1d1d459206e3227082fdfe50903918b6fc923148db74989e85b4b7f7d69c3fdf7b6a37baf9a988697d666ea1e590248b1e285454b7a1d23ceda3fb949a473b4d1a7dcaeabbdf9a3ab6884de8b3b4f794ab9f3e774f9cb5e05128", "0", "0", .None}, + {.Is_Square, "1b9534d0f69542f736a67333628ca3fc4f347ddff9e7ebc168439b443ffa645e63194ff22c98fd5c235c0fdc3c060c759ed6abe965a7182446111490370db6f5faac1dc29753a81da0f16920ba72dfad49818bd176078c3b57af2579659f4b1f6a5ae221ff48ad911e5ac864abb4c2d64a4a65bf5e63e99ec37d0d9ffce5f5208bbbd51765003405fe7aa0e1576039af57c0f4e28440", "0", "0", .None}, + {.Is_Square, "8be5168215b53d1d3b8d255ffb96883800933ff244a8a192d700f711a74d22b061b89c121ae16a91f4b7cab3ae8c4a08452cfa184b0a2259cc52d846589da129dbc1c4c1da40743afa41ad952d1468e8430cc2a94301f750a37cce6de4ea40135f61388295b4bd7590d4ee6a0993d53d40f685484672698ab57e327aeb4509b9f8dfb91f43b4dda9612cd49174b6cf900d0d5e5f56c1", "0", "0", .None}, + {.Is_Square, "89d5d457bbdde5860ec03d962e9f8d154f1c9c689322bf319c72785529af3581c7aa0d4969ce92e4224499b1bba6d05cd629031a313331468617c394cfd17278f9a6a1e692c3878968c0b6179808e50a8da540d2bf53085d6fc8f63240bc4f5d9b776b13c5c3332ca10a92831f8f2e9f8d8de956ee2eac05a4f74e6aaf08c25f57ed290ddd4475dfda6b9131620eb62b3a681508d8c2", "0", "0", .None}, + {.Is_Square, "4c802c8d1efec16539fe96d00b8143e482b0ca9257c82be76eb346f6911ae79472fd9d84f6e3aa0a339624025e9bdca4d7ee6bdacda262727d93782762ba317aebdd48903675633b1d0859487c999b8721a74936d672395bac6709beb3e195ea77f1f31e79654e06a3f31e60e4552fe13e493f174446880d42a60a9e7f4b4ac5ea8777c89043f45f58fc479a9a42940da710896de892", "0", "0", .None}, + {.Is_Square, "71051d08296b4c74cb7003871a1c8e7de7811da06349bb844c2c50418794b841b7b66c5b46cef5f00d32a9ffee4685bc219269914666c9233b88336c6e48d2b2c4e6ef5bf1ac4afd460096c7c3e66ac4f51076d0e98c70d0f43c4e22bb34b5b4e53c5e90823b560a94d937fe2321cd09f88a8b59e800ada0334f1bb5b1b4fc13ed73bb6723bd0ce0fe9d078818561650561d2b27c291", "0", "0", .None}, + {.Is_Square, "f2b988e44502defcf4868a4a7040c8ccd3065906dd1487d9245dcd4612050a8f10532ab2bc8e1f2189a25e0f851236ce32f58825ce7de8b92029a610ad6aac31d4503c2d4ab9638e216548489bb7a31e4289a1c02d7fa52c61dc327e6bd8e87ff85a34e92401e6981f1a0fd3f9dd0e97cade3049a37c9c6bf6f4164789bbdece00745a8fa7404742ccbc4b87295934f8ac454c2b56df", "0", "0", .None}, + {.Is_Square, "c526a267b9e153e8d7a4df53b49394ffa7f7c282392aaa8ac103d03932ca2584d4936b234fcd82f74b6ee5471ca28d468682ceee6af8767ba8a9e0faf4a0b6a133bd1886cbb44e90d46a8e21d017c2a378e9f22391a5a77f2b2671c913bf71bed8cd18b76ad7cfb7c9444e0ed40011215c1b9caa4c430250ed5490bc1e09cea6e6dfd3353773d299275608ac5bb6846ba01b061b280", "0", "0", .None}, + {.Is_Square, "4fecff4ec58236f6e6a6e274248518da9dd232094f18d3091912bf21f77da27f5033a0d1793bbe0d8a8f922b1639f9a71d60b4a66230628b2341ebdb310fd5422d5272e77fd4c161f5131922afaf81e270c289dc57fcdccf9b26ab4e93d0f1196d129ad83ae64fcb07b4ad52dd0494251cf951bb6b13204057c36e81ee6e9ef542c5a0009ffffcc04b2bf832c0c1e58bde86cd438d2", "0", "0", .None}, + {.Div, "4d48ccb6821cdf7b0f795e89a7de120f1a56b7360144e48ed88ebbafce89f03a9de3d86ff7bf458eb91ef4264d5493a3e0068d4932ba6072136cdab7c05151dd339ceda345899cbb04adf90e5a68a6d8b3a4b37c5e5531dcef6c34e75531ed908a445bb6ec947e8b0a3c70cf0941cc2d235c58ef178b72560752fc68344c26be6fc790704c73c4fcee47874690ec9a94f19accf347b8", "-14cb31dfdb91ba33bd1d8d7ceb258b2ce9a336f848f74da4f81b31d02ff469827b16ff5927dc5e470feb5ab4b5ceadfdd8be2b1ae5f8cf4559128ba5e12697674c7887d77742f3e3368ea97d4796ad64304f6cdeac89a0b95332", "-3b77aa776135372bfd0c38d31644fea17a8947437bb5437db262ed830f31253d5a01825f919e3e7e002e9e362fe81edbace0afb788a1a78f63dd1fcb1", .None}, + {.Div, "-6ef982b1c2c2c7a3dd3c6e9ec9d41392bb5a04b7c04dbe3e39867be3d10c7c6506425eb39cb42920a571f539bc6af001a11d5233e203e74cd1c5c4613dc01c24b3e611963d49c30401ced3a2fd53153e7d22db0d65a6414f12df0c9efec82b0200033c7209aafc4f1f1887d5ba57f40711cc21857c95d1c257c3649f2f33595c660b603d72c2e83989a38f3db3c008f714561299a74d", "7e542a6f62cbcb63c1d1a1396fa4dfa9c84ae2cd1e4bb765136fae43157336af5dde486db8007def56fd2036de784537ec1069aea38f0e6f7b9b064b666e838050f23a0751478902f38f73d73963746f22b808ea16311cc04104", "-e0e2b0d4b8a0257a4d3ad076fc7ca233bdc491482f1939bd114862ffffa6f2e424a91c984e5ecb27421381e577828b090daaa6aeb93a7b5dd5d5b192", .None}, + {.Div, "f5b9d71b696e7a3b0cf522b6a3be8beb7111812c00a08ba77d2706b52eb72a2d6b894586a68d1e93e549fa688cf22836cde352106095fe543b2ff36daee93a2fef712759f731f2dadd0d86414fa7da699e11ff7209ff1d31516275cb161e44ae8357e2bffdb155e4b71fc21403d4e789498ec74311c61b17b508dc47de13d013c55bacb464291abcf5af480cf5240a2d0882cb574bb6", "-90d827e52657675e67251b54767d2c51f44b73fc524c1982663465225d725c885f81590b08f40b35ba2881c36441de9aa7b01443ad598a0d49d4724b300f2d90040a27e9e4655f0a59785e911848c79257063aa54cba8c31287d", "-1b24caf81985d5deee91ff8af531597feeba2fc07208d4ead824afb2c48ebb383f239bef949b33ca5c9ff1751719406c7159d3f7bab6e3a6f38d2b2d5", .None}, + {.Div, "-533a2721c4b12a0f24608682da1763bb889d44a1a6d4e0fc3577cc62307f06d0904ff70b6a7256341acdc8e7099f78ee8546f00d7759b30dd07b491e8b39b3fed1b305da6437d04d6c68dc1148cb49a781af2169dbd0979fbaa88201c7d85f2ac76f26a7861255f59c1a01425b94f2ccc51139f3cc20ecf1b2217458664b654d9308fe9f1bff69f39750f957186a6b21fd850a9fb434", "336314ae47ee6639409b4e182413639dc1f3d476a4cf462769e8735919b580a86eca8b8ad29a03adcda42d0b65d8032869a278ef02be9f11e5b50a1c9db389a8d2425b464f6a2b61621df01be20da97a842d837abab999300590", "-19e9f05b90a8a2863943a0cd6ac46beb3158602f1fbfa558fd6b603e5471d99651ad1c7b321efae63bfc09c9b27a6d786cdc707f437a8c26fdf436b30", .None}, + {.Div, "85d7233d42501afc8c51abfbdc360e8196360db1465f48426c54efd646181a70e234fc290a35b6945f916b5ddfa1b217fb4e2484ab48dbd6ca0c52bbd3476c7266a138d9ddf8c23b529d18ff1a2113f86b9087bb521e820733a9be8302af588b12f3752ec11dfa72ffcb185afe64016182fe8a5a203d5ea53600ea703044ffd59287971cc7d35a63fbefa46b58a3ee6b6214b1e5a5dd", "-325b11645b468e6e5a6cd6373d431a281ab18f1fbce94c7e3f10d76daea102f8e3a91ebf6ebd06ca660101aec671216284f9451ad1f1199ce0ebd8f66d77c28286bdefe47b357058961c4729ae172288209b9a14072234d00465", "-2a86bf8ff2f8fbfb9bccf1b48ae913ee142d72bf2eb856d7305690becbd04331de1e5110874bd04c087bae9a26468bed87d40568f66bcc8837558245f", .None}, + {.Div, "-c1268192502ea94404c26dede2f7aba4345a33435c1703fbf1549b569b4f91934414853f1c30ee5806c31a2caf592fe3771fddec6139d796fc1a1f49b83e02e911326b630a243516975f2c1295c7dc8b154fbbe751000b1d850047e51806f2315ea3b20c0c68515429f576bb71018c1245f19cecf59e864e98ad8dfddb34acc447ad0bb9bef09efe7ce851e31da3bb5825c9f982567", "-604b77adfc6cb0ff54baf0f894938303a6b871e3d79527b3653762888261eac16091cf38b12ae8efe897cd9d43c3b8fd7103415a767f25853c3992334fafe40d78cbb211ec14b23e030bf5b5df9802bae64123b5c6ae02950b82", "2017daf2ee206bd75650620b230aa0d56be8797ce23ed47819cb97113964ca61dd2b488a5fc53786fb2b57ed4683a87f2f763a1ffe9ffb4aacf377c2", .None}, + {.Div, "c18766b4fb019dbc1604178ee483366b12a682240b1b19ac8e95236ef866c48b788c838dabc28547ea15ab4bf8388506b4fce692597dcb83999fd882ce01949a3f925d639ca1b6df9548802634dfbed39371bc33e83b021362d580f618fbc09f1e78f9b356268b1541f0dcfd5828b6d63807342ffbe2fd67ce9d6eb2c9283c92f832e73d7c9afa4d9eb2add075d93c3672b5f3346c17", "852f605f437ee823e1763d3fb1938b3e5beb129c420086b22bd7adbc382be8e71d8b92ddba0441846c2a2932241a291f4bc9c94a9d8d023e16d57ca48b9bb9ce1b855b23f5a27c44b12152a06ead98cd78a6d82d35dc2e719ca2", "173fd3a16f64c202e3512df55fd25b88e0300377d2a83a30025303f0838b0892234cd7ce4551045f91db1f4c726161e28d5ef81ab152b6e5240d31a6d", .None}, + {.Div, "-ec44f122de998b05cdfc8424cf294bae022f83f19a0fad6382b8329940749aa70e8ed858032eaa0097e648105e277eb3a1202a85e3cad4539436b06d97695073a8ff819d3c61a79b339ec081d9005c5b262dd1c79f88494e65747c66108f9aadcda679b5627282e5974506aea41de1f11a0870f580d186a91b37d7b820f74cfdc662319a2d5d490272751c08361eca725f4d27670f9", "6c00479b57e1db7b3d6e7f7ee06370a5d8e5ad85fb7b30ac642e11430b4baa5b4ed6e325cc3342f565d2e6a25f12db6361c25a82c5e2e457cab98610b7d73d9d11dfc74a8069028f925bdc288848f89db667bd9469f8510f3f60", "-2300a43852dfdf55db51bb3c2e3c18fd5b14146217505bdd5b8fc216f83fac34d10667f9ebdc36f74e80c054c563d55f974a00401411db6410d6b19e", .None}, + {.Div, "-b7568d6a2c675b1d9733ab12ebe25a40254a8177ab4233fd5cd2b73896d19a91ab9e869055f0a300bda295157912f9764d8f1b7aaae8ce7ff3a34d7f5d800ef758f8afcf416dfc794ead63d40e1b4b5a307077484ce135ff1d9156cba779fe41971ecbdefcc6b15998ac47cbd2f7b569918f4fe1a7eca428862efd4adc17ff1bf7c8962ef5df727103f225f981979216e20356ffa820", "8b7b5fe5795935851c736ad3b53e7285b512efdb590a22011fc090b10d8731d4ff56971dd0b6a3816b0e80e9a7223344337f5d0db75dcf9d5d4a50966c360e236a12417139cfe5964b6cb8f3896f0294ad3a601e9599c219d468", "-1507df2d5e32f8b7629125508201f160d8fe745295373e21db655f27fbd4111200408f79a410ac0c3c4770c8c3982745fd1c1a3889152b3cdeaad02bc", .None}, + {.Div, "76c08c2fa414981123a83eb0486746ccbe3795ee83a5fbef2f8dadc4b7d6f1b78a06ec5c0026a6d31d1cf15400d01a106e2a5e88179727ab7078f01d4e3f23bf145e53594784545df35be9b3574b09aedb1e157b05db6c641b2fcf641649e52b230757400419826c0b8020566ef8b872071ce9cf73ce45d08189a86daa5b65830a706aeaa3e68c72f2bce14070aa2fac17b1b5cc3ab6", "-e1f830ed29d133cc3ccf6b8f8846da064900060e8222a7057718dbd3c46c2e94de462026b32f11e3389501150522a6c34d9d24755cb37efad17c318063139411e7c3a78f44038e0f8500d9ea9eb1ca286948b4a22c055996912e", "-8688aac160f8961191b89842352b4d751a006ab45cfab1bee31002b2e1d8f8b34df912a6b238dd69c7430b68e4d704cc733f3e7470a058205e193ce9", .None}, + {.Div, "a6ff6fb92b4c24a2cc88b8494b0f045b169cec653b93d03127554b6d338fd4af5f276ca6c344cb30d020591a5cde4bef8d9b5fc13987e0d908f5b66cc7441d3f80d519aa7d0e6233be06c4bb3c3c39537775108134be3d585bded1c88c2977281b70f419e2546cfd5ea78bb50c45edb76e14b3d06eac9ba8beb130121e4eb0cdf55b57165ea15b8f507e2bcf061b0e7e96ebc4264bb2", "-b6d57aea20562fe33d149e004dfdb0d06c1b5edd6092b495197ac9d0e2f9e293d82fd3f7c27ad7e954e961d94c8b923a4f35e8353153e8dae3ee74bb117500afaf9562b672ae5ca474ff2013d523c31bb8b181250b5729194393", "-e9d39e139e7c26624684b28954e698dbeb381189065ed7d3737bd90137f9f209be22e26b8de79789691ed270a1c42d69adf7076658ba3ec60aea078c", .None}, + {.Div, "-1698be2103f85fbf89a1e09d4564ad1b895ad1012a40f9c2839609f1eef486f673c4b2a28c43c03a049abdc534291ddf4cb424dcaebb76888440d3e6460aba17d5e5c1fdb1c100d291146f1028e63a9c7b94d294df1ccb83515c6223104834948d757eff3189c9190af53abc1a138b3acbabc6c6852db8b7b1afe54d3bcaf214f24deb8d3da8a57f4741952a75861ef919eab2915583", "-8e7f29d7b575ba298eca68dde03dd4530b782b8386b0e2d415b562f1a31a7705e039d21cff01b6e942bdea83d608efd35ecd2818f22a5872a3249767285b2b82982e70c3df1a4ed65d21ade31d5e6a650ceee80d6321c0986118", "28987a526629fbc9213daa1a4eb2afc0e1784736a07f4d5a8de0a18159fe886a9231cdbd87bf3ddd875fb65949f3676881ba691d9fd6ea8c40a124db", .None}, + {.Div, "f5ab538c07a146e55c4950f28372cf49f0a20bec0ccce6cba8c13a7fc2a8802e8ffbfa8939516e9d0391e7aa0fbb568c4e6b7d03210a96b173ffec9b015b694594676416cd80c619c0597cf7857a3e004e2707ac95e642cc4a1d9e759747113a4a315bc1ddb7012df3203385eeff0c8460707d0441193fef59678f8565bce924406626963d6fd593a995dd1864db3e0b1899193850ab", "-1960565825779e573216179534f4fc8b99608dd70ca99e7daf3cec21cd7f0a90ddaa3542d930d8b3902f9fcded652993d91ccb4ab6d6a41280d8d008eef5fc4ddd5b4de5ae5c3a68a7738b6b5ca65e9209a86d48d211b088c8c2", "-9ae58e4723101566602fefb319825e83962ea19ddd23f6d8a8d26ae48d3502a994a5e50e37a50965ba4184a4ddc98a908e65b4dd1ae2aa052820d90d8", .None}, + {.Div, "-b367cbcb2c0317980b940db13594d80f6e59e96b749265ff437ed03a16fe78738c8d7264aea597465ae0e23890c5fffb4e3a5bb0f93af05820bb24efce5df1ff87261051481c8ff43331fe35388e2c9ea91fe302fd2eadc54ffdab7ea40a08aeb88d18648c2ccbf6491545d5a8c65ac61942b08cae23d99f461629dd0d0903b825349e5ad99c014d0f7e55a53ab29331d70602df8ea5", "636d1d97e126b483ac45bea04af0eb9a5a106880d0fd5df680b1ef084379b53ca54e564eae50d7565d01f7ad235483e381d78705eeb6db60302e2cb9db5583b69f1651eee2c3abc103f9d802254240916f8ec055ed1df2e2d258", "-1cdeda89c339bcc80f5c464424d165997d9895a8ff13e3216517f37f58f81823f793fa2b289a4dc4f37af4f1f5aa1d7f8a46fccd0ad50e0fce10b173d", .None}, + {.Div, "-67c1fad32913822f84edd18ea3e80806cb86a16abbaaa43c25c9e696aafb5629c3087ae410c9286f72947b022b002460ea9ac721d27ecbd42917171c0130ce82510dd6a200653043bd6df3265ecacdb96688718d39e258c3e23194545e95611a55dbbcf95263772703c9b825f5e30972f036afde45bed9b852ea1215e8ea2733b0c9ea3e0734d100c8b780fff1117d10df553de9ff36", "dd45bd3d38992da050430eec329170fe2e3c79e0b6e0668a6ce8849768e88e70cbf91f72d4b574c8150a00a580df65cf4d4820d4b47417373a6f92983b4139fe035c55cc7b4a9ec84aa6ffac88589358d07c51481be933acc448", "-780abf5a49676f1d95bd3f93b918948be850df5c29d25963310b1394f09ae56e8f3794b433927feeb283937f14be8d179174791e0dbbc026fe9a085d", .None}, + {.Div, "1e72a3c2ac1c622a57069bc46728effbd6fbcb2bc477242375a040044cf5ec506af4ed67f1c77e51dbe6e9071533a3d8893078541f52b586938668a478c4df9652b1fadce33026d25b00ddc12c2a3af5d4ec2ca6765f73dd032e74dc2539a88b16f0ea295af091d4bcb960bdd90af79e2119260d8b5d20d3dde32949fd29ab4ef636ce83ba16772236dbf47f32aada26692cf07be99a", "-7cbb934ee92ff0400cadf2362fc926c5c3ea010ced738903402d2312d02e8a3a0a461e8db38d456bc2e2b9c13b3c34c1803bac8fd36feba1989c5aaeb1427c8efc687ee7b6a381c9bd52ab716a45f8b39ab073f930636f376ecd", "-3e7da119fecac10572044791eae9983a2bf06954bf4aef5d9f8e1e5e16899f76acc1d5d59a542e6131404f4db833ceb68c9c649935098d1e506372b9", .None}, + {.Div, "5bb9e83e28d37233e90580a6899c976c812ee3f911aef6418ce0d5688414968bc572707fef73a37cabc359a663bd1b96f7dfdbb2d7e5325172a704ff887daae59bc4e6d269f427014b2bdcefe13e24e462c6c49f6f81513213c5b53ed46f96527bc5057116925bab99ec83853061b3ff23dc05b213d030965c9a7c98074186abca0deb6d608920190ed6b0e0a1bdfb2c195709c1b2e2", "-a1c475dd302ea2a8d2debf72fa818e4d878d8779220d71e6514d8e66c6afef486226482084cffae6b38f256a8eff10cf1f18f22d21a3723676307e66abcfdb1df68978caff15bda4af832d1e405e45c737851c9ceae2174235b3", "-91288fac0ce19670f43d78f0baee2c13c873c1c97315b9c4710f902ee4cf13685c671f0d37a925abd33d18632816b05b6ae35c38a92ebe87d3f90659", .None}, + {.Div, "-6939593c976762e93a78b960debc6483b53cac13097a998d3d167e1af9176d213f5048335aeb50df5e0f4df9109780f18ec1fe0748dfee7e8386bca1b8eaa22848dfcf6d6cfe70d30c0bde07d0ae94c2005d9d35f0d058f5935e81fa016dca54225c7f95339e076383024ad1b29c35df21d2e824a980c63d04dd68d497c4f28669c87bd78ff899c5782daf639247ee6a2f0572b2f02", "-db9ffc5079249bcdcac3d0987f0fe9d97dc05461e906fb6b6f1713d940eb785507972d72cdfd9f2d8e569d16ef97c16255748ec8408b72654387d5837f45814c7ba16ab08924450afd8c6ca1d7cc77d441aa2d0e4a8aa4a9c15f", "7aa6ce9c11715c1de16001c46d0bf72d72189df594ecb8ab30eecad652af443f55aa1a39085bfcf55c5fe32c4d75f9136315736212784f51bc8c748", .None}, + {.Div, "e19513aae2677b9f56f649f3c42bdfc6ef927a43e42fbc2c290def6f5b01b6908c2676b5f1dcc69c5e5c9f32f7f854467fe207eea3550a0b023cc126539e3041f936863faf5721e9c48790b5a58f4c5d2b63edcf75df8133b8d6b09669461b30e3eaca2d817583bf472089f0418c7b4b4073299cb834af1cab3d8628968086c57ffdbb8322e9bd41bd2b0278dd0b41c676eb3c3d0c96", "-cd3e5adcf6f8fd981839056d41fe323680390a4016dec11f4165d2d6a865ee516a61061fccc8e5091f375e3c7c38867f4a55b23ce85cb93103b5a47e3a1aeef605228fb3f27ba91eed83478fdca52576bf4a7fd3b0e3c9466988", "-1195e561b7a54c4d3b240aa10d27aa4608d6603cfbc645cd89262cb54a0509c5e1763a622332691517d0ae10ccf84ac08fcce1c0afaff8deb8bac88b6", .None}, + {.Div, "-add630ac1cd48e62472e8258e0238fe2eb49e2106bdf8d0ff82dc006b272ea8ad865e8a7437d8b87148e19ad760d08c7ca92d6841bf87fcbb1e1bee14818a08622a4f227d234053a636cc0d362469835ee46f1da715d17ce948fea31d99eabd4106d072b46398b840b7e9f2dae9cabc061bfa307f911f71df5c2d55e04127ed787d97d9ff2498df928cc3103ccf6dedce86050c3b185", "c9101414f4681599c7f9e456ac5c688057a25313d3ec7417b3942296d3b1092901e801ae4c3508771cdb562444439016744ca420cf7964addd0c26ec89da2edd6d8d90ea1233c446d6104b02dfa790c1972edf5941a31535b98", "-dd55b385d53fc6484c10e16e21aa77bcfae909d654e676945c58d0f78c3d5143d49814737fd1d8f599bed195d88d8461948b31f676af34f4ad3ff9d13", .None}, + {.Div, "a02b6d7aae794bea33cd5dbe7d035da8bfc4aa7b5e1e406266d28427b3c4dd6b8246408cfa67a7c5a841f88b79b1c64a2eacb4e7d1d042f58f14a77f2962c71342c7c5f1f456404f55833d7cce2fc7e65b6b602194caa1f81d9035eea2acb29f0fada3eceb3754847effdb2ba75121575207caca4f50513fbd2f53761578b75e2225464af804f28c264ade5bf011af719a6a6a484759", "-b252e5efd963faae89e9158e1fccc3f9ac9409763acd5d6a01f6cc70771ac5044f7d8b9a1c6c2ed3fb3550959dcac5f5942a12d56e354438095c502afba102d4aa8bd4df5b9b7d68897eda43b9b34aae258ca6bddff661a33654", "-e5f022905a6b446e9c56a1e158cc559659f918a5c538810748f8513a89a514f347a178a31004fb1e6490995be35f2a067ef9447db0c2a878d611ce52", .None}, + {.Div, "5c51f0bf327d7e025a530419bb64c6a5b12b98ee35b77b236a4582ec78f639ee7a5ed4d540cba49d3cc738ab3d949a2fb253611f26dd363fcd4b18d0322f02da15145fb1e3085623f7d4633cfe62ed3d7b0e46ea78e3c271a655d9c1e7a7a6e928b27913bbea9e2e510feccc0314268f5bee5a5ed48e8803073a2751f176e26bed786e6bacd370696783add271fa22edd27b46d49962", "-77326b4cc071e49715e934111d0cf200ae84485fa3bedc5fadd6eee9ee5cee92b3de7189d8a60dc67dab20d5be53db46c31c0f46cd7275762b0b371510767b79acd02407e8e200f7fb2fc0d03e201093ec1435deb3608f4f0af1", "-c646c13b06c14ef662b7abce73e11abc54c6d8037681200c51a26e7762339714eef2091d04b9bc8eae0737a7ca894282784b3d24ec509a4a244b5c91", .None}, + {.Div, "-cb471c2074bcdd5edd15262b46c45915096e3a035050a6477234ce9ac5d98bd8a38b884e52676dd68e59578fb394f3686a3c7448d2077c720dba20aba346535d2739502597958fa7d843ff68f54e2d52a1c19cef315498cd4ef0d28e7cc27495d02d8e29724f29fa93293d55a3c43c488e45bbb16595c27a83eb1a612614db23ec91ea8140a70a9f814102c67e9dfb32ed52191f3f65", "-7eca34393814976b4b4b66a728aae0d1b5989835bef91aab34b61e8abeea11e51f76987209ca1c50f2d007b183fbdfd2a99fed543419e3178d32c35a92726df5c3ebbd9f063c9b0c767ab3f08906aea11ea8a44d5aabffce1821", "19a6f970df05a0df07c9549c6f5c5878ebc18a816e0db504c525c1df1febd915755186c89215d0667d6a37f852c3efe27ca8bead8c167a5678aeb909a", .None}, + {.Div, "7b40a8b3b293dccd311188abb7d3097a00b394fdb7e515baf893e199a38e4d53a30dfc0fa746f6fc5a499f076c47dbda6ae075018945b001be5e36e79bf56d960c01c171f7b689ca4f68031ba385cb5c181b470ebd569ffdde13871b247384731d0fdfc15e7dcb183cea0a0ec0edafa258fe0374e6c0bae9f1587984d492d40b73c774cca55c0e3f63172c6f63eb885f0f4117af6199", "1bd6f0b6c23878b23940c4ea17aa05cf91e8a57096993ab5b9532c0837e0c44b818ab49b4b3d6461553cbe658c642e8011c6a33dbf51869e6f7e2f801288acada5643f44cf3442abfafee7cf19a204c6fc6c2b0ba2222b45c9", "46d5f73c9fae4970a4b17107311f0034652d35d09a7a978a2758eb46f296e599fcd85ddc96dd3a94481497b7228d4d0dbb39a59cce68c9f2b96f158c561", .None}, + {.Div, "-cf4c50a5c346fb366f256b67713fd7309d11cf4b5288f38815839c611ba85c831ae32c04c8965acb45f04052d0c40955c001cda27112ce00d03de774364f1b2a6d4cbe9cfb30b0cd55ed148bd2f90ad03039a301a7fedeccee83a22e29e4c723743d6bfacd1218e69fbb9732d2be6d9a844bbefa6487bc8f971913c0998ddf32ffed90063045a598b2d36f10339cd86c1ea87da42a5a", "94daaad6f7c64091d2b0e9cf8e75d31fc8925dc3b2b95fa337847df16b62f6b0ba38c617eb64ec392c1f08958fa93c6d0db2d5c983fbb31ef28a5cce581b13c85a6ba1b7b5ffad11b7b0d7da1e8d8c6810833f29716adcc60bc7", "-164831a1a20f0bc859cf81ef8ad1e6b59865dc10fb98e638b86709fb03d78f5fcd118f268d61842ea3da78f25a04cc1f34dca62df4459f2ffa5f0fe10", .None}, + {.Div, "80099afd5281f655b527b589c9ac971c9ab3536dd303b1e0bb6fbac62762f059aee4c05fde981eaca5e008cbc465421fa55c1eccef577a2a4e6021b77caba4056708aebe6c64444f3375122c88542916eeda23db1b6742e69815c8285b0b4d746a10f38f41cd034cb175e7adfac77161990d9dce4e8f42350504a09b3067923b8924dc5847861ba8d07c345f8d3a375c6290cf1f42b4", "ce0d88a579d53bab1fb7d22e60d46b1f0fb098ca84ead2ba87b15a6466b6ba1f07973e96abc76d5618361ea6a829b1fb630fd181bf41c0fe492d27abf79439b8315de2ae2776cc143a1e948aae6014eb78dd25f5990b9f52d0ee", "9f12e2533a9e694fa4d0531c09a594a1b854242733df0a1c620035328af391ef2d56048d247fca31127af20f07517e5c5d03f3c5678eb3c43120eb71", .None}, + {.Div, "66edc75888c27877e4ce8033372f15ce3132192c58883f694564429bd2ec48013c5330296dbc7081a0574d8a8dda1731ba91c2a0d43e5225731621d674134a846b9e299cc7187473f4783091dca849546489efa9de84612af0b313dbe46d702f44eeabaff390aeb9da6717fa5ccd6573be7c7db31a4e29d18586a22c47859d5de59344c5587a47f60bac61a31a8194cd274c0af55e53", "f49d3a03d03f66820e1eac19667cdf38ae68ae2a7083f03538a7727c9c03c774bda6323b3200280d937ef1e19842f297b65f47dfb178c54899c3dd816d6d9c78363fa65066d5be71863898c305b60f0acc37df15f0ac90a038ad", "6bb8420704f0fc2b89037e11c57a5ebd04a1631cb4378272dce5ba46dea35a099e759ebbe94edf2ec27ed6408c9fc97efa2eb2bcb06895d6ae0a1d32", .None}, + {.Div, "-62b810910feea390516aaefb3e1bef4ae0f5b849027bab92cbfe3d9740eaa4047411d3fd4266a6d5c47220d7962479eb234780e9fe3f30e81415ddc7ad930e237578a30faa9f365386c4b41902fd17d0a3a6eb69db99ee7ff51547b3b62a8196ceb9f0d885b425ce3f74e99297c5461e26d9167832ba90097e9b7d07ecea035c1917d2dd5bf890ce623a76614a17bf2c8e713c4762e7", "-e20bb46ae9528d23d2fc1aa8f7d3fb22e8629adf8faa8d8ef2be66b7e02ff2004a155ca5e42fbeb859dd4c5b88ca4f39149aee753eaa0093809095af8ef88333b0d1e4d876fdb69b8a33a6dd5ab0a1c8f5f978ffa0e6fc560d86", "6fccf92a86f4da045c8ad31044c890e9c811dc8bbe2d4b3f99893f49d931a7ebdc65d0cae9b854ef5f84082c03bdc2a462459add24a232e51626bdea", .None}, + {.Div, "de1b022ac6b4148405a73ef9c2b8d43866cccc05e71a36367488ff394d10d703b1fcad263e29d23f2184d664215e1cb8204f92d4c0c514175d35c19ad4a6f69ad6bcdf55f6eb41a44750eca2bf10f11f18381f1e531738b157cc86f065850c2a7ea3d4d29c285d84937ff61efe8c058bcdb6120c7f067ce8106bb1e5f3df6f83730997f665e32e9b92cd13a88c1011df7767daecb085", "-d6002112010dd02a76d60d8d3d9a06f72a91dc07a33d61dede0ebbd109f7fc0b75f633ca34df99e808261c2845ade33ac43d3089e0acd8c0d98c8b41f02ac40a5b706450c00d6eb802cde3db9459f49ef8bc5ca8308735190e4b", "-109b217bd2b191d469fb22ff867ac1908e8d76691e1658a3da2d895d3e66ea86658d440632feda4348e2277b17cbedbc2062c753584907e1de7af7779", .None}, + {.Div, "f00ebe6063b862c919f07486899510eece1c38f4a1356eb8084b45adc4850f3d4c2a81cabd71adbbad2dfaa6b71da926c342d24238d6b72ab78cb82afd9273beb6166323090455697ae6fbf40a680c21fb792654e81f044d2acfc33557a5e53a35537cf910cd072996438f26d916bf357cc69eee1f114a5bc0293496d37111a11239f13f2a439a70cb470a4cc1d7466d5f0ae76c19db", "-cbf0c89eba3b19549f79757118ebe8fd3ba8c9e7ac23011e1239292f1ca839d18160a96d6868918c0793fdca540e09f617f74039d3e4e150552b9d2c13cbe44eb3f3070d5ada87c2efad3b51b9ba3aa63866ec6e663c460942a6", "-12d5627ab92e80169f7601a8310ef0c7a4e60fa7d5131663a4dba07f9f614cd4649d92f67bbfc8e75fa3c097025a4c3b44f8ab6ed7abb13d2a70a4405", .None}, + {.Div, "-77ee60885ed71d86680ff69248701dbcde5935c0e30b072b9294d42a5b53c0a09c78c300d57b664c35ae26124f1bcd36f196d9632cc4d151233d695f08b47831116035d9df8188b00b2d2bd8f01985fe85a24d04eda3056a38b16e610419a7bf8823c1415edfb9fd743f8eb2feeafd50f493407eb3e3c729e98c93aad799d9bddb10281bd51351726f883840394d980364b8e53569e", "-aea88f60acb860747629f18ae2135c17e1de65b53c5609dd6d98e83d78c90bdf25bb293618143d852789551ba5faa0459b4135fa636c917d0115b1bf64a8d00d95af0ba94850e4a5bcdb08ffeda3dbbf23e899e81f6eb0a4fbf4", "afc9061e6d908f081b68e38382581e027a4c62765df994d1d88d592e1e0e4217dd72a35a3de0875fbaddfea5a5bae0f6dc4aa3351f7caef7d66a446", .None}, + {.Div, "-926cb26ee53c4c6db3cd55aa4d3ce80f07b5ffa11680009238706c7348a1fec4cf1f779fdeddb7f5302ef2c9c61e3dd452c32a1fff8dd460bd351b1fb5601f8ce3d5bf07688fa879a99d65913db3cab84f6326b12c8ab4b5cc3333bf8937d7f36e380c65f2286f35ff6a4d6430f6360c9bbd6e24e10345b17285c1efac64b88cc3d43314df5b59d58cb520ebab37adf92f4f8a99b463", "-67a1a1a4df2c555beeb01b575420bb8e18941022b6bfc8053864ef3bdafecdcae7861546e3c62899b0e980071d6e0ef2bb8c17604a34ded49e5e01f5798f0b227b1c56acb7eec971a5a715b6f306b58f37f677677b3e510ebf2e", "169b63cb84844c3fc5bdf8e30fcf9050f11e3396e82b44f899f4089319f0db4b0cdeed4f8b6460ff2d1239cda29cbf0e5c5d208900b61ec7e126d6402", .None}, + {.Div, "-2f6f6cdf85e42ddc5dd088f470bbf83a6b457c0fe6783f491c85d962f7566b8888a257c2b426535a5480bb1cf0704895833d4104034e26820e2d5d2966edb3a7e9b133c6e4c5a9c23ef474b78d3dfcd18f5c090636fe8556db4bb659cb213ad26a8e47aedbcd8ebc6189bf301e5cd79288a96be070b16bc46f6502bda78f628db6805873b6d0eedfec2ea6f1e4c1a01d1fed46ee9027", "2ad43403cc3e9817fcacd04b302d4def9e9730bc882bdb91a253acc5f8cbeab02ce02cc752e29ba6b9564e414afe3ca749926bc056d7827079f64947d4fa21a25b3719b04a490c6b917f5a032f525b346678ea6f554a47f3c7ad", "-11b88875269b7f831a75a93ab7dca9734345686e474b6b49b2cf8f467da728e613798d18a8a8ad813cfa8aab91cf0f2664daa36c7e35e910c24de483d", .None}, + {.Div, "-9be180024c002e8c636c80abb4a9d96207166f9b6be32b9911e16d26643985f29fb45f7cc286fde2949c6da90178d6d199d6867d56f73014ce84398b7c1506c1ba08601fa1a158b2955a1027305d4dfb30480602af68e6dd4d187f34797fe1957d4373787e74b1885f180dc05954bdb895bcafb73bc1b9e8024836272bf9668872c279d39e5e227c6cdc7c0eb8078b38238301633ff2", "-305a8cf3fc4d9b6a0109d24c1b063e7f1c587f1cade35a1eae71d09fb4253438919ff9093bef0664dacd619543a651fab6c476b60bc34509aa26f6ca3aa54824a4b3d7dd57acea8928df189546fbfde86db70f42d59eb93f3bdd", "33948760df214a8bb6c66fe30baf011c1d43ddb75144895098a146b5c53005adc7b2df38ef9aee8835fcd01a944578df6ca9802f98d7999a777736fb2", .None}, + {.Div, "1e5d585c229c387278471669df6eb5e2536d4d48fec10b6ffc893be1ce0864124dc729c2d628d54d6eba15ffeee6f17375a02cca2d585ee2db70f4907674befa54ffd31013c004136b4e7358bb749e856365c78191bc07b614845fcb99c25d1622d5808bbf29b6b80024136f4004c648cc40dfb973c8896b08d8f0829e8583028e2499d8c46600bfdc2497da728189f88ccac2a69d9d", "-e1dd3ceb457b0e469570ddd477c18b440b02d9058c2da05d0fcaa169bbd4d0db276c992f093ba3b30526775bc0fc8a0a30736f88ba82c81e7cfde8242cd8f20a680958cdda63ca16d2e86acd8ea40c95e876d210ff71419185d7", "-226a7fb1d83b9ec2f39dada1e7c8e0bdc3134f9d6339ed7c8a28b1e66ba06638853712f27286bd797c52cb8b02aee166fdbab2d4ebd04e87790f298e", .None}, + {.Div, "-1991dd006370f6c988249de600fa48632052e5936e6692e761ed53e04c4408ae7d1b2236fda9998ff835044227bc5f29849e299347c3301730e89cddb2587e791d299d81757d429d3a83687e153d0dcaf881e4854cdea23805a64f0d864f34da47625eb8bf7f6a908f32668a41a5a8f6650926c09538de5c786d4c082fc8be67fc019a617800cb1f121ab65c735c826df2adcb94224", "-abce4d2f87106d883904c58565f3003351ffb9e1917df2aaf79bc1069530e563d450dc3a450876f33b0cd022cfa7647997fa590ebd70d60974b441145e7029918a691148d90810211f17bdc0b511c56e02a724dafa1e4e72d7e8", "2619b06b3acba11c88cddab7a3003a1f72aa3507a9fe80f89d9be9a0fcc06f0ff3a6171e6fb3b153798011e16816f72ae6a87e9ba552ebea8760429", .None}, + {.Div, "-fa0e4c39e732940d5d3749904df475400aec30a4ccec5673d9f453f3fbcddcb00a636fda918bf362e99aecefeedd22ad8d4bcc05ac056b4c0889ced31e6155c38710607954bd899372d224d6ae4a354e2df434683adae59ee53abbe3c9d7850c7f3d0197bb57b57d3bb6da906c4970203084792f04f03fe4f24a3bfddda9cdf2ecd12235b2105a687e8b59248b7337d50e3533c21d5b", "-f11a48b945205d02b07f10f90732486fd769b026985067dd3dc5d3199857759eb8e2dd5028b753c8998fad45d4b087d7fcc61ce2a8fb7ecd99e02cb5a1ba27e08a09c848e3915c049e0e04955244ff8ca129988418461aa9fbbf", "10981a222debb75b2a5dcdfc4a07718241aa64a1e52bd249c96d8458c07f1ce9cdae1e9bf7c2a2541c1813ada59e8adab49ca787ec082f676bb239807", .None}, + {.Div, "-773c719b469db24efff95011cf4cd0b2db12aae9306aa07bf47c2897a19085ce82e2d394d7723baeba986bb9fcabbf9b3e5d9199ff13b60a26c50dc2f5a1b705ee8376c5bdca7cc425c0098bda2f21f0252b89bf32aee14c5f655febf9e5353ffd967c5db8c3abd6760613626cad2fbcb342ce1854662b48fddfe071a9c837f58f8e5e0abc7a85e81815eb0f9900fc6e81fa5975cfc2", "-29138ff3a4ab2e6dab3558ec6ebf25ecd42594f1750eef53c3b548d545475ebdf3cdfb50efa280a9e0250e73fe4681974af45ac283c64266d69f47211b57e2cd16f866d933cc9c7f2ed736915e8470a88134b2587d50007cbe3f", "2e71d1664a8c28010822fa7e74cce963b276a442ba368d18b7f725abe380e26516f20e868879f0a925c062fe8b573cd6f1267df69f0040d49efeb40c2", .None}, + {.Div, "-c75ed43a73ad36e440ebc8ed58ed8ee926a0b1ab07b7e4fe345e12b9f3b152ca32fdc272b3fe506e9a0bc199bde6fef9d1a2cbc129fb89963c5c1b1f4982e83271dc18d8a3d0aa53f26bdb2e9365bd13c1f31e51c45face871103a90bb433690eb69bc6316f944c6f2d7acbd0ddccf0bf65bdfbbc8698bedbea8d04e88c6d9238975d31604c9ffd82485a0c8f01ef9b032fac15cb3c9", "-39c1fb68f46b80628220a976a89a48f74cf8d7e5effafb4cb83d359b3d61bc24626e129753007fe795645f783d616461b58b668cda8fd450693670da3c05be8047c1b70bc8e69b5af8c4aa36378431ee64d1014d3b75df507337", "373abb7e1558cbd63b97651bb37c652d66d0ac9389eee34a2523864c8052a6554e2f18d8618ef40c462ec859452a11360c1595016fc3796f2f7c248ce", .None}, + {.Div, "7fc714867e3d1ced42c76062c5a9b59e7e8de04db275df70099b22215c342c80326b75603f39561a82d095750066cd73737eea77a49dd56164a4a09672a383bb6b812199f99d1d308a386a0bfda4ac81ff9a3520ae3ecae5bf1eb5bfa4374abba9014de5e29d5ce39adee9cc7ee78056fcea7acb3f5879c20cd9691ed94bd2bb1db915c3a6a9a7a35f30f3833000a70f16c8d7bd07e7", "a28e0d420207368bfdeef355ff2e28fdde9fc8240b826c388e8bffde0016a76edd23ed66a03d29bfdc16a8072b8eafceab7d2b39defc219f909246f4494929f309fa5f4309a81ea45d25c30b8e1bd3b4ad2453c400346682ca1b", "c93b21aa8e5b24ff6ed104c8698d553b499d896aaf6e9282fdd7922de74246f88eb9b828d821357c1d736ef3670f96484fdc75c39dbba63fc51293d2", .None}, + {.Div, "-5ecc938f7ea6d026fabaa3c87c2bd1c3fe26c225c4bbb75abba1cb5877d6be88e93699c51ac9ff52411ed1cbe3cfa761e059a0521d17bd6c0b18e1c5b6df950e6d6497fe142dfd95de8cf83ad0fa82fb74e7a8f98d413150b52ce4ddcdbed0e9ce23d78b6c052c3329985804895a2bb967330da1b0bd5c8bd186d1eebecb5b0980a43652428fd409c10ecfb5f6541d7269338841402e", "-7306a8e53b54e9de96363a260a4488943bdbaa9cf2d928b7b6d5e79ccc1a43b49fd06709355593773983ebf15ed911dcdfff03729b419b3440a330e207eefaeff78c0130923810de6c568ef3657cffd7ba650ac3f7998e22e896", "d2fbbe40597d53fd8492fe7df4aa040987ebfe8997e7fd2b200b7610ac772ec2e215f99510e332cd1b4a7124acddeb1ebd2ee886d2f597ade9e86f80", .None}, + {.Div, "15626ccbb800b2c9d709278b43b832fd8821c87ff9f31a5c368dc26c6f7faaad8eb964c249e0466b077b0524ea33ac90149c57e6aa9ea595011dd1a2d5b959e5ed873f13c404e98a9bc9ccd1f63fc5bd188993f30f4e5014278f682b837d69278869a59a78de9159000f6c8a8e98277d4f1a9b4f2db748d449e65a127e0426be8a9970208576bce9d409bc70c8efe22c37a6be76ad96", "-e3056681cf3c8b675d95efd44c829ab283bd172b48c345a182413ced0be3f02f107e7df52b9bfb3f104a3b3515b559283ffc41ea6f1dfc6fd8b4eaf729abc92608d3d24545ba5e07d9b7a6b40741d547f2694ec3cc9897ac54e0", "-181d3a2845b0a977cb3b9ff3378402b45bbff26d6beaa41c46e15576f8ef338f5a2403e966a68be0defe361e2c9e7294acc22b9e81e290f26bbc7179", .None}, + {.Div, "d335ace1653786628996ed1d764cfbe89be13480ec8dc7c1906ccce018a000aac00ed5ef1b54a1f99ccaf6759bc8aca1d571ebed2a9bbfe9fcdfbe69a9de325e4417542e2b9b0f36fe5551358508564bb7a0445c96e57e3f753f106db01b068600d68c51d63500a219e9f8a188cf4a804c078979549390d59f6de4f19712ba1c2bb92917b77f1d4949578d6df66e0705cded22e993be", "-9baadc9251b867c121c77fdc64c6b3947f0b8ce851c3b48197b2e074e624c8bb20373a72beb11da0266fb18022761c8f8e4060f52c177b6072742db62dde2115303280fb27a2cfb4899375cebcaf3ea4261fd2f35dea471b08a8", "-15b5749bc1ae283b30dba04811a1821539dc0e55bfec00412e6f6385dffbabc48a5495c3c9732c0399c29abf1a6a698db9f99c0a7a53bb31683c64f49", .None}, + {.Div, "7e814706d631dbd24eda2f8901b41dafe72db52f4b3f10ec75412f2666fa279facf8cc14138b857b904b68021bd52fe8810f8eac8ba3b2a903a84f8145fdc8b52352aaf9aaf45a05da1916314e0a070c2103f27ed0d035992778b1adfed3858784060cf3a023959e78aa5042710cb25529c147193d9206ab7d1d8218449b2af35b2a95d779a59621c6ff70f4fdeebc7c876d4eca8543", "-65b50bfb340b110ddbab68af19bbaf65190d9e2a75b430303fae3164378310ff3c5dbc3af6a7a8515a767401abfd84f30ca5bd53dc9c62919460f1d6785127aeb4adc6a6bca777e8fd2832e59e710412523310d74660fc7c6295", "-13e6aae202a2edf78a456004b2b94ada08184bf00b95cb0a80c44df4ae3b84dd97577e74bbb91b548e507cf8447d54f7323963415192ce6884aa47801", .None}, + {.Div, "8042944270859318db832f84ad928d020e7e5c217a9a2dc22f102116a08ba9662f1114558a597d7bc01034864f5bcf999f264a499722428ed2b5260d6c90dfb0140f9c9255a0520a1d217714887fa53068e2d0c63aeb532b030f542096453c87e88169c7bde017d917ba6582fd8b29248ba07686fbcbf7b06e36f8eb08bc0c722cd2c3d25235df41996d77191261732eb0c19952c806", "345e8790de151714ba72bf97cbd382806a04932afcd822c851f3f624a29749fe047224939ea381a5b6ef3eb288898e5973e07b87639024cdf584fd4c4f4fa9b201511ec53f909595fa54778c945b2357b65288407221dca4fcf0", "272fb6222a6111b13da72fac49cc620c5c165e7a38b54c60e3e2bf782e1702b10e241ea36e0ae233ef28510614deff728b86f9c52a0e5e37b25b8d582", .None}, + {.Div, "-df952e28170526e602e392931de2c8fa85f83c02d2e42a31520507dbcfb50c4e08e711b586d838ee05c6c6a5fa40c3335942df73baf918a1cd3e7b0447b489ba6b518ddd31b53a74f65551bc5c8750f255b784608e547dd638e8cc61f4ed7c18a963dc6b000ae17352324f40c7ee0293220d172b27932cfc56e8ab41339c32f8348d5f6b5793eac508b9d47b28f31d9cee88b40ab4bd", "55937508bf9fcda6172d12b420c686d322dbff0c2705d5fedd907c498e43796241bbafea5d1ad94f31498184c95f9c477cde919e9df843b957baedc02da098ac2ac7c32b2fe1eb87474a9e15829d9e14131b99a362c7186736c9", "-29cd89c9d8639695cfd66db80dc95d02b33b33a7faeafa39a29f70911d0743b64f557d9f3bef2cae904b2c20d0d343251336290c8e51c409576b94216", .None}, + {.Div, "-d4a91a1583bf44621d84540217b47c52b3c263fa7de41e84b725281e6e42b8bcf95e6f3c8868b0c01e50b1f0c41a7ab10c2b5fa5f725dff110c5a28e13f5d5802211869c6c670e50f11184f64c2fc7d0f46e75122ee2501c639021e375cd59898337650a3a2d3e30916de5be8d223545bcc2e99dc70335dc13d28e9c152f0b0bbb36d661f589394d400028c0497401f125c8b544c395", "25e4807437eef2fb447459bf6439c20c4236f3da4d938bcfda40aad9a3be8b58de21aaeb9016086bd67637c2a19f81abeb3c30dc3dedcd99756cc71a26c27e6f387e6dd5d10a77171d67757c426b438e0c648e85abe90e31ebd1", "-59cb8c5f628cb9934bedd8c24ed73e53410c97effb541c98b95e550d44fce211986c176a59e8cebaee12c69f7bcb66b710183343102b50328dce96e49", .None}, + {.Div, "-814ba60a998045cd1f98dd402530b8a2dca2e000042ad05231ea6a04d697b2ee5e1a523eb39f653c708a69eb2d7ba18903aada44114f46e89594626498f0fd2ef564d90baf12d6f6c271ff31f312de71103638178e2fb9c3aca2fe94496cd8016f7e6a3e2339e285a90951849ec8aec96ec8d20b4357df6058b657219d9b7baf230f18e4c72847a816dadc1c0f561e6ed9cf5206c238", "40229ab4b2e243ebdb50de91a3b5b6740116f977e3e68cfde9cafbde329b37f7da65160746857d447f2473fddb1c850650f4d50bf310f2ef097b8d0c9e9d0a7913763931dc9bf3f4ee70f37a1ada9d125c5356760447214e494d", "-204178c1e28171119e6e9dedfc122ddec0e4928a21c5219333204be7943006903092cbae1ccbf4e4aa1621ecef1db7be51b33e05ef0704c868ea16534", .None}, + {.Div, "7b51de201e5ef93fa220c1de45385628af2d071f4d72743610c37ceb6796f00d42e1ce70d42888a6b90b8948a955b193dc4c0d8f70dcde4bd54255b1a1652f0ab3a078ee77227c5ef7c342cfa79793350c0e5d975f8a55180a0dd8bfcc6478c67541fa1f3ca0be20d4f7afc80c453c4f6d32bc3febf37ee1a5a6d3cb0c9e2663b16fbf30fbfaf464b0f8b5f6e729308001a834e10aef", "-60ad9fd67d7e3f60037ea480e93028e7202498df40a135bfb9ba9a5686c7f950dd72612d9a618522da233b138b4f2fe1d66023564b716b1d3537663b5c7ce092f22f62027811aea2184bc7c62a607dca853aeeba7ef133c034b", "-1468bba2d20f7639991e11977da90db2392f7c93ded5da63ae0c0b47bf6344453c30a6366cc85ac42530338b39242c8f93a93d009fa6859cb4a1f46e0c", .None}, + {.Div, "404f937accd5654eb0800068f431eb811e7cb852bf0b23f0b51bf1862a0ad3ee6dfdba39c699eaea355579ebbb12a7836157d146bc98cf646068867bc1728e3ed9e668202107404bc3e759eefbb6d0d15774ff25bb976819260ae11b6ac9b7ae09712ab71f872d26cc156ff6cba2073b1c1945ab90672e77406a7d7ffdaf7109bdcb9a186dbcf9dd010e7dc659edd08981a6b770b91a", "-46d3d1daa2f1d3b446a9da9e76ce1ef17db8cbfaf2a5d69934e8ea3900087a8a576cd0a15e5021d3b1065701771044d4bad47ec57389bb4805da104a74418ed9820a27b6d7d5183356ef9dc5015cf86dc11702a71e590650f285", "-e8724493fe9058cfa9f1bde46393cbcd509e335a37bdfde629a0bbbaffb025733ac3641087e95b663578f3e95a17b13f1e2e0e9f8b9e60eee7d25f6b", .None}, + {.Div, "24d3609498f0f87401f9c8ec62c88e4624f44ca80b7f1a87edd46956a041e9eb994e830d5a83db1b26b31a8ad69e633bb8d6575dca68bc3df3ccefca9e2b498f76ffdf82a1e1788a66ef8204abf23aea01cc7bccff331532ba2d3687b19d10c7bbec75ff7105f4cb78cd2fd0f3552219c95915e375ee32de866bf8172cf09077b417f3e6fd74c1c7b7c08dfa3f2ed488bed89ba3062c", "3c4984bcd0bcdce23662f9d8b687bfd0152de5b1d742a56cceac22026e661d55f9dc21e074635d723d700fdd84b63a54bd2ff8783a45273b3fb7380e1089f3272e36a3f36c8b85c1b5adc9ab104c96433c2ac559b999694282db", "9c5fde8e5c821527a3e1edc73042ae4d2248aca9aa14a526f91f9d510954ca8192aa3673bdb94e065d4b781f8d20b5015fad39f63b40f13460d3a7b1", .None}, + {.Div, "ce9073b132eb4070927634a5a816ac65f8d9ba14ddf9b8eb7fb7d2da1e71a7f717379c1f41313e00868af2b32def5c5a06351b31bd4536c360942e5dbb9225b5ff5618061c94ff85571c54493370c03485851aff368d34f0e791bf472aa9a6a3025f9c96c458e8e974455efb1c03afae75732ce1a4ada54a6a860ddea0d8e1b498667d4fe106320b75f78cc46417660289640c34a74e", "-2d757cea705ea4a16221bb2bc1afcaccc170809fc043e6e84cabbf72ee0f4d73b6b835ed1886f36dc0846c4f795755785566b565a58689f2a5c56a1936adaf95658cfe553849b5fb6af823ebef52eceb8a1b75952b2800d91b4e", "-48b41ee9ed770d624b067dcd3684e65e63987b21f5735767573ae4ea1c79400961f99b1bb042a1a74d21598104d3ae881a2f45837f503e1c5b2ad4930", .None}, + {.Div, "9e77a512a6216c82b487af8b5693bcf70896733748e424b6086dca5d84123b19a6a01ee29b59f18a05b8bb88c8e6efa69d385601816d1c835afeb1894d3de9f77d1e10bc444cb10c58349d8c0311fb3f2d5a4bc3a6f29385f2ebd88eb9add51d7f5e106428ffcab03f74281afbe3887466b2a03e3fe08e27def524161b2905daa77e8c0b3a014c4b016501e8c651ec5bc0ba9446e00", "-59de12def8dd3cf350c44be0a437a479d6205fbcd049522ea2b005f00c20c1cf4f368174da0fc199cc1bd6a4f979fc02192c53f956c8dffa1a0479f38f57e259789fb92f65d0f5fa30fd4e1493fa23745b4ce88c740cc3060de0", "-1c36a93c5fc873170029d023a036ff4476522395084c7479af256a7c674c38c10129c9b05b53c4931aa747e239f67c26a677fc91b74b8ed45a0b849a", .None}, + {.Div, "-8805dfac585fd13ad29c1bbcc68851c32a7cf6bc42ef42d4c04c89d2f245e9a5c9c9d8060a8ca0be6743985c13b5807b6b6fe83059d303479353e1caaef63204dc93c8514994f935c6d36e5f026b4e6934a9efe575c452a09ab2a20e47292300659441ad0b6b2cd448ba18e523bdddcce52186771a61da411d4ac412391dfa741adcf9a98f31c49a2afb4f106bfd51692365aac80a58", "f41ab7f37d3728a2bf09ccf2c2631a120d92da61721369526a3692ae95ae515f4ecb7117f0e08b78a792c88c8fc0bb840e18064e72c7a2eb5226dcb2d9ac7e3fee3f6136198ec1595819a632129d4969070fbf9e74c492834542", "-8ea6cde1110903a9ec68a1ecefbc0960fac7813c0436ac3bc56df4db5466a8460a02f0dab9fe9a98159c07d2e1228f3083d82b6bd0db95a43674293b", .None}, + {.Div, "37e2d9ffbb7717ed5aef0db4c11fa6344a18cab081c22850b9ec429f90836046ad05234085e1df91ff0cd6f73e1ca1ebae3a2c7b49415057bb34b18183915f13e57884474b259927eedc8619bb8de169aa2afd420b0a658a8aedc96a35653ee8291313f5434f6104d3d10cf6862eb4fb698fa6afe664a5fcf68e44633a37cdaa5a31f389500d985b68cdee8dda89e1ab570771195854", "-768020ad07a07c1513a1ba27dd80d484665ba482af62730d62ef495047662bd1eb43ec3f824e917a60f39165c0224c47e1e8424b91fdd921246f070a9a58e4c3fbaf5909b39801b46f06900d61f848d2c076a7c68b3c1fb8b910", "-78bb7fa6c2dee22415a6202145b2fa05853a9b57116474ef8fbfaab9f9d6b1be788b7ce242f93b5d4fd0b26dc19189ab8b5d38d8598c5fb61c376ca7", .None}, + {.Div, "-391ecdc31953ef5670c94b136d9c3b5b77d5b4d3fb0d6e6bae9e0964d1b71d8e591307a33f51647439d7daaa1cc845175805cfea8881b1d524c085764ca8b6b234089a7941a5c0b3cea468f0066c981e3fd37b79c1519c0e56c7532107820e3dc61a857ca4589e3847c837734e3e7a38965b6200a0f6c2c7ec4b7c34af2f4ff965a8bafcbdc49f17f9ddc7797a8b2a58c3caf4346617", "-d288773370fc1a9bde1632e9b663224075a91d7ea192ba3edb70425a4238c3fc7d0a58d78abe7e9136b7bc98b2e461f6edddb16e54f4f250a6d2269a91d5502c1af7dde1bd466022086143ad09e232584aa614543a2526670060", "4574c24ecd13b53e78039ee311f9acded75db0effa5adb4b4fafc56201165f030fa3dbc2cf6647b0e1450745cdb11e940f4dc2b784a0de97c878d53f", .None}, + {.Div, "-6ff88c2e252ed363160ece65ce6b7082bdbaa0c5ce06cf5668a35ac07d1fcda86f2d209e873a9ca1c3133661e2a739f83d6d9acbc2cc00b8df82f14ba4ba4ffb283cb18de77f2d4944404ed1b6d28acdcd4df37585bca60d8dc8ac729940b8e01e5dd75cadd1b04550293218eed8af9276b12654d2cffe22592aa003acff560cfae211940e2db2d85202f517c1f97c50540131febf", "744316096924a901ae9386f126c8493ccf9f9cd26f27a6f16e06e2fa7e18137f3e1455f5a2e2a6b0acbf6089d88412462cce73c8e1f8ec70898cf910474a44d09b56eb86e75a6e6793d1e5f19ce9b41fd0c26e08a8c5819ed3e2", "-f68d1a8b0ddf2f3853c69e5b409464254d7772bf4b97ece68d0a035d4094fd1bd0eeff024d71e7e0033f90d8cbef075333207cbeb7bcca13ad0617", .None}, + {.Div, "ee7d0434eeaebf7cb57a4ba6faafa5152e2acfd1dc12c70013332a069f516fdded6862bded70f62c696dd8bf4b41ead03e830d896d56df090ba71fbb6c2dc122fc379211acbeb4b844f3c2b89fdfdcd3d8bf9c113a62dcd54670ff212c3e1de700458fad860987a62ef61e5b2eb81d87932e9cf57d4031638edf197aeabb1c74134f9aad4dbfc887ac64eb7e8717f1909f0108b37a6e", "-ace779243ff68d6a390090435f5f52ed8014cea5db6b1b8e02dc55704bf2a3d0ac7f35adcb214dfb5ba429441ac958c0daecf64b1ce676d496cc0651c761737aa4fa72e239a9b2c488a8875afbdc0ac2f8619143632afd2bd856", "-1611a689c5c9659256415e510bf192f5639072a5c66be95dd227cf1d1a569e5e9742b4657e098c059e2f814c5b91dec28d06d5f39d058e389fedf2788", .None}, + {.Div, "1fbae410c6f1a438de5e53a5cef9ef49bb6228740f16210e530bbfa465dc692ca261728b6d053feb35652f022033580119932336119c02e173be0bd366e9d3d4fedf0f435f37514a154d9cee30afc18f9438882233525c348be58b3ef549695455c2b93c815692ff69d46186cd0416e0283cc7ab02943c9a06bf7009ba390357bf6a0d6a3f85fd5f9dc32ee557c933c7df4f1b983e9", "2ce7e974ceb7c1bee6f49a8535223c2a83db07c78d7e37546328d9344e52eeb168718eae2aef935fbadf8544152a060bf528fc1076451231a9a4847ae48df9e35a77f0f80b859049b146095b543f2604587c0e530c771f2cf485", "b4e30cf9804db7f3c3f7180fb5c219ce63768a72fe0323b780ec4ad3740924d2d7222a7a7d8f5d6b3566295e579a0ccfdd1604f9ffbeb846302f4a8", .None}, + {.Div, "8dee910300ae09d67893b205a6863395c3bc8c260f085212e1134aed3d68c757815746ad5af69d49e53cd492dfbfe9c9ef38caacfaa1760ce4340c060c336d76ead41d56e5c848a89b11e2dc52800e3c057e1de56804f5d15c831c696be82ec1fbae43afac856079978382ec9058a13240a2aa47f04697a29a55d0a48fb936399a3d6b626f8e46968cd3c26b0db30561192466f039b5", "-21ba2385cf493c037bc814164f864c71f045ca0b2966cb278448cdcb7b339ac909f992396de98f5fab69ae320df89cae8497703225052900acc1ed1c95dc058d9223188e6f32a73e6e8578ed74bebc50dc79a548188bc8c1fa4", "-4354f81fcc6d92876d6f83082894be34d20de490cbcc0065c3803e37f1c461bff705d73939f0457859e8a9f28e57fba9a6009e0fa37b6938d8b9acde2a", .None}, + {.Div, "1ee83070fd6583f7ac49231e3d40f0102feb93d86cfb03d59781b20769e191d7aa83f3aa6fe1c6d69e2a1e7807fd2979eea4e2f4974b6a759a4de8a764acc531d0a09e0be6a577e8a4222bd0c08505451e56f669e4d86b40b77d025f58e4e9985989d7eded8399dde8913c66c177e2a8db8f83444574cb3281e0a0bf6508af83d066c637390eac4c1996428ce991bbad2c79e2c73e28", "-3a16d208df5f0f47849ea02fe9ee35610c7ab3ecc3d315de08b0c59cced4ef7290a99b40932405d9207b39cdd3d820375bd89358ab2b881b3653fe07a345578248e860e7d2e1e4dc970d0eb564d2b5d3792d974c84ea01b90625", "-88352cab4d588378de831f1da0a691b5c69cb5905f13494bcd8ad6bbbe16dc5f79d2e0d12a0e5dca4e399ec3d88f701213e4b9924737272c9045ece4", .None}, + {.Div, "-669908670f3522a82109430b80fccda45d232620f43ce68f4e04c6710e3f229b84ec8103958af86ee30eb71fdaee54f35ff8f5344aa9969748f855a34aef068dee5cbd67a2249cfbd6090a017b8ba0fd8189756d5beb4ebb8105aa9b14aca6a9db46d9a8c42f32de8cda1f3c53dc2c672ee0c3d0866411fd4c7dd49082b481f65080e517392b08d26b22df11f58bc8dad5c33cb00a0a", "f3524317be42be2992c87e85d89697cc41acf898505a41dcd5a7e6bb1bba8f546cc3fcf82b890408d824b1be6942abbb8bae6a22cd5293c2fd88f3ae6aa9b9e42217acfbafa1d8003bc0119e5a455450c087a9fda53ee24a8070", "-6bf19dbac63c2c6fe0a357bc03ab87399aa61b2d36cca0164cfc7f672b8a88fb114893e2b302d48b3c2916de0550777cbffb105b8817db6be2f254cc", .None}, + {.Div, "-fcce312a31783166131891a8ea5c5cd35b8137efa99a1c6cdd7bb1c66287bb3652002e207d0fd9ad3232e6fedb1cac74f237c297617eae8a828400f137d97d96ae06c58b220a60efce7e0d4f28c99bd73b662a36e13f664f9d00deecec4ebd8afd81a21d8ced3cc239156af28823820ca3a106edc2c32b89d58b1ca834aa681d6c40b7561315ddbf89c035a6c606bd05b026ad133217", "-e541ee0f241a9366f7a6ac51bf7623235661373df288ade0c88b53495d71997c50478d75eed5eeca162bc5469a34cf0c996ce6042b2fa421f279a9e1614ff93cb0e6f4c44e4465282a37a20261b98ca106149043bc3739744615", "11a4b7294f92a41ee1bac78657e182d88d6230ec2d6e96dfd75a3fb8d0df8823aa56483d75eee05815572cb033d96215b99c7376b638fbef1faa9c3db", .None}, + {.Div, "a416846193b299d542e6516725431a6db57c62c123d4e911655e737013e5872e241afd26bb6215ea9e9220e13752cb1675db0377cd1ea09156b061c8eb3e237f9e40f2a0bc5450704aa6b7d54a9b67a658aa9759aa69340e42d32d5074d1228fece2118f88ee5c4af0009a6245ffa6ed9687ebd86731ef7eab4571e407ee24723e8249fc459d89ac83681560c6feb1f281c5ecb699a0", "f5565afb6bc1c74bf84f5a983b58d187719a79b73937546e917d5323e8daf4fa6c4e9e6a3d65e8d8ab57253a7f05604d4790b49be05d7df0caa7c50ba7df8685223a4750ba5121c84f0e85c697d5204b617a0ca72ce6ff7bcf3b", "ab382c9303a609c601ae0e8c7261f8aa6928c1cf1eea0951670ccbef48ffddc072a6e471ca9db9674c167ad43089f46b6c4db1228589dd257fd5dcf9", .None}, + {.Div, "9b013111b1469bbae7269e69e7971a45f885823f5f54c926e990c8c4d1ef52b89e8a90d0e19d55077b4372ae450765627679053f913f23c7168b14ee34393aaba1e8c1ee5eb957ef0b65c1fe00e37efa087a11a5a0abd82aafa575be87f227fc7b3dd60418b36f6c6620eb2386e014ccd7e41af5b179d20e3bc852a24082f3c29c01c9a6a7cff7da7577f7eec98be14e4ff60aac64b7", "9c5dff5662de1f4c0575c9afa70d06e8ede7e09702511deae277c3c776bfb7016189d9f847b51a851a8657092a14d3e246dfaada5039a7c938b69f8795e2c5a05248c78d415c715dc5d27e6cfce452b0e25aba868a1ab1f82c4", "fdc4f1e7643fc432a8820a81cd99ee4400ad0e184ddb6b19ad8fa3fd0a4635bfa8fc33c5e962aa2624a310122ff1738118a2ef50f9ff205cd8a362961", .None}, + {.Div, "9ec151bd790266e382c777750ed394ded2e220e101cafdf57cc7accedce375e67f15737466b66f805b516232667de6fc786dd8b440050a88997902cc659862a36f6e08e75b4557e7da9f9d2d71367d7cb83ae881e1887520e52b96b2e1b3af602d319695bbf3c5d324413055cb1837d2e22e91dd6aa83ffc0be0fb11160cd91d826825f1ca960cc54c495ac6bee616d0a25d4f9e85cf", "-479282067c0658ed4cb9c2a7228986b05a524c12e8a0b4bb0eb37ce13ce2e2d886e4d9bc68ec5e8007c5ce3738fc769db2b8e4d17f2ead76cc25d336862a4248ab1211eb90f094864b726a96b9f8308a656c2c4e521537d1f3b1", "-237d5fd6f5c9c5a58c554369a71085346a521c334f25c620dc9b250c86b1f47e26357eb360a687f53dd6653f08a0e8c27b586fc45ec176ee8e7ae7de2", .None}, + {.Div, "-d4762c2d07dec977f2c2f7b3f1e4f1e0c8097541d25351969ed2e8df8b48001670c2bff078b8099998af3a02dbab68b84ff398c7960f533e6886d9564502762b27c041436f16da744e7eaa8d46a91f35d08e31caa1851ca9aace85a8883988a9df63d5712c41fc28a400f03ee32ecdd2bdcacb740a69c6118ffbee83ae099b5d2fdd2033c435a76afa5cf827082ebdbe88fe07c61b26", "-a5ac374e5ce21a4a5ffe373f0cb90805cdcfd8fb8699e44cf71577f83a2a0488fcfd6c444b7e115b4750298a8f98b30f4ce99dd2a14871d12159a94c89088a284ae6ff64429330134cc03ac318b57d42e8545377a69a18cf4ab1", "1484c852df3844aaf2fe7a23d1745365b9f24087677e96504a556180bf70111cdee87304f5c2e776cde4bc7d091c3fe5f09e0c739857b4b63766ed19f", .None}, + {.Div, "-69c03a763ba95ccfb7997ab3fe509dd7219ac715096098a9e14a46e4a62dca09e57efdb5a90e7cebdc9b1b766ef14f19f8cbcc0512ea58446954d71e299a763c22f761c1940a57970703e6c868469c0979539737eafae4f43f48dc2c7ebc7a66b07758a9225dc09241b79fd2b2451af28b37193ecc6d655104cda73258793ff40a730672cef2e300d1292dee56e6e11e2c083648e6d", "fe486ff76e54d0787e35dda6c42cd6242a02e3d5b90d50d48ab1abb7f838134fd57880e313611327f0ff7d8357c364a0704d2f4f0e351f86a5e6c2fb6b569064c1f3b51d6455ac9e5a3b8b5338f80be8a76a52f9e275fc723657", "-6a77087c4de5be92779a6d1d7a846638a388918e923371bd7289d394081b9c2dbc8e8607701914e9a51dfa8a534c56b8192a4c684637a83ac099b5d", .None}, + {.Div, "-3dc7d00a261883ee9c376426a99a55adef02e5d1951145480e31ae0b1af872232963281e054b1de24c423de1adbe9ad1114e85e45f471f9afb1fa48cbb8ebe9e18a27c56e16a6d76830a676612e5a84e5fe4be67e5e7713de53d8d173cdbfc290402a024485ac097d4565601f4bab4205715d356eadbb78b2d265b84647315046b7b8bb2d7a1f62a7c23221ce962e2359c3786e1b55c", "-fa4594848c33a7174f39ef80374745cd211056582a22ddab8c4159e089a17a50a144a9a3a54d378029962d0adef728249f962e8505b8e0bbf2463333b383d0c529ac39b337374c5b9674afdf921033b8db192f2cbbb7e5835df3", "3f31cdc6d53f7c38d3d0354189610e890a077a85cf37f6dfc482d8f42802fdc466368249f49829aba1c7a1166d3c266d028c8bf9ac7eb5df00cdbac6", .None}, + {.Div, "-44dd74c0503e69f2344831e3a359ac07dd9840d186d1cdbad9124b980fc60f54f911acbd5ecb73c8c327ae49d380dc64001d1fe8d79a8212efccd75ff3e8b512ebf556747aaea09864d7ff2a2ecbb77865cd5c834f9cba9e392ad76c9ee74162922f477592761c0cbc5b76cdde4f608947040c75b0d68fa8afb6cbc9cafec1bea76f7b9b8cf917a324f7f6071a84805002a909fa5b36", "-8bed512f61e0d6546250847f1c74a3104162f3f64767093b79e500003c2c9986730600a50cba7341ac801e40d67b1d6e4f17156e017408f4ed370f3eb1d5b6ae44c62670045568c0741f5ce26725832896ba9b401b71f889c997", "7dfd886f5c90f899232a804fb8514798fbbda5b65e6662e15d51fda378faa9451f7747db1c4b27dadc66a29da2dc948e8b88bc7812968b5996e6848c", .None}, + {.Div, "890fbf6e6f0543393aaaa360b1599cee4f1214e2fa094cb8e27d13ae8a8ac1b6f85cf7ed5e9a9217b32f20b3679446bdd45ab310427da3e10d35ab362fa304016e6038e7fcbbde850e93424cac40cc9bbe28ba927c4c42a4184811f6a3246cf83e54772ac9a96aae6c8530e800968631f154e2ecbd638292f654732e1b79169b5ca244514908ed6938be02a71ad54f341e1c61c8eec4", "-169677c61a97af3d7b33ac6465365a6081e86ed14af18b918aa8504cc720db30c23b3a3b34651fa0d8effb288f3c8dfc6054e827d4261e633a1d3caa1fb64d0c311d2da7f5e2c99922c77323340627387fbbd7fdd52411fd6f6c", "-611656b551c8e64442069b886583e9f74b0fa8ba93a5060168cec1a39bf20bee93e974091f64968caf3000f8dc5c822ba1402eee3d00826dbf94250d2", .None}, + {.Div, "f2bf0bf22db36444d62d22622eac750c3ecbddf886588b276e3e6d7a086f65bc7fc96c78ec7b79bb8677ca45e50f85f63c9eca52ebe8255eab5ffee2f427ca43898da6c4d7b279c92d68e5bf2c78f9eca72e60616b7fa0f5777d351dffc5d210e577dc6d54c33abb2c12e3f2426c034d12217cc41e16f17eb48acd78bebedf1049be7c9d95bb8c76d74debf707f58776d78eb7c5da7c", "25d94c4e41dc377ea2e155780e97337de9ea59b129bf82bcba08e92b0faf2ef44eb26ce315ce9ac1dc166acfc196ee1010edf915ab4f43a082a74f01e4f4b676f11f933aa7211ba9d69f1358dda21096c6cec232ffdc1eb3cd26", "669e018e1e5611d1764143fb240bb2757704c30b8151a8be0d7d9b9dac31dc2da8e4d424cbef6d1a7f622abf5f60d2afa500ebe665ade534c89fcafea", .None}, + {.Div, "-da9c84f16fcc454ee8346e0fea6908f3b382284661e6ecff49dffa819b1065c439c83cedcdb4b3ecc3ace4744aa6295987ad2055b4433be0a94bc592e5e08dccd11154ec48ddd1c11b481ffacb8e53635d5ad4100e5e0fe5e7ef9c3c0d8d992fd401154c7b34be5a28682cf3875012f70dcce80eac912992e2fd1a63b679697376c5f92be350e4461013cc3c74275ea1e7bb427a3b9b", "7d90cde37b04d99d94bf75cf6c3eff52c55639b014a81983ba9906bec67f1e88b0fc8627561623443e5148ae4a885925f33e9f996477b5a230c3ffd9a6b4308755de1aeb418d7a5fe5449c45dab1ab7c91e922b78e1edec7ac55", "-1bdb305b5e7643314d32dd8e94dc32aca9d9c85a00d184e80f1780f6f7c9cd7e2107365572bd0cbf721cc4d4fe25956f348dd841d0ca4feb5374f42da", .None}, + {.Div, "f6dced7f9dc6c12babc9799ea38e4df00e5f6da895a8d99ddb2973254456848f9a66b28872d3e3b082a49a90d6159d9dbbb3134543b261c94b694b65c4334f6f0ddbe5b760acdb5cf101b5d4f34d2453a38e944159c518c479ad676c0f28f72ffa6fdb83371376182bc9d742a3d99d8c56ceb14cd19bf88bbd436d432137d865a701629dd4a4e9211e0707807412cdb684a8b28e1bba", "-5358670c452bd114ef62711673935e50c512d617861ac2756d5005ef904b7b564091451b7bf530597b10a7d3d7720769c546e4ecb7113c457389237c0d4a7b0a8d6c4c60472fde4d01a53bce55ecdf56f7bb647b7ea64d347cc", "-2f64109031c3ace13b838d500a8c883fcdcf24ee33039a0afa9dc858ebca67838fdf481f07afac60fea14718a2df79d6ffb32e14d485f3f400618f67b0", .None}, + {.Div, "-e21374c1f98a38d393da0db8fda7633f1c1efce64dd360e66f5f4160529121d9c51c1d832d69336f7e00f922d7513ee86444e715187c091c2930314bfd7d300e53f331c8744b7ed5acd85c72661680d98fa5bf758432910b1673a8962f7072f6e83db7f7ab33797893839b357eb6fe7339c67ce3777c1ca3e81cc69f17bdceeeddfd5de5c5b995281e6fea04f6e7361c9e7b0be6e73", "513d00ae584326de143442537385474cb262be5f9b31079ea666a6f069aef81fbc734bd36d21a5274897fffda3904f8241546cf656ea1d67fe539a130ed087513528a6cc0d8081d7949be139e31d9ec282ad24d0373b288e286c", "-2c86a7ccd9c9672b30a1ad4cc418fa72c644aff1eb4e5bfdcee856328a9cef01e3d251cbb03a1c4f709f0d0d510c84a26c23c448819e3a2a5d62e764", .None}, + {.Div, "dfbfd1de70afa3447798ede0ec222bd8caf0112417eebff73eec5a3a41e6e30799cdfbfb0762264da2fda34e802b864de14fdb8f9aa06d1d944b50013111ecf2a63b9b4f6fd8dc73ce15e51d9fe67c4e4b6922d0688585bccad1731c9e774c2dba5084b7c29334ebce23c8298f0a3a6c02ce5aa2c3b2d8a31b286b33b8655e27f4bed7d3797bdeb137992186b2a70adc6fc66a5100d0", "-efca09da6db6108e6507f1964342a0962af16abfdf38ee40566acda0d7bc6fff7ff2b418c52728a417d45c9e88b49cb004a2eb2a2a299fa2229aa7da705a34b03aaa3246452e9e256a14eb9a6c12d057472974e092bc83ba59a7", "-eee02ee4f11f1f9334522f495acfd8bac41f8d63d7507d2cc5357b404b8384b444dc88aa011f33ac52ffb30c93ce80fde26b749c97d72cd12635eb8b", .None}, + {.Div, "734c2551b638086e309aaa285f0757b28526dd69bc2da5d5091ffb7df4679d7a1ab08065e7f4808deb3374ddfd62f5088ced11aae0418b40ba6f91d2c8bf3052a90f2e78c0dc082d43eafb541469e0c3f6410e15f26297f5b116cb69e571d2a974ab3e766afa56e54b35ce167c93b282a0909e9d35e4277fb8732035a08413cbf6a53dfe1f66a32119071740cacbadbfa09d41c76fee", "-dab3cde1872a8aaff1c961c490e4dba403b67d4bddcf40edb0bd0ee4ec3916d427ddaf0df7633866c99287fb3cd9367e8d6770a70f98aa0ce5c7a78fbb12c6644cc67db49ae262a2e4b3cabb907358bdd8f0bbfd6ddf292f3b82", "-86f5d91b2ca81c898d3612f3af613a459862106582c31d5aa1f389826545ac78ab2e92da4b8e9fe926ffdc99dd2a0643725f1380bc9adb30e9aa813c", .None}, + {.Div, "212f90b4de369145deb969b88dbb536730034c177512d4784731fee92939c4623a2750d05535bfb0d20a2101672cb78e335fb52465c7d6cf1a761f2701ad0e7696540b26adea941de29478df8e19bf7c76ff252d93a5707f55d4fdb9233ed68f8c9361d9a107b4f7aa6d978a75c2e9a2df5011974004a64f863bbcd3a531d5ba6a5cccd06af001799c6870ddccfb4b6557515db4e040", "52124f9c92bf501772399901cd00497c0344a3d4bed375a324471360f34621210b0bf79cdb3b68c5bb86d19289f05c7e9576d9f0bdf2b3dcd1379e63142dbd366124095cc5c97a0ac19f0a1e0e760fa41ca0f6a16c7064f7dce7", "6783a00862f0a1e13a0a125fe055b405482d356a916b4573d506a134e81711db1bba6b35739921f38d28a1ad6aa1a1af92e1fdc5a188083a564ea5cb", .None}, + {.Div, "5d15443155d26a92e660cbc793d6e401ca78cee65f40bea3497fee6d93ef328c6d4bf191c6411438b6260bf10df7d95f4b7a67b1b8a80543b6b05bc1811f191322f0751517afecaadd63d2aab21719708a4418f099e18b9427cb05e5ee5efe0b0962b20d927ec58de151a4b2f399f6134d1805ce0e44a84f771e9b1c0aa4f6deee45238ab8f24ed75d5b26475fcf605c512109bfc3ad", "81d53898da4fc3588570523eadf21802a75a45d724b2d0952ffb0f35bba74ec2bafdc23d1111543f2830d22b9b8e683a53936bb17df0765cdc5a921fc3d8d4d909afe0aca900fb2791d0411631352d22eb43c63899d5ab78b9bc", "b789b89ccfbaef95bb7c1130338877ec7926a0cc88291fb60f40f99a5b39d8b1ed4aab89525bd301aef7f55a0d6a28c8afc6540d673ca8d05aabdc4f", .None}, + {.Div, "-71b55cbc18d6008d48ec3c60312ae9ff6c0838ce5c6c6c3a0930fd93a927f0b884dcc16f1d73d0f5bb5fec65a7813d0bd28325ff0aaab2209c02f5539e5a79c9cab88fdc1f508f79995b8981173d75becc5759990a52bb5d0d0d63cedfd38fd24d5844870bbcd9ec63d65de3117feb54a0c6e88af945e52fe378786701ecab7e760e29f11674c002831d459def87c0c76402e8f9832d", "18a5f07c07b7f8c9241c0a90e4774ea45b0980d583cca517712a4607f984b49aeb1864ded4f4b7d9259eb1cb99545927653342d155f6bdd2005ea544561148b1882e8a0e6cdaea355053865cf5cd7cef9688c5b4070e30c09019", "-49cfe4f060b60aa8dc42fa92cf8848a286a45978214bc21ad19c0df6197430a5e5a1dab7129561e3df8448ec557c8e890c22c0a0e577bd7ebec5f7d8c", .None}, + {.Div, "e3460f0ff785c5ed542f079b80f0b5fe9cccae51ac096a7bb917234db05f2ef3c616f884b8c37af8f76b1a9d5e9196db20b3d5b0a6ddc8b3408280f27bd7a3c43d1636ccda7f361694d1d41c1a23286a2c00352b35c38b2dc7b2b15150e395201175540a36456bd71bdc66cfa70abada00c31eca3b963491132af7a2b47b13a1d6b0b3e8905ecff27243bbeacfec12b8ba897251d834", "-4734cf17e1bad697fc641b5cbf334aa78a6272577692dbde4ed968efef0781174c3f90ba5c5a9016eec100a5935ed30c9549cfcf75a6a2cd30debd1ddcd557708aa6744875f261e5ddcb478931714591a666b124f763bea2928d", "-33117747b02c3ddc36fbbcb0ae9ac7ba1c04db8d4f34ada8ac251df0e07b8a588454ffb7c5cfe82274340b30cf190749f041735b7fb51679151ef407f", .None}, + {.Div, "1405014442b1ebd8a52d0372584dd7f3f2e9f49e8d81eccebb9419967285576ec8c8704cf80c9441ad004c7aa8aaa8fb251d9cea95a79d646377d067a65e5e6e9d91681b7eec117fd4a4e6a5e99ac647fe11425b095219626b5ef66f965acab2fc883487f0fcee4af6d0d78ac2ad41a2311beeb87f1a0ba5fe080b648cbf861f145a5a147cbfc607a8d54b2fa637ce5b6c4b983ccee8", "-e2210939f377f1c93c4e7d673793f0d27a5bd9a58029948c9fd369a57be7c62c7314b49e94d9e1e0c6c791a4def4f847424ec6928617be964832e6072deb5b16925930059ad107456abdc521067a9f8a33eadda21033f68f4f86", "-16aa009b4561dd208a2fd6ac6c0ce9c85f35369ff35151c45c2af81047b80eb3c7d18a7314896d9c0e0f49b1568607be4142947f5d592901fdb3f491", .None}, + {.Div, "9e90478c05ac26b79100596de883e9fa6f21b9530972cadffe5e25bc93e9b885f6c17fd07df150e83a0c2e388846b68495e5a455f7440b91a0061513678a67c011c9bf52a1de31527ecb613bcb571cdcb7367da5144aee6e5dac344da59a3c48fde040de8993b9d832d8d9f883083993e258f9b57a34cfed0cf1fa362b0dce4e772f4ad1efe7d345d10fff08903c9fe649451c2e5917", "82c5aea4834c284dc26a8d9e4889c7b1b3025e69a49efe0c2a4080aa7016a15fb468bfc9010418e53feb63c870796ff95878565b136437e98ca88734bea226ce192568f05e5724df4d74d20f7b8481efec029ee10cc9acc030f3", "136678dfbde24de01aea193e9367b76bcb50d010879e67cf631761243861b9ac916e6365e1009c65916f670cf790b7f1610ece26511bd5a2398783e62", .None}, + {.Div, "-66bbdb636202ea0afc6ccaee7b5be25990e37a7b529ecd4eb964eee2defb856cc1132d03e53fbe7b8154d4160624627423553cae89f7705a8f4a705a3ba633e308458ab260c9d519c6897b353c35e58cdf154fcbaff08292e40fa25c8b3cd3ae086d12109e1218c0a7ffdaea8bb24e821a0de5bb53353437f24ef935280b62a648a7c55c108e348fcde8fced9fd97b26f0403860ea79", "b85296a15dafc3d300c62992425577ca5aecbbcf699f37377c1a6425f94ffd3b99dc47e5bfb7728438b34781acfa9644f632bf895ce1ff86674b7fe5f44a74b95050c3f07e5d0fc5da5a10bc5cdd414b2d3985d3a607f7188d6b", "-8eaf0fcda4f65f6aedfdee0b880e9bd275b31186926e38e0e82943fb1bc38b07d9a6af86bec1ecfefd95b4541f5f821cf1cd554f53823ee4aa8d1ead", .None}, + {.Div, "-16b6b6f2cbcd07433b5c4ca557eba34de9e20077956bb98828236c29fd44c9299d06437350b8c94c3fe6f70aabdd87ab9978f365c1527d5b7d747173dccdd50c66d79c2949ffec3294d645d74beb4f68a91519d6b9316edb954d14346de80414e897159d0eab2ebc4a78af9ed8ddf3ac48e126452c78bdc132f04f985a74ce4b058a3999ba4fa5f4158e24f8f39b0d0b2510cc02e87c", "-5227c566ce1a36f0d4a7c998537633e2b7ca6391e291a46810c6ecbd473b67667e34058944528eb9da0ceba9d95577344083da3381c0d39637e7a2a43bebe8137beea67b6d987883690f22c617ed9a6715a5b79e05f99a8e7d2d", "46c6ed7a1cc0bd49f8dc20dde8ee802e7d34c452280f07d74e76f09ff7ba4229e5aa24cd769bfbe538a61e57de356b0e3b14ec5a8cf73b7fee590679", .None}, + {.Div, "a1ed981b6bb020b1abaf61588a94e9cdb82f2cefefa4f73f5c8ff6043f7ac74e3f1fef4b28b117d9c3e74c1b21e7496bd1c5755b9cb2e423fad5c7ee3081eda6f86c076f7577f3588767f6e2e9e40e754b9911bfb1093250883018c8108c446c51dd30b022b55e1d0c4fe270a35e738d7a860e440889bed6a4bfe027061bd6ab590dcae948ecd19a93089d66f14cfbc59f940e30ccde", "b433edd955375f16842395a1b89c8c486dcf975bbfbc052ebf6baeb24e2a9744c8a39b960a85960cebda809149f269aa4deec26bc4e432e3dc067ba2846e3c26c285a8fb78cfa38f099fa305f31c7c4cb0d91e4721492feb5124", "e609db9ccd18108b88f710b8e681fb2df41c9196a2a00541038a5324cb595d6e46f9df5890e543088a19bbdd0cbdab8ddf08640ac728719cba74f31d", .None}, + {.Div, "3281f9ab9ac1e8c9dd2922ec5fc032d25ccd2b70158bdaf1f21a50678f702e06fc8ef73eebca28360e2684bde31cff3e5b21dffd0c8efbaf0ad62ed9d09d15a7f9e75f4064ba84b0679d4e93ce72e69656dfa3d7c87fcc37cb48fc7364dafc320feeb8000ca8832e7b3a685515b9782cd12bcf848c8c8fe0a970f24561b60667f6405cbf0ec6c956a9c69975f59b5e6cffc9dcfe1b4d", "f34bcabe5c95e836f5f3b2ecb496ab8006e5ddedc4f396ca49a845ff6c3da1e2d5e9389669b3ceab7607e8c007591ef50b1bd527b9d40ed7d5c31cb180a88e34a5ae68d6d8cc4c9fe923f207ee9bf017c9fa99cb33a7c5e104fe", "35252058d3288c09d18b37fb6069ca01ff7e118bb34ec776e17ff74698b8e7045f9c3044ecedf4163f3f51e54ae97ea9b16e6c3a291aafa13f567140", .None}, + {.Div, "c16802ccde42b8249b0e59677e2d793f1b907353d9b529b18b8e5ad08fb535e323de2035cb33a920fc4b9c37e146312168d0af2017d68af97cd6a46ba9e8145b2c4fbc9aef64ab489bf50b7f7ad1bdf18f8d6a59922deb3578af4395b92b9bb7f94e6fb4e8be18357b7151f0afb792f79691fa28579f770a874b67f2da0b944fe811625f2d17954ded70e1f99a75b7a4de95938abb82", "-90574c6752228a86f148c99655c836dfdfdd7a06ada1bf721d5a8e420950833eb0611455a546438943af3d3b1348e845105964e0e882c16dbd7a347d3d4b23eee5a518a1c5d55e39ddc8a0d0bf721340292c826bf2db7ff5be03", "-157056661d4409a1c709de085392eab5139f7b6baba4f64da8c2855d1d9b4dd694517780ba700e766f8efd4262baa734855b6919f1a920bf67942b7c3", .None}, + {.Div, "-b3e3632c6a4ee402e732e80721e44c314551f02d2a8089ef832e55c8d84d88ac76a9eba58dee41bd590ace1ce7747a0a5a9ca7d1eecfa39a9b6c0178a9778731a76fa68837e43496539390fa0a5914af529ecf1481eea72b6fbe3e6e0abc6c2e09afdb33a88eacadea7c89b85dcfd03adce6af3e284c4978c3765db8307c1fca44cfbb40d63003409760cbbe263490a4f6101271ca8", "-5a2e55b966e85e428cd0f0510fab131dab47234ac45909492ab3d67a685153f1b029e073d742616deac271f568fbe7d953fc61f614f39adb86d1670b9a0b11c8f01e1ccffa401f9adce63b52df25d363cd3fdb5a887e72ae4079", "1fea7b6284d1e5e877ddffa1a2fc4803110936093520faa192771d0ca5959214a9b6eceea0946daf8e001fefab8ad17df63d21f842d3d34870c8208d", .None}, + {.Div, "17328e8f55c82fee89ff64855e3eded9736096e6be58b955e13aff16100552b1c37dada5d0a298b6c165b97be5209d618352380dee5fb981b7e9613a1ca861705487efa5ab9b3b07dbdc63e63500756859191a9026c314192f9970fa75d3ea1429b8d27d82ad9d90550a4a767ba477c5bc77ad9493ad72ccd35827be63c04ca38930b9cbcb1908495ab2d7a0318ef25b4bed5668e9f3", "eb76099cc02ff217636edcd3e3c83a7d691d90d63c87e0260fbd8af3aacf8e78c70c1998c9eee6c783e0e497c6d2170c39f4e8427da96aec248bb8ae667f13ce8f7be23a41f0ff5569f89c640c58eec05178f255cbf7af067c91", "19389178c178e206b46e1553b5e1d8a68ba0b5cc464c6abbbcfdef40091d646ac4bcadf0d2b883b644342a4d81761afddb6f6431d4324973ef1596e2", .None}, + {.Div, "715954f8b2366bbfd6f67b301bea30c871c4cad13667bdc380475ea6ee2207a416bdb3447b4a3fda61ced153a6d082e0f5fff9866eb5acb62e8c12ded899839677b4ed4b6e7b11cd90217b47415e4e111c5754d57c3eef31ef04147f32ad4b8605b3d52e62348ddad9b7630e09fbe2947e6c9d4694e79d7eef20b10b677cb91e3872a1fe42eb793fa2011bc751e0d9cf55764fb7f819", "-8a2d1eacd20b84de8b7423ff510c8374cffa75427cc633815fc5085aab31015d35c9a0cdb601a8764dd8fa68be55a891a4a72f16179f6fbbfd27b30e775e37997d761357142641ac108b8a509004cbdfbc2bd5a278e66aa65f5f", "-d200979118914ed1b74040fb2e93906e6b9b9c51ce9e5548e96880323bec870f2793df411a9faba489b81cd3ff2e9b2222250df8fd7315d8e887247c", .None}, + {.Div, "-a081220d6d9d990c8704ed00d1c2613599dbb5bafd2114703ec3cc057ffa93f1e4fe5bdbe2fb99c5e75b1c8dd3dcac0b4d520f2e6e361eeda0d5b7095a3e008fa8f5d537eb5fb41d16506693767af0865db5e6730780f72835441f311a6c97c374717dede7dffc6eec274b8cee7bc2a69cc314068c23f9668641e71bd5883148b6fa8688412287234899f6ccfe55862e7a2dd57377cc", "f5f61f811d634be0471ded8f142b43c84110cd9078215771e08131d620bafe0e89f82899ec283622cde71854667d1f5444e13a0456fc404110d75a897887185e05519fe0ba505a3aa917ae913910d86fd452d60dc7035a108430", "-a70e21594046ddf9788b5a51d72ac9924904d9c44d8c22748b4f0c37cf404aa9abc9c48dc24f6fe23d83eefbc9c664704750ab702418538f3d0d9319", .None}, + {.Div, "3a2a195163956c231e8d92e97b65ba0725c586833015f4fb4ba37df1d46b1beb377100ce435a0a27fdc76eb4b539d1417dbcb33f1266c21041b00821a5152cb24fa2b9232bb4fb42d033d32c2541ce8e44d1744d42052d149be3465a7ac1775a2a658be59d75c900b305512660012f29fd543a3f104673b4de3f5362a56151c34eb1f3ae1a878a030aa47c50421d6406c0857c2236e0", "-3081538eb5412a409e74346b456cfe5d6714deec62ab0eaa20cb63033374338d7202561afe14ec56e7875ea7d0b34c3195346eced1d0c5d5f44462a0d7333f7b3425db3d8c56c4f5d37aa89b6b9f3dec3f6932e8c8ec030d449", "-132fac40b93f4f1f5f4b82253a5ffbcdb0ae1a3bc3eaf4d3f3e14f2b176866a937b7c66f0616bb27b617a058e8f3e49aa6e9dfced0dfb65d2bf27accc0", .None}, + {.Div, "-7fa83fe1656300567bc5366f5e18ca8dff71254691a6db062f44e15a9328240a765ca637df74f0e23c51242bdcc1e000249fc565d8bb98af26ba23ffb54f07bf2c48142b951005379b8b69d02162c3cfa5cd67f59aa23035aa2b2bff2978b54136f040e9b27b476cd893ad47122f85a3650ab50bef63271a90e24ea50c2882bb61df376d33b1edad017f75188d89f347686718c83e32", "96bb3fc300c3f485def84136384eeabd6c87c8736ceb99ea69be45591fbfc2782dd723750b3c456affbb7e87db4376ba8f9a071f4438338c159e2f0e4c25779052d6373a09ecd31715359c524bdf072e7dcd1f243f98859853ef", "-d8cfa430258b712b9b422719ef56a34e8c6ef5bff6f980e0927f01527bb502a6fabc2b18562861f16edf6b3f2ba6c4fd59a5d2fd23cc3f051f2c1163", .None}, + {.Div, "6e15ad962bd60644974454fc6df5224989ab4c0e41201192878fceb9606e1f40dcd349165820f2d5f942c46b10ded297d77de30adb54bb13cde97285c7912a76ba74690dd3bc79066a3c28b3c1fb49a592af49ec7585713df118cef07d3e9a2555f0ac68de072708ffd1c8d4cc52f477f9377a08667c3a6f07c2b8e5612e8581c69ba2fae8d81b9c1712800677e737aa0cf238ba767a", "-6807261237ca050d1ee89fd68556df983b013fd748842602d7f575e392b2a58befef7b495d2921eb6fdac7a92af0a4966758d1c849cfb4338a92872cbe4044cdc9a08ac5d57b78a9c89913498eca1926fb2087bc0252719aa3d2", "-10ee7a9c22002142d53cd71f8e40e275443f642f7a9a81a95ea6676bc4b9386cdd9d7d16cf368895c20c55e765f796cc568d9ab8b8d23a26ca618c713", .None}, + {.Div, "ff4ee60165d07b07bef2113c0defab5910545be7f09d060c7faf2bfc157f8b8a5099a2881a3f175615fb4965f6c4f2fb5b900f5d5ceeffdc5782f219a4d2cffe514663a1bba24f680a49e01e02c4d25a183f673371b597b6b6db876fc9933f4a3175dd198cba64505e6a167f620431a80ac766de356be3c11f32617a2fe5eb55b19cc09f981899d64b676b96fec892f6671adea8eec6", "9d594ec550114bcc9a5b68373a608c99ca025aa661350b8f85cef7bfc1fc6cfc6cffe996526295ef885141471c8a7075e8e0cf55f3c3be2302846b9449ebd6f8f1e1d1e8f9b608a6b67c12177757a7777dfeebf759681384f095", "19f6030843124f2dea420723ab75344d2e9efd53a687c54af67c44a45b75a42b166c8dc0699ac50cb453a045271506ae6ce720ec385bee786b615f0d0", .None}, + {.Div, "7cb0974a6b576e1afe657d3ba5635a8473ee6e66cc73dfca200f47ef7c08bab42b867be6d5062f4fc188faa58c2beef8e38de4e9cea52dede61dbce54f9d2ec6b837abd39dc3a302f9afef9f1bbfa9fc6963c882a4c6c79e1665ae1d4ffe024eaf8582dbc22d6a00fc692a40dae7a6599bfff9f14ece2abb0519297b378bab0fd46770b01367b8ab764f4708ff553b00672b8bd81fb3", "249930559e4a1a0f56b5f7878e671279262e9c04981580983e1a868935cf380c18b3638d5ed116900727d543f4c134d627997ee2b6811d41ac6399d2932e96dccdfe3ab42d2c21569a73c9cc607365541ceb2a2f31a0856a1a30", "3682f8197e4faec96f12733fb98cd7f50b7f40840adf6c726043dcf66ea07dc34fff3a1fabb883e26138a0ade9477f7c040dae979e5b762f31e01ba5a", .None}, + {.Div, "b164360252211906f6c0be2e4f5aed3049ed59ae50b71fa90f43b1adc8a471c24581816cc27e7f3bd80ac9756ee1b7208ba2cf3d2f569fb840564dcf6fb66591f4002ac8ee815e79759071426370ce58c6e307f9bd39bcf5ccddda6ff99b9c774e579db4da78e3098291b1e494488d3ee197beeb091e79bb52c2b09e19f85562c73ed8b9a1fe92fd04a0851db6ec18ad8461273c5131", "-d6e32cd4bff60d9e96684eca91887b17c6b936e126383aef618218202f24bf9d5628819b509688463780bfb8dedd6b990635fbbbcc36c42e4c2d9253443b4d901dbb2a39ef9c6558dc0093810df067a65463d2f159ebd91cb866", "-d3548c0006a78b319c4a0f7a3932f907c702e42030d4742628b31a6efd374fd7dda94aaad5d701973cf9f4242fd95c64ef73c6c8fa6abcafccfc9652", .None}, + {.Div, "-a7efff55b5585e2d772b9044a75e0911316491c01e6b87c218b28482fbae62b617a4d276ab4851fcb6171ac9f32effb0f1948ad282e96c8e7c2627ef45edf8b29bf4bd880a3c90a02dac84a0bc7604bd9c8456e5a1b1fe4aabcf158c0ad62f927272d28bb1f8a53a80ec8932b97c5e1203a42e13e7eb5fd594c9f7cc520d40dd59144c51d56195a41efa4eddd764438119f33595c760", "bb9eeb3b14380272556398667a3e743a59cba9bc9b9b63d47b2a92d9fbb5d1c15c815119980537f666f263a3f297e5a26e58f236fd9f38b4e014d0687f295c4fd287fa192b0a2baf7c3b02fe9cb7bd19cdc525c48b6689cac88e", "-e5249f0c62c9c1b2bbbecd64960d7d0d06236aa2b27927481f2c929c9017bbbd6d38a7db7e8464cc71f973ed6b88242ee70305994eff2e45a46ab18e", .None}, + {.Div, "-52c6e1f58bc4a8644d71fc01d630a9aaa8bdffac03e0f1b9dd991f138ac681a78caf005afb05890ed31d3709bbe95f234744113f5edc61389ab9a80a5985b7888d34818c23956a019b94a136ec3c9ccdec9e2248a544023c192250594d466eb0e6721227f22aac5e8762a112aa87fc14ecdd35e5a0c69d589cf1114d6ff3e7e17eb45c9806383d28072d8c7aa84777ec14faa1687039", "e4bc8c252ae530063d4ad49377eb93f945d05e913c0a3e449f40a9183c9331be0621cc8d0bd9c5b4b6229cc1c04b5b05a524ef717cfe4b480b2c671f6abae6812a4f65757cead5c45e41bab6cb84e73ce41efce63a5b92789bb", "-5ca4a8c7f8778f18b423c5d93e0ead4948f1ccf3ed072eaeaaecd5192a9db38c54cf8c7062a672d303dd84c29f7c791c27de4d4b219fea32ce7c9a32d", .None}, + {.Add, "7ba20b06007eac36cd40bf3a7f4576075408448dcc813243823502b2fadb5177c2be8594b2db66b3882e0adf4771d794ea2c0c42378f219981d8d5a19a923bb92696355c17107b45348c14be9e8608517a52e230930368d3a5f64258bc83469222e0afc092daa57496628800e96f807a757128381602b411963c33280c05d372a7edfd5a30b2102f6e42529e0592b6c45da35807b3f0f4f954ea909052fb84ae4a83ba8515158e1a6420d5be581c37427825bcfa9704b825f6f3e9cb56cf3ddd7ab998f96469e368d6ac96f9a831bf2abfc847bf35e3984b65a3abaffca789e2edbb68591ff7d5423d3674a84a35e2d3c48f52364916dba99e0621e46d2f9a6819ad38c274661cf8c607c001e5db0c5b6906751624b38814ca01c0f4180251efec35820a9fdc5bc214d17c244bfe6fe63df1922c287a0e72a49cd01feb5e5783f000dfccbe17f779d4a998567119de4155d889c2b955da2852e1b3597633fd51d982ada09126b99be4783d3324c6dfd1db0fd0340339fa0db4a619b3873a2d4836965bcce46137960785c2b2735b77da70c515910e0869a8f9da291eb0b0cd0bfd43e1f66aa6184085befbddc828ae33a2a94ec7ab7306c2ddc18e59fb88fa8c676ba35b8f019c5298034d41b7ddbfb072f82b9c310b11f6f5aa96b6beb3d1e10753007be135988ed8610c95b864f8d51cb243e81dbe334121522c52f6d601e1", "ee31e196b4cad9f78961237b6ed0d7622d7635b7b6b0bad48fa66b6a832d58c1c8732bece52e48a02898bc696b593bd08b3beba56d923cdb8e392fd7e8798c4cb1396d4abf5c3c26cad30efd208d03bb3e5ad56d8010f83a98d574410900b843c892221678c4a0f3b3f1d9704ed87cc91514f02fd5451bcd53c13d0bbaaea3726a1c63ab0d1ec973185f2d37b3171d23c0c85cccc89ec0243bdb7d9dff9f5dee0735545356fd87d20b6bb1840db4ff2467690cd250c7ed74aeed357cbdefc8128f05dcec9ccc04f4db3476e08866bd2ef6fda3ae5954423baa10c561407c1462562899a20b0c156dff5e40779e5c6dbe7b6eca5e57d8e3cfc1cbc919e7cbd8e7bd321df7c40627cbfdb31ab351466edad2afe171e6f9347d2d8e92864951c7f8ed12b662fa8873712b57ebaffadaae12b02074b10bb7ec3f23d623b62406c2594f8a16746522c715b1564c6f00b944783cd84bf44781e630e85c04fee0822ad5490cd038c9247d53ab7abc0f4dc01ab76fffd535b959433339cde9de9ee5007d8a1d993b3cd7f78c79721a5ba2c6e19fad507a3060a94bd615831d640a480c50aa03617f74c7a49dc258a09280ce8421f2100f249e776ce421fd92506b387169fc0573c317d3d98e82a0d4550f241b495b296f2ad9f331b19070269f73c5f28377b07e91fc2b891904cedcb941dbc22b02068440c91676885a5f765aefe1306d", "169d3ec9cb549862e56a1e2b5ee164d69817e7a458331ed1811db6e1d7e08aa398b31b1819809af53b0c6c748b2cb13657567f7e7a5215e7510120579830bc805d7cfa2a6d66cb76bff5f23bbbf130c0cb8adb79e1314610e3ecbb699c583fed5eb72d1d70b9f46684a5461713847fd438a861867eb47cfdee9fd7033c6b476e5120a61053dd0d9a286a17fd5b8a9d3e81e6bb4d47c8fb51d90c60e2e529ae29c51b90ed86c1315ec6f8c874265d13666df8ec9cce7cca59aa5e11f4814bf05f009bf75e60135e85db1e10dda30987c59b6c5eb6d8f37da870fb471113d239e4543e401fb2b03eab03c94b51fe89250923ffe1c94a0efbf795fd1eafe54fb734fd6df56ba386c44c4c3badab537217b363bb656880bacbc91f790537a615419e8d948386d9a64cf33402967d446d91df8ee1206dd3431fab1c872f3d60f6519dd3f8af641233abe8f85ffe4c571d322b992b0d5b700d7c0593b3db85856b62827228f7dd95a4b36ef8ff2f9427286fa894b0fa569bc933d40ee740392261f2dc5c0b3f50821392f2280f7dd0e1622597a1e158fc16eb1b57f0f5d4682baf8d95ca7474375df6dbcde48179c7048f7325594b95dec49ea73a6ffbf20aa66c16bf66371171ea6d575e11aa42196c701daf9ce219ac70afe43a8861abd563279c4647f037f0ddd6121a7dd2fe94efa40bb001eb8c828e6d4a9c97bb1a2ade6b7324e", .None}, + {.Add, "-ea5f03bca86a203008300e7387d67cc6865bda267f6e81772b4b3359a88b05bcce79f5bcc6d4810d1fb5ac495cfd480a863c210d5ebacdcd3c7fe19d50e2744443e848710a2fde36f3878e6f90d6c59c81d1ab43e12a6f60fb04414cc92c83dce0c9d9200c4bc40fee0c24cf0b2b95e57fbde82036fe196d6ea86d424f70593136ca547eb652a828e7952031810f101a251663a618bb5de0b5f97806ac4f42b5241d7f5c60b9de775f5bd7b275ae1389fc6da0802c7bf82faffd3528f54fde31e092a2b8ea73beee3c05fe5d6f8a4b0ff4c4f0f9d64005b41dabc1d8b54cbd1a55cb3e1ca62e5529034f38f1eee0ac9badd9238b2a87a80b820f68f7859452738730d528b2f121458f5c977bb8adfb19e1d35aa46b38faaa872cd92a9257f64582cbdc5b538e0307f99255b15968081d2a498bb093120e2d4e0f5efa7893cd4dc87c93fd2375a5e71a2be097037d42810b77834263f7f05fdca503e1d16415649728249339288e3ab360c178a9b9a3f623357fac9a8bf7e9cfe6cc043e1f3b676582a03d0053210119899b59396675de49a238fda3eef8f83514ed93c38870acfee186290d4412f85440850eac7d31ac248e75952f237425afadab892ffacb682490ca7a611b5deca6f1b2441a6f3bb6887d3add0c8c43b798acc22fa2a59c2a6401e0d70abf06544fd996ba7ad10dd29234d114f48af29ceaf0030a60b97bb3", "8aa27c5cff2fc0c8ca4b8d932cdb98c29719613ce4fb7bd923cf05829a06dd36abab647a8ff67fba9f516a42435b892cce21a5a776bbae2b3de83320e4d8585e8c74248f29c6949a4b2141cb7f600c37075e494bb9e3fd9ba822cfa4bd50b20e00f62f70f73b173f0ff99cd93275145b429e56b39e53b11c8d8d78e6fb9a2d2296129da8b6eab6404181089f89487a2175845bb16a65c9112141ceb3aaf835ee8bbd0de9057238394bec105b2bcf7ca7788eab1b633f64c3f809c062d75216f1d84e2e99137372e901eb83b50c9b9a751166dea120c4a309b73fd3e930c3ae85ed5c70d15feec1c0a160dc6de5c4c892bc7932718e03f519c7091ceea02d2a6baf5da22c78e142eadcf94e02de033907688ab274df801232a2663542ac7d111904448f1c165842a8096db543b6d2bebfbbd80da6eeac1a4313c02e260fc3c5c927c619c585905cc31fe2242137b9ab68cd0003b0c3c5e3cef0602bfb9d04f36032e8833e268d7b7264b1f3511351386befd01ade51522348447917db23d06c08f7e46213bd97733e05cf5918f45b3702cd3898b12cf0c08cb52f13bb8235993adcb4c09f9cd3738cabf761aaaa19567114da44c87dd3bcbe11697f480dc152cfaf3cb8b9f8d0c61b77effc82e53294fad7b998cffdfe82e1df9c0b1ab0b7711498cf9be4ae775bdefe7b63119a4b3ac12362245a1bc4103e421ec42254571425", "-5fbc875fa93a5f673de480e05afae403ef4278e99a73059e077c2dd70e84288622ce914236de01528064420719a1beddb81a7b65e7ff1fa1fe97ae7c6c0a1be5b77423e1e069499ca8664ca41176b9657a7361f8274671c552e171a80bdbd1cedfd3a9af1510acd0de1287f5d8b6818a3d1f916c98aa6850e11af45b53d62c0ea0b7b6d5ff67f1e8a6141791f7c695f8af9207f4ae5594cf94b7a95301570cc6986071735b47a63e136fc75749de96e283def564c93c936bb7f374c61dfdc7400844741fd7004c053a1a7aa862eeb09ae35e1258b57b62aa666bedef84890e94686ecd4b463f936861ee5c84091be408f15ff1199c83b2f1bb064c08e5672807d7d332fc3a0fde5ab2634978daaac2127948a82f8bb8e877e4c6a3e7e5dae52c7e874d3f3d35c05ff024a06da295495d6e717e09a465f3ea3a4f30d468d00784a0b67a379de54923fa49bc75cbc397183e777f91a0320c90ec44d7e6345f2204643fa155129b12c84eaece2796686b8a336564ce4939d4a18b6db4291a4ecf5e6d9e3e2942bbadc313ba4240450b3edb7c69a04c76fe386b7fe5d9d84152d772222cc58970709f6ba84923640263db3b0fb430ccb14fb7679e442c4122397898755411c0684a97d12f01b5c1353ca6bbb0c3a20d0e8dc0d5b910b714f1ee2b15cb3244f25c47aa75515e33a8e085d3116ed2acbad8c6e25ea8d13ee80c62678e", .None}, + {.Add, "e2d3e31f8ffc8d725112b30e51e2ee565757827f305d23411da302675e9624233a5f698060a7a02e2f154dd4cf1444c72cf59b96f98bf66a614aa1a475e23e5b5ca72a3e79b9e1f83f8b91e5bcffe6ce8f43dfa7cc0dba84f0aa397a1ee36dd147526c2489d89fba2ef9e2add2b6849e853fc0dc68547ed94ca9ad4c0427276e131b2ba25f59c87384f8c017aeb5cf0cb71858e51362c8ee8e6ddb5d13ea4c8a581bd6dac66b5258c02a69b19c930e8b1e631c1af3b7b79043058baba905632830fdadf3b3ccd78b165d3adc25afe94e304ff3d3f697a5b0545ceaa037ab86a9e74f2edb505f4ecfe56ea8324e19ed82cd9048cb70d85ce36fc300dcbfc78a3548c241d6350d919f1a3159d74b3e77b6d6bb2a4a13ade05d592814e499ce38495a132b6ac00e66e0f39ef6a30081913aca88c34613a828f5d8dd02263633027288f36b81855c9a82a58abd2616a3b83f91e928eabd8aae33b7953961abe891fdd217df954fdb0d04ae17f243c5d72c33c7cd1d875b853627776772c1ed0d9757dd75514266dd082e97741964095b79893b82c70d437c2c64662c5de8e4e54d110a894bb67527aa6fee5143e93ba5ff1379ee6967483a0079a9cf4fda3db40e39608bc92ebde5185ee572202140f5f852bfd3f305a4ee41bf3e3c0feae5c0c59bec1ed60f3b08980626bfd553cc8d3349ea7927ed8c202d10422e781ba1059867", "f8d145ae805f8fb896c58fd78764ab8a157236088ee4a538e265d8aa9f6935cd14f6ca739f105421f83ab673ced49944c7216806b633866bcb5aff32285ea4516212e943fbd7a988562a4cc261fb2d985a76a8ec769ce295ea7aaf6baaef45a0af2e16e64524f873f09e042ad02867668b375beec287e78c0df59d4c77a1d17c450b7d449ed82a3c0cf74d8221f9ceacc471e45777cf5c99e686ef8f7e57f433464a0d2d8d9933e111986a772fd62f384131c7eb88cc8786cf4be536fb06cded1702fd7dcde98f6c216812542b6d8b7eb7f0c46efe4bcaf6656c46f78a00a8a9bf971b93c8ee26d2ed91ee822e67061e198597d2284fd43efa5556bc29ab9a79f05f09ca428bacf87b70a74fd02cb1d0f85b33b47ea98e4fba9d8f77ef4fb755b32fb4dd66d5efe6ac3fed2abd7ade25ddc1c8ff7cc7ab056c9b82a2f4f460136c58e2bc674afa4b17ad3c8f1adbb47f989ab6d74ecf2f823a965eb2c460ec22d345bb51f1bc08e92182bcc8c144654197dd596460e1b97b6bdea9bd3d723858212c2c904016cf9ad83b2acfc332ac32bd3c84dac0d20ef6029e49cf2726695fe39f2c6ecd30b7473bf7f3d38b8eb4eb2209867d0a701d163b82dcd88f46b582031014d8969732953bcafd1d45cc457bbc5b528c107be1873fb9b0451f4c2b95e9fdfa073280cd69a550ee7478af9c2864055d94617f9e0fc32452daf11217cd", "1dba528ce105c1d2ae7d842e5d94799e06cc9b887bf41c87a0008db11fdff59f04f5633f3ffb7f450275004489de8de0bf417039dafbf7cd62ca5a0d69e40e2acbeba138275918b8095b5dea81efb1466e9ba889442aa9d1adb24e8e5c9d2b371f680830acefd982e1f97e6d8a2deec0510771ccb2adc66655a9f4a987bc8f8ea5826a8e6fe31f2af91f00d99d0af9db97b8a3d3c8b32258874f4caec924240bd9e65e40854048639d1c2d428cc693dc35f94e4067c843f17125170e2a40c31154800ab7181b666f737c54d30511d74cce840b842f4e370a6b9c93197c1ac2f53a6e64a6f194d75a2d30096b47c80f3a0e715e09d992831226a185798e97324af39214ba077993e9795a201271b6b2987cf165dfe92576ead13c5a45c891def9f0d42e04826e456c79fdee3cdbdfc6f60a84a8c45906fd3fb457884c92b276285f54c4e3deca794cdbd37f9b5317f6cbf2a83dfc20c59ddb5f22b981470497e20a55d9ae7419715edcf9aaf0c871b91755faa76ebbc66efa2e3461c7f2a7fcfaffea17dd2a6f3d7c96faf4433cc8e25bbf8bf4be8044e3b5a68caa7b80c0bb670ee287825425861b72a4937bcc734b3fe9bf7efe452aa1d8fe5522cb2ccfac3bb639bde07547c4af4213d1d3e86c23dce7c2f4591b56a23467df5c030050cf131d61cd0166d89656fcc10c3c8453ccf724e7e8581ed9fcb200552caf69217b034", .None}, + {.Add, "5b39993dbcc14be9a36918b4bf677d7f3aee1f8c54c093074355ed04e76d1206241b28466ff2b248f23460c86ebc50f16501f1a6d55f173eb7cf6f068941e3b1108dbd677b1a84025e9c9061fad4bd4b821b08f6509459ebf773b27b81caa313678be22912f3a79a387db79ddbf689cd0a7c15f1100e206f2f962a11531b6b7e88d09cef51b0f9552ea6e7c6e75c3ceab493300101a091fb2857bac7c0bf99a3bb64e2da8a5d9005328ded8788595d185c16fb7db5400bf0b656af8498516b6369a61a3fe65c22d310bf3c1b40a8bf2e9fe45527e84b67305b8ee17d5eb217606630bdbcf0d0726ea55fef31f96e3c71b58743e0042da1fe8e1e923d3b38e4f4bc66da55bd4472c4be5bae678b2456418470d5fb64a1d56e3a7abea9fc40836b8989a541b6643fc448d827fc1810e116e8cdf4f0388a57a95e160cc3dbf10cc1506ac7d84748383aae600ecd9e35339007a0482c35cbc2369354471454b3a9dada4223f03d0ac9ec7e7dad8179ce8bb35090f407afd9a37d49087e9bf762d208d42d65ed7847a7fcd76cd938c949ed158d2bb1eea3d687ba93bfc123a95f7d9c2de2dbc4a9824770da2005987cb1b4fdabb147011b51035b159f9b49b1272f9bf7a2d2ac7c247ec76c1c580025eb647719ee2859cd44df86440a01d7f29828b9846e063a8ec792b8848403451726edce431d80cc947fdce978e60c0db3495456", "87b86efd52e81fd9e53749122387aeedca091115d7b6e6f99dc41c3d53cf2c70ea444516d2a32d3ae04d81a9fa1c1f78bc029ae7670d0db657f9643ee2102b4470d4ffccd9198a08efb024421b78398c3456c16ab9a12bfdc00f79a91c0aaf08f6bbda34e8f5d003243c6f10bcf8fe87702caae141c92374f6b2b4163480e2618a633f3f000d7955b29ca3662ca34365f6717110c1998b1474bd1fd1234d9f6d86ea21e32430b63a6fa6e686dca6399f3678ed04b5e16989f5458b66b1f6786d0acea531cd91c414c78d664c696e65b43ecf746c0bac4e06c20bd129b00a64c5857728e4f4cd535856a630fca7d413e737bc4b1410e16cd674d961115e7d20c7847adf6fc37b0adea3958fcb616fcfad3c8c4cc2e96dba1fbf3e221482f737354aaaacbfb8a593d6d6788f90bf15b5464a4aa7ad716cf31ec45ffbdbbde6e852064a5cec6367e7ee3b2e25d6b2f74d7ca0f43c027730d3d27aa704823f04b41524265f5a750dcd085a2e2fb9f4d2c20752e0c5ec45fd924f1ad7f04d8a68183fc06d7295450a94ce9f9fed68db29c07e277768592553de744eb96ec93d2768af652e1bedfea2160f88d9911ceda392ba0e9b82afde580ecd28de42838b521f9cb486a3d49549bbc68fa58d7d07a8e84fca5321bc8dfbcf7494499f49e509d364b22aa14d4133d1ad65c04973cd9429ee2d932a122be9a6a1160d60578d52c43e", "e2f2083b0fa96bc388a061c6e2ef2c6d04f730a22c777a00e11a09423b3c3e770e5f6d5d4295df83d281e27268d8706a21048c8e3c6c24f50fc8d3456b520ef58162bd3454340e0b4e4cb4a4164cf6d7b671ca610a3585e9b7832c249dd5521c5e47bc5dfbe9779d5cba26ae98ef88547aa8c0d251d743e42648de27879c4de01333dc2e51be72aae1438b2d13ff8050ab04a111c33a1d0f9d14da98e40d3911424f04bdae8e463fa234d40e64ff96b7928fe8826b21757aab9c3aeb4a47e3d07474bf71b3ede6e7d84ca267aa1724e2deb3c993f3f7b5371d9ab2a70ebc7c25eba7e6a1e59dc5c6fc06202ea1425058ed438ef4150f0ed502f7f34e99b605bc40e1b9c580bf7da361f13e32ec9425eec0fd22be4e0f8f8df9b8e0be7f37baa0d43452016f09d39b1f50b78cd726965d33189c9da9f74ac82276089f99d7f51356b524c4aab02028e98e34a4512c810ca894842eacfc96090dfb4b9693b85deffe68834ab21896f4d8abdd3b6ea14dbaa371b9f3f5d735cc63e06ee981caea48949ad882bd523ccb770cc6a1a473ad93b4a31a47c92a662ee2792fece686e64b9310f7b2a8245d8062f996b56a5547b7ba4cc9b0f9a912283e7dddcd3c794f38ac297681116e3a8dfbc1e57d2d944cc6e4414a165b40aefad853a121d7a1fc1e3698a787cffb6465ea444cb8e4bb17bc70b0aadec069838a8ef36c65409c1894", .None}, + {.Add, "-6fe86391bfae7ec2fccf1721c62074ef635ec35c4fb5fe5199b790678b6cbc858d895ee6be739ec957514779d88563147881e081c0cca0ba129585268c681003c5c64f6619cddd217bd02da012e908378e4a2438500b32d92343f312447668755b01a39b790f6bd3267cd978bcf0c7089b49dc2757eb2a29e58b63f3315ab994747dfc16022948e62667967d86753e8357bed88752c6ac448943066cb614b1694332b4aa471e529b3bd8872f5aee664351a485b62bbf52692ba27e6e011340441455bb4c7912c476f5d2c6233e8b15ab525aabd7b1471cb9f79d80770228d3cf449c3c5d9d9ec2675b13bdc5e5a302115934b5d9c340dd24f9c4a14fe4091b49ba859f4a2dbea43d116ebe44354b9e9c66088d00909e1356802ccc61f599053eb7d95c6c33f073f8cc61be3cdc0bd23510d78adeaa058f2df0fb87dc1d25847ac93b39eb440aba9187d1e008b17e719782c0eb50c7ba32fb711eaa1f24c234f24affb2cd12cc2b17b99dc917c929ebc0fcad27bfc85dbb05012159681335840a487ebf2281520195194d46b85b226006d6374ccbf4bbdb700636d7fb9b66861e331f527759304a7da081ed1f654b154ecf323ad0bd89b86c850460e315c7fc1ec0b72f03eb86260f7843a1375785a6d152936f754276bf133c44f77051750c8538d6d4a3d515fb507f42d5024e19baf6a7b166b7a67dc16ae0f788706f05599d", "847d7aa4e7431ef071cf506a3d411847b9e8eb7fa2dda437025e16b86092da2bae7a6ddcf042c17e4e424170ca09bad5229f33599415218778df945f0a8eb35a2749c9466cc6cb51a343f4ba9df8f719fb9d0840f3fe082853465ef83dde0feeb1a16de214d7367a0bf09ba3c90919a5df7b967b7bc2167327cba56cb5c900bd3bc3a066890510aa31f57ca06224e475e3c0dc4b7f29ab78d58df2d4caf41ad505af53424ded45c315b3370b280f3357cb9f7a98f1571d5b91e6ba15f209e33478adab66f0b869b83e8fc51a28dfb6d4b2cc58e9e588e808d7efee64431b4cf8777ee9b0e021967acd084108c4ad4f2e5668540368658069be001e528a5c01fa5802b4c1edf427b3b49f17a1c5ee4dfa67f2a012c39a8e81cd05c1751b6c77ee43ae038223586fd04e7feaec95a44ec9ec23438d72f0847362abfed4ba47b94d70c2ff606bd366a1d60af3225b6232dbead95f029eec464d15fc30009dabb108b2a5ef12539e4dc83b9dc2d8510d622689e50a8a0a4f5822099822bf31f861da62718909fcbc64adef6b7556430f7239de802ab801e4922b21d3b838b0e6a970cb42dbf27f58a908e11acf5d5e10073fbdd55c8e845ad87b55c9861422fa74d6bb702491979f36b850d6ad3b1c765881d8a39ec1005f0d1f19bcf9d657b5f8b54f947992a08ed38ccb6f0007c9caeb0959687da40c07924c51d4e742a6b9f385", "149517132794a02d750039487720a358568a28235327a5e568a68650d5261da620f10ef631cf22b4f6f0f9f6f18457c0aa1d52d7d34880cd664a0f387e26a356618379e052f8ee302773c71a8b0feee26d52e408a3f2d54f30026be5f967a779569fca469bc7caa6e573c22b0c18529d4431ba5423d6ec4942404179846e4728c745a45086dbc7c40b8de622dbafa5f28c0203c42c62ff344c4aec6814df696bc27c9e9806cef327d9daafdbcd20cd1479faf4e2c597caf266443ba7f0f6a2f06457f01a77a5a54148bcfef6ea54a1296071ad123441cb4ee0526ded40f2792932e2ad534282d41371f48342df0a4d1cfd339e29a524a344c43b7d02a652e6b09d7d1577c0358376a330595d90a2af5e01ea131232fc7b2b4cd8f51325d372af8bd4a715ef67fbd7821e2cafb9987c94db4bb8aec8eaf54571b076f89d2234d2a787c57527c8ac104e391319a9e3c144681873b1d7321351a4dd85e178e97c1667a63c4540d222b081fff9c087e376658d37e2ca41f19d1d0876c9571ec2ddd019f2c9e77b6a6318d61e2e9de7ed12330848ddec0d28b6bb1b9ce03d158023529823897b26285e8b4098e23df8c4f1f0eea321bdc6d1200ed0c525310d3278b7fab8f58dac1910a8d8930c03c4f0b1b086102f4bbde84e0bdd7802660640ec3016bda4eecb78d83c4c2c2b057bb13012b1b716ec6589d0e170dd5ed237b499e8", .None}, + {.Add, "3c0bde6e000598876134f2460b09b2c3bee498553863a9bce6275f1993356b643911f3d2b810b47b547f537ca76cebe316e93d35c61a53a01dd5f1df93e7cbfb7a1aa69308e45654a4edd5e285ed1796bf7d08f73a0e2fbc90cfe37cd504ef1625fd54836865cc67f221c064d5b0ae1b376c1e531c4a4960dcf3960acdedd4eeeaeee9bbdc19cf34cf5594e1fe7b27beac3e948632f88544076877964d4f5522ea764385f49da9cb9456d403d98d8cdbcd10c03fde65459996799ae89a4c332e48a5fd23f43630ff30837ada4c37bbe8bb551596c50472f7c0e5522ac25a77e3bd31b79894c55a0e36ccb51c924636f8bab7f78bb4d7ca56f42da349861c4b8d9d95304ccb01b2cd9d3390bbaba94f0042d6a94015b489059e1d71a18cb06f86d7aacccb29a5082934d0d0a002914bdeb542dd9284d029aa5f04095d0a15b1d28ac420cf80496bc7e6dd87204e0774e067c5362b3ff343d553091830f0cd85554e6feeba57134ac3dfcc07ee56ff4299a1af27490311dc7d586d743fc6fce806d499c21844c025b8aaf638d2c74b751836cea5bf131a985c7f30e948fb7e9882c66fd8ff06e84a07cf861fd1820d47a02fed9346171224a0a15e03bbbd4a9a3e315ece1bcb1345bc023dc78e48f3ef274086209c2edc319e725d108c12fd9171dc44555dca3d412c0957b35cd2518267612cdfd91cd054c82df6fec2305cbb3e", "7c1eaaecd09330ebf0d2651ef300fa2b0d24624e03f20bc6bb80ddc84859bbc2d786e1a20990b8d586fdbef3d7f1f16d30cd2ac953f7398af2a95bc7d3cd0e2b216c10badc1a6530039708514debb37cc2bd57f40e46ca246002b0841e4061367c78e5c5ad52337bff459024c4a850be7f49f1216082ed620a53f04a9a5f791e2cfea460ec5bb71379022a8c42cfeb84025bf6ce34537ee0b387924654a16dab0333ce05029a0c0de6ba02aabbbbe0cd0e986db9c52cf4c78b8284ea2c4454a2ef1f877666c8a2f2a695552085bd6b3d90bd8f5264592605f6e7df72aa7204ae429294a8d8155bee553b04fde21761c9aa5395a3903f5e41b6766bb655d75557839a0b0d31b15ae16c7fe59d36cd6b1d9d6c36d2c9ba42f70110f3229f47feba841c22e2465b48f3dcc404c6c5ca8c2ae0b16d22dc3d9860a69ef524621c00f516f759242d0056685ba7698a9fb6fa66ca37780c6a7a258d04853ffcef57d8e237ca0cadd7f0b504a87f0ddbbab480b2e698ec92bb160bab136f1633c182e8fd09da0ac557c2cb88ea38631d8b79503200aa89c15fd859ad241e65d2766fbd45715a6faaf4bccd054a62f8f6b351a18f7488ef55d7229304495323539b8eccb7be1143448aa0ac570c2f362023c8618d35926568c03a0413b9b0dd92fa9a91ea8ca0a84a31373fcc1d39558b3ad69efc2f532d7e1d1e019ef88ecb1f76f02e1", "43cdc91ccd0ecb9620421897fa39c2666fb6de7a18a2ca7951df6cf617bb0720668a61ecd8a9c008acef2f6be4ec0af9e9f60fe25b59c738cd00879c11249cde2c31679eb6a5fca7a52746679acbd2ce8ba8de767af29c5ed6d00e8516e8f5298dc4e2dfc33aef9fb216196721fb33271f60bd6532527836fd98d50f7793cc80cdbed401eadf8aa606e5b78ac2a82676ec6453f3163dbd3212a0f0bab2996bfd9aa9806644c74a8c72c2742e85494ae89dfa471b7ab814e60f31c3373d1078787797f59b5aa2bb2e5aecd02c5493929c9460ee8beb4a05582053d021ed01982ea15ae0e32246afcd1c20656c7067ad15555d30e5eddbc03b0f950a04eb79c0e315ced0fd9e1cc87bb3fb8f157f1625b21cad6cad42502d350e2e80d3b6a4ef727fec8ef94e0abcb8729d10ec6eedf4a1634df464b2940330696df8af503771e1dc339661c319712e6c97fdb8f802e486d468adac069ae62e23516c30bfc302e371ec8f85349256142a53f8cc12aa8aa4d018b6122ec33d3809a465a303151696a53762c49a3c52713999bf04a0030a1b56d94e5b29181df75172cfa622e594571d857ff9b63416d8242c4f60ed4261b92736223b74844dd0e5f335f0f7038709ad3fe25013bd50817300baf04b30754013df46f2badfd1dfadf81e6542a73a90850e5fe26d50b528cb2b48b585feec57242212b0fea234e21d7feb7427cbbe1f", .None}, + {.Add, "4c7ab89fca4650a1cd0ada6eda760fc785da25448fe7749b810874c123e2b973e6a64c0b11d311bfc1ab6350cf957a0de1b2a01b29141d8ff187c7bcf6b99d85e539c4ec6d794fc9261c4ff99ab247bb9985168a84d5731d9f82e64bd0ad61ca422de2a299508d1bf8283fa20832e968b876db996850b0a0dc37e47723f59cefdf385232a2faf6f89d96552c4c3dfe352f5ec194b1321703fa8eea3af4a15a226ff34cdb55435633846b04828c84fa3f99236b229fcb85d9ae2cf1704feb98e15afe01271c1d5db36f5291b8d15de90064a86c44c9c04d540c29b00430ce446f7a08c3bb36de78d2af5b0634358aa7f184be10b25af91402069e8ce66d1fc0d345adf272d6fc3ad40f7bd096500edc28ec43fc0817773316159750d0cd67c610912f979eceb3b52d26c500f0833c56e1435e02b68e76e4f4ddfdecff835929d509a984e4346f8d7e5644959e387f12b36a9b8d60c99c51fcef85fa398d5edf0a247cde694618612652a632a2dd6c66269121bee65e662a68f81beb4ee58173eaa59f6716d8c1a11814e9bce96f5c8343f08c4e751b68bb0fef3adf78eba56f60b859e05d204969d05661e2c19a277b767489d8564a1496fa2eb1d13b388596d800a38110d16182a6907e85971babf906645be27742f987d417c193d5e14fbccd1fddf55c1bc2c0829fd8f513dbb88dddd3fa185ce5ffd76f6105a14c6b0d8558", "d52b8be41be4ef9fc00e40264036a2a41be4131e4bb3ce18a28601b7c947014114e602ccef4512de27cd0d912e53f64a070700935f5206718ae2f19ccd93a6ff63d360334237ff78a8609ffee29e1a0632194c236a760a2a1a2cab65dd75cc74864ddcbe5a8f21a5dd5ee7e8655169e23195f1ae22a9d02c1abe402eff3d3c4f4eb873c205ea9bc1269c3d0c4b599262eb66acd5700fe2ac35af573080fedcac3a01f3da627f6f9d1adc862e020b2fcc1e9000df24132a524a61537ce075172eef16906443e84dbd2b428402e0973e6685809cfb23f5724e45c871eefe7dfb2ec4524eea23d7ae3ab31e723e3e41758b3923000f505e5273bd83a6ed68cbf3066b8b873d6d1117f6e791b9e3ecc1b4e1d1ad01472b9d38cbbb3f0fc47f229c53c0ed8c639ec7d1401c681fe077e522f34905082a85734173851d2dcf78892cedf70127297ae3da6fb98c89e8520b3a118fc33327457bcb0e354aec86d12062b0e35d134402aa50b2e59afce4a2b17fea0c31c60468ed80a4f14c708593661dbbe00b7a1a8236fec2a028172da96003d02c4aed011b51651c23d9e534e776365950d2ef14b5ac2c30a52b10c37b16edb2387d61741a2a99a1302549fb9d76d8ac461201dba7e9b6dc8cb08bc30d991b597730c456a577e7e48a57f6293f2795bfa863ce5799497260606b8942db541268e44f2dff9024c515ed615b85e9aea784", "121a64483e62b40418d191a951aacb26ba1be3862db9b42b4238e7678ed29bab4fb8c4ed80118249de97870e1fde97057e8b9a0ae886624017c6ab959c44d4485490d251fafb14f41ce7ceff87d5061c1cb9e62adef4b7d47b9af91b1ae232e3ec87bbf60f3dfaec1d587278a6d84534aea0ccd478afa80ccf6f624a62332d93f2df0c5f4a8e592b9c4329238979790981ac56e6a2141f9b0303e416b75a036cea9f540b5b7c2c5d09f478ab08e902a0bb7b36c01c3deb02bf88e44ed3060b0104a14918b6005ab709a9515bbb1f52766ea29093fedb5bfa251f221f32f4c3f9e3e5b12a55ab6270d6279787273cc1d7cbde110c1ab576675c42233d3d5ebb3d9b13979b0440d52caf70d8a7a3cd0910abdf0fd4f43146be1d0d660954c8a6264521d24026d7b866d432d20d0fb2179d48c630ae113ea2668631b1acefbe256c300aaac0daf5367ee0fd11f868a8a4cc4fa5ec0880f181d0b24d0e6c05e7f41bb07d9f1ad48c2b1d938412f87801de6109d5384eac753ab0de9685bd478e791a685aae1315af89fdab511d41718bc87141cd73b7636ba202c1314c4add31ba5ba092ccf71d5f59600fb8cf385153e6928ad0739ca643f309b5ed71b36d5fc6f8446b582ec794b39831d2f115a2945145fdb8ca6cde8716fb8a21989ff2077528cc841c3b3b50c32e300447e56b70ca046b849465c76249c854e66fcd254bc2cdc", .None}, + {.Add, "9180ed658f45aefc914c814467dd2d2052a928245c7147b790127327659a366b5594f3b4defbb50934b5a1ec295496f110da223c555f996ef27c5f46081fa80993b8da9f6f8838c6fe013f3cf76619af740b3eadde7df314db48a6ebc4f1950b173b5bfe8b0789fbfda8848a783222c5cd90650de33e39499914e2193e8560e91a91126819e5609e4ab4a7be37852690b98264602a842f3815dcfed38f13e89a72c85e0b179c1c349e9339c5290941d2ab9403184c54e2c0c4ae9371fb1807463547743f458fac8e6a5ea613c4e5efa41a4e9c28aee343093c9fb002cdbc246083216238eae4172d3ae4f5305c05c7f6af203dc30b04f469345fc5b5da3cc9d4862f83bf7ef6cea900484928dd061fd7e1f259548082b4454839f69e6b6e5535d827e79ab57c628e7d546a8327eea781a5a98a5aa50223dc75ead4677d68bc70f39c6ae1e7056ff59e3e18b73b8813c37be3da8efdea436aa0471e459771f1f29ae91e55e88e743d8d91fea64579a5cb9d123907fb5d80e5cc04f7741ee07cee368afbcc738829622113234d8d066778dece94d7924aeffcb9d4abaa382f35a069989c9d2ddb03491df76f867fcf6c4d84c55e6c4b248c8af361e3d0b74f9964f09c5ecb3d6788de9331b4bbc063197a830ea3ad14f517f29860e4d5534bf9b53577dc6a47b8d37a769c9225eb8c896b021a789167189853256890784baf1142", "81461d4de1f983adf4cdd01293c51e38a248a681b996f0109d648a525dd755bc41f759e65036dfff04f1c2851a4d514cd265a4b10e857801a49bf350b966edbd890f05465aec0542086073e31875bc9529c08b159c7211238ec3aedc83291cc08eb682fbed15a55ff256cfc49e4f60e75d11823571659f316158505373de5357159161b8a7d4f19a0ab26c9b827f1ef4ae6d867882d3df27291122b47bbf18b8613677184ed7eb7da1ef352c08ea75926eed838adcabc9b8905c9832abcaa68e872258aa7a0c36722a45e60cd777593968bf271a56d5f8a4244ac29115ca196a48f78c2e96b1c620727a141e1261257dd3d142db23039fc720a5d5f02ec190059e4c52481880e874990128a09ee2cd3b82dff9246406ab58e9c1c01a9df233c253546977cf08b6f8b18a00fe91e3df12e2141c1f6a1e189a954c54cfa4c60223bd376f2f8b203f9ae3849db9539b60d697b9f976dd5fe4f501d149c9c3b2da635e349ffd16e31d9de2b824fd65eaad9efe70a0120bc2619bc3891723cb232e28a4ffe257a6de5570349cd910b5cd11f757ca4ea05830673c012c9413c38ee0f9427da3e8b80e573e1fa4bb7a4a3ed0144c2b568c9fd6748980b86e9599fb25275dcc25e17722572c2ed2eea3d4a85de10b67a9865295185e6a4f69b94b5257736b7303d2e638c720be3da708916512db86eb358bf4f6c6144f476e9c7984443d", "112c70ab3713f32aa861a5156fba24b58f4f1cea6160837c82d76fd79c3718c27978c4d9b2f32950839a7647143a1e83de33fc6ed63e5117097185296c18695c71cc7dfe5ca743e090661b3200fdbd6449dcbc9c37af004386a0c55c8481ab1cba5f1defa781d2f5befff544f168183ad2aa1e74354a3d87afa6d326cb263b44030227420c1ba523855671459ba04458567efead8ad580e5f3eee21880ad30152d3fed523667407b240826ef131f3b7651a8186a32900ac79550b2ba4a6e2add4bc69cce9bf9be30094a48c209c5d48dd830dc34305b93bad60ea7293e3863dcacc18ee678195dd4dad5f094e6e66ed7482f1809e2e08943055059ba608fe59da247bd6079777b71d994971c97be8ed1364d25278e4895f9e31fbb6b9096088f82b7c5112848519872ede6b81b9d2869487bda67a0f203c770b372937222ebe94b0d3da117225af9081c2b6708f23749a139dd405db4a285fa218680f5b24cc55f91dbe52ff7191db704a23a3ab64536a9b82d91a071fe2818f8e0e97ea03ab16db8ade241a667ed255affc5e42d379703698e377ea7b5738bb013fbdfbbe1699ac164085e5e95a873d9c2b00ca0e3c61d0f0b4f8eafb0114741a5266514abe8c4e6884acb489e00ac204a35f950b775b8e764d33678a305102b04e8e9e9e5128a0eae03d2df19a9b34da392e7cf19c468905ae1d5c0f5e6774afff14c533557f", .None}, + {.Add, "cf3bc8ed0fa52533dedeaecac0cf7f9e0129fe87c3920303055be680a4edd7befc3913582c2b5e7eeaad13ea62ae2c122a4d007d320ed0643957394518c52900d2fc7076ba083c04180396461baf1e8c46d717fc5807bdb147d5fed85aec5dc676c24c5e335713035d303428a2da58b2cc94fea203a250770bfd913071271916f4ba99f30cf612feafa48d71ce9306468b92e14f153af3a4339741f90e4e7343616b7f05819dd286e52e7de775e13d4a3b52d82726f6ad51bd2243b007af9a763213080e9068633e1cdee84b09b083ae7b427df690ce278fca163bc15e1c07a6d915d7f5815091dfef8744e638b7a4cd2b57e14053c4170797a3e6bcc872906106a2d027041185344694fcea03dc65209e8bee96dd3da9d2f1ab2a169f4116b6d71b917f2613acf9b38a39d5285105d430f66f8b1c98d2f988a37557622d49d3ad0ca3f4d9d338e801e0f60b7ae2130d8db49b6d0802269b5557f19c6c05dbfe1c62d5b12a4dc19bdbf17438e706bee2306f7dea0f23439eeca8e66b12cac05a5da4d56e030c1f1f16fbd0b014968ef5a59f42924df875c24dbb999e453a14fae3452a0a703a4fb02424e542bb0d405eb0de4ceeb6e9a8d74f89b4dd0469ba07ee18238828fb4f1c78e467cc9933b4149d22694f29cc05d8c959c6cca17f2812080046035ec101729aa8121d72fe9e411ac4c1f2c99a09e7a49424aebc3f4602", "5aef8b79a4ded6476611f269305528e182b7cea456162aef8e271c53f4d8599a7573c9820d462fc9ed12fa0c199d439ac4fd5b8a3171be2a890ee469240ce5f9f87bb78b7b95d324a0fc460ac1c7a63c7ff350d361f0c439f65be2eab0faa8353439afa69c0a7b58fd7c8af5cf3e65382453fcecd8c093efe68de68d02dc8f8493f76140373f8fbe77086a80efc1506554499402f3ed7e56aa545fcaff880c6e47e494f080a70f039008d798c1ff0308cf4a0316ede3d1b3a17471db662fa3b53dd6aa8d194feb927d728e447a9330301658a6894aca30ef7234d8ce6a66bdfd57d529ed893e0803375cd670921264b8040c0c630f83f79ef4ce926f3d7e7e3a0f4e5a051e5a98467149ccf437bd6f728821cb83e9a8a528438c0ae519a274e05d9f1d2fbbc55c049aff97a2a6f85d3cd9df3ecd47f66ad9d2d290a334e820a61fe695e1aea5749dc877a052a4dcb01fe0516e986f1c2607c37c0bd03f3857b03958d56af7677c9310a42c1507de002a32f44967e0d4ee9ee92a012994bc1e28d0c2026c6d581325fa518a42e1896881a90b15e94edfcaa0515cc01a6506d5197c4d2548e8365a19c4e3a249e1b5e4bef9b7ee8d40e942ca30f987babda5bef43b299682db3d5da48cf8510c1aaa70bd943deed6f7f30fc2a170213a23edac02aeb2f31fd97baea6e3a312b089eda69d05c9ca26230ac30a4ef9c0b56eb4cae3", "12a2b5466b483fb7b44f0a133f124a87f83e1cd2c19a82df2938302d499c6315971acdcda39718e48d7c00df67c4b6facef4a5c0763808e8ec2661dae3cd20efacb782802359e0f28b8ffdc50dd76c4c8c6ca68cfb9f881eb3e31e1c30be705fbaafbfc04cf618e5c5aacbf1e7218bdeaf0e8fb8edc62e466f28b77bd7403a89b88b1fb334435a2bd26acf7f2be5456abdfdc7552092871faddeba1c40dd67fb1a95013f60244e18a7537558037e040530a9cdb3e14da7f055e96b58b6ddf3e2b6fe9b29ba9b84ed09a51768f8443b3de919b247fdb98587f3c4b148fc882c5a430eb01e30a8e99e326e41b56caca09852f63eda363480ea68c72792c05f10e9b15f12a2c226c1d7ab7dec9de3b99d49326adba1ac6e64efb353734fbb8e38b9734baaeaee1d908fe4e89d177cf4963110ad5ae58648f3dd35b7605fa97156a79ccf339d68878ad85ca58965e1fbec32d6e060a05771e4ca318d3fd6cab3e33ae55bbab1c21b53e2eec95a04deee4bf0c6363c751eff8323dd5d2e794a786de832e66d7da70643245114d5af2f61ff7774eaa587b9cd840629f1859b8aa40ea145f924f535870a9c9e908878c9cc3251daa963b7bf7d2eba180833c97c20f78fc2941ba0b0438acc105dcb8d8b3de24d23160582621bf159b6ac9e806c56cd414b6b33923383cb0197e4b24cdfcec44de208e8c18eca4ccf1f38de5642af410e5", .None}, + {.Add, "-6e752404d704c93ba8895b8faa357f90728cf101ff1f82ff43f797e90007b6ace26c74dc0586a002d2d01345c006688d1a247c91a40225b39631b272fdfadf0c4d8cacd9c7c3dfcf7d4822f537ef412331f20fc968bd0d44886329f4424dbebcdaeb90d7bd5d9c4f2221abca0f5d2ea23f72dab79970ecd9a06bff789f55a791cc53fc80fb453f446812a28eccf4111d21a62c70bebb635cf07a6b0c1c9f0873b26d0744073337641bbdc09c5d602875abd5710ea0ed9ede9128d0e297e943f34db2dfa371b2096a03ee0eb31c1158a2a84e09c0280926091db8572ecc436b43d81e790b849c96b3c92b2b3cc2f04defbac78db030b3c1977fd6b5a279fdddb975ad38ed0cf00e165581d46a47d4eb1274a51e8e783e255d20a98b9f35681e82379774615ee62bf8521596116bb4f8a64c30608ad852985902be1a94aef00addce0a164832ad654733cc3ebc283dd90845009f2e2844c18aae32fa7c25fb88fc359aa3ba0a1546d1e8f93536d6c1f9f4dd4514d835a394f3d0ed38c22c58b59c23c22456db6422e4fbb1b3c857382405d23e62be3a4de735781f6ab8f394f7700956f1231caea7e3f0cd22f69168f83c3a22f16be7916d96da42412656b54c269cc05d7d8a22cd36e550ef6abd525a419595b65181a3c944de28a1777516fe714a599dce371a04ea77b8cd54d7f4ebc76ff0010e64600e25af12afdd099c2ea6", "13e4db1d2a07fbced26259e99ed0b98562f74cf18e63ecc04f3edbaa0cc1fd37be8eae18f82520afd103959bd8ddfa6be569b8621d2b0a15c648be257f0b09cf6e2527a193ce803a87fe71490289d8517d530342cac347ad35d5a8a232d142dbfcdef85a858c220a0a318802737a42bf4335a2528cff7239c873cd672fb767b4c155a53aed1290d5b0a69680519ed7709b743f012092316421db506e0b48e55c75a69482d8743ac0fc7a4f8bee86f03b982208ba55075a7d29d19769ca20ce06d65b07d87d1ab48bf4591692f8db4bfc07eed1dcfad611245a52de3a83bcac270235f2597dfa600ef7fb83bf90fb00e15f350e0925b3cceca083e8333deff79bf303aecb9f344aa65442662af99b9c7d2c8988da5f360144a6d1217b3d0d60bda8c43be47118d7a7ea1a95e206dc2560d41b4903af67ebca4cefffc633fbd58d81444ae33cb4153580b5ecb0aba36d1245b0151e70c64f73b29a5375a92917ccdf0aedb1cd12618b77a77a69003f8d4bb43a1e872a5454aae0679598c53adc400e600ff142849b81797183a5dc23e62d1cb65a76bf50eb39c32db0251b17b31d94afd81c690956fb48bd5260419736f5842f06e8114b9a91fed5c41789c36913ae6982e2f0daed3f1b9dc78bfdff4846b414eec7613db216655c0d6c1331177abaad40d936d11cd0994e99ff34344b0bb3fb10d695567ce84c1c4445b4869ef7", "-5a9048e7acfccd6cd62701a60b64c60b0f95a41070bb963ef4b8bc3ef345b97523ddc6c30d617f5301cc7da9e7286e2134bac42f86d71b9dcfe8f44d7eefd53cdf67853833f55f94f549b1ac356568d1b49f0c869df9c597528d81520f7c7be0de0c987d37d17a4517f023c79be2ebe2fc3d38650c717a9fd7f832116f9e3fdd0afe57460e32ae6eb76c0c0e7b5539ac8631ed6f9e2931f8ce9f1a9e115623173cc672c12ebefca31f4371106ed9383a13b368544be6446167573978cdc875ec7757d7caf49754de0f94f82023360ca6a05f37e32d3314e4c36578f44886bf1cd5e886b206a236a4d12fa77d31f54d0e5b927fa70afff4aadf52cd6f3c0de61d82a98a216dbbc370013f6e3f4e394e95481b95b41908241879d86a23f85abdc48ed3387cedcd545067fb002f64d8d3457815178728eaac8eb5ce1ace7af435504cc5cb64f5f95011b316520b7c9a6bf5ff508a0fb77e7216fb98a7067cd2712f568fb6083d02e5467151bacdd6826ca9290af6510b4f4048f085a329671dd95c1562146598df8763824030227b143dd8b58808477afcfbfbb4f1ba93d87d445274a71906b3a550e8a80fd0964fd1c146b5f3ea83d645d304db6c7d0eccf1e312ee56da9a9947dff7c9b327debf5311fae180c78a2066172e78cc940b61e5e6f68fac5cf50048e819de6a3355a3c0a0bbbbf4f037cf09913d62f66b9755158faf", .None}, + {.Add, "54c3de28a345dde281ea9b0b38c8839e6d604f00c825aa79d3a7bea73e9ccd4fa32f1d37b7c7efd8fb9ee4a7f2ca2ae0875adb7d2e9a7f55b2de43e8c1cf7a85172e3302948c1af11b9e35fbbed067b8fc2d249b55ea7de48496419046c0937f3a6c32ece276bde7148d9a8d0f7e3d9fcdacd681f4a85769cf508b423307812ffe2d3207c5763a9fdba8eb5135498d7bd034ebb41c63a1e665f5addfa0d35e6f986075958c43efc1a7bcca6bdb6bd2ce95bf19055d058e7c0690541775113335cfc473e5cefa1dce660bbdbc642b93a44864caaec42e351ba2e207a7b455c519a008aa623b9abf6890a30d2733bbaeead18f9841cfe86fa0056db2f38b54327e4f3f46c47aa05fa6de94a3601488197c4b0326c36cf6c6aaf1d8f50b801bb36d5398e1a6d3306148a0bc2196f1568c30f58bfcd194ea2d14e41e38369c4711069f42d82bc0a9f7c7ad2239b67f818940a0f31b2092962f38ae8cb7d7de0beafdb4ad4f8216aefa6e536eb831eabdfd3f29b6d3b8a5098c9749cf499977266932e935b93ff1adddeede1c473f049e9b286cb1c11490871a6358cbe8b91a35278e952a33e7d77873d7342ef01003bc1f46220308233577bea8206e272e9514984b7b3966c2748168d6629e23f97186e4831fcb7e82408e08d3fceaf189de803bd30a8ab5652556637c3a715a7ee56d90efddf91c20cd529dd15e966c1601c0946c", "5609e2c4e7ab2796a26bc4199e158fb856e8b19f0e6effed6b0f3c6c29ba24a37a73d568933e1f2bf6092a116eed44e695b17cbdfa70acb0f91201154952a52f9a66dd680968350bea282108045c3b82ff276f07f8f465005640f725e15077cad2e06a0287eaacddad6706ce92bbc30d865e601e53a0aa9b5f67498515a0d7e71b324254e7b8e1f27f93e7606b1b780c23dfa056ee97fa06af106e196513121769732d4f25a013d0917e27cd1bf9ee58e969e1765d8decfc260e8bdaf4d6b545c56a9834b25549aba4757761f426f5d55bc539b3d4810fd60741d0256809a66eb3fb28cc96a4aab288054f323f3b3e61e5fa7e217f2f59b46cbf6166a395f99ca8b5b591d3e15e337b712c228d1223fec15ffa6dc313c44ca67aea11ebb7887fe44e4656b8ac3a122e3f1a266b9292e383d42ea7211b6c0e1e8ffe4d35f9c4764bc338601cb9b14cefb6003f21e719f8f8e438dd56e0f234ac8a2ff37fa7626bc9b91293eaae795314eeaec7ff4fc9da9e8f8f82c18d739f978dcdb3043f1793a0c37d04d1db02ee1a6461b151efdc4670e7a6e28084984adde39f8708e936da1af3b42d92763a00c7d012bad3c73491497df62333ce98d35d5debf67aca6102355e8cfe80226916f877b35ab6492f11334f65b1634a3e63e6ce0c8b4a9a312d4f1ec167576b3efffc2c8985eac248e520f46515d371e8ea49dcb262a2e64133", "aacdc0ed8af1057924565f24d6de1356c449009fd694aa673eb6fb136856f1f31da2f2a04b060f04f1a80eb961b76fc71d0c583b290b2c06abf044fe0b221fb4b195106a9df44ffd05c65703c32ca33bfb5493a34edee2e4dad738b628110b4a0d4c9cef6a616ac4c1f4a15ba23a00ad540b36a0484902052eb7d4c748a85917195f745cad2f1c925b3cd2b1a0650587f4148c0b0afb9bed15061bf905e6708701d3a2e4b1e40392393af238f765c1277f28fa7bba937b782c9edff269e7e87b952f0c1a814f677a0a81351e58528979a42a046298af44f1aa23d7cd1c5f6b885403d32ed23f6a1b18a85c5972f6ed4cb78a16634f17c954722d145a2eea2c1af7f4fc564e81bdda5a05cf82a19a3d7b0c632131300a8af79853df1d6bd33bed37e727fd8bdc9b5acefb3bbd5ce91f1479602b78b605992302ae3683d240d57ceb06108bdd63a9149cd839f5a168a33999d753fde977216d5b16e7cb5db34d697e666216015d73c1685d66f9ea0dc719c846633b66970036e15d174c7b6580c689f93644c388e0dcf880a8f0568e776edd9967f7110bb2ae36af8840231e5e68b01de81569eeadd7fbff02cad78353d76b80fe466946577b7dcc13250fdef94db097f3c0f4a3d1ed5b15d75427d01394531ae433a3d84737e3b8fe15291a6d0059a976cc7cc1a27c369de404d02fd9d4feed8136a0c486bba8731e78a4a6d59f", .None}, + {.Add, "-2d953c698297c1b7d945678873e8051f61d45ffdd76b9035e0f19ec18af8a07e3d273a22d44683c3eca58181561692e250651f9d4060b4a3ecd971046a3d8bc9d7f862a769afa8640706fce498c711dbc2ee104d72900712b7cf5b66e9240f42d17f87450b16f570a6d2580c3c75e4b1d65d9b5a972aacdfb8bb4a8d9cc7711c3128ae7e83890115e971acde571ad41b34076b204b77088a8982eb66be85655667daa07aab25f1dfd80ebac5f59996636abe7d758a86fd0ef97a24732c5ef5995a9481b6f68db8defbbeede4714df304db33e18f81daea343b5b1fe3dc1f10002a3a2c139ccfb776c108a7d6e5c11778a229adc75aee144a7a75ffb660744acb484f47c3a594cc1d371cc95e8501a80d7d97112c6b83d379380f0346b5b472436c77f33afda5fd47615f1eb3821e7a8f514adff8c21363904a8c173585d6c85beec7dfedda02741d36bf4039c6bd549b9b7d7bfd0f3e58825af766de1408d02afbcb7c51370326d9f06c28760aab008ae7058c316c00fcc40dba5f5149cf1abc84ca7f18695ccb105b4c1d08184dbf41d67333acc9aa21d616ad3abef7c75aa11fd37732c24e44a065070b93c8452cdc89077c04919593f0b76fa52625451e9145d69846ddc8f8a36fa4af0653ddaad02e4273db72c6afe9fe72d054f8c10412d38a35af66f36d760430d4aa3ade0ac66c7bb6ac7c4d9b1935b53ea8ea6060ff", "c149a250d3000103b80c9a8e4765cb3c445b38ae5785068b505d42e79a6162676a4ec9fc8a6b400a3d814dd1820b691c7a80a3ec9182050e05e2218b4e5944e44a836db0af634e6cea749f6f2b7641998def8ca4dd553df23861bc8d893320fa1773ce18bf340109cc9af006dc7ba59985dd406b84b1b22042d3ddd62d4e98ad7408f319445c8f69516ee05f4cad01fc718b12654c5b52964aa271d07470879fafdf3064df535576e20c334ace786d8d7635d065ef7e26eb544392c2a49e44646e04ba851d7c816ba830682b57b796e2ab4b4b4ac5b9ef7c22792e90f5f4f22000abeadd95d7c061deefc0073939c892d0600aa39e1b724c2f5d62b3ca3171e49135a0f3f8ae60337e6abad1f0f6f75a51ac6e19d0b06512132c830b97cd76294dffba575665083153c6b8d52c760c3cf25343c88a3deadde20f5ddd8d4f570df13ea36ba03dea13558a6c5afb096237d9f0b15ad1d5a4f540ad55f22c4f482b5dfde3c5131daac7f96f39ce49405810bf62186713120d6fb7b82493d56d539e7fdcfa1b3cd96e6c215252b0817d4c3278f892d0bf3e460eda83cd8f5bbcfd7941777b1ad364eff44aaab2d03ccc165f770598fd644202c7cdd09764b45c81feb682528a7e4f49413abf57cb14f691a8d1a69a458b35e9a9a79c0e1c2765343611494196da5cfeed4ce918b75dc20675b9c1c00b7009224d095ac2d873a988ce", "93b465e750683f4bdec73305d37dc61ce286d8b0801976556f6ba4260f68c1e92d278fd9b624bc4650dbcc502bf4d63a2a1b844f5121506a1908b086e41bb91a728b0b0945b3a608e36da28a92af2fbdcb017c576ac536df80926126a00f11b745f446d3b41d0b9925c897faa005c0e7af7fa510ed8705408a1893489087279142e0449ac0d38e5367fd3380f5922de13d83a74500e44a0bc11f8669b5eb224948048fea342d639709fd7884d8ded72a0b7752f064f729dc5ac96e4f783f4ecb137038ce26eec88cac717a46e669a3ddd01769bb43df0547e71e0ead19d5e21fd671bec9f90808eb1de718305378b11a2e365cdc432d5e01b4e762fd69bd271948e6593053199416474df1736bf54f4cd4155ced652c9198db1d7fc4e21903e5e187c71c58bf0ae9f2679a21aa5791ada10863cfc82a874d978346a807788eb20276c37dc63b75f61ecb2c21344c0d9c3e73355dc2974c72e5b5ef141846780062326773dc1a83ee090311583e955785d85c8c35a71110aba9fdc5428b9e38e1fb127b02d37ca35bc60635a8692f8cf0a2855f23f5942438c3d692d063f5a2d821a403e81116ab53e5a3a73c7486e982edfe1cf8d2ac6ed71660f23e8f17636d70abba43a086509dcb1aa8c4c118e6d8a364266a186f39bfa9293dc72ea430233dbf0be77369917748b8440d22e3fbaf4d46095ef3bb8733d3a5842f894927cf", .None}, + {.Add, "e950482a96f9beb227c35793260d857d6380f9588f9ef8e589b68416e1b33d3836ac4cebdf129c81361dc9b52ad26a85e1a86e9165871491cc37747542137f488e392782cd9fddf5f3c8b4f08d7b6dd74a858a07640f61c5dd3f50a8b6936bf7af028a5d6bc061f55b7460eaf82b238c3adfdbd5b46ca816697b6daee022c07705134330974e0a8ee673c5093cef6378e4cc58d761f2d307ecb4c41bcd7e179f6f7c8f18bc5fa9c5ca3c91750d2b799554a3ac6b1c0c2d490b2fd2c9907ade6114c21ca4574cc89366ed9b3af3d6142d1686d36249eda8a409f4fbbbc855fd9ca8eda3125486497c9ca02fc50c039b2f1caa7b393346c91140d91ab70284516549c2f670f6b402daba1bf3f7439fe8aa8cd16f8f10d72557c75006f1fbc2bd32770d59caac1148a8a8fbab3b73a0d3be9b6ad21d6c8e07f2691e2ffab3ed27e6ca80459e9a1a9f76f8544250483e12db047c90882abaa6871c8b6fafb5a604554f6004583b8d690b48469fdec82e6d6dffb6fe81b5b89f3f2eddaab23b4f2fc4e95ba247c9f547fd32f631dbf74b3bb28974b9dd65e48d69c9da050a1835f4fcb5b0232b17c0fc5c3b02253274dd7b049f7b9bb06d6fe0307f600985bece6528b057e7231b8488a77dc695b3c145f71c7d7c51ceb33f92b372213cf2b624ba38e96f8bbe19ab07d5e81631d1898b90f6a0a62c3255cb5cc8bc41585bc4d2887", "293e13fb18f8d4d880ae773fc720d48802061f749b100768dc436569fd99c8cff05ed2765e1be69da293d9ff04f23884f5aa94a1dd21a718c7e337f593a365778da180e01310fda7a36a0e0c6fec22a2997a5a4639f53d290f65c24b5a247e91ea5732872576e28faa90f1ed38801ce551490ca06f3d4edbc4598bf274741cef87662033cf0e6b5b7eeaf885a8e76787127ed46267274ef823f24d0382853014ce78c9e4d054293b29271a37c1c60190932417df843c6ef260ca6c69c84332aeda6a3fa63cf09e44e45e0c5786a8ccea639c1bcb3eac71c383148a025f55d14a84b662c91c8130f324c87382cd33d539752daeea55cb8b3cd2bba02075b6f5116e7a7ce61cc309bd13131eb638231cf286c944d6c8b636bc9d20ca19a30597bd81e4f39c43424f6fbef43f0c61780c4b8aa48f55117f9c09dd38b92f990dd3fc91b852e6c92476e9fa0c7c17bc474469665ca144450095c269d1ee8977d20e899db2568d3e4924208499406b8d365f01c1f42110fcb12800b2aed0138defb0b98a00fbd01f91199dcb25f86e4381c1e1c8b23837f64b46713f6076b13a9edb8154e10cb9f1c882cdfc8b8f04b5d2fb03e14905bd194b966772f823d1929135f339d16bd244e53d72013f274df4e8dad71ed30874e2ced4816547e1c03dad008f523c65951e63f208146a74e960c2232e9269a272712668cdc408c7b686a33cfb", "37d3187dc26870c3a32aacb8f981acdfd83e2f0a2409f6f734decdab6bb4fca373c997451c0d1065b5f5b69a579f5f2d53c51b8af37a1861e4a6af3ce7c49d6c168513583feafb8702a6995b78c3d9800e22b2e6b03633456d39b755e58db55165475b2cfc32e8af004837fbe802cf1e14f70a5dca84195d2af142cd627648f6f7b75466d8834c046d5234d63cb65dbea0cb99efdd467c28a2bd99453f5d118ec57092d65c1a23d785cae34f1298b929e86e52a635fd31c6f17d6996614ae094ebb6617082656ace1acce60b35e62e2d35048901634b4c4dc3b3d9be1bdb31244f453cfa41c9958aee92767f1df40eec66f8569de8fff7cde6c931cbe5df3a27c316ac4d2c2e49eabeb4ddf5ac5d1b7d2f965bcfb9c3a9121995ca88c2c1c390a955c938ee0363fa4983f9c018b21987745b3c76e8487c8903ca9c2f444ca67afe605740b2c620e16991c03cc0cb259716a46a4cc7ac402adb9aa584732c6ecef2a856d2c201fab1391daa6979b945d8a1ef90f9180cb1f4a59caabeb1a4a3b5d896b5f49c306e1d9e555b8c02f6759cf14983d5cca98f47dbfe1701dc223ad1203c0eeca3449293c03bb157dd20d2b42b40bf782022946a7aee2469ee7e1c45c4d6ea44769d85fc791b90a930fd3a48e6aacd91ce02cdac9c69f58f690f4c32e0d35e50fffea28572ebd806795adc3dfc74053596831e9a4fccdd3c42f06582", .None}, + {.Add, "-c1094a85c214b6586dd4b8655d94f50732c68cd66ae47395210e2d022d41ff833785fdc41ed3c4550dc245f3142f8665faba42ff76186a3d6267c4d380fcfc7be8e81bdb2b43cbce5c6c8730fa86c35f7cbd67a4afdbb506b747a3d15cbf9667e2473b58e7c36c00ccd44c108334cbd8847991598bc65ec8a9a25c45944e102ee7949adbe3d1050a107ab44d10305bcca14b02f20927ecaf5efeb8eeef73a44f08e6d9c546913a5ea08bcc954afe6527c39ec1058b5cbcb8b74cf584b728826c6e63c6ef7a9ef4f857b9f82d9c22127d274765e14e48e05adec6fb0cfd11a42da066c9eab47fa819a8064130b07b9d7e830805efbcf1c826e18ade4a0eb00e9d00f282b832166090ac0070f155a52c198d74c97e09e8a60f1e5299edc9bc82eb52b6f75abeb960d1be1172244110b7f1581ab11a6800dd8084b435d46e3a521f093cdc90328c045f8c40e057264056ba003cf53ed0b5fbeba33089094a78550678c93406640705a5f5a508263060684349090d6c27acf044ad293998c3cbd986b193e348ceda5d2738872524f9f373a826cf88c88a0548fbd1d37987c5a6310d606b9272415f9c78f8358076e2daff76a72dfafcc49ad5c74f6be5179fb7461f1a67b62efa0094b00c333e0736af8151f77e7ba63680382d7c141a513d96d67b717caa1babdc9654903481d0c0f5f811a7e06a9d91f3bd4c0ae96cc157114c32", "dff1dccad369aab281cfef17c381b00ba47526d0389b660656d0ab436e9bcfc92335252b2345f7aa20e565292692c51d0ab574087bdc2b59afa0c52aba49fa944da442e54d7409061275db1c13bcf2f28fb4b1edc908101ed5580108214d872e47633ef2dee212381baf7d1d21242ed1ba1146f9f9b5feafa317a4bf1abf88ac16d8bafff9f2a8fdd6e282dcf7965233bfa3fc4d186a3e548e6664b8b2119dcade60dcf81f487f743bfb5a152af4ff0ca2f8709600675cf0f7049e0e27344b3f1521515012847a399728e6fbe7f77543bdd68c2ec456279eb21449e92f55205937a13b0b8ab827f3b25c565425755ef9e38b2bed8d70e4c4f5c6d0a2c1ce7930326c1bed1f07ad85af93f04b5d04af925f8393e5b76c0c081648f03efb18739c643c0ece9b7e9360e07959abad51242a7968d0887f80b4001946c75653568d5225032529388f0ffca019aa47f1026188cbf81c0d481dbf3e6e36137ffdc81efef062f832fd024fb53972c78d4d9a75c4b535496af633077d8a2719595292390bf0ad50e67aaf2b3a6f79df0c120b9f0a2299d89df2dfbe4dda4f967e5e192e816140853b8dd153ce2cd5447737e76d3f2109e2d8562c962522ba0688481cc4c4ce9d818b6075870a56d9dc4e1158e975e0dc1d6a7f737f6a06c86a27bd228577ec66c9b0bdf4b11ae0b483b0de3d682f02c13e3eac7cb8a082bee9c060248ac", "-b30a2cb914de1bad45b7b973e15cda06787f3a69675abd34bba1224df6584286a552ab716c9f64da6bb3efa081c65a142a0eebbeee5aa787c76db880d5585cd2a40dd7acd66c8b3dfb45297f394af43053c21c85d34b3404c9f223c0daaabdf4fdd10769b9d54add4b19543eb12288eb68d87ce9ec2afeddaf70e1f9a2a217a426270f2be431da7a330c8c1f40b6f6a96550c32d37a148ca161852a364528a725b00cbf5c49cb2675ccc16f3f84f1536f96f39fc2b5646e9a7dcaba3d4b53db87d11b1da7976ad54be4769bddda29b28eb69fd1e62037de0f3a5b66e6a1c52280cecb639fbd4259a6ce07bcb6e24478ee4cf5330e41ab9da922e713fe2932709fdcbc0f96025e5b8510731ec9fd4e120677c903fae71e54e9cee0ae9da0afbb18c73366dd501779bb009dc89863ba5aeb0842411e008d240831fc95f0904e949e6ecaa3d9f03135fc23f45b2a73030a1737d737dfc341ff7bc4d27d14a9bd31689c304833436e0aaa20ddbad5b86c0e6fdb5b8d57849bfccd486c8032ea2b5f5f2890e3a672f6a73918f873438d2b9b784a5eb3eaad74d16f42e801fdfc49e254a578a1e8882873c15682c2f6f5c88a2b51d5ccf3f380c64fd4044af1b3579d2cd7dde1643f93c3f66c5a0425599f2ba9970b9cf8e890036dba793aec1c4ae23f2b63d809ffd4b42e2293995b312218eb7b456b9a72bf1c202bd7e25510f0386", .None}, + {.Add, "-669405ecc667e52292de3555f38bcfe02f22e5158527c6ebd264e3358b64b1b938c3360c47831c6a4f265d8762becf461417656acc6974f82d72f1c5d4149c87ad204c4ca1dfcf06c96ebc88d2a43f2f5983c4f72bfff2b45659cd24e0ea4efcf05a4851431d829a880c30748b733c08f83bfd4b72f2afb07477147ba39d90f735be28924f614f96b97934c1dfe6f3f81cde93c3a6f7359a72b6ea6113805de719356b845ecb851b5e78fad0575b6a823332f8f4e99dfca924c04fd519f9c39386791b4c47de5f547fd85984ea59840caf895cdee2bd5a47ba0cf14fadf9bdedc7b26157c33d4a6b74ce8126fcb34c158e434e182e7f3178e21fd06a51e8cd46d36422526ebdf2517cb59c094f2479a5c614b2b3838ece3d919578a9552fb7185877634205a75ca1f7bed87dd5b5e0ef04be82f14fe9ce3e9f1aed3af82182240fc12fcae809a280a0382af412507a6cc0e716798e6a950b016a5d8ae692ecb24e397d2786f3016aa4185c4c65a78721c53ad7ed81be7b8c0b3dcaef9dcaf6abbd6d34b1b715eeb2244e399378fb16c3e5448f30d63484df9e88bc1844731b8fc5200069f4825ccc1b9d321da00ff44fd4ca4962efce9fecaf47cadad59bc0ab0e847a69f1ee5f9b59f71f4598033b25e692325877479f73da366c4a2becc39be1da41dc14d6f75d0a18856546cae6b9c7cc45f2302cf6a36dd1c06c2b11bf10", "88482718c95506b036648b1d696868908487f067159547c42d9d00b7fbc4e3bf03b0a49d590c495dc03e682f8c1fa9d5c3a9137a8cea0c5ce0127c599005b7df7510d1ca3723be64c52ba89f1bd94c1fe40d26387f721e2478f26b3f64f08c696a36abfe4e1e96367ece245630af45fb49c70b7052a39fb8c6146f8de70c81b150befef5ae776edad1f9ee49237f832f0d89ddff5f690ad6cbf5da58a671e77b5adcd088e3e63147d7331ffc770e1ab70d98fd2f6f4795ba2bb18fde95a68341bb282fa4708f84cd36e24ebdcfbd4937256182b0676c0e502123cb3d9ae2404b6e921bc277e5acf9ee2264082201f44e103584f15980d2c5876c671066ebcf02b7a03281541716f706496a9b36c11e235eafe3924a2466db9fd30f5a0f66d5a48ee4dc80e342a93b7a473f9fd3f5f4714c3a6a22cc6922a322ed9a28a46c30a3c2b032d9f74790d77e9e67a51514c74ce9d3b2b21bf24a7a14ef9b9abd0964e2055f96e7127fff45fb27509918aae5ec6654e05f05a037e6d0145dce5e338923e82229725c47d78eb599cc3c8ef78d1d1c3ace91ca4ba7db021c9b7e83fe0fa76aec8f2843fe5c8338dcd302e8c04f0e159cb524042550f9fb9d586aa51266705d0d0386d054f213fe41e780cc4a1145f871261397eada8ec66368e8b6b582e838ce05834f618e4e1da33628c030d978bf7707f017b3694d934846609931d5aa", "21b4212c02ed218da38655c775dc98b055650b51906d80d85b381d8270603205caed6e9111892cf371180aa82960da8faf91ae0fc0809764b29f8a93bbf11b57c7f0857d9543ef5dfbbcec1649350cf08a89614153722b7022989e1a84063d6c79dc63ad0b01139bf6c1f3e1a53c09f2518b0e24dfb0f008519d5b12436ef0ba1b00d6635f161f441880b98743988f36f0ab4a3bb871d53c593eeff792f1899441a76504851aac2c78ba252c1fb2b034da66043a85a9991106f140097bacbfae34af145828b12578b709f538e563c52a75d825d184aeb4086716d9edece8825da6dfba6ab4a8628e7953e2e1254ea83881f236d92b01a14ca54c96a6150301bbe43c102ee55924a58993ce91e79ca47d989b30dec695989e0e3d96b0ba371e8c366d793edd9b4c9982886721fe401382477be7317c7f546483d2acedac4aae7fb2ef030f0f3dee56de663cb102c44ce028ec9c388d87b56f13853e0fd676782fb72619bf8b8cfddb570ef44cb3035ecaa11a087183e1bc5ac4d692dec06892782ab4f4c0a531e8dc914b92a915fc765936f63f60f41722fb6393df663f8af417a5cc8ebe4f7bffb71d3fa0e548b05abe40d26bc11456b10d4c558d8fcf76a5c54e88891cde669278a44ac83b3446d62011def3bb20a33b1aec2cfc9e8ac8bf4c56f3c3a73a8a96f1138ab0c37965f2bef7aac1fde78672aa257685f46e20169a", .None}, + {.Add, "627b0c117af9eeeba4c49605166a9dc716ca84b8c73f8e452f642fd48a669d32c5992b66791917c98858988edfb64a848548ea221c4527ff7b62b3338e81e875e33c5d40a9942f0b25b60114e1e93cd2ff29e45d18ca9a601d4e5759b479e5aa9ab4173d617b6be955fbe90e02ca1525d45e2d88c2f7986ddcd6a28f088b06e05f86325809d5098075e4009bc5fcef14da2f5a157f6b22a0195a34c482f4016d880a7cbc3926dfc823fa6fc9b5b15bd3b93e301fb765eb54b094793f1dfc1b31d91a10fd8f58b2a26d7b3eddd4fa052f9a098a45ce9dd2788243a2e300123b66702c3f9341c7c604d1c8a2850c337948d8f58409e191c37caeb2d3ac1ab991f0fea7ce6636ec779a6d006162f9121513321504d3fad97a7247c5d47aff7c6f91f007e7d05a7243a92caa92140d7a562bd7657379c3acc985a2f2d0fc5c67e4e627c5dc10260c4e6635bf8293190e70e263a163f01ec48dba8b5837b2fedbe081dc07bed8e7576e32ac4e6727ff8ced20bfa9d0d6d1ecafe419abe4c3c60d3fca4f2ae7892c39731dc0bbff9f37b3e22d0b3e2fb802b07ae02f0390c0a8bb5831f97a3a5b5fa444434d0c81b3030f1ff05de85def4f78a63ce6209f4408667e1d1bb51a5e083459e5a66579bc4c799831034e24a5e47aac55047e8d6c3e7c5ab62c40f0ce39f71648e3c3f8e9069f8c0d43c4aa576e2a5e48fe9f338fc5fb467d", "47b2165f1f63b9881e7d41bc852af73f9b2b29ac7c00ae106436980ce31ed3c95da3347368f4ef340b2736df767ecdeaa0538e85e7f182a141fe504b37088cc9e78081cfffd31dcb3b376a45484c268630d0537f4f4216e4fc57e86c8f88545976c2ae118d4d456602fbb34327ab560adcb3d901dcdd0af614613a18148863da4322e3baae166bf0bc2d907f2df553b65e1b8c7512bcc7d559f77734ae6ea9facdda5d6953559eb9ee4f86bf7bc030277d760b81159523a3544ea60e1c348ee9891f8c06981a36e17f9d36c03e6ab07c17f983bb48b987d68668ee05f675c679093205e1cd647e41ffa78c49d9541119de5accb16447f409fce405a34f9724815eb3b6953e0d62617e98a4ae1ee3ec01ddddc81d01f00024211ef0369eef8f84e4cdc9824c196eaaa746ae696dc9f7ffc250d5672b07b322f28e9330f5502bfe9a1e9971252bb399d651e696d22da4b123356dbca98ba62bea0d46345d903123fcb3ca159c93e987a2d6ac695266d52bedfe465ca7fb2684515826056b9e1026edc53defbccd23af634c992b267bc7d609c8ac8d5b15efbdcf078daa618202c5b668b70f36689e543161346450bf3598bcae131792b1b4337f5786f3817d45f3f7df7fa7dc68edb7dea876868e66ff01a1e32bfef04889b5b79bff62b1916c3c84d952ff03b0eaeba968be6ee38ab8f7e2223ba1dcf7b7741ecfb65d39ca8e31", "aa2d22709a5da873c341d7c19b959506b1f5ae6543403c55939ac7e16d8570fc233c5fd9e20e06fd937fcf6e5635186f259c78a80436aaa0bd61037ec58a753fcabcdf10a9674cd660ed6b5a2a3563592ffa37dc680cb14519a63fc644023a041176c54eeec8b14f58f79c512a756b30b112068a9fd4a363f137dca71d136abaa2a91612b7eb75713211911af3f242cb384ae68a9227ea757351abf93162ab6855e4da258c7c7e821249f68931718bfb36b43ba0ccfb0ef804e31f4d3a30aa1b62399d042772e983ed18759e1364b5abb2030e0117575a4f08ac90e8f68801df795e45750f2c4446d1702ecee5878a62b75050bb45d9b786ab96d94f6a50b6725d5b84fb74f9d9fbeb99061117f601150ff2ccf0fcc97a9668e4c4b19e6bff16d4d5b152a68bb253d3f1407d7b444e2b99b648e0eeb47ca89581642d51b810e4c1e475814b3802000c116929eb3c159386d6d1acc85033e675657de75c6c11a5d8bb88ee83eb57ba4f25139151f3c24cada8173379e7d6686b040ac931ab4ff13cf02578e90696cd240898ca5e2faa031506dc455dc66a9dfe0b1e6b0a3d5af7afe2f16a960ce2977e6db61753ce55891a967106e22a5a706578263789e3c41113949a05e49d479d850df042dae09732a53150a4d4c3360abc1a8ccef00dc6f2b11a43cd3da801348d2cb757ea2a450525e6e5f94b2215bd1d6ee9ecffc5d4ae", .None}, + {.Add, "-7cb061450657afcb2c2c9ac788e1092ef6afda4a10ab2238ca02e8a460dd9d5c1d793637f1dc1c9c6d8d7aa3216c3c567d7b6135b6c2c3e010822138900ffaf817d3b70f4205983306fbfc323cdc871315f6ff857505c11ef4fcaf955e101160474adbc164da158f5259153dd03f2f5507ddf9fe54d31c85beefd18fd9e837790614816d570980b504c28e77f272c1398b611ce1f3652bbead1358026967fde303a36afb79f1095af94d55fe98341c5982c4cb8adb7c0cb36bfa71c290687455e9e6164f46b1b7f9eef9684cc7ccd21421f7d76855d7b80f5609325b40382680fb6c2ab66d0011455e892fc678eaeb47a9d6df11b8b96505123a17f2dc8b24ec111f8f983a08e0c7df6052ce2a1e7dea2f84fc05c44f9fc6ac580949fab786beae3ff071fe8cff2ab2a95108f52f085fbd78a3d7268012e5c22d51b6925d153b97819155244b0d8a7836ffae018f78415ab0c15730cb8846839e5832bb73aa8c528c38250e52a8710c00dec10096f259007628bea87c723c31afbb1b0b55dbf7c135a45b27b4f48d3791eb93688a37234025999fad90102f10132b45e4eb6da67abbcccc147f13ec0f1b2483579361b7a3b686b7266b7dc2a056fe6d5da13263a2f3be9add6e28ced841e3d710c26d299030c3986bac8d09000a30b03be9a54640198678de7349dac3dc231c8e78a11c5b008f08f11ed18e092c9c99cd959c0e", "fe78947feba67fccace557040b3d9235e3e867fbd112f9831e82a53cf79a25d27284fff2334e14a515a02242b2354a6e0ae35af76804c0ab650639dc340512486029445acf99db27642595abe89aea1a0bff16b0a35b7e90a39107aa5575be482695f7418504c4285296d2e60bfe25d7fb180c81e6eccce05cc4f5ad83e4ce00afacfb37a99662e66d8f0bd9a5459c18a87e81025cf11c47479570e654706396cc8713d719833296caf035b063fd967b6d3f00c8d66593ac0e02130783c0bf6929a1e4ad097466cd4e044d08d7dc746bfbdd7f39065ad3134db8457b6477105fde348edb2b6d3afa3cf0d9c0ca5a623f12e8bc236eacd6832b02f2eca929f27876d61704ddad414dd61cdbe8fac95e2740a56807db400eea6ad1b22ce2bc1de5a128634efa708ec6b685c437bb1638a41af34646b3116a4f41f1693ab3d9584e0eb8433adaf03a0b0d0271c88a04b7c4e493568d4981323267f45ea4d52dd1f2a16ad821861a228c36d028bac86971d2c94ff44a1fc97cbb29065626a55550f4d8d1572f57bb0d6a3e09128b1442f18520edd5fc3a2026c654977b2543ada55084ce03cf69a06573457c5649221a3c7cc430f997cf8a21a24c065e53a34702c9066310a0dfcd55761af2ad52c4f82649810fccc03106334d8d0251e69fb0e50a059e5c240a964552df2195b446503dea4e456244f2fae722706e4816fa92ec14", "81c8333ae54ed00180b8bc3c825c8906ed388db1c067d74a547fbc9896bc8876550bc9ba4171f808a812a79f90c90e178d67f9c1b141fccb548418a3a3f5175048558d4b8d9442f45d299979abbe6306f608172b2e55bd71ae945814f765ace7df4b1b80202aae99003dbda83bbef682f33a12839219b05a9dd5241da9fc9687a99879ca528ce23168cc7d61b2d2dadf1d1d6420698bf0889a8218e3eb0865b3c8e3a8db9f92293bd1a2dfb1cbc97a21ea7a353dfae986f8a207a144f3584b133fbbce5dc2c2aed35f0ae4bc100fa257d9e5a7d0b0831b03f7af1320243ee9dee2c86424be6d29b4de67a9fa516f76f76911dd11b5f3717e18c8daf9cc9ecd8c65b6876ca3a46085f6bc891ad0aae03d11206c0216f06f23be79a8e2e8049726f2e872dcfbe38f9c03dc732ec5e730445d7aa26f8c9157697fc41784217c43127736b1e5b6a52c8094cb721a88753f8389e2953618b5a9ebe456067219ba27664ede9ffc77c77a1b2acf49f9c7d27f79c8d9cb8b774d0a7ef7569b0b99ff74fd179bb2d4300618dd067726f7abb8ba61e0c83c5c8c90169744844fdf5ec237aa0a12370355215187366131c5ca86dac5207a72e0a91ea3dfabaf5fe645a5d065636f5206025f2ca742b0c97bb435b91ff0df0927c559a6448cf8213663c73fc3c584d5ab2c22fb781b457297b7d79ccdf344d33c01dc15946741ab7d2cfd5006", .None}, + {.Add, "-42b4a34d05c7964937fc5e14a30757b354a7a96cc585664935f99041fc61db2024233ed287b723dd090ed9a9d4cb33abf855eb99f309352c57a65f3bd7fb264ea6b116ca6e4dc5491da2ed4fd2e185148b5affc4e9cbbf9541a2b6900ad57102639616f94bf4b5598a6ac7fd16178755d13a5002f9cb0665fc398b296599e6822d85f4dd3f9e29fd24d150b87a61ba96336d84433cf007d905af23590b8ff1a4b3e6c6d352d4c2a82002d35f052b31703219158d5695756ef3b4b87e23acea7f8bf72198fc92e4b0ed71352ad88c59fd40124eca8f6095e3f3bdbeabc79659666761e0a9521d4358153e5784c419591b0bc3961a7dc5623efb9f2b76b217914124ad9c0964ccb15b06f57b3ce8682e34089939d3182e202c86ff1e0ff0a8ccb5b25411d11fffdc9bcb9780e8fbe16650eb7be670e59ef6ed93b22d17f2f35b5f73195a6073c01297417850af0eee2c7d1311f188bc25272fd400ed7b683d156b33b173f5ac7cdd52be35b4c8157de4649e55cdb36d7f3d678388b0ebbf5ea716f674de8dfef51c3e79511d3dc16a66453e2ee99d297f1b41605ca5e4698fb376e7566ba3020ecbde426d31d6dda66ee222be2569dbd67ea2f11b9176316de3675d52206cb44dd1e07156528f8b81b925b36a3840c361eca1c608630181934e0b7ecce2785f8c3f3485b2686805ffd5decea6edc5a95712dadd10b87fd6b4e5e8", "fe7533d1eed92056f70fd5523935c68b4f6342691b65ee78b5feb685cf4b88606f951c8332d56e69a52f4a690c60cce7a4c97ca00cca4e8ba577893afa8b0c156255572c38c42d2c87432c42198ec6819affaf4ce498951473c508d4299b72482b495baba02ad1662965a9eac3f78c7d7f6fe0069ea7a8713c6e174ba76f6b287be6748bace0584d8e0eae9eca0e557f59e770b0c55156d5dad1969a09bc8dbfd636b9e802b73fd91144c49ca2fbd67ecf8e9d7384e7c1eb7c9ed05fe0135b8504275ac9147667a1f0fa6cb629e0607e316864325e1ea3a9c9319894dd3a543d4c4a7c2cc9b8e6369ff6064952c8ed120384156095741c89587e96c5918e3f8f0775b92f02f3edfa8db48ec0d9194141bc08c2064f54b97d466e9d162cb7b843b570f879a9f3e9f1b9373f685b2f372f2d321be9d0c0b32b35381bfefe91170d1b3844d64908c9d0ea1b345e7853de93554eba41cfaa839ebf7b2e93c40998c49974902024cffb19715480d11ddfbd24fcd5e50ae1a1ed835061fda8b98c58f8cceda6ddfbc4e7bb20f46515028a03cb41c16fc63c7de85b780df06952a24b28010e481b55d5b53ac7bc46ca9ed1b45d3b6b448b947d17e3a37816e416d86676ef6e2da22e6407666102aae08a34fad55a87123a1b54a9e2a85656f01366b1e79d6bf1eb897f37524d20a1bffc2f27ee78dc965ee21f272784be37bacef0a3cf", "bbc09084e9118a0dbf13773d962e6ed7fabb98fc55e0882f80052643d2e9ad404b71ddb0ab1e4a8c9c2070bf3795993bac73910619c1195f4dd129ff228fe5c6bba44061ca7667e369a03ef246ad416d0fa4af87faccd57f322252441ec60145c7b344b254361c0c9efae1edade00527ae359003a4dca20b40348c2241d584a64e607fae6d422e50693d5de64fac9ae92679ec6d88614efcd5227340fe2c9c1b224ff314afe27d30f141f13d9dd0a50e9d7587e62e524c7c88ea17e1bc6671057830393017e382f10389378b51540680f1561567cebe0dc5d573d9e915a3fad6e4e89b83779ba2de8ab7aec48eaf93f6f7c07f4617aeba4a5cdf6b4edf76ae4de2c81d259e273c9f86bf1383f0b1130db36f883337269950bf6f7f063c0eeb8e031ce6a889f40d55ed9fbe7f5f4dd0de41b63578eb21bc3da185eee70b9dbbada81eea75d548b739a8a2e3af6965b216423cc8b913855c6eeb7a41185bcc835965c31c2a78531dc6b31ecc090861d8c05e8017577422b01bccd94cbcfa2db1e1d678c84ffccfcb7ca7a347d7411f9d860392862912fecd1a17b14a84e91297b119b7dc7853c6e95c854f14f3c12b457b18ad1f21b8a69940b25c856de56a830f921c0d357a163585efac5850feb341afa71cd9f957f2bd40e24df3ee91d363dc1e9f0f7329f2f81dc76e3957f62f520faa35a89938c8144ca7ad7f3af83bbde7", .None}, + {.Add, "48a198f950472fc86538026a3ce6d8b379b3f4ccacc6b1362b8a0bdfa71c3ef81975a2f764247d767f43283069530727d6fb56e2e77f6cf41d7a04d671dc6d44a270fc451b891f4e6d3d09d5a1439aba9ff02a1abe052d7eec3c35fbde9ce4f382e33cc2774d80bbc7c3f2f717b2e51820903d18c2edc0db0b6c2b600765baa8e7cd9b3414eafa6777482518b991cb8805e6715349b0c99d0d56583c2ab1b6fa803314ef3a1feb6c4e4192bfd896f9661589b89b6b3f61f7a5886a2f1aea8e69a5d698c2e91dbd66d1f88ebda58dd8da763f0e7256ea6dcb477c8ee9db4c897b6497d09f5e6d5bfbf8346aa151c5a5d2ec389d1589094917a3292e31c02962688f3c5fa850abae82c6d641a20fed77aa96da68e1c753f4d19d4cb7fbb934b89096e4bd88f77066bf5cb00bc1278b7d4107ce3a63d8af9ab9b85ca5e6c6ffaa87a50699bbe545e0c5213d88e52ec8e348cdff2bb3a9d040393ec67986618c649563076b6ccd0655765371bef80b5f677876b309efbc758c87fb006d85b95438b22963c8e838c38b06c82c900b5e9ca57d7bf97a0e2698871e3fb067cdf666ab4669c0312124bc6f6edd939abfbabd392e8e0bc07e9c1c097e4a092f51212bf10e38d72704c1839f6d3f11c752f1662543b7925caffd6f703cb5648e82f47c1e5ac42490ed36a42aee1cd60984bf37b2abff0af0e518bfca007a8d4a3377e9af6", "d36e0d49ac1f21f466a0014d180fbb02e70698bab9c5f067c6511cba02f341d06a5a97d06ba7b79f53f2d2ff71cfc72066ee7834fb2950403955e7c241ebee53a15c615b8f7e775c88b64393636893c02b4af56733f9960704de0e26a8ac73f5dbda4f1ca4c8387f9aa7e04a286487b4e9b280f3285e0829f42371e3ae584c669ea7a5b446092518598819ad0c3061e739151e215a9a53ed8b52cf7979af481e178b1a98631a9054e610c28fe85d1efa0f876867f0fe94898a1eedf76f239c1a51adaad7256c5f744d349aab0ec6c7902ff997aaaa9e2c08ca7f5f01485f5c781634fd3027277c2ab39723acc960f851b3def693d473b0826e6e7f868445c7ca72d43df292cb6a21b7ce3ca1529e5377ae27fac510682dba19766440982b541692cc3429bba7c6a9132531fe980cf1d9900e8d3eb659ad01bdc07fdfd35c748518e69cfd117e9009b8c3cc28d02422b084d116520aae8ea54d6f5314032fe5d7e29642e07963e234395233ee3e1fe79bcf8fd5125fca99385722e55c61d0f17d3369ddfc80c55048f28e73ef80fb918e01107657ec51e95cb565c993b643755b9d1d0758ab1c39af3dec2848aab8fc2f47293abe8ba51033edf0be46ea33dd3aa346e31605f1630a29e260eb5143402eff5da0739085a5c74b8116c9138e2608d1d0cdcba790fc133c95a5b026e38f2feac2a9ec89549eff50b1d22b91232dfe", "d7f826d9412394f0ecf38173bbde288e1ea1d80784925b7b2909bd77fd6505bfebf1f1ffe1e9ff76bbe705827864f792e45e2da329a1470f7b2d880fa909b527eb83711fe13709516f8a1430bd7ccd6bd549f808dfd9e8def3a1d18666964245140882e8cc3d108b57241f7999dfb6066bbb84c4b48ce437a4da3499aecea8112d247f678757d4bed0fc9bfe97c97e9fb97385368f3560875c2834fd3c5a638dbf8e4be756bc8f0baaf4dbbbe5e68e9070e003f1a7b28aa90477749a60d24500ec0b146353fe3b4aba542396e91fa51dd75d8891d00cd2e57ef727efe614250fcc7e7a3a1d0e51ea731a6a56de7d52aee2a280652d044513e8a11269a0485df0fbc803ed17d62509e43ba0bb739d2af25795a1532cdd6d07334b2fc053be9f9f9c3a80024b1ecd1508f032baaa85a9ada08b70e4f3e4a6ad59464a3e3fcc6f2d93370698cfd2ee160ad7a4b72310b0e511b1090d454b92a8e15bbaac6948ac2138c6b9974634478b9e894fddbed5de1356fb05b15b91f200d6d2ec34bd66350856001a8b045188f95f113cf036e55be5d8d00df8cebb71ce9960d01095a9e01003b90a6abd6800a62bc561f4a664cfc23009f6c67566d0cbd291513bfc469c4b86d4558652099d00fdd37d608059a2833ad6c63e905c9ccb16d75fb142d5e7ee7e1316da7afb3ec21e63064872d70a5aaab358fadae09b9f585aa6cec8a1c8f4", .None}, + {.Add, "-442f25242e4d8896cfee96f668b6ea491f5a00165ef822124e26d2c66d5db98efc88b046aac2060424187e41f3ec59bbfa9414bc53dbdebfa360c90ad799f9c7023f7e5b6a55e39bb1e0bcf47876065aec4a906938a53f6c2eac99123b791ce4375abbeb880f12b49de2e93bbe77d8a5b222b538111b9305904d2cfa7fe81db7b6464352692d7ab1c8ec64a0d91677c9b7241a456de6996bd53b6b9718aaf7b7eba3c81e1839126180cc27e8acc0f09812c0c9ef37ce9e422a4c37a63881f476844c85c15433df12c392cb49504beb323e2d0cc65a01521ee7ec3b0fd5d5460a946d5adebcb9936968fad7b0573e78c0c2c67920bd401517f8eea1e8e396b71063d7a0ea8c5df086ef181e3f0b688b23fd436fac05eb2ce236f0a20a0d169d7a2fc5fc480d254d6b194eb00c582377622eb7fdb7c7b293bd795659ba61cad511419770fdec7fcbbcaab85b40f1cccca23a0b3754637da926925702ff006fb1a2962e264b8835e0d4f566985aef9a285a6d305f868550bc1395dfb493e1de164ff00f110c4c98f06f2650e4fae3f49d291c1a22bb7f024e5a5a9914ba2e7306e8719230d974b262769f7bf1e3eafd5ef2473c6b916a1503202830901168647acf0a0aeced14a2fedd9dd520f00ea45a3bbdc2f8c774b80bfb58ed09a841520faeba62393bd008bb1c4af5176cead8bfac3834d25d046de0d9ea9217cc9fcdeaed", "5ddab85507a03772a4cc44ff3840df01e1629ea0764aa9d26156188c618cb0b195106fc99f0e2ac15082e3205fc498071ec6a72111b02edb18ac1f7c51f51ec28eb3f6b25b0b8b3d1621dda8489f93a2c0a1e9942a467de219196706209be6cc7e20f032e01cec33c4ac5f7c54e593647f3a7e6fc6eaa4de6605bf3413b45930da0f0e9712d02449824801005dcf4a58b38dd71a1e63a60f2f14e7b84966bfbc1a16af3fa456cccac35349a2b2faec56a242bacc5ab5ac5450dfc8676694a71b4b16466c454bc9b865c741d5cca99043b2a0b10b5db462314684fc1e060216c92245b725c7facdfe632e4ba21fdb8c0f0483a5b9925b7fcb32b463faed965c889bab06c8dd556efd318ed9e80f4cb3302bec39eb9669cdc498d103e0d04dbb3e7bb7e6808f54e9f3856021d4a57f168a8aa3c7a16b50afdbc4d996b06935b632a9ff104208d64a14c7dc51a280e67dcc7c65e40c77eaf5489b660116254599c4ca37468f410a56ce6b331a780097db414bcdf72fe7e91347d1bb7431d61aca5410dbbcc64e7be04ec40effbd153a2a5df49f8d6197fcf5094a0119adff75b19bbda0890477485477c6d36dc8dd84eff8ff011894c9a4bec954d96e06c246e0daa9f9b90fbe948d1910c63d1e2c3f6cded8a9ca8957bb4548c37001af552ae6284d1ec57f5856374de80dafee9d0e6041cfa8fa86815fe43e1c294aa03545f6e", "-3e51799eddd3851fa5a1d2a67532dc590143d62c579377752811713da744ee83e337a94a10d123580f10500fedf0103b88a7aa4a42c0dbd1f1d60713127aa7dad9543ef044a52ae7e07e9f19f3ec0d20c04071cff600d78e0d1b02a1d96f5e776f78ace85a0d43f161982343f9297f6f6a2f0d5114ace8b7a9ecd1073eacd824a8a55268f800786d30c7e490d33983242beb3cd3cc005f0ae24a1d1b94148bbc2a025d2a1df3a594d496f34e819141d2a89c9e427223437ce53e3b1fc218aa04cf9b215a8fdf22773d36572bf381522e030301b5a4260bfbd383eb4df575249e0248ff6c6039e68982c7f2f63540bfffd27e3ec5241a5d1b45c35ba934bd5147da1cf07dfe8899971bff30a08a73bff0fa84ac0d4c849005ed6391cc0011c1c6480a7de0042ffecbe0f8adef0dcb85f9860dc13db0fd88bfbd08c04f5b3779ae16f77ff9cbf2671b5e3a9626c9be64c57244d9139bfef9d208a0a2ed9e1b5806498ab1e294253b680eb366b36f90aaa65873801386d22adf18c3fd50c47c69aaaf01553fe7b1326a3a0ff4ff12a0fa833cd029e565827f09c5f9031f4e7babceb5b828492d3ddd2f230ebb075d250ff2b74c5a081d7ab73392e2f930fc400cc15f6b515c18b9b60c0cc8bd1e2be0636dd0385c1edf3c57a6ccb6098d4bff614c35904ce3da8357a76c743c6e0107d9a81b3a42b49c57e29608cf83229c798b7f", .None}, + {.Add, "20478341ea6dfa9f4887d38e95b1c45d1fd10c731c71ffa0ebc9570f601d25a420c033f432b3b156f6f21effe7bd7d87f140e04e9b9fa7bed8a22b291d7190ac87f7e6d20e92ef36b61490e32ab3f2af66cb827604bb9b9d7d077f2287f333190a6c2fbec96550e9b5125ce6748013ed7ca16ce51723768c2636286492a9144805048e4ce1c68fce8892167a061e42f85720888c62a6a30e5f452a1ab2ffcdf7891d7c3a486906d22c47e31789320d2728d5141bf837f3f7a26aa42e88083538c4464adb35439f23e12cf2192a0435ab6e497f443e896ebd424c6117566d12666f98b1ee204c763328dc43a8ddb991c68a6e68883a742d77d2cdcbc13dbdff7fa1c2b81473788e0319692cb45854e5070262b7bafb7fa10f0801d45d252a5aa9dd20f36cbe13576151c86d2aaaa383799b6746bed9e7ed7821b54613364d03e2fed099cf0e15d82b5719ceb078b08e06b34313eefdeb6d14e361796ba2cc62f6d1c2f25c1ee91e44e8695e94c4502b9fc632182d5fa924216c014e3265b8f0c15636aec6046d991438a0150b53e1307e99e1dc495d80e0601698c587faf0bfb6e86d73615b1f62b5f3293d6b64cbac182ece0c8ee08dae67f92ca1c1766247f03ac3b9a8193afd841d1779c16e43f60660e8f0222ef728ac903f6dd985e90fc0492081b473b768803c340dd08e88fe39b2cdb04929ea7d822a9871588988b694", "45c8ffdf83a565a5755978649808de55a352f50b8b3f7ec3c7ea88ee4d9d146f96419598d80e5b8c889de2a441d970af24b7b38465e938037c64a91fd947a4a334ef14975a1794c53b2313832ff804f8a903b1154afb34a801344cb3d582be2ebe399db180b47b66f2dbb816a68740b379f9c847b086ff8620fec99f47530d4391c1bb08fe0dbd42acb2a7b0985494a0a0410d90e735efde305cf4f60346f31a2eb1a7d3a380d59791130c24ab087354873a29ac2917599085488a651c4e34fc87584f618746f922f4a5ff9f6057b0047620f55ae0fc97cd8c204a170f22c18cc6176e31505b1cd0f25591b27947079269455fffa2991af9f526fddc15b770252ca40bd52bc81eff32d688bbfe4f7cba24fc073390daf2e6a1e18445b8d9920fb49ddb1ed18b7a724634a3f94c4b002a02603249b674fa2496ec93ca9e81d21c450c8d9fdf4b285d2a39854e5c99dbe1209b431a142bd07a3dc0f5f5c9f1293b524dd0b5a4c823d8d18cfeab3ac4fa6d09ee52ba755fb760664f349a9d9de5a6563611dbc9f2a80627135423f0616e0717a1b10a6a718a5c031fe627f910311e95ca79a8cae88fe90cf62e8ea34a0c9971260670965336ead58c4ced4d64e0c5171bd133165d6cea591a40bfb42c4d107810777c149f2dc74ae78d1c870007fb7e55f3dc809c7f4623982512e7641c4a825487571640a7791c46915fa2a6c3c5", "661083216e136044bde14bf32dbaa2b2c324017ea7b17e64b3b3dffdadba3a13b701c98d0ac20ce37f9001a42996ee3715f893d30188dfc25506d448f6b9354fbce6fb6968aa83fbf137a4665aabf7a80fcf338b4fb6d0457e3bcbd65d75f147c8a5cd704a19cc50a7ee14fd1b0754a0f69b352cc7aa76124734f203d9fc218b96c64955dfd44d113544be2a9e72d798f761961d49dc92ec8fa21f10b646c111b7cf240debe9dc69bd5aef3c343a807bb00f3dc8214f4d8827b32e93a4566a354b9e9a3cbc8a9846d5d2f1b88a5be5afe46a749f1f86068ace6cab2e658fd3f335b0201f70a793041b31d55b57009958f3b3c887dd0d4871c7f4c99d53756fa4ce66c3e99f40ad024c3fb57056a461c1275ebeee8c5a93f5a9e358a2de03ecb991bece8b8f9ed1d397fd1123f6ee83a39dc77908905ce79cb8a1d9ddd4ced5ff43dd276eed610088815353fed54a69e7d3de570912173d8f21226f616cbd8c322410c311c3b1421db9f65d3fff15260cd0206ae7d508db81d25082cd0356d667ac6cc0a1ce60411a5fb3692f44429e85b1838d53c7f26abc19b8abaff400f0d57e37ed0a2607f29f001f6bfa0815b8b19ff412ff76e0e552ceb8eeaec3c728b551df8adb2f986a6e7631ba8122704316d8f9679e43965673db26faf60ce917bbc7767590f453e7c65fcc32e375ed1a84352237a0402b24fb46df02b82c2f7a59", .None}, + {.Add, "dd48c4e0e5980da3c32a12c646f1cc127f06eb08b22808de32e780eb4c2b2a79c8d66e211a55b0b9533a22cb04e244c0b268da207d46c60a67dcdb169dbddfee6ef44d71189dbaefe9401d7528a3d906ce6968e66b5539c09ca78214b1a8b4aac01995b8639a52e1b724e3d636ae330fcd927ce0170adb805c86d5d32180aac877d18405e700974dad40344b2f3f8f560e04c976c79d01587e2711afdc57de6ee53d771696847b163e1b44619feac9b023df3bc6a23812ae80f8654596e3a43dc16519fcca9a7b230148d430a629bdf1d3587952b39479c72d4af3c9daf74871322cba60d45e18dda2e33c8f5e885ed341fcbd5788fc3f74deaba726795c63e64b38b0430734d8bd52b7e623a770ec40df9660d1da6c820e2593cf8dd2462f138740c32a58403c79f41f1f851a9c618f4bfc0f28afcccdddbfa5fb47fdbaa78c117196049842e306247cadc9095e2b8b36efd0e723a03ab363d0109fad413634ba57f76fe7ebd43c61dcd2738a94dd3c3fa64d45eaef7a5a0cb7b557a4af7ed9e0aef6035cec3deb5b754865f999d2cd1651fbc0c76bf88a6931002185c6f0ea72e22e41d0fa1d29d65f87705a4900d3778b2f7e1da3d4a183028bfc438088734d354ba1e3bc8d7e0e311e46d937b24850ff58b7988f64ea1c24c34097a15cfd760fd99359326eca211e5f180c2c7ecb2af6975f3e09d94d26131e4b326d41b1", "5da68fa0b4d5db599ddea413d51b3d1d16837f809e2bf731f17a9473c91304c128026008a1c41d1148d8c40728e596662bb789d2af11092f0ee180dd5f707a51ab3a99b727d6328a5ae823c3b1bf610a85566ca7168aa21e5e27efa3dc8ab7036defacceea5e5671ad6b399c2af4bdd58f6d297e25683a19f07d97bf370fb0a68eba84c42bd009beed92ecaae65ef7f28d4a2c0a6b5aedefd6d8c7fc079fe36623528bf7be248cf65e776130107f0c9bbc3a000d2973c1e2845ef99402fcd03dff1bd73368e6a217872205e99a16a95ccec86b300b3617b6787f92286af08482be4a67680f57cffee5498c9861f030667ba8b79db5418ae69ab94936db0e307cbdbb3e53620574bfb50fd809cf7958c497b63dfb7cabca78e26bfc4597d82f27792d0fb76fad36e218f7a6ea7e1e67b6f6cb47a423cb20e6af3d5f64365f1aae6e4cea73c767880e51424047262242002eb6bbd995908d18d828a3d3420dea51bf19b211453f285b23ea6a07af39ef21d0dfa2f71e35a61917e5a78a496c92085382fae505a63e74c914090af129d0e66b5823fec2b9d4ee8a5953b605621b0ab431d83cf7d1066620f4183d3528dda215856bb290163467b2b2f7f9085a620d23de372ef8c999bb657203d930bf5014b07f8ca1dfa00bfdddac1af71a8e95a96b4de31f59f68227075bd4fd9d4683d1bc0f75781061fb2388b7f7079b384114", "13aef54819a6de8fd6108b6da1c0d092f958a6a89505400102462155f153e2f3af0d8ce29bc19cdca9c12e6d22dc7db26de2063f32c57cf3976be5bf3fd2e5a401a2ee7284073ed7a44284138da633a1153bfd58d81dfdbdefacf71b88e336bae2e0942874df8a95364901d7261a2f0e55cffa65e3c73159a4d046d9258905b6f068c08ca12d0a10c9ad320f6159e87489b4ef58132f7ef4854ffd9abe3f7c1d50890030e54a9080c9c92a591b069d64be0193bd3cbabd49105575ed999e0747bc080f13033811d3a886ada1a4040674ea220e482beca917da5ca85f245e7ccf3f07721c8e3b5e8dc882cc927c0788f39bda574f53e3dca5b7964f05d546a946308f3ee96693a4d7d07c7be2d76ea4505774c9ecd57184c8707ffcbd36a1e5e3b006dd2e1c7ed735c0d16c66f98bac94642c756ccd397eec46ee35aac3419c23a7fbe80785faa6b1475beee102f806d8b65a68cc0b930c7cc3bf8b472ef4f20867971a9812d2afc9785c73c7b39cecc5e1085f03d09252073249d5ce1ee1c10e23431f0e862927c6024895170eac3a3b381aa1fbf8a25cd78f38a53d78b290bf52714067ec8cb238ff7539fad8f71de758d109b30adba090935b583f54bdaea80711382d0dc86273973a3222009f7025d017ee559782f70e7f9d0de37b22ff2a6e15dbcb2b328f0f1287a3415a973029ce7060cd74e6bd470aecb1552cda582c5", .None}, + {.Add, "-7d741da143140a735ee4df72effe2287bb7320d152c4a6f05142afd354408a6c8bed4244f9d50022c8d14d4074c569c3f92cd7b591e5054ff5bddcc53ebf85578b98a4bc87e4d1c9dddbd6e0cbf251d1e37040498b3a888991c0b6b35f3c6864f0a8a905d5bdb064ca1f1bcc44107e47149211d6f91e6cc6b5f4e33771323ac1713fe0fd48989f008fb0d743b25202207c67c6cf8443a393dfe1cf1c7df3dadb59b574f1a40c52097be5e24dc1365cfcd93d31ab221c565b3b90b680c5efd1b946e38a386c63b9450429a199ec8f0f4b72182382bebad0328eb89e9dec65be8facdf04ef15b37254cf187d3ff286069408005fb69a215b6ba5a5279c5f6f3a8318f191775e7cd5159cbb2c04e491eb4d774e6168ca1078f8d64169d94567aa69b59e2b7e349d751addd2fdb692684535dad4c01141257c8bd56fb7d27b4dd5bf624e18ad17030254dfcdf1f449f4bc1bb1707b1a23d7335e702794d0c564235aa4303a234aed60e629abf0126cd5a403d684648dd7aeeb620d4f52256da5782555ef05602e839c5c0ddbfbb3195619613a2719ee6c68e54da9d03a6e4cb34d010eb721ba1162ae725aec387ef0de5d64945bbc7eb94d00547380f25e7948a439452746c071d8b2a63709d6ae10f8eeeb7233d8f31cc9034bbc7045bf889d1b4b491b4de40865c3de3df4a7e5614622c7033ce89146c48d9da07ad5c025f7ff3", "e2e7319afb80c28d2264bb36d6603c18d17b1e9f3efbf1f48cca343262f9c4e417748d2904591309f74045708541afb16f4a75f646fd0db00b3902941cf234a591cb727d0253369fcd0dc1c85091928e096926f9a89670cf9097182440aebcfe47d34ad5de268dd77a18082ea51c368a491c7d1fa3b37b438a853efd8746031951ca8b03dd2e359e9fde7d51b2ee8d9f08d4b52244280a6091592835bb65e8826379da7e1366d91c37d27b4d7ceb3509fcbcc44e850e4be0308fdaff0c96efdbaba8d48809950597d90cb77bd4ff80525926d00cd29d15cd91fecb53c79f75c6a7659dc4029ac91c7d575b98be67916b0feead6a4c8dcc7a0f6dbab98aca7de87c9740bfc52dcf410acf1adb7a72c930edf6832b6436d4094b32f30cefa512d0d284b14df2dd6d4b9cdcffd50994408bd2923cbbbe8aca2f69f096b3292a070451a7faed96fe14cb1efc2f91d85a54ab22e7115a5359faf3b81d3670fadab84a180b81ce623b328c50bf3c69e8135477ccbd4ead834f7f982206be946ac8d128ee3025485ee4f7b5e07ae2e62f8a901690174cbc10e89102af069aa92f6de2a55efcbfe71f152e90126a0006220980fc8e2f48dadfb8ecef6c5689fdb85818fc1a6de1e998a2cfadd7488a2d9261ae464adbeb260421f8565b0f899d4c997be9071f20a7f8fc4a5ccab9a91a8122f8271097f9746760b81d555121c0bb68fb01", "db0fefc0e74f81e5ec766d3fa76059f055c3ec9229cfa78587b609352db5bc3d4eb5b904b4bbc307cab3309c7df559152fb7a87aeddebd5b0bdd24c7c9063c501911e83139d4e9832f30045a43d26d70eb3222f50fe2c846f77b0cb90abaf677f8c8c04580cab2d12d761671e0db2ea5d7d35c02342194771f25f0ca1032df6d3ab68cf408a4abae96e36fdd77c96d7d010e38b54be3d027535b0b43f386aad4adde832ef92613fba0141d28a0d7cf3a2f28f133d2ec867a7cd6cf970037f2c0173a9be482ceca0388ca1d6236368f5da2054dd4a6b168ca69134169e8d919ddac97ad75113f91f73065d3c4bf3f3101cf6ea76ee2ebb6c35513683fc4d38a404b0827a84f4601efb103681b2c29aa7c16819d14d795cc79bdcedc6f5b4e982a372ace960f9395f9eeffcff9a06dbc3874e4f0baaa787266ac999b36017529a85b831962c58de4a5d0ff507293bb08e967d009a8b11c87bdd11abd23ee8476146dc87e2c2d8c5c7dee247d68c145fa378f550864a5d490e20131c97213ee79a698d134f25bfcbdf01f9d232afdf52e807c74db1d2a2202add46997024aa2add54e114dcb7dff03a8ecbb3c7e32fb9b2644e98d12f4241cea251e7ad7d0c38eb8861b6d7d9185448373d7ecc2b1521f5793b8ad96d25568219f488541540faa34528d6bc9b875ee1ee6da5e9c2b0e95faa0642aeb52f46f437b497464b9097b0e", .None}, + {.Add, "-74fc4841ac8f1adec26997e0b214af6c4ffba4511f4d236d087cec9ee9a00996d8352b8a1c411d8b2ac5995cd07e8e34b93adcb49558d857ce09ec6e927c279e60673fb411c845ff354a9802f2cd7688c30f8045bf5e5bbf259a3d7fa73dcd078c1c018b2f24f6be1ab513dea0e9a1d9b64e7be5ca3ff083fe36f082ad2c369ad5abaa739fd5c975cf8f138061d6c82a43bc959c0559a8747c42288581ae29c115fdcb10b530c1200a3eef70f5263c5cd2b5fed33965062ca31a0a723fd39cf650cafd601181653e3c74cb8ad498d0849869641c1474b4ec23a250265808fd0a55c798d5b1b73192517a459f1221e801db7650694d0c308c8193d8e3e1f8910d2fb38967e66fe5f17df09b3a9c23da5c4645868474671693a5d61fe6483d03029105a28ffa88930e0cb9d28578caad44318af56dd1af0210d49ab907571ed8d99cd9c7f82e82512281fcc93fd77e3a432dc6d6d6c87106cac4faaf7e9c4b1f6cacd3244608c91c5e089f9bdebe4bf50f16aa53736148bdfa71967ada01208959b1ad326577a45bde192769aa13404458fa6649b072383448beffd6249e206156c9ded34c188416d4448a839a5e49174546ddb3e26d3143e9566e5f0a0e98b4662782990886a27be6554bb0351785dbd0fe72f42a6d0b6e9f7a1028de43919a7b0911d400f2f4b5e8bd33ac7a2c95a6836fdc5924d69529e1269f45bca5a09a1d", "811cdb4dd53e3478b97dbf6eeb15a2f7681d23221b0973ddf2cc8265fb04ed105b3fcefb20ca30949cc33e59c210b9a5eaced3ca8dfd0cc634e7261896295900ff46beaa114ab4b1ca1543598b86023bdfcf6822dca0f50091ab25725a3157b0f21a99b0db62c460c1f8860504cee1dc3d703c71bfe91e45910a44197ef6907c8096df0a793f8ed30d18529b75cf1d0ba4ef722715232bf14eb31a97a9fa562fe6ec9e1b332c7da926f1a83ca7855eff5b57c21dc8dfd2695f204f3c92efcca94b6753de65eaf96ac939f1fe770221d3a453becd620ea7d8c130e951e70c98680fe95cbb851cbf24079b0f1c7a0b94a943d4aa461d759af0a1f9967141cb478bc1463393080cef8775bf2b46394a9fa3dd3cefeff62a54b0da801d07ccd3fc5928f42fa3d2b436f4e061fe9eeb12e81e790f977c57b66837d224af57048cd82bd45f9139e83c13c9e65acf36e95139637188d2cbd7960a5ba7a3134623bed3525a63fe686b1d253d389d239801355b523dae5f5296233d7b7cff86dbecf272532d06ac89b570ea3ac2a4569ca1b9a12d32fef88b1141008e3cfafe4236ec59d38b28f19398b163861efe6ab067fe64f9b7d03c52843f247c77e3d4c6a415e0d3df2934863b8849061178c12783d404c133d73cad184eaf900ed3055a5b3a3d9ea9b141b603ea40d47a3e93babbdc061a134b4073fc74ecae204316ec129c84a3", "c20930c28af1999f714278e3900f38b18217ed0fbbc5070ea4f95c71164e379830aa3710489130971fda4fcf1922b713193f715f8a4346e66dd39aa03ad31629edf7ef5ff826eb294caab5698b88bb31cbfe7dd1d4299416c10e7f2b2f38aa965fe9825ac3dcda2a743722663e540028721c08bf5a92dc192d35396d1ca59e1aaeb3496d969c55d3d893f1b13f854e16132dc8b0fc9837cd270f212284c2c6ed0eed30a7dfbbc891cb2b8cbb25f22a288a1c34a8f7acc3cbc0644ca531c2fb2fa9c567e5469942c8cc52673a269514f0bea5ab14d99f2ec9d8e992b8f039b5dba21c3e5d3658d91b620c97d67e9aca7685e59dcd0696a642065bd8d5fd2b67e9192aa2b219d0995f7ce900b9d26c54796f7696b81c33e1d34a9fd218496f95697ee8d13d82ba3e6d3a82c1972483ada4784a20e86076626fd89f64fad6dff523785c941b9b9c2a7645e05f711d2ff2043c1fbf50f250390e2a863c78773b3e5ad90da22625408df2ffd87b942e9664327040bdf34da7f810b690c01ebd1e8f97b597a243dcc8e5ca97cecf28e795cd43898aeda9f08cc457dfb281d98cbf87cc14a1e47802d4cb1da73e71609b54db470f28870170de093217575bc957d2c6db7a69b7db4e5cd1fbc2d10f26c4e28f035644882ab4340f094c2dc7c17a8a323a09f6db510f58aebbd0ae7408f465f96a36ee74f25dfc2ccf9a3d12f6cfbea86", .None}, + {.Add, "9da234f611325c2cb9129f62ec102b9b73e9266644f2d5206ee51447803dfb9fc5caaa6c914fb10ea438e24f3eab303d7823f7b9787418a0a02bfaacc32cce7dfbb1718f1509f4dfaad965cc581f080038f639209cce296fc1a5d2c7b73a928ef43d27a22d9b9d3d960e852229951e929dff8bfada9ca6f6f85a21a78fa68e0709e268e1669f1cd7b875981d9386a064e781740dac840a100945d042a8851f7f2ee76896baabc113233736f31f75c3069e43b1b968a758295497c3c58a1dac2bc7908df9147ee36bacc0a1278733c97da5008ff275e385cd1f8894262138324e3be70db1f456b4dcf840ae6053946fc8d9ee283b7eea7b7f722746637e3d681ba52fc54cef78f1ff01290dd5ecb450bcd3cccc728b7349018af7c291869f26f82a63c369adcff32097ca42a3704bcb96c40441e393f381ccff2a4ac76a08432eab981f7ea6d71b83a62a7bc16575efe4f0f35ae5c7ab9206594732bc74a1ade3d36de87552d8db7d796e9a5e6ae2975514ae570002b825b66f4a1a1b140520560e119c87c9a97dae0d6f07ed1d9a02e013d6b80c825ec9e846dd285a1b073530513a368ca412c8acb6b4145ff55dd483b4a120eb9523be0524a17924b55616e6f8faca7c4ec60856c382cca3564d815a14b50a032181fffb83f0781a222b77b0a3c4b881a000d1efc7116e1276df29d0a06a23119b6724a95c5e3d91dab7b7ea", "5222b360275abb2be7d2860727d1bec5fd80b6bbc58f45e72af94392668a4e0587bb22a27266fe329c4215411731ba0d61cbb73545f48de78b9964cbd3fc71c2d9fdd0602550adedd59ac52ac683d9adf1bf9bfa8cfe26a667db972e88af6a7216ce827b3a68069ff7e9cf3772e69bf0b81eb22fdbf5b0469e458c791293b12fb4d17bf95ecb6ab40a3c45c370bc2ad214f72d7808f5c638f8027ebb2b690187841c2ab0d1221461d6eac2a74bed29ee707580357c3e86bac4a6f310099e173e16ec44f3a2e4e7f0bdf009a296f03be17708cb9f5c73ec7e9c723f7493dc3000e9d01e4d0780bce55de515f0179688c5aec2ee070e5a140ddb6b4103f57f86285247fb1fd9b18f57428af74b04815fa8eb912f3fc5c96da23e5115d6358dd4bc1ce7c45a9faf3d3de491199c198eda0365b8e1d594f4eebcf84c0a6124eeee9cd1cac6b9af0058a614d6c60c24cc70771af876641aff6b8f25ce756680b1940c2acf9666ddd35fe435fbb7d99af6b57128c1eef88af20463c87eb812f68f8a05a37fc9cffe11399f3721f357f27164fcafd25a1729556f9b2135ad8c84fea723a0642ead24545d0441c7e2b200ba6d334a9d52bb44442c05e5be2f77415b738951ef173a4e38dc470b7fc09feca1c091dd8dcae1bdb43f748880ad2c87e077a762633e2daf5441c5b3112c48fd28f1be14994659922a18694ab6a014c4817b1a", "efc4e856388d1758a0e5256a13e1ea617169dd220a821b0799de57d9e6c849a54d85cd0f03b6af41407af79055dcea4ad9efaeeebe68a6882bc55f7897294040d5af41ef3a5aa2cd80742af71ea2e1ae2ab5d51b29cc5016298169f63fe9fd010b0baa1d6803a3dd8df854599c7bba83561e3e2ab692573d969fae20a23a3f36beb3e4dac56a878bc2b1dde10442cb36fc78a185b579d04901484efdd3ee2106b30393478bcdd574fa21f99a6b62ecf50eb931eee4e5dee4193eb6d593bbc369de7cd2ecb763cb5c6ab0aaca1e24055f1c095b91d257724bbbfad39ab514624f25b72bfefbd771c25625c4506b2af88e88b116428d448f8d4d92876773bcee43f777c06cc92a815643b40520f135b065bf5dfbb2513cb6a3c948d867bc2cfbb4474b87c44d7f305e7c5b5c3f89daa59a29bd23b928e87089f77655288ef731cb7d62e63855d77429bb0141cd8a42605c0bebd149e2aafd957f15a822f55341effe3d7edc30ac3b61af6a523805d94cc63d7045f88daa2a1a37c8d22e0a94aa5bb1916657c7bab74d4490fb45100b67dcc3a91223abb439836812d5e6a005dc53f19e6539c86725b0f87bf711f61841b6ff3e73a6d967ea0b0a5fa89bf6b18a704ae9e1b69cfee49dcf028d4342ef41ebf242d4e4df363f700c712546aa0bef580627f6af4f5513b57a229a5b74081b8eb503696b2d913d12a714dda69f393304", .None}, + {.Add, "6c059a9d8de81a49388654f2b25be047997812f4806b76a0af16a2cac3cc7a1e63b7207df74a09aae8786e0348d495d61332863573e5be4b2f54f44a1198e07553badb98cb2bb62a2a74074fd9bd4141c2effeb586d5620aa2073358ed690fbf52ad886e765d800c82c636f54031934baa011932c2548ac2eb4204118e529099931360456b34af1beb60aa5679d4e1c44f3f1b1e2c84dc67531846cfe386cf3a95cf1dc9527deedb4987e6c0b6afd3cc5f58e26f24fae03a330c68646c0be52c5ec455693646ef5c8b5f11df3443419e6eaa488b230c70078291ddb932fc36a1bcea38dbcc68ee55b2d3e5b66b349f86ac320cfc6857f04b681bf78dafa5e5ba4ccfbada61c52e98a7771ff4af08cd1943733ff778ef1d03e7c7280adae4cb241183a655a0e69dcdeb0d97ef6068997d847f82b6d688eb3ca256379653293d889193811b617e4f098b67d18b56c5c33aced2469b92cce53f7ba2ad23a5aafe9ab49405515096f0e55449c266fd5261cdce2ae9ca8493bb28358d47e884befcf146a95f2c3e47200ef9b81b91c4b1d28693a352891ce0215d59e2423b6d2c671cd44e4ca4daf73aacfe21068c9c199b0a2ccc28faa4b83bcc97d933631513c76dd64ceac97f486405102258bb711209b241f6a9315105ddf9817a5061691abfa668d4b96b042ac39af213f099b0d7a292902176d7882db6687419f7fac78277d9", "36d6c7210119db6c1e4c70f9ea5f9ed6ca829413424654de251f3271a15707a73356fcce233991e8984fa790af7e62ee165a7f3fb77d2bec2d5b30887f93645ca6160ecff6d6da5220a8274927608097f252085f289b32ce9143cde3f1ad8bcbbdf4203f3ee3faf5d4c1545a199e9a166d0249ec5ff73c323f71f0771ce910bfbe219a4f079fb56c53d996a6988f394ee4486579e091a706ec097107902431b273df2848849ea0299008b079c59426aa5ba7a9dfa2ecb0773db29cf6c844cec2669dc3b044f02d5fdd1609876608cec63502fe86e821ba88da07b651467dce10777e31d1aa8297b1dcab98369369b7ad2d3d5016e704907c90e18718f940ff9ea27363c37835928ef2e815539c27b0fa4ea7506815923b5d9ddf07844ebf1e471921da79c5c2277adeec2c4ba82a2017bd471e137c2668b759e0cdf6755ffe65b596e3414a3f697a03299db78500bb23f29132efc7f94125201909750d7e20d01e597964a3370e3123644cd7c4cf098c1b276a8638ee09073fdcbcd21adf4c5cd1faee014fa7ac752ee107bdcfb0c713d0f05b935d40749fe17007790e2c2c7e57d8c1da74992473f83606434e59eda1b6fa4f537f973736d28db9f5e50d1ffecaa881e7e3d453bd38996908effe052865265ed804818be7727ff2a6c0c789bc7d785d5b6aea57c1c6b2438a79c11b16188c4a2eef47de7d7f5695c659826929", "a2dc61be8f01f5b556d2c5ec9cbb7f1e63faa707c2b1cb7ed435d53c652381c5970e1d4c1a839b9380c81593f852f8c4298d05752b62ea375cb024d2912c44d1f9d0ea68c202907c4b1c2e99011dc1d9b5420714af7094d9334b013cdf169b8b10a1a8adb5417b0257878b4f59d02d621703631f224bc6f52ab3f488ab3ba1595134fa9472d464883f3a40fd12641b13338780980d16836e3f21b7d773ab00ed09ae4611d71c8f04d990973a7c43fa76bb008c4ec7e790b170bf055b3450b3eec56219197b371cbc68751b669a4c1064a3ad47120b2e2a905c99940a797a04b234686aad76eb86078f7f7decfe9e5733d96f5d134f5c80c7f8fd7ea6a8e6e558ef431e9dd9fac1279a5f35484b307e13921a905f8e81586185a62f8f29a3e96b2aa580cf66a8c548c9f9c43b0892b99541c6a0ca52af53f3fc37058cc8893bee472a645cabbdb8838e916f42dbc67e5ec163798b5ac626649bbbb698b3291f6ad2ed7eb5f3cdff1677ae0f3ec2216b59e9525450bd81c42f756a04ba9f9e494e18a44d2d8deecc842899234f9462999a6493ae1c7a2095fd3b5249b47b58939b2c270e7f4f905f20f6570ccfea7388abe3c6784e244f73036a66ed58fa20e76ca0f56cb1631cb7c248bbc1c461100edaa71d0809558769e0f3fa430829e24962e64d16c66f151b5cb8c634242a98bda8a8adc106777594e5f3708dc12104e102", .None}, + {.Add, "8e3853f9c080aef42f28cdf70a7fecd2678396d753769cf9f40de45d39af57562f3261973fe662823eebbf8295b4adb86bb067adf0488bae9b62f63fc26c86dc86c1d384dc1ceac458e46e596293cd22e724a9f68ef8283047f8237cafd7c39ee898a4e0bd72d8129b48580aba964cd4c92e9d1f215f4b280f123b8f9e99947e0ad3cc0eeff423b8d0a6323451ea8edd1a282e82890a3a77e1197c241471bdf2ebf3dd8b30cb87c17736ff23147e197a939cf10bddc664166d7189dc1d3ed52f4969f7a466c8eb01c65ec572c29b8961bbd8c177f66ca95602889a837ca0919d72445b0352568c1b0dd54f1975733315073691f28738c7f12e52468c21fca66960f06814b9a66cc764cb4fd3d1d5d4a9864b55a3c7c56de9d6c3d778902d5aa9bb931a7eb9c79ffeb69e4c4787fdc8eb39eb2f5515f9bcf86822cb7cf1227f5beb3bc748f20a03725b40a3a1e3030ace5a4cb9e318f2d7d76ab245af7e88c8c6db73cd7eef48814ae5b106c1506c27758f2350576d7905250d39790ef3c9ad930ff9474300621bdf8dd54657c12c9f42453e6b79e3c29da8699c8a46a8b1548259bfcaa90b37cb413622e2587ab3420c2db28cd4ef29275c5895a6758e0142d03fb751f6fe8c99b6702b5874a3a4bdc561992ae827f61d0507a33d4be5ff1822abf492b6b9d404ecc68160abe19abe051fee8c6b7dd04157880b323e50a304e4", "3b196f9ecc4cb03900f5db082ff27c1c7376816f29e16bab588300b5db98df4a8f757130dd88884f86cf48790d900b4a970e06cf4a8457f7e5b4f0dfb02227aa1694d5fed917d01847203f1a5f4b0373cc60e8b78cf778852a3b95e45c5795629552a181731708965d8822bee058c81bee1eaaae80466782800afe900fc00fadb0f17a853a069c6fa0b7f917ccc098b1c9e0d605d0fa91b84f5d46c22d6707a5d6ed36621a7a5fd4fba86813c78e4f8c2c1b0a8035aafb5c07935df4c803d8af3d6b6859925a6cdd3248d1bf76226a322382a46e3137e7f4a51e34eff0d75b688eb38ef1742eaf35714c637021b400e386027fe913eb95d2bdd922122b137a7a4859bfee31cf2fd55c60a27d5e2c9bd0e54300fc8408f5b3694fc2361fb68a6499547fcaa51319fb57c30ce6ce3368727bd5552c59ddbf71a8389da0857ba74b821bc8335459a4f8f4f93e0f580f469eb86106b33ebbf40b5a1863eea32b8985f9fd26adab41b608c2ba23f9e53266a1797478e991f4aafa367449906af4c9e27d46351f88b3065333fca3edc1dba0f3e4ec7777fb6dbc1de9d4466442a6a2f636cad3bcc1f6703a2beb0e6d14e6750e4204b74f42437ad75bafde86df5ed3c69323967b5da8b434da63df893dab615dddf31da5f8e52170afad68fab19f9915a45917d926735515b1cc29b4e149a8091f142dabfe5c0d58c0b366a32261412e", "c951c3988ccd5f2d301ea8ff3a7268eedafa18467d5808a54c90e513154836a0bea7d2c81d6eead1c5bb07fba344b90302be6e7d3acce3a68117e71f728eae869d56a983b534badca004ad73c1ded096b38592ae1befa0b57233b9610c2f59017deb46623089e0a8f8d07ac99aef14f0b74d47cda1a5b2aa8f1d3a1fae59a42bbbc5469429fac028715e2b4c1eab278ee40904885a04cc303076c2e641d8c598c2e113ed4b45e79672df6736dc0c6906bfb7fb8c13715f727504e7d0e542adde86d55ffdf92357def8a7973238bdf393df5b65e627a4914aa7a6cf736d77ed0600f7e9f4c6853b507f21b289972733f88d3911db9b245dc3ec2b689e4d1020e3a94a2802eb759c9cc12bf2513002707a6b8e56a04bce639d401399aeafe3e50e54e79a495edab9fa0e61592e5631315db5c084816fd77c6a105b691d769e26a76d578f7c4663a86b5039e1b13b12516d12adc09657aecbe2c4caa99e21b4524cd570f42c9a8a3753a86b2abb359e8e170897c940ff6db01f43adc29f5ebe77758d3f7c6289152232c1d1ea45830840362a2ae2f1df3059c65370d0aaeb57f778908a9e65cd2e3b7b620df0c58f99b71a6fb74424316ca233b44584fc6d601696d2dae8725c354deb4a8f37fde1501f233f8c488e20db3e75b750a646979eb138504daa8fe0475a02784d8a60c2e4660e3f02ba177c2c4eb048be98e173044612", .None}, + {.Add, "6f4d6b8370ea8e2876411fe878598146ab5e11ee8c425b4d20b86522a2e2fa9ef65e5b184832fe9874ae1eb2603ce555a465b7d31b372993e2dc3c6e05073cc6bef9adc2c20865cb30512ad64ccbe3af0d2af6f5f18b69710d97ed185f24312acbe2ac281d4284240922827d01447f8cfb5d043e0f398ba60a289ff9e61a4a6b750b7aae1110647e5f9f9eda80f82a82bb27d020471d3a115542f8981569421c866c488adcba27af2124090bb77a47818ff754904a2162dc1a38cba0bc507a07e797f4a945f9a0c7e7c3e7f43c60c66e0fccf2c08a07b8db955e42206b6a0cda55d0536a5afe582d4c8728dc8a027a8de4ea380b2958534cf7b1a9d5751363ffeb4b3034af572f482c8b8cd58b4d548a9456de1d869cfdef3840f2ed6224f105047e0a1b805bef8086608493f205e43645342620d979b78174c4f79ec7f44f09007e96712ed0e3a64cbd90cecc22e7b9d05f63711ae69250640b5182e9be74c45673ec8b9b852e9cb759466811a4edb2df76a775748126a3b9599d38096580d8bb8399c4d72738e7546db3a114260e66e38e678dba249c78325da7668236d648ac4c49390cdd302d27458e4d9c1b65e492891162f990bf2b06528d562b73a95b0c9f65491b6c87fb525651576fd0247057ae9eeb427351f290fea0d6be4b632bd04e100297b0a51a55fd779059770a517f2c119a064ed096a3d9a2396d1a35d0", "2dc657ba03e738905b0d360e01deb38f6f0ef373f68c721061e931edc73f5b19ff0e8241fb726eda0463b077b1e70ca9844307e981b2e12bf94dc925699ebfa28ba9d753c66163d1d62d5e5b33133b02f2a8f1098854b5890cf42f8cbfa9a72edfbaeb71e714339805dcad4cc5f59ca73b11a4efc6e5ed0c867e08d67a8d25ee0f4141396396ee1e8614a2516ea3399e516978d9b7bba93a1b03140204e4a2000efd5ef23d93846421a0e9bcc433e6cb522608271aa81cbfae66e9bbe120a1aa32554bb86c57331142ac78dd89ce12192cf30dbcfa4c4efe96c6f7ce6325457617c6fa05312658a7503db1a1f0398e33aa25f9ed4ee6af1d5295f41071c4dd22c5947111452cf7687046e95fcd7c9183fc42a24f495087c8823ff9ae0bb160c4985b711dd18bcd0ef28d5d10a47470c9ded9d74aac469ad1b574f58449136cbb8c8b1a62ad2dccbdd4e046569bb7997cc158fbbc790a0f5f1a2d5282f34075382a6d3f187fe761b98d3f364ba07de746ac4fa2c205d02668a65128b06b4e0f84e9bf9ce06d00ccc70d53a5244577c5e3f677f6110972a48fa6b04633b2d8b8cc4b63d46ee69e16579562ff1f18f41c952a58e7376c0d9b3f2e314aef6007190df76c85d2f76ba29adf2fc9e9a5dfb2e2beb0a0dbbd7ba3b6338607644b77d5f29b46fe80d101639db44b051cb559e5a8c10a92b66b4a422bc414a58cdee7ef92", "9d13c33d74d1c6b8d14e55f67a3834d61a6d056282cecd5d82a197106a2255b8f56cdd5a43a56d727911cf2a1223f1ff28a8bfbc9cea0abfdc2a05936ea5fc694aa385168869c99d067e89317fdf1eb1ffd3e7ff79e01efa1a8c1ca51ecdd859ab9d979a0456b7bc0eff2fc9c73a1c34366ea92dd61f78b290a6a8d060a77059844cbbe774a7529ce5b4412bef9b64210c9148f9fed8e34b70460c9a1a4de41c9569a77d1a4dac1342c4f2c87bae2e4ce21d5cb764c97f9bc89fb55c9d711bb219ed4061b250d3d92a7060d1c62ed8873cc0007d845407da2c2539eece8f52506d974d6f8c24b0d49cc4da7e7a3c08c18f1031f8783f026a4a479de5e6d84122b0dfa145f48426b09cd2763558c9e60e9099806ccfed85b7ba80ec9b6dd651c99cd97b3951e7bc8f78ede1a4967a5500240dfd6b85c052532a39ed231107bbc48d09b0d3dbfeb064219dd72567da813691b85f2d93f0a1af7e38a405dcfee9fc80e12ba41b6c905644987cb3b222d4f98bc64a377a514d0c5faac5e874b3905da54336a5442805ae61c158c5599dd44ada065d9ec3974107d90ded9a350f8f14f7b01da7f37b4684bca88d6cb50f8279bce1f89a659e5a6a3483d8458b7ac269040beb1c12d82a9631861b4115afd753165f3fc6ffeef5a8c484a83b09c3391e6b950e8368b208b80a487cad0ed0effa4036a450719912c267ee47c64c022562", .None}, + {.Add, "230a96c71bcf127332a2380fc6f09941b32a7fc56447fb51de65784c3fed45db66709f08b95fd8cfc1a4ba09356bde59931e2fa8becc21a6b71e41e45a48f83a3b326762fe259f62f7d2f8b46c9725c91eb1bb3c073f16ff1052103c07c2907fc1ab816019aae4f0910568c9015164f1a408f01dab92285219c664faa77bc93fa0484e0ed1f5513fdaf967b790700aad66509b128225e85ae4505a12f6e3f28928fb325bd4c8da79db089160a38cf4b9e52c7c9e4a150f39288bbd297c64d425ad3ad1360af53a8aa05f8b4c9c6f39f19de6eca9a223270a96b7079a3b965c1af7053f062270d1cebc61991c4cc52a0997da99b4df20c550ff6e1a6d5cfeb96c18c42b3481fdbd226039e1a85f1d93fb481496f83bf3bd5bbfd6cdec56362ed123a6a96b86c2927f25baa49c1da26449b022a3296fbbb22886170169a98dc35c41139f5ba78c1be2bc21e05026250545091c5d92e45d9ba8deedf3793effca98fcbacd6f8380f363fa6a2166085a9f7b83c26e6b8cfcb167adf88e821d25df0e4bc4e0f131ffc0906baf57e6e5e42a6ba176a19a15d93289a4be887b01a787d49cdca808ec35c1f0f4230ee3d8f2e5d3f60611ed58db112ba07122a384eb5588aa8160ffd46d84212c1982ae71d9a263d624eeb5c10d17928faf9b54fbeda5c99ceddc976783dddcf7d80275872141e9770301c9b075bf55a9ab0d4ce0a8cf38", "2679b15919253b66858838a3c5925fd4e752aae3116bd6cf20eb7fcb9e7000f7cac29cf210e22b9beda02c2de776f13a05ea8a301965101fbb68dd50e633153e195042fd69f8df3836fa296ec03683e86d947146bbd8ca3b1eda17ba622a26f5135ecbf4353589c0f6f305504ef1b074e531e872bf1f319186b2d688fc5027363942da1f84897335d4cc97422aa6a95fe3c26d8c097d05aa99ca651b2af550cbbdef097fa1844c1f5295aef545b85a86182619dd8cb240242a7eb757f93ddfd925c61a55118f6e4895ae72df518d0e640d7dd1df6054e001b1ee22b2cf85013f2ccc2e2f4d91866438f8568d95d2261fa54236cfd0634785542882045ccada02cb1747afb951dac3ebb6f8bd5f5fae9129d86a413ff93921863e7b2a385172c4801453c36207c8e0b6e417dda25211b4d4b11be4782604cb26b7d7726a7c082ddd45b7cddcbe470c75a5346f0ec4bccb53c3602cf29d7e097b3c30ba284f12a2143c02b9e987226c26c87212c705fa816294619789650888da95e42e91024ec0d4cce986a209609a4b75ecbd0df612c81266d68dc6c231f452b39f4daf56c0aa5b119b9abe20213ae3e3115d00f1b70f7cf6b59a9de0d23ce400e3a882bc7c4843d5006a716680d698de3f47524ef1df86e67a0afee34c90cbce2945e813819caf9b72b44c0ecb36af7bf1e5887ecffb716ac2f7a9633d1a56a8ed4808031427", "4984482034f44dd9b82a70b38c82f9169a7d2aa875b3d220ff50f817de5d46d331333bfaca42046baf44e6371ce2cf939908b9d8d83131c672871f35407c0d785482aa60681e7e9b2ecd22232ccda9b18c462c82c317e13a2f2c27f669ecb774d50a4d544ee06eb187f86e1950431566893ad8906ab159e3a0793b83a3cbf075d98b282e567ec475afc5fef9bb16b40d4a13089e8ba2ee057e1abf2e21d94354e6ea3bdb764d26992d9e4055e9454f3ffd52967bd6c74f5d530a748175a2b3fed300eb8b1c84a8d3360dfe2bedfc4855ab64be890278070c48a52a4d0b1b5d5a23d16d3570025832f559efa9e29750293d1cd084af840cd653969c71b9c9936ee3db72e43b4f97e64bf0da65be7d428c71ed01397becf67d461549168e87a195a3bafd2ee8ca5b5fdc9ebc79bff475fe84d3bf0de7e1b6f3acced8dc1409cb8a1e595729844a62ef31c714bf34e9c2105cdfbdbfd6fb19b25a2a2433674edd3b10f6d0296d0815d021329378cf6099fce656d0031661b9f0888e72b0ae282dcf2091ca77d409212ab72544a3f3da3d33b3dd7827dc9b647df77227c8b0fe487ef7ee43a3aa55e32bd8062040d9e49ce372fcc787f6bbe3688472064c07a7d1d0ee56616a45d404f7c4f7c1f5c42894435d0b68c0bff064235b7dc49ae40127664c894f4bb392a913a753f45b0fa011e4e86dc4c159d8fc700053fa94e8abe35f", .None}, + {.Add, "ec798d3aca1a51a01655c32a2ae7b9e5e02a6a697e2b0afb2c1260713b2aa083d4d853f5659cd33dfaf00451c4661d8191fe45ea69731ccc52fd7eefac388f47526f264f5b7b2469a9704214e106732c8839eb5f9414cd335a485f6eae13969744a5c40b88f2758565020d9fcc32deee8d6ca931e5cc73828720a50248c66026463a08d3be8b50eb4756ec105b28f9623789dc11e6529f9a7a45f283a7bb2f394ecfb007fc9eead169f9e4f47b344c8b575f9bc4d186576b3a41ae65136c59619c43a818966319c0e04ceda6ab9ba198c345c6552aa8b6d493f54fb6afc56b88e05eb950b699406cc358838e543a86ff7fa53eb44937601a43d56810c591ab9f7729b4567693878a7c95d3a79654ba379944f7423c2f6daad096464f1072a98c9681103b45088f30c37f58ad08aa2b02c838e0dd30737a0079051f64870bb35aba66b73ca67db74601485e59de0537cfb325adf07b3b0b019f62cf387006c139a6e793a719325cd089983b9ae1818e988371b03cc0822bf3b6b1e051d52d2372b7b474ee390cbcbf986895532b5b05be6274f7064f6b2ad8c1f11322329b010254af392f9c2fb3f3fdef5336b6440099e659e087744bca8cfcd3288e0874bcd6f5a4b6460440206318bb4ed2660ae8cc0a64da21e1a39968942a7177d852798a585c30535796f3600ab77c5f01f52bf55f94ea920a69d7dc94e83b9760d12aa5", "e84f528c96d65d0e81ee51a5896c58b07bbd66b3e59af110be556393645d6aa1aeeaec94a3bbc2a7bb9f2541095fb57916332b33d5f5b16526401a48bd985ab1cdb339a5e81a113b8853b83aadabdd3b41dcba891a7f9aa31a042de08ef8203d678027a696a93c65ac4139d66016d497c6c13113f1deced3b4ef7f73d8a2597febca67292f3a3b1aac8345048adedd561b37b5ced7054b13e49f0180d094abe67dfd36c29a7f0693b6d5d6ede0bf1729ce267faa03214ec734f861448adb83555f8869ab7061339d59fab3e283f266093298e09d9b616b735888dd92113c1b148d0bde786887fc1725e54717d70bcb21ae3c973c3f341d4cde9d719d6223be55ad155fa08d801f5572ff442f9f58dfada04ab2a1eab9a9ce823bdcee172329861fd9309dd36d64750c361e6843266473a5c10fd09dadc86d5bfad27c3462549b47a140d0dc636e0dd19c89285acad9770f2a871b6e53c5fdac41173fddb11d13e85904e69d39d5a004a43358adea84e3014245471efadc1cba9a511f468d5fea9db23a441e73278a90a8a11f3c0b1f6812e8520b13d7bf9e2f765abc3f3726fd03bbc0e72e02a52a8852a3e42fb2cefdbb5217d06361c7ddd39d99aa0b3a1fa3e6e1595aa886c60b77d4e19a1905bc2fe098046b65f649dd9edfabd7cf78e4d2d4938e7f2ab6f6fe6b9796a5afc4e10383e6d7103a53c0a9047ade461c2471ad", "1d4c8dfc760f0aeae984414cfb45412965be7d11d63c5fc0bea67c4049f880b2583c3408a095895e5b68f2992cdc5d2faa831711e3f68ce31793d993869d0e9f920225ff5439535a531c3fa4f8eb25067ca16a5e8ae9467d6744c8d4f3d0bb6d4ac25ebb21f9bb1eb114347762c49b386542dda45d7ab42563c1024762168b9a632046ffcedc58c05f3da3114e607d6b852c191e0bd57eaae5ee4f404784fdb1fcccce6ca971df16520cfbbe25bf363b525861b6ed4a7a6326f3a0fa99e47dcb6fbcc11c406c44d5e3a47a1892f8e07a1f5dea6f2c60a2247ec7e2d48c101869d6d6a97c91f213c83e93dcaa62b4652212de1d5f0886b7d672272d9ae27b569f5243f13f70413a6dfef9517d735ad99e5398fa9e426e9177952d2233d2795d312b65a40d91875f3a5cfb577154bd08f766df9f0adce21426dd4fff1e0bb6e07f60207f80d82e12553d2e4e78238d01146c250350be98ed0ff4ba3e6784db7de4d8f40988db66c32708e3c6ef38f6c137b84b3f583df7d0810714c31711bba835d5566af32577fe44a2911367267662526755d49116342ea76f1676dde71d227ff586afa16ca32591e8641f71ae5f6cf97a1abf857d7ad926ad070c23813aedc7adc860fa0acc6e66e9090306c7f10a4fbeafcde8d4799e346330a1d4fa7cb5e5d2cefbed2824dea5e764f1304b1ba0cf8e37bc1a244bd9885996319dd7cf59c52", .None}, + {.Add, "b688fe131296494edb08ee3c0e425fa6ac0e35c7a2962dc271cfb00368f02de80aaeaa7c431140c02723a04c0e6e1ea9b3c416baca8af8a480bb32ce2b33651fe48be5c080a0993db7427ff76da94ddc180cc222a510520cc2ec46434f7718d9aee62e10c4abe08046bac21cdee4c0c79a2ccb22604c05c2f97b61d7a95668205c01a9aca72853cfdc3dcb9229e34d82ee2fcf1325b19f4b62c90d0db18edb12e9600dcefe9293e54bbce2ccee48781d07514f64265d5222881bb34943153882cc9f5d91179e512b197a6276581bf3676a05a27fa38b9b414d64e3e1d426e52c502ac1cfa7382501853c808423e64969543df324d5476ffa211c9e479aafc63c34bca1f83157a060ea887befe8d692c1cae20b8b516d98275dabb87f281a4a9f077371211c73215f72c483f95290026ca25749701814149b7bd853943a06411f8cec51a441f5586bdbb513d5205a1af905c4ba4f048205373dd93b98c11da8d09d4afdad9fd1f2c8546152359793f592491444cb0425826ebfaa32f8eb340aedfe64230ae7b5d5eba5ad02b45a13e2b6e708ff16451045901832fb5a2e228c90acb8eaa82db59640510c0dbcbad8bd7de870519abcbc09ac7cebf668206d7510e6b19163b3a748c11512a277a0272823875a454ab971b69aab7b5c5c53ad981154f5c92233dfc723d138c14c0f34287b125fe7721e1836750ab592623d875133", "bb7c90941938fcb24dbbfdd6e6d994dd1879c306df8b6c434f101817f3d00080aac178a37a2d5a8d42cca8db73f6e74541cd995298cc1ab85cd661d9dcc17d37a4b6e2141bec96bae5dae3a7ad09ee077cb1f2250657f6b677958fc48321207c9f8f5a03ed5bea405ff1ff68c40e54732bf2033d2c08a6f201acc59275aa7c0ca0690673f3d54a4f5b79c13052a43b4cb4f18d39d461a3780dad6fabcbd49b5e0e7d2b169a1166c49e2810075737e14799b037a4ba92c49701f63a499e16bdee9ed9dd73733ee2a04f45e4cfeb1a305abf53e119592ba8a5951cafa2395880c448ef6cab8a0c8d2ec9891883f9e1345aeb8ec1f97bac6c096e7d543a0a70f8dc336b8cb95ce5fe58feefcdb6c80962e3ffb99e1c983d53941d39bd9fad38fc4ae5df763611e403fd534a80872e636058604b5499eb58470f90eabc608d49aad28592b509b25deefc0d9ede2ec7755fa17848c9866419abb952f4d8402328b063d9212935c6e7eb717a6c7ec6c018b16b0c19a75bd8f6efde423659c32c4416910be7ed991999cfced8345006fb0d3682cc28f8ac6aa731fa477a70bf6fbdda407102d87678fc65ae3fd0cb671a050d63982cdda34ea34265df134a184d10412a61cb8ecfdb0f6a8ffff67c8f7833446dc20907154924a642d746f289be18e25551b54785bf89b3e2731f50e8f24534bbbfeb70b80db94f506d2657dfd2503a1e", "172058ea72bcf460128c4ec12f51bf483c487f8ce82219a05c0dfc81b5cc02e68b570231fbd3e9b4d69f04927826505eef591b00d6357135cdd9194a807f4e2578942c7d49c8d2ff89d1d639f1ab33be394beb447ab6848c33a81d607d29839564e758814b207cac0a6acc185a2f3153ac61ece5f8c54acb4fb28276a1f00e42cfc6ab0209afd9e1f37b78cc27c8788cfa3215c4cfa1342c370767cb97d637670f7dd38e598a3faa9e9e4f2d445805964a1018708e0f016b98a11ed92e12bf6716b793b048add33cb68c04746433623c229598398fcb743e6e28193840d7f65f0991a2e7b3144b2304ec599081dc77dc43fccb51e50f3dc038f99f281a520bf1868282eb18e3d9eb9e97849a6b0dff5a5ca9ba9a7e9aaebbb7ae5761ed55346e9ed52e7572e57255cc60f048080f362c502a29e0a036c5bab0cc30ff4c74febf2127f06adf4534767e953f203e7cf7a9a7e0d83d5689bb0f090ce13d8e4465934766c26e366b9de39cecdd0fc57aca6fd552dec26dd1c724d01e08cbc1778217f0a4c10a4014fa5ba7de152bb55211939b331f7c2afb7778a5fad6c199de066d11dbbc31ea6b1fbee90dcd923d4ddcae1809d2f3e0b5f4c125bff40806d7db63b487d20338eb6b35115091f07185a6c9149634c6002965cdd82c24ee611c67a66a6ab10a7f3697b064458123501795d36d24b582a2bd185c577dbea420fd78b51", .None}, + {.Add, "9f9ec4580a906e0c5a840812791808bc59f7059e13c1faf42670500b9c2c784d1e712f181ea22d9e54c76118b54a09c62a7bfeb863dba9c28fc40ba3a5a6054a5b09249ae5dd5f5f10302485ce4fdd75ca627b51545d59eaf09f19ad6211a5a477ab589bb5819c4530b0c65accbe64e53d1a9e376e59bd56468829bac04fa026b6f7ff1748e1ade08854166cec4784b5c62109cfb92e2e3eaac2e08ae2d6e6ee45b587b109fbea24f85e1306d2d5327c249032a47463eb54ae01167d491551caff3c031a1ce8b4cd4af55b1e53a20239ab5faa897cf840f1e2679b61718f0597e13b20372bf0b30e9cea8fd2201a7484ce6df1a05a49d1c02c9338940e05d7ce02e7543c188998ed259eeda94fdd1608eab16cf2047467a165cb7d88f268ad134c11287e08bcc709bd1b48ea3c52bcba8fbbc0a7652820e9628298885c609d965a038363b9bb995fcb952800d20f2b29429d8e0a3f606c13bc31db6284354c4c8e59cd1f2e038dd4f54cbe5b6035bc6baa2c8b63dc7b49d4a3207ace4d8522cbb95d568f1130f79257d6329a4d218627477c4da0e22f8ff5a54cff3d3403d3436eeb4289b0b88d2cda495dfb68a1c517cd0d3d64f972cb1fa2654705d888f3572630c9ad7a759351d943efa9e4aa088b52775f7ce2295cfe2ef753c18b7ed950890be36a632b4cc4b920c6e3cff1abaea63a3f88cfde071dd65e58ac2af0d9ee", "4d88b342efc122f8dd66a219a80d98fc25b65711c9d83d452be2d2f5baaefab95b39ad0956aac03ad1cecc551b0c1c38c96b2755c8754b2348e3183d2822524ddba90adcc7a60085893d1e8eaebab910108ef981000d796e5b091d8622cbfa7b3a35c1843ebe3702629304bddd22eca608c8e00ac2cdf35f5e2e1ecba76c5616addb4a8aa4905f0e7383cd8e932b08ddb2c59818d797e4c9663d8982e338069bdeedd9acc0952419ed0a411e566f0059fd88920c8bc96460e13da8dff66153d010aa41cd2df618d421413454373a68e3e9d8d29ab379e45193e867c06c1e51e9ca3165a25f01cb8495d9a6fad1b6c4dd03620b30009cd8a767e05ce7d938c9c54f476529665b65c5e19fb81d10a079fe205e2a0de94ae13b6e0c33a397f5f9ab18a06d81e298ab09ad84292a2f6153f8067c60f7cdea992eee3a8611176c30827908d0d54af8ec8d62f785ae5c0dfa5c25e49333b9263e400592fbb50938f7de195537c37dd68035dc1adf93e679a1e478492c6c8d238db0c01c4ff4808540757add14d73f92693f9a09fe9d754a17b8a2e3d41b19a93fddce7afec583ae085edd2884101098a5accd326ae41413c2ed8a5e9fbf19e651e030c2c7dcb1a24789810943744dd9d664cbd8b92c7023e1a44f4169c687e51be708629a37987f965d6ea9924e79520dd629df5d510c96de6d4d698257d01d5f819c9bb1f905c5fc9b", "ed27779afa51910537eaaa2c2125a1b87fad5cafdd9a38395253230156db730679aadc21754cedd926962d6dd05625fef3e7260e2c50f4e5d8a723e0cdc8579836b22f77ad835fe4996d43147d0a9685daf174d2546ad3594ba8373384dda01fb1e11a1ff43fd3479343cb18a9e1518b45e37e423127b0b5a4b6488667bbf63d64d349a1ed720ceefbd7e3fb7f728d9378e6a1e890c6130811006a0dc60eed8a24a3615dca910e3ee5685425294432d62218c4b1002d4fb58f3ebf5d3f76a59b0fe644e74adecda16c368f728adc6b1d95387d243072254376500321ddad5781ab6c85d98af27e9332c436ccf1d13961d1cffcd05ae6aa679473957be73ea193522eb9657ee4feb3073ea5c6607d90070b0f96ffedbf48dcd3d7b12c8a5ea6be64b195ffeb5572136a9f72146bb410b29638219f3312ba1850bd1e9973ccce18d30c543904b485ed2e8cadaf2e1d25856882213df886aa53c1c4d7178d6e442aa7af04e2abda0e0ad1679def46af5e502275b7d0699ed785633ccac2ce0a6341343a6b6650c360d1f1e03137c26b9ddfea6021bbfbd8cfd373c7fe02b7b1dba24c13c699c15132d9a77bc8df7cb58805576bdd2413591cffd3280ee28a2b3ae0a73a0d21c84f69b6a51ca8d654cdea2fa1b8c9436a0e78e53759edf923fe6fadf7b575b8dc7d5a9ae3002434dc888a1bf3a3c1e09ffb669f72fa0aa530b6d689", .None}, + {.Add, "de57fb86b663f7f7194429bc8cd7db4c3cd710c199f954036715c82d59d5b015e4a9a6182b12c84484f7bbe3bf28073adaac741e6b5b13bc289b0b199271fe8ea7517bc4103988998ee20d2ce293d8344c9cbbdf143174c56da2642bcbda3f2cad070b55e3e2e9854e9d701d5a3fe281e401c359c965a82bc773c8fa69b6d3267c2e9f38ae1989a5274e108ddb15f78359e410fdc5d7e2cf63d9aa63678694b5c61ecaaab83a78e84d4b6cae340f3ba4fbe7219b4b52a05400a62cae0f5f6e0f5d0d46101b89270961154fb6e6cd3a0d1aaf40a783f13d26be8ed5fe219f36a6aa3c768d0aab2e8e26d279e2644c0bf40015be3e3f534bc575a1d6f2db52398057eaf9ee6996f71963e29cddd741e6c811b03f4dc77599ceb6571f0236a97532b18f5a0b96ef7ccbff3c880af2d278629632cb74bd98bb5b51f19c77955c01d0b41507fd1f4beac3549197c0d28f8cccf4189b5e5ef78ab67f4ed55f2645d4c06fbdc7a7f744ac0d9c23b5a786ae47aad09478bfa0efc8d5f4f1d71540e2c5197423b099f0d150f8b879314b2eefa31b735c4b831ec3a21c14da9f6a620c23f185ec51dd66284f24d454f08bfbd63ecca948d3b54188c77b26f89522003b0ebdd87e5e10513873f39dfc4937204dd4da2bddf314af30458112735d736bc123fa4df8f1ccd7cfe0599f84d3a53f11573ccde2e9920e63a085baff6c2b4ec38a04", "f35cf9b0b6ce7fc02eee2d91237100c9e807210c459a9c28bc8cdf4a827cf18d9c4eb2da1ab07cd5a7876a52ddf978a71f020654cb4f10d037be0b28cf6fffe42b8bdc524469993d47983b5dec54bf1126d029ecfad9b6a9c23d80f5cf0762c7ec0f353b28300495424299e76a905a41dd4cdae57d3292ca858fc1e7deb3ba21ad92cd903dd09876e4397628f65f5681be6d00ea88462610a066cfea7fdcdfe8fafcb2bcc6d0cad9cf64ddb9e01cc3cb2f16246981e6f5c949aecd78e1b073f3a83b1e650f12234218b76719af536a6f06c2fb57ed849d9bd1671ba08ff365fb7682bdd401d001d5355c67b84adecd2fea9d87b4ce803df6f3a7685d452423d4d4ceda1183d02fe3bf98cfd6c187279ba45c2e628f135b774a558b9312c94a7e99435c26bd3b1cc90e22f1901535242a0dbc993423644e32ebaaf2277e9b3ff7d0fa75971cf6ffb65147678aa44e7b347e265fcf266bab430540429a2efc809d8faba065ca54c49e492529b5c91fc358bfefd82a97bcb1d032280955b5c05afd2aeba9473c3ed767683e96dbcf3d19a3fa0f7c87d631eebfefc890d0fc55fce8f971f66b6be41c2eb44053b7e9c5d73af1894ccabcb8a1faa3b210a8f3cc7b42becf3666943bcb2cb044728d1e597ad85faa888d8817e90a7d7cfa0d412bcc1a13ac802c5cd4fbd354036eb7a6300988a5e692b9cf0cfdf2405105d7e6f54838", "1d1b4f5376d3277b74832574db048dc1624de31cddf93f02c23a2a777dc52a1a380f858f245c3451a2c7f26369d217fe1f9ae7a7336aa248c6059164261e1fe72d2dd581654a321d6d67a488acee89745736ce5cc0f0b2b6f2fdfe5219ae1a1f4991640910c12ee1a90e00a04c4d03cc3c14e9e3f46983af64d038ae2486a8d4829c16cc8ebea221c0b8786b6d1754e05185111e84e1e08e004407a4de763749ec11b7d677f0b43c21cb04a68142bff702afd4604cd39961d4a54fa26f10fe203054864752a9b4a4b79ccb6d09620a47c21723bff7175dac28ff5f19eb1929ca220bf34610c7b30635c2ee19aaf2ad923eab345f30dd389bc69493f5020765d552cb9d3ffed6726fd237b6cb498c90e63b60c6db05688f54600acaa954972bfb14ad2b632542a99950d5f799b08079c8ca3ef64a8e0fd098e3d9c8e9f13f741c8850f7d943c42ea79a5d8ff4b76de0801723efb2d856335f9848f17f95542555dff69680dc19970abe548df5d4fce0b03908450ea38ac7aa62719e06af6a320169f0f59e12d10286020b7c826fe2cbcbf6d6bc80af4f590dc04a3303b5e6220da7f5e4848d20c6b5388954443e59c16079ad2207ffe416975caaaa5caf4078a00974d9476e5743f204e40bbc43ea74fb28b887ba237482e8b8ff05780acecf01461a571f934a4dc2cf388425ce54160c573c97c4bdd709e77fb50720335b8d23c", .None}, + {.Add, "141a0d868ca156dd370ac5df9cd5b4706a4f45b65361a3ebed0991da6000873797c9edc0a714be632127a4a4d7a68bd6c18ff47cb7c28b727e092780cc8863261ead69a5afdeb4de72e126204cd4e76031d9106f55e6db47940c287d936162fbb8f9abd667bfd259235783ae22148a92d9c86ab6856051978b170d95b8c8a72952382dec81b4d3ca67dfb4e16a3d0fe2485c8b46497393e581db70492e45e3e71063abe51ab47656c92de7be60e6f0f547f1825ee78bbf00b257fbe031370797f8bb79c1a4cb3a679113fcd33c2e81b55c9d9a47b523883cd7abc962cc560c450218b36027f5d7eb3c7a834c8797f2b1c8cac3dd17cee5630c2c921aeb3c5d725bb6098c0af8d046bce5781029787741e549fe5fb897b468e2f96c0a9b673b20934a40bf6823ce0e1fe3861626e37dca3db9c63743a710ececf6f9dceda4a2c9f018765ac3b1347b577a16262ab0731084ed44ae24ecc5f499821f204054a0ad315ccd65e6f05e273b4f00fc5fd7ace3206a256da19cbf46c84c95a27a96c5d77ddbd5a86d9762384ac8c51d0a3e3ef7c7d68b4ffa604259a86391bde6bfe5c83796c8cf0e776e744e9cf19434859cc4b5164ff446400b621836eadf4dbd12ff6cf699e7e9253fcecb3725764a06e1da578917095daeafe84996a626706180ea885ac287e434c921c7e182eb97853086f79351c5902f9557e9dafcec1cd5be5", "8bf7a382f1837cd5c0b7777131af40997ae43ff8f3500229acaae42d7f6c3693fc58c4a426c1fed27a4fece204ccb3a460780cb0b5f30b6538298fe41cf3c5b41943c13546e856e60942c3a08327723e65560a2f02bdb0211962742e080eca385411d3af525081222a1e192fbe0c0982cf677887c1ef802ff6fb870d7c9eaa68d827ed3a69d12e25dbe4cf84dc4719ae4deb320b5b31a2df7e7f9367a18f3d8087464042b9bff6407e76fd13b02bd3f5aea6b3d43ce08bf3ab1caad008e323c7fa9eefcf78961243495bca16ce7aa881387bde611e06e7771487aed1d1a581088d76e5db73de9cc4df8349fcb4bf4146f842b700ab0926655700afd101100f56e566ceeac9b3fafcf3bce55dde5f6993ab4d60da883676f3db5962cde40b1755dc1191e03e677662f12be9e87be39f5ce8db28763238f1485d620856f90dbdffde8fd76bbd48c874e3a17ad1c82a56d2d67c7c69d2d8209be21636ed5fca624c9bbf28038dd23726753b5d68324d0405c88b0e6857c43cba2f3f8227e2abedde98b66d3ad514cfa2943ab54977b5335a0e0d8a5f7126087c89ecdae5d200b67dea54aae8d289dccfeb6a493150e7e9163c0e4854b02bee8896451f153259d47132276601373c90150818b90344cd730e9b57f70a844b87a45d4339fb2e75e945163fa4d10e6cae84b0edea034985ecf519782e074dad554e69ad33aa14851c4d", "8d39445b5a4d9243942823cf2b7c9be08189345458861c686b7b7d4b256c3f0775d5638031334ab8ac62672c52471c61cc910bf8816f341c600a225c29bc4be67b2e97cfa1e64233f070d60287f4c0b468739b35f81c1dd592a336b5e144e0680fa16e6cb8cc7e47bc53916aa02d522bfd03ff332a4585496facf7e6d82b34db6d4b701931ec7b628262cad2f2eaeaac7270fabfbfc8dc1dd69d4a6c34739bbef84c7b010b6b3da5eb09db8f963a43050325cbfa2b5947e3b6422a8e0bf694417a2aa76b92e2c5e9c26d09e4023d909c8e45b80599591ffae2026b67fe6ae1ccdd987111765dfa43934af2317d38c07214cf633e7c8614bb87c378f2afc3d52e0b222f838a6388015f8b3cdee0f6f107c9a200c083bff23a6988f98e8dc18b07e54635ec34e9b343d32a2249de51d7398cb6c4d9a67362572c3177f4c7e8082c7d915ed16983dbbc99191c342ad55e03decb50b4b526ecfb2bae58df63cfac576ed4f4d9ec413d08e8f04d77f84a7ed3fa91b0bf31de08ae9bc44b820a555a3c10942a955bee45c618e7419b485917498a8af31470cc0ca224731401b06cb4da6dce1775c37153b73054184a943042e2875fad53f48fef3eb7c88dc32735a5a128f6cf9fb5cee411f4cc2b5aa96de12c40d0887b1a2672a2e1dca45d957c0153bec550f98caffb16cd6c023202fe3ffd88f16323a6b04ea3e84ae378d6527832", .None}, + {.Add, "-37a33a230089f625ac21852f829b8d0247d418d586ccf795d594cfda016705dd120fa9559bce80b4c197b8cbf72d916549dd511c2f53a14476079f22c49d6b667a614762433dbcae1ff3d0a0acce3972b08997d3b2a21023971d72bb20eb7645c99e16f306665659b83c096589b8aa41f6ebb201802524c5ecd9a28aa9b4d13be5464d5567fe4778b8afb55c3cea9841964a464cf60890ee4d0c6e10584d1def5f94946464e31983d2075dc3b7c61dec7ac62e5ee435018e2888bd05ba886f7184360d4b06871e3f66be4797d7c8b9140cfc55d2e4fd75e18de9306c01a0d92ae234d733ef544ec359a8480a86c64b0817871e2d6d67a033d31b8c7f96629c99d12efab3f3afc0ff552e14fe4223b75379ab4ef1cd8c76a82d81cf8d861cc2719aeae0f97c1ebe3c479bffb2aa66cfccc21aa1086125b9ba206c69dbdb5b3686b563a4f90f31b0eca3f621973868983ee18cdfe231a4cd935729033e828f98f98e354f0a9cc89ffda6ebe0ae6a5fb5eac2140fc651c10f79a6aacc377da2c6fc75394dd7da2257fac541586b1ea0cdf3d4ed88a3623d7671c0b18cb5a7f68f8718006df243e90fea9b2b8c8682d2a571fbbc396483a7b13e6d3a6d2a20d0c47d17b6d9e710ae58d4110f69a3a0f42c7efcf5d685aedfb995ff37a6644abbbcf278e0ea68767648aa966a97fc65fdf16edf1245febccbfc7db632c7f0c8e597fc", "5ec1945097b1e48503efe7f897929583d5f16a2890153af033c8c84a47201aac2cc587e60c9090fdd2b65379c55761ae461f29600f8c2b77e4001b5f42aa8941711c7e8ffdae7222c9e78ff1369724d1a9af9e092214eec2e029a0539824e8d36b460150d878c8e1d21e26a6ed68cfdb0a48ef2386e0bf62821acaeee3e26373a5d250cce01731643d0ece4d37f990762c800c877098a4b417d612e4783d0057c574d07d03ae18d4265c5ee589d2157ac701a1e0f34bce9dd2dd9d5f63f4ec314b2a8bf211b017ba80f4eb2840c9a706664abb22331270b8c2e60b41a604fb6d7f81902feb8749cfe47d85702eda87a204cd9d806aed1966ca5ed33091db7f5ea5b135d4675fd406cdd195c7a34b01a3ce93029d3f6e09c824750145e45acfbbbb4d5050c6e6ab3f78da46a87ef39a9f342c654f53ea2bd9c73884b6afad4da0e2e7814c1c13e2ea5aa4d9e87087cbc2e9bf2bdf5eb35252828b5b692b8b97088ee14885029348d02029ef80e012ff446f269e41b98f7b110f919657da374b5d901c000d33dbf59ee08b4695f35a9b995578f0e95e22d3269c90dd9f00737a6664374c75452d736482e255c3b7f3015c02511fc5c189e52becdda3355a006a438d0e14d0b6c16c36de5843129793ac43d054a381f1bd30bc3cf18b78f9e63d3b00d3e2e9beac3a8aa9b8c288affde8867adae7bfd8f60e0703ef69cafe5f9846", "271e5a2d9727ee5f57ce62c914f708818e1d51530948435a5e33f87045b914cf1ab5de9070c21049111e9aadce29d048fc41d843e0388a336df87c3c7e0d1ddaf6bb372dba70b574a9f3bf5089c8eb5ef92606356f72de9f490c2d987739728da1a7ea5dd212728819e21d4163b02599135d3d2206bb9a9c954128643a2d9237c08c03777818e9eb845f18f0fb0ef8349635c63a7a9013c5cac9a4d41fefe26865e03c189ecaff5054550121d20bf78e4c3b73820f16cd0faa54e059a96c7cbfc6f47ea70b28f97b1a36a3906900edf2594e654f4e14fad734fcdad5a46422429d4cb8fbfc32fb0c8ad53d65a8143c99ed467f52fd857932f74346b0fb78e2c4d4823b2073b0130778a380c961274a5054e7b3ab71e1931ff6f331b85e3e0d4a20626f574ac7ed03313e46f5d48ccad27211c446f2c4721fa6cc1adad452171a2d83dc530ce231fdb6aeb851381f338408324bfd2d0e84bf2b62582aa8fbfe0f00abf97a65caa8d2793e0ed275b34959ad128e7b67ce6b9768e6ca205c9484611ae2b23559b99da41b49ee2ad4b9cda5808b6845fbe55cb4dbdf50e9587ceadf4c36de8301446379e7b6c93d35205bea0694e6613de233ed7fa3360b392fa5c675573ae9a6131362cd48d96ef69f7fc4d35eccfc42dd77263db9e514af2a804887f2f8814835f1e0134e2a8c49fff7179bc8a1c11c2a11894dbca1da357a004a", .None}, + {.Add, "57a32dfbd5335c0b73bc91da7c2055eb7d89f43f602d76812ee98bfd3bf5029506451524d531be72da463eeff8a94efe415652632e9399cd3f6cb95c8a6e99e496b4face6ff36d8fed750875c3ddac03bfc70920bbb2d7a6afc1c70bc5708a8eb183c1644f23c205b9ff185d6fec15eaa2dba459f479b7f5bb010c07842cf20f477cdd3d86da4e8be20cc79bfa90ef483572d0ec5ed93fed5e358807f0420ff0af8299444f5309783b18137979b71c8ab43fe15b3a993d553b5655455c082b46c97c08d1d7b207012f9a9754e2ed7dbfbfe748e0071a7ddc1c7a4443b39d810a8457efd4ae857c49948c39f715953aceec14cea09ed500a83b18d242e2cb0257931699c08bb29cd48341537aa1f6ed6cf5ea5dc050aacb1f7fc9d277d7ebfcef43c1d8e4246b168fa9482def8724067a70424cfdca3d7bfb6d567581a297189717d91762310174eb92d63208e1303cc6ca676d1a05917b39fbc97143ac4d19490061c80fa4083abf9dc8771f071549fddcaab77b730070d8db8f57c6f0c232c48564fb8d8fa92d45c625e95023fbbbad0efccb2401b70de4e48654ba97a202e7be156de3c66d17c72985a13cf44724d887f068c1e087b3cd21d3254540deb6cec49bb93ec32e37a81b009abda96ddfa93cdf3ea95fad1eb84aa989021c8bf458b24e397af4f0e1bd7a5edb5b95dc7376a51e4ae5ed7eb7f61c4b7082b7461fdb", "b7beb79b14cc958ac65f3b87c178a2c64540b6d17dc4579fd9c29088e7ba3cbf8e90e86d4ddc27f96e8da7868979d84ec41f0f56a9fcfca78fbcdafb7e10d1b6b81a23cd568ca96861da5cbf36ee776cc49bd29f7931f63d3e21c12abcd7c4a4fbb3e29473a807cf7300641b3bb2319a996028bfb5f2bccd72f5233c6ce73e862152f2b0357ce19e735b06cf2678d3896fe784d5cbe173c3bbccf6b60718439720c7e882df1d234aab9698803fa2da7454b17f29fc30da66dd6fc1a4eed78669bbf3ac96bd4eb332f9e798150e7e8bea549a5411e8cabbccd7a00baf2f1a1a32675de91d3c86428e4fcd57f1c5c1c5564a0ef7a0b28e400133313211837ccde20637ccc0e3bb48b8193817b2cd3e26186c3a4ae8fdc6eb9d4beef4cea1b833e85399dbc99dce791f00067fbe05be3b4c82c3a7f6decae91d651c666d446edb82486812496d58c4ee64cd9eae5c2371f6217b981eb2058a483773026d4b666eb0bab673954828336fe3d726cb2277daf1d3e183c9683b61d5a717aca1cc2137875baf74550ec0da4b976c10a1995ae4f4561acc0fc4c0aa19441f59a81496930f711b1433f8d38ab8fcd02916c86168c3111d755f8249f833737721783198728170c222979e67028498a4d52eab7483673015f041767c98c66e0b3b5d3f36636ee7254da6939456efed6399320aed1c74c989faae1960c6c0bc4dd75b852cb601", "10f61e596e9fff1963a1bcd623d98f8b1c2caab10ddf1ce2108ac1c8623af3f5494d5fd92230de66c48d3e6768223274d057561b9d8909674cf299458087f6b9b4ecf1e9bc68016f84f4f6534facc23708462dbc034e4cde3ede3883682484f33ad37a3f8c2cbc9d52cff7c78ab9e47853c3bcd19aa6c74c32df62f43f114309568cfcfedbc57302a5567ce6b2109c2d1a55a55c22abab3b11a027ebdf75a5387d04a81c72e702cc2e6aeabf9b959f6ff08f1608536ca17bc18c616ea4adfb1b0856fb5689500ba3429822f69f16c09aa14819cf1efe539a8f41a4ff2e2b79b3cebb5d8f1eb0bbed7e45991e8db5700253623c641516340a96e4a04546647d039994e66816f6de58c9c796b2d6f3513856224a8a94e71b6bccbb8c74679a430d7975bb4adc2398faea94eadad8ce241c6f305f4f4a9086518d272dbeee705f419604129ab9e5a39d9f7a3d0b73d53aebcebe30538b7970582333c73b0f7b387f9bb183ba4ec306e2f819f9dea298d24efb08c3b44db3bd2ae82a70468bce36a4be1146fe29e6a07915d91f9f1bd56a0a165179733c677b7fe28a5ae62ac3895f72f308217bf40a2802655ca53bca88d9b990dde2162d1ac00954a46bd72772950355ddbd661953a2cb3a56fec54e263106cf52eead629b77eb8b4c45f5bc257c799738721888538ad67c2748da0c98feb6ea8459406df7eb6d89947de3c72d5dc", .None}, + {.Add, "93a654ed6d5e4c64e5a4c9729a359179345dc03df84f66e308ee16db1d279d7ce7a47389635d28e4b1b1566c897dd8ecb45862f222151ab9f6cf89f0a8016d7282c98cae7ee9eb6369f69d0d813ddae1d76d445bed1ecdba8c77f813a7825cfbbf6021d46cd2dec465196381fbf69a9ec6f918882b592900796523e63a3ac460df4949063fbca5b8193abcf1da750bfcddac1a5d40001317e52d700896deff8a4e250760d63eb5ba0f220f720f20c4dc3b3bf1f213586f83437ff5415af310437458b848178fbe126c01772187c762213e9b067f033a09205b6b7d29be04df46fbe3ba21fdb8ae96c4317e29c5d115620d0274e3a2e876c5b3e5c88616e0fa5e91eb177a75940bfaceb0e2253c3f2b8f6cc171c0b18354d253efc457fe2c9e03e8490b6a82a53cf7ca31dcbd44aa6a136a1dc9255d48af149bb13a9bc5599306b0cc757cc1932d89403bfc8e94aee9bf0715c80cda44756c0376b1da0810a81c455acf5584ae906f3dac105468a6f159cef6e3e79eed2695221e74552a65e658ce507580b798faec7c499abe15b695e9c7b0bb5462efdd534bcf4c1c3661c33b98c438c3fc9b939d20579c71d5458e6ff665adbf4bb1e4100cfa9dbc4b0805af1506401f24f3bd69b50753a46c9e214319a2bb84ffd3bb11a03991bca762f2edee37e75c84b30cc9c41233aa9b1d66cf11ae55a08114086b58f6938fb0be22f9", "cabfcb98e9bd941a4c4d2b9aeb73c0b1f04ecf1dad651a53252fdeff39b6d88c86900d367d134e6bab11dc92ee5609b33baaf4d55916a0f896299693241ad480856b6021762dd6e01aeed741aa9d4b394b183de41af9314a8d65554f36575921528e4961ac2ca8d9b27388815535127d0b2bb5171952a47fb8d18642f4efb7f05dc912cbed8a96300a95adda764e5dc2294af3f1fa71855487e2d8e3b685fbc9c25bfceb602f17c971df68a4e68283c69dd95217c992de2407bc0c7a226aa0d765d45e50c3f1cb39611e0e246be3914649570777eea07ba528437e34b5eace28b9e064b0370986f7febfe0201c5de4fe19adc1a1ecd59140016d21093eac121b533b2ca2d78afeef4f4d7251a479a28b1fcc386d90921bf3e198f562844986c521aec9a06dd3ec863c9265ba6f902749be5205c6234ae1b2204f7c6107d48009889844223594ce7ff7bc6bf81615a63fdf8c37e058a47a2b31da2ced1569069e140a2491f79b538b299e731a8d4dda43f9bd18bb91558429189bb7b27494b1498961c28196a0018feba961e3ba3847043a3d3e60741e99c352c92b8c1f0ab908941fca67e1236a420266df47512dd41f371ce92ab5b51178068d58d1c284624e25cf71fd4912dfd3ec5d1ac3a04f42598173720e0e382074714b2511b30d7028ad6563d3c821245cbc614407a8b877ed895a286e42ed2d4b35245848bf5367ca", "15e662086571be07f31f1f50d85a9522b24ac8f5ba5b481362e1df5da56de76096e3480bfe07077505cc332ff77d3e29ff00357c77b2bbbb28cf92083cc1c41f30834eccff517c24384e5744f2bdb261b228582400817ff0519dd4d62ddd9b61d11ee6b3618ff879e178cec03512bad1bd224cd9f44abcd803236aa292f2a7c513d125bd22d473be823d06acc50c369bf06f70e4f3a71986c6d1048ec4d64fb541081044c366dcd8381017816f5a348a2d9154409dceb4da74b3c01bb7d5db11ada2d1698db81894bcd1f8545f3aaf36787f20df6f1da84c583aefb5e73efad6fb5c41ed234c2358ec2f15e49e22efa6026b036858fbe0805b552e98f558d0c79e526441d4d1f0aea1dfe5476e0b8ce1a8c8daa2e421570c63588b9ba827624c909f7d50af079297e06c44277b43a915d286fceeb809390c6bc00b6fccd2e13103964b99ef727fc0937f86886aac48ffee6a1ffed32e8ef973550dec71d79aeba5964f3e77c49e3fa674a836ef5f4cb9dc8b3fca33042aabe3aba2c079efa97a257b238024e38fc7c67f2fca1cfeedcee01edf9b4d70e77169e9877a8556c7c442ce4032bddbefddf22be7bb92673628f2d8296ea0166f5881387f68e0d8c67fd3ad5b21c6e069d3da1646e680ced639c9b162d930e0bdb861184b6ce5a7063169b9d4b304cd43126807377b243d5debc9b087e0ec40135b68e1aebd870118ac3", .None}, + {.Add, "b73c9a3eb4bbfab7ec4167c24aa43e7290ae9a939aa5bdfb15029cddbd8714dc3af52ec7bbfdb0f294dedbfdd36c9c0fdaf6f53ecb79c1159da27949fb52c306734ec9c681d71adf7d46726b29e9b4919a08165fb446304cc7c4ec8cd656a58373ef3ec0a24436e68ece052e1d8d76571fea58039b901836548a62e60a52b437e5814ea5c34d98660ee3d54f88c0d67ef385f2cc0c429bc5db1e9a626ac6f35ca6a7117d0e4026531eff704d7f40717bc983def6e088fd46b3e261ebf509ae7990c0bd5e2f3710401995cf2150bfe1b5b56d4dcfb6527c74e97456695f8d953120490d2cc4bc4da1938c7fb262dd739790d9a1d7021ca385656036df13f2a348a46d569e0f064d9b4838ff08e1f0ea1aad1a143c3f19dae12ec8c01eeb477be6a08bbfddef2b75e802515d7083c9d8160e2e38950a6b55b66f914fdc635905ce2892660a17d4abb1816c5f19ce672950e9f83062955a8135b2a75a5d4b31ce6cef69634459916d9b2235425a60adbcdd445accc56e0c32b5fab377bee98d4e5e0ceff32ebf4fa0fbb9f91483e0caa1e672d0349bca8ddf43cd1d3d7851467085cc3ed7a00f3fd06cff351910fd54abd5d0f596717665484f76d3be2aaba35f138b3bc1ac0a1b6299c457b238601ca0f3b7d54285c2abc6dc2fe09265f41c164238ff28e35c0f8f48a52a858e0f6977dc8618dfb314ab7d2533951c49b8cf6c3d", "1c6aaec93078b5ae35c62d4e8442f8dd719e25e68f9cbe30d2aa04313ed5beb277ae497bc61cca62b7714c4bc29b7768d0692aadc235e399352bf0249e5ec1feac5a619b94ba3d8c03582e94bc5ee3a3e303b08c61db4afe7500f1194296bd4672420da064c1181c598356d67565fdc0c3a05e2c91e6340f63b1b6b446ebb25575462463b834b705cb9e4ee366a0f10e8012d3d3a6ccbf6d50f6f3fdb889932dca4eb8e31362fa1461353ac173b739943a019689912cfd307effbc0ca29b1d93875bec32f2d89e141ff137b949595b5e7949cab436710544a509a281da53c3cf0271b494b8651cecf2fa799b7e5f38c30e18f05017f0810cdf478f45ef64bb7d52c1c7e502d647b820243eb73c69725e412c1e5de20f24093f2dacf4b444b9678f88e099714e16b7d4b44cde554d2dcac2af9394b37491ae0b4451c7a87b1baa8b24420ad93c83f64cb6a09ba9af77cc393f4ecfc2143e690a04d02cbd272eb11872aad324bfd2f43cdbcb1093e03e7bfb7c6f16f99e4282a9f5bdeca040d0ec1fa8597f59443908e91fe9889905358b947583ca453fe71df11a4f73883590ffb927bbe90b903714d1c8391e44b1c9fa65fd8f97cb1c961dd5b87c7f03dce2af7694f21fadf4ecb7591b7fac8fe031935d1ddba73151e0dfe602d44594f79339d84f8028914b3ac02bda2fb75f5b6c2efb27c5e061e43e8e2da705adafae727b", "d3a74907e534b06622079510cee73750024cc07a2a427c2be7aca10efc5cd38eb2a37843821a7b554c50284996081378ab601fec8dafa4aed2ce696e99b185051fa92b621691586b809ea0ffe64898357d0bc6ec16217b4b3cc5dda618ed62c9e6314c6107054f02e8515c0492f37417e38ab6302d764c45b83c199a513e668d5ac773097b824f6bda822432ef61c78d7398c69fb30f5b332c158e602350868a70f5ca6021a320678034ab0ef2f7ab100385758071b5fa7732e21df897a4cc0d181ca991220fae54398706da9a193d142eb71883ecc381b98e7df8eb39e1590022bac1c17d216a8e8686f94de13cac5a9ef292271a0d249244a7c62503575ec5f72f1e8311dc9553685d3dc01e5a5c78ee46329a2128feea6df66d139f8c354e3014a07760798c9fd705aa4ed91705e0d0ddcc29bddfe7647ad5a1a40bd42178b3b6a814f1112fa7ce22ffb57816a11d23377f32576ebf9ebcac2a8a0858fd1e07dc0e177e51408f5f110d6af48dfb593fd73bdc67aa7538a4a935ab89ce1f4a2c984cae1893da04a318fe0c79cfd7720745b8660fcdc661be378cebd97c0185856693891ad00781d0fd522f420675d036f326094181de6d4c8c3aa9af8041c301d0b3cbb8104f511d7331e4effcd28714f31e2cf3fda7bc15e366ab8913a97c114ea90bed5aca08d104b5456ec4e40b8140a593768fbbb3613c21f7687ddeb8", .None}, + {.Add, "39e0006c197e800dd1e7c775daa9450b00ddf818549dd37e05882d78ffc24fe653c122f2e9fc9c55d0cf180fa833a21c5c187edc135bc893a7dfac3f3b101028789821dc4bbb4e69ccfda4d45ef96b5b9e0c89c9622c2aa1c50aa772e2274cb31859c6bb00d8a0a1cdc8045b6e5100d1ab9971ee76e7fd98d38a2fb767294d4cc278c7feb1c16833ef99780fa80e4bccdb92c38d48ddb89eab5da876d7a1866704a7110f95b8244e055555362679cfe0736d35c6d71065c135ed214926fd9ebac81ee172c053a384b9f60e0c2c8f22c8bd5fe8f96160efbf3d160ac310bc223a80456ea97ce2454b63240a65c81e5026975596de17aeeb7d03465c6a294b78aa30bc683041222cb5c335dead50cb14d4395fd7a8989564785ef79cda3fcd893838719be781d4a3826b0b99ceb4edf8811c33a798ec067cad42abfc73283c1574c36b34053ce2b48cfc171bd4d74262652e40214c9efc7caeeee730c89c907142e1f2fa26d8e9e2780cf1298e2d9bf3d1dea2c03058a57e77553b432aff117951aeb1c005db71cb6cc7da2f9ee15c24541b835eb1033a1af5653af31037302dcc6d55019097b7630a6f2a2812d64fdc4d0bafc48707cc5396563433453b28410ee9de542443f10b3c3fbcfb5c1d11ed1ff1544c7c5e9f3370e8fca39060f2c59df809010063454043dd222c3af4688c081df269d88cffac04575eba15f684d9e2", "8fb911228e9b5f29a05f70c48c81ba9e03741f830d6aa11b0cee3c72b219c1e19491dcea305c644d96bfdf381c64b2fc435b5ed386a117e0dcf89baed9a814465f4ebbec036b1d09670656ac8e6254d2cc703ae427aab7cb96f10210f00116bd908b6b5efbb32f330f00c7c5edd19956aa8b72c0c256df743123510c4bba27f5bc4c33ed46d956993c9d88ce2aae8ee80bc6c3f83778fee4a5c056ac644f4f8dbe89f3950679ea17f212b9ba413bd733210902b0e78e24e91833a53d0d72db14feeea07b7f267db8adba2437c2bab50d125fa916f6742d75b6d6b32d77f0044ba7ebaa9f704e95d484b8f43da43f2b2db9744427517222bfa4c5d4dd5faf77e34f5a90ec8a4b5eee4308a2c693efea2008753fb40a3af03b27aaaf525e081e6b9bde473cb9513133e5e26a4c10ec7dd6afb540f239e002eabf0ba291a723e57a779bd79e6482c4c1727c7a8d5739c3617eb3be4818723d403eb9d739a28780fd991a9e7f213abf1840c2e4658427c4188e56149c9320b52884cbc5f5286414de43be2ea92f45f58a068c8c03a56cc77bf849da531d5d46bc0fc06fe5e3b0eb352530e59a079a1fce541ec0b34266dafc4867068622312205b3786f23b3431d799d10f912218316038eb94e32899e84e92aec64ea3cb3464a914aaf7e4bf75f33403a4472a994ec74f0372c24dbe64f91797cdcdeae357a8351df29758af66805", "c999118ea819df377247383a672affa90452179b62087499127669ebb1dc11c7e852ffdd1a5900a3678ef747c49855189f73ddaf99fce07484d847ee14b8246ed7e6ddc84f266b733403fb80ed5bc02e6a7cc4ad89d6e26d5bfba983d2286370a8e53219fc8bcfd4dcc8cc215c229a285624e4af393edd0d04ad80c3b2e375427ec4fbebf89abecd2c3700ddd2bcdab4e75987858056b783511dff233bf0d5f4c33104a49c320e65f7680ef067b5a71394763877be9e8aaa4e20c686347079cfc70d81ee3f7a213d67b03243ef49d7d5cfbf921057d51d34f3ecbdf088ac268628311948ed30db1fe7dcfea36c5d7b5450c9db0569210e3ca80c314788faf08d8016f91ccb6d8ba4063e8173e4bafef441d5175ca2d054b386a24c2c9dd5a7a3d44fe3243b25d4b650ee041ac5da7657cbe8e88b25e67f9801b79f04cf5ffaef3b070ba3a165794e6e9396622e7c25c6acf3df94b76eb9ef2da108023f17f2407b0d98a5fa24a1904db40df3b1c3b7ea6cf8d4ccebc6339fda07092027758e2ff26feeaf0ab7c0f6ce66bba286c8ebd013cd3904209761b174fb62f61ae119019285e72a9f5182d8c348e8c618b6b7495416cb0d29fd759c09aca268ee6b5e8886ef4d366574213fce76498ea6b072091c40b1669b5279bb7a47530eacea24d1384345730cda2cb8cd59585fd04edb99976f46b73b352687a93de38b817b41e7", .None}, + {.Add, "-566481d2a275f5c9ccf3a4d9f978ff7dcb722eac4a4b1a16347532ae70020e5d354929135f15c3d033622ec271c3041267ca9544786f186fd323541e7909a2c190da9d1f7658eecc5e1b62254d2c2c4f5fcc14177ec7b3f8623bbed9fe8df8436c60ae8a601ae126ab22170d92ee371826edb1c6639c6c727ae26dd3a8652d4887772cc42182c4a5fd592993f0cbdfaa8138d292bb0c624c5725cbd3e3dcdfe847643ad6764f413222d25e9f4b45f3e4dd0bfc57f7b00925779c572ea89ba77e5dbf4b9f1109bb8a55d4f08bc72b323b2c29bd63a8fbee122850579fb82d930427e0d811b823b50937cd4baeb9e943532517a9912088f1e73d55241fecc0a62e1bb31bc9f914a47cd9c54da97a5b3f2bc704b050ad18d9c4a5653f5dae5c6e2da9c27405271ccab06e63fda468cf238b259975654db5d910deed4bcebc41412a66e3ba92e91fa6805c9813e95cc3b614172035513de885051cbe3d1361ba64d63c95d2b83b91a6adc7e31685c44287c4bf81be19b503ea181974d9a69df28f0f8e9db1838a2912c050014391a8df71808280395234070855021b3301176c10a7085e153774e8968ef1a5e09f1388f795bbc3377b5a86f55394164358c60cebf3c557129c92dd3efea6e933b6fac59bba9c2db84b1bdc49ad61096304eb626584b238f9671f9a3c924cbf8315153e86fa2b034c3a1aa4ecb7e106156b2a449332", "422d753c36b51cf8d839ffce808d353ad59e00d41a4e4184451ec0c6c7d4c0bf86ce29524859c43265d08606bf23545353e958757b6ae056faad00ad54bb1626d70d3b76ff47f7e7060ef3149b4fe5b27616b5f008d48b203d2a3041ef20d2cd084221edcbd69409f4a2d58e2b7b1ebed3ae3dda8ea2a602d2067f57ddc62924db6011d839feee494ca583fb9d975ec0e169472f11349b75de8850e89daf391590d212ec91ac10d34d4fba2d063f20336ceb07b3ece9bb8ebdbb5e643c6f33e2493678355fcf1d17d581532a2d705e21ecc6e4574205b6fe8ead9f8409375326da1f84037c1da84240a4c6bfc3ba7e201f26fd5b565f747d35b914225344271f42c05d0b694a10ab87e6465b2451e838100ba556cbc4fff53d757b7f42cb9aea0a913460ad526bcb84ceea9012b3b5b4a7798190f9cb3fb5b6d76cac06b754005de750713a4d40cbc9040048d1acf6304d50793689a66374ade1145f04a362824b8ed6039fced040196675a43fd2d322e352b9ad3db9c051d7d405108af39fb2ca8b7e420e47613891441ac9a15ac9c0b8ee288a2d492727e3ca5240a59b7a460aea6f2db2196573efddbb236514132891237140108c03092d532348c7b2b5100df7a5f00e2e3abe6975453b8a46e1997c85313ce70798eb0f351fb926b07670dbf22782bdea4c7c0c3ce09c382973891feb2c5f86180240a6a37e14ab172227", "-14370c966bc0d8d0f4b9a50b78ebca42f5d42dd82ffcd891ef5671e7a82d4d9dae7affc116bbff9dcd91a8bbb29fafbf13e13ccefd043818d8765371244e8c9ab9cd61a87710f6e5580c6f10b1dc469ce9b55e2775f328d825118e980f6d2576641e8c9c94444d1cb67f417f67731859533f73ebd4f9c66fa8dbee7bca9f0423ac171aebe783d65cb0b3a598533480e99fcf8b63a9d7c6d6789d7aeb462da6d2b69227e9e4a3305ed582a4724506d3b17020f4a40ac64d96b9e0f8ca6c2c739c1488d369b13a9e7280539d6199bad4193f62d90c66f6371399a2b81baef63fdd4dc1540e3c060cc6f72884eef62ec53305f0ac35ca297d6a079c0ffd997c7f0ed8f2bebe8fca93d151df074e560956f3b6f90af9e153d9cf67efc3de6b90d3439f313fa479ca5ee4e9951314561b6dd67e1ff3d453ea995b2815df22b589ed2a08fc6a21aed265b4939413a08b16bfe3c9cfbc1ab44221906edd28b45d170253f106fcb49bc2d66dae7ca0e1846fb4a1dc2f046c774a29c641a0d49612feef5cc41233417be1b187bebd28c80784a7bfc99210c806bde12d1e50e0c071d09660fd73a609c2cf311b01c8257bae74e46d2a9fc63b49faf24a66c3200ffe5a36e3b75f6cac84af04403d73ee7b707eba211fa8870e34d4b0c251d4434bc4b1ef13d646d1e461aff0164082a278dd1513710b181fda948cea773a6297567f2d710b", .None}, + {.Add, "a22e3221ba9fa2d98131afef2c80f622c62ae567b3946ff1bcaf724e066bf66386b0c9c1cc15372ef348f29232391feae8e7900b1b3678e0e2a40c6d2a6118a2014ca6e50384ae64c307c0188db85f978a96908a41d2de29e4aee0f411a3cf3830963a59ab43c6ef7c5b0cfac9c2993bac958c4166b2995332f2a135351391a243fbf3f29aa130134a0556bedd0306efa69e549d5072138813aaf84f6f17c02c55a953ad6b6e6790406a113f32b819cfcdd76250466a39aedabf5a158d61636d2c92a84b6f82d300cba915d12e92cb60eaf5245bcb4954cb9bfb70dd794b4f11703b0b693b9a4aaa2dc40f87591b8829ab43338a617658c4b4f68d1c3d9eee6c1b425ca37a9d48dcf101f6f7a93e16ce34f896b8045bd365794b52cc4f404f557df0db501fd10a8f84fdc5a192f7e494966764360229369847cbe088ab68f9c9dc73dabc177071907c849c1c0bb7590363de2059b2c6d27fe6d224866696600fd89494a38406c22db87a65e517a2201d4e2480781fa5609fb7f42786e869feb55c5c3629dd42e79016e012a5e9ffd885b81369c2e01c27bc1e48d1db11a0907115da6be941836e7f86be1602f2031fabd63356ec178becead46261dda0112b5d1971daf4a49df4b12c8b6e8a45165461f5d6f03f7e9c6089dae87096085f06ba51bd343368f0dd846c04bfecf61fcdcf644a928955336bc2fc6b1527c7ed4165", "5a4c206b6c4bef89d7777355ea17d08309be6bf8a7b70a4c3ade138920a85a5f2427ee5a5e89f46adb1472b11d29ff8fc20b8881485a97f55fb90078d66e42139dc1c96118e711428ed6280219a640e06cb14af6ca4f7c8250417368d5e4c14920a5b893bd813046d384f6cf7d4e050661b078ea7392e79e21299b6484bdd3a3a65602a4612e5dfe746ee7f6d50808084b31b6b34ba527afad726e6c5ebba0b7e8f496c12ba0f6d54bac9d9700612cbf7874849f30b14a5dc05c1dc390a562c868181492385e296e41de826fad061904e612c6f6def6e7338abbf0c4d58639fe56cc2e5a932e4ac3f45d0284a6d3aa020cc6bf49d031617edf809ae692b3025a1c5bb7e12a4aeda2bc19605e05b28380486cdfb72d97b2d41b4384a55d4127b3068692dea5fe8ffab459e57342c2d2c4cd2037eadf8fa6c84dfb80597e1d6000c9078d2fbe347177c1fb939e6c2dd01c66976ed09c3151b09297ac9784a21d9ec4f9ed9a7ec5d20c5e791368705659f57009db1acdb7eb9d710f6fd46647e712dea67a65129a204b10dfd0e2f0542a4f45e3fdced12823a7cb5619083c0dd8227d15111cd77a2eee2c763b0ed4ce93a48e2622be94da6a496aec5422a981cc8639b5b4bfb0cab51f9a590df1b980e5ba5d13a4dac6732222239d950f8b7b8eb51c66e3623dea0a4ef00c4864f7ba0f1d5a853a03d2ead7e9e2c9c836e038b63c", "fc7a528d26eb926358a923451698c6a5cfe951605b4b7a3df78d85d7271450c2aad8b81c2a9f2b99ce5d65434f631f7aaaf3188c639110d6425d0ce600cf5ab59f0e70461c6bbfa751dde81aa75ea077f747db810c225aac34f0545ce7889081513bf2ed68c4f7364fe003ca47109e420e46052bda4580f1541c3c99b9d16545ea51f696fbcf8e11be743eb5b20b0ef7f1d00b509c173b37c11d66bbcdd360e43e9dea6e970f5e658c16aed63319468f464be6ef771b840c9b1b77d91e06c63594aabcdda7e0fc6f0d879840db98e465d107eb52aa403bff26b761a24ed1890fc70739c3cec8956e2221120bffef322bb809f2d431a7ba4394772802d051f0c6379e1484a4e8367fad1b5755aef09a4e7d65766f31f38639948ed771ac81770884776e2ec5cf9a8a3957ab14d5bab75963879c20e1b8dd6095c760e2298659caa57b67ebd5a4e3083e802fba77e5291fca758f2a4ef824307969d11deb387dae9d8e823e02cc943a16f3794d87f87a12be2e5b92ed5d4c3d2903975b4eb1e5c83b02b08eefdd07db27bfe388da5402d4fdf76791b1444b63e99eeae34dae689392ef7d0618fd9d6db3345111c6d1b350645979aaac6657343f4eb6004992f7e353278fb45568a9d0c6e47c7bfe973a1c52ea951a450f82abfe8605a593da956f6e241795a6dae7d35c110851edd9dcecbecfcc8d281e43acdf34dd5ea825f7a1", .None}, + {.Add, "ab7c37d8933c370d72491a3dc37ce2284664456eb09f47e6cf3e5a348943c1bbe0af74c7f6263f56d5ce02dc8783a5af8521280252b82414e2270fad33cd7d2f82926fa1984d130a8dd146f090e4dbf161d87f3aa3b840d71e8bc60c91d52fb7f941106fe01fe1bc72094316f835b9d4461536f3ec0ec7c486c416db60da0a94e75028fdfa191fc474b4cc6d79f380301396cbb0cdd9fec1ad05bcbe33c542e8c6eb820387f2b8a75fce18336de068bae20c4465d94bcd9f05363f9f3a82e720c6390aba51e92cc71a5da4dff1da488eac0940d9674743f396f7a62f2947778c8c76d584c34dd767b1e5f88473f49c63a1a1066ab1174bb73e49a8b5e4abaf875121148d3ec3c98195feb913a6d78d22f3df455ffd39842205ac7c0fa223cb1d5b1425fb09efb93085d36d368ed035bf6ebbc030bf96fe06c4b9039a42e83726915b3e5796d0f87b23ddf8c68f316957cd74a70ef939da9b527e037f88098cf2d60d8f5872571a925b7e4c63b80bace7178cdbea40e994e647d54a0151884d8e5806a2d9a78e40a9b76659d885726870c433b6b2423b9ad9dab930b80680bd22cf3ef8e50c7305c515750e45891791c1c15ca960a3631228d5c9dcdd2cd42e6e816ea900f407f3e78c5c1662dc2632cde79dd63dc4cf29ca646eec84b25a789e64d9d893c828ab5aafb69a1042ad83d485325dbfed4231e6852f56de77ee3e68", "e9765b2333e2118f821fc97410a27713866d32c1a18cf40a5ac6e467f9f15f9dcf45a7eb85bba8d7be965906c140f05b8b7809f70aab48cee06c2c69ce401df12c4d661aee92fe74d65d29dd66fd82d8b67be2307b50f6a2593f233bf8f41cd7040470da91637671ef5b48fa670e722c870f9e4422aef99ad34ef3d0c03cefcc6424bf9afb35499a9156dc55869c756d36feb35fab396e4ba0786c97f60c1b9c11730e874803a2a228e97969dac8f6ec5b907dbb8e60b652f287557e4c19faf1d8a469e8f828c235dbf29a455448927287b2f7fcb3db5777f0e015fd9c4991cd42ab11d68a95fa11e669664936c8fbe5eabb4254b60df69966db11cba2da6cd5e768c2260c3546c3ac85591dc2853c28320b55ce95cc5db98f836bd3a147412cb4013c51f90229422bb5a21b9d56e8aed0aef099d2faa3df8233324d4aef5424ee207726ffae87486529c50be3f27ddf67acb0258dff438524ed45971cef5cdf9848223ea70491b90819bfc27d772839714fcc079c09d89aa7931a47ef027d43ede123052f1c939f687210486051b785a0289b7f5c820265506a95a701deeef9b1345f9579be3efbd63bb2bb0e041d4af15c01cd95b0775ac99be51ae0f9e9a11e4d6a97039ac1e22688313c1d39a31f0d1153321ca6c255278cc0c21ed053b3b9fc6fb6d9522f57cab05db21f0546f83f4c7dba718e2a030f76646ca0d2f31f", "194f292fbc71e489cf468e3b1d41f593bccd17830522c3bf12a053e9c83352159aff51cb37be1e82e94645be348c4960b109931f95d636ce3c2933c17020d9b20aedfd5bc86e0117f642e70cdf7e25eca1854616b1f09377977cae9488ac94c8efd45814a7183582e61648c115f442c00cd24d5380ebdc15f5a130aac2116fa614b74e898f54e695f060ba8c3008ff59d4a957f1079136d0d4d7e295629d15e84d85e908acff65b4988b7919d48a95fa73d9cc22167ac83f1f7bd951d869ce2129edd74a34a11eefcf6503f254622db0133bc38d61b229b6b87d7bc2cc5910959cf21e75b4de3d179984f5ecdaabd98498c5c48bf67254250a524ba8187861c5d3889d6b34af9104542841231695cc94b25ea9b2e9305e1db952fe7e3436b0c4a0f15624d02f1e272b1890f522c271e6e3f6ab0ca9291a1e646ec35e78dd78b4b7f7bb57e967f7fc38907bdd27323e7373521573487391e20776b4916a4f8e9d26e55b197195bac4b63980c263582d52088dca7f1dcf36d80ef686449408acad245e7c5ded6aad4491fd86a20e5c41ff6645c52319ebd9d3f2b23c65f085fac1c8073587a863144c0ebb0c100971baf0cb2b8ab2e391389839f65c1f80dce180f9fbc1397f7a2b5c9b2e4479ef95fd5ecf4af296fe175ec1f8bfbad46d12acc521ed6484aa17adab27a66f7c261b2caccc47edb7a5ed05be994a5bb4b18c13187", .None}, + {.Add, "adff4ca04a1f49040cb8c46a8a3d8addb054cbc506080a2841fcbd540e8544cfbb060f5f188c9b851a95ab03e3cd8083afb103dd9c1b8a42ebe09a1de6c4fd0bd53c6ce7a6c97a13c4d89cd2b18417978b006ba14154015094ee438e0e34314a71abf0304c6273ebadfbfd5519f5e98d27de2d59961c3f9f5e2650690bd3c87ffa219913ea0c6d1e9275a4bcd859aca5d7b518abff6f2d4b983d4b152ccbced488e6387dafd2b798e685709a87a20b009a8e757a6a099d4c95712b09aeede02fd56068f20db00c3badafebdf19a91158351a2689ab1dbc879bd45ad083f44a4d1957ac7c1ce769374b52a992a8e386bcd6081446a7770c93cb7945d2d83a4f094a57fb64a6bce86f17154b2be47b262b0faac1d4c7ee545f303b81d7befb21899db5a75d3be97e96e2f2363d6123ff8cbc271eb863ec5d9ea746ca8c11df4784ef8d733c92fe03b8f6946690b3a98b151970470190a39b03f2927aa506e718a73b828c113c663ea9d6d3200b1bb569a2821df20805dca60780a690f22c56fdb2f628d34e21e715fcd1331ea80a88f3ae6f0cf1a5ea8b846dc4a460585efe08e4cfb1f23c6ee22a2b2404c617cdaa02120aa0440fc787029792636ad2073720fc97f65075cf617060bcc984734701dea33568fc7915a5d996c54a9e7d74736b13d737cdc87eeb3e091c0659c7efea3658f5d33d5e119cb778f67fb9882a615e39", "44e13d28b0ac312806893ec4e3b70b1ade6ef5aa7166287616c57b0f55c70452b5c7c1a3ad00b9c0fb2f0741d43fb98998de07dd97288eb6840068aacd49ff9481e7a5f1bffcb586f743e115c8f8c75654849b712a01d73171f714a1eac57d0525fc37b8fe80de06df7cffa4312fda76b196646735569468f80363ebd04ab2647d42e8751b0a093346130aea7c2e4b045c5ed3c258f9e4aa242a5835d05567a3ca2c2e9571821fe2f8f0272e7e94029b711e5cab1fa974a4ff8fad93087e058fa442bacddbddce79c4f87ede5110525545f09f2b7bf96eec23e7a828eff60265f6fd1c318658a3d2607226dba49b7de39d82a0b7dce1b182d66ce9d90a80dfb0f58af21d3ec28b9d3f68557456cee833adf0298170c589fe749f5eacf8f54cb493db13af3dcb140a7dae09981fdb171222e3fbc1ec503e459c1978615972714397b27bb0c2246a562c77ad82ed81c0efb8412b3b124fb83c5900ca1a48137cf8997d65316458f6ddd3a0a966f7d5f60b522196a03ff1e674410056d040c4d8d6c6b416d09e26a48651c6c073d938dd7046d4543c39a6225d1746195a48bb7197e4761d8274e37f559ae3f998486ef85d92480c0f2523dedbc09ad9fb2341e35b636d9a5ac853c83bca94d610f037b68c00f869eed4086b260d0513946b9fce4bd1816251511568690de271e32075e675037109d3b7ee9559f8b1afea9b4f9af7", "f2e089c8facb7a2c1342032f6df495f88ec3c16f776e329e58c23863644c492270cdd102c58d554615c4b245b80d3a0d488f0bbb334418f96fe102c8b40efca0572412d966c62f9abc1c7de87a7cdeeddf8507126b55d88206e5582ff8f9ae4f97a827e94ae351f28d78fcf94b25c403d97491c0cb72d4085629b454dc1e7ae47764818905167651d888afa75487f7aa3413ec6e586911f5bc67a34afd213678531267132154d77bdf7597c906360d9c0bacd22589b311f19500d89cb76be5bf79a323bfe98ddab572a86abd6ab963ad7b0ac5b527172b73bfbc02f973ea4cb31054c8ada3400d09abc4d06e4d7f04a0738ab4fe8458be16a1e62fabe2bb2eba3fe2ed81e57f740c567da0a03b4a0e5ebd9aeb5638b3de5da4dae084b7f06e3e3190bb0c79b492a160a03fd580ff169edf0b1a7a503c9be4436042ed6b51b8c8873feeed55226e0f230c1413a12b4c04d1b1723ca2f353404b9344bf4efa959fd4fff142a0bf3587aa73c972138b5fadd43f88a845ce8c7bc1a6e7c26d1bd689bcdcea1ec00dba8322f9df1be3c1d11eb5e145e22431a6cadbea79b2a7b97a7cb4280fbee3c5a980bee8bfb01618fa6f9ce8501eecaae17352fe44cd2a790457fb63ead097b5389c875e5a843739952f36616667e9ae44bcd24fb211e013395fa8b93019d000a67229e8cbab10601ccdf9444731c98b4cd2ef316972c5b0f930", .None}, + {.Add, "b7393320b47f6925da595784a4d6b3bf2ef06f71e98eae58170a00df79d045d6eedcd7b694bb7ad364a60e0ac2c7ebf249bbf070bf1061a242812b29adcb761bcf85cec12d9180917fb7750dd098c0d30719c10f228ca6ef54f5d0d6b857c360a40711e1ba9ac6bebb9cddcd252e2bcb25dae91abf2017e80db14c3dcbbc3f577b6973787b458592e5478c133b0faa18fa747ae9efb95b3ad200fa0939fa15d079ca160f88b7e30a2e3170982c30455ba81c490ba1e85b4eda3bb64e97f3ebc123bce0c7ed45f067df641dc96f0a11cea02f76517ce6d56b14fdfc818d89b0f98b38c03e649c4c0588b7ca595e2e11e621c26ae785f57725ef4ffb6e224ff689b86e036c91a7e34f2de00e775ce278c15e797cfe09326e5bcf8ce44aafc9cde2d37f887f55075b28e935d05bfb630ce904bf537992bd07a8c93d577c2c9fd33735479c797b30e4006deb0bb8f6dd1cceb27834369f369445c4a5946c1a8c02951d9518dd0f6a98286800489424e6666d4c13dcc9da260958b50249246f0ff22dce88fb66eec08f9b9a1ee17ffc5e00008c86fa7e15c7bcd591c2f3226c2f663d9d530edf66f27aa0968a5568edd3902a45670a5e37f5f72269c609b6491f69f5c7b3f8f126077103bef60917f8c87ea263f8b5279ed9e736d2db9c4e1c7f588e21fc893065e19009443f1a2804eb6d00d94be19cf53e82ba5fb2f0112a6b9411", "f4280e5d09cfd5bafba4e31b804f0522ca28d3369fd2469fa224e9771de1208b20197002655bd9761ad3d4959fcaaefb49a7d96e04adac6ad4f687ab6bbdc592f32198f6119c419e5242ec7dc073c765dc170a1ec3eaf09cd936ef65b39577702cadcbcf6f9ed381312d811519ac1eff025a231a2c64e40745877b5b69f9e0e251e5fa700da58d906b4f531663fb236839882f6c761cb185fca4fdbcc8d2f19b4f0784cac9191791ecd5d6e17d1f0e3f25657b4b999de129419440525f2595a047ca5ae8d7c260213b484a6e840376501755b1485b2451bc25ec2de7cdb2b57222dc30aa71b9f4579ae82c92178f62f7791db318afb7b72c95eac20135c0421132afe5885c82a3a4b778d7c75e65f7fe424f8e6b15ef7dc534241c36e7699412abd2d71578564ba719102a3a9972eaa9fe121dcfdba5f1e1d2d8c1219b16eb8e8e0e19715572615c85822bc7f78cf2cb628a466d30e28981b71661d46c40700e61befb423d52f437389b8a751843571a7ba22bcf0d997eb18e5af6ee1b2a8468931fab48d9a85e6fbc6b89bcccbd42303aa943d3decbe94fb99cbb16b58819b0a4c096fbdcc581461fc25589987240a4f319dff31edb6be8ba6c5d4abb71ceec279a2eba709aefb793faa5de17b1a1fc1d1871ba66055f11b421b1e6b50813996006782ea27aaf3a9659ab1e3532d2a2d53b84e4a250e70a1e5d9c591c844f71", "1ab61417dbe4f3ee0d5fe3aa02525b8e1f91942a88960f4f7b92eea5697b166620ef647b8fa1754497f79e2a062929aed9363c9dec3be0e0d1777b2d519893baec2a767b73f2dc22fd1fa618b910c8838e330cb2de677978c2e2cc03c6bed3ad0d0b4ddb12a399a3fecca5ee23eda4aca28350c34eb84fbef5338c79935b62039cd4f6de888eb13235096df299f0acd8133fcaa5665d60cc0cea5f7c602cd076bc8d19ada51d0fa9c1b074779a94f539acd81c4573b863c781bcff6a0f71981616b873bb0c50850891aac6837f30d881eb7852799d80b27273aea2a695b3c666bae14f0e8d656405d239ff6eb75bd74dd9ae01e0035ad2e52853abd6f5810389aeb1de8f4ee2a86f3e558e63ebb4870bfa0c90b691f21ec2103b10081973361f57f525f94cd5da6d00245fa9694d5f79302d171496e62f98a9c16189dc7b6bec5c355b5ead0a3455cf36d3780ee6a0f9a15027aa3d0191dc77bbbf64086cc72a37f54141f4cbd8c5fa09bd3093d29bd87c7b60898e7bf880a435d40128a3a769661a8a6afc868ee0b568a6b3cc91b4230c7303e51f493a6254b5fae3921b77fee4213a5db43b7fbe6b64caaf28645d0cf3880ea5156d1630b24326701049138e1ef4e27ab96a260bb52f0aef6107a209e811126e204df464886fd4e34d1876c278203015f085c3f43da98c5463a1e3fa3ae876681978f69c47e108c6a46efe382", .None}, + {.Add, "e8f845ea17d555feaafa8bf7d0c1f8a571a9b0668a6cfa24d3c4bfc743283076ead959e7f32173de7a6b4363f23cbe7674a21c1e495179677a5111ba69482fb9688b3b4d15dfecb30c71a9483118062e10e29755945e66d56d62b849076d88af2d3bf7621005b19b8cca8fc0efe98edb33309eef715ae8406006fc83d716728caca22fbae885c9ad9bcb8c4b96349807f13f8691451450fc7173e8a799bb746964ac8daa433d092e44865522a4d70f22646fd66ecc1bf79e6856cd4c1fb83bb90b599824e859104ad7a10e751bf610cd174496f715449f3ba62206db902ae57812eb39bb6de6a20c2f86657bfeecebdf1d118b91a0de53f33b88afd0f21e9e55296b00945dccba062b41ef86ddeb6cb3544c9806e52e2d484e5c9f884216f258166b4c8a6b7a00244b8bfee330246b55b338765f85f54ef7b0ad03e9afa086eb6dab6cb4fd5b5e053df0216b11fcd3096dcd8d0178363ad21f7c402665e0904ec00afbc2e5a3a04781b704f5069b3ec6dec2c7a83c190d8714f96829454942fa85c1a37e7a98b570d0aac9068173a3209e68b1201468e35a1d448196ed1f971a8dfe59c5fd075f3119c984ec75f305528daf906aa636079c843d7dfbc5d17ad01ff1d99b09b6cfa2a07c5adc7ed864f6c4137d8bd9def6e6986bb540410d456472c2407c9b77acd87eec3aecd185146be1e97cda18012c75bfefb6b28f4af117", "7b262f3ed06c83ffcf91c0d1d7900bad64690155e4e1e63de0eefd036f118911f780c75af0fb2f66467b08355c292965a8e400d600d0ae07c6565a7ec9ae99023f7ec7fa936e41a37e012288bd7d77eb4292a7c33e152fae1b6d99f19966a43bc850739e89f137f56ee42787932ad84284c21069c0a3ad772e0ac40ef1a71b37aa4d0c6b025d6d268c7f01e0c28ed2fdcaf90f717d1fe96b13751434fb9d4dc22a9b752e4d2f46ad5befa6b4a48a4eeb916c2db902142b117f2db6151fd98bfc4395b0b1eb0655bca73a8cff5e8955312d5a74beecefe00f9494d7a577d9036cc0746d65a7eeac1d42d6075aba5430f4738688b86ffead5bd7f8f25607743233207399f42430ae5b92b0559387932555f26339c6c3908c275c51813df6f6a6975894dad252e1690cb09e769b1cfbbb5cb666724946ca3e37e10bcf4437e75131b51c34068cdb5c5be4844dcaab25edbf0a04e60c3c84e0ae408109fd600b54d3cd3610dc7f78fd97a0de88b08d7009d2f5475dcc6600b633bdecd81a29fdc996246821cba1ed8eaee249f5c1b2e36dd6dc3216aa48fb913e2d1133e11c479dd87680a8e242180f87d83a78af72c36df394e1cd5f709374f6513a3d233ea623412669594c6c36f38f8f727e828285f735462a582dc8ee3fdeb655ac25a1813bcb50bff7e2eb06ef21c9c0727b6cfc69bd8d4b77874a188dced2b8735656861653", "1641e7528e841d9fe7a8c4cc9a8520452d612b1bc6f4ee062b4b3bccab239b988e25a2142e41ca344c0e64b994e65e7dc1d861cf44a22276f40a76c3932f6c8bba80a0347a94e2e568a72cbd0ee957e1953753f18d273968388d0523aa0d42ceaf58c6b0099f6e990fbaeb7488314671db7f2af5931fe95b78e11c092c8bd8dc456ef3c25eae336d4284a8e2c58c36b05bc389602c2343a6784e8fcdc9558c22b8f4802d8906c4fdba075fbd749615e0df5dc0427ce3022afe78483613f91c7b54eef48d6d35f66077edb9b747a7f65fe449f0bb602347f4b3ab6de810803e8e4d35fa72115d54e29725c6cd6b9411cd39098144a10dd014f1381a226f992d08849de9a8881fd6861bdf2451a657e920946afd1cda8beb96faaae20c6390d98ef6f00275cbe5b6930fc2a757e4d2026b2699ee8a8ccbf8d2f91b8d32de787d81d22c7a0bb8a36ba6122746f35bd22c0c877d2730db4bb1b805ffd4a23c5ebe5228d410c9f651c9ddf22958da5940b4899d40a2574a219c3bad2e640436f470c90aa29c54a1c86441fb2f4bec8345710f77a9ac7ca5d6474984a55b578096734f3047f02a83f1f6eb8f203fd9be8b6734622915dca16c97c92d577bb1f04779e11465b32e775edc3322feed95f015e5c2c0a3dd5b9a2cd36c54ec16165e28e812fc382385f867e9bfa48acad683e817e296f34f4616219ba4492a82a08e5d1076a", .None}, + {.Add, "-f36967358682f98d7c768393854a50c2ba7e87977d1e4372918159a1aa60408fa23a546ce207a4d0a26d07bd48158b2d9352c5a01111ece367898afd37ed0af736b83ce543190f3e8b96255df4a776f79b42a55455481564e3531d96e9ef6cf83c452c3ba4c81c926f333c72f4f2b2496b30f1926aeee1575518f80aa3edad4f9dd68efb49f9ceea8c7bbada85b0c057403467c8a5354233bd23b94b2f89d46bd4c6998639c85b83b94728f6cedbe0f48ee3237308a1e427e7a7af10288bbe528ba587309d738a2645c69c09e6595f4be578f2b4dd0fffdb960aef54760e33f5b5ac29074972fc0417e8b2cd72e327faa605f98539d28521579d5e4792e03ba8ac8b06d41cdc602d1b08b310f582eb8a47dd6d7cffb7e2e668c13876c94badc3df61b648f46870406c00222b444ca2ed48ab0d1dd59b34af0940363564a5347e98f1fdef983c98223af4de64c0140ef190b6f28549b737efce5454f761f6d1474a71c589b07e28078d86cbe4576944a57f7513e623512f93a77ac88e6c221308b67d10eaa4262a13b7bce2a3ca376ae4710a616fd972a3ca3ecb8d2e7ab16af769688092921eea557996959153d96878ccfb520aa2c218e35916dd0aebd886624e5857ba7a7056e2c4eb0123f7bb634fcfee26a9743571ddf559a209c2927989aa8671f2a855106588d612338acb3f587e0410cf4bcb100b8a359f0c91bdd5af", "e9d1761ae144cbb7e8aaee06f3ad65c19009d943845ad61ca4fb9adbf727827adf98d077d18a2e50993f4468ae2b50b3dd667e99699360089740b40faf24943ed6e2581334cfc0fbb21a6dc386fa73f58972f219e9f493f5f84c403f847b4e31f18055ee40bd65835af3ed33a6dd12998eaff65925e41d9c376db9bdd412b08d6cd6e433d5a618fc24842b97453ae57866de6e883ca386607062ad5529609d96a00a9761a3db675203a6e559b316aa05bf7d4efe4f518a67f7708212696d10a5ffcb5b836f2ae859b6d489bbce2addfbcf5fab6ab4e90802079f11ee452e1fe259bd496ac3442c09ed30962826892f02d4c2b7c003c9bd1aa5223b2b92dd58cb2e13606ef142d698ed4cbe95aa6254e69fab1d6ac7ef53a7f794911ef2d86ecf9df39a13743574b15468bdf83c8c08c85db2bfc1143478ee6cc4b44acb012986356b559ff8f62bbdb9e71f9a326a31a610b49a45cd8cb217ee95335b454e05edefd0d977d4b8d07fbd41cfe8fa7ab34a1306fcd54d1306c079fce074861ea96f46c0bd0b1ca82cab39b6bfdd785c586a8548a3ae5081234dab9633c5a8fc5eb8f02556b4cec7b3f636be6e74d99ed07cd728d7d4bd34b948e97b44572aab99f2cabad0513886845c31d6b3374d7aa39ddd19c70d32c0e475e761d34ab2cc6c58f34ece1f942b426372cd4091fbe6b40717ca62d7c20dc04082b53aa52ba53f29", "-997f11aa53e2dd593cb958c919ceb012a74ae53f8c36d55ec85bec5b338be14c2a183f5107d7680092dc35499ea3a79b5ec4706a77e8cdad048d6ed88c876b85fd5e4d20e494e42d97bb79a6dad030211cfb33a6b53816eeb06dd5765741ec64ac4d64d640ab70f143f4f3f4e159fafdc80fb39450ac3bb1dab3e4ccfdafcc230ffaac77453b5ee67f78f434075daded955f9406891bbd34cc10bf6062936d534bc022495ecf431b5a0439d1bc536eecf65d474b95059bff0372cfdbf1eadac8bda2bad2e48a1cc8ef2124e182e81501619474a2826f7d98e6bdd6630e014135beedf9c862ecffa2ab81ca54c59f8f7d14341c53608c806b27b231c0002e2dd7e77a6652b9989942dbbf47b4b2096a3a832501237c88f3e712ca757d6733ef4416e1c358032fb8f1797643307c09a24eaf84d5cc166bbc09c7b81ea99a40af86386a84f9f466c64810dbeca8da9dd4b8002583f7c2a85d7dfbf219c1ca8cb595aa0ec11dbc55787d044fbfb5cee915b6c6e1710d63e28d32d7de819e60369996fbc53df877dfd687e0622c651db1279ebc1bdc188f1807c93355968d1b50c3e794329ddc357365f42d8271c7a3a97fbf5d27a35e58d5f9a6f9b98b3c12cec6f839d876941e9d28693144decaa40bfb1f2d45f9c41748d680df7cebf0fc60d30b737a3d31429ce021608d1a18ee48b516639adf789bd4fcb0780646766189686", .None}, + {.Add, "c2b2525d8e08bfab63db213f637f92d88d0bbea64a32742d29fb8c276a9f23e07154cc1fbd187660334741781d9684971f55142d9f220a693effb65a9abec6741cecb385778f52889e332318dd5cc8c9de32957babad772ff427e30053b9e2efb75153ed24596c8687f14cb3605b200342aac3bc1470977095a37133cbaa18e42c8ca5e66ca37d40e1f0b1829744e6612cfb92a6b75f7b8a77a0b97a234890d461a88fa6e160951d12a685b00190b8b333b27e469ce06087ee00b91129fe1969cc04126c3b530f027c13454845449dd8bc573da314ce549d9d8cd007ed42a4aa87d043be5ff5035f68e3f1d2131af4838519cf2156fb3e6b4b6aa48a3293357792833b67632bc6a749a696280e4d72cc2c3a598a5d0b3294088b8026b22493c38339d227ab9ee0f759e9e9090a0f55147ce83e299f854aa62d108c08ad5e2b60dee8d27ada03427557e1742e794f600f9e52dd3a8b63f7f173155032e2f9424817ddd92d89fc15aa7167a048a86b7c0f9fb104a23ddcb293fabd25cea3d18ef8d9ef8567a984780f57e3fd9486c8796a0cb3072e014d18ef46ad1a8a5d32f05cd8c91870ded49fc4ea7ad952389543d378c18710b7d68079cacb576ba632387c529c3f6762fd15fb740d5c9600113cfea7e442e436731b58753372043d9f2c59446c5a7da16688feb156b8962e322a40d0475ad4d5b2a1e581b7a45783e6ef6a", "461a307c7ba6fa1e9b47aa00deffc9226c9b436378809563065ab4643a86d098527b59b353b923dc091e2f009f6f439cfad51e952136a9ea134d071ebce9540f4303e977bdc96db2815ece24f299c5c87bdd4cf8f49e0153beb8d886230cb35b0896a58e859ee442346758c654448fd0d929ba797b0a71be7a00137c0ef6448356133809d9af4f7ee4cc120274fba074375e1cc409be37d45ce27d96ad455fd39561e59828d3b92914d3a7f90413d41de936ab14895de77ab5d80446a59d0ce51e2e11cd5ec899b64e5b3d196c8f04fb24f26bde3681197b8c02e3bb372a6945c780b233aa6bdb55efcc301f33640ec4e9b8c39fb9e1412b15c8820df46b94bfeb4182e0cb773bacb379d40861e38ceaaa08c3be0ee52da9015b024dec2b3749a8692a759c6d7404d6c7d6d983eff9db46526a692f7cfdb04b6d912b3a4926610e5da02d349247467b31b9cea6f2f51f74e3767f4b6d04e901dff332f3e96322c618afa07f0a792f73b02b3ad83fed7a8cfab54b5c2efe18a4951829abe021ba901df6bef77f399c5c9bed2f75ff02a60f14eb38e70b3273c394431532cc625c2b75ee7f49eddb561bd31512f113ba5bce0817b83179a153ae6bfa0f5900ab90e4f285c31b4ea4312d7e07fac93f0e76257ecddf07f3c4da2707fdf0516ae74bb9b113b02792a8c574ead167862c89b084d1561c9bf0fd2660c539d8af1c7f90", "108cc82da09afb9c9ff22cb40427f5bfaf9a70209c2b309903056408ba525f478c3d025d310d19a3c3c657078bd05c8341a2a32c2c058b453524cbd7957a81a835ff09cfd3558c03b1f91f13dcff68e925a0fe274a04b7883b2e0bb8676c6964abfe7f97ba9f850c8bc58a579b49fafd41bd47e358f7b092f0fa384afdaa05d67829fddf04652ccbfc6bcc3850c4086d56459af6ac11db35ed4833710d08df0a7f70a753f0a344e46277a2da905a48cd11ce9295b263e4802a3d8bd57cf9b264eea3224399a1ba8b8ca6e8261b1d3a2d3e149a9814b4f6e19298fb3c3246d0df04f50f5f20a60deb558b021f1467f03486ed292c110dc7f966133269826feca377dc4be482ea30253fd206a307030ffb6d6431d486bf0603d09e682749e4fcb0d2ba2fc9d480c54fc30b1bfe28dff4eefc33aa892cf024856787e1d33e7a751c1ed4672a80e9589bbd3132dfd2042552f133653b9d6d0fcda74f54365d6e2a56addf688ce09068ed9e517cb8380ab698a2cabb9ed9a0bb0ac9f523df84fb1b0b36a0d7c26a103b1abb47feac3fcc77c101bc7f266e8584b630a415d9f8fff52b9043f06f028c27b1b064dee6529a8fe2f46c99ec8e95021cd7937517aff32e40d378ec52a7e4bba2ca18b6490c9504b74cd6310c33e66e0329c3b6ff48f0a13a4fe1d6e2dc8f931c4264189fdb45eb3f15518b0f171a39f0be27cde3033036efa", .None}, + {.Add, "-2e34b0dd6ca6923dbeff69d8df9513813a85a3ddfe3f0dc381185c5dfbb41f9fcf7fcc6bcf770953a00ac34ca128f7dbadd7aabaa45ab2f2735dc637c54fcda5434cbd5c285ec07632dad390b667b480e3e6a49c70a9677d4e6a3033f95f0b102f488e6210c4e21c50ed7034b9f41aa914c452d3ef04f1b472de3a16f66f1b7fc19d974e8ef594de776dc9e80abeb8065b509694dc49af33d1f4e1fd71b16976dc76a9773e8e96fbb6c874c717044211574f5890932b7ac84b458d4e1253da8925f32f2a7e753f5ddd100310a87f2929c9259017164eaf3d75310a53fa4f2b18d724d43b830e90699b3aab95f2c19074c0cc237212d44b15a47d49e73fc79e8cc72349cacf4f854f504eff0c757e6d1eb6222d540c2944e3cdbe97f5f8e1996683bb3f647d135347da66a71cb6f0ecc284d7d25e626deed5feded45e733018e3ddb16e61d44df21d74762f18635b4810949262f20d7bc9fd7e1cde9987951819ca38d2f973510d82eb8322f4535a94294d20da0f468ed4d95dfa49adf6fe221e73ae4fa711ada4a24750e8bfa92506f105b0f1d47cf2db0e0142035dece9714e6a1a8f925a3d601a08e3f4fb024feaa2abc21ffaeaa304edd4e9b44ea5e04741d9459170695c6273e11cf13ff14d94582987b93c2b53d5756890fb0f880c2a20392167326ccb93f858dce58b623ac0dfb70c77f88b05a288d27da26c14256e1f", "bd35d845565647b0872a6fbe682b5a4bebbb134b90440cfc45a4655290218491136ad933fc321174256ff8fd9dc4435f30302ca352d9e104be72fa02253ee71793384e58127bfb90117fb6723d6d3146c96c77389367b1b3ea9d24139a86e302af01a2f4d882814ff724c80159a7662447b700d26d84146b97fb8b364091bab9efd5f456463b6338f22f213854c1a0184ec53a4faabf35b0b2e2b871c174f220cb34ff51315a45c3f8e26add553f8e7afbc165045dd2baccdfed899c1814233250f70737591e1adb7f1aed4149880e8e052a1bba733fbbe1aff21f8c2e0be4702cb570c658392ec6e45e2945ba3860d869b5517c22168c48a83f9b3a32a4712cf3fddd40c362a229f47ea1b91f8da483980a82040501062ead291bc995678f2be797855aa74e6e831296e0506073ab198159cecafd57c5634f32d299b8a6361e3523dd2f6332dcfb0983dcd272137e70ff23d6d87306855c172a367193753fa5b9b7566bc0d2d7b1578f74d4357b2e09e89a206865b4b36a1a3561858d5b53e8186e960440fe2e5121fdd1748816b7dcd5b7a14246aa8aecce05deaf915bdac81031f9f8a6ce54b1abb2b42d458150a10526c7dcd8430dc074948acba0da397a2059cb37af5403a9c44e24fc02f6b34b77638b3c0141551ce518f73caad89050edb77331d12374cf11e201251d4307b8bd7459f96301f5731ed35a156e7f9d40", "8f012767e9afb572c82b05e5889646cab1356f6d9204ff38c48c08f4946d64f143eb0cc82cbb0820856535b0fc9b4b83825881e8ae7f2e124b1533ca5fef19724feb90fbea1d3b19dea4e2e187057cc5e585d29c22be4a369c32f3dfa127d7f27fb91492c7bd9f33a63757cc9fb34b7b32f2adfe7e7f22b7251d511f4a229f3a2e385d07b745ce5a7ac157504a02e811f374a3bace75867ce0edd6744fc388a9eebe55d9f2cbaec84219f6163e3b4c69a4720c73caa7400494a7fc4e05c048a92b03d80cdaa8db7da20aea30a108e5643c048ba35cf10ca43ac1153833bcb95755909c8ad52a9e5d49237dafc776d063a8e92e0a0f42413303c25152f2dcd2a02cda9375f4131cdaa42fa2acaa0f3764e1e854aff8d7c14adf6a83d39c85f5c563dc45f62a3b1b3b38303933a982be56fc81fc6c9ae9d68d5053fe3b45761d3a57726ecd8ee4eadd950dadba0eb836606a9173e6658abb5e990d57d80be0278bef7e83724d81ca2e6c0c51dfe22099e09b7946591f25de90bc3b17d7965d31c9a4c0465d2f5089aedaace8b4def1b0ebd006af6dc9b7afdeccc3db51a4726979a6176a664c90f497a2cebf32433165fe5964a7e1eda008d29faad67cfaf9f238471439c745f7a135e33133bc11a91ef34ddbd1ffd5ed7fa77c87fc2d22cc6630b4960bff6457e0d6b9051b99bb0846d90667e200d7fc52ea4c55b7a95a5a2f21", .None}, + {.Add, "15663616c6c5c56a27451bcedb2142d8f56b833facb9909f7beb54d12b6b446329c79f096fd726bee67ef9556e91305244b5187959702c959656e192b5c28c8df57fa7bab5d09d6e7945d507df7216ccc457643eb5ea16d1e0fa1994110d6dca5ada14cde53ff4ddcbb5742ae5987f968ee72042a954b45ca4a239dd07cdf058569f7bd7249f3753489902d590375ef217ee6fbe7c5f26d3c506e08f0b404eab27d10bb1e5ccbf07dd15c4d570e3aa1eb6f3c03403dc62fc8fc935ec2b363fd53fa543e0eb0aad178fa6f35cae4813989465b232cb11f1bd6b9471ec1ef60651d109e25925df92b51601bc6fc0b741b6290338687071ddd63c71bd1a4b65431a06acca41b6bfb498c10a513d0babb9bf51b4c9205d385e94e5e4beb1c31e98e008f40c98f028ec80db570db69fb428857276bfb3373db66c0d44d65c5d1c2a6ac2eef2bd5e3e1961e7f2135dbd78dd750ccf4af2dbcebdf87ffdbcd6a3595e3a8426e5799b579945c628373b2e57fc02c43147ea800f59cffacb3be67355ed7050ec2546ad5c94531f272ff7c78cfdbe8c9957f3d8b9a2c36e38dd9184110c1ec8bf626c7f17c73a17f0ac5a38eef7a074d8e79842e3d83414354fb892fe91948846fdf91de7c62a75fe8c0f5f6a600dd2f91c98fe3e3bdbd40653fc61dd8ed6129a6787d77fb1120ab7bfa4ce96881d13c24eeb5b0993ce95ff43a79881c795", "b444ed71a2b56035feeab71724ce4a6be70b6c89d1df4cf56562793f46f250a82ae1ae8fbacf36b037ac819262d7b94af15b2124020f5a43b2c48663e111818cb21385006ce6a31399f186002351de1b05bbc39e27d1991a9bb784caafd43a627bf68e0b9b1d37fd30a003f185a3f1c41f42a8981a02d7483864824aa2d1b3497f73b90899ffce928604f02e4b2cf658c7c16e8408a548f2650e0b629352afa93d9fd065df10bec36fea648855f637c1c84131015d6f2aefb6f0d0ffd97f60d9e4fa407ce51c3217d58c3f0e5db192dcd8274b9d997456d2f77258a5e0f04f6b0ffa48810b2a7a64571ff5e2bee6e01b7995dcf50be241f3d4f22cc9ce8cbefe59b6db3155e58bdd92b073775f2b3da6ad290202340247aed116465b4e3a34bf6b126f9587e85ea2f98294511361b0db4188df420753576585724955113243ec20e2825ec527bfd264b68e7c21f683541237008c9488921daad8da475d41dce060ad1cff9c811937f7fd89fc1e2036f7ce305f5f6c3919b17f5283cc21864ca0c2daf6de7d9950bd87b37683a07955f50c247a198a517a6ccd760d3eb8690b1ee5f04f52a00db5b85d4ae0548d8fde1b35a2c8b13fa32f89703082b0090ddbb6686a687ed1a190846018ee748c03a9654e21819e3af81265a9895b071f3b1abd2ac984e084bc3814835a045139f41d5f71a207a727e7b1a661b795be71a17117", "c9ab2388697b25a0262fd2e5ffef8d44dc76efc97e98dd94e14dce10725d950b54a94d992aa65d6f1e2b7ae7d168e99d3610399d5b7f86d9491b67f696d40e1aa7932cbb22b7408213375b0802c3f4e7ca1327dcddbbafec7cb19e5ec0e1a82cd6d0a2d9805d2cdafc55781c6b3c715aae29c8dac3578ba4dd06bc27aa9fa3a1d61334dfbe9f05e5ce9df303db64554adfafde4285046fc62a14ebf19e92fe546570dc17c4dd7dcb4d00295dc6d9e1e07f34f135614b8dec46ba06ec04b5a0af249f845dd026df2f6533326b0bf9a6756c8cfdd0648648906306ca91ffe655bce1042ada310a0d196d21b2527f9e21d1a299155d7c541fca1163e9e419f202186063a5730ca5407653bac4b46ad6f765feddcb22913aa643b6fb050d1158cd9f74067c2e78114b23d4d9a207b315d960b3ff9ef53e910dd192b71fb16e4e6e56e3d1751c2365d9344ca8a1d9df6f60c91f064b7f705750162ad6971e009b3b1ae4d4027937d8b27dbe25c1374c7832fa9261a749ec4873817a1dbfb294dc3a1113c71c252af5e510a6daa67b680653b398bdd20d630b1d303baeead03c7a173daeafb1bf1f257cf2753b8caec67ed5bbaa7bb049828707bd8465d2689c0c6d4af0b16677ef8956aed6177a83eb6e0973211a9e3739364e417d8faf038118a9933d63ec685c3be9268e11c3f6088aa57c8564569282f14574f7b6d9660a2338ac", .None}, + {.Add, "-f61445ce3bcb5d04ff920e9497667ae8935c3de584dae64f46bd28296980280ff48a2a3d3f5f49f7d57517c95cfc88fa6f502bb178cec36e26f5810b22a38fef9c371423b816fbb8147628929057bef68695b0f284311eef59c7693025c37411c85fd2e5a102bb93e44910d48d7c7b357554536ae4d7e273a856892f8f5ae30752127047c99d8a6e08f02c119e084c47f99ce01e1ad9c867ee495cc8c2701ea67606c1d40366e22994ad6e6b05d49dfca25f95379eb041502c729ac5892b69f54e02eee1b0a65a1865611b28f3a4f93a28ccb9a9bf87bfe76ea91aa5f4513aff6c26361102ae98b7c326d4c190413a2a20b4144311115ff6de7e8fc53b2d3d6f4dd4f32b0ebc9c09e36d7d4db0ee2fff0016cb6dc1a0a05c11229f0c8e443ee030b83351be5722322e9d6bb325ad1ce59b954f44e1093685ee1809726b677db68ca4c91e8e2ddd836b923b74444e94a8a5cc45addd4a3f9aeb05a9d31f455a5af4c9dbcf812d86152e63ab0177bd750edff1d36207fa8c4160c12c23ab61f180690d4ed35fd06142b8994325a9f6155671ba91d2b00873885d78db46ec5eca3a7ca465a557fff6c3066e7fb5ac078f70b43ee4f753500b99dbddd318a550f8e003f70231001bfdb2ed5a5df8c39c61ecfe181f4eb9d6c58c397d447d487e3d927cd782298ee3a58e281d88c4873d8b66a89cb11c30229a9546a461c5971e34bb", "d96472ad07a40a32eaa833537081461152c53299f8ac3972d9daff730e7e6eaec96a2d876c2da37ee9072f1579bd7900e75fde97257e4159b2cab40cbf335b06fd8033e0d2acf8ac511169d860393216bb128b5832c34f25f042c646927fc2b5976642ceb4a48aead8a38e2c10aefc7e66d968b51cc1e90e40d5da95060c788d01f49c879efbe5f14dd037b67eebd38745228579b726b480345b8f92e3dc72c0a85130c8494ba16bec2a3c158130988055d68a46e0c788be5a2c9fa752c932fadc7a9555e1d9a85ce01ba7678083b97dc7b53aa41e96f95c968a444efb7521cdcf54400e6381b36195b97b242ab736def78804657b0047189af56e23ed6db80debb91ff47f849a53f6666dc10211c65baaa6c5d84467121287e0277619aa9c5b339e2200f2379f0e9a0a45b317bcff1ce0b4a6aa82bfb091aed09e86e9b9e8a8d798583c1dd01c4be577879d4feab38aef339175f1776d0cd48d6498359d7c905fae4be2a8fdebf7315fde0bc600a4803673e9cd63533fd0598111e7117673563e9fc5604fc2c4663a224b137ab3844fef29e59b1dd70012dfd9cb550365fd6f85f727b720ae25d057a2cb64a26340d06a94388652e36e23f5f9c18486252e04a282c9eaa0a73c8c7eff0cd7e6bc0380a5306bcad44b887600312c417df19f5e0b0c95e4d3108b9bb4f9053335d68de5264a0ee459cfe76cfd80d5b6be0fd8c6", "-1cafd321342752d214e9db4126e534d740970b4b8c2eacdc6ce228b65b01b9612b1ffcb5d331a678ec6de8b3e33f0ff987f04d1a53508214742accfe637034e89eb6e042e56a030bc364beba301e8cdfcb83259a516dcfc96984a2e99343b15c30f99016ec5e30a90ba582a87ccd7eb70e7aeab5c815f9656780ae9a894e6a7a501dd3c02aa1a47cbb1ff45b1f1c78c0b47a5aa463b313e7b9edcd35de93abe5cdb5910bba1b40bda883325584a4057c4c890af0bde8b891d245fb1e366236fa7188598bceccb1bb854573c173213fbc61177f05a0f0c68ad81ed656f8dc19319cd1f6029f2ce5562d6d599d658a034b292c0fdd961118de438921a14dbf8561621bd3368f3801b5ed070f8caedc69a3557005957d398e49894277967499a284fd1a1150cc1f8323949326000df01dc8bae0a89a5e4985f43f476aeb81ad950db50c70e2705dc137861ab3d6f463e11db698b437ebd2d28e1678453ae9a7ddca951b8fecd82f9a1dfd03ccf5b1bcd08ea97de994a4a74c7107401a3c99eb7e2a2a6d8973100d9cdc7e76f8122f4291068290ac37923173757d9f0ff1e8f8cccaf6ad3dee3751d0f2aecbb45109a44ea049aaac71006c9d75e5e411941f2bcadb617438465f74c1266e5b5120dce05e6c58e7b383e58b3d16394c183bca8c9e3471caec44bbd319f2732483915166fd818252a237d652b32849238c0ed90e5bf5", .None}, + {.Add, "-14ce2549615849d1822b0b63c29830db6b6cef4a505e5afd952eb0f42014826d4e6296a4c0e1508d3e16dbde06f9a4d01da97cf85c44afbd65dd584cca07d4a7ee20a7c8c6e4b9de14f69aa20afdf55ab4cd9a5e779533dc345cc25064471ce2e65c5d1deccbf14a4b900d73bdee1330b81fdb653ef4bce96919ba401c7ab62218aa03bb1151073742e7e3ec49efd528846bc78f481864ad5896d8881578d79810de4de115780f3acd0777ff9722b31e04597d5d583fb587e67b8945e943b219e2c24d6e170666466ddb65505535ef7eb194f4acfcab090cd1bacb63c683c04b85f981b37df418c0b2d2496042e87a64409950ecc13dc6aaf1bc7bbdd4478a5873215a257272b04b12cfea4df868602979adaa4659e0abfe6a8364b32ee08012c35785d211057e24dbb2d7849b9b095df3a6aaafb7c0bd898a36fd3a51dff92135195d8e98916d1a63a4c87b4abc2cdba8adc602fd403219837fa7e421df13638ce2a94c8ef45630babed02b4e6c455f1671c2461b9e7f460945c22cd3aa0a0e6065cd74297f57f4249b7373154d562a11fe82e98330edc366aa6adba8160b0c5fd924c2d4ce83357c3e3c17bca817014ce52c0b6bb4d5ec55418107ab7bf955769835e2701dd90c2eef37c4eedd8f7a606897c78ac311eb9d15075846addd3cdfe02403f46816cb26f5deed7cfaf57a1283ecbb8b72cbb71f49281b86bf01ab", "e8afbecd4616c8761747bc5dcb1e388a4c2aedc5786b9d4c100137fbb2cb8e0e596c0468d15092395969dffb7760295042d5322fe2c64f799b8bb416b33b69b45a547488dcf910e0d10a4d6aa9aa7ccfd321af9376c4b98801a403824fcb7b473930651bcf7bd67fe53a28c4d2502e4d72f34dec8eb6e194cb14cbdd76532e4b2482215b8fb4c348a5ccc4d9b80d2898be54f14468e224cc8ea43ebc6c5a992402ccfa1e2ea1b5d90b13629266860fef5d92130da76ee56fcd69dc6f2dff28cd684e6d3a25263b903b861e76ea738b015210a2be89c2b19fde0074a57df3370a3be8ad716c3133d82fa7896265f0a50d737d692b4494c871366f08dac373f78ecb3699ca10b2f3dd3aefc2d31aea2714f2131540d06ccaef3a4af5075d384555bc179195745720390b1837df37f3bacd13bd3ac178dce7fa4c75374cdbf76b655705d516be3f328bc2b3c0976103e2166d5a3e1ce4d79d95da5704307099d43570c365d3c0ef818a9a0edf179c5d69d1673bbcdf3ac2296cf84d606ac4945f641144e25db4588ab0a1796b2940c91a9f3c404f2dc977c5a1e20e69feb4aecc71f0fbe33c0c03882de244a1a7df822f2ba669b6a6e7f153844e00219b8c641e0b692416908eba9615f5be384cb49c1863f051093750b26b1865eff96f9efb704b0b66b31295e94400854499daa9e831ea295db46b00c05cf6b87282b3a101c0f3", "d3e19983e4be7ea4951cb0fa088607aee0bdfe7b280d424e7ad2870792b70ba10b096dc4106f41ac1b53041d70668480252bb53786819fbc35ae5bc9e933950c6c33ccc016145702bc13b2c89eac87751e541534ff2f85abcd474131eb845e6452d407fde2afe53599aa1b5114621b1cbad372874fc224ab61fb119d59d878290bd81da07e63bc1162e4e0ed6e1d537039e929b520c9c01f360d663456e1c18bf1eeac3d1929a69e3e0bea92cf635cd1593895b04f2f2fe7e6ee532944bb76b3858c1fcc0e1fd549cdaab926953d9b82a07bae118d17a8930c45a941b76f76beb5ef2bbdee3d1b177cd5400223082aa932e4183e835701c644b28d1cef2c6d3658153fa49e404392281fd8852281c6eb78656afa768c1ef0cfc790542e57c542f8c00bc36351a2142f65605a9c58b16f20169011c11c2a70c23e3a128a17724421ec778825adc5715f0ef81c1647b53ac4ac7819e7976b7c56d75c4c4ebac0d1e3e0bc8731fb2b59df500eec4df1247250c9fa991f23aa26ef079e3df0ea5555b0df14e98ad932bc7cddf7b62b7bc4752a41cc444646d7de7b63ff230c98c1659122be79373504f86606659022da182a59848a9b7c3c7d97f8bea093e0e824b5f28be0ae1e9cbd09c6cf0087c5be88e98fe8716fc5ef592cc8daf217584d930e2b868f0ea1812d355e4ebaed2ced3c7016d9c7af754d913f99295a981a42bf48", .None}, + {.Add, "92c7df32e0953b659bf548319a4dbe797782713f871370313cdea5d250fc7cf42143245e08e6f82fb5de4d9c3f533b5e2edadf15ee239115b5157f0b9cfdd0269f9b172e488a3cd7f7e786226f16a89c621d11c8bec3fc5381313ee5ac1cc2b4a1ad3e8188b40e3b8f3a2e2d0fae2206c819a35ff7403e693e7be16f73700e41b3abbd2ac9558672331dba908163c7d8f461d2831fe503cb9c9ab4ab36ca6bad400292c28a961ec45df19055926aec7bf1d9c97257734417653dd8824a0a313b4406d3056334b1f91badf42082bd4cadc4d2ecc00d3159873e49ec4399e212d47300a574881564648cd5e4d518c5261a7e907956bab9e66a28eccae6a228a038843949dba976c0b11b3e5cae25907dbfffc6fa96d434261cb3dec6f3dc2a3f08f8789fa34e4c6ac8d23d94d39c3fc8fe6e11bc0235412eb0662dea29f37b1e68d80fa28f9a689f468223687ac702fd93c9c4f7ae04da81d4f389aff104af47b50f36c332b1646fe48401967deb46e84aabec4a28cf716d4c46ba26a3c5927efed2ea02edf33ca03075644aafedfb7d0f9c1d51eca4a87ba2fb5965e68dda523127116e2807fe292107817a5920c45750aa3684084185406c24c0456fd08efdb11fc36f45110b67d1e10c2312a8712946eb6a36852a1d87884c28566f68bb7cb9b044238d98bbbf6184b20a12367bdc2d22c08862490ea388f240155088f41ca4", "428db20c1de14018e892622174f7611b008879522e6d47555fea4be144cb4a5a7b082216ceb280a275603713fccff1add1bf213c6b7c1c15f1c16c99d65b9d994a719f369c0b9dd5de2445ab440d02a27e049eecb248dace311094eb49457760309596716a5849d6f7cb3b456468420ccf14ac1f98e4da19f85f2d43779b40550a7fbefe1efdfb67341da563868e90d7446119e1352c7b60d3426b6356d0f7342b326aca1c0d11335570770d2c44d2bf2567749fa5a3684629535e8d1d4fd166ecfa61e3282405dc3b4c8650695667c20db0146434f3f77bb2b6141c81895ffa3556ca849c47fec643b825f8c393dc4148defa50ce10974a416e011fbcb69ffc06b95b5b18539176eaec5e40641ac5498900673d994094825dbb3c598cf1b7997d155f379b8d4108889623b2739b5bfe167e13e971c67d16d93c294dc63d4c258997228add71a5697f4a64598c3ac07591818daf1c31f3b38de9ee7faa6d2e48fba6929c2c7e9a21e8b5a537a31e56c05957eef5cef3cc7dea2a3db363849e52ad83a66f6c67eabf5a247617bf3942cc20a117a8743941f6f858eff662701c0901be5d1595db0f8a8dcaaab30bb6bf196a9eac805e2c966052cb6446420828e9aeb679ea5eb1d91624f8cf37a00d76bbcd99f158eb6fc16642322e39cb8549affd970eb5788f01d80583cc50dd5ed4d976639e335cc5030402d33a4c91700d5f", "d555913efe767b7e8487aa530f451f94780aea91b580b7869cc8f1b395c7c74e9c4b4674d79978d22b3e84b03c232d0c009a0052599fad2ba6d6eba573596dbfea0cb664e495daadd60bcbcdb323ab3ee021b0b5710cd721b241d3d0f5623a14d242d4f2f30c58128705697274166413972e4f7f9025188336db0eb2eb0b4e96be2b7c28e85381d9673b5ff407f258b038c2ec6455117f2c6fdd200e8d9b62e16b34fd8ca6a32ff7b3620762beafbf3b17413e11fd16ac5d8e91370f675a02a2310134e88b58b7d556fa7a70ec13b46fd283012442255102f10000601b6b72cea8576ff9245d632ad08e0acddc59025bc76f73a788ca7db46a5acc065edf40348af2a536c1ca5228062abaee89ab430988c761d46d74ba9f119a034d691bf6a2758dfedae9d9abd15ad3b8860fdb24fc848fcfeba707abc73f6a1377b9b86a8e61a6c51a77da44b0016dccd4533dbe095b46855d210c758881739e70af1c75fe0add55cedde30a066cb73bb58e653f0b0544391e9e6539ca30e4645729171d51806da95d5fa48aefcf88c0c7ad34bfdbbcbe699518e1bd99f3b255dcf04a6e3a28cfcb3d9dd938ab954c250c2c7b166a14d530889fb1d6cc778ba9b61297269ace79e92f6fbd40e80604f24a487ea002b90427de158d48ee8e5a84a93440c669addb3243114ac1398a35d66313dab10699242695a5d3a68cf5134f9d1a642a03", .None}, + {.Add, "-e3241aeef7c913bb930aa74d697e40018f2632604fd16e7b5a307eff30b49f39e7d6705027bc92bd2714d8a54159df06159c03187c7d50f335e72259714f9fbf4a7965c7c4c6db60e2213293761597917491f89d76a3fa6f3575a5e06bfbe2a7e188126fc145f27d4213ad2e327f550e898af700904cfd05a3c2dc5ddf23a500624a7e67cf5588c572f21bc45a8d216ebb15713ab30faf369653b055befcadad88d7583a1fa22319cb50030b396f6cf4c4d0db45f52f38c9df218e1e0d5ae1333463484914399c6e1308bb5ce0f2a0a57577af5d43f08dc11c5e72f6506d72dc13d6921674b6d47f2f8784d4375c343e23aa904fe0683d8662a4bf4d7bbe9b8440924e6b7764585b4d6083123de069aadbda47f624811d7273c7915376335bafdd91cbef90e7fd75985f4fb141523f6e5675ec40ee1d7d2d810cd9bbda13a7f3d766a683ddc6e35ae6cc905d07651873d6c9b448b6ed7eafcb8ba942934ef2bf9b389425c93864443af3f303e14f699cb2c03eba812cd87168803951d99db27e1b87734433044d3be368d4de81cae184e2eeae04b6b8eedc69d2d4c0ecab0a774cefd5fe0eed1e2c0015eb8b45e12dcb3d34918f48589d6e0e460c67b92b60a0450d0f3db49e00c74a008fd7af7880f092a19604d0c8685e8465cdec866e94cbe0b302a9003ec72bb0123f5ef4bd5bbed7d8f814b4ae7a92310391c1d34bfb90", "a19576ba4704967f1c2dcf3d296afa7ec81b8256ef965f7de87a2e8ea6717eb381b12af7000fdbf919ab38f34bc7b92dcc6ef161a3a0416a8d07f2b77bc961499c172a19e1bbf2dc0f0e7cbe778dab9d4f0a4a4c67791a1e7c7beb1de8267828ebcd3dc91286a0a7cedffb7e0d71a93588e2cde514550f11556da549d3e40e1e01f67e9ddcee16d268dd2cd556e86d9c9ce3460d3da74ea2cb49d98d9e5740e3722b0cb68d9ecc1b68b7cb694360b47fec7539f8675103a7ba9d8d26026811b229648ca964066f4934518c827cca5ea52022b16edda98dddc685438b08bc06f693b20be7509403c7a2399a8d2c269512c846d01f557cdf92bd9ac8ef64db37bf872a92fa86b191dcd807a67216e9a038b8e81ebc61bffd9e9a73b0bf55d8defb8af87f6ea5b69a3e047eb58bc86468c6c86f814c2703b2253737cf53421aed183bc164364726cc84d339015b567a9f78f07e3e60e418f9aac50614108d03f0b60333b2f150a16670b71e8ee5239c9b1d645c24199ad76ea210df318e32d3174eb495519a925c6c653c7c4fa4f632a32d920082679578ef79d03c2f8297c176d9e5bd8284e533f552546f2b534e3a2a75b4327e3b89fbffc7adc15c3b49cf027874fdbd994131bac5c5237f8db7b468dbed42f65cb6985063463a06a61dffa1c13d07c1527ef5cc4ea4623a890b5d89c96b731a64c2b53d2a135e2a1b5e86a11b", "-418ea434b0c47d3c76dcd81040134582c70ab009603b0efd71b650708a4320866625455927acb6c40d699fb1f59225d8492d11b6d8dd0f88a8df2fa1f5863e75ae623bade30ae884d312b5d4fe87ebf42587ae510f2ae050b8f9bac283d56a7ef5bad4a6aebf51d57333b1b0250dabd900a8291b7bf7edf44e5537140b3f96e26053ffc9f26771f30a14eeef03a4b3d21e322b2d75686093cb09d6c820a56cca16ac4b83920356fe629837a1f60eb874d85ba14d8dde3522248400f80af2cf810afebb9fb0332d24deb72eda642842005554fdee6646ffe355d92f6b47b16be58024862f2422d0b78d4dea470b359f2b5b63c0308aeb5df3a509f65e16e363c4b967bb70f0b2c67e7558dca026f6c97222f22939c2c11fd3d953e094205a7cb452994c80eb31633793e09a2578edd6a78e066af4c719cb0849d50a6897f8badb9ba5424d96a016d613938f01b0ea78fae64b75e7d2d4850506859532064b02099804e1347896fdd383d5641ebdb2ce7f4e641aa0e65569cf57a107c3a6ca9b2f66f221a9a0a7e0d6a6ec85398b983e5750ee2b9d213fff629996a53e54e9939d6732537929b928d9aba6c037f7a7035589021353be5c9da66084b02c6f5c5e27d00f51a4736c460184dd1049f7c41814a55e9fa81a3017fb3e2bc746686ef30aa3ab41568148fadd0bb004d5e95fd1f56c65ddaff1f93d681da567a674c55a75", .None}, + {.Add, "-e31119579857340c5b32826075a7f763f12dd5dacc26d0ae5fbf193c0f7152afd3b902dce441e50cc407c0451cddd59baa576d8c530f64cce4b498bf9c821bb4b6bd337b0404db24bf4c317068130a9493e3b14ffeaf6f4694fc7f9f5d0b1052cd4fd1971b41870e15a0e5814cb11f3161ee5812e0637a8784d9a247fccc0af61c6f1734e82c26babd3fd52806ed68ba7715b00672bd526f9704b97dc515fdabd59830cea09e9915fd863d34f11451b57b007580fba3301502c597390592b3e70fafe092488f3c9f921616e24b1be2b49a4e3b152b280f9273e9b3dcfed339ee0d4f2a63c3a7abfb8feadeae42900b52013cbd60146e18538c8e6c152d2ce55cb8615b0470b1efd20351c2307d8a798262b3f2fe6759cf3dfea79c812a5d772889b0e45b8bfdd3679e69948fbb346195a053522b5d3201ce7ee7c260cf97426e1210e201ea4c9980807b2713f2d95694af411c635a17cde722c426eee6a5a988ae5ede6a3134a9c4049dfdba2291827d1cee6c37abf19b16e0e1b972799b7c93d9cfaccd8fb9318807712d79f8e33cb9ba62f417a886cf70713974918aee67891342cdd00019586e9a95cc23bb65b8f3631b6f576e445ab18f9b71eb63c52663cfcb759d4b8876841d2214c83e8859d252abfccca5d52ec53bc6f068367f7227ab1c613492bdc5c23a7043cae54776a95695352e70e0f7e22967eaaa22d0957e", "2dc122a54b86114c5850c2849da6a5456833d8231cbbd2e4eec07836037bc20dc04a1fdd21214f21669d095123195725c1c3f239a485770f9bed57512638912d9e8179f3191ee6e423873c1b323b9a275b06017115cd320e7b1015637934685df99642cf2e75c064b615e5edb20dd1002aa1022f1a27b6644fb5ba4383da7e94d4ed4f8e354fff75e2937b3efc12c51a30c35dac9877fcd5e38b715654682657aa2718927a60167408e20f5747b5c76719135474dc50be5f1a56377523fd3ac349cfac59a84f5801a5006bb3544bee1db58801293dfce6bc8472844ba8d788ce6e86b0ea37f1b088e9a3299cde7b03974173462d1080289e42f36b66be7ea5f8160bcdd72ef6db40b7086b75ba758abc9819c9f0a9c17af9809b716d4d1a7651c76e84b08ed1f3932b21d600c0b5919898ee8032e0babdc49f3c06970678ad16c5460f0369109604f4fe9662f1e5f0501d372b6635509aedc9149f9775b17e3212c69cfaa0172751a6adb9365c75a1efca087aaa4a7dab30e4f0f8fd9e9301520631c3114176a046e790d13f42880e9ed53de04445bfe42cc4b06f88071bb46a99c85f191edae4dc0f702ccdf174a4a79e59ab7bb5f64803d765b7294071886ea74e51992bb758f8cb08bb6adba8385ed83ed531ba00cb98330f32226d744e573e52734d210836ccd66a94803cd233256a96f6e8f92ff0c6520dafd16b1f4734", "-b54ff6b24cd122c002e1bfdbd801521e88f9fdb7af6afdc970fea1060bf590a2136ee2ffc32095eb5d6ab6f3f9c47e75e8937b52ae89edbd48c7416e76498a87183bb987eae5f4409bc4f55535d7706d38ddafdee8e23d3819ec6a3be3d6a7f4d3b98ec7eccbc6a95f8aff939aa34e31374d55e3c63bc4233523e80478f18c614781c7a6b2dc2744daac59e90adaa3a046525259da455599b379482770add7542b71183c263e82a1f4a42ddda95e8a4e61ed210c1f5271b5e86f5fc3e1957923c5e03438a03fe49ded15ab2ef6cff496e4c639ebed2b28d5ef772f9155fbb11f9ec879798bb5fb72a647b511641507babfc9773303edefb5499b00ae6eae3f64a2558d2d41bb14914c4956bac314eec5ca9a290dbd9854447e0c2b13dd4300d6c2425faafd2bdfd47347be8efa7ecffd0764d1f87c774409dfabbbc9c91e95574ccad2fe813c037b8b7c90b100f366449209f0fd24c732f959af875770f42b569b98416f911d82725df04483c61be08d52e5f18d6173efe5fbf0c074db087b41d39de9bc4e4291411fe05c3ab65b2e1ae52513d362c6eb43ac89050983d2b31e797a6eb6e13e73928b259f55c9f1144bc4c1c3dbb84e12adb835bac223539df5287d24041fd11d8b5219595d62e021737a6d279aebd4632d08b7be45c90b23d06cc9ede771b58ef56405af4aa8754383ebfe3e4577b1071bd75a3ad8b7b14e4a", .None}, + {.Add, "af19a07326df616f4fe2fc1964aabdd2049383ec58ce926f30249b391e060ca98e35cfe9ecff62d5ebe889e1e507805e8c83123e8f8c7b0fa2e7a29c32c2b741a91d71144371646051e996d87616a6949bc4d128e3f1a1116d0519122221c41c7f841efb9d925611e66226b60175689a22bf577e174699af48c8ee6d1a96d50ef51e47b4fcad205786ee4ca11e102d4ede31266bb76e4dcc8b9f81efd88bd142bc9e40f284db55680a64d5d64b0b0d3073a8ae994f2dd76fe0c55b3d89ff4c4d35604956db8fec33ca684b3f01170f9d802925d68aca85105bd706bd9a95158e5ecb0b9d39164925e4570b5c6c81050dad9a79a37debc25e6e7a79b164e93d78e4690217ea0def6154dd1d051d447a33e01a3ebada7bd6f35bf0abe70ed5fba3b87af69a9bd559e800d670a7a1490ca1632e92ff681e9d683c6dacbff14797121c4194ea3007e26c57ef5f82d448062fb86083c94094af03c010072a90968253e1b59d0b1c469e85a971ec1395fb45bc46412225dc28fabebef82ccdd9edd1a1b5d3a22f690f52b2862e9a536ee950b2a8dd6e85cd2a1e15d7632a5e679c7a3dabc5e7eeb30e6e9792f970c4a40f6f18d0c8c467e7641920b0a9bab349dd57130dbfe368ad7b81572c34348aeec6344e808a5fefa89a4517b1b01f9c03f5ae939a07556edeeb616ba93dfe66e30febb64348f8043984248f4e87b8ae32abba4f", "8e04373d11d962d8c5984dd852530641a059af70d19e2f79727fc43b7510a13a5a57bf728f0bb411755afbaad6a87cf7a68845d8df58a3d6e942933822cf5c572b51fa048244288c5c22bceb21601d2c03a8181c31276b71ae56bac624abc38cf444df894e5def7d03da7817c4fa4b186de8f256b89de161b7aea590dd608af70b7e12e946496487922d0c9c6dab08c29f74500400695a54893d9f92cfc6f0a15cdcb5dd5cd0ed72c670b9fd90059ac230fa8f463fde8c8694063259fab1835ef494587b853c45987912ba279e237a50a25f2e67f5fa612cc15a7bd45357d088ba15993bc2c09ff0799f2a9fa0b14ded12d4e0271e3a563e2d7aae87273deead5cca0dd7f58ffc087c24cd79f49efb842e8159c134259d10f7552b38c208b63dda9ebad0d1c8cd748bdcf7200ad83dfd0872b59d9d1d0dd08eeb1d97135b57c6da824f085f5ce95c0a9c2f0706d1daf9093eb5316391df5f3cdc83d53dc7abc6b21e9bd9c94bcea853e9f79ac0160b3095e1bd2e2a039c8a772a976502756f7510c28f76291c04acc5558ad5e915ef21a9f6ddd49d221f74f9ee3dee926b6c6ddae45dce8ee2d21e382fe0a696b97661ea2c787bb3f0064008d58cf6c941d46572761367771c50ed530e91912dcc2b8a0916f1cb7ee987288466b093504a9470380e5b5131051b0882992585b7b3f5d2031c418a9bf2008b74446716f74d1a08", "13d1dd7b038b8c448157b49f1b6fdc413a4ed335d2a6cc1e8a2a45f749316ade3e88d8f5c7c0b16e76143858cbbaffd56330b58176ee51ee68c2a35d455921398d46f6b18c5b58cecae0c53c39776c3c09f6ce94515190c831b5bd3d846cd87a973c8fe84ebf0458eea3c9ecdc66fb3b290a849d4cfe47b11007793fdf7f76006009c5a9e42f684df191b593d8bbb36117da5766fb7d7a82114dd2182a852c1e4197af6cfe1ac42dad0d58fd3db10a7f2a4a33ddf8f0c63f674cb8d9784b0cfac29f4a1d260cc31cc437b05669f3a89ee2288543e80c4e63d1d318291edece61718e0a4d8fbd6e9165df635fc0d3252fac06f59ca9c26189c9bf528388c272c2641330fefdf9deb69d101ea7f11e375b80e9b987c0ea174045345d71fd0deb1e19319b16b6d9e275c8cb367c7ac214a9e6ba1489d053bab38cb58ca5704a2eed8f6c3e3f28f64cbc8628b8e89db19e128c19f38faa4268e62fcec8affce5e2e1a93d438e4e5926d2dfd5be3ae561150ecdc22df54062c97493622c432dc634116c69631a5922b575f4b84252957ff3fd452d44c5a6a4c3d8ad151684cfa07e6ab86aa45bd41f140b5cb29516b3ac8e57abaf53ce39b541f60b97f47aa131f2b788035f6d02497d2447f42c61c1c925fd889a151bb2783cc403616d02f54404303d215b0c00ff07c742bd723ec9ac3e1884665398ed576251ac2cc1fc529f8d457", .None}, + {.Add, "-ce651cd7600fc35bee0ab85815ff5cb13f233ee259e92909e8f2a7fcf7ed0356df517995c1ecb5cec38a054e5f30ae02776362cc2d4ad3a4e91effd3a85ae6576d57dbe1ac1bdfe3a1e764b880837fc59354d55f67ff231f398a284d67ce2443bd9c20ed6c9c5b8c3d8880526b55c2180502ce323e22a6d9df2fe8dd22c0ad653248a1bd264d012b7142487125c0d02686f9ff833e89845c7b37a528dbf8d70628190af4eb6c130cfb3f27975274166903763cbf3d22d8c3be864e35a5f97996a4184bbf4ee1ef73717c38c4e5cc0bc74b10ebf09cc9c01ef429bad93ad4bba372575bbb483eca1ccb72430bac66e69539225c089a096f7dfd64a30f57b043e85789240f850e61f645d73a70c9c6ad5f3a843ef78ad6afc4ac73ad097a24e5c204bc92847a86bc33b0fa0a381aec341fde20dbbdc5dec37eacc25d941705a8ff18907817fe39a890093c8c7692fa0fe92a2f208cee7f77d084cc689ba3eecb5dbdbd4dd0c7181ecfb7f9f53827adfc0cc83e2076ae8e2beb14557c6c7b94f1f387758418a036cb6dff82171f8999cfaefe23d865928448ec4881d131d85ac5f0dcdcec08aeac93833119ac05170128c7a5c8b539839caee91ac49bd741f9ee1045befa3388c8b7dcc0e619e5aee20b39017a067488c71a3e66ea43d59e33ccecadd9c269f9c6ed6c82f0cc4a4716cb22d5ea6077bf8a44ac3d70c4739a24b779", "5fb75dd2d6f2081930d19973f4d8c0ed2c169d284afcd40838b73a33b74032f02cd3fd6b09ca017a8abb65faf60906a412aa0a46aeedae442386f0c2cd060f87d555dd815606e8dd592b1843844c93a40aa671146cff8299b38b66e855db0bdad65fe5c9ce1acc62c1b85e207c397e43f531375407da13b3059ce4259fc6310c98a722b0bd72ce6cb7b0ad507ae94a9c2b729b4024b4be248491f307290b19d57c7e23df1f2bb9c7fe433939110da294331e01e727b45e454991bec92b718e99627d8cc0bba78ac6c31a6c18ee8990064bfe0fe00c472b39085faa12c04e739178cbdf1fd386ffc35aacaa7e3a2a855316f1d561edab8483db452c7e011cf7fb6356bf3d44242f9c1b586facd7e97bac33d4873a9720cab5019688ef62a412441e68fd068607e919b68df464147a3d6b611e5bab163c82bc00664da2a463830693c42c69013210c5b88db66b60ff8e4e3d19bf1147416893768eb3931cfe026820e766185af825be9179bd42a6580c02a4ae7cda02a9d1cbd5cb535d18be9b2836878113c8f7c283ce6ca71964b9c5de14aa37495820e6285e878fa8a1c0d24595b0e8a58af0d7018d9cc6ae9cbb36185fd9362c77e1b7c5ab621d24ee62180bdcf34bec08951ce382c77a4e357d433f92308f9acdf9006b4056dc56e1db24d418ac0d95aada9d25c99c48ce8a924e06041c7aafaa73136a7b1931386c97c136", "-6eadbf04891dbb42bd391ee421269bc4130ca1ba0eec5501b03b6dc940acd066b27d7c2ab822b45438ce9f536927a75e64b958857e5d2560c5980f10db54d6cf9801fe605614f70648bc4c74fc36ec2188ae644afaffa08585fec16511f31868e73c3b239e818f297bd02231ef1c43d40fd196de36489326d99304b782fa7c5899a17f0c68da32beb9919b20aad7858a5b87644319d4c637f6a5b221b2edbd30ab9ae715cc405944fcfbee5e416673d4d0583ad8156e7a7e74f48f6c7a87eafd419abefe933a64acae61ccabf7427bc0ff12dc10908294e5ebca10c67a864811f98b7c9b74b7ca5970c5988d723c6142223086a6ac5deafa221f769156934becf43264d240ea325a2a7ecac3f1dd31b306afb7bcf3b5e50faadd241a1780d37de653957df47ed319fa6c15d40671f6b47d028012afa240c2ac5c0ff172a225f884cc4baefd0797ca50aed60b31fa819aed15617ba73e0f3d0e3db50886f0c8f59cd5e7b86c1ff911268037f58155f00a238fa39cabe45a1f3e8a290f62d656cb50ee0304d73f08ea3115700624e009d0e979a11c3a6362c3e9fa41893699f3ab472c036323bbbc81a37ce5567a45f2af45ef7f0d0bbaf7236f627eb25397d60468cbae4780339af93e1e9f977964c7f96f4976d9bace19d32693677ebc58a818952db4d44eec5046b954837bbc847d1cd1cde5c815173141c257933b2d8cf643", .None}, + {.Add, "5d6c230556a05dc6627ae5332ada8287e14ab432b20dc00b4bd71322ab669a0f589a916208f3dd2d24606b2fa742c0cc8bfa66ba5fa0eb20f12b7bab638a32f261003d0aee439011e6825b57420cf15405c49d82277fa1570805fad15d24f976bf0a8006c1c961b7b49db3d30b9e38685cb5e6331e9a7eea557175246e2e9e1261a9f7215388bf69c95d12d84faeb2931c289691f1bf30ad8bd668c94920c7fa0bd4ef55b6e3e6bc915a85ecf3255e7fe647b08335e2db7c9a3bbcde3f07b13df455e18f0e5a86a4cadf4aa5afa30f7a6300e9c73ec60f50ec6802be89aace2b68abd9cc35e0caefca85de0a89626477dd4423035de40d731b3936ff12b751a237a413f9fb20a4649ac34b82458ee4f068108f762671389011640e9e732c74d2cb1026a83f69f8179218429c99c5fe1dc00557460b459309431bc41baee4bf5272b6d78ce94d4df578239a33d9546c85fcb5d065bc3d1e05c514acfd0a3606577cc94ebd7c025a8d144da047c537067dbb95d7566ba49a54f8b6d417e609420d51fde1500a2657bffb786e09c1af1379f01e529a80ee14c5d6f44a0fad4afa96c73df28724c9a48bc0666805068ed934f0cc85ea22edffa0f9a879946221bfd801ef44b8a6e0487686586cef0d888d9b4eb4f6bea2ee85599d6a00f4f3236a152fac8c901a72fb0792efb125a7ba0230e1557dda8fbadce21ac6c8c1a2ee446f", "cd2e835870aa91b8a1a9c4468cb4d05c4b39fd7c988ba6977ffd63151faf22017805ade6144f7d2afb1fba827ee15f7d1c565bf8f57057864c9efba85860ef310c80f5661f54bb3ca693de1a098ec4986d7fb4a963f5d9325fa2818f752b93600a15bd74457b5df369302896a8e918d6e1cfde35541f01152d3c82059966ce0cc2dff40e3252535ae5cd7411a3470e90da5e3ae64bce2c2c2235b435ee3e599f353185c2aebf78194d02ddfd11f5d34ece722a85756d1edda0302bc519cb9453d1303a9d156078a9b42b002fce99a7b3220ba4edce5c1633b9faf936ce9239e3f0fcf24916b88cf16b610b2350cdef17ef95009b0b0d7ac56763d17458f3ca4ac9cd2e6652cbcd8c58e157f5cb1f1530283cc35c364371ed311e5df61669e4c6de99dc9f2a8a593688b09b36e2d2bf046ba3001289ebc8531ecca3f1c9e0684bfeaf2c2e001d25cdb383e72ab5ec75949c67ad2fc682df3ea137c34d564f13ac878fecad2608ffd59e3ea8db9dd2379799a44ce87c7a967ccd4463f48903d18020cfc0fd1df9a9623fc73aee8a65d64dece6e8703f19409518b09db282b947ca3b5624d1e391d7808e70cce4053bb5233b489f34eb2dcab466e5b2ebffe059d3d0290d406a30a765b237eff29b7353810f30ce1661da809245f73e04a512c2d30540860917d13134f52cb807e5c5f8144b942e292cc2416be7c47ea93e7c1f0f", "12a9aa65dc74aef7f0424a979b78f52e42c84b1af4a9966a2cbd47637cb15bc10d0a03f481d435a581f8025b226242049a850c2b3551142a73dca7753bbeb22236d8132710d984b4e8d1639714b9bb5ec7344522b8b757a8967a87c60d2508cd6c9203d7b0744bfab1dcddc69b487513f3e85c46872b97fff82adf72a07956c1f2489eb2f85db12c4af2a86e9f2f5c123f686d1783d8d5cd9ae0c1cff375f21994106751865a35ed5de5d63ea051b31ceb4b9db08ab4ffa5a3a6be8a358d34591c5861c2c23baff4e7f0a4ad57e3cb72d850c8eb50d222584a662fbf5583d080f59a8cc154c9957e135e6e92dda30538fccd9239e68f18838829d08736bab1bed017142604dec71f0f3a4a37810adfa20904d52d25cb4aa7d42826c9489965999a9aa034769f4514e1ac8ddd37c98bd222ba8575895315b5c61e8680d78c5279e716603bae96a73c32ba7815e8f40e21a991d7d9582bffd44664c704a60851a0404593b6aa20b5a62b28c492363093e15553a243ee81f30d1c5fb380c6f0d138d72cda24d282001223b3fa8f84c14e9c7dd053b0ac007555aefa4e7c23004426102941759085b7c0c4ed734e90bca8e582c15251f0e1bca55608e2c80620219abd21851f91110efdc38905ce1a8fbe11c5de5c4d504c905ebe3613ef998362ce834ed129932442c3c881c692d8d7ffa452ce9ac03bc7d1e4e028b476ae16a637e", .None}, + {.Add, "9405aa859d03f2216c741f71d4a76e245b48da9c7ec18320333150ae06cade5173de4dd2e59a5474fa4f16c9b1343210e10733949d464791668df3c29b89b5e3ea6582d25063a0395f58d2c17c0ec67c638ad4fb4de9fb4d7da025bb76a23eb919b279bcb0d7334e06f70ae8b1aabb938bb0332d408fb48daf2485ccdfbc7beddd81accd2a2733a5342f53bf0d09e2a2a0dc852a46d4148144e458ac3bdd09826b91771150d0d2249ffafc0d762355e8f6ef9b69efa6e5c6246c40a9b68c6e1d0f60b6929a29d8e51a80c3d87cd27c7a0aec220a5c9e5df1b67a2e222d632b6aaa4f885d3870a9f07a8297e3a5e28792c0f407ab11e326e2597e2008a7b628674b3035960327aa5038b84b3b87a391859d784fa8b4c8741db012e12a433adb40e4f6a13de0e075144c2f84962103c0853ea58945179a697fea65fc52005157b024157970beb790c164769651317e13c6740de552fe47189b0de3a9c66f868787ec44ea32b9341ea6e2b7c8f5112d48655c15d06a958928b90027cb74485b61c5a1df77872a948c8dd9558ac1af35e45ebf1e6f390d20a1d1dbb96f10d4bb865b646f2fcd53bc45503fca8ce0291a5de48d3918a48186015db80ad0471468d5ee45a11caeefc6c0e630546a9639980b0bcdcb031c4bcd9672c28dd6c34b45a2f34711d19188b6817dadfd4002c6fd2e87a113df3597889b9aa83a6ff65be31e2f", "3e2d604189e743991ea577d0cacd6a522288a384099242c42ff11c352e9f3d55451e41c475479b3e891b7acd08567a6c5d225e6d2f3ca024f37dc4a708c230113baaa3fa90a4be7ad9f0649b2d5aeb155d4c253c19cb0302dba28f35ce1cbda247b40b5af867bbf20af864ef0950e136c5f8d85f6b374935500f65bb75389268f5f1240069f461ee203c1a2c45175fa12a286e4b2f1360e424e141a1c2bae934cd6ed19690c91cf33b23e36dc4f63d4697c610dcfa537ef4c1e8a3f459f061ee801b3afc707658da3bce18768bb22d1370ef3b14f772101e71f745e5421c62906a4e82f48e878d5edc9284639775c0e754d8749fdded609a36552e723c4e9614604fb47618d24e0ac024a34d4d788ff3cf8ebe42eccb2f25e071bb8c26ca3cc0f2bdc865b8e679baccb4ed60cc1677fc0ea82dfb6d5e0ce18d289978a4496d8fed7c1639a266cdea84e42b93b6428381c99c52b6b4a268a1dd9a9a52de4b2e54d6c3bdb023d73c9a3028da7164057650a6167f52dac6c1a5155561cfb1be20908bacd53546fdac8866f05e04f41d3d254b5370ea3c05a8154848e7a8a4eded641c0aec9c961452e029ab78982c38480d5cadfd36b7ca9c8e4e2ab065cd93f1ac4f7d09887a0b81fa29b398ef33b243e36806e52bc840a2c448fd5626d025d1041cccae681fe4d325d15f20ab2f772a0ba837158a7e831c26a5ec7d70562c1380", "d2330ac726eb35ba8b1997429f74d8767dd17e208853c5e463226ce3356a1ba6b8fc8f975ae1efb3836a9196b98aac7d3e299201cc82e7b65a0bb869a44be5f5261026cce1085eb43949375ca969b191c0d6fa3767b4fe505942b4f144befc5b61668517a93eef4011ef6fd7bafb9cca51a90b8cabc6fdc2ff33eb8854f50e56d372d0cd941b9593546b6deb52214243cb04f37575e7756569c59a4dfe97f2b7390048a7e199ef17db1edf7b3b19932f8eb5ac46e9fa64bae654e49e107cd00b8f7bf18f0aa031bf564edc4f0884a98d7bdb5d1f54106e10287174076f7f8dfb149e0b51c6f8374f57151c473d58487a15cc7c4aefd0877c8fd34e7ae404be7bab7fea0c1bf9f85af8dcee88d51c21796d070deba193a34390849cb66a051801d7b469a399c6eecf18e471f6ed1a38814d4db74084f87661778e95caa49ac54011918faa611e5eabe95ac1e4e7c097483daa3809b2e9813ceb7e44194dd1b5dcc308a7e2dd0b5b4112e0a3667532beb6022c4fbd704fea5e157d2d43fa1982562d8c4cbc719239164045e8c6a35321840a71e023492649e7240256b979a973bf807a1c69e9d09830697605785552a5f1e9e715db39509dec063580ace1fcc79a951e263769d242e05a0803856d4a4eef35d1e848140e39370b8b2cea1b6b73f763de7ff9a89b54a37f5c60adf6745893494af4c0160bb7c14e26ed66b20f31af", .None}, + {.Add, "3135aede611cf049b0470c157c8ffd385290e83e3d7f65612eeb1e1ef60f2db493479843cdba1546f26a6309324a4ba6cbcf023a6eaad76e37b5d674d6c50342f3b36a29acc1a0b9399e89a03c1cbcb9253cb7197209251bd9c7136a02e1ab920f61067f1e40113e60e057fb839a66732aacaa7ff04b2148ede2ee8e579de4af80875ffcf2c3a4dfe078dc2cf957ee80aa7c2cf6ade322ea730d6ded76b99b6eaebbd605081a1a49830036f665fabd2df15015b2d891461ffbb5b39235de47e8c1b16437e163f6f09a01b38b6947f7747bbc7b379896581841212578a39030da9258f9a581f3cfc451ad8e1aaf51b5f7a0ed71fe9a1c6b816d65b05968f4af3b4f2e506cefe5e6fd9b84c95f892d85ff851714eb43135f0ab00a84102cebade2da8f7b400f35352a60a458eac5f713949a6f1d7e7d980db0c64f63bbf499ef3f2bfcc222f558f1265e72d10f96e92044568945eda89f475d91b66791c53742b9fc0f4c282f833c2b72ce04a9bf2736e2ed9a042b2d53a3dc2ac0c1c739589534261c61908cdd3eac890cb34dd1d6f0459a85ba6c871a0c09b8feccb20cbeee53a91542f7e537f8e282a3cf3fe448b0f3a6599587c9313bdd8c2f51a38895d0fd082621717c58472f1a4353daa64c159d99f0c44701a370c13e2d543abc6949684f151ec03539f2dbd796a8d91b4f5a5d14c8caa705de0693710419e029b27b8f", "1101649b8634e76867837e9aa33bb4b4f2a4422241cfa28610e4ef78b08d06ffa8e0d2635fee5de19d3131aa921bacff18b7b4beef37c4d18efa91a7c554eb54a8364475912a3433b5c3615aad99272fa0b459df2f7400d6e0c195beef102c24e470be31290cdff6791f40f269668716e4f0d11609f2a90fc5b376687da7ccd102f23f684a08b7d78c04f822652c065e9dfd20d7ac4900bb9b06e3a0684ed09cc1c74fea48d673f7cefa3a3a72008bd477b7a420c4910da4802628b4ee531324fa400a06bf6c3b3600f08ea6946a0fd7fd552350c552d97bce2c61b8087c2061dedac84d2a8ad9e61261c2b5d6bfe7705f6a8e5570b495bf288d4fafeb705803463cdc9ac424b84444c321f45cf836d8686f788068712b17997562cc469f690bc6aae10bc432d50b6c2272ffa946c1de7f5b2e2ecb56ab40841c5520cc48382122eb9aa13266dcda27a2824a210a118a4b9de7916af1867f2d345f8983385e9f2cff16687a48169924f14bc409a60417e73f4ceb1ae672aa7e6ca344e3a0c4ffb9cc886a8e51f17df4bbd1bd582ce0bae690ebd32333c51a14ae91cd595d48b1cc1c4d00299e87424cb13963aa9a1324a37e0f386191fb7d4611878662abf0c6bb08e465152fa9c054a342cc9f150b84b0870af58fde3db68474d024faecb36a7f774f10a7953db277b7d3ac7279103a6aa5d847994ccad8448299c822a43dcc", "42371379e751d7b217ca8ab01fcbb1ed45352a607f4f07e73fd00d97a69c34b43c286aa72da873288f9b94b3c465f8a5e486b6f95de29c3fc6b0681c9c19ee979be9ae9f3debd4ecef61eafae9b5e3e8c5f110f8a17d25f2ba88a928f1f1d7b6f3d1c4b0474cf134d9ff98eded00ed8a0f9d7b95fa3dca58b39664f6d545b18083799f653ccc5cb76c7dd44f5e83f4df48794dce5a2c23a60e14518ddf086c0b708325ef50f08e4151fa7130d7fb49026907b9d39d2253c47bdbdc4724315b0dbbf16e3ea0d032269af24231fdb2074c79119e885de931940f4d8730ac0c513c7133c1f2ac7ea9aa640f50d086119d68005800540ad1014095f300095465073e956b2d07b40a9f41e047eb53e625bcd7ed868d6bab848a22497fe6dc738b16eea13a5c4bd3680a35ccc6cbea6f3dd57319ca4bad48eeb8f14a6bb8dcc0e227604ee85cc427bfce0086155359b7f331cea2272d7f1390cddcbeeac71b486fa159290e6290a9cb52c497bf506dc8cd3afad4d95116483a1686a92d650c1cf95a33dfe8e9fb1b2f302a7dc8850b2a03d1008116a63faa4dd123cdad5e7f661c370575318ff80ed68024cf5508a38ee2c41849d7a4c02ac3375ad240d929eb41c1c3c32f05d69187f0ef6ee696a7456121224a77cf3c9181ae77c2a2245fb755fcd2ce8c6dd0dccf308e4f4e7c858dc86a977f6ea2ee9f2ad16bb586b3a84c56b95b", .None}, + {.Add, "ef95cbc6aaa1f3184bb1d55a51139d8faa77a65ef9c22d2a08a1a93a31f8ae3782d4157deb0e5e9c6a1f8d74202edfc320eee4c9a13a27e0341ca863e7d443a9f67030f6a46627d25bd14ad2047455cc34559c1d3dea3dc1030b976a10c6d89654768a69892d9adfa81d21b3a1ba19fc86cda7b61a884177346dd1c33284a9c3e9e3335b1a2ff6f5bddc39cd5bb4771ddac372219a38a860fdbfb2f44af9641d686bd93248594cc432e11bbfac32e069307379c6e8a21a950e57453d03c9b7c7df4accbb5f8c8f5e9a4dcd36a535847496acfc0193cd609c3bbd3f1cb037b6364cfb6b604b27b3db7edb019463a461b5d17272cd0323db6b4d8142965fb98a9f73fc5994277bc90cf50617abdac1d9c77d69024334170328868d9269b827eeffe02fb681ef3dce34d04baf7ab03cbc66037d7320092ba1161387078978eda26795370540272ee3dc55727b4f0d212c65a9990cc4fc307d46c177146fa24c76c19829c27d5cfb6700976d0f876f61dac0a37a4b9edb60ec620d199b8c66bd02f768a3bbbb7567dd39d05b3190d4afb91833b8c13a1e5229af5ae19c2a04576904d44dacc0b47502e80c072552da6a5d271ad6c11c3399a0527781d57341c16907017602c6297eaaf594f9a84982e86d64925fb7a72dd9144a6ccaa0c6cafaa0ba4d8b2605d08ea8e24b26e17a52c75917787a648eceada7db0204b4bcb04a35d0", "1523eb9d2083088827ae5c86e661e526d6a974a400c431c4b91da5d7739fa5f2102061671bdfa069447f052890f160f85578f20b598f53c8b52c7b16f9c7e105ea0049995a010e999b99d19a3531119fb0a361d76b0020c37b026e98fc710516b3475305a1f4001a36e2979b37edcac5fe10cc5719e74f8f7aa6f51517f16080f2ff9edc6c7855fb92e5503e2bfd315cb3f85a440c170120157b48db28b59538008bb8ac6b94138afa1770fb7a193cec6a7856cebae082b97da4a3db1f39ac8d99eadd139f492029f0d116c2f83e76482f25a07677737ff30f53457faad9eae420ad08b2902ab9e848f84399e66e7853a5156feacf7bbfc000dc61c928d880e6c226e5cb17586b2b98f826c9d4394e17acb78e6494604d9a2677baac0b32465ec6e4bcca78107eee1837e50824c3fdc4be6576343f17e9fd4d3f75f14683d6606f371d82a8ab9517561785d2e1466d8a69ce5ba2a14b8670d0e1da3fa422451f2aaa34d2df4a0e7d7372daa8796b9d55e9b5d993d8d1bac4e2dacd165fb4c529e4a49639aa6297ba9e1d43eaef9d1319df7aff92642408e411cd98ae1a725e0ffb197c71b1838c8a9a30437c1d2f89b60d9c045cadf962ae3e675d7813e7da3a146a1106065cdf86e035462584d9307cbbbaf90456134b61737417b24fabe3e87e62b07557e98a6962a2e95e31108683856d8a1994e6f98c703de9268adcce5a", "104b9b763cb24fba0736031e1377582b681211b02fa865eeec1bf4f11a598542992f476e506edff05ae9e929cb12040bb7667d6d4fac97ba8e949237ae19c24afe0707a8ffe67366bf76b1c6c39a5676be4f8fdf4a8ea5e847e0e06030d37ddad07bddd6f2b219af9deffb94ed9a7e4c284de740d346f9106af14c6d84a760a44dce2d23786a84cf150c18a0b87b1a87a8ebbcc65a64fa981133afbcf73aef95568f791deb3ed604f2cf88cbb264c1d559aebd095a3829d4e8bfbe918230364557935a9cefed5af888b1ee3f99d73fabcc5d29c780b40e08f4b10849c5b11a11a6da87412db526dc3c7d3452e4a12da097687e2b7d29f9b2b4e5da45f88920b8636233f5f3ed434388dfe3e75aefb27df2a2090a7c87750c2ad054d15c35a355ea714734c674e4d22e8839482d500ba2ac1e2e95448438b1360c67d7abf7178c8046e22c2cfda78f3ab8a0121ee6799f0136768679d7c03b79258eeaf466ebbe0c2d3f7503c45757e0adfea2fe8cd78168d302532b432a726eff468a2c671c8214d4851f51fca74f46e78757bc44ccc321333c0cc827632936caf34d81ec9c714cf67293265f88f72a63768cef799e6dd2872c578e1930300b5e932eb55a9434115e013cc2fdb8a7c752eee6f07c19de14e1ab0ab83ec5fabe03eb8791aa684a2cbedd67b2878334badc9cad883d7df9afde7eea86394a16772429de33b27042a", .None}, + {.Add, "-690654b2e764ae24e8499cecbec00e88a5480520d7da2b9d55f70322c2fa82f0b3aa7476c76b44a00952be97ad11854c5a8f0d70b366f0465f320bf9f7186e6ef4c5f963b52618e75cd75790f71e87b3e46f14c2306261ff21c09c02e2bc3e96d310768537f80ec1ed4b2250c7034ee078e4b631a9bb5f52bfc6813863a57947f9c00cd9c5c64aa8f4a9e7d13b05b2564c12493d29cf844c8e16577890c7a5b75fdf77ce99a47e52399f78119e7a8c4e092f425976bece251e653ea92944f12822a6f9eb1ff55c1eb5d5ac68da3c7622c1742e5e9dc911f3c7f8a696cd39c1c66c9d6889322cdae9d5ff3596db0ec425d169ee9275548eebc299ffdeec4241976dee6bbe933a44a12582a9ab8fc6a9e3796ac0e782af74f8652427131359e589ceb079e8d8e3d01502bfdb0fdeb89cf967723a4a2fe9834fc83a243d72ab5cb31ded763c4fcb6cfadb2910a49482a177c9aaa229d46896a3284f71b7004d18cda21fdb0c18a41baf3a056e8928061f420582abbcd27bdb20cb991590e820d0a582973cb7e2f8d46116a95ff253cd67d4d47cbdb620dc68edeee8bbc5ae64ae33ba74c1b3f4eca862ac1911912f1a46264110d551879cc7826ebe362d02dd80431ad0ebd9947c370fee36a7825fcfdc225def6c5c7d1b79e575f98ff63a90bde230da05031c567bde403428a49efd0df3f81a1e9fc2b3a3dc7e761e2ff69bef3c", "e806c9f58315757424bc903dcf0ef48f962a776a0be8e9d6cc14c7ae9bdbae20121faeb70acdb7772159caaf90a9d4bb6a7e4f0b3cca162d0bb056da572c309e5b43fc47a7e70f9ce3f78e9c1d0be2c6f2c2549e10df36ddf71dca8d208b0fcff092a9d816e3802750d339a4ce0f4473cd55acce791b4a4e38adfad8a59a5ad3d1914d908c3095e13f1baf1a864e1092b170d0c6aa4f2b086ea4af9622b80b511070eac9b491d907248ffb671505ffb82616bee06e51daac1b14dd810ab1bd01b375406ed6385f0ae14a9a7ec7edd0ab4e688fddc7d012669b8fae507c7e336d1740ca1689eaed9f88684b7136457ab8251c5a046a79acafbb128a4e559cbdebe30aadd383681f1f66c3e18578967b17bb2991400a6468c4f8ba90764245e95d3c93152c6c5a1d62776aba1b0a750dac1568e398981b559c03a994dfca65a1da068dc8feed289e9c94a3cfe88b6a0b233d5bf0c42e140e73aa22c97eed72a40a771052dab27f6162dbb2ededa0ca73cfe3905cc7e3c888ab951d3c77527d33ad32367d167c6e31bba52acf355ea671e524c381e8cfe929bea51cfb670de63c5c178fd2a9e56ac25b5e0ced0e871b80c6e491b92cd7bb25964f8a95297334935d94273c83026faa43f2e42325743d664173ad9cf3bc8d3c96c525e8280a6937bcf1ab1be6c07212a76643a0d7abc32d072e47912a95395a7ae3dad6e22fdd0fb9", "7f0075429bb0c74f3c72f351104ee606f0e27249340ebe39761dc48bd8e12b2f5e753a40436272d718070c17e3984f6f0fef419a896325e6ac7e4ae06013c22f667e02e3f2c0f6b58720370b25ed5b130e533fdbe07cd4ded55d2e8a3dced1391d823352deeb716563881754070bf5935470f69ccf5feafb78e779a041f4e18bd7d140b6c66a4b384a71c7494b485e3c655e8789807fa6bbe08e581d91f06599b09172fb1aed5ab4eaf08355768b736a1ce77c86f7930c86fcaf9ed7e16ccbd990ce4683b64302ec2b74ee15edb15a888cf4617f2a070072d39707b9af4471a6aaa3618d57be12b5b26915da5b36b69253b26b71f5251dc3f8788a6f695a7c54751c4214f02dda7e414137d9e8cfd13441bed05887b4f3cc939669632eec03d36de29b4393764d4d74aadf0b2bbc70b2adf6a94e6831d24c3b6f70a257ba4526e8a052c29d5d31a1b97abf43f6e769ab73b14e9a59ab77d081d357c7ed258b3cd4f077ce99db45b3a1ad7f6478c4548dde0db10b114cad8ac98426e66a5c6307af9f405e99755d5a8e816f430ad90a105046c432af0cc0d0b6343fa15f818e285d1b10f5f07e19f8b1f3db7d58013aa0a380e3db501e5e13e0cc5efc7057131a795650a96df3733404ad7ba3146d8a1f15be30973f71c2b14f2c5831cfd879dac0d116e3a41b96c9260f78330cc61f13362d728ad285b69e6564b8b23941207d", .None}, + {.Add, "-f4eef6099cb4f95bc2196a2624363cc4e3213532aa057a8bdfb931973d5158b4875cf4f953b5b2b7765de3054768bf3a712c0202fdc0b0c635f9551efc1df66c4298eefd215d1cb30eb7ffc9de8ea91e34a21dea0f9f85003dc5df9e42e38f1e0a7dfd670fdcd296c9bd89d33716220270bd93f3475a6c520e18d64d5f09ab63fe393bee0593a217a554ade8ef1667c9f5389ceec98f72c9deac9d3f1372259501ddb864e7d54c69a09d1addc8384ae50d8d88b148449eea139b97eabd3a170addb1cbe88586123e1bb4dfff0b4c9cb019435c57c1d87e20f30b174f365ea462ea23201e2f31122b7bdf915d7821280a9e177c71cc70082e029195b65a944b95f5300dbd84518037f53652fb59e5c84d9d4f99b491a783d444b4867e7db71f275570a2af7efc1bab5881aa701ed5b224b2ecf2172ce48888ba50b84f4a9ec3c5203a23c532bf708e6418c405bb970453293de80e5a2e4ae57836ae857bfd5dde0e7b778c106a283a2183d77381431a263cfdacc212ee651ffa5edfb959ae8a41d1ce5232412cc54ffd03079d3d036b056147078f6350c71eb4f9f35484edb29e6a6231dac094b5c9f99d3f3864adbf9d144f43c646f19a2881dc635cbad66e9d0c513b1cea365071eed598f27c25c0b85df52c2fafefdae98d21781c1d1412c3574fb5a14cb4d700b66367c03b385a3507726ad9ad662e0de316d35674b36242", "c79c5e3bfaa332e5de814b03b685155983f982962c47767ee939739789f249d0dcd897098dd0e90fc087246d4054eaf2982816e0ea0851b3324e304b181e22a6ea30ff31f7d4cc9ed88d6fe7e8f8b148d5da49acd7db77d7f565c56619174025ab94974b60b757288929f03987141629c52a5f7d285c825b01866748b1372142e6f05c22db039b64f42ff1ebd26aa7a6bf2ca9d2c4ad56864ff792b4e68ebfdae9df153f0acd9c1b6dde8272e7c9bdc1f4fcc430c50b667e8e25db82171e628adf151a6957143e31c2f90f4ea4cd3b26a8d91ebca1ce01cbf4939396a00f4b1eba6e2e478bc862c5beb6f47f701d59043fc3a0035e8596604745c465dc82c6d4f1a6cce848479744437a1d12291f82a2419c751c2a9881ce0cfeff1e8b7a9ab5722d3990b09dc282fd6848700cf933ecd3208b87bbb744a5a6ade1b8a2f852c2a461a2733642b471bc424c17b89ba537191ad3ace7fedbb896a8857df5c70e10d11f984c13fd3f95e92c9b1ec33cd5d2b8143e9a5777f0e9a76f60c92bcf151ddeabe610823a9a1af98e6155f09bbe9236d6add1ebdd09e8eb2706a9a32095f6ab06512b1b85ed5a3548e0223464ee29c5d84615f2b133980a669fb7233cb90eca820bccdc73b07e92e69b28bd7f7741a4884e3e018decfd3dc8e6dad27fd66b4298a5aa5e03ed89d750b6ff41d8422f03c0e9e2f61b03b4d6c862c628a3a7cc", "-2d5297cda211c675e3981f226db1276b5f27b29c7dbe040cf67fbdffb35f0ee3aa845defc5e4c9a7b5d6be980713d447d903eb2213b85f1303ab24d3e3ffd3c55867efcb29885014362a8fe1f595f7d55ec7d43d37c40d2848601a3829cc4ef85ee9661baf257b6e40939999b0020bd8ab9334761efde9f70c926f04add28a211748dfcb2a9006b2b124bbfd1cabc023360bf31c04e21c438eb50a8a2ce365ba17fea325dd07b04e32be986ae06e8d231890c4808339386b8575bc68a61bb47ffe9cb17f2e71d40c58bbd0b0667f6189706a3d9b200a7c54fe7783b8964f59442fb4f1d6a368af65bd289cde0803cf065e53dc6e6dea71cdbb4bd1507e1184c1038940d53c09e8f3b1bc35e930c645ab5bb32498670f020637b5875ff23c8471e343691ece5e59285b19620011dc7e37dfcc668f712d43e313a2d696a7a671027bd88151fc7cbc1ca7d677ee02fb5f1c10231461722f6f2ce18e290786364fcd3d5bdf3ffc6ce8a438573c54be06445384e96e27bb76743652ef7ef02ddf7523f3226c21bef22b350374a6474c67ac732a7059bd7773bd35c9d2ecaae1cd1ca7bf5be0afa50ec86fc4545f163048d1734e76fdb0544066907775c3a59799b58e41cf2f500dc29ff35beefdc9bea64976b96cddf1ae61edec4f5891414a943c5814b70ff6eeb0e976df12b0c0f960180603b180f6b74b2a590c4e70904c0fba76", .None}, + {.Add, "90abeb9c83f3624c1487317953d0744ea4a336801ac157cb55385a813d575b690492d53acd9614596ab3a955a809b1c60f8c98975acf80fdd9c0c7c8e636c6c5517da0bcad9ab2e56d9c5ba879df80e34ef0bcfaeff394fbcf19da7deb69bdce81f9aa54ab9fb91c612fee1581b9cadfedd67109a96fd2f75cb1bf6129fd7f0dfc089cb372ad73083734db1abe7b37b81214d8a0b8e087e51ddba5ebaa412c2076327e6410d16fad7fbd4057ed79057af22d3220fb8494726c143fce58955e6a6466c95ff0347655d84f2a94e67e583771dca90b833e2386aacba2f7847547b718da153c3c7297956dfb59cff6c6028f1cb29cfa1656b47518b1b9a89a07c4e417a043102a5369f27e186b2e4df3bc5d7dde08eb7940d280afe3b9a3cb17f6e1bae0287d1921ccfff61dd704b591069d8656849c7d982b98d5ebb8f1842842594de027d4c027d08ce99013e1e03a1ab44305b261abef16cbe77c9e231c43e892ed75c9f249d19e6463bb16ff74408182110b9019af173b73fd0a59dc3626ff83596a33e689132109addff43decdafebdcc4f744961acd371b0567600de823b0da5486186bec7d6f42fe98f4b8a745a7594ff35ad63dfd9e57e21ead924f923a0ae88eb17fe9252f3258ca30f639b41a43b71775dad2fa9318d46bc10476ae4c917b29e150441ded5431e96931305e26da700d9b5ce32065d612677f35ce5e973", "8bee867b003980bf460823b78142dd47768e202cf22b3f111a2d9fe9559f47da8350c72774a5d6f7d1c965717489a10a87d9e2657f965e1d1704bc90827fdc065e30ec59b8dea62fdf475e4bb31cdc52c1b24592660db641cf3afd7796066d716a627ff5a00989b0117ae80c9f0250b0b85450883d077b90e1f4c90bc16903df09e00eedebce7e3962a704d7e2879c5d35c152888ef6711456d7a3aca9848f81f3b3259ea3a7af881af9ec73ba19c4261af714c297dda5df06844ad26e5cfec79ff0ee2fb7fb179f29ca603e3954ea3a865d41ca3296e36e50a29aeb35206eedcf1e901f45a60eae9e611ce73dd59d7f9e216440ed775904510fc5a5bc0d19bb90ae582a4a5b214d43585a9f62a411152b7749fbc763781c919fbff447541a81a31a45c4e23972d1b96ef897547262a764a0e40f9a970b94d218d5863b09ea60bc3af19d202e8518a91e7096b6a7c901570713459dfad9a93bdd342fb09f3c0725f538a7b560223b4bef050e0a28eb1a3192a16b96b7fa0f319f6a6ef0e5b20db37c891142cc3aa2d899ea54650a38075b3fa65e6a3acdde19f52ba924eaf7b0f9c46c59ddbd9240e0d05fa35c1417d256537cef1999dc26d276f75ae766937364702f8759c354f7b4576d50a5f0aa73da3b38c42514abd95333585638f739b0bb114ed3aecdc1298f54334f3868b44768644eba9b310392205d66d08a73600", "996ad40433f6fa5808e7b3b4cbe4a2231c0c1882e9e40bbc66db347fd2b14fe6acc7e1ad44e071c8e7d03facbf524bd6b80a36bdb2c8e6dfab311391ee5ec485b760af8249289d486b90d18d35114ea87b0be1541654705fec0d8a5564ca24a5989fd25405a051b762479c964ba9efeaf95bb6122d404ab06ad10bf1e6140f4beca69da2516a5aebcd5f4b683ca3b17de570edc941cfeef66349202674d97518956db0bdfb0beaa6016cdf1f291aa1bd53dca36d25026ed05c7c847b7f7b2e56de65d842ebb427cfcaebd098ca13a6db1a427d28266791bd8fd5cca637c74ea5f5cbfe3e30ccf88057e16b9e6aa35c671694b33e252e2a055dc2b602f5c8967fd0ab2892cef91c07524df0d8441dfd6ed0957d8b35b70a0278fdb5a30f8d3889d511ccd96745642d11b4c68e2ad82cc7fca092dd77419c52230d4649e7d8e0ff59a3d6ee922ab8de7421faeb4ba497445876239605cec4667b3a7166174ddc535fd51d7cc527a088187a075054e31033b424ba306882bb14f024508325355aa434a1fc779d3fe4b3db6992e3332ba23e42036eaf4850804f91f5c8bb70d0ea88b4e4a84c5ca3b0183df69545c0359bf2ba646d7c557977a7eb495a4ed36f8cd7e4cfee10742e8842a0d219e46dfa4c4b79152ae9ef80f3ef2279f195aafa58642363b3023f2ebae7dc13d9c8068c6db21d871ea177e51696832c4e60658d1f73", .None}, + {.Add, "-45757fc72f089d26f3039cdb23c679b5259ef55bdcd411c982830a955fb61949d3245c6935c37b86f3af06875ece0ab0f8212248e4df36de8cc2b641f6691703979254d8a0c465a91826b9ff93501c5faa1dc4f11f5a0dc2e270a1f5bb37ee2b4e41bdf17aa89d8207b8ea32d59c15d9ddff8e4bf37e1714b88e427815c0cc9f415d8bb0783a63e2999653da7e0810d8f57fa001951167c873d185546dc0a1e8d41010d433b9e594956ecd3523cf0325652f835b176e17e3d716cf15da64cc8c8c17ce0c9b1033f67a2a8d989a0083d309919cb76bacb829d66018a2f3c0cb32e351930ddd063af42d93e1db1d6cef0b434736d0780b114779b8f0d182128d7e4cb1cbb27b9190e4ce4e0a60ae75495719b0b555265ceb92b132c8516487f389e2a30dce00a6028ef31d86988de6ad4b9ecf9ac76229e21d7f0a9ea5acbab31f69a974bc8d1860f6f9d29f25a92bc7f64d263ae1ae32c7321f82ed7538c081bc93c4a3c75ccdf12c0adf5c57e7346ea7e957f6ed770586dc8ca1c4c2b3407374939a9a210660d091c507b2d971fcbc511145676b2b260c8a6530ea3fc354bae20c3ef42eea72e72fd8fc6449277eca233c267ef7341d189e0867ae179b1f795f50d88acc51f7fcd9372bc9cd0438a0521f772b9ea543e7cd919c5c42262ddecf3a8dfe67dc85d65c546da77cd8cf02fb4d5487269705884f766f0867f438d49b", "f8113779f677768ea0dab7bab51e3a6ec0c0bbb3b01c21753b1515c3c4a88deecade0f380e8d83f86760157e11ccaa425f9070a3a2cfd3301925dc784ff2d857073a0a4eea1548df6c744e5cf1ffe4e2f514ea9e1d4ffb7d9dc746b36e7b499e7b8f509c89e46346e99ada81386f6db8cc38bdcbf7158f89123a18f135ec5730ba489344688829a9544136fce28f9ea36c9e96639e9233de9a50163db76c08278e558194a093ad0d37183c8083fc5b96a7d7c33bc9c518a6b79512ac4246ffde5545d3c588d68dcc3e26578f7d4387803e569cd63571664660b2b18390b676b0d67d65b4e33f81ae26a0d87c90046c0f9cd62ad249e36b0d7482c1100a000d35570de24ab3bcd9a5de51d79790f95551cdb4977941262aef35cb3c88ac6d85782f15786f634ffdc7aa7f2f86ea985da43151532beff02a8b132c2a3bf58036637cd3ee9be016b2fd65f544abbb9832083eba48eccd13a73360ce1f6a790335a23addcd8a929329c830d01c613d584243403187400acd0ee8b8943951e6d227a6e8f130ec09a4f4dee31ed23662c67392d57b7c9b106c0ceb5e1c9d4d4bc6a9da9e8409d4efaef355223fc97632c71cecc71f4f3f7ce843cea0a886c6560b6b0a4dec6c55f92eb359359993205e873aa1838c84a9c0643de2b5aa01989a73dd71a1bbd16afc3069f0c26cbfa3f40a2f64a3892bef5eba415d127e6de7ac978298", "b29bb7b2c76ed967add71adf9157c0b99b21c657d3480fabb8920b2e64f274a4f7b9b2ced8ca087173b10ef6b2fe9f91676f4e5abdf09c518c6326365989c1536fa7b5764950e336544d945d5eafc8834af725acfdf5edbabb56a4bdb3435b732d4d92ab0f3bc5c4e1e1f04e62d357deee392f800397787459abd679202b8a9178eb0793f04dc5c6baaae32264878dca771ef6620980cc16267e90e949ab663eba4570c06cd9c778a1a96f4b602d587142a83fe0b25700c2e07e439667e23351c92e05b8edc659d5c3fbc9f6e34303ad34c5001ec9c4ae1c8a5298e09cf5ab7df32bd2a7063946b9f90cf6a172977d04598ef401d1d859c5fac9d03e87ed7fb70a5c1698382b48c11003cd36e2840bfab403e2241ac93f5c8498743747e591ee4c726aa162a9fb38b761a8ee5cb1b0589281b8648dc6486d94218b9648c58344132a79df52fe52066c22a586126c6a11f1940e0b1ee0e001414b31f54042b3e5a71929c335c5389c25f0c0095623d39b56d9905293c7880c2bf2748f3391b432555696cb0344244d1e171f5cf0c9b741c436152fe5460060f8ebb30d8871eef8924515a6053c0c254943652d0b4852c98af8d04848cb2b309840d8aebaebf1aafd13e189a736b67ffe6dc9535a4e9a4f6415590b1b205615240da5567445fea2672dd3031faa93946dff18271b3b2c695634a4c8c7b4b90d9c0f657fb85eadfd", .None}, + {.Add, "-4c5548252a67bf22c3052beea0f7696b5bc3f0ffa704aac1d56cc395e146cbf7a4ac6181325b4a82e847a68faa688fdbc1245343ccd78ab7f21699a923c9503db9206b6bd2044f010151db470ff213ef67bd671dc5d5a0449bdf6c3ef21d380977a9461f85c07ab4ef496bc149ca9fb6a78f0d88e8d848906c483091242e766aa4375b2553677d4bda693daebbcd46f4ad6ab6555126f4fa23ff379ea3307eb08403f7418b51283aab1a76f5f4228ac4a89de2c4f6e1502999f1bfc78002e031fe9bb30c100056c6ca7fa341402138e92565a47fc7bd19f1f09f3687ab2a22755103e54d42bae9260c7f68168f395be20b463d8d94684c936cdee1a2926af3410741e762078bd10707a5ff080df38eabb3d80e1c3724483f272316979df176b6cadc1cb678a509b5b0b3fc5d18e9a9ae56f276be8c4f3b899ba3986dc7a3bdc44c86a5ca99dd60f550f9b3b04b5da576ba1a9b5b2ef15a2b72ffb4af759ee5df77be029b31482a1e2dd77a2ae967413a39d3577a74d2e5222cba0adc3e41429baa5a392dfa670ecd6601b3b816c41d20debb5153c74017f265ac4eb6ea80d5cdccd817a0f168e2f07a4f2f03f2a768aaa0090f32440c65026743c05763d372b9d28ce91c3ab906dd6f951afc4ef56ae48bedc371fa3cce729c90fee1b9bdaecfd6ba87ee40cf0822036175283ba0ca6b9d5834515e99c27d4ff121e451998222", "652c5b0e2741b5bc0bbcf44f7dc5c8b02a3596f6e71f40fe088f6a8723e6123c672609d8ff7b07a2625a5ced41ee0c4ebf9fda1b1dd646ff9a4a230865d26e10dd55bd9b45327e4b8bfc60480e966eb01293b73d36a9088e348263ab64818161a2bae22a46edd829fdacf25ebba5a5edb7cc6de5b63678c5a4735dc160c42e283f8fbac5195f9a8f9181c66ef8b0899ebeadd5dc5f8a0b8fcf96e0f1e3a5ac9e4390d92f8185d36771856ece8424d56dd28fc712eecb58b6b0ff2f5f557b298d21cbe8557fc0dbf989a63be88b04e83f0d6f987b0e99791a6bb4b1f989c6ec351e77ed4d62face20643898e25ad0a0ccdf56c58d74099baee65b62bbfddc7e21c5ad06ded519bc2df998236ea96e8d40bba137df93537664bde0b448904f0ae1385cdd4a54cc6d88b181464cfc7be5864a002a69a9a181e00198b9e94b55520aab92e54c07f7765a330aa4219cafd2fdb8e8d2d57f515e04dcfe6ee30c9270a31faf6f0b76675d7ebe2bd792d559fe564884df768c3b976322dc2bdbc90147787d0675d865fcfcce23dbf5db98ef39743654e3bf82fd56cd5119f88d7817b6514e07d7104f6f2b4ee0166a4e79263c9af31333cdea53d0965403c40e7fc45adc770669ff4257a1afcfc929f1c66b5a36678d5280197a6b8e3d589611cd87c0470ddde5e4c25053e5f58a551d38a2d05b83bcd2d263629c895e1b7f36048af2e", "-4602827447f3a3c702495ca9a91b0ce0592097903892b6b1f4e3cced6f086ad3de3a00e3a2639a08c22200c0d649af16d52a55a21afa2647f871f7789d6c295cab4b0f921db1271c489215428f08ad0466942ba9f26b0fbbb89746043bd51ff35d7d97fce1519d324f6e9c9b5e104557cc1246aa8d74e1041200fab50e223388203e5f7901d183a2e1512147cc423e5ac17fd8f78b2e54412705c98f84f623e69fcae9ae9338cb04340220090be03d6dcb74e653c7f49a9e2ee1ccd18aab2d992c7ef486b804490731e53f82b770ea65348eaaf816d3826049e3eb68128db3b1ff1c66786c8b3c44063bde88698c51d53d50d134bd27b2d87e792b76d28d2b5eeae716f41a3a3544280c7cd1235ca5d7a81dfa9e3def10d8db450b5314ec8608b7564ee1d35842dd259be7f84921eb55f2527417f1b5236b9b8a0ccf32ee68a3a1cd7775d95de98fadc9096e3192a846de8c0e2dd6fc444b252fcdc144d5bed545c30baa79e1b44641f4bcb1bc11a154d54b09830c0f2babfa8c481e81b12e242289d1d074073f0083c3f45a5d3529899b560317cf104285909aaf2e12ff5a68b7f79a2fec71f03b8c4dc85f0b1504e0f0d7dbf5656727f9020384167bd72d0c0b1c827c46938cc27298885d328eb5412574ee49f8a527b9b8bb75809ce532cb65dca98ff4aa02e3a408cfd668169d65e51c6724386398b4ba0f69f0f150d2f4", .None}, + {.Add, "-cb1e1fd43ea9f88f7bdb7a540172b371a3cb26589c286a90bfc51a08169032e1ebc58f3961032761eb15b242bc463813ef3ed68fb526ed72b631f287ba965a0798531c7c9bb4095d1f47800378db05e700d86b41da764ee85b35ed5a14b0c71beeceb2bbeefd54c502ee2699951e4a72eb407111e8f02262798332d3da4cc983e6295bcf57257d93add087a72206043a2a40d954fc6ad99d992fcb8bcfbcee3ef89a53c528faaa5f3a8b390c28a9927faf137f5b1de805aa88dfd251130afda3b767005b16a5d1d13d785a2489df696ee72191501438080963effb090c5ce58ac83193b9029fce562b3bd20649399e46fb29ab461cb54b21bb350f0cb51ba1ff0069d0a74b3449ba12ee15d239751ab3551f4cb40edff5ee825c3fdb75988a323bc6be781990e17fbae660cdf3a015bf58d49a14f63cc3682ff6f6c7b456bed9f34717ac12f7a91f5c5e0888b218dd5c3e5b20db722408e52409073603793a73a1f420d75fae09d286bd2c9c24b0aaafdeaf73c2983b20b46af0a4e5ada6dbd93063bcb868c1865d1278299f0d5e5142abfa02505999517a7bc4912475f2c022e8d8bac85db91b63583d32e5412df7fd65713a19653bed44d11fab6aaa91c203ce0a3f0c3fe52cab99ce80601618c284850542b02f845d26f4bd50b6e743fe0a1e275fcc100f7f24a5a61272f455d57ec4b9e8c6ac550c85b7f69e5406e71b12", "2cf19683d846d0754c9bb1febc9c8f5afdd26bb4425a3db5a9bf46f4148c3cec6f93aecbad8a8a966c580a7276d471ee9224388ba07367e0d6f0b077c798e5b666e9071de9497a41a7e7e16b93440f18168b0f12aafe47b898bd0f6405d48210cccb9cb58a26eb7e9ace0dc67dea6bad482225547d0df6d88e25407e75127626e916b60c99844d3d6c78872982d520036170bef31d8e0f287a6c8a7930c43531331ecdde66e05b1fe0d6651300e2712971cc215f79b34d5397da0670d671a32efe00149ff7e935319c669851d006c280fa7b735f2cdf68592d3dc9477f68b4bfa7c4027f3a50d310d5a9f0b2c64ad37c65bd39852dfd7c6be67891228281a44ba5dd7f9fda6b49f371037fbb3fe8d43bce0f2757edef892c7b641cd177f0b842d547d028ba485673bd039b58b2f30f157f5dd888c84c02c610b265832e6675ba8de59af0131deccda6970ebd2a483a9a6c3441d825e6641aa49e7c96623dbe03173bd5fc4b98c36b34862805cfeb83d8aa0c2739d055087c1b441fe16c1c91f8f23ee6ba0148b894cb7c4d3eb34df8385ba5306a395cb90731e8fa8c2811b3651e8146946268cb5fa51ac75695ffa4e0ca7563422dcd67fc20c849bc5e2260ab2030bb3957c45aefa274b40d19384fdbb12aad35188cc53790b6eab7f6f3068add5dc653f71375e66ff0880523a03a0356b2f276eaa4ad8377a235120d7bf791", "-9e2c89506663281a2f3fc85544d62416a5f8baa459ce2cdb1605d3140203f5f57c31e06db3789ccb7ebda7d04571c6255d1a9e0414b38591df41420ff2fd7451316a155eb26a8f1b775f9e97e596f6ceea4d5c2f2f78072fc278ddf60edc450b2203160664d66946682018d31733dec5a31e4bbd6be22b89eb5df255653a535cfd12a5c2bda130564158007d9f30e436c8d01a61dedcca751ec341129ef8b90dc57b85e6c21a4f3f59b4d3f927c721563d475dfba434b856f105cbe03c995a74b966ebbb1ebc9c9fa111c1d2b9d8a6edeca61df0e7589fb036b231c18cf430cb206d9139c84efb455591e15382eecaca956c71c0eeb7ceb5d4bc7dea3299fdb35a8c510770c8ffc6a1ea9616f98c46778710255c20f06cc206f82309fda7d1ef667eee4f5f488b0bfde2c57540ad06a9d976c18c2df0c0a21f44914485f0491f65617cbbffd9bc51b5c6f9cb87d0a2c1d226df034c3da4ca7f6a8a9fa13b7c708ab84adb141546675237049654c526d734a34c88c7e618384fac8504418a49e03e24d5fe6778cdc846fbdc605a10590a5054d1e6203c987349db96984de10cbdca577433fb505003b3226b8eab2e531c9afbd6d7376e8548b05761ae4c6f6158add983d2e820d1bbf759cc52fce072a8d3da957b16f797ef640665fef050f77f40c9997818fc093e35b58a6dd0b59b7b6e06f64fc1b05f0240546941f96b2381", .None}, + {.Add, "8bba284db8d86fdf7e9b836a654f25e8ac4122988e5c4bf69c3557b823f534aa1d829a9034a8336f480711339ca59e6384b3807fbf5bdd78f0628ddfe11a6b9ccdffc4c995613d04471aae7138a0f5ee3ac8e867112955692d492b12a21307808253e68d8700168bfea87f5860ec1ad762b13cc9c6d5936ec44aaaba7e2ee10026942a5e46789980c454496f9bd46a8fd80f8cd3ad56a80a648edeea4bcd53f5b052ac9a7547aa1cab535890ab88c91563b6fcafa47c57378cfa7fe9fa0b51ff681617410ed594758f893766d04aaebe41006c043e5e84b9b7032f87e85cb4c6fa649af2b44088af17b56365e212afbb7eb4af8125e00850a304006174782da5ce5c8f27272e10d3b08c6cbcccb4ed08b9529634a555296f736ea9afc18ca8b46ad7e5672e393c8b123dd3d789b0d92b903a19c88a47a112955421216e31aad427e67097d4eea6ad8cc70f74c74d1655a857295974c9267f9630d459d640a4e2da7c11180da3bfa25dedecb15ef8f97e59f553d6cfba487db3507688aa9b4b916aa1123a48b3562a2e1cd12b0737dff650c4edd679f1b5e63498e8d72fee09f8078003438fc0b217cd0f8a9ae193a7835a126669619fd9af448230bdbe64102e5090b2a2b3fcf8c3acad09f09490a165037f793c5030800734a02b7b2253d10d95102f1f2e2965db700c79171ccabe09eacfc058d22901a9256241078e930c7", "b84e059fcc909c01717880dabc3d5d1f9d4b85dc1351c5446a84f2fd155d2337fb40df517b9d2f1bc4a925e6e14e6f33ed7d06186e93006b2e168bc1a9c3e1e828eb67f2553d9ac8ff32c11d1ba1656a4f4159e10781c635552dcc65a525bac9fe79b7daa00ed5f9b4925ac06a54ab89dddefd2dde419295ccda1591575e4efd6132f671f43e11bdb119a77a11d5a390a57a88373a80cda601c0d9d3b177e9ccfaec28d935819908220fe4b41184b495b0fe5e696d92e6ff63c592add9774f4ac4e52613bba7203444483dff720305ac7181a2e69a197a8aa0d0bb4ed4cd22cf383f526c71e8d1eb1fb202dcc1f416d3c293dab2c9d475a79e4c7b89ac8ad006f08882b8adb01de8a7a432ce96b1a71ff15319605491547fa85725cb62400fcc35f348950893928fe4881fdcbba32ab9073c88cd95fd7eac2ae682a5203e380d0b2d458c6efee07e81cdc4f7ab7d1b7dd1145e7d20afb39af14dc71384eb126112a9f02dc6d068f1c0d802f0f4c0faf0ede3e64051f974eb260be390c55461c62aea515a7ea2ca190faf21c2353fcf21725c27b3a6974d7b96b6b72e2ffab9be5d55dda7116aa0e3fa14b304b34bfbb8a0eb5d00ab53d8fd37d0639d1152eed67ddbcdac6b5e8447905e0728935c43d6fc4c315aea5941441cc18ba48af1c10eb67ebc4f6f10d28d6d851bbc9e543314c79d12cd4ce12407adeae2c6830eed0a", "c109a824a81e22ff6962391162924f7e280f98059c378a03d4484878979c76829d1908fa7ee7b252b92996fa1b18c91a25c83e206a88be42bd1cb49fa7d588a1f5cb643eee93ae9943a46c042f2b74c932ede86778945b8be8025f16cf46eb42069ef643787ed762747ce2b5f0636d37540a10fa7aaeebccb91ec03cff413d0d639c3917d8a59b55bd5eec110b92ea39a2fb810475563826a809c7c25634bf0c55f153a2dcd613a9ecc51a3d1c3d41270739ce3467daac72dc953aac7918046abb668787cc94797b9d40d175df07b0985591a9a6ddff62d63c40ee475352ee1ba7e59c1b9d2cda76112d5913201541cf7a7f25aadc32762ca87cbb8fc3d252e14d6e4bab2022fef5e2acf99a637cf5f07ce842c39ee6a7169f8e10665e58da577ca0c6eb7b77265895abfd1a343e384bc0402a6a1ea1f8bd543bc4b7372152ba4dabac95ec4dcae95a9a35eef7f1ece32b99d112b7fc4602eab0d459224f1caf4051b13f47aaa4ebe6b6e1bc0ab08a88d3833b7dbef519730140eaf94ffe167f4194627e232dff7bb290eed4e5b34d20d76876910e3668d9fa0045bba2f99a5dddcddddb4a66ac0576e5abae61653630d68c8367416dd6982c1886a8ed392fd962e4d8d6969e53d3cb28d7c79ca54ded4c8428eeaf5c4944900b8e5c3d16fe1f8fcfbf4161f368eb2485e34e1020def5664a0ed2da03b422404106d6fbf81dd1", .None}, + {.Add, "194061792e19cf74c36b256b51e67c7471a7cf99d300cdfa9de74e66fb3701dbe6b554c17367c9d3a171a0f3b9c0c0df3d4cad01f8343bdedd2c2066c85ac649ad12f8b58fedf6cbcec35ee7120227bc8423f8b9e6fad89f27b7c9fabe6dd680f6011dcbd69cde1eb7968bf9844d7ce1e5afcfeba8e59819524b730e51720722679ebc1bdf38e5807a85d2fbec4ec5c109c2562737b3446ea24340c4a2d547ff3febbf3b7bdb62e4a836ca52cc8ddb24064f9517a8300b3029cb679ac841cc2b6aac35a264c49e7795e00510b4e3241613ffe777bd54ed8fa354378ab955ab582dc2c1c0b6a022a67385876b0db9566ef8cf3141be25a66fcf4123b7a31a67083665ebb93232ed6f15c4dbff560ce4d263645679545d980f47184f3d9f8dc23f1842559596422cbb14bfdb39f5dd4ab10eb4286d90965d4f75755ce90f1b21010780a2094c06dd953db9300a57fd78b9e4feb1bf5b8326df45e5b9a0f89858cdbe4ea646f0aa2a22f44dfffe66f97369313580bdcd5154c8d674f14e745f38353913687311cb2ec634af3d765c80c74172e71d48682e2a567c9a563163f04bc97fd49d3c3419838d4bfca9b4a18797b994d9822be494173b15cc1904dd64d9b18c9cde383c36c2b672f35afa8fefda5f3414672608fac3fe5e1e2ed8b3f19312ece0f8289a86311f1ebc5b6988887206ff20a1b2d1cea87166b784e2fc4ef6b5", "ac620e9cc539e8a2ad530142cf234e76890fe7950bdecd72f6a89724bd132475d01842572bd9f0336f318c943ef57aa4646e9a40b9f107041183240af3680a3ee9fe77400dd634488915a94bb99ec1badb0cab549b37193143adbf40d4e2fa66197ef68be36db00155c5e0a878fdeee532d36c18a770f02b691d7a5258a3dfee2bc568553d18fe11600ab1db5ef7ad46672fd75b68ebb080c468f20be044e348751c131cee7ec0f58a017f20367b8aa86d1cf97e246b7ba344fcc080be59d35da6347366690075cf3c7864caf791437fff09ecacf7ab8a94e60c43f8f1e512aca734b8fce955223105a711617cd3f532329c0348e505338fb6a23765cd70947d1613f1fd8e10be61166680363bf460989deddaf89971d8932f2326f72ec999471d35572b2777798cdad2ef525ab75f3306a9be8722587240781e6c5d83ec03778e56ffa51dfdb2afd32e37ebfc8dcfbd409856b34428d948f4b2aad64e7fbf982e037b415100049cb03ee6b3e0ef0d5d9e0baf2cf813458a1bfa48c08da5ae5042c3a2163d46c902f7883672235319d75bce5ee3e07229238782592d844f6b13094371488d0703d66e4c2a72510182730a5925ac53d2c01f493696b3dda54a3ebcae51db47694ff8474cf6008ed3d98170821b42c1bb055ad062ee96706eb36ecc9eab9b66db77d30f32ebf25ac604162f304937fbc1aa89c8154345fdba7f63", "c5a27015f353b81770be26ae2109caeafab7b72ededf9b6d948fe58bb84a2651b6cd97189f41ba0710a32d87f8b63b83a1bb4742b22542e2eeaf4471bbc2d08897116ff59dc42b1457d90832cba0e9775f30a40e8231f1d06b65893b9350d0e70f801457ba0a8e200d5c6ca1fd4b6bc718833c0450568844bb68ed60aa15e710936424711c51e391da9084d74b46730770f22d82a09ef4ef66ac32d0831a2b47b507d2586a5a23da32384973030965cc736c8e95cc9b86d36ec8281b869b9f8910e0a908cdc51446d25869dbac7467961309d424b500782489607b83ab3abe04d4f77abd9ff544d7792c98cc8a8d4ba12b6b348aa32ad9ff85e35b1d708afb854c79ddb6c043abd02c2b5c359201456b01523171edcf70a2763b7634ce575b863577acc0bdb9a647ef92ca8c5094a9e4155de6f4b2eecf8fed93c9469307247895d7a1ae6a04904510e767f6548b4877259708729fac00283a98647747181865ec52218841aa2ebfa48ce6b247e880c6cf412feac5649a52f26f3a0f0204e6857bd70a894f11f7c92c3773e87fd3e118ceb57c2c48a0537a041caf5ee83fb6dc89180e84c1208763ba48d426f2891a2c9f32a7d83866d75a5f02afb8bb0a23f0494b301383a012aeba4050fb1ec3b3e0a4968268cab5c9592e811d6f24604681b97fa3c40161a8f22def475be34e761d2e50eaeacd9052fb2eccc828fa097618", .None}, + {.Add, "-6d227b34ebf55d3067ab563cb3a31b653b5a2c26029991e937ee41b7b9cfa90ed65884eceabe714d4f53e40e64f564b9b1f51bbdc8897fb4c2783d783ba38f296eee1d7afe4d8352f778b43d26ec43e8dfe6f56d01e7bcfe6998e6151701023524615a57ff79619d3abd81ef4413d48e8c6a20375836b11a2bb77fd11fcc261e44b5784edc6cd6470b9226cff4b4db39e8f3434639ab161bb5c61a19ddbfe541b52aa67f0312baee244d87a4c8c1058fff6b8752fc2a3fc4013947923bb4f2e4e18453be4ffd0f923292785f0ac1d4f5a9960b365c184a7ec4093d30f4f0bcf450d848cb3799b23bce191d1be73d10facc28b3f68c40031791453cf13f1495ac844b740f4b647b51f060b1d3297b46d4dfa0207faa9b3f09373732b8c715e13e1d2f41334b9e0aa3a6f1447a8d0fa6ac2e5a7e892f5ae9f3d35758edb94c6c0740c35a41ba5e4e998bc4cb31a38cd2cb92870d34e99b091065797b151aac663fdcf69f6a27ba5917c705dae90f27830cc7d21f8f23c7989dd39ebfc996071f06d32e3e88a97502f98bdb8723608d74f53556b406eab12d2a539d59fdc52db4e275feeefed2a2598e561d32c8814f743c776971c1bc0715242a55ab0b9e6dc344b14f51eac7dc4325e52c14eca8a6c29c043f242ecc2d681e9207157ec2d3ec94bc668664c4e2f0c969a78c50c7e53d53bdca451e2f6565f143f0bc1ace33858a", "bc8c40c8b00bc545199b5c3f3a8b999fa2da74d85a23c9081961afec5fbc4e671413400a08af9554399c75ebd9170328c4610400774451a7fa4def068c525154d5115af61818de5aa8a07a63659ec43d9137b4331256d566c72e5a45bce040ba60e1e557d023cf646fde2bdfea7d134e419995a1e9f42e98d6e251b518cf6ef9171e2f01ed0d79d180e6cd53c2891bccfd219cdad20c515c693d288d1e82e925bad0a17d17b7427d4a2cc018fc59727ce193b0f501804ef5eee56ef7c7ddef4ca1ad9046f341d5269087747dd028af82c75c7295c7c0a3761ef23492ba6bccf50194bbfdf8e2ec09ac2bb0a2441f1b1c45eaf690d20458f93b3635d406378a489260b98d1951b39e25b4b721057dad8de34437e699779512d7fc76ceec24849483a70d8f775a4c79266d0e0ae862c5b39be1f5bf66d3ad63a86dc715bdb980f5508fc95558d6626636962a443d9297b050810496f2f5d5f1a808448d8227f1dd3cdadd627abb122346fd18e0942d58f5253f4f3b27acba4772500e1a8c5f39a27426272e97079123dc7dcce99afed6ab70437b13e8b9d49f687c197febb9901c78521caa20a538bfa6fcfba2e6f614a2f39a54e3e05141eb7889710665021ff8915995398e447e562229144735a2af26ad03b5a418aaae8db4e0e753cd21a46e6576955ec1b69121825e0a94aeedb122492ddbe76b19bd8908f1e9b8d2f4ab7f", "4f69c593c4166814b1f0060286e87e3a678048b2578a371ee1736e34a5eca5583dbabb1d1df12406ea4891dd74219e6f126be842aebad1f337d5b18e50aec22b66233d7b19cb5b07b127c6263eb28054b150bec6106f18685d957430a5df3e853c808affd0aa6dc73520a9f0a6693ebfb52f756a91bd7d7eab2ad1e3f90348dad268b6b310a0a38a7554a683cdd44093142e599498613b40b3770e7340c303e405a5fafe14a4878f25df387433986cece22829a205560f31edac27658c28fc67c0293c88a344c5945df4fc1ec566da8d1dc6675f6ba858f75ae8f761c57b1000b0bc7332c14939cdde1293865ce20a2179c2429a45c455e1a9f0f8e2c722f49c0e15457dcded384c3554054ddc0266b903a41766eedc5609a0c54416250ea3566677cc5c2bbc41d57f7bc9905b531f076d8777363778c36fd5166e28046d14ee0fcc6f139e7813ccaad15f129a05c4e4bdf9f762095acce1428ec978677b8b9d5fe43df85300b90b7ff73df78505d5e85d6d2fac03e521a99eb14e50f6581a9ba0f7e8a5ed928e2a50a245c63a7161b63aecc70cfe08a77514debf82268bdb3a02532dab4e02df3150dfc8da65a6a0667c30e322244a2cc74e33c5fac6945cb3e00a434ec6683b303cfcff5a8cfbec8aa8c491754c7d466f22d9d1d50a4db7d9a9100ef9fcd3a05818b67e43e70873ce8b6396c93bb45797c5012d9e04c125f5", .None}, + {.Add, "94cb787ad143b689a40bcf1a511e7af0cf50371b48707f3b0a08389c12178b00c6777a9af53e0a80a553bcd2d96fbfd25e8aabdf36c9c2f473f3712bc4646b827ae64ca1ed048070737b0867864e06c7e50fe96a0c5ab4c6dff6c83c0d2937f08b309844a79360225ef09c32186d87d669fe853c2de37d627ec7232c0bb69a85b4cf04cafe11399a59bc2f4123537333a441a5500207894d781196667670819f1c6676e384adec5f583596efcd11eed5c8cb7401be89c9ad3acfd0fd8ab1e387106d28aa3384c06ed346cf80be365b6468c5a547791db66e4e689781af73587796e540a53dd33dcf55867f946402ee1f61882dd7973fb7dc57abd2e6bb1d0b0e4346154fd0e23060ea522082634d22d18dea0d27c7c9caf1f1cb1f5cdf411cd8ec1dfd4bfa45ff3d2ac96e1f58414c4cccdc1337f20ef46e05eb69d992722b604f3ef3565940f98b8ac7c32494fc30188fac15ad1ba8704c0230aaee6c5ef18dd392ffd54008e663981dd1f40b7ae348c81b1914368f363d5415a3346e70a76f9ee1f97b4ac03843657c5d1fb2b03222f8c0cb29af0d08a9f0ca2102a0d80ffef345454e58ee6739ca8b5e2c23a2b942f5ef0348ae05d5848964da26240522a91545f54a6672c64b1496eb2cb9ee7a7915ba83e287d285366e3b97281203228d8d78a02e1eacfa4ace7fc72df9fa527923454e2d53b4651de120c13dec5cdef7", "b494686fc67b484379820fd8ba1ccdfdcb4cc13d6c25d2aeb3b9e64d8e12b1f1604b271aea24b3c35223fe59369fc3c9f75dfc02a7719493e34ba5381544731037ad752a08b862d0a92fcf72bcc65d3a6e4eb3ce551ec2f79c576951d4e5a5ae11d66a884f6cf4b32fe4fef9e7a80d221a10abc168dc8b706c3ad5b46c2d71d32127a87719308bc15aa52f35345d2cb1fb738152f2f63b729a1dd3a0fb9cd094e81cfb326a4b5de208ddf09b2878cf34f2d9cbe9c320b34dc4a04a12bf7b1e9d5bf33bfb0ee8f3a2a1dd0cb00b900556547462b2d7b977ab348a6869d47929109d9370f7ec3045ebc1e28584bdff6baebc10f4806ec5de70403ce9c003a544b30ae9fd197b4474f3a14e32b34cbb2a2150df01ed74182d07d896016485afa8ae0997da2504000990362c4f19399ac5e607a11949ecba962e53b21de9a3985db0a4c3d31e07e6e9bf08aa80a01a24593cefe9e054ebb06bbc4b401e2978f923a8a0909d2d58d97a0ed7ef745319e5d8d766b5df4a2f70fae424384734fcfa61e6189a115d072e7dad2c87efb85e32191025ce6aeed1eca3b289236c57f7edc0df3d8389f01ce3ddaed09d091497a6a549c6cc4d5f18c1305803351364be24e1ac3956c85096138328a3884d2b741e3711b75d02a3f98f18faa32129508d2d76457780456abe513d239983fd9497c84c73964467bf8ad3362d191faf04b3ccc21b", "1495fe0ea97befecd1d8ddef30b3b48ee9a9cf858b49651e9bdc21ee9a02a3cf226c2a1b5df62be43f777bb2c100f839c55e8a7e1de3b5788573f1663d9a8de92b293c1cbf5bce3411caad7da43146402535e9d38617977be7c4e318de20edd9e9d0702ccf70054d58ed59b2c001594f8840f30fd96c008d2eb01f8e077e40c58d5f6ad421741c55bb4615e7657b09fe59fb526a2f4fdc4c0122f6a07720d523404837215eef94a416113878af58abe0abba53feb81aa7cfaff701b104a2d02246c6064a5426db4117523dc30c9c660babd3a07fa50d72e1982f2ffeb83ec81883478b19d2a0383bb17690519220259ce1d9922580605964c97e8bca6bec24fc14e3012694c26a5548ba05335b0084cf2dec90f153be1f7f9ca6120c164f0c586f5b5d770fe4608cd60f5bd3891dc1232d47d2c81dec98a9c599d87c3360a8910f402c6746127e34a937243c4af2089557f95f6020758dc084d70c917e558153674239d0298e26072700d46472560bc202ed0f85e66003121784dea696b6b0955b77c0ad851eeb5f092044cd810e24b331e8f361880f9ac5c79ed8d5a98c5d0de30c8cf3e75d244e89b286740bb495e8cbcbb50a7c6c705dc8c99ed8ae22a04554e9cbd9afc864973b81f38582e0cb18acd17868681619e31115cc0789f3098d304f8e598dcfe376e6803c4c291c29eecb989b5ecde879b4afa407042a029a112", .None}, + {.Add, "cd7dd8549d2817a5d93a650da58c3b873ed9b4662082efbce5e44b8ccc19b6fddda5b10e3af2761cbea67afc8aaec9779ea6cf2a28e8aea98f0f986ff5ac54ce7bf39dda3abc504dc53328ee18de42c09dd4c90eea8e9589292f51fd288789887c98eb60d8c9970e3ae3f46a3cc83e2e18c4b87561e020e854f866bc429f4e79b99289c8e07b78aa2ab19a6b5a2175e67307911063f5b40883eceee1a322120d130dd5b265704c8461ec176bf416428922c1d3e2b151d020079d32fd83dd6c7c662c65860d8e9bf725f2c825e0ebfb89dea472e425cbade3645f410a1ca84a410421696206dc92840e6ceeeab5aac25d23022a8dec8db70fc473accda9a30fe47d59327b155ea4c9fdc53644fdae287234078ba7466b7cdaeb51bc3cc3e48fddf2e705de5b1aef120b2d10c56f06035c0ccd4a349357ad26c45a5b0a6595a3a2ff25442a568a896f0b39350bf84c71a2416bbbec5f5df8adfd06fbbf4c9a41e251c6eb52a2e1067106d8fb541365edf624121ade20aa82d6b8ef2c0c2830a2f27d2a93675fde858dbf4f2946f8363fac86e38897c937edc4a83fce8553c1b28da20fb9fbec35a2851c244f837c815733b816c6e594b4efc3b57fba4a693bcc4509b6121e816fdf0d497b98354dfe692e6a4834fcb52821df0dae3428913ac0ed9d62f9dd69f992d95d81e20047347e78ef128a0779735c282b243c9e374816e1", "a3ec8a244449d090207f3972666c182157563655bc35c6c8018f1bf518363473d05da73139a387ef72158c17e04d19401da843690a195f402f9f1a890d2e336a27b8ad2d41056d98f6c89a5b0cd42dbb861b1c002cea7b730f0907200669edcb4b8adaf12c795012464be88a969cf56e0ccd6ff7fca0dde167431933e8ea36d2e53f07fdaf8e4b4bcc8a6eac45b8d1735bdd7d24d1d17d62d98b47ac006097ed2f99586e5509d15f31a26168c31a9e0002440589fd501481735825ce08b797c1585598d4071c04a558255f119b6f9b5616868a8bb04ed07c932d4b8069f1eb147c51776fe66899bd7651de0483b76f626a1bcd7cb66d60bfd9086ac6eb04fda4e3266adb9b233b73778b4c3e1accbd5f76e12051582f1a5a4d6e0df1218b9df598ff3f58fedefcc13ad072d8744726ca31587f93403ec91b77f0769224ede28362a90cadc1624b9abf3561967ed0593c51efd2e34b2e5a1c538641c1d6fe259a7786639cab0ec1db4f050c0476faf9010e08ce9c16c62f87ed29c284d347724e0d82c90552a152882703f982125c14f33fa7767b18045170a5237bec568712417113d8ce76e5f20ebcae069995a3eb44a2276f798ecb961636562e9fd93eabab59c819947c43bd29b397df8990495bb4672bd06a1c2f6589793638bb947259a964acc131ea8303afafd56061953832090cb6a5238be068f4a3e68a2f6ffa10ec", "1716a6278e171e835f9b99e800bf853a8962feabbdcb8b684e7736781e44feb71ae03583f7495fe0c30bc07146afbe2b7bc4f129333020de9beaeb2f902da8838a3ac4b077bc1bde6bbfbc34925b2707c23efe50f177910fc3838591d2ef17753c823c6520542e720812fdcf4d365339c2592286d5e80fec9bc3b7ff02b89854c9ed191c69009c3f5f73c09179fda4759cee50e3535c7316b5d78368da382a9fa42a72e20ba7a1de3938e78d4b730e0892505d96caea1e4a17af558cb8c95043dbe81fe5a14aaa09c7e1827377c5b96dff52afd6fd61a7e5ff78c8c8a869a35558072e0d1ed452c4184beccef396231bf8d1df80aa2fb17cf9d7c179494a80d89607f9d56b081e03d75508283187ae5d1aae8abf89e9a973538bfca2de5702dd38be6453759f9ebd345fd839de34d2a263e25c9c7d39676423c4ad19c8a83862661ce50d817ecd509ca6e96a2771ccade935b8ecfaa8c52ca508d3d812398677cc94d4eef4defc84c55de07588a60e6f7321ae97a3770b25ea618ee90fb7815408aad5c6cb27fd815e65322c90a92549fc68aff12e13c3f354d634a71aa48c4cf132392ca631b9493d8d2561d122542785a3e365f238085d9ebd5e8ea427a77f0637e2bb2fdb39c36fd1377bede47c4e2d1740566d157876886e46ce425ad1a97020fbb0f547c96890d574261dc6cb081fbc92f2b0553c51ccf0ac6cda74227cd", .None}, + {.Add, "-a2c37285b556f94a0854489a0b4ed17e62de0b894b67ff8b9720c734bd9f48417ab7e4551a371a0cf01e5a0fa45bcc210921194287f8c5449ba9a834c062592bd4b9c39e965f36c6b61a67f9d44ded7d916e75029db5c3e32eacfcfd7d54933dfc1c46f572e535e7443adf797368101b93256bbe304c50702d9933424d184b7652113ee1be34601ea93b50c9e6c8a0d2ae9bd28e6666b23675779e8e87d58ec3ea5007e8e7d46a23b4f0de8365750f5f21cd98ec33c4607018499112110968b2a7e9953995ed30240bcb0fe926abe7a4313a6dbad4e7d48784e30811805a2864ac08cd8e893d0ad60e2583beab2ec6b521653a6a9e3c84de145a6051002709638002436b82b99a0540274659c42990e21917589f5193c73954eadc5158dd551120993890f63a14bccddce18d842f0b02cb5fb7103ccfb9156a54152aa2ad20c19c538b34624863b0a5ccfa4469631e4c0230f5c0a9c55778c865ee8ea3878e30a8d9f0c36cc0ba6a76353d2e14b9efe8e418742123ad8ebcee93f5909dfbd949e6699433ce0c77c690935e88c62c1016c461abf6bd2e293bed2d2842c33509db6c6646a5f6bd809d9f8eab8c6f6d5b0182e83caaeb1aaefd727ab5a23fa8b72c3b1228562381866ebbf185217624f262ae8c72a24d63424baaca492aca5bd42815f519d3e0890b0b72f3da68c8052e432041a313a8dfd9679dff6ba72fb29988", "642f41dead514562e3d74db2f20c495f5439b6b6fac77435ab83f40bc19bfa963d122e6b74a03d8714095f5cf009d90a56a380f6e08216bcc336612bb83dcc5e33c2671eba4f22cc7babd308459c2e3eb6052cd638bf30f74ef958438c40d3c41c286477d6c37e976ebab914a5771013473a7d15ff742d64b0ac5c78fdaf168c11972204cac363479c14a6085ecc7c58ef4f19618086ba1b0d001c288ecced844995f2f56ea0afd6085456e2a87286dc35dc4a87a4b7d363425ede7f6dd4a1d5a6ab555e27bba1fffda2f9605397d2349948e0ef17600733c5a493216f88dcd17a0d5951d2e413b777404869627f2de65a5275416dec07544f3e17923f12d383fcb834b1a018c31fe83c2e93175ac792b9386461401af7f1e61c4b9c51c185a45e99244e5de854e22f1c6ab6534c4a69b49ebd95117c0e34e70f99e571b3587418734f87da86f659e0d01b28d4f211d5ca48a3244d925bc5ea50051128c94972ec2d4cef478b0f573d882e25b2840569d6c0533ef13c4cfdc34bad0e0d7831b25c019f1a7a8a979cb7e461ac28a88df2a9abd30972dd72f35ad52f79e07dddde68e3dc55e542511f419b39b8adbc4670b2d472b4b3acbacc0842216aec2aee1ebb1453ebe05bee296b6b0fd26ee6e16b1fc73ad6036b10c622e98e289114147b604dd50f8508c1e408385a53c91739baf8c558a7e901c0485ab89fbb46fc8f3a", "-3e9430a70805b3e7247cfae71942881f0ea454d250a08b55eb9cd328fc034dab3da5b5e9a596dc85dc14fab2b451f316b27d984ba776ae87d873470908248ccda0f75c7fdc1013fa3a6e94f18eb1bf3edb69482c64f692ebdfb3a4b9f113bf79dff3e27d9c21b74fd5802664cdf100084beaeea830d8230b7cecd6c94f6934ea407a1cdcf370fcd70d26aac187fc2479bf4cb92ce5dff81b68778265f908a13fa0ba14f37933ba4dac9c87a0bd028882ebf14e648f0c8d0cd5eab292a334c6dd013e3fdb6e318e240e281688d314156f97f18ccbbd87cd53bf3e74f010d14b9331fb743cb658f71e96e53b5548af98cec712c52930507d89c51c48bec11435df834a0eb9e2a0d6e557eb17c6accec94f5fdef43e1178cf476ece90b5071bcf6cc20014429851bfda9ec076d730e2c09916c0f97b2b53aae083447b4530f9c84d83e03bac87c16d56c4fcdf1b94710c7637e8529c5c32fbb2de15e97d7abe44bdbcaca3d42535ab1338ad0f086235ea7f0d5820e2327141bf2b4848829083a7978a67f5195381e029d8aefcdc9d8382241ab5d8ed4a50b6489257f8c8e2b72bfd03826a50117b2f7e5df371d3c1b11490d013c9f6376df4316a389437537dc90d7ffdd46a432598455086754f073e10f78ec537cc49f8318587e0bb023947bfacb5a744c45b8049276abb8014feedf488277c4a6bbfde191f4346cbebe8b60a4e", .None}, + {.Add, "-f6e1ebb1119d2762de95ff5517804126487ff2b0bd420f253cf99a278604a0bf196df80911786fda4d8c705e730cb026165c7b7441cc4e0afd5c7b69200c837a81d5f030b6175fc12368a211dec54c5287eee6d2f6ec8afa3379f9bc44d392538ee14824c855cb1a209e888e76c8920404989bfe1819043764ffcabbc26ab648c53d8ee1d6b457967a17a45988819ec66e01ee80a4a1cf8467c42b23ff024b5c26d8fcd753e5ad187f27b5c17a619bbb18b403d05ebe2d5561377a8726d37d9818dbfa6ee7990db0347d06be9e297c457e0d9d65f657635fb0f2e91a54825c5ea3cdb73886a74425d9736b96db6e1f229f8fe0067751e2aef93f37c4eae37280f1d46fd7a0aaeacb1273d74ff41f08736cceb804ba68ea758974438a273a7b315c8009d9a132ee8ee02c8586fed076d1ce4d39d10e9a8224599ca6234adbeef2fb1445e68ed9fd5a9835ad69dc7d28261a7839b6665271993a97801d34d21c618998777c95b7c7e0328ba2987cd5a30cab7ddd4ada71e97b2df07f3e6e85faf401910e8d9c6ecbb12f3dc93d0eeea368e882812b9a7fac4215723079b08f186c10fe800bab519ddcc24e4c1cc72d7810981cacc686af04e2774ebd5cdeba0128362ec6d27ea75a76bb5f75b0e993f18e134688ed34ec606dfa1601308c1e5c3b5c50ed34caea3ac5aabccd6692583f7680bd411381ffac31449fae13b35837d2", "ebccb5fef5384d2ab5300e4f65c09a1e151feab5c3d38f649168b762626856674e7b66b6ffdc515fdf84d3be4a222e8f5e6b90eae9b87f6c6b293b948c2da17b36b2ef9f8f69a7a0cfe802db4e96574694b7d765525742ac84fedac9b9cd5351d854382ae76d9d3a2fad7243955d6126c9780c3b6622b4cc4f5989ff798e48f9ae8807f2e34600cd50b109dba2c75d253855457c5362a0419dbf78f564351aa523ecd42385e2e0455e3eec524ccc3dbe6e935c23c24e285145aafc7c04374611a0f88197022ef683e8087689507f6b603144260f5e5b29ea90d30f121e37a60851911732f52a826704e42dabd7eb6663208ce754d339e7f5e582006102b78b116f849f42c37d88b3d751063bc3c92b1b26a8936d4e479cd889cb3dd9b29d48ebdbbdaf8a2d3e6fbbf1232fba944ceb3c37aeba19f6faa7c1916dc5b525fa3132b31aa4cdbe5d1d9e9a992a3aefed67c52513260e223d93d30fcc6c3efb9938fe77d7c05a599c3f36033a1412488d85a31bef4c55b9ed5259d5f8bd8e4e5b50dd7bbafdf1d5327c48542eb4067e328f21da5a6a235c57cc300101e8fe082b7c1fa74fdc4f9569fc75d211b84e58e436ffa6f26d3b2b144b989922ae9d9e6653e18cdd71e7eef69ea55272db6ee50331251dbf4eb8a1390c017d740c7047c16a74cfa89ec85f747b1e4a6dfffe55a682d34389f13acf90f7663895ccec5381d59f", "-b1535b21c64da382965f105b1bfa708336007faf96e7fc0ab90e2c5239c4a57caf29152119c1e7a6e079ca028ea8196b7f0ea895813ce9e92333fd493dee1ff4b23009126adb82053809f36902ef50bf3370f6da495484dae7b1ef28b063f01b68d0ff9e0e82ddff0f1164ae16b30dd3b208fc2b1f64f6b15a640bc48dc6d4f16b586eef36e56c929669a7de5ba41a135aca904513f2f42ca04b22e9acd30b702ec28b3ce02ccd320e8c96f2d955dfcaa20a7ac9c7005041b8c7e0b229c378677e378d7e56a172c4c7490354daa10e54cc9775697fc3975201fda08364ab656523ca005917cc1bed48f3deb0382b8bf7f02f8b1a417fab913bd3763e82be76f824fd094dd2d62173b22d1143055dd58462624976c214d9cffa905b0749d324580c25a4f73f47ed2ef0955cc6a838b95969e7fb7179fda62c82ee06e24e1bdc047f9a118d07cdfbbfd9c832eec8fc060f56513a84414ddc62acb13de3938e36311c0b7223c1b88aa2f518e8634481d698f8e90f52084972157f7c1b0202aaa1685d6109bc73c4f68db0f153690bc14470e2817083e27e0121470477ba8639c4c69aea3bc15e7a166f03c93ce6e494110f12a3f8b5b9ab949de2c0ebf4053ad46a95154ea8fb0bbd168ec9a420490c068f5873a3493b3546c7ca1f4c0445cf1c68ca84e6c6b75bfa7604ecd683cb1bca33d334fd8b26eb4cb0c09e1275fd66233", .None}, + {.Add, "5da33fb91bdeea01bcd974a4343febc575ff70e9299e860b7ed812061abae380b79d204abf848e7950e2d801052e8aed415a02f0d5bac59c7dcf2cc447727189fbcbef13b00fc6bc66455228b3ff12fc3f1a1f44b70464e5bc5a00b580be5618b4f9bb03ca94540afbac5649b55e08f3285488a6670f5cc518964cdf5ed980c9b989d352bef17713f8956ebea1c7b85aad14688eb454695f3c9ca31492fe4395d7d31949822a8a2e4eb051642413120700ff54dcce054d38a27114e9a40ec4bd69ad7f4b96dc4accd8a1995f99729a09232f5f4f5ec15862dc34bf249de9cf70e5f50a04a38a71e43554439b423945c3fa0c45de5cb44dd7e1a987ecab6ed103b2cbbf4e3c3c755d0d9635e80ac7e0fe0a9df4aded19c8517f85e05ceeca0e4a91b2d0ae6a2e306bdad73c63e8646619213215e595947ba5583db4dee9449aed4160b95c93468ed75e568f22f6a3688bb54596393672fc2a2be9574331dc14ae14982f2029d3d9179dc7253e78a7b00edc74380ec768783892a6e018ee427499315af69032fed345cbcf850659bc4658a45a89b7ae55c2890c8231af0b1158633a7621e2187004e1150663e70f7911ce1e5d43138c3be2af4a3f22892d5d3b5d95620480d5b7e483a9b2a67e2b1f540eae1bc347b7209557c4b81f1583f33e6719bffeead611ff50f4aa928dedd934ef686df86198bdd6afa2a3d2c1a8bfd41a", "6f1038900b63e89b19d383fabd8efccf77c7498c6abdedc49aa7cc751b3863f5d9bf21347eee89dcb343bf3c7aaa6fac9b1e693a5e73ad607221f7fa47d23f083bd75344dff52271d487b6de107409bdb781c32f142193582135fd5b8c4816b39b726b624bd03ac2e8d7be0c49baa2698e85d1e3b54f7f6edc02aa4d9edb24698ed0f83574855cce1b82e1577236480171860fc717f4d3f314b8f2c4e4ee1c48831e87ca5722c606b0de1fbff73093a13535759636c081c92793bec8507b0e0db1b27e888a36ccebf79b25824ccbe4a6fa6562f0e5b569af66753bd08429fad98bfcef5bdf69e94ad0435035d3ba73e62b483c9fa8c53df222141bb3980e7bf55f0c1e8482f6c289b7e05111be6085c3a68dcee4a327c742c1a1bc3a370da7b341c3fffd57ceb7fe46291d2ae99b0a9b942d4795f0f0fd258e405b1d2236a9b9f0a25a4a8fab69092f645c78544db1a84a30034feb6f672c5b2a37bbd24d4a2ddc31986ab1705385b9ca1f7d374f32d870f26e9d261a0a66f14cc568df2a805209ffedcca6ba48ec41f9b531257d8946a2dc5ee51c83b249fff5cd67f9d8d54fc8e3cf99cca2934710ad3d41cc64cb54787dddf322bac8707428ecfbb4101cf2b4df1592523d59a89eaabfc47f5fc291f07e84521a5e4be0c14f8e554fbda70bd23f6c3d23e315b17ebcdc5f6323968279de69d8f8ddac99bbff912c5b2ec301", "ccb378492742d29cd6acf89ef1cee894edc6ba75945c73d0197fde7b35f34776915c417f3e7318560426973d7fd8fa99dc786c2b342e72fceff124be8f44b09237a342589004e92e3acd0906c4731cb9f69be273cb25f83ddd8ffe110d066ccc506c266616648ecde4841455ff18ab5cb6da5a8a1c5edc33f498f72cfdb4a533485acb883376d3e21418501613fe005c1e9a7855cc493d52515595d977ec5fde5af1a113d94d5034ff8e71241b43a5a83634ca7304c5cf01ca04d3b1f489d2cb1b5ffdd4211317b8d03cbee1e63e7eb01d94c2404476c21242a9faf52213ca4a71f1f96082f45b2f059793d115f3b9aa2554827e05798bca03bda3a0437d4cf911d7ddd2bf3337e6c57686f9c92866c1b12bc39290418f9441279c9725d7b5fdd376d0abc1fce86a2100598ed1ff70b4b55f5d7b868578cae67e0ffc0b7b44a7320313a722f1f7e08dbaeb9b4af11a33ff75998921e2635687138eff04295edbf0c9c78adb442c9d579144bbaff6e2e74d66a6abed82829f83f3a581cd6cf4eb3b5ae45cd9b91c320dc93a377f39cf9f4736e89ccad974d30c77ff1704ea2db30359f17be512982825b3a128dbdddd2296db2106aef6ab1fbe680f84e16d58504a411a1327f53e2c485d6642aa7f16a09e9a4799d17ee1388607ad6ad3b0e572ebff6b27f9f5150273676eed50fccb71e24c623a919b83495ea363ee03ee971b", .None}, + {.Add, "-4714b7e6bbf1ea51565ffa0d6580d8842702266fbeedfd4e72e5ef75ea246ad0b59c5f7628b86d9bfd5075f4fb4a6ac82558a98deff895a49a620003fd315c9d621371b0fe17eaac8a71684421560b8fbc3db36b623f7b346e28d65979ab5d9152de0b473e945743feae8e0664d1c1e5a2cde8f194750bc0ff6d989e38ce4cf297e7ba6d9e8dc42bada16a0e3593fa417fb2816299d3768915c567b2762073f1478bf4f3f68661523ca7b80516a18f00bde3177adf90834c0c71f512d61b36acd3e2819e0f6b1497539d854086e22d6027c76a46003705ae24fd775da3f67ca6a1c944570e73cecfcb0b741f20c83b6f7b03603355d301d00f655969ae227ab81a877cb5d7bd922470aabe82944ce85acaec527c064d1d28f6d9b495353b9759d06e7a3a0791dfb1e1f5154e55f0c8318b6f79489fb4b504dc138ae4da7f6e8a8049b684817e6112ad3dfac9e1c10c5683beabb502bd9c80d5d34235281822120a79a1f19f04eb63926c9a8317d1b1314b960ebadd9a1b1d194e6106547d9c064d5e93fbe4e62e413838415b10efc4cb144e549b3828a583ca3d4b3e122d2eb8f243298560e821ae97ee1c617cacf9aef90b47dc4e51cf77624ccc14e8b935cd64bdaa654ce27332831576efc6b4a34ee247906a84f1c0ae9e317f09195be6ffa4dc0035ea8ab0ee8de6781a4f07220c0dbe3f90cb2fed74cfc502ee23b8a7f8", "5034b5562db14f92d3de9cf063189c98ff44a350e3d03e0d6cea746a65afd8e29315eca029fb83bdbb76da53344842380192c02bf5863cf2b2f942518b69f76c27966799bc71fca5c6d84e4b3f3a39dbb59d34c98aea14724554399d41fca37a5c4b36e30becaffc0592cdb286b52343d194115efa5b569b612f111b444b07219c21a44cc16c87568792b87f58c15156f3490e436d49d570d7c5c2da471382126449c2bd80cc14e2735e46f783b578a039ea407653ba3ad751d5e2e72ba151dd1f125fe42047a3dd4bd8155e9d2b38b91c8a968b0ef42c073ccd9f90cb6715765ea203ac23c1967563caee7528fa932f8d4343b936f849f587354b86736e5c27ca6ea0938101b70aaf166273f9ffa68b0bb7fe23f9d55dd04d1cfe3c43af312ba5cc63c71cf7629208a90af6d25e168fbadf5bdc0d0438de0374b650b6d2f2b19a61f0177e43e8a8cb71fa5ec522dcb4a7cc5fbba4120cd90a6aaf10781bd92a0a7af7bb1096d569b898cdc5079768b6608d816529e6a173ff65e8abd59f05bded5ae6ee525c6f2d0a7a16d9912649bc438fa5bcaaae7f70f7225e509cb5b6fc5a12d855e1670ab2e1889b4945c5d17f9eeae5f583d74cc47068eb0aa4faf9a9c8745fcf43afe4254409e136db19be3ffba426f2ddbd62ed405475617725ed9c4182e3a5767b84d11ae7d478bdd4b4c2700bf0d90e7a4a4546bffed52e57f851", "91ffd6f71bf65417d7ea2e2fd97c414d8427ce124e240befa0484f47b8b6e11dd798d2a01431621be26645e38fdd76fdc3a169e058da74e1897424d8e389acec582f5e8be5a11f93c66e6071de42e4bf95f815e28aa993dd72b6343c85145e9096d2b9bcd5858b806e43fac21e3615e2ec6286d65e64ada61c1787d0b7cba2f0439e9df22dec32ad9f14e71232d571573968ce0d3765ee7c2005b27d0f30e211cbdcdc98a45b39036b68ef26d13e99f7c0728fb7429b78b4563edd455861b304b2fde4610dc8f45f83a901e16490b58f4c32c450ebd265917d02833277098cfbcd8bf55154dc7a598bf7a56083257c0123fe385e125482577cff21cc54be16fafe723dda94424e63e6ba3f165b2be3040cbaba7f38840a7564349a70e7399d1d55de98d156582e026b3f5a87c6d4e5e2f6fe2936d4f83d927612b6bdc5384271a183992fcc587961e33ff94e361d05e240db406a154705834976cdb5003b718000155c97191ea06262c3341efc5b78514f772aa4c4c8656e61787a5812169b79ffc52f26d7640ebd241d57e803684f12f4151217285d9ed2ce513128a88884367cfaed0807ee904499a7ee7c918d7d0a5df9e1935857d4d0e1c1ef5bc41c3dc63b6b569f6cd70f2c0f46a4714651af1195c968858cba23ea222f6585dca069c9ca6e36f8bf0d3e28d015c5e6ecd92b6624db148434a5cd076fafbe70a9f5059", .None}, + {.Add, "5305a95eb26833b7b0e05105d58a5aede70edb7aa1dbc8b70930b4fbb83c368599e21a59bdd0101c685650d281b69d47100b2c1857a3556161b25e2b6ca92f6a0fa0b2a66cbc9f9073fe1b45b1a6aac05dcbaf5fe1efd59b113f6c5b84d5b36cb0418d9c5d5a7513212e5a87745e40f6cf1c6112bf0e206bf2286615e339d42e67d5ceb1885ee7ee777b13525ac63236ffbb9a914dc462c1397d33b92bbd2a7e1eda82d89597a65ac33cdb1ede35af69edf64c452a6526ab1ed1d0c713383c5f62f3ce16e95023f6443f8888aac88d07cf7e70601d0612f2fe6415e789ea6ee8de1f081a696855405960fc377bb7e721c37a5acb55232b756d7e687389a6e2f7e4b05fd96801ed91ea984e3a4c16a53bbd1a14003a73775e1b4728a3992fb1ec40a4f9363e733dc1398440b8a2525245c0884e33224b4446a04b81046809d637ed909066f47242b16fd5ef34e9db7f6b44cbd7d3c361123fd09b0471b1eca692fafdbdd3c9754140e61f18c4a23b507634dd6791c6e2825c1eb6e1a9d3c113f21bc7ba5d499394a94201c45b4996d5b3035e4b2a25a949526023ffa63a1282f41ee5a674b20a146ef56895b116541861d3e8694f48562da1db418737a0f94767914d46e4f4d5f2fd5f3b899da8f19b964480470c59d1b228aecca1bb2da3d3cb403e158270296e82967da487b5b658db35da26eddbabaa4ae13e9fe4e975e1a7", "942390080eb062761faedfc3d9c4a10ac6e5002fad78d41ad5dd37e2498c1e254cca004771a252f56202beab4f3990f53eab81e841bca4e3d851a2b1d193359eb7d3f67722be5099496a5c4c2df5d3e4bfbf857cf25ab6c5ac772ce4d69faa246c25019dcd625b62df47c9933fee7b140d24a9d290615adce6eec24d8e9fe1474f0b01c85148836d9681a3bbaa3f769390d16a2d47faa0cd6b75bd462dc86c0c8862ae74534e4c010f362268ffb6c7426466625eba9361da2812933044dec2c75e22f9cadd30dbee14b2e80ac31fc87acf0411e5de1ef335e79583c3f95a73f89524c71e053a23b3d86d2b439be5c0dbe27192decd85660a3bbdd0afff3a6c26ee84f3a21f319a9e3298841333167ba8fdbb43528b1a27080c3add01685bd3bb1142a74e8546cbd4c3a17e8132619522aea2ce66395fab4cd078be9d5f495daa424489265b73be1227b357dfd1b852f212b2debff849035c2412b0232ccb168578ab5e5def1a09b494711b02bb0dea6261bfccadaccfb3e7a9f161c594e74a6c1a3e1194187aec4d6ccb77fe6034c78d4c1a476d6cb594fc787f5711c39c631a9fb695c6eb66e8401611f47115557c1abd7b3a5c23f1454dc1042db85ea5fd591c37fd9fb5a97fb0a5494454e4079eca5a84461c4e0fa3fbb93587b1d626a0c5d07b9f32fc2cf5a1daab56f55a8a42d21f8b781fd7d4fd177ab2b775f7d3efc6", "e7293966c118962dd08f30c9af4efbf8adf3dbaa4f549cd1df0decde01c854aae6ac1aa12f726311ca590f7dd0f02e3c4eb6ae00995ffa453a0400dd3e3c6508c774a91d8f7af029bd687791df9c7ea51d8b34dcd44a8c60bdb699405b755d911c668f3a2abcd0760076241ab44cbc0adc410ae54f6f7b48d917286371d9b575b6e0d079d9a76b5c0dfcb70e0505a8ca908d04be95bf038ea4f2f0ff5985968aa73d314ce8e5f25bd272fd87ddec76ac525caea3e4f8888546e463f75816ff26c116c7e1c680ffe458f270936de855829e828245fb250628e5f999ab8344e2e17343cf386ea278f431ce277b179da7fda5ebedaa22a8917fa93c392388e14f1ed335537b873388301d30d24d7f2d20e4bad55752c58d9e66278205a5018b85a751e7a084c3ba0995fd25bf39d4b3e7686f2b1c995baaef9370c43fa1c75333e22fd5198d4fe600c397894714bb93d25d577eb693bbaa159bf4adb494deb7bd1873a91c31b88f4af57a9033c75d493ad8969d343f73b23643c8a8436f68a85e5e3605cbf1620e80f6aecd3c59a9cb9d404f789297925ede4ed8a356b7fdaee60ebe9c3c3b9d70fcaf0b7a8a222ba9947c9163a3ab6c4772ef9c45b4efff9f44c0ad854484aa7f72ae0484cdf28cf93a609f048d28a7e156246802296d03ca749110b9b4b56c5664247128fb7d10409bad55659f0db380a7625bf1575ae149d16d", .None}, + {.Add, "-b14b264dda7b256ac9ffb0f42b83f66b49d9a84c3d9d54f60e7c76c06e1b3189a41531d214ab0bc983314a94e349411682b2e8886053be54b1d57487f9a00988444b71ac09667be3fc57f52f85e4b34cea11491cdb048f332d7331f326cdcf961ea6ec19c6944eec0ffbea48058d285c928a85d8de7614dc607e96336e0f5c47e33a0bae9764e00b18274209570bf10fa854207ab669c9ca42154b0590ab87a2b0d7ed7cbaa9e8be6b56dcfe98d59ecb0aac3f2468bd14de89dd589807f985cc27f7990ef3148114006e1f807ab4d5209da98f616b42bbb6fd60530d3230bab1bbbea77bbfcf0892b6ae52ccb3fb7aaa27dfb581bd64f27d50a1b24e8ed3839d23239692db24225b7c69816ff75d2897231ecc92ac14a40bcc67a84360dfa730ad963a01314644b5698f401ca590147d5c946d2c7475a75accf2c303463c24cea3487ef6714216713d19711e617d562bdc10e5a5dc38ce82df22c7880ddba37b1506006a93efd1de324ad93d6ae7f0a3524b4babfbadeb2b3c31909b27c1ff54b59b52a74c24bf3f9f7eafac008fbe776ee79f2a19b19bf6f7f23916421c488c2213bbbf2b7a00791122b8c8c0f697acfcfc002e88c1f503b125884ca091e1a0177edd902baa9e25abcaacd1cfebac9d0436a15eff7707ac23576e178e2e935e18868860d2fdd666afd97bb167ad8433fb80aabce921ab3beac4c2e849df28a0", "893c9051a3561662058ab5a3dee378a020351a92579dde22099fd9467170804f7877cdd25ae392a66e93beb384bc4a18b5889eea19c9be514a9dabf281c7ad4754da40767a070a5294d3edbc0bd361fc44f489187ef3320d9d4179668104facaa72e09349105010a436c64a453ce463b97cd0d2daad163faf61303015f2eb18b61798869e03baee149e247960b22df61b47e9ce2963932d646e9fcab92f638c0a8b137d700359a5877b9434aa213e90cf556a89ff39a5b7195de3e48f05f7dd2028c0b73fec5d07101c7f25acb144865733251ef3e7aad354278a027fb6320f1acfd7aa62c39c8630224f24d598392f684538f4b22eef319d46b5d37d45603aaa1030be7c4f7bcfc4c0cec979504d8884d0eb363ed86d2a82cdb2b6680f2b6c7a0d086c9440bef3a85c5fc7aeb6150760682c43ea0da5e75c672fcc5c78a29857df3fcfefcb0a6fe44cc1ddefa2e435585824947a62526b3dcffddf87f408a871a23b293f0b71856c9b56eeb4d4c9beddecfe44d86004048f74dc2dc59b2110f259a18554ac3ea1bbe49c3071a06c36a4c313a470fc8fbd7ae2dc92726ce98e664dd1a45cf4d3c741dae1ae807cf06d20241b072b2a36a06e9638b24511c1d78525e6f02d6bf0ca2feebc79925bc3df81c96a5664b1e05d5490a4c75a752e3715eae400de9b18acaeaaa7835f2d2a15645e658d37d2d5b4168df6ba34d507698", "-280e95fc37250f08c474fb504ca07dcb29a48db9e5ff76d404dc9d79fcaab13a2b9d63ffb9c77923149d8be15e8cf6fdcd2a499e468a00036737c89577d85c40ef7131358f5f7191678407737a115150a51cc0045c115d259031b88ca5c8d4cb7778e2e5358f4de1cc8f85a3b1bee220fabd78ab33a4b0e16a6b93320ee0aabc81c08344b7293129ce44fa734be911adf3d58398203096f3fb2b4e59fdb54ee20826b5a5ba744e65f39d99b3f6c1b5be155596847522b96cf3ff1a4f179a07fa256b8d9af44eb0a2fea62d25afa08cbb2a773d722cc80e81bae7b2e536cd99c00ec12cd59395402fb489607f5a77e7b3a38c26369a75ff637c365516ba7d7ff282208aab162c655f305c94d86258500ed610192ebe8dd1639f8c7cdcdfecf0690cc5b337ed3a557ae3c943a1ba2ec4075611a8edd39b48e5067fc63d7eb1fb49255481f774916f72f84d533f674f12d6568e9c5e3613a7cf0222e98f8e9b18f3fae24dd6a338b98768956a521d9b54b5737b675e75adaae244e3cdbece0fee4590013a520160d523e134eca4e688fb0d22b664e309e8a01f49c46fef1b4dafa5bd36a1795c2cc404f3749de0b92790dafaba4fbbd61e8afcc7c1fd284f75c427c5206e8d54eb9182acdee538aa2f6ea4e79ffbf8b45901d6da4d21a1e6dbafecb9d84852e94c4b9bc52f037b74dae2ddb59a51e96bf44ffa81e55744fc8eb208", .None}, + {.Add, "-51545152fbad19a0c3c2501b9000ad33a064d170b66ba647558f7b8139ef484f83a71ab4e4d46ede10a4e88ce9dbdc5505a786c196e1dd1fd16f175f3596adaf11160ea8bbc2bf5188ea466d325d0e9f236e596532ee5b8a9a69f86795fe02d3b75855c21798d7d5d571573e396658f27cc572ea827cffd4c62e333111ce60ce1c1fd5c967abf34221237ed21452ec9a9f67ae7692bb5ad6111bfbac3bcf351c0aa7f8218284e5a6bb9666819c9780dff39672bf9ac6410817d7394d0d616970e34f38c15b3d37c45a88389ee19a51aa7d1c1c89185ae069cf113cb684b3830d47f461d5d66616ebd7c78fca32e110ae2f8e0ef983f5f1c82811beed7088a5d52198cc4446ba6075f8b980a67347652730daa7dc0f1e11607e40132e01154e5ae6b7cbbdfa95f42ec1bcb9ba62642d7e1b7013b0f47795abff16cd0f5d418c9c279ff7e45e235a45005c30a92b12372ac6c4a360c91e485a64d46384405a16d4640faaee0c9421f1be2fc9b48513bc02790b117c93ac39ad11359f14dec80bd32fc905e1e8f6b75ad3074fa36acf0ecb6001a1790f81f8888fd36ded48b79e10f333db8e6f57286b3bab85b01e075bddeaea85ec0744dde075ba7e7b3f3cd9da2ae895a686b5733c57456020c8b67e544682dd480fc19658c0e789b8adce7081d10c581b02eaa93e1e8ea40f1b47d8577b6b71c2669354bac8e6a4563971b093", "ff3c654c83aeb5c9407bad9b0039323cc03382c8738cd420163355e872acd2212e0769adb2a601e859df381ac33ba05cd85bbf03134f2aa165f49f0efddda44f11f180412514ebcb6cb6c27213c8173634616810061df38a21a833fd09beedf3b952caf3bab0fe36d387831114713109fd85dd90e16693b9dab00a5c14381c341fc7b9a98f1d599ff68eee36630cc94d48697e2e2c07b1efb72700d0a575429c881dbf858d7d4bcf8edbcea9594d856b15c8093a2c23b1080aee85ca6c564fa5feb649acc094bff0713708a28bef6d56ad847df2ef56eaffe119a7bd17de5d4b0b7a1f0329d561923b8f004ffb43c4015f1b14805b75e4791c9104ba538d486008132e315c61fcbd57036aecbd913b84792a76e8d9ca16e41f306bba9ea66f93c20bcf2edf11588c9269c7fa36e04edfc544f3555d13fb352279bfadc6965438d429d731319398fe0111f80e638c8aa32a83663b20b6d33882c4ea673dc00580ba4871f132d70486ac957c194f24325ec3aff9b0fa755f42e9a130a185dd59c6e6a493fb18b3972ed34d85b5061abfa693840c0ada09b247a290ba9bce17c773ec32de497877ea3d3ceb6739ac9b82b5ce84d82a5351ba420f1541b2e3d8f05ecdf82d956b19e74b4979e859a332437928896ab5247014a7a31c5b2ffb23e28884e27a664b27631e7a5f6db79bb6db02948c68de09726a7d9ebd6343cc9172cb", "ade813f988019c287cb95d7f703885091fceb157bd212dd8c0a3da6738bd89d1aa604ef8cdd1930a493a4f8dd95fc407d2b438417c6d4d81948587afc846f6a000db719869522c79e3cc7c04e16b089710f30eaad32f97ff873e3b9573c0eb2001fa7531a3182660fe162bd2db0ad81780c06aa65ee993e51481d72b0269bb6603a7e3e02771665dd56b6f644eb9dcb2a901cfb7994c5719a60b052469a60d807d75c7640af86628d3456827bcb6048b2231967a915d6ffff3174c7d5ef4e6351b6710eb6557882c16aed003aa551bac30686169d6fc0a9612086b06932ada3dc385bd2d536f4aa663c77085c862b3532f8d0586d77ff2b0f47f45cce304a28ae67a61ed15a79c475e49ea464a49d65d484fcf0ccaac0583a0f0588c9d912138db540370e47b645dd0ad0e3fd47c2161a9d4dfa4689c65892362f29e6954c79cac89df4cd3703eb900b5c765387a537863bec2da57988ade1df086e2fd65eeac5638c7032642e294ee65b264ca10765c4aa4e83466c92595d86b918ca7154df3b6db8e192fbcdfd4004636119b4bb0db33826a91ca87b9bf12bd4cae85602962f8ff02bb0920c1d2013fe1898e9426d7e39a523e4c0cdc61995ac337a49c1684a30f97eee464740ef2348838da7bc524e2068d6d14ae7e4ee234d1774d557206b3d6224b483cb9e05bd0c9a8806f02ab1920f71ba2df15c2d5d6beed931fc238", .None}, + {.Add, "e8d597771b690424145bf4afe8e4b28e48250fe8707223e757c7ebe64e41acae6012fcc09aae807e598943ec3feca976aef31e4ba47856e2fd39f766b5a3f6896cccee85fc8790da13ca16ab02ceebbf8ee5046629549defd611c45e1a50efbe2bbeb7bfef6a06eb5b515f10bbd949c1e23b099e517c0a24905d8378a5b1de494bb9d1b1108d465ba623155c7a723388693de1678d7ff6b348391238d057a6eba3f0ab8076fa1e53e2ddd4acd979972b9991cd30609f83cd0600369eb0139a9dfcbcd251f76dd875457542430e48cdadc389f048f44300c85bdc741d8d9d0cde1d01980f16f218aa374e339fdd15f2fa6ebe418ced04819c8ceed826e3058f8b1c922d0b5ee0b449e3eb73e396ac24be183674a4445eb737c095bc92a5d23490312e5e90d776600192c1fb9a1bb8e9ed0f730078a04f2fc3e662ab7f2869289ad106d20fa0ee05598cfe16266925cf50a467014ea8e0a0473890f41cf6bf5488b9c111212a3ea781478e56b4c58bd5892242a538d63ce1618ffc94d3ef9e20d3fcd55853d60f7c827cd7958b655ef098119d83e8fa69e06b5d5f9fea60a696d4ad0604970b844036112d5b7aa23fb2e3df8d742640b69a5c6063065f0489e58fdb8c7fe16fd67100698cfc9be52ecd61a6391cc9cdbf2e5fa342c9b60103c8ed350d0a18bf34a08f1270118ab7334638098353c133ad958e21d17ead1ee4313e", "1398ac65ad7712797a6c4f495de9b77c293b8671f2c14f50a75d03d55b088c455077064e5e8be47e5be7c8aeb8367ba9f8706db1f83dd88fb985776b8a91f8acc9d7ad22abb1de87a2050f2d6170dab8e56e1146e4484efc26d993bdee4cb9acb0075e313b48406e57ae0a110dbf61ddf12d0095bcc03d63628d88c86de132286fec3aead8a1555e5c0540d2f5d47b666951ce6412fbd8dc1cda0336b164e5c0663ec83e747c1d09795c36fc66bcf15808e14684aa24d88299d30050158ee960d1a7716293570c086dc6133600f3ddb4c9f20c803c92590e29b5ecc09467261c2a58dcf356864462e32019cc1db19ee51e8251d5b6c47e1e1b575aeaf19364e5eea3b72593c41ec2b99ad4c31b6ac926c33e3f1d2aab90fd7e3e91f337041beb3b1dcb9a93fef6635849ccb8d055b264f4589d7b9e72671c0da53d0190856cdd0212103fabb0fa6a9a03f38f4ea938ebed5bf5d49f76f3826d32d533c2b0213b88b098e3ecd58cece77aed98b3c1ab4fea6550d2bd1b989483a68467fa81525e69a00a45e06a2805da18749046006ba99c0e9f4b9a2021c30cded075f9500dd7ee14d6c8990aefb6e766519858fddbc37405d4f100c6e190af9efd33c0621ef1919bb7588813c2c5d57613025193d876ae043425d485561d5a9d5f2e441c3fe7e594ba02d3a33c444bd2403ac13c69a207c7768ce8e664aa266ccc10a6303405", "fc6e43dcc8e0169d8ec843f946ce6a0a7160965a63337337ff24efbba94a38f3b08a030ef93a64fcb5710c9af8232520a7638bfd9cb62f72b6bf6ed24035ef3636a49ba8a8396f61b5cf25d8643fc678745315ad0d9cecebfceb581c089da96adbc615f12ab24759b2ff6921c998ab9fd3680a340e3c4787f2eb0c4113931071bba60c9be92e9bba0228562f7046aeeed28fafcba07bcf8f6513156f81bc8cac0a2f73beeb763b5d5c3a0ba940368883a27313b50ac45c4f9fd336eec5a283fece6443b48ac4e47db33b55790f3cab628d7bfcc930d559d6859260de220432fa475a75026d785d0d1a6e4d6bfac791df8d409362a3c8ffbaa8463311d498f4710b35e430f2a4d30c9d8648a6b216ede4db74b3c16f0a48353ed44e85dcd6507b6c4c2a2b6b755664eb0bc852ec0e9c5203cb9df43ec196dff407e880b8ee9577d318e24f4c9effc4270209b5b7cf083c91c2f723485793c9a5c3c950b96f75c44271aa051714346e2f09444d794d80d90ca7f60b935879f613a3193bea1f733266756299b679a48856f00a1bab5f5c41adac2334948a022e6a3e706059f6a4ac9b1adb5fa48f2fecf893ad12fb3d8ea753934917417d7bed10020392c4ec04816d283739f7ea33c63f030f9e36c2a5d8543d50efa244847cfde028e4452008d51aa1c41b92d7dcd35e4251c5786fafda114aca4e1c93fa38483e4abdc5146543", .None}, + {.Add, "a63b8d38eb8abd40155421a33d8b53b6a019ddd68b13699b2a46a57a744e657b2b311d05387e15f939734aec2de5b5b258f587832b218afa0e505b27aaede60691ba4f9b22240fef2a22bd2b2f934a302c2f69e78327c3fa3eec24d671259cb39a90622d2a79068175a725011e0250390a0e39bafb2f18f5011e04aab76f036929d9dc50046dddea605c72ce67baf227bdadb89fbe621b363a6f6916934a175132fdb4f2c37b97efdf4cfcf779560c0bb8d17753877e5e114def59d81a8e94f216f262a32452b719e6d0a89c326251d482af4e171b858f20b5a28be7daa70d520d9d3c55be1851055b85aa945db4560f790ce5299f9fac9c9eebaa611846289188903271618c4ef4aaac64751c85361333b824511bd4b86f54d50af05b83db6a6a63eeedf824ca917bf8822ceae819c0624d3df9058fc49055b70fe6c9d0f607585424741b54c4799a4cb79dedbf7fd6131bb3a94e72b0467b2b8f524b36bf912205ab5e2cb122e6debbcb12473c0975b8c6679a7b4919c7f3296e4df7ed4cae61770ed8ff61afc72e049f55975b889e570d606af2c3662827cd83b0c7474a2d43ce115fd7e20ea2c3d685f741e9cfc313166184ed2e417e1e64a207ad375e7bbce3a8e933ea04f07ac8105381c5e5b2de608637b25f1f6d072ccb847b1184dd00f95db11b0353f13589482476efe6c4f71e6b00166c7a49de25e9a1eea4b632", "6024d02cb28d0b6d3fb1c801a69c770ae9af13bac2920fc0e654df9b42d40225e41c6ba40b6db74b2596552b284dc39b58a02d504b116b763fc9c59e9dba3b314fa1b254eb79e31716efc3659222eec1a4c28832f498161149074fc8e684b942b9b100b25cca47720181b8995b83e69dbe0d7553cc48bd55a71e05cd774fa7884d09afac7c15824fa91f549612679588b7d309c697fe19cadaadff454e2ab3081254f521f07c420e929b1660235646020a9ef6ad632b07768b94c600991023c633acd286478e7cefd91067f1968dedd1da0901f6b501ff54eef21e699c271fe0ca94df8c0639cd963e9fcfdb4cc03e81b5624d227a361a57fb4487a9f9340c682ec45c7edd48acd72a62e94217a7f52cdf79cb185553cc65d6cc0edc138aff5f3af5b3b62bfe8b2a9c016850ccc21f3d5c17ce8808797a9ddbabb245043e3a47f6635520820a1e8c5542a2916dfda60a55864f7351f3002eba7b10defcee18d447655500e1a1ba0be5ac80598825601150254870432bda582bcf565d75eeb53a8ed5f61c64e3f4158e86274db03b53e56ba262521ca58fa332b6b67efe518e8868f3f2dbfac259c656589c78f39fce8cef950ce29fc641bbd35d2b08baf27c32ee344e5eb6127b7f15d90583acf379861b8dd5622996c98c0110140c7466544103e87a96b626e7237d9c09311b38acebdc1fd3ee68f6163896d0dfaea5e74c99", "106605d659e17c8ad5505e9a4e427cac189c8f1914da5795c109b8515b72267a10f4d88a943ebcd445f09a0175633794db195b4d37632f6704e1a20c648a82137e15c01f00d9df30641128090c1b638f1d0f1f21a77bfda0b87f3749f57aa55f6544162df87434df37728dd9a798636d6c81baf0ec777d64aa83c0a782ebeaaf176e38bfc8083603a097bc7647a2287b07580c26656603501151d685be174ca594552aa14b3f7d9fe71e813579cac520dc3706e00eaa96587d9841fd8b39eb8b84a9f35296be13409bfe1108dc8f03fa65cb8500dd0878e75a494aa5176ce2d32d8321be1c4521e9b9a257a6faa7494912e6f324c19d5c6f49a30320b117a34f9b7548ef03ed4fbcbd50f4db7342d2b401331ef69712884d52ba119cc6f0edac9a559a2a4242355bc17f9ea7db7aa38fdbe650c810e093f2e3162c22bce0f304f4eb779949d5ee305ef8f5a2f5bbd25e068a2031ca065b07535a6a0314824d865696b005f0e52dcf2c4684b6bcf61698708ebb00abe74f4201ef8c4ab6ddc01e8f04d04f56445a3dcbc8ac6a34796dc83c2afc2bd0f68f5cb5a843a2fc598d8b5acc2043bd2a468691a2f227035899e5002ab6e678cf48339f1c1cd106829daaeab17f747e9fc806f90a115d72eb95f38f9ee5b99dbf5e8f9083cdf90ef77d91e04e1d847d12a3b14b3255155922893b0d33e3eee7f62908274f6c950948c02cb", .None}, + {.Add, "-f83fe53c8ce1b7357e24f40b6c650ba1375ea8518385b48c30cb9d80ad3937540a3ef82ed754f8d93da2fcd7dfdcac3d59f44a123aaadbc36870db093970f09e843a867050d3e33beba829a38b5348b69f010df9e97d5c6b5bbe6042291570e3c992acd16db46d73e4972cfa352e7d9cfe2fd4c83b8758d0ae92ed3d3d646953b4841d341bc1d8b010adbc4e6ba9f67a97cb196660b574d2c4e37155da7a6ae19925d332cc3bbd2e67cd051bdc230c2c712f8e9067301e569a6c06ed81a454fde33a1011aec03a640599f75dbea26a099c2561cc4a27359b0c805b48d3b095fc86b9ef7b0526b293e0106932dab3d6afc2d58d7522e98afcdfc6c4bbec3b8d8a6440fb3ccc01c0fb3077b702236b35efc2ceefb53d56df5b1e5f32b7b846fbdbe9a647462c1a473b4c84cba12c352b39b7750e0f48cee4d9b62b496fed8d7c7327e7262bf136dfcee03eb1903dee6e4a73c6b701d76f54713b57c846f40e6f67393168c275892840e76040e3106b363ac86dcd4e5cfafd753ca91c3361795d46f033d11c0d705f59ead98b1715c7336d97dc85dc2d70fd89c4ad6b2837403930c5fece134afb2d6cfa0f21ec9188e1eaeda6a894a8c63cb45667ad66091d80541d6e7d1270036d98cb7bb15adbc3a4ccd229119d60acab6c308dd7d5e91dad9aee51518e9e18590336133f7978d9233de8b5803be892cfe31e6f19f525b562ab", "56cf4ca78965203a613142bead28ad3127e9159c5eef5cb87ea6b25680404377c80dda9dd4da3e06f92923aef2c1f14b0221d7f56381734d29e614fe7a666673d81c08c8791d7b6486795a164faceeaf865c104f9867ba48844082d8b0aadbedf24bc484081c57a43033832d484cf80944a4540de49c76013beba51069672d18f280c34e00a036a33f35a378954ba38aab948c4f2c05e42cb7a2b426074ace53d4876a02c8328c9dd62da2e19ff2442ae8b3d2907bd767941f423637b8ee1d61d1bb1ba206533ef206a0c4c361f86e9c8b2fecbe25d531b7a26328ca61de9704c98d70edf21946cf190c6746972eed29d8ea7c169da6b96a471e633fe819bb84f15281836c6ea39556c2fc5c305d12a4ef0bf2c757290f6a94a4da333b26b32acb063ecb375c835007cc71cfab8b497fe21f41faa49016553a4e0c7ae90b7e5bb7852a81a1d29b3eefd9edb975229a89b3eb01ad8a901f9b7bde0b1cd66b1ccb41bef91ca1b442d063d28295dca1afa7d21e555751ffeff4d76b59f9e3167a3f78ae3359bf78e489ac3d986173d1aff1ce24da6a09dc58b8f9f1870857bf6f0e885c1daa24f0fd5b05d13499e095e52fe1d358d0671ebe6f7a2b2cbc247403d2149a44a84b9c91f0e045501e24b8de2480d6c0dd0c322b8700da582ef6bff5d5466a8f116ad9d1beda1feb4d60d994c51378ebe3433a7109e7eb2241232e33ee", "-a1709895037c96fb1cf3b14cbf3c5e700f7592b5249657d3b224eb2a2cf8f3dc42311d91027abad24479d928ed1abaf257d2721cd72968763e8ac60abf0a8a2aac1e7da7d7b667d7652ecf8d3ba65a0718a4fdaa5115a222d77ddd69786a94f5d746e84d659815cfb463a9ccece18593b98b80ba56eae2cf72a7482cd3fd3c3ac20359e61b21a20cd17818d5d65e52efec368d1734af90a60d40bd2fd32f9c8dc49e693004093090919f623a3c30c801887bbbffeb58b6c27b29d0b5c8b6379c117ef46fa86cfb71fef9329a5ca9fb6d10f5750e245203e36a1d327e71d1fef7bd2c7e8d130d6bc4c70401ec4384e985e9eb115e8542d19298a8617c0421d20572ee79b95f931d65d9b4baa5f30e234ad3c2fcede62dcff089ba58847d2048b11ea0087af4bdc3eb44b859d180a9e1b9d555cc14a43ece847bdd3cf50481fe177061fbaa4f64448ff064c3d6c8cbd3c0bfdbb5544cdf34d5bf79bd2a1da3529bf7726fa5d3d4e570838dbe4d33c98692f64f77f70afb0d80653dc2397e62e30777859dc24df77ad03e9bf2b5a1f5837bc9b7ab722394a4d0cabbe41fdf80ca223da2b069260a3011f43ded52b0f2fcbb0bd34fc441a77e44dc3c80a9e4a97c8208d4386a2466dba7eb36613cb70ac6a8515250c0547a7fe52fb37fa6f25db7c5a7e6c27d333e87445bf3542c17ff8e78d53c9458a5585ed93683f7b402872ebd", .None}, + {.Add, "3fbe5e45fd57ada761a11b8927f8a7c780449caca0c5bfb425be0a1e610479adc7d22007599bdc2748bbbae951c716ebf678a44f1bda88fdeaeaa53641e8221a5c346147e0cad7b39096daa7de1ebcf2ca3c6eb42cf139ff8ee32e00669f93a81a2dee069ddd58af92675b77f1601fb4042cb9c4422210a8e8bf6755940ec3c94b2ea19025a7103e042b63da5f043efba442566b3e480e231ad2b343b0bbd40fd86df209644fd0c4d4c1dfa94197e00bf6bfe7c1aca820e0de9d9ad58b4e333c2421fc1f0bdc2c9a638a9505a11b6dbeca29437cf321350c1eaba9c6fa08fd81c3f62495411c943284608ebe1b0076b7148b470f88c203a2fd0f7d41deab7efd467bd68942072c32593af17c7c1a94518cddb6c28d3fbbeb69abb0d2ef7c367265feebe59c73c56a608369c0c0289a63c4231d9297f5b7fde0e686323ef6618b6d954e7a3e7efbcd11e4b4d3572725c757ce285e06937dbe80d517d4a3d301908258e59bc51885777f7dd261305dbd7954d230ca657dfaeaf5cd84a7126cf2bfa440e181c7f3800b97315e69f5fe9307a8ab0741bfb90150da7e2a1b378a4e27a3f61218ae7cc3b2c3128d22b74a43073a2cc40622fbe347decd8683b1327d1d89f04ebce224e828df7664314485758ee8055b31881bda9a5584c1059c4024e13bfe6219cc467dc4a00b4b9c1a3dbadf38769403fcf9f4d1a1a01b85e36cee2c", "427090e47c12c1d1cad1ede5c2c7814a0203e51d6be5ab44b9ca0dbb9c590ce42d64a06591b8629325f63aaa583cf0a6a64f7558380fd7ce64ed1ee6fd7f2633a634ed866e2919a58b0bbf68a696cb98ec19514ad7cd7d9ed617c5e48ced0c28c3d21e631640b158b62e8b0a804ff0b76b0bdb1e1547177cba4058d387452b0a56ca719cb6e3ca535b18b7d087ef0f9b74b1a90d82b86c13f59dc28ba3f4219502ad28dddd37c203310459a36740d267d4f31c2e74f45523fa3d8c6579c198824a57e66228eda6630809932be201fefb148dedf323ed7bb13802105ae3dd2cc2368873bf9072e811384006b272fbc34574d6c0907388679bf6d2a802ded42e621702ae4daaac701047823b18e516a1b70f33fad7fece2c508cd8dd6ef7a8ff1677d31aa3f23294e4c9c3d1d1b3bfc164801306c1b6553f65d35c6b8aded630b3dcbef09e5bba550b0dc75b968a83fa187b40e41de926d55423d558632492f1fc0c03b3d92c3660742ce7b4dc2dc4b905f433f2bb5a21746a414cafc7c7219354de3a2b08cafa7eebb364c908d7d20417b3a46a56ec8b8843ff3a1991a38977256c5c8dd7bfb2ef3c37b9b502ea0284090b65f8500adf528c6bc522a7336a2881ae3fe264c548e4f7fa57a70b1bd02cca8080a81622f72dd30b3ebfc58badce5b71f567d74a35bada983ef8fac8f359e702fce8853aced8e02c85eba23983aeb5", "822eef2a796a6f792c73096eeac02911824881ca0cab6af8df8817d9fd5d8691f536c06ceb543eba6eb1f593aa0407929cc819a753ea60cc4fd7c41d3f67484e02694ece4ef3f1591ba29a1084b5888bb655bfff04beb79e64faf3e4f38c9fd0de000c69b41e0a084895e68271b0106b6f3894e257692825a2ffc0291b53eed3a1f9132cdc8ada915f441baae6f34e9718f3ff78c1007a37107075cf54aff5a4db1b1ae7418792c805c6394ca8d8b273cbb303f0219c7604d8db273b050fcbbe6e79e28134c9d2fd6b942831831d6cb9deb73170170eb0bd56adba21dde62a43fa7e9854d18f7c43bca095708dfc39fc8962079ffc4a6b3ef3e22544bd7fad5f5d7e84d6ecb39c42a0bd2c95613136089c11b19a8c0de83bf6848e41e7253588ddd206898ea65a4f2a473b9273e85bc8443624544e4af763b442f1bd1dcc923f4a543f189a3950d81fac1069e1ab1fdfd30f0c7befba5312a4aa7037c865f38c8e5c9974f14ee5ebac65873d5e22767f49062385bf9f6f55371a346ed98e8614827b0c8a92edfef74a962772cdd0971f5c4f7198ac448994d9b843acdb13c54d10529ff06e2fb2eefacc4225a14cc7104592bc562ddb35d44a92a92ae49ca59f38303121a76dcd20d9ce0b3c6055a25968860347ab13086d60c380cb27edf33cadf3c9f1167c389f384a4496e33114c63b737c8937c8cdb1ce2607281cf09ce1", .None}, + {.Add, "-56d36005cd2d3326787f369291edd60680f4c78572e2508cc4dcd5aa210dadd5ee823d3cf97e3a4198aa06d996fd569f2295ff3ddecfc63bf2c6927209005752aa5a26a544e1a140170a6ff7e88a43a4869d059f377d4c99dc48b286b1f35d7741b4941cea5b6d95784e9afa53bca43f55abcb38bd0f44509d2ea6d4cb25588c528407f5c36c04e18acdee0e19b3eee01f460697f02cac385cd1cf5f2066a5c2a45353a984ab15e09a2435195a03b3993943132ff8210538a637e1e342b6260d079988c34748a474eb1b018c2678616f9463945795c2b17594ccf3b3ad9a16b3897d0f51f4295d0b730b51a6d3bcb1bc849d2e0bd63d4404ca8704105655b63520ad23fee4e13014dfe15361578d0e4563ed90770fd7c6dd6596b3a6acf4ff37e00827b361fd86dd9c3d4eb25e7777e9a4e6606809bbd47bafe11e8fd731686221813dd9d4ff679b7c9bd9d8844dd5c0f7f73e602e0080253bc6777ba6ef273c1d7a314d5bcd176220f266451812dcaabe870a4f938bcfdd6bea568b24b6df70d34651747714cf435f2cb99ad2a5d968ea537086746eda5301af780d314fd9515860e2f186da1db5e655b52dda2d0c0fad645e125e7888779a21f10d0a1f7cd03bf08ccde404ddba751557741902e7671e38bc5de32d4cf4f150f0c6d20fa945213640bdd1a8581325ce78e3e86aa2c94b211aa642242ef559827671785d0708", "fbdda3b305430ba9884cf82b4a815d490e3777064613e4be63a0a4bc954fc691a4fb3c2a96d49a75b1efc84aac15ee760bcb2be5e4048895f9bb44544d8cdfe791330d797d630100f429667ee04e5a496daeb423fc74a677e8fbe23a162657de821856bfb0b1e823c820c0ee619b15c37bd43ca0574270c73bae512f8fd217e94e7fd630da169cc7e6cd338a875b586db8be2ab8c97612fe296c01a88c334a33483a1b51d20a0c124de561e932cbf28617c17aabee747914921fc1c9af518cf6d36a92e4bbd25d2321bb9ba30c4a42303c923e8cde09aaf716dffbfe9319e50873352805010f89023d2a23fe59dfb3b8a40b312ce33b5b6530771eba88df561d07e5fa3098ac913ca3439b61857da7021010dde731c212f4b9b5ddb0cb23a437bf63f46b0403b1ba8428d253f5a1309555e47cd7047fc338f0a3486bd5b7a9ed0449572ed1637756448dfc9746ae32af3daaa37df7f01732e7c81a6d45ff1b0d7c419d1b58fa0e7383cd6b354919ae571aa3afffb882eca673e63b0216372a1d40504930393867db93a2751f5ad77272bc63a4dde8a87d76f4d530d8f8c00cf58e04b46dc55adfa70288170b53afe4ff397aaba43270159bf7e7ea253259e2d8bfe3270e4df44eccd18b94d2dec3ea70cf1d1d838aee2fdb0c430d28e6a350577f2664a91eb7951e2cec3f11ebb2ea50b5f1bc8f18d3cee21021f6c5b48794c3", "a50a43ad3815d8830fcdc198b89387428d42af80d33194319ec3cf12744218bbb678feed9d5660341945c171151897d6e9352ca80534c25a06f4b1e2448c8894e6d8e6d438815fc0dd1ef686f7c416a4e711ae84c4f759de0cb32fb36432fa674063c2a2c6567a8e4fd225f40dde7184262871679a332c769e7faa5ac4acbf5cfbfbce3b16aa97e65bff457c6da7698d99782420d94966c5cc9a32496bcca470a3e6c7a84d5ef631b3c12ccfd8c83eecde7e677bf65373dbebe7dfe66c9b66e9cbd10a217489b8ae36a09a16e5d1e0c0a82eaa354846f9818213084ae57fce54e9b818b30ce62bf6ca1ed257862301fc1f6e03210cfe176065f01aaa32899fe7e738d631b3cb6127c36248002df098bcac234d7021ea4c17541f2a0a1e2ea4ffdf5bccb7a2062adce7eb83a19729b8abb0fe1c6efac3eebd40c229dbfe86418ae2c81954fc640fbac7f222bec2605cee45b3651dc9ef970dac01a2f19f0ff3d15ec76bcdfd2cf71162db04f03106d1ac5c1ca5b024f71cc907fbe476f1804aac6d09f7bbc22398983475bb8488319909d21034577439a323f325b8cbc77033a435a3d17c3e80c1f11c3261dd7982d8ef8c164d91d3f78d245dc5f918283a660883f29a4069ef71125c763d5ec5c10309b0e46125a7c0e2e61af21c621493a7125df023eb4d0f3d0b071dc62e034847876ad0a1e8d6af9fecb69f80543c2a8dbb", .None}, + {.Add, "-9ba83e16d702ee2bc47258247a8e0634de3245c34823b8dc0d7d1f6796f1b75cf350122e6845c32c571107e11a2e7d45db14ab33d34337af7c1ee8c49998d2565757188532a86cddeab036d6fb1b07ee7f4c2c2adefab2dbdeedc0e696773a218bbef41334183d50c27ca669fd185e1ffe5353631c2e5f466757a061505557d8d0c5ed1f23826192d2fd5cdb802476abf4e3f7e4cd6ec3c5e7d2bdfadec50c722d2be1973a26a35a70e95696c7b90455fbcfd6e439f56f82022add0ba5159bc854614fd45e59a06facc0167c5eb880986ccf797cce47710e8cda6b2006a2009c1e079df77d03434fee9f797f8e534afaad522b991f0b01a7c2326fd4f98b1ef253edfd1129086e4ba37f95ed0ded2cec65df094404012284e1fb2fb4d5d9b8937a039ecddcac114a7e97a68702f29362440fcad2e564683ebd5af67ce36b1b081880ff460d50373356fcc43e67a973cd129668d109f34322afa1435698934c3c7835a2d24ab934c50e71fb3f74157ce0748db93dcc6c9c4809293dea6b87b3087a6503f4e7b58659473235bc15f6aa039306e254668acda064d7528562c268a390d529a3c3d6cac118f35e8a101ffa0bd8a38da35ea376e0a8208da83f659a8a240edab9bf06611963fd001e5ceb4174f0f9c051eede3352c2798e458e32fd7eb56e7d50071befb891815f0adc1e8a48c95fdd2c19fa556720410eefd58b314e", "2fe1c742d2076efcc051e6c8f4689d4c21306f2fee00c446d9cb1a18d2d435c21b0725c47404a3560dec419148ded5550c0230401a861d86892856615a47b65a57b91f9ded6eba8a14ad9732b333870960f631229904801e450d1cf67b5984afbaf50be34b820bd49ae3cbb78db9911d1659522cdf8951a5b86433904f0e6994cf36275d95449f00765f94eef9809a0d5305bf2cf2eac3d4e3006c1f90be7b0f49b1a69aac6c26be8814898bb163edfc7d4a9b762ec388c0e81c10113ab2a4b6e9f9cd0b8c42b1cb09ca8ddd82fbfcdb61c93b37f903dfcbb024357ea7056b6d406afb1cbe40599cda9b5140fe00fda2d7a302d727c63ab23fc63badca52d4111c8aec60b3224142e7257700dfd24481499d6d93d9fa36c1ac84391f059aee7d6d06bbcabee9daaad54e1e1ac283e327adbaea1fbb70ff6391580be7a5509bd455e367ae6e952171edcdc2c4fdd1c8b2fd6935ee1393a94e775711d4525cb2702612e2a5b1b707e8389e48f80d2f61e2d7e95ba6d7c2d5c91e7d113b81c9e0c86e72f845ce6a8413c35f6ecc8389e27d193255aa6ddd9232669c1d7b5590e32dd0fd25119f0a2969a4b4b630f1da9ed0becc62cd4a1b7e668dffb674291dfd5fce8fd0764d1a2db3e8dba68caa5afa8738cb117dfa6d2345cdd23c6857fa10899be95976ce82e6702346114f144e3ba66d27bb5e2560aab5831386caea4a6e88", "-6bc676d404fb7f2f0420715b862568e8bd01d6935a22f49533b2054ec41d819ad848ec69f4411fd64924c64fd14fa7f0cf127af3b8bd1a28f2f692633f511bfbff9df8e74539b253d6029fa447e780e51e55fb0845f632bd99e0a3f01b1db571d0c9e82fe896317c2798dab26f5ecd02e7fa01363ca50da0aef36cd10146ee44018fc5c18e3dc2925c9dc7ec86a3dc9ea1de38b7da83fff104d251db4e069162e37a3afc8dba7c9be8d4cd0b165516597e853b6e0b31e6c11a0eccfa6a62f7116a6782c8d216eea4a2f5889edbbc83bd0b063e44d5439142dcb635a15f9c952edd9ca2dabec2e9b31404283e90524d57d5af28c1f744c6f5826c34272f384ae1376310b075e62d08bc5a1eec2e1ae86b1c419bb02a06ebc33576f695d03eca160cfce3031dc2369fa949886c406eb03a9654e0b329f368db2c02ea953e1a7f33c29d97979ebb15c1692f017969d7ab1a152d32e2f65f99d4384a3182463699cc5222c02c99022cdcd5d3b24766e61afd9ca45d96f4a9c67eeaac2caee9bdd2400bf20baf194b024583d2c6ef926cc78679d48ca9f8ad3b6dfe3b350a0d318575bfd8049224cca157743ea8591e455b3b19d72ad61487f87a1a20d73416479d2a557f0a4371ec33657b215991b29046edb82eaed3f471100cf4a751dd3638ecf5198523d9389909486e3b4dbbc7d04ea25c3821cdf499aab19d2d8824eb40c2c6", .None}, + {.Add, "-ba8583674a58c30df3fbaa07ba911c2a75abd917912bbd9b8c601452e5458f8f38b801224e458f89d9fd52c8a73fddc75aebcefa40a42f17a1e6d5e4a290e8892237e1b8ada17fee362cf5e2acf2c49b176caf59054fa93f2a987259f13368e0207dbeb8b2496ce5e8b74b70e48740ae74896e95bbf801361c1a3969d18869ac9b39b8964f694c385ae2ee9c218232ee3fa68e51e63d14398e28db5cb874c097374359acf56c5bed74af69572b9aafa6358c740f53aea389a299e713f331cac033d158044019cd52b93b1c47357a9426f1f851a7f618e9ee4a9fea05c589d085e904c9614fabc608ab1298ca0e8d8c892dbf9088c76e21a2c89d68a316bff8b7227c44eb027a515f9f602069bea01249b6b0fef96ba719533df7e03efb6e034a0cc6249c6eeac1f14d15a59ab668d015f109bc7fa35178940ec7df0da100efe42b44c8f5d46bafbfa1dd5f68f876fffc37af2d6f6afe49c46f479279d30013a9f151c27ca8614f72138e20b6004f32262ac5cf49294c4a83ca6f9fe06d2db67d09f97f3fd38149217dae8e9509e19a26caff2b997488d01fae2f61c7643d7c19baad8a3882e1ab4154f4e5a78cb3031348b1309d1216ee3d390ef4278bbd4bbfb5ab1c7416cee6cbd6f616cecfe26e5c171a46815e83fa384a2278efd66dd0b09be9d93fdf66eae06c82ff4f4a2bf159b6033bfc01bdca6190eae96e92f4ba09", "be888cb0777c972d8f783c11479c18b00db5681441579140309c7740f3fbb5962634174d40fbfd7190f0ada45c1730c55a70bf923bff380e6c22513388313bc08fa38e714c03f112c6dcdb6f99ef45679314d118ed4aefac8f144e27a56315a77950a5024c3358c0e54ba2e2729d6760a140ace3a4c1e89185fa042904bf02897f1c31891fb76ce0a62c19c859a9aafc49aa8d12bb7e762c48f4d79dc0a2d316929e0d6066aca70e1cd9f29f083004445c9eb086d3804f490ab78e1939ead7bd275ea091a4f42e7b8b0d7cab1d58d127ea25658054ffc4ad6b4c5f82ba70abc521cf38e83f7315f92badbeb9caa368a498166eabc4d5efbfcaded35db2b7a381ab19c9b46b12ec970ee8874fd49a310934fbb63547186ef52ca01955782fa512e05e04c365842374c3ba4907de38043f8639b2343fc124de75084c07d3262411ae85774b4c42ade3650f5c149076cb0a39242af5770fd72a5af28ceabe4e95b64349dacd752067267c96a1ddd580fc67ed63319992600bf5e91c49b749312756fc9f5552fb70447831ed4c42a4aabb721f507de46dbed863e4f7adaa6e89f189c03a03693afaf6c417ee7c05738ceae86a8a13a5917e18b3cad83856820e23cb5af6aa0c0a6b561e8933d7345d37006e443d4d808c145e3e40a9551e8af068c4a95f9e9b1f711495af5c7c26e85ca3f2432065c87a5da98e017dbf67d4f73381", "40309492d23d41f9b7c92098d0afc8598098efcb02bd3a4a43c62ee0eb62606ed7c162af2b66de7b6f35adbb4d752fdff84f097fb5b08f6ca3b7b4ee5a053376d6bacb89e62712490afe58cecfc80cc7ba821bfe7fb466d647bdbcdb42facc758d2e64999e9ebdafc9457718e1626b22cb73e4de8c9e75b69dfcabf333698dce3e278f2d04e20a84b492b2c3827780e0a03fec0d54161f2bacbfc41082e127f5b5ab3b371404b20a82a8947dc95549e27123c777fd1abbf681da70546b90cfcf38d488d64da6128d1d26063e7de3d00f82d13d85ee6dabf20ac757cf4e6db3f38ca6f86efc74ff0809b25efbc15dc1b6a56de22fd67ce1d02416aba9bf7aaca889d84c968989b376f8866e615fa1ebf7e4ab73bdb7155a1eea839167cc1a1c8d397e026f699618376a4a36d27cf3429952ff5b49c6fac4a66406cfa3225342d8340ae5577d6fe23c331fcab97ffcb0e0174fd860c118d65ebaafa70eb4e820c51f81850ccbf17b469088127d531ca41c29d62506913c1721eaca9d6dc0370d9f2a5d61327eefb56b43ebdad9ac9214b5451524af936084436c84be30a4c7570058c7930b8194b82c2f9965de6d9e7d521d8e3087f672a7691c9442ef650d80ba54b8d97f39c6f52b23dc0658d5492122d2306ff2d906405f686dc2eb48298140d75c55b400a29b542d97cd79e30b2988d1d29cc789fdf2c7092d5f942027978", .None}, + {.Add, "33ac648921982edf0d02e383878eb5c12cc8b6e81e91d26945a90c6c0cd78af949c356180cf469eeb956d637b8ffaab588f5e144456b5ba1b2de1c038434a462768d1b506790cf558cd76a99ae1fa065420bb2ac4f97f4ad0dfdce29f69b0a7b23062c92d339a396d57b6253d07c3688c494391173eef0cbaf65ed79da5bb027625802299a077d770ccf8d916c86390613ba73aacedfa7bd43c72bfa5dc119735ab525ee81c4f08ef58e02f87d6d5ee817c88c593a02aec5c1ca80a9c7c632430900597ed45cbcd2bfad5c42a2e232cc38a6126b97b7ca9f96b1be1001c710edb85353a81f7dcc446f6559128d40e08b8ebca8700ba3e0438f1c1e80cdd0356853c41840e03c745b6b6bece4b8660348dc0a3838c6afd4b38ca321dcc704868191a65f2df5d491004ead9cf9e89c4e45211bccb8eb8c0dead3979d850a0a47970b633e5b0cc05e7f6a8699bb9e99ff047e9fa3e562b2846924a980f1ada7a21f0c6a720b7dcbb5f6d010c6e8d135c5a16d05d560c493dee520c90bee0787c884abc592909b2ac67b585680b3e46f8630d0b6d514b88fa6f407f49e62ae469087ddf048273bc7b8688864445b2edd9ee63010ebc527b5627b91f858155084a237fab086fbcdaac0323bb87e914e428883967c753f8f95098fa85ebd538510b94ef49dd5635fde3e002cfb2834b8512fd873ff063d1f7593165ae15fbea0e0ce16", "e413cac52a5760f7c94f3d4eb432959d6132ef8709f3d15c420138accc704241cfc83195ce04eb05553ca771fb9a615e4f6ef6e7c1f9279878cf76ccee62aa8f85116ba5b0956ebf550716b1ea6138d87cf6ec50ad1e161b18a243f2a3959a7e8fbc8622b187d42ab74fc4c524818196fa4c95f86ca383cadee7668773ade4d89eb88a3b5c94d06731f5f793d673ff6e829527c0ab3ec188a7708eea77e1ca14ff4bc59dc24ac97880479a7f847f4618ad6c483421f0381a5b51c8b7f3fa81bb7ec92584a54057cb84c0a928c1f663dc5b4b6ec8de589719aa9378b8e10eaeafd01cd63a0e529e2f1403a1511756578a7ec14a73944738745413e6b8522ac6a2dfc3a633775e5220e2a239f241e8ab8eecaa8ce9224f50e0c2c937ce0303faa47723ac6fa1474de86df20bf110c1d88abe8bef9a91eef82310e18d72da45cd809aad1046ab6546d70cb0ab4f047079317d1ae59de75773666655367a8bfada1078a7548948d30882884eb959be29a8a4fac795e2633001158a4c7d8ecbccee44c50df2ae5cac8f3c51b71f0fa0a9902a41f040e800d33a226cbbfda559fc69125d7aad706875ed739b190c74d7abe87a126d980998780fe53230e920e2a2190b499166a2f7febccf3c045e27f3755e06ac0f74be93ce709ccf1f16c8155fd3455b9a25c66e9a8739bfe8eeb7dec749933add312913a897198faca06e48d5867b", "117c02f4e4bef8fd6d65220d23bc14b5e8dfba66f2885a3c587aa4518d947cd3b198b87addaf954f40e937da9b49a0c13d864d82c0764833a2bad92d072974ef1fb9e86f618263e14e1de814b9880d93dbf029efcfcb60ac826a0121c9a30a4f9b2c2b2b584c177c18ccb2718f4fdb81fbee0cf09e09274968e4d54014e09950001108c64f69c4dde3ec5852542fa3874964f9b6b7a1e6945eb37bae4d5a2e3885a00eb8c440fba0775d59d7801eca500c534d48d5bf2e6e01d1c4961bbc0b3fe87c97f03799d149e446e056b64d896a893f18134761061b9414536c8e2d5bf9d887029e22dd06a738368fa63a49738160d7df2e39feb18b7e33005391ffafc0b3387be74579ac67c4e0e26d6fa4eaed7c8b4c521e8ff25944f6c59aaca08812608ca0b9d971bdee8bc9fa8eaf95e26cfdfa7bc537d7b060de4792af7e4501517a6104ea1b825a5567737450aa30a7835fbba89834a09f7cf8afeb76c39a27c2f8511c694c69ebe79585f80428f5f6e4667cd6b4327c3dffaab15897cd354b6c970d3853ef7d755b7aa0d9fc38519165b12a715fcb962e11674b09c080842f99a3b6af597a43da5dc237d50d006898760427e83cec02d7260c42941363326bb434441ed9ec5a97d0177bcdcb941b7e68a428be9fe23637a2c777dd41b9a708c945037fb29ce78c539ece416ec9718796baedc3766331e2a2fea8e002ce9b65491", .None}, + {.Add, "7dedaaf11cb19c8c38458ece70f2f5964d94ab6565db0ff0c813a5869e7300443751db664fbdce2f2c7acf70cb61d4c888455e71b4403cd880911dd9a4dcac4bcd1593857cef1548176255899be597952a898073be35f548ecb21d0525e5395610379b6791562b1c4d01e52240b6261421a9cf9c49821a9a2aca65c1f50c653d88877a0977d7d5ee6c5f4d46c48203724ec62753c7aadb598e50c1106fe818d2cd8c56b506215b5013945040aadcc0e11cec0cdd25d00dbe19913d1ebdd7f4143962fdd17c8762ac365c3231f44decf942c55981f28cc5b9ca5cca4653b74b192f8952b651fba2dbd3eeaf113ff4ed113adf8f0382370fe2feb2785c4a570e7d1698b58513de59112cb58ce27cb697cf238a797188b82b8a7572319496b82839bc3a13229cbc9708a8f1768107a69a3442e83da5c6f5054b68639b077a456fdf309c5f1ceb6d827d539dd857a28ddfdd1c2e6019eb8e1978796fa73cb90bb1f3909aa79a1c708d711c020456f1c13b1c3a8a21f0a7cdfdf47eaed3dc9fc6fad6083ba68f1e2888ec8139df47dbc4dc8f8d231144334244f4c77bf7c54706e692d2c90190bcd16bfc71b44482a76321f6616c2269bf8502377829cd774eff6b84964ad0b12dffce5804d2500df9fcf84dd43e1ff2145fb5ab4664e843c9d93217414d287b28e345a12b7aa5a24e5066c182893f23a9320aedff4194510043093b", "34180b1e34ea7fcaa531aa4796517866b916c125749a4812a33772a7dc9e8848e0b9042d0a6db1e31ea086ed381fdbedd52dd3aa50e72046cbe5a41f87a121e2505439790fcc4494fe7fd4582249c76c1793fb8d1bc2d8ad5871eda3195450e47de13f23b4b7aae6636805bafb7445e5d3be286def8d7789a15015d66e395435d99b4bf8bb8d68d470f4f96c5434c974d898b8633c4a0237e503cab305f991ad970ad1d6427613af1f9ff3b71c45dedf81a221e4d92c1859d3d29ad247d1d0902a265b1e62f99551b285a52bbef11cc95c27e3d3f041a7c4c1183693785347b6e76dccb715f14b7f0ac6f52010e0e8d77e0a6d85ddd234867601429f251c9cfcf00c02fd142c959a9fd9520363f39ebd2b5a9c0033f312b58579714ba29ac2f486e51642b0253255eb4e7632f8f3548246c01ac3e524c451e2c90b37477ccca4ae1d8a45baf744ca142cde6d14b87819e0dc0199ad87154f51e33f71725edcb39a8d72d01412109778fb09ed334dbfe719071537167c5073cebcdc39f9ac2cedf5a61bfb149873f4401a07a1f956acb3a434610dc8d87a78732fb3cdb80d0ddbc63937a176b5770eeac558283f028617a2e735c5ef0a0589db2cc484da6bebd70d836f06cabdf25adfa9c84ce89a52e20e47743987366bed6f9a9bba64c593b7ed2f675df6e7cb2b173ed09176ede9b92d05cce3c752568b662ebe4c5ad479db", "b205b60f519c1c56dd77391607446dfd06ab6c8ada7558036b4b182e7b11888d180adf935a2b80124b1b565e0381b0b65d73321c05275d1f4c76c1f92c7dce2e1d69ccfe8cbb59dd15e229e1be2f5f01421d7c00d9f8cdf645240aa83f398a3a8e18da8b460dd602b069eadd3c2a6bf9f567f80a390f9223cc1a7b986345b9736222c60233653ec2dd5446b318b6cce7275edfb703f4dd9173548bc375e1aa806497288b48976eff333443f7c7229fc09e8e2ec1fefc2617ed63d7f105a9c4a4638958efdf80f7fde8e1d75db33f09c29eed3d55e2ce6d7e8b7500d9cc0a92d016f71f6d67ecee5adeb5a43150d5d5e8b8e9fc896009446974b3bafb6f73ab7a06a4b882280aeeabcc8edee5e0aa368c4ee51571bcab3e3ffaeba2e03952eb2e431f29654ce1c95e943fecb40099eeb689a85869ac19c99d4b2ca63ec1c23c83deb9e962a664c74767cab6c4b74657f6fd0a61b399152ec7cb52e6ae2b6a8ea72b281a6a30829e0894fd0e44250efb0353913727be4a4e684d6bb016997327c3fde1c28a32c0fce0c153e6e9d51b894331577251fc1abf6d3aabab92ff13f46e990239323386e30b5c799caae665a80e0453582fae8f07c1535691fc296b575ba3ce3fb7f8bdc0b2e47c185ae2974b2fe285942b9b962198b5ff83fe2e9ec5cf2e7c8fd91fcb10cc42b97633c53e507aaf8f0c07708461796570529d5b178316", .None}, + {.Add, "-7e9f45972a5149ebf27e57f40c89cadb18f62cafe23fc9068ed06ec86ca7f556542f0d4247d285541fa22fca38162d6a58279c361e308ed590b36bc652581edde7734990d99484687f81b058ae63343898015f40d6dc8c41864914245ee18c9bc3661200b01a9545c5b31deb2673da1a084d2d8b221eea07843608a31f4daf3f60b7dd0dc3bfb761ab152ea4b0d071aba737d7b63019618afcf218706ae600abe0279cbcebde9a4c2d354cdaa9b5a765614b16d8048036a608a520267392dfa22472ddcda0c3ef9b256724f5d751bbd58398d28ae8035771e79361999ee2e944bb630ede5c1509c5b475825321ffdfe6a376a9eb9dd259bbcc2cabef063e31289a54ab235bd37a9950bf665d4874cc9e8cdd9db10ffb50476c8f170278cd6f1a98577f41221382227fdfd6232bccfd4c4d5a167ace26794a32823fe07146cf85e63edc338f31338e5f141d084b1b4a3eef0b64a9d368667bab12f54e765e0a397389442389beb1784daee0409150b524d2913556c31bc5d83b356db3fbfad3958b3f7196b77df18771683ba5f100e721a6a4e83484d80b53d81274b096a7bec581a72df9da6cffa71fb533fda3b020e6c9e876a6a5a65076b9f256b10ff660ab89efdd6513d4ac60ab4e78fc2b8bdc10156a05fadb6ae4a17f6e273dac5d9165eb1d6e5258cc073883422c9e613cb436011fb443a9029a5dd068bd33740684f3", "9962c34c5ed7bd5731a4e33d9aaabaf72cd68e3838e79a8503e04f94f563acf6c3af6bd1f090351c8c355ad97dd277d5d7103055c73ac9b148bcbb950d5dcea891aed34ef9f604df8110355afa76c7e13f89730aab5d1a4a142e73990ff89ddcdb46b3e94a4e2d401264b939153cacf32088801018770a79b206479ac8b46fcaec2488ee95443802dcd56ec4e35069f5f5ea959a72e174d03632b87f4e7187f94b7ada92d5aaf530d3d4e57ba51a2cf845dfbc33fb7395c6880ebc124ff60dab88efc3f47d60b10ce80a2f6687e092185f2e9c242171719a1f5ac70b98dda2513898b30fe99dac47b66fc22c3f6b398d2b3ab933b573551b4b2c1d9f45c7d0d6fb3791adbc794d8b4fd842a385202754f4482f4f1d21ab40143480eb8d3b76c78be6ecd6835c5e1273ff3cdc8f761229682f6455529d24a9b795b00f09bcd5299330a1cc9fd5e84ba0716131f852a456b43b6b479a8dfcd3718bb6563358a4b969c775982fead4cac812171a00faa1a902cff32cd60ed2c54963cae896d26f98e76699df0a2d5a5e076703dfafc74f7731ccd060765bfefd847abfb8c444c6b9e92424da53a21481cef420092818c94e1c5279c7893745a72883f6dffe8ec188e5078b9d96a5e277bd916bf1cedcc79cd4fe78e71b38cf2f5f076f6396a834f3bb5e383c50251cb92b3ea2f9052f6eaf6d2e3f37854457d400a9facd382877e6", "1ac37db53486736b3f268b498e20f01c13e0618856a7d17e750fe0cc88bbb7a06f805e8fa8bdafc86c932b0f45bc4a6b7ee8941fa90a3adbb8094fcebb05afcaaa3b89be20618077018e85024c1393a8a78813c9d4808e088de55f74b117114117e0a1e89a3397fa4cb19b4deec8d2d9183b5284f65820722dd03ef7a966c08b8b6cabe0d18480a131c04020327ff84a4eb2bde442c813453940a00ee38b874d6b533dd5e9cc5ae4a69f98a0fb648592e494a55bf6f35f207f699bebdc632e09647ce626dc9cc171c2a30a70b08ed642db95c999396e1a2837c76571f9fab90c7d35a4318d88a28201fa3fd91d6b59a687c40f4817a0fb5f7eff71b03f899fae60e2e68a60a5d2f1ff18dc463cab5ab6676a919e0d265af8a7a569e9146e07acf38f6d956148dbeff41f66b963a914dd1ad54dda8476ab5f8513702e987605a3acf1c59910a4b4bd415d4429ad375a17c530069dc7259657c678c107bcfa9a7ff63e3174a62c23527a6336d96fa9ec84303ebdd612f30ced0e2e5d349ad79c035c27284852af68d695fec839bec668558b27e82bf183f3a9ac684b082d9d07f4677cf6e0793514daaf3eec0b8468a867526a0320e390f5306e91a02eee9860dd5b17ae3882d136171242f2f5a350eb8cbf9472ec3fcdea8ddf994825ea4aa38dd040c9e9f7591580a7fc765aa3f2ba796c0e8af3dc41bd7630413d99c421f2f3", .None}, + {.Add, "30b7ebb65902138ada803a5941aa4f6cdd06296f43c3c39fbcc531cdaed23276ae3812449a52a94e1b36a5008efe395aee5dd7041c8a68e3b94e0fadf21a02811e1c7ad0cc5c95d9bc63db1c72f28d77f33b469b1aa7fd05731ac072530e8fd289ca3eaac26285a7c4f52b6cf2fcdaeac1492ba62dfd22b0a5493318ce45cea699154888c89dff5d0fa9d5e68dd33c7b39362d0f70c269028b86fd872ed98db35b3726952450c11ee25d2eb181f2ac7fccc310758a0235fd07349420fc2df5746565f20f709ed70fae21b00e8d878b20748f6e45f024278b2e58f62face50a32f842a6ee420e7f97df30c0b6eb996711cf53447ddef176716bf172f821cd92abd806cb3974010164292d9abef28f8d25ce2d1cef5bec075e26f1cf0388fb7400370f0773733bcbdf7f9f84c9674d8bf308b419ea037eabe34624e38a4fba7eca11c8f196a8d04fea8f1661f260ae8d57f591f34a28ededde65e0f2d87000aad79b73ccc3cc96617cca52a5e816dddbbe0dd9656646cf0f05a0b1ca316b809c16e8caa6ed2dadeeeb5e8be1d2d9c542278bd606a588854a41338645c1bb9fd2ccbc34c160a61cee289cfb9f4d12a72ef81e789b888c9151dac9f8783938d8f62aae58e9be6a251a44ff46f8b9046a4e7db6b52d5d3786e300fac24e87303c149141c978c6a8e2dacee103df27d9f76f9d0627c85ae1522fcff3df0230c18f033d", "c34641e3101af45ba05c187bd28a94eeb5973af2532092653ea4ade3ef44aae97b032a449fccdb34b3eedda96cd61d29261e0a95c837640ccda1b4796a1064c2c4c5bc81f9b2ba5168866c70bfc2f597870232646d23907ea356e4380b272eeb1e9584cd6a1a013824627b7417a1ed90725f5ece8b386291cad512e20533044e1fb3493fcea63f7a65910c7277d32d7b5a3b9ba53440c99cb34b6c5a7705a668f3060da1c688415dee9b0be7e17bd7826146b76932ca5bf1a98c0766c902b7582c4d8329e553bfbe99b3429fb7ab045c8d819396eabd0b707dc3b03b64f4cad926913c5b1ac42b446dc71186ffd16e35c14169f1a2341a0e2b65d8959f2a022102e8fd90bb0859a01f6732554dd130ac33fb15c7722c862d2eda6bba263fa15b4557be82c2ba7adb592c0ab8d158d9667817c16891bd09b13a69a73de5927db4f3fc6cf2cdefa0319b63748fd98a82f197f8b98e3749e44721d01df4e2394c3b4e3b2a211a75fb03f1c3c685a9535106508a234981bc73639ebfd3753a18bfee59c528ae425e013bdc551b4720c304ab11fa5576b802e6624e6d0aaaabbb5ccb3aa93620b56383ac6ae61268614c7d5fb3f2aa2523e622cca497ef6e842eb4501637ce9fe9e64c6a8fc4c6e9bfd3edd18b34f5da84662cded03d46354cd230b4b610e74d06dc3024c1fda717e0e111f65265d83c68643a2fef3e8d369dbd57c3", "f3fe2d99691d07e67adc52d51434e45b929d646196e45604fb69dfb19e16dd60293b3c893a1f8482cf2582a9fbd45684147be199e4c1ccf086efc4275c2a6743e2e23752c60f502b24ea478d32b5830f7a3d78ff87cb8d841671a4aa5e35bebda85fc3782c7c86dfe957a6e10a9ec87b33a88a74b9358542701e45fad378d2f4b8c891c897443ed7753ae25905a669f69371c8b4a503329f3ed269e1a5df341c4e3d3436ead9027cd0f83a99636e84022e09c7debccc91eeb0c09b87c530accc91b3753955f296ce47d4f2ae45328f7d021101dcdae132fbac1ca66b11d9d50c1ed3e3495cd2aadc4cf7d23deb6ad5479094ae6f8125907f97574b8dc0f794ccdaefc8ca2f095b044894cd144060bdd2022832b6ce188d8b55cc3abdaf3b155b7c66c5f635f646bad8cb8f8238a6655980cbdb52953bb594808e8ac8354cfc7f05c55e8976bff01c2a79d6823a3910498d8aacd86037d22587b110cd5239f712e9aef6e4e70c5c80bc166c6dc0312cc45e6388afc88b82693f719da6a5995c05428fcf9b700bf0273ae0fd19fa8846d29dd05c1c408830a381f3506c675b2f97f6ddf7815b8071d507e1b1b573f3ac57d26b45adb07774a76e9067a7bd07aa7ac490b85e540b66af8f0bbfa2c43e3c4f41ea2337bbed0fdfcaff94bc7d0e4545f7da6013afbf0af3a301863fbad88193588da09749b669ffe31d8f675f4c5b00", .None}, + {.Add, "-89edfd184e3c60a32e1838c2bf4346915378ba9c8cdbd31dad68d195269dd64b817b40137f52f545214bba5ff70413801b7af8352018727d5ec963133fe363ed607de6bf43e3014d7cfcdaf0201fcbdd5fdc2b3cadc2893621b2be5835398984ca635c6123a1103faf0ee933add1a399741f612cb3a41e0ed52419217f26eb971c11bad88d4c8439d049924dabd1b1203ca5e9158fdce4583bc79c72e11d3a1e8e29ca37ad66566eea4ee5200ae7eedace5300e052b3ac933fdba2b780746b110b2d7d3618293c1d90266949c150cc3408d7733ee341aaf95365a67717551827723a4e52ae5b211af2e95c1498bdb5114db034c7ab871c4f7f5eba975e55aa6c4260358f4bca230251395d12917970a22a19d2ffcace31b98367af144c2e836ff3d93faa641f4b2c5856d30db115393676471c23307d5931b77714b579f9c7dbcaafe423d38657754bc61f20c0412a5e169ca0f1ac473a59892e7127ffb4f3882e29d1dbc5adb59430f329ac3073e477d3d7a1ee3276d2f643e0b5b1275b80a53ea90834b3d582a8ea0b9510f792a44bd4dc6c92dd9dcd51d73a9da45e8aadb8937cbc40c0c96f69f41ee11218ca457beac730814c9f150ffc31ec387e34fba70557a5d9e0a6b73db5cc7287621243e2e10ac282a5b95025981a78abc58fee3b82d84cb04dad834f67c7d54f3c99e39ccc96195c363a9a2aad98d101c00bb96", "35a1da04b19623459374e8886778c59622a5dbce82e0ef464379814885c752f75623ecc207e8e97815f7b08b6f63285b14e9a86a512404b174b8a9c37f514cdc854a19fccc82f88a5cb32435f9d32861155eaedc252736dc649ca40928b7c9ddd2764a6f21c0cca829a2333de8587a038893e4d3fc557f4a3145ed0f0676c2721bfe8752e7262903328109bb7840bb2f36c13cc73cf65fdd44ad2f80680099538cadd1155adfd031e9fe54dda31b473e61125551fa66a7da825f4b16ed9756caafc98b3bee441388a2a81c4f7e7a67ba10b8125148aa2dd82f96673a63ab2456d2aea5a24ea1d7c6f395cb4fb1dc37c3a63c10c100712502c4bfe4203a932b27b339d89929114524907d80e27117a7bbc08620c3e8fa3c7bbae2337ac46d5305d5a3ed990fb711573e8435ef6f26902963806d502106df9fca0145c88a3e81145b10a2d527c5e1e133e12eb36745db3b086f5e10e2f801ab7696640f47d78d4cf07836f476fe5a7f2742aff4cc1bf3eb5a18f35e084b83b5fbd59730d24561e78f5c0687761507a982c5f3e7626052695dcd2edb07cbddd54dded044867da2d18d1de93e65469f3c2d5d362c7428a2e46bbe416fd4e0c3e5101c83e23503acc4121a0bdf3013394c33aabef25c719fdd91b8e77b912200f5b345319f9b7042b8629b4948c7f5dfcd95d98fda676591fa75f5e7b8e50a05834558d8c439c10649", "2d02fa332cb25d3b609364fc3b84912d0d6e5024ba13321468a2f42f335d75929e0c38c0cff3ba23c3e2f4e56ff2e7231331f8e6ff227d899ecc13924b53169daf423b90d844c87584e35686f7d12ba33f60ec285a4b0e4902817823a564314585d014a90f86bba42eb144aaad7b5fc9f151eec1311b3d6943f3ab7cee8453b8aa3d6ba55e5160bf957c70969d83a01d32f6de35e3f89197c0f0b5b939eec5b1a3cb3471e0096acafb59668ba26cc850b42d2543f53b6d114e6190eb759010199f16b3688cc17fc6c9a5b5bae2655af6d02a9b1d5a7613289a600cd2f235d2d45b8b00bd23bc25b54467358e68505c7291610d7485b8b33dccc9f876c4add080ef13d5403454a2f46b69eb11480010b19de48393ec4d596022abb8897faa6aced666599e69751ca478fec8be94153c95fc1bfb8dedff0a0cae89d47d329ee4969e65a492ea8d7c69df24ccc15b41c89527059401c8338e05de037cfcc7dc3e146d9599d6baa37f25e4337d5a0914b5a3dcdb793f2524168697978bd5bfcfa9dd3b7176042ad7af7ef4253a9652e72824a07f6811d9f20100306b266a4094f7f603e61d7a593a08458e1b481b529bfe8cad11ce67c016d2941059651ead205d09a1c491819208cdd8584df7c9e6507b9f63a83b5366c66bf359c38a14df1743d4aa6dc47dc31b07989f5d1285739bf3c0a92c862321a65be09a7f4bb41dc04ab3", .None}, + {.Add, "fd1a2707d410167470e25b7d18efa935e735c6619a4eca15f3b5f6a7d6ae2035e5048b348be14ed89a2f074e3f41033e594d7f10f5728f850f880b6e24d31857f3fb24f708bbf5c5b5b9544e19bdd3e99658a0b92d4adeb6bba13c137ad61486176af79db0fe3613a1fb8b4dab07a09eae4a7d703fc960c6b6e733a82c2e986e7ece218d173ff44a5cb4d952124a24a0281e3b5a9fee0af111d0a20b3bf5f4f13257b64937af7f77ebeeae6302ebd8d306272cd956dabb154aad4759dbe5b6bf71de3a811292d20a61c5b2a030b3936cb6cb0a62c1919ca9d6a42c889bd55df1f91411d4c8e1ee1c4a2f62d8c1ca412448f3c2c9a5b0d6aebe442c24862b74726c4d605ffab9331a1632c954591fcf352e70fe35dda55c19d230e91d3281488d8e6625352b418de0cb840219fd8b48db98f757833677a1ffa04a401bb56053d2ce463e1e564585911630216f18f8986f8edecc3d07ce11b0b4a1fe0abb342bd0f9e74d9f22e0069c39e005da6a4925900f7816365054bf5113443a6820669badd7967fc09943cd8d463b9fa7d89c61ce673c92cf4fc40e3a5358518710bfaa64fa764e93c85e721012cf1395c43974fccb320e1ced829bbcb533ff64e81dd3bebc04e452e61b804ed1d5ed736751d357163785a8c0e85bb2004cbce4fe097f4b54449a89e01b37fa3825c4cfcd20d78ee2a7b28e59143a371ff438336b21f7ef", "d19d0dab2f99df642ca7a0e9c1115bf09f3833c0e482c4e61e3aab2181d154039b6781223fb4f176e06de35f2513123550ea1ea46c51a51975d78a8284f6f67190e9c519029186207ad07d439e675f096ed0fb63310ceca2bf4a0de3b4eff2c027141b5be6afbef638a1c9e57c7e91651984da92374063e48d5545029ac5ea2332bf40b5da766512dee278585b09c0be0eb24220f96dc83a2830319b68c0095398cf43f2cd5430aef11775209dc087d1c3775d30bc7eb9d843e5a2bb6675c0548b02e550035bda7d33b1c4a321aa498c50e3ddb73504cf718810de51e7501c5ee4bf506338fa3b4a4c3c212d251c3fad8724e9f431701be40c51d4515462040669311643d3352d81f1dcce7fad98d94d5a50c7109dd0e7c0bce1bd0bdff6409c787193e900243893f84cc51d935b2cfbcfcd54c9426fc8edf672dae5b5c98210fa7027f8d861ad947f52db8bf72bcd697ef43c9e1bfe744f523e1e71dce395fdedf955e1161f00eb8ca4ab77409d2e2bdb608b7614c46d0e19abb0bbff3a1bd49b90301957e8c9a413e603d0d4a453e313363656846f4327893596d4764c281f21a37c54d0fbe13c051b64afa97d52d9181b16ac6d46d44c9481e076f9ddba90a2da345861fee1af954a593db03090dfa39d42fc2788c52b524ee44cb4b99380161dcddfd1dbba0613ad8a3a9de6ec5ddc168c1cc59016460fd3e60c31960d68", "1ceb734b303a9f5d89d89fc66da010526866dfa227ed18efc11f0a1c9587f7439806c0c56cb96404f7a9ceaad64541573aa379db561c4349e855f95f0a9ca0ec984e4ea100b4d7be63089d191b82532f305299c1c5e57cb597aeb49f72fc607463e7f12f997adf509da9d553327863203c7cf58027709c4ab443c78aac6f48291b18d6242f1b6595d3b9751aa6d53e55e36d07d7b995bd32b3a00d3a6a4b5fe44cb26fa3c0503b026dd062383a0ac60a4c99e8a0a135974ed8e92ea15425b7713fce11fd115eeac8795777743525ddcf907aee819f6966c1b5eb50ada83257a50ddd3623801dc2966966b8405e6e680d1d018acbdd720f292ca960075da8d7878d57e76a3cdee609c080f97d406b8a88288c1c5467b7643da8f12a6291277892a06d7b91e2b65c674c3d0c73790e675d768c4ac4c78e76aed96bd1b016b29d5e3c8b666172ea733259582fcfb102465d90dd308db23cc860006e01c7c9817c1cee7e0a38038ff0787c684b151aae653bbead8a1ac65192c5f2cefeb241fa0b7827326afd9f12c97315a21a378ad40b5b17a72c925d4335161dc8de85b870bd2841c19cae8995a534c17ea78456db6c7d5e34d24c95ac9700949b5dfdbe1fb8e4f5edf18ab481a61fe672046b117826436b9d4c8a4e87120dd529ba131b2c312cb6a626869b1f6f2004bd34f0a6b07c3ecbebe3eab1ea4507d2fc81e3f9cb80557", .None}, + {.Add, "50ecf936a0593795304bb5c753425c0f737ef2fbe0cc002b4828465efb6b45fabff5989e2fda890c575acc0d9250e24a685fb8061878e691883e0c56fc07740b8155b093c790effd03dfef2f63155a443112b1ea779c2dba4433ae9882b73efcea239f8dbbc8df476095714feafe2886fb21274450d914fe5628a6bf55f4c1aef65e64cb981a33d1bca735e3149887c9be35f37a44625233756a4f7015644328a77d9b8e2ada0fde63e6cd3d0dac656483145a960bd9eb44c0cf0cf460d94477e6d433905687bf893ef5a78d3ae2e6bde857c4cb7fe0a712debf8f751efbe905d93717c47694afa9f026b80f3f79484df3fe7d2d076e10a3a10f398797428ec711d7b1e1c7b25021c12023fbe521059155cb12a13db0049f5a77a1c9a696cffdcc5b9375d021d19968675e1542d59c09a650cfd7acff9b2220fa7bbda156cef5c8d1bcfd07c53773f98eeaebf8cff767aaf52cebee21b48dc9cccb9e460cb4093752298513170abb5430fd780217eadeac253b1d03546fd15cbdb9bd5cef6097e1bc0877768b0cc8793253fd93a7b2672327d61b143c622d6ad34af8ad3c5218fff0afb9c13c004eb6d03e811d4688e0615d71cc61c373dc39f85a2e39b2021025d850eaa71c6256acc76190d63b7bbbf5cd575e9a2c73ab913b3562ebf0b236a7f5efbad566436193b6837eaecb358b27a676361a88a98d739f1760bf7e34c", "177f42dc4218dc751e2dc21f0b8db3e7d8c1171b9dd01f448e97032f12bf2e2deed58fa79f4edb89088570e51a53211b72daad0fde9d253d32e7c8a5ffe461fb70e380f7c8a06c663a28ec37041e8c3e7ab05ed1f3444306a3dbb950d6027e3aeb8ce777e31cfeb84827eea5fa4bdba54b19710a26f31f83d315a81da588b8079ab4190af6074be23606a88974dc82bff1773cb30218f0f109b5a117e994f62e68372f8e1116191b3a978e1f580ccd78c00d7bbd007dcf5abe6dd2d30ee0d09860e187790835196aac97aa487e718b447dccfeefd4a02a442d52992fad6588b6bbc6b2cf991018cb640d9d9b8ed6f63cf29b55980397142591ed03122a0356794d3d928e5562b8992500429d9e6e2973247370fbcef634d80f18fa1b3d6f2b9a1cb49ef897cb39a3fe8efd0a2e536b7cf705f8cb216f685a696b7d07f810009f5041d189210eadb0e7558e4f6692cb4b705a63703f1e69d7ffa4dc604c2c7eb3125ad75c4a7fd0b74dac8f380a56a29a01cb971924025cf4525b6a38d6d6bc0d16f582508be1505afa5fbbe8ca31ba6c85afd1914f6bba4fd1fcd6cba8c8d8de5104fe5a31ae5714e2904181b15a361922cc428975fb4bf2a2cb65518889669d64c37fb4ab6ccf164d1334cac85260899e720f01e87af1d292c3c094cb6d6cdb20650171081d58dcb79f17ff3be2818085ed1c425a56f78b91df92727e98897e", "1c8e126fac1e6fee71327d7b80c1d9a8cff9064b5bdcdf47431987950275e28d9ad4e931824c8419cdfb1da5f3782f401960a8904024b3a64b6ba96b6fa4d93c28f8dc0105197b660a66eb29fa4fe1e2bdc189f09abe05e2481ef43a5e2df22aba2f2170bed98cacbe3145baf8fbbe2dbacb837e6c00b0d3b87832899ae804228a19ff57af88ef1f51d11be7a6260b3c8d5a9beaa65f1614410c460eeaeb3a60f2af0946f3c3ba1920d5faf328e793cf083ec166613b6e0f0a7ac3a254ee64dfdf4ecab20d9d9563408704c1521fb9b05c527b3c8c9e34b55b3e9226ff554747195a244be07963c60310091c82ce8ac1d1db3d6ad40df52fcbfdf6aaa3777f65be5b0dac71dddd9b411244dd5cc039cc39d02225e2d1352204c07437d7d89899f97a582ff4cd56bd951572eb8280c53d916b05c89c3f620c8b7b24c3d2256d8eacceed58f18b012826ee7cfe261fcac1eb09b63efe008520dc41a91a308d49f3a5cff9f49bb1416302ef9f0f8a782147ec8deacaf437a3f1682745d4aca5b216951142d8034a012781f2e128a36c3592f7e24ef300af8072a8aa0b7b339c9dffe1040955cdc21719cdfd4569c32e9ea728e219a63c178330666aeaf46c2486be672104c355de953bb7dfaae3d5b618455dcee477d21db90d4bd773eafa2c77fe8ae4606cb573bd12d0da803726cf34d9386783a5bbff8224691983e88a906cca", .None}, + {.Add, "e4580a140e8d972f5bb9c0561a63223ed1d53dd9f24017efdde764bf5761f624ee283760b93d4147a7c820cb84a753b11165acbd79b4f6bb34a1886b646f04f56300848a6d167157ed78a22975e26b9955a0815abd4a974f2c71eeb8ad4fbc80febb3e5d4f979e23ad5d7df6c21398d5886d209904f8b86d17bc87097478bbca01a54714b3ac4c093770a8c1aaa2c0871300d6c21acee92834acdc2f6656a07e86d0f09957180e5f8ba5ec0bf0d2cc06dd8f250c1c4b32bc6da4810ab6438812f2c3e235f79559094579fcab9e1fa6fc3b01444efdf5673d11a7e459d97358269150b1fdbb75ccaf014908424dfc7a2a47ba1bc01c7f8034f28fec5d5f122481bf8d262e264418e030fd7125116dc33878803bf86b3ddf1e7a5f8144cf76c6c6c41393db03f2ad06a2e2da3cb10b15bb958e87e9535024293fbd6bc3e44743c064b9e1207a4da2cb3ddc83a8b412c3d38b08d369245b593c9f78969456e9c8c34852978f598fdc5d904596e6420423693a5611e62f4d6581100a9e78ed228be501b9958f3efb278f815fa28db2bcc6888ec86a0205df98564e1a88312a0d2dab7b3f223aa25d87344b8fed792ac0e9c2a0665057e0f8e70668bb96d73aa860808dd1c34d5ce1d3f9c0e6635fe5f3162b6b698bfec1283bb7868bc3da9081e4e1d65a6113a73c1e61d0fefd869c9459f72c559f63933839a32faa57d0244c3d7e", "2552c6c2ade73d23a8783dbc02e5ad299c60c765216097f6239e2db386b801de8df9782ecbad63f72f7f6e8420605ab54bbd5934487e6c4c39aa8a567b0bc4bdfac04f2d37df19db6e0a5da1d032f89698fcccc9c58702e2c8b20bc49e768681add1530778d76b73b1a5977a0df233a9317509c5ce6a5b54399e3845e609adcb305713a1f331eebaf215839815b4bbbf7540713105fbf0fe3fb17376de08c2e630a201a623019b7eff727bf3dd391812fddcf7a8a06156fc944fef609c3af9255452fb29a5fdbfb163a5347dca0fed416cde6f5ffbac810a687228d2dfea39473c9ac62f07af87395d9232dc752d988775644e3b055a51155fbf56fd6fc22da2ed78ecec4a8e4c4bd9a5514170dd380499c49ac7fbf504393362c8f781d962b6826088a123dfa68174a249cc4b9c610681e9abde2bc26471d98cf51ca4300e0702df2f306fff8dd00f9e92047356b7e76eb856005a22aac611782df80159c912fdcbf97507cfcb5c88c6aebec327b3dc188a4d157b2059c1a3da3aeea93b8cb67e3624ab7437811464af4b30e792cde187ed8012bf292030a0336cd5ff637e34609b6fe0e93bec5323414d192a4bbd01b409208c1994be413fed4b14fce188fe52922672719c2701e43286594d90f43d59b295c901f958efddf8bda815db010f5517c0a71f4170ee98f9c20ecef6477b1f3fb7fb0b4dc0bd0fcfc8b69cd326b6", "109aad0d6bc74d4530431fe121d48cf686e36053f13a0afe601859272de19f8037c21af8f84eaa53ed7478f4fa507ae665d2305f1c23363076e4c12c1df7ac9b35dc0d3b7a4f58b335b82ffcb4615642fee9d4e2482d19a31f523fa7d4bc64302ac8c9164c86f09975f031570d005cc7eb9e22a5ed36313c1515abf4f5a82699531fc5ab6a6de3ac429862c59c0577c46884147f320cada26745e4fa6445f6364b772f23f7a19a9de8b1867ffce0be419db6c1cb4bcac89b901f4706b527e81384716dd5f9d9318baa91f3129682f943da7dfb3aef9a1e8477a1a0d2cb95d916dcdeb782cc32553e85edb3b1ec32a12b1bd1e69fb21d9d14a524f435aced45224ad06131a70d2652c0aa2c266824afb3d1244d6c06732e357adc24a3c5150297d46741c7c27d2538817852408fca776c2177833c77f12889b194a60e0887751c767991050ea4d309b4d7b15ad27697bbaf9c129697e7e0402b0f0c48c584391d6461e9104615fa7ba190c45a5052bd74552e05efbaa6dbf42b3e4d967965e189b7fefba3ab332a8a3e60eedbe9a4f946a16b5ea14c508b886ee4df5072970abdfdbda921b8b9973876ed13a92550ca6c4546f70e3fa8da547a8a8e1ec3789e97ee063e9bfce7dfafba518e9b933840a68c51c21c7c32194a764848182a65ce5f12b7221bac67d8f5069f8bf956b8aa1724b95575e9e85fa603f7a2086c11f6434", .None}, + {.Add, "87e91a58bf66558ba233d1c8a62ae47ac946629e242ea8c4896fd8e4e4da0133e244db33a726ac16feb7c3ee67378691aebe9acda6d54248056097e76ea425af0499520685987abec366d45873c026a3c3f3b37f5067b37aa40ccb427af8af9e245300b4ec2fd9f7786830634d7831331268f05b5a4a54329d522d0e15ab112cd908a55373bbd200bcfd4c99736dfd1928ae6694363a7cb3e0327d8bb72a171bff3169cfd13befbb9cbe246b08fea51db04243a7bc43a364cd65f7dc116959a74ec82d09d63382984ad8423cbfb0650aea90d668950821cd471666d99fb4cf195aa4e58f355f142847fff75f372894f24679b06ab59b62c256b9c81922d79b337a10ea803a495f8a29e3e385e32944858ae5949a2684684ac3fbfa2b5445962e68630c5e154e64b1227d410c0a19a2026965612f9f304cfa2568c4bbdf23d02b52cc986b861b3095662bbb41c6c1b776f892e2714b8fbf461810a6f8fb52b570f953885f694b96302a166723937f5e884019ae96eeb1b9512ad332a4c6944b5bcb35fb96c37cfdac11f563148d05c3ad62546ba181329a61621efd796540e2659eb004a07e4ea8cfb7310d5296a87515d6d2c236a5d5acd2b44bcf832aa109e9469d62d23a5b7d74b2536c316cc85a0a4b68af65c50692a1c2d3f4785316dfc476dcc7a7cf5be2a24f31d20fa34877f07c792b850431c6c10167d0779fe318f7", "4f398697a1415d9e41697541cb338f2ad7272ea523d69c99b264a096c34187383bbcf0f2759adfe089281668465abcd2a0c697c17f4d1f699a724f940fbd11310f71aa9b319dc6b55206d46800d34bd33e5128fec960059e26917fe6f10cd6a11c973326e7ad1b59a2656cf290e2c5f3736c7ce736d07a0e7443eb3e1fc914f976444fe9e24ea12a5ec8c5f887d956758ae0a113ed79fb1bce14feff80d7dbf36038d2a67f893f7c0b0eebcb2b0550a10b1df58959c17e4cfd477957465e7d7342816d16cb665cfbac49c72729f99b9a3f8dd33fb1c5e8de3ef2f113432842519fbe23b53eae1fd5a8718b1d3468023c0b8b5f39fa0bf089b6e9921227f683986434b07ada494299b2b9d760a93ab622efc6d7df88235f852a0d3cec3e0b1c0eb4bd43d0dffdf7171516b60e55fbb7ee60ce1d1344df23e762598c79f5ca6792f89651fdba6c7e65552002d9a336c7e4ee335dda70a6614d9c537b595afcc10db3283ba7ca89aa6d3b4c5d508082b01612002aa03b0232ec42d451212bf5752095d7ed0e64211a8a1d2d5a5fa06553d7a01db5ee771b54a2f77cf0e1320593a87cfb051b6085b58092013058d8afdef1b3e4637e52c8a75282ae8bca0a137c8d9a53391723114d385acc4712f2ac323537177c01ecc07916a70c14202b4575f64ccc92e42aaae4341208cd24a3683dbc04e1bd16efaf08478d7ccaf57b9ab8c9", "d722a0f060a7b329e39d470a715e73a5a06d91434805455e3bd4797ba81b886c1e01cc261cc18bf787dfda56ad9243644f85328f262261b19fd2e77b7e6136e0140afca1b7364174156da8c0749372770244dc7e19c7b918ca9e4b296c05863f40ea33dbd3dcf5511acd9d55de5af72685d56d42911ace411196184c357426264f4cf53d560a732b1bc61291fb47538eb38f07a823b477cfae477c8b3801f30f5f6a3c7650c52f37a7cd10363403f5bebb603931160521b1caad713357c7d71a91499a20a199df93f7220963e9aa00a52a1ea9a846ce0aab860957ece2dd116afa630944740d33fdf071827c6b90972e52050fa4afa7534c0da35a2b4ace1ecbde459afb1492a223dc9dbae68c63faa87aac6c79aea7c7cfee0937179250b23d1d20502ef54c5bc83793f71a601559f0ca337e42e40f70e187c25135d4ee37be4b62ea694087aefabb4bbe1b69f87f5be6c6404bbc362093b4642252564f767eac7bc40733d5409d6562c47414020e9e5219d93729b3ec3d6da783c5f289c07c610de8a5279e18362f22bd742d6b17850272218ff84def04599bee5a9746760e1bab09bbded45e5049323dab6f5854078ab725b4f89e542536fa5b4d34b48676e0f09be95d6ccaad0d1fb3445f748c3f82802b67b1c70bb869e008987e5c55bac3a95a8bfa06c6d6613a9f3446b0b5ac815ae89bf3e0cf088ee49b6d1b7dd1c0", .None}, + {.Add, "-bbae0dd3c94ff713fa0e416493aa4f1209a572714098999734e87356dcb6587b93ac94c3cb5368d25022181a2a94b943fc84b2ee7e03d64f6dbd46bc2450e1ab845bd5076e1b487959e51398a4c8cb7627b311b32aa53fba1a23636acfb1bc5b2457780bd680a35c62d0119dd1570d22326cb65721bfdb7da58e12a8f6017d89439bf14cddfa9f723f1c87aeef87c32bd73819e9768e9479c124152749ef079e901fe012ca7a9e55198e11c0423904ee87c78fafbac48ceeb0cc2ebf71ac06fe9743999cc84807b2345f2c571dcd4ae6db5c1a583d7e9e30788d5b62e807e1c280da94a9a96ae03054a844b5fcc96f9060515820b8ca6f7baeca3940272f272419d63ffb244ab438300c504d144b812a575de02f59b4186a048a4d890dd9ca7ea6cefa7f5400ea8e3229dca43ad432d01af4ff00dddb9ced8b7a3f5484ee21de00d3c8fcc2801fd9e4b1c043a0d08e00bd8852820f07bff6ce3d7ba766227d0d0942aa5251d9e160b9c8d8d29e22b0559d75f62c2162c14a3058984b170ea2873bb9bdef2fd8435b194434e12f7b660f9f0cfa043eeb8a6130d1b8837dfa6fa62231be906ba0fae686812de177de9eae1cdea18b3863fee0f8e09780cb8948a24228c7d4b688c5b8840bfed4afd29d12eeba7ecd6a0e95b48c438f00bdc774c65d64014913cd1c3760f2bea79066e9be2a964c1dca81a1363700567aa243cc8", "476f865fe86276cb09b13909ed9ae4f71f66e4439e2d6e3c16b846e015969df915826340b088b34dd82fae57d6aae1b3f675a58467cd502763830ea7737d68434a188263ff5ba8f53cdfac01f943aa602af55af4e20a8daf46b8bb4df3f25f4cd2359a75627ba9612fa2fb363a941fbbf7e92c7bb73ba97743d9d89dd2671d861a5f6358e6b115fbd74531096d42b237c928f0ed89bada2e6ccf9cddc944b4a167a62152bc66c341503691685433202b0747ed1540279b3412858a35bd3476ccf31c386b81d2097299e1b1286477006508b4d05d7bdb6d77c54c497f1d17614d1fdfdeada60fb65fd2065e3b94483adaade55167372dd271c6c8e7c2df173930f378ff668d31fdfdf55766d3aaa031b1377e1cebc24b5b2a935609a36a4a0ae5cdc85386c77869db8497c3220f1e42d3e4826f8b312afe9b1e5a846a5e9e9453c23ccc3c4fea40590bcdb04cd73c10451886191e7b398e2d6c9466b4ef96be0d77ceb6ce52636d2f7f82e967a0462c96624d2eb848b538667322a3bfba83f5affd7491a0bbfaee450b34e088fc0fc43047be781d1ad23b11fa340b24eda187260807f292d9f9050383abaf47be6c88e142a68b28c547d653b5b6ad55e79acb0463f9214a23374807cad6c91f5a099f79bed71e69e13d2355cb43e8d92e93783723f096284a591c94c502b184897a9bb98587d91ace2ceb256996de8ec5e5635b", "3bb4a582abcd7759ca1054f3a4604005fecc8d1c8a23e4a2a369bfaaa7cb38715c4799f473d37cc0b32d8cd63401961fb6ad5a557fed12c26ca73a3bb1385a2891d2c5138879f46da7415ac86ef71da8c87a29d9af6039b3a516851746f743871ff022f4a5139f2b6975fa1c5d7eaee9d4c26116451fabbf6980f773430705ad8625a44418d16c04b353688e7e4a36050bb56f4ef251f0e6d0bd5b8b54a5c4277ea423518fbf195bfe9db04c500f8fdc1ecb741a447b52652778c749c619b65d09a7fed1b54d88f7769bbe62f29a2bb69aff0eb7f8038394bdc373c8ee96e330f7d235630b79085cccbbd9f0347ba3e1a7e03be52ba12b7a0bdc442edca446beb1db9b66daed52ba7256a1ced95b799e92083ee8ccb019a3f30d64cad96c6e3de35b63ded2385b32a1752557cb70ffa6e2d31f9b234d44cc45a2e075164fb235e22f8fac83c23e5b6d8294489d2f07650cad93f65a49122dffb08efa7934963ca73a8c292d45cf1973e65bda766401910875cf55869f0c51d01d1a3b09130b8789b8f5c1c8fd6a0f59a09d3ae9180dcf4dcda87cd6e3826be726ef9cb5c1e02ba5e4d6a9d33ef5551b439c69a6ee9ef660d8a11011c19665a628a3dddae2367a3fd694ccd7cebbac429609320f0c75a88feb767d0a9c39fa827fafe922b700eabe1a5613b91c4ad14ef3859a10742d1da2de7458f184d1120626d9271bc12693", .None}, + {.Add, "-59f96a42e1dda55396c4939d3a22167b465b5a42d0fc3697defde82bc64e7b363da2bbbc58cdedc9ea5f462f3aea841c8134c096a13c0522578f7aad943b73dcbc2a2b897df56764040659501c2c0846b7bb2d62796b6107d11181f5c08d3240d6625b76dd08799889de29c41787612182ade5057640cd4cdfc1ecc445998de6da0d94a45fbaebca44e87c8ebeae654f120bb989cbe59f9c2cc233d17f64b57eace5e682ebd389268d488af4e0553ecfc6e244d1e4cf6b0d1eb119aae22a742a2c99fbac765454ad90c9617cce6128d1ef7b404cb3775111ed3039917bd1b821faef44d8585e39ae6379a33e4ebd95296d0508037fb9f5cc4fcc11b79b8081ad3784fe3ead7047088c0683559c4561f7af0805f9193b0338b8c834af0a2d403fc83679aef45892c61d6d8c844598f5f000567da48ad7e4e03e4685a64afed8430f042baf4b731332cf77c0491c9d56c538ed2a6cf33bac0eca39d2f7a810b143163db785827d86cc7d3522982b234e7686b9558f484946765eadeac5e3b66fe45fa8e03167df13b8ba45ea3c279ef1279477b814b109b120093646bb5ef603530bc038e19d39ce3984dde046cff91e817a733e7c457fdd93d1ad93afa53bf1490ade314fd8d96742888b7491b272b2c49dfb7f1a65a0c7c18623701b868bb8efe524c643b42ab0edd7e1ac0b87a263ea306b5cf2c51924f43be6c88e44fdf022", "52df629c26329c3992e35e839a2886358816b8c9f384218875b828353797d145fb87b5ca62fb6aa3d6e46e29b1101f59bd7b55c5f17eb2c7415915ac5547070ba1b0492e59e94b63f0bf72c71c963e1a44830e51e433f9b314eaae2d6a9dd5e4e54e87fd570ed2a2c44da3f73864d90f048cfb9d887070f2ac1b1d9e120de4ac9c9e9ddd6970fda6e48a6831714e9516a1effdd7d2b6aa31cec3199a2be5076c718ca34631c82a82889005be7de56c135d1f5d04e269cf37bb1bf1db27e2681121d10e6d8ed4c9ac71eb7239396169809fd25c8946acecf320c22419ace7f06bbe0948b5d890cb266982daf7c6d22b01ff29a59629e0bea4b9ee9922fce4f81853234d3a019715e94e8f49c1ac6773355a64aa0e7933ea2b011df46d776ceaa6958f052559c506cea28b5dcb5da610dae54e7cb70ca0320ffb26cb86f554459cfebf7dccefa1ec70aa4732a870500c51fe5eaa0a3aa0822aa6aee352a363ef6a99641dafcd93434484ee0fcae707772fbf4b462f14276cda91d1355aaee7cd0c58c3ecb9dc44fbb8a71dae07e81e77d8b60f1113acb6a15868aa37c4656df82cb6445b76234a1138867571b31a4bdd8f3a23f42e125e6417c0d0de6675b7e2f730cb31c9183f3c3eb91d9fd100339411d08a7f4ebbda87b2d0edba17660d9073257ba6ab1935ab339c6dad75f2f5d9ce78054a59f32b41a8d4c929162132b637", "-71a07a6bbab091a03e135199ff99045be44a178dd78150f6945bff68eb6a9f0421b05f1f5d28326137ad80589da64c2c3b96ad0afbd525b163665013ef46cd11a79e25b240c1c001346e688ff95ca2c73381f1095376754bc26d3c855ef5c5bf113d37985f9a6f5c59085ccdf2288127e20e967edd05c5a33a6cf26338ba93a3d6ef6c6f649ee23605e145d4d5fd038701bbbb1f92ef56a5dff1a37537fae123b59433cba0b5ea404b88536626fd2bc69c2e7cd02659bd5639527cfba480c190ac8ed3ee77f8b011eddef4394ffbf514fa8e3c36cca641ecc6e1577cee9c7b63ce5fc227fcd6e87f9f6c84687eb6a276ddb626d55d9372795dd78949e9b8994e461b104abd9311f3d773993efddeec254a35beaa007190db7aa404192c0559932a774899a938bf77ae22eb8e7f2e5151b0800ed7e37b2d0431fba1f55aa92a61044ade25bd126c225308da0ac4d4a733a8e8062b89b29e4238aefa504acc1d87cd999d5b4ea4387f84712cd441bd746c76e0f603421d99bccdcb56b34cea2d806e4f3778b9a180013283c343f80794ede68a70104530fc7a08c0ef6f9880b26557bdd6b79efbd00fe686e93b5ad40f2404f4a4e3321797c10dcb5492f840e51da12ff86c09a2b03cf6dd4c0b23f1eb2cd70ffcba9c6400eb535b604207e287cbfa91f989af505ba3b73fe9594ac8a1bb8661298d1ede34b671d9f7823cb39eb", .None}, + {.Add, "1139a138c3e2467b6007b1b192f0d92cb9ef67a51e536aaba4a591c83f2f398b5f9e246000b8357bcd511521fad91613ae8d030ae740d0cb547efb936e96ad059803ac064f01f57793f3769c340981c5f22ab83f8048563fa9ad52c673f9a362647fbb9644313eedf9c552bfa9004d538d89fa3f15ac81509206770e7ff3a1906f3833ad31f815db46d05621fa9be1cbeb6e74f1f468b37fcc824df01eab52b9bc0b5cabe9a9c5f9f218bd0eda1e1c7ec4adff7df17c6c756b6349b85662af9cd0228c7566cb8bd6e119298aa39db8815680ff096ad2a9c38cfb5c1947f8d12a59804c8ec7a77a3d435edf1a738b9a12c37518debafbd87bcdadb5e4a82d3ac3a27ac54077bee11f52dc268ea65cb7b141f23a0150a4ae9fea669808a4a666f63f3fd3abe470a82077ebb59d9249b2ad6e8b7db8928422800cba5123a29e6f9b4735c9f230ed8f6036407ef6b12958b19b6307259e08ef39bd277993c05470eeddf3f256eab40ce6b95843802461956218a4a1d0a5e0289fe9ec10735d63f39b3763600da6049eb657ceb8330e93fa86132aad4cfcfa799985b33c8273e123c1dbcd7253b99b802a7ccae1722710bf7d57df1b9e193fd70b1d66ed65d36d040d8ecf5fcd2795478d643425e364210b22e5f861d3d8a08a2a89e25da0b8e38a9570b7384203e4c979ec322140cd1a94ffdc46f61ad6a4cced79134782970428f7", "f586b6e2a4bcdd2cf029c73870ab60386fc50b24c4233e237525912137fdd0e79ee3350d6fbdb078aabd97c7259bc312e055c8053694966a870b7dfc6482afd1b9ddfd8fb8d399661bcb19ffc74c84d7f0ce0019968bc0e89529ae747b90d65750add47019b4a18213e4c6d235c099c66bf25f4788a4166c2ce0cb31d8f004a9d38c919ca55e7151e3c11c2ed56158e809e5481922f6a63fa0d6b27656e12b0b9e269ad9e053b2816e5578f5cc55826df8fb5a41f44b5204652f9cfdbaa966e6db8eefd8f7513cd89a930a52b7fb3a94349695172565f3b91fda289dedcc7ffa4585142be28bc731a954484745e8cb74dfe829d66edda233979c8d9060dbd1f59d4989963a4a2ad24f48b74fb16be715650f232f99e2f499b213dc3f3333bed993f57d22c5e65e41e29e8d0e89d096d778cf43d3f9bb4e4718357e2b5440f48210dd21a736408b2667025aed91de635979c14c9520dcdc32283c68a8688b9ae62d383f3ca4f54a58e3b1dd127874a077990755bc57d3ccae30668f3284d636ec13bdca4ccc0bbbda83c73052e35abbbb50bc6fcb6442ad94c86f8192f693a730ca290665d6bb0b6af0b405dc8b8949aa8e34f09d6c7b6d0384f3147063d97650792a7af29b221002bf0e98f0a060400c81bae7f5111b1f0efc43e62db9052c21d4a8a1d4629efc85db4dd9378e2d5df9aecfd7a5ab71c745ece9c81fb2290c23", "106c0581b689f23a8503178ea039c396529b472c9e276a8cf19cb22e9772d0a72fe81596d7075e5f4780eace92074d9268ee2cb101dd56735db8a798fd3195cd751e1a99607d58eddafbe909bfb56069de2f8b85916d417283ed7013aef8a79b9b52d90065de5e0700daa1991dec0e719f97c59869e5097bcbee7424058e3a63a42c4c549d756872d2a917250cffd3ab3f553bd0b175f59bf6d590066758c7dc55a31f785c9fd787b606e3604a6739eecbda959bfe5c7be79d092e6b6110c1683abb17c4e5e1cc8af7bac33dd5b98f3158b17942090389d7cacd584b735c551249f0560baaa33416eecb32761b9746587a35d42b529d97aaf654a437509090cb93fc44ed6b2090bf1a224ddde57c89ec6a7015d30ea87a3399c7a7447d7da25cfd33550ceaa5706625a8a42ac1c1a4984e75ac18c8c3f70c724efcf4ef6df641d5812eb99672e1a869d42d9e44307bc0b152453babee5cb6be563e23c28e00bd50b2c31938fa9573f9d0a20929cd635d9b1abf78cfdb3f54e1a529fa5e23a2a874b212a5a72105a90db95e885f1eeb64163e71d18613d272e4e22be156a74caf2a5f678b990568b956d7ee74eb29a0927e6140c3b85bb440ea25a01d637467a5e07f9dabfc2b757902342bed404814b2f67b349c8e9bba939862643ce71e8b6b7455fda166683c5ffc77ffa785b47f2f98b16cdc08216943365fd0fa2492d351a", .None}, + {.Add, "-6f5d5d06496022b0a1696554b02bd360860006810394a3b542b8618c7a72934c58b6b80959aa4875c9df49424695174982873e01df197063634cac78ee761ad4a0a3e0749eecc744110207131ee423895b7575a73498fc7eb500c9457c37fbf0aac1d4ba65118130725da87864decb88c8a4c03106b7a710f2ad032953955e1eaee869b88acb3b048e1e8ca55b03637c8f8f9fd5550cb1ab1e508b868e48a506dd1ca469ab9bb518d8b6760e24a12cb90d124fa595b95bf5b8c30b14f8876f18b756ffc540e12d226eb6a9059dba5ebe0de13ec97c45334c7f91f9feb5ae5f80632134ce7e59e53caf884a149d33b5137bffd54a12eb5b2896e9816c871b2bbfd40d45da0f44b8c376e2a5d39c43ccc1f7799d1f34258f527ff5e766bd8786692bdf99996463b3dcd0214d115034cd0993e335d91d19f9a717df5b68f7f291a5db124e3cb43a90af7533bd212d2984136d64077f90fa9358d1d78813b2039186acff46d5b86b66a2a6af3488774e8575c34697030b218b54f802c3e85c013c27f0bb4ae53f9edb2b346776856d10043845d7de8630e0ecec928aef6d3ab94cf0cf0bdb8d3ddf4b22ebb5cb1756142ac185f10eaf20b633df9a67f39ed49c88db6aece377848aa126feba4ecead66cf593fde22be738618167e9a868b781748b619629d6d5b0fd409a52656f1b680cd527d9834921a069bab27169f2cb07385d2", "348642285a6e3d97cb1f6acde4bc1ab3e03735e1d9f9ef402b3ead30c3ff9c1845e6a19d6ba1e4f0b3dc9e3af6608e6512c2bc41c78333a1b0e060062a1d8e8b6ccdadc9e5c1e536beffbbbf88bfc9fa1b7def29a1c88c9b28383ec6d3fac8357d68a17705ba5dac1b3d7b1d39fa175bb00b099138146af03b4e71badf192815bc13cbe4ef35a70bb6479e80a88dfd10be667e284689af44c7b964e4c2297702042157397a31ea7ceb5558893742c98b717116aeccc0dfcb56d5d20fbedb3720e0855fb85787f44c899f5638ccbdae3b76dc295d26534ee9ff96b59535e05acb5388814beba2cd5691266ddda8f4330d5b8bd82c522a16e809be46b4eef37b763c171b0daf2760dabd273d126fdf2fbf1d25ca2e29eb6096716b27fa5ff29ab433370cad0f0b8258d30b2a96520f3f783009ed399d091cf93f8a1fc474bf0080adbc520f13db028a47196801ddb21dc646fedb1cc146ce64d3e4c61bc2d417e3e9ef5c834522611e557dc03795ba20a5d6b02df50ce0788911e2fc8b8bcd02ebaae899d965ef7286ea57b986fb42811fdba409497dc7f71c9a05014eed817e610e5706df6e02d423746b8df5803ae415656ce410721b57bca54d437a953b9c1e5170c4410a5eddb444b6ae67c1a2f867013b39f9e09b57a69b2f92828afef55bb32089215480ed8c55ecdfc80c4e21d25817329c6e041a9326bd0188d285da94", "-3ad71addeef1e518d649fa86cb6fb8aca5c8d09f299ab4751779b45bb672f73412d0166bee0863851602ab07503488e46fc481c017963cc1b26c4c72c4588c4933d632aab92ae20d52024b539624598f3ff7867d92d06fe38cc88a7ea83d33bb2d5933435f57238457202d5b2ae4b42d1899b69fcea33c20b75e916e747c3608f2d49dd39b9593f8d7d6ee24b275666bd12921ad0e830266569726a1cc1f2e04d8fb4d303169ca9bed611d84ed5e632d9ba138f6c8f87c2a61ed390539ac37f7d6d1a00ce95938d5e51752ccd0fcb0829705156c55f1e4627ffb44697fce04b50f98b38292b717e61e61dc36f43f82062073fd1dc0c144408d2b3ab79827b04997f62acc601d57e8b9bb68c12c649d02da53d2f10a3a2ebc0e8abf6c5d94ebb4f8a88cec55583183fd16227afe258d9163d9489f8010dcadd8553ba4833391252d55fc2da05f8e252e1a551f4f77664d26652c62cfb3c4f3fdf2c1f7ef2f79a2c30fea527349058451317450e19464cfec96690dfe4112cbe61fc75cd034393c45d2b10bd9af68a44a0fbcfe71cd83186a33d53cb318f5cff885ee1e4d37ce8fc0b4d4adcfdc76ff774a3d21d5d946ac20842a9eae9adc22f51ab0243f60ecbd197c1f367a2bc372ba03a066ebc3d6f23ea2e8c492eac06fe36af408ed18535a6642144c068ee67d4f397729aa32ab80258101f5ac02811800599da3ddedab3e", .None}, + {.Add, "-73079a427f7284bbfb1fa3332c40c125c0470e7cd5b8f8307fbe9408c517ccdda58bd3944dd098a1054727439901c2fecca1b8c9ac411dee0ba486f75c36bcaf24603eb675a9ea855464a7983c4d68214a5fd6463863997814da99b1a29d6898970162f221d98cfa7c5793340094f32ef3ab713391a7c687b9fc61208260b412f55d9f807f42f9d5ab515033fda0dabc149211cc41b7cb8aac769bc76d796e5241797a0177d45b2472ba0c501c59cf1c4a35d7f92be1df9a0f5eed9bdf58b8100318a91d7347478a4910978e54563b251b5b39d6a9c2b3a3693c55e2614f187c2a5c1c1e18d631783e9e51a222681cbbbc69142ac0cf7eba24e019db482f182ef2b2b37659fda240e4ce8bbbe1276b22516d830ea889afc805fd2878e3bca16b5df6b4a5f802d9988ddf5d4d7d046ac869ff7775969e60ed217b44d87268dad9c90cc42e2138aa7422e25c31446b4c7ab17eec2331179426b3904771fedff292a47503c21410cf2075d56bb70dac36f2ebe6d9ca123c3204d94c0d1eea9d114e146d292a452eeeb0c175306e12ef951cac25fa43349ae5a87650f31f3b6b5221da6e0077782b2b77a2f8b375821906daa9305e63f1605df55f2bf255e46c4c9a6d43f7cb71ba0168a3dee97672486516ab2fa6ffee570abaeb4a5066180128b08a90daa30f8d8005af55b7cc7ca19038130d07df65f694f8666e5f0224928074", "aaf511db709cc3de156dceb66aba11b6e72ab44a106dbd7bb1a28246697cee81eafb5d332daf2c79606669552fd4fc598062914bf5553b64c100c577f73d266ccc74eb434153c8aeadedf336a6d30dac691501f8f61325c071b5ac8c0179b4f42ae96834f057154a62cc09b16f0378308686b80b68e8a99d976ee36167c0ee998a1f8f0283ae9ff5d4ab5c1af8bba02dfb1b2cd0bf9f83962ce4cf34d06ac1858625aacfc8c6b8c3c9291df0b5ae7060ec76b84174055644eaa31f091fe39dea89842205936768dd6dc949b89cc5dcf1b8d4ce45386e9d16e60a03c074fca4d4f56d4a4e151e7d76a7d8b879960295c6a778a19e1997d10f4aa8ba1eebdb3fbff3d08f2014d0a6537633cc0877a64165c7c3172002d02d075a1bfa793e05e35f7404baae880c91959602f875bd49cc8d88521be37c236f69fcb2921ebb091ceb13379889b0fc1fd0290d7d1c83784d760deef89c28612d81a890f42195fc581da7b13726d6bfc00ce7a2e5324cfe85ed5c486effd6dd0cc6d8fccf75a9c9956d24509dad157e7f12d6553446234b014a6e8f35a89e94af87e9bf936aa1d89e78ac5486291da9739c61c9d3510005d2e960803f21fac0f54ffef9d2547f2ff91fa9791358e18076c2847ed75ef6fab4c8ba7f3134d7cd2db8667cbbb4d2c81004e9e2dd60de8334410727242d91877e35e4d08a3558130986266bc4a9ab08fe8a", "37ed7798f12a3f221a4e2b833e79509126e3a5cd3ab4c54b31e3ee3da46521a4456f899edfde93d85b1f421196d3395ab3c0d88249141d76b55c3e809b0669bda814ac8ccba9de2959894b9e6a85a58b1eb52bb2bdaf8c485cdb12da5edc4c5b93e80542ce7d884fe674767d6e6e850192db46d7d740e315dd728240e5603a8694c1ef82046ba620295a0be6fb1ac571e6891b047de7b80b806e336d62f1533344ac30ce50f25d9f566f11a09954a144a240e048482376aadb44316d408ae5da866b78e82020215324b8b22a486fa1cc9d79946e8eabe9737ccdadde13ad8c58cb112e2ffc484bfe693a66d7739a790aeb0f8d7358c8525525c8a043a3ac2791011ddba9bad304129165404c967ed643765594115a467d3f541ed2005a4941f4160e06089009b7fd08239b28404561c51e52a46de5850e7cdb374d4648a042114a2ad45b8fc3755c062b20eb3f0d00fb5c700c78f749995af500acaf971c658b033c3364c2aef0ec71cd797b3f524efa70619535c4a0dac1ffb0c256bf2c841f0fe37482d04f906214e003d8105b6c2dc2693b6569f9c9df736ea04b666d4c56d1e685b1a57e4824bed11fdb7deccc0eb74fe0be0960975a9fcddffe9ac3ac853c351b8d6fc67559e09fede884b24fb20f4f8a34e97622fd7b326b4ebac6e7545f5202bdcef5b43b57d16c6114e5edfdd1c38255f21c748dbffd65a786767e16", .None}, + {.Add, "-2f7b796ae92a00056ebe6c32e1f3f218a101dbc5f0808deaf6faff81fc664b6fa2769e7cd48d0cd1925d0788d772c67952e0b7431c2b49541456a46020a48cc7dab86367a65691245128f92af7fe22b822e56eb0ca34500879d47ea9b3c8bb95361a91ae1e843c72d487b9d66f676544bece2cbf71c3c78b9c45ec9c0cdc04e3ef8eee1629a2ae32069e450c4fba1ba1d3eaa7c03b8e1a567b19a67fd5963ff7c3a90f4f5505ee5d692db5604e4300387e79217dec32e70af0a6fdc98af3936f1f7804c786791643057361291aa6625d86479aaad84a22bc0014bc2dee3172f58fa0ccb5960f4ab983dfa6a66fe8c2bd0a2d6d517eaa3e935534ab746a2c8ac55401964849e944db54434a82dbed98f5b0d2056066dfa0aa6f1e8bf4d7f20b727166f5ca37694cdd08f00e1bdc76f60e587cd8ccf45dbc1b5aa593b4ba7e71fa6f02ada79cd63305ac196900939cac5f6300120c117e6b2cb55a7e4026a7b367c20411b54280f22dfadeaea0f38c32e68dc34820fb22954642ef91918e249a38b8ab8cf090941746adb851135c9ae1b7b78ee155a862c91a4bd18a39e20d4b0ca05c825da0c31121201ac468adf4dcbf99fd15f5c0686005f5245ff09190bc6f056fad70a8e82aa8d6f4d9a4b66d08c603b9ae344fa04aee9c55914d768fdfee34555d791fe1d738b5dd2c05a71c4e2c1545073efb1eae2e40242e2c3e17c678", "2647e880c46c977da159f0b22e2a1adb20092d1255a1a3a2601c892f58e9fab4bf4c88075bd3b29c061b95339fa9a20f774fbe56fc448c1eeff09288ad33e6154e17ab572c1f10e1fdb8915aaf8593ef96d7a38f6bf0460183341795dd93bff4d9b8edb04b1492d4390663359ae4eb46570335cab71b7d6c70f9b5703d7eaccce20c10fb36c1bd03747a7a19cc3204e7be555b895b834c672139f31986bdf0f481b28cdc50f746465f92f36f9f86381037587af8bf62ddf6c1a0457d19e2d7b0a98ff6940649f04ea93d4d680a217ecdaff2a36519137ef49b76be1142586780f3a01736c4d8d177327b81c1eb9e7efcc5c25008bdcf91536b663699a12801a956432a092be5bfb889b95fa7e46e1b6c5e5a1d0e0f9ad3a278e9fc30580c8fce29e9867b93fb2203b4707272aaf8c57c853bc3edbd7373ef658b5e798a8e54c1fb65d9217e24178fe3f50caad5a25faedf8f7bd21b39eb8b8b037b16539676dcffbb5b4d68d27f0d9160e1e3b8e1fea0a25eb805c4711f00e9068090d4a32b9098b498faff8693674f901feb0bec4d51cbcd092ac61bb6df522da13990668ce5ba846bd13d6e0fe31c75274aef9a948d1a72e342f8ead9b12a7fe9a441dc94aa7bec4d9bde1e5b47d4586dc1564a33432599d18f1952357f603b69911d25270cc0d77c3e18887fa4cb2357617223cb2a94c510374e7aa0aca7395e4da77de2fc", "-93390ea24bd6887cd647b80b3c9d73d80f8aeb39adeea4896de7652a37c50bae32a167578b95a358c41725537c92469db90f8ec1fe6bd35246611d77370a6b28ca0b8107a378042537067d048788ec88c0dcb215e440a06f6a06713d634fba05c61a3fdd36fa99e9b8156a0d48279fe67caf6f4baa84a1f2b4c372bcf5d58170d82dd1af2e0f12e9223caf2838816ba15954c36e00acdef59dfb3664ed84f0341f68273040ea817099ac1f0aebcc8284720a6852cd009142f06b84c7110bbbe75e80e33802f25f45c3613c11084e38fd654f745bf36a3c7649dfe1cabd90b749c00b57ed1367942516424e4844a43c0446b1d48c0daad3fe9ce74dac904891bfdbe6c3f1e038522ca89eadaf77f7d895277e8525744cd07f6348fc47fe57ba4477d6f4ea36e2ad9547f9ba9317e3091d34114df36ea482bf51a353b2ff01d38739cd4861eb21b75c8245c55bdfa4cb083709639f6447fa12a570329d3113c8ac248b667d9ae7320697dccbd3aaa3445eb64901b36b1764559e91100b9816ea81ff6f3f5910d83df5e28312850ae9465ebc1d82ae247123af9a3e90051a6be26e5d8168c6355013e03a59d1dbe5a48327f8a32b2c77d8654caa4764c4fb427c489835fd4cac9cf61029c6be36022d582de1fdca5364e156f3c1a27bc596ab8e1737de13b07595793eab9d4a434f88301807ff707aca40d8198eacfde9699e37c", .None}, + {.Sub, "6cf2291bedb2b8caae6c28c4766592959e47cbaff3648af06c5c4fe72175baa93586ff9138c877fd36b665705eabdf0db7d6fea8eba8ef0168cca47a87fb7107657e1ff44469ba7580469d85b7831dd0912ef8e46579929de5eeb143774f82a03c86d63edd67743e54c206f670662b9bcb9ccebac586b5add4b1d8460e7adfbe66ffe3e34a062e27ff14806b509a72d42a47ef88fc7be349814eb962eaf68e5ad058ce1d97c4927aaaf111f17fdea27e12fea0ecbfd97c29c3ecfa4d48644e2ff19f3a483553caee72e02815f2cbb04183f7aaf26c11eec41824faee300e6ac4be3354006245217afe7f0470d118fdba1615875ce4d32b40f3a5a55628a349992c531f1ddb66e6a49bb91834b805d7564f6ea9dd238a6e359d4939c2ad0dcb7cdf9fdf65a0a2074f6109da3bd495f68f406ac6663ca88307a8547aa57eac25ffe3179d04c3251a485ba920425e4e3d4810eb526695b8410e192914695b2e1183c277c83ebafba3fde7615fadc173d849ba09fb4e3b096638162dc81ce2e69f8e8bde8ded1150383dfed38027ada965b452ca2463cb4a1c99b4cd4244eb8b814afce2f0e4dc23152afd6eb7d1e3d0d134746623fc877434af6a0cc7ffb434259e0cd341eb5ee634b52cc5bec37f2d1468678809855fa23fa6976e1ec97158cf5f43377a270470df6c0d4469d7e6caa6d5ccd2f4c6bd17b5a0d8392582fb023a8c", "1d906cd93c741acb49024f2ff7006fe52884a03ebab0a59b85df187b82656427bf984d87229c73cf04a83ac04f3a9c026b235875253d374b5306d50783c62032a33d8466320118442783cba5c7510a603c4fb74dd85d805a45f205fa21d03ec17e1d96eec5a73e47afaeed746f1f6c6c938e6991e1476a3a6429359e2a99e8fba2a09e601baaf8caec677185cfd09da1a92015c033d9d915e64c20d0b8127940e1c92301dc708c2c430d6f2d0c2e516c1518cafcf981da8b0a28463072b8118d55bfe9ad0f8c97170289218d5b130388207062a260a2abf9d759f05700987b2e3fc18a3f236800778737c5772ae8c0dc8026853ec6a9c2c7b69501feedb429f9beb740ac901ed16a2d02ca29af13870945d4948eeae76165c199bcdcb2046703c858326f4bbbc7b38e9fcf1788a92882f9aec69474c740631c317f1921b7052ee9d384ec4816f53a57344b252d41ea5c9191a47e3e4194ea7c193e45ea4d95096abc655678ce091945a0c7ab1194506ba62d84944a6f4ddd10179a7353c3a7aa8a7592b52a4fc9bdeea9861f3c7ccde813fde9eb487893d4052a24391e40d68b6e2113420aff9349c6129179d1300831f63bedd1b491ec15f115c38f0f6af6371ce96a4f93a564de42ea00ab88c96fbf5cdd96eed4735db744bc143f5d476f0125c71c8aab4dc33cf825b082f9fea8f7d81ce8341e43519de258df5b64994e66", "4f61bc42b13e9dff6569d9947f6522b075c32b7138b3e554e67d376b9f10568175eeb20a162c042e320e2ab00f71430b4cb3a633c66bb7b615c5cf73043550d4c2409b8e1268a23158c2d1dff032137054df41968d1c12439ffcab49557f43debe693f5017c035f6a51319820146bf2f380e6528e43f4b737088a2a7e3e0f6c2c45f45832e5b355d12ad0ee580c9d5328127d9c8c8a20a339b02989232e41519ee8fab1bbb54064e67e3a2c473b05111fde5d5efc657a19eb9c4b41cd5ac3ca29bdf509b25c733d77057068897b8acb9638748500b6f42ca40cb0a972f75ef967e71c9c13edd210377473ef9a6303cdd95ef021e1e2968793d10a3573aef1f9f6d9bde714b48153a6eb64e0b08f2504d099a154e38a30ccfdbaf7ce5fb0964791747acf654e63f9bd26a0b244becce0c46bbffd1c7e142a48c22fb8c5cf520d0f94418187b0e250e0474d51d310c52eb7f59ade85776ac239d0fd62370e07c7a57bb62e8422d9ae4a1c09802afdf87de13dc76b9f09a185b06162da98f22f7e40168fb37e7006e801029fa08712c97cc3ecc3a7882d188c5afa31e0bcd4aaabf8ec1dda2d12381e1375c265812a0c9027e2a362ad2e2489978f70470a4c92f66efe9d79bcb40cfd6e9dbbe17f663a4a90aaa72968b2ee1ef52b20a8a1411605e1d705d9c59231c2f151eb954eccbfdddf4b60c929ed46402f5e046279668ec26", .None}, + {.Sub, "a456f4952d6921e419f3f69cb7a300c7a0eb222e0dee06e28cb911fbb8e49c6dd5f5cf52cf774a1a17cfd27339c8b3c55aaecc940c89911d79c36a610c846c9596db70ad0882656ecf044eab0e033f0b2d88a20afdb73374f6736f115d211819746df3537e71df7dec8121e3fc12aa94952e3e1f7368ef71c7a03490e99dbc3dc94cf746d2dde01b8661b5641099a68134704aeb7d08e4ef5738c0c53f9759c2093344a8815100b5a3413ed2ddf473716c2d71c1f43d290eb0beea252ec795fedfb3b9d1db6abeaabb1aeaca6500ef2f5a1f888cc658a7e3457f1096f81f62676da43ac622cfc89f3835aca4ceba521bebafba5803a81c4753342ef0280f629efb5582e1d05a7d8c770af1862df2d1f5ec4ab0350246b6438cfcf01be0ebb6dd565cc07d9dcca35801969a67eeff10bbf8d523ddc1fc277729c9f8c3dfb86aaf6a12cdc0556c97e3fa87cb87ac3fd03704f7a964065ad9fc73fcd29d6d5f5cb85cad2787d9f4a5faa185c9deea98990cff6f28b565f32b7e2919f3f3cfba35cc410b8d9e83468516e5234d0874cd11fba4e5215c2316e259e43e7a64cf275fb13dc050f578fd2beafa440ecfe82519c39c41e80b626948bea36611c101f73574439577b31b1076ea05f9297025719108e70d47d62c98489072f71bfe729e06acf99575959a597a519e7802e7f0be00b28c722c546d7767cd7984b5a1923e015", "f054052c53d041dda4c39770e01f237d196e0cdf174f683e26b2e42c66437802e0db395ba0d2db0cdfe6f04bb7ce59bd0477b2ef82a17c9ff2960fc84a196d9cce0f813432c08cabed39aeafd3c36bc914b6570507d750974b5e51afd08ade87af5d579c4db4da65dc83b2b9f40ea5a003bbd5a87a0ed64a2108cc481a33a944892c809f4cc9c2211f8ac1dc25a0e0421dce00f27dbeea2139336ab1b7529e679ffa0a0ef848db3f53440762ff0b75ed37482c30885fc56521ffc3e87669e344cceae08238ab7e8b83db8fe8303d6937a86f1fbef84e10fa03747a9529a69f4f46305d4c453d2a3870e68c604d806c204965ccffd2cca089d3ba16bdde4eb0b391b6e1f8a71eb29f385cf545e57c70016b74466f69e16edcee5d41edbe13523578343a9e05f612d35150461acbf2afcd4f93c725c9885fec1c67b4c06a1b6826b9951e03e8054beb1d2b7fba422710098408ceb82b9c08cd6120a0d842abdd367409654a1c7f9f6e21ab17c66235770ef9b1725b50a9ca4756e3b799d9ddbb2d3cd6006677761f0b564c6d7d41e565511c8bb5dd980864149bf30bca86876ee6105dd7e1283fc9c3724add23e187722afa9126a63d51fd86a03262d15515c5663c9a777d859f98663106bca4aac22f2d18a7c2324e83debc6898779f241ef6c2a2349d6e428797569315ee11361e2b8f26adafb737892dec007347e9e229b384", "-e60e95e300f9afbf6324580714a4f3709f5f5abc367087cffde7530caab52e3c037bdc6673db666b3e69f3248431ce80aeccc62641d8e38e1af9d922395126d374a1ca2962386655004969c522e337d861ddcce457fbdd5ffbf71abebab8cd061816786715cdbc6dfdbba09bb44d7af6ba68f1c682d84753048ec8ff0b99cd80ac97b12adf9be41f6724a685e49745da0a86fc43c5ee5bd243bfdea5635928cb7f66d5c47033cb33f90ff375d12c2eb620855514691bf2d436f3d546237d69e4deefa4e51af4d2a0d829e13b89ed5a44b2cd27362be8867bcf1c898bba24a928cf56199fe3102dae7d6331960094c6fe8aaad15a52921ec55e86d3cedbcdba89a20189ca8a190ac670ec462d829d42e20caf9b6c19bd0378b58d72ec000496c7a2ce6e962c19489dd136dc744d02bec1900674e7ed689d74a9cb15342c1fe17bc2f3f127e2ae826cdd830301c763130613b95421eb365b2d99e0d3ae6bd5e76aee3e92d19ee0550e7792bb28738bed7e29ba7fcffa4a978f7452185a9ce217d078c5478c8f41b6b9e7fa38acba989431623d63c7d5d6f5eefdaf24243994f8eafc81d2d1d0aff704c2a69c36e305208ec0cd0825872b68fab5fc01b544f6520ef861200253ee90f790a72a0da86b161c8a36edb4ebba5a33616905df3cf51657d29b4614e8e1ffb1792e6de2b7124b83fde68cf1f0b1b76f28dafc8fc905d36f", .None}, + {.Sub, "66e62cc7cc21690808bc8f83a11a712dcf333d52d87baf9e7557059473eaca1367cd29ca25d3ee8652fda3757888b028278e23926fca0e330f429a6dad03e26e2fdc1e78e1f3373dc2795f0eeaf7aa7815f1603f49bdd004dd259e21f285c0ec98ba889ead1403fc51683327a06b16d9ac7f0e819c0f660d593b13d3e897b3e163f628a1fdc5b7d71433b268f9647f96299aa3a190260c61d0485edd9975491bd525c35a2de6e958fe0e82623c68568e62a96f5e52c4e48f9c2de4e5b180858921caeee670467ae5da45c6d8ecddf8ea28f4e815f5a06f37685d4e9f83a5fefbd2bfa8a0d2cb06085eacf0ccde9885980be5631887909f4ca916a1bd983a9542ce2c24effcc33cb4cd62d12fe25ed5a381590e8c613512e1d94f4b01fbbeb12c6ac2d383154ccd468dcba4cbf39d10ad6f748b66a73e4a957a57a625d97de8f1096b796fdfd4e458674c96f9028560bba05aa4125a0c95c88a7f607902099afd5683e36a8973a06a7db9ab5a3b26ddc8205e76f02ed26ca6e17e8303755192662edf4ab76c324d0a22e3f51039c1a8ebfafed351d654b98e7cf34c881a4de91667461d0b105e3296845678a9eadd7f4b2b4b5274fe88ea7f80e4e46c4da5b55340851a6a43b84399bc469cdec9ec23e213e70121c7bad11a652ed18a3f400ac62cbbd58c1a5fb0c987fcfdf6f6dd41e58a7747c0bcaf814776bf2410947c9f37", "10f540a8a8086960bb5399bbc231212c6904febf7b7687bf735dc750f112df64db67b481a8b2014cceb678e06d4ddefad79d1d52a44ff80089b04938d345b0f2e094c31d17678f21beda95399aea5d491a930f95ae9fc89f4f4e2350c41eaa331895e5cb4e2a9981b4c3f17346b4beb136d378e4e54260bb9e47022be0bb2f549defae9cd1a225778b42fcfea26cf741dfa111bc46fbdc647c686ebd82d16217e864b9a83119bd6f3701e835a36125247ff929565c893d92ccf3b97cfc6832b32c699a4a4eaf8f11c5ca7c23a3c106513d4d1a3b64afa011bca86a400db53dad33c83dfcd4093e06bec2378ddf41a5b47fbd91b18ff49f1ab0d2c35533ebc04b74303fa06a421e8ceb1031ab6cb299a577ff83e5b8d9127fcbf4305304a5758519f2921a2953e4947912b85ab55e329312a17d35e4d4bfcb3bf188b160ce6b13d2a3bc4967e11b5b4cd58392e8f1ba9d8f18acc7eada08ac65cdfde7d5c637ce9f3c0403839c4cafc2586edc6e2d4a8bc0162bd042d1a57e5c2603938f1c135df6c6195099498f98a3d12b1ea90fc676872198f1891fa409a71b103d597b68304e16a67795d2ca7fc04c6dab7fa8c72b315295cc6193e97fb9337b585f4491ef0c7a9ebfd264890d1ff107a384d300ea2e61149a6fbb292dc2550730dff57bc27b2af18313e498031972655fdf7122b1e95c6fb994368f4ad80f07382dc6a178", "55f0ec1f2418ffa74d68f5c7dee95001662e3e935d0527df01f93e4382d7eaae8c6575487d21ed3984472a950b3ad12d4ff1063fcb7a163285925134d9be317b4f475b5bca8ba81c039ec9d5500d4d2efb5e50a99b1e07658dd77ad12e6716b98024a2d35ee96a7a9ca441b459b6582875ab959cb6cd0551baf411a807dc848cc6067a052c23925f88f0b56a56f7885449f991e5492a2ffd53dff02016a3e703ecc109b1fccd2be9c70c9a2c99073169e2b04607f63ba6fccf3a2b68b51852d5f561549c2196ebd4147b4ab5491cf298eba7cdda90f0cf25abb4e45f75f0c14e9ef76aa3fec1c8019feab93eff56dfe38c27d166f79c0031f843de68644ed4f759fbe54f92811e27e2529f8475ac3bfe09598aa6a85c00620d5b1aaef7193ba750d04168ebf8e8b214b8ec713e3ede1a5cd30e30c2698aca3e661d7478af7ddd36c7bd2677f3c8fd1a7713661993a61e1141f74a6f328d1c24b162912c43632eb747df6705d753babb613c7dccf9933c60484b1fec00c72885587f6fe6357f0838193166d2e8bd717f12c9f190b1e27573dd3a604d351584d5d83c4ac0d280e6192f76937a8b6816c40a0afe6b34b81ff9f8bca89cf500ffc7b16913ee612364340a7baa7153ba8c9c55953b451922f7e585ec8757ffa7eca2d9ca595f4a8f03b190e409067b18c66e8a9897176c1f33a11ad8072878f1fc9eb01cd866b5fdbf", .None}, + {.Sub, "b2968d3d146eb63d44e83fdf80fbc77b1cb67341d8b00f5971258e67b4fa0fa9d475a686ce3b3035945d1116c3c13dd9ee7a74efb2b60c7a65d12ed59c84d93c3f02c678031affbe38d670fd9b3195324a0750973a690eee5506f61d77e8dd91b995472d85e21391604aa0224971a2af8f573d07d32591533937abf600e3e0760ceece4aae18083d79bcdbe621f20c3925583a8cdcecd1a24b4800cf052346d98c817d11bd929cba6a630819928bc6be9c1de03ff84bf1827fbd34d0432a26d1cc419d20cb5e9a3683df3d58059da30991255a294adad0fbc53fe06bbc83c8378f8f19e172a2980da4fa5ac2745600dc5c4696990bf0ae4edc59e8713ec82b4deb88eb7a8956908d3000d4df9c9db128ecdd688ebc67456a146f290bb10bd5197aeb271874b8fff781124167753966179483101026b8297f1ff3a6daafba9f77d59d24e1cc27749353435403a1028550bf1a955d9a2dbde22c6b0a1b9cd575f2d4a7843a66f18464f67d72d6e2e5b16bce52bc41fe13c18a7ef7be56ca0ec583fe3bd36a571af65c1be4dfa2d94c52e43ca70f425ca3135590afd5edffa811738e44c8ebd2c4ced2c9423397b8886935efc3df014f680ffd54c7fc882f4d75a8ddc8626d54f159e3bb7010cfe5fa13f4279dc42a2295a0d5e1cef8a237af762bd363f316008e68dbbf1af55e05a0d717f805f63b148f1ec7a2d077446d296a9f", "36ebbfd490b2b4fad3d33a3781f6c441b1b3ba1c88cf8b90102ba8458c90d7e876d5b77b115efe8cc18c231bb5a46901c4238d6fc854e8a0e49c0ff40b90dd61651cbc64953a4c52f37fb36171d2c85745aa6de4a4c2b1a1db08c45ba1f34d70cd7f7a15abd78f35b8c978bba8d3b1424ad2ee75657ba84d829a1a61c78b9b4cfb217231ff6b269e4d93c9bd0ce264d251a541ab33d321b60a4b9d5cd3b067758b6525a4397fc40e297798fb3a542cff986333ae7d2482619bfb14b6acf3275aa2ef45ff9b8a9b4b20c7808e692fec627a07950c60e70964a3ec96cfe32269c87ce691c4c1b95be633f9b7dcbbbb406c4965f99e6141b40d6f8fb70623658fe5f2e15baac1b1a0dd230edc3db2c46c69c4f1a18c1bb66d97d60c782fe2289cb6c1155fceb7f4de4412fa15d78466c93ca06cb54b8edc0163923b7ebff12bcfa9e99c713302493bf0697a35e620d004a05efc83a5415ba9da33fe6e8f4e757a541606851a1403e0c36f13c4ddf320d19ef822593a0ba2afd8916528a7d5629e20b847d874b5e2fe1b401416bca64f219c2981012ae71c89ad252fd550426e53c7f86d7fd5822dba05bf17e5a6886af453e5d33a810a4ea0347f151fe60b954c5ae8b7f28542ff60fea5a0a701010aea136ef81cc7d0e5d5cadaec3d63ce601b3e0af6b27452475b08b75ed2cd736955e0e8a8430cca7e03c540797e5021ee178d", "7baacd6883bc0142711505a7ff0503396b02b9254fe083c960f9e622286937c15d9fef0bbcdc31a8d2d0edfb0e1cd4d82a56e77fea6123d981351ee190f3fbdad9e60a136de0b36b4556bd9c295eccdb045ce2b295a65d4c79fe31c1d5f59020ec15cd17da0a845ba7812766a09df16d44844e926da9e905b69d91943958452911cd5c18aeace19f2c291229150fa766d3b2f8e1a919afec40fc63723172df64011c576d8412d8ac40eb6f1e583799bf03baac917b276f20e3c220199636ff77295257212fd3feeb6317bcc99c6db6a7171dc51ce9f3c7972153499bd9615e6f12a8881cb0e93c277100a2e5b89ac07012e09cfaaaaefa416cca316b1b629b67f8a78fcfc7a4efb00cf1f8a1e9d944bf27ebc702a0b0d7d23e62b0dbcee33862b9d5c749bcc421b36e182b8ff0d29cdaf4165ac497dc281b8db8281abe8ecfcdec00b3aec9de38a2e9c91e1d803280b0601e11b858d21407f86c9b8c4e5ffb9ebea0ff2052eda3a18769adf8efc4dfccd6306307f27111b1ed9295aef4ac276345f3faf5a137f840dbd0c8e632fd314813260e17758689a86b80009dbd39bdab95d74916509714cd0a2a4df1301d74e209f0a48045196fc8d5b2dca223b8294df5106fe811f1f8e515cf69cee4ef29e0b8a5a76251afcb0b06e2bb3e694f5aedc86d40a1ae470dd307bc2290923781370f5db32e4a111b026256f8f44b3b5312", .None}, + {.Sub, "-69754fe6445ae268980e1fd38b16ea3336af4704b438e11d33953e8483ab94e44270fa7331df78d171dfc2f3a65dea51fb973326e01224dc94a925fee403c00dbd75e28269160dc0e5f30af7bbcb89b0b1ba0a1c19cbaaf627cd69ce4b50cfb78a3d59bf6620c989c73d1d1a1ccb952fe704902686856c28b04a2961aad12fd972f032a7a3e7ae886408e85fbe2d5207b667b92c8dcbe2434091b2533a7463e6c901bbb10e087a1d6eb74df15b8aa898274e19f3072359d7e77998d3e37085f051ea36607653e108391a8f172847d4b5c088a854429c663531da72cfc9111653b4fb360f7a8bbdcd54d471d3e3bdfde799a0c67281333f43a004ee86ee31928045d4b5eee97f2dd0ac2dc6e8ad9d4ac76eacfd46b58d09da911f587f6c10d6c618acbbdc7d120cfd39ac9a2e30298935c809f297bd325bd01f1c65524fb8f9238209c01dc97631d6dea481eca1a7e1069f5ec7e342ca0f0ac0a63c348c8db57bda61e6ff2b0d8b7560eaecd2ded2b7291214bbe73dfd72de7c84feca9ad23888874128daab198f425cccff10ff35996faf3182a0c1036f495a3411aa1455b142bd4ae2202ad21622420e7d7d27816d7b631a572b88fb790e03bb28c62595ddc5311084e15ae8eceff18f7b432626a230b28674af48ce6efcd8b3679b15e65c369a4f82213e652720ece507fafc6cbdcfe834791ed161835a9a40a4ecd6409fef", "2f183edf65f4281e8aa2e7311a283232b2f8b176cca9b515c7ad4e4910ddbd6ca05e4be7b9d4ddd6b2c241b8f2be79323370a4f8fc516f086fa6817865f9cb38777e7f8d6ab66ea65d41c5c35da903322288ea98d0a7416798bea223bc6366559bba4441a457cfd533f295be6f56093ef3ee19b7684a25825e1f1658bc96beaac8790cd46ded175d63eda2764b65bc80592f77acad06331bcc3fee596ad7ba2c7ecf8fa25c9b858da4aebbaafea4bc82d679473ff1e78cee724445d6d5b9814d50dbf865e48f4165d188ae73eeb2ea196959ca9905b896492087b91b9ce50514e97f2194eccb8cb2ee6975473f51f5b2d04407a65cfab462f546430c990134ce9fa28ac45f2788de7ed35d898c057d46a93900a53c946ee4df6263b7d76d0602d75de24d56a1825b4c117464088828da23f60961ee46b1a206e89598056ff17e6c1fb1712942b1026c24f250410763cc93bc5b632277f2268fac3a5d85dec7fa13713e9eb39680bcc25a32e6bec03a3ca00924ddf9295fb5aada783152494acaa5b73d80e9c37ccb5f6fb87d331a4db4b908de4ab47cffa8be4ddd718a92c595c9973dfc0ef563f45cd67f101e36b16f165a88f108afc2ae3f25e941eef587b5a9e1e61b4bd3e79b8bc37658fc5d3d8ab238e1807eb995c5ef9aaa8aae1cffdfc9b94fed31faa9072217ed2408f5e2ee4fdee61953674592be93d1fe0f6cf8ca", "-988d8ec5aa4f0a8722b10704a53f1c65e9a7f87b80e29632fb428ccd94895250e2cf465aebb456a824a204ac991c63842f07d81fdc6393e5044fa77749fd8b4634f4620fd3cc7c674334d0bb19748ce2d442f4b4ea72ec5dc08c0bf207b4360d25f79e010a78995efb2fb2d88c219e6edaf2a9ddeecf91ab0e693fba6767ee843b693f7c11d4c5e5c7f68ad609930e880f9730d93ad2155f0cd1a0aca54c1e1347d14b536aa3ffab1366099c5a2f651afdc76132f90ae6c659bddeaab92a073da2c62ec65ae3226e0aa33d8b16fabecf29e272ed4854fc7e52622beb65f61b689e7a57a467574a80433de71b230ff39a69e4ce18de2df3a6954b31938732c74ee57740b348a6b6af2b01247239a2c80e17e5fdebf22178bf7081bc37437ddcc8f00a9e29d3b38f5885be0e9238b1b20febfffbf9ab790d722604faea5528eaa1ee29718ef2b8e2d94ac9743ce2af44d3331b23466542013150527692126c7d75edd3259ddea40c3223451fb99d92f165b21de0c53726d294275f76fbed1b83532cf8665b94dd0c0dbc3cb78e324fe724683a60eb75806ef21881ef1b9ee876d886e2201c39c77a169ee4fc8d45b81eea7974e01c91ab3bbc42e11208148b657adaf26afca6bcd48b7d52f19c2283dfbb64bf562fc78804c2c84e1225c4035c166408d20e705fd0280efcf51f0562a0be38135f3824c8c8ed58d476eae5ad98b9", .None}, + {.Sub, "-b666e2d9f03d80293c3cb449b8c13452755049eaa52b518c1179d26b9d27d88252dd29daa174deee7588e25e23182de5bdd929957c5055c5ec6f84349fa60f9430deedcaf06e791be13c75de4fd4c1eb9ed39e39596d0db06c664e9385978d7fb43b691a58cc9bbe1441ff42bb24e0c8f742d9280e9f6dea2ee2a0fa8dbb86eb81d88c4de312f74f4a86424d5ff776e289ab429d8e5d94fcadd6bec33f89a7808f73226dd566063114e9a83ad37f21d375d44a5bc06369f853a3eb476a1c95df9c43f9c7bab53879aa727564ccde3e91e0e125eef2d0d7f6b5fd739a098d241563650441c707d10a78d9d13d2df31d24728970c531ec500d4097710d50e533765016c66bd91d91bc2edf8375fc074b24b2383d5f61352ff27de45ffb5f38d5113d01f32324200b493263da3236f53b991b01d3cdb653a0e07acf0fe1eb7053a863239d483f1f959a9cd6260b174ff72cdf9dfb848c6c08045c90de349d91650b401718702c06fb4f5f564f4a5b8594094984ab2217eecbd06f35e53a5aa899b72506f11ba99376ca7b31c512c4fcea3de70bfee12240d25a1c74126ffbe9d24a2a62dc4d2b75d8632034758e9541d2d3cc6c0c5ef6e12542890e8c015ddc7313fe59e95db4afa880dbb1e1ad2c4cf6b1ba28d25442af1ea6e09e5fc928ff8c4f7903e208f9b3c375da5b3ce453600fda89af33530c25cfdb97c0294825e4d65", "5d0b94a91b7c92085665b7ce8514e52d6b554fe39f1a8340352cfe1aa5d3f4c6f2aa2fa487f9c349bc88d8c1de884c1497549cc737928fe00415f9dea5021786a2d4e770655a2c56fdcfd3b5ac6b592053f7e9d650ac587571df157ea2bdf39e5f30577f73b90fb7704b77e4b705d200040da80bea3ffe52c2b0b6885d4b30b61a8d1e46ad894bb09cb2948673d112d297b2c7b6e8382c190497f9975275a9c543ae2d47fe3698d702824d0792035f815ec73386fc8f01801137817931a92003c73cfc02edeb34841ef674356831b0d5223406e55d8c6b6422b66a48cb2476800777f6f71049050eb40b781a3297c45c0d651c6226b22a190a31547316c88f58bf538b0a0c1652a7e9625ddcec24336b5777abecde804d2c5b275630ba4c386cec44f3f2514f552c7b70cec70ff16db377a6f8e175d0a9a25b12d2e0f33ae86462e72abdc3289bf205f52af28ba395d94629762d8dea6aa2264af033c51517aa6db9fba6ee4b03dc97e22988909ae4923da3d68d1242b72f74fc8fba94180ef9dca15701452b41654c4e15d8cfb088da2b8bb326f2f971dabb602542f236301b7cb1bb2dec06c5cba40ec4c5f99d4a9b8a987c7c289bad96568c389567e552eb4dc961e86d4fbdfa0c8404974706d833c10968c3fa5d3493839a2055bf76751cf9486ff607529b4d5f3ac5a438f7a3224d864e0bd26e9c372c2c396ebce64287", "-687202d6ba806a0aea29831320a0f87292aa5482496d3858f6449b415fa6724f17d8024232111138a3e166e7c0b9cef2f3322f608f57953c62dcf221eefc787fe5e2d64d146113e8bbe39b139168a53f0de523b9e643295078a57a67db176c765a740e111945d973518f97d8e2b8200c9381d59e6b29f531659ee0980626e924d2aaa70b8bba7b25915af8ab49d08a40c04d7be0c11e0568cf756583866e443d4ca55f6edb8cf93a13d0e78b3f3b519e9624782cb895381f9671c02da84ae961c1013b9f6996880bb99d9b8bb4ff94be404219444cb978e38e1641826bbd48c15dae473b2cb9821f5b99152e0576f62e548db36e79d0ef19de3acb83ebd6e2902454f770c9a82bc3ac5056144be4a81da29b2fc2d493a02b83059c30703fc5be00151324839155e10e970c6a3360c16d0957161e5135e3b062bfc3df11f1ed9ee9196492471a954bafc28d533d18954c142355e5d6b12b226c13fe170eee2dfb21bb6d2df10b73918dd78e7d36533dd2d23c213f33c1a3ec7befee0e39c298954ef1c612ffc478d1f4013229fc00577e09fc7315051d7f005d276669f1f4cd401f57e8f2bebe2351d6120c1ee2f167c8c75f3d421809bfea7f1d21557dc31a1c8daf007e489ab8821a3f22b219cba79edcabf5e93e88267df1a4065252066de1f0d8ae1696edd784bce079727e2da41ff62141410330f934e5a83c033f448fec", .None}, + {.Sub, "-cfaac95ec1b3f53197ba2e440510ea5d294a37c166027de625bf927592961303e6185a85cff5cd139c47967b55e20fab318bfca6aa91253e0359cc117719658620531d8febf2ad862da3f00217d2481e795d057fd22c5bc12be470279236c43cecec538b0df0fd30a4cea23c6664bff353727d81e685f5a8a131f10049fc3a868c47c00441b4d8a4c8df33c74b232aa3483a565714d2676bfeecc7d2c077caff4eb9e5405c77158dc9836449a979fe275e811e9397762e9ffa96fbe00e248c99329eaed5c72b903869a1416dcd0937fc5db9e042b50c5e9023ec7fa33bb79cd2e047d507102b1a82ec4adc59a1a2cbdb0dd12a2670e1a2cc3744265fc32b46906873075dacf5ffbd49f154e4ed4a801002b16a7afee310e7a3279e0a8647f9e4cfc11ba8d53b7a7c9e3b8797887cf4c7dc9ee5583430b29ef7edcb5164c7151b0f76523165d38ab17bd136b6e43fe209c0ed181b724071cd9450879dacb621f9cbfd84bfeb7b7f7a75e66eb0892dc89454a3d18774ca100aa826c3678ab274cda595d0f038af277f85cc84af47a8ca33c696a72f8fa77c894596c05be23de27f5f23dcf7d017d127c783d167bf3b2d97c4946494b0d26dfab06e72ad90df32e7fbc6603f80956bea3fc90a2aa48a1d77aac32dedaecb5632530a7db6a69cd8ebe2e8ba1a013a22dd034ef59b1779f777e4e6599507c4b44bc08e3a8ecf5d860a", "bb6df4a412e5b6d30063cc63b91026de38118e403ac0d561e9518c9d1af5ca29e47fb565588db18ce0f80d4222355bc652081d74134e0a0e3e08709fe2ab28e0808e3c8e01514c5f2d96e8a9cd68ec0fa5b424f67bed068a94e7260af6d881fe17f7b0410a10787893a28370d9e26f3bb708dd74b838a13a44da338d8b0be38bad062b5781a9ae50d5f0d074a5561442c34805bd56ea340dad75f34b8ccee6769e67c7194dd00dc4d5321fe46acfac4b2d6ccb72bf83ce7cf91576480a5bb7b0f3e0ddab1be51777b4d57c50b8564841a7780211e5b3a75907fde4b3cea7d0468cb0b1759a0a2474146699a3b0bed95f8c6b852c0447581333b1394592ee802207abba985288b84cc300dd1af00726e4f3b726e5c58be8766d9fb151707a815dc090565da5b4e58470a7be4bff92a8946693e7d5740b93caf56d7c11daf9517c60bf87af8705cdea905f603dd06f6abd3a70ffbe6b0dc5453b6620a59601d7ced602eb64fa1cbb76364ed2e3a9b24cfd4edeec61ec569705ef3603661e08e1a1ef6e99f707620527400b6ee76fb7dd86b28077de985a4e3cfa38402fde51c64702fc4a54363020d0a7fe0a2700df025d201e94b97dcd1276428ebb12512622bdf140b04ba05a71d725cdf9b1f1348933cbc5432aaa4570a94ca7249e2d8988a7bf1a8e8cfb3931ce4e7868d4bff8e76a85d5923f6bdf696e3cb3f45add24c8c4", "-18b18be02d499ac04981dfaa7be21113b615bc601a0c353480f111f12ad8bdd2dca980feb28837ea07d3fa3bd78176b7183941a1abddf2f4c41623cb159c48e66a0e15a1ded43f9e55b3ad8abe53b342e1f112a764e19624bc0cb9632890f463b04e403cc180175a9387125ad40472f2f0a7b5af69ebe96e2e60c248dd5081e12394deb5bc35e86f59ed0043bf0793ee60b825c146bbc9b79ac62bb1e4d46b175ed21ac59aa4723529eb5842e1449aa728bedea0656f9fd1cf3ac72281880444a267f8c80e310a7b01e76bdbe855f803e0531e2549ac005e92bea64570a5f6d196cf8867caa353ef700b175fd5261a53a9a3caf527528fadf6af55fa55619c6b2701ec1f5ff7eb80a0cf231ffdd51a6f4f6689160c46ef95e10c74f5bf6c27b42905172067af060010ee345e3880f9d5c4332cd2da83c4669ed5b47633fc066977035d9e0ecd9589c0c3096f4b4af4cc6fb5e17d9dd4e3712cfb6a84342b7f9c8a2007024e5983af0ac35419432e01591a382bde96120a710975cc6cda8bb566f95046ae740112ca6c5d7f396b760a7ba79171f0e2801cac63fcf008bc08fa8c66220274c0647f1f86f81db8ec01a2ff4e4b2f94e2e9f8070f2fd2dbfe20555a5ed07108b20efddc1659703dc95bea6ab768871185910c6db9fb1a254d4266193a20348a6fc7354ab51c75e6fd772dee26abbebd473a41db9fd422ee9ac824ece", .None}, + {.Sub, "cfd08aa075190852eccb163e3cf54c657f98749aa2e4a5c5036afc75f3d3a804b63283e9893fd0cd18bf0d6459b4cdb8e58d70341bfd8b102dff861c92ac0d9770ac387477283ae3fe010d3825cbd1197650d55e6634ac622de856e11317ec047a3ea4bfec4b38615f36272e5476fc20f3c7cf4c7990ad82b1678f1ed0037422e7ac01e0b07ec3af29da68e4029181cf79f22e7cbad7e57b284006463e0828137b4b33b14f8c7a5527ab19daadae8c185be84493ea3cbfcfe8b2942f10ec93da27ef108ab974e85e469be9da54a02e52f39fcffb48be21dace5b5f9d78a84788b3ce5b8e617fb12ed850fc76fd5d3f7d72366ffb1920779bac7959e42965682580412c72426deb3ccc3374c5a872a24b327caf5ee0e4e421cba18401431abdac5739cbea25e494571760885b6ccff6f5a97db1cadf07c7f32005b189f81504443fc0656f697953e3aa3e127a54009e46db7352efca5bc6e5a8caf237a0ac611f51200ca8a85d9566555eb5e548c04a5b934ae12e5a04c1324fd9e17dcf67963dc4d5536f15be20385ced60782191298934aafdd0aa7312f14eaa2ef5071ef25e1cad73a93516f6cd6cb269f7280215f1cbab6eb5254ef4f4379a81d248f1814f08f49aa1aec5e5435f53def01704943b7618cf12408753d14e5e29f7b9b68a990a59d4192c4056fc46b835903e2dbd0d0c52c30505f5844901d30ecc054d0e8", "46ea30ba87127398d5bbf698d7ae646d8cc8a2159a843eee2e288d65d695204100ab2b9d4f254dfa83c2ebb3cd9c21696d1c3b1d6c9e225cc5deb1c8455206cfd9410975a3e7392569183a6b0af2dabf9e86fbdb860d19800990b46cc44d9e091183e2e65ea3c73a9f6c87ae929970608b888e971ff2b4bf84ec5616ce873464e08ae6857502a705ec7e8a50f6089cef621a1b5fe8e5691a667c2aef52aa375384d367bcb7d48c978ea1fa9bedf2b121cf11780ee34b144fa468e8148cfa95af0229f2b3ed73c707b3e65b7423f163afdd3c8a0882f5dd0ba4a5df3c367b965ec9eff28938a49ca62f28d01ea4b5ac9ecb99e7cf4a6eb6d90e550d60fc4e4d824fb92496a574c70e5aa4a095ab4ad8b4235dd22d81e8aeabece8230181c2e70c64560fc9f8d1934aabbe9a566d174b5401fe26cbfef5975696c40e951593013c47dc93aaada7d74bf8dcc020c17d9b1e54933b61754af0e6c989f59c2eeec81ba14a479870db91260bde0dd469a62d49cf24e4a191958c9ce59836712e712e6f41564a480e15fbb17c46955934b4263d03abf89eab79546577c7ca7f27214c2900942f6c1d61098bc222b38aaf7d9e7ce1981f8f8574d58fff44ebac87844e1b40ba5ea7fde621f2fccc8b3d3a4560b11f51422d587f42fa72a51db65aad2a301762458eb21e4e32eb5f47127e3ba0ac703bf572a45654efa5b1e9b8f3d65e3c", "-39ed28107fc0e313a6ef4534f3df0fa734cf1acbf055f491ddf1dd9e7757e5c0b548035eb69150edb236fadd8800d48ddec3641a2ade49abc2feb9667c2745f6623645ee5c74b5772938299788961dae0721ee859fa9ceb9e6b22efeb31c1f48c9dff89a5fdf13b48979253bad52009e7c4c11a25859a9e759d5dd24e186fd22b210266769fabacaf9e0e3c2b5df84d26a7af8781d37eac2b3f82a8aeec9b4d24d1eb481a2dbc4f23c2748fe4317c8604952f3c5a4a74852a5ddbed19bebcc715fab01ab41dc7881cf7c9cd67ea760caae028d08ce69faedf7c029425ef111e63eb30cd0528ca19341a3c05734dfd8a6f47680cf98dcaf5f538d77c2b9b7f6fff7b511cf814de85a8de1694950c3ae8f7036073793da6069d02e0ac16d913b319ee2730b56734a053a4891d0b64a4be4a7664baf51051ad764c3b37c7611b0f803e08d53b710420dbe38def91c3d9139e6dc063278a534786efd4678b4e40209ac3846cde655b7cfa6882276151a28a415f0368eabf54089c09a9859517ab50b6508f5111cba19adf677bf51b29b13a4706148c1a0d2233662dd278fd6af5d031ec958318a0f9a1eeb578ceb3cfd7d1dc4dd68a4331fe640bbcb438f62f53606502b14fde2f9c39ec6d74d4e38d5176d67efb53c3476cdbd5dbf3b16df11c18686bca84d1f5a48c326f3c3b97a58c4db9f76c94253f6fcab1594b8cc33818d54", .None}, + {.Sub, "-40a229173fc1bcfa139c5162e6fcb528a0df8300a1454463244601c9b400cc0759e7e29be5d8cda74899c957e732ae854997baae1331fd104c69e24fc818ddf8d7b60fb84b4cae8c252b049749daaad0ea824768799dc9e7541ca898c18aa976ef01614ab3b3ce302f626043f50cb8e541742fb6f4e0ad5a08344e81f23ad2840ae13e801f705b595632e6b30ff5003ed695743dc41b02f5d002b3e256c7207f4c8f74355a1bc95491dae8462497fb816892ebae8cc3ef4f1cfeab0e895322134365ec2250f3fe4a10f9839bc139447451a3e1080c0ccff847747fa878bdb89e197f6b8ab4488e371d3e660a5a088c5736317ed8881811ea30e748851e61013776071fc75b0dc11bd195163fd46bbeee5fec6b29fbcad5b22c90a02366f2e348f4ac2ae6d93d647f42e8a8f5ec567a53f6bd843ac1121fcc6faa7a4017305b05f716ee5a8dc90a12b1487d1315439a37c2e0011056d3c9f01b9b09b5318e527fb2da15134a5f83916f1f2330f9e6bd4e15e603f242b08b68d31783f657490773f38e63f122e8d953fad05769514ab07c375c580d929ea52e26a586d5281177b839338bfea1801cc9a7028770647dc81ee3d94543941dbdf48ea40db2a46415ef3c1b90e1eba8f0f3d2dcc6a7fc090ee73a150a06b46bb074eeb77e69fb58053ef0b8d0aaa227fc66a1f1ed199b862e6e5073bd85e753df1d0a28f089fb4e3edc", "5c0890333522d07f94b4b2af585be709fd786b007ac2a95defc110d53dfdd9df437e9862d30469f724aa4ee572a330e970bcecbe4fdcb122ec838178fd6b1acb4ba85233fe745c42f374173e917076926de94547875343c406ecbb0285dbc2c1b60d6ea8dc19a08f8530a644bfb14e2d81ac4ee4180d110eadb5c48fd1ddc6506e323ce96c8242f86d79959781ae97fb8f075e3edecb882a171d145954cafdc11eafa09f5b58bd7e75bacff96aeda24f5563df433de2049bb6e8fc3878d41824625dfb81a4be2f6d177d6ce568c3f7d9856fa90399ea6fabebfcce890b6d6feed5f9141f57ad4b5de34d690d767e556ce8e8d859e5a661cd1629e191bcb092a1794b1ccb1608419c3134feb7203dab44eee132aefb2ef2309d26b58852aeaee909177e92524398c9403208ef15cb64c3677a68be52c4fbe1ae2d5a4ac36e59ecee2beb93cc9538f5b0d2b6a8717525560d5fa15661029b5602b3ea4e80b990365206871945e5b2c90b8f820cb7de9297b78fa8d9914f347ef067c6005f159e40caade5d377a92dafbed1860722412977c8252f3611e38565d2182b050a4e401a56bcbdcd77d0c1a5f05529c7a9d4058d7d019fa8ddd6123a5975952f2744e2706799e3bc3de3c39e0ab80a0124140797c79584116718f1146db5ee10353591d70e5ed67bfa70f84001bda8ab18c67a1bbc6ebece5d36f76100771b251b73362", "-4662b21a7313ea020ce79c8ddc82739940b709b0a8f16ef9034212d707e0a9a54e1fcc2213091446bae46e463e5ce193e0a38979f82fc8227b321a6757ef8fa58c7094db8b33f4505462460b32f1b23a1160dbbcf212fe23948b7448e9e865a30a6238354175683927b56aa84107cdc8198ef4a536617e6af30faacaef58aee911c4624eb6387f88dd0a800c880fe9be8f85ea21b207bb7871748527ec13d05b5e7a6e3f4fd1552c79369545bb46d5a65de929a2c0a20f98d86d3ad210e06395898bcbda6b3fe140e2715a6a17c583f1e9fadb9845ab76f306344c9109748f9d06defccca9c362ecfb733c9b317071ae04c00c5e267278070249e69e3a2c0a618d9bd1940c6e453594a8662b466f99a2aeda7e54eb7dc4d536630b7bec1dce37853da2cffe619e0bd6ebc984ddb330a02d352ac6a63e6f8a8a8d4fe4c36740a4c5f9ad13ca925da20c55a87d9c5aec8d23b5fb25bce3f3a57bc6485a1999eb8317fa7d84debddebdffd81b51c564a677915efe7fdbc57eb0c21e00565d3a61580039424e5a636c2ef6bd6fc9c36ec313b3deab00f3bcdd8483c7098578b65bb9de9f57db78fd28e40607da0cdf1b0877bba95f3e21fb1f18343b670596d8641642952f1daf872d2db38847480e4a4f60b68e6247cadd3f863592dd4afeab5e5c619ebe1261cf0beaa20dc7a44d1296100c3aa972cd274e931a30623c4d05723e", .None}, + {.Sub, "3d8c6ea0f3c87958ab7c29e5909953497f85c1648cdc2152987acb1d0fe5b4f20c3df942b29e59addec17dc56c4569436d3824bd898fb03bd4c3968fc6cad2de8ecbd960a67c1181a72bf9a1303b86a0911f9f7da6dae5d9d2725b44357ee2bb6abe02efbe080e051da9ec56312c72932e3054c0ccd76c82a7e3f6050ed254c281e3801fc3fb84dad01cb347e3cbeb9b1a54a261a3de67b6a307e6577a68b2b649c06674e3eecff599a2053aea7db160bbf312cf8d3c1adc618d3163d38950726a0e42461ce44ce66ffc7c2a344b02a5b7a1025d80dff4d43bf66692bf8271675158b938505d4cb95ec997aa9ac9ea3513eb260a050fdd08e45dc419e01d17de4fee14839250b021578934934aa1000d667abb5d858e4f4e8eb9ca3ea874ac07d3a3a345fa5f7bb2a4d317e37234bc1229dae2cd8513c1ecfdd9f2b0d7613ee5f75b00df05e54955eb99b769d694f2fc51b7da997d948c54cb7d7d39a1861f078825eb35a6889b380dbdb0468616ec99d1d1e255f608e35f86b0516773fe7b3e01511413aea6fa2bb26c475fdb8a850a46300be5ca86b694fcb6bb21c208e3e0351fcd340238833458cba8f74403b6d0dfd6ad2e17780a0cd3c48b7ad8958ad2f419e54d0008f601b9550f2dc215f1cf1249831b699a1bd2c8f0a1b1b0ca090a23beb991e1e3e82ba5d4e517daa600af09d0d2ef7565c9631c62d04737e7fcce", "3d19039f0f32f405929093bf00cd761512ac8e2ac6aad96c9ca8ed08c741a5b1d423bf77d8a9c295ace3c9b6befb2f54dc6ca0593942223cfd176aed24c151eb926c5526f662fd090d0ab9e27d49c7bd6c458070c57dfc1935984fd7aa055ce961478016616fb283e02df4df4fd9bc22e255b9472db45e0d87efea975e863354e959b5542235c41f0ba78db6de29cb89b131a9ea593e398a0102e6632227d66e8c4096f2f94e67feda106346965d49046acd3822776f6c260a1a22dce8aefeaef0a61689ad7cc5638ae4609e3543de9a384fddda49612bc06867e41512bdb50e714dabbfa6c96603ea054be9298d5843efd1e2ca362a65486bf7c93984440c7a6470868a3dab9f488f97e5800fc95d548802f7c1ac8980f50badb411d4c042df9e28d21ba87610bb20b7f0138e3325d6563100121fad7b63ac75f77a685049170f5e8a26b81dacff58020bfe9165ade369859b0a3ed31b9c6a5c59b57496dc16f46ea06b9ec2f48c2142c6e07e1cefccab1a058ce6faf3846c60110b7576c197f9d691290d59e024f66a07f2f9b38366878cff278c2dc156895ccd3f4948dc3f7398aa086257d0bbb2d7d3b9b0adc2e382b70556263fbba311ab7caae96bfeeb0a87cc7445d36756079749a6b4edb394f695b8c01982dcafac03a6ed71f42152d4b03729157178e14ce8f64342a21d05b32dcb6290730fe8c3d0211cdb2e9f51", "736b01e495855318eb96268fcbdd346cd93339c63147e5fbd1de1448a40f40381a39cad9f4971831ddb40ead4a39ee90cb8464504d8dfed7ac2ba2a20980f2fc5f8439b01914789a213fbeb2f1bee324da1f0ce15ce9c09cda0b6c8b7985d2097682d95c985b813d7bf776e152b6704bda9b799f230e751ff40b6db04c216d9889cacba1c5c0bbc475259105a220116922f8774aa02e2ca204fff45840dc47bd7fcf81eaa067f6bf91a1f45420685c5125daad15ccaeb657730e86eada51c379682bbc6f678782e5181b8bff07240b7f512483377ec913d38e827dacc4bc58e00b0d78a993e6b574c44bc1713c91f12419433fcee577c07865fae05bd90b63eb7d8df954a510d8c7f14f133ad7a2b8de77c39bd904ce59830c162cd3b46928357ad12a51e96af7841b27cfe401963bd3a9e2bb656646895163fb366f10f5cee7fc76b84dc79c569397ab6b452f4518e8323f8f3ec170b8612123842cef42f093b74aca07c5a6abec7ae96607f9fccd26b7dcc90f0defdb1a50405bfe87b9a6077a82eaa14d1a06bc023f6ce1d701a3bea30cbe3e58f53e7359ede278c007a0c187232b9fe0b278a5f3d53d9355f3ed5d1fa7d7f1384e69c2190ecfef298be7e99218d8ba358eabb1bdc5870d283e3a1bb3ca5b50173f231cecfac43ed5e7b74f0e8268cc726f4a58ebeed49803e3a956a3078ce4f2b97a5892af2a5cb95d7d", .None}, + {.Sub, "-f47554d6a46881514702be5d3271221b9e10af36bbc7ff28874c8c9de6c8442761be58526daf5c2e469bc34f0898ff169aa640572597c0cacf352b5b2643b93d14dba3b25c48cd0565c58ad172ee6d24c99ef4381714cd4f6a60209f68af61d6c6defc9a4505fa3feb46ff5b3058c446da7f727d52f8bb0b33eeb2686371ae006c3d61f5e48636dac65f11c163308f61846640891b1cf11a92826c6123ad5b1b95b4146e5bdad8af1af28202828afd5ea7b5532416434b831c7c56ad48fef28107e16cbe694d6b9f95229648472ea8b113ecbb035d4c369043f24f671b7358c059b66f1501979d453c190fa85850d56fc50766eadd07633b351f07f9f5379d0173d7554eae21fce81d665cca8ca9ebcc4692ffa8658a7c409efbd13282b225617aed34f59c2578d031caaf32741ad86fac37424e13481f420b9609574a8ba89c12543becaf244e6dc1fd8ecddcd5fa19adcb6dede82f12e28eaed8ffff08da7d2e71bd9c6083295a5d18118e8b6a25b2278731ebecc1ba3027eb66078729b58e51d2cefd573746277a05f8ba446b09c6ac4602ec516a5f37529788c7a03eb0886e91b34c74b9e7b5919838460aaf27a487189674a68077f49c15c8d1c226d1fc919302016dde304ec65abb7c99fec873010cfccea1731d97d5988fb6859da11fb0bfaeb87e7fe5926ee91e85ca8467f8a3f761c148e3e91af17529274afe85f8", "c09385e054945f4d626475a567d8b3df58900bba5b5338e892c3e2bb1e58c314dae7be79c559c8cd99d48c70ed8edea383dcd42061d98b2216f720d811418b6b1249897515ec9ad3beb51d4ac6cc9c49b89e4d72f9b845138c5328c2714a7d73a5dd389a237a7fa2b8d590f54e7703938272485f3cc46230b4cf19ca98cc96db3ce5ecd8eac988c8fef62e7fe38b70a5540a8a953b84da88bbb191e31efcd7de7553ffeb31bfbaef7509cb8ae29e24116e181c1b2967982856ccee5fabe8f350c8154a12d7b868d3af2d1f7a07215d0db1404e8fbc6d205bbc855351f7a2a0b2ff2c47ec3a76c4b5c1364dcb56dd3e355915af2914beaef94ffbeb9ab6b1d148d9a42be51c5379df91009b384b17f8fb868ee00543cdc038b44b2d9e1ee6589fcec7934fa8b4f00836cd24bb79b2fa4289b92a814681ede7e9cae9293bb570e0b3feea88823468282ec93f2627f377bc07de49e13afad44070ad2025789f44376e5104f2512bced14357a595a7b651cdd626afff23d5ddd4910ebed973085a8e973967d098d5827b23d14b7171090042179e30ea3d65f2ba3fce9f73da37427a4ddb37ecec1ab7984b2b0d1ef5e47c31e5081e3e982863295e5ae43ba18d3f6b69d37194d73dedef1e52f66e2bcad9d82c6d941abb0ca987e0a0ce9e985a8074e17c903417ba9908800a1a8ad749cac83e4d29e06e933aae83947df0f437fb24", "-1b508dab6f8fce09ea96734029a49d5faf6a0baf1171b38111a106f590521073c3ca616cc330924fbe0704fbff627ddba1e83147787714bece62c4c33378544a827252d27723567d9247aa81c39bb096e823d41ab10cd1262f6b34961d9f9df4a6cbc3534688079e2a41c90507ecfc7da5cf1badc8fbd1d3be8bdcc32fc3e44dba9234ececf4fbfa3c555404146bc0006d870cb1e56a1cba34e33fe4442aa32fa0b0814598d9a939e8ffc4d8d6529217015cd6f3f3faae3ab7349450cf4e7e5d1cff6b6d14105d473444fb5c24e5005bec52d099319b956ec0077a2b91315f97358e2b7013c0e61fafd4f5d73af2e13a51e1d1613f1c61234851af394abe96e4a4d7b8133ca7576c7ae66f802d7c1e4c7cd21dfada9583c795346fed0a1987e0149b4c84544da68d86897d3ededcdd2b235f06ccf59ca0d29f560f2808641197cc65326753158b695f0c6cdf404c971d5b5a9b7cf2329e722ff5bf92577a81eb49cc2c28eb1aef82ba06fb7243320777ffdade1eb10979804b8fa24e0fa32101ce90c36cdf00cc8a29dd7442bb5740a08c3e433d68ed051f19266283b7a75f302bc6ceb3960d49f4ddcc345650093a3d66c20b4b33ea8db1dfa70ad0d63b41167fb667396451c1e3de4adb1eac5c9a24b2d7a90e95c7fc71fb6395e551df82194923c3eec963a7e9aeef33910a1ce32c0e2448ba1b77723c97509a7183f36811c", .None}, + {.Sub, "1cf4a39b239ef3f8018007d2724a52f669bca50dc5545b2f4ff0e804083899682413f22a67e1319eb4301f137c709d795f84ba62611fbe9a55db5aa8a95f1b1dd5a0bb9dee0efc05a5ffd18f724d70cdf4f18989899bfea76cec623c6fb303efa143e056c5c26da022c3735333a3714eb5894219babca64595e7249167b562689ca5ca5e24e14c86bdf572849b20e858772c07e0abc93f6df35276e2e41174af2555e547dac26aa4b896f34c7a9932d54fbf757ec1d08f0d13359e19e8edbaa1aebb66a72e254e42c4a7082d67d09dc9a78e39b01724b4a6187fbe605e89238633eac0dbf4eac1027e0be37eec82791df8dacaf4e9b9568258e27ab555f89d4d469769df338d766bdf4bd66ecb5b4f0e4ccba820ade5fecd1d4a7b7f35fe1bbbc759b5e1944e897d633d2f008b1595be6909288817ba0626b3ffda7ac04c145dcab43b336335d4de01e5d60176dbe98568e1452cf1b7761aec2240c2ea9d033975cc68f5bfe6f1dae3ef2fd7015a3507939b38958068a041aba80f279ba15890d08a3aacccfb226fc203b484bd5d1a08530d85b5d8fe92178b76a82c59f4d96eaaabb671e1dc1ca9e68f51f510239a31ef2428810984f94e1ebca9f12e268d56a0fe201f1d6f5ac93b0e4ce88cb819ac007e717df74a990860635336c8bab3fef0478249fec211b4b814fb0797453fbf592099d3e9607ceec16e2b407185323b", "1eabac5af458b8082cd2459c0be4662242ea7f3469500d713a3607ff42dc77e4ae21faca820cfa98cc624a656e99c1c9d48d6d632e76d48a18d6a387094621132ad5d424eca73e2f893832d0efecf1235ba8a5d8ef9434123e02de1dcf771bab6b684c7cfd9f8de2b9a46438d5364441be9c6fe2428b300f1716d2c030aa863d85787336cb9f50cf28b6d91a31fafae258b2e455658e768f1d92f9e3e00ddfc52563d4c405a942d8c57627aa802920c995a2ac0c09c9f6807516619c1c21d70741e1d29e79cd1520b18060d6e99714734c16f36a8b9e22b0f14f6bf47fc6de80499bf73cc1692093ed17337dc375ab9905066ab0fbf0241e9f807c8c21a92050b093fd04bcc63649cee67cab117f36f9e9cd95e4cc8511b8df930e119e8c78600257c8e4e4c3c9a8c4366348cb68ea93a6a42f0c7c68344cdfb10fb5f249dc1afd44363b6b59261937e4d8a9a8e3bc380b7724734536f26ee88ca45a3b45f5e032bb220ea7d8bc4319a430f5d068fd53d4b1cb7d92c0f99e98898023bdd1fdb5cb4ed96efb3374402c263f54013fb86e9da0a1d568c80ed685c04bdcd56b421beba88c247dd64cbadc68913fb13b2ea1ed46ffbc80ea1d9812aa42a99b4be3eb215789b4d4bb1bda65641a950c4f0a6c72375fb9de413e87cfd33971c086add6ce8852a7898c57c3e98eaed24a1b38f96b5542ed62e45d07121e5d743c718a5d", "-1b708bfd0b9c4102b523dc9999a132bd92dda26a3fbb241ea451ffb3aa3de7c8a0e08a01a2bc8fa18322b51f22924507508b300cd5715efc2fb48de5fe705f555351886fe984229e33861417d9f805566b71c4f65f8356ad1167be15fc417bbca246c2637dd204296e0f0e5a192d2f309132dc887ce89c9812fae2ec8f523d4e8d2a8d8a6be04486ac1669596da1289e186dc74b9c537212a408300fbfc6b16000def7c2ae6d8340cdf345e058fedf445e3368d47f9677361e0c38233341c6593266bf74ba7c6ddecd958a981c676a9a488b9ba74796e0ad8cfad94213dbafa15b13660cc7e5f916f0b4ffed6f3327b0c2b9fbc1236cd9c469e01d6cbb0830369fc93258938bfddef9aa63c4623e7eb9d01edc41e9f12ebc2489292688e5ca43afe13035075402b60f93448405354d53d9b068464ae2e262bb1353b31fdc7bd328ffb080823513b35ff02a83207d2b2a295df46537f7c53fc6a639750a8f2a6bceeb918e7f1ca6835b5011ecf0ec84c411692e81258595cece170fc2230a524fac49ec22e3851d06a228acf43e29e664a931c1f8fc97cbefa49a3b07b7668ad40fcd5b29bfa3010f5d93f4aa117946ffe22d73b77652449f3ed98b86d25569480596995b74bc1112a55cdac7f96f0c071b8ee3be6f6a57f6f6fe63af7cbf9d7de40d05d8aca460f3179b3cab2d5f93a1234a9197983e01850b03233caec5822", .None}, + {.Sub, "-dfef9871b6d106a1eeaad28f2773e99be7b87cf7b410bedc72d680db2bfd4ce4f4d10748f3c38623da1c14bd21ce36329e0d30f3bc658b1c82d6d3b8fe0379c638b94b5d16eda9fc7d9ef3a7876e45feda6f9db98d5397cf7fc6368fff637e9dfbe9db99edb255c9c6961d8d448c8b8ff94ff0c016da456ec181d2cc71c0419519e303a6e69659a290056a263ff220960746be6bd54099f9f3e8cbe89cc7995261cb355e3af77dbdb925f006502074fc56a59dc95f26b52a24fc98892cceee4a8d78c3ca9e643d2a8c312d7408525728e519b994d3a1a44af5981119f3d7389aa092ca7be43cefa76824a0f45e0a39bcc38f6988eafe98349a424bf3ecd27f49948619238df0e319945ae775022b1313110b38600229fbf69482c2ccb0c539d781f7ae988c61fd742f00349dd0010cfc9eb42a4ed2a25b7b6c0c1359b83decdeaadb1f085ffeb0a0f47a257805cd1fc63ba5eac0680137b7502d9efd8f2a52378aa0d21b875d48fa53a7505cfe2caf2f7de797449eecac0d557238be12afd45acd32c0da59bd6c12609ff4d584665f1ce3ac4f6f83ab31f71c3cb6b03df6aa40d513314d7d8614ee19785e610f31631d02adebea23bf25309e0da024b3c4f9c1ea6c241592e9c93c2f287a91ebbe89b592ba946e26c24a04f114a545554ba1757295e3a685508e12d80947c1bb15732296583092e992b66fc3429e55fdc61cbc", "c0f556ed79dc37ea8a19c335670ef1153fa791df10279c32cac9a33077a3bbfe8f034bf435815667ff43654bf45e528412f01a75584c1deae0017e11a0c78b89dba1e7c0f4d122f9f4f2164ad6b1f5edb794d14e6ab5ea18d4c2ed0a732e8abedc90174dd0198470d9abf0e1cf968d43eb150dd63b9b57f81e001ecde6bc89d4d0fd239865210928a7c1e5bdca13f489f2f9c3ef85c1a17d5d7ec286609aed66fca288e31067802eaf79059430daf9667e6bb5c2d44c9e8cc63c6d1f8d3ab684995a558aaa2c7ae156c364d81f69d14bd9f23940133974017705adfbb9d69f926a6f1bfeb7693e8074d91e8f08ee8acfc63aac2b18e8c1d6f67df7da142ccce6adf3b6f31ff321c64fc3629a32f1f0338c99c8c15a8808e8fd8d9d2a4dda713df606f07d3d3bff662adebdf242b4998238d85142af7d079ed059c906898980bedd48405e3d3cd06b43b7e7e82bfd845823e98c8e0a8d9aeca9986c6c1ebbd1f0101d359516afb8b04c8f2324553b265ef4da240ec18c92a5f73344804873a0e8a9b8446cf694ce3de28e071f3bac30b8e85c0e14ebc33242e0f4e81465e5b415115f9c647c69f64cd908f2931976f663818dbed0aef8d99883d3402031bf12905833f012e0f2bb2a670dfbc2c7331ca79d1430f5e8aedbb5d641c22314ea8087089510459d2260f196ef99be5f40b879116ba2f06bf302070b8e7d72133ee12", "-ebfeede08e6eca20974c6ec27de4d8ad3bb2f615a513389f9f831b0e337788a4ddc13c08371b9b8a5a104b11e1141b5adf3c329b11ea4cfb30d6eb9a180ff27ed67369d9263abc2c1cee150c34d9655db5e8eace73fef6710d126560a6966749e9b2dd0ecab3ee10d430dc9b6185f4643801419d7a93faee4361d4b9502c0a3266f2d5e06ce86a351a8188821c935fdea6765aaacd9cb411c9c0b81102d14828d1955dec6bfdf5c0a41d805f932e2492be8c59258c6b7f12f1605f5b25a299b2d70e6923490704d8a19d63c18a48f43da2b8dd28d4d53b8b0d086bf9af74a293c739bc3bcfb3838f6f7232dd4e992269bff3144b9c8d245209aa2b718e154c17ff655492bff01535f9571d9ea55a321649d4d4ec17d27c85245b9c9f55a2e0eb61581da06035bd6a91ae207cf42c5694c241af62fd9a2bf55911afea20d684ea98afa30e43d27da7a8b5a3f6888cf80bbde4838948aa11661ac725c451160f568ba2a574d8c844855870428f438061956d3539858b057537b4e56d0617370e6957ce45212926b8f63ec8d5477821222872321050d267651b4a4c05318455058226292b13c54cb452e708ed8a40c8d2833ac6c7d72eaeb2ca264ad426b6e0eaeaefef6316c0f8f4eed5995a4e1831bb800c8bd77d854d37c04e78c167869a497de31f34aadf22b421f178415da1097eaa276eeac1f051e69033fb862d1efa0ace", .None}, + {.Sub, "-66ab9f307de190346d051b2ec9dc6da6d761764231ab487b609a42e664a6fbd1a7846dc8efea1099e6f355c493f7875f014610c63d1c94a04b67dfd21f543a8cd439141d50e6456d70cdd2c40f8f5ab1fa50a1c33215c00273b2b8945c9782f13af3fe7530a14a1cd8e5e9f410594a49ae49790630bc7f5e5377a41087428882fa23c2e3d6e65fb4a679e84b12208063c538dfef6f043376036f1b18a4cbf947d173309fb49ef6e9dd7ff5c7f8cbb432ca025ab3aff9b77630772bbf96c301d52ca94a993a3be652909b9be7051906a9c1950295761f624dcdc169ae09540a1f6d50e6c627bf90f365fdb6431207b97585ca240a1a2752ecf000f552fd3f5904b10bf08e141e5dfd8f90f73103088073f838452874a881a846a360450dad7398f2fa067adb64feeb413c130caa38caae50ba5e5e16ead193b4523c392932d7affa4e40b0533db90009b2b9c3ef2247fd9727a0fa50d60075872c72d23aa6fc79909446c0d42a8cf57864e1768d5600ab08ef32f586d42c024d2e823070ab9e024d4941a585a2acd45f1c1fa62c1dffee8821299f92acf38fa7f738ee8f260ccb1fd2b1c294bcdfe06e921c8e44b20907ddcb34771c9bfdfddb37ed366416906d4242b22c3671efcd71bb8d3acccca6201f2e88994a427ce47c15e4c0ba02997ba5add189ca6d92fa123a6fc9d7cbc58e1d8a7e2fdda7d7795cbf8757df200882", "9fa771031aef20a4956456e981dcc85ba16c216c61a33ae3154f2ce0b30a6f712b8e8500417782b002733b0a1931bc1e49be019dcdd5423fffbe086f40f2b2c8414e2abca5f1227ad03a3b3b303535f0e11e2fb7ae3f6c06537397bdd866f100de034146c910cc3ab34dee120749d99d5cc0775acfc0b0bc4e35f279307405630c5ecce96294edec036b508d5d88305953db1025619f36b8b9184c915631b349a879495b476189cd0ca0ba0145167e34860026cf6ffa4e3c13fa7a05442b6bc43bc82fdf83d51209a39c273bb88aeb0a0ac772e2a40fdd1d6eff86f2886feaaf790b43b03488c21a55dde390de3e6321634e56f3bb696f391823a7c52fa8480ee0af9391f640a9994b28cb4070a5743367cb9c9c320cd944adceee3fa5b2c5b0533298f8cf434f4022e99b4ae3b4f61cf2fc8b06b424b3b335f7f3db4ae9ae20b17f9c7ab4f20f4343c61b35fc3d9a9f30649174aad3eeab4255a646137d08aace2f6fa4424de2be99056557448d8066a7c52be97f9e50f0e89aeb8f9aea76f48a1d871bda3b6173c272a43a46bcb74abf472daea805774eab1885e4c166340233053b24737e516c6a85a0e2150bd934f3d57688e1ce00008d051161c9deb0a5a33b350fb76faa422bde470e7b2916d1c61479de45404a72493a7cab89a0782a9ef53e52bf0da13d44166611d3c2274fc80f8e14d1b74672792f9ffe27c48f04", "-10653103398d0b0d9026972184bb9360278cd97ae934e835e75e96fc717b16b42d312f2c931619349e96690cead29437d4b0412640af1d6e04b25e8416046ed5515873ed9f6d767e841080dff3fc490a2db6ed17ae0552c08c726505234fe73f218f73fbbf9b216578c33d80617a323e70b09f061007d301aa1ad9689b7b68de606828fcd397b4da0a9e538d86fa8b0bd1913f014d0a36a2ebc8767a9fafdac9179ec79fafc0080b6ea20afc93de23267500281831ff405b24471a5c4daee6d9968717a78be10f85c3437c322bda3f1b3cc5c75781a2f3f6b3cc0f0a091c3f4cee65c2a765c48530dbbdb99d3f0461c96e9187afdd590c22608249d182ce7a11391bb84200a5f0796dab9c27173adf4a76003e1c4a6b55aecf4724e84b3603949462c9f73aaa84e2b6425ae578dedc0cb43b6e964cb0f8546ea4a3014741c85d0abcddd2b082fc8434d78d4f9eb5fe29cc78c326efba9ef20c98219184e2405245ec3b66516786fb4116a46cdd1e38111b0b45edf06727cf335c96dc00b9614f6d766c8c15fde0e48218ec3e072dab7394768574e3ab26ade530fbed3508c40cd52d7ece7083b314cd917bd7059bde23cd1a0aafffe69fdfe683cfe982df54112e57de73bede19a0f9d99d44947f5bcf1e54302778f82c756c550616c43a311a644a30fdc897b34375650d5dbab8decdde59a0c44af5f1debd5ef275606e49786", .None}, + {.Sub, "49ac5d5774fd3c67e29900dde42823dca05519d91fc24364663eb02e6287e84cdb54d4ef378944845e2cbc3ceefce023f3fd52ffa6bebcb03ea570e7669651bf43dcfce5983698d33b94466d9064460b64495e59a76fc3c575c8d3934cbb04936aac8f34b6675369867651e5dd7542f2ce25a42d80472353500e7c1af71fa92025a4833a970e4c7896e7d7879c2b7660112720b439f53254943a4379e005b51c66b6105ab82d8204232d42f9bc2cb1ba287eae7bf71ec9a2bb932c72912fc8807a38eee52e0c48ea65200c8b6f51f6afd02a7d7807f703233794ea05d9ce420ef3e7ba58864d49061d0119229c7f5f233aae21888b75033a1bb99c555577092ac9207308a0f5db87fbda0592ef2db3191557ed3dbf5cbeca0bcfc4c586670c778d92304e47a1b40cb97eb353497848795bec7977f88b19b34bb4a6af2970bda08fa5ed785ee55dc0af0d266ff93f786313c2f7bc805eaa3f3440815409089b83fb594432b4517b95b2f1092716060ea8fc01da36b838bf97436b82c8042f7ae6b46e1887dd0386f1f26ff2c4998602d8f0cb3c02aeebcb58ef2c72581355457725a8369a7f7594ce4052e08dadb138ed5ac74f15649afd44e8972e96bdf0a1778f12c8f4f6de3e509e850d0c6268140bf658448b55426b683e0dae4230b0fc97405b83fa0df4d4c075a36e34bc544ebab066b49f68657061b11bb577da036c04", "2a32b079498e9a32b101a684c67334c84a15c2c03e9dce48832bbbbbe8cf3e5d2b2b94417f33c50ae359d0b067079d00dafe02d553be6a1e0118e3a6a97d644cb9632b4edec435d12757d4823a469a453835d3c95f4096cd05dbf80e0e9cb82e6c46d3a9fb60d7668d1550686a8e004c89c061bf03fa70753cf82ae09efb2d9e74fb6f4f49799313fd6313cef4d226b5c5629045c78111d52bd51ccd837cfd63cf9ae524a994518cd7473d834d3d43f174d56b545636d812d5fb87efcdfd0e71ce1100f93fcb1567a8b22ad411fe78d25fefb2b9fe53584b9d306fa997158e1c4d73d28232c0f661aa46a128789442b72631d7eedb5682140897f70a4d4dfb083c35a43dff147a838552334bb35785bb10adbacf18fb7e293eddeffeee515947041c5579d80b330f117e337639961aca907ef774309d7a2db24cd85368c0821b15338ee17571bc26d877edb26642c52ef0f8a1095fe8af8f5d3451a42eee2ca832292d05fcb4a86533c2eb3407c25ce105b85a8621c5ca4ac5836147445e093668be66fd67c512216403ee0d427b69a8cde07d36216561e3e09e8e8c6c74b0ed0b54d4489d4fea6841aa70957b60b0de7a7c2cc0cc3ae355f8e9c3bbec9e0f3205739d500ad4521dbf8270b3ae820c9bc7eaa4fbb0ab666adffa80b822f3c418ae1e72e9c169761e1e6665f27663c1179543188efb7c09eed31b1e666d34844a", "1f79acde2b6ea23531975a591db4ef14563f5718e124751be312f47279b8a9efb02940adb8557f797ad2eb8c87f5432318ff502a530052923d8c8d40bd18ed728a79d196b9726302143c71eb561dabc62c138a90482f2cf86fecdb853e1e4c64fe65bb8abb067c02f961017d72e742a64465426e7c4cb2de1316513a58247b81b0a913eb4d94b9649984c3b8a7594faa4bc4906e7274207f686526ac5c88b7b8971b2b360e9930774be605766eef6dc8b3a94327a0e7f18fe597a482c332ba0eac27edebee413382bc6de1b75d537ddd703acabe09a3aad79a647a5c42b8b3f2a673e7d6538c52a472ba77fa23eb1c6c147c4999b01e81261321a54b08290e228ceacecaa1e161047687d2473bd62d5e04aa326ea66140a0ccf1d4c69815b3308975dad46f9680fda8007fdd0fe22daecb6d8203c7ed9f859967ce5bc0b03b857a725e96e973a199d69538bd92fcb33422ca56b32075faafd70c2fafda1a6edbc930172cb79cd3307f2e1df30e43b1c7f6497fb09672f54c7de82180bfd171b04bafb18a753e74d08e6c04b7570a993022eabecc8d8669750e8de3cba6e0948a1a536251e225aa65fea86ff83250880ee04b2254986019eeefad6adad1529245899f2ba4ec09ec32df029c58b3e607702e6d9f8fa49704fd5e132d8a0dbd387e923d11104c8b5ea2573d084245f08da31b239c106ce96672de0097116ccee7ba", .None}, + {.Sub, "-bb0cd04edad39f1954aaf1d5fd35106e6b74defa572b92eb9cb2bccbcc4e77778e4781662f23e949e1bcf92cdbc3a60b10124d1818d542d674f4b2e6ba6f529d5ab125a1b10273f14939ee73f6671701caafc9afa14ec3c1b6eafebd6eb011a31c5ea070ad7380ca3b7df54fe5077624929fe8dc38159286ba4791e2b4092718da879526246665f9f61314267ac95ec78747cb4e4036ecacfdb590b8552772150f945727de1c3c0b0703a827ecf9dc94925606717ec620b0c77aa6880471558c96f49aa258c814ededd0ac4e2257004fe861fd3ba67e546f574170519dc61980bed9f28e0f653d21e5280419e470e35a1851f04a852d1d9ff570b38d5d36e1aebfb48a8eb41eb25aa13479790558a26dd90f4dfedd1521d3633045cbea3e4b77af8bc3ab216efdb9cfaf683b34274c00c4162450d6881b2ef1d106530e72780178931a15f73a98e68435e99ab36cef54e4f63a643a1ae7faa2df5242cbb455e117987ac0db02161f42f29b8642048c70937390e781756e4c194eccf748a3de90e85a03559b7e89b2ea0a62e8b4c37bd0e8d8493da6938e933136778e9b2b840ab6d9a1459cfcb332c783a99e0a9a3cde2193631c3554d0f58520f3088304b50384da9b03cec43ed22373be5044697ebaea4de69a9177d7e0f1b85c3331329ae87686e2a04d841abab561f27f22671fbcf63d4b1d82aa222bdd63fb444afcd086", "59232fddfb0f7f2677ed8a3d814c9e1e560a8d91a0b6acf45ec2cad66f31aca5ed9a5f64d60bb8e7c452e5e07459cb22b377b97d630b1442d667e5f1aaf282b688a0aa8d09c1d0f73ed4e45c70c635864a16d1f5b15d6d3b1af463ad8e0a018223f2a9d375613d51f6f9fd1b7014bce2a2824281c8d0ca05449b5e4d5096799b456e4c732c582cffdcb1d8185a3364e503e527bcb01f051499c76203bc510e775f2c5ef3f79c04001be0ec3bdaa8ef80d2d02893db2e9f50a28353ad53aca8e3ffa6e4791827135d4168659e8ed89e5237539d291bdd6d4741db470cfec1a0a70edbfb3919938947fa5dc664f1f84b5b6c1b042b35766cf634c7beacdbe3879cb7bada3d5c6e33639a6a8447f15e97962cd403ab201199983d79b3e613ea19d4de0ccf60afe02b1063140f1a70db9ef9ccce8d0d30f22095c63465511fa994ab6ee4955dbd986c03912301251b9f1e137ac61abd56e9089ff708f9d1691a94845cef4c4906a4de9ecc8a2ec88d1e53db01832fbac118f3711f78d280650bd61d93db22848fa0b4a7ba1cb918050fce5a8ceabd54a9906b167e297026dfd0b06ea659c5bf7561f3813db364b71fc6b4f2f5cdca8ead6c7647d9afe40d9b70b370790f942d6e3b6f35f9080e64224b3e2b80aae75fe9df2911a3dccd57044fff03ce0eb99855e9a03218d9077163e7502e983d3fbbd7738cedac3e03b5c40876c3", "-11430002cd5e31e3fcc987c137e81ae8cc17f6c8bf7e23fdffb7587a23b80241d7be1e0cb052fa231a60fdf0d501d712dc38a06957be057194b5c98d86561d553e351d02ebac444e8880ed2d0672d4c8814c69ba552ac30fcd1df626afcba132540514a4422d4be1c3277f26b551c330735222b5e00e65c8bfee2f030049fa0b41ff5e19950be92f9d2c4ec3ed4fcc3ac8b2cf30af055f1c1977cf2bc1178808c6ec0b61bd5b8400b22e49463c7a2cc1565262f0559f4c00169fdfa35581dfe70969b7f1b70ef284b2f3911ecb12f9ea21fb59a64c25bc1b6991cb75e9c87ba27cdb5edc728f8c669df85ca7ed6692eb5846cf475baa38a962a38723a391a694b776f64cc108ce5be3b9efdc0f6b73a0405e351a9fd26bb6ba0a9f9b1fe28654c8d98930bd14f28ca32c37755a502eafa90e4b15e077a3bc4b8056ba42e1c0cace777af73b4d304ea1558eabfcf0c0d685fbc55219103f09a99e84c1434ceea657487c709e1a6f4be0f7cca4ecf22e04b94f6c0a2428e61bd38c79f77adafb4ae7c3525da2b1f3e5aa4271c00b9d34a2b75c306925023f9a9af5fe7b57afc34795d336705125ea6b405370e552a60f1d117612daae2c1473d5ed0d7161e756873fdea2f313cffae081c7bccb466b4bce66af8cdfa7b5700f29595298a358299ec44959c38a36dbaecce3af9f0864e6feb8e7a8ad95a1daf1989a1fefa0f054749", .None}, + {.Sub, "e0eff9ac67ec9d0b2171bf8659c7c06a1d6b96e847884a046cb1d0de4204a2d5d71204da36b7f37579f462c3d81041838293ad9306df1b98caca3f3e011d0fa523f49419bd6215c3d57cdf6e8e9ed5a95e0bc5d0726c5329761fd2869d811236e5873bd3c178f91ed70997bc962b5f50bb14f6805c8dacc2cf871dbc72cff5425ff18f3dbd1976125d56dbfa22ae0301f562bc6ed2014f219365473c30117c34c24864c1645e32c3de57c1de4bcfad895355c7fce0ebb809cbaae88530cb5df4c5389ce34180553807f91c2f40145dab2ac6b6c2af2cd4bfaf49014d2b8ddc532bd22774fc129a7f7d9a2c1e8de96269f2a38e9b385af3ef446417d683a3fe9db4a877917c190b7952f442aa0a03aeab3daf6ec05a7d8d107f546424661f45ff4d11aad2a124893b926847881d57c101559d7a0c34412a0f4f0a2a1f40c700035eafa8e949ecbc84b652561da9cc3e098035061283f5aaa549f6c8bcd6f4f267d481c792fea81572014e1b0ccf92aa5d87a3a3afe07b7df87218bb1f605941837ea1fb6f366f5fe43fb6d243d82366b36109a47e580df4a9ecc914fce430755c9677aa29ef708be91396191df7a484b3c3ec4bfe4dd83df61bf5067bb3687c32f149e69c82c36bab67bcc6906d255459807ed779a5aa0a931d31c70c8ca166addcce1ff767252d704731c5613af045fbf5d10beeea9e292ae9a1b0f8a306ad54", "9c20483e6c4b19d529719394938a18c769815e11795937783adf4b28d0517046259874ea84ff38fc461cefe53afa5544b0fcf4dd82c3ab3b84f560fe1a9587b6de2b21c458042d914dae374d356a49ef8e37b70ce2726483363913fff859c501f8e590923a6a413746783da8d5d480a74ac1e1cf2174208550a6788c57837ff356d14443170b8abe3ff5407d742c57450636a54f991d31e453570b57d6a604a37576ba78a1c7854bd5363c012c767964ed7bda6c8e0e24f812414b016edcd42ce7a4b0da56c9c196e6363d53dc2ba7697756a09fc9d604f8bcedd21751c323f6a92c8b44bf65928427823b56ac2f2d94ac9d8b566edc0ac4d3264052a0fd775f03164e60f4425a63d4926c4d843d8a989b1b1b4c2da1d2c5b87b1b0c2d030b765ffd8c35422aaaed6d95828495c57177a7c871e6895d22f59efcff011851c6ba66ead1f86a023889d56ad29db6129a9caef25bfef1d8bc633988e3e6104063af41867692529a76e03ab2f2db1c8591817477dc60d9bfbdfc75b88edd6cb0f478112233c4b203e8c7619eafb48b116837e1faa91047cd812ecab480e81bec2f1d5e921460719b8d8fb7e23370d88b75a00635d14ddc145972e93673d512707e1ea186c22952128357b058f6ba3fc5db531942c24309372286af12f2841b0e94b60f4fb9c265fe3a0dfb6b66b17f8e2b90aab261819e3018b0f14c816d47c1974", "d72df5288127eb6dcedaa64d108f1edda6d381072ff2b68ce903dc2bb4ff8bd174b87d8b8e67ffe5b59293c584609c2f3783de452eb2e0e5127ae92e1f73b729b611e1fd77e1d2eac0a1fbf9bb48310a65284a5fa4452ce142bc41469dfb75e6c5f8e2ca9dd2550b62a213e208ce17464668d8636a766aba7a7cb633ad57bd432a847af98ba8bd66795787f24b6b3d8da4ff5219d86f7c034e2fd686b2a71bea8af0f919da41ba6f21045e1e390845f3047e0a56180ad5ba4a86d3d519dd90b1f6be51d59c13b91e9995b85a0251a33493514cb8b28f7470237a242bb671aa13c13f5ec0b01c41573b22086923266f90a7d9b5e5d16d3342f731b3d159942727c47712ab6cd4e5d315ab1be531bfd601b3fdbd0b97a36fe423ccb273a34f1547e711d20f4d01de8cbb8eef5fd3fb69e9db20f2edcbab57dff51a5a2f2f41e397b840fbc9c34c98fc18fba8f3ce6b145fb545e05294d81edf165e3a7e75f0ec2ce0696029d97e6e03fda2ebdf1dca5145705c25e9d2df8218aabd3231898e323bfd8fd832eb4f2157c99ce7488f72502fe2e9f9ed53911c97001dccee6271b26ac08e88e3e856d3101817f5e6ea1bcd59c388eee97016f85eed619f3e6241745107317a79eda24375ecb73724c928f6a44eeaab557516986ab24097e44af07d627bd9245b40c549cf677b0ef622f76342eb25e5d6d0bb279fda8ce8e1ce8a93e0", .None}, + {.Sub, "-da301b1d0027f699329165124ed8ca8402f899350de52460d47478b2ad38518c69c6aba8445a14be95f03c87a73a0f1c5a1437f06f5cb3b1484736eb81494c7d55887f6c6c39dc277db9751356b136675c195696796b2d5012d820d80cf0a03dfd85f203ddea5d3d73f1e1cdf291be61273fb387321134b54dcb0bfde5a29a991ae584bac11bcbe4113f7494c9fc68ae2f3e3d0fab9acb4f7e0135182b57342e33d8a1860b05c3f7898bdb75973bdfdc940700549956f18460571093b0c7e34203d436c307d0f5a3c484a82f24590175c69da5a9a505b4083b07bf7374852e5393aa2d79027cc93d4d16ac929e08caa6a1ad6efa2b7b54af1d8423da4288b1440f8278e8fa8a8668a83284e2ce42ea577da0137936161ed9fd818b273fca8bd8fd8323fe181616cfec20bb7830a6ed843677d391dd214ca1b7da36999e2a77d97ab6c04681d3f41368e308043afe8572b10666924fbde24fa9030818cdfb26134b5facb7dd6bab62b93ddac365c0b38cca3d25a3ab40fe27b6ee64b9bee35c6da08a664b07f21661db27944b8054a0278d374678bb97a16f102d6da7e50024be04166c901e47cda1a1035c24ac4f9b90b11bc29cf410292680efda440cf59c555224758e48e355b4faf338fd66731d47d6b373523d151f2877a91a93970a922f0e62ea4981e2c2f6e03830f32b3d9a79ee556ca15ccc7713b0a06b001833a9c9", "200492eec73958992318002a4f2c8ad0435a109aec8a61ce62ba6cbbb0d3def8dd8c0360b6f17a0381e311ca7c0f59f02e9dbc81f54cdc1a0e7abf50066740159d6d36a642561adbd3d6eb81218f02cc9ee2a3ddf45a13cf9d5cb512d58d0d28d3e957de1a8b13f7093f48a04fec33e0ea35eb643fff4dae3f17081bafcbe393cbc714a359732d12aafb31703a2e4432858d665d4cdc1159deb28503563949e3007192e931cc3e1a9144589ed734f684bb47060cea6c59b8b7d4ab64e216b1fa2f3abf53b96dc9fcc7740f4616e048bac9121eef6ddf9c53a00e7a4ff75799268a0f4f0c4d9e1607ccbb89f3bd88a013bd917895a93dd7967a4776cb7790a4c81f67df3f2af3cb1473e43ecb521ee9d0549057a1a6ab25ce31d9332dbe64dafb2d1c6f52a7b1ee34e4470b8e0be5cd7eafd1b3c4e901562001d0236d902f1ce7dc5dcbbfd9bdec174b80283ae02b6a08343d0a15c6e4b107667e7987ae30fde725a7802a49e3525c2f6ec6dfbefdf1fb018b2d8e9aaec1f7748efebaf2a7a17b74a252a39f45324ce36aca2fe27c3e466a6476b45b827c06938d8885ed6d84de01390f2a033c34b0e26fe57a67e552000e5e1799e97daa0ddb09a2a35bad75e70190a3264c2716270b3a240ad118582a9ed0b6c2dcd14eaead6bdff261f8bb042b6b96149301518f54acc685bee96513bfd4f87bf4b86f2209b63faacd6f1f2", "-dc30644bec9b8c22c4c2e514f3cb9331072e3a3ebcadca7dbaa01f7e68458f7bf79f6bde4fc92c5ece0e6da44efb04bb5cfe13b88eb18172e92ee2e081afc07eaf5f52d6d05f3dd53af6e3cb68ca2694260780d458b0ce8d0cadec293a4971108ac48781bf930e7ce485d657f790819f35e3123d7611299031bc7c7fa09f58d257a1f604f6b2feb53bef27abcd9f4cf15797137580688c651bec5d6860bac8cc63dfbab49e2287d932a020ff84af2f44dfbb70b567fdb71febd45b49fee94e61a6c7e2b84367d24390fbe92385c70601732ec7989be3adcd7508a71873faa7e5fc4b2269c756aa9dc9e26531d9e154a7dd868683860f322885289b46fa01bb909178f6dced39c319ef70c8cf8364d8f482e918f35080d136e09f1e5a1bb0d988b054eaf3429135b33a652c3111654a5c2174eece2bb16203b7f738d0772d69a7f87c9d027f6fd2d4dd9b0a87e9013c13344a3733ac2c2d601f6aefb148de35f1bdba24ba8209e0887c34c73161b092ac7a55d87c94ebea472e3754a56e0dd68557d48b7541e66986a95e40ee7e7c640bf3dd8de4014fc92f7966463043d6fd0be429fd82be7b90ecaf2a5a7c52cdf0b0b201a41692a803c75ea0746e42b073b3c23d7fc0ada5c7176ba6db3e1384a2ca80a07ebe6ae23413627fd892bd2a1ddf5119a3aacb12d80fd582fd5b872c30cb2a52bc291c17fe05d13bcefac50a9bbb", .None}, + {.Sub, "-d26953349b43ec19e5c990688798f7b7ab4f8ae8c9358cf648e48d4038fda351314347230372c29c11ce744509e72080dc9b6d9f3c3200dd100eb7b90d41523cb7c05647fe9e57fb09233b4fffaabeae2e7bdf7fa57f02c20fd22bc2bd920a945fb61fcca9c840b9593bb101b8b6e19a44c1e10e267b929871d2329c3ee3c5bec2ed5ee749f848448a030ed2bebcf74987bf56623d1ebc7492dfca5bdbaf2741a689fc02f7bb712848340d9c893deaca4ebad9be91823ab94e24e6054b6f91bcb7b5fc24d478bac1b2845e8f8de3e6548e9486827e96461e2aad904215e4978cb4c38e7087db22c5bb78b14f21a72dccb8b428ada9fc4efc56c6ab168f49a009ccc360be455f743cbcc22a41d04224d62a2b5fd4f249a5bcd65d3a02c20f7951e72af8e0c08c27396ffbbe981912b54058856801c270c24d9d50657c6477be323bb43556d58b3f187ec258b776c3fed7f83ea089e8c0cce675af43882cc99cfd0913e55867e84cbbabaa12110bf02a395c420d81b86a25bb9e0f89c1b26889106da70d8af84860e166dd87cef89058e750868cdb5fdcffea38f8173e51bb7044daad21e661d3a8f2d30170b37ce2cf08f0d750049b89dadce3f444b3ec5e98bc256e76392a691649ce05de9fe2479233eab913a3b2a93bcb0e8f9b6a51c59c95e6210fc96c0f8847090460889dbdd04690d92bdc52b75832358568e6835f3668", "a779fb5329f2a52e971217ed3fa069820e93a547f02f326a20ce3dc6f0a4b4e26e8f6b6c143c06f320184ee48a6d1111a04adcb5b497563ef0d913983b256bb9fd2ee248f528269f14a2c33be9c495723b561cd1af633db430bb76643355679ef7ef60e28689ca08965aa29efb3ccf40fb71a0ef0b721203f69ca7e8a1e0ea8ea06dd6eeac8340c9173ada04e386c178d9ac9656aa38facf28ff82a373b5f4132d00a7f4a4a73b01da637be3764b260907798296216afd653ff967cbad2c6333a6fe454882d3bce377ff3bfda81aba99c665d8f53249df94830d97c382a52b959f2c444bdaf1a2a3266768f76c34b011751e7890bb2ade1d0aaf795e32b1cd6cafe86fbb332955b6efb8ab4b0f9b721d4df2f79aab14452ca28d19d0922efc2dfbc0d873f5294b17fa0c6f51ba2a59104a8263d29766eb720dfba611203c53ee79e5e6e73bb21b431184c030923316ddeeb154e2757308d9b3d156c3b781f62684a8dce144981f8b859db7077234c61fada28465085580965ea9c8df411e5b908b31daf1c70d6e5b08cd0f17cfaf98a42875cadbf891eaff908c22ed8f898ae0e6f1b3c5351bf607e61aee120daef2ef260ddef12350bc9a2808153b6ed01421d8fc32286d588fad691867cec80a02a5ea9cf988433bb607b77cef999ede502218cfd20b0de3ca3c3e997f5b342f8731bfab7cc7bc9e15398e883a5527b1dd38", "-179e34e87c53691487cdba855c7396139b9e33030b964bf6069b2cb0729a258339fd2b28f17aec98f31e6c329945431927ce64a54f0c9571c00e7cb514866bdf6b4ef3890f3c67e9a1dc5fe8be96f542069d1fc5154e24076408da226f0e7723357a580af30520ac1ef9653a0b3f3b0db403381fd31eda49c686eda84e0c4b04d635b35d5f67b890da13de8d7a243b8c2616becb8e757b743bbdf4cff4f651b54d38aa3f79c62ac2a2297897fff8910d356345c54b2ed381e8e1e4dd0f89bf4f05eb4416d574c77a52a839a8d35fea0ee54fa5f77b0e025b2adbb28059889c32253efd2bc62ccc568e1e01a468ddbddde2dd2a13e65272d1961762474c1fb6d767cabd0797888c9f3ac7ad58cdfdd96f3781e576f9d5deae978ea53d3543e757fe2ebd154b5b572516a082de9d33d0e50a307cbd459d7adbfab4c0b8d84b41220b59a1c3e113d5a5b904718e808f715b5e6eff56c5e33d5c029809a4be44b93238dbcc239ac806c473147c9187e24f05909e491e6c0bfa651fcb952a0f386e4a0f8d8e87cbf55cf3c6faa96e6c83ff18b78fc57b7586eeae9c9843a2be144fb25c19ed5ab96ef9efab91c5ec58a91c1f816e52ef5beda97770bfc59ef5b2eacddfe6aa86197c1a5f7371e466eaa5194d9d5560d2bf5e4f1d2c60c8b03f0a3ecb7fef0e1d479f35283479ddfe3d1ed57785084a8a40f556d6bc40da33bab1113a0", .None}, + {.Sub, "730fdcd434d67519314ad2a60daed3177ef3e9ac91e0daa8c37335b05546ea1abd5cd13cc0b61c80d8cd86ea145c768bba52683f6ceb644eb8a17cea5975c595b674e47e7898e43b4fe6b05a1db1c4d9a6a64bc23cded4e02648609a66189593c5a80ea5a62f63c0a5ef8ddb8a830d53ea8edd6e34fe7e1c62f7b49c90fd442565903adc061bb63647c6cb43ab89fd6986522d49215b8864f8598d908c0789117a79faf5537be968bf09b3aa86b401e98aa7ab9beb7f60018c4b3a73915d8ed04a9184187d5c1ae7bb6c745e3c4ef0ff8af986c421dea41aeaec1d31f3d094fb87582f367070eabb7aab2ec1eab6677589bb4825119da9b9f4f13997bad419e97e99cd6074bd1b1c60101806c113d9ae83ba84ef6dc5d210f3955664fbb000a20c0ed7ced0c7b6e25d72ee82e45efb0c3806cf3ae42558e5bdafa6af9da4d1118f316364ed6557296573934ff62937ec8efb07f9c81900fcf3cf097d35523eccc8a4c424fe3ccfdfa57c60d005b19404496e20b5ce938dc016d1252e36131fad351beb0893257b682ff9fd1b226f3bce6d443e2022581d8e3f5f01231cba7a0aa43070a327d5e377e4027c0a0dfd69ff43ee039e6f7d24c5039cd994bbc73758093f00161664835af7306c7bf3f6ed4b8c945e5b83f4c88691683e3943a5743e29dc9eefa4eb62a1de1d5b87cd29b47681c70bb41679e9bf06ffa02212b5a839", "af46a95c7999a3c3e28ca7ba2958709dc25f571691c9be859fa125534ab9f8d86b30c2e6ed7c5d7f60b69eb560f37ff7ddf10c7d4856469e2ecd85ece31b46eb717df767b1d371d789ee2fe59a6f0fd98cfc9d0f09b376f5c50f5abf8849b856cff7f6fedc2e23d787cd28daa37b10a19eba52478560e917bfc0fd79d04a5d4b7fa4318d88754143e537dcef18d617e7b97946eac1e15feba7d2c6f877f73dcce843c28e7ee08db6d38ddcb43547d7e446e4739582ae912bafa15fed11f238a0561a048f542dc92549796b650fecdfc2103ca153be33589ddc9ae1e02dd45f3243e3272126c89d16562ee51a63e7affa459e5108c19af2c62495cb73c6b1ec799409297be16ba9418a421dded3043612a9de183702a7d08b7cdb736d8d27b072c559508825ae1d5667376936bd40b569aa633b61add3eb5c426cb24588facb1617db71fa8a8d3a8e01e910ed33dc1fb6d2c0ef274bb05597ed0180333278264417b2240eae8aec851b72a9bd1c91897e3effaa9f1733c0cd7c92be2df83e4d9d20d8d3c94529299b564ab50778c69cfddf868621ab5776dba37a110b3ead269afa561174360b97b2eb8f2390db15352ee45321713498ac4dee9072c0661462c0421940d6c62cc955491868e9fb6d53bc581a9a742875799519532318f842325f24e2ab96599f901a883a4cca0f274fa897c0bb6de0c4bc417a9d66f65d051bfd", "-3c36cc8844c32eaab141d5141ba99d86436b6d69ffe8e3dcdc2defa2f5730ebdadd3f1aa2cc640fe87e917cb4c97096c239ea43ddb6ae24f762c090289a58155bb0912e9393a8d9c3a077f8b7cbd4affe656514cccd4a2159ec6fa25223122c30a4fe85935fec016e1dd9aff18f8034db42b74d950626afb5cc948dd3f4d19261a13f6b182598b0d9d7111ab6d4c1a7e332719a1a085d786af793967ebefb4bb6dc9c7992b64a44e14842909ae93d5fabc3cc7f9972f312a235625798094a9d00b888076d6d1ae3d8e0cf706d39deec285431a8f9c54b482f1aec4ae3a03ca36bc8af7eab657b25adb83b65879314884bbe308e3affd490c2fa491dc0bddd290156f5c1b6cae8e252a3205d811f05c642623934794e1fe7a89461d089177afd0b94a78b954e6667409c47ab3d8e1ba5d725c6c26c9ae927684bd0b95eb55fa0488aa0e959d27e3649c757d9d3db2e7ca43c5e72d8397549af93276b5fd25e7774f0d5fe9b04e1ca575f648ed16dff579f59189e948a0330d65c198ffc22b2defebbce8c0b203ae332650b7ec5657612f7242480188ff594d641b0fe821f2ac905625a0d10e35b43b078ca786cd17cb2fa0651dd2c51b8788eaf3992baa4d2b6838da40c0afc845fa51e7fc6e07766670cb863c18a480b10e87eae4dfb49cbe20fb060ca6b4b42d78aa1cf14241fd9b3215f9afb9ca4ad282739dc6d44a4f73c4", .None}, + {.Sub, "db1b7e09807ac58fba833aed1d4c2e568c1e7171b62b1b9d96e55ec88249a443e81ab32472bd83a696f30f014ba72c99067b7a8797617f7817e58e03f3d670b70fbc29f61b7081b7a861cbba608581a0c4cc5de544d9b9e7e40a759b70fc4ad1f6996076481a9deed9e223e28ae542d33e007a2ea6fd23da00cccec101760f39f9b30e338ed398c66b5c185a85830e14972bef88fa560f08546b6ee6097593e6938365d68a385b52027d9fd93c605d4bfdcf32b6b5447fb1015bfd58cea4d6cb71157de9ece00f0d995277afcd3ee85949494cc89cdc2d72768a1b327eac9495ebe4ad08a511bb33c0f71cfa936f9201b8c8572d22f2adae9fea723f4613d5a55bfe39c02f2d8137414e2c522c4cb0e8677093a9da83d5e8c63ac10dcd8e27e6982ec9247a6ace63ff20839cfc0a8d8bd61076bb450c008708085b53ee90cc2755a060296c824b0f6ba7f782f2e42715807782abb0b33988c8b0e435344ea785b571907a26feeba68f901133efcda220e556a6bce1eba55fe3d8491436235b152152528d94e34b757b3c9ccd22f329d7dc84cef868415255ca458dd5b60fc7792268a4a319cc21b3db21359052e999d872b118dc3d2697352791fde941e078b8100065af72a8fa8f7eb0067a7b6013bf9485df365902d8a85a6056dae9f6404cf51256016a73d09f55b6e93d59a02500528cb9d48ddb4a5c7b0231f3f597e787", "d01a1aa75f1491d3442a3da40fa000651b92f93ce385048d4983a6c3f371587aa86c6def801b281f1519de850970f6d7f7a74746f9cd2c4ff919209ca9dacc613aab5ced297a73b1eac03ff0e03076f304fedea4989c0b4372537ec9b74b1bfcb5016d1c08057cddcbc6689e790ca3bae249957bc7ecbd6f81b7ed041a10c23d086180a9913801cb85def227c3a7a98bc4789f6b8cba9bba6b47dfde1b494f5b4cbf7f815be97660286fee0bd62e802195e7bb328908372e3945ec50cb92a468962ff970398c0e5f992fe767e818f7c51803911ad2b612c047353622741f309aeadc9fa788508dba05ed657614fca1634e49bacc02f6e41f0e84c2cf81d51b8e3a8c00909720f6cee006b44e8487b1e96b5b07c18c0e8ab6164cc8d1dee4d74fa634ae9ed2766dfbf7c002945cd7778c32c6646c48b85f823839a6eab2af480ca7fcd24792f185779e651d19ed93ea40d302af9bdea7c0dd8dabcf933b256c0e016e67a21756bd1bee97fa9dcae3820c3830c02b639d9218e551f4ac5ee2a92206abdb9c26c72760a491082912e669517cf393f35bbdb2ad206f09f3676cb7cb48e4d38e96c1017001bb18ffb9abb3ed6f4334dfc7fe706f51884df9491ef62f68a0dcee3dde0fc5db11ff84e233edc09ed82de7cf6efa92b492424bf94fba8080354ee02798e29df6df113b9b285f1d7dc6b45117f1ac722b9644594d3bcfbd", "b016362216633bc7658fd490dac2df1708b7834d2a617104d61b8048ed84bc93fae4534f2a25b8781d9307c423635c10ed433409d9453281ecc6d6749fba455d510cd08f1f60e05bda18bc980550aadbfcd7f40ac3daea471b6f6d1b9b12ed54197f35a401521110e1bbb4411d89f185bb6e4b2df10666a7f14e1bce7654cfcf1518d89fd9b96fae57d2632c1db6488d2b3501d6d9b734de9238f07ee2c448b46c3e6552e4ee4f1da0db1cd6631dd2a67e777842c3c4882c816110803123262dae58479b35400ae00229047e525f0943145bbadca261ab22f54e5100a8d63fb01080d611cc12d79bb09b7847e72f09e6a7e9c611ffbc98f9165af6fc43eba172172392f980c8a6861477803a7c4fefefc158be84e754b32afedf83beea95096f1fa1a85a7f46068076081089f3315ffa34a124efc53a104cfceb4693be1841aada38de1d990c597cd42da6905503cd4ad74d30fd20b78ab3b0514a1f9293b77b40328d80fa82e8aa0f8169624ea2014ad25e6917e4e1346fe865467d740b1f31aa676f16e1c2414d6ab94a4100cc0865f913b050c839fa8a9d683e24ea30fadd983d114830b2043d9661c90993de5eb036de3fc752826c5d609afeff8c18288a75f88c134caeac9a39e06f5992c25fef5adb14e8993de15a5ce148ef0a685cc74dd072142daee015ed7d801be77c5e2d4c6058375e99dea4f6bed9aa85c17ca", .None}, + {.Sub, "-65029e63f44f392514b2090aab6fa5914614036f68941f579ba77c80c8df371728ac97f962f06da2f7d6999efa268d84b2dbae5bc5d434546677ff50fdce71c09c1f0af317b86cb7f4261aad7e25f9fa030e6a84102a0c539386f0a535c15ae6125795bab8b8e4e9a3050624413c1a40414fe1422d1dafb116dea92a78a37b6b8947960d2aa09ff0da6a6d4b1424b7096a7dfe75ed0c2cb6d20b37ab66583ffe71e0d4f755fdb6b68191b9533d6b8e2481d20dccd45537a8549ec30253e8e6050b6de3886dc4fcf7ebf28bb91f971a5d8093e41c05ac9c7282ffd2347bbd1703fb4c4f35c4d5ea051aa623aa37f486756ba9f0f6eab08fa647bb12f13dfe7931d79c77bb37850ede8d058c382d5e531bb2709ca621725144a0f62e087c86fa9aaf469137a2ac8b4064191a84a459fa8f4755dff5c48ee202e00e8618866dfe61685d678d1fdc3705f75882c36eb269108e6bb571086506bc8a4a1f677e055b4e81d0e9edc99ba732d42ce74a142f938f2efc521c500ecd18150f55c24a33050a766a95060dc619bb57822200e0ae31f25332569f2fefc9b44c99b70d0fb20e5240ae7635babf1ae766d8d564bf6ef0abdd29b9a0dcb2a4507a8ad4c9e57a675eb58b7f3dd1b34a34b3e47f75572828a1d620c02d55a219beffb905fe44465351243997b06f4177bf0c0a03fbe6721b3e5c0b220018fb1b31ebb8d6e67a239296", "d6b8cc52c70479074a5f72b88eaa07f7a9d0cb38f4326e09a7e98b20188e7e2eb0b868fe15c520361477aa37e1ad1eff732601d110ae3cdcae270fa20eb06871fc9a07f1f580068416b4df154f20986250c263f3e02f23af874af0c9c7e9171b3873bd2c512eb2c05f2309f764b119699fd5c6f774844fd37cc8798468aeacb6b2477fe2ba524269e38ca6293bd687633395c4de55bf925990a720954b3259f62ef0c91cb133abc20e5d011f720e2ccc95147d63839ebf33ee3aa63f58d847811dc4bafa67838501fedb87827f6123830cbcedc01bc68ea07646526eeaca7c30c2c076e321de0e03fc5ba5cb96583666275646e3d90309dfae6cc199ae6d130910595ea8d80ac415564f18d2598147a92c78114aefd41c2fc4d6ea8186fa575e0020f7a52d79f5472de5a2cc445dd7ef51a6a777445de631c09e13fd69c96012fb99f13653823279d9925b38d16fd4e1e9993c6f17404f31d9e355cf415f4c24e398d5529382ba57eef3e1a7316151f614c7bf6afbbd81c8f86792b660dae34fed0bfb98b34246857499608c87c41866dd47dc09a262b2a92813099abf20e2b7c6c0fa4d10a174f65c0e350ecda39a198d4a7235e4b73f24c96106cfd8927c7c97736ec0220d6ce9b0b49415d1222c50e532e465907315438fdde5e0c2601363a6d7c5bd9e4ee7c787751fb554d11dfe2ce54fb2f6d4917da24050b68b4329a9", "-13bbb6ab6bb53b22c5f117bc33a19ad88efe4cea85cc68d61439107a0e16db545d96500f778b58dd90c4e43d6dbd3ac842601b02cd6827131149f0ef30c7eda3298b912e50d38733c0adaf9c2cd46925c53d0ce77f05930031ad1e16efdaa72014acb52e709e797aa0228101ba5ed33a9e125a839a1a1ff8493a722aee15228223b8f15efe4f2e25abdf713744ffb3e6c9e13c35442cbbf1062b25840b18a99f4a0d19e14073162788feeba72af79baf116e68b3057f3f6dc42d96941acc12d8629329e82d54881f9eace133b9ef83de08d50d1dc21732b12f94624a366879334be0cc618e6b3f8091701c975ce4cbcdb930037dac3b39985f627d48aec6b8c3ae7f5d6640f8fd2f3e354a50a86df9ac4dee8adf111466d7465cd188a038151f8af6788dcd026808791febd50e8b7d27e98fc876d08ecc834a0ac9a15f0375e7463f758c3735e697fd0eaddfc40223df27804f1e01fa555ee642d7536bf64a7736569bf405d1e618ac320c8f14590e58543c411874bcc4ee10d76e878ab0de85a6376909ec1086040cc1b828d68724a59307a32a8d2527c5d74acc0a7ced2f10a076f7082cb608fddc2e70a738d128ac56a742bd6c169e37543ebdb99be0ce3db4cfeedfdf3c0b71e6499138b284a54f2bb53a492e6152f028f96ebdf06a666b4cb115d6e0d905f86937f23b13b43393c88f071b30fcfacaf8df9279d0566bc3f", .None}, + {.Sub, "-3ff359934570999c6c6b9a6cb15140ba86e59e8c2aaf7ae7100c6cb518ee4fada532221be845d7ca7d0d6e9e7dbc0da579646681a674f2973a38d597d05964abc6a7ebefe36c5b539f93231dec999bacee28e2af74a31e921400878efa66963dbcde79da1cdac53d648575ceedc043dd9266ddafb7158344ef340ef0aff924428946cdca6f13a329e38919bcf3bb3f030ba10c70bd9ca9a5d4255ca2539f5fe59fa99e869f60bf6dd1ecfd2decf28f4abcdbf402d298c976c06ede5a2452f0efed56caf2b72b241c119818318a88bd9cc6f041ba5ec4fa9f4b0fbea317398809510fccaff569e4babcd947489cc3a4b3abd32fd8a6c2b33f19f65a08b40d7b00ce562c0a424ce852135294374df52428e4ed6d93704925fd4a5ff1dc7512acef6628233f205acd13722a24141d8b28766f645a3938830a8ffc4bfc02b5fe28f9b3a2a2aa728cffb94e122ed830d9953bb62814e478e9d441fd9d37f8b88167ca19f863e77b575344fbd6e7d705b0268b9700086d36f7d0be56670af84702a59ad66cc213e03d148a3f2537a10a8804a6769f00dc221b1d2635df44274300f27c11fa88ed50090f4d5604d4f493b84ec247124ad6c0155d93421299b1218bb3c5f55c78c73edf703ee457e5ebdcfd45998c8f1b47f9b06afacf7f0aa08801580ea26e16d0f3918965c712fb67edcd6644d86fee292836e13b344721cbc543e0e8", "fa08624f6d64582101e33f5e35b14e29f0ba36a6d88f77818181f64324bcbfdfabf865c89f250b60711cfe94be6e44b98331ee52bf776927db8f659ef39d245aae49b0ced01ff0b37518d84debdf36d64be8fec693eb812acecba49023e80f3f72152af1dc3722d69a4a477d1c849231c5e52af3a8fae2eaee59426d77eabad747a21e34543c7bef19153d9b430b60f704167d4a012290d24b33bc82e8905cfc500e74f8cc5981bc3a63fe0b7b0075252c97efd159ca6b367981566cdcfe7bb29810d7c3a019f5cbaa9922b7962d66ff09cc9b945c8143795b7477b89cf207af337e5287628bb7d37e17b142b7d882472da6e9826aa689ff3ee75bd4e5fd3f312e099caf9bb9327eec492056eb3975aca853c2d1e26cb57fdb2654304c11d5895f809ea1c06b0b63687060df9b3571f6052aa234c957e5a8639f9efa4e12c4685e3e68882962841ec91d93d184349b5594cf22a7bf1c46b1dda89e11a5ba985407ea8a82419c85e72725a452ef049c87d81442bbfd90ce727fb71cebab2db05f4aa90d16d1f3bf620e013aef3df79105506e0ef5c65615cf185571a62b9e7222e71327ff4eca579c2028f2357fc75228b29fdf1fcf1ddd51375aa83556cae754ddf5682d3f2a1a55acc5bc1e7ef22455ae0385956500729f88024d6405921b4769680ec8c83c584eda15ebfa160a3cc7f656dad8a9e7678e865481705efa8a5", "-4f93dfb83c46df1e7c89ce6294ac559d25f141f69838725f28248c194b3a1bab9ff1a87872382880841f3e87c9a2f1f111978566d26c6929b7f1cbf1bf9336f1718c86fcd06e5a5ed6e4b0a2cb578f1a52e7729bdde1d6a4c0ed41d7fca51731b3ffcc893a9e376ace2a1a46bf888d00aec5305ef1a531739e19a3178777cfeffdc0efadb4576ae8d51a6d96a7ebf5127be274455daed2b2f8d8986a822865b564aa85d62c26578995933d0ea4a2969d0fa572ffe835702a2806f3c0f222d8ab16d7d86ef12cc378cc41aa5d03eb940cb78d0b73a48d0ed6e0c7061ea108a8844447b1d86b92a037f4bac25cc8412cd81ead9e70cd6d1bdf0de4cfc6026d4ef3e136c5d53c087b7a0217263cbca8bb83af72a9c08e6ff1554812571f79d3ca47fc202d293c617dc9a8b12a22173e7f95cfb7045c851888ea8285f5f25adf554039868932f52327fb3aa40815491cdef10f75070ef4db98ad1b77c1d9d2dd114f5a770c8f9f711ba36e49421c34a0705414814c98f6d0dda57e627cc701b580a0cb1752e54d5c508060054b4ffe677db6cba5e1cb7e807e8327649b41a5bad99e406bbb6d44f5b4c718076417ebb4c3e4d23c48c8bd073b685588443476f8623b433bcf4a12d211e43f2441adc4ec67dee76f53a150007224c7ff2f76c85a79c3190497bd80154eeab4b45a278f2e0a1157d55bd6b2d557b41cac69e2cb33898d", .None}, + {.Sub, "-f29f3b2722300462664cca3fe1f492ab1933d924d01c780ab18b1f4c9ab04d114e32c9b5d088f1cd7424edf9a92909dc0a96307c1631b147773037f07419c5cecfd59ddc320902ecf5bc0b95c835a25d2b4c953ee502c871c4e6a703a219652ade7d17ff3b6ae2c30b035bd4406294b519a6742661eb9da768dcb2c3da91240a246338bcb85d6ce4be4296d23d321348e6e7eb67ff6d6ae9e0584e8e56545b4b302c9f15a9c929d27648f0eefa63084375f049720349607d85b5cb738b69fbd5782b83a2c51bb1438d9a924556d002487a85a5aadf43500c031d60398e6bcd881468dba0faced1ca58238af75585acb5e6d9d1a4123cbfd876f5057cdf3bc00176762b936e1d3ede3e337369c04e2d2da3a7ec78386828894c181b815f9cf6a8d1a8b95f99c6762741c9e7ecbd23588508966b6914215d653e6aec36a05491943a03bfe40ee7bcb947093cdd3b7d23269a14118cabc63ba698f0db7700ef22addb497c48b036d93e4f5286b26072bfd8a4326b5df10ca0b820f203f24f84e6a982691b8d84119829dc7fa7bf344d19453d4f740d86b992b2c0cf3097dbd470c8f51e0fb82ab294ff036940357e6028c1cf8d76fbf4571287b456e3815085eadcca08632bdc9a97dbf94fe1cc799947590246bb500faf125ab77f2f3a56beee30e0da1e51d6655132cb62b94549c982976e2d2dac4b68bbd7ed2317ea18c450f7", "87b5a095b6008db225062705bbf99c36a43515dc20df778dd44a6d41c9158da63cd125d9643d7036d95830ae6337ab8a10ecfebbb9b0ef10b876a468c17bd4c4cc452e09ac2dafc2331953ac910b154b2dac36058b1d344adace046d0fef3894b4706afb9df11623608dced342cd2d0a7a47c4289392cb559ce29a139a947e5dabeadd41cfbed0dfa1947105f440c2f01c221763e9d66dd8180f3cfb6e70ef605cac77e520d42fb06ccadbf3be2dddca6522daca92f0b26d5b596f001576ca11098f2da2cde313f57c1de5001e299a4cdf9e85a88887987ef8dae51ed46f2fc700639b16f392c973a085c6ab05fe3ba786ef618dac7541965f0832e9f737f359ff289a451dd2b8e06da3fdefb33886e1b8a503630442fbb4764a3487e75151cb9b0b0a4b50a1fb8b8cc2553d3c4d5dfb886b5dd118aa62f7000a024c91201a8246833597bcda8839a25af3d7e9f5d30ac14ad1889b9789d7b20f42467ebf686cef47c922f085b1cce94850422e2ce7afd92aa797e70cda4dde70f2258c43f665b98761a39a65874aa2f396ee4af4c21449097312a28a6aff1735631c44f239a3ebc9f17f5d87ebfc5fc8d274604ab84f859762aeb5b588ad05b05fe4fa652f5ea465c4447fbb4866edeeb5a5ccb53e99c3d53b617cd6bb7ed38c90020a1d4387d2216da38f56134a6ce938065e6abd7e561f6d351df3d8d79c56ad9ddc196161", "-17a54dbbcd83092148b52f1459dee2ee1bd68ef00f0fbef9885d58c8e63c5dab78b03ef8f34c662044d7d1ea80c60b5661b832f37cfe2a0582fa6dc5935959a939c1acbe5de36b2af28d55f425940b7a858f8cb44701ffcbc9fb4ab70b2089dbf92ed82fad95bf8e66b912aa7832fc1bf93ee384ef57e68fd05bf4cd77525a267d04e15fe881c3dc45fd707d83172d639030a02cbe943d8c1f8678b89c4c54aab8cd916faca9d5982e313cce2b890e60ddb13243c963a12eae10f3a73a0e0c5e681bab14592fec53909b8774574f99c955a242b5367cae88afbf8455862dafd4f14cc76b7ee619b3df8a951a25b83e85d6dc93331beb2016ed5fd3866d673b35b759ec5d88beff7beabd771597386b40f5c4cefdb3cab243dc262500946ee48746cb3c3aaea6871b2ce8c3d29f970b6809101c93a2ccbc05c3e74ee833174ac168086f57bcbc244f2e96430b52572f6315b5ee315475dc57e4b001dbd7fae8b1aca91456ba0bc8b0b389ad6f48e9fa7887d5d12f5d8197b05ff62f617dbc8dd0f3bf07d311e771f747f733ead7f41db598658e7202943fdb1d80493b420c6aa6ce0e80137883a80fb633212a9deaae1115524d9aaaa0c9b34ba0743664aeb1a3b6e6e27705c55e042e73e9772464e85f2c61bf6b18c85cdd98b0bbf3c60dc31b8b2fb8bf565bb647d384bf14ba8344015c44c9ae1695c94af8979c587f4ddb258", .None}, + {.Sub, "-60e0777600e0e24219209a206e7692f64cbdf02b46062eee7bf6e832954d8820c0fb9478bc65a8c2f3b420ce28e82e7d2b90ea415c946ba64ea314167e1b0e557aacc34a1bfd9b3a13d896e23c4f56c1eb164e22f48cec117427dbf9c530fd59accdcdfe7cd6e7ca760ccea5ccec0c830f3928436d48f3e449f67067ff8770e74ca6d7634e57e99a97316f61c142336dd4f8729adf6b46a4767d7d282a269ed34d277d8d8d490ccbe4b569955f71d9844e97b5443476bdf7b8fd6295daee59efdb8b7ba1171931ba0ca11ac633648619bed47042654fab5a4c402ce47092c67a8815ea323e27f67b945c3108a71d356745b514d9af1fa4035dc0b6cee211d3a62b8a3725def9c1730a51f6f3834fa92fb7cbaad0fe68a8251dd8a017ff209e440f59340295b0661a1532bf010001f02552ab2f84acbd543948b4bebc50f61000fc85ec13dfef915f991cbe41cdd05c1900f0d30a8fb1a7aa362d2dd094c178d26a8068054c4a4bceee96123cd10743fe9ea268a08517250981fb307979aea64f3b5cda45edacc2030558eedf579958939bd931cd714ddc8f23de14135bf550bde255d1308b756b2598ef2f171d72f0b5310046f834a74ee5ef52a4d3a6cc3bdd64228d340fdd0f1de6d0e5aba332bbab60ade37ededa869ec36c9f533c53bd78600580f56f93ce5f2a7bfbdccc7ccb05fffd806a4eb02d02db0e12401c07c664", "b5f7913f6fa05bac01c6beda4adc3b877fc7e522fc1aed1a4d97d119f26bae3960a6d8425b7f89818e793c5a67fc09f2485cf249262f182992d8d785066bc9203e335cbdffca4628c0c6b2f2248f4229be7e32b996c991aa97ee726d9feea8ac4c95f6bd8c86dec9f6f04ddef986f98daf28b711c3d225684dd7dba59e4049c05aad470ed73728f5feee932ad8dd279a18689365851ef14bf8c108111f37bb5299a55622a7e3209b99aef20594aaa3da689361d15e7d243877596c9cd1fbbcae9233a0f1c07331d7bba4786b91976c832900a552d08283ca0cab949393ba74afd616764c33dd6480be15696e8fc57ac98eb85436c14c16062d9a19ecc204e236609c98f5cab406556039bd7520bf1ad89371130e6dbde351e216f73c4cca26e1c56b7f3386b2c2b4130e865c843a59f9c3eed7d1234b1b1435a03c1a5df048c018932919a74c33feaa9ec9a52431982f037636768a7b8ad5efb49c00f0d90481a37eb3515382cb87a00abab80eb0dc2a15cebdcc8b0869834374b57307046a7f98ebb8c690ac72bbba0ad7af751097073a1e9058043f6d11154deefe02d1ba60ee5aede07bf1a5fc92761a4228ffe44586ffee792ab40c2007b5a753e3607b7340c8f6be6bda7956488d6cbcbd5a761e39154ab297ab4d098dfa9dd154a84d2dbf806a73e54db8bde4982bc518115db61ff4331b189e598d68abdc9175624aee", "-116d808b570813dee1ae758fab952ce7dcc85d54e42211c08c98eb94c87b9365a21a26cbb17e53244822d5d2890e4386f73eddc8a82c383cfe17beb9b8486d775b8e020081bc7e162d49f49d460de98eba99480dc8b567dbc0c164e67651fa605f963c4bc095dc6946cfd1c84c6730610be61df55311b194c97ce4c0d9dc7baa7a7541e72258f12909620028c9a1f5b07ed610600648a37f06f3e8539495e5a25e6ccd3b0352c2d677e645b9af41c7d5eb72b171592f3e2303056cf32acea169e6dbf1c92d78c6391c8459331c4fbf29ce7d5159535d22f2458ebc178044d3b2a5e2c607e72055afc52719a7736e2b030d46d6910706bba098b5ad0bba416b5dc8c26d01ba9adc7c86a8bb468a40ec4084b3cbddf6c268b76ffef97544beac525d4c4b3361c6328ce2841455d843c4a1f169a0755d0086f4d7e54fad6aee658c11519152d873bc55e43bb87e6f201f448046709811a2d328025e1c9d1859a7d540dff1b569fcd17568ea0ccf4dfb82028b471266d101f8e8cc56fe5ec80b310ced448930c7e5934bebf63c68ecca9ef9ad5f7c225758d49a0392c03115ec70b1ed0b0bf11076711222b6549594672d4fab80035715f5b5b05f7084c278a2cb750a4eb83f27bb788742f5e5268608d31c999c32e317685d3a851673d2490fc0aa61f85eb6954e1871d0f1427a1e48e28bc1ff1b385674e869043b9eed1916a1152", .None}, + {.Sub, "-80558825d7a2934f08c973c4e4472734ef3e3c5c8b6a8835da38a8c88ad48f0a20f5f2fcdaa504c238e8cd66171e4ea59e5a3cee6eb403d71a72fecc3f98a426c83c559ab915e48db75e823baba044eb1b66a8626d09c982ef8122cf89d63f0277f81c763b0a7c1498a08daf707f85a1c820f913e0c2fdfe34262b6ae3ff9cee1eaa82fdfcaeacadf74bb166f606525e4b9762a18ef4840447b56214f524a5559edf5300bc82f7b6a5a1d9373b3a865d6466913ddb5dc8fbd9761f711702f3e25b50fd0f2061a2a16cc8342b19ede919c3447a46cadfd7617bbba0a6d95d9ad49b8d5c3cf5fb711b54b437a4cff07139b4c2f48a2ce6f807345858150e4179c1ee4f38138326236c0ad0dac1232de3f90cb6b1f8b0230e102470bd8bcfc84f3ff15c250e33b7338939b97d4121030f37290005f07cde37c5216d75f075a82771eb5a517025dd23d0e4d5856310bd5abbba6a0a1fbb53e9b263a45d6096224dd9de38b5d04eb96fd058c7fd93e6cea85e86bb9090410937190e41d75ad397547fad5c21bd45fd67e0b46a9bc001dc6db3f2014b9f9edbf19b054e535bd39c0f25c47486ce1606f5ba1fedbfaab584f5b2fc3908b1a07ad361ce22d53d3cd2c5614b3b4d3eb42046d9275e48005c266478b4bb8ab2b4576d25a53def99108be3081926738741c616668b17cbc646b576d952236184387c3ad1e3400e9280f64505", "87cae9b4a1f54e7101af0c3f85dbeb5e2b3ecf8bea98acff5e7999bf5883783da8d65f8ddbd80b8a75b5fd9190c66959d7d15ace55f3567bc872dcc1645ccf097800d6eea9bf78bba5a4081630d72053900459654c90215f44dd6da23544c433511011fcbbef70b8333b8e0ec35c0af21e74d1bf339a239bca3cca3cf39b23fbd30541fe77cbbaae82b1b2d2c8be2b3d5a7e722fe2f68f9b5e28ac85f82fae2146d44fd45f992cd31e439a08ac4fe13bda93d1a652e25aebf85757f39cafd448c8452d83bfa6d3d955a78fec7535ca2d4496d6686729c6e6ce5aa90d5c80ea6fb511d384b0b31e3c530532e485f02f584339489b94f6a8ba7ce8c8008d0780d34f682400afe2a1293be25f5eac5bceeec458387a377ae9c41a0cbdb729710c9c3b86d649f3b999d1e3083723f35eb8fe1dfabba83a787f1dbe40e5205faa89010135707214537914c9ba12d6d37f3de3704d31d376793ec77acbdd12e658896f0d9579ba7934a53ae345d105a90bd5e7af1d0640b569699f96f7444f25e5838bf623a70255493c75670306e5e307501f8dc77361a1b146ecffd11369aa1d3cc538e25cdfbaea336304be0243df961ebf202ca41455df9ead31f6f33d546847d2aa8870891b84b9e16cce02234d4751bbd658ae7a92681401e1e7eba85c6491f3cf208d7bf523f859a759aa2f5b3f87d69de51750a91b6daca1810021d278c688", "-1082071da7997e1c00a7880046a2312931a7d0be87603353538b24287e3580747c9cc528ab67d104cae9ecaf7a7e4b7ff762b97bcc4a75a52e2e5db8da3f57330403d2c8962d55d495d028a51dc77653eab6b01c7b999eae2345e9071bf1b0335c9082e72f6f9eccccbdc1bbe33db9093e695cad3145d2199fe62f5a7d79ac0e9f1afc4fc747a675c79fd6439bec47d9ba615d4d171eb139fa5de0e9aed545376e5b3a2d51c1c2489c3e5733fe78a67993efa62e42e4023e7d1cd7764b3b2c82b23962a92e008767ac26fc4178f23b34707db50af32099e484a1649b435de8544509f2fc1a6ae8f57a7b96a8955e0a091f7fc3d25c1dda0c1b14120159b48fa953db75c143308c49546b33a1fcf89b2e7d10eea72e79df7d43e7d7b42f9395bdc2ce2fb582770cd5b1cc1b4651461c83546fac198b756b6e2dfae5b10d552b072ec8fc1e23a309ce5ae8f9839e43c989f2ab73bf331cd2879de703a737c7ad748ebce2f8ac7ee150b3c0dce998fda7e4635d896d0f672a0b8a5391ba9f97cd80ba37fc8bf9b46a4561b6da2a5e4e3bdd37fc8bf01408d3888051f66c57db94beafd56e3add0f1291d24abc1ee951b14721c65acc5f65a720f0019c87a913b0d33f5c3bdc7cfa500ba942c4a23a96db6348b14392d46bf81278725db416cf074fbe847010336ea0ec0327175f5a1f4feaff00878d4e197a87e84c10eb4536f0b8d", .None}, + {.Sub, "-8b7d16479fdbcc02f743afc63b568bc37c714fdd2a878ea58e58e8a194bb97310d7ebc97759e4b862b631f3f621605c871162ec69623d1498b8001bcc8575ca4f85f265e383baf1746020d391a1e1981924c71191bd94076d4cbd1ee7e6f5a16f44740be1fed6cb5c1bb647ef6959c7dd4710dae0028a6af6e9d5cfbf8e345ba8d0d8cdf892a1ce3407db9320bd302ee0a255d5cb9caa4b60056924e7316cddbfee2fad36de5fa10c2b3e547f2dfdb7865c56542662c9e21038eef5e4b0c0f8ad8f870e29fccb862c0dadc8aa9070c0ce7c111c803ca7311277b2d32f20b63f98b4c4be34a89c22edf45c957f91ad28b2836cdc6eca87e81cc2f279bb63a960a4543fc411f9f7e1d59223060b1f5bcde1a919395b0a3fce2f2ca996b06fff6f08ddc145b7e909603ab02ef6789bef9ca4cd5d0d6ca7e0c2d137870b0aaff6115b1c6561864a5c63cfa0d811f1f28c7cd3bdaac2fee2bcdcac16abf8cfbd38c716e644f3561c002a542b38e15232f35dd86d70737d6752fa796675cfc727ee65a8f228db48f6dcf79cf9cc41612850bb4f84f25f19cadda250c488b8ce07dd92eeb2b02827c13e11ae30d2723a0fd48b372140288d3c0db6885d7a4bc2b9cda158364dee11b878a4e279d48ce307be4bb7c237e37a945161cfbf782db165ef86944096e74c8bfba729be04b34a2cf865447b7412d1dc3ad0a1cd630820b60827e", "9bfebda938d9e0315beea149812e66b63e1d9dffe970617fbcc552bd5cb5e501a5d15826439da8889e7c47244538f8e015cb94cb473c6ec9c31e0102a664ef46390bd7962b58df360c9ed4f7742f8270fa61382a75c935384e01c58f5273a42652649d35bd401e3337f87716756ba8d4c95fbaa857327f97157a284c17e271510f2144de464450911de772a562b19eebb55e4585e19fcc7f5f037e3cfabfb327420e5440599bfec601936009b621831136da2659752eb84c158d99c75f0ff986b6361d33155ba1dd0a8c0459a8decdc7e37251a221899339f88419fae63c3bdbb1beb9ed103d81397cd119bc19c6fd3c5f5d636d7e99c6c2a39e9a98b13b43961a01800dbd63566107c2e4f858f7e90e4ac8ec990060a17aabac8f98c85d1ffd5214a1cc3a4be7b719deef605a119533f4302a12bb98140b5785d6d2b56221f85e0ab17e04e7b8f9f640b172cdc3973438e48d3f4dba2c2dc4ad4c174894f49647a0a52942bc8060039d1e3c78bde06455dde350ef7cfcc2181381c836bff4025c838497a60a56c8175669af3ecd40e07036dd4647eb1098b52647e0f8468f86ca19fa7956bbb042b7c7bfb0978832e6a176820cdcc876f0fdac269e27c2ae4c06391c6511c296d77e49db9b368ce8ed183af3bd8faabc022f10b70b341ad4045fa676eef06d6adcc08c1f6cad392376ea21bd80cc3026bfbe553c450ac53fc7", "-1277bd3f0d8b5ac345332510fbc84f279ba8eeddd13f7f0254b1e3b5ef1717c32b35014bdb93bf40ec9df6663a74efea886e1c391dd6040134e9e02bf6ebc4beb316afdf463948e4d52a0e2308e4d9bf28cada94391a275af22cd977dd0e2fe3d46abddf3dd2d8ae8f9b3db956c0145529dd0c856575b26468417854810c5b70b9c2ed1bdcf6e6d745e652bd76e84a1d9bf83a2e29b6a71355f5a108b6dd6810340f14f13c781f8d6c4474551a9015e899c9f8b9bdb5b566d191c8925aa1c09118f2e8e15b5285a3fcb66e0e451e5d9d4cb33636a2554064b1fff472dd8479fd53d0b05d05ac743685c16e31412e1cfc7879431346b4245446fcdc2346775d9a05f457c4edd02d47e60e515590aeda5ec655a802eb1049e5d9e772903cf5d16eddff0b627b8dc7dbac4e1dec7e3d08efe4105fae9861620386afe47836061830e0fd10796698d7f36f04e3291ecec5f0174bf396f3be5f9f886180ba444688107b604f45ea47c83054650ac519bed1641dcb4ea88c5f22c69ae7adec4a93eda5ceba6124c35782641e6f32dc551524c9568860337e498eabdc16ed36dd8c468b5b544fcfbd2cf915d9ad4e6d438857b9a138a8495b08952598383cb5a535f8861899dfb462d4a2125a5e724696708cda8945e71f538efd21f2b0839e64a79cc6da3afe563b92d254f5c6c6aa15008a9cb31d8feade9f3d3c9db2b6cc71625c245", .None}, + {.Sub, "-a42e217ebdfbbb22e460cb9fea388948ee1c25d78fe5143b13a9238276cd508bcf46a9cb53ecfea021772d6ac4f7522504f43bb7f721584f52fe0d736fa9eeab16c2fa43d94f6b7dfb1af781a994c396eb19ef1b81cbf4d36c47cfb5adeedaf34dbcba43d499100a3ff87b54f320435ec533d88503f46fc5fb2fa1ffc048a58ae2def75961e0edfc1df94aec53813df0d29d0c7552f3611b4e85258133a96311b1dff728182ab9cce7985a3c8014e61390d3a7066cc49c3b6b92f74cab44e10880230a0df33480dca628bee6fe13f13676917122e0e35106b5d01c8d68a509bfa17731f1858ef63026ddf2c075608da1a29cfdbcd82dcd7fcfc784a5500edb83ed714bfe5db81b99299b191bfcf020f95009d7a65c68b2fee4e558dc481f2d4123e626dda719e9ef17a0c9a4385059146c10e2aece6807c186f21a7e61bad07c7ba12c159b4b03c2a7a7c32790e5ae4b9bc7f3782240fa76c74eeb5243e721c54c18846ae7b68aa2596f8cc36bc0cf6436d926374ab68dd40c1a944c5ae66fe98258a3cb048c133619dd245f37f942ad214640c361b85fe8404479b9da6bfa3fa9198cc0ddea0ce9933cd9772d34462f2e578e307545d9c26ee35ff0b583b6c73e6667a4386eabd0b47ad373c1645ad9a38da91ec477965fd26dcdb515e14c941af047f19e7833df049b1fe9136069b84cef8eca918b9cabba4b00cb37961ee5", "96d5588d23fb43d964325bee9048cdce3014dafac75340bbce76f4bb35f9ca5e2bda7e942717e8811b3dc607d71931f0c2c639c4efa733016739546c97a05ddd5a40ee5bbafca6e2707f37dfb2200720089e338ee8eb45c32cc43e9a09a3829353c963bf36b218fd89caafd8cfb5b909b96cb0e1e4220f666a63aab84b0389dd413d7d165a005865f4f8d5a246472e67ef50589e2fb1013d5616f59a1f70b924e43ffa66ec674ce688042818eedd9d351c433a304b00a1e5fa286410a0c3270333a27a515476b50d8c77184a5012bc745505baf41f85b46722f954454ca4401d0bfcbf169d66075b6bbf62d23968a12f624c35c69f37d0bf64100871e86c8b14fe43a1517cffca3641cd9a9e2eb83572623ca7a633990b18dccd334314ceb32cff0117fcde105c7d38305d7844f535b5f92461d70f7c6bd8ced8d5b27de41cf13576b9642ab93f7635d3190af7f7afdaf3c75dde06e71cce9fb50f87cbae5eb5344ce6133139f44844d23efbbb2bc2cca75809d5728a9e8500c4e163064145724c4880349bc0945dbfa2400a0572eb89dcdd7a8a52e75acd870693805a25f4eebdda06c119568c4cee6e4f7dba1bae957170f21cd2707639780850e89f070513646216022f09788afc378722e4fcbbd736b31439eb34ae789b3f03d671783f517b7b9228139f52d2528e82038a496cd073c8cf3d9143dc0c72ab380be59e4052", "-13b037a0be1f6fefc4893278e7a8157171e3100d2573854f6e220183dacc71ae9fb21285f7b04e7213cb4f3729c108415c7ba757ce6c88b50ba3761e0074a4c887103e89f944c12606b9a2f615bb4cab6f3b822aa6ab73a96990c0e4fb7925d86a1861e030b4b2907c9c32b2dc2d5fc687ea08966e8167f2c65934cb80b4c2f68241c746fbbe1466212f2208e99c86c58c1ed651382a46258a49c1b1b531a1c36961ff18f049206b36f9c82556ef28348ad16e136b7c53e2165bb5b5d4c08080bb3c5845f47ab35ea329fd7314e26adaacb972c170069056dd8c970d2b54949dcad73f10822f4fd8b929d5592aec92ed104e9338377659e3f33d78d17387b6698ebb4ed4fdab7e5cf6b68b3ba2ba8566bb2467f4c9001be17c1b28c1f5cede06e22e73eda852a466c4fd1271c7d458eca65354485dde4739a55caf030df9eed6db117e579c6044338dd7adc3288dd5e268f8f5156292817456703fada0f95807a80656a7e18f07eea9e41cbbf26ec9230de31300cbd412c590cdf75af6127b55bcea123ffa04ca793d97f64693d6c2e36fe23bb4db49fbab5c74b0d3a3491ef2e66f39381f740993681ab28f4e74ff4c49fc8804d47b64ffbe6ebb0d9548abbdaa2c87da66778245bb0b25a96a66116b0da40bd58afac44d86dacd18b87598be5966bda19b21786b15729a1ec9da9d688c0b85e0822cf78b82cf638d71d345f37", .None}, + {.Sub, "85f402ad2e6f348d6b2a46af5a4b1d30985cc1102e92c4e41b66799312307bbaad3630c275171c4ef0cd759878b1fb8f51384ee51ab968e315cfef8ca77736c16155e9a33034990cfad75007eedcf0cf6013e0c8860900b4a523a98dea8853b9c6a83f89f74bbbf3328f244433192ab2dcafed773f3ea92ffa21ad4e9ec87376055dbf6731f87cd45a85d2ab866d91828fc71f4abfb8a74ff758a9b48c5a69f6a5372c9d94654c716b47aaa04ba28c30e2b491c7cf634000959dff90463f50175ee19484a07b5bbd066c36fdbebdf49b9cc769991394826eb3044ec5d87c1c49831acd18b71dd9d07441fe9ff2dd3b521d3816143facf8dc5ffebe71a0d5a9ec14c2d803419aa80863eb8e718ff40b037e466a20efbb69b8adf24dc971b088c4e29d571875bbab65820667ce05d9412653078e6413764c8d38fa57658f32df05950845bb39ba5fc8f3ce693b540a8820c60af696d1074417f15365dbd3fc185711286d12eec92b29d45db388c302d912f191cc65c7108b039fe8d3e202701d101869137169ad3b550d23cc0ae14235fe2cab4f9bf77796c77b3517f3f4c07001339edb39614489e979727f5787b8f6e43b9c91d9e34605b62b92c565d5445c1342de1c4e775e54dc9e45fa15b9b5c493579040baa443b26a6783792081154b43818578943b2d94f29257ec22be96b3c683e27ea668c3ead29ade2448454527e5", "f920ec584a8d3d76c0ddd93725b3b228d7de592f60f3f12273a74517b94e73af9961a7066745bf9593bd818d5f69087179f53b25b62cd83ec7f6f71ee6aa4e78f1452de5b5aa37661a82948ea410b67b5194993fddde3c9a1425a97b7bfa184e55e7cd45db3977bad56791ef357ca1d520bfee471ce8e4cc9f7754f96864186468f3b2a2b79e5362e7af8a9a73ec9662a44039ac6f0bc1831a604bc601d6e9b8bd495632195d53c1a3105ce9e713a5f8447714b4ea4fb114ba6adfb89bd61a897c60e1cd5d68ea660442cbddf5e96a6afa115ae945e575565adebcc37fb49878a6de4279b066d31354693fccd502aaa8e0fece58b62920f65c124fe952903e99478df309456f2dfdf1c11bdb7f37f6a6b617e73b49ffcb9bab4477f15222b2ef53aee331da074f61f73bba31e58e294c815f38021def64f33fd9ff0228904b77b39e508681a4602f0b9d49a5b58c37dbf5d1d6fbe3dfc84cd8d9f355357bd75b6a245c45b80cd173522a663a9ff0a079b2ac786a6aa6bf5570b0f4db3733e5717aaba134348ba27fb993f8eac851f3678d8722a9606a4c4a37b3d9be7cd2adf47131a8180af14d8d951c7bcd0e147ff499ae59c753cbdda8b45ce5af53e0c2adbc30a6a9f216218bd8b89358bc5c440303df6d2e86a01c85736ad33733042361b4e62ab77f01599efcfdbd8ec7ff1729ed2071c05415cd0473567e545e2db74b", "-732ce9ab1c1e08e955b39287cb6894f83f81981f32612c3e5840cb84a71df7f4ec2b7643f22ea346a2f00bf4e6b70ce228bcec409b736f5bb22707923f3317b78fef444285759e591fab4486b533c5abf180b87757d53be56f01ffed9171c4948f3f8dbbe3edbbc7a2d86dab02637722441000cfddaa3b9ca555a7aac99ba4ee6395f33b85a5d68e8d29b7eeed7f04e014791a61af531a332307a211757c7fc21812299484f8075037c8b2499b7119c761c282ed1aec711424cce0285596ca721d7f4d48bced8ea8fdd694e0372b75cf5d49f1503250f2e7a7da6dfda7387c2f23c37560f948f942e027412ce2256f56c3c6b844767c2819fc139177b1ba94ad32cb1b0603d485f58dd58d69ef43eba337d17d1a5a4461e2fd522a27e0722a2a71118c19644ba3fc75355263dfb4e8262e57a99e0a79186606dfa79c995d6c721e960acb47ea006617cee06a6181afbb2fc6e06512d88434e7868d79617fbf0458fbef32c943a6497dccb2b1dcedc766c11aac04a3963451d0c820f934c3c86162428dc2cade672aac702cdfe70fbd6960dbd30d68f2b582bc7ec1ca88123df33d92ccdea9acc3a41ba9fc75865b89105e11c7ed7085d7f288ca20497e9c669a79528a5b7ab7ccaf3a72994302a67f6fac4f2c73e25c6a1b0be75a16b1eed81e3360b22343d3c4ac6aa5d16c09686363693df319eb51e231d8785a0c18e88f66", .None}, + {.Sub, "1ef5e0b335dbab250c19ff95900c6fa6915380a6382dffc693a579197911a4a2ef7a1c205a7d762d3f3937780c57e9ca33b1b4139b15de221ae5dc0ff65e9680d6ce2764027e86e54fc99705635dbfea3922907fd4bff8c791d664663c372e8b4e9f3f4c38fd75cec1ca75135f8aea0d196470f19f5a429fce7c3fbbc45b41185e54fcc182c1c5bf9df9a0c0cd17f8fe17d9d2fb7dc69715a84d60413dec9bfb2f82dba6a71db00dd22351fb2fcf0708237e7ef0ea657f1b6ed7573be263acd6873d0ce8955c4f526eca8cddf264fb21e161730ca9dc54d5ef141fc13deb83a5fd090bc0cc9110745d18e0ae4a8436f1d7f11e99193fc487e8232172bbff5018d681fa180440f27db47d291c936567c0f9c1d4c70848511fc4cf7f11454a37d065f4e934a0917fa12879a757ae590f0558763d8d43645b05db3e09f15a984a490926fab99910c80b5ec5b38b22cc90932dc36afe0b2a6b83bad379929d285a27cc5084a9139bc8cfbf9f433faf019f2b8e6ab5fcd152879d0029d79356a437a56a62b631cbbb77cf2568ebe04ce150db6d5d9ee0126efccc90e70f55a4c31e04c0665a39b6068d3a6b74c53f900810e036f4f6bfb38e84f0ebddf89ad4749666b7211d39078cac93a7c10bb606fd8b7652ca24c0082f7f5645fffbd17c093109334f206053f5905124edceba2a8e82ba407309d78463797929cbd7378f9bb66b", "59d3e3c22b8eca332e92c86df2e145cfcf98908a69d195a256877c76eb6a33d7a56177ae44c7709aeddeceb5e1a7516544e6ce453db09a8dd7e9662443dadbc5c65c49261cd8477ab8cfdd3a9ec6a19ec447748c10c51d3225f9dc972ef4c32ca8b751442108dea1f34d3745e4302ea8e858e49557f9b937cfba060e3e31dd8e3cc74577da117006047dba660e042115611d0135b591ba1abafe1122aac7f2c6456f3f79e36939d03ed5280c1ef8625a91050d8493e7ae029450a1d279dbe7f1354dd3d3d4403fdda82aa05049ba32606d69bb98429b4bd7a2b7da33090b3e7c41c7890518c0bf1d97874a936d2df4ba0009e2b3af6cefc653e3475777741a3da0de294060bee4fde5b02bab01c41a9041c0bde651694f8d9d26ea1e3fd0fbeaedf535cd47dd0157889974c03af43b17aef65e3dd6ae798ec321a7e9fd4118f5acba2465001a989297bcbe7afd4db715d767ab752fe56e18aefb707121b0ac10863b1c12e10a331c30848ba07ef188722dec22e0bf7483ba9b5977675b33f7f8c3154486441a746494fa777cbee4f5260064de30bb53db9b0cfa0980e15f5c0461d61514df0149d1f9e13c6161289e710d36a5964565c57a988dcf2903b1a1d849e4eff01c8aa371bab3bb85e397c081b57def53a74fc47a2e4c848b12c36e12926f8adad75ae310bbe834098e3f24e43718a25965d0517cdf31dee678dc9642", "-3ade030ef5b31f0e2278c8d862d4d6293e450fe431a395dbc2e2035d72588f34b5e75b8dea49fa6daea5973dd54f679b11351a31a29abc6bbd038a144d7c4544ef8e21c21a59c095690646353b68e1b48b24e40c3c05246a94237830f2bd94a15a1811f7e80b68d33182c23284a5449bcef473a3b89f7698013dc65279d69c75de7248b6574faa46668419a540ec281749432e3a37cb230512b0b0e16cdb56cb15ec63d33c4b89c26cb1d610ef295b526d868e93a9822ee725794a9697783b1aae10c6eb3ee3f08b396013725755373e8c08488b98bef701b3a3ba71cb1fbad644be7d444c2faea93a6e69e522a9bdc82818c41a962d2b3e6bc025e4bb74ca24ca5c2f285c7df2803133028e6e5eb2cf47fee91f4920fe6dd8576b0cfa86c41a88004c98a74b81b6601fcd688c9b2c12568020b0934a1e88e7e39df8a2a8ceaca39329ab6709d08738f70aefda812682a9a4407724bb0294f427f6de848851e8b9ea9769cd6e6a4c70e54860cfefe9469f816ce3ee21fc1d9b2f9fd4048fc05358b28e54785efc956f918b9c7203a44a93073f50a8e4dece7c12fa2b3c9c3dffa16fbadb28fabc978e6c7721d1208d90d641aed691d74089acafd68e2f3d0b7192c3d2b714fdf6de12f2afcfdc9a350b62b3ca939f204523e84c88b996ba3d095f206a7a836552bf96fa654f63b0a229f6a59881e16cd803b56607aee940dfd7", .None}, + {.Sub, "-536e51a30a9fbecf168b89cf5970b4828572e4ee9f1536efe32a498fea2f71045c4058f72df91e4e4cfbce231cd4bb70017cd09530de188449aa726b42330e1f6b26031278f036c48d8131959d4ff4d1bcace55c5cd062d822f6bb23892e1e5ab627702a008fbb02cbdb4ec124585861bb8d12054bd05cd56441ddc88c5b2ff5e48cc4b1ef747576421bac2aa5968d4bac8e42390339b2e330d274fcd56b0d3d79b0b00992118b5760d2507a4717d9eb8de324c28bbb8dc26ca23cd64f0e01b926bf6e7f812b1c7812a6de1d3b07361405ad814b331967545698e6b9e4c7ef67b63accd7ca0fc74d81e572696273f7e33975b890c056c3f4e2b5361aa2f1ba1d557d878a4adf4bc1f40c8144731f5b5e75fbebe8c5f8afc2a0a20d325fea429cd8ff41d966f186cb04da5c13c0d9436626f9bc8f51904235f45052486a6a8351751453b562476ff83b6c4a0eb1c4e53d7dcd76965abc5909d8f9a3ac825a4ad4e465fac1dddd22c710caeeef3cdcfdcd1e0a92816dbffdb441f480e3853773f39ffc8bc3ec4dd7990cd66d09ff82c5ccaf8c37ba7356e6c5b502723830c16e3526493a57ef1adb8af97b336a7d4c281914a02c8e7d6d51b4fd7aad05744204764240a71d401435789b842f3ca23d1648fc72a92395c6874eb187ada41bf45eba3e356723fe6e7b26a1189f61570a29ccb78144e48cd26ed807be03c4b43d3929", "306afba0f17a931e697805f1dd95b07f3f517eec3d7609aacb5b3b5ba31beb62432342b14324f8ee07199f424d8e7752d2693d0abe01b158c3a073c23e429267fd1936ce976d90f70448d89129f93f70a8d77e78711735871a86b0d488d0d7d1e058f2bad40afa9ecb39bbd2e1c6ea3a2d92cca64df5895873576bd68c95aff8b45d30d33c93ffac65080c3a9b1b098e69285d3b3c9905630f8dadb442d577f289890926d6b26e26c15e19f1f2d214a695e900cdec1a8c879fcbf0eec68e69e5d374969084552c6e31abe611f8302a77f53cf5f39064acf9b7b5eb815f5ed0c91e2a878ebf17f84001e4b87742d7c82920ffc360135647570ab4a25edb8aee750f50f50ba9d19e38d5d116770d4411d77e9d4ea4705e05c547deb53d282e6ffdfdcc9af47569dbe206bdd7488666a3dc70a3daa3f540b3ef6700214ac4f16d0b1ab9137477826d9b9c29fd2ab5eee3c430cdf4bc3949b06ffca1310d8e6a3319489e21f7a529dafcb9fc217c73cf0b842f6467dd578ff0064eff1dbe211e0bcc04607f6bc9641b15eac7bb36fc55eefd21c931ad50f4c7d137c531c5eecd67d3ed1e8eb09fdee02b70f8c332532cf2488be26658a0706fabded3d703d94ce4529f644cc2fbe6bff8f23dbeae1710c842df0db5870f7b1eb9c501a78f476e2e93348b01e3fe2689143495109cd7488ea3997ba298c92fb0fb4b87c8005f421e41", "-83d94d43fc1a51ed80038fc137066501c4c463dadc8b409aae8584eb8d4b5c669f639ba8711e173c54156d656a6332c2d3e60d9feedfc9dd0d4ae62d8075a087683f39e1105dc7bb91ca0a26c7493442658463d4cde7985f3d7d6bf811fef62c968062e4d49ab5a197150a94061f429be91fdeab99c5e62dd799499f18f0dfee98e9f5852c087522a723b86540b196da15b69f743fd2b846406022b1184085300339b93068c3f97e22306a6c39e9ee9223cc259077d61a4a0c6e2dc5159c6b9efa340510058048e64452c42f3337608bfaea773ec37e144e0e4ed23b4426c030d46554668927bf8d83ca2ae0a54bc00c5a757bf0d3ad0b4bed69d8797e7ca89264ce7c95f4b0e9fac9dd97bb80636d35f4993a8d3656b587e880c26f8818b29ad6cbdccddc5b62ad0b98335c473fe742979d973346d0f6255b5073932f5bf05c8fcd6729d9c9dd93d796473967b3c901ae9b6b5294060979d59ad4ba10c47dee2d041cb98306fdc3cac7106bb0ac09514d6efa5ec54fedba90f39ea1a6557fbfa45d0b2fb5b1f2aef79e2840fbd8b4c9d1556967c44bae96ecc7a3fe1f8ed6091367c9088ef9bbb66a73f69cd0791a61a08292e71dddc160dc4e84094d8ee8c8e1a4f3e03bfaf5718dc1edeab94dde8bdb805eaaa541a6087689553363628d4d72c06907fc95043ad5adaffe2e52b87050fce77d56021fd35345cbc5137f576a", .None}, + {.Sub, "3005c0ae483d4861549269ad76d9615e2d3668c44c2e0bd7f0c30a69b32f81ee16668f1a8abfc9d6e8cb0fbd8be5303ed26082c57a2b6ee5b6ef5c3ae672783e862abc94daba45a84aa9a5d794fc8d7a5ad9a5cd95afa3bccfe7a18404849188b1bbfbe8ba75c44a6ddea4a1a4355ee1f2dc4fb4f1e131ee49430be7962f34293aad228b288b37b9ac5f7cbf6b128e0323bede48db4aec405baa26f23dd084c3b5a99bd1c04fb9a1ea789497b0a06bab14a16c9952e60be4b7f521e6d2a7b08c4640e9f3c49c32031fd0ba800f56cdcf9fb791b28fb740991f3e1cf9d69c399e67d32522150efaf353de798063ea46b597c54ef45c7433e8ed37161c67348ea3767df3f370646076dc37a7cb7ab7c5e0452e01d07fb354e19fe89e84ca16143f43a61b71c332f0946dd617f6ca6a8b7b48b252de2993938a25880c6cd9e024d3d0d167a5923a4df4cb191aed04153a996e023b69822a045f0a306eb5d2c3fd26263fbf8fe8bc656ebcd2514eabf43135e9ddeca27aa99946d0cee6b0bdc591fcc8d699f8d499f6dead29033d57c6ba59eacd568b7e221f0a134ab01d6ce48aebe5d354668a1141626c1a576ba4b82a9f825187820fd1099e237e0a62f14615a365ccd1adb30ba2d41fd1c53dad383da72a064a604ca3d9663083fb643ad963132abd57c4cc1768ff8193ad3a1edd60540d645ac771abf8aa19b7b80417201320", "c993c64ab004a2acf3ea75b51e6694ed873cb4e8c66ab1a1d5972fe9453ed12e2d8b5de6b80a878bbdb947dbedb762c98a0957956c7df72ca5aa2cc3ceff52f6d151224d8930ad8255980c2411e532f9499f2b43514fdbccea55b95db0b49b3e734238a2b386a2d9da34285158eb93843623b6c7c00ed5e6e7cfedff65c2ebd32e5ecbd2af48e7ffbe3df0081f87cebef4a03f361285774d353dbce1778ecb59bd146a94fc58b9bc0d616ced1dd446a362b520881d364486eebf4b7c62219c30e88a8b3613c5fda49222bb5e42945fed2aae7aba5e198da0d72f3e26370c44947fd7905b2c23aa96d90c63043f606a78adce3eeee6d8208ce0f367ad7791afe82df8312421333b858a416b39539dd74d1f1f2926015d28b30b2dce48ad0b2387d5f5774781405cb00bd7f11c727148abcd2b7187ed00ba0e75f4aedb27864751c8155ae2d68529f9a66fd15f08a92cc03f944ce11ecd3d6add4fb19cc5c2c38932078d5abb96a7481cdb7d574d24aa69e1d6f43725c4fc88ff1eb0f2e8f09dbd4da6dfe88e0bfdac097142c43cce073c7b525170b4f0136c24d68b6763881018b1f06acbfae03d45c9d2a0baef3bc68b2951cf6c5a9f9f385dc83f66e783b4a81f47775536710e0d8b83a9b9d6a21b3998296dceca90f3d65a8d815368012f89e40ffcaebb92e8354473378660e62bcc509f1743480886d796f0f76b28d27173", "-998e059c67c75a4b9f580c07a78d338f5a064c247a3ca5c9e4d4257f920f4f401724cecc2d4abdb4d4ee381e61d2328ab7a8d4cff2528846eebad088e88cdab84b2665b8ae7667da0aee664c7ce8a57eeec58575bba038101a6e17d9ac3009b5c1863cb9f910de8f6c5583afb4b634a243476712ce2da3f89e8ce217cf93b7a9f3b1a94786bdb04611de7348b47540bbd0e160ed373a8b0cd99395ef39be4696076acec33c09001a22e8d8556d33daf84e13b3eeca5038a236ca29958f79eba4a249a1424f29cba1725200de333d921d8af6e907ce624d07b7f1212c60700af618046b391714afa3852de983db7623c31608effa8a63eca3f3bc5191105d2144b77a3d30b0cedb0eae09c36dd8e6116cd9f1275581a9d3d16b452fc3e2f50f48924f5bd5be0d6c1b9e01d925a806bd3084791ea9c36d2684506ca26e4da6227df743f33d444adc04db56b6720493f226d19211779ca3390bd31f42e6f2fec6630bc7cdcad2da41d960092c08a1307933f7f90794ab1b63422e4fca422b2b0bc084d045efb97206cd5c483f86e5074ce29084fae536cdf462118bdb49f6a3852ccc1d166570cefbe35db8494f4a839beba70047ea4ace959a3a4a3503f63d9f04b97aa5a783656b396bb1e47c2969dd926e23236e7ded1a702a0985ef2d27cc76b952a4e9ef7b7f35c2df8a4c4208cb78433abc7bd65c8e2d7d393f6711b25e53", .None}, + {.Sub, "9b27bea11e97f83129d5913a444a8464417c947d9bb9181ae4dc5571800a1f74cbcc977f38df8b155ed9e6af39c6a3b5233a4fc393da2493ad146bc8b1cae98c429c8411e9a68c066a2367bc89c42b763c892645bb3b7883e16ea0076a763eb313b22d8ba35e86967eacc3a5f6b6dc3d4f2e328484cf5b4d8ab547bcf66a9467629b784934368f536cfbbdcb802a4e4154e2fc16a17921e90d8827c7268319fbcf74b6552a936c5f7755df17027891e89c1c78072f44f883904fdc455bd30223321cd78eab936a43d573c5f445c1194fc7242517098f87cc383693b51c1c2e786c06c385cfac3fda68e41536e77436f043bf17e167ec0f943c9aec6e23ed85fb5d8b73559c9ae828c181f36dfe2d2615c44a3939743644494e0da55fbcff45da766b52cd00ba8c2fe04d309bda02a79cdcd58ec81f728449ef95fe5f94903eb2cc5497c79851a5c581932a0a16ed34ebce0fe51cc3a287c75b66e468c681a0613a9b5e791cdf7ab34ff96b56c58889df47ef6a24e996ffc6dca9436c8048d514e934fb3754cb2cf92e142baa65f07d02e8a72e08d085ae3021bc2b8e4367835766f1550582ffb9c9b34c85637327791394430a0c8cb64d430aeaf4ab885b0be3c6be9fffe655372a97003c2835c2e5c655b75dbd3f20c802fe2b1bc3a3b6ec9091a3f98f1af9ec2bbba75ee631a5d0dde4215feb866a189f2fbaab547ec4c5de", "3addc67066b3f3580ff571b7f3d190682f62d67d1f3137d4aa471b194f6668ed48a05e70f2d327c16f2b93e753223a5207b705bed23cb66a4749280bcad3dbfb796f905fccc65ddc024054a3801730b69a088df1e6272c550b29b30f945b371a06562f5342775930269143c315b5e558d42e566f6cc3dc3214c09a86e62f93138774664b029c3c3ca42a5eb28ec71d21b5a3b59eec17d6438067867cdd73d93b26bf37c36d5466a67d3e14f8535b40e4482431ac7fe70e2702999303c83ff944a4837eee88bf73fb7f55c1af4dbb0f1ce4e45bd49747719f32587262a2ac6829f8492d920335b6d624538a8ae11a7352a4094ad958214e020b2b6e548934495ad781b6cac177373ddc10fb64c4f3793b632b3e51843e4289da434f1893c5d2742e1a814ffbb7857aa2f3f81c92c9f893794c2a0cb08ba579db2976c2d45f340d0dfd72876f291174955f2fc3e64da77f231f33410a1f4b151203e59eb2450af1ddbbb2d793f0dfb22322ee2f133d8fbfa6ecd22b8eba46ec6de04193601c570aaf15539efeb6ac118e319724e60c8212ca5ac3af56984d12ea7d9cb0173c908417d00c81ef674730ac756b51f0a6a6a08adf43154f6e9cf26a775cdc03ef2535e208b81869d720c5cf4066d9836d1428a1a252428b676a92fc3cd014437d676243971352eac1035f8daaf771b9f0c5ab71b46a70f0f6f1c909474680ca7bc64", "9779e23a182cb8fba8d63a1ec50d6b5dbe866715c9c6049d9a37e3bfeb13b8e5f742919829b2589947e72d70c494801002bedf67a6b6592d089fd947f51dabcc8b058b0becda2628a9ff627251c2b86ad2e89d669cd905be90bc04d671308b41734cca966f3711037c43af69c55b7de7c1eb4d1d8e031d8a69693e1488079b362a2431e4840ccb8fa2b917e0573ddc6f3988c0bcb2b7a484d581af5f58abdc681d08c2d8f3be25f50f81fdc77d42ddda579a34ec674687a1202643151f4f028ee7d49f9fc30773041d7e69d950e5685df8d5df59c01b10b245110c8ef1f167f5cc8230acaf78e46d069edc8e39628fbb197e8333d269fab41be83588db5a4165b01357e8f08374b4e3c0e3b7b1ddee820e1785545bf26020b069706e33c2e8b33389aab800ff13d8361df11a10d60813a540cc275469c9f251e366f3674a4b71fb74c09f215f14ae383d370dd8885a73dbddf1e8b30093160a46a60edb5d4fb21cbfa34ba3a06cb82dc73c73d454b0e34d809d0230ab5b5815cb3f534a470fa43e43a5fd64dfc23815311238178fb4e1bc0181cddb1c295ef31451c341f3ba4f2574543d64094556a8852eae541d0ea98b9515db37bf6373e4437eddc81c1990689e147e5fb7c51e3a0c35ba9d8c1483cb9d3899166a5159ce674ec25f7f161a6d6a8859ec4ddbf5c2ccaf6f1606c4832d061944775aa9829f2636ec721d097a", .None}, + {.Sub, "caafa58fa5e3461b95e095df309c5051e61e805ddc3a0d8ceaf8d6f4eb201712c4a4c0d21747b662a39916ef61117a61b985b89b35c7c8889d5bf88a76b87b7c3c96c968b77ccbf90cb57dd2cac84602827fce2ed6910b02e8f1a6fe44daddfa14b99d741adebb258e795dcaeddebb2c203975a5915b5b0495fd5141e23c8b704bc31f5e6f5bdc2761e7c16813b2132f9d7e62d2f4e8450062931ce3901b26fae2c2e5ad90b188ebc3c739a4324e746c95ade5547cbfd985466d4e1533b15237a0df2f18958913dbdea24c272930e1fc3bc256b0d89012ca377fbc912d0c3fc87118ec5ec98a3826eecab1785265bbc1e0c72bc048fe7fe2d16c76f67f71fff26785d118afeb277fb29b8eee08b03c78ab30165af26172d1163bdfbd020ff652da1d97385d9a9b5a655f89b628c783875d4fa542a22b839d20c696b0a9fd030987aa23c172e968e05fcb28e6b64191d52b079d51e5ef59337eb08bde0fd792c2bd18315977c2c526b309f93544fb0671d90f838c743f253d53037b63993bb0fa44f49d0a87f11f2bfbe483cff219f65c7c66ed8cf56c4263555f295a52074ee04997ae2682f34bc7fd9abc95ee0617d4e5c6ad53e0c1b6243815be7c64eeb365780d6fd2959aba6a7c2055e4904f514aea2ab06406c3caece10e23c1c3ed5442df1cb28b35541599c3f46bb77094b4857f6d18cf19e82f341e3a13bc510257c1", "7d39b74c9796ff3adb5b607b171c9aad1e105467efbfad96cf974efa47a9fb84c9aef8b9f3c9a56c8e606c64b523ee6ec5f91a65e3edc69010db7177ecdb174a5ad70c4db8c88f9e53507e2d5b9383ca87f5b972365bb0bf34951883704e465697dd582f8380917d8f77fb8bc0b736b79cf27455ac3e497f36332eebcc0c21ec10f5bb84e296d334a3d648998022e772b884ca61754819d8df5e9d7f68106cf5093108ab17eb879c55dbafff4b05e4714ed7cf75fa91a54c28a63c545df31a8a2174c4a82408db3f7ba6524f6b6fa9bdf547a6cd487d6fce65ee1c4e9a5a31cc71150865b34d02e393d6ad3bca274c0e2dbcae50e4346033429ece7ef1a05eab9ef6d6fea55d05e644815c419c4f3dd8401438fe197584a4c76e91de90ecb5e7d404b1b2b928353673a9f1bef7974b3948c0bddd80432e0d98a98d42ff8c3dfb2456f46df9c4d8979a9d2ad09dd5a0d002115a5b695bb63062b0593b804e9abd9e2602bd30625d91de7d4169518593f92064c72b7a6f8bf55ce1ea2a0622db06e57431c5f3be57410f574a2e6c44b35e148c2c22cdf85548e500abc8cf57867a88e2f7ce5ecdbf4bb057aca787bc0ac68c00e451652aca43f6d569d0e08170de32f9664d6afbe1d3a4d79891a09b4174bc4c1737523170921a4804fd60e750197535c61409c44c7a755d7706dc428b61f662aa81200ce396bbca42deefe0e88e", "4d75ee430e4c46e0ba853564197fb5a4c80e2bf5ec7a5ff61b6187faa3761b8dfaf5c818237e10f61538aa8aabed8bf2f38c9e3551da01f88c80871289dd6431e1bfbd1afeb43c5ab964ffa56f34c237fa8a14bca0355a43b45c8e7ad48c97a37cdc4544975e29a7ff01623f2d2784748347014fe51d11855fca2256163069843acd63d98cc508f2be1178ce938f2bbce4f998717fa02b2783347f64280aba05d991dd0278c6014f6deb89a4e7488ffb46d615de822e34391dc711c0d5be37ad7f6a6a707180389c62fbf9d7bdc1383e467aafe39012a2fbd191a04292b20dfc0003e3f9163d35435af4043c883e6fb3b30a7d6f64ca1faf8ecda8778dd1a146c88efa1a0a8e21996e1a32ac6c60fea06b1bdd5cd8ebee2c4ecd4dde7123406b0618e585a4726623f1b597f73130384e148ee76521e8558f881d096daa70c50e63532f5379249048c52dfe16186bf10528f642f67c93a3031c0032a28f88f8051ef22e9c47606794d48cb7cbf3757278b8aabc60f9cf9947f62191399318d5f35f806b449432c7eaec8d39a185d542fe67dac16a2773ed1a705e7d9182afc865c0b4b65824258c7c4d430fee664a0d0e59c5c9027b96ebe0414054ab846d4287451409852a9ed896d748bd52efb40fd62dde992cb4925a5ac6c61ec46306042969e6ec772b8fc91f4e96f4b094522923890a6e4df9db4b9d626fd0dd61216f33", .None}, + {.Sub, "-3c85ae6c60a8305fdf5d28a153c34433422222a51f35e2610b5690562ca0eaf7d46c3fb8e3ac0f8b36473b4ba8479945b6091d2f6f165d89dc5b71ef7eda9dcba89c1b133356f0d61cce8031eef8c453d47cf818a2de5978883cbbc43d979b56b28c0228dd3badcd4d446c2528141c51773bd74753f965e500e3d68cbbb89d7caf109261a8c88c1ab097f7f470a4b8a297eb0fbed1491e6250e970e478d689aa05ec257137e056dafe4fb3eed2f087769c0f9da6c3a80a11ed0e95f762a1c67929d45af6cfe6332bbb79509921fdab5a70ab501950a337b08bda30fc84702701989813246aa514459315f4c16f87e5e8cb2eb9a0b839ea8e8b8286e92fee2197b2b752caa0d8faf35d18c396d2d5969516de3d15304e88fc8a611eac37dc44e28203f19d9dcb21e26129fa8f74c89f69b6a8c3f10add29aa03e5eb12d46f7ba53e1a300684acff49124b256974ae0cd84e6306ab4c1330e92dd7a68921bf12c2b272d0c0a47ae24eb45a7326f3df489addb348ae45aa27638e3d6938ae218ac9cc2d6ed1b85ee6c924322d20cb1966b4676ab372a879a255a9749b7359eb140d5ce06d7494023bebf3940c3d71c15af37dc8efe6088a973ad8a8eab95753aeb824dccbd32fbc7f2ac733c80a0f469e7ece6057aeac8a5c219edfedea91d88ce92ab156e2872972430a266af937ff2aeb0ba6c34d823278d2ef04799b71880ae6", "b5d648b835536d0b1c8750ec0a17d452545658c0fa0bb2aa5e5c37e6692292368e19e086a1511e9b4a65b9f18ad58355d32234f74aac690171715a3d6555a4227a8e230d49d8fc31f89f775daeeba385e54c9e0ebbc551696b52d13743688de35897632cfc0b75cdf9e3988105780f27b78b37effc82ab08d6fbf807b6403f671c76f0730570d46c7ed35198b53f37a00d0c330b562db1447ceab9e02fde11bd0c22aad245924cabac1243b7f095fba14b8158048284678c1f311b64f6223e9d95a76fb3e82f5fb9ad247dd811db179f74c9f00da25c169d9529abdcf76cb09e8fc2ae14dd9500b5c8e9b405952d1bcf99328051294baf819e24a568fca199e1ff7a08bda27626208329155a0f38d09efa22a0c873d5888fb3a39ef9690fddccbfa3acca9df7d0b355a0f3b651096bd6979d895e29361ebe96761193614d91586e1eca7863608e4a57673f598a80a36f03eda80c6e8af215646f5d0f525f5372237185ef8b61dcb4752e8fa149dbd7ea12212c06fbcbdc669a4bf106f2aa1d309c3ade86ddca93de0a59a6634d5c8bc3e82ac48450e97f7887b0181cf6e89a6f6848cb530a69ae973ad8f8a4b1a911e5b3cafd97e52e48697dbc7b56ea90f265ae769c61638c7362bfa2100147e3225642203dbe01965c53dc33c17cbcf88155388af28c073e80024bed9b8d2ba096cba34877c0cdebba09263356bfd1ceb23d", "-f25bf72495fb9d6afbe4798d5ddb188596787b661941950b69b2c83c95c37d2e6286203f84fd2e2680acf53d331d1c9b892b5226b9c2c68b4dcccc2ce43041ee232a3e207d2fed08156df78f9de467d9b9c996275ea3aae1f38f8cfb8100293a0b236555d947239b472804a62d8c2b792ec70f37507c10edd7dfce9471f8dce3cb8782d4ae3960872f6b498d25e3f042a4f742ca2776cfa6cdd42ac4a8b49b67120ed0437d72a386aa61f7a6c3868317e790f5ab462c719e0c3fb15c58c40516bf7bcaaab81592e5689dce7133d8c2f9e5754026f2ff4e4e2103dcd97bdcd7a0285ac139483a14fb5bffa8c704b501b8646139f1e1859a1029a72c522c8fbb79b2315b88434f2113e041d8f0e20e67341100dddda424118c3e04bda5a0ec22af41a79e683bc2f295b6caee45c5d20b404e464d4f341348689a5bfca635bd0cfdac38fa7ee80d8d9369b264c2ff2eb0475250aeb7ba9e22fe92470398741e6634d5e456b02fdcbf03298902c83dbb2084efd474b5417603ca28895a3fa0cba7fa68684d5896297aa72e8bd3841875f2784f9577f6f96321ce3124b39050d3ae7cc52938c79e6bea832e6d04e2236a6cd93193ed7dedb8dfa45665661041e4a11dd35368349348f28d86d5d80b5729c0d51080956cae20b8757b13af674ed10e3e633c496e8e67f24556140686639fc1b6aeef3b0e501e32dc1537d05b4356bd23", .None}, + {.Sub, "a095f1044be748ccd5881761e682c1907f9fbfe838ea0056450991bc319311bb21d4cb07318424fc418f7689f55b7483cf55fbfcad247a6491494122e3b3074c3ca287f0c96e2e3904aec9de10e8671a3b2119ca9add91d8dcb2f7aa8fb25911c5234167fb9c927f78c14e54e8f3397eaa85cdda664c872c8363b6ee773d9b370b4f34a1b70e076c8300247e8fd1b0463612f0e054452ce7d43cb9195115652318c83f63b93d4e995dbe906d6c5fe18ee0b1f563e492a002e1089ee369be233b521153b94ba73f3f0073ecd9981db13be7131d4a6fdf09f49ed681f8dd391e092fda68372527e0af772828533dd804246c2de250386fd62e98f519ab73874d158861d238c92df35686ea1d339de5d248e69b0de627543e9df7d7a747d1f13942cf48000eeae8b42d59f0a4dd894dbf5650cd2aa80da68f2381a0dc6e3643f3e61da3f69b6fc28822b76f7d8432f668c9876e0c2940be4ef48dd3a3a2e1287643ef90343cdaef6346bbe2ca968bc7e448e6309f1983a402619abb9faa572e0842392fe848c9f4b6b293e160ce1072fd3929108ea2d3bb4c03069a9526a2b15122ddf566f687fcc1cb375d70280958db7ba91188d1d03ab701a390f0c4f36b27c760e6b2259575b7517e745903797da7b0504124ea10f654e0f5ce38588d37260da85a10293ec2de9f289a0319b3a7931737b97d9994513094dbf724506a31c246", "4a01429bba432303062fd532d46aa92ece2801e28b2c41d06daa485b526263295439fe089eeb89defda637a27f3f2707b1fbf44d6d1a107fe36ff4376d34918539a4a738cc74d485ae71938788a4398c5dde51286e8ab39a77005a775d7b292978b64803cf41a82df40bb3cdb262c684323a93eef908ea99a8b15a817493b2fc52e0d4298c496dbb247f5570d25d93f771344d1d6301d1090a087f8eceda4e053444c68d4638649bc5419fc6528c55adac378605b0314fa5d9d8fe53ffb29ab54f0358519b79c54815a8634e7b49e0d48af966c2477d0c10dd76b8323020c733770ee8f35a032128b2559ebc5ff75cd7d9851a78238270d997c4518c37356be7abd11b25cff02b6ee3129f64bfe733207a8d6846943db2316ac0a357f61705741d8d095632a10631c51c744e4b1bca45c8f8429d32fdb9190f6255c43ea0c3aa93c4d56c6ec21d7812a09ba80148069c9be1a6bfda7aa9ac52718e619be8dd19bde078f6bd2523c0400acf81c08c72cf64806746df53a988bb6412e340e07219fd702b2a232a74e7500f9796a6a50d271324abfd7240ecfdf59e7ad02f23afa5bc668db35893c5f5da70788983b5e389c695f611fa93a6b4ed1d9b5664f0ec2eb2a1a92b0ad1e4d4bd1db11bd464c3af7d98092606b4c19bea889b8f923f9ab881af5bc900e267a6ccaf68c69039967e1738d6516e4b2b243d950b83578b0454", "5694ae6891a425c9cf58422f12181861b177be05adbdbe85d75f4960df30ae91cd9accfe92989b1d43e93ee7761c4d7c1d5a07af400a69e4add94ceb767e75c702fde0b7fcf959b3563d365688442d8ddd42c8a22c52de3e65b29d3332372fe84c6cf9642c5aea5184b59a87369072fa784b39eb6d439c92dab25c6d02a9e83ab86e60782ac499b15e80cf0dbd741c4ec4dea3c2f1435bdeca34398a823b171de48378d67304e9fd987cf0a719d38be1347a6f5e3461505d072fa08f6a0b8886030dfb67b02d79f6eacb898b1cd3d0675c19b6882861fde3c15fc9c6ad1856d5b8cb7f43cb24bf86c4d28996dde0a74c92a8c7d814ed65550130c81f3c51e12ddc90b712f93dc7e7a3d77dceddfe9f286c0da59f93168c6c8d1703efdbda33ceb1baf6b8b847adfb94d4308f3e31f51087d4e80adaa8d60a723e86a9f7a3303b89df212f01006aaaa4cee1dc31ae622ceb8c65696643a5483b621541453f992a31afbb461dca3f867bd7fb14cb3b717981b037d2a45058d8df578cc7164d96283bbfbd1ea6ca41cb43d1c93769cdf01215ebe2a5617a5f0510fc1a56738da17d218ed9432f68fbd55cecf79e85a2f7f1e27b92bfd5a7104cb673556e8e7a3b98ae4508fa8aa3d27cc156a7e7a518e400d2a91bc40a4193450b459cc8faf78b5526aab4603de076f85bea9a53236dfc992080a748260605709e6218cd12a6bdf2", .None}, + {.Sub, "f0a0db0fbaa540b12b193b743b13d539b05f3a82fe83fd25e2c307153035dd81140b7e84f3840314e4b4e2a6dd8806eb27ba9c6aa1c414d39af048866c2dd2b4d41a84d87704dd3497edd9f5ed7855ce7863f76288f149132614a5c88f2672c0be37e5f160a91da89afa36ab6d4f80117225796bcca49c708c2ee007e35f3722685b9a31e45d455ec2b1540e041466383d94f70ed3e011fb14d605d3cd294be6a7edaaebc2b304f17da4014f6fa8cd5c27613fd00c7238658168a51ff3c5f44e4f96ee08cc4c653d53f2a31f22370cc6f3613e7cdcd2b171492edb4226a5ac56b6bb18450be8cdcbb0e4ce01cb656e1e82a9939ce69c54af805cafa2204562eee929993383a32b0cfcb6043f3ce8c1f538ab61b72913c6cb4fefffa5d128f4c6d5966f78dc9b9d4df810311ce05b8a9babf2ab9ea2c2023e295745b76e626aa8ac7026550705d9a742fa4dbf040f161f93676026362641c2b945861b279af6c8db342ae44bf59d7c13dbc5b504942ec8cc7863260192d61e4a0cfdb813ebbf4c1cf28c08e4b1444611b817e235fa6d227f504624d783fd0b6dcd16bd2c696ae6af3f415fbd157b6b08aa1312eafda64e3bc0c915a56b50bde0f18b2e124f1338301aae72c7c8293c5023a7013a815aada1d2398cac4f10ea3d7fe8781e9c2b7f809336de1a2465097c52033f2fae90ac2fbdf54bda82d9795ce46df898e01041", "c4d06bf05b0040da9401596a64a3c35193b4c2348076581fce97eda28c0170630a3ae4bc870f865289b933b1ee44265104c47554447ff3329beb96d37e8815492911f1e402d34443ec930e57cfdee88eb0f5d4dd2b5eb8c61f5f975bc7082dffc2a5a42291116cab373bd36923d08e8ad8701d46eb87a32ed60af2e4245e9e3ef7c5a5e1ddafb57999d96ae1540c3900bfd4a7bbe94fef521489ca16be34aef5b14302e5f7c6eb02914aacf00f1d68887d42e453c6d91afca5a893f8b27be1707ec5c06817e6a33ebfe854301549c5f3bb38bb3a480107edaef9cbdd18ab1b140838e91b428a80471f15a26da3d25f2214b78989fb09fe14e38e5fe7e0e61b1d4403d2c487f804b39216a049f84718057eed772a76cd0bac0fe0a9786a68115c49e8c0e96dccae1ab31b2b3a6b33585d080c5d654b9ccc8a7d6e376eec47055daedf57f03cf3f69feb221ec025c86d8dbc25e14e554dd47f3ff2cfd6ea4d47268ccd22b8177ab67fbd41443e1fd4588b29f02ba45c5372ea5963e73c48ae150e49429225c99279bef2ba80fbf373ef4d4071e2f5e7a338697bbf3cb6c75864fed8dd1946e7fa76e3470bbafb5a41b5bd22ce0464e1cac157676a8d2bd4232b8fde5c05280aea7839d89fc5ef88baabe0ca5d8fe2db32b3951937867f1bdc852b797f410a1e707aa64d243150b332bbadd2fdc858c6945fbc676966aea4f3f8cd", "2bd06f1f5fa4ffd69717e209d67011e81caa784e7e0da506142b1972a4346d1e09d099c86c747cc25afbaef4ef43e09a22f627165d4421a0ff04b1b2eda5bd6bab0892f4743198f0ab5acb9e1d996d3fc76e22855d92904d06b50e6cc81e44c0fb9241cecf97b0fd63be6342497ef18699b55c24e11cf941b623ed23bf0098e37095f45006ad8fe528d7e92cb0082d377dc04f52ea9022a9004c3bbd0ef49cf0f6aaa805caec19eeec59545f608b64d3aa1e5b7c45991d68dbc01127414a12ddd0d12da0b465c1fe940a4eef0ced46d33828834294d1a9839a350f650dfa9142ae822f29c95e4d8491cf2b9427930efc6df20a12eb92569a9cce4fba3f5f47d1a525c66efbab26596a9f63f544a1a9efb9bdea8cb246bb1f400f562d66c0e36a8badae8f6eceef3344f505e27528323ea3e64e39572535b3abe90e48821b654afd90ce64ca11e30757d82efede46a891d7417ed7e0d86d437952b6443d4dafa24e67082c347ae6fc569a8176e4bfd63da2883781a53f6333f0a9167bcb3daa3dd3aff9e31b1eca871efd96e642867dd53ede632eefe0c4a1f20dda06651105e7d6622818d51b0487c19e581790bbf09118f2c4b0c3a08f667986fe023e2be7a851bea94abcddb1027783e111b1c6aeccd774a9a9d11c5d55244861f902bfa6540713f5d3fbb3ea632f2dd1ee7c7bd4fe5cc02cf313ee79bcf57b0749f3ec1774", .None}, + {.Sub, "36f158817a97aa5aefdfd3bb002066577c41a556e02a733b529edf5f8446c44a8036406a43b829c8297eda2baf2452a26293fcd87f984eeafe934323819b2fb16c95a8a6bc046efb98efae60b278ed4b435acb17301cc61d25a82f63feb54eede45402379a6549e5409e0207cd51957c58fcfefd87bc57f5800db6d52c3ebb5acd3709a4f508dbd0a539ffb9a0a0c4f48627e61df93062f18573f453b9a5bcf55cdef870b30439dfb7c1240b0f765212bd9db863a16ed44d3383304e3ebbcb417cf68a9c86115e4ab7e472462f79f827e27e96e6621513c3266d9ad398de03d36cd4c7cf409f230f67ce60e20cd59d9c47baa4489f020fd1263c0c10a8ffca7ead3d6f8a5d94d03d316a08ff04f39cf62397a95573f895e53c913d70a5943a56c062702186daf566025594dd14294903efa4d66d8820f5efd5a0fd6e452749932762df872bafc00a88e6bfde230fe678297adb69d24ab71e22bb30e261d92a5a1e9e2226bbea1d047250fa6b6fceca35670f56b59b064709189a3216fb7dc34ed6abb04e9f7cd70cd64e4e554e6e2828161d76ba54677334fd0157da78f000c2e5ed27a2ae1da59d857d00b79e012ee04f076c4bfec0f69d864625fb0e42aeb20352f7be4698910e118640948486c0cf4494d115f8164429a5770928dd6b80a57ac310fa475b9b3be9050baf18db971a4dbcc0192b6f1b53884910103bf12b2b", "b1dc7ca614a1ad385aac218858e5880d8c724330420eca56df03b466b7fc87eb0e4392534af878e0a7b320e4dba8e006e4235fca7115f030a59a2f628b71a4c001d4cca6c974edee8b5507d09136edc26d9ca1811e3691ebd67508fb82c775f1c23f3ee96d76bacbb91439a38cea1e2604580bdeb69d2038bdcc1e4b0d2bdf54661bb536a58ab99d964d93b8c23e37dffc8ca037b7b76278f3a07bde28f5d39fcdbd2214cf158fc96c1a97854679f8d1e1a3c05317941343911a5a2eec4247589bad88ca6ba92e00265200cb5366e1d2602e2917530f16b8a24ef41ee18c7fc5f9158203aba68a8cff47786865ea0e02778486cacbf69f457a42491e63364e265d58b1697d5607e0df82fe785d3c3258f1698a93361bc1b11b4073d3fa3aea07721504f28e2042f8191fe309b8f427fcaaa2afbb9309840e98a9767f32e2241201d7ba48cf1ce3bc5dff18855025e07655763506ed0f6c601c6feeb23027b02fa55c2b24bb48288457528cafd05500b4cf12d42d392e05b0595d23ee0e0bf807b03093f1c3f15ae84d84d942b47774082786fc9766d5effbf4f4ef7db3c5cf5b2e81b0f1de419b9325442370b034ad3e5c7aa8aa8165edd5817490f63f39501f411fd0e4bf07806fb003c2a1c0e5c21d15a5e8e5732f215aede0c0ddb948306f8226c3463bb88a3c815381b9857578373c1957d382eb93bfba8db2def0651e12", "-7aeb24249a0a02dd6acc4dcd58c521b610309dd961e4571b8c64d50733b5c3a08e0d51e907404f187e3446b92c848d64818f62f1f17da145a706ec3f09d6750e953f24000d707ef2f265596fdebe00772a41d669ee19cbceb0ccd99784122703ddeb3cb1d31170e67876379bbf9888a9ab5b0ce12ee0c8433dbe6775e0ed23f998e4ab91b081ddccf11393ff219d72eb7664ba19be86ff876e2c878a6f5016aa70de29a41c1155e9b459737a3703a6bf240607ef76253ef65d9729e0ad867c171eb6fe2de597cfb56e6d8e8523ece9aa7daf9230f0fa02f57be1594b48ae7bf28c40ba346b07677d97791786591470662fc9e2822cf48f7454063d0dba3683a7b01b41df1fc137a3ae18f57958489562cdd1e13dc2232bcbdeaf366354a6afb0b1b294d107454d9216ca4e2ca4cadef8bafdd94e0ae88e1ec3087910edbada7eda74dac1a36d23b1d51858a72d15f9fe2bfb599d1ac4b541f9b4bdcfce4e85d586be08fdff5e0b7fe50192446086367f68037d779e27bea740c2f1d7128e34b8d984e3a3247483db77368aed66094be0116985dd126e7cc6f7f397a33ad5ce984894894f3023f5f59fc722b912337e5e0d733c5e82a4f737fb2e6afb30f6a16d3dccd926786eef619e7d820d3c5f014dd11117cf7b18dd314869b7b4dbdcafca0763b24bf45cef00984e760a6c99e11cee5c97ba577c786c3244a2ceb473f2e7", .None}, + {.Sub, "-42f1afa2a4a57b53cbf4b1c62f2761987884347a0effede635bf8304b2b3cf27d1519b2eaead9141f18fc0732912b85ea18d693a18b3f6a9417cc171bd9bb3b1a6af2a5e66ac8933c6c1696df4d8d6262f43bd12ea560343ee02005d5052d2ff085f9442319c79ea096ebf23701ed123d863f2de6d8615d9e0f3bad4a442f2b7f44be568d50f42e28269fb091252c51100c3be71ccc7869aef138a388717724177fc9035d876041df8c839e373d9c943f8d920060613f95de8e261ce28592164931772187250489719a855ea484051e87334e3f7821ce1ccfe9a09d5317a2fd99d9701074adcd8d245da0bc87c98cee12ceb83c1a6d9e99ce184f03af5dca32d595377054a1a2c0de59c9277d617a769e1c85314f39d3efad06561d0a1b5857b76a51f87eca5c59a1ae76fb070dca06763eb471acadaea2d7a6f83e87cced081a867a78f080a1d3b08e964ce010bceff35233b13b80d3eb89f87cb7a06ea6a70952e49e9be8ad36b727e37635744a3e699cfad2eb4aca8b849fb349e860d96f0c8d5c1c01fcfe8e0e5fb82fd93c2d280fe363223a63d1a6617ef785b79e8881b077b864b10d98066b13a480faf9b4206f7f9257e46644643fbb300c1f0e6be18ecb48d59a35d239e1096964aba53006c36f3c9d41cc34fc976c33ae1106e5ee1c572641bbac6d3960dbc8bf10f7e59605624852ba6dacdfcbecd62eb569d15a", "d2be2986e918d547ddb0dbd632d42a7ba0e365bc2a7a9b92d609ac89ea56b1fea712905c648002c9ffb18120ef1e1a850b682e513e0f338713e8e270bcc9809a9e74a191e35668d6755f2e9a8e056b571c0e7525fc9f4a1fbbc68584a67a546cea41f95c9fdc8a876ccef4a3641f516b806449a4325a85a62ba650ac43e4ab819b571ddbf4f816890a78f1e15d4bcf6d48dc2acfee02f7e9ad91a9d532f1ada3f973ed7fdc25b4a6fde5f2c8cb32fa46868e1bee40229570ca02e86e3ade9fc2172d31b555fb09d42ff7cbc5c0695c19b38e1ad8b0c899cb4a7aa8fc204907e1f00927b63d078641c1eaf7db5e85e845aba93a29529c237840b7585da71c5cf89a1b088ea857e819c0f874c621803784f690141864c8f3a65efb4c31d389864147f3860799e319e766889557167e156e8cfbe6bb076bd1c523760f287ee6fa660f1896a0930d5e60973b570e093f94954b8b2e4f9e7aceb3be6140925c4a8d1b6e723f35e259c74f48fc634bd8e9786ce1593d79e9682d6bcb422957d275c792c37e371eb966b392399c9bfdc8a8d66f17fd16c871aa1fb48084c1fe1410070556cbc5920e7d822346cd5e1a404a0be49e8663fb4a4af67dc24ef4fb0688d3df177abf20d16ee44164b38d9a848e7ee1dc452cec3dcc58db36765622043327784a8ad6812544b7f94877bb07c8b3e2f66af84b8d6fa683b450bc569c871b7480", "-d6ed448113632cfd1a7026f295c6a095286ba903cb6a9a713965a4ba3581eef12427aa0f4f6adbde1eca7d2821af460af58104e4df9a72f1a800ae87d8a33bd5b8df9437c9c13169b1cb45316d52f8b97f02b0f72b44aa53faa6a58a7b7f819cdac7f2a0c2f652260d65e0959b213e7dbdea88d21932e703c9b58c598e28daad1a9bdc3282490ab7329f9191ee70fbbe58e866b70acf70535c82e278bb6324c810f3b68339ad14e8dd727667027096dac61badeea083d506a8910e8b1d6431d8605ea8d6dd200e5da192512464ed61383ac1691828ea67e81a6449997360aadf89e297c6b1b553cee6489897e64f7533be77f2656d09c2120ecfa761567a272b6fb03ffefcf98ada9f523ded9ee1b1fb94ac9949b402c7960c01a24edda4de98ff5dd80018ad764108370c521d8bdf75033a9b2cb4198067fb1d076706b3e76e299f1119838e003447c9ed5ae95051853edd6200d9fba29f4859bd49fcb933c277c523d47e427486002446c20e5dc2ab4af6384cd4b2f7f74fe1dca1bad6a101d00b933abb63b22047fc542da1e5039727e079eaac0df15ae203b983cbae8f8707437df6bf8b1a29b1e1029b3b43c0050e05f6532eb13ae2020a250725973fc0a64607f66ba4b67b45bcf6ff3033aee89fb469897f988dd7cde289d0153a0d6666e1fcc2e0f12532a95383c6d9abc88c705a93e02a1430941ca92ccb3c8545da", .None}, + {.Sub, "8e50ed38ce4d12df29029953f479208d04039e8b1cc26a76328e6a1b50bfb2d70d852fe28d1fcb90247e8ce702db75cbf5aefcdcf3865434708760b0d8a69ffdbba048b27c201d33174a964caca3af2401d6519d82ca8856649f180fc9f07375b03753fcac81b9e912eb12d1c0e25eec13901c9368adfca79926dc11474b474711a1a3e3a7f6e4022fce12145317d86f4ae984cd563a7bb50f72e77d3e996f0f1db004fab23c6dd2acdc56bc9ec77f44098887d98c01f6d5a1bf5d284e5f3205b74cdd549aebd2594aef65ad774617211b24caf48c569a8d44f95c6af3a7a4cebeadf94f9c952c95ea034c5f425ec52193648c6c1a44fe115ff17e95717402c69f0de535ae87ad4d6289f3c3df766f4ec0d66992567587a0d7eb753872d4f34e3bd23301febc04469662e5e8c7e9b08a58041e7d2d5cb79b2457570e5b154cd00153d555efd123a0ba358793642bf8bacdb7d6eb99268b99cfae0a7561c91b97325771d25c8765d4f3855052b91d6e6cd8debae16920f497a0b5f5bc87b180cdc700a808ff3122da3b48cef8dd182028388b4000b6c6f3f869802c724b2408a8d45d612a408e23f0170ac05d236b4c10d308c9d9f8029650686bc1d55f6e9e4210ddfb296e46c48502c43c2b5768976b253db30bd8a2bbcac61bbee1eeb3d9be09f754e05df82676ead4e476da2a41f69692234e0f006bf6ce7a22945d0a0128", "64f65ff409e21b21d46a3d92fbf95f01c4b4adb21c5c578ad7fd473bd15e2ee53c2eb9fa9c61b245a812622f956a24737f3d84d4b80fdf40ca30c807e6acfcc953472ed289027bb642a6b3f332ff826031d82a7eb9e3930afefc4476bd2ef0dcc5e37d6d078fb868bbd840101a603eaad464daddb1217a4736cc836f91547a9a433d548043084650ef3a5c9a3f613ef36f55d0d5465e1b6c023290eb1aa2941b254fbbd237b5be29655ce5b85e2534962dabb69bc419e3254c35675371d225342225ab3a9182cb187a6d9b79de8dca7075d759327718f45ba0efa33c2af87b46eb99851546cc7fe5a53f39796486ea729ef1bb179632dd751746424f250115ba576b1ebded4b26bcb8190427b6834c3cb236a8c649acf324fa23ce884f54c65e44f95d5f93a97a575cfc8ee373b6f26f58a351fbfd1be0e22e24202f51e5414f6983499326f1833c1cdc56e28530d98ef62bd545fc1a9852fe8b76255eb53b85d03da2a189306d16c9bb137cef4e16e2cc3ac995f214ba11afde73a1842d194ebcfd22aabcbd689a11da11e218e8288a57a767c3a1e88691c9c319300d57578187f98ba84e7ddfdf56a8e5dc038ab5d612e4c3d74a41af1bacdfdeef8fa42694852edd2af5f5fcacf058c4274e5ad3eb766e30c895084c71e77ae3627958b950cfcc17fe3071d4148ce18518a014a2bdfcb6fe69790c6371c50ed2ca365eb0c3", "295a8d44c46af7bd54985bc0f87fc18b3f4ef0d9006612eb5a9122df7f6183f1d15675e7f0be194a7c6c2ab76d715158767178083b7674f3a65698a8f1f9a334685919dff31da17cd4a3e25979a42cc3cffe271ec8e6f54b65a2d3990cc18298ea53d68fa4f201805712d2c1a68220413f2b41b5b78c8260625a58a1b5f6ccacce644f6364ee9db14093b57a13b6997bdb93b3f80fdc60490d40569223f6daf3f86049287a86afa9477f710440a24aaddbdcd13dc7e813b05589f5d4dc8d0cd19527321a09690740d081ca3398b84cb0a54d71c2153da631a409b92ec8af2987d314743a55c8acb044c412e5ddd7daaef472d1548412209c48ab3c464c72ed0c47a2c677c13c8690aa70ef9c28f323120e9fc0cc0cc8947bddc7a6b023802ceff6d8d5a26b1289ef396657055432be1aff60cc813040d6b8f63336df09300b8097d08bc2c8dfa0649d5930b0defb1f2bd78c01a59d0bf346d12294500313e0116219cf30d356f8be29ca3cd5c9cf578a0ca3f14b770c3a85f0d7821b0384677f0a03855e4273ba40296ebd16c42ff79de0e3d83d14de6d669fbd13423dccb1274c63d581f2104410c061da811fe0963ac0240602adc0e734bb8be2e5cfca77ad8baf1dfe7850c7d8126b7804090dc37faecf8243439a6f58dea0db7f755b206d3a2b3ce22d8652625df35f5e3a159f3899db24e495f40885096b4fca26ab5065", .None}, + {.Sub, "-f0f23ff8afc955ad8a7d14d6ccd8a60a6284d5e31550efee8b32bf5301ca0be65ef1902ac9a831dd29b0741abe0522bac3ec6b76d7cacfdfbbc7147fe0b13a71a468264e097b88bd7436b810e8f03f844908b6e74eb4aebb8356904c96a4b08613371db305eb5bcb6d07cad109b0cd90ad44fb161c81993390a6814aa6feb9e5f4c4292a623444be8bea269bb30c60486d0541521d36b70b3503a50c138c9b618ce27e6b5cfbec769e02f0ed347bc77ae33b3e01eb0a9135167685831e7efbaac97db4a2c9f85b4c5bf40a4c1e483263b2139925594ae63a0b9ad46bebb182313d869e4aa02cf51f82636484b130938d245c87b2351bbdb0eaae9380a489317baeae6401e4f4a12cf7f0ab172d9b868636f944ebefed992402078482bd5b4503efaf13df923442892fff98efee1550a5f45a1e2e78c19295a78f6aeb628366c96538fb1a2c9852b8cacc367178445dd2384e51a2a42bc0524e72038399c1bd6460e970263674515291cd7ac8ff980c652307094ed13a41d719db0ea8e906c79c4494dbbee50f147242e2032bb7fbbd93fbcdb8475c80bc5f77c56ee40c5a86a927e8eb4178b45d8243aa54fa001c8c61dca52ff23f060e60d1522ac7c74b18254a67031591a6e2cfac000971fc82c9b673a5b1777ebfd9a727859930fe6d7d6c2e767bd532b5ba0122f0cb95029b80b9192412e3cfd1f0dcd813ace6b71663b2", "bb933902b04ca9e7351d95ca0bf679731beb40d19ed417dfabcb6bec804a3a586f82f706b0fa3cfacc0bdf2f84ba139a1c6623c7097308ae7c29d2cf2c35a82f4175618c361eb37d641e5c84c42f60d486774ec1d6bd01836903658bfde0d8ce6c4ca0038c4c16ef42030e078bd4b9cbbe666154ae60c1a3ae65f8c93008f77a35da9b68b961594bd82fa465e320376e28dac41951f061d4946270be13b9d8de1390bf7d1497dd3d771757841aba510cd5c553f2ea990cf053b5f991b994368738b70dd4d5da7ec5224702695ebd0ea429e95c7561e680eea4f95bf3ecea4e5a590f4d402aca02a42f07b8f666842d03b3deea4dc3b344a14781a6adf4c4f50c038fe3518dc6afdf8237e34a9db281c7795fcc94513fd7a004c052f22e18a3fdaa24af75dc4bbde9360eb5f6e947693255e1d857c6cb863264a1a37dbafe25b0e574bf23602ef7ccd55aaf72fcb00a1b2749779f1dc0609d283fed37af4e70cc57df07ae85568fc0a541d819ca0a2b7d5c2f0dbc575bebd64dd340e0d7abc31c7930f3ab69645b58c715d373e5c49760e7824257ef645e13ddb72aff2145edb840a5b97f81db3bb3c3f90f1bd0414eb2ba97f0dad94c115ae7fe61e71382922c70b2315b8a56448d26c038d4bf22f0bcff1dab030e9fb2d2a67f4ec77cd4ee3a3bf8ff7b8caf3f823616eda6f2a7c7767f3fbbc63699b9e2d4f8f48b6180270", "-fcab7388dace204bfdceee336d980da1944389f02f3e316c85ef7611c9ceaf8be5e9bf9b34b7d5acd671320db650c3f465b2cdb34862006aa389b1acd37494f4987f7c66ccdd73f54a789dd93533359191702bd36c207ed3b9e6c6a55682be12f9fbe7b33eb01d3a6127fbb1826e192d692b612b6767a54dcb8ce0d739ff495d9821d2e0edca5a53496d20e2113e63bf4f92ed93b255bd287e49cc17f4c838ef6e1b8a632e456a4a7574666576276c8bb097934119b422041bb1e51c3a183f133d09258017560338ae187a72b434034df4b22eecaf694e48f5ea6a2b2a802716e317931ea2d99549c553e0141798d65d5f9a76571156f1faff26adeb83d580cc6ee76236fdd10c2af014294bd776aea2ae8f41b53501969e025389b1e03ccf43ca515ed6eff8fe67c360844f5ca9c73919b83bb3f52e4af8cdd985233e3349247390470c629b42359821e168a80f5e73eac2e91c9607c65c20f6025714b6a471266760a11ec9ba4e9c21984a9c38af1cf8c9fa2a96b000947eb842b6f68183ce0c27eaf99ba55a27cf536062f658070a0a45dc6cdb770240b5a0e193fe6ee584abf346d970d2113d7fe9e5ebbd20a14d084eaeffec9acf767fd210e6388341481172262b4a4c47187e6c0cff4874f8c243978c27afa9d4d451ed8e1d763acc4fd2360bcceb80adf946523a6f71c5fd3081180ea0333b8c7b05633c2f6d2e6622", .None}, + {.Sub, "-bfa0de7442d6cfb16bbbff1593cf5999b6f1355f9580552e4c9950279612fa50f8efc33f8f502397681ce8a3ebb5f24aaa4e3f4bcbb7b38de32bb33ec38a6196260baafd00c0cf3fb61dce453603c312b5a596d9a76c9699245bbeb88030ec158f12a9d3883c17224949937e3751720314bd54e85337ebf21311ac26b49a4b107143cbad5cd6e33d7f5b9df83487a497d791184b6b95e0e5835e1284f96435a00dd481ea003f1a6e638f7c84dcfb38694baa1936df8b284556afe25f3c68fde64c590c39e76e02e7753dde7347574e456f757d0ba5ba5cb48d0cc059df6aef4c7fbd917cd4e48aecbe04c3b7474c8035e68d2af33fe8d372073704b2f86171bc3ff0200476c6d6f3165c58d2cbe63ee2307bece671aea52b03ed715ccb11aa54116b89e681ea6f8e96470ee13e7ade75f91e5d55540ea02fc8da3af5c6f9c12392ef0900c37427c1c29fc6442c577484f39cebd88aebdc550cb39f1be9867916102e1ad6eb47f2ce529a49d200fdb56cb7d9e6fe422663e8a44c5554ede95681a3dd6055ced4992f9ecb27b06403ef581a3714b5b485f6ac16b2c26ef50120bb2f39a562c67b328adaf348d6ef6d3c626de4fd63b55ae7ea1e03c1135167b88cea9c23ee5e130471238db1853eb245840ad847454c3961fd43af0aca523647c52578417b4261077704ec0686eb61ab13caed5d03f24fe356053454b2e86d69d3", "40bdc053a5f979380230578127867e23b6af677faee0f432c0e93787e229dc44f9ab53c54f488c3e799cd0932e245f45726c2d471bab597ae9adef99817d3453354024b057b357bcb237d6a3c95e928c2ca38a3d359e9dafa8f471b3125efe98a116ce55e9a37f337bbd5fc258cff75adcec002b2572e1ba3bc822c174f296911c470966364d64a539f573b90e41018f84761ef79f8d5b65c0576cb4311e092906198103afa7436de5f6b8cc7998809d55a024348ea040cb90b284403270465a12fa711cb754df81a48f3ead9d9395f5057b6398c574cdbc61c0bcb967968f55f00658cac5db99228993d04a1ce5b5074b1cca240204252930510245300ebf2cdf92541d2e6088b6470722d5912fcff3fefa58d1a3aa4433d0c59440af4286155091210d8e5490e93f917246aa7ae5f5bc931f409ef6cdd4e2be1bdb26b4e66258780f5887826aaf0e36d917bcf9c6b0410607cdd6d4b28be9b5f13efcb4f7cc76db76bd01cb204ca1964e0937bc270c68b1183c2b3d85ee4190481e14deb4daba3b0ca2ecc8e610e48fc40e8cbd3695da973d39a56d93561ce670cb051c1b01511557b53a55e136326a5f329b2879243c6cca3f5c3d3bfd4dc7deb6d43ee866653aa9d8a6f442068dffeeeeee1464520db38feb50e06267a867e13f8055192ddc25ee513093ecd7c3bb9179364d68fbe9fd73e55f2653993cd37f71783b0718", "-1005e9ec7e8d048e96dec5696bb55d7bd6da09cdf446149610d8287af783cd695f29b1704de98afd5e1b9b93719da51901cba6c92e7630d08ccd9a2d8450795e95b4bcfad587426fc6855a4e8ff62559ee2492116dd0b3448cd50306b928feaae3029782971df9655c506f3409021695df1a9551378aacdac4ed9cee8298ce1a18d8ad513932447e2b95111b142c8a6275c0737430b233c4b43b57f392a823ec913ee02edafe65ddc498635515693b906a14a3d6b6e2b6910e762669f6ed944405f537d569ec2e26919cd1d20e4eae43a74f0e0a46b2f2a70eecd7d1347017ea26fc3ea479ac0240f479894016432353d31a9f51741ecf89b378806f8287030e91f827421a5275fa95d637ba85d160ed62f7645b81558e95ed4b3059d7a54306961fcaaf4103f0077d5d88127e8f5c46bb5b17c95f3056e04ab9856d0edaea785eb6718594af69270d0d69f5be9513b3534a2f3a661c08ee0f669905ae63b70e287099193ed13131af43097db38b9dc79208aff3a6d63e9d6e5dc9d7302c80b5c5e186cf8bb9d7f40835aebbef0c125edf4ce51ef59f38a0233993339fa1d3bbc804efd1800d113c10d5da8098a95b586aa51c7a3119823e76bcb9fca25a6a0f34fd6cdc705074677b18da0742cc6a9d6188bd7309d19c464ec16ec09d28b60f3019e2fcc72f4f44ec8a7980021af140fb4ead0e9517636ef4207d42460a870eb", .None}, + {.Sub, "8fa45ad55f98a02029f10e226ee0db95bbeb963c6f5f57bc3e36a11f10498c3547a5bc08ae1888ec102459a4621ade9a6e6a3ed68a96d1c9590e8306032289376577b263e9fffe31629c4f1b7c2127d5a736b10afa4037c5d6b7113bf193c75c976a1f395aa8a0bef937d62f406f48a514d054b1d86d00aeadbc7f4750137f22ce9e05f5539a76c4e2d0b7afa42fa78d30e1e16663e1d5f5c0f59b6207621a71393bce02dc5ec57024229a8ab94021ffdb4c59a4c2a3c99409b2ef8f1a290557be872537bd717a823af6a2512d5c5a92b8f36b41e3da5a66b6e71b02fb24d3ab69500f75f8a64bf8cabf823db628923f8f8e3fdcb47cbffbf30ad1479b05ede7426693a45c584ef152fac9420fff46c92290e0b06cba6422bfab8e49dcf4f362fc5c871ae74545383b14d16da99282c94ac8e708e30ef1e26c7c82f630ff7aa4b3d96e79a5020bce488f054fb0714d5886e05ecb98e967d30c7cb09d7b396703c699ee578c0a41a9cdfe6c0269365b5cf652e9cf35237516c6f934bce34a3b6fb73bb8779b8edac05dcc27063c1b49da4e19ad5e28b45d30db6ba10be408566b5e0db5418567fdc4cdf150cc43f82ace26f5f8948f981fbc24b7e9dd5a94737aa2f97aeab56843e753617d1dbe1fe1e929bdd7fa46fbb7748bdc758517fb103cdb5d4cb21bcc6905d8daf40c416e8671975c14f855ef09f6396de3bee18eb10f", "111231c9f4175a00d286ba161b309ca719b870dc8ecf3188550f2d642e8e17ad90dfd9b2b301876e44cefa68cc54f02be88d5f36471cd97bc6a0d6565f0fc3f32adb6ac23f931d214a477c247848e2fdeddb2c8f647fc6649cbc51fe7ea62441b71471693d808df4d8873e79c22d279cd3df3ae7e23755676c42f7f324697ecdf774c4d2d34ccb1601f51eed01e642b3b25f83a2a32002e8323392ce21ce7b9198006d29c2088cc411538ecf99e01f21f6d32e47e51fb120076d3aaddc84069e203fd5d15a2c3015d187986e97c5a2ba517866646c745bed66dd39f3618daf3ff5ce17870e01a1f7aa82a8b1c08426f330d982df51d73624e2118281168e008390cecbf5910997c1d890e3ce648c574760bf99ccb72dc08d38d32a70b7c63d35de48ae377da0079f89213885c9f92286576fb2f322b93738b469e320a5e9cf94e9ea8a2a3f753c21790af5cf2a4bd0297b1a5b8ec6fe2be111c25bed151be4a219effbd91b41da62016fbc1558b0c81386db6042f29bae25f823906964847df44a0e0d81cac1b087b084d9d26ebd069915fdd0302dfb446eb70196094219282a2773f869c0fcb2a2c760d2d33320e42857cc01e59b7cfed408c843883d71b7c439a07d1945094022698d59ce728c205066df9934199e3c0a561400383714d63c12bd1c52dc5867360c35770c901c712cec04c562886b2f42eede96b61921f408", "7e92290b6b81461f576a540c53b03eeea233255fe0902633e92773bae1bb7487b6c5e255fb17017dcb555f3b95c5ee6e85dcdfa04379f84d926dacafa412c5443a9c47a1aa6ce1101854d2f703d844d7b95b847b95c0716139fabf3d72eda31ae055add01d2812ca20b097b57e42210840f119c9f635ab47417987542baa0054d7294122804dabaee0db98c2a24964d97e825dc3c0c1d30d8ec20893e5939edfa13b60d91a5638ac12cf0bbb1f6002dde4792b5cdd8418740245b4e13da4feb99e474f6663454a6c696f09e29596b7d8677b04dd7765fe795009e10f9997246b7381f7eeeaa4aa01203cd98bf5a46b4c5eb4bcfd62a589d710f94ec68477ed63b197c7aecb4eb72f7a69e573ab72ef81c1d146e3b58ca39586d863d9252eb62d1e13d8e369a53d98b1f398e7df996042f3593415c055baa9b8129fd58b15ab0fc9eee44f658ccfaccf840f8086257d2f0bc6033cd1eb3bf1faba54b0661d8261aca9f27e70c86747cc8eafed108593496f77898c4287c6f0ced5a4537ec5bd7b6d2daaf5d0cd2a38ad474d33cd5e4341381bdd2dfab918c2246a0b02a1ef2e413699bcd7c46b4b2206907df910d746a5cf29f6aef41b20e81befa6551d22bbb66958fdd1705f03c4e9d4234f4b93c198c2de3ec62d5d7b6a35c8754ce0e63a00c8a0305f3f7401cfcca57cffb1521544ab574f95cd83dab34a8f4d08c86cbd07", .None}, + {.Sub, "657e17ebcde2e639873c2980dde02ecfacdf48c4b5242e2504a897deef6ab97961c2d1db961bb362cea2ebf48854f97f46e5f28b2f2ab4bb3b4cb314e36f7d6e3cb075f0f3cbc6c72ba95c30b9a0ea4b62c605815c2eaf8894e79913fd5a905cfd1f09a0e04d246e8ebde566889964c26b1bc40e3ae1c462494dd2535423a733001fdfc8dc9ac8fe72ca66c5ca55419730aaf2006c04d4edcac36006a8b0403281672ac864023f534e0a7fbe4b532b38f0cf06f35e408d1cae4919db988d8a4fdd26c9ea7d0d36deeb38a20cfb35c7b6a19326bd10e2f5318b990000a976d8fe7f2ef2fde079dbb59b52c3bf628a84f435c5fe4ea6255369c48e831f5dcacdaa94a1981758ff93e10471f232ac8d9a76c228cc6d2577835f4f77bc7749350cf14022f31400466de406a3c83c6a7a9297fd7b6d3d46d11859aeda550ad5d653c4aa88738af32a9eae5b76a9f78611402365c2d8207c582eb860c303112165802f1bf181480396d601325bff74ca22f4b9490e9773d7cbb508a5f7e3d4ee5279c41a975594e3527034afb18a6c7bceb09a7719ec38feb81050d7d693991abd9323927dbd45c49ad29b5aa141f49b690bb14f4c7cd0ca0316b9816c0a7d1c055ba08d2514e38b3f6888a3fa35a1e6e9d2e7506d65f667103ba8e8b90599acac1df38b8c263c9116185a4240ed11e47b1a00b42bb50c00602798b6c8b9dbe7ac2384", "1d478bb659483365834dde84742ba85ffb07a1053a2ae90b6e09631b339c2bca0707ede2c4e1c85ed117b3902eca73440aa776b378343111acfb319757d29cbacc7a90c6aa29b655a5a5c5197267dd5be91df69aa35b784b0f2674643d2894dd135075c70c4f9ead04e27fe0f8c0baffa59ad87dfbc9a8fd3daba701b09c90891fca1a13834df5a6f050b55d9d4ced399174098a6f6f7722b8fab4864f34aa8410124a7e5165c96b0093fd76d02f870c1a027ce49761030265d052bf09fa55cfab70d2b5b5ea7cc63fa32beee8ecac11a6ee51a6661129486cc86217a20ebe42699b2db651ee3bad4c52ab378d9eece2f068a74533c6c59dfab8d575ad89cfd1666e7c1c412ce3633f6cb46690455773bfa34298b12ee67afc0dfd274674ab4a51521928ec67d5e7b4f55dc71a3b4f7daa0c9954292602f895795a170327ec12e334ef403ca78162b0a6e6119c5d0a86ef1527ee70197c64b2f922f1eac90dfcc4afedfcb0637da90db8b4bd95cbe7fd31188467235d9e9dbedbfb37b48a7c7eab33dd43a915665f09a44eb5df50857044840ecc4872855e41ae6771d5a4b318c337f00dac1d552cac805ff9e992c2aeecc307eeba15b9c659e3a61e34929d579e29a7b36feee072988242c5259c4676624039b1a4e7eea144407607c1e6bbcc98cd1a083485256010d5289e909b7ef17664bcbda21934e488f06aa504faa567", "48368c35749ab2d403ee4afc69b4866fb1d7a7bf7af94519969f34c3bbce8daf5abae3f8d139eb03fd8b3864598a863b3c3e7bd7b6f683a98e51817d8b9ce0b37035e52a49a210718603971747390cef79a80ee6b8d3373d85c124afc031fb7fe9ce93d9d3fd85c189db65858fd8a9c2c580eb903f181b650ba22b51a38716a9e055c5b5594cd3578279b1682d08545d9f36e875fc955dcb11c8ab80597b95ae7154e04a129c75e84d7682477b23a42cd6cc8a0ec6df8a1a4878c71c8e93348031b5f734c722ba18ab95761e12491ba4faa4d516aad1cbe91ed09de907681abc1593c5478e8ba0084f001887d4eb9811455d5709725e8dcbc9d5ada9b040fdd92e331bfb17d2b07dc5053dcc1c484303028589d474489ce45369bf5002c061a6eed0d9eb13de97fc51ae6a75503f431a536ed3e91dab15611960faf3d2ae67b1c753844ab6831d4baacfc3e5e9b4359c76adb0320c3eb253adc9e01f369c72325741934b5333585824a34ab734570cbc17f6130cb46e166ae71be89d39c7fd456f6378513a3d09d5a60d3bb69c7e2b2a3295dd6cb6458af296282c274518e00acf45cd38187d7d6eae20e1fab1d64902628974e20fed5cf32788645ee772be48eefb6d301b5088160b77f2dcc14d8c70ee2d2c44c2284d07a4788f91eac56226f2bf0c345c90f2fa316bc47353df9b0f3dc6f84e5e46f2b42dd84f36e2b17e1d", .None}, + {.Sub, "699011e70ce885841f5b34ff1c7f2ff95ee8b2920e0dc27cac5181936fedc6a7af45078dbdac2a5ee1133c2bfc9a4721a12df2f7df383641113dea80c8a2e73922d7e650d198b5282d1300b3ae2273e0c00d27f4268efaaf355b47cd3c979cfdac99af0c524b6d329f3073f32fefe8a845feb548d02d291d0411e2d7f6470246bf01f7cc3b5e69eb7b238c476dcfbcafb341c38c4f21c7d172211a4761d3424aa9cade3702c9e64aff3555f4a9b265de0022499e7078c5c193523abe44373c3f9eb5517d5167f32c9253dbb0bf2974f7d3e2b293d08f9dddeec5fb03ec37479e5fea56076e876dc3ecf063ac7113e64180226efbc2f1ad5b2322f4bbbe1b090880cd932af0d5bc9cdaaf2778756f116b7c9faa403afc2234bb8561caefcd43b14dd614ec783bb13af18892f51d1f88e45fbddac565fcf099324566c90a350ffbbfaab3987f0f472cbeb9ddd4fe9bf322bdf6b4f4ee4d01f16984ea0a7e7cfd32f2597e84a3cf927547a960e9dec1e6b2a782ce1ef29930936c15e056dd00ce8b2cb05449e6368c7593f2a33617e395da0330b34517e4bb8d15b1bd8ff8237c6dbbfba151409fe3f023b3d2ccaecdb6e8f64f3c20782cb34b3b4e34dd982a9eb3dcb6d7583f4dbb1202a8c5a592fe24bec3c303a90520116067547299d1e1d7414332e93a0717cd36d3789e7ef77b6aea7d5e2c6b295a379df2427e8cceaad687", "f880ff7b339e70c56bc49667f4b244a384dbf629e31883a75a10d0f822af0570b78b9436703e62afce56474aacda982f755d18fd512eaff45642e86873d81e5ecacd76c8ddf8cbc137da09138f682c23ae7827b51faf46679c784d06b327498768479bd90f966e92a6d53d25ccb98b3a47716feff492699b79361defb2dfacc2727fd06f73a6f849be2a90e5ee8541555be218ba4b50a23b9d7ed0e2a1ea9bf6447610ef8debd3ba550f3fb8ad497be9c6d1c54e72583fe6e31a376e0c7f74e314f6153d999792922eddc0ff1d96b0ce9d522e6599bbe13ace2d9c6a2e638813976ea6270dd6142ffa77f60470efa92bc448818f9f141ddfcb69bff747f503fe9ca46a81bf9f590496798d896de16f24cf533974a1d620a0e5aaedcb2f9153df149afa637dfb1579e3f379bf8933e5a72e1d7b3c617560c70d91d81baa022a172629bdbf894e50df80b3b58aa119615ae4f4a9ff23659ac4352160cb9333a892566590f51dee619694be0258ed5919d1acc45e7a0c1d68488465be07e5860e5897452647a1b443b7651dff16b9f992ba1c575632e5f3329e4fc329c4b2da45659105a63d159c57e280c2aa0ec16c0db17ec2c2dbf322b796dd2aa115a4ca42af0b9c7bab7c2389a795f704d69b350277d4692072039c0fb63d9de48ab50470b7028dae39daadfe26098d144361cf9796b7cb806f607b159f9f883eece1c2dff1", "-8ef0ed9426b5eb414c696168d83314aa25f34397d50ac12aadbf4f64b2c13ec908468ca8b2923850ed430b1eb040510dd42f260571f679b34504fde7ab353725a7f590780c6016990ac7085fe145b842ee6affc0f9204bb8671d0539768fac89bbadecccbd4b016007a4c9329cc9a2920172baa72465407e75243b17bc98aa7bb37dd8a338488e5e4307049e80b584a5a8a0552dfc2eda6a2b5db69b401759ab9aab32b88b21ed6f55d9e9c40397160bc6af7bb001df7a254fc7fcafc84838a37640c3c0482f9f659c89e54e5e6d3bd6c96f7bd1c92c435cdf67a166422c40753784501f9f4ea66c0d879257ffdbc2ea44261293dc227084a846cb3b89d9faf61bd6d756cec99c67bbca6610f8725db952b38f3466d9fe6c2a258c003fc4102dc6c4e57705bf643ef26ae6ca6c145cc2ce5fa076fb78702ddb4c71529fcd1a1b667f0a270a3f09b2c1f9d7b5a27d6e3826fdf50a351898d2cb9c76c114b6ab5f640c12707a1ecf214d14a16f0e97331f0541905b198437b5184fddb108853fcd6a94d1fdbb7db741d12b5be0a215fce01926a2edce0e77113a116c34bab6c8f7d50a04ebd4fc73f25d0ed742129e56c8887386bb7af6044ba1dc6c380c9fa3fb2ee5a4533cd5ce95934e3f310836ddb910a61cc8fe7bfe55d64971f0e3229975bf5ac4ffd39630ef361475c46a542cac3a6d54043720de01ad45c0601318096a", .None}, + {.Sub, "-4c6d5a6ee05a5d828303620e9e60f0fd9a3859ef8c4c12f38acb7fa7a2c96c3921da62082eee1bbdc6ad2cd41a6429612301c3439d638dbe85a9b7d6dde5c9cfcbb7e095987f43721fd19cb9fc4801046609fcf08462836b3b60edbf9d9847034e1dc64347b574d05b5a9503fe81c6725288a3295e18580438135cc84a1bcf93395075ac74cb8b49c07de278d523009cb268df8d4680cc8ff364faa01a60a845750a66bd1851166b6d3872e812e51918117f655d312581aca3e3c9e9da9ad657cfb3fc3e988cd5a5fe6c55b9b89eddc976d18faafcba5cf95281637d94e6e6bb525465df62ae892fae27ad8dbc2cac03c086eec896095e8880db67e79c9eca55557a633bb7a824a148ca99100040eb2d7842ec475e93c16ae33f314805775a7c6447be85f713fbd82fd92ee7e5c3cdb525b0cb94c5100dea07e57c0ca71beeac85725b8c222e2218787c9f451befe3dd4f8219ffbac52c39e08fbee2ac1b0739d3f761dff6b523b927abb526166b3d3a35194bf98acacec66027263599e6fc3bb6a9655750701bebb5c55070e93c483a12df21d1e1420140a49970500576d8542eeb8b2553f185f671e66f29e6519a50e2d09ff8a4fb333255eb11cc75100ea040944afca975c6a9b8f1585976cfb0e27a06f0bd06ece4755ca6a6b1ce526979b8a6f748e71155d36612113c8453e8d2c9af56ff97bb3eb0270f9410ea673731", "486bd936eaac501bc9724ea52c7f567d673608803ad5e13ef56e2a3a1ac0c9aac150fc0c787f2bf9b9894810592c8fe840f2d9e5f2432f3fee8ca47e26caea8884d91bb742235d556205ba54c89f0f40541cbf0981d49e22aa110c8caaa0099d07af5de7b54ef014ea6ffbf35b1a30e195f71f5ef93caeee8e3e66bba04ea3f1050ef3ffe7b600d4b76376dfc2a42fcb0234733fe7ee8b1e828041b99febc92b65dd4887df9dcd5762e80ae4955e83fc90d1c86b1b244788e8b9f81fe2d74473c8163d8de36723d14f711a653987585c511c34c6df94a58a7fb82f06adc160c5e8d601b853adb210776b0278faa223c51f321826580a392f701b536516d71fac55fe23eabb3dd6b751a9ad33bb81aaa3c1d80afd90b19ff07fb0657d9d6d012beb9638e97d399b8142b6be3d0a0b9b5b889edb7528e6d80e915b8d37cf70e84b4b731933207587abbfd4a785d7041983010091ef376c63ab23fad7b053dc6792c1362b2af2a16dbdc70edcf7eeb42775992908b1ef6cbe040ec76a0db58ff41e4a38e4cdd4ffeb6bacc45430c38066fe80c9ff4495c829a2cabc4fc106dd6fdea5a5ee292928ca3608e6d10ac345192f1b130ddc1f44355f54af3f28dc65b37c45101347afb63866e3dbb3afbf399ec9c58ec99b65335fafee44e5a31c27fd3d0c2468fdb0d3ca45c24e67639d96f2e8e66fe75235eb33a0da296da8ba44331e", "-94d933a5cb06ad9e4c75b0b3cae0477b016e626fc721f4328039a9e1bd8a35e3e32b5e14a76d47b7803674e47390b94963f49d298fa6bcfe74365c5504b0b4585090fc4cdaa2a0c781d7570ec4e71044ba26bbfa0637218de571fa4c483850a055cd242afd0464e545ca90f7599bf753e87fc288575506f2c651c383ea6a73843e5f69ac5c818c1e77e1595897c73067b49d52cd2e6f57ae75e53c59ba4c7170dae7af44f7eee3c2d0207dcca8439d14a2512dc84c49c9358c9dc209bd721acb97ca39cc7bf3f9774ddd701ef2263625c7edc471dc4f0283d239928442a847813b2a6797b65c3b402592b006b6cecfc8dfb906eeee1397b7f0f6bb4cb375ea01ab78872672e5fb589a744643bbc295d13a1af744ef45615b62ef96c5a2e45ba84fddf76f744d9759728fed24efcf6910ae4fa709edf6e5f899410944768cd6f7d0e574bf42a3a9c4385146caf2f3fd605082abeef2318fe5048a9692fff76ecc952d8d0ae9569176eeba921e051f64afce4254ab7a378cca6eee90434f76f05a00e24a25257007576289a4a1acbcaf3893a92116770a2ae36f55c0110c544832d491794e7d1a502c7acd4034a996b37ffde3add4c43f6891aa9a50f55175c21c85a45e44592bff109ccd0c0936094fac3f95ba586c2044254aeb8c54ea7a66b6c4cb604697e52019286078a021eadbbbb01f3e51cda67251013901b9a4ab6a4f", .None}, + {.Sub, "-f68b7d1fe347d729331db821796acc4024eec604222ed82873ee70f4c84a3bb522e5cc76e7333f6abc6119555b2ebe97e2be5e09be1f56c74ca09183de972153044343d66a8e002d3799ee71c2d89d955ab95d0072334ad340a5302cf524f8ca49a4de73fc919b425f641b60da5db14cb21c849c55b069d96dbc8e33e4a3c1f23e3a2315414d6f39c39bf42ded18c4507fb6ca9dae778628e3c915bbf2224dbf6217e14190a5031c2607d8986fa3ee6c42931f674caa0c92c14586a4abd36935af30d0b91fee8dc9b6d945e960b3943f2ce03d4b0144be54125fe9f05553f0a4420ede529404a7757a67c9e72cd4b9d70c8e72b0bb4e7961a88c2908a877b82689d90f880f7aed37d9b1f68f14a57ae283a70f9069c8b9297dec23a3c5c3f48b5d44e11ac6f8bedc86c0b68db0316406fad66c6098e52ebf6a02b114a35f0bb33f50bb94de7d74ae8e31334d001e4e901fc794a6d78f32b0f3ca05906412eaaddc2cc89e8c573c1d7f7a3eb849774e287bddd0ed49ca67c9488a988fa4d2cefbb51e01f119936ecbb37f86b4556f31ddb6de1c4db145c46fb3fff94a9427c1dbffad05074037471e3c33a05e1068babbfd95cb8810793c4a587104aef0ef7e3857d21aa890602490a5007a53d0a0abea179f64bc646d5117f199f9ee4fbf7c73d8c152837d1acf1a11e85f1d6edaa58e10da11e0dc2cbfc43c5966024f7e2732", "a2fc67f6037505139020049f235f295f3874ba473ecc1bc0d7e948489487ad25bd1b45b9d0323829ceb1c2cc1264fd04af9057441356e955862f6649430ed462a6b1fb37faa913ad35df8e0cd84f0d30913e04a8962b2812d12d91504762a65e056d06e3e1ffa9fcdf383460d8259aec8b43af2bb67daaf473f8bbbbc2bb93c053f0cdef1b8a31152e60ed77d46bd5f1822a196e112ef6f14e2dedad54b6477f76620fa30d1ff08416371ff64713982260b767044107309a64b8f8c2f341ec1839d2e53ea42f0e517f5eb1f5a59caba6b68118e0797218ef672cc700e0b68141af9b8a81c05a5e35e728a0d77ee3872cff2f458c8fdb6c8bb660a82c60487225c49ec5d35fda4205c4b9ebf5170273c5cea05b4947ff1ac72fcdcf5df348a4255828886b7a32d7a9ee25f51fcbd595177fa81ee3abde21454bb7eb22d13a316972667b8d3c6be7e3226d9f79b8bd0904cff5e3d10ed8def88806a8494d53f642e454f822d2a7900e860e1ac370eb5ab626ac5130584b7e00d57a0516f0157e85c69f56a849fc01ce68c32a4bae5b4757e39f60706c30cb76f3b2ba075d6cfd3633b5523511832da737d29b1efb5619de4f8097909d633517b4c392d1e5a9e2c670f1ff41d517dd332d5a857b8197ea5b867c3c4e1e4772a944834599a0bca34a75e88f18241119c9a4d0910e05855ea1169a215845d86b6e0c6bc0cec0581dd8", "-19987e515e6bcdc3cc33dbcc09cc9f59f5d63804b60faf3e94bd7b93d5cd1e8dae0011230b76577948b12dc216d93bb9c924eb54dd176401cd2cff7cd21a5f5b5aaf53f0e653713da6d797c7e9b27aac5ebf761a9085e72e611d2c17d3c879f284f11e557de91453f3e9c4fc1b2834c393d6033c80c2e14cde1b549efa75f55b2922af1045cd7a04ef1fce1a5c1849a4201e0e40bbfa67d1a31f7036946d8953ed879f0e49dc4f3a03c3ef88eb6b7868ea34a866b8db13d2d25fe7f679f15554de903b5f7c41d9c1b3637f7df06503fe5e361562b7ab6d743798cb0f1360a71e5f1aa68d4545f05ab61906abeabb841040bbdb83d4b29e5ed5eecd13508c02a4c4e77d55b6f552f3d9e6be2842ba7eea852476ad9b1c7d3f0adb9f301b90c98b0b56d6986412b968674e6abad7c06f91e7a7e8b4444c35004b5ba9c3774993d1cb1b737221ae95c91b09ed2c6b8db5794efbd7877e66811a97bd0add9b166e0f0c081c0c15efecc2c0588597bba62a8dea28a221da215e5ca1e049da694e84d817bbd5899638f709a1c42b10003ca79359a7d7cbe1d768fe6a7b2b351f194bf123362573c51ba74c574063b7d0bbed49a4d166318addc71620d349780d69960fec8c419ea657801c3d25affcf523896459e1ba10a82b4c3c1361d3f87f07c1fbe4ea9e19ba12be8e3b6b8f02b7460042f2774333922052b3248c526d10fd6450a", .None}, + {.Sub, "-12acde336009dd260309e0ba1e94bbf1bae3f89ba6db5783b8a5f30cdcddd24ad407fb1b40030c435d331ee3e70d12e249b4e182f71d2621da4f62fc7d1c45289cecc53aa5488f1e38456bc64dfd7fe6af71027b638e8e0a0601f04ffa4868e3c9e9b4ed3b37989b2530d687cc6fdee4fc61bbe4098c40117c713c6482cd4c89721a76f1cb9c0328064fd0b7a5dc4873b7ed366fae107e62603ecd0bb7d5a1ed49ca1a7df3daeae5b26994c9fa653d9bf0a982aeba0200d110227ae65195ccd4a64ea96951ebb89b0b0e99780157a0a2195ea45568b8970d0c08f593e2df8fd318e54eb097486404373be13b7e55c7154d59d5b8566491f4728eab354fcfdbb830d332256d67b36adf04018c77d061b97636372668cd7ebffef0ca2acfa42c567576e6029d19ae2a8f427a36066c1b0ca88b3fc47c98d65057765993bdbfcb983d08da00d1632d8ca9081ff689e0a9ee8342391238b16ce20484b30e625b4c8431470a9ef3f04249ad926e75f8972c8c38556d292aba156b6afdb08e5ab4f1fe1be0e043ba5279aae4d3725126c1e58abb809c6182d50c1087eda53b29252b3a0601509dc485ec5f81eb468f9dffcd4e2927ffdcfaaf4796628da9f73e53b0036433df26f7f650732727b016116ed611b57c3c865099cf90394fb5edff6bc4c76fa7f5c7c964e796e2070c36a41656bfcb2628a592768ee8e4080822b2c1f682", "bc7e49cd60ec036c7c2ef03c6ddcb7e3a4fc732ff3daf381286b46236c7c5bd92b6f3558f0d86fe4c678a19b04eb353824f5f542f9a6662f7faede73b9799f82690f7908d29837186f03fe83ed1b21a62eead43e716aab28e82939517ec07947be5d99d3dcf989a20ac703f825b8c227fcdd34731440212bf5afc6668b95e2af22ce62aeab975900ec037216f1e84cf08d14004d4dbfcc94c59a5c535baecb068396bca92b4d50b5b715aa8c6c6280819503000c692e3072b37fcd2f6cafc2df3aae4a9ca5636b2aa57d91c3ca4d594552ef1b0d99992751c2ecdd16e23d325195568a276d605a2ee66de88ba305d7a26025e66b6ba669ee8c1f9f8154287df3f09a87572045be23912d7ba0bb3db889570b4bd402628dac4af93ca00c9c1ece450b2c64a6776b2f19870206fb4c778cba7bc153a347311547f5da4ddfc86df7b43d75b58654d06053975e576fee8a191019e403ecb2acfaabf0c0cb701b89162da8ccc38a94979c77f6661b254deeede96528bd0bb1c3b03476ab78ac1e26329613b2ec5b3b8de11277f17acec977107c472d537b0d027abfa9019a8dbc84843ee0418aa4cbc784064e85361003f5469f645af2bde4469bb80b9c722c7931db704d863c620de899c4dbf84064ed6554ea39791a72e8f3e53fd49181eb01e589ebb6d14bd16985e41c8581f29bd609aa299c330d28f8b6d7173dd7f50ef28dd1", "-cf2b2800c0f5e0927f38d0f68c7173d55fe06bcb9ab64b04e1113930495a2e23ff77307430db7c2823abc07eebf8481a6eaad6c5f0c38c5159fe41703695e4ab05fc3e4377e0c636a7496a4a3b18a18cde5bd6b9d4f93932ee2b29a17908e22b88474ec11831223d2ff7da7ff228a10cf93ef0571dcc613d722102cb0e632f3894e8d9a077335c28f25342ce97c49564450136bcfbd04af725d9295f13846cf3cd60d7271f283b9b697f3f5666c7be1d85ac82bb23303143c3a24815be458fb3e0fcf405f74f23c5b08c2b3bcba4f9e76c4dbf630251be5ecef5d2aac51cc224ae3bd8d804a8be331da9c9c7215b9eb7ad7fbc23c20afbe2feae4ab6a3f859ac216db97c8dad718e70317d2d330e1a42cd4182fa6b300c6c49ea06cadc404b24ba82126743911959a8c97c3d01b89299630701181fe007659f6c33e19d88398ff1464fb657b7fdecfc9f7e4df9cf3407935c1d16256419dcb07573d9d276d59a5eefd7627e84d9e62588d4911de51b7a21ba95e6366bd91b9f745c0706d31830b1f49330158e078bf74b63cbf58b5c9b37c7c9b4fde20e8b4796a6d5b6e1afbe44e192286951b3e38839cbc5ae03c294c88c5acfb8938e321a9946696acce1ded48165635a04390cec03a856765c3b669fb5b5a0c382c3757924476fea6daa515b5ec7139ace6d7afe8c8e293fec6069f4c25bb2bb6f45bffb45e017c1b48453", .None}, + {.Sub, "-c10de2825db799c1d699e84b57d5d17756685169493e49aebd91b3689d6c72f21a44a849ef10803e8f5fb6e3b44402d68550a4f4e913026f0a24951a2a3a32801df0dd519d97afcb50dbddbae309a754b062e7d417495e08e7f31d9380d698af815bf347b3072ea6ec7e44c89ee4fcfe3e7ea730d3dc17c344594def2decf3a28851e89d82f930ac6d32d035ac7908a1067d7ee9b96784bdbeb541e584a3a0fc2f38aeeae4d1a759ff5d218ce5d0dd34d01e7b17d52ad765305f0b28fecb90f327912f93b8cc8f1a68dd765fdc13ad24b23e5c6dd23353fa22a087faaf81c5bde1b1279c84f28c2738b5c18a5a5c4eec0d7d6acfc342de1baf14d9c06a36659dfa47a71b55993154dc01ab245f086cc01d7591f6f0f674765e0d73196e2aa968f32913b6538519789a55fbcd129c42bd91f7c496a06348cb6ac500924b16aecab2cee3200801f80954762301db2c41f3c6e2e2f26a26be28417f4c113a97af818465d3b7d67b9d0bd1ea1ff39eca59df3c68e83a7afb1ffafe50e273019688d2bae02a7a450b1fe7480f0cbf6baa8800494dbf0fbfcc261065e5645c4b520f17d3dbd1433e6830986c32dfde57368fbbec05065cb162bebf2954305ae13ca3a6a0729b21134da118bc5c94b134e9a62482c1da029c084dee906fd3ffde9640c3b5d2bb31f9f3fb5c96f0c3f036da9332b7c0dff06ca85adf580751117b05da88", "abad104b434cd85517347a0e9ddc874f2dc324393ce6b15a4deda9907519016f3b73aa6c03dbb4de070461459a7669a653c1db06f23d332be2beccc069f4a476e0dbb1c2cf8fb9f170db5944e5c28e4171d0a1287ccc5de53fa1395f1d70912c5e2404116a73476f38676858c9e239e427b7400cac371d4e14b1ac14182c55c76227a15aeb6a33b61ae10d280e16d2db39526d45a7d423cc09e245f083a589bcb63b65464f8fa7c65b39b285c75b47320d65308d4cff76583dd2478d887c2c39102996bf0259222855e153c6deb0ae4d591edd48e9ae927e8bd64c906117bd2a8c7c3972c2741fae9f8d3718d2d0da12a2de7606c9eb79ee7f77cda583db2f2a0ec87da5d3f627905418a120b8af4f6c7b5250d7938c2a0b655e71acc040bf468397f5202975b9068a70bcd83b0ed9223f2d91de946ae24ff623dad1600767f0487d6e8afc57b69ae30a39ff1aee48c0fa23119601b8445f7e4ff10b51a8ca3fb9de9db06184cfb4d8d03c52ff603278d4f3bb49af3d8358306a79e2046053a849fa4e21e53222dd386d1d20162f5388aafef4d57b5059f34de11101d4af121a8b0e74fee19776808e093ff11ef25c33c2edf87a4e0c46254b26e712ea9271993b663e27c3c53530213cbdc93e3662b77ec22a07c04b03e8f003f19f226e297379506b1b47866004cc5b0b11837fd5e2d3cd1f9e63ef445c90e7dc0645bd68ee", "-16cbaf2cda1047216edce6259f5b258c6842b75a28624fb090b7f5cf91285746155b852b5f2ec351c966418294eba6c7cd9127ffbdb50359aece361da942ed6f6fecc8f146d2769bcc1b736ffc8cc3596223388fc9415bbee279456f29e4729dbdf7ff7591d7a761624e5ad2168c736e26635e73d80133511590afa0346194969ea7989f86e6364628813dd5dba8fdb7c3fcfec2f613ba889c89787d608492ab8e574143134614f205a96d412ad2c2466dd83aba5222a4dbd6e3152b68747bd2c37bac652bb25b142bebeca26bac45b720b5d39b6bbe1e678ae76d48b109982e86e2d610f4766abd5d842f8a32d2d28feb05be0d68d2e580a2e8ca765ee1194c8091024c1298f58e5301a4c4517b7bc2c98c7e2ce84829e81c36be4c62e6b68af76c108d67cfad27f24c6b8a54dab1bdfd125567534ce2b1b60e8db63ab1e16bafb4c51ab0459aea437805d00f61a8ab4c105f4886bdf0287bfcf3d1c8c4079c13e44716838006cc0aaba5c469e2a8c58115ca3842a38a3532ebb5c5505f6dc7b04da789c2a3d42c4807c29df81d9db88f44cb3e53b1c8003b3c6755e200121325eea46421fffa718fa3c1fcf7628ebefaef2fed6ff6f04e4747b176dcbcf153fdbd8d948d712d648dd99527a732008dc0184040a5c5351d78073c59f01046a372f23264d417a5b61634bcf01ba5a69158b8dff8ed0979f3be8ef2d17c0c34376", .None}, + {.Sub, "-9fb43e9964fed17c266093794e38c5df58f3b5d0eb15e4cea7d77860814a57c746023e2fe9b775d6070964f461705bd8452ca2a85026d068b12cc468ac387ab0a5e5a7251f7dfecd340c9ee9d7cdcde2ea9d85bd11cd39d462aac5f6cca32f7fe5fba01f197925592cb0290df1e33db5b7a176283513f0ee82560821a9f513cf8851e8322e58a93b2a8f946dcd51c943e5ca65f50f81c574cdd0c579f4e0cd5f17259434e8ae759ed4e9af1141610efaaa3acdaa817307fa03375ea681769ecfc47d7995802d5e302d40f381c5970272d1361a06a7effef20a5df29b517297e76a2dc65b9dc109f616bc7997db471f9d5b96387a9cb2e2cdb2f4065905ff511edcafd99dbdc9392bfd6058822a9c814bb01990f5f4193acae5ee79afb5bd92bb55af200b0abb2fd22c35879a50e3352b3448affa12650db9ebfdb1aeb49c00e9675b65c1378c0ce627f71d0d4e98355e1110f7fa6c4296001dcdfb5c6f9fec9b46f072470cb614be86332be08808618b76c0580eebd389f77aa39caa3865343d0b59599d611a73cf462f8557c73897e6f1b1107133c6f4dd011c4ef9204f8a8d9e7993a64066901d090fc954c2df58194a0a393b254f2af38e6e5a0b1e3d09c3333f7bf93e4d5ab2a498ae5b98406ebf1a8702c5c9efc295c11a9c7c12de06a7cba8c8b73eb2624f96d0c269cc58b36762e440a5f69d2a36230a2e776cc9df11", "629912b9c4bd85723cc947abd1d6c15661846d831b5510ec073f358308668ee79e04a391afd2b4e0a4487263ec32bfc22d0267e1ed9d1718ca146b5f16236cf04fac6e844357c0fa3cf72629e7551d48e6fac8f8fa6f678c3c43469389f799e1513a843d2058acf771424f7a671c37e764ec0288de28ac8a561e00e703d4a5b3a6ac4cc9bef0358b214da2f776b9a9f688627ff30d3aaac94ffd24e57b65ca63a3720ad8afa43db7cb944a6a3d894eb40c459c3b812a150387a99e49aee6df5d0dc64f990e2607346610e537dad7b663d1136d166d30ae362f6ed98d84ed915ece0dfc280c4fc23e9c6f2fbf55aac23fdd94092fc3bb6572014e5cb7753d570e0eb13a6eedee63e6691d7948289ac6ea1e1b66f6f1ec2e2f11d0a5c7e1d7c4d5d3b8dffadafda3ca48fb236c6974f9977ba7886d031a094db6ced460e51897cb7d445dd6ef19177735287192b239da8285faacc9fa91e5877d0825f8d241a8f3d9629a8da8b1447e07b53653bbace7506218492e1442b8ff9f087bb32c3f5c80f8a2020494fb0412e09e8a5c01704428b20cc03faee0957bc38931ff2e21f2f0c70c5382880a0002dfb819771335ca1f4cbe837d40670ea77b2d2a88ecf800ad945d36cbce84a8fe536387b2f7b98df7a307fe412620c4d613e9d1f514d3a8c0d370b584458ccd6de10b3bd587136b2a25199ffeb4d6545d98d9e4bdde693ab", "-a5ddcfc5014aa9d34a2d27f40b5631f4bf0bfca91ccb35dd684b6bb8b1d0c0b5bfe2886904b4a124114dec1aa03387d467fcc9266f00a1da3dce0b1e9d9ab17faae06e0d63b37adcd7dc114c76431fb7790d324ca174304d266efa600542a91dfb0f4862eb7eb028a3c44e05985501342df03650c2f67bb727b7e8301a325e2ac2bcacfeca47ac93dca46e9d44bd63e34e508df44055702162d097c84c972a05515cb4e273a8b97a51a2f3b7e539a3e5eaff276e3985a94a3bb1f88b1c650cc59559de8f110fbea373a201d543447dd90e4750d80ec309d56d54e03429c170fd570ea61e1e86061a00836c93d0a1cbc1596f790d98ee9924d308ec247d53268fbd9aed44aca81f6a63f23016ad262dba51fb47656337fdadd70b840c33db0f08b2eaae0ab86b0a0ed0c539d1177a84c4ac032880e296ae4ec76a9ef4c2ed8a661f2fab9ea67d9e5d9b49a42679bbd3063970a2c70bebb458959e7dbbfcc4072a84869befe741290666ae7f45c3c330007ce1dca1cd17b587749424656b292a051ae379bdaa6a241074396dfd874f9c297cd1dc752eb4fe34bd54e2191331a9bcaaea58de68e7301d370b4aec3412b4bb3ed62172f9559bde06212cb3ad0c89ce0c854f65fb35a54289cee6d6c7bc079e94b782a9dc51cee32259399b642b4133d8dfd40f830b2f2674e1762724c9ea1a0535daa5e1ea8f7bfc97ccc34ab072bc", .None}, + {.Sub, "-c92fce2f880349268668b4f0a2fcc8ca07e97db6f51bfff36c1ca8e3887a753acdfb5c8e1056a50edf95261a58c685ff08210619fddf59631b1dec2878b4d7964c551140d9c0a16a71e1ce46bcc810c16e4c103e613495bfa9e280c62b7f70cde998ceb374f37835c1c19b751d3481f013f076204e72c5bdb13e29b4c7bfe0eee1a348ecba8f8973b7e7952cb48726b93b00fbabd8ed0e194704e52c04dc77450d8474cb938a7a3f3b17a386ba505469f2d7b2e45b1db32c0f0bd36dbe8c6c5885be95fa6c6cf677655123e7b8f362dafa3407c053843bcf98e38a5e3300120234b577583e0240532781c9c1b34c11299d3a5e76118d93086aaa0e14897645b30106baec5fc8d167937c480defa59989d4ee7732e0602baab61e165b3196f1660293c73b5ed75340ea06bf09f8bd3be28541e9d357929104a18efb15f26590b5848ef0f50452e26ac0ab4f7e70451b9d344f95e0fcdfbd9e6910908dea7900f343f6e6f9d563ed31c039b124718fc616abb7a59f8266e424cd83cf650f99e6dcda087629b8a75c8144c2a5ba850392e82c12edbdaaa32bf33d0ee07b63a3c6b40a44aea4d34e5782d50ada2d7c1f056c0a7ed9d5916080fc564c65b21a22c3b864803e282976ec197272b53a2f9731f52f6cfaf6e20eea81bebc282a5a55eb03394617c03399da983c4cc95f8d1ef6a76e72371e36cb20e8bb49580fec1ee5ff", "80eb9b92bea923f11e16a24ed0ce1990db9e1c8ccce3a9caa3fe1b46c59d936b23f1fce573e2b5a4fc01a1de7a4f918d16096ba90c4d78e52ac94c2034ae69924dd439b25ec6c55f2e489d884da9800989d10e06d48acceb817ff15b03c0c9b5682a54ba97c97f744d9165d90ace992693c1e63e3de3e488a52834c61cc57abc98fddf22e3edf25c0eabc0a9b971e875db4f8e601437a78a862f5dab7647f155f7c8fb8a67bb8f13c76fbc80f0a374f602b55f93cbb64a74ea38e8339409c5a515c7f30ba82ccfffbbdf165eb7d2e4c80b9a4597b33eb74d9d8bf38d3391b3757406173d58d321d6096ae9035dfe7958afecafd08e9bef586f23b7eac777cf8420ce30e516f9e3169e35cc8e2d9514548a7405e839aa78dec47acbd1ca654a64e1aa33d0b7c1b7afef25ca39b7564d1327547ce22cbae2f63482b5162418a5601534bc250ea1bc4d50e905095868469c35a665c9ce09cd4e9e6adfca6f86365b76c6d0333a482c275b81607629b1fe1cef74f08ceed61ceddc15b4eab452d7b9cea82089542d633703b5a4775c25467696a39549fb54197bc786af31778a1cd64755fd2ecb50383b6f64f2b0be3e15b647d3ed1c234dc43aec8f6e3dd23e55c730dcc921ca5a8853bf7e2902495f4ae3510d3e3c4afbc63bcb47ccfa49a194fb5029a81d0db41e1cb8ff4e533ad735038a2864ed1155d3cbc85ce51be8088fea", "-14a1b69c246ac6d17a47f573f73cae25ae3879a43c1ffa9be101ac42a4e1808a5f1ed597384395ab3db96c7f8d316178c1e2a71c30a2cd24845e73848ad6341289a294af3388766c9a02a6bcf0a7190caf81d1e4535bf62ab2b6272212f403a8351c3236e0cbcf7aa0f53014e28031b16a7b25c5e8c56aa4656665e7ae4855bab7aa1280f9e7d7bcfc69355d66df90f2f16508a0bed24b5a3cd3442d77b24689b054d7055fb46095302876007aaf3c95ff58d127826d3fda0f944bba1529631fd9b8689061499c67721303a4670c647a305ce4d5806c2f31d366f7deb6691c577a8bb8e9596d5622930ecb2c5114a8a824d270e46a0298260d9cdc5ff50ee153721d4ebd176c2b47e31b2149c1d3aadde5f627d1b1a0aa4897a98e22cfbfc3bcae43dfb0c16990af0d92c8943b01388f5ac9666b5844d73fad611b02c167e361599c3ad1a12f49eb811945487c8ad623969f5fbaacae98aed077b705859ff374ebabdb72d0fac19591bbb119a9b41c4339b2c962c713d0112a999844fc3ecbe96a8b096b30cd4bfb848784a31e128d95ec2b68307a5f7456f04958facdb2de38a519aabd39e9e8fbe446fccde3a5d1b225252c6f1b4ae453742dbd3efec61197f955d0749f3d1746d31f0de3c78f67cd8807a39332d0ab0bd8a03f524a3f77ffe896fbfdd414df8b4f54c17b2c7f62baaf89a9c0b4820f4b483a63d2bd42775e9", .None}, + {.Sub, "3b42cba3b71c18e28cda6bc13b4b3b9c75016d4cb8ef4cf777f8b8203e6bc74b1cc07e7fcfa081411b7abfd67790cceb79325ada158a417a48902252b800e3bcc5a335f7e0e3f3fa746369f2eb05277d867b1f4a5779670401241c1cad87d4018805e8465a1e1ee5af0e06d36f85ccd9e030cb719483f4c28ecdb4abadda9c75e901ac3ae40af140c7631388f793ee6b75ab2d78b6ec921cfdb4e17ac8bb544862d158a7482594aa3463c2decb58115603b85db36dbbcd17cbb7f5d5a848f56ad040f0bafaaea604d40ac4a479415dedd86c1e184d2c33b4108c8b8047a1bfe57d3fd4284286f69b2e99b8de901133dac02075adcfe321c98d18f91112fdfbb9d9c096a7fb2ee242d8486333c3ffeb56df9c91e5b4f85121797d3f71ba8640f34ab503106aa854e4a798dac688b09824eac175727149834e3e778208212eb2433b01dd89d7aa7a40a0e1edbe58599919d39effbfda066ac61a099f5c8fd6dca7e94826bcdd8e68046404f8e5ba8d74da99cc63753044e829b7d98b4a631d3ca61fb781bd743792ced88369783aac7d20b20fb4b014413756b998c44e60d6c95423ea3068ca6f71242f692b7ada6f21dc278a7cf103564c565bc35e93031f5e92b83267304f9bdd5b3e107e562aadf2bd58b6fa436d9596cfc6424c963a465c55d0d181a56057047bb23800a605412dacf4f65d0a54631a07926157bf377dbea5", "2d3c34f6799b0c201340b106395c4b66891182d95d498e4c3af92ce6930bc10391f6adf2248d63896d7461ffaf29d76592bcb496001ad94916cdd5ec1f2aa68b930c5c8efaeeeebdacbb23e613fb1ae487feca1bda6853c9f880f8f7a0aa082207043208dad71d0454418fcdc94bcb29b964b1890a0544be9eee630676a99a101df0696574c7f2b2985f9ed7ac2f0e5de69fb6ce861336c129ab9d7f53c7767e758c1cc14ff763430b55624efe825a4be48a9e8c95ae18b958e9ec27427e15683acb2861b58c4b0436760e47af357fe319e107a6e37521bc79e0c441fb7d632f94efc61e22cfd59522e4e1a08821498ff94cd92d408ed0d481dd37c213fec3ab17cfa42bc2d89b29cb7a9b7d2d259fe572ba2c8159ea6c2d1ff5b11a3ddba0fd38234253ce387dcde467407ca3bc6897c7c238ee84f1623d3d1f4d2930682cdab1064198b16b150a7f13b7efe240309f7b6fae645ff5d94330f147efa720d6d1c94f4ef7d9323683f5a444b242e1f860f0c6aec80a572529bd890a39c996191e3b70891b689466287153b8f2424f82604d15ae4235409fab401f0575fa4891063150aedcaa25ddf34f812ddb33ba7dc1fc6af2e00b739e21621f35193515d7963717926c201b67b33a2b419a675aecad4154529cc82caa52bedcb4b2c60c3d0e55176b90a0a7bb867786d134e5733ecb9e03aeeb49d726ac7d78125c1909a585", "e0696ad3d810cc27999babb01eef035ebefea735ba5beab3cff8b39ab6006478ac9d08dab131db7ae065dd6c866f585e675a644156f683131c24c6698d63d313296d968e5f5053cc7a8460cd70a0c98fe7c552e7d11133a08a323250cddcbdf8101b63d7f4701e15acc7705a63a01b026cc19e88a7eb003efdf51a537310265cb1142d56f42fe8e2f0374b14b64e00d8f0b76aa30d95b5bd40943fb74f3ddc9ed453be5f82e3167290e608fccd5b70a1f2dbf26d80db45e72ce09ae65cae0029575c85945225b009d94b65cca0bde0abe8b167169b711f796abc73e4c245cb5e8500e0a1fb721060bb4d73e07efea4ac6d39c808f5450f50b3bc14efeff380ec1f0f27c385647190ccdc7b696da4b716ce265645b0de4f459878e577caa9ff61291c0bc9c6fd716c3319a49e4f42f8d22ff3c83ec582111015834def0c6856889fb9bf1263f653621ce35ce7619687a582f515b7a109182e918576ce8b605d61ff8d7c5045c31806e60b43377ab7c79a905b4ad25edc2fffa50811099872387e446f8a20ba32ca6672fb085f85cfac064fa066ddf0097ab7979bed8668e384df299818c20499330dfe7fd9fa6b4a41a2b1f8a10f7e2ae34f9a42979ce0986fc811ad4c42f8075a803e53cbbc35306101762a7a6a568ec7d076597e3743a1f477bba1614bfaf48f53ab12f711fcdeee156f2ae1f0a8bf35b14e945631e741920", .None}, + {.Sub, "d729fb048829de10559077ca59dfb689fe23dccc9a3a731e94c2bbbf5f23b6ecd1e3ea51fb43eb9c41e79ad24b788f104169815585bc0f0db2d552b94c33ec0a65f0118150a252c236475134d550f2cde923ba53f31e78bfa05a48baaaa71f9d6a14efeb338015193f9a3f8b0301b47fe7d9139b1ba25507fc7ba9a0abe724874157ec0879b8548d286de17fc763abf5f0d6f6d4c108bec22004f83b9f0f5fece22fa07993e348906a0f93db1ebd5de04880e98cb34e4c6a26b25deaf9f74bfc13ab95f4c9b09869ede86a3e1092db17d996f518209f5416597a6878d70898d7db8d55483bcc9b640e3d1b9c4d793df43a32587e57339971e67aa0c9714b3a2c1ac5368d7f8a11012d175423ea4d75bc8a5320402ad93fcdbc533e41c4f7c15fe761a6463b85aa62c9fd46c3aa5a1d744ac8b18ae81d24fea029d77f1c978e9d9e25cc6a19844ad894db6bb1e951d8f832037def075cda1314fc2b02e28faa0d3af5432f2cf13bf07113e92e15429e105ee1fc3e0c6bdad63a7b0ea07f81ed495d386970b0825969bb8e28f76a3c88d9433e907755c12ac56f068b250f536611cd900db152d6b9c58753bc1b3403b1adda286db97d3af8ee11cf809b69dd9669536524eed3ec36094c341ab506f36a810136ba666d0ce8618bf40cd99faf4cef284204510b065ff4509ed9945ba556f57e5d5a751aaf3cddad1c0ea748972b98", "5e6f9e36de15684225ffb0dfbe04bc5a49eb12758de5da2f835c7dd121145357a56e2ba1c0c049a475b5d03550678ed73e9a4116728539d61c351f98f397c2108b1bb36bc5a6040910424d589904fa60fe86bfeee3e54908ea756c8b3afc3bfcd47509c2f6bb63e2fb24597e65880bf5f5212f0f4cd871cd87eaf573b884ac5cd94f93272a4eef3afca093e7fe5a4569bf3c430721a49e27a3d5b8acef1306929f1b4a4fd70706e1296e4906c85c281fecf9dbb30de645edc3c36357a745a87e245a37921239366b2ed5869ff6a25466c9eabf8276afbe0f369640353bddc3813a027fea2ae7c95ba3c2530af19fc30d573be61dddab3f6904e7629741e4dad9cef55f8d4b519d1fc3404de4799f4205a02712fbe1ba616e4311944957554446f30f45291182654e6737aba49145b06dee5296faf9b74790ef0b1193f667e9e62ec221cf5ba3dfbdf65fbb3797d2969597747b81791eb97072d6659b4a6b4f36113def42ecfeabc0716a43ce8ab2b8458e5530ff4fe31a9fb744483b380f187ab88de98b51e2f2170d7688ce630eb2c705992b54567b8bbba87e6c6cd19372bfadeb1bbcecc4f56edbd669abfe41001912c7bb265f4651a402461f7473006c19fea21232bc3dc85c93e359564fb50bbbc91eb8abd39166f6f4bde8c1026db74d8cf1a39dfd39419fcd9e2565e2d88b9857b8280ebfbca575a7f823c76931c35d", "78ba5ccdaa1475ce2f90c6ea9bdafa2fb438ca570c5498ef11663dee3e0f63952c75beb03a83a1f7cc31ca9cfb11003902cf403f1336d53796a03320589c29f9dad45e158afc4eb9260503dc3c4bf86cea9cfa650f392fb6b5e4dc2f6faae3a0959fe6283cc4b1364475e60c9d79a889f2b7e48bcec9e33a7490b42cf362782a680858e14f6965522bcd4d97c909668c319ab3cd9f64209a7c2f3f8eaffc595a43145629bcdc41af40a14ad4566135c05b870dd9a568067c62eefa9352b1a37def515e62b77761febf12e39e19f086b10fac3595a9ef960722e428439b2ad556a18ad55e10e4d2086a7ac8915bd97ae6e2f6726079885a08e1933e322f665f524bcfd700343873e169d7063f70ae33b6ea2c0d44491ede5f7941a9f86da27d18f452611d2a03451462c59b1f19146d065c761a8fee65dd6db11ec5eb262fa4b76f63aa9abde06b1a9e7bb07a517f42629a8f026d8e3e20a2a225c56798245ad729b753ec3ff2902fffa9a55f8a8fe5cad08ccb3ebc88c0368336c6654772d4cea4aa7fe55e9f6752ae17a029072dd6123da56522ff459f09c6881eb83dbff3521fa4f1f46611c456ab7d526f35c2b194c760b2931df4a74a0f896126f6dd2a4f54c312bc17ae6dacb850c15eb73e5ec5381801ba997b816a973624189d4195a19b5060b30dcd1e548300b42e78cccb5d26a532665af297680523eadfdf65683b", .None}, + {.Sub, "-f42b72003f6252607fff721b3877b49f94c43ca90b79e2473b03a8063987e5c396486cc0e82638a85f4718b5d3387444ec50638b3553a0aa9e2c7be2484232d637eb5a4af8b85bdac4e1fa153a93393e4175695dd5c0b105e7e512da5a6a185c5cb1104cbd939b402a2bac5c280afca9b6331ca5248a2d7d0e7a908b711636bb44823b4baf15b3a9150fdf94733c7ccbc0635a05361b9af99c056d67de508e5bb5976f47d1e19dc530c45d45c667c02b5195dfa9779867f622a6cf7896231db85667d938e69de8bda0646b28b2794b1c1e401717677204283bc817dbce24f6c47e4e18dc510ff77a7a523625bd1bb6e10da9249a46ba60e3618087a5943fde00f557a7040edc4b3e9fa4ef3b2e7ba4184016385b2db74136f5deb02b9e8a648014c3188c17fcc2ebaa48614314d76d0806921f1475641a285d08495de6b5b2706ac5ea971b4f2216f3cc8fd351238b897e38bba180a9344960136103983d0ba53b67a67d6dd004b640b5a72c044847db3ea38a0f3aba73d79e35bbe22e79da8c6af02d3ca37e74b086ea6ac3f296c513f65336cf987f9a482512f8831fa3e1023027a37871df8d67f980d8268f8eb6b388e3e5c0646819e6ecce76f9f6c4f55f9a1c038c81e08715cf425743f740f91de552f313b95b3921f30a80adc2352588559b3c56d884a86b212b6db360ee0a092769034c6e0da4560f5d3d70d8337f70", "6570a280c20cc0043c105a7b98ac1573b4ed9e3f2f84112c7b5de850700439bb8eed83dd42bfa1244d1434c6b1c71987a5debf56635f2bdcd3b75f9ee2b6dd876924b4c5d45cc30ef157740abf10abc06f9fba6571c12d3929c44b8492145ad17006bc60c2fdd99cd660549f2111b709a8b3369f83df376f2af07811c823f88a6fa9098aebc4748bd7f6adb7309353cebf9425234ae01550e21cd26b3b41e671e26b1e59df7e23254a4f98c4dade93ccbf757705cd62f797119756a64db128d37c74c100535ae27c0511fba666d6cc3885529d9eca553cf383b0bfb86ba41ee04310bb701798881fb144d78966d799efac4da01afb05a63ac36d1005d3f1d2890925b174a9cbbe27f1334d1f8cc55317a5f33c1bbb514cf741f9c0183768c9e98cc759579f599c8654179d0f5c8861796bc4da1acd8006c9b05ba7f34b7ffc0887a3ab55cfc7eb25b89efc1e4351df51ba6a91c780b82e123b309d2aef3672e221ac88ed69a192747241181d9083431ce349c523c5662a26af514f146b1c92cd4c9e85bbb3e6b1a7c38f46b7c433e4f2bcf2610d1b23b441d0a3e9d638d6f2ff271368e29aff61c130f8b0c1498a5806cf28c98652672c7ead0f72b1e2ba2d7852d2d66f0116828af5e26d42fcb81c5ce08913ceca0ba9b98267166ababb039cf3cd17033b421a329f866ada3b99094d93538d01386a8248cb86512832265cee", "-1599c1481016f1264bc0fcc96d123ca1349b1dae83afdf373b6619056a98c1f7f2535f09e2ae5d9ccac5b4d7c84ff8dcc922f22e198b2cc8771e3db812af9105da1100f10cd151ee9b6396e1ff9a3e4feb11523c34781de3f11a95e5eec7e732dccb7ccad809174dd008c00fb491cb3b35ee65344a86964ec396b089d393a2f45b42b44d69ada2834ed068d4ba3cfd09a7ff77f2880fbb04a7e223fd3199274cd98028da1b15fc0ea7b13f60aa14653f8110b56af44fb5f8d343e261ee3d4468bd2dc9a3939f8cb39a57666cf19501754a392b4b631c7411bbf78d79439c915a4c15ed44c68a87f9a2b970daf23f350d0b9f6c4b541c0071e24ed97ab6831b089fe7d5878b8a8096690d83c5abb40f72fe6097476e9088e2e37d87043d5f32e69a18a71e3b7565f71fe5ffe52715fce817256f92f42e420f20d63f1513235ae78f26995eceb170d3cac6b8bf194756adb38a34d690161625b9b43fe2e87737e875d142f6ad771972ab2f6bf4994cb8af821ed4f3300209dfe4d870af699966d59b78eb2f8576526584a79b17bb6caaa06b34597dcb3a34e89f5b6e259587ad401573b0c5b0cdeef292a7988e7d9190eba580caf46b6cf466599dde9abd97f22d7eceed9fb82f709a0c524c486f3f9157ac5dc06e28366e2db757197187cf029254968535a13c6c29dc0b1d88d9c871356babc904da678269edae38e990a59dc5e", .None}, + {.Sub, "-78b0b7f32541904323bd065b795b14315f763b8c453a26e1c98492ecd88a133ebac080b95e10ac59f17b19811df2130a505a908c7995a0373ed85d83da7a31bfaf67972c27fef1e3e5744689578059aec01e2ff68c8532a6186c364a42b403bd55aab5f20f994f134eb11957c87d8d9c2a5d6babb6ad525c8584c543416e2d70b5d10ddc8b63d05de4c41ddde12b448faa46c8b9417019c35dc1fc2ab29da5c78b812648c8e594c63e2a6e469389d150085347110bf4b38be1de1a281bfdd8bda057dc5a30920293e59413953fb01b50f6e702b686b6f09540a938f29293bbcb6e9a92ee5d844c638284181dfdfe2040ef4b00a8725fbc76a7e105335dc02aeb6fe95d1672ae9c7133042a69e021f95b48b74a57d0edfdd3c4a5d1b34ca04393dd63fa1c5198c71cf43fc0a9d6664110ab2e6bd53f7666956ba4720a1e778aaa0d2fb4a5b83d2079b65718c15f3bb0c69ba055c99e408aa5abe49b89e612f55ecf2b602a734f111fe65c96f1d6e6695817a2f34dc6a2fa72cc25c00a3ddb83c5fc4755a760554ee3fd512315cbb6d2c331129e836110ec739bbf75d2abcfec06f177859545a575c208e7cbfddcd4e4df43ec0f45aef9d1cf47281482ab61b6937929948c69d934953b9071ac6bb9c70a7f02992d5d9fb6e748b1c757a48d1b98c0ce51a061514ecf4fb1b69185ef4cf945e4e9bacf831fdeb5af8ac95effa0e2", "ef6840df31ff32c6e473225f8fccbc10a9e0419c2ef396ded67108a708e8de615c2735933c9bf997d07ec9286a9f180068adc65c1c6e3d5889867a2338fd9cf0f70e46850588c5109b51059ea691a10fcec3dfed9246579ff700e294094ab0ff7990f5740363faa8e8012657094b48e55523758ba589346d53c959fa68b5723f7c1b10695a7d02e965d8fe00f9b4798d1babe62afe00efa7af635d063a76ba322445acaea00c15951c501bdfe55ceb0b7c11db670948845e09bc61c69e9675b6f9b2997b640a84b886bc8b44261b54bde863652e1cdd4be85195279c9fa065b17f33585448012ad3fa91ea1c4fd09208d891fb20fb5e973e69b403af28b43ce1d1602b65ea78481f909473463ca0c87af78fc61a97aef354d3173dc3ae006573f50d375d98dc7fbca84b9dd5039a3c6a707d37c04f119cd34b0f802c433b564cd03d93788b271cc6a6ff26f07c6c4a7a5391fb2f2d7ddf1023ed5f37fefe07b0a87aea8db958112b76d140be92422470ec893f1d71c6b393e09db89237c0004590979decbd29f2abdffe1decf7a63b75e07febb2fe6b5f8d5dd0eda1fd7e698b56f654d2f1fbe0f9bdbd5091d7895e6059a90147d97ea8295fa2b14207b3548eca17724ee634a83c9e1a9270fb391d40762f8955b9b10f4518de13e1b99fcb0ffab94b619cf4eedbfacd614af51dee9a4a8fb796333125adffa45ac92ade0251", "-16818f8d25740c30a083028bb0927d04209567d28742dbdc09ff59b93e172f1a016e7b64c9aaca5f1c1f9e2a988912b0ab90856e89603dd8fc85ed7a71377ceb0a675ddb12d87b6f480c54c27fe11fabe8ee20fe41ecb8a460f6d18de4bfeb4bccf3bab6612fd49bc36b23faed1c8d6817f80e1375c3686c9d94e1f3daa239fb031ec1e45e5e0d3474a9d1bdedadfbe1cc5f2aee43f71096b0d255930ed145ff9afc6d2f768f1aa5b5a7a8a2678e6bc5b84652278153d37e9eb9a7beeba944e749a0a75d5949c874c6c509ed965cb700edf4a67e4a3943c7d923e608f3234217cedcdeb42a58577377d16023a4dceb249c7dcfbc96dbe53b5119508e2867467cd4149887c5d26e490c3989db01cc2c1d640471072689cf12897bd0f76faa0a907d2713179ea7546d99c8b5e7eda007d7b1baba3958e880368b6b3f23661b2e0f6dd6d481e43643d405d563fb1dba7fb40ef3250f8cbbe69b5cfd1fac1e510fd0f77a64ab82ca7224b5d2dd7b069288dc9042c326b3869ae06acc3789c759b840b8cdef3941d7f418fdd4f4102c35d0e3911928a365f7c4c00f9906374a94e5592486dda6837a156bbc6a51c8fb45e433f9d95108d887879f8a6cac5c4b3150b22434106db500ddcd1d9ab041d66f2e44af53222831750c62c618fdb395e2ce6a8bb879d01fe463dab4a7f17dc7b0d3b939074a15102b4458cb553e59289dda333", .None}, + {.Sub, "e2bb94013d1f66b36f4c97393ac9ccf08c6500dd09f097a5d746ee3a7b18361a1a56213fed7ae7b151a8f514216cdffa5b9ef87a1c60cdd276a24d86e7856f5db88fa58667e835bcb91c743be78713e28fcc9aea139bb70cadd6f55fa85851a384e4634a898425c2868044f17c282ad66a529aa391a878b97e288a1ed8f8a6123036c696bd7576b635310c7b22b9fb5a2b4efadd1581ecca9d8e5ced23a87399ee2b0719307cabd10856992f7f0a201f3d0590302304b701bab69b13597dfb7bf340e64f6b6f9e19b5b7f5eac18ae266452b4f61d557fe2d78d0e1f359d32fc760835b420a11e222bfdcba57e449d1f0f9ffb17c64cc68de84e25ed29fb1ae54bbe5cb74026dbb5f3eccd65dc092bbda1f7353b7984f7d9653db05311811242707601c177576693f21410c4a22b1d37e3ea1ad212391b09f9dce3fa3f14119cce32fb5a1656c88a142d324fd72ae197618900c77d7e0308ad16e052af2bfc27959e61be80e573f0f21c6623430ee47722201a57bbaa2c388434f96aa903cc559af3e5eb0b261a5b8cb5f52893033179ad4c86b42a08d383854c9f2ce2677160a3cf48ea1ce63be40732c9511e83da4830315a349d4a29374e7bd3d5dba07205b6d384d00e80f65f15f2d7ff0d93839c1acbdef11a242a811d9f15c11656f58e04b7671ddd853941e377ad940938964888a64344adbf244140ade6213cee6f159", "669e210d3061fa5412016f6deb8c81c403c7f6b8c5130f78a81b7900fd6721d82b4b9ecf46ced33d5d54b87d326baf5aa789474c759d4033ef75329f22b0372deccf22cc667c930f768425ae7e12315e98f5235510d0194a2db8449fc59b40f933ce920ca1483d5f02772056370b89ee4b6da9dc5fb82b1727ff02ce1b7030c4db50e1f02d542552ef4f2ab6510b48c6a02ab4271f3aaf0314155d2facff37ab4fb3284d954463bcdaa650d8364bc26d4609af22d0786bb2d5e9278f56ef2307b97db4c04e7247805c475e5f3be6cfc5e0addd41f7d478be4718631b846aaf70b8a7302c856375ffb1820b91b6469ec7bf05407c203e4731197cf689a873f5a4c02759ce05a406b1670a3a9fc8d8a8251bdd09109920cfd6b5dbd78d361515c7be515802932275c07523c65088847f8b5cdf9ea4451f065f76a614b43deb88bbeee19a434a090f9a76059f2e923af8c1ca09fea2e7d9d82c93c335b12e395b804183c3e5eb619a98b1ab0d705cdc5d13f6f35ef7d42574f859f5f2e3d494cff48d2a25a3c54eb52a6dc9c483158b4f8314dedb0481cf2e66f6d8aa5209229365ba288b4703cc2d5577ae87f6b6d850078fd13556d9c84354b755ce52242f4715fb57440ec2e1752b2d0dafc1a80355f36e8176c0537b7a533d393130cf4dcf52a1105702700591b7d6909a79642d1c3e9a901144e1087516fd674d2e22625c91", "7c1d72f40cbd6c5f5d4b27cb4f3d4b2c889d0a2444dd882d2f2b75397db11441ef0a8270a6ac1473f4543c96ef01309fb415b12da6c38d9e872d1ae7c4d5382fcbc082ba016ba2ad42984e8d6974e283f6d7779502cb9dc2801eb0bfe2bd10aa5115d13de83be8638409249b451ca0e81ee4f0c731f04da256298750bd88754d54e5e4a69021516345e1e1c4d1aeb2938b2446b5f6473dc78978ffbd76a93bee9e77decb9b3848142db0485748be5db1f6fbe10d528c4b4ee4cd7384028ed87439c3318f1cfd56995970978b85a412a0647d721fdd83856f31b87ed7d5688056a7dc2b1584ae6c230e5aaec62e0333293afa7100448e21ad6b656848f73db8affbbe71a5fcc9b4add7c29bbdf7ba13b503964aa6ff2eadbf9dff2da3e1fc0e5f490ec414e253f37eac1d45f99a2d53f2e1c20e7cde72aa4027282aefb3559110f44e1b5e1b637906cccd85cee07320b44e860dd4f006585e3daacf79c48666f91862580222f5a476701b54c3d411ea5e2b0e4683e67d4e8fe959a3c6bba7f5652214390ced12f08e5d958e061aa7c817bfe9903e1ebe09d15df1487c1d5482a482cc035aca9790eafb7e0d1b3165547b73446df2fada502030676f0b95d7d94571e108f2252df0c6321fd02f3134e3ce3e3c78514ec72dbe9cb82ae09621898daa661adb684e026660ea3ec72f5c4849efd42305fae9cefd0d7714e5ac8494c8", .None}, + {.Sub, "-5e94907f3857916bcf09a7dc1221b1b7fa3e2edf218cc1d841868cb6f9a178565fff4276c7c69f98da86107bb71188f01f368a419834dc57a01ebf5b1f06bdfd17c8cf02490faab688d0b1929b1a1d8cca75ebec7b35c464bec7197cdaabe8005a1b5173b67eff9b38236053f46c267ea969bf39e91021e9fd55abe85918292e0df715c21b0b1ecc7f9aaa972be84742e965d601f2bd274c452177f0f356f4b2441db784a6dfc69a886f0fd954f05aa7b22dfb8ac08032a2eb688f55253c05dd861c5491c8d4aa37b72ed7a641d81a4c779b17eeab25ed40fd1b794c49624b1a2f68e0ebebb2d36f62b3f10b9d868a9452fb3b3b15bdd48caa9e9450356c1562fbce268311078bd0a4d18e417f8c4e09a3e2406d0a6dc656b7a58c090367fd5bf4c9ab31c82860fcb880e59680bac34a1d1fdad27bc239fa808759603c7a53f6975bc534731ac24c31b29c58b2e24505c6a120a9a4b42b3954400678d36a4afa46378e81cfbbebb14e8be31003f45ee1fd09cb58283ceebbe5ed50d55549d2db8c4caeb93d6347860afaba19de5ce8f830611c307e16684452e9d18220e3f8dd20ee2d9ba612a73cd4ddbd37741a9d2bbf17e7b90a0ca948ca486f50be47e4b1d7e45880795af0b4a07f4a193d226c4ddb928c25b653f6f61ab17a3cdd017ee4fb098ef94edbecce9ae503b8db2bf44834531d7c659352a22fb6dc60aae5576e", "64712b6ac833d9b53776426b83abd38ee32d39f37981d5b368b511ff31cc77e3b53309b1b106815d2e183e72e0ac1c77b6640df985a2d5646a477e6ba4ff2e417958d20ce6cdb5d257548e5e2faa795223e12eaa2c2feecb47a3b420648f9585b476787e56092bd9a11ba9cdef5b83e2648d71227f7fceb9b7aecefe4cb3257ac2d5cd6de3150a7158d70b071847217c91118de13175f6ead0b249550aa01691387188ebe695d8f65c459f52121d9757962c0b061bd7ae3e3b703b6092ab33b181e05680d58871107d469816f3de646bc1ae19e32191a9d525159389e3a0b6ae9ba5c8be3bc51899ec2d8a5c3a63e8fd7c3323e21cc9094e320ec317e45b097c6f243b7fec11b9cbc148e4a282593495bd54dee5e65b372d60fda1c44661f536ae21b01dc5c1b1508f1be55a14a4a4bd88148544e230f047debd3133fe9ad24208f6fad6a204eccfd242d0291fe9701b7935110770b90f09ed4d5b0902549db6164638622149eaf56d887c554c913161c259614967383258c9f7e34288640ca19d21958b389acd0426d15861d6a0ade10652adfe3b7b4e6bf887fc618e7f80593b760e21d89b165692fe51c1684666dca6e967fb5cabe4e70bc9d48281aae04830cb832486023644a39de7f813427338952967b60ec4a605b82b6f6760b372e3dff9e7033197592891f039b9fd87ba3f202aa2de5240bf5fb02d58c940dbd57b", "-c305bbea008b6b21067fea4795cd8546dd6b68d29b0e978baa3b9eb62b6df03a15324c2878cd20f6089e4eee97bda567d59a983b1dd7b1bc0a663dc6c405ec3e9121a10f2fdd6088e0253ff0cac496deee571a96a765b330066acd9d3f3b7d860e91c9f20c882b74d93f0a21e3c7aa610df7305c688ff0a3b5047ae6a5cb4ea8d0cce32ffe20293dd871b59e442f68bf7a7763e324331e3715d3c145fdf70b437c8f40708d759f90e4b4af2b670df1ff485a0690dc57e0e126d8cab5b7e7398f07fcab129e5d1b4834756fbd35b67eb8394931d1ccb7971622310cd62d0301c8cb0ea9aa2777ec094ee17b67d7ea7391cf2e5f1d3286dddadcad576819c71edf6af26202fd19459c661a72e401e5829f61371f52f0c8fd8418a32dcd49c9f292a2eb5b4f8dea124d479ccaf0955f6807a53460175df32a425f448a943b152638a052c00b151faf1c03f56c81d2cbb5213fd631b1156d3a43418d6181d5bee8b05c7dc6e3f105d6a6bc145f6550859043bf632ca18f752114afe53417ddaddf7d296e444475fe148a31cc127bb4fd96d936b3ca2eb991b6b04b71cde3af6379365c643bbd7eadbd9367dc0ef8dc61040866014fb466b88e2fd61243d33ff2c4fa08afdba4ff5d26f9441d32115064df8670bbf3dbc5189cfbd2dce9a43db4f1c8db0375fc807345f72cd53d72d8b3ae87547dc05ab7d41201dfe43529ebc12ce9", .None}, + {.Sub, "-e7699b1366ecf0726aa26321a69786b7bcad434baece16b06459e17e63021e4b1896f941d160c9c9156610cff9ee25a17f7a74cbf6a83199a5aeddfd0929d56ec797be37b0118a25ee18ed29c7f1919891f6a60fff79dcb19886932c470be1cdbc408041daebcb6f336fc5274cdf68ab106c539ed423d89107af5d3d179078e6f034d059f9fc1b1ac48c10c87df957ebbe0c0fb76b296106269e0b4f0283c5676810620280ef78eaec08afa68d5cc6235fd049defcf7695b9a602a15246e8d439535df8810c1cb49bc411a9020fa4afad73037120a9dc0db232922f3fa80c6440ac03a134179fb0925f0a62d60018530177b6be48356be338cda33a87fa15ce64668e54ffdfeb409f7c9b15f6699b1c26e38da3e2b75a0248bdcbc8c335e33e81386548d17c87165e8e20cecda814ee00fa5fdeec9348e99ed8915a15e53756d8cb2fa4d44babdd3cc2f485cd9075ab1e7a9fae0e905a0d1bbee45cc6210555b64bf54f4fa33ffaecd0a116464acf6e333b38a600ac773643368223804e515742c3974d3888b2b29a9f9b5f7facdbc0629b53d7fe7dab679202bd11c2a492b8be69a09d553fa5eb5125c6dc3246c5f1972a8a5d505b5c5a8799a5d048ce3f7750e35331a6f88201cc7364de8e59e4977789cf057f749de0c26989ad0d1a0b87492d066c92e755add8619a3d767c5d6c7eac89fb84eaf03a6888c830263913433", "daa4b8fde43d1aa1f75f249c46dec51dd15ac8b4df3882aac91de27d6625b498462b4d8c8f4b0cbe6726ddb1c697b35cc8bb08251f0a6d628199668bd02f25b61db470c2f9bd5de3d4a65f70c4ae8462398b60762e790f854c0f687b1bc4ccea772b6e13dd15f4d73077b640abd23c504a2f16a892b82f270bc361039eeaee20ae74611656ad733ce8bb75176fffdced9e16162d1132b589a13614024318e18ad351e72aba11485b0a2044212fa06358e399cf9d9b0faecc778ddf5d227de1cda9e3f575547f88ce9db13bc37ed34423a8cf2ced47989389d55b51f20f95353b08438e8c556dfaaec3696bfd983cc24dd6e2a0d5d017a9151b5a45602f459e86c75313efdc8e1d5f2d7e05a09194e3eb638c3da5a9eadadd2e89ac816b5cbc98537729dfe88a5aa7f9a33282a11cef8550482236c9807446a4040917fd9cfff527259890b6ae584ef89f3338eae9714f9ef760dda0d1b6efdfeb0458fd00583c795d709793420495a48a8e2567f94c9ab3504270e25597abbc230db354a9d375088f78be3d6e0050f429828525e9565c5bb2ef6a1f0530c6fb4f55ed398f81566d9f3937af624609bea8f758e9aa5af9179751cbd54f26566259433dfb2d5b283d27b9c107592fcf78cd2baf2b4e72cfa676e6358fe849ac714f865fb5d4f776bd3ace31e8745764ecb3fe7d74412de89ba3019c0d4aab789917468a20a16aa2", "-1c20e54114b2a0b14620187bded764bd58e080c008e06995b2d77c3fbc927d2e35ec246ce60abd6877c8cee81c085d8fe48357cf115b29efc27484488d958fb24e54c2efaa9cee809c2bf4c9a8ca015facb8206862df2ec36e495fba762d0aeb8336bee55b801c04663e77b67f8b1a4fb5a9b6a4766dc07b81372be40b67b67079ea9317050a98e57ad4785dfedf934d95c2225e47c5c168fc7d41f51459ca6f23b62492d3b00c145f628f3c7bcfd297c436a197c9807182811ee097246ec6f113f19d4fd6541541859f256539fcd8f1e7fff63ff52365464f88474e60a15fb7f1303c89f96e7f5b7e95a122af83e477dee5e0cba536e6748a8347908aee6fb6d0dbbf93fda8cd1692547b6fff82e95add1c517e3d5607b01ba66690d9ebaf08066fd7e6d0052cc0de2853f6f7b9e3e655fee202592b502e0918d1eb95bf07562b3d892ddfb691622c4ce7b95c3f0cc0186a15bbe89d757c19bd94a255f10ad97de1cc58c8d76044471949f89cca6437de703ccd0ed1d0b0fef8b2feb598ee8e934c8ed91c5f92b7a9e23387d20b7126285682cea06dfe7401b7b270963d8ace25439430d035ca4bed105651c0e16ba128a3ff7a0db04ebfedbf3a0428811529d4b5cecdb76e14fec4003799810ecbc471f13d68d873227b897e821308775afeb500b34fb16e9b24272cda254dc0704b0866ba1545bf9af1f21a3c98c84329ed5", .None}, + {.Sub, "1447b95885dcfc72bd80454d540cf4cdae3d5478349478f64b290dbf6570a5f2c35ca063106ffd86344fd9385e52a5e6b54479d0e66245ad6f027828d71d1041affdcaf1c16ae1ebdd1665c46cf97608f2cb6eedcfd4d11a743d21c69a046429646107fdabc4fed80f2a176aebfcb174767a5b0c3269b085a17f6c424c2bf0bb815047266692c23b601386109d82ac08354baf250202d15ef89a6667803568a7db45256e2db28080468c68d30b37a1285ab4a2cb8109268ffc83824375714fd3c8ad9c06a6980a2b1f2790cac83271af01145d76c6b1436793e1062d58ce1550f73e32f696ca8c11a8715daeee0405bdefd8423659215748d7670794335a3095e00221ce0346af5248c9bac369bc9555e713391a228d083213bac2b81e723e7717f3b4b849a410cc8557411d00fcee142ae53d2507ed279115244566df7409bc6668b78e233d485bcaa8568c81ed2d8db3741ed9f29d5986144f42d7f0179b6d92f2095971afb3a7deca3c235732dcc411f5fd363e65ebcc27b9e31557540b3838789d7f5272d21b7482ec2b0a8206f422630696c926b2fbc5c87fa65eb88f8c7d2bfa1ec88d60fa398d7718906fb5555f4780e13f09f904473171086463c7ead45bfb7f9e78631ffbcfaf863cfa35c053e8cfff72468169494b4e062267f4898af3c18a52ac2ef5b88745d5ea5c68adab4591e0ed044219568f2fd6341fbe89", "bb432a5dfbe0b210d12924dc49a404855f5dd8fd02355f2911031bb67407833f940124962d81ddb82b0df0443737b4423a7b9be697da6120e3ce8e8e0cc36e4ca9d35ba78fe62dfc3ea6e8336c9bf31760b3b3c12aa15b9731bb1c7d0dff899213d95636294b7c59a976df70f8042c716eb524f73e43591ff26f4050d88419e32af31565ed7d2c2c88cbea67a1be6f372dc3d3417aa91e384a95ddcba582d57d5be573d17a5f9c1057173524cfb14996a60cfbaacd2cac943dbd24ac50b2dc9d0cfa47917b386fe28584a96753b13797fd67d9d94beea66d2c2ac99ccc04b84a7b36a412ed053ef178ece8461a667688944288c78fbd918ca834a9d2b7198a19cdfbe7ce5c9fc74c6d6d9f807c2c13071ad65a3621a8cb79ab03385ea099d439ed1022f6bef5a2e40965c72418969a01e98be1db357ad3e8d00a4b407ea98e42988252a27b2fc3816f2e74313f805574ce726c1bf3b0bb67e1b95fbce36247aba714680d403ab514b656030b6b5539dae5638365abb0c6d3cf821b15abd3d3a16c68e509d5897534a61f6d02114c6ca51b57dfd15f2ca5ac2b0af6983800d0bb2be7b0e63d2ede73ec603234b0c2dbb8e90c94777924b4c2f04db3970c3f1f7ba202b9f4d573aaf3b154d6f67dbe63ec086d50ad546ab2ae727a69bac43628764b67b479ceb45de8f048c5897b3dc8822e785107d829bab94229cc27edc2b1b0", "-a6fb71057603b59e13a8df8ef5970fb7b1208484cda0e632c5da0df70e96dd4cd0a484331d11e031f6be170bd8e50e5b85372215b1781b7374cc166535a65e0af9d590b5ce7b4c106190826effa27d0e6de844d35acc8a7cbd7dfab673fb2568af784e387d867d819a4cc8060c077afcf83ac9eb0bd9a89a50efd40e8c582927a9a2ce3f86ea69f128b86457043bc32ef878241c78a64cd951fb7764254d6cd580a04e634cad1b90108acc51c479a86e4b5858df4c2386044139a268db418cc9444cab8ad4a065b7665d189c8b7ec5e8fc537c62853d63059849c36f7336a2f983f8711c563ab2dfd07b8a972c6270caa46a4691369c3a43d0cda23e83bf5983edf9c600595917fa24a3e4bd126f7db133c3211bff1bc347974875a6822795c2d51c6e3e75519217840e86071799abedbea6a4b62d8dac57bae605d99f35848632199b1457f27b25a4861da4bd9327e71afe4d42011361e1cd6a1ce4f34aac3e14225eb3ce8b016cd78bc6e814225d16d36d862f6d4adb07a7c83800547fc86933f0478a8316a319319c80d706ca65b0f8f4d93a9605f2b0654276f1d948412eaebbb6c774a17d79b2d2bb1c2053266389c513963a1abbbea91c428ea7db5790cda6be7536fb47d3b585277040c42e2bb48480ade2243145292f1bb4a1ce33ecc073f2ef7c082ef337c17fb390e15fd48332bf26eb25789feb9a9c51b9a2f327", .None}, + {.Sub, "610714ec9551586b9f083b72a49f29d00e17e24267799f8c48f64160ce35e4d27d0fc43d072aeeb1e3e1f79fa13f9a0c1ccbb47874c75fbfd5aa444ab7af68fd70ac63f9b0fd0dd2c096cd1e604fdbd60c36fd1da140298cf1feea8498e4392e04fdb3b5113597442363de9aeb5e6ae270cdfb1ea484922b49bbd5737b6f94a29a75e2617b6aa4708be3936b39f7c2253796dd7028f8e8198875ba4d919037b5d4d6d4e964f4d236d7690ba4128fc796d5615732d030979d1cf22769d1b3b7103da35c053689d62343d6b6caf990bbc8fbf28e508e8934351294dfe07e054692a32106ec5695685e099a98c973b812bd2b26ca8796202cead3aa9ebfc3af3da4dfe3a089181d761a7d65cc7524b41e47c2fe38782af39128fd713c980e8e986975614103cc3ac3c5c6b7f5d44b2e42a4a6d047cb2253b40b7d17f8f959fad7f8b28cea453ba281cdb70e40675be1412912119cb2c998958184d5beedb5ada3eac6e3a26eeacc0458290da6fa54ff4dffd1b58a8f78892fe17683b73bd4b62eb14758b65b59f9d4e29140686d11b8683d9b3df7ee0df6ae833ff356c24d1bebdbe80ebac0fb9f5b6cfb1aa7aebda5b0165b363d07b232a1589adaf762852af213b902a35be3a98f62a77c19d6621b094d70c9ee04cf60b13f8fbda31e262507a0f2a540b7cf2ad88787833ec6870bf43e6585d3d62def2476be9b0115221102b6", "db274668c3a3046fa62308ed5f7dae77bc3c033d5f7aeaad84ca1a7e98da0291322a0e9809f915598a887efc148d3b4f910757566de935df830d6ce9739ae14ec9a16fc476a9c610122f42ff506466d012b1da44bdffb6415896d644c9b0435d4ac081f24e55786b4ac9f7564395f738c45b5c16f3b447b340ff11aeaf941089cdefff8da1a37448ab5271e5bcdcbde37c5d9b8c5b2f4e35fa365129f38cba5da7e810a1795e761e6e77f802d7cde2bb20eedf56fdd04c1826091ef683bdb6bdc38972807040e106ca3965200c2203c65a86412fadacd6187abf8c03b76a02f2da42aa32238da30362defc075c29e1113b29fbe73971e0ad3aee78cd0154ec21027e888a7ee8e18476f2f9a498d918580e6ce5906496ae13aa5e92af2c995783307d2fe091850e9fcdb7a16ed6049d0c05f34bb17842d55aa8eed508197450c6b716907503b8a16d536ebcbfc20a8e46d0ae18f4e62824010eae5e7a406628e8f896fc431b796b0162f92122c71ade366711571abb87f886b6a59ac4266c473704564bc8d507291119796b4773db104f1f23f428fc6e029d5d4d4ac4d755ed176a4e5f6ae2b4fd7fccc2cd2a9496aa55081b7495cd3e79fc39342d3bf010c15de5e823988f2fd8d3deb8b2ded2cf356c6e44e6c6c3c5a3f391f386a62d839e96fdac82d66ef6743986e8b0033af7cb740610f6660156eda41f3fdbe50c5743e6", "-7a20317c2e51ac04071acd7abade84a7ae2420faf8014b213bd3d91dcaa41dbeb51a4a5b02ce26a7a6a6875c734da143743ba2ddf921d61fad63289ebbeb785158f50bcac5acb83d519875e0f0148afa067add271cbf8cb46697ebc030cc0a2f45c2ce3d3d1fe127276618bb58378c56538d60f84f2fb587f7433c3b34247be7337a1d2c2638cfd81f6ede7a82e4fbbe44c6be1c3236661c71c096dc61fc82a7d3113bb81469a3e7970eec5ec53e1b244b8d88242d9fb47b0916f78cb209ffad85e6167b39b70ae38662ae55129147fd5e93b2df1f23a1e3682aac233964bc603721a345ccf83aa55944633de871ce541003315fa351b3c26743da0d3da5ae7c229ae80166cb6b69f98d2d2f7424fa104b6ead1839a31ceaaced56171e0abf19bb1beedcc54a4ada06ffab9a8ad65a675f2303e655ef214f2bd6dc0ebf7978ce0489a62fc8161f9f9c607c5866294d1dbe9c7c421c8f8e7f89d89f8c8ab884fe31b359d430ad66a939eb7a28721b9036955bcc8b42fec8a54021e38851b61885bcfd956d7b0d542e883902da6222a81183e5fc3aee77541a1d59f4028a3a013b823fa4a9e715a212d1a8257bd6f0fa3eace5378e1b0bd8a39e5935d96ae5cf4a2ce5803cab864971373c990870b42c1efd7af8c1f464f2b40235e388075e96f60b07421e9fcb9bb1ff65713cb3ebd735a08b228fd367c92d60a4dacfea464130", .None}, + {.Sub, "810cc5f334ff377df039d0ebbba9cd43cc8e0c27b3d4f9d379a41d1580f990dedd47c0cd3eb90fb221329f7fe96b53485791d66a0f98793ff2dc3ae1704ba5ebbb7b08c2cc9482bf16bd992f7625820144b4289e8feb7aec7e31b14f98bfe4fef5b8b1cc9f0d82782fb8b58cea7a6d6c4c34da095246b0d0b01f0f1ef6b2541a397387a1cd83457857142f6900ab68dbd5d6ff1526dafc7fb6ce5a64dea1331e62f0ebfb88cdb38530d3167a766c580a39dd2fff7d85a8e31a2354c52cb49e8285bd75f9738a49ad25ab5578064fe603042011e4517bc1d52abf0ee8dbf85b31360caec9f1a0dcd565650ee4d1d08dec1739ba0024dcab15fbbeed36e64fcfea4f0f46c8c7cce7e67fab2c6a6d443894b27a57d225c57d5de7cbfe96d582afba07f399d7368fdbeaced22254dc90a569a562f37b8e0c1ddf38c5bb290b4b9edd6f92767e258c30801988c21011a0eb359aae324ef974d4231eadcb8d4e9f40981783bf4a28b2de45c8ad9a24ee3751ce80841f0321c416cb40269d85a57518d553b0ff7c58b02b961f90431df0be0ff8a7a57a5571201ddc566790e5df20610b7c20e84d1e20cc6cab3c95adc971556cc0357b86676bd46e78aad256e78aa67147249cf448b79c4c868ed230a5f10ff50bbb4818037907679aa7049876ecff321193e98e5aa361684d3313e32b0c010bf9037393516926e5abb81b2a1246b6f0", "7ee144e1af27d1a53863b246977a97fe6d28a43342862b320b17a87432e226f5122f4a6aec3e82dded67ab9195fc7359e753980b5169b187feab334fcc141765d52ecabd0143979659837914d146064f3642da29dee981fed6f81824411dcae76d9d808bf3cd73ed3a60eb9dfb51727994657a0a33e8a023e98f7bc32ddf72c0540259f4d8e2749fd6eaa8983eda73687a9ff60dbbb5a14f0ae1d49744452b64fe793c243047aec9681ea29e750fa9054182c70888637cfcc5bc5519f5e6c67c5142be920bbde6d37e6022799fd1dc0ad0120eabb8f3573c5f131bc1012e125fb3af668127a9cdd1fad1999071c76e595e936eb5b7471f7d13e13b27a46f8227370ed027d75be106963dffe6365090559db67d3080ede613e1a9569508566d9a39fa29d6c6ec36884f96ba03156c7d6bc2df08e299e5ca13b360093a7dad7cad42a4f0f8de1f1f05f0cbdc77a2c47c92f86dc3ea52e31850e5bec5d1ef4a9c2f897512a44d77284104689a7463349107f4da2c25f67210bf529a5a3ff5e081fc0103210f040b687f53409a02babe42b09d476c8b10edfa65f3953e57996688c5e767439d66bf2f8bcf8026004a7cb1dc07a7cdd18efd407dfdf23c212729a573583d77a4986e89241452c6456578a2d80ed6c6648164229a7f1b3d616618d9a78bcc48440a9b4bec09607fa5e6024f75ccb2879c094f258bc62b142e086a19fc", "22b811185d765d8b7d61ea5242f35455f6567f4714ecea16e8c74a14e1769e9cb187662527a8cd433caf3ee536edfee703e3e5ebe2ec7b7f4310791a4378e85e64c3e05cb50eb28bd3a201aa4df7bb20e714e74b101f8eda739992b57a21a17881b3140ab400e8af557c9eeef28faf2b7cf5fff1e5e10acc68f935bc8d2e159e5712dacf4a0d0d8802986d0c1d0f5735b3709076b255b30abec85cd9a5c07b96477afd7588604bbc8b473dc015caf04f85a68f6f5222be65466ffab36cdd806347ab76767cc62d9a74b32fe667e09f8340e033898886a98cbabf327daca48d1825d4848c9f70f036a93755460091f92b8a64b4a6d958b98e7ddb20f41e04dc3180076a0f07106dfe96d2c8436f3a83f14c3daa1a4d7974a0622a801cd2c421fcdf970006fa3a5627f3b6851c72427fde283ea98f42653cb8565b1ee8d9e22302ced8585476d117a28bce5986edc6ea2a2406e64a691bbd238ef05bb5f54a4688e0eaca5db3bb604c444ffb08b02c0c68ba9f2dd2b52060bed8c4345af9496d952adde6d54a4c316cc4fa91b35ffcd480a5e0dca6032237662d2528e45b9d84594b9a4afb7619ce0dbbc6fad7ef4a390b88dadb4d86e93f07ab89635c06100fdeee7254fb0491328723c0beb40786d1cfce481b38214e4cd1b8bc73710d4258a85c7a14a5008157c43d2943d4509b1962c50ebf7481a0159e58d06fc09dc9cf4", .None}, + {.Sub, "3ceb133b422767d1a0b553facd09ad28be576d65d5eefd444f31e50f57d0768ce8b71692b1551a46e80633b9027030e27bef2ea9073d8e432fb97dc52fe341e7ff39732fce62bb527747a3393112234b6339f541be27bde81c118350d96b085c830282feabf92683a0e45d83759ab157f4ae3bc22e2034bb3e343450d4d3a36b8b20a4100c54096662975dc42a206c4311f4449df42f40fa17655e3159d9fcfac1a91223f81e56a3f9e243bdbe47ca205f2b523b2c23ad0e4e3abf4fa33f26d1191eec12d5b0f786a16b703e7ce4e97d63baba3bbce330df42827955280c13e7ea6cbe4be72f676957710f771420fd6124684d69e81ce00e07f12b71b3d89a37e2a232fd64014adbc149a07377782815f077278a6e04b16616a12c3342d486055808eee6ce7df7e1a16551c946565df85e0cdc18d7aaf52e488b64dc555c6dfc707c2449e8c94c5c5a060061cea7eef992a96bf074dc843aa6f8aeaa2c1d03cf7d4c3d65a73f78615dc46835d45983bb10e8bbe2d6b984af2de055a41666c5e51290774fa85001e843fe62655c5a0060c8d41a1f246a3d77e578b3be0ead1b7332f0c2d40ab5e5544c00626bced68bf58dde078d46c89fbe625a23597f00a4629b3c05e3cd13466db64a43cb9715de1163695c40c1a27d169c67c0c7ca71e5d16d49371c0e383e5bb433c5e4fce5af980b3ae9171c8fd3a3d9eba68b94324116", "af4a76da2f7481e72294b9dca93123eaab8e4384e258c2ba6879fa518dee0eea5887bc5b62c709c075411736ca06052baf1aa40a8bc3a25473895204e7af7f7e741dd202fb025472b990bf67e15f9b9d4db32d1c7ef718d87d3bf182a9a715ab838d39ebe935404e78f3449dc9bdd0276fa04b5e734659ace6e41d732cc61e4c75199176cb1e0c6652cc0716057311ab648209bec36d4a8e61570dbafcb170a401ae09d24f31b25c995f0449019075e7ed03f42352fb6c4b4e8947769eaca57125fe678e741b3631e0bd23c7c4fe6f90f8b597872b9f70e75a62830c17263565163bfe286c30e2ee640a01ba1ab4ae4bee335abc827b9af744af17148e38e8e114281e4b1503f157284db12cddb94130d7d8c082433f9e69fa6f45bf4718a20685730abc7ef3e5879631f9e2e0a64564804ca955e135c748e2b58ba2c37f77b1a948409a0b50d000e392344f8fb5b3c0be9590ef66abd0283afc5b532c3486fa12ed43dec9c911e7a34c67f922728c21cde12df49a32af2ef945df091fb0b51a06f6ba003f07234332e28d699bde1ac4dc56a53a2f898b4b3b431e3045a20c072b065000491df0e8a9ac9268f68ece75d5d8cd12aa620cb041b11deb67cc0fb924fc0be1f9407ed4fd714c46bc217cabbadcadbbee9d08da29e5c99ada52e4692305c9893694e28f29c858602ba3727c491e33b6b9334cffb97641052e14be06", "-725f639eed4d1a1581df65e1dc2776c1ed36d61f0c69c57619481542361d985d6fd0a5c8b171ef798d3ae37dc795d449332b75618486141143cfd43fb7cc3d9674e45ed32c9f992042491c2eb04d7851ea7937dac0cf5af0612a6e31d03c0d4f008ab6ed3d3c19cad80ee71a54231ecf7af20f9c452624f1a8afe92257f27ae0e9f8ed66beca02fff034a951db52a568528dc520cf3e099449f1af89a2d773a94004f7ae57135bb89f7cc08b4348abc78dd8a1e826d7bf3d004e8826fb6d7ea00cdf7b7b9e6a3eab3f51b3894819861394fadd4b6ebc400817e009b6ef1a217d2bcf3fdc85017b850c98f2430693b0eac9cb0d529a5ebae93cbdeba2da604ea93185eb4db102a67b670410b96641191ae76198f7d53aed03e3ce198c04441c012d6a1bd5b075eda5f4cca8199a4fe76c223fcd3d098ad21a9a2a26c66e2309b538cc1c50228783a4898c33edc10dc4c72bec24fef1cf4bed9403aca90017832a95a10679228999864587ffc34e190866bcf87211c3792a7fcb6589650949ef34f46642b096b7215aeee42b043f841a6413828b1b0b1f4dd355ca6a7236f4f093f8158d2c3e680b945dac2ffd27b8428047fac58563996cf1df56fa91e8cb6b5689c005fe2c2d38674727087b250b9e9a5773517b2cfa8bc38d7e08d30fe0fe97b5bc926d285ca4337594927b2ebdc2e43de34a9f9ca3795bdf8a9a7999e27cf0", .None}, + {.Sub, "bde0ed38d73a1bb75b70fcd32b9e02a9a80e5f068924f4117dd6482a038bd7d5d2f07d40411293ed501f855832c2daa53f6038c14d6424fb8591424571c3225eb1727c302edac5d2e2ad5c4374940244a0f50a562674d8d6b0c11cab5d3bf43cdcabb77fb9aae2b17da24eb264e3f43ede447b21b91d01c53277c25f1c47940c5e7a24fb2e68f25ff05328a7c31118869689f7c998d9d6b26a1a8b265a072178413dda4dc5de1d9154ef6eb4bb764f6582121024e17e0fdc0ba3e06a2f0a8bd3cd2656ad63fd8ac59f845bf6bdf0d221da419291da4d5aec8b9c18c3d510b3e07e28f16d638c1d3b12a5cde9279b2b9ac5294bc6bcbb1034c65e1db86a5a88e0e13dc70b7e95f119e5bda5412cc20741b6e2f108deb285cccbfbf55f4b79ab95b012877a9bcc034f52e3ef3bf419237c7c9262e4f4cb0e2f12791490a7ea40696a794690ba247bf0b7a8320a9b3bb1961576c98b13f8aad6a4147cfd9fd00999996bfd07c7aaf796f4d379bb990d79a6e7a928026734d16038b4e6fbc5be2aa6eea888814e7f2b71595aaba8f815bb0a1e1959ca6d68abb101cf41bc0e3fad34479105ab03b0714a09bdf2b81f4458009810bc30e461db1b7f2541f486319e9e26f66a151e645ca54b00716ed1449376b1b87293fd7839e27ec7a591a21922732ca6144f435c8e6f7e59df051773d4fd6d379db56025a3f911e60db47b7c51dc", "6efc6a49fb4a0e0a9b0dd791c29432244757f258d19fd58123538e4e66821431f25ed469dd42918a2930d0aa22f39021e57a969f97cc7312a9603751c58cf0c05aaccdc85fdc237d89e3c966822a07e8b873efe6a1bea1e53a5c66fbdee62c419eec0f94971aeeb4d4c593742c906a3905d45c3211882052a4ebed21daac0c3ad6a9af57bc930b9f353349544ce60dacedb0172f0ef439819952a91ee16aabbf0b69e786aeffcd737839b342753bf5dbd003dfd85c4bd41d8c9dcf08cd8b2575333afd125d9d173eec3da5b2d7364c089eefe34edea9bd6ee84b345b37db826321a4e4be8ffe6c4fb0506b8b60addcef02dd55d4ebcff484917b14d1b3ed708a54271edfd359d507c644e54e7337533a0035c5ee2d3a629ca9d7a700a3a85264440a06737f4ae073778c7e07a6eb3abf3021787e3a39f7d7ffc9e33b1c64a0030839b830de31517868499718171598b22e14a3f4def17c8296aedcf1a912f51feab940fa7cc25c97710c0cfcb82c054d050055eb2e06e4d2b37692bcb9a690f1c32a9c41a6b128939dae4afdc5376c78bb467aff20f54df341951868d7fd74a8bcba9ecb41467ce235b542d4b0fb5a1c236631b03441779b1cccd8923509e869bbb90ca011d361ca050d907200dc40f3d18500250d618838076e77d767deca0f9061b71b546fb0e4cbb5ef2412fbb76e2f834b32deab93cc3c489743b6db3f95", "4ee482eedbf00dacc06325416909d08560b66cadb7851e905a82b9db9d09c3a3e091a8d663d0026326eeb4ae0fcf4a8359e5a221b597b1e8dc310af3ac36319e56c5ae67cefea25558c992dcf269fa5be8811a6f84b636f17664b5af7e55c7fb3dbfa7eb228ff3fca8dcbb3e38538a05d8701eefa794e1728d8bd53d419b87d187d075a371d5e6c0bb1fdf53762b0ad9a8d9e09a89e59d30d0c7e207789c75b935d3f2c716de501ddcb5bb72463a5989b20e304c85323bbe7f061161617f665e99eb599b06607386b346b643e6ba86193b51af42fba39d7da350e4689d35317d5c840caed38db0eb6255625dc6ed4eabc24bf5f1d0eb1bb034e308e6b66d18568d16a82bab3c1c121f78bff2b98ab407b6ad2b1ab178233022244e5ea7d159316c0881071c8122dbdb5771344d2de8bd4c70ea66ba91165712af31558b85a066623f8e5fdbf32a784f5e9af2842618e3e762259635072e540d65a00bf6bd1479aeb2bc0d4ae89aff83c76cbee0e17459e2a8d217392dec8d853e543f0c1799b52b7dec3fa7ce02ddbbac60ab32de4e9162d2decb4c735dbdc03a29533642388b8ad666dfc269f467d408afe36e48fde474aa8a80b0206380625869625127b6346b3d5d750c90fadb45f2e0fcd0685282e033726ef016b1aa77592dba3a3a58639c445d33eeecdd8ab2a3efe104781d8f3db45282817a102cd59d7670c4a11247", .None}, + {.Sub, "ee322db2f08ff445c516b4aa8c68e48ad17c7212fa2e2608d097e55eb130cde1226e7d715a8787f45ee7008e5380bb7be878a8cc75067b10259e9d3c403c44716e1c0a6694444fe0d381a15c2839d4c8a20dcc8760f0e1e2688e08006ea5d8343f514dfcc93767e446a86ac200f5004f9a7317855077c5202c62aa6a6f9255395716f3eda5474fd24e52343277d10ed371849d9190e30855a36af13415daa4116c1932cc63ac44aea25e08384462d2e4dcc23f50476f941291f9a3374b2d00344adc0bef3de09b8c8afe9964f1c3f067a4ba13beab85d07b10b555db167daa6c1d41d82d0b91b9e1429e1e122aee042185c7f526bfacc3c44bb531ba29d62eef761202654b07f19a7c68c90a935dbd0e2c9b77f6cde12bdd21e98aa1bb31044995e374bdc865a9e07069e979696e9e0765b65757a2ab19952a76116d5650562b90ce50e331275490b0578360d31d84cb55e9b6b713bc68fdfc7f35524c1f6b3d9338a6484154419be8e79234d393c105473be7b9425f68d49a0903fec2633b61b938c521d6a78f7bcaff226d3438eeba4193a2f0552e6053a8c632f0d45626c9d4f15d8f6d64d80a6f81358af4ee2885fc9f085971085ecc0158019a897726d10a13ef1f215a103f139c7344b779f34405c7c56c46166a93381cf329fd70f25b57ece2d09f8aef4bf5c856ec71ebe9237108fc7877f51cbd4490647539968f69", "818687dfef4db58c152ea6fc8a50e589c76431d64daa860c2e0682120b9010c3549031142925abd16dac38c64670b508cb99fb0cd89208875c7cec3c75107e9b06690b486cb883376ee75116bdfcfee1168ce87e0e2ce57bbd73c1205238a444a24855fb8f403c37a5ad6aceb13d7dadbe5534ed0a672f9a4018c052189dd8eb0ce8e303dfcd3deee970b9af0ac26dd899f9a6773adcb1ba37a5da63a921efad883dce8d464d7374038b5917c435a185ef52cb4e04da7d10e537d5bd1fc8667f148f9da290e49622178adf0ee092d40763fb2fc56bf1c901c2562511cca44cbda8dd96365d49e9a715c3ec513ae9e87cb31c70c5dda67ab99309f22131f5fc1c679a66ebcaec898a1c147bba0f000d3c0657753c03a03a5d2f2408ff50dd1f563aff4c51ded31ff40a6b54f506cf4ab067ea95dd6c58e895a3004ff413463cf08ee2877df260dd70111eafc669e3bbd21e0b07f790a618d4fcf0551cc3fa6239f15d46050b579dc96f39623b9f98055015c0cb2417ee5e8baf139e0595d552e337e019b8d4282e532e3b9b4cc0ca4b189ff6907da04e3a7aacd46f5cbb4c00d0b18c993209f57c88023045fd2dff0a5e5d5537fc705169c7bd0732b816766a2769245b75249a219a7de197a22d52213a09d626b39b6c062b91bffe2a6ed032a97f050b61baf462f1a20b09aacaca51b930f9b72b4688f04bc83eb8a6885a180d", "6caba5d301423eb9afe80dae0217ff010a18403cac839ffca291634ca5a0bd1dcdde4c5d3161dc22f13ac7c80d1006731cdeadbf9c747288c921b0ffcb2bc5d667b2ff1e278bcca9649a50456a3cd5e78b80e40952c3fc66ab1a46e01c6d33ef9d08f80139f72baca0fafff34fb782a1dc1de29846109585ec49ea1856f47c4e4a2e10e9c57a11e364e17a836d0ea0fad78af71a5606569b6bc516d06cb8b463e3db643f1d5ed13a9ed2af20802d315eed6f740242951701acc1cd7a2b6499b5364c6e4cacfc056a7373ba5611311c6040bee3f93f9407794e5f30c949d95dae746441f6ae47d03a2cda31c0f0041ba4d2ab8460e206490ab8ab3f98f7e032d30e779b79801b681060544d50845dafd2264402baca40f17ff2c581a26a53e4f35ae4286be99289ec65fe9484629f5356fdcbc17a365230ff8775c179430a193b01ebc9653ec677209f38d39a6939c8f937deaebf83165028ff8ee03588250903a1db604335fca3d279ae2ff933fbbbb5317b1c952a710a48eaf565f92c8de87e8158ab69027f61289cc38720736ea3a1a19d1272b4e025d8fbf1c394190a25f92364c45d636f5b826d50ef8dc6ef1e279f49d05d00b6f5044450cee27300bca9a0ef93a9fcbfeea495badba28a27d209fbf19eb8aaaa6467a65cf4ff8ea0bfb1d8e7d76ee4968c5a53bd4d41a721976a400f454d316c2c717c51abceb13c775c", .None}, + {.Sub, "-e9dcd8a7acdb388f26b865bbcb9498a51ad4a4bd7a168469356ed5aa07366149fa092f5431e3943c2945cf3852de993b099f01047b2e51b9eb791277f823f5ae1f17c12177951db4784874d686397d0e2017dbacdd8616b56b8f634bf7501a723ec5ee487f47ba9c433e194cc575fcf4420570d4cb5cf988c2beb37833d881dbe28b3a4edf17cba0bbf2f0bbb07fe8c685bcdabcf09ab4a4ef378a6895963b504ae4f721a3a54412881f179b596ba6d33ee92e498eb7d017cfc2c8db1a0a8549648f6276569cbd64b3de87965cdbfa17a4b2663d1962825c5331527aed803be829fa80d03c57a66de18845e388d9bf85f1e838d2da5570ac08c8bd7b68888c42bb53204c99eb8f844c61f91c5b8a2985adb454f66849cf43c69d4d584641aa5c456f42dac2670a7f05bb5149ffe4cfd9902399cd6f54586c31326dd90c457fac102e6610ee6cf2940b48da8ef07826b41b5b5c4d89dc084515cae399b80d386384c213905da3bd9a49b54bd97c171b255e59d4b541533b8f75ef087014d188fc2bc59e2d2cbab0aab9308e117b2d9803b1c568d3ed55736b25e0182b4df2ac1513b14c8486e9ed63f6b0f19bab4baaa34a25475a7a9903288ce0c74309c77442bf9ca5490662f6150b51c755a5440a3599bea14b40030e3b2006e56d62a9afaa180813612b19a77b661c3d5d59b7f6b736ebdb89384f416b5d58e7fd03f86c5b", "ece192f61c8cb4a666b84b15261f8f3de18743976dee393d33200b765947632fe19b99dbbc9bd8bcd1e7361ef8f6f11af5f5f83db4859c478895de6a74972471cf297726bec6333a7087f1e436afa6051185a0f5159c67b94047e9c51471073e169ccac00d92147dfa4cd56b1c3e65ef96c8a0ed4472cd41f25f3c1854869212a799e90ffda10a2cd8e702cb69de62878641a25ed52dbe20463e3669c480061918354981423d00ccfdae83a60826ba11d462881f45f301ada4c9b5a2c480a16848101247d3440421fe4096445456f690892163da5be3fc645a6818d792ebe56743f80ebdf91ce708ea3efc388bf6221e041e0e125c0afa28e0eb330a45328382a670ac1c865890a03dae0136c09d2f125094cc792cd0732bb75e351f3e9e3af599ca9d037712b25c6f4c201f08503f9e41c794295b526a4c48c6cae5ee94a639e38e797c9f14ae9d9e34288233a95427138dca2cc5a92c5a7f695204b24d44dc82ec0fa12eaa2babc10b44580dcaf330981bc688b9b22972176d4ec00f4b1833d08bcb61cf866b71d47b78084035cec5a9e74b4b6c4495fc2ca23ac0f7f174ce93a3fd2cd20c4f5236c7bf85f0e18fc6ad21874d29e78b442fb72ad656df6c95c3024e3dd0a7407eb36ca0790552984343d558692d985e7318afb83702626fc5823a83fbb3e3b748e85410052c6463a2630ab94aa8ee9b037508000d8c6a3d56", "-1d6be6b9dc967ed358d70b0d0f1b427e2fc5be854e804bda6688ee120607dc479dba4c92fee7f6cf8fb2d05574bd58a55ff94f9422fb3ee01740ef0e26cbb1a1fee413848365b50eee8d066babce92313319d7ca1f3227e6eabd74d110bc121b05562b9088cd9cf1a3d8aeeb7e1b462e3d8ce11c20fcfc6cab51def90885f13ee8a25235edcb8d5cd94d9f3871a5e4b4e0bfe7d1bc5c872c53575c0d25a164169631a40a2e5e244df85cd9b41619260e5134bb668d4aad1c5748c7e7dde8b26b1ac9f74be29e0c186b21f1ddab132f0a82dd3ca1775467ec0ad996b52806c214f6df28f8e35748d76cbc7421c14cfe1a3f60646e536606ad4e9b3f085adbb0fc561c3cc69204420248a0ffa531c275897fe49216f951a426f7dfb827784dfe551df39dfde3979bcdb7507716908350f77d1eb2df6caa6c2b879f938befada25e5f3bcdf8d8d81a131a97d031124217adb2ee9267a4f85349f9534359e6a5a7d4007ae23318c4de9460ac0903189e20e55f6759b3dfb0565018d5c5730241ca12ffc51698efc411c1c8dac0619bb6366c95bacb41f599a0967528252ec45e420e3a75549b158f63cb62d78b1219c2d3a69f746cea7a4808e6cbc97f21960a6e0d8829ef386d70a3693bebe67ceaa96a278dd93f9b46d9b6cae38b69da4650c1f6f9a42975cdefd5ec44e704d62861c5a5999f694d3e13ddc6ed260e80a9062a9b1", .None}, + {.Sub, "9db30f72a16dd7bfcb1efb3722ff3b19998d745aa8a896d45bbf25e6bb0cafe66da7b014cc78d16168a8419b5c339d11e1812ec1c3f78e46bf7f4c03d467677946a92d2c4bbec62eb30d10eb5b93ac6b8d00277572ae5dca5203934a346ae0be3a9db214bb8704d3eb516badf16d64f61839abb728d6eac3367f9c8e2d6b4aff64d6050d100b917ff747a21a5e89f76d56a09eb3aa2a942e610a574e6d0aee976fdb080e5509ac2c8abd7955d0cc749968384af5db9485b0e7ae4c0302ebd2f995fc9df523ff7ee738efc0ff61034cbb0fde404bd5df0375c4ca6b66af64168527c7a00b86a8dc7e44f9baf7fb87ea364cb86ba8f8d329a88d2887fc8b72a8883b54245f01950c93e8816ee99399d275a26956a4f2233f020690cb3edd7edc721327d97a862ee396eb21f45130351208d4414b1aff766309a8e136a7214db5e536f5a3cd9db239e82f42f74822d7f332d3f2118422d4608171bb9eff159d525b90c73c3526f09c31081d99e918c6a28586748f08d99771b3ae72b0d23bffcf8cae0bfb67f32ba28747486145eb4d6f1398241ed56c9b85b9d20af41df1d06242fa59dd692d4df54a91db853899bf8ee77820e925591868ebe69da022de51aabbdb394b056567a90f7a3dfa5a171a3f6d4d56d169a15c336dad6289306ff23d6d8d40863f9ac241ce44985efcad36571551ce5a4d7d6993b5a4ce6ee609313a6a", "ef5f8961eccc8e72a5f156263d370d7ba7a65fbfe4e14fb7b036419d338c2551992d148a57f6adce386b6a14cdfe574322a873b50836fdf7d07567732b23ab47e60696024f7492bb6ce426950b0dbc4d8fbd2424d28e0c3c7a98c1670ad4cffe373f8f45958f4e8662387b74e6fcfff61ec0fa0383958eb9145dc01f3d723e0a10df00fd32bae9fb137fade021e9eb080e6def004b32101cb962adf4e62438dfaef0aa9fd95223eb1982067ca1736ceeec32a18f429ff190a179c401c551bd639de726382bddb61f03d873e449937a360a1d74911cf279dda6bb9b19344222a44aa6648002028770a828f27d6bbd18568888836468819c37682fb4d739eb06f9e8374407dd83e59e93eedb1479c9c0138e6a940d48ad14d796058b7ce557c0ff46209aaebd9f21b75c5022e9af2663c1d5c86d801f9d0ec43e26cb37fb7fe58d25498111ae2da503a70a56b8b0b0dc14f4a2148b3af3742cc814d54671dec9832754e78ace5a3432449a90eab0ad5a33645b21aa7a40e5da1737fb0730fbf7221ae5c2d5a8d272895407db7bceedc5b3fa6e511a6b271281f70b4eb6fbcb7e2d1b0905958ed2f26a0a59b2bc875e3bf34271aede760bec809cc8d9535370373284f37c5fdd5b75c46fe80fc28a0c8c9d2651d732b8260c0c97630dd0eab1cf7c50ef463f87401323d510d60f6b3bccd7cb67659af7518efab085768f0b36e751", "-51ac79ef4b5eb6b2dad25aef1a37d2620e18eb653c38b8e354771bb6787f756b2b8564758b7ddc6ccfc3287971caba31412744f3443f6fb110f61b6f56bc43ce9f5d68d603b5cc8cb9d715a9af7a0fe202bcfcaf5fdfae7228952e1cd669ef3ffca1dd30da0849b276e70fc6f58f9b0006874e4c5abea3f5ddde23911006f30aac08fbf022af587b1c380bc5c35ff39ab7cd504ca1077bee585856a679194a483f15a291844877be8ec48d26d0a6f85583fa5699670b6bdfb9cb77fec265ea6a07ea884307de3737cae8b2e4e8902d7afa3f344547137667e1f12fb284de0c1f22dec4747b59aaf2632f378570352e203bd017bb6fae728edb072cdaae785e71ace31fa8dbeed90aab6d6c2ae62fed9dec013d685689d5d58f74c03e07d8e48d32f8c13437703e20712e2e987ef151b9018722652026abba95459490da322fa7ee53dd44107b6b1b77c75f708dd8e8e220b00307181f13ab565936475c417727968dab55a76998013c7cf70197e6b7addde692a1a0a9742668c54a34f4fc27956cd9c76db5a6d0020cbf7a35e3a056a0624a3244fe8b8cc825005a9909fb1bea20af282c6184fd1f787e2d83ed9ead0bca50c5b91cf38394b62b3930751e8c76a9ba315a77f3ccb4f5aa156872f24d2fd8fb05c916c9d89eea0084a07abf920ec3aebfffec7dd15590787712be0575c279990b4d79e7fb450bb707a90205ace7", .None}, + {.Sub, "-ed272fc9e4e19175b6c2ea9b5e7ce4ed84a10a460870973c08bfea0b5afb408447894e64091ec4fe4d7289eea1b89320ce34bcfbd4ab6c2c61f2b50f00b82ab59e13606e53f03f88d3f5de21118bc0195ceb11b739dbd44026d9f4a46448f3ff463551b3c8f84e41e4d2097f0ee26e404be2ac3522ae6042d8b350106d101efd5cff6cb67d6693f28c0969595422c32c66eb722451e49faa3bac063b247a4ab2900d1ec42eb966d638f3ece4cf1fa3795108cdedddba537dcb3478308e4a07e0668f2d3120d4d6f042789f9dc985ebeb59af186f3ba95a4fb57057eb5f4e236cfecc4e56834a666fcba78719521f1672e153bc0824299c107dcc3b2f521e328f1a016de45014b2b807bd51c6ca1f6953dfc2f20d8f97be2344bd6c6d2792080756e2017a6fac795617cde0ff4ede49ea726649abec5efcd21d2bcd9fd131ac7e242354d6ade1458d517a8be4372fa4c021c03a0dfa7f4768fc13fb9ae29a49a880cef17fd97e94f453ed53c127d60555c639e627e32ac2f4671f0d4b3c0c3763030121c96ff00a780fbb6936c5e08926b2c3f2aa1da160b0db703bdbd311da9d1af1418130f61fd997543075a8f544a427768e9ebd3777478196540cad6f64ad148cf8c8cdf55a35cad509296ed0cc5ab2e81926d24eaeb31d1c79719948180c4f1d2d9b924fdcd0c293f4be057b7bb3e9e677c1ce05b280b9a283e321719f97", "2e3537aa073d6d8d1b4c8d4d71349a2ea33bb321a9f2f2345d2c962c2e8b30af4c9c4ad75639fd43b307d0c9635f7e5070a7a8e27a99132744f3e6a214e239d2f5ef4b0e0c37c5cf8a812b9cb41576889553e8af5301947e6daad8dbdfb2f433c1f50cd0ef9b764ea737d728332c2801c543b732bf7bdc99daef9e9c6b0edc1f3adda6475fc4c99d7ed02e1a77a929065fb568b9b71fed81a6bec58b381fc7a552559ee82eee0a0c439797d096482ed863bc746f14cf1e5ffa627fcd7d5417544c9a952e2e909ad845ebe0a8aa0162707d552c89b304bd3d251cd6f111f9a47fdb629c7512dc0a90c1a1ceda64e49338c5dcbd599450ac190805a6b4732bc6830a06ef896f117526dc28a3adcd098bd748e8d162d02ffdeec94f1bf162fa1fc4526001767c256f68558b717db4900d87da4443cd68589fc505ec0dcbb1decec24f5f86cca95d1de9df49b263ef52862e4cfd83b7dfa982920286697df8c5ed9d33c1fad74abf8073e3dde5921df57e9f8d0136de0a6889eba16d303bc8a59ef226deb7487af0353f82d2d9cded741c6d38cccda4d5ecda16a6b2cb44dd435b6bd54c9c84b86cd33b9e9f864cdc9dadd14c2bdb1180bd7a01cddc42417d5faba8fb37c6ca03949c056b532a471cccf21751d50f7a57492492e14f06c4f163c1c1883cb62145bce5b9c4a8010a78d4c24483663835c75310e38423afbe0e962b69", "-11b5c6773ec1eff02d20f77e8cfb17f1c27dcbd67b263897065ec8037898671339425993b5f58c242007a5ab8051811713edc65de4f447f53a6e69bb1159a64889402ab7c602805585e7709bdc5a136a1f23efa668cdd68be9484cd8043fbe833082a5e84b893c4908c09e0a7420e964211266367e22a3cdcb3a2eeacd81efb1c97dd12fddd2b5d900ad99773cbcbec32c6a0dade09048d2be26acbc65c9a1257e262bdac5da770e27c8b84b56567d251b4c5425cf28971ddc596f7fe0b9e1f34b329c25f4f6571c88864804673874e5bd70444f8eeae178cda8d2edc7147c7ecda2eeacb962671008d4955f3b703a9aba7307961b87a482985d1e1e3c549f91224085d6dbf2627dee3e5f5749728f52b28abc3705fc7bc120e0c885e8a8c27cba94202f0ebd1e8be6d59527d036e57724caa8d7954b79c972317db6b83107b407382dba3573e637730c43e4826822aee6ebdbdc5da28c9fafe9a6518db603745b490ec57243e156837cb395345cb83f5533b1d05ed934ce0088c3d8704b1d65529dfd911eae03fb7928e4304b354a593eb90c04ef38e3ac782230720b0553608f03dde05e962f31535f3b6c28592f27573a269b03df4f1494f72964e2acf10560fc4bf92d189f63b362833708b9dbe7204bd28a12997d345fe6b80368aabd9cdd759e3bcd80cc28a873bf5c87e503df86d4caff79558c3643dc633a13007cb00", .None}, + {.Sub, "e8efd95283f5685c6db20fe14a31da90ba792b8d4bcafa2365660bc603d179928d59449e153845bc2072167103fbdf9eb7a4889da7bb996f7e80680650f2cf8444056ab706cd19bba46d643fb1739c3dab2ae5f540f22d34f1a11376ab5c29bd45bfb9c64b97a71d043161e978f097ca28dda8471af85e9eed2f7cbc5c8190eed176e9f0e38b6ab406e13fdd42e40ae9f310223e06232e2ad2338d25050d48eb65ff4e60b342888880c44c2ec3e642f2aed0b4cbacad6300af04ff613e7f25096e976ccf83a59897fec69f486e6f8473577f67b732ed656624fa9ff63ecd4cf6eaf8fe846ee0b2cf60432368a78498ab925b8079aeed096401d9bac23136f94452fe895a881aacfb86544c5081333a60edc840b9ae99f71f8504b0937e061e5403558c861deb705cba6010c122752a95a4e0515cd9bad462bd44ed00a9adb51e9a601fa6be041557ad8835eb43326bc1f08627a0496d2841a2e4519bb71b62beffc5fd507926cf3e96ddf5c8799494d3257aef0f14edfb641b9c43de5dc817d0d0e8c8eb9eba1ef9aab3f501142a9439c0a33f78266cd70efea38988b91ec5607c025e34ef750e421dd1486b3883bc8b98a04b008e2b10850fa10b77a3016e53c86edb338879bd3373b4a8d46f09bc6cf16754fdbb4588c41763c3f6609ffae2dfee905b8d5adca1d8ff001e485de6313d3b8e8966a243d4e82d833d9cf57562", "4558c09236b53171c735ba40bf33a0d10aba81611154723cf47f2100d5ca90d369d9aeeb2ccb35914d108ae610df72f387931434107a03a0f67f41e2ff35a16f40f5a41c94060d6b73c66a79c68260fda4ab6f2c5683050fdd91c652105e4826010125be5994b5f4d998f63f515730f238cca48156c57e13cf3a7349cec75bf8fd3d4a904c5cbf3d9b45c0ccfaa33becfd5bd153d64ca31772a49a2e8c04c5737856ff46acab5d2b3af7034a2358be3d5bff97203f7cacebe2bf3e41d8e25d3ef22e273d8c76ed5af84d1013e312b59458a256b41b45dfdc502cf471312cb6f15da79ac51d472cb52b42a7d2b097ce5c425658a3c214985e5fab9dda9e04de27e12e8a5e1db16c7cf954cd2ce797201ee28e03e62280ae6b9fe8662f71ddaa3cf0dbddc3d080a0c1f02d5d35b0703bb99fe83573d751e79aadf40fb0b9c06972c48cc37d056b6c814b4421917c68d0435904e253f8ad3130714e1e3cc5dbce5eb21113d8a4d19adb7b0822af283d4350a6918d886e7478925a2f8af8abf8713a1de78fd81396a7635b713e2b855d7040754e04e4c54f265cc9243db8d8e9284a7ceece738a485c54123ce6a1b5e3fb222fbebca4a4c942574730768803d0788d95a5eb3f0a0dea872e7278377dbe4707f3ecadbf6cb04cc79b24953eea09747aa46496e5f3d69af9aab5c2bb37f1c9fdec3dd012811c2b4e544367488c123d0c", "a39718c04d4036eaa67c55a08afe39bfafbeaa2c3a7687e670e6eac52e06e8bf237f95b2e86d102ad3618b8af31c6cab30117469974195ce8801262351bd2e15030fc69a72c70c5030a6f9c5eaf13b40067f76c8ea6f2825140f4d249afde19744be9407f202f1282a986baa279966d7f01103c5c432e08b1df509728dba34f5d4399f60972eab766b9b7f104840cefcf5b450ea2fd68b135f8ef2f679088377eda84f1a06972b5d45cd48e4a08d84b552d11dab6d30b614cc45c11f659cc7ca7c694591f72eab3d06798f348b5ccedefedd110317a78589d4cdab850da096058d5163bf5199861a35007b95f6ecca4f500527d5ecd87105a22e1ce793321b1c71cffefc6a69407e8cff7f23999c1a420b3a3cd38c1948b3e51c4a640c2874171279aec24d6acf9aca32b38b7204eedc04f81be90268ecc80f50dd4fefed4babd5d35c29b898a8d662441459c6c99b7e9781454c50bff7113196335ef13f94604db4e977d45534631bd5d319515751827ee96186a67982d1c16cb8e5b1cfa696b30139138b2377964f42b6d58ecd23f94b553a93611db0b2357f4bcfe0359d15ff138fc1652cb1ee0b9461c9829fc16968e18e5be961ce2dc87094ef9f30f5c632c8eff47e6bd2ac4542309cf14b7564fd7aa73e4e953bfc7c3f2eb7769686683b89f975998441a82e493d63106c1c3350fdbe76e586188693ea1bf510e33856", .None}, + {.Sub, "a968f25673ae8d3118dc6e5eb4639a4589d93f717f99dc552136af75499a2560c9fc368a90cdcb670a85a8035e81e64e071fdc0f01af3b850ea9575e2259f08262a9ec304b21aa9f6c987739bf7e92ef0dd495e4777a5433eb3a05311adcb977ac4c32870b20557c716a116b52fa9558ad58c490b91b52d0426d1d1a2308520f1cc7a1e2ae86010df198b6038781c85a40119cf370be7c7eba6e5bfca32fdfd8e012fc5192fc706a2a2593d6e26f49bfaa229c4d00de486d866e94106f8b6283e3867bbe439769dd363b3c6f6703c7061981aad824024e6d59ad5547462325aac5cf3fa7b951caf8770a7fd8fc22cc2e1b256fd096457d95625948817e3c89fd53c502631cc0a4461ffdae1c58758cb38049880aae66cb18a945319fac35222509a6ee5b87883fc6d21fd2ae890593d76331edd1b68f1ffcaba202f9401a63db546eaee566b8a96cff88c44e52995e41eadfca2bac51e5755c78ec34b5f47e440d0c5cbacc633c34ff283169f3ae88a1f1054942d260478f7c21d686d567182fae2fa63d26ec0702fedb64af8483bb33f81326e06c4f3edb7796b5d3d780c6aa8221f63849d3f864bfc426aa637d7ab4e478f229192ce025a2ce3b91edf0b023ce36ae01dacae12e92c04101b1f598de7fbbd694204ed16dbe192b5cd7cfac1a82b281ca0b0abb2beb05624da0598c59d013f1cfb87e7f9db0d233405de6bb41", "66848cd9ba950897b61081d6062dca1de233b58eece1d8035a5bf2b4d95328e7a6a1e18ae28998d9d487005acaf130632955dead623594f6fe66ddeba2af9f1e5b50d91b96685a6e4a90229463c6b36fb08acf7e5ff0f591b49c8d168e5e72ed223e143a70597c51479cb8f33bb0d97a5c5a953a7ecbbb84b0d1b8b0a71d2e42a3671fdc1b486a410a4f2d1af630a4072176c43b27adfaf176338f11d3107114e733efed0d55beadf5e6180cbd2bd49dd3c33217b364db07ac26d6200ecb73d638b812b0bae76d085a730cc8353f28f6919c992f5191f1c6874284b8629bed60cc2207cbadc3d6dabb39361d281fad1a249d79c5d5fa4be72290f50175a538a73517d91d1d9556484b5f912fcb61b9af94108fe820ce89dbb413a3b316fa884608af9fdd1754bc253e3e64f43eb33231f21312f3d1e4fde327074aefb76273637f12cafd0457e901c97c66742cd87ef5afa49947b605ff06bef01573e41218e72af1fa9123ad818f3a073241200c57654e61563e6bb5cab4b27f470c3b039b91eb4e68a920dbd216bb105437da08684800e2b060550dd4fa7a5c2482ddba1e712f00f72c5f6b89eae840615d0041fca7aa2cb36630377d6f12657bbacaa96893a9d187c2ea501ddd35c5b7237d0025dcccefce840bc771ed3de316aca047360dd15e276ba16da132330661fbcca60af826b7a5f9af9de4e84ecc568198b514db", "42e4657cb919849962cbec88ae35d027a7a589e292b80451c6dabcc07046fc79235a54ffae44328d35fea7a89390b5eaddc9fd619f79a68e104279727faa516407591314b4b95031220854a55bb7df7f5d49c66617895ea2369d781a8c7e468a8a0e1e4c9ac6d92b29cd58781749bbde50fe2f563a4f974b919b64697beb23cc79608206933d96cce74988e8915124531e9ad8b84910818d443accead01f6ec3f8df0c6485a6b1bc343f7bca25437521d65f6a354d796d65da47bdf060bfeeadaace690d88affcd4dbc82fa731c49e0f87e511a8d2705ca6d26ad08ee3873849f9ad37dc0b8df41dbbd149bbd4031f13f687f60ac04b31ae3fc85380089751561ead2945ff2b4dfdd49e1cec8d13d303ec38f8228d98413cf5318dec953a99df00f74e7e703383a193e16dba4a5261a5711edadde4aa2219849ab80988b7f077d55be3e86260c06b360c5dda25c0df4c3b3b30e3f64be66e9d88d6c0d1e2655ce21a6229a8b5baa5c520ff28d3a2313ca2a3f30466aa7cdac9a28f7a9a637c9dc2e13d94061034ec43cb1077aa7b52ebf7307680174169e0fd3a9150f9c6a8395320ff0bea686e79d783c54d633b7e0d3a4c3ec2e8f562b69068bfd7234747902465263ef07ac3515cfa89de34f57301b2cc081014875f80803614b03788760cb1545a5e699d19f9b7ff0051d3b38161a95c4bd608e09ab56205dcbec531a666", .None}, + {.Sub, "-f1190f400e3b4056a7f2331376ca8853b3b333df32c5ca688a1710a72b5fff367c9a83b3440a40c1680372d27727cf0fedf710ea96eeb6b19bb69aa6270663cec96fabeec72e79729ecf524d53d6f553b549ae9a1de83637b40ce7ddd0ffd63864ffe5ca0a7f598063dc6484dcc03b4be244c325dfb00ac37e5b9b827c13a3bca105c44f59fdd658143bb2328449ba29f79c0bc4c423a6089cd3fd7a7d7a6753aca0614f30b30941db15bdec83c13b2aa647a5a28374b34cc750b1d9b0d6e2ada556bcd61909571749126cc08b8f712657cb103cced74d363ef53a3eda5a1b18a613741e477d1b0606c27174b818076dd8bcefaef51c7aa97737c8180e26ff6538f0cade1918e85d42d655d473dc518d6d98c7753fa25cb6298722cb2958493adb5f2b05a2bcd4ff37789e95864685b6d845422499ac66ff29d6e28ca670c142549c430bcf244ebd99b17d765d34f57f2faf8f6b1f4a4ad77916d2795772d592696fcbbe7841697f3b98b293a9e094961768a46ca053977367c594b450836a3ae71f9778a970730bccb92f41bd1a35e0808a26a8996c443557fc69f39a30c901dbd591fea6a52a55c86adbf879cc0e002d8896fc54b4a00ca771495677793024c3f1ee4e83def1a0979bc3aef7eacfc39b17989d286060239254a926ff3299c81aaf7c55a4a8ba62535fcb803a8595c23f234484d1f2d6969ed93b937e56596d", "8f6c2104a51d277c90e5dd979b6cb57f6eeda78dd577e9d93ce1a02ff9770d3feef6411fd0c33d5cd3fcccd7934b94e69f6d8cf0ce4d1488c551c1d33a106ea5a59953dd45fcd2bee734e3a7bda02292d9d936c1f48b32da3800657c3b244348c443e3f15be554cbf29e0df194415e0aeb8cb6005f3d16331147560e668d82c76fd163aee8bf163d9cecd2d2bb7db7bbdc0ae436c0af4bc1d458e5446b8a210bfc90314c91d1bfe50d4975d6bc854ca310ed85722ec4470b99d27320967efd7dbd895e3f09d21171d027d618dd8d31c00f95a85a3076eb72e6bf23f1561fbd08c36055af634c7f9f78363bea999c4001cdfb696ae026ea3237dc0bc6e8adf021e3e9710ec268a007be76f0bc797a265bfeba7f2b8b159da5734499a374b812856ee44bf3a8ddeba991917608cc23c56436184cf611f63014476a8b489fd01c942355a912a482dc1f8b31b43ec621808f626aee4c2431bdcd60bd931006fc6913d629a2853aa25f5d34f3f59537847b96d72ee8dc996ac36da27ffb29c5e861f76e05e63f3f5d0f0b6a9f3273a4560afe42e32acfaabdc8afdc72b9aa541b85ac1cbf45ecb81b51ebb12d5ce546ba15bfcea4a9d956badfb1f5c72ff7077f4a4821bb4de810c4cf62d80e37dbcdbd41d1995b78eecc0e01e86ad5f824948f9ea690d337b7e663724f32ce0ee5aed2b0d0f9ee0e91d3799da53997d3127ff35132", "-180853044b35867d338d810ab12373dd322a0db6d083db441c6f8b0d724d70c766b90c4d314cd7e1e3c003faa0a7363f68d649ddb653bcb3a61085c796116d2746f08ffcc0d2b4c31860435f5117717e68f22e55c12736911ec0d4d5a0c2419812943c9bb6664ae4c567a727671019956cdd179263eed20f68fa2f190e2a1268410d727fe42bcec95b12885053fc771e5d3a6effb84d2f1ca712ce2bee904885fa930929bc284c926e85f33c3404687cdb7352b14b238fa58612324fa4755e02b62e01b1522db6889193a42d9691ca2e66760b896ff4e38a925b45e303079d8216973c9cdaac99aa57ef8ad5f51b4476fa6b85919d54364dbaf13d3def6d4ef871cda3becdb818865014d4690ed5677e96c5346a0cab7fa5b9ccbbc6e9e105bc04a4376f94b9ac0a8c90a149e526a4b1b0e5d8f1aaba2971371416dd54640ddd677f1ec1e73a72add24e331b52356760e921a7db7437c08a4d9d465895e6f3ea63f996e43b2e3c8dc708ca828e165102cee978d4939be5ae10a458fde166bcc3255257db7e8cd8217375861b5617040dec36d5178442a0ce5346f239dee4c4eadf894d7eb5ec07c41799838ddc08623bffc2d40d5ab6f7fbe9d38794d7ef87a6ce5ad3c3694a3c1036fa9fb8ac5a811953473118bf46e620bfd2aa14b93c2386eab82b40d8b0c2cb1862dda65e958469339115316a56c743bd8710ea5fe49aa9f", .None}, + {.Sub, "-f7491e937ea3e795f311de87cdc34dcda3ad75e3e660a95678c4e5a211658744e5f32e96c0a978a8a24bf2c9aec0bac66266e9e0c2badb04b38c7c4f6d276e78120e8746265f0207e4c44a624195f02c0316a1af161a9e19b771f2c665fc613fa18bf3c9458d62b33401588ddcf254fd96f0160fea784b5bf82e0faa2b736b342f3d1862a135b64acb33d5d4d693223c87944edc883202ecf63aee84bbb628cdd1514e3cf5c0f90582a0085773dadfdfc0c54c7a814321461aa5c6d0748852ba6d6d930d0c75d5af93a5229c3e4d7500bb195f91b1302434a42fb129d612c1af73e8d13a37dc2e5d076091cb3e0f05c75774aacb8e1ed47972c20ea815dc62aac0146d86a220329611b3a53373c17d7953e8de222ee837e80c1d950527739e90efc03e0baa02176fff0a9576aec7ba4d3676bade452905f7d25006a512c76cdc29a13f42d881955b28a454012bd0b145578421498b8b89f5a5f2442ee5b0ed46043cf57da7dc97b0d450237edad471300d4c40a1644cb77748d7e8ef94e8f53c18ad2aa636e2909c460e8bbebf8c14b2e4db4731d0f3ade1615b5f425df44d411b37d65e27cad4e88329693843e0fce5c11593df0d536131125fbea6e10b2866ae3df7e8fc3deae2a922a507953a3e3ac4498e3298ffa55e51b5a8164724f53b4d111075f7553251e33377f8bb77c5ed1f5f4a2c4cb2ff84c60bc8e770acad40", "ff51f0a46e95c9a3b4b9d9d42b101cb5a4e59f5e998972b3739a8a090d3a84b4c71c1cd7bebe92025889e981784923a1863e7902a404edfa784240fbce98e7b36e86337806c6781a0c55a45d2065a8a9851480fbea4d2bd128329280741a315f4e2a52688bdd3848fb8729bbd09d95e5969fc4b4fc9de4e5afdbd802111dbf9b8cf0c7aa58a5bce8d4041714ea08010c07e2751cc2815a94516319831cdf78542ef9ffbeb9e25b41d7c2a0dc1ef12b6905449843539d8e6ee5cfc18b746a6a01ad184b5b7ae1ea511a857a0e8bedaaba4d2ba211c90cf9aa45d9d6247f45952b3b3fb0ebaffe5778004dc30bb62bfcf2225f7d203d5997b20efa1c0eef4d1b61fa8ac7196a3043200c97c021650408f01b7088524cb90b85fbf48a427ea346c1b3e870cacdbde25f256e1489b2c677c5b4ba762e8270eadb0eaa3a149ec78a989237c0bba4c92d54225356f53c658dd8e5db3cb693ae0a58480442ccfb1d0a106593117b41163df6d7eb19fdf016e911f54fab58aec55e63b32d9483562450369eb1c52e7e42e3afde91e8242cc33cf72251c5bae260ceafd5d943f07ece87c869b87e4b8fcf0e5980756bca7759d66cb4a979e7e45e61c6f88147446ec34234b1ebb0fc9f22bbbe836115f8d7879afbda2e7cf1c40f2272170aa795db1a5f1cce8db2fa9e5fb106fb9259ac15eaf5a474e6a7b16d07861e5136e48acbde29da", "-1f69b0f37ed39b139a7cbb85bf8d36a83489315427fea1c09ec5f6fab1ea00bf9ad0f4b6e7f680aaafad5dc4b2709de67e8a562e366bfc8ff2bcebd4b3bc0562b8094babe2d257a21f119eebf61fb98d5882b22ab0067c9eadfa48546da16929eefb64631d16a9afc2f888249ad8feae32d8fdac4e7163041a809e7ac3c912acfbc2de00cf9db73339f37ece9c09b23488f76c3f94ab35d81479e0807d895a122004b4dfbafa354475a62a93392cc0b48c609e4bdd4e0afb50075885be8f2bcbc1a85de688757c000ae2a9caaca3b1fbb084501a37a3d1ddeea09874e555856daaf288225e7da85d507ae54d6f43b02b979d427ebcb786c2b81bc2ab705297e0cba9f34a00c5075b61e4b6554d8c586696f5966747ba1436e08121f47a616e552a3a8aed677bff9cf2478aa00618e3212eb31310cc799f0d2e0fa40b9b18ef774bbd8fffe7d4ac2af4af7aaf668363f1e3d5f5e001f39944dedf686fbe0cdf75669d006f8e8f2d5a7ac3b3d7ccaeb5a42029bebfa131215dafc057d72eb0d4572b75eefd4b525744c24a073e2ec4f51aa072d0cecb3547c913734a332dcc2d50984f054a9b799e342039ed502bb3ad35275bf0dc6f1b1c2f80ae105eb4fce6a9b6029a8e59b60a6a12c83bb006cc1d9369e780b245d0ec7d068c04fac223f54581b9ec37095b4e358dec5d1a4d162bb919445f1ddb9ba85a31742ad723c8ad71a", .None}, + {.Sub, "9093fd5ffafc99296e10de629c2c9f5857985c21211393b56387273d59c9d36681d138f140436c2e19f055f8b1f4f647163cee9368e160261356184e8bd4d6b4557086ee61d868ade7ace4514a499ce862f6454c693087cd05bd81b4fc50bb5566694a909d5b6b8735a7c942c7fce2380a7daa59d86cf601682a80365d464f0a25fa189fb43c24f50483620a64c1601a580e49783ca3d1cdb7c5fb40e1e19b47f5028dfb367e0b3eea05be5304dc224727b7cb2063255f7d5d335db66031c98472e88c7e574090578b04d424699507d064ba3354177f604e7c6e6c81a21d66de859285ed0eba87c3ab2809f11a06eb9db05804e98e076236d3a4b8346fb7db979e8db4e30085067b4e1072aee840b6bfce89af80c3cc910d8276171ddd700daf376be62368f019dce5b928bb475d56f6b073bb613f831c9b6b8dc847e7106f5bfb8af64f45b9ec981781dbed22643e3299a89a1355c2182e70aff4bbf3ed6b6e5f33eb29eab6cd4fb5045ebcb928cbea92e13f30cabd4ff7c93084dee95968a13e601e34042db99c0176f171897162d20f79665f295894615a68dfafcf051477969fa6a076d40981b718c0b4b241c10c8a07722dacd0b9e8e6ba1110f39b6c6a8b9dedc46f60dd5d55a8629ecd3bf5ad8bf879b4e96e491f901478d535393fc3124391d455ed3d614dbfd7a5f1c5db04975447f02fcac2e82766ab6f45c613b8", "c4b1a0240990e2c59aba5f57969b0f0cdb34e2af9c7bab2eed63d0a154f1369ab3bd8ed2179438137fff8cefc2ffb516dd932e05063b958fb2fe05f9f9bb00f30f20682abc1c3223033653b0515a48276f6359dec125c39db09ad29bf3eea27936c9195264c5972d582bed4aaf94caa9932330d5b53edc8aeb16af62f38dc6a6e40a5eec1099cd7c62da242b5ec58843133f562289f95dbff6ea246b1338052393e4376804d19022ee1659d7d90b0b82f24e88e278dba0b349568e990c136c6f2e750faa4206034ffc35a53e43c23c4297dba4427e1a7e2d26d6f9814307864bf33eed4087de9fd9c31ef38ab0128d7ef68174eac3638b6983828e59f68117d28e7d1096f160888da68af800b0e88100b280be9d4f239a615b8e7e0b9256b30fa7c7cc59373f64eda25514b4c119e7138c2a578d71d4b7f8f32fb36766d7870a0b3ce2ae156c2349180f57e18c94981430e61df88019318b23211c771f5ceb1ffc3c0cfbeb1ca9532a8a9e59580a3d762717a0bd241c6cf641e12efe741e2e2d843b539aa51a43ea5876b817c7aa02644d9755cdefeb7a49b88f8e3b9a8b6fe84ff98c9662cd90638061cd309ab3d10f7f95b862060f8c5bd244f6e829c915405263ac21dccc1e55f4d9694e42ff823b84acb5df87894a8c0cb7a0e431cbd8139c60246dc5fc7ecdf655938226ba0a97bc4182d84cf630083b499d36e6eec0e3", "-341da2c40e94499c2ca980f4fa6e6fb4839c868e7b68177989dca963fb27633431ec55e0d750cbe5660f36f7110abecfc7563f719d5a35699fa7edab6de62a3eb9afe13c5a43c9751b896f5f0710ab3f0c6d149257f53bd0aadd50e6f79de723d05fcec1c76a2ba622842407e797e87188a5867bdcd1e68982ec2f2c9647779cbe10464c5c5da8875e56c220fa042828bb310caa4d558bf23f24292a315669db9ee1a96cce5384e404109b84d42ee93bca96bdc215b64135ec2330e2abe1a2eabb8c832beac572f87130d119da2d3472332170ee669b1ddeaa688cffa0ea1f6d6dac67537924181617f6e999960ba1e146297001355c2932afddd62586c93c3aefef5bb3f0db8212587a8551c8a7ca40e3f70f1c8b570953d91866edb4e6a560705be635ce4f4b10bc9bebf979bc901cdbb69c2c32519b5d87a1eb1f7fc717ae0fb1ec5ecfb236b1008d7bf46a3059e1973d83e52a57195cb27127bb2b6f7fb19d0821d20065dc0375863f9c9ee1718b9436618c595f1cfe78b0aa1f8ac4c58c45db3566a0ec8a4e56ffc6a63e389f923e1def6ec692e5e85e26ae8bcb865b70b959e5f5ebf986e1c9490c7be8721002f58e4634593ed272eb8ae5d7362da8d5c6c5be5d6d6b40f89f3106af75c38c8df8b43c2a9e1b016c7ca3280efc9298508a1c9299700f416ca895bbdc34f42f9324ed3ae81d2b6d2013e2f1c7a128ad2b", .None}, + {.Sub, "73aed0069039c6c52b47609d029dfa63c66844b3a96be03b1b7892449059e9904092396becb2dc2c57bd14cc2be0ca8ec8408718421134e35f5cc72f53508528fdf37ca1c574f16d47971fe9b57b398af5e2a506b36f613dd808787be47766a6e2d3c30f5e4ed2fe343be1e74a2eb6cedd4f3efa19691648b4fc8616fa9788dce91dd56893c5d6d7b8bf1a22fa7948869e4136477cbd5ed1e1c24fbc42000b3b46df7990dd90a10f85f1bececba89b3bc68986293f39a4f087583c24a510fbc6481cf5c5449a83f2d21cd7c477fc19968580fe0614f05f8ba4029f882358686a3ef2015a78b35800b784ef4b5726d45d1913ba90d1cd58dbf0da289f47be68d8e5fce65c0e6c2f70f22789919a45dba12618bcff7e8b0a5aa56a9e658ef54e907274a16303b23c3850cc6e3708a4e23c4f52dc3fcd3a9ca1e949e0596515de32200ef352f931bc073ab6fee032350816e134fe7ce2d72361c481b34b852cdacc53f36684150e75de932b5deddd219ad3a323b8902be9625234bd33d83cc580283d6f0b4bad88fd11d3fe1fc447fe3c3458645250583bc0df9cae44b6ff5848cf6a198dd2d7ac37a9c7b8c259973d77a03904962bdfb7b4377c1df070edc25dd5de7451449aa90b9bdf32f5f9e216291ac13ee195d25635fd4424b55a645a42ef69021a298f48f709b166dc7e562bdfb5aacecf97caf2e8b1301c184c5e120608", "72a9248e5947a9013767c951890b3a1eb76cdd5dcdea9c446e3f04682390a9c351dd05907a0e4a0d6917fdb136d9923861d16563e4273ec76f5e79af882ab04cf86eba631465ab18cb63725c316de2e1fc408e31d334a481a7b598fa3fcec18eb0efa0f89bb613f39d391831b50d202de4eaf43cc35792114c22c83c9422dcd05ea3775abc10a9d116c95ccb0b6dc83fd65a35da29132ab3fd6f993fb5618d90b634be218750acfe2648df3c8b7a637e70662c747cc4f004ada31687d40e61c02d5da5e940c1a1064a2f57c25109b142dc29cd445def88e5cb1468e05779a50265e6ba821ae7d8c7acdbfebd718da0df5e874ddae9001c63109ff11f8ea29825653c51527cc00a6b3a8f9c3eaeacbc87b2976c3107e70be0cfe3d7dd237b1c29a772c59191607ca1c904dd842b30ba547ca573a89d10b55087ec468d9107897a998bda57999425f7ac8e43c94c5ce0c72a08f068a265e1af4113ceec06ea4eb539c4f70b68afc80eb9a821c0bd1e76283fd3e4e4e0e00fb109770f2bdc711fd9deb1334a43865d54d32e1e9528516e8b4850b1d9a5cda8dcd0b474f3ea7f7eff387bcb0e4bf93c50e9f647ecad7ea02fdda3ff04d41a43991268216cbd67bc6d1cad37942ea5f4c56815ce792857ab142ca930ff56dc6cd0b8529c9d066137493a0da0e8e2e8672b1ac897d0c2123ffebb282f091f888362ecabc1f1f90e5af1", "105ab7836f21dc3f3df974b7992c0450efb6755db8143f6ad398ddc6cc93fcceeb533db72a4921eeea5171af5073856666f21b45de9f61beffe4d7fcb25d4dc0584c23eb10f46547c33ad8d840d56a8f9a216d4e03abcbc3052df81a4a8a51831e42216c298bf0a9702c9b5952196a0f8644abd5611843768d9bdda6674ac0c8a7a5e0dd7b52d06a1f5bd57ef0b8046c7e7006d53aa341de452b67c8c9e7daa90aabb6f563ff4115fa8df92402e37bd562359b4c274b4ebd9b5259cd1029a061abf4fdc03d8e2ec87ed800226f26853a95730c1b700d6a5d8ee36a7cbdec367d90b46d85dcb7f390aa8f08de599337dba8c6cb5e8cd3c78e03a377fb91bd0b380c0950991ac2505b797ed52eb991f19738150ce76a3fe79d586c6886b7a3266cb01dbd17251bf9687c790b2dd7427e7d2ad68973029e751615d99cbd40e54b7868318fb5f9d960f8e28bb16e5d8274fb72c0e14407141b2836de45f7e428c171a2e6f78ac5eadcfd9833c2d200324ab634fd3ab4b0952a12b4624ac6054604e5ebdd8016a029fbd00d0012f1faccda91013a076b26e1802cbf9cfc314d8c9d0319dc2c48bb2fb58ddc27a6ce9bed7705b6097270b9d709e69b5cf04305aa168c1c719b06c0316d6771d2780b9be7e069495b0967b79c92c8bd218bd5df90ba62ef47940ac608fde969e44ad94199fb6efa6a08eab6a654e4370565a6503ab17", .None}, + {.Sub, "-33f5d1017254321e17a7c1579ef743bd0458ecd6da7b774edc6da68e2351ab03508757ac517f85a9b6a70d01bd97313824a170a0d6b1e954cd5aea24ec656d07873565460d78d5fbe86a2aff94a809bd264bf78edc1c74d92491315b8af926ce6d7e49adfd366faea19b08c8a04b604c72a3b0be677143342972cb9e30e39767507c338ef7f866abb5af01c731a103e79da90d778925b2e97c95337368b85912c4782427095ce29280d10a70a52ecdff719d7cfe931b3c366281f89626d48fc388a234c0536fb5f97c094bbf38b956ad6889497d35afb01eed42aa13c5b518ca5f8bf9f2996dbf1489d45f2deed3d9122c7b3172c36872583994af7ce9cec2c363307bb0b4095a9b58097a9e984b385cc7437b08765bb487ccf9fc2d6caee5a904cbadc1cf37caf3d9fd1a059964ae21e17ab7385f98d485f6b780698ea61b80de8f833a08358b79d77b71b269e1b1ae85c0f0bb7472dbc917a08cf0583bef966a02d1e6b53e22d92e90c60f0af4c11b7a9af4f142970ad0d83ed7560719a0837490ab66214e116d9fbf4b40d881a232b41c49c800b8e694b6ad646535e0e3f573ef813a5a8708bcd98bcb133277699ae41aec8dda2002d31f44db59da70f32aaeeabe95e66c0c823f1961e360c54c63c886509d6e2354350f32c5c0dc151229e6897c0226e46b1ddc1df0753bb21cac8bf401783f88e3f83a5071e522a1e970", "dc3e9c1b02a6ddc55fa0df61ae294e94587551034101ca886ef0f476023d371b56c8854c054b4276bd0cf4325c4cc0cdbafd83f5da49c3281c7dce35536f02a84da8bcad49af08f66b17bba8756e558c3bb8f4446c1ef6ca060221bb9af248465eac296ef5ff98197f344ca043c1d17d3fa45a8c255e73d5f685f1c0d3464cefae5bf107e5b457df58647fe1213f93039ff06dc27fba6c74c417293881cfcea1b13d765db85c6f25c96b7e738fc3b9f117c4c876fdf0aae255b28a4cd7ffcb586448207fa417dbc11233687495a3cd2e2c5c0659d3fe427a3de28cbf70e0d4f11f4348ccb8391fc536e2e5755d6aa9bbc0e43c7a55c0f0950ff2e536e1f06c4373148d4771bd21ec3059e14e2b479a2f153188e9f8de84a8fb0f8f69e7aac26890531424ee1192cf1d2594be3e69fe59622f5248afcae4b1ab983b31896d6a3b4d279069909c5f518908cc46974945ccce1f889a1e8b16e76508194a9dc7e2f265ebfe740485f92fc851ab3da3ca0f5d815ad4820113db011cad666a29a8f58fe8b129a22e236d5dbc33208de24c81c81a410e27b98f7ee185d08a2f392f808b6216fe464014be8aa111d4996e4c681c982e334a2d1bc29eced250825341913a269ce1cff69ef11c446a4c2cf9ed9fdbe9ef401cf1a67dd17c779c2c7496d844921646c54e05a73f13a4d5cff05a4f202f6b3200d60a355c041b48bfadcff541", "-110346d1c74fb0fe37748a0b94d2092515cce3dda1b7d41d74b5e9b04258ee21ea74fdcf856cac82073b4013419e3f205df9ef496b0fbac7ce9d8b85a3fd46fafd4de21f35727def25381e6a80a165f496204ebd3483b6ba32a93531725eb6f14cc2a731cf33607c820cf5568e40d31c9b2480b4a8ccfb70a1ff8bd5f0429e456fed82496ddacbe8b0e1381a852e096eb3d997b3a08e01f5e40ac5cabea8827b475b59a84c1b951b84a3c88e434f287f089624575910be718b83482e2fed45b1becea553ff78791ba8e3cb433ce5d23db94e54fd709adf2992b2536d33695edbb7ecf42bf51a6ded9c0b744a34c3e82cded5f6ded192962ed498794b3cbbf2f06d64508f825c67c8788635becc392d28bdc7503f26f3a3930c8098b975459a811951ec1e6bd495dc2f722aec3d7ceac7b43aa09810f63b937a24fbb9b181385bc2bb713a398d1eacb60843df9012af77b53e0795592fdf2b07ca8a63af603d288cfeed05ab9c41c08f6e2714caebed078fbf5c97343aae5d1f4ec3dc030c296135d41d5084f717ecb5bf26bcebace23face5d57efba4865763c7dee946f106480d6067f809a9bc7477a9d9faca0c3d1b77c491fd8073bc571ee172bdc2db28464d587a065dd0afd9e8383ae105ab2ec3fb27590ba5fc9d2068baa61ed50abea6e789fc2c774ea125cefc2c6452c0c6bccbb5f3379159319543e6bbaa4d071deb1", .None}, + {.Sub, "d15757526be23f24fd1a60d46a412415b7145149561d835afd83f46bde70fbf4b9ad833195cec03ae9d20e3985e3aafce8fd4b1a9454d7188490a9c06f102484b4dfaa71f72e1d2703fea9aedffbbd3af5c9a07535beaee29cc6e2af9a04c55a6c2ec10fb456eb5c073cee206d98bd8081f8baa462f80c750a3064de9f2872a751a581a63bc4437fceccfa17a8e31b668b0009d66a07abba012eb54c2efe7a89c4745a58b8af3262985dc45fbf2c827235e78e3ee2f298dbd8bf1e3b0ca4048e9fd9e6c7258d93dfa42d5abc9e7aae2915eaa67a2f73631563c342356d5b59ac1f0c0ed1ac84250abb0bdc14595e13cf9f49dd47926859b3e04dacaa87849e35d035216da534e48480da9ebaa08ec4147d2905738b717b6e836806d623cac61c4e0d86511b27e7acacaea236463bc399adba0e8ac9d8d11cd75a2686998ac72d9b44e3620c7a90fd5a1abf0aa71702d576954ed9f79d20fcf9e713a3854cf7fdb7f8421fac7a97a4ecf2fef6cd7a4b42910ccbcc86360be0569b3c5977722df73975db6651df9d8a661883bdfa781ab4a3bd75b3afe157cff7ab9f3dcef8d0b3740687205935c4d0807575e129008db7151a4948436abd24d69a9ef9ffa724d1b9e86e30a23245378c68b1716cf79b8507b3e09032b0fd69742b26148c91c1155cb2e5161474d694c433a871ae71fe0ce481ee28d514f5f3816171ed867e5c4d", "9e9f8a245d9344115a70cde3599ce43e9a54fa4c55479cdab748f1782cb0008c024903bad4a5e3272100b9ece62c16782c26d61d83a8fa214f0c2288458f4947e0bc2bf61447be3005d321570945aee6fb4b2b71bc63fc7b9132fdfb35a428b9738235eef5e7d96a03348a98186b83816ad9ec2c5eaf85510bcd8685b023e000bcc768886acd932cf287cd76fc393efc90a211943428ac4638ad114fecab53b8ddc61b8268a4c6588ec8d04c93f5189eb1df0dba55e0ac1cba9da66350d4798a3ccb84e9d4bfaf2b9c583ec361cd78b1ad5639a01a66b2c13f9ff8aacf1e1f8fc240ed8785c233b5d04e54c2e921c72419f5977ba3d93358ff7376d226d736b995701703e4d77b9d60aa6153378132932d4e4e47ccd2f28d3c33780eb0d9cf82090812b11ae59b6b60c2a621bcafeb5014b4e6c5fa3c62e007e93ee00c5765bf72c3de12ca8948eea4ae8a2ebcb62c99eb669dd2b5a3b854d3dd12d46434b414cfd974fa087b95f347d2b599fdcd49ce58ac69b2e6b7fec6f84da6b7114b329b3d6314df17d05edb6580680137bfdeecb3b8d915012adbd1b1fb5ee8ecc0d337cb0f0a3d0fa28f5cdc7fe6eb6a6b56a87a8e88fdbf4d86370cecea316f08898ddee6fba812f315332c57cb4f2d016c4c20f6cf77c8bf9804c3a82265ced6a83cd92d2bafce5f75a78156542897820879342d617796939d75db2bce136ec6a704", "32b7cd2e0e4efb13a2a992f110a43fd71cbf56fd00d5e680463b02f3b1c0fb68b7647f76c128dd13c8d1544c9fb79484bcd674fd10abdcf7358487382980db3cd4237e7be2e65ef6fe2b8857d6b60e53fa7e7503795ab2670b93e4b464609ca0f8ac8b20be6f11f204086388552d39ff171ece7804488723fe62de58ef0492a694de191dd0f6b052dc452ca0aca9dc69fa5df84235deff73c881a3fc425326d0e6ae3ed6500a6c0a0994f4132b3769d3840880848d11ecbf1e2177d7bbcf8b04630e61dd50cde4b407d51bf93cad357768946cda150cb0542423498a9e3d3a1c5ccb214a26c1f154eabd8751703c4cab855445cbee8f265ae0da35d860ad677c3ac50a69c05d68e720303d67690d91814fdab72bbe9e88e147348ec772f0f69a450573a000424c414bebfc14898bd849990527c4cf9c6e3ccf70e7a68d33616e2881054f41f1480eb56c34dbea60d63b8b2eb10741f968a8260a00cf211843e8e81ecd25a3ff01b1a520495ccfad0174386062199f7e0d195e4d95a26626fb5bfc12c6873a0f3eaf00981bbcc2b83bc7f0049c9eaeb67bfe45b04054e237fd7ba8f77ce349933573a3f58ef5be95370e9a8bc04a841d36edc9adb4c8909e9b43db0172888f3f30046010e6223ff62f38e6bd111869f16564b08303aebdbb18d88385b966461560ed42dd544916eff593b0548cb13e81587da635a3da17b7b549", .None}, + {.Sub, "-f2ba93f4ee89da6fb1b2e7a1316f37afecce9d70fa0cf36877804a4ae9190707d16fc9f327f82872ba385172aaf74e1f53e835e1655a3e84e3acc837a1a24819f09cb2b5538e186b8a59bd4e3f52552c7311516b6f77b0ba1276280b4f0aa6bb924257602b72c83ac0578a5e28c85fd8e4a92376afcec170408ae7d24a4aed974fb492b0a6a4ed40695d017603e793fb128a82aa2df55ca5226b07b67a5127c89b1b05b68fd36106cb3b8fbc9e62a2f567f2286a9c100e4ed9d552027a874e9aa6feeaa120bd916372b9e5150d30ae70700b8736ad0d255747a1aa21cb36ab8041626c6c3628e07db1f631409438922793a16a37a00fdc42437e1c12f257117a17ee1e170614a6af1fc598796edeee1f5870046d9978b1c1bccab021ca43f471bbfdd47abf030bcb6086305c7fe4c24616a98a368ee80d01094520566b22b087229cc911aa4f05f76cb63852e0c20b7e5e9394173b519f4b22971817bdaf57491532678aab883303381ab08c4f5ff5f78dd6c9867ce90d924c8d104b33ffed4b1a639ab6885710d0f3cc927227237893e5e931b5128f7cd40d7595b8d81b1993bdce41c3017a73eefd8551ad66a4d9b0968fcd45b97401cb3e73e262e1c5b854f1f0c6c700bcdccffc8254d12e2806ed3d785129c421b595456b27bbaa92ad37fc4bcc9567081ea74a407839abf5d646ac3a26573d12b094184a021c56c8ddad", "87c18843f3f2e4b014d81b27a7e0821bec5b89b3a828e5f89b6004a57d07007720c7bef1d89efed4555282fea2afe44ec7499b89914f36a8a6ddf38ca142675c47df54d1fd5946ab43390dda9d0b5ce019268234129e39c4bb434b8894c064fbe7eeb004036fdfb7284e7cd67e0ae482785fe080d1f17dabac0c73d60dc8830a789a447c2c18c30f8a7c592a892658e0dd78dcf811885a52f493291cfae99bfc6b142c8e173ecba33ba5131024df6638374f7caae457a4e76172e68dbb94c535944004600f36b8d7d5fe9b77e45b49d5cd42eb85921ff1ccdcef977c1e60b9d30288a1a5aa26b06a31a06a768dc1b5b7f10d978796c98a08e732a1053adb07a2a3b7ee95ecc0cf08c0c81c3f17073ed98fb71a84ee7880c46532323635e07b571323964057834f1119196475d6178cc1a27579842ba3c3ad7b22dadb9ccca85330517df8fc629427a419610aef4b6c3399fb9d8a029d5db32eef785a06ec3f094bb796d5fb26461c32f42f287f374f6ff6c5db4c361e98841ac5c41c762408d835d39a50589004cb3ded0ca9031558f1d554df7cba053af935b69fc772f70a1c784000ee1781e8edd243e6de45c0672b53237bf28709aca84028f015ebfbc95fd2dea1451f3818e4292e957d363042cec58c17e09c9304db48e77cac7b0faaf9b1cf38ef9b320512dc843f80b1fb1d70b826ee5cb03d916456a3e9ad03952c7", "-fb36ac792dc908bab3006953abed3fd1ab94560c348f81c801364a9540e9770f437c45e24582185fff8d79a295224c64405ccf99fe6f31ef6e1aa7706bb66e8fb51aa8027363acd63e8d4e2be9230afa74a3b98eb0a194565e2a5cc3d856ad0b50c142606ba9c63632dc722b90a90e210c2f217ebcedd94afb4baf0fab2775c7f73e36f8696679716204c708ac79f98920621079af0de24a51b43a4849ffc18861cc487f71474dc0fef5e0eda0b09958eb6720354a55889d4fec806b56409aee0042eae721b0fcf0f019cecc8b76630dccdfb5ef062f24741570a3998d1cb71d718af68690cb4b84551037e7fd14ad8312b243b0197c74e2d1f146234604c1f442299d0064e0b39fabd21a3d604f620cf16b7615e86039ce031dd3452da1fc272d300ddec47b40bc7217c6a3dd463b1230d0e1ced1a2493be0f74e0424ef7b0c55a1e0f13a152f39e6f7ce638fb6c24198334defdb7b752655860f9d5e1e1b39a9ede0f80b3a9764fb49f37ed7536aee8d43273b404af71a8e396c8cfb622dd89dc0d45b8de0111da7ab633cb754ce23033e7facde2fd083a0d0ffb54f4a8a35855241d1e2f2927ddaa9901b4b00e0234bc20504e1e49c95c2767164408574eaef1eb0db52b05e5e3f153e29018b0b1a29d112a7cdeae5e2f9f99f867243a7e79768c02460bb3ef87808bc31b715881db7bc953d081689aa5db440b727023074", .None}, + {.Sub, "-6087bcc733d7f8135405254c3dcabb711a2274b9b4429c2e7947827b3c3da522760c3910c7990fef93f11dbd2f791faa9cef8ae3c0fcac1d9de71ef7bc84173729754feb4b60c685de52840468e050c2450c6567242ed060c11fc62390c96ee0de326ba0b4a75ec3133afe635cefe2d89c726b897c806240e4bcbd94f6881210fe545b5143fd435cceaa0f9adae6879fa9168020f028b31fa397fc64c50e8900bd8fecce1ecb2801a57a8e003093b18d2da50030c4e16f325606c642ba9c3e972e3876ca44b7443efac57af4f97036d1fbe79d3495cec577c4ab9093cacabfd094cd9f70fc6df181f4e13caa4c6132e3f5340ff1135277d727374ea9ce81e3c1ad8ce379ce776ec9f2643aee818f9f1818a3f32acefe75b2e9a5c7389e6043f45e68318269947be1b738fe1da68492b2ac0dd617a25a8402f5193ad48f5d60728aa9bf42b7ef3f62d00a818e4c6bd83c0b926af595be7580e6151d9c348862307aa079cd6d584307412e845ae273fa079093e08e9a760065c90a2e1119d20d796b4e268233aa20c8bd51b02cba6bfc4e75cd14696f8eb3396cb32b9442136648c7029501f5b075c39fee5750ab53863f1036b481dd5cf56ed4694f2be0d3b09c824724c5ced0e4295ef6fc5c44c91764cac4051398ae5940887334486a6f0559b72d517e5a25671c70b11d15c6f4053b62aee39300873c1db201d3f04c891609", "629b4192931ecd243531766e9415873aa0f3726f7ae890995900f3aff6b7e85c4969961e66eccd2b7ce765dbaf327fd69a59a83c936e2ae628c923e6a633b7179bc942f675b83e93824405f2580c2a6ce18ef65cefc17fa1c15c790a1b68a1156978fd11ea68d03b55f0199acde0c4eb9b7aa73da5a4bcca094fe3fbf191092aefce57c49c98bef60fa559b867cdbb7b24fcb69b732726373921410c0d15b1154505de13c514263ba69e93da6bba06816cf6083f5f7137c2f614d6a77f0bcc5a36f9e17fab1069818835c94122ac764b3726a5607269e017311e810c4ed8c6d6abdac9c6dc92f26522f7d127bfb92f51bfb2ccbdf552482f4d55cca85b73013b9b3bb44dc1b82189dc893ef3123e153429d702b7d53d221660a81f0f8d6c846dbe8ffdff9a9175a1a62c1acb3752d5ef50e68817a26840643ee9529a6fe0b8b875caa33ac94a8ad4f14ab4ca28075a01411e96853617ffdc77288dcbb6972dac2b4156092da4f6131fce7dfbb30b2cf244a2f61d35621379bca8f51ea53abaad2c35c2bbe6566140d689d159332e0f35e8b72d24c8c4412a6934cde02dda08356fba4899fa7f880b0363a1aee20786c33a2502519ca5045c3a168bf2c6a54903bc2c41502e22929e369182212b0dc183ec46c729315a7fdf69a6c8ac6aed53008ca9d80788c011047d96babec4e36e8faf8e84a1669e7b563366accadd5c6b6d", "-c322fe59c6f6c53789369bbad1e042abbb15e7292f2b2cc7d248762b32f58d7ebf75cf2f2e85dd1b10d88398deab9f8137493320546ad703c6b042de62b7ce4ec53e92e1c1190519609689f6c0ec7b2f269b5bc413f05002827c3f2dac320ff647ab68b29f102efe692b17fe2ad0a7c437ed12c722251f0aee0ca190e8191b3bee22b315e0960252de4f695342b4431ace1336bc634fd956dcb93d70d2243a160295cae1e3df4e3d4c1921da9c4db80e9a9b08702452a6f54c1b9cea39a80af165325849efc7adc082fb44361c1cad1d330e42950838a58ef5ca11a019a386a740a86937d900e3e717d90dd20c1a6235b4e6dcaf08a4c006748d1b5229f4e4fd48c897c7902f9053ceed79e193cdb44c427af5e2a43b97c94a4de6482bccc8621cf82f820425f1835d6518e8ddd768a1fcf45e2f44c2c46734028d6eff3e192b0074627d8139ca37c15536587473323d4cb1017acbd6755d5d3dab67eb1f8fdca5e1cfd69afd391a60fd0256957f26f9d536d6abcfd813df85b3232fbf0cc8269783e93e1a00820993db8185ed9a0b845e84418e3852f463d5e7f9746fed6e7e36bcdd9bf02ffdcea351f8ff8d5b0d024a5bb6d37a01f9cb0e7fdb1ea778f9a03e736615fcf376c795887e7d6fd6d8e8b70acc3cca08d91ff219fcf4d55c585a43d72985e2e57820ee47d7d48bd773cb123d68346725b773e56880bb29e58176", .None}, + {.Sub, "4b47f06b065dc4c9e7ff68c52e74986bc14c34c379329331bc4471afa5a638a1606aa4b3eda415034b9e2a98521af5b9143b7a2f5ee456a2d2a2834a56fd0fcb49244d789a2282f0bdff9de057a017bce3fdc6dc086c2ef06eba32d15fbc03dcb2e19ba40d8e6742954f328eb5c558311f999b6c2187c423fb113391cf9de0de55b3f06fc2c73ca9c7b3d13fd4371c8667a78a8df74a21b611b82b8d232ce6a8a381f4f12cb68832547d475eb17c83c9a288f1e44584495ce5fe60f2193d433e8ef19457e3ac5fb943523af852935c2bcd0b0cc747be16a273bb8d0ac7b1d7b278f40684f925c3bc1d08a9ea04899742b12f66a12de2b3784d17bbd4cd9db100478f6e1c5321380dd8d15019420e35ebb5241bdf63b366f9d35509272eddeaacf3af8dbe9cd5ad07ca8f4e6a55ef977b047888d5a843ea4a1958d82fa1cee77f35c49f34b32eebbabe4c852dd69ff10698b3155ab63190b7352758a422a6257aba2de078c11e7fe94bc89d055c9cc379b77ee705fd3b2b85150ce5a83e9f2ce6f6a0242fa1652d8842485aa3492289c0278219f06a70152b30fa28b5db9389b4734a94116732b3d6abcdd7c9d610ad54e339067ce5b4f744dcfe3e8d30274a2996261347abe0a7ed5bc16c250a419e679f94da1c371d19006de1d119c311928c0bfa59715eae84807a73ebe8e0638a89a0c8624fe64f89c1d4ebd1b0acd12f15", "9111cbb5543a0cc44703a417bdcf4ae2e01419bd3e687ad762b3621c8b9db3ec05f354a787752e380ccf4abb295034686af33310987d892f7868bc84dac4811fbd0c408f0d39e42f22ea4135e0e8e54e0cb37aab86e2a09b36d00853fbe4338f21860cc0e2af74b7b70d831a5e06a8a891349b13a32cd9a2bc4f573a3f231775a334f0852226d029e8531b418b5bf3fe9a59a8a7e2edf1a562efe534b131ac0935db56251d9895c867121ae5349d8bb98e926d33a5b5b994a1666d720f2af9611049486dd17f20f59939651709c367b5845dcb082138d8da83db5e60c1164d95da6012ad360f524a93f1b2fa4b8c2a69a217ea1a454f938d72625cdb5e7c2ccb95922e6ff685ca46a10c3d82cdda3ba141afa6362005b5fd175f4908616a59dcdeea331f247b3b6fce7bb7fc160a75f186fcaff099061cb8eb3842d5befc592d3c9d87f2e34bc697f1c716c65f678943b952dbf2cf4bc7912acfa655182f5d964469646b2e62736b26160d9da978a1778400abf0f663a324bc90779fef0509532ceff1e266db128c664a6d3e7c76422dacb4674a67a37ca9579fd707f98de6c315837f6ae5cebbd672675c58e6c2dfc0ccbbed7e5dd55b592e969b536cc52daf667864573435214f9a4acd7e2508c9d77d1c06e96b667f6105cc72cf9ec1994455b5220c75a31764d680f97a7c5a896271f5ebcfa5a2beca565e47e57de902a9", "-45c9db4a4ddc47fa5f043b528f5ab2771ec7e4f9c535e7a5a66ef06ce5f77b4aa588aff399d11934c1312022d7353eaf56b7b8e13999328ca5c6393a83c7715473e7f3167317613e64eaa3558948cd9128b5b3cf7e7671aac815d5829c282fb26ea4711cd5210d7521be508ba8415077719affa781a5157ec13e23a86f8536974d8100155f5f9380209f4a01b724d77832b21e19eba3cfef5137b9a78e04c56092596133f0e20d961294d386832107efec097b4f60317037bb680c7ff5edb6228157b415edd2c13c55e72a1eb7300b89b752be40d97ac238101fd155f96475e3616c0c283ce98e8e76e9091047029326f0e88379176ce015254aa10690de7bcb4e02c053a3649238c83aed698bcc05b58c8b8a56bc524f03440a3fe1328c6f2feb3aa56087a58e6803ec6991c01ade768284271af0c2326ed1df6aa61d2d71ae06d8e8be301cdadd337a919888c7983d209fc698191a36d9f5a84db0f589381b8a3b83f26d43f381da4d70984cdbddfdcc81c4eaf928779fa78391f7b065dc6c364fcdb2c575e5042402129b3353b86d85324d59fd33677e26a5ae521dfa5d0ea238eb597e9c07ffc699848f10b2326be982e7017820641451985cc63c9de385d052510f885479623e8961591ac72b6fdd872ccd3449666097eaa1b5dbb006b849bac89b16f492e45c0d0d919bf6fed8d12d897fbf53350881727634d117d394", .None}, + {.Sub, "-eb64dd92838e1ba30ccf5a531d96ed4f3af6ed95d6bdb131c92ddde7fd74981e06e61959ee40f19e902797d3350381bfbdc722ac5d862a2b34a00c4cdf40f1d19a44c71862f9cbeccfab4f630cee3a4ef017b6878988e4ccd3251e759f908f8e80c31dbebbca4cfd6b900b1e8a734ec01e73427894e2554652fe5f0088912f49a14d17bc024d580354eb3d611bdcab2b811e7729c41070e354f87394ff7c47b7d420fdeb7e9955a37c7447a0dac4b6437d27c2b8bc4552f981675c257bd397d9595ae9c4424112fcf2c95f88b4b7a8a22f1f7b3a150dcf655f6d415c8cc25357fcc13ae3d4b506c90fe49f3318f3c07ae44a5c550e8087bd18c739d263717dfd2f570fdb42af9fa722b57f93a6f8c6562b6b7310344fc27c40e3f51676b65aa16320ab7877dd7b824dbe8649b70d6a0e67b0fd65a5ed540b830fada3543762814e2b61c5ba2115cdaf2e761b3accab284c660eae81b6d86fd5cf6c43ef6c011ee5f0f79718db7209f761a80cc7e6ce5dfb78620b9adf9ffb6cfb52562631429524719cb23bbd2c0a2ad69085ef494bc595cbd0ee8ac953cbd02dcfad14d26a52d22546383e29e3d84449acf1b96f59275b7665a4d9311f1d40581f631a1c27681c2e4ced75a160a35f43a5b6c3ccef846a6e883035331ea530a5bf54f51397943ab1fbdf61f5e21e998ee8384feed92ea97e747883cf9381063601b2a46b8233", "32512111698c12fa1ea6e193a6a4e4291e42e0ac25dbd251d34611e56f983e8da86bd26c0976a27bfa3ce0aef5f32043faebc974be11080673de7ba9e8ca0e83c0f7f141377d99fb14c6e4cbd3e014070b1fe3b64c5ad6de7df487b345215566cefae88e684269795b7ad7482c82de646043d423806676acadfe8871c495f987b9a7e1369ecb5f445c88232dc4790c1589af3bab0b8207f5ef7a39ff4c0222f580351ce1e3b399d1fb9bb38d5a7d5433d2c69477dfa049e917b30ae1eb97a97b86cda1b91a9a8502ec69af0e594d50f7cbefec714568d5430dac4f95627fe5f51d050428fc6cafc7bce9c64c3db16a9026cecec660a22a7ba1bf24adf6aec4e9461190b679c12e8a1ff6f9fdc3162be8da321214771624cf187a23eac62b29bbd79c7701c4c2fde5f9d1e194af59bb3560fa06c0a3a5f1856f8e53ba779d44d94dfd69baa80c379295b72854d974217c493a6ece7d37361826309e520d8c3ab49e54242fa823c319624386aca2487353b1fa0cdb6c0879e10f2dcf02f1fbdda8a2c091704d4cc34ca73f7c3bc82154a86983c0afcb5d25d2604b143f555ab7992514eb1e60fb58ae667d131b7830df32ef0ce8abc9b3c93ff985a2060b58273c5f710b354fad02167a0e62ddf2b61b22b0504484a1936a6c69bf284ed1e533656c057b32597118d482475f74e15d65c05bba6c43dcf0880641f0310fb70e1c85", "-11db5fea3ed1a2e9d2b763be6c43bd1785939ce41fc9983839c73efcd6d0cd6abaf51ebc5f7b7941a8a6478822af6a203b8b2ec211b973231a87e87f6c80b00555b3cb8599a7765e7e472342ee0ce4e55fb379a3dd5e3bbab5119a628e4b1e4f54fbe064d240cb676c70ae266b6f62d247eb7169c1548cbf300fce7724d2728d15af4f8f2a118b747b173608ee055b7410acdb2d4cf9278d94472ad944b7e6aad54561acd624cef75780ffb2e35420a774fee57309be59ce2991a6707676b4154e0288b7d5cdb97ffdf330e970e04f999fb0f67ab5a76a4a86d1990f1ef42394d19c63f0cd121b690ccce657f56a52b0b0b192b1b6f22b238ba865e805a2042e67568a091bc70ce3142ac79916a0ef23f059d8524ab65e74b595e19013ce1845d3abd227a3ca07968479067de66672543c8ab042649934590f29e015dcbd4a75a9c28cb80622d4d6044e59e701440cca495a07d7cfeee0e87fc000a95fcf83bd384451bc6c0ff352359a52eb96a2f41b1ad726ee706e819dc7c292159182d203dc7322e228909ef56d2160cc1b76aa06dff4f919e5626799e3078e3ec6a2d21ebf73a31569f253c86aac6c00d31a0385a4a834e50a2e4e85d39ddc16925744ea47b9f5822c54e62b9d9520894b6830aa71abeccb4d6c689119a64e7a3c6f8caf9a6b77711bb66faf31bd647ad314c3eef0538e0bc60c01b87482632c25b799eb8", .None}, + {.Sub, "-2d6ee5945d0d6132bddec1de891fc9ebe8e10fc2d538119d96320e38b9b2afd255050668d3684e59cf0542a2750cee546eeba8b44f800a7f6445fcae663bd813db1b746ea1e05aeabbd6d4a9270217cb9c26e7da851dbb60ac52277fdc1ba6023f834a2b9eb54d3444a36666495add00efc5d974dddcc5c45b21b7cea401574b742ad8a6058c8f0575378c1dd0ede8fc9b224658177c026515408cfbac54d9b29d121d299343e89ee68e86a64d58d2d5778f43a791a6057a03899cb5cd1a29e53c0ceba8164fcd7c354081133639e03906d868a05df2673147e7924e2f7855b0b37efbe9a0c454b3aa3422abae44db36150874a173e0f66c3222fd56a14ebc2c02c359c4d2fd40af848bc19fcc65cca402a6975c1bb02ca2d0275f6bd30c8df7121ebc9b0d570b749f866b82787b6882b5f10ca511ec1c6ffe901fe9525ac543e9d3cf766ddc372f60622a13b863ed3aa84f1a3ce8a1fec70eae3871fa01ffd44819153c28e79167b22eebfa5099c29cbfa398ff21d0ac7b74520a7445bf3a6d399b1bd062da757264d40c4bb9cbfbc0711e9c3d8435d7cd8f29b4a1cea459362280693cbaedc8703f2d9afaa2e4156f2b1259860176824e3b699fac5a5bddcb81822f414f95158557b8a173980125719e8ea5f76d09d39084877d1828fa52f1fd3825d5ebbf0d1f62087b27b010cbc11d1e74f5b68f0fa6770e0fc3f571ef4f", "9e02a7fb1ef8312ee78aec5f0befbf3027436db1d7e451a80ef8606e6cb4d87d891f573c1227e9079c099e2450294d98cd4fbdff5b882c4a9f96a83d4bcbdb1060584473748c6a71769174c58b54c132e34c8d05a02583ed000ade3f93a2957d08dd31f99de6120a1d24ed6cd32f467265c00f4dc166c2d12cb0ec09335caec2cdc6c250309814997a5cbf5c8af1f14ecd6264edaf930301b01c054ed8f2f34ed2388270a2f0412946477b3788b143c6bf495ee3ae7ba5b69f0707c4f145ff0dc76f8602e8d93bc853add5704ec0e030ac6bb47337a50d53c4d0f25fa069f963bcc86b259fadbba90ec8f004cdf1a37a010e1ba0f07a18a24edf0a8aad2e46706f44ebc2b3d7f5f3c7a84cce1007bbd187c1008cd13604e03832296765a61e9ff2322a8124fefc68f805250e2fe8d3f267e8e3166ebbe1cca8e8dc2433d8553350bbb5fa0fdd5503f10c0f0eb73d7c79e8203ca4092ab89513e3168f7315af0e9a7ae51cd5db99861989d5c0042139a762975dcbaf56ba53c281a96540c2fa6e5677e3341c0f2246758fc5686f2f2cc18e06d9a39bdeb9c39e3ef299b15ecb8ad9ed1486fddbd0c5aab38270160a05b1bac91d804b516efb42f36c34fd9b9aacf5a5132f378b8249e957f52c61c4c1efe1451fd3f96140e94d1bebbb572d9f3e17b55c00197e4f376fe324acd4e3a8edc0062e115c5e559944316aaa62b54953", "-cb718d8f7c059261a569ae3d950f891c10247d74ad1c6345a52a6ea72667884fde245da4e59037616b0ee0c6c5363bed3c3b66b3ab0836ca03dca4ebb207b3243b73b8e2166cc55c3268496eb256d8fe7f7374e025433f4dac5d05bf6fbe3b7f48607c253c9b5f3e61c853d31c8a23735585e8c29f43889587d2a3d7d75e060e41f19af63624a39eef944b7a5bdfda4b6884ab45c70f0566c55c924a8547cd016f4a9f9a363429c82cd601ddd60a169c36d8a28b4021ab30a290a47abe6028f3037c71aaff29094488ee568384fac069b3441d13959774850cb884adcfe24f147047670f4072105cb8fd12b07c367eb016169042645b0f0e810207e14e7d029c7208458786d536a34c340e6ddc6d88758a6797e8ece63183085988d338b2ac970450e71c325607dd978b9090a8643c751dd9efbb80a7fe3ca778fc0d86331a773a8f85707db98c33516e39226fa169b4906f56e0f1ccb75c22914f016d17aee2e293fa58fec32aedcbb8c1ba54bafc44223af6cad12766cf36d3b3d9868234db9012ff047ee997b8da63d1b428fb2881ff2575e1201491912d68a73b800324c0fc6d7dc3b8c99935e9e11d6ab8ee1b20e5db77064cc7f1497e5d0be157f7787877274270872097cf4110969ff9c5e7617fd3c5cb666b1479d1a368d38027f23014ed81d6053d5c56d1eb9fd484f474aedd24a30712ed653fbb3f7a6e582738a2", .None}, + {.Sub, "b822ec85f636dba5c4a4c10ddd5716023caf3f4a43afeaf16d20ff2ec2f7092bf0d6a1ab25c4b20b679680f8efa06633ffd3afef8b2b4be328caa66ffc6ccb60c148a5ad17510aee9b93816a8538dff267e3778810775c9ad890d94b82eeddf3a6f9ad0f7f9f41604e786c7fe089f11014873fd77b30bf2ced35648cfe982db3a918a59a8e6dfc0e3ce64ea038c71b0ffd704ca4a545b8fb5e765966f12683dd29ec88a1ebdfe5cd24ee0e7c8f625e0071d45f413ee67ab1cef4b4b5094fb7a15645044038ebccdf75f387b0825847f3bc995d3509b9989cbfcebea8c78be1a78f34cd5d35aae2fb670724f72c6e687822cff681b926a7c3d3a1f41daac4761da72cad3df6e48b3ecc9f75e0f051b1cc5ff4e21a91f70239272aa6b71c1e9948a348be9002dff65424ec082ec799d2d56b61ab69e826bc8cc9e077ee9193e396ce57cce43bdb4b42efa4364bf3eb9baf7711ab11cf8f75da334d75e8889ae7961ed3c8e84d84851a02d26e164cbcd23657372343a584259d66b748849b5c5d778bce1fe393bcb93ff56e01947b832dbf06bd9c4045f29e119e4dc6d4fc9e2a609cddef70bcf78f327df9d8afe27a3604519a2f2e9fc6db5a9afc02b1e873f23a5b2c55ea3438c1411c3beaa9796498d55b37b5922dcf13fafb834cbadb422fed5007ab752957767adad7184f10cbe1b2404da936cc386135025bae848d4ed96a", "93f8e2bad2f7a3341495963544f9a1ecbc3d0b3046658315fb39bd4666da020e7573cbcb0a3ee7b9429eab4298b8bcb463f6e4f45d7152d56bce0d2cf48afe1f8f535f804369bc8e36901c783cfcf1cb8938a3e505d033f21077c47b60e689784d94b2dbf9165f9d80b37119b66f1d39586e1c4243b4d3172a441b3c1dfd6d6381a33473f77af008d52897fb311da1253412a943d9c508ef388a1fbace05d461ce20c11c665e3f42247ed2ce61fe75486d830d928217d63ece7948d854414a38bf22ba86b65c8c89807a342cdc30c958b7b27ce266e31b244ddad64a80a41267c00eec89668a54c0ad1c1a5e246818427a08e8229bdf91878cea5ac932f4bb6e3e574a60b62b69e6a0e7658fb200469105fd11d5fa950f80453efeb4a4593274fd9f18fb35d7088e2bee29c7ceaefde3adbe228cb5958a8e2742cae8f92ae5f6eb308e7b998ad41668ec61aa60d6dba6f2655dcd4c645fda6add7c7cd5606f3ddedd2067e366ae4b77e765eca138a1e49f5f56b947e3b9e0aa85989ce2d3e3c18f0c4e1cb01a0b1ef95848d83716623576c01d1cc17fbdb59f9f1d60ca81ed018ee2c24ba3ed017347c291f4685a9ee302e730b48288da6e9fffc9ae80113043d7d46ab2089870e5adb312023d58518811989f60cd334755d82da0cea9a33b0517d773d14b378958f27586d026e08f99d2a52acd068617e41f169614a40e0f25", "242a09cb233f3871b00f2ad8985d741580723419fd4a67db71e741e85c1d071d7b62d5e01b85ca5224f7d5b656e7a97f9bdccafb2db9f90dbcfc994307e1cd4131f5462cd3e74e60650364f2483bee26deaad3a30aa728a8c81914d02208547b5964fa338688e1c2cdc4fb662a1ad3d6bc192395377bec15c2f14950e09ac0502775712696f30c0567bdb6a507a979eac95da360cb80b00c25ec39ac2320af7b5bcbc7858581a68b006f3bae2d63e8b8045151aebccea473007b6bdcb50e6d68972249b9828f4055f5795383a6277e9b04e6e052a2d67d7871f3e85e46e7cf3fcf25e0d3cf208e3ab9eb0a9908065035a8c70e5f1d47163c46b7995477cfbaaf68d562dd40b921582bb810513e516b3b59f7d0449761f2b8e1eba80277c566d3a5a9a594cd08edc5f8fdde66f8ead4f1bda388dd329131fea29dad059868fd9fe3273e68a250772c86b7d4a19314c00884ac4d44832b15ffc86ff96bb33a78583ff6a8806a1dd6ce8aeb0829ab843051b7d7cc8a5da06bbcbc31afe7b88879b5fcc1d1c6e3a2ae20fc15b8bc446ccb898ffd7f238472e05bfeaea974321c3d5f0dfb2d25190a8dbf363746bb7a1f97214eb2fe7a1d3e00ebfafc39036862c1f68357eb382ba0505b6e88d8a73c0c474d499f1631609bcca52355abec319ef4e8383037a3de1fed21e861917ee9eb52186da87e69c5b24950e345186fe940ca45", .None}, + {.Sub, "-70156de89de3c5bfbb8deedf66a5187ed27583aea378f593cee4384ac8e87d96b92c42108e1cf072889d6ec302a0732c43f1a3494d9348f6e198db6be42d99a3ec72fb470cd224f49f5cecc485013b0194a46de8d6f3bf3bb1a0fa4a156325d9f6e936e5806183520a02a9dd7dc7e5f0c0000a6228eac01ef2cd0e1bdcffa6e671e93c40de5bfd4e5c7b02090b22ad7ec3c4b41b7bd3383a4d791799b09c9c913a12258408bdf9c8d918ac7cfa3a63d818b1bab35f383f922c8d30a74122c93689bbabc48ffd6be1ab27d25b77ade28f6381b059d6c3bcce344731cec74726b64498f15464bc1ab6c5b0a3a308699eb08687f4b660c4a2a1464ccf38747b0997f9040781954378f2a787a4f4c78d066684f4752713ea82807302979f11f35e1affc0e7eb0666eed85d88a111f39f789a61d2e7f0f6ef50eae5bf73e68e9756357f05f14ab839204a9e4fa7ef3b5757866cb1ac26854baad62dd7911a66d84966158531ddfe23fce8f9c9cc88d77a1297e1cf9d7ed31912a16ffa46db713781977d4f55d9f790b1f70ab21c1ee4b019fb391f709b092ded1c74c9a927b12337674ffda82b01d4c3bd3e7a995cddb1ba2d00923addfc64dbd2edf81fc0535731aa1eb6953b6f5bcde398477fe1294b817a88b384fe3b3c3ebc5dab4167181926c0a28e2f9beebdd783f5e5a2a9c9ca8af66f6d8d0545dacc9772e73899c38333d3", "1e6702adaeac3b62510d18f7042319eba729a29f7526c93e625b38a14dab740188ae89942dd22f320cbb6bfc947fce7156af42a83d8990355d949d4fa6f467920de5101e5248f6b07d7613a4debf92316e57c6d926087794db4d18cd4c7a6d8ccd45529a048cd4f602956ba2cf7795ee0432340f621872b6f7329b679f5c90080f41d049abe72951b9ab8b56aaa80b86f41f6cdb339ce6c46da929677f3ec753550f597e6720151a66f63db1a8af1394753188350ab1671e9149c6fff11214250c10ac0985230ef7e3f22eecc6f8e15dbdf0cbfb33664e9947fef35b5fc9e35a0ad5cc1e23bdf685cbd56eff67e004c3e9a87de67d9ef2c093812377811045f63029a40ff4545dcb031014d5c70a8daaf3acf3272878e529f15eb1cbc267e7a653cb75ca4be5b83e1df5f50d40bb16901ebb9474ec268845d10fda475ce9319ccd3d796c54e1701296407baa369b037fbf4afaf0f5b47ee26efaf61f9359a068c9ba9179234365870e00e5e7473909ecd8df248360402aa97b57ba71bc11edeaa3064d2ec697f2b4b8eb31f6fd3f54aee19fcae05dd9bae877b54db02090351911b21763f4d44b638540dba3e40de378712cc388b34f8f5fc45b33ac7b0d75783dd2c578270d14fcf830e9c272b08ad1a6f22d2098d9e4c3ceca003d5088b337489a18fcab4440b0939eadf653bc0800602c5882ad408f26a64be5f65212bb0c", "-8e7c70964c9001220c9b07d66ac8326a799f264e189fbed2313f70ec1693f19841dacba4bbef1fa49558dabf9720419d9aa0e5f18b1cd92c3f2d78bb8b220135fa580b655f1b1ba51cd3006963c0cd3302fc34c1fcfc36d08cee131761dd9366c42e897f84ee58480c9815804d3f7bdec4323e718b0332d5e9ffa9837c5c36ee812b0c8a8a4326a016268d5fb5cab905b7e420f6af701efebb2241012fdb63e48f217f026fde0ee3400eea2ea2e9776c8de342e869e9a6b0bdd6f7a73234dd5b95cc57ce15207ad98f1a01483ea6c3ed21727c550a2a0b677c46252a27110a104f6ebd72887a113c918612a27049a3747030729cde639561d9cdf2aff58b4f8e292dab918997d6bdaa97b9ca8e97941178a1684e3c6367aa6461496ad45b45c1538c5db5524ca7167b7e961f345a8f2a808e7c65e315d930b6cf4e2deb8087d24c436ab70d1a905d3490239971f25b062bfca7177b0029b89cd28739fa31e9cedf3fc3572167627007cab2701eb31c84baaec20233593d4aeb52014d2d496f822055a308be28a4abc39d4e15e1ef6eaa1abf3b7b6707a804ec7ef6d7d1b36c8061afbf8ef6a90f20c3bb7500c1bf9da571befe66afb46b32b253536cce64a7225c895ab39668e2e0907869a39bfc0c4c2fa5b21ed41623802c7541a468a1d9f7eb2848989a021834898450a01d8692f6cf99e587f31b5bbe19331e901595eedf", .None}, + {.Sub, "6906a75641d76a4b3de054cbfd901c4ff834b1984f96989df9f44e00832f3ef17c95e0128b50c22e7a0bf4a649cb1c00ada102cddbf9535cce07044f595e81727247086ce7a6136f8fe3048e11a35011fd98fe2dc08aa877b7edb5e7ebcab38b21d5d031fa57058bb4d23b17d811893a76aae068708248655ce45ef2608d220cc3f7f1cf4f0776b840e583d786369d1594b37a3dd524cce94b9ddea638356698f530b1adf85dc1f6e1abdb119e3e484fc4d48298d25f865d86fc8786695d98959e0bd5332db1b744958964d95956032ded94d1ac1cac993bf3e839ec75a0ba81341c85ca00e63046ef182b5fdf386d4b737ecf6a09affa790ed63d69c75c312d47462bd1dd041c6f3c0a4c9e3bc8a8b375fb1b7ea39bfd7f4b4ed16888dbae4dc946ed53a34eb3bc00a75091c1fd0148357e923a175aefdc94df439378181a73472697f3705d83e24b634422bf2c99bdc4e51340c15f0893c7c8efa94c51668939beee1749db5f346766a437076c62ccc6482241fae7ec1ffdfd794abcb98c5fe5b1d0650162b62497a810fa5b265230a0fa3fdca94ca71129b28ac80bb307ee41a5c32624d50b05e00b0e5fa0fb8d4575a7d8c9cc231c371cbbde607d5a3abc590a3f6bf6864fce617a22f9c21d35a91454678d0ea3abba8b371015fc33cb97428e6733f12591d67f602eac6b2563410dfb780dc19ae61b352336d6e75d7db5", "a7a7fbc24f21a47e38fcb0c3705948d6480e5006910d01386ad0609dba31c4b508c60753890835b16f39f1a5faee5cb12fac9de267743a9e3a18e401f60887b5cda5362efdb5c72a7e5e02046b86fa375ba3f399035fc53b7f93b84133a92fda17da19430722483d76330367fb73ecb6f6a013e0d4fd1f63706ab5357a8913f3f62a392bada2590097391af11efdd5e07a02ec5ffe7c0d0e79bd397b64a187ad0a7545e7275715933d25bc14804d7f973c782764ec820e153c0a64fdc92e076109cec61928d9fe4e8fe8cdf898a739e924a1237566977e0c568f61e4a16363d65600494fbfb095beac6b6e740e1628af2ef0d4ffdb8d859283c480c67f8649b5929bef22d6f5d82947eeb747734e617b4c1cbd632f5cd68ffb4de08b43c53047e3bd0d4fbfbfdd98efbdf20c3b59fe033c3f6b2269accbb3d75b0b7c15ddcb511796d8b37e9288b271dda9711edcb249be6f78f7a8e3cbb490bd5cce3b08c13158bcee26b1aedcb14c7a60a56a925cccdd424ef5374794873439b0a7c3312117930c193e0f81cab1daf855e85769d9875339d7a8e1ab2654ce7633370a61761933e87391b7d7c6f5971315013941ef60ae0499707374c3046e6c64f8c0e917e6546a550821d9a962d601a4e79d4a4af70d7a822e6424d347f6674af0a5b6e5a12115f77d804e47aca153b51084e8f8d2973a1af81c6cd94132b6a6a126d0126d", "-3ea1546c0d4a3a32fb1c5bf772c92c864fd99e6e4176689a70dc129d370285c38c302740fdb77382f52dfcffb12340b0820b9b148b7ae7416c11dfb29caa06435b5e2dc2160fb3baee7afd7659e3aa255e0af56b42d51cc3c7a6025947de7c4ef60449110ccb42b1c160c8502362637c7ff53378647ad6fe1386564319fbf1e73232475c5e9ae2485653971998c738cae54f7222295740252e1f5ad52c6c2114154494392ef9539c5b79e102e20f374777a3a4cc1a2287b7b50ddd775fd06ecb6bc2f0e5fb284709fa5f691f3f5136bb370c51c949eae4d062a727f82bc2a95521e3c385beca6577bd5343142eddbb63bb720595d1dd8b1974ee435cb82a18884b55c350f9f1bbba0be46aa93785b8c7d621a1e48bc0d910afff0f22bae981fa1a761ffc1c7129dcef16a17a795cfcbb06c0d8e85251dbd7427bc7e89dc5b0ddd07040c00e3504d0267a654e5fb0188bf98a65b6e784c320c8f46d24eeb75aa81efe000f67d37d7ce513bc6e6325fa0016fa2cb33c5fa867363c375d067794b7ad5a48d90e1f148d435044edfc438756b23f97cc385e7f43a4c3a86efeae6e2af242b06b9302bbefb70806a19846621b385cc0a6a751a6cd51b08698438edd29fb60159c2b535994748781eddb2d154df9261aa15581278d6b303adaa9831a09de8790498f28b5d621f3866419c39591893ea2ea5ad1f325fd936fca3f7294b8", .None}, + {.Sub, "8c224c0aa3b75511c4d5cacac9c5707200affae23411971c5ccf8ef23e522d378cdba7e58514f17f19b2c6b3361a7d59162df74a6182c1f57cfb2d6c6511d9af69660260b73ebabf0fef646e0f50623aa633eeb7febb9b28d3980437484bbfa8fbc0d82969e15cc1588c4f7308ed328460d78613aefca4e26e824d65e1b2d2d614381c12bf20112a0019b3cdfe5796a989fb486bdf9ddbc63245482e4517ea6d331f76668f62469487f4c730643ceeaef2dd60c4eb7237b2f56e972ffd71b593d1649a2671e73c6fb1c199b80224de1dab868021f963a6d4a2d101e9031d63c5293aa0ac8b4ef28915db9b2f5639cf2bfc234cf7ee0bfefcabe4abbd113016e5893cc5c675546347929e1144bda0c0f52a30ab07467829e90c191386827392c3f011ff760a05d310d2121b7e4e82e37ee6574b5ada0556252d2505f17c488708570b3f428a722bddec1097268c4228eaf979c8a56a28921309cec17bf97c48ddeb0da4c8f82140ec872378f94ddfa42b740098dbbe8f133713cb6980e2ce645a42d42e1e458142d9ffc210ee1f019b9310cb0318850ddb71e3656284e3f13990db9863711f6c23233edacf72f64dc5273365f0281e6a3e88844207c8aab53ed08dad12a1c4894d569179c2a71c108b597f4c08916b652d389465de7883f037b9fcc7fd340d2bfdf01d07e822900d8438e676c2da9de980830d4a0abeaf1f6492", "c5c7a871c783984b31baf258f446d413251bb563804ca4e82a54fb16c6d2d35230ed4a3ef8c29a8c965bf98ab60bdba117b927944502cd55881bdd3f6f06984753393d2c3f59c8f97b55eef9f05c557200dacb01a9fd1ebeca4a11ce6475d718ebc48766ae09afda2a6ba5257c64335b77d65bfde51017249aaaddb2a41bd59b22002d5358797032d0009f6f8819180161c8342669450b4d83d82f3895a424e4cac4f690b2f9320bcb65454dca41abb79a70112657256e1d662efe6cd7bb87f787d3a0dd9dbe15b378d04b00d75e5d2b404f85e49f7bba3215ebd287f280282b843478e474eea058579dbe35b2c4c080fe00881544ffb1c76a3420d84a68dfe591cee9df1a7296b74101f7479b222ed9e47fb6219896269ab4aca6502da170feeb33ed97c87a80a9b13a3605044fecb5e1ce724a71a888220c1ee438e3e8b388b60d12cc1f2bc9c5d6ce7086a4772df599ecd3cc620b6145d913027a6bb3cbfec3a89520fe2d1bf57195e12c8a68f2b691fd0d10d8810eb1acfcba0af7f678aab24d29f425be3f6e9e167539924961d028dda94bd42cbf1401d7f99f1ad3fd728e171a065a1cd5c225f44382b5e5a19f2d010b159d28a3fbf74b0e6d8b95e34431d20b4fc2b0cd31f5846d22a475c77e9a054e76919dadf4a48a27b8853a295f76d46bb70d9ff411c335771ef3d0e56ade80a44c97fb20b03fb169a206eb65da", "-39a55c6723cc43396ce5278e2a8163a1246bba814c3b0dcbcd856c248880a61aa411a25973ada90d7ca932d77ff15e48018b3049e3800b600b20afd309f4be97e9d33acb881b0e3a6b668a8be10bf3375aa6dc49ab418395f6b20d971c2a176ff003af3d44285318d1df55b2737700d716fed5ea361372422c28904cc26902c50dc8114099595f08cfe6eba189c18157d7ccebba89a72f875192e70a508c3a7797a5802a2396eb7743707e1d6604bd08a792b0616bb3366a70c0673cda49d263b66f06b72bd6d943c70eb148d5397f0d94c905c2a618135d731ad09eef62c4665af9d837e99fadcf41c223065c8af15501dd3b1d56f3b2cabe4f751b3938c90008922418a51e336fae63e602dd816de4ba4f0b1a521dfcb1a89392c9ab2dde3afb21ee21be74ad98df281a86b5cd0936fb7726ef97a331fcdef9de4767a02c805f01d38994b99de7eabdd9601835050aa0730b26f7e2cf32cf4440fe72378320d89af058060bdb08ea7268333c894e8b1dfc743519f1fb7a9931508a152814506f78fbd5e03cfc949e54644b7347c63d1812a6334f1ee3a21e72971a36e2c3e1b27eb6953ab0b29ee719740fbf97dc77f99b1aed7ebe6573730906a4e0e0a473a424f8adfe277fdb640aaa7b88653c251ab945e5263880bc102449400149f1a57a0c6e830073f621a62d8efc63c36131f809e171fa11a02d32675ee357cc0148", .None}, + {.Sub, "-b759b131095167d85de6e0319752cdf2fb253b47974990f7cfe95378f3ff04c11773856091b06648db5a68065b47103ca1ffe74ac179a85729cb4fa4143041ddf2a3d17092185667bf80d60083acd38ee9805be169cf4ccc08771657801cd48fe9ff1d932d85933e1a2d6d0accbdea2406ab3b44524a7c2aa19124821ba60963e5954340925853617d4796f0bce6f77d357ea0d95a2e2343cfc1bafbc1bd172a2f0566addfbc602ac45d28a9013b839718573caafb854dc1af4e5c5c0dad8047bf396c4e0891c6040b068d1435cf592747dedc0b4dff14b11bcbee30ea13d683cc547c454140f670c0be3e9456d0d3625ffbbd94a554e66a292b1263267f5e13aa3118a71dccea999add3aec944d7b145bf76b34c32f8922f6e993ca9973fa9a5c486757646795ea7cc6a441201318875d5f098fd5aa516d27ad2e064d12aaf1bfbe29b5ad2a6c6820d278c0b856ce69595219196fed9edae2b96464d5c2308112bf76f5a460097caa9f3e71b309d77b75f1bb41446cfa2b39d0de8f242daea850d8c2cfe24d15415ad1e20aef31a03ef8b6a70c6c7880f9ae395137d0967cbd184385d93cdfecbbfec73a783384793a549d627dbb5135e1a5f2327e553cccd9a82ed3c740f8bcdbb8747c65f8b96983c63a2356099e5d3a91ba9d1fe07d964dfa11b836ba6d8c0eb4e31a4ddc90c8f4fd10da678573210ce55dc5fa69dc3cf4", "e51168608e4f233ab252bfe3eca725a06b24dc868924364f955e1f95249952dbcb09d00f18fd9cb6faf7499fe60b59b5a3636b70b3b35db867feb87d7e192d1915613bd1f34b4f48398e31a58f558e80190a1eec338e1e98dac0d85f0c3a518e8cc87e5739866814903d8aa43f7386c757606eb7302777820b7bb4e69a497422a178f613de497d8836e54c44749e7f974e296bf44da573b01c3195f278ea948ddf07f6a33a705131f905520c366b47de437bdc7e4aca8073b8c8945704709f09d6f0073b8c83a28b2c168179380247688b9ca6b8ffa89254f4f3d1929a5c530ed102064883e7ffd34429a3203da8b900b48cdbecffeebce5c5752666413b55c03027c7de53d471f648283cb03197cdbddc78ef492701dba25c055a7efe90401446b656de7d3e3dc2a6b05195429fda3e37b9ff6ec3f5fdfb6ecbd99263916762810bab1c747c1e5ca960e8901b9798ff458b9b975de08be54897f903f0e54cf6ce698c5b460e0092a5fb84a32aa2e2308bcb3f777a570113df3393e2080d16860d97c9dd03231d0eda690de54db152bd943d41ed51e66c2f7be199a4258d6df9b037d9ab6e698040a3763395e906f8212b6c4a66a8772d2470d6355f29167ddc1876a6be6283545e0b23d30499ceccedad14fc951e344d6ab44338a15c0a1394d5c0e8a3086268e04c974ddd875c9e1347e35ede60b702172979422f64ade61f", "-19c6b199197a08b131039a01583f9f393664a17ce206dc7476547730e1898579ce27d556faaae02ffd651b1a6415269f2456352bb752d060f91ca082192496ef708050d428563a5aff90f07a61302620f028a7acd9d5d6b64e337eeb68c57261e76c79bea670bfb52aa6af7af0c3170eb5e0ba9fb8271f3acad0cd968b5ef7d86870e395470a1d0e9b42ce3353185771483a80ccda7d396f3ebf350ee3aa7abb80e0d5d511a2cb15cbd627ab537a6cb755bd31929464fce356816f0b3121e1f51962973899515688f371d0e8d6dd1a08fd37b82c44da7a70610bfbfc3847029929d56828dc528f64404e7e1b494798c6314889981a543a34feea038c967bab3d3da58e08571a15c8fe305779cc5e548d238705a7dea3164c552eeee4998043aaea2febe35e1a5d3ad2376f5d662b2f2c5951908fe99a04f6896790798b0a4125440c9d4d221a68ac4ca336150d3ee67689eddb4b0cdce2ac02b515d68c6a77d77e1290350ea6e0a0f509ac314ddacb9ac01bcfab8bec3fb3f190472712c3ac52e5e708cace5703250353aeff03ce2f2fc8cf3e8f9be5eed292a1aeadbf623eab6c87b5f84ab496cfca23d6e0e1c8b715b8009ace463c8630616c867dd7e534ab5c0a57a85a37c1139c3984f6a92883671734f1feb27d2aaa545fdd5c13c87a9e2cfd2a0d9c2cff4ef017a682b63ed670844f43945e62a23240ed70829ce8a2313", .None}, + {.Sub, "9c89383f948b14eae292999ac5a05c2c6e555c3c22beb8e9cdf9dc3d045df9656ad9c207f55edd802c035063acf16f82011513fe2038579b94d3686f155c0b13568447868eb3919ef8f88c283fc5b505dd3f54875e094d58b72a48692321d127eea2e7dd98a09789aa8e7eeda9fa9bc74a1887fe670da1ac63a0bb0111a508a0e291d22f1744a7abbc35c162f55dbcee3164a70f607dc8a08c937aa74f8fc1c34c38363334bb997c0ebf329a66a439897abb5a3e8e3827cad69a0b785a577d19e2a5fd1ec7ea8b99d374d89e7d76e71cf6c63dcfee658c65accba084f49244904b8473f29931c9069fec546605fc2642b0e74c3cb4836a98eb4ae0b1cd120191735380ded22f394208471215784827ae7cd0c11b9e52403a2875269bc8e8f62da6ed372f9aafce9763a9babf411586f77794856c1d9f54de8d9345f14d48d2f23085a02f019bcfdb3197683b12c06585118bf5cc25b10ef6d4509c5070ca5740e6920c5acfc91183725a0a1ec56cdb09ce71514f23925cd514754952664888890133fb83256f189d668efcebc63313a29e5a8c11f0aeb54e143925942e8ac4cbf3384cb2206ee431c5b3a8bdd8a4fc24ae31238d28c5529ec948ecb5689311331b2374e1b297c8c210b4cec2baaae6336c3baa52392a53d6c1503f5822d84641d3cff24ddf27fcd390adeb2eee2954b67c4c492419d1892b8f0b82c1c0f20711", "b5122c7e72cbf035d2b9ad848064be91425549493697bc84497ee373f0071c02b6d3616d5aa0e9909ec7f759fe1c62248d55f56875822e76e3d3e967210e41db7aa72ae48fb959063d1f513a1cd5a3fd572dffa6df4534ceb0c3dcbd2ae16594cb2c6d56e185f66604f34005198a927586c2f8e7c4836f0245a244000b3cf479681498a5c38ec773d06fbba513d0214997c480802fb3c931d68e235c993d79b932e612a25785bc6ebfc93da301b310891d817412f1ea07a4dab97cf2d1037b3a50a7ce87a959fcdf4f9431629ec475294463f6814734f1052cb59828878f0051b22abf06a582a4bdc35da481fb541c7b120acf4655b0d418cb4fd1a6ed588d9738ff8a65538461f07d7b6a0f5fc0d45e61c6f3d0184a13dd9982d1a11afe9f4011615b8c47a7398848bcd839d600837cb00a2480e10b2dda10e1bb0578e0335cb43f32130ec363bd133ebff31622808d352dbc2cee882a6e583d2ea7aea2a35c6b2853c406256ba9602ffd32ddb6420120d123b7c63df8ad753775940815df6a03815706a2a497a16279e151df31abdec7ad00d51b570f6edbf64b66c252cf0de21c733de3ab6ede7625091472c88a33859499e1b4cf6ec8826f6a545df67d8fd2c271c66d6e090491fe73390833da2a75c6784bc6ed761dd6abedd129d15e2629ce2d853d927816f7b1f08e8d526b855b594e00cb4bb96f499596ffa132a5d5", "-1888f43ede40db4af02713e9bac46264d3ffed0d13d9039a7b850736eba9229d4bf99f6565420c1072c4a6f6512af2a28c40e16a5549d6db4f0080f80bb236c82422e35e0105c7674426c511dd0feef779eeab1f813be775f999945407bf946cdc89857948e55edc5a64c1176f8ff6ae3caa70e95d75cd55e20188fef997ebd88582c676ac4a1fc81439fa421e72645b665fd970cf36009149faa8b549adb7f5e6addc6f22ca22f2b10a0b089b0ed6ffa2c619d463b1dfda041f717a76abfe206e01d168e16f71457c1f58c4214d8e0c4d9db8b158cf649f7fe9f7a392fcbbc166a64b140c50dbb72371501bf557f63861238309a12d697fe004f0f520468c05c5ac0986815528ae753457f9e778acafe4f632b479f7d3a3710dab055215a9126a74245cacf76af0e5131d7a94eafc8538759f14c36bd8fb834e75142b97606a83b991e40d2793e1e1a757b803621b0823a1c660c8d71b7783ec92573dd84c1b84964769365c5a25edd5f314184966f7525fd268a2ab9bd860c22c41a1cd56e1024d5b837d357f03fbeae46618fe983c295274c32aa85a20c7bd25d293c80a41eee4268bc33c8aacb07160569a238e0ed76376548c0a1c29b9267d9ef5636c5cb79efce4bad640428149a4764d88f3f7098acdf98dc32247155bae7906f917e455fe3b375e6a7b436704055f9f2916cedf0d04dcb17a3043ba8a143de0409ec4", .None}, + {.Sub, "828ea4264a145e6f66fc997cfe7e11246fd7ad69607fb00675eb9d007ab4c74b66d79433e890b6aa2a71e7f22fe580955e003d41f8227bd0d22108ee3beb6b990dc2ad8aedae9d26878013fffbd427da959f3b60e4a053cb38a92ea97fa7b9e7e683622f2b61f4a1631eff536b9f690b9e9b4374e9d4b3a75ff86bf0a6b389acaf16facd68ceafca82271f7caaeb414bf8f413986e507d07f111c8325b043a6e724e11a6898b27ee6df830fa7415a3b5e76c20192ddddd682d086f3b5ecf335e3ab69a61a90330a73dfaa708b98b739b32ead17aafac16fee81177f57ec21f1f36adb023a0629ac83eeee56af9562fa983294e42c73427b2c9528336d3c48f8c6bd3e11a922cf6045349c9ca30f32a01d582c59baacc2ba5485bcadbc79993bc344a786a60c217bc61ea31fed7ad64c2947680932eabcee5d6fa62dd4b1ede271746647496cd0d14ad30c352fa23f1c497c83a38c3de92360543c05cd9aef0b0d63efc43e43b29a7b4b25c04ac0aebda2eb36364af854c5d957c974dde4f1873516fcd66400b69578865044d99233890700c10be463a3648a4823d369618f2849d8609827ef5b5aef82112c4b848eda98c0f7cf1389bcca5e71b0745c904b273a8c231491de9bf558c47a813621c63932f66f9a630561187a10141765aef4f46b25a5d46dce465cd9b2d7f63f0294e19e990b866a446bc0988a6c78b8eb23d16", "72af3eb8e625494dda65a6463e046ff5c49101a14adf39911d1833fbc41fe4563ec2b2dac203c37a5ef7cbff3acc9d1f5caf881432bb3b4fb27220d752800b87c5deb9eed4e9cab271809e0d7e2d8d13af96b316a4f0c4eaadebf5a3d6540fdb3758502f5a1df8b78ec9d39e281d394789f1d549a126bd55a8f9f461642157682d6f71a62b713461d8389c311c6c18bf5f82fa29de0772e8ee64e043abf8e2f5f54e6f73df683920471bed9427fefd687c11170730bd39edbe6347d84632b8421ac94afb06ee9193e208349165168a4d3b51384ce53410f647491be8a35a317d4c9b6ed65b10767852f0ae16a447a9ad7361da637450f9f700cc10196b2d65b46d7a26036942499c88b8c15ed65013b041e111032be11999ebcb2c9016a8127b7366d7b51ddd244ca434693ce36c397f5bf0b7901c12312b99b1234d6c3ea16864933c11e75223310871f1f14663089c7d2fa823e81d889b7fdcfe8d7df8d59d4a15d7d013862bb821879193ea7b0fc53811e00e0eea2d7b346e67c1c67d993ba42752b8416ae5c374183d704cbda18ee59bc0d8256fb1aa4dc96724ebb7f40c3e6b91246f161d5ba291449f72c01abd361cf0b44a7c7036aeef5d838d1294c849f3146976aab40d11af4c3f70c29e9aa52b24a6124f290411fbaf6a80856def51527c9117f0aa83d880e3d9e7fbfa6561f08c9bfcee2796b04249426a509475", "fdf656d63ef15218c96f336c079a12eab46abc815a0767558d36904b694e2f52814e159268cf32fcb7a1bf2f518e3760150b52dc56740811faee816e96b601147e3f39c18c4d27415ff75f27da69ac6e608884a3faf8ee08abd3905a953aa0caf2b11ffd143fbe9d4552bb543822fc414a96e2b48adf651b6fe778f4292324481a789273d5d7b68a9ee834b8e7f288c9971196e90490a1f02ace7eeaf0b57787cffa232aa22eece26dc43664c16a64d6b5b0911fd20a37a6ea52763189c7b1c1fed4f66a2149f135bf272775474e94df799992dca780608a0c85c0cdb67eda1ea12414d4552244febfe3754550e85fc0fc773df52e32dbbc886731d689729d7fe59bb1728eaac67ca91086b5aa3165193a1b4987eeb120b5c909e4bb0f18140c0e3a0b542e4f36fbdb5c8c1f4412b433885c90312999dba3d493f8fdee03cbeb2b32862af7ae9e3a4bed161b3c0e9281a989214dbc1099a8566c1cf5bb61b138c292473d0b4fdef932aca70c18fdc14f6a18356a09b1ee2610e2f8c17d17f37ad487aadfea08394144cc6dd4c6597018a704fe620ca849e56b8d611aa60fe785f1a785e0fdf9853558fce254588d2ec55f28c3cee1f5c6f382ba9c23bf21dab5ecf1cdfa73f0b487a985bd3f159c4f88a3bd5001e06e8838f05920bda69e1576107e0b5c4f3bb49c2ac9b8a082d53b487a02bcaa7589472d8647e492461a8a1", .None}, + {.Sub, "-aec09533ae110d961697181a9d498b519a47788a06d4a6192e794fb2d098d05f075255a8c8f250642c25075c230fa15ff0287b306fee785928429e087da11f142cd209d621e9a6fc549107d086f65fd638fbc25e8da8c7f568998e570858bb4d3c02a28449541d3c952ad112962e191196e34a0afd329b770daa2d0920a90cec0a39623e8271c31b857c47752962a6d60a8a90c417ceb182beb544d344c3e92ebef48e396b72e4faff86a03bfaaf85db3423d6a6b2ee1e66914144b05e8899f888e3d16cbed8d759d1cbaac8d96d1c7000465f736450845ff02e7a5cf8736964909d75012b64b022ad34f6f5ae4ae8892d7348ff33f7c0d9a9e45a9d7a86e412117e478a3fb7f4e0db0f0c5e40e880d5ee2cdb85bf531a7a3997c2b97592b1091a3cd8f663aa29f43f3b599c9eeb7a94c0b6b864c330b19cefdeafb6b3e76657fd4d65996a2cee4f3c6748f35243dfb29cc94273f48d6970a2a1f2e71d3d313eb8de4063f5ae4f96d1c9495ed7cdbd26a5f6263e5f8bd6f75fdaa72af3c46ddc980b000c31c59c36a258ea7347b0eb121cc6b3c75f4f8e03ae58e38046798bb4b88508cdcaf444071be3b36610e5c9fad0c97649e880867b6a91d08db8f3a350a881bb506dcc4b28c09e3c22ef2335f8145802eff94a885f913129957105d3d9e916783b4a1954b41e1727c1efa3ddff25109d88562e84ddafea0a033e98120e", "fc8940875521288ff66987b7d31e74c726472332263128562d9d4d6eb76bbd082ab44ae1b3451cb39670df614fd9c524b99e32732737e014da74f2ed88e7f4515102e7512df6fca1f52339b6b50c625816e03ecf2fb3bdbb9d1bd4d5eb3922fcc9f162ecee53503908861d89a060060d1f3791f321108d5cefaf4c397ed696debd3826748320c8a70ac421365c7ce49533e8954528a144461020c3ae894c31a780ce497413485fbde2c40262b64bd5c23d1159600fc0e32e0c939b8f66afd58f9502268f03d56f63301f15317357dced1f1666116ba646dffd7fe3121abe901af1b8ec6e1d1c0155d6481554e56171da74ca60cac334180fedd0b8c82156ab84d96d10555543b87d671f33369d8305e49da463b15f4d161b019abc4ff35e41cea3c08704f7036581576d3d7b6b20c0b018a1ac8365c054edb7d8bdc58130ea5e1f4588411969e3056a1ca11b481bb13750b18b12975c8cb7759b7e7e2446e5cbb96c4f4c18793017cb3091b2141dc7e53fe770cfaef25c226e92f3f1c5622b820a3afe93304551cd3ad046d8f8f3d3dd334271de0cbbc71adea99bcdae27255c81fbdb519beee4cfa7e31a733e734b435d16416f9597ceac9e11f57becff1a19bde94d485e1250c2baca8ed05826005c925da543f93570539514c78639d5f4cf04bc69c13c03e8369204903ac22eb6f2a03a94f4c2b080f625f144eb071d6a08", "-1ab49d5bb033236260d009fd270680018c08e9bbc2d05ce6f5c169d2188048d673206a08a7c376d17c295e6bd72e96684a9c6ada39726586e02b790f6068913657dd4f1274fe0a39e49b441873c02c22e4fdc012dbd5c85b105b5632cf391de4a05f4057137a76d759db0ee9c368e1f1eb61adbfe1e4328d3fd5979429f7fa3cac77188b305928bc2904068ab85df8b6b3e732609406ff5c8ced60881ce101ad63fc2d7ad7ebb44b8e24aa29eb0fb5b9d71353006c2af01949dd4e03fc5386f881de5f7fbc2ae46bd01eabffa4cc4f95d1f5cc584cff6cb3fedae5d6f1331f97f8256616f4880b178837d0c4a93ac5a63a23da9c9f72bd8e997b513659bdd8f96eaeb57df94fbad5e422e3f94de6b86ba8bd13f371ea030953b327f0968f0f2d7bdfd5ffb5aad8f7596a897180a0c3b44d95864e828f1068aa7b76d7c351850b61c92edda8396d154a683ea0e9a5f90e9ed7acd868be9f628183d71654184170a724a8fb00e277fae9cf9db10ebeb850be5dd970e0e7e3319ce6d9b1cb926995ea245fe9f620aee03dd29314c40a4beef500925a56c0b551e8d027f4df4a0b1113a80e41f66e328d6c3c6cdd94f59153e2ddfb7b97e18552808a3c609a5f2bd6a666b0898cbde9beb7b68caf347493654a6b5a833f27ff8b32645f11baadbc8a8edd2e1fc861d3ceab01bb7fcb1d294f1c54b327d18df05d3d5db4eee45b57c16", .None}, + {.Sub, "-a6bd6492ddc201cb5330e2a6c64dae63a30140fc607b8b7b7f3ae1440fbd0224c72e39d2ba686e9e17eeb1ec19b910aaa373b59b1da77191489e0a7f814020be94128b15d74d62efc5a771adcf76403f263c8ec0d32090dba8847423b1a4692f38c31aac9f02949c2d2d2e2e021cb5b37aa1ecf52518a4dfe693911ab951f37c416ca07478e6307b6f3f6dacfd9e8163494543ef5a2022a225a09c10a3393ff88554a7c7cbaae04a5feb51cbc4637ee5ede0ce2cc1e0a09dec52f59e7c24496de6f69fd2fa10b0ad48c1d542382b3238877f5a2ad280c782b5d7cb59c686ebe84ef3ad0e6bc0d056d2f924add5811896661d1855f67d46372cffabc3a3c7b665d55d47b72de426e6759d0c82a6fc8ae9e4c4e80806ba82a3dbc3d1ecfa4ae6b5d0be759b50a4e795419e38602b1cf3822ae3a933dbeb4e259de773752c9a04fa49e07637259a8bf207a7104604d4b9aea1b6496243c8f388007d52ab9c68279da9a93b3f017932305cbf4c9dcaa927cffd64a8062a7ea3feb8d2e2e459d889b1ae7dd4eff38e67f1619f8286c09856e32352d4b973a80dfafc9039c4c6c0000a67534714fc45fc57de59fb266fb0cbf5dd11d96366e2af7df7e5b0d9dcb3f9a03ae649c87c8090b48d3775bc08857f8408b8fda4a7ae1dafe9a9715ce8c4b0b234300f8b6a7d0b759e55b4dd48da026c242ff5ea1a8f7313ce11eb7103a6ab2b", "d6341ac96a35e648f960fdab63ed9d90c4cb4974ff7db15cce3be79376715bd91c116444551af72a7782fda9f6bf2e369211bd89d6044ebeea3bf8bbd6ad4f3778f7b73e736c1639c468f6f89779f5f76d72fbe9c4ebd8be40edb28103cb70715e82b9e95d046ff0db0153a8d8e4b0741f5a0aed29b54251dd7552315886f2a36e0964ed82b8d41156ade1cc2e8ccc4d081da9014f69f61ace56f208b3f47228d9b401fc19ad5c475f23d48cde4a0bd650b2f5a64a014c47203eded96d6758e138a3d274c14cd87c7b95da8f5cc05a7ad3883b5e3fb8d6af7c16198133111a23ddfccade6e2c8aaf90382dd3b2d57ea66d6ff7a6a614f5ab2d844f5c3bc4e88a23f8c4bde8a5a38e997ebd3c7197b3f54cc4b5d0c4f7be941e84e51858d39c4dd6ceafce2efb23e12ace16f39f6eebf00dea8ebac2c8a0035c37d87ab2dbfed74141dc2eeca608271a80c43f97c6ba119d957194e4808bf072601848955b60ef1b53a9084b0a90d8832074b56fb4b98f8d42c601b9f399eae9ed8e5150ed0b6caaaa7dd78efd7ba65045024c8b4e22b9be57331a92fb7bcf6cd3072e603b923110c944dd980594223de0c081bbebacbe57ba2966c7be4d34758debf36a65ed5976378c1bd44c05ab5e9993dff217e6fab6d4f2b11ff464f3b4514efc5b2ccf01cc286f98c5214265d8e70269a1314919cdd8f956767ea05f0fd1c4992946bfe4", "-17cf17f5c47f7e8144c91e0522a3b4bf467cc8a715ff93cd84d76c8d7862e5dfde33f9e170f8365c88f71af9610783ee135857324f3abc05032da033b57ed6ff60d0a42544ab979298a1068a666f0363693af8aaa980c6999e97226a4b56fd9a09745d495fc07048d082e81d6db01662799fbf7e24ecde731c408e34c11d8e61faf760561fb9f048cc5ed4f792c2b4db05162ecf0a98a18bcf3f78e19572db2215f08a9c3e5583c91bf0f2658a2ad8abc3e93c3d30be1ece50c91d477e98ba24f1f9a7247bb5d8929c457afd194eb8cb35b07958912399e3231ede4daf998060c2cf077ecd9ed5b06633152818856973cd38d0ffc9c923be25a83fb1fdf8c9eeff9560c751689ca750f1bc9bf18943edf31899dd8cbb24137fa48b705531e8303a78d25697fa00b766c6c4f53ca8bdf7238ce37ee9eb3ee28fa1f4befdf7603d18b225266124094192227d4859c9b73c03f4bbaf728497f7872dd6af431c3888cc4fce4474c83c308dfdfc1533a5de15f8aa76e07e4723de9a2c07135aac5951e592852c7828be397b1e484d34be6799ce1aa07d406a389ca696340f326fb923b781c8bf2944b907a1c3abba82b9c78b434cc02ca2ea0fcb26d739ccd4719e6f9b11dd5e450cc965febd1099bfa9d667ebf8df055c7a282a39dfac05943f17fb400587f242f9e4ddb773cb746ea0b4b85f208ef40910e1372dde3b00a2ced6b0f", .None}, + {.Sub, "-daf3fbb135c60765878cf59daa988ea3b544778c9fac59999c347ac076c6f7e5ad832c9ea1e9e2093210d53d71a9f180d674e436de2e6f1df66a69c22589308847434379ba7613bd69cc9bae42eb1a05074ebf9d048ca394515e7652679c5d57dd2895e669b9e8c303f753c301ddf80cc1a95d8bedd7abac9339f59be30424b7074f449d3dfe4c85bd7c773dc90077dec8db1ff6c5cfc76ac8e349828d659b8e87187c9f195f33774b4fc4b993b691bbed2bca58d00b2f40fd280b5d12e465e9f9ae65c14e46020a8f5da2e83b8a1e010f6d635eec2317404f0a27f80fb692b5d203398b650a71b39e762809108b4347e7376645bde1e85f5218823e74286dcd54f859928a7bbe13c94715205e8715f029a87a5e7f6be971d6c2a1b2ab88dad02467b15f4c998126ab908f294a13087db0bac560dd1524b39733fbc4d210541dece54a75aa23a0f5a73369e411c4c870be6adebc7d58ef276abdab14b0dfb74848edb82dc695f638a672290768840e31fb2d5fcbe25b4ac2f9b42eb90a7490cfec9cf638ad649531fe79e5175120348fd77b4ea78f6c1f863c9bdc3517970565c67a9510cc5c5ff5c87f51a5c55652a036e8954fa995ccd0e5cb794553f15eb55f77f254408e0e7e5e1679eb97539d47f2ad5b4df8aa83de1ab20d1d35df292d441529b2ca9439dcd40bad10d0b8a6b1d5f7f7af96caaf4ae859f1942eb4cdf0", "2885de29fe5a305b0f8fc7002111dd5a3a026e8165f4ace1eae37300c9132e43d2efd19a1497a39b36a1402c253e736a85d61b6ae3ee8ad056f8983d69f65904edfc5cda5e12757964da014211a438b17194e2bfb3a2fddbcb4623a8e302c16ba1e5c9bc7ad54ca8db6b6dfd06028c65ea820e2368d3f64e4bd208e1eee65de86a0e4124fe8e37a55e94228e78f9713afe5b3c5a29d10847ff4cb31148c5b336a8fa8104c9d209a449cc04f6d5b4ff872d0ce41b14b7db37a30a18fac6bc9adafadfe79b3a4af569b1e5f6f0216f52d6fe7a20acc51c00256db332382d171f191b4096e04747785c1cc1de8a85a4bdec3715b7faadeab401e364b49c90f97c4930744f1bfadaa63590d240ba1249c1ae47e4bf5f8ac6f6c49d6eb93c3ee5508372aca97d21572052d7d03fd58ad95ebf44e902d2a8d47d8b986dcb790832382f31f62d8a13f7c9bd2b02ddc8929a7bbcfaaf97bc3f9065e847b144554a37b0f5fa1f8556fdd3891cf284190e833d84510fe2004212d527b3d4d061fd34e82499c8df74e2d1a6569eb19eb92ba2c7bef33e171d0f7224b866e715140742098e3a651e608c2b5de5c365ac5f90ef6e1375ed611bab0602ead9469e562c60787c3d04ca7de91379f42709037db906ef2fbef92d4bf449ac98569299434c7761df44933581fa53db85805c3102682c6ea4caca2df8414c4167df2a5fd14c01b6da6a", "-10379d9db342037c0971cbc9dcbaa6bfdef46e60e05a1067b8717edc13fda26298072fe38b68185a468b2156996e864eb5c4affa1c21cf9ee4d6301ff8f7f898d353fa05418888936cea69cf0548f52b678e3a25cb82fa1701ca499fb4a9f1ec37f0e5fa2e48f356bdf62c1c007e08472ac2b6baf56aba1fadf0bfe7dd1ea829f715d85c23c8c842b1c1099cc41f9e919c7365c50efa0cfb2c82ffc93d62b4ec53012fda3e3313d1b951bc9b0696b91431a38ae73e4c30a78a0322457d9a100c4f48e4d5c8890f774414399d85cf970d80de7840bb13f1765bcbd5a303ccdb1ceed43d06bac51ea0fbb380693963001341e4d1e406bcc9c61357d36db0521ea16856ca8ae855664495a1955da70d0d79e718d39be0a32e03674315aeeea6e2b5397145adc6df0a1798360cefed4ec673cf5a3c83385e9a23f2fa1c73dda428c4d1edb77ffbe1b6ab2d23647aca45f442db91a7678bce9550fb26eef69fb17683e430d3d84c4697f5598f64215ebc192830b0f600df5307276ce8490b63f5cb569b57c6b1b7f0aebd0b0189e42f3e7f38315926bb70190d7ed23b0f03c59a093a02b98f59cf7ba45b92e2bb136b4c466162449b0faaf98b7aa2c69cf71b469daf26442703d540802a56719f7a49e42cd06ebdaa74242571c34ad4b5069ad410871d74aabad1e6fbf5d303caf78fd274b7ca025eff0e30c172a12b9c2e0306ba85a", .None}, + {.Sub, "-e6f61d98e19955f458c29fa62230a4f83884a7d4532cf88fbdd47aa3188aa23ea842f9fc56b0e5e3d12929ac17e371c850a2f480a966d850996ce5ac9dd2367f9de862311b137e9c2fcdc050c964ac1fe60eedb701b3de2a65159558224f631e171267a8df3a847d97a9fb1c5c513f5cbf9fc96a1c57ac53dfed35fa0328370e75c348157a6fd5eb4d359599e6f9c1587d9406d28ac41bc36a4f3516472ae5b9740915717136d90cb77df32f2c0e4f9c095a6c8581fc34b3246719cf8dcf22c7b64cae675c37a964240b175253a44f4de1ea7eb0f81d79faeaf25dc5d88089834f37dd3fd6681830ef2126e0532243deff0101ca482f80477ce6e62ddc1c9d04e24ed502522ff288651401e92c0bb20edfa2fd193c6910ca55f927a31c560c71d11c02e6015e396ad77c2dc668499c40feec365ea967c0674df1a35fe2d0016cfcbd5a7faeeb531487f5440ca38938fc6620fc328a4b10529b9fd5a4c90f51773d0aa5f9fa5f656106b317d95d80a25446518d8a116df8728904f49c8a47e756c990ab2bd5e50ed0a7cd59a5daf74774863cc2c9d6dfb7bc494f49970587f395c2d12c82e2994d75e0e00a0850f0faa8f9d722c32b9acdb216f799b555bd1ae65180d583e9cc4e2f77e87601a6f1ee924f7a456c207fdae0b7839670673abbf9ede41b6ed4b2cc9e3a7872f11e50c64506ba93b1d3eb220e4c5735e3fcf73a93", "f023e5c1d94fe2655ef35b1b5ff2692bea9c149e21b9266e474c3b274b8cf5acfe1480694335a5e14a0a85c7180f9ecdf64a135b36f42b340492c911e0ee57195dcae167058012c33435d6b5dee2a5eb5bde16bf59a1387b8cc3a6c3948aba85895d2780971dc06753135466c343e85ae0cdcfba5d019f20e913388cf5b75179aea7075e1ad1140a89acd0f18ca49203fe9be56ce4e3978af7a0432fcef5d728ba58c4bf955fedd3b185664a8cac49aa16dcdc8e6ebf60f6d045280647afead9e02301489cf01b7e8a095a206a390ae25ab43a2f9ed4ddb015eaf34bd3e72e42e3f544c09b58cdfbe7573e7a7419520bae36585d0099b8cda477999d34b02151e01203b00c1a66d35b0e0b40e14201854f5ed03f30cd9a3dd66469dc93caef0603996f3ec7f7cc8a93fc508cfc263bb93e5983a437f3bd4026ce21a8d5110511066d10481d3326f3f1e8fe377a9cfba425a5a638274e81cfcc1fd770001da8659757ca7fdc982d9a88c0226f5da79fa8c9bd5cab399e3fc55977acd57edfa66592d87388c8db8fce2b1c7904a49949bf592b5a3d5f1d3de9b8a0d3ff37fb3def9982d6a67e0aa159bda812ff3b21ac8ed44bf6033523d46807dfec304c5af811d7d08a693cd681fc358a63c76c6b17bb7538c0ae863f2d2cee366c9d14be6b8fec3bfb1af4c37cc379aca5851514a932b0489b594ed8115243bacc58b63392fb", "-1d71a035abae93859b7b5fac182230e242320bc7274e61efe0520b5ca641797eba6577a6599e68bc51b33af732ff3109646ed07dbe05b03849dffaebe7ec08d98fbb343982093915f64039706a847520b41ed04765b5516a5f1d93c1bb6da1da3a06f8f29765844e4eabd4f831f9527b7a06d992479594b74c9006e86f8df8888246a4f739540e9f5d6e2668b739e535c7c2fec3f6fa7b34e61ef78461620bce22e61da310696c6e069035979b8ba994620374913f0bb95a9f4ac41d5d57f0da1966fafaff927c4e2ae147172bddd5a303c9eb8e096f257ab00dd5111ac67b7c6332d220071c0e62cd678655ac73b95eaad375a2748c93915215e7fcb10ccbe56c260d8b25e4a595bc0220d2a0d4db3942f01cd586d36ab082c5d917fb020fb77d4b57224c95605f56b787e53646fd7fa3d45ba02e15b7da774bfc508b7e1067e032a6ac7cc1e7a0879de42441e2634a08bc6a26ab199922267bfad14c92cf9dcd4627079d6f792fb8f733a48bb2841fd100eea354b0c3837e27ca17209278dbc5c691eb49ec09e9ed2e9d2aa7f909133df681d0735fcf5a601f01d963d8331855c54032960a3eecf9e881d078c12a737ce2318c660bea21a1ed785e5a21812f829515fed26a2d02bad72d9c9135d064dc4b3061aa6bf080da5ba030d7bf92789da201689c9764961b425187633656f77b7032f0b22c333609012023cb32acd8e", .None}, + {.Sub, "-7c9c4c10642c1af65f6dd1b8257ac40ff3eaa62e3dcc06ed26035aa8110992f5dfca7f2b723bb21fed636266564098ec54a7f19405bbba2c63fa5b3160017e6691e8bcf5683365c57c184e0785f1b3193c4d855bc7f134ca4153d2f281dd5c1bdbed503cc2357c6258798e9fd0fc4c24bd16f06d3902ad5567b7853e4faaa3c4b787fbed582eccb47f93196709a0805c55e22743835a972ed71775a660b32fecd9aedb1f4df42fd2039a0a7beed0cbde3e663f179329ed3001d9b22b77b40ba8fe340b9c3338a61bf693a8b85839672c9c685d00bad6e1a47bc5a7eda3f361da2d2a3880b09c89768c569a842ace484a7faab44199d24245f9ca1fd62c2c151cded9d670267129c0a4d04efecb7326398202c690abd54ca1c7e11cdeecdec3230f6c7077c55bcae6da9eba8a7dc8cdbc8765e035c2ff1bb995ddf0f524dd6e2248dac8e0ee6ad87a9c4388f94b251324f53f0b894cb965976371c5a696b2aa5005ce3a411e41bdb9d5ee234ed8849e192ef01f79a9f83305be31e5a85a9a7ccc3702605934fee7158f30b2e26b35d4f373628f4ec08a248b21afd07e0dbfd96036893e6dbc5a23a361ca229f42ebc0a1cc6c2ac644fb30f696ea6c72401df1afd34f83168c220396f4f4e6f86189416756fe16c477556a81f7895daeada8e41d4b9b85f114b3cdd714ef5890890d580ba62ae4cadf896910f1dff377bccf636e", "cca579b06f8ee6e88b935ebdbd326b86f486823e9c8cde17d3ef85aa0ebb0410c87a9140128dce8e097b2d5758637f9626db379c0dac1c9c42fb2de76b497a0cfc79e86bab5df041dbb046903b7bfea514437548af2461943ae86502948d1b5a863b53dcc049b9b3ee16b5a98f4dbeb775372f08fd1416d50028c653f4369629e602438d5aee0385a5419148ea75015ae425d7c0e18d8ac6b1b1c5bb859c36e3bf9a79b7e97bfd436bd83ef185756d15120cef3abb1ee3567cbe150f62d75a3497879c58a38e9dddf8acb12740279d9ede983bf6227270e570fb4722cd4b33f3fc71dcd721b430f2c0851e13b7f68a0cca95984bb25e6269e3195d57318ddd5ea3eebe0e85c518b16a11034f7d395a0a20b7d679ab43ccc6e004fa866a8c65faa9f11d23b3c7870fcb6e72c24d5b0844b8468d60aaf0eb5b0a5f624e3e565c68f83d574e51055bc8e9d5aaefa6120963332b2f5bbbcb2f52b27a9eb70af5f886d5c6dce7bae3eb784850e785277b33e56b959eb6771ead06bd2c97c4ed43fcd3d94ae1c9293ed228c820fdf68afb6c193804a16680a75589b82a04a9d960ed7e5dc700f312b4817d824c73b54d9aa877a23b97d01bc1ff8627c2ea8d16517061529a4acdf5e96f3329c018d6d253dbd89063cf61873e10a3b9055373fa34112129a24dc23cf6d0148e2cacee1cbed59ed7b523d6a484734f26fdd74fa210a241", "-14941c5c0d3bb01deeb013075e2ad2f96e871286cda58e504f9f2e0521fc49706a845106b84c980adf6de8fbdaea418827b8329301367d6c8a6f58918cb4af8738e62a5611391560757c89497c16db1be5090faa47715965e7c3c37f5166a77766228a419827f361646904449604a0adc324e1f763616c42a67e04b9243e139ee9d8a3f7ab31cd03a24d4aaaff41581b73a07ff0464e821f588c93b61e64f66d0994954d737702d156f72496d744638f350732e524e48d0867e97c73ada8b65dd95bba7f4d6c743f9ef4059df986104cb7b0098f6dd495289ecc0ef10713e95ce299c1557d250ba694cdbb897e2c4d2574a404c8d4c30a4afdce37d2d5db9f27b82c8947eac3642720ee1524e48ac8043a2ba9d0a57191968a7e61765576b291db95d8d9b792351f6a60d2d4ccb23d6013fac6d966df00714a03d53436333ca8b4118202f3f703443861933e8f1371c88286a3ae5088494ea15ec645da1a8a2d6db951728d925a9321e3f0ad3ffffd1fe9a85be302116e00c7b5e7d6d47de79a0104d42225e3db93e5751b0d8f631410cab6730b541317a14d9d9d527e720c6de94503f60cf0ea520e4169654908669196ea7c29660bd307cbead56ff566f621125e9cde4820b72ca1eb4ffcf33dd1d3fe761e625fe937b25b08eb122a7dcf53e753dd3b351aa9deba31c057ea5cc2daa7de008a1840ddc6018ddcac75ee005af", .None}, + {.Sub, "f19d95b84f1131a7503860a49daf9b571986490349c764a0fd10f34bee4e0a5a8ea7da5032f74be491bd3a4372f5d20600f36240210b403d097950515e2f54e4f854a19ce0da582b09820904855631bba0dc125fe8de62ea387e4f5870ac953fa15bbe0a0d60a2c89a28740d67721a9d5a2d27bc5976b4520703c6d20bbf1e139449b261bd757da265d867b29df8352d7673e6f4765bcb7abae8e00dca4b436f98917a912c6acf071f0fc464dbb5f3dc4ba37f82c5cf0cd2c3652b3a7bf1d0505c8a1a0bcd4952b0c2f17aa03e241ddffd8e37a117ef75135fa271b210730c231f51e9905046a86c7fb6186aeea367473df62d8c26991ce64cffeab1b60f0f5864b6d405eb1c44e30ad9f20c9c76a21b2e2b56c94db87dbdbb4431e132a9514257efbcbc94f524de443c583c77352ee122b13bc6a642d4608921a7f7aac9a5aa1caa409f5ba2eab7ada8bace04f26143d9169618e51e49c8cc904c75be317f18ccd36cef61b52ffeba9a0f34d9331535940b6fd387efa045015492e331b6194ad895d5aade04424a4cf35640278cd7e2201e7d5fe64784eb2b4aba1bd448038641414d30deac98f6dec811c67706a49f49d197c48001bb39efbaebf7040cd3286923e9bab46b9e715016b6817851ccd7887ae434061e1e0edeaaf2cb64a881dbfc7121f24cf5d739bf281f9051b54a30a44498832c5d2debf6900b4b67fb5525", "69d01e3d5568f74cae625592749ec4a37f72d558a420dd919944bda48374c7dd1f32682053e84ed6c8f3c807de13e092b609fbb012e9c1fe5363688194f0dbc6a4488c03e2140f8826a171627d055ada7c2f0ab449e5358f3c1af113bcdb9335f7200953cb3e14016d47c2dd3dbee70ae666da7ab44a2e1fd886e0b0a9f04ff58ba92204ba755a3910082fabd9a8fe7a20bb415a9dd16e94f85f992477d9f98d4832706bcde4e9a847dfa629486e60093cc6cbdbc229c1f90feeed3dbd723c452ee5f0fbb40fb1d506cb6c77e06072b88b71f824d259bc0ad926a31b0276049743e669658971bcf82aed3b97b1eacd5f5c66c174ca6b4a037061cac5415101e956c8748eee70f37c8577dfdb31f500d47619133320acb2d54091240ce1b373c68d8834b0734c89364368128aa68b91fd9f25f2e69bff6045ce0e89436fa0da07dbda19c48211b0694c35edac41d9d7020e5f85f70dd635b8b296a7e9c11ee7aa21bbbd7f3f33fbe9d8d845bad835373ed7ca40310ab7b0cfd7a2f95c2215b89bca2748e19bba1f5d31e1a486fb958fdca2b4371be04586d638b5972520c893b8a04bc53cc5d471f5160ce3271fecdc41a4cfa597bda2ae43007a4b04fd53ea01390119de1c5cf22784db62e9b719c5bbdc54cf54707e15061bdfac2786af2b8329e22794ee1cb486a74224da47675c91fc8f7645889794807ca5e14f5044143f", "87cd777af9a83a5aa1d60b122910d6b39a1373aaa5a6870f63cc35a76ad9427d6f75722fdf0efd0dc8c9723b94e1f1734ae966900e217e3eb615e7cfc93e791e540c1598fec648a2e2e097a20850d6e124ad07ab9ef92d5afc635e44b3d10209aa3bb4b642228ec72ce0b13029b3339273c64d41a52c86322e7ce62161cece1e08a0905d0300236955d03806c44f36b355b8a599d88a5ce5c28946e9527149e2505f0a255e85e55ed7301e3b934793d30edcb3a703a54ad9b3763dfcbe7f940b2da429101939a0dbbc260e285dc3ab27721c3f7c4595b908867bce970dfd078bdb6b802ac6d4eb7454c8dcd33cb899e7e18f6c175c2dd2e2dc9e1fec74be0d6f0dee5f76fcab5166856212316a81a146b81243962d0bcae87ab30dd450f5dd7bca67880c21a89ba800d445b1d0a99ce3838b48e00a43741abb131eb43b28cba240d026dad9913a4e6172cd21c3188a41cab71021d748141019f9a48bfd12976eab17af7022813414e1c1c97a00fdddf6bc412fa27d37ef7529b199870fa060af0e6e8cc9424a22ed1b11b1b92bf748057d6a46440601fe14f29522f6b37f6fcda0f587f418d82701c8bb2e9f5719c85da501f22cc25f0cf6ef40a0f206b8e9273022cfdc980eac49cb3b5397c138071bac2614df95a00908c2cb46a3ddf95658d28efa5d5ed922b317e5fab60a4ded9ea7b5223da3c5996b79ea29fc17b740e6", .None}, + {.Sub, "9e0803a7ed0578b87d47eed09dbb4b3f469d46ac31791d192c5c06b336dea4dc8372e68eaac51b52b3b9fa846880f7d9e7d3f2cb49fbda64fd8b16fbbea32744c2e66b61002cfe97ea30820dfd91e7029cd589014ed2fc59160d7a9b280584201aa486467a4de279b277f1009a9dfc898ebe8dafb938c4bd08c25e3786d5cdd38a1d061a67fa4a1828306c6f01a0f20d8b07154bee450f162dd64bba26b46c8929a3cc6e7f974371c6e0d072c667bc153e2939aa6d10ba82e4d2dbbafd07e6103c74696a725614c5f7ba39d40b5b319178af5b3ad76c57e4aaee0f1de77f1ccd3b05153f7437ccba3cba01fc88c14d903855e2c0718b218a853088a361e765eb2d93169ce6bfedf1462802cab7e967688f37816a0ba5b00ef16074cae3d5acaf6ede061db0e0879008cda2962b4f2b06f0237113ff21e153ec44ed9e425cdd764384c451e3cf6add4935de8ccfe87a3874ef75acf23caa26165d34adac9dd140529fde4aa15b99f607cf60b7ab7b3ce50d306163658aced4a8f120e401e9d45f56be814759441afdba7e30cbf67e10efb563ace23b8848a2e1233a48606b448f58ad72bf47712ca91474a41cc9098593d9541245a0fcc2ee28f5825953f81bca427094b472f555a74b698b5228ea544d83d9a0c86fe090697416746992fb39b66c0cff6b298539ebc1cc3be8f3aae5fcc7fc6bf535eee49e91a3493a87f9e373", "7de5e44b96461547dc6df9530c1a623d931536680824d63f337802f8e7eafa3f245641d58c2fb855f593720fa00842da48147b1c6ef80bd2dd5df9b99cc940278edc53c29c6e7c3ac010b6085769587687a8ca0151c14cedfc7bffc4926853e0e5b7cb923fe846676afcfa4ce93efc62434c89a2c9a1b6759cfb545ccd2db335b8ba3801155970e9fffeb54f8c4a3768ac2c7621b45c1bc11971ad5c946da536b947502f633b6c4895125b933dfe3c16274b1e6effde11a7a70150a0dbdf8edddbd4ee876ea36fc45abddd8d535523d521a0f435296c1780ef3c9beff6fe03b23396fa75f8836385a0920231dceaff7daadd1594fb98ab05b99cba23832d7ebdef496be5868c4210b36606e5008bf5a342bdab2d776d0f33d781e9e4f215917d6446c85a9e5dee0f5b6c82236fba6263d2e459601f0c0bb204a03db29fb014a210af8dd68cfcf1a1467d916b18ee6ae93ecc96e7256ca813c8c1aac8027d4e0d96d57c01ecaca5b97f006484d02695c96653076d2aedd36093f7bfaa266f06f408320e88d5319d427e626e7a3b0ff652249db6013153a1710ddc355cc16361b224fb35f361d0b9fc3fbfff7af372313e187acf133dbd2bcd9be1c8311ce6f3cba3d7aa556df8764341330fb5537a24357a32730696e7fba44fdfe5ef3e525edf2972bfdb3d1ce96040c5921afe97432e46666e000a4181d05c0d7cf85e27e76", "9629a56333a11763ff810f3b6cf9a51b6d6bf345b0f6cfb539248683a85ff538912d827152021fcd5460c3636e8073ac4352ab19830c59a7cfb5376024d6934249f8a624d66616d43e2f76ad781b517b345afc6139b6e78a3645ba9ededefee20c49098d564f5e133bc8215bcc0a0cc36a89c5158c9ea955aef2a8f1ba02f2a02e91629a56a4b3098830811a08dc4e9700444de9d2ff4d5a1c3f30e45d6d9235be0f576b89638cad3d8faab99287d853dbb487c37d12d9686a62c6b0ef49ed225eb71a81fb6bddc9b20e5bfb3625df5426954bf784d5966c9bfa455ee80f3c9217cba59814af9681e2b0e1d96af29d985da8116721d196da2996bd0129b48dff4e9e7fde8e5729d03af1a25c67e0a80e5b0ba6b7342edf1bb3e8562c94b453979899999806faa8af1316da73f45384e0b2f52b7dfd312098cbfae9c31861dc2c2279cb747aff9bc334ce05761e599389e102ac3e7fe5dfa4d9d11a012c75fc5f7932868a8290cf9a6fdf5a6f5e78d38876cb30ec92dbf19e9fb1a4e95f82e3f0163b605ecbf10129929809e452cd118a9319d18228730e8bd04576f294550e74365dbf60115421095078a42519d2627ff7cc65546d20f0314f3765d64229ac8d88331a0f1c15ce4317565a56d3b2b20a2c367998067210af2f18760a9f1613c87975d36d75b36b55bdbfe2c743c171c9e3960515354acc818be2716b021764fd", .None}, + {.Sub, "-18273052654e8656ad92028b3267498fe3abbdf14d849af56cefebf15948fc24796a56ad8b4ddbea91a1fb2269d6fd3647ad13c487ab99ce9ed4453c947aa747fe2ed91853f10e9fa37c642735b55af3599d8a79b71c486c18b7fc7717fc506ea9e460c26ac937d69938e09d9eae6f4ff84e8b1f4e158441a5f2a8c15bb846d7dc46a9f79f911f8a793c5e6517215ef5ab57c42ed7ff41250e6b11356eb6ef8962b9cf867d0dc7486224d6d5b5710973611133689be8ee622cd9662ed743234e4bdabd8d9bb6e7bef622b3bdc14eeacfcc8728e433cc0729d95b3e2387f751f0be80de126f4b1fa16bce640e58d76ac8988de1520142e9b98c35b776a30ef36c7384ebd5ba2c7491906de79a27f6bc4f5003627795589addc6b53972d4f71f02c36326196ff4d8007b174155d08b38fc9884b4891ffe7c6573dc27cad5609f1b1dcd3f7d5c439e0c841237d719050627e0ff2677375fe0609e33b090f0258297535f60cbe37419b2a6e3277b7f90af46272fbae2934cf71684663d64b6ef466724308217e3a52f207627ab0d05de7c7ecac51aa4f29c1ee914f05858c5b39ccdef9e9db6e14420eaef666363d635dcc30a0171eafb949153e02ea2e622325232f3338b119de8220dae095fb8011927d7e8cc85f9f933e422c7331267cc02934840a1b5e75f9a46ea6521313d3160a815e880450a37b2f8b38ff4c428f24a5275", "9c1a75c03190f7b0d7df523d6cfc88468ea52ee26070d563f8cb09344e6b3dd0c74e28efef86eb7ad5fc92ae2651d25ee80df037d92a1d3e726cfa73e241ec6e540f07a34196e0607f89f2afe91ff859b76170770cae581cddaaba4197e0396b6ac9d3348508bc5adcd8d6e3a04a1eea3bd3e2c20cd21467851e3f71322ec14ab360de26cdf15bccee79d8c97c551644b8d0b457caca6700803d5373502f53ec60b2a9252c397aa967c1586cc2fcba147c9b570d14da448dfcf47e7a91a840f5fd27f8a418afa92b3b05bc54862890bda57ec5a6765da747632e0f6b22cd3f654f1b10379e41cb69d6fcbb32e432d6f6ab9fde7bb65418a9cd691819ca9d2cacb570dacdf5db0747d6055388394dd49a8cd022ec9b08692ced73273255f84675e3e9ea280655e07120bf65ebdb38e24c629cf5beac84c480f2bff48cd002ea5f536d8698b336c2f3ca3c7223c054a7b6e25399a5adf10373ae0aabce282f7e64dad7cb57228c62bb2226e6e1d8afdf04cc396207e0ba09b313cc76d6ba0a32f3777e59ebe6ee5ebf31be9cbac9c220ed94280f251a3006c934589aa62a535e81e74c20a0292b34b5de9dc8f3e172d1b78e26d31488a83b23c0c27b3755cdd3c9847914d8ff6c044fbf3ee9d7655723da1a1f0fe314a7d68746bc121c9b2cfade70bfaf4f6fdcfeb02907ef9a852cf98b33327171fb5fa5a5473bc3bdc4cdfd24", "-b441a61296df7e07857154c89f63d1d67250ecd3adf5705965baf525a7b439f540b87f9d7ad4c765679e8dd09028cf952fbb03fc60d5b70d11413fb076bc93b6523de0bb9587ef00230656d71ed5534d10fefaf0c3caa088f662b6b8afdc89da14ae33f6efd1f4317611b7813ef88e3a34226de15ae798a92b10e8328de708228fa7881e6d827b5767b6372e9376753a64287886a2c9a8258ea864a8bee64375c36c78aba94741f1c9e62f42786dc387ddac8a75b0c332f029cde4a968eb64444902b631b46690ea3128701247777b8d7205ee8aaa29ae713c894d8eaac491560d9bee4a0d8ceb0b42cb1f413d0a41bf442dbfcdb7970263599ecf906dac201928f5c6a3b0077bd966733b22614490e9dcd385643061040ab42860a52aef6578a74d1041764ab8719bd6a741abc41b48fb21aa47cc8340e6669c1c57a563897a713ac6160f7a61004e4ea9fad959addec352c01ce550e3d44c3e5c5f185500fc2e372c2306007c6dc90a0e5d58408e4af3691cea740700c99832b43b70f9795a9baedc03ca938ddfa7e647c7cfa09d6c5eed29ca0ccc25b24948f2fef006fb4fd6eabe570a6f55a0ce042c57b7a8ae7a982844ff843ccc77a0f11e1d780025fc77ac9fea9d54265d6d48498f66704bb202eb95dd0ddbbaaa0def2484672f8e26b1616536cf77459a8e2920d7b68da1a11bb2b67c33129e58d73087e6b7184f99", .None}, + {.Sub, "57ee4a47ebeaf5f47fdfd7ffa1d63685e46faa97227a1e55f5a023565002dfbcfe122ef534f6e44d4f4aad08bedba38dec05385c01ade5b1dd8406541d851ca3db6232b7dc39544f1354e39af6ababe1c91483ae86761487b4e3dfe33ec79635cff59e62213b918f0fc97b05d589245858c997480df56c79daf921cc46a67347b037b95b14e14dd22a06364df6e0b2d17d03b2b7aeceebbfb42ee1f0890c7835afda5694a38e85338d0f344704f0bb61468447c66225c5dc224bca36f1edbb46bef0f754ce651836452c4d9a77a95b71b4667d3101f938f05a8dad25cdd80138c189b7b83680e7665c01e1726188119e6ce40866d2c41b66e6ac7b1478c4b8809a3d26edf2055605b3273ab976cea2c6e7f13d64cd73fdf44d90afd4cb89b3fd2e5f65b9dc0e2771e386370b69150c31ac5f0399ead4b95cf6a30d2e4dcdef4d277e93214ed1468600f2429c79bbb7c5cd04789a4cd39380e98d5ce3c5dc649429650102ab1505fd18104aab4feab04aba54f495539104c9b3052560e625585fc6de2d5410c004a2be2d4819f1ed0c48a6873ef1875623bc8d37f5d1c536a84a64bdae665e343dd8d4bbafbd064f9bc2b39045826c212ec851813fcb47f44fa7b4220bb49420d30d8bdc73f2da8c018bfa08ea79c5697059fc42e9066e964f673df761e67a28d95c13c0f8af081118b56fd2e24787db207f5f7b1c57b7ff3f71", "5b89a2d4eac56d5acf8d95f56cfdcb392d87f71d45b1ed4fa00b973c62853dbbabad3c0e29b8dd111a21048f89127acf2f5d273082d5978a8eab796b053183edd57e0a8144cac11f9ed4b78e6dce93d9d0f499d40a48294f271725f573cd10c803c5afbd78c07004d4962253dc2b24624c98dc9d218f103bf03609d2d657701758317c0b8533572a4680258e828e54d03d2c3abdb351d1cf7b0bd52e3b55105e522c31b70ac0175ae801a8f1dc0941171fef5924037c2e646f4b9dee95bb136204d0bb1f40da8af4f9464523dec654e1731245c14065d286ce867e4a8aec3ec219e99fab7d1f85186e5bae24ee958bd92affa17d87eeccbeebaeb682dc102fa614f777e9c3d3c15f652f73924608f8efc9cf732f4bad2e329228aa1af1a34d27b4f70482d4ae3b55edf42c913b7e1381dd77cf0c18b01467d91d55bb3e0ef997c241b3566168be7c012339aa0d85251d683b00c10598b23a3e275d804f74bb20ff69cb01d374719e962bc5116b8b47d6b25770a04c2083ff126efd33e7acded42c49b32b8f93f0cd0e1b9ee8615ec795e9318e483ec1845354a79eff37b30df3b24c5c13648f1e1906ed63cb9e7a49d65243f24c3d77baa864cc5b26e9725deb1a4341608d4bc17253e76a3af22250f6ea378dc7a479524c1812b35231edabe6493b3ff9108daf59356f4b0bfca72dc2ce8aa0aa36563344ca4ea252ce520b62", "-39b588cfeda77664fadbdf5cb2794b349184c862337cef9aa6b73e612825dfead9b0d18f4c1f8c3cad65786ca36d7414357eed48127b1d8b1277316e7ac6749fa1bd7c968916cd08b7fd3f37722e7f807e0162583d214c77233461235057a9233d0115b5784de75c4cca74e06a20009f3cf45551399a3c2153ce8068fb0fccfa7f9c2b0705209581c79ef408bada1fec02888060482e60fc6dcf33db2489828a251db22673192275af274aad71885b5d96b115da15668884cffd3b7a3cd581b45dfc3ca727572beb419f789671cf96fbeabc8903e6c999673f8d124bd143d89585fe7f3469e9db21259ccb28d0d7a3abe1b9916b52ab15805023b6e634b77257aba50fbd1ce6b59b20838d8cf3a5628e1de35ca7e39303e4497fa462619992a86979ec8f8a013e40a6df585d26907503118cb722ddb5b0ae27a488cf0410a4a9ac32035129777f60030f70d93c96d579b368826b8c51eb9549a009c8998568cd604c9ff285f6ba17e1b7a661ba0978bf8027c0af88f7f355f69d7d301878674656b85d77ed3ec2a4fee56ce6f71bb4d42aa4f56b76b6096c76fa92d727c65a94d8eadad065ae0403231b40e982aae139eb3acc9d1568be0134b1b5ba17e0e43662135abf92aee64c80af64817964f6af02ea34ddf0fe1f21bcfca4bc3575c7f0b43de129664d5fd21ae525cf496150d5eb7be62ae7b12c56ad385fb1652cbf1", .None}, + {.Sub, "-14af623e8566ea4b108e9c4bcf6e2110c87669547f2fd4b3444943a4d6641b0a7535409746b687536df6e3f31517834a5a8aa3c8ebdf793202f1b5024ad44540efdba138f4db7a42f724cf788cb01f442e5cc86c5d25e3853732cc31ab2530030ea31b7fdfcd1db0db6fe360260a83527242e788869af16b0ce9cd1b5ab34a220ed62afa0376595fb1821dc1887d4d478506bdf12f4c898ceb12e429b6d1eff87b8c0bfbe9ecd6d0662f813595c242d30c184cdd763bffc47273cd327d09a975a9ae9bfd6eab8f8c3bae0f3505e29a131a18ef2b87cd107d39c45d6152b7325d8187a133d0bc09e45205999bdc2e8cff35267ae52d871b4cd99fd5d4029f88489dca5b96d5af7c623de57cb00be66ce5cd02c6098a3787bfbd4f70e5a182114be30802496956ef2907ca42ba9600d3d1ad96799dd986adb34d438778e12406814759acad884ae09eeb16e5fa47e0cad6cab91cae7a881918b54d699bd337f95e14f7c85a20eb8a3b21a6de591bac7734c5cf6e6eae7717f2791b787348cbb45fb21d6259e15f04b41ab44f4e53cd5952ef65ab8a0246bd9e2aab1e53f0abe6c5f980f94e6c8b859277e264c2447cc414e636adcf01e304fc548a0712ffa572fa2a7b9666f3bdf8d5296a8126458abfb2ab5040516b3898e51d06790d4e8a03b0e466be5a0876965f6eb359305093b1658b566925edf92f9534a254bafeb36800", "c484f5c742e55057f811b447aa55efb69dc9efb9c2af73626d29f55fe0877a97e745b4f5974d039af4185949647c4ef8c7b17ade43b78de5414a64ebddd471771cc471805b684dcfa2d94fc1b11dcec924b7b8116a7f2494e330e110b8fc424446dbf1cc09ef590c325715beef2bf806d6bcb14b45855d527a661620fee52383214cf7146868682070c4481a34054e490f5c0f7207cbd2793d925a7af443957941cc8303cb30c779a25fce9ab0bdd4d79c6ee9db5160dc05051c9767cfb50d256304b528bd3852dd526bf6c91769ab773221c284e3bed9006d76dd80773d41405f64ebbd5b380678be95cd271aaa0f2ad1cf27d581a5f6f95bcf135c3b3089ad15efd23bb7f7af5bbf57515bb680caef95c7d95c12d25c6b919a67e1bd89f8fc6df0f0c2a54d35a912470b493a9bcad1b613fb20d569ddb7e6ca05e9d60cf63e5fe6601e9148e82004fd379d4f95ec380b3734ee3834245caa13e40ef2ace235661410420ac98469e7261345b09da1ca0523bfa77aeef27d558e7f36a094bf098edf01374b7df564b059fc0cb9387d8f47b7f546d0d47145d9742bcf09837eb3f7c4f05d58f7042c363aa2924d9cda47c0f54fa95720881291a06b93659b6f91d845e877e82eb034297299ae1acbf52bda537c83d178f6b9be0f89aaf735dd4cb7a5f5609a6ecfad465f9a1a42ec8e420b644a58073c9d47d7f041769200cbad", "-d9345805c84c3aa308a0509379c410c76640590e41df4815b1733904b6eb95a25c7af58cde038aee620f3d3c7993d243223c1ea72f970717443c19ee28a8b6b80ca012b95043c81299fe1f3a3dcdee0d5314807dc7a5081a1a63ad4264217247557f0d4be9bc76bd0dc6f91f15367b5948ff98d3cc204ebd874fe33c59986da53023220e6bdec180224665dbbc829b909462cd6337185c0628a53ea4ab158571bd588effb51d9e4a088f4fd0468017aaa88736b8c79cdbc97790649a4cbeb69b0cb351262be3e2698e1a05fe1d4c458a4c3ab1b06b8be97da73b3ae1c9f4739de0ec8cf12bf4105d109b66c2f6d89c2a06f5a2baaf2d1246356ee9303dd011f5b3ba2dd28da72bbdfd3cce0bc26737d562ca9f659d09e42b4ee9d8c75f0c0a4850f8f30c0ea424d21a114e03d09c9ea363aa74beaef08b6b340d8d62b730fcbfa7400ccc1993c8bef0141d979776b70ed5f0519cb2bc3d755f614daac5e4db937b0bd89c2bb50ea508ccf19ecc4a18fecaf32e1629660a6fcea9f7a9e960736940fc63912cdcfa18cb0e4b5b0d05d6e2371da0d0d31b2ee4041f4a22fa2f6579f145e9abc58289beae1d075492199e5ca72bfd7859038d0ee62a72a66540e28c02c17ededbeca90952dd1ad46056b4de85a3bcd53cb18f9edb1602b845bfe0fd9c0cb3baa2e5660cb512f34a93803fa796bab37df535ccdd0c92963190b433ad", .None}, + {.Sub, "-48111c5891fe2ba159f91066f45079cc6f9dec9fff837710c8e7e77c24630ee004951fe7c8d8c7feb34ea64973227b3fc1db1593b56b78085d8c77f9ad754249d598efb73104bcb4c89e8e267d4e1c63c5d7852cb5315fb8c7cf1fb003043db74602ee39aa038ddc036535bc80a5251d589e133fce7b3a73fb5ea01b31752e4c0a324c3228cc088ff5e2d6b1a34fce1b0017ed7102289d82a8ad0d3683d18a042ffffe21af33fd9474853571bd1a2103a5f00c3f7f47912ddfb7b6f60d78a269ca8deadceaa5899d536d877887af7ca01013cd960e6d6a5513c5a6f9c3a2b54f01552ab023f3a1d208b9fe3d8c65bdeabfb1b6ddc8f77b09326f66519f4df5b6cb73f83b64bb84ab318048de6d0b2bc21f97c500a375e6441c970862a1483a263ded7a1dc45b59ad66d58f308486fb20224c705ffaa8f853240144e2d943a19e4f6071cbde28a27ef69eaee6d279f5dc2d02661c758c90ef855f29af019f3ec283c425d5d3da8aa94e3cc38f169f3da1c8782c20a303a2e0cc77cfeebf20359061a20bd7a11f553ebf2921f3fed0249a8f47e4d6e41c6736578d41d547766e0b0a2f3c5e3ff7cc77848c6badfb959f9c58c71a1be27f6af17cc426b5904abb89ba7d403ddcc3b851c3cd95f26ecc42e931a92e00ccbca077c7d8104c7c0e559f6152dec0b6f10f11d9e21c625d401579c1a6eabb4d5461463b02ae821e8a56a8", "7a9c83761b4af5b9ec445f988485531d1370c2322f16ce3445d4576f8a8577f94a5ae5b5f397cfcf421b0d290b061c19dc510eee85983f77aa8b8bc43640437a5032c9099d92a4fb390b6899fc0138e36e4647c165ff4589e39764ac020950b9793126185fc9eef116616877e642c039be439ad054ca7d6b4d05e348b2808521d1b0ae305c0849b55204f49b51c09a4b635c02770c8912b7bf2fb840abe8b56d1dc3d68da7db689602444b921dc85ddc79deae845fa5e7072d36b969505c39a06396a7c658b1079c0023dde4e8161ee3c1f81446e921d7d8197b453caa8dfe887073468d1b5d9caa7f09e48b306da4a4ff35ed4dd45114cda64bd8927c293bb002fd7fc8deaf4c8a267749049bdab77f23cc73102c9589a3c3a8ab73682a726620c11153b4b8abfadbfa3db09742fec472eea60707a97a3fc65f3ffa30d9fa5cc9c6cb1df003555e6c307837ff9ebf68b366e2a68d771e6c7d90f1cfcb6394c09ea5d5524ba7b6a192c52441241d468ae3ba83fca7174bcbd6caccf12653d90751bd05f5878b5bf84233e25de7d687de158ed6b72d73c402faa309530a50850c700d67f86d08424876544b4e3d1198d58e340c9fab145fa93d9b410ef9403bbe8181f6821c54df85ee3a2f4de71ce48c7e71d989ac5cf501e1a2425ae71de31e724e7c20d27b083f0371d4a036d1da904d0ed04ba2106c0594c05bc6a6fe5c0e", "-c2ad9fcead49215b463d6fff78d5cce9830eaed22e9a45450ebc3eebaee886d94ef0059dbc7097cdf569b3727e2897599e2c24823b03b780081803bde3b585c425cbb8c0ce9761b001a9f6c0794f5547341dccee1b30a542ab66845c050d8e70bf34145209cd7ccd19c69e3466e7e55716e1ae102345b7df48648363e3f5b36ddbe2fa6284d4524547e7cb4cf51068666373efe80eb1b03a67dcc5772fba3f714dc3d4af570f662a76c98103dae27ee01fcebac3deed78350cee705f5dd4dc0a2e2492a3435691395391655d6fc59b83d20be1dcf78f422d2d40ec366e30b3d771c8713d3f513e7c87c3e2c8bcd3628fbee7a42b9d488fd6d8bb3ee41b773166ce717804436ad13557f791e308e5e34143643810d00b6fe7e03fb3d60972ac8c5eae8b71791405a842cfcce11bc9f9e4953b166702527292ea6084dd0a1d9bfb19273ce9ce2bf7dd62cf271ed218b544e06948c30303af5c02f01b7ecd02d3832269fb281f82414ae101e7d03abc842cac32b01d4a1aeeaca3429cdfe5740e97b35f11cd28aab137015d0451e6a6ac78a4d6bb8e11902b3952304b2851c6f3177a3ca456ad000ebffae0b6fc38a73871e6fb26bb8d93ca9aba5f67c4898af7483bff36bff91897d7b207c54055e92775b01b078a79199579a97a52a7632c38bdd3a15ae1896c1750dd53f1029411f00a0eb5bb06ef64cd4bcfc30a48c588b2b6", .None}, + {.Sub, "-55afde63fae34f10b9b707d4c8bd9305f7646c9995fe9454f81aed22689ab65541c5ee6fd69f37b43bb14c043dcb940370e6625160e8e499d9be1996670f85d57db59892cd630a13970a4d93273b0d1dad7e8fbbdca3584cbdfd0c3b42de5ca3ca76af550d391770c4e1b185cc98eddfec8dd9c5b5da19ba2034e5cf1f029b953201004fe536481a17a99a96c2df5552455b90933a2c32e7db5d2108e132cbf457df968170d6aa2c6687150f1b6183f127c2396641baf0f26e4a7f76177b8e3a21ecf7dae2e865f8fe488fa82469b7af940e7f4f9d30cdc375f265948e00d13510e08d08044fe06789fd8951bae77b3a5d86d077fe4a3a74f3451f19875898f67bf2abac98557fa8097d597cd9e46f7aeee3ff7edc092c39f02ea3bb35e6bba37809852efd74220145610174fb8db28b304fb7425bd41827c2564a2f8a0a6906f4671abe8c51e7184d1c118039e7f6f07da1ccfb1b957badfe1e3961e591e752857079a953975fa7cad38e3bedbffbdfd155dcebb29c8cc9598df5f8f2341bce45d4d33f2fffe1d4f08c2d71a2eea5ea2b952ee6a75f2409e2f384a07216536684a53730edec375f19bcaa95cd1de87b0ce20bad53848d87d7368e1f53af52034d1c6deef8bd5339144b6aba3bde7dc6dc2c3899cd8e35975917aeda2b234b600cbd477d74110bd258d251c09a4edacfb0fc09619fa386ad960dfcbb7a80969a", "c20384a69e6519887872e13d48d24d4e18428b6dce4061a04a4f968cd8ead62d06b376214887bd48cd2cfd820009c3a619efc3fe6dd4f1b7124363344278dd94187248d4bcf99d8f686d3b693b6736e616a236fe88f15fca9996c3c2c6ddb638cdc871a047490eb468a7994a30e5c05ac5322fb1196001a16bc8bc0b7a9687a3482638db2e23fd20d76a8f04834801f1fa550b62d52a54e236d60cfdd7079bae4ab9419ab05ba43a565724ffd7429634233d8bd8b56aeb300698e49e66d390a5b8b238976806765ff7e6a2ed9978de6189f9a37ea2f506d625466f099d4d02954cf154771667f4f694d6febead4e427efe58c2f4a2f515c3360759d3a4c034ac82030243e959a15043010e59a5e8b82262aa9f5f88b98c6e6e5c62ab27beb16499b89ee82fde75196a8c0be4cdfbdaf4e3395874d491ad32dbb96bfeeee9317d04dcde5185a64fe05dc28762d8b416ca06760f1165f0c16a3aac5d46efa02aebc1f9f7ab696692d7ad9f823433addb630e3ffbf0d90e284f12ae2339e2144ad92ca60359b346f696fea0c1042ec78e73de908356c1bfd19d35d7ca66c9d91118107eab89648fa88d7aec44fc917a12570e7033feec57cbcf7edf6df5e18e88858b4508632e0ad36909698885df0fc82eb842aaebf02ffe84b4b3329a39deac18c1fdee395314eea1f9d026849db3938f36e9dd751f735a035de1db8813cf0e00", "-117b3630a994868993229e912118fe0540fa6f807643ef5f5426a83af41858c82487964911f26f4fd08de49863dd557a98ad6264fcebdd650ec017ccaa98863699627e1678a5ca7a2ff7788fc62a24403c420c6ba6594b8175793cffe09bc12dc983f20f5548226252d894acffd7eae3ab1c00976cf3a1b5b8bfda1da999923387a27392b135a453aef14299b462757443fb09bf60f5687ca12332e06b83a67a2a298d81c21324e66bcde3a0ef2a41a254affc53ef725dc2274e364147e4f1edfda9f30724aeedc58f62f3295bde296111e0822ce4025d4999b38d49e2b4dd3ca5dd1e17f1ab7d55e1ed488106835bdb95bdf936ca13f5038294c78ed2c18cda2fdf5adf081af20f84c7e67d67fcd279d518e9ede64c2b8a85e8b06665da56d0811c224172d52971aafed0d59c9898d8013890fb73065c55a9e0fb62e78f39a83f943f91011f836f8aade98e3129c0dba8417dc0c81863d1838ca96a8d532123e476a7154bcfdf27f78731070216dd742df95d8dc8baab5186c3c1932d44866a7727ad698e346d86bef2cee75d1b6345e0a25b23d691ef5a718cb4f073bef647e9523e2ba527bdfec94a8ef925e97fad21b523fac3fdc59575615fc15353dda88d861765226c826a21db4f3401aee45f5946ee385bdbe341c0dcae1746501f778cebb35b6c725fa7452a2784538026e5ee7e5e6d6bf16e0b0f3efd8438e4fa49a", .None}, + {.Sub, "19d91579fa54e15f95579b76f8b064de28fe85a1c8cd2e9812af1b96359e093191fdc512493fce2b5eb929dbe385979767702e09a83a60671f67c5c34029d66d7733d2ebb4defddd16a41f8ac1a1a3a87dd3bf62f19140ec20df93f5951d3abe64ea3956575d0c689e0c6fec2da453aa918dfd48a6ac7ce8d237f285e60987a6d8f887b962c31afd0d88abfcdf12593179993fb485a7935f2e2f3a517ae3c37e217392e90c8d5ce6dbec40b858db14f74531b57606e7d8af8bdc6120f474f74fa3371ad4d17aefda86e0e133d65ae708344ceb08a9f3f98c0c6129367757735d4917ef6679624f6d94de0a1ae6362d8136d8a58c673000b8e1b2258a0e49f78f215fd24e07b1584038c8925e858429a8bee206cc74eb79f550e45b75e46a9efecfc9c33e8072438fc07640681653cab1f8fc6dce1f1a2ee13570c2e18d65a1e827402974972862accc9babc65253837df384eb6b2cc78d3267affa20d3f62db916c16f458999ffd6a06d3129c566be9b5facc4daa442e4a24dad6932e02b01bc94c5ac11b3612cf10bc974d5a112473deb205a42d49139edbfffd50c7e8c2c726ec65cc6c9994b60f87c3782dd7d2e992549ec7c227a9646ab80516a1979b13f07f4d34b42c298140bf0a1585924a966cb095d0c97aecf3b5b107eee7f746711bac2b96629eb963adb0c0a014d49e31f8d9bffbbd5ec7f45a28834fbcab38fb4", "5ee36b90c7b5bb3d5d0f48d4f7f4adb1a1e67f369509b07cc0e6ab98423ab302a1d126d60b50740b5c93564287a267f1a1c705f5f4b7c91b6f62a2b52c0445028d580b29dd8831ee41c1ed547b2f5e924c61c433820d585786d0fe3a52bfde90da34d5bf930b0cc2daa26a13c2203d15261145d95d1ddfafb62ed073d1be8c256f5bdd9b1860ed1ac4bc19bf2889228ca5d156e972192bd65b5f56cdb1958587938764602d479d5390da0c042d328e963b605be0d917ec00b24006fd479ae3eba31b8311aea3158b54f35d6f1c0ef0af0c2f19798f937e7d1f82ec2292c798317e4c52291768f2415a837510e314d3dde2bc6381b815a33274cd231a5b7439ab9737f2aa7b8f5ff4347e8ecbe00d5a7965698c29ef8c7435e4b5da5a162e96ffe4902da39b6a671d208cd2e3038ee43bdcaf823516a071d04c89fa90f45ff0460b6756758280cbd32b3229d38a09fa44e50ff003838b7450b1df5780af9ccd2f3c4ce3493f4bc1e215dde52bcb8df13663572ba6b66cc86fb38593785262e889e0ca64831d4f2d876d547f5083143c2702474d987ed6138fb57c035aed03e5209502af085c7a14adb5271d59e12f119324447918b8500b39749ef0037aaeab71dc4f6009fc66eed928982fa942deb0444035da8eb02792807ef412e6f964edb926b0576eee42dc72f21c8b8429d5148b0880703f00a2099abf106c65caa98f85", "-450a5616cd60d9ddc7b7ad5dff4448d378e7f994cc3c81e4ae3790020c9ca9d10fd361c3c210a5dffdda2c66a41cd05a3a56d7ec4c7d68b44ffadcf1ebda6e951624383e28a934112b1dcdc9b98dbae9ce8e04d0907c176b65f16a44bda2a3d2754a9c693bae005a3c95fa27947be96a94834890b67162c6e3f6ddedebb5047e966355e1b59dd21db7336dc24976c95b2c381734ec7198772d301c7c36b1c2097213d17720ba406cb4edcb4bd457799ef62ea66ad23013512663a5dc5325ec9bffe4683cdd2825b0ce127c3b45b409a6d7e22e70e59f84f11321c2ec1b7024d4353462c29e06a2d3c5a56af5fcdea65cabe3bdf550e5a279931afd904d2a421c75d8205c73de07b3fbb5fc6d5a8930d0a687855d7aa0fa4093d17ee431c3f80114c66a651af8238d6016927aed3b1989e3b31466f78642ef171937af66fa4e5de4272d00eb5869265e967e0d37b676c6f18b049856c3e71e4a2f5d5fdba69f76258b7403b5b1c20b7570b4020627329b03aa66cc1229e3cd65d82a457237e6cd4c04b87169ee0096618b0a7ae201f4e91726f355aa44d9a1f57c2e4e6e77b8ae263c524192e0c94cbcaae5d703b1e2f9fefa8c9c95d574f2c91e9e996134fa32d45a8cbeb9a456c51ca78e50e9ba06dd752c7d821878c34523e393f879f086a76bed9e08c457463817108182dc8b316b7ae470832ab58a551c883769fff5ffd1", .None}, + {.Mul, "-71a24c24302d22152d0bdb15caa26ef6fdb4823351a0b84f17d19db69549c8257413d2cf0086f6a1a9b0fae4157d45b78d9f95daae2ec9b14f866d4e69f3cd48816f38b6129e4497949107c77ee856e20a3ef0d3c4bf955a31de5cb0295bf4d1d6bc9b2334e1cce37093dad2bf69cb81054f251f8966aa4cccf3b106a2e53b652b59e26bbc6aed1609fa24f9862e266c1d7e88b33c5772b113c1a551b2c9e2414d4abcfddb9fd31793c1eec2d7b0ce5aa85a2533eb2d14e8e973a1b6ea4804de4743bb64d6b90332c27177b2ec9da6f9b18d0ec21810c1c05fa53c3f41c5355e3f015a66dca9d3c0590fc9ace04439d17b9693e061a1cb677b008210dc2afc5102e33ec6b273ecfe590a8feeb3fc3d9eb196e5a95ee0e22341df7e08713b6a2999ec7af3516178fc1a8616b23c28e08ecc48db32206001163355edbdf33ed66fecede81d2abf0a63bba73f7411ed1d36b2bb0f9e2cbd9e6a78d9e317047c00a663ae7135363367d9533b216c64a2906f59d32add3bb8790b35049ff4d253f04d62f83583ad2929925f95fc0bcf2e7a7ab4269d1e675dae03c5cc5434ee910d6e2407110620481b610466d6ce90df38a2da38f2409c69b3a0edde55c53b672afbcf46b8cb138cb971e706e0f84d6bc15576402b222f379c147421f6b1ee649e6977e7459f5099861bf7f98d9ba52c83087494bf9823486a35b3eaf7e9a934d2e3", "b290bf0ed28fc15292d9ddcb5166ea558321de2d3f4183ef72470c5fa175738540bbfdc98586919030fc38781dbba20ccd023d01d51ec1a314838accbea3a340f380270451b68b875aa4fe68741736390badce051bfcb36b9065c3457591053223234501d368eb9c827f4086f2b02b0a31f1ac3de6b96d79203cb62f5f6771491997df33520e4ad5e2b9e496795cf3107ddfac1ae914a42104ead0afebe6fb215b19dcd3e2f70287240f4d9417767d9ef1bf52da99a610ed4325755678be2c5d6d79c364c7367ffb29728b34dda2707adf3ee8f63ad4fa605a727bc9bba19c1ed66d1afec7c729f4cb677637bf856da20a517e84409db6a1ab74e10a6e830d472e72c6705de0a76f1b50d71049ca095b518a1717029820c34fa493f6a07551b3c03cfb6a45781c39c050f75ea248a4a84cc468cd0760da9ed26def9792ff3e2cec2703bc60560797c72218688afadcea6190640f57368f6577d47cf162cce64b62a188adc6e5d867d8b6e67d629a81fc345a2a9aeab75e6ac863e954221d8009bd2c8ed0dd83171c656f30d12487e5567c86bdfac71f4eb2c7781c102160dbffa5a7efff6c5a36c16df3b282a20a5ed9e4aad31e3b672182ce72e74082ab11ad496b0e9c1c07ffe04dc62aec7778ed6a1a117f0c7d1902d37fc4647c34649f2e0953dcca5dd3a4f824a7ae8371c0c674c9f5fdd026c7e9e0804bc50398aaee60", "-4f43190aa90096f06e701e4c19e729bd4694c75e36c306a072200f2816fe88124e704332a1be57aef9494258c8b5ea03ec56be94c04b31047da2eef73b34da48d3a7a220cc734fd5fdea5577b4aebf1c075b6608c73e6529807f60e0246a1126b0621b9536abecb431a147061f8ee302f4f8ff4291e25a85c24c5d05fa529f3507b5eab740cec237211764a934fd8fb2e433dee6132bbec83e3585f18aa4de6e5466b7f306e032cccba2dda5e8e14b4897a15993d941a4798ad90ca3184fd77da5bdcbb866341762bcbf766430bb4478b72887e5157ab166074f6101a0ba1af73f7da92fe54f0768c87c2dd7539cb904870d2988eadb4395bef9d3d42a28b5e51eb9bb4ddc06d6d3164acb94300a3bcf32f86c5c8e51a68281af49df8e32cdbeb3075559c0b87e1efc131393e331dacfa6a6af7ebde2c4669129809afca421129c521754ddebab8d4d289af668a2ad76ac99684f237461b3e7d9c20bedb21373bdfa9dc5c86ae02c180ec3cd9cdd734f2a76c8f1f86a8b48dc807209cafbe6e797688666d8732e37ab1a710ff925b58efe6206d4cb44721932e6725ae91816b9fd3a323ac8838ddc044668390169071300fb8e8a2baee3e95145423eb4b36817b3d852c91940a79912c7303a99abb302ddf422eb0e88be7ae7906c28bf13aee69b13a4f44b91da062afbf16abb5534eb2aff29bd13566cb62751f805f9114af1de3f1a1daa2d899dbab438a53d50670a496d6350881224350008f5ed998210e52be50dca2250abc8d277866888e7a38e8204ff2144cd696df96fda27c0a92a881adc3810e501d994abf4ad36f20a7a8757da97610c3019c902455ceab2d9b4f5e144755f13b8af7638d89e6e394de8881908c68b33852f32ac88b8f7ba6f3f4ff6c87126b15ebd1cc647b52614df9e83b53519ea6abb067249576c9583be68fd9f0e7231a6356c75869218371a873c90e03c5a5b5d00626a905104450ebcae1ee839e13da1e47e2fa217b443a2eca76ffaf9fa91fa74552b0609288ea81193b09a34ba94be86b00654bd0f2e43e225ab8905c5889836d64c29b825e88ff5c36431eb8377e6cc6cc6429153f55c7d4267f52fc6a5b2f8037eae450d7d9d48d95d9229b581cd52cde501f14577b7a94afe1d50bcb396b8b55ad1c706974914e4b10be731007e929da041a4437c5b9e852c9057b51f47e3feab71ed8814811e57bb8138b3e4f409a3b281229d5fde3397fb43f425fd9cdae11b2c1ac2c44ce069bd0f430160ebe87a095e1b2c8c005f80bd4b7e737aec69bbc29e154bc54bc9b7ffd7e4bd088747596f021cb2fa337576ab1e09226106631e8324fdc276368bca582e1c2ea24202bbce7a3b2f39ce307fae0364b9eb2349f6e26ecd28cee7c8517cd42f561f51b970ce85e24e57b6e9099b19b921241d97932132a214e2629c1f20", .None}, + {.Mul, "90bf11f9aece73d6308128f58608298bf7410cd7ac7dd5b5103a98d72f98ee966f5f71564fd9ff8903b3b10f2b8bf41065660eefcc9f9048a464dd23fd18741355013031176124d55af78d78539f1af4784d7c9fcc257013e3664eebc7b6df26eed20c739c167a3baac483d8de7d7b5eaa895bc73c733b452616b1357c908f822492c80cee612688211037af9e86ff09672525d2f18191693e3a68a82e261239f7f1c8de674d4eb6ef72702f689e467e3d3070f66a952128e86d6731fdf1c66eabcd1627726d26ce58a99ecb0bbda1a9bb011eace8b14b471571249acc6ce129e97f2f4cf879a0eca215bf02ba14fd1d0d501bea37e227d39c66a7f01219506c542c2e1010b8f0dbd52f4534300d84c3a63635f4cdf9fbef33163f0dfbb845cb8762b783cf853055b5fc757e86106ed84f385c12a3b90169c6a76df4cb727f7663f3ef20decc7a625a950a80ecb82b2f1fff4e29bb686e549bdd5dd7c27d00c7255fef7dcdd3359e73314ec35a15f4623b8f564e6325e88aabd2404c7d52ccc5007bf37bfc7df8a9064e42858cb212ca1c611a7cc2a487f22ad6f7575dce3945c87ac78a260200efa17d4e13c7dd49e295f943f4ec37ec2912504bf755a6c4778a0c86e42d13a68b117f2d8818d4a0b30d45f846f7822043a43e80997ec7c13eef0bb85bc896490a9df09a1586c9a94eb7ae89ba135bb3aa156c1deaa353a84f", "ef06fb7681080089498754a257bcbd7df54254e38b0c89acf76511fe16b973a2943567c228973c8a9fe9af50c8a9d33c59cbf1ffd505f1cf1dc4235e5c5fa704c9bdee07f36c370cf0fe3759405411c212381ebe28cea98c1eaf6856c74f0c76a16b29c6405b01d4db914080f37265c9a5bee8527f6c7b06690e47780955944e5358028e8e401afee44aa8cf998a0994193282c044707d1eff4ed8c5011c5b1baef994a39e3db17cb2d6fdbbdf851c3a5294575410f2bd2f90b73d1da7327060566311d7546beb3c0b472fd51772d901e79149da51f53b0bda0be26350f6262f78ec89db5e7c471af89dfb763456efa4903ba87599c169b139d0bae9a5b113643c650af8bd317f1b40dcc7d229e75216ee5f1d37837bc8dccc27802159de3635263d5d83ae3747e324da561d3a91d9e625aa70b97e620998acfa09004d155df203c11c246490cf92e92e1ba3895f6c8319ed33970872e2e4042c1f1cd4f83e40072b91a3860df4cf4ed0249a190e1774c9944f977fead3b72b53c4d0de7a372d8343a5759e85b5d217edf57033783d5717d3f6f730e761ee2d976021c36e15750aaa1ebf179c4d9852ff0063478ba4fdb7c68b6a592d820167c2f12562d36ed0360e80cf22a7acd42b5f3b294de712e9cb874af93e6f3eb00f1cc27a9a99bdb858a4f54b2655add9305e0fcbc3232f13ef5bfd3ae513055220e4837742724a2e", "87265470ddb3bccbadc13cbb7021f7b23f6422b33796b07a44e3033634b3ba9aeabff34592de8e606d27f7bfc5101f51fecf0fecbb553fca811d4622f3d18e25959a700eabbc8e74bea026896192738dea3f5ba40e8525718e05ca2d17752ad55021c339d82318af10330183261443057650762aa81f2c29481dd9b1afdefdbd68a020773b1604292466560a253ba06c3749e16cc56ab9c20d66282a1820e8eff01bf4a84a243cf4f2bd78ccdd19a57318ef21d18654eda2931f7b3a615dab2ec03e1f11655f889ae88770c279cc93b3d9dd63f91f4acdbcfc6a1692b2374cc87787385f4b276c41d72788f287426cd554a13d6c60dae413cd878cc21e6ab68beaa6cfcf20df71f2e43a56d2b5727e94bbab183f6d2d5e88593dfca651ca141dd863f754bcbae177351f96a6dc17af07a802c551e1f787de3b69d07cb0ecbc2fedc6595b55b1fd51b8adfcd4cc9e4e2d9b413d67db3ce7ff32d087758d902b68ae2810768d4586cc0b91765dd6f2c4f6a4e2402bb2d66f8a1fe67082a5c47024d9e5a803a28c32d6275a07b1e670e0c887b424b7573c39778385d725b5715d22054fa1e4ad330cb93204da1db032af747f0522c7409c3634dae32fbd61d01c3650a8b69c952a271265afcf0db4c00f9244bd002e10194271ac15335eb03052aad4cabb90c56d7f796198fd6a47dcab21ccdcf3da7086d9d18c51f8701656b0fed6a7613b56ea68e6aeff480c919a6f12b7861dfd81fdb9e5aeb1a0e406b35c117cc84594aba3a4775fb81b4c84565684fa3e234c63b2291e39c96e6cc062e24d5a77b367b29b220607dc8d611dd00691f8ca08ce0cdb2482bc286280409134b52d363f12663d76c12e18316a1934287602df4489eb29a32d1fd1f7305caff914838cfa264e2048aaef08a1ab464271fb2e947e1f4ab7d285238d3b962bfb2e4efaf4eedfb18f208f4ee271df996d95b6fc8c601fc407bc523b57f32f2012fa0cb8263c90b45675d3d04fb696d109418edc09e63979425bc5b6731bd109ea4792f1a972db9f0049bd24069e57df9165d488501f3ecab5a66147e1cdc2b975f3ab5b3b8fc0ae39a5e7651774500d3fc4b89bea421e40505294f9362dfc6ac7330415a5ce9ab6d69b97236240d9c7100b11b660d06e33b989861423e445b26eaa1204001c548462f2af548be21fe14aca2c4334a1ddbd2f8c9c9f8703df92ce7d80b2a9534020323c96e2696a0a2fe16560ae51cbb49a4756a1679a41090446d942acdd46155f4a86caf2bdb7db6a57b81275279bfe44a6c99f6fb2fdb1cdcb1ce7ec48a7898d811be51382ce860995e759760e69627cec057f7980b41bbe711a402b2cb9e983c70e9306f687d5c37cc063b4d19d9b2c866b5c7941d9a5b83f4d1ad27d5bd35eb699c0714952c95adde8fe4eda45413594361c6c0b29bdd8dd1432", .None}, + {.Mul, "-7f646351591b740a6b868b7057e53216cc46b55a42794b8aed80b51b80336958a8338c13ec260314788debe0881a4707b085ea73df250421d0712d07dd05a0812744d41896e45708f6efd654cb08c3f11811167d785e35066a43baf6146f1f3d881f6f91680fc5c0bf0b9534c5bc5e9437f229d6b7d85cf1bf369e139a0553513de52a1b460b24f03674785f119a7cf369e753d3581f5721e07d881a752dc63b77338a19c80401885e13a7e70604e10ba64c68ddeb3749b99b1cee7ad00b33b094850cf7ce8a11682f88163772b0b823c974331d57f60b52f3670f156644a940f1031c153c65f27013a4a1e3ad8cd3062889fad57deb41009c9e92320c68c78e58d7e55dad8fd22842d3e51f7acf26fc56d69315651df772d2b182c2971bd49d00f30f11dda63ee3c69ae42d2474cb6d1aecae3961ebd8af4debc3377bbbfdb02d355324cc12ad29e8535f01f470daf35da8e584399da300840228a48df970f87f01bbc538dad38029114f39934bfa7df7929768b66e3b16baf6b27b87cbc59cc9f23acde136af80756db49d90c1872eed38c6e36b5e7ab71234011459985c1571592054a1e99a46aa7e63c4b02db08ddca981762d9e342f78c89614f0a01d8d5978d120076cb473ede6bd7c23feb2441d8b7af79b045d3bede12c9ecbb1a4e719ae7034dbccdd59743025a69125ea1d745726bba1df1955954eb7c6295384a5", "659669a3b8ef5149fb2995e5e1ed8a9ca9b82a3351a4e5d01c980019d0aa964e612006625c805a399d905e85f689099a2c91089f9c986f10661e03b19c3ba5914ccfb395dde72aebd3ad20ee3f89da734b5d2057e9e0b555d0a70fc237f3f391398a84f55e95ef197b7552f0d0f406d7d8a30a78ed610ecc70856c0471c052678f8f31599587fba5726f89df62759cebd3dcff69da6173a3662d26582234c114c6603c3f9665f0e2593ccf86bde5e8cd39265666b92f5a2fe3710355bff8fabf224590e172eadfd5a8a0c9cd72d9cd611b116c0208cc1d68aa01b1ec9b150918c52c752db0f701dcbc564c38a398d5a50e087da9e2bfee009fcc3b8f931180ea20f73edee30ee500ff88199a5668907f23800e2dfde6d4b5dcbc8a1684e6c6297bb996542fa4ecb44e0435f6367d65d36192ba87cc003ef86658eab5065907fb6cea5d2e878bf8e5b6031158ccaf6b4c70198cc58ccb749a4d4a58882716c79bb8d242e23f48e22585175f28214a77c97aaacf338c4ac8e2bdd524e0b169dfa527399dabfcfc37121a4c4ca8bf020ff62d22ff191c7455e15eae5045374aa14696c2dd9eb8d8a8b0901d159cf354ca38f2bd09c4ab5fd609ebd02753309b66ab60de5dfb80d3c32f9fd94a3ce9b034059afc678af7691496ab39f5e4168018c725e8be22e55b62abab2fedffef45f4660e27353c78164795ea9783a57fcf1b2d", "-328d7492ef80e3c4dea1590f155914787af5da006d297d42805bc89dd483f351479a677230185cbc045867e3440538ff42aa2c29c3522cdf43454341f1230e18087abc0d95c7a8ea3957dd5f9561d9d28754ad9d3851c2e792b779bb240cf387169d8ae45b8d8fa3a0a3b07bd35c9462b272982b0d9ebb00b77608410ba8339d5b32b89b4edf118b7793aba80efe18b0337ce1ece09a82d35c51fb724f4ee332adcf07e6745eb5846386d0a5a35387f7c2fc510968bb48e849088d980af7374fac28116b60aaf167875cc3ca753b6fba6bf6729f8a1c615bee71170eaefdd86613624b2fe93379a96445efc225255dda1272936afbed4acb5820b34d8208b6d368bf25386a0be4087fc40de5e4fad6407002c977a5fd8cf82bf62fc514da7afefd7357349d4a264a09049e0674446f386ed86f94c5789d143c66d1d65ab9b316cf252e908c4426e14f1506c737bf5600554366f6a133a89c9d435c824c43d93a3aad6f2ead84b304bd1cd728848ca51cbbcb4abd42f3d61a27250ff0df9192a2e5a1e8573738a9c66fd319ba2d59a0763ce0fe3ac703b7c9d967ab8b67ccbc2ee247a7fb99b6e17d13b23e2c7e05980f3cf36e475fb91f90289062d70861501f1aae05c0a400cb0dd3e23ac84978d8390824f4e9aa90baee47516b56527b3bf14e4070bfba27be659bdbdc99f0acf412f64f545c5008c631efc076eff17143b5b624bd9cec7f4af6bcb0ff4eb6862e0cc083b98222e99a5431adf6813043f3d54248e6ae13fa80e23fa2c67eb6f493c8e177faa2039c5c93b9abeb5fc0bd36297a25ff9bf706d012458d71028c11edc193d4ca5b52c9837e5ed69ab838656cdce880c9113e533af6eb270c7f551b59f3b04ef5af2429b9f8e04911ba271cca352570e28989dcc0d0f56258346829f48f0cd380c3aa437b35b21e0e5fb44978337bae745f699d08d4bd4af456de6748e943434d13d8873ac4ef269b775d8bcce11441c841ccccc6ca45d39d33d2bdd4189aaf41a3f730d6c7b06ae5227b4068067689f5d94be3bbca7ea2a5455864da8e48f7a65e407d3eefd0705f71316d06a49361a5f7237b8552e2b9dee5c4916a91a1a7ff863e6ac59570161a1b0ff03054a8394c6b0473eb9ffc2eaddb30030aefb4bf02c110323b43aae077718474b3d397475a364cb8c917506427c2cd8bc1f896de9f85fc9c9c8cea175b59ba7177574c2b971cdce2f0f18e331e4ab4a3dbade5ff13d9a35b8233519e50506bf9487c120a4077cf88344d64a92c9574dd5a52a0f9293c0948d6382fea2ba6918fa151bc484b3cbe5ff2eedc49477d884bd604c4b4475784bd1ab58df6bac7fcbcc51d3cf0bdaf5615c385b3bce6765c23cb9a62fb589be0fe0fd685c834af29587e38bf743166e0be117d7c1679ecbcdb3d8055802dd1ee2ccb05e2fbfae02f16b801", .None}, + {.Mul, "cfc22b13b75a7c2acd3f7f8d92584ff0bf8312af001950fdc71dad2d83c70fe9a92165104bd6216e97d1fa465922a943eea24c4e577341c85b0dc366c7ce60e1ce0879e59d53cd96a51d2fe9b2cc93b81d09018e2eb0550c7a378547242ffb647136d46d751f67ecf9bb5fa86437993ed36e4cfe8b434942ebe7bf3acc5bdd0e004f22f8aac920b0d7e6446233c0ae415ade4785aa48588c99b97adf33e26e2d89a990f107d572c5848320fc43e47473ea86dca0fca41497f34ce18ce72b88642d755bb0bc89af7870d15b5d4870d5f15481779edf04436aa430eed5d720b142c176bfc506fa13dca574932a716f0f2d041c8a44156099f0275366cc9d3e8dcdd34886be990ac70f8651f604472254be2d40f0de8881256c6411312857761759522f924655db03914f0eb10d0155cc099173e3a9f0e8a739baad02fcee7e63be082a11c0faa96fba64fef60f96395c30ba0139ba793e4ff65a4c79ec2bf812491f3f1cbbee55bb90ce69ae12c2b0d1812747b0019c0502ab80267e2bebcecdc60b14467966bc85f1ce7cd30b5c3ce87b7550a163e69a8820b9600f539cd14047fdeffcc35644d737dce1aeb149df8c7ab91073d3c4dddbb033c2730d63217f4d50ece1535e3274e4f43f109743e49494f293c5f7399d124d5358cba7eabfbbb1ea48d26578d8cbae0f089cef11d84cf53c049aa7e85e8bd05165cf381f554a21", "cf72b7374403c2037dd1a63da4b98d6a3fec881244aa20d1cf5aec179691136459c62eae68424ad46c2e48132bf0cc4368fc0c29da28aa78d6c57f6664dbf84df33b2d682bdca026d2be8a077c45558abbfa29c6a146871a4a5d5f57a8de33ccbea6f056dfd5d38186b073e2cc0a2fff404774e3b68ef713bde9344ed59838b7373bc5a04493d747034a65f67f15d079f19405b5049c7218a8623c627c6cec30fa739cd958c89d208c6f98205e61b72cc1f425f5a2ac0198b427dff14ec7160df556f43d0e2d846af757e57b20150bf7fbd4bb31bad08ac8be7703cb52fbe49f48476dfc3057b3746d7bb7fb5d1a22036e79ba94b3679591377cfc3718c16b7f9c21c45c6828a4615c22a90d83d25ffc27d362d07124413a375ee4f79c341057ca817de26a95824e14138f54d1919e81522fdcf62da0c52a80d606271009a4259da273155483549098ba4585993456dea8a215371ab93ae9e0defc2c61096ef05722e24478c079aa0eeb7fefd1eda32d13c9ecd604ddb8159a49b6beec31e0fda51de94a91b1fe8d40b69441912008b9b8328838233d8853c1a88a9c08f9e0b05c59985f9c128d5d29639ee75be055540315b6b1241220e62bb4921b25784cf67bd64d2daf76b24de9348d76363c6877d5bfac4913997bd4de48cd46d1d24def6c21f0fe75030ba544d01ceb8de64501b9bd79b0a1a515529d2d964a93745984", "a85b19fcc6beca2bb22f990508e23e6f07114f74fb8b4acbcbf132bbabb030f110a671710213dbd730dca3ee6e2d0bc23ee20042b1e86caede1ebc7cbe6db35cff3152e7208188e479db28ea0d9fddaf14f02d5e8313e857261414f4df887c35af775ed6358757dd9574c2ca9baa44040b3fb8d4fa59a6b8ee9a666b011e3125ea13a5f14830a8a294ba5d1723983bdfa3c9e5c0ff26b12f90489acd6b61d7f9c97b52c767b7bda8623284e0d9312c3b74119377f6a73ea2f10bad878552d0c288dc9d5aa8b2f8009e4c09f4101b203b4bf822625ef6a1d423377567e67994eda8c90bba3a5af74608b21eb78a50c6dee76e2910bfd69ba02d174cbaa3c18b6137b841e7f8dfb20e8f3e8530b4b006cd9e61515ea31c0b9e771059072be65d2b3cec2c2907828a3ca371455e085c61f77d12bb8434714b5093dbcf465e42310dd1a19d41f3392920533820cdde8b447ea06ba2a376432351157f4947fd3e24b2e1bcd1e372e75da6732b6956dcdb1707a2e70b1fbb8b340864c4715f59e8b0e062432d5b4e5173e51c60baec54d2c5d36929b874b36f86fc9ae89e7623f24c02b5ba4341a4d43fc9828a3a45525d70669236848fea8d7c8f49f139eb94fecd59bf74e6021dfe472af522a7bc2438d4b991d3a21fcc8617e88b5634c397cd1118ad3f0dd4e9c01f52c9107122139b60de948707c5e186afd9f3ca87069ea8b885ad8f4399381868942a55acc395faa8352280b96e8814f6f1c734e3f0483e3994dd909b7bd34b554a8cf38c4f7fe6e9063b89cda2080aba16c0d67ed7243362f5e6d8ec7cb3db00437cdd80eb5e54906cd6e99a1762785b3f7aa341ad854e5a79e918f1a4a4c3b71934ebf8c0366136f69a7d50138ab2322ab2b3b179f32c5a29b1d66fc1e22507e162b899eca9d106fc48e178f83bbca4a99a1bbd14136fd3d60c3cba3021aa09347c002d7c724af9909ad59dd199e314d42e54b2451438820c620347692bd72847e24ee0ec3ef7fcabf426bf944913b5936823276263c4235ee2624329065b8cfe19fb775288e9cd59b6aefcf27c71c65223d112074ac17181b3205f3d645f5959325e1e1ca5df5705104b9b416e2bd13985433002e594630172a3c306b351a81ac4dd70ab6b193725dd0cc4459195c93e27971d30a126118649ba5475778507ecf710a352eb8aa7ac57f4d2b400219ed6d42b3803df460e7506ea693628b8f70c15e78d892f34d87588b820c8c53e777b2c551c2f6ce548c3416f8c67c78c624c11b9aebdc7cf03a3dff8df7e8d613380a1e4eaa7bcec9bbd2f176abc4e50597829a102a0715e2fda190db2d26e6782832c94b275683e9c73a5c4beeefc85042d708c14f72aa20c753b4499ac5664aab40b701b3928681b40b9b87ca972b30224f97a261e1f0800aaa6f84c344016e870c9d94b9558b3b204", .None}, + {.Mul, "8dac17295e1eb87327e0a2913945338806c87d1edae6e23b3bac9c1544ca992bb2d59b09f80733c58a45aa9273260739c70266d615127ced10886eb4059632f89b2689ed31c64e3678ce7422671f3e87d7f551a6ad23c20182d98119ffb8bb7367c05b85de990347c3d48d54e1b26a1c0069e04b691f605d66f3703b38ea02958232a59f7fb299e04996211bee5fc63dce3da1e671fe7afeecd611063832267bd4221a52b2a595bdc4da90a63a861fe798e907ad6cac44423465553bbcd15e4e8f779d26dbc6b1c961e692f93f2a0cf283e2c8db60c6a6fdd28671a63880545e364540a1a9c3f06f7a26b324e0a9b51e85fb8c9fc832d85bce08e3de2152e0eb87f8c73a7ad069556d6952ef32b94d2128cab72bdab944ca4c78844aad535dbc8fa0730e2dd95fb243d3f9d6e20e1f9e1ba0187770705968b37ddfe6167c080f30773e4e0cb2daf0486924898fe9152343e747092a32531b92e141e6cdf4983f037b3077323fdf110b6efe9003387362b1f3dd6b9d76f6f72f5fb4be82b2840267e9123f13b749c6896936a1944ab63ea825d491f8740624df46aca705c1a2ba325cafe4336057d7afdd460fca049e60595e4723d44512984d86b6b5ffb18ad3ed3201713c54a02110960917e2472892b0efe2a4fc9cede65a39ba2b15847c0b46f3236cea5db1314ea5226d62c21c9e653dd028306d534e204a5e3f997eae81", "21cabbd3a5d2eedc7878ec5824e18e96a7016c00c87def111b6d56d3fa602dd89c62de0aa55ffa98b3bba44291076bf745a78daadb260dbbc5102dacc6251793cf825d62391fbbc24772bfe1a3ff01bd183f5d8e685a22bad74ecc67f0a43739f8957ac1132b1409d887a5c28ef15cd42b755035c4992c30b9f881f83a3ac0efac62a8447ede3d750625f26842ee2c172f22c3de59c7a2e758c71eae5ff4a6ff3fde31f2b1aabbba56a55328e33c0cba992555a370d96e9e5cc386a637e1a3fe7a095752fd39ce9f872b3e490e1987ba6cabbe2e147927a85c7ccd4c1833ac8fa67b2e7e34b18ea24b0ed3ff4260f07b34e47887149fd98bf08049cf3e213f366e7d90c1cb16e8e8e517640fde93c688b8d5a7e0997716aec774d6db51ef9204fa33599dd40b553493a03fdc194cf448d5d2a063879fe9105d4bee149b7d598d782870457c1ca7ab562f76dc83ce2b44bdc1c75e0d36cb040983eb739308fc130fc7e5d3eb29886ca5dedcf8f2181743f7d336df2caa054515a93c2053ac8089eaa432eb0f1a2d787a2fe8ced2ad6ead0471fcb0ce821fc9914640cd40fd59e057aa26bda32736e99beeb2be22737d2d943049f4be75a3e81138376ca4011eb0e1dc622015ed2661f63bad252a6f81f8d9e7eb4d8347cb99cb2259e3bc6aa0c74fca06036d13c79aefb2f3ea14c27ea1b148acefba57522d7d77289785b964d5", "12b360b8714d2f2610c086b49958e42122147f34ebf651c332f6dbc5c68e4e4d32e0f484262e0362cb8a2e36f96fd5ec697a3f1cde924cab25094ec9dcb8a950d65a655545602a1ce5b8097e9ccaf5aae70dc49e7d5dd457a8bbdd50ffa64c5f06b042354bacdc320f6dfccee108e0b88690f735de45468d1f991cca22998d4ba2a91de4f18ec59d769e79c3a2a03a3f660186702566c95d95160c5d80004bc6359e89d08c454e7ac69edc4ca704e089b803798e6701db82631ffdd66d84a9c74b65c9b77d76a0b4bf9cad0a5cc866eef7fc480683e8b34f05d63350a08b776710d661174ed586fde9f473244e3d390fc441f631f1de3a0ee9dd3956134d770d2c068e0c332013cb3dd0b22ec84480edd15766f4fe6541a767552111e26049c24b8210425d7318e6337dd401b7f160e2c2974ad7e10c4d64e758fb60151b0f356d86eacd0f8a6a27495a69cd721d2320d96ad9c9b68f569f1646f2009c675914aa81d0ea2ac38ee4436d1f5a5d3e387d67cbb3f9b747b8d3aa7be65e6ce02196e43bde67919e5a2385f6685c13f12aa2f2a6f91fb916cec54d483c5f3c4e6abba72dc2bedb5cbd3b9539670dd7c15c0615b9a55e5b6651340178add292c348efa6e80777e4272645595eba61f5152910b782501783735e3eab4c358270a2c5f014a5ac94cbbe424831d2a52a15c2eec9ed7d0a7b0f2856da4174aa97f571a2f98deb2dfb70a9a224aa2ce0fdfc71d52fc5054502e75cc624b07ff011643c4448cd987ab9160947665810a3aaabfff74ad65ab3b1b9918ca5e826f8014cd2886a169d05b479388f7b7621afbe8ef38c358658db44b59372e152b054eea34bc0203c0d51eb57b59f197b4e9340d229952b22d687b38a923ef0257c2589000f127d935e67950745b04847d074c9a84214286918e2ee095065364efe630cc2960e1daacea53bed57d737343a046665a361c339715162778b3d0f43d5ab8a75988656fee4dc825a0a9a39d7c546b5b58fadbfc2081dd1e39836f5aa51ee1bf2e0f59d7d5e1bc24f7eae656f1310235037215ecdc31b95b078d47095b4fd0ac52eab21d9df70d0972e8869bf7dcf48511f023ded576d96bc50bdd3a5289db60f138dccc6c45e20d716cf5f3d3e66b7c6fd366dece48544c042ea9279149438d1b77fc7c841825ee8f78456fd7f18d9dd1f076c7b2c49dc0d5a41e0ed91be88bdf284dc9b0e2dada9fa1e6d167dbd5d7858a5ddcf27396e042335b6244bfc4ea7e1e0a9017610a43bc0559c075e3f3caf9072ed86228aa3b10a1e88b32aad4f11e2e387bb27943400fd57f50f4bcf382940d70f7565d52f20903d12408b078c24abd54c0d5e3785579fbef3c4c95c94b85db75ff53fde27b0e60f1364a08d8dec2fba360d5629b9cc6aec3a256e546b210f4ea9a0b915f9e8d88897815a162c52ca9555", .None}, + {.Mul, "9d566b3b798c2caa685f305481c3075ae8743bf3848915b33428b5a86f726e7a38e829795a6f91ff11ecc46157d76eb0c18ea8c6f1ea19287c3301b2ae291df38b1403e725301876641730ebdbab98089077960a8f43040caaae8cab2f99873f0c9dcde3da63e4c035aed240feb7065955f1e2bd2a8640d0f063e58fe57a7d1dca1dc4a73f5d8c6933bde54affa5dbf44956df90650315c623c7d06a8d40caa1ef212c0627b442e1fcb9f675e79421c2099475492bc95114fdc80512b6e6c10b34ffae2aad37b048e7efd4d14df12439a6d0e41b4fd8e5d5added367c6ed3759552541b5aef5fb42d9486d07b6a5910894b3d4aae436bf708c727b192780c67ff42f2b01f4af97e918603af6e676a67f03af10ec9b6c1f309b89545d1c06e3d1bf5c080e2eb400b053b0a901944aedd792c4c013644b6d724cdd57a9d0986070453e2a412ac74be1696e10d75b5df3386c4044885402b6cccdcedb9211bcb576f13a565a752b3d7196242aef4fa1c664b2193bc9f381ca7b8b07d6c560b00810810d467f4612ef49fdb31186566736bf6ce5be1656e3453f9c000c96d4ed4bc4c4c41bc729ef4b2ac71b1425dba31fbdd325ce580bdbfe912ff731f27d65281042de33b7c60dd74bb3daba0a03b2e89757bcaf1bed9c7cea8fd72f86b1de0400d866c74b22c528e16f04eb486a60f4a6fdee212f361195abbdfe96646fc08abc", "6f1a9ade3c8bbd57087c80d76ab632c6c08ed47a595af1d2a4484e3cbe6365ba5e2c5609fbc14580cf8e5cd11e13fd963f6309827b0f42855d58e48f4c59d9cc4e1cc332383576b1b5b8c708e48f13db4d92f25836ac6353575653a06f767e3b8977099fb0d240c351d2d73fa9a5c57fa86925129b54a249b6b2bc3bfe0c7aaf0648e72ee9c024a85c70176303287d869099a44cd446c6b5f5530331fd4b4e76d055dfe393f0ddf9d42f0fe74705e80e3c8157386c16d0a021e2739728ca2fdad2c9836ef7fa5731ead171f992aa8479e6e9a9b2b1de4685fca197fbad3f157dab6536b3e38015dc8b5f6ff0778bb72941ffa5e1f2f45685d4adc8317c73a507386c5e3a5f1c8c90aa576f12f345316539830a7f883270ce5f3c4b2fbe510111fee9fd2dc638c1d29726a92a93c58e01ddb35e30c6ad355c2432b821a04adc015965feea0c8d89684d73d7a29e06880b1edc185b68ecbdd040f042ece2e7f0dfe27b61ebf855651c17168f321ead2084c276e746947fdc1a05077ea1a6ef41c92c2c40418ccc42817e60dd08ee54b5d584b6ad6327b6e5202aa2172422be6dd2738c21391cab988c9b1e7d5b7429b00b28f44c35dc2bb484004cd39724bc8fc04d3f21337aa6b78b0b1462d38964f413ffc85b3090019a2ce10103f927894021c27f7d2f26deddaf6fc5ef8e2121f6046f7d2607104db19a1ad43b9bc15a2605", "4448d274406707b89b858a1bb6744561d480e75d6a4488de16007ac1d8575508e0f91ef44fecd2d92239882dd846d609f9ef791785a06b192a31b4807477bfc1dbe87ca5c8e721a59e3cbf907453f850e0cdd73f67d67b5f83f20932df1b1f86861269fb2e3639ba754c6d0a1569fc1f8e5a52cf5a8f880e73b8c300d8b210e34003c6bd9ddbc700122bd5aa30151713cff241d769884aff844cd34678b52075f61af29ad037f221c2b8a7434acb41c6c2b4682a1745c54e0eafeff28a990d8eac4d368c4345ec5d448ee074326dcb8db74595afc5f39b8028bd86d78a7d6868322320075b1940dab6d020f71543bc14bcd0785f5260ea14ce8570d891625366b9e95751981a220aa38a3c07d5c2cb3d6306fc98f640cfc49909ded4f48d9a0ed465efe516036e22c71ed287c53203f9a6f5f347fff7633864264c602a2e3994d02313f42ff7a0a54b6d84940b3ff34c5f98aa49a97f150b62b09f31bea03a02bc671c2f2b909a29b9beb37564988258656610ae00f591ef4c11634f9ae9cae9b32c0496ae9e3113368b7e92483f05a48409dae3742ba216fb1b12798648bb7e922d7b5f392251db944de5b1052c25c3b534e028908baaed92d851917e13172636334bcc63b75601e53bbd34405237b3c4e179b18b03ab3c26a35d30697f78e8f3b430c4e73d3b839f3e7cca797f837ea98e83eb2d9dc62cb682c2e023ce08e1afdbbd049de656b01e585a889a673f595d3123eeeb1653c484f82845bf36e9a3a57b38a1d0837e67e7c3f70d7b88729cbbf96f1d7a44cb55e9357ca6429e3f4266481b2556ad4736cb673c52f25ee3c5c0ea561be94fbab0461619b1701f0d962f04567bc76abdd61ef27c3e192e326187d733904e04083a890410d897ead55282b08e1cf650003ef5e46b6db9585a69cc9a2feeed54c1fb85df280020806bb0becac88857a1401400f409b08368ab34a769efcc0157d837247ccfb98cd8546885777c6a2ac456442b4094a9d1d0d61fd58521dd9ff45ef351c7cda28617d4a3813dc8d71ee1c05087252ba3d3a5d1e42cc591b1047c136bed145c43dc6f4031c17d5afe1640deb69cea88d731480a2bd290511482880b255d9697d93cd65f90cbaed0eb42fb6e5d03d2ea278001871911e48a4e95830637329225672d0dd4a034aa4f8bb6a619675ed4ae491bbf7e8d9b689ec4c7b7040d548c0b63fb705b4fa05ebfefa68e24732002a8a8fc000c23fc00130e357ab0d232d096a4ec3d1130e912ef23aa07f87b3589484c54c0c8a4653fd97069e0b0dfa1558826dd23244d1ab061515f32f1434c1ec101b195d3393e6a62a337ea5f4a2b6f0e8db2350ecdf1eb66ef88c0378a8af5ce83ceb9694ff9aebc3339b78513e7859da15c52574d1a3fc78730df685b756631b991b4a297779494410bcce4a41d189ea945729dac", .None}, + {.Mul, "-575f67631704556dcd47d0c18feba923fe35e3a7d236ca82030929dab87949d1452ac382243b35822813c7d0cd45fea485342f7c3fd17645b5d3b68817d4093db8e38867d606011ccdb81dd2f3f75cae7f28e7e2ce4362eb23f4d4780d12de7e6622b788e16ef3f87b1cb1070ae0161100b2316f06b7fd576d9023a86483ed17aec0fbf0cfd3b2dac673a818e1b15c422e4242902e1606b662b47e99f4ac278b45547f0887e16e988f9b6f2f9d136b43cbdd33ac56e59775ac78d55a456e7edb1979fd3f2ce1aab31ed08392e24165de428d3f24c6f5669b4ed9816909cc135e727ec819c8dca942e31d47207f7b24690eea20a694a4773ac0ec3806217c5c44e8cfc0fcec5c0f0a4199fcd551d4939d07f86e75e4221b3f1abedaa07c1e89092ab70b8f4e8c82b13f019312be48d256d3a2744f28a1307fd124ddce5afbeb7bcf15c49eeb3afcb8ac7dd3c110de27d4136d45cf1011aa0386292b944bfd63565e918dde0f017facb180f8d0f544022f36220c1f0fded1abb50a892b121497813e1c735903fa472958c87df2b181eb49fdae50e80d5f7108aa1ba9560d4e87c7b46d5c3555918dacfbb35ae94a2f87d6976ac68bb0bc351d784b38fa7b0df1cb741ac09af32b2f929974af0b0a95b8aecb5d5544ac9425906b42f19c647b421a02d7663baada1669bb20756be2ded1efaa9af6cce84da69e9910712f83c0e2a0", "5abb55546c09919fa2db9fec4b2ee2367d3e3e450367cd9056cdd35d35df15335f3f78c55ba65d77bf399150548503c5f9e2306342c8d758f26f1cb79ea25476e23d5e94df1f565f6d5df12dc5b76d3a42036576331a8b054db14ed0b9759c24afba67aa75035c0c5989b4977c1c2b45794bc5577b480df64128e4da2946010b02f675cb564d1cda8d89ea4caf48d5a10d7caf099153e600ceaf4a800faf6fbf976f95de9038c63caf2202a06fcbc06bbc5db21aff1b6680fada15a1f28f9da63934e8a8f739b7999a058f336fea391cb3da2545cca98af7a932f9a6e1fc0adad3b00322d06a92ac6fa0c983362e74ccdf769a8a060e5a26b61a72acb885e2a53341e0bd8262974d14faddae18e91b4cf7857c3710fd636fdd30556d8f7354d10d03cb4665f733d37cf9f868f686259e59fbd82f3ac0f2cc194ff64b03dc5888fb4f72adab6dd64b5a00d7f354c1439411a61c0b9b0b9f4afb48b12ffb729402515a4bd6a2e58bb2318198b9925f83c3048bfa505742361de371242a6a6d1cfba732dbf81eda0752f4ab01444f5434807291fb534e799a08e41a09a837830109b469643ae8627b8cb075b8c0fde3defefc0ac06f9d98a83e95eac679f76aff40bbfbfb7620c5a7b8f9f071fbb0f5b256052679a82178b78b5e09aa1ef683628d3167ad1f3d8d371d013b27f72f0d63a7d6af5d96e4fc1eddf9df2258aaf39354", "-1ef77a28d8faad06f4c0fe6ede90c004c118631fcd523f126d813191939627c38652b1d7a4513c5ee1d9553cadaa74140b0091f3a04bc600e6a39a7f2dd9f0c533021e6f533f141deeb0110f245bdfc9dbfd7c567ea4c28379ee70d09231175017f59073e038bc74e55bb4f79909b214c104bb539870086b9245c4dabed797c828721ad3ff2f3aede4abbd64afc6755f78a699320f066bc74454d88a4724756353fa8fc50d64fc0999663bd7de04c21d2698dc91964e2236c13d852a51bea0a2b588e9e86c2666e87a84152cd08c4aaf7f8be1321c8c67eca7adec70581e35dd30a63ee52904ef76595a257c778b81e744b5b7ca4cfe0f1c72dd11a82d02764ce2a318a3027cf656861d544de9bf8d3d39c72ccb795d7b6b4712fcf799e0fe35106505491c11e8f1af8f16193c462592d87c3deaec42d233e043160d32f22123cdfeac5112bfdc49d72281268412eacf40d9af684c129599109c1b5c3c8c71a66d9c2469342636000d7daaf9297762db776e718d6fb8d64396bcff40eaed749ff5acb7bfa209c423cb87e86c8a1eb8306b40b4e943684c4c0188d277702e423601dc61d9af97b71e3242a7cbb08dc41a35f58cb1ad82f39bf831c69707c549159c29650afb58751b4214e7779666ef0a0a3bb40e098538de7787ba7ca55eadc87c840f204180a2af5721c0c3f841ee13698be10c082ca69d84489aec28eaa673330a4907e22679f4dafc215d9ac283c13316aa5b757178fc07724a3ceb825673e9d5fabcb35c32ab74dd9ddbc4558a94a7b439556870ecbf94f26b342ab804d1c306c726d67da5c53fc452f1c09b6ecd2674eb800928e4aaee12d86b5be934ec16322e3c852f8199f9e50af98e33ff1ca9508cf7209b31a6954e604226c27608081bc99f9665725f7fda3bf8a90a403371a1bae038be9f8291823f83bd06314d499f65006783f328ea8b1093b03c70666fae2d402daac94d3cea6a3424ed5db8a1ec5a889f348cfa221d73b0086c8885aaa5ff1510dafe76436aaedb4c07075401674b38134f4f32939840235a4f518ecf88538d35636b0bb1bc9c63a5ed1328419f0741f96b6301fdbc091a40b0a16bc6e0a63b4da819bc053a5280a7e9c6002b910a0ec2bc82a957186ccdd3e3fb2332eacb3923cb716d5bede950112918004565598f2167b2939bb257faefc4d1526d7ae88eef86a3fa4fe4f301760a9cec9ef24450a1c30eca5cb52f993ac047915baccced0d945fcbc4e869b5ad9d722d1d7b85a495cd30d534015760a3aabbeb58e54586b837448b0f8540cb427d10a1e02f7ca31ebb2056948100ffa34b8d0cc885d4cb20261118df5cbf0935b2b81ff6f68ebb495d9e99794b79135930dd76e60a3b40208c35c87d6d19fa4cd97e971982d6dce37bc1266ea100bc6be8a1ce9c7b0e28d423f11b99c2b9d45b4c3c80", .None}, + {.Mul, "-48f213f3cec5d943512e8a7096c59efca6f338d8dad992ec7ce7d9c28d787a8e9f49d810033b2691105e70958d5747b385bddb722029ae870472d98ccf9bbda68493c3aa56640e366c2b44e5606b190fa7dbd61400f1e9f88daa5c5f4e9996314c4f79bddcca0f6fe1f1c72f6d65b1605f8073a6012a3441b1d54825921887dd1c64f8b90cc1791d8df6dda405548a57a6f2697b0fb0099de377a981dd86f3174120e83f8d3a2d9d7db108a66e97827cafb721b2bbdaf3bfc7dc4527f960e1da6bf7103d34d275877a05d8ec45fb3436ead893adb8fe7c0431b7366452bfa59b1b83da4125fea5ac7ca9a5c02698f617586d9c2a467814dd63a8b59aa92ed37df3c64950933475335a3e918a38bedf67c1d4b70ecdd6245f620ebb0f1c1f4a7eb40787eeceb6761f064fcaebfacbe35a43233ade0560aedfe8d075c5fd239bc7f4e5eab11dc0c29d3fa267e9b958976e79ef19897e0f345be7dc1a3147a730e230d507a599b1d5422cdaa09264d67d3ada65ab9e3f34956e2093c9e426f0eeb07208f9627ad85f3790d3e3e63ac37acad7a56f2d6a1e0ffb061cda3c549477d76db278434f306ae073a858aeac225ea7df5171c2deaa834ec2d96e280b974cc68b7e0ccb5a1dcbd1898b18f3edb789411468883a2f7aaa1e83be20ca11aa810efbd7b558cfc6f7588d2ce524463ad04eacb1b6c16a2df588e4b9b35ab3bcb906", "985699f5ca41a20739c70e3040d5505536eca2829f8a575f47e3a5917cc76d383a1b3a28d510ec859e84ea5e1451cfb752535882a2f819aabce0b91e74f8935cd4006acb55603d96468f27888e7020bf5fef232b0b748f9f659a8f3b56c725c42d47317400931c5d94a90575fb1f9b1ded6f227882f4c2de5213012f1cde87d8788bd2d59bf2ff24e9bdcdc68874b125442c9ecf17dd5873ecae3e7608f625ff01809292199a8773db6a737634c5de6acd9ffee08ee0628fd48c860a00e104717d62a91b840692c95f88a27d0652e6da503f5fc241c0a23a151643b9ae85fa30e6cb123e0c76a5aa1f1d4f5b654ef27c7d091e3587874b162fa72739237b6a5909afde26d34faeeea6e2b7e17fb7bef02729699d3892ebb0452576f0ac26dbc0c1ea25c0277f796e5b0b398df4920e5ebb14225a85f88abb2142823959a2e71c4ead6d087c8264128b2838081888df064eb4632b1678ca1d2ea8391497710f438c75cf7bf064ff5b2edad587afd3def48e29129f2c25adbfdccb12261a9c844ac09790a3aa0f4c455a66cf0a1d1360691556357a30ea44463b3aa9c18bf90f70e78c31d04d3268d3e881b067483b501cd3f9635cc5dea3813299eebf25565cb51a8e91ef1796114dec2a0cbdd5e6d55169f2546f4a048c106926575ffc1d904807e36a6e20df947d84ce7787588726e8a199b843a4330dae4db0b1124d56f7dc", "-2b68690a2de875c0c8c8219fc92fce676fc79965aa1b76eb52825c066f0cc04493146e917a38ec13463fb014e70206a816b5e9e0a24058370ffe3611a26255feed778fd5516ea6a3c1ce2774c8d30c86566b02e261f0996be73b3da80bbf7c40e7bc0c569e75df86d6a958e18902b0106131fa3805b92e5312c970324a6864254e9665f41d634a2290957f546dc03297672e4f47122dd18e120ce38f11acbbdb2c8fc8dcbf7858a3589c0814f68e3c2c753f701f4665f58d08be3ba06a1c3020eb7ddf417d24f53e8f02ac6cf72e18368eda03fe21d0f6c5940046ee55d24dcda856e257d6d0215c888a0b62fc3f9407b4c35d1d1d350149a0ae35d27b21be968c0f829e20f2ffe42a5e8fd5f2b85e09bae064278326143a3a845b32559a0f2b7abc914c004c7ab97cfda00be19372904d555bef28d649bd8ec307c9de4f67eec122c54b82fb0a7a528d76249b7da053cb7de561fbfbc5968738b29adbb71ac20619ad4c1ba5c5e9162327c800bff94edcd1e480599bc4be5e638dddb109a6d0b2085ada5c9b866a644813c39952d1057b28667f4b5a3cd52762ef96e81b8c3179c6de535d7370b40dbaf3f1ef3bc02c99ec084ce140147fc480dd1274ee037061a7765ce2a85eaae9eaa574038da0457029245e4819607f40d2777b2218ad1ef9a2f41fa2b3b16fbc60ba78501ae362bd8b704539f3a55a4c1ae75f15ad308053f61b060703585fd2f3ac7961860b8d7096c2abe189e139955d81e2eb85f07be691bd0c5e1f381069d5bba2463a7cb01c1be09ee057881e9b8c32cde99bcdf4eb3c665b8dfebf10195c7b501b522e6249fbe0d3ac0f360580456115f1f17865c7fd890e967d0c71504e1fe9b013ca595ac0d896357390eba99da99e0585c470d2783c32dd13074d1dc51c48a6116f6c63b633dbaf6d08dd0d29566023596477215d7848f5ebef8e81183e9cc441cf9e2ca1f159be02f63419eb29f52f36d64d5fa1e10ff580cf1df9128dfef92343966f22802bbc43fa67a0dcb3ca20a5fd625fc69069887f9e983a5e515d80f377fc66b701fc6b5424e0cfc7cba2c59399903830f70634c7b47cb9071380c25dd8a95539a939b82195e91eb0fb35194875254e6f14a79ebc88855659dd1abd6310e14c1b8d990773bdba28751a2f3dd40b78412f40ed5632c69056471c5ed3b1536590f31cb812e57e524af59fa201c3e8ce5c9bbb2943cd5ca8e9006bc2abfa4f2b2a845112663d38b57b90610937117f47866e94c5dde7309b0faf2906833a5a0a0a34b406d0f98d4dacf4bc8da74236132451b9daec64e24ecb9dc2a8f8361c73a48f1ee70c4f012d280acf79226500b5c987e97efe489ad554fac15367e252e4c7a6c8d2ae64a4130d366b5583b24c574723db4e7dcfec3a7ad937e7cb95f86f6f6022cfc4877fc8657cf2d682b7cb28", .None}, + {.Mul, "-84a6c8bfb7ad093111f7161ff950e6ceaefdd30b54449cd7a9f6ae184ea9a876c73b80a7f381caa93b6262b0b74d8add48cba6d7d870ed92512bed126a1d3dba61d7d594651ddc6573771329b9fb33c054db9fd7be12572216f588c01ee35d8cfab3c28592c3111417d86606ed958caf5c3804f4d62181e4388ed86552472346700b6f166d49a539704eb1ac5d54dd2fb90c545d466d151dd86c46f8e87d5309d79fa450364e767ce6d810d3959863c103fc334fda64e7c82387faaf086def584fbb80a769e43eb7e676b0d01318d7698d146b9f2c6be89195faf49cc2a49b4de4343ad3dc6b7f2084cee2c3c5e93609f656bb9c2e9ec79af4de2f26cc7bf683c9c39e0c262ff8f93901a0f0eced3dc576078ecd0bbff59cd937247694f6645387d851bc09f6d412f500de2105db3e6c9596376925a051b814bdc70dfcb75bf4927c1f84fcecb8152e9b576113f7272011cfba7293e0ba63d120b66685cb2cf122080e243d3a0f877f9fc35bd92c51f873af1d67f55c05f52dc6cba222493fd74d134b0489ea64d1f2f337b5f3a80c524e2148b729bf55dd9180ea380436e25ff1a87db376cd4cc570f1310e7ea34c4bafd35e1181f41816cf57216b42883af618b2d50d0bbdc2db274e8c5956dc34f9f644bae66589551dfda533fe400c0ce608cab8f7fec826a29247c42ab636f778af0727f4a3883478b8d1104a29b8e9ee", "c4c686d7c48c6533f8b1e18af4a5e6afc72a75ef9c6bb8d20d1a0281dd1a452eeb1561f5be877df2e114d73122cfa56a3ae2c6ac65fea339bc9aa6e3d5224cabf7fc8913cb33cac3f4f635aa069d8c71a13c02d315055ad241f04322f7a3cda7695fbd850221cb49d5605cc77782ef4249b287b0c521232a61cebcce912ab7b8e178b28fff22c161ff7781fe336e5488363a6197d14591033b5f9b4c7c0a9253cca163b2ad5298633ee8936ea4468bcc0e4474c1ece609b2c37f9a98dd32153400d02425e907d9f5974f88f2d5416361794bf2510364f25ea0979f41a0bbec581e3ca06005379253fabe152c00fda6110143fba9de2eb2feb39888531b0a8e8750d326767b3b48271dbb0e158d6dc5c5e034e03e473693d2095d3cb08f379ebd3a316dad57165410790939668d5f5b0865208d8f8aaac189078b0829683750e7314e8c5144800431d80f621ad7e028b534707e5583312e888ca9d925a8f7b8a0b04290774c18130770eebd77219872869d2e69a53bf867c051c591e8ff49ee48fe2bbc47cd119352d4dcc644873f5be044f9ff6b47c6dbaa937b1b53e0a39dc9342c13ca11ca914b1d31bf88425ea311c501009b0dd9cc894fa9820db8612487f70ba059da1beb161ce58297a39c5f48d3a53383916040a5de46c57f98a43b14829a3589ac1e02a551a221d091ce58c2120fe47db4c66dc2e7b911a96bc9a828", "-65f6909127e7ef5fcf9bc7a596008d432acf522af86ace932fd354d3bf3a186483af2d0327afc738188755557c2fad7924147b11b9452d191604577e9c812368b52e47fd5e11cb22e03e66170cee27b1ef8b87b9f3a7fab96201252bc7634db72a087c5c47f2fda6455af515d467e94c82bc8bfd46f6b0123adbf91d05b124757d6fbc470f411ec966735118295c3df2cfd5febec7d66c04c44d81a85fa038711fa193d5e5ae65e6f256ae8839c4d9237945bc1513e3af9501bcc14f9db1ff5d01244d2fb1423da36f3d94bc26930c82bcf3c4e936e8f23a560e3eb7181454f209164f9e5ec894191e72088ed4839681af5a82fabe797e014faa8f56ff609e25de82e4f44bc08b3df9b6ba0d241c842d5919833d2a0728359cdce2ca4d0c3b0f6e7887682fcf13123b807ace7108060d8e6f2b860c16c6c158a75d6211e2988801ff3369d888ce651170121686a6d30ae6d525e3573ac37db3e4f812798dde8494f4cba86002e4608b4e55fafd7541be62ee9c2ef72ca296cfb431c78e866216474ee6a53b596cc3ed4deb36717784fd4fc612151167c8eea581af3d9eb385c304a524c6c94cec6d4db816586a948fca900d5855ebcfc286aaa6ff63597295ed3d20aa57a813944d23ec32e717c7548ec675e8416dfa579850aa722b930ce89f7a7db8ecf6e64d8e2c1ec4ade714f904352baa28bbc760e396fab1339560dbbbffd6caebbd14b6c905ade1acb8aac3bb527a6dcbe47ee08a418ff1dfbb6b909180435c8b37659a77574a6cf8c556216bd3cf269e90502081ffbe39e484224764b26cc728152778b9a9de27a0bc7283fa0bd7815212021d85cb068c610cc56c28abec078ca0f672abbb5c1b1d36e85d67c3dc53c232f93d095445d87bf5138b5f5ac03903d1f87166ff8ece7926a5d240f385fb6808a1f8517b51b88529c5ae38d9e65265eaaa895a1f216b6875baeb090bdb691e1f660b07f2640c8f44849c1f7cb97afbd40c51136714febf635974fcbb1075fd4d3119fdf48dd3ce037fe89f398e3ff153fb60011fe7b82acf26447fa081163cb4ff21cef259e617442a4fc4c38f388fb58e6e791dd8ef68502d6dffe4a673bf5ea7afef7f7280bc07ac84d7550e29e1dbef76d9f4a9baf193381292ab463fa91ef1acd7a2a779018b23fa0b0440f774857477fe70cc7ff56b6b1f303dcb9d819e04ffc24d90abb0c097f0ca307c85ddd58909be85e3f1ab8cfc95efa015fe43fd88910372dd5d1279e18f3e84af8698119ef12da803ab7a90520c48a1c56bbfdce92c123c9c46436fd76c62ad053835aee47198381aa96caff25fb39d69128e9162ff25d7a20e8c0b3fbdf5dcf2685530d344d1c909437252d28a4588f6f3cae390e28e5031c99af28af54fcd3ab34a1885ccf9eecc4dc82770a183d6d260d7cce635e87e9f7f0c0446bd30", .None}, + {.Mul, "-8620c84aaadac9c06ad0147bfd0f020b0ef6985507efeb4d2def5bf02c87ec9381a4024b90f69b440df3fa93d24401cc7fe83e2e4c1344eba3faa7ce95b2bb236cf083b307bd9d14a42abb50c277cac88b61741fa71dca45585ee12e9f4e864def1b0e31d78dad238d401ae3388ce756c16d9a43cc02789f2f7f73378fb72cc5ccf490f207d61cb365ab50921e1bd6ee57df52776a351e23dafc23386b86247817dff50ccf18dc67094eeafd8da4f411b7472168469cb6b3c25bff7838bab3e1de1f49174fcad3a24e7fdc2ed7ae7c6bb93db2d57928a65705c5d1e2da5aca2be35848648c09bfd7321fb62b015e8940d07ea17206a7cf1adc9c02f5fe3086afa2163a279fb1a4b4af8a6d6f5014317fb3b72a4ebd33a6fee90975bcce4bb4c8ab8d5cee51b55167acae7e547bd4c96edaffa25f41f627e2a6d5c6af8a1ebb5208d5f1ed32365ffebeb3a05818d48115721b94f301d4b6ec1ce688cd74575c197baa7bc3eb27368c97f367635bc7bd74301e4a432226042b88d1ab4870f45fd9e985ab95d29bab83958f32bfe5cb51c6b98d2a5c2f4e57da39300b3afd8c19e0ffbdaf2d4898181c395e6205f9f1870426485427061fcf1feb947d94abb18f33a767909326860d2a0f62404435adcfb6ebeb80735e366822abd32b8c08dd1b2637e8f4ca395337cebbda5efc8f91e3192294bfdbdcd1bc4cb80123e49bb738fb", "4d38a0f7d4adf171018d04c5f5f73db882c913d73b0d9e4e60ba3c836d24663970a3031995877ad8ae17d906fa0f7976272e58ea265d4031f2d2d18b866fa816820837cf8fc1f82e21e22cdc12dbdaaf7b7a1d1e87ac2af718385383ea9d9c86282a69f41db7a937eaf18175fb4d72a0fffa25aacc8cddf44a1d8ceccd585abf8e0ed0c93ac0c0c4ac395f53bf91a20d36be1cfa649540c189dd3303b36aed172c91d0a69a5069007482781f67d61f43ea0464023c9602723c2e595bd388af404f0cc7ad313c3a1d779e1f1a039bf162ee7cc634937cf165fb9e4dbe1a29d2d6f5f53753897ca8785bb5043604d2237fbd1f0a27e51c00dc7d1f5231c95ae54f121a0235698a06ae1ee70c2ee868fb8ca4bbf822a3ac68d4167602ee41f766bf31b557353ca63c8bc4d95ade23fe20c5617b634f5c2c97fe244f867ee0ef7fba5f52fd40068c057af702471f4dcec25087b38f354dea07db56a6da2779a1688c0502dcfb88be57ca783fb62916efd01d203ae5140a9c6f5811a1f4d4c66a33f3f86c1978412b9da951c9982733fbdd0488fd5106baf36bcf1680780af8e978836195ba8d8a082f311ab76654b87d8b4c520459947bfcf7883c76278cd4184844b8fe2eb9a867ec65c6f71a89a241249f54dce8b639256cab6ac1f7b36d34a1ba8a7237579ea8106d866ffbd3d36d5fd3cdc37b44ed1bc7e719e333cb48283fcc", "-287587c09bf761e3db323b28cad0fdd4d5716c68292f8c2cd903b7f1202527654efbd906deb71bb5b0da254c93a6c622dba93bd4ee9b6af0d58e31cc1fa8871507d99ad6aacde2fbc1e9c751c6a51c8baa373c9f941308ed473487ca7b4038a80925e4201ff33a1f18b52144c571ee57abf905e523c1fc8053ae80c443be507f75ddbbd830c6490280c1823b5a1ef9396b0caee2f5b2849a303e9d067280602afc0eaaf8a77ab1492e3523ca5853705603cdeb65b9c8f06bfeb3293c4ca249439bde00b7c692daa9dcca81fce5041a7c0a0a1fd0315ad2f4e06ee121b0b554daa6d83b68ed3805429b62c41c023bba84d3a8398dc485a8e37a258676b1585bf5be9f5a769a95cb894e0d06335aceb3406789400db252b40a5e8557dbb61424e046ba930e7715af1f1e0d232bd49c3f0610f0ffd473ea8867ce00b2c095311a336e1e9e98bb9cd1d317b67a6ee4e1290d3d0da3577286aaf22b4e3e25bb7819a83523c580743381224c3b1507159f95889a8b6a86d2c5e6d5c18e2190eb5f148fe43fd675f3a183111e5dcdc2608397a0e9a85850387111a924e86194ab8a7a93a1d7ae96bb2a64f86c38dfb66fbb4a18b65b15f86dd5f9edfe5225579e788cd8bd398d1ec84a0ccb33c6954a8146dbdce1355d6bd528cf783eab041df52c314eeb32c635711c3d2c87b7bccbbe7fc2c452ca1d67d431a3a604e42e93c2a031c3210877e3b783390498253c2bf2f1e118baa24f6c71295f734812346dd0209efdc9b99077298f1bbaf49f5026c436bf623c74581eb0a0aac794435b7d705f68c6c41396166bcfa308cd50ca7b1bc35d9353bcf90dfb8e83e406ff32759312be5b47cff43c29d0d2df694afec74cd86c59783a895eb1de5a6019442356a70da594c4dafd0405c9114dcb48d83f04f4d8a350ccdafdc2afddd664bff731b5e113b5fd305d5fdf2a0ccc29e6e56856137b5ad722b475b85d572b24e0477ab05acefbaf6e6fdeecd46a1d9786499860d824435d69d45667c66d349b11d4cf458d15fcbf28a1ed3cb29703998b800584da043b3e96095a9db1edb40a38c3d13d962262742f45cd6fec6cb5bdfab7e012f480f916dd7b98230a0786ed5b8cf1c0469abd9b8474d0c97174e67fb844ed5830c3f17f3b157e435d6e6bebd29e1c848719f798356d46ee6defa1e83cc1bef7b5f6f56dc45925b14ea8918fd2f1c67ee91eabcb0f4781747028b3717e99638800a98a7009fb92d3c78aaeaf8ae79678d26bf04a8523e98ca76e99946fa932a848a57f4d2cf40a0bfa3d26c7ecaaab052f19f5ae218445d37533363ab1ec7aa50f36f02274185b5e712173425245a17a88a7958a3eaeaa63300e01066e79c55f51491cb22f0808a13882fdcb9de0f27d469e323b212bf2b832edf4d16dd3a9fef771aa77783b5c2f478182d476e92eac3f2d04", .None}, + {.Mul, "-642e924269f05f58a0c992a248a001ec33e2d87eb4fa47dac765e8b1e754e0c02c0a82531fc997ddf2aca86798ccfe625a744f6d12586fb471554e244774eeca8251cdfb33bb5703a631c06fd4147d18c06c6c927f6f43135107f0a2ae88105e464328360fd08658209255e4f393389e1c54ba23f017ae9ac5d8d1cabc1912ab77b6405f0d1cacbf7bcca54e3280a77271b0df3272d3f671013709d673d207faa4f14265fc8587c185efb2d209a5ca7757fa6218c3769c862d35c9c0c60755c989744fee3b7214c6c60323830d80a43ee4b91bdb0a260a2dab67b071f1cad7ee103457fee039c9c4c90a9c165e2bc7500087f050a87c77658ce52c08517b8ce8f1b821ca062ebd2733bcf2b9cd478df8207838ece1dfccbe5a246a5af176aa86b49b483993075cbd11bc2f45da4daa571002586bfd6a68ff151d78fe611513b88f4dd203f1afbbfcd85bac7376cf99f4f29e320328c88d42f041bf430891a6707205e8114e4f09bbfd483abf9e7168ad546200edd8ed4738fc301a004a075b85dbf7f37c3a92222bb9da0370684530e0b3108a120d31f8390c3c807c43839ac5455634c53cc9842e40b7b4262eff0112064f9624b1eb52c63b2c6a3c876d6672360c86137419d42172fe0554a016eba194a70b59a4c790e8f9b4481d1a712d0657ee8ce87e23e2e9077f34063625e5f9c87dbd6691885da41179abe494e853f7", "a9af5fb4a33bb1d5ce1d3f8bde614e64ffd50f28f8e362450027f18b0f332350c3f1ffc4219234ed2322a6adddf5709b85610568a37b354280af1b31296f4c252983554415ceca54c4a1ec1a5efeab1f556079aec187299ea62a87ad0b35705777addf10fd4976081c18f87de41b290d8737174ef0395ae4c76199d8d5d36d6e1c3e062fbf0836c5d76e6a50a42fd4caedb8a4b71b161d7203e88eb773ab2a6c8ae71e68f24e2db2c2346ff57bd522d7f1d4e07b450966089d39136a29864adf9e25b9367ad90428887cd06aa922476488a27ae205a9aa4dbb0d5af2e46404c2d3a7ce2f20550b0ea72a34add9e8d88f596d723da20f4e06025f60dba3c6b8334acb1d7703951c5e7c9b5683eea3745b1979ee490570d8c22ce68a7ce07614bd3278476c0d70a6d24137a994e727345f9d1c0a41c872aec371ad35f93b53ff7db75d70182174341ad92d361242f3eabf17a2fe41f227e4d16024b117b6954a34f662045e133fc7b3163be448e57523f5de1c89ce59f9ee77ff572303df57d60bce13bc70163e96a463fdf82eaed34271632220c6bf44bd442dfe3d9abcffa7a67f46698f73a490a453e1a9483488071495f86c6149562acd95d9148b917e3729f7f68673c3b411cac4064ea73fd31d64740d470f20868f4c5e3fb002ae712769351e41be959e93afabc0d52ab03261ed3b77fc1e903b460c0280a6932a4c3399", "-42675fd7cc3c99b93d6ae9072dd342ae7afcc68985366c1bfb9c9e7649c9f11df153c49efcd185fd789692db3c5018475eb36a7c7cf70b2e95945a087f12eef851c27fcd5bb86baaf9e85b39469fbf2785eca7b89db022471b4975976097803e818c1b3c7f57551ca8d701acf32786d29793a51d8bdbf522d344db02aeabf88d1ce814a8b7e96431bd181baad96cc2eaab1f0d900ae2f4f65411d2d43d278a9f8233f5d63e628f198de616f3ba9333379dd195ef8036d89979e3afa1040a19939c56275973beb3775f35f68ba2e17c917ebb9d5fc2388a24c23d2ef3d54c3f7fbf00d6d574c718888d32691992ab9c5492d9488cfd7a80e163419ce15a3795235f4b21ab9826f0eedc744dc824072de667b2c5e20548044a82c1e5b38b39d633c8b57cab1eece9194406a1407118b448fcc7bc03026d4ea5557d09679b9e38e4f96804dd77c7f5ec066f9dc843ccd7801f0b6e10638ed492e3b52771f87423dd5e55639bf24f81999058623811deb18b87a694b035b6646a92c3f974df6ed2dba78b9539c36e5447a0c37d683c406d37ec18fc0f16281ade02281bd1cf06b742b88f746a0f2f49e049ee280999b5cd90a69636da9237b2934d23ca5da617de7e9a16759d00b16276586e39dd897052cfeac963d503641cbdb16084bfc94136129dbbd0e8e751ebf83919629a91c78a5ec7c1abea26b468f8170b4c8901a46cfd17af20601ed711844340452aceb57cc9ebc9587bc7eecf6c662454c36918543c9027dfeef826f6e6187485d97b302950dbf3a3cc07acd8b765c1ee21c03298c4ccdbab3b5e29aba70b3670864a8a9d1c8c54917eab8341efb6236611bcf3b0828a439ec4f4c8a115f3c56aef5a44c10a06f56e5eb792b9e6d7f63f00b9cbf0af4449a0e3bf243eb06c9da8c97d8606ba0268de95d97ee8ea01e590eb9263dcd6900ab78b279c3d43f368e81ff2de22d8ace2b8d1bc9673a42bf194cf7dc0b5ec007faf1b2c2188500b20dbc727cf739a5937c843628048b7e6d209ceb7328a6558d2ec32509c48d3478d5c41ceb5c07345b58c3f3911f1f313d71262f82bdcca35f10d40fe0a8d761ef6347e4135214cf7d5e2838a4a86539c5c62e0b847a0c823980fe3a8ec85f8e7932389fa48446ed7ca9ec490395d861ebc716aa14c14f07d7eb9748e2cc21b9ef2d2e4052bc5a37fe7fddc0fc42cb638f55625f860201e5906fec343be7a516ee00f341efa17351e7ca83495b3f61e563df3d955cc68bdc2eff0a9b1352bc8e685d30320116cfe34350c3e1e2a11ef63f14b71a4c512b97a41b59147900b136b83edf9409b5327313567de0a8eadb51c4cbf59a36ade25253632505b9bc3ef53470b4a9eec8d583a4bf907ed9b398e4bd0c7920aef0ce41e7b818c50ea10d0591d883ccec56a64693e990352497812489af8dbbae8639f", .None}, + {.Mul, "-e40f360bfa3f9fe909e22068133c584b124a251373946f3b88ed108f709454a3fa43f19723da084551c1afd4a90216f20d411852d8055b42495ee770e2f93f7881413bf156c50e39fad7002be8fc6a0ef05af4a0b2c27df1307d9d20ed56866d387c6ab95897dc7b21f25228cd1243ca9e3ce3c0a436de4a53a05f4d3da0a192f08911c6304fe9dbfe1274903468b7a7dc8eff1663839032ec1b7128e9b08474a2c103d07bd2ccdd76aeec9a9b082338fdf3878d071b7397052dc3d8ce06dc93d190ace7b9efea77689883cacea020244e7354226d9c326173c5c79ba9d81ea2b6c6db42a5aec3a31555af6d4228aaac47ad0dcf2cc784f5d69bf4a6c245a7a3709288e0b2acafb7f4a7ec846a8821a01fee7b084ae35a0bcb2d2f0772f69cbb9e41ebf59c1e0489147eed882f0984eb82dc5070144bc060b3cfe97b90d2d397cd21af592f9808fdd0e669498c9f88aa94c6fd076f3a4a54b9560f4322dfba371c095e49235d9ce32a0befabfc82496300cd2e2a6e97532cbe2922812da5ccb581c3b2368762a5b4bf171d6ce7ab40f639627f197331de5fbaf2d5dfe44c5474b65d3cb1db03e12b537a2287daa0cd35f76ce5abc9479462e84741b8e858d0e559dc9880650c63cd90181a8ee047d69edbb89ec27bad94cc5ab51c93cacce0d018ebb96fffe2a3a6b26a4b5c281982b1ff64753fbe9add6c3e610fb52545617", "1fe0a28ba65b927285a8a2584d5ae3e5289b77c5dc575018d09eba34b94e9dd7311dda60afcc9be39b8dc88a213221738928400bb6de28ad3fc595a646314b8299047b28a22cd092e52f857919c2c9cf655489590afc80ff9517a138c79165f86634266ff632050290da41b1bfaf3546d0bf5295aa2676eb2592addf93003dce9eb15795d99b98b9f9d097c8f8e242e28d31d3167b8ff2b6c4048c2c5a7d4e74e37c7984fe516ffe92f07aff073c7180248d1e6489e4a63a65237953a988da21f3b3aa5d1ac59330979720d0c03cf4e09aec195f91d9e9edc4243400bef1b0e44cbdf0f8ab35b37aac4264e4823e8ce94e0f6c77c15c9ce72aa0e109ee4bd368ec21cc40e80a0e95214d128913a1d9008e1a2468b5de0e17b57fb5bf5cde82e0728ca8b81227532cc854426d6949669778288c3801597f78aaa43d0b71c6ae7db08cc0fe2514ab9797cb1213384104ac9336779924a4122fa2e6daeba9701f2f88a6e7b12a42de402b83cc9e3109650e4e875d33e5818eb26d71b9617264fa26a879a50448100dbe519138ad4af56e899b0cb43807da385def4e82cf20ada61e894dde77038e4588a187745da3a19c1e763e68b78f956df4d3cb51827291cb4f8c6aee3ffbdc7ba83d2a72b677dc042d75344c44fddd553fddf33d7dbcde8fbbc9e2ba4ca40b4e48f01c517abde9a20f8c0ddfa408d639af877ce86626ced078", "-1c65f5a8c67209d0f50a919f14acd5eae2818bc00a1fe13924af169023a32923e7777e3b1c91ca412ef86741eacd67b82e38b6147d9e80f695597fba0c63b5a58f37ee760ab540b7e93b81bc897a6330509becab23c54c75a33a888afceb1c7714e4a29ed458dabf7532137c3a313082542ab04e1e2727aedc7b74ad38277ce5d828faff782ad49c83510c2ab5422e6306a424dc00dcf9a1ef48fad81cf086880b45760a9ac66275a8ab7d0ddf772167af39c03a2d78da47a873b254da8c22c3fdcc6b17b514f330c1162b3fda893f0a461e0e7fb45f156f147fda99b6f28bd76d4740134bbff16f30b1437d418eb3d9f02fb82d3d6c4f6b56e37a616b54cef1f953f6bea3d32766e068542c7bfcbe865018a62467fbf0ceaae7e43052011b9f5f39aa4fa242968098d8427bc49fe27e71ab09b1243266603d176db962d07f5ab1937455f5127a4b6070fce908d53faf701b896627f54bb32b5658d8d99f441c7c3bb21174af4f3d472824ba02e1338ce6b43588efec005fdc7de1e8dad3aab17e30b7f39d00a630bee7dbb640ba004236845e034468a6452350eb82b9b4f660249364297bc49fff1e73859fde45443104755ebe15497c4cbbb253db7047ddb1d0fee389ecb5e81e548fb2701eeeda25d9d70d4a50631097059e1776a4c286e25354f486fa97ccf76170a1edea37a982cf25daae7f4619585aafb78958cbfb1cd6f44d7c3962ec93b0fb0f94ea27df6b4d5f7c012c9244c62e4e398e6bef16f722ee98ba2c736f1e9bcd387cb8bbfd23ca4c8bb42362f071e2df6b0291f75adc24ae8ce780143868f25d94e5c53f74166e3558524abe707a69605779d718686b40897783e6cd5c0eaa0386b70afb9a0bb6475d34c3598e8f1bc2ffef468956511f195a43f7e855dd27ea0014c08a0c29c2e9611def5bd0ae7ac3381233240a1ce65f6c71f32b49a9ca73bc01c201a825d82206f78b4ce054a3d86456b3ca7c4aa2e293dea9e8f1fae0ac7ff158d9f66ab426fb4af1a588e290762ea1318075ab6a092831d5f68511b5b7135b0f4a3fa5a57ed20083962358d5131e2c588aa20f9bb0f0919cf0d4791065f2e4590b3f272512faca67b0b76baa245b5000918501647856541963df60cb2fad9bc2b9c01e83d8b6954d4d7bbe5156bc45d592c374abcb3f10617d91194ba65797d4f24a08972223c67d1cc214325edb8e551e74b4b1e1654aaad3e21f9d99c6242a2eeefcccc09f77ba3ce6411bd5775f4d5dbb40c5c36c3ebbb7a3f2ce06cd371d05b9d4259f499b3357b43711c2eac1b2d6df269414af33b451df9b5bd8d3aeeab1250097be795477ca9077c9dce7fbb24a34baeffef0a102a2223b529f75817a23a08b3a123ad2b5493cfc7cd7fb3cb852d796155ad4dc084be47a788ccbd168abb47e5416371c3ee9f35c9dc1281cdfd0ac8", .None}, + {.Mul, "-309087d9b5810b7a2cd5200a7a551b2c3926184c1c551fa73ba5422d47cdb3cc2b6685c0f6e77ec4ce8884503f6a134e26d71330b8c18867762ebf55251298bb3377d70e2ccb6566c44c1c6f3ff06316cbe47f89a7108a59b4f6b85cecc14199c86bde58326581ff9f521f3fa4eb281e6eacc035d9c0b02fbb20be63f6bf5d0cda940d2d870b4a9d69dce3d6162bf73a3695cd83385af1949e2588ec7a8534d094aba300b488f9db604427394ecc6745387e921bb8f82b1455660fa83692949001f5fca2b21bc4048e0551de4524ed96c73089a49cf8aaacf92cd6c6ca96f40e28bae165f76fe8ee7b70940e18b08ea60e12d3fe2303c6bdec94fc0fdcacf79d15bb2b77e46dbd7df56e5cb88ecea7b04e5a0f259b6974fc97063b603cba7a9a8792c7821280888df9dbdfd151bfe21dbe83084e2e5dc4194ddb5125f42a88edeba262440235683746e1c377ae6c41483adc3293c834b0685c4be8dcb0a3ebddd8e4537765fe6cabbfc850a9812980465231b92a30eda8a2f855da909ebbf06638955845a40391b223f0386938752ae3b3549a62886fd4e296118e0182871c1d03b2d449c96bda5d1495919b9596e4e6b1f10c4ca4b28607dae576530d86e4e5eeb279f202c02e18791e4d78f4b383d36ea199dcfb43c83ac97267c15910f0c4a852302c8d9972c64c4c4ec942773a474e69ef8a47e45a0791ca948c1928a507", "46d248d1fb60d986267718dc4afa09334f2866a35f26e096c0054158393e7d39f84c7b0adc3dc5783b09a473594c7a0014c2198f232aace578bda5511749ead806c30ead27454318f603e61913676c1a9e451d3bd8219a5b3ce817c43f36797a2cf31bc1c132bea975da63643739ba19f61f3041a8246093bd71f754fc8c9316cb3047530f5412c73ca5a37d7fb67dfcb52a64a7f80e2370e5845f2d34ebb702275ec8d6a9bb67171853c9bfbda4e980f58304b360d8aa47f7241ecf414484f53830b049932be865ed086b2c0582d0771708c6c53e6b140d303e635f22904487341b363451a063b2a68c603616b76861b7ca56da37b4859c1a204c53f25ab2beaed93e14954a4a5ad11e620d4e5b24909a574e513f9eed35f5b197b5cb5d0848303e6fe6acfb551624d1017586d924e34aac08b4470358e6e6b6674f9c0c6fe7401e5207df48b30d88858a7acbc367f5e2df71de39f90b4384fcd0e776e26a3eb8fa68f344f9c208f59dd6d49c3db2a67e02c5509fa561a487e0ef7cd8058d385dbdfca869c78c42b9a4ceb289b11726024d164649eb4977da933086c976dbaa57bd9d184783382eb5cb6c8b3fd4facf93880728c9a3c988e36d26c713404f20cb411524e37393b0edfd64ea6a78c6c93a68c18bbf5458eeac506a38cfe7ab2b4214db9da3b6e09ce5e8dba3e8bef1314f3abb75d3295cac00b5fbfe933a341d", "-d6f6985741c6571a8c41276fb68f77390b237e6011dabc73ff7ed8cffcde8e3acf9258e06486268c55a61f9bfade8eb085d5c6a8205a2619fb8582c199b98d8bf1b0397cd9382f9fd330773e71c768b337fae8349ac01f11891a8941564cea4fde5d671b789089b609afd9e53009f1f417971bcdb0563d466b7bf9617e3b0d0f53aa06d920480a55da46d50abd8583f7065dd767e860ed32f913b3572bbf8b17df514ec5f3cf6e0d5de74c3f96a4543e11ae599a09917cd3ec26103a403b71f25d150056cf63f583e6761e1d3af0e2b8681d95597c4069cdc2b10fa452d54cb0e0ee836c113f8fc0e83d405426313b4187f188b075656c3e5da84b5a2fcb88d3cd76c53b4712ade5b64ee358818072fe1c2a9b4332f0dd67b760eafc881fc137e6ec44a47a182640c3744dbf191dbe76034a4b402c49d1f830edeb6c5186def7bc198546e26207be5930e7cd5433d965f6a9747cb5f4164b11ac0ed9fdc385f20c265bcb24319edba74c8683aa3743c1502834f90ba56b15f1b8eb413b26d18a385e58f1cf479efdb7215cc9d6f33aa39c6be5f0093c0207ea736e027dc8dc55f27867881c27a0d39ab10ad001dbe2f709328cd51a85bb52adf4d57a6bd4dae32d36b40237c99adcb9e66c3d610b93c395140d4456772df562b391bd702add2e60d0a1234e0206678ed0c3c94240ee1508834647805a313ec0cc34f9742d2b55d5ca7e162ed91add5800394c9c213ea4e05b433e86e5cb999729e0443637b7bfda1b682e07022a8b5b92288141f313e65e82caf0d1c446d3a935906c6ea48dc80baf9e898a1033b3933cd49dad8e4acad566a01d72aeb84bd0a47a07905bd175620be776a69a6ee71a4ab4fd80652d54db1691a7a3ef175dd48b116f82a0dc79e64f928e1d9e83d7918d25bf46ef9dacae26f3a8ba6fe13f4f754be4b1a34042dad031875084aafa45cf28294fb14f7f4d2280ca4201bae26d2a442f9d495379678d5889c995f04750f86d907cdb39a2c6abc8faf6abde790bab7a1fad7e6d902f191beac4b8d0a97fa11cbce183dd40c2dbe777f1f41031657be464a5a0962a01e71f75c15a529f7f96b632c146e9cb93d93c02c5fbd8aba78386d2a6c67a80d565be4f96d4b19efab14ef5b5f9260a0875dd61717e68b90fb7d77a350395538f9cb33bbed22653437b6be4db25eaab0f8ea768e3493296a85a917b152992fdde5426e6e41199e7164583856d428b2234173a647a6b5dcf51c821c19cadc9b8360a1fdf45c913d117b15f35f6377215d6bcc25c6a9ca6dbdf3d84a8dcb63bdf4d23795bb50dd00cf66abc8d126e0c265ab521b6231fe2c48ef22d174b62a7b42b7c4356c5281af7b3be44b2b570e3da055bf52779011aa11890dc752c423f25871d6e43c94347b888dfb335a59efefb4d5ae48490505c74263ece583b61dcb", .None}, + {.Mul, "-2f983e750ef58aef47c1cd39c7de0746f669097a5cd53f24df5fa07488716f8d9aed85fd7986c22802ce15c5df1f83a980554d49acc894972c15cc21b98bff634c88cd5a3b55ddc3a3459fbf8b43c55d7ac2aa73bf64f518c66714f816687c503aaf216b53a7be2779ed45b8aa74503d97f37de65df3ff6d4dae6e4cd681cefb0f9aad9650dc95cc6ecf43efb55f981b009b2e43c29196c8d9bd6b18fb26eacf84a93e50f6d293f233d226e4b2e6709b8df8c5648593f6e968628a267d36d457584ab4713beeb0ede81d13fbe76f182a66c360747d6989ad91cc289bd8019f6842cdb244c87bd3189155ca8ba90c4852118763447923f3e36f9eee24e0845bf67fd73a2ca31f5996d241685cb610924f214c46a8ef45ffe796fa8da7d45a53e0794760b2d08b1b8f303df440ead3f89c7448709f38604f945dcee64826073bb2cebfd2d3dcd7f8386f691ccb9f7afe9b64212b8dc02524a1a543c1f6afbf255a4e43065c0ac18999a698fcbfdf918ac3bf600f1164f77e23d1e78cdf4f324e70cfefbfc9ad39195ab85950b990495b8766fe918c0c6bae6d8b5d41753d815e95475afc6a53ded8da267f977ba346cf8702862daeaff6bd48e8cc78e3918b8f45a95890da323bcbfed94b4de04bb6fdd269e8816bc0d2381168672834fbcce2b3642098194ea8535caaca36ded62a47847ed47c868746e0afd127f3a816724555", "6bde6cfbe128f4436dee96ede0021b56a579ed4d84f322e5e6a4305cddf027c35361a31fa27d547c1a8cb40d75201f970d426c40141570de3c5e42d092321817a5c7de78e071eaa44529a87d5aca88dee0b1128f689f8ff0c30089fe3e499aa29d4ee8880a02f7149f9826e9442c80e76fd42e9fcba9625cc9f979f676568e161bf58bbdd18d357dec76a2db30b704a8878f529ef5654783accea2b62e95453fe919ce8b1a1819a44a9cf39ed853734a759721ccc15c99ba70f36b6eaf624b2e555906030e71e38bb56e1ed89cf79885d2d03b7c4f08f0cb0942e4bdbd7b0196006e49ff410824b8dfbee91aa7f705a9c56298b9f12e3f60c858a9ee2b3472a93062cc5016d08ea185b00ecca79af7e0d982e4ba5d751211ecde9773814c6db5d202b0adb4f8871f40f0a16cf79014abb3da2a101594379c8b4acc304b4793611ffaa413cf16e91c0eb5ab0c3738c2c7eff527d91034bd0cbab033fa63b14298cc8d50c61beca2191008ae4bee5e71758961ce41cb17c6b994eeb3f60a8c651336ed6a223509c68d993e21c07a023f3f8ff209c14ebc36ea436de2df179c2c2bf124f9027bcea527bdedd6ab44e03d603f65f484af5248ede2c593dd9f60439a4e94e9c15105c61c31c7ff0ee27bf8af86f4a63d9eb706052cf02cb607caac4a98f9173449be58507407216924613622652de7ca49f225815c09c0fe7f4a14c7", "-140dfc64253ea52e091aa44888c428b7cc8bf521cc2f58a6ea18d862ccf9ba86d54afc560e2b12bd9c4978ae557c4bce91d47dacbef4c2479310ef469c0bfc1594a593c27a4b3fcdaaf2aca1df6cf46c5f5d05dbcf36c8baaa61cad320d090655b47ecb27d8af8fc541d3975167e0fa2e5baaa9241da147c0a6e276c92b1fec24f48e340cc37897f6ca2b51b96917920a1828e4fff4cbb308a2ad6557938f79f5ae49ec4e0f7af57a8c501bb8924882f8c5832f62b0be65485ee9f1e9ab9656e070d1cdee57cf43fd41c60169c0a34e746692f1f6bccd5c62c0cb38af64601c4971e2bd8a58b18e3b826419bb3cf15e0a4d77bcbb7c2afb4f2d26f9b40a9347d4654087a4c00a6af2e29a3ef0185c139d2ae8416853e94b8185b33a42bc873ce19eecb622a90a68eed994d95f3ec822ccbedc56fd60ff5fa35f37f9ad713a3708783ff5f85c44f1aa626240fba308df4cc588e196f1dfaeab3e5fe506e8c0a68f7e10edc86bf92c3270899e185a71d1303cd02261fd8ead965c680796d50598839f36dc1c4ec75fe568796f9bc93cbe82d1f00a27e0b0b42df27f58c94672b31db113ef916dad9c1e8d156d3f928f730164cbb4df021a210f2ac046d13ba79e1f3360d1ab94bdfe5cf2c9078530b9809ee2f3e6d38dbcf7cd9ea868b6516ddc1e7022f5930f1431b60d53df573c37828eaf7fe136c054d6d5e58daea4211958b48a6c29546fd3a600d9bf762b4624ec3f621ec98d1be98f225ee95ac4e30b0f6a3f2436cfd5daf513ae072f863a7247095752104f17e3f3edbb36bca05bfe89dc9fcaa9a5139e1dfc313e58bed5685b21e826cff0c5b7ba9efe27b22fe6792033bb5c802317e591111541a30c66c3b01716160922e40828f571f1bbb7b334cec1111732e6ba236d38b019f1642d8d1dfc80b8131204f32a57310898ef50967e56dfc149a989c2e238de68621aedb84972e80366e2999d8a54cf2e2ffe9f879e255a02ee851258801469a6d4923f13002fc85c1fe973e19630c7c951f96e0e997707f550e3abce2c968bbbc79a00c51469a4fcaf31525b3ccd2197bb72095f32ba6f17050d846971d8dd377ebc55051c5be80d393cf1889d691efdd02af5fd875ca65a47efbbcf61672196b2612c9ff578c8a6dd973b794f5be2255bc223afde1a68761e3d5f4e415e46f0a6bd217aec02fa033136da00335449e6770d8d5d5741e4c7e67fe441010b00b8cb3f73c0cec32b4aec479a15dc5d438b43adf5d058349cb63f7aeabb11c77c79b8c47272c7a1b5dc0393dccd4158f617fa60ccee7cb26357f346e838c7f803b9e4615fed73a940e22c5ce34d7f3f46dd94121ec274571be2798c8d1c9b393fd32bc420d207034421998d557a1e6be0566110cee07cae71b7d493798c390128da1749a1189f65d665d2eed8b91cf7c2e412d95d08913", .None}, + {.Mul, "163fe1547e298a190ea9ac67a805854a4d746de8d209f3b4723e55727f074e9fbd21583ac665cb400a8baea2e0fce7d9377f8b13b3cbbc7503e9a2e688724024caf8348725bf448a04acfe51442c4cc33b8135c3a6c6895eb88cc2a493dfff4aef1967b5c77f959f34d380b14d83c1f7f4ae8d86657d374b1ab5e2fa94414d69a77742344583e7ed61a1fd694c7216096b49247dae2876b7d1ebba844764aaf67b550ce01f8a6e8db83884c0c794be6c3cec8a58552ba56def0b10da2dda6fd4d4d34278a2a472d2a128762e4b6ae706cadbfdcdd46c80aa4736ad631c1b28cdeea8194efb3ba285b7d2a24689b1c89033ddece62339bc61baa45a6d39b0253ae04f2c950ff999c2200002d06a2fb1720af3d683c8b2c3b23310608759ab5c4d30a70a1f070f7854026f73c9bfa8c11b6d4cd4b77cf422de0d6383205605ea00dfd9fe53415b31408d9d8a4df0a0ac167305b710ab3cb5e4b8813dec3c3d2f5090f78c6c68ca412420e2ebb7fd65b9ada4f244502fe1d7fa3f2909837b1754a1d2725e6703f01801f872d2a390993b5a586238a84ca6aa1d11f8cf9097913fe2dbc5f9b38583e340c70a85178abdf2f64bea5750eacd3be2ba402dc11ada4fce31e1b8251356049e91735fa1be0c2f1f9f3dd1d639e2f5aee836c07698ad655ede5c49a1a201cafd02920712a955480a663e92a070122a34666848bce814e113", "124a8a2d7b9542cc22a6c195079185f355ecb845bf50d24690234dce70c0b9a48b8391a970b78683f97e4854b9ac6abc75dbcf47af526375328636a320adff07ebd86e28b5b32b89a3c022737aa3c95a185596406d5bfbd5ae12808bcc54f61961e0d294e5843bef9b42ce0488b9cd9035a2053b9001713f6897983cb386a3177acc3c1ba517707609e87bd6b6c370de35e25595a61c08babd32ed2ef9b905175be98e144ef4ed3b631a6d817007d2a4e1b0775280f02e45a54799c0f028eb9de7ebbc77f1f33656c9d3f278e29933cdfc02fdf5a17a78fd6bfb6a7bd1749413f9571672a692cf870a8d4b0f90176bd7b73ce5e9f207861c02145bc14b250acac134e2813ad0f86dbbb5bc7508c9a352b5bbd5cc24c146c37d61f8cfba9d53505a6ba342d464b36f7f19bdad3252bf4cacb0457f9d6660f533b644f4a2500edbc50e49d790ed8f17806fef15e0d7a95b84ab8bf316d1e878b91b2721b4ec2337707fff32e2df582084b9c526bd45c0db4cb537ce84bc6e5997399c604ce63929445473876a9e1963a8e8c30c2132a8fc8c69f39017883c784e99c176c3205038c67f9a899c36a9bdd14177eaa129a5fa49d91246745cf7759c45163f14cc81421974c987cdf6184d1277748793e49927f35bb62e3f6f6a800bfcdd70cab633bfa845f2d995290906e4a337052d7f2d4811f734670d04c5fb5a7aa7248679e433", "196f85176bb35d434d2a909462245a7bd6d16b41f9f1a6047bfb0e505cf91bb159e646c05224d309166ec81e64080810952737c69d653f0e8a452fbbe87b0f665d5be9b2e62da3d12b6f2711cd12d5e1e709b0774d8a531de88ae8f8445224ac2533ff7dd216683fdc92fa9ece9ad06474d374e3fff5021dca466602c870bfa9d6662bc98a923e5d978edfebb53f37b546484d497fd9eacb89c979f75099073a491003ed47e179593f10ae6483f8dc9edfacc7de75a424b989a398efb9e5ebbc3f16613e2f2ba24983eca7a14b2f6c7a5afbab3b379a8d60d9602ec5fd586bb7badf39360e056930669a7faaa8485beb79db60db81af743f609ed33895e1afed83b5e9e93765cb1f165e474bf4de0bfe4c174a3e6c2b54061ddd7e6e09e20480ac1a89d248fc6d2c933e89afaf2ac96de06f8113535a900b6f0ad31b33dda718779fbb724388a4dbaca6201a14fd7558c1bb5841afe27e0d77201aee573c8abcd9b6ffd045caf210e5402bd18f15c778508cb7da6d98ac2327a7a66b866c7f0aa8fcd9a1e7c6eb01064829cb6479a15383020af1576fb673ce8cc2ffe2fb3d88559fc4d2b4905752b811b9344f579f28b0d353523e9d086721d580b7316a95811f857632e96ebcbb40648e38c1930559d028ed88f0b53c5a55f36b1d9a1c9b602236e8d91061a6f4bb99ca445baa13bd64be05d2f645bc660d51683b14fdf76ab755cb1d3ba8d373c9efda1fda605d5bf66908206d0d49ecfcb39acd1d8d7779628ce84fc683911dc2d6182311a5f3386850905f9822804c398be276febdf4375f857e83cf13c1b223dded315f65047556030338cb348fbcf03716285589443d5c8a318976984e1cdedf73e57e4c2b0dbf323953d23e7888f08a8bd7d1f1fb42498b1424f2e6ff1f81a4cda668573cda14dc42891b55752bd9415a73f0b6e7b0738e55f29d53fc6463c4105e72757d2a951e9b242f8802be60801245ef6cf6850313f14319d1ed485939199db33ee91572a081b5ebc2a35c7001e09c116dcb85555f0cbb84a0f93708ae8bfde8781f56d3e991814769699cb48558a217ab219512e8ffff4a380a5688507bad934937390fe5b5577b654bae0104c93bef9b631caa8f0f0cfd33e1a9fb0ebe5a641ae0081dad67ed5ae5df220df6de7d4669740fa04faeb0552ac7c453ea5db704c7c94085fc1a02527e2d6dfd5e93cf95dccc284e7a1151a11c9de32d7f0100b503060f72fc888c41a5e8511eac130589772bf17b70abc786134b0f5f4d031b2f53cc76847ab8e02688a4a89d5f49a2aa1dcc4b78b43e79339da805daf4d66cfe8418caa99c41420dc42a1a4062043266a41855d3a12cf9aad6445166a46709da5d1cefaa3c96a85e1c4472185d0ce7c38645cbb2a47132fde236c9ad88b99e478f4b5f404f41b7c47c4adbd2467af2898c2c9", .None}, + {.Mul, "-ec1a0d400259d20b86bcb3bd3bdea317aaf5fb639896249cf896c9507cac5cbdbf4a165d73019bd6cb814debe490d1088eb8624d190b85c02ff12c823b985c996437856441012e5846d9916ed999c5f8ecf82b0846c87b25289d0e1ab2f2dba22c839a5278eaeb17d1d6a4528f429183a543a89b591ab458afc252ac114dc6652ab734f3f919b02abf10a88e63a2e11a137f141300828a446faffe7819dc636e75038544b66e9ed280318c7a5f63959d881ac9f16de3bce3ddd51dc10f7677b3d7e2e5ed137b315a59d8a18cee1703830f5390d407c82e107e0f6e54324f53a492915f65892f907a8e01d1deff79829756668bea1bb037e4c4b45ee61fdbe9bab60b71c36e2be28ddcc7454b35c97e2402d59408e2723d3426692df1d8da1d1b49f3ce5762cfa005660d3b513acf15c5bce14cd0612426c81172259d6f4cd00bd1d748505abdc99b95fe9f4e5f2357ccfb94b2aae3fd101c13e3dda88a8b6c86a5d9d260e26849e8c98869206587c1083837a67911b49c09ebbc524754c9da170b51cd88fbf24b022a55a2d0a7dbe28fe9bcff5198fa0b8737d6eccdb5a38087b4236ed8313a7c6673cb9a6dc3b56a30901fc62026de1ab46c20a774e84c248bebfc8e3dbf57ba115c7e4f26c75fb94f01f3bad2b56cba9c5aa3bf58754315cdf4a432594a814e453ac93111ed0f77a2bb9df1d73b72e0a8487fbd7eefb0816a", "3c21313522f52ec48bd22d6d39f52dd04956547a7021b4ec2ccc552f957c084b4b72b346e43b71d14cbbc15d65b807492919cb186fa4bbccf196a98af46fe7f1507042506b7eb68d5cc1a771cfb8ee4e06f89b12a93874d3f8936df918ff4714cabbd1e758e6995601c690aab4b282dceb45444868c01b0bb4c18a9b7e6d0d0a8dd92a2e68e87f837e60b72051192988ce7f39ee29068fa229d2960dc0c5538c5c7c55881d74fa668a78f7d867adbdc0590661846c8a0a93900b3f42c7ec981cde475daad335ee4af3693fadd2d5f695f15fa6c5b276d2dbf85b305c37319ce7c35d85651d93a07472f75bd89938cf12268c120c4cf74b9d778a3f6ad2e6416dfd3def0940e86c2b66459f358e791d679ecd6496ca11391c08c0f1e624c7dca0925e6391a6d8b8b5d6000bff0b37dce2c5c73aa1246e77412c6ed7ef5f2389458ce11b6a80c284a3a09268f8eabf64e83db949676630049addb425759b85274501814a54fb2d516cd5919cfc468fb4e91a3d94c538e597806a859a01c03427be91bf21d41b8d99750b28b27541300e2753d8d1125defd1f70f0df1a40759816b7afcc00e2befac57e97cf54c02e2f1ffaf852813e3f0df3bc425a207382dd2ec7c26f239377635e011ee0ecec2fdd38269c547c514e90d620c3298e12e47952ca69ca1ce44e5236a8904f2ed727a0ca7fd946f200b60734130e69317ea2b5e8e", "-3774b7d8b3f8ef5596b7195ff6fdbd97c0f33a317bba04b517aca0144ccd94f40e3362edfe5f0a2abda3d9ca474618e1ab59fd7fcb4fc547337df9989ab7f8450133e5b201a7230872bb9b59bee6e156df809f37d6fb59d0ae2e548ca1b64ba6ad056afc7ea64b9d32d05c5dd1fe914f42512e31c1e458d761ae08a1a6274ef1b8aebdf0c46d9801fa253cc9abac636e0b6e2b3a7a461a131ef38ab98dd2b053c41a7a10849069da9b6c539755da5eff73a159aa9e00d04c359c482cb56713ed3a53eaa697d417a20c86243edea7cab9f08c68e917515a57afb4f6eb58934936f0486ec8d358d25203098117828b6aa951ec19a39e22a5c55ec1cacc6aad1675d8e7fbb59869d0f5d0dfc30e9401b3cfa8aabc9f052d7a5d7a6d292bd6c15193ab3cf184e3702fd0d47e6eca5501214e04e155182fbec4866bc43cae24e40ed226e8eda81e5d5f1a4081e62fec151b8cb6f5fcef3dffb02245d2ab647fa2183099ef791f8aea53ca83f54e532c07fe86aae339b199e4298bafc80c7c3841df57eab8e9601fa1982bb0ca4b1b47fc920a4e59cd810107df93c9a8aaf6e64b948ee0406c564e72812e0fbf9046398aed33981f4cc8de0e187c8a785de45d6e0986f7985acd006731fbaa08a46a8aa61487ce030b8e756ae6a351d3f9901822f121f54e5e7494b971a441f72d8c718dca41bf1827e1852a1c642230b038a0416f3f288309df1431b4e8980deba5ffa948240d91c845b62c80d3d7838f75c3cad85b480025bc30f3ca727c20d16c1510eca2822bb65adc28c75b2e1bb36b5f476e8ff8a5f378963d2eb0bb1fb8d1249e62e11a42098e873ed54d472f9e9701024fbd5e88c11b4ae2616167a6d7fcff9bbc6825f56103d36602264bb2e85f833b5fe4b85c8a1e1096b066249d84a697424264c80f680bfd6e53bd07d79bdf31454e918dafb496f2def6b1e3175f72f2e72c22a3389f5a12934289341f76a4a4284fbc00fbe85765a53a4f9ed2290d18b75fbb5dce514c81d2fccc37975338f390152c97a267d217d90a579f77fd821b825b59a767fa2b4b33bd6e30cc28376b569ac53b7ef243ea4c182ee59c052806366d636365c964f86f4abcf0146b6ef68301fa03a3f3c5e550be176bfb64555e15392c1c9a4c487da9b8dde74f87cee23453df12869e82a742d2c579f7387ebdb53ad807dd9fbfff70ec5239d555337adfa5fcf9687d47c1c7ba68d8da7144d59521082e2643a075c453eee539fc42876bbdeb4bca7e9fe711324fa3d065fa3dc1c41f4984381a7def6e6806a70cc01e806e11d6804fa93c4c68f9752f8cd605adac1818670af513aff8609728ae296d4d94e3c04fd46c90694b758368dd46c48ab4f478c8c29803d98895451669abf5858a3d6562b4af2d5fdb79dd580f255758b4c67eedcfcfdcb92d6e0240cfe2643ab4cc", .None}, + {.Mul, "-d41833de619d251456ec18ee7b2ca671c18754456aa257a3ca24a6835e7cacf9883cde4a684e22e921a50225b7ae2351acdc762e1a649854725bf18c8d610db47c56139d2e7a574b4ddaa5e1e8eba8ed0889358976140bdd1bd5623ab6aebcfe6233a2decf7662151e842bd5a4b7afd9df73a72429ec80e8f5a4eda04cefe1f34e199a09bde60888414ded341049567fd0d1b87fb48dd7ef755c5c8f9782b38bff09a80565942fd96ae8065c66b6e37e67f50b374cb0ddf7937924c66845dbe047f2284d67a874fa8c7af4546d8b55af42e93cbe3b95ea1c4cbcba90525d03b6e75732de9df92f777d58fdb7ebbb9e39ada87349342787e6b059c2063bb53b52bea440acf6131720a030ca44fe16454e1a11ffa96db0e40abcb70b937e2e7b58f7457da2105f6e3f6c2ca6406485f90ffe8b195bc965b39383a66afe2c1ae6335cf1291278bca19e41bf954466601d7962a744d0e185a8a01e55bc6cdc5c178b4aa2a8a55dddaafdf064531649f59b13c871a27624aacf98624f8aa8932e4aa997668bd138bf999cb67c8b08ed4fe836e31d91cefafb23ede3adf618d33855bc671a076d7d1e8a8087f267806cd793c6ae02808648cb9b8d577a6ff5db1569e38b48b2d7e299175a9766bbd8fd4c3f1cb0b7feab8c87bf64b59f2b89aa9ee5d6b07cadb9a8645d052492c40f2b8d7d92e9da80661817540ca218c4e6a4855039", "1c64f0ff2bc4e7bcfca7a54a1075ade2f61941e55fbe694fccedd8c7f64ba8fccc505061171936b6a7c58bc1bacc386a041e4f75cf2666a44e62f76a7baf46e92bad7ac1ad7d182848c7ef0846738147d540827a3141506623795d9f2bace41c1a7d70352488dae5141a644afbeeb49f56adcad3f4cd1bc8e69b046e4431565ee0e7d3779f820a62d9abdd655c1aa5fd785f38ad8ad58e5044a77cd2aed9c42e81af4c586adc41cc983f017e431a7b55a4bad1d0fa602ab932e1d9f36c267b9a27ee06cf98596cca9d10ee7f8a3ba9ed3200e19b8b7c7dac3d0e39604af733f65256b733ba6294fe091ec083e6cbe9a3bcbad92663e71ae1860c3c2ad5b906f4d50b290e18ff8831c403c6150ea6cc0d6519bcf23cc3bb4b03d503d199fc2d5dbe550777872cdbd005aa73fb25479b2e6be9bd1e00945b808fad617dbbeb93b365be5d7362925a157d85f86484b175bed376ad4e08a573066ffdc73b3eaa128e5eda3199b44484319dfbd000ab313512efaae5030224fba57c73f3671daa044d24fed13cde7addce196bb8596d062796cb0384cdc5a4bd9ac5ac6a39853bd623f8c53398dd2dcc8084e65327ae66015c750c8be4a9ba513508aba779ddb5f791c0b145f6c1b677a977fd77ae57d5fc976a58c0052147a896cb524ec76701c5d2622bfd7fb92930fafffc17ad41700510370d9442bc11e6357e7b1480cc312fb", "-178646caae8aaab3be4d626cbd6ee691bd7ac5ef497a87a7f39b6c825d1e0593ec187be98888bbe23884157c0c659918491d22701d3158c97f1ebbc35894201e3d4115d573cf517b1d08630d15253c98a96ad22a954c3accdb0510388f2fc7966a1cbbf3fe6bc0b87da668a746d83f3621e4fdccebb65d1f62d0d82d536a99c5e8527ac17c909c96ce6eb591a1bb30db1c248485a92a93911110f097339e4988abc8f28b27db97914f205f7f1082e0d2524bfa643f987ba392f5ded581dfc4d62464bd17e5f81997a527e405601edcb2ca3e98b863c21b7aef14e8c5c6b7a6463e781f2aa40a1e2230a8a709e1d74bedae5dfe9bd6fb1e6d96f5428d717e8cc778a48e2cf0a5f98cb8f71444f1dcc4d8748eb31c3c0fe6b264f5c4398346433340e4529df96714576ce808aecc3e42d30d3557a47ccc8edb0b5c0e5e0e7a80c5ba39d24b727ee1405777b51ffde41738689c2743b831edd46a4005b24ee85e0c06165f82a70e365b1178ca35d96db5cb0ce781023bb1fc895c33720424591c37101b10d51bcf51d5fe1501f70d0a28031282d8451c22f3613635ce5887074f8b61d20cb77be738c336904522554835551e2b6924cebef66bf5251215de2774d03a4e376bf6118df5feb993b6cc4d3c6f9a96bddd5e86af23d5001db698c2db8860368932d81a294dcb51e23014808fe6acafc1ed32315c5ba77e09ffa4ab3b5de919abb703a4539b2457569b49924f3a77e42f30e3785835306b1e662af71ca5bef176ab8116c7f424c62112f940f62b8464871059110a69ca9e639f41f36d5870a3a5da4152eb7eb4a6b3d2828ba2025f58119733fd6367a9c3a1c826db1ca00fd0f5950ad4cf196d21ceef7ed97bc4b798b280c8f2ee83d75b31da4708295b6b5ef82d636c9073f20a04493e6dae1ff5d149fbbe710b7bc0b2cae37b6bfe81bfa57699c9028807f79f590a8ba21f2974dbd2af1d7e792ff67695dc760cfe986e3de86c08ffca19c80c5069e5ef89de78c056a86c5241ca68ba3dea86aa63ff4ddb7a81415aeefb8cd3cd85ed4f134e4a39d3aadb56b93d41bd6f7600a057c31fee8f6ad5bc23ccb2a5211549fab1361ed24f6e4cf37c9df3db559d9afda4a7f6313cc9fc9033bbd1c64cfa94349d11bc54ef32f65b88b57784a956263711eb424ba46eb97b753f439a6b8fb12ea0c09a1755919f881733646b5467928a8fb5c69d7ab22a7e7e0ccac1f8c6760b390133fa81950103f8b0271f3a62de1e761ca56db9f2b343b332c4495838beedb16293f32944c26ffd4f7703f25db2ffaa06f2cbadde449e5c22eba91a6b245281edbb4754f654bd77907b6eb77fa42c5377204819ffaa5cc42a722d5b555ac144181fe8bf0e34e6be4c2a42ee4ae249ebd8bca699abeca63c664f5e5de7e35459385d6cbfdf2113d19abebd00b75c4a9e3", .None}, + {.Mul, "-fb5e6fbed4868a4ed491f437adae3e7d35869a4da3cc7505f204a37afdff0a1ba2d0a344c98b4511a6dd1e958204f7d012d7654b980971a0230d529161d64a2739eed6e55d31343cdaadedc18d18ef37ed180d6c089e838df36baf00383ac269a5319ad5b9cd60fed210bbe6121a92b144ad1d4eaa064bba5e84071537a7426aa8ddecc57ac4898393d73ca6d47701b4bd079bef7ff57334c74592c3bd68d70e7ae9f70693749a55d9afd55aae680d1842d1e24537b42e4814fd3116b286720e522ae887ccfab297996d3e6314c3a682aaf99a10ede78a0024455ef93d408782d7350b82ef4becf9dc1421461708dd1a44e96ef0cfe0f3d11ea144b7014950b84447383ad9a7c970916cd7d8b83bbbc8c3a5fa2bcac4d8d61f9534cd216094136ad0e426b24d78c26369e4283ab2ae56110f3c1ef43f12c2b70b828e792852fd1489e4bfb5ee3b0a8412542a5148d2345482fa961d40f6649ed1f62bf8b8050f03a9b3215bd8cf7f7660cc06bfd08aa76320ef369bac30d1669acb2ff1cad5eb0bc4193d8d5c14f8812c22c4a794c292c9f7f4b820b09a8d568bb2ce98057317bbe5770dbefab2a765ae2b79f453b203750a140d97c631df0d7b058536577b91e4e06754f56e1f55b2a3d9543e1e31c7fc76409b7802d47d18dc29a8b151c4668e8f3bba79f6c0b1ed206b386fe9647dcc12ab0ff1288ffd17059e6668262de4", "112ee279a1132cc8dc4996678e53ae6515cab4df166d1fca20fe03e10458272342a19c7b882fbefa32716cb734d78566c63363d2e5bfc1ddbdd3f481911a8a648e718ed5220e7701dc528f5f98fe0d18a1b32c7345547831393a5d907a39502561280bc47de43479819f3942fe51ba3be656bc001ecfc3115b50f9119817aa81c7f37afa33cfa85adf812ea8e8b56b511a952a4b212483b7930128b40a874c3f7aa0fd564950e0bae246f3a3e7f37de0f713b91484e82c2a08a82d626034f850415fe3be35163033dfdcb34ad9cbe898f727e9733598c4ed0ced3bafa9242bd663078e9b1518cf68455252da2caf1408cdf98294e48e322b7fb7aa5824e715cc1e2573954921f6d54c1ffbd6fc98631517f72ade221acdcaa3264329b77ad5b1073ee3849f0127eb105b677814035d299d96206fc9f4451cb819be117dd69b7e5320287c1800c32ce2a37b1db1df6abcc9a06bc8deb6155df0003e856711fe4dcee3680354b983015168c7b6049e22127da62dec9aac415b4d6427f77e38487fecfffa4f104d248ea347f8ccafa917c2c56d32aa04f8bdd583b8a29a07e6b5755eba6b537970dc3043488267b33043aee006b62b355e81ec43e006062811ab636c3762d9ca56fcd36a16f7a201b91a97a74677ac876791d418cf9815072589f3872fd9dad043fbf94a55325c48cddb5b84ad00554b1226f6af9d3fa7cb20e0f3", "-10df4ec48cd9a0701414c096c7d21504cea17592b4de23fb50f9c2ecd935a24b81936b470bb2e4a10cb8252064204efc9d9b9cd28a27ef49a5bb43f969564878805bdf50c6943b715365069bcaef4454c736120ac88b28cc1644ec5be99b98a19f56a446712ad401df7da0caf6d863f36082b53f1eeb8efe343ec3602bafe7939b91ed381b984ab3d9e7552342ea35f3354315d0fca82c607178825894abd1490ea9bbb996d193c8265e12ecaf8dd1ed96ac8311981123f56ff8c98fa427e8a09b03856b9b2a670198eecf6aa9973cf51609731df1b171d613e34d5f7b8b4142f29996bad353d718561f6ff4ec0645f3c4dee543302267cd520b267b9ffd095881d3585226f8e7adbf309ab7a0f959891907ae7dc44021ebf01d92192f458d0632f2936c9c686a6a9ff84e90f15eb4945c62de18f3dc2656cb09ad3ab604c562bd16767c46e9ab610849071d285af4f2d8c9b7087fc5277524ac2e77e45f06861c42d8251479077ac28e1f905908708b625c063e9c015982e1fa2dbd6f32cae115a48a54af36385d61f97ebcb9ca4d23ab313cabd101f09b026d14b9814c5552a2758f1cd73ef33b0cd57aa74bf6aac0177fc90377f5968a76c786a380ede77a3202b9cabb16615ca28477ced8b1b7cba8bcd6e22ae2deee5e4724a1026d41dd661940f244a2659f5e15ace6bb369d5245ebe37ac3b3d1d50d865e84f1dd96a99f25b26f699304146980202c0f41c91dcabcf2dca5d951b314c7454a5600abcca2c4d6dea154ff1e75d693d0e2761df3b16fae0d3585c3fc29deda08643c18bc2fb8d12abca1e58c1ae508712d9334361006388a2a4a41659ce0c2ae5d18ba3eeac517959683a46066d3b0c5483d9bc848f3f8ef7081c20e4d5517449a719f393da346e197d98046e518fb466d775af8a67e0a8be32fb200fc74fc1075b840e67394a994e61b73199a7253068f941ce6f62acfbbac63e63f35f24dc5205ae69b7f7cb16bb8312a61125a46b20ece9dd072581dc7982fb3f438c799f556619a1c94a6e148b2e241c82437918ae2f010d163d8989dc2f83fba14a91b03c258c17710b4f4d93834208230db4f89005871233804d56cb9c01fcfcfae787f65c9ed354cde3fb73976e8798d484bead5b8dfa584ad97efc3114e30b74ba4a77f97f372f5a84a1e1cde4fe07377318c56f56f4036ea0ffe3a565aa6cdff872b2d4f4ef2f52c01ab7a44ef87e3220760f9edf619821b701d359d372e3691367b24b6bc25f38bc83ac8884430cb1c6423722a49f50775b7aa07e22013cc2b45ec731272b1911ecd9935f30df40d0fe93f5d2d89dff858d06717c5e21682c02d3e95f4f39f58468ba244162c90d84eac916f738e66beefc6e5598c56f6cfcc0d84d4cbeb8591d2eb77038121c0c8af92995dff21f0efd9f7966a8fe9011d594d3bcce50f6c", .None}, + {.Mul, "da65fb48d7651bc1cf57ddb8e4b49ee574d00df454d46e57bcac5119341707e3e04e6bcf52c5f20db51da8e0feb68a635906a756300f9bc528348b37552ec5c4bc4e0c243bcc4f24fce7f8d28d21e2fe21da8f02143185be684729d1bff97de4477e6762163aa14c18c4c5134227921645ee3f305ec66fb33218a5e80dd8ee7e96e0fe0c7117e75e43ef5c6c494ef9cec7e22f81a7162ff8092c8591891956565f69053739281adcb65a1236c2bf4891358977bd54c11468789b47e9e8b9c8db38eebebf8ab474701ed5ba12449a7c9218b9e9e93d3a36bb6b94b18efcd71cf7a7774d98cc5a7e79d6b46ad8c54464473b82e99041254bdb338591b58106b5fd04e86d59968ccbfb56359aa2dea88fa980fbc8e92f2e4469b44f9df2bdcc34adb28771ab3c4f3ef1d21c4e3ba0c552cd518b90e37f1816eb8d463c7aec65d6116c192041a9d93cbd831836850265889281ce20047ab3bfb797f7e887b41062f96dbd3fd146fa168812811c6c5fe07342ce1359fc272b4c8965f51a35fb35e53990648ca212263cd4e0d65b88987983dcc7525a27a9e692d5d4ea8663e532082e3da2f94b117bead8aa6e0fd0e1c56b91f10c20b7e6fcf186fa512acfb0f351bf4d107b398af77a3b500eece6d3435e0701f3eae45d3f44010322ef7248f27b8cf7f5ada90cfd3b71acaf047f62238b5d8f12f7c152a39f7d30c4c4b504bbb75c", "5392165669cdb008e09c46b106399a2669d5a0f2d92c1d1652dd8ffc2c77b7c7a97466039545c0fe8baa48b0d5899db2b995417e43f64e6cce305083dd1eb6a01cf24c11074ce2ec135df70b202dc160c562a138189d8e9409d6c7542966784312fb60e194b2510a97611a48ed93e9ffb371b1d5908fe8ebe2c4cb17bd026f00de431b1dd8095e5876454eaf702d41eae6c640d77cc9b684a699968508a3d0cc2636eaf1fe8bd547e711e91820ffb955a6aebeb8550584b4dc89c336da2ebb3c7a727399ee3c3923cfc53e023105e7c4a27964cd98ff3c22d6d5a28695acf721cb9e83e4e40b2783d61dbd54a3baab18787cd6d12dc30d55c1b20f79cdcca2c27496550a87d9b72d6739a9c133f57da0e915935c23711e2bb90a102de0691dddc6328eea62c1e7ea68abef06226e2b208c6b4c3aef83985c85ec603561bb63d17dfbbc19e2aa23d1d1ad8aea47e272d100248ae15382950c4d66262cb3902f9ab210006cc1c16b38695fbb8b2cd70dbba0b1e10f29d9883aac56d426fa361a582d3502ba06e8985a63e3f3f01715afe5617382252037a7e29169bc20baaaa0f80bbef9c6a927e5a52f06c762619ec58a663c16a361bd96a4491afc8e8106a51bfe85bdb76e3ecdb4c66f70525f57d35200d6f95d129c8174e1213f576336c0ae65dd4d7b776c605d348752d8485304cf7279c3516ae41eb339c5836a317f4900", "474bb1b0697e9a8d805928f6560b78777cfe6325a40c912c962adce89503ac65b55b5e6fae237d05ec2a78b8207051d8ca87e7ce2131d9428be49dbd218a477058c7ae0f8d8a381d003831de1e28ed68f7364b5db33f679f2f0e6cd78dbfd0402bfe5e1b9990e4a7ffa549260d351aae3e57dc75a275a3d791f84b79a7b8aed77f5ac47d73dcff7b33687bdd94b439d50709986a881678e77393b4233da82b33c4961f96a3ab0541cf5daf60fb44b9dfbe7cb6ddab4fbd277477aad595b684dcc41f6b353c8d57b11241c3379443df87857b1efe338dfaac8029985cf869e3a7d36ac14dd92aa0701ad08d044584895f2d46973958c2b63cefca08a4471d48d55a367817b82256c14242d5d2561ca2bf443f3ad49e884199a52be7009461175c2c7e3b76fd61c567d27d7d6f2b45f0baf8384bb94470aadd15346018eb9053ca8b41a33e3aba2693344eae97fbdd78aa88b60fb90a23a214f46e2c7993638af8f309baeb62113b33100b4c4c9d427bc428004cde4f975bee6e121c369df6ed1be5c76c271b595fde4f653d039add6416e7cd54c34e557a7c644f679a14d6324c7c877309aad2304e5a0b490a4246dcb8612d150b350e67c5d673232212a2ef8b5e6c91866e9813016c2f35b155284c7e6c0d1d765b024d0e60d3cf05ecc2660dea77efd54e2d3e2cd4728aaad957bc20a1ad260ec8500833e5d9e5ef913b6c3b022b0ae3f577eb2753f472aabc179fcaf09570f79f722405acba5dc27e25f1e9ecc77e8eb864b325fa502eef65ea961e679d2f283a4114a8fcf83ba23ede1d8cd07f90ae9bc0691a3112e94a23ecc26f9a0516203d136f3dc09abc1cc066b6f89a32607518dbe41ddacafe6ef1b9940332a0afcc5c43e322ed90609cfb0b88d5fb4eaf924f910a07d1d65dfe328d356e9c906690955e56cfde72f60a37a5c1db44b1aa335b4c33a6476662d14a5ce49315ad3386773987574ee2ce586e8e5c44daafda2530dfa9dc574ba643b7438c83f4e1f0363890045dbba010335ba25350878c813548b689e8c0e32d8ca0f781dfa99570b1cb73d9896538fffd78a2cdba0b9c50111f29c6603717fdd5802864fcca73398e162b3e4fbcc31b9e56e4df10290d50c174e0cdefbfe238d949a24c541cec2c15b05ae36dc756f92ee967802224e1ba7e9057107f8eb6a014243badbabe6ec5260f8110bc450978a12da958c221c7b75d1a11f9794ce2ef3263c597e857e490cdca584d99c83f9e38da4e6028d1a6042a681f8af961d274bcb624a379fb64022d94ce768712b2a15837f7c0512a20ff99c249a7e79fc7042b4277998984a317dea83af7a549e3029730cab786ee2d538ec009a31d085e4f578d179f41420495528da116fc419d5d36bf5e287a902c464a1c03166f00d1d97da65f93fc4c4bac9e02161027f226e5aa19ed3c00", .None}, + {.Mul, "dfc46c252631a9167cdc7e0577b94c548bf550770ba5e67fab73a2e2f30b09e424b916b732fa2279871cff1d76074d68038adf01c4ccdbdbb8328c0dff4fbf6e2dd746c84daa1a203104479cef2117753142bdadebdeccbb32f9ea1a07d0ef7eaa106e423486ed570629e62560dc790c455a7a9d7587e4cd7343e40139a4580ed88e593f8b6a1c81dfda879072dfb9e7492a4ca117d5fb9a813719dc5eea6704dc5316b865ee427eac9bedcedb43d7d766896723423cf5cdcfa6069613bcd68fbe845dd508d3c11e8a485dbc207ce9d2079659dc6a049aa377d21f87f8a51c823d2c8473aad562cf64a335be2b6a531248f10714db2a95b0a622132783553598cb33bd6de2150f729c3fc73f1ce58452faaef16c7a143f99428f5069a529438d7d7b800d35433a24fd63c8a5cda461261623c94879b4079815abce8d7289f82f703224fa5db3838c522d867cbd8516a913b67bc6500e49b57bdfc22960f6be6c016e96e18ae51b3f2f1a42bd750ebe5f2012473d705bc529ff906795637681ba34eba43766d1accdb0c16376389f100cd8abc3f8ea1cd02e35ac714681da1af2b00e435ed06dbe3e12d83693e6ff4da333ac543114a3e025731d9686f76040a2edd543c93a32a2295568c220dc00dc576a48714df55d5332bf2d1a91bce4bf0f23279ae20756bc0200491f9efc8c63516efb682f2bda275e493d07b1e5eb61ca", "7429441398ee2547d1d07e39b0de07d00e1d9886d62e861552d71a84043854e62b569298343f455f687c6e11f5a82bbc245ee5da9b04304a3cf03ba44e32807c9210ba15f1b8f7dc0a52acb9d688c5066cf871f88764f2223886b7cb4861e29a212e209a729a342c9ee456f786bad9f66cb6bb3a99cc265706bb611d0a59f9e2e33675c98a9790ddeea726f38ebc9d45fa0e8f25d08693769975e9de13e49fe9926447a7d208165717ad4d8689b2491f5af7b157b51c81b78b313b56088e0c0c9a0d87d693194e76068d22579fdba3b5922a7f68524d7b6a879326773231058cec183342e7e890f799fab4b2f41b2975c3cb4ccd43c897594bcd587534175a99122004c74834ea0d2ca18e1e2e1d2554c00b2eae2a41d9acf13eea97550d0a5731ceebb630b59585ae0f9dbec85bf03fda466b376e1a78928232a7ec7fdc333e3d2b5ee50e6f8eb3b00a8be245b70b5caa275fa9ddea998b3a7ccc19e4d126b153231daf3850a9a7c1254970ba58e3a56d59aa0296f215f0899bbeeef5f8d4093cffa22db1c1c97dd9b0d82512c852f78b3fcf10c01eac57910cd8d7a5ff851039d5a63597d727634c56b13095b80a12da872e6c2bb2036cbf15793692246851613a54242b182d89cedf16600a103e684447ec992bf72a65115340745dbe3d05572f5c8b5a7663a9d8fd4570c2a875dd89022782c3c99bb0e624c8f37a77bd32", "658912f7753c4ce20f7f63db1e25248bc95fb322f53588e7afdcc79c0692a1e5d7465f3e43f1344dc8dd18d1c299307e2752b7c0b52b857fed73e1178c5480f018ca56ee0feef897d92908f81b02d4c02d3317f0c935914d6f61e9c7f82d93a060f665fff22239569660eecba2054b379f1d3546c6d8161f48715e030f3562dd2ed7b6d41925928134d912507f3b5b542520e032c95e398fcb08f6a4335d2d05b6b943a568c9ca75192fc293db58af371d400f06a545332dd36f4fe5af02fbb8e0ddac8c2cc7ef44bba8e161e45618ed013de93986ef0a17b27802e78962735d47d7578fe535608970c639c44c8d5c1009e578c25a85b214bc74f6a58f2b9eca624125d106a37e5d4a11463687db0b72c264306e76c8b6b647beb35e52fa3483ac50d8e6665f4e3982d805905edb8225657760f6863a4d6afa0fd455b4fa1d0f3a6fa31e6854465e9f8b428ff37169ed7f848f13b5b8bcbe10acb6866a50b71884e53f9a493cb3712b20affa5439bd07ef1b769ef2bc84ec06e8b4fcac6a8cbc73975803e988475959aacb01a20167aecfa2975f55badcbdc1b1c83473161b963d5f9f7b68adca46caa9b863ef55962742a07d120586223da2d786a7d71cfaa61189517c8aadb235bc8c2773fb67ea1ae965e1091e8d855c4005443897ce72570739cd09e30c2c72a47276f04d79aadd23477500b22a9c9ab33921c1b22ea5b90f7ad9c5c14870b792454c3c2d4e831a38e1680bf5ae8ff2440e30d00f90e89cc4513676998825fbe7f487f4c5a6f6bfc28105808ab77b69853fd82aee0c0aa7243789fbbc9e0e1fd16bc28b1ff83870e0cdf03d4823e584c0c2bcc63fde121ddd0bd9aa4fa5f511c2fce90f852f1944fee99f131e9787f9e2ef93d77959dc69d5101e4c78f742e68dc680011bd3311157ee3b7dd9d00f31d826c87663f7da6a1ddb66c17821f792e95771297750c4870f56b229fd3e60ecf205760853f509ff9085015e81886be6da846adb0370819f264cb258b0eae2d10a455a8cd8c3ffae6f22ba37c5ca1cf4dfe53b476674231e5b8fd76c89eec7e05875ed846d31415f95fdbf970aa9307b49c8463b9cead1bfcc5208f79b2e84a48e2cf002036b4c73697ad62eeb28f9550d382621bef7f4c2eb8ed26c56eb2714a557816fa6c94e8526ee4168384c10eba35fa54b1f90fc735a404992d425be71bed392f82282077c76c8eaa978b26fc4d16f7078eafa3f9fa51d875ae13f22c39510fb547cb677766f2ec9689b7f96e1295685cdd9b61f3b2e0704c34327903e46ce7220a5df983181181a07d4f83e3b9c76fc02e538bad4e5a5c78cda6adda60c26d052587488319223342410d2b347b1ab3e934520a59b652d17d8fae48e5073388e6024e21247847682d5cc46a93aa7200a8bc43d7c4dd52bef5c33910ed81719874068113b74", .None}, + {.Mul, "-37daeccb35bb95d7e37a2dbba8469e12e40541d4ccecf60605e3f01ba4637a48bbe3c66735b7ea5677f63fd250a94a02a64af6a6a0903ba99b1af6a4d24183fb74ac239968edd398f774caf7664206dfcf310bd285d5a8942cb1d21ff4f3be8c9f1ec40e5caeea6881e55d3bf6084781d87fb74139c07f486a51de9ca288acd2504f0dc3943d66e7a23344080b9dea7106a0aee83f844153f4fbbaa15638cc7929963dc9516fc71d9b7c68a106d7ff4ada5523bf7b215b54d1cf2d2f87905bf81f891ddc789a3c074d699ae9857b69e39b68c79866644fb4dc81909186624fd4c8b018653c7a4298d7f10fde0301aa19e250edbc077daa0a5b5b2051d72af4ad4dd58d5525952e0ca7d308af5a57fe3e9855d100cefc3aba7fd4a35731d69124fc86e345e1365874b55a0f60ff592229b2353a0cbdb56a753c5d85dd161037dc479686872de96f75f9e67cb4b5c0748f15d021715eb7823a1f09123b75bcaf437beb96fb0022a9a2f922f9a88cd42f01b50bd83beed16efbb0577ca30422c465390eef380a73e07a77a8eba047ca5cc93093c54553f8c174473371f56477776ded9e63f47c9f5f5a1753570f62f2d12c22d7c014fbe85c906e8a780ae4420ff8750f31aeb181292f62b70fef96114fc73fd40be1fffaa93932e2914905161c2cecb6d58532fd3bafd630df93f4d4d8226537b0b4d970e1480d5eea8bbee70b31", "53abfd58b579c87e38275cb814d5eb1fb8d01c58a85252a937c39480c583a03505113ae1bbc1755b3fa2d4273ab4b0965a3c3cebb7ad19db9fbb6cef3c41fccf4113bdeb513d248e519411d41def229af6d0ab5887c5c4368332ab60d60f17aadae8e7fa677e8576de4b59513d858fdd676bcef3525ad2df5ef68ebd587f11a9d1d99f938a0ec357441515a99916d276a192d03c4c11a5ef6387ccfca8d2755d7b742438d907bbf38b57a915429222eabe059e6d07f2f7584d2f74cec1091bbf48a2171d4d944271d2f6e6a5caec5b2c68a8b33be07787c95015bb1c78e71ab6629059c36165dafd2ecedd255ff0927dbb8d60902af7b320a1936f748f626d2566f06765cef1ef02258e120c7babbf4cd1e80bc32c8d3a98b67247b3e219a0b737662bd069d6cb9b0d2c8b8032861cbe25ac9b0bec9bfd0f0329c273a4262e863d508f550ec30e33f2ee004b84ad081f953611701c63800dbba7d0de988402a05d04c2785a25c9ef2c439fb721b03fd6a0490da5d3de2e992ca2682fa73672bfb72cf817e532f06c2e2da0688a7d0a32a35963f63297ca22f32f8c4222b3331a09d0d0625151b7bc7019f194518488deb24f45d1976b5c8c49044d7d47190bff65b1fa3de711adb8607f4f21f04d893dd2ddb52553fbf409f45702225dcec595d231e50c5008091eaa580b2b957a97986bacde6b54c64ea400c58a8fe8c051af", "-12418148c5074b7b1d913c72291403f6ed629b2d04c5f877ef1239da3e9a4025a3d5531a321922dd58f6d88f7ce632cc55bc5164ae76ab684abb79603fe9fa3620ada181dc7fefd74c5e6ee37f83e6c3ba68c2a7341b9deb9249d10733b1300bb882bb5482c8ab3b1216146516baf9a1cc7376d579e79f8c3c70d887323f4373730c2e1da192f585f06d9f51d0ef8f59caaa4f016b2f597423051faeba9ab27cefc558ac67bcf231296f2dcab9985f64e169da51753211e3485719d99ef1906f51e3970b8eed8bf402af52b09772385c27559dd5f7602ff22c146189ac54f812772d505cec3932b6e4d8511f4d5131957e8c18364ef18783f4db31ec4a0b9f010cc94685aaaaa146ceefc45ac6d6dbbda314fc4202c81977c06025684543b0ab8c27675ba911db111297795b33502a60e996bedce5795402c3602451d39ce8ccd1550cfbf80ea9e4163cd5fe3af7e04fc8d294f028891c020b1766ffbfe583c34b51504ffd3cdd3a6b705e78ad112b8858d40bfa51afe1b4039f89123b1c1b3f7344970d91223570d0c92e1c68ca60c9f6242fb7c9f86f6030c7fd3ec3992ed8ba4c3862ee1ef60294a051496165b930a53898b7e49c235a1b491a2f63bbc7237840c76fcd39a7a10286d47aa630be633299a6f959453904f770721e949e8fa4d4858a794badbf0dc18eca189bc38fba2d77db39bf9b4db35b1d8450afacf2dd21dc811191af06d4cd0765c45164b4d5fc98c1e5e8e543b01ceee403c02efd3754afa0ea1e054fe623142ac243935d34e70f217123e03c9971fa50c30cdce7238d5036e67fcb51a6f3d455ffd75fe5241f110673444677f137fba3d4b064f13de9dd2c7de1eba5b97afd3727bb4a81fe952d4134b669a6c69f815a56a2f87b6c39beb34f94c5e61dda46ac02887450a6eb7160554a6d8408bdde798e35e4b1283622fbcd00cc2b684c9de56651cc66613eb7dd2bc99adffae0cfb12d6d01f9798bf0443160f99a74be28accdbe39e7836dbe9a9e3430728f91599c6d4a4f044bf0590a9c6db95332925d4406eba640a07a8bf6f51454991d89d32373ccdf2abb1e7c5cc45da94d13e11c177273656dcf942ff755dc2d4490eedfd0f6053a27b2099dff6cf21b284facba9f5b41cb15889abec9407efa0c7d7df33d39da8132b38d6e2c78d0a213cd8871f45110c5a99f57c0ad2a3df3455e7a6aeb88e49152d07d972b2b23849c6786be8ed8600f81e24faec7cfa9c7193b136275113824b02303c65039f7917315b126c4a07ffa33c4f295d283035e6567786ed70bf1022c0c614c8a3d750f9583f179c5efa809232a5aa5acb54e4c0ece6e5907fae35e579e3e76682987fd0aa6dfcbf41d41912fff52317fbcac5713a114653b620218779e768a278e17713f6df5b1460578e5e51ccdcdd5492aea326285b5c6ba673b277f", .None}, + {.Mul, "-8bcca2230f0dc980afe20c88ba18022639c809a512e0cac37e4e1866b387fc62628515f91edf966b86f7d5acbd58d9beb9e093f09126dbf619bf053a64523cc2618f113b2897bdf361a71263299f786213fac5845e8fa689cd0898bc1467b613612efe66244343860a875a550b8999f0952461bd4d44e6a26261927d97986cf18194682bab974e504bf90e2ad0c4c9c3871c2d3c8f5fc7bfa06af52c70cfd87aa1dcce5e49f91e3e64aff27e8c8cd1b20eb24d5810fe86685b4863213f1450617e276177c330a06483f0099e85318c824b8006594b7231e8e29ea96856cf09ddb85da7608e7258505fe08538ff63b661d14d83801e6b35153b91b9ad881b90e329ba34ebfbc8c2f28cca841da3c8d8ce748b711ad0b02bfb8678d02ac66c8de00215780f3e54543d0d54045fc8acc4c57aa37b7813d31d03094ac94949ffe59207656e3b61162f34bc892c962d7f3361bb08024232432e85a5985f70a337f71ffafc7d8ff1d46c91185ec57eef84328d30a398dfff760899ef381eb2abc3a6980468d71791a14dbccd21eecda9c142848fef39a7a7a32fe55c43218c1337f4a2cd4462c303e17af1d4cbb58f275c471004678c983f92d3c3590a82b3d7e9a9668fdcd65b5c4457c2a358d1f86d9f54ad00934914cad35c581ea94fa87333b4d5bb14e42323a7092ae7e7ed75843f2bf5419930840821a8caf161f402a4bbe47b", "d6903e0a011c1513894d8e4e85ff148e499bc30fcb7f525640a625fabcba37be241eb76b899cbf0bad370d708f2b0519a263a52b9064ef8ebb5173fbb5b2006d455b43e3a16f79e09990850db94d79b29916ef5ae1ff1c086b0f1ecf0d637e4a98abe0fbc308d59fa2f398ad37c0c9a1fc05215765834b63b56817eeeb163e7b3e00edae9e9211ed540c7ad7744119f9fd4cf032518264a4e34dd206dc2bf2326f4bbe5c07da0c41b444ad11b0b7db0b099368fa3b3bbc30fcb4f51ad13d2f201111a0ffc501fc7ef75de812366afa77fbe63fb8d6336a0114863a2c97320352fd34cfac9d82df3a1f8cf4e5568b595b04bf02cbd18c67c8eb672d32cdabf7c11e0a6d28e2837dbd295d2f240ea531335c6f3b9e19d23c9510bd7b213b6fa0fa9603c83edda5cf3797fec46501ed4d26e05a7ef8915e0ff063bd12efc5721972c5f923ec9ae214562ae3015098bd0c64b4c638decd0a993cbaa3a5bbf73307cbd582c86f7773cf1859263d0bec56246f9548a5626d8fc5147dae40b1aa0d7b7c06ae4b5d5b8a62a0cd7cf50ace1122887b0a96b2b26f21b42982a4ba376dfc96eec4ae16fd5ca6b753d5d0878565d1af20aec6ee3a64c4a558a83a8afd4ff113b0ca881a6d4c3f5889ff0cff5e64d304b1a71d7e999f8b31f075d4d1b6bbc7a0d3f955ec7e84226b57131c198161bab0e55f3f64739de325278d4871a016435c", "-752bd485882bf3bd2c1d686aabb658c5ddaa8d48ddc845e3e10c545010973bd28026a6e1ce4043ff3d10379253835efc131397b316b1830dbfee2756eb706efcb4e2837f5b715107062d3a28f3648f917da7579f1425b42b5ac4624d3f8ae888497ebb58829c6b3b4b97c6c624bc01df068abf30f711f1215c3fc9309170f79a381446e734d555a070725214c0b43f23c21ec5d72c4adfb8b9455d88411bcace32dadcf882fdd56f611856e8e44d8f647646d9fb8d94bea583ad16eb4903c0125a95282078df3dadee6b6bb37859b66e8b4f88858661b94fcd2746c2379f87949bd13e543d6ecd77db885f95acc0a4adfb076de504fbaae34e5f9c51c7470ddb5eaf1074a6f7fab8d7bb5c6cfb1aaa1858eb74a42d475a63fc681dd64bdf61fa2f167aeda4d921066dc32521405b88c7141a6ea66d1a7474fe874c5c0891cd10213e83a2d31da4ccff9c587712164730635e20a9f9065e17d912f9e530bb2dc6df7d305409c4a88bac3f298e59722034dac7b6372cbc63594ae7865c0ef2165235809a5ee500b2661a0eb0fc4a1cc444ecfababa474aea290703815a61b864467349b8f50546e8b27c5c0d55949642c4c03b7a725d87af221cc54eba7b5b7346b35060ff71614de5bd8120b6291380f04d2bcb2769c5cfed4c19c950a990f4dff3852023c7407a3509883f825f312512acfbd706cf5e30957a7e721a75743f95b29fddfb8c118f4784a851c5bbe63d7f2c7a07728ac18cded7799d11e7e412bc91ee10b1cd75ad986f71822dac19b6cbfb1730eb22e62abcbdb4d607e59c3daa36d3e576739850b9376b6abeeb3f0106257d780242c29a45c58129f35fea83fd5d59b1fcb0977cd829c1ade4fa38c8bda59cf3b4de158419c95c5802295a9d7465c0432b7a411505a4bbd51a2c80e841a4b59fd0bf64c0b205a85e5fcc75dbaff4cb39e5d7b4097698f1e3a085491f6bbaaf29884063a6eab0b0c07566b4faa3e2705b320cd221f03fcf16d6721536eb3c0f20aa2dde20896bfadabc510d45af4805da3cea34c5141d98646d357b94936eb7051d567a211efcfd44759eab9ff5d64f10afdbef9531b58a2b77568646aa450d359eb9d8b0d9490100e83fe16b5a77fbc2e4ad6ef14c370470f4f6f26f9ef8c4b569590cd38b8bd46d5c5808890ddb415a01b1dfbdaf8ab781b0f267c3a8029498861add59e843de462ebfeb84f146822aab982331bf24e9379c930d2d10a4a3dcce468fd1c127ed94335dafe401af97b3ba8c9ba187c6dc06189781e582561e9885aefcfc34f3937fecc7cc4eb4d66df3e57c5bdafbe24f7ce3c4ddb2432ce1863a4bf8bbef042743c9252bffce433631acf42583a0eaad0f93b91b0b896fdb639d8c0d40bc7f305b04fdbff7073c932babd52b87aeef649a20566087ea4779beedc42ea29a25316b4de2e44d34", .None}, + {.Mul, "-c12faa9799af82a86cfd4908fc477f2630a6c243b2702e55dd22c07291257bb63127759067fa18197f9398e4f17eceddbcc6b02783b721aa44b8ff368032b856e615d702d030245e4f3bfee30aca8b81fd20eba831a6aad78884cf0d12b6572c291a9a370ad6c3090616b5b3bb55a1b4eb5903553ccf72df8e788ade6ca5b9a2407aff44f6ce3293074fa87308c7d14ee538df732857271573719f7e1ca5a3a9faf083b45a2d6ad778df46c5a630dbc058ca98571a54646f70c8988ac56a84c559a06d8272d7ca6c4b38406f8b06159aeed0dd6ac811e0ecccc90079471ec6a63666e53b5bb1fdde0bd3ddac92b9133ee502885a739067cc74cb733441ce4ba71b0ebb077d213589f450f5af85e7542e0144273b92df9b50242aefc8f5be525fb64c46dfc282e8311069ec734b398cb03c25429bdf7bee3ed8d3ef345763b37f0cc0204b115ff988c0a36092567505ca96a67516d18c90bfb2c14dd55e94788349d581917c2d08fd4cb2645be756262e46b278396a52d9ad1f42317bb91673270570909f35925258a934c6d90b7a9bebad5ef476c344b364e44727ee8ae5bc42c8afaa787ef012933687c1c79db63aca653dc0ab3dd7e579c7b9dd0f70cb6511725ea950bedad9798b1993d7f972dee3f34cccedd988630e88964a5ea46ac0f5172897a05d6f469236a734103388fa99e7805bf84885f08d51ac562ec00b399b", "55f5847c74cfe6d99f59f52d7931d77c2123c7f4966d735a9863fc38aaa7e505f1125ae115e65c0a7ada45c07ba269e4b43c3507aa8cfda3d0ff7dd42b5595e7aa02da3e44e901813ac7d6ae10bdb7e404215a8da63e1084327664e1a2aa6a50f2b1affe08e3270b13495f70cbf0fd1e8dfdcca0ec41f976258537dd17fe2408fb7a79cb492ebf32c93497aa23f826739894cc6c80f6eb29f996fae46fb4cef21c973724d77c4e4d85be75d68fe60a291b870fc0213a08d3ee51cb747ae9b68b60ee7d8eb49783dc23a9245d529f19c8f9dc85e64461a93ddf067a2d21f92bb439de4ca1ea3a845b1a36fd5aff744283e191791b042b80ea31d310cad98c8c847f046109e37f171714c974b8d76c2d56a7ea4b7c0e4634813f8e981362bb04bde2b97897e235368ef3202451473f9fb6836568243e3147fbbbfd4ddee976f291cc07a659a1e5389375aa565b227293e0d71f7abfc416d29727c17985e224ae563d3b23161371772ce8a1949489726d3c0fe6e972d86bfe824ee5df7a1594b91ec9478f27c20d708694d4eb6ee9c52c9377e1c072c6de8eb0970cca6a0cefda4be6177b79169362ed95aa2497e9c47af2e25973731e9158ad9e482656c5cef4535283c0bcbafc0a287f5601767dc78b0ebd223e6cb4bc23745c83d060761120baa33dbc735d6d58dadc18650660bd3adb5dfcc6461125a7f65dd20016b0c5381", "-40de1a3d1850a51396e7a1ad98b2cfed87f568f6a0917b8e1bf50010cc7c5158791dc2cbf886ee075d095921529bf6de841a39a59033be65fdd42e991533850e7d26e7355ce773f8aeb395336629e76e765a63d086ccb9a52151fb0a45ddd1fd19b4693acf2b6645ee8048fc3039beec640bfa4510e3be51690851c43856d6d8f7d9848931f8b63b28bc8731ae1a5df553f67029b448614fbf65b81cd1cd8fcd1ee7601890122be1f16189adf2972d00fdf7e2501fd4da43101f3acdda625dea477afc5eec8f14fd330ace409d1feb69b4dfdac5897ca77672701baa5f3e08a05a8ee5c0539e91c9a37b1e490d5a27e0047a0b1f8630b5fe8795a20b203a44e061988f62d5a3307ce0fbb2ddfe71cdcb7da25b069820c8b706b7d92495bc707cd70af29bcad2242a04e0d4fd9afe1ce128a64d9b72ce9f5e02f0cf09e82e6c07af21622b23d808c325f6c7e5fdabe50434cdceface51a1ada82dcedd9840b66b3f4ff0da73e22860630f1683062c91d01d401be4e4e52a940a30910e3c8b1508f287104fe46f67b2e23953817b614dfd45d4178313795000b0a2b6af0e94bcdc5c5098577227036b98963c1d59970122fe65c4a4c108a0d332bcb248912d76467420ce16fac6cd30fa1d0db326c35c7c61b95a3a1e5b88f08d5e7ba43958250120985f5dc428c0ba212f09851b239c207ccd637cb8b289fb4dd2fb215b6a431061162bdb5bbcc7eb8ca84c23b5e683cd0a17259133e68bc04d038f1373b3a5b67e505aa83d6ff42f9182a4dd732d1ec58da87702d226bc927d1d345459825c74352d73700adfffd086856f2bc2453843203475fa2a6b6b63bdfa91119d6e10605edfb9cd7ce0cf702beadec02487b1e0bdaa6fa6d49dab65886713a16decf8d148b25cfb0165478a49bed5b37ba184a4fd1ceb570acdbe7ee9be00f77fd8335c95393ee5a8d2580e57cfd9f985e18fef42627bbf853520fbc6883621745ce2ee1c506745a9c79c7a0264efc6dfefebc8c3a29e310e30d9b831d519533d167eefd0ffcc8776f824a80f7ff0949d8944d3a871f6b3ab760ed2cd27940c00b0eceeb7c2391c3410b0977a08f422b2907eeb0f173135e6e689fa116153245f74153d9d7d85ef85739b670b2a01409352b43ed4cd3daef46fb7171494aea570803c3fe25d85d94f199bb098bb511564219f72484e479e9d4b52bda3839e919821c02cf59141f5c5fbd95a7b0ff493f55f8d5d006cf262ada094b085b9258bdf99c568d10e4d4043c3675f3051f29b19404175007e5091627d6e2ddde4732057053d9e7e9b0c96abd7c583eb4fa776a2934bfb861970d53e962508c570428ca768cd8ddb9e1dd064cbbea8054aac46a11ed5ac82d17656baccb77124421eef276d42b130f0ad9c4c6d83803d5d4fee85269c7696b4adb04895c4aa54be107e599481b", .None}, + {.Mul, "-5c7b087f66e2110e4cd1a42a31f986eeed9a0bbe17d12d8bc7b26fd048b864cbdd46809097b346a7046ab10b22b72bab5418e06dc833334e9c02d459ef333ee1c310b57f628567b7a9775a7ea17882f3fa59f865dd23fdc8646372cdc1d6c4ab8dbfc30fe633b2a19bb8295323d0601c214561296cde341e9d4d04e92bd2511b582a72a3f173c2da9c9b45ac8380cc10f5ed2a09253aaa2cf9d2d3ddfe32fcb23fce52d945537a1a8321c6f75796ab9eb659bfe0a997e8f2bd8351bbab610b74127491def99fd18e96264957a12bb17a4c80e1a3633154dda1a430d1869a06be51509ced055c3790df53319383dfda21d082082cc00e157436f4a8e514420a7afef8ac2076ce2dfe53e6eedeb0a19f3addcde319a3a354d76cc058fc7656d8c3caa84bf8b59fcbd3d362fea5997a89031c3419c22be13a70c7db1b456959ade92601b36c26a10416efa712843ed44519b875ebe3410a6a092e0f706a003126a602ae813f2bede1c2f49405f208a5df0ec4274e596378eb0c35a9b59bfd3d944512fb060f1ddd4ac89b4d1dacf1c51e4a3658ceaed07504f5a95cfa5fed547ba14488b57f1fc95b9ee399827f4d3c0236c2bb5560b402abf1c54aba99420775b6572f30adc5400adeebc7661758aef027568fdcf7b4f0130428658f8f21314828f55ba40371743f307bdc6770e97a9ee89466327da486340b32127919fd405d3f", "eefc9838af0fad8c8623f7c7c54d842b65d5677bfea47116fb4213b18bb2134c85d4b03d4468bd067f65eb82511c93e005f56c3a20d6253062e1e39bcb04750f1ba0c99f4428fcfcafeb72db248b3f06f4a9b9020f2ac0e19db2fc6483cd82116144dea318439c584f6e126e3c17bba8837b4d2e522c1c41bbaebfa119939cf87faae40c3879c4f0a51a4a8fc097ed6e25906768c6a814ead10e951739492c938f460f27fa037af1be96d36a99c6bbf639e611ef39d4aa1967ef133601320deb82387444694ea0e7d06a927d723d78fc7704e1ee3a39e990c1837127c20f64fa1b81b69e7f6576d92d3cdf582ba701b081281513a657852b25345706b3dd76207d7756ff1d38aba0700cfc84509b38da267e59c86f2c5d91808c68d6558e32c23fde64bc45e3c0ac6cdec8614e1cbd2500a6a8db2458a7b31289e1e5bab9e0c3c2feab10195d556c55a66b36d752a7564c3faf1ed18f61abfbad59538b015664c9ad231d67b0c0b918afd406bf9a584c5cb6967f4a8e1025d78bb3d2641caa7603ce62611d42368746a103c46d935960c7fc6b195f213f823b6a688e216c956d624e792178dd95b96529d8b9142923a42f38b2b2e4a93da0c35102ad127a585f2e46083ddd7c66e0d2a477ec2f2b8e0cb202ec3097b4a3a81257d358808efe7daad27022c361fc07a10de93f4ca798756dfa77cc57956c9b169b58ef3878f9f6", "-5655a2005642b80f505a719ca4388ca4cfb13c1b0b95e1f48353dd5e7e7adbdc0e98be2dd3bc5fd49329fa094a031d648b93dc77fd47cc31a47b3f0b9acea822948e44a33bba1cc82db0f7a46265769e8ef011c6482639d6d78862ea19b45bd3a30cc2e74949f92d586bd5e91d4280ce6c55ceacb1cf830fea933c0ee48957a2c620f9dbf2313b542b4ca8adb286e32367600e075af6c61bd314acb4edc54820b5187dff40837058ab05f6e823aff2b31737ef8b887437ef19bdae50144bf2e738dbb8c5a3fca3d7f5db17c53250f96e91631d9cf39a51ca9ba1840ac4227cf94c9204912c1ac2dd6a7f781f23f17a8d554b8e163f76f6972df4e611340411f9f9bfb36f1333fbf4c3e747154a61707fc5a1c9ee18f49bd88ff7fe8bc74a1f4b39ba0cbf22dbee7ba6b08ac52dba7fdbc99b5ad5d457923f5c41cb5922bc694dff23ea803176ec20524bacd8fd6d46fb9eb9fad0ea389699d0c868a73ab057a004aabfc821e092488e11ab3545276612b616bf3b56d3c3eb37e5e8599d59c3151a8fb4a0fa2987a19429820980b1c529ede0a96191fe6aaa8424c87d866848ca2fe409aa7a0ae63f14260cb4afbc5474e65bde73bbe42557a76399c41ceda28089c60fcb695cc0e233695bceffca57beeed1718b18b5d1eee691adb150a3eb2ac7847b93f7cd9e47dd5e7f313517447304489713e84ff6cbfccfb25ad8010561798dba1be47a72d645687d2f69d152c8a14eab8a2f3fffc133ad6794f86ad68cd5a022c8c4288419c03c67b689f8ae8d256514065c329dcb584e9b6bd20cc1abf711c4321f47542653723341b62f1fde5c0b812f462247e357842c039709fe98c3a9a3e2fb1a1581c0ba8b584423cda4719f29727afe4673f7527d889708dbc5636b10195f47c3429c46c1fbd84e9cf02658707472bcbfe4494f55eb1200d2ddcfe8bfaa8eed0c26b3c10e9b4606312c3df9364451056ac604cc129c5be8eda5d33cdecb25743c16188e826ff6673760182de371c3d139fe6072ac15820dd44f903c1e628005cb16b542d814e2fe0fe0254d71e0ca356f4e49a699974703695c57500154e2e3de3ee393811323c87312680db8dde5d0f747538f9ba736dc8eac548be7aabc04c6b20db8a3006e652ab38db38080a8b6a038cd41f25e3dc00c55efeae357c0f6452795bc7dae372f78929b9098ba75b298a99a27a71aa0e284721dfacdc397edb4991c8d3acecbcf36b9367fd68a13611449d8725efdd5fbc61c3a44c4db9f4b7d50546597b4d81da05057120ff0b774f67077b63e5cad39162a8bdee29671e5fa669a45152c23e1fd786c9b4fd4ea8fc3b6ab7ad3af1cdc2c001c3970e9b844b3353773630d00a2c086bd72a49475263ba338bd55e24929efad15c0ff549fab44d6e01531b2abb44bf66716b23d4d224f0ef76926af7413e18a", .None}, + {.Mul, "-cf2d9cadac94de08e5f46399b2a7bd9779facb54b662ad728cc985e363f6c058e6173f71e58aed017f889ec7fb9cbf862c7886e2515942aa72d4d69f1da2ba8564c26488bed9029b52fd46a75433ea5c0dae3eda462275f13914b7394b65797a4e04ca96d94e60c229b1f79c11443317725def52874dc056b4221a435f1810649a57d80818c191ec383b8d92daee75ea0a59e0129a97793e7c00a87759a0299892d0f7e84ca423690d754f7d4419c0befb55acc6635ad0be4d21544e784b4bf0687e5b6d8cb1cc4a8f79cc5abe63d0b68c429dce667f841a6f2a1125463457bae735258656614a6821882db35edbe5abd61b1bcadfcaa01779307c4a1c57166881c281343d0cb6dd775a3a5e10b90ee65020a345c64bbf7575af9e0e0be6de4c7cf7e7824db1b4c70fdc054a8d271ff045ef60e27c0a7e225e6bcc74cb0be19104e0306cb8f4933bd47fd1b4ea25730d904813dc2f7b3f9ed340214d978102ae2ab783e75655ac3579433c4c6714e5f9ed9f38dc6c761aa4b41a544a6c38fe94740bcc686c94e07e85221d80bf1868834c24dbf551be77fd35602163ed60dd16b3dac7ce4ecbfa41fa4b73beaeea05d9dfd32a4d70e3eae775ce2a1901928585c24399556c00e07ff46290c708834b4c44732b633c23172e7ef0c8c92c4601071a17e0ff380d74087e3133f2197b9c2021fc9a1aed0cba567856b4b97a43696a", "5f16dc0734b5854f18bff751ecf7a12a23e0f0a1b70052038634057b94f24608c009b6285a5c7c46841f6578ed06a07d4ddd409e51eb53c98d37e4f8e233e6caa471251bb4783444532d02d4dd4003a781e7ef76dfbd50a36c9e4dc742aa01913cb59862ae776c074609f96b8edff6bce096aefcef15348fae1b6d41e3cfcaa2381a643c9ea611765c319175e67a74cec0c22f3ffe1f5f8c1a968d55f38a45758db8ac6df91e262bd4ec15002d47a5392c60839d7b8a3745002a643a434bd43e2f0341b55380eba69446bcd8692f59b80b740450e2cb77cc8caf01149914f9acbe2150b4e2766273a16e6c02765f5f2f790febe49b63a73d26aadf42c1e2795381dcfe0dd5185c9515dec237da3bc670cc7a52b56b6ea5256f259297d884df76ade092d04238fd0bc227f38db5118a00714466e3238c487325c2fd5ea9ee65d2f4e14f9484314ac4a61ce67ed9bfa78f8c1add15213734a719352e2f98022e3dc526ee2cf2f9ea83ad4b9e8be686217623f9c5716070cc26137d3c32e572b097d5368b3ff3466ab2a24c3893c033fc6c23b01c642a79ababc676dae6217d64238e95fc9c91a3dfe3140a5ec88cc497a5cd4e3bd31473d6d8810c665d3513c924d7d30f5eac04e493a069c3a77d7ce2036464b4bffe0a2eccd2bbf9a2312fe29274082bfa4ca86c7eeace24fdda28eb95f7981f5b9b478b1c1da904946570802a", "-4cf46d20f184c735cc55a44ec93616f7e92c291dfc69a4458eb2f46690e9a1fc189ff13d92a75cdc8ed116bccc07c015012aa4a16e195f29cd7c595d72a1b431266bbbc52fd858be094e6672a76c466a10d81f6e0447ba82dfc14e7061357718f33772641ada38b8617f3b037601c02973353030501bb9a7e488ac67f2eaebb4273f73381e6d8d209085b47ec016556c8fd0a1ab1aacece9b6d8c370740843686ee852c7011c4bd2585f5fe1c278489a69c62936c1f9201caa4484e0a523d2c587e526e1857d121c8e01a45783e3edd5bb5a0f995816a405fd6c2f72d47ce650828b36b68a5a4943f483328dff41f0d6cd7b406d7f950c02f118a3a81ac3430c78778f4e082d1d3dcc35054002d2e7a7ce6db80cc39b0fe3307d94e64c56fc27d41e1874e14d661a533e4eb585a308dbb820ec3daf4398330ec3fe32bc4f3bedd10e23fb1def34e4d01b7fe8bad6286a308cf1b4bbbbee3e539ffe9f155da7c71cec9bcb11e39e7793bf6db29de4f701b28d6f5dac627d5a33ec07bd718d97c8b8fc9a3ab8b82dc4bb2c40b30b7b3e28a763e4c54fc849142abca05d835029b20db8f0224984c1fbc4d649fd70086c497b2a85fed45cd985e36a370f8c26d7b87fe93672c98e5b63c46a23550c3d961f3777190b3750e7a79c706fd3eb47d1f9b118a7c93f4d30af98361339ab73de6837246943dbadcf1d738b7eac2ef703ff3795aa6685fe38ae34e55825dbc81e784e5ccfafdefc56b714e1dcf1c0e790ef200f8c4b77c3e74c80270775e32612ff4ef85b843dc984b0286c75077076fb16c7760b2d63a6a797836d5ad38df9a0d07be5978bcb51da4b2d8c5eaa6a0440706923804843e963fd7aea21b2e580cdb88da37294da0855da6b0576570f0b40b41935eefefc2208941fe457133a2b0d5cb6e2124eca0e780f0de79edcb929fc6e6e8eae5d0d6b432ffee6e4cf0a6ab05c9bea386a675786b0efabaa8ca6880cee719210d554654302e997756e81d8175bac91d8bf5cd5ba6f4c3a36a39c6fc768eb8484c94cf96f0a17ff3aff77b9e23d2ee1c7e6a5924230b5f927a1f8617f402c7dfd564d3da577fd6f0864849ed3aebf153f1874a4fa841e0cec5997cd3a6151ebd945953377efa047c738c91a3068e3d48af42ef811ec1b616f1e0512f6c604ac65191991b0ad6e39397c9080eba15bfee34cd2161bc2753b2ef1c25f91f8cd24308d8859432a4e81911707631f0d1a3faba0a1f05124d7b51f33a87edeeefe0e5f2c1012c55c72f5ea1933d0112547e379eda4dea393b7cd4aaa6cebfdaddb6ccad1e0aaa3337709353be993462fde6e739771a3b2bcec5b0a8a1f281dfee988e862c1b99c098f0d741ec4eb3b47971ce8d1e30b351d43f18aabde544894ff42ab5a0a67449f8d0516df89a7dacb1f87537b86d179c4ac9112ecb4244b64", .None}, + {.Mul, "-d860efc975152beb63e497877a0c494d4338211659f57ca3c971cc7c18b6c0b045f51632ed5bf79f5f68f578e1d4bafe5a8621bd2ca05459b9650706dac01e466969c8f7159aa94b847adeed6829eaf369bb4e595a5591bd6d9aff435eb1b692726d99adbb78eabed2aa7d0d224ced8b194ea8491f01617e62eb31e39efa7f72f09cbaa8ba8f15ce8b266af48a78b84c6a72e5474eb770759bba9fa13ea542f82b43b198a72c3fa6a985bb497ac85147ece84444b676c3d9f4227cb7cd0d226075025cc96a581f9f2a3be1c8887419f75575aa34cb374c636143cd18f9aa609ba4b5cf13a25f9e1bc564c71d1a3d12f65dc8dd92f5f7efd3a5f3e59f98f7c73687566de40dee4a015b1624978f6162a8b9b41a40ec84ea8bfe96499eb4e8c72afe258d16bfde947c305935a977fee37562e2f535bcc1c835f211fdd707547f205713b00015fcad5acbcf0aa554e8fd21d0e4a4a270c946a6542d13fa1f11d70feed6d0d8a46b063d115a9b05a93228465072b98a8e3a6ef6f8a7272e605f9b8789ea62cb91755cccb54175572ca2f491912b0d9e51a58341e5cf14333efdb34a06db26dc14a16fed264f949f304bb90d711e9642ed0349759f827d7201e1ab3edfaf893c53599d33e3ff7d367bc4d56873a92f184f6f0b083ff6d209aa02ad8723578ede30e4d9e2da732ff1cd4b6f317c30f8558c5bd8e0544600830f6b0ca7", "6d23cd8e6de02323b261ce53147ce1589b6c0410017728669a15e8d4d15b42c7c7837ea64bd75bca6d7cfded946ca7dd24e445ba255324427a6a9a40a64edd3060585a47b4a6fccbb3a6fc109487acaaca4ae6185e6bc4d288a1807ce02c1cdb077d780ef5598149c0fa79a36a11c1e5769720af271d81fe2ae82f8675e6222ccc4502f1c4f8f8dc5539fe47ee3a04b8de9e2c8ba6e64dbc16613cf2d76458978a924178d79c0df5e207bfc01797d1d08018f6e42878f70b91687a89546e4228f3c8b5de3c1fdfadcc2cf031d9c5582986f0f8b877109ce96d9f2672b0481fd5673a1556ec999c681a9914d271376e12c520d6fc4a1ab8c2118a0261bbdfcac477add3975039911ff863e85069dceaf376892c18a3f49c8eff228c15265314cfb760890cdb4811852b9705b13589017ce02a82fe1ca56021180edf630b82cf16833c925b9ceaf2f3d86f45458ba48b0825ccee55db747483b0c6a7fe99d9017548c4cb8a00dc84ab6ece2bcc0fb600d7ddfdea52d2186df9e9549089d8350614ba457204af33a1040bf47f480927762abaa60217720178458a6b99c4fcf49b3b3ef0390dbc686e1c46e2813e51a9a199ee38befb13265150fdc0cf30eb9e5b2587b16013906b0b0cb94d0e4a02186dc86103f6c21275582d0e5d28b9fe04d7d5d3e188ba73f3d666c711944282aea142157612b9e23e79bf21f81ef1694869a0", "-5c3f8917920d12b72490b3f493777164ec322ca551c7fa2497531af84d858fe74295572c7274611c9649a4535895c813c271b1a153643b605778e0584904e1aaf1f73a46a81a02520fe54701263b5737e3b0e2f77f4390b3626c4257a29d030320e1564f20b5b89d84e74af0c2265494932369ecd3b0d6c86183e1750e5da8edf503fe76d688bb617cd3d6bf8247f8aaba76a045c9b811173f340ff3f5976fbebe4ae9ea90b13f6f8ae61b8933c38b2de812800f751bbb1e5e37c5e9b21cd54d8c39c4d6e2cfac60f9d87b9bbadc88cfad43e71ad475111fbbbac529378c40f07a0465eb166333dc9560bde283d65380137e1949aa8485d7c81cc96dafa90683ab9098c5ada8b2052a9c54cff11d88a180b5dc4e33141a74ee68a33e9068b9e25d641423053b43a98b97f2c25d9095e94a41345c8813f2d20d65f2cc138e71790fc2767a253f308da7b96c34b3673bfb115c90bcf4cd0c6c51747a272cce467d5d598bc1d7e905ad85b83a87496e5e535ee07b261b42bcd36d3e8748cceaad40783e730378f162455044ea7f99f227336f7a9b45636e1558eb74b51d2d3f6f06dfbc3006450a2c2d9c8e0901a10ce9f5a2f1df8bdceab65f7ab07dd1c90e5076fbd0c078cf3199b6c5c1e8a60986c5675dba1f687d3397b8632b38f5755183efa39221a8969d782ca06077eb67509f3b8cd9bb38f9244e77435270aea8de4d73f5abd1d09835b32572d67d1a8c458fc6479250176ae41af8350f59f81b803347e18c90b123c0418c2ac784f84a7c836552fb1dd8960d9c5dd620bf05245c72130ba21d9b96541517d33f9201704807a9194826ff14164921add3c405c177fd70c86328a46e81f96eed6b6354fbaa916450488ddf1f9425d2b0830975bee839d4c84b79ebe9fe9503ef9db836433825e5e11e6fe5211d4cbe46bc5e93279eefb0f2e2fbb1d7b18a3bc2b7aeee298ec9d19b6d302d2a235f46d985f0fc5105d9ec7a138e5ee154cd76fa42127cbd14bf7ee586f92d3adf0ffef57d2ce59690edf9e2e52203c0d64666bab640f83225eb49ad9cd91745644ad4c0aebf798ee39a6de210fe8eb49b9974c941ec7ef205900e133cba25cd9c6ea1894aef57a771632fd022f7668fc50b5135d95ef4c1ba658d029d938d97b354192ffb76fcf7073d97db371441bc566c40e56f5ddd43d36805f3827dccc219639bf6d91a3d20fc8eb95693638780c7c9521b383a1c4424536e377245235194108d4d277e72fa5aa93e668934b26d240c092d101d21c7b6bf4d863836f4d666be01425ae60bc0333efa7551264fbb19b38c86f943a5c9fb8dc76f2a8646ed16a232e4ea9ec1456d033b6d59b29ec61084a69dc1a67b89126e51bf4260cf661413010b2a6bf4ff9430305f1d911fabf1f3ef8a9f01b048e73d408a34049ced38ebca202fccbf99106760", .None}, + {.Mul, "-c8640cfd438f6082294b9c4d884e58681c525938864578c418166039dbb4c1040d22dcaa76e4b60f069af25308e5029cda647b9e37caaeffb295f235cc0572182d8f78d6c47d67b235e2a9adfc06b9812d2cd5c52f7c4ba10c34cc51d3650cf85e54df1864581057049e24ede47b93b6133f50bcf783ed2785e92594b69b4946d8bb02c2b5c56b50a785c3f2a183891a8f3e8f7a62a01c82ffd45d7f0fb36f67c174076f5a8fa549cf7462b906fe37eea81b233aea34d34c496420ea249662343d13a4d1746b9c1071505052a9121d56b37eed8860aa177850f7a61bdbf48f22cf3db1c7205ed38ef546d07ddece5c550b28d755d0e129cd376086680e4b5eb67b362b4c69d9b57d0b527aaecfa59ef47b003ac3220b25adc46dc784d2ffde66560c963cc96aa1d3a258d5f92fec6ef82b90a6dd996e1019683edb75b022829f0690f3e5d5caf51a4e94ae1bea28373f7d2122f2833399c4065c0ccda671ed858bee8582fc948e472a79a6a8a4c6e5c06b31bcae2ed85884c44ae0b29900643001ff688276e932038f5a62bea1adce31d2c2b788ea7dfbe304a2de35b2988d1175b9544d7090e1f46a292e848c247ae7cb8ca969050f2d7299c58d80abcd516cd28a577feebf341a8f2be0b33e0016ee7fe4b827aee9f08b7d8e405cdf399ca755710dd7f438741a77ac9f3f08538e95ff5041c4fa722117369b32a5196ad53a", "290ce27c83e1fae261e317bf786bb775ab99d3d62c6bbbc587866ad5a13178c309a09177199a04cc75a0609ae897636292580ff2851373d1990646430462a7f67bf48ef0b744ea4bf812efda8c51c79e70895cbcbfc11a2584262c702e06177fe35dbcb271b302b24e8c183ddc1571c225b8a7c26b07e9fe1cd125107520003609afd039af90f082adae75ccebbb4f57d92df186cf4ecd732f945df527ef75caf9379c00ac150008d4cd11d35e1f55354f72d60ade81c8cf1e512bba2574c014b44c0a0f317dc941faad13bb61a3fda6c9472d9a7b57b42053e68c335f7da63979113da4808bab73704aba84e036d3ebb01141bf1ae9f07753e8061430e61b6aab4430f29558572826672b70ebf04366d0bdce4c593f3728a2193f603cf4f6e694d8b597b6f4f1331dda6c8fc1e3b1c2a8e9dba7972a1a3efa65a9b70d0a9a5dbe1d405c59b8862e8ce95c0fdea64e435aa7172266a17dc5a01b9639c4c73a27f7d382059c2e1851a1c8972bbb2149b1e5147fbe85790ce8156010b77da0fc4fa9aeb7f21fe3014742ec2b9acd7a6ad901a29bce31a1f06f7b67fe1a9700168cc23cf7b13029e788d69caf52c454f4ce02a055e386739e74f294e58e6b19e03ea7d8b536849fb3833da87f9c2e61d3dbeb3aa333514f1969e2e16e8cb8aeabba12ebdfe189e00eb1cad9502e4e1578dfef4a7761b23f48a8b5e320bc71682bfd", "-20221c0ef6db18769929ea44eead48a34f4379d4d1098da34e5f08bda99f37e60592575f836451b8550463571536d060062a6a571c8404d0081860955e9ffbdf610b060dfc860c80bab31d1866ef864a9e6f69a5c2bba806c888a9d768eb8e9bd2d359efcdce1011cf4d27c2fced6e667209f9429d88967b4cd9f1e29e90b0fd710e5bd097813f87ef4264ece4de584a329376becbe62bfe9e7f79a1cf121baa004275d81d5f2b03db09f6f3a55d1856f95e29986a094ee1c9e2baf4197b7f687674310df32894667e9f2611c14bd573b088adf99b59dcf295065a911a553aae72c0159e4d1fac9da1fbb8486ed7ef0087244f07aba1ca3cb4337751edf3f4670a6f0cafcbc2e36ef2c1eb92fb3b49b7ac873ec4a6d6515ab511bf2e9db7d233226cb9fe69c29ee82d539ba2cc51eb4b9dbc04d10f2ac8778f180fc6d1bb830d79e4077e05b0d70158aed9a6d980c1313eab6e3bb75c1b6226b1ecd5580fd86c4156251c280d48ad6abe9f8ab9ebce0f5c17f473bdaf0c60301d18942357ff271fd78c08f5b5981a1ff660a5e7044e5ac24c559c0b0d6c9c0c2102b5a3f5e5ef9085d78756a3f12fa15f3637969bcd6259f121f4b8247129045bb53e6239b09a628878e5f4abc930da734eca68c388da40b336ac1a8db32204f1d7824e39c7898c88c600bb407c9154cc1d559951cd4b6b481338be878aeb6eb29b104a04d71b6b84941c2506f0e8950e9907c23884188f17d7912ecedf46a57a29569fc3d2fb466089cb9a885d10afc067d808cc623f02bc1aebde7b5704d4044211149cb0c6d2587c62e8b1fb7baf8941c796030ab329fd3516a3ed8c5cfd46f1394ce112d486758d40dbefde3dc5c39971327fcb4878e826e26138d97bd1b83dbbaa69304288f136f417c9c2d8655ff203c3d8669d9b82a171c5a5a3e9aa73b95c587692ba0e392303ba01f355f43533bae14eb52069370166f6e1cf0cf4fd8ecff0d06ae0a1060396a69c3de58e55f1b8d92e7848a48123fa628067e855e0d64656c6179fd3f211698216bb7dac37342092e746675dc23e7cad6fb4d7cfbfea5f75f287cea1ffc91303e6c41a03cdd305662d590619f5fa1408bb2cfbd87bcf50a6f599644612397dd7f41b6fd11ee642b8c7e033202877e1c8f60f2d3c982b49aa8d5731c564714d14a59e835638e497eef41fa8d629704b95b45d386d32f645da37bb26265a011eb7dce74463f7103c8457bced212cde1b2f385d274235a2cfe257d016bb0d6614b781fdb28782ebbee7c7237df550995a87ef90f76c10e93951273e8e0b160e72b55a88ec3a1ac9592dceb2882b70ff93505f449c45cd7194a93f28a6d6aecf97735065f8c1add9830d86bc5f727136175d08446279dd5370ad94cb266481f77f38e5b81284a4f7513e837d293ad5850709e86f7d95b71a8c49f57852", .None}, + {.Mul, "2f4d50cc9b366746cb6b266d9f9d6711932e094ed92854e1bf8bc24674578b6bd99019a69b23f03588b516be8fabeb14bbea6f6c811b63721494186fde1b3148bed3ac0bda0fe081b639ce3f6100df72826c52971c268715d21d2ab61777675ad9eb1ad3e82afbc64741f06b2eb9b88a5e351702f55740c174bba703de1026d26d561574597e9af3cfb03c9407fc5cffa3eb0499b9bb148b2040f475c7a3e717263a4148b9da13a1a72736935585a84c423b087b3dd7da8b01670d6af016d750a73e3aff20b5f4848b46b05c61b01f290083fa71c300eb975cdfafd9c3e6d62e47ceb542f795bbb1803527bb3e9a733afaff2ea8832693a824b7a8943cf5a64dad6f023e28145f4d16a4e4d0c53a2f9c6419bd04ea562447636f2eca2efe8323740c55c4862d0e07a2445d23285b932463d1ed0bd03b71b734973fa35da32477340b2a6711a33dc4291455d131b9a0d35943f4532b504460c71634d682552155a08eaeae35bdfe4bf2bec10300cbd30103862b41cd95769bc82ffb7b107ed060b288706db6813ec53f6703bb89dd781e426ecacf3809fa0928b8c3399b6d593cbbd61515b0d2e72fab38315aef1ee103a9bdbe660f002917244d1ca89455c8cdacfb52a65f4ebecf25eb9e6c8d61f56868dd91d34350c392fac82d77c02fd33e082a28ff4ca559fad7042ad60fabce0a31f60b0c6963198d890a46550dcbf175", "59c701d0860f731b9cb3e557be7bf9883389b31072381b76a229c4c8d08bb8560b334e81552e06ae8074b066a5e05bb20c9b938bb589d74a16697bea64bedbdd414925fe4cc649ac0151e84cfa57eeeeca5bacba6fb32c09265a40a735205c3499fb630b4b884aff58e15152221252ab8963bfe275740ab4ff93b97fe1c95af931034ca805a0c5be4dbf50dc2afc79f13f1f8e2b5b32cbe01619ba8e42c6db9540f958b6b2f7a6d3806454326351a9dfeda8f8890cea76ffd453463dd7e0bdd60f4f25b6ccfe540765afcc01dd17ce07ef1589fdd2f5def3ab8892a6feb39b95e05bad8adf7169cf7dadd8139104d52d65987cd4e343047e856c46a6bb3f0e3dd245e4f46146248c4c836ef3b44acbaaf760d5304017615ce8cf8fe449dacd79eda874636a4a43802ee91176d508e4e1fc298c6d3b32125d006fe3642383170da24c8367fd161b4a6fcc31820fdf35021f6be8e5130850936126c3a29bffdd43381a5e3087e019a4797504a3ff59f3e12ee0a7f3001d979cfcf8b0954fc4afb52055e484b15a86c718212f7bbc4374be01b87056a6501da9d27a8ade16503f809ac465df2ac3a84c0d844be617a7c004b385ba569b57eb264e3484e3a76e26103c0e1e9409abcd6e3b6473814d68c1f301f5615086065a46a9004d9536d12540fd90d7ae1b2c8e29e0a0b1a93025fe22e549d9bf6ca261df4d83a49f7224e5f4", "1096a686c5ea5722e1feed3126119ab190adf4b07b19a0a7fea0a537383e64c18f0d32b78410cd8f5bb197e3c0571f2ca2fdcc6746f5455dcfb75b75b27b3d1b89ea0a78f77cf4496b28513a851e458f50d5dfea959fbd4d47d7f6d0116fe6df5f6e763d4b5cdb634b3715e609c714a11b2fed6b5a4d71b43ab39a2894d0adac62ca7257fd27d39a529de5513e0b47f8168027dd0cc8edb5aad6ca843157f2f4e1bdc10d8780e31a045d0ca41f146bf6b814bd64228b558b8adaf7b33c23283d82a98b984dd574a4f6c1de0075a5575c48e87fdb696c2ec853f6f8f349edd1beb8b10d1dd0e06d8369219a369073d32b19c1a76af9af04366b868831a0a8f24f8b7100ed1e5326830f1771f75488ee0a08a14a488567221f4ab01b7d4447d7789b14ca58bb812daa64e4ef9ad17ec226e435b0d733680ca1afa59c9531b880762c633af89d24bbfc45856d454c3a2d44ecc665e8b901d72e3b57989a6f4c51d5da307688f7c6adc57fa4d9c42f0822a36ea1a8dabdcf2a0889d1bea780c7cd879ac05ed589a17a6bdfb95dbaf45ef6005fa4d798e2380d73bb6c9b3ae078e7f5b10152c2da7fc5ed0f9cd20e7175183c59f10b9563e3c67b37e3feba2386a55a1fc0946d4c4dd724286d1472d64f0e4f2beead7b2add128cb820871ed3f4f1ff9c0174951fd822740d9a46323ea2e835275068a677795546fb94e1b1ecd7f2f64c981c6cdf8c96162224739c034e3114fe0e7ef6a8730fe8e46c15166daa9653c4d5ad52d7d31ee8ed1c280586142c102dfe9193b5c76687601d3134a746165c0cc61ee02970139e851f055d33f3716e35379974241c2a107dd6732f3e54b58e6d20df06e11bafb8a1010efd94cdd4c4416b8549f7129df411859ce4087fc57e35fad0827831162a45e205011ad8f47035a322b210bb0109edc92a1600e7fe89498296abcfceeae1d2c86e6d57535a3bf6141d7102e3504efd9c6491c98446c759263b1a08caf46dc2771eee3532f3d3c0abbb2b2426386bf7a7e05dcf72ef083b515e2ff4f59ab21f8042a36b7be4faa01130dae5965f6973d68f11c510c3c5cc52062144a29ad286bf1369929feddbfba78835f2b73944cc2adeea22143bea47b47ddf5fb4fb01a14a2bcab65f728289344207cf2460fe728ff8b5ccc8807576bdd3dca379595a6a67bccab2010403350421cfc16d9d0f4ef1e98828557f4511ce61adae426a20a6ff7b49837529e337753812b7beebf7c6049c189f4da28303bb7cc36450d0243353d4f2a3e768252c32dd766e0500ee7e6ea87572167e35a178448db2abd677d079274c019428900b7b76c7562ed0ade63040a85eae035d4241b0c2e5c54f374daf5a22a14f15af6d7b45803a7dd8d10dbace285cfce2b4dc3ae99d0b6a5472b86b7c568484adc6b812ee0f6f890bd28b08cc47a3d3cc84", .None}, + {.Mul, "5de641fa705b388ec3db0329415c872e0e60fd1b7c35a909ad9f1c161851d90c45d9e147c7989f871341a93fb5ea8c5f4e841a3c3de325873b61e708ac820a22525e68ba5d8837ff3ab95ba29d6dbfef2160ff8d4effe770cb5204d9b451294fc6b55fd4c2c3ba1ef7642aeaaf3f959c75586ed2cd70d55ea17758211bc3e76f1f31cbdd51a90fee136b97874591420c69af96ff684291fcd0b8e10cb3cc8b3fa42687744088af4056508a114425c4aa98917f543eb4141740e94cdca442d81328a539e07c2c6781c12461b5f2c0ac1f1b55c566651f0d5dab8e81868e40dcfafec1e9587f05362b18aa27bd788ad2e39ae0a36a939754c179376925ca0939414162daea4a46e6f42cd93c0b9b39305dd5c8d74e1cbdb8cd30d58289232e631e8b4235f1263ada0eb6b655ceb147f7d9dbc973891ce2c7f3c114333afba8cea547064deb704dd23733bd586635a94beb782a68d881dc108b660085024e41fca89e98a00000cefca2296029b522da83a4096881bca91bf9bcf1d5fc6d6e603d3b4b007844e940c79acc68a7d4bcc12944bb3a321d555c898649d1f2c0ddca8dad1ee7146192a5303275491d30c2315cf841f2bfede8752982a14575ba03a31b8eabc21929cb4d9dfb34ae460eef5bdedf3336356de5fcb56bf45f2c45f5d448f84299b64b880678c214d9b12b551bb681e526af99033d6957cc0a3fff60452084", "fe71cce979da88d9bf398155125038c9bd7211d49425e7fe1cda925db47823758f7c183f4fe68a8c75b1ad16e74536e33b053384c9950da456cadee71c720691896c3bd521bc389c5db17ef74b81a98b8d75169058545b1efd8ceeafbe14054c16b87a5be60e6959cfee19052dceecb61559c3d4f14beeb2ba5f6250b0fcbda7b606aa6026abe8a0834077f03412c8d80e83d1949b3b153f9222231893e76bf60a655f9b58e1ea35a7070b66fb1b6533a56ecfebc0626ede2184393d4f701cadbdcc6035a69fde71472cbc4c71adcfa9d671298147f18490ea978aa325d885b6a5abd123f960b2d8f9bbda8b2dafabef4a6e5670984a2de5a9b4917dff65b62afd76d008ca1bb04e5e8d695e20b52f5fb1bd6f6ec11e7ea1e11f9cd8647eb3a630f50b79d1d4a5124caa9d936e39ba8342f59ab0d0ec3904fe501b9d08b1fcff7eb86f38459b39d7fd899f333f88bce5dcce2720b707373083b807af814477fe478e75a532c89953d822cf87eb66754d54687545a72735bc5fe1dd0034b3b43f0f7fc319d6eedb075c63a65addc510e46f9e899042a91792d3b1647dec296bd8c02b6d25b91c48dadcbaebe53fe1d3b667d2995ecb38c6b6e02018bf7e1435c497264a8df7663febd6f37c5b199a2f2a29431fd900c8939f60d4c24a7aa4d42d26a60d9ddae822cff3cc12472beacaf076523d879a690949106f5ce96f88a5b4", "5d543342baddb650512da6243a704a5d1f74fb661c1fd0be9f07730c5e77c1ff0a1b569368d57d0ef732b453333c715168cef7e8431ee920b66f0d51f6e8a07803d6db81b478b28f0d08eb5dfa6da1a0025e99e537e4a4995be1bbf51c43ac3aa98408fe028debb7de65964285fd00963f87051fb8bc2fa928eb3416dbad1a19be0f63ae72aeccaf3c4290a6a21c0e7d5b426fa178dacd4b15542da199842b22587f9dc4d413812eee9d1e53aa366d2612c366ff76b6048a870b6d067cd35bece4ff3a6b6cf0672f428317dbd55a0890e2f1f7903293d2f556e016ce8970d26987884deb3e274141d171565149457fdad0962ee1ef5c143c91e30040fe864434004bf80e9b139fba7f9d13d9c8366270f0bc21788a491136f5c64e73ead569750ee3e92ec07add871a62fb1fcb26e4386dd84ee49658d083ea0c4377796547075dbda1a4974f264a117a37d5c1f5b0216603d14e940b0bd5dc4c2da702630e684a914ff1e2089a0e4ef48e63c9935578dcbf3525aa355d58d13f39a736ff337a0ff6bcf41ccf93f8f1b3edf2cfd4f9e21f5db80d72bf99875008fcfac8e977737a0b3b3016185eb8ad1c1aab62a0706172f87b23248e8cd3d507d21c4a90d1ecab958681a01d64b81512fc08466356931f16b95b572ff9aa7f009b5f7aafd739b97e94ff60371b8e779f78d48e0a1e059b97e2977704f4abf5f6b591cca62f8a308757d9121f1e842cd6102f3efed9ef573e99db977a9d74df610a05c539fa68098ff05342fbb3f5d78467fe55eefaa7e245a8c999298870d352e41d47257d4f7342d3bce52279fc91a67093b8a7b189af508b8133a69545ae9b0fd6fe83bc19868e9534ba4266827f0ad06e9c496307019a7064a4929d64bc51bf89a7b0a6ca34c8e59243856e06c79cad963b0aacf6e167423677f0952b3e4534d4dbfb09aa5115be0cf86a182eab9164bb7f8d38c95aa155398b47fff9c20ba7c2cb5b7d832e2335f38cef1f068f5824e918ed89ac3447bedf65a630978ec54af87c62f7703d7fd042c1937b447308bdf11c615f769978103c68330666fcd409039e697d6f2d03e3e2252815d439d1eec1e96fba823b44e04a4df8e43920d388b79d4a00bb56fdbacc99d68fa2c1fe3686a5f6d0b81ee6406ca555dc07db3ad5b2e0339bfe9c7ae2e9c64d44f44d0c434910b78bb8f69448831eec897e0551eac8bce8e87c55139940edc621d8a17e4a09cc6ae96f52ca00e442a596747ca2e1d1c7322921bbfb3a3d08aca8ee1f42baafb632c0d577660d427566184db168620f7fa8fc008f58199f36fd132e712962a5115c14773734437fdf9657d838ccc5dbc65ec564429d19c3493810fd2fee6c4861a05d119371322582146b460f4547244e69a5865f300d2213eb52d06a8efd25334387c2c8f4e0629e427f1c9cb3be92c0aff0d0", .None}, + {.Mul, "-d8b2bc30f5b32c97432e2b2f94a52281245d30108b6e2e927a52a98be61a207e779c7d7a291e07cee6d448ec75a0ea796fd11951c07c69a87b12f17f6607a619b307cc011ce66d276c9fdd759efff345de611e39a5d6de145f6714929395cc5fffdd136eff1503630a4574dcbffe48704a960894183b7b0331d0e03b1cb8893f3833f1c7b3145b7896e22d814fceaeb44f174e7904e33a10904fb73b657d8f646ebb162d35138a1f248d8ac11bbc43b4c489d02eea231a12bbfc331a055875daedec2c0787535502158dff95f79f1087ffe1b1b174b0811362c5dd03a32b334ea5d09b296ee8c7ba994a5bbc5f62971f66cbb7a347011655b4d1fe55e6a35007b1a2a810f64a18c91081f0dbac475251f47a80723f99a084bbb667fad34c208f4b0b2bb47c3a4f68909d95ee74fcf8ef381695f91a917b21f5a70feceba0323f5c9e9b22690dc86c52d2c40aa3f1435333b1ecee9c4cd8fe04e06adefa8d1dbe9323bab139ee9b1e887e6e90ed8ed02a705d2bc91d3ed16ae6860fb26f79636fe5e1301fff8020ba217f7b691b91237c5045b16f7fff1cc97666f0c681186e8ebed74e4c16103c784f216efa1834f2e77e8f99f3efeccea3e42a0dc314e0d7df5a5cce64dbb1552c03f70c3066ccb4ccd7d921d3f4d6a7b4836eafd61dceb74e5e0171dc73d0aaa7fc2430e41bc0caf45e85fe7f859fbe17aff0acd8b0532624", "84b72af38354b5bc067d36f21dbc67f76ffc50395b1b19904f70f4a60e5a6d2a5996bcb4cfcd7e3beaccf7bb85a40fb95bef1b22cc83092d0065fcf2eb6d5e56a814bd9d60012f1af1fa425ef898945f1b4ab6411641f1a0632aa3afbe9e471069cee7e7b4fe2a4acb24415566beb13a95c36dfca6459d592465b2f77910d44e7f73f14a7e2e44adc0105aa6be91f5487c4e9960a5979dfa2f5c3376758395c8cdcfa7072a59b4978ab49fe5a4427736dadda8186e5d037324d2a151ccd721cd8308177972102de9b4f424d03f9ad308c7cfefdee339c6265b668e0e289c7e930bbacbccd0a1882840d5a9b267f74dd732502a3f5cda6709bb6c8c9c2d6722bb3dfcc6f4fa5da4442b36233c513f3d465d176e596d756883ff380328f33bf7524e51a5dff779e3f85955086654ac9951612930661945b703fddfc024b43b4dd3f0b07d42b6e81e9726612f49bd797bc3b2303ca4192a6ce47aa166effc052eb4ab65955a89fbc80165979175a201773a012977dbbfed5b7249fcf7aedb93c4bc92879565f8ca4d2b799ccb9bf566ae8620e342317f3c95c7f0ab3dc47f31fa9a74c4fa3c34d3b10318b3ae38fef9acac2c5bc0bd20c72fbe0542a3a52b2ed70b6ba32f1edc644deb8855581d1512d7bf667e475baeaaf26cc5ec702543bf2556cf39c8065f92205be356ed0eca102a23356c6597b53085bf2a1dffc204c4bb39", "-705735293963dba3d2c34759962db1716d8ea4b862251266d6b8451952e0b6031c057dfaccd288e973c2fd54b7bea9aae2d876bba5ddcc8e94b437b5671c8a82d0f9929db003446cdc2f67072a34876d2b386e619b87bb84a4ef91236bb17eff3705c075eca51824a1602bac724981aa369339c4865d391928949cf6aa62eec3ad2653d0191fd7d9342333548043e2a1df6260461f5adc023aba3a7c4bd0fddeae9a5796ed9367216be9e7a7ce51c75cb655fa0fb5199f8b528e0ab90288042394f0cbbad93014d42fd8dbe6830c6f7ba2413c2bd87bdaee1d0d04b65a900cca52614ba8f73d2a74489cf2228f09c3b2186f90917e9bd89928edf96883a235c4ceb24386a2ae832431e3b0a2e68779240336a5ed8f14ca2926b8f060e50389dc09cf68e6f401e0c7631ff7287dfa93a58a31e301ac463ca3a0aa32e25ed830bf25700af23d0b6f9c699e0ddfefc3845f83390ac240ee465fc307c474a4b6747fbe837451ba286f89740a936472f735894e7440ce71cb1ca10c52776272daaff5cf4bc9c3942bc3e3bbe3ae7bc9da7611d14e769a7f295881589f101004583e482ec3971742e847f9eda991f76a5d8363a278ad00769ecabe29916cb798a1a4a30c0c30b0b0158c8047e0d2fe24fea66eb730b824d92713f41d2caaf5450e2d4f22b5a121353d7a9c03e931c966d5aeb803519c45abad00358e4010de3455016971d3cf577759eea3b18e32333340f2b76b63a532edf683e3a7c8ba7765e46c5b38697ca1307f784fa9536963c6b26c879649dec58c56062dd25d6c9f9c585cff5f5ef31c124a03ee18e80271dff2f11bebf6161e1aa37a29fa28931c5f042fdb8efdf883c3d8eebfc9cb2232e8c3017094fd63cc84e25c7c5a1fdc354bdbe4d5c8b13f379d8d8994c498487043bcb1b75e7b54bc6a517928d3b20dd0a40642f901ab421d64d88e69a8c13cd99e2bc6212b0faa5b42d360a7f14e33ed1dd292deafcd2383ebb9b23f3ef78fa4dfd09168348312fcd093d52828179975d0e03fc8e2e4091bf9f6ec61686b0613fefe2d256298edf6a4b35062374b9f6c5ed1ddd967437ba92b0ec405431d8aefc25ff19e9324348e8a04a8981e8a3d46f54a7e3d23a7b0597b4dd45d9f3a7d56f80137e6206d977cbc134ef8f07aa9befe230d215dee417f1b476bae2f2faa423f6cdca91a41eb98d5b022c4dd9bd6f3669753cf16ae6c67e94681ea7613f27176e361767e059ff5f337f7489f292f8813cf7aa6b5613a59cd89c75d2392cf58da8d74d2bf9cbcfba16ff8e12689ff2e1dd2dbfee1e756318f1d2923544d569165452d4d6677538729681296bd202426e2fcb239e29bc9bacf7f42e7f8a624f66ff40ec7dc7a75957e12d96a8f8577dbc2893ab2eef3a1b58a8bee0c5d688e8d31e4d6bbd75ac52ae6f1b2245f95d495c2efca04", .None}, + {.Mul, "469a13452fdaf61254946c0985df44ed9825c55d31a49399e798c703e97798982cff90741ec4caf67a8e45a67e7dbf479fcc923e33afd02d492a63a60edbc46093934a3abd52d90bb1eb5d30f65451b179c0c21bbef241216d8a3a9273e1f38064d581245c704c16106e6627b9da028a1c137eeaa052073d5ea9d14c2842ac85a6cfdb2098a0e12dfc4e897bdb0cea5c17b35815aeac9af4b4e03890d23c2d944b30ade3efc578776e43cd437942d6063e92ec667a2eda7a997c4cf6ba5454407033be19cd739e997000d4b8c9bb48ce6ab6638b7f96e0e116bc8eb467c5abb59475911f88ea98b954c77ada1c0036c684db80980cf0847d58937d3bb544471583af3dbd54f87f7c43331cef1cdeecce6dd9ae80e2b2b373dfaef50a6c91e98fa11d3910a4577b9d745638fc54a164dac51577aaabafb50c637e3f7243eacf789e19df5e9970836375548b5e7f683fb3624207b536c411109d76768a0cf05cbdc2fe2809d383630bbafdd7bf1aea7f024cca4c7d800e4b4490849c92023dc7a25a973264ed0690fe5eb6e4019f95707aa73cc993f61e8132ee0af18ae1e0934ce6dde4808ff1466a9efbf03ce0a9c7163705408c2646f771a1a39ec57c3357b562e1e95aef39f35cd6f07bb3b8b806c4e520c8dabb530bdff6aac4da8440753a262d10a5c75ee92d91c989e085880c36eb79c70b793c89e205544930a45e1fe6", "95d2cffb239a02a076d278c55af41a060abaff988f75df249ba0e576d57b61edeae65bab98635f53a33e81c0194d86ced6a28bb5a248abce3b0bc4d2791fd213409f57cabd796d45086e26ec648563a8bc6902496f3d7b7c5a8c8d72aed3ce8d2d23bca6d3fc580f0a62f80f5fef24f955c5efe5a235b1f24651771dbfc3e6d8748fc6d8bed01d0b720d70b4ec1d417cb8ff5512ee26412c6fa332d2be63fec0398571c8b3043045ce73a898cbd2a216492baa1d14496a8f3fb8471ce471b0178e79effad0788034abdd14024b7d9d51fa41278e41a202e1a7c37bad52ca6f4b17f5e877259990ac7a098c2d5175de070d42367f5c1d7b815484a5f8b64477a4394eebfad9335b4d9cd777f11fa5210e57f7160cbbaf520062ef8ccf474164ed92c7ce96c8e9f3bc1972a6a07a6c8fdb65a31bc35f7bf013e8a21adc7b87a03efe5d3e7764b2a990ca4d1a61dde8ac65ca8acb3368e6dac6101b297ff4aa87eb01d679884f359e409c1b204cf011c53838125b1534ad104790f8f0d81606863ab4097d607afaa3443209d5e15f21c129fea39f7f179a2cb44009c4967194b070b4ef02ac9281c05c9eafac7fecac5e863ca4734810495795ef4bca95a1906112743b6e75677a7411aa1f62559c85cbc948076514a528ade79209969f41d022b98777dedd38424b24af975c6917970055f8bb5d7b2f8ee84464e9d4a1937106d8", "2951d0f6ec13136a014d3a8d9c786f8bb5e68dbf7cdc037528f82b7d992a7f0af66f126dd66365408cb362523b50f49a34614e518ab51db4a2b58ee94049bd994c61befb933b60267b30ed258c7bf0f59c1497a707fcc21f6190d3d1c0dc186ff02a5e89db0f69cbd81291fc9d7c2ffad63d25daba8130f163c8fde7a88fc7fdfc4925221c698e356e9a59544402ca7773e7c54375d127e57c93acd54f190cfb2359c78b8a6e9bef1247a53eeddfd8ad39a3570d2abe23dba5ad653668d773df137993e9c108de3fc9cdf2aa6733e48c28ab688952fe643fbf4de300535b43f5f3e8cdfcf6c9678cd82a6bfe148c7b0bf8a5c0f8eb2b345386850e838a8fa329a7d10784901d37092b7b802aea502a2cdb887824dac376054ad1a4360166e8a421a2512ba7c0641b65a889faac7d138d218b7c79c9bb72d58167cff876840f2de97a3c6c6d34a06f2caaec90a4aa1e1b046c5d510b18b6bcc14e60611a688350e386778c607902d403f4958dd0e310b3969f70546a95f74bacc350b1566f4b0c4e9d201b4ac31abd299ba5c3ecd97f6f202ff456dceca1f88a98061975695427881550b576b531c7495e276b8bec9a703d71b1f1938c56990a8bd482b27fcdb83904581ab509b76a2b6b5356cb09a6e27d626475184cd1d99dec06229dec172376f38c6cac1051539d403b7ec4581e851d100bff9707e9bf3f06da53e757149ef4c1a9df552182a27dad4bc34673f8351f9b58d0a6ec0bf7347b13a6d2e27e53b1e0c87adb4275c02bbe210884150fff7c55f3c2eee1f8b7faccc8ebebc3011231cd7ade4366debe8a503c475526a667c10b862a2aa13c2703901f09923406c49fe3c34d6c1a8d79a0f9bae19151bb0e22aeabcb9e688463de447209a967ea0c6f6c9cd07bf6110941764e9dfe843cddd599b044930508a4ddecdea04bf63ea3ac2ff5615b2861b8ab407858f7738006b4a62a2f21442f1e8b1420bea95ec6c0b55e830ef5bfd97ca4d05fe42951cb390959b3b0b0dee2091f2406c75bdceb207209392b0f357b862a5cdc42183e33ba1632285ac406fb1ca0d85e44012c67f20f0a19fe207bbfafc29859bc8880e2836bac11cef7054ff7c55baf1716623c022e931c39526f5af71c38f5aae499f108f2bef765b52bd8a5d49928e5f0c83e0f8280c7aef2a7bd38e8ff0c27c486c7cd37684407133218ff36dd7e6d400bd2369472936b99d96b4ccbf8e06476a357dafe33fe57aa2311a11fe4fbcc414c3034335656989e350768c98e13bfcb2dc2d2e204f0bc8c009d93ba3d8f70cf6930bba62911a45068e621486b920da3efd33b9d057efbbbfa68cfd37f304823dbe12d7926f8da8b38b277b7f3ccbab07ad7cc64b552b4fd565e3e9fa4ab85705082c11fec4126d7105ed5aaadb1743ae7b2a4c1d802bc01b8f9fde7a206680ab04e10", .None}, + {.Mul, "-6a82e7ecbc54a79cfc94d0ca2941a4adb08f7a45f6dd6d70860034e89fdb58ce65a35b878061964ab589b539ee0d6de2cd34473dbf4a57e0224ec51c6085f99574246a39beb858e94f97a84f4a3c4715d23e2cce5ac91dae2b002e2490bf85e6a6a1c2b3124e21fb4de27964fd16be3a3a148b6619d25cdd6109476f379999d0774f7d4398270f6d175d22cba2ae03cd0ca7b4ba15dbc65390445c0073a3c3a27a72dc8010ea4a87e201c48579b38d799da1dd5ff71a702401d963ff9ea37103a942dc96ab0e0ed83262a8237363368429123c53bbd40985e9eb87730cb8c51f4734ac6c60869e8c141e47b09e7456dbfd248ba667183e9260e162bbc129fab05a3cdc77d687ef059c0a4cddddea4a7bb29ada22659b1567537698a4858a6b9bbdff5837af9d4de4ac4527214867a2e59f367c0fcb61cfd492c5b230fabe4ffdfee8f1fe05470ff4d7c22e0c92011212c2a62c023b1603c94cce641c2366953969f2f92c0d7f61c3cba119cfbc5873ba968a1890438ee9f9803a8af41673d638df442e57e72649a84559296cdccee4385d9697e5b8f4274844a164d8c03b74b2cbf261c9abd753ac7b6b4f23b2f0a85c9e2de2864d7c90c2ae55c49e9cca952762cdfe0bb7aefcefb26eafa1efa61e0c4e4333eaa88a2b1603b1e615cd00ba7b42d2ec7d164603c2ab0bcdebbeeac813212d9095a6d6f2f41cbf9970c4bbdc1c", "6a5114856d0e2fdd632dd191592e4ba2d5ff6281d74e35f63200c67ea3a4b747927e467d8f5a81da9630f7621884186ad9139a00085544d6bc94be35083f721703995c98c10189a7ec7dc3e0692e8478d742ef8383882c868cc7baf6f5d6a0593b781ef468d3aa672baf53de1fc9255bfcfaeb13101a05fa2813335680a3dc6f869ebbe9df9829bee8432e85a010046349d12a59e4ba9f16cc7eea939d7a7d648812163f480dd1a51125cad7fe672b83bdabd2355b488115a977c0949bd3cafddc9d05eda451e391d29d951e4d06a3de3ace7742e34b1701cc2b4938aadde6cda4bb6b00a430a10b141ddf87529c6d4fb93b441bfa5ed2d1c5dfddb976d1159cfbd57fb0f74c4e7fc5fd2c8df8d28e3f1e49a8d802ae67ff3a8e92c4bd22d2ae3dfe370b22ea5d1da0dd29bd48291520c1d3cb9d808120a482394d2ac8e3db9b1b0cd28e96168bd12124f86dc02449c244ae4f10ea795f69a3bd278a7585d383d09c951e208ad622cbed5751c823eb9e89f845abfc74bdfb3cc53cd52a73ecde5ed00b6225e2361bac56b6adfcc49201855a630705c62ac13ee93856fbd5bdbf2ae429bb602142a948d8d538d9cd5fabe83ae513fbe471e614ac5781fc4ad2c9ba13e10dd1eb38dc704122c06db493f9970fff16da2333a1fe09a38ae03e976e39273fb66d734383511f6dd452358b12d5c10faa607777bb7ca4db7dd9e5a36e", "-2c3beffd256344b71e5197aa6ab2724e7c5a94b475cbb6a539a1b719600734c1b51a7857363efe7a6f92b76e8a93e75ddf48fd9c0cc0437d430686869d78a08fcef912aa50484b02905df7275a2477bf0c8af542733a6faf2e59e1e0fd77a0ff883b32d23a0760c396b1650e60814ce48565f82947e5859f1adc71ddef157f0348bc2282d846cccfac61f976a69b804e251a5262fb33c6717ad34f6eb46ce2e84d90cf27acb401f5c2bdc55b9493e942ca8c418706fb31c61e5d314364359e503855c33e09c95db0562e556d7add9ff83ec1465a7f19da37224d2378532033dce4f8f74ca148062ef4cc93dd4edcde04a148d0b136798d0fb6fc0537ee01f5127716ed0eb1f5ff67334b3d8421853e1554ed93399f8f724e261fadadf050a01e69fca05075a65be20d53a23b9b1a4499e7491551aba5e54d9a5318b7ec3a6e23d11ab85e6a7acb7d639d452759f2031b9560446a1cbdfc0747191ab96fc1f1de369b89d625c04b3f44591d27389528d39f03f6af9b947ae7f396d34fc1f5d3501ea4d3329cf6dbfefde9005f3ecec08f64707b999525300637eb31dc7678880f809a8e898252a3ceb1372be789588e556ddf77992b94707ceb2b1749e05c5673895db66b276cf99034b7c3c218b52f925ed48cf2d06f4282a36c0a87956beb4edb9a2b33bee78afc90d47c2a8b96d870f9b9e516593c66c9a8d7808a098d7351aed8e032f5c8d92f621bc3c88f885a9702d3ac228b7b9cb9ae5f60a70b3c183317e9d53f03128b7749f9178d033241ab0543f44b516d2b675b2b1f5bd54c9bd1750fb9e057eff3360f69ab83e5363c176637a592c95ad934b1f654b1dc4753fda3d06a2423c0d70614aa621dfaa5f01a831128e82659cb295c2df5fa8f46f7fd4fdbcc04755e9272a884c8b203ed9dfd1f874d6ccc632e1c6352cdae0ad185df8766b7fbc98e3d5c88eecff692c294b5514365d85d984da517f91250ec01d34cd4b676254244f057157bc133d66975cfc4ba6d632dfef473a0b573a37be2e6057c9aee2f5c613a7a460e7daa64b5e28f8cdb7c8a2f363ce3fe3ca42a2627742e6d4634cff1212292885a2172bc4e2c0d1aba9dee058a14678e8d175161e7f67496d41470a7d62c647123097c09ed0d37f87969af253712ee46325721d8c8c155800952868b8da46be0130aaa7c0281428b9ec54890524caa7a5b3cc66616c551cb6f7141290032810a90497e92ff53a55dbacef733bf035ddbff41424858f92d19662f9f258638a3866d800380316c6df0aef25ef8b991cf9c8d3d969fac83d71f7ee00754868d7612fae25b5395dcb48dfaf41785a32ab9c9aa7696fab1f63bbaec439c0b5c477795ccd75977ca056a04b3bbdca5704916350e4aed5be3e024dbfbb8a2763b0b065267f48d77c808464144bfe484b32b6e88a06303c6ea6808", .None}, + {.Mul, "81d4d27d0869943e0bd15db5cab911c1d4d218e6a46bcc47ea15b507a33cacbeacb25903c9b48c1df444dede8f1722595b4c0cabc56c97770f1ac834a3ed5687f3e22f304174fd3cb22a7e2e91ddc3e15288afd0e994d1b78159e104ecc395099ef95dd7b570744f63cc6c457db309813dc432d84f651b7ecbf08cdbc827cddf36646cb590ff715589d66b5be9575cddc8827d895572fa04feec56f9822fe332da292e6bebb78a7f0c62f8d873a034733d49fc5dbeb57c1e622607d396e6f67141dc2d24fc9322a278ca71eb5b92e15ab490afb16f660c631cf92026bf1ff0e4333e7f71bd2104870d25c9bc900134e264995a639cc5d70c59597da66604b39b2c9d4376c0a62ddc16a230f206c932d414f752abebc4f90e1433538492461f9f86d210f61037ebaa9e0e72d5fad264b5579222bc552af5836df056636f51b3a740acb0e5fcc6f6b343f085d3bacc00f89d9d67fee9c18405188c4c5b2797e92d8e057d44a3a9e6af7d8e6cdf5c5f3f50719814248445cb455037d7b05ea7099652b60338d1d68ce1687fe6ce15cbb8197dd7c052eaeb71649bce2353fe47969e5c4398d74679e6e85618e782501702079a15477379cbfea74beb4fb876afdbcb267e08f019bd2d60bf64fd7d90f38b8688b567fa2d152faebf72772c54b5a6010522bffb72c88ffac97837fc968d4ac53a7d5e506c68341debfa845d2a24f7ad", "513db981fd60d7b794f2139bd19fda135096a3478f8bb562bbdb479934936d14617f2a39e9e101ceae6585f6d220d4b4eb56a417291f2972c5f244c06c22bd4b01c212c50b29b5200bf0b7168621868afbde60a338e55a44bbe1eb244e1f544ec4cb3eca8e57989eeadd0c3a836afd84d1dc0d7b957d5a49fa5b89d677b39aeb73fa954cd88939eb2729585bae7b81d3c44ba5e35eab0d63328716910d7ecc00ed1ca24bf98f967a28dcdd52ac36b1a467bfa22286fe177bf9ed4ba39472804356c0f0649c0aec8733cb3cc88c0068232556925269e64046690bb665924560a549fe3042556dfc0f17d7064480a4529b671ece50d2b9dca48c69b36142f91d74f5aaed8e68a5f49eb4c14545469b219f0ec45834f5236c2e89b6561c58b39d06511c8cdcc96ea60b1811f4d7bbe01a7838de411421a47ffc7711678853fe383feb5e55bb6d33db5ffe139a898c5c89f64ac1f2cc99513f3681eb5d71d36a8f182e83dd45215267862cd477384fad9f8738768fd6c4b5bd22dbfdf8a10f22b8c6995d86ac61141e30bb627a608d804758c16365e1db8d1c1fe916c5c20f51de4ec4986c8b178f5d2a847931e6edf57c9d3f467d10d91b262536f6314f5af3dc5ac18a4f784bcd85ec284bf2987d86be78d4f614bab735a67341d8e57afa1d8cc6ef7bec168407190245cb400f0fb56aca132f10645ceb47952cd25277a6d99785", "2933a464704f4660d58160b3c77369af5058c96f62d50bf0a27ef59da1c2a8d4fc7126c3007cc3104841138e314237aee8b4a630c90f7167326bce033aa3016345dfaf7efb5d4a1da4996ecb93401bbc7f3619da30d6383a6a5b03b92cbe5cb5b981c9fc92eea2ecc4bc1e271234959aa882028c041a8092f95a27cdab42dd8352a5570e6aa70e601c62917ff15242a3fcc01bd671af36de98e2e96cf1c2ec1f9636424a46e95fc14165f094f736b81c192a46ce9bbdcf8b006984a8b1d9c7e5c9c6035affb99c1d9b38d51a59892a78784e7faeb53947f08a3bfc842fa7eeb8b64d9d950dea4ba30f40c2aa395fbfac04b5383f0542efe71252e230dcae42442bb4d22e0116815813bca3463c98e047c4e30e864e88abe8f078df2a9ac090918c8fcc6e0fcefde7e6791a7fcdc30d090e92eb2ce51a8c6125834ec0224cad8116b1b302ac8445519d4e3f2a022dfb3fc6ea26113bd3ebb5cd6027f275ead882c3fbb8fee9d6b68dfe414e1a3272d44a358522b3c62663857e0d9c6556805d36cfec9fa0982f5114108a7384bc08e5df99c4619f0ab73d4fc7b3201777a6445f20d8d04ce9c4da8148831708d394f6f821b8ae11a97154de7956345524ec37e824bf46df5eef3ed0befc3b2ca979b420d54ef8b5fdd33b9af81e8d1e33a679e34753aac446ad594202112ec45ef9fcedc5dc56c4b429b2df6353c454ef00a8b594b2565bbb8f7db298b8acb1f66457df2fd2fbcc97be7fbf82e7e9a1c4d8802723a5b2460a5e6e7cf809845a837445b8a4eabbf598ea21fa176b85374790b7e95512f91431a5077bc1391e04d7821e2ba8584bc2d171a22630844db0f60ab3d477bb5ac1a39a90c82e37057b71f28ff772604b0978430ab28ccacb9c979530ee94554cc627049fcbb09ce82f3bb0205562c6ce8c6c9565964070ccefbc2bc727be56037622dce6d9f87f2c43c6be44b0e561050b28849c8178b9d4f7508c74ac79013094d5d9b6caabbfb348fa2f21c32a2ad0988172dd7c4fe20ea25e3fcd3e8ce84bb7704ca27858db4b53ef416d06c85f3cd20be2346284fcaf28ef1c6807aff614345148601f5f6377239ddb4126eeabddba99e284962fc787b27b5b74cfe949d7d2f0ce2b5d5aa1f9b4cedf1bc2a24d8d6391ff24b8f79e22aac86b0691a3659ef741036a3debba16cc31c3d054e36e305072ffd86981f4364b1ee7b58521c471c7823c91ad89193268581c515899855aab8866cb157cdad303d8d11983cc1f4783aecbd5c08b0606555783c14a2a60bf0e98421364a70db2b515454be3b6ccc0ab9453eeeb537240f46894de6872cdf42ab85365083792dabae9b8393ab3c095937a3419f24802f6fe35408df759de926e0fffd1efad08069829599fd7f7e48eb21ff4f086f4a6d202d17cd909fe55c10834caa14f4ff4f59dd2f0b7e1", .None}, + {.Mul, "-757d12bdc587d3f899bedc3beeaec3cc9bb1df559e9703924dd446ad14fc7bdd669063e11af42139c7b949cae7630f497fc580d2da3e627b0d01ac58e4fff0032e24dd76fe515901fffdb55629e59129992a03c8d9670d47b3863028ff72fa4f58cd962245138c958901024b560289a7aa3042dc9892c23a651ebb42c58acc4b32d974392c972174a9d717204d448525a3664259b36666d747f42579048340090a2d15289bb54045d462e38042eccbbf05ed25aaee25a4918c13e7507743a96c03f8a820230fcc5a493d6aa5ff90689df5eafe4c507f99fad9a1bab51679b11934fe833ecc8cccd140716da5195ceebe02dbfbb2c71957568661dbbb1a4879fe50dffb0c753c6c5036cc89c4dc0a1db8f180084f5d23e256b6d4ac2ce5e2eafd394da6ac68c5db3256695ccc9a0b410bc9b8618f81292eb23123d895e5e7957b6c61ecfdc4f0985df181c575bf9eb6e2390cd6c7eec4da45b55ecc09a8ed30af193c7a0146405b9a7476d717be0c82c086c377f678d6cc3f726b9d762f8aae839cc99fffc12c29761d4fc72f39b7fa78e5be8841c430188c6758d486f9d0250c46901a77d03142024883ac2995fbac77b7d9033f41d49c91bb8e257591b6245f67ebf8c1eff804a0252c536d82dddfdaa18e0a416628195f916ad11a6419c016f1f1e66241b2d37e6d398faa391948808d8fa8bcb2300bca2a8a105508409fb1", "9bfe214c8a02912586fb09c4e61fea9125e516104a4b19bb5044c9b3d6cf68df08b0cec0ea7c73ac50b5589785f93b230dcf365b8ae31ff748f4c622b1d3ee125e561a12bb53ff053df456be7f98d2c5daee8e7df58e4dc04ada4c14dc1fb7c35b1773de016ea6d950531fec93e5962775d0f63f673ba348a16dd30e02dacbb578daf1dccf396936e15bc96286a1c60730be3b86cadd32305ac148c2be3cf9a479287f288448b0407efbf0f8f3fae8e0304297e46d6c0b1f5980374f68a59b60b5b2d94f8e9cce66e745e406333d56cf6a931a83f83e3a2199024aeab3e22d1fe87d8d84c601e9225d5537ac49f847a1b06ddbcf4a18149a116c90bdd3c638c42623c5e42e9c9e7db4622958ecc03804aeda3b303c9d3f45d4ca505a1e4571c79387928f8f3e5757c3f78fda80421c58d8f8cfc0341d4a85590c53f7390630769b37244a72376a420bd8286d2bce422389baf712f0ff4d6c9b25d78504e21a42cbf8fa5f17dd9a555d41e13288b8268b3ac32e6c2f423198f2ea5ce3bbd860ac4ec9992b1c9997bccb50dd3fc5170ca3700fb8c5f39839b18a059f5bed9143104f8f9a27ed5e4a35a0299b8a5c3ebb75517795742ed675f95842f09870e54e9d54e7fa3690134f0f040d0c738d28b42512f08b9c227f9d35673dd5d2c8f094c3b31c8ae16b348b3608517393476b90dbfe18a33b6b148d2dffa621f02784bde1", "-47975bb9bec5da9a7effb7e5ab0914bc91577316179375adede220bdad2c4f26c81b8eb4a2c0daeb9420f4d3d3e72f974ac5395b880ab3ea4dda42f7d61ed6c30a6e4c58344f0e2d32e2f8bb911484f1ff93475502bd4d0eb0b6bd3d74a17f01479481332259f2a32a89310c83640fc1049baf18dc4f73868fecbfc10c21b4da7422afe2c73c74846975386ad760b398c11ad4804e6c0373d6e3fb6524bd31418003b3be6a40e01fa93491685cf2c00e96951e21742f15f5828d072831b976f384b4c47ee6ca44b008ec9611a429a8e1bc8b223cd4f7bb685c3343d6bbca9864ee737f98b88fcf3f19d3b3086e1a18f5c75869c9d809ce9ad1a41d50c5a0d61c3d11c34dc50dee8036f3c6057c13322ad41673e28cf2fdf573c6f8b41a88bf70bf7777a8d55e14abac30e7577bbd1251665a1934f47586578b5c652d0262e4cbf170c28095bb8ab7ca471fd5b272871bab59ebe98b366d8f34f4a34011d4287e7c3810946ad1c8996ba6bf726124b508c6cf916161e77363bc1dbce98645e9200c60437fd98e9f64510f3bd6b23e03f1b3cd23108366557eb7813fc890d5fd9941db97653a04c08b9a169ded9ee544dd1a40f6b689efaab6a730385a4954ad351bd920bdb7766e0411f2c49ff01b28b5ed3652fdfc743841db329f8f3c6b0e4eac02e682a254fb4682289a887002996454ec3d5e804b41c8d03bb19575fc01b1d147cba145cb18e8ccee13a7832e5b0a9df2afb7819b95fc9c6eab3242e977128e7fd5334a74eccb45f1dfe54abca4e3d2bc30b51919c05a69b82af2a6868bd447d65edc4e3ca09a1b09cab890e249b64e50284f7eb82d40408dc03d4af16cb25348e6762bb37b6d942c88d4bcd7ef8c134e86aa065c891c478e0e298eaea840f8cb90d1578dd87bb673a2d74089bbcee280e05861291849913d065008e8c096584307db81c0586f307e09ced009e896c0ceb9aeb5c90be7f12286ad95b1ecae7429579a06fff3a0e65cc81afe7fca5cac1aeae30ab5e2fa2b4cb7ec3b0f4cd1ae7dbaefd4de880b2829a80cdece6a73e69c513f0d2e886e6ca9c7b31487a50ab59b0cd825e1dff2b07cffd468fdba69d203959d5fde0f70f0ea1b848f445211a05b7b4b2d65c5fff44f905906037672d67485f0eb18fdd2e7fe7b5a9c895eafb68f687b1f7b38c2f87d3d3676bc515555f28677bc6069cbb724b3de5147af52685b1a24c6249f826651eee3a9f473763b792181594243820c06f303f00f991f61c2f74a0a826e7890b4133fd48a11ca82eae642fd75dc7d01494fb175c4224ba0cd78d4c89eec6e6c2eb33e0a6c5425c87b6a33c0d2a66217530a1c915ddd9edabb2f6069c0ab736366731fd9be92a9670a949ecae191794bc3e822c9a0d3686d3302e0159a15c30eaa0efc7cdcd96678d4e5db6db223a29e72c26a44f60791", .None}, + {.Mul, "-b383e0f93819a070fc3323e745f318d75c094972dbab5be9fe3b5acef4e8f4968e56b790a7be05923548daf837b0e350f48bb712f8117f572a9836ebbc7ea262264b0988bdc704631f17ae046a01d7b92c5e1ebddd1368e9387f832526f409b670532e1efc620b71189f2fd7480e6ef309f3d3c22ecfc5eb1f856ae449679b3b6fb46421d57eac5408387bc032800a63b600bf2ab53e0365274c9bbc3d9b4a095e2bd486dcdd41b27cf58354ea16704d1e8e66b88887abd0157e4c0957e3b6cfa4e37462b7efa66cbdda7b7f7ba06a8688fc9901f204f1bd44d9a7dc05c5abef58e797ad4baf98197c3479494a31c8f32cec0f7f5c6e2c6568d0a1333923375d9a00846f719c96bdda9fbdaf1ad424578ab14dc6ed3dff13b152520a5379442d188fc6140fd50286c87183a5c3db9f1289db28070ae0eb9e4c3ab377be81aaa65171d024a643644efa3dae7d5ddc8ea94f4c27fcc6d56bbf0d8d83a9b9b365269d41a19dbdb80fa9e5a8439439ce321d3f63cb53265358b5fe9b324423ab832a62916390f0908812144b6a4b0f7d60ba77646c9145cd421bd1af6460eb05df871a09f22671f1eb16f8b09871b40a7b7f3b7413fd4ce4ddfc50595237f41117d1aa5dae4d741c4f0ee6c5fb0eb0ce16d19a41694992836718cad508fb3b7df0f7555b6419bd9a733a95ff47f19b06f222712325226ce0ebb63cd4f5e7c82ea136", "7c73c39413d504043a699c56b9133f1691870ef6c886c9e06f656f58464bd9fabb0927c19ae79cb90bfa4ebf3ec21d2220727bf95538e5a8768624a8ea23cbef5de41bce0ae4793bbaaf86be42d2704c21be5aefe306534f46567ee8d5ffbaa816bd3ee4803ea3c932a5294f689fda42696cac958b745c1dcfd96f795799ace33782ca88f387b646c08c5c3f657a51ebf9c56846b63f7696812190ed7fb491cb9d1fc20938f2c1f7167af70cdc490e402ce6730a5a0f94bd1f4dfc422a88f18c3084ab463efd8dbe4c9a532e78dee57f35116d44ea70b5081dd7731b7c15e95e0f00c02da796a38de730e471b3247eaf2afc92bc215b9ca5e70e7470db36675b34a8320f9144c619fceb5156599506f24f70e36a8a73bd55505a2cf83881ce2ac58ff29a4ef4dcee0d1231ede85eb7b808339c5a939a511ca68c4b8e9bf6b6a17124781c223555bd5dfd9b5bfc7f98553b69598276c7bb18ea5e8c6c1e9ac19c84812ca6122db8950337f38f011c4b8f2020f5239cf926f8f8afd3d01f91aa962d3676144210b2edbee70cfe26ab335557ef1721779b4ef6c6c52ab8d128e4fab8255ef4a84e3a8c78bb02a19b7bfd5a62fa9c49af513fb68f0efabe13456b932b489bc4bccd031cb1bedb27db00095a353238bb2644c3847d0f3c067bbc47fddcbed56879fe72b66736a7afd4a52149ad13f07ca90b3608dae5c45f29d9dd2d", "-57450e5c11a4ac4775ffce7afa6d0f84ce683175367424ac58af9a5da615f741792c97674936d2316a2f50ad0ef33c7ac4a4d4849c2892b821cd3a0986feeda67b9a91102103944cbcabd3aa88bee98d81f0d6c7fffbfa4266ddf228c0aaa9bfddf40674fa0090836a4df4f0a33561b396f1a20aa4ddeee642381eefaf1f3b49ee93e05b644ab14fae2af4c53c47617aa149178c13dd156fa9aa577e0f378b4c059f526c3c2e25a6634a3decd09bef033f28aee5181574e39d04322bc6b142ad796dfea0431170580d8141146e7a0972adef7950f20794b6e7cca4172e1539813c3d82867536e3ebac329f161be200b1b78eda9c17743b147eb0d385f7f892ae3aace091404595c55125a2642b7c0e0f1b38ad06bdd618dfd958cbb15247a5fa387cfde4d16a4e6d1fd8d2209599a5678c22d9ef113587a15bf560c02fcaecd523f4f006d6e6b8eb34e8e0ba52ff946b3c7e775e0a3cb190f9d433a67396bf7e99701a748ea78e7131e24ffda309ac5abb629ae623814f9bf13a01d9ee8ac50da46c3dd318d5df24a7fed72804e721c3189f17223ee9ef55b8a9f2a91bdca689dd1054c5fcf326ee2b689e30238fcf2a9aabffb3daae6fbab21d77d00b4e0891c3bcfd77f320c753f4ee9ec528b625a70f2ffb34ba6456a1e46e9639f4e04fb61a2a9c13daa5c13e32beb2f8abef435dcef693b0e3c4d8081c6e351742491144cbb193cb74d3ede8a9fb6a056a4a6ca32249c69a4ee3fe76beccf2b09d87ed9b000f2e746796b022cfb6e719010af832ab72c21cf03e2141485ca50a745fa8972b4e6e8342ae43e2ac2900f9693a8cb9dc856f83b8c58edd8d69968888b4e57df164b426ee0924d55b7d98499d69903697cfa705076a5c8ed14936d69eb4bb7f935ec75a37d5a677ecdf53fabd64a9e63b35d95b5142f7dacb8bb5d1886c46efe957016c96bee367f9d0cff55d08d9d5e93d26963e2bd70c5a6c6dd8e935472f1f25d043ba169363f6ded3086cfa9856aa81402d6a33e10afa0387fbaa6ba7b288e205b0c4e438f24b1b781f5fe6d3965a60b426beccc46329e96972b86a199c92069d0cc03dfbbe81ec8325a64c9dacc8c26b88a65f3496f441a8a8824694b63e6008ce3dac136ef7b6fe5b33c7af23359391b412cd909ff67c5a9ae5005f7dc970e40ae0c3f32d0759c24478c382d5bb6bc44450c2ee75dcd5f8e922a70070ca02e51d1b080f2f7d66d7b3e759f071a376b11700beacc4f8ab3619481148f2e89ac5211cc7d5431fdca22fb1c586e64b1829c2a8488901afd2ab7b73bce5306009b55b1664b8585926958db311146effa70fa6b51eddc22047766e37a3a08dcc66fd0ea69e3fca200396fc0c52ebb458ce6d595707c5445d932cc1cb73952ba6d7be1938fe94fbf29833666f579b4666f8fe9bef2058684849a3f0be23f47e", .None}, + {.Mul, "5bf7e553ab6d8b5d51546f9f42329e851aa261642555a30a63882e3a331f162ed9456eba81288dc7b0a293149e1b43eab4b57e1171f75528703e233906d77c0b6f241765a7bffc2b2b84902c0d5e6ef7e456af95d751a83faee9324b745c9473139dd077124b9e2e91687becf9289cb96aa96d5bdf423c672a424e8dfed8859b6272e756c5544886233e61d0c4e445bc99f209f61fb73baaaf48e3c597809de99db869bb7d5fb125f35fe24dcebf9be483ea7414bee0651ebe687389017ffdb05a4f95af0bf842f00b00f7518ddf10383460695a3d9c8aae3fb52f35c0e6682f89bef866a321d652a30c10b957773c67d959f1f904efed357724a422145ca3a240c4fcd14481bed1a3cba52d1ad0fb50506387a0c4f3fb2db68b303ed484b653d039339f2fbb670627e80f4a8a107ee605c3051be6e986070f928357b08bffd01b40be0700b4adc76d869bfcebe5c27df24d952fbdcc3c6f2487a321f4262dd6c2871e2016dccb14f19347949d28e6e3498093d3a61adea4e1eda0292e112c8037040aa6d993af77d671fd2a6a1d792973bdcba26b1e95a4749de4563a6b85d0a230610e7185d1f6fe6f6f181e3c5d9f70d7edf4499fb20eca2daf127b2c4aff039cae64a3cba3cb091627d899fe1dc586d4af948ebd030e658303b53205675098303f1a5cdfc3f2045c97cefe54fb58153629a912fdc202653069d72640d9bd", "db28630150bdc3ecddc09eb3ae2af3ccd5ce14f444f1e1f689346a5ae9523ce6d727026e80428de7222a7f233f7176ebdf9561fe7207cca0695105a347f0a97af91ff6502752854a5735d564d579073ea344f4d4eef74f8bf55dc002eb8cf9f640a3ddbd9d5b08e01b691c24b2266940640e9ba59adb225ecef1415e8b9c452a96ff25ff3109ab318b11f9c9b5a776c6498de877c18a4aa745fbd65c79e7a4e90b381a506964672c8a43cfd29a064f10f2e71658b871fcaacb6b3f1ae55e7fa5522f18889f8e293e063c842c8df193d4e9fda4e168ce6f347d84a687d81c2a44483dec34295fd8304f627f31d729bcb63793715aecedab760867688b1e3654f5e0a47a7f91a340a554ed13d9929e52ed3dddd1f4229b3f8044406b3b125c545fb799f065b61de664153785e127f29464be0222aebc0d0ef04f9b1bd71192cf47f2fd9ea2ccd3df016339f24db2cc5231af3dcf232da49a5a7fb97c0c0c60b3897b79551621013375266fa87a507989150644da06ca6c1b3f9eee9abef2a1e94eda68cbf78de1f80cb61fd80750eace2ec056910f202a18a27e2ea4ab57429a5e03f4d93016043879efb27635abb9658be18c34dc3185a566477733be9b71a264f24f9c96f1c4f1af3ed465e3e304e0d5f7d733cd9fa82ed8f92d6a3314ebd32bf3d233c759cc6078605688cd30672194a7ea50a84d98057894ab28e51c7e5da6", "4ebb937bbf62640703b2b68bf4a5b5d6e24c09b255802303347854120c2eca8ecc64699ccbcf19b2b521c72cdf91c7f51ef6dff5dbb1f8f8a8d6af022ef8a9213b4121583d8b12b6e45eef1a1fb76a518812c6ccf0ccd4cf37d73ec17e73f9bb357866006e86eba6d6c17976d8408633911aae747a61c7beda97cf891129de8f42bda9e78f4f2bfa1666890bb490400519f372a7d8ea3e48b1d0b64fd5af9246af4989a218a83fbf67bce93f7a85c67c1c136d21ccc7004be77cb8b8d9a7302001d13947d6fca86943c93dc4daee59e0eff260ad6e28bfa339cef95155e54bf4fb3c2615a3f3aec5313d85267327e69cbe12e8aec674b6fdc65eee9111a44c3d4d5b5a52a31e4cc8e9cb6c77c1fd61f404d312903adf0d475c5d3019d3b52220ce9fbfb3593f3d91120bbe34fb5911cf232f4e934a437b47e1e9affbb7921862f6ad56bf513511c60f76062c8e751414b793a0ed27c3b0cef9d940e7aacacb201ba5ed421abce0f49ebad5bb5bda8b5a78a206095b1f048d767b72742465561a0cd0e90229eaf226f37f2472529abe975aaffe8655ce19eb7c9178ee382c01a97884d2bee5434b6095e699a256348845163d3f9be1f654fd4b8950317587121fb265a28db7802d542cccb2d634bf5ff2766753a725975a3160177936b1cfac19b176f14a46f2269db77957a67cc931576f849961a23a49ac27de693e6c98565c8306dc89ac562688bbf27a5004f07ecfc8521065a3038bfbf593a88e3203d3c6e90a7ea3f36ce3871a596e63ca833b7f7fba915793aeaf5cd9581647ffeb045c0614ee3d4eaf677a8819b7284d569e89cbd3da38f9af106af05d65fa635178768d56d5f76e20d7957f5963c50c94c05bebd8ad7a46b45a37076a12cbbd5552a00a559fef0eb4764a97b2b9717e5113b54b4efdd494825d16a5de321486ccd72b408798422e3bbd820d89efbbb4d16f23f61285101c3a0b67655ec610e8cc26270819a40ceb54fc46ecf7d69d8a5179ba31bc5768fa10d483ee3ec0bc3ac0dd977cd80a70b633d20ee8a857642bb6c2a6b513efdcf5edf271454f33369037b007d31d2530576e6b442725bcca178d784c701ca39be5866970ee04115ff77e5dd863ccaaa84463d489ecd94471c5c1f653648187388fb488a512547c03dcd177bc7a8fe4f3621c0d835ae46a0c7c186f81bbb8f5520786533cbfd0e3464c5a43a7cac82890f66d18faa03fa4204911b26e8f2d13a31b034b0d82593cd55949de8a8241c53a5b183a9d05b4bfc2b45da1d3be1de6d38dc4d63793bd21a493f17c8159ac52a282399949e3cabc05018c62ea580f8942e31bacd2b0c46bd4dd2f49f990015dd64ead37bbde153b2dbb049345af618cb2ad22798ed5f1d385eb4076d81bfd4c25589253db72670106109f4151aa5406c1bdd0ddf1e3330435342cd98e", .None}, + {.Mul, "d1883da32186af9cdabeaa8888ad6d46d6ada991f65930d0da3093d4ac2a417cb024c5c44076e5617ff28b53a07ccc7b42dc06358cb13bd6bb26a0a7837167672370c4e53f24f8af962b10e5e44c0cacaf2c3ee5328b95de61fe0c41279d369d307b64a0c42ac0ae4f592f4631dee28006b6632b37e1ab753cf9d8e66e318bf7f2a86f884c586e1f1fcde4ed1a011727c20f8e456926803569bbff71e2f43bcb70c4ce3910b90b30bccbabd6d7e46ccbec01e3e0ee13075ac146fe57faf6b8490d9e1cf983582556521d5e6dcb37680d6af00f698872c7d0240c3978e3785ef3f4cdf586e5182398e2db503a239d16c6ea8208e7ca95f3a4a3f0c102c01d8b0b3cce9a77de751f5ff19a0449a211e91d7e7f818c10b2f81b9ed4088fae0871d78fae141572a977fda7658b60a50a3de2cfce2d9b48fd38e33d3f633da777d76deb0e35a489d7a0167faf937d95b08db5d309e35d3e117e2837934f4e76623e7206b3357c13cbb65d84a16c68a7ce224dbacad41decd75e7047b710e17f0dd0ef340c767e7681bc233a0967569434d5a458139692c2fd97a79481988076def9d791b3cbe7f07ef36f08b9dd6875dd3150944bba7e82f6d600f12c39fcd1b48376402ada089503cefc03c812c35fef342e0921e0bd5c6b6794c9ae772c505f7174951fb8c8bdd096630c019f9111e0f69aad4210a50756925e90e25ee4ef06540e", "4ef236bbcdeb96c01e6551860086a146ccbe1fe10556ff7c6176796abc02c38e8055d59c0073106629636686e7c530bc98df22bc7f155c806d7580a6d1fca6178691dbb2c943899d2ec8e1db3b58e4b0b777ecb33c27775c124f2c3d16118075695c0f50cd45b7210b0d847584e4eb0636404fddab13d99c6508863357a2c611c23e3e1b88bf4c5037377292954028a7a50a7f9dc0fe9a82b6906596ae85bf197122b9946f68863be12cf2d79d9ff895ba6367060429b555d1747e69f97b2867df2012ce8f79512de422337b493d764b8a689d609ecbce0ff6d65bb542cd2441d518485524394302892243661d1185f95fab4eac52f5e3180c27798eaa1dcdee5501fd45e82856871f87eedd70732f0643295af77416faca5017c72f9e9513e50bb146fd04994c5e60f5308ec7dd94c98bfce8a47c546fe7f1539e1ecafc0889f6d0e6369bddfba267c3962aec84e91177f6f357079bbfceeb200fbb9797d668998ff5d5bac422a6c5fa68b510d472db3ac66a6863c5ba17e09f830fa277502fb797cecae02442402515a776fb4a795bad16cfc060ebe24ea328cd34b59cb7cbde1b2cc6c7a5b4a2b91552db530eec999382bf9d29071babc5fadf9f6d2407966c825da7030a53c37cfc745af15b4591cfe8a4821550c016b9f53573bbbfb82c12c3f98b43cf7e8b036eb3b90d90703b2c00e33171633cecb738f0e8542d58dc", "409dc25e6c7d16defd1f93dfe88f983aaf613c17b3162f852e8533295d4608906478e7f5a0dfd64959685a9420f0ac09299a934ec149c048668f4218f9a415aed9c94fed2084d3ed8df473acdfb2d2b3df8e08432cfd1cba9728f87f9f288087f26a23e5303ea269288097df9b202661f3c32b5080a05e42beb8ef7574fbfcd2392d0cf593382a2b549668b0de6f47c905680d702d0f0668fab851310194d956a6cc3d17513a8d034a6ee254bc4ea792a16da3f59dfdf938133a164bf6c499e8f5018a4cf601c3c391286e4e1431f328b5e5dfc9d080d2d26268fd98a54d7a116ed31dc6a1e4686d753d4c1d0501858c216d25997de256bd156c0f820825836fc2ba02cb604d166d43acc91d193de478c44852b19c235ff4dea8e3110285489078801a4d3c59e35fd056971834a0b5167fbfbbbf0fd584be114cad5e3abf5514daa29910b2127c7780fa80152534f2718b49506179bdcb4fbd983520b0fbfc8f898f95f6dabbaea0e7c3257cb2f344f9aeaf74aedf526937603906fc50c801b77b3db1369fe77b9859e6b7fbcbb88c05abc1bdbef12aefadc18d05e71d3aab93efed6ee86a6c8fcf029148f3ade15ffe340f72ba7d7f1a1f91ce0e94cc3fa6769af5cde3511702adc2aaa8cc5a856fbd371abb3eb784a56c927e190451ceb3c9756e58e978bc99d36238b1ae4838c8299f0fa31cb81c4bcfe1d0fe3ba08750f46583f1027c608f3fd38b090b7eb83e5fb822a01a9f18677c873bd94e90cc4dd726afc4fbeec84676310260d462b9f73414da4c3d8cd613680e99373cd513a3e2bfa0a821b3be5a281c57b265478bcf8bbb9234f3715c6c2bf3713dad6f7da121aec566e40ab76164e64c71ccff470a4f8da972fca3d4b60043419ea8bb31237679fb0cde994a6d8bca39580e5ed998824b25f98b288488810c6785148852a5721dafd58ba7252e4a942fab3926221aecb7a0006c8729d26cc0d9e27b74c82f8730d69ae2547ad60f7cedec8933d3edc003185278a1815fbb7643fd363d1f0739d009cae2d69ad0a55b666ccb01e244caebfd3aafc42004a2654087d20880f4a1e6710ea708cd3c46248d812b6d519dae6eac80c9f6482838fd5fe09adca6628d00c6af803ff6e8fb5586d5c61892ce097ccf45b64c9f4eaf9852a6a2515c07103a087f9a0cb9788d34c201c8b41b9742277085593f1c21ff4971df94ed7234f34d08e3fe639a2aecafc0e8b2f7d0d979a87a56e70c3d103c2ea667258df6623945bc979d5065f35a59bcada6ca8c5a4add82a6bb2faec561ba40338e01069f207b2f56661846d42ef733f6bc0ddb4f3b6ba1ac9948abe933e278e5a7c73d4c8c5d965619d17ba6f233ceec66b28d58404d75a037bc8d373996b2a21b64be1513731b532665cd7a2bed73c2566a4250913f8e69c546e13def116da348f4cb0c08", .None}, + {.Mul, "-2c8041bf43b2c31f790ba36d0e7415626eec6410713eba047ea5264e9a25a7b722fb1f62874de7d1fa9c550b7797a1e33eae86ad700b3518a7d481ad16cb81bdbb3dc787faae697ebe3b1cc48eeca5eaaed42dbeef12613e9d87d687d3e0a16b7335a8f86163a30686eb660bfac07bada122a699b8f84edf83c82bac22a736816f376a9c0c5599b571fb4354f13bdbbe95e46fac7c70a608038f8f8b9c630548255fdc3f54120530769e2b2c648004b19e7b7f5b7c935807bb7b5e50a0f020deb29ad1e9c4fb8aacbd566e432a495bedfa938693fdf24cb42cbea209353e9532c9ba5512bc59e007fa089c703468236df85a7c5f0bc45d84e814aa9eb96371b08ef21a4606d2cfcd6b2e1f2462183eb5ad189510383c60d16c7fa20be8a44714b435cd6a530834d0ec16f69517fdec9aa8ea92574ce8e69f3adaeea30aa9b8fd065b0a541f1a41bdc5d7832cf5c7c900a801049ede5a5f282343c6c9367a9f0b970c14765939ac94c0a2e9ce6318c94fd6c2e5721e0da22f698082768007e9010c32761cbfe74c9c9a22cbd46e2bbdd2f0d962cc9429e0d3e49ab842bf4c3e333692f041c22c8edb47c73cbae21be7c57cd528cbec9e83b2831011c33f3c6bfd3d4bbe9304369318dcf8262fbbcd53d01d9373dc6b9ce7d0bca02556d9117ed51498bc6fe15309036dfbe266dbf001fc3263210f550ac3d7736807b7691c014", "af69ce8eb989083fed42d5de1ff332aff330fd153939ab78b28b7413a006671fefb9202dd0af311cca64eaf3c28e426c854a66e92882e331b1136962b97423e28da001c3d856d7e159c84b671a4b7e8001772523f9fefaa64acfa222708acd8bf003a8254b42ea975b0405942a7bc3197b36419c1208e0d6a9510fa6a5d7c4d1ded46c50307cffd0662d9309dbf420e694dbf627978b06f2abcfa400eb4f47f10729460bff3e651ead64ef8afe9de271b3db988b6605f767600a8e15fabcb768003e2e96bcb0cb07cb5bf68f60b6cb1417c51161fb92b378e5313456fcdc4107a7728d4ce0068fe821336a98f0f86793bda975dfa3a729da257869b959fd023b8082bd711ebd5a83287135267e12934b7eaf74391df7f4426785ab02b37eb3017b29886c69fe76987899df0a14971f4549c37f97e5e2edae1150b2af3591adaab77050c7a63ada7dfef0b61e122065d8be01ad6b7766cbbe7c909398d5883ce101ee31ef3e3d7cae9eb3c6a95a2706ae41d3a9e0c1da1e1e33bb68e7fe3b37c32643db42074eb8ef221e4fed4215ed85b19ac2d01781a0168524da07010cd7de444de169159fac3bd92f07694c4c448f443b08205cfc25db13ec76b3f120e6146a7e50a829303cf66441be1f553ce1fa3616f03fe3d40a857d1ab2e504e3182e44ff6c449529db9ad06de455c2f10d34f89cd80c73f5b84e92555e3348573cd7", "-1e7e1174bb06d9db77f71651d871c9a4ffa9411f14d9764a728a1e7747b8f8b1871cbe28ea7ae6122c3db8f9931e9a86ac3300be37f9e9bfa600280e2f1fbbc6536cd2ff812929596542deddfe0181e5c7b70b777b963f4d4320cbbfa7f0de4475b192b956aade71caf2efcaf8ec35174d2962be4074aa038feea5d13a0276fce38c08ab50396864da885806cf4c1cf1e8ba589e708d1b03a38bab7be3015fab094c07aaa558c0dd6e2b82252a8795056bbecbf80546420998756849bbfc700b7e507a16eddcd040d21f8a23df1285aa0cee9d6d7e0224281173980f07e5c57ae526fa3aab6bcc4cf64985b058894724783980237063668c3c2e6e728e56f2bb36035c29cdc1f9b649157bde35df12f354f0d320b26d30f25e455a0d730bbd9d720026a023fbf27d6c766eaaa264201d775da9174bbb95feb8e3030806d67c13916962a25a68f3fb584038fdeed79a684c692b75dd23f7e168a05dd31fc4677e01a5379eeaf562d5c33ebe3fc1a8b0d12165705f71f0eddc177fd598b8eded0ff051c02efbbcffe09f45d175d375c7758646cec8e901cc84c3ac6c2656efe55d9309746a07065b98548fafcfbd5865fa2f5f0e107b1a42d2a9a5148707b6f3e20f9f0885332835cf1eecb76b21a1df616d729db19dedeafbe41f2573e61810911e371eb5bc89049b5e1b42ebc128f2f6646934f4b8c738346b44490aed607b58b18f862822a109205a9bc8b1a7674cf235dd7746f698749a76abb4a4b578ce2a2f2839792d24f2a916e63049f1c49db52ac7d919384c3a31750be7a7bd20d2b4c5a8317b756a8ba079debaaedd159688bd86ad69cbb2eec7a265d2cd11ec5be671582cd289046521f450ac54e00434ce45924220893128da1820ad8b94f522f8f4a70b263b92a34e335842d9a15c748fd368769316c75a8eda877ad3f83c0fbcf01db6b23431a3f0f9b3c90cbbf49ae9e2ca2011a50d76fae37a55dd6e5496c9239695bfab05c10ab3e97480a60e69839d4ceebf1d24a6958a143c451b93cc99190905c157c0598dc0771cdb5af238d0a5abada8f0e8e2a6ac2fd124cf46ed3e0ee40c43649c3267938332e70fdf8b55138390ae0a592d457fd68d19d9a70368f85dbaffa3ebc14ce36f345b5b267459ddd05dea007d8abf8b617d65d2548ba9a12bdb32ca5572157d77b19736471c202256c0ce1d8478cbf3b1282bcc07c2db3a8416594ce2e3832e885793a38b52b800300ff139109f20c5d5d8d6142c60756739d7089fee0e7ee137127d5cc0e2eb54ffe780724a8bc8b43e6c636faf2d7f4aaff25fbf489503f6d461c7a175706a2f552ae7da167305882c8bbc8738c06a377599651fd7b22e49392268ca6928cd0d28024b5a57e5080d6f9f56e3790ed35c52c3730b26dae5519d9e239a72e053ebe578948cb39629a65bd04a43900cc", .None}, + {.Mul, "a2f8d230a563e4a6a376e35720e6c2ff104e31bbf7bcc8f18fd74f0635753dbad079e81fe80baf6b5874e85bf345c232d3fb9d17e838a746c80fd308a1f8cabc295b347f5e12bb6906124164b5a4ed43c1ecbbba1568e29f6aff62a11ae518691cc538ea2342f563ceabb1b2333a6fffc984d0c394278a155054b7f5281d798e8d63f814af83bd31270185a4d0167ccb86eae2f3fd43c66069076fae7c64638bd2b0d2db5611464e826169758a9f36c7a4a059351d60358f74ad8e43101253fe7f421bf27fbf9002e55dbb51fd130cc3df22b264bd43cd876d95d361dc88ec3fbe184b1314c010439a1292dba32e89be80b8dca8fbc1bef9af89e7487ecc4b1cd7d525fb0b7e615f66b2f8358ae3ac1cc7e990848c94b0198c5a62875142a750149cd3e712227c2fd1d067587d81a8cebcfb5aeaa5ad9330d09a89250a41f1e08b9f1631a680aa8333c0f99497d0ae85ade07fb4f0288fce1df9c780f67db3c757e2a2440ec805eb97e6f1a48cbd256aebf65d7821a66eb8a38253f4e746dd9e1a110234a2c72983a8123c468d51530921aec947dd456138b976c504e1a8a84c451f55a4fda18a74e903c1dc41ff7e3d949711f373dc6ed8734993e29579efa5f50c73660c1c03ca792c0f07860d40412a384db29c98e93766378f1a40ac80e5d2a084f98732794725d5f20f4647c9ab7e7aedf3f28dc2c0e80025a62b35a147", "6393b2c7e3cd1491dfc05940544384bcec460c940ef07f10c011340eefca7ffc71248f14ee7d4dd5b7aa4ff76b7db947fae2b888110116385c4b0ac2e16a3eb5558551b64662c023297dcf3f127210938d3c0c9d63e01820ed02a98de5bb38ec9b8ef481cd16e294c03b9e7adf82b59c727b1f24d04763a24afd6ec7c33510103ab678c230f282cb299a40f1d2cf3219d94ec02b09510e1692686714bec1846dd2aee0f4d07252377d93033ae75df992c633ef80f67af9a069ed62c834a776a3e27dbeccea6b129c4640ed3897fa9f6e439e5e64be8f035ebadfa49a04b201f66dc367edfd69c31813be40846947595b52829c1f3d337c2b92e89bed5cc2cd75a8ba6e1d5296efa3f710c4baafecc2fca4671b945d211017a169874b17bd420040c6e832da2777128c408e62d62df2726236d7d1bd3593d846b69c28c98ecbf47f38298b3468880fddb445da2d067e63ccd6a14a6cc2bbb65d7312b758d8d913fd1c6eae7988f395d76001be7095dbbc2d737e59e6bed5694df933e15215a8a77f13955027a3a207a8731d2d9a1e66210d0b1e8b094d76cb62f9bc0648c16fc22868347c1fa5ee3a75881709f733357cb5c75ef3a9122159b212a93fdd3477aed3f4070737aa5b365bfaf7ebeac6b6ceefe80569b8cbe706d6c9193dbe4397dcc8f36d498685e4b7fcfec7e7ed9bd2595763d17e2083f2bcfc81da577ff29cf1", "3f643ff9c47b015283f1841fc98d6dd11522cf099a01a71a0fc349881282b195d426091e171d51f431ed7c004bb2bbf3de5f5d39196e068b1afaff5f7b2b0fe458a9715f22845cf88e8b4bda943870000fe1bdadb6a2e36cef88484bc3b2cbc2849a98d628cdd8fb2cf72b6405d9fc7a71151da4ac1ae7b46605a045680e583a809ea8f20e1e99e8551199f0bf1e7bef6bf98ab0f1c628f9cbc4446a9e056a382def4f1066b58996521321e4544eb3d9ba6e00b3a39680d441c4782c27064941ff3b362120044745c80e6af5dbff210a2f6d1016430b4a1d9cb06f00a46c722929b9ade6e7a553d8ba02aa9d110170f4a8628c4523e8b818c24c860c2f2c4b3301be949b7de35b7730edcb833527cdfe90dd3a2224808a73037c2039ff929148a664268d506d262c4e6e9a864189eb6cf60a56d8c259d1dc657cacf494fea634e8126c88400a035b704eb90d095b21d0a020808c5094e71ade2bf1838f9fe1b258e694c4ddf0a602b46d95eb5647f29e09d22d352fadd0276ba3e3a59489138a8e65a43334561084fe898c8a600d477ffb1dacc70348c5ee681d29891c76c1fd0a4b959c7daea4e04321d2e883c55782d561353ef3667692c0d1754209832ae695be313557fd008988eaefefbc9760188c4dbb04862f74b13bbe6690384f9ee0800d7abffe4ae665334d838cd571bd5a89f23c5809119a4ba8b986e3042d4f14fa51357889c118c9210ed8ed2c15746b49ffd79ae85924ae9169f6717ab677193dd85634ae174da6cd1719b74437e9e847dd95c649bbe10d55d05bb8cfec9b53e72c67f6479504ce3164d4e633ff52c64b5a499b4cddeb810c4411acd262f852e2c467310e4fe9c3f25beb75fe4f2a798b864d067a0c0d11124d593f3dcfed3c3e7ab2fcad463e5de9a45c61a4a719321b0dd8085dac0a2da6850b358e4873fa945e7ad106dffbae97647600b86be9804d31d2b6a5aa559087dae9c709538d8722e1053717e92443740d69bef2f80864b88ba825e5ce872c0457108cdb220dfc6d099baa216b85065894794c63ff2e3a76d2e22650bada499b4292f7be7b1b6b1fe30aaba7af2b6b3a6086a559a9e84571a286a5647e22d82b1116a863091c9426d29c07685a9f861e4f21d2f558d88c816ae7caffe6f528afdd3219bdb813548ce83135e54796b95f1eb397d351ae83d19af12cf0c2a8ba130fa01ff974502ead67477cc22a832ed71ba30362425b575b49ecea645496a0e724acba7f909f07f193ab426eb87a4f0fd3f8001ea11f4a01963698c460f2c5bc6e5959adcad1f40db826fc59f5b76517551ae7c670708339d247f4f0b5b9797bbd0c26beb489977d4827dbe668c504a3a593fa5257cd7e1a7da913f85ce31ce22d26042baf794016a741a6c9eb39ec2d9bc9def90ad56d37ebadc3e022b2fc08f06c9909e217d7", .None}, + {.Mul, "-3a61d557d5a47b159550bc4ccbdc3e2cd32987978da10b1559d25b9aaf4289fcb5fa9100a2322bb2e20c949ab1707b1c7051580aa4809278299c3337b8489c92d55d00ba00c07f3840eee30fa7fbc84db60c926ae7ddb660f6d6c31cf3a57bf5f9e6a257d2b7f5837e189abea6d59f2333ded2a2a0ebeaa7835cb0bf27e78971ee16c823d64953ec70f0648b2d1e1e9c18195d85a559e5bb47094df1ce2f1e68c04138f4e6f53c7fde1376741cf03e0ec61339c2160b74a6801161d79a60c0a97540f1ed31a71bb5c269ecbfa1851c7765d4b58d1455480391fbbff778f20df227dcb3404c5a26bc829166f61bbf6366fd20693f6d754af2aa3ae9cd71cf06a8f9a708475be050bfbb693f3aeacd4d9bf2c96f4bb1cd9902a21b8b62830fefea5d50e878030a20c60144d1a1c4dcbdceee023a210fe676c95d161c663b8067da0e63023d1aeac59deb4a10e2c8d2d9df82b86adbdb69e2e8c65cf56f63c496b5da2a52350b9b5e0b0e55fe0f4adaca00d8fa4398fe6c6cfda49b7819a14d843409e8bf37da37c01f4d4351c4dbcd230f894524ca656009d738cbb98fe6dad5eca2f2e3d0ebb89b08af05c4e742d3baad15e4e662f699694bc3f717d57c6c6786e06be5830a8b0ba11338116f96ceff03d79d11c73c50ca2dd055e920622d69fb21db1624277b764165dbbc107173505390c1bf3ccd1b1bc1000821aa89203d12", "f04b0345cc2b978e5317ea3ac1057979d18449b4654d1f6abced875aa6dd8f6129fe14cf451ca81e0ef46378e5924c66a87f6906d7a195e0190517533a32529937820e4142b471071b29d715d4ae6b0a99e72c196b7afb9d488f8f96cc58728e24dc39793a6884bca90bd7c317a285d8b69444372ab76b8d14bddd12d035a63ece2733c915f902e10d560bbe7ba40f36267add6ab41e6ac7f4b3ac2831ae48fc07e70cafa3da6e186ece1e2b02f7dcb3365338068e9e350fda36511a08e98c36b5c6086cbf3f4e89b34db845085ebb827bc9c4c04b962fcff926d4cb5c34fd75de93e44aedc1e98f49cfc4de7e5abb43c0d3182a339fce54e9a69a9630b0c40d9b822a80f48e8fba53c6eb3a260c3f36c2b43871a269d1d839f6ebefceafd0a02c328b5d2a115b3fc8c1dcf805910eded7955fe6c7f29087edc1465aa6607e59d022009a1ef63ab7cfe40070a2947af4bb019d548b4bac46ebc07bc9074ec05367ae2715a2fe6bfb3bdd289754c8dbd24613a359c3a7e80b18660a13ab3f3db0ed995e37cd46d58a61a9c6f7b10040acf2b8a425a84c53fb98d7d3f042ed5340cd7905688f9b57c87ff86691e2646701c71c56939e9b5185c02e0d1e339c08e5150b1d1803341d92b6156ba61dc588e1ee928b94a9c0ee47c82e94f05f3b9d83650397171b1fbd3254cb32ed974ef28c8ad408331e38f28e8352d6138da42277", "-36ccd36ae97439c2cc23239338626ce1402759d4f359b542a4d20cfe87ef4f63620fa0636aea7452cfe4945398ee94aef08b32ea7ebdd4a3e1845f4566c4026654562fb10fb2826c0c29e9f2620c648b858308560621b1721fb05479e03737c48d78b85f80a3e424bf9c89d447c47f0ea3deb7cef76be042619e090141296630bc3d4394e58e30be04ffdf5e48319bb510880d24a47e44fb2163106fd4b620fba2230c81adddcc85cad09a8c4f7dc35d3527d263df9ad1646e51b866c7da0f4854380760c9adc85bd7b27b5ffc311736813c976772824dfdb93015568e86ff1dad3f2efef40e4fcc75df9b8acddabecd96c543446789fea3bcd0a138f50bdb94b224c99bece4e02e4c61709a6bfa4476ea4777d7066d3d9e5d1e83c9db1c822a50241f9051dbb7507c9c773fc9f51b92370748d164472e10a472b9cea29156ccd2265eb4a07025751771172d52a1d026d0c3014895c07673587d1af8213b64c780bdc15d851813b6d0bec4666ed98ad76837472b72080cf9439e3f866630afe5ed4de5b0620d18f7141f37413c7d0e624a00a10239ef268d33c84a87f97897e7dc1db034ebc037ffb4e82b60337c0d06e7a92087b433cd304f4019badf9f6609e074389da3e02c765003535458dcc0272e82f5b1d87dad1346951bcae03a8cc5f4743d6d82b28461d7862369c714bf151b22b7ade29172121b049ebaf804d65d1e14bdff3f5486ea7244b45195455735b4a78d9bb64632ebab7ef3a41364f40401176bab42fe013b6d60df0d52987ccc1d2df29920ace4b6c8da7ca8f03e3f8228e04ee237f57ab92c36a3a98a4152f1311db19438973b5f08135b4da02f4c9f4f38197ac4adcfd118c4b35c083800ba437b14e8f26b7c6a7db3e4f261456a98440fe92d4c9629147f096cbd5932b88234eb9de0f6c29336cd341cf4b74bb05c6b9ecfa749f38739d5387a9e24f1caadc9a61809bfee0b9f2086ab064d2fe22da273af3ac9fec1cd8773c3ad139a70cae7f3e13124ff1db2857bd9d68ac40c2a4354245c2f5dc20a0c11aabeb436b599c4f95cc5fec1a1a12cfe2be634decf01f0d187368829fd20b3dcb379627302da25e72f888290184bd5775f70d375e0233f009da4cd2978ff28a57d6e43339672f757f3631ddb292005029bcbfc84b574a95a5a1c025233621d1255c22c252fb14cc257c64f38dabb6aad19139b965432f64cc83ff7ae9a8d272ea46eec5e055559eb602002fc319249256d6c1f7b41ecec3852d7eb81f272666b11955e3ab17efad1c5b05fe1a8d5ae6903fdd1edbeb7dc053e3d9de6c06d04f78960c3cfb7001c36e75ff9f00ef8d6ee1d311f0f247dd22703aef4c39502004596105610373373bfe167c175f35926bdd6284339f947a78c3d100056cefca38c297b745da8e73660405ae10966517d3c7b1c0fa0c75e", .None}, + {.Mul, "-4e2fc7dd1399426302e1d4b2e12abc548696f5e3e26a94e5be07244b4fae540329e11ab5cf5d2351bd02b00e5e4ec4433e1475e78cdaa18f588bc9964282dcd77b7391dc9bbe37dbff448f9405fa66f7136c9e24c3001c01d5c2e16ffc6595af0b244a69bc574c3c7291060ed3573eb41eb4a6e7b5cb8ac2639b7a268549430d943d08372d9f7136c39cdbad7153085efe35e60713caf268b64a078215349039e1bcdcad88ee85d7c9d4b91f18cf7f564b230d041c1942d27b15ec195c02f38a7a7f2213e273fed62d05e26ecddcc14e74a03a3e75747bd627c10ce7f3535ba502deb2ecfc8d310a913ade5051826a5d4ce2937856ce3f6841bef9aa61918ab002af6e56da7588623de1fff75b09b38c9a1ff2d75271f2384867a43e0adbfadcbdb5f217d8ad6bcd7d871507ef208679cda8b1c4677b33f41b63fe3a215d615530b3567de2cf06d06ec7ab31afdb64d3ec60f93095b53f80ca2055df4b9b5447d36047ec802c2795a5c5175dbb1372f5ba039aee353f588a5ce12b797508cda3ea58010ab3537dcf267aabcc035b30262d8687a8dafbae9a036f4bc2c6b4bbc140bf708092779794ef4ce9c5d1a1a847bab292a60df63579032b4edddb372ed01bc90f2fc41dbfef2fb649fcd1ef88df496e596a353e292ee6837e19b82b5977ee77b408c14e8fdae0baa34bde39a6faeb7a6b2154be1b22b0620df31804e3c9", "4abb521db8c75f7cad6426a636e1c95831b82f2773b14b4b8f05c1779da43a992d33034cec0e0a4f9969a9349eb25840cef888401ab31f968a604707bd119290a502235cc44625aaedf168098208e70c2d9145a6ef8d0341ba59c17afbb927643d22ad2de947cee18136917c5203942ecfab1a4918bc11221d6d55d8485bb0b3487067caea1d27901680bf5f793adb6e79bf3a1d7bf4f9f481e8de42e87387077ba6c1beaa9d547d0d93042b4c2811a8f9533d37c913c98393140d1f23c4f28f8c214428de9d01613ee897ed7552d3affb2e5572fbe1853880de0bad72d84ada1099b6968aa298a3e36ba79f83145784147262042b51d8f40659cfc9bfdb72dd7c16fa6d41bacb2443c33bd31d5668f37efefa893e1ca57aa472acdc4a02e5de1e74e561e32a28a3e073d48f248cb8291d23ca4f006fd43a0445476f587f5db3e0b92dd0b6b2a0878def14694aa027e69111054540415ce696c66e926470b8a751cf1223584fd9304730e0b38b9c053c4a449a4f77054022200cf9c655b5c5df2eb16754bf8c385d6c2cbca3d5aa2d51fa57157147b7daa4803e85fa85f78ef67f404cfc076d7f7e6db302c6305e69b3cfa4a7b5afa1b65d1a4cc689c6cb71c1571370903b7d3dd1a29419af3d4d30ff80053352cd89c1e6be2972895f9a816935be531b26390c2d428b2d7dc6814d1209d6c07121244fbf7477d574784b6fc0", "-16d305c148054e6b7efdbc5334635b235ada3b7d9d3edf2f7ce519f837b53a9ed138cec74e3a69891abb68b38a6ef1507b67fbbfbfe595a8a84fe51c26a39a30b0324a4809030f469cb113c336fadfe1022c2c22599eb34bc37c3816a14993e5c1ef650c07d1f80f38db8c5553c4454aec65e8fc69199aac6739035f465c573b1266e53e425ae961426c018e365f2534e4ffa087a07d7a45eb5ee53bae014f48d54f3c58e31f8a614b18347014a476cefd1e19c2162cdf16f3ea23af6e34f017148d91e04fb4fd1bba9e91033263b92c5af491a14d3ae735811f0a7ff1a860ec267376f9f6aa75317c3509bdfba76ab56e4255e91237b71cbd92fd24e13361c57a79d7f5c281feb7e20dd33fb457a1cb901e837e893896f3179f22680813299edf66b575ab9eb99dd8e44db957f4ad5681163f10e7dfaed4cecc0d117e4b84e7bb090f7673ff2a8e98257fe1534103a4daf6977392c5fa4f959113dc6c018089cb17e45e2c6cfa50a3acb6bd5e01bcf964e017aae2e27b788d54d35c3c2885a07f660dcc717dbc9c90de6686de7994fdf3ddc1be8d4b2ad2c667ceb464450de9062b73ed66737518427a828f6658a04ec67e298c03c4dd8b71a8916193caac2795dd745badafe3676f9d4a59f96c4c1f77d39b6426f1e2766c7146446f4c5fb10493aa10dac38384bacbb60ae17406cb40bf17a60fcc2060579c6d2968c2122d55af0e61ef66fddffe5f8bb2625d2c8aa6b8b48a1a6095c9f6280c71debd9063116b4425964367a755aa96c6da771e387ba745134a46773e1e921adaaabc9d94e7d2707a8aec492311db2d21a073249475653e178ab659e00153ffad7396eeadadaea000dbbb215709e000de62b128ed7f02d02554d7a876d5decb1ce25b101a1650c2aa4ef8f12c4b0c9ab807553c532db959647999869fa1a7019d22e966028fd4d690482546b4020be29261f2c29c8c0aec20af790dc593ce3752011ac1974fc52af3ea046af16e05e690e2732f4cbb4a88c40a5794096e6ecbe99f197b81efa0bc5c35a23e5ee1a312279ee7b8865b3327b1f5fb08e4a4d78bf91b1e4d61132af620005fa1571fa4e484c23a3d4d4b7a881726f6ed2b1da6abd3e8b0ee9c87efa32c29d25d4b1f9e40683201b79011f7423113d8b4396d85a36ca7b1e21c59c79d9c84cbfce5b3411655810f3efd76c2e1e0e9dc6d9f290aee5840ea8ba4fd449f6a013eca4437c231577bff3ef6e92d0f474471cd441fbccf6f8b756c1f99b82ad62baf5f2e84131b0d993084d318da57f6c42e8773080c4a74494b53d61740bbeae5a29511d8da548bacceefb6204e3d990f9ad22cb60d33935785dd4b59305e91e1f9a8518fdc0fd1f470f1f9c4ca4af035c0ff4fa19874605db783d08cc1646058cebfed9ac5ede6d9cccf1882490c16b650f859c13da6051651fdc0", .None}, + {.Mul, "732720c4fdd54c9a140dd1e7771c32e3b21f7fcb8ab0e60b2a01a375c9516eb652e3cc5320067575a8b49010f6af63399205b7eaec04c8e000adfd414c290c92a19a46a33e6cf65e24c6590ff0ba09353bb53bab174448edd4f158614eca4974ca3695e3805b21b90ae7309c8d907016ee9cefa7f520d5a0cc746e44941905b26b334b530939a49b39b9af67c538235c0a32091f367a18c9bf63bbc14b947298b3c43c1a786e3dd121c551bb191cdd9303164956b4706f2ef62feaa6fa66132c129dd609e1ab7bc2338f0920a372bfa3232e4cb5e52e5dbe12ccc687e26723652b695c9a9fdb8d592fdffe695d0670d95e2c67294a2c68a591fb0aeff5d5fbddcc4ad76a6bc242fddb39d1225373520ea337ed136821eecd2803ddbf9ebbd4a369de2a452b2d11024995b054676d761adf36e082b65dd0f85c749ce851ca7beaeb6221d076b5235a394eb84d80ae816fabf595385ff6f8ddfd3f47f0e42bc117d3a64ff84ee4d976aa1f9ce9bf7a8611218ca207e708199b24fac4fab99e12e0dbf974826880a5bd1f340c0542b9bf874057cd0bb55c2ca61b46dd6aba43b3fd368f2c5b7ef8cdbbd13da802429fb2f6ebebc59930432da8ca763acfc46505b93a720410b32fe4b8f51c574676a469760ac22071e0e7a3178ef9d3de43b9f993187739a09505cac30c4b607fbffbc7fef6df4e9b4363c1deb4445b6fcf2a30ec", "ce0277e9fa5bd2e778d09f5a80c9d0e0fabbd0cb2ff9d798e37a6e3c3a40e61ca6d6ca50c7e526a093c5ba8320299fed60a4ba504aadb9c6b84a3e4f4d88a9b173b66af38c9529b3a1c46b4c50affe423e062a465468c3c6f3b0bcb544f4375ad182bcdf89eb1cdb942deb0878c184d3dcdd512716757218c8d781a887fff6d9d67472461c9cf67f043decd2ca214c5bc2cf8dccb78316d1bc6228644708c3c938b6108491fb652684b5745a028f207cb4103086436a1ba2a2f59fb125bae5ce7401e8106a1b44a30ea0183a90aa59d34a1524507063aca91848d5622010a9cb3a9adc8c26310d4ffe6567664b311435a2354532d44a627d70e41138b4a4429512f0eeefd7ecb4d8aa42a729567d65ea5a2ebd91e90cb3af4781c66e848be2d02ce2259ba44ad65d37b33d6de9d5083295905a9af0b508b22067460f7cf31fa77187a6f004c29c252921931faa395b1c79dc28a2214b1b091bd102c4f9f062365adf00ce03fb6275df76875bf774fbe070f4dd4dbe7080d23c4a64257c65ebfe9d599f83c51150d4e13f88934e5a9364d9d30773f5f8f8a22dbffad3f2e18ad4db15419e284b4d029438e64b8177fb0b03487747af6b2dbe3ed55e5ebe81e175e033d925b7a2b39ccc3137a2c910cd30faa90947eb8dc1a68dd0981ce98650fb117d2231bc2e034a8ff39eaf3d1c406c67313ba28c7f50f82c6959d514a689a2", "5caa989d3541885f00867f02438bd6c59f12d389615ce2f1799f7ecab240748d953e85d728d944f59cd824af526168de779c21b5c6ed370d58129c58bc7ffbfad5998a0d58ce7ac15825aee3759e019e69ec40712ce749def0ceeedffac0cbcf3207de361f8c28bf6202e4697d5a05aac90c2e2dae1db5c8675f5058d736d57632634f195db3b2896f1499d71d888b250c616b60304895dd4cfd67416945238473369bf261de59e9c6646b5bad343744d5fcfe80b2527b624893a312b2de7facc027638a1da9906abb175f05b7e501792cdef75b1d00f0d3c93fdc80b892a4cb6be42f81ffeddf7de33ee7e31251b9d2eb227746ec72a8fddb867696a75c0163c0a79c7319b68c54d84d259f137657f712150a2a8f0cf99ff640e0a22ca277793990151abb26ad51a74c13636950976a33ac590bd42020dc1839aef67e6a66bb1765c22aa33550e234b9df5858c9107e6da579ac09b8836e5c0796d4a6b1c2caa05ee37d86bbeec98494edccdb2217f68ec096f98d4e1c4e474a96d8d24d8faf4a58ccb8e671a71fbf3e5d045f75ffcf755f29f9e1a3051bc316013393a9d3817d20615f268a713ddca9be1dcdd2728991741bf518af8c6ab29e947c86ebb7bcb8aa5d027df001f1a40b29b6998b9e10335aa7d6c269ebb8e8f72ea548f1814d4e67bd3f0df587ed225f685ac28902df20ca8aab340b96c8b36f7b94a8606761c2813f160bd65dc602cba573bf8e8b0bce91e73e480c3ff83e42fe5a31b688aee08d6d34bbf71d0a9868c3a978043bf1ae8c616d189af4c595ba328602f5c1ebb78a3ade95f2fcf2190e26a4f12c8af341cf6312a20dd1fefb80022abcfadac8dc2035f2d6abea5fd5bfcd15b6a5381067ccbc5d72dd91ff9e58b5ce34e521ffb89cb328ab9a5e05b986f1eb64b7123616d60c307955f184e3513a3475deaf34db50f3a475c4d49e440b15eff60f8bac188e715f1ddfaf1c723cb535f80bf63b3730a32018ea8bbc79785c39c80db8e6af73a665ea2ce9426611eb1da8165d8201899493f73fb1f90fc0fe485642ff65d73a05e0765c7a9e7b578d06ed2199b2de64c17606dd5b97d67b80a068b07bf823857cdae2955ac0ae0838a8b4fd8626c8cc2a6b7fcbf95bf95d6d69246766dd0ef36ca214e502944f8746abf584ee1d86dd587c9131cb4b98af64a87e8aaf90b653d2a7112005f83f099e9dea11c6ed5c401fe3ccd596d8d5ba6a28419d2ebbe8c56a536979a168864e17bc7b4edeec6ef7d9698f57194848b1890069481e59bc2171c912689a2b0cbf6dbe385943dc2bee1ea49ef83aa8659d0040a3e7b6923c144293f2167400b8d224114a2710a8200efa81ae345b951324c1f6acfc2b7245061283c93b3d16afe3af7d17bdd3915f47d003667df411b148486e1394d11103c074f3d2bd694258c91428d5e94158", .None}, + {.Mul, "-ff4e14dd1a5a194a386ca9cf3dcabb6abbe983bf540a84c4fb8284f568bec53aa0c508eba9491924e8e580a73ec20795ff26e4a57da9f6cc38b0e514e16878485fe0418f892aa875c23e4c501f7c35a7bce69838cff4804d2ae61390e6a4e47a58b2fe469806f75e70a6f09e9d91db42ee782fde4dec5a0114038c0b9b2c81fd916570acffe4c7a79af7f0711bdeaff7971507fe570039ca3836a8f1b391c4cfa80de59b6551aa3fcb3a00547ae78c66903ae216e9e956607093db4ee28754f671b1dc9ca0790590cd7d8bc8db5b9abbf5d680a0dade1c6e0b5ff965407e1e3c48da7c6eabc544291eeeff1bc0ac5f9ba8de57eab438c2e17f31f133e7e4c5923246668a070c92257c0454a4d4b43c5184b9458888308b48b7b322559985553348e184b8a0476a68b3596cb5b35979c490d242f18d48eed1a2c8f0845fdeef65d91f13b4cb4e128bcabbb6d1c16929d866efd399e1e9efc1be13e5432df13c3ec9728558a9c34e70efb01f0d793df99dee7d3ddfb1ac43a45712d66b9dc6d3ea14a6031392116f60478ef9b2b68cff9db59b0412c09a203915c98a308fb52ad30d51d548bc835b9f4188860da32151b46b3c712055ff52e6754be7c96ec6c95cb706b1f2e41079eed454cb38dd9480f46616a2fdc4fba9f2bf31a7d3ec67b185edf4cd14468b6c375fc75755f6b1e1e860eb8bf06c096d05bdfc9ca3d4de18ce", "ca1b92001cda270b80d5af7bd4550ba00d7567cd083f43e14f4d95bb2433539cec6c454f5c010a130637ae71e9077a1f1a0b8530aad08c6f993bc87ac7645b6fbd443d452a2882670f47c321a64a8d60c503c5570455428e9c74a4aa1cab9b0cbbdbd4238f9b33abde75279a01996050e1a3d06380b08e57d8826fe350fda21f7e67c8eece8d55bc7baa10b760ecf24d997228cabfcc0fb51bbf23e245e66f131f725488982c1eeae82165b264cc800efdd855ebaa4589f62260a6900273b3e795e53e1c912eb4af4d8b55b0675482f2da29a5329bfb62f4eea03ce91591d0759e098e2a32852a137a75ff0a368ce1b05aaad0223ae2e344ebdcb557213e8628b9a2c0474c728697fa7e1c2bbd7d54598193fe72e1ff8a51b22b5f7a9a11a3760c2abbd9add29f871a4bf84a389430751dd10517b82ca50975f1f6c0e14f509f6518611ffa4939d63d711a7f84448f73c94830e1ba4a849083555a35340451821a2e2d29c4351c118e094cedf18b66a21abac89c1dd0ed8ee9ced072d955dc09c6f8a798da70423fa4b671b93fe12be244b18ec1befc43ce22ca17f631c053b9a3665557cbbd568f1fb3f5ad49abfa4e48046b8d48e1eea3b89b453dd23e2282685099c5c5d2d6df252a7cb08f295c3cd33f493bb17b6ff2377bb2a39003d4e68ad1b5dad76ba4b53718a27afbeaa0e4086021ff1969ec9e78c3a6e2e5b4705b", "-c98f1b4d4ec91232eef50b0ab33ba00d4317bb340241b9ad932d5514f985218c7f1f6c1903f6bff513dc9b9e50db9ae12a5d4c4953e942886f0da36b1d5e5df67ff2f25e234257c7e71b0c2fc4422522e0fb53971f87919f02317883841e449fa649dbf24fd07b63625f7c6175d7bcc325a9631e564e4670b3ea91751737a4060c5104be0b16394cbf970980ffb05a491b18415eaa9b735dcb62a4e3f52d606243037f53e85eaf45002c17229e87e54610221238fddcfe76b00370d8ce917c07ee7e0496eae36a2c573647674d44e0554d97d08151f6bc470c7e39ee8999cc2b0dfca3831ca2dd060fccb900c2ab0dabbdf2f6a3909bb9412c9284f54a2d39456243f40ec1223a77bd4d2fc8843451a2db813c6b3b1c31702e7e5e3a8bf67931fe3053234115df1c346f203d3a05d62b54731a073857b462ad36b497934eac1360683fd94fda54b88c2044425cbde725dde157171a645ca45344301b89d1f9f0b42a06462303ddf1d858f1548bda91638ba8503c3999ace47df033748a16ec9ea93c619c26cebcaf156ecd3d5e5aae5fc8152651f76aed15abb49a194f85c759159c710f2a31b765bde037f6062ca3c8552f1439a097dd2241db376d63678e45bca78c08546c690b3d55e3093816516ad4e793766410a7127b682812bbd641cf237f095a3706341d35d4aab1aa1bcbb041d1158076fcc1fe7ffe540ef6a36685240bcaf2cc8eeaf19e7f51da9be0d27fa4511077f82ed514e82f0dced674858322f9b5fd0c7ea5dd6d25ca9374deb886ee6ad86394daf9bdbdf29d58a95e13fab4fbde8be84764548363229262930971d35e7017e605f1dadc7edb6135a208e34972e8025071c958a43e0cbce38d10030f101aa9c0f0e4881a2b27e41e4fe8d0d60cf6d8cf166e02fcf7ddd6e6f493d3f984839b5bdee7e45c55f563616000149c1001f50f8fe8a76a451f6aed4afd3460283f11d8d58cebae8bdfbae049e56ed72aa11c7dec27369876a922440161d3e4d084eefe51dcc39abd02a085fc4d63a4ffdf5d956c7e78f2a525652aab24cd0e1d06f8e5257a109e6a20bb24947dedd51cbb878fa0105e90528c01d5bc6e6f00b71197e67791fdc3226369ac846854408b1b135b778be28ae62227e9952773f4cf7262d63c4aeddd97358dc5fdcad01c95ef8e37d73833fc100a82e59384f359aa0ff7c79c9733ec64fe1bb98c36d92c4707404dd878095deda13a9ed77e738e5853e3e6081f532988b3f207d57b3ca06051c8e6c78db581147232e680efe08ceb65a23121578f3d97ffe050bb69576afd40a02116e1483f550a9b24f269297e5a6a38241148827429a233267400232b9f82d26df9f75628681906a699c178c8e7bc6744a11be53f35b3baeebee7ceb9a0db95a7f39e6fe76cb8702d5be625f90f640d5f9fce8123012d938ca4f13a", .None}, + {.Mul, "-fb3178e3c630c6aeb73b1edd13f00f919f6d9dd40cf1c2ed49b826155be096349fc7f5ca96336f001ce48be5c07b65fd79a16940cd6f683c91dc39ed04198fd460fe9741c9187a9863194c6ec372003fc19f778beeb2fc853d9e81862ee7265d15af9930333c57c828d8226e983dd409f6142e048217cfb12aec236fbb4fc5edc6e9bda9d32ff20b296d79f7600b6bd7fd9a1a7d07b03679a9580359787328996ec4b00ac8ef2aa7a455106353bc91352f3506aaebe43e17bc22f2378e05521f4ed6f9907ea5861dd22d50d73902bce1dfb8f01229eb9aad9be80f7316a62af83f613b915a355cfb93daea8ce9aa465e6ddb133518ca91cd98d740ee07de5d67f7014e145cdb6b39b5f0e3136c2b1bb018c2b56e0833a6fc898297c3a133303a18fb1689e7f9d341a26fc3d70ac71cd27fe7197882653574234ce1b0ec7bce2a3f5aa0d5b953d18b5c27e99f63e004b8b659f0c5d33406c3afe9c239c888a72c27b4a005ff1e59b51838ed94411ce7d009190a63f12a498b591d2dceb4c65a0fb46509473be9a45209a52f3214d618f40be9cfa04634e56c128bd90c555c342e02570e21567b0a674a0442adfe61e36831af2665db15d20c19aef05b65924dfec6e44e56fbd509e56c352ce494d13f69078a8c7a3f9cb0754b475722c6a3aa170176de2eb4230517d664771cbd2a548a35ef89475760c68ac86a92655e7ea339", "b6cc9fe7ce52bffe9fe4ebce6469fbbb5f514fd8f49a2eaa1db91b4db35f94700568525cd105398f249325d084259a73bb12fb35c9db6eef4c2a9210c15fd521ea5f214df932a494c5d4f9a9e4cf1c1ee5149de48956ae44e153269fcc0a4c647b1659aa7949a188da3ff9bccbbdf93d683d32ff614a05f75eba3f26cf905f820b439f0c66925f186d41a82d8821cae3debb192c770d242a9127bdc6d7b8afaa37e35b0c32ea2e9f3f7790bc4c9f944b27784beb5d0ad802719cba9fefca18a30a8c23be467f38acd4b6110bba46c2806869b45bcba07a5081ce5becebcc252ef9819709252689aa561bd002ffdb389da03121b7f632f3ed5903949d9dbdba05bea6ea34ab5c6dec39278d9224364465b1558cc46062546a8bf2f5c278aad1aae3aea2d7e2e430d58edc16f8e07082b7f5cc5f3447a6575782e42df30b80425539aa379c2efafd2b96bfc103b326f5823d77a513bc73b8662b63bb5e3ff824fb5340a2fc9ec8d5cb39fc8d8902a5cd34641b5e48acebe6d1d36d35aba64c09b7c21892ac68dcca39c764489227deaae18ba40b8eabe60f757a46ce8bdeb6e0f1f2eef4558dd04789696f1ce882dfb3b7568d9077ba54fc3e666151fd732f750ff1ebcdd256b7b65bf8235c98ad97aa8228197801ff83f60d3cfdcdeb579c9bd71615aabd19e46e275e2f63e351010354223be3ed04308521dbfe0bcf3f5441bb", "-b35df44572952b426e84ce66282af5a65c4be26c4b6189b32e1195c51caf876a79cd4d1c9dca317b7d9e0f8552fef6f58163d7fc4848af0cc1b09ab67d85e5ba782d524e6a5a19a2785ea6211a753ea41f193d897b757ed23706bd0477c51f21c4240d6978b9ae244c9defcf73ebc0abbc2d02f3dcf51afc938e1b53cf5cf1247735f684b6213a53b8ed99a4724e0d750b9b5769f0ae661c389c8ac656b1887bad0885ea342e8093f8a11d5723d1a0c49a8fb1c0b636c81823a28d6509749b4b373fa416e4894a187cd7112a9f7cb49fd16bec8d28cd5743c1ef62ec05de94079160259c62ebfaadaab727b124fd8de122eab9af8244f2e3465cbeab1c55d9137e85b713e9cd9f8ce17d05ee662ca95939cfd2ad3254750a887e78cc9908ccf12044cd769201cb0de73230cc479151edbdebb88537af43d0e968f6194f02805e4f1eb80524246cf0382f6642de8836fc483764b2a320a5d633c550aa0a5d26e1bb068876a4bd68133b053674cba329bcbeed37835581ec83322fd123841a550812a29365e8ab901ee8fee02c4ca8cdb7ec67c4959e782c8774e8d0e673483ba3fe34b6880a5c4beacb6ecaebbddae4914f55ac273ae91d694ff8574255b9a4b5b964b985fd0637ce7c6ec974a19ef02dacccae9ad79a0f87adf0feb38e0f5fdb216a5f0b14ab466160277a46291030a4435c756b72fa7833e55380434392a555d71d7e32da73e3fb7bffc6c3c029534dbb793a8076b03336cf38e0c9dc459c65eae28c1b4fc7ae7b2c257e0053ffe4e0eeb765b62a0063efc6f622cdb69becc0146f6afb03f8a8e65dbceef797458ed602ad8a606d551fbe84ede7d36469da6c40138f511bc3f58f88338fc490d8b7979125dabffa2a1e26e90000f682f8aa034f9a4fe9726ae2be814be974c59f3b0a325842c46c40d7cc9d2f10ce8e09afe9633382e4ebf6e02f9849890040ac3e11556eb27aa8fd3c75fd239a4638b3bc0b5e0fc56f78734eedc09cb845a6a3d0fc4e5138fed11bd418d154a4ac53f056b5fd6db50e0ec9e6fdf5751e74270577978d2a85bc4c9f6df1d7446e7074a2d1d0137e43eecb8fd0d7df843df689b51f554998be7339b6fd4362db1025c525b47a87fb8c826c2e79a8e6de110afaa46b33e10d5e0fbe99b27366b32b6857220fbe93ae22f893f1b5e7b369e292f06a88321e79e9a7ee18fe14c782df091afb957d8676bff1fca226d9c9d0ec46ee68dff89bc7e841c70dd74b15d1cc371292b078066079dc32fa6113845d3fc7f4e4bb519361aafd3ba9132218ecb0d2756be3ad01e3b8bff604871b7bc0ae7beef13b6ebeb3b68301e4a596426b031d7a0d4898cd8b9c8dd7e56dff9cdecb4e3d2047e7e385e7e66b8d908cfbfbdb027abd9d5e0dd7657d8d77afd3a0c9d2fc29fb38d38b0f48f1c5a6bae9ff8046d9c3a6b3a3", .None}, + {.Mul, "-8f629dd437261f696146fd9d88e79021f3231067765c7887655a41766da37283debb754f6ab20e3924c4cb4ecee9089ef700fbd25413c5ca8c501d7df9a9f4d7111c3cea3525f28fa71499f6aab7bf0da640773eddfd9a646c13ff88029f8f917bc25dfe9653f1a2a68bbf8537982507b97ca2520fa75f573450a3f70b24620c85d239dd814cda846a4fc60958c37fd286ac67e43431e6bd8bdae587dd6c0d4a1e43f3257008aaef28776d45a9cd685b7299291b1cc659607a533ddc258ab5c44d66873c2b291323f40dc4d04caedc90ef5d81bafd6a0abdbe711a24cadf1752b3d090efe2aa6c1b9b777c41c8a17053c0b479d3ee78719ef051a3e14e8ca61b05ce1db8e2335224f4d3c62b223e249f6fa81ce967972568430d5bb4965403e4a669bb4f5f44f0e63c7086f2dcbe00d813b5c33dd7eb4f5db9d1b67dc1383b0a020d3de5f4b3774629ca169a548ba3ce48b21e24f2ff1c4b5c12d01d95145e39136900ca0bca77a46a20b5a9a6203f06a9e740abece1a75e41f30815acb05f29301b80b981a1fb73efb54fd63b5c0f509c99439280174e408458fd34dda5a7c953dc76558065070a595cdc22942dc3fc16ff2fa235a630d7176b70c4a9c3619c8c88825e9082856749a75c989d2092a155312e8d3fb1cbaf156b1439abb0cc77494d39ada203e7ab26c83705ad0c1fb5632e330b110b919deae2cf1b5cac990c", "958df6ba6dcf8d65220eaca3dc91a3f26e87ef73f0456176a0a699ae238f2a65064e153e7b9b797225af4a5b46a8a387cfa87f420bc2abb3626b975be6b14c32a4be0952494f0cc39b5d45b8fe65fc078a2ac0eed6600295fd0cffb15b28a68890c05bf1a567cf24a0fdea1e02c520e8cfb4308f042d9c6720c7ced7e505454e1e6697f544d5439ae233301462317a919f05521ace1539c8527b0243f5222500e281ab4bb7aab1276b2d7895770f4c1bd125c9ff1fb1f2e603817b6fc5c6ab3dd212ba8d45df2249e46a4aa33213e110aa5c6dd83bd1bc7f9f0193a68d5fedd3096327061152087798ed7c4a30126fdd656fd59070853c3e07880aac6e94b33a13c348992064a068f0b83e76f75436effb0278ed9cb67e30801e110cfb601fe219f48c85e2f150dd73ec95a26f60b33645102617044d0f985ce96150ec13dbe3c646be73ec8b1db9b8356b2702d7ee0cc477334d8291f4bcd8606069a796229a92874dc348350480b5dc2fde4b975a956a0007183a990330188df3b60bfb37d9f3f0b52cb27bc8234e2ec86ee40296d6f25645c23c7b3013f02086e5c75901e843049ed2e6cc6e39dc23cc26b74c86cbadb115053fb269802f54ccf82730b9113d92582a8ec8d8b4968ef6485a4f9a0de8eb09164e093b20ba79e14487046a5e2b6c11e94c93c8c7ffe14ae1adced60d1480d41b05e2145f1d8289342585d8d8", "-53c3e95ea0cd66994688471b26029fbc8b9b2b9ac362b500715ab488c0960f6a8a9f5f94db111ce5011de041f32566b9a690780214c7b64c0b368834139feb1f6ed515f52c7052d9fd40053ef0e77a9cdc0c4b955668b09c3863edc933955943c339476b9c46676702fcb203b8e3bbfd45ddc348fb76fb914638b23ba417285a541d0d58ea61509b6b95b6bf6303e93a9d40e17c1965c3d14b7c5710c3e07625f665afcaa2e7e5ca10a79b2f64e93d0f1978590db69d2e5ea0688af8b685565e73064e92972f4362cd37db2efaa49c7569f381b976102dfdde12217d1e96502c19a75085fa1653543e07ddd51af3af64978ab7622aee18b8a7a8f99706f15dd1053d462c4d0ed49cfbbcd192543ed0518e0485e82060f0344a77bedb1f1ee33ab4d5ab5b84019de023144b147fd5c04f940dcdd2902e6a8986eeca542ffe2b6ed14ade7176262d078866f558cc0621e1a291ec499385ffc44e152f57e73fb0ea9e6c08f96603e58b57adbd5ed516984c0a813b25dfc0140f1d43a4364a58b1a75a9aa1a6b5616df5d4412728814d51cb93a44864ee3b8e915db56c21562f3c7eefed3b1468a2072782da995c76cab1a0f624ef108e751fee74a0cdd7d2cc2e164a25e56b35ad90999916395313b6bfb11138ec76514cb8c921d1e0ad183f829a4edaefa0860029dadaf8c9997c8b688632970f3d3cfe9bd901e58feec9490f7c580fb6f359225632d47a41838e02c0c9b4a44e3011950bf9351b7c35c9f2a80610a73c4795f516a49214a6dcbd7c567f0036f70b9483ab763aee43078150a4e7e93dd531d04ec8042cae364efc444499de043d9db7492696d3e538bf5a5d7d33c1441deaaf3711a9dfeab7896036bf47ff1fe2221fbb62569644ec9f80a03b007b8fd131448b10e7cb19fd545591937cf48b8a63abc31f3c6bccf7a485b4225b9dfbe53e6930ef97937e6be7009a7e2f0ae1160a2b2be1b7b8d8993a34399fa9ac3fc89bffa7cf54d8a5c25011e14eb01ca9aa2f670c17619047efbcc26c96b9c36fd21c1011811dccb11b34e495b110a2396c32958a7a8b820a53cd7adc3b0bf6b0491680867e825215b543be6f1cfdf54156889a3395713bc0533e986118996137ad5caf7050e183ab2ca23b72835bc4fba5eb552cc68a2bc4929c8909671c676654209a858ec26907ac7437dfac232c9620951b211977e5ed720b11f8b86013da75c094668993dc9029fa600b70b7f13e3a818b8f323122040c394598036f448ae110c9f315bb6387fd05fe892b52538a32da2c1ba5834cbc0840f023b6970fb3e13bfef70d8ab9953bb8ce2eb321c5e956eeaba3f0a56465ef3331fa39f0dee14802e005dbf7f5231ae8b0779c446f3e5a789e6c2315fb705d0c0f5868982c9bd86f8c42250c0c38f0d0612f8d92b19940363383f9c960c86f8211ff4220", .None}, + {.Mul, "81bd20780ea5fc31d1aa0b2b205c2815e62dbf90a0e020f113fb4b8ef2e6300ba16be48996b9a316d24e381b090fa117b700a82998a69e8b58a9fb78d613e950a93a3e5edfb2ebdb9973bf16ffe7c54a684a7ad83d06f22ed9b8b43fb150a9028eebc831797dcf787d336371f089948a90040c84b2e12892087a98e09ddc45bf31b1171fbe6b19219d5434b7861bc00a57ccbc3684a5963ce90bbf446d8b8abab462b53b7c8733217025378c504888717cbfc8d678b6a4899b9f60e81a2d8a11046cdd251384046d85d2f144b4bb606c7b0e514a194230d8804eb800a82e80533e1c9a81e098b808b5f77f470d709cea1875e87d05a156b07cab465370176599e1a56d2dbee601ca6d5ecfd1b1dce1c3d76ad16f9c6dc46edcbb31ee3cd894e727b7f0b0ac256ddaadd0f49b7010bba6013889da5f66886e1f1c2a94853b735cf84fd561dd87e57dc6a5e8c98bb7916cd46848eee80e348063ab8f0a3609b3766f4301397027c958d29f12285b0f2583ddebd0cdb3f8a7af6b451e61767fce0c0f42a240a05f1e5ab9a7a67b3c49c9231b3d6ad4b6e946e30703c09d435b5f1f2c18c618c8d55286e44135a15975abb515d909dcca7d709ff585b6e01f55d5b42d5cdde57ef3322144916f510aea0ec5c4ad272aa27a2dca3aa254e13b019848c3417fbd6208b7947008f6f79214fa1babf7bd7796420b1d4f698a79c4d2f004", "da085142aaaef86a075a90dd3f91b2b101da0dde0aba74b734e45b90e45e3c6a2ad2a66b3bca359c9b3a241e7a16778e1030f6b32910d4a2920f9ae65b785d05d6ea2adf1606e852668398849d442be63fdd1706dfc88fbf26259fd4ee5437d5c8ab6e893d80ca90652fc70c2341610f821562aea446891e58a1475bdad1d96aaf49459afcfd4d9a3a50a51c5d13762efa8f30f9f7835fef73735036e7ae18b02b22df671c3363079c2c4344bd7ebb9dc413c08d0cde55f0b6f4c8cccf2c44f063fc5a39af613a36e6c1875d5c9f65d41b190ab8a45ff0284b1efadb7b1f319fe069c5efbd3d05f86cdd21f9c5844fe4648068e00d2bce642e428bc23d692de3658fe7c76a66b9fefc74131751b828df88ed30ae58cda98bba4eb5bffa92123e074c9eb41d2c6fe46847b18445c570a37b75ccdb01ed0bd703aaf02b166c029b509547ff2137e565692ef1674544767b1744d7e8d23e827bdba94429eeab5fb606023f52facccfe8e2df5b7610e1943c2ad982f6e789049016a711c65e07b5261147e91454873942203e78b0651265768d78f69a6f17553a9a2ea9be2079736b55536b0e12d52b82fe6810903b29b55e8ef7ff9f75d7bfa8bf578fcbbbc7e7914eafb1ca8cc1faffc98e70fe062661d66a3e2b60d983fdce0863f39e37d8fef299aff8432727998a1aeca7fd5955e0ce39e469c08e3137e8961162d8b3ace069", "6e7f44bde0c26d89588222fe7fc4c1e95b736d02141857d719bd21bf38bc794fae2c0ec6fb4b0466fb70f0d00da8ba2b35e8b1da6c034fb884bc6023b2643fa83db51a85ff0346ffaf3c6782d493a8b605cb3f27a86ac9d8dbed2338031824369bb7ea633c857cba654936cc87a7721e6343a3fc48e1148c684d5a0b4f192beb1cc990bc5a29bd15ed231b0229f2f0ebf1c478f3808be27368121b6c64d0c59471031ce040d25c76741ed05668a596812d230fe3e107a586de6c2c680826275aa661c182e51e88ea7372d59a89a4660e2d86dc583b24a85220560d472dbd7f8556abc947bedcb492f39ded23d21b442ae99f5db7ba24bc8d5614f0c7bc4b6ef76a45bebd522e7e04a0aedcd03ced9d7b358c69eb8cd22bb50c92ce2045e6d623e0549765e5faca1e9380c6d14c1d95d776658be923f619644d8a1241374d6059c5c1fd535adaec7fb441041668a057cee77dcf29de468e2c2fac1aed501e211ad741da9c39f74e75e6c020bc143516b4f0c5f154f0ed70a662dfeb9682c474663a6b7d09b08a382e802e85251ba842745b88299e39665ebb83d3bcda1900df948a3f50d2544ccaa7ef3797e0fb04e782205464fbf9f3079859c41dfee12dfa37a4b82e09685cd7778aae0da80a74b116393579bdb8c5570cf4ceaf4cd18696ae1fdf3566b32b25c76f0d4e58388507c3c0582a98051d3b760171547b901d8a38a2e7c0faf1779d3e1fe111461b7752bc381621a5d42cbe7351db4728baac8733fd7e7250553ec194b90c4ac43832f297604f3bc9141e32a454a0f54ab1953be3da533927541e6d1b0e9a9d6e32fe16a87f9b7f5e95083ab0d17501f9cac6f8bcc06135d15e4ea9921023ccafe67d81687ca3e97adad8f1bb715f973f17e5560bb94829aac5367ddac20f0a8e7b918262fef15214e1b61692a52bdb903e1247db689ab5865954926ed592a2de1056f132bf59a689a09f1f3cf6dc909308bad0b509fcc84c6e5f77b0ec1988ce4833e41d317dfc29804d1ef893965343a61147caa0e60bc9209ca4a1329ae027a295a04c5b132a178bce4af3d474b20e5737619114cc0d247c07634f05be5a6ea2c9947b995889d85eac0069c822a8fa06cecbb672ec16e6e7331875f454863d94c21ac70e189b0b1c907c35b1ff792dd3bf89843de314838548745a1a6d1e964998784d86431a3c119070403e3b9d7a0141d4a6f8a49245c2c7432005e235a56854b53ff6d67cd3d50f14ce8925f1910e29ea9ab51ec1df07cd6a7b44132d22db23a0b644ffb9594604c5a8816ae7bc8cf9b425d065c0fe63592be70ee6f37e4e022a507d140cb3cedc34490596a5bb8419997fe1ae54a0d3b2829932bfe5786e0e71cc3aca681c6a90bd571f161364ca70c73b49be8b5ebe2f10822c4ec9795208b149ad5a2e182dffd99934041f165b37f1a4", .None}, + {.Mul, "1759d468d0db0c48e85d2802f763473433693145e81d0158b036ec2be7261eaf14094de9832636db6ca9041611c06d24153a2aa7676a842fc3d8c0324a3b3ff8dee87793c57a77be1b0675c5addc7edcd4b337cec033af93d41558bbd35f42cdc74d2eb91b2188aeb51eac0bc567466aebde3744693f98d77eba7976763c983d7c0bbd2d6a600c60ae1bfa7376af01afc0849d0763351cb21975975fb29e78bfbe43a6d4d754097aea3aed81d5224e9d43bfe60c8259798c98267a745901f26541e0ff0533398d81c744b9743258b3541910aafad8ca21d89c3bd703cad6997f21c30f0bb4dedb48a3eb2452a0def5739cec6e6a9bac57e6e86a6cca5d945ab6da117272a66e9e54ec4887a6c4e2edc569af04f88d5126fa3d3d5500a9c0b1a4bced15bd7afd5b3fd27ff3ac8cc9d4d0d2754ec22572d911bc230835e2f7aff44f1f80f02a6f44c553cdae851da003dd18927de916c16aa769cefb092fbb3ac2ca948bb09be1a528a9c5d5911b7f89344bae0110a0253ec075dc2d0c264312dcb96d262bbb0229712b790e3f091657b538a8f027e00b6fe119100d40de8ec1bf0eb9b3f6e548e725381d5127a71fce10f907725dd648b234fc8ffcf75791bef23457a1f8155320cc643bde240fbb72d81b654c039bdcec062d0afecb047f0149d2c2729970bb0ef1dc127f06fc75f204e6b610b547bd5d8d8d6052ce7b8f09d9", "ba378b2df95fb73f33b8d68d2df9eae8c720a865af1fa62fdded320f9a4114e6c3437a830a0d7ab9bc9eee8b83a4f34cb9b526e9fe1b9f26cca63ad222b08353edb196796e9cac7f390aab5f9de3ef3e607f87122f52e637ebc52582c97d138b8637016068babeef3a9aafe55c39b08588577c6ad5c2df84c4db7b71e268270eb3417b5f5f06aea182a0ff6bd6851a84e4b1ee31bd79f23e9ffc7815e23620e97d2cf5274070e4ccfee02f32388d0da77b80132c8ff3d1c6c80556a25b1d496fef5f0be75e8e6e276253b2d62ae2dae24ffa670e8cfdd9c1f9b9c7920a54747f1aa28f2fbbcc9c08c0abacf0708d12d61bd94706f3ad44f75888d5bc70e630611f7874e5a7d4117eada174e76fae8925dd9a45938291162e72619bb733d36e1fb57815e223a905bbce069aef02c8de8360a560ad71c3777459c47b68c5c7dc6910af7dd3b5cdc2fb7e3594f40c5bf9cf23fe9734f995d9a2f235acab26d4eb16cdfac601bdf4645219ec3b3932f684d5f568a79885319ebc685d1fff014162f5adfd9868c4e387dea24ebf1e170569e4c0bf4a9aee78cf7ac57884f665f4f6b243e92d8602f9aa373926ab35f4d509f0a71b605b68da7f605f57ab23ca1de1131e51ae07c1a40b41f5bdd938b9fa5b507708587bc340566e12bdc676e8ca4982adb31115cb8ddfa8d6d987a2083bc81108c317628b004a01b71682759f99e72c", "10fc5552c2226077035eded92768dac9fdeeb64e4c8d52c1bf38bd9af1d9b45056b550cb4558b957b3b9336d042f3af54d74607368e637fb66485ceea4496afeff0627920a547c5f4b9eebc3a17bca3c77f948bbd1319515a9a45f40fe6757a734ca9ad578e4dd615f9d36ec04048d52d332306e5a042c25c3741624347c61bbc3f00a3e3b0cdd3e5c6bfee78904d02cdfe277dda55e3d007e7828ab142a3bc1970bdf56800934a6950d2926afddcb2ab4c7f3bfc8957028e648660de16ecaabdd6f32079546d514a074e37a1de9763fc274f82280e36bfe2269fe05730218043f5697ac49e86638e7ae5ab477f6c45b1fb59372d79251eaa108d6bda813e7259c85abf1648104c19e193c701d8c9ca8792251c920f74673e836408aa0d078f6697ae518ef0d166080f7803c97b2a639984b1e09046fe77d7569c1bcb99f5bcdba7c2161f6305bddc276a600fc0fe8cc5a72239b48d67ac76e6e17a9c43ac5f2f0c9f2f504261419cd1d57bcbfd3b40c63c8de263e6c96c23494c421154e792c30ee65b724dfef71af513e3a85ddeb8595019d7c3218017073aa388e3b2273a6e108e3be5ece11bcda79bd80cb4cec0f5484880be1f05e22ace75b414ad4bb4dc5af4425e3f0855385cf99319e9ee8896056c9383e12b8906c0954cb6a1255a61cbd80d06f1c204477c7239143b80a7e0235be4eb095b7bbcb45563593558e0e040970dd395dc37e40f6375e2748e7b944afde7eaf7ab8f2876585699dd77c1d5308b3693d6509a1285730c636ddcfd33c369ba96f96f46a7fe628cc34af129fa7825627411a03d76471f30dd2cf7f770515dfdad7ef5231476b36ba0ac77b7ffc2f04ec0fd3ffaed198f8b02b61960fc0cbf6b501099007fc3589528ad6202389560e031f6fe45ba913a3d6a4c1d0a8e7af6dbddd61411f852da2d61c82abe46352370eff4f17f0d2b6223bdfa648a6fce2bc1bc00098dfa539ad50370f02b43bf5ac9a5e1ccacd28eba71d0fff60555feaaf83877cf074d0fb3659ea61ec1d6b1ff1dfcf95e4c6601a50cab69edd8cd8643f64c23c25626ce97e5a633632ea45772028897916bb8e290cb95fae8e5ad4e6eb214c016c0be730ac6b62b5439b7ccace89d3fc008c6d3cb3838a9aafe621e6b015c9f2f5b63255464b7596c651e2499c73c201078204cc3af77a0459a1acc548d6be908f0802575738d075a98306227ad5b26e4dd93c496a3962c45bf70c0e28a5f7556c5868e51e6c076fd451157324f56b3620b836e51e09d607b29800f8ada9a7cdff8b9f0cef81389f9d199ca9dbc5059434021896824c1e0ed629cf0696d9803ff26ecfd757897f76ce2b2c8c85a52620940913d85ae31b0a5a30dee2f2dafee4e241cc3f086e10c8f4c5101bdc42f0b860c603bf4aba9ca3d0d7a2e28611eeeb76310671eec2f829804c", .None}, + {.Mul, "a7309feb68a3ac5fc5b6d180546d18913e1197ba19da0bde1f40ae24bd4a67f22dfb2b68cb1e115ce176d2ab982af6e50b08ccb423c0416f9cc9853bc289ef2f9c5ff5d7a883a529166ddac67806b6f7cff886a9bc59b91563e5244abd2d34858d0054d4b2d855b5ead30581442238efc13ee052a729d66ca9329a5578251834d4fdf313ee3c853da949b4f00a352d04bbbfe0dd8966162eca9abf5c3cef9300eca1577de35b7abf9ae27086db4a2c430b0a697ddb1b3e5ed08d3c5cf51b2d9a7dbccea6ec92a85932944f9668652b68f2796ded4796478440ce1baf789aa85affb7b10c5161f3a0048f180fbc927a08686a83e71ee1bf0ade13cdfe89ba5c4de4f5496400e60aa55ebec7aa7ee60e5f73df4006207deaaa49c43707004394c6ddf0b01c8590bd4aefec88293a16e8be6f5b58a7979bc98a8142d146f30bd0bc58c437d18210a08011644726b89f5965ab62a26ae9b0e3d2d2d12c5b85aea3b574373e86022dfce999131d4c97a9cdc435f600e7f635a1362c07bd37e2f982c54d3082ff73152204a53ca215f85cfb7f5f5e9b62626ee1643ee0b910ab7dda99e53a98d603c31a02580cf4b090cbe7f665da9003fa06a3a1cafd5d215f4e2bc365915cf001081f1686dfc3636638fc4bc391e6356ced54d4c7352195c2891ef950a2192d0b463d109a2e195db3b16cc7c1b574bcc6eb4cbe78ce7c3dbb4aed76", "7edb8b62dc7885930c437661068e47727b45d5405c12ec85d506bac19b200df98fb032ad6f4f71df5fb32cbfa8491ebb7869a8bd1e3ab99531e67bd94649054b6d2ce56a082479846017e424bd1a36e33efd482d3c3220b901a320ffe4d4056a2c87ac21c18d439bd41a06d479e1ae8948d8bf22fb0b8598b4145b10192b6e39bd4a9f510df972103fea2e483d3726d226f870ca182342f3aa7a69315a21afc219594afafe8af85800f830a6c85b58107400c5173ac03cb36bad147edbe0358b5277429f13c32aae07480d65e1e8d23c9865c6c8108a41eb1e7088688c1279429d9aafbdd63d12b1d93ad6ec3e26926e77de42a14333df3684103b7ad578f3edfae2a704932d0ad0e914794c8eb2dc9d878d98ac575fc3ecdac6645f0209774cf1fbc4f72f074c865cb6b3cf3d8d6b77172764d8350eeea9e0bbe88cdc9704ce14657c9a485d876b02a51ced3686148fde568a0e09f22e3fa69696f5462cd5658c0349645af7dacaaa0f8167ce5078e16a23e90fdac78b9ddd829e0566d96a57f0cfe8335a856c0310178db81abe62ab1e0ac0c0a462a1f76f68ebad66590546e9ef848bdca58c99d7d9a199db40b569fb41a92b57789e2cee5c6295b1642e358a732049ebbf8af27f76a39a809230295fa4578dc249f1a81b7bfd85d2baa87c66ffacef533215a0b41ba03e75ebdbe2fe3f7aa81ec5c3cd45c16a1a03aa8842", "52d95056a3519c4016c748743a598b9039c772d0c6c7e330f812aa867fd5512b7e42617fd8c7c5b2ecd2d31144ff922240b9708926fb8f0845bb0609c05e589392b49db1a0ed16cd1994d8b9b7832d8edaa6a09dc4ea99760943fe6835a5518243471add9d28b67547a70532897d929fdbb3d8a1662ec366a9dd45acfd471e327118e52074878e16c2f83c7bebc2092cde9bb75d11dc5902036d592946e430374c75a56794d93808b1d0dc3229db29b3a51c4a217223b6f7cb1486e7646ad677178483c5f5d96a6af184d04e21a9fb97b20030e99f7e7bdb2612a977e741a451d7b4a2339cb69db53f20e9d6d1326d827f73ac250d41e25f724656a3b0a76837ab4f56e233ec1cf31ff2305a3bfc9eeb9c0d92f63da17dc815ce6a6a2aa86b78ae8e14dacd555048952b0c3fb809833ab5a4da1e0b9cf81856db4b7e93c9f5c43f7bd862656ac30dfaa7bcffc4835268b1a6aab64f9ae0795e77fc2698c8c7cc28ae184c96e78faa6fd8a40d4a2ff5712e18294d57e9246a86f66011e306d39941cc60f790d3e1c4d466b8e20b9d7d3f50d72e1df0c6de42f3f493edd9d63fc820e953b5e7bb2917a94b68379b4183401dc18c33143997ffb7fbba6a9e654060d937c6b10a2ac94b433dc0a931eb40e7048f9ae57d55876fc50912eca27e796c23b11a31d96314723c2b83956624393ea47279535bcebd616c0eaf6abcb400a597eea8b59121d4dcc09b6a6c58fa9c25a6ad85abaa5d5be1951ddbb3b3267772d9dde046c319be32dd9341b2c7e75ac0e55cd0af8cb9a8e6befea9877838f1d5c26e88a26dad90ac29bdad5a6b73420fdcc37766ceeed7f3f78c13fffa99799d5eff2b6ab8cdb5c21f3ee44d3416e13a3d8ed5f800b2b6802639988b216d5148c33598881966fac1be34c77e0fb9f4c89f82d2a7b8a043f92be6007a02e3e6754d1e27c8bad83b1dc751aa1c69a33365fb5fe409971aeb3cc8b242f5d0c121cfde6d961c6193021ef8488880c1281b01445906c7e9ef647c65c84dff47eedc7215ffa702594e66ba99c53d1afadf7b0d99b7d262cccecaa0e56caa3618cd16e1030993cf8359df471f639bdf87cfcfcfb26510f162d9173017ec5d5fbb2b5094aa35fb22d426b67fab044e6cc945ee6ef4938ef263aeb9a2067bfa26e319c5a382012e3b8013d79b54f68b3e20391153a770b26608f36a1e3352f906f5bed966e8b52731a4f96e53d641e60e81dc94975c743dce5fdf03878dadd20041521e45e80ae5627bad60820c669267b9cbe7b19b761cf3ba646b031066ee5d87eb3fe8f2e4d6a817953a18ebbe8c298e32ba918852ab375dc2f140c23aa0605c9374bf7d4f095f0fd2e3195486700eeeb8b9affad87e4d2882a314b47dc02f24b77edad109548df12fe71d57f0047d9f1c00e0e6231e0b2b743aa9f1520df029d3e86c", .None}, + {.Mul, "-99b6578a9a06db00f77707f104369b3cf3d536c7356b9aa08bd4d19b0cc421506d85d57e90091e5790f1b3d06f16ed509d78a2bee67ccf4c21cb308fbee8fc1feb7b0cd72143f3a2a39b86d47b862193cfb10dadce8c6cd0a3815dd2e9c748b86a89fec6e68f1251ea6e1cac84aba8c75655e59f8b2e008a93799149ef32b5bafccc7d147d934b73d0a781b159db0ea6cbd1d544bc2f87eff1b39dd21a77cd027e8c38da189f491bffcb67e8e1e6e69769ff637f4d4c69dff51779988cb01cde9f8f1e46869612d85350a119fecf9a9e229b25fa53a4515441715d32a5c78f054b6663f8063b881aca314fe7afeb5cca5e8d3413b145c72a2648c38dccfeb4a868baf3d8d8f6220ffde030fa5811643301eb7a0d91a0c6e738ab860efc4d8c0aacb9e2684dcee0bbc72779c8184fec0071c4a22a9bd92667b8c09758a2a6957644890240216efbff36e413fa64c55d40c09141384183ec8b728121e6a9305767e1c88c179bcef121a2a819e63d2004c23672aa668d2d45f911743e29486a07fc667b2547949ec20c43bfc52a34162a8db85da0264c57a2e068fc9a0925deef79ed131b77976a50169c1d5bcba8d7c95efcd2598306d450dd0c92d74fdd91894732fc0858ab853aa263b6df18dde7d830cea8a7936fe56a39a9526fcf35bfecd7bdfb88fce793e1c9c5621d2b8dc0b04e559209e269da1b8070601aebe0655df8", "5d331733c59123ffa4dfdcfd42258344692bfa18837a488a361c9072972034eef5d92a7dc39f0afbfbbfcd0bdb518c368f0fdb8b60c7caeea40d2cd9063acf1335d49443d2b6dcd8f20d3f8dcf5faf2048db63ee296208a035bca87a33c45728c324a275956461893722254af4f56b84c349fd3241076e0c243bd6d06bdea0dbbc533213c8c7c5980335f4169e866f96a7d79fd45f9d14f32f0a66c09cd6d938ba228a1e650555ca50e8daca71eb74a9b24777c144b7449a4ec67cceb8820f491da315a2f7376440ddc5399de62b611a242ea1e758f26180b67c4d76961139e53bb335e4a36717608246a9c21ff5c2b9d5b37273ef3880451f7e6cb763e4928cd5b736546d172806dbf7304ca1df6d9e058673f2709d069812eb49cc256674503c946039e9d6c98de6e60d6026088b4aa721d8bd520508513840d2b6e53869262504566f697e7a38e66d1e6e09eb2ee1d2177c8e671803603bd789b75a97efc857163b86b707811a1ead1110d9b424bfc1d57500b0ea00bcd173ce1e26c3d32f39117741adadc80d254de87f4b6b22ad6d67301fc24186cd5f41aa7291bf8ed4e1acb7b69d69ace1fbc5d5cb9f8b4dae05a42c6495a464f44adcc1a8c4c30d443b48ae251420535ba5bb00752fd03f4bbb214076f18987db7c78cdfe2af84d752701848060ff549ab388e12db0a586785477dbbe13fe5787219c625ecf2dd7a7", "-37f5eb0f426288a2f3c3272a1948ae59d46f31a6593069ac51a6bdf9801e618c0213cf3418fc86019030e402b70b11d55a99796b34e37e4b8f9d11f46406f8f537eb79160a6459bb924569abd0b732908e8f34af851cd4a9bd7b326940a3d4d0ff01a2f0393c9eb9ba317aa884d34557ddc2fd39fe79ac9f1ae7009e510a90d17999a680d2cc5bbd47b7cb4f97c50a1ca64b670c8ca41ec8172b7a481592bdf8f8748f77e03c8bd56d4d9938952ff27507738504508078814675e5b633971760092b09f681416ecc291eda9443a073aa65d58f5f6e4a378a3bcb1b2fe4745188588e8ea0a33a2e2c6a62582a27d039a1c31fdfae0d2be128ac11b26ce6c7c9508c92ee7721a4a4eefbdcb288a91aedd605a0f0ccfa1735f7d7fcc84c3fde01a8425ca53f066ac6d6e1553155528a32e98481a30a592a55951a8458e267c8400870d518751183465d2a2843a0bef922ac94c24db84799e4ce4e75f5b382e93229ba5a7a819ce386682be6a6a29e8acc96b936f83e5105e3c59154e7f6dff599cb81d0fbe86666127b1cff776811f9a3b9132c6a693b3a3de3bb3f71e987227a3d8a316fc7019abdf03435cda8c96d644d2f58ccfefaff0a3d2ec9eb90d6599a02505ba980c3170c9a578c61c1c7ee1ef863d8fad2983a0af3f932be8fc9e0d00c3a6971dd44d7914a3870b37e162e4d674049258b7d66305280656908df6b7b015ebcefc1a90de3cc8ca19afd168e2cd7d225db3abdf2cdffa83929e4c6e49081b1880e64b1777eede80cec26e7e552644dc52a760abbb90780a08e260e45bf6cc4f43fdd2e6336f257d58e02533956cb6483c0e699303628f2b33edbe0f714bb4e3a964bae9a5803074a46b93b384037027271d58843b726a0c5a237fd1644f4d94f2e34a210bf64a8b59e1b8eb88edcdecf6c4b32c2b95b96dce5c8b52b97888ff5cecda3477a385cce4549858872c35c8de1ba89bd0af76e9b5cd8255543724da2567e5875f6ea30f00f542244ffe214b2c9978f855f73240d2d5993be7c5c580c9863956795b19ffe6c0c52f37ed0d3c29440b1c0e50d95f709c81caa43174b893889cc23634073a41c3d55d0363e4713d2193fe9080abb637bb3ede88f0cc95c6c600a61a6ebc1a0955bd465a36fd9ab441f7e802e846cbdd5135ae7f4dc1794f6d7322577cbe413fab2ca53b9b21057a1741cfc9f6dc5c95c21e5011837767f0c9e18ee1811ab74c6bd3566942a64b6b06e9aee4a4df10eaa92f43aad22dbaab7deee72d639572f747cfbd01c7f3f749e45c6a48ab639d73504655eddf6983feb953dec49c39182e02fa391ae12f10e94e1c2187b2089bda62cabe2e73c2e19ff1c67c24bfabdb5c3925c6a0c0d6b8355c159d822c9b618c0643848d80aa332bc17f3e22c90a83e5904c512d43f6abf1fa634881900e987833190a394c8", .None}, + {.Mul, "5516485595b0cb80fa5a8564a1af2cc37a2361b239ef5f734779c6e247f791b588d3aeeac5acdd7b07aed14f8eb6e43d82c08f73723ea6f31efa57565b088a682c79c61a54323b3963e13e7479925a64bcf303e2ffcbbacd848d21c2e69e30b5af512f31055e063353b2a04f2641b182f04142415cf2c71c8839d1eb93654b019813c24b6813056e6f11dfe1ea86665870772357ec013b5616058616810d821bc2f90d327ed68f0b901ee5bbe342771f7ff0e58ea8a633e65d6ff3d94a579a01f935433cbd1ec4fa7d3828b60b67669776ed828824aadf300d2272ce2a10267302f450b831f88d4e5bc647e849b954e02a5c0f653d66d4c477cdc1d21f7924e4b8fdb35131ba1d3cabd94d7ed9658d24b00934d7be85cbefee73e1c39263fe2b37aa7d912799b1d67d529939394204ef4ee741797504a8d5e795f0e16a7641e7af2c107f3eddd7765a4360b3b37b5fc92356e57e5d21bcdd5b54b6fd3fbba96586169ff77eff5aefa12bed78a350b2ef9c2c0aea2aa04f58ce9827391fbeb5f338037925773befbc4e5d9d06467820a0d21e9b25eb0b7528429eef68aa9bb2f5f97b7cff5efdccdad373506f088210da8a076b75ea94c30edf474ea655829ec582d11e7d279e3329a067019624d7d3596dda7eb8f96d828651f8281b57ef7c960c2f767791942d9217daf041c2050d153064a05f9cf33c82b395664e5939efa0", "a69ea8d35ead1208c2bd95869023a903d91de097fe0c3a669e570b3daeefb6ea2c39a78d3efd41fa16db4a13f3615ad30ba44c2995e514b5a742c5ffa18bfe47b06163982e1468fa7854db63853c915550a9c1abec09b17afb1abe7efa96416d8eb8cb647afa98c2d19b039faba1dd9260f5a228c3b76974a07ac1f686ea108f7797c438659e15332721cfe8d85dfe05d3dcdf17b01e0c39fb7fd28b73a77c5eceafa455e6c7de2f1990e4d39ddb444f793fb8dc12834d2c4ab6c164ae9bb65bd2135c3cc4ddcee4f390af0166fe0a4b8f38436618de0379af7d44ad1dd71e01a7b24a1e485e369151854edcdc053e6c253a0f591b484f6bd40398895da56648276b9c8adf9113cd971b9e5d069f14f79706c4d95e98656a646d49330a9af687a1a8d074a3312e653dcb97268f514b197a27e62419488dc063ec638da46bbe7d222358d5c08f123be5c19fdc711c6eca18a6bffd3d9e6064e539912994a57773c8d07a30e7d56099c9467c58a0729ca0e238eb640ff3a7ef4a6190966c7a182ae9900d5240b4613969e9ebf0349f3949fb31ee5fbad6a8b2d9a1b303b2e423a94f8be5210511091c570f3dd68482dc86702fbb2fcac78066a926fd1b0b513e7bf04298c8ce3d8afd0d1146dd6b0126fd992e71018f8f8c6fa51c449b3e41c0997fecc20a35f1e1c37cc2b60d8c1de51b3deaee20f255a356bb2cd64f2f71b5ee", "37612ec5043084766b84d6544750c48d25316de13794dd77692b2abd770acd56c3828bc69e61fa6c8fe5f2dee5e4b58882a094497c1374edb5998af86a04df929eed120532c859c60bb9d6a6cbd3bd85b89f14388ff649a3d257d7e971e60e03286eff6ac5e8d64b40a72074e9bc4f8f02240da2b110b3796195a7fd64c60f0f4fffecb4e5af3c3ff765c328d4d1882b5aa5f67a9ea596a7e7b2d049eeb29f786b232e191b0ce4fa2dba57a0a4643caa0820fd368dbf68d7817285102bad6d5cf30138eb9c53887d5f7e72bd8ed8154848c5839ddb63b30eb254fa52d04a80d4ca72fc8fc574fd21f150d322b2d726ea1ce4675421eb3b3da95dbe850dd44bf7e066f13b9276dca98953690cfbd52ce04ce7750bbf4bdd236f9e2afec54ad191bd0fa44c98d3cde8517a11606b70b7cd5f3b418fd3409b59f9899d1fb59c782211c9733a59d5eda65ebf71bbd59c0776b936201f5c188b6f2fc9ed739d5ff89dfa7e5882914526ab3053ae32d1a9c3c15ece12371d56ec1c3656d93f9f61ed478692ab3af1fe8aa5c4e500abac9a789159e44b793626dce9e4281a66d00e992fb9ea1a3aedb9c44bf0c29f263f04b7e2e1ffbbb6fe77603f382d326d9309cde39b6b8cffe4e2d945b9bcf6a96cccc90f233a47f4339ef024010b9afdc5d5a2f019fa690806d19fcbeb4be5715e46e5f32710533fe5409e4a0f77451dda036e95e8e373dcc861d48a3fbba1b8257048ef0c03215a4647eef3164cb42877529b31044126026118ac7f57362a8a5edd21446ef674643f0d148de11cd82ec779b1b09b841d829d8bb448633a2baba7a8646b1fc0abbf709ce0e7c592749bb2af881925e9e618d0afb4652618b4595c403f570566cd2549a32a394ec4c170ab79f54dada9df729c9ea262c80442c003353199eab290e9341c0998c73ca9ebc0bccd8188723a69cf1661fa8352324a1380bfbcdcb7015c8640bc79e5bb9c0cf18f63f8376ea580bc3513581e134bef62815fa055e6a7d10c876438bd2f3147facfdd88329b0a69d084914151b29a4fd3208525a55eebe79e8bb5e74bc8a47074d46f752c7acdc3432176bffd329052bbd2941f95a84ab1ad1b54ddcc3c8083fafe1825c0d72e7c315a5e70bbfa6a4628bab38a57acb391c3e25c27d2294dea22c482937cffa85e6fe9e2ddefa8c30456a175fc7d6013a0aa92e039fd1b0dbe2f68b42044b107ddb26d2d7285c253b4e70550784ec184466679b483fc455b6a23a5d0336369cc3dc197fbbde4bbc739d1fbcce486c47d3cda039c31368aa0e025ec8dfcbb4491f2d5461196d3651fb8ee621b1cc016f2dcfeee3df25773b40e8bd9a38c65a0cf31387fd856931ac6c7a4dfc4c95d202bd0e8d5a1123b3c7c4715e8f815b6a6c33b5fa10a77eafe3570b907d7bbc734ea16650275b927e239de0fe8e6c0", .None}, + {.Mul, "-efc0dbcff1eb4c76dfbdd3ce147faed7292b5953cf945de1b42e97fe2b235ab11d1925c3eb6d17934ed69340896cae8e754b3119dca3dd3191bdcbc5a93a1a44f7b7f0ee3b95337ce9b816f29e28d7a0a47a65c7039b594f8a0745acb025744ff917b4b1322865175313c139ee854ad18d57131ff5944905ffe3950b5a8cace9e60302bf6619a04260044e9d1976743bcb068bae761a36e31ea93ed29641ac0564300af5ddc1686331d59c6ce522df56bf53d8b466f4f111bdcd390a93bc144590e577e336be3ec380926f3f91acdf54454700583615a6ad31c6f4a88e9a41e1e6d440cc2ec945f33ae7245b91f5ba7a9cc77de33ae5f811908156372e2de299d42fcb63f4073c97c880bf427391d58c9249ad3e63e80df01788368fa725bb606e5e14625dac94c3e5ff176175a06cb6fef5e5fe654179c3b81e8f02a362cbdd9456e3e3c1b12fc63b8d21e671d06b003f8fd1834ad407cfaeb9f9da46effcbb5197e628a175164c01a2a3cc2bf954e76a90c425647cb5f3e70d01e6d63ed6e338f633893cc063b834847352f8215561339f5707f56edf3896c5c650a652418bfa2f1e9a822cb4a7262e86e83ee0cc2bc80ab5fc4b431f2dd98cf0943572c67393c2ebfb3aba28901dbacc16cebfd51213521480e0602151620090bebfdc3e12007c4591e2fd15cb0f9efde03281a4c9370ed09bd90cb87f195cd04eb577a0d", "207ec700f95272ef2f7edc147cf7a58f39530fb3c57000b7885f56affdf56a0db0539094bc38ff6bbc36318a77e18b13b02cc5dc97fb454d8de286143833eb0a85f5f795a5e662419dfac904fb86b6ec9b950a3f4798d35329301a86f9ebece124b90748512e8573e7549a7b5cb2097965a758017b88fe9ff6a43a8b10f94f12aa7f3d2bf4f5a7718f435d30f2cc54c59f1ff52c259bf494844106b23633d4e0825c65d52c614326747a9dddcadda54acbb9af02558b2dbc65db2597366f8fa08f8b4cf3ac505e2273a7387b37ca128db54c459369d4de54a3d5a0c826d8fe43939f41b677ade664d0c9cb8ca62a744087710d2919b9e5223d4500917e92a4f0b9742220cfae27a04810dffdd4d83f4992d7e3181906d872b528240bea28a834e4a3a1f2bd1dac70c4a2da524cdd335476189af9dcf8b3592ff8d938747533a08862283066b09c6bd1638478dd0d2fd7b12e57f820e3655a2a35b03305d49bf8ff1a4a4de1b3497f8243c0c6cf8e9b3bda75c76416747ad7196c5cfe07f6670cb2f51fa6dbefbb3209a40601fb37234367d85347310b855c3b36342b84e61e345fe24afae536120a093f3ee3b3505d4e376401b43e28329498006b1c47d3747ca15ccb6bfe408601f2188ccb525d7feadb547a325e98ae7cf6867f8df7787725e13ca278e1cf1deee991ca0433968a952026024e7d4c45fb11069bd7973351d3", "-1e6ed6c602f4eda3f53ea4d49cd45ca9b9083d307d6a9a334aad0b8c63b119204f22c8c0e34f1879adee9670d2c8deed23f7221f1dd3aae01e48cbc4335f7a757a1952711289b15a9dfc1f850bd3d69651ae3d2f448498f4b60a24278d0fcada0b2084bab40675f464e2a0b3af1c380c122972f7750e7af3daf59ee72ff544a02a2a346fe0b8a58c26dd84572e519d5c1c6f0d5ec99e2f50a0283fd2b49f17985a00fca3c3c3f3d685b4cc82fd4f8baf84cb5e72589014eb093c2eb23c05089ff4c77d75dcaf7ff120928f6e7447f7c6e86934467b6204fb9e67f2e2b300776c9a82543fc4f0c82e10f9646e6014dfdbb7cd09b7f3b8e016688ab3de7cf0d6223646d2263a0b19c6efa5c8056c576466b344d3b778a695e9f03debce3ea368b1b485639f95744db777360ccd49cd8198fefb017866c7e57c470efd8a1424fdec0fbd5dc69d36b02413a1d0ce2ede51d2d3d0d994a580cdc7242495ddfe464a89da7db6f7149902d4e270203622e5748fcee543d1e8abdec0cfb843e86460dd959755928cb440009dab7fc4cbd8e77ea509f718ac8c3a81154fbbf4b935fc7b7b1b51494badd53c51c8e385fef94d2f53df2dc9a44c3c29c9165ec5c89ae4690dfa09240f2d9f75014aa56a77f556ddccf26e0f6deaf4c96ce5358d1382e13ed16acf533516cf13523553c821b76591992c63f3ae7d55f1d64d48574f84feaaa2bb8e7d64205412c39fb37e75beb6b3b86e3778759278e07e1c7c7b1e868d626997b66bf8eaba1a7cf832cbdada08e10fd13a859bb9dc74a26bdce35215bab5fc03f7750a55c53d868849c5af85c8c00e6c03249a764ce6cf658ab49b03997c74ba05539e46373b1684e8c3e27069fd2409acca3f0eccd5aa9859fd1c6cb48e998b70df2be4e79a5073d7411818f3488734865828a3e35f2edd964219e7d5aed8d0978d428bb26d141b922a17d5c20608a3ac65c9017ace0b4798c8b6170747566a36d54352fa73a5e7ee3b03992032e476568ed93e753cda025cf05a359c75f14edb8726fe607159cbc2d03b3769d0021f5fa3be5d9e8c8fd51412fca35aa205d17274cb0ecf16943d90c468912691416c1cc20870890fa3c27af5599a8ab9f7ac1daf2ecbc0d5965fbad3009c887ffa4453db45c94f0d63ddfd86eff604fec280095598d097544c411c7cea15b293360e4ce6c084a56c19abb270939b7a23eaec15f026a7438307c717ea82fa8d8b2b93d60d4e8b2dce835f72ef9c544c171a55e96a4347cfc841298070bb105aa1cfd6548a75c7e49a445366ec5768453c0417769c9829766d8fdfce3eff00ade65dbd311882bf3e5f8508b22977c9b39950c348e48ad3275c518afeb23f7ade00310c9fe39c52af1097d442b3f0ff61b6546a1a3bb272222a8acd5c723daa2661288f0b0416b87e9c899cd64daa24eb5b7", .None}, + {.Mul, "d412cc0887765db25007f825045f31a5f551328d72b927a2422ba9014e9b265c1e340a07aac0a57b3c744625b8ee333e0a9524615aceb0fed2522715278c0caffa46d2063d0352432c7a52c21883968aca502200494ee9508c577ee380ade036e9d3d9b591605b3fb2012b56425d374fe4acade34561374dca02c329a0c2c065d16ec17b4873c111706ad5b73fc6e8708591e3a133867e428e5e392ae253fea9ea3afdd77766b01f45988a31087a99f381139774f3e889b68576ffa297c5b13df1342401e2c3ef8fa0c5bcee7bef25c62d538a604ddf9b33af779c9d832b15eb6fda164404fe12ffe107243885440fa5e5a5b5df27bd8689c5af9c35b7702db1f50d5285efb5148dc64558209108be0fb1f37cf0d26cbd2108b2288c18ebfd224ff56614107da9c2b13b6f3c6bec56e3b12295f023a1636b6452b8603412d4f1d1ee19c4a091e3aec9d6cfaa58e7d8a84794bbc9df7685d07277c128580cfad5d7d35b7150068019b832d517a116fa6d05fee53b9e3736c44e9a96f0158b6da7936b7c03ebf12966902d444c1c59bfd5e75d040dcc1c7f5f98b4b6e86dbe42ad3490c984638492fc7173b605f4aa9796bfed42f10b36b786841cb76f0e7927749fbb76f963208a53f646ec3d57d6cefb7e66e74ffd8db539220f55f55aa0ad9b4f3783014586ebac6bf73af2367d3e4a34ad8c771938482113618c44410dfcb5", "a91b079d62116433d50a0a14552fa55ee39d8e4502bbc19124d9fe1d6fedd99f5ed62969538417a5bfb579e49afea1150fec316d845e7a88593a660d646fc9ba8dccbe1148c7d3d3ce62d2d470c48dd71a945be2286ed005c132b3b6483fe708e743bc9693dc98cfc8169522f4420d729a1352d9ccaac15c97afd70abb19d170829d3862a28400e15da5d98f8fdfb2057cac0694cebe757f1053624c063f48ca08be042455e751f67d291fcc994a396a3c7fa6ddaed94cf398b457d52dc46981ec9c19fd8adbb959a14cf91219735d967a8a2f5d505e623b8f98d23877b1c5577f91d77db1764b8b36243f61caf77f00ed5feaed20ee7258558cf99b54751f98f43c5f298d1c08110a9ea38adce06b9df8dd0bb8a453776144f4c5c5fdfc7546318f50942abe7791f74ede3b4ce0dd72115a178f098a7f6a8752a55a31190aa46054fa0f07ff94da234f3cf16dd6019cc92bda988dd9dc0c67de8fd76243521009eb8706d41b201db25387d1707ddc7aa8745ac5da555f5a86932167b415d2ba5ff52a153c089cdf1d305699dd6559e59ac5f85a063330e200933237f53817ee95f0e9b372ccb7f35464036adc10d8bf055d57d986d84e3995096b8f97e2263994ca1263ad273aa93f2b4b670421020e09d68c181b6dc68f5be0fe0ee8111dd90e98f4fbd37be9b03ef73ef8e764e3bb857289a7eadc98d655615a6700dde69", "8c16ccfc0aac64a301254863422bf1ad06cfe8410b899e00863aaac58d92c0d2fb60c423b73513bce208a253cc591c8fef9d8b735e9dcfba057d6d2d70c3937b974fc3423e0a22c56495f58586a56ba1b8da62f4da9c4744e52c0fd64a88916f019659202828e2a74d6667ef27a9177a94641ee752cc30ad42618a1ad1f061099a84296fe851bcd153c05494ae650f1d22a41d3824e3884bed9298fdd21712d65f63ef057c6b93c36002aa80a4af0866fc3f7034dabd21b602ba69625f1325f2455bbaa858483396ea84c41093b00f4b80d3cb7e25414ab4fed1368e94a85ae07746ff30fd27f7925a5818af22a28128938d384a987a6680dba9d32d2aeff86ffc7b960fe05c8cbe0139673dae2dfa6b97e456a87feaa142f862c9df352ba1e54bce07ce4005a5a71c8655ccd8bbae8e05153d08a33d18a732558abf9364065f7be94251c9afab70f68fc3ce0cb4110632dcb4e4d3cf74f73ecda33f9e497f7966346f9a6b0b13d39459f0444869716fb1ce1358f5620b4bc7d4927d28efc656bdf99f8b6584b7246dcbb768950ed896a066a8fd1ccff997d676ae584696645193ed960a727649ecc236502bc6209b4f37b6def20c40709cf7b45403026df779345919ed2d5f661a0141e7a0a265a958ba2380dee1db59efaac109f91c26d2bf04162e705622825d599be6a15266a8c1ac4af1aa57f7c58671b95e177a9250fb3508761199a6b30249a2aa16a3580cea9cf9a41b3029ce0d30362b37c021e597b20129decef20e360afdc7ab6045ce55786f3112c1f6f45fb7b7afef84cf1a245f0ed0d03f89f5805f73b2fb19b100d202baebb6e509764e36ab44b506d2c578495ac15b5002b9a254f85c98e2d6a761863a57d26d9fe8f1af08942a271b54c60c7c6ccc9e3585791ea155434536737cde47e6bb91315942eaf9bf175e907a0b89ed5135e904d7e2e2ea3037c09255b9884dc816cfae61737a1c24a6507aa28f2605769eff6bb16d07dfa9527de728530e62ca1de79ddc8687d431856b84fc7757c360cc401a0a7338b08731cf8ab14655c78b4f80bd35ce798df2e9494b112aab2a623f153ef267b9ae42e35132f5e81446f1de576d1e62958d19b5c0f784548f7244e928f058ba601b4904a6b0cb4953fadbf942dc7c792b173e2e6981ed809e5f65c1fd51488e7926dd88ce4476ec862bdc536168d58ed3beb83fea96464bd69f0b60bc5f2959c91fd9361bfcdfef355a3514850fee97bb1496f5cbeb070df0a82ed0cb8b06ce7a7c8bb7876f6c75975a53b00e483549817f6644956fa4d5a2e32af2cb3eef0dbb8780715cbceb6b63c139daa04ca1f4476b5dfb3dc9a5e7918365e039e1d3e4939aa9348dcca1b862420e1002e38dbdb17db213727ee2b6a1ce575980cf4ec4916685905f16ec389a845aa93952761292ddb0bd5129c3d", .None}, + {.Mul, "f76c17c7cfc4bd578e8bc2bd2c1d0760ea14c56a371d469d739371d1881b1aaf92c26891df1706c701007e9e13414bc4e19586054aa81476efe00ee7e2e7410c83027f021434f27d2df38aefbf87cfb580a7311648cc2b7b3915d540dff8cc9b5a03be3272f78f4fb91712113ff10108238e21eedb852389b0beab851757e9e7b4836a5a2eea3ea36a8185931e9ffda2173108b6336635078cc851ffc74b206e4c8ceed3ca7b7ed0be2dd1e2db517e50cbce36acb74ab3d9a83028d9f47a4d964bba3f76d797c5bdcf2b7f3e0b524ba48db50a924149b50299825d7acca0bed065f808e9ab7e43dc8e4770ac622a7120a3af5d9256472b7130683be69d5783961f2be49cf58ccbc0eb900a634edaa3a2186b99a2ab898ccc37b5176bd75c8807b4470cd2b5ccfa82a0e4e007c7ea9adc1e38856f1bd3910529d2d9d4b7e89c1f9b83b7467a6f3fb376d14c8103c6343068791f498b5a8094755bfce73db5298d087911a6929b4694a5b2578b6bef95dcb425f8c3c33bd25b462b654b05a4e251d839b969d5e18fd3322409bfa30ea751caa7af6036fa2341681ee9e3e5ae8ec9a898d1d65ae7ae33f167df983c1f2c8364beaa33d236761333a068ead98d4a2f7af28df02c4de5b576373443c69bf8c9b2d27fda172d8dc5714e407ed61dd75c127ae0b06cb431c3189359cbca9ce8dfba526f541fc7e797e202ab3ba3fc1b50", "308d00d5e8da43dad6e0702fb0f98053e6b2881c7ae5785e39a0bfb51b2e384985bf58a63fca81f9a13c6e1643b1bd253f9708b72aa17ee3f6c20093162d4db3d16939daac6fecbf0ee9da617982a33c7b6a16c3ab6c3e182e639e5c724ba6ac08dbb4342cae4755abc1ee0cfe46ad32820dd9efc487b08f5835e632a7fd09366231e29ebec9180125097faac73bc6a114ef7d0b994581f0a1cd60db1ef0aa3b982083993fd17c8d3d1281b5a7c3230894dcb6ec53ef8e650060476368e553f325052cbdad2845493abda27d9465d6748bb216ec6aebf0d0b5e74d2bd06ad946604e36814c37bf67aca3aa8f3f732f2544260d9ad3d1328324b0e88d32c992ef12a21c0d677c34e5cf36b89ace2ca91ffe5fb626b22ed53149de4ae8b0a1ee749b12a66140d7eaf0fa241a034706dffaced0fae5beecf25767333f8d9868469029b2114a2a59a5ac32de729c324302c2880c712ba0583cc6b4d8edc47581755f5b3a6bb3a796790cd729f31bba0b44b08f87cfd6b8c27f19d098f2ba73f7bfb0c4b52d0762a9cbae4a2921daaa0facd9a231d55c04d31859148a82178c5a7761f3eeef7f1252d91e144668177f82e8d70fbf367776f92a607d29a9092be2ab14ea215851b5f742945892915468b37199bc394bb638870b44a1e962143cfab52ea71be4ef5f4360bfaa5bb3f6ed4d8841e68e86dcfade19272bc29accbfc849ee", "2eec8bcd4dff054ab3094ce28e6476a7e54b6deda12574b509e34d049f10356c8fc30e838a29d6ecb466282a922c00ccb4e202a9fff7aec4d22d7c6440de7655cde1204204cd7bc78f6b89ef9789feb610d4dc79fdc3c9cc24810ccc1d19e581faad7b850049a507bb9aa3d8885eecf65ca02575acc2ed476244c9b8f0177938e9b6c1ba3640c1c6e2b8639fcd0fc2e621bca9c62cb88fd709f457914fc55577236b42fb75a9ddd1d0bce42eeaca87af8084833798b6835ac469ffb6733823e062936d99a28be157df8f4e77e5d07bb53754340dccd9d054d52914537ea657a3f602f4c8d39afc21aab4cb8d5fa14afa253689439e55cf09d1ba933e386c2d845c44d8dad2e4bef0cd11f31e605f3732b1e3ad980b0de5cc883c5a3ab82d9ba5194bb8813e50ddb198eda616d0970a44acc68c5e24af8da2fdcea10ca03006ae7c978eda59253b41ffb86d7a22349fbadf59674a426522537819757ec3567a5cd6c3d2c8e7bb1559f1e0ebd0b69e4cc2a1a4e7c2d100e5dddfb26b1fb45296c5f3ec3ba74aee1eaa195611ca002fdb45d2c259563b200671e665e914bb8464077c79b1d3b68f0328be3e639f089ebfee975502318b7730040181441d3b5fd521d60caf70ef63e431fa2a097b49fec9241a4b3e5496aa511675f72535cd08bb10b487bc6a5a6b4864548c40fae6d75614479661f877b3a5f0c8a77ed5fa6520e3691af93679fece0750585bb50e07f1efce163eeecdef65745fa9653030cd705f8fa468a905b192fc4b36eaa74dca8ec6032226f2b9f39eb1b5eeaf9d93b61d4046b6f9f3cff84537f371dda80c5b5c7d63ca7237a30742990c648117ac767c2c684021a378e4065c725ea93edc062a8bea328645d8d884e388e2e0749364e6ae3dbd09064f37dfbdc82200c75b6c7fd404f5eedce60eeee42536b9b679186ab989d0cead7bceea298d323f485aed29b48472ec2e4aa8feaadebbe555f5dab8e0828b93fbe0f439729f8da3fef3d41be4dd6b686e75e1bde4b3b50d06854d8693c2b83f5863934994f9f04a0ab30ece7a7d1a034cc0e4017d6a2fdceab2eeab8d762c3d948352e8ac89249ee079cbbf1d1335e36a3d1ba9a0918f03e63b5214a3b47e0cdd8025cb270b8cb13297609b593ab3b0cc66e1ec18c974f43d6aeb9a1a029dec22a30ddca3ef06b6799a1affb8b365b88490b28166f1f3a9aa76ab0c0ed19960f5a5957c616838948946d86b8f7cbc7144e16e3247def70e58a3766dc400b1ba6f290da5e38e1d12dd4a9ed61f4c6aa59dd17ae897dc53d2a7d98d3c69a5a766e396d62f234aa2649d3a75b42f5b54f1840c3dd6bdbeda8d18d57c64aa0baef4912b9daea8014f2e753f23eb65d8b340019d442d9221a877ca4622bcd3937ce7fd63b2b18c2ddf76f2153f54a966cfc428b37f197d9f344c4b5eab3460", .None}, + {.Mul, "9500339bb6f5b769b350008201532bb8d3c8c9a8b415b49d0714d9dbdcba0fc3cbe8c28b71a54e20f9dd1b21774af81392737772d1b13b5e4b005ceeabda66611e7d249a4d3a281bcebc6bed3a4a0eea24e1c6084ab96d74488b97eb9417125cfff51b5812022e868b16cdab32eebec229561a162b7f9d5bc69356e1331631aa896427dda3df10c6869c52ae342a6fd581be0c379af4f8a566a8e38c8a9086d21210dc64c37c720c794667ae68a0baa1178c16aaba04430e9807d3e83ecdef56b948966760ac052fbe809fcdca62e31cfe6e7eb236e6d35480eb5f6b4198d096bff4a51561837a8666ba5a9778ee7a5d042286794ee7366b89c57e3a5dd637a4329b287fc67f81ed2c94f9a2999d42a22d60ed34a0a6b53bd1a8d19ec163dd36554baec23f12db3bdc0044b5748df13ba36519fe39cfb8568fc0f6c68e999e49485fd9f0625d84ee5fae0b26f690b876008685c016474b48e946f7cb92a8ca43335c784082a20d43d1bc406604068570112b56ce2bf58990d4f635a68a2a2638281d068c01518f94b648b007ced8c13fc37e8b0f9a5705d8b5aa9e4be647e986ef81d92e01a22a1e54af135d70745acec4794a8e1dddb2669b1cb4261b7c674e79762d80d22bb22544d139e3b1f220a1f98915375c4d93ad1329c9bcf54b00a75b419734e0d691d85e0d50dc92609857f9ebc1aed5ce4ac5962b4e0e928af796", "ecaa81dd161516155545c95aed33576888eabd35ce957de9e59dc02bae8cc52b2202daea2971053ce1b7c8d5f4eb541efb9324efcb97a8956c915eb8b7156aca4016e201d7b80d006be853deba94becaf655b531b7f439a18c1993384dc04bce023cbfee595e1a22160617532f82bbfb31445bf1db66061ef5e301260baf753c7fcde8a564774d59a1e2f26e924650a1b3db60ca261fc19e2d72d4112aaff9658149ef795fd7cb505b7213fba72f04d1cc00c6605af900b2a546844412a10c858cbe7d7b57df1a60482285ad69cc79289e8322c38685664948e8b9933156224b4cb3a390b4f37f84d529de52d333691129afd30f76ebe45fec2322ee3d25499c854ae028eb131b655bcf2d194bf3288438f69f0d83414e306d544b4c61334549a92280fe6f80dd712f17fa007edbc18e7b5fab5c9b797e99cf4d51ec0c3e9f907c5f8a04faeadc0154fb639ac9016bf4013a6f0ca4bb494ced63bd9798bde8c5028996c6d48fcff0549a2bcf2da886b537f123b07f2ac7b65a2e67c2eef9e5a838248c1fc603cf5ed366cf4bda643d1522759f090552e5e20dc94da54f4f4aa7b263710853e327325b61d91c3ae4d71ca53ba1aedf9023b744b3a50f7e303de78e326dd7deb0222119e7d10d43b6ddb695eeffee9c713099115626620bb994cabd8dcaf8f304dfcb75983d50c9053e5cad84bcfb0e8ad639f920a454573d987b", "89bf6d4b9a1a532e0d9eda003e3d965667530078eb12d4b6d8372a8b90c1b34699693b2b037937e923fc40b6d6dca9e0f8aa0b3725a58f4ca0ee91131961ea56f121202fa7fa5a26862167cee509a0842aeb0ed57702c202e205e4bc8a264162fe57e1ebde8aa11789acc4ea9e5b50d9e72b7d942a101fbb7748e3cc4f627652f6e376bd8e4385831b2481ff406a832caa079aa029f5f187c47702072dbe37e2a5f023e495369d4dc65c81514497de64869ed77c45330603fc5d5ab8d626f40f3d2806338155ac23effdbdba820bbdf1404e0cec4a031ff70568f2027c8611e7d8595bfbb1589793d2a5fc9c26d00c1c4b6cc75de81cf9b5dfb3f753728b52d18105c81f3a2091a6f0fa2b8925091246869b3be43f523b939ab58b6554c589e2de44c9daa2f1212e6eacff2f1f14a8216fe709ead2a39996fe12a848fb9ed85f8aba826ae2a71125db76255c4ba487fb58f5cc545510c3282061272dabde0591e45ac224febf488ca35cf1f49af30514bf969ee3899e71d85126661fb227f270762ce70320ebc8c52ef31dcac3ebffbcbea082773c0e487113816577db34e6a4ba746cd3f80f2898fba344e380e1cbeb55c263c8d25ec2540bca0186874b383ea244833c6856eaae76906d8d5f1b120c8357848abaf7f491a9a8f80b46a662c9bafa2b9a3f4c026d3096dd7cfc8c21bee8ba03c9f74236705d3576d6252fca26452f91e2ee05d771bdf3c903c28655d29a0fab7514156d390307db0de1d4833fdf606567b67e3aaac82e437778d5c3b9ec64363c757b146b35c9b2e74405882f28b2be862ba5819958898f57c2dc873bbb401d45d33f926dc76a3e1be39f152ffbf4897dcda75afe49e1960840b4232643ee0ad32075b37c2fc0e95968c4c599851c57b91aaa28e1502767815f3fe14e01f80767da1d1f7fccc2d8a53e98562f2aa92c4414f607e7158ca85b97332720a6123de031c6129283574069ddae270a8129fca137389993b94ca3b536aff3e9dc9fde212afd1da8fce732e71234b1b50fb842fac328d146c2b0d59dbd351eab43eff0ea88f07c114475a83d8fc63f68090a397d7e2539af2907b44f400662641c881c111dc3d4501d39d7da82fdad85846c4b7536b2e4fe67e83aeb1a0ac58557013ba5c29573e17e0ec5d0e94eab93bb30a94ffadec27898b8e6a312cffff7acde644691b82e9e800cdff08c3579c37928366ff36d93a19ece225f0e6564b169d766627da57cef2fd150b7fa2c3477d7c5bc261bc725513a857e0328e844e93955acebc9eb85396d16e5a2f52212682e14d63b488f0d4faf6b87e6743748ec546d563bd1adf867274c48f03c2c5459647e76e05fe07f1cbe4c5d914830cac2ff2dd58073aa2afcd043c53144c3a0591b63f33f5f47a0f7a242024169552f6dbe1ffd2796f7b1305f62a27be4840512", .None}, + {.Mul, "c447d9242e9514470b2ac6fc79645e6943705e41b17b7bdcde89157a5091addf8e4996a90b9aac90353871bcdac594a8a8ae626fd1bcdaf519506c050163fd29e57ba72524539d361630953ea9144e4fe5847f610de6da56da4a0934fe0743414913d647b409e5f5ddef835f902454a207c6171b50e2c2d5db4f085d96f33f7c2557755adcea35130169313b3fcf327bc98fb799b62de7b7fc62f300a6c3a9b5520f5264ff8acfaea823b636feec78d58fd8cd2bb4786dd2c35020173b060e6f0eeeac1ea663c44aa5386514b31eceaa7a2cb0ab363aec154933be4bdb90c322f292cb68de09e268c11d002cdcff2288ee18cd89e1b9d958ad879e4a7309fb7b52a5cd5e193f720cdd909fcc049bd9ea7d094d56cc65c9208d764ef935aca950fb119d28867f7cee782830fe264ec8897642297e8efbf525053ada88bc3669d3adfce492ceb490912b9ba6d61f66e3788bbc11ec37a7990fddb88aadccbcad04bf2422dd0e81cf20598329b9906c1cbf3c250240b9e5817b4640b7906a41335ed4c3554450724bf356af36f47fc4c50dfc83935ef7cd872076d334521d6ed6f8d27f4aa207fbca00dd9d87f4c40d501d5bd234724e2957422d7d5056b49982563a6f143fbc4f44019436c4e3b8f0c11c85803b05f8a0901102205c4b99db79db427a648faaa73b8e7d5fcc619b8e0b87976f9aa9d212299806b79b6ba0cd2511", "91f1456e41f89d325204e3015ba2870f5792914758029b322618bbe2d0fa4658bf9d69bdda56c72ee91bb1d20b901e8cf6dde11a27b4edcc03dad2094eb16a0b2b2fb7f78d333d0d5bf37ec2212b97882f0e5eaaf31bd56ebe63db72b1bf50edcf7512caea6025796666d9d4e092c7e821937b0a2be2e883d5515b9e597f0fd06c5ddaa7b44b8d229f41e067cb4cccbfa1545512e087b7354729fbe13237d7b64b843589b00719b4eda1bde703612dc77ee747e4c8d32916b05f6642c01f432e61eaee5b46cb1395ea6501401e4002ac6555d6891c128a9e16b8f44b8c30b8c2a679e397eeb95ef161fef3904eac11f6be868ac04c47c1436f2837662ed3928eb22703fac4d329738efb9f9f82ca558489a2c6a0ea333b6dfef67df18c2813b6cd675b9cffa4ec35b94be47bacb651bd265f96ed5dd6df0a8dce773d743294205b895866efef4570c5c4f2d6a47304876bd42b052dc654cf139759e7f2a40136ae7808e47eec048d378793d6b87f42ee867c22a284ea20dd0e570c69b23e7f615c2f225637165b91aaafa4850a5f78d1941899f4bcc53ff22e07cac775fdacd9a2609a5796ff4c60a9ef487d241d6f5e0e5d7e1fb86661219793bbdf0f16873c620c53034b1178b01635e47e379b09fe3dda0394fcf2d40c9ca3f2595ab09963ecd8769b6f0203c56915dc8a155ace6304731abcd3170b8a696f258061e857f", "6fe5aedcd06d3531b6b1f171993b74555f3ae08493515aff06be425fd35a634fd61c37c8c10f2022b764ee214e2e5cde7016a2f74d893c870e7f1cf6dabc4e1e60268a319694eda77fcf2576ac4f9ca51babb64020485066b9c3842008348432fab5e043f2527f1a14ccd7f5ae95383267dc0dd0e5ffca778efdd2ece095861bac92b4fb62e41a7fd475f90b4fb668b02e601992cdcefdbd5979787535fb5c1a70381c2a40480747044f8ce0bf327e6ba153b89a6e5846ff44b6463f6b33bcb4e8000ae2944cf5478c95ccc5891dd627d4c446a1f92444adfabcff12ee7abb419ebc46461aad82ad3f92c7adba755b79493bd0628d6401229f24939432ebfdb633aa7065770109e0308985ceb52cd66b2d3737f0ca5abfb6bf487e5e9dd60793774fe09c639b65c0b4dc63a445a63a2c1ec95765a5e5aa16146163ac4f52a0faf5f25d243e8507cc8e86004d83e9fd653427f375f1c78141f0b63e3e8422bf5003b5232c44798fbea8486038dcc9ce7f8ea7b284c1bc88702497b7b8711331463b3eef652645fceb53b6519a23632ff83ec80e5714ac5a07fc9e9681d8a58acdfa4c0129e03eadf3228ca7903365969ca1faa38ca7c3968152125739b8077373ab6e1078a4af4ca99b8617fb0f95e59a7bbefd24c324e9d84addfb8a6beb8d0d41303a16faea2442a929e83bc640ae0055d8a4cb1b6b0960d49186e23df1dfd45cefccd84fa62e7936201279ebc2599dbab93bcb245b7470534db393ef70026e3b54b34a50c96d457d1eea75b63ec6fd567847193a3c5c1449a610475de954acbf98e4c09d93c2d5006fbff2f0d20046e8efa9d269329824d041e4de5cc8236f3ad72c5864d5dbab284b2cb2482d113e395a7d0ee425f48a1d636f78db480a16c506769ebf6cfa4b33517eadb968ca37009afba7e4c0db4d77ad48e064400d351caf63209d0b1d7b45d63636ca9aac2d2564a10679f8b06000cc0e407e328ed4b6de2da7774c543f32173c38f3160b39efefdf4be260189f26c6fc51597a1c8b6443ed4fc2e04f1eab20ecf602fbb3c1e917a2a9ea753da9e0ce19c63968f3b4ff2e2178571e32a637c0877a806915a5a41f6c549e23a20fdf9dd3a54543e75eec8e78e074926eb89c3250c476522cfad7ed877ec54876024549e537c2684926449968730aeba1b87089e011dcb5f251a9944bfcc2f9315a08e85171998f809c3a1008ec4d009be93d519f2bdfd26007d7e181c55143dc2947be132a31f9d89c85abfc12ac7d86431b117ce9c44d98c347699c60d78e03f1a913db45d2a28a83dd4136703a6d58dd3f8cd2b872fcd7a4ddd6dcbc79408a55b8d0ee00df5056a1208314d156917b5fa62228045e1afe1726c79bd23ee7428ebe88a945d760f83014ffa85373c477d47e5c6b0a52b03d0c7b5dd78dae1328766bb7bb01805386f", .None}, + {.Mul, "-c83c2b7f6055c7c13fb5ab82600dbe97dbc87e5a117710aabda88bc09f496ebc2b542e9831d6461a8d941376110fa06b617327adb9940c27bc2d2ab67fcfd8cfdd010a110487b364bcbb59edb6184e72abbc4c626ae1c4c399af15515010d18244e44bbf896cc790075703d7fd7acbddbd3f121d1bdd3aee1824b2a26143a30e1fd711606d92521b59b5c7bdea6a5ba411aa1534802871d260d4f6a83e274f75a92088f2fff6a6117d95bac8af3089d1621b4d787615ec08c906249a89e6877bb2988cb04fdbe9ce9e8f9ef2e0621c9252b694571da7712693e528a8ffa96d43d968f4c4dfc743cbc9e6460c4b21a4900f42a0c9dfcd06a017858b6fe6751232b2504b7e720611f5b12fa7abda08b4d40d170f8f3a46f50dacdcae670756cf2a1f88c5f9e2ad1393ce44b4f1866bd1ea0c69e16ba6694173cb3f27c9d92242da6f4a14a8f539b08d6b2b36dd13d9d329ca8988c4a1be3667fb0328c848cb65c0ef9e73543e12dfb49949329e2e9458d5879b4b00020b8b51619cac518b4b6fbe1ff5edf24c99ef19189e024f8492add9c01ef941665083c988945cd22fda1acc14a11e525af3e1cb85a5680c05d6aaf0706c21028ed0079db69b23514a19b0b3812c10596ae92c9be483113c587dadddf6a70c46f9b4cf93824a30f26775746bd8e47246e404760d95c63d742c61f65d75f6cb0ca00348d06050968f5fa1b9cd", "302ea5d8a53d89e4274dcbdc96946562a47582b3398b93f24c02a6b365eeaec43f9cb2b6cd291f2fd39ed4fff6492963b9b5a742ba58020868ebfa9567827d93305ff6fc58a4dc5aaff47a0fa973298d045365a0a29c6135ae818546a0aae31ff2949dadcd9f07c6ec3510f9add01d0dca2ce9bf4bd457fd216072b77080b2c3e5f9bd5b4f4a1f6a69fe376a89d5020af95a1562df9141540239d2209597246215e0b2ed31e6509e1490312b0287fc08759a83c123e7a8e0dc114857c1c7d4d238144f75fe860205569d6a4ce339eb330d56cf6ca3654d5a2906e954e6d1fa357bc33713e311be4783db04be58fb0a69306a98ceaae16ebccdc90f2daf4b26dd81a3dc545858032f1f48ee761edc52a28bdc1cf2ee9f196b11e8b8644da691eb0ba962e5e6108e0ed32ba8065070ee4d5c38eea5b2085c47f7e953741038a6a59f9b88dc43e5e9b4d969006e60d65c3fef44bfd4ff5179ce3000907db1ba33d223ce80dad7d53725273b604257d8b48251af5378110636d365482fba7f8f8f7fcf52bfc76ba3387192482e4b699d4558e7cf5a14abd022430641581464cc29d9049157c2af96c6b3730b6bf9dc10edb000a4e1f166d3e93db0b342100a4190d97dc9709fefb95e86be26e2d4b55fd559ca1696406e95e1ebc96be741abed7ec3751fab58e2a85050c92b0d55df85040460f47c733cf2e21f878c26aa6ac17564", "-25afc4afef001ba8d0d8c648b4a3eed17e5c1b815dea221842c9e02a22aba40d3629de74eb675bd882474c5a86657454a8341cbf14c62e0b2b5feca9d1b1e2238e2e1706d832c698414ff832224e3434e604b40a78240dd32bf82a486c150e294a4edecb8360a125a036507c1119df198d5577b32cb05254cf25a3e5ec34f896d9a294cfaf1572e977ffcdc19bf35840350d9730e43cc6540f16f740fdbca37ff42d6251a4c3f7e001acec654b9ed93e7ef8c8beb211d79efcbdc1cb999af00274ac19ddf9f045940c222db0d842e71030e775bae089a63134962d72fdfce2d7132308ae387f9f1a3be33bb6869168ae7ce7e2ee2d3c877101b66a52b3bd08071ea8ee7daf8b23e22da15d369ef91ca237579d0827c4c3f582f2b5ef17587165199e485f745e30a13c21964c997e1a1086489559a997d53c7aece6756fa469dd46a0ac048d96161e5b294b81dc32d1dc66e3c8ddd5fd009feedf7c30ab13321604366b793d2b4d47522b803e86467b13dd8ba571764a03e97a37686d671335662f6ca9331797665d5a21462c04960ba115795cfe4c39e4ef8944dcb116e1d8162722d73df0eab5889c42a1ba7db3b7a72557ada042598e8d82610d9d88a62567da88726a74f92a784f788fcbfa86b6108a62dd6777e4513e3de9c8496a3c629b83dca4be03942335797c8fc5abe50bbc39be028b99315ad7c3a90827ee600ed476f90174b7f5f34d380d35de441b92fe6382ba9d8c6080ff9f83116f1a34bf8c37c29ca51197c23ee9b08f0c6691eebceec9eaa0df3fd7fb287a9fe1565a4e63552b78e8cf60b5ea9868c497d6ebf63c858a9cee04710688aaa7a99e6cb04d2a318e9faea0b49962fe521ad7b82a892d7f8ab8c9c94d3af6331f418d8af4e0876e1616cec6bea062cb05a060fb2949e489f8db86f058ffd9cb768db8babec034253306679db815d5171d42edaf88e935efb3ca655306cab680ffabedb9991323598fd1e8e3ce5d5dbb6e737b76a78c588cc4cf04156b8cfe421b59c34811759d8b87311749549e4c9e98e54d2a09377f9761a017c105223583853c65431e5f2cef4cb3f33d50dbd53a2e854adca5ddf6b8be935c436f7bcec78b7c72959da3ad99931d09866f09f87d00c4eef5b7df5b75689c4db00530cd62f382536a6ff78ab76cf303c66d37b192a7f556c61a22fc4996783fa822a3742313ee401134cd4b66bacb19c54f97ef624c8dd913c58f1dc1639b2d94f53e98fddb434a615cc2ae930a716f8cd4abdf04103b1eb0aa70242f78d423f970957aec79ba7815007003c16bd38b0843a4896a8765b15a3e0a723a153e7680e3fcb2480b63c11f25af57450a7afc24b83a132fdc175b05295214139e19978215220c38f3f32351cc57cc3c0440491a512631a771f04eda4ab75da15f682216a3fb2a8e1036b43aa44514", .None}, + {.Mul, "-c50fda512d0d0eb0c2989c5c2ccab93eeac8bf6c1231dda612da144954e84962bcdfd56d2a85e46b1d8bc3c5beceef0af8deab5013597c29f9601733747975340c85619ebd277576db0b366fa5d465ffaa2001819d664844336c00c58252b04ddd58b7f53cff7a9cc260db3a29a129e2a1b5b27e95cdc1fd2fe785f40cc0f4b3215329f8e9e78ce88e5f3fd50e94ba86e2492ba27b149599b0ee7463a0ec3d3c732e34d399dbd08e30b5e09f6c56d5f70b4b6afa8d5343aeef9eb630fda9298c4c96d14a92b7e6f0fe50cf9d5d30f610645ab96416ad54c709bad6f717e599a68463895c16213809d55a43b8a50363e213d9372a140a68c165157a3535f45a74b70c60d4487c9281bf1c412043e3f93e6526c009587c1f954fe5335d9e599af80ea86fa2a97b999f0ee9476bc71b22b2344bcd8944ed3e516666ea6a531b85fb3c11918d3bd717a66dfd236f24dc3e590ec7fa0e55629b10fdf8a15ef34a016272329e620b96a43b15d8de1ca9c6e9ebc90d13f17c2c3da3e4f48581b416f43b8795239a5046fa9541daab756be22b4b6b6c3f7a051320aad41367a3b3c188458b5430da1616aced98c38d8cf8f28906ada23371020dd4cb5550c7ec3b26701dbf4cfae17e17876f9c551f6494c365ec0be5dbc2fe5fa45390e4b7e5c1392a9b4dbffc8dde7c6056f8220f23602a170d5e4ad8cb37bf29bb3f71e4587c05c802", "aeadd5a4de5e08e7fb740981b6f8f39b46c17009c04247ca0af8d6d62a1808de6e63a13e88cef9595d3017aceafdad19480400541e4ef2949be557e4f47a47fffb7949f6fcf345a0d44999afdfd284469938c887f2a3dad68978c5a8aa6a9c927b4f3359b6ea0dce5e7be6325f784af4299c62669c93221fb102b4baa9d297911deba693d43186dd2bd272b08d5223d4cbccdfc32327372e6c14f7175760646fa2ee11f2c8b7b0d0d7a1732351d76b47890a3e5f9f90e067d62e1e6c951455dc98323657308955b02e5ec101054aa534d4df818c5640890bfd4960ee86542e51441c16f55e40606fba6bddd7087e4e03c4ad18716bf0aca46f570ece776e703b94b363eaa8a6876139a6e58350e283d189cdfc04eae572b645241bf51b26e2ef46b2350ee70b834cf0acb40a96ebc0397068ad3b087ba7c7169e667d366e936ebf3ed3ee94ff4d854289c410dd9b8b9c1234fbf2dfc781d7ccd52cd625b3e2bbd682738a0617e6cf0392906df2f67733ac77af72e73721f7cada3c61f0e593de2295d4dc4ba889d367a8ccb64c7bd77285c155c971f826ae26e969f10020c14666a1dea909a1448c6bddf2def6b8a779b4007cea1e9e719981e64a23f51637d2322470ae16faa440e340e02d8e64f6d0026d45d8ddeebb62b20359979c115d6c0045bd2bd95706600188770eef9cf7b0cad3697971986fef975c7f4a2e3c3d5a", "-8676968ecf73da4b6bddfa4c9df57b54ee542c5807ca924dc0e743374135d3610f0050fa8d3f9f1eb01e5d5358c6526245a2bc428786b7335b0178444d285e9740ef4c31ab452d0817ced02ad2cbf917286c34328a0cb13da263c810674f000af8a037a94405b3e28abd1c09c62915c325b4e2cc56160543dab500e0d8b448eda5974691f779b4e55815695e3f4a08007de66f8203111e573ce41ac6f54b082f1b284bd8a5751873cb684c6656cf6cfe4e9e10ef1b152ff6a23b54631f269a7dcb818b5ca2c0f523c3578a6bc207d4b3c16567b7db069959310c180ba45fff6365fc561a8475b2fcf102e3c7e6680de84ec21d4ed10b9066545076ed0069d289924c06c8d8deff518efe6fc42b40d2cac32940c40c552c2ecb2b94f0c69f0e7fa8967c450c1b13bdbbb35363ba2491d100f35271e475351dab3cfef14bac5a6fc03bf2af7ac13463bb17d918d79ac51af4ce1b35f3b4f2a69e31a8e228a61996b0be230b21d8e6be2eb3cb4fef19319e239f95b13b2abecced03799f831c90b1701c3691c416aa9c7c9df115f01cfa2067347b9819a1c4ad1fe4d332bd7f3d9d6b89fccc5d7d16a2d90ffdc8e878334ab2de5551581506b043926aed9efb7b43e2d4d41ceaac955809d56a8094db2d1c1a77d574d5528a4a0a4dd6a59fbd8d1391e8677c37776ecc5e5ade8a8c1220f8e4be97032f2c9ca48d1adec6a4dd9b2ada8d7081d6ddb95e894aac10b486a965ddbe26051c57fa57d37ab688b6d04d2d00179f383ed89b03e8de570eaf2c8c60b586668d9ba34fa5eae56d1fbe75a24831576dfe45c5db30b7aecbb69f1bbbe76af3309433375b1fdbfc07a365d025fb11ba61bb389ba8956d0cba27b7033c81ebde0d86ae5467ae3e46a78474788bbfaf5aca77b6d7239ae37ffbfb0170f98d51410dfe3d836cf9b1afd436bada827dab2150c555e37e6eeac24269fdf05c80ad601376b143ad7daa86014a1028a0d05627f2103901269279f7fd3d9069a5dc6b06e2770f775b80f5fe1b6e3a96a4fedbc2aa93e3c89db983bd79e8576bb9719fedca3894570178711d9ab3fd623074e6b2f198e81c291840f7c01781745b4aacf43f8b5cbd3007d9f3783cb9c911ba16b3668c0d834817d4a1224f548fd56d1b4344dd633ff57f5a9be22d13c7ea21c07f0613dbe4779305d6bd26b4ff947e71d8a1de1cea2b506fec12027f6f003737fe14ef00ffa1c66e57a2451141a92f73614904c05658122d05ee584e2ead53ca3307d136cf8cf6053e92ec575f5a80b7adcb886678af2b8f13f83b629c0978ea57d3ebdc8001283eb0a557f64338cb8ba90045d6687d311b833df3441268852083ae7833138e3bc36701ac381bf40007bfc725f2c3ece54e35fe99244baddbc05d80664c7f0d96e7dd10057ca9a4c46054154b99e619b1a31646883728cab4", .None}, + {.Mul, "-a78dcba2e71b20afa5d852a23173869946f28ed4b942e907795fd8ead225f215473e99c1d3940e6fa00ce50b83de9f6efde5ed09ca244226a69a0e25408be18909a9499d8a57c43025183e6638ed36e002162b5ba043ceebe9f492276c7633bdafb05c471258396272d2ee67a134310c7466919df56608da06fe01beb8057ef2f775d729cd50f4438af7a8558c9f214ab93ab4ad7b47336fe23b16cc9354b9f499bd6d90b8455aeb81f244189843122935bc5db584283fc6e89f6e6c6413f6c3f649d4b95d0d4dc080089aaed836602efe3ee85c397fcd30dae57cc653ec9505120e7d5c658ef5368c478467ed53b11d223eb29d0f597bc4de6f65712dc2cb52545100c06287a5800b6e42e8bf3eb5e4ef095f2d92e2f78b457277033c4b699e5cf9b7620595c61a1bd17bca0aae149af26e1bbc1b22eee6875a6157ca8ca06239bd75b0921d55dc399ccbfd5d3ad5ee90932f4570cbe30c5d8f012b6fdbdc244356427860e1a71bbf699cd652c32783519bcdad92c2a9f6500517a99e06b2b2787227aeda191f2a222bc7333f91ea6626d6f6930750fee4de6be5953b6cd09a86be6f904062caecb58efeb287f80c5cea8adcb68c85dfaaab57a404320c8947dc4225e2aefd94d4e798d8f5a13fb961cfee39d2369b4e1f2778a70c186f83bd9e58039092277bcd686a2f0f93233ff896662f1c2b1e079f11129c6237673392", "d94ba4e34bf3526176491becbdac2f665323f0c47d72cb948a97e850788c69a69773460653fa945dac2027bdbf550d732456203478d77da250bf0313c73b3126bd830e7d5ca70433c84c104876a83c75599c3dd2770b7195bbb844969a7a1c1b5db6102ea6e66f8f1242889897d5f294076416e9c04ce82bc7c4ec893f12d9e09de0bb73dd3e6ee010bc44be67235b664ff88005f1509ea7d896606b456e50fd6de2d78147ae53087fb5236c2ada6b03eaeb7caad059afa2f9ecdc0774b3f46f80ed09143af9f65b90f5fa718934ed892a84e09a817904cc76d0b608d49603e0adccaf32bbd0b7e370f0fb82989dddfdf6879f70566cbbea48b5f6e8ef5c7b6d45aaf6c36fa72f6aa6fb0d441a59122285b39e22f50abc9467128e54ae281666ad0a7edbb673ae869012262a9a1d3b2c716b1bf3026bda6c1c6e13256f4ae9cde2a7d02cd0bce3977ed704b507d984a5db1087541ca0a2e5fc1b1ddb56b8fd118e82fddb8f19600ff2fedf09c290aeae262ea020c2d267b0865de8bcf4f9dec9210da02356ab75b73d084df5668e7213867585163131cfea2b5703edb5af0c01fbea5f1ace701d5ed85edba2ade036504bef92ac238b303982f9ceb0c737edf43514604fc3a210de94052347f0f990d36e8385071a4840d3d1673af12083e5111474f959055ba68960b59c7ae7d7878f94af5b60e291c3bf0fe006f0671d52b5", "-8e38b41359856d53ffbe54112291bba596f27cc3cb54db57c23ddecf1de18de1ea3140389c85165624ee41d9923600236c9e9819d4f27e5f5f39c2ac4bfc38f5d1370bf629544afcd50334c185b3fe54677a0cf4768a27d724a2346f26e7759e9b41ac0a52ed119aeb31c4806ce3e8a7ac5dcec3d786fb597b0cf29cf6ab7032f50bc1bfeaa2ee61258b8004f2966b6e0cccfcdfc949d8631d0694a0762e008ca066513164e663013e72ce825aeb8df145a5f484267bbae84dc81d8926129852d085ae11a62e98e9226ad60f3019cb00fbc92503575ee5f1eb8f90458e345c3dfd3cb220b06c72cb3b62be9d9ed17818d1fabd039a560456f746f19b77707b5f7b38560d0986033a2b91d19ce85b96063449962592e349ada8794486e88dc5f460dcee2b1e69c1ac5f9a840013c2494ab7c56cfe0d21c24f96dd342c421b8609414f5906a2eb555850d454cdf1ab7ab09baf62867a28ae56d9c32bab7c34a73a36b08cdd710c269dfeae88fba4bf1fc7d62a904f3a6f57a73f6c4104191872ff7531d9495d36a2b940565900d3e3267f924099317414e3e8c8fde3144c828cb875ce57364799ee0066c84648e8d297dcd02a33fb67aaab7decb015b2ebd28f20445ed0a424ec4204f9ec15cbb350be05df36a99551c2299337f40ee39383e951f9315a1e5287a4868f1bd02f1c51468052206dc8a1224df2aecaa771995991b2a1a981164b126fd5df3c6e8af75a01ced9a031c1801ad09202e37ed42a30534469cd8516b8f300e6fc295108cb918d0bd35b2bd91a732ee0a767cd3c446107de8cf153f2eb4d688223c256a13f1e8b134c7f8c36e1f0eb11764e476e070362454f470f461cc2f996a48814a57d60eaa2faef93a074366d2b19f907490a9d0f2904a27fd5b51504bc8c9a7fd503c749dbfb0f0a2c722f5b0fe1540f52171431f0a5a64dfcfdc2a03c06594220ad1f837e774e3edf438e90560aa6a5aefac36c09954c3958e552c71892feedf0353bd6caa5c62e4e5a8275ff6d13c911a05fb068fa9214502829e54517bc8d5ae7424dbe329ce8eb3897972f95ea330ba56cc4e86a68b847822741c48dbfa691623acc2406dfef0dd5d4dcf71f53427d6976189948f97977f69f4cf67c17f5abf7937afb1c0db824b21c065a5d5deec22ec2eddf8650b78dabbeab0f0cadd963a2e4ba6693f67ea248ba2d3c3a0af7ddee9e1aa7c1bec25d22a5eeeee9ab6a6be10ebe629104c86763509c3a64a017947a39cd21f3c801edf8febe6e2d59460ca8736365bf35a3f28cfe0ca2cfc14c1422fe24f5c87cc59dea5fea0c8d68460ca783e00e5968a6dd475179dd35a43bf170a0121ea430dac21e9379c0220239761da2a34d1284941bcd5730a0f0e47a5a2ad4785442cf866d2257f5352be236eec3bd29542bc66a610bd5e2974d609880d0063a3a", .None}, + {.Mul, "6fc1c716c9ae1a98732aa6c42cc42ef6b50ff799d7a21432e3a91e7f7d97c5ee28f053d7a7c2f98cb1c674f3092eb979edcf4b676a15353f3ed37c1c8bda48438255074bf9b1a3caeacd16b86f65f80bdf8e8326ef8b53ed9e4105139af2c2db579d0a57c51f1c26f4646a87f75489a3bf338db9ff1d6199c78704fb2fc5f184608d595ff34592c8e3e4bb715afdfc972061f8a4707e927ef375da12910bd2298a8005291943de8f9a5141ceaaa2c3784960c36c9d5fdc192682d50e7154de2dcbbd59bb7371249d12e3e0a9cb0b74f2ec30bc26fac09dfd1a0bc84512671ed7bfc6a05d82e0292442fff351c7de2cfd0326098b7f77c1887be28b1c4972ae55cfee257a38db0a2d79b31f8805d44868448b059ce436a4b2649c096e3eb0250a776037dbc24f8892e70bd1524ecfa7f5967c9e939fe57d97eadc869621ca582e880d18bbea284db7de7b7b1b52365657a05e98dbe9276fe1c7e8569b81120d8f9dd753b90c545eca56abca4af2a77d62dd5bbc1909a06447e73d371b0abf9d200edf99af7edd6c77a682bb6536f90ef48eeba5729109022089e533e6e1a3fcb3094543901cf0c2166b12b4e80b7db1df84ba494bd5fc7bbe45a65062254a3a3b14b7f0695fa7a023de631c34250a8be6ad101af026f72e83a66d6a55c339a38e9b5df1327324969c6dc64ee83fe2ff205f35cc22575540badbe56ca511b74614", "575e82d14868d452b0e850be1172060b99545e9a1ba2b7af9687b11051276e85fb34a4481b1d2b5e945d546da3a949fb1ed58dcd8cb36f4db7d910907aaab28ba9c9f219a5e221d50c7ef710244373c6a21a6a45d9804aea005f921c321d4777102c7e2e0830732b975bc3c508ca43886242e95baead6bee6ac6c94a4fa596c11bbe6db69ce750a8c67a651a300e9a39e0e3a053bf9e5132fa3b2b1edc06e79efe350438458ba3994ef631c78637a7ef5c3756b9a9a4bb92b67f9a3adcb439a17157ed62c387fc4562693c8dada95b306eb3f4a66215b49740e43942c1d722656d277fe71d645ba071f81c1f6c282fec972a0a9a87fadf7c90ca55d47e5f84b975a9e56f9b08a48e53c19a31a74c53b757b9bbfe07beecb5287a3b9addcd3206d9d140fbffbe381fb4c0b8fc479b9620a5ea3ff67e456afe5bbfa110a462425f6e94b33db0938da23b8e8c35ba4a76c0b9a326d8a087ba08e1806907eff24f8360265572ddf65fd12d7694781dd349065010abb85709ba3c3a50ec2c370aec1cf7bc45b88eb3f6b9f3838a1ed86aefe96fc5fab70d5190b038b64fd47f58581be3586e774d40460ddf94b916eb517d0026bf4beba61a631d49944f9f81eb5855bda2e842885f5ddd5b822c929e07bdbf9e10039798cf8f618d6f7e69caedb272fe4ca7b70978ba324fe2d928c82046761be7cdc78ab322ddb5cf68dba4fea3ac", "26241ceb9cd198647fe91789aad36c7a2b84f27f4a241c25bbe472dc01c019bcf0d9a7dacc232dc08155213004c5ba00cf295fcd6d4ceb9aa5f114aaea5b92c3158bf6dab9422804b716da89e1e8628c06b4f407a5b6e3d464239170fb6bbb778c9f13e144bc92c68a40397ed8d8a0f3f3295e9d68fce0d3a306582ca727dd2a9159829763f9bbc6fad6bb455a817c8f81c4ec194f6fcf416a5c87ee1d499750e0126b23a84b1628eee16748ff1b3f0689ee4884badc53546630964fc7917faab3da31335134694f022ed4b501796fef693016e218f7d7d39c68d5b993f5fa036c5a50a22cb84829f4bf089090b4ecb953ca473623d771cfbaf2ac488685a34e74b0ad6e76f8be139bdcfb10dbcd4e102baa32a1a18b7a64e6d7ebdaab7c87a9fa8f786685d922dd17cce07049f78c8ec10bbf505c862c7f98e787db201556df54e5655884fdbc844d9cb6f2a06ea719abca00473c26a863d3007733c3d433e6426d2ef3306c0e1f026625aa554d040f6baa2bde01041f9ce9409419e3a13c6defa7d867f2be4ae3e77b76923c968dfb8e8994a2a08a20dd64808c0bcbb223d0cb8b969a223519f1432f0ac1c1badef14186baa3e22d4960f5a3ba30befe7e77bf2479c3fa160375e5771f65cc37e583f3c204cda581504ad28e87f4cac3068551c5ba8582537b8192959980790f39d613a82fde89a852a11b54669a9dd4be36bafdb13f5c4b5a1c014af3233d4d6e51591b68816a3a41abf3da6152dc2542e6c0dc4010bbdb76ca65f79d9eccb7acf63835e4074883eed815621c9ebf07d2becfe83161fb9349f98ef780a5e812cdf4c3405d808279d2ba2e70463cb67969e40d6e61bc4dce073a44f8d2a0c70b6eb4d62c6996c71a08680fa18ef8aa800122a312cbc02d33c254e7dcf3e4f8c79c7986142525487aacbcad23a1fc8593e13c450f5280a13cc0525141c905507fc83b0b2f2a6405a34811ff1c390906774ba550f0ce4c9efcf92ebc827b49608aae9703b56054b83532a1c39853afdf206a65361673080014005ba8787856362138aa61e569506713b5b87d0e43e5ac637b5e2451f06673dde5fc85861587ce2d0aa4e487a93a6658ad6feca2e43ecf44146fadea32c1d972f7fb881ccd437ee76b5105130d56f3390331b7cf50bc6129dd0268afbdcb88fefb91013f1e24b01acf38b7772c0ce91ef8a2b12d70fb89ee77d8ef632582642f1ca7fbf692bd111063a73aad6f5b23b8341a9f47cb3c3e617019b8b60b3e096285bc106f8ff05f2a98474073a5b13bad05f790c579f8c4287505469fb5339714e80c7e1cc491dbf998f6fee3201397be83afe0b4933daa8532310dbe8291a7b98d8fbff6a8a1fffeec3d927b0d0fd8b47e2a38cfccacc515178b052b88a45655d274cc5904de71394811b105f9922eacae34c7e02907f099d170", .None}, + {.Mul, "-ae8e1bc99f9fcbff298e76c139a9ab09777c5e7ad9e812fbb1bba754b5f42a83581497c0ccb3a7229e64b6bdcc7bc3989f8c20c13615da885ba242a4b610b0ec447028d37e6dca40e8c9476cef57c54a01dfb135b053469dcea15c2ce4692614ba6a32ef309785ced17e6a5dafde74f6eb61cbd1a9c5d122a0de7aebe084fc80e7d3b3744f53bf0fc5142ed156fa03e87889455b5eb10baec21fc0f98c5d2b2fae2c2c1d75ce2b004e81f96713b1cbf8184bd248591b451eff524762b10e60ed3930c6bf7c12162d46d2d98f61bee546094677e168d10ad52a1449ff5e24e4217fef2000386f8adcc00bb641371b7b2ff21484abbab2d8da17c4377b4a651e49c421d60e3c6dabc56b7200e29482052dcc83112b6e88ce1db28dac7e6d70f189510cb682b946ed615172135fa85d862dd3f2fcd84324c3915961022cdc7719324f0b6868bf0f64be83f15de376009116222c959413cf77aaef2ffb67835250b2a16b9660345f0ec42a01b231f679f0714da466edfc85965406a85b72990769b4d12d24ad32f3455f0e5835afc60ef6766ba81f9646e47c85e2dfa0e91743c88c3da4e712ed91991564d9d0e9e053ba595a27dc4ca534f831b15a4f14b43f3f3462a9c9175899df44a137c0c3e0c04052467fd0967995e460a6b83857324ae73874104406155d8ae3eaeb3d02f5d44d3b7783f74de4d7cca5ddf528a76d4ea61c", "81fbb01e04d787585f1c07f31320d0a0c6fd986d5cc8b764ca7259835744a8ab1e5774322743ab213aef3a17dd001ae784a94daa4c6142e90f00cdaa2fd2a0dba5ab4a5a2e23f4fa7c83c6b9944d834a1f94df5dede33b5153b43c378390503a3d7e8859dca53bea26d961426fd9216d7ae0acf68efa808300196ba77ba4df354f6e0adc09f48d541b31d4c84ff59c704d63460d01e4727a95c0bc6ee60dd0ee7ef0e79a16dfc1649c269d4cd7d61bab0357fc8efcde44c121fba37b992395bcbc56965416e3ff771131be8e06626bd84a355ac9e049d36d5c517c19d96dd155a827e8fcec550a79f1c6d988a8cb993014e0ceefad3bad423135fe10852b13b244757ae0c34dc71d51713c0e8220d56b6ccb666b3e1b4f3dcfccae445e6afc60de4234246679446393e0a4eefe50f451ea5b71b965501848c1e54361b1fbab3125345ca2f084dfc0d8fbf223f32b55f8246c382157f2d28f91bd3a7cda96a5c7b6f76a72486dbe581c3e40f72a8b2d28184fb3ae818f45fadef0723b8dc2038fd918bf25c94d3f11968fad131dd5acb04b4b78be895929f8bb7b964dc75d64b3a37aabf37ed0a5c431c159bc6a12e11fb276661286a4d02bfca4abbcfa9f36fc4272d8429a54753673e347778dd8cb6039101d7ded36c562c6c727190d293ee42608b69cb554e08c563cfd37e972190197a776d82524ce1e5fd9363794d31e9", "-58a1396c032e14e8d74625258e482bf77475067c8eb8e3c53d94aaffa59958ae7a9a49e0020ac4c078236a93a3507d360536978afbbf1ce2569913d8caf28c71fb60a26ff0ac63d72706c33cb5589b64fafc799dc45a89ecd49659afb69a14213d5c2c4f44ff949e40efb597fea08c3bd892283a46b9e62f32ed01fc20534495e0faeeec7b64d9809ffc8022a879d3822d6378ac09653fa9bb3230fd444c0aec0d7d46216b347e1ae014cc2bf1025532deaf7c433aa4e48d95b68e8aa749fc93083a5f7dd02efcf336b3999956dc8eb9f7f90de7012eb5667660ddd1360ddaef0546ca75029d76758a92bf8af856ac76ef8e5c5b94e242c2078e85e1dfc1f40ff495d6fd8c74874b4c9e9c67b23bfead6e4f12ad20ccdb8397e12c45333d2f674e932b11e4a0eb7e9f722a7122b91adcb432f0b336198ab0004a25bcae4f70b8bd94ebb85702e862d41afc3a85d36646fdb13459ccbff94a2d58700e91e9673dabd3bdc4c439ed831382e5d230e733ee6e61e7c86cdfe53dd6d3a486011a03ab006c4497faa12267f596512271c4cd5d85f8f31b11689d2e91d43c5d0846b5b1967679d61ee89fdba8354ece4b70ba8d3d0b2966f04b8113acebda399fe8b3cc7326a3a527238196a5cbe273f8f9b31374d402646cd1e244d0ab7b9d2ced666f5ac6fe4f0e196c89f92d2271f9f20a3baa80a6159f90e82f50eec5731016d0882102fee07fa9f74127666546841c7d893539365bd96d8c692fa2731c1fe8127087f1abcfc845ed3d9d0c77f7440a338ba50f4650c8d2f711b77a0d8a7d0d3c8ff4e599e22f436fb8368e00fb9b290c1944f1fe2b543eb52e816d678e1e9bcd0061106b291f94bfe1d71e190569a3b30c67793342a00d2e4fdb634c73aafa4683363cc0c7de65512962fd814debf485a111db657f94d7ee3884ccb17cc41e010b3ab983e54e72cbe4c88263a8d39a9cd5b77237d5883431b64bc9c8215b986109a56e21bfc1fc1a8d50ff0ecc45a86591898d05d810421552f995092d5398e879b9025a7f7ba70901cef103fae89513a1abd78f7e8a251b76c5e8b7ca0c3ac89de2ae199b87085c9869cd9e5acf306578bf843baa82a379368cfbee95f3a7bc35d79d1d9f7c58c432d31fefc4f599f55fd81322ed4810b06cf56d273c07ce20a51f5bc1b8af122804618e32712fda23c52e749e247634a0f2fdd857359a1d1c9dfa25ed6dc094fd2b6a6f4ebb1b1bc29baf9f664f235236cc4fd6ddae38b4812f09e22eb42777b30e2fb45d52ff5296a1b40cb8322599d0aa292db1fc0fda4a42caa2ba1946acf95f5229c749320453162991f951fa658743c6600c6f63a50cd6510cb99c3b6395b1d5a94b4c2934e1fd3796d0f6194e8515fd0e012bee87201cf453aaece08fd32dcf511ea594b37d82d32ffa6f12f31d7f2686a4dbccc8b7c", .None}, + {.Mul, "b3fff3f26275c8df287cf1ffbe9e26c2222672adc2632a4ed1ae4dd279a82bc5f09887bf305f552b074790b09591a2a97af1230bd441e6c3e14573ca3f4c417438cfdead73533e89dcd3d6191908a69299c7ae13ca4d23a2275add58fe16d9cf4659e81cefde1a2f6e3f21f8097e7be8e3a3a9a34663b1d6c2545e5ab58df9ccfb4739dd11fcaa97cb67b646ea728b4d01ccc45ffe087728e1fe93464c425db7ad89093dab023d87c34bfdf2ec60db71aa0f4c9f961f877297a83f8b8bbd54dd7a6c3ecd3fe9c838acd4178eb21e7d0d34bf406750162815450b5953e29d31413f52abfe445a96d6ad1ecf1bcd2aa9138b218ad002483c8e755cbd9f09a16c3f76b9ea5f4effcebe4cf995c2dece2c67e1cb0bdc06bbac4e9b3b54d0b4b6b403843dbbe49ca8823ca27dcddc3397665ed73914d003ab94a90c1cd5888ba62516bc3464f400fe2ec8571fa647f611d6df8c3d468ec4d1eeaa704d0f8a7150b8203d6d72868982b0db53ccd80b824bba180bbf79bce5a8096a6452598e1af3d4b39d2aecc2d14fe0ba7be98dce06477ea219a336e338e4c4fffeb89ebff081e6852ae12da62142eb27f5da86a0415ddd291db15b1affb9a0c591edaef0c27ee721acdc9996c8d18119b7573df53a45f4bfdcf6b17b5d2d0b847c179b1b3069c447371977777157c25f4eb5678786f037fa57854fe6f4d615c47455329812dd1532", "ec077e97caa29e26fb695c7dd2e2dea38cc0837a920547a661e63e5b9e91b453198d192596a38eda842e4fcbd2541dd2d67e84d27e0bd36b65b39b01ae24f22af39eda27726770b009aa934cb977681366e3a228805d9902c29ade517adc82793958dbaebab28d49be9d6344ef2ce5639d116e1f881f074eed4da93afacc7622735ff62306d5b9e7397a48ea769e768a91d80969b20e15b9922da8254ca9727573059099fafc8c334357db154786d28d7a9c0903ec6622f4c87791ed18aa0d1b3366724f6ec08c9a56fd31e11a6de5c5c8df64a31457528fdf2652537caddab49499bf7f432b3432259ed91b31c3aa6e91f975a8ea793ed94a6fb1b55120d7123439f3376afbd8b078d6c1b355f11f56f5e8da6a12b0a2c774bfc85b9790efb6fecb8965cbb5bff5d054649829bc6cbf4440837d1cc64cb675d04d82140c1499777354665286e649e36d3870a0d14e028667a33e668f5077ebc692015839964edd5650e2803babaea9cf4c15750deae771074ce3ad5fccd1f028656ab5ac09dc23e4ac40c03f723ec72db334ce65b21ae974c6e2ea8d601acff9119959b756f7360d9393ea2ebfa6f49ed20b8308e5fc4ea1b7e8fdbae8cf903ef2809e777ec63bf2812725f47a450897030c94ba4f0aa067266f57e54507580a83128e4f5f46b4f3cdc32e7e0dbd98c635bfa80143405bf04a5b9e7afb4c4e3c8966092c4b5e", "a5f539e5d2e9c47d462bb30b6e06f3771a76c1af938e9f725530f59f3f55e3c67d91b05d5eab78eac62c607f247036eedcee1ac6b587da557dc57510593abdbacbc65b1235cd26e5c6be8def699f60594deac07525204129d4f37f00a58f594c316687f1400e8dcd2560f2d3d716be03bf0d0cbdbda060c1293db487b9e9357296fdf3c4a35804d7df57c131364d056217a9207cda158b0e691d81eabbd1b4535f380621a708aa484d36dbb45726ac72f35d7bf82241bee1eab788b591aabe900fd08abe5062112077d2e7efbcae1860f622499535033b0cfe8998b62e4510f4de0b597d82ab94c1d6a0c1e769de3fa74d13d5e5de8e1c0c2f7b5e401646a912098c156365e237b28ec530ca219323e3fc7d6841f7bf35132c6df38c298f07a4181a071be18d964fee6babc3a951f7a5c15424a93e7f21878faf9ec433409d1a3ff392454a1c3abd4ed311948b08acffc02f6f28a2f9f53428ac89bdc9dec2e19877b931a8ca267580d79eefc481585895b196d5ad54db352e3329ea67964b5fecf3bdb59a7fb835af6da141b518bdd84844501cae5e1955e63221395c8f85d520e298a8d377e6ecad09deb82a6be95df150cbf969030d08ba6688a028ff7a598e87bf047a0d2e733d55159d195996174c55597b3ee2ddbf9ae16d9559426fa177c5fe9a37c8786679ae53edcad983a92111d5d1c9e9c38c3d03d32319fee8ec8fcacce0921b052cc43e3541c447ee1be3b1a7a1bef4493b4a38732acf6a96af4e35dad7ea8b8d6e6d622e0d9d4a8701912a29830fa501e1e36a4b69abbd2f08bdab4ec42eb88a1eb5726358503c14e201155203ace605480715a365aff4cd79dae4c0995282cfde7c7f8d908b19970471ae96d93fb31bd200d4bdec8b8cea743562d9a56bf25e7163a8e1c63a52becf913656eb2295cbdefd98774e272b80cc1abea402c01ac63c1abfe44639e743521b52547032be39f81c235826ab09a61fc8780a38f3771d757aea5652b0e8c998f37d2c09f89b54f1f0a5be7bd9072824f74a3c7a46fd2b67073b72b7c4d2438a9995ee6d569165d2eeee2c7a8be42053ace317b65b235694212bd942e7e9533e1b82b21fea6ce912537ac11645f3af1ea79082727ddf964348577ba78eab8b38e0a21b98bdfb0de2498461f4299a488a8879e70ea2fe8c7c7b912506dd3d6c6e6ab1abe91e18f976218edd3fb39857fdd0edec502e9f89d63b4fd21263e540c0f137d9acabad60fd597b42e860d041771cf2adc9f2938a077833f28e6ca2b041910c00075fe344065cf65f7806aabd47aa59800cd835b808cff171aeb93cf21d6e6ccb8ce9235460412d97cf33dc2ddc28f9a9504cccdfcc6a1bb19331a291c464f6d9cd5761d24013174c389ed7804e796417d82f8826b017866327cfd560296bb430ddbb7f2d71c00e590818fb6e5c", .None}, + {.Mul, "-9facc8d4cfd1c2108e3d71bf46120b3455071bde8ffff63fd443b332979234247a6d0f377dd37e78c1a4e3ed48acc6c221ed01572e5b2e593159cdc003ed74a5ec0dc2703e11a4396645880cc1287a93ba97d821e3c20a22e01705f91b0cf4283f34c04d8cdf3d67ab2472a3917c86289e5bce473735631416c2ed99c9acb846be0b8a2118e165f92f095cc7b70678ebdee6376e2a943113494df3a7fa7370eefc7bfb9b3b1feb9204e7398ce849c27840633de60b0c92acbbe430e8c900b3386371123619dc280d7cded50cc6aab8c28ad85ee4d3c34cede58103904e361e5162441dcefbe2a195720d508cb0d7a13986edd6e68c7638f441b2685426bf4488563be4f7c53508c99e253aa2139924e39d34bb3f4b06121716847c2ff47b552dcdeb1387748fac7cee33a115fcf78d5c50be24a925ee847261bd5b289baf82a72360874dd2fcf482fc941d868fd80bbfbcc1f6d76700f19a333a4c62b957cf056fa66fbe949874f02bdeb1427222083acb33974fbae6a90b21f48515bb38430df2949f197da4ae18d3a5cbfb4797fad36f58bd956e4451a98e80e7b1fd8d8d5751763eb4388d9bcef6c56017961e030bfa85990798ee0aa72d22e8cbc5e86aa5b3699feb53f006c7df9c9f56f2030d0eb07a9a0ab055618b3343de4f620d00961a08f19c0e7365a48c0b288e37f0e4b7e8dd7240ae7ccaee4fe4967823c1fbaf", "439ebca511bdf433ebd050574584542df34be4e23e0ba70c10f44ec09515bd7bbc728e246561cb6aef1933f49af538746e7fcaa3466b376c7028c9805a1c977d57999b0861d6a471b1a9447db6cbdd5c9225ebd1571b96125f0a445b1bb8e3b3ebe575ddd9a10e2b13ae702c625f3ae7cf824ee70394d7d69d9481541c498b553297b24ad1899c2195e5f11fefce9c7b893f734c29d36dc7b5d52b37eeacae64c478e77c19b7bb9999e8e7fb406d1977ad49743f34c61d2a80917e88c690adb11b185db6b38ee78772fe1b0687c4bc1278af6e298dd5d40d1a41fe9ce1f540ca8730db68fac0c3d3016bb284b91254c74fbc4a6324907f7c812681af5113c3f99583099b614c2fb1365f84da9eaa84d3ca9407cfb72670080f89fbda28493b9d71786c2e882ba9097b8c60ca82ce72a6c91d5b13033df99592e89cf165ab4c8f0df620a4761539f021832a40a234366e499b251c72c118da14d25d50abf03490d713a787ba4f1a069ecc78ace6bb9e8f377b4e6224aa0a4f02f6ccf2fb72cba582131ec004e5234848d1cad9c2e0120fb78e0cd662a8c7ae0339556301dcfe6dbd5f6769cf6e91ec5e63b0b8c6516f8167feba24a9138e3b9798128acc15ca8178638f6af5c644b666bd971ec1969ee4fb7f9453986db9d65ecd3f4908d6c834628d6b4036a29178c39806adb63663714281129091791dac64a2d62c64331589", "-2a2d3add7ea6d73f90fedae5b9788d29eca7294da5f3f0d6c4810b74d5388bd132fb2ce483a1cca2c5a8c7c7b804373c85b127cc9cd2ded7e16e751b7a8a80acb6942a109fc2d49f426448bcf559eee49b538fb9e3297670633995796a66385fc9bafc5d853b49dc181a3f8c37c22ac61fccc1bfaf118ecc1f655c4f26240ba36e8cc94a9b743af7628cd428a63229b5da27315dfc24508b07a6288405364bb0c69a1a3b42999beab97463cef56a3574fe4a3512e6861c444de535ce30cecee06ad930fc864819ebcc6379a3a839891481b833c260fce090d4f6a2ce24babce09d63e643e0266d5914cc72e19ceceaaa2eae078660ab7ef6ef9c9ff34ec0fb9e9b39d43e484a0d0eb47dd9d12bc44d687d3aac0a8f47fc8642281387bcf1a5531d362fea49fb7ae909d0dcfb13433d8e4aea7a415af636cc64aca74c2e632aca398ce5634ae8041005e8ad888ce4c6e8f49c678dd138a5cb18c6d24e633c9f3a2b744d3fdbb4d4a2db191adc24e2cb832e77e70ae18d8356d0556fb4785b1fe8ea30cfc0222c0c0e8756cf8ad880c4fae6f97809d247b10c9963bfd8077ee5957500212aa8dddcb896711d022d5568a86e08274bc2d0a317d337ce00ec68810156a46a74f084ab913992a960db6d973d51eafcfeb600e60b4918f08a68f2077fefd66c1a767c4901a9a28e4ef156f475478120809bfb1e708da9ddfe1a82db87c495879e8646dc2e4aeeb833bef695b4eac8be538a9a18e51688ee531cbb4128c552e0ac54c328f50f4444d86b19de77ddd57ffd42a820113f668f9dfe49bc481c760a70b315c2bcbdcac09e4d729fe59efaa079883f7cb1b6eddbed7fba49f81711b1e44e43f87d557c696a9d24f66461f81849d0d30a11d416d6589d273c990c66828954822c6c750e4c9c4093b06ae9dd0d8eac3454feea82044236364de7e397ddacbf6c1dd8b26727cf358368ee1542b22cc5d92788cf360c2473da319f66820e7e21e82befc938eb1aecda4c5cd08950902675c88ee11eab13aa5e86b2d6995b8f6da193b2cd4793abb0747940d5aac4f39ef3e49fd5525f6b24c050c78087192b7d94efba5d8a1abcd271f6eed8904991296894b91b3c75acc5dacb36fba67ab254e434b68b9c1a4d4a221a869bc711be288095ef67c682c9fa861d6d40aae9f4470041f32ca486cfd2f79513199346f829ee475879931970d84f102f7411197e91436a03f68528fc7e71859e25251bfeb044e7a7e9604bfd99f67d1a5966a8a32d31e7bb88f4f268b793c4abdcf42ca90f07b73d05e3295c2b440582324d8d07c4918d40c2102faf366e0e41b2b42cbdb4521dadbbf37a9d2bc5d342ca31ccf5441c632f9ea8e808b9c0a8bff195170a84a0965d8818cdc6806d95eaf05ac2dad26f1b021f7361d53073b6e610b041af2dbcf997580cd3438c520ba7", .None}, + {.Mul, "4aa4bb17efe73a4c8d530233b0a5394f82a9a720ff50a4b14f0e6cc66f0384dd739c00a6a545a56472d6bb488a2066dfe38eaaccf3e3a2cd92aabe9334d342ef239cefd4a313c1e46288b68906d5f940def3b661bfc2836600b85023bf6456d01fd4fa16c58f547a678141a3ea8ec5529b45e39c9b0921db68f84f7a2f5b344f0fef3ecb05311fe5c124b911e6760d3007f6a7c7ee0a6408a77cc94d226467ef500182a1ae7028d6877d36b5cfccf8310f8c647541e38782a647899ea8459939f0a39bbd410c07b16f89b1dc7a113547b3a47f8dd86d9ed4bb12f0ceead23bd5433dd54c88bab77613eed5ed76987ad455556a589b0d154367c761e21616c842ba81927c05fc81b1bac743a0946bf7cfd0aa547d5a72024520ff077a83ea3727d99d53ca731d4343b38c6687a457338dc240ffd389725fc6050fbf679e501259b23d02cf4a8dbebd7b782e4f4b222b19ddbe3f15aeb629adfeebdc9223c7e27e384c8d3a1236c15e233d4dc2b39b6f0fef56fa7755e579abfde607dbc21a80a7617871bc6bfb087ce9a9304dba632e5614be628bcc3fde0b97ce036bfd0fe98a3add1ad3ee9040783d657b8332f5929eebe5aa33dbf82102c8a86e4dbe679caf842c28caae74aa6d50d796c4a98d0dcd1831204447ed889fab89cdd104c9cea43380538d3a7d2365ff9d1a66dffbfeaacd70de3aa0ea0d208f7f51b0413da1e9", "71b036f84afdf9f01c5e6137893de884496d0a8d8486cfbb4f55cfbdf0280cf013593e5e3225701460af9882963e5db7375dc343c29cef85d6ef1a55fbb4eac0d0b86510619a4f63dd5289e9fda60bb42aa0e5d05cf015340d2af1237ca46be652ec965a9f227e68f6b154e4ab7a4ece684ca4481759cf809e007657345a1cf410343fce9356ea789f485e62c0e189dc0e75b1ef145c497f600f99c78b789c058ad32c76804a1191b0a72770f1c10606126a7d5e47b7ac6437ad8840db0d80e15c0a6fa4e2a5100c30288c7f86536b4c32fad36f0b6cabdddf8062819358a86c9a692134286d6af0f5e4169d8ad22dbc717048258cd2776439e825cafd374a27e2c4413ed3e250870bdd36afcbe16baae4118a4c032970a7c846c94a2e2a47e6f8fcde3b2353715c65f81532f13e6b35bb95e2393df77d3fb7183a5d6a4b0d1c0b27cbbe6de4d0cc79804f245e47407f069e45e22736bbb185396f0d09d2a7da979285d8cd13d98ee3b99d4e9c9469863d967cd2dc47ffbb0e833f3ed5ee7888367c267ea02624ca0d46167ae8d29a64d2727c9deb3c560b0281bb8fc8b179c1d5e46349f4ca8e8759b11cf47e33f1fbe59d9616172b526753d69fee66157656ae5854b450558de3ce8fd540011a55ec96d1d5e86978110132d69cb0130c828e4c487e252c0beb5bbee97046b7a089d6a08b4e591918524ad15d7fae091d79bb", "212617dd5643f7411bff93763bb40a9f01ec0675562910f18b872a1d371d3470b56ffb996c65c09c071a6569a8b8884ebc11c9570e691c7c5ba0153c89c15c5a5f268d0512a45ca2864cd4fe9be6274c3784a2f1995c3ba477bf2350b9c96b24cb8e658d38c9e3d59a873903511c36b7edbe8d3bd45eaa1b00ce03de536ee8454a7a6df4a5ec3054bd7f35565520c0991dda1cf4bf6a34c75f751a81241617913d66209fb4e492aafc2d68357bec40e7eda2f2139f252aba2ff41ea74669c0b3607b3142ddba636de28f705ecde936d892fefdd215caf9fc0f85d13a857d732fd356e1c4915537caa2b354e2844982f6a55df7e579ec9031e99764fe1d6934fbd7b3bf2f56ad4601b92e7c4f1b69c1acba0286b69fc4daf9c1081758f7b0bff5556aa59952a745a825d3ea6399238cc09079d55793c8f6a1bff225edf2f2a2d101ea8013cab729e985024ee63c550cc4cb03ea7e0b8a991b81c96d2e403b6b413e2f121070b63a7b5fc65127fe52fb1645cf5e27df5716ed80449a9507bfde95f62a327237f175bb39c45f9a8e817b9673601d4b20f3540ac84c949350eb97aba01c0d2bb9d1ca262900075bd72f26ddce3a3d3dc9b88d098affcd7c0008d8005891825333c35d5323caf24d9e12aac7a0c47ae9e44f9426eaac5e0a7cd07d0701f54870a9a7a9991c5dc470e3850a88314745b194525dee303da42f1264c0f6655bae8c0fc37bff91e8110ae58c86918aeaeb9099338076c29ac15c833b348ddb8d805a13766c344231ca22668d8080f2af1f8a9f81742a6a184aa2a1c83531064b95002a019a6fd5016b9f06487b75af24f702c2377fbe67ff3c96b16d205331aa7d196ecf08aba27c1c810d55911696436b9da24dc56084da0fd8f016ef169178698b2c4b2b1f6bf7d4009a1466952ed852afbf683a70a2d50c6725e4ae133db82bd0178c948c5e0d28f7d5b63f7c8c71c48593aa638bab465f7fdad51e3f0bca20e0f909b1ad27c458efd99446da215ac2a256624e9b76ba19d5633aea3185b076633f0f4206e406f513a1b5b6777ec740fb12e85fa736e0f69d8f738152690ada386f40790444c19b0cc6fd88af5d723cb4b776d5b2bc75e53669139f33636c7223672b9f4f4985ead2b2ba194ee8abc628a1154c273dbef5823b06f64388db1bf7ad13acef271d24109d3511849c8d603e5aa1f06d252b100b01ce6f534a6f39848f2115e9d7335ecca05b3112fcb81e9668e80ff82c7ae25594bed98f8efa3cee82dd2a11a18677aeecd3a72510dc78519db0d2e173b2b7abcfdf6fe26ac2990a4153f84154ebbdb9c2d9295660b5a74c054efe85ede27101baba1632d124a5d97818d52c8fd8a8ad14fc58059a77e6608cb33675fbe3c3dafe61e828b15bb8cbfb301e82dc9b561f28fedcc39d7e228f99c81ffe68bb2ca051f16633", .None}, + {.Mul, "-abb763a2093c671b76513c82d12a1834aea001e9f1e8471dbbfb94ef62b3aae5f5ce6ef29636738f35fe4d5463da6d469eebfbeaf7091997490e10e8e3ac5692327a32906d64f44bf3d6d9120d651d492c9d621204e13e9eebbaae86bf35174771666ad67d4ca85ed7efe58c1aeb730d75a6c852e1d4294745628bdd4e47f6419beefc70b4cf311cc9dfe799099a1194623d9a570c38188bb0aeeffba0bd12665cbdfa4e980f44bad65050b8ce496be80ce029fa52b5acba300a0cbfc8ff26489dfeb0c06eed7e6a98ffe2c6c8b9e49b893ea8e454d8e6832e4490a4427b790d36ce5bd00be197462ca2e81f350d1f6d078bf18cd4e170e22cd7dd8761bce9e35e45e48747f2c758158d6193103fcf351b89df0f0135343e548b574fbeac83209be37fed48cb0f38bed97b1c3d7d55316cd2dbfc79476502c6a9a11838ab50b5b63f9b2c69446ce48e457220cb828b556adcc27817c623b9d8ed0befc4cdef22eac32ab0abe10463f1363706ad2835ec3c1ad41c244fb30f787d880465f2bc0be314168999bd00af826e61cae8472163eb74315ebe65dedebabd5dfd7d853d854d26ceaab90f563b2f46d19c0860c54f2d3af8ebf9e36617842fd3d97403ef47f6a2cf4e91d74b69e94a9f521d3df847e38df885fc75b6679a623f5e10eb679aedc0b8f2325389a77a43953322e4780f202133f11ed0a75eb1b54e5cb3df8a7e", "c114ae05472ee350343585a57aee0b98e06a494d25131d0503936b9c2daf06eedac18e0d3a2513e6ccded80672a32c1efb280dbdb40d690aa68c65bf510b883d6825206427c87acd107bc6ffb3c4a5585d10f9dbaf1b01ce5ff532037fcbcdc0d9eb309866b96d086a89e8b54894ea491724411c84d7372c426c254144c111bba3f61f7b530d930879615f8917d0ad0869bff523334a1185aeb23aa8ed64b52e5ca4d41fd61c0508499462e288dd2ca9597f6dc123636933407fd6b3738c6e7597f15e310152d16627db808a0d9c05b4929dd80de396ded678460b019775a5e5fe8c949d78497719a1caeb145f97cf72b8926464ea79a7959c0811c88599f155633ffa8ccae111755610947333336fdeb2d7aa056869ee99bdf1675886f1b635870afe03947bf6b4cf4763ae0cec18ae8621b6fdb70fa5e590e9e09669da3441224c47c49226d462b7a8853698cb5b73825152f7291621a30a334d07c795bb5492a31e0d9de2d5f9e57a60dad0b5a66a62f7937e1fd61fe3f74875768db45698916815f317aa817e30bd3280388bf274d6c56a43e30ec9dadfe8fb3fb38bce9582bc10699ecc02359480bb10093ce342919efd6ace4f704d906bb864bbd7d4f0935423d3a5f3a8dc9f1f21cef02b1b31056d2df01210d678324df7710d35e6a39654ced3ce3c9f7b9990186a18a3ad1aac28e7d6be1f05e20890d4d6627b8c20", "-8183212b21aba6f43ff58c0c48852f92ff8fb0c000c933c8aa0f3eb8025fe0eb6273b74ac930d1e273c17f1af9b7505fa749853f45980b58ab015ba31e5c30ed9aefeffc9d904abfcd5c37798d8d5a77a4afe49e14c30b97f81f0d49cf7b36c95b2927dc522267d810f8d9d65db603525b6384bd572c26fae8b323d243bf27615b390d0d20f5da792b8453e25734994add2696a488b0ec2afac5b0675b31c17e911b35cf3edcdc334c47b98569067071b1263484d7001bdfcf34c05cd330a580506626f06161b89f4110fd1938c9dd81121503944b4458e52334b731eb879b9716d556e179ec24e5c44bb7e11b5d87e059e380236d8bff6d8dddbbb632b476f0fe1a80a2e153c6c5e61071088193bf48defb65096eecde197128b14ead300950a9fd905940badcfcc9908c461c2468c305d9c9df98c68795798b673e91082d67774582c3b95c3bf47784e043abd16ac99e4ee4ecf32fc6ae85a177a8e5b1834e87c6d41b841748f3c96e5b73f3c2904fc3da5f83f7be4733d807aaf971318e10349114f3ebac66419bb26596216eecf6817182755b96c269b990e4c1734133e7eb2e327d528cdf7b2598386fd313d8aa65c1e2ac725e60a3464b25465ab5320ba3e1c5bf30572e78bf0dcd4e799e530822b49e9aa15d78626d118ecb2a6c6709f563b19a8e2a6670b9e32aada519dd5bf2f3f0dcb4c037458df3c93df1c0e205d720c102337b0f2c094c68256f8c3cb547848b17bab2672383699ea48f96d5d366a3f3bfed2d570d40afec51bcd3d4516dbbf0efa6dce7472ec7caa0f5ea7a301eb1c5f941ecfd74422f9f75d34ed20b46ba5c63b8a938bcea7ce1c979516aa75771187a653b2889fff1adf1733aa8e6da9ac181fd8e1496f8bc7c92c7ba4b7808f441bf6679af4e43441574669596f944917b4e6bf86ed82464c8c35886076500f852e8fa9a53da55ec78ad4b0d082c5ebf3b6f4a52e6680ed50dbef38ba4fe8fe6f7a723015616066f9c967229d458a99250743bc2eb557d2d7805e62628011f1bfc99ab3a41ebf240795968892a579ad112decac645ce8856e1e74968551a8de499a7195edc331f38e96587bc05d31da9f281eae16da28c3f8d84871d40740a8c32d8a4106f4203b57e8cd781047ff264789f4dd1f611e1a618b99813424f0865725435c02933fe6b9efc4c77f2b1cabc64fdd1cadde575c716a26ac05ce3da9daa8f3243e030fd21eab5eaf171ac82da2f6e3cc7f112f58f9aad587d373a9bf4a4791133c6b83186c3963532bef28c51067f930579837e72f540d98a7ccfe3d9d4a30967a6f40850880376d31eb6edf881eac8bdb1f5a6d6334653931fae20d5d0a559f71398fd8e9bd2ea4d83f41a1b367db84dc016946279a6f8d1d5a4ed63ed5ea4e3eb0fbf9a2ea8b91abbbc2ce2239bbeaaa8e2d3589ab4823837c0", .None}, + {.Mul, "2847ad33d7a8b43a65bc0808d6e108c8a8e7d089ae9c6a52c5d9c494d6f2b438879f566361e4fb563413d724511ca5298439d6bbf5d03d555cd98be178a2ec1f63e97908532c2044d150636e5927eac2675823e5c3161288eef649de5c3b3a74fcb6d51b0e07772ac8cec0175b7e37b957dc3a2624bf59cb80920cb130dc5379850d8e766724fdd5f6ee517e031b76566f8870baa12b105d1853e644998cc2bf5d8bd1de7bc70836b129c80ac203b167b108b01395ff1a184c36e1aa0aa2f3631bbed6e389a6827311bcb1f51e1d1fc76e5cde4d3e7a1b0d6b7371dc57a4056f6697b84a7fbd3e317d3e637836f2f97d2685c0ca53e90a6760e339c271b101e649e18dfca643bde7825cf6b3565b4b19a464480524b018d6299993425b3e12a31b80b9675bd57f500c84c2c8bb18edec86c2bfd902f770afe56c862a8b7e150967c14dbe60a06a9f4174c8dfca462a548193671884165367be4e2a2353ee75339756d100a2cfb7374e1812be6ccf686e095c862f5d7bd5e99d8129699d0b2a06087e7268ef03dd82d0b3be4c1edd1b2aecd7e884a75e2ceb5e284c18aed6522ea397e7cae6816843a1ef84bde38cb1372c86e9e84c20f6cdb4c234995ba34a1f22ea3e2a12ed5c1117971070a20577d95885e37d05fd1d152ee59369c29ca6eb8933472d1d2ab70ef4d79b28e9115ae299975a669cf6f7574559e62e44e6a6a0", "94516cbcb5af3fac3d6475b2b5d7c41d0e10978f7c8f26cdd59feb860b9e6519e2a8b643fca57bb81cbdc63ead0986d8b09f1728b56993d90ed086c1b0ec0f55c96668fcd642955f932c2760dd11149e20ff499a1fe007632b45eb1006639590576c48f43044bfe6632026e72aad7baa90f261df0d183a4379a9ada2c6e2343cfc8552442d9161c8aac763bc6405022147cb413566ab9c2e2c632d2f1407d513c0c45831df686f425adf9258d7fa73da651aac785d6ca85c6e066357d317b0fd6861346f706cf5054f1d48f7e1fcd577dd0c394c9f2c1182d5314debb61b0f39f5d1ae8c79c7dbb077e55208e3ba459fec1802c4e66b75ee17e03139debbd0e45c50709c5f5a60ff23fc8a98368a568e2dd96f88c1a50297d01d18e9fa2602f07e4e89c063e9c89dc4acc41d71bd96ab7001c697777f7801920ea5dbcba728fb3bbdf5c2ccebbca6f0a5a0ca56e2bbf9ab417a8afb5a4286f09e8c00ff58df296f9c2aa5a9448bebd4b2415ec040eaa600e021ae2eb2822042de6f339e5a855e67d83f8c630b098092993a1cf557c57c6e3fda4a2a7c44346fbc8ba513648973faa2c6f40a77eef27c86b7f13a3d06ba272b1de497d29b1e8d00d9c42225761fe94b846206e52dc16792afc14ec3b25b4a65d43b3e891b12e7d9154e4df89bfdb4ca639ebbf324edb45d167407d84fa30b740cf4f816faaacd64fdf339ca7c45", "17563febb460161a20939a637b4bdbe1d410ecbfb9a5861572bfdca0fcc82fb8872e12a07fc6876b3e7c9dd48fc2dfbb3976dc0eb5195ea9becd97927034b587c40e3d440798a4c671eae5a6283958d7570898187283048838ac900f6a644e2a66608a07498c8894e9bf22ca8ccc4ae6455c75a8282b4c9aed278478774a7920c18dcd30dc686a657750fcfbdd6145ecea6daecc95f40ec63adbbdbebb9665b9fc92b651199f222ce450a409271d5c7e4189505d28859ea22226b4b282b43e9cc3fb489b65fe51b7d0b068cccb3bb980a4bbce4a7bfd6ad0aba8b9c0a9a8ee8554307d59ec607dfb1260bb3cf43db04cc6afab3406adabaa5cddb720b95a86966dbeb41d800be6d4ac05515272ffc851cec877568c2a2e5264c0b9aa5ff01124737f80b946c2bb6e57e4edcc56d15de4ea1dd7b799b61601e3d37ed531cb2c357f9750810309b663aded82f58c08769bb82f047d571253a7a9c624fccf8698645e3e6c9acdcb14fb9286a967a9a0987475bad0736cc6f2a05b11f6105d9e15d4ce4477fc55ad06e395e68e48b06b1196314b16d5e10d8b10643500583d197889fd056e4eec3d89b7f8b33cbfb1d6aaa9d42442c41be9ed4475b838d8d6d7daec7ae1b2cbeb3a890b09136b4bcea8f5c45b342bc2397435836aeb3fcc93a20ce8707279c13173e15de46cb9fdb1c4108d30aff76e3742c438451650e0249505f36921e7a95d04fcbd9f8bdff4b7a406e1893f2935d88ecaf5cf703bf92374197265d6df4316c4d3e2bb61309835c42c32c26de7ddf9663ead2d3f8271010aa1c845e3f88a85dbc286c6ae07abfe2d6e9eaa497ddb54e8b85c6ce3f5015dc6b1848370ee9ed9b9c260d43d3b789c8a32f9f659e3b2f32d9d6197c9d95c469da0996dc32d6967a977397014af964e19fe07cebceea0cb91f07c6d2ebe53dbc4d8d07abdbb1913b4707fbd7bbcfb79fe8a3b8144bdf476e47e0da4f5993611ee8f2d62d2f1f97f92830e525577611609ee866f22cd886334f83584408bfed40981045925b2d586be3d7b456742ee7e82b213cac0421df63411e12efcbe94515bd48d5adf238609599f8000148f7069b3a5fb96e83d50b8946b4bd8528d21b7baf00fe3022da47ede62b9589d5cd5b79c0b9b844f7bc726104ca3ceb1979093b643ad91be0e4d217df511648211718f1d617785fda6c6f08885fd5117567798e2a7d25a80cff8903a4db47f0b551daf53e7e07e0c091b96f0379207b2082dad7a240e9ae0c7d6c87ac4c266406d5a4550a99ecfcb9c6d3108a3ec37f282e7c51096f2ffb32384fead34accd5a9b4a753dbb663203f38938074b964e3eb2fcf0b5066612b7ae74362cb5c3c9fc1446e1cd02705f8732deaa3eb4a8efd8a832fc1884b5607d2d31e41d3ed9bf9373f51365225cc459bd337d606917baaf76d165206920", .None}, + {.Mul, "ec00a75c9225b3c506a9465a102cf4e4dda091c33df7ebd1fd34bc35c80f67778f16d828cc34d769890fc30efd78c75c14c4dd9b5ec4951c0c1660d4cc6bc9534435de5c2dc16e92c596abf9f6203267ce687b1c65e5e75992c60a122b77accabbe6c51fd7b509fe62dc9e46c36bbe2d0d3bff7e0f99c950adf47710865761d34749c6839a8d4e3d04c936db9372122d3f657177e6514e1421a456eb5dd780d8e3bafdcb29ab323a26337d3cea9131511343fb5acc10698aeca572e202ca0774ba3efb49308680a8eba434ee832411d4783e8be9453de17ae8567befbce8d44e8bcf62c9f645b9a0d21ac030296f200e51193c6e95038ef5d0399ce62441dd4386855511abd8065e20db63ea0edf9cf2b2c380dd48488cecccaa9dcff3360e0092d89782e06a550f789b849cce297b892f25916205e9fac3a67303731d04753dc4b531467b688f133c8de6af5cd09403b067841af5e483d94d132ba4a75adf54b062fdb389f0eda4c7de1ba7e065c26cd2880fcd8978dbe0134ff961e41480b4df9d5a4e0367cf89864ee1b009aafb7bf3b5863f80d97431be86c114bfe61a7dcc9f9a738ca62fac45e281170509eb3c1245b99f7f1866b0a70eefe73d2b77ab2b130a1f8b844e8f07eee0793d41bfed348bb3d5ad72e73d2947a969993630ede2e5076ee8dade397db2efc2a537a4b67d9c98bfb72ae8804fe668f958fe37b", "7d8746773aa711c41b49ba9d66da034eca388d47f49d68ac306e749b81220f2699edfc8419f1131b39c100660888d4f03c303b1152ba962befdb874a8a9956d7e03dfdc7ef1c92555cb5c242858ebfc69c111bcee7c39e613543da6512505df9692efaa559a4db544e6d93ccbeb675600bcf8ca58c9df1f033985c64f7c81213ca5224bfcc5d31a8f62d2a85cafca03d3c68ebe6aab3fc798595a4370c107c02c2c56e8175c31789f9b0bce53f9158081739fb030a0da3cab4c739c5c65e24aae243312310617a43bb94b155c9ca2355dc2883bb586acb38dc0462f59d1ce61b2ec94b2c77c58d1a246f17cecc5469898c50ef97f99990c6d79b8763169281cd599072866d48d0a2057b8ccce1bda2799f37cc0b39c59eea1fd2c23edd11d3b069ca4fbbc8a42d3ba6336b2890350ec0bcb365c412e0410288fd4da40e0bc019997144d9f72ffe79c8c790773f189d29924ed2ed50d73499fad40f90399ce3480cede2b2d31f59ded679663a758e82d4997530f930ad394c18b6dab2941173ca97c18b46673461805c12e8342d8718ae70d9805ff19ca4e0a8098df09da9384b1d389972e4dc0e3661875b10ecddba8f48138881b16179eb0b487dc55a7b415d5265de73c4717ea6bef9b41b10d36465bf9c7f9700eaeb459cbc40a4d0968de7d05e9f4e6efdb589976a45e7d4d9f30ef13d078bc62b44b5cc722e0ee6a7b219", "73b907068d50c1603b1acecdd5c9052f74b9a222a5b085e77bc53a64e35e28ed39673e7d93124c3b4303a8724dbbc82e903cf8ead6628c13e2203b4e72dddf8acd0c9e5acc735a1218510e823bde84f5ba161643c1af205501481789a7868e0351c73a047e700ede81a3f6f4d32169fae66690970d3da53b28d2a40f68424d0c8145c3f6fc047624910956d664d034578f6ce1c9b51557864414673c200121e543775129d9fe2b4511ca31676dce9b58ec06ce8d16ce279a07926ca351d2a4fc2cd73437c1f0e2c4afa06478adf5c4a7701a05396f8c19605974db1e9ca9527ac2bec78ea6a71139a2c702d7b81d31b282d88749694b15bd428219ec43378bdb1d189b72e5e58bc741fde22824c424556bf1e8cc7ea55f6b185033af144e3ec4741957ea21f82d3cd52c5da701602a28eaaa183aea03937832a907193d5192c16a68d2cac2d520f8d506c23624ebf0b5357c4c9b5180adf7d26a77fb5457462e2c7909eeb56d4e97a326745f66aec44833696548b9a3db1c0ebabb3e8b9daf85967703413ea0d8da45abf6a53828cea7d56fb321b5153cbba10855f74cef27dd8daee6d4d337f941b37ecc7b051be20237ad4afb7647a7d450d700e19ddf23fb543fbe8bca429947bd1735d1d3513446b71eafd41a607f263b55b032464ca73560c545104401328fac118cda32743815a737bfd758c9339e778659fdbcfe0229c95539ca4da6504d15cbcac07502c91d9be0ed25e27da220ef88adf52c5ffc264ea488bba3cbf3b3d7f65b2715ee0937e73c0774617ba50230aeb6051129b4aaf799245f2d2e3e57d68692e3f5c472db3901f8b6dfc1215ed5fe482445c29ed90091bf73a05634b54d831178dcc447b3825bd8b8915df9b7cbee34f2b8c7c8d7f034b0727a90676d4bb21517b337ce9296d82197d5560d94ab85bd25b9b72b50b15c4c560c3ae8d403d339993dd00a312f3f951ec5de02aa0fb335aa66c157963d20604d51ee2e09e97cb559aedd9fc131a376e4fc9a4a5bac0d154643eb7fc40f40fc906b57b37b3830c7b66a0e3dab8e7d30e1585af7e1aa6f65de02397125db01e85dda3e964f987b6d75b7ac847d1ba3d49f1583fc9ac04c556c414c0742f2fa423aa38bbe50fd31e0b021b8ca954de36a027826ef73c5492ce6fd2ca9205e67d507b3206c0d74bcca5fe56bc01d68eba581b04756121d286f6e3724c93185391aea51b618e4a12f55545c23a626bf45734d2bdc26b82cbd2b5f9d5c2308ad8a0868e74ed45a6aa16c19dfdb71289cf38ffe114da6cf0f99179fd3af82cf82ca1c15c9245356a9050af70257ae03536d8819470bd5906ec27cad40df2eb4c48b10507c82430cfc47a7b5879b3c8dc2e13559f33d7393bf80c540e960fceecb24a7941104d1f130c9b184cac5b79cf60f49dbd0d9ee5a1b63bfb8e75bd03", .None}, + {.Mul, "-fd2522e0467e1cd90c7f224dcfe7ad4fff0bc87c7f4b12c1ae280565ebe3cd9a81de346c5654dfee8c542100058b8926769aca7bc79431f19162eee175faaef4ca7e63b60d29f4dd81edc4cd95394446c5fab49367d9713e39ba1b86c73f95cb4913ed3e1374a6a0007b84823ad17860f189558eadd59513ef893045ae6d7f1bf2c49eeaa5b26ab6799046617e6e4816607fdb544a9de847b4d6accb523a3c56fbdb6c71793e9fcdce8c3eadee31aba23b25358c865683318e8783bd610d5b02dde0959d920d19663235fff1341f70412f41c2cdce064ccc0c76f8aaccd094c059923fe991d645780ed8c997374674a19ef60d12264bd0006fda49bf93b185da948fe97e2f67da18ec45c409d41df18f5f4ca9b8fee4d7916411c8c1cb69f2dabf1caf7aadf77f66f4990702520c678e7cf8e51a8fc9dd5c1de0fe5a382dde2750eabcc9837f2d974fcab22e3093023b109d8ef37868c4f9195774ff88d439ec3ff2304c9bb57b795f7531993b460e5d87205fd3550f9086bae15534aa242b7547663ecdeb5b6a2fdd4915390ff21fc3495f5300adef9f27d7a32c903749be7fc991521c1995f430d77de135595c50854bff54b8365f61bcc19872ecbdca5a740b5c0ec3903a4e28c8eba3a83e61ce5508dfc682706afdec25d0be73bcefbaeb868d2056a9ed63a00e14a98f7b4b225f2638618ba2ad74f1801440e202e0bce4", "a96027fb5066a61b1d92d527933003e62900076f9db6667037bb26dcab43155d6073bc8cab51fe13c4b9949e43795ab502461ac7be95207e3b7a8645234c95d19cb395d62997f1a9e4f424360d505adcfaa57dd958cbe19a7677362ead523175a28bf0cf828399ba6bd350059a49e10916b44e5bc57238819161bbdc24cc280d52e7bed461ad14b77c4ec53f324ea6f942fb5fd784ae0f35e78d76958e96f9be1dded06702ead6f093c7fd7fcdb9071d72e6e94464de3ac18114c862ceb12a2c5d23084393aafe2b76d53380027ae02b62ef05e52b40ab7888d418da1e86c6214ca822ceaa11a17cd1e1d6ad83b60ee8424fef63ba48be7abe37b5d4993ce3c0d5c3b6b976e52256e9caf2e52eb2a39bdd133289d1dccecdd8e3e6a91ae58c59d128c9039791db4b87f8adf5e82c674a1a6d2dd88be7b508643662488b1107f4c2972d8f9038a759af66fcea64a39ff5b9c64f4d739e58c7d2a714abfc1409afde73578cb956dc06c8affefb4d1e7a53ba1f19689c62e70a1b7c012ad44f307b97785453bd388fd01110ef21ad3f762457a29daa90bb19f6db1fe6dfb9149ebf4115911ea1101d90264734627866630be50d96ab5fca5bcb7c790db8d75595d74e99968ce68801f3720abf34484b50d8a05a0963516dbcf4bf8ceaeb429ba190824e0953301123abb0c4a381f26cef5c353ea242c27ea9d095f44803dbcfd091", "-a77c997c4dde28eb4ed9f891b6d0197bbdcfeee0a8dc785282b41a20bfc0a53a1b8e79f9fec473f837535ef4a756d5d8f1f42eb4f38b3145bde80da774280b75494e078d4a28ac75aadb3a9eceda2a2b5cf3b8380cfdad398e40a8e4d1c45d5595d8f0c1772d20493a4adf6afd71ac0fd36f37e98a9eab439dae63119572f875181905d4aa60c2cf2f442d8edfd3d87e325e61fe13109e3e2390ccc653f2f9deb56ab4b92635f7e02905aead2a759e9174997808f780e5d54359047a938e55cc63a44a449dc70c4d57f4196bfbe9e1aa4f48d3aab73ba3b4636051c399769f2c1211b0943cb926855ae515e73743a7b3383983338228430d58da89929348bfce46ea2fc302e254efdf8390ba61bdc5e758362423633861c74651a4af990be148704a2b5772006bf7583ef8ef9be9f45d045b30bac4720f752f85f82722ba4fbdd42336b1c692c27f48ee3a33d78e3b9bd4e26da1dd9f8fa184a59d8b0db769a892ac85d52293ed84c3e7c14217cb661b72445d3d4c4e012bb30fdc3e48f682990ebf8a83bd844f0e8681c657729c126b6091195871332be45843e77da5b2f52ecd4b9ea4c7e66dc9a0bc01054444fa23f93609dc6aa998038eb49540c39205cb3e0c2edd1d96c8b9632fd2ded1193377c6be38b326333db3b5f558ab47c93fe5c0a6ea96d4efd23f2faccb28a251314354a74d9a8f15ae0911525884c76bd81141a94c39d7a78af7d5660ed62273b3f6953f0fb69e56d024f1d500968887d76f5202d8d6f60ac30b6c939e4ed7d3e53a4f4b1decfbd3fe0df1a0d75ba3c97a0aba8518c907e4f536c90058281db8a7e44625b6117f21a64ab7bd46ee54355fff64859c0d1a758363c1f36736a4e44b20a5752c2313aadee55e720901285ea33a61ef6f93b1fa69cb30d0109cd224977e99c587b74906b18b66b82f93a28d0bfe817eea95509511d9b87a3e53df14b3a98d8fd0be3dab559dff1a7d2ceb96d2b51a9fbc44930ab3f8522cd3ba3496ad9ce11fb5b208c8872a44effc6b0e15af9936c4349e533043dc2256561b55fcaaa0c52bb54996e452b000468d6739a1a2208a268850965fbb1af5e46fb83a05c01e5114fb51bcd45d651f81bcb0d263a2e5d854b2d67a29395b22c87a982c32006d003e63693037718d3bd7add189345de421ba4467f1d6a0e0c871e0e4f27b4892f6fae48bd7a7395a21ddb38580402ac8bc8cd0e095794652ce4ccfe4067c3a3810fd815459e0619a798846a45b5f1e0b4f25bfcab0c212fd7373f45b261288585224b1d2b5b6de273930af568efef109ab2ab7acf4b789ecca2bfa7ca4717e7088f78837993422ef374785b8a6a92b75a7eb0b2e7b59b4982f8cb2202a7207f4d8faa2e8b4f75d6e52968638966b4c4456d17ae108b38b65556278a448f4e33c0d50698e44333595ca794e5603203d24", .None}, + {.Mul, "620ad14745d1ebb5b900d8d7cb50eec9116c4f40ae65ad206c9446ede161948c7821725dd3db46fe2d259c93b5836e53cb42abd769ee528ae1c1783e10af89ffc1d4398cc68c536296155e5d54c6a16496c56a54706c0e15b2a9592536b2008f0a168792275bd5590b3ff7572794391de59fb5289b2e92985ab4a15768900f5c8ed7f454656bbeea922a30fdcd6d5fc54183b3c4cf4ec39d4c08532c73a7d54cf6a08bd497e2daa1dc6636d807b036aba5547b5e955a8d5e9794e6d4f0a2aeef85dec46e86f65d265d3983582285671757bfb626ac2b7c52cf866945c0a0fcb11c667836b1b32f9c9b112925f70af4f60ced6542de57a65662ddeb81f1104c6f3e3ea0efe3ca822d3e3d9a95db2fb647487fca660d0611050e47a0f6a3e47abc587fb59f08b869b67e7286855f3d494a2c57104f4593eecc265e89349ce8a144da4e3d53eb5aec4bb2f9df4e2ca2a6c5b140397dd440d08ab88aa593f2c6c59a215328bfa2cf6df1cce248a0a68dc4e34328ce68475ed64cb8ed298c3e881d58ac779c141be2263d10104ad62f55172bd560e7812ff5c992b6952ffe37e743385ee53cfe019b7be01b069105e5b6b45e7ce1fcf87feda3eb1b6ecaf7571b9642a01a618ba5c369d43f2463effc26a19dace31e395b5f7b4a003823ce3ba42bda24fd90a4edb090723a3729ad77edb7afab712fb99d3a6e70ca1119e5bf104ed7", "9203c71375833717ffb90ff193322eec944f16726f7d2c333345716e1581ecee1ae719867ab2aac361653be6103f1edc6a6156fa0ba8dd9f1d0b1fc8e9761e15fe9df2334b33dc96dff9fbbfc298dbe032dea635d3ff7ba4a9c8e2f66ad7c96f04134de05184f9c3b82240109d4eb5f1fab2a239f90d1eb4399ecd5a241695046e21eb6da7e3cd21111e6a06303050a8df8d410e4ea4f4c504aa9939a24939966b229384ca7820683d37a3df92de0ffad16ee3807cd5df96594c5278e375ad68003bf209bbecfb1a9d3b018b1d630be2233aa8378c318dff66f06035bd0d92c4997ec128463d675ceef8dbee48f0de164c1f43c66e4331f09ee5101a535b68e9b3734840f9ef8464a094739e26293430a1ebce92a042b96c93deef67389f312373d5c6001a338f77a2e81dec43183bc614215fe9e2aafe2ad857db1ac5a511ab934b437546c53039999bb74e6fbf9010fcc0c5b779b94a9efb91f8227ac77ed5d7cf37ddfc3f4bb7819435d7277dd11243e1245fec9cbffcb1e39c50c3d530241100107beb9dc6d53f444d46a8a274d28d0689ee49f057f0979a9f76e4b1618729943597566695939f192a5f7b651b16eaa46c202dcd7d843900b0844a3976f1070748100115a2b89a68343fee6c0aed1070e70f0ac3a82fdf1efd233ba1ae1bd76ad4a41d067526e4fb11b977f224d51404344a8ae0dc51c2c420ddd31ea423", "37eb9db8f624abbbf1b2d6e96d05d5bc975a6898ecb80256e5137fbdceae15ce7b2359f1f29d928109f322d782c17e7e10fde87621df33dd563bf1e50f6e91e632171214561b52eecf559df52b6c864b989a14fd66160b551b930ff7c54b6c0aa9ef3a29281ad968d09226c3a5e190ee23f6251f7cd02260db574daea5fdbd7284c1e41980b32b7a57418aab4531e4cd143e85403fc6d0654908856c2282fff5069e8c52c2f385fff9c4ef83f0b4721fdcaddc554fe29d9835dcb9cc91d773c5c36a6da62abe48f27fd509b0ba4ff69f0fcb9ceac67b691273c3ce120f6bc15a161ffa18e953207df2b89e258b77dc81abc8c066d1639b4947297255294d06dc588b4019dbfcf5924943442d1cc9a9b15623c8ba8ee5449de71274701221e184f7fe8db094057b7bcc9fe58f6ced3f4652b297d8b4861741670894c5f354988b9d9c85b2e671faf35cfb7cd2d0a121855f7e90bfffbb389d26fda144bb07f8ec572191184b5d3a9281a93874b8cdf3897e408b8b72e7113029fae17336c2f149541866772fcd7bf64e24f455d4fbd28a4f826f9dbf8a30a3a442f372672846f0e7fb6157c41a65dfaf939438e289f078afa362b001b1a3b11bb4a714746d0718501b9b1848b17ff3435a46d9635c224eac26ea479930d48cc5b76d888a6b10f2e9e4725773fde8bc3c87bd3187af644611901eac2ed8a8e42f4d892014407044774890299437d560f6b436e4a27caace1f50984487a32dd9ec32d460db6a818f005bf089abc3b8b54084f34428440e1c19dcb429f40e8adbcc6e890f27b65a6cd7e38a13cd55717866a9a67fbf0d94860e157f279d048ad83b03936503de6424ef81423e3e7e8d01ff8e2b0fb19fdd5d8471f48925dc689f2549c872678fa9f75a80ee32a2a91d6eeb7dbaadd0c48e954c3432240d2d2ba7c676e1e1af91d77042740fb172540b1c4adef221d2e4ed8b6b21ece1263ab2db8eedee5645b6cdb5b97e83a16263d44ed7abc2969cc2f166bd456e6cffbf654e7cb03973a73b64fb7d45f0805dcfe7aa286b07e950468725b12f903584baa5751eaeb5b580aac1a05409e9d701f908b5e3ba6090a7146d7500f97080b6da6de1e4a566c1da3b6819b37130023a6e6703d375ee0b8d033a981ae4c0a457b5a64977aa052f847999fc76d7fb06e0bfb3d70fdb7af087542243f7286efad07cdfd3411b6569549602445401a9e815fad09a4f3ef84a672eb2d5c6d26dbc309d3c00b49733245412eb2cf26ff88171fb739dbb0d56aeb333bbcba193ef78f45a205979573beaf805ab0baf72249eb3706c62debf5eb698635a597d654a10759b045d1f2e5ac443b4518da46a98a334108b1205e2a1a07b819085ec24318e233658f6f6a078fddb588fd1e932c9b1b50efbc91991b19db8a33c8d4de63120b23b8eb23fdf7d4f03ee8365", .None}, + {.Mul, "2fa133766f3eeac19efa5204f1bdd930dbcf89abe69deb19d9ce21e96f2972d220dc944b1dd56f400b5189ca4433457ff0a817f5d33be1189bfb647107fe5d936090e7eb1b400160362b06b76566d8f98996d679c304d8a72d027437edaca3c26d243265a6d2bda9c7244bf6c4f1ef0d3043048c235ac8d6888752ce1cd9f69931b2938fc93fb0474db6bf6b920cf98a14c16ecac4925d50d29b53d98dd7a20d03de953446312c79b12a7dc0d54c5c831384a2ec91aa7cea80452e3e6d52d7e1cfdb15b8d190b65311bfc81f06f34a85a7ce2ba059e9e7d7525ea67b384c2a11d94ad91c96bc40b94d0fc02bb8569accd5804fc51ef9993210a91c43b78bcef3274f392a55d97438b98d5a073756386e813d95a15f6cfadd9c68f7db80defbbb02947511617ee0c189677cab88969a9fdc4ec7aa42dd853b8d3acf0e950125aebb1130ee35e67e188e9e7a1975b42d099d4608745cea72f798a1be777c05358da2c05c05a269dd0c0413975c7071280323f407aeca0342bfa905c2fb1ecd04f7e972a580b5019de16d3d521d0e26d5f714b7b4f0f1ff5c9b43bbb3ce3472669b8f322745923504663e8e17421275d978e4337f80edecf2dc67cc87f78f130b79e2f424944af70b11eaaf093310694c79ba8d8cf4c89cf853c5ac72d0d70ab1ac312261c9fdaed6ec87fb74d76b524c0a5d7a7242aa43793e9dcdc183698aad29", "6c1f53f6facdf04eb2851cd34552e20bfc83a3e65682f776407bb3d76d41ea114a0b0d48bd057f65ed637031e425cf7f384ee749cc223c931bb4c8084b6c894e26db83a83e63a6901294971ea2ccdb774c2a6a87e42d629679d81469d3309abef041c6f621a58ca00c8fce1ec0b20cbaedc14a64612893f714fa132f14368833f6f94f18a604f3299783b0b718e9b03a5b39f3c2d06af3162e5291dc4aa8c76f3f99d27b08fc857b1628699e240ce816316361423782400df97998b67e609b14ac45e840d4af95adc5a0151b96a61e6229d12f5b64e0458e9c0c42075058bb5598d60cc02623c216036aba72d82bf129407cc96ed583362a4ac9eba647a5858f4333aed52a00784c2e6e475c4c60ecf80e394ddb40312dca39cbf53dd53981a6ac8e8cc480f99d28c1bcb723a0d572272ca40609c949e4f703d53a4d1293ab55dad9fa5631a28658281e4e55db25857ff65af26890955323966f0a22a60ad79abc6c1ea4896f542af589a3ad88254a7ee230d774e52139f302c5eda4b3d73faa0c9b4f9ecbf3400dcb3dbba8b7600e7f7144d1b33ee57cc39dc75529a3be87d88065f679322a0c5e527e2250d22e5bc13814dbd232c2597fcd76227ff31068e51a6eb8d11752e0a176a726ff4a2e0499d6659c6e00e40e8548e846b910f849d6107fe3e6259e878b94ab2283e67d83de18228fb2e4c5409ff730db2845c6288", "141dd5da69869a960c244e6ceb8b5f977e9f2c1d8efc6cb0458edfb79bfce16632105c011b08ace29116fb58f74b47bc3e77793029df7073e145c6230426e875e33d9ae46a2e289dd1f5f0dc4f16a82a1b67f5f37ee85599b90c27b18114aaafd9c45e7a3a694fea2ea869e3352283d23ca4b28d179ad53fb2607cf606d6a1081ae5d465c9a8847dc6d6673554b66707b81aa21472318c8b057b7cec1e3b58c69cc8915ed81c4acb2954600bbc3ffaa12703a772a8a4cd69ce1767a4f9e3b68439cf53848e26215b600a51ae3217add6259e1409512350aa1aa436afaccee2733621d3c3b1a643916fde3f77ed9a3d29491f6879fc83624ae503011c11bfb55fbc8b3ddfb5c9a238a15ff84fcdb06ee2476de039210051f7ef23e04a41e6751b9f8efa471181c15c30c3583ec080f3acf1516cf1da73ac467ec1047ddb395237919b613263dcb204dde3ec25953f85ad7ed0365a26d13852e0540555eb88971fc7d6d18998469913dadb2e9d0f64a26d146d0e597d3541e754ac5545004f04c896938c3c421daffc12f48755a62d89f35ced9e4b7a2c1e0e804fbd45f919ebe6bdad59025ef1953d5fb837290ee1a499a6ee077feb6de98a7eba2922dd52a69e08e6d30384a80cf8d03749970ad26a3f026250da7e5a4ea73b3d754941334635a8cc4fc199f869385ce6b125fdebcb9a435e33ed031bbc2d714fbf13bad5910f474b27aa0acf34c805aea6b6ebc3c1893aaf31ae853eca1667befab4b55b6cee03afdbadaf39fefaaf08ad9da719a06f857f7c55b2510a1092dc7beb2fd8bb30b6f361f98f5802f5aac14c43fb5a42bdc24b41b209f38282ea3d5633c198ac32ec0be91feec223a724d443ed18b85d9766e6547fac5ec0d32b602d05c3c7ab6a4248184ddd33c412c436498c62a8538353d2448ff1f1363add1b45f1d298c4d4e5ac5d3fbef3b9f63ae8889c94191a1ac36fb4741f59dd19222eaee75466f0354f9f2cf0dcaa5f2c03f6acc05c1f518660b59f000959281a475f93f7883af208b9cd5e7546786f41abdd48afde4d229d0c87e66d7776e7c01cb4006332d24033958f90f0913e6696af05f042a7f45101dbbfc836cf837df7b51e57392b6cee568db3a4bdbd73898339b9acfabee433d3275c03d5fc6f98b2e0c5439fb5b879082cd6adf6fc9a4b736c47b6cc8309ec6b815ee372e1e843d444b4be7751ca930a4bc3c57cdf4f2717c37790af04010091902f02ac7d88d9a324655debb2a02125a2fac68ca4001cb4522d58f3ef777ef5687f10b5d58ee991d3bdaf67aaf311f4acfd8660e43e34b79e53696d19c8afed39581095858f678b947a18ea2daea85f8a4c68663488caacc29bb8d6bc035d2207c8f266b8ac298030f49a9165d5e7970bd9d9a03c85c0fca5ab33ae773d9d8dc7ae1d5210c7f59f4ab06d886b1afc8", .None}, + {.Mul, "-c0029f843ebd9c4f1efff57c782c4b58eedc228f66e1689e77648859d57b603a23ca391d481069d67d840247bd7afdbcab4630672111db04b84f8bf971c5a1311611270dd90972973f3c557dc054b95e3f8cd8dc72d87146b63f034422b0fe9b80c7b16b7df2f36fa4859bcd259a5b03fbcdfc41976732297cbf103a64b29d693450e7f83fab505a9089d33c5d4c7c6aaa6a7c6702d0b34831b047b1149f7743e2f27c0cf08ad9142ce61ebe66ad33366a2475f82c9d52e425926272c96b85976cbce7708eb84405b33b36aed7cf53c99a85b8f8fccda857e7ede59e8d47d0d3c5910b24ec5cb058ed7fe3879cbbf84d0ec69b7b5de376106102697f358304ed61055c036106c96402f42592311bccd763839a69f811a7ca6c1be4c0cfdc201e0cdff5a9ea87804292f61a9511de1bfe7bee037c581f6def93d8f1e54e42ae982a8f7fd8f168996a3d54bec43207c418f6c8fdeca1fa474193cb8e869f52d794d2719447bd5db5369a4d256fb2a3ecdbe47a17c12ac27f3107b74899683ee281d60e87e9898ce957428fdce1ff434c10c813539631efa4472680237ebd6cbf2190cdef71471ea353fd4a77820f2c83648dd19869801a2acdd29536f60ad58a1d8044e7e81d7bd219beb98b6b6341637e3faddd5f8852a2df85927e8b6a623d0aa970bd13f0dd80ba65e38b31f223247be96cfb7f85cffd79ab983a1e9e66a26", "8c2e413d0a6bcd29866124ef7df2cd2832a58ee10f1aa1ee08c7b424f07ced0b9d2931d82d7eb7faa82b4356dfa361ae3d758074e984a06a9c252875119aac0708f894a89ccf7af68875f820a83ca3a325f496a9458cce9c5d7cd9cd6acf339f285be66da19ed08d7e423b7b33f001986b249714f518df88d613ac49274d87d9b86405f600729d1033311397e247fb818757ad4c3206522aa808267f3d8c4a7597076dcb65b8c445bbd67f3767de609da4d6c0455ba519c736c26407449fdd5f38ed2a9c1ef2ad74392c41f0fde15eb7caa56fd2ef7e988496b16c03ca6fad4f4003afa39d5a892f742541b64169c061b33db4f581f31a19fd6e5b51d9ded757513a8402ee79fd9f6eebf033ae6da88b9493705e98b016de4c1a0a8eba29b6050dd35d66da2cb8d0dec39cb8d74db59f28eb97b3103bc62b1d8495b21b911bd284da83a19695143be621902c2214db42d8ad38a32194961425f047ea4628ce8cfce6f59f5fed3e1a3dfc096a5de6da987d8aeac7619de3311166e5253b57d9b6a8078b22574648233c2f6082be203a62e6db602de72367a7f5c800aad2ff20480b7cea3a71c23e2530e623aef207c24914b86edd5cfbafa4ce7658d484b6afcf3c4d4b7409bf357252d46bb2eb786374d67d3b68c613068c5f5ab8966099517e86a8b5f837bf4513e5a638736894042cc323314be87117bbf92863f998947914", "-692420a36f04833388b631f086853298f392f91b2a12c0109c5fac6f09b0b0bfaee55c2d006d4e11c5b5c4c2c72c5e658177d1f4e8f260f3750fd8e43e7af2030fede98c797816343c0268b11a28474631c9ca2dd148075f04112c7d50380a390332093dc5e6373e38727516bdb5c1c2c426aac2581b9a6eea63b1f4f264c9f7c7b004b0576e7bcd49f032bee2a18cef38b7edd10881bb39101cb0f4ba27e8def16c7e0ab0912667a312592fab5e487c65b1a9ec698a640b849e8d51edfba7b7403a9a441392ef31818c1012f2e89bf32c8f355988fa101bb8a8c037dbde3bb5d336808f8a9f1d0fc1a0fb8e68466cba1f74e2245028be2cdd1b3ae73c2da35935147a0482ab4ae86693a3e78e7efc4957c943c74d2b188b03b1838b13f4814c4c08804aa5fe72f81f0452529962f4a2187c508c9c915ae92d63a545ac2f1f347e4e4daf344a6a1ed63915b680fc98dca991db9d1d359b3b041d10b4915378e70db436b7584161005fd3f6aeaa3d1d9dcdd8e957f43f4d14a5986867f53d200b0d90a8631a027e7a3278cfaed445ad6328d2f09ce72bc1306090ac3802a7a59283761b7f3bc319c7f0681d52a938949ef32123d9973b5e9d1aaf4668ec15ac4450956c68b048628c3ba29d5b923a4089bf16eb6ab56ecd85bb93796d5f371f642ad3960dd96ed88b79638bd26c7dd7a5f7db21b33ecbc82d72c398b7addd6bd1aee070ad08cd42dcea488c310d94a8e0613d9bd45d7a2eb7e6b508b8fe3f11d9d2592899cc710fe27919058fc13015c0e0334c546b3f73b26641b829995decdb12d55c8d15a52d28446133a5809e53909b60b97f16b694a4e4ff43e5f3903f7c26052fbc57e4f6ebc60af02c2a5ee79b1c39cc6c074b36cd3479727dcedfa28c346128b5f7a76d694b9bc30477a4ebf0d265edfc292cfafd6cf539aeb28cac2f71ad8a407fa080ecf0c8fa0e3c9f392891a79539af4bc0dbe99fab8fcec1313b435e6f6f486318668c34cb837a5d53c156be6e6722e3582f2a4a0ceccb007dcd4b01298c86758587faa70bf0fdccf053f552ec9e56bd8c36a2b49df45169ce763b53d77d35116ea4f3218664d95b53d49eb9ec5cd16380afdf8e7b315acad7c380277b55d018889e69fc405955cf53a0262493e9ddaf24458bbaffcf57f8399b38b5d5d3e081f0b9b219be393c1da9c505e1949185ae53915cd2cab76fce34432413bfc3c88cafbfd10b18e65890dddbfd7d3e4359a662a5505b438a44ee885c406dc13e093c8ac5f9910f6812f0c6f903edca4d0e8c280067f34ec4fcea11c5d4911142e63081bf2e84e12e602e655665896acfe6671214c1b80f1ba81af26ad73883afecf05ee61c71654c37b1c7bc1ad586388fd7593656e72ebdfcb1f714027db25a19e80da6e1759533acb923d5328f5526c79c1542a4bc9661c2440f8", .None}, + {.Mul, "-3e8ab6668a52321d0e0c618589642d7452adae656e4889251ff52084524ddf92f0d49d596eb8ba22374f5ddf54f65ced45d27ce13d1cd947f4ece80fbeaa9211eb27504f7d3765ffda8628c6f7f2e25cc3d88c14a834207e1feb8bc67d781d145a6b97dad4d3e4c5fa5f56e2a4764b2f7be28b1f668203b3f628d70021014e19975fb8fb24ff2d85fd026e481b16c8a6a89e8ddd266b72aaff267aa74d8a17e198985433de8d82ec2975f626d3038a70b8868b12d926a332c4811640593a7482f89c748a4925622d60bf4942b475e086e6cf21af732b9a0079d6c40d5e455542d48f193f8c4de2a15bffe81f0b89ccf59b56d09b5598a41b4833dadcd7d88ccd54e57a280929cca315b0f9da1f412f4e18cd1babc9aa7e9de0d8c85554ad3f50f8f9c0b769552c2e578df610bde8886c0de64ece637ad34e7a9602f415a3905ff1600a2c1e13f729df25ab8c9dc070e7a0669dc59eaa9ffd8855323a0ee664d38f9e8ed0b03eba67927406f6312e2a7256b32853c50474328951c98c67ec2fbcce85e9c62b5bf3dd2e6d76cb2848b6f230027a9c4ab9575595d243d72613c7361ccd5e58ba682d1d66d5dce4b68344ec96e585c020e8b4aa760e13b97f6638fbd33dcd55dbb661c99b7fb8f63de270439417792fa73988c0a7ba65409a15a4edd35e8809bfaf47abb218757db84be96c2847c063a609c05189c761052a503466", "477a82bf96ed4bdf82b8bee73984b6a53707f1d83efd155f0305a51991250b5af03230e704fd94f089b33e30ae341a52439e6eb678ac500f7f4bbcb754c5ad08de327fd26ae480c92741ca8a89e90c3974116ab63c3578f7cd93e6214cacb26e210b238fbc239ded7ae4cb45375e02d40a419f6b02e8e2130a69566c9c9ea58858d213a04afec281f1127d68513474ed9b2f2d9ca7525cd68baba89c1bac23878408acef7f546da116730c2683e930c194c216eb9d7007babb07ae1e1a742d372d4d2fa3217fba831b2fefa084c45bd3e8d2ec48bb23b85d2f581a9a6b46138716cde65e21e714434912a46386d6144bc6ea392e9f2d4347ecf6245fcc824fd34cf72285bbdcbae84230083b653e49a1399dc920f86c037e64897f9fd6370f5001c06db1bd8c691d47e2b060b0860eaba953e4f20f324f43fb580c2a0adc17fb52aadc505f8cf1d7fa56a94c172da71d8cb85bbc3f080fd27fb4beb1cedc2f259ba656049917205685d7fdab874789bcf214264d61e36580d1df3b5fdbb0b3186b0052f2c0206c5869bfbad80b2f6e1f6eb1e9c80659c7796ca99da49c58aac63d421248c1e1f8d7b24ca0e2a8a32e27070fb2a775aad59227ce53a34a99e060091cb1f6dcfe1b0ff75e222c83eeebe15994732bce8ae1c21c80567832970752e27fd15c044cea5da310cdbb1b7ab208bc73e62fa1a55d98c9ddbfccf5fabc59", "-117666a29c381fa511b2fe06e1736a3f253f83f57e754367e30fec28f16c336b6cc7689affef06e5a6ac1721a5a2f282a148a647d00831c42f7facfe54f1ec75d1049b4abc1f4ea7d6be0367370337b3d9919de963ed97d70a8c2a10817ad91137183405ef9d928e4d0fc9ef894fa197dc79e901745d6ced7574ff3128ed81ac6ac251aaabb4760539ab85be9a1b28cf0dc289a2a719d255a7cda526a2047016fbf5363651cb937d22a8baa8d66da980b47fa9e3ace64345fb12f2dd4197ac0f96c3ba7df3fc0ffd7aff407ce00b09568672cce5206e506dbcba621f9f5c8963f0ba68e7b0eefb5d3614aaeb7f35d297aa4a672c91088ad93e7bf54008c7780df4ed0c836ae5e291212d99fb72f2fc08e110b53986115adaf69fb14fbd83976ee102786e48963e747de20fd529c0a6627b665b1b7f15a21103e579fa0e5325c3160fee29fd2369ef0f4d1a7a6c6bdb2ba285aa28686274f599b4a3839084c9d48186367dc83b7da396d831135b755c11a034a0a93b64bbe80af6b886ad76f5d23e948d9dd9283f35cb3cc10c3c8231bbd662ae01930d1712bf5d212249641796df692b6562c686dab6ba914f2164a5ac4515c8ca9987e2c760afd4c167698d09ed737297975aab20ea92d5d59c7cc094768bed5a52e3e7971621ac50df4d4418fb9d153a29e15b8f96fc5082278fe13312f61bc775b6afd5f04145c316e940319e2bc3c851157ee3b69e6d90ad0c9bb356d7e459ce3db138406c28e0650dda3e6d045d920dffdfc72768acc2661e3b77260a5f2e72bda034586ce2cc4dec21e9c480b696888c0628524215defb3f420c55ea05330cc3826548b3410a45e496cf4d32ab5e7ef11f4a4e18ef9652f4c1e4247f52c63fb6740a9f78b5e10d62e2d38d256d884fc14e1aa313ec9c32cd8d4d1fc1d587ca36f6baf672fd0fbc31cfed2360df77db57d65cee15f8b52a2eac8683deb64a076968b20864d4907eae83d0c9efddab657288d5dceea7aea195624327be42e7a708c0b677dd5c4ecffe223656d0a08778e2aaa827f910a200c0b6e0c736ade056c962e3c71ab6ec65ccb8393e78d29b9cadef5f076092c2cf6d2f7ec24073fd13065821756c199cda7a8f1c957d955110859106eb1d4d2c22b0a5ac1fd0f6a11b4201092b7e5f203d4481e1126d584294dc36b4fd3296d415428860456727237663ccd81343c70688c26b23d88d3781989abf6202371eb253bf6d76bc908950b829802e5dc79e4a801e45bba1af95f45fca0b8e725d43e27ac7118d4a5c9a57fff04508610de32f059ca8d4cd18f2d393a6c5dcd7a26b4cd5d49a1e97675b016f628c6f801f35987b9f45143e9aa72a409fa9946d4efb11c0b52f6d97fb1338bab6db321c763fff5437dc56516002549f076a291aa545f138aa28badd7693094574efb6e32a759f65f91f76", .None}, + {.Mul, "d73e5a1cdc92e780308dd3c3be7f79dd7428e4758b3734ee299f3cf8bc576cb0cf052eac4dfa8dca8b864a01a9ade533d1034bf547a1bd87996c0c940ce96b07440e21bc96972ebe06cfbbeea9ff4f4fa6cc3b3330dff78b44a6334685995129096ca59485e90b6d24b9532b626a1251d56e0a1ac348016b33eea86ae6dcb4efbff358e803ac7f12c83ca96f7e77490ed4e92305a9bd4edd978460f1ded0de434978065cd306e63625cdc43bf11ba24c444cd021d2a31d86f01cdceac176227e74f73578e2355eaa9b67cd6f7eba3b0bf64df96f4871900e9f91d46a2cea2a1d72bd92577a2955f87b78d8d288e2e79fe2cbdc6fe9aed525ca886e9331f22da3d03434396595d864bbe253237e8f16e38842ae0d67351777290b3baf0c88b001e6aecb9711985910bb20beb9cd49548a147170e8801ddb41fafb174d77788d9e903e0fcc410fe39072187038e4363a8a0301124e113bdc6b2b9ef05d300d69d4e46826e6d18a82afd55ab4692723855f1a069b8c0c5cc25efbefe510a72b0281c469c07f5ad704095482073bf77d7450d1b8a69c89348c210575d7bebd4a454213246af08e1958e448833636923282dcc69bbd4502a6632c22b0de2d3db36e2b5e57e9c21d2a454c246d43fff89490cc34b318cb9e34c743b064ce8e0fcb5dac08d1d015a420e304535cc07f2464b1abbbd2ace910e54fc0b59cd0acc282ccff", "614c39cf5410f863a46370ffe011779a85e869c99b6c052046109cc12bbb47a99f3e7bbd02984ad7eb4b243a104bda78c7aba2ca47bcf870fde8f432422e795f8ea76cfaa5c0d897e834657cc8415d1dc7f89cc036959761a3ad851dd53364dc9f50220ed6b70be37ff90c421ff6413ceada9bf4cf4ed89e843fd77688a1be207d6309545905f6afa106995e5e3e510cef5fa6c94ffbde4f311f62a36b64cdef8729a6585cb7538155411f19b9561ead45094bfc5f12f4f842892680249cf6eef5a9ba71c83d888b0dc4473394ae2a21df321330f3c97cb6d9f5d27a83a09ee01cd6a4913f52f3025fb080e377ab41e6ed0ac6d6cb72e27c79035b59a4840d1f521abfc4640cb623e06c8a8f057585c2e6229e72e3ed1b04ba77c351c46426d8404d9f83252533b7fd00daeec40c8d2d341029765ba904b23630fc130c7036da715c3a75135dc8e1fd878a92133cfcc582783b4feceaf314f49cb823f4943a50f821124a2639a68c7e9ff5b9c230f5b7448aa5db1761d8199afec092cddfd79dcfae5e7dee542f4f41e696615d0ab78fc4ab72e9d2aba73ef1e56c57f1e80a71b81474a390325724ac1927e4d5e11ef3b155dc66580ba0463eb9730aaca826b77e31159a28fb2d55dcaf5a4b65abbe554c587d386123e25f7994e095c9d8f27f46426b692ecb9dc6601da5596dc9d66ab3185a6f30a4de809d1d9be1bac56ae0", "51ceb742e44f2a16a5973ca4c689fe96eae603c0ccdef3f8dfbb64d8c17556ef89553618b00de6767918ef5385b6eed3e2c9cf99a91340ba50999b56c0ef2bb728941f25f8d2c9d8ab455939e4439dbf127dea66276c66d31b9efe59f334e1d9539a6745e67894fd1fbcca80b3164df81d497ae162db79486e01a9edb82ed9917f02c84a30caa8e478e041fcac6923ed2b959720b57a06448e4bbb37a5f6cafc64746dd8354811f63d3f7bdb61f845a9df8c42c9954b901e73dcfbd52b5c3a8e9e08f0fe91a4e36d05d00a78427d9f636121454f5674e0044789be1721014123bdc6bd9812ba38862fcae243933bc374f03f43a6553327e418e29fefe7e6c3f84f658c09164759290a7fa10ff1c87b14538eaf13963c5771c8460d0ac05bad06b20d2fe2d6aaddf57b808b6a59b215ce806a9cff7bf4807b66197eba4494557f9ffe7fc19eca5ec49d59c16e2b43ea6f1f1fa7085c026b776043a4a8851499dcfdeed32fa3e8f3141ff2c1be545a34446d7ee4b4e4f134cd179be1c5caa34b145219a93c5096b1986b75e4d03a440edd32d4032550449f9fb3d8e072391c9e45f29932ecb0043ec852a6be24fb85f70c053a15975f2e415186cd294c4af216c1860d67c353f92ae9d2da89f0216264fc10dfb3398198c2b56ddd0964779be6ce7c2cb52f94c9a64abc771e35bf71e2edbf1f4ed52bac86feee2e9eb1ff35333670ae1f23b831e85898becbab7375311ccd808291a8c3ee4a4f15c726c710250a8b3269d218814510a174c28fd2b8e76563bcfea17f659e0744edf97fab2c3179c5903b7e71019b3b72788cd001cc011fad19ac38577bf1cc2ee4203c7cdf514e125087b9e6eb6bd25b9236f2ee4a2a1172157e3628d492b3dd9d48a73d677724223b2621949c26e4791e01b7eed1eeab59bb4a54750febdc0216362c618fdb784b6f56ba254d1629e6034a03ea80456066903362c1830f746e2aa2b1d9583b7977e2d0398895fd940456c3cf40ebcd3aa12f0835c4963f7ae6456199adbcd649a287576943be95d9ea1739c34216e3b2bc812dbbf3ec3cbc1d73ab6ce1c3fb2273bbf0fd482eedc80b6cc5a5ee29a2c231c44021ff98f87ffefd621842403ea59733ae1a090d5971f643b386085e9d09c25d6426d73b9a7f9830fdfbc50857d80ec653d5409542115963c833b1bf82477460aefb3c53be76aa356a4eecb306f73429819e00ef53ceddf19751dfe0d768baec35cf23b41c22206bb0c2fba7a54f50fc78614cacef1fa073119c747f867445b4b95bbbaad0249c04d9e04d342e2eb6b6c6432d6933ebb2e2e5a92e29ec876e11fa298008c326a370b166d5fe4660a33c98c5ea86f456114efe2498bae44b886cefa53d4713d2c9b9df5f29424565330e1fd584cad501f6761c495e8880a898cec044197b28c1b4da686c618ff520", .None}, + {.Mul, "8a53e3a41d12ac712c413851c5ebc9ee61625c5c60bb3187e0584233a4b8133dbdc6b9ee3751f56c049965bb65f30efa7783dbeba8e8e6f74285abf8135d61e87a5cd667effff88e391c99d560281971083ab7117ce10b155f475cd8e1a6002f6973d866a71889bc753db1aa1f7fb54f1014cb065809a11a9e6e0d34e945f6365ba9ba9c09e987c28e8ccd6b12128a997c672df891d969af7b055e79e3c834772d2d2a0e94477731182aba769f61fc6404ed22e9d7532142d4630a4b06a289eefc7f77171f6e98904bcae96cda80a1d53f51b4d064a56dcbed3acf62034ef5afddb05c13245edffde1bc214574cd8008869a25cc696fb60027a47d03fdcb57a3494f404f3559b90a6c54244720faf074710d0d6e9b286cf9283a1d8bfc904e4405c702341bcb9fe30edcd3c5d13fa87d54ed42beac5f62a1295c13af164de56fb788edbca51ed83b4edee9b43871d323bddc2d45a06d1d7b1ff0df7b05bb197bfde0db17ba572f9db42d91b1f060f164fc62125f08f12e49bd597585e8ac5990f49654980dab6f2c9334ff1516d06d31fc6ebe13581abd081db8dfea15649842214998bb73770f32d37cfec17ca6767a21fab8948176bef04a2fa2e894c716e6ecaf29b927289ff7e3c30496ddfe47f96921f60ffb8bc6bedc3d5b13faf7fc3c69fa50261ec54bb052cfcbe73990bb6cbac2d9bb4ae91e89de3def839d7493bb", "9395549643d8473c3b7ee81dec1d9f54ade8b08fe2b93449930261c12a51d58b1f6732f2041e59490f30478518c79a179f724d973ba0d7ca652efd36d8540359e7fe72f60cd2a6aaa6739ff0eb421d3457eb3a2eeee0e69601d891f62fbf37ac417fc5393c175ce654dfd5a0f4627374d6a889d389de05259512e601794a5f7e2755bf75934b8088c662ebad9ae2f3bdffd2be4842c4bbaa632d87bcb15e45ffa7c48090bb3500241f48141d5bf88888aa735b9e3695649cabc43f0f7a729b1b7307e28c7ce631e0a3e973df5977a7d58d29e34bf003a30f0a429eedd4c0ad57766bd86b360e89a791d439cdf382150053c37f2fbbd1da47f6a27d1699d1b1d1571f2daf4bff6b4c563af5e5bd152e5b094f37ad2e32fdcecafa12173624be94bae48d074a180135deeb60da9f6b0cfc8d38c9b02604867a9edb3b02f387c18beabe2efc51a148ba9220416b29e06547aed6b2836bb7d6b10d0d5ee3f20473295b8538889af464c5baa7cd43b80b8cb9f12d3c447bfdeac8df770f506516d2b6c418aa6697a569e7c3d12501ebde975e4de3b7d40d5db92fbaead0ecad41fe2c9d28437d02593516a5e4a49e929c38c1b61ae1fc90a67e5fe16e626c61dee633cf49a2910c94ba36aad06f95a65ab34d9c7b42ccaa1ab0cc55ced4f074edfd03cc1f98ddade276a7438d11401578ca5118a10585d8febdabde0d815249735cc", "4fbedc3f73b8b27059d493b93c131af03e59c0080085e96967abd10320c7c936ba5518cd9eeba0efd70dc8d0189ad4a0cc3225ded16705afb099ea3ac898bdabd8bb87faea74fea3884859b0e58656790882a8cee83d93e70edff6d45fa1abe5f889e29029f4cb9ffb25d3a4cd008e9fdf97d38e0061018d4883ab1e9b9f88b78d938f5d2a2a5ae6c7158467d0e06368171ee923ec245cbe2b6d68e2fcf1ff769a994bf25ebc49ed8d577db19e1c3b6b0e1c4f9dc4367b543e46c5674c7ff66a8a33820bf1abf5c9e79908392a4b0678191280e858a182ff8f839c095857742b8335609f641272e6992a1a92dd6f6e3f10558f8da7caba853d3917dc9ad5fe53d1ffc6c48aeb004f97201e462901e19203bc6fc2fcb8459aebdbb0dc857d948b733892aee17ba329d96e16af496d2181afa3d1b7d41af851af6260d1e9ba4181d197d8e565e0f67453318963f43be3108dcd6950ab3b316cf326905365de4b6e2592fbb4622ef35f31ee2e77678f203899dc34d8e0e267c383d3db1878908fc59ce1d40008cdabaff5651259a8b537b23cd7f74495ccaefc992ad3a4178bb1461f741bb30594dd9410a4c8852c808b9b6ef16756837d477de487217b1a60d3624882f23485a508aad756bd3b6133766b5597ec278d375cc6ecfc096c1a57bbf932e34d5ca8799ecc2f78660d99aad39cfa83af00b00987c56104ced48e8c34448f16b545979c85c1d9da34672377aada6b1dc123bc2af99e21e1c82f69cca66758d9cbffbc3fe7107f5511f0054cf2af65c682782c567be8d26ddf67d47099997172b04ee350e2f458435fd0d46602d661606eed03fe55c02741c958b6aca8a4da030a98ac4635fa36c613cdbef13e05af96749800f61620aea81de7a579d904fc8558728c6b13197040111ec4ce8e2fb50a5cb7e47ca8ba5ab00f22a1d3cf105beca742ce214a09f89576d92cce533aaf75cd53adf956f2d5636885230e648e08210c5257a5db5f4a30ee964301573aa4cac58ea9ad8bf88b77997b2edcc5f90371b43e8c9c95cfc948ec5609148ae422bc187412b096e830f5a330e23ce7d345cd0813cd4f8e898e31b8afe7545ab48645395cc90b998e9968eba168bcaf4fcbc1a903ead3c64af8a8142c9bd70abc7cb20c6b2b731b1057ef90181c54a208729ec6070a08013094bc76145148ff86a4d444390f7f9e7e76e9c3a77ea4fdc64e60781b9c1d8ed237f20b49e3fc06bb3987b68b596708b1ecd3fd2c787afb87db9be7fa92d75e5dd68658eb1c30a3436bec63e950a46bab4b163ba4ffe561e89a64cc51a19274f5354ca3b2c9f654e73f6b68f6a3065038314ce6fea2dc7b2467e026d76c68c66fa94c89c362f9041605d336ad355f3e856e13c0cc73f391419dd056043fcce41f6f07a876adad63d7465d2172495ad0d4e8d475b0ac87004", .None}, + {.Mul, "9e940259f79d4ef1f999d00f6f767b962985aac85c95df740f5f959a11aefde216bdc978396e8442bc6eaa4d6991ad3f3f2277334cc7b3f26c323740a228771ebc72ada877e78deaba50e97477dec3a70363aec0340ea9749b862e0479312a109a24fb17c956bcc1bac892db07d78cf5a4b712acbe61e133a20947a37a022e33b7ca5b682d16cd154f7ff6d51e2dc529d40a8bfc51f31f45a77e229258a1c5cdca06ebc7fc79f0acd0815dac60269350cd8b2fe9d278d3bb4b4973ff53dc3e2d14e50d9250fc978d607c58013fb2dc190119ecbf5ecbcc88286d25a5bfb4e7651d79c8cf73fadcc99c0439152d374e6b310ef09319ec7508a7cdea7770add498f032cef0a29f30a48df29ef0e4a25bd8e21822c9de9fb81b9c9c04acd5daed58999c0c4f2ae611ec0b787c6f9c176ae10217152b0aaf818285d9b6fa778c2ec9e8c90b5720629aa80aa1c14a0bf925666dadefa4aee8ade0ae2267cf87e704f931c40aeca1b33a64c1b52aa521802bc8638ceedb7f2654dddf403653b1b956212d4c0fde1b6f02b6dba0f24edf96e3705af1b9046e3c177dfd927d62caba15ea06cdf3d314ded037188198d32fbfb64b80a57fa25b11dd82d58991b53cf46a31410ac78f559207b1875db7a9f7bdfb40152ec5a56c73b3add8c00fa55a80a38622724961d7ea46ca698186bff4ebdc4b1f9a3b25e24141968b51672203d6436f", "f9bd42ca9fdae390c387aa3d239bac675727b5304c9d0a59c0f6380a09f80de6d78ac2b68f26343be83629e4bcc0d0178b6f9c17adcb8b4d3376e023b3a8a6f5c5f5989cee04161598a990b8f277a92e3725bfaee91f122884c50c0cbf82354f0edadaa91ca2d915c95a0538e7eaa4d91ff509b3fe4e5a5f8a850af9cd0cf36ee30e68a1deb0314f5c5f61d11e3c8ae83cb2aae28a3fb3dc7cc7fbea85c20ae70731652423e443054c2c00ee506e12b15063d526232c9cc37ee74e56374c8d264311367d849a0f1db2d068b345a81e9cee593f93466756ca9dcd9ccf9ababb9cdc280e7db59ef3b2cdc72a443508afd76bfb9519aec35905fe0bcd0f5a967453a9a4421722726a3c7a21cc579eaa527e55d231d81921152ae6f680db28299d429e53d62d90bc75c39d35336ee25b813efc0957ebdce8c6e3aff9c4f18b2ffced1a6e5fd4153e7d770d3894311a79831dcdcdd089177e499b9599c793302202b64d1f5e778a5678ca7b0eba3cb2bc11728bb7f318377deb780207d3313c567518b9a2b4ca6c5463e4307d64473086af672650e5a472078829686ccc04a5fca9e9b4caac8e963bab176d50bd838353711f1b7e8a810acbd4b4cf0bdcecb6e30b5a778604cd1648541ca70a9ae16e020cbe2481e847a0f3e6ced4a506e264b6a5dca057b74907d306c5cd94ee71e157ce990d3609a470e7ad6ad537d74ae3f094ac", "9ab332eeeaae623760c3ffab71551cedf111215a3fed64b46565770cdf973768ea08c38f5b059d0b8de09fc23a8e64cb7fc9d5554eac3fac5678e33d81a5661a9321793ca7fcf7ccd7d6b65da0d073054194df9616a7694a4c67506822ec52651e1df92cb9663bbbd54e80b6ebeb19d03dd00f4a598e899f280f9dd95cfc7643196dc492ae7ab527125279e851f7f230b7286ab1c9f7b50ffdaf42a77102b5a2506b9f163b65267447b7a43daa3195122b2a83971bb6653e5c29b3fb50d8ea45afd10b791ed93746b3276bf802f39f5e9ff53683bfabbde4c01d6100563c6676ef4d2584907c9fc5c15070025e609e032faeddd0bfbdf8df2128912eaa8f9a78998f08b5d89f72fc901941b3157cffb05f306af5104bd097453dc6d1e71fa30218c17e34101fc433864e7268a1c9c1f3532c6398ec60baffa4359c8119d61660427214b8860fc73ec16c52b1b654e9943732ffa311e0d595aca22f2a0252ce66b767cd16ad3320972571122f88a6708312501ceff5a8f915bdc0aef5ad799c5661ded61fceb8b6ef9cfde870eeedd4607ff750258ea577b144ae3eeac40734e7e585db2063c6ffd1dee395b1ce1eecd955939a855c9e2e5ddfacc9672405cdf371ccb13cd93c600484945333d6541f927b26e192d084ff0fe91bea26274eed5998b231fd7967930d90ccea97189035f12a224aae60c98fadd149507cc6dd57e031247dbd48ffb4c0198ab4a6e7fa7e73a187505da5735b80e0b3a2426a74f3b7b9130a98faffbfd339d9b86ff5db46f68fc57043605c81d2f3bac6a31008e83298a7cb6d1e0c7d1e93249c0fede9487a5bafcb70b0b6f86c93f08859ce7efe7849dc2497e25363239fe64a5027b2483d653ece98ca9fdb68065767d329b942d688fe56dd4a6846dab25ede2f845eccdccd1ce51bfca79af925e66908bb66c91603fc178451cb93907acc7fce66f7fd640f10592e950f28e1082172fae36008fa87e796c5e08ab2c4b85148a11f56ed2094fa93f57fe671ebf3bee98111eb276215ddf2ecdc2084cae82d28e0140a5cf0a54b9076c59023a36591f6748fd0a924de43a125a5ddb6b0fe18f7da1690687e3c9ca13da07b88ad8d2f197555017d009ab1989f9bdddbe9aff193ac8e44fc832d0694bcc77d204d90c457c3aa2b00076fa061c80ab67be24486edb5a32d2ef447e43f257c57ad903cf43bed2ab3729b7f577ad172812d83926cafdd0c0641c6cd68d40d4099592ccf90e883de5451c4f1ca540624841227c9cb40fccec987f15aabd7a21a8db1df9d397480f2474e4600e3834104bec2cc61a0c168cfe358517676f1be5fa9a5d8b124b396a7c083c124d34c212c142a62ccee4c02cdc6b50416ca888dad246119ba3c465cac9fb66dd54c5f84c8ad48247aa560098d3f71497cfcab0a9c874d9c6a0642d318017a94", .None}, + {.Mul, "8cfddcf7faff8a3446b9785dcb59ad2779f0e3eb6ab6cb27b5d2e2932ea2a9b8f9a7144013f0caf760ff55f7a0f93e16e8a258f16afbbb22d1399cf749b7a4d385974410845d3512ae69b30793dfe0d84f09c46d6bacac1e4e1cb9c7382d84020262649dfb2c7b06511dcbffe7360e99a800baa37f333556c1ad7b4612a753c49084288cbfa561d07bfae6425ea19aab6c2d664df91114669951adfccd35051910824c6df99c53acd4aaa7ba1a95c086ea54e278416fef7b26881787486ef7edbc9df724463d80cf855458e0fc709f64d18f3d2627607aa6d7a8099416e3dc86969e3bd98be73960b9f7afc46adc10676fb3f2ae3cc660e3cbbfef2ef3b1e1d2e3ee948cda3cef840a8b5d4d2e63aba1e4cc0b73b35e49101088a4f9d993fcb0fcc798d7622545fc4674a3d283727a143a0e0b2c6bf763685bac552bcc307d1f855aa4353d2fa912a9f2e51aa15016bffcc5c425bcb4c4dc2cfa0f56475250fce83f95b169ef47d2e3093ee49a503e28c9dbeeddd1b66ee2e63afc03be9a03da378508ad64c6d35d3cf8f220db439e4d81f66cce5cd45ffb2f1ca2a9868ebade68d26a22a39b0a50444c175e53b50759e0656c95d0a9a8c43be29d4d6c24de7fba9da5fda5e1952cb57bdcbea10a27f54a5694b48e5f302891fa9d2bae43c4c74557737b8318cf13d7092db26fbd973132778a97d49a43e44605ef09a0be0fea", "aaef32a1916ee28e670621ab3f4c08175810a7789f60de216e5768fd86f43c74e3bf19da6a3c220d179dcbad20295c17ff67bcb70b04b58153efbdceaf944c4bb8b0609f59b78930638ab73465d1a80c5243ff79fb9a02cd07de837506aca97ae1758759a68bab2afca6a9465e53a2c92f2ec287428799261bb61b4dbf6b6417e3ba4e07699209b32ca1612d60ccf04c66bb1a4b03e985d77006d24b97a8e30a74d0c8cfd5ae038b7be6dbdd8bcffa9843047926a8a40dbea1ea958b9d3cf5393194ab5d59280857c1b1fc8a466b29a047a278cd69f9a4a7fc2caacf4f5d00faccf411bc65dcda5759ec43d0cef09f8a6988915741ecebe433c0b3f7e7696b677bc6850ee05ff1479219f249a9384ddab5b4de998b5e5ddbc0258ac85fa872feb368b1d765e6bf536698e0f0e1c74181c0b9e018fc586577f7c47b8f43858539b2a762aa641e8ba1e679d38ebc3d63330787f25d5337156393e86cf3c30b827d9d1ad650b19d75ef138332d733634f4408e03cefa3a990bc4ce2065bb4952cf1c2bedabcae2bab97e50eaf643bbc4032d4abfa2bc10ec18d1fe62cdf6a62d82633aa1da76ab45f2ef1f58d128e81a4eb612d763d1b4842db6860874c520b18e546c70a8c789d7ddc8caa6add8f566d0289eb5cc3e065b096ad42bc37fd112b8c38e1cd0bcd575a7925a17f41a4bbcf7cfba644e5e1eebf54c05b2813e6c5c334", "5e2451a0891a495773d2ea642abf47825f75eee9cf9eff1220ed51a17ba2a70af2d8670fb836b3e541c7f1ed470f0fa26327a72feffda4ac4ab922f8127e860dd8a084dfc0659bc2c934b13adb1ef0edccf498e00219b83c4705a6040cf61a1442a70c1eede5df366801fd265d2c6a6fb88a17eb14ff1d7548ab7be69dc8fac129944f3e1f98ec137ebdfc6ba561a3269e46fde034ba61632cf0cd198495f8f28716d6bda00366877be76cfc2f43a871c99e04179255058ca61ecc39f7c813ca5d287f4f8ae39bae4a78ee5f4cc58c2ff029eac54713d5426b9afcc5aceb7b6b5eee4ad5ae23f5cba31f94d61f581721bb21f9f2ae9169e958ec38943bdff77fe57081a7688da98ea6f551ee1ff692546a42fe48a8f85f13f6ba047beda5d7f0a4a842b4e350f5489b1a3177dfd12aa53ffb6b6f13db7281969e3236c9e1994ec6d9dc02f7c3f01ee88b1ceb02c6540d32adcf4042ceef56683a5b1b22595544caeb722dba1c3d191664d0bca49560145b111df7cb2ebf608c65ee0defc5106d696ef7e726798b248baa06a35e1d6caf1413433f246c0f974d8186c269af3700ab40377f71ce929d639bc807ff901f916b18a432a9bfa759e4951469669bc28cfcdb4c85138935d6a69f2c0c9639562fa36174242b5d61896807febe1a8fdd988c1fd9eb59bdb2832c318957591a9715f39ccb6916926404c2e6099deb6926b4af923ac6dc3b8f21860481469ea8e4bd8bc04997681671ccfa7ccc6b93393ba6d7d34c7001e27c8e2f3e3b1ce97460520607f517e85177900b34594365075efd24e4ec3d4e37d49f575e89839b1eb551aed7d59e499e4a9c65c8bdde8e0b28cda32e1a1ad880c683bbebb152ee375ecb92d468b41d81d6078be6cf76af5460819db901e98095bc67388d5ca2823e87c43bef8eae2878a01c9d0c0155db5918658a045162743c2dcca1b88ef0efa0cefc2683a28d168526c052199f9466f54fbc0ddb99ab2083dcce0b0a183cf0126e67eca6784b55dc0a5b93161528cfa11594480640e83282e87d175b0c23c2b12a16410a988a991ceae32b1602b2cf187450b2d1719b0756ae54af6ad8a034860749bd19ef41613ef2303d151667d93504ee61c70cadef0a93f7020362824c08f1e015bb91660aad164bb6951a90b97c5327ddabc3d87c118e5da09409eced26bdda74ab9265c0f56547cc15509e91f5f6e450e322e19e58d7e873f06b1dadc03ab8f75561f8ec7db5878189056ee5773ccdf47dcebb86ec2cc74cc5a7aa78bdf48eee13f493429373d6887815b76770688a8facbfb85ab17341ce098142f5e8b140b0a92c0c828c1cd009142522684dfce07871de128c6fc1989b6b86e3c9c955cd0db3bafeb449d44dedaf7b59224fd36a28710da14c9b09582b3d7bb18e5f7e70b5ea8cdb592da0241fe21651e7cc7988", .None}, + {.Mul, "25c8b2392bec17896fa8eb2164e783a98667a14e4ab540cc0de75b73ed569acee539ce3e943ffe7e960d454503728df0f22236adbf8fb92af5b2c98994ffb8072a808931ecf0bd964064c2c96d809665cb9ce7a8e58a7ffe9c1cd784c548668bcaf0259e38e8c27a72effe3347390f851d9f18e42bf9c0e84ef3f3d80e8f23704c9566b7a22aba1165d18d3577cc93e144b70c3b75987db268155bf3dc53c67abd7f687514c21043ce320d8efd1d9df396848f25f8d6746267a4c3ee0dab3d734553054f66e3d9780f4505230a9c5cfa78486453f17378cf22a12f371b8882e135693294074b7b6ee9a666bfb654d54036670946bf8fdde526230372ad7e392974edcd9fc5220368096df1356bea1f2cfed93ffe99ecf9225f37c7a0198237f5e5efd730a91f252738c59264fcbd4460fa894f7d26419036b09833d472bcf317473a448fcb1e92b64f9d0f7d37a7be3aa1cf1ef53d1d3f91562dff398fc0553c6be55b988d7cf0d16b2c754c36d38124f0c91f4c0837623fbfacadeaf2bf47ba34c18e0084685aa8f4287d29a47da3f6abdc6ea66af8fe60a915fb00d9a8932b95a7e3f6658fde311f744f17a55372ad9786ad46294b13d610cf7bf879a81a46fdb191a345a3ee43d14a53c9e4cad10c148d91fed5bd146c659f34fbe7a850a74e964a7274a4ba89438d3eb46f28bfdc9c3664f8aa3c8f2b56846c6d0d39f20b", "d6a31d45efcbbdc2af29727ee376f0d34309a4d52b38e3374c2fcf653f3a385c77bcec81621926b466528ac8e46ea947e65b035c7863209433e3db8c8f528d440739b3212caf2d2ced9f02607e51535a557a4c365b863db17c8ee3c498ef10d37d222ea4ccd1bb5fd69fc27b275dbf0598c75bb1af12d48fe9ef640b768463143687ba0d860a7cdfb2a3f076e940f7e7fa480ab227d4f1993f6ee7bc272254f69f1737349895e8b6d0d22b1f7896b9330f14cff9303a33e8c7c24faf87b87fab4917a14c01e7c8970716137e07147362b2402e39f5c3c464abd822b3880807d03652485e0972eb3e3250e908c8c52f18923fede4aa1b28dfd27fe5f474eb720566ba3426eb8c372fd86367c039c33611bdd6d94672265fa1badec94612d8bede41a30d263796c1f18aa2aca19f3b95a5ef8fea4ed44377fc3f6de04f8a05d2269c25305e08fcb507d3cee4e403a770e4882d375da25314b598b4cabc077b8dab6c194e5601197c2c364d2384f47c875bd76d2bb1c4815fab3a64d0c8c25e4e3771948b48ba76c339a172d7a011f64c76935e4040015621bad2cf31ce4eacf0b17115e37f799c6aefaf391c4e4699cca9ea6c7590e0fc1d683d4d2ad37250b18b635aa356411199a9b128ea9ec2b03382be8ccba554a0f6b2c1a29f95e1496de7409d1fb1eec890e4f5f0f86a20ae5e615b05c8ddf5794fea9032d0bd893a96f0", "1fadd81753cb46ed1003099d25319aa3929d11395c4b8fe9492d8c5558430e23e30df64f3e6ccc1e3bf582f1bd43361108c7a804f7998612d34ad9eecdb036067811c2d8af4b31b7b303764fbac51d13674cfce87af0036a2de1bbff2671bd6bea120800a19f21dcd3ba2ca0a416c84cb7f5a6fcb9a92050b0c59c570399dd9470e38406608ab95bc1794d21a6f3aaa2c6defea93dfe6b027c84f146609e97591407053946c3db405783729d9496d277c0fdcd12357d033ad48b35c83863310ef0481c744c5f478bc16ac3d4101cbf9ecd3f74720056e714465cc3f20d2c34b2f823c86ea945cc979ea3fd76b23960a685e65dbf6f0da03384c72c1b846be7b97b72fc63dc0640c9e14f5a2ba4f5dd986f0b6d9206b97519a86d41fba55c3a217bcde61836f46fc7a55b96058aa4c170849a6fa0470a1f4c33b245942c129cb62fd11f42be12646e1e352557b1bfc352d491341920c3c699c873e25d1d70ab577d0628de7f80189fcee5bca8410dbb7314e16d1565275cd23d27109dff8bac47bb74c10e7e302cdb338d0ce9967a6cca73d2d904a4828566c9dadbbb9a0c157eee2c50ac136784cc43f2cb5909868957f915ddb7598c87c2ea3ff5c78003891a438db6a695d8a74e55b083b69ef4c83369f9bdcf4621d06079a6f0ecfd685fbcb2ffa5840f9d8ac8588f5feab0b036e2229133bf1382bef01f74f96662ae62139ee256bc62699cadde7d50671a2fcc6311ae282cf6125ab1ff8262d93e9aa258ef89ba7ec661b1cbe4b9f0dee9ec0fbb4882c105cb1cc83d7d86f32ba14648ca106ac17de4c7b450834ee63258498ff26a8ba4175bce4bcb96280233eab6723b4084e75ec9eecf1bd92a98cc2c045144c07f214a7027bbb064a9766aa7e9caffac4a4a19c5dbd297b7fba97abd27876d0a8df0196ca39d4e40f2e5eaac0f702621b097fc33df9d9b2ec82bc74885ff9ad9bc6324ed8759a640fd102fa95d95fa7e0fa5bfd4cf81e9bf992843585dac604126b66c79ab9792eebe2b212a0ec9ceb419c413542465b34565200879df88e22cce0350fc563c8731ede9e2a0162716f7887aa993b8eee583e850768f80bf7f9415f941cf8c67a153d3a2fdf7a9eb6556f058f573ee065ac1efa69c2ae8d6878359137e05ab35506da34c4feefd691270d80c398b37cecb4295b614ffd1c0848a9906d3dcf4e189fc5b128ab378855b0b66969e093d655d4d4b78927146cb5b044f63d27e4ae4d5558a43dba41b4e33686cb809861830d5465244a8972d359351b4d272c150f5236598f6281e831fb82c3cf807cdf679be2cd69b30522ce33ffa3c98767ef04c6c7fa80ffbee8e64e4a191e78ab38697f65f0db207a7b528921396d4848f2a9380be76a85f7ce9628fc99bfa5af85107a72411676361b5ce7562cda6a4993d8d20ef0d2fc413a35c50", .None}, + {.Mul, "-82358a80200bf56b1b342f20d159aca9f37bbe640702b0aab6b46e462d2aeca98c516a19243b70d69415e10a8bf37f33522c4e1f6e80b7e8a30e992152c15711329ed11aae05a1a1cac708a9f72ec6dc09be52bc76fa39904269f87b8b932c901edcd05bcf3810fd09454d89c3dd87266e6de7341bdafae972d085d7151259cd5cb3274f8b97f74d2369ea217b9dd9ca0f2f7cff60ff38a8350675f568c982b463cc51171532c2bced95e016b19fbbba750b84a85aa2ebe31431e5e1a0402d3fac41d45e19533063cbc6d108efdaa8aff2559a4e55c7c708128acc402edb8c273db263891a7ba51a40ea72002b657c5a5a35f02b4ac0126bb8e2b11dd5fa83d75039f41490ece587419c7d6b34eb6b627ccaf41f28a900f793f58596765e4f72b35c4daa57ebc9efa5f43fe65b04c7b940de60612d54942fd0135cfc08a7d361125028e76e67d1577014e0c6c2ed2fb7997af1ec8575558e9556738ac62e2470ad2317debd5fdb4813e6c63664b3bb17529a8a9dd597386538fbe5cddf3df1b019b30c7711b99f4dc8d7694d11e9bd09bcba55a80441458076006e293abd2c5b37fe890102386f4adb9bf0fd33f3780970c33f6fcff9018c1d881d2878e204ff8bba29ef083599162414ca7a409cd33c39977287d8cd614e1e1d6ac00efb6d1c17c44ea9becda3b9321dffe275d03066b6b52673ac8b11d168c09b0f537a254f", "dffe11bc72b5f4a1f8192c50bd0842bd5871f73f34c969cdc338d71ffb5744c491789b66342d1cd1565553dc368b73cbbb1b7ed3ea4dcadd23687c649e9f0f984c45edbd8d80eccffae3693988cf607cc118960c37600e32a801a91d54288153553c1172ba36ea42471bfdbeba2815254fc3e121244e1659176df963b5d3659155f93bf856119211d7e1e95485d968dfeb73ac4ee0e0412deb51faadf30c4082de6fb6153c674a93be7468eabf907f3f8ea2324a048e118d6d31f9f7e8dc7a86dc730c98eaddf19185d17744e3840be3ddd835d689b93ed8d5d99d208a9d270619202fed626511df532736dc72792ad3fbb072856ed16e6cda4e141fa226d449310c11fb713fd5d5e86e90a5c54256b64196f79fe895a158ef386585cc84e1cab3b3d6770dcba5ea2fa42b1af434b3c3445db17bfd1a1e2f675cdd32f8df8e3bb88390419c6b4987319f84f0aa23bcea7b8b694e2978500681b02b3d1cfcdc4c1ec23504160952e84b32c2c9d44110c7d4db9e13bd6833bde69ec8567eaf03894af21efdcb35222cecd0408d2eaa676992e5a0946e3c77be4bb46127655e0d77c4a97114c45858599cead1c1be3665fd447ba709bae97fd8c461800b9cb2e3aecdb0e59a357118997d74fd049af3772a67c01078a993f76c7f16ebd828d553962bfe47ab7e234bf3d9d9e2ca9853b79ad46c69b665129d2dfd0aba9fe194dfeb", "-71edddca6ee6d2d385c6ab1978e544e3a9d320624a9abb91154102294461b86efcda39c6c21b431eb5a20fed7c320d196226aefd042aeedde28ad8cc59c927fdcb0fa6841a5dcc88b170bdb3b23e7a2d22440258300bd22e358cfadad0bf5a1c686a8dfd0207c80f62771710d467d9c7864ced2910267a00d175bb82b16cee2be528e946abf1a3ed037eff5c03b38e83f47155e4ba4a9663972a8b5f02bb26b4f4dd979fe5395ae56556acda023124f0ca92f521a6ea55bae00de385aacc69a3f2ea02c1d8ac529c7d7ea085782b4e6da4dd9b7f49daeac579c4b58d3299df1b59549ca1bf7f65c9c675ed1b5efe6f36ac2721dc58e1ba7716f61c11b39bb16650ebf86519919144371bd2b72dea9b3bf7449098478b3541b27ff98b706219ab8a27c8d3b56ed6cab83475082d52764b429f0a1cc65b05e6703ff1b6755ebbdb8dab5dfa67eaa7bec1b7fb909f41d8342c1300e496dd61c2d8c76fbad58cefd589a7901b6f4e0ddc93875c96423f92f3c154bbcb7e8528383ce5c9b0b5bf570da0e624e4ece9beb69307f3126b02ad1665eb667668c43aff2e2821c4f16fc76610e9637a98c6e456a904767fc35e04b1c17fc70e9b2f64bbb43da70c74ba31b64015fe0992da91ee41404747e06b527e5cdd1615b1db9b1df7b978a7ace24004358cbed2b1aa6cb6da8461ca60c23ba0e66f34acdb955ffb8d239315c2fcc9d0d59b545b5c64c1fa780f618e312ef64b42eefd929e938c090265f15e38b2db58225717ac6b634e68d3384e74461a7d578068127b7075cfb290bdba07a1e55b7935391d9c683fa73cc7971c4d433e109a56893e0159bdb14c5879fd66d1fa9ee7b1901e2deaa701af82c39887cdfd8799f5a42df517779ee5f2b0bdcc8280b4e6090b28b608b1ae3e355146ea8e29c776dbf3cd9f7d3de6da4e5e7c6529fcc0331a58038e2f338f12167925fca607226c15817cbb7bdca5dd6567305fde4d0946b356c25aeb4bfbc368b031aa07c5d1951ef902a52e20c7171c858b2c23da97d2e933220f12bc02bc625f21a22bbb98ff75230614fdfce6727c1397d8f6da9750d79b69c67ea3b642f1c5f7754189eeaba8e3583af89542eb018f5fd824f19de5c4b1611ae56cbbd4b2f3a7652714f678fcf12d24465049e6eecf86c9fda55c9087a4cf78626d9d7fb5feb069584c3c6feb268eda37900139ada6415897be8f2e3062e985f5fca079dd8f8e5925f83c8d314722d480a6ea480327c326bcbe87618a0beeb418cc6007563506bc4196728a0022ff96ba16c074b264d15156b114427754668aa0f91f977c727ebe23bba6bc85069dd56ac60412dc1566b83f98312a53e8dcb7319272cec16d767c47a659697d8223e5b76f3b2ab79ed7f743805d659b093f2c66f0cddf80620f7a470993125dc456d8769b09d02d29e042084c1085", .None}, + {.Mul, "dfdb0b75e7ce84161d1ae6d250fd85abfaf6649dc1c974db231dd4fd527081acb08f3f9560c7e1f986c07410817c831766b1d76ebe9eafc0476434e367196cf17a029b9978068ab19c2c4f3aae56ee8bbac7932de1cdbce2cc596b1a3440be7725e38d12e64127b2e5057670186213bf9f3a855d38c899560bcfc09d1696dcb32d0fa411b4837f652cc1760eadedd2234b8de7a5753f5f38085c57c6b218e4a4ed990078ae7f5ccde1862d7891c4537c3e718522239e81c35ca0d4f9823930ac20046cabfcc6a3ec7762a4040de490dbce5e1bae5701223c6ec0cf4ee82bea8634d581ce1ed8e184b912f753fbb17e0aebd5fd4bb03eaca1e02d90a4c41560aca1703c58cd46acb604a17f395c292b161ce947ec05da17402fd6bc310d765e412b1e89668315945d09f1bdcffb000d909229cb1bc30b0d8f7e8afbb917711b7e0d8b231af64454cc50dc64835028ffcc9df512c7f87e8dc66104874314e73980054255c4dcf7c4a4ba2db2ba6ba1823e0ff203268f2cce15573d5b6438a0c2a0b1f8785eaf9448e3f95137481e2a99e698c6dbf968518864dfad77276316c9c3cbe9deefb36434deddde7b34314c994335a2fec7fe729b251a06c7066a13c6121c7a754640f9c4adeaab523a82919edb947c6f036bf0f93da130c998e02b0596fda9ef11f9881a8af2be7fb674ae32514f18688664759520b323853f1e2b27ea", "2989f8a3d459304660fb4fb61aa79301f274ee0a906065aaf7b8976fa89bab2bf19c278dac428b95bca20527ffe793c270fee40d19b4c064d0d3a3891b441a7c59f48dbafeb0f0efffa829f66413e092c6468dda00825d498482ebb2562d0911d8d9f96c87e6be3d7bd999844b5f3e8e22a156f3ac713e628d811e7ab8c79aeb5220c0e0f3589d191454204d4ab882bd21a4bcef6c3ad78ff2a72939a14afc9d04d11d73b09c5bf79f9a6933989cb3be552cdb3c4b7b7ee1fca1ddcda1ce6052530605ccdbd653aa7919028d45c8bd6a76d773134dc6a81dbf19a4b6af2b4653f94c3cd1553f1145af887631c7db77400e8201ec2b0e8b6e6da2731da868d9d20b5e4c163ebb3c029f1c9dc4200de75bff857e94d6b848d4b1c0df4bdd181e572599329ff7d4ec005e75ef8870be0bbbe0e332539446439d0653085962f4f439019d3ff43693158ed2a220839e5162a82a8b42486f37d1516ae3ac013b5428d6e76919733cf78fe2e250a62421d0b27c37d98308af4caadf376782a7fc2b64a7efa65baed082591da7b66e6c35ba1bace8f5e11970e7c6682dea53a07b07558397e031d9801394a7f62b040a2ba86054b337481eb50a2db82843889204fa708c0f4da09e90164041bec17016b26d71a4c01a3491bc60629b9b1536cd1645afee64143874b17cb4a49f07264fc484e9e348b78d69cd3640c1ba1ca1a4dceb9665", "2452ba7a797b082a1fc0284a6d635a6fed0dbeb4c7ce31d0d5d4aff0455886d1d46284aff86b5b6f59c87a5be05611f396ff7f7451eb242c4763eff20242ecbdc397601399cdf5f457021ef81b87b7a645764ab658589f977e368a0094c401fa49eaa61ecc78b48b419bfffe352536bbe8dd2cba39e02f0a30ab319c62d5960a69342645ecf4bce2d6c9f6214f6b5a1186b958f4eb0512500564120368c3e610f80bd37a48d90e2ced55a413f3710693ac14cd76342473cd791ff93eb9e79324a9f5a33607650e0dc17104034bc4f54785eefbc3171c85f587d3d6e7c8f769ca5b6000f35cd9d36c8622b14166f082fd9e1159f63f9e6e8650dbdd6c0c3daf25c63c8bae2381d70a5c2b7dc2a47625c56db78444404943f286c551a05fc73f2cbb28ee41acbefc25a4f61f54679fd7fd2f551c9d997c55a2d38340838b762807ed18800e0d509ae81351d5c110a61014bf9f5096b18e1ef664bf992b94865f1dd5e95e3936e4c7864c8a4530f4fb537b8e7efa6761a737ada2224140fe69bbbe379783a445b403c260e0c293d6bd4ee7793635e341a3c0f8f81fde8cedbc0dcc013aea3eb3fa641a394f1ad94943fe8db536613b011baba4183de5b70ae88534b507bc829642646e1a9c5cc106498d62d846a58c502edaafc58b4d33b14bfcbdd11100e9855b06c54c9f884a21f010dbc2bc058086347bad0881083e8a9ad1a0b70c9c35c97e603f60597cf0d8912d41f079049e66d652dcb86ff6069ea6e1eaaea29f3b303e6ec24f5f8b1ec44378684381c0443abf9f3d6c3b89c9a6dad41df40091f9da383c82b8229453786722013d5bbb002cf10b4b76ef4303c4433baa2efa0ed336f2529dd7b6dc138cf1a647a381f7d57f9c6b31aa8ddcde217f18d37486b568fd50e3fd7fc506689f20556b54514327771fd8bddc45c6ffe9eac96b392c58f03b693835dfe492bae1fa626fabcaf370e7ac0940858151542b25aef3d593feff66eb779a49b1e7e8c49dad508bc5ac1e416e1792ff64a249872bc4f5c45431981fee62ec68c81eab88e21c8d971116ba494bd2b343ee4aadb607074ac291e41e46f56ae93e2140224456eabb8e868af94b2a5075ff0a25bdac3ea6364a87e4f678a512d8bc421c68a7cf9538e98d0a5ddaed4e0f1ca11ef75d9fba5ed51d1bd9051d458e4563d5df38533dac51d074559a2aea12a4d3ec9514aa00120d19561033a98234150d84cad0baee59290e33bc082db69e91b7ab231601d6f420838baa8f01a3cb213929da4b4eacdd93de3e7c381f37a776e9275b77fd880453f23ae7ee435eb391428a450d416a760174788b7b7c3908e6e863c01d139ef8d7b1b23a6c48c60a3b2a6ad8f6fa4855d88d155162ee4aa7d8ed724e192961cdb7862edfae105d21d1db13fed8f94cd865f1297464fc4485e54c1166ec37db52", .None}, + {.Mul, "-21133d83332315b73053dff2f4f818fc11b34e95a821a6efb6e9a2ea335dd9b91329ff159f8fd68fcf8d0ed20e01d71f3bd99aedde22dd8ccdfced53f1cd46cb4a73af922d9d954be65bdb1b5735b46f0c0f5a2ebb3a6a14b9afddbb40022506378bf1619e238905baea507e521f6e4e2b77f1e872244c8f73a4054b1a106e2eeb6e0cfc259f32ffacf5d7a18d3efc1a54ff345ef42c7f165a4531dd404065a76fa5570b45bf700275fe0632cb322d197cb921c73ada231a7f611ff1b7ebeec6c05eea109c6f6bb4b7af6e11ce16d4c4e7f17c139c7c9404bd2e9fecb4ac6663cae970a34525a51e428be005ba243bafbc9737fd939b8ac78e9c460ebec7c1ec6f013b57536a9be9c16d7ac5fbbc26ecd3eda5340e1ffbdb9619def28de4c6bf521d5fa0ca68858a61d2fa2c43195518b5e342cbb94afd79e8a7c4e372ae150237797e8e7fbc5406c0980cec12a5f6833768c75eecbe27a2092ccbe43c404aabf740db57b04a8bc05fd52524addc93632e9cb631de78a1c5c719ed761cbd56a491db22846be976858c111b7988a55143ffb7320ce2016ce28585b1fd3560ab1fb7ad5382dfe06eea29e14d969c894629ee8b2310703f12b5719e3cdf3e5124682f9c2991104fbf0cefb20a2303a4b5de4c3620b7179b19802dd186ef8f0ff4210a37c73594208f723f8a8836772bfce3ab2a8bf9e6db27b71aa3a93eda3154df", "b8553f2219989dcd34462e4772eefef02e8084bd35960b0fb81c84f4e29f4f768f07b7c6d7c2c04918b3a02cd68f24e984966669f7bf63ff96157c101c87b59738cefb6bdab7684b3cb5862e36fe4ea04f87d2ff144115772129bd9db404866cd955a8bae671f8a0da53c1960c46cd9c976b2406e6687ded6fed79d3528548e13a548605640c8491b53aef9a919483e38973b047c1eda637f418396941da9c769cc808eb9f5a375c7342f29569c3c2699f510bb82dc979c00b51bb4f5e1b3beea0598320749d5a86a50c79337aa5b3890aeed7082bae34eb993afb5677df5fc6edcecc657fbbb7a4bdc19be8660ac4d95a1ab734998188161efc2731bc652d4611fd094196c8bddd34a3a6cdfe5c22a92660b869be066d6e306215d2b536c9a6d18e4f30ca9b1d3cc4b7308447331c5db72b70e01d6164cfe712b81e86827d902d287dbb1dd8d4bc90eb962c5f8b04e81b02b317311a1378f3fa720357842a843d07377789e21bddc285611f970965ab873b9cc0382ab25a3e8692450074021eebe042e99cfb2847329329cf32f5044fc4301f0426247549a7e0fbc13fd2e38f0e0c3174b76f3c26f8299ffb581a5507d74cdd28eee2fff15bda488dc42d6cdfa17e61e90f26b1127c1dcf656a329f0b83434f85b1ad528c639c0081a272b02fa3d4d1d3ce1f23e67e4077943191ed7609cb3604e8e1790c47b2c9f2319870a9", "-17d0d7c1dd514015f357c825736500b0439161272eacbe13e7ae1338a085607c7db30f7ef0dcea2839b46dfd045bdc3c0d43e341d91d24b1d347c1e73077c9391c68d9411f5e5178e25f7abe0e7423f28a5f766a40d99b12cbeb31a86482b1ee6845b1f017d86cd469a4da800a3c6f64415310520d19acea50be38a608d5893578cb9eb31e08d4f273cf597cc6a93065a259ba4688a5fe94c28eca966ca24e9a29b599d7cc7987ad7e4156c57be8af44473ff98197f3320d3f799de3ded44bdd6e8e96abc920485ce9d748d00ca4f8cd9fd111ca2fde82ba1de4456ac5ab4900e4fc4b2982da636ba358d962acc662a77ab41d7ada34ff10663597a699a5943247ed2383ea0995a292255d51482b47efad97e91bfa13a23a11c8e10d4687ac025d1beecb531fe9d8c2395dc1cb79fa1076ab00fdf48a35488b0fcd79c862422f7fe525485aed268c874f919a5dc1d79594a2b16ea4c775d5784db06d8c926a8adfdb2b29a4f010622fbe3dab7e936f8b024232d34ff7993a5690d8bd34ffdb3cb8e0459f6e63fc8daa3ffc93831631b4f09d44ee3f88fafd55ea0ef3d8634c12a9508c9c6b75ef5abdf4feddfab0dca6b76aeb7bd143f29621b803570c6f8f9d3217ca67818dffe2cc551fa34e76ab9a8fa6be0972a1b2cf1ec64ef6e4cb5caae0ee0105b0fa01d993fb84a20acaba6c5545da10432d7e085b0c988d9a9eeed24555ecf301e4259aeef0c73560629a445835adf09c96dc718df2d51700c6825a5f70092743a0f5edfee9c1037e41807a21d81b8ea0ee2b8c2de81398e023b92b81c65786b8be6d4550da0e05b8c04ff7e9ab6f78227ff60b51c895588904c7f64233accdd8c3e23e018011a9e4c55d9179d8eedef2afc06d75cd41adc22d4a0b895e9ba995e60cc97de1bac41d54ae89b099eb9f243a5384e660b1ee8f3e91a9b477a3b86f58c438a87042f8b4036dbe2901107e63b38c7c64bfda91cf95786f89029231a681d2e30e5c24031c16b8da69904428768bf2f74b986eb218a6b973af689aa8346c5a2bf489f1e272f806f30ad42b8f2d9598349b815406aa8dd9f1ec2d0f0a4e2e0cdcb02cda8c42fdadf63ecaef16bef1f6883937ed67f64eb421c09f64af2637a324bffc858d6310263330e6e3999257758e8acf3a6b6c15f6fa402bb1cbfec8a16deed1244dded7fbe5da03f1a8baef8bf42cc0c21d3e96320f8ed7fee824f0edb70b259471c04d4c95c11a78ebeb01a73a227f9306711809c5884afb2982ea0ec0017dc5735c050746533c6fcb413d6c58211abd4c48dfb5a54e531c13952e71866b9e408f8d659c787406d18520d0217e14071c884e26f5d1e51e2e96115fc25265deb3ba1e4fd7a473cddd2227b2751d7f442dcbf68d169977e79e783046814d2941d25b1908856b86197645ef1a951f8f7e8a4ab31a9737", .None}, + {.Mul, "-64d9f129b812e4edb3e3634681c4ce8f452384f9e921e5f90789c970c19e5f468e1840a2b063f0bc644a9ae612cf814d20a5effd4c1e75652351ee56112d10438fd5f63d3f0310372e92a5d361a14c0a50b85a9a2e5d00cde0c65c7eb05697355e8f96626c5a3d114979fa960da3415704e94788874618663227771fe97953159e6d8e5144a4cc53816aa6df2863d87a52afcb6931e6acf0c10e58ea2c9a5ad7c7fea5732b741c762dcb77a0a8d17f14554f5cde4369a79b5f6c4f8f80375a88d533d542deeb5844b075cd716f787a1dc91c0ea45c9783370dbfae13168d4975c83aec54216d33c30ce8f6fe12ba1df9fe765f5b28ff14af5a86dd37601823cb3f14184cbb60a1366921c46bc7f794dbaf3bca34fbe821f7a74284143591c45dc914f2308edbc0f2fc1d7e698cb5cb4fa79e70d7d76d2b8071b56ec96e58ab847c82a4397c1d4dcb5df7fcb20038705883defaf032b6f56239d12aa1ff1308eabb845d3d8b46a0d80f457ae2d511829b149de7af977cbdabe0900c4f0c7dfa8f90a9b339ee7224d0b2d47c123c845b04f1f988cf81a28b7c1572c89741893477a06db8a1222aac6dfb1ce490df9fdf6fc9eab4037bd8bdb754348470a2ac4a26da21c0e2b3889d671938bf1551ca8b724d640ce79ff95ee1bf36dd21643a4448ada2b120ca5a65fae780fdf3223365f869d1146177f496b5c627d8efc8830e23", "fb082161f6335134b59242dc760d25ccf6449525a7f883a24b22dae7a48cd955a3f67b7552a02f5db3c4be2f05ba5df05e144e71d6c7da23329201db71aca3c8d2a7f22f92f1a42015244a4f315b257ff778e60f5a25a4136e8dfaa53392285eab365f653dcc1bc799a05a6d2a12b708fe593992b8bb28f9ef2b1d80b1cce7b9431cc92e0b93557f80e97c62ed0210b0877c02ad13772dddbe2d7b4f505f21c071b4a48824070eba3806eef04d23856f91380d0721970211cf3b3171dcb85a31bdb29ed306dd09c678567f99563e84c094db823196f6ea9b2e02c5a1652872c27b2279ec3d8ac0a067117636795e978ab1733b55fe97c233fcc4d5d66bc75bfe39ce8022704d47934a378fd9e3d0b2ef23fff07b2be1f92c3c2606e3e77f86c39f11c5573fdbf8fd591a7036897a619a7822968c98f033305c4546d6e96c0bb9b6e87c0886691a9b3dc147a3c1dbd367a2674d4c722fc51892c36379dc4589f54ddfb114797e6884a6ee211dd473ad6ddb544169bd324e6f05eeb3df59503290d064b363bc7e26fd2bd85c8c1e96071df6d5039c32fd962a58c63830454f0843d9231cce09ef4a104a0e35ca5eb419cb4fd8f793059bd5303f7c3b1fee2f15007a529c4eca1b54742a26f0919905a327aa912499d34cf1c742852a8eca07afe830b77118df29e3497e6baa08be52037cf85f233f7aff7560a5e1145362db4f52", "-62e4e36a2070adbc40c5ad4f2bcbc214e35442038966f5a939142fb5b627bd608fb53005a4717c5972838c8b1b9c04e1b06896fc9fcbd53cf1cd2b4da00bb9f32ecbbc9cfa736e0153f45259603431436ee7f1485bcab18bd77ba9dac8aed0f9a2565d03a4ea060ef6c262344d063a612a8936472db636d1da8ebfc705a19bc89ea4c31e879f56260e593a09cc4b485afac7f5fb690070ed9ef6d5dd597d96c5bc982a32119a9a22f89e9a01008d28a4d86b8da17964f3157bf7700af844029516cc2bbe39dd508d7de643a4db38c7e5e8cc80fb537831bd31996b1da91cb5e7d2364aeb9eb9acb9215088fb7b6b615004e3e73cdf7280621a7108c850323cd07d546ead0f96eaa0ca8a5ba0d0360576402b830a305c788f14833e01e6fd644ea7513e6adfc9fd91f96229bd61feb402f2dce4a67624aa143447c12b0f389261dda3f299d416c1e6d58c7a1318e504ded428a4fa4d8e0729f1888577198bde263d960209563fafb386b79487f65e8d93cb847522f1c0d10c3a967c732abb0d7925a175d91153d7d3ff961a3010b34c2fce11ae19c104b7754e0648d7a5ea2717bef0d09c9afd6eef8a3dae841f50f6e520b1327577827d9ff809facf6a6375cfc6a638535c88187fbf84bcfa52300802dd15d61d4c90ec105db51c0baa06808e9617470f09d74f27c69b159e10d205153bb36ad268eeab40ad95ab21e68115762c20eccff60e62aec317c5b44dd035b260ace0543ec40b8a497875fec27422efcef28fddf5ce0481939ee3c759e3b1523c94da8a815cf7f26b0eac76876a4d98df9f6340d82c222baa575813092d692a054b27ab993a00b417a440d3be26506d65f20010003522872c1ce2002b6807909094b7f8ccf78381eb51273cca2d8698ccbc9ed1b9a31adbca0077d3f97493df368719e13f7d3053058cb47283781f8152faf987d58a67e7e0a1088e0ab7541fda8fa7c3454bf7e7f82da43ae6c7f3b2bd9952d550bfaf71eab6ba029568d0a418629aeeddbfe16b64f0f8c827fbeee1534285ae4d9e96dd72182abe14dac789cfa93589f1aa1885c37af72fa80febca6b06dd8033c637ea1115e76d77801d7ee19fc659a76f313f9756ea41eb8ce6b92242dbfe9b1fa14e6d025dff494bb7bbf0c4ecffda120fc36c38cde9946f96c1c8ebdb5c499c889f0ea443b1017cc865889ae73bf5de7d25463d8c89305512d11c1429792d87546e847dbff6bf7b5369e9a600f4c44c0dc9720d0e9b144e0f619155d7ca5506565e61761ea64db0a3a55f011ac35e9d0100c41f9f5afbc6b9a09ccdcb6e204f6d492222892cff0d21d5a887c9bd4c3872466dbf3425d3bbfc4c47de38ab4d062c26e25aba528bde1038f229127fc4c81658f810052bc9d31df36bd3fa9b90b636ea6ab3eacd34f4f07a13c826e1d68834565ff3808e29485436", .None}, + {.Mul, "eeead6346e78a3a1c9ff9c135f3ece9267bba5ed30dc457d81656cbd3cf7839c83fe66bfef40618859fc64269df75d356fc3397f41a07a493571b9a8f83c67cd606bd2d5007229bc563344225594c0a9302c06db0a0a398b06e314ea6197546994b7ad1a1e93dd083b6dac334123df61fa4ee677d2be7df07dc547c098a31b1900038239b37ef1fcb27ea09c89f495ced2cf7b71d98f4ed773d4957adb24a9272c56fa564bb8da213749ef6760c04d3f69ea1d09768c89bb46b55f5fbc37235ed910ad517ee8d96d389bac68f9b88dbb28abc1c73a1366219b9f565d46e5c6ad1eec11834d20fd4e9af5892bdb3ffe9b42eeb01e78d7c9c891e7aa355cf71830db38d7ff163f3cec418a9d36c7891f53cc71d268893f9b8309a2f8a773f4d76a66e90f56982073ee30790e078a4f8796beafbad5218624aa7ba7dd2f0946ec649f383c45e77a4aa1922f699ed76d4c11943b174e73534cb0826e95d74ddccbda322f968c4f3ba8599569047a8e0591cada2d5275d8bbc7cc742287c975680451b48d165324c8c50dd0fc9c72d61d53d03d973ad234912f30735884ad7fa6c3d3c499a123f1aad263ffc2c9171555e308b917c294991c6ead5ec88dae6a3dcaa38de45d796e025c71534adbbc803992e920e75d98ea7a72bf26fa86d7b8898dfebbb9c6b49b65f7eb5585d0ded217a379f608ed264e90878e527cf01c1c84d70", "ad906b450aeba75afc0652f80918e57d3fde8b40c6eaeaa0d49ada1ca9349b4818d4a1873c38c82ffdd0512b96224b102c7a6820139a9363b6c00cf01eb664d80269787280c497fd9ba28a8d2aace74a418723be6fa355784317246e7bdc62c18b555ef847c41606b0aa875b5f1912f2f1e19747e128824cb1bfa2f2afb5aed2d05a1e4666aab767ba3ed1d0284efce8303783c112381d8da1b8ff179bc06dc38053e90036a983591ccfe4817af6a6f7662cc0b8cb1dc41922597787e53c99213489bd3ff228dfb7c293240150cf79b2284eb862090739375f85a3f73c571287985efeb089a8aa5fa5edefc272959f19eba11e4ac48a242044f2e801b156dcfc2f8583b25af36e237e19b8f277a463481bdd11fb9f01154b66414cb33d8ee9019482264ba9b2f8a9f92cc8b14f4ed5ca6d4d416ab9d38775b7eb03e2c1a497fefff1e30427cc7d12a8ebc322ca3688adcfc71dc4acafe3fdabe9062416f08231eef4cae80f7a4357088f7da2f83959e3728d14e916c2d30ec4935696ced78410bb68fe5fd4fd016e398bf7e820de269115e449daa2285579690ae43eb5744db0d9073197f2818388c28a3a8be9474b58e8f78b0736917177ade33c526121a98b86547c833b9905cf4350c2c447a0f9ab8682cbdf078046a3c01dee0922fd96203eb2b8013979ef052654589c0c1054d30f4afbc289bfaaf15672e187a6378bd6", "a1fb7af6832a6adf5d5ec9b79187ce267d81b1099c57459a7ad3c7367ae37f227666d5a1dc6c86d6f3f81d11dac09ad083118d59a0edbff6acbea8fe027c04573b059891078e6e603165b050d5102aed6f568c31170569c788feb940d443c0afe35e9a3b72465a2eb9dbbb9c619822f9eb708ffde5a67e3522167f106044a33011314cb932cc9f8059f80e41194029fea2558747b699c57fa904b32721e037a30658ebc22499e50aa315a70efcb72ce5957ce81d887a3e76a8efa0a4851674ad5b771ff8c1a1b7239184a5636f69a85fd5ed961390174b34dad55e8f42379b6f692626ed1030671c25380f9ed2373bff3bb321d40fca49e24a928ec5fc799d086dcfda3ba421d0883460b9a2ea2e98eaae1dc213311d08b67ab40415ef8e2050c12a1687df3c6dd953d3633b759eac7b306072fd3dfc611a3c06f67d4c591476f6dca87d6d643d204529556140ef4fadba3ba7d4c118243d8a01cbcc705e44ff4d4c45a760b6f51c490024990a36e7328fb66b2267957c602b75dbad3899d3e0cad9cc372365a634e29bdfb36c8fc9d4169d402511cace4513a939467505ac0f55b501a668b1f7dbbdc6850a38d7bf484f5531cd7401edbb31bcf358d159a6264a5354d46b9c4f8f2d7ae7fd29bce08747b54063e9599f27a88da4544e7c8d340f3ea2cc710da7e5f0914d1129fffea0dc3015675ec6c7079883aea572eee11939e08c8c57493fd43607e6dfa845790696634a85eaacdf9067a549c959ca90f59204468ebdd918d4a48a1e1045fe8931aae40b5c78a785915ffbef30076a70a3bfbc331d4f0c9aa9ff9510cc5d8e251819ca9f665012f8e95abf43d4fc660189cee0f669bb7c1b98e72a1713cdc3b98578958a41138e80b346bf89969e724cb5b1ea77d2115d9c87f21c0259576218d47cc929caefe351de26aaf055974f8948fb11160c12b08bbae88bb7c161efd432b78e636d5d98990d3ddd51ff68bfcdfdff7625a3f9c5dff1b16f5e65cccbd246aa2991d07cb8b8737c2ac5311743635f96f78f265fa306213fff60d449d3adb4073c53553bd76828171279696d56461d5f571820097401024a33d1e9aa2efe240c2fead115b545e1c5fa84106173e85e914a8a1db753f7fbec877a532bfbac8befd3c4390cd9c1145eaf3a1331468351da6bcad854add7dc190b933273749f3ec39032f137476c6668ff5f223dd7fc791f9028149303a58eccb2aa33dbf298a6b56837ee6e22175015920202f060d4c80453770edc454502b540f7c99494acb5765a832d0b728430a8bd15116b4e3a9a0ecd1cbb7fbab35397a517bb5f70397ab17023cf5bb43620aef9eef6da27464d6743b5ccc37291575567ff465925581edc8383a1bffe334d89e84551c5438e87735514de1d0f075e7e1d410d9032131ec19dec0db5556292245c9ff028c8ba0", .None}, + {.Mul, "-37aa89b85b8227da0e584dec1d3fb0fe1663c89ec1513f44fb7599d6d6c6f819d888468b6008e7146b5b0c1fe985f32a2fe8512ecfd14273acbb8efb10944d9d32e29851a8e9f76827046e1ee0da251aecdc5daca098d604fd3bfec6833f8c95112f53b12914fd518718b036ae546b087ff0ff49555a34a1c93f4d92183220e7ae00fc2162ed3d3ef8a17d7fc6b6723366803ad3039040688a610805e91c6d2fc981de3d328a6d77af74ef41d2208607db0401f309d28a43cfa953ac913415b08e83817db76c554383ed320db90091fbf11b76f3ea0281ad0b93c5fa8ea2ba0ab757052c092738227c93880dd3c41e0d0c9096f06d6c8da1ff3c5ca1296360b35f19a07f865dbae49e601e04726ba1d161439d54ed2243e1ac060d2718a38dbc5c87d72edee1b14879d13669905eacf484ea0e60e9e2801072858ba2bbb2c7ce1df9ab1ff85a008a8f5aced84c27a83f828dc376fcd5dce04066de155c938dc333565f28bda924ff060b6270552ed963432eaee5e68fa32f65d4bd18b1debd815a2ee84b522b2773376f6abc8e6fd41721dab6a0dd882f2cb4ebed57d18c5d0dc7fd0de5184640f044141d30f819732cbae5f3831fcf8e93f92a3e63ef61f14b93fc38b61b89d584eeba5e4a3e5f55eceb7bc8e2ce8aa106c669823fd932adc8fdbf6b8e6a9a5291d145064e1b345710c4ce6580849902f385d523c5e5041238", "5289e9e5f5bcae56416dd3184de5cf406d54ccc268792b1b367d37ca0ccc0d3074e38dc8e50be30b0163bea921df89736d11270773bb0ff82e73ee5fbfcd5d71c90fdfec3fd3dae11987fd855d19b3034ab2228347dd27d21f23fb0ad50a2ffa293729d7ca4a53f91d7ea75e7a9a0cd63e81923cd8c7f00249c683d633da863a7d594b3ef7b8f5601fa3fdd974cba30e550f63e1cc95d9a8e3285751649a4051985c5af207cd698d48aaf256bf2c087f1fe99afe6bbfda3db06b3694acba79f50ec9f52270547ab436fc9f4fe26ba635a1ebc74523f532b589f490ee91306f12bd95f78b79843835c3a6c4e9b7fcd7b1a254e683f852ea7f1a5247d38b4d1dbc42bd4431bb4d0e7824cd36613fd048756729f569bdd7b49674a4e46d16ed77e3b8ab21e8f5d9a2888de875b9f37e68373e4147fb6de0c9ffea90165b7df0d9b25d1374d50c7d8559b61f286cd614ad2d345b1ae9e13821f56b7d3abf3c6a7d5e9a4f9731b6ad25345b0a95f84181e615a8e10103f57e0935ac2020028bac22915f7ffdc5bf050fb8dcdd63dbd5e40a40edd09b65ed8706360fcbaffe108dbd7b9f33ce9d698586ca9d33b4f956c651a2acbf3462589ca93d92ec16cf22d98149d20b6b635e85088d0729d55c92554d64f8e939e17875c67d246ef028a9092e4698b4ffb9aee8d5bc2d8250ad5dc6ad4450f1db75fe4e65118b715e4689d33867", "-11f29d3cf94de391bc1397a9fc7b705202f82bf4cb3517a2cc58571f618eb300c820575518e163dcfce5ca8447118871f90580a8914780b7f44b474a216e448ae11d4b6a239125367d028b839b45e630ed36630c1ab7d3e4d0c9b80a1fbe00d2e9052c05a5af95f6b287db2e417b4238362003ad83db351c581b98f9b2ccc3553620df47b75b8f35ac03422676d8b208bb9a3704fcd702ae22167e2d59d63c943c08012f2ba51153c3602f4e388dd146688d37343689e158e0fa88e5037a42115870ac7d6d03d4188a6fcbcb40628830b19dc15943c6945254b37413bb4b76f9cd7d14658f396a646353583b8fb6666de22ca13337744790aed39e37c602e13c105e16cdfa2a7b5f02190eb5fee71e58e6cf1f86993e2b62f4ce84d7877cd3dd8110fe3c321a9aa1b6b6e8dc2e2af55a1755955e10d018ecb20e619526e39c0c90f4b4af13ae8a7cac92ad5022787b9739451b8e79eebc4c4fdb3b2956598e5b2a5e032b4b3d9cbf34845c23be6cff0b6326613a2d569144ca870e32f3685552d37cd76019e50f44f3d4f9964a575a85cbc60275df2978bb37abc536b21507cebd187f5afbaf3dd5f6d4277c556af696cad525162d059d831063b9fbb188ae978ffdc8ec3dbdf17723b6d9178a47179cc70b15cd269c802398f6197ac922a5af7a2283eaaa6979197699864ed865934eba38a4a52a8a23e6e93a50b829e985337d48af4621866d2f301cc45563ab36dbac6d1e85743ed4e3edcd859b37d36ca363bc5415aac2bbc40f543cd9ca978deca7006b29559324d8498ac6b6ab8f2443e02f728d8c1e99304988eea61c849fe9d902132b24f071e1a5e576c8cf634dcd697e0a9949750fe08ce370329af1d59920b20b3cec176d99583c33127478c362597c547d211d7e5dd1dc65502f90a59e19c6dedd3a5402dd29bb08b49a6be8c141d8d21dfe93cbe3ace0632c3bb9f5b5b0977a93a9babfa58cce1aa9cea60a2410ccb01d90bb5e86c46b229603255507ff25a302d5b4f1bf7566afecacf63083f1daa8978bca77fe26167e041e7de2074ffd02f2bcf5ac39252d62c53f8232a2736913d529a55ff22c6a43c855d86e234c9a32387392dc21128b1d6a25cd6fd100914f9813b105f19efc0c725a551bf537c2d41b9500dc9b0ab819e34dfdd77c77056817a5b6915e99405c64ca2398a42de23e0819d213e31f3bbc5761efd3a7527daba6b03a277362838ca98399b413654602df1bfee2ba2d8007fb5d93079f7b74944baf8d136dacaaf32ab00d9501f4010aeaffa0864d85c6412b36150a7ae0c49ab9026f41151643fc99b25b7c7c8d073bc30338d820c6f2e081176b8b2fa5eb3c976ad9ef400ede31ed308736fc806673b1fa41b703bd24fdc3c2e4fdfb114ae066de06ca99148f8c220b93a35fc42ba80c9a2ee0af6cc52a2304c79488", .None}, + {.Mul, "383d6114b7945cd884052acfe744c41aa0052626f16ee7c3d8cc00392f9e3d5c7b38ed0205d07c57a720229f6316ea474377463ac97eb4a9695908f8d624db4cfedd5485e35602be60aeff72fb06952aee97e3ac8571a2a18a6f3459eeddfe16272e0ea13cddabcc03dde0b276bb59d05b0aea00d6b29adf3a8fcfbab565d7a84cc3c931d5cfa72ad3ceb3cc47f2beb197f295b11df9c9938209da32033e02b684ea5dd12cd8dc56cf95bd5697e92d292b53f49c93a438e62dfb9cc5088441836a4a7cfbabd146445b51eff8d8cec39d594c9e37e64f3f300e412476c689d58bca1e6dae27ab93028fd8fc0d675d51efc70badaafd15aa4c442ae41de4867575f4567134077f02c6856d8f5c5785ce8492236c330d7b0ba4dde2435532bdfff0052f11afcf597817a1d1d83eff320b34476e4c9aef482843510e7212256b374bf761da6666464c42b3370e0e3f0c765eac30b8af224083642ca130758992f9e3fc0788d93adf8593a88963980e81c9e02c3c3a105e84a7ee898bce0e61509ed7f65b25f0a460cb12e8410dc3462e08b63a7247bc4d6bc8de5c24f51718da7ec062562622ec7b9544ec56eae91910a7acb3e4302040119ae6b5667c9942ea03b5ae432a650f20732efca157662aeb255fc7b0464b130fbb34f9266c47406bc078388db0fb61f64c72ad0bbb713ecfa299961d5cae19c4c0520fe9aaa382448580", "8134d59110578136f53a5cfb908bf9d6fd66215bfc2e67b388fcecbaedec611254aa6e8e7dbf85f58f0ac3a997934b795eae1bbcd81a96f88709043996b5b3dcadb49bf2620f8d898ba2ff8a1fddef318e2a0fbe535e5b602c634607af62e1b8e2a67c557aeb693cabffab6ff9a91753ae6e171f429570859d43313c662a5d217d2b37da6a8ef78cbe9bc657ad3edeae1e6eb235b5aac48473f966a0394086bae2a8df309122d306decea79745bb1a13b0eba002704fe25c37b0a276a4884354a0646d94ebb5c4e04a07a5576b018eeb8817a60882fcb71dbe3bb83b52823d3b97170a3a224426dc07ab5f00f78aa72ae0de4a69db371b3569d90eb3d200a389216943994389280456efb82728d4c41473021e9e61b2d5218ca3dbb6004cd06d52fe83aa1d377e99aca0c6c1c5367c3110611cc7a933737036a4eef509d7cd08ed11fe2c4a26cbf699e0b04eab831c5dded8462417cd73f06365e60cca778f230f31359ffc6078c611549d8290c2752227296168b9d0b3e6e59fdbb4eacbfce01d83ae74ddbbfcf7f0ae95616b05c82f9a2b77c1b3e962c692b5fc2c5b17b5c3488963bbc42dd049bf8050041653f4c9f50d3d5a58290ef7ef3c9d35491b45e6efb6a32e40d438d68b51447182f522910bbf91cf692c060abc62ced68ca85b8b5353a639dc3ae1884a228ad71b4ceac444afcf9437376c93fa771bf340d8b07e", "1c62894e18d855b6ad0b4c724070392c4f143ec6400eaf6ad2470957bef4daf49419001086f8466d0e3812eece5e1560da9145040721a4bac1ffed1a9b0b90ada5c1a5bb7fb8422a5d4f2e32e77a657cdffb6d940ff121b354c319a6e482a0b74c9990f5653f4785dddd81754882ce818b3c2695e70179e7b93002b44e631f2083a2f5bdbdea0356a23bb6fcfdd1b960206965d513405e67893ed410cdf1b83722bd288245f9c213047d94c835c373371315eda99857a2f61611b1d8af4e330d03817f46f25e089e96a739ddd68105a9f3b4fd80f962d627c5a9cbe130a6326614fe42006df4f185f700a3300f90c7d0eb877d8b86aeb1d13587eb0668d4ea568acd14d5e34ad5dac36f8dbb8ac17827bb415019311c44c3cf36f205a3ef747f8d81ba36a606acff2cf5b176a1e55812df94144b563aee15d14dfd3122d5fe63468ddb740afa19df45bb450bf3e003fe94311a1f8e1d3644bb50de1874bf7780c7d86001b07586d860a8efe5893127a46ce2143b217e040fcc8b570e2c29d3b9afd75590d9bb6cc484be4ccc754e94a111d112ceb070d917b6ce37375d6e25a8d23cf00379bba9aa0e18aa0b832a86743188bfee470a5184ae045c52bc9e5888c127d2942e75375d9997e5d60758cd11b3ff79fb1097bd8172b4bec39f370cdeaaec44929265fc52766410e0c9c8a686f7028012992b0f3d44c535d7522dfba232b333cb03305edfb20bb987e45d97e8205708eeb62975bc256ddde341beff97212d624bf7f9c67caef3f22b1f469740f47017259a78987dea61d4e6688f53c7a1ea40e3a9c6d1947775d1b5605771f1aad0121c1f65442a9f62f5b0c0f45f44d872249f048033bc504fced521ed2ece04599ae432b478e0527e87a24d78500a8e87848b6dc9ecdb91377f3dbd0b08453459dbd5162402f70a73dcd921026bedd2d38352221545380cc4218c6431221dbbc6b40d4cdf328900142aceb9f153b58dc206b302583dff4816a787ebe0ba0c4f6f6740fcc0768987e5b394995d96d6e22efb993fb3a503222e472f8d930ef8793af18e4661055791d477eeca3214592953f2b49f3d7f925ed3e7c06c3c1417dcd5398ab8ede6a6a6cf771e7af3d67cad1cca1ca9690cd36761461b62e83cb753a7f798f171ea000bd4f2b35e82b6333b5f66b21d81fe4995eaccf1507e1f2848716d2865628cd5b89b7c4f80c406394664d19e8978d8b6855cdbbd6dbb79ce5137e8e51002493627c83026f9294045bfa18353b2939179e1dcb8cf47fda02e5fb9f81bf9e8af48afbc054517490382f34578cf60d744e1a6f97756ba93b762ce1cf5802a7b6dd752ccabd7e609bd6d5605eb85e8e87410fa5847feeb3ec5cfa0d90162420a2dc58f006273482dc824d09e3d0ce857cd62b24618856aef12da069463935f7643d04478a9b9dd81b500", .None}, + {.Mul, "6993e836332617959e792e1a915da0f2ba68aef859f6e1fd1fe183c96880b0b7fed53b1983b9fb361fa779b6b88e8d7c2527fbeb2b0dfaed59a6b5a29720281aad23e23ed97783889c3fb5cb3977b0ecd115d42fc2c9291dbc36a905eacdfd9df131c7155a767175baac40ac484a4990c812c2565b204b78e8c15f8d8225df1aca17378ffba1dd7beaa978ef60b3fe5b5285cdba5cec7b851a90da0ac37fb245133e5d26234f31439fc8c4e9be53c666bbbdc3268495f1b2004845b0e23f500337910b94bfa12588b499ab92be7b3ee51199b042b57633881dee4ed16203aec877ceb4bc7553d0519b8319e220380470afa89a7e856ecaabdb8c26e4536c570ae12954f35caa5fa8b6bd0bc2dd4fed1ff956b4387c116531b5939ac1d9e9a890d64f63972bba12abde4cd5e03d1f9338b2f72371f729335a1dd1db42cecf7aae08e91c11c35d96e831c2765118e2a396bfb33bb8cb64e8277cdbd5e78f69200631ad2505e87392f23adb601ea4bb53c0d013be1e069d2da936a0cf7132ae7f7cb3aaff1c6386aa5e919e892d4b9d6c8362eca6f73922d7a1874a974ac8f8479d5b2463eab61f8ddc2a90babfa8c0120ffef677ba59ec61f6e38184eb52860db56e88f0775fc95e50adbecc0410c43e2db955c70bcc73b5aef6365e7c1064bdecb893d60d6de16c20a3dd5e015e04224776d4f144fca9a8037c2bf9c90dacc605", "d19d593cc92c473830cf62c7d26dce2abec23fe03813d6df5f7e87e6339dfe5c71beeaf68cddf0356814fa366d61a1cbb0232804fc12f3618532c237847f099a45febf2c60a429c5363e4a7593b5f615c2fbaf27c39e3cab9d60b80a072086229f610666f462e756ca54852f98215ebb784f557cb30acc9072356755e23083f6f57f921fbcc7d7b65884f96fae1fe55514d225bead9998909ec0fe866b4a986fe452e84b880e78119fe6000eb1e0b1afb4f766e4eef5cf4ce9c68b287ded8e69e5d652e195706b0c579adf60d7555bb055714057f41c34a2b55a99a38b25cc5e2ae07b59e4de97ab3325d79e047baede0c9b88762c50e71e5eb5e627c1a87671f9a2bca915a6c907a66d4aef05aad3aa29a618fda4cd16252279ed4e5da18e71c6ec63964f20bda4286ef0a64e554ebd53eb5e53f587fa711cce0e4327ab938375dd719595ce33a73a2841a93a76aa8c14f098795a9c78f329289c2c18abb75426bbccc2aa12eb89e1af70f3230aaa9a9677f7c92888080aba0e9c9f6a27ff4239e081822f53abc45284f29cf7bfa13aacfbe6e49a68a79112cb1c19a9b99ba5dd984b7cedeba8fa2db625ac54543c087fb334744383469778a8856c692a0b6582fb2656f968361147f9663c0ba19e0d6c338114e1789ccabc183c654a76bd03006621320bcd8d0ce1817fcf88ecd10781fe6cb059f304156ff9a370ce5d065f", "5672a517265c203781a07419797c0ab6ff1af052e1902f005f47641d1441e3f40152e1cb328113a5e79c727305906191e54868c4cd6edca056ff704c41b4ae0284d35acf1d960e646da21614cb72654b8638043104a9e5bc552ef25f29cf0d1e96cc8dcaa106672c77055c48ac435f6be1e8686a0b92ea9a11ecbf57678ea19354960145d95c6ec7537c110bab39878dc98209fa8f13ec523c5fdfcc7efbf77a11fece29780065a0586e9eb1079416b2de0ab3ffb92a080ada40f436046c18fcd78bcbef28f758d263bd2929eec21591210de2c087aaf6eb7a514d3ec9e5a6afc57d60966a0d162ffb7466808d380e77e1e1d52abbc8f742c95aefb0bd97be4d23566b771dd13c5dc05fabfa0ad19a29909233fab56f43908924bbcdb275fff837b5a31a7d1bb4c973a136801b7cea8c59cea12d6e73daa8ac02c86b8c760567c2f851d7565d6c7bac873f407fa51dcba1bc03146aa8cdd863b42b07d848082471d2e7b839c11e951b72a9cb3179ddee8d9b3556dfa743d6eb4dc4014c4f46a3396f3f848270ae87568d422ffb22ae85d364dbeda52dd7b181a7b628fb57f5171c6211421b2c03a5200b3e7b5944fb436c053882b51462d9cd8bbee9c781fd28f6f96e7d350e4723798c73936636f3cd621426db1e84934e1fd84d4648243e3ead7a92ec273faf988945cefa3eb6331854e674227cec4a1c6b9de8300cb9203ae97dfdda19a4e30b3d5ff258f4fb9e7ba63e2fc9546951fb5182f1ecece8245cf007c857debed259f71b280b1f544ccb19209bc286cd70748e91702bbe6ceb025664de8e94dcf89a72a48919689596bb3daa55a3a1a1ec4d3eef4b117eda36e2879483bb52c10188767147559c5541b5ab5979a6a8eb7f7a9f934a4856e56aa13de2b3b8995b7edda736c31ebc53f457d9cf7a9d55a9b8acc7c11a25b3a9f46e6526db5ffc8a7e71a37a596467fd33578a9198c49c0efe9789e6cf25649f75d49d74af8d4c8571003790c80c124fc04ceb8f57acd0912af5ba84176c6c6fec96619822b31737bbc56ac0d5876fd565d1b2ebfeedb3e7b24512ef92d9fbac138e031c962a27d1f4cbce28fada17d63514615977e67308d9b70c0c2dd212eaf3641badb0f091346769b91727c819c6e5379719d239058cec7078f07104f8a21eac390bbf533f1198a3a52d20e0ae70dc855775dfaf0c6d3bdff5d938edd938c58112afe97d8a6f2bcfe5c345ea214b5e9c7eed1cf418517e3983cddee2df84ae45859feaf6fbde444918d78aff3210597c7b45243cd9de931a8c49d51d22f4f6a6d9571de1dea21efcf8f0057d309087288e70a4f39ec78a2cf4ff1fbbac1fba84f2044633b1935dcf93dbbf01d1e31faefadd7b4a941e8a9165767266aa994b4b5eadc46ca6a277807a7acbf9df5c60e0e5dff4018edcc22a66c0383a159299db", .None}, + {.Mul, "-5e2a6ff115789ea1658e93674bfdfa5dd43db513a4f8a3fb3121a9088bc27cf700bcfb791b3d333383a2fb16585171a7bb3aa8fd4d1e8d96fbcf820ac46376605581049962bd3424879d8509c844c66c592245a8229bd36e2c2db9254bcd3999b8d7900bbf6456847db802bf68a1aa9e32e0b7556cf5cf370a11b2224213a662d5b5c5328bfd950daa1ea2fbe7c700c4e1ae705c3dc5c0f79a869aeb89951b1b839a45edcccf24485d2fe0e1a8fc48085e86eb007a4676039a921f7416ce21090d18d79b4b9fff05aa5d79e862799152723ccf4ea594231ba1d56719dac8456883971acb4c42e6386b717f10fc1e13c9a0514dc21293945f87a048054a670b7198230caed139eab9f48753db2227450ad9f9ed414fe32270f0b588564d5528a34a66fcca23c41c6edd956f1107da32edf74725644ffdd5bf936918d29ce15c117e9a32e7a4350141102366970407b1c8796db4f428df6ca79ce9d7c3f6187739aa0e3fdb9c3cf9a0b224425e881e8b94fc40b372519442755e913e5cc58de21bd4f3e05e42a65f32c1012f76f2ffeccbac4eb492647fc6c43b48b02dda54c9a255eae84090e6a599b3c356b2e5bee82126709e597e55cada89e5068e450659dd769fc2180c2a234f380ffc0587a3dfabce8a24d794ced1658c15b61758e11940698b50b16524c27599df6c9e694f9628bbb61818425e92718087f3885d232709", "444d03a2f271bdb3555da63743941b332ea395b650054bb347ff837476f4d1f81ebf042bb70f14f080b5c8c0be1604212ed69500d5f773c66b747e905e4cfecd28fdf905859b4042f74dd14f00057d283c62d2473d69d652da6147e96477e645f8f6741467f7aeddd07e544def8b69da8b1bf75d5ed788b1525e4fdee23eaeb9cbf63a2a26d819872fb809e509be64db4e5314df036aaff8cd628a3a58c2505cd4b4df22cf77d49fe1df14fbbc439c80fe693e4a62fe51f706c5cb2ebb15ae54e7b222dfdb2b535f6cbc135ebd0725f9312bb8c112e2ea81ac5e56d3487089583382fc7322743fa1a25e98cb85d367118d041cf9fa9d3fd626fb495953d2941b57a3a8f5cf140df093286b50d117cb4fc132bde70931ad1628171ef8ada8644fa67b1c680feae16180a62f138d4f7f3cf70b169dce72617254ead9d15b084f3f15142ed4a26d8118bb7ab999a6204953599a69369d504924c135ef1e181f48ff6b864d5587e06855d08ec2e3ea86d88aeb3a0bb15a3753544f0149919349229b77549d1542076ef2aad5b8bbf1209c1c217e0352106b43b93d4c48b6b93693ed59b7b4e93cf15a95878ba087c5a6eed7518db7ead5762a76be8723ff8a3250d9144a194a7d9d03714176ad38ec2b5f54c456774c7771ef3e3895df7af9438f3e12c15af05c56377eb0d91cb174421b01e772b80cb68f1ec789e8489b7c6648b1", "-191f99d624901d8f3123fdb4ed2d4d4d6fbe33a5fd1d8701d5d010b4e73f5be1188beb7aed8a81123fa054370777758b9650199e89acaf8506af5c395a2835c9f8405a02216f2e0c96632c43f8c7c40fc42207ed113e6ce0b21780c7d355fa2ec85872b851b1168608c4c40d76f65b249ea72c53d21edee411889ce5a41ae4594bd94b7335b7f865bdf65a8dc77f41d26816c3357dc8f5ed40f917c19c01d375902d7474d451ab960009e2100c42f44ca2f441d485a0c97385a438cad5fba618afee53e25de3678b65f6aee6832aba64d7afdf880879c4e7cc62244948223c59f47c6453c0d6a54ef30dde1a4c3d72b127eba4c5f217d4e0a6a647c8332df8ab32d98a6a89d0f3de9ded40b584ca29b6b8d0fe7c6c92afb43491e6c40535df75bc32e1d7c055e9cf515f267afeb214a29fcb24f38ffd9cc793cc2f935ba9b29c32e277c1a8f82a423a14e40edc94f7e03876a5a8fb6cc73d3fb1c28ba3e05a7206d5d0f22762b77885a7d77528f6da268ce3e83f30fec5e8ac964bc79ac2485439d9c2826a17458bc2a4f342b583b96ad9a8a104603b95ef6a1d8912695c80778c3eaaa1072e4782f67f7e8b8f613d7abe9e5c65d5d3e36b387773de4b1982494b1c53c7484dea1d69b3bf73ef90c745b82f928ade8adceea5b2b95a9a8e2b10bf092c93459be0a4bba4aa99dc4315ad76a74d128f95ab84539ab391f8c5942365f3188d0fdb9470d6cf9a3f2b01ce0e0f028dc51fb41b6b3660a02520b2001124de69ac4cb7c8023d45d7b0e99e8f73f6a1cb8b320928836162b9ffcee63a43a980c8d87652c6a32c3b4ae258e53f90f0ae16e3a31acd14ee30e531f1bfd134da5fe09a0f1b2ca646b3618ddb0e6ee53a7e63872835fe7545fe89f9e46d71256f6161a9c67067968fd97dd4b0ba825dd63b83e266559dec81da42693011a23086bca3b536c2949060742a624627dcafc165def19d78ca8d000de1169b239c952a7254e12608e322006e9767f295c411bbcef7492d28d9d0dd1e8c371f460abaad3bb567a6d5e4a45c22c379ade13de087ae1d524d74f2a0f996c775ebfeafc77db718069cdc942b2d35abb576c96283202a5d67c61183bc38c30b7deabbdb1e4b72173093067658f040b6c4fab81dc5797c50ecc1f638789498354a03eff82e1518bfecb09915f02be086004c2eac8bb13742f9bc07e6b703aaf4d4ee739c8c8755bdfc0dda7ed4bf15cb98d3680b7064ceffa09c807c659cd851ba628309d425e402440ddb009dbd563e59e94c2349b1e9aa04c78ed7ce959ee97ad41ff159b269a09438a6dfef2d25338255cbe8efb40b1a71f705a11a033dc8204ede98d37db79c3d2706ee60f6367365cf7f9e842722193c9c80f3becdfd878ad5e2e2f3640ac7cf54bc82c5df0a94dc0f26c03a8ce72a2f4536a841a85b08d731de8539", .None}, + {.Mul, "7f30bd14a4d457d7d88ad1143c9bbfabe57ca63f72a9e7fe2fa980ce6067bb0fb0161ab0f21442ef55950df038ad5e3a1260903ed609e875feaf929affa933e6fca7625e680e4b43e6c5188dba834c9cf668c6f7dd3b57d4cf49afff331bbf9dc48e5e978562d6511e004f319cc739b1f6eb3307e9f4984864ac1b377f6d79ba6d6ca883914ca10ea47d0fd0b6ec792752b5afa8b198cee145090777b294affb8a9a58af64622204162ae09e00bca6428b2764b49042b3a74f4fee39bba626d02e68982f77a47eac8377358aa0d585b21d1a943f69e23076ea2af93963368da4aaff2e96deb4e96069c6a45cee94700d70bef1a3e2c28fd179e741e39b2694a577d7322e15071b8d2a1bc1b7c128c8fc3acf3b72e49990279c8cb7430fb0028e9640d874cfe58d434526940dce0f97ec70e98274a0763182c29d89c2c02335693291afedb420fb05e80dd2a1a82e9e8113d936e4f538e8ab07ba9080f2bb39cc88b6419ac02bde5183a23e1954208ffdb292ca42c285a0719a606409d4142c174dee11e2470df53e9df180a5e32abcc80314d0b997d41f068e86582061a174b67dfec285e27d86eed325631d5397689744de6816d874ef47fb82bdba2cac7e353e3b7a773c5efd8c2b454cdd07471b96895d8fab33249bfa988e7d3d859aae2ecde16304cc3f2be9a11b46446f7ba8f76d4d29610792f871b7e83fe5eac94c6b", "fd2c6741e47c9b1c13a10537784785c3b5410732d178b9d6e158565f7c246f82fa4b3f49462a1b8932359d91d0b868d8aef72e81952b334989f6bf9f811f7e339cfe2d421fe08caf53568978c6b06c21cc5ec41fb45d9d1268e6c17b2ca1c03e051100e971e799a4e8dc2bdec85c717348c64251ed5b8c094d509afaceeaf75a7878fd4f6fc998d19c7a2c9bc257ae2d5231a58f4c43e2bd93c5f3d67ef40f7c94f6c0e743136449b89cee7beabd9ee44b2401dbd5930ad812b24ccfacb10bd91266e9027e576a9f500a7907cde2b5d5af5f949e67e9e0bbc68ab900e05bb9afb8051fef4848d5fc6c3e2f6fead9cd042c2004ab3acde166e89140de2f04259d599a166bdda6fced4f8967e70d1beb030065c26ac310b2956b2921f8b86550326840925841c65a26b99d4f91a872494290f0307da2d0c44ae8b4b7317921ab552c0729688ea9b2b2a599f0979a28152528c287dbfe52287ac49590f14c311507268560d0ba5be8b8ad745bf9e72e1b8d21fefb5f125121cefebfd11a4707669df6446eca38bb7ee5561663c6eb37d793d8d5ae9fc4b08d2e2346b8f8ce4453d96bcffc8928873de3b33e7d02567bbe37dc85449fd3f833db6c5a5e5bd95a6ce6820f1bd6593feb61962cc554765cc2a97db2453fd511c04f1e4b3f7d38aae30fc0022b492ae8844c70aecd98ca06bcacee15202057cfdde6122dbecb07d68376", "7dc93a8b3f6ad0f121ba4fd71bb43736681dff3f63ecff25718490247526756766167b91f3db25406318c0cffbd301973ea6254bef4e94ea05cdea98f09f698ccf804f422993197e724484b15a28d1575dcf216d2cbff0f912be7968bdecd0b58a664c07a0aa651cfbaa289964fa60768aca300fb1d1f3a95f51004840d08fab5aa6d7e6705d6a40da6c34a3a5fd03c180c77b110bccac3f64539c3e8d03c88223b9124ea10fd083838a160eda0434e4de42de8c508c90134a6a844614b4920764f869080da69037337fcc976b558861df71c5bb01cc4da7f43d68a9194baf84e65e6df217599f4edeff7e8796709a417ee8e135acb51bc605f877b600773a39a51c78b835e39a938a4bfce6b0990bd7487e40c75d4062a2ea8781db34507d828af43cb9906f7dc5a48fad20f7f0a04bd92b62d006c2b22fa323ac178a4304ba9fa81713f10548d8f86ec799196b94a812bcffd72d02ef6d20c412e18c118bb4d9150643948bd0ab1afd1d33a8224b955fe94d5994bc96739cd70433bbc6eaf5e18ed6cad0b10310a78298749ca1501755c2b9a5939b24502b6b045b8095bf4e3d8da4a64ab79a95dd8e73905e08c97455da24590b3bbbad1ab2f05df7677258ef3401d15f016f943915ddb8358e77a6ee5c309843dc0333d93565e5b30cb8bc7cac109bcfa24ca26567b511dac278f76d5fca50a304021c45cf679603f5e388a9d665ab3457a90fc971985d187f609e8db5e454e2931118f94f04cad089e61d31ac749ff51cfde3354907866ba69ea2e2c50424596380348f36155a5d788cc397d4e7306be281bfbb035d6be75a05e1f743bba835707766b56215182b63d5d655ed6e8a23018bb8e01012bf60a8c4ab23228aeece456a0d8814bd455d92426228df7453d8beee22b6df69e4d798519d2bd4c27a145f6fcc745f24fee8831f84a1aaac784a0d7da218b4d7914f9fef21845e1f5b7bb1ce417d6840148d847dbe45889209c5b82347778f1dccc7ba1070b02afed04564d3877ea47392c3a7e1ce6d52c8291db15261d6adca1b14ef07449da1d8a694381934f67adc220885ccfed48d96f1d4357de4c181a98cf3498eac58a87cf1b0256cbba5aaa6bcef4d2571623b49c710b7dca4d86b48a4dbf86765d0e79edd2ef097a874b5001c2ec1cb6ef371f24cb4c1061e64b70b4a4abe97c3629d81d30d373b7946caf0e2b9d1a223a6d8297213e1b643cc61afbea6e3a11d7b1dbce61c0ad28f02f7a64fb4c79218ed9ab0e167846f67cd78cab93a963406305b6a48dfcbd32871c78dce59918d1b1d4f2331e146562336dd7cb585ad0f85cea2bd9e0578687816138daffb58a1964c6e0a2262adbcb17da8db0fec00ce4d58c0803c311b3d723eee3ee8963b9d32ce699f77561b26902a4bb478bdc68975a5ee379af7d38ee1da83e3550955fa52", .None}, + {.Mul, "d46f2df95f88fdcda55e6bf03465eec7ba12b903c6dd42d3b37a1e6be7a67eca6fbe36a5a80fbd8965f131b3cf27106d5b71a9847cf52d985308b374c11b80dd12fe43429d4d8deaaa4f0957b6f62e55cc9cf6956fec699f54ef3a4ac0e17e722e503b3114d8d2ab30a6aba68820a82625998164bc12696293195c3970d5db60d2fd34ea8833c2e87195b1db86fc1b3f38c0a07d2d89e1f56b22cee7fbb5b031c1c05d8ac854f052482bb0ccfb188175f6cdb8a8e3794abd68dfeb37cd85ff73c1047c93ce8131fbf83a7927964a6bae4ac76a514394d8737af3fef89266cc43f156c6be5efbaa73b7152ac1a869d852be834ca6d58216df6265757ad547a4b2a2025b1920d94035df083a84e594d7f8b41e9b0f8ef5ee315905f6d319025b3d98680c575b4579e1054297df8a8cf1a046a469b11a6a7e24be4d24a2c2c920efaa9ad59cc51c029f15d4e83f793cf7d32b8edb8aa3d8011c8aa83bd5704df81478615a647c664b619c470dc6e9cec198472b4f80071b3c57686a665602819fda1061eb6a81fca8fb06844cc8f1709c4508a159720111ee5c01466d81129f1bba1f7591a4c327e67d19319579b3d5f7e1d9bd196abce895fb8bebbff1882c5d81d129948d22397c5121bcdeaa1e41f96fd3d071c1b9712743ffc8a9c2e502fbd6dcb0d7ec8a94e650d74ac1394b86250fd3aa01edd7b6ecdebafdbc13447ffdd", "bbcdef30c24bb84aebecff91de63612beb06629f5dcd00ddf54b7a75e908e2863a96e7b3de68e580c1c479f0e453a72ce409e47a33675477051e8c87f2d0b1b062788e57b0c6ab44439b0ba724dd9964dbd00b8359172b1fa3f5411726107f118bb91f447f7bfca9576b5d0ed45b36cf8fa11c2d7f111723e18f42224b4fb2a2a2bfdde9c435d4241fddf8452e32c7292ff7483c4127fa831e39f0dad0eff49585be85b2bd680b0fb804e9fffab8673b16d619e24a1df41cbde7fd27a8a736828811c06dd76d338badd94566ca42058f279486434e13b4df68737b26bbb226668aa2f6495ab3a91a9c2388c5319d90a2278bd0f4e4f27a50645d384251d3f64a88bb40104b47ff22942efed7f15bc91e2582f79be1c8b61a200c9126b0b8672e0c08b2c8b1976ab70c89a8b785fdb0b33190f4c95882637ff8d846f4a197929e3485a5bb125ee740af0a7f5df675b8ebabd46815b031cd5e99ae6ec6cb9dc8145a48c943d01559ede43c1333fff7a2850f87d880d65461f58c4cb3cfc715bd6855d0439e62feed8987b75348575c37218cfc1b7055d42f243d3b700c0409b01c03266d4add989f330d60474383c8e9157aec317bb4e37657ad89d4f685be5c5f7343b1fff059cb3d2873fd822d2960b90fe6b3c5307e5012209103746d4aca4b1a659da773b7d2d27967995a61d0543f2d783aa69124ce9039bfe3223ef9b646", "9bd81a193b7a1762cb8607656b963af2560b6559f7d18b5bb21adab6aa5d45c1c7f0bdcb3cecc9503375756530c8d90c754b9882c44b2bb1da8ac70b751b719b8015d0f7ead1d6dfab3ac98d68552e684854dae581279d4a33c64e8f49f81d8d108f4b3280fe8cc8970349d29a4fb757d5901d9c54b377f6431587c9a7953bcc808e599d7bebba46ee4fa556414d45cade4d1a538eb26630dc5181c9133dee9ff71c82b1fcbda25a783a219da335e282de18e2cf66bb30512d2b3d52fe1fb70a32bd027ccd98da9e3f2b581872f116353540b6276c005fea2b6e5cc4964695fde0a953aec7f8c3023bab0e02747b7ad9b96dba097330a128899dc82787a6bdd5c6f83de7860e0dbcd8228d3a329ace0d472e91419ac21bb29439e440ae81062030b3bb612362bbf11f7750dfe9794c8a48c723d2f8b139d7a1c72c46ac57150194ecb5a57fa5af4abaf452173a8c6ed3be7e40bec90832189d2ef31542e50acfd1e1dfbc615a512f44afda03fba084d56c47997c2d68909482a6982db35603899eda554eadeb592b9a470d2793dd61d6fc71b76d0727a6ad8579b20ca7cd57b7fa1ab51f971317926848496f89b84de5f28793df752793fabc7c7f202cb4efd7c3dadb594e07c85ee56b7d09ae3a9099ed257df1f7fa604d44ab7b8174b449256231a327b26f5e3d2d37f694a3804e610a0b73c470786dbb6e0c0cf4945a1eca5b43ad7a5c6a564901124dd65347121bdb9ce3d9ce9beb78f92f08d321183d6c87b740deb05642ad4ed97d3b59e4acc9a0be954f330e9d8fb713622f7bd4721bc451097128313c8fc20c1d2779c7bc73373df811749684c2f5c8b5c25a5d1663747d1822112fc899319fee53d3744bc312fefbdecc71da6386a4b915147fe2704473c1d029ba66e55fbffdff6cfa5ec4db11b699b07f142a2dd2e088ea3be9d9915c5c8843b5aa431024b13c0d6ff5be609f78c2b9b3643e1dd7e0cf2439d0529ba9df12c14b5d48452516730687c70bf315792984410237ee8bca8eb8af25ee54dae5a07a640ebf0e57cfa3c304bbd462dabe9e6d9a89871bbc12b4a80563d122fdef143ad482caa5b2eb2a56f816fa0a28d42cbb150858b102a0612f702715e50ee88b50b51cff88b2203f9434b18602879f8c6702c207ad3b21ae57707a06f103049bffd3c9aaedfe2b10390fe945b0e56ce607ce295df4fc11ae5f03dcb885c1727d419324aa966a159b28dd97bcfb5b50e7ee7ae0816f20424a1427e0f6107f09fcb2e2d6e3cf37fb75a4e7dbd9db3c5bd1f270426a369d3e7c99bac89b524a0af093ceb98861031430c1281545079ec6d63d8257476f9d7da4424d2d28744a8dcb40e0d6b1e0328ab5cee5e58827c88c950d667735c1921d20cf1305046da30e4869b6a9afbcf4476d5630627f1128d5dad5ed427e63aae58df8c146e", .None}, + {.Mul, "-3eec68f8ad936024d652ede54dcd833f95cc184ca4052d3db090d5e24af0e963764305de77027aff06e4af47e04961ff05c43173e8c90877180ebd4b8328a3cc02c543055b48b3a5d3e2a6d751f7405a3caa85a5ac8d01e354fc0feaead9ed8fe612721049d6923d3f945966b54faab7f3275a5f4c993b0e384e7a4f3c6f1091c19bbbfdc0c63f71f8f1892c793710594f81ec44631894e541f0718f816ce58f32b47293b7a62a5ebf680621de5a36c42286b4cf02c130bb691557a90b784dfc51c7c220fa0c79ea04b5326a8b011d3ab4dc6c012ed4602aa01d7adcfc94c50f56bd06bb6a98b974c0bdbe77654e33be1de3a20b1e9e042869d27ce9d9b593ce858e122dbcf94bb86f4cb677fcb6349199163499da547cc8d6e0d1e6d0799eb008b8b20c9875034430d0b4c9c9f51d0a1b8b76811f4f0ca985a608f122fc4b84dc7493a109993629fdb630047cc8f68ff547d62153ca463c7d83af9183ea70fce785c61bf97c4678260ee4608c7d65d9a16f2de77d89f4b19ecdb0cf9a7ab0d8a3f678ba14d919e54dd5a40b1a47df7ccf7c18c750cfe21f32b1b13d155063fa3b6636ea5419e438737945fc69aeacc1190c43fc771f9008c1948fae4b8b0d732ad36187fa3d73f5e605ebe2912efecf8cb55652504f01633af0120dcc1d94f4be044325783e933116639e287e64dbf173b352284683e7fd083c4b02377a143", "33f3f2d65fc43e3a1ee8e2924fc54e35460028f9869c59e9c63daf0ba54b7aeba012abf7209a5c04b3abae3ce4400f9bd18c0e57d29e9707b2f6a58f2ce1930e4fbdaff84480e661df7a0d986bd91b63c4ebb9d4bd7e2e4067720f9fc40c24faa7166d09e902cc624475fb0a3baff13cb46de25f532adeec116643815ff0ee7d32b8625ca23de6958bc03007fb0b3d4d3751c46a2ecc45eb55bdd26472be55f7e07553393bf10b8c5b6e52e13dba453425032cdf0acb1274a7fd88cab6d4e43b68527b7fbce7278339dc4775570303923d7b52bc9539a999bcfb4646d21666bbc407e5e1b32cd73ec4c3e67561a3ef15f93ac9a46e17bff6de5a2ec1eabdfd043813cae68b79a9dba16b2f9a41f5799498210a0b35233a3e2f45dbe3ff2c76332c3daa846cf12512b32f0e994b6ed8509d8d506136d14625e03c55e3608121abe6f98ff00ccb69dd5fb5ff0a80d7e8b211e6862f5d96920e0d30c732241d093f6fbb02b9caea8d6b27318ad2f6f27b8756dc14cb685a481d29a11329df9cc023df181b3a7d6b01180a2e08f91675b1b56c6b026f84b4e2aa57e0c26b7279c3429dfb09418ea7052a4649926e560eba4af49b149a6e8a3d527955f8ccf212edac0522b15341b8578e129369cddb00ec92231b4508f656aba120af6f90159faf9573ace3cb3686b63fe9d86380edc9bc19a41055974e93a86b336a98cd611bd337", "-cc50f015b05ea423522b1a34a976be8a06479a6570cd3a607a016478c720c2bb81f6c7146ec17e2aa19470738d88efade9874f3688b40671454163f3deedafb7ffa5485c83a9027929fb42666c50b44614f87567e319b27e5a3ff4ddbfc41327ab8c1c396ad310b107b4c3e50563d98bfd4f63761d7a953a548465d224a812e7ea27c0b55c8730e7ee5f5b9b6a0cdaccd43ebd3a46e2841982a738676cdc1fa2d0bf846db462189da5d99fdeac299f16f2045cad305cc38c7ae7772199018c92011210db4a41e764305a4af5e779ba0e57ec1b2f44ac6863f9f8a4024408a2384052d34b2a9d8997501644a36f1838ac850b851bfa19b065934b73bdcf60c9251cbfbb374cf16d9cd796445c53af3e856c27bb4727dc2db1040b396410f042123e0ea0dad43a9c5bcd6e079e654bfc5d73f8c15f3397dff89837626b55fdea0f500329e3babdf8aeb0277e6806c91b3fe412a604d88a7929a124cddfcea1e71fcd9c150642d942320dc8be13b8fca4114f9dbc16c16ac6b35f999b71d2ab74964186288f81d26c6c102971bc93c1109103e8497ad24b959f4ff6040ab0ed70d5ea3de636af2b18f35fd72075499a98a55d74636b11e3c2102249e965d6e39bbbce466c24db7ce80e9d3386b8e10eaea6e8222edef539f45bc73c4005c12ac64e24534d1b7853c05e3673777c81e3d1a89a3ced1ea472e55907791ba99e21616939ddf315a7462967496a125e9d83aad2100aa2ded33b7e9669265e241b39370327f0a3ea512309689a1000872bc08c1679066f30719888324fe7ead05878864c69bbba47a9fe23cb3af894269a96c601ead2f1d67daa22845f79e8eed89b9cfafe7563cba0b610b450a8d891df7916d391be6664d1e8a5d962742ca9c0809cfac212af1c7ceb36ed20d639d27414c22f890761631e74e4879f0bdbc90ff4b097248b903b83f6f1906f4cc743bb308be943b3d6c6111c5abf591cd0c2c4a02bc6dd836d2fbd3eb6b0679f16ff27cba1cedfb6c373dcb2c6538a3f999e32e7bce0c81c18e1828e592a0b220473b10de9ceb3a4526ecc2662e31ffd578041aa6a0f88c2bc4f6d755020949ed93edd4217ef524c28ed22a2c060d3a2520d6d43595df4bec4df5583b23b3da97a19380889b8d8cf07d9d612653f284f1c77ea92690b2a56576ce398e3323bf1dbfc470d86752bb65c4ab659bd7e629d47ed2f66f48ad66fb1b6e296ef2fd8c2100c03835e5ad7af4410c06481e6cba6f798c67953edbd0f377e02710480aab45183112dd6e0b6296c2e2a003d30d6841e81ad55726b5ff7013493c0d59eee6e49d6f532e7dd362a02bf8762464e5a2742dbca4106a2c33c7e8c5d2a44cad3610a8e57c2606e6609c7df8dc7ac5cb0187fee4d9d41d375ffa77cbc2a4a8621fa65ad21e94d9dc4d65e79ffab8470ba6b729daede65", .None}, + {.Mul, "5c375f0ab322556a5979b80f7f8d0755a92a8bb0abc4d3fc6e01588771206b6a1384e42eaf98a404269f8de4699d6afcb3b5edd219bca03af9ce3c7ed02bff05edd896b7b3434a0c24c6c1e17044493a6623fda0128dcd3dab702bf77aa0971db00158759e4fcbe1a864f97759b4fcd591ce8cee3413b0ee52e49a5a61245ea74f145e8e7a6738ad7f6025e974c774d6be81610e0a7e9b9967e8c42e05c4bc782ccda2f1bab15093c060b0a1225e2dc7ce9189386dcbac4a17476bb292e514d54805a163a66c133821b512131a97c6b11d338b331161fe63a4aa97f0c1bb3b3f603da83daa687ad6ab73f1e2113c0eeeaa034e0c6dd0957b89aa9cc57c11569c68e51f156b3cb4fb1620e8a55a0328b3c255572baa9bbe71db0163a56c503251e4038f78039a3a93d82352011b69516169b123feaedeae473f15b47b7edccc87fcea646f838e638a49a67879de04c79c12026dbd67785970c996dcc411727a8592bcc7b42749a17acb2b734315fcada1dc2ab6ab0b83ab7e677e2358d5abb3288eaded6d4b84acc72bb1c35abf3299e9a6b2c77256d7d173fe3086b96e504b7d3c891e83cbe75ad9c5ace290f7e9eed1c1228386bb3377d072bb1e8d6dd163ce4b45b5699fe85da1bfbe7298cd43567fd1a5cc6c072edfea939537288daed86e40801fe30feaac1f9f40994592bfd9f2f98a5601c0c8b47ccc6a679630eb41ac", "51443a737f9e13176961683ac5e3bc433afb70992eeab10c11572a08b0c94c9085a23ff5140ebbeb6524aeb3fb2e90bbc6f25fe5042278361422d82cc2e69ddc395f2f7faf75bb6529e64b992c04b788bc8c7df4fac2144c3e39da72c18e6d05c5a125e89fc99c924bbcb71ab939505704bbe2a1a135c32b692de8c75a7892a68202386807e72e1e37549e1f7bdc02e5f5866a2f8b3a4ab49dc4d1463f653fecce4f4b643a86dab55dbf18c6bbadee7cd0a8e4ba6dc74c8536339839899d2412562c3efa37fd013731b6adef33428f0122cc19e7a26785e052592299abb648f6ad28052e3fceb9f77600f0704371bafb30e8ec77cb071069fc11272ebe4ce0543f37f854d707c2a1bf786e0128aaf0d1f41156e535f89b61fea887f168cffe285d1e84d4debbd70b0921943a4cefde319f98f3e7c8eb475161a0e49699356da45358fa208b0258984de9c089669374fc8f8cea77ce77c0c51d185cf43a232be6d91688c7c81815e492501c07fe21f24bb04c3a52991bee2248cf511f20748aaa62ebef7def66ac4a00839152714176ae3e18c21e9d7e3a498969016963059c1f00487f99b58b669d62474c2dcfb6d00317ab6fad2e0f050425ce21ab9e2c4650a2c040dd7e9eaeafa7d303aa0169c0c119609bae9cb62b104c3371747c3dece88358b1ed43ff8d1f37b016609e9f9de4462375123447b5ea528af9c960fec9d2", "1d4618d5c7e5f9bd18cb77f1c0455a909213f7d0181a3b948c664c07d24a5c83dac8a9d06bfbcf2875243c5ca70edd4c546bdb5eb459566cc0d544bc5b91bed22828f51ae967b48bd594a0e91443bb5fbc3163648fb3df02cf59c5e71ae464e1d99b1443b07b2ff30898e99fca16a6fb5da818be5e12990e62d2e11eb630a27d8ec8a8d9d23d930408e9dd6b2f508065181d08c100ce4cf8c068cc616163d5812b41f577275beb66d848d184c8a1005daec8013e46e5d8730600e2270aa42bf30b0017c6fb8d6d84b74ec3141a8c42dda323807dc65386144ff18c5164304f12eca32f2ced45879717795872383726fb896b819324e5ece3726bac4e4b5c03b350745c8b52280868186bb2b1111b44f21c3ed0c0f87dfb66a69f1af003652726e0bbe8fa1705b9aec358e1deb691d66682fd70a428ab78926f3a63711338f4cabde3f899834df8c078dba3aff49f1a487e596c7fd59a681116b9fa0ffb283f7d9677b037bd2497a82957769791d5d52e9428a823c9a8e08cd24c63ebdd225bddddc93bbbf974431aa628e7d11334d37b3a96ed34b7d97bb05559ce58a3985e71a51d2d6247df4993ffcfe573390617f7d65ce612586337903f23b178f16dff17464a59a07dfa2261fff19f4d38275310cc96dc65a8b3262dc13140e7d787fcd4b645cd434f0631b37a10760c933e3853c0c2cba59dd41f6d4347331174549f8269a2e8ef3c49457559bdb7105ea60c958f41301aa14b8aefed2ab7d4f0b234c35a61a257e2b252da4f628ab28c5114b33098344fc311a6b54fad8c07e432cd4e12450ef1b469f18677b82cdf09812615fca294799a87c5d85e4456734b01fc94d860c47ee35a3fe6bfcd0a03b934e5bf39f9ecbf8e20ee42751d1dcc732572ec929f715a83197b4ea6153398647ec7641c64b2eed9d1755610c22083eedff8056853b6a1f41591c8bcb8163282b8304021daeec0db9926604964261f92caff10cad50e27824e47851712befbd3ee607be47ca5ff6f5fb3a3bfcdd8aee5f84e246edc5d9804aa62d391b3dea1830e97715a4e2e845068e007f61ce7ad713ee20a26b0f7fa3f631fd53244431715969a066684c24d2fa78c95f94bb58fa78b5b35bd7c8168dd455adb6d863e0ba691526b4aa3cf32fcc558bca7044d9f5e0ced049e5e04c21cfbcd5c00b7941cbb8bde742c5539285642a2a8dadd3fdeadd3a6a0fe735e3d1d9aade7edacc81207599d6551220c604d771812a8f5ea77257bf2f4a65ec0293be6004c762f7e8282fc6630b4d97435f0f770c63c0cc2c243fb37bdd7c9c7bf963113f7a0cd4d3672b02fa626904c33a20d4d21816554928475e361297d67c9703667fee07cf0549ecb5fe2bf32041819f8f34a47333f218afc7e577d6251b07140c343df45673455afe80672174c86beef8ade0e4983b48033eb18", .None}, + {.Mul, "-cd59cfa41c1048b96c016b952bdbf97987420e989882ce46ef202c329319024d620ff661b460509f743f0e2c3b403e06154388a10793863295e97b0ea48f07df3cd84d13e71134588fd532e3c1c7e889949cf5eaf53498f46176fd0c21edb7e3f83997ee5e2c46e729ff6deea6f8690207915a7f63e98ca4ad39767c802df158a649c2cae82c34e4ed3c2e6276701098bf637528b056460fdad090b6745945e5998bddab06b93401e878ae7a510c3b551d3dd6245d1dd6b0cd830c364f79184f1256b153f7cde54fd293192369a82ec8620dadce41a2ca2a24b1c22fa477b6ce7a0781f0fcd3b7f29fe517374e983d2a6ca6feec919dfd662b243fd9fae2748f63bb6e5c9297e48efb741a81bfa7fa720333f20ec5df533f81f05178acec865da07b79fc78b6348ec234cbe5d71e21c3d2b3c8b54087b47c0f18112a4b6115c63b4c62042c62b2c32a8a0f7c453f73957911f0e3f5800ba3aca597ed57f174cb350a64906f2885e361c9ac0a809fdfc15fe6f3ea7e427711341ec5fc009217c7e3f64890c2d8833d9af3e40eb315b9dceedaddf6619290ee7c55b6ad2539d6606596dd813f66d1ac069e557346ba0c78a7da36c482503746296f41b68d8e248832d8566ac720969d03f9a5368f6d9b00ced41c6e86da69a54cc120bd31d7f12d07786f6784107e8c54405a3c39110be676c3240ea7b74fbcb3e7aedeb275a74b", "80fd6bdf73ac58a83960d01934d6d12ebe0e8a3834dfc59886f70c25a3e87c973beb98b47030e8c6bd72be4bfa261d618b0b955be06eb6f90bd421c68927b6d350e6b76fcf0e47b31e57d276b990117522ac2b4598e75c3dfe3ad63262eb2f520f46ba99c881806f9a50a9a129eec9bea28c2c69f6c60cc3ead8933b7e4d639a7c0bff3d36e67ca11d0d936f17b5b0441f02f6d0afc1d529e65cbf2811c497dc70607abe19a27337d0ca043946137e0478716d340d2d50ec1c27ba607c6f2d9fd795de55fffaf446a773d02969a68e2f68b5dcb98a97b96733a20926797d5a7b53d2cdf2bd27a238490d8ea001c61640f47cf201be66a56e51ec586ea83eb922ea55c02ebfc5cca3270d4059ec334bdedf370aeb8f02e3def36deeb2e1c143148663efe838656d22764624b69a5f850be83bfd46d0d411f9e8060ffb1f06f176060865c865a79b2ccda3c220fc141fc061536e03c44a79494420403b1b48e857bec8bb7ac3b8c0057bb20cfd089367e7cc934984730f9fcd0bf93286b1839596a689b5b91acfee3d2c688d2d7a7e0a998967c4b7a8115a59488246aacf9eef3290cc5c8ea5e7116788090d6ed724c96d0a3a13146d34d0826325ca5aa4615412983ddd8824ee3c19a81ec0c2c5de225db0466b497db6a49be4077edf2f641287ea48d51a416b911f5bc97d3ca2732e8d4d2e27acd0e53ec8e9038ee63b5ad98f", "-6778301c0b06efdfe10acda659fe63ad60b8edd6788511d948e3557d17f076fb7bb03e99468652c136d8a9d7f902bb76429bc59e652a40565cd61c438dc2c2e36030c5b0420de0b517b74d66a007813b4fe2ac9dc2bc90713af5e325a78a5c68a21b8e6a4bf45f834a3911df8c26ec16ea5de8e7a01bf7c487bff3f68b9e41770622a2a1817d85520caf25e35e1c1a7f708f9a32f57c1829fa0be723793b21fc2d255ce7726e8cdea9c6cceddcc0f72a73e7da638aaa8119dc547262cbdc2f2074a78b30361416bb4a9f5261fb6223bd7d588bfae5b458a733cddd4c4d726d938830aa773ef13cbed7be1dfc1bd7bf7ca6585cdc0e5e721f8f54f15679f1d0679d32d21456f02a3d5062e01e1745998426d20c59224b91f400cdaf3e11132ecb8a3adf72b653aaa2aa86f6e695c7d709c5fb635624132036352de991ef9a1c71be195f4a1fb5792e2aa9711cb5fb6ac7b2f09bb00cea6a314c7c9ae5225cd857f51850e2fa1a9dfe8fa63017807248be2e2e63ddff5fe03697c7c1197be7d0bcd6f81abbd89ff9b6cb3ef090efb00078d1cdcd7e3ebb670f0b800e48d3d663d0860e395727d89b2e37364edfb7a07c54c2617048022af99cf7ac0a707c070cbe1ae69e2c12e1d9bebaadfb8a5cbd571e59dbbdd18f07ba46e6d2d39c323af1741ed7d297ae7c97517318f17b108c94d250ee5f030b947b4346064ae99ebf7a0e6d68fb952d3e6733fd0efd58597408c55fc0da92006e949ba8dbb601f2c676cad5c14ef0bf5c2fe4b0dd89ab6e8dd476ab5de4abe510ae58d57f29207c8d65e4f301d115d051c48ab0390daa074c04b5f2c41c03b300aa96d64a34c25362629b62937c96690da9d76e78c9e1fd286bedc991ec3247bd6e1b1195155ee58c566bd6e82c176bd8f186aaeb84aa991b5774f53c964e839247591c0a04e9f90acb5540d8b6963aefbb7b7911b03abb5efdd69b8168f822f933fa086aac36e4f07d7981db3eedd461848fd3bbacdeea4e4a1a0b62c07afcc078e21088740939bb4d30dcf3cfecaef4530b3d44acdf9d30893d5b876a0da3d90d68d3eeda0d48e2b7178689bcdedf4fe1af0d1949a4ea2fac95c1a5f5647a1c54c662a1d9923d815e7b4ca734fd142cd190409a6fb8acd5a31532c4c3e87782807fecf76945d8b70494de0f724efc2da1ddd105d2a57cd92a8b5791c880a86fb46b8ff44b5c1048eaafaa0cf535089b56309f3bd19db0873114fc88c2e704791b1c891a482e0b80f8f56141a92fde33cebfbf6c52abd8be424da63082f533a24a6165bc988e7a42be5a7389701079210de63a42da48d2a35a8f44bb40cbe66fba90a6b0269c70e7ed8d6bb87bdcf2697e6369f7f9b92799a84478a91d36385f000ddbc7583931fc1ed8750edc8760840a423982c60f0530b82453d2ab23fa7fcff6807235f883e505e5", .None}, + {.Mul, "-bed8c90d7c61490d27cc12583f397f60ffd1d460ac34cdeff70e174c662dc03849c97b87ee587f8911dab6c03275d3daad1c302f6df3879f24d2001f556ff270d1d70c3fbb81200d5995de70db243875c5ea31511a51d8e49e122af5e8e4f1e29cdb04bbc9ffac69c72ab7c008ef4579665ffa4c5091a5b12b7929f43301d6e5ccfb395d574e180c6b883db573137fbbcf9bfb6d3b51e6f0a99e4e62358529f7e276b3c5a5fcfe4bc56ad56714ccfd7912226bfb00dccab7bd2b828b10484e1e0cb076b6e601c238df1917a4dce47b9b3290382df683206bfa7165700274862a533a06560d4e380768b0e1866d1ea0561517a8436bcefe868cbd341c04d8a7a4d11fa5674058e814f88f6b978bd189c52db982439dc9ff27c65420c0239678db2a3e74a09caa41ef9695bf26acf20ffcfae40a76c5fb9ae544d93fda3a257b863705fb4348126bf024bd2163b6045ec5235898a69e4dbdd857cd2e29be3a14908a018e1c8db07e352aaa0561a0589a890c501f2c7efcfb73e9b0456c9cef522a1904211c1bcf5baf1444c201ca03495fb9050e7231f307d9413fca79528be249a959d63c914cb21b96a6f380bc113bc69f9d7caccb63724a287d3296fb989c68e1fc5ce76290b5e2b20bfad01f71b3cef9fa219b433299375ebdcf47652b663370d7b20e388241df6190db015f847874e05c1920285c485768456801880c4ea2", "b9faccfbcba160716d798662c1ac9c641d8a9a88b780cea3c3b18878e851c4cc6f96ccff54f7264d6251a5f2c0f8dc8494df8ab4d7a3acd2de4aebaa9d2ca36fe3cb277ff5c2f5902eb80364d956d66154bd83db57f34276aebe2d112aa22d41a151a2b76ba9359430c32f545b0d8d3540abc00ec00ee850e122a9d8884995e17ee8d431d06a155e35825928994bd93dbae44be0c1aff701e3a35c749e369fe4229d831b1d97abba5adadc48b376fb24ffde7bbdc8604172790f643f4c6c120ac825dc82f2e186c1e283dc61905c50238a9a5241105d9a9111687d12d53936aafb12879e6782787be72ade79d3a7742e7bb2951c7f6ae7fa2371864b6883618cac34b1d7bbb05e7b257ed23407c64cc18e0e3bd0a035bbe3645773b11a33695a12e6d96aa2ce9b4a3d01b0c885d1365703e911a8b2c069119c5a53cbf9912791891abebfb2af6ecbd9fed4f5cdcebd136db69cb5041bed2a9dfde2bbe0609c17f5d8e97917f033c96af4c1afa19f3b481a3866a43da3016f09d8d14d9fb4ad1be5c58ef96ba584e0262ae73f9836a55ca60b1d41f7ffaee22fc00d14192c4f65f8d518c6829fad921d518564099fbb8b9c16f12b2c86a0c3cda051525b9bb873d41e6b80abbd0a238ca6e055f9a268afbacff1deb43f67e8bdcca9d738be3674a6d07a044738ef2f7520fcf333fc14558cce877727b80da9eea1e17cf5fc4ec6", "-8aa5a1cf8c9fd9cc5003841df3aefbe58fc34ba731d12d020143b022926ef5306a45d1463de35f633206ccd541d590aea32ab4be170d224c4f648371bcc2c976463671303672da1056a8963daeeab8bc98470c4d4fd231e7bb0103bfa774467cbdaa0fde3d1018826c02bd2cccede9380dad936daab75d18db8927dcbc1f73e160c34f5d8f1c2ebfcfa80a5d1ad20c5969df636253156b6d4a305f62883998924cb8625d254d9ef0e8f9961657897160788e2559ffca480da7373975cebc97e98c79ba03f4631a3682e4dbb25814dd1ecf066d8ffc10854a8a8aa5f703e5da693dd05f1ece8a1bc834f629aaa29c19d8290e80257826c512169c9a48292316a939f0c1fa11607c0e08b81631eea5b10bfdc2a91a083317d4831e1bf6cd56d484268d6df68b7801bd4a789358183393f5aa7e2a3c5ca28dd040419cea236c65491fb670e8976158f7fa6204edb1b7529be490b057f4d538e89b082d56bb5406ebd0587e83a4a2262ea414b247f8023108602fcae3bbe1baa5108a4e45ab92c160a8813069c99a9355516a626e2556798d502b3092019e912397c9f785b450ea8054b634cb495adb58eacd6f45624b29ecba0dafff419226e3b351d8940b2a836446a0ec4563b37b039c523c6ee4c1da2d9cc0376953fdcd1ddb5d564a752be18f0555f9be824364332b55e39510abca73f3db74e4e22524e4ad58b81d15ad58df3584ecfc33a6ca5418579d79ce55adff4e05aeeaf4bd3f0de9af306e9f2dd2c81e5c650f42cea802e460f8df339f70e1ba348cea0811cdeaa4bb1a1afd89ad3cc2e78c5b59ffe0a3feb759fadcd265cb0a9cdaa187f701bda24aad09ca3a170c8a395916247d7c084bf20b4bdb7d70b199da3e2b905e44d77086b168f9f20e304eee351242dd749afe452a4eed46b038ff88e95eeafd57a425328a8a2966d4f4c1506d354cb0ccbc06792cf2dc741bce43fffbacd8cba66d43bbadf17e586fab974b457547de3128c75d31180f59fbf46438be1a3166eb66cc1c4e25f13b3ad1d2630f6ee2d2ad6768b6dbfbcddfd7147f6289845b460ecec7ac6f480d06bf01454b97f99458df2db1c8b46debbc6a6632c36b8ece0cbc0823df484c2cc5011272c443a127bc6a0ead728db15000361b4234f7dec72215ac8a0ddea67c56864b20950503bf65cc8efcda0d066d373158c5ab427b036034f3f663d0469655e9ccd3927b0a9f90f0eb35202f343cf72451fc6f8e032eecf26f9b7285778d8a744f648c3a7e61c77c1950e91abe837f074936d54d591280da2aa2ac8ec816cd1d996201b015717c490e49bb8954dec8256a296c53625fe19fc6e5ab1d7a39d5dd148ac053adb0a2b2bbf09901e021a3f53c734c20aaca85aa1043a6b70205802385574c2e2f44016207a48368980a1d38ae75d59f9e2c4783566b0914796af22d4c", .None}, + {.Mul, "-9175e298d26aa95da624db39e1ac5c820c0465095b5ca14c3c0710e30cf346d54c598d4e66ee20721f460cb23de9c66cb708eff33286df75e94e8bf3fdfb4934c73cb058a03c01fdba042b0e032f4db395bd0534ddf111bb4c0d16de756749e35d6ee20b03f7a0907bff3f9a4f832a70277ac19f5340dcf49a760d10497bda616cba8188a894155ac83a5e0aa9c0a9f5451b8dee15089b6c32472f2417fe3a9cea7284e1f92f82718022bc407b85fc98d51022600b3047ed84fac780058a36d669931fe120eb2b07e603f14336a2d09a7dfc840a572e898f62be7d12d01e86b885f77c086b6a394c095db6e88a34572b3cdc6f576b7c951868d7c6365a29e5b8cb52c74c2f34fba3befd818c55ba46ac776142dd3c3393010f81bf00acd52955b3efb90ace975308bb8f56021747e0a6f6059e7d12bf91b43c09aeb69d5961fb1cfa8cc8d6b10bb90aeea7d24e92e51f93d17d1f9360e7b32559db5ba4a35f420a60489790ebc253c1349419694251425915e39b7cc99f9832ce3643acef0372ee111d6fb7657372b9983692595d087fc976d9069b05980cd2fad742da89fbcf045acdcd86f033709914559c7021543dbc05e0859fa638ae04aaa57aa63aa7c29cdf8c4768a565cee397010b2e8582e877ace7f5fb5429c690ac918604c14e38c5d60793b3a54b35c3cb8cb94d1f081770f987f0483885df6ba3fbc0f5cb0d7f", "582c5235307d5926bd876e87632d45182d1bac3e9ca814e4925ad9e287b2d36ae54dd0008151f9014031d76f8d1e806592fbce4b26bdf4eba9e0e916546fd56e7e7d48af33f5a3e3e9a29744b837c0df2bb799bb13452237bd890801458334d801afc9d6b48b480148f26785c11a659789c369fbb0548ab6113daf9c7d954976911be2e7161fa27c0bd7db62d3e033602fa13d2e3f96fb173b89340d2263f741527de4d2c6a9256ca317ce449cff8101e071fcde9bbf259754f252bc08c896f732d598501640637fc0631c88b0cf089b22faa046449f8a4bdb46d5448f7558671a946a2f6273ceae3b11ff36c32716a60a488221fb719b8ff06e32426568755970dcb81822e9694c9fa526e7801e286dd89724b6b24f46ca2f42337c394283158e54a0567619a2c1cca7b4c455d6c018f34a319013fbb05bc1f82906fe6bf75cd6753abaffe864f795d27f6f6c35c30682407f568786d64dd24cae356fb463efbe5beedaa19a46a385f37d5f0c2164135826de5c761b6390ebb66c080962cc4546fb091224a49844771c3ffff072593a35bd013c3ff3fa071af447b863ff12c197f122749c3ad180a2bb8cd84cb4bbb75ebf6193d991ca6013f750319423836ccfd763181cae84f6cd1b6a0cfad1dd5528f07b2da429b7fcb3ea00a7a7c4a631b34a64f5b03c1abfaa8d9147a08b81222d798a0f8309e4caf76bac5b105a9b53", "-3219b4dd7623054b5294c73c40c9e05b981f0d4c3fd43f5d12372397bf4574b78924e3af15ffa8e47a42f592ff8c309b9ca15dceeac3bb28677900cd310c6ae5d37cf5a244bf72933f85fa1753f0a7c74e432694b69a7c56207218712e925e7f333efec5f65a0a616e423f92f6edf615a6d4d9dbd63f7334463d264e56480847fdc3ef50ad29cab4fe9ae629422be946a183d09ee4ffd5d4e94c1d1b6d04fc6379315141d74e1d09c1f8c0f8667acba6033e8f156f96196ce208ea42ede7d61212c2a2778dfdcc27c8b36e13836022e565de3b4838010f878e9281d712f77d0aa70b990999b13b647f331fde25604e804afa9294f095c714b4b5fe980d6d4178aab867936382aa82793bb38eca4cf307cc545c9d6257b21d628adb4ad995efce12ee9c29c6507ad14e7aff517c8fa82cdd5f8ad11a82284918429fd37e0d7a39e7d3633cb257dc38b7ed56b4dffaf3dcd2177403586a410d43508f823180819b86849b011dfdc5f7d265341e04712bc5c621a3ecfda1c469eca308604be35f24321b1eda8e76509827610e8ac9079ccda3d2a6bc0fc1eb7a72feb3270fa552f0cf24180b52dd63d1a13754ff7b02f96433ac119f1041ab134e83449871e1d2cfb1bed2e79cac1d2c63df7a1a20b03ff46c07325e05fdf55b24e958de8f89c90332091c04bc2c4d2dda4f62abe793d03c2b9f636d593147d15bb0d1649a98607ce8444d29801259cc7348e4029597c920e1bc6001edcd43054ca062ff00ca8736338d30863228db5582f4ec4c3532455dbbfdf36b59f002c1038c771d111af35d300b435d5f52411f07f94d127097f0ceee9936de8c099a5125ae445d9611723a8069b42703d488ef1fa0d65661da2ceba0923295976505781545b1fde675b164ca1426c680de6e35773d097bf86f8433dfe192938aa655c62f178e8d27c1cc3ecb6f610d98d0167b01138b34db6f7f6f9d6d9f4637b36e2770bff40fe9764440d3ad72f82097faf5ccf36afa8a4f0269436855a832e2fb47465365f50dc17486fd0f7ab080ae1c77a8b50c25fc9ae20539b38c8ff79333c23b5995d02162e63c6b73fcbceee1bea2a85044aad1ac4e9931556df61c0beda87782424fb71209f44c42fde1b635bc67c746b71bc5ef470656f6392265f569c9fddc4f22e40e3dad0f8f1b891468a092fde59b85ed2f79e922f93ed2a1b74fc60cf61b7cfcb2928f7402e7c54c7cf513c606aa1cfbb901f765f9dd4c864f253449a8e8650f55ea2a12acbd8df03e0d2dfc11b1b9f9e1971601c05cbea864bed8760e247616ec741cb2a1eecb4855b7ce2abe6b326ad7a04cef538d70f870aa4177b3c72fb9304df18079c6ffb65f8b8c7fa19e07c8b3a07b93a669e4386ecc2fcb7bafbb20f59696599130aae649471794bde69036a15ab8d3d8b0b4c29a4fd4ba1faec150a7452d", .None}, + {.Mul, "-f730598a2b43e006665d84438000a8587de12033b05e78b95ffdda414b9d2c5bb133540aaa5e3a0e99ea3e52195d837b19a4255dcceb88f87dfb9b6830591d9d17c34bf1d8d53279ca5eb39209ba4093931e41c723c59243839c0f211d08b8d7391dc1bd0955ad1fc2e0664a8596e8da6a1a299494b40c5a9d05a6a777d6e026c2bc38e77f230a6c2d3d3bc45e6d8c093ab0f8fb2ecf7d62a84e28d7ba025ae3151d6a5c7d8002bf042c26c47bd256a241b1cfcfbc989fdcdad4f868d4187e09c2bc830acef29311239892547803150dcaf2b595186bc8a6592aa2680f9d5d6c8cb5510c3bab5bd1882264c4029c2dbb83627ae12ba0e64adda3230563d22cc8db14ef1a65812d8be44689529b817af6df0168a406416da59b2cefd904baf8f47fcadf95cc00d798dd8681a544fdaadff97ab7f1591ff011630c7ffc96b2304bd91ba736eba0652b6c013798c4287a98b1a659c43301af056a7f8aa02058f062e0c335db3e948736dc2cffa6afcdb14f9084924b3ebcb8c612abde11e409d172fa24db4f8ccc580f4cb197b8b08cb0fd95eed2f8b76f9f619f50b2ea553cd98fbef94f445d1d127e9d6bf34b2cb5ea53bd51a6fefb56715178a8f22ba28719bbe178d1303f82c1bbe3424fb4805b624c5de7e1add4112bc676fb1b40c9b4a1fd1d46ada707702fa24ccc554501172636d1c4b3d007f63da72ebe42567395c967", "71848c9f8718a2acfbcbf234c9999c33068e7f30541922ad2002ac512fe15496f5784c721b4eeae1e26aa045f4d46814f670f2906e6287459dd7dfc2fbd34ba0c37b3dcd173207c23b692e49715fc4ba890118987cc12cd53bcf92d1b58004928e8dbc42a59a39a611f4d788808c8162abf3b06a18835997591fea17e8e3ed7d1f01d0bb72f20afebe45b3a7cb0225acf2e4f31c53ac1cd6fa2a9e8c3f789c2f62166de35c8e8b016c36a42462a31c8014f5564235da339ece724cc1e81667423aa9ffc3da3be24e907b56f9654779fd3a47abc787b68a6aca5673b2e57a1de29715bd3f8bf61af616594dc258dfab8eae91adadec950f38cde5ae60c4190742eddb015628fd18472edc64dfc5229a1425fc2a5c1e84a663ffc2c8160fc2d718ba0ce3ffc8585cf9bd11408c699dcbc879facef6f8276184a0fedccf23138614572e544d083ca1feec79ee86c899669516c1ad9925c9c4f1b41158ef5422eef541e81e5f16d1948330ec94c490b5083da223edb21b1776ea954238ff2d6ea573a0f112dee987dfab1605e66759c947bdf26eadc7211a70fe0816f8a4f11fa7f6b971805b5c41ff8238bd5fe329204d5605af0900be8089658dc26de3386d6033d46ed35a85cbca2bbf928a85ce35bf334647f352400d93dce8ff8a03bffef452845077e8b2c079c3dbd1fefe892b753e1ffb2f665a255c493745b7970083894c", "-6d9c543ca2c8ba3036337a4542c7c6a047197c454b388c4bc40da1f75d0feb3cfa49f0bc74ab6a85f49ef2b521852717f22e93927155b8442911843bf55b672b1c77f272a66d987439d212db624783de642b0b6e53f53cc88278617347cf2fc51f8a0762803cb22117dd3e4724c8325d63f8c8b335294f4efef8dfc1b01f55e3fb5c94307b0e1feb389ebe4e780c5203d5ef9e3097336289c03ea526f01b4259d38a3da9fecafc838dc8110ef709f699dba6c48457b394884777e3399cb2dfd254adb65fa070a323f811a0ecfd08c870c56de2dc45241ec543aea02ad88ea5ac7d1af2a2afa24054d224388ae858e23600cc8687e5418e100ae46f4b73fac9029a86e224e2e759f6d88947fcff529b0930599ac6ef92c6e27abda33b71f35bdd47ad6da1e75bc59464f2dfc147d8bcb96d926168bbe1eb9b0ba3e82ca6a7c289a5c371d4047d0d07ae9b04aab5125cb9feb7dc367d9c3e86515df75a768f859ba3c37461e04dabb38574ca4bf45cfac1618efbd6a7d52a704dea93974e2896ebf07466c23f5ed7c6a4792591831736d72252e61797e500c940cc35dde2a9364d96da611b892cdb66c2135c9133e2acd328e0486331aa5b8808d4de5f292dc14f7b1976ffe07092ebd88563e41e602759c4962c23d0a8024959135d0e2ce2b04dcaf6de437352cd8a7ce452beada40ae126d247e2579fc5c119ec411a52e692b1da2cc7607f743873aa049c1155c0d72fe19a87abac3757627db92031cc189c22d053c1cb09b79f42b0512e24d0f84e7617726c4116f7b4b8710f1f0bc9b714da240015c0713b66aefee38f395d21169be8b053d199d25543303f72890d62c0d35e04c34f5729c70ba4ee86467e9ba339e06427cae795c9a8ed12aa19736ea721384da721832287768689e67f4e63d6dced41dca320e7103e028a9f085cbc4157b0a99c7b0118ea5e0123777a628bfc79de11e6356d810c6ad19f98def792e28e74e31bc9c7d7dc867b0479441a6f672be47854560ded30f6987ea8f64ed40d856600208fd48e0bdb3c812290c92fedcc8908826dc97a8366b92d9773eea81e4973de752bc76de19ff2bf9375fb6e67ef61ba02fb34da9e354a8cac7b44d13e103919d79f89166e8cd1a2b5af919b5c3bcdcde4f037b8e4056890f70c4916d037678999dab1bb1b7f0c636a5fe3ff071160d3e0ffbcce7d8f14f81d1b43112b2929c298c38227ba686b1fc0dc5d05ff9fb8297ef22bed989ba576837edd9491c20562a05816434c9085d94882eb242f57744a30a9882093bde3633144bae18afe767cc0f70baeae51a8e20263545ea7d9ea3bb078a597235d30ef6ad7989b088d93d05f39b9d8ca27d40a3599ec21f2e82746da9d84297a79c2b2c1fe8c11452cff88fdc078fbeb7d475062f7af0ec55afd5da444d46766a34e4e87ec88f4e994", .None}, + {.Mul, "-cd0d88d3e283e53a78dee9a9bf4bf4634cbec0ca58ff55f0017108ffcec1999036fcc9deeb7946e38dfa61bdf327d1ba1fb444b6f5a91bb93ab6171a2f48fe303d7d25c7c66f96b5ed5d2670ff5ce4b4cf42dca4cd7df97fd9ab920ae8f74d586510ceb2aee5db005871b89cf5732872c59d873c3ea9799e537f250ec51ead8b3234a081436713f72d36e0795a2e19b5fc6379303f45f7e8c99a1a581530771d2fd1155c1a85d42b94f58ec0885def21ddeb05e5c8648383f3b65b5ae6d852c5d59cf350fae8f7e381395d11599a5a2b02d3d0baab59a1fed584f96ff0c890fc3d63295bc4b893be85b95728dc1f6ed84bf0df3f90df526675329b18c95c14efd8bc543515230a4dd10352a02ead5206671296fa2aa49c53093445a5dd67c9b0edef65e6c43f4a58da167f2629a883302e5a8b429540a752b486a7562a1d5ffb3457d7a42eb9be06136637e0ad2f940bed65218637e68887c9edbfe1f415f35ed25bef66777e67f2aec005bd152849a88e2c7ad7349674b0b989e1491cefc35e8b23ac153615b871180a49ddecc0d8374a896df104e317810a89a7fdb883620dc3a9cf8de4f4155a04a17be5223ab282557cb66f10fac22401dc37903c20367686709fc50aa559a0a38f0cc631d4f5388af2e3b1ac623e890caf8e3110d943cf4b4630c05635a638526eb8b47c78fa0a4922d42c5cecfd475df01904041d301e", "177eef3479c06d03dd5ee549d63319d33104b3dd92752285123bea92c6ebc82c73844793ebc7baf5aa1d178f6d98ccde135e3b7deb75beabb29f9aa236d9bfbbcb1c293dde473d2f15d1d4cc757750252d077614dcbdd28b143a9605cbac572005a07d26c799bc8960dc1d7226d58961b98409d3b0b72f4680abf7e29c7a63ecd9dd258421e565f9b9a4d48daadf526c5b159ae92ea8da34d81c7f8d05910c94a9aa20640c73cbc1fe4451d7d817c75517b666de1b01557de4b102dddc0755f187bbc929248aa6fdaf9b9973b44fdf6cac88f61ad5ef97ea594837156a84c6e1368448fd1f3b3cffba77691012cc89380447450e5454dfb189431d9082bed8cf129d4fb608821e51a3e610f92bd30d328aa7893a6e9a8a8d66388054b71d8c2ab12981458e8b7e6ce795e5553b6847c5a770a148dc522b892b040ba74ab06ace97ddc6fa09d60154105d5240738f569c347c9bdad0f8d27b5750921be55872c15b8a95c530780d8fd708ab4a70d1270b07382abe9eda4ffbbbe5d2f5f19909b9a37267db913d611b42873e070ea01a03488369e1c410cc30a4bb944620b9bf8fab0b5e2357db47d4cd44b432e672a2b0bd6e47dc318af6628903ff613f8b96a5151a3dfd6d45d8be9a27d46da49485e8b7e3d3414794de10afea78d4a9981cf6a093dc174804153de233ca80b4062bd2374173c76c1c4f22f1aa5abf11f7ed37", "-12d1e38e0ca6792ada25695fb2775950df02576f8431a1d7c4c99f63b217261c7b8ce54bb1959ca2cef313174fd1e215a0c25362a903405d876394ed7267993119a3542945e4cdf86946f5993a14a847511300ba22fbde7e413a26832e530d224b96de06f30450982d1e370710a337aa248473541f70e30da248f141abbf18e6c0abbb97e655b52360fb2c2fbf55409b5db39e117dcb14b3ff33c8091aba8d54f7a5aa6a0133bb9e3a2fd16be990d7c716853219c2986b9ca6e703770dd0f63df62d83d764f87c4d4daa2329cf913ad44ada6858a7fdf8ce5eb25a1824bd52ba3795f02de72c51bbc050b8c94739cf7d3557cdb407f0d66ca3eace6ac393b315ab6bbd5663e6bb1eedc2a83e676db245caea61440bf203863f8d71e8befa8db560f8143dbfaf8dce0c9671b96e44dc89bdae9b629263f934f60e32798b036e54183a95b4f330f069a0b3af5d2ec5dd276611c17b7d0da94236c0ee66d2d308519a15edc7ee82f6fc96ed6d5deadbda0e89864bade7f9a26051418038fb22fcf8561b66b83014920c8d469e42489f288f7da89e17d9e4c5303a2bf9bbc6b98e55847cb1c7d80f32d91f1fd67f8c77bcb0ceb2acf51d7c095d654e831b8bbb51919fd7e38a938d75fcd1880ef9ff4a6090c5c9e1281266fc227c3f2945142547658b6a2e0a89433ea9d3381b3c1ae17ae5c72e5599f1ee2edc0f35d8a059f97dff2cd63524acd1da2f7342c2925b209a017ce9d55926d64add3c344b975f0964b74ef0a9b463d4f33697be150448a9644852a05652a3167f9d39b863de5bc7557d312d43b0ec05267d9c11d62fdab8b22135fb8f5f7f6490ddd49e47257220a8d49a5c4b2d6d12edc1d4a235e36d50c79c22bbd3b35cfc5a7ca5a5f0a7f18a09466f7ecee2ad65a6c0561f6b954afaae118517a89b82f90841025d4fbb0c61f4fc7a7713fcf0258561d39f323369e93d659885b8de08570961cf02cbf7f3adb508908a475544c311e8f57e5c70bbfb537bcb01b7bbf19840479c133bddb8011ac667a794a680fb4d91fd3c2a897c393b6174343d388d058d53a938243b0d0bcbb7701cc3527ea7b3a54d19bddcdbd1f46b344ebffb0d81443c70f42895c30d12ceac3138955c00801559e58e6ef4a46ce7b0f6d4826425c3cb0faa5366010f2c5be69ae75710d306aa9f879cb775ff2db24b3e680d09cd1819f287677979ea76f7890b1e0f0c5c93b1033050d8e65402ad7b9193554012694dbfea4293816b9e77312ede5c9fe2b1e6c72ffb129216ec5f6a64094959fe7a33066ae2c4d52064074a0ce9f4127a24e9bcd916ea2361afe0b1c42123d9bc3d505f41e969e0fcfa957b7222a5e46edac8088ed4907d2f0788bf21f8c7e18498922a5010607346d5cc2c6398106ae2f4f6362d5d73055a21cd9d45b9e9d6f7ffb96381726952c31c72", .None}, + {.Mul, "a376ba7d677dfdec794de21fdfd868f164a3057f4ff02f319b8baa8e73c215804ec27935c47a9ebdf7b4fbe22a749290461cd31ac36ca99dc7dda89f61ce444bf46118769c6cc4ad9c7284d233baed6e4178aa343ed5283fbc9b7ba3a6e837b33a82fe06d5fdd1c6406f80ccfd70b86c1988d396ae5c34ea454130af6d7ddfd22cdb5efc82a7430ada0b8ff0d5437f3023e5561f21674f1b11a48e21aadd556506ce1b7c4e0a0b37a3e8fb04de097643f1a30f68b679805e3ac084a2e25ad5693b63cfdb44a41f699c4ef2d45a2fa850a36d54f0aeba460be2cc45f6206bc28a501369374596a3e0fee1bf48d102c4a8515ead41eeea18ffdddbbc49129575c2bec87ef9641fcb0f63594d66de5ee4d2429e73af8322dc2d03b8d56c7fb034850a3ec6c76da7103fb06fc83967f0726f45eeac0de4727369f362e205c8d717fde0d7b2473b68e5285ddfb8357fcaa904f6b731b73f33a77c2856a4633863ceca5331de35b135aff4a9228df3d84e2a9be7aaf7c6a0daa3cca7d0c371a050231066dfd410dd0ad00a1594236c6b81709a4a58e08a2cda940f8a84cdd82a6c1f0767fc1fa322706ede8cb15ea8c327c097802ebade54cd243d57d447c878a2dbc6890cccd13c68554c891032ccf7388f7314ae26582a615cee37b55e7cb4973bcefaf90ba860cd3601ebdf326ae56027dce0fc2766e450d2ab3810e35ca77b91f9", "97e912b1f3391360f698dac1bcc60fb07319b01f2adc93dfb1d323ed3e23287609fbcef3348bb414609687aa3ca8b2aaed25dbd814cc58fe68900a0da6fe21dbd209ead7bd32c4c3dbb90df318ce0410b7f40187b269ddbf3c3d0af4ab898f421dcc6845966621c8b0f4a02c35ed04274122b4e0ebbe04083f74b5c7d611c0f2a3b302935154fa488b7b95e50318407081d4408f779ea9247d22394f0054640e1f7964f247adf13cb1bbe56202af7acad0a20ddbe1e03f37669f974c04980dadbe6e932e04fba676c52d88a875b7fd20423d851b0c959afd5d187aef5afb56e3e3779b865e0fc94f3656bab131857a3fd5cd554e7526345a865fba0225e41ff2f70199ee6859c8046bd1d6a445be30779472ae6de8ee58b8091ad4013105c2bad61acd8119bdf3439b866663e8cce87a8a4183ae29135f488cbf655a23b9b6f61b79cadee78a2c8241eea7e4024b9a71d4686179593e0f729f7ead9f590d231e3157e0a9a3d7b01a97ad579f87861827498f7fe2710c0bd530a8330e25a36c1e3fc6caa34c91ec35a731e7420fc04805e59072e25ed77cc46dd15c8c9951a6794d5cb475583134d1d7fe3dc05a033cc1aa35caaa8325682c44449dbd81497838f5d9d7abd43f6deca93b2b7235d8d3040d8e2e06592d4c6f4a47461ce5bb6e02579ba88f4c5b27889ca431d51944056ac90d2af38dd8efa4ec605c37a574c6a3", "60ffdaffadb069424aba1b772a723d9807de3f19f8d15b51e3a6f8b39c87d1afeedaf2d9be616082e440a172ecd95432272deb9a3916bf25b46bc9769487baeddcf27a9e186b91e9f5983067c46efece69f83b13249a584629bb71fe52803659b3ef07b8a83b7016143cf2f0c94db929368f74b2792e044ef1b70a9b2ef15900854ab73f1cc468a3e07ec89dd01862a7d3116dc99588787d61e78c4d663c3ca3299c96c64ca019f8065b588ae2373a0d00ecfba3ee24d8317c053cbc5393580d50465b831c4042fd0c22c4991408f4cb6cdf70f6fcb48c66491829a22b5e08b324ba0ab5198b9917d6777e4edf84c591fe7e90da26257224916ed577f7dab0bc51759d7c8c03a66fc8395c9e5749a49600e180a85f0befbb9fa1114bc01c0e97404b951c621a6c63138952f1934f993b780361afe3c5bbe67b0f8b03a732b8a6b049b590cea23139f93ca4ccbd79835f558e1d4b9eec5ca022ea7d692c95e1993cc30faa170f176f6050da86a0900bedcbe8bff58824a5510b86818b0add41951c6702e931ce384ed79190e6b0832d055f9f100c6c27d82e1d26a2040bb8796864309f32de464a3d5cf3afdfaace862e33c1391e5799ab6a9316c3607adbaa3a8a0df1aa10ddbae13728edc7f7b29b253103a8e0b1f3700a3c991c89543514792c45edd34bd8e764c522d7d348d56bde44f0c96df1876d94a2096bc59ca694faaf0efbc146f30e22ead6dbb472c91fe7ebebab8412be77a65cfaac50142a7a20ab66720b95d9f213d540c78826bf6eef5ab48c0f3862a5a36f2a3694c019ce046c0ea5861791db175384d766e6a9edb5c77dfbc8abafaf6019562f548a1da8bb5ddb3a463f1b316e7c9b1d8e41077655402d99c59411333d2c7b023c22c62893f2805217724001199b6a6dbc35b42eb549e8036752c4784d2ad4f542fdd61c1b4e818b2a4b8bba0655afd83c196b8ffc15bb8801ff59ffab856c5b66f0842c8dcf766896351d7c4742e635ec237e9d26a0f533dd10a3caabe91972d61473f427ba4c8a2a006783d1731fc0c75458d9ff548a7b249f6c976f14a38fd852c1c8dca0c57b376bfadfa0d75c379ac273aeebb97994a5be5a6ddcfd06c59f919b9ab794ededc626128f4733a4e55cc8e26dd03b30a51bdda221e46edd100fc1a52b35ef9e3266ace841696294b731abba2590a511a90250cfb343431bb146c511c0a4da5a1989234f82651e0b3646e797bbcf740ac5ca9be76879f8fb81d3363cd88e2afa9865a224b30c588c5ed00449229cd8e8336a6b691404a1344eed1963d6a129cb54d45d10d68af8709b4e80ae1808ea2f536b99f38c95d27cc2d3c518ef43d5f96d0e2161cd982bd13408e35bfd9449d2fa78a5c6950544df8b80c2a544f64f468e028643695ac529b434570b84e61c2a8b1b7522b3182deacf1ad868878b", .None}, + {.Mul, "525737b4ebc7fc678d206480773072e344de98f11191d780d83fa986b11ef397f16f607a4d178134cfc7b0247dc3ba1d46e70ea0bce77d115ff966ba247fd0f2662fe3bc042f71dc87f134864d84bea038967a32ac4e74c54df6c3a112ff75584a61bda2348aadf6a890085a2c799589435550bd8359832acb625adad6bd503e55fcfcba8e8d4ad174b871c8dbbbd5ed3e233266c72c5f9284301088378abad922916dbfb0079c40bdfd7102fc0f2d2f9a65a9a3fda8fb5f57affd5b71612add5b59432d3fdd40bd797fa1c654df759de466fcc0eb41525ee71569e2b7840837b373bbd5fb04667a4ebb2c53260659e9306d7964924f02e95b42db8af3a69b40309f60269799e632a124236ad5254a2675961099d12dd826ba80319d64a5971209d7bbd5c2d9fde0d2e245f3370cf279419bc10b8960cae285f2a0697e616936649f3bd7a29774736cfebcdc2e499f41e5c280ec15238baa7ce3a9fe76371c46b05dc5b92a5caa9d7fb6883af3df43017e72d2c273fbf4906c4dd94ace2beb73f20e60ca8dec926f38de9dc5873ad832793aba033fcabc07799781aa394cfb6966055f61265f952b49f6bf37c02e44c2b32ed627c4ef7600a6ad20a503b12571dca20af409d1c4bea6959b2661aa4d0007ee20923b6a27ba22381fdda3fbf8afe58523a749e255a8485c3b6c5eced4f9e942cde3fd7e40387633256da3d05b77", "cc063cb7073fb7fa4c3aba4c1a41c632bae3f6ddea5069713ef0c8498c55c9db1ddef1bc2dba30426b83e25a84dc970d3015a15fc9b49aad32a63f3de82246fd8dbf440f1e93c20c26e7c73369252b73e2625f7e7d418139ed4d3569a2e67a2b7ae89a3503acb5011452abe1b06018a5040651064d6c4af3499174a2b333c8a14f3f902796032b219531c425fb5dcad9c55a1d296e30560380568d0ee31917359edb12565b8a6ac6bd787cfde949706ccf6f2db1c4dd45688dc92f92495d180a88bba26108b78e9bab36580525a41d88d67e392f09af06647275ddda2fc75bdc0c9da3eafd2d468bb9d156ebf7fe0d4c8695e2b4beea7b03227edb650d9db2dec95bda88afe96825ab8340ed700339f81c4703ba075dce200ce4c77d17a0c52de473ad578fdad641e9488df88e258921ab47438be4769a885db6831ba69aff7001cadad89b256b270cbaf6b784f704fd1743850d678d8c167dc16f5d6c1fc69c4ec95c2323cabd9b8b25db8e86966d2aaa01b5afbbdf265c966550c401eba746b1aa8615f984f47c05354df6fd99e91189caa0236bbaaf9d01573b349d9ba79b523991da65206a86f0d68abf64475c1ced5749e47f0f153475c3f3bebbfd89c28340aacc802243d3ff0147bbcb9f65ac06ea00422d469f07a48978d9517f30a77fb04554b6776e8a1b3a1334809ffce65662aa28c49d0d1a76546a48a3c63c79", "419f81f6c9dcfe935c7cd3828a9245ff185977324fd420ec16640eee0f26eb9d5f636ffa37b4c3480a0822d5e104789019b071b0cd80bd3f2d793142e0acc3d6f536a97458de16bc563c5ce687503bf7d825778cf38bd825569d8244a720dbc46c78c8f6adcd648802bfc36a0685fa2663f0aab53e946994bfa9a616a8c8f66b00a13a597aaa6c57129d8e0e78e988c15f630288ccd5925974d2dfbc9b0db24bfa98ba6027103af0d7ab847f2dabcdc63dec7d0315bf2b0687edd323408bd94bc949786acbd75d1ebb4967527d55de8802fef4e5bad5f509c30095f5223a5fa612416f20d173cf3260f3c2607ba4ffaaca3da9760b2596c1af26fe7bfd449e0337d1d65e021de22288dd4f0ff3b3a1f9f54e73778d1356f9d33f2e42b30c8398dde75dce90a220647cdf2a347749366680c3c16d9f96048eaa92c8adcdaee07c6113433caea7cf8a2ef6d879d24c3fc288fb7221f2b4eac2ccdd9c19c0240d69ad075a4affb7b101a5789b0f8240f25bdeab64603c708a24ef967b0250ba81e9bdf363cfbd74224e4a6d907dfad5556b585acdfde61bdaf9aecaa76e43513457db5bb80d92a51d6be2df305e8a3835915fb73047b656032a6272f61d014fda510bbafb687d21ea6eef981cc39889c38effa3b625a1a1bdcb9493bf397e88fcf4f92f802e34856096aae4e33916f7ee1cfeba144fdc36effdee6dfdfb53d907e32da2d13a76d0880c31953883708ec54c444d05d4e8f0d752bb6e36dd1a15f1ca84af2e2e874104d0403a50db2f5a4fdbe72cb3927fea48711dfe852087aec9dded18d3fc8b4e6acc14a7e323f095e747ff2925b41ba52145ac8d90f3f66fd0d638ed47998cdac9039cf8db9b0ebdea5f65d7ff2c3584de493f33a85f41dbb7ba3ad72cf3c6db5006a9b23225c1a0450ca64c93dc0d66feee8ca6ac25c14b05cd5456a8d05f1e53a7471b353be967822168e07194f6ae659d0b2c175eef046759f1592087d0bd4a7a72836d25a4770c1c4a0fb1f73c3dd2750faf7cdc58551d5b19e04a36fa4485eaa9254a352c67a11e7fbaca1697d60c7000e7d1fa062217aa056070c2681ebe01ecdc810a26d54e441d7699689ee5d9b24398a0505cbdc46d37c0a912b79add3b0605e1b103f19c90bb9839b53d45430d75c9cdb60778a07b2609792d8d08f1c5483f839ecd1b6451306fad00ff16db47b772c060c187ad0ec5708e5f7dc88ac5c860da6ba56ce7dd850734ae7d75782272a8a5fadbe9a202e6b380edb8f26aa81ae40c784dc19dd9f8a82e98812ceffa6da75ac6aa5d09ee28c85df49b0c38628f738d61129a8e9207939fe9a886745bb6af1a00510191f550982dc5d34f4772d1acb5740d4ddcfa6ef7d3c7440c3d92cc6a480f0efc4b837b3f636d9b65ba20b04aace0ff6194be6f48ab6cafce9f0ed291c012c5f51f3f", .None}, + {.Mul, "3887f49d1cd2e4734fd90c240bd9b31757524b8f903831687eca1180f533d58680e48fc080d21e4ea0c2e3e7ed29d2a2eb6a906259accb67840af603867f36b9459b7c96a865f980dba57350e65c6b9552284325e63bb3d5d774a191b878e733c0d6c6832b7d897807cf00fb5345e08cbebf88906c8cf6ca149e5fc053b4aaa7e2872f1af7cbc5d27cf3d598dbe84ac6197be9db504f7863a7e3e3b950b32c76e71d87ef234ede6ce608f1f07083d4a69ce6c8ee5ed6576cc9335ca5910474c2a48783bc11e2f63ecb3a50b3bc9baeebf9de8033430a40d33e8f697e7fa3a76ffe53d4eed2c4d2ca4e61179ae01312605b3bf4ec3f740f66b09d3706db47d2e42fa6ed0c6e455a09a7547e388f37c247a2259fbaae7546eb0a150c15199776bf5c9102e299d4deb81dd10caf0339a8af8fce1bd293193c20e12acb4aa3774a4d4aa7e47e3a9e48dc14fb9ec023b7c77ec0fb7861c701897db2ebd718452b91983f3ab14778a31f1fee6e3bbd38513389819fd15493def41ff7bd3a4fbbc65a759558002d3cd079af2d1511abf57c0f860109cc0ad89e1631d26218c7d3ed9b4bf7f112ee7af5bf06a51a2cda6472115b563dbede9b294bdd121fca99de22865c1e6d9adf98aa698741d1b0ee62f0254ae453dbf9bcdb9e5269f375cd5a7e130b0115faab5faac8351351c815f739442741bca514dfc8f7420b261484a973cf4", "ce8435ca92f811d77e7cb9ba22239255014bedfab04bc111dbba6c985154af3104d7398b7eadad8fdf90211c2eb45ae576e2dea9c4334524047737e6a1083f3595d817735f296bb4e7d35f0c2dd330c77f08c4c2ef00bc12e130f491198d01a77da7e1c8ac964192024ed294db489e3b02ed7d0e29b3532689205a39ed44fae8030149529dbfb265efb9484d0ef9df735972a1a978b930e2260df3385df733d20df5dbcad72c03f2ce7b63f95847b26a77a2807364e6848d2dae2077adbc85902cfe7c2aee7732ef637de1300f2b6bed610dc2662e2583291a348f46780fdf9531bbae9a3146f83c70071caaee827318b28bcbf58fd766f989a7042cead17b4c9c73348d6df606746bffd79ba01472ef4738e5bf65e7c614c789ae9162ba0fe3cfef73917146b470517fa8bebf6a78b45b43f136c0d5d408610adcd3f93fbc36a5177fdbc240dfd763648649ef97f7d5c6f7ed5da70770f3dd72d165f2ad0c5876e7eac57a0cdbaa03b5306e2cddff894b01846637f030e5cdf55f208600cc1a94a1008fdb2f036894614cf28829908ce31148b37c6a1c68c45b66ca8c6fada8f899d489badf6c7898e11610e7df4b35aad833247c2a759cddec35111502bd07197cad55420534d4f3d24a896e728120c63340d9b046a60dc394268d9d75d310af12eb4f0400bbea554a379dca0eae48cbb194c3e7956a44fefea9f8d1055823", "2d9a98d16f946caa2d697ceba8cfed8eb6a48289058a53faaba7f353b06cd2206e151299f707b4969bf76c419c48a5cc79ecfb05f52757d8c04d9df7a55d63b49ed5e7c837d7b210672a484b7c59e03c108a15374aced05cfb63338245752ca58dd7520e39616b98a6e9033498225b17304074cc8ae2cf8a92ece86f3b4d175e123abb55c2095075f7ebc7d308a6483a087d5ba270c7a55a691b9d17dfb5f64b053007ad0c69c7692cc01d6be59a5349dd1373281ec304d1edf8fab985ad0a35f0e5fabbb5dc879e046c4d49adaf2a39523b7b92530767a15ac135f9802080f8b677c6daa628eec1823244bc3c07e187fd80c26e23f9425e6e26a837df7349bb39d6199d76c64a191d59d350c722c79b5af24eb8c9f0bf80c9df78991a63dd2ee2eb6edba466e8ddb63fd122d30d57b9566f0bec03757b5aa95a0aafa1bd37660ce1a8f0c3cc0b12cca0ef805775f99e1022d77ec7b5abc19bdd40189728685f1ee5095970b3de7ffba8694bdc5f15525eb7dc8bb23791f91a079d03f03aa760b75481e1809538ed5d45c033975014d79d2aa070da1bf37b6042b4b7fc3921038d3a87fc42c4c87f62a94acace461445399999d4b56d403f5027745810e14aab425a7d6ec9e87f981b1342eccac60fbf343358f49ce45c46c9645f9fcc8d26d7f33552efd82aa76607a97d9f11fdb5a39fc7545b57e05fe88364611890544d57d53907cd84fdbe329547d32c433176dadbd2225f778300ec4315617c891c1bb1c9826c82bf3ad3e5c86e8df56e6bda01c9308389b464e5094300cf9bf5ac2358135218d193afaee1bc1285604e1b6c56f382e09bc7fdfb2519293c76645499c80febc5109657b4f7c54fd7a13570c3e2a0b2684fae3710b51f5fbba6a22aa42f46c68089824e8cea8b87cbaaaf06bdf1b22067774d58d2a37b62fd909a2ed9b2f975164c0f133091e8031ef89ec6c74361dbbc97aae00dbedb97ab3426f6f1d3b3a64c6112bec550e6c36eeb49086becee9a0716e01eebd2b3b965204bd95874a2e3e7a7b6b6240f88de4257a366b771094af78e4b2c5c93c473cbdd85d3126eef98d7e82a4d172a1f591fa6c1d16b6a558e6db9324e02fb8d39b9de6c2156806944bf425605aea0acb2d368fb65a78a653b66cc92176b2c71b5bea5e7ebfe831482820ba3952e2d3c58503c04e70b646cfc9bbd07c1a44c7498baea30bad7fdaaf79aa7ccef6490b241b9dcd9f848e3b586e92ee0bbf11210d2e100d1fa6e943284f2faec5c47cde29b93810218481d1b7018832fd78ce39d0baa46f1ccfbd5ba91d142523e947a271fd2de5e53f5e5360c659bb267d5e84dacc058be03ba11e2ef493ca812ecc6aed356ffc505a8597184b9f0019b9498044c42b63fe1844435de8905fe9abe72b59bc55fd854395ddd28889dafe0da460fb349d9465355c", .None}, + {.Mul, "-ad7616b7a448d6d25e131e2cc99c5eb4c0ff77bab00d60b5f5f72671d46fd504381cd5db45a0385a673f3e31d31a9900c4a520f543a49bfec51da526999f285a59045445741cd9419ad72d11549fd34d2a258b5c26a780b086114b540b4a5b2b91d517d2ea99aebc5e037194ebec0ca15cfbaa8a4304ad0d41ef8b31a31f718589af1f8039cea42d3c7ff7451f4f40b8d8d3f47b8e32fc8e23e8e9c6e73ea2a97da4cb77cdb5d36dea3d17c308501b644dd25005aee228e5bb5fa8e33db5b6d20a80a5f06e9a4a63ceb44779bf906096fce4ad2aa9fa7e3fcdb3d8e7d9d1224ca67869ea768fc410a6b0ceaa11b3458b422302357c13a4e6682cf1110cb2ba7998001384956a7c2c2857a62919c615a6af51d1f74511dae82862862e2b4308809349e8fcfd16534f4639bdc58f9ac9cf852d71811f195d615c08b321cb69c5960dcc362f1269a636ae549927c2ffe92aba8a1b82303f1a6bd599cd796221a4687e1618c33dbdeaeb7cae1a8928b121616723fbc02763af73eb61b2f783a96da8ff98e9cfe5f24ec5a197231ab4d0c9d704d9c0abdd6a33ed27f440b8f112412dd0ee660ec76c9644f480efb90f319d9aada0fa3f55d6993dbe50db71a7bb5555bba67d5b51538a98bac001f317ca7edf1556a2a502ba03fc9a6a28719b2b7f9dfba5f3fa4744a38cff8fa1e866b15133783474ddcc74f886daef948fcabc50ee", "fd2bc61882a16c21e6b7279208a3bcd4374ba9790f3a64718b414de86541d5e6d3a18dd43dffdb2f15d95bf8a7d0ae1e46c7e76926c16c9bf6a77ad830d7b53bae2f86cb397cfbc15f8f3f32e92a572fd7fc6e8ec4e9b95df843b26293ea2bc2902f425be389b7e3d8cb816ca9fedf1c26c5d499eda1e7067d376bfda7ee1c22be9c17791958ab313ff0fabafbde7ad3bb69739d70c5650450663de0bcbbaf671dd925e0025d98b0ed98429d5fe819343c7bbbab61ffacd7f2b9eeaf2d5c6fce7276a19a76244b863bec0421b06eea68072012cf12d87294b9e7fdfd18c4ded7cc71d5d394eb800f8ed3efdbcd42e70e2e7d4701443480c5d190345709b53aba2e423e4ddc363113be7d5b83ee4663d136e27d04838f695b2c4ab429bac0a97581e0e6ab6d9cfc6cffffa934c50786f0b45d7f7510e523c9424230fd2a37ba67119c998273380cc9f1cbb1d86828d0dc84c73d292f41f6f34188e2ed30f99a061a8827671da08b62d5063e96fc584700a11120dbba810035b9a69492ef87d9ea1cc9de13cdf778cbd09a3df9b26dbbffeedefeca1704cea3c26aae3cc609ea5f4181357582f23b822e7e33fdd280eb6fbeaf9c510dfadf52a16277a94028d79f501718284e4da68d026a9046e20fa7ed728b207b543585ffe801b80b1a1f2035ffde106d49ce9c4e05c84c14dd3ad00603ae646264d52ea7e74737abd5eb63d7", "-ab8b5d833f5c16e40e577307f187a1d35febbcecf689bd1af9a6f210c17c1d02de36e3c9d49d160f29b8222eba212f61e657df92ed98ca76417de6dbf4cee3df1a9a4429e88d68d236af148303df265bc344f5eb5ccd6b34bfe1e7197a94d1dda500942b9c0e3dd26b4fcf89cbb76812572f57b8a56af7b6d5573072778c6b97eadb6c8c0f550664cd872307397f2b18531e408cfcefa104e4e695bdb903c7d093f641b5379f6777d1c89ec9dbc57046f9e021468c8ed3d897640c2d8c4d15907cfff544fa0cf1c427b11569419caffab289671f851a3d4aeba1d66514cf362b9d3cb8a6905ea0071207d88a820c37f85000512bc77fa90b40e70904e287a8fda183e352f56297f2634fbaac239a0acf017ffbe17a4c5e86012db9fea61e9d08171d76fc53d0d68c0d807d2edae08d81dab21dda982253a1850b6ea49b8e0240601e4462267fc5a695bb3dc2e3e8cf53823fe93daadf0706a19262f38ea8beaea34073265247cc729b7c5b602a8e732ebcbf613e3805d68b1aaa075d330abbfe063cc7aa0d03b1f9a74d94261bcd6d17933a07c6e43198c14d8d711f08098275ef99a8d673c2fa38321d54e6e604a77a18d315c982ee50a2ea77097d1e4b6f552d901e6ff851acf150a03decc7692235709760a0cb8cba5ac4a9a714bfb522e1d9a117dbfbdc0091ab0bb3fdeb561d6082eda79713a0c5063ce8bed3db09a4fb51deeab8d198606230f5724c35e62f62f75ffa720f4338922eeed5036863926e3f529afd5d6be1a7d968d286f7c7376dfa1853ac4a5708674c6c98d098b6bf9e3cdd98defaf2f45384707f57b3bac65961865ae351e7e276ab3a8b4e72ffd56ebdb408c4c3cb1cdb4155c73c4e31e2b93b445c687fe1849289ffbdf24fc960b13aa445cb812a294d700e2f4b018c486760117cb506577710a75ee5375b4abb24383d411bc0b152bf904df225ea9c99f91de3537e465198d31306a37acf353f4b709cb581bc88d7b245a44f855d3e6cdb291514dc05037024b539274d7b75c871709ee0463d7f298cd0a123807454768254d3275fe7ce36ad8d5dff00fe1a3a5842cbdad4826bce379f5d5985f7daaa9224edf2be677711ce76f084a7a4e7aaf5775da8e2442af21b39245387375e2676f7b2fe5a53854579f61454216ca2b38a0df1eb34c01a5ebf7d592dfecc7d22c42043cb3d00794565327faa709ca2fb5af8d3a961c34dc8a523b3840acc219392220c73baa6069d4a801da11ea4a85426c10c2da20aab4b62595fa9543cc2ee76076fe14d2f1aab006311dce95076a13bd32f97d9f1c5221c7a51679f69450b6fad3446cf7b1440416c31f0ead8e02b2606603dda0fab5032122c8d91be04e0332d16e76868f386681e2a6e32557ef84b87e453224148dc6f33f4bf35c35e7a52fdbcc2c15a7b07939e865b5867ee01e2", .None}, + {.Mul, "-d624366451ffb2366db0c0064dadea830e73f7c0e220d50e6feae890369dd9a9ab06bd9007c07730edc3043dbc739e956064116e98e5d73bdba86b66669b96afbcfe5c30dce73835b8e0baac94c184257b12c1fda621e30878d923e0a5d97b1002bd9a9692fc71cdf05820d980ca03efc7b2cd5d32c336947dcc5d692def80a1c9b4a912172b4b6c1051169df43a12d94bbceae23afab97258e1f70c7c5303bf95e3a96766ab220b531e147ec0e0a5fed68cf096469390d8b497608cb75523c31278ff1101a18a26113f2793954f54a9469e4c8c0fa143c5ad38991e6e75a80bb2778540a07673ff42ff0252ff74bdbb887e587de5d13ddbeeb356b192b97de3d49acb62619dc4aaa50700b8cfc888181c247816f78906b785ab87e3d3198ed7bfa03f8164c7f242913461c8175cf315c8a1b886725d94f13c5f884819fbe1d2b34a24ea26d8b9ea4f5b1f14d15209d1407c95e3bfebfef172275324ccffc0fe833dd8cc5ede512c18475f8ab89e4cd4ceeb2b9e95ffc75a5750c093b1b57af4d478840aac937b858c36f080632bed1dbe1a8a130b4676851460f94e1935b47a454270dd1be9527576ff816859441523288e9d73383df4735f82dcad001238954c0b9e96eeedcee51b08aa653cca9b40e9beba8b296492f961bda00aac06233f66787e439c1f04bd72e70f991dea8990f7f208bbc256e8d55b9608a53d3e145", "bd85a21f77da19e10d340b8e7001b7e564183f385ad163b6fa5a050f9c90a73a88f212cef351a67df1da9af6aa2f231e923a3634e371960d631596e933c77b91f407b8b56b5c584acfc299467cf4c90807ba0b8ef50ca8605dcaf1f3b35f0fbefe5a412ea0990a08ab8c558f6ef4eade6ce2ff852239c056f7d393e96bd3274a39e1cc2218f85a72f83f4c765285e5f07cdbcf2c72e4f6b1c97632cdf5e04ffc1084c234958c8e7e5a7a59559bfa4c532b988cb03a0d97c1810dde6921688e358c2dcb86ee8127158cc4790f0449987e85f4107f9fafaf4d248ce97179291549449ead0b4e691f382b86cf3b025d361e0c5717e078bb184f07dd8d1b2e0f1f02ed8f498b661de0596242fc845a43386c4362c4f0f7d0d6ba7bbf3f7a7fd00bc42f53d2789f2417cb809a9c3ead2cdea296fc81506eeccbe27936c957b5b5a10408993a7cdcd5241880c195ea98cd8b5afb63a8b4d4fa1acfb81fd8a5211fce7b2af1fb0bfd12a0f74bf41b694c3cc1efcd5c35518ea0a2383e65e58746e68cf98aaca89e310ea597ea9934794353b24ab113a23e26d2cf23d3df7e26d0ff4865b2b7c083037cf9e89bdfb781a98fdc695a889ce3222b6704d663779bf23174ae90e7471c43bca32c5ee5d29572d26ef83190db1682d21cc336b38eda522f4270b8ac1b482a0df88f1ce9aafd69cb6892aa0f36e01e5fe13a69ea8d98cde6b506", "-9e8884958fb7b8383fba2a257eaceaa87b2e44d1e09c6c00925dccd06593073c7a8ff91c0f3c9d586f2f67b03a0a6edcacc6899be96895e023f1d137610ed9335d96cff3ae7de1c80bc926e4976cfc3b5fc9a117de6b0ff0cbf807386b78b84ef586ca91008d4eebc346d27605443ad5a6d350e38759e9458b39f4ffd63192620863359d96ac9a4315d5a83b2cd69c2df17d9bf06d42c04318826ec0227d0abedf77f57235a8dc628f2ba15dc90cb45c96eedadbb78aa5db32fccc2fbaf09b31f57bf85ed8ad9e5fac1030cf9ed20edeb392a87f0be19cbeb4c7d092327a2d4d29e1f5cd24e4bbc01d8250e72602a8d7dc5a51504c0bb61958c73c128a506533b6db1d49322042ff9f1d209fcfe655dbfea69bec020452a7dadbecb0f7cc943aae3948486cd82de3210b8bb8041f25da5c3664fc00fe33245dba7e07d565e728f1c9db7a1195164e9e3d0e6ee33199264ad4bf40a39c5ab89881bf62a969324d3c4446a16fc2cf109edc98f630c88372d0e440e72867c78dae43fe1232f3dbda081b702b5d7704fe9c4e5912d83be129ed4a7d170942c0860026a57d1d3764aa25dc8e0e0a8c93d93f20dbb9150e997af8fb1fbfe104c9f95957cb7a7693df4c8952b18504f7ef9f0de763c2d545221590f6e0d693f013197ddeea858cf7f6340f2bca1ec0fe3f8049028f4effc326ac4dcbe5a1aeb81b7c63f2948d0db4cf979fce4f3cd201c4d90b6aa7d53bd7a4d013894576d7bf41ce2b2d58c1b4e1040d3b584d6c2d72013c29469def2c1be903f9131177586f8286a565ac6310ce580926a164639d8e36b52399285a58657109170263ffc83089f898912d1b0d442d1262dac28f3ede75801db617ba197f262e3f8aa17fb4f438ac6498a794ccb6b9dba1086c70d4880d0aba66ed6dae1c69f9c454641e239cfe76178115713995b480704b88af58a261efdb309de66adb5a06afef19e5269b51b81c9466b95470f9f3107bc436770f08a1af5edce20f43b1f5b945683e3f54b026c618cbffeaea64195ff29d939e819a38ef1ec668f49bb719b6e98e035808b5ef25b4672cdb9aa50d22f1002c5bf16bf758be22de1aef11793fee4b08b2165126c44263e099678044577a8e8bfa99b17c64e54fea70c830e50319c17f94339a01f1e1c0e65fda9b5574aa6f88229ab73a80a0dcbce2b2ab8d627c7fea0eb1cb80fc85b65cc4ede54c13807804a28b88c45e6e76b7d3c0b94b1eda912e03339f026b371821587e54853a2c063f058beb09ab3920c4b0b2f5ce67b806482b4aac2a5bf0df614f390e68df5b7021310355edf8193f3446d71ae0309adf853e04665e1cfab5596f2b46cc2f5833c6adfa3fc5dacd7d8d47bceb99b0123a06636abd31455566baa6e8abdf7bd1a383215109587b85123ba3315862e9f800d4154b3c843f4ce3b6a3b109e", .None}, + {.Mul, "-b8c5a6c118adaecb367f8701e84c2cd8e1c881f69ae337fe178ec5a569ed7e9cb20b0fc4fbb6496f76cd188dd9ff62866b8aa6877e3730374b6c6fb1ed56a418bff2154af90228fc20114fc634c241d6d6047ae1d2cadd5b8a7d727d4deb5e6bade8177d7f3ab8a0d8145458c7b33ea3d569cd952d925bce8e5b04b173e72d445628431e3f33fa2b64c7d11fc71ee7fd2967d8248849e3277e67a16517bd082e0d88576e735e87d6e51969ad6411f2880e8cb75278306f872de99baa22542da5e1222bb8486aeda3692c74bce95b2837870732d3f09d5e065ac95acc86b8fdd20d7ef1eb6b647663fa6a659c58fb014fff82a50bc6871d90f5f9711f50b6147c7f26819d5da146244dbc47d1ea23ae7f78688c794c78020ef071a576165aa8b18e819a02cb34a14866d6879e9438c5024352526ed2d549f5230020ee1789c01a92e04f45db221598ba50f26c5582359c0f9664abd87a3ea0a6bbd9e7578f7d9bc81beb148d6b066ae4e18d481b6da8e972ba354e00fced0da63172cc3db412d8cad01e6df8bfaf09cc9e4370a71b5c2f4008fd1949c365d4231dc27358cb7a142b47443b123f9a73d8d63651c1c75a6bd49d6cad9f431ba2c0ed2598f8714e0b2f59028cd97d2c551bd176858d7d12b46bd8e21b2e0e970a3010e3af72b91c285309dbe1ef075d2470be75176aa203e003259fb8862c5d2923036ccc9f03ddb9", "5558ff89df20b98d32b9fa5badef6e2a63837ba51f63407faef040ace9c5ec848946778a76c46212636eafd700673127c83d8ea2119b383cac005546dd57e18fef71dfe3dab35bcfc6002cb8b0c921f0f6c684c5ad110fd5a10687b0c9ee5c06c23e0403dfc083b6f0732d69da1b648749d68ae1e1968432f1fae2645b24e963de7b80ef6185cf1fcd837922ec793831d51daaa978da71588a867557ee4afefa8942e0dc984d241e61d0499fd708b50edf14adcdd8bec890e0372c2fcab7846db371539dd3222e05cc5b4152f8926b827c57cae92c27c8c97c2eae1f84fb9e4544f81ff62b8619f4f2552fdf4bd7646f6e85839c75152f0cb2024f05b08fed1a6d9908e59360c22441d285da36a4d7bc55f9a5000eea5998a35e87cf061aa93c4dbe01538deeea6b9c3847180a41accf93e0957ea94889d368247333f3788ae4a331b15448a496381a0da4ac1d51573c7a2941728aedec589b31370296b6cd12870bbff18f899f2b03d2af79f48990e8e4052306ac9269daa5a02a4a8a91d81895d89af3a31b0a7ac1d18473c1fa9de31eafea5275ab7f711e0a55fcc5bd6e74479c834a14cd7ca843c4c13fc6d1900d8fa675da0f6d5202cd7df96ba9d32416b152c952dd0fb767858986c8bec061f39ffbd351b31ed6b0590d7f160f8e35739814a76e98737edafeee5b05128f1471faa963211e2824392329d5e24c17634c", "-3d99dcbfd37e868c909fa3f69e5f4e766b244df6d2b47933c7b2dbbed79f4bc36978081b6cecfd029776cd9c9e27513201f17a7df514c62ae7fb5da9a614c7bd28aa1916a7d8589c023baa7ed9257e8789ce7f334d6f6359ebad7a398d2a6fe00388d0d5f79e2af4ee09aaa91bed3721269bf0364f5a4c9836e1240fb5fc4d9717e52157bead182febf9703d21df3bd5c7fffa812b2144355b76eba50ec3d703b0fcbb5bdfddf00bfc32824e328818c9d4772638a70e2e0fe670b40ba6de9e17f80452e7fe629e36a8f66b48b4ddfc27e843ec816c395373fca4a90963bc214a53337c32acffec4ba17c3c9290f6a4d6065659f4ce0a83b6f759adc649112e2f37a38655d01d58629b2c7d1a2b3bc7869e03fac4c22bd4a02cbf34b97f2739f00998a1673fe3583f782c703f7f09f4d386f739bf739f96d56b711318b10b07e0d532326395a3685228d0a5c5ba219b5f529153e99320d3d0b0992c1f0ead88cdf3b378547def02293dc87036bd3385f0dd2f68f262c6f07c3ed88236fd4a9cc2ae1ff634dea6c30697aa98fd10d7494595bcc95c50e3d613a16a650786432905959f004532f83ca5bb7516b6af2ce6d85f0febcba1c784c50c750c456ed9fd8040ac75318aa9adc59f1adcaabeafe7a172e350b6d11acb48fbcf5571adfc5b1b88e388727b573384852b9741fa1a18c1c4c1547202f0f0e1389e0ae6a98bfc119860a7b07d3e20ecc24eb5c6cc59967276f84db431902a55be3d3e9e31d020eee20b911cc9d866dddb334e4c61853e50dd43eabd7ff7aa1f1cdf646e883e0c5c74d672477bde996a9e8535085c184d908f3e0beac1368148680df11bd415a698728390b45603da0852e51e465d262887154a1dbfe1b4118be7a1b7eb7b31b6b53b78bbbdafbd1608d41d6c2488089cfe8a91ce2678e897d920cd7f28e29d51ee7f30c0fb471c93f8b9cd2a0e33a849753f57ecdad8896850b0e49cd9aa37dddafca25a58bee50cbe70e16b70aeed18a050493985efc0e702722d6c7b402006f74b854e3ad263f0c58d70c18dd706b4567070febfefa2a14c620abf7296415fda258e58e65ccd3e0afa59f679c502bd0f5c2081609ebfbd1ab17afb18a79870a4703e9d41a523bdd1c6b9d849c07eacf2dec596e6e31552f5080f66f9a9bec037ad67b4d160fa25d0c281d39824a971d6737972364fb3d2335f0385bd8b4851066192097e12ede4b56c7d9fb697f7f242caead10e25670b935c4c16a7ec8467cc0d85c8d3de68e12ecfcd0a7c40676e61b933c6a92420e3656ec66ad859cc2cafe3ff4672753a63a482333d5e56855931c351fdc74dfc22e8c6d8c9cdfea7431c84dcdd15d3aa3c9cf5036afd0b0699cd2fcbc9c49165dcd515783c318b10916734f3563c61de241e88023366626cf2dfce70f88a014b686ea43487bb8b835dec", .None}, + {.Sqr, "13e081a11e6befb312caf1ef00a8660c8519bf79b7d245dcc73718debd072af1512a52cb68cfdd2e707add4ad859b4509410a033efcc2a30ee0187492eca5dc432d1cc0bea4755e7a0d6e1f04b0c28ed813b5513f4a5fcbac8b98cd7edbe7506bad739ac55f0833fcef5b81eee8e959db2f0b4789c4ed7539113ca0adba4871bcf77219f9fd367ba3ae34c095ea17f0cf8e86c46c17bf03b18c49f0c73896e71ff02f54e620a32e620b0fe1fa51519e6da138f6bedb1bce7621fda43cce51cae263326997f75a9ecd394f620b1e4a76231605faefa3fc40c263598cae3110be8d45ba4e1f24b2d527f41f21c5473292bc5d906cec96b9fe46c6aab48be753fd605a169c3e43257c3c74300e3de5ecf1a84c04a1a4ed361ebbc05c0486285d40f11faef7f1f87ea228c628062656bb6ade8b2b5666fa916710ccd6ba76448b5832cf9a51f7c9499d3e7f65d633a11a3f17820d7e25d13298e1b717534b20887934311f000e9dd6d3f8ed3ec4326a2eeecef95e227636064bd8ab09a4c13ddcb7da0a8557b8a51702a76fd2935901e4d67ba17266323c1da8e75b19f6be7dff5fc2307b799ebe5a9ef0a5e5b3b23759c37bfe6f8912ff438ef18983373c170e15b144ca97f56f5bee247cdaf9bdb5f0bde2f22d49ba82871ff5173afc1d90b237028f43e3d2022d5010eba7c9712a38e36cf215756b86d683ff116f0bbda5faa11", "11f90c14963b3cc27368a6e938b2f5641b39fc70123676527821b5c1b6482294070c3afc44d916cf85ea6aee65a401dcbd19f539f229b9ad08301e111631e2f5c5da4664e331bc9b15e1c1e3f6f8261f5fbb35535957ab31b813c54c84b08ac25ca223f32c73212f0c721e2ab20b85f7781f0a8187765a3f676ba5b4d240b52ce258dacbcb0607150633df94a0891966fe0ddd882ef1f696e2062052dea1e54f50b45485b008c85d9acb2ab3edfd890054a3e93dd005d77837fb123ba8903e29689b937e1fe7de323174522012d41b2365f2352ddff3fcc6e3309aab33d1ad5f33058377decde7514fb1ae5fa1c53649e0c311267044de222d176d7ab7d31e15ea20b16c53388f2dd7dd43be2ad28b5a0de36d5ad7456fb54e9bbeb1eb668b4b75f5d63e205f9e7d5f76ae2e506c4fbcd14e6d4a251d02918cf0b0ee767095fb53b3ec770424f9979ecbeca62821dcc1ddcacf89c2bc6fb1a150c2935fc3efebc087efe3f97e0a7c4eaf28722779c073a871039199381965d9e3e50a99f5b587715b39b8251befa36ddd26a30d31e98a33e2d6292b8970ede7bce06d325852d3dcac6f296b119b82d3375f16c327e8bec8202b753e807634c594c83cb1387ab09fd508fa516bcec6da4e9cc1bf0c57fad640f0897550db794d3de9198e44f0ffe19d20cf64aefad1e2334187c97f763af7ca6f9ee679b04f76ef286bd803c10b", "18b1821061d08881d1e74ef3ffa73d57731806c6942619d0e3b627ce79a07b16d2c255e3618249e2ba673519cfe38fc698db82f33f24eeb5ab6458e7945b03692d7875c86a2b7f57a20c7dda1303ca99c4842dd815476906ae4f3af7101e644c7bfa3b25e1d11580e741efdd55b068461133605972ef60f43fced5661ba1f9ad7fd7e9d00726647dd5349a99c2829150d771da8af549cfe44a76e0aefdd61b1afa7332a1c93c1f5b7038ecd017d2438125d1b9dd66c3e29645005a76dfe73f1daa2869d025dd7411f74876e932e59f700f0b9af222d2f1d186b181e07e116881d0734b105dff5972689d2aba4392d633090c4e18d2a09fa694c0ad6ae1f2900eeb82e601238a348a90e22f7b1f9e1a989c06856169e49b5e857eea2f3a1e3cd4b510a4a7ff112a6fa9d5ff0fd06f1dfcfb2d71e70e1eee596b183a5c06ac8db98a2bbc7295cb07aae2a2bde196f3340ba6854b12ca593985d1bdacefbf3689a7853c9b3918cd9008ad7fe2c5ebc800fac6fb12e2fab500ccf343a642fa19b9dbaa17e15db6cb3e9f89f1b25a785ccdc7ee77ecd59bacf3dccb558639c168f9c6b588ced3f0c4ccb77481962bf94f2ee3d7b7f2cc919f73aafedec7e9ba7e0c0a56a8114b55a3ee883c5efb1c5e9220cff1d7f0228d269907810742fbaeab010820a47ecc7973d1766c7265bfbe4341bf8a7a953a5339f36f9c5433be588889ed91a392321365bfcfe50d230385332ae0aa43534d74e8b46f3b4cae422d40685327b962889de587edd939967b1b7be4ed807fe6f5ee6d720e99e029f54730876c2b4cb4d215f36c85a363ee1375d49f7a217adf499f38e37d729905398f63c073f3a330a1e416d64f8bf4bec50b6bfe0e9bf6cfa4b1adc35f61430f3a3f3e66dd1aa650e9856642e5f5c95ea091f1306b9a6cc4295717f4db4f2843d20578f0b0e2c571dbce0702516c516b26991e5417589af63ce4a49dccfdb9aa1cde98762e9f5bacee2568b687767224c70a02304b9dfb8b1eaa92ae855ed734ca0424a9207bff27f297a654df7cec4b7f60b1a57537b194b489a2a3b23e315a9753026810834b95187f99069e009743abec50f53888cc695246e9b5b440226f629486ff70b8654f1f0b6c47eebb2c343594ac3b523e598735b43bd8330b01cd1e9adef69912d1137f9064280c0fe8ba6b0e55f6cdea5333e55903863d1981102ed464e317cb3625b13be10a686a1ead90b33945b96785f31d159e4f76541be42cbbd9a3ebbb7f5f6b722f6924a74eb8b9334822f7066cf43fecf002a1ba5af5379d45d147859fe340d4a21894bcaf03d92b40223e26d283e019f910b61fa31eabd25293e427b3bb6d81e6e908e0fda7ea48332fdeeb53c1bb0c76539a74242f89f30a54159e5ae4a1ef111ee7c94cdf880c354f34e109c8e6b8fee4f5dd5663a9d989521", .None}, + {.Sqr, "6f34d16d6ba1ea08266a92a26e036121b93d8247c33a30d2ce41f1142611581ec30b2e4d97964b5373f1cca40cf9a50fb5dcb088ad83420a1b1cacb323993e628ccce6f20f0967482320bda632fb2680e5e75f3671a20d5c2608b5ee27d908b375d4ad30361a9fcab4feb59d7074a1a4a62c336842f4892ff76f9d01cde711d28868ebb2fdaaa528a9279bbc030c7734e04fc9c753a04be724cc108007a9e583c0555e36fc5a2b1523d156bf5a5044db7e268f39331def029fc249fe8f2f2529d8b7397546e6aafd9f6d2d311941b898ff288da821fbe1f2fa741749a5e026398e9626063a4a606628d3610219ea5f1733c618ae47b563bf9473d1efa754196aeb08c05a38e6fa37281adfbb1a0f1d0ad3a696ea453f6e22dc605a29568f2ba332b372103371f6e67ec3f63c22ca3b6b12e1d4f4413ac10b1aeff1628b2b5b8866868fe7223017d1c774139c141a2551657dc2aea7caef2aade2fac36b56816ca45bd6b0cf263a63f6c332c1b8bfff4ff361c6b1edab40844838a1082787af8e0dd8c1e2fd091bb6f6aa318f3d44620426d99c4946fafbc1e0cd0d5bd2d36170b30654dae09a1230b27fad22e1641ae3f63f47d4eadd89e347e15f076fe108033a31bbe96aa64c629bbb817b8cdcdd7a957bc1161ccf8f13a7a7af409c9f7eda2528371b3d8ad004055d30f3abd17838a7dbe880e54cf79726fffdc9df5fb6a", "14320e021cfe478da747c1006193661dbb18e961edf197fa91ada3e3c9a4deb0724952692f13b5ae288f1d5d21fcdd94a056d528554e58ad9900ecbcfb9ecbdb6e19463b9143fb017a2b586bb3249de8625dbc34ba383044d4dbc1bf20aadd27bbb570cb077f6c4c30a5a6e7164826082eeb60b401da6ab4496cb63b3ee8b275a794050c88966c0f1c2630524c2822eb8f8902b1f7abfec2765598d159bb66898db0fe410d6bc500592cbf5b8f64d5562ba13b1f5b51313b4eb177a851b24e06f5a298f078156ca2b32a14e77ac2662299a7893890f8822d8cd1f60ce1bd1c68f35579473cf4e0be46971f610a1be6e9a444478f17d5e38f71582499ca85c6119e416c9f6b510dd1b521c2285f7431501e1afffa56cac60ff0b716b34ed3f76b01a41cddeec426f98a44fac7639342b7240d832cc1278f2838867b19d1545a4eda544bb91722a69f058641dc37768302aa327d463465bcd53331bfabd39a995cb7f2bb0f900721289f737415352bb45dc21914c7f063f5f09f0491bec7bc50245bd67f60985adb26699297e58a964133296f6f98b73df482e3d9b9ef7116f6ce257b74abd9fc3c4180e2ab60a5c14f2a6b6304b96d65be9855b8869379c865f859b5465e9fbc33d9a7ca8df782eb0cf056730cc293b27c4a10b06a4d35d57d55446c64d1fe2bddaf984658bf87fe75e58cfc098cf9b6438174b88dd4cd10f9f5", "304ed882a31dfb3d59e3602a2be204ab60937dc2bbc3cf0f828442a3221f25e5d1859ec6c54d2cbc4b1f6684d3d7a31905e71ed6d049e491b72a3845009b6d2332969f5b90e248a1f6f23525b9d7631d90455d79f351e32a262aef765a70d098f616cdbb1e1682813bf6a5a57f54b1269905e52263ebf0b8103c865433cdad3fdad6dd45cd920171d6b730c35792c6c566ff11ba0badb21f3787e980cebee84b63224498e07a0d15208956226fbb4ab7b04bb8078cd655618cdc7c4d00cdf41e8ba458f32d0ba7e7066c043aeb42ccdc47efde6d1429f8d9093a337abd2516b962c25fe2ee5fe273653f72c9e81cf9ddd1ed31e4e28a7dba7ac3b48e5fef40ea270031aab8711e7770575ed62bd8d3129104c6b46eabaaa10995683f508091fe28e6a0c173982c4a8a2518de033af8af8da125553f62f4c023bb5ab26030ebff52a1c10c47583f6530723f2ef6bbcfbd9b0fce2efa58b8f1d7a96aa48ac5faf455f1ce7bf33571853bd96dee025e87edbaed3f94f957e250f7f71d2e4e862bb1a2bb0669b08f418ef3dfb1a36e1c46001088d0a0e224cc18555469eba08e26a3cbac8fae79e3415537cfa966a18c644fac17822b02bf22c76e0b350fd241e8ca3bf7606067a8954eb276c6e0957683157b6f0a4944c6f291101001d74bfb3d1e5c7dbc53347ea8fa3b01a88b47ea2b35b67f10c16fb0f6cdaf6ac5ea1f25e411ab01f481301a5e5d5be16b11ec660ec50085e2f450897af6fc3ce226cda5146bd3f2a65f97a891fd75d13fc8622d52505b6b5bc8d7d81559701867d45477495cec34fe7fac439d0142f1d6ed001ccc6ea0e93b467f32fa5674df17b7bf3a2b4b3fc18c7804aa99a32216767051fe1f76f6013c3b38688952f4834ca117f228317c43a7f14d4133db9aca54f9a73a49608350a3dd3ac7d27e462af226fc565475df4140da17f68e9f8b4ad87a10d7ae55e2aecaa8b8f55c25bf842d17ee4e8cca5096bb95c4e39825061e3013a20cd0197ae2e024a40cefd5f29aba382496fa14d2acde5c533603a1ecd514cb321042c9192ea0e527ffdd1c9123439be77851bf035b0034298cb3e6029755211c1f2cee601b3bdf0cc2d8dd06f60ec10fe27f5cdda016972cc6cff3e1553625746314bb391c015b4bbf19e55defbbae206df49e5715018a9ff6524ff988df4264d463caf2ca18ac235dc24c0ab31b095a6132d6a3833ff989983184cacab2ff4283ff22d6bcead472d3bae467b14bd1082fac068e4358c2295b2af63fa338ccf48928ea008737e1e92788255074aaeb160cfcd6d3ccaffd70040fff6835ce10f5b2e3787eb12e4864bc37f9889656062148eb51e8f48d74310ef35782b4fffb26da2dbde3b3e624c7d1315e34f2a625e7040caa6c832ccc705d8da07300a4c6581ecd4eeda06e1266663e5908eceb33cd07e4", .None}, + {.Sqr, "34be48ae043c047a4db349acc7bf5ebcf3ae46899c504cacddd8adccc82998430b0b80d3b738942d9238a134cc6431462a6f2d02a3c9f80979e7e39e6bfc4745b53be2dc4c0cc681a7951ea55f11297a4f670744aeeb6fa57f6a7fe065fc8a36de040416556bd38c0c41f62b15b901df79f87ac110c3bd256f16dda8885b840270c6d4f5401b49aa4ae9cc292ad68ce9d3956a9a36b7930997d9c937cdf45b83b1a2e2590a30cee5d9517491ff42dfc91f5de55f08255b7ea5e9fca810bf8c65117c24e10eeed6f2da9c5e6bf27c48c3194ce76e33d3723e474640a12d5ed0927fa492589413e665331da0e61a271b6f4aa971db3872b1768cee3558067ad792b7be7727bf9b5945e39708bbd753bba9f040f1e7bfe9efde4aa1f76ea0f8a805b5439c9f6beaf8cfec5e2eb42e6dfb4af0d69c5581eb84f26d2976ed30a5751b9acb5398fbb9145a086525e96b867df1f55bf5a2e2cca4cd723500e743564d2ed7b94131a5a0d69e91638f0208684fcd263d4b7174cf1b9f713b8d6db473ecb2f6ff325a1975983c6feab59774e412a80a2e14535c50cc3c74556d3d224027a628f22ae939535d207476df96c9aa709f4f73631f1b9acd27b6e1abbbb52a07d8792533430b387c3f6768e99a77414959b499e0641ff1c7fd110eb2ff1c92c9b90a9cc7b7057716d142bf93b111a92ffdf603c529c7b50d127e7aaf5d1112804b", "37096784ef87a139f9dda41d384751cdf4172618e55490ce237599008c42a4be24f7034a2fc540f0b5a3ca304124c48d747c597a6a328e3bf4118b25ce4cfab95eae12320927a82103335648d456a5f63100e9d7209081ddece71765e43d39d594154d76b329fc66dda43e07fcd3e9c22be54f457a91241b598ba5b3be7a7e860c8b3493ef9a2bc0b48707e3daf66c4c19cecb3848184eb8ae40b002f6f415be790e34693be406cb7269f89ab7dd1e3b30f453972165f2f329b1bbc77904a7323b496177bb22efe7dffc174887a36af8b08e55fbd7a51e77d2553f7685f6abc58d22bc84476450aeb351360b5db7abffaba036f289b9caa0dd5fab2dbeb62de17c53459d766ca8439ad202554b869d1ffd85b9246d5f7e95ea65dfaa1e2bf9b1b4674a679048aadc5899d3761519b6af5f380570abf8e5ef19a2371e275cbe486f4178f6226b1e3e55d4fdc5be6e455bf4c58f1784279f53c275837473bce3d7171cb98fb8b003f4ce0fe117a62a3e76fb624254c709dba5c76796775f6cce7553879348fff619d717357b7c626dbf32dbb8a036dced351629f28ff8a3124346ebdc878165683feba0ecfc37c731f20faf08927709529e67f99d122b7443ec2aed53bed68c533f990d603cd0e7f5b8b6b500cd639d02222b356aa7a0f5c5fd2d00ed5ef0a286cdc7283dac61b4d2b8df3179273f757071d77e69ecbae67f4601", "adddaf6a8a90393d948fc3bf29da8fc40e828be9ee244151493dd77ff3cbddfe14e35511e652452de83de6b319c264a5063c9f2f372040105615e447ab694d9a7aedae20373c2370f6aab2a9b6015373a81595943e7e86a95e8cec56c1b71e9a10e17d991c40ad0ad7b9279a6ee995c394b66d58755e81f4c20b21a553a841f1b4b22c1049ea393d495a878966c5143e84ec95aa339a37b5e8331ec0063f50a491984532eba28192d70e37c468c87fed042b5fede7dd14e6ce96d889799340b44c8b0c758b6c77b0dd4e5699ebb7b404b293496768481da622fe260173f62da4c434562813f6d9b1b0e1d144a0a81cd7a89afb5bbbd8fd902ffeab8098bf5d728410e178aae062aad76927e98e7aea8dd20f3ed9bef1be4afc5286184bff6ae03514b05e8005528e9d435f07a28de6df5128794067af491baf7d79438b10f209335708ddcd72ae5fe23d36beed615c60c072a49d2ca8cc98a3d70013ff9ebb406c7928864394726d36af7db77c6aae522c0ec1abb6dff5c68a2477272424f028b0ff983b6ad6c58a8d09a3c6ec49ae7f259cd99d4251c511ccac50bd5dff2d9fbde8a926c63cc5cf9964da25cba2065752eab8b17e524ce465402ebebcda338cffac2f0b813054f340eb3e8e749ff5344b3e66b60ab4154f721910b6463a6b8ee37ef6d661d46d145786133549e131e0788d106f0b591b6c45009a41cd5259b753bedd67a47afd3d1c3b912015243b1a7aa58f16582e67ae49479d9ef44431996c9516e49ccf622dceb6c501a72ada84b3c75b5515ef8f210989b7a2775dd9b47242b0dbb0735af95d0edab1ccc83b7e0db8819807227f23d360183b9549e59cc664e3c577b9335a93ab384575a045ceeed714389ece586b45761a60eaad70d22534d3adac6849cb9d922875f16125487b2d89c57b66ebd467a409a63df57e4109b8e79cacc4b14c7bde4fdd2444aca2c2f6fcfafcce801a133fef60cedcd9b5755871f63c3047581a862966ea8374b932f09e02292392f2d93bf5a521b047c79019a335d3a059967c24cb771963731ac703dfc6340241ca412c47df02eb4d7ad243aba43fa399efa89a9da54553bc53b32835c11bcc5fd904a62c683412a147d8754396b4a6926ea65c4ed29e36358d591febac33b9eaa01190920a736f89c41765cc55f0d6736dc409999ceb3eb0c21c19815e01b5cf4868ce0797f2288923cc239f76dd9db5c2cb9ae7fb2018cd2dfdf2fce4d17edec6d798c1283f79cf78c5fcc0c06964dbab6491ed4b6a33ce093ad6797fb1ce579a3c9d83fade61e3c8364cbfb1a42708a731d382b2eee3bd01b79660d2cd931fd7ac9bdddac46109fe444fd2ed181a7524f778d8c0fc8702ad554ca30dc1bfe1b826cfec3807c48e0391a44522738a455fa47b4406e56f3a03ed489e1855283a4cf7736de40d715f9", .None}, + {.Sqr, "92624a56be545d5e8bac8a8530d7d7779170144aae660137638aa03306e5101e86f1deb736802997e96216d961f59a4dd779790bb40c9b00cfc3dc7acda850055bfbc203c1b4f0c0dbe37fce8b7b1689801b73f26e114a42f244df39f32594762044e4e26148bbb4082c3359a4805507da272ed3ac576327b7641078f0a2792a33565a2c051bab8410034b24cae0a6daedb4a965f09b25dd7cf6e78297381b703d0c8c4923a0082af5868e93da416de002c2ccd0b76d26f50d7866adf4516769d55cc3801e1cc70905343c8a51721b26f358ce683c7b50007b3ddd91064a749e59a9961403ef14bf3cf5e20befe940a67cf11294b5b9ac81582adb11d4b634974fee62818f79e1113acd75252a052be6142a72a93b365dfa2de6e7b15653d61153d6cca608e54c24b54527e0dc3c595292b7a2185661c5c1e4c534bebe1ff63ca41b97c040f48657a454f0e83eeff793a2253c23c0daae214a43b39cecf13a95be3c17595c5c8028ba35a54f964d9d083274b01a6d6e252fde4220d56f23712bf821b9d177fb73c50adf9f6e7a74f6ed583104664fa5435043eb878732c60433dff019c192e917b4ef74725a22896449589089bad1e6a55891f46a54dc4d4a606a5af9b89ee91bd73f85b064e2f01496ec4e39eb6cb3d334387c3fddc6d786b3ecd50694a0ba2077cb4960a27ca6c63b6a16287d6f10e21559a4b740cf913203", "e72208e6258996952cd5f21df421a76aa87f479eb6b21156ef323e739d6c21ab1b44082e6d3e141664f3059d878801a7ba5f9da6e4c9b2ffe72049d781f577d4f9131daa49efb6197dce31235bb931e6f6033807f19e150f76d6e9764fa507596dee231a079d5922ba6ee3ab1bbda3eb679d37e7f2779ba40e16b3da7589e98af1cdc2d1a5bdf81832457c93d81f1dc9cc02c05ef618258ed766ffa0a701d7d89f2b618f69295fac97017729614aaab9ca3176488c34a466578135dbbbe781ead202f97533882c536cefa9a60b24fb0cb009eb66991f8acf1b4f1c247f2f65148a2c135ffec1983ca2b6c026fbb41c1bcabe113c8cdd3b3276fb581cc2df882b7e0b3a77dcb5a8e153da7311681f06f1252d0a4ecc2235b05722f199ca1dcd71d0862bbfb96d97b80501517d9a73327401e9f96d9d9ae5e0b33792bff4a447786ac700ef4787478cefc312855a89d5edaabe216fa8e0076a39514ef3b4fada2f6b03e11af4b64dc5dee6c54b4e0990fb9feb8cfb68e6c7edbc476c895b17b750e3905395ad1355ec77cc066ec36a1f80d7dcfa0f6555e1a852b4bb27a69371c9aaa8700bb1d1f4036465bbdcf6af15b8d03ef39c40fe371425ff0cfeb1147694ecd6a763a8604eedb181b24c92f4c3c6a2ad93d9644f940dac69ed07c356214dc16a0330bc257ddabf525eea450351387f2630b8bf8178e234511f480d0fec85", "53b44287f118368487de78c5511f43fdca7cd8dddf837d9c889dc863dd6303d0c401ddcd9689cf005ba51aaf3d8e2dc1bd1815dde7a928bebbe6a62df9117e4f06f729cef4602a712feb8ea059b9a5ab16c501b8aa4776121b3c5efbfe7dd8ace3d3dc0bb32faf85879b0f93a254e96f669de066beab2137c63dba2269f4bc804899a4d2d039147d7b4a201fbd658a7fb98653e9af224a2a37ecdfaac701f73e3f93a2418a3652c41d7c374d3760fbb67ec12dab6852d32275f36495381494e9416638f510fcf3e7ab7fc59e01519adc01cba072097b31a5e3601c7003fe782469425e2cdd81b945173e87d2ae9e44c5f27f42cdfcb4ed7005b2397c0a83e0cfdf7c5ee9979ceacf536b4e58fe9be64e9bf28a5824d415b0ceabaa8e0f3666e6c4444ce789fab51c970a0c167ff4f1b695b1c89c1429d78e2de57561e4503eccd260511c9b7686a52d6edf125b6679ee73b29e12a5c81543f500f9b00e12d691f254637e82d068347544e1a5abd142d40cf679fc4f2ab1acdf20f0681c05ce50f0ce411d25bd312e7650dd73c6b4284181363f3866f2ce6f1104739a142e4a0fd7b2f5faacd3ee5cfc6efee8149218c1adc6a55a1d9fba0aab093429ca7684cbe1005edac896441ea880c1b482086739eca530cac69b9267c58a2a2c5583347e0dbe9564b59a40f044ca8a7161c727e853d6adfa1e8eed71f6ac4e207f7292765a9f7d5fea867f5a915407500d5b7dc3cad2d2b32b5fcba3e82c3e032bf68eaa59ad067019fdb117bc86214630461777b01abe42550127a24e1440e39911f5b6e805639223a7322c280c40c18ec84f1356c80b3d5030ad878964eac7fd49006d319df707d1160a2e31c904a06b4734c1d31e83156c733d3f5fe42c60c1933a9de020a1cb7eba7b197d5e9f3c524c65ff780b4b88dede09c1cfcec1da99ed56ec3627fce66972e6f4d6f440a723697e3536839b12c4e74c59c1211216c182fc865a5a8bb28c09566fb22329bd8e756a4cec0ceb1a49bb64289f2ca67ad4e1e82dcaafbc6e3b469a3dc49a6564e79b3d16379f1a8007cff7a225f603f8820352aac9ab10d1d52b7a3062a941da9637a9633dc8728b38bac657e75be32ec7f841e477fe8d4c90a999dbb487aaa378674f99a33e701204bc9eec4053e785408f86390b432f15fd145c54b4b1ce5c9653cbc9649484bf74e7c91238fba3b4a4da24104ceb594c00efa0c10f509866f1837d56867268066507dff71648915d02d792d9ba1b9981280965a29830fece47f720f450ead62feec155079e8c12ed01db99018e469e2deb7cca8c9499d16fa78c053f41c173b5e536fdb6546a10ec889309c531d7d085f88205b2aa9fc9bcffaa049085f47b93d6098b8669ab0b0790bf3d73c82799ec09e2008ee6bd0799c7669178ec0212f7a30a2076303d6cba8b2b2c09", .None}, + {.Sqr, "-ca0ad7ac5f3600db3bd06c01fd94ee1adbd0e79f77d038143bd190cee95d2c2d742b1d35d217c082de0570ea6d96f5bee6ce244c7453de8b0ec93d6550ef3e841051710eb525f2496a60bfe947603ebe7f8f89bec80372db987fe2af40d7fa01d592ce9d519bf729ffc6776b57a56dd579cc4aaa5c88b18bd968b8d751cfabd66a4c331ba7550ea7d116c86adb7753416993a34ed00627e73d043ade126945747637e0a663c2995d3174d76abc88c38f6772c661b32124c439a1fa95e4689bdd4ce613ef7a5b289b40df8bd04ebf67e26c489294f026272ef7832fc42751bbafcb0969e22969ab0de261e3648ab76eda8837bfeafde861006d89a848755028fd0c5c15269f2e009c878390f76ead37c3f091a4023bf63118c9923733b0f1ace41536802f491791943d7bf172a2789770eea9e521811e36f20cb911ecdf368fdd23b9e4b645e2e9bd26f49df05cfdb57cd39b11160b29eb068e4f1fc7c8343e53845169fdec6f97ff59d20fc5bb2bd3cfbd26ba697fe8fb2133bd887f4feb883e7f2b82a0b14fe3ee1bacb39393efa654dc630a49c299afc92b95c35642f54a84b236a99ccd57736fc8dc2fa7881fef295545547ac1a44bb17a9e6eab82ab197defdfc44e25a30dba6f90e8eecac8b6a517b65428bca47f99be8c571983473bdf56f6d923518110e8bd4771ce1a41750242f8503a30e0f38390d6f2d0fd5a4308", "d6c90aa8cef25878cda0f77a18cf34b5d7d41abb8ce954f122f11c864526bbaac9bc78409d5bbe1c55f1b276e96ecfdd35ac1ad667e459b7d62f5ff76b1f4a5d0b9d075701c3129d7f256b566faaf9e876e5239fc0b17988522e38ab3042ef691336e8666d8c6d653ad063aa6575307b9acbb3cec5f3393501b6ad161ff39ab18723e8596e193317869f4209fffcc5efab4887e635966108fe82b77b0189996448477b0695803fec6af71ac80f83878369bfc2298975d086e5a042c7b3400783f8725722b7b5a7354b10dc4d5ae32fabb89c8c6473cb6538be557caaa839c53a4dadd3eb5a8128b4ead4fff645b6cbe260c4f880c0457fb9cde7403ea72bf6ee89b2eb0a397b0cf4ad70f134e588a98cba061ece461a33276cfd1d10c25640541ff162b1da46d719b9bb0acb2903cff30f6d7ea9dd0bef6975f7318e7a5bc9139af7251ed20e5fdd46efac2b6fbc8c26196e052c00c2e629e2da4d842480548515017369907e86b3c15f79c392cbc52832c0147509ae890f7f8e7a194e091496eeb2b69ef31e5c595a54fb3e25dd50203b1012bbaf385fe343675507e2cc1d828bc133463a0e6f4ee04e828d8eb2ecca2f8bc7a2e38ef882dc30bf9b6de6d5e1ee91eef4d16b98f8052f01e5c0b4886054de19536146cb424fc2ba3fa3d0956b7354a68b19772489b5923bb14f83325cfaa6bd440f7b8913621f0a32ba07b2ed", "9f751cd1956ba58ed4f01bd31cb5f9d854adf596e2489e0823cfd60d08e22ef62dc83d3bbb128a87c3295227015132a5e1d97ae6c99c398f11bb4a7ad2018e998e100adbd70ec1050d17bec45b3d3101e9bca58f504c6d2f10152a547dc593c4c642a6ca3e61f57a85a8fe541d70fe7fc9a40fb22b9684ba1c2a3f89e82274f0f06c8fb147b2c8490310c6ed17029d3e8a8702eee0c20d4ed45edaa45c3df3040d8a1204fececde90cfa02e35a489e1e1e3f102241c8b97a976c273ad2dda41d79c9f0f3def352d6d4221d0673e2fe975b71945d3087631f57f53f4d45e85d27fcf8a02de7aa57a98b0e0faf8f68708626aa855987132e3bc8380331f196adb04bad1c00fddf71e4a749964db8158b8f66d44667494f0ebfa25e7c723a4028181f2375f38ceeb7e40903ce833a5d1aacc7e83233f028400375667508614957c335397655fd1dadd274943deee125375fe6371855f053fdea4a790e565f27eddabf0cb619af1732b4bfec1769a997c2636990cb4e98a1a6eacd965196cda314ffb179dc6fcec812648d97efdeb6e113d41ff9beb87becfe3ac21c5b811e33028d63cc92d95f6f9bc4388c751ab14775cd7a678d06455cbab1c9a1f010be21925826bac96197cee076258cd4aaffee610bdc0e4a93a2e90d229f5b2fe5b37e5ede8618e8d4fc3d9902a53e1039e7445401f325217aa2b51e294185638e13714079f73160d7f28fcfa75e68d35e70440dc4d53a924b23165f35dca3d33a434aa36a24951e0aa0d90ab5fd55ddf9cd7073af48b66ccc9fb3ed7d6ad0466218ff885175c543377bb433042d37021930cefddade00c87c4ac5ad74cbe3c30b6ac55557991c1f5ff39037b0ade91ed888d6a87477919cb6d66026bdee304b17affe1ba106a58da1e61666ee5e54d104ef2bab3f4a589b2ef26558d776a529c5ce9b3d111c6c17ef6c0dd18a8be852dbec1491690ba782e7b9b0848234d18bbf304f866b0623be1fb361ba1c15b8a94dc28f602a8a3a8ad710c8e0bdbdf7a09245304885d2c4f84ba68ae66bb49a032f2bb123ba0de95970c5d70826532fce149054c78c994dd07ac7b1a5a4b55e58469e8cca1e474e8f0a3344fcd72bbcc9599d11fa6f2830bbbf88ba483f2e8e840caf5398d5db15905d6f62bc93703ec5b1ba4f379dae3e146da54ded425ae19dd8fd0fcd9f22f4d0a71cf1765eb883b55aa75aed3f5a651563576a8101cdb6c648bd96f7279671dac28ae24f617cc5612f0a21c3480be2a4636df0daf58891d47910d8b32927b2e0118581b17711b092a53b4b01113869ee39fb69324951e56cedbc753f9f9a78d25d2da38c9727a5cbf9642d3429afc96dce04776358cfae36a0c9d3c89517233b7b1de14ee98936fabb566fccba18a648e98bc5f9a756d3e9f6b5a5866a21f05f3aec5eb21c65839551032d3040", .None}, + {.Sqr, "6cb6bb52a0d1f6aa5638f2c3b1deaf0dde326244fe05d85ae199f8d2f8e5c0add85873d70df62a81ea289ecd834736f8f76ac610a30db7117d948a31b2206b6f3a8a66fff3146008079d8c960306dcaadcacd0aa33e405b24f65e0d50fccd1f608583fc841743cd3fd43a138382016bb57bea121b84f20e1c0377eaf15487da422e38403d5b724bca47c6332c6938e41d3a7a2c6270377e91ca8c0fe52c82a6cc9d746ce033490e52b4cb68d1a7ab9687dad25bc9d6b8802db0c39481017032b2a821d0f324d09e895a631871ebb2bb7407b9c151be9b0291573f9863730b413c5a336b4129deb6dfac58160d3f2516785bbfcb78a39e0d882e65947f9c6967bf6f46bf8b4606e2256920e2eb430e592e2266458e784df9f636592ee46a1e079a479b7b3d3abb0fd3a0bf21fd6ac9b3198b16f4c9a533c1b9ee328ad7e57aa886cb118315737dc066b122d2b1316d85d125e08ecaf20d397fcfc0041c700dc5c588c7f03cb4140a85722d418d09568f06ab2d723c3e5624862eb96c603f0dd6458f1c78eb8a56a87572b2c8050669bbdf45ed9101e4a3c19174fb0a37129c463120bca2049e7ebc2eab8066c1914f07fffdaa36bdd9906139ed4a0ff51a65a2145005ba34a2fa68f7719ab28f50fc4583c5f17840bee82a97df221a647b2cb51121f2142d87aad2f2c7005e9759cb7234f65e452f11d48287896693c5ef06fe5", "d8eca20d446d82a06c416669f4bf0b35f4ac8101b2a19ee00536c8453b6c45564681dc9299f84822f347038e32cf7435ec875d42b957a7a81c9b2d59074013e2883212a9c9a68eed314ecf91f17867eee020d00fb4f90add29682b6f5a8d91dc18162d626dbb977b2255724ce9d3f8b4b54456ebe6149c267c4aeb97fea85350f7fac0725d7dbb2b8e220848b5a47a1b532151122d112f4e3cf4a5dea969edde8d752a26e4251437c8cf6eaa714c77b15b68bf95f81cd6ed4b723384705215511933a9bbed185bc1bca49b485124de49f594fd4313f2be3c6f049b95b62db35025fa4c52853e432145eba94d16275d050c77c5b180f680fbab7ecb380781eb0a877a856de4ced6f2a5be3026f56dc8e9a00330230f9974813d73fef2186242eb8acab5aac8862666e1900bc9b717b73a062c6fbd95629963b6a8847118b5ff2a1ea29593c033cdd720fb9e55694a3dcfa0504f96f2147fcbc46e9d616d84e8ad2dc21e7a9b0c983a7eceaacf44924747926842e92b9a811eea2e6f447bb73646901ba9033acbdd5ad084592afb9bd0dc0ffc22e3a1acd624810e5107d85708adcc508d5aecf2bab018a5ae99071952d467613b1ba9f203ee156e19d8b64c47bb84e3b696a20b61a6c0aa0f543a8564e95cbbf50140c0b49660210bbb77fb7986784a6741ecdb33c4c93c1b26bf2ab1983c3dfee79cdd9bc8e5fae1ec1907072f", "2e2ab07c9a3fa4489cd8a56e570dff0af6b477ffda2ecda59680e78f1c846dd8173f24fa50f1a54bd60295cb4b9a9319e084990115b7be8f3f9b277913eade10675cd741197c2409a33cf41d8407e32194e55f1816f9dd73dee0580b31fad637bf8a278cc5ab0851b4136f5134649f65624e282728f4953be1d473629936cce8714baa1f582017d2e64df27ac7954d8659fed2ae0500371ee2ca6abe50d6b56f960787a0564ab50d15ca73c938bb8112203ba80da3e91f1b15949b90c705032824806f5c2331183c196f838d64183c17c27f57ae146138f44417510cc896216333b6cdef464339418d9c2f4a27a15d5a94c5a46e2f4a3f6c9a3e48cca3a4eaf57c6838d8733e1b7b8bbc20892b3e220202fc29e7cd1ae1d3a74a13f380d6f3fa58918f99d162d47d7b2f4f8e7bb5be95699d2d32403e486f42676e9b20463b64b6c37d2cfe5e95df70ad79c094ca6f1d0aeb1119625c8ce2009236ee329e1405ff043fe2b18226c27ce5dc449c8f07f0ce1d65a522cba60abe84f59241646f222f6efd54478d35eafc9b930aaddec2c413907477983294847a0935a657d1d5ad3f9dc64cc481dff7dc63fc3bb02f15fa90126c254a8af028ac604eba2badce29be5fdb3492fcc610f86fa03a4befd48b543ced45e1b16b526a3b99508aa7059cea4bfd29975b8ccf0b8c7abc813d98a507859abfb0593838d22c0f44ce335680efbffb3d9810e357cd5d99639dc077b58674fe82a8a1410780be867e62d44662d69756ae55fb509cfc5b2c2e15f823b6cb9bb3840f4b468fb68f7db14b9c2fa529c883db7d0b26d80bcd20454e7f151edb6958cd44e60b5946a05241aec6b73596144d0f54d696e7f377cc5e5e459f591cc852ae90155bf2b6ddf67b112ffeb2076182fe0aa9540ffcc6b6e723b13604c541e5462d7c1edb7b48655112a41957f7cd21bc7f599c31f617215edcaf6ba7865a600d07cc5078371dbcdfe937e16eb20695b61bdf8f6946086885750e97ae7ee16bef736b225d9f1281bfc05a3ea42170dc5bc5df7f70c3677aa937d654a69823cd2cc8b611b8b8bd1f53599211a8a36bf413f73e234442b2b81f5025141486d0e7267df4339ed83c6cee05ccb56a528ee0d88f9e85cc7d50594b0f3ed4e8e59629b1e1b744b61847e0d6fc54bc776dd6b2b69b43d115a5e82f9b97eb81d925426642edc78799b2a318e7469a9d2077cc5c0de0c78464ad2d2cede11173cf1bf3437ba461ebe3b9378c9acf468a28c38d2f6999c31f14abf84079ef0a76844cfd88303f6d28e7768b53c96e35eda5bcfdfeadcb73bb95d71991b8be0271db2accbe1ea46a7d1da8272232a2f0bb0960e8fafe6a3fe1bedb532ca0b7e25a5899fc7eeae70591cc475ce9baed89df5da6e1073b01c47381b719a3f87f678fa0bf77ff2784f90657b00fc1562a4862d9", .None}, + {.Sqr, "91cdd7fc16665fbe6ba5801687b458782904999a51a3d1e8ea24016230e3fd032c33543b32c73520628d65eeedea7b24780f82eb9d00c2f738410767b6a16974ab15773e044b496547c9c4f2317521f92659a3a9ab782af0d3a9bac196475fdce67fd3d2f2f68aeccfffbc5143fc347fdb0b4209e979e0355d23bc6578a50fa3374bf14ecc9cf5008fa4d9ce2c3abf879e795bce123dcc2c761ca3483d7c5bc3d895ae7842f2032b4a425679ca546fde6fb08f4ccba72b8542ec113076a95e675b9ba17c62e07ea72af6d7b6314a710d2edfd01db07d0b0eeb11dc8bb7128a255703d3ac18eea81bc401fe968c60b1808eefe01dad8f4604c0fda2584d8b2c13d2a2b086c6302aede2168e7f374a663b2d43b6c965a99d157aaf7a6501264168d4818f0c70b33128fa3c8f7ea72f5ad3690e20046d403e1f76754e902f1ddbb12c06150e0230f22a24ed63a6b00a1d3ebf12c1042c6c2b1bcea36c5e25694b2a710a723339516efde72f2a4e0992ca8154965cd3e264a31959ab9f2ae7dadb2ec4c096c02cbe07c54068a49fdbc2d857a0b75f05320179617c95a5329b1bcd53e38bfda82c6574c84706538cc4b1734e9fa073c5f3622c0db4df39637eba1bccb1c211e4994b5d883a783617e58d8de96865def97cf9bd2965beef5ee75b8220ca75f2be40411018aae28963e59db3e908b9278a8d162f3827f58284f090d9f0", "decac61b36accfa5d0b0b38b5e9421b81aa77aa142613fa4a3e0511b43d55eb8c47c002ba6d0018d583f57f9003a8f2fd576f1631b7a0318ab3aeba8b04933f25ff321101f02c090d0152f9a224cce4609aab57b6da783fdf352bc0f04089999265617a377f03d426fa03216b02600888313ef63866d869e3352eff9860b2fdcae702dab94aa57797ff9b64874f97137084669f4b0c743bbaefd48b9966d303f25cb7d33a8b2fe6af2d976262003e90b436f654e546e41509f8fd805a547b951f4e3b38f03707a4f0c553d051394914171231c0e5222b7b56bf70aaf2f6372aa0e595bfcfafdf1e8b80bf3203d8b2a315b86bc6a5a2a8202698a6e86669cfbb5d065b07d7f8621e23de475e91583bb08feb6d971360cc9f3d75f775877a71ff018ccb06443945727837726e7db996dece4487b4b9737933d1a119ff4f38fb6de652172711d9fe19a93bc1c071e8a4dc6d65d489943a825099d314bc5013bfc6c9c3c91406810e73b50ebd9a71fbe848443424514e48f7f6671f3e093ade1edcaa06ccd0f2d3453cf0beb001bcbdcb6966d122322d302b55c1a765e7eb1f1c2f5414e1503e2f111d4f91c722809da57b800fca309ef920cf1f7a9a94929c07604627d74f4252ad292ec7f0e018add11f820e806662af5183689ebbf4eedbc23c6b3b15be3c8e7d553df0938c72c18149e0c5fe8415eecdc82ef695859bf881445", "530ad42f31553e471d3dfb41bed6c2c8a3d6a9faef6e261797c9cdb4e109b581cfbe86e7d9b941819d721c6fe2ce66af94ad3d1c949770dcdf5bb58553a71c8103e652cb82f5e88f092a719378b13b750146b372e506c6e79090d05b20429917e7bef71bac37e44b28173f4df5e2aae0f4fa87683419d459f9ee60ddea6a10f3aacafd1d9393ceadb704764f98e4626ced87f23dea2bee990ea328440a0f6f07b5b5efad0572b818d11277213fbfa660b7c49c4f5bc78fa5617c997c4f84743afb3ef52e93ae2445203383d1b08f6eecee39b09f61ed65e721a306fd44def691b12c910a4d73f66546d1df6b4c6dcf82613e50e20313410d81d9985b30fe67d5a72d4d4aecff53ae4416031f01768e5a85dce251d002dfaa53c4130529ac376adc8e516d5b660f37161b053d5505a50b8466dde958c78b5790206434e9b216299106691c14448c20e78cd481cd4014b91e443b64df1e013372d966178a4fd5ae27ef29f1d0947d11867af50b33989d13facae8259e067fa9b2d4d8a9557a70ae9f8ed35233a24d068e4da66da13ce9c1d1ba9906872d3b6f10338f47ec1c9c7484f37fdb55af71da181847e314758c96412fe256c7c7afec53c8c51c9162d3c8e30d9b5f27e775e746bdcc1518dc41a41628550cae3daf16ff2f2d53397f651669fc0ea84696d47c9fa96e5ab491710855f8159b7a55c83b54272c1ff402c2f64da9eee27ca47f5dc47cc06d1b416b1dcd611d9fbfa744220cd5d17f47858a20c50becf80d50be1e14b7e1a1d384ead7a50f1457ec1ad96b147b42358d472ae889edb729d970afa27d3a333a6dcca343391051fa097e8c9030d8616a4233c0c3f280eac264b81a40178098b4a01bb1f16ddddf4da821c2fd5a7f1c27fccca6e0f6d1368d9e2e5c94b35af13ea06a9051607b3fb0689b70392e976e939e2e27a202c56f2afcd0e2d370c65d18e7a267346d24c830948f89af525550ef4276233bc9f8bc4921e7d77c88d4ac9d18b149ab14c23c3002368b53a4f17d6927a54a81b50c806292f5b8b8f8ef5d241a73b67e03c92313f3ddd269440913799eebb4012a9cbf26e5bee7bb8b81fb48c4e5adcfd62820e3df7971e38454455832fa744bd83c58f15d610ebf45a29cdb43be79cb7065d15702165dd825bda74d2d29dd63bb386b55d781cf45410705865548f43114ead5d48e2f952981078874394fa3238f59bd40f3dbf04bbcb1f00a76b0aa7ac4c007c9ee68de243725f2cdacaf9bd6321776b0c878a6f56dc2e3b0e9189f2ab797f41c59aea637ea2137ac034fa683a5f4c4abf7ec7a089bcbd6af84631e5885fb0b4d73c426d33faf6ac4868d6dbf96c21be7e47a11d635acce1a88400e89b35546367e7d6148acd35be7027fd42ad778be61a20ac43b91a3b54200d5497002dda36ddaf15a045a286a17e788c100", .None}, + {.Sqr, "-e49ec6d89c2d310de878521daddc653d0e687c89485540c6982a1d2e943d9172e096f01c9c52ddcce90ffe811f47f86d2c0027372c8030fe164d004c43391bf9e71464177190debbdd05cb09ad9206ce4b307f17401f173fd584353553b8edecd4cee16febcb5495ddb5f2a12f50091b2118bdbb1219b9ae6c65cdb1c962c918bc27e01f2ed650058c455f02c10fa4c3cea62b5d7495ec1039d58f6b7f2b95365c1b574cbcab2fabd89e58ebae3fa6092fc40dd2f639ea9923b796ac5c78a4834934e178c9f43d1aea4bf20c58739b9973919cbec68d1a8e766cf8fa6a4ed9db7f9ba510cc8ea064731dadab0bd666abc99cc0d3d2ce41f36a7e4ef3b962e10014ee169e694bd9322978a360581406cf8f42e0b2d771476f88ab151d8c7642818d138d60828e0a340ddb64bba265ba536466a5b524eebecdf5031fc54af476f30faea3be9f7f8a880728dbebd003b8a8a846f0a4b81cf2ce2b0f7101386a7365f4f34b2b780129f876003ec3cb4a53655f9c9fb0e4d15f0df48f288628bd2288978b245eaffd6c984c7c047ac29f8c5ee3c83564342ae17efc212d425205a497ba9dafd330e1fd1c0b09f4cecbbcc5e393a6246b22aa7f44a375cf8f94f9b69652abb33f2cf11e9c68aa2ac79897b5ffcb799a8f519863d82f6e8f8f708bc2eb1f4c7754596fae8c11da59d3c4fdfb64585786ce41773d0c440f18615f04e948", "cb5d3d7d021865d86b2d04e6752b3516c5e5aa5bb03814ab894fcac858b7dea8f52053dde86fa09acefd711e5bd179244606d8015ffd34a8ab0f80b28cce67d0af0bcde4d058b98494f31e6bd1ba63f81de2d9c3b9913122a6584ec912f0536f793617e2b4a1706b565980a07f307df05fe549c2c0c0c7d90f9bfdb7554a51feb2b9298e0a0393a7ab752a62753db061b4cff48692556304a7f77cbff65cfbe91b80741a4ee11591b6e82633536948be6b8a302e800a5daf513b3979f8b534fd241ab54587958bab2071483b29caca0e8497dadb683c45adf0f8d3994682148c3ed39137de29d402f24567556c8f978e8ad44f0709ec6d2a56f47206f7f4144ddd59acccfaee02c27d4155c48d97f9a01ab53064847fef3e613c15b709058600eb3be8821d13184a714c6d07a50eb2fefa5ea36e6ccb3c710d64674066fb390e82600ce8594f80b6d0ce63aaa29d908b7c812aa4dbe826f9d11c45cf9f151f0febe5c710d9e071895da69af27a35348316bb4995546346ad09a9e4b31ff49d3affab628ff4c0956c9ee1016cd70b6e27fc32c4fccc79e95cf4d349990e9a2c92d48df4d9d791751ceebebf13570868389cc465e8001d139af81ab814d9154b15edc275dc7fc9a774ec6e9957f9845af97e35b957157307b42f1d0eb8f5188fbdb1b869045646dbb652c07e43446aa0b91c299ddc48f4fe65a90c1c2f60429b3a", "cc2b34abe405100726acad9fe0005d8892a2ebf31cb73555d12c72562a311663c09ce15cc14c184088ae15f8c5bc0b9e9de2da930c8bcf35f5a8fc094a85380577dfb338ee19029e5f77f7d42eaf5ee2a58047a4bc6fd0504e2468810953dbd19ede5f6b83a3144f587604332e1ded7de6e5427a0aa418e331107cc8dca9e9eb1661766ffb688a88de92cbff0a8fc1656949f453a1c61a5f6cbef870e7b01109d4dd6479a50d01eff46e0f2eabddec1013957d03a47352a7f31ae72aeabe81c43b27c0c177933f035cf1cdcac32b27f9d9439a2c2b414c1d78f2912e13ea86f184eedf207ea2e712c5f7a1ef316d8d91ba69aae5ae90563e7498493e692e13ca6497f6549ef339d638034af57c5cbbc6c96c540d29bd3b085d56736a9c894444d9816e0f7cf104738b09d98be87537817d9452ee15d70e231979e635798356365dfb3fba7edf79e1006728da2f1a9372fb9adbcf045971c8233d9ff7d5a0e148bdaf21a3880a074bf2b038aa4f5bc5cc2e42ed1b804a2344dae42f893157061e30da12a666856d2fce2513349d076049c84e95ffb35174c78269a24aed096817411d28e723705559925b817be90d7aa7057be244fb76b7dbbd1eed050cb81c49818a5a47b2f770b6c42f77f8828324373fc3b00f7bc1db30618b60909a36f26dc20dd1b13c3017b569847ee0c9e27264aeec37eca775cac64d68a97a1ec9270e82d4a7a6e0fe534f01e97abc97cfacb06556ef818412c4b9ffbebf93aaa4b91bc6de9586af3705a1619cac416d17c45a2c1778b34ce069b818b4fc346c152646bdef74e57b1ba609d41ef37d025c43d1ebcc4b8aac329313938c50c0d0284adadc18c566621f676f872c202ddabc2a40ddf8a4910876988511819a8fe4f576f8503841edf0490083f200ecd70515e9b6cd5a4df3027813ef2eda3c64bc7ad763eeb90d3492492b391bf2dc92a0806d581c7de60ecac52b28de53a5d8e4761b595031f4a72505e7aa14776eb282f1da8836a5ee3597d547ceb3b687895b960b2fc252b97cd0842d9bbbfddbb805e5283768ef95ab92b506b55ebc1e264d325774a0b7c365c10001da276199024c2311f353a879cff88d2be8bd800c7de6fc844d7d310a4cb7e9b4b11a776656cd9bfb3cfbd056366d8c93e0a64dd98db63c19987537c2cb13d565f2d473788804a5c3fe68726da9f3713ddaff7cab734c38066172eb2430526ce06924d8f000a46b8f6d2cfa1d7f9e67bf65c6fc3c615dcfd950897b455701108649a28ce5eac60e2ad5f65454e2f4cffa34b32e3be7c83e8d7906813b440dc817627f5f41264f2e3f773a65e09b0b36a3ddb00a0ef35d327ee6f0db9242258aa4219780133295fef5ef5bad4b61569b9517695a10081e0008822713ff2538b9d49d28296c8e19725b95e0f65b2848c8541ba72aedcb8ed42440", .None}, + {.Sqr, "-ae5cbf57e68a5670436d0a2e6300be0a896e48be00cab8fd91adb767dd50e2118c72ab02d9f496156793f41ea83f277aba824010cb72d421428c847f70608ffef9ded8492c67adf028bc0bffd60b698dd45f846af531986a5b09b4728591b9c989b0acc1a4fa74c94c0548fee5b542c7141f53a1dd3a88f32dc4e820d05c7f3569a2ae2faf3e96341e8d7fe70408d58d34fda8cb144d912a4607539bdece6551042ad103ac5a6d8060c7c2803f4dc00aa40439009ef897e938c8ad04635a163c91d02446b4ce03a64806096d59a2340c65aa8ef386d3b8873180fa4519e803a73975ace1a30921776f13e081ee2194fb67a13aac4426f8e111b576ebccaf60cbdc8d80e55793f9f931051e89453badf9ae89bb840f952fe22a4a9a2525a1954d2604f21e09de4209bab778ffaaf0ee7876a7df3eca4d3f4dd76db3a79319f6302e8ac0a95711a503ebdeff40c79cd77aa6c936ba5f7996f660754d78c4084ce26a8897660ccadc43c0cd955d15f25d4ef5eeded94bef9a620eb542d2ed9d55e6e7ab6a1316a9717cdf4fabc485e066717439cff741ec967da667c4b34967bfa48bb56016923024189e6e9e68cefb86b1fd6f10f5ecc387dd026c9cf9b153b78d8fa8774dfe80474d3fa018320b199cbddd382e8aae8c5e82ea3f218634d7544f2d55800f4e1c355e7b8d2ea908f94a8f85ebbfc48b202b7ccafa6c13819628ab", "896df3cf124608cf5074cf89dae4f992d1c13a8a1de9646d308fe2d87102efb530d94888e530ef7a080b30e1d41b2fa56de635492e3586e3268f22e588c6e951b30e1f8faff9c09fe376d9b843c4be37bec64aa3a1fa949728473e021f6d5dd2a91eabd9d9869b0a6ff4f88c9ca4379a589b9aa3e6161da6a0ec2165dae5ba346aed54f236110b1beb9f4b1cc2cded9694e394630f5458266d977927f495e39dd609e6cfbcbbdbccce8a1560b895eae3f9aea96d03463b1304f353f1e5d4d6d9bfc2dc6f38eae42316c34e580828527504b1439cd7f17310064be67bb7a6514ce937113588bc9b826f9f754dd86dd7f6527a76887b08fbe1030820a6a0534c681ab4658b0279eaf36a18b1f0f0ca2653cff04a7bd64734bbc84150a8f2646118ea4a871161e382efb7b76f209e23eca08261397f449f05f7bca0d06bd770acf67cca94e42a295957f4b2072ef080f655dfe057bffcc85b09ba7f1990e135172890cdff54e5dbec99dfa50570c67b23b9eb1f2fb7cbd8f41129b2dcedf28045a595f54d7e424571c4e5e89da4cd985b94d7301607ee85274de90a2d78d5cf0eda61695a77605824728b32f8401063b1f6d2b9c9d02947f3e7322f43644c5cda3944db3f084fd5a7a88845dca07b2fa8b1c402d60a04812ff2c214127550c8b51cccafbad84a8ea0e01f84d986d129179923b84d39e53637d6dfb0154ad52965de", "76c235b59396091faaf7d333f09a8c83f863fd8b718328ea0410d72752f8d1621333e24a245bcf06374fd1fc4c3a334d725260109f92182427c59e13e35ae78db11d2ce027934061c00b92949f31b7e04fcab7862036f0f1f8da80809e5049b117ede1a287e43ec7785b49761ed9ee24d7e5c39a20a3c0bea014ae6e3f828d6832cc9d32cf24009f2d1700081397a4c54f9b35e63ccb067eb4b0afa458ea49db7cb057ebb06428d7774f0a3fe1f0f614a7d8823aa1edfc9e5b518d3538bc4d05edbcb09a50de5755961254fb75a2192b493af3ac5b1d946b23a7901f4fb9ff0c9179cb9db33d794084fe244e2a628fcd8b1e88dda07145e6758a11525d66731ed670a0fd413cc0552a962d2e0dd356cb718ca2e92923cb997de1e3eb59ab1e92e85a88c5e7fc072925b930e628b98d819d4578581913356295d16169e20bb7535b162bcd5dfe680d6e4a060f604cf1945fa4645864c3a1ecde1f1b3aaad462ad6c8054da62195ba007eabadf5eed22a29f9cf459b1eca55d1e2d90409aeafb50f75090ef7601674849d86c825f604a9fa1c4c88bd4cf9cb32e380bb79e62b46624188e5ad63f16c360c4dcb14573b90eb49777d36c5bd527b104df6860160a75380b9c1090c8743321ba5b0dd2c43f5ea950c9eddfce8448c36f0f2fb8d57fc0e730be2e80d0a7f35a002832c05e5f003ecf08eb5ea637c1449335ae04b9ba43c555600d0f8a84afc026ddc97547c82e53bf6d6f049f4991e7ae3678d84a6839159ff1de4b43044c3cf537ff873aa742cc3a4743fd29ef21be2e1ec0b917f1504dcf37781124a8b36c714c135162e5b36ad9bee148f8c8bab2cf9d259a13f22fd5bb899185c554b2b8f2fb5ae94c848565f99340b14b492354c5d9316dba0047e41ee1f87c5135baa4348b5be3ae35cd39a30c55b3ef47ae7a64b6a787b6f6d60ad2eebb3a491f9dcfb6148e4e586a802b07d810288f0815a5c947c79940c9407469acda2d47f6a6c8e09af4d3955f3d466f95df6d49ad756acca5228ed59cb78f8e84d79c86541001869fadd5968c0f1002b12654f4df872641bd09f1661d209c37614e28df07b7678373e11151a95d02539174dee3133af725e050e467f299e7d541645b3ec77915637c867c7adc35a32975d6dc59586ef689116c4cf36c88f1bf61a46084331405451bbe5f5c782de98b5580342c976d7feb4a66e3d196ac14866fb66be2527a28a3e7cf399488feedff69b30f56a56cef5184d04d4177a79878db687cf05dfc84db9630faee913080d791404cb27627ce7c8f7cc0a73c5a88419f89805e9ebcfbc2e71d0d0308f72b77b1000852ed63d5113efcdf477b1178d8b0715d25ea5561db111fa0153bd33d21ec31c77f39b377926938eecd7af455a8e2bc81965fce0550406cfa1cad346e004d7fe41b5ff07a2efe7204d9e239", .None}, + {.Sqr, "7e3406ec1a670269234fa7d7720624f338f420d389036342ba9911388a84f3c61bb9c8ad89e16c35e25f4a54503b4ddd858e600b042c73453bb06a35dde02353d06a39967668fb7b73f16e3c854c174a616271ef2223dbc06730769cad386bc293a1e88bac27d75064a2ead658763f167b0a7b6945096b8af52500708bf85b5e4391a38e6c2c0e2c88d3c30eddaab7aedefdcbc6623ef34eff5f52bd18256983b4156fdbf115b42808518800ffc7bf9ba5eab94c8c0b2d52a25a4de0de5c42a91ecbfcec3e1e0efeb66de18e549382a816ec89f3e2eb54f1950af4a873087f61be9ccfeeea718723271783c544514e845519a1a152b3394a3117288c2af57776123cd6414ff7e4e3ab983f830b3aeb37951a82aea88f97949476173c8211d48acd7c730b220213397b1ce0c4b17efb007fe8966a5d6df238b7ab0b51e126e24c3e105c36c27de5479d2182dc07f87af3680d242cb3f3fae594f613fb5e81dadfb249cc5ba88a77134b9007d31b3be652d2af7413d23bc6f1a24994e168c9a4ab442e718665b9d433ce9cf8043fee65131f9b38f2f5cf6b30111369c9155b443f1f965269dab437277b952f0024b2785fdf74c5b6fb56b22fdff7ac7c6f4e63fd06613972fb451103b16fca363d419a52fb9867a27ecc7fbc3984e1f161b3ace0a4c4f715fa857ab577a3cfbae4c78ec2b1c161cb6a5672e3b9f6df8cf29791ec", "f30eb31b0a36536284cd9eb1e11e422682b0f6d8f7d7d6a0f08cc8c14dd63dedd2866b460ff36b08394db838c6549be3c1d32358a3b7d7b41bc9f3dee1d531ce713d0c5ff9402223518022e189b1a2955c94bf546a5b30669bdeb4804368be21ba0a8b314145e5420e0f91067ff985fd6f9b0a1657cdeecbb7841ecd2448a4810c95a9dc984438d1ac552cefc629ef4dca2da4c032bcfaefc6643e95d78b6a5a8131df860480d582ad6b60204b6ef19b3d6c24b8d232f361449ff2963280de30a754c285a496daae48e00baf565cc9f9d2ba9364c1de3ee04c0baac451c8471d89ffe5ffc836b48806ad2641153639b44a0cbd1f3d1c2d8c4c8b4a0176aa3613e5fbf486595fb6c6def93add9eebd83ffd089dd59d38335029eedd04dd0bebf693675d81db9974c805fbe129475ae57d04a5947933cc7647a1fd641eb0915d9f2318606ceff1c103a399d1bba6f3e18c725b626084d941adf454d9b32a7fe23e62b213dd02c779b7f986e8d079dc8ed5be3fdc456534ef3aa50628f681a53f990be4b1fff10d897407e9e5d0bab0ae3f0f1197d4876f7497e94b7894533fe346ae2e077c125cea5557f8dedbb84ff9cbdd3404a385d2454941d1817caa4b6130d136467285d58d06c9ce4d93ce4a123f27c16904fd112fdf1c01ea31eae14255dbd8bf8813dc26bcde611fdac6c7d20ec1ba8594f9fa3c8eeb27270f7127abe9", "3e3741633a180b35fe3b3705664c555d014be83eb78dd106c184910464a5482050822531cb7e36bdc7d8d21680c4368f98b28b81415ed119b38a88e3b1db4fa9f2477287f6d2f6356c5c1ac08645ac4f3c177d1637728e32cc47d55edfbacde5dfb439f73a303619ace86726be828e48ad2d009bc3d705cf13d15dec778bf4788363ebfc6f5dbdce236edcd6b64a140807cf3eeec2935edc2cc96e2443ef9ba81d3c3465e512e782f2e3fcb68f642c810b075dd51dbbb314f9c7e5ccedc434170f4d71490f8dae0d1208d51f268cae0bd232ee56fbffc96a94931702c698c1045e2c23ae0ac4f15411b9b171514bed40ca759e1dd5e2e0920b2c79b34ac82ebd832ab9fe9f59596cf4f98e8c444fef6235e75ceced06100db0163f2208b8d427ce8b867e38147351a1f60f2f9e9eb790577c3eeda6cf626e1d4321eb1f3af0aa4cbca7653ff6b8e987a7e7d1b4797af05573968fd3c947cec76319557052569674d9edff6079083dc282216b8d0ab898fdab53cb13c70b19bd9821c1b809ed2d4add71255b0ea2ccfa4ac464fee94cd6ab4d8edab0acb5cbaf08063563580d44111dfefbbebe13128033d6fc4ce060b51d75a581becfbb3899ea950b57924c86ebc9795e941833bd9216d08c6d5453aa2b1cbb5f97d7ce0bcedaa23aec129d7aa2ed8c1dafbede471d1a204d21e21b07edb1313c45b5fa645865d26cde165ee60fb16b77c074517f81094624067f7bc792924f626604c21b72bee5b56c64f5d744b5e56dbb3443e40829e451ef2d9425b753d077685ba4d9b6c89cc8553d3d388c37d235a45b53ec9e71e82139245dfd936d584f60cc899d8e77397abc4efe3dc12c4afec779749b8f1bc5ff8d9d3c169647fd7e9d271b74218e0a83c7609d7a5e52e601b1b2354524f952cc8f49eeed1a57f44c59273de9fe16bdf5ee196608c70bca8cd8ec0b9fcebe7769c3701d04395472579b371a2a0eef2674f204dd7421384c371d799f7ba49db24041d9613141cde0cd3b67905bb1f73b729ea2f5f9980cb8be175e9e7997198e98111f78f44370348d890bc358a395d1a87a67fe8cb5498804d171ea7cd11a078a072c38842b6dff4016a59a47c0855715925750b4260e168b2c672775c6e37438082cd72ac60593d8e7bffd8613282795ecf4efd908e6b1510dfa959f24f72ee74caad319762f088b7b0f226a29898abeaa483bac23907e4b95eff03fa6ecba88e8248416f974f3010e49e676c52d35be7b3f8ba2d435cb3e7e0311c1ad71e2a749d2245f05dab8c1a427947e4f46ccc5c486da5d1e9d3a6fe8c9a49eb8315a76e1ad1f078fc76ced69cbad2fafe0ecb60a19a9b23bac0c6edc696d8190387b69a02208fa2543c50f6ae3a8deafb1b0d09375f847153ba23c76cd306cab0a490b07feb29414678026ce0b20f9d573abbfa7953190", .None}, + {.Sqr, "80c4ae10cbea3d3bae5d812f2470f4e3efbd77993ef6c27d7616ed7129d973492bec95b6cb7d72d31cc672ee2ceb742d8983913c55c2fd9c228d9ead52cf08b86b3a28e5229d35bf9eaa47a57fe423986bec99543ade81d894b7d4be94766e352112616095727b86a3e1ef159d9b00bcfefff271a60064df669b0ee3adcaa974c221826a1aa8c593c6bb66d82892ff6026fc387a3c3284892b161c0a8a7d38ef80a3601230fcdef837f0cb3b0b565fe0f0c064414f4be3d2b9b1380f3a26aacec4cc4045a37db0da3ba16c2b75ecfcf07eb484502a82dcb9ad668540579c249e5a5a253789f31150f4d6bf2ae647cdaf3ce4f39410be858b45783eda184d6723e00c1141db21fea50ecc2a787939e24df6818ad46248e2be38de7d1fa46199393bb3fd3582c60366bcdcf05faf455ead6e6a1bdb5d876be389559df868c2bf724a80d14427bcbf955ac5057e5f09f20d70a94531dff7c7558c91a84928e90255402c575a96f597c5d9442bd955bcb23ad5ed999b9005deca95ac299f588529c27b191b7cccd8136144635e908fee0cb199afba13c47dc8798d4dfb72aa0de8833901442da4df27d05e4c984af3afaa8c15c56108d54eb7320356cb5af24555c09d8fa7a26e776ed97eeaa967d5e36fa173d9a89c750173669f1df11a22b94476d8da1dd1604d5d1611837aa80980b7ad78f2ea42309cc80e4459d0d2eb0f0044", "af89b2f5dda11c0a677bc917653f0e05a0a242feb37623a47c4b0a0b88812ddcc0d480eb0d59e47dc2774ae86c9b4aa087578fc9504711d6b1da3541d75694c9d7d8149d29fbe5079557532aa16d875bbbe9251f15828502258bc158d420fd43eba8e4e07c780fe3aac87f6441cf93a8aea1fdfc0874f7c79750edd0e80de8114134fc799d10c547cb87dac14fc8d46862bcb3b02792310d5243e1a7768d655e3d9d546b4112b9a7429707ca4587de0cc1d0ac630577dceef1063e53a2f484dfb013d91eceb36b2b8a0a3f52a93c187c0d15dcbc2fdde86d39a559341d9d846a6b24bb6ef339d0c94e6a1aecb6998b48743116d5adf0ffe54f181ea5febe1ad5a2cb12b63a2bad15124ebce6647c126cb1e11a650cc58dff7be9252278306733f5eba6b6d3ad859b2f44a0c810c85ec858954b467e145991495135d371562f212ac4ac88d80383b6e9f5e938725286ccfb052c89560a374ea178569245e623996142004486301d110486a1943535fe6feca4acf2aa72c642346884869c99a6f399312bca08268c1ed24f56384ddf6110442ba01f0be285cd7987b2955e1c04e1a52d8372ee1b0cf63d102d8acbed537e78e43968c0f073813005d0bba53017ab58e3c75a65736a429a419f73afc1e159f8918397367d750aecedfe1eeb401f9362e6851d52504d9556187cdb4454931afe4155b810a3b358e7ead8ebdeeaa0a8", "40c5452bcbfd5235fcb29c4a82358a1c5b300bd8ea8b46d314be91395002a0a70f7153c524fa65a72115d9b3573703bd1d94321841544457b7dcd104b02aa5b2bc49edfa41e23d500ae7bd8738420cd9c0e57f74c66881609b871f512fe31f35dae79c9a243922c12084045cc3ecd4d09090d662b1ea0cf544f91194bd19d7e6d5bacd2c68285d65750bbfb0afa1dce50672472fb86176d56ae1cd73cc32be73ca068aa2d378108ba7f5f80457355da298b3f8d0be1ec8bc352823da691812ba56709f17284f8d0157595ef9c0ca24aa5a27ac39cfbcdfe1bea005bbabe53c1347ed8a163b56ce9aa24f2774bd57b2d58810b1ed4fcb8b599e3fa433fdbcc7e0206322e51b843c90048af8d78123e3321abb6f9629452de078d2a7d99270dcf8c694ae0e9cb6ed6b0c8b4796a30dbeaa3ecd1199f07005fa8ad149e08024786003d80a058a26741c8b51ac3570050337e3b26add29c0623c92d19d114b864cfdd619f841f4c97ca1b72853fef0280dee72be5f72ec68dbcc4e1ce1347635f0e2fde074df8275bc96c1fee4898e3aace1ecbac5a7dc0b1b5ea328966cdbd6b948e91733f01e30845557786ddf71b1c30bec22367c0c653dc269e8cfa3443c01dc7a9048f4c0fc9604675fc42a2ef7ac698b6f2a0304c3c3c051e857c57c558a80ecbc78f337d6b9eba6b367f1cfea918021860acf3561417858572a9cd8680a44a8a102ddefe9f339ad13d76ca205ec0a06efaace1ea6c854950835d4abfc561906063bc6a9a2df5040dbd8a87d887c7a9d5865133ebab2715c0ab3079a5dbd649d49a7770abeb42312de200faf2df1f1e4e50dda020ad724eca328ec77e061bff9972967bc5b00031779d4883870f0a063f36f60397d42bb0e71962f835a076309d71337f11e6d8047e81e75a502f62ee71429c6e8be86cb184376cc309c9ca4a869c2d1d2b758f76efd44163ed33360f342949f8b1e567ebffb51838570c8446a8594ac0963aaa4ce2779f8052cf32bc44eda37ab06fb9e6332a85094dd906dc7ed25e4123c4ed688fe43684e982e43455e9b2a2756f953d78944ffaeee49ccda1b830b3a5c0ea2cbd20c3802786fad463a43781bda02d06f13e193dd17d4655ec1492ac5aa3b011644f66c4407d510fc201481dad094b9be661c6b9d884f7d5baf380842dfa583600fe818f7041ee60a3d171c785c8e68810d49ae39256e5e385e0ef6304d3e8840775fad2e389c9d2b3928d183124865e9fc05aa658cc4c9076ccd6171c1eb3abd1250d3058720c21cdf5d5f2ff68ba1222846f747e2e6daddce1f3a3fbcaa94049ba7bd9d58610aac885aea7f8f84b13111daece8227accd5f45fecc1e4357a7c4a7a43a5163308b5ade0e24ea034c6cd202c63284ea12dfed132be33be8965e1c6e453f336965a5c58ca3de2cd1bc12c277aeddff81210", .None}, + {.Sqr, "-c1dfbad264c2b6bc1fdb8da5c072b58bd4d3d079302562593f38989375019eabf6786db9e5c70ee83dfe9f7b6b303c62199dd352c7970f647816fc68e43a3de05f7c72e9f46124a43b91ef36fbd3bb1e2ae959530b6e09d346a7674915787025783696cb312b1323c2368004ca942b8f13c8bd480e816be8b19a339526faca83136332b1910e01df32295662ed5141b564a25d6420e9e18af6a4c6768c533c835dc819082c415e9860d0b0270e30dd2a425724397e79d79fb49574e8e6e0dd0d4b3365c2dfe9caecece6b7f9d2f1c42e61b0df17f0032896b1e03b96c7ba9eacf96e7f59a37f06f3b7856dfe8e3278e0ff4a88e40d3dfc9088e3edc8e3d41ac6549d2aaaebed2693ca4a17768d412fbb4cc5f0b43f920f60567d0c61c1e503bb256d5f8b60514d9e0fe68e7bcd5c6257c3226dbe39b68fa406465300f4dbdd19142b93bd7ac795c037f81a7cf04570f341c211aefb5b9d938bec1954dc3b77fca78f43ac2f109d491f6ee2ae0f9f6431bf0a6aa1bd71e17e505d748bf1a66d8945104ae6ac7a399b4a38124ab3ddd15a6b432bce0b7a96c0c14380c45720778d93db0d3b53c238ebe44b2a23a1de0abc2ddf70caa54625806c8cd8b7f08cb3da440ccbe9c0c7bd7778764a58ced5d64823f6a12a6bf918d50066519c671a62538da48839b04056201c735f661600d71323164d6c3b826b16085643840504cf5d", "fb4be692587dccb3c216df408cd8ef7d32a8e129f33688d8c7c1805294ae4fbfbd4b9b0b723f16fd2b3b4efbdc5e46ea2959cab9276abd838082495562787d51a992fd78fac87a943ab0d12b09f5ff62b4ad4c8d560e97c1db25d6b21659e2b50a9dff5eefe9413fbda42947198723b625e26b4097952e126bd0ce97c94768a8d8d74c9e96bdaddde45a275ad3aaa52112adef5c4d0265d4d361eca195cec2d8130f24b46a61731d0f4bf80f391b8e460967345b0e8cfd958a517a398d70e712f0e8d6c58394d597292fa1d6641db06e24a01bdf8a1a1bfd8850af7ed62a98383f0bef758a0b53d7ea2c2237f7064f5ce7d81298c6e525e205fb8500b9484edba85892af16672750053f0a2cfbc3338967676135cf7801f2f20250ed46b35bb48fab79639dde432052ebeb2cbce508612e02b8fcd6ed17a2c740911410aa2fe751dcc6afad88bbfb539dfc26e3c5a04cd2515325be417e3678c9f4bb9fe77184ebfa65bdf8524ed60fb9ea49af2b1cd051e621517abe7b6fb1869bfdfd429ecad39d54fd69f851ec6fd964065abbef186580e85276a48e735f0a4a67c9ccb692be04329475904320a2e29bf8d7dc70ec90cf3bae8e7446ee11465ac5bf41e72146f996f2d344afe3903a86a911f196935ed15a91b425a9dca92e6f0dc2c1dfb4d8ae90ac112e5068c5a24be75e0eb4e926c52a7c7ddbfc58b4e3a64a9b430cfd", "92d31b383ecf8a166c6e69e0716f5422b5ed2168d990f1a41d2ef6326b8239b0b9daba690f74254de35cc68a7684053966d9a11e699d3a13a7504fb6ba0460645cacac0f06e3748402e1de48a2ec2ae6f6f8a35e947a377042bd32b8a1efbda54594a218d9a20b04f7a8372ba4b4873661d1c058d7a5654bfae8cf38d029ac7cf2ec7fbc832766668a0d553c5d43c5e60ec8c30710a43cdce3926f598c1cd46ae7549ff52a0eb5a6ab0e79aa63f8b6d9e64bc5f5ba1ad4b3ff72d6ff7001c725f77b2cc2b2597c81b08e99174ba1efff0330722fea32a19bdc8bb94cb6f6565eef9899bd81b4ee0420f5006460f79ee3128ef91855f4e342b9f72f13efe3ca00acd5cc34eb6ab610e62ce04b8163e429b5693b0a76eca08fe443a3621b197889666764e09d103bc2c70558a0d4072695f5a85a7dc4af45051b0218f2f08db4f3c79829d6cf92d7e0a679b77683c89f748cb15e33f03db145424c21000fcac90324da42c66af1df4db49ca7a3f8c4000e7b9aa22cf895af1390344b57ba73e6c768915aae4b21786c45ed214dd57d746a90116b894cf66957556df583382d3559b1ba068bb90e29a1c8063e773b3abbef47b98b43db5fce3cebe5a4e76e8df3d594a3f2aa48a27fc3c7674298f3e7d82304011aab51c232ff08746c0ee7d5cc0565434e97fd508b67c7a9a599bc450bdc33497644d0ff5bdff04178f406be512bae06891e70fa69c3ea58e9e6ce0069de3dc074ad05571c962f12ea17d395b39b41a198460c882b7a9ac69fff4dde727ab08af27eacbb0c3ea1d1cc11e9ad88be3eb30d1fb762d6c965f5649c9ccf0d659533bf7629cabf1d68af11636b9400cb8e6fd9b4ba77cfabb85b4d49c17ddc60824ccf9bbdd439ab25572f318a7e5cb8ca05fd2306f34dade3526f00be5cfbc58ae1e3a94852b098fc6fe40c54291180bbbd239bdbc809dfcd7a82892809d21386e2d582caa21322677de1b6950fbf60edf5ac187a6cd167d683b3856d7b852d6c9017cd3489cc81720c4098208534c6c3934979af92533f64b6e81ac0c7510fbae2984a78bf0df0823ec76e91ab7b14f3d9fa8173f6019e1d6700446275e16ef11bc54dce5cf0dfaea10525ddd998fa1822b186e2b7a6da77004e72312ee4f642c22a8731ec144cc49b8ecbedac0ed602ec60100111cf7e2344dbf56f8ef6a8b853756b41a00bd7b4d35619219f3dea296d255267b4bbb39a8c07a97fb1dd53fcb576ff91978a14b525a35ab7b53387750efeec51c6ec5507a5d96c5f8d71fdbbb73b7e3adba037d6af491a1b5b684ed713d8488b31c39b8afcf2c1d28535a334d0b536c1ee1b1f6b6b4522c620ba73940045f681b133b672c76460bf15eecc7bb2c619b1a0d87b37896aed46d916c656e0b6e0ec8993fe30b8de78877f35572ab7b11c09716ce2d415b618c4df87c9", .None}, + {.Sqr, "-3a6650cc0cccff5204aa17796257af851ff261e59da703341ba37997fb058eaeb225107759cfa70a094c41523e4623604ecc15ad1c05ee582ce048252a84d467624122f79fe52acba44d0b4dc00af05f85acd32a52ee84bc53e2db341dd48b2eaaefbd59fbae86a4ca84d187d89ebbbc06ada4151ccb17e191ee774c299d598029f61ac47c8edb9f9fa1da98947763e2e3e44c82ec41fa7d169a3b18f9ac68ccfbac080b65c8d2040c8bda2da21a3599e166a31088a372e75690e3cb94146ce81e67cf57a876eee4d3b9e8284c2dcd48f212a12b312d760db0174df9c74ffa24d8159e2f74f38246d5f311dccbe7ab748fd5bdd207f36c0d49add54e4d1fdfd5ebf398937c7688d2d926f5b9956f2395825dc9cfb6c304765752f43bd5f1bea1523a0d5b634503b1d09d6cd98fba342b0fff87a123dfd14dfd678dd846e0b03826cd837e717ae4243d070b22d75eaa31f2e2a1e3833c2f31b037e05c8e735ec107c92eeaf4ab14dbc720e7f7b4457c5049ffa011712822b5c02ac22664c21ffeb991069ace3548e92520b63ca2e981b8a68f639c40462e07ab8c63ced9aaa0514132c5f1d17576208baf15668bc8b9d97bd02da3fcb97e32e9fa41a592d7732b7061ef14b67a1b0b2cff2ff2fe721e2768f9d086dd289ccab33e57f8859f29a59d33d54e727941bb7262b73b701969de2eb7df779fdef85b552c42f8cd38df2b", "13fddf54c85771a90968f5c2bc71dd6b7ce6650a3e83d2dbd2a2a6726f73e0e45775fb182f61198c761675fd5b2cdc23ed5c44cca616303da182d8c23dd585f3549827be3d65e332e58d40567595801e64c7180a61b0cd727fdf9a32580988db61d207088c3c58f2bfb1aed2a0a32202c950309fed1fe53d5b91d5c7b35bdf574a40598a6cb9751634532147578987d6844bb8f599819a20eb1d9fdb84c6f180f3d7388f3eecb959829555ac9d6aad21c9510f5281a4cf2ac3a36cc4a848d15d3774319e69312f52a2293a03b448a255de9e6b1b9625e4af3a76e8d78a16a69d3820d9f22f3debdddf03e1e7cc3f2d6f641b37be0dfd1b8cd6684728cbe7fdaf4f9560e275597c3156e6d6758fba1b4720b46c89dc2f3555bb8879b5fdda47e8825a522a7b8458dfd8aef38cee8c48219f0db5e6be9d257a2c50cb62ea7479f13237db45f90f53b4348aabddd011c64a83eac7134e776663006a854ce25c6e88286fd15f06495d101a55ef929fe7436210c356b55377e645493e3fedc1ed65da04c2db8517d68738f9873965ab8d2b5a426e1862d37d0a2e1d4c37a9d649e0f8d28d8314a29db0382ac21b351e88465f0f957da3a5870f0656313a3452eb0c18595c280a30da05f31efaa1244cf15b084a7ad20a30d2ca8b99f079d763e91cb3e24ae006e1892e3aeab6e1e685ea50f5c0909a1bf65ca3f5f482ed13912534d", "d528580f1e741b12666d3e70cd7412e5c7fcb4557568497d545f04f54498878aba812dec067f9a51e53bec11cbeb43ed300b6dfa346354e1cdc5741e2986a77e863e87f9f2168b741f634a98aa7f21ad1b510767b178c9f94b6ff628a30e583d32aab88a3638268ef091f6dabd42af615ce9aef43f4432b7faee482585614729a90ffa5054abfe725475428523b4f3320262770972e3e0c9bb24138464e70e8fc2b12a22d1739331a77d2e5ef68eb65590ce9f69bc93df7ea86e8ab18b3505d9834c6381eb5e23588b946b386ae8a25081d95863da17c0fde84fcc5f9194e0895e1619c7ec18227b85caa285347d4ae06860d0bee64a443e4b8996f76de7865409c49cf7de0643a03f29eec206a15631b3a50ea142536066fa4dc904e29f7ef6c8f299b22ae74f5ab2f9d22409e0a2ebbc03106587ada426b6e0ebc5349cd9e89d918eca40c381a73a0b9f6e80749a46761a7719f0869300c8a098e611eb6670fff962179dc74020eb4ca3afd982a3977fee8862380a5cd5f1c1cd1129723b34e4cce92669190bba17068aa33d4a2b542834ae04b99a0e23289857655c1bfd8706493086a4055da8d9b9b4b943b5f5deef5cbdaf00e6555d02b1a2f183f5c6ccc37f29e37da60f89f0f4331325d90f9399c3b77e62d92c5aef739e149f620b3d120858b6fcda69dc1f7c17737dcd2f5713b440cc799a352547a4f19124266e855b45c5c11b53519d2c69af76fc11ef7274d70202e99bbc493bd7466d97dac8ddbbe9407647fe7112e4f1f2069ad2e461e8beb6af3c58c0711ea3b14facf4a55f170f64dd3c7f9e4b40f989654039fc3c358f19a1564962be6beeaf8f7a914b9faf09973fe34062162e77d155de165089a7b6e2250ad084ee7685d6d5aeff2a78df7102a583ee4b4806441727208beef859b1e38d2bfe78f8db7f2d26884b79bba4a5d9db82082295529c25e50faf466ec21f2217c5ec2b0f3f1fd0d015cf4314d1198dbea33cde97ce3251ae4069f042491120b4c54d67f609f42c2df649bc1c024e282e74b57dad812026d5de756bb1dd766f8914f24ca524342c99d15c1ecc2be3ba5c00b0593eecb0aec4ce49ade11a5e7c1af94c5b9a2a4e6aca12a317f06dd190189eb229e94e1fa5d926a1968d9534c45f109890e0cb8fd1c9b6e02645a34a4eda07ad1f88ce5cc09796cfe93125ccccbc03846bd539a688019c4d0d994aa13c58bd1b0da21f0c8fcd13e605373f11c575e54062215d8edaf48ac535b11818370b36ac88aae153d86da9dcb0faead91643161fdeb4a9b2a727d97b1e077654cea107db1915386820e9b24f1198f14cbe47eac66b2c1ffc9165465b6a465aa98239d327571e6cd27dee10ba0b766bebf102191ebfd2af85d8d47cdff51556cb1ae34d5932e3f10db6a6489ae7f05270e74deb983f0da8eb15d435bf139", .None}, + {.Sqr, "-955cdb975a28108471dbf1f9e8474420a2b9073b20bfb0f9c52deb63dbf2f1a2e3e267519c07f0d6032d5508f95418127dd9285e225cbecce65232829eabb9b0b6ca9f2777e55d0d41b2ba19fa5f10d7e7e2d78a2a88b325e668067491e4746b8502e7edb62983b82f99f46764c79d26d95a9d43be2f190907d0f0b249f2c70139b734d795ee2d4712270d84b57698551ad149b0a410caa5ce5d9f24fdecd5ed532fe02989a76c60e9aaea0cce47103bf23a7eb138ba85c4fc216c1778d718a9ff10f8003e2b14a24e9e6d9aaa5fe28ddf34e9a7ef321d86330df57f992a5b44848854e915abc1c051ce13df8624b63cafab5a3dfe3bd4e48bc24d9e8bba262e229fd3c799ef3f696af348664742b60cd1aba9f9154d2707e06cbdd32c514e1ff21696ce9e9034f891ab304eb2f0ba207bb2b7b0a26bc4c6d326af7364bdf367985f688fdfb793faaad2b287265dd923840744e4476d5cc49b65e95f9f4ae93de76c3844354618fd6e364fb83ad511d1bc2fd26127ce421529e8f4d8c1bde30a641598176ac0afa08e91183bab7d72a8475803817b48a906cefd7f4d425a4de885fb8fa523c10429032a834a8d44545d0d8c66b70322223465d6fcfa56592bb0709edace81ccf659c29642b4d5a2f3b82fb39a35f5640c6e4ffe6feb6c44a546d6d1f76d190056facea5f5e772e304309ec8d6044271da5ba5b51df6568f8e13", "ce91ffaf2450dd1f7420312a26c3ca64aed33d06ef26481475e466671bd1f0648bb73aae91289df49281547e1f28500224faa3a0d87f52f8bf94028684d0a008f8f80cc3ab3e71ad2d7c40fe8cb6a79dcadb5819f3abe18b281d7baeeed143299a3869a8b30b6360919d89eb8b4bd3430e5336cfa6c9c5b2ca1145e67bd94cc79d44ec1abf112dc0f62d8d1fc94024ad3935e4cec0ea8782ae6b42baa54d0a550dbd4147e4007aa9487eb89e7f03aa57bbee3db1e37322910e6b5c82e54e517a050fe659970104fbc13c092025d048536cbafd7ee51dca3c28721053db774110f02a0a413f81ebcd7ee77352721beff2642eed41b2eebae4dbcc33a4af5ebba7e44d4d6561ea7dc7f202c4af1cb37a85eede3bcab087fbe16ea6562d5bb2517d2ba0100d617ac80d019c5e0f777b00f1b598917efcee3647d0d61eb5e1b6cf4feb47247e8603145ff25974af8730a726aafb68e8fe7875b539295560381f9bff6fdde6cd4b48fc7b7ec8ed55152f05db9a9dd4d2de5260f71636f7ab7d418a3850e49e36a9ada4bb39babf5ca1c2c4a1fe011d70ca0e03669faeb0c51ed8115110c5d6b79dfaa2257e7b9c48a1962d06dd6e72526f1d098830d2dc456add3e81d49b4de0099ef00c023b97bf421b7dff8c497bb248e21643e4d27324a967948f8d61e3aa576547022ae8e7edd4385ce09399d7b6dd36f13e194ff942fafee51d", "5725394cc017bdc2130226b1bffdfe6158a1edd3c33e77d88e5a2292c402b155c237d702cc8d564f1d55fdfa3af87d3f30fe36a3f16f8285caca6984f1d3466b57dc454ed3404e794dcdfb6c45ae8a0a367ab0bc7f311ea19d311ca335b99ed600d69f227611c49c34df632a057d2a431fee2afd409b790479492d5d1d7c075a65c0a3f7f63dbd7b78bd12b5d4a6cb920b8d83da28cd8a3bca24291a021c868ef2ebb4127d4e9ff94ba5c084f9c31ecc26091ada34605e2363e59a5f0923956df8036c22e3d952591460ff1730b51df1da133854ed2ad7558ff207be3370a1ee2aa7bbf512b9aeca46360e3a74300f73aee72d35c5e87cefe26cb7f750ae4936e11b64edf6edd1d2859fb2b3f1726d701b2847618ca4b2cfa6ff229bda7cfb72d5f8418333fb6eca2584d0414020d1128c438e4557d3791d5cffe18ddb99ba207826226344ef0dde3ff091f41d6b6e7c785bcbd2d15a98a04121164d09dd30ade46322eeb0d6436a2504e03f504effe8c36f0a3a5a3f611b449dc14be380a76bbc196eb9fe39933239370af6d8426535c797678a46f23cad73843f8bd8e2243a68c5952434eb6ec0cd5351c7b20f893f23a0cb40efd2d5396f8dc842850d4f30ec8322a2a19c0c62e9c519ab5547d81ce38f63e59f2ca68af37bda59db264bdf463bdd1568f70bc9862c4a8b3dec8dc4a4e743dabd28d4752ca14ab9129192b19057edd6b9a67fe8558233e6d396001340c1890b1bf73943467483a2c8541d697497f94e7e485117e61fa5d53a1a7c63ee985d8a76606a6efa95929cd651cd5736f29f2ee768ece95c02cf5d6f4b6527c15c8146accfc41686806466d2ba0839f8f146d1f8f72de28bd3969dd1aa8cc345c884ac24ae8956b9425482f3cb20d91de4d1a80f2e729b9a1bfa045253b5579f7500a266aae3d344fa38011f979d66af71147a231af64cc1ad22482fd5aa0d29bf3e09fb2388b60bd64e9adafe3e0662727bc963ee803d81aa394ab99c4de4b1b732fdadea4638e4afb694c38934789eb24cb44dadc0637c3a337e144e6e6c33cd8f9c2ac45c2cf807f87fc722442af04d22b684a63930cfbdb1d7de3e49a86db6a6ebb17233fa1102342f09377438defdad1dc83933847f12c3384ae8d712ea40327c6d9410293150fa5df3161115912b8e836df65eef0337cdb85ce3baf352a1c3e607c7344a0af56e5d6df5d3fb3ad2c4d434fd6456786d8a080535127d27b9bffc1caa1b88cb350c830eb2d9122641685e9eb53c142b3de67298beb4410beeea578fb00aaa49088c1554edaa85c0d19251651da47f05d7a4f6dce739e9446737991a3879975d529830b8fba64e242071a80a9b9712569a1f7a8f67c5411ef5dd459140f039918f2098e2671f5645ac7145b81fdb13d7ee7f9a7412ff9750dc75e62e3a8e4c64381e78cc131569", .None}, + {.Sqr, "-2503b2ead096694cc554cb737166b3dbca247ba2d0daae3fb1a592369344e24a32eebb6d1087b2a4a577c075775fbaae79ba48caf379b803499b8739c37236bea6ba8183531840812cb11cbafa239a8a7437af200c7e69b5e326142da703476f7ddf0850d9df31b21e3e3fec17abc7f75e250b9040e7c475b32efa026b1cc88e06cf26e4dec88cb3b5d12671cca72b2740495d7b24cef6d6d6bb81910aa50057d47dae8f639cf461196be9bcfbae547222dee10295d805bea619236d5387ab2683f0db4009e5edff449802eb06b9ac16165a17f65a1b1de3513296174f1fd0f8e8922c4c346ac407fe104fd1294b5f103dc829bb520b8f89a61ad516096437a772317ad19c1123f8e3a6fcad1d9390575a895bc49a4dbe507d05dbc081e007b7d07cbb86f011b05316c17c94b46c3521ac34811b070bd5754fb419914aa87a52e1d5b7f9939a9f8d60e2306566259ab8746959bc7face1c631815f7c98236f0ef56372320e6700629917d75f82ca47730401b5cef79cb5c2eac979e8f6e2e080745f7d02b75acd6bcd0cbc0aeea18a05e47657ce567843df7f21a5b61f6fe077e2ccc131e774a9fa2af27039edfb944d7bd373471d0cec0743ccfcfb1f9023cfdbdc985d005b5649a31e95dbb1b2271cef648366422675b387080302e7119d14b663132c3631d71c25cfbfcac6b60579a156226209a6529fa1c45ae844629efd", "fbfe3869c798762abe691fda0f40c1acc176b079c23b0472a1a1a9b48a5e3e1f5b74b39ad71c110c00a40cc64f7a350e61b1ecf8fc12f050706e7819eb60497febcbc5202b080072bb9177ef8f0962a06213ff29be1459a5e2b276f60bc4a8535783e56f49f8c48ac6cfed1d86f5f11e014cf3b79aea5cb5915a8ed09a7612f4b04ea45f8f0bc101239418abb6ef2757cb5eff83261702714ecc22da45448ec7b1a0823e245ac0a1c4c17424fa20685a069b6caffa848879bf26f408a0bc39679aa4e354f13a7587babcec510b88a74198611deed678a2f0ca45f7dc636c0d8274b5cbdc9d48b3c2f80af4d1db49633af362bc163dcf04dc4d6ca219fb540d149613346aacf443e4a19ad9b7a7b3e9807859c6d333d5191d99aa73c51bceeeb04a13b7e62822de455afca6da64f2bb1c63a9dc83d2884b4c3f82ec64806de6294a2c14c69308891ae1b0fb5f7fb55f1f733145011beba4a136942b6eecc4b918b371a4d254e0a8b641b6e9411b83ab20103fb4c4b6c2d1a42229b3d045730e5ad2478bfc6b0f3970b13bbce39297f0871a57ab991bd37fc202115f00286de067e6c1282fa53f6162565d15ae8f51210b386c60af976bac964369ab38f4b4da26b9c5723ed3e86c8ed98ca153e3a70ad4f49810daa8452c0b6e15041c7fc5ddb074e2b6ed0d6f050b8aa188937e9875b35f2ab70b0eaf26dee6345564f3267728", "55a11c58ed7bf69d033290b1f5dec03365ca0e7915c93ae154d054e5910cd90afac71970a45fc96be523a4ecb7a7f99682d6ab3253aff5a5435bd28c1b74f250a5c863f7c9227186632f580012116882d3b685fa4da79c5ef54a1d44980ae42eacf42aae5ef572c3b5752b22a1ba5c3a1ac2614b5537635aefde8c3d54c281a60e0077d2ae0a2e08b2e959a27a8e8861bff165445e0c824d75e90ae1147327f66afe2424f89a91ce496dfbfe44b83e1e8f1262cf7bcb7fa6ec0b32776fa40fe41196948f3187da06dccdfe424b16b42d83f1e3f69ed5dac038b05e77a60bc86d67d9b1455050bd91e09e4b09a37f256709cf6b650dc1f7a2878b482ee762b220ff028c59295a8516e40f34a3701a6b2f242ea425e804e46388d1030527013fb8219487f9eb65512746b2e849639ff72c772c5368cd147af396026d49df6e76934d0b62392357e5247378a642264d12ea91217922b23f6b5da8ed0bac35332155d69b46a5eebef0a03b6865f6177a2d261a710abf9ace152b4ffb82ff02eae4c63166787cc9280683153123a14d9afd9aedef616d7764bf8d0dacf97091570b136499a3cc9ac1a1813a4958cf5c3dd01deff07793a50cf560761e969535119e5d46b398eba7fe7cbef96958e8f3fbfd4b1e5cd17f56db8755e828ce4bef1679bf59e5134fe5def35355421b9b40aa8e3439ca23080f1d5599bf869dc4568af2068010879ae857fd1d041944aeb95e1ba897bfca8f2d3c47f5e3ffcfc0534bc635f5b31495c849790e14e15e2d3bb0d252c9f4dbdef047282408507916f82b534ca4405903d67504726132363e80e21effba8c44999b17f5df1bce805ee191e8ec26a360bde41e9b52424fa92408fa967436f682a91aa4255da721ea9283eabd35891b148b623ff87767ab1918c305f1624009e379a84fb6c916a83afe76f576506627061e5ea25da4f83dd5d785c0b06be5eb154691a2c0346cfd3e235facb5a3d825f978d252f8eb3467bae428adfa402abf5b53bd2177ffccfef568878d749adf79a38b3017dbeaeabb36e6e459c3301e7ed6efebed10c6e2e4d640a5395379f537e19340f8f69f7de9b45ef2e4b057470db647e9677a6abda71f5ae6d39c41150ae59bb4a888a00fb08b96a6d8a318118b1cb6114b35aa73fe15e7e90a0c098af0592f02ddb99c0cc6db37c42a64d149538edbc113fc201e0c9a68fe7e88c30b11b3b0dd28714b7836d53d48f0f22569ad4feb8d7d1338e99695e1d3fef6882f8c35e13d7d3c41b6db9e4c6b2a734aa5b2fdac16a2c391243d093badd7eb99dbf94a837e2840ee25dc2bf057a87f00ddde57576ba1cb60217a76f8453a32fb8216d7d5d0af2784d30753df1150717218bd464f99d65cab5a30c28239bd3bdd40bc22d1cacda32559baafda2c9b79bf61ed60f946c78150a36990484714609", .None}, + {.Sqr, "3b6932fb76a1433f6cfe3297a49bc4223770bb5d851828322f2156b08f74427133286791006a881ae15f719ab1634c19281d8f64e0bb991d5cdaae60eb21714440b615eab357b7711a7df47a49862246b969e6ff9b321b666ef97c1370cffb978ee8157f269d2eee1aa6973eaec36a22ec8d199c151a2735375f3f707981f1f375568c98085be88ac1a4cc2cb6fca472b3831f4ba7984d46ff1f8dfb7ed2b03617008b2cf97344c397dda6d41716b74bf9eca87c4397b5ebd20c441b58ac878d7799e551a3e8e93c57e0ae3991b03833c2614cfc4e32c5a0eb3980bcb2044b6154caf474a82d50bfabce5217791b59fa485db4dd8aa857de23afea96fbc03afe94436f33f8fd53318426990a6098bc1069609b59b971bf8aff4f99a67eb5fa10453b4a5e89be18bd5f2bc05cdd1e56a6db1319aa7c7c6ed3ef41dad9624a54af90cde2f37de73aafafc9b577104f85d01cbe9124655179c081e951a893087ff92177ece02092787eb417235d746e7f3fa7404b06ca189dd834ea18f061a97c326c15d40231c81c900e8b2942c1d56420edccbcf49932f89498d38bb4874f6b1358ac75a3499c0d88df8bd23a2f7e1ab6bbabd539ea5b4cb13aa0f0e51dc95031f146f889b531c660e3667689021f91d58ca4b2ae399a92fde2e97208a03cb7738d19b5fa1bfa1f4b0460a991b84e4f75c1d3c4785a2eeb6d5d5930be1009792c", "9a08a28c2bd6769e9d843843b13fa1e5469f69577eacdeceb6aef15b176e7a5c89055102b03b8adad1001167479247e02cba637df8656cc4e67a2d0be7b93a7373ce697b904db054f9f1252c6bcdf33c68017ab2f43ad83fbe266cf1cfb08332262aa20b068b65c7ad2180d61439dda4177bd13f12eb37c7e4e83b9966c3f880813e3c825c4d31ad97d3c1ceb954d12617de172737cf0f7e746210d7f165a4ee9d01de83bbd76509c4a74df338fdbf583d173b05eb0c426802a2277feafd67cc1f998179b3e89a28ce4ec5f76cb4e322c371e5dee2a4a216b37b5dc1c0e21dcae72d91d0fa957c77d53d6b3a1f1190d6bb5c7cc0637edae9dff831ca8a10ebbd158c464c7b0d23e852fbbb1956334742dc0ac301e9bdbbe63fd7eb1b90b45753e1b5b4d190f36f445f412a59e92dd3e0ec88311042f4da0980b5aedc8dd85a628a8a4872893085354f7feed55ad7030e6af91bd19627f89fe7e9db4036d8b8855ee4ae1e37a3409aac8ac7813d621654d39fcbc096b81ca61a8156a08a4354d2b07e79a2c89a153cc667d7c1a656752a20d7e52ebcd497cf1abeb91d07361f5a660feca8b961051327b1d2908bc1cd8b220e1a0966a3417f7bb483971135143acfa838ba9f444b7ed7bf72994e434ce88cc122a69dc4629f9bcc93558d80577e864d5777e2ea5d6815942c2adfaa662a53f1f8653c698ee50c38c03af7971233", "dc9a8bac51cd6a13bbc485e8c6af6fb9c2bcc38bb9804d13abd1f25fe7c55ae82a932c6e23ca075809a53cda698d7a7fd6a4291ff1964cd6400583de931be226beae92e84c8010bba99473f72ac9e9c7c2ee38e50ff98b26024b2715e4d53b9574592a39aac15da7a07f00e6ae85134c35d83ad5c7184290a54f6253fbfc5a316dda078bbd584c9701ed283a89fbefff0723815aa1b6530182f6fbcf231a557d5766a65e9ad9aa1106d48416ae0c0eda766822d5e9c0d3400b922624516e06e99ef7fc445c44b1602fe25cecb97d29a791958122ef00b3c60e438c07e0c8eb97e563b9fe760db17aaf5aec90b0d62cee32d524c867cd31764310bba54c5c9639453c7386c90ac2d0ce7bceb3b1e3c2d46531e3ba8ed106e1ade22e66f49982b40957ffca360baa32d2e3b9d69b8dbcd766ddbba57441d759b5d22e3fee5afa2674818ad2daa899ec2fcc99729cc9d5b0d7b8cedb523837487fd2778beca987c46aa8356ec83c0abb7ff6dffc741108ec6455ae431f339834a57eee9ed76a8673e661a6642a2955b4f970488d82f2e56329ff9d74d5246f21f19e15e7fbb2ba36a94199905b03bb69d7e0949cdd6f8c4bdde5f5bffc7da7ecea36936b953f4dc66e2ac15b4e74687cb7a743135cd00043ac8221be4266f19c4341acb117ee901fddd3b0b25b11910feb7b0a58935b8f916a00c05fc1b55db3b2abcd1b379fe7a2a0a6a5573661eefc3f4616e375b31817bb01dedb7fe885d829b341097e1686935b5cc2101e265ad743c59f681e5ff46785cbfd280558fcc277ce53e95b3840e6100d622c9c9890c10680ff168cca370f58a00119bdda1143af5b4f13257312e1253efb55696e78a2a277c49f8a9eeab54f65e4767712cac7537a314c188ecee83a7674fa26b2ba33fa788449896cb1ca75b6a2240d0a740567b1863eea75db943a23790caed320c0ec0ec73bbf21f58aacaf646a93372cf2297db4f2669320ed8672ebd942b3837ebefad04b5b36d8c7c68a5864a31fc52b9325956212117e23f20709a7e52745317e69289a6bc2010746eda6766da44e7d709787dda64eab4348fe926da57d4a0e32af17e5da5f80a2cca08ed6281f5f7af5c39404c9afdcb0f4a81d25278a9d805c76b7576740ff02af726afc7c4dc691554325a84f6c88e6cbd046cc6a26032fffa081f3f5a1e6531e3e16532609dbe68fbc3afcf1f04e0510afa0a524aef22fbc99aa346085505d3dd73ea5e7c5a7eab1b65213b0dcb5ab94356c77cc5afb6ed8236ac4a6ddf44c2e5ca8c7e9ceab53b84ea7285b7da79ae2a44fd397e5c39d8a1d0a08da409d059bd6906841f5fe21900cf87df58ba1dd0e58d405096bec20b5bc4011b7c8c8f3b58b840c17efa5b64bd092c3f83db24b697f0e8a173d825b97c2b8cf57197b52803c5a28d6dd33795198ccf3e729f90", .None}, + {.Sqr, "-c2d509cd90c158a125f4295e8c8f7187d5f927ce27f375a615bd6567fa422e0b726b48347f9e62e70ccb9b0e86bc9b416b27fc58438e9f38b00ebe724602d380724c002c4fd1057a84bc10efdf03dd909c59944785b6cead2d94df6479d8319cd5581a40c3d36e8647240ac7d20aa8554696a6b32cc8f943dbcc04a2d1d50f1bdff43320c04d56638a6dbf9829425d372d8019ce606bd1d6f0e89a9df7dc8e9bd77e8b3d4f0141b4869e2405606bb0294ed37cf9554952d5fb244ff33ce137ee05dbd9ea1cfaeed00074a35b908e5a811b20177b75382a4947930b7b60926e91fc7348e7eb9b0622d97cb039f0f6390a83d03f2d403bb6f08df5a3ed13665d5960ae3a603db6b71f2283be6fe59196032583a5f05a5b1c64196f38ca44cae0c46668109c3450a61d05a90db58ad3ca53b66930c6f75358d92176e732f0b67bc8d783a8492220be06ceefe0b9a87e19c4c5f34bfced66b150f2594381e8ed963edcc6e8e18a5ab3c62ecc0761df4ac740aeb9ce4f12804aabade4da3a5c49c44d5b1b172ddc93abb48502331150c64a02044930aff625e43f0268c42c55543a9cafb54a482a54e569761d5a1242bdbbe193ce3e30d6dc0e2c6542932b6d5f53e9dbf6709e665bfc479cd189f84e37272036a45ca46148e0abde3af8c2e1ee0ec46f7d86af7485099fecbe04a6e9dcbf84c243ff8dc724d1015422d6fe5214bdfb", "c6455c644c2b10ed37e4dc531f68dd047d4a638f10cf750a83af4c09e60f223e1e6fb7156d9a8bdc29deec191a6809626f4ff4da98a199453a14734926bda701bee06e67e66799c1f829ce7957aa813f454ddaf41322dc3e42b2fbab6730735354e2cfb4cb633157116501114dd533930d0babee30c024b37bf4d8c8f69c0547a47fb77f11eb68470b41bd2cb0ddd6941bef9422a1862a60f0bfcaf0a996c78537aeeff1c7d8b1f5fce0281339aa9ae6eee75783c766c4d32e3b93eb4a805b47b159fddb49d2a237531d46df9ac99449e5ab19a5e2770f39fad85a4f81ad016280542e29a89f3bea9e6b21484f03c50f936f0e1f1a5ae53bf4fbd84a060198c2f3e245dea420ba86931782aad15aa58cb57f82026073bf80e83cabe8a5eb953be51d22ca0fe0367069a2f27d046f08f27c034519f071be976e997168915755cf6e6154f10bcce39293df4d6f4301ebf1814bc52543a726b646f5e5691433eb089186c4b0367732b903dd5d01480ba7067c1c36295ec166934b667aff92fa2e4727732bf2388739317169b5564e57a950a134c572c034c41264153200334aae58fa2fde8e80c0f846540deb95d7a060eb83b0bf0a4432a3aa65731ecbe2478ffeca4cb5360efea4d93e6356abf52999b07ba714b34966896db0237beb1fb44ef574f0fba0a6f25ad2f67fdb317921c555dfc63d2153da227cdd0f36177db9d9bc", "94479424dfd80550796c937e24af4e4d5dede7ee8901ab0c21bb41e75b2b0ab3be179e24c2582afcd85eda6b0109cda312b3db4984ee994f342c107e9b0ffa75df430b833c167865b68f78081024909da0064a72a34f979a33194fbceec9e4f2a35b7447a7d128ca43fbb77670671fc0bef4a517f77ab1e766cf3377aa5b4fe6254762e53114d45fce7d1eeda61d384029ba529122eceb1f32677684c5bca94568ad8a3c12d073f7145fec04f1697423a0d94faca1c4c80d0af7effc3d7e2e38512ea655d677e0ccda3f058c55efa8f6d2e2a42ff574441850708f1387d578eee14a9eb46d15b080d1dc5f0aaf998d94fc54e02820a4582d2234892ce7e95ff7b859ab4629d69312d63fd1bdce52fb3871165efda667da8816ffa5879c8c71c98a99578ce424f1f58d20d403d767cb80b62e0f3e155cfb895c4a209e6ab41817413f98059d559e8f37f8d7f6fab3862c575a7aab9afeed3398bd6df03cfc3f559e8123c5d99b73e8cc382de89ccffbab33014ed3ee29abd1dc5fc4ccc4fcf84e83116a23c5a7c31bd4ea5da8c7d1ba15b087ea736ba08e4da90d334b7f00351cca701b804b559a89cf3a7ab38a921503fce203980bee9d6a896ab6d80c3f6a62653f11c283c1895d9a684bcc8570ce88f4f401315352cb1530b9667a2d015ed47a5b6e80a5b2c58a50b09aed4ebb77444871396ba3ffdf87284cc88ad6f3006c81c895d67e43ed39f126212bef856eb2739f4fc98985faffef95459f96c77a73a823a0b69e6ed04c20861d56dfadd3a774f4f9a6e5d5057804719d7b9a8e7add8d6296b9d300ab1eacd05c6f8e75b23c2af58fdf047bb35b8fb3b232d2eda656227467dcbbe8ca5b5f313c83100456a5754e0cedf402fbf0f4083d5efb643b41077c53b0e00ac2749ba5a04a37775afd0e5251d4d88f263d76cf2facd3aa4ccba9471009168e43bf38d0b0fff66316a6eae860db72cf163458ce830bfb06f1daad328104c224a348f92f4549fe6eeebd061c194909734259e7944f372f151217b0d0095053cc91007af134d87c9e6815c14d0d83884099c5531fa1b84e15f6e7129f79cfeaa8da052f480730bfa34e48938c330aead99d77a70ce18e0f70dde6cbc13880c98c18dc32469722338626dc4ea07021a3eee6800fe31f5cc6ab6839eadaf2c4c5618cc6ee7ab018484229bb155943af86b13a4fe695d73564af4f225de759c20697bd5310aa97734833f368bd07979931bfed338af09e479b175c000c494a335c2a9eaa20e1aed6c7a51d2696374f7ff04fdcbeb8984947a9bf8912a8ce8e5618fc3aefd2e8df1e78dff904ad442439a0a45732204d13c8a6083db399771cf7f7cda7986c4da5f578afc8d440dcac47c24565e5b80d68d0f26bc677c1d547851f19d4b0d4be3f229e4f56be1cd07786e0eeea06d7c5ed7708349419", .None}, + {.Sqr, "96ad2fdab5e5e8422469bd7bb57140116f34ab9e5da9a2ea3c446d916da5c0401fcd427b1f5f844034d42d5878672bbec1095bebf7c4706deaa4546c90907fb51efde00dfec8277212f988d58335505ea0d1a1c469bacdaf63e309100dec3fc6a9a972db5eb4fd6503226c9016f80574216edb1fe0fdd81ddb142df0e0c266ce8870d968dd20b286c14e783e85aee9d013771561454b25228e4430deaed0902af7aa3d2d4bde1321bfec6a19a3161d6fbad167990ee468a89ba508d5bae35928ca3083fa38f5ef18f8b223c4e01d80ce906beb7d25b9d49fb1ce4f9553b7cad147dfb792b06bd8fc4adc1d954ea1a5f674924fee58aa52050ac28f62508090497979ad65b9f2c9926d36164bd3f21c92b4f3e15cd36f3156f9690161e9f1357e5338ec4397a96a0ea043d6a21343839b4fbafa0ac11e65311cb47afe3f687a0b0b89524872eeb8c55c417b8e4c244131fd6eed00817131d177d4d7486ff77550a0839ac8423233c33a4aee80efc03604a54ededc33bb0e2b6e3d740fe1aad82df3c713bd6fc59e64144f4e8abeb5739b9f2e463e2c1ae289269e6e09f7ddbe63e1cdcb1f3f6e06d62dee557bc26cc1a6bd763b6b6a3dd37f67d7ad913f47f02092331623394b9ab0b8330aa78b4b9266121618d8f8ca309dd60465f97dba54fde20c119b05e1c2332f828de903ac282865dced4d48ab5be2a3513b34a96d8d6a", "2cc3d5ecc9b115b5e105162f49fad932d8440edcb96fba15caad718641ee784df34385dbcff4b09ff0c1d73b956502b74ab3eede8cdfa8b498f96f50b06f9e413f4eede626c62d1f0883f8922fb159396e4460126c174a3622a4310f512eb2535fb1813613082fada15cf78ac25f5eb28a42b37e046839031e647a52bfa54a47624dfde0e6cd459ce5f5de39c13ec2208f590c5e88e8baef819fac4da96474cc256719f0e18c3b6409174bbc0f47aa87c97ae2f9a0807c15b3bde206aa2efa9cfdd5e1a2354713cef9eaeeba93b119c463c0910636caa90cba9a2efb44132d63ce417b516305f831dea40e1e5f988696f64982bd770821bc91d23cc9220d3e32c34b0ce5b897e7cb8fb6c9d994d077fc7d3ee4140d24d01c7128fe22859d43c0e908399a28b29ae9070837ec5050693c23ff8742af431c18d4e4741018a4f5534c60f9dcb76c42fb273c1cac22318497af7be8a06ca762cee7b93e36ba2b209df2888f27c4ab18e0150253f08e3e47671ea78ca9075fe69d67b64eb2ca44c38b54b15f0f035c6c466fd048d89c7d531e47d5fcb748064be0f45f6786baeb347f58b921836af91b95b788d69234763718ff26de154a57c051b56022906c1d217926d0da13ac0b69f56c727f9dedb8047cfcbde5bbd224de1aa73b435ced9cd917c6dfe2915ef556a1a6090301e5b287b24c4a0e9f2c86de68ebc05f127ba33ec0", "58af693e03b54e8e2427e3e2ca08b3aa015221a8263e7a5ecf88c65af5ce400d19f37b02cb0eaeca159fb81d4de50e96acc719c81c3a7582edab899fd6cceedc6effa6a156e865047f0723d05abce60736b741be1ed266fdd8b63d54451c23b396e30a27d6e8f8e9a49eeb4789bce2882fe252f7ec3eec5a392e0226431d9070c0a84f7f5a3d645901189d0de69348dd73b4f98a28cf1c454df03f9c0b17298ba9eb2dc429fbf703dd234f21870e82dd43608bdeb76f1c76a683bff7e156fe2c6ff54fd6b688038a5d5193e5facbf279f22f126ced674b516b358e1fe4b548b271068033c67a2c5d7e692f5622471d4edfd3e599b77fc27b1bfc87b1cd912e47b2ee2eb4270cdb5bd88a5056ca3aa0944b529e6ab7304d74a118440c0f001ab57622bba719d5b02c8a22de3d46c85f64740ea3948121abc56d0baba0405b6eb7795bc4eca5cdb7afa2082398aacd81f6ae2c37be344ffca4833b6f4300fec15a0b44c0f58145abb06252ab992a62ae901a3afa489c7fc54c2fadabe013534724081550fd950f524ac05bf22659a617d723ce78d0b18c82c480d6f2e6cda6c0b451303eeab51d178f5a2b0bb328bdcc09b39535eb0a4189083c078fc412ef96eaa07b055dce304f28c70f0ff3d4b4a4513d4a4898111f1efb97041fc33ad3a7c462f4f8cf4022cdff368f15c8cf65d6974e434561c8375646e6cde8bffecbde23c5f181cd3b5dee6c80c743d60d5fa3002249354e75f3f6d2480a78ed4c357a13241fa7137bc9bff3a4ca1097a1b025b0dcf3906b4995698bab3a4f21754862e529694e3a051c0f7398241d2ae7c82cf43e04739587a5cc3b804e70eedbbc136ed45f79825ec59878b40f21318a5a716ae39d827cdd32ef131dd52a3f795898c5e164aadfa034564c55a8737f988ff35a91b8efe0e2ff56eddadd4431ce4dd6e28c62656042ceda7521a5a193cbccf51049c2258d6b22cd0104271eec0676c446b22b6f13494a16fcc931557fa263b1eeeee72c5e7c31fd919250c8cc69f83581d53fb36508b1a821c2f4181692e62e7737d18f7b6bce0cdd63700f1cfed84542b4e55ec139e6225e675be51a6f7986f433e25c7e6b3653bf797f3d6e114bb1ab51888cd20f19818c53ea72358ed8ab5bcdf1d95b17182c75b402a25d6f38fef751df08158fe6c918c77175f1b0fd2279d423702f8430aae878c1f75db42bb4bbc73f04de884d34584f9c912d1291881b61146e8c976410b8feaa2a64b351472153e792b8de4924f8bb0fa49eb0ab97a5eed9ef723f328b8c389baef399de713f1b0d8394f78f8e31deb492bd06f9a7fb2ef8496f10a765407d7f35a9dcf2aaf5fb6c8c4d519da20b43defbdd8aa7130daf9167c403debc5d4d3162c505b1f7d1bf3d7c1b3fde493bafb7ec55052cdef6b149d2452859157e3ce622a7ae61efe4", .None}, + {.Sqr, "-c49c1fa2fd441ed4af51b578154dff9c54f0592359630aa8daa06d8c44e7e97e28ec7536776a62aaeed1e698a1b9eb4a88ba183f61e9be646b6f8e40e6ecea6ab771616d032f8b59538c3011877f0c8632693f8153420a50ea35c211bff676d2b644c747b129df321ba7f04a3792cc71950a0e51fc6bcae5197a2524176dab2178f2d5f020646b3f1109060ba352558be7f8d90c1e700a3262ded7af9e9839419bc30bb6cf2225038c4c7c31a9545f12617309f4c6f9cdf01f42fa8d6e71d3382f2752440679fdaae69113fbf9e9a0f0086c3b5b38e5cac364e4f028fe0f1147e8216b63de304ec810aa00258e6460ed4a6720ab5ddee30c8726dda07a877bb07ad97f033d0790fbed3958f5669939259b4c14494e905cd9ca5d45e8ee99e1246d26252dc2c5bb2754488824cde6838eae3946c9c3fbaf3948b7b6231277b0b4a9bb3d40e4aaf8cc953c090f19c8e4a1051479326a35b306fa4078acc5654f7e8fd39be970390b08c55e4463df75ceeaf29006995eec1f1771c2fc82f6328c039204e33c679a47e32533b93b69ecf3fc9b81082caed3db554e3a9c7c94cf5fe6f6076de686e4540ccce4a092bea974eb2a288977786dd3af747424df8987ee3be17d6a4ca32193a59c8be0c6f67f2b1f1eced7c8f139be7c5911cf7259650e27fda13ae87a1f5f1e1a07c0e5dad3f2c86c09ce82cf560a76baa0db656525e9d7", "cec63dd1b4c413a59e1337f9bcdd7221f4cb647940627acd82b8f959328c12f502bdb464c5cf37a86b5a6b45bdf9598a6d36261dc44963913511057c5814eb5ad91cd89e802d31f309aabe45dcabbc3679b4cddd1960e81f1644ab1ede7ae3c065d8332c67e01ecb8a5e4ea0a094b0ad93c37206676ba6dec09aa0ef58cb7c32ed7b5e8a99df1b77254689f1b4c3c6c9ca499df2fd6ff969582d99b0d734fb396df0daaf609d0dfcf2edbe67a0c1d57ac2c65b0fd84eb27fcf6f67f8c0fd72b5963f46310994ab1cb27df4971528c5d393ecc092809676d22fc31a44c144088ea922a557ec6e59d4f0857ca6d1f55ea5edc57d415872483d4712fb5ee7c0440968496f11e9dfa94e51a6ba2b11b8f9e61ce50aa1b747124df96f92d4f848205139b5f7a806ea6cf2c9281fc996efcc8ef10e9be115bcc41c1cc47ac49b51831287dd71b238f11a3675cfa0aee67c51330f9dfdd3ab2c04462200a2eaeeed5d8bfa3d18ab362bf0a56f3aaac13bcf8ac84a8975ea8219e74cf830e00ef3d59c8075d76ab7596bc50e3d9421886fd472e8348e95275c34e9ec9acbc30d479ace492a712beb1e841b11990ef96cfc3f7b48d0311ca3ff127fd91b614424380599410de1f5997000511b61f66f6a8cf2b68a377500d777f1af21c5fc27b214981c20fc094365a366cfdd0389423eee72880a11f2561c8ab6b3d174acb0faf3ac8d94", "96ff6fa8265ddb5743e908297f91557c830bec9359854d66aa5299702b8f0dbb98e177d0ef4684e8fd3bd582cc3a39899a51dffaa9283a5b0aa26baa8b11afc7e9cfef7ffb66e903ca24d9638d8fcca408fd522c89864331d06938a93e2353e13cee08846b3d3423300443f5f65acdb97769d6cad5cf2bba407d0fa936e6cdbd417317745740f1b75cbdaba2f991db5c24bebe9e38da5d1112090c7cfacb023e6cdf49b17078b12704d717f9ea15f24f5cbffc678564ab05c1321931b9d6893ddfe46a1da7d3aa52562836e60d7d25ff693e50238011990f5c8922dc4223993e6e9339ec67c544272aa83168bd3406b65ea6674124d6f11c99e88e3849fb124b2201af982cd968657f02f737523eb20e9a2c8e66ee0ade103a528284941a0901ba6c6897b47586d91a2bad42761d12971039fdfd648c3bb3b92a94c12f31965328d93f7589359eb2721f39fb942af0fa7f2a9bed488dc39e56ade79802c2d92860ad1a90babd16586dd441f6aba142c3073dfd8a9cb7f56761fc15824fc9b7cf97bee57d81d3bddf91452e0bc3d67861190f8846a335fd9d13f1375ab788209c53f671072271a50c4a51d9f5eadeacb63daf7cff8790676ce06b91c4b16b4e667ec3fa8467c892d400b6f214ad8cd7de0826fbc9b5a5626e77f810493b840b221eabcf1eb7757c67ca99dc188c260c62acb1d176427336d8639f88308b9fc505c5878baba7f5b0edb156e0378f183648a3478a274a59c0cd27cf265a461f545c9172d746859dad4c18424459c9344110f88f6ea514ac9d0226b175704b300ef97e13a859a5584bf6357607777d39d57bb4a01e1b09f2ed53f550d3c68140d19704d7f39040d13caafee5850e175828d74d64c9e1032f4d14130e11e8c2751f3bebedbd24003c3a5c73f25609b8d8631fec16d5c822f03fa5649c38a0690cb773bbc82ebae160ce4046742ed8fb0252f337d118ed80af744a0e19e22f29901c9cb9b58522ce62419b9c304b3e040a708c53661ae4113ea57b5847aa7fa6c895c2c3435541db01032b29529914c3f772c8ddb06291b6ddb7d6496b2a2eba6fe2992d51900f5d9609a6ef180caf7fc90d7c34b303d7f0f3dc0fcae73e226f365acdd2e199d011c421758f4cfa1e4b980eec50694a65407c26f7f8e5fc6b2dc97daba7fcb0e1e734ee8db44b52c5e7465ab092a49f2625652830c593806d2d69a8272db2f13e2b4ca383c87971064e1926d16eb8632d7778e7aeede37475501aa060b371d5dca3e4f9fc090f505a69cfe90262191497e5fe273ae48041e707431acedf7b015507253826e2a326005199c7d93de49c368af6584526ceb910939a0060f64ed224823966e62e2645f3a21fca861ed71fce61b253b112edc71df6fc7053ecbcd6f5cdfe99aafbdb7a45ceb3fc321f251941556c889c8eb74dc713bf1291", .None}, + {.Sqr, "-6d7e95ae4c449fe6c58c8745782cd4873e73163f11579343d87c94f6c6cc176d595bfa60f411f96beef8513799104b04db4758042080bea17cb2104c012b3840e6551a2619cc60ed2b8b01e9212b92071fe9e462eabe211e07dc4b92f75dab51578a91680ca0a950fa7d4f302a010984af5fc294148c59bf4c3789e4460b8309741c1adec6bc840b184c64218aaacecdaeb954eba4c08533380ece31a929dd104d9b645d3abb5f5b1a3445589a9f04cb53282f973a6bfb2cb6af4f7b445fe69006356086def1969940e8ccdd08f365963283cb5d6065061057d7b46cbb09b51ce22dc2fe0d316a05bb4ab499c3bccb7d4b132c45eaf1ef0262e759c8e6f365fceb06ab75d54e72bd7f19dc24f3ced5d20aa0d8305c20f646dceb8b7d85a11c3737c17ef8b55adede20713633d23da6615d9f7389696140bab7454dc6fc78b4c2ec4fd7b715672cdf5f96dad591cb20a536223afdf7cc04a5537db2a14a044c957c2693de6d3e93c0e13b9868e6eca52208276d14620efdc01412bc6c230f467ebbac04ab132a444c56ff66550b0d87641e1002c175933c8b3d40c9ce8a8eac97b435c39200cd7bf03ac7957f6a28edcefbb8aae6429621f0434a8e4a02aa1059cd576096a8ed8ef927a988906ebfb8d8ecce58fde5da197433e84702f7cc159cd44ae6597469e7c807411f0eecce05bc2fba60b8c3f7452adfa59153eabaef53", "dec4cfeef98b7edd1580216b1471bf27f0ff2c99df840b23c061193e44a6c6f08931a9cd4c6983e82e4853d9c51c461f2445b7a630528e249534fb80b5d6fff80222908a732c075129cc743bf973a44aabca896fb8e9ab9105c2cdbec098b9ed05eaa61f6cc8ac3770223775744c7e15f8269f9b200ab3173566fa476fed08c62d014f0f5e2d1e4a02fa3dd6ddd078e121353ba2fe4263fa259e30ced26aa56d7145f18f6b2a393ca41a778880d60f8f0c8b94de191d82c80136206e978152607b43eaff7deee5f57cf4f5404e1532a257f65c9947b840e1b4980319f2f83c8639dae987b68de009c9a5a2601a5a6567870fab50622fb539aafcd61bf195376745b0038b502b9aa0dca2e8ba3240841eb9a4512a0c0d329b1b3d722e27be711fb02fc46eb68d849e8c015f88c0c47c79900bdd773cbba2cbc9ea5cd7f64971ab93538714fdd0e722c54e817ca97262d6eac3af551bc304b3a81bf8b32b49a2045e7e1c365237203f21363baad79e970ecc803e70c90a2c79b775190bf103ca5a76780d47ba3ec201c1a7db5f74be0232807a45bbedc2a2c1ae155341772700b9a850590f2e204681bd08ad8889ac19da4c2f352c0162a8c175d7d7e7549e6416ffa3b9cca374cad3be4bdbb273d64e34b94c842ac4ba4c7ac2f61ff5f0fc184eea7378eb78a721d6d3e4552e11fd08adac04ec4d916b4bfb1483c9156f4a904e", "2ed50a0e1c09df2b9188f286ccfc15d529e5383873177a32949c9487887d0534ebcbd1779c6eb61cddd08e86f5c8cae7186ab400344b60da8faddfbd113d112e99a356725bd260a6f3e395035de6dcab7b6cba0495ff858269f453bc6e7fad0fdcaea9afb72cba6c2ddf47c4a11753a69d0a8d9755b6dd600d78460dad5a8dcc73598e8b2383d3551cb767bcbeb9a7acca4a48fc584089dd1924590a5627245026d340fe1302f4f0cd2568a572aaeacb0d67c052d82fef5b5b80aba0a794a00fa16d533176333001156f2e5fc634f6996625e93dad3bb53e935319f2489a967bbf3a5bdcc60ead374cb8fb9e8f2db0770e94a0f5e2c63b6ad215fddf08e3ce7b4116aa8008910923b3b3591d71940b2afdf9819e7d34c81590717c7a19b4aa690aaa77fee039ff70c20eac1cd107d01f0e81c66464bf46b2d8ad625536eb09ffc494c3cb8fb16ce8bd36b4372b9484184415ff8b01eddc3e8989bd61c3d3505fe1d95d38ca43e314ec801db0ae4195f74b5dbfddeeccd5ec376e7204943ca16d221c8e6d1d208ba0c07907e4e7677222d3ecdcd19e903cbfaae6dd50ea6950ad78d8f0fcbb4d1b0a22e21244af7129eb5043e6a35cef24a8e95796e40936b1dac685877c274c52b8d02af96958a760020d483ff1fa9947b83aeeb36c57582dc6fdd2add3ae3fa54e063db240dea28895b253aaa16e155812c23758cfa1f59ba3d31a31209470af3839bdd1b509cc3be282cd81729a4ddb47c2693f70fc296cf5cecba67fb8c55b8fd04a426d6e35ca0e98c7976d381a4aba143a1107056fc33e89149d7a26868f119e366b8cbfe026e08cc799bd1cd932a947939fb7cc062292e6932ee0cb0b08f55b8a237f40afb50d9688831899f319b4444e274e945b2b3b1b31c3e7bfc0a6fd12ec18a584cc5d37b220b8e9ecbded498ad91eae4c196160087d4ea016e9c51db67518cb922426e4ca7e6974742e65d624994959c0ea3c9be2533aa6eac6ddd4fc6756dec2ce25a7ad00983cb9ee7371a30ea0ebed4a9ec38c37f6b3b56e5c81c97b2006400a74be351261e8960b068d555eba958bae1d5f5d7ece8b02298b0a8a4ee6647ec41a65e91ebf80289e98eec7ee0717e4874d13798db413e04288891ccd72b1f456c2a363b605234406b33c44d40a96d793e8f393d430389c15eaa64b9278ba5cf2b590782629dc36afb9b37723d7594fde6ab6d7704828fb746edd85e7c65ccacf6acd97acbb8f57911134f3548ab4714f35a58accb4bbebadaad23b57fa6020fff26e7b3913513946350b77149612a723a239530ed78c7f750f4aaa1d6a1096e7cf8ec5c5f682450be51e68a2c9b94f1c3ef493fe8cee934bda0fe88ec3cfdb181b8f25d7bbcc8de5f8249fecb040294b195cf96b2144ff0c7ce291016f21c6c044bb8c66cef8ea21b290ea8b7bd6605814e9", .None}, + {.Sqr, "-611975da87adb6282d1e7ee542a8d565e2c01bd4a0afc322dde9c62c0ce1d07ae6535c051cab3a9e37b2f2ac6eddbc419fb0b534822e1649c2c9915deafd59969a582efdb6d75b0de94545960b8268559e3538f31f9bb8406bcb063892a6651c5cd02a55902493029b0494f92e359cc8e531256c3d98f38b901166eb66a99ee54374771a863e69272dfc500c131c2c740d8851bc50616ae368a698147d6bc2d7f00de5d1457e9c2f089dfa782fa8d0fd727df51aa7385501cf6f59f0c4e25073d6705121458ff18c51a5b438fffe53755278c0bca5b388b70cfc0151bce32a438f00a7604e591dd3f5e4b061836fe2d8cf88efc9f766410682fb9ec66144a227ed366ddb0cb36a182aebcf9a30aa8c1e92a5820327c8385a6c16ab924cdd3d12272833efabb742fac64b834047984bf892eddff7acd97c3537bd197ba9c5fdc0d2a4d0b1b9b02a2764a89632099f8985059f261956ff0edfad284d2c88b45fb7e355bbe6119e9e2a588d9f471c2c618b1b883c684e272198ee48a0b6b12cb89c36b5652ac7a63055be0588f9a0d14909432c0e9a36dd5d2666e0a3915566e74f2155e5fa632ed1ef7ef85225f065a0539951b18593db71e12d56b5ca5dc3ccca0c275ade3a5d5a09111880e033124a40575e3d839d7e355562af9022e05ff5089812047e95c9210231ce583831e52ec65677071828b708188a49a1277c7dacc9", "8838d7ecee54c4314d035f5f63f729f57169b7789bf4def093a6c5cd54709d2e278a107cb694ddcb8206adb163d3d17cb9e34210adaf53572c75d186b03dd629bb0eb8c22834f785c789d4cad2066b14e444c2ea9ccea6ec1bd93ceb1a98bc062afd1e7012e2b172b354a95b50abd0a4fa9e94daf035dc0b908d83d0ee615219fdba8c0fd6dcafa385b408f8e43da208c7c27db34f80383c43c8ee27267f5b07976d05aa0bdeddb209f3697997052cb908e441b8a3f64fc92ada0c792f161b456b854d0dce87a9076c9b5a149ded0d70c17776d6a613d98579324139e51d49b83ada8da44613838cde71b85ee20ebd752eea5f24767c9b906874a413838a672632c7b0464be7ac3933007a806c8c0c8fb66ba9e3c4a15cd53fda147b98dc4b20584a06b7f9fa7dcd9c3278ce1738edbee212fff51c7e0895c2f9f4ee6129f2be005c9516e2e78b33a2600d0cab5d47fb368ca5ce406426880b84a24a1d472f14df3a5bd5ab974717faa61a3cf15de47a552b0f0b0dec98dc03ee78e61bca2ec09a957bce5cfc5b437238d8b7f79681552a7de92357f691648a457ec508660f59ba06d1ca22106957a04590102e99d4f669122d90c5642e4fbb3eab4caf51a6051558fc85f131ddd8a26131069dbfa2d1e93216319acba1f506a6d06615ae10d81118b800b7e01d9236b15c45c98d9616ac0344da3666008473cc3253e57d3a29", "24d44dd7d5c19e882a4d8dc750b8ef978a69f953b5086dfd1a388a05b9286109490c66166e45e0952948ed1d498213494b4d051e3a2813072f0193da990297c6d1e3a526fb9e9e7a9ad44f0ea26abfb846401ffad4848abccf90fd4f3e9d3e98f19dc0d6c4e1d6890ea7d633e14f6955e8c768e54d10ab08c13e928a371cf4583603993fdebbf00b8baff6003c17743f2d9aa68179f5b916afe2684ed225d7a68f3a5b7eeea001369b0c2ec7603e9ce9036132eb9d9763e68a36d47bee975e613bfb1300a796ebea7dfcc4ac65a7f888a6f447c165f91f6c9de588ef46676d42f271aabca3127583ab390982bdea7d12f82951ea52a767569e2f637ceeb80060bbc28f238a5051288772f14a4bab7cbfff1757ea30a1eef5ac445ae03cb46c8c9478728a567cd023bb7312adab2740c98a739eb97cabbca93ff24ada73fcdb14e8682ee7108b76e7605506d7e074b4901247a551e9d6a976adc41d694366ea98cc1b9ce4cfce0595be401e7925124b5b70f16610236b156ff159840b5d6645424d2361f29ba8a9d64034c86893a2b485bb47d5af77dd85da51c3bbf8df17c6d09872efa27266544c9b4d34ecd92d373e74e4bf6eae016688a2ba4a4d6bf60f20034fdbc3ba8617dd310195bc871f4920652ef7392ceb65f6edb356a45b50aed07b3ffba0fafebe0e9ada99ed1e357ac5a4a39ba410b16af09fbaba0fa3ebd26f9e784e321dc28f1d123e3bd6dd7897ac53222665e6b17ea231641bb987ae48fd1707fdb5a0fbc9a069a57ee4abc80e1cc0fd22af9db5db850144c824f87aa73d67c41982b286b6851b91ee12b697f08af5760362a7631834870aa0ae2a67b3eae031fb22a7dfd001e4a70c07811055ac506a3077d88604cee0d7705c6adde0582b2fff3b0664dd67d4f95e782e891e9f2f182bfdb537b023f85da55afc0aebcb26b800502853b7c6a554e47fc8d0a35f5b343902be846e9db56f9088406cacd09725aabe6c6a86a501923198d1ddb0c1dbb3607e03af9466b6b507e8aafb902036d36174883a90e1b2c48d529af1f0770c7e0ebe3205f26c50918d5e62adeb4a291fe10bc91788d22474670860639c6ce06e33d217c843bf1f5ff6b6014db0bc58e4ae92b03040b61fc86748473299d608109c1aa1315f00940329f0b8e894a17a6f211e1994e55af3d57bb8a6ec931ee914abc508dd72d5db3ed88c939827b1ffc1fa5c328d4a0b5c2a666f3e987acd0d6cd989b6beea6d1e42727a42b15477c3a7b61c785728f7b625c055172753f2bac026d15d9079f30295acd3d19d1d6375cba94b942e951392ab89edab87b704aa5b90f8c6a61d2c2df0521bb0807813c40f5f72bde62e67aa2fa6a2aa50cb35e4ba79fd9cfc4f5ede5c07485f04e60e47c0c1b7b53eb9976054b1065ba052af75d0cb76e9ea24527ccb7452e8e8b5d1", .None}, + {.Sqr, "-67b4228a5cab5a44c37139af8039b21a704c5001044e5c5b479783c03e42c1310e8f1ced943085ffa6186127fe0e35013f8a72502e872d0832fb563bb7c0ce55cd7781f0a4ec3cc75cbcce4da35b0df4666f29e3b45337c379890fe49bbb70f5c604103cb2f210674971c42aa2041dc77f6178f2ebf23da2e73552f2938ba15fec8c0ac70e67c522858bd9a722627bf00327cde601c36a322bc0a6e168a5824479edac356c1a901a3cd842ffa822e7aaffb068b2a180a05d6b69385b4006019214e6e7df6cb2a09cfb3620ccdc95459ff470d2de745ad51060cac8a476d416af6e3661bcc5525cdf7b3af83abcca2c78743131693680db755cfc1e0693291223009c1ad153760a3c9300c40e0df2ba18896427d7b9998a10ffd5e40e508d99627ce1e6ed04cc93aae89fa813342391cb31907d1a5118421f375d89231a345377a22fc827905db34c58b156eab3ea268ecdfada72a3bc772b24b2a2aa2e937bd0c8a8215ddd79a4225ac4648517b6f56884d204341761af84409d25e2701edc03f31c5651756b47ea23d15a20fc7c7fdb210ec6ff8a61e7f82d3176f52b6cbfe6a3d473a7c12f9b0e210dee1c82a04293922c4d4e01d106cd2687ca331ad367939b5327cb72b93e9de8394fd6b6bfc5b427850e04718268815a1238fb903b4e055b6c09395b5be1e652fd6cdfb5a15c923a762abec134499f54b9e57b5c44b0d3", "dbcc6ac5b9771dc9eee7b1d47eb2fdbf16137beecae6ef5ffd715627105a3562b9caae0216e726d9729b4142d3dfca5c17bc8b44e7d3fc9648ea98f7482b15ae531fbf17e8121ee76e99236246da82353ab9c7e587f0eda3af504a04c2eeb4828512e83d1acb92ad2c12c81775ada251a752c644a156da48f112c56a8b0a2b8e3419501eb8265bb61f8294dd5d01afd1c331271167ccf640e75453ba13acdf0ef321bf9f2842259282a0321c617d09a473b54eac2db3ec037cc015d9c6a8cd30c8c7132958d1204fea19d659854a79296e5b0116135fe27d09e16ca96cc70c3b901e4042cb9861dabf525931929901270278f9dd68daf9f9e28f6f62ea6ae1b04a3f421822e33b5fc83473599da600dcac705ac609a9f5913a34dbdab748da9fc715749832a45d62dd1c7afb3233ca5733f3fa3b834e8a2a2b2a3ce5479105d374c2c8f3b324d83421c0bae164ddeddf3e5c7c233b8a1f65ad1033777cc65c4d71d74c5bbe0bd9af7f92ddcac23f1fd056cbbf7111f2609c826265813179de4e06725e9dcc0860a3951444eaf9a047b34434d94e57ae8a504d49b25ce77ee213f0d3424efad01cfec736d49aacc8d1515bd10f1b20fbc6ac5bfb1d4f89e1e6ff5970d45fad50170a10adaaeedd0f97e9e3aa6fad64e1c3b9c1e2ccb3a951919a316108467dbbff959698762a9bc826e4b214928748313cb308bce304c63b224b", "2a02728bedcd3effd43b2544458a74568798de77a19c6ee379121fa8b4284723e761049434f86b01953ba7d697aa3a6c8e42797a32c5b79897bab169eaf732deb3fa5ec9cd5e17f0645595d33ad8ca99312e0ee6ccd4c26280ea99c66c8c55a3b7116d2fb9f7950b68aa7413ff2e2fb6dc0bcba0d17b68569099c1f499a015ce4d8e8945d2aaeb2e59ecdb6a63562e5d5b7b4d8ea9e59837d02871c9e48f9a160bef9549e9cdf61d489acaa5dd14b7f532dae4b7ee976134c79de6ef2bfda4de402daece9389e38a36450dd612179c352d78b6dbb87b7a9e85d0eb427a8b197a98a944172a9337ef38c9ae05094e6bd2fb0930f79e3cd33a81207b62a59ddd90ce9ea722a14070192a9b0c62b666bdbe6c96e3e266997847d0ec05cf55c0517e5c3c8dc7c407d65cce42788c9c2ba5d3f71adcc60e155192d974d5c139a79087e4abd729845855ab08344ac2f0b970d0bbd083d0d087568ae072916196fbb89cc7ad17f466ec5d50337a95dd710c8a8ff59b688fa601021c348fb1ba2b295b132e07cbdc79d19b8eee6bb1bb444facf4a0d0091d2533a24ec34b00b3a7f74318e03c19616a76e01508f68e188888802341d78db8c04e1b951c96b0ff7d54d66acf72c5a6ef2fb6786d57ddd81b67954a7298c7ca35bb3bbc943ce23535c4594303dce46d405fbea236da4583fbc335a6416d807fc15982902613026106577848d77d225aa8f74f2adbe0a02e009c895013e1bdd842703e525140fe7ad3176a9b3414cc85450f09effba6980ca6f5c79d1081059b82123782ce776ca2bbb807728bcfdbbfe208fa62caff6dcae4c53f6eb173b20af2874cfa8026e5c5e3a11602e7f7465450df49f6904626c3308bdf4841a828849135e4a5687b610706e41f2f8f47ec6bf9a450b34754276bad230aa534593c9a5db48e5694609a9a0f9ab45f35e880d62af15cf7765e0722e503f5e71221d5a86ac1ed184a49896920f33b49d729347cbd5ccb3ef34fdf5e045cb4bf3da8bb1b582d71ff973a10b83ec3d52874bb6c60645d4b72815c822acc82e36da975a7f902ab86ba0f92769ca9a50c406d77bcdd9bad46c55db6b691411f4752d584dbe0382028b116a3b3ccd61c750c145dcd631fc5cf3a246af2fa6f8720299fd9be2d4cc8928ee978652a399d45af811aa3feb6076fcc3b0b327a7f83ff69c06e0e651bf53ddb775d0335d332518d8af9cba2ebd51f533202e4d809a2c335b7cf3b337b3817079d545d90f016ce467483f0c03cac7262674f8b457f7d139cd2c4c100e9a28d17f98da34e5ef6efb18776b557223038ab3d8a3462bc395b88706b73b2fed5304d8815d134ff038bd8efc15534ce210de33602b2f5dd608758f913d6973af88681f7a4c3d5bffca65a762f081d0fffc7034d657c6bd7439e87b992b32c347259f0b892da48123acde9", .None}, + {.Sqr, "-ecef211cc6d4098c7b41924f3a0cd575d6938813fb024fa492933fbef812400ea065d9bdba5d38ff8cfe68fc5ff2745bbacfee22c60ebbffb8b706cbf42fc31f8e282f24968b3c5a6e784edc087c1f94d23e1247286e87c620bfc2bf2560edd9248d7c39b28931575ce4609421c5a0b9240f80355630221428ae1f918d0ae74d9747c3262e0a17c10bbb9c830b6f9b5870201c2b76c2e6103963030476b9118caf22664856b4f1b809f9da64011b0c96c97b28c399fd30697c3edf3bf42b3837212df539ad260186cbea2035514eed17ce815c4b543e5487c169dbaaeacd34bd996d95dac8473677bc5a66144757b8ca598628a9f3813d76ac0fd4aef744980eee910e924c1affa577907ac6032a91be6f517d381743f0b572ca3cb5df904db860f58755678b4e8a010061e5bb6a916356d724e59363439ea1dfab5ac7b4e12da0a25b028efda850d91a15266c35949526d2ee2d9dbb1c79caab85ba6231dbd2c8bb9c90cad07631f58b7c2787f213274dea9faa8cf3fba8b424936b9cd9fb43b699e01abf7f283751bf02b654fd39c7f04cac23e904201d6618d9118846d6c91829e1ee0788c913256fe616484204a50b651300f82d098284e8ee14ac9c63cea8dc073188771c24884f9595a28b9b356d780c9555547b5fa6f51bd931124d5fd1e560bbd4befbf238b5c6a325501426d76939dcef511484ea14810c0e45ce74", "f1dd339e958ac1f47fc449ba3ce7ac93be4acf009d750c8dad276c675d4cf6e63a794b366361dce3dd3d8753b2513db354bcb0fdff32565e3e1f41affafc032cc54b91abbb15f13f72555cd0feb419ae8263b6b879ec44e27ebd422cd2f7dcc2faf6362597afcdccc93024212b4d2649cf681b66cced1705d631f5effa40214b17775eb32540a348dfaf8c5f60afdb94af79bfde30a693e64bbc9fdbf7993b7d695b43eca297aa3618d2843ffbf097bb5ea3a1fac573d6522529f07a0774f8be57c94ad934e1eaf1aabd5d2eefffe7388907dce89e0dde86672717d343ccffb08d5ef95b6d3a22a714941e1cf739b888f95952d72fbb8c74495cdb30d6a905fa36b868622d0dbe9bd8e884c3df862178950e45ac3bcc536d19bfbee43cb221f6032dcc2a8bf9799b54741dbe2c2c385f9f3a12cc22927c4068332f34863293e50f375c55d2029f52a4d82b80942386a51566ad9c058f0f0f05f1424012c4f751ff177bfa906c3d4de58de9766ade48d7a1ea8dfeba9ba4a7fff81751500d52701ea4ec656cd5d3ba290b3831aab5961945b5fb6069c50a6a91e9340c8efefb9f0b321e2264dbe7ab5789d2b4974867daac1214112b2f6c0bf67d155b832711ed7d665d5b09e8519a1e6e449ba66a8f463b3934311a1dd97f8f698f2204610de6e0d92fe9ff83de80751d0809035143470c6bbef847943c867eca5fcd4c15a218", "db49c46be69aa0039ad4071840b73c825fdb6909df3b7f6e2579475173ebf9da7e914f65a375de396d70e51e7094783153600b4ba8096633dc601d1b8c301bcc91563300f14a3975ee35e2127b0f3d2bd9c77a53fe2bc12e6808cc86a33d2dcf0d4b51d0709cb12d1987983d3d71492463c7b9cdd74b0b049da783506f7a5464d354070501a00c718b3982bdaf6370b8a6d2f4590b8196120e76214babc7a883c38d7eb956df967cd592e50ede51d9960d77476473c5f0ca52aaae5a1db0a801a1e80adb919df4cfc6d5a74a97f3a0cf9fc44f5b0f3bc8dbcdc7190bb8912595e6df8af31e4f8e48acbab72c22b7a0ea46fb769030bac2aeed585c4acd2844cdfeea771f1da38cd393bb5b48131e68487df515f2a2b2477bc7b601519a0574c6689fe8778e7a1b218e6d054e8ceba0c4242804c0cb226afd4ad831e0678b2f21af0e7083570c2ce8c2cc81261b4fb283ea7f5fd17d5ba3d265443429e0a16a6bbb5a0bfddbfd77b140ecd49cf06842bb9a9833f5c9accb5fdc849ecce7d60a364fde624966b98fb0fd2347fcfd6459178c0030bac7f32d01629eb48706596ee24fc3e2862a2aae3a2898e7fcf69425dc949a94a004887ef4f5d10eca917eb17a9a0afc1b82077b7cc2147e797fa902a6c05bdd8123e2bb0022e68750437c29c16680f968184aa55817e6ef0646372e5c344f80f9878aa51abfea97bfa6ee768778765231a4990cd7e4bbe55360658d20a145685a1a5260989e0235e3f23bba850b2a8971c560405acffc8326c11c79551c9ef37ccbf5ab925db49e35af9eab517603de45e21fef2ff67dc802595f26939e07119c5a7f7b3f657bbdde8c7b88108b8f3135954d6b412390a5487a8f2090f8774a34810bd0d84fd5c2f1918f9d0af2d43bb63ad9d47844cc914c56f0ec292f743cf79b635a9ca768ec1d87e9987ee587b76dfd4cd61d6236ba9919db93ad28647f816a624ad2723b1fedfe49060b5b6509318c4222184c7b236121274b1196c47719cfb383e1bce7b114340639e4b638eeded3216675620bd14e496ec912a6518b03b367a6fd9e958c4edbf3a80e2d1d55f9a0773dab237da8243c7c5d21f19ab319cf14b1dd6b957ec99db6a884cb95207d1ad92a04e7087b816764ba847f78bfaa3b247ab9269eb97e3904c4f7020970fed328ad7afbeba8ad9bd23ceefc587d8e260e09f1dbeaa9e4f7b6ec49ae1301b1f2f8c1bd254878843d3089578e4e39ca1e0bb1908866e4b3cd94665e627eedcd6bba4481056ff7fba84786daab8655ee9af3664a611c0ac4e1b4b10d72a059ccac111e40f327e7e455d21445a3ae9a82d812bc06d89c2817bf7f4bf80a47c7f3d449d3fee1041eebaaf54f4acc5d91fbb85b7514d640f32961336a16b9db5ea496553826129f0b1770e0ff116cb2534152ae06e80387f87da106e490", .None}, + {.Sqr, "-71c8e43d7512f03032f3fe567b54eec8bba07a362d00b75acb3187b0c128b3cacc1ef96a49d0e840a9170c39e19fc9b3cdb07f0a3f4552bfc8b92658a69955e3981e1184c2ddad4390e27ff0eadd52f69d28245e3763ac86cc78c6927a3ca1727b9412091e3d97f7f99f127177cb5db936f135673eac06c6d6b32c2ecc4ee0037c9bec4272067d5f2313f1b2263346664874adeb7ceba78ffba2beb5e767b6c0fae997e39bf08aa8ea907fe6d843d564a549c428322becfefb2cdba4602c973d5a98d95ca08dee3213f3247e6192120a7cf665fa94db385a7b85095bb3ef937c3eb3d61cfbdee5db080730353d2fdceebd6c12dbb09ccdbfacc595c86fcc2295374596dac6154b45c31d7f510f2108f6bf1b6d3ddd5920af2c16cc5b2998342116ac71ded7d9b249880f334d3033a18bad42af7620e22f449992c92cfce7c48c3a91de1626266c880ac9c75d8bd3e933fd0dfde6cb1fd9c85ed1957c79ae111d49c29e33181583a66f9212cfa72e22778ea4ae110c2e008a0e4ef1643e6dd2729b5b18d0b5daa82291c6cd026cd8f2e564e06338bd4a254b7d6b1ee86755720ad67526b94be5182eb5d88af8c9e98e7b88bbb6137fa54326bf68296d4afb8a39c1cd33365be73620077ba7d2f4c85f871ccd8f935a19adfbb31785ac44d4f49acf68939bf84b9363eb51fc557e93ac74263e07c070a43d29d145119fb3ecd3dc", "f0c7c37b2279a7edab2e986e9df4ee48d8e06228b7e60655c951accec3919003b0e808ab94843a1326e84315f1d7abd2a818f7391f0048c5159114761ac2999c6ecc7af3ef31e9b50d6c868a31f7b072acdf11a205c1ee593de32baf0bbe9ac6a15215aba6bc0d5336bd97b0bed13690acb373d44820242849f856af5aba88c9cbe0d466563ebe24c8ef04ee7cbd972922af7c8da2c9701e40a9907877271435e838d7f68bb944cd3fe61250bebc2f7ca17e48c60d7deec4b777a651db9ac2a4879cb546b842023c49d0268b9f9950a7f18627913d3270f365ef50616517b80ee1bdde57e38229ab7d90b5d6267d0e322be1348e83771966c72ff520d3ecd8998e4726caa53e04ee0085510a5f8971f7000f689988e9046a59532b375617346bd692677db5c819d032f759ed17610ff97c42756b0ec3d4b36660d5e65b3939b1f93a2edf45eef9a79d287adcb28ff4f8036257c809c2d89fe6aaec23ab861a5473888c844018254d3bcbfcaf023a9dcd02f34f0b426af202279b8f74d84be164cdf4f6b9cb00b071ec929b41d14bbf7d852bb589ccd565665ad1744ca10390286b6be94267d0c45e5cc44b6a75a9e5f9544dd14f6fa64d37f0ffc024d25c1789d79e460891e7646ccb56e6ddff5e583bab783cb3ac77f67c4b1077002bcd8f445b7995a814e27a1d0d7724803794315cc2e7220b3039c03fa674b8ad80785aa9", "3292f723acdf2cec94b1a6735c0789cfd282ea4b38e3b8c8b0f5160042149e59c97e12b835fc61f53ab96fae2b76a129b506f255e7779245d0298464f97ce2fd6ad37550a2f73f79178220dba1b50bc68107034f358c1ed156d5ee70ec99fb1cab046e6e43258233b8937aa23193518202447a7b654218be748dbe90a6b3d55ea744bb5abeb0d57ceb5155003822374b6f2e8b06d3eed5392a7ac5c962a1f48904bb6cfe55ba0838f691d8bfbccce6965dab46a27e59cb027a8da169f6912845f339ce4f693a1cce7d0d315066d44a4ad917a2fc1a00a8746e0a1c426ba962295e0c0cdcd0f5275e9b19a547142011551c83b59946384f07bc0a25d168fa09a61f0de797b1b4182b56802357de4f347230fc0d0e6e408812649d8eb757767e9d1292a3637fd77aa21e074feacb58a77a9f7c7f01fa2629da4117fda61399dbc3bedc4403933e5c0f61afa25ae279bd2cccc8606d491030472597b4409ad76d181fc55252a3a9c88042885f50bfdcc5dfff4ed3c03f461eb578ce7200f6d68ad3bba42050d37ba8b4428f6992d85bf4d361085d922185ce108e673f7f1a84335389fde183c214d146a1f9011fd4f2e8cc0b0599a670562aed43636e40e83faabf06233166cf7ab3b14af4e388a5f445c747ebba0d561e8e378f3057ddefb8dd30a63dda513081d57248ee2c1a499d3da94eed60f9816876e5ff6a8b159334acb24cf7b44ffd0da755aced7d0b27105205ee39ad9649be7eb0a14ef4c34f50f6c00d20e9e5e75423984ea2d0e6b692a70519945d35a1ab6711f5b4e842dce0f3a1bad840c561af828ba5fd4ade3aa4e0dd0bb7f4e97a6de48890ecdc04b514e491529c441aac342c1434286123e65c15e6ff424d9b630070079f6de485a5e6471247acb342224bda9bdb233b7e58c30b859930f0325f1e3832c9b2bf871571aa1c8959d97646d2eb42b4aa885b2ee520b36ba71e795a6e1edc1868954d31cc6032abc8f67477319d3535fb987ecb68002c769a434466481aad3ce8a22493dce61c7e2ceb00222c7935f1081f52fc1c9742400f72610589775536321dfd35a6b423a1a3b8a4b088505591b6853b0195d082b2920937c0bf3149844326dcddbdba4265bdf6ef3faecd6cb4b5fb6c64e64025dee7979e8d9895a362494ed99877fc028eeee98448eefc7bee439981fcf8f125b65104526644ce977eba3eca7bfd742cd113b99e4d7c1b21edee1fa18f67763771e7ac5a78a02e5453db7f0609578eb342cbde639e56e926bb511362fb94974ae40282e2229d0d0743653450fb23d17fc1b1ef0f05bafbb38b568c7321bee8d1f54eecaa5455f6e58e6b8af52137ed426e54b3a6679646d1c93a8bbff620c2f13c4dd4dbd1f10e7601fabced2f400fc6b30fd38de748a591cc082adfce9bc4dab5092d1fb5c8fd95df5f6ea4f4f46510", .None}, + {.Sqr, "-96e45b9cd71b79b7f63236e892bc5c6783487ae047d3ac37c7846655fc7410b13b2d4e8afc6d0bd8645188ff28b8054d6b74fdd15effa1881bbdfff833e78fec4733482c9ebd83edc7058265dd83fc2f41fbb7637e9c8b4ff6033f536aef04d6fd44f2c343e9150b6a42767c78ccd3fbc4719bcc7ac42f7d17ff9aef5095199132a230db569121afc76cbb417011d127d945c456cc8b8ca0ebb10928faf4519c8a14cb58cc65bf7c0994b75affb1c174937fcbc6c76f6f098ee495d26b2b41fceae121ad717c1caa9dea36e4073a95554ec0205ea0c7af5d976017aa706ab0f0f4a1e58a920f827bcce90abfae0afa1007306f8df0c0c016199cdec91dbef8561395164a20edda9262fc196931674159e965425dde2686c00e78c86edb2f332413a05e9af2249e745d5d43cc596e6456a9788f1d33327316b2bde2462395b00e2586b4dc6e56c1c12c23b7530b2eb60ca3ad160456f1f446ce970de0f4cf58ffade88a70cef136e27819635fc805431f4101ad4820f3aa19e22cdb3f78f6a895ac9df89ecb44c74c32bea9661c7163829b3258688d48928319590b41857e57205935b5c4a5f48b54adf52f8a1366de490dbaa6fca43a6140e1fd37058a26bbcaef062a10dab3ad442c9050deb676ce0fab4a6ed7e2b0f48354193ddf4d7b6efd5bae37a4eb5e84e8fcbf84824b8a6ba58f2f31cbf041c923c72b26f3d3f48c28", "ec65d47a42c60194378ecd3178346344eb46f0d0ffab35131888cd253095c992b52ad61973ebe810f6ae0216c76e43690de21869b0185b614100f9bff0d5ed3000cfea5218b9d3731db0617c3ade7e783ff16c629eaa67a5bf39c0aac83486784f45ce6276d223ee51d392cd77849e8ba98edc988415497be8f87e3dea6862dbfe432348f5307c6c9b17ba0c8aaf6f94503d16fb3b0d5a0268a72c6471e478f0edb5f8407142adc1a9f713bb005d2f9520de706d8525a401023181765df57959905e68a376ded1f3810ff3b5106b2a85558a22c4b52f8257e410a477af5c3ab4df7908b5b8488dfec91469df27b9f34e85f930a23936bf0cfbe610ed7a3194f06e453ad026a4e4e732738e43a6daf7ae94f3a94ab8d82efa6f27509e09182447484f10339c72f8948c553b8c50b3f3845b1f780bf8ce14a01234f18024f01eb12ced877bcd9f51569e6d3b2f633a4ea05f0c4fd356c769588a42cea03d6cba3f7deac94bc3960a43b228a0f2d1bbb477f099ef38a9b790a6977311262a3d1cdc7956a5e88826914b7b7a36bbfe45a10737001cce2152b2cbd36c58e84c10fe300a042cbe559813fc555352d0fc12efc2e938dbfb497ea8b2e75417bae0b33e5f8fcdab76ccbefc7e184180186bca9528758c06ed585ee3a99c543dbf139beccb5825b785a6a2ffe78f9b96a047028ff19e7aabd6bbb6f920e89fbf6c56896ec0", "58f0670f1c3c3c98caf5ac6c00ac1152417b3c20e8fedd67ca8d9984a16f3a0d4b6cfc4b131daf4c8fac8595d08fe7398c1096fb9644c9819cd8cd4131dba6ab9960dcfb624e6f98b157ad3202f202a89b17ab89e469fa9d89c814995a842f865029cee3a7af7c6060dc68f3c474c9209737217ed8bd126cae73fe14e3a554720a8a6bf837681b012d6a1725e3c94b74562c0ee7dcc540ce49ec9f0bb57a63208f56c64c01a9a61c612951e87f7c08c5e37a57eb9555f9881bcac1663bb30ef10ec8b1bc15d51c91cc16452122cbfa7eeff02dca0cb57b76cf0c7e8907ade88f8f703c6f8d14dc7e823485702ec6e7d4480fb72adef67c77b692f689da81422de68a450ee832f26e00f69af311bdd7680208d3bab053454dcfcdb820f7a62ae6a21a09de2cdddd83a1642854abbbc6bef4f182503fff9367cda7a2ce3570fbad1a3e9967bceb60495aae5786ce3740deb4bece130fb2ed1ac03e97f636f665d3287bfef5b808aa93308e85afd1440690288d57995982e7db263b68110276714552c3d29350e660af0ff66156b4320a5ecb3c76967a77fadb66d9dd9fd1de649b4bc97d287cdf5b55a6689490f501e256a2ace36dcf3f65dfab35c350f52208c2f766d5418f190485600c0c845e2b189c82343278871999e4c8b57e67b0fbf5d3126eaf2d62790694cfb01e908923c169c7550d59bdb9a5ddc84f0766bf92160a2d98b243740c5f551e83ae122b9292a3ad7a98db86860f599c5c9dfaed0edf6f7d5462d569be0121be6d576cb91aa628fdda4b55e60564719f2c19bf78b9119e482520ff9223f5a85efb2c5e2ee9653ddb8b3b1aee60608ce92c804eca85e0b45cc305024ca552d052308fac921daf35ca9ada443f313e6ca4d9b8cdcaeb952ec7534fea43e92fe026a1f5c8b9f543a61b1d57724914036e4a7ba7296ee07e6a5b935976025bef34242429eb33af3f7abaa679b97387ee4a3236e9778142903bceb918b2b16882634436de3b9b2999e28ea4c6fec55371002b38acb6b1b62b9194cba485103ad923b0220d55b31a42c0fd956c090b091b20922dec5f215db1e10d12e6b245e3d57ac5534ccdf7874d59e706e753693a2626d7ac74dbf003841c7164cbcf185e7306179088c0da5d4beea5424384bff28998ff42fd0cdd3aaa1fb77a165fabec1fd9a737edde73150c8493713ea73089e3665bd40a8a8c104fccfbde206dcd98c82819ceb5d62dd82f44abd0f3cbaad3590e064efa3e5e4e3dfe008f5e3d7e9e8f43e7b3bad1d192f0c179267abd23b50f0099d1ea3b4a960adc6b2ea0eddcbdeef6f4c2b18ca03a230ede1f06759bd962c91e6c1c92b69b4b1ad361d9ebabe7bf44f36fb7b4b8d75c59012182366dfb98ba8ec1e209b745c3ee4f70c6535778a4d2f24ee24820d7827ab35567c154a1d425f0cafc9568fbc640", .None}, + {.Sqr, "bf3dca19842aaac2180948279bacf0729fa19936488d82bea7fc2780c3c371441f7d85f7e3365221da153443df9dbd75cda90aaacd6c1731b363efca711ed913e55bb1aa339aabb1d675afa0f8579c105051b72dd37386a7a71b7e18d0714d62234601250daea477d850ae8cfd4553f4543f369e3fcfea47729ec700c33cda587ee39ea28e86642837538920d76722b87a49d16a84559c17d60729c23e233d84a3ec0328f66c7f7ec98f04fe1cb65eb11783cce5bc4f1b552a69ba62de01ef90e1ffe0560144b40e3aca62edac39aeead7adccbc39800b82839887ea7662205ee4cf006adce83707ca36b6d7f800965852dc45c88381801a73ccefeff442674b81b0bb4d78214e4efe6b083b4ea6f32e260b6dad8ab01df71219686eb08fc0f1c1358baf46fc02ffea9fc3691bd880a44949f2bdc7d43ded33ef55dfb50a45a0be952ca3fe3b08855c17eb428a7bfd6ceda173cdea53d8d54f58f6c90a41c07289b67829a9af9efd7e23f3136ebd681e2b192012dfa2840e88a438a5b1f2c9ca997dd2bd7af7a439e24d88d871e07f6d9494030f4bc560adc91e333548336af7be591717cf9e38814844414913f6394beafba1ea2cecad5f9c10abc23e60c135d82b087875b9e17a180c1f545b063db09d78496a30710e77211403d1e01004e3309cd9eef339b1143d1ed4629086b8b66f2f7d491b56ccf5842048f08066a1c9", "cc42e40c99c52355c3d494eaaab7a25cd7c94fb64262d4cdfa825fd94936ba4e3a9d735350a518cf67b42d8572e2b4ed8441fe37f8cb1aa0830ceec7852b381dfcfd2230a8ac793029874897f45b67ef84ee4f5702ecd42d9c1b757049af034ac92acda8fd29735c0ba675654d65c147b6360f57b088f626f3979e9ac65a056695572bdc5dcb72cdeb1aa47a116b7d119a560e2aaf78c36c9c0eba8fa98fff97b642b44309a32594713ef3ef0760125ca76ba55a5dc6d364896db5d52406195bbfe7379cb187b4dec4ee368024da7f86ad16b8b36558737d7982faed91713fef2c6371047aa07d976b4dfb33398374e517a74ce84fac10051a6f58bedd2e95f595ae2def0c7c051ddb1f8ddd02b4c3fe8e12eaf39debdc22765a276b6788f0cd337ea9fe62cf38117788d1a095c139d775066d1ff3def61adb93f85e0f29d85a9386aec12cf56bb404fb070ebaa9e485d65c3c3a9a60447c3c3c47b2b63c5de159091c00d9335a31337406e62c11d4e238ee3a797d3ae3927e427b2376dc2c772f1114c3580bc84f759938ccada46c1ef2085f301098e2774d34b4163684046726c6da02e01cc3fc8851b094014e52cc4b2244c1a0b398cbd212b45cb0a3555862d85f7bc202efa7bd243eb72b447da576d34cb26574b00cae0d27b94cdc8ec89e0f14a64cab8b5857b5a3e6eeeb4dc196f94b26b2efea5e28425703143d189c", "8edd427c02ecee416a68fd23773aa9283dc0314c877ab1559722ea2666fe8ae95c3e01b9a0497840a34e4606a7d4227123bdd61d05c491f39a5f429d577eff1d0e2d3253f80bf3b0867ae081d4f1539c825fe8acbaf0051984d4963ec6cba6311e13642d2e373f61c7329b12ae3fc6034e532086983c66022ad1a5c6674ac1ad0ed2ede5f3bb00a414c0f988a21566b2b3aeb77ba25df184bd0b648027d6eee8ec66a9e22726b52ffac25e091c16253033f1589b3786c960999304acdd41a9a799cf0444fb9dd2ef02fce32d66f06344354257005c67b635b51ce09eb5111fdd0d534b00e5ccbc63d65d0bf0061fba81956a4b8f71821d53824479343bad078849f4c728026696d55025dd00fbd851bff3030a818d525b6fd742c9099d075f7907ff0175bca4da0f3ce766a0ec3611825cf4c7b7836c5c6590450164402a6c23be9a35d9f29ae718a4ed7c3d6ef98e7dc3931b2711234ed6997917794b6fd3466e9d7bde1d04ca1825163e475008ef5e489d9c60dc05ca804aa82de1eb65430f43fadecd40ef698aa7b99581a7b46aa0098fce74b0a8d93750cc4376781b60eb11e1008a9a260118e98ae1e9a94f0c6fc0c11eb44eaffe255291d6f8d6bae6c8e8bee4504e3f37a745d20ad5a2dc63b2ad71a9957890a811322cd0ad78acabd1a1cb9e8f2c86e71a293836206f8b452e2c65217e6063e3abfd18fcdc606121c112846633491e31e52c175eb58cffdaae9fd7a6a2d947168bbd9b83560703665159711a46dd2722abf194a9a505b0b32a699a2c4316aca814cf4da3050dc1e9b8e77e633ee6c400264151040f210d02e9e68d3597dac79fd52fe8b211dbcc2bec6dd8430374e27fd9c941381880f2c7cd86436c395af2b66e2406ae796738f9d22cb9256a6650527ecd6603b778e6afc5c7374a30964e57b9a9021e991fe490d1f34652be8f83748b791596834ae6e4413be5164ed58fbf91b62151c66bea634f2623cd747f1013a781a19c479571c7ebdd93efe9f00adb84aced6316b3dfc36c8f64dfd69473c6c98737e6d53a45dbe69084b14833ccc3918bfccee6a81e83603d19430213fae0b67e9d61ce2194fd368d2a915cb5448204c883383c7a73d6438347e22899e2c196aa677d9fc94a10fffb381aaea93ed5f8ad081db9243de2cc057d45272d2717d64eddc842c2c45589ddcbec0a85cd23d3155107a5bff14bac4d4ea275895e6c661d43dcdafc41f0363f1601ab5c433f0d2cc80407b8180dc8139543278c35ec7c5cf0a4ae53b50bb28f74afdbd30c637277b11d8eb299bdeb9aa7d839292d149575cec6b47876c58f9a2b5ae4c669676fa981c626cb69d208e079df6888fbc6613cea5db77c9ad562df4718a16ceedaa24a3f983929a888c3527930ff03ed2f6cbbeeacb3f5236172853cb1fac4a81d64761733ce526a6fd1", .None}, + {.Sqr, "abf6a69983f69f077836790fdcbe7265ee9e0f736d63b191637516bc67c2a74b2afbf6bd572d282ee933a7a68a7e19c2e0b1f510005667f055264b856fcc5156972f53c7475d8962b974431c97fe29d93ec2c880ac614c9663da589d7b753681ab8305d2f3deeeb767ca534cd70f4145972a51711ab9bb4d5daaa4ff7e7ac4f41329644478445bc7f9515a45dfa8925287b095f93bb8583dcf93b7d0fd3ab19896371c7c062ec5a163fe0d76fe0c05593a3c213b0d6b2c61c2a0854c168f0e227e0df19d0d16fea123e08789a08cd99567ef3c374b4de567bfa56f8c6ad186d2ee1d88ebd98db21ff0d0a09f0a7ebe44555171b1630722b837c2782949cff181a3a1d359c4e6e64beb09c64bef274d9c7b5812189caf87e6a045ecf8a69ddf9bae96daffe1acb9701ad19c5bff441c69f723eb5b2b38276a1f602a270686349a5a70d88e445783cb61f13bb3c71d9b85c814b1e975f23555b0931247ca22f13755aa708c81cfb0108dd0176f76a93fc6428a9d3846ee8d77cde634b6f54fb93ed8f8bd5b740824f809d6fdd8befee4c42687176bed3d0d4319832f4c5f249ce49a27c9c871e4960b9ab542510087b11f7d1fc2e544fb0675aff61906a613892627ad4ea6de99c40eba1244c1f3c3c06709094ce0dc0060e669c2a8ef507e37567c659b81a5817791a813ee77e78e74c6f2799c7b623209cbe4d294f41a8a90df", "f0f1413a1e16670e9e73f0ec08eee4374c61eb8db677663d57c2ed29913a4966fa3828402f93c6009de342c5d814e37cfa76323fef42251f95c31da662452b549cd5a0f00ab6d7c03ee7917033daba3a7ba7d05d6871fb52bbad8514f8eaf06cb66e206c6ee153344c459685d0f744ba510f61da1d31e306feeb7c52dc434f5e4b52a7c042e5d33d2b7107fbc6b42b0637e828802fc7c9e191674b8767efdf150e4653351016a331b4bfbe5819f65e57767e1f3022aa67c5d0f8c6da7dd1e2adcaa36c6a46939e1c19dc4fd89a2c328e538e539a4b0ac8ba1c40757ab4c2d24cb5aa06fc448a717a0ef307da06dbe01e9442046a776aff619d1278df7b9fd857b44266abeaca774813482c2a4d1bb616be41842d486be64bfed070c18daac6d202072a444ae097d2d5c63b7dfbbcfc3a35c8a715f2303766dd1d17cb222533aaf9293f6349696797eee7965ff5e763b9065c78b90d2bd75a3333eeeb38d00573863b2f8b1df0545d248a6b0df9ccf09d482342833be40ef02cc3c717fd2355697c07972297f1c372c25e51f6f1159c9632fa28d1954bde62da5dc6dd72be79280998d704b5f2770e53ae7a09ed8cb3af2204b12dd98062bf91c51fea229e587cde3dded7277bb227e7b8b1b1c0f560e667b2772288e5e91e870eb06d75fd175587e53ccffa9c7f8acb4537fa9c48d1277bd329bbe09f2f99e886b7954cfae499", "73837035b1c089a07401e997dbad02373ce546f718767b7838df5aad524f9ae654cf8bbe0ac5fb82304af008318ce05664e14d1395ca6290cd089ae8ed6d64b90397d4a4009fbd2abb643ac8f8c6caca343c994e3491f8ec9eb4fecfdc2a88a8a4e9fe665e945417c84f8544d6acf0aae11a6e94f399f7cd36dc0691e8123abeb2310118ae2d00cc5c06af6615e4e2bbe8afa98f3f7e019d0854c025679efecbdf84332caef4bae920e4d17c038a4c04086296512b1d5d19c157aff1d333ceb843b9f44281afd1bdec0fd3fbf880d20d5381377a0bcbe59543ba124fbb7d4a96f7403295ae38e78897f4782910b2b6410f35fe77f0474a383fb97e5e8f5246b02e0720f7d8422241ffa3a615a57a4ade72ddfa2bcda9bbafad0d9d17c81ba778da61dfc15234497ee517da0b32fa19f40d6b8ca591ccc3ee12d133f93e34eec1e9b9cc4b3caf00f28c71e9b32224e5382d72da9aa9fc990305a5a345d0689b13d7094604dac86a92ccce01f21f633bc2eb62c274049f75f61626bdaf358624a18b0df2268527bc497cfc1d07a6d3606af08eef1a7d1c5dec066d88bc4feb76ef810a21a353b92c33bc99c93e9c2d1938f738a50e00d1521e479a76ce949b99671bb02bced2d2d8e2678455bd60a0039ae8710834a54b271575ff3889ccae17147df2e42a1bb07bf2d1a2c2fd1573c42885568b975365d76ee35f760a0cd44d7005a7b303c56bf543b72589deb8a139850472643d982e952d5aafad4d86dfe16484c50f7a83e065521b585cdd6c2312edcd75d1daabec325b1ae8b2aaaa8a815ec0518f35b3820ec394b29c6c5809e24476a9ae22bcade6d01edcfb84262f060d5110c21d4591a0bb577c70686d55042c4ca4568ea6ead17862fabc49d468ab14ae030ef94459b590c7c7f332746d38c7a104730b8006f543ba023501db32ec38f6f3b7627d2ed1c6bce56f32961f5a9abac64d9c070db29532d5a38990973a57cec005981d537fde0cbf0c2f2cfeffe5fc27dea648b2c6104d321b2d6102ea26f0f4e88f9745dde28fd02409c5617b7691ee97d0cbca1836a68677b043b7fc5efb106072e26b7c2d25979f425bd183b327241c1566e0db0685b0364bf9b3ddc5f92cccc84da8be3493be99034fc9c7d0caaca19becbde913345e0ffb3121501d1de0a86be589dbc50f1fa2db449d05b3cd0ae01b5819b907d236d5ed7e4d1f0dd4ae0a0c487fc2550c879f1c7437930c22030814eba5e0c1448f60be83e6ba832cd91ceadbbe13cd3048142c52c17506b5760ff7f5a2e48d63e77a01f47a32c4fa74e3c0f603fabc2b9f826758b2c8ad9e24773c29cd2b9e980396b5bd475d6a43583f2dbc77e87d1533571af1737438b186e20f4306fc4f110a2528f2d146d8814eecc7c79173c853c72ae893107989852a9ee0af7af47fb8427185ce67a241", .None}, + {.Sqr, "-2a60e8338c8e2d83aefea9a32546ec1c68c0887e8efb8bd7c4ce9544a7fb17667cbbd40e106b7c80a7c5aae8c54f92939da937b67ad7b20cfdc0a341fdbac7675b290cdb0dee5022fa3832ddddb25dac0978f668845ba76442453b710ca3d2206280bde11dfe5a397e009d0b05be31feb12b11d0966c2d1b5017679ed9f936c82ae54909e2aa813aa9f1b8c57849d23c4b78cf373801a315a7d756efb2fea9e1a356cb603afdc54704e547cd3f89c009380c46b1c2faa013347f02e8e12f2b778049ed82afc3cbbbf078e4d59660780d364a3e978dbad0a9608caf6b3ad64d6f3b66bc10b3862f139067f8c4f5b1c1914de1cb2c6f1c7f35e1bdc448c847410d2f1d0e56fe40f6382c53951293560d38768fb3a4594583a087daf298a25557a262b4b769d2ddd082ca3259a8538fed48c502fceb67653c723e532cb6a1dfe141181b4ded5dc9987d0d2f97b1a26d5c7cd56e61e5855d4acfb37c7c38172c1346b95fe073ae3b3847b43953e819f75384f0c943afaad3e8b50186cc2594618c7d66ad5a56e983aea144ea7e22e30723ebc83fdf40590a6936dbaa5f642938bd078caeb67c24c5d72416e10108dd4e1890b89bf6ef66165acca7c5fb91e845c859c21ab34afeeb39cdf06a7ad90155025a6f44776a49faff6c678e37c5f4ee0e8c7dc3d764ed69dcf0851c5b9a7c43bbc2612277c49da95c8190534199dfcd8ad6", "3472ebc2b022b024733dc635ab2b8f39541852b66113732af9124df9d9e41acfcd5068d92e705797e41b54aaeb82ede93cc91f1aa1d36113452afc9025f84d67e433e13554a6ddd72078aeb82fc4cba048a9c11779ada2d1dba7300aafabd77b5a106611dccca6d918d3db68b3046cdd779533c15691b4f4a3139466c441cdab115250680b1730189581595d4686ceb01aae41fcb6c503e4fe56f58f406702647cd9a16fe0cbabcf97ffa3b2857494808e1ef09e04be1eb6569987a475aec9a32d3d5fce872f99cd79332ffa9854ea48b529b75fcb18d0f98117aa68b7e6568ba8c1972d058214931551c1b167ad2e49ac9749a2a0f1e53797bfdec9fe9aa1db081700803d781a94dbc3e016410dada7285855dcb8d8766b4a18ef2a86cbcd4024fcce96e0ee0617fe57d387e4d71d73892c7132b8eb42a49eb4388d742086c4cd94c10a7e4c68a54a79bcc35549a1872c5aabc2e8a94a1e133e5ce777203a7a025e2c6f5fe04c09c245926dfa8f67a3e7b9c7b21e83ef18b9a39655df2fc1bf36a5fc874d349b4d1bcf34e6d9e51df12306e8b310158110a449bd8d17e2b0653c235dd09ca3eef73c3f27350de8a7dd175b8d202197fd357e8744efbb1561db4d74167738b6257c4e3b915d02d5aaf1b6aef8f37a37340baaf2f2d05252c80517eb5371049c66a555e731410475ef2fd100ccb360b9c6c9ac6049f3a6da933e", "703f0dfe3658ab4587f6f0c9d1ac08c878a5f4d887329cc9a2b7a63e92f78843fe5954cb7ba14c74812df39c6adf18ae3daa8cc600eca82cdc5597350dc0418e62750f4bf4e70d7618b478eddcffbf8977a57a5af6c81e16cc9e28d3a822bdc0d16a2b13e369910145927fa50660a241271100c4df4e7c0c02f6cea6e2e76d783cef79edff7949139c4eb54d3d50e7d2bca99a49bbd864d50b9cd0662c285e0faf5be16eb540026bfc93567d254dab5ec4040e83d28c20d53fe239c7c26c16beff31cc629e1016e0b3452280b2ca9076774981591c3d99ad2c2951453be12a77346c4fe4a566b36be2f6dfc88eaa1d48860b3e8312af75b34e9c749f4214b2a7528249b32dcc7bdcff9db0235595a92b8f587bcb95aa04bf09d4fa87ac9b255f7b3b2ad9493946a40e7bd8e18d49575ffa1c0fc04cdf10e60bbd330bdadb5095c2fbb5ee9c4a11281686479028e8e7491343c2a49000050114076abd8284271e177aa1950a27068e1762617fb9281a2a72f3f0c37835ab39fbc2052fdc19e54e350d54881b1cf0e2262e7ab7368fa5d411ec5daa89a67b0474dd83e361f426846982686ba62c68641a73cdf57afa17601bb77d11ae32a739576a79ec795f28aae50cb764403691187554885e11015639a0b41957af5b755738d3a58521cb584c642a4748a6050cfc6f0499d9fb63bd8e1bf8d1ded5b34d9ec700d8b54e9cd8a2655d57667661b5a0b4171b3015e8db90f574b7514d8480854adc54d64838636340ad13e9975137cbf9c99b3fbce61988cfb304949844e472b9a014598f426872e4407e1efc47e44de77e89c5c00ca18580d5f78c8396bee155a3392cceebd054bcaba58c1263c545a91b7f5421ae4ad89dbabf7afb895415c3c26b0a231b6b535ee8cbb0478ad4fcb4bd65ffb696bacff8aa1ba1d3f3cf0740872607d2867644c8b97ecf591789251c31b170e3e90bda87790fbdbf631dbd8138a041ff4931e3dfd7b0a5a2131c28b60c273c5cceb9003017560f64d27ba5c01ccf019872bcfe8619ad96d45373fe3de10690081dd62dfd206e1be74b635654a58df0ad2aa588adf9c564aa04af36e2dc3a916cba6ae259ab4b82ea84c4091d310b3f358b5d21defb0eaaaeb699f90dfe7668c85c59abe20dd875a707608764b62649ca7354d87129f148cc50128360e2f2693ec971c6ffb3baed13bd556aa52a132e5dcd812f46dcfdc5b5ef8c72a05c075ce7f38576eb8948fdba90a7d626108ed0b4d57e4f379fc24d5b97f93139609b1c990b31882382e5004c759673b9f5dba3307072d6b87f0bb0b85b8419a0b3e390fa25d18747750df8f368145612306bea40fab352d75c98a3fc4714d7ba4d11f5efc704f9533bce83eca7058f4d37c14a12b7508d8d18ae571c745bbe8685fa416d5d588ccbfa02bc9d997486e9c5cb47a076ae4", .None}, + {.Sqr, "1c5610a9a8fe93520d01ab82441cd935d7dbf248af49b8875084e0e0068549f6a510d616e37619224c9d74d17712e0f01d68cb4c4e2155567c5774e13da66d81c04473bee88c8ae5a680eef3920e655dcb479b31d7930a1da1cce76d90b959b5ea7abaa830afd4b6464651c50f31d15fdb220e9143d6f13134d2c1e2e5b3038977045cc76b30cf0fe00be8477189494c8c249c56d2ae59824c4d6062bf64d31c06860d968aad42574f136790ba9cf54c8dbebc6e12fdc7f82f961709b57879f496584de6c280e33a3a5bf3f8945f4ed296e05659dc3933db6b56776f3c67e50445d5f954aaac41610244acd8a7ec5fa90a2e9978ea4dcff87d906bd36bb21fb8cf96ed8e163caf80e71aef9f8c8a807e571a67247c9c37f387e6cfeca75734cc0c723d7bc48d86063df6f292f6396fce815d30bed503db93be3b018f200c73c0d3a664d0a835dc96a5d0890c5c5f46070a27ec42cf670c7f5270fd5dff4cfda001ee7bb8aaa267e54ba29ee38fe7dcc80529e7e5584642d18c132f0b726566a6f48e39db1c7172ed2ddf5be3930b3f26752ffcc01a8151a9cb1ba5f684fd330ffdf27ed18716751d0e0c102679bb1a08bd82fb86ebab847e27869859d858a5144a326f23751256b90fa93a5bdc30e7e976e272b03f48fb96f53d8254eb6ba226bf07d9dc2361e7e9ed02c1c9966d01ca0d7a072e3ad83701f13d3c000bb4942a", "7b45d4796adbe96c96392a0762cd3a0a332dbfad5186ab283bcc9a38b6bb35ee119844b8fdf8109062b148394ce806f987a5f0c7fa12db9cdf03c3b2c5f262c3516dad5cdd7569b97f182bd6cc5e999cad9ef73d861246b65f9e2ec90b9497aa3dff63c10a4458edb8d7efb5de4d2bcbf1fba6ffbfcd8a45701aee10690ad01106e2763eee4884842ffba4e93effa180502c3386673d617a8ebf4e698068db91510a063b7c7f746ebaab9f03aba1da1cec7106d5f140d595ba074504e3365ce6f664c29279a25af3f6de3ec9cbc8f95f014d26a17571f161970b3a34bb611480c328b0ab06efd8565b40908e1d24c3d8b530bebf9812f4a39bfc6990b5472c9dc91982a3cb03fbb3db15bebd6bb9dcb71a7dfff82c86fd4206c454345425604bae58e32c8c601d15d14154be5a1e09e0dd334a30fdf6acad4da1e71327931f67a37d123cd810f07c06761ad34c12c5b0ddc73d858d5638bcbeaf4d708c60d611036b7ced17f29dd297f08d213c9e917be05eb4e0185855a68e6027e064600a33aabc60e44f965133a4149fb06e3b86f03cd1bb62d54a622fb39632f14472b9b6925510eee18c8bca5a7214b0da38b5ae052e0cc7f1df6984ad4dd878bf9ea8869c974bc3949c4190fbb1f84ff092bd44c181d4409e25f3941c625305bcb4dd501317740f03679164107849088b91f703f9973edc28451575cb02f4de7ce46416", "322f094500ae0d55010fd1d78bc230ed13a5449a8cba2303e52e592ed04a9baa704d53ac426fb7402366b84b571ce2c4a951f4f22639566c0a93cc9ab067ad5d9cf12eab630f26cb75b27ab6e37ece6f2a1c75b652b6408df95ab6f1fda00e5cd833da847ac6fc1092815b07fe683eb62327ab3e3d7db601fca12d78676abf193f1708badf756d527c19db1b41b68fd44912b492b120a94e19879314b6e982d5b5926e0b4db2fa43f052cd5329057728a8994fd0ca6e02a92e9a03e8e8b9b7862f96b326bc220cbd4e26fa334dad0f75c8a30abb2a6cf47cea61569b8ef17f55d3a1415bf7b048b0cc9eb076afd621463a2585890274cd3190aca66f74298758ef9abf1c5d6dc21abc42adb566ecd55b34270ed4fe1dbd6314e534e1a5320f7f52e2df9ec59232a42d4a5fab71d4cff0c96fb3688739671f1045c3436ac1d2aa63556a00f892afc0493a575cb9719b8bfefb0bd1d5624ec2aba5078d7bfa3f39118152bfcc6b7eba35ff0f3a2a549bb0e34d3683a6e995e56aa6b76fa77b63a47bd6691868a12a7064de390625a3f9a18ea735bccaf8483d98e6cfc7ca932dd204862c8761b80111f9e566897740666da9938be19cebba3573a3e551e54ff0fa04ff6b646d6a000ad659b3b7c94b8e607800a5827092f489d52d07aef44821d8459045566a3d4c8503ce98613b2cde0721ffe48145ce54a9d78d9008f49e87679a4307b41ef174b15332cd83dd109fe18821c8d2385a05854cf485cf7d7992aef0cbb6ceb3438a9e4e3a86a56a0199e42e68198f079d33a7be0914ec00c16dc91dfff5b6d28727dcfba1217588bab55c73fce3006c9c9ddba5632202c3df44c835054828288805d7428207863249707955ee64473342fe303757ea41d08b4e684d51f1adc6f0544663f4e06b02c4e57c299e61196e9097cf1ea0ca6904a1f860cecbae3650c3a64e7be39d0f48b50d9564aa20a984ba83158413200ce5cd1803290cdb243986a509e4f904af8a4e900b86ee8543140e921ddb699a1e41a68362210fec1ce44c15ba3305fa503c0fb8841e94620e4bd3fe3212b6339fee75746d04cc12642c7fc893155efcb2d1328fb921e426f343b1afc02b7996024288916846e305a29f01ba1e9d8f10c7867d7457be75a156197dfede589aedef8102cbad0604bb44d7d7ae1038076f05d05f092cdd0b9efee4ae5461fa1c0abe039d0238c80f901790e16639b09575adc71c6affa177cc4bc262efdba86405b4f85e23e8c6807515629a0e71307c03498a1fc98b88b18af2052bd01a040c9ad1dc329a4b3f055559806ca5d3a52729a35f784dbb7f4560f753ef9888681f9e5f400672af0a8f3a4a6868944b401db84bcaa790671a8ef5f1abb4e47f02f3d1e7af38d8589aaaa7e5877f1f8b912f96842d3e24aebfff59a7a12ccd65600b41c4cd096e4", .None}, + {.Sqr, "503e2c6010deb5fb59ae0c95ab4554c2e3dc11a52e173c7368984fb5de5551950f3bc5c07bdba37aa4c6907e28152ac011fa9d5ddf04ce6c8b26c827187c29fd35f5304765d32de44411d6de25f2219dfd0ac352fb7f08c8241cd0d98dbe9ad31450657e483169be3b3b6f8a0cc4e3165603588cc2ce356d928496d67a493251f56009e5ec8f31e7c659cc81fa89ec8ab4453662b9716c1dcde3b2e6f918966adb00c9a42d17622a870f5e4498c7e2a4e2a63c7acb3daab481c15fc0ef2467bd0b62d812ad34929a7f9261d6d8c4607f47b4a66455950b35f68589f7b77dcad0b0170c71144261589ddb564087e310cd2cba65e1f9c47e414177ea2e5b7b7cee7f728da3967d1db941376a81be956a89d6441f0e1be07a5ab621e92aa45f009fd5a818e9187cd0caa721a9ec41f2dbcb1b90805f351c3ab28e2366971580ee68529657487cf9c39b4426316ebce2be2c7f66c7c4aeb05a0440081ab55e471976dea2412e7870f73cbc7f679731a1076ff9781ff3683b15d1eac397f794d0b0c3b9b0cd9984d4b83789b887d6979079626dff042b896f9426142eee2a2828dcc4a82322656a7aade5c5efddaa53371292cc8ac42bc946918e50fa5cec3b752997e7246d651f09d9cf60a75095e6817cbba64d7e7a56212bac7796ec133fb879f9a8db3ac8073fbeb4a122427701dae0755c1833c643e86f132689039106b14abe", "2555cf171aed5be2d0a2509cb0e9f89082508ff5e1edd4d89e550dbff4534d30c77e8ad653a2e062e57f842ab977055f12459b012d05468c1f9f56ca801957a6c8623fbfd25c27f8855ab9d85ba79c3dd8fb6b3b5a9334febb5802497eaf8500938da8b56ea2ba58b6890f7d6df1bb3141e5d7a7e246584903e8f9396517a024fd7523202b49675847a7922d56c9997a383a5c2cd15bb396cfc4d2b3b6af435e8cbb69b1fa18fa16b3aa7da868492271ce8fb19c828831aaf1192cb8dd4e2282280ee1d27106ddb2894e6ef804e41426ae4ebd8cc07d234c8c6c01b7a37024d36f8c3f455199fcd92d252b9a672e4cb648146aa045dfdd1064715930894c941cc1d25ccd4dc41eda652cbd1b17b70a0a055ba933e7552d17ba7c9e37d7456cf08486913e844c54f9b1d80c59629dcd12a5e91eabc88d0c3f83918ca0cb1e5382cb8f9b56857b47db49b4faa68c9ef301a7db2a6db57f0406fd15a43c8665ce796a959583b9c6e61c571c56257cd849a815e166e6a09fc51e7379edc07d2f51aa311398d8db30bd57b4c390d7206e40c40b1c9238b00b2797364faf42e3f58999036bc7d8c703d2bf0c54fddf16e647623169d340d4637ab14bbbcbd3d8a97947dc50f2e834fd1066ea1254c359207a5b49723ad50e3cd2203e6e4ecd544d3adcb33c0f4db5748ea6365158d3cd27a284be0e3536647a290893ec77e233930261", "1926ead590c48776747fb40246e9dcb8c772fdb8c366c3c546d148b576e9a3cf373d3dc0ccd4caf988039ef10dc805e969c823c4eb1832e459283094ad6b810caa35dbee983c1b58699b22a39c20c14207be03da0459def3f56a4d4d9a788311eec9af9833a7d4614feaa069e360528d598977eaedfef54193a75c3b34ba370cf8aa080fef58ba59ddf65a911dd059a1f84acdf0b1f8709aedbc9d21b7f886a94513b6c22057d9570df082614143e63526b0f3ab37be99fbef6862c698ff14cb0c68168a8f6d4c80725fb0bc6025bdbf5a56a709966d924bb77585e54660a25b9ff8b176182d8f30ee4479e4cdec2fd3aacaed8bfb6e305ac84c8033a8b12d2d68efcbedac2769af6a489be99d3111128e5cc53c65774107c2a4af6748a374e31f79597e099b78647944febdc9c46843dfb8fe03143476469bc101e2c5ba944f511fb72931779c19201c11cc019d86594b2614cfc0f628c89fb252b2453dc4d23154b057f30d084c79b2f9b7b6e4e354c47d5b1a048edd7fbefc5f3bbdd0a6cb64bee7e847f7afcb489f6fb802a53b5495840029ff71f8bccb8f28aaea25bbc7652653c7c3992e8d53a06a1b542d85f68a5693078f68c3749e306984e17b40d6643a681253dbe18fe3c73169082456b50b10bdf94ec6a92920dd229456f63d26ae6532aefae389f126c69cbe89d2f321f493972fb2c7109d145e1283e800a9738b37dde61bed629cd74fed9cbb763aab9314e81826deccfb2c83a115b0e951b975d1164b5f40be40139e9a1ef3caf09dcc982b76e084465f14e94082a3e89eef2f17a8784899806a1c6da788c98d0b34089c2dd8e1cac87d96733c368ca948883cffb558ddd54da1a59035f6c7210f5ab3e56177e4b47d5a28d15e43474498b172677035df7834dfffe43d669e4330eede8714f94256a46068e86dab004424fd383082f14c54a5b72421d35001c6e8c523353bd6bbef10b17061f0af8dc8f858d75a6307a967624b6fe4ac2a6e73e5487b6167ff620701f747dd67ed412ed30147e40a709a5d1bf9dfdfbe5ddbce05061ee33771fbf684b0a7949fcd3c8539d947c836bb83b1ff19f03c415af765ef21691c8a5511070734758a42da38e334ae9b6559375a340453e8c9a97e23edb4ebe6bbf09cc7b9400808cd9dc988d7845ba8e535cd98d51751a5e9163c9c449b95f550f3a6934695558ee8d4578cc074898744ccadef61d4a63d6fe49985857af6677e1461d41989f6c09756fb850edead47b2a40daaed8ebff5d3cf1ac9c85d00660776fc9f2137069ba9eff7818b9175c48a32857f48db2c2bab8efee939578d2ec68e9939bb0bc88fe49462ff910a4bde9eb9a718c9aba8f5858f03a967dd4c4a5f755b39abbc1447bd17e7bf3ae9d344a908f4002624eaff77efdbcce3fab1813f821788c46077241fe985588e6504", .None}, + {.Sqr, "-4e8d3ddd2970ad1cf5eec1f960330b5b057c31cb148b572f7270af95f936e619092aa0ffc3217ee50d83c8a3670731c016786d329434792625ffb507ae1b0e1a24162464cf33fa74bcb96bad99c0420d7194be78f714afcd84114dd13840cf742ea3012e912c7e06a3f16e08637554084e5eea93413f6bf74bd3a0a03227b3af761f29a697f4a980300eb79b3141911ead9fa79adc70761696e557f7ebe74b0c2c8200537d453aa8b6396666f16b2f470b76d511e1f1238a0e5a4c1e4099b3559a4e1e94a24ed6966b223343cf5ac95a12c8e965aefa86b3c46dfcb6203f389282fcd6f4ce820c9825cffeac5941590ddf172b5a41034d5300b06bdaeb8bace8f8a8a48a5c2699f4db871874835fe6e5a278d544877098a7467d1d4f2fca4c621cf4d20c5d5d43a5e041850bf5d256529cfc01bb62821c16c2999c2f44499aae3cb71de31af71447556c5bd04ef77e96990bc7e31cde97aa25016abe393a2c108b6f9db9afd1c78330f40cda38938a7d7da0ae43ee9c3a126ab731933a5f8d2059c1fa04f0ba62d86d8747c64b8a52d9db751b00f9c1d6c1e556ad04745c73725f51d629feaa98fa6367e7564ed3e7e872fd2b0e882b324c9ec546fbfaafaec88a492e097c19b86e9d507cc3032e2bb646f5e32caa476b18bf9cb43397382121e65dfec55dd1932620ef00787528a7ec68f22f322af276565260d66c74ecf5a2", "2558528f27392c8a25169f1a7142748d037c35c8e404b8a3957b45966a8f0ff40048d03b5a4904c9588242bc9fdf06881f297d0d73f7ba88a0f2f42022ecfdec26fe3d0b58598e0aeaad9dfb5297fe493d2077c3d331cced27fa4b3f1e9b439c8d84b13a5cfe6d036c9c5818a19fd325159a2847bdbe9f2c3f7a3f904bde9213617283ebb6fafbc34f2a8b6d3626255bafd81099b3649b00f4558b0244f5576ae071cfd7ea17b4e40d093047db05016298ca65ecf240c8c293374831462133f9a6450a4631541e0bd37dae7f9dd298b2cf6f7735812dadb24885de30856b251ae1fcb36a7898b734d1c623410f9c5ba43c0a5fc02c8fb9af9491b601edacd63301f11b1e0e339f7ee6e7e91393a1db8a396c2be50bd6064db08c838e4932b101169f86c3b36753e6371044784bf3108ebdffd2a56869687ee4d9f3d6b454c46e6820d5da4247a45c161f91b465803a87e8acb3c360e7d76f696315fb283339a0bdf12a9c87781d7cefba50ab9f3206c49d5aed1d8c0b2a953a3b688e671e5bcd7a30dc9f578e0294543223ad409169cdf8a4533306b167e63aea41606a48f106a704f717729d921bfa540f01b926b87a2b6d77a5aa0f12b005dd738ace444896de0582c459347c4483f133aeab291641a726b5c0cb6cef37da3a7585b234e37829d28a6cce10e64d499f933290488d6e9fce4897f3a008a2e924677d302abe56", "181a5f9ff9d3746c9d8461753f2ca6456ad393bef316e99b152f6be36c484bf2e56d49be99281f10b639c3f63df34876cf7ee3bc7d87cd47ee44c22cdc8f63ebd421f2e32698b31af4b82e28b0d690a1d334d6c1c6c2b839677906b212d1ac923c03b15557ce4333bc1a262af1ec49cd31ba3d10f1ed88083760994675cd3c01e94ee98a24ac27c1fc03be40231054b51255fad749ebd1b940a6e551f06ff743a27b0cb5a14e67273cd2cfaa7cee2a61c4dc28b7b7acaa76fe4d1eddee0885c5a75a337c9a24343b1c2f43d1066ce8878f13df5599b94e1ef0baf990a53f6fb580a4dfbe48c9e2d1dfb3fedc344709464c43e92bf67abb70f32de7801429aa91cf7e5e56b0d9dc1079b8011cc58cdbea7472883a04886680d33f2314920ef748db72607299f4147ba8fb6dcc6280cde420774040919fbe9e7abb54fe4d68bf0a1d45619e9617ed000722797505561f15953ce330afa17bfc7eb81697ab8f6e1b9585b91b9b033281de2f32d7fcfec87fbd503aa0410878dade7f2fc6ed0a200767ead3c7405de4ad3f2198f602b6877432111fa88c8f0c7b80782836f400ff01983dfd802cdcfc131cb3ea7fa34ba3c347a436121a0e023fae8af0775d05205a661afb7099483a01b01f477e6880333f6a3d4ecf04450497a1bd7ed5e2eb3d075e6740b73dbb180f0badfdf74d1c057d97a84dfe5ec7ce321d77d4cfa1f384d47eb0a967d6de214927aab94f6e5da2ed7c2b2c9a28ca62f1230a25c0f015634beb1a7121f6c0010e1ff45e87c2fd4a4d3fc34e0a255dff43d665206b8d8b6c23df4cfe8c27ae7725ceb4175add88bc55d0b701f7f1b8aabed1a06912dd207a77bf7e86d023220a7caebe0b32dc0ca35228fdc426648f0a65d371b9d7317989605f297894d3422c82292fed5767a7cbf6fd804341f33f59fe9f333b90729b47ef620b6f84636254abb2041e33e2498a652e9b5be9fb7464c80f3995d817d76ec23fcbd38663f67240b2bde6e1f108de43fff3d65c1eeee4a25a5f65fea6b8f650771fbffbcd010aeadc8b65b2a9d81b2439bf57c617f2c23a5705b674d85039fd820eaa8c3ff35ebc04756b73686639c7a25aec33eebea324dfd932d1980299f340e2830159ce4f6fcae382d635c72b3a86839de595ac497eaf271fcf3f814e17739a6b641b25858150ca10e41d557bfcbe15ce3bdc5fb1c573f05d0f129780be0f44572a89f63818328323f04172742e22957e8156fdfb2f91b0c739bc48e120a5373a61f524d5b4c0cf783cdbdf1cf0a029e286e3118864833ab111d1f2126863c523709be0791b86e71865706d2ad6facfca07082d725d1de3fee72cdd340f47124468b9cda9f318619011971b4bc3580a7628b9c37266b03eedbea0d3b5cb5c02f675c3a246acd53510b5198aa20e69b27a898fc7615b0981b2a09e5f7a84", .None}, + {.Sqr, "-f77d01a2292041aec0c78f4e192ac9c4b33a87fb561c20ebc409f57bde964ba6738abf5483d30fb49488c686f2fd365b4247f903257f5ddac6779004028db0f28a90280db79d7dbe67af3999a7c59dbc69c6d892ba9efe3179705808880619e2e29880d5415559ed16136b1c6778f41c8d83f1f9790e58658ba74a252dc666a4e8f473109b1384c1bf30d2cedc213b6ffbb569d3193397ab5bb9f32d4708470b7601aa52186593cb7a106d5fe9baa4b0a1cea88acdaa05383c66cb6859e0b94609280e7275429db4bfa0bcd3c57ebacf3cf900fc08250ce507a0489d4ffc12c5fc852beec0c36befacca4429eb1ad732db608f31c1300a801ccd860545230b544220a9352aa0d29474672ef830861b8dfb099254d69143e2181e900c3437d25aaad4a1cf1590a6b87cc2fef5dd994bd14ff37318f396fc556046d70cd09152fe0e9a84746ee681c160fc559f11d4053183b7a96ca4275f00b5311f7748ead093d3bb709dc3317fe4de8e134162a61ee02c538d4ae5374223c4f36d4096f6fdc4a2c3b3a70c136f794d1efe41c63e9542d944dafd3fc2423de99909a60e2bc1357a5012ae3e599b5f4e07269d7ee1159e0ae425574e85ebaec3bd47d40a066df16366803c17ce583d9fd80f0d6e34ad9dd4b4457ceaedc3cc69ee3c03f957f617b22fdc1d02a6bd82608370c26e7156adf20de7a3f9199a2a2052b595379fc26", "efba4ad96429ebc74ef3100edb4cca4c19fe5b00a1a1ed5ff20edaaf93536d14213e6a948bed3edf5d8a29934a2c57e2f07d90fa8862483981b343866b8e5b021158ad03b9d70fbba241bd2d916eb9cd95eb8d3248e9a213987c44524807d616703a3042417f5f3f5a8b560a6cee861e7087113afad4a15189e752c50aa4b30ca5c259b3ddde00c34afe4db285fbd19187a5d3854a5970fcbe6c7a9f8294011e48743b98a1da597df4219f02cb29aa3a69ea0608f4482fc28c477b9efe83c728953c2b13bc7595c243546edbfd52c0168148a96d2d32292900d445fce9930ddbbdcc879d2bed554bf6161d7bcc13be486a4d2559a19e07bc95e60d5ab2a050cdd9c6ee21dbc0b82751b7d282e3ecc2bd80527816a87889c0333bc7ac1c1c1e02fb737443b5a20785fd07e6046e28684283735aa49eeae9c9e6d1761c8aff1a44b25e23c66332938395a694d404b91f33b65147e932bbe007b6be17367e45b209ba88b25cb73867ef33dee33c44451ec606ddc853cc284e765c402d8962992d25ff22b2e0c82795e581fd51a3473154788e9392e776c5855aff75933ee47088b63b2bc4b96e8224846acec0a507c351ba20e95d7881671a35e120d90e28107ccfceb426e8e6da1538d19c3ce6258d108dc3eabde5558ac9e00430182650d0a9a41eb76b503565f4ab39c057ec982625035a3ebb2f8e972b5e44fd278b9f2a016a", "ef42763183bb1349b09b3132a8cf73279a7b48b3bb59cf7a0e09b7f24dc6293fd73abd2aad174d0e6037569c51db6e096241cf46c63629adfbe43bcc57f1083638a1dfd0ab0786f2f313eaf1afd88fa1f0bbf7c1ac5985bb365efc8a0639b31075e625a4b74f319c7f2f9923b914d7dcea537d5ff429e4563f5c36920e2bc5afef5ed99cc72eacd58f742dad4f1bd19298efd50c382c50d726fc2676ab628f2e578ccefa3a526e4473db2209900dc8917b0b6b15d75601747cba05f0f65bc00d5d01c76190b37c318c2eb5ed58616639c26b9b68e97ee64bdd5bbd1df55e966cfa75b79d68b1193cfe13d24f4f81afcd7d07f319af8b6ddb8c323a6e2274da7ad35e12e0c862a95bf3eee053124cdb30c1368dbe432d7ace48807c12585d4e98b7dd17bf929b27ce7d14a4022a48da4f89776c24b56305924b3627368c1c6c4505f01f0ad0e8dc38e38da7e130f11852a31f856596e3b5f0a1e1c79d78d8e4606c0f2e9fe58d91383cd2b44ddb67ed40663fd9fd17473cf4f1a491b9ec7fc7411eddf60bb9b82f17ceba1d295911b59aa2ee2535b1f2a605e3c76577890c67559a8d67e2d120dadbc80bbd1750be7bc0eb6424a51b69c3d289c2dbc1eed8617c80b2c5b7def644824bce58c12447eb8938a4d5f97118cc19f9a749407b281b6a266630e21e5ac7be8e42ae352377f6001396655f03fa50142bf69cb07f1cb7413cc0cd3c44db3f62f6cb0ebf3ad3c3cc824ffa008de8a67a63ffc550b61518c67dd287b662cbdb844fb4898b84600f9717848fc375dc485a1574680f11c49cee1e8a15b032ea93aec0d6e3f74a2579eea6a3c729b82420c0b9f0b5c1c3a8d0256d1c38fb9bbe4fd185e86ce156c8d165d1942a7a5a4d2d41d36426a3a78a97b2500acba8e9fa03555bd8c378018aaebcb4295af17fa46bad3418d9c613bf1f44ab38b130c33ab640a9f066d588d0d0a1b05ac0cde958d2d0ae6b2b135dcca39394e0dcdf918053fb6ce408d0a97aadddfd2ad97f22edc1a4869bf9890e938740fd3777c9ba9138aaeff91c0ddeced80cb53fb761a417e00408f2731959b47d7368eb5027f45bc25623272c08afd192e9ed8f5ead2c26f733b4e2cf5f8a2f6da7022d6585946923f118ff91a97e6a750c64da1318c001bab09dad009168a55400472249a4d9abe2372ec0b66ebae3ee9767c2b4de98aeaa0f56198ea89082e1690066d9f16eb5e9f762f7e53f7424044fb43d5ee0e8b166c674e114724717bceebd5fc9f2c89894031bbf910a40f8f2720dad5fdbdf7aea97d1746f6eceb043d97c1b96047b71ce9cb0920e0360cbc87c30c8248f9669c9169e15f432e0e6cdb734f2ef71ea741783d73b958ec2050cb79bc748b294dd5e53b38becad249946b5f3357f649ccafff97c617cc5048f591443044f934f5332123a6a0cf846d5a4", .None}, + {.Sqr, "82088ce4bcbd905214a83850ed0c9536420417331e74e46bde25142be8fef549dc7619cafb112bde25b45461c7e495ab7db16e8ea8d7811db77fe3a3b3971ea6d4f9f70a47e9a4f9ff2d8be0a208dee4d392934b268e434eab0ecda345bfad224458e68f0cce3e8242640b430e898488e8896f89f5ecf330e2a3bfb18aa32015656e475d86ccae454faaa771a2acad2a7065d6f11847bbeb1fcd45077aa8e71a03dc21251c66d3e6aa44414983c6858fe4eaafdbd15ca42fcfbac9f85ca80a0bb49f3ab24a0c68f94e478d2ee3d6cf13389ab8b384a02949eedf042f9d85229e25a38942f3c9117802b41a1556047a3f2a709d564bc0fa7fe01362e7ba32a7fad259678b9da9a5dda3b73fe64f79d1ae310d173d2175895ba28496386abdf7f6041461d5a6ee5a06ce509dcf388704399ad86191772cbfdcdb64636143926c57c2b8b00c0772bd31579e520a46be72334710d5bfba7a9c78b84a8112cbae7043c791b7f2f20ed11f4161d0356b971559ae58de52b648540df85027d2d3e96312bd9a6050b350f3c88e3c758e581ffad0860c9bcf8e7eb084aa138b602aa1b8da48096b9517c1bf0ee5f68e4be5f55c5678ad9535d8ebfec7287cf1696d7f04bcc66950b2487e6f735476ac0d78388f7c8dead323e7bc1d120ff47a7c679e5e2f55c586546115063daa30685342c89cf3c2d56962b369e648cec09628aed22dba", "bf35268e536991a62732c6f4105eb31609b3150ede65538215bff041be069346a3fb8717e1ff9fa844c8e60087fa41324c444048e5e205b87b3d1acb790b5b4f06121c0389f15240716214e6a553468b4c8813c59863bf4fb0f0bda1d210a03a2452278029b345b6ffeaaa1b0a16ac190657a2db693771a5eeb432317d2b21c0e6f539473cb76a945fd78660a1b7d82fbf49752074fd7aedebc39157af3cc06f9af258535bb5832eb55e6dcca364198e08f053b2b8c34afe0d5380e01e02d28f4a40c5cf8b7848308e69e573ba4b509dc34619db16eca1b50aee5f870ad8c0cfe0ce8a87718d1522c6852a1e02980a846a712922b70f9ac3a52f0613dfe977636fefc782e72c84a89a4b9a3d09ed467803e764b6267f98f7b96c81783b4dd19a5b212ace8a46afb8b27381dcb47440bdbb3c507f3c2d3fd49a178e0bbe3ae9c054f892a30274411d40ff178699fb3c5e082303bc756443b19c917ed0690e144ed43d79d29c49b6a1fe95867734255f320d9b2f5dd01eac4fd0791e7a002d9a66ac09282a8a7269f003f4ef46c1de29e996a1415850f0e4800ecbfa768f4885d3e6f66ba80e82cd5893ad0babb1edc33cdec36af64fb0fa6baf8c1af992576a24a6a791a8899ba54263bb463fddc7edddbb81f4cf0c210bfe3f982da0573e253eb8287f327ee2dc92fb24144f202050558563522bcd765c9bafdeba5ef580c9ab", "420caf616b874d3c74c5f4d977f27068f07fbe44116e91ecff8401b31bbeaf92deaa429df07a9fc44bbe750394df6208c0890bc7b6af7b7628f57ea1ff42df6c10a9a130834a6e348dd68ef109ae263b74f69d987631933bf7ecbe917ee4c2bf0413fdca45e100a9767eed6fd31e923fbc9f63a046af8c7952f62c1adb60e236486e7b0a21efa7038ba76c53acb84717640a5ef64f8ecc4f6563e6ea101ba7c710f4e719b0bd413085ffcf06af5b2556014dbc87d93addf40dd0341addf4b6dcf058c8fd3283ba597ab682aa07ecc0185533869cb4a8542f797317dbbfcad9292521f8df320ad26ec76efa016f64f5249007c20b3a0482000af19af4d8676ddc3379c3a89063e021d1e7058023d2e9faefd18451132e3134d15de01097cad42058c21bdfe4a125542ac2ba5d62b26d6ee37b15941e3f38be87a738f22d7115aaba7f3759c7ac7e6f17f430612fc385884d66bb35c3b7d6e2ce449dc830b4e2d3dbf983edd508a16acef81eb6a3fc8144a0c35db6782f49aae7f66e788331306317e918d16ee54c04339d6a828e59bacb0c13d11e2a43ed9e3b2c980548998c951ef8ea1eae2bccd674ad50e48135c9697375718ea15cc7af7e5db48db68956b9316edfea016cea0ea5d829ae2d14ab725cde964c16597fd1ff8b2c6296cc503cc4bc812e8b9dd8e781e43afc1d9db9e01a3bcdc794f2c8aed197133ca33b98a12a8702566dda0d7b2963e1da23943c96123add3ddd749f0757a0884a510da38decb5813268a99422d7d747d3569600d1cfbcafca26b1ffb24e509fe9d6c7775a0f80bfeeeb2cf3e816556b537400be0751b084704071dd0f60200743d0dbdbc5dd56b73449997f4d511d25d3c9b9f1c64b022449d2c6d9b787d7074608412319c5b9507cd465b37c7961fcb43773154caa558672d3f9374fd8d8f649c9df9350663e341278b268ff2783a09e11d3a4cbcf3ecbc12e439604aceaf84b317e61c1e1b59d3ac3aae88eb4f2d3c46f196eaa1f37df0240c7800b31176042950456420a20e5e96dab84ab518ed69782d4f7d90593f679bdd29dd2cdf886780c26464c31082a8dccd2f3af49d6dd0afdfeb204d46fa2d7243988d6a4b8f1b9966e14491c3086f59c1794b229f960607daadcf92c3f4027a4b829506aa093514b5acc2bc3ec01d01c59b81a483776ce2a277e1da1f95078941234bded19b6b7209bd81d9f906d7a53f716ea647fd4398a23734c3fc0494da1228b37c244566da46e7e15e033458182c35d8cdc4250f060e279ab73e68dbc00da9bc9baf0f10cd54b961ab614457aaead5464ed6d5d641bd21b733a83bdd8bbd057eca0c46125aebc4496f102151cd54f40ef0dbfb7ba0a0214b1c22b407cf988ff085f91dfeb23651652384f6381aac513a169c23223bca920e754eafe52ad6c20d155a6a4d7e552eb24", .None}, + {.Sqr, "-c0b8ca34bb404a005cf709a260830574ccfbf1a26cc5d46b25a98cc91055df7c3679e5a6010ddfd92a9c3166810d4ff20590fcced35b6bd250a4a8a346c1c4ced170f17db46f62b40cea2d7e23ab8df2b7a0a223265696792a986a3cd0cc939d435a1e9a0e8d175fdf51953b15423ef8d2378e3f94db920ed20d8b3c68958bd37d364624761aec03e415e475285fa859fcee6fb5337245bdfd4c411365a45f7789548ad60216ec68cd43d8c7d3e0df65fbeda1cfdb042e0f65086edfbe6664d8921a544666dad923a6154c43c19773a3a66c466496c92dfda05055b615f16827138de9fdf22016e0c6d8e1d686fd59e48f1edfd2316bbb4c2ef155fe2fed0bfdc6b558cd495d57b0e29facb54d2ece92d9a0428c7e1b4903df6b22b628ae1efcdd6c3d7bc3b2d0e0ad87b10ea0d7e0774b01d79080869268df4928c361eac222c3b6ab738bf0b74bbd7fea324a1a8f11c08109a6aa40f4a22c49799986b12897671d66c2cf8536e826eac7adb69e7962eb39496f04b329b1a316cd3b4aa580ef4e268e533772da27159d317a91fba85f110c687d17f253fbb31d04a87fbb3e71ef84aa860951d1abd40efd1771a26b3e5cbe276278aeb5552f518f931e013d5f6d49abdc97230f34ccb980544a8fdb8e1818b01f3877e4501e83db22adc721aa45b695d26543d88197aa6f3edaf948aea19796af05d9b8fc017d73a426ef684d", "214611df0c6d9ca3ac517a4975df560815c05cb7bc88a773ef5d0008ec6b0d29c80d370d144d6c00c3f4ba29d0a78cf9769c062165f728449064f18a909e40b09c25682f877274fe4812575bee65d96b968fc8f65bf54abe89a27ae57669cbfa4282ff7bb399799a6f9df523caaaf7a8e1e3eaa6d0d3ebd44e714f6f5b974774a8f31843d64a635430c6f9c1eb4cfde4ac7a7af59ca049c859e15df1f0496a63511ad78111c0fc0c4f3b91b4373f161d8652964ec5a4624efc7c6e8a476cb7f947e30946a3e9a8fdf259791fe18c28f2ab4cecb9afdfd8207b611904ef695a24f1787027bedbb9e6861dda309ac91dbab950e36e93b840e3033d7819d6c1d8088e9469c1b76dbddced8135c58a098a7b9213f22ec18d7926a409410e0ded17d7c341631f00acaff73bfd361b4b667e4ba435164c96bd41a0de0ae77d1ed367e7dc606d085cc49ca88feb53af004bd63d96d60fb2003ca97f9c604c854f83a1677f1dc7f1aa4b54a2b3ae9930cc2a0d7582c2fed3980580ca98a56f208a7fd313e467d8c44104cd23d21d1567aaa44bc747d13ca64572fa6310a7db090215b2a82feae6b9acf81737409f55cb65692db1688e4a39961ddcfcaa808209f5125f31275a599730a4537009592fcf6080f5afd5554aa368b55d1277eb67a5a08321305d18ebc086aadde560af023837b84c3f59ecb3b9754313aac17f4b35b4bd1e81", "9115b4b26464ddc8fbd5d0aea723082402bb2827466aeaac353d713c50d91c5fbe7c45eae6ae7ebc2f6503d23d8b8b8a5ed4d9c8a55c8c58a519250620e8073ebf7ef1a84d673948af00580591df3d59aaf77812225e6bf259ddbf4bdef0ce20469d56f59fba19c851fdcadaa00ec0e77da01780a99b859f0cae9c3f5a859c08156f874656325b8ac218105982e5247fc992ed8dc791d469c439ab0efec4eff513e1553b9dcc1b021450619b9b6a9ccd966e4629455d2ab7f1892345161b526fd4213382615ecf05e4274db5e4d45a440724389b6e0fd55c6db7fcf74acf94d4454465aff64b0090dcef25e121f242dd8f927a4a73d856cd5c88425e1e7e29c4784f0c4d13170f50c4fd188dee5c2d25bc82088c399299875508234abcf4737b2d6a5bccc934b9766eacd092ca35996e39f508fa781d5f94b7a4867e8165997781b7918fe7a1066af44128d3f46b8a1e0377d7cf8153722f00a1ce5361fbd92750992539e388a3274ab99b64c74dc8dac19d5e728abaaa5716f0549c7cf213c8620890e3491698391271a4078b8facbd49ca6f0fe2903427f05b54481eda364a4e7ad4c68e2339254a351a43c8d904605bb4e45f46dd65e8e87090ff2d05d4b1d3c7777e53603f498bbfee5e0a78b6476a5407c6d3476dc0ad63ba40b89eadbbbd66945173e561cf1eb0cd091ae6a171ad36ce3d3ee768f929f548e4a08d5b2957fd8b119bb6a5adb1bca994c2ca6e602de7a7e6661f6e659c5965d13751ae6520f0d121b2efbf7736b6198c67be0dd819165826fe01b9b3a286d3520785d8341e66277c79b145da397577fa99dcaa413b56219c986ba79200b9db51e3a21725db0c5130859210d24fa80aef52559b61e521a15fdbe0ff6e4111fb1e0e55199fab5c74fdc6096b49705b7372a86c8984a8aa09baf8bc1f640da4dced2d60c58d4948aa790d47734cd6422006b0cd49cebd2fe16400c2ecfc44284e08ea5f72a66281b298b7af2c21b9b578a8086e6779f63f7fc5d9af1fd18b73f4eb277e61a9e1d75200109f20ff57ebdf1e376f00aa8c747c59017101203e78b6fede2ae3ee77fbedb39e3539d8a31616104473fd4d8d87b0c0456119141cc2f815a9f085a765b73b93de39959d963835c0ddaba02057d281b976284f2042d2b72b4a0eeaaf1d2706505eca1b5f531ea3fb75322d440deb8417570ef480749eb556374e66176ea63057351c5d5f452b33493cf367ece362a228d0cada375bad55639404581fafcd6192c16d6b54a40a1d7e7af98597ea843139f2788936360997154949a8c7a12fb53eb1366512eceae19070ff32ed82de188c703af5a42e66517458c6f4aa846534084571d31d71f6bbc9157c8253d8ae9908d705a48bc7afb61a3f11a7b6c97d32920fe5a8524ba451d48c8347c1696a0cbe0ca6d0717590c382c644a729", .None}, + {.Sqr, "-614bec78b75223cdbaa55fb11bab1401edc8d94fca6774f6e453e42a9706818f4235080a15839b0502da9eacf728322aed894d2f556c3a73113e5e56ef5854aa9a6d462dce121ac580fcc77fc62b257446cf584724946cf1e48a9c29f401326eb61c48522dceb108573b810bd5707dc25acc1281160d83d96bc19eb313f97ec56250eedf4523c0394c35fdb3255857c234b2ab6bba8b7cf167b1035df83a2b199d4823acef93e622fc13c4b0fa154c92cf78a9f3d7a4668084da7e9328f85151a71ee6177587d188439a51f43a65e47864c48d2792d4c38edfb4bddda3b3a1425851c572fa5b7948774214f9b69c5176e12a010d5503b6c6aaa329a65b475dd3a99a0da89afaf5893139d81c8ef47b8cbb05ff751a0c6cf44814712975b6428ebf1053172efaa7072def19375ca497aa3da856ed666eb89149c82f2ad68db5c25ab54751e9e72eb21ec52a2fbc9d5df3c3db1b9edddc892658c739bdfb216952f82629b272b53740b02457f19b297e5e194ef16b4450c879f77924510ffe5a6374ee36d27f09f91b3365590f0be6fad101171ab924781f3c2e3cbb8a06ab4f6e05839e9afc3a3f7e7f2d62de8ccb67d489b8fe64301314c599ef096af1101b7f60ed12fc98a4b72b39ceba383f8c0adbc882326595c4b147ba35f465139c79d8c88138463d274bd6d354b96ee75afe50b832cdaec0a5518af1590ae5187dd6f8", "d0f4cc86cb138163c878a2bb90b5b4fdf0a2ccabd010f1f717b2e88d255c80c205f2ce29426065c5c35f3a04d31a4fca85429a2ad3304ec0c353978b9bc1a6bd8e47c166b6c8f003f46e756b93db72d74bea9e972aba41482d1c7f2f8f34e92f9e39a76adae7a8ab308777a84e5c93335fcd00467eb530268f80bc8ad62a0404d5acbeaf610f503012e1656af5504d2611bcf82d734899b5a1166d5b2e83ef871f7bbb25136f75d70e5423abc35b82ebe2acc2216c6bd5670c36ef5c913ba91c300827ae962b729507badf17e573ccfa2edfdb2932a85a8318b83d6526e589ddbb54989a5d4633670eb80014d5a881afff88123ca0de13a9fc75842859cf5529580e15a9a900929f710d4a7b344971eddf92c3dc5c5bec42d1e598004c443864ed88468eceda33d205e46fe1b4fda2608ec2ad9d97d1538bd056fd8dbcd459ba46a0d256827957823eb66dd3e6c3ab5fcfb8fdf7a48e98dc9a20652e7d5d7e3511ae2cb4dec2f74a8346393fc04fc0ec61be92784d949358341a00c0a69502fd491c9f8f522c452771d465ec6bbe973da77425b402cef738726268d251ccc27c8c6a137f63e7ae72a1f46f1b806ce897f36a418cbd90f3ae9bc928ddb122cbf9373f5535900b1f9d6259e9a1efc28810a395639b21fa478941be26d2b316c507162c32984b36e3a32bf7bead17acd937a2833465d41b0e2c95c5e48d6eb24c6f", "24fa9fb7e416742eb44819f541dc0392bcb891e38e0915600258a985274e336232a2cc15c3b90662ec7136e99d076cf3a0b32158570d8815b974fc38250db6f7702eb70797ff31111e1b1a5b64026601d0cd88cc284ac25886926fef91672d9a3c9cb7e7dabee6de10a4fbcae55a5a0538368cabe7ea5af36e6dbc7e6053cbb7cb51628399692ae65be202929c24f52ba3152f55f134d2c48353304b8426f5314248913a608622e4aedcc0678c687f86e7d71329dfcd4107c00230945512af76da010af6f2884a4907985166427a488eea0a3ab473424ce87fa1ef9d339cc138f1b4e48f13eb7a55ca781852f7324ff93ed87cc68d3ed8da0a45f8991dab726bae1fac3401d095db02c221b2ab40e09de1bc16aa78487149b648c97d067b166e0ea7b5a54229e1beb5b5b1a0ae20e09f394694d4013ab78568709e4f327f75c6ca92fcde5d45c2d122d3da218e46e26057c40418d2b4b82b626d97ce61342508bf5c6bf605f02385cc19085b4b2a0084c7c3fa81a5033d430b721f7376940277b2103c876b9792409c6a3ce8eb733b01a92450a391542d82d82d328ef8f9e4340494a79df2356e5f859c18522ae42070c71aec2b72be481cf3173f16f013259b541e993264c95084b4f9bda44816dd5c57a0f8fad44778c64b68aac6d3e2bd5a3aa57fd625b1816e1ce3c05c6d727ed76c03c1a5a750c7f19a2693b469172f00ccfe93b1a3464eba4f7498b3c2ba85289b32efe36624494e44c3699c4ab45de0afb26893e39cd0f6582163f07f2a2414b78d89956bea1f505d25f05965451657c7024c8e4636baa73dda67527436ff21ed584da094bc158bb31be513bcf1aa25845dff79832c5068eaf3e41354bbb37a4d68988e66bfa8c1cc53ea5d16396cfee6046b637e9156ce313983a105545043d6e9ea01d9481be49200325436b00804a8561727d69422e6b6e31e93ac9a022b9a7c326250468e019fc05d54379bc7f9c8ef2805f078893e84729d9ab425e9579f605250a4250267d61ec09da1d3585bfe1559e2ba37c929e07a8fcc1a2a289c9901d475aca0162f7f8b6b4906945c711e48a19691216d26150dac82c2383f08bc614ddb801d2aeda870548aeb61584fcb9a90711a8d9fcff65d4b6542fcf94c00c6da4aac9d68114a84d8da61e9cb97723cb333e38ab6b62a0cd1f0ce9e8abf662278d13eaed03ee399923c71059a176b0adbdf6cc4a99887e4f4f23eaf07a2535b6e1005ba735506135754ebd8dbd4c3e3d02b52fb52250daa204e7afc37091a1c9505028d4a191c27e989ba7c86bcc193085e04a4d96c8e9fe52a5d8e23ea3c4025b11b3f49cbce511093ae2687a6d8304e59bd2b40d668c629104277dc42b7c4817ad2664fdf105a889d3af426a64376330e01ba03803fa6f644a1e48f166eb53bc511435c8d10b5cdda22b39040", .None}, + {.Sqr, "-c761f50f88259ff25e60b40d3749ad9d636cb2481faee948c6cb08133dab92de882013d85fb86e1c9d1aca10feb00a2f5cd1e7e98711b9cb3c1552c0ecfc1b83df5d3c28bfa31beb0fb12f359cfd9e27b2196c968ea9b9da2ef1a1e824f05bd6175a20fc8b593942c0f657053b819cc25ef744f4201c0c8b9ee3d4205d556eaff35063a99b7826e89516ac51b4256c2cdc248693867a5ad4ba9ca95659137ad8ffe4decc1ed03ffbde9601f5200a8d9d409dccf9aa61694b76ef93523844f87dbfe29787099631c11d75f2fa6e6c3304a8d045cdea1a804231c982f971a20be4d625b1cab0e370e2ade1a8308717f2ac8e4e6fe38098038d9189bd3e6c2a10f02fd5d6dfb635cd1708339229902b290760495274b64f0e7893cdef522bc062274fd4bbaf5759afa6566158b78d7fb6d303c137a92bb8154cc63d8efa696a1097b34b4159bae2522cd6fecfc9efe1c1a782846460cf2f8f2a46faab60bda2911fcfe71a967d921539d313cce325021d88ab39a6755d07e743c38fe6f2fea43addea6bf6cb848450fd69cbcdc58f32fcaa3767903d4193692ba307cedbc737e4475a829f48dc0d395505d667e9043faeec30c39184cb5f7ded1958726b7d0035557302ca994978e0edb5d9f865f4fa32c4ba14ae71c11ddf0d4b6627c6d1c137043ee0ada65894e24d6679e5fa1c9a1405162a14305db14a309be385574c75541d", "863b6e8bd5a807cee867934583682904aec9bb159ab7f6d33a30a4fa7b032258ce71449f41e434fb43da15fb6c2a9b293d7f5e6ff121de3921bbd96bf6c8ef93f5a64aff3f2f1799f6f509b7d8efad1e1a5def9bbff6fb0ee0928254d55fc025d71925913ebe64901236d5bd21168a1fb360422c7244befaaadc0c58ddbc799c3ed71eb0e6db2b793f3e476ece07f84e219e947f90df94c1507661176ca3141644261984594357da92a4b81933244db7f7da261ecbfad2af0cc4efe1e924ad9815c3b297ceca63e69ef33ded6b64f9ce2b04fd33d3ec8ce81bef1ab90911044fdda0774f37cb30d83d5c6ff194f148eac011b4b065f7bda244d83fac808e63d613c00b5ac21cef75edbe1630c6e1da18ccbf487a21125b2801e43626607c84734c13a66bf088302293c7c2a0d974e936a54d81796cecbde36de699fa032e7362434c7bee578a1d1e0716adc75279efdfdc33341f6c177aee42f9135772f28f76b89318d9bf3c140d28e5f253dfc02f9a218b162de8369bd4b7e134566ca2aabf7f060f344cf7feed6d34e2881f0a72b58935f44823b1348cac594379f044e5c2e2ba0d22b67cce87050f4522830728a82ea21e0b27c6cf6a7ee20336ff7aae8c5827b13b622c580c297ac1836e04d932e32ab6c52da742ff9d288f6c899fe7ed87670cff5aaaca657281d4bf2d44fadfd51bcbddf86063a03bc7a2f94ceba1e5", "9b497079c60666b7455c83ba4a33d5148aa22e79a323056da954afa39bc52491fe8054e39048ea836bf9a0509a8759612ac342e9be7ff89afd0c3f4376f3ded3066ff9ecc4ef0007b92be78dfd2757a2417989a3679ee5780ac5c87f2ea9f214d7406644bb8f8aa7d6038121e72fb665ee2cc8573bb2056b5ecaf3889dcef165af4f62bb272e48d91e84d9f7d39c9c881eaf337b8b198dbccaa2c36ea47482cc34004ba9bd4433ec69f414e4b87f1686badb52cbf327b7d8ab07d8fd63678fcdb1e5c820e43ce743584bd93bcfc5e36b3bdc6d0111ecfcfe4937a3084f09bcbe6f5b6781f628a5a2bd3cbc57de0b481d1d078a266193d95980c6842dca973e4579aaab5c069925723144dbc6998e1083a34043ebb72b4e87d60abb9e4e8e115f88ed0a94dba6c487ca52a7ecb8a54ded66838decb07404d85f4ee7e7cc7f4911d802721ceb8f5faed3745c611907103cd3fa961801dac3e610d23231061fa038e16dc41d71f89406223f4124e457ebe9ee9c98bb71f9a0d41617383dbab27e7c31f6b99f4cd05bea73427c7260c81a340ce08899e62c275ad86e7d3e2965d07206a8509b8fc6ffa2d21ca3e69a7c5cbccb52b3704cebeb7e5ac483085ec6ecc12217c06d75ea63689b00c7a8bd7364f88764bccf20c485edd4470cdfb791858fd955f01452ee44f9f2b7a4b9034edd6c92dab81b25c7265907bc2ca3805ad591eb56a14e7632e50ea74d13e7bdcb50c3438bd505bae67ee9bc59709ab2561caa2e76383d25359aadd6dab34d7358cbf040058360bab37ca6e43a0b5d49893b4ac88bf4fc41e5ba842f395e8cb4c7e72981c2781cf80de54523eab0dc0432a834602ef9073da04b554b7bc33f84018aad59e6e8544af9017ecf79be73ef11d5490e1580ebc99df4056deb9ecf09f85da7e6b2b42b16e435c2eca2a33c79abad0089100081109002973f6ab333db9f5f8b82472d4711b080101c46602f9543a0cbc173c7e4879ac34589f34af1ebceb0feb4f8c1d60e40097377eb81d63d7ed8264e2121576ffb5c972ecc80f57d2cd526e8501b5439c26d9fc007b641e3c2abf2d1f4c72e582aa34c69e121605b230d316b669a53a08f801fd19a7da5d73d7c489b474a5d8715a6fc8bfd0fcd0fc33e6b94d7040bf149f36d12f7595998b66b9058e45b1183e9ad34c08ef1bf5589ddc93108812e7b5933fe2350953baddea6b8f4ee4dc9ff9cc7902ed62905fce2cd9b4ef937cff08bfe90f6098cacf30147ce3672022582500daa0a40243dadb6c6fb0c308498fea6b5581a5a986ae0f32d0a7b598c512cd1355ad0d79082abe2003a82eda0ecfd5027181ffa20d36a9f20acc3f50b5861fea2fb49389b1999c3050bcd872395f41390c18196ec4248de3c2906f95839adacd08ab1a4a2669e89b99fc442d2d95795ce0541692d6d36250b49", .None}, + {.Sqr, "-85cb44423078c7b74ee9790f301bdda19ebea4c81c93a8864d730b855ac8840f7fddfc8a612a8e9bc841149070925ff17f6782f09f6899f367450b6ad5f1f33084ccbbf24214e7476cc24078621a155ff344ab9262f33b2d052484033143a5c7fc050c1492af3b5bd876efd610646fff1fb662ea5af74fce9abab7ce34cef76df886e9df13faa3875e455e7ac4d387d660146090a5c9bd12c22bb5e11d22b7dc36fcc041c856476429dd958cba997788c220eb7d135a3c0b0b585e8e37e7126f26a01525ba0692db8cb0d10b820c2b8cb4bea1551d532290e2f4b865d0c7fde05b4deebc5c5c363fb44328ef4446add61a7807c6587ca2b7110090afe726920433aa452da2818ceeb8a0d20d56fdf1b4cae4e1ee2a985d6fb331e1b795921ed489206c8626b9a68be46679cfda4ba4489ce8dd94b58817af366f340634b8795aee1b1a74b7510033e62cc8a394b52b9f63c731744414462a715d5447544a11aff038bfbb0cb5da09277df9f1de92ac9e810fd6f9cd3507f5bf1002fd3509ccc25918c661014042c8f064d226e7c3e6f9094c9a01f8de29a15507a2f09f88dd0cd88a6d2e59c11198bf967e7297fd11b7edf0eb05edc385ad986cd524b02fd7c3768d273275d1871c584d1ab8a8fe501dc3ea6e258c279cfd58bf1bd901dd855294ef36407e0b348f26b4999443633c92cf6f164b8a747f2725d4de62e84e6bca", "e7e2bff5d119cbb6cf962326297267ed4796ce847f2944af711c13f7b89f9e828da748defafeb286dc6b26e3bec2fc86be6992feae9208a1752a26d2ea71f99af479197620739cc55f70da45874af65d6185abb1a2a469108d311d002737a14d4b1dac06c66d59e28842823b69cce1b7677cba980f058f1c988ac6448275280adbe219e63c4f068a9a7da1bfa67325e4f44b346b4ce2302dd28f5f0316b862bd2fe1bc3a639666bb211bde6454de467b387f27b2b7ced52f41adcdad9c717eb9f6562ce94571ff07ee1c1cc93e12b17feae406a557a195964189b218483de5908dcbd2b7365cb77f301832134a369e00ef287ca78d5f5ac2abddb20c894a7ecb3098638ed2c78276ef54bd3155c7a54a3ce8e9c1eec847a1287e0074fa0c828d7a218f5b3306396e15c39490c3584f11e9814ae45a1e7a4970ac1df24800d18fdecaabe6efb4c0f511afd9d7330af09305d869053a3df2e68666343ebfcd575ae149686100dba70fd781f0c90b17bede425375e522ac919e8a9f4331d3b2c33060275edffb60ea72f4e814d9032161e8522ce4bd898e6452d7b5eaf0c0b740b97458943e017585bf7d61b27814b789df9fd9dc77c7fca3cc9b4fd43c670e05c5f8c5ade2d011631d9f88c837ae63480963742667c99602a63fb977c72dcc743bed698b30eb643528ed1a76b848f15095e9d210fe7f5a745d80ddc096a6b74311", "45ecd652198999ee66439e611405c6171dfb55adba906231cef3d3907c9c7ee0d463b7d63267f2cf9f06fca31e284535b81695d2c0d15a7f858212062bf8a2a56116bb79622a0274173d5e9cc26f8c90abf01490632b93720a9aca28455ae46ad2487561c7bbe98124bb6f0ce10ced8b98b6354d673c82d3904f8d059f2e52167c8b4c31fc6e27c5ed867e717ca7f5c2a042b06968ad20bb58287e25a3c4729675438780b96860c66f65389e96804b8f8b9511f300cbdb9d9e2a1cdf64acd01df2423f0814043861e9806c3cb76644c15739d328a88d4528bb150fbb2d4ad7bca5dd2a171f1863899ae93871d85b85bb232b9a1a6128d9c27741432fbbeafe9d942bffe2bd67e434fd3791a4af1cb25f17b4c30ff2d14f5b7bd4305405ca01aad577cc3d44251c5842e4ac83a498b8e7bd3457d4856ca71339ec65f2bf13458b8eb3e535129d4d4ed042f04844bdfcec5c7e57eb2feca26447bb204873e84383b354f1b5325560b7fa2cd19613dfdebb13aaa5fb89dfe06f3a0dea3aafa21d9f4f01cfe8512d72a649fb81f428bae1301deef0bbb8387ddb59d6f87d3c6b59a233881d023994ac8c8f59cc9dc565d7d973234033e0b4903511b45373d4f08764af11719adc7581bead4a35e8810055ee60feac16fcb7a2a4e5771ed5d1224e1ce4edd2f9adef958efdc7c6640ad43e5a5299eea0477c58a2495f4ff1997c27b0a6c825ce9cfe1c1dcc03675f0fa90c4166e3976923795f222b2a2d37ede02186e3e998ebbe10c7f01eee9ea2e6e1f49b72fd26f98bcd942afa3ea438c5bc50bd9b9373c08443bd6d12bf069d7d7b73ea3504a8e25b2a0258436a99ded0a1046f8accfbc72a63fbdec228acdb6705f8b6e1023013ba0f27a77e2377f6a93701964ddf140173c3fafbd2393306f4dbfa17961412e28aed681c8bbe34ae45ea97836fb3104f0b7e74ebb6125d23eacb39b38eb1b590084edd8bfe952e906a30b9f106657750411843e2bc889b33913d440eec9cb9c45436e343c54ecf05ce52f2cf59d1e49cd46bb320914386094e4be3f72bb88916d3b6d35f6e6c66ecf7a202c421f7bd528d9994e64f246444e30c4c2ea2b31b18683cdb037dad941aab02710d0bae40856b22e353df09ffd7d70044af0667ee46a1d1647082b1f2d5614f8a4530dfce88cac922e20c7407d3ccd549cb22ddaae84ce459566caa465846ad5d38a660ec947d5b137454c2c4a2c0c460ffee5454b5192d3b32cd2af17ee22f578cfbdf105ef1e88c592b9f6180d5de212ed8335209130a8834c04dc5de3df696bb74489b86d084622c5c03265911f2065d47d507eb272b165e71a8d2a052acfc3be794f85fdd2bbfb6443b98ed7d77c3980364265a36a64d2dd2ba9e18efd623a92a4cda8da6af682a9cd8ec201408dccdaad6118dba0e61b59c5b1a0bfc7a7b64", .None}, + {.Sqr, "-bf938fea7864b47603d6483599f75cf4213217d4c143e84c0746ec1e34b9845d930da515956c6f9a2a930b69b06e1aa839ac90fb8e24a94385290ffe4709a10cf7585270f06fddb5451eb2dad387d3b793bc2a93e9b2836546a87f58fa6de9b7a8762ab04f0205338cc411c833ee2d6817ed883f0d660dfb6f5356aca6a7c78adad67d7c3abc2a4e4e7c45900f57021638ff9f3ff75e96f66179cb36748e549a7590259b75454b200a7837fb67b513b7ebcd8592c343862c533b5f9467c7cb11f00049663516899123fe4e6faf1baf91c4ca8df1712ecb704e0196054f4d1a2003dc429a5f0ed3775aadc9dcddfb50b61a6e552192836164b6f6a94faf8515b99168aa3cadbee8f7d3999e5277319853cc4450d3a1d58658d7889c2961530d1639cbaa9f88f5ddc8c7d4f1172487f965c58a2956ab576956755a4c4ad9530f35b95d22bdd4cccbe49d41f06d670fc75a2481d032be6e31f75472cb2ce77f76ac24b73e8c3e0c0b4d149c4b07e7eaeab4b407573bcbf43eb74a14d6ae9d3a4c92dbe66df132dede981b0fae46ac1cdb5ea1e10e26e0274829bd661800328dc3a91ef809fc6d904342e0e94eff2ebda43dc2678637508012b089edfae4d35102d511d4d80880281745ad3670dd3a02752259fa407320e215d35c17c9e5d7adb93b03e80447f5dee1968a2f08536ebd2c075ee753c42d5d704edbb1c938a2f6a58e", "67e4a601bf3544eb62832f90cf5235d3d5149fe267a173bd66b007e2e424abb08ff4c86679d53786a62dbd328b164faa0a101c74e2d7c5759319fe1f41f591b91af92d76d02d0cdd4c9b1f22668ee6c186f31ee604653f7b3991bd1e7bdfd385b0bb5ee1182d5b6b4431acf429cf61ecbe604fb9b9d7904d97fdc6a6b73930474856aed8ac942e7ecdb6dcba51d960008d22178239fa754ad842831e4eb7b189f5cf97c96c4d9ba0fcdb36cbd7a9620b9af77ab04256e2b4185f17a1203bd3afa95287b9dd218534817ebb7b135c43b2eb8db502871653249500c902d0c25b2c677bd6d16ffa1b221f2d7df8386c5afb635d7e21f35dae2e86609ccde3d0e40d339a01f58f75357318661f39a379278c034bf65218390b075589a7dff3a4471599415f7556485ae093dbc17e36d7a86f0500765c2fb31bab2354dbdd9d4d8bd211705f58f4cf6d82dceb4932b9b3c7a9396bdea0a93a0c1f2fb9805eaa4a85a0ef8444d72bb532a13db7efcab1af6567a2057fd7c5bb2910af61dcbcb2f25faadc4effa716c63cdc010ab337d28fb1dfa2e3c6be2696ce46fc10ab350b1851517be93c902e346f76a707475b32e12f97e19bdd0139a84d3fca4e128f37ab65005f3362730f1420c28e0d94bb87720cd4c7717ba87f92fa0a45abe76568b42df73bd76ee96679e416028be98f02104f9d8708aafae45cdcb71dd174a3a5fd0b29", "8f5d85ce77d452302b9678ab70b7e1b0655265dad51dd641e92bb1d6433293627cec372f66271093f43d6a93f188b7bf42588e2a0b8b4134da045ac4e6c5d815b96745e6fbe1e8449790cb53173bf439a270f3d626122249ede8b1dde58ede4df419cc8072cf04e315e703e6afc5a7eb774753e212cadb048f7fd7a20b6383776ef89d92000568012ddf271b51384af2cd4a846f69661958d06b7747846e3b2d5ba6aa37863bc512274e3f613b99cba84bdcc0aa9e50beee9e134e6ec22153a0ec5e85cdb148abd4e8740282f3beab775660129a07eb6e6b455a0780e715ec5e2d150491c6435740b73c4ff00e4b0e0e2ea143901a93880e1ea5da522baf87710165c5414331e1d6fca0745691b1ddaef311cd8aabf7879c33dfd090ca541360ce7f75f61695a6c37e5a8ff9e24c4e84840edc24803093ee56ac81ae85a7c9f7f3801bd8faebfe4f12f0c0e61578b08bf4446bee61d6dfc1a50305abb034b6987af34e9a9501c0078f2cbd81863060fe33e25d59e3c43344d87fbb00b2fa5eb0a739dfdfcaa95a9552ec70ccd42202a948cab43cca9033ade9b28ddf54d6e3073965dd9abda412c36f89988c0c5dc0462619815b695bafa91099c4624e9b471f1cd6ce5e918ca555f4825be74dd6dc63f6c85dc8aab9c77b8be77ce0675fc0326f823f9fd6aea77a869494d18173d55188121c12d6048982f74449d53b6c03590cc6e3b007114882f53007ae08ed637bbcc1e8e9c380f3df515f53a44fba3d91dc413078c4160c3ad338d719b52f1f8686c9e30246aec572fa5dc5d7d29ff6fd985d4cf7bfffb8e3c0a35a6e521f8fa4867d8e0a83e82566dfeff7c1411b53cbc348143458c0afa6e8744a9d27d750fa01c4694169ba9ebcb13b38777ceea22d4321a816de9325fbe12d8ce0ec9ec7aa40fe3e721a74c840c0a7e995714c9b74d71f93242dd656a43d297f0d59152ee555955b6cec88bb32ba5b7de1069ca91c4602cdc286cfba0d0e887a9df176297589a4a00c55a602cdc6080c4c6426be022354bcf669acc0df50fc4fae1bec9ccb9ebab83236beaa182ce83b23d388066afd0d3cd4c4e532269335f78e9fd17a135cf31d429e0f4ff445a89304a27e972eb2a214cfea2c5443cb18ac56a119d69da02116077d87dc30afcb452743de8f0b3062d3e40cdc08346c4796a93ce1efc99aff2047a267d601a502353115f569b4f06d5582d9a42810a7ca26e3ff7bb7fac1dc6720cafc17b3195e8ae9a9c932068008c89762b6f11dc544e70dc052d2a88599ccaebdc3eaa8ac1d88b973b60af31bf1039299b8dee431e88ee2eda0a63f29f3cf9061dc85984c6060374b37d369eb1ce742792625b4beada7013bf01b647e13f2d5482fdd0b08fa5aef18a712ce804476b286671a7e90956b131e79294cd0ae89b219a27748e5fa814a4ff85ac4", .None}, + {.Sqr, "97577f7886012d4018b2e90cd3e36f753adf55ebb46c9bda7c3b817d91e7b71f460ad0d36183de1b687f3be560373525d74ab2a54b06f8cbc03c64d6d86607b6d0e20c166dc32c2a6680be357e603b4210dfd29436ad85220aaab6ff022fa4dad66e635da8661d309c6d7ffae358ebb2d201be813429187f8b65a21d77b21d01863b4b5d6188de0023458964d05b3b3ae3822b79cd6e585ff587f0a56cd6fbcb247b02612ace6144745f08d9ff764db118d3a09b9818089fceeea816005676e80ffc43fc76e1c8172649d693e4e100055cd940e73acc3c4268e985470b32b08fdea43410cb8e152753eb52d0a6843d4ab8324de41a7a67c7c699874e96d5669eaee1cd7271df5e4f2445a0f1bfd58718316fe80c6349484e758e3fb0ab8e96fdfd02fdd48b8bbdeb3fdc4318bc42aea265fe26e3161caa3ee8d09d7ecff92e2ece32bbba4b711bb72356c00fd79d438c1fbea5b3c313f68a24a439e1f74eed3693495e7cab32a4220fd3ede0a5e8800c84275b4c889215bf6684597156f04bb86d0cbd1d88b1552fa3076b982daffa0c184b5fb794d0b78e8766010fed3aaeaebb18e26a5df8b89e8de25b120f34b2a5b7f6abe0a3884ffea9ad02332ea1ef7016b80a82149681e0381e293a0802f320ff071992dd72674baf2bc75a837c1d3c30a37855863739ba81cc1ce40bd98fb11b4e94633800b167bcfc50bd33a47e2c", "80ab320cdc91e7fd6c00e9dd4231f5ae17013ca2b562a9c1c8bd550ca04a4ed71542cc498b6f3a87d61b7b4678908de45694fd15842fc9f36a626e86d0eb4709f8870e0a7217e62a6bfe4feedcb0a7d3c642608b97e90b02e20c15badc26acc6098876b16328f3b439b3d652c82681d1e3f57b82215d5ea1b9a5daf506a583e540aa14e312a0bcf96ff40536eb2af076e7fffc59136dd3c580cbeaaca7e5e46b13103abf1827977d5ccd6ae24311ac9155ec687f55925f372b5079d57a3d8ccab5080d194976b996e1f6ea3f53c00fe5ea70cfe3f172b722b299f740a24b434124d3fb5c2b9fb420753881c23936133bad091af933322648ce7556ecc5bcf4ac2d37aeb50e8b5c0e993c72171751c0607b3aca9d89e07fea0411ecf787dd01b5fc4a4524e6474e5cd25238584c397198c482ee597f5dfc37d3ae8e7003b71d3b19a21cc9c6c7bc94459a3e1d2d5878abb8b6e8ab0fd7ef05fdf2cc29a359d372abe3aeb3c15ff1504efabbba7aa3d64e5dcb2b5398341823a7487e0da7e84782743724c2e7f4f13969d8543232de0e5582ec884340fdd5abe9f5208db2d926035dcb8c7e0274cdaef823b145d4c7c632e2da5b250c79744d1a473eb40e3d5955ad9ff37a2c37b662129f9920260d1008942af05cfb3b23e19cde1e0089b8f593d56ac1152bcb0cf7ef98d2e7e393972f1e55b9ec7f3461e6e53d531d19d7621d", "59785648117945e170d91880affe9e6edca11b920eda08317dc2c137d504522d546fd2f9210b168e7b071dfb2ab351435d287e25b71096379eeba28976590b7fe7bfff18f741c35d0a80afa6919c75daa6367d4118560cd75f7ea73ad7c68e408437848283d2a1fda3fb7cf9aa9892fdbe26b2bc87c2241763982f42f4fb52a833524eab8cfa79c110b9ef4b702dbda0f20e9bc771d98119b5282125622d27dbcc6d9ee814faf0eb4dd90acde6c6b5ed47172b4f4739bbde05d32181c0b734cba7697986493bcf2c6c66cca4c6fcc80817538bc7b5a1e4031145214452c456dbaaa07667b6bf33936f5f2443fcc13628c14b84ffa3157bec44b472961895ddd5c06f9288278807b070fdda7d919dbd633a9318398aa0de4dc23ccbd9b5c44cc43403b075ec64e61e10ea5dd76c0e542c9d42411e093baebf52d5160b62f99a8641773b2a31b1338a675bca6b192d884b5e32106e9308db3db58d101e8a3ee0024849acf66e29398456b1dab6c5fb3dc2e598787028e8e20aaa16860fa5cdfd7ba77a2aea6e49201c1108a3d358c6e3c1907d4b2a6c00d60e4ba3470fc8b5e4cb9c5a73a3b31ddd10d88f32b8e43c5fcd968aebf913f4527cfec036416a183edbc010da4e4903000c5f98204eb559fd9648da33983a48dd69460f47b300487d47dc4c05d45c4612f128e1be44df83f130bd3b06155d2647ec6a85bec5d27f327561a22a639099f67ef7598f215e610ac4fbec7e183d126e3c293461762710339a3cf70a0e72a77ebb6c1c6da4c8bbc31820517d9e5706958024eabf9919060796f7ede5b93c6796b1000e3f71305ed9e48645930d4096536098e8a45e1f1602f3579d8a7ea30284aef62de56dd4d5e4f5cdf4989332a737321334be2b84e23f931e9734ad1eebb4288334f6bf525e09c28b85a21fa233340655f6b80391779bafb0aead157a9c744720cb3d3d3b0e10734b9dbd942a311ba1eb05b0d79be9d43d42bb505a40933dcf3a0883ac928490207b276dab05c817c39582cd9956e46c3f09aea2072c7830006fbc4e223d8f19b64090150d2dd5b868a2d5eb063eb2689ae442e89d8d194dc09d1292f17777facba0e7322fcaa8048a4f2c6b69882d58e1b10d26e6444882cf8e5b48cdd2e0b78fc7368f5cf9196c6572429eca76dc73b7bee76dae355b26b3423bece3e9cd225bd35cbdd260d6a9b3d2dc50b2f6931a40ec75a606afd303a4c831294b267d2b63dd9491bce89d5c26badb3bc0f74d4b9b4537bc6b616249dfaa78037d19346b2a6174d47f1b9212bc410a33d28190707d505f1450477bc1bf29e6fe08f92c892f94c754848811ca741414ac86dd2a7161902ad8667f3c590c67ba6809b6666c23db32f5a176be171559e0fa0f848b3f3143b7e525545aa7e4e804ec8fbf54026f9ab6962936a470ad20c8c0ef6e8f5790", .None}, + {.Sqr, "-75959395c06794b591c23a06544d45e2b8c9e7e71cee565175f61553f18e9ac7ff6540042df84add3359a28e2d9d6e7c86649f8dc481f9cdd3a48d2f994140b4ad6814f7d5c989a152ae278e184f51347dc2ce650573cd56e0f5c9b498ac9419b21095aaf3728f5985bde4abb36f9782741cb2e290af588691d6ecc02e8e29d30b437416e02ad42e5bd7b778b222c0349ec1be3851274c9ad41ad1c4bd371b06971f414375e364e2a732f53038ba11630eecf7883925f96ad4040eefedb4504ae6578e8f21b869ea85603ebb175ca4cab4b578060d76935a2a9186a497fe193b0097e4c80e4d4a361eb5e932e59f719e319fe4712ee5a8ce67396c238bbc7b9fc0969647d344f5bf3f5fdff89dffb1edce5fcc7c25f3cafe9f1e9315e21816a6018c484a2f629a0eb3c86ca6f33e78068d629a765f831e4bde33da683e4198e4481bbda4c2c5aa2b5e62d78f36cb6a059c1c022479aa96d0e56dade7ede9bb002b34fffe34f160d8726a824a8bb7cecbc61879fb325f32afdfce15eb1ea764a22e861c751cc40c02f2b1ba63c32861ce4e32830f1b51150dd50ff6ecd2e123c69df63f1ffb63875ab52b255e03112831d618f35377b204fb28adb207aed291eb19a5b7b363db204d104f6c3f3a56d848e62b834f16385343692800bacb4014deb86b0e28010622dcbd0892804bc6f5561df21f50a21069d544ffb0618b94900b", "9b62eb97143ab7f2ed21e4433110cdbd82c276b12fa96fa5fe888486fb0c5063877ba215ddf3c2c69800162440a4a6f42895dbd9bfcb122b7db3e9001b5b81f3e3fbeeff85c8690b352ed5c342ab0df518e34a464ffc3f3462d0416c9a9aaeb2e7a7f3c765fc1a9a446d27142d759f1aed12c15db421bfa7038237a4455ce5bf300f98293c1db70f9ca6866346a39d6893a4553659a70f5d572c93f841d4e73b220c008b103f0bde8f0e429cd1b276f1330415fc644c4ffc6f00c49f92604c7905c5b6f8333953320e2a0e12168d360cab2d7a0a2054c42ebf8242523742db5d349dadac0bab608c79e41652a304cae963e517783b0a135cb9e3767f57a360357a659cab7832249236a6bc0f6d7ff0df9dec2e9f4b41879809169b1b7777a0e56b5ccceea77185e06a571c1c859f2006ceddfaf264b9ba07b9ccd52db14efaad0adc23a40876e015902c0fce82a4ec5d1c5409337cd6fcde6fcf489e7a2cda6a402d26ba4a1494ffd6d21a690f91aca813078b7ca6aa6eb743a24d6a4af766dbbc75849fd53cb1f115fb4eb48cc2493ea71cd9a9b0ab3fca76ecaac8e0df9410d0e69e766876c29f8986f556e00a193a63d267604a0a71bd3a1a6f9a1c339750a5f326b24dea7c2c65771d5e5616ae1267ac05088173937e86e204a1a0fdc94f6f39f5fef95387c2e1a8a3e67fabe71c26384a979ddddc453dbeae9f425c3638", "3602104c0345f911908e5edb6a48a6a7a95019aa38c599d2323dd208f51e29359ed06e188751b23deddde92af43c376531a41819527d0b32d181887a4c74f3942a644dc2204021ee8790a089a0709be33816e207260b9f1a10c0a40caf5ae6cf6e12595a881f315198bc090521a2f917b4788d32b3a2147ada5abf372edf8d3caf292450668865d40b8064a439360bebbd9cd62ce8d0bfb49dd7092085c2e95d9696789c9e46d8f1bc5be3f64e3254a6fe97b7d37995d9f0849ce8e3886e8820df3791f7645f5bd02498e34fcb956cc58f6fe225d9b001e373723828c57f32bbd3191881cf28b71c9018fa07fde01e3ddb32758d27290fd7d3459ad7bffdb259b9ed6205e2109552b212558a70d56784b7f8f74f3ffb537ab3634d4b2622587c98d471a4ae4cc3a475c440ec2cfc500c571b4dababd30dc76162a840e042181e8b1204b387ddd33a1d36686c39712b6fa5d28419e45af23ef75cfefacac0c238b1b283c3719cfcc835d4febf7579f60b9816e47de17f474452c9bd327d819d137597a31381a753e96d1478733baca5682ab419020d5bbd650806d3d1a41f0b1ff656cbccaf6328d13a4ef28df3e8e7961cc728bdcfa1c3a550f807cbdbefe39cba473c1b3ea3313588e4649f12e24dbb1b5e15ab2502905f8323d9a2da7fb4906eb763e72b200d751172f0f4f0d0b58572c29b5bb229ea6adffcbffa0c25b644ba035f08852e7112d5dced6321119dfde8282002fa3e97768a4e09efb11ffb70dc7fc653f968fa6338443c84b551467016c0d5c20e028eb85eebb0801c2fe69c6f853e1cd03b6c31e1a51ca6e6acfd4727390a2ae2cf78ffd17426f506fdd5ebf50fb4c102833cde57d443de03bf1b2e9c1322a4b5739038385c7743e9da389ed520d92bfbe3e3828d2a3131b9d3caba7839715bbcb171e141cd72cfa0c6e6dda116cc6e4f5d5e7eed5d57389bb97fcfc900001e3f82d21731fb719e9be2c69a0d8243a562452bf6804ccb8d73c5a7851fc3e724807c73351c7014af068870a4c50359437690247e12b3761fec82a89b457b025b37f3db935d6bc3c7c21977888b29fd8826c7bf5587e74cde0fc0f05845a2a78c70ee648d463263c7e34c89e61416152221e2d26ca684d5f142c6cb4a5cfb3cb31d91e16b636027534b19d9f3a3de33627b990b7b06ca81c55da80936d1c9afc0f6b5ff31236232b6b50c888cfa21b563d3ac21ae66c58b5ac313895bb5301ac8ed1d2c9c90651724f6ef44e78870894fb0c56de5ac0386fd69702f5ee65d10d28d553ee0e8373ff05ba77453676f1bd625520efae9b07e0c6156ab7bb080534e8debbd0183b501165a132987f17dbcf437648dcbee9c2be5afb0f1deeed337ea9c2dd21808fb966f81f7244731805e845e1cd7841cf3b84956d81f232e2685a6bec1fbe226a8f2f8cfc46079", .None}, + {.Sqr, "-6f87096a80332a42f89bc1216473aae70163eec61a48a3fb9cf9ea06509256ec2a8a04d9ef15e5d68763791b7dda185bec2caca90c98189d19706bd07afba528a114be2a0f6a4e78ba83e596a6d32e76c9f1a8183194b4b93082a82f2772e1d81fc3368e66785549bdd41f3eb39d10b05472b15bf611d1d79d6b7362129787be39036892de144141d5b127ee61b25a20f29d1a16d741c390d2da089b8a3904f958380793ed406cfd9edfbb98595cf628648a685b6fdff4a01767420878c1f8908f05ff3b28acb81d8833da15ad9f4498bc294153e49d45f366b9001f995f836c92134ab3525b6e913b1367a6623f085ebf3864ca6e4b928ae06aa3904729ee36449b52c49e24b3448e99765bf0fbdb38595ef61e83c57822ffdea860f98cc10aad01e900fa62a6dafcdb1d23833eb1fee52cafa5c2a22fb5452c33bb2fac9ff6017825a361525b6d9457d7b57f7917cae0b893dd467b02b474795fecf315563c5b025ce68fc8bb2f66155f4ce4df9b6181db9227a59863bab9e71dc6223291efb5d051fe7e890bfd7bd41779160d0c3369bf1eacf9f4a77517e1cab4216a3b120d6a1e71451dea771d59c157541a27d40a86cf67f1a2bf510aa82abe7873db7d1b6b1910fd65676e0defd2ed98eec6b6cb335975e5e2662d8c0fbdfd68ca193132d9bb26d6f1d948fff744267af583707b62e75276be506fa6164a6e193e976d", "3c6dd14e97d147aa9427c114e2bef7595056a4eb60fd1f0f68567a58069d1ef8abb1b0444d06dcdbaf5761c3e204f495ca4c5d843c814f50239e64954035a1e6938684c3c6927d0159f4b06b9bfcd117a0cc6780c660d0b465b3f21d94b1218fa666c485e5254126fc7538ed3e1ea9df2cefd61b4f359b119072ba33bf0a6bde53e385ef748a23ce2ff5c26c2388e5c198a14c80a91b4d937b930ec69ae3717d854784209b2a1a70f6c24e0d884cc633ca3482e37d518ba6097f19400301369440652b342153f545f4a4ce4ac051c1f152052a40b72863bc49b04497076a027994bedf0da47272ccf27b8177e76adb9f55b8fe602b8fa0f45a8d1ad48fd58f91cf10df1787edbaf90e02946de744fe13f683b39c492bbc007af0abb9ef05da0ff87ed948bc69a96eb2f45984e9ee26a0c09221ea7915dab453fb2c7fffc94a4e83eacde4e9b12240407a1be9c698738d6c3afc90f7a716ceca298f1c30132837a2d58572232a9dd32fa79737d3a5a47c60e16455be1e9ecf674e4b8ccdd7243e1732e70bc7ebf6c4348253d306962b72b31ceaae9b30e2221364b972f7b458c4e86c8afbd591bbab69d7c23674a9346fd3cc1fa11eaaffac7a50238b55bee4d81d94d68c559c42dcdb31f1fb99c57db2c5976f0f43af6df989dad2b94cfecd22d99172096e661f8fe5b8c0be6960c1f06ad3768114f5222fe8ab2227411a8c50", "3096616549d83deea9c42f2e51296332798445fac92fe5e2bfa140b1abc37877e4d0998c3932f592401637fb21476e4ea78ec646dac3d773b4e3c6243101a0e047b25b6265df4fb417ee9d3e811cf3106fe4b08772945d42d902efb227a510d3379fffdb71c600b65e48d602750f7b9eedd6db9ad18b2299526f0d04df837deb4c57ab9ad5b3ec0dd81ca185d90333a75b1007f9fe454a701d1c6588b9fde88695e06b8b9517efb89c30a8d1e9dcb488650291ecc637aba5577045fdb03a3085fed5e86c40eb2be2bff37febd99e489e2f2906d35f8d15de602b65cc95bb30b0df52a124c761904c4148546d5c00881dfc85c30a57c32bb864b320940ece4d584ec51eb78b2a506fac8e6f4c782378e8cee74c2c477d57106d9b6ad3af8ac8b6835ab45cb5d29936aebe03e6d71596c75403c64e55c3d4332ebb6954fe5a6b99bea6f6608627378f96a4c2c28f81794d43febc6c6bac4f9856042011080e2c5c7c31e709b6469c39e27f3edf365be6130739576a4de3012f0160faeaaa3a403e7423546fb28d30a3dd9e45fa52ab5a8077afbeaef97b224f3e42f286c67ee678da758d5bc29836c8abad8630e24e4d6afe7b61a7da4de8907ae82ecbfc72037089d37c19279cbb8e9d44ef0d6475bc966d545a29e26b65f6e419aff81cde771a710aede77b3b14e69cf42fbb0b3f6bbe4b47fd79e4561d4da5b702d866dda849a788b1bad9f1b96a688fcc3e98b60142f34850393a84089af8ffebdb622462a90bcecaca523f14a98069d245d20873611d456e7ad62d70d04e6f8491bdd79b46bad60e68212d230e9fca51cf86e2d5760366773016a9b3db1e00bff579a7f183db5fc94daafa166fcd24e1967978107a8b1cc2d5621d325b766bf66742ca5b666edad06f38aa024527be597bba8559a7f5e7d0e70015ec26f06a6cb0dcc4f82e40dfbf276d736d8718cfe30701d3519f0768c0a06da2c4f3bf7179601f60cd582abc2bc306d8214dd9bd319e110b753c8d80192227d244d5d8a77966e7e564ab0a4c8524e7911320dac76051252b6b14c7a6bb619c1dadfe53f515f1a569e487e5097253acfaaeb9c1ee4ef4a858c15a22d91858c55382768ca22aaf2e54c1928f675c2f59361adc12eae4b24ccfb2c8a79aeee02964f6d6fbeae972ee3780fd11181c1265ee12a024e6a098b2e8726377180b46b38e7cbe85000c8bce1b42eab3659f41e5896cb6253b6b4715c21f5db9a305e350400466c4927615ecc2fc360dc37ca8cc299b11dfe67a511ba967535ad1ef4a384af4e8f2c6e41cb004063502f7b1754e85179b84c3473a92425cd95cd2ea3c495cf36d8e661fec3cc106675399ea16210816d8f3d508ea31459b0efa5a44a96527f326c3ccb6d9eb0d75e06e24a7e3fb2b790041143e25b5a4f5192b212a0dee04c99b468e6e8cfc5dc469", .None}, + {.Sqr, "-9ce48078a32a1eaed03eb3db7ccc5df602a8ae9780cd7d129a872f0972696df30e4ef15285144f44f87bf673c279263dbbeaed716f14d0f17aacec0fafea4bf9335b1612fa858108f7e93e46c564efecc83f1af074242b8a6987a485a023b80a944c6668d960b23081c7caa5bb26ca64d5818606eede45f14f259df4ad69092e78a7110bf8b1e357187e7dbc1dd6ea973586343c3fca88202cea5c0b5d9540440cfc13ee91aaa94fea7e83b825e428df5f411bb94786601aef3a4fde033f34a6fac070d3be1b6672e8e7664f5e6aa9b44f7ee3bdb856815ff3d934e983b3b7abf819dd7c2199bd4c0c504dd41b84bf05a875c3ab55bf142cdfd2b6eee50571f436f8f9d2becb9ce87e320020072071b4bf34bd7afb13b31fabc6dfce2b0d6a966601e14215d998dcfada8adaad88f1390b02865797f5c8fc36c035a5d90b344815e193ab055d23fe786f2e92b834e4508ee86017d486ec9cb4440c7a4ef393078ba843e080d3dd8dd41531006c46fd4b3f9536f5df47532314979a3dd3911887636fce70e7bb4f2f7faed9e2c0054cc6e1495d68533bf16da939f3192b83e9596ffd91c59620f334381235587a6f219def51b23f43bffe72c05646170a6beb03b282a8917de1f8eadcf5cdecc9e4c93f6b25e245d614c6ca09757aea4ac50bbf2eafedcb35afbb4678fe8145498952fc907e8e149a328573a10b42f5f10806a3", "563c8913bad660a58253a3141cb5b18b4dde0b97fb310573e399011c2ab38b9690639f1f6be0318a3b464bb4c4b11676fe8574e716ba2c46639f60476d4553c6b19d0a9ac83d3c750599ac8cddad3081a7038ec4d062a44e330010aa1d5d503fc612cb8f6b85c2572f8dc45703294f9d6775a2e1b7d3cf18b7e95287e339bc1c75122dd844b963ce4ece43bdb9dfb3000c6b4077743018febf1c23738e342b74a8932f5e90d8c503dd8588f938609643b1ec0e5a4efa90dc9f9ace81b7b28b04dc97fbd7e44f703974b0db055a1415d83e1156f90cdecd0cc9c5ae63b72ac3319396a3b52dc69207c61ba138a773d11e7d3b71923be356a1ee8eb5a01249afda34deafd4ab671127ea669e836281143786cd8f8c33812bdb82942a1f2b2ae374a5a55d098a953a582dbb8e0ce0c5805da8394d7b4540096fe7b3f17ffa1de5f50925bfc530560e3f7364e91ae0086e2ab2f7b2026ba3041890466fb121c4700de6b606c301b395b67bcc05bae334fba852aa7f1ee4e217bb6ddff559cc6d1c946304140bc220d17ce8e400594e15823ce575483f9f74e86a8a5eb788707e62bd79b461c059a1580972bac7c890c0946fa0fe012dc49a928c07b104400615e0a0c7de0ba97b9128630f69de08bf4f39f5990365538ee884c8ef9fc5ce09cdbd206eec2b7c2289615fa352555e1cf2c97e22cbfb09904ad59face841b5cd846c19", "602748881e36d46f335999067fed16e784bb807ebefd5666e6857524be2a454136a95a4c5e36558c437cc38da2a9198931d5d0e648063cb6089cf8386fd59189e3a94acdbc44e404c3fb6690a048545e77e4a9b09cc9c2e5724b1e1930c1fae3637e8678f9a9ac05a26df427158d1021244902ca8aa55bc5fd956557dc41e1923681318ebfdd9bab87adb4316e65eee1490216cd8cfb5e6d345127cb16556e81cd4711ed3bf101b42cc2cc24c135aa29522b560b510baf563ed78af0d0f097e49852b73a1f08650d9095f51329a13a6532300bd7519c19c9ee7959735db4aa789d9b5b139198c032b79c412d5933b687a931ae081c343f1f213c6ec6cd8441d450971ecd68c3700067814622e0ac8ce29f02f6a21a66998d5701b034b29cecd3f809a374554c022ecf50261f8ab7f1c3d3731c77453344bbd5791db476c15825da93f6f84e93d21d8b02a572636c134d776d15215cf9f494f25bbae043be4e9ce8f3a28b3eb66a0275566bef3c0cbe13d6695ca532b4ac5d9662bb51bf33ed1d096afa083a77ec8761dd794374fd5babc44816a802f7a7daaef7d92050904bb3136bffd5ad23aee3d89ecf9bb044d9005907501483746e4898fb3df5d3807d80ba5ba15ae03573cba9fa6ff1ecd1848f62c175d24352d1c8e9f2d568241d2e12248c752b6a95555b0761d2c34ae076f3bbcae9bf4fdfe9b9ae5fd3950c81499f60c904d59fcbe0a3afd2e466f5d1a42d0c155a5dd397bfb2f03fc510e0ac47d95e2d94fbb69e3c0b98af10317f79302b01e9704750a8d6b4593fb4b2875cf4289ad9b14427c877e0e87f63f1a0135da52ed1cf781fc1ac26ddbec6e132b9d2a84b72360a556dc9d55c6469cb2868b67b1a1e04a798256fb7826a4a91bcfc0b1c7d36f3d8d06cb7229f947076197cc0e570a8acad58860c4a1f1ff1957ebf45185e1fcf855ec89f5595c4045dc1cd95d3809d03e766a0edbe4307879d5bb00fdb4bd605abade154a595644d23d30c6a9a90a1ec0829af6120ed6683707ddbeb8e26739435add37f994b60d94a515f16651c85d1e17fe3babb6a8b40b18db822a22450af4a7dd12e37f317c58c20521c281cd8cd53324d888ecab4d55fe19b405d5c7c7c7776a86105d3aa04a47b2fa57494189fb633003affd01506a4a602dec001958b8b32c680bb80dd7c18a53cbea06db3a5c1e3648ea155212bb01734f8b794ff19a9a92467ef4c587afd1dc5ef3dfba7f61adff138ba118876245e1f2ed72fb5a881ff928c179f96f06e486b17dc980fbb2b4efb19e2056285d15d65b17940e86eeba9eb8496c33c0f9f6e4637267ddc4d8617b3d45b4da08ed1b2890386b643c229b2225a8bd5d88b453366653577783bca67061841b1d1e6de1df8f4a59fc91a8bc7aaa06c280cf085824ee49e50228cb7c399e00af7badcbd505c0bc9", .None}, + {.Sqr, "d214568f8b526047fe1b76f10901b1ba0780e9e91dc02f9ea3c25639593ad890d1a31bf2dda4c22f5443b468f1c10eae997755c85d373031d42c7220c2928069510b872ea9d4f806a37ddd0c4e4c56bbef7886741a34a6a4a89115a579f46052422c775f3046a08de7de930c07282daebcca3f17d0c6ee2d871ae3c6b48f4b0dfde98dde9446b728ff010eb8f1182cdc91f20a1d9282d0246d627384e46bffef2f865597caaa6e3c2430e2c444826fb4d584bb15c6b59fc9d44b761f8cf3cf132656a5c5cbdbe8cd9a7cd8de0dfc39a157065871945be537b8e0c20911e8c7584c720b1658c3b797ae0bd9f7b2742b4817b827d7d55dd6cfb3da88f9aaa01ac47654587bc0c317b898690e214b791e60f355f01b34b9b544f2e4894b7be051241ff6974fe7bfa8d3dbe8877533ab25599615814ef88289923c90019d71c23ec86f03d5a8164583edc47af92801314a2665550b387bb67b54ded57659b9d0131f646b2dea6705991cce0a5cb289b05fe79729c41fd77ec99c54d2a90bf397c0fdeafc5a51e39a4c4209d48720a2139f3b345c4e44a44054dc971f9fab7ed6d1de727a9282fdf3f1057f763d0b3357e74a1cbde45f28deacaf5f8a60123f569599009458394d3ea0163acf0915f3857e1a7964dfab170e17a915fab88249146331cb6d921bd0865836bfcdfd68e147e43ade905600cfadce898728999db2b79ba7", "b538f8ead1a00039a271327f3108194c52e791ae8f56443e38cb6447b76bca3a496c83316646dff4693224c4cc2b8987d0f0d238f7ca3ffc9fafe0bf9911f2c1a88fb086c7fbced45a25adfdccb87a30058d46d35ab69ff7bae81422d5fe30e4b3ad4b1af1416e60c89851512b30661ae45215d2a172492caff3522622d5004e1ec7db1fa1d0bca4ce50c19ad8e0340011325d44e657a1e55043565e34ed98b882bf0f6b5d3c7615692ca08bb7d42036543b8c56b8261168a79c494b443b7639029380143e56bc46579a7b4bff0e60e8af425634d855a79181a58f45d8fc112c4ad7cf1c0d3cf76f0cc5b2fac4ea7ba949cd13c8c8fbce8b830fdba3de194188bb9e711618ae89aae8f6b8ab5fc7b472eb0847ae5c618ac083071c23293c0936f84d3c30d82fe56f004e480eac6b6fd26585372b556a3d84c2c016177eea9b83adab9f64be78669e0f6d5977154209ea7e8fa26ccc5bde38195fe1d1dd4862482ae94042e5e2b6fad9edabb9d99e4b96387eed70a90afe3afc5c356b96a7c2f6f0ca6607d9dbf4f3e1e7f01104d3334bda6402bffadf19bdf278183a1e06293d5848d75fbb2ed2a38bf4437bfd8859043b4853640bd6140abcb58f92c3d65af10d52a75e9cba0f58458b1bb8b1666254fed0cef44975c5e121841b84277b54bc4d564fa5b9efe6fad4c444d53920278ae611dda2aab8011efd8c7a8239424205", "ac655fa12445aced72af41a65f4fb2c3a78b1648bff32846143930935a1b89da2cffe5c7b8f8412492cd129cba5ca6e76af40632c2ee67fa0acda1c4daad5944d671b7315185315d01fb5c0b451b62fa162105174b09bb71163cc9437d19884875a4c25cf930a02a0053d6c9cab7fae588f88382217175053455b92a84b37e4b87b3c9133028b5e76e8ded9c71d8a62c38ec0b560a237d694d3eb76cda5a851da5255b74db2202615fc8beb66fc9716ee40486af25ac6e79c077200ee1970b89a285f377b80b84ccbc25f3c2384e109222adf1c05fb4c26c77854d5e8369befd2b4d47e32e182213c79d916ede0595ec8b4f69b5f77f9d5ce7d77f4a331ce41441b760d299ada0f91dced7110d8604f46f6841331ed386279f11bb2ae7ef15be1eb526958c36105e825481b36fbe17e9e84d87815888be9537daffad7e27d64660b2aa838e7107181825046db68df0d620374c1ca5d7ea78870b00d0d9e146591245f0207ee30eca8d325db54f27e1850da90696fea24ec65965e507913d8f5d6095ce7b15f47f6f908781f157e103d26a05e09d89ea7d117f297d35dfaa47779a44e60acf56c345337b37a637d926270c57b274be73c70481dc4c4797c4e3810d8ee1a07448b4d1717d60efa96011354f927c7d37d4f46a7a5dec398db871e0b32c441765477445f4a03d5106c339608ce034d9a08931bd674afca05f0e8ade2c0f3ddb2bf50349783ffd119c2fe1e62009946eeb2a8128df73f237eee6f1797ab77d0b7403e948c3b4f370583ad25c3f32964281b774fa9fc392a5677d80dd34b0e83f4b65a9a21dce9a963047431947b3b112d9d622c381c4a19638e62833614e7742ce01d7ef093463d8a25c730156d088bd39f2e857f7e88d51b80fa8180f92498ab075200dd9bfca64be761110046367c44e41c20b1196b62ac0d0c215eeefc455916df11f5518b3b1ae080e65882d3fe1d9f689cede51bb95f98d0cd074b42d64c369bef21757523412500da60fb91324163a70cb8404e612b915f51551528aa8f608e4afa9db4f16cd5f3e9aec20021a64a237628facd3f7968762fc87ba9cd952da5ef3a7ad0f02b452c265f17567432193530f73fff5e103a8cbb7a51960c335aeb76cfacdae2d1de8b112541409d9695cbd1b8a754e0983e236b94858bb9de435cdfa7bf8b3cce7f191031cea92cd5805a98287b432327ffb60ef2cc65a31441e8f143a473d1f59e57ffc7cb14dfb8df8ec1576f78947f45000d553632ebbbe608e3e6b1f769dd418f9180ac6bd2abe61214561977bd30463aa7c9862b65fce4e66b7791305903483abdee177c25d794b473fd93b9fb4644c9d05f5904b6a453bc5b18c55e7489e8170b681583c8fa6ff861dbd893e597903163ea5b87935a3adb90ce45459dcbcc168f80aa6bcbde8aebd0cf03660fa2365a6f1", .None}, + {.Sqr, "-f864867e824e7f547d609c3274d6688ecd878be3ce332177d90bcfaa3c47d92ac5b52d564381aaff81f0ac7fa0d4087d94d520309a876cc5442966cb5060c4aa39a2c70ef5673fcfee1479bdb26952cd69c052909c035930033dc2671c4177abe6d87841783e3aff76a4b04e7465cc93bea40f17b8477425b7100c6f77c90939a5b18fee5808ade8c5de9e1c6e35823e03cd318106d850d8babc58b8198f9beffc36bfbe1741973e1bca62282a721d5e60e722db4dac8a23252c1e9b9496e3f36deb43d024e521389710d0f4cd0a00673dbbd0e7f37fd8de55a7549edc8df737e4be4232b6d5638c867415f645445b5eb418e283ded1ddaf6c646c441cd5764dbf803863a89ecff21a946b38510e06410c077dd505c982eb4c80e2f2add9d733d869ba02536a7a72adf9e4cca3d8888ed167d70cc2f29d96e03490c54febbcafcc55d5c801ae23c06b6d434333adfc8ab02685714ba074143dbb58326216d79dd0f25ab92f2d5e6846c37b5ea0bd84606eb79850b6ead13450faa31686b1cfebbce33d6b4c4d8b38292a0331f6413708f0bfb70f5773b82d8815d8e2a1ac075ba5c2499deb2c26bdcc731dbc5a52753476fabf74d1989084ceaef87a84fff37c357b9976be2d1c452e039b54df691df293b1fbb62e508b35bb5793cb49482059f9d8025fcd34808e836217c13d97577beeb9f83792fe43a913e2fe7081e00707", "e23e1f8e48b616d044582dad3b80f4962f1a02dd91e38b29ef24436174ae089dee1bb18e55006a986db6f10ff68b75ffa8c8327cf4d6e043fe5361b4755bd4b1c4d9011fd1d33c34c982fcff42448de6856133078016a8c48608e7d50a2993864d9d908ff3167c30cebd4f09ea3cf9e22bdc840fc3a5a5ffa850468a50d821f1720a722175bb1064611f49b2d66df851afb13184fc34097798817f68f7d1630057be64b91689d4e6aaf3006f6b0afad04bc831dfc1e1609d998da004c3d9c226445be7e29224b9b11848de8459cd8823df4f31dd91fa908b243c2bb5d0ad1cad5c6fc730848d7c89d500993768a865ee69813781534eba8bcec48c6f7128674c952e8320c76c0d6d7b48073b7367f50cff89aa3564f94af3c54d849d97cf326361ba1e600360c3ee6bb46fbbf1ddc7a9a89138b313e45620a6507cd6136c446825b0e3e32b67da5ffb806d34b34c3e73d30dcc05503f3eb003c79eaff9a906c13ced24e4fd9cfcc4119f52d85d3dd1288d347ee2599f189fda14d52c25558496288db81bd1f45c0f90f9cd7ba939050d87c0806abc200b9f8d65b1563de7dfbebddccd00dfb8a0b6afdd510f0aafc35149120094000c6566c026805b04f97c451e261b6fc91f282fcae0dbbba1b815cc26732ee1604c20fb93ff180ee376b6af0af7272639971b3de02a8618ca0fb547099c576463b3e0c56296e0e0002ddb00", "f102ec0e75f692f5e1d2bdebfe90bbdca37c9f8bd4d01a77ddd6aee1826bbb0cccae1d372fa8f03949203a0294b520c7757b8daebbcc3b8e2ac1052ae0498c188dd0e9064910a5b71add27f00547eea41efeda89926b50cafd5b2e77f563f4d8afdb7fdac7842815ca938e8f42760a2bd4382b791e93a8c494a508df123951837f0e7240b25548e7d69bf22c050f1d492c4e0c82bde67f1a0cde5e2ed3d3f27f4807b667d47b22976a22e9a208a52e9749a5795e016635333a7c424f6465a0a00941b96bc8c35b8a9f0390c8848cf21388fc05c36622981345afb1e656131a13fff22f5aeb389e8741c5ac9d24b86e08409785e49cc0d80087283de87d84d937f7621530c88802418f05418f7704de6dd18812c45e75d0bfc4cd605f23233b9914ccaf9e7bdf711e1e6f355d186b1d5b198c6c5b8dce6c8f5124e424a2755381ec8a29fb702a0ebfe6bf3ec66825232268645b0df62758af9a882a9a6efe1b8fa85d811717f08691b689fe28425c13dc3ae1d04dc22204872051ddec33be2465c65176c654ad3a2e1bd0cda5018f699bf5a08ab4d990fbacabe31e4aa35d87cb1011af65b903bde547f482dc477d7cf842ab0ece186a5ab3e16fd3bd3ab2b221269a399d053820c5197569969546dde8aeab6617faaaf737a25cec0f51cc45f2d787b5de14ae1be2e02353ba05c233cd86548256008c104437b4e2483bccdd5a12695e29ee411044ac1db5e3f8c8b6575646417cc328a10fc9a610269cea8caee38b3d6cbb03e289cfb0e517cce94611615fdf5961a02ee2fe8ee25a2336540ccf5a07d6e998d7bd37fb2f9000f97642fc568bc78da70fedf0a7a23b49e9706cce0027e03777d443f7d297dfb2a5701ea74f3ee106ea347eb608c43b37e197e85e718a91ed3ecf3ad138fc45523d9f136771d0bf5311ee581ba5b91f5bcc490d4b0897df60bb7824f3c751827e79eaf90bea7fe274a6fd55b31112c6a79781118ca54da53f5418caf8a083f8330037e95dc8a3e344f14b897dfdb0453efc7653997394fb687b501bd4bfd382b52f09c774be0ddc98a4adf08c51b6cc44cd43990eb23b64b486e4bd68a2e840c39b141b1a1183781b95157d79063ce817291c1f37c779442af83362ca67d6625da3a7148ede8cc8257139d9b46677441609a64b4f10899669ee6dedbdcbc8248c876d33e07b3fe2ae2a001aa43c2eede3bac46cb630c0421e7df5c81980fc9462927ab9078b9caa14047a39bdb01b1537a09af125dfb47fe889ab8ec57f64c2e7b56987c2b3cec92b248bf1a828c4908d72c3bffb0760dd87cb2dbe0d01aa210398ce2d57e7ce775d32dcd2138e8011a9b9c3e6724826bf451199249502e2dd225313dde309bff67a38ae37dd27ab48128cb3591f26c8fd6301e4a5183146a52aff664c57d225259a2af4ffe63795415a716231", .None}, + {.Sqr, "-74823bc745a24b759f5731bc8ebdaa7a420de8e7c6f32a5e118b6a9465337ac4332bea97e8fde361c9c145b550a2514c13a77067118304775e15934b355c777773b80673e8c052485d3e747fdae7acf17de39c3ae455574caadb40b8eaa9fd570fc0e8af54d8389bfb318b8393e8631a61af42c8914039ca8c59d95cf6a6172e1e84459d878a3d7d7ddcf38a7b728bf52ee8ba02e87ff327d0343c88ea7ae1148b39854370755c945af162913eef84edf2f8089c28b7c090bffabb222cca35639f7a00adf8df8da486d3a11ca6fa6eb259d133e9773c613d071143092eec586f23bb476e8859fea9d92e111fc451eedbc20e9b5e28233c198620ad9f49dc796a9495db8be7f9e623e154706e27fd2f33d6265c1bdeb7180ed476cf3c9a6ec38d1a1214112557735496f54a2bc4f8351abfe8776d1fd191d0f326639ed9876bc9b861649c7819e257a362b00abdf1d8bfbeea20e88ffac5f8c02aa6c4d49a37eee1483676056851e5972b252d8dd9ab1bd6f2b78d1ab35610b4156146a789b0dda566beb67e386a5b455e8921593568c678dedcd714bf320b2440d8aea4aa837846403a6a26fa9c988bd8f194cbdc0e1e8f837adea75d7f19df89b41a2871f7cb19557a24d18a751841bd6b38570b92c3c45a283dacd386c006237183ca01dd8a7ef0512b6f31cc3f46787a693a2c2cd55e76ddd6e374a0ece7b5bd1816e4843b", "57d60747e60b2b0d401906474fd77c143b287c668d46cba6baec674963dde48d04ef7f80a7dd65d9adb9e8fb01827fdf9acff0aec8e4eaa03a9e7710bc1b2d1246d0a72f88e3c38151d1bbdef6c3b1bf7e58da8fab3bcd05c082e35b5d6feb5bd5fdc1d18eb463194c520a4bd6bf76dff80a025e91fd9587ee36c982b984684212bf9fb589b72ca3354ed17b5b8ab9e067828b08f1451702d7272fde1b70eaf80b15572a764a5c6e8badf917db8b604e9abe140fa92c1f22def70dc69490fb492f4b8a3d5d4820fa5605a08b79f79be4606695fd2a6d970c068b8cd886f27441db010d04ce774bba78816e8397c60d7726b1fa831eb836b27d5d7f94cc162a2a50effa2b9039b45d43a865e77a0c92fa4095e65048ca4c0cbbc1cc609f53aaff039c368827b253309d7e4d82cb8fcef41504959529c37074eccac9f3af70ce9c696ce7a89a4241724e0a8c6b7847d396a027012ea7a2ec206b611268b0f5e9798109e75839ad1086441f481f22cbdfd4d9c39b55f2d294933e0597d4d5b6c546177b0c005526135b0fce1818f7a2da84c7e70a18cf67c099f5790430d21e861bc76acab178b1b192a7696d10304628b178ccb1f9528234d68ea71adabda8c903bba37e8d580b6888b85d0f637219d55ec11f9d2d85a656db069eb1961690308eeb30402a54f35025967e365d4766985ca27417a43244c4959306bb5387304587", "3506486d5b73426d5fe745824e59e4a3ff175b2209684338375b4ace477e6495a22f2229ef498b13b1537806a3fc0862d923dbd2ec66cbfd4a05aa44c23caca61fcf8d0f622083cdfcbd6554b22f92b618434e0c32da6f283f759fadd465714a119f1b52f2acc5b8e0ad7cdd738fd94894c8d4ab599cc9c13cb9af3452df13ff37029f993788613c862c541c4e2c321b6365dce4e0a66b49417a02f3127347441365ac2b9f74aaf5e13f5a777fc9ffa974ec4f6a5d66e85186e21594de4e33e29b38333312f02cce60fee70ec59d70ca9c579e5b1e8983769b6bc69d5fa4e4fc0a467456897ff71fae86987fc6deccdf2d0b78424a92d57e2b093a2f0085332ec3a5367f62739e679d7cc22998f4df7dc13e81564414c8cef0e355bea3156630fa183008a7cb096a57dc7e67947d79a658a06be8f323ad9e516551e813bb6217a37872fa85ce213b66897b567aee315c8957c977c76b08736f123bcf5cb3b2fe9bf72b6da549b9f8d21376b9ef1e8e758edd212040d29c5a60e96cb3947169a4d17cd21977cd93207c4c81478e0ef47a05eedf4f270fc32b5e8c9a3de6719e8fcfc77f9ce5a213e7276dbe661bce5ba91070227548e47292cb8e51135ddb10618b0f421c6aa23e3eb824f6be57cb3874d570e973869eecd925c5caaf21878fe425c76f2a122abffd30115d77ef92ba05d56048cf7b86dcaa5730ba9d6eaec31143d895ac800a8acbbf26b8f8c3d657e193c58d9dc3f5dfe0b2e27fd0033517e4837fccec5fb792eaf94cefac4b866de729b238a2267a01778d6ae3c862958351e3b538deaee13c6e07b73996ce68597ed70b1fe58dc6c8a7a1fb05e5f5c640481ef3736e300276ee4536bee54a5f756a136cd684248db591503f63b541ca4a5831dbf9442dfdf95bc0943a2b45f4bd801aeaca68d005d8dd0bc97f64928e09e7ab3aaf6b076057b6ef64b3d4022b70dbebab0cd9b196bf2d94519e2b0f842722e29e634a6e3fe0b7acf53d7ede8934641b2071f33f9c8c5261b3fc6ea7950cb475b86bc6dd1e04ac82c312927400c80daad9738caceec60e7875ce3d9f6cff4b2388ca5705600780e2747b3f75b27ce583dbcd91c93e5b206968da0adc901196c373923c3ea5f8081b56a45c1d8d5466a669d91ebf603a69d1077c5fc339daabf578c171546e1a608a6ea7e8999a34fe9253341b5682e3b31be915f124ffed5c98ae26b0c36f39158b7fb2f352ea752fdffaccfd2ad2e9a55c658b8610464c9b9ba4f5b6f6fa2ff6ea3e60693efa7eb274bf368109f4f177d09c52dd52dbb142e6b893c2291880f0f36f6ac39d4ba378c284e512a20b9de9aca7c8055b7e6a3874122d31c3f004f39b30686f12800ef1ce67b613271556a7223aa5afc1da545e44ae242d516ae7fd8c5e41e4642040ab58592f8abb22e69f2d91fbc5f164e599", .None}, + {.Sqr, "6d2e10f2da571925163e89c6c7e0f4687cf899100a7d6e17070b0a44be058cdb5a2e79766de469bde025c1495ba89f051f57ba0050a14a768731f9cc0f252dd8fdc778f8095c45360ed0a4d2bf3fcd082f52aa2a833adffd2f1ed300107925f628fa82665a5b37ef506fbaace965782781fc7c1b9dcb5978669b1c2ae78a1d9ab9b92dec5403d7d69acb1e6280c912cb46020ccf0a6b9c6abd000ce763267dd671c4ec6cac6f0840a709a1048e73ffc83f4f8411f1097a3fd742331795901eb49bcde52783b97dfee5f6a81146a34e285339e96adcbc9ca65e4222148a0fccb20b10cc87ff8056ecdd47bc3934ca6e4400500f5c1e4aa35a9085eace55607bd3a7f44cbf2858f0183c29c98249d06ff10317bf57cc71a953c77682ca3fa7fadb4a3c023e26b765d8d380a7638ac4b2e999fb92d83b0f5495b77f62cf108ed8a97178784f80e6b2b133c9101c357df422c65fab583fc2968329b74eab5dd219582acdb22ea11a14a209950c5d6684251fee2ea7213a7afa2d0487900f5b61285c9a10f8edb063425350d81c4cee6d1c370967fa4fe828e8e17f7ebff7e3d29a0f99dea5dac81161e162004f8a5d0ff4e467bde1fd9188b391442f4b85af3eff13dbfe47d718a6b8ba0b7e21953ab11af8afb9419bbe06ad26f357417f45b3dcdf925e506d864b7fa5dce72ecd869a276685904594b19dc9f8fb436da09d211187", "433788dff7a9a5c268168a37b997f1ded805a4c1e0fc22ae0f5a5421c27ff9b7ec9766a6e957bdf3a59eff100c032f4c00ebb6abe30732e375473f86929d2a6354a025d5c3b966796c22022c26809fe7ebdd316dad8c523ac948a643d3b81c9265a85ec4702e15561acb4e2caf7ef0f772e36ef177b11e5892d43c04c0b46ba47030c9d14f7a75a87d8ad60182e6a549ffa00d987a3e706a94e5a49abfbb1dd73f0a86a7262a825dac736b35f6e123cb909f8896cbde774a2225fd332745873417187faebdb7ac8301510ff4a22cb29c47728b45f7ac88b9831755cc25720e3648c42f02aa62cc3b6da3ec16ef6e95d4b3edd0a866db7a2f07cc7789e7a54805377d7046af6bd579460068817c450bac2366b81e62ebd89bf8baaa3c0f739e857842a63faf6e1c63da5c253b9a9f23544eea70b730b66fbc4e4a3db36d9c66adaa83c4f35b08522e40f5aa397a7f4bbba4343e56eeabd2a2a2904cb0cd96e19b7d8f14c0ac6d8f57aca477008d8cd709c6b7d94495634ee4998260489a00411efebb0e92c8e07f958efa38da56feb908ff087bc1e0528a91662b38d176e712289d9e540b99ba507e1e57877af94146f8edb2ccd3dff0cd9767aba6388520e44395b5a2e9579be5bebf3c7b03f6eeeed360566fa97c3c285dddf869a2e57bef9d212ac4250634ce37b6178a5475d4f8f01e39a5dbc2ea4c0562a1d033b3d38300", "2e9042b8e653e463084de127ecaa9ea6ac463176ff3f33fba16bc053dc840c49d6a50a6c2ec9c07fad7cdae60bfbc2402aa2bd1005f3ef31a1d5890b1061484af4a02930306d79a3f85218a6357c407d3edba0a9ea4c91b94e582b474b90c780f0dc149b3c59deb02e1b807f2cc9c6a4bf36b9f90a7d8ddfc6da573dc45bf29fc48fde54d0730e190c59b40e93068286b98d7970637c967e6233dedd6bcc7885b392edf0cf016476648ae2f8e26f214de9fc05cd21fd50dd37ed4540e7cec7b9c1c0bfa665b1fd4f1ebb49180ab5747c0cd604563ff9ba1a518382114f1f3b266f5c2e5ac83960e34f26acccf989f8c06def8e1436c81d5e7e1ab25b339ee83bf5a399bb9ba739adfc6e69e185ed40b286ca7835189c15a940bf3fffcc0391d7567da9b74b3b1b7d54dd6e10a0b687ecc8c1af31b76387f0534fd6a28ec7a3612107c22b181a7f510fbbde0c85ff5b6eb86dcc87f3dee02bbcc610e66777c63a8a4a8ed6c39950e53cae128b1600a17a7d98b081b27d75350a96f3729c68f923358d76f6e9f562e523cdfdc8700a691ca2f1601caadfa069dfd4a11e0cc1a7ea3fd97fdae684cb49ceab8453551c422eb4646d08d763b9f6ad615d960c2d02b8a59bd4a40fd09a90309fa33cb3b4471e2263f8f4d99e437f17588c6f0d58e6dc45ffb19ee4bb575632f84dd5771c50388d1dd87c59398e46a0a11145a24ca3ed33db7649f43b216a32992869cfc148645584bbc1b1e8259c3c45b19ef71d452c9bd8011173b798a804f1cdd1fdf514d9719c71181ef39ff28b95d17e8912f5b152843b5976449fca4e4f1f39da27b3ab26504e59867891d9864a183596ad254e9c65c29dcaa23ae7ac13eec1c5e53c5fc2f64134fd2b7834720df43cfea44b0e1cb2b9b2363986cb4e0ab206132ba298278d0a7d17c4611d95bcc601b0e2d6475449cc268faa1d2a287aa29e9c38bb1824ee8544f611a066f1cf75ea1e8a050373b1d6405a302d41281ad3a5a7514e44e78c3f0272e8b503cb8c30387ced59037f03881ecb3ec40f785697de70640871e52f34ad24b611488367e8c1c93ef415fd50b35411892020ead2e967d4c1881f5f12aab2c7514026bf5f4b43f5328ee99e726bbd9ba1842a96a7bcd0c172ac259e3b73ea39b797e924ea4eb1c45971e1b74d2aba028d290d3d78501951cec7fc650e6054fe2ade74b208cc52b2b542c44831f9532a32645ce92810dc2f9eaf89f9e2564f129357a775d797edfcd59c3fc2673ccd0d73775a15e1afdef321bc99697bb624c6961fe4fa75e1a36da011e1dbeb6a400e4306892bc26371cc84778afe7bc70947869461cd49a6e10e4a88888f1665fd48a62c5ac44c600c681f013dfaeea4e90e31e33bed32c52bd9495d0625b9d0499f0d33ded77e99da7151ec6bbb3f678e105135d0d95e72851c013531", .None}, + {.Sqr, "-ed459826f8f08df71a1c2802839f8cb04c3ae20611c4b1fb6fdb10363af854c5ad6361ca724d75a53c28b6d8fcad2a53b96492457e1c3ad973c59d1636d36c17b51b4529ba4fbb310c46edda8fa9bee2ab8003d718bc58c5beb4574882a1653203608642f26b420c987d1c6f223e294320c1956ca35254b3fb538c0e1d300bd12a09c5cdfe9192689096ad5053f35106dcda6c182ac398d9d925c3d7c698d9d7ac5f172457cb7473b40c07527002ddc3d3e996935afa0262b971480b2c91feac03b112a17a23d6c6a8e594e2fceb2b4d88c1339f7a02a85fcbf62c5b4e8b4179031fa7a79b75e376acd1e29507f47b5929df43cc7041bd15d6d1ec7a52324da8975cd72542459fa2b5139031dd8930dde4946b1eafa5103c2aea71b266e7a3bfd2f023230b73e5dfe209c9c2d451ceb030ffaa4ffde3d873af4a2c91c2babf295c76fd5fe77331d369da924505e0277a79b2c209e9455cd03c6de169f939055e4fe1e8a80141be4dedf3f196fa01f8f06a7a4efc3cfdfff4169b2036e6ae566cdf22d9151cbc2538be661c1346c7f12cf57ccbb71054fc44d3e40864fa858a0637b0e74b0ff4254d45bc9de12c58795ed9046162bf57ea9f30ccc9f867390c0d245cffdea33ff1bf8164d1c4a9f9d1934d0ef5e8078511905d311ef0c12d3089ed4b4e6a261a20294d5cf73555da5042a70a0446a6d731123fd1e61dd39d4cf9", "5c03b3f05f7d1ebf8388aa8935dc314b009da0be2a5114c2d08873f8b0b6e06c6717e8d06ef399c5d7d6cdce4a0dbba94d03cb679727bac44c8d5f01bdcfa44b706cc4db75a298cba5990956114e03cce64e5b50bf191725e4730a58e7efd9a48dd2bbb190ee253fe6067543b60b0ac8a02c61e8f2dff2ae2a61d3352561fd77b20806fc1a890c1677859ab63bdf0973514e07b0e4865d0efada5498393f863ae450514b4faad0ff3f1a2b3760df8756db2d216a3135e6484df9deeaa759b0571b2865f50e5bffe662dff582e66063963197e5f79a98af25c03e92ee1f2e3a38e473a1a40dd29378192e72ee0df6cf920e1e1b5fad73fb6306aafde19e490bf676c93dafc8272a4c3ef999f8a79ed1b6cc70e4c4ce545782fe0d1752e77e5502196a91cd2a4c2b80cbf21a3db986f4a4b4ab4d36044a640761c7cba082ab54cff3903b49304675bab28024280ddea10ae0b0db3415ecb33d2a436b6a043468a243e120a50266313cadc16812228da3dfb0b59f29d8a91ea7d0d5689b1c1f5ce3d3a2158b314d82d897822e5e5c08ed0a594ccb8539a2580958bc059c43b1da50a70b14a77c954d63d4d03a55ed422915e962976460b9c9223f8cc42d3c29db299d64998ec6632c777cdd9e0d6844749dfac0b3c25ac704112f29507a74218a253ddc1ded8221a76735129c7cc75052b3582274a1c32ea70e08d35e76592e3825", "dbe9eea3885de6148f9ebeb8a990df231b6adde808b4c59ca0fd2f4d174ee998c58640cde4b0719944400ad9bc5b9b5e3a71aaa7bfd3bbed907018f49839b24081495d0078f34406760e62a1b2e18a0021caa59ab77383e75d8828b2bb23e15ad9cf231b291242db30af9133aa119c763438f584ebe009cfb76f236b93199718a39fa031f77c10c94cd4e699735fa0ff51b624aca9d48ecbc50a813b12480254fa2f777807b077045a2990d27da8b8e9c550ac0c190b6417f3e21d8bb22ac14073e198541a573625e11260270b777aacebb59622642241f1fc977a7e1767ad2e8194515a6072653130a51cd85c2b71c12a66fd15a0444c7ab332960f0e0cc8c362e48e63c363b60fd352b123b6a162348570cf5f160c55295fda20ceda763939713337672cdfd965566cd77572aefde64a2c19492729813e1499550ee1b4762ef3b0aba213087d003563a8b0a0c9ab59bfb6983173893c99dbba8c8e25882f2826e70d440a4b44e150c8d30595fc60adf742b536212d92a93004fd78eb7192f9862634d65a8647064eb3b4b67467d3b266ea4f598ab7256d9832f38dc3459faddc984b009adbbfc80cb801d2e4bfae6aa3a425cc71a136d5b9e92cd652f24950f0880113ff7e4606c8ee9c57a2d9ceb33490c33c1cc3aa9847b4dde38d2ad36817e8df058c98715f0b40694b764cd0d95cfdf36075c20e6430bd74299b6b6b54e8da282e6d83da21f6ff371c9eda529db05f9db2011718ee0d81c934946c7203322dedf2003f35cd0b0f483fabd584c0dcd8af0826c50d4aaeae945ff2932a1412f7982a711a46df136c236606d8b3483256037c5685c25feaaf4d89d4e6b8e59f75464f10ffe3d2c254a526bd13e482356844e017fd309254b416a7f94670c19fe99e87e24e9c940945ec7529867af263fef01795d796fc29c674dba258a8c90bc36d27f69b356f75e799617384e87d8dec23ebf91cba8a5ed1293e5f3bdf7ba376dfded2cc5f7b56dec0cdaf43500b2a493b7d43893ed6a1bd0ac19b7200e662fa5f481804cd89172b8df157ffdeb67f57f212eaed3393bb278c0af596e67a77b73a1921af5fa317c31f7298f4528be89128564db53ce94c6dcb3c74cf08dcd1bea3f81f316ee4cfaa13b8bf9cc8096f4109982451e35de7b5f062beb0b838364756ed61c193480b0399bceb58052f3fdfee91b2c6ad830febaecf707921ad225598d9f7507c5bda0aa807dde148476811b4cf2c9813ba5cccd0f2374285407ff804497be4c76e3958fbe5a9977b18cec39b46d070ed43f36f0130d86877bab01adf4bb083c7066b01e46a511a988a860c66ddb25bd273f310bd0dfc3d14fde014b5c737064f8a4bcb81194995451add522f23d4fac7885464fa608d1ba4a559f77b3a324354f620a68ce35a8540c21df014c66988b376837189f3f68eca31", .None}, + {.Sqr, "-6b9e432dd4b98cefd5fb4e0e0d949161f2820f052f16b23328077ba42c5b24a20c2b7f9835ab58950fc2618a4f86d3443278b70983b8de500a579c6953c78d1d2d71470b72a12ca61af34dbbf36f56b788b4d3f3f132da8d1055a0a6101f4dfa87f513ce15ee809b12911100cf8cfde65bc4563edbc77e35e022f05765db5350f10d78468f5b3a30d669122a2f93a41fb4a99b772a18363c3d7840ae4cf9f3e4025009c73904a5b4fb536d5b710175f0ff699c2ad09812d8604383dd106564a54bde4fd858f40b5042e687335944855ba430ed73f741f9735af8e1a7fa6d5838935effa4b34753b879a97f291d269aa71b86d38a3244c55ac204dfe64ede3c539bed0fa9e7b65a1ba3435344ea9ca6e875436588022f0e2b44e3d00c2028d78e3b9c51fe4955f66426e6eedcac69ef6d38dd835586793697a51f9ece77ad0f4560eb02abebef6c87c56584fc8a19f314c0b27e69b0cc1b0f8e3b37b769f0e46cdc3f5cf39a0419bee40d2a2ee5bcbe4edbb639cd61de00691ec6610e6bf7fba743c58a32e62290c2bfd1d96e24689451e06e5be6f23151a7090e0117db80d3e0ae76b7396f23efc61d3608ada81c5bca12553acf1ed16223d4a27d66cb7c6ce1bcd82adee93395d7583adac292e21f665ad79e5fc5718ccae820021035a24400a8abf0b978fb38ff71420847f09c4ae4553d79e0df9790a8f2424bea443c263", "c4304bad8a520f3927df131875a28af4f102a6ec0047d182255954e7d947c7a7313d153e879b4b29e53ee99e629ebbb60536b106aba129cce3f114f75583175e3d902c32b945def5a94bb5464566463b1e5c161693f1ba26494cfcdd5a99d877483f5698f20cf087d1342d35859d4da6d4b44761fa1743e365fa31a2cd5fc894b672d9a3d15d033498609bf319af893bd70631174937ffbd82f86613147d7c0e239d79fb79103e93c3f90f0045c1e729b52ecf0d71f5ec98ae87a055bf63cc566b5a400005ec3c329fe05b209caaf2730638c4dd86fe9c06ed10c473f9d6de2b0ba472488fbdc203a457cedff9c5e78e2e1d2eb86c61d0a6168fb655bb8a70701f2ba4f2c57f8dc6952daa2cc3d11e0b14be6d9b13c8490e61f0e0b9f11b45492e46c643c6955378b0d31537321b7ededf27db390107d0c5e5335056b3e10b3fbeeccd215b45ef0c1652e0bbd3a210c7e85cf37f8cb7425d62aeb5f8e806ded90b3f26b1932b751fb9cb99b8b6767de7acf5d4ce73bd1b524f02ec0aefc3e33647bbbbb807e911a2a0e473089a403bd6ef7dfdab768b1c7033632ad3cfa039c15c25f8a754889128bc34b18693a285a43afe3460103a6bba78eaf5629925112f7b8f77614efea6c4348fa7175216f1e6d26a75f9dea581d0822a12fb66223f5ec0a8b82d09af2a167f244846427b0507af26b36aa3536c87d3dd1a196b9660e6", "2d3dadff4e06b6680eb123b1188a7232123967a9f2f002bc9dcc702b1af1e55bf77257a5e8cde0d0e1df836b2557dbf2d4ec4f4d7652fb64c68b00d0f4b8ee6ffd6c25dd3679fec5e108b9ea11fa0262cb0dc54421a22083c446af6f553ab41d4c80715775281db5e08f3349aa3464d370f6da4d1e4dfa3c31d19f6d05d2ddfe790bf23ac6030fa9ce839804eb0b124dc55c710bfbcb86c7b28a6dc980c15b54c27ad0879398051120d8f01c07a5736cfbcf20ce425795885b203e30bb0b4836dafeca5f24d88023580edfb6e4b5eb33e2ed42d3e7f886b6d485b7b7acd06ed2154748d97f4a232a071cbb349ed82b5a7fccc463d09df93db2d2c5bd3568d3dcc09c7d9e3109dd9846413be51e9d93efd4b7425dd8193b7856a6383f52616604636b642f8fdda0bbfc8b9ed99eca9507fefefdb3c6999f145899a0b42040d6d8799770bb4b384522537495fefb42adb369a70fa219303fa2b1e2aa433adda5fbcf62e1a7ded7369b13d4d9454dfe1be5721ebb5e515bf5cb944de1fc4a6edfe03c216bfe4573f83c9c321d036a13ed6e6906b5fc33679ef66ade2b5c062ad3f84c0c30d4bd3c4d8e713451f044fa38685ad76358403817b56160682d2991b6358087c061aee1f2b20f62cefcfb08e2e5e6f62bfc502b8abdf07fa0320cd1f377561823107ac5f015db7f8c7234cf55f1cc501396bd1e52888527f44407946c08a82c1e80ab97d8899c7f2d11f408152c9cbd1b2090f3e416072889b5409997f4c485c6ab6c37dc576aea531b0c1bc42740f8e60bed32ba7ee889b7d36ff12b6248eb9142d00abc646713abdc99d4b704d9d7b6e7b92b59efbf740a3763af85972adf2f3f893bb0e53ac01016a80355e2f676dc03cc742b871f60b59691bc9f580bb5218b6c6432810314e841d9cf3e8d0cd74bf22055df9ab42b641071cb9f47ed838942ea461a8c735c37e147a3ed7b4804a333e5322edee13abd677e5456f3d3e03ed6d43276d90f6649f7a1cf2fb4e0fbddb3b58328c6db49cdb1eeea26378767524b19280dd48cec0b6f1712ee21471bfb153c88aa55b304e132cfaea480164c3d1928ba69f1a2e4a9abff8baff1ba021dc5a440104da4493d130cff9c5752d86bd0becebed523c5399ca2f42622c08ae6a2b3fc7b3a749bbeec60fbfeb407afc60d6cb51e49e748852502a3578082cf835c16ffb5e4ab46785da135705ab89804ea187d6be79deafe075b04a58d015defa1965bf3b15f0caf3cf5d860db95583768d5834897e0ea80cc20c8ecb8b4d6b232e081e85259e1e542f20964dedab2934e52cfa604c34e3dada5eb2ddbc96e646086e29539d9d9af96d218dea9612fe88dde157757c12b4026a781a253d783b2f66095b9ee7e08f091467097b06f0b07363aa091e1c09886b38990547f7b26166c0ad820927f45f22b6c3249", .None}, + {.Sqr, "4c31df7823b7f67561e94cc5ccb52201f171d115717457cbdb17d3bc321e6d6233f908cdf1f0f1175d6e6d3dd631b426366fe9f8d8e32d7ba49d9a1b48f8f837243ad27faa1ccfc233f84870ce54ff5acd53461c640ac404836a43f9a184053d3678c3c0bbec6ac12ffb4b2b8feba5a5899d1b96ca36434f01f0f3128937ef530499e6b1d1d2de3d0aee5c0a37ec44e7bd64e287564650c9862587922423b1b47a10ffcc1d24c3cceda409fad4e5c832a07469f978bc97dc345dcdd01c075d1a32ce01743fd777164655daabefe37068625cd749e3ddccd07b01cfbb425a0bea4eda838729983d0b57c21b829c55910876c5010bc6f1633546fe4f3762ef8b5f03302e9a5a3bad902fbabfa43b8eb79d912d9983accfd8a1ba3a0c0b637bc1e7f0ed98396da2be13ae3216df508d057226fd8258c181ba2343b0f449cff5a35438b386bd523830040c9ee208cf291f18545eac548344805bba4eb2e5507fc0d5a2fdf3b7919dc8906ce1402200e70dfd7c6ed1b598b0facd31812b880462f5f520d4e2851021461b3c295d873135a626dd634b20472469f2c21ad46e5028901eb9fdd58b3a735fd39f3ca2ebc965cee6a7484a386b86ecc2674c2b13e27f88af72cea89b029c4b23eeccda8a35a621844e42d7bcefb79688978f26f47a8e79c16652fdb9d3c89f5ef25183b1902ac2af20a1d0e3dff9b48ad5ff554419c14ea0", "4df221fe66c3b7084f440e7ffd609f52ab2287640cb720ceb8c58556be5fac1c3f68012ff0ea59cabe930642cb482355110ff4abe8bddca07be13ee3519aebafb3753e16a1ded3b41b568a2f4db0a468f54f90e4623bfbf01817aa986d626e9b54a1e15a5c25b6cf2c53d0adb1958cd3f04f2184ba0bcc482cd665a072bbf2492c6cdba655b6869c0a0f8e30d34c5b38fb8d61c1026796f974e24bac527a9ea57f93806bc472210be53cc81dda18262e4ef2902a22be3cb8afa4d4f878f544f16eb591b2e185ef2b3c67ef622ee9b0bb07e298d94791a1cf142045bcf307d6eb9bed27b52ab3ee45195085d003580997f4daf9e30c149817856c5590049782d2e011d28b8cebd0580044df40d5abff38f32c0c8c897fcae0e8e9d4036d6927bcf856a5aa0a914e1ce13e64959613656ae31f8a4b6860c0c3f6770c21db0b43920ba0cbad9cb5ab4edd25abd6317e44cad7c3f6a7243fdf4cdee4069aeada3ccb44222841c9daafd2e2e3b9ac8593a208a5b7132da145028f00fb35ff95909b0d7d78c102636b58ecbce665f2bcc8b11d686ee0de769bf180ad361d6c055c51ca4927a0f54c019839d53ccfb6d781a57582ba237d26096de8cac4553dcc9471881e42ebb0e62c96c95e4d2b4b572367c89ff60d676f36ed368425d375269f1c0530d963224b927a3c37f43599ae70972ef7c1f05c300b074f63bf04d60a27ca61", "16ada666a4456d5e0be5611b759a1224842c6b748878f3fd8cde41fa7fd9f4b63e9a4f9a9bdf99bcff0624d3295e33bdc7d1ad882a10e8d561920edf13b172c63298e5b9a6821546c9155751ffbb69d1a6cb9e909bacaa94671c52e28f08688886f22e79042c90d0ae595f8a8ebbaaf3e6b0a1b0faebf1697dbb9e50b6168bf7a258bdf5c4a2d56ff2385199fe03738f8909a00a67eb0dd15140729a49f13711369efc6a3906d5a402dae63d74c9a86e8352e1c226be6c8d013b524f513dfbc11ad51d7aef5a226c8b15057f602bb0a78a2b5766f1f2468b581788c30803881241d440f05aed5b8555abf54735a00a78177017effe8ec59f14415b9e0f7ae479800625572d5d2c6f5e7c8497a13fc6e452d8c06bf21245d1825e41e7b04e5f278f49c2234b660f726a79ba68b6d7ad9ec0aa9f37988171f0530e95cb81b04c7c232b9ddd393e1ce34a0ed6acacbbad2c24dae46c17de6643aa52fc16793c8122828dcfd8d30e82381625b81897ae7eec66d2924c3741c545dc82ad4a0689626b4695f88683211aa805a13356ca330408dedc7d95798cc3033fc21d433d9e47df5236d58ce793b74b8a8cd04014dac4ff7e2c8a54c6e90021da5717abacd48d6b0506bee5b1ca3cec76d0a79404099bcac5ce13fbe65d0e436c4b38ff3ed1cb0c391b2dd0f650acb37962ce37afde959421abba08d006d929a362aa7619d1254d89e6faced92bccc8f0bea73300784aa63c67578448ece0c4de0b1c21d681be02118f53178230cb6f84ec5eb9bad6636a987339c1d50b9ecb2391e224bed437a71009e1bebf70ca92862f64fe2b8217769a9ba6d3a2c83561fc87020d9cf5c530e6004084aaa5a483e5472a0a530960d6bdfa72543b6bd9e0ed5e3d50aad4d59e418cdd3f83a76ac27f3d1af33d8e1f661b7d4dd5fbb2c5f0b8dfb861e9d5bc16cc663845555bb7d4aa8ce0415fa07f543649d3c2d91bbb17ed5982981c0a314758a5cbcb5f6af999f61c3c35b4d7becedac74b026ade255c6bdb24fe9d4ea5c5ad305514fc61959f7888a1788828baf7552b1a7ae60d030621d8e10af159ca7d5d3857229758fb312846910a0d20187ee86efcc24940fa41793d3175c30dc0c6ef7127228af31611bc2830b6c353cba80532ac2bb28e8ba5ce3e401130abe40e4dab0346894a88eb92450e10097bd13a99b23b78bad175f3165cdafe43f54c0fea676eead24a755142c44fda75bb0fc6345ca6017a162c63ec98f70fba6fae3b6875285eeae63100cd57f5ce51dd1dfa93b8cc2d7519f4ee14deaa66c5db5f72c89f3549e8521eeebb5be76138c2c30b856e9b1b18e193df6e4d6da14b057d159e60c98f3aa129610fa80d51780e3d8f9ebf890d5a832863e92a44fb01c90d6ac8d6213f1227d2e266f7f5d147a741a7af40e4f79b270ba8f23f5852e565e400", .None}, + {.Sqr, "-175bc72ad92a690cb8d9a247fbc70dc712d2602af00ad7b4b16ac5ec9bd1937b0ffa07c42198bdcd0a92a5a2a98718e0c8f70ede48cef728315c33986806bd60e7cab56d8e6078fc048e791857c5fcdf5aa162c3f03e1b8a5026a5b020ba56f40e0fa6bdeeb59e227cb7c31fd306d1632ac8a1a3b789e274dfca46e1862d3c9127e1bafec97642ff872478ce2ecec9ca009ada17247eeb88b4a30f21d36e43492a5afcffc5de54211fc37c1bff5694397529df81e83d2cf2c61bcdf8ac96684f1f3bc26761db1eed146d8bceaa6a5ff5396884cb88435459c9d1cdeb84bdbe2ab1b9f22dddb264945fc62eff583fafe28c70ca85948de9aa4fac17ce430084c634c77e034473728fdec0a9a2ea6b79c35258cb71822bf7c0032b294b580b9a87d12bf8b70bfa93d9d18d10ce6e6dbdd968eee97167f72fcbb367e2fa1ffcb37f05ab65295155369d8428fa7731fd11ce667222181f92627c77d9bc23c16d6e9ef6a148236a25977ddb91f5b2f9518eda8c5f6340dc36edf55fc757e0b84b5390981b4b0493220f4ae5baadebb24b3fa9f3d366d7007fbe15c78809d6c974abb4d098b3dad9cbc82fb80ea73ac002b3afb6cae9031339b16b8c3c8fde366fe9719effd39644ba1c14469f5eec9e9c97f99793a2595e09f94ce9aafae7b8abfe9d9c58e076c3ffa19181f31213aac01dba681c0956bf7badf9101dd7b135d12714", "1adde64bbd4b96f4f2d40d52557673133f5ac970b0b7c0eb24dc13f5e14da1bbf432c04a6a0e66cc7f458ecd9a017fe002ff932862ee2a9994ecb984391a4552d194e1e718523dcfd8bdcfd455871283f728b56abf823f8022b24766f61a1dd3373ffc1860d3e92c443fedac46f7a66c586d7e466da7db993f6a6fd9c1a8bcf158032207856485f47913ba0956c212b0c67743b5e0601da90a2dd4eaf45f5e5fd98616ca9540129f4a94e486a8b112f9b87034b0f0cd7ae8aeabebef3b18d529d8b5a75736e3c05183b042a72c9a9652ca84d70e71d8595f8fe36aff6cc422fac0939cabfdeb748d8f0a45b35fa1b6d5ed2c10cc57dbb53f242745711e52185f20fe719a6e0fd13803b36aad72ee6e38189b1bfb53e680a5a55a70efe7ada48ee9f98945039d28005e04d9c1c9638366187201d50d098c514fe6f351cf6a16ee8acad209085dfcbc1e165a947f0a9f14848190c578f4fa49c9042eb9c04c2b28ca32564084056c4c0618f00c24ed4c85116a9c19cbc69878805280ffc463380b1e903b562c7f1c1e5ff198e2b97b06da332590c6d90659b24f25781f5ef943df152e5dc30e7ba751c9b8d65aa0eb10a3e6a2c04805b56bf484d80d6a54593ea8cbe32e00b719aafc5c46392fad35643f44b7134e812484249d4cdae39916931aca0fb3c434cb984e2e885f509a5e278f5ca8812e5003a82d890bedafe9c20fc6", "2219eb0e66fa7d2e1b7b28f84c8f9d74f1b1bae3a3a801334ec41b43264bee1daa642d96a6fdb4bf5d03e11f9d4aa54831b8c63b0516eeb11698afd5391d47fc97d15367497ea794f9611d4fbb467c30bf6e67f49f07786fbdfdb46ae9e42bfaadfc6deaa7ba412ea81422d99f23abaeea91d938efc549bf77db5dbfb8be65ae51147cd3383cab1ba6baa0e0b67bd3c50f479d687c27e13ba0c462c620ebb4dce765fceb4f5a31da6bdf7022abada2170b4852a54d47695d79aa95a948347465606404914939edac8c06a675c02514dadf6b932453fee4934bcc2c05c14ae1430d77dcf9d9718c02bba5490a64a61f043db0f21502495109a168057303883a57e17c6b6758bac3b95cdf0b1999ac17f0fd34cbc215d3bc62405a1b2dca8bdcb111b5a3c0bb6d56fc954802b0d4035c8d04242c47b06460f7631a39b6f8a69d80667a27d0ee1fa927935dce939fcb43bb9173ef52e0104540de0522093bed6caa0ca9174ab18dce386b7eedb26adb34287536a0ef5202350c22ce6038c180fc241fb827927423f53445edc27ad6933a570a55cdcd2d4578dc80a0ca25a06104b81e2edd0b8b86dc02be913b57b5bce065989c996af4a37f05f92b95d1e66f5bd4d39fd404911db73224bae025d7746256a8bf963d33b8e6d9fefc5d8ee51b623f37a5f6dc8deb407b6b6ec584961d4ebce3c72e2ed2d64d7b99c8901466a8dac13bf72dbedbaef28d4bda8ef9976f56b34b9022f297401ffc0bc8bfab38e90fa04e2d74484fc6364cb3b8efc9e6ccf7d1f8b020c0118399f5bf509ee2f506762daa9ef9881d64b87993e1d7477d84917498ee4c57488e9f5023e467d30cde13da8692604621cf1a0a5b6c5c04d796978d5f29c6e65838bcae5423f99f481410521462c5f6f9db89a8d3947d285abe7f983a99e4faa6d45e8db49b1540ce866393354e31936c2f94e559e7bf200c22d01262d2fdd930c29f80aac4753647606ebedcab82937304b1ed3ecd334197a7015d7b6a58e153e629762860e4cb5f082460ad4ed5a1a1049102444e2c6c4e419209c087738bac79fcf7134cacc9d3472c3c046be22299278f6360ca1e7f4aed82ab85c18e9578697ca011610f3054ef282d952bf08d063780797350c2e34b0b6bdb1ba64e02ad527a7cb04863c4f564315667ee716effddc22e73b8f15860f97aa1681160a437d234ae402de9356f99cae70a9f9d3978f5b2aa50b803869e196489f25c833232d7fac463ad3da5755fe2f4407c95ebeaafd76496f14a9eb325cade168a742878970b3335b2c5814c53727cd42defef3200cb36048a215d421cfb252309a6564bfba8e0dc287d278010a4b6e55fa7a866e58b9db4ebd68b660e30f01dc4ae803c555a1fdd5de30935551aa749b21059061f30b262aa7e72618fe0a0cd450a37f82863e20b3e6b71c9f1990", .None}, + {.Sqr, "-bfa125346e0085cd669747bcebee4526c9a49f0fa128939817fc8dd0fd04569016315ed497d7a0297f1cf63ce4dfe37e791dacb8245152b607cfc34e67a3bd4835f1a7d6958fb90951ea6567c9f1499701340d959f58d0f96793e48bc43283887ddf46a2f8848d585aafc44b6b76d0b72c75025ea6d7f4402d9f60957c5095548140bd41e4fd33baf739bff345d86d3456f79406cd2b06097f7cddc89d42d3248d2e038fa43469a58bc8e5997ef77c02558d3c7d260a5c2a5b391c4636a3536b0b1a6f67760ea4ed7fab9cb86b89890280f4522759d94430f70ef654ebc85e04123828fad679d3f97e48c0b8e5a7fd618726cb22d1668da780b27d62df83627319f7a21e7b6586ff43e6ab06c56fc6b493a3374e9d78cc7f4ab2c5d2c465364c2123c2ceeb104cc3b9b48dd47e9e4358b9a11add0a3e90379bbc7f45b2e101bf463e6c476636735fd98e20de7acf81440fafea964feba3dde1779dc38d001c3b17503a24e2a841e1a84b179ddb56e6e03e8d78914321af3b25aacad96f3407bcab5b166812d1240374975481c33a79dc0a68e3d99299ed81bee035346bd2ae843b048a93263c33b911c020b9d785c860f955105b4b8be8e8145e66629e2d39a72e93054bd76673016d11332e461d159bfee02c8e898c376c335c99fe7343a9ab672a85ca50508ea76fba34cf8717d8debec03a92afc50ba5d972b7945713f5f5", "9be1bd8f769c299b2e160d8cd2194d0ac917126923274e3be46a8abaf3ea5ccc8ab7da1f5be919ac055a61e21f1a0a36c1ff360614b4cd88b26b6e799e6303fb84a5cd5e3d6b06321314ac52c184c9890dfeb57c4f89db1d8a35796c77ecf8c8bbf27c919ab52dbf6504fd3b5396455a3db3055511e8f42b25a4843d685ce5c799c1be5d4159eb972b755112f9607991b9b644854013f126f76025e2dcc0fda42b1b503c09ae182cab7051cc502612af2e144100525c17a179e4e24d40da0cacb4e34057c9c7b97034c9f7ee62a0824dc56ef6771ff237e2eb7c33416d15328ece28c6c356834d46ae1769e6768b59ed913cdea8d65e688899cbc9825d2223571a9766c1d58d0f660678f0b9f06bd078503289e99695db3407e9573c6db0dbf8212e84a5f9d4c9b90b6340205f928e5613027dbf3e5c4042dc830b2e301db8b178ecccbfdc8ba6d3449b468e652b9f7d2adf3fc10e5dc958931ac73a2cfe8b9a4a76b93b4f9a8da609c82c449c6533224fcc763b90c6c2607a4f910bb717a25f8d043cc48eb520c99d4279a601a77ab0afa15da272f2442446926047fdaeb8beaaf15bca27467b8a57ca83b6123349b611feaee450df16e2a85255e5d72057912ecf53689c1b5caf466074d82b8d08795afbd7136d21bf4631ec8a1e5ebffb26a4cee97d7ef0e8bbfca7f2f7af690113e8305e9f8eb926af94faf432eb859f45", "8f71daf40d7f56d9d198f56a55f920e297277029eab773053fdc43d362da09928ecad1c29d8c5a1f28879c81dd33f2b6f7274650ce6f686ecb58dde6cae667d6690739ccefc97c210913eabb5ce6b97ba424e7b0fd2239da9ef35f710adc94bdd20ef05b835093b7747617761318a368cd09e1883a053caae0dd79cf98c0b92eacd36a75022daf63ee03c7dade91d81bf4b0675d8e1fa406b4b34f29d20ab3dc7d44216177330e853ac7523406024d36d9286cc5fe1c552d63fb619e70bca1c24e1a4b6f3ab66a2eacefb6088e113c42b05a5962c97e34f54898a249234afc860aec2f21a53fffa8473a95939ee586c62f2a06fc5a857dedcedcd81f8315cc16824ec254bc93f248e08c10a6068c9ca1ca4920729c57f566a939ea13e67e4dd652a32bc27e64259117af3c1667848a4e5d76f49a26a31d10af2aa9942b6bc25129d6e185ec1d41d1889c74b0820dcf1cd8eef9260d19ba193132c258ca171a6fe80c2902ea865802994468c7aa756c2297bec3a1a4ee4d428a437555b49bff23ae781e3355e73c9097cdde33bcdb46391b24e227badd7e5f066fcd5e0d38a6a14e20240cf028bbf39ee2116ca470f5286f6513b1f3c8b734a425306196dedf6258c4e5a67e99ba925d7079de7f918b2c41df1c7835b53d94705cc09d5b36abaa3ec954ab01cfe456e3e884f56a7b17013bf4c1444d7befed86df00ef29514ffdb99fdca11bcd41764dab6e42728d720008d5a2ced914cae1d5adb643d5ff2cb2db0fd0219df4c52784df8e5bec18c68cd6549e63c66c218f64564eb3f3f4fc356e397a1941aee358881a522149a9787e24f1228d96e2dc2d66b9e3234a82d9ea177c012d4c04fc86e02e2be5b181c163c9d62bb8f15526f2ae88ff9247d0d5431dd36a5de8cf0daf92a5c24ff56bd8797910793850d035fcf62eb01baef0483ca1fd257a9c5865ab56ca82a757958f16dec8179fd4203ed3ed1d57efbd8c06b8dd4d7c3aa659bc613672240cb579bc4c985f5a436aa0a406c8af9fc79f455bffb9c4ade397513bfafb17a9c0eab153a85abe51b6eb99ad3a7e67af696990f3093a8cb169ac11dc7acf6c91ae54cb2489728aa0ac883bd8fd3ab3a6de802b9d347de4f68f847860880a2d6b64e8f5af820fb51bd30d851366466f1af8cd7c09ace8bdbeefca3233c15bdffc2d577fdfc91803201d56d514664cf02b2d1bf6f3ac148c44219c00942962f041b87a3b6be53f81fbf588ca02975796d5d80b3e0fc95284f9ff220e78af8829fed6f1d7b3d768148c60e0e569d6d783719e22e9b0b07ef03506c443ed42e590be844a53ab125871fc3a07a2f8559c1884f056824f049a6563fcfa1ffa5ebac608f0a0ca0caedc2b11f74938d21ff00b5360deeb977a7cfdcd6c4a14c296dbba974c8c920e4a356df1c6f752eb05be8b3c02f4acdc79", .None}, + {.Sqr, "-44530655c094acb036f2fda7623ef6f07f0412c7a1cc1367e741349e33294756350bd4083b32306dec4d37ed79c38e59c57d02fd403e831dd635d30d5b9008f15d3040bdaaf1980956a4d5fdeb102d8a4767c13ac86437877358ff352ba08927c4476dcdc3022141aea5d28fc1ab232fbba247abee49caafa341a006132870463e864a3087798c047a1f143c89987cf4a66022f9554e134fc5091b20d0fc8ca8bfc909e1b7380687a380ddc3a57b4149de95d57e422f63e742dc446403789dece8220123bcd98aec7514b6d92b9329f0dfbad014d20811118d536df041c462a69aa412a1acd53126d953759f66fdd292bf84692069cae8818bcafdca0ae7267cf82e4b9b86784679be45ea7f32ba307a0cab6873d3b26331a6959ee9be518c1ef2de0417e8d858adfe65e6790b9f64131b8583ebd51a66f3d4dd21a8ff23dc91f81bb12905a94338e437f16b23c3a12507c1153065faf7659913200df22c627a87e4045420777856b579d76cf0cb4f93855f48ca0ced12fe6024fc39ebee9a5198e8cee47f3b5706cce7a7dc25cefe178af8ceec5cbb5abc15ac86eb8fa37d740b88e238de31651f259f78e2f47b6d4065d168d57d30bf88896f0975983335274536a599572391ae10286a9363c3f1667c938eb52e56be554ed4cd7c1ddadceb7c225233cbf52d834f3f21092e5d3462a89a0c4b04c31c24d3ea64bf51ceaff4", "d5dba5d965c1c53e1e98158572f82b0e290c98c37dca3a3836d565372cc3b2f890bad1c8326bea93872456329e4dc464fb7e7a414bb2337f856812f719f6c896a96e78fbcea0333301b6d7c2b8e5e70c45411522ead5c4a52cc1bd10992be34c0951e26037abc58b86b06d2b75957d8213176651e8d159f23d3570dcab59b1ce288c65a3d867203452df3ccf9219ba3a1c673102f91a491735e3885244ba6535dd51f84d232829dda5085700ca617e47810efd08ad314b31fa64b89e21a7d2c98949e593818f25723de6e7564e7a1cb661f1982fd50c0a869d91916f0678e43dcd8cbc58ba8ea3ad1b7776179f777e43954bb80ea4218a5b76713e1eb2fdc802e194c5921c95415e07d0b10863e912fa15ccb7c2add0bcec270a88cd9effe6de0f8f9703698b6e04b4461d3948f0593559f42e5e6700b51dd70dec1769bfdedb3adfc4c9b3b7c61e7aa55f4bf273f40b27d40a31c99d52e562981fd766fd203a2c9ab8a1dc2691ac464567b439c10bbebc71e533e329f58ad4a3375925270c358964ce62e76dbabe14ecef3028dfc026c7a7bd69bd6264d04f583bab1846551843d2b54767fbf7d791b3d8e0840e6bcf48f07eebcfa604a95cacf3dea1a37b9f28c5137f723401c87fb106eedce5e0075c796422a68eb6219b6c8b547403ee0aaff7e74af112eb7ebce214bbcaf460fe6f4faee9ccf58cfdb437380c774373d8", "123c364aaa11fde603270149baa4ba589078ef4fe5396be22f3b480df149c4b8dacc0cd943aaf4e84044c17c5c906c38af1e0e2c7748d9c040ee927fb5421d09e58485cd3a4781f508a3600981f42041ea780c692198786757fa89c0e764377671cc1cf220c7a8d44e2be264c0221d874045871497de739902db8f640a8a17d99e2aa9ca0e93cad120d35ba38590a11003b967165a70be41ae747386348b4582b0cdbac42c8fb763c19a792feb663b9f1283b39389589ad4fe0d76b1a9a94f39b0f946d888456e75fb3d64a737b0d003c047d1d75ae0ff689b4e898e6b591091123af3c72f04912d555a9a2a7d36c410326d89f223eb003d950ba184c8edd77bdfe99e034105a2fbc24980f9ed86745c69584179219628155e8df4647f2ee1ec7157d2e02bc5e55a8afc5de7039cf1d1904c79a8dcdf175c8bfc8f2229aa0367c784a640dbbcffabddba22a06d33571b9ea573b165a3756a4a0f8d8d0b2e7cf72b7cc4c25dc88287caff90c003b02de5aa4633d0af219bda1ccfb62dc24e135faaa4663ab68419d132ff7753edc233bb63ddf4393c793fa295b9c9cef9b8ef0be303078bba8429ff6636c3916be98cfa165fa423b169154bf7ed4ddcb172debcd4d064fa1c1282a8f396a43c5b7bd17063a43fc0a9079f899ef82124e41d653c773189c1f8c74c165a7a7b783403886933a59a67402afd0d30bfce374283a1fbbc7a23aa1a5f64cc1a659f756ce782288d35c70c428c19be0bfab12306519e554707eda84208a9b8dbe07b64bcb994534f2ddda9b528b6cc0370de384262b295dff47ea532a2cf3989d8c0c7a2f9522de4307b71dade312161cea29dd5c48c0743c759cbf69dca0c43be6e4ad0a0e1847a33b02e99e56b1bd601381d2ae98fed27b81d8d543df31f2791eef1b643f2a205eb491ebafffa20825af1fe132957663678d7a0d80270bc061dbbef5cfdd914e2ff172e3b8810781eeaab27afc67f305c6c66156e45a88b7e563cd54b411ff1d7c757d258bb4f2b4dc4c3a55b726321e4eaf36455ad14ff3e0e1e69ae089dbb1333087271ede8043ea85f91b248906f7e8acfc070a464afb9283ad71cbe96ad627973235e4de7b29d9efedc8c6e503c194db318ad6138a923be4beca3f07fe5b1c1bc31014be0a5ea6e851a11ef8121e3a0e9528b6938e8a2d6cf193d481f99c1484da56a95f0d2b0f9a1b4193534865c09e7a98d4fbf33c8e608cb757c2ab70985c2bbca695b8bf0c6ebc92f9e6aa8eecd6cd81b8f23d2c65149b3d14a1257476dcd1dccdb80e976f603d77fc5897d51ebbc459521aa00b6f90563474af75768a502ab3436b80383165bd1ff1e8f12ca29c4360017b791f20ca7f3de5dfe3ac5ef3c293c0fbeed7f0fa9834e753d56df379f4afc5bbd7df0471389a12ac014469177bb9c99276a8815a0500d9f8090", .None}, + {.Sqr, "-90659aafe680be027189ab57f27f6cec06c158d092c34ef651a5d1675628297b504fdf146c2ed37e28aaec40b3527f43da06a460662055f88ac8f5def2f00b715bc94f4616a5e1306556b9d64bacaea4b5955e63150acfcfe036de2be387de2fe306b5d8995e25a5f64dcd2e3a30db933c116f642dfc57cba91f31e72be0c8c9886b9232c45b8840f60c70873b15b959ba89ce06ce7e4e201f4d58c7557c84ba52a8b4b92d299a18da02812c334a136e3bdbc6781ac2f2691571e260a6bb22241436291fa4fcd3424d100c46530b5000d177e9cf43ceb28469d1f86be006228ea983f1fe49fccacd81ce5fdb71ba796441f6339e2eda019d00367910543de45d27985442c789549c21d6133b520641edb35b7bf2134b9b3a011ddd96fe459495d9dcb43756cfdb6f43dd98c052bb37c0eb23c08cc89d4b40897f9015a3e7f64a6fd0cb1c9d1eaf8165527bdde3b2ee38faf93f8542f9084f00be88c29fd0126b495456c3adc1ee0149e6760053bfb13949b7dd7dbb2b9e6e2bef8e9b5027a5b1e7ddb9a01822a8941786efd8fe328f599fc25bdaf0a8030a25b980001e8c058cf35486e5d82ffbfe718280912315ad272600d2d4edc4877485662e2d47c0f4a4599832e2927aa2a91c89b4fee538b13acc7c62e33758a38a4ec13963530f5f7f8d3d408db82e59bd3751fbbad3c21f9a78e3b5aea6dbae8e5d54a0677a58ec3d", "ee4b239b1828172f7d5550517fa3783eed763a6c8179c079f96707144ba635fc2aad4180a340881ed980653a316db35530a28646cd018ffb3371783744efea5d016eba8e4991d86ada7ae68dce66df91569ed7e631ecd5be31ba7fb41a140cb12edd657313dbf522a17fd2b8f0a941655310c017160580a6a66bb5cd358344c7f3e5b617efaa064b0cf551f2621c7928fe03af15e82478caf843b3587c00cd51fd4d0959309208bcf54e2739ca9e27a358d248483969d555bf89be6862cb5b342b65659b8ef79e170695331b7bf52143d44129535a2729ac8370ab5bc4118970feffda75ea612995a5412589f8c5fc58014875db2779d0301570d51110bf2c4f4045b2c45b7b01ef2069e1bcc7d8efa80fc86499a4eedce26196a461211041bce6347bcf7b4c8f34b4fcee003a04df436642ecf4a603d85b2d926bfae9db2511337ad85c2b19e935d7018dec74d7747fa75f6d7dfb0d741f9a3c27290ef57a08989aed01c3b0904ee593ed54f464b37e242009a8579d281eeea920144e018c479977bbb4f0ea96536164250ff79224082427c02cf074ec21d18c8eca7f3792b09719202680a5a341efc391d091e1886441b042d256a6014238910a2c42e8dc88fbdc0ed5c416a64c358228a61d9b02ae62b749b908ed9a2e24bc33132f5e6c25ddde85c4deaa88242831801203445d6acc2a2301e6197191335d794c227b2746", "517276594f94d18885d2c57ff40f4f3005a13f13079cc60ba5cc67dff4910212c20409e588059c3f676d6e288f886f7e2a1766739bc88d8375316eb42a65c20beac37e989e15619f3d01753b9f630a6fd3017b89a35d0f647dd4d42a9c640238240689b2e0a453ab5135a486f88e40644ed911b0e6c59419fcaf658b946e0363418fe81fd451f91fc59e1be21406c7c487e91f714da431ec072fba67e2f5e73d104c070782d1f812a0d9d58539f06b6a3439be9106773e1d70a4bb872e0d115e39c4eb9c838649e841c603d61eec5d469f87d1000e29c5e1c4e4a1a24be38576d6b4abe2ce0c9849e4e0e04d4fb16fa4e3472134f6c62e0d1f8fddf2e2d07687c0f5e5aacac515126742fd64facf2c4fd63fbb64ffe2614411835d7aa5ee58018911b3401c2aa0832aa5b5a5b4e601c8e79d464801001ded784ed757692bcb9741104fce02571b2e21804e7d7fbf8d4da05cf4d50070547560c9d2f51f6edaebe60392567d1993025b77fe6a249f1d5e32a6f943de23c9721c2372b6143f2e1423c2ffee9da13dfb92bc9132b6a9a33b81fb88b6438fd3d3c74f4fd9f5c72a8d095e47ac6a55d6cd6a18f945a17827d058b55b3ee2d156a4fa385cd9e70a4f78c0344b6673f9dea5f8cf8f4ac5e2084809fcdd686e115fa08f4841a809c92fee78d4b57f1c86fe42011eb08ce3caf38135ffa643fbd2c8de8232d687b39c257ba434f1f0a2796d82172163a7c835d6b85bfdbda033ed0daa15b8d2e323372563acaa302f2d30344cca2b5636f762a719884e202271a64c933dc7add7d56f9b21163a02aa46d3aa96c19b2cfcd5c462c5c10562f3b2b0baf9f59dbe8a1566153e7b775c11780aba364647aab4776b87120b884f80d5c60996c8acb5e5958a1597b884a53662f3fc64e840d118f072bcdbc8aacb53d1d39e7038e4f195752eec217cc3ba046f9fbba4186742af738e9d88591ec7c8a688cf52f4bd886c1fefcb3534cd39d8320b2e84283cd3f9ed41ef6ca47ba38bf88aab83b0c26089281e63633200fd3b486b7c665d97ed0b9eb0471418ff14a0d37dc2b80198f33f2771784ec36b800dcda3b22d36d395680f3bcb41d6e754dd3954b82ad79d83841a0f74e779f4a597656f8dcf6a9a8ee1965944f2045eba7a9d46183314bb8d22cd069fe56144a8d9c3220f08e0f7a3ca56b72f3975231abbe47efeff7a72352da9a0a45fd9a572574766e4bf386a31cc9a0a099fdb7290fda156fabca438a9139d96eb6b44b376897343df6bbda12cf8cc6a2e06a214f81faa358edf2574d90678972707288bd7770326d1521dfc422abe79cfc3d1b87f669c06954217a6e71b841ef50afccfa88b7f0d89d42c866207b8f13c0ae57edb3c8630f8b92e73358971f81e810537bf153e5a9d0942700dd21a5cfb178cc94110bf75686e2f5b392367f08689", .None}, + {.Sqr, "2be5350b38ec3d12399a958ec0c4cf2b66d8a46dfd4a6d333fc8a21eacf6b2afbdd0769f86f9c30ef7591cd574095e3017f9891a1c36c7a3240a7f5ea91a626e403ca001480609189f164c4eda89cacfb32139260f692eea708fd07794d893b393111c8d28e5b9e21f9b7a0b5980fa54b265713dac3e9ace673ff8303e913ab767eaf3c80e335ae12c2189caa6d904a92c4d1810e7292aa94fa9efa010f4d775fbde858d8ed2a12007c9c60e69a56a006865ce5e49f21e9f6e315389faf15f9c78896518e0e2d41cd3443f6db6e192f08990046e27c55eca36267c01e9e312814368b81dee555f792887eafc3f5de7697b36339a06b140d810dd443ec0e27083a20ed1a2ad715a40d705679dda298b572ea32d2e546a4f5e49c5c31c5fbab1473a49ba7d58d68c16ee5788be7a85ba52028ebc0b10176c9b19139fd0838d2143f7aa70999a3bfc2d1c707a7c3358c14aef1647727ab5cd604173a273fb203bf38635cd00b8c0c820f68d36f63f94b68d31bee93c86e525a107193ce8e6832531ca6e6530710ce8fc3fec0e2d37b76de4dfcba5b96664daad56ced81a80f6034a884dd5e80a792430bf0b463d85853b97ac6e071c469ca29ad9c6340460384e5245d88601ca6c5bdf3017405bc31c5a8e4a9c09b0258b31a194fe90d86c302b3e9a3da4c74648f22f32f0f1eebe83292682f67a674706e43d14cc5b2d8783242d", "68214b2b6bbecd6d1a37e70febd4872b1c24d14b875b46bc88bee6a2ee8f992d5a292235832f76e0b3653091ae075e22e2c358f5222207e4581104b45a2f2e969a52615a385b81018911273e6f1095d673d6920ded910b4d294644397abdc960b567a955cc635978aa896043b130805315a139ee4da6d3c44ec05185392c37a218ced0ad8f85113be83fe7e44615c846c0bf022848923253b1899465a3a8bda083420b3fb940e0a5ce9040c61c05b1b09dbe5118f00180641c731288ff391588f652898ad9724d17a8f0e85239fa629d7ce4120cf53d73af0bf178334164a406dbdc044d30f1c6045be3237d814b35982a84538f964ac81389788b63a73654cb91424d52de877a2eb1e346f1152ae00a62701fff35af3be0fa0c6aa0db305f70dced1eb9da9c7146d5f4badfb5ba489ae10dc161325e24af1bd25cccc7045934f7e040d3dbfdd64e7012f40b05155f96a9b1bd88067496c3abbade67548e0aac21d3a00d244960385a0e9cde841eeb35eb188345f24be7752f5f15fd107b6e0c223c99125ed6bc5759bae5eaa4ae5ae8f1d876f39585e6068403f4daf8f588b0355048d744f3c788937d85e0603ba07c31e575856e8cb4549d7e3aa434942ddbeaf56c91fe7e9fdbf4c204349917f72fecea3c9087134471667bb90ce231d4a2a8a4b9ba0af014a72f13313f4939e749f19f8c623ebc82b15984b87a2e53d73b", "786cd09b630d9392433fcf11cbc7afb4c6756875ef519b241d39731d3821b2f4f2ed5a6c4bb3a4e25fb975eefd9a3b897bb3f5bb132c1697935e6536991e673ccd25433b961141f2e589b5d2dd0440081d6ee1b49a99a421fdf54dea1383c73f7da6c7d796d4f5476b50b8773ca3e26927f078d2fdedf325bbf59431ddc098f2bd059cd2a0b7ac8636eba81c51dc7f41e006dfdb3f8219ae0476247fd836224a84a2b03902478850124d2d2859057db53c43051275d2a9b5cedc3b90900e0a34b5e4eb7f98d57b05ea760f8d9a422f485a65f270fd2e066970965dd018e4a3dc9aa63ae253f3b1b69ffb928c95241de447d4e424b5c0a81b97ddfb1b5cb32b22dcf51bcfc6249b4999ae11bf0dbcfbb82f95fe96a5fec8da391f4ffc59eee494289c4feeca5246d567c25acc25dda7f9eb47af216e227b4fa568edd779e9c883339e6244abc59149e2136096b68e41856aa3c4e42737c856dc9a046aea96401a1e3bcc118c84118e4b8bc9550117cb00193cef4441c5a729f263ed54b5cc787b0242bbd598d81e02aa88a718e467fdd207c59231b1738b8b8e726e58e1edad8499816be8b9697ccde94ac796f41b42f6a460f1fd43be079cb855e00dc834e247bdb8e93302002b0400f6a1cbde7bba66cd33bfdbc7f7457538c6980e644555903f027a8aec086b14e8661fb9c73df39887052b2744d149ce86b10fff754c9b1bdae489f6ff0e391deb31dd1ea7b1cec4ee299825c1805ce2c46d8d46fefc9a73fa37158cbe505e1bbd617fbc3f82a747f5be676d61cfe3edd2c4d17e4d009ee2f3d7feb38f8b883bfd940a843d4f1429c1e99d1813a3623d60e5e6a0fa8553996cb5c51af47acbb0adb3a47f96144825787f5b4fb3ea772c12352a56d22f6d7f2761080a70f7addd8c2ba790197eb0e506dfe943c36d83dbcbf86838493a4bd58b44bfea1903113ce9fbe87510e1a5cf06a99c64d04cec0adbe87907487826b3adabab677f7de01eb4145790e0eb2dbc4a9463fc54ef3fbdfae216360e2ad4f47f2ceb3e8b14f3598e95f5249437de7de44e383f7d78d54157d3134dae93cd3a333c8f5b120d3bd12ad4df2b8b3c89d71c73c6848e97eba0f28a40685f9c556b5fe39b5ea2f25d48fd3885395296d04df19650faa1195859d1956f3d4e2916658d8cbb3523b2fba45837928acdb96348f2a246d8e50e68ab006282564ddd54f21e1389802a56d8a0de79f11b6ec20dd457de1c1bde416a03d2ed57321ba85438963925f0657d2d1e80c816b1677ec26446f60e01add6b222f38138969e637e092f8cbe0117e1bbf8922154b8194b80b9038278cc132477c12f3fbeba831737db23bc4d5e5d38971dcb34fa32675581cc2225429453c9e363af5373e422b0051c88534d4bf7efc0a4d41379e6af0bbb5b94836e16341428ad7464927812aafe9", .None}, + {.Sqr, "-64eff82ae2f762d52d9e84ba34d2cb5cb7390c00102c5a3165bd0fe7cc306d68b126a21ce9f6b576632e84d4d846ac82f4ddc6dfed5b70e2d4563ba3d0221b84256f95649a8447afd729b5357da3fd346f81fceb63420244387a5d8dd04fe2ae2241a5b6349f64a07a158b01ca4408b5a6b28bcbbad6255b88f6bfecf45d1e86fd29104baa0dee523a2a18c94388118b698f94f5015f2658bda2baae0c056895c29e994a4b3dc2d24a18f72b13de1b87279e7ed5337053942c9ab6ff2be69205710113446db7c2cb8469e6018c0b9be95d9b722829b2d521a70cbdd883be44d40b3066c69f1173b2ea96078dd9a1c74d2489d16a704f307a813e611a6b415b3a7a902836eb6306cc46e296424165f0bf98a74acf41abc4120956d1e5cad78453320802aa907410e8e9093ef93fa9f8be62e3c3722ff1291d7f4f2e7dd9c6e9104beb86cda872f8d8cf3ced7482269a84cefe6ba8d443185c0f31f8783cc277b45eeb0637c9a53674746d6facf0a049a0aaae4b6153277182943374704fee7f9b3d00eca2e8cf92ee3183bffc66c867851adcbcc9de9215a082a8bffcce407ef9b1992a8dd8b74b8727b9ed0aadfa6fe103721dbbd6e99fece44168e6d38fed0e0a82f817056d1c3e5820e81852c4e76abc36f9c7e0c55d520cb11179fbcc2a954c46ccc4c399a236710254f27e78614d86a3965e5545bfc41606e878f8fd1988", "f99c785a2af66f8e79a93a327299552fea68456d7ee08282675efaa131b9a50ea7c4962112da205eeaae3f488034e537721e78394dfe33931d9ec305ba88e77577ae9d6b18c9bfda7f31b1ad0fd35e86703fdb3cf3a4a2327f645bf144a427bf467c9a88963bd5dee7fc70c28df519b13cf765d033af39fcc257d060f5b82f68a8463e215a9877223b12ace65a9f5ecfb888fee60957d67e2200324e2b79ba81a0989acd0ce3df811ff7c1fba7bb17376c1f7c6b04491f2978af5b37ebdd27cf6efd445b14224fdeb88b9f3b20ef5454a231bda6a4b2526e6c1245cbe657cabf07ec84dedf5bf0d4c0e67fa435903dcdae8960370902bf374debff2f7cb8ea4d6fdecc0d41bdb25e86ea99de05ebb35ea901b3b93a3d3068619c97464e8fbe569be27814a1b178f5c399e09612532e6d21a12a123c4608a050cf1fc7a9614cec84ae268037079e5c7071a9d688babee9e945cda0f81eee06bd8d5d5ff76dd7f87a494683fbbf09b8cefdad1341e187ab45d39863909b9795ff6f60625fd80707e812751cfb7cf85f84dbecbf2029eebc9a527e33332b1d4014790a564b1663e403dff971fcf3f04cc86b47b4eb3d400dfa80640891d27660eefcfd301716a2ae5dcd01fec47158b9321812df48817aeec0245bc7b311c291e6937b6ee6a362ac9c429f70cdfd0815d931ccbbd8b88a5795bba422d3d3a1c62a7bd5b3b41f5207", "27cc5ad2d1f82e0fa7923593a8317699198fb44216d87413e19a2a967620786f3e6719af78bfd131045c289d077a5713d847eabe03e2d2b887152b3c6768a1643f13f73c293ecc068de1c21c4f510b405455c0c2e7db3e1aa844f7cdcf0f0ea745e4b675fecc0a74c98496d153d1c90e8224b8a0db2ec38e229cf5d0aa991e4f0b8d4a3f267a8fc41c890e802d59f6818080dd09f2caf89df75e353f17969d629d1ddde710f7ea4335d8a01a8c1e3302f85923d5f58271500fdf0cf8269a99bb5a47fb0760154ef6743e5a217718f89cb47a16b9cf48ca9b90e9c2942a4907ceeb0f6829417d0cd45a79099005d319cf7f7676464e74ea62ff932533a577990f0b25a9ad1b52e3e19cf685a13d5d3810c13f5e65187acb496f46c83ac6b3cc718e72f3a2e01670a369932e2a8825b455cff85ac933c425d9e824a6fe381a7b6532152e9635074df1b2d71ddcdbd06edca0a43382f0c47fe282d34fc4b93d87300452057e929f4ff3fb6e3d7d259bccc5864c0c2b6b6506168a6614d10dd0949f12bd7594eb07e2cf95abfe0cfa271afd9f7830590af3d09e9195edcf0c6a561a38c9a32ccf951bd82a7a34b9fd4fecac2cb97df9d6323ee2ffefd596f955789c2c5fffb76f0f4fa9171a2cf328303fa0bd96ffde5cb6b0be7fa2f7083692982f59e0fa0065d049d8eca4af30a6f44b49d97218b3620c037819a50f58efe08ec982f1146c925e899264142ce6c777920474881652f04dd7f10f70885988a1ea1a6f33be05f3e629210d066eb984e4e3e13cf11b8a97d64754cde9f10e6f900806224195f6bd7dad01a42e09dae90a5940ad0e2a43f848ab772a44add7b59d2c03d4a120ee87390d4a0a23e2ce0a3ece7afff4eebe6a03c89c374d55e1d3fbac966a5b54fca04acd1edb5a579d0c85aaca7b49093c8c37f5d174f697055fcfca6945ef693fb859ae341680b0318de82b1e61867ace910b10ddd9c9bbc288e6f179ff7202104ab8c30637f18674b12b448f96f3127e0c0bec7280e0761bcb677d8163e3c5d1cef6894838565575cb6b229a875093395ea4b9682d7eec81917266d35192566837092723d5d5d503f9814a7bd4d47350d0a25adbb378c22596bf2362e57c196177f5f4cee955faef2092e21e94dd27744f20a9899fa861ed8a47d9c3310a5b5db4b94098aabb2dea0093468d824b246d5de592d238fb66b5d659b35f1f244d5998dd39f62dcd28572174bd83d41b5657034c6a4a74a5e6a939e28187089ce150f599750d05de0072baad45fbfdd244ec1e6632626a081ae074ff5bca2564eae496dbd9941199c0de55c9d26be6c204d357345a33c11e55c5b007de6e0b86e406558a5602d47856bf3d5964a39c5ffc3a4b8f7dd94ed1098d5fcfb08cb9741dd6397cd436c358e7537f4b96a208e6182f868ab0f5b019cb32f95bd840", .None}, + {.Sqr, "3b9404e3640468c42699a4e33db6fed5ee626166fdc7decb4335feb97592491c6d1aa3c587a1e0cfeb7a9f4e63d0168a701429390f72ab54da5a3d73bfc67bc4dc823799454a3fe7e659b71b21c32c99f609b5dd22278f51df63282393755cc3dab23e192c6b7af1de4edce40a9ea1dfd8284cdf52f4401ff4f55e42d3cd2c011b9f8ab92f8c5fd4f7ca5781d2b75f2407081fd0a696314f3e2f6335f2bf58c6b092fa873c301837503ad6f33bb59e8f828200e93e23dac3a24bbe7c7d54169ea79c3e8e146cd15ae86603853c30244b618e95005ca42d843933f1ce8b1b25768a2122625366e86aed4559fc5d06d2b1d532bc317ecab4b3b0533b9329742c0f9c41ca52430f73cc71a6d287e85f68e48e7272d698f94ef7a2ae791a0250256842358327ca0dee1cd4ccd3b06bb4e9ddf1a3ed3c489067cc042206a0c5dd4e4fb156827494d76164bad5c3b07ff1fa0d486683a2719f5fd1dd22fdc92534d9ee1f701ab545f196c814160f610017e45df628841033dcce058b392f3cf40bc7192d740e79ac5a67b8de40cf5415f466633c9b81ceab00f65eaf4b6b3b6c57eb4cc82a300c37f1853fc32477b2395d1135c8e12a6d77f9320eaa5ea95376c204e18f3c4f0329cd9966fbe62dc29b1546d333cc28fa4972bc086751544d7fc323587ff41a058b577c4c2c511e0c0f32b79c49e7e3ce8a6ad0035458d5b6e7959667", "5ff69a50557aa53dbdfa4eb7336dbe831cf4865811c4f694f306ddce29a910ca623b0385aa710cef1a324efbdc2a605071bd7ed68ce0ccb4348b0bdcfe680fc5f756c0c21e4852040029efbea754295964f313ecff78c4b29a0b05dae939365a950f406340f083499ad30ef8d4976307e7f53d259f2838d8bd2c03c901ae0abbc216fc42c00a9b1087c6b32dc639348f59744f737fdb52b02626dfdacbc57a6aa25ac5b81440fdae8c2c34c1ab7b0336ee111702eaa5748f88538a4e8ca0908614f75ae8f25ab6a8ab171470dacee16051f458672a7ed4165711ce6d67f60f772d6ac710c6e94f6a87f5476624c6b53d6c4951815618dd265f59866a9fa8ee505ccdfd29cc5cf00e0a0123364fc3ac1b36bd17dc66bfbe0a4cf58d1dcabe02e9d23621589410c9dc828f7c45572101b536013a912371b68cc534759a40eb1a9d4e1a47c57cba30e8cd4ae7c428233cc4c4f21bd82933a8a7e92ccbc22e1c6a4b1bfb8780b1ccac5db341210fb58e8550b1c731b1a2eaff13833896983ffb651911093c32c5299d074a6812e4394b5d91d3a46eac7667ee5f30533adcabd6d55b01d0078740460aae0771c9d98a2496721a0e2799443bb75f763238d33430071858a35dfae98e47fc165d57ad5672992345f60b5c515db62c64b5795c8d7103b5a6b78e974916be4df3bacad5aa5bffcee655dbc1062ee306bfef82106c185396", "ddd8fd6771d927e36c2d2a555fc6d41141b95922de9e5fd2917e036bf75ecf081593452d10b2d3609d93c6221e02762e5dbb2f8926c350f1ccd8b6ea3833fcd354dee87c45e54d119a51f011cd15eeeb130040abd749e617766ab25ff30841d608111cf7abbe6cd5d9512a5491da0092389c19ea2c43ee8a4691540320545d4bb053928fc8da7c5eadb396d373b43988a607b7d143421539f41b421a40b873e50e1a69280ae8eacbfc9f0c5d69180a0102d73c10ce477e5bf9830509a91f491ef0f06a214ff8d52dd5ee24d3d1dea50e9fe78abf18bce29f42906c8203a8684bd66efb8f3935db1061a4bd9c643d2a2f538ece51a0ebeb434ff6c08e898d28ef09051ddd3ec0fef9529a693faf1406fbbd5bbb7670193f5f124b12ce8edaec4847fe34f6026d4e9ddfee39f9a171d0b3081b174a906e70c46939fb97031e543f649e68f8e3e8ef88a460a9a7e47098aaf7d4bf9836e53fab0bfdb85dea7147cb001fb7e0beb7c99b5caf87267ae7acccf92ea9b99bf11ab39fea9e7b52fecab0d36a798cc0b86c88608da23ddd51b0ddd68228ea94aaf0c48cbff2cc9b37fcd7ce4e223465f5ffb0ec7b647d403fd996a8800f80d2a4e58e8c9083a4fde42b36dc7aac5a72c1510e5cb488fe316e8f7c13d3997b8d7907af669c75311d26a69f3e6c1e54f8b7503a4a41c9db8e70a7e46ec6f7fbeef845ba30c08102577704f23421780cd2269e7a55bc2d9db598bbcca1da4e65cd0e72e9894e43bf196c84be5828395a91adc64a8153bf85cb4bfbd5f81c66233fc2da53985062f446409834fc14536ee286edc1bb43d7310799322c93d29225a6c842e4fd99b994ea111b7fd5712be4c0a4b130e46e617244f53b468c4c9c6612c9e1e5d5ee03f8bd262699775f79b65645cf4126f80d110cdbeb83e5581b37e35299d8a7fb0ee884e3f90dd5ababe52c6d40d99aa6b732b06c01f7c50233879fbb5f489bbbb7346a837499ec7e8c0a23e158fab85de966b0f500acf31651106e8c7c7a95c3ce8644b6541ad0b2e263e44af9196ed8012f0365e79ad4f785b92797d4c1bd394de63ad2f2a94cc0d895cb269595e4fa3ff0aadf102bbc8fdcfad44aa7dac050131c2db1807de23b9d60279666f96f5008f233fa63372946c7aeca9b189864a4a2874b641d60cff69c7545004a04419aed825b4f78d6d6c2f9925f4e47a0b0e777d6895e2c42a702e66f363970174269c11fdfa93354667241245d5a93ff1f300c86d59d231dd120303ea140603af7c85bdf837273a21b2807b3752f0c629c06bbcb542e6cf6e09ea4e8b5f41f9b50c02caf4bd657c3bf13b36e9a80deab751d466f2042510a1efece05f9ec16a3f6fc641a03bf59c7c5c6b34ec15cbc6b052b0994bce68c804bc816b17743ed7da9b15b2ba6d2969c7a86b7bc358280205488d4a4e42dd71", .None}, + {.Sqr, "9c8b1f1fda2fbcd93fc0036e9c48bfcdd0f53bc72d2656e47fb45e193482f4071550429b057c805fa7194d3e9b9d00d607e5ef1d50cbbae309a0c24162a4e82dd29ba5b29c38be340bc5cc7f7434c1304eaba4d92f5ff40e05a9779adc25f2a303cd512ae49b2debb1140ba7c4014fd0b4ddbfaf49456cfdb18f9ef6f80b9831c654122d594a85bb6e690f46544de9d8c558f29269e7bdd9a3547f90b1ee4865ceeabe9e25915d9989d45c4a60843d0832af348f80c67cbcd3e08337c4a6610b7d6be36ae915b45461e17fb8c74913755d71030351dbf3890789f9754d6377b5d31fb608908b7ba762dd911e3670e2dd25e9805d327b1546a06142f16cfb591adc056b94d0337215a24b07aa601d123ff605908d98efca1d6a65b44152326f0240df3cdba8336247298ff28b873179f5226fcd1572ed41f336171efea92d1b1580cc05a7e226cb83dbcbb4c8f4fb2c254857dcbd19a6b6dd71859f94cca01a2088c469bc4b3f7a0797c50386651012506c6a264078cb95711589e9b1c59617193d56224bdbc73ad61b178b024455ff1f0774f810beb3f1f3e5156f29a4edb5ab6f3a4ca1ddac22ead880f87cbc85aded701f8e25aa183f14aa106a1c68af80e128ab872d47797f259540a206fa47074004988ad2c549b21111cfbd9a0f346b69c310a0bd6cdc0c57360639971a80116086fe1074771e330601a37fcefeb8435c", "bbe99678a54b8eef89e51acd89777ea4da3ea99992e1ebb1303bd437705d4c81150ae0c0a97fe7cf981e8788d4d67210c76d6e4d93d6d84b057a57371881cb09779a69056fc93893c515a48a049e1bd27521128342a7554c3a65a005500c524ab5159244633f9182bc6e953a284bf52191d9fb81922dc8a9cac133be3625f452c6f33f6d05918ade47424ec0a83f18d83d2e3c7d2cff652e1d61303cb06cdaf5e04d71922b2572f9412a9cd36e077711e5dda96ae08240753001408d365e02ae09c059dcd5d422a37bdfbcaf4dab8a23106618a76dafa5df8de2cfc812749ae58bfbf0c4df7260f76e797c31dc7d0639d2ea94cae141d5810a1968eac8e63ba97aab96b9abc0cd957e601019e63589f68151bebb6db54fa3f2962a45fe3f6dc40551eb894035be913ad439ce724c7e5dab7e187b79f9b2828325814582c82fa417bce14dd0137f51f661329ba564a00ea6f88b25b7ff179c90b0bb740d5577be29dfee4305619ed0a9ab652242f95fe28f36bc92722c1dccba14c8786a02755e1a25bdfa44ef8b301ee165f953d5e7325a51bd963e6adda4b325825c57c4943b338c829753f62640e920526bfe034b90ed341700e7d3399c1eed1a38e89572ee5b9ed2a07b7b9d30c5031438a7de01a7d56ef365222c7487056c4c8e7368769b1d77a471634bbfb74505d256070c67df0b0af1b57175699b31d289f5189d632a", "5fb9d989a249d8cdfadeef495d943bbf6577b9c4029255600fad2e57bf24547217537ce06e94973186427691cafd3886c69945a7e9df20056a7b3853e7d0db16362ed80799a12e103bab930d4b2ae7453f5e65a061948ee56a499c4b8c6800bb7baa9d4804cec1bd7240d45a965d2a2c47b8beefa97cafc8cbd0da2b7d6c57d64a55e2a7e7bd63ab0d4e046b348567a71c0ab71328bb044cccab4c0cf87bf0229f0792d66f076a9c2a4616d5a0172c5fe481120ea49997adead7b343696afd06d519d3151f87b52c5b6d53bc359d7695e2b7d3e6e47cb1fae0d8e294a45bbbb68078ed8d5d0d77ff7d44bbcf67313884c8487befbce726215f56f54aa40cd1c9b5d351d8516c4c955036db34653ca3d2ce1c5eb8bbf3b9076ff705403dce6270fb40197af8eee7aec29b561f2cb11bfec02372c0683ff477871c1e5c20c0d507ef19043a80753b96bf570c1063486b6a8dec08f1aee7bed44abaa1b4829f13c301f8f94d516cc739a165131abd2fc329da22f0b2a05b2b8a509820897284944f3e3a7166cbc402dad8de20895486d2473b5007997444b243a3e0d828e3c69c5d9af2ce28c007a1fb4ec5f194de5399fe40171ddb82620c42f0d068ccf7f1df8b8eb93191d6792780308c68c6cfdb8af3fe2ed933074281e8566a771959768af8bd45de538ec204585aa98cd205afe6a90681682819b997e2c6d3749b9564cdfbe85aea25d65fe02a70714dccb4d988c5ae2dff08b5279415d43b88ed3a29e925a6618020d92d093ca55ffa85aef5cbe75e3292ffc069f14b314e4936218d2067ecbd3bb7be704d8ade3a4bfbe8e1a0ed92a2930442bc8a2112ef2fa09334534bf8649f232cec36ad951838a9e3837c1a9e29354445ea15fc6f30560b29f9b6bda835a80c181aa7a04d4c6b419b0cf763d040f7aa78d8d1e34933d3bf4e83ef7c3eb61c907e3814612f1fe88bb69e1913ff68abf629a288a6cfca44849dd98b46f4448126668791a71a731401093ca4ab95ccff38ce7b100020e0e5fffbd73d2c7ef70dac2e948d6656a463ce808cd0f10ce18d3aa8d1feb042978c02a19f3fb9010abed2aeaafd1c1754e7ed1c931ae5ef4042ceed7fd911bcca5d5bd722c3deb1066951f863690207e6cc55cc297c3b53749f0261b165d6476aebfd3e12130c0c7131a9a62e76be584b5c95abb37ae1addb8fd6b515397f389f5582543edb7ea29006143f27b0f6fe104cf4792263e93517ac64938d6b5c84ae26bd96aeb963483cce906fc811fda6e5ec523d6d2813c7eadd86314e86f14d2e33b5c021c6140f446a0d1b9c5ee983276acbef803676de20fbe7c00d0a42f54c442e1813bb121cf400e9daee4d3768687d3464d233be6864944e421d538402658bf314d6595c0d79f2740945b49acad26c7161ce948777e4b3cc4c6ea7963ffbda5b75f94910", .None}, + {.Sqr, "6ce076216b0a1a2f4b917abef8601b8888e3f2af00ab4a69e9a5ab1760765dc767ce97196df99ea22aa6f3a77a862f3aedb314d268088687adb34fc26bdd05a4f874d91bc1af36c4a4f74c9d1e98d2c0ce266b7a684ea5c5fb73ef8271edf56caec64be25b7bf5e842f057e17abdb738ef95ca836139306b05820c72fe8528da719da221dc247090bf95ce001eda5b2fa9c68ece1c52f2c2d986a8f5e84b90db866476d3cb85b228d78616e5deea4c9aff5f06c58e7623b76f9e2c5ee9d77a6cb22b8acdfe8609ff3d50a3cda36cb950824353b4e204a775c743d57382695bdbec41ce3303f58d55a1a2b24cc5e719ada2454e137c55be964bf3d430a803a047456034ce8cda459b4244958564b051c0ba3880325cf7c54742a01cec4f8712ffda9e09c4690e7cbac1a37e752578f647918f2ceb850246086e1162188305254c72c569a3f217c1db2af9327efa606e76231e13ad2470edf1756c72ae8df1f48a5898691fad52cbce0b7582029c3c1ded57113f05ee8f586c9858702cf6a5f7d6a06c588d607a75a82fb6911781c775b640527371d308aeb1ff65a23a8cffaf81f455dc4203eb48aea919b1b3682fe11a217f9c274c9d2604ca4f75f361a4601567dc818d66506e4e6daab994fa826ae6700668c95ebe2444be480e080d78000cc58f661db3694ffa71284f7403c417cd69bdb04c68ab3fc97c11faaa7de1a494", "dd67f9bedf4127208ed1dc5aec1755c89a9c75471ad452102cdf6148826279ff86d0d413c9a5f62a7556cda0aedf55312769fe13f6075f0b5ebaa4f80c5e66418d07a66f1d6d146e94ed3d0359dd8919fc76e5aef5b0ee8c0f749218985a20836f2c052d0f516f22a8aad16d6f24721ac368520de25e773019b13cef9afe57fad9d77ff6641feb82833d063a5e309582042ff672ff52e2e8a7133dd48a1c946de97fae319ac164249cdf05a82989f050ae970851a16bf67321c2540a60b236692de67977ecc5af4b327ca092dd08b5ece1e6bf413017570029fcdbe264e3ddd25f6fff4de3effd474d94b44ea79915b87752c45437f318565e711f3c2ef48ec395498f9327b2534d2077e1023c1aff02631e8bc58d112398e03b35ef9ceb00a48f07bb7c74fa8f30ccf0f39cf2147a5c2a0c8d1e830f8fe59fd12a5f626e97698fb3bbfe19aa3bc4718601399ac0630e4567f50560a0cb1f854da94fe2b49d9a9b977d6a32bfa1d5e37e3325bff47dea65494d405c34c62dc9361b8ea686bc507d441eb050384092fee95c302536bda17ae249bb254e3838a7b2c761bafbf7e399a44f874ae6794005942dc53c6e8345c3bf290b31300cbf31bd7e809150bd3c5e1dc96941ea0195fe89b4ae19ce866a1e556b1c010c620a85cb11ef380d6f827d6f82a1c5fe13b91387f307d190baf83272c6e0211332b1395e0a3187bba83b", "2e4e287b234eaacfd006ca4d1ff899afa1cd06c2f802ef17e73b5ff2993a7a7034c35152e3a63a583222ea8e43849b9850698933ade0f558296b68e85aba804e2e1ee2c02a5d6aa4b28251e84416dcec3c8b246b570565905e85da592fcc9f2ac2de4f5954eee6c714fc57ca56ea82a229dcf1d82289bbd5c5c5be652c5003e818949f235040f63873dc1247f75e4269d40981a5fe77f1fc1144149ef1c6b2e4ea3940c3c991dafc116c22d9f7591409b0fe07e75521a4acd7489f792e3f85247b7936934137e9592f58eaca51f0388e8cd1890b9325085c49f9714080999c8216939a79c08e5fa692e7d0c6bb04d2b2e08018cd23ecdc232bf17bd76e38c9ea3d064faa4c8b788861bbb98a5a1ac5baf679f8477a4fff499940d885c8f9dad346f8948afc3939745984570d5b23dc241e39d4d0729eec0d936e9de3e2fd8403148c678cc341b2f9e72dea7f5002f58008bdc41c8ca857d898e6ba3b9459375c861f8b3344524f265177b1df4c112e7a29aa03c84a9f91cee329530a0e6029db1674c2533d92bd8031f831bf8537a44080c032c30cb4b9aca79facbc871e9b7e0a08c3e70f61faeeba754462a77130a869f95d367b62929ad24dc976ffaf65938dcdfd1d98044e5c83cea718eb52b3367c3cdd1f7a1efa750e354a8f7c5f1210acd2c5e2071b5915a4de7f57a4a57c7828c30c8d27d37a58c8711469b5725c9c8d18e763ab542aab9752966f89640bb8184de4b24d9e689e21f2716b38fd8cf6adfe4f73ebed373729f50895e048944b0ee024516e53b5c441bbae77fcc1af7824237f3877c2763af3eb648c872f02261ddd96de3a835048ea2b25d79745d71f3a04d8b028dfb040342340318c32827cb472281cf07bec83db6fc0d949ec528bc9cd00292e1e20bbce8cbadee4734a174c56ddf03fc2da410c34443ba6f55e2c9f3e0e47bcb34fc87042d0a60ae13301ba4f924b6d361e268d4e32b4369ddd998c37de8d69addef5b49bf83573fdc25375a03cc127e177ac1e238d559573f39b186c29b8ce2e707f7aba01c72c1fdf64d811e4a51903200f49ea3069d32504dcc59eca273b87126de021e7f0b5ec17b88b1e3042a5aefe89b7612569f5849ec2b4cc1b52b19e410c9c40c74f56b6c991ed51ffb7a6d7bf8958e128dff74be2a30c760a0ffe6214701142970738861b1e8c71743b7fec14b870c445d5a4b1f330a024e618a60fe385e8ed0e7291ba5e0978aaff3e69c8fce1d9a497490d177f0809d7be110de3615ebc5196913d15010f42bfb232b37673690bb03df622f18dde9c2d153a50fe762371bc234bc25ae863723b21430ea80ad0de2bbf9769d595d5d6aa18085b9abc4987308c1b88e8f57903a0c8555ee8f17a95ae107eeec995ac26ff2b9ec05aa95e71a113f3fbcb8cdbba95aed1431607375eadc62b3df5f590", .None}, + {.Sqr, "a06ddde00def0e581b52b55a58b14ecf8a8a75dea2c215ce3f94c228ab4e6a820bb0f85a5543b42e7f0e0af1531fbc0c6e38b9e5da469300e2e47b1aba4b4b26029af5cf55d2860b503ccefaa1fdfb9a6221b869f55f6de0fdb280acf7c7e0ba21f481547f3fe189d62efc776a20c8b1950c184e42c0ec86e9a69ee149106cb0f792605940d9594b38fe32d2a58abc1057b0fca7c58487035ca675168f1fcdbd0da0191d657b232ae9fe32a20eed0c5ed5389534d542dfe3e93ab6f2f2da6f819d67ce4cc81d072bddc74ae3184f0677c6b37bdfacb6264186a9061576c31244051bd07d79bc55f061cab04c4140147a2dcde1f0637210721e3b9fddee37afb0b2dc0443843bbe56128d88323c22a75668dc303aeb85d730988886311ae00d4995dd5db2cc8b1f9931e6767b960c4473007905c17a593e833bd81ae38a08031640f852af9679793c0113f0806b5f51982eb3c254dbae7a455ee0b23a6631832f692eb89db7cc69e724fd276d176ddaf9801fdd19c4bf70dc8b77ed6e8f2cf3244c1347348c40db0687695132cbd387505cb8ad90078bf19992009517e11636e353d8878b6b1fde7f469acc8993252bc4e1f07a590bebf39295364d392dd1730f7e56937b4af6d65a874abdf03925bf47c89e582c3ad643bc570dda63d36edef17cca4ab0e5284c07ee221dbc3ff8e63d615407f5329625a1bf4675a2ab036ec", "e57740a1e7f0297d7175ffc7b578f58abaaf120751971d8c2b897a6a2b37e6951b54e315feb3acac49f4d0555ccbe612cbe03133af0c785a6973fe8b4632e916517c0edd7765fcbb7a7a6304da60256a3bbaa3d6ca80a5a2dc2f2101c93d4dd58505cd75eef99e339fa421eaebf698109e1897d90ce5d1f341845083d01cf66e6207ac8b19a95388f1cf3cf0540544121061d50a56a763b168366bca8d1dbd55db1666b237312e73415a11c8115664e3e42eea97d7235182be928c00aa493dc9ec617b12d1ac0022c5f8fe24cd337aca8caa12fcd07388f0f65f7bb16de707ba7f8c99a6e0f4e194241d48b816e5a5a7070613d63047998e8a7a43ab4346fecd0722f31e6433686338b9da2acde9967111c02ac6a4a5ac4fc263c4eb4de1a9d8f8885d505e01540628d859572874dd2cd7a72ab65a4314ba389c8fcda89e69c6411cee3f4ee0668f42ed4c2a2257bd69e2cac46db0f82ed823af9297281f9206754c759462ceee4e1efddf2acf98f05b6b214ccc63c58ed7a6a16388088a4c7e9849df5469732b877bef0c41e59dfaa051757668833a50c6da8ebe0b2e9dfdb306194b6bb1151b7f06b3ea291e53710dfa3c4ee34f67ef669ace5a8c29e8d286d95739efd9c941daba1d43f6b75dbe33928353f673db37d400898c7b16b64bf894d46d6d22845524030f75f1f4f05d096aae001f2dbd6a4da2c49ff2573d0f01", "6489847ec2834ba77b0e072cb7bfb0e78596078084049902ddbe93f1813011e334a34a959cc080aed580b45862d7bfc1522f2b49ad716ff0c45493d9857f2f1ba54ee71e41dbbf275468e171e171161566017c453326b212f90ee321e24d76e1d15bd3a8be54c3b63f3f6153c6ce7134a149e35d2e1d430d82710c49be117ec86bbfe8a9ceb26c5f0a4ad3ade5dc70312d3ad31c30a4317d9ff8e7ccf8a6b232db1b1c5e8eadb0fa1265c2c2806129712e00d8f29c8d674cfd474b3e3c83c25e5024f633415c24ecb8839918cdd289044a57af2819434e0eb5e42e6c1ae7490d9e3e14bd6c5c94fb35735a4d2912fda0a5284c1b0cd7e9293559dd034b1fefa2465edc7f83205910058ddcfc82dc789afeac526f5dafdf04cc6fce58c91b750bbfeb1a80d0d0ba48b6a645b5ed34063ec8fc8a9ecd61ef4316a4f833eee3d7c8a88dd453e377ac4bba53d5713cbe23a4849c502bf7de818c8ece398e1798057cb5c83ff0e1574403cd7052a248e3d6a46af17caf9eab95bf8a8b976345cbad95ca31aca7ef727b70832bcc00376f8d192e762055722af311f5879768f70701ff4ec5bebb3e4ab2a784d537575a159c2aa508c916a1f2384e3981af14ade1312f2dc50192eca64e8dd48c72f97ce09f6a775a2f92f7664cf4b0ab38ebaec385d6f4155df01de6ab6e794e774d59bbe1df91b2f9f5a344655187168c1e485b6833a1193397803994e372573d09c636d9e2a423788646b40ff3e988f0ab2a7b086c427b1c986806fdd95c6a5f1e727b1d6eec6e2fe0c64e2f90dae4ba9b148671b449398de0847bb64578081683aaa6aa30fa80380aadaa99891d04493d6c9c9c2aae55cf7a279e7035bc11ef92c8b7ba0f1b4f9d452e45269fde020da0e0c63a8f9777418fe0ec1632f5ba841d6fab4cf2334c537b618a4e965cae1a67cfc07afc8d24936d0900f7b58758c7f0580bd44a518bfb3f8bfd9f9cf475de20ed838a7535f8673b35d36b490803829b5347f014af92975b5e4f75e4a1e50c5a2286304172a3684823ee7abeda1e604b7d2eb858f45f14886687ba4a0d0d071c1440c36a532bf052fac277230c07b21265dbf40af23b6177361e58a6209191e167617fd459519762cd8c110e6834b2b7c407f444b7fad621eeeb890a51573c56e197bd0e794b7e4737199c94a0c920c00358e4a6b966d292dc0e2bf1e8b275aae3179235556495f28c2be510755610aa88a79e1fde990ed8edc83087233f0b470b0edd99bb8bf269edc4b4f1585e3d5dbfe53666a06184d75a7dbd472f4575f31e4a4108bd4e97822734a7d87ed2d218865bb2f7277668e55772b5436a5ad9282651521386d81c3c98b6f427d0f98be3ae4d558e926bcb97b2048e05f55d555ac26e9569ab38b2c99177a6dd75f8562c7c147e659b996dc027878a5116d14100486990", .None}, + {.Sqr, "447aa88beda3d9438dc5f83a75ee2b40976f3118b44eacc4cad73b69ddbabcd89f7537a316d4028688ee0500ac6ff84504e9bf306d42bb1662b1350202c4b876f6fac15a7cdbd076f77d40a01b5e5f8fefdc4d5dbbd1589e830683bb52f3c27dc4c5ef41ac699c3bf85042ed853da544015282879d992b34ac5e8a2fc0b1a2f84cc8e714e87ad7b03d24695fcea2e9f4dd24cd3fe1220a79b9c2be0d0ecc8532971e3d221990e398cf50233de49dab1557091d4cc1aaeb1a71e55fc44982f0d4a53d6f25231bd98967e7427a96580e5bd5ee2dd0ad99572157893872ffdc1adce5b963e691ca3dc4b4bb047d76d644b3cb11d5d5830aec45900054926e8fc4c78f447909aab8dfeffd3ca4a3db6b59d94935c1c91ff90ac504f03828d324d8e378069ab665d014a3737189c41b9ef8b216bcbb62111e1e0e803f7f97d486429496c4e0f3d0ec469af4476fdd7343d3fe1e02ccfab8f6f83b36db1c5426046368585871910bc9f0c1a6efe1bc93c22d38e3224b4212b64772d11bbb74ef843b807d385af5de8c654886f45505843e4859eaa15b31f985a252932aaeacce7db719e322978057bdcbe4fe8884da3e136221a847f52f8061adc87bb65c3626b9c839a402e010e1b3cfc601e2994cbb7aeaad85ed676e356712be926209bb86242f394dc300530a3c0910475fad0f6d84be235153f7806cde21b844146860365cde0", "f1dd1d20454e70ee593ed4c922b03a12125993522de3df35cd9f9112f03265c1f4ef360318c8dabb9222b4a507e76c19a493ee7f38a32b3639ed9616fdd324db2696adac24172c5c83a875ee3f44d12b0a9c5d2b2e4b6fee2791a1858859a5be49efc3737666f7d0df4abfefef1437f7d33be253fcc9b96f7919eba18bd06add12407a5ca5676ea276f61aafc484fcd0ebb09241ffc5f587185af21c1937b2c59a343ceeddceb78a1632992b18228432e7bb2c809bc8f835015b327710b620bd0489e228dcc13793bd6f75419ff4b0c3f03a197407ddf81dfec339254e7d3a0d827e85ed67748a8879e31754a6d3c745fbd2be4422f49ffd21bbc8c38de07f01b9e41373afcee655572efa037b751ed6440597bda488b2b02c37a2f70099686cf9b7e136d904d60eb84a9a5ea80d7dfca8183a27893367c85d5c584b092af07b98950bbefffc38a33af57f96938331929daf3a1726bdf51ef7c09496c14c74f3cb68d950ca249517e305a2cb93764599e1cc2f8a4b6e033f7f8445696f9f34be246ebdc8aaba87109b78d3a9cc2e9ea8afd5a2183b4f638b21daf6cf4e0f6e8b77e67c1a23625366bf23217def0f9f00afe2af68cb377ad32ac7777798583857be43a4a6720f139edcaf4c2d3d4b1418f0e387a27aacc9d0871c6308425ca1f20d6bd6f2d1f775854c0163c7f6a78befc55d6f0bca02166c811eba51e0db5be", "1251644f6a957ff9f163af24ea11e823af2f0766dbbb6f55228a4e5418a32401cbb190ce56f411f8d89fd4889c0ce27d0d07859f8f45d93003a006abc07998a027b681ab1401b3805ed59232fb85d75bb62af878aacd72b2a6632404e7ea1c33988e62175b8c68466b8af0d6aa54878f9bd87679784583611eadbdd306837f1a767ed93fd5be2a8c5e3c8598c73c1e97209668591d9bf778391b36c3dc72c236e509329bf2cca00e649749828a3cb893b3c1442345617526ecb318aa7d51e4e9a84f08a9cab7d8baf5e4d1e8eb7efb907b0900390aa6a0e5e712ab46d463961e8cb6b5253ad35a453ff79069b7f1f76cfb74c533819dabf9cfb4c4cc5312ef6990a0c6fec115c4eb32316ed77376fbc89328166e8f63edf8275c40042177a8afb46d66a817b0cd4414f5a6227da7632c8d0b33e110784e5dbcc4d50154c261d5144c746fb728db11fc0b1a447bbe32bfa3fd9efcb355b5e8f0cc624696c34762b970c854456c99aa5f291724c21cd1b0074d4aadc5e993bcf97eb79b2d49d146f349f6be952195902d045d09b23130c48b891dd063b15df70463f33ed7c85931ab8a6865a23cfb668ef6c63dd8ee0c43e043a41958d88eeb1daf09fb00752e0676158e14ea37127d8787501fb9fa8a234175ef861d5af86b69d5834f07bfec0e1aa113e7d5bd7b8bfbd75e02386a05f96342925aaa2d3e9a58d357422f94398c19adaa06d76e8561dec5d9bbb178c3bc4ef0a6b91236580509a7081fa40c54497a02d5a150fb73ce7c186d475e5c2a0cb51446629c0739ad979e2c79177e6802be3797a1d41dbe846e60627a1727e80b5c71bdd684264eb960bf5bc2c53260faabe6df9bf356a20dc456ba6394872c298551b452a7310edb05e59a6bc417a03b80e87c0f4354138f6f180dc9ad631ba0ae913ba8a2f91399428386ffabe3a0a3ef01fcef761cd90c56c598b1e7166201c4f91b889bc425b39ad7d6540f0d788de25610e24e495702e04027f73482f248956b8c5d83bc69555e179b5191de47a8ef3d16fa80cf32b88e9f015052a74bbdd7f4b55b923ab6e3e8c0cfaf6d74c59302813ddda1bda9e9bcf94a108dfcd37907609d7cfbf8c0557967e78fddb8ca31024124a2544a7263d8c1adbf9d21650053715ca471ef6b58378e24e991528d9d811a3069d5b510b7c937a59e6adc1e8167b7e046d2fe15738b56ffc27a54bcb32d27e2ff319502bcbe1e4aed3f8c89f69bc65e2e3eff06c899024fe55cfdb5d8170c862cec1ebf6c8e3d5de73e39098dce0d667c10829630ee8d9cce3dc9a73601937288890abeb7ad2545b629ac1851e3c7d8efdb5a8dd9865e1f103426dd8e04037da1e99b4d97db2582dea7fb42edfdf3eee1c9ef307edfb21d91dc2a4fa8a2e9540aa87c70114b050befa7011376ec5855c6b53344c6f591cf58508400", .None}, + {.Sqr, "-5475fd914a33b90be1c86323b3b8c56fde3c6102f56a7d6757b58816293827b9d0521e7e20e22ce0b9fa4147f1a1f07855806368db62b6dbf83075b45237d9cd9657003e5e4e6d90155aa31ebe2a769382aa07636f909a759b6525d08529c788b1646aa11dc143fb8fd75390258774a992b2bf7c5e5adcd308ac232c5ce5cc4c21f3f2a84128e229695daefa84c11e60821aabb141d28629270ebf2aa73f39e37896fc923fb3559b7a98f8cfc2a517e4c0a3013581ff943d8b05fdcceda6441615ab8013c4d4f6ffdaa98380438b26925ce3ad5593d41d363bd02d965b6d51cbef3c4a53b25814e147213d93509c1270c17b49dd867951c0c4630211655e7ba969c24f1af9c0a6a42e923f13ed570da2c1e20680dcfea26ca294bdeaf2c46690f6ce2cc63f0f74b40bf75fb20a8702b7f731a675034e4aab3d8df4ea9cb31e36116fcadfc57a30f68aca4faf0ef4c091c79479879a9240cce8bc40937e801174e7200e8af87e731c8acba17368367db45edfed8112f1055b819bcc765cde8c1ee14d2dce516204a74365e0e33f7862fb26f1120eb0bc676cd4519f14588cab2fc8da2a709f1a93d2d0913cb8663fd4b79b0b0c4fb6c9268c1c68bdbc30003e0501af38513b9f37fbb29d7c35c15969ecb91d205efbba9d568f1d9cd69b2f65b9dacc0a66e36c7f8e6f9b957f889392f9e762a877db7bc07d0459a468fca855ff", "fee5422cad135f0f6401816fc252d5c298e29eb90b7cbfec1cb9ef7b2b98fe81c8dbf73f3029c9f0f8442744cdb6d31762424262bde7b392f02c8725a0e6410482d2a2671d1eb0840299e050e5bf95a3205eb9c7f1e544a464da7f4a4123bbee73afe31912108e48ff43cffb32f7a86de5c42bf36a6760ce2d2eb3feed78d124a712f854f0a2e4558a65e58c7ff3e15da3ffae9cfbaebba238591cfa548b3667b1f20de6a07ab0fdcbcdd0b2eaa8ca2e4d3726f5196d79a63232865f711772d5843197f1863c0960165a5d430a8648cc2e8fad6d7f97d98813c22ac8edcca0eb1f5ccfae1becc5f46b7ae84ab701b61ab1be72637d53d89d6b90f58517adc62f267d0a418f912cdb368ccf34dcc7f756fcd8f0adc30b6164e508ca842f4a85e65ede4619dd998ca9280d860ab8ffd9dd0731dbe29dc00f89eec97ef2b91c44f8e197df52e95ac14bd564b6471481d79ce44817db8161620775fcf31371cc599112822815c36e343c6f2e6787d5db2d38480ca3784639b79d964739b6da723c7afbc7abecb4a17e87823f34d34c816e73b62cbda459bb593a4c4b6096bce1bfb411257ebf8bbf3376231559451a4df7bb4f5c66b9a13d43bc1a2fde7f900a19cda1fd5afdaead55add487b7dd16ffcbfcf7fb204add7c7ccba8e020741d4832016181978a47650ea22ebb8a675b3f3727df3830b8c7117405d7976ab125c682b0", "1bdda4c91aa843d650e2ef64048e642ba16bf08d5c4a4cc459d3625ce9a34174f170b8512134f6476445967dbe221e205ec603cea5d6bbd231742b1ade44341f74e47eac7f5887b9fd5d6b5663b71f5df067e565a59027d5673df53ee7f38da620109f6c9fb0ccfb4eeedf3ce0abaac48c51eb36934db81fa6e0fa114f0d617d213169e768e52d2ad617b6364681cea37fde14864b2a3786ed0e9abf6a189fe6108a56e616d4d41b003ab162e15cfe7063e2ed50c08ac1a6445ef2f2319fb9945561e04075427c62d24775597874c15e1be5ba5c7f325b006d72e63407d2fd00474955f00ce706b184027428f900bdc5cb7426b80c300cc42fcd6f2e72158e429df10f58902bc016a5dfa692ee8fd1b6ece2e6559d92fa6291d77745507a6c26af5f1bbc54d73ba0d53196212953381714794b5b15128212813e5c2d268072fc954a45c75cc9f87fccda89c8013cd93c209b4894f717bbe33ffeee7798b58d82684ec891e7da504c0697c617110c1065c95d390e5f7b8e27e417f75512228245e46b9c86f5e75d8e46a2019e5aea78474105081e1c8841f1c133562daf75072fb1ef880ecfca15593cca93588ae8448b68b204347ece15e30b870281962c705490c53acebad8ca3cfc7d8324884f07e5a3ad4dbf8c17372126318d012947956161f45eca3df5ab2ac902f244500952584dbdbf152b46d60cc1a440b73fa121c2bd5ab4a9899e2dabed56723f679a4267405f46cf7d04cea1e670c2b32eac8aeaf24212b0f35f2cbd0dd123194a872e042a94f7c6cc96d4f6149f6db3f057fca9f942d59d2d10226eb730c76c1fc159f58171ae3c92fa3b74c443292d876e11cac6a9d99855fa7f42d0d35c96fd8db28aba5c4e63194c4215d47ae7010048a874e5a43b36700f5ac6435f3665dc649dbf607580ae782039c9d83a0e95505d80ba8fa792d6a45ff0d4935f3018d4736953250615b22373d953d2e16cbb8698b4c9d2041cc70bef27dd74062f0269b031a4f99bdc3800f47d2288802778266a997ef590ffbe91dc40b65df24dc5bbdb3b4a9b6bfc4cbcbf6391e483d274f42d9e416b79c0aff1ff653bd1412ac4ecbc497a2f9ad14ff4bc0c2816e42b7692df66009887bcd026ed0c7c2973a41e620432e69560076fa9768656d80827e4154089a7486a668f22fcb2c131d37b614f94fd249c94fcf49a408f473fe81528d61e7ff227ba7f74ace68695779a7dd0035079bfd602bb54509405918177519470e4687a71fefc1b04dee442cc3d2429e398ef642acc1b3dd0fab1dad33b4f4494de79e395cdadc22308941504f09b45ad5117756192d117fdfb77d45ade011c6a94ffad91dd3ab9598f9de1248e129b8a949e008da045f00ee0205748bc7ad412dca44922936b54a101dfb22e47de8eae31585d320066012ce81987b39e6f2f03935401", .None}, + {.Sqr, "-f4f2580e44f5669f7a5ca52041ce74582ed61cf40412c3700ca62fbd23005ca069e42d100b9b30bd55f6db80013e2646767ed3018e4cc4abed1d147b5933f6ba27ba82ce29e5fac4baf346d771217f4592037b5713504c710ba8fa0e4d578f1a8a0dc8258da1838664f0e95dbe24ed85030a97241bac913171b65c082be42472c01544639fd9ec0a15a11db47efa8256bd22fbd571a5ba38dc36bc1ba2d43bc679044fb9ec7c27722e4fa9f7cd890348f64a24a4fdc1f6d25fc386931cafd85818dbc926d659f2ed09b01b93fb49c8544b14fdbf9ffdda1a246197fde6e2715c97eb70265e792c07d5d88334d5f7930135e64228d718a73ab6fcbbb4ed32d7bfb7dd9bb5878f14ee5fec613ab084ec2d27faa9530d7a2647b1b218e89c5feff072399f3f7d337b90e6f706668ad50c0db756a6d61293367d886a8cd71ec355cc1328942ace1c71fadf40b0c6ebec110983e9d9e0da2bd0b2800d1b189b8e0640eba53e1b36a9151edbe2da842fa5a86306e60fea3936ff18561c0db97befe880ed124a61304dac00a11802ba02779ceb1c149420a8a0c09b7313681c17a8f9837e254d5c7510db82c9d9051addb4136a40376325b9e22dc06f69028c3d80275efa62c254d8bf457e38cfd9eec0bdf0caa1141815e257114df79750f5094134485336dad17969e3d1404ef7ccf5bd3836f44fed6b3ca13565bacbca0f9f6a85d6", "9ef9bce13682772cfe4d1ebd4342df4fffb833405c3be9f53eac2339cb159fd9cc5ead3c076de2c3321ed00dfd3be0f033e21f9f5e247f2d374850bb7defca29e15a517a95f1988aead1bdde117059f529165ab96d442df49f3a3e6723c3cbfaa1f8aa980facb6a8d0dc2d7d04ba3a63f72ce37ab514d1a73b62262da387797594ac85e4c2ddd8e0d7867d9b962fcb131c30b940f79fab32325b0fdd44452906ba661e0d2b8862c210844b04761d8ffc91e5114326801781ef45a018b3339a66673498dd3532e94593f347f72b77f52d8886d0925cfd09d8022b51cb9eca90eb5e9e9234ecca0e0d6f8d9189b825a8164e51eb1074d3fcdd6e342aabc26916c9eafb5688d1da7a22491ffa76a7dfc96b265454860ab284e9b97123916a015efb0ad29122120eca70d0cb962e921ca307e5f78e5050ef03707fe53aaa5d127d533df92fb41489c6f1da35626dd25912922cb72c2da31c17ee3b8cc340df01834bc308a6264515fd09f87011a9c98a159cd9387bf5dbd0b5f62da63eddba42a853474c74ec73b708184fe1751eb06725375ebed69d554cdcb0e3aca7a1488cd5de89fc3490b99ec82c49bd8fac40717ce95d3512430287a44fec4584291e675ee40bac3233e26724dca3cb6ae4ca3773e39aa8c7ea25ad135c43c86204fcb297c80138a743c2b1f0c41c8ac81dac0e06e3cbdc55d4534968a99e11e686f7d0dbeb", "ea5edd45ccb7fbca5abc1941117b1ac9726cf23dddaf41c29d2a49bd623d6ada3df45805d5d0449cec66d0d51b3560b6102a5a104452ab71becd776a954eacdd3b49bcda59c1f98ae6a7eabf1f615706e83d91fc51e9aeded3dcae8705ae041cdef9b190653b95db720bf69a8f0133feee952d90df7efe9cd8c9484d9f3042eae2f441129130eb6e14eaa04a0c1b7e7dab688e97e7950fadcac73448964d79dfcfbbc6676372ff7e23815909d275d517b689c0f21efea764349e288f0cae46da04d7ab7d8fcd32cc6846d0b9e3f9eae1f860fc006f211d8787ee222e3c0ef3eeb36dc012c353ed4a49b1e2e8e795ff1965e8b789d08bd1509d83a2cc4f6dc59127f910ff60106efa73ff83ea2e3b37401afa21fbaed80f721fb2527140deee9d2789f0381e2c5109f8a754372642888ea4abad027d9371189048409bf0469072590892459197c7dced87f4595034efd991d43060f70d554faf0bf8ccefa1362b8efdfaa0a4767214f8b4acd74c5b135c2d79a41384a9e4ae81e8263351f37f650b3f7fce1ade26b950303c043a32ed2976f12ee43b1ad6bcc603863c3f5aab7129b4f5a1a698e4b82fa74db04767008aa0f72c53c83d9456055f6f44d6e20c71bff6d31a3a482b3f3dfd71055f8eec0e41cfcc4acb8cbd624acc42acbb2bc328eca3c0a7d69a68e8cece450d1efa2b24de690232081c7ac74bdac3af6f29a930fff1ee1eec86fddf330ea422e653f9b6242d70d5b2bb4a9fd9f17bde08de9b385cdd21f09ec33a02c219102784f9eab924ff7d5914422d6ebe14d59709c8d12bc94babbabc9285a8d5607e432f1d2ea14b77edc7ed70f5ad559d2613d525f12ae09c5b87841e5774106e5c4c5e25331428b4e262f723e9718a16a74f29d519ede585a57f0beeb15a518e779096bbaf643b2ff25aa27faddd0eb1e55ef97d069e5b0df38f0ed41196a79bc1ce301531133bf45a6138bd4fcf0e3639e9a1183707f7b70d8fc0b5b5b3a8319a1f1f34904d490303251ebc3ab32ae6bb0c7a9f17cf6136c03f3292a36ebf11396767e5a446d2eef051dd5822d8eee52139ccd4dffbdb557060e2e3481dce23e5bb0d249aae4c88ad64e08fe229f229f57c812168414fd27f2105dd2df51a3589ff7ff30011e3d23d2ff9327ab8bbb8b42a49ef57dcfe26c3947b168f9e52196c2cd1ee3d3aee4d761215c2fcbd41f139154c971fece4ab26911b7605307deb879fd2c599cf2fd72b277eeb594a332c538d5f98cf1273791cf105eb90ce8e70be4edb28c0e0ee29399f713bb7fc8b29115b6ac9df7545f23041cbf74dcada178b1d14ab26b17db3a0ba7cb4d3616cfb03be7e2c79853057d5c51973ed6f9d0e5b755389c1d4ab592f522e9cc0b46479ef256a113ea5c340dae3abd4008b81de5542f2252231d2133bcb548e7ccf665ae5a6ef300ee4", .None}, + {.Sqr, "51c07fb27f3d55d1c705d627f4814c69f04c5d61a3799ba4529985bdb2bf96e2a9b92caec69f0d991aaf2b0d187a5f448c267a3c1e0e4214cf6d2f80887babc0671e14b050c94657d79e85025ad837ec95d9235330da62a4c9332733d99b3f73a0b1cdde4e3c5ca7d306cea6f3a76d1e7e0dc5cb7c12568ccc0583e1d7cb5d14a321b518f261b16420b72b74f4a14a9e27ee2002426e162e3a1e640b41e66314d63b874b4034d764f9a489a9cb9170106e75d6a4a5cfab68d8bd51efa399f3399da72ae4dbe401482e09a60bc1416c3c100bc69ac8019afd987f3604315835911f50b46639de26256c2f48ab569e4c27580a80eba3a2cd81dd9cbc238acc044cc064f29c0f6ee55c76c512fcf3df6997effae5fd073dc9e2946845ea134ec1398ab02c1df09a3326f7247c65570ba686d3664efeca17d64a6a3bafa9b51efc4b5e828046713a8e2a8d0332d17ed443ffb238b2443161ab46d5129143f2b6f6552fc028d51cfb6175770cace37e0589e511322a70debd2411632af4144ee5cfd8a6e1cab7f1fef6bd20403f0ed3f4a4c6590fff2c60fa9da6a8c268638f6e36e8b67145cb35c5d517cd93a1c15681d46bc399136b9703a58464d99f9bd503b6c6de4762bae5431f6dcb8e4061e95b7021c24e35c38edca63539998276d2fd24a5ee1a5fe73728aa277ff76db8cf02fa16f1d26408f06fade3c820aeed47fc8c5d", "afeeac9d4ea81f37e776565dffa9b61e40c749778935ed858f9501dd7c7f249ea2f32899fa131790b136651c6785159838003e5a3ee675f33ba56440a09064ef59995e2862839615092123230a8a837adcd4635b90e008556df433fe1100eb2ad0cb7b886cc2182a727b5eb04b5faf67f08bff4674131f9a311ba794e99a5944ceffe2c8af9f315e8e995ce1ebe2671fe99decd8e799a3863f422edd7d866b559c43fb75062bcde939d89220d7c24f5db60d7df62558c0bac1a0f1a2f72534a4f9960a4367acf139d0fe232a6357da091088514bd1e0f3b346b1e5372d10c667cec10d2a409ca9c85c5828e4f92366355b4e9a2ec9578871d40575f9422b7377cb0770f29ce13bd5d41c15e1e58e896398152753ccb3d05a9062a14d2dafec3299510b420c2c19eeed491717701379f5f3e302176dce9352affac95ad287e5f78ba85ba5360cf76dcef7301479a689aa3b5efcd6a348c2b506937ccfb98b46a4e3cfec3db3c02a263f5a8e4b049d42fe41047b810337e578db289e45acbd31962445a296757fbf54caff963b04c170f5b092ef725594012a98d0096151e49cc696b266d14a80d2a223a61edfeade24f90ef7b9edd3661365f14a49065deb6e654e60f253d7135c63ed7191acad55db55bb9976d56ea31d11554140d0a7d72c40649f8d2e7dbfa39d7af8c820482e50fd6a4a90a7af156e8535da497fdfa4bcdb", "1a1b618ebff64303864b9f4f3977a5ca1cb33d80985db358281fa4e71d08764e728c93744c9aacf2a24ca6585f872ca8951427cb6d1af7a0e396887b5b374d86b85c3d32aa48e2f901cfbac91a7aa505f55ec361e507a2848b4712c56a14567235afedc736179e4930f89dba495370096b18ccec08d4652af181f8269f90b523dd2e5537e55837b474cdbaafda9f6fbe9e37c92724e0b6d7facbeb1182f133367a81192edda0e21bb8e0b532585879c4a467d94a2deff581876d7e185ffe49ec5bec499255cb6fd47a10c2251e34392c898f79a5ad56349ab1c3d2c1bb59a42cc6032dced98dce70c5c2bc00ad57243ae9bdbb4a1bf7eeee4686624070505ad73817d80ad00e8f54de3127a263869c3c59b67d030984286530711513c18e3d247d9806376c1c91342b6b35b44cb2eda0482fd3ee8e534a8e3d7b9d7da2d659db32686bca5f8ebec10a782f4266a6b4d2b5bd5537f68131280c0bce4c02e3a67bb411c14f3bcb1e7b83e1aeb898e50aea7f8424605d4ec908862674c985a88e737ae46a8aa17024ccf22a5b04d004bb75ffde0e39be962cef3f8c94e6bf12f360b2f592da01a296941d36f644913e2a8da45316f48aa1b34c776632cb6dc963432efd58e4143d9f32f97021580e943c18bb4d8d8c3385eb9f9da18acdf05622dc85035853731e477b7d202b2b66ff830bfb7f9c51c3e8462180e529be64e5056bcff00372924d6477fd09bd2d31204c415cbb6e71c2874a5cba9e7460c2fe5da17f3f8dacca025a60f47c0d08ff95aad6d681e5eec87023a1591726d22abd61e2ed160e1be6729afa7ccf7b0aafb2ecb0a63185bd3d43b63423e81bdf4483b4eb9eddd79a05fe7b8b11407d77b770154e306954dec0ef43864579abefa27ecc5ac1c8cdcd32943066f494eccc7b44052020fd235a0e93ef48bcdce0b53df6a4fea1e44c0e22f951fba1935a139d94591604a84007d4483b039d013dc7160eaa95d9dc173a76b00d00b4516d47bbc2c8791b5fa9869eb527b2831da17905ea9dca82c323aa6531fdef49f9a7485ea5409acbaa756a48b636715431d3a6d6e83604300c29b40dbad0b20f93babb601228c1a461ef42bf2b518faad8b804888a96af4bcdd7941b5fad34af255bbaacfc2e9be47d0aa635fbae3fb53f81c757e9c40b75d8c672ee5eb5823e9fc97e3b10af183ec37032e059339a06f62983acb57f745d452b6bb531fe711e3e16b3676fcd09e8af61af0e43f85884f3a19b22a2966c6933523fb8606c0e72b7a3e9e7c56439b53d5c13ccee3128ffe74d16a13ca02add724f9f4a21a1477b98da69265fa58477d46a8d7bf4c3a0c4ffb4c42631ec9b0bbcf68377fcf1af7d425e821ba68835551ab1b7c556834e3fe0b71c7108357377df26cf4e27c389ae944c555b6c29287b9963980b90a32c13e85f323a0dd9c9", .None}, + {.Sqr, "e786fe7bd1b1c904f1ca43436f5cf44d7ccd3e5d1dcc0e7918dad062646d33203a1476d1a07964ca76131962fc8a8ed9fb09913de550c4cb654f6f0fdd06f015c5e5816349e615abf20c2505495a3b843d0660aa20068d03391aeb955eba9ff0f5506f6d81914348412fec2888d621a2edc9b9ecfedb54e947e8c7948c0089163e6d1be94447fda685aa9894cde076f4d1b1687ee58c670c87521b6b6d052b9d1a90e23503d44b06c3539ba68ae1bc365c7fc56dc94a361a354f37b224bc1c22117f6c70b72992868cfb2ab53b8517592460e901e38f0ff34110423094b3d96224fe230360dbbd8926555bf25659606c98c731e162bea316848e0f771e039e28c38384c6464e5ff71ba5e9a7b7adad5c8bce5417a3e2b1b75a7e7871902b0e042d395145de3da93c4c460836c52bd304221c098d37b6fb88a2c1ad7953104f5a708d0be9441112bb1cdbf33e64111735917b367dc13174ad3677de9b1dbdcf73e6af3587bc871759b600ee8b1348b48aa3f149e88156fbf0e64cfe7d8d627904c0a0312d349212400579378e9cbcfe5d75b2d384b435930391f818e039726a016ff5fb1773afaa9f1a1c065710c435152582b32447d2a70478ef0ff56caaee520202eb7e985e4b9c647ef3fd3a1a32e28ab19b07335dadb7b619b7975479e935fdab1703f200bfe940c5d5ef9684269e5c3f8f98e4ed2187804414b6c20d624c", "71b15819e73f23a9ea0e3605ab1a7ec117696cab24ce5353a7eb96a37507559c6cec8df1b8d0728308c1c93500590d32bccc36a74e2014896c847fdd6695f174819acec54c8d8ff6c87dadd7ca8d70b6c6de3a201e6bf97154f21112e68fd2fed0c5c7b459211eb6ba4da3a4ededc24fc5d4e8746a19fb2d5a336313dac2554e560efe18bb1a420ab62741b12307817224e0d15520e245b80e68831253bbdcc294aae41df2019219eacd29ac63a9fc68d8ca13f2464eb1e4ad25342fb00d78c2b07c2a79e2956a6aa2de1daf39986545937e3ecd7cd9069714d64c0d18546dc7d14adb1f74a7aa060a0d6ec7ea81e9ed66b84e7062bd60fcaa3b73e64e3447ef0d53bf65637c40bdf08723939df12c97562f2ce0018c78ed9c96ef3d12bb5c52f430ebf98b07c961522bb9fbb266922f86f8c31468158f1ac09fc8af0b23ee3e3bcc7460b7f1e56ed8e9678d6fd2827b4e74f76d2fd73b84fcb249ec90b3463a76f773cec326f3d969db9f115d44381608f388819929f96b04e0e764d37e244f1f96fc9fd26c895da09d593887d20071ab8adb8323921ce6df74818ca7f44138933942f69590fb9328aa86889cc937deb31ee68bd528be7723b5b08edf7d5ab1f03631e6860713426590ec5a99b1236452b2ec940a21098eb577f2682535c0eaa1f3f145f0f24a001d75a8e11c9e070bbcda57e84180425582a98e1e782ab508", "d164e672db084ee55508e5617ce4294a3fdbca6585784d1d4c6f3f251d5a0ea2754a0a642db1a160c66222a65db88c21b5ea35ca410f58e72694b5d03c640555e6e6001b18cc069abb6171f63246fe416114a6831459cb9f7281022df90105cf3115fd60a17035852f4b4fbf9b8d70ff4f7ad6b9ec2ebbed85611f0052b852b7e959a55e4bbdfa6edd8c27a6196ebe85a1c4b4464417c1a0249a768ddf8f7dcbd9124075f27646ce72a50f18b6914ade2c28903a97d348da0548a401c10893e65510aebe10356c23ab4e076a21dbcc174beed272a273df3bef15dfc8e5ba611392d999c3f3b8109e0489fd91c8b19c4b1acb90718ee2cc8d00594d5c19d91de19511cffeb4ba867270af886fa650903bba149031c9f8b5fdbb53f84ae227ed7d260d528b684b9a875fc517010816c6cca7e449ffd2cfbc1098b1d5f6084de20011541e5058d8070d3a5f15c807fcfc8b267062e6e2bad13b144e9d8ebbed5876385c8d25342a22c3de6ad9c4b2c793d1109f06e76fac18c8d2aa55efae13ed70c7ac55b1ac5acf60b85713cfdde280b30f317fe2f744d571221b6d0c74449d49e941da3e877bce39b26ee21fb15c3dcecc5a06004e3b91bdfa055efc3aad50bc067dba9eee9051abde38fe5bf55c8a599fdfd6d3ec9e0864d59ad66a22a8c2e1be2a1e0ae03e1ebf5bb4ac49ec16b53a35a9d19b012ace3978072f69b67af641a0894301df99a1a577bea1f65e91faed41ed1731a0a0462250c950af4408d55fc24f85f4c654debf3a9d3b45a22fb7dfee322c6d5509e1739084e5b91dd7d99a97e8a31ff9b4f3ed4ae5cf2151adcb640123fd13780bb9237f23a1714dd5606ac58c9552f6c25d930049d8819b69981b3c8be6d5543e933d115826274dd5340df4de48a231b7fa5634ae042630bbd614ba6af9e0973784ed7e0dd0a8965b7510ac860b2c930c22f34cd27b5c486735711ebe4cea996bcc477cbaf35f6d24686baa95b6cdc1fc49f4520fe395a6d5b2039b9f63f66086da765158f8b244c747ba34178c610d6f7388fa0edab2a78467366f33ced49070874a12354c59a617aff5ed3bc374274af8ae5108a0d527b07c2f94cf580cf45cdf9a8e706fa78a69e7979432700c5a12198126e9a049091d4300718e54374a43c3e03bad829dfa190255516673f4b6a6f90da6439edfeb65c45e92d2504adae68fbddc157c662d53d614c906db0db6d75ad94476388e08a88e7abf1f8e9d82a8a3d1b721809c390feabad6644181538d301547949b7c907c9e0b085627114b89fb267c191b8e14950624a3f111471ce39770de512408af2564858ceb65c61bbf94bca4d70a90de6d80ee3baa44c373775f39166eeca9f7fd291b3f87d165cba4d031357387714a2e77549ebd92f72bfb6ff36c3e2414533ec69c5e91e3b942fece5acddbedbe51764690", .None}, + {.Sqr, "-cdcd6da48608a740f380a71993a40c8a4d85cb6e814194d66a65156cf46b4b5d0f24630e33d728a636ea7aff438b352ae849ae8d02c1355bc8fd1053d3442a3b90990fb541c474551427670118cb1daebdbbed7b381b9ab2d05d703f533685a14841671694a5a2e58de65e5d7221c810557d4cb95fa5e315238811ed69b295e3760973c7fffa6696093e4eb28cddbe9ca505285bace5200e2f05045ca7ad7424521b5533af74e3d05d8e887a956b63ec20769aa8cfae71f88097f70534e639975ae7f2e58545a71f35b7d2e93b9849b903ebb11220052ebf873cd7475a2b9dd170dc39b7b4c557f36c8ec35748ea3ffac75fe33a19ea5df720c7460bdaaa3e171181c1d33e39e278bc4a168f58a8cd0e834f40713e01908ae0a6356f5c77fe7ac6c158a7bced6c947a871f3857ae12f933fa604382fa5f5497be096f956922c38b43d3d06005eae0874234994a98acae8a49406d0941783e0fb5b9f9698d4e4bc2d3e8ae4eabcfe78c69ac912be33e7a4e514e52a3c10f4d3580c9c8954debecc0d8a5da800dcb1acee90c4dadc2bb8bd50c0390629447a6b37c88635d38dadd8926910d914ec6409d92432fda8e8ea819e2a7cd164b9bc89d91762de1f14ff38e099d97d4131e88e542fab2ef1be3ff7986af0c811cc982a7aaf1752517c602ef4641ada61347130ce1052201e6284aab42f2aa66b2ede6381f1c647183cda8", "a7b6b6987ec05137009c74cecd2cb3abdca449b44f6784815faa21b7ddb2231df4a619bbcbf6fbf24d466c6543717390fae3b1556849f1efea11a6ddcb0b153195f4fa5b67ffedc35761f5811397d28215202bb46bc14f73227d9736618136d7fc2df17c8f06bb74b2f7755e39dce669fe59ab6b2b17ea3cac0900af08c10869ef984ce82ecb0c8cf73246016303b746a1940ba1ada03f127189f233352fc2a8e8535dd4c3bf06b7f5c8b6bbac428f72ba3ff6785aa53814ef7ff5d8e566aace75e7a0322a0a26be345d63c1c07dbfcbd30ab67ad180f79eb4540cd8e28586b9196f42388b169dbc3349d816793de5a3cefd4921d55d11da4e4ec9b6ead1c849dac29a5692f5faeff8bf99dba962153c742c95728b053147ceea7365ba4faf8d9d262d821c0a0b17dae865d6380c146357ce0c0d7413815550a30947b40a17afde8420db823254ccc3048271683c744bc104f4e990af7fceb40a3140858e4c75598bb4082f10041aa954e08fc0f4869da15af4a3461651debcb9eaa8647108be77930092638bbc33f2aa20216c3c60e2873567907ca847aabb31bdab10f170d46530007dfdf78eeda14d1e1210d92559eb798b23256c85784ccdd9fa8aa2fe034ebb3eeed4db335e02ba17f70f0f22d16d359750df30b741c437a55bbaa5d040bf3d08e6a5e2feaac145d581ed5dd11b60f9210f20528923a3b36d64450f5167", "a572a672471e099943b2b1a100ccc6762ca3a7fb8dc5dfb840206d02fdc01071385646faf6da60768bde2d7b0ab7c3555db59353c137674bf9b8618b7d226b16d7f90004a6b952bcc55a5ef7fd2f303a3231cb0fda255a9f7688899734e43dd35cc1e66cbf470b886536bf1d2ff4ce01ea5fbb38175c970661989ef2d8cf0dd8c1b147967df39f5b5a2f2dda64b6686cb88afd8154f869e30b25a78e0eb33cf2a00782343f38f5dcb8f8ccca4c0cad3218d07dabb417f7f913114d50ef7848391769488627b6141689067b354e02d7da86c8aa02e99ac6291d1a881db167157434a8ca5d24e22dec33b7d9098e6fd596478d6ff8f340f8ce0b42873297831a6abfcbea9ae9261376837cad5a9ea8fdec6e07cc94a0e8e9a63243668267acabe8faa0c3a8ff6456618a4abb69c46995cddb1513416789c609cbc91cbf6d62965abfd15a31ef7bc6edf5722f18fc87eb6199e149156fb125728aea8cbbef591f69cb8d309b7be13ae1f57b04a0aaa2e1e565337d053a2d82c16fd7432afbcc86e9addeabb0aca038988baa00eab082e7a73c69445c5ec039939ddf46c728766acc32b8bdebaa33376ec38727042caacf3b618f295677326c86f9425e47954c8ed692f8a0168b4c1045119bd1b38d3a64c79ae959aaaa9bcab6d10578146bc49118f56a1c15b1f4f7c332f224ff5d44a44d9f1687e23a25fb1b2d5451783c116d39a2908cb70da165817657b24d6d9e124f83916b14b7689e32b2d8f54d8ada1e54241113680ef02e9965284f68f2e04a02be3f5fbd611a6f92f369662f3ea071e61a44fdbab9ed07a0317a5a71889b3d4eeab459ea8fbc0d5e25a9a74c7469c442acadd0b30843ddd0f35ec379566649c764e54a2cbbde8c4769b03133404a5583a31106d2e9d95b1d7e21f12ae0db98069fa3a591f2adfeb688b2e1e4cfa978b5b5b48d510d5578285cae3ae6f537d7827f03328837754aa79da3daf281ec0aa75cd27436f699a5affbb837a0212eb975fff0acc0b80fcd539f5f86e4a30138161fa7b0b15c7f1e6c2b89a6fd7642dfaf4b1c9a5fea06ffeb4a03153ead4cd258c5aa121b409fba19a4300a8b010e1fe65fed3a6ee53f03140909e22e494e840768fc9bd7b05ee9a78a57cae598c2419aab4fe5df17512c26f01d1d7052921cd358a9e2316d3f36af789ece0ff343f7684590ba0542ad44bae9668ddbe6b7843ef08e69ed5cc4286d7e9eb846aba36272ff47b37db597b2fdbb9dafe07e1e495f2a8cf4264fecdf58ef22f6ed39c22afa94a96c1175151e91d4b8c363f150116ba7e55de3dacb32721aae2c09e1e5e1d33f95b29191926af43ce7dda0790186ea15f43fb10c3f7082604c9f0b2886df1bebb0176931c30febe6783713eb786e705bceb7940a243d7198e2c914feba86ae73684529b661e20304fb0aaa6f267e40", .None}, + {.Sqr, "-ef38aec98ff0658b6bd1724dcad092d0770854a2e5e542924ead0b150cb15e84fb493d86cb13125dce5487ca73d6d9599b828f0307b9083291f59bb6825f8172592f19cb297faeb9f0b32fdd8b5733a9eb00e2fcd29ffb55de809aba1dde515f1d460542e979ce988d2bc7ca075075d34798eacb715bf815523d057adddbd482415d77319abade5c6d1f9eed341ae728c1139d47399d814c18ca219fde2f46b8585009de2e7d5f5fe642e8ceed74f222cc7bd72e0f3d657189a98ff44470c47710acf0720fca4b2fdc5aaf7ed52d1432918149146b17ec3504985ab35e61e9488ad0fc726ad1fad69eb79792d1d35af11cf674a5cbdc1a9293a269171851470f61d0c3b35bc19fd3c8bd51742a1d90bb7cb647764c5b69d3d1957ed35337a8bfa863befa5650f34f6a0a752b716d1bd18fa3dc7c5760323ff2d2af115645a1d6728db14b7168917d2162128baf48aab52778a3bb50f2d58c2d4f03c05300ef4be474684117c21ed7f853e96a3186a61a720d510a1fca290369746213d88d2a253da578b28fede4ddb20bbb05ce889c62ddb2317e377e35f2ef7d7b9a0d75952ea070e5b8094ae68775b11ca87e696faab457d73c97e9d784e929be211f49f6d899cf310750ba7baf489af6d8e148cf8bead8db9c737828ed44987de2efbdedf7b2a0f59ec6ecbb26600ee511ec4520322b070fa48ae03c83472467d5fa8b07b2", "5c0dc08248d199d76d1affe6595d2f081e352929d438bfa194affa8297f5a0ff6df593ec0648593615c0119c508826610aba1150c276ec5b76dc201a0fe44082da9805430a3ebfff6dafa3db539c7c1f6af3dcaa5a68cb69939666a069d2beddf7683a9df4eca454953ea10dda1ec60817d083eabd62e64709189d21a7d1046f6459ff11f05f8471fc0480e21df6b2a28b850f7391aeabc5e65bafa8b53b3d8952ca1026e7a566891ba0b3109ae21b9f294b2307617474bb990708d05d9745c3667ca4b047c0a35346d73a3fffe13c20ef25966246b0227e5c771031cc6aa98bd85e9d54df9140bed370db0ea4126ae49df79c054186ec40e9de0ae606333b5dc49654ff656d111ac7d5378c5c81f49725f3e00221fa6fa82d9e127d72f2b62efa2d6c76d4e9342f193f38df7c7896731e53bfff37c1b537abad26307a762a4d3fdddb96063459b2f32ece0129a54dbe48033e46879d7b4333d183fe51ecb9159992d5cea8e962c103250de9c54db958096a2554b5ba1f1703c12565e7720e12dfa829e93eaf629cba6b0c9e3f4cfb43238fa4d5341310d60822d0fcc10244404ab0b6befb12a6d7b027ea61a8ae2ce9c47e98487d4bd9331bcfbfda3de23516e05ae216bbf754129ed16af87a5e1a05531a9104ae0c6d5ce7d0f4314826f5b8b8e971668632bf50ba9b90b082ce31cee4ca52868a3e174e95ba8cabe4916e6", "df8ae2e94a487524e2c7adbf9926e0a83e0d1d5b4a744cf4dc4fb30708c55d8e357f6bc46b4c149e95a31c6e6468fae298a1773de065c9a066c9289e998270e1de2705b29f38f73b6a5f97fa6dbef77d82b0be26235d092681d0987f01c0f9d1baba71f678efe5b67539ef642d4bed38153d4756675784c3a8e042afa99d7e11a8790d9f97e557b90dff1d700d9fcdd79062fcf0414e436ed67826aa19dd8280674ac03912c989630381ffc8716ac2d51760ebe2ec922d40dd2dc93dadecd391a67de78a8cb16ec6318da113dad49af300eb7113c44176f28b65f060fb3f7009e1a3647480eb4f4b5f5b0eedf7b16691bd0c702a1f566fba9470cda7c5fe4a014ec423b5a5dc943a9fa8097005b4667942a6226157f94306bd84d4b41aece6cb81d046c75eb15b8415dd7e875cc5b765746db365807fbe4232dfb663abf2344035c48d9f722a105b8350be12af4834d948a2a9773347b49b15fb36b95e446ddb928eab64b8a2d8923a5862a33903f6237e61d2900ff43cd6fca98dd1ec6f946919b0d71cde9f7b3573dc56c5e57246eb13321c01f47bd72a0081fb5eddfe54ea6cd3ce4b2f530dd8e56e640d2d28ce13836cd64f5e449ed24c373601aceda6a6b6e73f7a1f790a338f100c788787cc08ba1a89c8648219ef0f970a6bb0c642024c631aead71c179cebba44ebbd2ff970af34889137bb2b191f1d8dadcb10afe23ab0e1af433144c938fbb6f96ab8c49e3ea053a7e54f3a3d61ef895ddb28fa033fb36d0849deb7d281cb465cfaf35c2cc095371b0d92af61e2e49ba65602a952d77e0904e68f15544708cc479e10b844ee18b346877930716c50efce82a04df322eaf76a56b093c1ffe7358b4a7552262b0c1219b9132394f6921b0822a8e7767fdaf68268e6edb2265a50e002d2f291b9f19fea93a03ce441893007d9340b2feb52d12b34467f038d531793a59d6105383a4f81d7ff29c03026d38956739a06cc7001bf9b53ebf17246ecf14c3b0fdc985a87364e5e2a29887fe7bb553cab943e1c9229915aeb3924530df03e1d3f87f8a55ed771ffb04bc72398f621bf3aebe7db8c4cf04aecea680ca8b48fb371b20c95ff975e6a7faef92553615c0920904ff1edc3918466605155ad8fbb3be699218a781b8cf0918f1b8cf074868b9c4497a99eb39701059a57811f94d19d9bb0f5c49225475c9014d599b1bdb5bdc90526a1623980808a3e073f9310186680a763cdb47a65d9c8fea32931cb389744d81c2548d6c0c3d43e851825d7c5f6f7258cba366a02b67a76e81b4ee24445e1ce6e86a1d6d39c5104142789a3d5bfd7b1ad5a12fe4a744ada672df8b4ff480bdd29eab98ec958c8f0342c599cb2142442fb3d985ca937f3eeb8088bd1458089c461d78af98de22b3da7fa7c0f6d9b9390e10cd8df04aac801a6cfe0bd038737c4", .None}, + {.Sqr, "a3fe25eb0a67dec358676942b6c28ef0e4dcfa1fd9df1ae99dca8ed313284a30c654fe8671c909619f1370f425bbdbfdbddb54a5603b5672725fe45332f523fc241cbef52b900aa4ca5c05b323f2d290c7f6fec60f2d6fa93f54fc221f88e3c269deb012c316a4bc4690e40c0fc2a283f246df434b3025350b4dd277bbb635a3c07227eeafef898148afbfda040fdfbae85fd50e13b1348d7e92e5fd8dd0cce27b46d102c73730739843adc132c5573e544396497ff840a66b0b7e1642f25cf0afb52075dc706799a72399dc355de394cab8cd214b6305b5d7cd6b2bd29bd02b17bae80f054425adbc3f095aa2e4e57aac0d2a973febf9a1ba64723d556c3f5921aca2d722825b26a220c5e13eecf1689602c55e6bb1c1b1b4d081b87401948ac4eee6364e6e18e59ce07aa464ebba49ef6db6d6c3726fa4b026fa1065110ddd5f7388cf8b2abbe4451f513ff569c8d68a18cb533fa508aebf7951018de1b766a6e008dee0552296beff01ebd230111f70d694d191747544d968d518c58e0df1e52a909e586ce4a0e0a9ee13de6ba8808d8c942a59f9013766631e55aeb28ef147b8a05e5dd8fb970b7dd28970c338cedc967bb96d07b3e7bbde96414d8759dfd2e200dc5cb82562abd53eda1e1963c88dbff9c1edd31ba051a8cfe3ca6ddaac8e901ee655952abfdc6b7f30d9e8dd6769e826b7043424c8e792375761cf0fcf", "12dd538048e7b086aa527eb7e066072a0651b3c38d263238dcbbc2f6a88a177e998ce51c24e5cdb4cd374d3e433fb08a8b4d5bb5a110453374a7c68266cee736e24c08c01d2e1e64d07b93ff1e5db5fa30d8394322f4dd33e6e9bb2dbcce3e9417a615cd9980b168a7caa63d7f8ffabcf5c19ff1ede114ed7acf1edd64ef941c01e0d6295740e95f6f9c7d9102f6df4076cb9c459dd926d966c913f46f0e126efcd3b4834e5308a9ae5c5a5e4477ff135c464bb64b0bd2e9678455b3b40297a0db114208632ff27f0aefdb52d0190609e675e1d6f03e95bc76c386f69263f29e3583ebeea118877fcf57154485b544e044e4c0ff5b9ef068decb0beff7f664040cb16d6cdffefd22c559409f2a3b7b8b69d34914e024f8427b0052d82c40b2c59da81c4b801b66f6bd99862d85c5c9bd75d8c5535c62a4c01e6608cc489e4c90de37c3e24ee56d3f652feb27efccd625f8a13cf85331daa2bd38df149b33d35211eda1174863267d8cbf2816ce2c85ab13d5d9a7137ff91dbb1a9622cf8314b5e0dbaf839e5bec96aea63af842852dd34dabf36b3ddbe0bddd2e664578176b3584d012eeb5b701d1f0f28fc5562e272482650a052c6877c1abad35b6cf8c30b635dc6d1dfc6e2413741b2c127183d272537ee0dfd9a7c78437c8219039a1cf376fe3a48f42410cb54e2e0d6f351940a57fb8ff88c9ea440ea591cfd89b51aa2c", "690da0989346b498efbad6fe4d578f3d409333ea654c79de0c3fa735262a8786567833dbae8c9b32c5557078cd754672c23cf427608e809d0bcc1f096425c3e6105a6cc04d5a7ffb9bd99a3652778fa936aa8c9883fbecb777af8ad02371683f656bb3e88ca4c84cc6f2256ee287176a8af050a51eebb40886bf236331da5d52cd2d6f0c102dc2654e608a28fc59b790d0258a283e5d5fe611000e482dfe0e640cabd84c702f7a43c8404ecb72fd7effdbf7ca1c32b1ac4d8e9e4375c6717a9f503094b1c8bb93112bee4c2cf0b11bbc1c1e82ae9073390af2cf415a6d288db89de243a8f1c6dc48beb97e8a50d0c5bab4cb310b0bafe0f97cd2911412f564af40b14f41add50a3a389194ab48c5e4e3fe91127761313ca2296838f5cf4e0defd7cd4c18e63c734bc846322d084761a63695f483e5ac3ba14b5ea86d7acbec9c25d161d351bc28799d29425d6d001692743d469b1c313da4065cddad2bd83a881a20cabcc1f6ad1b40ca68923742aa71d5f6dc3a44c70c3bd2b316c226e9873f188e2c1b02addc45faccdedcbe0f9738dfd77dd22d5710e7dfccd701f92440e2d4499a19634084a4ad755a3e930f1a848d47c7cfadefab0d2874f832cac59e657b68d3bfedca2cfe38355dcb57baef1b8399d828088adc5cbc6cf912d3afd3b2d8cc982a21389fc614cd86994ce764ef2006578b3380d44f822bed589aea4e0555b7a4bdfa77673975ceba2d12c5f30cba18d96220c8109fae9f4639f1268c31393b41b269fefa792ae3e06f3d0ecaa82442f2bab3c80a09d40f56b4ca51c0d5e8fdc3e867eda2b41d8542008e03e9df71856286c6771d6300a74c93c267c0bd547b9299d8e91adeacee65487e19024aa2bd349e4a1dc43cdffbd2e2e6805e1defd93cf1a3f5c7da2308cec2d663729b2a7bb3889033a0d39f7cfa936321e076c91925521d456129a52a6893dedeb2fe37db271976bcb43ac279dab59d88a9beea53db7a41e0860d4b1634abf47479a7de0722efc166345b56ae308d9dbf071896e953bf06b7a503b2c6b64c4c9f66fd49439936d47117aba619767eb110c87170decc22a4e456c0eae55fa8b3722369521431c6c29ec7683051fda8e86e5162e240e04614d923449ecb6bbe81cfe8d0467acc1417959cbade62a642f66dc047ac716581c61bbd6ee3da29056993176ce3294935e0df6c66d4fe040bd0ab62d502f32438fea524f22f3a018c01b3aca3adc5933a7d26a97f14af11288d1f267028202c0971fd6524c67e025af7708200aa140270b81cfb454060087dea087bd754294cdb58c10729ead6bda27109f6e6078a4b1037e5b95c8fcaf513bd6372e8e8cc1ae1380f68257a489f3dac3962b041a4c0d5fa3284ec6f1b12c5bd9f67f4b3f8f8191f3bee0e536a9913815414babff881fcd238d400330242276fbbe961", .None}, + {.Sqr, "355c93edf72cc44cc262852dab73cb8d2e6659d404eeab792a844acf46f565fbda03d76d8d96471685bf652d8a4cdf256ce8f6856b173d8710ab6a2002eb2aa64f38c6e2a49ce55477008068f1f366d200b472cc18e7715eb2e54ce4207f2772f0b1eec2295c9ad1e93f2c58a143ff6a698606eb214ce329c71b77db0628ddbbceb68862103f03ef5cf8d06f454ab7812f6aba9302a36ce4aad36e2f8298e839e1b814425543cbc146e6995d6759ca01988dd98790cddcc7166ca70c23e58c2651a6e5ba42ff004ca641bb4e24e2c4b938ef97f72219383213d390ed68c9d54f205b062d52128834dca42e113e1c3d5448ed02628355081016551692de4cc79ec4173f6ccf17efca555034caad719b4caf6b38db315318b5c31132aa244fe192535213e8a1671bad4420bf371f5b0230c39293ca5dd5d31ffe111f704a42249b5bb56bbd0fe601355162bbbe7925c5f929896265e018a9e25517f4baed82ce2d38b1ae15de2b32f3d0d7dfee3cb2a433b34ede816f9ae20512b4b0dfd123de7730615cb5cca925cf664ac9b7f45e3672505de4948af75c5a0ddc987c3f4f22c79b84d618f89ca271e5705af1592fd3b2af8a588d4ec102606d48e8b353dd79cd776b79440104056942fb989c62a873832faea18eb3abcaf08eb6e5b16d78c3ec6f4cf910f82b06835cffd26b9ae4521633cef0e29b5c4f07f70cee1546ff177", "a22d1b4bb0ac221a0c438284aa37c82e7cdc112ddcd34b3c1ee5670561907c465bf8f42e8710548fd359ab6a603fe48f6e09d19f3eba7c0a9d99b5fe04b9e1e28c25eb28eb8a2e37dbcc4f7f05971b787f46ca83d647988c7a42313e3581811ec056159a4322ef24630c306a6c9ea16240a05c1f93f9a845db236dd28116e9bf46d5611c72e44d3b21fd21168995857435ea65db222ffb1c777d2e104b3b5a592bec058e6bb452ae460410a71d32864b167692b98bfb9f514b8a8f70c3e67685d0fdf4799bf9ce82015c137206ac74bb478776a7d645d8b3f6752bef5812bb23f803c1cfd935c8bf4ce214ee6b006f1f84d4cd4d0d7e660a1e68ea907b3778de94d682ca3d261ee0729558c21c86973aa788f4cc1b8f31e935e45d982844045998c729715ad8e8adcc791550308545e973cf6b9195765e8b34b6253f7cc23f54d0a2ce491d33f928e746cdcb4f4754fa35f83ba89efd70e4e9aafb0516bc088ef11960b81473451aa3e9e3df1deb471abdb84d4b5b5360814872793df1be76cfc5e4b6e5977b1166569c0c396630b20e02b3b9ff8e32421bc51d650f92d17c44e60ba2d8d3e90e186e124688050336d1082e48e92ac266527cc9ea2ba2b9f29f0201f360e57fade7cdff418455eb9d7420dc0c6a2698cdadb5a07b3c98c05ce01a7169389ba44e84474b536d282da6af4ea794d5764c38a0fb4158d3c45b68d9", "b1f76bb30dd5885e0a389f1e130c67ff56d9d76c7b7efa2cbb508454aff7075600ac310d845f6e2bdd433f9bb046c2f7be4860977b49195d83537ce54d380e2ed09ad78d40b5c55655559434ba9e47d87dff6dcf0563f9f4721ce232b63c2cf1f026818b27be0bf215879e36357c2389116af801dab0c2a96fa93b387d2d478d2bc085d29ca5147f0ef6558d3d5b7f9b174361330fcaa43f64b868ecfe68aabb5ce12894f5f2c4638aab28b8a80dc7c1bbb8305694de5d21994566409525f4be6c11154e27c6897192489a5668791a9a3d119027ccd0e383850953ab287b5fceda431d696555ae5ea6203190ac79b19558882279d62d13c3aee2ffa5ed3deaf4806244cead5ea68252575cdc8b87a4ac489e92e041908d3447916e7c79169cf1335c50a048400c96e238134b04604cdd059a5adf5d7fc14c7206c8f4dd5f58d5aec71aae50a3b66a95682912a33ea198892aaf14c219f2e9e291489be1cc8b6edde55b179629e0bd24dc65eb1514340329ae4be30af8c205f747a74f583fdd5caf57b6e7d1500cf6832daaf66da37731ba914f89eba4db152dcb0396c960d098fa8edfb83e287d80a0b2c58c6500563cad684278eecb9af170cf6ca091fdc487a9adb27652b39591bb41fd7333f818341155d523a8f878cebb2159f3a6092e8458e1c4646760dd62645168fc92836c17bc288f9179880e899da9bed983ad3d98d5bf55d10bb6d405fa7ba9891a95af715c4fac8bad22a625e6ac6ccd162e608a1ff5c38d4a6ae9833b29826a331f4110b3ca1ad12d0c72dcd0285332855d6f14735700c60649d8807eb79c2f5e52e0d4280eb4d2090814a49069b01c30af76d2c41b5249e41eebabfaedfe379b9167c7a3f4bf3d88743e587f0d4aa3109ff467ba788169f98e2a87a07f43a137a7be0ebb8fc16945ef0e4722a4673333dfcfd30b3eaa1d7722baea2c7653e80a1362b9488581ee0484a1978d9cb14ce3b7e947a068266b882deefb8a4688a1d053d1ec7aae277cadb7ded5c03ce266200a08e32aa3589a3bb2caa64aac1bcb312b866a9b7f47127f5fc01b26156dab0f58bd616abcf12d12938bfb8dfda10c2f32b91a1f42e5480f53071691f3b6b94e30acb4ac3fce0bc43bf76c6af3d0474207e6cbcf1cf4e248e05d68036b0b2f59b4dcee7d39a0d89feae36b4d17e0e2374f812411a1cd4550cd10354878edf6d4259ca800f78d753df458c3ddeed8a02dd48c9c23319aabf0ca68817d1b69764b25023419b73e78e74ec0b5f2efa4f2d3d3a3a9c98544adc02fbaa92d622472498bcbcc8d5dbe53b007f257eb350ae028e1142c3898599f00ccf30a2b608a093b8c8da2e4a83653537bd672f2fd608207d4011ce268aed0ff06b8d160fe7c8a30224fa8444a04fddccbcf999956548bf6914224deb6a8a0954e10b5b9e9760f34551", .None}, + {.Sqr, "-a561a129fa1fc96e8e647b2c915cb24f37f1e584839320069e7d9ff9fd24314195f50731099425eceaedd2ace1f30960bc615b471ece92fb7fb32e73058a30d10823474771de2eebe34b80f80f947eba0a06cee5cede32191541726c7903e6c06ea8122999dea23660d25ebdffa336f2d91a2d2268dee906311d758dde2da8701ad9c776eb2616c77ddaafb393f7dcf5c611c78a46d8569c383f77010e7d13fb5a1c42c42da823626c9ead19c02f1b85a049f3ab95327911bd96ca0d5ba36e2bce4df3954f56cadef81ffb6e2d3fcdc3325a821b56ae245702ddffae6f3174eec2d120b782f50c7af6fe486cb279d1bb989b66a79dde13e1fac5e6067431d8d9325b6a1221e42ed72968fcb1a8e95a2c2173bd5e8828bb8860434b51f1b8c47e6bb40ab87f677e4859d6cbf47123edd08e4f9acfa599851741c9b31484a739eb115d27c27df8801cea7dd5734f2fd9363ccf650498d61b41c28d32fd16ab004d853e77585ec6ad12f70ddbc08f6d31421201446416cecc460b8d003b0f84b18d5ba89aa6ee10fbe065a7a0c54045cdd557557d4f7eaaa22c31856d364ab3e9fcb8b184552b2e0fd6db7ac4fdfefda368fc1449b4a79a9436550ce443f3416049ba0fe99d909f753661f2a08dcebc7def043f9a75ea52ce12ab33b15995b13f778e8fc5c34deba9bf379f70a981f98e9c27947f68c729769351fc1eaeb98f8e8", "2e9efaec62f2554c65e9aa9c80fd101d0ce6c7110b5342ab212bb257002ee2b515ebf354f572bc3aaa456f7111ebbd7c7d27197f24add8fcb82f82d4d48d6b38a3b62a14295b5cff9ec45bc14e703ae77afa41fcb803d3aed95de9d098cc4c831c250be0286dc22d4e0438382928a0b5507c6c81cefa88c3cc466b3b76054dbac6d73df9f6a693d825f517160c4d6146bc8e2419e83cf725a99a511d384c011c28a25f5941a9313b067af04bea3508216b26805df97567805a67e0a4ed1b704127a1798ae66ae22fd31654a2a5b914966dd34128b59b89967dc616d6346d2ca6e988b52b4760f5f404261d77c4d81e4c59deb317b9875507d0e99eec264d6346b80d29283f73512bc0d966d6b85bc3320bb10e934cfec9a2314311786ceef05d0b0d05ef321cdbc4892f084a6e572c453f7c3ae7dc62d48d55131c78660f863818b21821b23bf434873e4d4a3cc3180f0ecc500e4ecbd4582ab2dbd9d5a178c60b5fb2fb01a0ddba60b355a8d53ac0c30519cc54ce7464c6b219d104b0cf9716e6b008b3f2b264731ada8b1a09260decc6183589183d1aefd070398c84e5a938ce2f906f4760c4ae7f0af78118aa48c225feb4856e8837d1c27e5e0134b1965dca9000e4805eeb17d62eb8bfa980e7830ce2eca4bbb6ac145880135693c2c514c3c34e7e63d117f9f36a74ac66e1a9a7d2b6f7f81875577acaba3dee500ebccf", "6ad6fefba3b2593d37431ccf1fa6b177bdccb04739a9732ee3cccbb76ece917af8055c1002c00b02bf0105785b7c7e5d8c1f1a1e586ecaa933d52e530eff609e961ad645abdc64d08fe9bf8d8bb4b5f3864f9b1e33b720a40d2e55cd8142796d5be1d1356e6ffda95171e0602470dfb18f0deb432d80fcdd5a2e464302adf576fb2a65e29759eaf1a3d8d4b98a586aa9901323b7f28b3a890b6ce5bce87fe9837e7e1669b232b075745fa96d24755fd3b83bd832023ae9e51a79f98bbf9893ec8abb90c90758fb9d1cc89ab2c73e859d428a5d4ecd1a748dd4a1682734801c7b504e4da34260d720a3981aa5004d9d8f3efdf7b0819b1e1c24ca33dc79b13c6676a8a9d60268b6dee98fd7d6802173fbf40730c2a2389524c3d127094b750f02c189ccc63956f40b9170dd4f4a37a8e5db3ca1a43963b0c1ac1299fa0eee2551ea31d6bfef26c21d1a72e0424e81f92ab010143cd0bef97cc1839c12b58e26fc9b9eecd033ff591c92352aab38742ceeea84972e07cfe0b25a0bf62ed2dc6c475ba3fce7f370ee3c73455d2b271d6a01132f7a480f5cd4f2833d557967fc8454dc18a5a622ea4a63c7acfd542b783c3d029e2f3c5420a95a5a301a5bf2017d512f479a50f83761a5f01b6bdd2102f6bac0f1b8c3a58bd22f32945a9ce276631cb1c7537077269ec7323ee4d7fa0572752498b6dbfb1dd48723f1126c8fd5fce5c4f7c455718814c5d3800acf435d3eb43a7973cd0936b48e4b60465cd5ee93e715007a4181d1dc6e7f9f2b852ff46cf0b0948bb07faa7d3d9866e355d93f7485343f9e5b6d78b806ff9c507791e76e05f27d3aee7e2c7cc2530be960e1ff9414227ef0679398bd3b87be56e606f9bd3015f65e0e0d8c51ba8685e53e1f7c7ac0f9f34ca6331c4a8944e317b6b4405396dbb9c4886d914d07b7a2afc549ba17e4b6379376810bdededb53d62c4cd2c5b02e10954c2fa6bb70c050038d2612577f89958dec9fb2e32d7718a4754cff01305cad5ef2951d1e105a90544d08112429fab56ffadbd252f832c512145c9e8f75c39c6e00bfd4ddc58e3c9589cbeaf130827453983ef7e9ace4f8ba45ff89be09a46bae1bbacdcddc1733432a27bb68c68a4ea40dc2227a21586f8e1378b24dae4ea95e2b383ddbae104b1e6d8b42f8d889b62340fd4f80f459351827e78559c6cbb5104af3725fb089e2ec3404d37a02da0cc88fa32f597cc7264398038e954e1f1fc8e7d66f9e476e2750979a7ac4cbd6696f150afed10c2e710b1c20641f1853a8ae5450fbedbabc5903db608be9620e1b730365eed01dd1f9af89872bda6d9dbf397ccecd7312879fb2f311de121e3b50b3f903416caee789700137ae3ce2c05986ff5450931e1d6761401990b425c3dc8e607262c80b910aa3a55378a04c1e913af714533c8bf70c8275825240", .None}, + {.Sqr, "c0662f5aaf5eda4e07fbb816b2e6ffd10c8fb217d0c3d900eac8fd9e0e5e3baf852e3d33a8112bf795e9b52486a5ec0fdc346b03b4fb3efcbcbe1af0fcaa84c0cf226d42d3ebfaad1ab6bb025ced9ad4872b85fc0737979956e2e8de514a852fcd2feab08e8cadcf6e67a27b18ba696620acc6e3a1c6a4a39f0393e3bceb5c0a45968dde72b1308e5c41509297a76fe460a59e4110c4f32b8a902b40a03783c6ab7f7d57fddf3bb6f8e0aeb6151fdc87b2a390da3c5c71dbd5be0a6dc2c761825989f62dafc71af09f2aadaaec8d78e568cbe10cc78062254a50738fa04554fe3b59d6e23f54a53b034d31b70bb63381a763c7fb4a22caba5c3d7fdc7dc5f6dd6d17c32ac73d96460109afeae50f2189a1eb4c71f1136aeb78fe60664cc21a27de4d9d5107e6e88ba24dcd8609531006ed3a1b6adb3c80a136facb41fc1f2cd6e05e70bb0d214e57e2568ec5dc3eec421d7b879a979835fb75e175149323aa135926dbe6b548b387992f98804b90bc195ebac10c31b83b739b98b422ef983b7f22cfa281e1d1cddf90abe631029f7eede9c998c504bf128fe6b6641744714263128ca6af11efaef59488e81b6dc57a1a6ab6f72dc7f86dd3799e2e81c92b3d2d53164cd300c3b1ffc455cf7d3946d28b3a450201bb902842fd9ec2acbc6a5232a7ea7fe8497af844a6216d97542616528c037b9c95c1233eadfd64ca9909be06", "1452f5647725f4e4ae4c296b92f2a984971026d551409adde98d13f0498472bffad94982aae628cef3953d3c35216ddacc12c5da6df487c846d9708e92c7302887934a876b2c5be7a680a032273c4034392ac8594672a66cc906d1bc78a362948f111003efa94c56463e421badccf0a3529eee12f5b5dbb6c27548bfe97e58b552c3c8aaa7b46f332c3f7c8bb4e4ba44386c55dfeccf72b4a4e4dd1eef0afaacf550c9882996a1273502a7c4232ff32008e466e25e0a72676d11a7485116a1df781d2a5c3d10b4117d35e882b7a9343ff652c5e6c11bb41cb434aa72fcfc86cf51d183f9e1d512e15ff50992e41794298c44468c71d3af3cc100ab7bef9ab539e0cd96a2c23da47dd8128a38f35bf03719a12085b05fe596204f5f99d260503f1f579fa12327966558bcaf561804f6ce5c4d492a6982fc755858f751292c2b0bf9f1db2bb277d9791b35cb84c2a27d68b88cb530c1784e3705316fde326dcbadee0b103bbce8125cdb047e2d7d44cd5b2b747bda53aaa738c1388da50089488d2878b3238ef18abf07bf0036eb2d1fb559654d34e1b03e20d8ae15b0d50d33559e50d017c0255e99a8ae6642ee6ebc3d8b05012e9ae9436e53efa73b63a03d58766b34fd8b78337b4dec30c51d609a8cc0eb34edd6296400ea4e49a12c18081a76af987e200dc967b4d8a8f332ae30784a0acff99f0cc9433100923764208f5b", "90996fd1cc14738f9d24e8208367d55fd635f4bd185fcaeb1b2aabb6161ba1812d56880a187663b245a25f9f2b6a27301de01c5f035664721c44a10e6a97f70bfdf0c9861d6f51409e05c578cace64af3d01acc9ec204111b7a2f8b0baed430279a357c4b49141dd40d4936aaee5b5150e2ecf84c0e7f1a98d9f4f9a29d7dbd00411d82b3b89ed2686a48ed62f2c03bcbf438ed4b7c3271f90eee2f57364c80a07fd8e7ba72603e0170a4b53af8a12087101624e56e432edb278eda0e4b5deadd881587e9661d6b031a91168d189c1ada8d35652b7a890beaf9dfa87a3a2068445ee368699b03e40b62958f6a9656ee65df85de928d203e664459b7765b86316b6e671ee16b7738856bff055a311c324cf6286058457cc48ed7c0cd7d864e94d3c21b6464194efbbde2d60a994e8aa0a34346f9d2a6fd94694ec01a25d4501f7f17d3f9ba985bd1fff93213459da97e41c9d7fe444538f88ff6a8f8e54d0dcfe3002bfecf532a0af616a8537111b5329f2c8a0b10eda20583150604f5bc5aed958ff89bdad260cd8bd0e6fe01db23f26aa80d2bb783e35471a587228d6b44c0291210ea31b5be7139dce9bf23598d963f4f653ae0127348218277c20feeee9bb09ec0f414fcc99dd782451ceb6affb280f97b04f10d06f2ff8f386a461991c436cd8296813d9c068df31496b07e3f85a01fb7097aa1e22c417a27e571aba7b28020b44a9e416eec9fd62625aa82d5dec0fe9fc5447a8da4d73f4384745f4c759dc408ecb08ac4e7cffd8d6d202560f5e9846b94952f5139150cfa60822eb5ae1c41362c1b933695f0a63537ebad791405e1dc5b0b312125c01ef19c82b0aef2dbab94aaa04ed3d0919839e049782d920d7fbe3ab3d67caa8f2608cb50e22b6d12d9a6b76e915cfa60f8d9ed21574fc70d978c825496a101fc9714a69c9ff735bc924895ee4656be4c15b84048912ee0c11ed39a6dfbba3fc92079919bcd9005b05998e5150116a474416d4a0f4dc269041e58d16851db1b6073b25de19743c3faea2f03f18800d49d54f22aa26d36d865a188cff1b810b1af20aeae95d3242ea225464d024155c9f5d38e8b87d0c99d312d9b3788a8077d156c9deca7837e98df95ace58db39d656715fb9ff447b8b02ffba60d5bfe14cd0331eddd862f62765fae108c8d1c8919859fa1351965ff2edc6087548f6ebcbefefcb228f41b78235be3475044fba172e3c4ce833bf52fd04c73c9bddad4709188d169e29c91d5b182340a69a99fd6fbef84bae5deb1c11dcd24af3f9e01c2c337cc2a5164bf43cc65d5f8d66169b8fbddde795bc9f79a82f08419d865ae5ade8c46396c9d72e4cca0126b69a72b89a7cd4b54bca4c3c3ddc6b371ac8ba2265034baf950889fb291ccfeb6a969a3ffba553b74d44b0640a34baca20387eb23ee32f2d36fa1578e824", .None}, + {.Sqr, "-ca22c4b582abf477ee412e3df0a2e7e5435aaba8adfd7d65fabc34e9f1e497fceb62918521a84d762cc994eea6a046fe7bcc1c6d9238f6b15a7e56e02f6bd532199ecbc27561a10d758bb3944edf592f29c78b387b1c23582d26e4b44c56fbb490d7104d460509af9e1faf66652c8d53e03d99a7c17e76102aba21899a8b26de564eb4065e5f5f70e890f36ea1ce3b3a02ded29eaf5a995e6013d5d671671725946c43894fc821688a906b8d9c490104e0bb9e01211045f1fb98565923fe17fe7f1c3f9f052efaeb7bc0c852cf3d19917e5c364d0d6ce9a001150b4261fbe5cbfca5ecfbf60e9639e60bf180429d452e4e8ead764d4359e690b8e0cc46626c93c00a5ac1902c45c8901f4b5b892cf2dd32c4ca74039fada6c2a391bc5805159fec6762e61f1ea95f78e4d7c5ffe1feef144f2d2c4e960fc9d157060679cf3f925c3c396b1052ad4ab1fce8d2ab8b02b3cef76aaeb9b637af69c8e5966751f349c60337dbd3901e6a15a65dbd090122c556672672c4c0b4cb687c033dbf2788175ec1a666b559c7289b446d9539923297c32fe512838bdaf446eb92b8b9911920b90e04710a7ba3a63ddc2e5d174921f465e028fc3717e26562f14c552680f2313aaac263ec666899f513bd2df5dec84f314b2ad969c7eb668b69c18f1d9c4944d2c911613a91161fc0372a066476800fa1f25a3084c83d516859a5f174b1c328", "71babc02cbc50de465d6e65fbe5a2c241ea3f14201a18af69f10351f9a2a119fd6b5b70553ba56f8fa23c3a08b99507f24e3272a922832618eaf06915ca349421c46a878b3c82e61cabe13a9d2d62c055f6485b48cec8a19969b1d927537b303c2c20c40ff724e74a51448421325917bb0316c5beee8648c838976694d45ef5f03511fb9cb90e46076298aac18b9816b8b2e58c1732ea6e49b463d877ad882c450e3646755a06891407b548da15a183df52f3a6a43b3ad7939c8d46c9589a85fe929992207db54c670ff587b976c6d07d3f9dddc957a0d84ce9b8ecf975f04b2809b8e2982a5d100762e57769fe08cace11e97c101de69490920d682d5d9fa964a2ab4ff1919999fa15233551ec793ac1730b7be9885605b4f4913503f20fbce4956c253d8b57f862945c4b51495a50c83925d292a6cbca2adce192dfab03348b76813b4f344a4fd11d71c58e354d9cf3b526cc3c6630819c7732ebfbc9b511024a5fe7a56bbfbcc09fdd64022bb608cee687b7ef529aef41a32917681e683352f1337b2c96fa431e2f2ae81a4c22061730626202fbc6d14ed9637d18e63807cd701657b01e481fec6d12b48a4909907d20109e86df497d9f0e1e12911c990cf547a494447b683c7b292164e6308db1543e28feb0d934c40c464c94d19a41540efb5ec21926ce62c4f53622daade3ab0bd2cbd949b241de86b41fe4fa3e9af11", "9f9ae327499484438c0c947f0ed691b16e45345675e1648dafa5ab49bd381005cdfc0a9e30f3c0fa7aaf742bd7cdd271a6cb70c633f2053c2951c66069137bdcbcbdcee8e2bb113d8c0e1d1bd1cabc27c75f3f16bd9d361ba1b8ffa1b71b4e7b6264888fa4a196a75502fac3ef471dd54c6d74e18c5ef05991225fea5467952902c2c0cd64f4e1eb5411bea953492dc4940d26e0d48db8d43d1481bd2191b4c9e659be8dde27d0485363a36643f9fc7aec4294ed73bbb54f5300f0b7ab4b0403dbd57122e8de2a87e9ca3c29f661c0ad64cb488007ef7b1c7e2c4ee35bd37464616b386fc3cde2c50f994c805aca19b8c5dbb563b1249eeecf16b5b959ce149f249145ff770654103a9a994a293a39f762455ef9611babf942b0e0956e8321e308bf84ffa33f32db969437b467ad8829e4e45c19897ead726f7fe734093c0b9584cc2caaf89396161cc445724ca4962e2a756352691fdbe61444419b28277b56d599d6b63f1305e141444713ffb480844144477594b99a26944476c4c2b223c5bc29cf55f9d4b387ab274d6e62a51466e777ac15268ff7880d6001cc2fb141ee9c211af2363a19a9d64dda1e86c62f6924482971df85da68e37764bb4f99f85552fdb1a6af497d6556ad75b14e097fc2fcfabb46c6ade1ae14dc0e164474c9e9373be683a1c9d2dc6a7bef68dccdf4a6db13f8c3ce4cba04fb5430cd939559e178d7b263b34b97da866999a0cead4aec02b713b423e17799ab7b05f35e9671b2908366b6d17ef01977b4880994df438154a8fd4e25a71f07e5e9eb49c92914c40423ebb0c27eaa213ae5038e678f13e6c4bdb169905b1d7bb87f1995b00349465189d1791bd5f423c0fcb3b6353a8d514adfb6c4e5010abf2e79cf666b124d1e3d4510721351ff79fa68f2878c956b1d655578ed206525a400b30cc6fd7cd95b9178537a7869b086572dfa0b25fd12b8da6769a89bf831d1e362143297b2ef06a2016bda832ca02ed4b028905532fe21009f07afeba5d325d63a62442ad9b5fa0eeeb0d0d1ccd186b7575f3df20804757157b3d18f01afcca5ff8fdbe2e84fee4d1bf2eb7ba640df6d4896247699ae5a7d594cb39e90791a174bdbe4f52f4d62a9561385df5980b913303edb5cdcaac42c180c01d5d81c3437c8fbd0cec1e6273367c56f0b469f388f5d4740030a3511636eba61b8c1128ba3536fc9edbc105d02108c1c8045274de2fa6b72ffa4948f21b1e08efabc25a71261b625c7c4ae0f9ee4fdc4e34b8bedacec122b6eb5f342914e4d9ce282205db9671e5f618db9aa24ebfcd8987f870cd76d28263fbdc01a8aeecfe75f1e44d429c9da8ac17e9129c750d80c369ccb7a1d21158fdc989dbe786e58493b4f798bc1874a561394b4165c9731fb6739d0da5401052e05f07ba83d7800a3ba4345a44344959bb215f640", .None}, + {.Sqr, "-cbf3570d49823b7f8eac111c5a7f3baa4044fac56f6951feffc0f14df72a4b42c4eb1de409d4dc33fce12a16dda5581f5a9459a9fc3f96c45e1ea81a128cd6fdc3bf0611b541f157c4729239e16722615e535e93c08b147c15a3d7b1e84efaccd95587d1b5d260e33c5446eb07f634f6406e16af8cbba25df518e5d85479162c749f3f797177757e0e943146686ae77c439abef12086cac3b38068c9f521952acad5e146dcac8fb04a4fb1be0b87f62b1ccde6839330952eb34df0eb9b2f022a2d5905fcb713789fe9733e4f9c523ac9ad6296be7b5fb5bc2400825d96ab9014caf5527f6b105c5e14de7a42fc229c5c7407ffae94dd652f7aa06e1b1c3b6d113647bcb032e61b00f2d6745786cb98967aabbd6eab985d985d5b1b35224374beb8ff01189b9a58f8e7944314732e6789469abc7ca8b16fab2d1c51ede6bfeeb7c98517f522ba3b6f40c2a3f3962f7ab2e5e696a98d3e6c477f55dc6b3db582710f00aa990d1db5c2bdd3902ee169ef376535a3ddf3837d3114bc35d72fbe395babd87662e3f775fa0be7ae7695eeea58320607e8a0beb90b6b3dce2789976a625e1836254e00f9a32df6512aa47a013cf6faefa0564be2828c81c3514273fe2a4b28f7f5ffdca6acf143a1c6d131e09783287f353ff476e4a04ed31041a17d895734dff9a25d879e5b32ec6a615e8497bae248ec7e909fca13fbbbaa2b166dc4", "46364cb6f0b9bded14c0c6709a4d227fcf74c54382ab71ebd70b4181d795aeef8093ab6ac07b9282ad973c6d9d7e49493fc1f75e2992b8f304c7f0d575d09b86b278cbbfbd069c4fb2847d49766e63f05f1ae7d321307e3d1b6307d6b8ee8f0c3c89ac643ef3653e9500e980f5121d0e6ab9beccae46c776f825d41ddfe1bdb43f18e1a8973c9607f4522e6f65cfa107aa843a12c65ed44b1d20dc3348dc2746f90a92d055e7d78e70d21391160967d4661e36abd5a9e7e95c7d60d5253623afd05f4ac5c89ee766ed608b322382e91598d0c3618b7ea34908c0b3d179e2c701b0c31df497087f3bde6c5479d4a0487ce8f83f4938417af6a74621692256ef29e125b9ef1844928cf096f7a5850a00c39a296da92199522747093a5b7b843756149dc7cf6c3905b15d4452f9299a7c8dbc8928a9359d181a804ad6674d62821409756f0636781907e57a6bd9ef965ba3e754296ed2636bfddbf3b97d395488acdb03f59052b011e7367321e2c42ec983af55140f3ce483d59ee0f7efd7ff2554ee3ffce6d396888b4918147c18ad02b7afee7092b7cef234784a5f3a7fa9201ceaa7af57e99d3f4f190da2dbcf56049df6d343413dd14c9e948c60b5d24b2fc91ecdd7df226c60d5bdab87827a673e587df7088e469ff726f28d7824ff528f43d5067032d520ad19c45b999be878fe4ef179a37dc51f030b9915e49bc7ed24c2", "a27bd35d73682040513403e81f33ac64ad250b5d2fe805b3b20c778bd80e4c1f2130fbf3d571eab57d6c45b604e6b4ead31c11b3ec2ef7edb2873eb6d066fb84118f48bf180317a7052d9f8e1f02315ee86640f26f5ccc0d208c2f4e459411987fb4f478daa6250c4e15d9b4714be8adfedc77a9009b080f007ba64066368d4d9688522ea418a92201532b0d809772e318bcbce1cd1acc99209f7365f2a26fb99b5f1407da84b413c8e94d6276578d75bc4b1d3509a8239ff5501339f2feb3724a618737865296df16a3adb50581d0124b15ee159ad6678ee87fff3c2b0f2cb4c79d4066f2fde871c59b74fb4ac801476b94d5256a282c1066ffb2480292b65fd5a3c53489061d902830090c845295ca886cc39db2815d99572be79461f38d3584ee472a207a072d7f35784bab17fa41a1510069768902c7a4f920522eb86a780f1571b694101c8340bf94123b4cf1986da828d4302ef276d14761965027479575273cd462e9a0509f29b49d5bb91434c5e933c5beba5d6abe847bff72a2069d3229582c370cb6976d3cbc4b626a8c6decfbe51a99989089d39c2230ef7a1769f5895957aba86021554baa037cdc242be459c3b278d84a64f5c413e0653d7098e3b155369d83b00b03de0f62e1f1f6faf6f632f8422f29f85169915a716e1b51f7f9d56d5f91f21b27a1cc370ced0af3f5e68cdc688c1359d3a55697b36ce57bf85d841e03872538ac48589c061b9062d81576d5a0ca8edc9e7b78aa768baba36c74cda90b59febebbe1af236d6a1818c1451080ad30b6bf90c4e7114514ac79327d9323c6456097c02c0fe708b0fbca4ffc52c4ec0c24b89f7b39502853d34fcad993d25b8a87651a2b5a0a1eaff918d39f31152ecd668dc6a7254f945656103e6570c30868217d0ae7a8403d13e8ca5aeecc01b4e586d0de811843bfaa27ba853b5b28fd88957cd121706fcff8587cb80755152a911b482abd124c294fc08cc24a4e26ffb83f8badc48029f5ea230e5a7fdf0793be507cc28fe659b94986e4963a6835063a577c00a91e5994e8943ae76eaffad358552874e2a2274b28264422fe94bf07f9066b2d4e3ae17307c8e8cf63f25d2bebbe8e38eceb6966386375e74669bfe60b4e056e1d37bbec1df7c253d7c4dae0d21287f4d3272f2eb5a7ef07c1b3dd337f2be875340becf0863f88455c1f808635c6112f11029c1edaea08250679da2b678a3f209fc550f2e7bb311df425f05b0de15e5af9aa753d0efc2a249d6f4aab6c4b9432a88cd6cdc878a55c15076a1335a3593a681a43e466e9fd9bf849ffb37efc1e8d6cd586a9d230e8f549ab1f9054814a214f370fe363edbafbc25ce078ecdda8cc4239054b2170750def73ab3208cff6b75a30f4c9e2e3ea43018cbb0c9ffc63ec91d5213d18ee938cf40e1f13e68fa65bbeab26e4c07e10", .None}, + {.Sqr, "7b5681701a437a1e98d4a29040805f2a6fae64dbd8e32d46b05c412037c3fdda7bd9ad52538c8bc6fd536b79ee9ac87dba8b71cbb67cd826f9b50ed4c6385e9705a2d978140f8cd2a6320bd4b7a4be7be8b667c854b7ce2a2314b27b4be14c4b0c5e6bb08df8c4d43120c5a434be2ac31eaa950b038a886d1a06df1a7120fdbadebda15033361bc45f91498db6f5badb59bd574750b2413c6ed29f5dde8b82d3d68b2e9b8e614c665b51ea2f45a3ac4a7c312565822df70c75088150e3fa66f4045e6376ac2490ebdae4b3d1f419f260bcc34245a6100aaf347d3154e24f3793ad5b4e7d31e39e5baa792feb379b5d6cee1ef0634f85fcef0525d87a56e5010563895f434591e68a6745d7b332e52439f21db331a26a5c25a28fa0bcc196840f8bd7682a63ce25257b288edb4d1578a5055afbe37b1f94a0b659d11847e185c40aa310d6a9236fd115842f460c3367e81b41f7794095069f0600ef22d710ecb81567e4de209ca9f45fe5872263c18aad878e71e2973cfa4355582cfa7412921ff99004fe886dae144504afa062ce029fc9c714b0959c2b7ac46f3ae8707e4a84f58787a7e81cff21500148fd51e71a32b1cf248491c6d74573f3b4d9471e2aa5ec8483776bbe7756142db837a622550890f1762587d4620ed95e3816122a76fc8bcbf3d8e61e363d34137b7717bd515419ec367cfc4fe68b4dc902093896160", "549833ba1ef6675d96c3576ebdcfacb38ebf68bba01d51b496ec069fd571463fe5299c9d1b6376cf70ea7c18f476c90558d5e87b891397666ca1f41560a67a75fc9f4fa6ed4606bf60819010ecab8c0fa7bc4a157e222cb3bffadd233d1285ce4d10bbfbc5dfc3bf7d24450a9108408aca4a1456a8e459c4ee7abd9fcdee876d5e1755bf4d988009ed775a02bd7a7afe4f254a7864fd91d6dea2afaf86c3b61fbc63c3cb1a6b8f8e000e2c8c0640442219c1bdc060111f77ba5dea9f15438299c21283dcf323176d55e7e0e265f4bfe8853e9556e61896b328a566d7e0dc1646cbb3a13556b9e64ff5174402d8c92a56649382724aaf52057bbc7dc0ba1f43531063198b8107a53a63db1e4dae04bf4f6e6e2033a1f7b4c351172cf8ac594d067edb51ce7adaeff9bcff6232121e11cbd917c51a8429689801e96d548d0c7a0b9af7151b491f904e7c260857189b183cdf59878c7eeced7f4023380b2581e0fd73634820ea0551c3aeca2c076a77f932e0ae493c793a2b359dd77c1184247613d026b470cfa97c2f682d3f88f92cbd9904a10063aa2913c599cf9c91c1b3262bbfe362cc926b6b05b3af48777df7824f14364a5430b89f4baf8ccb5305d0021b4b28228ac5636fde6d2c57e91cb183f2a19e021fe03be575a1343309509321aef812e0df4817f8d22d9949b557c3db8f55ddbea668e20b99ea77d9e4e68b68c2", "3b6c3d9cf200a83e723a7a773a1aae91c4b1473f5acca1cc0788202a6bfc66ca397f27b407a1e17f3581ee03a51746c0db3a6f46b22ced6b3045cc408ed22357167442160834a9225c0917565472a7f6fcb996ce8e33d843040df2d0d77c966d505601c0a289f165ad2fdfa8702819868f544601a147433fddeb1719faeaf52002dd7497c1ad537ad0cd9f7e951408ba602202a391296261a5791bd56e6923d0e3cd419c084b41f479bfc278a1ecc3880fc6ade769a80b51b1a232dcbcd564378f30830be1914ec78303927bd0f8b826a2ee54a6cda53e802bbbfe704315c5d9096419063b2f7b7e41ac560156c1ea43fa9d2806f70400c660ca30e5a63947fbe796c1055b7afff3f1a4c79ea2b0fe80b7b1419d69c407fcb744bcf14e435c3b5365be4dc37afe61e1da987a532cee5140d223e728dfe70e8c34fdcbfbfe0185d08dba56907f22a70d1987117c444b650261c231bba27988503f1b0396f406fe4caefac086567220ff48e05c3e1f05feaac2edc37b9c390f6906ac48582e8919cc04b9f46cc797fa11e3732859d84e06881ba9d2aac55f215a53ae39a5a3c9f1c34ac91a9fede4f520305b7c7fe49e5f7b40b4b932bfe9886e5d503d7e26314057374f58dffe6010c77efa50b9fd295dc02ca544de78634623acd2e3563cb45ffa1b1ef0c8bf034c2d1836b709b5e9d00c6f5053d2f394d3381498f37b8fdbbdd9f8ce94f08e945389174c759d0cd688bc9fcf741bb079903cbe04ff36c541754802ae50f00f184173fef78be7b2cc0af6103084bf08aa95a97ab98f34357e40749f274819ae3b9f1ebb2ae5a2446c976ffca9025b4236cb19fcda9fcbe252fcba04a9596fe0d7569a91956e078efd810b72925293812af3af632a8775a4300d579de46bbe19894e639fb125baac40b4ed186c1afa6193010c99b90ab0c09e7ad6bdbda491b0d1fde37daa08877f79b3b04dd7c9c97d1d3e0a424515fc393b67ef795d820df05117b8aee26ec34359cb8621a4e3dd828d605d65441fff2b1fb351af2c3e9deb53e81ef29c4a40d0e73b114be131d2b208e9c92cc87b34e78eab58e4312cc2b8a146df1c1031cd1727da72e4321fdc181b7c543435eebcbd992853d73237547f1dd6ad2175b42ff3a452468bc63e199a4299481053df152d5bb20de354bb9ca31399f4328637eb9a1d198e69ad97184be644460f967c1a8df4e53e5ea0ec0f30bcad850d1b2c8924892a5d03be2577e6be70be8ad22bca70f965fe374bc0a64c51a33a55bee9ab7d716f665210b49ae346892613b31e607e6e08b2283d0879232982c919a75350d27afc76947e9c4ff5094c0decf7bd28c730d426b87de8600bc5a3b2cc254cc93d7bac78a1ea4d3bd7e0b0eb84504fa25ac1a7cda21595774ecdc863085504a8ca4b76db5908b0750d2e21eb678d9dc9e400", .None}, + {.Sqr, "-332a7846982641da4b08d05fa9f5c16804e151b2239d84377a6cdcf9cf4f7db053766a7cb748fd253d7abcd4dd74b8b283d3aa85647985ddf326fcfca1a5ad627af33cf06200f67cb6c6d923c8bb8041b453806a1f760305739bd8a4b2b030c3af6a508449558021dbf07bc2431e0a92c3281f5b2dee553666abc5e69ed0ddd2ee6b1eab8199e6dfe372066a844b3c00d8df465881c3a674ddcf46d4f6713aecece208480a0d7f209f190edf0a98f8b2bba6f41873aeaabefa37dc455f868ddb6ded85af730c6e0cfca4b15d102fc50c1ebcbad55c1c4c735415d29bd5d7ded3829a3530ccfa1ef90299528434965fd42ebcf7269c1b8433cb1da33f5715488687c87f75777528b84449ade9d7dea4cb1be761ee775245cfb91be8ea054725ff1c52b52f0a0addadaee7f6bacb2c345dd346327266fea1b795fb821f88169a470e5025db8c4f65aa5dd504baf98067609d1b390c483ee56d8d7a3a348667107d6908105779a70e6b07e79829d19900db56eda1df0d51e986925b0afc43ddaefe6e4a65417af0f19c891cc048cfe66b1b75ecad8ec2870b5f3997a1327c56473c009c223ffe3aef75181eaad8177c4dda5cb18563a9a358f843c23af93f268c3a5717ffc3a6a271cdf7ba501b0d90aef0b421b3386e1dd460a8ca62080f1f50f3de39363a6fd8117e911943ab8f1b1666fdf4d6f821d2b0ad243e5a0f32456f22", "a6d66b5ec60a0e666fd34f0717ee0298b230ad61830e4e36abf56b5f5250727a39523abcf90297a8340aadf2800e06052477538bc9330c55dbe612cc14b30bd5d7f8460262f866b28dbfabda28d50719b98b7cdbd1dbee793ce214e7b37dc5a10b02ab918c3f09826a7116ea20fea4dd4b934b9f93ef2751941d8a78c10345c31376de5925941ae0451dc550428bc4552ef4af27896ad5f2682fb62ffb77738b2ec8b3f18a64d21e3b4977c600a9fe6302b6d730944dba0cfb3999d6b0b2d4abd26be7a9aed93b121b3a9bb40b2ae29fa3a742ea266fa38807169ac67c2174290494040359e8c433cb0876621b362338cf02e99808e526da4732894cd761bd7734d7dba57d10e664201565e3f8ba7b6b5cda4a796cf4bf57289deee2f192c3f27dfe427778eed2612617ac9fb8f05a6855859a93169f02df74b8285342dd0ef33cb5d86f7902aea861eb7c7f5e425c5e472c7b0015ccb9700d9b3f908b1708574d2bc6c41b9260de322708ab7c6ddbc2f6e378e674b17f9db315d3624ed519d45f2f2a042577623d142af6c5026496a23a9cd6a530e76f9245395c93b981cc941eaf7d513b65cd89d8645ed7fccdeb964b963c0451eda94bb8efb0c197a814d26cc407cf813d0a4c68930fb420cc7eb312539836e53b26e61638ba901d0916890bc2a1c2cd65173415a6b868758738614dc2cff783383fcc4c3c46da6b0be13f", "a39f2f7d04b6ce6029c3f8ea020a5a810d69634a1119355225e627d2e2d2eaddfae69506ba9bd5a8a129d2dd3b38559c17d3879fb004e0386d5d7ac1ed80875fc27d55a801ea1b371e4ebd1e9e25f4501da3e6ff0d339d53a18cc7d57b6cc3e0a854a6b472c53d3feaccd3ba2c55192f9ba8f1a57ff72e67ffa8e57f69e79eb43f4814c2aaad334db022f0b574951a14e26ba45a72fd434fc112b981425a6bccda08a6af8db6e86306317ab7c7a17db9653d47a6a280bf603059482926745c4561ef362297fa919039b21d816bcb4bbd3896d20e204ecd2b9b793f7cd8b990dc6c1e040e32b85ac48e99c5b731ada6bb3ed61ee47c340084eae60e56b1f2102b9c957c5782e846f4619d1e6afee15b89913cdb3e578b05c51b5dbd5b0b716c6f54af182f76bdf9bb23091ccb569fbb013f94cfdfdaf7849cb32bca9118a67d77afc131bd48da084ea8aea97bfb2c30d473499cf961927aca78150f5d0401384004a2862ce7fd7160e20014e7f6d3208b343808c7651cb4f722a1332999704a02051aca0358f1debc84dea084fc77f470d0134f0493c79eee4747f2c9fd9c5f5892fce7fcee3ff119967128f17c674c64cd03e71b68c9ac431bdfb1f9be66c6c5b2f92ceb53c0ee2f42e4f08c636eba0e26bc534897fa94387d51684026797d879f3bbda7a3734f67c3c57d8c321f1fda6bf62a2ef0d9f16cee9abc39ade8783ee2f26cbcce549f6e03bdfb245a4da4bdce12cbbf98a94a1dac6a4fbece2d65c32862c330b0ba746808555506862ada3805c7be5fec3c64cab4026464e1dc2d6748fb14ee2e87d56d596e72493095015b9efa212180ca0f2e7b83867405a71a51e5b258dbf0c41e043cb5f1582464944b3923b9c16d6a587253d02210f1edfc9871af6fe61959790a0d6d9c09a34e41a0a93637ab84c68e7568a446441f1c8509907bac6886a78f3dd47616889765a1a5cd048043dcc25866d6d8f39184483a9c4c84d83c10e8aaf9f34dfa6e445b992a7e359fd000eb0ac6c1501a73f6f95e689da7ff04af6acd2b800cdc4dddb5ba7d5971961ba8b01191d99d6f86f47c53ae1f70eac76fe5090651c3124a22f4dd52a35810e2d60bc65ff59cc9205d465c9cbdc63656fa2f8827cf79b0f2c65c4dd982c13da284af64215cb346979dd599f80affc0272dff1107ede29e59345a75eacd6d476292e7517d860bc77d8f67b02d809e42116acd979ee153d87ae1af9e6f3cceaea0c9011fa048cc74235cbd823cc9fa22b4af1b02b5694974d344a469eebacc459594a90f53077dfe12c2047739abc5244d73bbb3ff5af85ab7c9576378b508aa8d786ce1464e739f08d0e6b5482d826ba870d4adc5a4beeafa18be4ff9957fdb8cf342793049b8f31c7f9b63fbeff1b7e647b35661bdaecd892a56f0df244c09e879d8517249e203a60928084", .None}, + {.Sqr, "d87d05183e691566cff7a7d688988db1a0a2642d1d8a05f74729b70a7eb6e6113f3a95cbd8945ec8bfd4036f7e1fddc09a12688918f624dbe50ee0449a774ad9865aa8d51d2ec8bac8a59c8f9e39c66c0b4fc30ce0d4e64818bb34f795414e64b90523c22bbbabde65c5f61119aa46f26c4bec3c8c488972630522f3bf20af4c0ba002ba753b55dd90b6dde5976f1ec23e77b007f5f1569365d144e6d1f889da7f421ea001e2be6f7e9fff12a4e612719c00ca83f4445a644f2a04f92c385c2ae29857a850eee44d63db773758725e9e23aeee830ef3b478c868d4d4ed54b493eba220cc6d263a7814dd0f5be7237c37f78fa2a7e3e034a65bff4c208f89da21139b3af8afeeac4376f4569241dfe6266d591975116ab3c4e3d87058c4b3463e2f99f4b8d4b86020bfe17d208e738cef66be297e7d41092978fa74124f810784faae6beae29ca89f50cb004401e934c3e6573762d7531a29346887663a7262f42e1198e098909c39e80cefa8d55e7fc72b819575018fdbe5568e4ac616d69175bbdc34e9475fbdcbb65ffe13316eb72638ee91fdc5c43b7df705c9ac8583ca921c49719cfc0ed0998fb935fd1ea18aee43c6ebfd49e387d1fb9d9856c358e3b4e3ed00cf9c45fd6318ef71484a41b5088b04b62ce8fb2f54e6478d2115df0c228909c1caa80a7a15d473c149869393ba610b61832a1d694983519f7261fb90ae", "65c0781dc493deb9aa042ecb68adb8c440531cab6ea2f08255c671ddb3a12329ab834d27b8b2fe832c141697d64de8cf25f1d97dfbb7220faa3c09c6397104379239e265b5def5d86d8286fe0d2f7d1c34c069eb621f13f45c025a75c85cf20f294afb2f5622b1bf0dd98581e4f9ecda65946431b8949d66af3404500178d31ff12d84ef45ffa01a9feec49730d35f7dbd76770dd2a4f018100bd6f096c1a306217542e948df571f641efca6a1ed6db928de3ea9e0297122e77b2d18f7c2f2ef6e34209e748d19e0b412f732fc9817ef7eafee8e68d9506d327427fca61a656acda052b36e7ce6b432e9fe68568fecc18e6e586620e990b9f6a689a567a67edbd609da572ffe03f90c1ea39c0fb0bcc775178e4d3ce270fd5ae2d87475091545bc057b3abe6a8382ebb2e2446097c847f6e46d11a357740367fa658b53e8686bbaa7b03adc24d53ee30d34cd835a7464baa38c54595297d4479fbb37528e6be48e8f019bf14601de0e1a5eaeda52de23e7e6d39b87d07ac15a5c5f258aaa856269d4286f1f2584dd89e19b5aa62c3a3caf2ed1970b81f84b68fa9c3c046c56fec3dfc485cd8a3f671956db3a0aa69193f57ab4bbbaa095dcea599da454efe97bb273871146ffd85f6cdb77074d538e8472e0a4a0809d2d188f74fc996faf35cf41d9cd7ee83e57c40eecf971c7b40bb676f7cc38a19c0de6f0b8ab24e0ad3486", "b71335a6e3183b78431a1bfaf5dd43824ca7bd5cd184afa1162ea90c486404cda389427e1b4903a46b107dd39a2e833484abf13afb7d4ee8525e1f7eb3275f5fe6baaa1eb690c81d06cfde719629de083a193fb3aa5185691da5340ef5a04404b75bb3539d65510e3ac690fd6284f0a8d9459bf3d779ff065889981a6bc143b39417e1425b07609b5a6e8d37b81bb47fb2ecd58f0258a26a5b78c84856e702554869ecad08a31b53f3d3d684886728afee193a45207dd2d557738a86bba413ff2da672cecac6b15b3a0da6cb1edb4b7af171be768b255b37c60f2943c03d135b1639ea10f74f633a8167cf3f627fc68c7e46950a4ee86887e57523a732df15b8ecdacb9cb22c0d4493bc18e87cd0c2e5e8379ea3e786d6d18957774de174f2f20c13d2ba51cf48d3b7154d234b300980bd20e0b105a63e3d1c31c676640d8a2ce607eebf5e436ab6a8db7c67c28643cab12bf1295f76097c71289251f6016a9b3898900857397f6d005ee3a80822c5e852aa16fb8fa4d5bf99bf7fa49f954685943190e7352d6cd79b883ec26017367eb2838dd734924fb0690d135a81e10f4ed951710ba24d83d8c35804ca2f574d8546b5d2bc31e277c239a73863759d956b85b5a8a5c71255a2bd091a9ed088f9ad21c9844d073e71fec2d346e9824342c19f79bc69e6cfb0169d1350d648d435e858ed9216e789199f0388bf1b3c49c1820157db291fbdbe5455fc15a20755cb2045d1ee9a8b9b5d324adf7d2e678629fe827394661f766550b30206476c9e19ece46e258995183adbe445e0bebc6bfd84678b611352554bd438a04a13db14c2317a372c60f56e49a53cbac73828521fc96f6c94a28b4ba7668d4c43a08605b4e85688c7ff2bbf5f228f5144bab84075ab80ece573879f4e109e048b3b58907914e9c6717721f6332c3c99ec1438a00353e063d97009ce9319fd9f1e1fa9eb8228321c467930dce2f5be3099f591683e43033abb7d143538e642d5667fcd0416b884d32357ec555ec01947ae8c9475cb40ab1a68c57440faf34ce9022bc01c68de1d65074ab426be973884e90cee77a38b92ecda61a3ec8d7914ced27644a5bfee610b75e8fa717be512a1a204417573cb15f2a044163d9f098eeb8afad89e732b334ae2270c0469fb9f3c9a1c27095f43ca0dbf247b79d191c45f1e279cda89babe19464aa9855fdf348a4d8aaec06001c0819daec143ad582e35ed4ba02467afd351d70032d651780e2791a723ff0f699fb0385b17e30033ea3d7675ab91a3eeb9807a141d854af41668be9e97368650f5be000d7b9a21d2a0b22004deb9efecc63b7101afa0a398776c1741426cb994501d8a8cfd1112387c602525d41a74ac3a0afcee640921d1c3c8ab1346f2954a8564df01f6a9eae3f64214dd6108e90ffad4135d778bff51896199d0e2f83644", .None}, + {.Sqr, "967634f9605d6948e24b65d1e1dc186d163781cd52c19f4172d5f350ad824bb6c204fd3375b1682058218cce595eedeb7ddbb356edc75f78fcce4dde51427be686584be1719c8d7965ae98ae057e33e74bc200d8d0cec5934f7c89077c33d63e3695e52f6a268d2ccf473992297767a4788e26c8cdc365c1a59eaaa9daa35dd0ab32deb08fd2ba72f004940a1b96b7d4b97f0fc117c7fcee7e2eb4254fb3bc95a91ee1c481e9bb521ec71c97ff2320f8ba030373c52cd1deff469ac5c9b71a2a27e2aa45ed439c32858ca8ee911f0f180b8fe6cba376235fbb51029ba66c0d920286fc2fd07cb98059e6ec715a1900bf47197eec28393a6124ed90c6254d769a7330ea234155a8843688110e5bd825bcf70e087b333e1e8c6fee1d953c86d39e4e6cf8f99aeeab99da06e1739bd40d443edf6ef70612d5d7ddd499ff4fe22480ceebc8d267428fbb490eb8661ddbc4ed8e96648d9c9901cf5b4d1b35b7a1a8250eb1d6b9c8604065a5b71d715442e29f4f846d352e14c09b9bfe1ae84f957c794882dc43b7fe8e558d5f898b8610654675500afef4790a5828436af225831b2f562b06eb8146b057ef9f82e284e586e07a9eb0b7f56ed66f918b895aa25678c68573fdc3871a97ce663d4bb2b5abb35c99616a66c2d22bbaa331b929ef5ddc0e6eb915a01c4dad073923e87914816631aa9e401898a2972d2f29d2932de1f2ef", "43abf9c2ec1cda62c60088d3b67d136ea5c54d58ec873352e805adec575bc92b94754daf19fafdc4b80a0431b05b361ece34866d09bdaa44ab8a0be1f7e57a8d68fa1fb4612c0bf6bea06d9ac2c1807413f45c78b65ec29e1d687751f7cfb589b459601cd889c8aaf27179fb94543c2f8176ee9b457b931c235281a12e2c497f292d556b73a7766990afd859ae402c5da913e2ef098d48c84868f66f29b10d840fba60784580d6acbecf28414a3778189dde03cfc7aa9a5f66d38a160dc45a27eaa5ab12d0b02b5feb280d5accf08196f558bf1ff936aebf60fffac26dfb9f1871ea65c70fcf5b084bd414e768704d785e4863e4ea21477db8a0fce23fe74493ad288dd4ec008e2de55705176371f703f8653b6838bcd130051dd05644f01ba10c837cd98367794060079d705c21b6ddcfabb2309b18f33ed1462083b6d71abd1b23495eb44a72eec10b1873a0ec65f22ac85b0c0cdb33c763af2a9790542670dbd0b66c578c3df0e7af49cf7b77fb6f1c1f9f7641837d5f2f5565a7f23134ccddd417370f13992719c118410d906b1bd3aba94cab18c0a9c20d3b18f2e31dae15b6f565df56c3671455e8000217879b2ae61a2f42c5611426142d7d8d33aded05146d14aa62a575ef051d5bff95dc6f2dbdb958c3048540f596be20db32469e8b2592a84df03870ddeb8834b080ca31e7aa2541b58accdc03b715ff6e824f15", "586ebca91dc88f9105239596fe2d4f187289301096fe55cea4455f5bbc569ca2f39500b4f1f07efc3f811dab421f67caf0be3010b068d5620a20bdc0365dcf8db1e6a50548120a5af945bea6cfbe5d008738040d72cf081311db7425dcb896319f91e90df0ce72a2b9fe858969ab20ea6f586f20648103ad544863081c7e513067f5450a224c7b71db85cc22ad7a5b7a3262b2b892d198c7d42de3710c4f0be99db3401181cd4e40744acf88e6a31e7dd4ff1a0098e8b77b0901f4f1b8f2986bdb2dc5223d94bc878c574f3af7e9a643b2c5fe3079ad9045e675094eebce7e85628b8c036d56a3d0ac1257ceda198efd7d93cd75323f89da5557db64ed4479f9582362808f320cf8cdc07a06bcc6d6c2bba472ac42077b92ccc4d82bd79b8c3189e3c532f998071327f98e8fff39319e9370f9d00379037ce489f97bb32d35b82c711cc194a5ddb7ed5588f6499ac39421e3e684ed6a1b56a992bf2c588762400dc9d69ea28b415ce30abb635ea34467877c44e74aad521baa3b9fb77ce516b29d64f7c31b33f7a47b9244c3b43d89954a840c2af45268c585c6385f807da0a0b96585f90bcd7cd053f1295ac8b536341001ce75872a91405cfba26f8261894736ac4f370a637d6a729384285bd9b9727334b4fe46c36855176460cb3613cc6f9caa33a80a70b9c850c270808a76fb6c1ea6521b5b7d5baf13b86b415df5e3f59455161419afad6a0b6720e51433d90980a8bf21df7dd59e3250c7126fa73b707fed76247cc79ace8a5885fdd710141c0bc766988f51ab3e7082485376b0c8bd2e6717669a086a761b7716f1d6c340ddf945e87ae2f827068ac1763281fa2247320b7b954eeb1280107df24070483dd6483402b899fa168465f8ca19d95f52e4e8ed47b1d79a467c00e6be165b707dfd708a35e0b37a6826877302b2732d87b051f482515762edee1e69aa568941f6b123df16996466fa92b17e3dd037fb607510795ebcb1a864d66f3a891d1e32063d1c7564a9ca6cba08fc0d0b8a3a16755f8ab0592e779141caeb5bc69134bc2a32b93d9441a205162e2f53bc0d6a8884f8a98a893b4024afa6090ba8bc40ed67aea9a19c079b5bf4d9366dbf76b1634d33ffd5ef543b8ca351f7cdbdb1f64736aea102e1e007b009f336aae596233f6448c36a40cb1cd89d671a5d29fea20546d1443045c26a09ba8c0702b109661aa1668c34c830950f637e5f5a5cd759190a9e55387590a9285fe13f0cadd833e85e3d410b0c066d142d1f0ae7fc33ddfe4f28f849190a365eb67105c14b9b6db09564021d45083fa3b1fc62159125fea828ff292c3a888249ce01d631eb85783b01c86d4ae7b4b467a0b5f4631a91752ed3f7504ffbd7fddeb0be662f50d03591ab32a64298c31517e56b401074a44928f02f1b6979491fb4cf7dfed4514ef4a6bb21", .None}, + {.Sqr, "-3a99817b077db04b35b5d153d8ef28973f67a0e3e1e86869a06a6afb7ee8cb181c349be508e0dfb9be424e4f4ddbfd9c43b1dc21ef81c755071d65c7288d87bebebbba8a4ebd63834f18958a1b1899f2999e04e2c4b37c3f47ce65b4adee9cee80c8def5b144600a2d545486506e9de319c405f3eb6f8c93bd39f528ef84fa4b450eb357d1242cb8509b42f4061cc79366b79af05a87ed4c364620d18ad1b3a7b638c510aed5b409b180bb33af9efffb25dca8b05e327c7923504c5e59b3d7b484f2ebea58d2088582ddf4986d34a87aba881d7f0308e38fe6da406d13bf0f8190ab3b5f772138454547dc1643e19bfef3318d3318b3ff00a148e36298bcfd234baf53088343cb6d24a96776380a361b84c4b5cc2800e0552d1072b4c6bc92efa5b802730e242da3cf3fcac9b483faa20ce4bad7839f9034da2fb35d884d13a92cfe87d4f587eb13ceae60e596b00433c15975a6fa06f6d75414ad546c27218aa85f1dcd5fa5970d6820295168434658da93bcd6c9384179bd820138f8ff6a07fbbf07d472dcf3cdbd46e48f6eb70ff14b57525cf2f9125fa0663d00b3193a2546d68c2ed99ff5328b4413d4ce9ca7f9779df42a2aabf5a6ae8b66e1220a4cea6a5638a9e89ff1fcd2f2028befbd3d235750871d99134120705c24b32814da0d2c2e87e9b74626162340c76ed45c738e306173ba0ac8a58f07992db3a5caca8b", "e994101f3f1803e20045023bfdc26af3067d29986bbdde138bbff112702aec004a463ce7bde128335ff1d75d422f1fe06f5cec2bf16efc05b71842eac1ddd64d0513936388f714188adf75501daf17e5cab28344ebe229fc4827c5f5d0da2eacfaef926607c05dc7d2588443236133887d45112041af89891cd1227efa03f36319b5aa070a561954d772cc1f72432080ac99da1c761204d7ae23bf1c7c9d7fbfff6a994392256c647641bf3240fd75f523ab523f48e0ba3af25e7ad8958997fe67af3e37f3999bbab691a45026a5e49510c8f01fd6ed3043e2ce15c5acbd839adab25b3d9295966c7b7efe9ddce85866ab92de0ce9dee6bdcd405e1f28c917da6b0c0cffbc31dd8c9fac43ca7e3a90074751c8bed79f1b3e264439f1526806ad3c782ab01e66e2d98018d939634c49c9ba31f32ad557cf0776979bd5e16a5b29fbc76d71227f9c5e9c1182eb57fbac216e15ff0770c97b072f5a0c5ad99d9625c3cb4db22fcc8529e0a8727e4085adb0b35e126b2567a33dc040cdf6316b173b6b3978e43972c2ebabdf3f765210896cd8baf1d3c4bb690227e4cda8157e6ba689daec3a182aaab5d60754e95e00fe1a80c82fc50033edf2e0b21bf29ffbacee4c0c3aba991cf2a643a2d35925f5e705dd321d805cc7243cf99b109ac453cbc27cf49f1ee04ba12b6929f0a16c0a20f6501fdf2ec5097598c1653ef254a9f42e", "d69eab7c5f120cbace7e7eecdfd386a0f9dd7013126be3c1ba7fc5923634ec559e66d54e678af35882b3a3e881bbb023a4b800717cc64398e6dcbdd02153fc65cd968f6dcbbb5bc476b8af1199997fe175a8b4927ae294c3ffd73e1784e33ff76136be97f2f9414eed3ee8e6878953a6365fd40eb88a5e71f2f43179f076fb6f38e0ef7863c24655777cf6f3543844f706fc9f543758cd142c8eab798e59bd6092c7a28a9182555493322d28f011f95fd70300879406eebafb31dd1371f3a4e62eb490a755adbd70f08db8d52b7add256b619173f5df6f1631d82b67bdd366fb7dd10cef7a8fbc0a507b45d8510355a61f612fbc5e92fb444c31cad0014e670c0871b0f59d13019ff4bf9224466c7a68864d3721c44c38fde03474f874426d4ba9767ea27fa1175283493e02da70ef5fd419adb2a9d91fc1a334449bfa987f4eedb26b72b57730708e61e887e0e26b63ac6bae668eb66167fdcb76fe9be732d44bf80fc82f5bc7a837dfdf41fe06cc7279c4775101af3c3c9f21e1f3020738cc931ae26a5fbb8d03a131f63d79b94c75d3f451b077cbbc577166d64feccc07b004f4d4f58ff9619f349d37439b04a24b8f21c9fa4637c30ff7152c8e754b87c03782153c68e6a6dfacf34701a088e574727d48bb3e0fd42a2377574be1eed7f15b32e8b9bc9688d5e033a1d6b91972439eeb3ca65891fbf8c371d3b77d5f7820a80845dafca99cc2f75a237b7255180a0e4c3e575797b7315f550cc649c9364525e11df19afa69cea895b9efa8825bb4957fdeb7bd59783c33d2c496fbd7d36f058cb0233bb58e3fa5444a2e0bd1ae057843d74a9dd1007093ca0d89b53eeeb48eddca9e3edc59bd46a987046971956fd8a3f5213985016599528973c40a28b052a96779b8cc9b7d7eb4bb7707e54c30a257134326a7ace2294116e860ab40eb404f15c383e9bd7746451fe4e71b2ce9d66f6940760d87095cdaf88cfd34c1b2c556c18f07735ce87610466f113a81f4556b968d57527a71a6d1e17ffd9f95bd30c3da881ca2e8be7a45beb696be5c782cc69b4d62531f45b369fe76b04d7b3b7f25075a2e6422c3f12bfcb5b7f09d04577fcb52e9ac4a4f2e5cc5626b13f567e0f8d0df1be215648a61ff1a46aa1f1baae3742ee68df5cb5a417a171120665a2380bfeffac6d6cd902bdb8b7edd689dc75a6faa3a1acda850ec5984defd051b157f3f80b7a39a69d4a0a5afef892a1d029ec2f713c07aba0e924c36d0b2b05b3932dfa7deda4b8e9b77b092f2b60954fa1b5af581ddf35430edbc405bc647a974d8dfbba9449791fd1e3ccf40fa25a77bdf75633849c58f2ac1f70d020268b148941db8f59439ea25171cff6690911c821dad5387e43d307742943e4b382d6881bb267a0ea6b20835fdf00dbf49a751de8773d72cb5f1e4451261d719ba779", .None}, + {.Sqr, "-a3459157c24358a2b1c25a12cb6a71abb7a0096e9a37229a6399e690d8a591b12b32dd70274cafc62903003e3145b82401cffb2e6603fa22bbe50b499b7893007ddc8610e6071d195709bf9a561215920a1056b9d01dc0f3cff787111963e82b41f0058fdce7fc911e28a8896d96911aca82c71b361e8244e287b8a467d9e845147c4c14b5dac0a993b1a6497d12e4594e0c90366d4e6b2074f19bed0a2e68a22c6bab3e34eaef01686ef03b03e4c005ee67056dc9d263d2a9cd57a31547a59b1f04bf848ac66daa091286c2ec1d61cbadb5ecda5a15e92c86d79a6c0be39e1de2d1db6a3d442cc7793fb1f17225964e93290ec194ea597094774c782e7025283d5a0bfeaf2f484f045c1c24e58f80e34bfdfc20eec61bc9e69329d7ed8a6baa680d64702c16bdfc53b3c8c196be5f9c705c2971d5f28f044d6ca674dc39361dba693ea59b25de77515f891da39a495ddc58ee3f9c1306f49db582a01ea327ee136e343c94ca0875533f0cad159244afa157412e301195a2ab25b2a6a0e40190e4ed56b82095c7455aab9c546875fa9700edb98977312cb874f2a4f720602f46fcc7571f89027b3980e35a939a7daa92c64c56e01dd63c84ae9652f248b498dfb0cbf51f9f85c963b4e46d5f75748d84ab3e6ed6d009b592b0b3897ae0fc9b0bc9188cf3a25108a7f62e001eb627694c78e72fd8be83b4becae9d69ff9ebe8bb", "b2e4ef014ccafe81fb2408459fb4d37308b1d8b429f77d8749611612ebb28b8ec1e40bc1e5efb86cbd36c4ad61f9c4e27f9a6188b2b72994c6cbcd5a9358ec1080232baea05d2a22f6074adfa2026662641ce24a6e32ca36e3fd53bd28635cdbf0344fac798415196e4761ba988277a03bb672f3a0c1d97a06a45367f3ca9779dd3033e9939ecbfb7bf5ab0ccfae71a9fe9835bccadc427bf385faf5f50849b90983d4d546875332b7c6e674f4dae600103c4979655f8bc3c4a0486e4f278c5a245998d0b364c260d4ca617f80696c5fe67dbf8b79637f1027a067b49382a0476cc1e1523f0470f50d646222d4e1908ae455546533875d5f09abafd5ebda9ae312e7d0927f522a510da4364c613de8e41c2d86b4cabefc07520b7ec4475a13d348527be0acfe1e20b7d5f5d9165ecd906cb1f92c9bda8f253f272f5f5679398ca115c305e699a0463f7790416ef692a7e1106fb9a63bcc4af0001321a50a625d66f623464e599aef48366dddabbf6758c178a713579348b2013bac6d1fff719414ad9d5a32b70c65e86bff1206ada305b7ebe4214a94a7232de1a1c877b25a3ca97acd0582c942c1c4f384bf4bd7292da1285e462b8bcef1909dcceb0c935caf918ceeeb3f6256030dfbce9a0e985290934cdad619bc7b9c9c83e660f254f14014ac9cfb307ecfd9ba9f5d7b4b4bd83eb697110f758e8e90c0bc3b7614bae5fc", "6821a9fd6d350352ddaa0179929195317efd9ebf0bfc5a375818ab0a3903bcb6c3604c4e0fd183833bf04d4e84b2f1fb1cc4999c870750b1fbc4a8a087b9625b37bf6fceab5fea4a039a31500988e161c949df7ae3989a5289af59b44fc4aeb60d5ebcd04909a48011c7cca7021a96af5d6d981b0b13684e26a1ca43af9d556fb84cd0e36ab771de7c6181cae15f0d08b76a5135343c6fd9700da94a3101cd2558f4fa0e23a7b9959eaca22fa97c5d8a1770aa5c59eef77131cff0b7220fd7dcd63f3e429bf036e7bf42f267382b91a1a29a4e28d7a94b8776d813e9932bd13bb400733ca489f8fb17cd27a27d2aa6f36dcba083cda42bade99400bd842c4237335acff5a55ddbb028688b90a6af45abc2c964d66994509bd3f138e69838c79a43894564d36ba6538a93bb4f0b7698d20a1fa62936ec8220eb5cb1bdeba7df0a6ec4ab8f6600a38bf2eb5948e47d0879bc3be4ffbb4ec6d15ba5888dd49de7d1446ca687040f36cfee4b7e9399cdb1c8a744e2432699d93e3cfcc8001eeacae64d7eea8b2e861a17816cee3a870225fad2bcd9ea532207390ff34b4a3739b14440799ab341ed79da82135cbcf8fc5bb37b35458b0f5216c096526a807120fde791fb3688754a172060197bd55e5cf750b2c22f63199c1175faad6c9e815eb8c76880c7a8b79b8ad142b981b2e774540b415671c765a247bdd7a206796c39cc23dbcc4d86f6061f6841cc9e575fc3e3f02ee8976c7c99fa8134eb2a6154ed0b1c6588879f8f128f9909ce2085fd4eaa278d349425ef683f62ebcd92223549f7af7d67c16645fddb32cec7d5b388bed8716649d3c81edb9698af2775a74a593c78f5ad20522f3257492de141d451ad39232db5b850882ede66bca544bdeb3ca862daa12e530f14808741b5eb84795e079d991dc57055f73e8e055d005007e50b4beb29332c432c2e75d7407796c52fe9f1c1e651fa87c590764ddecc9c5bc56668a27df138966bc1befd6a9dea35859732af3b6874486f3277ac625ad11705fca3c0c17e58804e10517ef3b8151da790ffa01eb406999ee294c67d519f00e1fb7b73ccd4d508aceec6d9b5a31609cec88a97eda4c15e426f1ec1fc4eba0114dbc841cb1913ce0d446a4321268c03e4dc8f731cb32b849a4d9c8942d018b6ad90f97f65484974c2b85275a0292c06fb71ab4dd0411be2ccf23f7ac5943246cb28775760090cc03613e663a8b7259b78b4b2388fcbde33139e233d6749149f351d5f0a446e4b59354015e3d0ad027461212d2db559f7bdf1dcace36c83e3d75622df8535a28ff1cf2647e5bbba99034d01bf3e5c41219f953b2afb2a26b70cd218fb1c5d7877f395793c99a21c8ab5e6e2357438916c97bfc006697bcae7bccc76081d76de26ff1b92483a730a5bfc745421777cc3ad566382179086806ae0e57899", .None}, + {.Sqr, "fe67a9f3cece862f8374450bc2434253f159b6568dca0947ea28fb96687a0c5b5a179208c151e3144f94da6b6118bd734be8b9c8ea9b119cc8ac1cffdadd4e7e32aa7801677d26ac91f657a93981b48f36da5966f909a59baf3e82e56383e0c7581bb9f75583fe83874f4b0b87399863a15b516a653961c48f3d9da465725f3b87f7a5482eb85d3d10eecb2c71ca8ebec7d4a3ef32483a07937bcfeb0129ea6fae719baf31aa29d459ef24ca4d8aff6d044d2311514a26139cca9215eeb618afd65dde8a6c548c635733f284203e7676494d70617ee621dee2577af661c8cb56f96d8dfd72e359be28d1fb21b617c65c60a22d86914f8b973cecfa4034b488f46a4a2e4a67a73066769aee7b9078f316a1fb28ef8fffbff42c7f5bb0ab5e48311a152f8bfa9a673bb5626289be1833961feae24150d3edab79332e0e6151201f1f1eaeca5133eaccdd9160b81411042edb931b95cc630d7172f8dad5a3d7576179f3d71bd7fcd9b60cf1fa67d8f5235b55105a6e46c80cd7ab5af455b7bd9b629d4a27cdcbfb2571f0dd4711f8f1309a9391c6be4844ac618f09d058c9ac1d71339c4077e738d7b33e9d34ab9f3725ac20cb473d407a9794452e0f135aa455c48b2f25e908256a8459880e767928f8855dc8ca151d1bea1a174aaa695654f515c24522b93f9a6f1ecd13f908df755ee4642c588a52ff93157fcc55f584fa2b3c", "250e1e7b4c5363f431e1cacbdc3553b0964b91114d91d2eb0d780951ff392fed57900b3c0509fcf3ac09e086896732eb1eb382d0d0e50086260735a4b80e879f8eb25e9b95794d27b20b15cd17851a72dc5d2d2b09edca43154445d111dd6cf408b8d377a7a8f573f7524c06cc5b24281d276b0ded6d05e1cb4ae1cdab969fa0e086e85d5f9e096f70cf5f9c3b5b4f7f46f610a8ca19309ff7fe03b9488e87d32da912ef173ff1b2409f278764091ca1f6b2025999b6fe0d4b89fc5901f8f4c3ad69b47337737ebdb8affe047dcbdb815851e1dc15becab3955f478238dad9ef716315632b05cf06538c1447e674714bb2c446383099ff65644d9d5f606724030d8fe9d7e933e0e363585ae5e5ae409b5a8c1d5725056f89b0c2e15111f90dbf6a05f4a060892495d994fd5480db1db1184ede238d21bc8ff051da54102abc6ffce8152576459c38ccb01c0c4dd1a7376cc64722495ae2c0d51bf510c65263a33f1d808a7678f7f6fcb92fb4a89eaa6fdea72b4ae2ca297dfad34e46e1062f15e9ebf322a0f0fdcbb19230d20e43563c642b4565035dbe21cdf8ebb603fa653982d23791cd84aa0bbd0e6a43701f9754f5f5e586ba26bff470e5b585cc64bbc5dece89a58ec951fc384d25520e2dfe5b6c72bc0f74c43c847a84c853be44e7e34ee2b729658a61b0430d154517967396d9894f22f8ae32ad6485a8238e5e2439", "fcd1df3a01660bb5336500e6a934d93ad7c7bc2f61d0b5edefaeb9a5bf4b425cee0ec8df73b630a3ce281c0c3f565ae6e224869d00e507950cee11385581a0267339d2519b750327de3bab49609cfa56bb8fc92694c3857628a79c44d8193ab03e64c9e10953df61723dd1dafa4dbf4c71152b1a15d0c971dd59f7ba7f9193b93adea56ce8cf3b0aaa391889bb35b0134c09ba31df0b418d46f8dee313adaca2aa73fab7bc91c04dac1097b16daa8d2cdb2c6ad39240ea523d40cc2605afd76eca6d305b5f18674fb12e141f4ed54fef277baa523c221f457a467efaf684c877612408c2b7495cc5c1d2db371813e2072ba5f2e65fb6b73a2f0e35f18dae3cc1775d552fc6972a37d32db5905a65a2f219c62bbf9c2758277c4e3a386b38f415f4bd44a8851a9cac58d57f77d3fa4973d88572cf2b5407f1067f751034a0621520ab4def6207867bc6e95e20fb0220f73a3253f81fbf3182750c2ad3b28129b33b47ad1d0b22b3806aec80482eac8f6586641308a18bd3f39b84a9710476840f9f5ae92ea585b931333282e969352ea7d416ae8b1562f747173e0ddb14fdd4bef6bc6fd96765569c5b28ff96b4fe73e016af55c25cf622328e8ce604ad09567b1f4e75c08f7aafafc7f70c116758a58cc0debe50c26b6304e819bffdb29e7a5a3323f1f59433c526301faa76ee0bc245596f899d705eb05ee69974102ff05b53964673edb5cd2d66b59e3ede5c361137c12a6777d8f579bfd32d3d1786fb26f0e65b1b0dfe1b6c97721691c4345b22fa2115c1cbb67e142b9459e7a2811dfe5fdd27f96e3440174b7b4572a8d54d2cbc28a1c0233624adef24510656c6de038eccdec41effd155cc2478ffb2f322685a0d0fe3a7fe6c5e7400173c55f74366282f56c63b222c8756a41bb1c71beb1b74a96eba231e8c2715bd4178a75e6ea7e1da61352d0c68cc535cf93e0d7d8bd80087de4bf5216129fbd2748e0015fb5a56e8c47f1f01f6af40ca9e765baa05ffa31e71098b4287bb62532b38ea991cf44e3895c87706128c318369da36c647336b94059d06a32569a6cb074252f65c344b9304b9eeb218e58623f5478c02185cf79c6bdc9ba839eabbd5e8e66f58a16e06e0c8ea6fe49815075cff14a3aabe970f67e20806630ed3ed0372c33900291dc5f7dcc24fdcecc35879b4089d27473359a210aab00537422d8b3f0c3047592da3eed30da41504fb67263c2fb28074b532dc316dc0c8d3828dcbf76ecf4fcd805ff9676544f678894fb3a627d6af8039fc664c9ad33b4e8aadcd25aae6ac19fa8b25c98d2f8f6e27910c7bc9a449855d4c6b1e5b083298851fcb3f39283779be2ba0bd8ac7eb54fa1603f1540fcdcc247544a2c968a8e030fbbd5995a2625f4821fee2efd92a49b9b624a3e08a6118e57c82697c2666531b385c3f89e6587d3610", .None}, + {.Sqr, "-924d3271bc6298b28caa7e08adaed689c8190341ce887c80d2cc3c57a6f834c96fc9c38c2056fd170cdae1957efa71794453adfcdb0f45b61ebf5f3218c10b3e94261ddeb4818620580abb83cbff8f500144697c6a09098f72395831043f34035dd9b37f0b8617aa072eb414c602a6ea087ef63809ff8d973ed3c94b94ca1b301a2e9006dd4b3ade31b92fc5327baf641aa64b31431701b90cbceaa91c2fbefd81e1e87b0bb8b0b0d09084fb223cb9ff4adb091af6e9e4a3f2c795b4ea8a242bd1630836ddc952082368c51e63a00ba503dd0d67c5075fd745df6fa8fa0f19e21a2d2550c3f2f9b1999f2d0ece56f468e090f3c86621774232d8301b8df803025657066edf78afb10ee76c877d9d06fbcba610205f05aa6f21311b072634bd32afe50cb9de9e76bc331749069bdcbd5e3abbfb7e544bc0fdb8bf052d055126e05f291197e5e566867c6e97723235a2ea9e7a5c033ba0c6622c6b3eed4e7f9061761917ced2607c33c32481bdd65a5cbcb0420f48fdb255103499cf375950c7d16cc6e870cfc7b8e18c5901b5799ec7aba564c03e2880d85abd044fdf020dae3e9d8de8650dffbfed688a60828050b245aa0610d59d4100a7b9349d035657b1b6dd20840809a2aeb814ba0469bfa6a112b3c10ea12dbe00f07294dc4ab569151a7b8c3d1e625a6d001fea9e8a9108f9d9d2a62dd90e1cf6db13af43f5d7f5d2bd", "176e809c1211acd20a624428684a8bb289604a855ec3cfca3b86df6488b0748ced77e9297f4bb4b930b6cf0466a8144c17a63e83d3546327b31569ce321c18e2626f75e27f1bd80d824521e5f750709296908e204750cc4ee7c8a0afdcc2ad1b0b24437c5af826133a34e89f0c724b9d23d87c022215a96d99df07f98a878d06db94c798888548b96b98b322dc263eae45dab843302e0348a8ec525a96b3e235fbbc020cab5b921a8fb53dbba575f242900af28f3fbd1f2fe00ab88d4a670255272b388eb9fd45d9620f8fadeca8b72e94f4690b940167ce7d1453cc62b19ad60e6e76c9e2659d74ddd76b5820d62c302682285dcba9a6ebcdbb7952dde8489fead19882a7eb1689a6220598d37f5b5333b645562c6f98a31e636192876f71a8b5d4443db65bda8fe53a9606593ecfbaec3c9b52d02c8da8364fc797b703f515f41f4225490aa11bdd8b3dec7a7d9e91a1ec84ed021f9dd3434a6dfca743f5f00f315d1b7cb785489a5076fd634b4764f8b22b660d4ffcfb5671dac6497fa3949ace3e9e95ea54a619e0a83b37ca8833d533289c633ba83815173d87bfdc26f879395c8a5dbff8bac9c6e23107d5c5b4d08df4e3fdf4de8c4c890aab0e333e559df994e115a4fe00633069d69d0197582539b5b9bd69b9054dca24cc3b1eea74e07108ed112fd2bd05b70b11fd6f593a8131a4e25c73d683e3c3c2f44ddbd004", "539c24d11d3c6999e12c992401752e9b7510613c5556d829a53d2f9ff689908cf866d38779034d93beb977cfa761466df140e9660a39e82e86ac97f490b730ca15a9e91004823bb78f9656ef70247c19c92131ad0eb9070658e6dfa443a796551807dd44f6235d544ddda6256c28773c699434ab320e1be285af62517793fcae3dcad6ad70a90e5b6b45cac639a158a0b18b0adece2dd8eeabf001034d66ab0377ea58e783d79c33a7c97bf101f8d1e2cebf43237b12fa346cbde89b32e68a48957058fba9e74c947f4a75232822009d4e158d4475ae325f60246fc8de3bd145c12227641e4de2e5f3a8235d6e23101a14813894c22c27a53acb8ac9f3ef95490415410a75ad46db5d8d02ce4874b6c97d93ad75cecf20052c805c8e6fd6e5fcb9c7b5a6fc275853bcc8dab95d0fc4010cc7b9927cedb2f9e90ab96abc09a81c7a89c35cfb86ed9e0347dc709393ad165ee696a55fb6807e70724d54da33386fa95141937e0ff676f135d3a9d4a45ccc21fe03d47462c48e0ae33800ec5c5c8252941cb622a2524bdd5e12bc28ceac3c051d4a15f7b049c8da4a8506d76d458ba657cefe5b4d517ee943972600e558407125a292922b5335eacfee85e9f052d9495ac7d572204c8ccc818d844ea71dba0c4f830458c1113faeb382e69a850c27671fb93f3fc633f57aa4fe439c0470bac65c9162503a98f209fd70be4134c0285fe0840bf5cb23813c46f60389bad4d5660c04886fd7017b6a2cb5a0645b14530c176b2a1fd5855d3cf78fc6da290d9a05fa7c49c97895b77b32f5d1bc4d2bbf4e18c3617c4219071c534e4a9177f3146537ed13798fa35f5109c5ca4363cb6eaf5133e87a16543b18516b7b396590206a136eaa7b2ebe1782c5356fbf6992db2fff1695da917a74b17d2522863d8dde46c14631396e90b011bb08be037d2ea83ba2d777a849606ab0a57fc8551a9cfa35555e443910cc3351d7b09fd720702fb113e8ca9682e0829b8896de136af322ba4768b50466d54e1b138cee98254e8113eebeb2d3bca28b740211cc206eb79154507fa597ec21f56dc64706dad9e67aeb112e900ef2f8e9fd068d2dcc53ec9a68370a38218883a4c7d505755f32c25e9720cbdbebdfa9b4aedc2ca9249d465033f4796ba9a5ba3f49b46b49714477c8c0ce511041222f00d8e66f0b7966c67526594457456bacb58a1214ee33a3f14d71f85a3a55c21644be81f6a30484f540fccccabf50c154816665ed4154bedf60d83c71b30321d901a5c0270cf1dc00866edb50e2f5cb474b90a8ad45e41e96bdf0082d4747505ee18b834529a50f576f02c66c79daee8a0744ede3cc4083a71bc5a1ccccfe99317e645b1b7365ee67ae1b25ae5965b69dfa558f7a80f0d0f5f141d895b907184f410917b224f2c932bf335614fd2f2825ddeb691fc8813c9f89", .None}, + {.Sqr, "-3e6eee3e5d0030a767fc8ddc76ddad053cc4cf7cb458c899fbbc660b31ced2ffb835cbaf3235d8c8b73644398fbea7543fd74bd4fbe030b84d2f1cac1ee5fe6383219a581bd8729fea329de3fdcfda8027fd7f3c37ca7ac79b0050895be90610f388708ff055a94cc2dc7d7acdd5bdfb4526f63f2448991b575a83d2c4aeed7577e3e33ff84afcd76d597ad6c360d9610f0fdf69e1251acdaa67d6ef9af9ee7675c25f7d5d52a7a9c78dcfee3b7652e6d5b1ec457edbde25ecf9f6076ecc8859c0d4165f83d13d1c4ee025d863b685446da7b0502c4fe7c6c9f179eda478c3857747c3d0263e2cacd1bfd3419120820abdb928d8d6e96a532db2129471a34954e2b14b9ef373af6c174780e791cc4c90c0b758abef7c6a118f3495ee36e9a351d4a8ba94ce096ee0c74ef0525e702a43d271a3141ed57be0808a023cecc062ad754fb0bfabbdd9c0a484108948fbb8d18b3158139c6e999926380103b3530c74bccc3f76f4da4811e0011461f387c5b4da6fde68b23e9516dc030bab1f95b4c0d00e07540bac9f1f261ff6c3b3024f48f60b0e469809c40982d37fda9869f01786d47b4d4335a4fd800e915159b1d1d9113e6d9857af2e4bc9dcfc06db46ffb28780eef21217173e6a55e9200b665f350495fccab2b20378e7b1d3de08885af0b382bdd10cf34abe978eceb348bc2f4cb212e867a5aa07e22a74cb4d19a1d25b", "b0b0523751d6926f55f69af43355170af6c0a306946a7802f76bff231c4dc1364f54bf6d73aed1ae7964dc0138723b0053b0e864a5167c4d2352c6b7e293ee99df71e2202d15338e56d08f9269c4ed32a3605900fdb21f054c86573a29af22062236e9848f59cc75c70e7882623b6a95e37dffcf96f5b3af8580989e17b9e6d231f5dd318d7c08676286ed75c04300e80a2abd067948def6577acae2773a6a6dd2e6211dfaff38460e013ae7eaea99fd7c8daa4aab4b77eeb76c5b765480636ce83bb3439f8579023d286eb3c7add34c7bc00eaf219d884dfce4f89fd9810823fdfdf9a97f168b705f4b80d4e1695d69576acb448ae59b86556f9c796321553c8efb2b0d822e9925aa5814a3a8814d5baeab9bb9f278bdca9334cdbce7462e10ffc378233cc30169108c85c877f9a855757784fe69f8233abf2991c9ff265812434fd6f82fd640da255dec67fb089148062c9d966c4013f1a4daa0c31661bed1928f39464e562e799cff4581bf310d05ff98074c55792153aede3af0334218382d0f528394703b3e8aedeb2efb84bc2e0e4a83d68ffa8883d34757f2c5b6849480cc5db09c12f14e0ba7a2fda4a54ca6791a31d0fd5b0e800f3fe08e53e72283d6d6c9aa109d9d262cbd0892165c29a36eb8e125691cbdb8c116c0e946c96a161008aa3ecca753836a52101a79f02ba32bcd87290d563312b96873bf2bf95246", "f39eb77d05c07d86e93ab8a53f0dda6b4531e651c340e06a9e14fe6ec2a7ff45927fc3fc6fd13457cd0b1922eb962abc527e2400405cba652c3b178bb2ed8bb78d0cebdbc3979ae3cf0ad3154347b63a2b671a57500d40c6cfac57893f07d6771ffa3c012a520912d892fde202cd281f6134d74d4afff5f7ffff00e2def18978d15a079ec75783a47a5c771c9d43cc121505b9d1b2a28b6da523978ac96d8db97dc4bfbe952320ce6d0280dd444ef8ba3feb445236dcf3ce5e9f54e1c70f0e2a3de22131e036987ddd58c5ed14b01b36774d1cc5f67c9ed9fa02fd03ffd80ff6c14679a368dead72391e44559aab9ba06b017b7c5cf9d7d437be627c4d22955e0de0a81f57d0f754f76cddc98803dda7dd2b20c881a64bff74bcebebd70287ae0ec31491f8e8b187932abce3895e5dd51b2b7861bfcd7942d1a11d72c2e913788a4f532d93c3859c177b58897c9cd819adc0219813cf1a82dfa3aa1bc32be27474acd0f6fef2a8315060dce7b5701f578aadd332f610d1226533599dbb6e5609286792fc2d694cdb30fd16d8de0836fc990a441a40b57ef442184df41b82df4939d79aa1cc19e56dea106a1b303364a5bd335c95adbe7774abf84468526c035f1cf5375bf953dcef0c1c42e55ea1a4ab694b7deec262a23809d762b14a89a1d49ddfedf8c8988ac8e03f7c91de45bcc18a6d011b654ed0febd405052016d6e6388a34b8abb388b0af863ca96c0c19630d0b880de2bb09b7d23f0ab19d718328477faea17e744006c9a9c7744f5dcab2ba4275bd1b1bf3f55edb2adfda1bb61357432ace636bae4dc3357c460f6ea71debed4130771ad8e2580668a317cf29ad23bd8b78493505eb029b4729109114384e02b57674d05e99c0e6fad27cc38b74ebaea2e1dd9b1473472d75ebc24669035744a88ee710a44e306c7adde0e3c626c6d149d27b488b7c57606bd10fbabacc8465014d4788de6bce6e23f1704aecd32a08ff2acd3fbdd66d66d11463111f8c6796642942b0a042e27e6b8e6dabfed604f21a122e4f182877a70253bb9360b896d9ae1ff81996e3d6e5fedaa4f1fedf8bce7601e2c2ad7932a7e8075454cf49baa5bb0d3f203dabfce5b90fcf2753cc667582c1ad5c8c4606e4e0af043bb5ac9ab3819b9fc0579b0d90fdb264d5033c5e528da9b4d6e86a14adce06083e1dbe798389589a161e4dce06b365524917b2c86f6533caa9a57d462e0308fce5ffb54823554341f7b0517c438e5cb4815778790d05b181eafb089cbbf374d4388c2e69b4d13f423597180440f1dc5178b22cc02983852d4162a38f61ade648f7811474b1edb4aac1de6f779d085dc4bf67c36dc45df1b6dc8b4778842fa2f2dc4a277f933668e099609d80e20779adc62447163937e88ab620b3949b97a075476120d4188cd4f5d014378ffdde1e094f6c59", .None}, + {.Sqr, "-1d198085b56df143f64ffec94d33672100970bd336e3b69d8ed2e20d34284b7ebbf8c6fb014aa9257c532eb987d54c381d36616bbb3b14a25292a9dff1913a2f7d9cffb347e08d8edc9772e1d35afb1a479db578f172aecda24c44fa1ffd1bd0af8c817f3197bec1ca4854803a222b79672bf554b72f9ced9175098234d377de509e45bd2abfbbbb1728bc78d80964fc3f02f5750b6cd4f2c697dd008fcfb178d2b885d06c64553c773c0080582636a1d9f91e57f5b7b42ed7727ee48881e2a8660d268dcd6ef462ef31508ac0bd4dbed739dc36fcb44abc2f9e4637992b2c5dd51b8b0311fb58daf36f3e83d2caa817a84da56c95a16501010f3cb6747c1db9736394280f829b002d3d6daa18ce010c0dd6c862636a8b2b9f4d74f96decbea67125fd67d5493fad555512d7eae3f2bd50c503ed7a74c9c0e598667badaa0bdade9b25875c5ca34018ae480c7b55875126de623b980f738f1756330ecde4771079b5324a0c6ab6714053476976aa48e50bc740e5fe0cad1c00959f5a277f1660d8958cad3e4e51ed419b69f2f15afe5cefd44e76e1326fea4b850cdef79d9255a8496f14282c51b5ba5725c7019021d68f821d23a07d588e37098f3616bdf98d0eb5e20f5c866e84396213da8fa5fd5b4f7061e5ca0a96ff7850cb411eb9a8f107d6a83a4a64219eb7a65800102c84d7157caf0d4c767f44e0e9c32c36d9e31c", "a845cd006b55600f84866a3c4f70cdf00bf6638b2435b77a4c679ab3914476b917a2f441c93cf219184da7185acb08fd8f5c335282ecf9636d180e03f13b710038561ee9c225845af485f837794f2e560e339bb935791ca40ad0b1addf6b44010632855e7586afd2a318e49780d5c07bc3b786d6b09bb10de766892b904182d0ad347774b44b7690b8c08770dad95b04392acd0daf79e047e4df61f7e8472c015163c6df4a0e68fc0f25c22a416e0b3ca08ebdd46402ab827e32cb5fe4ab96ad08e0e07ea00fb7df2bb79c2bde63c55f5e594ca14606fb020f36eb3e1236cd24cd0f02e4c7f6c12a14345a675e23a5821d66f314ddc4fa18427f26aae1bfbeda3506397b7940538f6ad0629e3a67c73d4476601709d25e50b7bb2a8c6e410aba783a8125856a129a2890ad952adc71fe239def5b6959623d16751ba5383e198932116871c7582966594a707822fb0197dc4ac9ceab5ae64acefb3deae13423ce7013f21e49b40b69d9270345cbaa07739f11d3b88e65d23c3fee31cc51a6f0a0bc6edcbd670d3aea77d38c3504b2b77d0d4c353e32d693c9652811ed6598430d0909c3848bf44c441dc7c0bd80d27544e9fa31d30bd6509309c91b76847ea37a16604d963a9f63c856a8be0f169ec49ef126e3d633d9f7f75eba21bb9c4852ae4239c6b47937f0b58ace8f3095c2b3f8e9b6e19635551e49598c4106c6194c7f", "34ec9a8a5be53667b2988a8be44a9fa5449240d9eaa8958f34fa44a32475996f905e74403edefd7c8d1cde01fa255f6b89cf52810e0ae3d2884f45d9ddee2e8819093f2ae7d9d2c015798a556262b1c9be677254e946df138a1d2bae091d879c228d7d8014bb42a39bf61273e325156ab98b3c0145d4a755b7d187fc1d7c7519bd0045781d5aa1480c0a2b8276431d8471b13e2c5905d599daf27dd97a998a8f10b975a9ff2c21ab19bcf1eee95c67d810b93e8494e7e5d2b4f20ceefc0ed41214cf1b04bb37d1ead2c302914c005fbecb3b719b01000faae46825beb3696cd81d09b7fa7b2971d37cdac78f862eb6022a8208316c02809af0dd6344627324bbcbd2f2942cd79c8b45c6252b290ec07a6d4043258f4c4e43e70252b691b15f3b98aa8846bd49df107fb405e267c5a8dfd381cc5798ba676ff42d68064433b8c16b5f7f5a85f5b4ebe8b4263abd8af4f2b1895aa17c20278fb8c58b7926a06aea2e32bb8c6b94eacfbce94bb24bcdcc7bbed1e0707149125aaba421ff6e52d7f43efaa8da1f184040c98ff04ff4ad09800a062999d66a61b0b4b6a0a2ae8627b03553fc3b6b989ba0b2fa78075f363ba08125a0dd6a9865311260895b6f1e1402bd3d353c0733a942ac80be1dd242dbd9e3ae3556a3f51cfd6901cdf3c71594802735713cd56054cec2a6f4752d521418afb5b65b37c569da8727ff03de3d377fd5d96526585d0ed28e8a9790c7db0b54f189cc9c37e9fe78dee815cd39f89d9ef219f12c91a1e712316b464a883f34f8a5bbdc161f563b18f903f2aa50164f51d2daeaa51c0f9dc2025d86e52dd3d0339860fd02ca6071fee589d3a7ac10392f330c8f8310ddbab65e9f3ee4db22fd0d9ece92c0e010b61367097062f816574d0e167bf1a0ea889897eefa9a589beb9f29b402c6867dda78e8b2a5658f468550342fa013faafff1244a7cb5da2f699997d1d326111b982ffdf649676134a5ea75eb6eba39ccc3bbfad5e1e888e277aac9c2da16442e134a7d11447a5fa738624254b9183a2217c7014967b7e8c2808792deefbe146656a37fe21e3abeba33fb4097bf2f70a86fbdff5e450223f7157b8e9491cfdd257b88f4140c7245a742d563ca34e19b450e4b0c1cd34f744b500f25538dd374ccc91f178e4147a96ee378771d023de63b63a50c93c4d207463acc421b1e62f0228ae5e079e174438fae0332c5cc61eec7ee9531cf3e5cf8e66acef9a6b10d1deb5e1c55b0babaa8916f63dd0b6fd57ea90b6a3a5d89ddac3f8018df5cd609d1117e52b5adb326a33cfc592f39e49ee42bf64136b4d88da2d8a4833d8a078c37f0335a69968edc7426ef608daad15ef07179edfc2fafa5a98ba1c7e0e2b68b2de4faae8f35cee0432f5bb881029307c286a2d548ecab81a2890dec7084c1798c2bf8233f9b5ee29ef2ab10", .None}, + {.Sqr, "-8cb4720f7a6d5829c378367bf657fae3cacebc8fccb47e3459b1bf3dd23f7fda3dd6bc517bae86f5b76f31610f5748dc58f2721aa8e42380b35b360faf453f25c1944086f95db5b9d792bac1d285cf12e32a5b1ed235b0f9c846f92435dbe9dabba0faa89b8ee69b9966ff154e7b6d76b87773f2cd048fd18ef8c35c092805d9e2cac67645388d678d150276f79b4aea3761a0535eebcad9e0689005760e73e0a223b13c8231ab3a8c86189ba81660e1d464fcd68ae3ed6164e7c275a76d422b413ddb9dbd4441ec013f40dba6df74a9d0bf561f652f87b980960dc22f9bc9f81b63aa3e73532f6b81695e70833867a95a53a014a447fa539fd1f81199f8b3b3ef6fe961aa114560f2b692f0cb074fbbc7502697459d0e12efc1362e24985d64b2a812db2c09a9342821bd90989e03a190a3525c45edce15cb0a0eccd6a4c694616aacb08ca57615868a24901e62c887753455de889448a96909c84309bf5658cd0a73c78877a70feca9310f711e6993627c6a9aa44c48da8d08949469c7a3a9c7d209d7bfcc87f6668ebc1a1017f1a07850c9fa83272e19429b721cdb82d95a18880250a973d97a336a5e0bf6d41329a2b818a1b909851d49b36d4a8554c36720457e4bf14928270287c5e64e1a38ea7d93e6c9fdf9be96728f7071eb4aba7b6fa4a08a8f737fedb68b7e9344c86906f78420e52d12439b43553c20d2187046", "f9682029b82d480223003398253884678f82e77c86f277a11405f604816d16b4dd15f412c1f526f80b7cb37e3e9e989a16103bc9a5761c57c4f04c2d5bd14ed320925be5e36fb6e4f8acc9430e3f456b011add562c9c2edacddd3e4271f9b16fb39e8712b0ee2a2e4bacf7af41c374343822c36a2a343335e159a9175be86ef0ac45ce2b68225b212db17a9c4b185c3b11244b020961e2891f3817ddd02822fc5c2a183de4faa84326236b7a25a2364c9867ef24207f377efeb520a7659aeea6bba531569cc2fe270651397d00e2de8d61b8caced12d7e06da4be99470d9459991ecb350e5671e2063db798cd7859273cb5598008c87138afe836e921e34e9dab58fe2c36a22b1385325594fcb47f7d0d6ea66cd569bb240e9f6764c463971e26080d41b469d7e863e0cb501cfb239c3f74476a3eed92fe2a24594ae2d4fc1d00aaf812e15b48778c8d10555ac3c8fcd1fe2d83c87a42f1ca72896380fa21e8224a32c998aab2294123cfbaccc6437564822cbe04afe11b3dc48aae9673b3e978296327f44758c92790a7afe4d69d02ed218ef5b3ad1907bd0904415a989e1b676397afca323e1dd4f5f075ae831ae0e4c513aba198562a104d69b856552644bb86d868f9a3bd939612c8cc8429e98465e98b6d2da6ad49cd1737913d2eff5bac7f023df689b01410a84514c8631e5c63df77ce8dbc679e6832306e3980ff874", "4d55dbf1867d8c2a9e684a5c2c9b358e937c42da7753add632a70be09e0e676eec72ed97dd6deb634970049288b2870316bb6c2f25e1e2c56606beaad3618e077e3fc8443ce7ff489c3e9e09f5ed845223f0681663554b7630a462d5dedcade0f08409c6c2e8ef3d6c9b5693a1a6482983052ac7796624d48f40925585572ce81f3b128a66dc6dcda46f5b0db73d8983897f8b640ecd59013c4fb85ef8e13f114eece54a8ecbdbbec0f09b7f81d549da3bc4d93c975935c756ecd0e462d93926e95815690019c6ed31302a32dbe4699601f706b703461d7304e3a648aef52322a500ae50ec96fefd76b732c5ed3200e026c84241623199066b27bf78c570d30cecf08044c457d3f380a0154dadce6dbe9162097f653cca6c12ef1fd3197290e35f703301ff1cd3df3cc8c423c48c429871904a5a1aae99774845f94c9a3a3f9d9614335b50043c9450e5e56cc0361f29d41258abf4e36496be14e4aab335810362d320b60d4c2609efebf976157084038534381253543f3703b6380c4e0de1d7b1f67233511f82dbc4a109239b7d485fab8a0715fb92dd3e1b8f379b70fac5de0ea88bc33cc38a075e1fb76bf7a265145cb1981c2dbf11181e978692069abe728e37a0d29bcde7fdc7cc35bac7f50f8ac7c983a6375a758a59df644834a39c6d9b94f0431f02c81b37d4f35dba0dea6b3a1844c22115007f196a526e9d7aab13f052b60b4e0c9bee7d4da7329b6acf34b92f3d0448dbe88304c5308944f96fa2862accf49349df816174d5e65c3cb69f9edcdc4d9c0e407663b1e4c4d753ca7edcca5ea18f50a91f5755be82845e0371d4f45d268a4bfb7b20489f66c65222e7c39be8dbb4aa323c76e3c7bdedde3f1ce29340cbb15b1b01fa3ec6dc381b1375fe4fa2a0d680b401145b06d770fb37cf3d81ee407669f3011623418a8ff2f90611206bc969ac4afce9bbc26fd90e891c6ef6f47bfe56b5c580921c46bb6c1be74b4b9fd176c60713029a3df6a914be638045d72d2878e7d2add9e8e4a2a8ca6e21508d508ce0e06e879689eea7ffa7d7ff471f7b02da4f76c2b8cd45e7318b96f3d1f91793425bde799439cf5f4879b62fe370539ff23495fef37e5ccbcf37609fc95805cb582e69444a84ea0a4a5d8e7770b584c5c77622133c9ff01925724cec3b2df632fc1c4f5742db0c3a53cc4fb8cbea6a02be601d076df02c43713ca2e957f738ab59f8ac157fa5e0d04c66718a8fbd4c59c1b0ee68515a544f1e9afadc3990a2c4b6925c0f4d47b54ccea5249089629eb64067a357ca96a872f66b8080a12437a1c1b70b7ef480e84b0fb13ee26671757d722070fa47c28d7ad98e50f3e20d3840ac417ff04a0ee32f4883ff0595a1e100ef97a12c93b9611c8eb8a988733090e9346fa6d05ff3b5c8c45aea0eda37b5c4184e73d9a4fc08165d5324", .None}, + {.Sqr, "-328f76eab9935444f4e90d778b4223506ae32cd5a0e7ee112506bbf2bbabdbc55ce2c83b49fc0be9c6e19c84925b28dc2d2d8e131a68edb78bcf6c2b0e16b5ff578940d0683008b57e2c3de10cd605411a226e4a01a0dc34e6faed131743ed295e1aaec969ecfc009a138ba3d59d0a29b6d300df1b81875b310bab2f27309ee23987e351a3efccb5893db40dacbffaabfc5933e4aa711f5ea71a1e4f109b1e9db9e6f3373b01bc33b27127dc5f42abe1d219da189c64c582674cbe106487b953ee0af5de7fc4ec620e5d1f26ae97a24e8221124c82ca04531836471e0fb0981d74391b777120231651481d45881b0720e121d70637b026798f5b337e998334b12a18616da89888cf023269b200f68d7f8777c7e9bb9c610387e21d0c4e5af1295be402c68d90cad8b69085a8a924f37fea883d7d6e7222d33be565abbf57af176d2be5fb3842d3cd1451668566d4d5f24e816fd161d02b2a6e99f5796db96fc47b50a3c1b34816fc28e065fa5e28b602e69d27bd342b2c39a435af566b0b5042e89dc35fa783916957c2aee99738d799a51c91f1a6de0a6138b5aacd3ea09c30fc635dec0b82982a2eee01d7d160b3aee4f7a0ba2a05bea06171606fa7a1cecb06961fa0f246d1fa19e34c573b4a83915536eb9b193607fab736de08b600d7290be293fb718cd5f54eabca52db8aada18f2f481cb5acc4c3a152f3e7de12613c", "49137b088773c3481a2abb0a5737d3dc17fee14d5b2e6ab99e18740675595656bee6dfdd0eda9b9cabb7ced420a7081a32895641f865154bc34fafea673f644144edf62ccfbae431854b40064cab81449d16ca6f3cba54af734f9e5ab8e5bcd8de2fd510f8904ff77e8da155917e59db55b87237525cec9e5654438ec6cd50a8cbc9de722f4fc0b522b7ba712269bd2f22ecab46207c194e72e725d3f90cc36e9fdec116e24f57a4e58fe3ff39b412b7ebc289c4a013384d9f89f02073354f9c0f1a79595d018ced8b886b6a8284f698890d5b4aa9d897fde93ed8909089e37367a5582c0e241a9ec250241d0b361b44d4387227c9cb090bee687256dbe825b3b8ca3dfe77492d888975eb3bac3fc08122d8218917aa099aca0b8a60fcf20c27d39a5ba474b5296d1cc8d60a26abbfcb79a0c941688d1779d33ae246a93d80105c2124f5f120255a5d146095f390fd088435c4b3a8ca10583a6aafff14233df2d790ff6f1be3e15e265e0d8ce7072b0ebcda8fecfa1a79e6443232195e1d4264c71349c61cf7c4fb7b0c75f15ef2dfce077a492f7835e5092007a6e2a2909c010ce95e566acdb9eab354a918b7e96a89e0b0f4e1887fdc430b34663ebc296a61607fb2ac0a42419602770a0eb7e46a016359f9abbeab6cb3be83683873c27be1d6c1b5084350c035d22cd73165ba6989c94db17ac226b236480d086f12271251", "9fc5ad9c1f619ceae408a0bdd51a902a0910e95ef14d137ce0e89fd66796ea649d49db69ac0956f047b26e87e3cf4ad58b8e474228d9bb4c3785d5d0ee8366155b54e3b0937d00ea1d12d191c287d526a8a2c0f99d44a377e3a3e0724bf77bb1f440657ca9931ad2690406c4e002dde6e3114dec5176b4a77105ffb9d9826057cd46c7d530a12fbe38693c309582af334592d8fcdf83b0c7a9ffd478059549182162afa710c3262298258cc9ff2eb4abab28a5e1639a8f3619fdfc3a5de288902a94e2be5fe590c668fd25511ef8b195e57bcae40778d25194f0111eba9b6a8685abafe1c06b97a949031cdca88524be5b76e5981bab0c17a537c4a686b4b54b590188e8baa402406d54e21f843deea53226fd7dfa45d81517720949272718cd8ed1c5d68d0ece38f3f55ec08bd19267908a1349db5edda74ca00270cdc62e29b7614b6ae51ba0422b5da0027fe6d12fd8b8cf4bb6bfc7c09cd9aeb49bca908e00375ddc90b56f9a61a6ccf880fab90c23135d1d8c1547e047c918eee3cf652d81c3a4aa5f5365a444e6336fe9e25312fdf91ec2620ce017df6115b372ae4d59827da5737a70a516b684d3ac1b95ce2ade93fd73a399bd99cb54b49b311ad585b5da17a5b1b42c986fe38b1939b5ff84414e6ddcc500aabbff003daeaa1f2e94665de85540e3d0eb434429e1edb11ed845a9ea1bb12b262ca48942c48892b71e61be65e87413d174cf3e7a82494526c7cd94721e08e899721fc8ff607022b5f649fe6ea2483fb8838b543dc86d7be6742902c5dd7685fa32a3697bd4a390e13a71feddcd737b77b335eb6a624f0f9b019d55247bfe45ff9a7c1f60838971f2119b9f5355d2a8d5fd61f2a4cd2d522a4058be069b98d3b66466bf9ae030d0a04b266438c6cf613fdbc83472e7b809ddc496d248fa46443674c166be4f9c0f676f2ba85faa4ad1168a82650f435ebb985fc32c6042264bdcacacc1280bef7a0d9673a1cee74b5119d9e58b6949202b7adf0536754c1e8542d702306f71d15691cc4979d6e8a82f2f69cdf4351369dde6fb78fbef0bc77b0de4a5026ae7faef66ada81d9658928972631945c1a47dc6e105769f9bac63f150faf31c0a7ccc202e0d4b9853fcb1ab6ced0086f11b4c908136dd67cf917c7b7fb873804584e62170c9f354158c5545297d230c73fd75f1e04703895718c64579d436aed702f206de7a0c069296d95437c79aa4a3828ef5c5e99888e7c168aed897d76d6feb8a0c16bd51514d03c09cec27faf6975ae3cb4ed56f49e14034ed39ccb9e7dcb74f85352c8c4898970f07e7c07c1d7859faeb43327d3b46549371545e4823d34f512eabea78a1fc024c3c41a6a7a5ba4d94b331157792ea72cf8502bbfa63a4ee70c8656ff9d102edbbfa32aaac4c5b9d409795f75db7c44c3c365152cd7443de15e8610", .None}, + {.Sqr, "-2cea0b33765bde1d8f8ac9f84736ac18a073733da6759375598667fa747265f96b3b6002492f1f5e4e94da5495231e31f9e3600f60fa5e085d97fc73cb6299e7b67dc62d33cb31c29a2028864f38e75af50bf9a69c2fad3364bab9a802e76e726c2b6ef28e3940bcc61e2367b2d523af84ea9f4159084420d00a48bf0677e447fa5a3228bda2ccd0d6a41071261ec111a4d5ac67b9c64522582d04aab797a6bbb9c3cbb9c4ddcc91c04404eefd75e8a283f135596162b9983abd17c9b969627691fbb72d69038a3497ac2766117d9b83c15dba278c812012ace71128444a9588f50c19f6d6ef1e03ea70bae285c841379619f662ba8f470dfa7d1e4e5be8f83e082e29806441ca13ed72c7cdb56a232fb9cd3a08cfd0feae661fb2cd3969680aa1cfb04b2e8b27926660b54956ce756f86e6a3b99a0dcdc525ffbc9ddb2c6bb631c3a0b96b624a1ce69427f08146f056986550c527da3263e2ec487e71d72a81f8e33737683f8dc5d83f275684fa61d5a27ebf4a75a99da7dfac52251ac8e863a0668ab866cea0ebd4f4db1364c21321efd3e46f4d84d0b7ff76394f83aed04b87c37520f82fb0133c47f52f97ec897a3878721e02429663fca56b477c31774ab4ccc3f68cb3cc0699458d6970dab9f0f78b0dcc5aa2af258a81bfcc8a4b416eea5d28e2b4f66837c699b1eb8fe9f0c6d3718722b1de4bdfea6bdea8daa942e", "be011e1427d96f24cafbd82d4ff4b03cd9514b671d2f7e6f3949ecdb477f9a2bfd14720137d5a5d8bd3b1f54f26fdcd65b69594fb648c766a888d2bb001d20628560b26cf83fabcda42ccf3ee1a9272bf96c0e49a7fe2ae9531d4c8d0d54e4c6465d78dd5b69eb804a9fb5a1598201c8211e75b88fc39e3e780ba306116bfabf847e71700ede7ac0a60ac2ceb0d09195881502930af6baf0a886a907f6a6b15694972a119f097c1c6118cd4653953d55495995379e81c4eb3fd1a1459c70e398cf2360dfddd3134199b1625d66f2c720c9b2437ea4b0aa0e86f5f40988a58e10d4c47c805883c58b83c351e14d22d3c93b81a3dd17e979234660c18f70dd37cb545cccd4745e219b748a3cabe309faf1d70d8e49803ab0d6bfdf406dbe7d04e13d48f8245f91f1bb2218065bc84e3b352d1de1120d034e954b87163dede0ecb5e12455e0d2b5d1928563bd053baa03467ccca4e7c06e6ff049457a456b89dfe04cd7e9a0bf6b1a6b6ed36c7097306d562d7a92e4519b2d53ab790192b9ead8563bf7cd1bc5dccb339773fe560027b9a980205097f721d9b70545867106f398f221683763745451db8035cd7f7dc3373a8726794be6d0e0f21902a702857a2e383736480ca739fe16c69e76214d2ce93e508bc70d516f79fb605c38eade3425bbf5338aea90f56e0466d0ca2308d6fcea2ae954d9a6a31736afd7be59a793e21c", "7e149d22b416ad07bcbfafe9b1411612b21706f78b1d080a5ebea200ce362323eabc1f414b3d3c031b142dc1018a4bf715f4c2bec25fdf6b93925d964362e768118bf4aca490756c7c98949300674219a6bf16a087498ce0a7c909d4dd150b77b3a7cd1a58a484b80f40858d9839a0532ac587b4322240f29ab58066f9e815ef2be955be6c6d1e2b84376f7f9874da1c1f776ed132666c75bc67bc92fcfef6d9ca8035482c35d009e69c462d6abc9a46b6a3d03fc7fb879a60e0b87bd47ffc300e9d9f7736c3f24938d652967680fe3a324014adbc27b2401f0affbccef7e1765f7e0fec8549154d181a14d2810defe8f1474c29b4369b3fc697e978f30c3e744c20613ce544065f1791b8541b488126c32c9b2bc8e80554b3869c66366f5d94625d8bface3dbacb50244f6ab412328e22e04170586d1cbcfbcd33ff3cfd61cc120198e7c2d394c06e0783a6ef3c1909ff50e9edcfbcbe0d2159f258aca614ced8c7c3a803932ef09a7cd1ba23f8b29f8738e7d51021e44b46e632e1ad8257d48c33a9d8327ad15b598c402325f854f747b7983668bfd5116abb6ce68803d6219ecbade168459e671ddc186b290b184ed0b03ea727bfdd034a303d26b45f8df6c55ebee35f7dd8b84cedc9f8cdb8be1a46780636bd40c41754594ab90455cd49623b549e7777df0938d573750f413a2c04c8931001bd0f74acf598c11a10f95314855f19ed8717d8bbba41c0db87b1048dc0cc9ac8538edab732f4c7753cdf6254bb825d6d75cac9f30533d872956cfb2607a5f11004fa99b0b6462e98fcd99b531d94c63fd13abdeb734ce7f5d3acfd0211525852141313b8aaf82438c25587f27046a7aeb2cb47a425f8716622fc4d8d0f6def7ecdc8740757a125b5b363da520329dc621eae714f17c2b84221bd80ab5abe209960665c5c917847c1e92e1368d50c726188ba171eda76231d8b61362ecd4e6c4394130f91c31842c7c7dfff3cd462d7b377f5f6a2a18e7e14bb2ff4df9502e98e1554b001468bdd29f2ee09246b50ebb16f11e09dec7d45ebdb73dd54826ef37c1f06ce8e2a1f4f8cfccde6bdf00dcee5d673944b34093b20927603172ab34c6cb2d46ce78a1c1cd8ebfa321024c203d1e86f7d6d1e99460c582e12ec903f46a8d0c9272c83869b3f45198da5095aa4ca69ed196aef59986b9a78566aea0e8e9dcb1f8685bcbfe2e200db758dd7833bcb5e7f58e2d6ea0ae7f67eeb269f51a0433a1c92d0379acac2c5cecce6e30fa36c5abbea557e5cb146bd47963192ba9f4ec718bcebc53ee6bc04f77734cb7379a8e9984d911764e1b031c6460b64b8728128dde8fcd44395d478416d33bb6c5ce183bbf6d85146ee8c73d99f81b7a2097f363eaaeab3abd0ccdda8d3095c35fe25dbb070bbcea31daf96fd401858a566f1f449cb028fbcedd3844", .None}, + {.Sqr, "-5a61ca65b64e95da5e2b2b0475931893034c6e5f2fd522aff6af5f1304034c0fb1777878d26441bf9fd0fdba0e4a75207c1407a0258a56978a2db3112ac17157cc4f9e3df3b969000993d7e0c94f787dae58608caa7ebcc286fb971071e06aa86f27736161287d45b2366719a461c54287b023d10f96ed22450eeed974e39a7229a509826a6dd4dc4aa5647965248ee4aac0c00ed6ed4eca30199109829dbe3ab453d8892c385675c16721a7ec33d1e43fa641385e27e8ed5637ad3540ba6ba14ae346a879170a920c54b5f8026b27eee3910c2f87b2f140f97a01e46589523d7cce78d932009a3741aed0ff09e29cfe6a863ff54ad29d2f80bbb39a6e6e979fdc3814caf92680bfde7eaddbad693a750509c856d2d54acf941a5afa57acfc852c801ab8593558de0bd36c45d46bab9f33208d44b41a67b01b79fbaa6b0a557798091e204ffb533242f398143d37023160f5fbc30bad5178cfbe9f77d9ca50044351f35a08ed8560e1129687e83f9d4e5295d5d0c879f83a07269d53b453152584ef7c2126348ed7d90c46159e4cebc77a9dc5c1736dd4ed436cf0fe55064bdd112af7fc97df30608616ff66cc7233675dd971384f742f79f6ba5c6428ccb3cc7c0e17bbeb1c4a0dd5ebc0311d2f48cecd4078256697f1fbb8f8d5b08e9cbac031402e53596b0f463c8d2aee150370aed993a47f81d8c13fc6f0480718377930", "df9fa8bfe8454186cbb8a62c9b8cc4debbadcdbcc1e37aa97d155d4c4a06a3260e444664b292a017f819cd3dea505771b311fadc568ccd3af834e8e15165c2289d142562e684a46de09b1fb9e0fd043b8adc43da554bb020d3cd7f96591776540fd52deedb71a999610359801838f66964c2e6118ddb019e4580eb538c5f7291c611353934afc5990d0b6f17e0b4018b8f0f152e1b455be28811896566289aa622f50322537ece192e2ceaf529be3de92a30946dd43f2ab4d874fac0d7362316a45d405f2b0bf5deae7c1b148b0718544cfa782335581f6c3a4644f560c3dec4fd455b446484613cd050a116551a7653684ca3929a7a45c82d0a2b8f6cfc0d4c71316e8ef8e96d1fd3559e32ab95e1b129a3037690b0134fb47b249dbce29d7854b0fdeac253a1102ff5575790dfee5f7fe48beefead000b027fecd9e0d694efd03106d7380cf3ab90ec915f07c7f6ae7149e9f221a994c255bf7d59a308a93a5b8dc154046f8d895edb5cedd4ed916dcf4629db97a67b6b18980b88e6c5bd476229742f13e9acfd986266faf9f2d644ae2be3e25116b96b91a71da80e7e2e1ec1cec555bac39597ad62d1a750f3aefcb7a100ded6cf0fef661d394dfc101ce0149476c7d2d566e758c0d4f810056ee99e8074d48b1a642debbbdeff90b443cd261c66d0b7d2f0163e145b0ade6f95aff7c29838ad610b40186e831a8aacd091", "1fe8e7aa854815087a04671250ae312c38b49ea406bb1b44d10b784e19c98a0926178e2e34c26262cc1fcd346c96083763657e51bd3a92032d6746fa0af0840b2e8fb47abbc6086dd9dca82d4b5215e5485b0af9228002f54421ef04142a693298955789758fb4e4e648e972407532b444ff38469ffd5d4d823dd6140c2388181865759cb7cc314efcd5ad2da8cdc9f855250dc26d3882351d62970ad99851b4993dc54df1354a5e21b0ae552725e9813091de3c2b8afa66234d49ea884d9a3111b9e51d2f1b71f7454e4151d9d631e9b7fce85da3217d8b559f8f566d1aa8b466cf2448752dd64d75b57dddd8df290504a8d1bfdeb404a171091297709378f3f17829b59ea006411e87303d8b4916cca5ab90117867a03105bae7c5a8a086ba6fcca86ac2a5ada86d9a49a1de25cbb8f9787b871178c61a7c0cf1410bf76c771563d159e856570fda89d7a0e8c5ba6ddd00666b46732993c8ed1a4611f7a6b08b198c3d74304b291f1e5eff234499e3c0a0e3465cc46d5366deaf029416d5d61a4c15af1a1b442d2fbcf29de35b0b76764632bd2696c889dbd967692fe8463a15fea81e81d7a415609910f2a8f6514c0c2d4964d8d7fba1642f1748e06ed0f9b1a6ff427e5c329195ba026cddb9f528528e9802b88afa1dfcf2723094091bc6181aa4525acce48c24c4363fc20ef0eba238d7667e609fce53e6a7761007cb2202b892c556f12f6108c30e6e1c0f4d6e3c342307d6f0bd718b0b76de9469a596a62cd9049322b8ca920de42d7d1a7a4891eaac405835585cc2add54997101a642be2b1b26c0416c64413cfc8351d8267132368f13a07ec09b3e8ed112b901cab4e9d52cf7bd307bd607b6b2843ca440919b18a035c52bb9c394a2ddfb87a7a9455fc46f51f3b4aecb22066f6aa5639f72c73000f7c2fa5b8fdf5c0e7c03c5a7c9911a5dc3622465a55da9c533d75c281b1637a25243ae1fd4f357407facd67a78b07ebf8894d842405a2149f721ba0ff5b8cdcc376d4113a203fd4abde5a66cf10b3db1a9bbca07b6c49a4b5d52869b8f028a047ee3bc7c28715c036a036c7dc1ed4126a6e604e2eccb878ad002e24d5adecf16fcf6aab5edb1bc26a69f134b95ac6c9679d269b797fd253a7e6f14ae7b495a8924780ca99312f97edc332c6fa18c08033c64fbc7fe8ae3e52973b24d57d209a9c98689474bd1c6b9f0e5c5e801fcf5f06ca645ae102159b3a831f372d48d1b97387d3f375bc69e56a3e5465f614755ef53e60676246677ec30d739fbe03e0d2fd64e8fe28b9abcd829313e4a71597f560bb5709b81b7cc7116816fb92dc0385c02ea35c06140cb501636708cb98de09c2bb9f1368d5bccf771ea48b5910d7ddf116e9e0e6842b17bcc25bc7dc7bee508b7e619ff09e9c4fc71e763e642b473a528c0f3aeb037e135e4bfe6900", .None}, + {.Sqr, "6b7a0750f691acbfc4c5a25b4473641a0789e60a9785459f7692484fd829806323beceea9161aed51db59ea23e90931bdbea24b1d6d82a6b2ac3cc39b939442d949627e8e76aa21ffe9b845dc5a88f56d922ff679d66135647fb567e9745f8aab73a7fc9ad669903f24cb481f5ba74d99fe6da541859e1b691ed30c1192aa9a742866c5c300e9590bf46d13b798305e5ea9f4925947a295085f97387208daac93a782db00ec10aedfa6c6070eee1442174349f4125d67c7d3bf1ed74242f4577b75eab05198c434e2f0f57fe9e3aaa94a037c1b99160caca6e4438ce04af08187fad41fa8b92e8e260954bcb17978400d2a755812a2e12d016c871d8691c30ec881781fa209ae3092824eed247263e18aa5bcb53a6fc59e9cee1a56c76afd45852216bb9c29b7a0237caba9c9ce9dfbf622a6fe1a39828408979ba10cb8afc1b1a07f06ba91c38b83566e8eb54cb3e3f7b9358a76526c5304430cc735e77fba4e2574e51ef021a394a8e536496e7b6a89ac87a30b1284e669e60868bb490993b5bf7710e80d00c1e5317788e0cbe8a52c774a9b30d396f40cbae35227960fa1d26a58ffdd451dcb7da195c31ccf6e190912304bb6aa92ba6c05b1fa920d67e324ee18227119bbc8b92e06dcb19ccfe205c919314667ea00c557348a8e8fed2e3abe29886213b2a2f02e433afa7d2de01f16ab0033c5b418758cf11e4f891a496", "7b860a94c0fa618175474cf11f8fcdacc7f4a1f153c372555c4a4f623e997e1b3efde001a383d94e4e3c1dc83dc6b8039297a985d120e5f15443543adbfcdcffe7e72def3d7dcdca86bb1d467df1b583e53902bd68eeaea3daeace39a157aafd31402bf454a617bc992fb294392f27c127ec1e5242e4e8bd2f5de91c141a92f15787abc16f8d16fe38b93218e6b737abffc16d1c22999603975ec0e2e44d90109b5fcb0afe8351342b84215aa5bad4620c2582d299e7e843b9d01095ddc55e71b4a16c6650a1df09d42cc446c7b46408e09eefa6452e029734764777b83d8a3ee8f69d7155f73c6864608a807b36850e876db0cb7098af71eccc6f923a55bf1136f438cc395ec001d722952a04222523f5dfc850d1938a82ac7461e544050ea52fc60abf84897debe1d1ba0817474a4ac30a71cb9e9f2013013b8cf2acc9953ebd720cf71df77ebcf54579e8cf7e74093d0dd047605ea9c6ecd9fb3b17a6985855b4cf9ab7382e978c803a9d7ee11140a301db3eaa7a2225ea43bade8811edaf38f9c2527d3d6f759d4920b4a9ea716e9435bec5a246aa6743c69a7d01da00f6c89f2497c63e0965f75b1e9e67782b7d98054aef5ff770f643c0cb778f0b7e132be52f023708e32d2e85df60471eb81619296b296069a11d965cf75e7a16b3a3d8a65a3dddc7a5438b61c4ce29d70be5c04d3426d68e1b9a327b088ef4dba693", "2d1f3c48a77e5057f53f819a8897266c5df7e2de0471c578d8ef2def5d28823ac67ba1882096886c32ea14f17570a904a32e616ac494c41e5c7c07587cddeed2c31ac3a97188bcc43c83dbe276a4016fc117c072823f393097678224de3e49edad939ae0e6f779b7eae188fb1541b9d2b0486a08992eaf8e6038dc0188e64a176ab6b06cafed670f8337d70afa6c005748d82ccf9a0e90c6d0833efe92ed1e48e4dd6705ce06b0a730ce35949abad06458ce69b2c95761df509d0520179a3e6b1b6179555c6475d71fc48d54b355ef19c65b8726fbace97263791836261181e33c46dbbc63ac657b3ea9944e441cfc3354235681699cf316a8e6c940f0ea0d80c07b29befaef5453b9250c8b89f6b8d9300ba4cb79d5d1f4f96f943b50eea2c6b7eb4c09e7ee8ab725c77c565e4082ae71bb4c72d282a8536f85d6f14afd2f3216a557b461e4594b813c68c8265178c47250138c97410f9aa8067efedc5b1ab346fe7c9c156c03d3eab387a573c11901853214375ffe7a0f2bf5b0117b72ccd89871e4b8baeac207f877de4bd3bfc1e5bdee0b6c8b7699a77753afc248ef42302af911c444c9e8c3b8e1f4cf2ab046364578b22755a13ff86896085b923d4bc4c321e5aa79427860936603878e2c4df8ab2a26c5f77e701639c1cd033d37c1f4b3aec2f5d45b3c07e046637b3bc32a88e4691c70acbcc04f0f21d63cc553fe81e374090bb02e399be25f176b0765785935267c89c8d4d765c2aab151c675395e8d17c85b780ce1411814dd2c4d0e145599714604eefe35e35dee6f0f753880b64e6a96f73aa622fda0dedd8cf9ac706f9ed5669f38d25481344c1dd6e9b72da9e434dc160c7ee5f7d5d1b90997c74957c5a95ae19e83fc3656bea6b6a218e86715767915ab787231cc8d525fe6cf59fdc7839331e7f37fd4aabd093879f8989e38b7e5f7b221dbc2bbfc3898d5b67372f018364820e1653cc8ed09e528a645cc793853d00244ae5c89a123ef57e7f2d2c20018136079fe53cfc0bb4f1e9c6422fe3bf8d4507444b44e847c7cd9f533fea96b5c65df65aa7e25bbc341158d0715e94e13579f94aca644b6d435b49dd8a91071118184513b07cf61df12e233c86f92bb5202ed913f62acabdffd1718c8f5373205596811d0bb11b1d0aa20c5e87057d0d7478fd7dfa1e591d22a532c471e043a70acb128bcccd6a867268854deae260b2706a365bc4b6a23c73ecfcbb1b0c160b66b3cd75feeec291a70c44316bb5b255c633cfd2a60d31f5079d0d3fa46374ed566cc7e6319ace98d800daa5379cb294edc232e51655c25dc1071c8c4bdbc4e557d92433016c0cd3192c95cf98a35eab4742553906db9838af2b51bebf1ef4ce0bb30f6464d72ed99a976065c4383764f902237c14c5a43d55c1864f912cb8741b8ce4214b2573798ee7bbc87e4", .None}, + {.Sqr, "-5b876359e67aacef5b8df33f1994053a5c013b4c7ee51fae66dd31d069519dcfa7faec33a7767d4d9ac1beb8b101c30d77e3fdaeb02af5463e2cfc920c03072a2f348bd6cba5923bc78546c10777eda4034d5b4a2f4a38be09199c2165bc6c763940bf923a7d45b16008178e12282a02f56df456a39b1a61e4a1b137469c4214023d6261cbe99ffdaeb84129d8b9bc94e4c19ef6bc280c2cfc107adc9e567ee2cd8df43536cb40e6941fd5f39d1b9dbb24545d85d4bde0db87b5a55917cd7b171ed097251d2556ad75296bf2df1a36f692366a57a8da935318fe4dd0c2cd483278d411253dc87fbb86eb9e99c7d9a3d656dfd48ad783b31a8a702ee3252ab005152d52b2ea928ecf815cfce2940f142b539f80b899a0bb2740772f28a41536712b31934a9b8849b47a4c64f4a919697598a93862ad252d47189f2ef6eedde1502799f20eb91d325d086426d4ae823b372dac17c6ce563694436d87bcf8de898b5414cdee0c0a97f175f0a10fa7d1de0798e6e7c939eb24efb03a3b82255c1df26a07b911ddd0dada8134ac7b17d4d2ab6b409164c91d12716673e70351bad67ff03659c0a07aa6c0060e418bfdbb9db46ce367c8056e12467f353a92e6e760545c4bacc2de9a9c97310f71384c5358d1f7a77ed5f56e950846ca49d336dcc2770b4f6507d9e694c7cb8beaa0f30816cde52e93163f867754f0231d056de5be9d", "9594580faa897b0b11074cdf36dcb3682a370305d77f18d24f10dc09157230b703f98ea333c918184d787abe21eec4eaec8bec7a5f2e0c4396aae29e2840bae901ba73d637ed8633be4f6ac7a6e9d566f5135db197e17dc6189654b748116a2b3fcdc42a6bb5a21fa77aba08d5935fcdea9ee05ed3518e23ab1285c14ee2e9ef99de363631c236cb41ff5de70a70300754f66d05f8914b5998e4fb9f7b4d17d8cba8b018245d04c3f671054426dc4678349b484c56e946a10d3ad741640123de6f3a321586cbecd8c75f1897c0e6cb4f222bac0f64105d5320da82766f76a83d3c5df5e3d6080e41cbdfa02407b1fa59d33d85f0356a0e927ed50a36c42622053e90833a4d7e517b12b772bd0785251ffc7988437aa8607670e78e7d4bbaafba516563f7d6eb65a1676deb9c9ee0c39b183b2d2397dd318ea1fab3c63cde16610c9dd7491172672a30b49de3a11ac07dd84a2ed192f88748593b6bab7de9667dcef402eb86948c44fc1358aca0d3218029a65f7ac41a36eea605d8a390b6dd21d1f50557efdf90ec7bba14335e8024f404bcfc03a945314cbeaf023f4dacd38082b9551ed83ad30b81056f6e782d1c37c45998ff23f49f0c165288119272281a4594824b9a125426f4858213035fc95d797090787999bbf88936232d1058f6116a4155dd18d640f3e3751c48ca1a520f33e9a1c099b05c5bb6d9ac9b8ed665a3", "20b9883bd93af4298217836a3d0afcb152ae3d8112c978b81ed2a9b279acfa3762697673d1234596c9ba29152b43c2c8d8e6d1a7874098b74a5cbfc4bc1066e8cce9e1bf8a46db0bbe68903eff39be3494e78dcc0ec098dce32b5cff8299beceb011debfa5fc5e9f37ca16d56f016782d9c08d9042fb073d55f55b16acd489120d97727744faeedeae59762b1d4979a0b1f67987a595b92823e2a2a56b0f3626fdb8ab134c84c9f50dc226d3f8ced71b826f97477f419c44e11dfc65640d658fc0862131ebd2b8c49fc48889fcf1c80eebe0e86f65db8a6655edd4308c745d2fb04a06a7f24bdb5d643acbe684ce2bb3f1c554cd0a7b075414dc5cf8223f3011f6c5e3d9a9cbc9c269a6fe762c679c57d94ffe189a682b6a143aab50aaf18199e1241c3fc4ea6d7fcf3153aa302a61c7ab6eb59aa5cdd2d54f04c3d5f35363c99510599c05aac72153b942465af266c88c128e6be253c4a362b36868966b0691ba7598753dfd1ad61096451863e371e8816a7f15f617538e370343a0a6b0bd21b21af64225e55270de8bcc3627bff74b23e224f512b1bb6fbb4eb043633a8deafaff2cd8f0fdf806868cf727961da29c4f6eba840f9059b2b943e9de65272116eb127aefd2b4f95fe7f06a4f66d67844f3c023a26b644145ab0a3911a13ba0a4bd6fc2f5f27b3c62f410c9fad4b2e80968fa7729df7d63f10a4ec73c99829135ace67adf0706b4d87388efda9fd1cd906cdb3344aa9caa4a69a6272cc3f1a20a0865bc6beb042eb9a9609e2fc1ea772cb2a12492985bed3ce0c2a73ea85482e2ee01b952920365decfbad49f84a5b28dcd99604f1670f0a61b1702f7e664fb856b6af28c1c3041f00fb4d192792d1cc41605a08fa31cc486352ee9a62f2bc620217c874772a4b40200e34f7a834863d71a4e8358d8e5e7e06db11d2b9a2e74789ea0d89b474139ff2f169f06863bbb50ede0d9dc323d5fcb42503ee02eaf69b37c83eef9695db8318f51e4a429936fae235756ae070cf674d9bd0f9929de7a3e64e46d7995be314c19a18f18a10e8f8832208e9cb3a3bf1f3f4289b1938017d9bda758f165b96fdb8d1528e5c9027906385c1fd7e311610913c47b7ba1a382d353363eb81d8a0abd55341b5d38ad69c4f29ec78711ed4dfddbf75cca37b37072daa16820c988de36033c258f1715d05b2df4956661016eb10d468a101fd2d98b42450d75eeee96818f8bdb5056ef34ed3a5689f1104edfda13ca4956929ebb23055430dc482d453a7af4384ffdb949a7434dfe400a6e93a2640ffcaef5ba489c9d4ede73d5e8d570b7576c18b4d0b9bec13e9027d0517b4b9fc41926fea072f85a35049b03ac92e5af409b9fd0cc48edaf3566f825efeeecf9d20fb30cb6e981866e908436091ede5c665a582730c2a649df2447a92c1a44064476a244cf6c49", .None}, + {.Sqr, "-1303cbf0bcefbe170db167c7f33ae0bc49403f3b43a759eabf6d96facc5ce126a3b8662a8e44387aada0c268cca390a9f48e8746db5f09f21c951d9d6595b766fe7541210d505ff96fb484d3efa94fb21b7dac0d0deb12f87d285852bac643049756ac57c3eeb6b1c10f07c8bd83f38133f95af2a4d8d9939f1116766c86327a03bc506e933c2b37c0de7cee0dbb775a456f865e98141a0323db8c70a27fb0f1073cfb1e462cb325274fcb97bc36da29c8545387b293737988b702a9be1c678a9e52109bda21d6570c26cc1fd2d57dfcb6d0a7e05f7ac049a021e4da98a58864858670f7ce2e58d261b3258af771ff2a9d9bb3dc57b2cb0a46a28d89917fda77f2d008b65366ef95d18ae84ccb8c07df9e8c1b014bc49bc1be4c93cc26990e599260a45284a61e25d7be967350d7aa14445538214bc3cff07d153ac62b1adb2e133372a474e50df9c0c80550d94ebafdf3d2793a817973a6d1de6328d0cffe40b77d511c5e0fe9ec0610d70fb58bb02c7af011cb129efe89607da90d33c8aa6c2dfeb4b1b8d3a357a90add9bf9000d76541afa7a9e4222633959209c51994888325ac6346a190dc4792232358bef93e9f078d634b81202caf9c5d11a55ec82d5aad60c3228f054c6902c0d4a1e14fd1d89d485c19def9079e41299a90b4994762c2f2d22e87262abaed08fe0a2a70d5fcb67a5389c81cf00109596fc90c41c7d", "fd9f1539414c6acf05f7bf39210ebc52a8466f45baf83a903fa64a703495390955254490646433686600477851daa0147720d4ec83f7f7c18dd2c9595df74c988786dec1fd2f4305ba6af62052bbef92d4f343a7f89658b27a02432bb21c607f5f49a483c47a18717bcecbc5da36b285c4e32a5149e8ba7288936a9dc27b5b0497b252a65e6cb2b51e60cfbc9606d0c317eccddbba3c4ce286b6a8e20b34f5c43ba97b4f7d8be7703f67378369b7deebde885de516d929929addf161957697642b821dcef8ad013f2aa20043ab409950410b6901ebb09b192896e55a1fdbb3a0f7b8b9834e4c39ba2e0314442ca10b02746e233fdfcd348ded312f0f01036dbaeb63dd02532fa69f3ac18892b86dd3fbb8b0dee4e10ffdbe63bdb03cc728214364613b7f2baa976af7f0e4ef6e9cc35f530dfb178447cf7583bf5cf3c657a11465d146b83362c5ed8a7d33205872e253dd015d465d353614b48462c0e23e9a62b46ab9c753766dfb2af4066040537af1d394814dadc9258812df26e8375a177767efb5ab45caed1c9943a2cf5b2f1b05a3c00b08588a09842462542f688604bb8b13096953f3c0807d6b312405af32d775d7f28dce2c5f5a734b0c48ff61d8808e3dc4b95377f22d8041a11e534e11e47961c93d05b2769e3698300281de1be87b84e881e5dae2890709a01e8b91d281a115274a1535307cd02808e2687832a7", "16990542627b1dce500a2377c527f78e758d291c4c4cf382b02a575d56a299c1e893c26059a956f8b93cfa7b08606b8d8da212f10b158014f02f8210d8dd1ede903a27b1dc9aff7cb67ed599cb2fb2e9c22472a0030edaec5eab5b453ba43760221507dcd6afe6070b106a7bf2d9fb29aedac8cd019f5854cd30d3c4057c889db900c8125eefc12c6acd7ba67ba9b620e885665fe2c08742a492a26d9194dbd22bb12d123bd82073447dd369a51174e0e204962fbe3a42f9b3ea7b8df62e7f387f86de6ff32bdc1057a1ee61141227e546619debd94d7c970419928fed9913a549562f41ce26045e1db5f76e14f2cf4a2013c9275a834b16257de814aaf1fb964e0be0b605a42771fa471467d0f71b680d84d8dbe475115c0510fe0061af4ee9a38388af3033961674dbb81fc64c8cb9f694dd5874c485926353e071a8fab3e91497ce1efb8c75b74a1c08323624dd18668038cb726990405b365d9b6473dae8d05a1adfcd02136fc50cf506764dca025868200dbf365ef87cf233bd55020581a6c597f340ee20639c23d1d9dc1c8057f9a4e66132163b730d76754a85f8559c73871b795340b563025a7b1d36d0de89924be35d3d3b0dd3a1a761d9cdaac9c353c76ba0fa5e5c3220815fb62d307b060722917c94195c2752d33e799a24b09bd2a65d54e6a7a9f41276106b748b8ead335f9a656e232877c4403d19e2872074efc8a68cbc73eb3b1c80f1096487933bf50afd644bcf8407a0ff663f380eeb73ecd6cb9036e85771b9e261352d24ac591176bcb6eef3f6f0bf1d33189118784646ed64840d15a5cec40175b186f778de7f2c39decf146710b904941c38cb652826d72b4be97fa664c242121e8209b35bcd4cfb58ec60fd8cd133a8ed40a65f509ccbe5fd2ac55e618e1cc2c338d235c43393c6cfde8a4181491b43450047e75cc6d7bd92516065b96e180215c79ae6268664e2739ceb9261cca9d4e703a2b508d5102bbea47b15a6672166c722a3ddca7af57c300759cc4e90053b650747a7426f8d1968205e855e2d896453b5994cab0e8cbfee3a4079a8e6fc5dec1b9160fc8254f712a96f878cbc098656574bfe73f30a812fe48b01d468b2222661bcbb8a0407cf96413be1f99f6fca36730fa8e5c46e44558c048b6e07c394e124388356ce32aabd050dc45e67c5b25a96aa39e781c54e7f44acf2af633946817dab5ac6d1bd7ef1516657e0cb439ce545ee0c5fbded1b20d79d06578b215e1e2d12ff84b3734454b0e5584cbb54dab17b3d7d3294ab36215d330be54291d9405c657854031feb75d43af19f6df932ca9d6c9ef00b9c4789b493b2be1f511bf44ac312649a9cb2ac2bd7f9f7b77189c10d479fbeca479070b45ed57fe589e52482d57c7771bfdf7f3a46b1fa4e7fc2938171c773353fd72e13220abeed9c86042939509", .None}, + {.Sqr, "89a176acc8dec4bba463e3b92431e7a2a2dbe3f888af6f82218771344f38d5a84aadcb43113983a62a785c2d84b5793cbefe06487a297654ed93b6190efd1ce433b3257896c1cca3ce6df67c3d7ab53fd8ea9331b02dce192422154b8ae4725a8749ef39ec851d00b735bf1a2a500d554b3773f0f91d8a0f0039d808dde3b5086f88e9ba412a71f4914823d7a0c3b5bd7a12541f47d38f502cd2090001082f91910bf286d3bbb581eac0336a85998cccd101430f90dbc21844c172c16b72997051bfb4cbe5f8151512626df8a10e9431ded99ec57f6fd9853e0aae0836467a51e789457edccf54dbd1afc843467843f6d5ffd92d5f143726d17e9a1c9111c2897b36a6c9317d860c96e7e52b25510188370a6d076fee7e47ef5a913cebe24df8e66b9cccdd6c51172caea5f1fdca64d4cfe276f9630125db0801ef08c1978523e1ca39679d6fbea1548f846e6e8b2517bf7b5ff1cd209fe658e9a885ef82e0de1c654d7d0e93be485cea83c3b6d5ee32840e103c26acd1217a746e237a246cde7e86b4c9864b16b540ac59b965af43c9a6126fb6ceb8364284d3d060bf051d8e0df73204d5e26dd7ba12d1a81fc56ddb005766f20060e044c5d2a6744a48375927e7732837f3f0c2f3f604bb9045648213df74e40b894719dcc2063fe874f32487de01bc46b2ccb137ef5564a36b0c64d22eb18c04e3907f522f6fbda967b742", "b576e8c15fe5a8c57a51ea71d4bc41c06693c1428103938ffa231ae2aa3cd3b955de181cdcb5eaa4785392437b05c6d9b83ea0cbf9eb6016968f62f37c22fa83c2f9c1d633b38cfe98d4cdda6a4d15a4acbae31e54253cae36edaed455e167f70a6748e78710a67a15e2cf3b05d2d9f9c3310da80ab898f3863357d32674b1b1738cac319c417734352832ba44e03f1aa3dae9b0c04ad1466ae8cf15874fb3769bb2460cbac698c98c48864a9b46059c3430645ae701dee599247d699c1c5fc8b14b80ea7f1cf81059c30dc59fdab212aeec22807ba1a65f6d8b31d11c34a963782de2cc1341bd1bdfafdb0dd1b130705dabb5784b9933ac22dcee50cec51268ad25fb7d588c16e8292f4954b956aaf7b9ca2d306c79005d08beb18d5146750ed6afc6b28687ad234cd1439bcd75e5ecb676f50385d34dfed06f3a1afb547b71644c8347e4bdec292c1038505df7d762afc0f89f6b660542205821c8dee97b3be739918fd76fa06552777a7010cf6bb25436457c280fcc6431dde49ccc574cfefdc9881cc29e2f17791071adaf4642aae8cd6ac2cf694965c8ae56b2405456f8dad292e8253f5e65fe622776e66e475e045e4639856276800133bbf4ad73f4c408bbd135411132396131b25380b461560dc36dd0c9d644fd1be7602abfad15497bb33debab18625608f2fa07c85db79aece45a16b973a4f411e961569608a821", "49fe36db6b56d4903049dc509142ad2ad754766498d26c02a98ab91bad309c6e587f0bc4ceb31228f421e12415c43a5fa1db9200b809729c5e56e930d5282c03f10447f16694619fdbfbeea7f6741790ef147ff0e1607cee6c6d20194edba67fc326fe1d8f09e1d31126d96c05ed65e0631a72719beae9bf86b768c60cc920f52275e2592627dda301b99947bb3c81d8624f63a6372cb76eb8ae6e12b070e9fc9549e3f28f608980aaf41612aa56bc7d59d6d3b40dda953f9317707c9e6c01ace2a733963f15ac15a25dd7b1e9cd16ed17314817396e99c65465fcfa46491a7d493a2834cefe98c45d804618d7dcf0d5b275833720cdb137fc9097a983c1ad43bc449e3c400f34606fea06c6a6a29112d2388de620e387973e116e2aea73d70e137e9685a853b52b78891fa2bc757199d1cebee248ea5bd0021769abd54be89264b53b0aecc354f7adaba35f6003012f070033e67f7e5b0fd2084eb1770227a72dfa80a4d9963a0a53799fadc9bfcc04e199d97053fde7b64a2faf4013df49433392d1ac4284b315c0fd18650ceeff55bbcfa115071bef6ecedede9335147bc4e9d3831d3f327a7b468165899365b482d66227e396cf66f1113558f4bf3fb1466ac328e5b87fa917d9bebcb5cdbea9c485bf205ea9b83ff110e3c94de54d38aacd0620fea7d2df4113be49a0888b3ee4068c60b06c8f1c189485ebe17f3fa8c9575944494067214a5b38e7df704aa07d621b99014c7ab6faaa0be9afb3fd9c25d68d19653ea32ff68ce9f9e924cab9b0dacb1d721f351ce1bbfbc95ab296922c8b83ed358c69286f69ba13f384c7bf988f90b6e4424b81ae6f5da688cd713b56659cda9878d7d39c6f1f1c815db4345746ff643f474c84f5418d3d6abeda99933b4eeb8e48d1a87ad2c1ade7450272f2666908263edcead7cf6a999e494b228d3f34b08a6893144d654166ed91049039e0d187cbd0ae16c1f253ce21c478121edb3c2068d5000d546aa88b283f504f40e2bd579e6c47a961be7302a4c86c2b4f0905262ea35a31e3853d4c9b2cd8c557c43b9f9b6b336a9e1af5fa2a3c84a3547bb9db8e2da8b8fa6ef8a85e6416318524ab310d9d68a8e0f7451280df41fd7b72887cea9e8bda4f94f781cdb599c861b92f91930a10db1528e8d08542c8e558a0c6bcabf48a3b408a89830de286404b1fe56edaf81976a7b408e1af19b29c00ab34a48b94339fffda0094c08fd012de76dcd231395072f75125dfeabc3911ede420edb611ddbe034e610d316cd5d918b34745403a9cb0b286292f5f0f2334d9672fb59aeed47456227de1344f34821166db931ee887d26b2637e69c3e0f92841ccd762085caeb2798d624242106a22ebc031440fdef3a2fa49aa499d079f7e6dc0e642a6b5aada62f2921c3abcb9896f36008fb8b0ebe631665ed6e1e4b6d04", .None}, + {.Sqr, "1bcdd282583222d094f687da14a5e2a49c353ccd1dd733760ee706159e4b782def11b0f4d257f2006d50139f556a3bc69b5ab602b1ebcce561143d6d55b8e144b2ee03f478c1a2ac4d2ae73b4430686120e2f55e06d3aa0bc1001283e064d4d28d1a902b7338c2bd1ae3f53b5e450f0b2fc695a1fab9a9bdf0eec93be87459f770189812ef3328bf2066a39baac0422df5871ef4ca083d82ce3d7b431a5dd801dcd2791c317f79e0c0bfadd01eb4e6175b94bf3c800b576fa3145a4e3391acabd907aa6edd8e92d0c22287a30ac5ced5421fd79d7e305fb6d921a7aaf712e57fc8d29ee934fa6ea2e41163d74ffd475995988bf3368a040cd03d3404f2edfec5241c1b12b7696df0a2d50e9049c4b9386d2fe537d80635bcccd6d9b203b3801cd76d92a23e485b8a692858980a0d5c86271afa5f41f6253c7eb519822c6a42a9c34cfa31123854a72258e658e8fd409bef67ab0e6cb0c72d59ba8d5d6b4bfe17266aebcdf8ff9d2966b980b2e42e348437ed66b3fc77b9d766aeff7f101b13839d503fe985ba7b26c5cab570eff5f047eb874bf9e98273e829916c74896b3b6c4951d8e94a10e273ae0f44495e1825c677e08309c771e7470a5df171428c9863d9a43ac560353b9e438a70ef4d687d3f60ec272ee652b097c6d94384b70811824f8b0d63222c120ec0d2ffc2aeb04e35432348f52866c20012bf41f358b8db1f", "14dd06abd5e52435ec68154ddda378566ea8fb74baf01e4fa1c67e5e3baa58b5cf9e0446c4f0c5d7f7a5ccbfc0ffb07ec52b0a4d9ffc0e0a5b379b6c8a3543414797c34dc898dd50a287547f193b8c63e14366b7bdfb0d86c713a5bc5ebca294c42b69a992f924366c6be57349cd497d8fbbe18df6c78b90afda2d05846f72acfd0139c49b54f4762800e7cb74a802340f1157a5d07c73b9469b8cba7319155891c02ff63ee3902f6b33522ffc8dbe2a1d5f023ba5ef57a6f062638ef90fc0d6c8bb6fdf62d0dbdc9380f46917e8f52d5fb76c5e0c7202c530bdc93e6bb90bb60375e95f928d5d6cddf202297047a89b4422fcb9a3060e138201ccf67818f2af5f05fc5612b8555e2a6523a888e62cb2a77d37af852031954b5c68db79a6d7b4a20363804f8c2aa9b3a9cfd2e080dbd43666a0d970d0ada0ec8df297a2fca6b1242eb8fd00c022e5a9cc24e4fa79e890e95bc37271e71b4010a3bc80c7b98efd1567ded8a506f3b1b86d498a69fccdfb9a9a107d76ad6e169593c616459bf91d0c721091c941d8be6357c61d7f25f40d0ccb4f4cc4295e82c71288a6c137d5fa18c7d48b63b6c9401c175001d3d4fc4ac0a1fa06dc34d0325170c1129c79b7cf5746840a61ded01aee7af22def73ea6f259ab78d6651b8acaad2146a35d815c99908d07056b54142a5a51dba7f4439ab8728b66075c60ca8f176ea877adcb46d", "3050fe25075eeb3b3e6a57a5983920fb7a86e857b2c50cb7ab72af1411f83c9b4fa61bf9ae99c9c92ba7687d3ec3c9cd0f01c126563a8b308373603fabb97c1dceee5a0fb3387d1e49169d06bcbafd1ee1b60bccd5862c572bf7e1f428ede01d9d959633f32718ef36d77f74fa875d6c0a50431e50b41f513211a86f52a3b5a4536fbeee0243e46d0dc2a85a6bc2a4f47d5e71e8245a6474938d65551dbd95eb4729cca6ce0a6265bca442a11b846c10393825a7a8a59cc0a5537a7ce69735ce788d69e8321230f908cac05d48b7fe47511f8d6f1d8b594fb362d40dc80fb048a2834f23d38b7eba1dc31ca76630551c22d1252290b8b4544b17cf4cc1d18f61e2b80820c4f2243eafb5118066b986fc3917c8ed25273989746449f8da52ed370a1b795fcef0cb0d725532fdebbfc95c366f971f7d1c243a2257cabd6f45ff359efbdc3d316028b83e407dd7933d72445d71d5f4e87529b53db205fdcff3d530ae779d3ba19d93da6e3aed0e67b5bd39e0eae6cd04762b6096935ce7c62d09ae4b1665eaf0512e094db0d942bba2f9a1e2e162525e8135c113f14976d0e29b58c0a1a6d5cf7c6394e820d31ea0e110f0d608af56a22ac431aeba6a4ea891540312bea31276ac1e6c7a4cae86566d0304d50f7d476026d43dc1857004ab307795534ab8aae3a5c7b26cd7b2ad8b89f64974ae85ae0338c9e111bbf9cc673e8265c1985701d272efa780e4e07831afa8999e415c443341c09f822e80b61909d5a8bcb261ef6612282976b45b748a19c6604b5feedff19e91ee9ef241cb6aecb4a8e9c90004ba46ffebcdb7cd4f0065a0b2572ae7fdff1981fe2b6c39c58ff2404d895d20ebb81f3798179e89834091610eeb95ac33f1591b624666691f5f352914099df8e292cd6b517b94da3bdd0dac29632cabf70e40091c9fe0420123548077b68e55d0c4e59e80dc3f167ae0a416a9295d5c1142bea1240cbce8135aa7f13b72b80ec8c33a4a7161c9f542f74b6ed062d1c5e21b4e2e6ada8458a9b59d4c82a60d1baacd7734341a8a3eee031d361cc89e1cde6d7f22ec3cb96220aa2950aab4de38525880963520dbdb30e72792dd4d7f1d7fff055533c11abc41a6c734db34a28938e167548c60a8ee8021c34b6e5b8d2da51435a1836441b35454595129c1b4bfea0eccfd7487f5200df5ef34bd826a067398879ab1400e5d105d43d20fe33e84a0faeac0c66444ec935f5d761668be76a88b19cd4ece6ac836a817cbf10cbfcf68530e23c1310cc64f314e08a246b714d418ea2029f279b29f6ba6da02ad2909624947300b910f8fe1429af824bc9e60a168b64e0f1420b4352bc21df18d02d388d718c46a05d703071517e123c696acb1cf21d8dbb3546f97ffb79ed0575cf2d7699b627c42b9f3ae1c893326c8797c02b64d906c13756fb081e0dc1", .None}, + {.Sqr, "a1416d5ef6c5b5dc924f8f0e59443250aedbc951f21a33682b92e9182412f4494897611bc461664ee661ccf5a46413c9b83a0247d177998e3bea9242bd01a0fad307a1e9e90f97fc5a434849a468331e3c0ed94505d054fec1edf108fd0cb70cd6bf1bab490bc5a832fa7c491f140432ec620bf66e9e35b0f474ba27d7c1bbb8ca9f85fe02465e036df5991f89be0cf69971694cde331979b822c3ed38d58ab42134cf4004856ca058bbe5700ca75dfb0d2259cc1531dcfe6879f0b3e10885a4fec347f8fee44270528eabec50d8c7f570947fe5964717c9294ab67f066f54dfba524d6f61831c16d6a35aaa1328ed61b27883e0fe2dc3dba2ba2198bd1b461931276ee5b2c149f7da1d1b563505742b6fdf8c37a0b0c7bda4196a09277ffdc225ec8cdc71600bd130f674e29a8504f6d0f51df4fc4b884c31b29a30bc9888a2cb94daef837a958648bb55e8cd918eac67048c9fd5c45854d9cfc25906aa06aff06a8e8da4225f98dc5788e450cfd317302b405c6f1ebe6a0cf374b7c96d8d44e0833d1a477bda25a1d28d1daa7b9e2221416bf1a76940ad022da01c44e5d2b7b01d2105eb44afe6eddc5ebb5f7c65808093bc757c9281c2f2488ac2663df3255c40beb2506292b10b4eaadc6d9a70b933274ccc52e9ff8b2cf77ff8b528342c3e8b7f7add8b1d3ad2aaf2e0d3101894a41eb6b2d434b20583b5acfc8e4984a6", "534d3009c87e2bfc4073cf37bf555956487cd097c28c1bc7e9412ccce1170991d88f30720f50901020c74b5412dadf1971c37dbbd1438378356fc43c30a1df39167023ab0ad4ea695c10f37867c2a68309697d01e437fe6928dd1c73d4e3e6929f651ed8cec820aa7fb75955ca9476ff01d8e4c15cf7ad97c71fbfb5d6601c0de5a13c57697646e65ab27b1c71c5c7c942738aa3e966bebab8a76a5d4cd859c60deef7e56f07b570e636abdf45a3bee0531c77be137a7dcbfbaf6425f1aa4d07b115665b3a48cc71ec270deef7621d30cd5e8f450ba8e94d60eaceb852df36f91c238e2d3256438d3175e57b963441af2c98065404ca67e265f5967ba3e97a70647c41ee2d64e95b0e01fc5984ea50db73f0cfc1fd482ce3dd06274b3e696a9956acf29baa02f950b19de90961cb72918607f44a0e4ecab9b5d3aa47971e148551e408e6ea4184fb9a7fe037dca9d91bb5e031e1c72c6a92221dd76aeeb83ecd7b89c21c57d2b623dd20c94e1b51ead3f1acb38ee303b5230ecf0c71778bab932063f94e49afa7b5b3ea3b17fc0138b3868574721c5795470b34ba926fc90f87e89b908d243aa4e08330f67f53447a262311916e1a58ba5bb2171157cdbe59497e9af13804eb6e4520943e5625c65ec781542e27af1c6886a94e660b692afb2197aaf332b5cacaea889901b836dd7a3999eb6b277de41fd561092f726dc9077a", "65935c4a2b5800844dfa531f33ac1ccab6225d6f362f876f0e9cfa5193d12acc78aa6e3f1d896ea085ab5c628c343df57b1cf6d4e83a129c4c3f63471a7af0ef3d961de520fd028ad45feb63be3e916932d3ebfa73a2f56615831f15a797524a32e4cd9b9584042b6daf0fb2be5d44ff65f22d2b933d25301ac195e2c5785236370a021418e7da6a2db5ca2542ea1c0eb01fef58967ee1a89ffc61adff9caae724834fc5aa4cb227dd27ad95df9747449fdf2e32d38dbd5cb001de73154fb5f582dd8e1d9eefb1eff309e0166d9f3e81669a4cad0a39408ad0f632a1e7a232fd07f01eabdb36b9c8bcb7d37dc698241134aa7828e33c3c3ffbbbbc26bed1db31045211900e411c03814b5aed560401e77fb345f2eacfdf7ef5fe44f6b27169b93b315fb7ad95377bc665ec0bd5d5086a166a414a75f70ca4dc43cf946048007fd720fc25de91203f38450ce173a06c06708f3cf22d6bb9670dcfc78a9cdd40f98bd3c322aa8bab69b1f24aff34f8292b3bc93aa37e42afa6b891e6b796e82504abd804a2053b226f941af090bfa4b47cd415c4a7fc1861b395091f5180626a5d1c0fef9406235a4440c69d1e39b118be2b6c0ae028613bc5c3695b34de730f8de060aa342ca5fb8e4a181cc6d908dbe460ffb24bbf4a97e57afb2b6dd9524fcfece8d84fc730cdbd9526b8167a3b4f6467bc2f2b7f5cb99ec040f3f41a9c5444393882c708c4af9b4f17692cdb01212f4ac81c713c07fa46f3006faaed390287d9144d1bc86c9ddba8019fc38b34a25c0c6509b98dbfb989695dfd8a9e4172b5ee766f99e5d6593e3633ea5e9f870489d629a4f294c754421eabe82d071cc8f991c461878e1d313f9edfe5d8593d9f628810e910fe05712865196504548118b37adf7125b351c83372dfb74899eded7640cb463279f6baa405c0252dcb0b37a9900c64a746d65d545f380f16c42ed19129912846cc65fc7be0ad9c2c56c014bfe256dfb5da2500a8d1f04acd421f6bb14dd09978759a281b5c44c5d287f525a33e9283e2741d052e22fa1f4fdd1a20fa83ddb7ef48115aafc3fe55cc68a8d121dbcdb5a9cc8b2002c8199672053129ea88ead89784cef2ce4473df4dab6b7f972ada8ef8db460f087c2f2480efbbeb9f7e370bf25bbd8932d10c5580eabadf8ccf5b590a9f196bfb16dea65c738fd29624a70fc40f78f2a6ee2c93125d86c65ca9b1e7540625805ea9520f1005f83a3e749187ca3af212cc38ba603c6affe7cad0d2089a3cec3807acd4c52e5c6e37f151adc02066ce1b7873e6f59bef7747235a7d761a89f416b405601abb72855614e0352d26291d276d7756b3d760209517f2ce96044651286b917ea895de542502f5bb3ef97f09fcfded1909fb4ceab3a1cabcabe2e5c8598050e2afe812e9c83dcd6f781d2a6ad08eb0cddb1513679ba4", .None}, + {.Sqr, "-aaa2b9b4a09135310ee2f6737cf147c21dbece6682f881111440418f9c10f644bb85320dd6483dd3c03fe7a783d54525cce4491674cfa26f78b18bc7b61aa0af81b5586c739e1492dd1daa1070f1261246c20f1a5323a440995af8869e53c54cf6b2b73340d71b9ac4f8d531e369f3c6bfb2938eb15a66f7234ee6304e5557fbccbd4a15a8834cfc6424e9af42ff81581c7dbf8ec208c6229f5633ff4a9df45211f43847171dd9ab30622073c5f01c6958be62cb1ba20cec78ac756f7b3672b4feb6877e17d51baba4293b06c53d0fa217b6aed8a758efc7246fdf145f3a678e08917eb74630680b02865136b802ac4b8534a8b0ab40ac6473de3e9488dea24b7da9f6c7bf3b2149dfebdbc50c153c2e5744cf2f2e80f9b680e8936ecb43c16f254afb3130c92ccab4670cc085cf9d15d4346271262d5e4352b5ed622d057ab6f391df5de539db5997cc31c24e60ccf515687985932cdb1e28e04d33d1a8093f051657955cc1badadc304671c0230af92bcd0ea90bbc9ffa9fac7a79102d54ef3348c99f97b59ce175eb5d5c97004d60ed9aed0b5a2d982794ae3dd62832f26345baa7996e996d83b9941853ddaff27ce9c8a2ffec9e419fde28a9a1a7588b52319f7fa32ad253a9fdcd32080e9434d4c843554511a2f5474673e05a86ab5924c831200f63cb15d42ce3eb041f25cd64bdddda8a0e428df0c34267ef1ad0b07f", "c1bbfc8e27538ec66b730cdb07b3890486d8d5b4bcbc4e92524edc10e7777e1e6c7db6e41a9b05c4c640d7fae42970dcaf9f5bcd4de02d664db2980c80011ef8781a6bb15fe00b2516331593291c437504802049cdc8772b3898876de198c2adc015103165dd7725ccb6f18d248404142db780ac6023e2ca9ad98cb0fff8414391db3163e79db685bf711c603c8d334a850a44716b07c061926755741ec00e59efef3bb1465e12d9326d56308c32eb657431ceab3c3c0bb8715f3fbd97ca2af8d05f03710787f987205c18c39cb77d131c0969ef678eb623c2dcf6bdfaa8996fbe69422ee23d94c4768f55d78f5b1730ebc4dd389e15475e9020c266d8094380a75c61599f30d934efa7b97d9b5d005cc451924234c358c32539080b3d8f64b97021234f794b84de376f2990b0343d5dd9ccbfd6b1f10060689ed7747ba23a4273a0019f340bc9ea1811ecc089cc9d96e9c2d29199a8050e0b7206c8cbe558238585a275e811aa2b48cfd700e181d646b2b4b4933f85d2cc75bb25a35fa8d8882aba00f401870219617722964903a571d30bc07288c38aed860ea4cb399738070c76dab64ecdfa5fe48a6f0581347d4b9b1d5414131d8804856ed9e3e2fbe4441fe20c91a1b497184db86e499849ba5a951bbb6d4d7fdbf8403e7ac96c542cd23b71cb8b9e1c27ad6f9a196716ad14fa639b63ee173d01c9c37c40e3987d4daa", "71bc86137492a1f089a5cfece2b3fc6546ff70b9584f6a3cda8329f4f338854ef60bd02ee518d18639f1b598ae4fd9bac3faccfd4dc9b96ac9b1e6d989cd09abfbe76a44f6dba20f19784a99820be8e75a0a16aeaa93e38adc863e05c56b3bd79f33d53f3ef2ed8d30e76f7d7611dc35aed38c6e9d12dfd8ed646deddd04cea60a15bf83fc58142563ac96d0a1f2e4d75ea6c642b42a53f7b433119d55dfd7266548af8bafd6ad08b29aeb136394a2f9ab6190277b50c83e8ad7a081e2acccb34f7858bc0b4581668ea112f8eba06d0d8ad898a982e41af0d96ca921011f19148de84bf8369b635d0eeb4c4e9cf79c5f92919358877460911dc9b90d89ef8ea8eb5c913ed2efa592efbe806d992bc08b444034838655cb3db4be0bbe03bb9501f85ade88dd745830f22915f48e1c5e14ffb4e18c17687f86d6145461df959491b6807f1224dce0c572d2d43b0b003ca547bf837209ae864887fb5cfb7f28a15cc53889fed09215ea32a72ccad568c6e0fcd9b3af2d809471c0bc5b513c2b9ca18ae557c356de6676c37442e89fb751a350607651c8e590d08a5992acfc692a859b1eb76d581763311aaf71f890c7ce6b5b48a019ea387cac137ad1972c3e64bb14cd221ccf4cfd2c3067085da7f45ef286e7dcc59f3a12fa3e87e332957158bc503eda38ae740e5066392f48fddaf272abd4a05f75d6963905e053d7f84778298dd6933df237fa50f1f74af656c96ff6a1be48e726ee0a6117ff881068fad2c456c6862de2fbc29999bfd8c56e28449805bfd086b60779e65afc85d8d53c1b69488bb323842259ea5b0e4f43b014827a0344309619444c7053b6db6959415aad7648f7cfe75ae88248c2e2933455786f8e853281b4d66966d07ea44f9262c17d0b023a4de112eb09c85c1f638af3b50385fb82aefe1fe0c0c248cb7e5110a25f763fb7056da5a795d40e51115e2d58f3f4e9b91942b6480a98d491cf8bfc50a319094c9e574fb4fb113b7294271c2ce24d3422840630a3a04375fa12795e6d74f2e3278daa9fe3af27961478622335260ba9d5c27da7ad102fb81588dabf0b38d68a2e45c00024d616d8184bb32bb24e85414ff5aa5969d2037aee529187bb7f549b89ce5a1ae8df78006512a3f8438b501a0afa3da911142e94327fcf17831db40d61b0f42e9219103b94a5b9f99a81ad994505793d3bdfe1a303356a7c6feaa7403299c01f905c57ade48e9c5de44fa632790d1d660ff75455f1e76393c9c917aceabd28bb22dbec39f75cded3b0df865491de99bcfe863c8a85a0f7b25ca5d0569ac1bc97eae79935903310b9f9980b76c61ff37924be99ebc51e47ec14fa8efa9c94bb98d4db67bad9d44d28104537adc9d6be4e3548adf4af8dcc6f6eb54c74b7894a58003aca06b7dae5a60cba2d03bb411388db837dfacd1b140edf01", .None}, + {.Sqr, "623bf2971db99189641c54f553256c967ff9840934cc0bcfaee63697963cbf2d936fff28c80421db68ba401c95d55b836edac1d6305683c72fa6be9c92f46959b47a65ae0f8b5d7bbe216b966d118313dde4c72af1800173ef286e4f2dbac952c749be344a6a5fdccb7130af405f3623ec8c1145c9b6febcaef38180f48e34ef7f9e6abcb28503789181e0d33b4278da51a3e261bf63479b0400d486e0e9c59c897389e2311e184b02e7ce83fa6e098feebc3b1f267f6dbe2461302f1d47ba83138dd3a2d25fbe9dfdf22e33a7b6a0eb86fb19ef89be5ce72a6c15709322d30b28efd78a1307fbce698790b60c53a5a4f979fcf21c6935f6a3c51ff0b8eba396b2f2fcb5ed38fc26daf16f63b850e89780e0ca0e3d640b38746d6e970ea679f6ccb9a19999dae3e8741794fac1c21063b0262831be11ac1a2c6b7ba7dd216c918238d62a8e765ab22b81653b2bad7d7c093156ad5b7b0b9883fe731665a5357c93fb869fc9196a19bdb1e398501ccc7685c379f7cd39bbc0d020d70f04c43668bd689384c7d3ad208886f7fbd2dd4c3e261917e494da19e88fbe4de155dfda76fcc91a108c30c2bbe4966553d419fe335151bab4ad8487f5b3d1744b24a497177ea1fcbc6b5040856d22920e2a73ed4f118d80d28d9a9d42109c8e9dbc6c89f7e662d57b819b1726ba451ce0e0e9ef20689a45c0ff8cb38e37b457c797660307", "7b5ec7c13c876f2061bf0ee19261833d6f56b12bd0e5ccb0721f3d88ff7e008fea5edad9ba7f298c2fe68a33e4043f5f056cd6e54f7592f9ce50e5ec8521a504b6e7adabf04727c2da96a4f018e1ac0c2c3ee1fd989beafabfe219eb84c3d7022cd2e72e3207e54f661f3bdc37659dbbca9814b3a1cabb3068e081aec83e771a101d49de19459e5f95e744e624f4e6e013b63c6d2febd8cfe655a0ab1fd39354cbdafd807ab538989381d6e4707d692e914a22065f2fce17b713ee8e6ee8228a4b802cb5cccc7b8078ce821065cacd7c00969f5ff0fdf7a5cad2411e09da0197601475fd66ca952ed5d262ee28a4988df1582e4c01d3ede60f4bdceff665b69e2fa807e906d309f53ca62d8acbc627cfbb6cf0c4a2a5b966a793f23779b5c75f4f5773a876cb4149910730bd05b01376a615a12f6c2e2205834269985bb076ea40be69e7af5f3757dc6cf4bc340283dc5013715f17f4087220e807ced39a7851108d9134c1ceb8fdc148f1b7a26b98f55bfda0cb1aeb72f257c59cbc3c242f1eff4a6fdf8adc542fac8b33b761ad6322c8ac422c08249db2c0d4c15dac0db7fd63ec08e684997e2679c175f2e9e211a0d6582dd2a966e4f1c5f7a53a55b86ae89cbc5d343d28abf815f3daef12dfac1750d19dfb816738fadf85038aded9acf0fb5134a2505fcc3fcd89ad3405e265099f7dc6f080a415f047ff1fad02548f62", "25b1f3c56a4bd45d317ed8f172c70e54e3ec4c8f670b450d3360927f814d7315036d0e8659400b48684e69cf87bcc6f406d79e95103f20c04757a8a96922d1eb518ea3ad5ca839ad4a6abbb58c2535b45e278443a4ee5e763d8cc692fe415e03fb74e60f647fd9458ac3da176e7dbc3edfdba6659a649c7c8cd6005b2af3671147c420e958e72730329b8761070b9bd3fd1da74642f4213aac10efedc77aa0f6189781386bb99eaedf4a0586c0e7c43f2d6d71ce7a487680f2e31896e1a517d36f265b52bdcc310a3795665dfbb70800cecea2b78bebec81f914c9c945f31b6af9530e6fd1ce7a6ff10088ccb603006ce43ff72db294ad0d754e7edfa162a749a79625d0ee6d94caaf2f658fe4f6c3862b95fe23cf5ac074326b1f753dc2bd303e093b80a87bd8137639c0fdd275a7ab846e651f8027766421f7e9d42a0609b0ab598de62141bcaf6ed644dac9de5ab37befe8fb99578d276e4937f90e16738c9e3b1d7f274182f824e3e240b23c3bfeaaae2dc5927f0243a7573f9fe5308ee4d8fd7dc54294b1bd29a5a41e9cfd82b37c9831fd8a521f5e38174d73148029dc4eca0bf47e49b866582bddc9a2c461df5e59e71b3f856250b663bd85a936db172113d70e8c5cc2a3ae8d22ff218258a89434f344b1855fd759b110f2f579eb866d97696c6b0cc6115695cbee1a761c8be62d1770f5d70f37849c438be3332adcdc58917459e6ed17ebb98bba43ad4f9a3ed691f39d21346606c9de5341821dc05660061b9b53aafdd5ad4b15586b5a460d27986bac6252683afe007477dd02c11bcb1c1b35337607b91faf77530bd20c969e64db85edb76cee7f2809082724c15bf6d4d8b222806420ff7980d118e6888472fa17f21e92c04d2cc1ba421150e4cd05e2ae226dd10598874523077dc94410f5b513d05d2640db6c7083f3590a731ed2bf7ba7d598c6985fe9e17aba6da0151b0a9d2aec73988dba80d2c367b34df718dcb72f452756f4858a4d3da31862525e6125e05db8c4130cc0eda06e1aeed64c4d97ab7f5dfff67b1435b1520fb4fc59cea8c2d4433a30bd5acfb96de83a1570b4ce49368bda06660a88f56109b8a33d90093a37e36a1eaf3491c39e5b2f2242dcb3cae381654e4de9544beae3762da02a5b4089e23f2f6e09114e97b17a81c7c223583534f4678fd75e780268ed67e9959e3a81f247d253caa49288f658ca3bb68e0ec0f84a95b8153a51e61cc3f3082f338ead856400879d1820562e12c2e48d0834e4e383a245fd3c10918431222e485d534c0edc877ba29e8570e060a4fdbf4d59b63b3a40d0a50dd940ab9e4baf9ef555ae7008e477555876a83700cd9904550d588a76cd3dc361eb56d7d013fb1048cca9db292d12f46048a584950f34f6ff6b5819c28b84b684d75684f917ee9e0330e327095408f71aab9d2a31", .None}, + {.Sqr, "-5549e9c4626bb45b7936b2213d21d035f9544f40ca94082d5339b287702e7ba6b7d47fe849ec32cb1ebefd3a2c65a749ec2e3b04e981bd1f09175e23a2c3d2973456257c9e9f0a022d29f7c7d3b7e315fbc975120e05d156a4865a20c22fc62fffecee4770f1a4d2f8b83f5dae6fdfb66b3e9af0daed22b8c8a26bec6640a8a2d86c62ca385a8f2a554107c518cb8aece5ebf340c42e5abf738d3ea26a4d4498c9c552ed2beeb2da346587ae2f0566362327226f74cf67554eb63cdb47fe26cef6545bbf60540113eb84892f431b9d55ecb2efee45e1928d4ca0be3e07d63b0a416cd70cf50631d645744f32d18383ddc0e3bd7022bf1123e538d14d37ec8b242637ba1ed63d1fd381fef6b332fe6e6f87e416dec940144e6a55009c4ee8d9498062bf4a65d9fb3825fec16f27c8d0e29e8c694ae3a51082b5fe76d786174197e3a0b5b98d84801a3388d0ba326cf39765f8e924335cc5e2a8f4a1985447835dc83287bf1cca26601a542caacf05dbab7c33ea5862200f5afb83b17c2977c1110077842a7d6cc93128aed10992514b8dec4d0a8ba4551e23b7c8b3dba4cf09500415ab9a90530ee332e76c930d9494ec1601587344702b1efd027636418a3045037f072553b347339ee7c4e61f2b4756c6e5393c2d69ab428e1911977f9364d0ec21b8a2cee38e59bb451c469207ac13038f57651ee01c7cff60d097eef896a9", "ff715e5645c78e3b72eb24ac4f354d5e6ca0b13c7b691a1808a4b57d8e0bccd770329a66c43e75ae4cc82aa7d862fa38086e8c70f55ffa4c000a2dfc064a364e7f1d3e2b846cb0db82d7d2085c0017cef6caf8b5ebaea7487417ec518f0df22b0cfd813c60015e15f828fded2b5a5062ae174c83aadf0abb7ff592e80c1760a1769b4647bfce62b5752ca361793175f1e02f48f9b326e2e82a5b7db029560dd70693009935a4a6b8761b990d7747db5e98a3f6bc29939b2081c6795ec061ef6053e55d55bfc441a59517d52f0388e118662cf376a8b6b8cfd012e3226223c110b8088e07a064248c4f5520f9764db861e53660f5e2acc10a1bac0a214b8a2f1be91e754d9393b3fde4e81faa2c2c9514de8beca3efc9f759de63b06a96ec8fe115ce23595d56d257a04e5d395e1bcbc18507d496fb7a3985892bef99852b0efd326a66ea4a0ecba212ceed7a85d21cdd8f457866e813fbbaef285e54026ce71825fe57ed02c2a153c8cbf2a77d29806a356a4d29a34c11ae5b37d8bc134ee024a7d79b3113d2f4a35fddb932d359921c8bc6dabb12b32e29946c97a2e7d9b9936ecd8bf3abd1ad9c1698b8fe0e9e6ffab5ea777c2fde80281687ae0ea99a1e783bb23c219b7f2452d1e95c014255b2dcb2521ce9e41135a8d42cf54fc0da59ae5261044d91229c9493dc37412b983647a445fd99e5fee31cb39bf1c82b442ff3", "1c6a2a9390d2b90083bac59921e48cf86a806090eb720662cca5b21f38463308bdb44e28f6380528398e35ab123471a89f9f855f756b3c32798385aeeac5889cb0721847c69d255dc94214810c8a098b74be067b91a1589f8538a19857c4a8d9efe94ccf06a16e9b60e1e386d20282cd300082b579b425e49082e1761e3c58a9b21f8aec35af1e65f1d137cce62e6dd09d8b530a710ba966ba4ed4c5dee7f6613026c78e073b776f4db730db55b4ec233871530148051b61fa6427a9e2a58ab7edf128095092bfc040600335cee251e0c0ed6887cbd5f56329cffd2bb9f512b407f8a6751f595128a7ae8c13b4c265c9e8447ac2e469ed2a254291d99d864d0e5a1c973c846027248d58e392de8dfbcfbcddb4c1b559852ebf64daf4807f747ac52f0d068d57a2a654dd593bdc6c4e528e947dd7fa981a0b41c91a0c116ae9c1d511b8183c85692dfe8b9ce1d8d1372ac0f808f0d12f4270218e0968773b0564507f2d61d9982d4bd59fdfc735dfd735108ae4a4577f8ea9e184ef17cfcb7ed2990be0853afcbc213fa80fb2bf9cb13d33b846dd9de25b1ad5be9c6061156ee4a5ed93fac7f30e0c519c0ba80ea19c124e9e81a51df35b25991a32224c3059ceddb3310973bbeff1a40ea4885df72615b785583c1760db162d6cf67e41361addfc8545c85f079ba548e619545656d9e1d6a13fd5fd561df54da7b2a8a392e475e7f40b928aaa2f8a49019411960e1431773d9b22e1e634829f3f6dd8ed79618d4b84cb156a381480619fda8ea5024ec11137d020f1d6054f59fd3b23f3f763281731d32a44b3170b721222c3928c4091b0f1d5c7f8252db829c62f4c5a438389f5e473e0637e47439b860122eed8e61d839d4eda9055747d57ab22decd08cede158b0163403112cb0580e4ecc44fd660c482854abe688f18d06f67bc1fb0a0e19bc85d01f949f2200fc888baf7082028480fe2cb1367d0e7f83ccc04b37d2a193a64dcb21d04672f4ba19208af586da5ee4ff4242aacbb18efd071c019e430173b71288e0948ee4d414c75fb7eaf7cb003587385aac6ea4d703e33ebacb8348989dac7043ce8d8d54852f8331b066f3d5f02479529e67d62c918a0eb2ffc9ef7760e554910369871af8651aec75f60eba24967d333d5d8f7b6874509b719793965fd14ec93f48cb99e7d7fd127d80e971b9706804f9749785670ab32ebb6aa60ac725e1194b583f80809e067948b352a2859ac324ed2a8540d51d89739f0aa6a1a29f0f1ac9814d8ef8a44a00af4ab741ca33a3d9d12170061584eba85f6e1cd7a45610b06b3afaaf7b363f327c94d664ba4bb646066596476bc5889e568d6f00cf67400c0b0933a6b0dd7fbd93facdf842dca526e61c635700dbd4601e59c21ca4df2ad587fc3e4591d67a997df4ddc056d8952ef84a0cd69e784e47c1a7b91", .None}, + {.Sqr, "-c4066fc76db20c94f14881ab1ec8ab49d6065c7adef5cfb783e0d5287f5c55bf0205022b0274c9f877f9f7aa68bb3d4f73843260b305541a0fa50e32deadb3e3f51f99879075eb2102f4363c0e102c9b4a6d72cd6484ffc9a432c2125ab29d19af5457557200479648cd6e3862a10ac61a8f18e9c6c59b4c8e20f05b0c9d547517cbec258f1cb7ed0b2f7f7a42564bb3235b13a694b560f8a1b88df04999523795abe7508bf9d83bf76b45e984fa0ad56fe5314b27e3d316bc8243ae4da445365fe10c0a934892930780971f115e16ad9e93cadda02450e252808a777cdba2351b896981bc08f5e10a7860e24d67fd6ee4c82cd091ef26d5d62d619754df853f4d823f0cc89d7ece5617888aa69d06f35f83437203e0de352daeacdf513e84f6cdbe6597fd6a606e2c29e42e89298defabe13260819903ee9ef604fac15f34a4af16dbb1e2a85c2c40eb5fbb7bb7004103eb6200d37c08a6171f0f659d5312e249027327140356d94ea5b7420c6e07cf7f7bc6e76dfc4f4a6cfd3e87f63c6dfb98bb4a34209e45637fb7cddb6388c226adc1c85aa34ccff4033e368a4eeb68a5b64f6e7aba21f1f715dc112bf125760468d08e50adce6e244b979415caf8a1a6e4017f0874684494528b9071dbabd6f8d40a7be78463e6db5631ff6d1202e1d1e1a4e5d37fcdc7f65fd437358438e9c4a7d7ac2ac9cb8cf00a37c7829ff03847", "71be957a122fc49345d11636707c73257d7799895a9a8f78f3f2018c5c38174dff3e7037134a1ddb50d243ae40ed5d82f4014c11bf090e1aec782884514cbb5ff5112b8e9ea50ee94475a1d5ea1e983e24a2638fba74f00bc23817368d81f0ad6641eefe70a2ac237851b88871075adfbe64afefb5f22a7cce62664a67aec134a9ee9ff017f6fe20df42fb8461d96a526d266c265d29f87bf7e921ae0117d13f7d91a8267f76c44ff6a5c2e2e4b53f36d99d8a4686b5273d4b8400c4707899d5155c974e88045d0cb4352aee9a68bb3a547754dc42ce8475e40a3a0736bf4af476ce93cf25830d0804337bdb13380afef1bccedf3908ec0d6a335f30d44b9fe61738a99a683e387c5059fb556353a4df430d70c93749fc0ebe5ed37ff5d01a810a0b8c3d267689580d44b463a7688479d12d6faef56817bcf6da2b9995329c4ca4bd21b567ea0f2a9b3ae409fc31a1d7153a3131b70919df53a88b67539fd01f724e12a676dab76f3536c05bdb3ef07d63e0aec046cb9c30c33a11e00ae9206b6176baa40f2b22aecd591c909021f605810b343bef7f5379c5b486a6cd08e7b819f8b7471f601620d25cbeed93c0e99775abea71372624bb05cbfb8be324f7eab5842573d16bc65311da03f6052dec54105ca188d3db69ac058aa92a1944813fdd981fbbbf599ea333a9fff76a7bc2eb30cbc4a5ec4a1ebe09947a9a18015c42", "9619db52ce205418c92c294c6f8a48f3ad495ca39a2a3dc9967f9dc7114156ce90482bcd2e9d278f29f66645481a2a05e481442b5745b1e5427081895e35d0699fefcddfd475a7e1b63ec75b54dc68deecb0a95614a0f83c50c0d6dd8340efa7ae5bcda751734fdc1550b379e5906645ab36b725d63ba5b7e85373869dfeabae66c79a7ccc9d036ec81be2bfaefd7d5ee678036ccb71b19bed707d9a693f29eff302e40142ac0016524f8348a4dd908991b37d5c9c436d846b7b0bc5331b3d1e14f4d97e2683ade5bc5de0ac702588a52e8fb4850b076464c03ab1b1602e404f852c190e21566c0de34433522cf2b10af6bbb9a09cb23df70125a6d960cce82c5f46bc58926223b4f2f99f48a8ba2001612c9be705de2cdc55789c8d8c1e8ad3cb55f29cfab71ef894454d25e0aa41dbe8e4247b836626806f814627547f7570960d2a7da356f4d53378b3dc147a6f55c24357f2480caa19fccb9fc593376b3d9aad9883ea9ab47cfdf4990eb109a71d593c7935b526a8b76e3d655c24ced0ce2e7d6d962574bab35d0f1ac48fa25596fa76c7213c15186950a6145d27fdaa0ee7ce51b549abdfbe4a23cfdc69fe8cdba76b4cbdbc816bf71df4859a53a959af276f7223c0b348745a9702a561c624946cfa7d26dc6029a6b8707e0013f68d6236550bfb9547488945ef0273dc5d1e374c7d9146571481722bf4f4da9abfc431b21088d07752a2ec430d4b9205e7ea3a016823f9df970ac6472392bd16f971979078db76a021fc11c42edb6856eb22cc9b96bf319bd3f1f82169ebc0e7934172c6b44ba3a035aacd66cea61f3b9269727005c06d2c58f886cbbaa0292e0ae56b107b46261b39bfd6822d0c4bd973fe1de7d837456820dd62c90a36104f4d4428d7168d62176f6a7a6a7672374815530719d5953bad8b1dfed08922304a9fb951245e1087fca49bb17d50ca21194be999564e48236b67562c36c4c2df7fad3c74086363413f5fb367969dca009e0b12e19418f1a069165564d6218c7b63f8d860036ee1d5a8173019b9536498d1293806978edf390c5e2c011b9f0346959b9e460d63aa112f73f1009b8e3a35ec681a23eacdc9a019411ea62e1f79b2288c9cd2a2a8d51a57dbbf3a9237557cb06b9e1fe985f4b9f179b4356393bcca5326f1873076c114e2a3085b3b0a07a3d52676c13927ddb8cd361dc5dd36baa0d7c62ccdd19472398fca294e387257b50251ddf690a5b370074e64b21dd9dd6e76241873d31a602e928b50402c468df8a8289d5448cf6a859b8db3b7060f1d977bab5778f50e1686153eeee43232860986e47c3547ea7cd6edb8243add23621331dc721adb0050c43f2c2358505f20bef020f50d633f126ae6d07aed3adc96c14d0e9741e5696f1c337b434cc9accb55a023af6c233a1a3ce8ad020c05e5d16dc37f23b1", .None}, + {.Sqr, "-52430deebd30c8632be3c7822b7a28e7e5fec3288c01e0d1975fc43029298ca5bf16109a673d3bf52770c0f2d1ed7ee726147b00afc26e1b6109fe60240f98837a98ae8e7ea1d4cd9c7ee18e5c21b9c960b0b2e6846ac86d05494111daf119cc9ed0619cc08caf4343f9134c0ffa1122c1189bcb4e50e6d0f05914e8ede6587c649340b691ad8d392cd90eb0dccbf6ab579727446c9588bb56e7e9456be7ade18dd4db2ba6cb5a86e696b75f367c6fd64b405ea2009e9600bfb5a120d67cb056f517ec36811f859c7f3b8f74ae24c56172d974a3eefad19ddc1e0433ac8a6b6fc436c3daed96702e819cf749ceaa3c8c8b66c28344c6e7a28412014c805a817c44cce86bb15017ce2c65a13eecb115e13d69b07586104e6c5aa61f4c1f93528c1af2fd9b554df32c95dc5e1b5576cdc4e5b2ddefe5ec6392e72dd80bf8b66f3e96c79f6357b07c76b0aa31568a53428caf9d49c4740949f2748228379bd3120d6034eb2deeadebb3f6287e7a69fdc65a05129c724bdcd6e6c70495e9190b9d5e13a141c79948d6f27bfacdde389bd9415b624064424c2329508cdaeea65163fba3744cbc9cf806982d4a86eac581f2932af9625e8ddc1310d44392908674347f567af30d47ec41e5d3b776cf34e34df0fdc3101548b2f753381ae29c00bd83f164c0b5cbe435d7fe26d063a3b27a1bed4199ddb117101d98e1cfd7cb0ad62eb2", "59d660e0d443618217a619952aca020f553af0312da605bee30c54131cba92d29ea102c9c46fd66de667cbf32668faaaf8f471279d784741d2a7188c95ad0e87b5e8e457e5552a4438b2eb8751829e675c82e1751cd3ac313ee2c520cdaec235197b68d3b2149d420727fe4073f7926445247eaf85362287d0c401ba67880ac54d83afc68e4ccd4918db1d3e7b58061aee46083959332ca5551811656b594a67300a0b451fa00aa05d55bcd7a2ea3a9654cd84516b23e02ade69bf7a9a6bc31416f14facb3cfdb515fac2f8376d124448f7be5c69b918e724fc2d8c023ce2f2862ce737d3ea45a89954908b21ea10993ff3e83c50aa2325d4d7af3516f5b759387c94bf8e05e666892b5a16c5dfbd861f11c2ace29a0f115c3600419651be4a1eb5090ed18ac28ee0403c65e089f8d09ed080e673f346d9cc66879d902b5685dca5c96645d936f235d14d29f5756e940d0f3695616a5241a09a88702e2bbe6f076e96f72debfe765372d3a41901045a38f54c2ceeec2db399b89fdd3aa6a14518e3384392d094df01617665dd3fafd7917eb3ef811ce26102be8b6c3dd2a0f46d6e72947912efb71b30a7e355cc9ca33c89fc2ed27bad5fe4570bd31f0f377317c30006496cd6da06ecd29757de64457b3518e23376ffe1390f9388185b70c4cb0d0ae71a08c157da460834643e3934f43469570ff088524bffdbc4a3dcc93ef", "1a6f067d3cec65c3b2e6a112c0a117991e75e56f0e55a736067d462c0a55a3d44d35cf78735e8fd4e620ee7d7889f802d27d306cf26a85611ab291014bb1de2f1be1c144101b8f883ea8f32d411a2a067e4a5e274f8f98c350becdd029bcee0e52afede018ac0046ba34f470937495b73599c75d236226405beff98cdc60e18ee2689eae79f41ef923c6cf6f6d88b42fc612f0d6afe5acb0e52d2f18863e222a5cc907865fbbedf385f923b5c23555029b9c2a5177d55c2a3557b2a1c5eb4bbd66a7b39791c06a1e6c03cb7ea5b3889b0626fc5674d3b3b26569942be2bfc3451c937697c985c859cd7ae64bff00e335e2163b2be3b39d334b163a4bab25f54065cc3fc233d93119e32240e4db9b8c23ad1c421f9cde163eae61f11d1e1ce2e736b27046dab7f0eda267d0be48b4f3f68edd2f2bdf196e6789529a84ca193315cdcc8f0aa7534ea3c07c980c874ded6b93497b8d8fcdf45ab5fd4b137c009ced1dab67274df092bee38b22c499aeada7ed0b6998642e6f5f612adcc666b4df884f1798864817cc9560afaeaffbc7cbf1af9beaf52a0fbb48a8356e97a2b50711683b499efab5af1d78c1bc8fd6a5f92721cbcac0cecb57ccfc5c2a5c28f03c9236300d6a48065c050934e5307a6f0dacc13d05a7bc6e18581c86c1bd2bec98c3cab9516b9e61505b24d09f741118d41d548ca4a76c077783c84480b1c5d89d9246b117e4f487aa1ec8504a6fa50632d6a5c0ac69a8818e33950f2cb71032fbb875baa7c0ae93154fa0c2e1ed95ee196b6680a57e4fb5374ab1b18d28044a8b721e680c493c74761a292137c1226f2e19db7c66efbfa30ba40d0d03137dcdca1a6207bedec75dca5ddbc2aa518d9676fba6fd20fc724919b8e6fae4a95ba65b6def900612bf43d16168949a0498e888ceadb011d70eb649cb2f2afab5ddf5d8ac62b1856f7cc095a8929bc0e371a2b9e28eba1cc88af415a21f49c12759e07294516063a5acf19589d0aa3db4f502742a2b4760573bb8ab98dbc2b2b01e83f761adba7237971d5b2e002fe70b82d07f959e4c4d201d6ea18499224b4b6695c67da62e7bdba1d61eab4caa3caf96954673c703144985b5f15dfd70b35905de0d5160d744689bf007ed0fda1aa5b510f8c21728d813a344e2e424f4326964c088eabc2a37121c12e575937dc5566b2c5456663dc2c3f0f69ee9e010146ae2f0ac5c7bb612fc43a11a222db05223400e5b34a9b582cfd51f146cea9bba74aab5fe2e3f78e77b6e2afe49302af2e69f0a6e88b32d253ab6ae07c694a3400e598131a724f191de842b68eeaac80ae6922b29c626bfb34673050626758a99d5e840a537be904a793b92c909a92b2b9a6728065dfc59b58a78716f95536c860a3d563655413352c07f14f993e5eff19e9f60420077c700f0d07a79125a6e7924021c73c4", .None}, + {.Sqr, "-fa60d60d155e8017b7a67c3dc0a79475ab7947117069b9a619c225d36b10ec3c81a7c9724740d479db39340ecb4aca807df9fdf7a8755dda34de8a7c8605bbcac4956e7adccd466c0243ff39e38e85310e4eb832d69f71e3534f775c42d809e43fa063de6b7c22754d9fa0acd3657750ca7d239218e8bf0e37b749694d9ed75d5de1b895f14708f88734a2094f578966399af814f4395f12884c59029d63cbe7d3e622e971a44c6b38382a63fc6b138ab0aa9a46aff73f286bc0d101e3a5ad01bb38c2123e3c7667d0d085051df0c2b70b8c6e5e0c6728ae53bfa2ac82c655fd1d9e3cca33492c63490d54ed87596e179e4998c1766bdef3ab90b09f7d0928afe06678da4da97716a704ff7852854851ae641d990c094a426ff64278af97a63a60921c5ef56b13387d712ebdbb4ec27f18e7fa546ac4b0874a8cc44fb2da2f1cea99079df54a73a201f89a08d1851be25f5b8554b03979849a30800236c55c57de44aa9857823cd9462442133d1363d2454fa75604a39758b056dcb7e59313d5ab54718f71a9a11d990e263c79fb013b28662077a88a6978af28507a66a59e346efb55c3b5df492ddd65334e9ce5f3598bcb20b56ebfc81550acf8894504adb4b5f160e81c8ffdbe2d6a1237f58a8a73348ad00ffe4bf7db3f0fb7a76c082285aae2bc89c95e248d2ee691f0f659fd90a0029ae25206d78ed17057f9b0257d8b", "1230ebfa5f4553e682b3d7b8fbb08950d8a607205ee72e37be563ad511254cf264f83b1bb9f677a294992d9de08e062da4001952f64880bd58af6f2eca9c6b174f368ac0aeacd6eec58686dd52029f0176f1cddb65d2263c9b0192aeb34822e73e426a959f3a4283f2a4d454135345b2b1d788a7544eb1b8cd9be925488558046f74a16cc1503b55f266a26edef3682652c9311dbd16efb55bb6f4c5e7abf0a6f166ed63511677fca417fa935890a9ec5d94537e36a6cda7ca02d4904a7393832ed5498329ae95cb20318b509b0106a555f4fd932833ea6a70f92b31b51c37c1c2461749d7f4243998b1f8d6ec2a910898fdba60fef68deb1788f59685d4ac87702e62b2f5a8c2b14802ebcb37d8fd78a6cdd9370bf70db9ee78b0036632cb5d506694919f33dd9ff76c072bdf95db17a5f14cbe2fce293b5777ef95585474426025af5ca4d5634cff5fe0eda48058f96d8dded665a27f75e96ac94acfd8120722ca505a57a10180e713bedea2b061f6af227efe703a717d4b088fa7746fd18a32ab795448f7549ae43bc0623084e20397c066bf9beef1a4e394b7f81cf178bc39161bfcf0488d70008ec1848d9aa2fe8206020dfb343e967bc2bf08844bb25df0b0e2d7cd3679fd15c2c34a1eab2360de6c37282b793167bf80737d870bb0d50fae027f9bcd6730d321684bb8f5af2e89dd87dc1247c78bc29adc112428137c", "f4e146b2ca867973900434defedb9081473fc777b6b4aa0d74897c89da4a7de1488db3252325ec75b6c967c356e220b6dd6e2050c2a3f3775ac930216e5538a046b55040c272e21a0ccbe431c31715aab20978c9b232bb5872342debba6b1e7bfef73012b8d29491f5ff536e1768b8109725d99ed130bfcdc4526468c666628264d37e470974b11c8939a5fa4cbcf5dfad530ea5cd9cd1715f35dd9f6158001e15e5d9558dbbed93f4f0483911e081a633855bcd99de00385dd1996f25a88081ddb4b19b44503b668a0d1ba25d92306a445bac1754c13df02ea3798e00a65262d109451b0c5bc2957c07efa8ff6bb17b06ecc8620b52c7ce889a58f244764ea577def86fecedbde23c34bb3a410d79fa76cf73862e1b2262eb1d9b5b8ad2940d7fb3386bf4bd9225c8190cff060e3fd8b3e9bb476ef7d53895b1d91d01132194b8b0129a37ebee0e1cf8df359d49273d59a85582001afb4efafc24a7c26a16f49d460fcf5cab58e495d241cde1198377c8fc0feaff388664049ee4b590dc495b27d4232eef269e44bdcfd69bbeb14cae15d33b858a66dca47a32fab7d9ae14a3af7f0985c879a344b48c1adff758003c65c6109e5dad90238d47ecd09dd4704b40bab82a428c7281596880f8191f69b5ce56b30adf949ba2b277522e657ac9c5c83bbac1c15eab4d9efa0b8b2a2b94107ecbeffa1be910db0fab55a2e57173f657b4f842f49cd5fd4f924eb1c05e4e3c6811d7aa6b1dc66f72b6842e6a926476a66ee9b3939e33c615c06e849b200ee812d675b639469db990dc5382442d171ef2c8ae15aff29941215da350fd9ff609200ae3efed16b840e71aca05290681bb49ae016714a3de9cbd9d9bee231b8ea387b3354979cc2b78e15f9aaa4b2e15dcdb94581ff579e6df0d03bb3177833470435ecd5a1827c5b9291a5e351b170dc4ffce3dbeb0fd7ed84c11f1eb279919fe779e255cfa16ba06db89a2fde26501bf5dc92f304a770d632bd20e6aa24d4779989f6270050ef7196b7f0dd140f21ba37820735c6bbba10cd53bf6961141e646ae83e5553d0718823d009c3aff06016a17432d6bce69ce22661b8722349f66429ed58902f94462c3d3431b3e224e44cc68d72a6299729e55b5ea97f856920b2cc82c07d55952ed4a4a715d3585654f1b6de2ee25929bec03468a4241e47bddca9aaec031d124f8302a3bf542f4864d0964d89e6188dc6b3860db0b14e75fc590016d163a32ff42a83a9c63cae3103b0b01dcec102ed8c78977d9a5768a65805fb0a658e3963c8087f24b7002fd65576203e84ce758cb15fd13266ea10eb9401bce3f853024384e669ef9455bcffa0d624414158cb922c65e7d2aa0319fadb8b8363ff72f7f9b361ccd206b25eee4faaf476793f6ac4e69760c6e632d71a051c39fb4cb6c1b4dc1406d164482a7bf0979", .None}, + {.Sqr, "bf61951aae9f2e30711efd708379b6f13e85b2a600dd16b99bd2d1a73f160e534113df50121055aae182d43a1fe3967d815e1e017b90a8a3fc8dd25216e65443c62e5da3ef1a48b9d385871b1619bd04350597d33d81945c5d7beeb21e2ce7471363b72be5531cbd9dfa5643e34f7988d78fe6fba3fd44f945b1954920ef5467d98c65b3c00cf743a253e1ea1f7bfd3b6e46e7ebf75754b22adc96b56f5d34955492ef4c05d78a992ae3a16938cb4e5df6f3d6f76a5843e8a4e27cc184e93a1c536cf2302a67dfc5bd90fafb6930ff33af4762da34f30e9887ca453f2d221686bb6bebe9486ed6e753f3143ef5c39a8db83cca602f2300dcc099301d6a0691bb269b72a9d292f80d09e6c48bf66aef323b992f6ab59fa3f343f457875668946596646a8d0af81a266d2c80a743b8e13a616dc9c55bbaade4edf244fd0008c8dc95adde93d63b76081fbb2787ada727f9189da70d034bff3072eada68ec6050a4c84fd2c415caa78d02f3d31a0cac97d14b8ac30ae70547cd0cab08528cbff1574cb173323650dde24ea93878f01c701afdf07d86b2f8aa9d69d81208b78313c171b936b2b2ac3ccf0441d162043dd4a68c2cce061d5563e5cc7161d35b4cb4a31663bf224ee51c3aafcf25adbc67f9cce199be964f63fb19618bc14357dbc8b3575e8fa4c9aa33709aceaa8909b84945a7564d453ae94311df6dd58e16856c27", "bb226532c37df5703e20ac7c7bed4c58b3e8f6d0a8de74794a73771f3601c3ed458b410e7c23d99e2ad5c08cba5cf1072c76413325d5a6218ade0078860dbbea9d00e04a425de8775e37812c3ac78721b2e379d9f9979df2ace45b6dcd149b0a99d3d286f16f4ec6fdcf179580bfd357a6a0cd70ef6912f62bc028bdba4a0e3f1b0c6306bb7661b14cdee9db31b4046cad0757bbe0128ae8ddcebca3fade69fbc0039b5d69eb58c7e98f8a90d0237d1aa21fa5beb5928062fe6552f70cd5cd48bbf62933ce3769abf100bbdbb7af0a68b7fd3cff35da3438fcdb63ce65de34f6f4e084a1c4dcd2304af765d70efe6f4fc34e81344d3782830e9a794a8838b2234efff85dc72854c91c363604f74cae74145c923bccb2ea4136b00b0258e7ad621805787833bc0392352b9e6c63fc546c6633ef175144bacda7d488f14204f849f9233d8f4f1fce107ee44b0624c372249d36e4cdfd73bc0c9c38c26f4de8866f06643ab2c56b48260d397721a055df081af396472b8b95b03a13b2acc0c6ce1845af3d126431d2682ab1672646b588ed86ffecf1800202b3af6d40a3284826aec36d567cb93d11e2fc7bd42b0dea53b0cccdc4c00a2ed03e1adb3a8081890d7ffba0579d152465329d6c6d288deeaecba856a76208e52087f63bdccbb730821b7d68e83de31ab95ac17a037aa8a06549ce364f524b8bbb595f4f99cc9f7ca5bb", "8f12c1b025a1ed9a84b882f3430bcbf486f77c7d5d98a564859cfe988dbf04462385c48063c311ac9db496a37f73bdc24d3504f9de318b10d027fc5aed71f0ecb167547486a38a7c9459cda1b8fac5058e6039c8990e1f061be12115f0500e9e9e504f871a1458783ea7d95a603e2606cae62b9fe800baf18ef29c76804999c595165f12c976b817d0e5d41091f735350745f4bd0a412f364edd6cc01b38263253b95b3c1b59c360ab1c861681d371e6ac5048dfd3e1aa33b916bdad353fa5213907a51de7cbf2d6ead9b7f67bf323def18696e3c43cbb5c52385efc16fd01a8031829d74056d61a331b47101671126093e989d58e3667cfbe78ab478b3c93dcac0ed33bfd115e53ecdc24d91a21874d451538c06ef5b584dbfa010aa4bb3196296cab172749c9e40728986491307f66cf93a5a6bfbca9ca99eb72c4f00e58885e80783742d452b81e475bdca45da8f69bc004c0ecd188f3ab09f1731fabeecb51e30f5ebccd2d18506d7885bbe15f8c3a0b9f3a61efe7c1ad14ed91386f4303770c6eecdfca0875d275aa3f9a00a314d43cccc88a034e3108d9fcf6edafebbbf530722b93f8b2a898c238903e986c7c13aba6ea7d6b2becd156b5517c9e067df03f88af29c6173acd40dd4a1e7f09495bbe5abe50f68652bf2ced17daa29b900b58f48d5765d2d9b0a020b35cdea717aa5cfbf1d060dce35c0cf9f83ea5e3758d1bdee96a587a12ccac50eb0dd5f552b0f7cf5765325f42fe88e9fcccf02f4c1f8f110b6c9c17ac5f16dc860b034d6196f580cc21d84d5608032b10253e8285eb6eddba0685f221d9a04ac32c2dd3a4be3228c1ca679e12c604aca02bd7d73de44dca01ca272da6251f347cb0db5e121154e9e04f9fdbc845f5bf90c93732e3c169d167cbb8a90978697d21a9569ca1a4b5b53af9f82dadbd4ea1238ffe7b1daa5847eea26a6179f5a7959574e2450bb5f47fb085164110b4603aca15e9db74b906aa63ab226777ae112b4f3c8ca827e7d6a7864fdba7c90bbdeb36bca981fabadc4eabd9b30469b69601a983ac4f59ee6de35ff206be40c1265b64301216a7477a9ad1425d34ab6394af1f0e6973e5101eb8d226914bc5b6aedee3aa667f089d485e1c5fe0fdeb24211b4c2b36e8c6d2509aec7eaaa4635a39f805f2e07234831b2bf2b6b5727e268ad3edf2baf26a0502522e684dd7efb82c12bd05fd93706b1f14746eec1cf54da4d6fc3ae39f804913268db2dc8fbab6548565aeb083548800bbe0f66a9fbebfb5cd43bd5b5f0769ca5126a40f14f5dffd703881386db32992c8e6bab6da41492d9d2e72647d8cf557f1d36c5c8c23e3a16c09133201dcdd2bb2a30ed4ceb7e41b7f209a819f5e89eae028a9f345f57ed8340d34d44d70f3a238ba30ae1b4fdb344ff913892ecfff687cbc77b4278f0f2e15644236edf1", .None}, + {.Sqr, "a5d7aa76cbc264b05d6bd9ffb3ee933275458438f203c9feb2f8e054730bd86267be4b5aa96229f09c74dc9efd0126b29ebfad487c5fde38da1ae4bef30ed63d4d2f348dec47b8ca1ba75d12987b5d91ffa6e5ee2e9fb8555f15d80ac1b876f9788fe5157a65b32f7f07dc5d0f9c009bb642ace68d951103b8a83149de4ea1b1fc538ddb0bd48812b7cf1097a2377ab354ab71ea409849f1473a82446913526aca964a0414a15e1e83c5d11d5285985768d24b106a5a296454c99f4306074bd67e9e6d175232c115b2cfd39aa755521cfed1e24e802626d09c97825d5fe53bde5ca1cc0399baecabbc8e11c01a5c1c31fce19e2ca3f862a0a954978b1fbd7b2983705a4b0740d200a2686e8bc98544257e2abece897ea36872c49aceb773d6ee87b718200a38067518fca9368ac1fb31408a28fe4ed111481f63848bcd975e0845159efca998cbac4849014926731a54922b43c9e7f6f9b46ad6ce233c627a99f90f9f2e32537a24c163dcf382540aae7f161a52ba11ece48508dd1456a2ca6d88de18c5f64edb323d28476a7eba21c33881cea363c6d820fe43ef0a13015fd7eb68c27d66666d2babd93a72156b2f9eca1b75cd572ff106a0260599c3b12635643b6ecadbfa02c312f9977a66e721e872cbb6ee5c68879d2dcb93850b991b71d91ebdcbc8bc784499697f3d1e14bdeff7e18496e5751bc238a92ace83ddb26b", "f623e091cfe40e0f363d2dea9b844462c1e60385c8c1d96fe7381f3a73fd4085d387ce46a81ddd9a02cf9c02dedd4c66279d078cfdb945ea357845ab924f13be132a27a61b9c76677dff498cada1b9c4d2a07946a27edfdf067b011d5d18b9439e396bd56a5d14c3ba9844b46c4ad852b8609c2d3586bdfb88e8e370c98ae3c7489dcd6f2d5fac46fe314d1594606e503f567ec9452668350456c47aab76683f9a6926a8c024f978d0f70e89368ee237d7e7bc3ef9e9340e47c183ba4a47ff7efd1ebe43c2cb065e874821bdba0d407fc18802ed56db6d2e930ecb1b1befcbd5c5f7cbe2252793b9bd856e6df078331bef37a5fa8fc1026d4323738c3acce511bb5effe4c6c7cf47309565efcb4dd7dd206bef69f7524b7d387a27f70528301f99382ed61915ec928c0f22f04f9724d86656b26622c11dfa6bf54eed35a3ea2cf79261bd6b407b71649a569e509b18244c4437e24e11f9d5d3bd316cf220d5991e95f67415224e906205296b9e467b8ba020a020b9b10cc96f2d92f50ba91ca56423fe1a04c63209e949d7867bbbccc03739721f9d1e378e7408e7c94c644da63835ae1bfe942b666f40967c3c9b2f341537a5f9989fe9c299d978933458909f972948a2831bd4f3fad90910a3a29d3db7b16aec819784fbe03cfa4af93dd1a917d02a4ef5d860300d0883f331dd4c333bfb8e433723fe557b730568d81d0f", "6b6fb76ce7b4d40f1fc6e0219d773cdbccf76e8096eff78e23fbdadefaf36cf05d3ae9b1e0fa24956b12a73753ff23bf2f1e54ed38112c6a65821809ebf6b88b5a32128d39e9e6fa75e84bdedefcdac59b7926d04e4787a4ce5a84e76dd2c0fde94b158eacdd7b8d12792bde566c0b510abdf2a63b21ed30be449cb1d4e9236dd1df557eecd9d2dd933f39721fa18966cd4bca7327237d85fa022940a48a911a27e92d5aa96634157c49edd8e9de097a99b36260640f266220826d32790525d128be9ee71dee5e3fc67818fc0f67137ff6e958b377ba8ad1b1a0f1dfa36094e9c37c1ddba8688e31351f95c8d73b5b877f2ea2d4123923f231e772e74db59a34c76d43ee56ce4d653a7c37643c20a01daa5720e6610f73c5b7e56fc20d431c7ca30130a1b81ccae8eb2176d1b670eb8e88281064780511195486866381228e757175bccb8eaeb8a191ab6f2a834dbc775a9487a1e7e1a9f899306487319f147aaf30fb08db3394c450b49378bc76e960947a7638df1132519c88d9567f3d1214c8fffa897bc1b3fb4a217db0bcb8581b20a904c35bf0551ed9e4fca38fb9456985b6dc198d51bb2671f37e687b90f547746d8e692752bf2d361e8a7b2c2eab624016078924ad8d761ca4b462be26426e3d17def78b9d50e7bd0c96001c5ac4b7ca1d34c8935b6dd5e64a24ce9d1260e21f5ef824c9340063c929690d5ef152cc25fea2f08f0df9a33f6b6f2cc0424ecb9d9453b4890f824e3c4769c7960fdb0fb6b0f9d9cfa5c722838d75c646c0d073fcb1b9f8ee27755c024930ba0cea7f1bd06d795380f1737fb81d6c2e850d9e7767348bc6f98d222838824161936afcc42b3eb0ab43da30e26a0a55c09a345132784e6e116989262027d19db7392d7368a1597bafb8aab6a0e3e4fbb9ac1df66fcb0049923d4db282985167e90a22ffb4e135b3c8d710dcc582a7dc0f0e0f1117024c1647ee60bd50f4c6c282202f7244118c0fd3f24e0e2af38daaeeae2a569b6dfbd2e7cdaf54d1a765a3a9107259346db2ef9b7b7cfdff0c17aec1c1474a5bc3e79306c7cd55e7b1822b442a28ef5f405fc936f69c518ed22b0049335472a369b746028b83b84a60256e47cc1f537f585c9e31539216b48721242fb55949dd8bffc6c67087d5d67f5bde336e4be6b8338764a6d244c8ae28acfc644f937217ade7bfbeab73e0dab9953346b62c52b8aff24bc8f25636e04d832863225122739be9aaa67f044d46d73153b9d3bb04a49573560f3a976e0f2b09d8832bb85163a203794e63ec5f4e9b16a574b9596767513b08758d10ff5b43490c9512acda2e3f73c54b7e169fc4eec34da7e44fb9c6bbcf384181ff79c0281a9afd4350352faf53dd99401b0a459d15742ed854eedc441ea206ae4bf6fdc8f832fefde2da4b76877a9108f67ecd9c88e4cb0b16f8b9", .None}, + {.Log, "82ed70a53d3a5493708cbbe2de39ce2eb050ea0b01c6fb9ab75b2a50500b6a9e862ca55a2f320e04c2cb43667ea40766e60da2483974d19bb73aa588bc0c54efe718e3cf25cac4a22fc3affbb34cb3c6ca2b929a5e6eeb5b9b2327b44229684f84d8181dc409626c0b2349a8d47fd226297369255a0ad2f1c6b5d1bb33ceff172fd6a3abb4ba5ed9c0f47c62d7b20e1cd2adb045c9880e751933f622a965bdafd0148909515d1ca072e908f402b57b773c3795a236aa5a70918e2f77c7a4d47b50f644b236a924fffda0900179011a6e9b4bffcc43c4cf2482ca7fd92657b65206b4401293dfa5ee41cc77890a19b784ec786f06f06f5f664786999ea81da65ab642ffde0fd965c7dd549063486935e23c3e13dbeb10b7aef9a32da7c967ba83f29a76963049b0dc31d3c5667e1abf27e85280ba0c5b03640bc61140ce5e76f8f254090d54fb51235f1e666f5fd5998786547b88e914a06dc7ae0d562079865548ac4b5d3b12582be15c956988db8ac8539091d2421da664baeb399d29638fb797e928270bf34575b8926bb8aeee6964864e34ae7df2ec497c9c62f2e84a7aabeb2af62bb56d1f700212c6fe9bbda840cca1f4bfb9d4fdc57ee85f2ccdec0af39c7514fb9cb44edbec5fd1088641462cc6e6440c5711ee8f61715e08339563b152917c6b31fe4a7643302dd8b6fdba62bb496fb2789c52b8d4dc9e7a45aaad99", "b7fddd113230a7e", "44", .None}, + {.Log, "6febb7ed1ed1090472121407b58a5173046537d4b6260088a295f1c4f2da21d37083d67b0c24668eb3e7e7ec2f1d8107ab76ea0cd7b442591e61ac4f2d65a64421d568a23f2d2d019158ee759889d6362eab1321225e09d7d5431691c09bccc473611eb156be134864709b1783146260e4ce442237cf36f705e5d69b5a08d18f2ed22598e52ba792ab43eadf80eaf756e8bf0a328915bd44b4eceda017d42300e71dcfad3b70b580ec20b49ca01fb25559cfab98ecdc403f0e2bb9371797130ac1b83f1468d6e9ca2377d50cccee42cb11902673b347b0be0c4ef006b7c88ef4a2dc3919377f3c2fef9ba4bb5c6d904ae9489ce406b798a53adc3f10e8192149dabe8ed1dda75db0e262e0c531beb8db390339b62f8d732ef1f1d858f6f6576ce23ff23b606cc2c19fbee679ea2641d9fd324e7e7fa6fceb0c21bcc12a018a93aa5726eb4144fa51d7b3bfda703083451e7341bedda481a11d2c558d4a5a0fdf7704559a50cbf0ed3d7aff7fd289305bbe0e594cbe44858205ced38f181ffa8e768a4c33796e486090e5f48480a029a7200d36780ce5d98b68d7ef69f97b42a319b4176893d219948569b753d7f7ebce10515133880485ef8e384aedad9ec2ac643d6d54d3591612b1dfbc131a94b58729856d9daaeee7e169195cc47a34312ad824573f6b8bc57041abcc62748db3ad7b50557acd500c142033a6e56cd5ba53", "2bc678ffe0d7631", "47", .None}, + {.Log, "e9a197df4ab3cd7f37f14d9dd6bd0d1a7c344fe7586324d741a7c2ee509490283aae15a35292e834ae43e31b1ab294d3af82303310042b68e12d02e72a7786b4da1103eb095c95ab7568de29d8d4e33139f68658e8912f53347219bff47e5cb8afa617d52a3708327f77634b8ae772fa2307d43e2f2a0b134e317a8307c79c99f53eb30975b32e9210edd75b0bf22c67253c39466095714169a5f0eccc94f69edff70f7619bc128e8c76811d7df955ac368d35e7fa9bb39bf1a7789e8d3a766f14ba27e01190b9c54b00a5543db624a25757123342dfb63cb9f4ff9944faa5ddca44b663cf0ac780310390fdaa83c6af2b796436f0cd51cc8dedb4a0d2a949100767485fc7341fa6009ad4d749fb3311e549f56041c690990b63f0259b50c19a61ae3f43e4aa96355a419269bf0a127044a2a28c6b04cc7aa844c79ee805b5dc73200f04ccb68ba5f0c592092371c6365f76d4ff7e7fb9539c9712719a2b279d2b35b1d35fd245ed70f9fd387d6f8f6a1bebfb42557f803edaaea321c7f82dd6919456ee4c96af6dd4f285a61cff13bfe8482342c47d54a4e4eac1023f9d8a78d896fa478b8b82f6121ffd0e20800cff3f7a95394207b3c0f28507714c5d385e296fbb7177636d3e914fbede4bd1c91397a5a3b8c5df847f39e7ee8e8d4d671862d706bf64d1532dfc3687d0722e020a27494c3804f95d08213da38ea373ffa8", "c62f8949fbeb994", "44", .None}, + {.Log, "e6fda3f37326c64295bb70a07fc776c09006c369e32154ed03a5a3af2752af5a36ade3fb1c98593fd5a2b5e67dc7e9c43bf6436dbaa36d831bd354379a44c5cfdfd23510ffb389c62e3701f61e5d374d1402b963d3f51a540f40f56aa36767083025ed206d26b230bc3bdecb74668dee28d9543baa5189243f467da6337047fbc9a7579ad0fc7db55deb74e0cd0085274901a847539acb77f7fefd53ee5cdbcfa8cf0bff3059d2cdd3b939d4ad7a1b86372cf60775dd3207632fcab32113cf8cb77d6e3fe8c2181a7855f306f2248a08f38f84760bbbe68a3f56d63b7f313038c49c6df9f723fe22b7f10ae8ba5ccca2df44f0a2fea14c9c45bb18b319a54a42e7b0b6bbbde4735e5dde2f12853546175edb271326005d367753a7a976bb1c61b7759518a35dcc0fe6983791baf308f4f9015a07c30222eb19601dcae612e59f637a25bfe00263a1b3aad02d55892f9f34f6545a3f02902988d371b2c974f5e5b45d8660cb938c639ff549ac935eca974e2ed4e5c70d05f3035f219cab36c0d1f8e61e0ecde2693a30678a018f7df6109da97659567eb42ca9f20b87935b0198515378735f9c5cef4e6a1e6e29996d512e54c2207e29df36acf6926b2a301a4bb0fc6ef9879d39e546fad545c47e88a36d65529eab57ca8e2962ad7ba53b92fb4a015c3f2472ea0f8a8a770b85461d2505af449433ac5586f72468cf5325f5bb", "a114a80598ef979", "45", .None}, + {.Log, "285833da5f2fdd792de4f9bff37b6243263969dc4956a4becd875c6b0f5238a3948a5f3d0d17b45ea4680c1f24d15e070048ef257f2d3afa12759906505e6f3d754d8fe245bdf9e174daab73e334e5fa921339760faed6fd4ff33431cef0f40bf201fef1652234b0111f533ed70a03a05f1ccfe0e0858165d70e8a12c7876ceb5118d01e5de3a6558bba33d2c8569e01775f9ea9fd765463e8cd282dcc79f7506f5b7633cf68644208229b9d94c7b6dd1386bc6ad8731175209654bb0ee3bd103a5d3809e7f048bc9ff79196f9469af0f7a7a792ff1e95770b4d3280565fe2dc2ccb148af53f1c09670c85c24659f351878fc54a8036d3139d5a4783ed926b85a3a021751a46d373bdf3b416df8d06c36005aa539ce59210c0646c72f5d2176ddd97842158d92562e5f1711882e013b24bb1bb805be35363f64091bfdc115debda704e0545411a6a2abf4e50ac89d95f7e6f7001393034816ae2a1fe11151233e0daf1cbbc11df25f7c5f9e979aa09f648aff57c75e55a9ff82b01713cff0d73693fc37551fcdf7fffbe9361b41266175f677f25b96f101c71fc5dcbe1e643bf1df2aa8ed09463d15a3f37dc16c6f35ea2b2806f94b7a123b63c863dbfcaf408671993045196b47d8ac2f74e2d858299d318e0bb9e7ff8b1c96112bcc14df3aeee9676fba675d59948ad31965877230d3e0cde46c84b3fbae1f987cefd7ff0f4", "bf12d4803e8b201", "44", .None}, + {.Log, "4289e0c8965018bb35250a766a79029519619bf71230f418e0c73f427e3d3c3f8737591361f8e9485bfb86580ea50283040c8682e63e7de1126e4937408ad1ff84be497fadc6b53914a07887f27f68cee641a4e492e3fe7fa05a604162ce4a32962196979daad7aef0204c6cb12d6975a23675f92a2fb4d2e078c23eaa4565d4c14558162019d033f93452e216e62e2112e314abf3960dad8cea8e3af12461ff257d68b253d105f0e52b436a95a7ba9c725ee552d7b90f6f411a00132566fa2d9ea534eef33836e531ff6d96e5530409e14d75e1c0fd0555fc8f8cb11f4781af5ccfbbbdcc8581ded28b21930adcc7dac47a47462ac9ae463626ae2eac4d32dfdc5b63b2bfed15fac65aaf78ba9e27872244ec01172e7e511539f01db83cb95f46f53498cb2509b3fd7ef95012e317c40f098bdb35b29113ce823e929487c34e32b64f91975647097b49e834ddab46b42c957fb9ca03f1a95d1326e93d640e1cdc7a4d3b4fad861123a181dc7f41fe344e55edc75f81aa06c23b838f4dd0b3af3b24822218d4484d629bc0a03e50a6ec66987debedfa31053f43f62ae608b3c13181399be81e24ee3f60a6c43ca08bd1627da175a3dd9100bed1873e458b6ff9f591c6591b623c64fd84847c51911545263dea53eb8185ae51f25770d8e7820298d479948a340fa2c883f0a2ec88f777e7876fcdc98f5fcb86c60b52bf03c4c6", "5002ce4a7876352", "46", .None}, + {.Log, "62b31a8b1d1385a473c532bc5adc9d1242a64358279951276bcf23fa624d8089aa1839a8b08399fabde05d89dc0c431dd9658b35f680b4bcac4ce9b35c673e61ed8dd306bc7d0197a0e91403b12d745ad146cf620701e9e45fe41f878570cc2fc3ddb2efe1e8332c3f037b5b052c433f0ba5f6dd737618fb4dbe6b1f77152a971fc284991ee51d368c052c1db9ef58a280d38b3f156fe3fe0cbc701991d664939b2cc109f7011f77280eed9f5b7f2bf3b924aeb89cae5a99f20de702c79aa10f32f385bd1b166c8ae2a0dc7b93d93b15990ee3c5e7dc4278e41cc90db96e83f4856d6f316f25e90446623c399c9ad8f00a943d347aed431c12b2676506af1c079539de7752c3e3a57cbea86802d5dfd7d63ace822258cea35c75cc7bce87b67f8ce33a99afbb43ed57a7c01f68a2f248e4fea155da869bc128d6bfa790f574e8d2af16d78ed82d11ab0ff64791d89de983a1bc2483e24d3abe61860db9e85276964876f52147e6e7b45a4fbe070a6a82bc6c43ca230c6fe3a50027dcbe80b1bc3f75e5e07f55f54a391a7e88e12e60138834b4354e9d5bbe86ce3b702f14e6f8d42a33bad610a49996316aaca8a5c1ce0433607f41ae39712a0d670ebd5f5bd1253fa92929e736fd0850eaa1828aaf79d987df77353b796fe36c2769143c08234708e98c6cec965e09b200728686914a2ac395f4943a4488a519c52a005c5197", "86aadf660460a1a", "45", .None}, + {.Log, "5705451c1b96d2aac8c9213621e4a1c92abaa467061572eea427e9c15c807f7667726ad9c618099d7d5dd5f6fa6318f35fc0242d2d02e3beb839aeb74d13cb77997b8f1429c74e788e34f84568bf6b5172878059278d212e510baeec0e72c40fc4d4505fac99c48c45ad4f9fa9853ab1bcea9e1120b7ab3d483f035b77e3a6abc576d28bb2bb4ab357d36fb6558772bd935076d8f40074e1bc9016bea74d001b243da6eb77c45242ddcca2bc3092deb1fd1e1af49c4137f7e4f4a071cc0e74f4a369b4607a37e0536359c3cea7facf17b40b304edcb6b3e12accdc54125792be9aadee27a24bb7e71ef22f583a0d3f8c82d751090becc4560bb4c3b43d62e6fab9742f6f1e285e51a406e02532195f1c0112f4c1a326605c8ed98d74a36f0f8f6a178e0904ba5cf34e84b123157b237a40cc40fc3d25ee3db146554392530ddfd3b15b03e503698342ff8f099f9724a49f5151982d159c87b227e7efc8f1d48fc850af6dc51df48011abacb8be78a6eb2703bb92e3b738055b99f89c03c88e91f4641434a516db841285304d66364747cec60cce624f1f253bfb0b8c48fee1a9e9416882db7cbc99efcee81b06f95dcd4f66b9a6a26611320d45603ea903317aec754facf347477ba1a359fc988e49564b31a5df5a3b6414ab84c316df1ed07b1cb3001d6bd72308a5568b5ba67f4ea567594845d97a61edb905432359db4e2d", "a6b6b8941eca370", "44", .None}, + {.Log, "198882901a1d49b5ccdaf8d4e19a0fc1f78e456f9f992757a143d1c8c67f5af819cf40313a3ef92b5ad4654a400466dee0c4bdec0f69e1c6149735e941af8828236f7a1860a40cbbc18a2ddffcca67180378dfb83438a3d1546299866be727f1cd7e62763326c06c70d5495b8fffcaf8e4814d616a4193a060b3a9a94ad6ebc73660f07c118a34bb6ffb008046331b99e46507448d251689478065706c6db82177bef79ed2affc73aa756530b4c3c5ea11f0b225de127dd2eeab37f7b8af86c964ca9dc683212b99166088c83df31e39d3100a453dbeb5cac18d1a09223b67ca67e3111d0a7a22d8491e05186422fa8448c821eda81fbfb3088982280b9da8a1ce8d477454777d2126bc799a36b36a181f2d79f6fea596b0f80159ca1d5a46932cd1a045a45f4c4bc8471017799867614f6f29a676a2ca70ba0b18ab7950d6adfb1b760d7ff191a49d93434940e585f7dcb05b0c81240b5d878104cafbe14a6f8827311ea74f466a19c556e5890660c2393ca0c3a3de930cd6dbb547a3f7ba54025ff07f79606a8b5e8cfdf868165783eee29db128aa828ad685b924806e2b0350acf6550ce6b15eec15d6292c7df6fa8ae0858a225c00fd6a2cca6458035902385886a3f76cfc03f255c203922a6c588cba660415a498b3a71822b260bb1439209c1cdb5758505f1e1e0a13fd56472bc72b7de8729c686fe291b161922d5c6d", "deff2c878a0a961", "44", .None}, + {.Log, "99c4dd996fc3a082436fed5f7714571f1612855ee0c3865c7230a32a33b23a83dfff0ace5a0b1e3cfe9b8c40400d8464613ec4b98a74226b36730c3c3a6183fbcca75ad9588ee257c8a36f163350b592d35112e96f5a51b63f65e6e0e5ef2d9c78e1905a644983f9e75e6c1f4013dff650ce1804898693d9104c019cb28e187a7dab0101cfde3d272c2b5cd950b1b5b8bffbc59f9304813dc1455719d37468e6aa5716a772dfa21dfc0e6e8312ec97f0cb51ace9bd17fb5769ea28e92c85606cbd99b5de1434b63b22d4ff45ca104acc5421f54b73cbf3ea8e0c8b506c1240918f9bf76134c3bfe0f1ab2194b236dc8743a6eb9faa324ea738638442d7b0b49db496cd2f5ac65940fece2f1e5980c9ac64734d9f15494eb8a8184b52022faae2687e3d5e588a718c9fed7310cfc8c0b3093e66d64ae19f5fc7b6c64873b8778c02387d81d83460d21cbe1f823e0e7f8a6cb842178e6704321a492fa6057ad2f5e409b336ad7b170c338b929c7b812ae153447079e9435af2eb1a1bb9ed00496ad541fd880499e4e0a9855f362c92bc006c292a5df697ace27f9b62840010b6efe15404a7aca506b10b6b2f4f2ece1e25882b3a7aa03d4b089ee500c7cf879d47808419517402a59adfcc213b4005d16a3cc4dd7ac0f6350352cf6157c8ec506bbbf60d6b6655612a5a49891fe7212085a7e9216fbee89e3a9ac0e43ef136a559", "23ea627c8abeb5a", "47", .None}, + {.Log, "a7ae7e794048163d82f1a894185316dbf220a6b64fb996c58e0035e0644e2864b581c07d9a7b332cfd2b0e5e48d754f5264635a17708d8fc53a2a655489bbe45051296bdb3f88ddcee3111df5e8721a218013ce80520d9f7d57b0aacc8a328648836d3b6d68cc16b2843f2572c77b2b50254ec8088e5e9682a223570188a2b024d82d6d1981f8691a98055ce49e76dea91b534c796bb0117a7a3bfe35c607e2422ac2caf20a408f0c2c4e4ec5fc0b939b772dd931d1e55fcdf6c1103506e95007adc385a81a79aa50fc465c92c98523907ef83190d00ceadefcb40e5b6d426b345a004978d6cd7368a41cbe7d67fe71030069943949e0f23a211dafa8ed43f90bea8c6d57a42ed0d676c5d9638e25968a0b9852dffeed4d34714205850f42a43434a9910c9a330f2a0774923fa6440b880d4a0987ab3c0cc95d0c3c6074d70159efc3f8f931d97fb691ffb8cf4f82e617fa65e2085d2eb6ea40f8f2ed13430e4f77c56f9e2197303b27e3e768ee3bb243fc3b08b08cbf8995d918ad63ee1534a77634473ab5ece25c62c947b5389c0e3b88efcadefefdd6363c37d21acbce5312fd502a1fc6e12818386d1586d5e6f71c3082b146cf01c4a0f7f0ca178b5652d493afdb792e08187a982fd7bb91cb0d556a95a3856d5877d2826daf35b5f018a33249ebf53174a56b8ae03abb6bbe9846a88e72d1d12d4d1c11cc74e4c841a2d", "e39e5f3bfff45c1", "44", .None}, + {.Log, "fb8b1ae34a56aa351b189dc78823e5129e3a1e3f5fadd690576081d2c666c96fdd1e99dca6e443846d4310dc6d2cad6f184958c58f3f632abf99928d33e704bf76ab6a0bbdeb15235f776f7ecde7918da5695a3a37ce8adb3e87dec22f4ea4c4ab83a1ccebed4b7beef133b028560884f85a0c3270abb8763d3cc6015fe2425d7f13cc027aba3af5b4e6adcf787bf96e53df1a16d96441261e633caa6f28e81a869e8ec3b4667e6df8693f63bc0f196c674c48b67b6f54f1469b379c2470bbf5d79935a20ff6b8a700122172fb801b2e75d4e757d328497c0ea7124b279a42c2564a124767dddd8ba3c766690faaef82388b81521f96b2d601a670ed89bdeec121374b670f4eceb08f3778f33ddfe2b58e15b72d1edd7dec1c9802c952d6be6bf434f5730e0b6dbff83f261b2321963ae843dcfedb4af4236a0835a30f01b074cdfbe0b8278e338408efbe36d53373714d4b243ba5cc4bc2079c6fc5a5ccad97b9522c36613851c6de6a46d4d61a3907708464c5acaa331ab2c6c350ddad372f0a9b00ee26d6c6ce2b1c1a8489366b80f3d7af5ee6a529b51040a478802cacd9cd089fd75f0bc0a9724e5ce44bcfa49645a19a877217aa65b19d15933f8325034a4ef9fd232d0d510c7dd0c1ee6656bde42a6e834cfc26555b55876e344eaa59e2291904a9a0c4c3613efd6cb45b164d560f65ab1bd6f1c6dfe3e316bf591380", "569b9593ce841e6", "46", .None}, + {.Log, "543be003ec903a0ea60c5931aec853021320c8d421c3182c8ceefe9fc8b4877c09fd8e791420c842b7e7d6cebe56404963d9915912daa05e8873bb20453a1962475f230eb96c8b34c86ff4243a59089b4a54a5db903bafd39c406e14109531f3415e09086fa931d8a4a14f8fe98e6d0485c9ea2ead581fd6228957012db2aa735adf6008fbc8a2271089431abd57570424be2593d7c08aaf511c25f071ac9245cf7e33535e5047e7e137b5e2edc960f0af8505f010a2658d7d50b3141cab472953a00d19e3c9e46b484f9b019a2d27a65003cf362da76d76070c6cd6f68224d6836cc68fe68155ef6d5ee77f7bec9f4a7eff53c54ec22bd51120f451df121d98b1c46d515e1273ade9a0325796d8a950fe588d0a2fe90b757aa144fb7d974fecf49352765f62c61dbc44c6998ee48c21d64258b516e2308b8b62a1acdaef3e1c7b890b0cd61fb9ed92d59ecbfa2b25a0817bb550f55f3a9984986ca1fbe6add0d2f6d3bbcc9cb3d6d7d910fdc9182d7c04442b3e5e36a8d6930c54a4c9b0c5fc392c1b0be8bf12d7b35ebf42bfb64da9534f26f30365f46b674c21dcb0ab06ae820eaa90e7ce06e5aba0e72a328fb82ff8e9450bd4e07b508c55ad90143ef5e782003891b28d22a1a74a35ad1778f98cd86a6d7960c801cc224ec532c90692d04f39cd30d42aac6b2532a9feb64fa7487236c274af558a2f0b3d094b2ebf6661", "d52dcacd4b8181", "49", .None}, + {.Log, "f53b2ffdb711552cd45c96c02d32291d5c729e5063c4702f69ad8cbc7860dc79b653568d4d2f2bbc2ae3c6992392d97d0123afff28d6adf4c3d6bfb2e26550fe6fc67437963649a0fda720f392ca7612d9d42822f520ac539c65070ed50e0e682cb4804feb218805fbf2bda62cae58cab756aa6b36ca9938f5ec21f051a4daa63f726754641637bb38bcaf376da2ac975c506f25200f58ba968aeff6c2d5817e19d3fc2ef9d239da14294d161e39b4ba05f17cbf1450fabfee0ac92befb908db16e0ebd3f24f768868cc178d9d471edcdef86ab6a22f2c17fd712f8cdb841d70d55455bf0f90af1e2e2e4c74dca28327175841c68b66f896faf0ced20c24f7560ca963e2f591a7b85f7f174c2b97e0805420b6947157ecac5577875282d06a40dfe85018a1c55a9a89553d466d32df06f5b2b0678b1b9ac3e33a39c8590b6dfd14d1c734a1631ae92d98145c8e4ad09a620f98211a6a7c9e69d03aab40f9675ceba48d4e03645e36b15b3648c2f34f31a5ca368f5f0216248f6782d92aaa3b9e3fed5626a04032316c93e8e8230ba64485bbf9499cc2fe595f2adefcb03438d97948b567e8de90b16bbda8b00f8b1492f4e04b4b029a3130d5b9ace6d067b6b82c72ca07ecec271c7f76f865ca2fec4b10cc0edd6b1bb530e9f473fa741fc75371b23050b8cb1fbb1ff0b690de50f9ac3d902d77b4a0366523da15716c042ba4", "6f0dd57b6ada5e5", "45", .None}, + {.Log, "3813912c915006d718b918ab6d0628432b7afe69a83ff50ef21d345ac4d9a7db69e764526777ddfaf098450b76ffe13ebc99e87c47c07e6ecd6ea49eaf60266a063426fadace0816788aa40ba1bcce8df6aa8fcf4aef971711eae2484cbdfaf0e90bb7686c08531643b523d34bb918ea91ee88c2af34e3f6bd828a9c44e8088000447759402f23d460985efee86acf06623f189340e3205f41b94d49b4248090db7b174ba6b62a294b1d2c7aaa434b6b09f896e1feb3f193babfcaf20051719dd1cfb4973b72ea4b370715a3904efd4db17622f2fbadafdf12137919ded099a6848a8e677df413bdce988ac1a98b2290109392ae06e6caf03c2cdb03544c57a5e4552c7b4c997567f9ac45d861df4b277bd388e4c2df64da5415c161a4d491615c2d1d57ecb2ec98fa381e6a639511fbe1312e6b05d558964ba4d4d14f765ae8ec2917ddeecf739131c66ae96a22fb52a1436a983afa065e6b21b63875785496c9a53e5c2927a5c2fff076f5d3c896d1080e348533152b26e80fdfa46594c41f032faea286bb1a2eae20cd71d23813a98c585c057d4549256ea52b351e6389d6b4ad2d9cde6509a8f95880e4befd6f665f6fdde57932becb2cddfc99a19d47369aa1b002f60599fb0631e4584644b9a1051cb0d99224e3451352fdef659770c0a3bd84b7af7ea9af17b25b709562be18999920890004824ab2cc8656e4db9698", "55b976fc345ca02", "46", .None}, + {.Log, "b9c51647a78125b6e552640064a1c9b0c6210f24b88ac5169bdf24fbca47700222ac0d92506c71ca25ada635f257e51dd6db6a24969df1385b3cfde64a53d5834122306f2fe424561872891909e84a6b992fee373f047f633686125066512682ec1f7d6b719c1ef4d2b48b0b4dbaa883c585f1211435af5748d7c57383f38a48d51195acf4e8c00af69d0b6fcafc154bfd25a52bcedcf306cf229efafb67d35201458bf30bf09b6f29aaece662fe91203cca838d12e03855c61e2d4befd47e2ade12c68fdcd243e7a6d3b240bdd3ed16335fc676201d42c62ca9c734cdcfb08a1bc1fd224360a7b71a07cffdd9b593f1f22103786aa78f9266e397046dca4d17a17faa845f14600d6b25f6637c1240504feb421a32e3316a58712011d2a85794b6d59952878d4499d408f76db33a441c83b30110a07d680ae86a1e248a915d59e988719ad1e04b0c7d9eb3812123e13d6489b740ff4991e21f181f841358f970d22134004152256bff4be7d009e0edebc86c8d43f77f8cc47e011f6bf84a4aba11b4f7bb6cc59c63e04e77dff1fcb51bb88b2b6b3fc1cdfe7291e3ba9fcaec7ba2052e24cc88cc9c512657e65e209080ea2d2d32e3f387e6391c1c350a9b709f782d8aaddfa575d1bd39bf3b94a5d0d48a5fa9bd8123d39b1c6f9dcc42c6c3f6cdd9c214101dee2f27f585c0308c44ac2458f9d329714056ec3ddb15f4ffcd1c", "5a86c81e5239362", "46", .None}, + {.Log, "f77057a34cba9d425a3702fc4a9f0ea05790c884e5b4f2eceb292e0bd872d71b2a399b835883a5b7cc8ae767a1b2e5dfd1f9cc713326998c25f6f105bc8b33979aae9e9d8e2a668e4228ea8b4042ada3ba14304e1eb365d6767c27e122edabd10a02ebea9fea26cba2dbf1962ca64720833ae01ce9e5bfac71701b06464815d0094864a6cd4a60acbf31cb29440bda7d06b615bb38df1bfed7d6f8cea800870e4b4c4171f435e165832f03733300708a374153a8ddf7ea82f1e8a79ef1b06599b68e53b53a924cb5f78c4032ffe7ad5afd082978b02f013ceecb264fbbf1a1e169f02153a40e94174a4a85767f9410202f4ba6471dd0e56d9ceebd6351335fc05d143e59f7f17fd6d3f7bccecf5d99013416c29a5decf9c8d2486f3772ad3beb056e0b414897d28926106ce50efc169f66b5e03d0420cb04d23cee81c1b32479225615a9c5aca8cf4afa036a259de6e9d9aa328090bc9953a7b95def3b841137946616e1d41834a0b31612b69e9f90555bb6bc8e7b93bb1c49d36d0740af1cb4fbf74b1cd8f43b88ed936d424a209271338b10e5c5e476cb7a54acbfefcc26e9e5ba6c89e186135fb3609127240df6200c5d4ed6fff6dc256f14af6daa5f3ffa773859ea0b39b2575a5421d37f43bd40a353aafa17950f23bc59be1199d9c4701b8fd2334ba06680e4ec1830ddb371a068c8fefe727e37d7d0e31105056289b5", "98c6ff2bbde91bb", "45", .None}, + {.Log, "8530d4f2a773279b9ba93997b3ffc4080a0b854a94875c52381bc7dee7462d9ff84cebb0038955ff59200fe80287fbe481b3ec152823a425edcddaf148ee5ee9f5f56b13843566dcbde38b84c784e01c5eb5cb6034c48a4eda88951a151f9a73e9082bfd6316fc01828e8b01cc113956c86a90933697824cad7edebed93f916d7b094312e012b05cc4399c30cfd750c0a1a194bc6d6f8a996c238221a1462cceaa69cd6a90ffe63119114d72996fab29c8e1d21f4cca305df4a04479fff10b1bc3a8227b6c4965af7c4a1e1763ef39b4f5f3fe3816cb4c41494f6c044e35e21c21ba05d17562418c2bfbfcd8b2c970c9cceed46a94a2dd09598180d25c6a70fa118a06758d8b4c7dab72decdaaae5f2976115f960a8a993e74fd081802388cc09fa8d7f3a99aa96e5a6a0bc417f6a33f219b7dd566bfc91df1a467421a68bf6929101a7e5b20ce1571ef2fef276afbbdd6d74115ac521995e204e6a4c37090f62cb56e252b757e57e8d135a6fcd439106381318c4ad217e8377a904e3262ed339723a48c7443adb745e3fda603b62fa883e9afdad58b7ec1ef58d84bbe33396e59984b98c0e038604dc073bda3bf5c3799737e031d5486cad1d8ecb7aaa123f3b62d60e4c3100b123cb128b624e57c0b1a800fa19dc8b07d263476b33db41df3025ae7161c67efda8ab6e2ca21c89073dcfa0ef6d1cbee3841f4ec29b8e7a938", "66cc301ed9d14c5", "45", .None}, + {.Log, "79547f7659a60082f60d90a64bf927ef58230eb7989cfa0a9999c1b7c912b8e11bf7ac0747fb196bc8bf6b4740cd0b1371fd0e985f33666924e89d58c97e1622336d456424ae7dbc833e703c6a8b1548d44fec1728d3afe39d41c0f24a166f91986b44ffd4d74001710ea0c11132e9f804b2091d18d3e92508a101d5f76c7a43518a84170bd0425b20e9342651d7a0f9883effd9fb0ac92fd8774cf2050f1f66c34f528687ca458050c6b10d8bbab77813a272b4ce9efb81c60e5bd98040bb1a194e25515c758506691881dfabce0f7e12dda9b10b7dec4e1ac41450ecbf92d6575d2cf251e2a8d09af8c79d0cb2215c8899375b8788a91a449f30f75b7ecef1efcb4fe13d09bf6d89a6be3dbc423c3b1a8a4dc45ee1de01a6298405d910a1b51135b5a301960cf415b3118bc2964ec6fe255d85ea133239fed659f9ec032cb9ca1d7f0ea6a7d6a857015cc8b6ebba7c9d18ce3eb1d11c3822b0a8f6d8bf2e1c7aed44a34926543f4b5a579d2d2ada041d7c4820f1a6acf89835a98008576e945c576151fb5c20041ca93c3ece937e4409b5cdda6e8b1aadadea707efdf5e2f5a3ff1c001f8c66d5b367675bfdfdbf1a08ee2fd42c2faf38d2e4f9963825df10fdcdacae5702c4c9f6a202c36bce16edd8e02df0f7be375e5cd1e45466d5e0be82543fca0d74f1e8cf300a13b874441bbff0ed693995bcbefeecfd88123e9d7b", "608086a17ed9fe7", "45", .None}, + {.Log, "2d8431d718b660458a7aad9f0ad60542113cda099c85c0a6db1c218f5e83cb0342fda7cd5a32dc67058695c2a46dfbbafac7ede987f49068c711ad58793db77ba29dedad4a4d415d8a9069e7d2e4fb5b1ecd87a4f354f06f89575681f70c1e22b8806371798efba23f75db092cd616a5db72f9251ecff8cf31552693d9758954b22b9b04064804eaef5baccdae3438e19db2008bdf2e7569dd242ee0340d9efe4a195ec19f781a7bc265e29f80ffbcd3702ab5233267ad0f9c2849c87c62209494edafbbc0684db0b522299f908c7d4beb6147266057c9e7aa60c5931b6ee7ed8add0d1b4a5620c4ac5f1d05bde7e2803b0c57b0a92cf89bf4e0a46fabf5bd7512b45a3652e15e73dddabe93fa7f4a5eefcbb05b0aca80728f33db3ea762152b53a0e47aa795c96b7345ddf32b7886c0bbb2372c6a614d9f3310c542c98f72cc831aded8f12f4c91f4b2da99df78837dbc602417ff17e3efee88bcc3570ad9c470ac65e25bf980dbb453b0705be73680575277b4ef1b7fbf85b62383e4b739d75c64fd2a848ef133e028e2995bd411c833ced5acf027a75c6518da100146232b11e3b8b016616e965b2390adbad6d2cc5f39123143fb12fbc90697c5db6751cdb7b4e5f61bef83a30f8312532c51013a52441fead7d2439a8d2ce1a544496c26e1cc8234576d8b065906c34b2b8ceb2bf94bbb4c4ba8a08a7de1db91394e60bf", "43f580169ecd15a", "46", .None}, + {.Log, "756193bc8a9e99cf31f71450c110312845a1b38139b9a94ce3f28587636827cadb728385b98d424e9d378381dd9973f7108bd50304361c815153ce85eca19372529c82030ea77f0c1e3ecb2da2383a009a5f0ae24e5c2f1ab5f86e333365ffccca4a47290fdc99123fd85d71c80b5db304379662c74697ee9150e82af55b178a9bf3984221a0d02cfe16c8c7039bb0bf021c3fe66c4bb06251b995729df3cac163bf2e2b6f66a788e472fc3238b98a360f052c2ae421980f6ad8b53340cdf91f534f5ff7305fecf5595f1f4ae3f742a79ed5e71a5c54db9484c4d343912e97a1f85495d9f4a848df310168bdf25eef05b95e67a970b645c657a6b47f9272d3fe8e185d36f21ad0a21f74cb89d8a6b3246820f20f4040462662c1e359205bc65de53a4c417f7185d7e59602e62f10a008cca6605dc1f377a0727b9694cfca1d6992161d56fb8d26c25f4ed0976022fbc969643a723fb02ac4676de7dd566e71d3e1792fba20d3ec0d130e20bc2a7c3fc7ae13faea8a84353084f748896b5c1755f76c0d384efc316125d1b4043f061b4319d35f9baece5095ce6af44f7519fd01046059d2ae3722e6dafddcd1909f72570ebb63557e199f2e7d29f4512eaa9664e8e0bad59e246dec893a0c218371bc5ef2901c2e5ce462cc704a16f7bc837c83bb39e3b450833d91130337cb5b0704808468a1ea3df74646b433362c53bdd0e1", "c0e75dc32819021", "44", .None}, + {.Log, "b34286af6d178032b1416bd71779ceab967d1d1874fac6cab5e517c76d71cdb296334586b54619e65014fa657b57874f6594dc5858abffa2745cd7fb7e078a74d2924593171c62219f1e31585d24bdcf9f93322435a408bf975edbc9230ca6ee64ee15a7bbe5ef9701db0bba0a0f90a650eacfa58f56b89c07f404567ca242505156a284eb8c3e979308f9d168a873342f788619ad93126dc50496f64ff46799f1ea170bec65f5723e435d1a4d8e5e1b5b6976f7461bc0f7409648522176228fd371aa637daec25a9dfefc82114f85e7b328077ac89b17dc152b2cad5cd2ed47c9c63c7d18ae18940ec99a1cd75214cefe7ec3732587f4007542fd1e95e0906a74717987c21a1f4ddba88c5fd2a93ed12fa59bd04224c5dec7f7483e2be12defa05153231c3b2271089fad14312fe5501ef8aef63357428da21284d5c1e78cbb70022e2871b2b60cb7c0c5c98f78fed685eeb1711b748d686c464dc631989f91bb31c5828c6b5f30a1fa6b339dc08cdf594ef9a5f779089c184d74ec6c3869343a769195930ce1d431f8cbde7af8c76b979dbb392b1f31c0afbba48476798b05df98d75860ce97430a6e29dbeb9ff36a1b69e8a42001105d3b73d4abb8d5998d4c5c403ef420797f2543df5c2578e6e27b616a24daa7db95f1306ecbdf43ad41ee4244b489c570b03de93e447498cf1dce7ea67dd132b0489de2ede04201cc2a", "f3ff6dddeda12a6", "44", .None}, + {.Log, "f9acc8ceb0e4a5a64aa5e0e161740a8a9a69f7ad8ff736fac590b778f7e82cd41ed20b58ffc846078ccb47603e23de6d20078410912ac99cd3f1e6bc652744d6f7cf3467a5df1d2303ace9a5208563c74466300d47930408e7d7889842abbcb3f54080aa8759a6bc3dc97d26d75a2d52b9aca55b394ef36fbb50711ee4b3748a8e5de62ff8ac5b0fad2a2375df4d74ccae2c5c970923a38e8e98812b6b76c28108fe60fea30676fb538a19ceadfa3af7f4f461ab9bb4d400792ce52ca77754263e2506d0c598d688e18a8a39f9447525dc915dbc9d0925f1c0a43e93a692e73c56b6a5c9d821f2a60354660ab645b6ba29abe9ef5962cc9ee4bdeee9304297134de75b51cdffea1a919928357cd0d820589da05b992d28c237bc4503f7321798ac2a9b8e9a120d84f870ab3a4185558f97d02ae6b5eeeb6306ea822071d7669e21ee75f3dc42b64e85afe4b3aed303b96b9b541d3ae2e80d2d0370c1997822a4de8ddd976ef56ec024215a9d1b02999bea8c031394688324247390ccea58cd53907dcba6cbf1f736f451831c424261b35e76e039dc18948f40c5d7ad7fe94022f0715fd9d1986ff2e113b3e015572aebe6475a6161e830f9e98267901ff3b17a8d647546f8768db1699c176d1ddce8f120b887d07f390b73748b9cbcb3e8f9c17e3e294de554f69bcf962f7b33d2a02e7f43d5b75fe9230646a60f58cebc3288", "b5e74580aacd5f3", "44", .None}, + {.Log, "32718d988c6e7b16354a7da0929eb24077664f9ec2e58d995aff2c6a2155487cd5e3d908f9cc0abd750487ebddb680350582ff10228d861d6fb6a1915446ed4d6c6ef4f20830c2287f189976454f665153b57726ef8b91bcf139f093cd0f67d6cbb7a0e315294bd595f35ebbe915e28650ac9b1744fadb076168a2b9278eed6c76eee77e20dfe687a6157d6d6f75d16567f740fb57a90db1e1aefba5ba59b457335399c1ff681e3672dd5f62153d7122c5edb55d6409c7a69c34a41fef3f95df84c8c6d3eb092fae2b75c054d41370ba78abe145b117d87691da7bdbf5f3410671b4dce208cfb8f2e7a65b976f44f4a044fdac6fe1f70ab159f56b9d24970ca25bc0df1aa0e2e2a3145ea4a2fac6748a8c75b7ebaf845efb6481d67cf111df0f776ac0e31b22e9cc2e2d809cdc888dae55025bf0f8e4c432b61c9a26ce24db1269522ab1552a8e79f3d8d62c6c6e5bde29218547b1b9f062c737fda6def457b93f2aa9e583433cb8d1bedc3535ec6744734a1996c7c0f93d809463980c49cc9daa6e6aec1917d572fa24ca085b0f6fd6fbc1a0c118179f1c3a7a77633909dd5872b17268de5dea4b4af5a854d5620fd89122e5683bfb6b8dc2628b61850485294a5c44aeba8d8455b259938d09bd965d0192010fb2545e0e14072205174c4a2546c0805cb0a2ecff2c03f18e39e06fa29cb4b6927d8a1a2fe086650fa3f9d8d1", "f2ec169d66582ac", "44", .None}, + {.Log, "a8ca8e6b21d0c23a758c059ecbca8f39f81c2eda46fdfd602d75d0173c74d50271c87008a7a5c30d92e83d987472666b6fbc55db24dffb287b2949066bba1008a75e6f91ea9bf16c92b7243163f56358d8c2d099f969e4fc4278c08a6552e58f6d2bfca5b4c4072f8d71ff8fe6034a0be6a7057d88dd5150a394c2d8080488bde441f1a6a0c7aeec2dc12a62b9231f8a927942787644ef9fc4e1c04c75992e2e98218e5dfed2793d15573fdd039510bfd90e539bc5dfdc1cb60aff3c9f38dd0c1621c7be31058754fbbf974f45ebd9295d88d3949dfc051adf700fe43630c3cf1af0cbfd328a2a7158c0e353e5bb49c184e8c5530df32727465b9a85046a79379598ee96b7321e4ff74b64a51ca5c7857f19ae6e6b33cc6e06987d0a0aff04563cb50f078abc4a1b44d0f4a170856e310829b66879cb650ff0dd2a353b4d5c709ed6385667474d49feee9b3602f8a502493c26870b0acf9e645376c4f1eb6b4f3f83b5f7676779ee3f86feb21c246797446b0bfbc5c43c5b15935602c240b221a47eac843c1d80e0e12417c53f116d4593f89d5f63ad172fd70e97e3e26d4dcfbbae22907488e0a9c3daf057bdf57735e0d52d018d14065e43370a0d3acb9bbeb8256949ccc40d1b5d999d87e8f3710566d95f0bb1b69353360c5b513aa6d2518104b14bf63366036a958c54363d7e02f9e1fb6ddbfac82a5cc7bd6c9c931ddd", "e86477349427027", "44", .None}, + {.Log, "8e55957fea4289f85b57f3e6381af26a5c0e05611715cc8fe8a0a39deefc78e0bd1def3112a5337b2fe4ee0405d90a7c1e784b5c07afb80d574e54bd6b075a6fcd263c1bee2ef9fdde3e18219d2033bca18698bda3b4144550eb0ba053cbc178abb01902df19fe29e5f873d2bd5eed9fa4b4ba0eba9be9dfe9f524fbcd190390ea35ff7a4767508c78d1a18607d14e13e827d8009f87dad2dab52e0efedf9012ccfca714c2cd7c6e3941bd36b317338dc3de26f78b8c63dcb2c5cc0a03a62928c4eea2123d832098f492b09f9ae6cdc1c4b563feef6222985eb5f5f938a662e3c2450ffa0c69059eed767bd90c3b4a121c90d2dad42e2c99184e401993237b20ca43948023519b365e21a46be9be634f98f9ed29b83da837e09de8daa0c076291060ca6d066de902a18aaf681d666389ac62725ce06970d914e00313a17fed2b1a023e367b73ae5218e2cff12d388844a6c8431c5cd44c639e0633745d37e7e07113c7e9919213abfebb154101154c63f2920efdbf5679f824ab52b33ed6d1ec13c655bb54c842f6a56101c8e85027b6e31c735ba16db695d6fcc4a4c0e8135719a2ba93aea1cef5acab4d9bfad01c9e95869940be9402450acc4eecca70f7d55e9c8f0652ec59edf70ab8c7e0025b002e1c76e737bbf09de6f36ae07668d9be734efc7781370dc53905523fb75a42646063bd55b562ac6de95c8db6bda93ddb", "6afbdb1bb91ea1a", "45", .None}, + {.Log, "5fcf9ed838a120f03bd9fd778130cbf97474c8b5e7e3638da564b2b72618dfe923884be033430ecb6e609b1441d26e47ede0a6892fdeb9bf20cc0878be9180993c948fa75e2f7edc99f50e4294eb3e12663e1c8a5d8cc7ff5877021ff432b41448496731f2319acc961abdf2f1d88953e6e128f2fc8bcb1542bf19bdcc253ba1d0754eab58b30b9e5c409109d3cf49427946ceb3a9e7ee5fbad967417d899e7e5ebd4449a220c0afc845c298298636c05afcec38d86dab7995bac20e553e4bbb49914f94bfecd344cedb70758d9597ccd6d05af428737a95281a3842a9dc7110d2c1aabd471d02a20808e565526200248bc6a80a79a657a74f1a73fd6b5980b6f273074917fb3aba49ff0399e1b7783712983a280876621e55323d26c16b6821b3a06af008cc1f12f832f15b4c06e0fec9d2683e62aeb80f4410283b05796db86426f743f23bacf5b2a46a119bb588e037d6c77d7b02c955d4c2b35511374d30c63ed2cd9cc7a774880673649ce573f6b47c764a66b722f37a18184b6e1cf3e8405c24e1614235e6906dbc507cda3c2d663b832203de7d39d188d3985cb6c2f4b4b5df3bf77fee7b4ab8f41a6456ebe37ff1323388a4fcb483eedf7cb2a0f8066be643050138f6ce2b83fab2ea289731ceb28087b32ffc0c54a8d9188d7b68da41e222d85527f771c3d9fce959e2d303443b8baffb80f0acf9929e2931509147", "d49b2be386edf2a", "44", .None}, + {.Log, "78a344e24bb422063e39427c7e87a6a51dbae5fc43002feb24d901e61320bebf5168aac415e1a8ba3c151846717967d97c76f936f76b81f122c5fd4afef36593c79f362b85668b6bade5f176ea9a1eab53c130b30fe3413acd5adfa6d6fd854a704a7c398cf8a90c995fc3ee5e0319429fc34772703444087fb203ab849da78bee7861be9dc27cad1694beacda922dd777979e24e98480fab89c2cf45ffb75f999f16a08df31885dc6389717251f7f985d8a71912020c412cd09adddc80601813e14acef589ed754bdc9e9b1fd96b0cbf93eb52fe049d3045e5ef0d08b984c0aa7f3f4f4bf047013c9729cc3886744b77b664463fbe9ffd1adc1c59c10aa044c339b1273ae238df174beae6516edae6a1a7bfe06cede24dbccb962967df902c8a752087bdcc8018b9ff628f92b93da50a1c3786ee2a0aa76d39eb1d2c081b710d20cedafc4673ec0ac5a9ff6fd263da8a90e0a3df50800429003c1803f14aca4c3445ee065d7200a139adc7c81ccd082d1d7f38e8664f8d4e147dcaf62064ddcf997d41924c2993f3920f3e16cf568c451f3dc1915c919f791182eb43b51edfbac53f0daed875d3df5b73ea0bd238cc38d1c48c9000d742d216aab51624829a66bc0db9b5c69ed9dd3431f20986b0dd170571f04864a4837ce23e06d5f19b1230995bf9a17a9c58f55ff1f6f3c3296dc016078bdfd87390ec1e1f3c5f139178a", "39a00f27cc5c2ed", "46", .None}, + {.Log, "a14c8d5f5291e7bb3fa95665d19b16c2942a365bb475610459cf7d55e1c5172ba1cc0d5c8c37a98666be230f2f097cc7e7f50b71fa82326f904848db134b96c1fcce4790870e6ac7cceabb1ad7e4ecba5626e08260571e1d107789c3d139fb99092ffeedac21705267f469a6eb428b0fa0fbe923112563774d3e9d93a90653e8fc0bf6675ed4a87d24aa6ad4b0f3306cb4b7974dd21ffecde6fff4d892371f88cc2ac241a51c3cee16b8abcf0eada1419ff6e6cfaf73b8a98428ed52fa0f2b4673faa78fa6add41ea861823738356933689f8a793abcca5a88679b095dc5734581ebd457c429def693c1a14b94fd0aef7229b3dabb00ca3da7cd971cbc062a08981451a79e731f9ab1c61b18eb7a0aa3d12b99c7147015c6ecd79547b416a3bd4983311de23ebf5ff965ede93310db1cd177f0cdedf2c8facd0dbf0c908e7d36cdebb0beb009ddeb88d3aed9888fc4ef51c980f9f7a176430e0f9a20fee4eb4bf0029c3364d0084f985e61589ca4b1a981c195d03c4bf522328359da5bd9d72c834d574842f7398f409286e977eb9cd70651b5535c2c2c91a762d9a34ac663e590353c6811eec6a781c2f2b39ac68841ba601572d3d1b4a1ce7cf4cecf350775951eb102e4bc05338e1d80deb360cdf88cddc781160a91aa7f7312dd223f6777dcacf53ad695655d083c190c1eada6520c3883da734f2572048b504e2751db2d", "98ce1e2300ee410", "45", .None}, + {.Log, "c97489a11dfb0aa926d7eb21960de81253a3216c3967931a970f723b7bb90649ccf46084cc8aaaf7ebe4ab2062f2c39d1b127efb21a80f972dc67a69d69dadb10d596113b6a67b2fcf7a5bdf4bdd6dde7289d7e37d2aa3a36e9a52cfea9fa725aa22816fc8bdb6a06f1b069b72fbfe5ad6c486baba23336d33628135e9b3b2d1fb695486df58155dde50b1688c599ad957d64bfa8bed942132a9222fe928b32d66078a570b295b0fb329c538d5c4f3469228782b6f6ca8c123eadeca533fd5d005f6e0615c31fa7616b45d9d24a9f292eba24bd2f6c78c046a61d07f9d21996975b88758df5dedc2b9165d2892e39d1b8929ad19a95b66c10c7f2a5f91af7f077e880ee88b8befde3c1f7595b9de5d9c1c3e71bf341e2b8cc64eac09e2c145a19a2803550bfaa980e71734b67b718be4c774ac9e8dc2fbccc5e939d73f0a58bc9ec283fdae113019620c59687e9259467f07b7b3326133257da50b4d38d375575d8c12d24b7fcb74683aabc791cbb7e56f651e03162d018f84de6965ef4c7824a44114655e07c63b41fe847f5d8d425ff8ca6e12b084c4e6859423f38124308ce6694db748890fa4de7e983833b6150bafa6ac11f9c529bcc628ba182e8c8b53f3f4f114440dd01cf745f5ef96db4b97bf64887e52bbc239aa6ba2e3bd299ba0225dcdb779be7a0e599e174c364fa5a5bbe90f82504d356080e7890a5a9ab290", "dac4086e1e9eb8c", "44", .None}, + {.Log, "38f864d447427a3a194c892e151a6bf89d30a1f3d8038ee61b0efc16c891dd34c9cf0106abbe01c12c9d3f2fe917df97f92907550a6d93059cb6d03081415a21ac5a67ae6a1836e8994c37bdf18c97601a42a1ddf1aa1c38f747593c35f57789680119fdb94fe028dec9a3b46aafcc79826cddb4805e67780b8305d7af07ff9ceb8d6b9891bec99f2e4b88cf4e3adc3525772aa10fc0a86ff7cd9bbc57e94885a09d19d98f8a4560ec24aac827d3f609481f00dddb1b9d2be5d6d5c339d7d5648f86798267e0cb7d3f3e438157bb302b219d0de844f8b08a9a1cf48f717ff62f48526577e71d7dc74c2041d81c2dcb6de4809c5046b25d3e54ba07f42adb52c1388d9d22032c7ca8021cdbb4b34ea0319e57e2e4d1db7a0f5f24eba0b06b519aaf278df3507a016ebb2ba87b96f0ba1e063e1d577d4e02f5d211942596ff91f9025f49d8f1b56c4d221d66f474849606b08dff0ef68e28b2c647b8b5b0bb227226a103ab7cb7eb94324a3c51164a479437d1cb0a7cd23a41b35e564885d096b68eb57cd29a9bd8586ca4b5ac6933b9fafce12029ea67e33bae07e390694b337a8e344442139dc39c13a6f66429ec661f8b5fab6b05b595daf376a0f5cfa4420640543fe5b09300c884f6dbe18a492b40d5d0d6187321053ac3374970f43e7a9e9cc8c9dec9c88d2daa690b22fd9e9a8904cffaf0d42f594d889042d782c2cb0a", "3b6af2bccc7850e", "46", .None}, + {.Log, "8ea0ae774e940d0e568fc9f4ba987d9e2c2dc1d7d27eac2ca7f3fb8f5413803f0d21ed3daf08367966b285539c7b998cadbe781bf315f051cd65b8a74332ac85346ce6172be44562bb951c56ab6b1d62dff22fe965a67a48aacdd683d80c76c22a7f04243f8906dc57c0b1642d6ad454adc339261d07f0da07d8df80aa0a3ddf581e3353ff0116ce4eaea3b31cb054763bace0463957faa072038f136f9ad2f90a4465e656e82596648caf65ed619a16c96dd017429178738b3890ef5ecc2bb4e9b6f1a5c487c6edeab2613cde4a2a72669711ec6f18bab32ea9a5bc04a69595a34f35cc82bd8ba467df955a3b362534121b775f114ab1c1fa1cc976045ba84fd74ff8648c794fd2abdc12dd7a76ece8f98ebc103380a0c866d43dc3c4021207e47c89ef1b78c538db9e050b51445334848cd50f5979ab79f820a3c733dced3d456478a1283e9e4574883171ae430418a1a11664acd2950f28e8f50194e71f0f40efe73481e4cb1a61d63f00c2fbc1d825ab3391529c4d3bb276ab7df19229389d9c2e3866887ecfffa6db70aa2740f75560f3f7e74478b051bfd9601159722c09bb2573e8f1f400bc4ef6eb14ad475e755883e66d53827220b829f39e668232a462b84ce13c6ba9b357376faab71008c0950e20b2c8a067652bda069323a6d12aa96cd11bd47bc6119a269ace81c238847f1b4a7e5120e7aef01c8deab80c5e", "367e04468644769", "46", .None}, + {.Log, "9663d72975ef5da23a678eea8b863f93ef46494690cb07f1742678eb0f87400afc759a7405cff332b5eb124e95631fcd959e7a966c694a4a9992a4408628d484a6572858505339f04914dbdfc34be673405506fdaf769cd2befec2a7c7c59a4fa10840801d3cec08f45aef7eaea772b5a5efeca0e59290d6662c11a0d18570882c0a0173396aa4dc3e0859a39ce7c311fda45586786b8a0fb44d6ae73cde371fe5aaa2668d5631da93ced8dc26028e2acc26883665c5604ae9992e71cc8698d2da3597f8032e65fff0d1c7df2e37e184609b3eb49322cfc1250b5d63fea35a1b73e91c655b6a4b860b0eb98cb96520b44ca79fccab17f6bf2701c81cf7cd775ab924e4e75fbf40aa3bc567871a3ede008274180bdcc26d5a74ed1dfdf0a8a010fc38a3693791942e8d6333d1db622a2ebb19ec732a330563fea4266c9501287326abade493c062f854f1166c628bc739c407573e4b5be27299d0e3c0f982bc47acc0436ef09b455f1b66b9eaaa29405352815588bcaf45207301a408c8bd1c7e4c7cec7a2ba55f324aca17bc4a947c856dfe566227d72b4631d70b09082ecd37c97ac61c069dc1426c46338f34ddee821554778f282757db0ae2d9a02cfefc6c2b8c942c0244c9ce6f83905a9dcd0a7bb2ea1e7c0453a0da1366e5c9f5dc80d0592b6d60702c3da7a2bbc34f574bbd5a2facee59c6b08e294160b68cd073a1a6", "cd2477fff399df", "49", .None}, + {.Log, "de72185c8d37f94387981fd07c6ec3c09d32214d458e4cfbef691c6acb8da78659d4c870c8661e686560996ba094638ea1a8f5c10b26259e0cb7ff081a86cd51585585436533535524fc176e254fcedada12407017ec6c53cdc5e302847f51db442b6450d60686d1db4e7b5f9113bfc76178424082295eeeddbc8489518d0d8378a8add90c56fd33f546868a0aee5bbc787d7ebd30afba227e96828f05c51689ad9c21fcd565e6c64575f2de28370011908dee94207689bc24ad326068fc27293d4a4dcefcf8d9389b411aaa7795705a2b31de0781ee6c83bf6feeb27b3810ebb0338c421d1c94e6a25857bf89d2bbc4988669ae76aed66ad2f2374a6ef7f6227a74d66169ada5646431fa896f438306a20f65b4e778658acf659d8264586162c515defe85035666f7e2aa2380977612fb3022a7399f98ee0cbde7c32f674030563ea94e7f83376f6db596459a1b7b6139f77973a1bc66f244aae3f581e5be158f9f7a7655c647cc96c566b78857a3a7b397f1c2bcc756f3abc36271a4f4e76d23df28831f24030ee2c2e2209850451525017aed2548f5c485e44f65f5075604cd95690c447f754638d5ee6f5c33848c5168454424026859bf36157308b97390ea221b666a82d1d5660b7ce3f753d3858ca3a7b1ebc90dab845dbb9c4b0ec8e34a4818378e4ff99ebc653fcd71bffc98f6b3a565b4c84920b4fef60b04c88a9a", "e0df80933f94187", "44", .None}, + {.Log, "95ca55f2afadcc17f48e9308fac43293c2d7f8c0f1d6678349f3c6542a510669b3338c124a7bf205679ea98b1293ee90df23b2dac665a12554bc1b2fbdf1b1aafa02cdb454b3f9c511739b75b909546adabdd4855ee38bc6829360d9dc52cd1661017343538c170a52883ffa348ff3189d0060a37e52ab51a352c3423498e890e7c36bed3f6c1ce7ba71f828f2967a17381fb762060494e7ccf92ddf88beba7fcbcea47dfc63b13c2818e6c1e50d2238de334945253fd104f6e9409287e2465f9a7ffa6d36d22c4bbd51c66434e9f1907560a13c828e1390227d2d211beb121b5df13eceb3c4b39490a3f6066c6743123218fbd97d17b8bc079a88959717aa1c0a2fe9a3f75a6a41b37310a7babd9e5a6c85aa5aa9b4ba2f1b75de594fdcb1366e829f49355101f9f1511596b5be970100b59c147c6926dae80f32b5b41a2aa355b70f0337878c43f9f5b7a2f789452a1324035edab073b2af98aad92ee911399088ed0fd0dea3d07d8f536ac58209ffd26e60dbabfb2e6a82ccebbede0150d1ceddea6ad7e04aabf968af9cd34864aee7722ed4aa5c5dbbdbe0a2d68a5ab080e628be737b3550ae96e6daeb3d9682faea0590e3dfc5be955623023c20e5a99f09d0416c3ee6450dc386ed559857f60f376862c43cf24dcd4a39679a1de1896b64053371f2de07defde84a39a783653871ea81f19863e9a5def6a94aadd74d69", "909fc3ef56ad688", "45", .None}, + {.Log, "bfe832b93987d1cf7fd66f1be68abbbabd6092541fcb5a26d12a0ecf6167c2f1d69ddba7dfd8a0715aa7d6cee1582ae2b7669d594676f1519f2e5e62288701556639f4605de6b2f50e67c701cbb910a91b508c4200abd9b972bd59e354e249569a43c530e29059821dcb3c3a37ec67a12eff1aeeb24398fc5d687a302baf1b13292e077b81195656f540e1e2adee75be2534dd713b88627abb7204d63160d64963f5c535e074a8eb1c133300a381fb7383bb98f84c9d86e80a55f7f54f7010f6c7208db36f5d6ad3d46ce28fbfb23e860bf6749bb8266d43aa523dee49c54b1cd8ad73a1e2ed155773d31f0757198b3670ad39856ced452e6cd62ed7e9ee54f2132718fa7ca1ed9c711c4a0200ddf9c2a725ebcf74e6a920b4b48efadf5f58c6e41dc0011e9995ed9a700a1c0a8d01e677d31bb003da001be9df2582902502fe61e21c4f2d3cc6a3bddbc47d8dd9bf2f67ae8b3651d2ea07167bdcdb7c13ba087aa65451550bdbb1557e09ea215aad6f2bc0ad07ff0f61567cb03bfa2af369b926afcdb933f1c55c44fc102c83582f1d49561569f8a026a2cd0fe8a7c808094f729598ade112ce63d5b5f0b696792cf4a7e0d4518a69754711809e6aedfe338e9c8793d1068942fb8dd83ebe892f763e6f5e60a420a77023a7ba4b9913c7a5a565ce3c175690d415510bda9951927bab7d767fb9c2e6039cd2076d354587717", "91240f8c6241cd0", "45", .None}, + {.Log, "6e97b82aeccfb1fb687c9a2a2fc60fa8d3183b3e192c05e181ac5e6d1434a001bfd90a44be60f0459c98e0a461dec94cf15e12751977dee241f9e50310652da27c1ca01e67e7b8a15affaadc29b3a46301f73cddfe195a595608ae46460e767fc24e399d5f94aa61ba9f09a019108b6165db81562a4b08d95bcc72befedca45d559f02f52d90c4a2f55dcd3ff90180d0e618e12ed222e62a478e97bd98a600a00c775634efef52f0e1fdf96ebc093eaf96e9f8671b16fcc35e5c8aa0fde7223c8b8faaada13fd61fb64cf39c27478280d861f3b9c24d7bf1e36863a76f9a34e3237cba0df800b3c1bbba376206832e4522dc3e65148b8cb486413c7cae8c80c79c3a7f4771c11c9acfc5f5b612e0f971c2214ec892a397ab69ab6569f51d35dfc18bab89deb00a1d8ebbc5976a9d5f2b8570fd421f306e1d398fac1c70bbd964442dd6527ba2ad34e110ea732b300f75f016ade6c7cafe4a0fabaa5c74a30861792c5c08f0501cc0b69dcd9f47f3ec939fcf903db05812c27af89bd9f8fc3b6b39004a7d35fdcaa2f69279721815a59e4096c9b3a75b4d0d7996e37f6ca662227d3a09aa016391c42aa9cbc352a16737393b6b80cfaa8745a65fff967ed027d205f76fcd8c50047abba0ff8afe38377a6c2fe48f1049596a0065c8a6c3a969ac4d05ebe0a4c360ed86c1a56050c65cc2b5373d9c1efd4860c43d2f073f481f74", "b88e4e3ecfff173", "44", .None}, + {.Log, "f41ce3efe7c13b0f3a61d18414dd3cb1078cf39de8c7e784f4610acc12ce3c7dabbce7064c9c4ce78e993f7cc71f8705dd28c4eb4a46271674a71458f694bd670409c64a95e642190068bd135064648fdbd1a78320e894c09c455e68f441dd72f985ba6a6d570ea50e64c6f2c339d07d21d3619edd5ee455cfed90fcf3cf296e897f66b138268a37625f0cf95e7d46af17840970b7b052ef28b6d874192cc4a855f05f1130542803537449641db8981301a66c9860f0781c5a295abe37f075746c93ecefbbe0d3b66290a4dc0e936bf13573b1cf49040239776a6244b4a705214be335c1b5d9f581a2f5477e43beb1f97638b0cb8998a327241dc3ed7057088b7055f4253b6093b53c85b7db268c6a4669feaaf8b21d5a274b69c18242310e0a9a8c37234a4cb3d459e108651339f8fffc43683abb7a77e7b108803b469e680b69fb021575e8273f0b75ec192d5cf28bbbf7236751693ccb525a362649a2767c901168b6f9467b1e6408ca2184fe6434f6323df4d9712badafd562b1427ba86eaaa17036777ad96f6084c9a70a6a10ecd71113eed7ea8d3dcc68c2c644af2a91d10a5f89db8f36c2fcb5b2e94583eac9e199bb9af80da00ae3131ff3ad6b445ab054776df515b92fcc29accea552c37e88c41c7a2973a5e79a839bec21472eb7b2ac305218a47e2c794dcdd18f2a62aa2d7fb366bf42390fe1f9861bfe9475cf", "d3f82c8db09f1f3", "44", .None}, + {.Log, "43b7aa8148a20fbbd8e6103c52530cd7775fbff855a467a986042e655d939ca8fa93af22a0b0e83a1b039c19dec665f61b388c197747c6b600c2f749851eb9b19c72667b8f31059c1cfe8d01f4fc8a37dd6fc6a7402f379b90faf4254cea5395b81a64575c10498d0913792fae61de4c7dc84d85b08342177ea3c4ff2ed00b03693b86468a2b7b9056ed50e7b8fd433c2a4f7ddf3e0ad93b9bca44b15d7f18bff1fc688f9e135e8d6053f0bf169ea892c07cdb580392e8ba3758cc29d7cb7f65912e108fb5846e740646bd778b37d8112f4923d8b6b084ba9c701f67e6cb47d4103672787c56e5117d556c07a1151a597c6312e1c681d86c0ddddf485c1b8dffd0fda7070b8bb4430558b24a37297e530bc6fc4500b03385793f75302eef2f2bfde04b3bd079cb80eaac7a064d8d0d54e2e04efef1a48e8e52fbea9d3dbe5a272a3308b25914b924a0dc278e40743ed52abb110fa20690dd1f34413c6ef3734d9195ee8421615a7af401baa3212536ecd0aa0a14ff5e7b25b2b4835ae542a4136ff59102084e0edf40a5ae2df97f6aeeea04882e06212a99636478fc42ce350aba67cb535be0fd3926a1048aec6ae469dba14e77e623c79e389858f1c8e5937cd4e40f4ff2119212920519074d87711f674fb5aa68a030b1a9879ae4cf35050919adae456184302b252317c339ba529ca09b04da3b60e721e1256b9a32920a95", "2f9a55732e10a1f", "47", .None}, + {.Log, "7ce8ae9690f6861ddbfee6be8e78d6a53f91896798eb5a331e08223fe29cdb8c69dbb8dd3742f0fb3b93ca299c895691e72d8c0e901cf923d604e151c3c3b0910cfa6368bd3b36d50bc6763443c14f8cb22fe23f0399a579e4dd913ef11d1c293055f80bb8d1a1fd3f68e527efd9a4e138f217f1356cc811fdec5988578dd3a84a3a0480ebbc0ad97a3fa8735414d5bc0cc79f3b0d717969e940ebcd8323616ceede704517e559888247b758f079f061f6755d9cf405c12728eef6354c3a71de4bbfc394f64a70dba4fc566c950926f4a655c2c6c921174419ce4d5a91145d8ae4e3ca4781c89ecbc39a7a5e141586337441bc9448efc50f32ccf479d789fee3e8e47740257d2cc1a88fc5f4e1c14b372ba2d2822f864f44819fbd21229c55546c39145d6d6f43ac835e6390b3ba47992583fb1f0eaa38a47a320464a348a33c32655cfb08645d748262e0ed02b7c50dbba34eaa1a4726eba60e8a26061565f84cb9afe894bc00ba13df68fb8608e30b7b7b1d590e9608cb59c821d59ea6cf1ce991aca1490cecf77b6366f60ec08eb21929f7c3b56dd39a6be037ab6e18b61ce91e1ff54fb27c774a8d4a1e15e5315b94ec68c1fd24621ee3935802df71efe907e9dcc83ffb2c465757fe76fd8724fc23761785c1f395e2e2b1cfbb02315e202f81e3f3ae29f12131cc339ea4f6235db84c27d0eddb6203c109b88a9eda918d", "813b45ed2f58d21", "45", .None}, + {.Log, "a9d3fddb793c0058914dc29ddc047d156e35090f026eca5b0c8a538a8080f285e082077dc134cd44bd6cb769b0e7cad8219ed95e6017d35d333fcf346aa1eeb5cf3002d7587a0581580efd330fb3ed7619a966a38d238d6108ca15880d17f00429a17729ae581b35f5175469093e94cc21d7814e20947e5f3d9ae5a4a994cfca04d9915bd4cb4668b9b74d72721fa873fb31762e6728262bc2442cbc4c67834646a643ea306b393ed1430c777bb0247afd2c29507fbcaa87d07a9a24bf8f9c8abdee58ea5758d1595274458874ab8ede31b3763d6b7586c4daa5d064d973b50748053469044f77937867f2aa183eb0bcb2db850110a6e6533ce83c11d3332b4982f6380344602f31f37989eafcbfed58d97580fa2644d3afa9d3eaed0b834a396ab904f9424b321031d68768ba774785a24d3355b432f2acd9f8470c5df293f66468158627e349f0d64ae3dc913299eff5df08fe174614a628fabcea9fd45f3127932f74b9b42cb1213ea74012e5248ac890084ad3871fbf049b47d6ea834378b1500a2ee3a32dbdc618f733b8d7d00f9190abbb55208ec800d5f36700d15a9a5adda7592deef68bd638d1545fd8c6154db4377ae2712f5151b3c8e1d548df5adde5d8ae39e749c40ae97d13b1fbb5c28dc30c345737d98d7359a35cec32fd50c96a7a650541c2bf9dc40c213b9f81e01123f5bad1ccb9828347509d7b73ecdc", "1c4c8228b62460c", "48", .None}, + {.Log, "5a26129151fe74b8998dbc886b0f4cbb4ab72c3464a47f9124af93049802617e404f753d811f2d5f290440b2be038f347beca2f5aaf626422b30366f814b6349210be9a58439b55d432d9e1480357a66e270f210ded750dfc3a45fae866b32946985ab88f4c9177a491ba0388af0dbdf37d59c9816de2074ec2c63890043c492b7569792641be2ec1c03d46a19ad47358966920f290ecb7dcff218742a1b97c67f74faf415180b5b52cf29dd2f4113e88b9495c98a065f861eb965da620c3c7d08b2829f035b2a0023469fcca2731d640ee1419ebd1829acfb68efaa57115827f8e402993734ab42e76333a4dc9928db622913c22e917ae0ca0f876019cf2315312d7ddd71a25ca700212fe2303adef21c47cfb19563acdb91e58905351ebc1baf3e02249e3bf5a4df8486230c6a48d8ee3bd59031c2193cf32acbb08289e815a6e33297ade85685fb104cb3adc24c4fca30965a5ece2bc39bbdde9d0f078732a3f37b17bfab166c24fda6a6aa719761b1a6d1b22c3631119cb3ac58127ba7e91c3785cf13d167f7d4a8264f53cd0c85ecf2e9b699241825ea94fcd67175fa9991aefb2200e301a1098bdc7f909c70be9690f8015ee35f0e944fb66d9eee17519854c05f43610b71692d848181dc82ac77ef3e99650c50fa8fca3fee626e136c6995e954ff164e0564fc04114cb5efdf06887a3f1f0562954c9859aac6296aeb", "c07bb11ecd3e492", "44", .None}, + {.Log, "4d21f4aae5d2a3aee422ba6b7192d8f0889a94f5964824f625a90a980c5adb950eb1cdcc95a766cc642836613c8d4b7e062c38d8a1519c47c05bb75faff15832d780cc5522ef422bc6252114f6c3aa7ef6d9848b1ce25978aa837062894c6f71b6b2aa9a0a5ec0a937500bdc02e14a59c9f3e54439e5081aeb6287294ab611da11da636912333f06845bd199aa523b77d05748f743fca39a4c98b04965db5fa59c1d346d8f3a0ab59cedc11481f83d1319671ae8439fc93c76e24cd036ed770e481b993672191cd424ffedc8ae9b0c26dd57c76d70a18c6d45a723c2f844d685ddc3a3f462e9b0b0279adcd5841e738788facd7343589e4582cdabd6fb7bbb6e8ef37c4570b57bac72d476523fcd7a48c2dc606214c3dd2fa1a03f9db46755ff629a2f8fa3f881915a9ba4e464e673e5a0da94ad4e74ea4213b5384875b4b1946bad1c3d22d9fcb1e099580b95b7ba8d4e4a751a927e5840d5e4730faadd55025e6635c7f42be42aef2477e9ce9992793136c11e232f31d76178edbf4ce9e1293c17828af2374b713028ef1d82a475862860f60be41ac1b2f63341946b6cc994f4017b0cf0c7fea8c7fd9e3b323675f29d41c5bf98fdf0f5ac338d5191d5096c717c07d2684e4da559d5660d2b5c30bb91d1f4a602111ac19efecab8812933c6d7537a29d5f69c661db591d46719bfea764d491765c31a950b4e10eb88f5890d", "c11bdcadebfdbb4", "44", .None}, + {.Log, "64322ead43dd563fc50cb95c4925c2fdece7c16587da9d4b4fb45b7e78c14b20d63446bdd05861bd7563bff6d1304891e5c2e3436d6120ebf5cdeb0662cdc997b39ad9365d15c699d8867ef2641a93eed0d932fad9d6df236c0d75096bb2a0e9152af86c0b73d0d830a0ab57c54fd2bc34acaf791918230db7f9859ae10dfc116a937ce7dc5b53d542dc7287c4055f36c14f53bb999ea5850d3dbc8a8375c37d0e52e842034541db1ec34af979752e7cf99c65c9530386b2924311bdf7d8c8f6241ddeba3532767ecdbb48f6a332031004636e3c08dfb80ebd9797be45988f96bef0f4aa079ddd3e5d8524492f5944de7dc32ff55faef3cc33f20562521765315e77c70968a777899969bc4f830d251d23ad26351479cb00c0b1019d191b5d7061f184a7927b9356db36625d7c78253158f87081553f35a1cd869125125ae71b2a0a67d77f4843110075f5d91338b7a2687437dc980eb4d005135fa2b4df31754e8e91ddd820e8c3fc15fbd9816b7ec302d2f7517129346970f4516a27598b88bd25e75164218935495ef6ad35e8c84c1f1d567bbdecb1076391ef12be220fd4bf9fbfa039dadc99244f3480fe7d4bea97cad36e5308e8c94321adb30a981a1b9fde6a87265d6225a76b894d51dda9051a3f5e670243309acc3fb417835752d78379dc66bebb98ae7ac336c5eba0e93ec7ca266fee3011e610d01dcf234741ea", "5769d301e9e8d82", "46", .None}, + {.Log, "d2a73f2c299ccef90c7309800e6321184bb36b18b586a1102ab85125a2a9b00970ddf384c5a95a6ebc9ae46a34b73787aa026d05cd8217f051702f54d96fadc5b5bee078a36434f236b02e01e22dbc123b2436c8a789a4e341b5ff8a40af2d70419381437452c987d811b5660d9f3b8b107ce5fd6c81e29e73109b57f1cf2e7006ea6163ab98804d79dc6462ccaabbf163540a3dedf08c234ef59c8b1101d615bafee13efab760c96646f695e902146c2371228be581a4fc5e5e6eba5f2b337e03b1057af904c2e161fe58c404ec5ff97f9fe998f23937bc66b50f843766135435f141b0f33a66f2cf02f10cff66b8a8b8d02524f28f75f8c6dcdfc896269c8ad66e9f3b24bdea684dbba0545aea16a5db72e1154b3a6bda3e806df8f6a644ff97523c4ec71dc0a8d967d32d63881f482e0ff3c3dd43debb2135304128c02d300983776665bc3e1d93437fb5e2df7fdc0bdd8d3751cbe4f9d80b7b30a55056ddbbf5e130c130809bc8c8dc1638f742649ec2b7169e9a0778c7ad93f2089b9dc51f0d97e6c99182a9938e33bd839ef0170332957c3841ea83953365f4bf6c302ba871175988e4e153f10f1bbdc8b15d2f8d909b206b0a0fe02fbd8fabfd9d8d690247653290e4713ee245bc19e097de765279f5992c8378ffac439ee1dcf6b4a8a409beeceb5b19bc229a8462ff347807b0a21780dc8efc72d10349e4a6616316", "c4060711e8af26d", "44", .None}, + {.Log, "6d832e9ba9fa9bdce55d9476864f53559c5cf2d289f3bbad128f866ebddc94e95fe2f4388840e0d1b735887c6f8893b9ed6a5b5fa6669e22d8f1928ae3dfde568fdd03637e9f879af8d5be596c0015ae6b0182e1bf9625c5d0a4bade822710bea851ff727e0a552e086bb21d2da6df6c7544b97ad8e3c547ddb3f5be89de29cfc3488bb3c16ee38b4d3398fb485902941b80920314aa26f3eb5b15a05bbd30b90ff6d3e4f2cda9f6036b394c6e7aebfdb8989631ef35d50289defc06681fba503a81bc55ff657b86b1f3e75ab5f6e3187019302496c4e6e8fc4d33f43acc73dd133ef2f0f963ff4f4d2e7f12dbf77cbed0890d1850dc415d39351781467445565a8eb4ca6bee4b284f27b52517a29c8f67a04e1302758ba13d77538be2a6a22cbfcfffac5be384637bd2901301cc97f2ff39f83b192809c47db1b1eb7b6b1e35f4f0df064196f0ad025a9bf47da05dc24ba1cad288d7b7dd5c719cce002b6c79b8f50884e8c0abc4c5334c877fc0855c1996617de8dccd80043e3f235138c6090b1270d5ef13db9a5672f2f1af2c9a6fc43f7053c6263e18c425985f2d322e4513a5b1d9825e4af65f492f62221341ecd2f3e61e223151915fa906ca3bf5d10586f3a1f99dd30436d38874efb70bc9f4ec3d519e978e84debf1b3152a30dc85ccc0da7c85617a7c52726899164d76c131bfb2924816b5a88b2b187ccc14b8de3", "9967cef65c24b47", "45", .None}, + {.Log, "a906143ed776c3ac7823663cd78cc3f0062c4f2aa8b885a4837f51c4ab452038c47bf6214e50c94278ce5d9a9d23086744194d63769f4bd3b26581f67fefb9f56817d08bd40365c79465e2e1dffad917064e359ec1e11b25b1d1e3d7e4545a151aca4802bf5a2e7e00998b6938f36f0edeb8fedc02fb228ffd67ab5fee226904ae0201493e1eb3b4f5f782e5c9d34302eb16f4012ae81f240e4ac3f10ac40c73c1c8d88777be728e168262f292af432eb57131e033812a17953d56d046538ecc638b8bb587e7a3a4f8291a4ed8eb8c4a41b02c0a341331c7b185c756702eb14e7fe84a4710cfa5adb363c122f08fc59018aa684efb64bd64ab669e66bd3318838543ca3a87b9af0b4513ef70fe0976794358404aa71d493882f31b94baace6e15270e43d46b40a8a81141b658e45a263eac1afcb1def6924e1081607f946be7709e4208399d3c709625bfde363a841340dea5e81c423d21fb8b05d2f63a4346e36121ffdeae9bad3e5e47ca4718033bd8542457bcddb85b005d8b416f7d09d2d670e66f98545dbfac8fb4b726a020d9f39662897ed96efc36f9c456e1a8ced823610ea686ea16904aa028bcf3fc8c5441c90923134021df8959c01c3568e1785f91435db610b15dc0c158ad4cc5584cbe7e6fd22fc2fff01125f19bf40dc9d3dc4e474d45e57571856f9cf5f949eeb4cb03e6da5c9941c4000c154a3451fce09", "a22ced81e3c4002", "45", .None}, + {.Log, "e8fd6865ee84fd5c85c8130c86578245e4e17430cd96e3ef0b2cd9b1e92494e8ffea0eea50bda147bc09add767ca7219085605df0ebca3872fe8ee6c92cca8c4bb93034d77cd9338242f45231435d3a52dc12fb279f0a078fd3663b9860cfe604db4811bd1a9e0aca71695bf0b1c79c3207e3bd061488bc7743085d5c28636b183c82f7cc729eaa0d0412409f346ab0ec42ca8698638f22a4e1fe8928e3320c1868ea837d09367f3f71dc5bc891af3151780abf8dfdb286c5b7ef8853f9e1d71007208d2e1e31b464be8b2c6532d104a7553fd5824b9e46c34d4f04620c2ee4feb677e135f2f928a84dd79a8f0d9ca4d10a09cb29458c0bfb2d7543e2005e0a5ad429228717db7b1e1fb72839d1c6b7028d5e54ca1b65765e513c3da0dfbcd2a777ab34f4f0d8d1c1d9278ce80a1c9cea333d1f0342d814e03d1b81e94be916d2a6d51dc69b6a873762fee3e842f7711411f771d7ec28ac251734ee9f7d590d60c610bd2daabbac8c6cb1805c795e4cc4bf9ebcc2c1f14e88b11eb698d61e7543f4bf0f0557233784a0588236540167ad3354588278743a6e8b0794ed7b75a07299150635b24db615781f056bdc9697172282bced591dd76fe775388b68b1007599efbe60e59db666991b28d2dc7f6037ba489e57b0b2f86281dc7c7d8ad5cb6c0995ad37517fcfb6c79a58f586ba6c31bb08b644d539441f8a26b3f50df7b7", "40dcb1b2c537b0e", "46", .None}, + {.Log, "ed429328eabd0a1fe400df2dbab918aecbf1631af825d587d53b892529c27bb26935166fd382287440b28fd758185569ae0447a44586f4c3e1a80db35fade33abe58bc9c2ce2a72ac96903484551ccf82e151d7023390bd87dffe9d98f609528be84d99cecad733083b59a574e29bde7bdfa17804fa4e8bae771cafe94bb2a271955a7b760d2278983b2672c551ab71ca7b3374ee48d1cf15d022ead3950eee6adc6a86a32f1f08aa45316f7f17addf412d6374a9bd16610f1a1e29c5bf48df695f4f29d04b9b7ea10b72a5689f55624d6944684386f3b9a327bd860428907d51be3433b28d1ab442c6b81d18fea9409e6eee9e1dfb60dbc1ada96536bd7a16965ff89c4f8ec2f1772c3ec3935458810e30d17a6176ee207d4c081910041fefa7019fa63b713366dce31d92aa7731ef6aa3a1405d46bd7265c1acdc73f8079887935a93df7e29146222c999f5f483f5a3f254aa1ee62ea4ad6bf825332bc7758232323059808b1d91a8ee69fa069962a84e825fed0d8e32cc38a25c89991493d0834169b0a833098b446c309e2676a201a8bd1d591c338804e7dd8262a8f6bb2ea6a9a270b96c2448f7861562b582321b5d6fcf56123387c426f957436c9a728165c7bf35274356a73087f2c8ca4570174022f01870e3740d5cc1219e69bdac58de4ba440c76160104c93e44417c620688d8e5b44f27e13ac7f61abc0f2da3f", "80ae9d5e8920064", "45", .None}, + {.Log, "16da8789ca31363283d76eb70cc8f38ba4c71d362c8c3e3837236428992e77bdf9e82389148ffbaf6a674ad239313dd934db5f4900933a62053937b2925b07f476c8b9c0f4a485feff49b51d4e207118622aceaaccec8ea683bab620cfea47cc62bd23eb0755b1b27e3e09523b1e59032c6e7c3f5990e7eb176735866176659c9a217bb4b9b908df8d9d2fbbb1aa38b7caba315c2634495bde05080e206d6594060d86a7392ca2fce4ce4d3062b7a047f6f816d552d91d71c02864c60c335913e955052022ffa25384272f1dbb95da81a72b1da36a4ee3275e2c4c7aa29490097341f6d6dc960b0009c09ef633a22c31fcc99c30d672faa5bde01522b1c4d0ed82acad251c3a27acf0d2869f691521fa0fcac8fe5ee27f6e300b3b9888abcf83d62cae5517270b4ab67326c1561783521ebd1ad3e105c2590f076d5213765d6f2147ccf3922175c06a198602b923c933d4d9e4aa601d16b62431e896bddb0ef164f0f3b05020f0e1bf5042231daefef1636a8ca964370d6c7eb27f07fc20b37ed68358df89d3872585b467011b57fd2e2d0e816425693339aeab1f83bcf7443700c51d0da76e66201772aaf9cc2932d29e4df0427d9f807b560dbcb3e3cb7e39f6abe3aa9931e130757aae8b32ad2dfc128a2bd226ae65e41409c14d1cba15a12e8fb002845928cc7d2dff15284dc8948f0e8b89139d56f7d9f93c79e34fd026", "4da54bc70eda06b", "46", .None}, + {.Log, "e3450a09d9f34ad2dd5f2eb21cdcbd52106271e4c132ef59ad2ec2c62eb261981bb48fa66a82878a7c48e2de3d7d654659c2005376d2a9ca668d0f79bc9e3438662998be1c3daa0ab82ee9cf15c0c21a344428cdba45fa958f04c2d11a0916fb708b082400be0993f6022b275679e204f896f087d2e3a27ebdc221531fd1077b8c6337a273a27c0173fd93ddf374345e8d0766f6796887263333e9b71ea5e71d765401109dff3dce329a0644875d2a592689fdf07dc6bcd353c89e869cce5f844d059f8b9e0320cb0ebd5c9dabf1711e0586acdbb9f1c9fd28014cdcf43ee3b3003916ef84a2e670ef9cc2f5f5c813b5f3a411d533710f7025a497a8f8988f7c0c042a70ad1c09ac50c46acdbae10c0d22548bc40168c9fd68b3fd14ac90612ac4922b4e686e4c92dc9835efa88f9c73cba33923803f0c22a9afc3b389f579d5d4661a4cbc1c954e0796487ba65e50d18fcc42c15cc4ef43faac68ab33e8212b99bde476953f2aa3a0d920c3736f58fb29acbc0a0f6cd5591651df0db42977d048105ee45255d23ec09fba3ed807c4cdf926c77273ab2cef3a4bdf15f75d3821f7e1ea54500e8b60b9552602054d7adfca9fcc4765ad77cbff593df6a035e51c7e7620a607c04b773da8e696a9ee69fbe1237b42998cd6d383f8bc8de6508ce347adfc81ea4384f0be98f32c27c949a5eb91b56221462b9d041a22199cc8980", "b9f7983564e1f21", "44", .None}, + {.Log, "6d51e5cd2b824749b4c92068c1a3fe33ac7321bc5f084beb03dfbc03f407746fca59de0a685db9f804f3bb19eee0f4af5f9483a822b58b6c5ee66b279c59a22e7b4d17aee053de9fbd1613ba3407e93cd2a909fbe9477934990654c2ee26c5e75a27245fe3a3c8572783988653f39bdc652f341bd237e445e14cb4acb58281656e91c334f83aa299559300c6ffdf64ec82c4aa12e3008119910d3bed5a46fbe807e009164cb8f40fa17ddb01c8e4e57a00811a61cfc514a0076359abd68c6ccc68b7ee68d902a8c1d62e8fa2cd1ea23364f908714d35b2c85cfe577147809a650a5ac8d4275f47d3385739e8fc8306d9bdea9409c0b6792f474bf74337b928283b527d69bb3871f4a79a8ddc86cffd45b8dec1238e9a0ff4eabf147ea2c898f52051c4d8c6a0c0a9a6d095beb006bcfc39a54b028a21c8c9c8e4b32544a55377fead64c835b9a5863b9c36ba0cec69be79f8b59751eecf1b9b0449ddebd38f948797a07b22c6124648e36e2e699385c2d0fc20e5a2bdd195f3f8fe6a4bf2d8b704692d3d2ce28ce099344f43228699592bc14bafda1daa1970560aeb9c2a95d43f2455da3066be690f2fabea3ac4cb3c20b73802a03c2f3cf52135ef43aeaf1d940081c0acbb26697b494344a90f2dae1d96a35c3134e2f34d496e4791585093cde362318eb82423229fdda935620f489ffcf135ad466f2053b342c89cf94b57", "3adaaa5c5dbb482", "46", .None}, + {.Log, "4dcb869039c5defe820420621580434e1c3c48ce5951826b96f4e760287d023e411d13919a3301e7bbae72fd4b0cababf45ec42c05eb0ffac886eb7096d2ed665f09435f19590e3892e681cae79912816a20ef2ea9bf7b31e97abc0c714cb9456d10e37ce237810b1ae3fba3423602bf036cb9c44bdcd2f62ac67a44eba39134413b366a3a8788b50822cb55614981fcd710e76897627adc20501a90532e25af655d72e3fb3a5df5180517f3a341431f3524b5ad0c9bcf6bac7a80e7207e9331958488a7d0f2e7fe052bfe64bddd84a467029bbaf0a650a97057b057340ed0fb7b9fe7d6a22adcf68a021f7da6999eabd4a8bb0ce22610901e1580a0e5f341daa7b295b9da7ac9fc5b470201dab362260e43457603d7c215c96383e69b4660d797c96b8cd4a66c1434941def46f2365d64249a224ad19ccf7ec4bbca89d674d9553bc192c0ba327b6114b8ddfcf5e80fdf7dc3509a1f81290b6783a3dfe49519f092f6518d6aac3be1c88224544cf10377cc08824b66704384c1eba4494013d25c0d6df84237c3e38bce3995b05dc20274d75166d2192a4c3fc1fd2a4d7ce117366e9a9b6306dd93e6dd8b3f2fbd065279316b29b24cfea95d105d60578e17f1b4c5cc3bc44c773697211c5cbdb12bfc6092b0cf6a41c143d0589d6403c8bdea26a33a3ef143bf655182bac66f4936fed768f0f3e2fb9bcd7a96243fc0d10764", "65b3dbf94fe2b42", "45", .None}, + {.Log, "a0dc64cbfd339981570648cc9c5fa3d5ac6788441f0204d86b5aaed01f0724d182f7632cc868d64c695524481befcf753d544e38667b741a2526b00360183cab96f219126e638038e822ab320bdabcc65201cdccd5070bb3999226b01162b0ba955473375ca15554a63e89ed08fa1b9fad0a9b26dc85de33c789497f1a28defdcc9cf6edc76a08dee3a74cd20cb153e8e2bacedb8bbbe761d678938ed048b142cd6e098bf23323d699a35695c6fa4f2f8ce93a8e0756b7ac76b4ab39b20658e510cca63148d3d73fcb3d89f5bb5343800a8ff2c718b6c218f247a45e8469028fedf55da5f77cf261b413db24a8a346306b63ca18babdc471849465c1d52d775939bc07d3c672d33c7a5e092dbffc37fb479e2e0662c79e7ce6a0de259fd4b564f629dc3352350cf8844ab512f34195d49cd01ece6e7997a62be0040e95f5d8a16d756bd271380a81ba15cfc5120b98e9a302c8431eb9f8423b8af350c8867dee10755892d10f1958071db305be0e9d5c342742333e8080f5a38beddf69b6e9f01a7de8ebc8d86e40dc7a07f89ed7810d5dfd0e55ae36c0fdd4dbb588bd24b4cf88c1bc67cf3ff51e11a36d45604e48a3860fd9f20c059c4a5ddc74617495ffa0cea113f5a09175840248498bed298975b1639bf83cb60cb9a4797450661e88a8188d6ffb6e2d388b91fa897d037eaca36681bc1c6edf417487419c9b889dba40", "123745cf2100885", "48", .None}, + {.Log, "ca402747a08340374139f5717f8e0cd3ba778942b6fa68a52eb98cd8c3b65fe973ce15929cda2286c1eb9ee2255a6e155257f3d4409155cf88071bdc8ba3598ee8e75acb733743db666df3fd0792964ecf6de452ad257109994dc9565ee308cbad9b5ea040c16436f414a95f26dbcc51ff51c8174664deb0aac11440953009d63b14aaa9c0165da20fa99cf362bec5ff890d6b9bcb27e0485b7cafbca3aa252628f7b916f7461e69231d95a4d819facbaea86a364a1a3ab51b9985d50dc252f0e6360e9888418bb131266f76d46aec0fd008be204c8c94cd744961873176cc8acae0277793d00ff2447a06909d8ce933b26d12c43515454921f38a67cbd7edde4d65eb3849ba717a990b5d38116623b0718f48fc14fe0e3ad5049a2243b6d311787b908cd441ecf014aa774cbbee73f08b3734d36e446283b3b42a9db3b711236d144f3bbc228380faf7dcaec4e5c560a9d90d43006a91b210d82013cbfd4b0886e61ef4fec64e3986d31676fba2c4158a412a7b034f612f4676062720ef5cd0f23f64a125cf2c9235ede95a7ce116852fe0448051fb48f68bc9b11c6eecee98f6c079226a9162111e207737b73e74e929d59e7749977e1151674e30f645640f7316da315f36969e2cbe6f22de512ba3880336572de3d21cf64bf43cfce0754613fc18b46ef9e2f0c06fb042f9d25dc69a04beaa78d2c6462f5562db049e57da", "85eca2d6e4fa835", "45", .None}, + {.Log, "ce91deeb7ef105fc8c08720e8d15605c911b06364b236cf8b71b66d931aa008ad5ec833b732ced9ec99ed17902e1836d61f1a058582851d3af0d05deef19a3ee0f99a3f649c5de026f5e96e87aedca7b2ef2d69cdb0c6ee9ac87c7f0270a6e2137de265bd6c76d7f5bdaaa75fb0e0fea769f0be756f0eae81d4cc1c587c10b6bc3d5dbf1a6c64f2ac120d9242b1eab028e95c74f51a7dbb9721e348c101770719eae8bd1daca4f364cc237fb827b6a82f1103b2ae8486abca6205e64b83c31fb6b935978aa4240786707942aff27b92c3abcd3890ea6a64f32f4709c6849083d69bd7abde30608bf4a12b0de96d15cc7d126233e5b64ccd72352f622d6dec2034fb787a276e559e472b474904d8a8d4f407492adccf78a8e8e2605d9eecef67e6a91e8b5fa79dc25cff186919c29f51d5047ad07572524b0be1975afd167d2b625cf505f3fbe94dc9abeba9e4b679956ca21b283eafcd5b42f403d44ab99c815da537327a61ed6f68ba421c19495c10bd183d7c344ee2a59dc06b2cb60b8096838104d3db0712a5ee5c04c637d9b26bdd14c63ae79090157ebb8a3c4353db7b7b4411d440fd6f785d806c449c5556d89f856a725bfc7e939284782a215fbc008a4ee7ef4f48737e0d5f7c71b0258792aef97807e7109e26b0314a5072b0820347d20f45250690b89a9d858d89344dc18a242683c7550d29e0ceab27b6bc698d9", "2561201b9b2843c", "47", .None}, + {.Log, "fb4ebdf9ce30441ad5a6e1c09acc6cab5163c465ad4fa84d4252d7e3a64d86e7f92b0a9fdf42ec8d94670297bc136b307c83518bdab4d396de556c0a0ef8570222c277f847b41b94583798f4ab9fe36ac1761234b226a04841693c0fb4a8605fb977abeca082acd5cf4ffc4b4e508003f445bc6d2ba7dcc2df7e5215784c4102119225805a8ff97b511fc5320dcd905d05ec19610b772cba105364ee1287806b8507afb3696051158ad278887651c4206e6bdf4268130e9c98e7ed2b3d632acd9b120b7db63188210e3b59aac20ef9f26c5d3d6d209580e428f31ee2c813eb3d1f29a184709838059367b4deac08fcc81a9270d448adad0b7fefe78d43e2d893d41cacb72eaa1c1a0335c461da16ba93d55e19c240972f5133b4fb3a1623610161abf3b8a06461a4f6558d869d4faa2984b57bc50086a9e1a0281a89e8f11cca287389a839c66fa5edcc72e2c56a0fc4af4fcd4c54ed56ea1152d125daf7b197a994d81bfdcc953cbf1add60ad97cb86fccee69d60c2d3bd70369e1ea983bdaa167701afa7609410a171191702c1d259cd5e9c2cd64337e17972fdb02893a8995359695b50827ad7015e200a58af3800aed66a9a95c39ee93484c91a3ba9c1289613995a7a8fa47b1c12d196200e779ca24d4d0e45ab3580d66cd5382894a6eb2b8878e681a306f7bd494125189b037f8f7c655b8adc998c4846b8cba27a9dfa", "ec56ea63de08b16", "44", .None}, + {.Log, "5025b63bc0c20a18c1a054988281034cf30e16cddde403a803ba49d2897c9fb3e98a9a4f7dc1995e24acbe9d7b5b45d8e1e886124e42a6a56a70e751d9347a961551e7a56ceff91b97ca3338074cc42ffe509c5a4593b3698112eca2dac7253bf865ebb7fa6b994ca99a0bf992a54084772abbed89ce2f944f58c917e2a7d07e2b3f97132896f165b0b65f7feb119e74bc485b896e4eb234b6ff297bf8db8d6e60dd49600b21a9b72abca90cdab9feba2bce0486dbda7aefd1a278d2472720d83ce65edd9042063af2e81ad047e92b161f85fdb84ef966077ee52aed195c5de0b30605656c93414ab328470151071b1a398723c9d5994612f1c21c00a38fd909999e1be060a10c689ebc6ec4291a177c1f54d8bd993c3435843c2f22a5e4b4e96971e3739affa0652d3a6418c81d453891ad914ac6b70f3af20718d759886a8f6f9265715239f95d4df9dc0c46541fc025aa4f971fb575bd907f31d0ee6f4091f0d62b16fa363ddf2cd212ebe6f7bf2c2609546035ca6f976c052dc9509149794eb4918c8fd7952a2de20fdc4b0dd03f67b877e77f278825848946958d501270e40e9e6549f5bec8ae1e0fa8b7e4a641ad0b6c532752dc50b0edd3b0473005c63db655b1e72b072d1680a51b351d76c0710d474c7f64ee0b04c20cb2f87aedd3741ed232db85b909c4ff9c0b920b28f1e1c294b94103f4447e83c4f00294b7ac", "e9dd1fbd619f89", "49", .None}, + {.Log, "bb4009934ae014d0ab769cc960eea184de421585983fdcb61f1d530861a7bd808699473a20e7a971953036b008080f4b1b6db33557629b878887803314b46ee4635def6f3f5748103e4b193cdf3befc4bde0213ccbf270780349330e74cad8e3133835cd2cb1a770fd50e10ccdf8b363a56a84709cdf8864466918a067c1f19529ced643821a4d25ed0db5b68ea19f41312b161ebb67c1187fa33ad1d465d85bcc2f2febd82195b088b4d1a2f21b5056c4f72cb7c9dd2f25dcde94b997233510eac721e22738ccf9e024ed85795c33f9ec59549b994ea745795fa76ee6e9475f20e15e5633f306bc952bab9a870df68b96934a3ffc83da39ede1791f9ed6e86822b85cb369ac07ac3c701ee86a8f010310c540769b714f6ce7d9b83f1ea65614641640ec740b792496fc0f22783455e49becdb13625ec1be40a20744bb8ecee74bdea215431d4acae97e94e51986c66e8c2f3ca8721cb0f026772a855fb172a10d0f1f7301f07521efa05065b7eb6c2cf3e11f8877d75f33255a296dbfab00d0246883c404501ef6deda76d074e6ad164476730a1f98db15d765d026af693036d1690890160cae4b81f995534dd11939bf45562d19936ed641d52ab2edaca47fb2df547bc2f365d1c2e48cb6e4cc9c0b12e089ee06b79c8e1ce3e51325fe69fe1c072568fb40da5d8239c0e972b0ac0109a0f3db8962de36ce3e52a2336e5c18", "f73f4dd3a84a650", "44", .None}, + {.Log, "fbca57e040df011be0da5aa40a744cbe0a9b4d8c77ef1bbb73aaf15598a251b398113218a8c21e4183f911a295dd2479f4d86668c7c2e7d537be40859a27579f5a8318e0418ea9a9d7dd72294efe2fbcbc5655413da4d5d8ca4026c85a196b48f1f50664f4d01e2d5b3351314b016f68e4a371f596e7a2bed55287918d8f5b7e7ea511f05047518cfc59625d62512c1c28f9a422201caa47ea03bf02dfeb32f5321dc76cae716cf0b5e9f7af1416ae0dac065dbdf02e631bf892787cd8ec4038da8e934fc7b926e31942badf80e746791ad32f33ede237f5e39f348a66371da061a01bde4cb70740e44afd08b82ede4d71a0eb1ca18599c0cedc2d67159b3943d277c8c4080de0d4690b414142fd378684fd2d478ec6e89a9c665c4a12d4493c42e7788dcce06d90949ec77c811b8a89f6cdc0456e57f0a345587b1a15f6647610fe50180c0fd9d71502bec7f65c0481e6ee82a3b51b6a40238bd95957234c163f0b184e9e9ce9ebc45f03b3707da2bbfc0cf78ccfb2b04bf59a71231ab5c7eca75c492f2e39a1c023da3cb9ffd1a376523b87df240812d6d6ba88b0519241a17333e91898fa434206c6a8e84fa0d0785232a3d4efd6163045043899fcbeb4ac479365df6f24f5c0076c06c76986e77ec97220ddf0ff85cb4d475f4e4d8a01789f7c0196a9a67e16b0e2999de799b58f0ae35272001fd501b32677db098564e2", "7d8c082f64865cf", "45", .None}, + {.Log, "4059a6820ad9a5db13e13550e0f32fee42a32cbc556ae2939a8fa24031c2097c5b7d56ac7e8deb54bf307eba5058e449fd6636a3b2195bb77c31f33ada707da1066aa10cdba6e89fe2adb4fece98e320de495e5460dcd78b6224cecddd6b0baa80076ac963cbbe61a8e7be3ecde4c1a6ce592cf5df7da0bb1455293e8e331010860c079308a8db617166229600ab3049947799682b51d6d8b94c5703d721b986ca9b4c7357d8345bbd0a1ed4bff12c69266a71ff7e5d68664e212b6f7083ba41587dc16a4c82ee46f3c7f2773c95ccc826fa160a8d674fdab1fc1cb07308274419545ab7d12813a15574a1581c81b1c199ede31937225f19ad7288bea795b886d8c09f7730fc601fcd0f04971e7365831ea45cefe6453fc0211610484d9650b65f7b3cbb2ea0579aa59bc14e6285ec3b6745b986c4fb0fe39d9f96a42bdcc57ebde93b7c844050c14e35243e668a8cdceda386a121790de8775ece7320bda32be7d5f6a3c1ed3dabfe2d164d454c64b40fa09ceaea0dca217fb523214a9334fbd612b0a8a698ff0d71d634945f806cb7ee689219b054e407bbb47a303ba153c3569d259bea7cac7c59524d52cbb8712d8d1babb3287902636a0ac1a2632b42c14377b814b20f952872ad98cd8e901704fda6472c7a4ba3f5ffefe94cac13eb16d052508183f84e30fecca5d03778c87183b9d67ba41d8cc9f5800ec8e880e6af", "5b61dd65c66f0ce", "45", .None}, + {.Log, "dd8bfee681c9e0468048c0d82d8806c3dc4825f93022acf3ce2755c8e79360fcbb1e41efbf64e556927c99f1c962d3864717b2e4fc0fbc9216ae924bac62a410a198394f7ccc3d74ccac54e2a23c514171fca673f1f53f2d76e3f4e21c327e6138ccecac66bdd0b1fb82b078b9f2f0ac5611648968f6ba27098e8a0f45ce5cb90b99b8d40f2311f31b445e775ed64a6fa4de94279d1f8c1c6de47033e8b862e8726017b1e0770f20dee9d305a95a79ec05a336c45a72d22b5f4381ebcaebabcedfcb76d37dbf8a5d00abb3846dda57575638cf72f9deb999f8bc3773c7d329f0cc17af7afdbb75b931d3249da2a27ee2449a1b9b5b3a86fef15fe30558a642badec068b08585345b406c5ef5d187d6bf85a88c4c2aabfa1957a9dc6e3a95a14f192a7a0089704fd5692098bb746f1a65c5021354acac193269be316bb5987912f6c32c8a54e0aa42e544142a843fbb47593aa115eaa8308ebb27d85cc1b7831374ddd45eda613a272e5ebf6c675dfb9dc8c4851ae26fc7afa07570fa89ffe160f694d5ef5624fff3c33c1b54be4f6648854b05e7f4e3f32c2a639b3a9c1877018f798ab9ca9bdf2c68f25d0e278302e1dece01ad1e19699151383b522a4890a7369bb102d07583c8c9078d52a487b4c6537d3a8c550cc30ec3adac1afabb2f736a1d2ad4e8aa05727a3f04863a7c6a22791eb55af0fd5881c09bf780659460e7", "8a7c6d210c2eed7", "45", .None}, + {.Log, "119ed34e853cff22377a9850c8c68788537983974af1a4e590d04bfb2b3fccf434896c6d8c6520cb3bf0fa5f8c2d8d90421cd0f6590facff5e2a4e9cbc77eb6d6646c7b9916b9b386e89b00f4994391baa4897804e1403f9b4441c8cbadf3a5307d0f025db4f297af95e7106c1ff68e5a2ad1e4c50a4c45d54138450d7890f3ab4ef8c09daab0a72ba242d7550cdbd5efb05a0d48656c6f299064162fff5fd73709654c7a333dd32d020472961b770fd1b65b340b7a0567876b4ada399db160bf191f196bf5cf672d51ff241b3e4edd3e2ed5987ac9ee6a59c10d5cd08793a8dd6f3b0e42dd121e8ddbb10677af91ccbda49ae9ac73a4c44f25957098f89b7d28ac0b53a3e89d8cead195eaa13e08f6a2f5182e97f24c0a73a82396ba084cf3d5ff886fa06043da591dad7b0d539874e8e3101abe53eda15c1114664b3c6b7e6c5fd2693e54530c0d0d67bc9ee42d0b40fd710b85b265a8b96411ed511447d06f136fcbc1ade6e4f0b529e10a7fb1c10b37af0e7d35cff7bd5e1c73c4bb32483a190629456936c59001fa1f1988b23645627cd392e52eab6de40bd193852ef550b6e3bc310c29ff31a278fef89a0844599e7d9807af09b503b28d8c41c26c85f9c582aebcfbd3eeaaf95b23ffd1fafee3219618f12bbf71ffb89187e77a827fbcadb684bc87a00d5b0f91eb99d3284d1ab6d2de4f9bc43c0ec7f58453e055ca4", "6b26de194dcecdb", "45", .None}, + {.Log, "1eae459e977c68323b4e74115099ebb5c231faaa7d3b636b508898dfb420acab0da9dae26e2e08d6acc57c6e0f341cc4a5c8990a26aadd2f898f7daa0fd729f629eebf686380622b390249c71cf02ed12a321ccb272ed86d953b4aea4d56c9faf394d7c658e8a2edf52a7ba0599d85d2bb09fdf4c51ece70e2f40c0a7f8fdf09062ddf14a5f58d9a84811e4e5f748f808ea463e0857deae873adaad4043fd08a76f28c1c4de0a0da7c6c7a2360ab9e9dc2be9c622b3580e667d94de9dcacb2dea062c7f77a9a35fe090bcf003b7cc47e5295446dde72774e76bc3808a87aa206ee585f5e5ec28483003ac5374475db2e01ae19b0e607eddd23ce4c103d2fd48c43dda49c51308d05c2f9180eebfcf53ccefc744b857e33838f2f7679d1dab652f9d574d7232fdd96ea4146f8aef91d71fe858ef3df0257458ab70325cfe079f41fcd8824ea38b3c24ef5908349ecfdd2473fa06bc5f575a69fc1a3ab0a3799818a45d9bd8a465b8d6c2b70b57d55620dd1c69120fee48a37770acdb08a729fb015a33b1a8fc51f1140fea7a7b1caf38a75359d875f54dabf52b5b5dba41aeb2cf7b4eb7f824955535513c4ae5c75dad4f601acc3e8b14a1aa0639193f67fe9a443f5a416e5b576f33e0e34ea0202ba91b6c65f5ae1c461252c30ab545f29775b78abd6fa2d07dd10fba730cd9664c123f28114b6043fd2dbf21db6eb74fc67d1", "70ee19fda2b7274", "45", .None}, + {.Log, "fc7b0efc7da3d65dcf08a04f3e9d39670532933a7ad86d56cda4329198c7f797cfb0852418cb2b57190a7011396b1fa8eb531752a05a45b226901844d9fd79417660f01016fb9b712d5ddd3c49dd6764e6a6154d4da3261f5d48176f4edbe60f9c06be28163cf4f200e0fdcb157686eef24dbbf2ddce8326c62495cab112b6a17e661d1e4cfdb7e2435b4c88930ecc78f08337380e923f2f093135d7c066cc4a0ff01ced0aa7af4172744355bc03bc66c221f09ed59d61bc131a69ae0760e42fa947216b82c3b11a06182301dd43430d73307e998abb99700dc237d9d4f755dc8d089dae1c0793fc585081510c4478446327cd101dc99cbfb795fb02c9611749050c67a9d749ff85c1125ce48a52bad5c765d3fc0b83ffcd8232bee77a172a73b93009674c2bd76bc08495e0e65348757a4d8a885e5d346e31b2598476829de52da5ce1fbfce36ea510bba2fd20be05b4275bb78bb591fb10354a1d6ac93032b67cba73abdcac8d885a6dbcf976317c0d3a0b66d4173028c9e231ac58eee388ab028879a60de8581748f6a18eecaa987f1f481004e3f97c6ae5a9a25377975bcdd304354705cfcec788389aa0aac3560e6929a9407db6dd4a084113bf028203ee09caf063f6a668739fbb66e5e5670d65ccd6e83c5398a9b60c5599ca0fe9896cb86e6e3d5e959a13aed257e8cc4165081056f75c4ca64ec417526380b3ec6b7", "e555b9dbc590eb2", "44", .None}, + {.Log, "de6470a87ea1c8832eb66d67dd7417b15b4312376d302d72e12c0e429a19979d67dbec846733a2cec23c7b087ded679f176687aa8e47435ca071befb7348b6941f4e28a0f2c81c94fd51d2eebf99cdf16d73e41fa42d57aa76bacaec4da974a0f7b1b6d3f5b1dbd1d2a3241688a8d8438032406cdeb3ce71c12313fcf32d5a1aba2e52f5eb8af1da6b9e08bf19e80f586e78be2e7592c9d0fe564df57a8a07b49a010942ce4e1a85237683ade125a1e471edebb7f03cce7f39a54a4fd43408746938d85c40235f801967e110e786025e3064e36d22bd9fa11c2414de51bffcfd02d8b1343a4f58ad7a0ac0a73c82d670c9db376d2d3a6fb7e2010b048970dc40a98ba70a346598888ca309f730f095cdb100f08e5db83d65d0f7d69d6c44ebe979b6f242ea95e770070a39436f9301118333009133db4a1aceba5a51bda4ad3289d5c73b905d1762de65fce8bcf75cf31cbd87a0f81daf1ada97d2b0135d72abf9df435deeca7c58501df222771f630a93ddfca636774d904abdf02a837f67c139d63802128fa0b77062f6e642681bbae77f36a4cda44ecb1a579ea02d3bcb80faa6dea8b3e3476b68277c8ab03e627dfedd9ae4c5af6c98fac0d33884fe1a3e592f040b9929692bc5d6f5ea037eb271eebc4ca147bdeb530a1bdb359dd336cbfadc6783f130b1e0faeec85ac130f2c6fdffaae69fabd111a7b9a4808814e75a", "18f5bdfeff6210c", "48", .None}, + {.Log, "77538d70a4ae8150c3b9f630101c8bcc1e49050647cbd6493348dba7b2c3b2bcf80e19ca8e97b7ea008b006f16ea6e551a44f9512da02387ceb4722db74d46a163e7d3a058ee6d2bd9b43b3fd35ee1946ce3f93ec37801538d7ca3f3a3d9d36ba015e16a669c92a10d4d27fee461db143a46405c485f4c7139b21d285c2e8c752f52ce46cadc81d2b39440f3ca21f13f5f4751968b979519c286ce7ba2080d4381452cbed1f39b5eb1f4dde3aa2e9959ed959d8a1cd9eb0ed600ee28de5af65b0821223cd3ee4027ae5b8287b2a40af5d32b7c92ecc7495058ad2362c4d6bbe1b7c93301814ef5a3766543e4d3441fd2c9a5f5ddb08f90608230e60f246804fdc16fae47cf319ad09f1c99996231443713a5a5679f92f1ea52024c26f68a48c67c29c976eece05c4de61cb9975a272ed404dce1cb102f5d40ab98743890702e84a80618ae8ffe01442682c7aa33db1f72ca32b6b1586310fd40b119a50cdfbabb53bbdb72877f0c03bdb0b096e87a62ef667d1e0fd7f9659d614e07c9126c0639401413b04f65a20f1c5739a46062581c1d8ab63229aff0ce743418db6b63ff5b79d0fb87e7cf05f05484e1a9d96f8a59abeca60d2bd1929d2131a49a44f166b7dc81186fb3d3cb2449109a45faa3c602c640e42ccab974b5af58f0b1ee0a44cfc32fe1ae363c7a4e9dbd404e1c01d05195af2d48f900d4b4ec1d260aeb6eeb9", "fdbdfeb0e382664", "44", .None}, + {.Log, "994da12035c96e318b8be1eed54eb4d55a52f46341485e8ce0e80bb272917f1dbfc6dad99e127bc9fb8b28226c6eac38d192b331f28be3d84f6c4de6c043c2223f9e1dc21a5bed2583d4044d6083f7e43c8405b6cb04dcf4dd3997b6f0c9f68c389ca2d55e963bfbde51d1d694f024f5eb7aa21ccf129c6156937560012b1e840dc6d39ea9834d281230b7e8c8a146d4630e099f83a61ad6678d6c7e98f0c99697e15c57405577978bfa60a8726c44d3a69c2b5076e905919214fceb2652189eb554be6753b724e34769d065b9c3652905f3dc5e051fc063b3086a2650ea54508032832c059c65f34211c1c631aaf916441b4c7de9d574c0843c542e0093f6d535dcca5ac4b0558b1fe203270160919e96bdbb6cb11086fb8df90db649f1dbd683287147bc59b36450c1603a589a916f849239ea66dcb63b017c5cbf6e8964653df7f8c2534213d758139a18a230453362bcb6db855bf77d6f8c8092a85d47350cb824cc4ca118faec72d6306b3ef645b69a1ec4dbfecb965dfb2934123ea8c94fd84ea6ed15a6be386bd20cdf200ee2153a2739784f514da902c1cadce885d1a7d88459d721bed17c4038415fa1695d6200b72d0781ef4e8d3609115e5fef4ca085e313efabbc21c9b592aba81500bc9131d768e4e69477e4efcfa6527df5e2fbf036e57ef7a17ca0ced706d92ae1dac797da050f459858f1e8d8249e6c5f71", "851f5d7804b1ba0", "45", .None}, + {.Log, "2705c678c533428420427331c879a8d6f99c44c044e131a555614e6ddc524007fe85c6c9555f8e25c32ee65f03dd9a93582310574f8026bbe2f5d920efea5de806a810600727e609a06d65dae6295bdce33343d64341f89764275d89082368800a44caf4e563eadc21f1362cf0da7d21c07235a17e4148b40873fb07aa69c19486cd5f586215b9d890d7834ffc92ea3ef71444448bc5e5cfb1768dbe33f00b93a4a805dcce877994a02bfdcbb40de79820fc9113ce48a580118f7f2defd93d593b3c4a2e8f7083d706687b8c17c9f1a2d3a81d61bb9ecf278967e4ba2c2b8c1632e7101ca028225329460f2124f3ec8bae4d94956e189c64f11bfc96a0b6e992491f08d7375903daa37b7f648b46995478ff30ed5a860030a284fc74cdbe003e9fd34511539720841793a062223212db57007f0682ba950e88d7f7858f18f4f9a946767b45f8981a32f745e6844fdb170edc07723706de10ef2d53476a5b6d659dabbe9c501ae2a8c383212e86767c4e885e0b3b5b077c947805af361f49c84ed96ae68fb9fb21865040868ac9093603b727775b455e667d2057b8815fb8f9e46e4fe9cedcb6c87a377b0a9578ed4ad4603b65818787e2fdf37420232461a85ac232c62583ce7273eff07025db207830b30245069afb44b9aa873d9aa3da9304e915b0b67aa2b17cc7fa56123eb94950a02e2d75c31c37afe6502243da9b34e1", "32c2e3b7ffb6779", "46", .None}, + {.Log, "c0e2774a322b9a9171553e426f948493c28800d1cb248b05ab6a275686a24431a1dbc7b148204cbffea5923dada7b351a47a87e7f609c13ac019c9afaba37baabd69663bdda13c760e0b736c0734ab47ccb0f54ae6fdabd4762bae23ca99bf60d6792f67ac4a4bfe79a491d177a39994d48dd8c6bc7c210c3c5193e7aa605adee1a8e9726163686fadbc7e5b42c7e6cccd3fb5b42e69c5f052186849b2238326c88b2cbab04490063735c3f11fb2ff72d151ab652e6c45c5af958ae9893243cfd20a90b710158265e943056b626d113c400307373ae013d0e1c01b2960bb5c5ab6c67182f863da8e47599d353359e440bf2244f80edb365bfbfee7bbb8cdb72bfde8a9d642ff94f916a3d9a490eb9d2f670bb77458c43ad706a771aee8c78fb208cda1fe08a20d1b1d6ac95c29737d196932ae42b32a5ecb43d49ca8d9150b124043e04c7b8dc6c827a8ee8b497a96346536bddbe1b6de33b8c7883f787b4607208f328dbf0c8aa76e7c773e4a9a4c45347c6deb899b422dac2f3dbd99710e265efee1252df16cb2758e288f3e88910c4bff1fe562f361278de7cd9692f823c1582c26a965d0920db23f8563b599e5ee26cb800e08466312e799700b53e7c6e19ef137df19b8d3284fea29b18b21f271626e7526a6a8893f5b459bfb5c01883c2783d6021a72c2a0f86a2a382b18db13f348070941c677b26d384c45474a4a56", "e0f1326f89be9c2", "44", .None}, + {.Log, "c76ca9ad078973b5c8c1e5bddd7a6bf60e84eab1a9325ca8ba12d5048d788e9bf7370beeff19a6596645259bd9de6a1c2d315b2aa7b19c99c2dd72944a7bd1ac2928a63644bff69646867d9c2e6c32e62e305544d0389e226f0838c0595480ffab36b57479facc15eea561cb7a7c54855a90df0331d13f5aa5b283790441d52e75b9d2464be387d86745bf62fe3be6865c37e1e2f85a3403c1a0fd580edace1f77db6bd6d1c0dd90bf84666db20cafcad207da6d351272e26f29eb02c38fa4c0043a267c13b15737fe4b9c2bec398638345ac4b387bbfa84ee8c6420873f57f1d73c6454437e48f0522f9926a7252f30f7bc832f534ab120665a3f705dc726d74a732c7c49bc442679f71b948a342bda20852cc3d51e78a96aea3a194b91dec25561d1f39383886916f8b4d500dedecc69d018ae62211d634bbe9ead85ad35fdb5209affba9ec6e5272b39a979b1c98913e93548f98eadfb48ca9ec2832fce5d2ffa55c95e53f3a5403eacdd00404094d03c1718a7e2f468088f7ffbc1f0f50474be11a3e9bd88ead3be53d72bdecd6b22304a77f7662434d01a1d7e74c4e92d04fcf236f4083b41b8d0afb2e0e40a234c2590b61c7cda497b8de8e5e47b866f001db4c0bdc0a169aaf688b472517a93108c02198933ebb258c69c67b7c698d58c401ad66044628c5fadd98321cd6480d77bee2500028890e9bd3f5e0ceaf5df", "1f9219d38f59d87", "47", .None}, + {.Log, "931ae6c442deee3194bd01da1780dd2cf2bdb2f37957e2e4df5a08334066c4a9a3b851ff5548fde172c267e750d7cac293a202e8042a59e726cef77bd4c2278fa4165cdae852ccc140d3cbb292b4cedbd7c59678a32b11d571fd5fad47fc4bf12bb0c5ecd43ec2f50c527f1e608cdd289031752e954c92cda6ca845f5fdec701b2cf9cfbfc9769fe180a05f2c0969feb85b4101b868739eaf6e281e1bf9a42ddd3a5daabc936e077acc13150703583d1e9aa6a5e23ee6a8dcd26724aa5cfd45a4d6d8c30226d355a07535cb029b8b001af0efa96a0600096cfbc0959c2067764f9be5af5b299c5281e65180cb7fd154e20810fabba587637eda1a171eee44304191305a3b222dcf9810f6ee3f6756ffb6410a4414b002da803c80dfe7aebcdaebb3a2eb39b12c545195e45fd2e8e8d92cb322483d3d2e60a7aac72b53e0ed8ea8849329dcb6a43860316dfb0c1f2d130d3e11fb1bcbe2076e2fd6de1f95ad8059e7e01ea59cd1db6d5edb7d030efacaa5cc4a642e86620c4e079abb98cb4db6605eaadb93080f09ba333a1a7e69540487b8ae6a50de6b7db475ca3e1aaee196bf2641e0f8fe3469cd7ee91a44c413030064ccaf54fcbed037a80941daae40732c0d356ab01af6d6d4bec4c62bcfef15d8122f031708b134e07a9e12851d1d9e2b5f4a62a70b59bba5298e733bfa1333f29d7975294458f850dc68a9d83329a", "5430b61ed4386f8", "45", .None}, + {.Log, "ee63bd6a8511d0b0cd0bade85ebc3283cb4e9ae0d7cf8db3eaf894011a5c7535bef117170ce3853ef952164cf5a097b1becead2e7d101d4017f24c55768f194695fe764cf3139d545a51b59430836937f83d0ed22a6cac0640da5b7a294ec948f18107d65bbfe29e5d830fcd3f6d94ded71affbea96c297000dac9f254d823e4a1d792ff8c07ce6062eba6d2d2d92bbab08809ae689013dc5b6906070178455ed183c639a8712a67e97172fc5e0410f924da30ec4d73ba95f334aa9c0ec8c7eacc7e00d0391fba711bd42c953e9023a0888c08308415e4b66ced1f5b1f31ce9426f843f1e28e3e769f2691c265e7f342b0e3500d199676bf6858ecd5f214896bfc038827b152e90295478a09329a5e1915f52fc7f88471c52f967d7364428b9a3a349ae06634f24c1b63d1dd96129d119f24677fc264226547104a2564e1b32a32775fd08d0a0a5e3347955af1c9fff5045eae3987faa1d7802b21eaa8f74bd30d9afa195f96e36d7be34e9140fc04a6da3ecb957aad7e1f2a3e9fb5f47e562c1f883f65dacf8aa7f238c110e2a4cfd65a25f35f9c4a9458c707458e187a06c5c0155a49bcf6817035d03171038e21e338cf051b54a5c2dbdbfd7886d0b0897dc1fad011373f6e112d17470f5ba799098b38dd615b44b71f6203d20e97a6df496c4ff0924e52518cff42a88d4234783332171214b598fbb0d7cb4f1f9d1ac4e7", "617236e107f3dc0", "45", .None}, + {.Log, "37b50418023e019a7dfe362597439bedb84f6f8418e4d53c02e46c6488255b7d6dac80ee12b43e63e32318955d6f57a10601a594d8d1b3e92f8e34fb2137476712eaead9b36a1bc08b63a131aaf2759d5e0fe9da682d5097dea9f1f2c25fce42201c947ce945984b755f9097ff482a1f31c74dac79a6b5eb1d55dc402443e0bbdc15436a3f3ec8654c53b6b2d674fb450346e77a2e55333846ec1b6de54c64dfa8e34c0812189c9428e34349a5786be5306eab8bed31176b3041b4c452738e226db13790607a0948c3740fcd75f2efa56537e80a7879aca0855417f72266645ce3c536bb041761ed43bff820eba43023668093fb82733c8b7bacc073d58d29ef49349ca13ba2c9c7b89b833429eeae01eebf8771cc8fd0f633b94203a8bb28db49448886df368186cdb263f7ad3a5ee4e32b192e10f931a3f0183ecff1b98ca39a4227e47297e2f63400eea6e964ba274ad168904542c55ee0874d46541481d136f1a85c60ca9b1ecd8cce46a76a1d79fbaee12538f4eea92411ccfd5ced5d432e5ca03beb4ebe4ca305576d54dadb3b420ee41bb02aa03379598a7d36e4b07f7f439127be4132f29c66a585948615a443d5c1203b625cc99129ed8954df126e5ef48852766a530bf1685b3fd195fbffd1096dba2419fd9792396148814a93a03e95b9ae78c56b342c2894eb68f7af52475421210950a04187ddbd496e5ace5e", "cb8c634430448b8", "44", .None}, + {.Log, "25d97bda00e34728498dde8a8f0e251a3eca7306868953d0ed25ede6612c63cf7093e10f486e6e31156375417edf3a1aa426c82183b81129e620d6458b259ca0f156bc7a6328d7dc8386c5b0dd81c6ca3af4b3a62e05eb6b7811669aace41f91cbd8239e3dd1c57074018d29d67e506b9bcf4a688b9ff6640f82358b53a5ca6083a36858c4afaf6cfb0193906fe3dac8aad83de5c137840bed4859dbedfcee40f573a79cb71e9ca4b09648d0d0e1fc3905e73d454cef68ac8137893ce72717648d5a55b66a3076e8cc9c750aa776af806981473fbaa666b1922b13ad406a85d43f4e1ab87a7769c74d530def6ce3d46c5f49e3eac685f1ca02f0082b0086d7ab05151a8bbd2bd394ebd785211f1f270130393eaa7227db2b8fa33b5f0fa48cd788cd978cd6976741c7f5efc6e38c4ab10e52ff00675b6ab1197d44d3dc9170c6740d7329c60a09b809ec0d795154adec7f36e2451cf2f2cdb8f5266ee05c4f2e9024d1f8542d3750ce2db1ef113b90fa1f60f0c2dd751391b68189da3163791d7020a92119de0f84f635de199159d1dffeaac87183985132f198673deca1d16a1fd7b0a2df31a0c2214d521be32f062aa0d8c4331812ae64995de1cc5291564a04687d2d1c5fd50b1a4e59d5d9f2634ee98bbcd8152859fe9b2571b8dfc07ec33866573c65088909ea144a248550356ca4efdd962347ddd2a0a8a9ffacc13f26", "7c283c7b1ce6ba1", "45", .None}, + {.Log, "e485abc295bca06a30179c43b02fe44e6aa840cd4b8615f2501118a6fabc8bd65692dc42d5bdc56b04a7a70c7822bc42fbe79b7fc36c29916356e42b0ce38782689aef32d2716330c21c11c4c2454e8a3484ca2dc708ce9358be0490e8a781e459c08b7ff7b772aeb31e8fa89bdfe9bf85a1c80e81ac01abba0658ae3e8bfca2f34553d5520943a3a13f65ec1c434829ca10a5782eacd0f08fbcb1bcc7ecb1ab52ef92902b88192fe68cb8645d821eb5b8d9b0a0949c2978bcfee796bec3d9f26d2a3972ad54ea785bf7848e3bb7cbf134a90832154cd1a250a9a6fd1aa778fa6164c03e2c4dd3d19e535679f5563de6fba26ba6af0831bc1cae8eab11493e5ebfeb717450203d96961857c29ea1d5ffb4a0d5fdab6654670712e546c964c335763f74620700604902311d1c0eb6cca7ee467a2fa2cc669b9fa0a3f541c9a7c488c659cffa202bd953a333858e9b6c7b79dde38e7f4426e26f529a6ef6b90ed55e873216a67842dac83c7e6f1aa79e52a11e550af7e207382f10099238ede3148c1ea8a57dd8d83044122d75c1f2ec97821e664cd751c308184df282e14800a10c303fe1d22bf3864c72c7f0a1936d8a7e1660ad5f1ce32d0da9cb0d7b825375369c7ec4c8142891cd9ebeed934c276da8c2ab72c3b94457666663b694cb604fa9551833962736d34439b88e16c0070bdd08218dc4ac4ed54e1358bed6eb52e6", "10039cfc31258c4", "49", .None}, + {.Log, "af295ba1f41f223151b4f1420738218cdc3cf44b80df97e563f59bd1adefccea89b1c1083bb2abb71dc9f3c1a092eedad5c4c87541a1370235966ca12790e35c540fe2cdb58223f6bb1533c10cd71ad8c5c99c3a2966b52ebabba593b4c2d14dd57456d7e24a12ab7deca589f6db9e5cc3f756791a7364f64d13c068a3c04823bcb4ea796a09cb67b5ee9f7d0431d54c6977d3a6fe3e86c3f9944700154383a379dd53433a901969b387ed34d3add6b85ac235cce50073143a3b404ddc76d9921b87ecf6f8ee696deabdd83cef2903a428eee669b22aeb4abad83102f7dcd609ad5664506bd78d7dba42db4e3124fd6865dbebdf48d7fd727d0b19c0cf1cc5b4eb6e77cee3c66aa40c864b96ac3c7ccc49caccd9b29960826594a6b6647b1d295b0e9e04aefb8de7835217bcb4fc15a00bef446302075b9c01fc4e6fdc4b4fa5f52bddbcceb1dbd5f5eafd6a2610043798a5c78641c8c4ad36def2511f0eb9bd519941ddfa81b8203d5fe1a79d5e8fdd3fc4dd6a20fd3d4d1d49e98e9bea70fbb0a8be5330b6a8f36ee398a96b08fa3de3fa513f597c94190a0d87054906613d0f79b749223b6dbb481add9cfcbd5bfaaf4d7a069d78d4242b8c02fd7cc40f29c87955260398682813697f9fd356ba51b68fbaccb1acb2bb42b3dd148aee1f3263cd7dcd5fa5deb73cfce25db4a50a42b067ef2da99a0bc977a05fe5364520d7", "aedad54c2cedbc6", "44", .None}, + {.Log, "a496fa2add673bc26bd7252ccee134ddbf5caf317e464ef20862eaab832c0708a793f05cfe7bd4b2aa9ed1240d24cf859d3710dea82973e0450ecdaf9aafd911f59fa29958389b711a2cad5936fd2437b8e35b63d46a658a8097eadb59bdbeac9c6c6ec54a32ee1781e0c2cebf6b1963d776622fa28c688bbab9930d1712b1cf678c2c38a337e1e9f5b9fd4a32b41e90a302076092ec32ace97baa4e500b5a2d7e10860cab4f58fa26502bdd22cf03f1f7727c3c1f13755026593bdb17128d503e4e76a04b8a86bb37f90eedf7cecd91657beea528d603e98a45a4fd18dc3a9a98fabee7811682c190b8c96a905825b8ffc44f24a820d70d7afed5fc8fcdffec1cce845664168db095469c17ce3c49309e08928644c3f21204e3a989f624ac46434a61066d7343bc7ed4a5681898d76bc80daa5b4ad1d8b0dd28560282ad4d5af82994eb878cc6e0bc3e565494e5aa18a181bbf38600b2a237a7fd30fde019a5e263be81a915b9a821dc3eaa6be7d9c26f837965e3237ad77eccf652f278dc9cc706cb73b9a13beb6d723aabd7e7b72fa5bdceebca82fd82e74cdab9793586efb9fc35a98190d8f26ab42c762144cc38eb6ae3dff77d26c414ac3829678a7d2998530ad201926b398afc218455e97344a59c4268e2bbb86bc4957f5ae528e16c467b91e087208a421e3deace18c2364dcfccf5c8d28dbe32c1e6aa06938a97de", "f9ab23fd46ef520", "44", .None}, + {.Log, "33a3d7349489350331607daf9e4fc8d6cf689dc2e36390db70d5c9dd74da894a429c38598d3db56c0cee94a4d91bdef087250016238aef321820c6c1ff532490e44a60ee608cd1649e034c916b7800fdbc220e34efc055f6e4b4d703be2145327995eff61967cd7cc1ab470878de8a7457dc9e6d4c44c85c8da1e797be935e04559293e10620fee36617393bc45914cdc6931140ed6c34a27ae068d73259bf7f742162c3667a72541489065530fce80efd23e30b83c2b1533dfe002aa7a6d426c88e8108a88a29feb128f0d447d60077badcbc6d47b3c403b288551b56c8d39d72c7601f86f75f71ec42533d21850cc6a8d1dd579d750261be9a5aa3fcbb7dccbe143179876e2426b8e2e0c34e8ef12507df54b1219b369887cd84da3f4f72f2b6d146094e9294156e8be17a6fc9764d54f5ccfbc503f29cd9b95a48a01ad72c9b2ec50ece8de6fccd28295be1dba5fc4721e4309242652fff592e0a10f03169f70447d95474ba11fae5285a9a22e0b11f8efb8b36480a15fb6feed823a9afa0bc2a3f31d85c92a52a3b37b0f9592d559946136000ebbf58a43ef689bf99659d9410b813494a2b8f2c583c23788dada26f55eb9d373179c1f7ead6cd617bf787c32d1ac248d66163d751a32ccca6cbf840252395b5a56a43e2b2183be4ff1d566955824049f9d8a221a5161fd8ac6ebe3c8ae616185107768e14691eb177d3cd", "4b9813dd3f0d04f", "46", .None}, + {.Log, "bbc4b5bf3a2e7566d15b629ae28fe748f5e446db09a1042e4685dbd28d3fd9da7e05a739548107fdb02a8f25c506d8c45e7a7abf569c00d2f392ddf885271029665a93e70a39c890eca4eb35068e4f28f46137a30974a3dc34db091a255757ee0197a188c9bca785f0b8191ef6b685d54ac798f3f9357fef8b0919a5104592f33b345f71378a1ac89696af7a09b6b2e923430bfe61e0dfa355b98922176a7ac6bc224d4fa5d0873067cfd9554d5835e56e522ae4bb5925c35aa1e5da4c658675abe7fb13f40b1e7cd87d732f6e4f828f1840993aa9fae41b895630dff02165efdbf0e4b055890e0cd08e98af5a4b372dcd108900c96390e9ef99c2ddb46e45f20e7c3c14f6a0a88b7f14b71a477048c8c9e1b3cbbe1abd4fdb9d12445f05391265739789ea74c620f11bc246bb6cbc110fa51403a7ee1bac4da26806c92c2a31a47c01e7755fff846aa64133b4c54967eb58129503af191d9969678345bd45bef676e03c5e1244973fdb5cf2d536c418843cf42f20cfb434fbaadd9a855196b335c66222700c0f95714b41cfbc141e872e491756f6caa784d53c8ee8abd4f4b3e30c07c406a5d852bf34d9451e5f64a5e85ca31fb99a0b29f36d8899843a05120493e1f31f83b7f3748d73bb4b0641662ac586835df21c4f211a9c75bce4ccb01193690f9c131896d15186771948ac03d1438ebcc6c8922e74bee01355d0c1d6", "271af4e05ec3f79", "47", .None}, + {.Log, "d3ef132243ceae8e83b4b07e0d555cab6a6ddcc0e42e8ef8d24a2881955806311a696a4cf289a846c984f4537fe584d89be30e3c0597304662cf5ada4ae96d236e78c0e59e9bdfd74c0b24262c91dc4e7cf11b0b40cf37fa6fb711d0b44bfb20dc51d3356d25abebf3e27a05e5712e431c0f39a79f0f6b41d77efed385efa8d25b4d67dc56fe5b0e77768eae9db923df8ce036b63aa3a8ad2c8e8f0f95f054255425fe3803bd8413813c98f56e204dcfcd9d9087f0340bfccd242a9c8503da10a2ea4adc7c0c833f61a6f45d1efa5c48752c78f82c3bc21302523ea83aab1547a1275726fb4d51bcfdda6dd4eb33c4fbf7de698a83f8c745ded98962c934cd9f43530497cb5a4b3a32484e54ffc0c808841747739e74975e7342d8cd120d811d81e46053204f97be1503dff89c75d3448e221898de4488bd187e07d36d89ea6edea1a1220f449415eb95064b36da5e04f54cd228db18d22afc34dead30e5fe814b8b7473af2032efeb8fd58e62828be4e1be77c2cc4815766b844e899444a671efa449c326a45b609107ec57c6829274c7f3f5ec83d54aec5b11702a6c3b5a39defad176ca6e689eacfc361e0a438e9d6252a282bc1bc2c1e7367fc3d56f7874a0b3f2cb88a243ece0f024cfceaba319790b24a86a4d029f70437253a49946bba3762b066a5360e9fc8a6d5e40f4b2df2b8eece5fdeff9621f3ca3bcd8d20f3d", "99850ef3f645a4d", "45", .None}, + {.Log, "d3518d7e7932a0e64dce892c9e8037a5014f50e90a2485bd9e44865473fda3dc2f4a824b5d32b4672650513c50a1bc6dd75887a7b76749bad753f57d0a62f749d2fb937acf669e2ccdb0121ff059c3f070c2e92573abe20ea89ce4bfe192f054bf3abc493159364323666acc0224edcd7f3d3ecbfe7f0ee84c7cd89875cc0215b842dcc9f28f22a6192571e996c5a69fd137f14fe1795d7d71c4e5dc53e59adf57ba45878e4858f538ebfc20bfefa1eb2343588b6c0018cf0da7cba1b99fc31f25ef9e79b0586c3f128efa2ba8f7d47ed1b885332a969635fc09bd786887ac9358298abc71638fa502ac96291216f6cc69b205acfb84cee94488db91ae099befef859b69afc42c776f65d2d06d5923f8e1f2557f5b152d97885514f9b8b14831f4e3ac656bc27f79438bc59cc3aa96700fcd554d817c61592c00d95a4e3bfd917202dbdea8993717412b251259f98358d426992b1a70c4cbd9e2f131495195d4d81a77980df7a3fe66a90f3475b619cdf7e076d9ed1f257d1a76aa32e2be49a773f3cc1da0b783113ef7256102c6ef27e31367edc26ebf04625e878f14dc2c2183d237a3d1dacee69138e97c780e763b31c50f1aa254fb02bf2dfec98b26ae1062475a69de6561843eb91118e755ebb270adf520590dd2f38ff053599f9b7566988b4e20d76d99aa5a1b61f2e25a3b1679f53ca0313abb2ecefd42f3a5f796bf", "2f71d582cf4cc33", "47", .None}, + {.Log, "87614843108a78adeb49bb82e0afdc206f2add1d92b6dbefb6f9afa14e033a1a601a5c4aedca0bd7cbfcf3b38152773f5d1ebda04811dead806c694b505dba23b7870d9c3c5bcd6c81dabb542937b0c504e613504af2fa633ceaf5e66e2ed84d369b269afc6d476645617a6aaa8d8752e5c6a36b3004533978492af594fa54b2863b78e2ab37f122976483129f1b58b63b1f430795029e2493a4f7d08908105b2936b18a7baae65e0709ef2325da33e9875f486abfefd0c9582584504a239ed617a156e20bf130e778420e5a667ff15dd3f0dc21053ac0496d4a971ee202576f755f6d5dd7ff4516047fffe18140816d375c4e9b24dcd7badfa8236bbf12995500225254e3b682c08822dbf6d75e94c08eb5aeaebe18b76a503823104746039d15ed6019f76b70ff219376bf928641c797f0dcc6eecbf0bea7c803d18c967110a819ee6bb0051e99a118885a1e7a5dfbb8138fc758e6a22a2b3094f75311ed0ffe12ea8a06886e1269dfbeafb55c6e3486875787ea29176abda4eb37ca64b12674ffcb6154b05503e3537283cbee408af84d3c988de423af6d3ffd06e82d6e5389f2bd96577e5f3b615eac0586068cdc76aef89a7550fb17998dbc57151f306507aa7f8edca6098eff3305525fd8d26b3dc66216afe1dd5b10f3e7690484ed725ff36d53ff1de8968ab2545a81a0840d3d7ce6f8e3ec2defb35556d1396e340f", "4134a415155bd46", "46", .None}, + {.Log, "19e84ca88615ac028699a3ce9ae35fc6d2f41569330a7cbb39b581e7b01f92f4ea459706a0094fb0bec03a554d27f4cb0a26f4091f500603320bd76698d3bb40657b7d069b74312ef7dd19aacf7002e155b49405902a32debbe0b8b5bc7938d57357e634bf72ff40216f9fa9aa3052d8e630ae8507b274f5e5523fa840a5c04853abe1ea07126eb8fe910a53a017b200d1699aa2aa56ea30c1ecfa984daed0ea7d29548827621f370a1da9f945c3e4432737e59517a21eb119c15975ee2d8604a36d9a4ab42dc5c0fe7f889faf0096e9f45e7d7c26c80f66b2ac4c5177aff093054454c2a678466e2bf63f889719068d855f73be1b9e315eb37aaf3b815fdc848dc2d9d353c27a2b391b10e894958329d27341bb6d147d16e837cbf781e903c07b220d761b5341c30f5b59b178a6682e0b187330f30515ec04652469a3fa5ff267a5b6e14d2a7ff07358f8b7b46b527a29225305c2b23d59177751d1b11a23427cfcf96bf619eb285a8460f352dbb11d0a71e73737c123aab493755fcdc7a2dac32a32aa6b9b4e18775eef4ac8ec8dd6cdc870ca4da17d9dbd2fb6e8f17e62fd03a3a7ff33b897f59466af5fa4015debc00f94b4f60461aeddb4f0d515042ebd298979785d8684788a0c3db968e8d2493be5caeb55a015bb773677b7df3706c6661de17261064eb5bf0b982823d7048144aef3cbd3914e5a07f0d98754f51f2", "bb6f3dca837268a", "44", .None}, + {.Log, "4f03d15b233d98299a0e235f2ce3652b89e1013ff357b0a970d8a4c188f8722749cd987e4bc37fa8e56b151be5b8670cafc829e73e32130c67a5b40209fa4f5788012499c27882001b48aa94633854a054bddf1f53748038236435b5c2fd82c6932daa14f4bb60cb4669813b35e6016196bf32c8fdba6accf6eefb03d04b315641722d76a4df6383048c609f9f8dbe0bc39863b9ac23bc1e11b92c9fb25d0e2a7cec88ee742ef24b409924fbafbecb4fd90a48dc9d4b9bb37c3d296ecfd9e0d2f491fa582a700b4f2c7fc7737716586a04964d83753b525e06fa1046fb2fc53c08567d4c67d1db841b30d758d71b734dc8ff15e4b5ec4b34ac06e1205227972246d51addbfbbb9057ef2487e583daec7c9003f6bd9dfb5d227428692a5dfb1b4c45561065e34c440a65af0038017a42aa5be2aabecb33765822bd959f79566216d2eb8b617fa2b6de5c59770ce6acebe16eb384cd6d455a5ea04b42246654ae65b22e024a5bfc416258ba77e373855db12b42887e605e4bfba9ccf4ed5fa81448fa260240c5513fcdadc36e6ef3c9e96200b0ba4ce979452a1bd34d2294fc74285ed412338b68612b68a0155218a97e7cd35f062ae67b52adcd3b62454e9bdbfec8d6eebed08ef15d1dccfa3194ef1ecda3de8703c0b992bf29b51adc24ac2fdd0a3db597160f59ff2348bb0d04ad2eddd63839fc79102807949f4e77539ac5a", "19c4d34a2927ac0", "48", .None}, + {.Log, "507831d9dca710a007c9da6313cfae49df2f2e473104660e2cdb39ffa46e6d598f2cc2072bd931e7971944f0116674dfd87f865cc8225c91db6a052600aa468b090e2f8ac036f660005b8ecad36107c17ef9338f5d4bf05be06e0e6446cbf584cf465174073466ccae98646106852533b2c3577fdceb1b2c7cf475e4209e3290bf7c213ec441ce52be4212192a94f87cda342bfcc51d4aacf51873a3bd40dd0688132a3a17b16543fea57b6d21fd6f2509796e8ad73dab00430908a2748a5c4f96a5384db130101fff56da758df04a41eafb08bd9978c443ce5debd3b71e05ecdd190d60330ea44916ebb6b872805d1b31e2216e0da40b34716ce55fef69ed5733ca448625795dc36931ed3a9c439030bbee18d98d1b32f3a7976145bd98681f8c13bc6cfb8a768aa6937d5d95e265c5d6d3dee21eb71436b41ff261fee334ee179fd0f03a52b3ca4855953156f4215cc7a40620c1cf32e48297d725c9df29036dff00e9c4b044b848e687c808c29d98d0c099280269f0a2aea26f3e3433abb5bdf76b1f719fa512b1fd19bec83bf29e4494ace8cc8ac7f86bc093ca8cbeb51283e4269cbac474e85f1eb40db6f9228d3d3a8af54c69fb7296fa054a2694f6f1f513200c1f61e7a0de33eb7711bccbc718af62a55311fbdd2122fdf02b693513b681af01bd4620cf04b6335ce0a23930b860ac5580345a1d55affacbd1b13859", "52bc6ee6a015686", "46", .None}, + {.Log, "36a5b58378f6fbb462ac549873053d53f8c281537f59087a3665a95c16002b124c355598f1dc27e9a91a1056fbfbdbe9970c65b4917f5aa6e4138c1660bb68b111bb1cedc2250526b661eeb89299d4492910991b5419f356192e8f3771e6fbb55f250007afe5a6bd7658958c446acdcd8d6fa59c7e12c81d854a0dabe87cf9cccc322fc8a8afea3c593ae2385bf75282bc40b741fabe16941297176d5d5c31899908b9d1b90bae0ac617fcc26790ad70373e96dc50e28bd0e2416c87f5718944e0127c599212af89d23a8f2d6c6d7e2cb84e83908f667686fa8c55e8251ccaeda1c0da9c8b3ab15275017027a3184ce6126f37a0ec791987d03287466a59de1acc4f09896c0ec36dd8a729ef4f0a7beabc8c8b9b672e0a3fad8dd876e2bca68aad8c18c481b1e0579a7ba5ee0228f05465f3f202967557b41bf371ff9320b7f83802fe2ca83f735af7ebbce3e858761ae3f72d400caa0693d95f2d6ca239c41003c01ab00e8b1a60044ba45d305996b2dcbfdcbbe7b3b9d1c3312fd241f872257e3bb0a1f25d827e9f24a71e8847fc3d90f7c28ef18dbace2a38d519b9457f53df01545a217615b104335814eab4712e6baa946cf2924089de62c9fb6652fc146dc37b34060501dcaba1bdc8fcc8848554ab6b163428065c048d7062c01767871f893bfd8c8b8dbf68aaf5d1f64381d1f4bcc0cec200683b225872e271b58121", "796c91b95855082", "45", .None}, + {.Log, "944c2d0880986a09bd4b2baca1d905930a95d4e3016ccd0b5238c7a0a2064a5a4a5fb0f71193340cdb385c211cc32df321b58bc33bab9ef168d5ab642e3de4c7453a5a30a1681225fd12de3aa070c3c2d77dbd8b9d55d1074347659b730c518893428f6c9acbd24451cad73a6558e390c0b866c3f90ffe43135b59d667d94f33de64f9f839ba928906f2be7ac8addd7f25d1e62cfb3bd8dcb9527cadebfc8150f1251805021eb58c7e83b3b8f3adbb899051ff2a38fa9125e3fc30a1811f70c9b40bc7746ada75cc538b0116e262e65c182fb38e945d444e77f2c18d39993e50b60b450aabdf2f5abd4eba9e37061d6a65f9d5fb91ac86364ffe291debed13ce2313e1a6c98a498a9869fb663c1b99c12cfa8aafaddcedf23dc8fb8daa5cdca1d19592a824c22b74aa04b3144886fd22e3ff37d170ee064ee816cfb28f7334f11b69e5d592f9ef0eaab83763c048670d9a88e611dfaca3f13e3f0ef1dd7b7c93f20d4acc9c983ffb6a7f430c65990af9c3d7511a2859f6f2ed088a7af2762d7aca7e3f5adcb4d38ba708a514d16aecbca3b3984d859d7cc0efe4d3ddf1a605c11f509c063b6b7f7657819aab305dae94c38f21cf23f1f8d00249ec18c0763374867e30a095a9df7b9dca7751f2f5ee234b30b6cc6a4a5dea2a0c27ae6e6ac9ca62a850ee69167330c8f78d4ca32fdeb252e09bfcf755e4ec8d8f4746bcc68bb2", "39cceb944ae15e9", "46", .None}, + {.Log, "bd79c26f5003f8524e3462ea067e000b39bc8427323888baafbf104841da142fa05ed621a5ce6b20f50c0962bf5b0424283360e4107d76a67cedb508e4362ab85cebf9588cfd3ae12bfee1add331596b2ec2cc128033441a0d37586ba182bd564f83f7e0fc636308d22c1267c85cd7b3c16ad0dce39665685e0e03279a79d83d3b9625d256f82cfd248ab1c7370ccbc74fc839ac540c5003fc5958b88150435c0698ef30c915bffb988c25133d320903d55c59f577454f03a4b2cf26ffef035615fdd178ee30802dfd99af6991e1e8b95680a4fd0e854588c5a9c3b6ee9c7521f85129d426cf7be2e87f82c38656d0ba71d987a40ebd2b3fb9ae05b4cb275318895b38a7bcaaf9cbf089007600afbef0832d8fc2dbfd5feb6af203d42429ae0c1003d0d35ccefc4f8f28acb8f9c2d2b4f14edefa79f2900455b69cc896e05d219be8f71c8cd9b057c87fd3bc5c15aad526780c5f50dd01a015fd588805d9834397597bdd576c0bfcfef9c19fcbab233c06d380172151003ea45dac6edaef922dcfdbf07c2c2e63625921fd0ce2ba1bb166eb108269ea3274b26bbd336e24d8bde89aa04c0288172e8d3d32166fa6ff8f80eebf0238a849bd486566cf737801577f2245e186779c7cc30b0656d4d1aac1f868fad920e4bfb86bb5cc19ae526e4bf2af1f1d704846355c6c4132fd979fce757373580676df81c94e12955c30a48", "2d3554b66833f2f", "47", .None}, + {.Log, "d6447d3101f9757757a980306b6fc6e049259905053811656c797997966aada867c7bb799b7bc817123694943ffd077403c4a7da4792f48ebfd646b2e07fd80a6d3cc3159f119c0ded8846b322f56675e1e8a1b224b8299c8f7fae7da15366de7da3c77b2d84905b2d17aa0e4c33cd84fa3f7524314e57d0d5e551b96bda56607cfa4f77dfec7216d48bfc69cb296a6ac1f6abb121fbc9c894283712b1ed8d80cf4b3d77890d92f4b3a13681fca8a538ab44b1e10577535c5f7299350f2db042a0cb1b4db1b8999ec6c7a0b283da729b6b33b1ad3c97b63b92135cd29be58939b77d854ea33a947136b6ecc8188ad862b3ba920368726e6ac2daec8eadb8773428f4cd1c1df7999b85fcc66931c66009378ebce164290187fc34a1679a61ff4fd1527a84b229960284ccac1a208236ce3937c72adbab5950c362966cb4533c75914d7507b1f352f1b7a4e751b8cb1daf148e9c1e3a4b739c92f2a64226e607659b1e8e75e62439de9d9c79415f5636e235cd027f127c9d9b2cd7f47f519044d65e9fc60ccb3acb4f583cf9099530d5159554b6e248a23d1cb91d153e5d207f96fe1163d287cbbc5d5a3c70e8419c4e99594d70b03a5137d20e40c8cecf54cb2d08e5e8a1126c275fb0d9ef207ee31f9015ad1be7876b0b93c4f90ef3615b91954896b29424374b75b53e17df3701d0481e6810e81c33439cab5a40b5a62f22be", "ab9c248a596f8a9", "44", .None}, + {.Log, "69e493e7b4a6a8a9507132229ac5c0201a21b711a25fd5ede2b21ab0c7a13d6937b79bda49c807c6aaa27d12a674637731466cb117da3af37af868b3bed6544ccf6c95ae585ae0081774f13f1a2f587a419f120071fc13909ec9913c576123ec32fba24b06f46a594119900699da8e100f026c61cab59073fbae6a71a62f12dbff0fd52c1807cfba24dbb498e635f98664ec4381aa713104733cd7f3e2b07e244ff52f19276622bef3f44f2c283ceb03e05d0d4ed5ffa594e267019ec19d42d7c61448cf49ba7db28df90b004d3404d2adcb8d4d520ff0032818d182c874d48b29996df77524a8cc63c92bfba07b7a7d3d372ca9bcf58ac784137d65a218c4176c2042eb2d966d0660d9d543a6c030f3ca259f1f6292c741dcaa58199ffe747d9296aa8e40f49facd178223d2194dd1f126ed0b1a0f2d4571e932c17c2be6e1d3cda51390bf652b2dbafd26bcac8c2b9612e7c7dd595714e42d2b2ecb314dd4d42f3d58b63a96b66c1f3b3b52f80361316a51998f0e9836abcbf757a78890cadc8ab3ad1950b9384331c654e5efe90fd7fa722ebb2f16302e8f0b02af85b8b7a1051f3fb6f2af0bdcb1be8598a67a7430d6ca802533f37d92c09ad67edb5f03ed059f92b8a9eb45d87fc4d48d588f71b86fbeeb2138a440ea287771d59fb2733f6bd59e952982055305ed58ce0547e7c578e364071fb3f8fcdf524d6829e3962", "255e436341651a0", "47", .None}, + {.Log, "f36039d05e94d669349592f37afe299df0da22b06cc74311c031c3ddcef3f6c6e12a0ba1aa39eea8b2beec749b42cbc5678488fac4999d1b7bb9464361ab12e18b6ad03452e517e9127a6cc616429d2eae0f4ba96c3704a5413bde2d0270a37f269ada1d5ed2965da04ddf778838238e51c827708f98d6ca22ba7aeef90c8a0978ebae9603416ae18978bc4c528b01150962a3de1ea9816e17bf08c988c0a7dd982c67f1eae65c4838220db2bde1676ff2a78c4ce7089b43bdeee01e5cb107c3a91085169a59a1c55e55db6ceddf501cde3f5c21ceb2a343a75c4330344119f899cf5c59badc20618d973ca55f1e55ecb5479092b60ec0fa2342ebd5379ad6eefa1103290830757b953b3a0c3aab31dbc7374109fcf8130dd467c81a894050d9374f63fcbdec5a408dc5ebfbde2a27ac05e3281dc8440bd6ae19cd7a106bffdc1cfdef8ebc844887ffb118499d67afbdae8691277d73aefec2c398f72628d0d5192e8952be86d73da9966da10f213b5c06f970f8213eb9a7c30aabdf6c0ddc630560fa9cddc626cecfdc6e5f22edf3cffa50804a6589831992a299d05b45d67c1d70de27437829c31215df4580f742d77dae416f5063932778d639697df0a73ab58f357b5b9138b5ba8360e61787bcd2d171a1354308b52a42ffc42053aa526ccd9c078911fc44f5aa1194b0ae8b572ad3d31c6a051bbefdc97231f78f6586c4", "a7fc41fea55fa7", "49", .None}, + {.Log, "8479d49bd1635579ec7204ffaf2d44b893aa93ff5be031af0b0acb3ba5cb4350985e5650adb5c0459e2ac963d2d4de7e1daeb511f6487f047a1092bf540bf866e8da9f04700751b3f4e8ee4bcefd34439967df47a93a2893b00d8ae4acfb184d5079d71d4ab9409d52538ca4c61a087bf4fe76c4b53eedcdb68a51d7f5bb4b433aebed0364be86c12e6274635ddb57b40520fc778efbed1da5b34c093a6d06fdc2b87417166f54b7c9cbb0cf290a540f7a04ab05387100cdf2bdf326a1eb0705d29f3995a7fa99591f23b141ebc05018b816d31a9efff5770ddebd54501e7b6e4a345cae9cebaae496502d3c08d4958dfc9fc95fb79a485d24f8ba374951725bc28a3cd221d1fa370d7d0aff5d00ef848856db26bd9932a013488a1868299fbf88adcdcc16e9c2cea57dbb12087e8951ef471ecd66de0f1434b4950e14656aa026060d09ef236ca91cc65c206f42cc164dcfc02d04e4166bab88995373bbc77f3a22b46d5dba4fa5139900bb98d59b6b3c4ee44ce4e586c4ec97efdd407af131f647a407730e65db47f0a7b77826e15e64ddc8295ddbf49645e608e33dcf197616d27cf051c33bcc21b4b993a3e1b6155f0732116d7113539c0a95fbc6e86878d202066da4aad7d546c7641f0213528193cf9ab00282856ac6d5576fc4e78643de2e66da0980b3e1c2dea2649a1d2ca86fb8e85e8a8cf176e000f2463b4bb1f3", "a1618cdea3b04a", "4a", .None}, + {.Log, "7252444ce74a5d34d8253851e9bbf9e035232cb3bc35c4f2a98d62603ee1fc292bb9aff16789e9088e2e831d8c0a479adc9201c853eac632621d713488a5d2c0f3c64196df8d41424c48d9df649c72613e4a10fa1b90a8999588273bd068c9dd9bf7e5ee03a0df494d52a7fc4ef5a1a36af90f270f2c90725b4b36b665c16831db25ab21a2f77e4615b45a2896ac33f5a196ba8fc4837156affd47f625f7f3552018b8eccf15659693048b248d0f7d2f47fd249bfa8c0899d961e77f1a886a34c8132d63bdc514fed7cc4fc91a93d07c718e28457d1a8c83bb73e581ac827fb8592c00e6c1c5dad8cecfe65a4178d49134eee7cee475384c84d173e2e08500291279abb1866ce0d1bb57f4dc2a9647e02170f470159bd95b8551a98eb9f0808ec0c37961a2dea288a9283f49743108639868b460da4801639999011efa8ea23c5c6d61e768f8286ac9d35ecfdfa6cc30b8b93ef6ba16d092b0ec9f1652308877e6cf45eb64eabbf961dadb082efee3dbdba13d7edd46fd8e1f807d808e7bec5745b1d27894c3760181c3b83a5fb8162e9f5441d720579632c239b5a963ca3987fb0dce8c3be9a04fe683c1490630b7cf9badd803b568bc34b9caa670b383fc3791965dcdef775376417b8202a6f14efce7cf723e6e358e11e68187bbcbdee78f4e7702c6e3e54faf213d3e3d9891c6ce497f37143880211b91937e89e8e945db", "8330bb2c058cda8", "45", .None}, + {.Log, "349fdc28d9ba7bf553703df9037a259facd258ff46e9acfbbd298f63e427ef7152a66201aa404e48be3cc7e3629f851bfb0cf5510bef7585515e64cfa85936e78dd4baf83851e1f5cc2454026fef709d748e9f73ceec02118d3a0e1713573cf1c56c7b5d4c5f10090ab95f00f5b538bae1956e8cec157d997599e76275620007b5e2b49c5936b04cfbe0b5443c98f45ec66144d0fb2519c0f9ac7e520a0b29b7f91fbd4e65a32d24f9453e84cd37f8c7691f743972eebfdc87d794e60c3cbbb294e695fa522183902d2a0a0c45f9a7fcfa697ee813cd4f5c193fd8a2fcc3f7858e86e2b1653cd01cea7079fbb5e8de7df4a4960b22498b166199407af6636febf1117d9bea74aea35ee8dfc4d64c2f73434ded91cee5075462577a74bee6cd803c05d64fd92b22215ce88ab8b7230dbfdcb36c9504fddefc05b94d2672536526c5579bb602ed561e47caf99a05dda2e6830c43dc633d4f65ffb888af72845c4552be9cfd78bdd86e11e5f05732afb5e0ff2dfba330fc75254ae2fb608823c82f96a349d3ea6aecc4230f4051625a475dcc57f247d0c6e56f850ce6a4cb55e4f45307f4fdca4a5767c8e6326e7aa86f6dbe2a31def95861ccf88663977537ed1592112fc1ee682cfa1584a1ef98f62eb8d9da4dc2b538543715e4285e653de0b893c0f2c4e215794e877f5f7e8a5207cba890322bb823bdeb299dc82acd00442", "1260060f4dfee73", "48", .None}, + {.Log, "950c5023f76e4a48ffeed94e5f4497cee00b6e33fd34d10af4153974e40ef9fa2d43256518d433c67b482e68fb834e4397ce479f2279f43b607b5e56429dc07a2c01baac389614522b75e0dc53142709fd92fea101c6dcf03d9c2eb01f77d6fdbb224b09d6e90a1f606b657705e02d71640f5455ee23e5ebb34b615fa5125b2d08ed4c3f6f0642b6596b190376e8deb1e6cefbb6b1cff4306461e42d620c03c42aa0ccc00dc71d569d770fd22749cc9b24bfaee8f956a6fe86f1116331a57c4c5a731a38a2cc6742aef14c4c6520501dc52b1534aff849f9957af0d277bfc3e5a6eb231dc2354b5eeab117ead3388a28c620066213b23ee9e59c2f146520dc57479f5cc9c6c11f2a085dfcc1c15acbc9aae33d210e1ff43e50025d35340b4430d23461e834771cb5ddceda0805145fc0cf1174c32d646789cdd040f897f3f93107627c5dd65342aa3d69656a4a5f3557e031312b1028453130ae505ed743f7d382fc8aa5a49ecd1443a201d5475a1629594c7c7c75f78f9ba29c698eb323eab2fa3095b01ad96cb640b9968ad67db32f4681f4f19ef2369a194c53e586f31f977c26807e364076a318e719a9c66e6a7c70c0254e55f7564f1ef5814b0a00f2a3dafa1e3815073f05a9787555496aaf7a755963ce68b3e8563a0b91e1db3bcd09a9b560a38f2e1ada0aeeb846d36b89b4dfbe782faaa0b23c3e69f66815e2388c", "1506cdde56deb15", "48", .None}, + {.Log, "2a7c2131443573ae5685d829470ddbe35fecf951cfb885d819bb9e4607576fb25cff860ce4ca76f2629363b9a6771a236e0d8a3103e236df805c3a93e15f780479d3a6b78ea59525fcd385f36220406d6385f97a3ef8201aef42f05e5487cd0635d6de1ba65b6dff4be90debb7d775c03111bab585bccfc6f64560ca9a0b146b1a1267f5c5921c9e2c663bbb5fa87d9b6418f7ea916a553209117391e66082c52900068904d03eba77c650ec6f53ffd3b821b4365cf32129c3bc5d832e4ffacda70d774a8c388808e05b809abbdccf037a90fe8e9d56b1780b1afd6c4696cccfa9a6814260ef0dbb2d4ad78cae1ef242934339d6f67a1de50b6b79598eef7cc3ccc1045dc89f701e6d1601e778c091b31f4e9181b38e5a51094ebefb29fa4a9effa59acedc634d52c10352f31e9fbeedc6240d61cd9082879c1ba57d449f89e4191ad3f91b825b94fa21a1aeade15e36eb5ddfbffbe18cfc49af81c9d72a2cf0b08054d16e3413d70a7b6147406986ea50c646d7b18353ba64cc45a59f0092007c8270445773af2861c2c54d652698d8a722b46378f76c916397d23a4b0c992a85b93c5a59fc91d365f2ff83a20e50e33f1264c485cdd264c4a820b3f0537111e09668833b534feec2db558e47838f1f5e2daf08a57ef86f9ae4df57f9b9301f341d44ef1f90d744d7535e109161fa92535c5f3164ea16a91a49f326617c888a", "838f1c69433b3bb", "45", .None}, + {.Log, "c2eee8f06e4c4c2fc29b936e186b7d1453f74b180b5aa1057e288fc69d3796d4b301976f04f3e421f5401c9d6ad2e97e929184ee84de9abbffa6ba4005c0275cfa0c50493768b73a9a3331fae1cfd1e641f0cea4579dba7f8d9d48a7c952781254bac1018c9246f5daf91eb4b64a8a4024e720a689b3d3ed2aa5deb1ddc71e31240c397595718f2b95395efaa64b990528f0b9f2d60acf08060892a9db3cf7b087fab2795927e2a3d62f13d3f78052a4a105c617374a6a1b51d2d6872a5f745c4913584abb71311d451c6872cdb648d29cfeb52f426c521326409bbc65f42b759d4c8e0b78db97a88e9cb113c404171577fb435a2c627fa4c6c06b707f01a538cfb8176fd9c75b4973ae43389cf2eaa887c3f244ff523768f45b1ad37b33ed18e135aa446a4f851d3f7025d5fe76a08d3ce4f42beaebdfa7cd2290a66ae4e071563feaf63775caf154575a9bb152d398f20e2d05e6e46c94add6bdb69c3575e86db68433f1f522165b0a5fdab196b7e7aad9348568dcf0d81f2cf98d93d87a58c3250fd4b2db0b608a938093a12f6583119eee17e980f0aca6bfd0c314c13b6c9f00a9d5d9411bd62e0dc42237c8a759b2e7f33dafaa8ab471a7be8c0d6d34a57ea4befcb1b271a849562c202d7ba7c7c63d2b0ab6f3cc7054afde993a087549466b3180eaf30fb6154812d2ea3bae201291872923be540a406a5fc75cc5b82a", "bf81d064ba74d2c", "44", .None}, + {.Log, "2f2d74bff4eea3e132d5afd1951afab6e57a049521243345ca33a773a7c953826a68a0ce9c52c4d60887b8ddf51fba6baa6637719f1cbb2b48a51cda8e45017fe906ba63fd6ddba2c7dbe66f7def952ec672a31f481b86f23dc27d6c76791c7a1530f91484645686b633147a1c3e68c9f39bf787eac23eb147586518f2847a060187a8fdadfcfcd33569095afdc4102528292556104f4e3b34d1d634521f800efa48c6be55fc80da38d605e9a92e817ffa90244faf2bd504cbcd0aed8cdfbf3426c9f3a5d0f1a83041a3f91b03d6b760197da0d925dcfa6ad15af638b35b2c4091ad4f1cc14e2705210ee01e7677aee15ff5dff527033167f7d2b4f73e5cbcae2f9f4cbc32355d8c18fca4ee696d0f63ee18981b1a2842c8bd6dda1f5467bf8848c2f85bce2f8ded6c2924932677466cc3e77ad3d57d38a46f468ea4d855c321926f9d0b5a7700a3aa4fbef4c9e1560e69d77012f00f7d8881d362614d77143877889b6a82660c8635f2a335e5292b8f55d7f23f9ea46a426eb76754ba3c7fcbe06e914f10ef546d5f2ab3665d32dd8bde8e5fdb9cbe3a3a0346c9c81a6f1b2066373bac1b6c4c066c6199faf2ed639d8dc4d7d32207aaff440e9a1b68b0e94ff89b76fef2ff1fd8bbf5f96b4a8d2809b455e2da3414a9b9efcbdd51f3c933065252b918e90a5d1a54c7c14a110d65d5ab9ac3d6342c5cc5b1c99ef637128a1c", "f465d4f823be2fd", "44", .None}, + {.Log, "a665f18b9ba0b89d4151c12c36ed46d6e21e0eea3c8aeab0cd03e11125e7a47cbf055e7311284c378c1687687bdb6e7b734233e303b0a09f8c0bf0e989ddf9c79c615fe6e81fcc517721f1bbd2d4fa784739cf3e04ad5e356813ba4ee86b3b798e1d3f9f8197c84942f2b70026524e55e5e8e1a425f98c97aed1e390b958f6526c2d99fd1c8d0e66017506548527488f0616560375c1bb483863e01ae409cbc0f9c38506e5752144af5ea69fb0081d8a8d3912a3bee5840d5da8f03af6eff6776396d3b1d56bb8e7877e8bf4817cbb885398d3328d32c78d3da90b84c9f792253ae29cc7fbc91911646d067aa61b61ea95ee5dc7eff7445cd8629800850d00e4f839920083e69418c1d6781bcc06bffe61216ed2e8206882470bcd62d41839524aacc8043a1a83f298c59d93f0ba6daf0b331d40ec46ad472bf25dda20faa444a9f13d1df6c6693988d46794663a9ba669371c70bfa6e46c1508150878be0ca373e0e6f073089d80a69d007544b3c65ac288ff039ceab674f0abc6e704c1817d7517f8aa555611a9abde3e81ffc1dbeb430f0fa11b3f0b71820567d6108d03e7b688ed6ff93b04c80779b54e83bf9eedb87ddf938e0b5f59308016ae1d88f883515509e8eaf9d335fab841661736d5736bf14b8ab05e8a70d8f5428b882d66741aec9acfc23801eaeb408d4bd0376cd1d8fe5d840359e99e867709d440afbb0d", "95104284ca0572e", "45", .None}, + {.Sqrt, "5b4f80009e280ac5a0a517e85e0c0820d042db9b94cd25697ed8245989d2e256f9bd60344db679a0b440f3568237e7780c3417635cae578e2f5af18ecb2038d9c1586dbfb8be8a87ba6bb529510f0a39a67775b414c4aa2859025c6858bba8a855c473d28bbd738edf835220a58514da7b128e6f2c05b3ba51470ce4a220e38c45f4768145c4d3e5b2e3e8f0d14d4d4ddc6a793af91127d8b9ce6bf2efef43e838195c11d09422dfbe48be7dd6909c0c2742d64237b4739c0a1055c2bc3c95984a2c5d8e19bf20465268ed0d6950321e5c29bb1966e6e20b10ddae146049107476a500a8b8363acdb20ed23fa22201fec4a58bdefac546e9efc709d5f283eb4c13e6fd33ef86136cae547ccf0397eda23a5aa77d8cecdb946b53cdac0da90c91c3335445c8772afa633ce0e42bc90bc3e9af61aeabbdc9b3ec9cb8819f5972e31fb54fa812428ff80c8d73732e65f91ee2cbbfedfd2b806145ed358285cc959837b96ba436f4645326f352cc3db03d537283b406f1fea58d6bee259497ee450d21e395b0a82b75683d60deb5454824f92f96f14d74ff106484a2da83cdb8a1e450baccd6524db094fa9f68afa27a926dc53fa307ea667cf1b5f750fc74b7a9e096d7865aff27ba8d0a032000068321abfcf208637269506e833c6e7a05a92a40d3bb8256fedbdc2c4bf37f6eb57478cfbdb9725693c909ac462600905165fc81", "0", "98e3f6bd90f952354bb3ddd7ffd5c1264f959438d4068d45d21453ae10dc3411949fbb2f0a650e01cf2a2bb3c2ce83766650b5f12ec8ac24bf736ef000cd46dce4895fc874c20b92abff3c574dea45f3b58f96850b8ff761d420e4647ac3a7fb6783097346b046330c67e1c177deb3f06c837fdb06436d41799aa24202416f275466fae7cf2471fbc7c437abdb41c088a7205abfad033c58f885fe92deae08ac6589f8311d094d9646e2215fb7ef930ebe809225dbbee762383edb0499271251a742525b8a37c4390b49c959b313224ede86cc37845827058096cff7f453850ace7890cf3b98274aa40bf62460dd6bfa29e361075161380a53a94b0e6774584d", .None}, + {.Sqrt, "784475be346685f6d2842bcf74b2760bbe17daf5fa91232d1036cf942962cf1ad4ca9c14fd352f61b551ccb03e834e618011bd7a8fc12f7e083ca8e8f3ea65b61f707894c4b9a56e0d2d4f8317d783270fc1cd321d9d7312d02e7a561c62bd3b33f0f277ea2f2a0a45f3d6beef2eaba24f78648a9e6b4d7102ece74ab9da9afcf5d9996c7e557a78c0e795c781d90b014714c35079aebb91d56ac3ca9ff71ecd75c425d03d28708e8c95f6692d6e56aaef9be79f08c99ad76f576778ee0fda220109006f0c052a56eb6d6837e3ced2326316ea1885465d04634e5a8e0d9cddb816b8a5c62e138b2444c87587011ce57fd443d7a01433dcc973eb09d90fb74be5577e123fac1c402d7fd0634dc6e1e0e64b0caddbbee7bdb42d5bf0d36a86fa888ac00d7db8f3bb4b1aecabd4f9cb8bf50b2122324cac2734c2c54b01e0e9cf88adce17e0bfb1463860a67f14f6e003c01633a413326746179776b121478904dd4f6bebf352d838763803aab7080765c784fada88357db308fee232c5a4caffaa46c9f70a5b2571e6613d02ef63713b08dad00bb1120c86e062c601de05869ccd27da6be1a374637732640d540cbcf8f99b34f2850c24df6a6df1bea2e8ff7b25e29f3249a6090aeec77a78c0ed95d64037461547c222b1d3e952eb24abea48e1b1d11f29072d6fdd9940bc7cee295230d909f58ce351e333f38fc26747f2d47e", "0", "af7766707fde36286bde65bf07ec438f5e7ca9da1622b56380e5db6f9c491cdf35dd82c4c6d2460ff5da3fa691d756dc82edf9a6a684f5c5a21dab6e7550772842b6fdf9dd3e339637ae0d63a9feadf38796bb8fbd24734cf086ec5cc9417f1562099c0fd2416e8553b068ab80a6e09ef706f452450c558d2f5b0cac3a28f97815abe1c82da88b1f60b1e279bd18f547ccf796e62da95b5cb2b26d0c2c15e0db1ba45408b04ab1f0aa08b17d9d8ff421e14512a5b729d5dc5c9bec4f3a4fbbd58dda04c921fa8916f748d398f7df6c1b0a75c088351502cb5531413c0d79dc6ea9ba40e7801f2659cb26e6d2f407cef08ca69581182b5a4c392d0f4bdc24b14c", .None}, + {.Sqrt, "c52a7547246837375605f07e9f08c03466a00650d623b03ea220fab1176fb66f9fb4ae3085ff8f22186c56737f5b6b246b64954ef5a817be38f141cd0fb60ab79649762c56e1ae1ce726a1d8aa8034f378fccb483d2788ee9797ebf3d6b9e48f34edc8c9590f1e31617ba46f76ad446ef4170c6df8816f8390a609385bd9b5b533bd07cbdaf5dd74f6d1fea8bcf3aa0f6eb6022d9858abade760704f9fab3c0114c8ce8caea6c92e5116ead5c0de0d6fc9aba2bd0ba87cc277e1ef98b82609664eca8a982202df7a2f6faf673d80057aaf02a21832eaa7388c724460dbdde4202005bca06b167d75b62b11c65cb994359abd5726d61a945f381f383442c879e6a819c49975969ba0976be437817b96414ba0ddb72f1c22b740622fa9821e08eebdbab5149d7a45e717b852d26cb2d198027c558395630f53ace1b0d53bdc8a10ce34931364f0e263aba1e81deec050ec630e6d948aca11bc3e76484fba6d04becb593ef2b5712490505368df141b593fa999ffff6264e045aa19bbe3412b6b258510f8768f857410ce361e109df2594d25b502f1a4b207680d92438056eac26cfbb4592ca73327b6da5117dd7849652c424bd7bcc910362f0def0284476d672dd9a1b99c02d25c117eadb1db0c81f149d77bd0243271d4666645392b77a3a5b1757ad55983c38e0aa62276c9630be6dd8f4646643c5bb23057158a84c87cb28", "0", "382a92db44c28c4afa1d4c81984bb4ef0d2bdd576a5b78dd2ef0a65faf00f0417ceca64bf12282e6a445495cd60f77e7a33b2c72c321655095752fc07570cc6a7087325231e42888769eea77d8aa2dd442b1b84aa2cf493c739bf54263c6a13aea715a5999957a125bf17cb2b9e390f99a8a671986a0491129fdf1872474c911adb8f3c2854ea0dd95276bde66e908c777744f45436c6a5bfa39726b551e16104139781f2aedd2b41d2f812861f486375f0dacd7648f8ea761d58ee642635336c9226ebdf772ecdc1ff278627a3fca2671b9c7ddecf2aa64ea86aa9c458f94b7e7f5888e51f6773d4ca31353777a1aac022f2d96d87beca682f1326b537df7dd", .None}, + {.Sqrt, "ba2e31e9f1213c5a8dab06a0ccc886584fb62676ef7cb93fc64daf344d960bda75b2f5b0ae26f915fe28c2bed1eafd0a4af9b4cae26e58f5d3ec3f5028fe37887bc81b7cd9acf84593dfb92efafa461f0f7c784e06efb2083bbb34f536cdc64d678a8bbdb5beebef96a2761c75069f80f56a9d1226d2022059bed4a57e53ff3880bacd2f5bab410d49ee9038b4893917ba506cdfa21aa647ce6e8a4acc5ef53c7d8111b7c77eb2b3d3786d835c85722872f6d4516f30a392cf1af6f4c81907aa921850d73289417597a5e88e8b67d8dc62e5b9e9b10445a0978de92ea27687bcca1bfe9bb697572d9025a654feaebf8453e6daa1cac471d61f10e44b2959eb4fd1a4e5c92b296b8c25d907122bcc44be0fb4eccf1fb1204a614867cff748924af2555a3e6a0836ac45056987e050f4993d5362071844b140031cf412b767a8963affbc0cfd2f5549a4053389bf218eb404ffaefe18d04644659f1f7ba65dc5259aeb7f748df48eaf83bb0765981fc857e51dfa89c455084ff31fec6e49df94034e569be6f2f2296c219ba00f7072c882eea6f746cf088fa762ea50843e04ee0ec89ba4bd29074835ad804854c3c673ecbd34fb2046d90e23673677cf856067cab330fc1bc2e2933c7673ce6117549d1e011e3913d52b4b1f7ed9a6ff3f6156b1d06439cc08966988c1596850d8210f5b16721f81073897d3fea0bb1cef758b1f", "0", "da5115462625e0d2e588c80fc5a730d03a189fa32f607a7bf928ad00a19fb2475d811b0aaa00e31e9606e35fae2ca00d4a9de32ab5fb3cf75973ab7f13326e09f5c8f57582e1877ca432ce367e73e46556f672413b379a0a6fd130429dbaae1a098048e5fd3d83e67eb50f5e7fa158fd7d699fabd168332b6d3b72ab9d28d3ca38bbabcfde8ba067df2a8af224208d2578727d8647839e1c05d622ad5bba2f0b07f9f5d343bb92aaad4b0568221d25dd3ae63aac5d2e192ce0466b846c7117eae8add5a1fcad24f1b0a804efce9fb104f31914f93169061a04fe4abdbd5f7912d0f0da9e645294df9cb1c4222753738575dc457701ef947f4a772c6f098f31f0", .None}, + {.Sqrt, "ac54862618b5795dd07105b8a27576e6e950558a06c756ca5e48888700e75a96d18456acd90317e434ccd5dc51a8501698e6481356a7094f8f9512b36f8ef745369dbac4a53d2e4554bb4eec955ba6f04e2671905263f7c3f6327f63013fc1b45d4256bd56920dbfb6e8c8f7bd3021bd2da6b0963c9263ec6df89d95d775a035d33d6665f03877bef0694bb721b6197470a1b837ef0bf834c32c1c8eb3c8594c584274bd40a23b54265dcea65937b192ca878f64900905f8bc6c58301dd29342f19ad8e15c91a0f0c58df546b6ed61641b3ad96e0c48287f3ee8c354ef1d6af932d32f73c4b075be04851ac1abf9ff793164eb3c8bef85bb8cfc5a0e5319820c505a718618e6ffb6dee3c70c90fbff28c48f9bcf191f6707f808b80430d98df58387518bdf3dd8bcac83161b02604f1e8c81fb87f0db3300cb90a3c01e4c184b2b981be7b4795d1e5437e16ec3ecfcd3f83a0e76b31fe6177c97ea3ccef9bfa04ea0412733b0b3783cd4cdde30804711f139bc19fe8c80a7a730a76c05049259b02fb7e8cbd8fe41d74ea1f8c93fe2b6073d47199ec832f6f64742a04e364b1d6bfebd9c06c03eef02a04826f8ba9be5c53d39c5b8c9d0b31f152988f1e140641455fdd2b49139ebc61e954278a6854199ab37a8d38280e3ec14d9467a7d7f3c281d3f4502f662e8242289f41b0272ccd407600a3fd3375fd80cbb84cffad767", "0", "d20a12228b69e0cf42300e70195a3cd2424e34759da9b590095236178ed764eb03064d2c770ce0c956e8308175cd39fef8e3cc00fcb2bd44be8f0948fd9ee91986dcee6ba4bc133e2c3947b121529eedb2d7cbea312b4387e8c2e10d0f2479d4eebb5b492aeac9b5833a00b16127bb54b18ebc1fd26eb662dafca515adca06707c3010b3a30315e15a6252f1e5a15afae7bc5f34f27526904bb6e46be299bb6c6cd75a434bd8892061409fa5c7e70d9708862f5f10fa732f4f98ee44fea997b8c6adc1aeb02d315384afae2bed97adf34b9808c4e65d9c9fbf3edc06d5bc281201bf73517ad1935d74d617077673db6b84902ebe3e563e8d3e9ae9217ead7f06", .None}, + {.Sqrt, "83864c0dd72376e5aee03f994670518575d286848d372150a6ea008fb31b7b9829a1a8b8633cc635ecce67f6fce80ede31f0328cc7df1f7a7373bb87c4e66cdc5344eae7bc23b0524b23e526f79c88b2c001032d05a33f418f06c8d47fa44f039fb1b32f9e9f63ac728f56dd57e0169433ca70ff70ac2246562d92e49ff56a6502b853b74fa941b73182e978234a0e206dc96ce7b10b0d71a8dadbd3cb18fd9ffcd9a6cc6c7e73b30d93c6f1e1ff30b61c01147b2f2920ed228b5cca91163474430deab638416a3f724a87810ec395a6fa6aae7a545646f38f96923125bc69bf5d4650d9fe3af5161aa246aeefa58809116eca19266955b01be45f3d14ab56f86283a9f63ce489d88f814138927ed81b9b5e78cfe24bc67dc0393cf9f7167ee3d211b17daf039a5fd886dd864ffa1024743f7f8a7b3c6f08917f2c8565e74c85f9f2d1389d38b9566ad6941f02d2d5e858100352a4de85d21e773e943bd9c57b158c62a7b3726bcc84b22993fa3a58d3603c760b7587cf261105df1ce0c54c747c104066a0b1177aea6fefcb79f7cb520cb046788fe6d5d8357954a466d39a42c865f42541e33688580abe5c23fe9df84148150e67fa6e0c0a139269c22191394cdfddf9ca4a2585299578241b5bfa567f8c850407a875f10e8ff02c2d36e547cf42e3a154d27f3c014c6c72387e28111183155bd885b246ec7efcd388261e3b", "0", "b77ea342419c48fdd7e2b32c088ce5fd9849e35834765a93c6068e2b7810cca9a6ca683de0d6735d9093a9cab09802b86383365746bda2e551d4b101db379ccb16f8af44ff8ad7376f9ee2cf051ca82290317885ef45a17a2bcc559404a62d4cee1a3b2daed8c55d370402e0ef226455281feeb735c13c590c2d6a4cd138c0cab5b1e8f40d55a59b1e0364bbe193a1a30f1b0acf1adc0295d3a17035deab4058944b9bee2362ac227726f3326acbf44bfeb885113cf9f6e07df8be9a4c1e4ba88c4dbad10d289bd1b5fd4015e92ed3e3de0e06bd3bd555b2c3d207e4c7127910f66345614028148b838a3f4fda3f8ad77ab2272498dd98222a5d4f21f06b4684", .None}, + {.Sqrt, "c8fc5ee304c172f81dd9136ce443eedc051043e6072e2994f2f7e054a9ee7e51ad99ab62f39a62138abe962ac333856354f604b492c8e453356cdd43d4ae710c16f400be7e07e393de3052ad0d627c544c6c89e84a580a6136b3bb97f10060ca2cc39e6a80d793823a2ae5107a1772f46c80a90fe4ea892f1cd640d4c5953a905610d0fa8a5f491319905618a8c00291facf5c0e67137db3e59304a7c59b250d3eaeef8a7b0797d77ad49919d98b1fb20ed066bd4f9347bdbeb3f8dac578e979cc0932563c8db332e13b3f5f4241ff8c39f1d6b47bfe3738bb9bd7c348d9c1827225557fa47a4be6995c60196abf291808b9c1e26eb1b66e69497118485172ec144abe23c8d061c43d5c2eb5acd9795f9cf7302bb0e605627474a98b461a22727c3cef52d78b7ee81f873d6bc8db1b85a87d2fbc3cda9c7806935a5ddb7dbe1414f74f26e4af587b57abd0ad5cdd2ef2a8c55e53832e800bd58e8400bbc43e1be97c889e1f60df57613de78f40294841f39dbd3c1dc4c98de5298c5147205639201f6f3490ce09e8ae1bdee34288cc2bcb78574f03297ec6651621c4510476c446c424c32998c2d9c661eaa7a43b80e381f16b2c9f2767bf7cfde567d9cbe7dce981657b8ed24de64b21cc796d867e51fd2867565746e856c60ac9edad6f696f24e1aec2eedd5e469e8e1648b4bb836144627d3e5c50c2d77d115ba82ce401d4", "0", "e2d4c6409a2e7e647a3aecbf6956b917879df84de6c112f3dba7718cd3f8b178472a479ec5101b7298ca4fe5f9aebdeda4f12704aa476f4bcafbc0ef93b7bcd7913693f6dfabbe33f24ae0d465b1ccb15e3abf7a5bbbd6c6c54ccaed8aa76d7da21a597dbaa2cfe7e191599d9eb311f5a7a970e74c93da0600a6cdb0feefd222c4ba0d480cbf4c93f32e0aae0cabc8c4979173e582adbc366b8ebd870cd2192d1f8c74483f5fe74296d87292f922017a9f7240f6234d5dd9405cfd2194d42d8fa44dc8a999156605b203aa614bbe08c4cd43875f77e0ed1ff5a8b18b99ae2ee28bfda10b75288a862ff74d41e816725f3d9d1e51c6ae8731a9457e0ec5896d1f", .None}, + {.Sqrt, "3c994e735278ec5fbb12c529d9e174a41d7d7fa9baf3bbf456d7f05ede960b8b5e45fec7bae71402d38ed14d861ad0a12a0c5c1c50e3cf907efe51add658247008703b8a9ff80e8f0dc4614ccdc93e72b7c30a2c6189f0da63ae0ebc8e9812db4bbcc9843c5d7f6ae8bf4e1655cf0034ba73a24d4d330143dad2f468cd7f91203a0ccb1c1780ea5c841efdc964c54d6a5f949abc6720651cad722a38480daec50a21e218027af096f7df9cb203d81d96b22633b448fea07bf465f49b8a5561bbd598cccf38b4ef62d6c773f265947afee124ff3106bae85304cc5cdcb9e1c15dc689d11bba0ee73080766b6f7fdc0e0dc185054325cfed14639220a03a2f3d2e275cd86f8c37a33edc07c780a0ff60cd9e5aad3556e75cae653c1dc4290c9983c39d61db374657a8ba8c2e8e369d2104a59d9e828fb4c35ca96ed35ebf6b2b203a7f0f0191caec342ba517ddca8f6226c7232d3fc24e06e50a17a4c4ad1a084aba12e3ca8841db6550ec2878a98073ebac357cffd8419a2b3b1b04c4aa18f4c14759a74642fe46523b791e7df731293951fd3e09116468605d4675143f2b5c86eb7a03bca1495315915b47250448881609a17ff83c0b1cf63ef4f29e6f8ecef7a38e21e3aec99da571b0a7ee73d9a5b131d191bf5cff28f68d538e18d7ca97cfb748d54c7165d61c1132fead3c1f48ae27a487bc3911d3388a1493d5606f9485", "0", "7c8d6bb10c87e2dabff3598d34e22c884b57e502e70ae41fa673c1353eace28e27cfd0288cfaf58b823a50fe66230556ed60752b43ad050486b616a62a895bb32ffd27a3b027c9658688f7fcf60cdd76d85f9616e0ef90582f3db937592593f66e6515a72bc69200524cdebf8c246acbc5b593cbc0b50bafb388f655f88998fcf19c85a13d8ab90b755104a47707aa87968e182ecfec850f470dea43a9eb365ef07e667990018af6a3f0fbebe2d56487489f044d53aef3e12b5bb9aaf6e577125d1ab60ab7b5a70d2f014a78a0a5846d8a7dd6bb0042dc57d444c0954eb96c7879d16db45ef849efbfd69e0193ba4157db432cb834e3ba1608660159ed2db925", .None}, + {.Sqrt, "104eefeb133dc7a174495e1ebd508e18b4e9054a69ffc4f3a54e88452eb24ca3cbd2b13b975f7090673f06a6d63a97ca284ee757b73c9f6e80d7832b0e87bf83e068b557de1fdc65750870669797f72a39ec4eee90aef73bdab8dd2f4f48e628622934aa1fda5a87ef4127167d36da26620d2636ffc5cfa7ded798eefcf654e8434dc2345b60dee00c1201eb8ac397dd7b84a3ef337c6a367f414b515956ab572cecfe826a834eae8c27f5200a90feacafc22541a3021c30e2fffdc8d54a26ab07df47b681f9b158ffad96715a3ef5f07032fd0d2673fb01e401f8d93e784457758bfb5cec44afda2e098ea549d876b36094aa5472a5214fae9d4262d67708ac97619e5e5aebe4803a59c0fb56ac397157f48c8b6eb7efe076670f5ace4c23998fc62fc796aac92dee3ac6df9d54fdb5d8f1e6d24a09c981717c2ab2fdaff16da51d1035c0046ce51f20ca2847681cbfcda0f4a2073f1db7e9015bad004d3d17a2c3a94a47394c364eeb420c063929b8a61535c28aff6a1d46699a2532bb26c63b971b67a54356eb443213d8baaed51484fa35d388b691917cd9005c05517c40ff4bfe6b17699eca0668d9365f47f7a57cfe66452922beb64988136cb2549e9ad509549605f2cb993e0e111e88ff5f1e503812142f941dd5794a59e4a58ac64ebd2f4af9025e56157715e4bd3cdb9185da847f2424705948ac63c1324f807823", "0", "409d1ef8263f886644253c26d860316291f647959e81579ce432a5fb94249bd04ae46aa623b6695aabf6ea0179fc3f6d6fd03289e31bcc48757862a57f0c6a73f64d71dd3dcedc31802a51887e6cc4633eccc50701f7ef7ca55c1439dcee060fc4b68708145dcce10d281b0ff07e35fd9a77df6dfdf29baec118c12ad1eb8d53cac2d0d059b3f345f7f459d49cc408c8b341d67fd7c2e729e5c09f699e9e9ccf3f944c312867c3edaf528f42059f38a231696acf72bc88d15efb40eb667ac993edd01c3e91ce8bea46e408d4a53b9d0e7a1975efecafba1986c796e6a7f014a2fa6bb10479d690ebe96a67cb18284ebf3809a95206d0c935a288688c6b75b562", .None}, + {.Sqrt, "2a05aa91ab21d6b289ea02d26df6a15d745f6f93114f7a74c4f1ca0cea1ac0d663b8c9da1ff4b85abef3a9c4727ad4629828c3006061e53d032f113bbf5b9437b9f5274b56fbd2b7cefb98938951f05d092b89665d06cd25192598b79222ebec71a398aa36cdcda798185c7373bc058252442a75d7677f1cf6859fcd0d040f525729d4dd3b2a8c7fddfdf2ce4a5ecf339a8486039fb073961839c4bb0d5ef96e2e290f614d4eb675db08e7a483fb3b712ba90c7bbb27c63afdfae5bddc73eda2086268708d82866957d9f68a09d64fadd1fcaab911aaa95e7c964d38a733bf35517604e8758affff2b816c71d0454f6a7298f63e1a253db30cad3c74faac9281c1bf8df16693d09d8f6b8f6c26bd8bb1ed32b8befaefa6aa0635e30838b64418a16806b90719a1bb9c2f463e1fe63d959865254a62d9355e9561d9975cd7ffd77f66121ee6b0a6d5a45001bf14fc90d3bc959ca86dd9b379d1e0a63b2c973003b72fc49fa4429e70ea22a26a45b878ca922e472dfd0f1e63538f2df3174a3ea5140d73e83d5ca7caa001a0078e862db9f832a5445dd3c6b63ee3873121ed870b64b086102101c02769bf11622095d2bd0fd58961cfdfffe51535b30c3f1e23c854ccdbf708570463b96eff7cdecb0b555faff648aee47253be091686ed846f7d0cc7a72c421cb2b2a102a48710b7992f4f2960dddecd0a5204251c1f132a68e2", "0", "67b81b8b4314cce93aba614b7b72bac80fa1ccd133162f1211fbd3c390db837249873fd9c4329904edf7f657f2f8e78218b2eda58eb2f44860dab5ef8cc15e7a19e1f2133b534897f22b8f0e15f3c775def9dfdf80a6c8acdba0758e48727416a5cd85ffd513c3ef1fb2f11430ad9519119797af8f58abb0eff24d71e0ac77ec823beee920e799fed15c6f669d853b9be6579eb3e02a02bc2aa7145ad6dc2e88fb2d570fa7874032685edbbcc90f85b659c280e35e7aa801272370e3d7cd8aed7c1d1c0b2dd17700d2f8bea949b930ed3f7034823c4960f6e7b1d73ac0d2144c93f006fdfe6eab231c288304a186a6e00611dd2daef2522da093ccafb776e570", .None}, + {.Sqrt, "b66b3bc4cc0ec1e4692faed6daba2cf295705f3bb5e559e3a89897c43bac347a75e482636d11b104551d1bec3a994bf4901ff36b107310adbf773d9ed2cdcc6c44769df6825455fa7fc9dc6b5b3449e835f0d92fb025d8c3429c4fe7e5c94ff122ddebb7fa579281b62b89f04a288f2b3827c8ef54227451d39a2233397a0f2a1aed6921e0b6f0814209fdfc158e2b546e0b8104229c75855bf9e681c7f7afd6947c57b7199c557a13b55b1097b5e20b41aa31bebc37dc924f4b0105bc0e08661acfadf5645d913d22d9e7964a61d9890bcd6c24f7769f7c5eae5766395ff7f04120adb3e46068af4cf84a5b5b8f21c55853e205750bd016b49759c5a421b2d13c885a4384be17457c65a212397701c1e2fe6b1756b058977d294d8fd91225ea9832fb3b1d33b9b588940f03ccc20d080f2b3a90fe9da9f72d1d6d1b57e004c4fe84f1e5438fd6cd3c3cbb2c52cefa6355da670aa3611f2de99942a4ed4b659773f77b396ff364930ae35222d8d8849f7ed70d836790845f00e1d5ebd2f937aa634cce6c7e74cf9681f68f48e2807086f2f0448a6a6b065c5638f9cb0927d862cca2d8d8d40453f90d4f66b7a8433c6dc44842eaad2bc7cf30e1692fa877100d624ef7a19bfdc029486b76295dac2a82f3e395942c60976d2eb7fb8c658d848242610a2160f3f61c1fc7914d9db010de777ae45c97bbd7a8543e5a93bd5bf7e1", "0", "d8199d28b9d9c41a4fba211140577d49b8023f57ed7834f35a18cd4a2ecc0cc01e7a758db0b471b93920902de53bf3f3e5404d46915b37a5398b8f4577cbf92054525b7369447f0bbf1a2a91143ba0cefbccc9edf0b53d7c33ed6fb7d4c3d7f6be2dd68f2d17d99fc7f741dbda35b795137a314d7a34c00adf5ae05d5e9120d0d647479abe714f2ab105ed044758d49862ba4fcdca38b097a1b1af3644983350bdc81ad73634341409f0f4082a1956aa7fa1ef3ffd031cc710ac2681ea4db3a67ec33f6d88a180aefb2ce7d2070a0a45339cfe8b6f4d3512af26f7d8ead463ff8aff70595b72c0bee7f606f85f0eb74d9ec711b4100e154581b9ebbe7a6bdc56", .None}, + {.Sqrt, "5833b2adfc41d68855f89dbb4483ead83e7a7078b1a15a384b0ad34138a087c90eea90aa52bf0b99c7026946d2af6684df6e3968c6f2d9629d436cef55581b93cef4fe949ecb7209947c9c0101c61f560b62f62af651d9f8e70c6fe2e1cbdb41c404952b6e7033d0c56f034029eeb4b335f0b191a1da8160be14a22eff7c76f8ad23e57ef370c6682cbaea197ee1b9795263b860cb0d893dd01b6568cc2ec02ef5f2c950fa1615d1e3942567c740282cde50be3a6ee254afb2d4fa3dfb1463683a78dd598c02e64604b0849eb6eadbc8dd0db6a98601682235f95038f54fe47b22220791a313acb3eb03d63b52a0f5d85686f42d47e5802cb90d089064c7d16921ffcfbf849ce467434fd28308f87031d7f4fff254f3f1e7e51afaa6f003dafc1f63594e07d3c45ab184d065dee94d39c9c416bb84a68bba54815b66dbf4877de81995a130e38c2e07de1f86c28621757b761796b3a4656094914e2d9102aea8e27f1a32c1def4014a41f6ad00df1a377e12347c25e0cccf341758e4a0e55594cf026ab5fd1d2621e3bb43853dfe10cf14c37b94057d9de41627b393aa7040e7ca9b9a1eb041e408e7ca5ef1c7d97a16f859ced069ce4ec944af82285ea14505f54e8337f6722a7b0a8cdf64649f979097d75d4df6353432d468cc0627d6f094497f57c7e4b5cf4abe5b4860a8194a6a7e8c6c8c00405136970a4ad03467ff44", "0", "9643f2e57fb6dbd52c4b3c2882af254160c9dd1030b5133a6173e5d6305b324a7874bdfffe7f1ffb69574fd279b901b96e1fa87942902d1a1ce5bca9c57cc6d433f1e4d4c1fdbe6f7bbd1f2797d92ef9b73314952a950bdf555dfc3c0d5c84f30fe0d301c7443bdd77a9c7ec3ab9f6d03864e1c7697421b6d61b343db0933bcdd454973d61eabe69e1eb7c69b7393ca3951d4b76ff3f611c3648b24a8754f8eb4169a99b8cd1d2613831d643e5d2da868d0c2c8dfec968b152ef2116500b46651f3d1962df179175bcb9cd67391e4790bd9dc45a44216c9cc94aca3cf7b81f3c0ed4362de3b1d928013758c7b6f0a63ac1c1a2b18053da23a52e773f40235663", .None}, + {.Sqrt, "949102120d36423b31016a433bfb94ef049823c5d6b56954b29f1e67ce6fc6bf7950da7d03941cd620222ff35c627535bae6aa1b72aa000419e7ce82002dc277c75b689e18b9f4543f9a248c405356a8687150aed53a0e9a626d9a52747b739428d06498c1fb55aa9e0fbbf91f767eb9c168b642d474b744f9b266fd795e9b2eb4d99816fce527519b7f9291a70d9a575c2fc6f8f64226ce9df03a6cfd807ce7ba82cc986c7b2e76d044ce622de0a78c9d02e9de7ee1fa5f5cf53754d2cfc601fffa4a08288e4166e0d252e535c4c3cf8f387f4c7c234b32fb8b8012167e98696c86fde3404ab53e198fd594320eaad8c8a7df01dfde780dc0701f216c556240572b1ce7a39b0591ee5f3b2573c1b7b8596ffc8e4eaf875ecc0d9c85c25f650dda231efa8f8911aa7650b5ccb7c086784439b0cebe0595413951dd5f11369a91173c0d7f9b4fb6b20c6f971deb96024f072934edc167c071c18c2134964a31c1b24ac81c066fc488a7ed66e6d1c7218a4b36d5df139e0d394355979a19d5a43e89bc15b91ee3a5d8cae6c29918b112905c70a18c4d921d0bc59da79affdab8a1d8c2a59c3113fc6b29f64628530bfdf8e42cff6740dbbb8db29edb6f85b0f1d19516220c017855388d2619dc1c5c4ab0722c3260c2037030043cff4caaf6a56262f1a956ee9a2894943b27f795dde247bc81bb7f583d273408f11b112ff3cbbe", "0", "c305419dd0e37f548d7e3a37b2ae8378bdc8d0d1066e9b59f260cde8a873320edcf99bdeb868a46ab9dbc538beb32f4f48a435bb224e2d6ca8b24f47bbf2f983a7e2828724b690320b95cc6a08b3a2cb2d96a8068ef86203d8d9c568fe4adb01e7317008f7ccac53bceed2c2e8692e3cb2296e2dea7fa6371f82287000e96510a0cddb7c9fa3d1d0ed99168a20d13572ad7b47cafe974d3da802a86ea8c401c918725d550fe091323c77c2e4196fdf531dba1ca2d9d46679e03e47c527f1867bd44994ea104fbdda8927ea5b0b6346da8f37eb4696d84f2871814aaffe935993569b42654d27f92e7b5945417caa48b0f96c2d78c52dcfa322a4b03428b1cf0c", .None}, + {.Sqrt, "cea7bd41405e39e9507e7b21753e3dc0cbed177529582ee73287202a988ed86e8da6bb27c12880dc7195882b01bd40b7cc28f1546a7f2f9cc8c6acb65c151f4a884ea6e000716c9585ecdc7ed444495294c6e750bf7a0b55025fe858173464efb69b79c1958c872cf29645540c13f929d83663222528c0caa2a6a5426ac5af96d3b88aad26e5721e1679d051ce90e084f2a9d12f8670893429cbddaf1c2573822934a72293e8ac4fad21134583b4c0419aeaf7c79decc6a80233d4c83644045612cfa0c896b5af40e9ed1da4637661b1faa1533ba7ee013f2423911d9fe272c0358db36de4e98ff74aeb0fa7fd6326f4e6a349894816f4dd6b2123ca2dabf6cc2ca87b2071a90c9e0cceea0e914d5a28a51e4540f1ac74e6c30b50d49db2538aa08a4d2e82f1095b1427fb7af6bf4b5fc25535d4e24362e0d97663f09f08e13e16011e238ffdce36ffff1d2da6456bdb25c259520dde9c69e0521ccd8665073e79eb942704b659338b5c7f3f6b1599aa6aeaf69cc6ca69905815890074b565f8bab2b0ce9b76a7fc51b9437866840cf9a6d8f7242857b409dcf14e54bf53808092d24cde6a699c49852e43104d997c0e6ed719e20135351e8306e8a1deb1c28ee89737404b5b38eb82f46d67480705d1af20b3db9957233c9a576df4e5a1e28c4ebac57ac99b28420ca54f44f3f60c5ddccf2eec0f2f487aba9ff559defc482b", "0", "e60214b9471ef73810f5f54683eb6b51d24d8e7dd72c91c4b1cbd9dcfc6c1620e87da2f7c801953174d74b94b85142b59dcfea57684e2a9235972c6f8b27569573efa23548729f6e3d6d958e43b4de0f15ed2bcc919b963f15de93a836b4b18632e4adf43b10e4e2d96c2a64ee7006bfe5b6469e8f78d24cd43450e64ea854d8ca6f8c0987f2bb0c2dc009a20fbafa30aa01be29a910bac97fb71d15b95f2c32bccb1de92026528d0a025d77997a67ade254b405d53ae962645b5027a101e8513c8cc00514457efb39e47d82b2b7fb13d03b53bbd561ecac2e1e897f82c1348d0a9208c905740c0c6312c2e4fa1bea617996bb196b15b6700053f37d027b9a2b", .None}, + {.Sqrt, "564e28041cf7e646efdc4f9e041d75a391ba36b28558ca810e7b7aaa67955f77f0a9979b8bfab587f6d38668e6a493a850c83867eba3148232215fd192277d5bc4982026df4aeb6f7c5ea5d81f3143c7bbf2fa6f8e658d8533f1cbccdbbba177c843b0daf0b670e6965c852ef51eb11f4200bf0ab31644db15be728115a083c652067465ef12f24f4fcc8c394b8483a347d4f2b07e7a84455167a2fc520b97fac39216a406fd312d99a828feac87a21fe9e1e3338843dde2cd444b67f5f72465ef2023fe9ee7d46e9d6874c558cae431e0f8ea2531f9bafc9c1170b37595c71c8da0dd862260c3b14fcc060b0b37267437e1c1ccd64b27a60142b27e7cef12a6cd60088fb596838988627b41e2d0c44ec6fd6b2c78bd8a3d75a6dad7fa115f43f215432011ee88a4e5da23ca09c3c94c1fe3fb2890c49fa11764bca79f5e13099978c2fb23a9585c343009623f6cde6fe2089fc4abee5d4da6b3ac67d0dd6361606ac6ab97f60ac80e4a3981158b2355996c8a7a44721fe92ed8065d9d1e44e090de7b190fd26846dfa43fe51e2460c7e85d7c4f2aff543868641323458dd58a658e028f5ed6141dbaec43af94239b1e5ea5215ca65eb761796e2f1a7935bfbd54aad16c9e5734a53de69916ba6502327495d232c1d1c3aa1e2961034f4246094760faa4dad3099c80dfb428e88851c6fb0416704abc067060a044a920f81317", "0", "94a41aa7bda4af6e7a3aa310b9c887514eb33d6c5304f2b6ec072be71246419a20aa9e0d348eb8b8510b698c3a1007a5e8e1954644fb55df92ce1480c13890bd976304a4ff6e9f793b78480f796a42044a4f0f19ced2b7af4006bb81cbd48cea1b628892bbf057df825b50705bcbe24209fa0ab824e679b4ed9d6b63c80726434eac2d6b8831895472618beb813356791f8a20d003a59af6f732a8759d37cbc198bbd5b891fc10ab636ed36b420cc41ec2ca287659e7ded9a078e7c04489cc644405444355194658817c63b7e9316a071fcbcfcc5d5e3442e4e6c943875885eb923c81279620b051f93afaac87e4d46f2c498ccf05608f1174399448ea6ec073", .None}, + {.Sqrt, "c01d6d04c4395fc22aa0e27d35de007784d35834f45b21362e5467e5ba9fcd042f3a15e76a4a76fddc1e6eab5aecd9ea20c5e9047108908d726cc0277550a6857fd6f42919de69c0ec16733dc06ae7bdcbbc0ddb968fc62f4e42553bfab21957f05b3ede9ec72ae172dde5e4a7dfe8efb11540dbd7302d6b8eb6ecffddc07257c3791bb2d5263e2f8903032811d947a22958e72d8c61d2ddd778d9e92bb1de30b8231c22fedf609547d2f520519518a1e629a2c1172a9df72c278337162a3ad026944eb61403a2e7c87210151239a20489b4ee5d17fa0096062812d18b662e0c905e42f3cdaabaa6898857c690c2ddd0527c3587a0526f256dcf3eca0ac8e97380b410d73542c5e8aaa62f924198b187a5a6730249815097df1202427cc8c14f05903a865eb7c7e02b5aaa7e334d080613043b1ddcf690017bba72d42c1b049788b6252b2c60c556eaf25d4caa7da95f7a32e05b48e75342419ce6a17699fc6fdc4d8dcc5a0367d68fc20c9d721cc0796d1d08fec63c058ff9e6942c5ef5aecb722d9b90d959cea18011f413862b38615e14ca79344becb8921cdf316d384de59cb6b25a8db9e5897565451f3073e0a9a5bba5693e14c2602799813d335ac7e3676cd880caad72d4245aa9961dcb66b1d7e98193a2841f7947223eeaf388a8f99626b7535b3e3a737bb578c49e232f34d7549cfbff1e0c2627e5a42ecbc0b0ad", "0", "ddc4d3cce4ebfbfa0590780aaf292a92f3abee1743f9fc8f1180286651a8a280eb1001630937f0e7de7088c5c9d97ebdd43d095a0c2329ed545ed509913348807c6ee018ce5851636f6ed382e1ea6e35ffb377b25aa2685aac0831a1f89d41ec53c9a0409e773bbcfbcfa4761e5913e9ccbc1b8240e145338f558347b2e22c790696a10d6116c1e8a6bf93f5318a237769a0555873fe0d86ecdd8eb36797a8f2ec6dfde6dd2e0f22568beddd4bc503ae65dcddcaefec494cb79e21c4b6df2b44e81a052bf587f1ba631cb6b69f5d8d46b1042cc1ce4f105fb8a2820985471411880969841188f280ed0f5f53879190cf302a3ce91671680e055b339ab0e467f9", .None}, + {.Sqrt, "862250b9ad84ebc8cb100fe781962e0f85716c7c22bb302a95d950983b25e4c928cc0b44aee62c9bfadd8deb5e6d8fe05cf5788ea857b9153f2a716e314b3de9e01b67c4a7f2ee9c2cfcff3325f70c529141c141d8757389ff2266f413e4c7dbf71cfea054a73181a8ab2ec84c77fdee6500bdd0b61df540da231d2c2a6621b76ba6da008f803c6c3587db690790f71ef27b511020357f1238d41acbb5a82e085c9fac6c83d49c03925792987c1d77767a1cb35f88d84ccef91e4e1c4fc5346dfb298018bab3b1075480ec8ba2412246c899beb1e4fa58d1aba4e62919c225fa43b8556adfb5053a6acad5fa831a1e4ed5a505d63f962da50220e6448787bd40280163026d6d745652fe2c40bbdfc4ddb99e14433dbcf86bdd48f97d9dbe317b1a3932af4223d75f8bd6a9d9f1c4eede192bb543e90661262b5896085ce022401727e8d71e36db9cfc03d0aedf3fa78595dfae7770d6a5ed3d40a928ae50cff930d526dafda2203358f0f31543ef2961d113d294355e16eb53c1ac02879155098d06f0dbd960ecbb345b7f686bd2c624737f67b554ef2e8a057263714d39520f8e24fc0c51e34e61e2f8d234d24e583bf2700898b8137af109288995e1895a609f04a0236cd5506b275a70649c4f79d775bc5480491f4227443899952354b8c47ac3f6984f311c3fe0488a46e764fd69427adb99292f959bef1d3b5163591848", "0", "b94e5650ed637c98c475f2fc7f704e94b585bd95ba5b8e545287dfa1b01805ffdb7008cd84a17d5c35014bd9d903fccbc7c36e2f2f2383b57d91a8848629d265ddc23a1be4aa58e223f1e98acf7d21bcd7da76d25d733a3eac2af9cf2e6e4888f4462571639cc6ea4caa9c6e8eeefefb6732333b478a39dc1f36eedf5f9e0ecf2d19c1593334bef2f430a7ddc237f02118f8ad47153bce3f4c11ce614a3d71c9544219e75588535400c318596759b7d84619057b6cd00bec230fe74baa39c3df4225b3e056851f3b5f3d69a80977232eb9b03ab8410032f899f12a536f1366c1f1b4032d44e8e76d31f2c1300d177f6efe2245a55c513707acee5e9c3f4ed92d", .None}, + {.Sqrt, "861eefc27bc1a47e1be2c4612800e882859c3a2e2cabd8369a040a7d2e25168d6e2c6cf9264c880c0bad823c1af36171e80ca3e79992b415164a08c9aad8227e36fb4a491e100ca25c657d185ad43c31cd0a7d74f7460c88448dd126f5e528857e206fe6654b20c5242e60a438a8ecf38d2c7a5c40e1a52be1e03e4bcd358642dd56e3ad61254e8d7f45a4c774787ca5adde74b70e1d518a8f16f1453d75fa30e30ce9aae9b1ad6d7df47129785e285e6b769cefdc09a0e52aa6b17d01bcdc18cb10cbd838c67e0311f7690890a5369f2f7ef3660705795a0e78ca759579d8d1b69af4ecb96a5b86d10cf3ed568990ced1edb9ef4e830e4a4b1312d104f57051dd1cbb72b0657bf6d9a84254ba98a49fc21cb6cccf6df3bb4da7d7e52d390e3ddb3cea2174272093970f6bea47205b3a4fcaf5c9ceb50a7985aef5823b5b5c4f4302b98984c9f0dd6d1f98fd8dee72fe20e40368e4675621df87a7feb37030f56fed1e6ed928d98830e35a71c1d927a242ffa22ab9d7a19941ba0479840ebfae33cf02d244550c71d06f06f0b428cf0fa3ecf56c59036d6fd8b9f7fef682d39c1581092afec047fe3219adb2c99c2026209630412dcc4c9221cfe7481753f6adb0d7dda23aac1f505d4e83940a9f4e647286a79d434315ae7757133cf30e56d49416ce14fe0f57f825512c70373d35d66b1e8db0f0018190e4eb282e6c5b83a2", "0", "b94c00d3b6b175a5c4e0f46a7a46d1aba565b264b89dd1e804003eaee6ce9ab96ff5e48031fa972d1d969e70ae4a1b3e077172af523bf27e17b48dff1291cb6b58cf6bcc7185983b94f1759aa86e41125e092c8767fc2548c77e5f60cf88dad625f3b37fba6a24a9ddd58ec52f2a3d1c96641dce31d581041a6900b638fac3bec66bd8c0afd8b015c9819686a320e458ee23cbc0cd7e43a7648fa425b270677c5b92b66cbb47c0004ddcea42c5830fee90932ee872a0b2948f8d6c2560d00104a5a4813a5f64893bcb23e30e6ded6b446bea3fe06166c225d72ba34ac5f34e59e4d5a391f1cf86936897f7bfae68cf8eb2dc2cf51f75bb205772345d4c9ab4ab", .None}, + {.Sqrt, "6ff7fbddc17d0ee7099cb96135a132b3d65c0a12afdc0ae3a088f5de8a39ca1eb633d684d773dfdf794ef9ec9f066d3d3c18679dd2be44d259ef7881b71300dbe6eaac098747d1892d577fbf9f21476b8d479e82f617a964efe57ab29802a803a85f8a083d5ffb185fe53fa77656a361e1294aceb03bd5a1054ba03f24405f360ed361d9294313ed097764b83297d852a924c384221df4146b355ea99b1ea64b553e370713b6cf21a7ef05a3671109b822ccb5bbc115b16a49294ef12628ea7d81550ac0139b5c56f1059eb7dc636e2fce4548b8689e2de160e24b8bc60d840d05a450cc3e1c590cd6e74fa9c306e8cf7a655deb684261a0accb9b755a9e417a2304c1910453eab1a5f613df7f044ffdd5d53ad8f8a92d18e879721abb1b73be8c036fe8fbda565e4adac9a9715117ba15bb4dcf104e3cd75c12ae1b6edc5b6e5efff71287e52af6030fabb0d229d8becdd2e0a74b4bd1eff3c0497e5e47b4a1086b5a9f9b3a07926511df7364dcac289d0898c9c0b135d40f72a0b1d4d598a017f1bb22d0ab3318f0b30855b28398a87da3edd3d8c5a3e4e51741b6f519afef7109b6e9e407c017ce482bac9c224fc26ecafe643d2c40deca81c5af5af9dc375a1188e6ef1b637e279b3ff19b02176d8170102e59d7893244c6d6b4960a46d12f6d46b569b64951b467706b51023a00836a57a9c82e74a602205274599d73ba", "0", "a94dedee6633babae08abb6975e086c9d6641f143f29c67d4acbccea9175a9c26a2958ced6eedef0d9d8c2257dbf92bc5fa8ccd2b2ace4a9096e5647588dfbfa10cf7c3a278bb049ef8a10714bb5a7ec207b2f3132aaea453bbdfebf5a078345d35e36c7c04e54860978a428dc5d4ab4e82c1ae21d423fa4cc3b6368cba2f34988b4ca4c2792f0a88ff48259cf48b8b711441eefbea88a94eae6862eaae1583e45b95083b1bc848cafb106075391ee04130c055153963b30972f3b6f7a90a55d8005143b4834893a0fcee497e5279c33d00f3af584f0dcf5bbda706e1999f2f24f307aee8e8e332b6ff92191a5646d824f61d3be14929a8cba231908d8ede116", .None}, + {.Sqrt, "278159bf84562ffb4af227efc86c3e12943439c79d523de2126d063270890d0745f3a6c11426837e7fd40eae87feb276594c7f69a487e4447edea157831b7d1c7aa01bc844cdb89aa130479fa5bb5ad546f1b26b1825f384f9f56aa12a283489bc3b8b940d4bc198651cd78084879634d0ca6ae5337138eeeceaf0cfe88c5ff7311c3c8ed37ba8033f029b1f1e2954f76f07b582e8ed0dead831c1791046f4579f2f9e07b3d106cec97503e3a463fb97e4424ee99528036a19dbd8a65a5bd5fd75176f35e2a2f7aef7e2854b5362ebf67d8ffb514a11fde9b67abe8eafe7f378752e4da8fba7471bf107cab5bce8514d6b3b5e67981807ccc67a811e6f9744aabb177dd7896f2cee17b050dac25a1dc441861cd8ab95fa5ac6408a3a53f9061b39177506a08a14441d7ba944ae3fd09160fab97bc856b7ce15e10dd997dcf8d2f4445739fd0c9ef62ad71ae096b12b853c456f360a3b882f8a00ef6876cc95627ac740d5fac715d9cfb261df779363ccc8a9be32f48e8cbef3b16a9887a18f4ec7b62af9dc26c68f04a4db4e64661335fde8cfd4ad9d17be087b0252fbc68871708e2343e46a1a965d883fd7a25c2d6cbf59371e4692ff53195c987a13fea5523b9bc5e2d12fd7d23d06713c5877ccfbc843f711c4ab1b8484ab0dfba9e3123fa30839041fb31a8de80f98a3d0f5acc51aba8178b71c0a3fbb9af4ff84eb7a08", "0", "6490ae0e6397c8ffbbbba191c9abf503e904c75a2202ef4351455b050839d560f6d519c4a9d36647e1c901f23186d52b69c86d6e75be65c744e6edb614fd0839da71eb5b0d55088c2cafee247237905d58aa22ba793040af351c0ebac735622808a8849981199c446fec5a763f48ea2bc407593f2db37526c1764b2a0dd8424b352cccc24e666259addee0149f9af88c326ff2a357fe9a57aeb9c1e3f20310d62ce4e3b5bcd4ac4e73d487cecadcca8c5dee41df9cdf242946a2cd3000365462cfec7403502ef6386ab16f3d8316d6ddb41432f383b2fefaf8498c1e55e8330f34b42d7d8180bdf8905b697f11eb267dffcb75e77e53eff98b4c8e58a8064353", .None}, + {.Sqrt, "8308b66a971a6f28adcb7b5e6048c305f24738b8c336a088b71979eb6e6c509f7091e6fdf79df73c836fe4ad1c971b80de715793565c3dfe6bbe62f3a7796524301213427f982e1c83786fadd9ed25e8bb3c32e37b0c2795c57c12a8ea487b8eb4a1bfc63c60542ddd62cf9bb488def8d78f471929a113af1b27a951607ced10de3f9b38f7d0d4e73d0a0fbd34ef1e320b2577b3c93b3a22e43839825b09a9d2c0f00ee27119c5c58da00cf8c0b5d542debf9633c9014036a11ea418cd52d1290dda8643f8a5fa81c21aa3e29248493277e66b61e078cfae330bf8e9077eaff8d7fe5506d291624585822d893e586eff1c319aea6d8dce0d5411f67dd6ca8e5f295a71cb3d7a9b109effd214409caa788d2cc756efda05324d274138b8621d6b1d4997111f87df922e809b32687fe3600347f2b0f08f02902b109f0a88e1bad7ceaa9b7bf178488ac463a5b26d3837763baf0a5d46fb327fc7be2e57dd21b2011194308f4347f3aa488603c404a9abec086c7cfd4c0757ef5396ac3017aef29e60a0121d91e3d76cc2f1b2a72c3c3e987065367ae87546f1496b3e90158a74d72bed9d207bd2a624fc79c9798a2e539c06b5851ee6f6ec17fbab9a643cec9a0c3b8a95818f8f6844748bbc573725b36cd69373ebe683b97c6970efebfe0d74d140a60ff4721122e2f2041ddb8a4f2970fc3f8132d563b154c2afc3db7819f6ce", "0", "b726f3c092c6706e92af293fe2ff01b4cf584c1ee0c4b59cb268deb7888d0033e1ce115a3a590900f6ae117327c7fb384575ccf14b52d8b62e1c6b8774887499b40b2990cc5b61a56df3174ddb8961dabfcada8ba2a9b52eb1b3cdc51e2a6e002fb7d9165e25c1dcf75e74681f2194927fddbf1c201ea67226b9cfa400da3df16db60a1f3c74caef78612ef7f90cbc520d2529686c4ca872ffd7b24eb649cbee078f873f493f710e0975c73779384d7cd6034c99c91fa51433ae0f7edd5c43eaa1456f6da269abac49d2290eb2e76cd43f99e84f86ed687052cf69533820bcbfb693733d850bbb08ce441be9c1071f0748b8108810d463e48515fef9bba9ce9f", .None}, + {.Sqrt, "e0fe4735b105d0661027a325e0b172a639f65047a38f7b33dc341eef4022b9ab26f5546520d659b62a6f4203a0382e342291842f0270f824a28e31fde50b77c0bb7b48d37c1f145b5416ed6d7112cfb5e71309b3cefb1681d4b2765192c4b0380290fb7cbc824afe49089231497c6969be0fa4cabad86e7816ad4b3df5973fbcbae02ab21b0ead6d79b2b4fe732e8150a220eff96b4e1f1162e4beff187c76b58c84a167a7b73246cbaada5dda66b1cd6be2bc5d49da269aa1260efc4e8b7dce79674c7396192c6186d1268ece3729e48c012c799e8821c5f91befb652ff17a829f70c5bfb65095a4e0a3d9fe0031d772f3bf46222f772fb4913f5f14ce14f7a04e459aac74b368063ffffa33c1b911a17b4250039e2a030aa13d4482b7e9fe2c2bc98b9fe8b40844e7b8d75ab8dc07da31122725cdccb7fa8ff42c14371845cfd44a026a2f4e79e106cc66d4fa442fcf17c43ea4007246020695b7814cbe943bc5a37b067f16a2f5ca81c78965f01f272fe50ef31886fd0a26c8f57eed1edee6ec7a2d6198003745eaa98fd2e27ddc64996856783c17f5108eb4b9f7be10a6b3ee1313b33089da82561d6694949693ac9a6e3006570fe18319f6def0db8f36605503506e37dfeac19210e39625e838eea8d4e52ae4b70e5a8ba4b3818596e89ae2e47ab45e67e134ad5e32345ed5322b66658b382432c555064234c8658dc21", "0", "efff14e8fc56b1ec925048ca18eb1563856bce2a38b17001a61a3fd6f61971d1ef4c70e4bb7e68a92b78fbe4b444cb4814352c43c140f0e50dc73861967f8775f8fc4f73cf8dfba508cc8d90a462846502416c7667ffdcd9327f34e7da449f52d36f474a09dc36a9538a2404023028d4be2831df44ce04ef69cd0e4fb2735d677fa599640e4ef8b6d7ab74d728402f98eeed68f9cdfcaa7add8dc9ba7d031aff71f716de2d6f5df9e3a1f1107fb603e7b45ff713cb5478a199efd153192e8d43482edbb75a4a1b6f147eb95de36a95fe0b2173f7fdd92e3950e8bb4b6a45f4d99423ac058cb0cecfa1dae24624925e11f99d9641996453dfaf522f74ed0629f0", .None}, + {.Sqrt, "4f31514013c93a0f62af8b2efc72bd70933d7ee390ed167ae01f69b5a959a3b51fdeec7f26bf24ddb7760d35a689a2706c7497407c28110c746934e93e56862f88afc6138d6ccc0b281e7becb7521cb385cbc5a84dbdd55e99554cf8d0b3ccee23938de1bcb459faf267eebbed3858c66f2eec581b7ad3416e2c5364f2eb9b19a3b3d4e9b9d73be7fa2fd6711c3c25b9aa218af466a3eee0320f0d4b7fec23d8ff5a962780538dd8bb96b8c3e3c54f40c8389fab7f9d5b9c7a493c42bb76b15e68f10991129d13bfc42cbb0e0fc9abf8eb0a67f425ce401b9ab47b2d8bc533a291124138286ea58c89d815f53384fc260d5d71add7291e0f3c0eb303cdc226eb9ca2af7d464904ff1073a8edf0492e31b0cf5adb66858bc73bc2dce562e02cdd5f318c89bd92b2994503d137531120714096767d69e7b7ae90105daec0f6b00f663ba1e4305fb6d4acc19b78e71d8fc06b17b6446e4fb6e8e02a7cf8c3f93cad23419fc3d66934b278893fd2f1cf1bd4d5055701975e9e80fc8572a9adb9f156363329070354bd9807a9271a0ac5eb69bce9a0de8fc81b9435751db3f70d32abe75fcdd5de8f2c13e708a15ecb178e9e31a9c72db60e9bce0c45c2e9f721bd0397cba0640bda16feb7e0a6596116e8f90aba0484b0a64d7e6157cd59fe001cfa4a7f10e534feb1726669957856e9978b3f2b2840f3cacbd8ce34468bf63b7c2e", "0", "8e62680b0bc206bdce21109faf1f5b7bf793d0adc61e2ee8489a4e90cd537206d41e6f3d9988035bfdf3530ba374086c815024d69add5f5f4dbd9b1eaf6bbca222316dc7a7c3c326f3853c9cb8c097b89f115a836c6482787437f6dbd0eac8cf8afdfd5fda5076e8cfc45e5b266997ff66e5a48f68dd89f164ec92f231dec2a4105859bf8cdc1564cfecc5fc84cbb01d86eccfdd83f6b247e0a731e437774ab426a443c07f3761db77527be20173ef58bbf51aecac9bb1db939f78ae27e56fb77d20c5bc77042d0dfcbc3a48af46dbdd9edfb9dfa8d5441b7553ae0df409d705133d524e16a7fa641032a8d9d0c6a39033b874321c9b1dfcd274dbf6f4ed0a34", .None}, + {.Sqrt, "e5dbb78508efd1b259a2aa5bf25d9ed366d0f8ea72000fea112f39fd177e271c55924cda1088b089742a9013ee5bc637402b9357dfdca1a482ced17aec2cbc75a551a7cf17bca052dfe0449b7a68cedcb237a488e35e4845f6a582cc5dfdd67c6cac6ccfb7db9bb7a7c3c56df46c3986b6cd2ec56e608cd8423027b45cdda840362b54b422b82a0783bc7945f69da490154f0b1c8742e85deed5ef239038ecbf3178fa632bf1e1d20deb5db64a0f8534703123eba165ce7fdce1006616bda3c0cc85b5115c3f5d7a5360fe5376c8bc24204cc9fbc214dbf63ba5366e68ddb3c030a836993f41d61244bb27e53552c0e5b2ff0a071484d21187efc0585b7fbbd04065101e4b1910681b5a5684f8bf75a76f9100e95460790c5af701de9b8b9044e0d9c21d0265ae3abb0660a3244205174bf80707513d97145cc1dcceb692bdf34ed233c491326aefd2f269b2a18ff7f92c09e15952c089b9a77d22aa5fecfdbe1e50321ce6bf051fff424f033067d8422bbd4d72b6f6dbe659b48345db766fd1b567d1a7e0633a9d21da89943fef016ad4a0472d01f198d5308c5ae99453701f7fa9610e03ca9826718e94bc4fb9457d878d7a5d1f5538146543b485299caf73f0e3a5ba198599584e14b545ff6f6417b2a1718306bb61b3b6396147cbd696120455426ce1837c105afe60f536f4c10c77bdb66b2ffeafc74716ce04a48a654", "0", "3ca4f17bc8e4e5d34df59e9b5756d08d8b935145b49975d0030ea2399a9e11baa8bb3e6f35925d2031db729725f66167da82c424b5dbc1d525bc1d7abf94dd3c4cfadb2b9f44a3c36316aaa69a9f07fd37da09033784653787b7dfa4304ff4288f8817918e2cfeb4aa6c2beea1bae2978facfd1f8c5793c30dda5913cca3dce17ee48fe0e3d042a272286ec1a33e2bc8520ec074b80a4be52f5aff043d64f6e8085f1c676fe6eaeebffc3c606ed7c708224c5572e428a2177b245a6048368351d1efacd92137ce201149b89493333a69b96bfbfd4df510e78a32b4ea692696cc10adaf0e54739e67c63bd5c2af10418fb1e278f254408c90744e65c679a3ae29", .None}, + {.Sqrt, "de3f2950b5de80c73a4b870209fad1084a1a37a3d707a154e1f34a0e71c6d2739732f192fdbd5c940735bc84ff78cc33e2226c7fd15c083535da715e56ff14dd6b758cce8bd4001df2d661675234d69f43087862c840eba7350d2aa95886b086d6df6d3578d91eb80ab10ad6d4680b0a9235a7347a45d404c38fa6be5de6074d8040629be2c996dc70ebaef67e8bb20f749fe7394ce3e405beb344a8b363aab5503e2cdc0d02175ad29bce15cfcef08289228742b44e9c6c1c08143eb0cf5b5316601c2922128d3c9ef3c7709c16a3fc8132a288d81883b63221bd75e07d7033f4341627c841d8ae2a4176ebf8289da1adf3fc06208612e6daaf131ee37a9d9fa513f0b1b01aa623085d0ec0e7e03bb7a4869c36bb95b215a44b12e5e51059087b62b8843e6150e1fc27078a2a653999c6e3f185e3e31feb7d22ea9fa6541aceac005a60c052f88b9a9e35b112bb8322c3c1d75aa2b874290e27d17e1de2d07d7d7d9972b2e7102af0c8feb1a0d307c943bab9fb9c783f66c22c27b9a975d375ecaaf850406f9b9bd35d061ae381620ccd0c00555227bdc7e8278b078c9b18ccbea558b2a8d49b7bb9ac187177e3a671a576b35456ab86fe21366c7b7f663e9fa36747824ead712be5f0d3c7264a7355523db9f6a923e3251c1ef93cc8468480bd3e9bfc02a8c46d8597d864afda426d16f78a591bdb72b6f8e94c85d06c3e3e", "0", "ee86edd23865681ad778f95ba9fb4ebb2fc65bef11d2d428c1ffc780b9cc62927e94f4b93c674dcc0af5be556059c8489cdb1f0c91f481b02baa83967abea0a5e0dc33ca4e469be611091be05451997164a0627af71a6252765ec6da0480a5bc681b46efa85ed9c3c5a82468d91f893d74c1c68b80e72cc2b872d80f24006cfd41ddacbf0934fec03e970f418d7827c180d83bccc27373b055be5cfcb7a09a790030abc45d3cda409eb2208f49754286f88390bcda722b0650d8af3f99ffbb42d315a9e966e8f4f595680f4eb2b986da83d16b6ea6fce47f3132a69539aa47b46ab021107878bb3f49065f4a34fbaf7d373b0c3bddf0ea8a6a63840ae22723bb", .None}, + {.Sqrt, "1f7a95c6f6fc6cae89156ffd2809124c73bc2089843e0a1503620ee0898f7f852ddce88dbc10dbb787791f4bb45940e894d77b220729b139d75a2422687481751c952ffa285363433e65c2f9349a7413d611cb9bd22b4b210f722ae9265c2495eb4a1672d033b2bf218c8cabc03ddd671f7565f3fdc1e150d34ed2688b49975c885b0c971ede9ed09334f99d4870695e452d652e89b82ec8ad0a3d2a0cec44acd32841c59b7cd5d8dd09bef84d3b5e279c5a85880e63f1173c6ddd70e4f53af1781aa05c2564864f806293bc2ee384cf69aabebad57161ced56e4777a0467057a4d6b9e467993610c99dd036066c8402bd4a2b6d4052ab1cd6923b850d96ab863d005d82957ba2e93e8b17b2516358a74481d785e775a03ce00cdea7795e4e87906577863ee6c59083d48dc7e28379f530dfd62051d6ed21a3997840de7da28ac478d30bd5a008a60e174573bf54350f25618fa4622604081352f1b9430a2a978aedce89a985fad2cab81f2667487765c43c744b270b0c861fdb11a7b51296a4ef25bcafc2d62015aa20ad62d1fd703a505b627644d551eeef5325d2238ecf1aef4f49283df383716d247e7ab0233bd04c902bcb02efa753e174ae06d95866213460980e36c6694c8805a4726fa88692fdf984c83b02beb7c67b912a8847ff40902938acb261a6823b8b713a71260b079dbd67127b024f11563f3b5f271849b3", "0", "59c505f5a23b49ef77dee6f3848118559864d24a9fb8a5b104058bd66872c2cde9baba9dca5a2a03a4833c7f2cb7af748bfc87ba964361f3b4d3ac287204635fec6e73d47b863af5f6c66411308670f007a657ba2fee790477e86e02deb117aeb94157e5e434cb828c814e22dd084dc4064a1d77c3c5fcd65ccafdc5baae8e8d06431218ab3546579ce9909a596ce074a90876b3cd3fd3caa06463c75c6d11f9dcbe69f4827fcf2d6a5bba2a6656346cb78e379a194689a83283bfb8fef95f1dfcd87a68e5c29c5c10a1e96b53191ad43c815aad8595b9698350fd199d2a8afc27e545490d3064c0610add2537319fbfcc318f8b488d3c2dad56acec2acf8c8d", .None}, + {.Sqrt, "7bbeb9b243ae299842e49c3bf75ef91035ad1e118b72589a1f2c392f580a7bef534a2d30804f6833bea2da72572f6cad80923acee0d7baa53ea4446a8bf2e0d66939a626c684bfd6ccce8d3a088cf77d06c726ee342f5a2aece4067b3d2bbd070550ef171a7aa367bfafd14ef33af373aa48ec50b482681869f3ea9a4bd55b3f245e3a2775b1f697131b8c0ec5ba6cb25080c412bb50c445b1f900de71e7b6beabc3d7d35e812aeb787ce135ea2ac8ec595d98413febefd855e28fec8942bdb530ee6d8f5bc8efdc200671dee74eeb5fb1425496b4d41717a789a3d66f7981ef222f9b458dd5e0331db7e59bd5d5909ad2865061c3eef5a0167d4dd130ee87d2e0d1c8a31b71903ef8c009a9b6fecf69cd9fa979c63f07e020dae4a701577885ed2dd60b57e364375f93dd9231ab70ac65450f4369a7e79a74e564f0f241cdfb3be02d66d292004d27f7f6042f4f43a131cd3e92aa7ec710df8a9e9743b16bab5d536321cfdbe985d5f8de8165b1739b406334fb60aa83d3210cc8a221a9e3d559761dbb94626e889a9d4ea5242ce83c4285497520c80112336762ba0ed56f342057dcfce0f01124ceae7197b45210d02e2cbf038cb17197c826a61cd5fc546c2a225d9124a170f7ae083c8266e943df973f4c3343ee1f9bf07b12ad65bdec35aa856491cb0134f0423c9112c9f429e7f88849ae06d8a3574dd3fe45ac493fa8", "0", "b1fc34f467cff7ca661fcbeb4d9cdfd8f824b4ce55a8f18f62a897a6fa90e5922d4269601de0de14650d37a47bcdcf2f3b0fd67d640004c318f48b2d240e284d8986cb3647b173432b883f2309c5b7f5d7ddfe3e6eeeff7f2d0279944b4d12afbe818ef23a24324ea0bba9478734388906b22591de60de5048474453e7e47a2d5cc1370def8fb213fcd268f16eda733648bb136583040d5d2cd2103e9a85b05873a55e9b11802ad453f3bab920b9c5bc86243f68a69aea953a2f614f1c5fc432ddb86feb0bfc7e61c27f950c5e876b45c78a3d68f815599d0477fb7e20f9e3b21576b608b6fc6153891c57c7b8e4001374488686f94cb77b0accb4e91143690b", .None}, + {.Sqrt, "ca10434d970373d1018324dc4f27fe21628e2a6ff7fb1303c60e240a34656d5e0158e0674e0ec51b7e55b8f6eb8ee8f296e8562ee4f8e0b694b706d027ca7380ed7694618b6a6859710415259df3959ef23daa88783345ced767b8c087b9883a1586cf3c90a72f3627ee4425bc804cdb35d191b38987bea8b9cda65d7077e4fb96ae52b040ddc6107636173344e07133552dda08348dd43f3f694d3dae280937160f9e81c48e9a476ccb3fced100c2f16e57ec7c3ec8b291f44c2ca3b783140a87def4006d09a29788c8af3ff9f60fd8eafccf66686722fbfced3729bb68014d391e85562dd3f807ea6e8b70b7e4365ef62107e1fb76b02c94f5796a7c5a5045f45652c7f91fd03ac34bd072950989f5661d3df748c4e5208d4d60faa517104f8320c813da1e884eb85e5e5c6dc5cabed81d8405f54c53101ea5248fc1bf08b3c6fe5eddbd0b97e14b72f09e718ba75ae88cbad54c43f39447ef98ca3d05aa3d50feaf9290b52611730fe3cbf159dcb305b3dd18af163f4b4f4d59813d22ecddeee2972ee92d579b027e43ea0acee9be74754f709985af8a390fb54fcbf4a27265fcd7383c941e0c4ce73e4a2a8760fdae7e80012fe1104a1c221613a8987032bb708479305cb235addb86a211204f89eb2a4ca5f07ab9381983b4d7b8ce28f61c9d8849ce08cfabb3bf008e38cfc2e9b5a76dd9f0763cae42d420ab44263102", "0", "e3704054270765978ed447a762ec6d6fcca30bb6c7db1596a46ff86b2d060becb6a4dc876b96d567df3a28153aa648db95874306912e25dbd1c534c7ca0e43c846497152bbab054b7bf2aef84fee2eb803ec8cd74ce5cccd3169b1990faeacbc0da1d770a7540871fd79b638d3417b90e8f8e40720b26fc530099e2b7478e6eb024b5d3a912e53b20032d48f89e6e05548129fea8a67d6957a94662380ecc163ccc0f72ae1141c8d7e36b5cb8430076520fc56868fe4b9a054a37ab44da421b10a5e29dba8e6b2c176a68b6f6f94e4552111a56589585cd42f992e1ef3045920a9cdb2879c680c2b15583aba142045dd1eef5d808fa9cc1a4751aae899f30104", .None}, + {.Sqrt, "55ac3acb806d698defeb668c10206edc785ca26930ffa60fc26df866306cd07582d0b013427e897d8e3a8eb64b432091e2d558a3fdc1d0d001876f23a507e068491e37ae2c60c75a59585f3fd3f82df7c626db569b343f3fdf077d6fb534f9661405d5a95931947f768673359232b1cc84347ecd6b1bc22a318572f8098168cad0f4dcfc573aa17616e9ab9b1f817237c87aa8064e2536ebd75b5bb716b35e765640be869de6b9876e555de39f6fb8503c30711c7eaf0257d3ee8f720212f16994bb1312c062962245b54603b0f1df8852aba21fcea3a80ffa0cc21a8198263d01d99fa9239c4cf7cdd20edef976b308013815985adde87dd5e1906ebdd472080d542704354a0dce2a2da8a5ee17e4d13f66257b075208cd7f1e1adb55cad58fc1d4485d7869f201a8831c6934074365754d4d2dd582541e67cf5ff809d80734b91da0456cd60c3919465967075be37095978a63cde3d4faf69e1601c9098e9e7c4e47b7514efe66aed3715e952a9d8a66097971d67e04ad2d2af14719f3d94aca5e7eb238b5f6c04271415ab3155aacc0e62ddf22890d645d54cb775ed756de11b19bfbc3b6506148420589628652963a5be56732e95a7a027bdf3b7a30e9e5c0bacc790589a78a42120f63f77353d506f6581596a3752603e9dba3c2e9baebdc892c852bc4e6aa2e5c229877b4db928f7c9a57f994b367b85929b08439dc8f", "0", "941868304292c0bc225656d5eaf8b76a02e909f1c6b5989820884510eef6f25d1c9531e33205dba3346652a20fe1a481e0e2b6a14534207066e7ae4f257f41d3f1080feb71448cc1ddff762f56cc5679954b11fa905108446a937e633447de516c9a115677c4e3921777bcbe61c808b15ad4b0000474c71f47d58489b43b7d6676e433489d86af39407b5b21c1425cb5bea9901e09302450c8fc13d0b73e9cca64b4418ddf6d8b659486539bb6cd442778bcd74319bf0f071fb66079f00cc0c1f45e5598f43fba4860912a47e39e5b04fdd90f646c3eac1cf2de9405a647ea31975050e18924e8a122203647cd7b9413c907a30760420a8e5837ad1938339d3c", .None}, + {.Sqrt, "b3bc60b02ec6ba4163e6985870282cf78117b83a5b38a9f11820073fa969c409e01218b6ceae28a29a05496aa39f10fd3b6b4c79a8bbb07980e9765cbb1e15cc69e857bd4b6dacdfe7641adb0c2c7c0f492e829baf4dffd308b91bbc84c6a17ecc510a071d7acef0383011504a2c52fc5d6124c6f00cb038a1318c0f8a538a56f02544775c91dd6bdeb5f8ba65f89ffd7b522a780b5195c850e0bf46ef17ff39abef36638404e3bdc48ef221c175c8d03f0cec3c4231ef65955a1948a31d8935d2022012c575a5a55acd9d2d58d2b8023ecc2128f38592ca8682e578db444d052907f109a0178bdad038c43e207865f2019e0bdc9a717c346fcf7ba7f6e54eade937f04c59d9931bd1dc87a9f9c804b301c5c523cab3ac9d1a5adce8ada568d8398cd4ecea063b6e3e1f3be63e86861cb9056c58bc50f73bfb92a1fca50c57422f6a531ef0d82e0a1931d11f97505209ecbcdc13ffb3c3cf91d78b38448f6cb92d5a4741b04c42a0adf842c2598ee794b174dd8c7414d0be2e4b897bbe22e4dc4c26d812b678ecb72755d9908a016e3c1dd0e786063734411b0062d925f6f30d242ab0c4a535cb77e74f0595c8b0f4ee42ee30064dea3a51dd5279af64667572ac3bb7f245d8631be4541c29e6f70e80d1b1771d390f15130a3bf2b2873de175d159d7b68c25c26b81dbba643887e85b19903b04ba084426fddd81df5afd3cd6", "0", "d6814508191f20f2bc7803d4c0ccb99d1df766232833fc0c8a0af5067cd7a807a344610c4311114c4009981f02eaf5888f865fb3950181089f376d8dc9defe56df8d1f4de2b4a7dd02678decffaa01d9c76771f56de908cad0287f7077e79aec14be1fd565ab0487618c7b47c7fc96ca4538786bed49d63bc53f331c7933f85e073fdd6912c799ecefe09d5c22cab0c8beaebb1f519c713829ac862aaa338de222f03b672ba65252cc9802c939f25472bc9207d43421249c3bbf4e83cf6e0975350f9019d98bd9033097df93878c9b80675d5c5a6dbd3c0f47af2185736d23fc48fe6dbfa52771e4447fc11bdcb97d0a8502f95801459b7a30975af19b6dc6bd", .None}, + {.Sqrt, "b04da78c6772fc95583876c8853d12d12f8fbe7ff5e45d4cc0964cb435c19717141fa471dbcc5a6e3753aadee4c90fd059c9c65f3fbbdd249ec70ce781bd74d3f867c691d031c4bad0835c67647eeffdc11f0fe1fb23531385f2cf58a44e3b58a86c2c5b7af1da9ed93a1e81e777e6b1049f66f9817ccb3b1531ae2786b21a0082b6d56a1b0cac482dfab45cfabe27bccf0e56a1d9d931a5c1262917729a8af8083f2eb4db2ee5abc371cf28cc3357bb6011e9b1bf5e1f1bc93b158076a4a9ff91ffaee50605e46a9653dcfe106cd09b3fbcfd3b9d1bbdb9b5e188eeb7251d695459c40c27f9b493b7e7343ae295cf21c5fcba2f3fad11faf3ba4b698a6578f5b4fe43dea5e85be0fc4b2b19c268cf8cde4f111c62bfabfe1a30a18529b98374329f4dbc577d190fb81a15dc8171351ccbb3de10c806b0cbd2633784a58de0edb1b5af4e2c264e0e881c749912ce29b3d06aa37a01526f82642eb156113608e4478c3ddbee2a226bf9590275d90152600296433d42c2f34afdb245e8864b2c5c994a40e9cdc07ef47a7d67a38904086dd308396f74c469642bd4a22b710ea48572fdd5dffdfdd780929e9f024f80cbe502e4b2e8237e8f99d413597124358aaa0f6ee157b6b035bd4bfc2d2c55805dc78c0f1546b84f6ba01dba6d95b97d9730d542510eba9834495050e4601b41932cf91530ef79b4a9a6c01da3edc4767e06", "0", "d472634859aa51912708435b1097ad33583bd1fa45bd034cb2d9a6f0b117337795f478a6afe27d1759acd7f31ef0b5ee16dd262ab86aac6cccdb55a6f65079ae07740c003064f71f0082ecbe5e1e4262ff56ece8840db12810abb0a3b4dbc510738919024cf36d07b293cde578e68b225bd1d07fb77d4205eeaaa4524570c13573fe43aa6a4cb44ec6901f40e33d2dda219e1b5ebf84ee368226ff91694266b5174b70aae2f71268cfbbfaa309ffbc3ca019dd9227c197aae58cba1a0e0a6b345988ba66c79161bfb259292d60f833e7db2c07d3d4a57b1b7d237c13d5ccc07b338608cac1e3ab7b76b61e0ac4e44eec08925818b8d754ce5a2918bd6ca05189", .None}, + {.Sqrt, "a50d68fcecce79b24a368ab945136b1e73c4c2533a08ed8daf60a6ac61e6a45472682ad7183e004406fc1931788141312500bef640eca1a25b501f6c9edb7c73a35c58477d4080e0f6b887c5babc3e88578bb4e7bb2d03ebf4ad0c1276aa133cb94719371e7fa591176d2af4bb6006d1fc82b0d33e8e28d67d1b8abe7e8a55c297656e1738497b79a799d68b1cc6ccc4ffe39b06b0c923cd8cf7611ab9932977ff1ea4c3992a8c344f64754768d64ae4ce6d26b33bc5988cb338f5e381237a703f618d347fbe3a6ba702e0765f3d0d3b3be2c3275af07b1c71f20457eeea19cc478a0e1273bcfb816d83df29d1594f647a3047cc7b2081f4a908063b3ce1f4a4b1769ceb19c7c1fe93166db0aaa9565d9c611b20136c7d3537db6be241d8c7fd4b7a824d5e6808464486faf60c5bb0a423b4943a32ce0d833a51508003511872697fbd020da4b3c11fcdb8d35e6b882f1072bd5ba9e94abffff00a04aa4d016b47e26d92fefe91a53de0df7aeb136912fa06b392e5d74959dab6cf19234b5d7f1c5d6a4824049b02a994381ea9d3c542b6c264fb28c8e301dd20419a252be203fc451dd070eda658d08bdc92edb42711ebb07d39c5a2a45de334e0bb4d5d24caccfcf3a21c3b19ca546c17f14e42b405117788985103cd5d83dcc8988a4796dd03ca9a317ad456a856afb333031dc26ff1447d7d56d4f2cf18a07a6de9baaa42", "0", "cd8e6c7d1f3bf350164cd3fb0971b2671266f73f57d6340a59319a85c2172403d6026d414c59d2eb8041b8a992f34f9b643b35bb33a6d13ee2e24f3f6c559982b77540a199de069d6ac3ab3f293ed2fe42505c79dbd8562c1f143ecaeaf7541ea019a492cdca06f994e37541b3fa161bd6b7582ae5381e2a7edd0ae199df1621a43733aa48dd9526f8eb00a0bd99374aa54c756fbf4bb17d5a634f9b51d139d556dadcd6204240da76fa97c6977a9975d716416b190336ef53a78b63044c29779a99b742d811d54fcf5d6ed8c04e7034cae027157bf08bc826d00a2e633fa5de832a8bbb1ab7e5603e85123ffc77d6e0fecb7cabb608bc3d03fe2a18deb7277b", .None}, + {.Sqrt, "13cfd796b9780f70ce090524ac3e5103bea693c17b832f9193076abeb3a69eff97740f110c8c61d75042d8eb6249685dca8cc7b11c4bbf866e058f8c7692dea488a397808b84b6a0610309226f9d7ef82e689bc605bceebeaed1b455f99c3eb0f8498d7595454b01d47ad004fc2a89a552ef9c0cc86cd02275466c7ffc4a06f68f8682a0e0b6de38fcc45877a3b162134f437e5e8701651ce121dc6b1e6b609a96ac8ea0b1acedc5399cf20d47741e445399603d040fbf336ab9f3b2ca7713d43129c94eef41bb57e5d2581de7397a1667af9e9538a7e1ee9113f759ead2077eaeeef600787fb8c09616a643fe326d34624f7cd6f8714a66676570441af0e9e76e668007dfe40ff84279055820133e16249938e8c2ad2adebb8800baa6b956c43db3d845a8a9a3b56c999b2c3247014fa3465dfb79e92edeca3950118dce8cdaec0d33291baebbf987654fbcf73372e22996dd3e3f629e916e4d8bb66764538fe30cd1fb3ec5461d28b973707d8e60904c977e5465e3dd7e21033a790ce090e9980ce4f86eb03b24dba4f83723f4154909e3399fb9addd2256581b74d57bc268801964fe9dc8c673b253417b60dd2c7d50c779e1f8c84be3537d49f7a11c61ace009b150c4c6255ee648541e696a50e570f85274d5c5703b4db4684fc84b7e22791056474a123dc8905b78c55a9fdbc207be064da7d6dfe18dfb2896ecb79b5d", "0", "473784984e25f8a5b3541d1c43a06c36842565f3774e7d1d063df73af37765f7039c50acafc1d432f1d5d8c06dd9d44648f3326c91a125b8f04fa4e4bdd3c11e5a71acb7dda9fa42d7d7167df1e85b19b1b443f6b86e8c7ef1c66abd716e82ab1b819a4889b16429c34fe22c6799ce838549fe06c1046e63585e676a95866b711b286d0f0627d3898dcd88b7a30eb0753d713447f5763f4b538594b13cfbeb75721ef54b94c8ca88471e7ce55c7102c9992a8416a9faad149dbc957060aea6129d17e52eae3172b1ba5064d4f2f1e25a70f78ca00c20246cf1b7fe59edff159c230e811463c788c1a1ffa2a478b6edce5e30ba686d9ad7ac470b008e75ca7ae3", .None}, + {.Sqrt, "1a1fe68d79307dd16669dc69ca5e21f46049ca50fbc3684524aecc591e478b52845cc7b16653ad640e6c43f93a89197d268ffd2b1993ff4cd369f8f9c3354776a1a4ae87683085fd445223942b7abc16bec16d549d7dff44d3f9d60bb364071762f0a4654bfe55742d4a3f967a9a64d52f4c1f2eac3565022b2cdf4942e68fcb5337b9d017d718db8474031a00c29599c49b789fbb3530d826dce87dfea28d7ceb1487bfc49809a813237dfdaa59a36ca1c180ca6a8fd2882231ff6994aa385f9265af8d9b68930d5fcdd922d7011fa42a19bb4c055ac98602911ff523457c387811a1d30201fa40a762484749139a2ea591266f745b1460d54b113d4dd07abf812834d5e57eac66707e9b86af082f193a8807bc1155732df1a8761339e00b7ac840e09d99d69c0fd240b3e3859e8e9d47175e84cfbfc97d41b9d078265d92bb2dbc48fb246191613ff379adf5b4ec2b19795d835ab18722ffbbb4bdba57d049973af70e5448f4f3df79e46b34af8a103b6e68da370755eb331e07c810c0040c9f2c60701f161d22108686873e97f29f76b530e18eb89e89e9fbb8754ce215cf39f58001a30eecd05bc774c5a3ae76649a6c288f0e187daa49b023150260d0f34ac46937250c581e3983c5c02f1f807cea901a83267de451185006c121e4c3a011e389ae107fcedd0988f9b7a3a0d5d7acd00156fc549f38b6681bc8926b0350", "0", "51c792e977f4b9d689d26fe1834d63e6b2c1f811ced8372eb84891a6fbe89c6fced49b42d661c834265f52fb98c0841393d0e16f2bb8b7e363b2e8caccd7ab8595a340cacf77503e8cc4d621771645876285f8f55fdd31e7b6c17f469f4767077a80cf82dd598616162d035d94681a064f8a5a7f6a26d2316fe00828f266a7afe3f94fb1690966aa0d894fd5e0935a7b5fabee6b48ba7e71fe6f03d3ccb863547ca7ef3124589d42374098641d30922e68471ba767d65e1ba40fc387a781fe6738ce3026dc3f49e6553a1582aa5cbe83994021d54d9a9a651a7a5e1003ed0888fd0ad16503caeed8cb1f6c31f29153a4c10f205a094733d97a6ee96c73570fb3", .None}, + {.Sqrt, "d63955c68b8d12e2d8e454502730209055e3fa61907efd6aac08334a8135a24b4b70bfa6076c1ffb2e986a484e63f96bb6ba2c518663f643852b5571f62f3898e429b202329bdf18829eb54b39a62ef3b9b43e8dcdea4fae853fd599d1ba53e1af024edf02e6dbdc6081f676dc0ec3db290d92c4cb62cb5fdc0a5fac7e289c7e9f999c1854e844a5bdae90628682172031f5fb8cf67cda63902e4ead8ac5bbdbb6574816c7baec6b816fe86b437d000b8f74794179069c37b87022fa0cd3427d1301583853f5c89da8e47a69d2288e0892c4f4363defa0ec5823cdcf308026967982c5543283e7bd20c87486205c6171a1a9cdb6583934ba94d347e6cab1ae3b5a1caa6393ac13228fd02ab86f1e4a5eb316fb3244f67030311ae4336febb773e014bdf33c3a20cb7ca6a8685bf79212dd2deeb9f0ab801fa5349cb0090e30c9d5c6a98e9c8cff9db22c4435f73c6c80d5ff4eb1568a0711b135612643cb596ba4c7d7d61ea6875f9eafa9efbf131a22a183e14a707fb004493cd5503f7910b4d2b7c7aa077e27bceca145166877cfb46387982ce9e7cc3133303a14031b95342738070b0556def14a408d0f7c8cf371fccd2473e14fdf36fd86c0c77d25cfa0d7329b23c9f05f80c34d7445d716f98142dba23ff371d623c7ee5c26dc4cd25f0ee4d3b5000c486b0091c216226a47379636315b2b6bb08738fb97efced3b952", "0", "ea2ea92c7a679096e35b41827453fc5f15760e6b02e6dc47b5f5c642b0c4c3a52b43fe2af10a6cf1b57f5465f71ec80f865e35a64b3e0897e1a5050c5aca4d5f0a12cff51dd06111f60a3195135e94e2ca0a07f817f2723a93a0c03c543fce90feb11a24380c3f2d54a63d7aa9b02d06ff68f35b9ea636586ea384a2d5ebaaf793189d3cccaa35f003563e528637605619762a49031a19d7af80ad1d02ce7e8354fae3b049efc462b47dfa47b53976188e4973db456650323f2fc5e2cd76951e79b8afe751e1e555ab77e6df8ec070af0116a255743274346630d5073fa76e4b8cb5c7a0e13c1d6a26d1b9989e696983a59c71725daa3570a756cc64a05deb94", .None}, + {.Sqrt, "3c11b4536524bb03783899504b6d94faa5b3f2103177e582ffa0fd6e7a31706d7735d4cc2746d3c0922a141da1d11a0ea13186bb5c1e31b5e10086545631b8cc5c607c77e168e2369541ae9a30a0a1dcbfa14fb1d46adeddef3c375e957b2a9f212dec8b0b3c8b3652fd58d764860f72f8afb99bbe1fbb2142860de885ac0d987c443f6639b103199424a29783b4ada4f09e818199cc0e8706cff73181e02036a7c5f9c1072b1ab3b1201a1ccd1d283a3a24e235597cd4b1a6e201f826bd7f4980ebd75cca8d76713570db75adb0334668e8346898597de04e1bdf8a8a468aea24ab1a433d79662efd03533bb33207f1119e9d41250e0d9274a6d163204d873191bdc65d447dea1e37601b6ec1d2a8532bac20e817eaac17eef0313ecc847af6ccfe94d30dc5d26fadff9740e7105e9736866d9e09f8a268d9cdc418cca376be3bc4430f210bd096c05a7d29b007ac03cdf8e8881697310f3fb4f2337a8402e5d26340c32cc0623958d269ccffb345b51ca2195cfa52060f9570832f36c39ed55beda6e4716cf4471f3d6aec125a0bd764d2d557464bf71f4b6b603a424f20fa1604172af2cb095a096b099c80ca66678621b567247641dff051a074b7a49975f5232d7703f2f76095bc2b333f0b3daf40f655189499d765e8532f26258d444e6acdbee7cb538cb8aa8d3c80fb6fa23657940dcaa2fb4ea8bc021a742c558f80", "0", "7c01c26368033461a477f4a0ca507b96c7163958103c14e69bd1a228e32ee03ab883a4ebb98d256e9b1206e32623ec0f4f9053adbdce0bef04027eefbcaa911efec8d0c28634b7b5fbef8a09b719ffee89c6241b336e617964a2a64683b32a25c5b4917439a4018db7a0960bfb393875f31a625218796d9d60aa655666a8c376ad5a6c04717c7dfc40da844b6110fc899bd06e144dcac7e91ca8a3cd3ef68f97388a3b25cc035bbd03435a3dbeccfe0822ee92402949829b2f5b18f5e491d29f1644b1b94651ff44e6155575457561beca195b6160674323186ff52200ff5dc69efe37e080f75772cf661e6b248d98626da46cb4f89c239161f3b1472414d5a1", .None}, + {.Sqrt, "93af604f8feb4299883dd7e12c847b106a69b66038e155e27fb60576e9d2e33a847a84f09597f73d3ef9c9ad1fbff88cebfade7043141b3f68af8814b9d4c4542bc4585e0ce842d12216cb74a9ceac940f53266f66fce78b507dedd30a3dc984331a1f6de7f2da6f088debc6118c73417d01d4c5600907f60775ea9f5db613ece2cd5207962a540bff3dfdd7e94bf6f22885b8bcdedac57b3eed47f6bb476e792b4f44f5535c91e1c10bf762e4816c364928485fca251d9670f5147fce11d1d7df332f22253b8559fea28c98fe1d8c8fb7cdcc949b8c57356b5114363d7f507401ea55bbdd3e8ff5be5728dbe222c1c3c892034c518915310842611b43f8b175243302eeff4604ae3df394485430e6d16ebe3fab676ff4241404da3da78d5a5411c498acdb1b947cc61ac4db4aa50f2b18a6de8b6221a3b1a106552b28aa61bf94cc295272a50d842f5be7107b4a0714f0971e941eb96b93069749efffd9867745f596a0609d671ffe764e1c7cf47e425b4dba18d730a04009f8b75d5ec8af789a2fea2022922c94259baef5afac75e012f2bb31d266b009ff6d91eba15e01f2438b9789bd09d3936e8bfdd1d2da9283aa0efb66e07b7e419c9cead71aa6626cb037b47c1b53c19e415e4e9be32e0e1016e37da8ed47827a8bec156634e736ed360139af75a5f4617e5f468b17f5a6323f5aed9cfe3436ee0f835820438ad741", "0", "c270f1cd41ee7e288ac00ccfaaf2c30735a9ffb538831d6e0e65938a50097f15860f6acac014149008fab6d2521706cade5b5d45c3a347dd2edc9a728d11e66d8496bdd6d89f6ebb84777ef8b7cb75998bf98bac30de17482cbc8cb56ed1841bac94887025604e703cdf1aba13214c441278ce5dd9a432ec9fd0697d20609117b660f55de5bc9d7dc7cb1d533e1e0f8ed3c227b026342305ca2028225ade412fa326bd6feae49d2bc26dd3d60092b451d8a60d95eec600a47f030ed81670d7a9c5730d3bee9e9094d517c9b5c36a88470c045b5ae7c4f4454e26f0666c1d9778ec3659041180bf077f3cb5c5894c2533c37134ddb893165a793b598967f63ede", .None}, + {.Sqrt, "3a3e1b082ff4d60843108fa692c2808e930d3b7f2fbb56ab3a87537d4e14e212b6e6ed72c922727e8e30585f14df27e2cb44e10548ee640019b33967a33606e8dbdbfb93a09cafed6b82542b2277fadb3f62a876c7ff5ef45984707f182412eedeca4416f60038b725e3cf7543c9bc4359964d62bd905724d0453483d30a0fe7e075a099e72bebdd808d2d19e2641360115e9b603c359a476f86aaf52e5dedcb1584a467561950e7633319ab5106cca0bb6283942da0791ca7ef4d6af2704e453e17cf9ce62e58e271550d513c031beda4a795aea864d36084274484cd3f4195774c792c9bd4bde73776153e65a36cfeaafe61bdfb538c85bc35af76c11b9c7f3677c1aa059622eeff38965f0568c89374e7a121e19f834c72f01fd9f84af09b543b41bc9d81c8f70f8410c4fc60dc9282916c2e4dc5e4fb793ace4db347684d423021d2b9812094a77e318f48043267d31cd4024bb8c1a30aa866d2aaa68e9bedfa3b7c0ea7f580f0d8b6ccf05d97fe859726dac712c63f16f33a5d0ffe692b868a495dc22ba9b4127bfe5bf4bccb3abe071ea179b5268e7f8c8a68cb002436e682034154e48b12bf312ef72078b79845bacdc4928bfd84024928c16997b640bcde8c624b0d2fb216a0ce3ad5b0d55f89cd3bbfb9c3b715623e906fe84d42216772509a3c6f727e3291c890e7c19965cb9cf7dcd379c6ae00f544932d76764f", "0", "7a1b60a24475d0c459ddb6660f1126106dbe95b6795bf5648bb627f62f454d7a3d767f10005f1dc8282db3fd025f3070c7656bac60185e3c809f9ee27152fb5d5682c59ec5a0b9752e7484812ca1545c74dc6673908b3782eebb7f16544bd795491a75e9284313885c8a304a0ea3b096aea1a59519934cd9724917f3917996a7ea181779b29d84500eeb0d4de8c4efee695b55d2778bd6988e8fbefaade4d5330e980cb1adf926f0544bc2febeafe21175c8434aeea803c914c87cbd554c5f771391aa787e6081358e46bdc865a1ea0f73a37c24a92683e814a20be5ee470204caa6a9607ad5e832d04dbf0951a69e63a84d8ba0426c81693d23d2e75e9ca0c8", .None}, + {.Sqrt, "621619e346eaa2034e40d139532d468a1d19ed04a45b4e619f1a261998c494766cebdf92a6471366df24e7a01c9a01fa7b0a7b68c3a8b97875e092036839a13a888ec4695c1e89c5ee4454a86539d88425725776606c3a0280eeeb47d2edc5cb8fef3d2647897c0b14837374bffe3232a30d50cd84cd47a921c3097e250092234c256d447de35f754aaad7e87c3f0d128e6315339f9b76d7cd2ee41d2a42d57b5412d36c8df0f9f49794c40f310d90c9b787a005f2cd4e184f2a891d0aa60cbd95aec63e7ac7c2e795c99c71f1913decd1af61150a4871c1f985384736344335a2d194243dd050187a221802dab9416d0a495de915fa4880dc1f13a58aaf06db8b5537f5455c8ca5021c812eeb20fe318656f4a6cf22fe98f558d3f8294e0a0e21257480c836d2d8b8e375749f09907eb182da121d9f877b55a5625a502b5ae8818e1e693d4820d6c3c11bc30df30df922c02d2ced2aad9653992d642d33a4796918bbe12d3b353ea7a8e020090f5a69b48d24df76851787c735f70b4017646e7c24aac630b327204a0d76e9cc545ff5eadb9912e21035ca0f0097a6fbe4e38c5c75e9f5c190e9aac49fbfd55ac1304f6df2fcc63d869c26a519aa0afc76f3dc4df457406c49b5c3cb665e258523c474fcdc6772a9aeaa8e258f8dba77591f38650a2abde593cb66948ef2176d4fe1a9a688815b1b6e9be7b03c68fab001f4a1", "0", "9e76300f574adbd3a22bee057836607ab7389e2c8cda468f446cad89113ca6572c95d0355d5d65723733cb8a1faf14f75d49fe6686d172dd9546b5c3156a1f15d4ed1d5ee0653290d366e912a5207422e680bfb05efeed31afd84500ff141d4f63f08a57a85f7ed4fdc0a62cbc9382e06659900cec568abda8ff49524c28b369b355f12d8fea6b7133b429046e63c3dceb88748328a844cd0b89a21571541ee91f6f39931ba8b32086ef2459e1a7b82ccdd402ed191f8245c7c9da3ab51866372f560d38def735387e207b49a9457050e35e2a6c432cc1c6db3948937ec28c98871277b1ad80917b95954b936ad07f66e57cb3bf1e6f7d9bf870af6df952be8c", .None}, + {.Sqrt, "2e0401a39b0db091da990d98aebd927b7e1fd148b4ea93daa95adbe988195bb8868b7f9890e789424e806b2b392e91de3bdd79e6c7b30e963cd49a2a3deb5acf239fc261dbae2f08ff5dbbe6676b10ffd8a3384674a44fe67b4d7d9b979d080a49355b100bd4e53296d67abe6383cbb29d5d2734a4fc9405cdef7315605c208db18897da682feca2d7538b45ee01cd3bd3d3d2eb91028d70c3afcbd9bf846e640c6a43d02fa5de3b49634ffeb01bc9e877f49d7b3290de656498d61fd52c8debdf012972510c23ec502e1a77d776d132c10c00298aa40a1088de560a97e8d3766b7a32082ecf711167b3827c402447b203ec9ea3234db44c0e7bcdb1a93cbcea17d9a671576eecd156e4bbe8aeeda0158194a5daf0f4a0c7b4fb5cb5775a0be040e6d15db26756eafacd72b42e18ac7262c5428f68c4f61459c71be2624dac6b5f05e71665468a16c9cfb8ab1f46ce4f8d47a1e37af95322a011323fe485c3b3950ce405b47ad489c93bc38a4d4d640ac144c5b5c96deceb5ee93c210386a2a4f480dea8b777b1accfcaea5e313eface4891a1980fa2e1279d681214f05784003571071b6152eef5f1fa36fe2e51aa6d2f61328573ab4ccb70c2452dcdbdea4488d9cf6bc4436156280b787b263ac8e48818c39a4d4ab6c93a7ccc1aced418fe13d6bf6a7273fb52b3603469baacd84b604d11eb477fc4d896048135ea648e0e", "0", "6c89261e8f042f63a0066bae765ebed4d6cac6430d784d50a0bad45f67f095c291c40625345097c9a5caf1cd576ffa0991d30044a7f259d7c07cdb6bd8821df8d85c9c2d728ed3c58800e5a754f3a3acc51af8edd4059d3020e27b44b1b25c5a57377d12e02940a5660d1a81aa2a3c45f0cae8f018dab06b500f9c95b20600c7cee3f59955e9d71796dfd9adff22afc79a51159044972fd97c4fbe3f5d0159276b9068a6981b1ff3385305f64c740567e1770b4b28f27df702c24529abe1701b94965a717aead35a4a137aef38a08ff8effc2d67129db6aa74ffaae197c1e7b1ce28d45a5877672808b90c8fbc79b98bd25db3b006037fb471c216678100f2d5", .None}, + {.Sqrt, "f762e9c7eb4574ecdd01c673503fa05ca2a259ce8797428db8e696d09153bad6ebdbeb094f10fbd0e98269dfd19889176e226834841f3ca4e0f57e2f5ec49a2066e5d55ba58219a8636d06bcef3e22bc6f417e6f483097657b8a620e54c46fb4c764b9a2607b0f106a54669d367657577e6bfc7ee6a3bf955218b2ecfe3316784b806490ac68cdad2a12e127219ba0c44e89d1421777fa805e7af7b1aa87fcc4d3c0f3cbfa4c8d22da5471e84d08905b84f693991a8aa10d01a8cf29716ab87473eb6e557d57a403f50a0fd7482eff4547a147b7514bacdea659ece1802a470f7c031872d1c7b6b19ee9e042d76546f0cfd5593cd715054ce4b248b6cee2306d6cab8368e88c29d71d121b751ece40015017777f4123c2a440b2f502130332bd7d6f532e1dc278e34755792d1b9891890c9c7412fb9d6380e6a624b380673e4aee9d336e17f9c3ad1ebd445f296704e1c324c6b39e4ea2bbd846646821a1272a121a64d13baa566c89ac9cf16069d6a658cfbeb3c246c59d7a5c17a9fc58e7a1f297a6de1d67290f3dcf4f8936b9377d35acc83407694fa9ee6f99a87777691c7157ca23d2675522cd616fa4709c9de975aa624d49729c44ad6e2c7ccfe16fc9d68a6290ab06dcc486a11dff764ab8db4738154aa3e1aa81cd49c393e8d6c2c9bd0cf675534e142c501659230baa23aa162e1cc45d7981002536251c5e5e2ce4", "0", "fba805dd6f6d8b59cf1235e4b7e53a8b92159ee65bf31e028e130887c4a13b41a35f6059087b03473c504140057f2118d9fc433a92aaa03fc57301d7a2bfd5f9e13cc2997842733e882f6403e5e78470e4ecd85e6afae186b4bc94704a969ee004fc06228c7f8988d5e3ad42f34721c31f111f167c34ac509e0953c91fdbf7a04f347e3001d3f59ce464dbd4fd8b7e342f17d2b6665f4788ccbe353fbd252005162775233e1455f94f890ead74340e5a67ece7f5abc9d27b6f144542e7840dda148b217c3b55a418389312997d0f6dd120d6740729b9ca898f232a0344334cf32ea3ef280737244d2e7a53cd8b1ee324b9dce15d7043c8c4e892ae010c09a0ab", .None}, + {.Sqrt, "d8631e4344a67ada35865003fe6b6d6d642dd6493afb1aca607452b348818682395cda759f4b84bc7d580f8163d3318ca2fba6ab443900b3bac44ab33ee7f148c81cbd5f080cdf82fe532e5a8a5f850d09ca4acaecac7ed0342ccb26575f4403aad0a217a256e7f605c67ea3d5b5f70bf74e30271c0b0cbf255284761acd11621009a52ab296fb90e75942870fedf6dd5ab8e506a8ece5fc4579ae3dc18ad8dbc8de7ab1f9cdbfef1a88d9b218df6efadd92c2203d21be02462d60fff9aefbaa7e8a86a1750c62e591318436040c4312612c5b97bd30b4ed028bb1ef887220e611415673f8f38d8ee86225ac8df79f2492e70f15a7c3be2efb82f04b6d1d74b8d0332ca803a2e6e00d8fd0a29eb7aa430cb3e35056825a779e6ad226949c5e8e1149ded4d58e654b396051945af6cbd69702cf319542e520b7143b66200f2a1dfce88a128a1c7678d5395ee8a702f1f330cd34ce0e4ecd1cd2f4f5e940d719e05ea24df4bf39bba8da0381be6ffc9f19643268c8ea4ca3480c489a5ee5b1d49b37c222b19e159d2f5c7dfcb41679dc9453fed7365edc48f62e7e76e43764692ecb7e0f2fb7122c510670b1a05841a401593d540345fe6375ad34f85886a6d6ecc97775bd15d3a57c90fde861e27ac4f62e41488bc5b1c32f6e5eaf646d48924b1a68847c1d84a9ebe0beb4f590d2d190e5ac314b1a1493f17086057242c4ec13", "0", "eb5c96c1202bd466c23fbe1ab563fc15d09760dbf398f449785fa484b99fe83db394ce450165dad4db91a1a5418670dea49f2222cc4d21477df6bc2771e4e76e64176177048374b3a6bb21bf81371ec574b309c97ec0eba3f9c93223dd0aa9d383e2b03f4373e12a29e84927b973a72363fd339062e903f107bf824cd802baff10f0621b5fec49d9fccd5401b55ed90b30274cd76cc7bd98c7d4e17c6c72ca3da75f8a5dc10707542e570760583eb4802eec46fcaf80d7c6219f29e895654855b6f1660b36b190c3c174e464c39c6c9fe75e2154a757284c75c3c6f7a60125ba8068fba4736bbc1faa5d77ff09c4589388bdc12af39cf5164ca4c42187c7e2b8", .None}, + {.Sqrt, "7b8e68f4c3a386fb1f73b72b5609fb887a19147d1984141b7dd37e4871c93c5aa761e888dfd0aa316766b732b024dc349856b642fffaa701c53e7a168e073ac945f8ced50010c83839645661299324f40a35fad5e411d82a9e377442ea64305d1d48cd1727f90573a2a9feb796ca95278dcab98e30af3951b147c7cda8a2318341f025ae7730da98e3dda9c90ae6cd9e8fd0e774d5f126b47a6712322e2ad1236a2bdb130725c768db1e7532a57ffe18b0e9e30203a11b4c33505a25ccbdf9aef5a68f09d4b19c44afcc4bddfcf0d6d6b3fd0d0368c69d1a1a91d2c9ca9cc58380bf9ca1083c90e2b52d9cf164108400299eca8a3f41e174ee8369582848a98f692b0a0a296110982af3184925b603cfe4341bfd77d65eee5c9fadc995fc9bc5fb1c3371edd226263829fbec77124c08d836d8089a7ddf0b56ff241ef508d726454c2665b4bd521030251699d1ede80c8fdddc557194471b475eb2cd27ab1c8b7c6c58d656fa6eb701693423f11752484d7d4560a3483977263c626e1ac7763d459d26993a36e0fa702b4164adf0c6f17ebfe2ca4983ff4b789b360d031adf3f6eb0291ea2a69e8b462e9c359e92a0a4f7132686ce74d05e84a2faeea491a7b90083cfb26d00293259819cedebc4e3755ce3ce77a75b156b64b56f7b5a3438860bfff44521cc95e75a3b07b396afc2bf74608ef15fdf2ab571fb865d1dd5f51c", "0", "b1d97271ee289313e85ffbab342875de0bc5ec9b012b372515b6743faea9e4ae7a2a935d14f93249fabd92cc7c2b4e576c646c53d84bd5b31dea8725e3293519228846097ae53d0335f29a6f844b4d45f35ff4ab162e38254397201dddf8d4939b2d68c3adba348a8af4ff4d8f0493f6bf7401969cc2b225cf6c55623197612a17aa252804f733c09382d0c4a6d7f3f6cfb95d38c9b23d374a424f201fb7c91214019762e23fd42062a1dddb1c1c4b922ce741d7e3a142990f7ec9a38c733b0da5be7af00f1a02569f745d94c4ef966656d266e05692c0d0e8eba519f07f885f5efbd006bbb4987b9e44b5375533ecdb48adf3947a49d677236f4741c5594189", .None}, + {.Sqrt, "b90efdbf64fba5d91361882439dd216308626801bf0156a5aa295a9c32bbc3abd2db4f6d0f8a206e1a138addef795a9b0c7b1e72c866d3f0987ab97dca5b82e7520445400fe995083cb8203430df008bad240ded223ad2cef0cf6182fbff1623d33be1b496912aad6d9d75b1969c6eab0fc65d3e9d52a6fb79d1d9f8fb21022a4adf3c0d5c4783facf919d3c69d91baea62de31fd93cfa0730823e1574530cf0059c48708b10b8826b3396c67a431b619c34157d1028027fd590801cfa9483f15cacc874e6e043f1e430156c604f0b2e4ee26e1e11d09b7359da602b1838d4c8bc470232883f2ceeaab9c6fd42b2213268c6f035d503fbdbc7c390ac7003b8389d7b36046256014907905c5db56b58494a81d2c15fbb424249f2b60a3da336121bf2fde4da51d27fbb9505699247a477928a9bec50d813d240bc3a859ebcdaafc6578f1156c7c5f1cb2bf73a71e58830838eb8bba6be10df8af515996648e7853745a203896e354e35c578bff2b2fe86ad0cf2a1407f8779b7dc848b0697f5888af827089bbf98c3aa1c050be468b719cf4a34aae58cc1581571132c80b7fa9df5a8f5b90d8e15da43ebbae48c5855695219e86f23226ee6b94fda1424cded810dd06fb17571f3347281a00f605d7c7b25fc89ecda4584435156dc2f497cbe4e42b8426ce7aef408b61f94f651be71770225ea59da65ea2d3f66125cca93cdd1", "0", "d9a8709db9783b5457d848fc608d0b9dab4cb6022eb1c957b217861c4e527c16def958a70f9ad5229f78135d10e4a9a2eeb29ec2fb25590d75aecd5ada7ec84564494cb2f1bf51e418f6c1563dc0eee197129f81cb6ecbacc78940112aa7372509172fe8834d4c66e4855b1fda3c2632b8c19f16bd5ed56b23eb9bd13f9e04b61c2ab348f43f48af915fad35775e2f0f666dfdfd69bfe37eec63ea8ed33bc5719907c2363e56b1de0532f39152c69935996750a68571825c11862956e959cd4452a987f79c6e6d5e5fe26d0bbae342d86df5172039dd6b06586b23ff836469776190b4951e73df0749a22d7a66c200130d147f3af61ff91bbb37b4423a258ab0", .None}, + {.Sqrt, "6e932f672d89f57198eeb25665e2fa1c34f8c0d623640a5c404833a23956d531465560361af2244446b0a431fb53a4312f119a4e209da303a31191666ab95e328aa0ac545816b8b12796ebf4d5a2b7f6f25e15b12255979a28c149b81e17c08a317d5ab19225b991fb58bd7a8c8f6c644971e8b11b30457b90b7a97d66a374945f1f4d96f69d09fa2a1278bf8acd49a5ea1502e82c853174938efb43a03d416594c513abc3086ccac23e878d2ade5647c84130cbad514258babd85883c324615e087c8062d422e891321a4194e94446c1c36731158cf7151f20f1e0ee2c1604bfa52490f773dfb093893611f9ed5569cb5a4aeedd24c12b7c163d15e2fea1aaaae546b2b428de1dd380e03cc7d500f1da0fb27bb91963cb86c6dfff27c33e7594d98b8e77ce4612e5b40e5b0755d57366956f99fa6cfce505d1d89900db6d18f52509dcbcbe3e6ede70bf82df4cab523cc783bdcb6c74fc30a761abe1f7e17282704887d0e6da37e8fe5522559ffcef9634087d95780ab08a4e1bc86209f3929c33a07413842a59880048698d5c06727d339bcc66fe51537eb3b6e1acff35fa89f716a4193bf532631dc66642a66ddbcfec24082fb027b5e5035face8c491825bd16f9f8fc6eabe4aadedc5d3196b34a832d304864afa3a95a8e650aba7e0785985e922b439c3457beded4df58cec173759b2bb6f52e1660e75a298c6044365c", "0", "a83f5521a69a5bbe24ba059378a92f7a634a87b4e8f5d33a9877a89d2d0409acad7774bc9ba2cd6ca9f60bb766b4a7d07f89c26138f700941f1b6090726a54e83b31b6ed310b0e955466d61a0c5ec817f3378d341e2c466e21472aad84c1ab9e0a660893957d3b087cb456506a1cd0319e69aad3ca4e6093922b7ab1c5c3c55e9489835fae0c54b2fc3c97d0139b3964fe18dbb44186a9863e6fa55654ad3e229c355a86fee5dfa1697d8538f8b54bc84d14c631d9630132f83d39fe422d33052bd2f1da60d88fa5e90bb278e0df12d98269044bbf855297df7e343de0ed6493c33ff7e4ed70461bbd35ac89d2780975d4fc316680fdc4c2361149e282315cdf", .None}, + {.Sqrt, "d1d25eac5fdcaa1b72f49806acc85e29d01d951b54553d8bd8c09da919a34915a50da2c06d0c3ccef22f82fa5f7f2eea969e93eaed31f76f8bd7f24edc7c3b206f2b47a5b8dec342a0b355a56be8f6c566733c8be7357aa789505058ebfcacfc6693bea40a3d55306e9f113dce99bea1ee3347c5133b769c79ee72a795ecf721c0f19603746b92293eb2ecf303392568396c7abff77a0c584c9d921d1e168b238851b56031f842d33e80e8a5666922b6ece2b6ba7ea14238856ff16d4b45a75ba3d0c6159816fc380f5c37f28b286fb59c05532ff27d6c27a876fcd81ff0558ef380b5a4b4307807d329008d272663d93fdd158e194737e79c5c57e845dbad1aa87b0a8af86cd686480977b4655d4b1722d9749bd7119b33a25a625d84efb5858eaa5ac59c71934a0c913e9c7aecbf09627dee87263f56b5f837d5b274745d042251076332b5cc8af99ca4650e3c48d1af02ec4ceefaa852fd682eb7abb78662d8a8b855c89f4e0c8a90cc5090a43c2e006282262ba6ca31f2f20f3a353441a38982a8c9d66474ddca788dc621be7866a3b7df3935d99a10ba66379c256e87cfe72baef8620d07a663a8d7af3e36fbc483278f1aabd94f66f1931867ca4adfc896135f5a3c29511af1990029b2d88c280a6379beb3c15e353d32d3108972f69999cf5c9db2a5b11fa5cf76710dcb9fa30a92a9b7dd025c188d5a8a577844af32", "0", "e7c37bca0140d76569e9ffc995857f64f9f9b7a81f6b81d1bf5c8ee2b83cbe547a6277324dcceca709b9509a94d1766e206f2f3eac3402a0aa0d4efdd10c432a47fd44ca2d0ef17eb829664ae43090f1ac84a3c7bb2478bf7e3d25d5afa4c52ffbee1b011286d5fc6d5f9d4c4588378f048369250d7c982b48fb7f5ab212c47db2bd70dd265355fff7380145447646e9701e35c957e0833ac74427360df97f5d2359ceba2f11236171bc6b4fba0f3e9372e77a373c3ba73f945c1278e6e5f79ed4c1651bf18f410dd9df9e62d8f090573e01685d6d28bc9da8460759fd733fedaf8e717db447188451d0decd1a3cfc5a8b746d613ca91d770d4742957b773d80", .None}, + {.Sqrt, "e34a63eb6cea6b4513d2295b418850d9837b3e18b44b470aa7c982f00568e244cc565e45214e111535bbb7c27ee1010318cb6cbcdc838f7f5418ed6f0d39c062ae1b1bfacb0859d59466a2deec20b45ec8038e68f204f9cb7cf8c028e861c8e32fad97f97f7ac9d65e052497ebccd2b32f51fd8041a4a30da24f617a5eec57b0ee8ff44f2cc080e97950ba45a761b995ba13b17eb8c24245e45e09de356d2b164888377f1a3ec7f7d8cb607793f1232449efc9e224e93ac7924a274db2ad08fe9ab3cf50f576d4d4ce909e01f8b9a69f1809fcf1f7463799d1aef60c82677634e2e37d720eb41e66a5f8d6fb17f231b920c3480c21eb177822043ed6d0748df05175e49aa90d77361a92618d8d3611a6976d58ebce7ee08f3bd9e25f7f6cbc65b92b499916537193cbd7221c0693e2432d75407bf4a012ba70a397f7219d5c123abfc1f9576f62896f2789be4cc452c58fb61d5d4b4e5ed984476903f734db2909dce43e6a21400aa23b1ad185b51845f4203901ccb46ef768196ade43f67881b92dbc1626768b8d25cb559707b86b547c8a253ad618fa9d7cb3f5879d7d670407977237636c56da19cc71b9ef1d4260a403e63cc403a7b1ba790d1c14e6827b2644cde559ff480d975c11729e3d4d448c48b574419cd9632094c7dc3ac6da15a060f3b493a73acd6b42dd1e52cd206cac698a8b41fb66049329603d722f9ee2", "0", "f137f316e044d792d2f2d21504e94a9e5d9c661918049f770dd9302ab2d73dca4d7ca121522ae36cfe29fc958cd3fff84ce0eaa27e7f25a853fde8ba2ee4d293efc00ea30a1b0cc92ab0172e5e29c856c957075d0ef06fcf01799639561fd184f4244e34f60b242f58c9f32c7ab9825a5a973e96f23ebc451febbe54589e3aef17367fe6f9b105869afab8ee3d2befed1f713a21404ec6e64d01df02aa855acfb703b79a6578b5aca18766606ad45619638146d815d07f46035c249d80090f4cda0e309384b92e8e750dd4290322bda68710c465b665b40da17a00b09ea1d42e7e7cc015d9ff68237d2128407fe01501c02f2dd4bb34c2e104d91f8ba00d7965", .None}, + {.Sqrt, "58a123c1e709e7a3472b128726e6a2466f847f512746a1bde5eb4f183f368d8c81d61ea647000aac921626fce176f36acaafe085a178e9c35a087c35e395cea09aef470933cf2a50971504ac3231d3bff11b027de25305f1434241299e8e626d116e7ac634ce8fddcfd082ba835b6dee90e49a165e08ffeced7996a3eb5c07b05a6d0c40cb3639d9b414ffd40db6d2e265abdb516d979d36c4cd83eadde0fba02fac687dca4413778904e77cb339ed6385a55dfcf58b8ec85943fe81ce848c0afcb64eafbdb80cd952dfbb61dc8d808782e00ae2eeec784ea6fed0f0ea0a74bc6bddc8fca5e5aefaaae592b7184ed9ba53bd5181515451d3bca14d7b28c4406a1bc62d899d659772fd8678631b47d36674f734bd5a4c0a3d48ff84f5daa9857bd31fb99b10e4747cc187d2e11e18f1133f22181455ebc46cef5229e5db0c82cbb61aa02950c03929dcce1922fb95680c501910ef5a1b74cd139da94ca92532c323b1aa8a820a5ab749155b1a01f54d4a0ab3fb5165c72ad3ec9e8a8d00d8ee64073795551189e4fc903f5f407fb0ee148275d311d625bde05628d88a5171b6f64644e2bf26aedee16058547ad2e7c2b3cbfcd302e92933cf0fe5952c2ad8a533d5e2b1d2c55bb9cf42dda34a4b14a3516bdedd431025be76aeac102b97a846f4f14743c9500de0af3b5a6b5363e5c7613e7a2b8586883dc3838d6c1edf055911", "0", "96a10fb946da11e11214979d52cc1edfc6785fba09cff10e4cf3ea93a4ab46c1d9fe985cb01bae519991cdee9e6afeeaa79f056edb95bd59c372eec7df995bad779e2e97d0cc0e624d096b866f926d54b29a4f5523e9b176a64abdcffa6fb232075579d076f29e5a8cd3d3e7430b9659bfcd6b55c4b27690dfff482d35c23a74d112ae30d14a28869bf65723f3d733244f6d4e9944c0479956b9920b325e9f28964b7271acfef6ac54ff7f4478d754ae3f4042423283a8190a6b19898be06e8277d81fddace5514171b7fc0713768e5048bb25d412309f2fb8dbb43f28c6dab471d1583915433b458cbf1065396c3ca0a2a980343031a127297cdf35c8269dc6", .None}, + {.Sqrt, "5ebb6d60ea600369d3f7d1cc1cb521e4fe68a00c1e752c989fa3f9ecce263228389463a93640cdb83cbd8c1696249072b508ae8cee8478ff096e38fa48a2343422cb83d72ad501738a67d663ebb71e18d55abbd8d806573217eeaf1cf55f18521de03a02d65d498cd14c70a00aa24cd9a6f7fa0eec428bcb1b2a676a068f674a80475771c8753b84e109bfbd8449df6c0704e8f3e743c2285a53b43af692afa8037e67779d90dcdacbdf90cf7a5508ddf2bcb3ee133b67b02a544e3dc0c50495feac0772dbbe93783261763d828abe68caa3627a5ce8d81d797a7783b8be5ff04304044ef5cdd52a9ab38ee5ae81ec625d48f6348978f444710ce9a6015ccd4be8a1ba9738d13aa0c110388dfe46bea63ecb1b2bb8d7581f73d04ffdcf023652e1cf262898620e79b5d24da4b61df40c8589019951eb1194ec3c057a391be81a5a548d976b386e5a49ac99ff1745854b2d19af56b467ae96fe90481de452deb13f0bcadfe18813aec1e9e1d3aa7aba527f01194457fecd38d7b9afb045cae1a00b1eab8f509f9427604467ddd227f89952f65bfb3b5e29fc0ce47d7416a6b1b2940393f1c21ecbaf6fb1368dde4ae4d20189fb0f805b1de267ca44fd416da0e4214bab0567e6455eca0794d107d9a323ab94ad59b7f1c8b1ffad3399773fc30c6655cd258cbae93056f572d3e932214ed44214c23fa70b0c6bc5aa1066193de1", "0", "9bba8bed3e0f261c1af644c2acb634bd6240a127dfac8aed6bea04b752f3454a84eda6b0626e5cbf78c11871827eb5638b9180b5fdf857fb9aaaf8043d54c345afec28df6cb7266d61cb6a7fb7e7cffe4828df6b7b425f201cdc3af4b0fe7ca4118dc653acbe4506f5dc7133e5e7c2cce85997476d9328c4d7f7316775fabcb5b9f652996909cffecaff2bd7bb01292a77db819d6029566daa1f096e5404db97d3c52eac1a798457202bfa32bcb21130c9e154d515af7992eec7486392786d05845ad28516208501753bb518f0eee89163b5cbbcfb64a77618af5f4265a2e0c5edc2a6fe8eb2c33d0ac58361ea6c016be56a18047463acf156be970af64b2c41", .None}, + {.Sqrt, "55989c2433b061766956bae1b72946b41df6a35c6d26d10134317a37b33907b16290fd7f5eba952a22718f430d80c3e2cb608eaeb714897d61cf4723ad087dbf2b4aa2850857a090db57c01c3826e6c5c7ac2f9b67f78a89f9e8de9d345da4ee59ab9cc40f59a22d7fe0ae2dc109d0a6d60ea416f72ddcb0c08f05474650c5f53735ecbbc73272a3865112086bbde282c461679bdd90c638a2f4905e1ec52255b1d14e241ae0268cd4202a4fca70b939adcb7d5dccb144562556c664f9d1f5ab99b5a001727aa3dc558e7597636e1019a66e010a8932685fe274942024574926548d6eb0d5ed32ec1e2bde6727daa05456d22f7f0793b4b8f4e96423ccd7c49874c157c45797c24e3a25da647449cb05ef5b06667f7d36127c840c96f6b35a43577880e0cf75e1fa9275e7dccaf2cbc47539ec5f88b6c81a881cdc0a48fcd27d2847a6fd2e11aee85927371f4a48324d2a13eca7a627601d45eef88235cf4a3a80c359562e846f701bbe5c880157fdf4cfc363e1ec488420f352c1f629f5b92e51c5e18893cf645b719d9a8fba531ceac96036acf608ca5e46181a976dba1fb860847ca3fd6d6435c7765837a74249493f441f98b8f885ee768f9733c710862cc670454e9ef12fd707413e6d806f003728598c4356a0cbfa94421db70e707f8443b95e36cec92bce1734812640703798cb430d602ef8351989c3f94d169557b0", "0", "94077218e06976d778671d913826b6325e72660e70043323bbe957839713ffba809c84f299a29b8d5dad38ad86aef3db08e66a25de2c43b25ff2e57e97c8a1ef87166d1b9b6ea4e0fd9745e8cd5291b3dea2a567235d29da87d5c6302fcf5e054565203892c556737a2b8d46cf11a0f21d04ab048caa7cc5e2c4e146c51e3d8958b739eba640ec4397b8747e46528f8abab36e3d0455f2f528481ced604b38697cec09eb5d09c0469e27ac664075552de209e1919b45ebd50176b7a434e7cd54eecf0598ceab74f180e1198682eec4bb6990edc3acc3ee05dec671c443b7060ca3ec94c890f967e6f7b9edacf5b2377844f2aa0b1a2a4a5378f3495dc9d40bfe", .None}, + {.Sqrt, "b198edcccea81f69c7e883c09777658f7941a16c3e6324481facf1b84c44b87fec3683b60f32e8483f71b09a418fcf1ad31a841c09a1b4d99e8c6a499fe824fc2a24bc8295f8eb4d2a9acf6565b19e0357eb8b2034a4bac50e08d6c0be758afea9a24cef62f0cebfa1cece570b54a052e2d2b6e0c2e6515e3567424059b0870f63f925cfa3253a8c798142d4bcdf62cef4e10f8457375a504b3ece62afe7ead41be8883afb576856cbfb60dabcfa300e4657f8265d72f5d896188f5feb23bc5debbff13d2bc0801d56e418d00e670b35a58d99722f3dbc37505f1d123a87fb3031a47082699e0f9dee4cd130c9ff451a8a2b6c474ed54145db35ebf9dad86315fa1dcfaf649472d8363c883462f788e251ca8e80fa27c95b061be021f37430275625383c7882417717dbe67bd82718ac2af1b7018cd94a45d2a250e0dea60beaff961ad21e06dbd7dd6ed4627d42cff22ec614c205f61e187502612377eb7f5f56a40c946533a374bc025b53817308f5c71bc230b82c11333a45c6887bb9f2a84f968ae208013c579b73d9d40c96997422e2ac227bf26149f56238ceffa0ec286288792fc27dfb471ac24f215ce58e1cf2a40cb0d862f8f12bc9fa3dcf6ed5aedd3ca13b3468e9227436e4470e4337fdc8482b9e81c0a5f16168e07a622525e986a8aee17705cdb2a06574b8571860c6a08c0fe6b931bcc66a3ad020ac143229", "0", "d5399df23bb232420d3cac1e1f7ea941c37a97f701523d3017a8eda50900d355a80baf4e4c6f773689c0bd4b2c6e09330edae2db8f7ed67885064930c248b6f7ee47bbb97baf280d582b4c3f629a2e9d520893db5034354f0ec72692defba74a735260c4894c66c59643e2455dbed42b3e4e04440b211e9307c3a6a141093a44b214798e820ba39af82c6367675d68434533e4274ea744dc4709da5d4da63ef1dce2d9b5d93993eab03992d81d8858673f81eb73dc9241a15c94626ef00f3996c001828d20e249d5a0abb1a3bcad60aea46cfed8d00b91873dd404ac3b4f563fde8870b522d826ed8e780b2974559f62c345889d1245b8c848ccf99ee92b0731", .None}, + {.Sqrt, "9e07045c74e1b3ce8d33b2c8df28701789abc7031fee17359b4acb094a0621bbf3b1355296101d73e211fb2060c9cf50287fbda6b27dc8133cce8728e22c386e8974af727dcfb5e945b91fa947c8162305a8c243d8e1a519ecda31b96a284a6b66e4b52fd3451151c052f4151192f218e00d614d5213e3f8632631be79f5da10ce44c79597a23e2c032582ef04205be00e87d64c05c368a9180926b8c9c29fb42520b909c81481c73b8fe28cc93ef9cd89666ef7c9881292d72a29f336b07cefab216c17f90d6b58ee16ed6342b1890435f08ba1b7d9ce69a97ab1a865e3668a247f2fb617cd528a20b4341cc6ef00b7cf0dc7730727dbf7cd6b103d341d93e9412a7b1d536df137ed20119ec6cf8826333bcd5c07641281754b8575cf7b2cdbadb747c2dde93995ec886ee379c116947855668e4ae2f3dac92d07abe01fcefca1c70ffd88ec5069b041b3e3311962208fe94495f328ee5ea1a0eab816f1f3237982064b3ce8298e6b818384200e5581a99fe29295ca41e3e0bcd9aff7a06c8bd67fd1729671bb48d04186237913cf501bee96945561f273b0b219ee7dd059ea1c1cd311153f302721d525e8724945adecc04a4bd6913be4f29c3a00187fce0c1d4fa894668d82f4e609d7b92b4317dba1e06c6da2e499fbf15c86f6927ee31393c91cf012c4149025cfe3389e952e2d1e64c1414dd93804bed6c5eb6f63bacd", "0", "c922632dd39ac21f5782dc30c9b1cc4f82df2db72997cdf8bb1dc99a5217ccd32287f9dae93e38f499a066bb009da6f266a64c818d80fd795b03af346540f52c05d6f6d77630e444996fa51aa03d589e5e0521b083647ec2a0d5f24c32864dd3049366ce16e38ac83cbdecde875dbc39e90cc4a8d88f61f351ee305a110584fa18b40f0646bce307bd3be761c90b5968c0dbf280f09f2a3ae400619a52510bfa1f96b4f272acb16d90253446d1bc6b6b845ae4e5632408e065f1021c10cf0d0052f840fdf7f1a23f0cac22a8332105364a80f71ae9062ee24223a68a07b42ae8afef4c90f7ebbc8679ad975fbeac3a9584697535e7c4d61e7ba81acfa813051f", .None}, + {.Sqrt, "5477cfe3d45c6d1df6af994b3d03f2475113b7c2f5208a85a62ede0c39801bb10fabae08628e1ea3279c178e9bddff59a55dfb033646a13987456c4f3bf799d83fd657b560a8cf108e32823a4251caeeafbc65882304830d047c55cf94143c6a7f60dab8f8f7c8d4c53049567aef830a02e3b22c2d39dade47b28d7d10132137d93fe037d5535750032c1f56799e3007ad8922d069e713e7607686926e29e1c093322136784a892dc580be7c7b328452dd57aa9cb7a08b3e7a908df36c449a7a67067f8bee6d6125823513707ea3e49baf01cad45e3f0389eb5d4d7368351cbe848206b12bb095fd4b6fe770f28b2d87c59099abe2a958eea3eaaf2e9fe66428b3914d74be531842d6e06d5f18b3555b3f3fae8da5509c54bf6b3d394d9b3b52ec89fe4820a1b09e0b4ca876854c93ba3e20e6ef08593b2298e56742c1ddc77fa9118e9087d9eb6b6421dda2f2941d6f3edd6c6068102d8ead2d2281eb3f1e50f7a79e09f940bed72ce07df2f60b1a43204a5d77e0f9353a9fd3520a43b739aac1512f197e6cd848ffac25423cbcc70e8524b4431b019f107beedaf9e4e094a016ef8279270ddc384502ae953f1ca71c857fdbeea8576174d7a7cef65f2317a2bdcb4ccdc99cf2b1f48a41d78fb72bf9f46481f24a10247490c8ed9773a332413703d913417ac8a67fcb9577e29af78a0ff53efb199df1519937b4a7e3e37aa3", "0", "930ce537538a12135fbb89840a4405ab9aab70f7bf29b00a56ee5a3f7da79e7c50156077eee087668e85c351ce1dcfb0b4fc36769e1dee8155f02dfa6b1ad77270067065aa62774fb14e125cec22302a91004b97b2c5b014cbec5c9dda4f6cbe69f387f2269680561f46dcc1acd5a721efa7dd0edbdbc25fa2d722df574a0bcff34f264a36af63797689c8a032b44cceb20dea00f1618607babd0e5f8381189c3991ab9cac8b7c6c12e0d29fd8960850ed83abc199c43510eb3ca54903b0f81964e74949cadf8f238145b7d5243481d8d191dce82f330335064deeffb6a02103cc45ffdac2c30f0287978864a676fd04ecffd4175b3891efdfc9fc33d3b06bad", .None}, + {.Sqrt, "f63cfe2ae74f11e5669913cf7faf510817126df460d1d4a0ef2dbd0770cf33c7aa933b14f521ba68f1c64f51ce8c190a868ee52cf850a2135bb3afd3b92141bbb69dd7eac40d3d4718bfb60108b1d76b809569d888045afbfb7522dbb5a284addfe02a05e6f199ee1fc0ac1a6780a144fc6000789f02a998650af3b7e733d95dd3310df673030f5fc039ec2884afd6aa36ed32688514e4c2f7c19457858c3bb036baba115b3f8b8a0d971403e1a06426e9b31c7c47ed1bf73e669f45ce73692732553a3da03398ab1106bec68b794299208e8869cc004f38729b9da8c62430782ce5e9f047541244cfb34c2d9719649503b96e5414c0d2a0ffee85498f7c2ac673413861d26a2ef751a71a714c9aaf0c8a4e7b883dc9a542103ef1dc9f699de92babe11d255aab61f0040cf43ba7a29beb5216c64928191ee87a008e69ca403bcc25d9be5f0ebf4014efebeb3eaae4ffb5a012741e3b8a0869e9d5a88f0f98b188e329aca51b49e87c710368253927c3d28cf7e7fc3fdacfaf12129cfe61dcf597239fbdc2beecd0a5253226a33ad9459241273e2aaf55d9d24d9a1e6bb968845028b6112f2c273e079d8df839347f08c6aead2733e73d15cacde2df36e0f154709729afe4408b558d17d7a58ffe049e11c5835ee728c09058ecc8e78bd341af9a53add851822f4cf1fca9aed8ae4a1604b4e8b274eedd6a750183523fdf4b67", "0", "fb125a2ffc528487b63986c1312113d44d276270287288caf8a28db55e48ba01d53a4b630dd920f39f528d69edb5827c4146a536ec86b83fa71d762b05cdc52e0fc8c42c17b4b1d82ce5374f5287513ff16a03341f782d7c3236b75d83d0acb5a599d2789802773564e2fa16b139db068fcf22a15bb5f2faa7836a83a0ef8dcf1aaa6b6424ae72e0986501c6f762dd63cb7adc0a695b25222e48187d1eca2734d69c3e2905b7bf7d0d7b700e95773cc3bea5845f2bcbbfb04d088828029e45ebb2f7f577eff01417d593249b69a0763bbb4d25059ce834114189df18ebd1525f60b906114a68db925b975157dac6a1a8b60cef5b8955abeb63f5bcfc285de4f7", .None}, + {.Sqrt, "763f7d997d72c09df219fec0f7f2b65de9aa795c344b3ec030b18163a8d1b6944e316bc01a2f0f0dd5fc1e8af278e8bf53b862757bb71ff302b8b2dbb2ca7ad3bf19bd872759717f61a93ff6e5636caf3db436dcd741e531437b172df04feda21d95c912678ca7be14935c71bd69159784ee5f8abaac9283b922d3e2a3eb73a47ca8466b860f9575cd5931901f6a87c3ae466bbecec7f5731b040a2a1b70bbf2125cdff24f896045814b0278e0cd4ac6100e447ae6f9b9d67b925d84cf5f55bbe2deeef48d766dda999c2bf9e53bd9bd69b1fcdf543e032409b247c27350dc540ff60af3627f794bf50c3b561f287c4c93363544d2cd284c8cc22548c55d1c2ba37a6ff55b76c035313908e8ef53344b6c5b5e05ffd24f2ffb0e4d5ba3029c49d47bcc00cc828d298fce8f3ab589e96dfb5e8015d9e45120fdae6956429b7c3a4bc2d2a8af30da49dadece6b330369df9bae21151ef19efcbb6f3dab2d953ccf52f3a624266f8d25c2d437e6fce499448174667ff8ff2c7f3eb780a2eed94e35ac8ea1bcf5ec6b5d5d7e19e71e410fb66963b3fa64a9f035f66041593ccd2209382c6608f3d2e398e15d500df06915a8a500825b43c7611bcc622e796297bd0d00a63113c07ebc44042da6ffe40da3b57675c91c19d3c606b30b555dc44915eddce9b24c7cf7790b1f9d0433ce9bd98f455240e2661c2ff4425ee55cb4ff4821", "0", "adfcaec117adee81a758bee8c9d7bb54c1f8036b8ed2d914dc43613f642d1ddaefff2b89df4fc3167c857a5aec946034f3e449d7cec80677174185bff724ceebd26b08613bb0ccfb72cf4f6cb1d3326882218202b3117990bc2fc7a3ffb179a88ad3cb5148cf3effa76a55568daf93188529e6092806010b803238576d977accf4c112767863251bc60914091752f530c4809098ed00819333223b668ea10c489fb2c98b8efc679b3c9fe3fe76a4ea3def5f0e6ef2589efc8ebd957d77b5e0846d602bb1337146ac27d02601eb753ea0ec73ff92f73226d84d02d6c50e8f01b9340505c3c2cc0b1476d98f64c431d000c5edf82f15f4733d31379453393f5797", .None}, + {.Sqrt, "1231b4e63edf624aceddb03decb0a68228a0dbd612384de4fe2f49bd5b21e7e89e43c9f247d33e6eaa44fb5e453137cc8307999f0a023b461ef9da3de490e7d93a9ceadd486edeee47d265d028cbaa8b1a4f63ccf22b76ee7078f3d33426c78a579932d7f669fe6a07e00c1a3678429ef41608714724818fbe4cb55e2c1e506bc9bb95ba99e71c95e90b6d1c8d3c075cc11324e714f9674afd87e10b6044008ce60cabd7b719bca266d070bf2f4f61accd7f3906d611a61c3984a1d5088f4f774918c58281c74b2335637554fbfd5439f6c21c99ae9e7e3ef158f47e69ced82d0ef49ec540f1d41ae6e530c6ac3e9b7cf4d187d62bbb66df0f8579848160fce373c1e3450d5749cc375b4c5c4ad6ff9f8a194c64aa755843273e639fda72087233fdcaf372706eda96109019d0bda0fc6940208149eae2eaddd359545c76ec638aecaf54ed27b21257fbfed4288e0afad24ea36c29f8174e454c4e6c33738efcc5d523ac0591f8fcdbebf6ec643f2ced9dec666f14bec461802b16a105b1a3703a4c4d12a15b74ec728947484d9c103b73b8d1bc0f4d0e7d0244438c2ea89ea595e93373c6c031023cc18194850d658567d9b21b0530d5963c7e87b98bf9cd83f0a95f50dee2321f1c41b477031c68760820f907163edd017a72c9ee109f6848744b4dbf8b781ad2d4a662b3425842aa92690f76b8f354fe5c4c9d24b23af8f6", "0", "443f55243255bf24e1729389431ef5eeee87996335d7b1bb7c45458bc469d7a73cef6251ecd6fd5593f52df9e490f739c768afe08c8c7556d476361ca3d11aa8d26ebb07df2215153cb2b452d56d7bb32143b2dea0a4b7d1a428e24c3a26ba2b66730b0fe008bcca583ce09e53836f38d03c6a5f30bce6693832cbfd89aba3b2879fc6f27c36bb8c51f9b180e14f514533a1dba6e23c02892eef94fc5e03f994cebe0e879c24b2ce8ed155b000ca305049ede7e3acfb1b0dc85259144286b3aceb03a3b3f6e3d1131bf785d314c5872eb39d5b5b9661f2ba76653bd58d7c088995dc32f9d7288c5b489dfb909c0a243d2ca0a8fdb2ce272036c1dd28ecb5a8e5", .None}, + {.Sqrt, "78be68e1c8de0a38702fbddc701429e5fa8c8eac3c46c44fd10ad5ba7b70e5bc12abf92eb95214d7e53ce6dd76ab2bc48c309ed06fd44ae65f2795493d0aaf5b7f79abeeafd329ac9bb4ad68e1fc5e403f289cfe25238656e464bd764abcd231414430fd23dcd6e491c4b34ba7b0586f397367b3c1528d9f1ca2f7659991a03df382724786ca660283ae2a78371b4f063a56c76a9b9fafc98d78b42a7d3830c9b823875515ad20bcab2857072e044f6118af04c070145104abec8670f6be5ee53e3012f98e63dd5b36174b7bccdf39963aebbd0bf6fa71cbe88f8a838ddc22448e77a0e655cb635cd60094064ad996f347119219311027ab5e03a3c31f6a34905cf2d220e742838796778357e520ce1678ba529775c421fd6bfb16dda08ecff8edcc4cc44d1c13f48d4d140aae94219b3760b4172539c397da56bcb83531b5f88dcbfe246445c14350213f2fa428b6328f1b1bc9f3f969941816244a220e9f96581de38cfbf53c50f1eec163c2fb22bb28498e063e8bce2e6c4e18adf31b3c32b4c71f59a51b4df56dee329c787d1071dc4fd07c3bc31b1df1ce31b223b6512e81b6cd493de1a1ef185ea18e6b1d6dd305bfe0436e55799739d730d5a9ebce9dd2bbcb0b5c8c8f304f10a82567194aa4334459668ca3cf6129ccaa717390a23839017a8fce0d54a8069bebaefd3039025b0c46a843297313a56240d8f16f78dd", "0", "afd045ce76bb5b9bff0efc9fe1653feaa8a9bad6ff2b1646492e6d884915d48df53f0c71a8b19cc8ff9391748ce52397728f566d973ca9a7ab44f29754aef433042c2f37e375f723e0ea13cf18212faea78bb29e08eba308603daf77f82132896686bab8713e44fcb94d8473dfcc2a10f3be49c48281995caf291e1c76dc202530277434e5acb5d620cd8e76c86f6d0c34d3246eafdaea1f9d87850217ad56d71b4c75c748d82ecb8d73e5d99ec416540c15ea68a820bd9cd07c82e183f6e6a5ec548e2e1d77ec70de5e9ff17567b07c4ddad1266c6913140c4b0af394a1551de045f4b4c1fb0981a444dc94ffcdd29c749a0d85247b4f2c3b4fcf4afe6f0a92", .None}, + {.Sqrt, "66b32d3eddcce36774e0ae7e205566d5163336dd5b7796c89c7e33a05f577e881be0b3f9864bbe22926978a9e35ee3db02da501bce33b47a79763c76172832f9632fa274c72d47ee6e451849f1c6e4f81b444c3bf4ba16e09c9a5a9ae30cfe115a51160834098340e8eed443130227d7d5585029486850cec26c92f05a47b71b316d5abba30a692c22836c5cbf20dcead58b22d662879a1fe3aa28817397f366e3689d7e67fa222fc26c3394d10e9a9e262d06a8533d8a827bb6ad14bb2197908e4561ba76094e9cd5f6568099bb6db1b5d001f8dcc30cc7d57fa22b0a8ba54676173a431a0db5d860eef84ed43fb681f8f80eda1800bacb2ed35d7d55bb1d33de05db5bac576a9aaa46fc6cb4969c231bce25bf190d45293ccc0d8db3e2ac24afe6968d271e018cf4e54b1180c82df37735c8906ff1524701774aadb637df774b48e14d61ddcf2dad730377b09913b0c0e3bc2c6090d15f6ab853025d16c8a0a67e44f4b2d15144797479f417c258287230ad4aaa1bec9f2257e26aca9bf26568eafdc4fec7a65a1ce890a3dc40a872054c0eeaadb8290710b85cdec671375fc77f1d088789db985c3faed67a84f8765816b01d99bbc3221f0542fc8eebc0400c86bb1cf64034088c43dbd931662af026a195a7b7bee29f32a028872e2617aa7d1382a1babae0145621000dc004ea83ea2f10d3e812ec7bf49f45971260788a", "0", "a225423afc89065041c04c88ebf8f54359d18e5dd8645e644c9979f35c7bf86894d2cb0570289cd9fe5b32acfeb393e72c59f5863dcc0967f105f87e2bc7b7ea0fdfcafb8f017b2361ae1e6975070bf5be017c747ad6c37c896d3ae5e83dbc04fed59354b1c489c6b64232cb3c55eb047835d366c90edd1374e696586150c1ff6a8506a94fc93d37aa3edc9aafc93d8eb74bc94deb92ccced64ebb9a8199ffaee589f2886bd1678690124bc8d239472a3da068598b7294f908faa410a83e67a4978797d3e09b39616bf324d685ae6d7582a82ae70d10761a80dc742e333b8e72a051776f0cdcd085c913ba7af9cef07f96b9dec02de42041a1cfa8b0e5e5ebde", .None}, + {.Sqrt, "a234e909871406e2b39e66fed15a9097f772e5144d16d3035ecc74163622326206e2457806a3f17720cb8b7e2b725bcd8b4c7a87432e77c3730fd42e418c9bc58965050a0be1f0173769342666aab67d612a0e9b5321336e6ba725022eaacc079f54bf988e3c048e165f0bc013a8f878c0aea336ffd9a6176ea0f7ff306448a2b9e952d9e2a4d1125c861b697cbd4abb912b709b37f684d5e1c64b9a8679140753574eaa415a79fa0b56ff4b79c87ff8e2591af7c25a103cdb1b99ec6900d89a95ed3947e8e6383d47eabb996c556d188af9ff9bb382c906fd770d21fc3783a5fad31ca34342c2bba00fed40f0ed379706a4a076298c11062280b0f89a4385f04fac6ef6fe9153f02b7d8b7d0df9225b1896cdeff99655f64696ba7a06f3b1ba7b23377a9bb9f5a0067ee5b087438c8ffa7e09e80af7edaa2873b72c6ba1fc04d46dac1cec3848d1382b86b7168929b45d296d3891a653a7720f0afdc6c2c55b1c74ac3b4b5ff1ebc5de62775f6745abe29d0cee1924db0a4f234e4be1296e03bdcfc940223eb979eba45748ec4d1f591dc671ca6d595f1dd3bb93a8ac95c7b7eec590de5594c68ea7d7a014b8786bab9a5c283329ac299e53668f17456cf9d505f7c0bf8650fe232a891324252596ec4ab740513c40065b4f3f623060f7f8fd02e777f67a5b464abb449bdd2bb6c32726b50d6c4ada9c5e98c751f0b1a612bd", "0", "cbc6d07a8f9524af8f9b24d985168cf7f12236618cd1f9ac449e19a90f43a01250732c19e7d3887d5464893c657fdf1b96ae278591d48cedeca292f9cff59e71a5832beb6575bfd62b97d12a213d1b10c5bf50377106643628891fcaab6bb327147f7e5b4099cff7026f3f1f615b2adea03aa6dd58215e554224a9b6517dd5b82edb4d1ea107004f77795e101a4c1ea9e60b98905fc3eb8eabfac7f3128d94063ec84fade0c25b8f4d3b3076603962c8dc8ca3beac8ee8988a20483b6acdb083b8f2b9d50f2b33ebeb1821436c4582f8249252d62cebac0e5cfaa876652482e2c0a1a425ef59a871133d9d1e3ddb27ce497af5930293e0c4dc542a927ebb2fa0", .None}, + {.Sqrt, "bd7994472ff15d19a0966649394287ba4ac411cde25769d802037a48155881534e4f58fdb7b0fe3e47b9f48e572e912b645ed3f13b88f9f9037e150d30c1e2fc87f953ad3dad6c9b056095abadc17bb42172962fbe942ada4132b60de98a55952c89fa66dc528fd8ba0fcd70c0d9653e00eac9c5b07ad0616669b028d1f0bcdfae7f7aefc82171062b7e2de976acaaf5a61f0fdef3717abfeb42429a85b7a66dd30098d36685999b09a047bf6b4bf3429b361d99be4738ec6d83673d034d90ba73accd46764c2eb50dc5d28a3dc49a6f50a33b196d86230ed42d06e0fa392221b8b0d7a75415437b60529668d7b6f1619e766bddd732cd793306dce7c27c02cc1c17b4d4642848bb5933d7be5cba8f98b3e7ec6b0bfbbe93248bce38c1986181552574dfb3d410296bf91b39e643e3ea8cd885dd38dee7d99dd615e92251069b98eb21f194edab2eb6e74da8b4b6d13589dcde8d532219e46ced7dac9d33693928c34daea5f5d479ca005f1659c7f32c9583e84d4ffa36f66a771d842602c8b622907c684d6a3573d898b2a2acae1770c4995016613923640ba6f436175791a57a865b4a7486adc33bbb10eff79e51e5233dd25d5eeeefda00ce49ad543e65436e8aa749696587fb0a594595a7abcef72bd8490341b44c41c19735884091fbf4138a992de7f4e51f38b4b2d5ca9f0093fac3fba36773d2c36c82251b3fc1ad58", "0", "dc3d64fa211ca27061b2429413971bf5ead613162b79d36008c384c3790c45f1a1865354de07be9cc290d2747debcd125e7cb265854f097669e3ac0208a994b0168b7824092e47508992caaed01bcee0e1a4b98a0a113d16a62f168747da98febe62d55164dd4cf9beb8241a0a1e56171de4a342c7ad118a400eefaa421ed55813e8f1c34df95ddf0cf713884489e7720d42815c0cb9371de0e7a49a1ad4aeb6957e81835acc8bb596618a6b7c527728398e7980ff475648d545003d9cf80bcf862687af4a541a28e5ff27f8c1132e3c17d7e6add9922adb9de9edb8d62cf2750abbbd6feb9e465a3a5112179416d48afea67cca9669ecab6c9c9a885dfa032c", .None}, + {.Sqrt, "de6623287f0b76a23a0ede249ce95f171373ea611df1cf37cce42203a4dc54c35625669b25ae8caf9940ab5e61b7cbacc65f299e20c721d9888b931522947044bab5af3728655f2aea713a790ad596e1b3b25f9b8055077288d2c02bbe317add33250ccad66da443de36730d810ea94813f267279370a98e8c4ec0a8f5096848f85500dd903d861dc23ff46294d564a74d12aab9ae87e40436728169c3703db2c8f4083d7a4c9d51f68810295596de42180ba9a8bb36e10664c1bbbeba8c404ec552649548c2ac521f49a91e66ec3171ee0b4287b12677f5a1a7f1c3146327d0503820bad1006410930702b24e195c9d04949aebe2c8ef096b55a3da9f03bec9718913262635d9f439125b76ee1cad6b8841ba7cff9aa0575b71a9b9268490068de010ba63d5c64fb44a80bf809b31cebf42fd7ff0bbc8961b4d72827c271b0502b22425031e560ddac2fc0ce6a310f0b6e943abba975ad4d75fd54acad89940845b389d4a67a4ffda02383b119f6d064a835fc2b19ef3c70117e77f05a3ba8887a2c09d3eec82661480c757c78994b64419b8359225b353205698b55e2497c99abda651f6cd891db3c729ef341f2036c17b8f08b2fec2677f1973cef31cfeecde1b0161124debdb8e351c2e7e37f2ae4a4eb54da1fd27d7dfa3cf3fef33f32107c6d4246da57164913bfd24e115e8220916a696392b156341330b681edfc89e", "0", "ee9bd7481e7acdaae3795e931e3b3149b5ca2581bf81809b67c27b4541a9a6e508d262951b1130899679d72fffc2d6773dece498300509b07e434d3a004b184a0e2eb09ae2b8dddf6b0c95a043484b8fdb3bf8e091953152b0a6febfd32a5856391994b4d15b5350d40ff1f51f3b678a56c52958a2f339d3c94b4d9d5331f4a86a34a63b5b5b26532c45eb80be0c22411bfd3f397f7c2ec6ee04d195baac712a3670b791a45a607284dcb7c88c1d2eb95182cfc8f8d09e21da18d867bdcfdd2f93085578ea6f3712cb991170b79ee2dd6826c70aee5803019ceea4c690764e329e9d5d8aa5996bf42037bb938ecf40c6e87a020ec104db407a4e574cb979a383", .None}, + {.Sqrt, "54e334bf0f5e731a9a67f4fab3f26f9c315183b786fa494fa6d6031a798bbddab2e669d070b236de7c2aab6c57a35baac10d173b77ef14ec32c39f5bd4af08d378b6e3532ad8236b7519270729d75b7fbea1e1f1bbf77135345219840340c15a397c8403075be31fd9f4740768734b15613adef55e5b387c0bc887188156315917d95b60fafed15a6c8b21feae1d92258ff249c6822f04e0fc93ef67afd8d3bd168974b03780c39cee3e232f8bb2bece124bd76a4cebf821b13ed816e90592c03e32e4969af91ae074b11b68fdd6371e7a57fc944199008f683798f0c9fb4d9830a4497229755e8d8553433fc611a14602d80500b78d5c64113ae34488723d1b8e263346737c95e3de0cbe1b9000d63db7c31240f50a096cabb11fe74e6366a49c0c2c2004f45a53f71a5411891d3aa1b111a96bb778837140f644fb53ad4e80ee2461774025a55644eb400acfb1f6a9b7e5ba8d6769130796676db39c8145443c9eb507e32d38f2d754d0546f68a3479960971e8bfcf2f9a541d5d204fe6ce16eb08b2d840715224e874e824824e7680c2875eb18d4755662dde2e64dd00751b84d46e624889aa2e1f408787eb97fe15efe9a3c627b86a3cb0510a35af61b150b74c9c5750591e898255334c2b2fb5cf4b11e2386572b6d6ce9da824449d4fa02d1617553e4b9890aa6f0d8a6926901c1b6661ee72a6758e01c7bf8917d7457", "0", "936a42bbd84e4d671a14ccb98d2519d567da249d8a55dad75205467fd9de2a1b97a9b42a36ab513bfaffdb5d4fd927f111ad8258e91ce1ee2d25ca06b586d7a70ebf19f40321a06204bcf1faaf228159e65276f2003fc072730670e9dc31340021c4fc3ed2faf69b6ad45a89aa7b68e0583b8d9d7aef6ea11603fdb53397f4a4cd4f87ced29a1193cce71fb1afa858c728e9d45e95456b1dc7bb0548c544007aed7d88179545283a29452c87442ed972b39b82ac7d97a705e07ff2a036e181cd66807e67801682d0f0ec025a47c506ecaa6729d049a65ba979cb0e79d6c61dcbfd34572409701a60baea4f8d7b8dd387b095828b06e548ebf0a749122b068d1b", .None}, + {.Sqrt, "3fb7668ad314515122607136c8f2621a12a613c872ac7e35814bddfdd0fa07e28d89ba2626a0ac8157b2360092c22ba2e139656452d9ee679952a31a2f8b65ca297e3fef9c449b740b7961c04495074402bc58207ca605b494be81c7592c4d05137e65cae8b2c741479b31107b36156970a3b9311e42e61c2a69bc8b37f031230854435bd8192a70910a0af20b99dee8026865fda002c61eda1e819b350d777b780ac54e010bb9aadccffa14e3cce0fa4e9efc507a692116656c77206fdfb4f8b5696efa18b5a59d3a47465caa5a6cfa04900cb2d229a70cd43eefd2c76138705c8aacf44cd372d56c4184e9b225a5ae007b505474ef650dfb94ddeac4bbd5605f3cdf3be5ef905245cc6e444e44b139129d3c38cbcc201cae1ad77f7f17e3954b1441a1e3fe24e048824dbeaf6678b6463830b37f475066a366ad6a11092fc6edea9ac3959c57b9c7640d509dc2de74420161e882db8de5ec2f386312865b4174e1485f6009d33f8907b7b6785cc2a31e6a86b0080d7099a91b70f4cbf3d573349a364742f1f0c0290c62213b91bc80838cb8a9a9fc2a99b82255a6ff629f36d0c77fdf5a90f0be8a3ce5442cf10509cc31c46079f9eff85ccb82c2c0c18ef14f2855a35b06c716e8b7ad35626e732cc1c0f001f146e598f824a0c38becb94c4ca4757d26bdcedaa56a091b24105ca7b554e83d78091a4dc4d01cde6d150744", "0", "7fb751e86f6ef50a81b0360268b7511658185b3a88d07206d659c89a0a69a39b26c3b8e98feb261a1817759bc6c9fd6c0616ce78ee60559ca392e8fbd1cabf63626d6978ab122ad25c872889bd22e72248c456c0601e98aa79f6dee02213a9627fbc2706adb1e5758bff4ca09c2b9461b071f38772f41201cc6db6b768b69a9ae92cdf9ccbfe85ec59c87b268148095cc33a22d951a10cb23533ea34cd93050495f714f62140880f0fbf9f885ef08e21e3cf1a46d30e545bbde1e5d39a649475d3f7ef64080e462b43d680153264b680ffb6157a652360d7f1c5fe06f200803391806a92a44e284d78745290f51610b6179cbe103d6ba3da66f1b126f431f4eb", .None}, + {.Sqrt, "966846a57fe6f46cfc86f557e293b031c396157f9916d685176b218b075728fee2300506002711b9982dab2fd6d49406b58f512b2491aabce252edd6c87e530e8f4c5366eae738c8b578906dbdd261484275b17956d68cf3b632302ff652de6a6410eeb26c8592931da16d7c3afbf0834beb0d9b86b31e4613b3c125d70e0ea698178f3b77b42380fc714f8081f64c2e4c214ff3d6cb1a042d2ebd5856634a42fc6ee48a5154a5afed9e4a8ab33af58850b4a0067a4e7a9ba6f95dbd5d875dce5c22ec945489ec63a2902339df9102c04751cf83d28d4b02dff37a84bb91967cd1f8b85e999a39a9ee31eeb561135eab3e27467d6d13bbcca91388925487e3f990735a0df0bd35405921975b6ee22e1a9d4a6aaaf2f7412b6ce101f41613391839252af0a6f741808046303e987cf394950a5602b7c2e160219b5f248375f0c1eb1c250a9ce105d6c0ec75216702415f44a5a486adb0b6926cb43b2cef8c8e2264c9c0ae66725951bf94632a993e1dd2440373aac3500ae5d6877bf880d364726bb203d8aa8db83eaed88e70bb72c72ba69730e742e52a595128c0bd2a0d5abcb3f44d5f1128f301009b7b3676565223159284801cea1db64530bcef7277b2c309250b5b4b63f92259e42c568d01472bfe64fc0627c6cfbb8e35e954df157be1cc19425a50ff76a8453263a51f1ba34978120f27fd4fb46aa046b09d6844c857", "0", "c4399dd4ca579cf6c5ec448a9d7b64feea16311595bf86c8d3b0503fefddbad2638ceb75cb0cbc0b5c4a21816942d2897c53a5cf1a31227023c37835dfc7b2984866676c5a0004a9fb5962b898e8f75a713e82ca102ad9824f02be6e6401c5a940f9171f8bc4fc5271aeae1bb3d73d4e5c41b15e0bf945ea5e99eecd972fe6a0e694dcec3c37000a0fef734d6ae5b8caf5539254794d52b3586b91edf438d3ddb7b7a8e2b2d55b206e8a2983038ef813646429a833bc84d6c5c9bd9ea8b0faf37561e249eb9048694d29a046909bcca7852d810aa0b3ff95a2e6e838dc3c7e22bb2fb19db4f5534594bed62d046e9cc2cc9c56d48299fc4cc6f743d8629fe384", .None}, + {.Sqrt, "2c4dce74ceb3ead1c405ea40494888fe5cbad56f4321eb645c548e7a8a5a702a715d1d09a57cfaee3140ec91ea2fe5e7d1fe4a34de875497b989f1e03aea7a6f8d318daaab419ff6fc3d14c44bd3990cb4714fe50c7612a042e120ef94dda9d1acfd3be98595d6042c092292ee6c6755135ebf9d70054e4c8feb2776295302d48cfc1dd0b7f5e482cc931000b5a363aa99cc55e01fab9ca57789f33d6205a26deed068037b4cc4bf21adb5669cf1017abee1ea889954100eb2094c69fc504a962be3142735176389b034de959f57a9dec2d8fcf6b67121efdc3b70f55c51bbfd005ec6023f5f29deab2e11ae3e113240624264fbfdafadb28e64212f85782c7f7b9462df27d3bbcc80033f7a3b1e25973bd80634f872f9ccbf90d69d30530e30cdcb569582ed4eb909928b98a78544808a8437a2fb5aa37b84922df9e2a675847979435076fa6fab7b620e36b377ea85c2bad1e94168923afe120086c4f51b567077ac49f54b455da22e0ca9eb310982fffebe888a81c44835f3fc4e3f308ced4ed6760263eb2fd6634de81cb10fa17253146e0d797d3451c0192dc63dddef7ff8b0c880f9de1e2a6534ee4b5d17d08569773078654d4ecff882407e9288054d5b24a6b6756f0bce394aa102f88af5f5e095e36eebc873fe61b4a05fa215a19d77a1df7b1a5e69409a9eb69b2b3f430d43bc67dc82724f45226a2e6cb59be3cb", "0", "6a7f778870ec5ee7755b816138626a929977ec0b9ae024ff80d3a3da830d095ce977ea76800a1407d6bd14903eaa443da14b90131016814449740d54abfe0389005048e4e0a807ffbb1f1fc1c2fb90b3df4cc7fad766a3d23288865f175a50d16923110e0a8852e081d7706a467a6728e348e69f2db6c9e8faca4e82ba7594ccb4fa1bdbad5583823269c8f0ef854aa04e99fa3775f1b77ecc7c7bb448c2c356fa2fb2d0506588b02a01b66b5098fceb90c89df30086f3e1012ced47079173af7af6d97a4beecd4f4221bb5d67f32aba15039c789b496eda94bd70e80c40e4219376f174185028585560b24718a2ba2e2c894bfc8dc8eaca131127b55684365e", .None}, + {.Sqrt, "cf18d0a38d22d917ffa20881d4c5afd77c815cab055f0c22eba2ca2701f622e3ecdd6e851c371c2ac48c92b7012ee97566adfaf5ad674e55ef2fa526c5bc66087e3e97f97e9d6d628de91af0dc14870de7c9d0eab1b66492225ee5bdeb2e8712b48e05ba77037741f484e2e0472e443259d3d7945241b23ed62fb2222a884f10079bd8cc729183aa9c7861ea782860c9979cb5b41b438d94415cc6c7adcb3f08c42d87311e74250ef2566af181dea2b4d1e93c3e56cc09d7d1c54d9dc54de771a817a4e75209c9f7cd5f54545e110aee3f7714edef13f9ed37f2cb38f326e105a9f97ac6bd2029dcb4761d8bfeb68db6143909cf364e64183140abf65a47df6392ca578aa2d6d448b43727a9639b0dfc95524c7b6c6229c806b94291018b3598d48b1db67bc09a2f0fc38de9e5fe81f9d9eb5a532f5024f3cf47d7592f07687e6368fdeba00ca5bb9102e6b029dd15d81c8bc3b1873f8257dd237ac52e93107065dd5360034a8bb33e5d3cb4be31b4ae3557343e12e9a70370daecb322594ca0fd5ea66b92613a3fbb67585d3efff9d60dfccea895a9d6f8373cb2f269bf9098d33999be8238a0472e7c3efebaf8e9fe9897418ee6b5cf5403d933e070402afd9dea0a31df87eb22366649c7c2d2e5a9c55ce9eb553cef24b2557ae2fa14b62a3e06e83433551ad16c6ef2a0a37897e4f125f781ec282ad947e7e561a8f382af", "0", "e640f967751bc17170ce6b43c9f5df762a7562c9ea74d473307ae0798f4e64e32c689861a27505f893ac29711ca3597a782e1eda5b4195b31cfe49001750a466625163f7fbae0d3cfe2e05cddb5f32f23223bc181b45a77cdd6ed9b3357d6e556e128214c0871deaa442d369c2ef879287971258d0a98e075d993374d19d19936d658ae13793cc77b373398c2900249b69a2787d04f416ef4ca0be177ced2172ac8761e7624eb45fe01f058fc3d8457476b5062730b6875a0ffcccc38f02eff0ce332760f536918b3165030932824ae1acbd89cb82ac5251257681805c0fe9f7d54ac116a49ed3e9d30be23de4e01696581516274313269e3f2cb750686ae622", .None}, + {.Sqrt, "83969e692fd4092cae7073f06040b1246da00202c45b128add6e4a01640598a6d3f20c579171f459d062147017d7d1c97136bfb9f1c7abd57466c58b0030e02bce4c4fae30227a197db7f05edbb905fc4241db155e5907d44355010c13b3de91192512f2362697a94d110e29186a6f7ab180aa08fe3737d3c22b066a3a8ac6679d585195f54189423510fc30535502f57013b7a433bafb7185517c29d5c9d88a0ab26b97829711425dc1c3d29f971d0d413d5ab2491d3960750467bb4616751698e253cd912fcf343a9fad3f5fcdad715120ce2df6aaa9ed7c9ea34c61e06aabee058b6fef7ccfa36c756ae357bf0b1f7db66867c66e67b95c351183032052279c00a6c976a275c9334d8f5cb0cc4c109f645d9fe7cecb2f441cf2cf4869a7ed587d40e755da50b3c7b4428baf4db6478cb265646fb8582a22ebefecf8f6325fe65d586beb9b25b04f7d33f1c9cd4be940a15f7e458c5a1c8bbc30b9fcc2d8f4b17e67e370783f8a7c62036c18651313bba7428cfafe4cba5c89e9fcdaba341590deb8ecf1b317d6a954e93dc4cf44b895b4e1f78804e4177057732ed9c20a3b39e64d151b7a4df2287b8313400149dfbde50b502b1ec63425520f150a2f53029e2b3b5b847ec66f55951f19a38fb67f4d01b7d7749381c4e48406ca6aad50a281c335d78999a7d57617610fa1238a1a8e9b94c0879e165800ea39faac7ba722", "0", "b78a0597e3fc78463a298d1ae5fc95df5f1396cccce5924adcf08a9bdd8e540c3beccfdc54e0a3b3eeff343836350a147aaac059d72cd92573a482edf24638d227f67b99a7b1c86ddf704f97d58485245138639d60212ab82eee64d14c9af8203aea7e8802eedc47bec864d026ef43ac473939a1946dfe4e85fa17ac6bcaabecc72d2aa6a3699b01e53f7a19033218cc57a6cbd50913898014053b772a6501fec0ac851f9b3863aa00ff0f614ab66c5a381eee826c78796eb8de973a0078cb0f3ae85177a2dc419ab6ff41e5664078ec82fd834fa38f5cea02e31749a7d1e94d3e390b6932a592380816fd0a77335ae96abd665cf7fb656aed024752f560c581", .None}, + {.Sqrt, "f62894209f9a1cfcc69a0a619f7709343cfbfb53aa970d7d3a1c46675c121a43e12de0b7360889a98d40de210411873186a51e7d60a1dd4497d4ee83b800419141b07e45ed58b57f32f0ec30f4dd0ba6232bd3f0791afb2a2c44fa0defa15382c75dad8ae5fc4d6b6123b6d31acc0e68255558eb19785c069464e509de630a94f85c8d8387181f3775758c9535eee269628b5f7c09bef6a30084ebca14faee1bec43367b92a331e1051c8d7b1bbff07f15d4c1743e543ccbcd6c4d216d9109e4f7d034e4e591425fe0501dc0332b198dfd4674729efe34338f6e1067be45b8989d238dfe7ecf7138511e76220cfc74ff51a49d165cf935e3d17b2c24c2a6d017941f5b9a404307586b2d8de8553a9616324ef2220a9b77a231c9a983bfa082ab7742080ce7976ee13c0e63b70e78a99d2dea45fe5dc40106400f15730e8b4de6ab379f3d16964c2e4c2b2d373d843ffdebdc48b1f890d0c2aa9668a61953c03ff5bcc18cd4934f058ab2cd0658189337a8790145786b5c9ca2ef8a84a2fc858e4b9f7931cf4cf404ff885d5f8bd2d1636c84475586af19efe2ca370d4aee8079f7c308e925f89fe0089bca35b76ef10e7d25df7e6f279954a11e93d6944c2626c4c5e9911df70db468f720cd439d796542b93bb1182bdf5f9ebe28a3f5fdbc4de9108f28f04843f98da3d60751b1ac44777113ff3821bcb67189b2de6b2e9735", "0", "fb07f1a90f6ad97b961cb60422a484b9a0273cf5c8f4520b471f439a47ff53eff3b490148b6f8a769000eac09ffd213310438e28b855632c2c2a4ce59107c667539742135459353c20c7365bd06c4760cb525df82001e0a98fb0f80139d46c8373629267a1e69abb3dd4dc1c17e68738d64c7dc1cbe36addec6b84193fb10d9f00dd6c051cb441a091755dcd7a4261f3d6a6c05f72a3d536c9aeb2a82affea8880fa7c1688bfb33c227d45c3945902c8a9a81f5d9eb8e1b35db075d1439d445f5bf6dd16c43e3e9b9557d9d77822269151c01323953f2de93fec2ba75c386f3f363c5401f6ca39265c8f4d2a430b8f3fddc8e7d691b54c448a488f7fc623912b", .None}, + {.Sqrt, "7f6a76cb7100840248eea0b25f778a23e6a2c54049afaf548c231eb76f0c8a1c4af88fe6652daa3274ebc5330b98da059da21d1081006b85065193186cf97eb9113f1fa3f06aeb9741f91e8aef7bfc8f51430660a16490b5147b38514731502757eaedfd3849ab1194d10527f6b47525869792f6f59d8bf578e742f727343b86db17493300790d0bc334efc611f2f459a92ed80f98e6dd9989441a08a96dc639ada15f3d5ef84006e0b9b4b7b977ad77ccebe66c1837d0a071cb5d7cc535a62fa68a9406c063a34b519717a9c44e0e9d5b4150dc0a5d1a7602383e8bf62c87131169f73f36e7370f59d89b021be8621db59fbd2d5efda21586925421a7feb7f029c54721e9561d2c12a42058679ad36daec6fd6769660e535ba15dcc461efb60eb53d86832c9ef19c0bc4035d8c8847e6bc2ce34818cc01bbb3cdb179c73447c64d8a77c00494d8c0a9eee3b0f8fef81c23589514e08cae5a9b8f205080a214db4637c39d87280891a139d0497b6675e4ca889a57809288b78b0260b76728e94a906a98c033001d07653a2e57fa23e1df4b6b8bd0a0302540107c14886f5b0e3cac59795dae53f97ce6c8f8ec4909f59ad2a79ddfb4dffdcd2371928ebcaa3133eeb450308e47b06ae999d57f1e35164ae129505eef8d7525d16d71d3b9cc45333d93504c521168f5b22663886cc16b09b43944e2176a6dfc003494970affb1b", "0", "b49b1759b6367d0bfed4eb9d8e1704ebebbb6257f1c1b3f8b915a37413c2881b2dcaccd9a50fd4873b11714b60db0f1aa95ce4661289423cac40f678a4653f6d6cd2f099b611e0eab38210a33b1be9ede54576adc6e574c4209442bc9ed5b880f85d0b184fefeb55e2388e65789a09475c1b7ba831eac1577fad248da6afbb472b22af31969cf3c2446e4af3d1245b03dab35ddde7d62a9820ed337f4b2c8fbb016ea34de75a612bfe391b6260d91547d349d04ae3b690a4519f441c956d954ee13ea5a92fe766187da17fa6126548fb024ed0e0337d3bb00387c2b30941d32f5a5308a1bd71cceb99cc71e366a09a731d070dd3b1aff6eac9655c1c13b0d1a2", .None}, + {.Sqrt, "34dc5748d1b89c3b872485f17fc949fb4fdcac79a235ae8b233a0ef6dfb1fd18ed0d51ceb2cf018165b0a08779113178c6f4713416540e5f4cf894b460d81620e06e3c11ceea74a1679e462c83291e73ac14f46f1e83094886b6a7b7daf947c825a172f36ae6ba8565181497ccf29a9b85b7ef1a7effee14b5d89909673ff3ab47b81b2cd847eb74f5b961cbc75464abe9e38d25eca12ca8040b923216ef6b1766cabdd96d910b5e2d7b9821f814f1d038619d8c4d5dc70e21b49790f7a0cd4852de64289c38c44b57af93bd478c08b0711295dda0241201b69536899e0212805620a8d963bb52369d3ca17be31fab1896ede44f7aee163371f26450938c6d48880d51d2c6a7cf971a0934e0783e6741293fa10aa8dd4348befa5e105efc7c85bb2e7a585ea1a1664f63341348b034a0bee50f99f80e7974f33fffad6eda3f73cb41069f2a628b90e7e0b19158ac2e750457b3518ad65e5fd3c57b0391959b7f9ee02571054ffd2615af5772f978514e0d1dfa7fdf5d56c952103e7f9992fd362d20d850e39521db2561d2835a2caa1146f84083359684ebaa741547101e4be11cfcecf25fc84374bbf5587aad51e6542b5a28174d842ae2dd836d8e08038553a040a18c547b7450bc1448d945f81bf7c1315db01ca1b4ef43fb8d450f6c723bad7940b68675bb42057dd4dbb9fc7b082d9eb498e3a99413d6f41873fca8932c", "0", "74541e80de5cf0d48146512c0f78f80cf28dc821948cc11f97d875096e4b8dcba574cfd44ac6d9efdcdd5b9fde09f336d2f4367107691ce646ad5a5d1c363c8fdb872cba9544e8123cf4f3fde113eafafdadd9b3e8b3014c5eb96e42901e39c53ce28519cf6a33c41232068831fb8c47a263983ecb9498c459dc516ba53d4cee8c7249cb2852591ae1d0763dadf526136dffbc466053cbef258a095d89cdd5f6cc70d5b8b629a8134c87598a5bbcbf2470e928ddfb22b8cfd9be431a6dcb69df8c3eb2d3fad654795fb34b286721ea427788f706b6395be52e99bd8a64666402b19c0cf7dcfa644dbfce64989badae222f42b42bd690d2bf8c1324c600a7a15e", .None}, + {.Sqrt, "1f942b75ca073e542cbd899bd8aa82adc6744968668ccbc3448fa1a562bcabfd2ad0a6e22a6a6732c7ecb02465ea03a75b239a5974412b47e248ad9deada98db6898af8510d769ecf40cab619ab65e30b154e127ddec28925d19d0ac2ca26d33c688da702e390c99bd737ead83a47bb259ff2463938b844942dd84111dfd37041454c14f6fc561602063a2d072cf154d45853415d798b862eed3f1bbae0397904d0a92f5066c6db79d2d84d5008e28282fb5769e85f36c71e9309bdfb0c997d50d47538b18e09852705bd8f6a37484f6fb945abffccb3d45265c319ebd582b09f5f7f0f97ee890773d70c9b4a6fdd97f52de56a633219fc046247468de5c67853bff2f3969a869117bfb0386d641ccfef001ca562cfe3d665c5812d8b985b03588c6e14b03d255eeb23268af50e5561b2379ed66c747ee64966b8822045ae7a70beb367dbd6e09aa6ff7b3cbf008b6e612c728b1f80b4164683bc42991547fbf8541539235c1b4062add4c754ede6fdf84a0579b454368021e72a1af6c3b2b94de13afeaacf4b4c62239868e7b7579f71257db82b93f0a98fb8824d34925943c9136ac88b2d7c3711e02c25ffd6276fa69573010a34b9a8f6b06a08315ca014efbcaf3506e7b394876270f99f188195dc1663eb2b2b7ed5e0a1d593410e460d2be3ad7ccea0464806941b1cfea0d0a6121a32cf3433a39ef10ba1042f9f54a9", "0", "167a5e6469693ec3a66324b3e4a760b1b544ad18e11eddc9230a983cca61a1865645fe03e9d16d7204f92206146670018ff92c2f72a0f0b6ad07bcebd492134f560955091956c905a68868fb5f03d3e8f87ce407cff674349c880aa4a0c5750301f4ba28314cc0d3aae379b55b4d1b23bca00a919906500c8ae00fbb80f0afc2dedd1aa57a0b71f1ff0992f36be76a600deaa9d520d18ea977bd6cf3152b3e305b496403a56338beb69d3321ee8bcb16ff6453062b914a9c73f8c59868f87299c2cff3cebdaf4916194759e7bc21c8cdeed4272141472bb2aac5ad67208840331147704d6c9f317abe44b666d16dc24d7e71553801d1c184bfb451897d7bd7c0", .None}, + {.Sqrt, "748e8fca7265702e710f809fdd1b609263f157138ce141b24318e1a9434e05cc937ddf36866f40cbe128a837a5312e87874c1e84c626699a3b2053012f0fc0992a0b463b21d03de93cbeb60adaba44b02ac07c8711b2f530fb7ce76ed9fdb72827c1860d4a4417a3e9d8b8bdafc238ebd5f6790303765ea03cdc83a39de151f6a16084038f25afabe6d9cb644d20c2ee651d8f864b8ddd0bd1883020389e7677e2428c01aa20d18e773e3fe90174c94d5ad6fe324fba8d7d0a00650f1d8d9ffa0f68d940dd83873efb5c8aeea9684f8fec7677b84f236c917426f7f6786e6e97ae116e6a3671ab38402560e7e73ae4802d17b6ea05d644598994f9d32aa42d47f41acc5a42dc15455a018789fa7fd700cbcc9790ba6bd50d313ba93b07adc57834a969c3ced7e5b6f30ff635794fc94b11d3d394c55202ef547dbfa8844fda3c72265e51eb72c651f1ca0320d3a7fc118e33ca81ca0d63ecf8b9db6c3676b6dd749beadcea57e85f0d7c130c2d2b1b8c12e03c11b156d947d58c0ab3a2324751505b15182e482e6b044def220e9f123f3e401644076b52e4ae4cf54cbda34f34b7a28ce57f80f0a69a9cdb32fb7a6ee9e58c29ae7077888168e9a2e678c0fe6191d02f8230b4883d1821d06f67d3cc1df1f67cf99565eb4ba32eb76cdefc8904bb30390724af4f3e913f99ff8f73f1193e59c5fbca73ec3b99b9ace5709ae8e3", "0", "acbd0914dd38cb36628ce08a1ae327184e814a252ca3271ecb3a7e294d7379ae7381bfb9200489262c8cc90e2aba47156b743ea8a8e546ea312e9fbdda6331c6d67a87d7cad0622f4d3372025dfbed4ab7c818435ccec40a9b2a9fa1d0199862628287bc027e9bfcfde6031427fb3d1c416286b011a6c6de8b6f22e998001219cda2f8d81a5927b0c88ecae4631fa6fccc65c69892e9c5635d136480a8144df6efcf15f3930b13564c4f2fe2c39f2e7dd4b98a686c725da5944078a07870ba5cb21aa61d60a054845889f81e540b5c4f5147a3af748d384217dd7e899b0b355373a376a3c0ad60dafde319ceab209636a0c72267baab33636f4f882b818e8f90", .None}, + {.Sqrt, "b67a1edbd011d9b1ed32704a62bb19c3910c2fbd72459e1434b282fb151a1a1e807089ad19e04db851f08a05b691c3fb4e5a83bec3d39fbdafb19192a9a756ec24f98263477370a325207439dc02bbab25d77c3dec985490cd16c1055fab7da1dab28ef69c0c337700ba6af4bdfb5e482d75af09f721947072389f8b7f358cb89a8e84a8b699ce81373b6097cc5044670c02da2a02584e8bc4637b35c815d1fb7ede987a29e82f227b945ee64caa0bc040d80f09083d38af96a0d05eb212c3a1e798fc4b089816a42d83296d178631a3c61fc76f38740dbdcedf23ee7eeb2234c1310622a555cd17eda91be6983cab7e554e1d059de8f342e4c52688d5658b6b5d2a42e5d5b743c664b5cc6bd449f39668016a8165ffe3b3cf159146a920a7475b1da43f93b1c1729ecc6303b8af365b46fdd3fda6b58255b469f0ef3e6ed854a0339a6d1b3d1cdf1d4afb088e4dee1d6597880b84615dd494d5c0b20121cb043304fadd04d4d5ca4da809c4a59c8730da7c8e1e69d1299f4a7782def961254cecee80d09701e5fd5a731089c456cf5174cf2f128c70ecb034d5acd90cfe651f92c846fa2ac94ef4772a8edb6faf37c2965b409b74533b0a6fc6488dfc8b9890a2dbf2591462458525d85990009cdc6cf58556fbafcc2404e1c7c225d84b05aa63f089e6a17528b22ed38a9a1ef67a2f0c47b703c3f2f7edf3d489ce3eb7d524", "0", "d8226e5b71e672ec8dae8dae81a825fe5117456060f65caf110f2de37f686d0d9f500b3e3f7682fb4b173509152fc8384b2b6e34a26aba7cfdab35069b6bbe1040d6cb24d26e146c4e7f8e0685db17defb88e700becd25bbcb2ec06cc74e861f7529de318b8567be358d868618cbd86e7bb698af65c0bb372fb231b8918413e960804ae9ca8cfb662dcbaebb66ee67277dd45047c21dbb6d36dcd6f6cb184b103ea56ef2429cb640d5a74375eb9fb1578dc144fefa7cfb94caee249038608b6f10dbee06707c633162d66cadbb3f8585f220b49279e49c9a7a1c9d30509e5644e1be2f88553d76dc3fd47c34f00b30ff3abbce5768831f520521e747bb264436", .None}, + {.Sqrt, "4f19cf68827d9e783ad7c3fcc575acce8f252fa7a4a989f79cee7104060e2a45c10b1d82f3b209dbcd36bbb728638be81ccd5f362126b834197de0116861fe00e2c3b6167f790dddb063c4da753040c26572b9684b5c21f95eca9466966be9d65d85453cd7f323051dbe27dab31c49885afa4ea67edf64b01b86538fa7c4140c5a04704c5d927fd9c0d71a84940892827b92f9846b3f4fdae980760341b92749dd1d16c72b3fa10bfd3daf839c425ff774a6b6e8e10f808e3da6a50ad2e2b26c69a80884c5c2387ae779132f420f65a6c3b609ab6f84560d1b765089611ec00c7827b9a9964542279743e4cb93ffe05363ad4c7cad165b9d2bf5aad71e9641b7a304bc179e592e390e15a0fe6aea4bcf49562669de582144507fec46c24137d2ba5f265bb71bd40c60279b1962f5e6fe54a77bdc23a89dba8035275d16b38a8708c7c6b1d61e2ed77728d57397ef57ad681dfce5554e1b96d79cca57ccf9e58b9619d04e7b493287c5ef5ea72cef57dcddebd73217d89796874a23068e5c4e5a81dfcac3a7ac97e48c8c5aa2b7871b8bccac000ea87d87aeaa69451aa509058b4a86494cd14cb5bd6a7acd1ecf716a34948b26892af624ff269c4c6da916f625f235e6e27e3d28ef0bb42cbb1cd067eb3770dc88800c8ca53f0b0dfe6f559a131cb7e64686daa8170884e63cea53af595ac33a424b49733190c1e80bb27189fd", "0", "8e4d4495cbb8eb952d95b176651df19579f3c6e69a8aa2286425440d03b2a7466c4e0bc4142ebbb84469dbf3821a57569995564a7987450f133c1f529b127931722a6c1b5e3bc6d0c5f12911b64db5267358bc014e591e5238c9f1b1c015eb1d092f053859ae4fd931c864819f98f660e6f81f9931aba6c9e3f36e93257ba8725b6fa20bdec60e5500af6bc60fcab9010295b69a7d643f69f6dd14cf99ca25f5d2c7d1f02079dcd02e9a7d25325f17046cc3d9a38fe8c4fe02d97db9ffcf87d208591e841c6c4cb008a87df1342fce543d8bae6192c1ab6c8c7b85aba692efa1063e30be1ec8fc8137d678cd3cc43e8410feb6d1a86482d620f54acf3859eb94", .None}, + {.Sqrt, "5bab265cb07053c6d98808f5d6c68b86467f8a5e1a7bfabe06d55995542964411495bfb49bc23a41cb4336fa89929f83f7340ea6522e1bf20b1306b03ea5d6a9a7d46d39f63a65594f23f19fac68ee8a9754dc4b1d1144606762fa3efa9904d8983f9cc1fdf13c2f3bd48e35b98db221e9a683a9f1ceafe95cdeb02ec2eb8f64cd84cbbf53c3b977e0a947a0b2ab0bbe7228bf8a4e718939fdfe9fe80f998c3cd8dc845d197243ec44791cac37fd3952ac3b4c42249715e089cb5fe0cd133bca439211d2c970beb5c693405629b76030a587b5edeae3e13ffbab1022ad9fa7b23d3d8e5ce9d749194a1bc7b5cc3fd04ee00b5331777a2410f2192009a3acc9a4ae1607e11c5f31dfebb8e5ce7078496be0d1d0ef41ef71e493c0eb3da8f73d48fa67d14bf88d8853aaa09aa29953eea9f7ab660d272dd5367262d7f4e14717b8e6b68a24d730b578fbb5cdc2c62759d8927351c4e0f86a6bb377eb371309de4d7a1942569589e86b3b082f040662f03cde6bad6ae5d4e0aa5e20452ced8b4554811708581f4c001243ce08b73f45fd9d53729df6deb53da788b8e9d408045641f619215ca901ffc73fa0bfd5873417c8589400bcc42d2ba451d2d4f2231763c0327104315f2f6ac915ab3d0ef444bf3f49642adb86ba2733780c903817c2b84949d0560cfb9cb993c3d84d1d134ad94bd9eff5c72e0e88d0a992c1153c71b20c", "0", "99309e39b3dfdf318a595445009bdfcadcccbda45d3db50fec3c8fff5f07b52681323d07b06fdda307175a3e114d560a12b9603f95a0e6a69e2e47a985ad27455138da7cc0848971675c9adc67e0ff0ac116c3681c73814a6b0da5b73b925ec25b372110d219b6910100969255369b94f5ffa95692a43ff73271304b6d85a05d693a34a2b54484c901a0c2461eba92fda16c5e4d1c8d14380a89df54757a587b7762f24a8fedccdb4395134b026a96a0740ddcc0ed947cd1ee1018864b68fa84cfc673eb236097df932c4882132242979f0f0366b643f1f61d671e8a30661dd349f87ce470bfac532bd8962a7b28a63a7612ec47fe30831fab9460f1295ad74f", .None}, + {.Sqrt, "9034c69ea8fa31a5687ed4407a64957862f63a2267007f7bbbf485852b60fcee9d9d34433be4c6e31957682bfef07a8fd4051a54c26247e577c53f4bffbfcc00b421a6174301e863d2d9205f45b09f1bbd889b54bbe7768655e0086986b2765ba2d59e3e461f3e541d3d323424dd2d46891eea6eaabbc658d6db423fd46ecef220b9ae49a3b2408e062fa45f9896b60cf27eb04948aac327f6a04515db82fe4f858b0f1abbdc87947b61e5b9bf56804eceb90087b5c9b04f0525085dddf70a155d54980936460ded7ba4e936970db58feacc62f90be4b8323a4fdcaab7b220e1a3b5a496ede9a7c5eb7d21e7fa030a4d7cb963f01a9768f3676bdfd91b2cfeec597c27d610c6f008592175f26462fe65ed6360ff85e3b61086a29c8733b31fac89b56880f3d34f5ffda0b40be79c853ab5c65859983fa90f7373a18a61a402047c245c954ec685dc267d0e13efbef451035afdf89f50e1201ebcea71f0eb51c220946922f7200874bbce65c13801152251397a96d28df8fa54d35c6d628b652ef81d9383e1546a001f50f14183c88fb52b71c0a35d4ddea4bc177232ffb55765f1a8ab0588e90fa11b9f24f0f7870c74a9abd8f83449f99ae4d2033f1ad1eba683846ad3e68f2b6c7816aca08120a9592606a8511d7abebcfb3904ce4f34bae2e838432bc902adf206b86aa96e8d371651ad8c3c446980edfbf7b3076de192c5", "0", "c0232bdbc23fad8dc20f1657b25c90160dd448e604e3cd6a0e787580bb079398d8b6c38b72f12a8e7458be531e7e8161bb38fb765c93a281bee858fe475483da0d78c873d2248dbecd699670a71bc062721a24836aa7a7cbd31e56c89ec319a86f6fa39209d45184beb7a6ca94bf6645813c9236b5c7d5b53180f1769980dbbdc28f347b0d9ae6c0040c1d33c214d2ec940f4a448132ef1691bf0026d31afa729c9808067c4ab5053854621a44995b51dafd04a3c9e2844546af27133cc3991648b29a3cbd243e31fa83a743821569743699042fc5af1e570119848a5832293223b988de371ebecc615712f7df14dd6be583a5f398f75d98f7a5640e3f6d3056", .None}, + {.Sqrt, "3440ceab38f1bd92e32ee22a788bfdf69efa96691f908c4d7a1824784840152cafeaa139023db6e606746a8ef6d8ea6044411bafe878027b5feaf86fd7f436116f30db7e85dd4099efae64223612598b45a30ae8cd7456a66489da9c1b9461c56760f75314b1548018aa4e1a82579551bd9741bfb4e7bcbe705ca44963eda7cac3a92657aeb1a62e55517fb25426808010224b6749c2cf4bbeb435bf1bb8f9c9cd7803a64e6311b7b4484eaeef6135652dd6f8497efd10528802d134c9b61e29685153c457803ac36ef2be3deafb3dfb793084d0a37075f2e3e1c212c2815344495268059434db175bfb7c95c47a815b7513a1c5347314e424c9d944c64244b0da6336214f8c85b8cd16e2a1b6bdd61d0fb347d21f5230c82defdebd6f79ba92887365b444e41b5546c357ac65b86687412d3971e0b7514e433d5b5e11e539e1254ddcac1210027d315bb9d2b4cbc68f650f524091133a6698b4768671663031dee9a1d861859a416685eeb431b034b3e607375bc816e4b021eb56c46f1d5a5f39ebde4984d7dd722d37a8786910cbcf5b4f2696f846bdfb0540ca8e99ec64be6ee0cfc05341ed6e9df09b910600a80c868b21ef0b771a2e7b73ac8a7391a33be2e0ba097b2f0e9a8ba671b2c7d2e47ecbd61b2df733e1152ef2463b3e819f1080591a20d416b3e1f2d3d3ce8b79cc4460a1992a113697b1e720fb81a87f00e4", "0", "73a87c6a81e0bff43630e80a166000bcbae2f34fc2bb3ddb278e39e11623e28f973fb16f8a0c744aec810409d04444fcdcd9a73fc6d41bc61498b4d36e9e94fe44c828c50bc444fea2bb29da722665ddfe01aefa663628017cd8311a4db4ba46318a66dedeb09a6ebb2d4ae305dc0429080e9308ffbd83ec59a23c3306836c8fe7a533b6f32f27afb3884c03796ec1b45456577da4f592668fd29b56df4c404a780ff16ae06e9e2ee5193cfd7dcb83ef164fd50cfbb085b27f9dbb83a94233e2f22b5b5d25c6b68dc1f0e68741e7b44c885ecbd6adfac5aed734fee151692a803f690c0b7d61854a7e9c13b6cdc873f9c7233e020c6ca891a971ad9739631444", .None}, + {.Sqrt, "844d0c64f7c4bf53547f5ad55668eb6f8a40ef2c45b767e1b752810236ad6ad6f7844d6e6665061464d13c4c5ac8a34a44e6a49cabf262b47213ff18caf7488e1c0e0d809d371f3a4e9a65c17f7082848d1b95a5303ae9502bbecac4290735ce80b2be1203190aa2c07a692fd444b38dd626e382c72f8c94e22db1ccbd85df21921a408aca5c688790f0e7ff8d06e0e888b7f900ff2f01203db5bbc5a9d922c7a3078475eb0bf76b62ce65ef96a0760ba74b4f811daca303e9aa77d44a4ec7450989257e1e9b6167bae916c1ea3d0ac086f376de4f01035851f370a2ff505696e184e570ed3c0bfeab3de22c94b5ccaa91facc73c05c0122444ca434a3290bdd4081d8b9b4bac7be533e52fa998438816014cc8338bc969d106f96bb54eb7ca7ac5ac626d7dcff284ad42259fb2b84a4eafbb6287ce2ad022ba7329f5c16958098716d530a024b69e30ecfeccdf1fde5126b900586f8fc9d493a246d123e5153686b37861b8e8fdf77b8a354b29ba1070d27446c156e355d18b7552d031fcf7ef113ffaff88f33adef17d824d95bc166270fd39163800b88cf57688d0b41f345037fc7769653f345e8b0e00bbcf7453534d76106b707d56b4eb36f8fd749e2d94bf8d5961a178eb48ea5e81d0639b0cddd1a1a895cf6a0ff928fd7c3098cdee3a2c73b9f8545992a2573dc1c76cb9abd7c9a16a00ffaeb1b2c39c4d5dd68960d", "0", "b80913875dbf273a912072172e7412c9009437845fef93ee976d759931e6f4ac3bfd4f7db40afc7e9b676a19c2d6f6d518bca30a0ed5d1a8196a2d3b49bb28cbb37661dc5012ed1e75150e1b304273ce51f20b860c2eeb18ce60e09dcf8f7ad6818178b2e06ec3e15467423571abf5d91f5d4900ed8b25d1ec79f2438891124fbef046eebaefa195daa75c02394d19752efc3b496eb8793850fa712ff35354f8728247d4de138b91586e629d7baec24eec38ff0fe26e7ca775b93589a9dc53b769cfb462f7d32bfb4f534ece0b08c3f9afbe2580291d567df53eee1f87917c6458f82ccfdc5250af07c2447531fd3e96d08fe53b153e1ad95ae30a77f1d23bd7", .None}, + {.Sqrt, "95bc1b3df0b5e6fc2f33afb09d4b3f1bdbc31a2f876489e5a2c155db3aab226048e99ba399dc836be979f2da73ad6f9026a2199e896ed8056bb7ffee03c2ce4cb56df7fb3cfe4f7989cad77f619ee91619c9abce5c0abdedbc56847f5b2dfa1390b51e3599b315393d7c1aaf38c86e1d69ab731642e6fd51c1a771e0343031c204b6a2911480ed4505430b0941553d209cf44e444282cb1b6f1836c62615bcfc535312f323e97985bb05135c1a948ebf3380c830533c0b2fc185b799d9cd72a56eb623134f23ce154ad305113da602b91b0caa43a4860dba3eb10e46b8f03fce3e42c9578392f6ee8787c29a04dd15bce4a84f9de93e3ebe1093db3dbc359e771b86d8c6e0907ebde74a920f1b7cfb54de1eacdc140842cd9e50aaad9dc67cf30c1ab558796200e135507d220ace6b99871dc84f469370c8cc365a819f98ea10e52fb9d7864092c950eed83a18947e3d6ac4cd3f4e299e2014a7f0326613b9d6410ca40c1d255bb7e9c76911b220d446ba96ce6bdd01ea049541730382f52d199700ac271deb6fb11f68adf27b3db6fbf445a132ba20322e4bdd0396c9aae9c605015f50ed56f1a3af17eea5742190c87f8b5c49c8f7a1c7eeac9e1b4e7660f21deb08afac91e39e99de853374bdc95ee6e3f4e1642bf589016de9d28aa2c73f8f3e8196b94a2c942dd614a3c878057a5b116d92722412e2da9a814853f8dd23", "0", "c3c92eb2446f8407935aef62053681646f25a12a5e1114df9ea325f4996c02ddc2bbf5c2b24eeaf27cc707c64fe2bbc4335ef6542b7bd4ec9512a83a718772a15f85d62992882674a7538b856279061a0f726375e8016ebb99b2e9e7f6797bf50c2c996c6f50043d7738a7fb6b37f49f29e6401a25de813949708e4f1cff687fbd11ba5ce30d79306f65b85338d51fd1793da4850cbe0428d70f4f2d5e4ee9645bc8b3afb5ca4375dc90f79bf9e69ea024122791d8a871a77574e7409f9751c4b201308fee53d2fa769c708e780f9064bbef1552486bdccdd6227596b973d98cc9eada5e12948f42937e1826ea6132cd39c5dc8fa3f2ee239e990a1b7e50d32d", .None}, + {.Sqrt, "87e766cccdf49651d1ce9e0ff7570bfbb432880e14474a50ea38125889f26ae13c68acb005119a0817176a1238b210853bd37d2c4938d7c9ee8e466bc97132c40b10f0a9dade03bd2716720e3ab52383dca18a29f856731f0586f3d3e574de081bd061ff9da359c4b8c182fbdd37823c1548436db5977d8723aa94cd0eda0967583b657e009cf8b513c011a77f81e37a8bb52ef80af446e54d53af06101aa61b9f2183bbaddd9c137bc75474a7b1e1d162137319af838be3a3248ac7ebfa989a64340f43ba0c426c119296e19dab640ac6c40d5d3fb28e6081d4ee0c4ef0c0e55ca98beab8e0b3f3e3c03ccce602dffd14222ca6ac6309db8f6e4f9d44c9efb58c96ff88f2ea5ea436040a90b45c510c5a1700ccdde143cf62779f8c391609fe9347575a397584185e68a5dd022986c449b0af6c00cb4f4342822034774cac5fdd6bb5bcb74ac8dd59f24d0e4549fbb1133d53c1964d74ac5b35a5cbeabc887ba75f72dabb2466fcda750f8e0fd24c208606aacfd77945c96cd6ba1a3390261f4b5017b13ac7fe061f3f7481c373f13798cfeb1ed6448ee4b8d715a7fd7e6e85501cc85dab72b9e2aafb0307f5cca7db99f44a67012f6970189ab7d16bc855de17f4a8d4189a2fda6f6313f0342e30d7fac68617ced193d1e0bde69a2c132871657694ae0d5ab7fe64122c03a0270c79b7376e8abd3f42c2b89483446ac5b9e8", "0", "ba8647d24339bddb4d7045c3efb5c94fbae276393d3c0a6cf51fb54902fc7084793784702329b599945a59e84cd603650fdc5183f4ee576586663e1eda9cf69a3e343a47186474693f27874f737b22915e8a3531923ba5d9b10a517aaa7b1cf3fd50f1872073b94fb0df5dfd00504bc414fc7b4149db8b7209f3abe3c4a1c5deb6919f59d8fe51c2d3329cc7200f338b1d52e618d4f3742b8b7f2925cb601b44bb6bccb7a5d9fbbd561fe6727221f690b535726d0b451d9b40fa47989548d1b025de1112b0393605d29b5f96192a59d9aa493a28eb3adb8465d1df2d7200a6e1416f231306c050fa75f7c765e2b2cf28e39dc83531059fc8de12f83a33eae606", .None}, + {.Sqrt, "85ea8d4596f6ea443fe069eebe403a11da52546c18473474aed26e929862dc6ebd2cdc0b31cf51eb56029c293af153c358886d7b0c3b678bef4656aa9d53c398fa6d4cd7184434c89cfe69146f72fcbd4078e2e4041efdd2272c66a207602a976fca11ea7dfbfc947854573f75c015f9d35558a39d07b72d42fb29e2ac3ba74d17c7e7684b8e973f11f46d9d5599290618be82ce6f051e3038be3c3850ac76639a601eadc847f13cacaf1195a2d5bb1e6e77801bef5b283104988c4b3947f5d19b68cb63757c1f313c48c69115eb8f06424e8a5a8a79c888907717bf7ea5d595aba7cae074ce5e33e5be647e59e6a8493f5f9ca6bce3ad3aadb519f6b59d04e695cb9e0da738b2c7d4d9e03e255e1bdc2b9bdd87bcce81428497b93514647d1dfcfcd183f7d83ee1f8a0cb8fb8ad86c53921be496ae6363a1211984a5a621d83079abb5fddd860f7db583e14f280fe696eb7fe7c12aa9b6d1a085cf35aa85f3fab21dfb08dd5d92885356fc68b3c8ba8ffea16f45a45dfc7c0f5048f8defb2818f32e8f396bf647469532ee16a1d421702d1065c8adfa5c90f047c47b6f2766506f9e2329597b316af32056674c9db8c982b449e59afd65c11583b551b7ee235e837ed9f415a2dc17fb2e7ee2cb09a70d2b83a672a6ae3bea6c2b8ef87034b911adf8c5854e199e1ee91b94bf10677fb5c87dd898d469f80cc7e2f6a7d018464", "0", "b927cd8cac52e583e3f03a3ccefa7b0e7d14064ab20ef868151f2106b68368de11895f143e4b81da18ec4567c82d3599d053df2cbea6f1b7b6b668529b22f5c88680ee3d27dea2b1561e87400c61682e640f0406781c648dd143cec6e7e814eeffb37bc4b8c0093f943227bfaf7697ea8587b093a88376e5abb1d2e00d5db0a2835ce13365f632be1bcbd7bae7f006999224d085300ebadee6960de8f34d36ad1968dc27b2e7ec0efb3a22418fc93e3aaa1aa20d7ff6195c53642cee339fb6dfda347dcd7c572e87f27c938ad8c77867e1baa9930378a5f1cb1f295628dccd02ac6bd45b47ebd785e8d3811a5cf7e7cc05443a0ef0c550bcb7de8ab2c8d27975", .None}, + {.Sqrt, "6746113a8f1359852db8d8c9f5004f28f34282588667eaba6fe614160de8ab85f279be8737a6f9f675df542be980d25c29b25287428ebd639ae6c00c1656e261820a26713e3fa6d9dee05782052295666baf11040692b4636e768b3e0edad4ee4b5bd07af1c4fd4342759498561ca82ff45b014187156b264f5c19aef4a065b60cfaf12f8619913dcad74fdaf640c6b4991b38d173e48babd54fb1d415b03d511d66814ac3dab7067a67891bbdd0ed77ff6d7f2e05c08893fd0cb8cb354c248c9399bad174954d97e9ed43180f6e62f5052a1363fc2d2db5998eb138fc3aa19332105e0d337480fa3792ec222654f261973066039e6446c98ebc9aa1a586a7581a537a628cae5d3ea61c937087d1b8e30d56ef05f6fe8bf1b322270a2c64bed3cb646ff4e35de8a0ad604a3bb90ec53191c899a83b7866de53aab413dcfd52dc745e7c73944052688b8e853b17c1903056dc669076b5644141b4d179c984a8819df55817b268926bda9e2de0205d317d02e362a47846ad767bffec28fe8e96b4414efa1db858bc4af55e506c4d8bec1a7804ffeee7bf33587a997c12e8e608cd0cd944dde47a2e5df403c0b25a6d229277045c21e2af627adc71592c0c361074a7cd93397e93e4d36a11740bbc0006e521224c15cd69cd44d8d97edd9da61aaf13f24ee5fe5d5ef573aff068ff73cc2f6da9ec1c8f455ba9fb02bd8d818c72b4", "0", "a2990e00a58f50acc36a1fdf11cfdbf571be3d181424ed41d4db13ddcc8f5fe4a6b797d14c62abc23ab74bccf8c2fc2379e491f24f1cab63482e78dc423e4a4d397cd6c449083bd276d1e9d1d3652f079c866aa8cd868aa119bdacfa5fcbf5b33c322a0412518ccdc2262e910af462b19fcc882be6404b3b26e11cd22d5587790058165d08f83440ffe59271439c5ce6f04a1fcbbe7139bbdb6954c19c3d034fa8a12be65fdeb7099a484e725a1035f460e6fc80403a9166b1b59ad9188428781fe1dd2cb3b7a5ffe7b5b8633e9d7fe3c598f2fc0b9d3c1cd8ebbd90a8c6787232f4036676c2064ff7be4c6b3e2457d6c58d75b93970764e7f009b3666adef34", .None}, + {.Sqrt, "77409e2a0396e9e2a69ace443c2647a0abd0a1d64c252735652e55fa2f47e341ee061eb89a0262c42335dc6cdbbe7ba4ee9e148f3c35ba0c7ed911226478b11b7e11124ef1b9a2d712e3d2f757f15aba370164e7e2f9f24e08bd2965fe60c36593d02037e45a1150517afa9aed3e374804e2d093ddbf7a51f3d0f7b612644f275c167753502100e4d17a9f0a7f73a8f4766aac3bcf15db4d458cf4c396655bfec603dc702c5b563013bbc0e2d3534ff46c4369b7de8816b163c6f1a028d1431c702f3b5d6032c8dae04e5141b6570d8bde0ad01e8fc71ab042348a314420910096a3656915f56e151b6d6402fd56c90f7ce111f91b69fbf0afdbe755fd52ea8a5d43f731f1f63011e60144a59047c78d97add7aa5b41ae58af27420e1d8ba930166a7538a543d8c4dc68b3c214df190ec9f9e0cc2e04e5393596587737ba03d06f5b903fb48c5de9bd18e0e799e7b125a70d55b102fa9240a927e44e624eb6c459b2085c6ed82add83990ee3133755f2e070ff4d355ec12111603acbb5a5c4f839d78b821a6225816a55b96d0b097147dc68254d4d87722fac7e3c9e42007c91a6be3b6296d248848b946cdc5b6fe6d2b21e6c2dfb8e6de5216a9ef2e5feaa653994d83de8c7e312213540a1beff984e09e2dec16b0fc12d9eedf374b1bb60e62d5901c975c412d9cd0c4c27ea4ecdd5f3ed97689529397e79a11c0f0a40bd60", "0", "aeb972a1346dbba550c3b818d785cba93ddca25fdf1593e06a273818342441d2af1d557550e3f81b1bbea29d07f5000d6f13b1801cc9ce2fb9f4f37870b455afcd73b83372d24a652a565cccfc2f6f2e896f9f8a06ae30035d26f1609517aa3f5069b2f6a50d89154375443f73c3452c30864f60108ac0006dd179803da1d73e9e61abb4b28fb29ea0651555d00c027184440340f3245906028dfc8e212c67bdddbae57f9950463488c456835eb672944770dcfa56b3b6148f1629018ef815974aa5cbca54ebb4830d42c6fd341ce72b0c3fb0ec9feeaf856129b38aa1879ab219a094d5cc2bbd2feaa27d47bf44d3ddabe73de388025ac7188c7628124aac10", .None}, + {.Sqrt, "e9cea52a5564368d234ba4402c9ad10cbf8afdd1cadf35322370caad834eac79d8e23acdf5d9f573ee903189241c61efaceea5ce2df9ec238b833cba284e0367ee2f090fa7d1b79b9a8912e625cfd5522f96e1b7bdd07a3a6200ed588243f95125b44aed37b40c19bf834f4e217a32a9b95d3177ad0ca1d0307bb201ecbdbcde8f3bb1ca3ea14ba2cf80296906379192d1125d252be772838516b87a78f924ff2da8edd98da0a0e8403bde56e7b9d3d315042c957e85c5175e17e1cf628830ff03e4eba8b7a35d40bb1e1a18d28766d7c7372c1474da418dc94485e456730dc594f7849ed4a46c839e291d628ab5c70d3ef57bb53e7be17f8b4cc4f0e8bf739adfd83a2f0586931b33738b54893d263fb51fd4f4dabe372704049a5efb3c0d41fa1d18ac978ffdadb559cfea0880e8f2583c608a549835a24766373686384d67cdde6d7fb3aa6719f8db8dd9147fcd452b0c6677cf07552a2ae3bc12261cc3113f85d3c7d0a205e0a6b85e826e0d2a1f022bbb2c0336b8a24256394ffee76889a383019c1e4106af45873a567f33a4c0158859a456ad92045708b4597f030b5f35983d3408eecbbd4a19e1018c828e9255435c1cb9cb3f97cd5274108497d1a0855b792ed60dca17c2d98940bc0065b2dcfbd6ee6b63dee096589f933ad10fd4a99a3a3cc96855783c1e85a050ea2042f33f2803c667697ecc112aef3d9618b5", "0", "f4a6ef6002a5f6bf9d26cf62916406ee7bcf70c24e48989a5361674eb45b7f318dea8f21c804b059f14103e7d6557712ec3e8497ad73b9f5a48fa6953e51cb00fb2679b12db5e46296f61d6b65525b75236c0b541729b2625e679dd42d753dca5ba6e6f7d7329555fe105c9e35eec2a6ebf31ceef41b48adfe76551c5efaace00f94a0563f7ca5fbe7ef17da517d1a6619d6f800007f5dfa4bc126723678bf633f4ef72b4023139c3fc543ea2f76079259744be0b91af90da94c47856100efb15b06cf0d3630a5abbd728ff2d3e899e26457f0c56f42647e05f9b452e84e6cba9f079070ace36bdccf62977987e0d9e30ce3e1e0eed60229d135a97a139dfec8", .None}, + {.Sqrt, "77e12f0499c8ffd06031af239eddab98c983ccc9d9028682df2e303d3f4478115edf6a21d28dc0b1d2ac1da9350400b822943680f50eec8ede96c376ffc4e4ad22fab7a64aeb1080b2da2f2c995c9466d31b871f7336ed59324aa9dbd28acded4b710c442aed10747b5999396d6560d8c9a65180b08e159611176c19c51bd374f22e6ad8531237e4bafe91e99b725328d54cfb7779e1cacbbf0a3ea57986d0cdc11e0c324f8d918263e2499004ac2c05fee0734b5cf537445a1514a63200c11ddc30fa51403ea856a3ce9909481ea4798d3e46d693f31b59b6587c3606b0f41be2794ea7302d45c15a4d4513c062bb284ac17c3b03f80e1d9b8d81ff04cd6d1673436f12a4d256ed17a51578d536c3aa9815966144a2aaf7005ffdc63736872ebf692a326370d6f28cc81d253a4e7a098b1ad3d57ccc9f3deec1390ff15c3d1bd30b2725ef11f91e6091c08111f36d85a3b34f8307782883359bea46d3a33f28a14ff535a3c4cea5d8022fcd26b3dd51f0876e9c55b7eb640ab6aef84b9454b67c64357371c656dfd55f94ba350f576bb4542dc0f905fda8eddfeac8b5be751289173fcf33839eb55c2390c4ff9b529f5c133cc493a4e4deac4dd128ed5f38306717995a3f2db410bc39d3af7d67e6b849c24ba0d91fa816c4771f7eaf6a1347658d6d6d3e3d93c6b45ef4fdf4545f772ac89661ee61d21e289d8657bc5d09bf", "0", "af2eebd3626f1204ce96720414d2751b98ada94a0336b2fa74f64b2e01ab02404b65f7b7cd9c685eeec70a7b073e63cfa6e8904a92c59b41e3c7b2b2de81e5127f1f1c844e501b64d55a7ffa1f3715a3b712fc4deaff53454a2c578de0dbfd9ade1beb7bf10c3457722d81867593ae6d90aa54833b3f60bed141fd103a93ab17ae74401914add1da037570537dd37ab50f310813b50d3aa964b7737cbb4a646ae225b7cb26344ec8bf96acd4747fcc0a8547e9e99243e9b78820aef14714cc488e8b2327cb6cdd5bd096935fabbe6dbb43662e512992508f2c1bf3bb98953807c55ea75cd3d6486c5b2497e31bd1549d368632c5965d62d53abf1be83938c72c", .None}, + {.Sqrt, "3c60519b9ec7d52446b3154b7f898f71db95db439ec1fc8e3b7b514f1eadbb7065e7dd36b2120ab78ab121b8727631d846effd2682423afc8a1275c3c67255283132dc81d41b5af9012a630a6a6b911991c1d3016fb1da55efce56471f7c4c2d30b3731d09993dc85e77e89e6650a640dfb0903cd1d0bd7511d1c011871c499c1c0c46a25a4863e2fc116a56f958847539f0acc13a8cc80e6029c461d1dfbeb5430653d7bfd1fff1ccd83fb06da3a906f6e57cdf03e2e2e2a06939f651bb99d5e7adc32d7c04c71ee1efcb5a7b447566833054bc5c29835cfeb8d00c2c244a4bbce7cf33498a9206eaa7737fbc5f7b21287c62b34d4a79258da687648634ed50efe4c6fd313e0812ccf154890b75bfaad65ccec9dbff2141ba24b1296d5ea4503742168ccf9e100e02bf16deab93822ab0b740b2859cf12984867286a6f5416c9ffe8bbf348e9565f1903b6a0a4e830762a56b585db17ccfdc7b93b8b27ed982f119cea8cf3502ea0fd815104aed271c165e643b90fe32a97b74533fec523ae961e51d3717e61ae74b1e22b125e11a753d4d3a89d3eb64eec1c74e6f47677e2deaec7a8ac1cd4f8e236dc1b88fdb21c0e508d87264816ad6d9071dc828e89aa7435bc18d69345fdd6d0e640fc48ee7218148c9c6944373447cb24a606205d5d2a5effd955038424ddfbc4408c60ebc315af5b911deeb7d17dc734048443fce1a", "0", "7c52cd3d6a36102cf1b9853db3a82509050973e0fd40fe0eb43dde8acf9e02c86e54016398680ac3b99612f66b399e99955475cf2df87be5636283444dc64e68d28d133cad87e8968acacb9fe53e4cb2d084b5a95930be0167aec035c0f089c0bbfad6bfa5b06fd4ff6b22aaabfec1549ab1367d951e8f9be2c7f99ab9e79fc7c2bf405179bd144e3dd8e00157431da34ba1db6ba11a1e08271961c52156b4a4cbb8ce51ecd7cc7a37c49c4ce3366cac7ef1e3a9e85a2abe511e8a80aaea8396fc5561ed298a804a00f970c2a4b3bba36e77fcf1599d10210aaac4815f44bfcf46f607be6c659189c625d1e2c3de0a3456db6708fc70e7dd7b8d26f2a1aa3b06", .None}, + {.Sqrt, "f8dda838987ca93abc90f722b03cd21f00fef66e2d2329dc0516cac84d9eb1462ba4d60d2bb65a470a5676bcb8cd6495a249dd3be5c5559b8cb0d582f6c10ee1d246db155de369477d87e1f6143d49db1f914315ee4a726edcfcc45aeb4d3843b4f3b1f72b78edf992b3591617582a86bbf811f0dc1b26f9ac428d1d78812bc6d270813d0834843a249972531b6918d2545bf55705b44af05de788ac31b9b1e2c21fddb00eda603be923421d67e9c51a317d8333842bd261279c3bc3901f7feb2f35daffc68548d8d94aac216f1b708a3bf668ce8d01691332d4980519935a16b3ef25248788d0f67202caa68bb72f3156de6926478be0c46edb76449c18cfad7b2c764b20b2d95b0ca402557fcf5b8816da5e01de600d4a2e9ccc9945dc1626b1867f6f58d9da495624253e183b204eff43cdcb666221e4ee215ca32e4d08f8b1576920e31ecbd0b1a676f9e2e80bd2aaeabf54110149e4946febf040a224f27e801f4999d582eaf7fec0b576f88caea7666112ff6bfbfa4f25087d17275350b8a6f83b8c884f0c6ea744e0bbf2c88d791de0901c8b0d0bb4d49a3cef15bf73a5e2ee45ffab899638d335b4b097c721e2fa708ec779ffd619f6f87cf2a2468148aa7b5647f58143c25f581a640f35cd561a91e1cd9c3a8b0f3c4d64ec91f8cd7f7c3e46e3ed3ded3758c46158d96aef7f9e602d8f50c6361c2ce39d358258ff", "0", "fc68605670c318dd96ebc293188ddf88bf67df114c7eb90deeb2ebb49d5d350fa269e7de17eac183d419fe05c33b4e2e2c08a03e62a61ad90d087f7499d54bfe013c072f302fdeb343fe6f1e1dd917384863245212be4d7346b991b75524dc743303ae83ce7621c4a8b8680a9b48a0b58f49a7a9860eea43631b0ff324a042e6920a37bc910e091be9059c560a90ccef66250e9ec1cf4e32bc06146570bc10388b49e891dd1b6bc2d6643923464921b4a0a6b0b426f7d6bdd62a413789c2c3b9c209c115ba302338b0a3a9517d3227281c67e4b287950b7eaf61251688030cd9d091e5b3a3c89dc51254e654c71c61e32c4c6268f022a97a1ef0c0b4139cf1e5", .None}, + {.Sqrt, "8195dbda3bc64e7029342d8a4ed799c439db4760db6ad2e9fc5cd9d2b2c3e827605da04fc730a0aa390874d8b2f67e99a96e963550ae4d878cf00d73a9ec4011da1435297d2454dbd6562081436d727cbe72c1ab0fdb0b99cae2c2d50c33e20d6a3622e6c760c853410175a7c9f2487813c33e7840104e3fbb8b534398254276d50406807fa51d61d07d0377acb0008df40792ab76f0b9cb5d2b406ca9040ef3016cc678eaa395409b19691faa7a843d8857c6949ae9a13deeb39753b1c0bb11b3e6aef87c2e3a49f65a9ff1b7e4af0713e6a50cf9d745d4d041367eeaf3abc328a43ae9ecb617dcf31c7fc3c31b364e6580372f587c9ea38b35efac197d8bc5f06302f144d23a0ccc06efb8b22c0d6eb13cfbb98a5b4066ff3f666611476b01fd194d614b6450d9a405e5d486028c70e34ddb3220adf05e643f941ddf68b7db09fd2129ee3e1160957251352099236b500c275902141881353d3051dd2c930e8794bc7b544cc9856f390d3b7a2211e352712d418962ab83bb9a9462b30231ad47ab14fd674aad20d4605252fe828fe2a43b1ae4f5301ab351f906308810beb859ebf988aa01f0e3b72c0d83737379c7d56ae804b1ace9ddacc2800175531e71aa7598fe933438a205af72d412284cc1a693cb7b59ad9a3b160adcc981a856f1ce8738b9259b0c9850bc7b063e7889af1f701d01fade80e1abc57aee2b18bbb9", "0", "b6230d6660685c4042ab3bc941fda14795ae04fd10320e9db9035d872771fd8c809d429a10325632571443e57bd2bc84244313699d0b04331ddac04425945d278143ef95be59bbf7c74df21be9809449dbf13f221fc6e26ad52bff12adad41ad87e706d2315d68259d3182ef79a0f076cab12cd53c4e4e505d8fc7e8dfe32ef50c17ba81e4c79a569ab2d0ce4df3bcb3cc9e11a8423cf72979e32229beb6525578cdbbd612ed23eb58c56c9e1c50bb6843a8d9c07b1f75ef1d6eb2d1995d5f097195128d341e23577d0a8de1f34d2ca6cfb1a2642c4b5309a86f6313eb32d9f969c2760accdd28c8988542aad11bb13ea7e6abd4b4c404860779f5f71a54ebb3", .None}, + {.Sqrt, "8e4deeab970be188f0c0595a5af2147f3d8430b4b4aca555bbcdaefacfc0bd6ebc3f261203742c9e675ffaad8eef8c062baa0853da342b029489adc85d820e57f8af8710189860f894ef39d00d831d02588146588e70453c242790fd25c1b7ae4e9ffdc594b95510c15e0f40a4205e4a16fb58989e923c290b9ea74065cebacc1637792c643c9a76bf5c30d30449ce3ed2b80b757db1cc7936333a9df8a1b97d97754d5b305eda775d8c372e28cea26308d523ae0fa497335ff9f55aaabbbe4cdff8563cf6bff529a2b79a184fb80fa0a2fc82fc37d4beb97568d203c42578ed01969f480c7408fcec26fd638e09f63b2dc0f777bf0fafdbe946385e7e431614cd373b6536eb91477b52ba7109e8d02db0d2f8348b5b97530a729d66f5d9f67d2508dd2e3daaafe937ccf1ff16751f89c52761032ba0c645655db81472ca59b0050cd13830a4e804235d8cda6730625e264b3e1f9a2950d98878831df9fc258ace84746b3f708e0910a8734f4d14ef7f0bca5325d604e666a7fcffdc265fc9e665525fbe5895ce08ce603335cbc034c31a4bd9e3b25c9fd5b7ee94dab8b44242ca1f50a9922ee646ad113b5ebb8869c67b76c3844a644627a67b82ea7045f206dbc9ed25977cf5861fd767a6849933b9c9a00286305722d426ed61fcfe44481dd8de6e82a7c8794c380627d9abedae6754285eb2f38af636b1866037c5bce3c1", "0", "beddc3bf5998558f0b4b71621c3fa69c366c15c3f9b29172cd61f1995a5302344daec8b758d3a8f6b0cf6bdecab1bf5ef7bc0943227d879265495f58c0becfd5a5693a50a9b728223f18fb212fa353c771504cfefa379c17503d2264592a95ca87257640d3c2a703186fc203e97ec601a9d8681b73701fcab70348f9f18137c8d6813fb525f1f9f8ba568bae60e5137dc31c1da9b099a6fa085850bf3c207ea51f7bbb1768e64714d112bdd19f01517bbffc3d2d71a80d50d49295573980bf454b428e7b869b039a2649b7dc16d8616b5d138b0ccd07b945dc3f7ca0e79d79c9ca3790da06c27df9438e5d871ccc2520df5d871dd20ef37d6cf47e11f79989be", .None}, + {.Sqrt, "6e7a927e1f4c609a5b8e816f756630c12b3911f50c9088da53b0313d24f4d282a39b4c4f84cdaff5d78da92ed179ebe6a75d530d269cd3793543268f911f8e74aaa12f05c4fa9fe1b44cb42298346b25633541d5d0a0003a6b617db284575607f3d06461556e8dd5a058ea99d4cf462c62f681c7bb98732c154061b0366d4ea348a5651953df2462340fb9b49dea5a3c2b608cf98c64af1a670d74d2b34d9de6ab1c2f7753dc1168d73bafb1c5b52b412a167812902c5bbcf4d9d848db9276e6fd699db8eac546fec35cc9981d9ceb96bcc3d594d5332beb71a988cdb65aa1c59f02a05a9ee26ef66cf90056965f2759ab570f79f9e57c28b03c8e4e919873868ce85f1a7f28a549dd83d0ac3dfa8396c1e7fea72195a070c7fdbe7abf9ff837bd13aa02c19e17243ead0fa342633bd8ed8d9896c3bc95b312ea9f5350ce675552a1fcef1ff6a892c9c0b80ecbcde36232f5674f71800ed707bc2cd6187b39396e76165b9ffd8cc1a9e8209160272048c4db6ddfe4574c247573eda997460ea225243406c7e3eda6bf1b42a0211075f584446d2b2e1cfc8f540c60258496f64970e8f5eb317f9d36070049a9a4e806328c181cc7f484db58437e42b1f85ecb587c1bcfeeeebf8770ced24e31d4370dfd225ca148de01ef2486b5e9dfe96f06847dc3dc204395114b2c6c11084bdf60a4b4a0f750f9a6948ecfe364dfd9f45739", "0", "a82c9a7450dbc23b49bfc8631682cdbd1027811ee74796de245000b49d6fd402896ef686fde03f6465ad453be16acf74633ecc8f1c3e6b92c5c10af9fe85801799a99418bbc19dcb86948753eda855b446ef3b66785c730eddcb6b6c9f67b7035e861e88a999e126aa04c3c1f815b17415a94e1cad7198228e63f202bb2938e09e4bad6969b6ac08ff06c615f944912f1d6812207064a5f51e8aa950a41fd503ad1112e3b293bde5405b3a94ec9765c1913bfaa9d391bd76ba8f0fffa2be09ab7f58eda37fc327c90ebbc3630ca8e0993aeba556ee778ef520bc2fb5bfc3c627454ce4d91bfd6dd518d8d945dc492d9f01891952c54f07863fb3023f63e34949", .None}, + {.Sqrt, "99083a44c5633682023165d59060d546af84cb7e6c4d2d59c303171dcac518ad4fe1dfb77b638d2213a62a02700178fd4a1b0188a9416d86742e95a873efdd1db7b827cf075c14927beff932e89039d80b487a4dc25bafbf925c314bd461cbb0102b3b10fd40dcba45896db57633e78df032b438ee3b4bbef33e475a7eb5191f920d1bb86ff9790ddcd297fe231c907177bbe402c4cb992ec6d3b5cd35e8adffe0446d9043a7be251b2518cde943f2111564fb22b06f076d40a4d7c28ed92a67c2707e3b1928dce2e08e06ed6e4d9e59a1f9824b6e201446c8796331d992961c2bfc7ec65ce75dc80d1b1d9e8915dbb5282dbbf8c13326bd55e47c03b4f552c29758e04a6d4a5f499ac21888f078c3b635bdaf98a7078ed96e7fecfdb468866a2a63c2b45d60b62b4e604ebecabe15da4495231de1b01bbc255ecf0ceee3806fc74974690231dcb1b611c245d965ea6021f1b1c2906bdca50cc215492e9d52daaf41df1c8dcb2897bb12d812bc57d38780d7d106b027883b49c27e18ee4459100fa3f5a4341fd5f1c8dfc059dc234978602e385c788ba0353d69b02dacaf3b2b50347e9c73e901fd5e942f214f8e3f97e609323ba0ae83180cbacaec77d93eb424c9502fba94d59af722e5a6052d6e11aa96a10227a9ac7e702796c2f4cdf9be202e13291b71a3af8d29d9b43eea907cd18efac5a0b870addff0c843a526eb56", "0", "c5ee0afee9384f1d295069cb3d3a4a381ea317f9c9d78f65c68173b0c46ec064c78b2ab0f5f2533a4bf7c77cec92322082928304e59ac692c378fb026c536f1c894fd939f49efb48f60810873f261d164364d47bf76efa3aaae1bfa0d97d31e7558b958b164d1c3b323f98c475e26ce082aed788f521b1ee185de7e23ad48e202321784c19073e77a691e2ffcf5b067ccb9ad726eee695f3d8dfc6613575d82d25bfec1ed53983b4a3a983dce8d20d22f7681047a23f51ef6ee41c453d1f33d2049f80a4b537ee62b0edc8785e7b58b4a52ba989ff65886597500dd6ef2e98fa2182115fed768813e91b7094f8303407b4709705a6b5b04706d43097b8e208f1", .None}, + {.Sqrt, "d9d2f6d110ae297f6cc87079c3508381ed02046c7d653a8121a477095f55a94a9d75519fce1ca7a542da3562bb6bc046a7cc3cd6ecb4a9cdf9bfe800b1646eb4275f56e040721de53c44ab67852df3e3b0a0a9ea9ed78c8297b91e876a4b036d33afff83fdcc79c7eb6882d07bc7d7480ce6604900edd1564504eb4c80c1392876379b721e5cdd70dfb1ccbd8eacd2fc84a98838e5fb0a603f6b57a6eea3f05e633467abb3c6ee87026b05713f70b44969b07c613f61f527d8b7de6b0e260d24f3f1e0e05faf9637ab33777ecd7aaefbefe139276eb544ecd0e933671a6356460e01de20b860b11bae8284e930ce72919385900e9fac5bde418941749cad08f72201657f837fec5b074992427128f890c627df4b96e450f004ecf5324783fcbae854cb6a4686a5b062cf0b36f1fc569aae4605c0addd00cada232610b6c70930bf65c512466b9c68c148cd649975519fa61ad357d11e58a8288ed29355369526b3d481b4e5d2cfc0a2452aaab6d0de0bb8bf28674ef9e3013b0792791b31b70564a352b1547f2ba28aee28776fbc40eeb0483a1200de2b1a13ed9fce92b5b81673ea2c8bc5e1067d6ddd23e8285950665b081727c091297132dfd23b7f201711d6bc814dcd3a624739b4d04b3dc76f4e9f989be0d9a0cf6e191405610acfdfb40d9ee2161722485b53c54e5012eb07c85155ab07bab5fc3c6fcbf797d2d9cd9c", "0", "ec244f017dc3b9efc95e2cce607ad51e518e8a2714901e620eb3d67ead73a99271686a50ba73c2f53463214e1d79150a0ba7f4cbbbb09535b1ac1bdbed0a8bfb1114f64181a34c12b976ff3fb91b7d34ed8aa166606faa15e3ec30d60c8cc058b21e5dba15c6e0bad28edc556abb45f55521326041329bc78ffaef3aa3029a3ddbbf4f059489dd81c5acb29252aa362a7b9cd60dad32d255e0e649f566620d659d2f1a084929e52d039b1acf65b2d8e22cb64395c3fca2ea333cd32ff6f0437dea3364a91f29d7fb596b06407d72f602e330a7e088dc83d82f9a4bde29620b2f3c44418a093dc77fd7fcec07f3c40527546cf524d617c6a6984c9681dda8a675", .None}, + {.Sqrt, "e966aa827cdab4a5827f308173ca3fd25e05db594a402044fd53ab87c67b5fd8e8963335d155d78aae39052a0b2d5d88138426001c3f14db4b3a34eea4401b29c64fe5988cd9121321857b71a70d8d4ac2271d644397985716975d7f3d22e601e3bda6a191dd98c1d601b5399b57cc743c9f91708ad6fdb6ad2ae567535154b5bcb8b66716d15ede1bdbe6a465fac4c98ddbd002bf049b641f4e0e09b7574ded36005dd4b29b195de61d6a5f750e603dd45ec5d1877f73de791acddf53b5d49789b68d34edbbed026b61913dc300146304d4c67ea93d2500003f55a38f9953e8270f8e552e8d17a52ed66de4491065ddda1d02ceedfbe1355096ea89305b1896f6400455178a68ab45a29d787e4da6e64616b1d57bcad2439871986db2410b341e60e6cd7df7e66ca8f26c56e6a8279035ef19c6e6ac5174c35af4611069cb39101d6b3e59cec1e3ea76dde98c201d088dd092b914dc16bd507136233f5c34ccfe353ab827ac15efeedd6755ac9b51cd540c9635306c90f69ca5ea5c829383e4d7192584fa924f3b05d019dbdc5e2dfb71ffb0baec6d483095777c82c824d1607e620624bf29ce0c19e63a116bcb37e464f30aed1d8b4ef126d9ac66b680b318b73cb47bab2ae082d430338ba6cebfbf5f706f37fb888ccb7f10900559b7a8246ebc65104b261db3f769ab52d58f0be65853b218e3c2641926e1e444e9c7e40e", "0", "f47082a7d17c15aac73633a14c0a4628da159fd582d2efb8832e2c47e05e40b94aa01fbdc6e85749d3ef265f72e7069a5f3aac78bff8cfa2853f1e364197a0cc640a7a0e60d8d8748e17779580d9dee2f7325123458824d5ef4e5b3dbe114ba16167ebd26a93da564e259303c98d3cad756aa287f2a4634de11033c19f296a394efc2279de43c5f8eca3ef6e278fe4ff50597af7ab8418d7a4914cdd23d1c95227de83bbe7653f1109e0f33055b80dceb45fca86a22c1063f2ee5717315a1951c636bd43319a3018fa6929038c5ce2136e2cf8c4d4ced831d7b5f6c99e2623d16c0784811f193dd05ad582353abcc925014c6d55695ff39c2feaa8538d62b8f1", .None}, + {.Sqrt, "2de0b41865c986e681471a335b475bf07e0cb1e1abf1d0d513e2afee0fcee49d53df79913dab6f2bbb28567e63f1b57d33dc726ad5103ede8d1f0b87513f85fbb4cc7a7baf7d47f6e0744d14d8f23fde0439c9d82cb8612ca4461447a0ccc1f8aac4ff7e86e26096cd9ccd03e2f50e7d1b6bf7c2f8a9b744c65eb2ba1bf999ac0fd86e492de2f8f65382d8cebaed43487dcb6f2cd39e3c9f9e9a49340bba6505ca48a951a5c6b15f4322279ee827f48b75e081c4a144ba09b8a60fb121ccbf833f38f056ab0d81bc254d5b116f54022f35e0975f57690ad80b1f0c271139b37f44ca0b309fb6f140d36f2c00438380565d0e2c75288b767a3a956fa676c372def7de4586f75c0fad96409286b0666888095ca1adb8b361b4aa6a2dd480d3a53a73a8d71901a8592d9caee6d699ed155d71f248e614ca3e3a1e8a3e26ca260bb07c09e64defe6005e6fd300d32ffa20ab5318df558fda319f91e2c83da529e9942cac95f77e23432577dfb1b2c804b0794be6ba7e1e2f21d643bb3c9f78f90d2db6fe0bd3b2d4fbb4cadd72336e88d6e3dc82ae23673693ddd8775fc9e66bee626ecb65b08147f6009e6b0bdcd8be4d4bb2b28561bdaddc5683929065aa9a84a2a05da66a4ea06f530a50681d5271b86d3834e4c3b4e846b5fc6e171d6fe1fa2a9c2f682d55ea8f40705138747c589c943d4c1b16bc14856fa661de5d86644e50", "0", "6c5f7bd47465175b4f10dbba0064fcd8b8d73aec9960569847706e511023dddde9fed103f157d38d46b528aeaa2f75ba01396cca39706fbcddd1852beb0fc85dfabc00b6bb83c813cef180c02dd89a52bc84ec20bbe5eb364dca7fb9c799370de4010c1077bb98f8495acf25c2f5404786c2fe541c59df82f9605df113b445523d7178038db20b331f4b71039437b2a25729758d4b3682c414dfee8ccdbb603969d982bd261744b64342c57dae19853a77ae5e55245739318bc058137571f87634562aad5279e7b9896d004272b5917cbbf3938313a780afe402a0085b6541c087d3403b9595fd275826fa54a1da1d974b1df24b5d039e503be3ae4a667287f8", .None}, + {.Sqrt, "516202258628dcac77f40bf77484819c9c986a31738116e05ae3443ad78d81f6c66744c33911324af4d94204db61129f198998c5f5e90265d363303c1be472e05272bf3268f5e4e7ba9fc754b54c0e533a9c2df5dba420c13c68c9574bc19842e7f6ef3068121e93aa0917fe6235f1f7ed8a58f791dcbc9d246bef2e4e28f7190675d6ad9339b062953d914412197089660430f71dfdc625bada14c4d0fc28ad8fa1867271ab6ec1c7ca70e87c55c7bf056034c806a3b7758941cbddcf2a07110998aa83151759e6e1c14627a06e45f3bf23b7103ced04a573450d2b1505441a2f6b0d18ed37c5e1dd69898d0e5da4c478e48feff9ebd9f9e21780edcab20236f3f5b6ec1401e0a41ffb3e56c901ed5626e7bada09d6008e463622c1e5914a3cc1a1a1cf4927b4d96a596acdeb50aff64a5d58077c8120a26bac15d2a321043a5e0da50533f218058320aad4a89793c2ecd8d03727955e45aeec33c8992b835de52e8d5d1685db082eb5d97795a5fac143b4ad066f11d92d90744ee48e3acb863f14855017862ba48446cbf530fc93de871ea964131217ce7a3cefbb6fc0669e8dbda8ae13f93a8a5bf24ed4abbf73af5d7dfad2aa77dd40913a57e4b09aee1b09afaa87034d7eaa432456e7564a30c3b08c51a97aba7cdd97597f292131e6de705c62f7762cbf1062c111e018d8b24e8e61259a429986b460affb3155019c51", "0", "9057040fca19c6fd6d41a6c287d25518ea5e9614e3df52d111960f18ddc4196f6ead09c14d41a597a6e80fc2f821de7c74aa1106e88ac5566d424a5ba7685350f83cd6f988e612ebff35e9c537c51642997b19ab8e8140af8b852ee1b28e6e50d2cd044718218db1ad86439c5ce2909f4af85255d65514cc259c8ad16c9f36617018b01e7ca3c1934a1f271a3d3a8acfffe03ad667db621fd57182bfebfa7b66d823f0460de9df54eddb4c0b5fe9586df033aa1844f3c6dc3f7d2bd3472aa947ddcab354ed40b8fe1f16877482221095346887ee0128d81b044575b56b821f57386237159be87a17133277b539ce97c446023dd81cea691c9a484ab4629ecb85", .None}, + {.Sqrt, "a3e96699f0d0fb60d5cdad02ed0cf3591ef77be296ec79b28e595b6a4d3cd487fa7cfc6c2dc645d405428d8042fb23005c8234c9e2f9e403a86c1ecffcba09d87d406a30892557e190a8e8c9f7ddc29c0d0c17593c4462a7d875ae241cc0e89678cb18740657101c9f9f5b83808140633ab1aac9946dd81cc44ce5f40525d337227e412dfbbd65faa1fd1bcdf49964d0607f30c31292f3cbe118979edef8f13e7c5451de729a04522325a0dd1978ff176a6119a69703123b454abb70559d8596b1484d2757b1aec43872a31f1c37df5e5b16b667ae0388cbb02f01f637272b68ef599fdf091c4e285ff5c279aa44fba59b2a5e738a781f220233fdb0e0754dc567c62fb1a2c273447fdcd9d7c5de8a00dfe4e8e659aadf950e137e267a6892a65eaa5afebc6f386a3a079b63f658a0e1aca55d1c8077694fce4562ebfd3d89caa7d62cd3855b1b3757082897362fd4c42f162e38c1ad2ebd651e717e811d6a092a7850a6cd5c89ca3386361f4bd02658f2e15f62b70487d28c2d5931bddb72cf40118c74d4eb9bc55d861ce9493fa9dd5a567d71d2e37ecffd98b7473fafe9e2e598031d7a60fb3e7ba8a8207355a39f38803cb4c6602d91115e62a036973644da7e156bc1da0c079a37fb931ff568b390c0b8abd00b82413434e9e583fbbcec5604bd8f9d63e3a48822ae04d23f2378ff01842fb653b6fc662aa31c1ab2a638", "0", "ccd84634539da13a07c11b6f1e54c1e79b437c02d525f32053be1fa3f4355b6c418ae921eeb480b491c2c6feb6308d72a4979993ae517c37515cb530113259ca44f8cc076f4e90114b1b55a728b26dc0d891bc68ca8ef2ff1a581a616eaa5172a553ee95369b3c8623578fb1155c65e2dc697937786ea8d5f9dcb1c65fcfd4cf9fa908af8f50b0305ab3b9f1076d77f94677a0b809b5b6ba523a25ce0170a9a2d0f69d4292b38681bff4c5244b5d63fe5195a696db1143f186064a56b19ca64c047cec45e811e44e76ad72f1a12561ed6e0672f84394702ae107aeed5a3e8333dc06e070a0abaee0fd769c132e58c0b618fa637575ecf79d5681a56616027578", .None}, + {.Sqrt, "dfb75cd7b0d6e6e95fad91a9d3ebf9ee34671fef11bd0f55fab11d1605e5605676bcc03515b24c3a45bebe51b36305119cf329795fff14222df4857899283156ab74dd2e2425d3026e3fa0fe2aadc7bdfa16263b4db44f50222e085ac981a28bcefb9cd1c48da26637a3d239e5a455ce8e6dcc7ae3961e76b487732b96a87585a3f73c292b228a6ead60bb0432160d0c945fc6ac77046625d68f19a9eebccec295911d4b12158c4e5a83b3283a691dabef40068ec4e9a22a434bf2c5af27883ce12b53287de21b87ac5adcbc3fcb0b924a4cca3301d269d471c510086801ca746750a60790cb1c97fc2a7012995e82e78d7332c8019f7115db4f0bd69932b4f5c79ba3bb8a35f8dc9294435142d10838ad7180e931ac759b5f272d8e714e162d778c223f467698aff16c196404e30756413076c9e4cad2636fcd0008011c7d60554b17a2db387be059037ec9c5ea4b8f642383c5e826b65b72af645dc2e64bd1a55a9ea900c74a777d7d35a6675c800ea9f4f4ed4c7933acd26a6201b0113452944ae7918ba40df4cff3b5cac9b911e423ee9db3b8cbe7bd915427142f3742ef0c84d8cdf08b86aedc0cb93b160bc351f81ef961e1388066ee8cacf219139aa44cd7383dfa38e54973b9b769c20624880cf0188f93dc589d30bcf64516c29fac89e8e2319216bad6e049a066d8a10ddea181a4386e378063f823f7c161f93f06", "0", "ef5079dd5929df5dc9abf3edd8b4f06f210003a7edc2aba9436490e4cede0d94f32710596ae00ece14ac2efdb4a81ca104e86817d953dfc13ae35ba48b07ae95a011c0994d530ed081a32dd868a7f4cfbc1a18afc64d573e317511f86f6deff38b3c63055687092e826a624b3200d8144a0db24abafd059886eb6ad218a45e9e2f29e6ca18752d87cb05e9408112c6285ec4ed1fc66653e494e099964ea30583507e80fceab459f6a5907ad3743307686de8f13a89c6aaa888fb0d44cd408e999d8b3b916137a4fd059bdafe9397a2096f9082e3fcd673d20625ff73bd3af424c813de15678f8387e60f4ff6d81f5184c63c59a1d777ef30fe7ddc27d5b0239a", .None}, + {.Sqrt, "93fe21b68242675fbce147bd06e97ce1210cf618841931304af77b8e3b39e1cf5aa98a403b6b7bc11fb6b459b531dffdc60f65f45c2b5a2c82eef5646392f5dc33ec61f9b7a3c8bd9e119bb5f89d5b57fc1d70f2f60c65b6924e6023bf9dab5bbf8d82bc67d49a4db62cf2880486f51b8f06daffad806792a4f2e2c1383b4c62043322e7a1b22e0709d34a5f25dceac820c354dbe0329edd8be6497b9a2fbdd82c8facb632b758796101b233ff692fa343dff2a66ec97b8e5d234f6a6538ae15d023d133e71f4bb434f4ea5a4077f02ff0d2de5ba485fa491c738db703e30cb084de65d3a521bf4ac4faabd4b4a62de18175bb2bac220df9fe1c1f4cb3eccf1c5969e642f173a695d4f566e11a2b7a25ffc3c56a4c43c5fce2103552a29e87eeadbed3c1835cd9b2520d33bc23d30d01b5eaf4f77179ccf779cd63d631c76a78091d9d3993655ef4e77ee297a25a1dcff79f8f1761bf4a0c8a635db92b0a76ac40a50a1825bc56b6c69dfb835c2250d635da51ae0aeae1a646b6be97fbe1b58eae9211d831b9078e7e57a349b80f1833e021c489316926ee20251793cef7a8f39c34dbf920ead5df06ab2453af0b42b52673ca5685b87545608fc7f0e15d965c71866dc947c092afc29e62ecb30d4c7a1a90f210b3697261b8775b4dbecf7fa41d9fe90f00a10229136b3e5bfbbe9f3136fb0a1c01e8b97988be1139931af2e8", "0", "c2a4c3151971ea2c3104ceaa031388db2d85faa46e2d52e523c43d2abc3cffef0f939aea72c5d37ad7650793021f102b4608344d101572a91b3cbc30f29b73c48fed0d67641865274814f675c4187997ed81bb08d6eddde901c54fcbbaf04bd31975abcd5e77c0a1954d63d303e09aa5d33621b4744ac0bb6354a7905b365fbc1f42b5b470a61ade93f9bcf78b6471032a7d141f6491a5457a4a3f84b58fceadc63481744f6f2504c5c3a05b77a6c1b2c5a71f761751996774cbb2b621cc19cb8494c6ce752a6fe157eb3362dbe97b19308ec88c83415dc3a0e21ca57f89651d6ced34ce5b2b0d8a527d689928378243e92e468b8018685553e5f7cc4777f554", .None}, + {.Sqrt, "9cbd6b9a8685c0076e3322ec821174a522e3c1b073d79d1a3e0fa3a9748eabf214353bcee63464fd52bc7e700eeb877ba409c9907f63032553123c82c259dd8540f69870adae3332c062d9de133d85b21e55c622be29632b498d63ec4dc8038de2c8c65141a1f6d477412103306e22c84f837a476937de90c3a268b6c2f7a9af908a23160096fc0b97d80be05fdbd0742afbc4a14adb215017b96ed96016057f5beba4042e32fe2563c620c31dc1e8c42aad62e43d39dc72883c649ef595c3eabc09070a41657c0b3759215a44341839292bd2af825ba1a411dae3f78c06eac48202d8d400f7ed4ff7d4afb80c6ee3700a4cc8c267fdb5b08b0d9910a81d480e60043d4e5bf5adb26a99f1665bd500585c993e17ea7504e885e4b566e6c2678c0c5ba31901137741df7bdb2a289283f894e34b448145b35e72653c29fc13bfb99750b48e719392562cdedc9223a77dc25f69f40e3de8639dc69f321e5d982c1bc9eef761b4ec2a596865bc780ae9497607e6b5c5ad0c32018d7d08824e93aa511b604a44c9a7cba1983275264c061bcec6bdc96cff8cef9cc8fdbeeda9389e56fd6af64d0d11023f0daaf45372f70c6a1c30a938e7ba4f3c5a6c2bd8405788128fcdd3e96a38d8bf4c5fe95ef5d74e42dc840d093a97c09d596cce25d2ad907aa5e25e300c4176625d03b591b7044d35b94324a5c8b469cea5658f5a4f07faf9", "0", "c85034c8a2b6feeaf4c2be37d6fbea006ff90674fffeb4ea49eb3363432c219e18a21b666ec32db95e441ac11c4b97781ff8ecd7b32f261223560cb169f8606ad5e58210c3054f790da95626c7a9ac1f684bd1c0a51ca5a9f25a9292dff203c79f3776431a9c2caceb7dc13f6458e53f7127b517e55a31f631bae9d81b40ad4b0a9af411106214bb0f522c7dee2827941ce647fd40649e86ff59cc7f479b4d349598c113e8eb1a92df782fa855562cd08d782219789f83015a49039263fdbc6bc57c63c35fc0f4322a51a601b2c4905759b37e65415a81dbe524d2d6b945f7b0a5db6edbd659e3b7fe93ceab91dff29b125ef96dec7a3b03011e89eeb21988d4", .None}, + {.Sqrt, "1b3d91a254e3e4a873b20b84cf293e3040fce56740953096b6efc1c6c004eb505b1ce7448d4e726bdca6627781f9c541c87f7505773594fe3f8c4acd7ca4d6ec09339a14240afc455ad8b8ecd47bfc0b08f2e23fc63987c42399f62ea4e5edd540aa1beed5443a97fab4f2ff113dc6fe2c860a2bd4a10cc18a91cef0ad11cbe47288c8224af4a49d5a413466062850d9e47b7f9380da2fb6cecd188200fd7bee779859234788f0fd201e1d0203db4099fc9613187ea3a78e6e5c1690f2490806165039d662835c3b72ab2aea1072c82eab64483f714203d249ae99d4e7bafd9127d8b69dc57a70add62d9b676fb8bf11bd04f6d0556e750e3ff6f66de4089b52c0c4a1216296b142840d97612f271ac5c3cef995fac98629f2cc9322fcd7656841c4af63b580978d42af991fab8abb97245e345c6ca064c1cfea514195023ea04179451bacf5f8f8ef0ee41dc267cc08772250c775aabba4ddc3d42921d91b28b90b73773478b0ad021337219ad9651004701d30172f2e53371957b90a8cc7b48d2e44a6d4e02736cd90c1093f125f9e843eb9a9db7e267997bb72b8d1319c98abdd2855a12cf3ca83121623e993d9585c4f6a4b5a95bbcbbbf71cc9a397c07aa36d8fc0cad3e81d87b35dfeeb017bfd608df68af247de4f67a91789ab480c782a91fde3aa4567ac288a4805b36cef9b33dec5673c9d262d1b92beded5bdcf64", "0", "5382058bdf2be8bf99de16ea54e821a8a3de74bb9dee0cafdf8820967ca217228319cae4cb58279ee3e6361890f9a1d0e54b94cf1cf3833aad7467b78d804867108263fd4707391aa23240d74bf1cf8171f47a7acb690070fe3a5d3dc7b376b461cd6f841bc1590f226825bfa82b03062f03b84eb195ca9e3082bd0a654dd8c5025c22a8f4163a095889f379bfd84cd4cf35cf7fe38b9fe5c1dbeb5c2241c53575b4ac0da2fe55034e043dfdf31d904f85d2c16876fbcc07923035ceb96f4ef85a770e657663ae979a92c6ed949762bcfc974c93f75af26555d6a793962c1bfb5a579a92e15f38cd60a0dd58f5cc0d503495faa69df87f6362f32b563ec92fc9", .None}, + {.Shl, "521743bab8c45885a4cdfeeaa0556273298a3ad334e35709d84cf11f8fe1cf57f0e142ecb555450fadd4c6ad616ea0b828ff0f6581ca1eb22baf9006c66b8a8a2a9996247f2ffa1067d8ac1d4e5707211037e5a2ef86c304ae243b901c8e6d7c9af93b29f038646201151016f2611f1c8497027a7ba23bb312375a104ce084e5440d097f42bbb8108b49b8107c670dd856910199fa58026e644635883b3a1759d8aaf50fd41f2fe03adfa6d75a534eb223fd9e030f64feb19f140e6131f5dcd6d912af36299426bc0a8f9c152ae87cb1fe9a0456a8a33d6beafb121eff6bcde6e9c6172cf6070953f833ab4fb7db901ebddcb3c38746c7c21b78b79443eaad97edd560ba587d509c6eb9796928c7053408633c3f788142d82e7e4083be85f16646764979710f238c56d5bdd9a08c031a04670e8904812ff54e3b0f463746213f48e04f39e1ff468d12d8e999d9ecb8d94f05ab3c85f40a0039e48e8ed1e95475fc345e29606434abecc40f59ad0e255c956e6a5161be091de4fb10fb961d94f98033e2dedbdc512fd10ca674e936b0f26e9a05ce10ea24120377d7b994bf08be59d3b8d9278f07864e0e5ae5c392d5495fe9a598340e301ff0926453504d2f5e03ccac7870162bf1d58adb40e5b9f36f859b37b6bcb36d8cba32d52f84bd064090118ceef9c594002dc36ea42b586cd4b2047978ef21f7c8e3d81d8fa96efbac", "12c", "521743bab8c45885a4cdfeeaa0556273298a3ad334e35709d84cf11f8fe1cf57f0e142ecb555450fadd4c6ad616ea0b828ff0f6581ca1eb22baf9006c66b8a8a2a9996247f2ffa1067d8ac1d4e5707211037e5a2ef86c304ae243b901c8e6d7c9af93b29f038646201151016f2611f1c8497027a7ba23bb312375a104ce084e5440d097f42bbb8108b49b8107c670dd856910199fa58026e644635883b3a1759d8aaf50fd41f2fe03adfa6d75a534eb223fd9e030f64feb19f140e6131f5dcd6d912af36299426bc0a8f9c152ae87cb1fe9a0456a8a33d6beafb121eff6bcde6e9c6172cf6070953f833ab4fb7db901ebddcb3c38746c7c21b78b79443eaad97edd560ba587d509c6eb9796928c7053408633c3f788142d82e7e4083be85f16646764979710f238c56d5bdd9a08c031a04670e8904812ff54e3b0f463746213f48e04f39e1ff468d12d8e999d9ecb8d94f05ab3c85f40a0039e48e8ed1e95475fc345e29606434abecc40f59ad0e255c956e6a5161be091de4fb10fb961d94f98033e2dedbdc512fd10ca674e936b0f26e9a05ce10ea24120377d7b994bf08be59d3b8d9278f07864e0e5ae5c392d5495fe9a598340e301ff0926453504d2f5e03ccac7870162bf1d58adb40e5b9f36f859b37b6bcb36d8cba32d52f84bd064090118ceef9c594002dc36ea42b586cd4b2047978ef21f7c8e3d81d8fa96efbac000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-40df4d8e99f4c7075cc8cb3aa04ded5473ef1dc3982e7ab8789929dc680ebe107b818ec57e00d7a6edee3b65beea8ed02448c789453cb3583ec80ca387ecbc3b8cfd3c0da7a156c41acbf6c7098b2b04801b5879e92775802926803d2394d644fc05c49a79462adb93f76ee76d2ed2ae4591750608efc69e34e4c4eb21ecd5f05d5448f39d152f03217187c5ded64e8f3126d33d70ad906671f29be31f56ba33f63e5f929ac9a0eb5f67b6bb23aaff6b2fd246d93b3e20207a7a401d36f80e33cbc1f0b39258994c20f176e24c50e1441616f022de6be4b9d4e8d350e8a7814842e010f8636cc443c3928a52972f3ffa3c24b9a20fb9d6c72ca36ac9329f84da9ccc04b8d789a9220577542a3f85f43c34d01848ecff412674c22562949de006751eaebe141717ae85e739ad38c6fea1ad42bf04a5d0a5ed8747c6e52ac088b0347cd7ba2e7cfb6419f4169084d6eb1cd0a99357784e526d552fbcc9626d995b38c33050828925d8e4ad43ec71916d3f0428dd9593ec3298a1f8244f1bfecd4bf9748f583e98eed1c8a4e6000f8393590ba19e0104141725303e71e13a1489e6489623fcadf7baee06a4a7c4fde976d11fef4cd36205c920b85b3dfdc515928873d563504a9bd9136446a716dfdc0f6bd63388b2cf15176194926641af9cf3af70aeb3b724cb738d98327a6daa5fa13513c26be869a847df6cfe0fc71d78e050", "21c", "-40df4d8e99f4c7075cc8cb3aa04ded5473ef1dc3982e7ab8789929dc680ebe107b818ec57e00d7a6edee3b65beea8ed02448c789453cb3583ec80ca387ecbc3b8cfd3c0da7a156c41acbf6c7098b2b04801b5879e92775802926803d2394d644fc05c49a79462adb93f76ee76d2ed2ae4591750608efc69e34e4c4eb21ecd5f05d5448f39d152f03217187c5ded64e8f3126d33d70ad906671f29be31f56ba33f63e5f929ac9a0eb5f67b6bb23aaff6b2fd246d93b3e20207a7a401d36f80e33cbc1f0b39258994c20f176e24c50e1441616f022de6be4b9d4e8d350e8a7814842e010f8636cc443c3928a52972f3ffa3c24b9a20fb9d6c72ca36ac9329f84da9ccc04b8d789a9220577542a3f85f43c34d01848ecff412674c22562949de006751eaebe141717ae85e739ad38c6fea1ad42bf04a5d0a5ed8747c6e52ac088b0347cd7ba2e7cfb6419f4169084d6eb1cd0a99357784e526d552fbcc9626d995b38c33050828925d8e4ad43ec71916d3f0428dd9593ec3298a1f8244f1bfecd4bf9748f583e98eed1c8a4e6000f8393590ba19e0104141725303e71e13a1489e6489623fcadf7baee06a4a7c4fde976d11fef4cd36205c920b85b3dfdc515928873d563504a9bd9136446a716dfdc0f6bd63388b2cf15176194926641af9cf3af70aeb3b724cb738d98327a6daa5fa13513c26be869a847df6cfe0fc71d78e050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-20136d760352f1c55186495dbab35164d757886fc16db04cc995179c5db5bd8cd16ee87fa9d580d1d2117b3d6a96bf359f655b4feb14fb2f264ce88420f292d8187f9cab4bc67b5a134be2d47f56d0acf315f2bc28beb6eef8553f924e6e96be1c8ef2dc2a335bd4cea39f27db584b462b99b6b77b0b5d07c9cee5e89437545af2e997a9a579bc24a3fec36c69df1cf87f849f853896e95ae45f48a4e4a724e3344b32e47e60c8be1c24a7ae23cdd714e95088157e23167a12cf2c69a4d2ea2a4ba7740e0b6783883d031d75bdaec56e9b98c09dbea105448b874ba3d209838886931c203ca3f9c83b85255b5ccae7c177d52a5f46f5cc150f46ea56e1a373bdd694df4c506c514926d0659c3eb56124ca657f9334fc35c5d1821230499ff8ebca91a1fffbf5c7da17db59b863ddec994f0b09dd6339807482f9b00c92c57a5933703095767c2415b2522ca298a94bafd965c820f114fc5ea895703b574f2ef6ee2b7533c5f44b46b348c9bfd3ccaf4558d9caff41757ba57ed8970b9ba3d2527a76422e92f03b4134eadacd29a1c7898e4e3d134d8f3fa813ff724db96dd50c40a71381e3db8cefe42cfef37f9eaa915320ecf94449343234a060c8517d290897f5b6c00c9343f1c3187b7fefd2752a0ce6fd45f3962a7940cb4ed41715fbb4237e6cbdc3c90e3e32da0deda21c0af3912d7e59d8ff37119fe8f861fd54e482", "168", "-20136d760352f1c55186495dbab35164d757886fc16db04cc995179c5db5bd8cd16ee87fa9d580d1d2117b3d6a96bf359f655b4feb14fb2f264ce88420f292d8187f9cab4bc67b5a134be2d47f56d0acf315f2bc28beb6eef8553f924e6e96be1c8ef2dc2a335bd4cea39f27db584b462b99b6b77b0b5d07c9cee5e89437545af2e997a9a579bc24a3fec36c69df1cf87f849f853896e95ae45f48a4e4a724e3344b32e47e60c8be1c24a7ae23cdd714e95088157e23167a12cf2c69a4d2ea2a4ba7740e0b6783883d031d75bdaec56e9b98c09dbea105448b874ba3d209838886931c203ca3f9c83b85255b5ccae7c177d52a5f46f5cc150f46ea56e1a373bdd694df4c506c514926d0659c3eb56124ca657f9334fc35c5d1821230499ff8ebca91a1fffbf5c7da17db59b863ddec994f0b09dd6339807482f9b00c92c57a5933703095767c2415b2522ca298a94bafd965c820f114fc5ea895703b574f2ef6ee2b7533c5f44b46b348c9bfd3ccaf4558d9caff41757ba57ed8970b9ba3d2527a76422e92f03b4134eadacd29a1c7898e4e3d134d8f3fa813ff724db96dd50c40a71381e3db8cefe42cfef37f9eaa915320ecf94449343234a060c8517d290897f5b6c00c9343f1c3187b7fefd2752a0ce6fd45f3962a7940cb4ed41715fbb4237e6cbdc3c90e3e32da0deda21c0af3912d7e59d8ff37119fe8f861fd54e482000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "6346c48e0d0bbc2148c48dc3c7f0bf48b87412fab948f0b0a89dc87b67b4c14a05a3cd737ecad23b7e8b1a011d4c38cb5c51bdf3a1eca03004c149f09c5d63ea63690656aad97002fac1d3589bc81d535a49a7719f5d2c73582c8b5b2358efdd2033d16775e8ab1bb72541dcc38b4ee2ada25a6c759e50eac987cdffffa7b7c9d651475bf26337433a5f32d5b9ac7513f7e2105df999517b3ff00bcae9bd130f704cb6625eb4ac3441ab5fb9cd91bbc1177d9502998a31b05c0105ed13c901a582cb5a474b7d0c3a4e9bef612366ced058b7e5d437662a618161dce667ded6d242478dc07ef7160f4f4e6a34e1ded2ff39940142e49f4e400de424867f6202eb99cb911bc3ae272b04bf40aceff290f22a33665474c4f0d42779f9baaaa01a4c9c28c38d16a827fc81b094245a674bcfbb8d77473730d3639c03328f2d883d4e29fd74dd85bab8d117b36b039d6f7ede67b15db9b9dc21a9119b38801126ab4a545af45d9e53425c1fe11ac61be0992f0f1855f1ecf0af2e43932b7dd45ad9b72a65621e504db3e5f586cf7cc22a798e9192048db004192048cf29bbd8de1e17545c070948444a367ccd54274b9a0c2330c1f10527065b5f88d058c304424190242338dae8c01255c2ca5f5b2c77cf57594d4c1dc54c2f3f2208c248c3ae0a4e682fe4d2b87890b6d888f0976146881f5e3746e4c702cf8069e1748c1838783f", "1e0", "6346c48e0d0bbc2148c48dc3c7f0bf48b87412fab948f0b0a89dc87b67b4c14a05a3cd737ecad23b7e8b1a011d4c38cb5c51bdf3a1eca03004c149f09c5d63ea63690656aad97002fac1d3589bc81d535a49a7719f5d2c73582c8b5b2358efdd2033d16775e8ab1bb72541dcc38b4ee2ada25a6c759e50eac987cdffffa7b7c9d651475bf26337433a5f32d5b9ac7513f7e2105df999517b3ff00bcae9bd130f704cb6625eb4ac3441ab5fb9cd91bbc1177d9502998a31b05c0105ed13c901a582cb5a474b7d0c3a4e9bef612366ced058b7e5d437662a618161dce667ded6d242478dc07ef7160f4f4e6a34e1ded2ff39940142e49f4e400de424867f6202eb99cb911bc3ae272b04bf40aceff290f22a33665474c4f0d42779f9baaaa01a4c9c28c38d16a827fc81b094245a674bcfbb8d77473730d3639c03328f2d883d4e29fd74dd85bab8d117b36b039d6f7ede67b15db9b9dc21a9119b38801126ab4a545af45d9e53425c1fe11ac61be0992f0f1855f1ecf0af2e43932b7dd45ad9b72a65621e504db3e5f586cf7cc22a798e9192048db004192048cf29bbd8de1e17545c070948444a367ccd54274b9a0c2330c1f10527065b5f88d058c304424190242338dae8c01255c2ca5f5b2c77cf57594d4c1dc54c2f3f2208c248c3ae0a4e682fe4d2b87890b6d888f0976146881f5e3746e4c702cf8069e1748c1838783f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-58e4573446a0277955433351cc1a2b0e2ac9b00d1eb98cbe4c40e1c8a62a77b824a27b332b569f1f3621869d986f0eb92c9c2617836508d3f95baf87e3d0cffb75c7aca285cad0105178973a69c93ec4a5b425f314aadd7b3e1c8e9a454659f466007aa0a649b71d45e63974a7ea86f0ba530aaa30145b2a6ecc5773381f61948547a075987913ac93e9c9b7e27719d00acf2caa241b655b19e45667d5c15cb99219baa5cb2df4dd5cc11717d1926157abc4dcb044bc9db5bc53a1e1098d75bcc7996545974102847e68ce244cf430f96c817359bc7623bfed3d59d4d55992f1cec388673b9929b07472dba0ac24521830ff93aeb87ca670c161adc95e72e80a618359667649ed51996b8902376ae1e4645095579caefdac5afaa8af0ce825f5d4b64a2b58d336071a30121990a979fde1447d753dbdd9d28c94eec41352b3e9714b6dd436d0fbf8ba49829c3e1b74d96fdaaeaee380ba0cd3c65e0ea98d7befdf4302789596674ea6bc497bad74d91018f79741f244cb8397319db67f7284ac85643bfb7a9243a35d47911701dd32af14dbaaee84286b207fa877a018527540f5937fe42b459c45c7548e0f52cf7d252729cdb2e0b7791d74d875c4cc07f2d43bc0f10aa3ca54a1e7803dcb84c8e627ea3ea9fafcb60a7d571d9cf30890b4cbe5c7d73fc31923dcab4e0860eb35d5e60177e1d413a091df294166fb7ea8d0ec", "1a4", "-58e4573446a0277955433351cc1a2b0e2ac9b00d1eb98cbe4c40e1c8a62a77b824a27b332b569f1f3621869d986f0eb92c9c2617836508d3f95baf87e3d0cffb75c7aca285cad0105178973a69c93ec4a5b425f314aadd7b3e1c8e9a454659f466007aa0a649b71d45e63974a7ea86f0ba530aaa30145b2a6ecc5773381f61948547a075987913ac93e9c9b7e27719d00acf2caa241b655b19e45667d5c15cb99219baa5cb2df4dd5cc11717d1926157abc4dcb044bc9db5bc53a1e1098d75bcc7996545974102847e68ce244cf430f96c817359bc7623bfed3d59d4d55992f1cec388673b9929b07472dba0ac24521830ff93aeb87ca670c161adc95e72e80a618359667649ed51996b8902376ae1e4645095579caefdac5afaa8af0ce825f5d4b64a2b58d336071a30121990a979fde1447d753dbdd9d28c94eec41352b3e9714b6dd436d0fbf8ba49829c3e1b74d96fdaaeaee380ba0cd3c65e0ea98d7befdf4302789596674ea6bc497bad74d91018f79741f244cb8397319db67f7284ac85643bfb7a9243a35d47911701dd32af14dbaaee84286b207fa877a018527540f5937fe42b459c45c7548e0f52cf7d252729cdb2e0b7791d74d875c4cc07f2d43bc0f10aa3ca54a1e7803dcb84c8e627ea3ea9fafcb60a7d571d9cf30890b4cbe5c7d73fc31923dcab4e0860eb35d5e60177e1d413a091df294166fb7ea8d0ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "404eb15f55912e856ae5778ef74696d9ec39e83f8596457136de5cbdf323540b5a3bdeb5bbec7d00c0f803d9db49c941b167b3afed663a78b5ffdec9a86f5f97d5b03d6529aaea37774470d1a3cfaa89092c3765f827bcf81127890bb40d115913cc2e3d86f761779b59adfe4cfe71fbc04062c6aa12351d80f32d54cff45e0a3da64b3fe0235fc0db28696bdf5b3079816142dcdd664a1e7c98b095c350f08f234dc7aa627e31e4dafbb66758d331e4f79cac1009dfad584cce17859d48e9be3dc4883db4ee0e7d81e777793001363b4183d6f3033e0ff24bbaf2269769685eefa99d0076befbc51f7eb2aa6a6c5dac2f2b424894f64f65b321ed295ce32e5e0c6b5687b2a3ea143dc5a0309c35d2805d76817d798c24c8994017f314cb06ca816493be515f1509d0b9d1781c0536c4554cc475cf2d1d4981f0d81827526850aaa0aeaa98fb622381e05626de68c58b01cc9be4229141d20e551e1c59ee16c0f9aa4d0e65661153e5f09f6ff0efe3fa621e67c8d3e9c5f44c89b17c72f4533aa94966f7b4eebe41be25c6a6ab7d9be85710cd016efb95e345ac7edef53b9c613cafb4c120e10c51cc7e0aeabe1aae508aab545801d893c584e886dda3823e473996a44665b87dd35029e9531dc88ab3c4891821c1334610f28474e41d74593355360a84bb86f903a8d98f14c11af97c461d0182e854708ceef6ebcec6ab8a74", "1a4", "404eb15f55912e856ae5778ef74696d9ec39e83f8596457136de5cbdf323540b5a3bdeb5bbec7d00c0f803d9db49c941b167b3afed663a78b5ffdec9a86f5f97d5b03d6529aaea37774470d1a3cfaa89092c3765f827bcf81127890bb40d115913cc2e3d86f761779b59adfe4cfe71fbc04062c6aa12351d80f32d54cff45e0a3da64b3fe0235fc0db28696bdf5b3079816142dcdd664a1e7c98b095c350f08f234dc7aa627e31e4dafbb66758d331e4f79cac1009dfad584cce17859d48e9be3dc4883db4ee0e7d81e777793001363b4183d6f3033e0ff24bbaf2269769685eefa99d0076befbc51f7eb2aa6a6c5dac2f2b424894f64f65b321ed295ce32e5e0c6b5687b2a3ea143dc5a0309c35d2805d76817d798c24c8994017f314cb06ca816493be515f1509d0b9d1781c0536c4554cc475cf2d1d4981f0d81827526850aaa0aeaa98fb622381e05626de68c58b01cc9be4229141d20e551e1c59ee16c0f9aa4d0e65661153e5f09f6ff0efe3fa621e67c8d3e9c5f44c89b17c72f4533aa94966f7b4eebe41be25c6a6ab7d9be85710cd016efb95e345ac7edef53b9c613cafb4c120e10c51cc7e0aeabe1aae508aab545801d893c584e886dda3823e473996a44665b87dd35029e9531dc88ab3c4891821c1334610f28474e41d74593355360a84bb86f903a8d98f14c11af97c461d0182e854708ceef6ebcec6ab8a74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "fc7145e08d0989e75905d1747f3faaaf304261c69ac3f55b4ee5dd6134b893b35d0c808ff68cba947b39f34b269540c372ef7f77015868ef03e3acfcab1134eeb56fb11151df2261df26e8bf311200a4b1ff8780081dc5ad8a2ce7db28426b1352a41f0e910efd4d2b3017144b13f5dead67c11c900b68d6d614e290d3c5e2da170f975e712fae17c348ca2f6e16ba88311a493d1a32ea6ca4c4a3c5ac5bfb148f9b3a8d0cd692220fc8e8278ac6070ba9c39205bdeaa647b3eb5f88fb9961c173264e683b217c11a954ed56b3e440f58d2486504a2b623a39fea812fb0c1907679f0e8772e614cbeb8a29accd3f934f3575b1b1d241479aaac132124f3fb8573e3d935291283df7ea5502fd3b9082848ad827a614f6602ad6f84fe87377070a0a7d13b8d5fe85df1e64c46bd310d38852633b9dab9425f2d63e12f70c641308b97e162a6ae1bab5e5f385a46e479de4958622e032ccbd3429c509e568092445a6e4c08549cb618f13345b5dc44164a34361ec7355a24cb7b467d929ce6f33e1bf752340b08baf0353b532999cf9c56507d1c91df859d16543b431b47ba2c4b33697b3316d0971423c04ef671ceefec1be97d5fad67cca54cb6790e8156fd0c6d5d04b2dda0ce0f89633ffd38e07cb88606d922d43e5335d640d4fd0eade9e54ea759825eb4172df39d6c36878fccd5ab620924ca2f793e11d950913a441ce20", "3c", "fc7145e08d0989e75905d1747f3faaaf304261c69ac3f55b4ee5dd6134b893b35d0c808ff68cba947b39f34b269540c372ef7f77015868ef03e3acfcab1134eeb56fb11151df2261df26e8bf311200a4b1ff8780081dc5ad8a2ce7db28426b1352a41f0e910efd4d2b3017144b13f5dead67c11c900b68d6d614e290d3c5e2da170f975e712fae17c348ca2f6e16ba88311a493d1a32ea6ca4c4a3c5ac5bfb148f9b3a8d0cd692220fc8e8278ac6070ba9c39205bdeaa647b3eb5f88fb9961c173264e683b217c11a954ed56b3e440f58d2486504a2b623a39fea812fb0c1907679f0e8772e614cbeb8a29accd3f934f3575b1b1d241479aaac132124f3fb8573e3d935291283df7ea5502fd3b9082848ad827a614f6602ad6f84fe87377070a0a7d13b8d5fe85df1e64c46bd310d38852633b9dab9425f2d63e12f70c641308b97e162a6ae1bab5e5f385a46e479de4958622e032ccbd3429c509e568092445a6e4c08549cb618f13345b5dc44164a34361ec7355a24cb7b467d929ce6f33e1bf752340b08baf0353b532999cf9c56507d1c91df859d16543b431b47ba2c4b33697b3316d0971423c04ef671ceefec1be97d5fad67cca54cb6790e8156fd0c6d5d04b2dda0ce0f89633ffd38e07cb88606d922d43e5335d640d4fd0eade9e54ea759825eb4172df39d6c36878fccd5ab620924ca2f793e11d950913a441ce20000000000000000", .None}, + {.Shl, "b7410da582654ca77e87fa13772681f7e354459262d3a5e8e0a8cc5ed913b701a9b67bd4a240f20d5e5374b0d902d853390cee5d6938de22736e80adb9bce50403b7ae99e51686511c236ac102f14d0d8e5d5b30bf3272f4a87f3b8a8c685091c0bf7ab8e3404746e99bcf9555371d41bf7a4b3b979b1a707dfc97b4d14effa3c38282c1921c2e56258f5b2c29c504187cb915ca1fe8bcc129d750f6d826735233cebf7b4d6304482881912593096550583026d7a4c79cb0990dc92fc8c673ff01656dbd0e4ca56062a04a4a44c41db349baa57a13255da6b4d736d1fbc734c9d3aa08e67a28d129db0999c3bbc0d6b471f6667aa6ecff45ad8932273d018d86d718e9eec9593d3e1926fdd160c35ed577914da419b981900556a47a04635a2553c7ca759ff723809634f091dc98a341cbd66d099be2c51b6b29fc95fd9972caef3d57d2d08e2d4f975ec52e659f3b30b9534f0c83ce716f8e7e3d42e0b6dada2c88268590a5374cbbc54f16e93c21c9f4f117890f7ab008309691dfaee67ddd655150f37bdd072cb67cb2dcc6bb746cf998cf2c2d12d992133b1baa98776c081b455577180631efe15e00433200b684f4ca1a3c7d143c20b63ec4731ce8ceffb73a75098d9887ee497fd94e6aaa237f914a6db4c8deeffecae4f582e1006004a37b6ef051cfa7fa7745df16ac82cbc89d6d739b80f75ec506195a65279c6583", "3c", "b7410da582654ca77e87fa13772681f7e354459262d3a5e8e0a8cc5ed913b701a9b67bd4a240f20d5e5374b0d902d853390cee5d6938de22736e80adb9bce50403b7ae99e51686511c236ac102f14d0d8e5d5b30bf3272f4a87f3b8a8c685091c0bf7ab8e3404746e99bcf9555371d41bf7a4b3b979b1a707dfc97b4d14effa3c38282c1921c2e56258f5b2c29c504187cb915ca1fe8bcc129d750f6d826735233cebf7b4d6304482881912593096550583026d7a4c79cb0990dc92fc8c673ff01656dbd0e4ca56062a04a4a44c41db349baa57a13255da6b4d736d1fbc734c9d3aa08e67a28d129db0999c3bbc0d6b471f6667aa6ecff45ad8932273d018d86d718e9eec9593d3e1926fdd160c35ed577914da419b981900556a47a04635a2553c7ca759ff723809634f091dc98a341cbd66d099be2c51b6b29fc95fd9972caef3d57d2d08e2d4f975ec52e659f3b30b9534f0c83ce716f8e7e3d42e0b6dada2c88268590a5374cbbc54f16e93c21c9f4f117890f7ab008309691dfaee67ddd655150f37bdd072cb67cb2dcc6bb746cf998cf2c2d12d992133b1baa98776c081b455577180631efe15e00433200b684f4ca1a3c7d143c20b63ec4731ce8ceffb73a75098d9887ee497fd94e6aaa237f914a6db4c8deeffecae4f582e1006004a37b6ef051cfa7fa7745df16ac82cbc89d6d739b80f75ec506195a65279c6583000000000000000", .None}, + {.Shl, "3ce2a4183e93f604a6d7be710ef572f745f5640ba56c7dcc897e594549c8e8d17ff0b341866a90367f2624851088ffd984847dad9da6656b7c6e66730c8a2ea55564ab25cb3c46f18a972a29da97e89c09205ce4155480c0a7cfbe45d501d52564c73669703215edf5b2092b500174abad07d089b2edadc82c6ce2e4773626b364a1d03b81e6e2ad0c6e94efcd6ebf1388471913c4ab7d16ee0dbd8836cc266170742dab168db5135e916f96742705da80ef6f936a992534718f222fc5f50a6151a961da11988a9fb7782fd05fa701c02d467b5aa569240ae92e9091dbf48dad894901b9b9b420e8f4a561b7481796fea154bbae564b10586f0448f654e6d9d99097b25c6eaef48f5ee72d30f810bf6330062aa6705383ba66d1b5cc81fe5d3f15bf0142aa55c4a1c05cc33e47fbb3bbe4e2ea2c6d0a06eb04a05efbb3dea6936ed470c3d0ebdd8951c5065a1cfba2b9359317cdee176ceb2cfcfbad89884bcec4afee6c56169b3bb37d7309fb42356feb2fe8acd3cbaffbde5ef65543c5fcb9b87ae134b9b747e9d23b669a627be2df3977979a963789beb759a9523595343b31429872f0eddf8bf7849b988d908f5262f39d8d821a1e56d5342aae2fda6355e8b9c908b1ba68c28f002fc2bc375fb09c6664c1eb1da352c89856752679ce048f887e04d15ec8bde53a768c34577fb128b4ebbd7ac8aee394c0e9ea211b0242", "168", "3ce2a4183e93f604a6d7be710ef572f745f5640ba56c7dcc897e594549c8e8d17ff0b341866a90367f2624851088ffd984847dad9da6656b7c6e66730c8a2ea55564ab25cb3c46f18a972a29da97e89c09205ce4155480c0a7cfbe45d501d52564c73669703215edf5b2092b500174abad07d089b2edadc82c6ce2e4773626b364a1d03b81e6e2ad0c6e94efcd6ebf1388471913c4ab7d16ee0dbd8836cc266170742dab168db5135e916f96742705da80ef6f936a992534718f222fc5f50a6151a961da11988a9fb7782fd05fa701c02d467b5aa569240ae92e9091dbf48dad894901b9b9b420e8f4a561b7481796fea154bbae564b10586f0448f654e6d9d99097b25c6eaef48f5ee72d30f810bf6330062aa6705383ba66d1b5cc81fe5d3f15bf0142aa55c4a1c05cc33e47fbb3bbe4e2ea2c6d0a06eb04a05efbb3dea6936ed470c3d0ebdd8951c5065a1cfba2b9359317cdee176ceb2cfcfbad89884bcec4afee6c56169b3bb37d7309fb42356feb2fe8acd3cbaffbde5ef65543c5fcb9b87ae134b9b747e9d23b669a627be2df3977979a963789beb759a9523595343b31429872f0eddf8bf7849b988d908f5262f39d8d821a1e56d5342aae2fda6355e8b9c908b1ba68c28f002fc2bc375fb09c6664c1eb1da352c89856752679ce048f887e04d15ec8bde53a768c34577fb128b4ebbd7ac8aee394c0e9ea211b0242000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b263ee20a258b47f4d26d623abc632aa0b793931cd3ab3c14d215862c6c2ae45322b8fb2b3cacac5d0df19e8f65d1a4385fab2dbf4e229b21c65172ed9d64560dd4bd12a03c8effc5bf6d744cf0441aa4ac04a5d640195319dce0fabebf2e76380645b18e3efbcdb5a4830505fe477f3a219cb8b912ffaf00a15d9d7faec62207104476985c7a0881f733328a4c0644e9e87fa1de37f155dda9ee9471518588c75a974a12e15c38f273fca9c269fe28eec63ff38e21c12c89e16b6886dd30dca0a21bee72bbd0612208db3ea56b95ae364e99257ce669e516df16db0aa6dfd2f0d7e60dd9edcb4b623ddf4931d1d2ee5126ac40768a62e652de0b9177c34419bbc9a3fb4c374055c1f77f4854142b77a9d9f91eed8e40d6ba5e6477fbcee815ef9f88ae3c8264462226fdd11989a8ace1f630019a65e6cf62c4c39c3019df95203db24b7930e95d6e4683264ae4169752bb2ddfae53eb8817f273e7b182bca5efe9d567739051310f34638dc304c25340ea79c1788ae08052b3b1a2850c852ccf0820ea2c450e9f98d4f1cce82398d05231b055a0e0cd99afe42e7c3800a71dd58f2d887e476f8f4466df994826e1cff6c5c7da5603bb97ed395b968b5701eaba40c76972d9ea065b9a3e45539fb25aa29b2aebec07307a89c68177da008eff4481e39e891dcfbc0c867a4276f060890177aa3a071ef0719168f57104ffaddb6", "258", "-b263ee20a258b47f4d26d623abc632aa0b793931cd3ab3c14d215862c6c2ae45322b8fb2b3cacac5d0df19e8f65d1a4385fab2dbf4e229b21c65172ed9d64560dd4bd12a03c8effc5bf6d744cf0441aa4ac04a5d640195319dce0fabebf2e76380645b18e3efbcdb5a4830505fe477f3a219cb8b912ffaf00a15d9d7faec62207104476985c7a0881f733328a4c0644e9e87fa1de37f155dda9ee9471518588c75a974a12e15c38f273fca9c269fe28eec63ff38e21c12c89e16b6886dd30dca0a21bee72bbd0612208db3ea56b95ae364e99257ce669e516df16db0aa6dfd2f0d7e60dd9edcb4b623ddf4931d1d2ee5126ac40768a62e652de0b9177c34419bbc9a3fb4c374055c1f77f4854142b77a9d9f91eed8e40d6ba5e6477fbcee815ef9f88ae3c8264462226fdd11989a8ace1f630019a65e6cf62c4c39c3019df95203db24b7930e95d6e4683264ae4169752bb2ddfae53eb8817f273e7b182bca5efe9d567739051310f34638dc304c25340ea79c1788ae08052b3b1a2850c852ccf0820ea2c450e9f98d4f1cce82398d05231b055a0e0cd99afe42e7c3800a71dd58f2d887e476f8f4466df994826e1cff6c5c7da5603bb97ed395b968b5701eaba40c76972d9ea065b9a3e45539fb25aa29b2aebec07307a89c68177da008eff4481e39e891dcfbc0c867a4276f060890177aa3a071ef0719168f57104ffaddb6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "e2710dc2c534ccd4890cb9ff74ce87020521a1549bad4a9c0b9e53dff76bcb9b137c7d901d2c8852e66f13324f8f757875fa203405f5f32f9f1740a9d5c0f03577549f18b5d077cb6dd0f13cdb72ff414bc962e792feff54f22ada1b6dcf223b4eb8bb4d82c80b1d16dff8fcc71630402a6d066883921e8defd9527862643bf26e32d5c1b96decccbaaafa3c5de8443454d514fc28900a9a26d2ea8eeda5565098a1766645f160c50e5667bc271d89d0de4423c71086046c8a5f9f1530360c336f5f0a517b2b98d168430ee48a0ff7231c9f0382c769f3e218fa734a7471e847b6c9601f074c0088dca83cc10dfb2d7c3803b66f68e29fe365d8d28a3f3c6efd74b3adc9d577ab295f054c6baac42da44038381c0d5cdb89e8d7ce28b9062222b97fdda44799310aa6a9918076700fce4ce9cea91269b15624993233d9af54e513eaace6507c27e01313bd4bc54fd590e41ba9469116d514734df96499df36fee5272eda529be99d4b60b9832c59db224590fef71f37c41487e63fab2902f206a57ef30e8e2cc2fe8bc2bf725a6639cfd2ecd597e51b70c7a124a5f069ab1814510f3bec75e515484567af80032038b0094b370e4e06e1f261fe0bb0c129fb91354803b8d827cfbb7a2de1d7a65accaba345ada2781cd6f51a12c95cdab964f4a31d5c7cc38c5db0847027b33430c33fa53dcaffbf53911899a2578bf5258c61", "21c", "e2710dc2c534ccd4890cb9ff74ce87020521a1549bad4a9c0b9e53dff76bcb9b137c7d901d2c8852e66f13324f8f757875fa203405f5f32f9f1740a9d5c0f03577549f18b5d077cb6dd0f13cdb72ff414bc962e792feff54f22ada1b6dcf223b4eb8bb4d82c80b1d16dff8fcc71630402a6d066883921e8defd9527862643bf26e32d5c1b96decccbaaafa3c5de8443454d514fc28900a9a26d2ea8eeda5565098a1766645f160c50e5667bc271d89d0de4423c71086046c8a5f9f1530360c336f5f0a517b2b98d168430ee48a0ff7231c9f0382c769f3e218fa734a7471e847b6c9601f074c0088dca83cc10dfb2d7c3803b66f68e29fe365d8d28a3f3c6efd74b3adc9d577ab295f054c6baac42da44038381c0d5cdb89e8d7ce28b9062222b97fdda44799310aa6a9918076700fce4ce9cea91269b15624993233d9af54e513eaace6507c27e01313bd4bc54fd590e41ba9469116d514734df96499df36fee5272eda529be99d4b60b9832c59db224590fef71f37c41487e63fab2902f206a57ef30e8e2cc2fe8bc2bf725a6639cfd2ecd597e51b70c7a124a5f069ab1814510f3bec75e515484567af80032038b0094b370e4e06e1f261fe0bb0c129fb91354803b8d827cfbb7a2de1d7a65accaba345ada2781cd6f51a12c95cdab964f4a31d5c7cc38c5db0847027b33430c33fa53dcaffbf53911899a2578bf5258c61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-a3f4ba2b570125e7ac9c9e49d84ada02aba7ee4805a79602e23585dd1559f5200468e34c48032b97c3f93759c1d2eb77f029774ab8bd59735aa0d05c0d3197fec355d3cef263f2c76cc3e6f72d36cac2a469aea74ef6f47d76bd6b4a593376968f234de6b46659790b23f9e3608cbf6e6ab4323fe86c1b36a4244f55f7c56050ebc30728745a66287d30af967cb49858593185722da85cd2a80f330e886cfb752b467f37792141162b028a378f4c0b057cf6c6cd62bf551b830f983801dd75d26ce1c1c312e097e80b650e088241588b6ee444807261ddf692a8608b2320d17507d81c239c9f4a841b10cd8b660a9bea15a15db96c28f0ec4859a06eb501abacdf44c5cbf50892e67c8cf29277d3cd5393870f569168d732a29eefea7989c18907780af99ae8e362e91072d5b91d10aeea1a9d139a51d795eedeff65ae16b5391dec668fdb2258a31e1b4f5fcc4b5c7665c386b764947e069e64254fcb67cf000e8b0126ebf4b8a0c49f6c9cef8a49c1daa45a4c70dda74638e303a4bd8fbc9befe16bfce8fd9622377eb3ef62aeea91d412d6e8d0a9e3613438f66500627280ba5828587ff7c9cc9d45008b8e7ec4ba3b3b52f975283ce1d14aa94db8ff7c36d8c0e5ed0530e8e24d5814da9a0fdef5ddf043b3134bd2491f1ea36eecee32513e01da406967dc1f4a65580de1fbb8a8960f6dcd7d4392c4fb3f8ce02cccf439", "1a4", "-a3f4ba2b570125e7ac9c9e49d84ada02aba7ee4805a79602e23585dd1559f5200468e34c48032b97c3f93759c1d2eb77f029774ab8bd59735aa0d05c0d3197fec355d3cef263f2c76cc3e6f72d36cac2a469aea74ef6f47d76bd6b4a593376968f234de6b46659790b23f9e3608cbf6e6ab4323fe86c1b36a4244f55f7c56050ebc30728745a66287d30af967cb49858593185722da85cd2a80f330e886cfb752b467f37792141162b028a378f4c0b057cf6c6cd62bf551b830f983801dd75d26ce1c1c312e097e80b650e088241588b6ee444807261ddf692a8608b2320d17507d81c239c9f4a841b10cd8b660a9bea15a15db96c28f0ec4859a06eb501abacdf44c5cbf50892e67c8cf29277d3cd5393870f569168d732a29eefea7989c18907780af99ae8e362e91072d5b91d10aeea1a9d139a51d795eedeff65ae16b5391dec668fdb2258a31e1b4f5fcc4b5c7665c386b764947e069e64254fcb67cf000e8b0126ebf4b8a0c49f6c9cef8a49c1daa45a4c70dda74638e303a4bd8fbc9befe16bfce8fd9622377eb3ef62aeea91d412d6e8d0a9e3613438f66500627280ba5828587ff7c9cc9d45008b8e7ec4ba3b3b52f975283ce1d14aa94db8ff7c36d8c0e5ed0530e8e24d5814da9a0fdef5ddf043b3134bd2491f1ea36eecee32513e01da406967dc1f4a65580de1fbb8a8960f6dcd7d4392c4fb3f8ce02cccf439000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e7aa989af2ccceed6813ce892084d60516efb4f615cf50748b8b522e4d5c7996ba464eaba550e464e655dc7f1b2199440cf47fcaa1ecd5e880399d556f181c0b3db4691211a401aeeca89119338b6f73c731517f0f794bc805e1126a46954fc9305a3be0b91fdc132a35c77bd6c2b8301d160810e8378d17df8ac2d94865e3768f7c4986dd14d90528f9ec53e2bf7e6baea6ffcbe096e67f55589e7003be5ff89d58fea48c3f8adb3592d3567d7854280960723450238bcd99b3aefa2bf42ab6935f7a037212b00c61dda4f193189f22d657643f39ec9356062d1e9e2a4dc3122bc16436db3ad51d1658223b65674dcdde0f60ee7fba9c2fb0c1bfba3bbef930e0e0763cc7db5a6936b6ab69d79cb6059bb3080e99912d2f1fe9abeffce58231d4da797cc26b702b7643a4e538d5c6bc9987a6933243c05fe10cdb40c2a88a75a4342a74a55466dae1c4e69cd80ad7515dcf3314818961cd643ac2364405b0c36ae8ebb0f8d00150a9ac450424f263bb40b47e1fcf101c4a28a7a7a7dad06550eb2a2a69a3f065c25a7f051cc1a16899f62e188c3a4e7d2300077a753580edb03f4b9a33ab20dd312717c8d1c5780cc9291f91655517a5c9df89d1ad031c76c980eeea510f377e1c5afa08cb397cdf23f38bec579093300686d97c13999f88c0d0b0a1d45d27ea8109301ac4cbfcb87e2c50bba2358029c40894310c4fb3f480", "78", "-e7aa989af2ccceed6813ce892084d60516efb4f615cf50748b8b522e4d5c7996ba464eaba550e464e655dc7f1b2199440cf47fcaa1ecd5e880399d556f181c0b3db4691211a401aeeca89119338b6f73c731517f0f794bc805e1126a46954fc9305a3be0b91fdc132a35c77bd6c2b8301d160810e8378d17df8ac2d94865e3768f7c4986dd14d90528f9ec53e2bf7e6baea6ffcbe096e67f55589e7003be5ff89d58fea48c3f8adb3592d3567d7854280960723450238bcd99b3aefa2bf42ab6935f7a037212b00c61dda4f193189f22d657643f39ec9356062d1e9e2a4dc3122bc16436db3ad51d1658223b65674dcdde0f60ee7fba9c2fb0c1bfba3bbef930e0e0763cc7db5a6936b6ab69d79cb6059bb3080e99912d2f1fe9abeffce58231d4da797cc26b702b7643a4e538d5c6bc9987a6933243c05fe10cdb40c2a88a75a4342a74a55466dae1c4e69cd80ad7515dcf3314818961cd643ac2364405b0c36ae8ebb0f8d00150a9ac450424f263bb40b47e1fcf101c4a28a7a7a7dad06550eb2a2a69a3f065c25a7f051cc1a16899f62e188c3a4e7d2300077a753580edb03f4b9a33ab20dd312717c8d1c5780cc9291f91655517a5c9df89d1ad031c76c980eeea510f377e1c5afa08cb397cdf23f38bec579093300686d97c13999f88c0d0b0a1d45d27ea8109301ac4cbfcb87e2c50bba2358029c40894310c4fb3f480000000000000000000000000000000", .None}, + {.Shl, "7f4e326de1a8bf6277dc414a09e85bf86d054731894070b2d79aa8cd13dfef4b405eff606431c0a45ba20c60354b4387490da7143526f252d494f0fc3d9a3261c47ac17de585f7250278ba180f942ba9ad321a2b81ec62e5f39e153b4e64e4791cc16b8037a7a9484027f62f8863faf4f9d51a7a95455c65dfd1f82c55ab750fbb9818c1a3fe8b81381ff023d71579f6d0b2139746cc3ebcf75e58d9172bfda098620dbd33847d1c828f01b8ddee4585d37ceb8c180589f8bbed3b3ccba5b1d45d2dd0189b5699ab5acc70ec2eb33348e18ef1077b68e479036847c9df8d99b15d6c36e565f467d087047a3687ba35d07cfd4263b10133177a8455b79b286f7db73c650ada8b089230c5c9c415b63f11e42f6ea3d26dedb2142184b6c7b33ee092c3031acb09ea4ebcb3826ba5aadbbeb88407d3648c73d695ea5f2cd14fcaef17bc2c9a8775a569c1efe0e61dc7e451319575aa584125fe205a71f333291fee5f936c43c4424fe1616da0c02a34b4ed8dea68aa8608e67f43032c1d1628ab23dd9287941a4779ac011ddb20969baa48770d020a001a6beea181abc572bd0a1208e1a473cfcad479270354190c675624e92d2a98588bbf39c5dff7dd61eae700d2fc142dcd8af7073344201f14b0cbd3fa028624638183ca07319d5fd5fc0e8bda4118478da5ac77b4c193ee8d77c9f61d24890f5c802153b155b7a9f2e298bb", "3c", "7f4e326de1a8bf6277dc414a09e85bf86d054731894070b2d79aa8cd13dfef4b405eff606431c0a45ba20c60354b4387490da7143526f252d494f0fc3d9a3261c47ac17de585f7250278ba180f942ba9ad321a2b81ec62e5f39e153b4e64e4791cc16b8037a7a9484027f62f8863faf4f9d51a7a95455c65dfd1f82c55ab750fbb9818c1a3fe8b81381ff023d71579f6d0b2139746cc3ebcf75e58d9172bfda098620dbd33847d1c828f01b8ddee4585d37ceb8c180589f8bbed3b3ccba5b1d45d2dd0189b5699ab5acc70ec2eb33348e18ef1077b68e479036847c9df8d99b15d6c36e565f467d087047a3687ba35d07cfd4263b10133177a8455b79b286f7db73c650ada8b089230c5c9c415b63f11e42f6ea3d26dedb2142184b6c7b33ee092c3031acb09ea4ebcb3826ba5aadbbeb88407d3648c73d695ea5f2cd14fcaef17bc2c9a8775a569c1efe0e61dc7e451319575aa584125fe205a71f333291fee5f936c43c4424fe1616da0c02a34b4ed8dea68aa8608e67f43032c1d1628ab23dd9287941a4779ac011ddb20969baa48770d020a001a6beea181abc572bd0a1208e1a473cfcad479270354190c675624e92d2a98588bbf39c5dff7dd61eae700d2fc142dcd8af7073344201f14b0cbd3fa028624638183ca07319d5fd5fc0e8bda4118478da5ac77b4c193ee8d77c9f61d24890f5c802153b155b7a9f2e298bb000000000000000", .None}, + {.Shl, "be29661bbf56d2720bf20cd3fa5240c399436500bad6a1d240fa7b81d9672c1e3181447f2413d5c8a5738d7afa84d2c48dd67fd19333655d0c6d1ffeff5f9252eec7cc71f888064cbc1474df3894be378f18fb5769440680c4b20a3dfcdd749db9a82b2b8b621f29c2e5a26a6d55afb7c0738269cbd29e63d64dac767378a8de6978d3d44558a60ad48948cf05cc57b01942ce2a9f91e74420e4dcaae8935d7ba7c320122df5c1b7e7e40a600cee7809dd9f0543eee8bdfb6cf4829913199b74703b89497384f11aa7fc000b65c97180d914c20cdab5be6ecf939141323bbbb53e82132771d6394e0e1b7bb5dbf233d4c6ea2572a9d147172a0091150f80b3982171e0701998306fd2d4b8552d8c36fa7620b53f4a4806e9ff906ef161a1778f1b908494227f0c791aa4c7c7caa6fd9d0ce40a1af8dd85867ec9f330655d850599244422fe885a6bdd16cdc75948d22d4f768e8ae14007a4f9769222937306b2e559ddc6464f7156632cf4f9f7352d7dd84200b581cfdeb1ede740a3264a67869f40ed721f523c8509c014f861457c158ec9e8fb4a34412499f46dc94f151bef45b61c4f15e22d886425b067d62379d63832d0db0fe4d3a7b374fdbbcdccdc6284c495ff5dd29fe4ad6e7147dc0ea6974fa17e2f8c67450bd908a3cafd6053894532d15a2f9c7d4862cb8da7c044f709435dccd75d8208632f8c4524c081d7f3", "21c", "be29661bbf56d2720bf20cd3fa5240c399436500bad6a1d240fa7b81d9672c1e3181447f2413d5c8a5738d7afa84d2c48dd67fd19333655d0c6d1ffeff5f9252eec7cc71f888064cbc1474df3894be378f18fb5769440680c4b20a3dfcdd749db9a82b2b8b621f29c2e5a26a6d55afb7c0738269cbd29e63d64dac767378a8de6978d3d44558a60ad48948cf05cc57b01942ce2a9f91e74420e4dcaae8935d7ba7c320122df5c1b7e7e40a600cee7809dd9f0543eee8bdfb6cf4829913199b74703b89497384f11aa7fc000b65c97180d914c20cdab5be6ecf939141323bbbb53e82132771d6394e0e1b7bb5dbf233d4c6ea2572a9d147172a0091150f80b3982171e0701998306fd2d4b8552d8c36fa7620b53f4a4806e9ff906ef161a1778f1b908494227f0c791aa4c7c7caa6fd9d0ce40a1af8dd85867ec9f330655d850599244422fe885a6bdd16cdc75948d22d4f768e8ae14007a4f9769222937306b2e559ddc6464f7156632cf4f9f7352d7dd84200b581cfdeb1ede740a3264a67869f40ed721f523c8509c014f861457c158ec9e8fb4a34412499f46dc94f151bef45b61c4f15e22d886425b067d62379d63832d0db0fe4d3a7b374fdbbcdccdc6284c495ff5dd29fe4ad6e7147dc0ea6974fa17e2f8c67450bd908a3cafd6053894532d15a2f9c7d4862cb8da7c044f709435dccd75d8208632f8c4524c081d7f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-ab2664524db61d43bf656a0f4e1771210c6ddd38497e3d8b2f1c9f1ca847c8cf0d765926fda51eb2fba2cf99be0c50d265a479c61a629d2e3968b7169e1685ca1aa69f67761302e633bb42ac5a77b6fe562224f7afb5b55888a7378239652603e4b708e5902c45bd38f3afe6240eab5b64b76c09a059cbf78e1f45a7cfc16b83e2a97e3f373d0e838e1d00b2ea9199bf4a01906993ff18ba1190727dcd2560ea5ad2d8a1c1f64c1b3de7de98b7d17c87f164730eaa25d6b7270b7007346226604c5b5c6aa83da371b59b6dc3ecd849e6926a42831104ad9008553203ce780397036ccc74a501efe9a3a6aaebfaf63c0d5958136eeae062e4a1fff9fdb823a032ac8a32ea736c216096f638d99684bf0005aa2f5c3284c5e5417e159db30c52f3ef691be7fe37511f999093a86e8bf8281aa7b72d785ed9dccfbf15393ab86188724371d370aa2134d984f47110db74e232983c1396047d3d925545e47b3bc4c7f8d5f409c398bb6ca32a896ba2494f7ed382b8f496f61d6ef4039aabf5c0f7253cf9620c3c50a9537ba3b4bd4b865fb78bf4b2da849cb36ed5e0969a5b2ce153a8aa305d399cad402a757b550d86ee361240c9d289068d59796061451c011bee8bd50e78121a5d0b66920e6fefccc95ac3599a4965431410a0cd446b41abb8ec6479fa85c75a3067991dd37721b76f90df784ff3c854c512d19c9bb0f528301f", "168", "-ab2664524db61d43bf656a0f4e1771210c6ddd38497e3d8b2f1c9f1ca847c8cf0d765926fda51eb2fba2cf99be0c50d265a479c61a629d2e3968b7169e1685ca1aa69f67761302e633bb42ac5a77b6fe562224f7afb5b55888a7378239652603e4b708e5902c45bd38f3afe6240eab5b64b76c09a059cbf78e1f45a7cfc16b83e2a97e3f373d0e838e1d00b2ea9199bf4a01906993ff18ba1190727dcd2560ea5ad2d8a1c1f64c1b3de7de98b7d17c87f164730eaa25d6b7270b7007346226604c5b5c6aa83da371b59b6dc3ecd849e6926a42831104ad9008553203ce780397036ccc74a501efe9a3a6aaebfaf63c0d5958136eeae062e4a1fff9fdb823a032ac8a32ea736c216096f638d99684bf0005aa2f5c3284c5e5417e159db30c52f3ef691be7fe37511f999093a86e8bf8281aa7b72d785ed9dccfbf15393ab86188724371d370aa2134d984f47110db74e232983c1396047d3d925545e47b3bc4c7f8d5f409c398bb6ca32a896ba2494f7ed382b8f496f61d6ef4039aabf5c0f7253cf9620c3c50a9537ba3b4bd4b865fb78bf4b2da849cb36ed5e0969a5b2ce153a8aa305d399cad402a757b550d86ee361240c9d289068d59796061451c011bee8bd50e78121a5d0b66920e6fefccc95ac3599a4965431410a0cd446b41abb8ec6479fa85c75a3067991dd37721b76f90df784ff3c854c512d19c9bb0f528301f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-dfea519f2cec6536e0b664be1041648f9d02fd9bfaf9c831219297826462d26285e17a9e62894783fd9a10f37c7c519d15beb4d886d816847f0a7611b860cddcdf9b0c932d343f45b87d86423c8669a12063f1415536a6e1fc4d319b13f9cf89d965ebdc5078c681212b663f2df4daec93c29a1fea9ad691f478edf62aa0349e44f98b868bcb415a4415e47e04cd4ae30c12084e658fdf74fb6280942c85633586daf14fc57f8baad64be5321afa0fbc01553ada66a63e974d7ab686607de14b5b13ca86d4d8ed63aa24ce73cc61672c07473d0bf21bc0ccc6515fedb4baf5e8e5d21ac883e2fe0ac7b7a32295401dbab87f4727640f537bb60aea701f064c02405b2259ee69c6364436185f19cb8e0a87ee4dd20997cfdd8d653e95b2638530e3abd5335984ee627c4364b363688e8530cd6e5c78e9ec1a34f58b4498f0649b06c7559c501bca5b9c22e3bf5e619a60789271deb83e6cc0486205414d9b6f3461e475e60e42f79a2ed16ecd64372e121cfcd3d5f5a351aef4b0b91f3b75576358d15ac743a98dfe53a6d620e7f49b3c9ce928642d6f68b69b3782711d423514568ecd30c23c7b5118ee603a54f33784b37374d5e1712d0255479b2a0176ecf8da1928231d87a71ea302c7bff15f33486b9187bdc784469554351f77b6d6b1cd0bb012aa64982a8a08874e5b66842c1c10d00cfb3f49c41fd6c452447134aef9", "168", "-dfea519f2cec6536e0b664be1041648f9d02fd9bfaf9c831219297826462d26285e17a9e62894783fd9a10f37c7c519d15beb4d886d816847f0a7611b860cddcdf9b0c932d343f45b87d86423c8669a12063f1415536a6e1fc4d319b13f9cf89d965ebdc5078c681212b663f2df4daec93c29a1fea9ad691f478edf62aa0349e44f98b868bcb415a4415e47e04cd4ae30c12084e658fdf74fb6280942c85633586daf14fc57f8baad64be5321afa0fbc01553ada66a63e974d7ab686607de14b5b13ca86d4d8ed63aa24ce73cc61672c07473d0bf21bc0ccc6515fedb4baf5e8e5d21ac883e2fe0ac7b7a32295401dbab87f4727640f537bb60aea701f064c02405b2259ee69c6364436185f19cb8e0a87ee4dd20997cfdd8d653e95b2638530e3abd5335984ee627c4364b363688e8530cd6e5c78e9ec1a34f58b4498f0649b06c7559c501bca5b9c22e3bf5e619a60789271deb83e6cc0486205414d9b6f3461e475e60e42f79a2ed16ecd64372e121cfcd3d5f5a351aef4b0b91f3b75576358d15ac743a98dfe53a6d620e7f49b3c9ce928642d6f68b69b3782711d423514568ecd30c23c7b5118ee603a54f33784b37374d5e1712d0255479b2a0176ecf8da1928231d87a71ea302c7bff15f33486b9187bdc784469554351f77b6d6b1cd0bb012aa64982a8a08874e5b66842c1c10d00cfb3f49c41fd6c452447134aef9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "d539e743e6db13240d326142f2a71d61c8c8da794bb0b267e124bbec247a355c70813f61e290ab2a0c2e5ab52a2392680ce99dde2b5ccdf6a012f489ee6165ea5c6bffd2b98f0fc606de1a6f33772f635be48be6f5e8486ed1de14083d34417ae78405d16eb7eee2f0d45b7d3ba64b42470570ffe9cf6e41e8106659a38094fad3845c01d61b20c552f4445d59f8b35baf17f95dbf1ded8c34b12803330098421cc6527669fc3278c0e93ffa3e98237980050c7d5485e6ef3b0856b9cb9573e3926f00bf9c8f85185c07e121debea4b75fed1d383d08581561b6e78b62d693e92ff45e01f2023b0cbf7182e1bd349f47afb70a95d371b6b882dad36af6132c4eb8a16e3e800cd3f1a872bc00a8054af03db1b2bf7e06c67733c456bc1a5216c49985f2a9c27d7a9f2ad8a6857db6d49a767ef88b2298771a20f50fc307dd54788e2a9bf0f87bdcfa9c764fc91adeec4087e2c56c2e9bbc2822453b99c32fc0ed90b32de75a1d1270ab8b40b937bb5267b0f8f2c8468a87cdc9632297bb63e076a51493d4da1f72c9d195cb5cc3d9eb64991a0d6070ab0d0ad9cda74e23c8319d6c57311999f66cfcda446da2e472d46bb6b2422df25fd4e082653491e52c3160f7f2946f3182f6ebedacac38b3b892ea060f683ab06d320329d1277e3763aab215a84901fff2c670f8d8ef1afc2fa15442e02c17fcc574906c98bd7fd467422a", "21c", "d539e743e6db13240d326142f2a71d61c8c8da794bb0b267e124bbec247a355c70813f61e290ab2a0c2e5ab52a2392680ce99dde2b5ccdf6a012f489ee6165ea5c6bffd2b98f0fc606de1a6f33772f635be48be6f5e8486ed1de14083d34417ae78405d16eb7eee2f0d45b7d3ba64b42470570ffe9cf6e41e8106659a38094fad3845c01d61b20c552f4445d59f8b35baf17f95dbf1ded8c34b12803330098421cc6527669fc3278c0e93ffa3e98237980050c7d5485e6ef3b0856b9cb9573e3926f00bf9c8f85185c07e121debea4b75fed1d383d08581561b6e78b62d693e92ff45e01f2023b0cbf7182e1bd349f47afb70a95d371b6b882dad36af6132c4eb8a16e3e800cd3f1a872bc00a8054af03db1b2bf7e06c67733c456bc1a5216c49985f2a9c27d7a9f2ad8a6857db6d49a767ef88b2298771a20f50fc307dd54788e2a9bf0f87bdcfa9c764fc91adeec4087e2c56c2e9bbc2822453b99c32fc0ed90b32de75a1d1270ab8b40b937bb5267b0f8f2c8468a87cdc9632297bb63e076a51493d4da1f72c9d195cb5cc3d9eb64991a0d6070ab0d0ad9cda74e23c8319d6c57311999f66cfcda446da2e472d46bb6b2422df25fd4e082653491e52c3160f7f2946f3182f6ebedacac38b3b892ea060f683ab06d320329d1277e3763aab215a84901fff2c670f8d8ef1afc2fa15442e02c17fcc574906c98bd7fd467422a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "e7e48cd1dbf7194f324841dfdb24e2ff35c863cdc32658c1ef379576adafa212a04a1cbc082b6af591e08240318afee6d102e5c0dbcd4e87d3a03d0e8351523e3311e79f408ae5e4178c35f98c0731cbe34f757aeb3f5284f01695e36bffc93ed37be1c94bb38b934c66ff95c6221eba11d2a52900a44a1f01d1f674f9ea3e09add49b584927aca7909882a4ab6b661dc86b3fd80815e545ea00d80cf0c8752e29f7d62a5a842d3db7344d20bc42f95b0879b244183ad14c791cf69fc31feb4bd729c168f9b76ce77a598a0749138a741502404ba6a2a01b09a8701a5d4012d8e186d67d01f26489ced17f74491fa2e67bc226ce0b2785bc6646c7612aece898a1e666b5520ddd7c620167690c8f91185432356c11d30687ca5f0c5105a7d9979e33895a0bfa0600468189ef389bc95e3335bdc2ecfb8c6941db379bf84fab47cb5f1a7a14361654b04e96431f49aa75ca4f32859337bd50666ca4edc3886bf8635705620ec0af1a9544e90f49122701e1e8728b1213ca96676f68d796f3a7ac562bd586903d39e6a2acbb2088f68be4cc63121c86b129db946af3cbeac9fef55f1eb7c03ab7d225e74d96a9e9ae33a1ded864d2c4a6bbb7936e419d1cf230349ca1948d39bfdb29850cd9e44bfbb30da8bb82e5291991be11a44d8886a02819528fe8ef7b24a2c4581f1c57b4233e9377cc1266c75767535439682214a47982", "f0", "e7e48cd1dbf7194f324841dfdb24e2ff35c863cdc32658c1ef379576adafa212a04a1cbc082b6af591e08240318afee6d102e5c0dbcd4e87d3a03d0e8351523e3311e79f408ae5e4178c35f98c0731cbe34f757aeb3f5284f01695e36bffc93ed37be1c94bb38b934c66ff95c6221eba11d2a52900a44a1f01d1f674f9ea3e09add49b584927aca7909882a4ab6b661dc86b3fd80815e545ea00d80cf0c8752e29f7d62a5a842d3db7344d20bc42f95b0879b244183ad14c791cf69fc31feb4bd729c168f9b76ce77a598a0749138a741502404ba6a2a01b09a8701a5d4012d8e186d67d01f26489ced17f74491fa2e67bc226ce0b2785bc6646c7612aece898a1e666b5520ddd7c620167690c8f91185432356c11d30687ca5f0c5105a7d9979e33895a0bfa0600468189ef389bc95e3335bdc2ecfb8c6941db379bf84fab47cb5f1a7a14361654b04e96431f49aa75ca4f32859337bd50666ca4edc3886bf8635705620ec0af1a9544e90f49122701e1e8728b1213ca96676f68d796f3a7ac562bd586903d39e6a2acbb2088f68be4cc63121c86b129db946af3cbeac9fef55f1eb7c03ab7d225e74d96a9e9ae33a1ded864d2c4a6bbb7936e419d1cf230349ca1948d39bfdb29850cd9e44bfbb30da8bb82e5291991be11a44d8886a02819528fe8ef7b24a2c4581f1c57b4233e9377cc1266c75767535439682214a47982000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "3ea2c460533db51a8ac388a93d791dddc705fdca99681e0d1ce7ad7e1dd5bc7bf5458433e3e53b934cfe0c91d198832523edd48a8b02c83697ebd469976d2bf3181949a82dba2264092e49c51251938cb14d1036dcb57dbd4eee046d29f29cc23f84d6e21589462d2dc7220639b02984cc01cda0f40402e60f8c0ba65dee79dda5e9a6559fa819506c783b54f957c56ba9bf66842b9618ad5927ee3bfb106cd151580fb11773d04bf1fd58a374b2255afb2bd986c28ad52130d2492cae61d848ba45fb0555d02b817e4907e3d6d586dda5a9508592a8122cfbef88dce5ef344c764f49f8fff9440138ab461aeae61b68e8427379b4ed2baa35e0884c9136cd6d0156577e499f69e358cdcc427863539e8951651f3c57b8b554cd859f28ac0e4a0da6135eb0a60f0c01d145eaf132e29e7a41d23d70ecf9c3afedef3f80b4b07fcf3f021fb11241860650d630447132051357a894108b6ba5b1a29887c511750a259e32925d059d6d4dd20baa30cbc86c0973626e66922dbee5c3941b802403167e64c0a5a10f29123b4f527ea7b3911beb918b720a998f0ad226f5f6384722c400d2c4854a6d8b5c18151730dae323ba689f58f2bac788e48db97a33766391b9724f53d5b8f38c84a8c22ccf3e2ed895160cb0a9ee9c88c0483c1093cf88bfd5d260020a413693ec8f89abdacf8bbe7524674bb340790bf6bad0cb6aba47995f", "78", "3ea2c460533db51a8ac388a93d791dddc705fdca99681e0d1ce7ad7e1dd5bc7bf5458433e3e53b934cfe0c91d198832523edd48a8b02c83697ebd469976d2bf3181949a82dba2264092e49c51251938cb14d1036dcb57dbd4eee046d29f29cc23f84d6e21589462d2dc7220639b02984cc01cda0f40402e60f8c0ba65dee79dda5e9a6559fa819506c783b54f957c56ba9bf66842b9618ad5927ee3bfb106cd151580fb11773d04bf1fd58a374b2255afb2bd986c28ad52130d2492cae61d848ba45fb0555d02b817e4907e3d6d586dda5a9508592a8122cfbef88dce5ef344c764f49f8fff9440138ab461aeae61b68e8427379b4ed2baa35e0884c9136cd6d0156577e499f69e358cdcc427863539e8951651f3c57b8b554cd859f28ac0e4a0da6135eb0a60f0c01d145eaf132e29e7a41d23d70ecf9c3afedef3f80b4b07fcf3f021fb11241860650d630447132051357a894108b6ba5b1a29887c511750a259e32925d059d6d4dd20baa30cbc86c0973626e66922dbee5c3941b802403167e64c0a5a10f29123b4f527ea7b3911beb918b720a998f0ad226f5f6384722c400d2c4854a6d8b5c18151730dae323ba689f58f2bac788e48db97a33766391b9724f53d5b8f38c84a8c22ccf3e2ed895160cb0a9ee9c88c0483c1093cf88bfd5d260020a413693ec8f89abdacf8bbe7524674bb340790bf6bad0cb6aba47995f000000000000000000000000000000", .None}, + {.Shl, "-f65a3a83fbebadc68eb1ba4fa66bbb39dbd3c5aa353046685f1a9a7d8c69bca6d60f9f9be1d22c769a405506a4163ed21a99746097c82e811b3bbc9d4ca49fc1c86c2ed905a64a03bae1a43bf3341c47dff9c70fa72ab55abb9589163dba9aa1facf796cd7caf373c20ceb226d1a5e17f73f8725e36baec1d897014615aab57a743955b6b301ff02cd2eae7c6fe67f9cf0ef96f1da1e5384832ba6d069e4335e03a504ddf2e73c8f003ea2fc46f4d489b14a94f9309c0bd9159b6b1fa54e24ac268808545e83cc74c2f3c34910a103d02bbee171404cfcedaeca5230fd953b990d51a1220ac91a4acd6957c81d2ea1fe81d2744296cdbe9a99a1f2ac7a54464dfcdf14e2f37fce2c6f5c5c30692055d225ffb8fa8a3dcf6e41dc4ca31b9289c77241f8ee1c0898f27221d9c678820737192f2a4c87de13f6206b1225e9f382c7bf7af7fea431033881ee5954c879f47400a4347e6f253865d57fe69b5e48f03e66926bef0c6b93bc9270b24900db1a2755aae3fa45f35fa83ef7d4c03c4f87e50cb84617981473114604206b6bd870a6ffa09eb0b62fa23efddd89e730c5119b1dad8022ba1e32531281d34d478763c7970d2889e077d29930d56fd4af8c9eabd466deeef6da3e9f555e93c5775ab35644c539ececb6f92d78a8962c2b546a8fa296f4232cec1de1955eeab2e3486a4bbde8ab4225c617361ba531b6242ae4fb", "3c", "-f65a3a83fbebadc68eb1ba4fa66bbb39dbd3c5aa353046685f1a9a7d8c69bca6d60f9f9be1d22c769a405506a4163ed21a99746097c82e811b3bbc9d4ca49fc1c86c2ed905a64a03bae1a43bf3341c47dff9c70fa72ab55abb9589163dba9aa1facf796cd7caf373c20ceb226d1a5e17f73f8725e36baec1d897014615aab57a743955b6b301ff02cd2eae7c6fe67f9cf0ef96f1da1e5384832ba6d069e4335e03a504ddf2e73c8f003ea2fc46f4d489b14a94f9309c0bd9159b6b1fa54e24ac268808545e83cc74c2f3c34910a103d02bbee171404cfcedaeca5230fd953b990d51a1220ac91a4acd6957c81d2ea1fe81d2744296cdbe9a99a1f2ac7a54464dfcdf14e2f37fce2c6f5c5c30692055d225ffb8fa8a3dcf6e41dc4ca31b9289c77241f8ee1c0898f27221d9c678820737192f2a4c87de13f6206b1225e9f382c7bf7af7fea431033881ee5954c879f47400a4347e6f253865d57fe69b5e48f03e66926bef0c6b93bc9270b24900db1a2755aae3fa45f35fa83ef7d4c03c4f87e50cb84617981473114604206b6bd870a6ffa09eb0b62fa23efddd89e730c5119b1dad8022ba1e32531281d34d478763c7970d2889e077d29930d56fd4af8c9eabd466deeef6da3e9f555e93c5775ab35644c539ececb6f92d78a8962c2b546a8fa296f4232cec1de1955eeab2e3486a4bbde8ab4225c617361ba531b6242ae4fb000000000000000", .None}, + {.Shl, "1c813ca79b8ee15e659b53701c818bd846aa2ef73c95e7ba130e73015b8c5deb2348886c504405cdeb90b89e79f6d29c3f4704ad049a12ba7d3a6d2cff37e9046d3af0df7d123641ac3a9bb1af081359c4ecbcba9b595169648d7a65aa17494d49eeebb430a933f24813afa8920c38e7397ff9ae68e87a245afb2c1fe56c70a3c2b4ed6674ac834595bcf611103d95275e411e024f24aa64908f78e7ba81cc198cfd08e493a3ead3291af00f04d78fe263764ffa2d450fac8e53dfcedcd70d148f759ad9f5d882ac8da510902547b992959c268e9ba1efc9b98b9f027bb23ad378a47ca2f79d18a19b6266d795de383c24c24fa8b9688f7efb6615117bf2ffb14e7a465fa5b6f354fbd07b3ae008fd7e0a997440e8650086a3bca2f2683fdf2341393f8a77d0cb19f95d95397bc811be97f0f0cd66cf05ceaeca6fcd64349199276d294adb2351a7f110a0e3ce8067bb8011cb198b7e8eabc0f65085aca89506704b145d938bc27e3281e1f3e15b071a94a6f39fda788ea5466c4a6371fb3fbaddbbfb789eb15cdb5e9d64712dd7b6a6a17b24b209581c50886b974a52bc17639aae1f2b3486cb04821af023d90579aaac909a382ac0c99696c18252b830015292c030e1400c10397c4dd6a491e7ba8b25ad56bfae07f57b1b97f1a3de1d48e7181fec35f4f12d705e50a5eba672467db592a08f9556b18e1ffd56cbc6edec65", "21c", "1c813ca79b8ee15e659b53701c818bd846aa2ef73c95e7ba130e73015b8c5deb2348886c504405cdeb90b89e79f6d29c3f4704ad049a12ba7d3a6d2cff37e9046d3af0df7d123641ac3a9bb1af081359c4ecbcba9b595169648d7a65aa17494d49eeebb430a933f24813afa8920c38e7397ff9ae68e87a245afb2c1fe56c70a3c2b4ed6674ac834595bcf611103d95275e411e024f24aa64908f78e7ba81cc198cfd08e493a3ead3291af00f04d78fe263764ffa2d450fac8e53dfcedcd70d148f759ad9f5d882ac8da510902547b992959c268e9ba1efc9b98b9f027bb23ad378a47ca2f79d18a19b6266d795de383c24c24fa8b9688f7efb6615117bf2ffb14e7a465fa5b6f354fbd07b3ae008fd7e0a997440e8650086a3bca2f2683fdf2341393f8a77d0cb19f95d95397bc811be97f0f0cd66cf05ceaeca6fcd64349199276d294adb2351a7f110a0e3ce8067bb8011cb198b7e8eabc0f65085aca89506704b145d938bc27e3281e1f3e15b071a94a6f39fda788ea5466c4a6371fb3fbaddbbfb789eb15cdb5e9d64712dd7b6a6a17b24b209581c50886b974a52bc17639aae1f2b3486cb04821af023d90579aaac909a382ac0c99696c18252b830015292c030e1400c10397c4dd6a491e7ba8b25ad56bfae07f57b1b97f1a3de1d48e7181fec35f4f12d705e50a5eba672467db592a08f9556b18e1ffd56cbc6edec65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "e8c18cb54388ba116db113d3ddc89d710f2f067965e4b7dff7f789a042111068b8f65780cae7fed8c39b5864213b64ecfd26ad8d24c91077f11d718e31604fea9b3615d18d240320cf06eead4707f8ea434e537fa743d475d60ce458d0e0fc9ca9af151a57996fc886b392d925cd10c74505ab1c449e758667241b2a1f8240ba5fcb03cfce6ccd5c65c68ca09c8d065a443874281458c8ee1a8cc776cad803096de3363ea06d9ffab0b3b61c9726eaf5b0b3488fbf092f955fbad4a83c1bd017352e1d1c07e5232a62a875eef715290161d3457d07cc4cf931a6764c4e857c9b100e5a1caadb947291020b54f3115f801d3cbae4d34171079e52a6c7a84a4465cba3cbad2050c023181301f8c772749e4d929cbcbd8a816ae231b9f5566734bafd21ea6bfbbf862da65ccec3a8c00d3a0ac2ae7c039d54eae38d4d28152427d916f5d288adc4f118e5a86b9443402cc70438e6eeb9fa225ff6850395773d38c3949e6281c68b68db120d9829cd5cc7279cc3e0c82f1cd4d6a19f3cabca344f62abe134dda5851fcd84776668449f0924dfa51db8301b2cd422451f16f8fff5f50059c262a6fb021d801213e1cc97a3f43440f1ef122d439b05979cf4cf9297dbee8d5b07e02d1d42acd4b3bcb08b86dfb8914c4a16d3814e5f8d20517c39bda3798724f72a441ae3a7ea80a0964b158a4bc325a76ec095dc822599daa010e724", "21c", "e8c18cb54388ba116db113d3ddc89d710f2f067965e4b7dff7f789a042111068b8f65780cae7fed8c39b5864213b64ecfd26ad8d24c91077f11d718e31604fea9b3615d18d240320cf06eead4707f8ea434e537fa743d475d60ce458d0e0fc9ca9af151a57996fc886b392d925cd10c74505ab1c449e758667241b2a1f8240ba5fcb03cfce6ccd5c65c68ca09c8d065a443874281458c8ee1a8cc776cad803096de3363ea06d9ffab0b3b61c9726eaf5b0b3488fbf092f955fbad4a83c1bd017352e1d1c07e5232a62a875eef715290161d3457d07cc4cf931a6764c4e857c9b100e5a1caadb947291020b54f3115f801d3cbae4d34171079e52a6c7a84a4465cba3cbad2050c023181301f8c772749e4d929cbcbd8a816ae231b9f5566734bafd21ea6bfbbf862da65ccec3a8c00d3a0ac2ae7c039d54eae38d4d28152427d916f5d288adc4f118e5a86b9443402cc70438e6eeb9fa225ff6850395773d38c3949e6281c68b68db120d9829cd5cc7279cc3e0c82f1cd4d6a19f3cabca344f62abe134dda5851fcd84776668449f0924dfa51db8301b2cd422451f16f8fff5f50059c262a6fb021d801213e1cc97a3f43440f1ef122d439b05979cf4cf9297dbee8d5b07e02d1d42acd4b3bcb08b86dfb8914c4a16d3814e5f8d20517c39bda3798724f72a441ae3a7ea80a0964b158a4bc325a76ec095dc822599daa010e724000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "b8db372dbca74b5940f97f50ba8c37a44ed5b916e7a0ab815f8b14b02a8946e3a9fd55fa57a5d037ec10d8937c0ba55ad51373b5c3edfa63de591559e34c4d73590de269b6d6d9d42a2687a0ef5e519c314e36f97079c44e4ce08a29468281e964233cec98c88181e4245f0e20b953fef016237f53d70d65ecd3c839cd5c2e48df1f40e7ecb443a40b3676ea886f27fe653a0c56a7dab1c50cc7526b1c094979910711cce37887446443bc9403191c7a58a2a0fd3ef5e8cac818e30570495303bff305ccbdc2292a001fd4537cea9eaa08e98ed310d1cb824079433ce64232b0018653be0dd4159fd6b05938981a45baed534aa5601a4d88b1c7c12f81ed0e2bef138738e028e12936f162adef2524a85191d1fe9875f790e282af92687d4b99934587e9d6217f479ffd656b1fadd2c5f09eb09c96cc354f7a08785afdbfb60e72c94d4bf8e697830cac6bad2dc2418198e1642fa66e867f45ba812e54fee4897a52410619789ca040001f15ba362f5de19da1ffedee290075d62dfd1eb15e22ac2c62bea4962a2b503cdc1417e87c38bb353567f309121cc93ea0de3766a5baef2d40b5c6996a59721f5450c9d35c65975e10e75df57c86e73f68e5f9a19f42f895d7bd4923dc3c635ee961b43741a00326de60eee98e913eefcf77f4109e6559975d7c5a0dc942d40eb012b27ade6b43a2b43189b7844b44a08d97ea90d7ff", "12c", "b8db372dbca74b5940f97f50ba8c37a44ed5b916e7a0ab815f8b14b02a8946e3a9fd55fa57a5d037ec10d8937c0ba55ad51373b5c3edfa63de591559e34c4d73590de269b6d6d9d42a2687a0ef5e519c314e36f97079c44e4ce08a29468281e964233cec98c88181e4245f0e20b953fef016237f53d70d65ecd3c839cd5c2e48df1f40e7ecb443a40b3676ea886f27fe653a0c56a7dab1c50cc7526b1c094979910711cce37887446443bc9403191c7a58a2a0fd3ef5e8cac818e30570495303bff305ccbdc2292a001fd4537cea9eaa08e98ed310d1cb824079433ce64232b0018653be0dd4159fd6b05938981a45baed534aa5601a4d88b1c7c12f81ed0e2bef138738e028e12936f162adef2524a85191d1fe9875f790e282af92687d4b99934587e9d6217f479ffd656b1fadd2c5f09eb09c96cc354f7a08785afdbfb60e72c94d4bf8e697830cac6bad2dc2418198e1642fa66e867f45ba812e54fee4897a52410619789ca040001f15ba362f5de19da1ffedee290075d62dfd1eb15e22ac2c62bea4962a2b503cdc1417e87c38bb353567f309121cc93ea0de3766a5baef2d40b5c6996a59721f5450c9d35c65975e10e75df57c86e73f68e5f9a19f42f895d7bd4923dc3c635ee961b43741a00326de60eee98e913eefcf77f4109e6559975d7c5a0dc942d40eb012b27ade6b43a2b43189b7844b44a08d97ea90d7ff000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-3bd5614d7d89ea99d47e4a171d5eb80180478a3dd85511adb5b4ee25572b80acab15c86764584ac8f1223a3712bd3ebd94b79fd93f67ad8c99ab2badac83078eff0d750c410f0fed8e337b8e70105b3f38c02b388d51cd8ff2046b5c79315ebc4f5b2f37e8d579b9b3729e8a3326e599f231a7819475a8bd7b4787467ca0009d8bb15121c8d633d2c191791928809dc65c87a79bb30eecd43d8f6ab301cc9da1ed31215a7b2222ac4968f2a894e588e9892e63667f66a213c99144daab0dd1c513022f7c19369b854b807bf3ba65d6bf07452e29319e999c61b9e29a16bb58702dfe071b856cd9d235a3c898b235c3a3e3d807c2747d9662cb980243b1b993ef872d2b210a81f951305b18374ebce215beca0e99c71dc55a51184ad7dd7a23b8146249f9e8baf14aa01ba89e888b514e74c286bef256b0408b44b677a9f6a4d1a364762767d4ba8254a0e84cc63ee5d6147377251be9b7af6cde6341973c88ee8a95f4c4b39dd2fe124d205d1693bf7f8a6ec46faf72f2f82109996cbc8bd48a856e3ae5b4772b7c4976d6fbe0e9b91f755e620e18b25a0ec4394567eb25f7fd25b8fc1969dccb07b10a7e0e3e14399b43037ba142333e793f5c41ab01a56b8952efe2a3857c3a10fd083e5ae16edcde2dfe18f05b4fd00e923e63cdd06ab22fa793d6a421e18528440134987baa0d9eda7431cab351046f164ef33e68464707", "12c", "-3bd5614d7d89ea99d47e4a171d5eb80180478a3dd85511adb5b4ee25572b80acab15c86764584ac8f1223a3712bd3ebd94b79fd93f67ad8c99ab2badac83078eff0d750c410f0fed8e337b8e70105b3f38c02b388d51cd8ff2046b5c79315ebc4f5b2f37e8d579b9b3729e8a3326e599f231a7819475a8bd7b4787467ca0009d8bb15121c8d633d2c191791928809dc65c87a79bb30eecd43d8f6ab301cc9da1ed31215a7b2222ac4968f2a894e588e9892e63667f66a213c99144daab0dd1c513022f7c19369b854b807bf3ba65d6bf07452e29319e999c61b9e29a16bb58702dfe071b856cd9d235a3c898b235c3a3e3d807c2747d9662cb980243b1b993ef872d2b210a81f951305b18374ebce215beca0e99c71dc55a51184ad7dd7a23b8146249f9e8baf14aa01ba89e888b514e74c286bef256b0408b44b677a9f6a4d1a364762767d4ba8254a0e84cc63ee5d6147377251be9b7af6cde6341973c88ee8a95f4c4b39dd2fe124d205d1693bf7f8a6ec46faf72f2f82109996cbc8bd48a856e3ae5b4772b7c4976d6fbe0e9b91f755e620e18b25a0ec4394567eb25f7fd25b8fc1969dccb07b10a7e0e3e14399b43037ba142333e793f5c41ab01a56b8952efe2a3857c3a10fd083e5ae16edcde2dfe18f05b4fd00e923e63cdd06ab22fa793d6a421e18528440134987baa0d9eda7431cab351046f164ef33e68464707000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-982ac9d3603db4a225a5c95238bdfa26cb67f5f1466e087528629a31dd44a8ec98ba92398f81b16dd976de3f4a4e1c88e7f4ac7a87c0678c026a7b8875d8058463ca7c44110d6ba323fd6db02486015015bf920f5303de6442e080177312601342c62bec7bc207a3ff385af385ca6c8b15fc10608e3d959562fbee72b9d4bdb188eac3b5d233143c9c78e0bffbd1a6d552c21f8e32c4f6b4abf8cb3ba514474ac1897e17eee99fea9312f65782f4ce284fb3e09d96a66bf672c2b5eded53df9f969f67c4ae9748df11677601ddeadfdf2477dd81bec1f40e9e8c69a84c490b78b0c72cb52a853982438f9b3cc3ba2789d2d8e1cb43407beaa9db2a6ec88e18591d40cb38473cd6ee6f4d36e0267b02211d738829cfe3c6e12e7719da9cb88379417e223947509b3ae1618c733f931e1b339ef224ec1746c41054013e6900765899654e66eca79041938ee683e561c06f6cca32cbcb5b0546c7333a6178db3b1f26dbd3fd25b3503d2383eaddf8655840609766b76e28783e4bb5c238ec1243af2212c4c3ee1ededcade1a586d8ecb0ad0f4b02f1827d26262c3496d583257c9ea76a31d215f3fd42e9bf5801011b863df2362a22aef05b49c84ed3d449d5373143c721c733c835d4c49a3a429c71fb968ce8a4ca1ac771bd5cb100407f914a4d958d4763f58b51519a0491374d09e7230015219477389bbf919bb67aae4d9edd", "168", "-982ac9d3603db4a225a5c95238bdfa26cb67f5f1466e087528629a31dd44a8ec98ba92398f81b16dd976de3f4a4e1c88e7f4ac7a87c0678c026a7b8875d8058463ca7c44110d6ba323fd6db02486015015bf920f5303de6442e080177312601342c62bec7bc207a3ff385af385ca6c8b15fc10608e3d959562fbee72b9d4bdb188eac3b5d233143c9c78e0bffbd1a6d552c21f8e32c4f6b4abf8cb3ba514474ac1897e17eee99fea9312f65782f4ce284fb3e09d96a66bf672c2b5eded53df9f969f67c4ae9748df11677601ddeadfdf2477dd81bec1f40e9e8c69a84c490b78b0c72cb52a853982438f9b3cc3ba2789d2d8e1cb43407beaa9db2a6ec88e18591d40cb38473cd6ee6f4d36e0267b02211d738829cfe3c6e12e7719da9cb88379417e223947509b3ae1618c733f931e1b339ef224ec1746c41054013e6900765899654e66eca79041938ee683e561c06f6cca32cbcb5b0546c7333a6178db3b1f26dbd3fd25b3503d2383eaddf8655840609766b76e28783e4bb5c238ec1243af2212c4c3ee1ededcade1a586d8ecb0ad0f4b02f1827d26262c3496d583257c9ea76a31d215f3fd42e9bf5801011b863df2362a22aef05b49c84ed3d449d5373143c721c733c835d4c49a3a429c71fb968ce8a4ca1ac771bd5cb100407f914a4d958d4763f58b51519a0491374d09e7230015219477389bbf919bb67aae4d9edd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-6445006404b57c34a9b79ce9b613a8d9852ed1247641cb02b36acd1ed328deeee5560b6fff448cabdcd6eeb7a40dab4b48123c74365de56597bc4655c12c6f8c5a288f648591feae5d7d038f71b02faf537c8c750f80cd375b69999e55de12b89dc95618391c31e1e33dbbc04f314b9f2285836e40bb515662ba8df30c65fee401be421e2bae815fd6d7aa9276b03749c87d7c50ccb6260e0e3180767fbe0f11047455363edd565119d43d9d7a00ca9c53f0877e99e257ecf7a210517c6adfd1d5c532496c1ee5bc82aef6e31dbbfdd33614f4e5d44fc4935d474a8407b753e8201f0fc15a4fe9ca231a8506f5f303ada76c72624ccbeb62a04617411364bb2e7c34683dcb404d15ee323d52c5d697db8f590f4c43de058f954acdbafad2d1c113c13f055aa19f7a2b0252a373c1139d51ead0d5a09b9f0a1402b98831b8236b105ad8a050e83fab04c4495b7b47cc1eee9262c87151b7fb26ddd5e43f017ba425b76042ae9542960b64cddbac9fd937e8f2c9f4f41b92d1f7ce45937ca4c5204ebbc59ea1d02b2e759b3eb0406e675f18efcd47bef97345cb0e94c1fdec902616eb840f07adb8763ad5e421015d64d7db8580bd8b146b95a85999fd41b291f0e2ca8211899d075ebca318f6a9740665509f8878dbe010feb763e3d070be46a7554aed2051bf2a0b5d10f165759e7308950f0535688cbad312fefa0c8ce6ce0", "168", "-6445006404b57c34a9b79ce9b613a8d9852ed1247641cb02b36acd1ed328deeee5560b6fff448cabdcd6eeb7a40dab4b48123c74365de56597bc4655c12c6f8c5a288f648591feae5d7d038f71b02faf537c8c750f80cd375b69999e55de12b89dc95618391c31e1e33dbbc04f314b9f2285836e40bb515662ba8df30c65fee401be421e2bae815fd6d7aa9276b03749c87d7c50ccb6260e0e3180767fbe0f11047455363edd565119d43d9d7a00ca9c53f0877e99e257ecf7a210517c6adfd1d5c532496c1ee5bc82aef6e31dbbfdd33614f4e5d44fc4935d474a8407b753e8201f0fc15a4fe9ca231a8506f5f303ada76c72624ccbeb62a04617411364bb2e7c34683dcb404d15ee323d52c5d697db8f590f4c43de058f954acdbafad2d1c113c13f055aa19f7a2b0252a373c1139d51ead0d5a09b9f0a1402b98831b8236b105ad8a050e83fab04c4495b7b47cc1eee9262c87151b7fb26ddd5e43f017ba425b76042ae9542960b64cddbac9fd937e8f2c9f4f41b92d1f7ce45937ca4c5204ebbc59ea1d02b2e759b3eb0406e675f18efcd47bef97345cb0e94c1fdec902616eb840f07adb8763ad5e421015d64d7db8580bd8b146b95a85999fd41b291f0e2ca8211899d075ebca318f6a9740665509f8878dbe010feb763e3d070be46a7554aed2051bf2a0b5d10f165759e7308950f0535688cbad312fefa0c8ce6ce0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "db924cb4c94fb2a6c034c84370e51aa5134d149ead7d6d5eedf0afc5c9c35ebdfd3724b27177cf340e66750d0870d3c36a1d1f9413ee3695b05c7c51feb669dff56b5ca074db7dad7c752d13c6679d88a34ec095d7d3bf3a50026d33cdbb67db71475a00653f8d42aff2220b6fc3335a9e8ad6aaea5c8d18d2151c75a10ae00c6f1696c0b14775641dd8e1629894900e538fe2c3ab4b0e4cad2a800096861c7e416d29c72b80aa5ca7f01615a4f12f0a1d4c3bec1a2b5deadbe18082fb25cd5bb7e63e74bcda8347bc6a5fd539b02b3c59043e07eca1d5bb646fd8fa5b9f65c3629c04a2063135bedbcc23788080c883aa453c2b7a6b1a25c7228c3c45b0d7e2a8386cdbd852f9ba5508983023b983ef0b7b2bab629987d2369f8aea457f13f3d6f7ee81c3b553f8b8c6465a7c5ab548873fc9d45757efd9921a1eb95a32d8e56d4440f7e0d850f2a2a362626b33a9fcaea30a88686ec0f11e8b0e68017e80b40dc32b8055ad40a02e6195af3786594c1bcab850cc90a1b639e3a93a2a9c472586222cd35fbf9edde32fcaa6a52d513b0c864066bef0d54e4dff8f9124c09ebbcd26dcf580c028ec2ed4c0c49b4d393cededf358a4549ffb3f178fc54c85713f8fdc9c19b2aab748b032d23f2013e13c7074865452f3a52e1d0733f1c730b56e8d7b9b6c2f811d3c489bff3f591765cd569241b4fbe333d0faca56e005825e1e", "78", "db924cb4c94fb2a6c034c84370e51aa5134d149ead7d6d5eedf0afc5c9c35ebdfd3724b27177cf340e66750d0870d3c36a1d1f9413ee3695b05c7c51feb669dff56b5ca074db7dad7c752d13c6679d88a34ec095d7d3bf3a50026d33cdbb67db71475a00653f8d42aff2220b6fc3335a9e8ad6aaea5c8d18d2151c75a10ae00c6f1696c0b14775641dd8e1629894900e538fe2c3ab4b0e4cad2a800096861c7e416d29c72b80aa5ca7f01615a4f12f0a1d4c3bec1a2b5deadbe18082fb25cd5bb7e63e74bcda8347bc6a5fd539b02b3c59043e07eca1d5bb646fd8fa5b9f65c3629c04a2063135bedbcc23788080c883aa453c2b7a6b1a25c7228c3c45b0d7e2a8386cdbd852f9ba5508983023b983ef0b7b2bab629987d2369f8aea457f13f3d6f7ee81c3b553f8b8c6465a7c5ab548873fc9d45757efd9921a1eb95a32d8e56d4440f7e0d850f2a2a362626b33a9fcaea30a88686ec0f11e8b0e68017e80b40dc32b8055ad40a02e6195af3786594c1bcab850cc90a1b639e3a93a2a9c472586222cd35fbf9edde32fcaa6a52d513b0c864066bef0d54e4dff8f9124c09ebbcd26dcf580c028ec2ed4c0c49b4d393cededf358a4549ffb3f178fc54c85713f8fdc9c19b2aab748b032d23f2013e13c7074865452f3a52e1d0733f1c730b56e8d7b9b6c2f811d3c489bff3f591765cd569241b4fbe333d0faca56e005825e1e000000000000000000000000000000", .None}, + {.Shl, "6e90d4a8b67bcd83ff7da9865bdbb33c0623a4239511466132ce492c0713d23e5ffae9eb772fa8c1d95ea6a87ecca5892be8e14b3e87afe4f23896dc577178795dff80a35c03b5764787ce1bfc82960114eb6d89a9838476f99c4bd071dcc2dd2b4a000d7c39f4fd3275595de1a86321b3b2d29ff102655a009c84bcf1f27f6ad29d6ae275882ad8368c4f03e260b1aa6af30b136c1d882f72ed8dd0ddb1c8f4160fbe1b7549ec50634fdf40a2c87bca174aa41f6fb3be70bde9734a272af82589750e31bbf5bbb80022e081be74ce73c316f087afa419551e876a7a162214a9c350ead48d2cfa5974d3eb4fe9aad6c7edf5e00a8785fc35d4006df4e501a636fe1b6faa201a97bd4dbf5af074a51a5e1a6814979a0ac56b7e29ed0004a35882e81c3d6f32480438370575328acb984a6949fe8a7cb2f24033df2616656b202b9917374491239358c209d2e61f1d188c10853f720a0329597e1a1a5f942b5f1739dfbb8f80958bb88f57ff1c91eba16324b7395d50cdaac9f091fa7230905e978c30a651942f6837a9879d6bc21819a5b3c30718f493ac9501067ef010b649112af5211e8087486b785bff163d26ed6847261f6bb173531504fdd540f66ac990f4564b48975a37f68ee1f96605044e62ec5e3d50ee066c9406ebd490ce379647d8a639d8e43902766fb993b75cc64f7bb4ca01ed0c146de63f3b8c96bd2650c9", "21c", "6e90d4a8b67bcd83ff7da9865bdbb33c0623a4239511466132ce492c0713d23e5ffae9eb772fa8c1d95ea6a87ecca5892be8e14b3e87afe4f23896dc577178795dff80a35c03b5764787ce1bfc82960114eb6d89a9838476f99c4bd071dcc2dd2b4a000d7c39f4fd3275595de1a86321b3b2d29ff102655a009c84bcf1f27f6ad29d6ae275882ad8368c4f03e260b1aa6af30b136c1d882f72ed8dd0ddb1c8f4160fbe1b7549ec50634fdf40a2c87bca174aa41f6fb3be70bde9734a272af82589750e31bbf5bbb80022e081be74ce73c316f087afa419551e876a7a162214a9c350ead48d2cfa5974d3eb4fe9aad6c7edf5e00a8785fc35d4006df4e501a636fe1b6faa201a97bd4dbf5af074a51a5e1a6814979a0ac56b7e29ed0004a35882e81c3d6f32480438370575328acb984a6949fe8a7cb2f24033df2616656b202b9917374491239358c209d2e61f1d188c10853f720a0329597e1a1a5f942b5f1739dfbb8f80958bb88f57ff1c91eba16324b7395d50cdaac9f091fa7230905e978c30a651942f6837a9879d6bc21819a5b3c30718f493ac9501067ef010b649112af5211e8087486b785bff163d26ed6847261f6bb173531504fdd540f66ac990f4564b48975a37f68ee1f96605044e62ec5e3d50ee066c9406ebd490ce379647d8a639d8e43902766fb993b75cc64f7bb4ca01ed0c146de63f3b8c96bd2650c9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-739686cc12ffdfcfe0ba25b665243b1222798f79107bf53212ae2a9c58c2ed6b565c44efc5f5ae55e8541b70dac6bc877b5642cc707e056b7811691d9c135ecdfd27aaeed16fdc19d834224e198fbcf144e53a5e403932657bb2f52b42510c76b92d6acb03d275016ac168e5e695d359d3c25a688f017bafb80f497e72561f85a2b39850ac567f3740d9e6816478cd9e25d3c736a1a5eddca3125cb150ddaf0d3219a0ff6e59ddade4582808c5858b56f32046f8b6352c9b106b1b1e0fc567d9eafd9ec50cdfe4ea6aa604119b29d4fd4166e90ae6ec9b335c0435ae2e48e21d7579c740054baa5d53b5ac52ac1831844f31280227eced8bed573ee2a4bb5d1213203645a5967c385307b7a4f2d1567a57cea9c08e3fc43323a97fe70779b909f964d3521e3d21bbf6fd35fa7e2f9c79e5337d26c26fbd7993b27687fa65aa73937a0d3184f5b2a188c84cb1cafef717ffa093ae26564e124c22074351580a5c5ea1f49559a18c22c6f1ddf67a5ea3ef0f51dd7fea5030b5812464140fba6c770c3d028dd81afae89343e239bd777f0a85abb5af7dcd88416cfd287ba9c9384ffd23e7a1036dca8cecfe231d73e6bfbb52dfeefb5701c368acfea7f7dc260d3f56cc2abeea6b4b0f3e54263697bb3681e8943e60bfb31e81a20cb744b07b219dd2828b5ef0bf7af7046c3b64087e60c0287d73cb6d71db25576858fd3ac66bb0", "258", "-739686cc12ffdfcfe0ba25b665243b1222798f79107bf53212ae2a9c58c2ed6b565c44efc5f5ae55e8541b70dac6bc877b5642cc707e056b7811691d9c135ecdfd27aaeed16fdc19d834224e198fbcf144e53a5e403932657bb2f52b42510c76b92d6acb03d275016ac168e5e695d359d3c25a688f017bafb80f497e72561f85a2b39850ac567f3740d9e6816478cd9e25d3c736a1a5eddca3125cb150ddaf0d3219a0ff6e59ddade4582808c5858b56f32046f8b6352c9b106b1b1e0fc567d9eafd9ec50cdfe4ea6aa604119b29d4fd4166e90ae6ec9b335c0435ae2e48e21d7579c740054baa5d53b5ac52ac1831844f31280227eced8bed573ee2a4bb5d1213203645a5967c385307b7a4f2d1567a57cea9c08e3fc43323a97fe70779b909f964d3521e3d21bbf6fd35fa7e2f9c79e5337d26c26fbd7993b27687fa65aa73937a0d3184f5b2a188c84cb1cafef717ffa093ae26564e124c22074351580a5c5ea1f49559a18c22c6f1ddf67a5ea3ef0f51dd7fea5030b5812464140fba6c770c3d028dd81afae89343e239bd777f0a85abb5af7dcd88416cfd287ba9c9384ffd23e7a1036dca8cecfe231d73e6bfbb52dfeefb5701c368acfea7f7dc260d3f56cc2abeea6b4b0f3e54263697bb3681e8943e60bfb31e81a20cb744b07b219dd2828b5ef0bf7af7046c3b64087e60c0287d73cb6d71db25576858fd3ac66bb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-d2f25a8284dd7c55d07e4a49179f2ff1f4747148d59c2bf166c52a64d7136e2264e3ff296d2589689b080aa2614f82f465fd788067014e386de68008db09a3b1c693e870547de5f463bd75940ead461025f259582f563dd6bbc3b085e5f6f5308581fa8d74dccf8a3ea8b75acf3aa4b6fd7961fd2a583506b0278195f8a142eda1e462ae146b9221cd74918145e93829028fe56ddf20ff5af33c63ff0f0c2f8aaa27c8e6896534b4ad6a9d9a9df840cd2b28d9171da58d98f76b2570566cb28abb05e3a76a531e917f3a0dac295691fcc29bd2644b198f708fd5a316a94878d554ce23021a8f986ab28ae30be4d6be0db8a5556021b79c6a8d9aa9700cb4c261fb2aeac1c39c76008b47de02b8a8bfd4e4cb935d3d3a06bbee1f6d660e06d3ab1129ec1c56f0001983a4a7ce8e818107a60b1586f71e281ffed3c969385b03b22e344c72f3b18b24eb63f2b72ea23e09370abc3b13f43908bf69081c09b623c0de81b1d38c1a3433b0e1f1b00771baf618204b880c5019003233c56e41d29203cbdf75736975f4acf34be0ebdb5da12085a78489e73f52e3bd9e5c06cfe4ee0e9698e97c7388be80531ca568a1f666ecb298f7b5fbf9ca9f2ea9a87a6dd817222900deb2bcf16fe6d5d615d623e2bbe6cdced1bb7c1760d38efad189bba1605c6cdafaf668641a147be5771cb7235f138239ab0f5a77489e9926cece8c17c307", "258", "-d2f25a8284dd7c55d07e4a49179f2ff1f4747148d59c2bf166c52a64d7136e2264e3ff296d2589689b080aa2614f82f465fd788067014e386de68008db09a3b1c693e870547de5f463bd75940ead461025f259582f563dd6bbc3b085e5f6f5308581fa8d74dccf8a3ea8b75acf3aa4b6fd7961fd2a583506b0278195f8a142eda1e462ae146b9221cd74918145e93829028fe56ddf20ff5af33c63ff0f0c2f8aaa27c8e6896534b4ad6a9d9a9df840cd2b28d9171da58d98f76b2570566cb28abb05e3a76a531e917f3a0dac295691fcc29bd2644b198f708fd5a316a94878d554ce23021a8f986ab28ae30be4d6be0db8a5556021b79c6a8d9aa9700cb4c261fb2aeac1c39c76008b47de02b8a8bfd4e4cb935d3d3a06bbee1f6d660e06d3ab1129ec1c56f0001983a4a7ce8e818107a60b1586f71e281ffed3c969385b03b22e344c72f3b18b24eb63f2b72ea23e09370abc3b13f43908bf69081c09b623c0de81b1d38c1a3433b0e1f1b00771baf618204b880c5019003233c56e41d29203cbdf75736975f4acf34be0ebdb5da12085a78489e73f52e3bd9e5c06cfe4ee0e9698e97c7388be80531ca568a1f666ecb298f7b5fbf9ca9f2ea9a87a6dd817222900deb2bcf16fe6d5d615d623e2bbe6cdced1bb7c1760d38efad189bba1605c6cdafaf668641a147be5771cb7235f138239ab0f5a77489e9926cece8c17c307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-556a109b038e65f62e2b713c08190fd4e5e5228a92400bfe42523e0c185867aea8a056b35c2bb156e3002dd4086ffb8da46385492509238fcf18c7c0b85f4a434de70798b8c509403d109235491e300dff962bcfb112fb8a4b2e05956cca85b4d15293f67955456e301bedf6b6b667d26f1ae26a8c9edadbb375d1c6b01728984957bd2f7cea2d11294b23cd069e1d1b27b29c6de099eeb4122e95429c662859a0cd6f9858f2f69ebecc459c221434b3ee76354bcc83bb16b0671fb288c27c619d675cedfbef4caa180445ec872974982aeabeea04ed9f5ca1ea427dd88ee89855c15899f449c524c8ddd3878fe422693c132af815f9906265ad7f83c0f88140e9ed0a8d6a8da148ed591ae0598e87ba8854ef3334c9d1b0278975aa87c5841c34419a7533b9a999ba3a950359e28542a8a62aea288f683f71362656e28d691453f09603edefde8b9f5e0ce0daa9b446bb208332e215ae0f38f3617c49c99dc909540a9ad167f87301fbab22bc19743cc9ffd1ed1f83b3af1e23d7f455fef7cb1884a070714ca037bf8fe3ffadd75467128de747dfb2c2d30e95dc30457b24797de4d27365f851c3129ed92053df4f0c7b8eed489fa8aa0d88909e8c6376e072e7bdd9c170ad120a933a15aff84b5071a197e048ec7a697f95293595daa1db8330ae46a68bdad832f7647cb9a1f7ed30a90088d8fa2b1c0654caab819ccc2799", "1a4", "-556a109b038e65f62e2b713c08190fd4e5e5228a92400bfe42523e0c185867aea8a056b35c2bb156e3002dd4086ffb8da46385492509238fcf18c7c0b85f4a434de70798b8c509403d109235491e300dff962bcfb112fb8a4b2e05956cca85b4d15293f67955456e301bedf6b6b667d26f1ae26a8c9edadbb375d1c6b01728984957bd2f7cea2d11294b23cd069e1d1b27b29c6de099eeb4122e95429c662859a0cd6f9858f2f69ebecc459c221434b3ee76354bcc83bb16b0671fb288c27c619d675cedfbef4caa180445ec872974982aeabeea04ed9f5ca1ea427dd88ee89855c15899f449c524c8ddd3878fe422693c132af815f9906265ad7f83c0f88140e9ed0a8d6a8da148ed591ae0598e87ba8854ef3334c9d1b0278975aa87c5841c34419a7533b9a999ba3a950359e28542a8a62aea288f683f71362656e28d691453f09603edefde8b9f5e0ce0daa9b446bb208332e215ae0f38f3617c49c99dc909540a9ad167f87301fbab22bc19743cc9ffd1ed1f83b3af1e23d7f455fef7cb1884a070714ca037bf8fe3ffadd75467128de747dfb2c2d30e95dc30457b24797de4d27365f851c3129ed92053df4f0c7b8eed489fa8aa0d88909e8c6376e072e7bdd9c170ad120a933a15aff84b5071a197e048ec7a697f95293595daa1db8330ae46a68bdad832f7647cb9a1f7ed30a90088d8fa2b1c0654caab819ccc2799000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "2a5cc6dfca28b600c5c443dc9e364c949ff11cf6be0fbc3dadf3dc3f9b02d2b8212d70c3c28150dbb94c5aefb8125aca34602c919611e03c6c0cf379884eea31944bfe3af36c7b8f0f504d274f2c52d62a0fdebd4adb94f3a7bfedab66fe27dac3fde74847fd65da7c9c29fb93be70d7ac16b9fdc8080863a5a90dba065cecc2156ee2a1bc89d183931944cc9ca21c0f854b3679487e2f53ed8fda4d0759a823e7a2863ee3b542111a437aa94c835b7dc50035ba1060c7c63f1ec395be9c67b6b16cf4a79410bc7948bdeb0c9fbb24322e773ce9d189d67acaa1945466861c8130eeec7bd32cb36206dba386f01d71e5be168e54904b91ff19cf145c38ff0cd32dbf171c9ca34dbe02659fba8cddc259565d57190a95acab575ba7efb4bce9495a848ead1584cc726e4928b125843c09d01203eddf3d57abc8a6b8c2848725cbfccfc0a58660e4c7d27d40d39704538ae73415334aeaeb6e957e11cab9cf8124255cc036a43dd2d2a01fd2fbc05d4ad497a9ce3995d36a9afc81435fd3470069c54b06c432665a3d197106fc4758e92bafa02c4d00a8e57af2c043470ad2812622677e6ae13bba02b40c374ebcbcd01ffacdc7193b4006ebfbfdb8eaf400981342f434c0b648b3692b656ea9483c51ee9a1aae9d665a60a45a12921823ff28d600bc9d082e8d8a829dbcd5f7ac933ae277bb88b31bcaadc9bc46c3994facdf6c", "1a4", "2a5cc6dfca28b600c5c443dc9e364c949ff11cf6be0fbc3dadf3dc3f9b02d2b8212d70c3c28150dbb94c5aefb8125aca34602c919611e03c6c0cf379884eea31944bfe3af36c7b8f0f504d274f2c52d62a0fdebd4adb94f3a7bfedab66fe27dac3fde74847fd65da7c9c29fb93be70d7ac16b9fdc8080863a5a90dba065cecc2156ee2a1bc89d183931944cc9ca21c0f854b3679487e2f53ed8fda4d0759a823e7a2863ee3b542111a437aa94c835b7dc50035ba1060c7c63f1ec395be9c67b6b16cf4a79410bc7948bdeb0c9fbb24322e773ce9d189d67acaa1945466861c8130eeec7bd32cb36206dba386f01d71e5be168e54904b91ff19cf145c38ff0cd32dbf171c9ca34dbe02659fba8cddc259565d57190a95acab575ba7efb4bce9495a848ead1584cc726e4928b125843c09d01203eddf3d57abc8a6b8c2848725cbfccfc0a58660e4c7d27d40d39704538ae73415334aeaeb6e957e11cab9cf8124255cc036a43dd2d2a01fd2fbc05d4ad497a9ce3995d36a9afc81435fd3470069c54b06c432665a3d197106fc4758e92bafa02c4d00a8e57af2c043470ad2812622677e6ae13bba02b40c374ebcbcd01ffacdc7193b4006ebfbfdb8eaf400981342f434c0b648b3692b656ea9483c51ee9a1aae9d665a60a45a12921823ff28d600bc9d082e8d8a829dbcd5f7ac933ae277bb88b31bcaadc9bc46c3994facdf6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "d613243338f817fc296f4d77a5a0fb313a92e268427185cf747ff901ce82a959d2845b078d69c983da189f5a2ab8668a0a0cf324f3ea823ab6e018c61c15a177bc3506a093b0d0de123926214793aa9bb1e2a46410ac8aae0cc8c4c24384818354dfc16a66892621fa4fd13d9c610cffff96afefa3b2ef49a06f1b1a122e8070ef3bd2913dc29eefe57306d7c3f3f78316f86de346bd0d68a15c9d64b8a89bd3835c55239f49b5324c55bd593fa8b2c75387b41743aa8acd6e76af92d015d256162279140b16f9d00e73a76b777cb3e3ed1594658e7237c10eee9ca79c385c1708b3485588dcc76501c911c7c392f8a8b7a8cda529daa678f497057eef1b430c890c880fb128d5162f1b8dc7f7d1571b929da5cb2cf1f775fc32e6c714d91e608f40a4ee16229870ae52c8d4d7028a18567b8a980fbf677db2845d9f3befe0dbfd139a743b11b59614286d6b7032e8707ed5ea0d8b98474ffdbf50c93b0ba8bb567626fce25fe25236c030fb99bf19f88368d64efe5239b6c2aba6ea99a02941d723ce49a2de6f4c2024d46aae9965fff64cda51d9c6d2ce93508fd17f76c378863916a192dfd0d96f1d9309b05eb7dab4e7c8fae1c13f74846d7905cf513ab58e18f8da7f0a766cab3d30b77bc72ff55177939af1b8ada4fc54fd72a5e53ec14fbffa5abf7ce318260209296a3927263174bc0b4b88be44a50d67d42316b56a", "258", "d613243338f817fc296f4d77a5a0fb313a92e268427185cf747ff901ce82a959d2845b078d69c983da189f5a2ab8668a0a0cf324f3ea823ab6e018c61c15a177bc3506a093b0d0de123926214793aa9bb1e2a46410ac8aae0cc8c4c24384818354dfc16a66892621fa4fd13d9c610cffff96afefa3b2ef49a06f1b1a122e8070ef3bd2913dc29eefe57306d7c3f3f78316f86de346bd0d68a15c9d64b8a89bd3835c55239f49b5324c55bd593fa8b2c75387b41743aa8acd6e76af92d015d256162279140b16f9d00e73a76b777cb3e3ed1594658e7237c10eee9ca79c385c1708b3485588dcc76501c911c7c392f8a8b7a8cda529daa678f497057eef1b430c890c880fb128d5162f1b8dc7f7d1571b929da5cb2cf1f775fc32e6c714d91e608f40a4ee16229870ae52c8d4d7028a18567b8a980fbf677db2845d9f3befe0dbfd139a743b11b59614286d6b7032e8707ed5ea0d8b98474ffdbf50c93b0ba8bb567626fce25fe25236c030fb99bf19f88368d64efe5239b6c2aba6ea99a02941d723ce49a2de6f4c2024d46aae9965fff64cda51d9c6d2ce93508fd17f76c378863916a192dfd0d96f1d9309b05eb7dab4e7c8fae1c13f74846d7905cf513ab58e18f8da7f0a766cab3d30b77bc72ff55177939af1b8ada4fc54fd72a5e53ec14fbffa5abf7ce318260209296a3927263174bc0b4b88be44a50d67d42316b56a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-7bfaa447e89d31a33317733ef0be9d795c08a7e0f70f5ed9d0ec6816f5a42d8f9484d4be2f113c657e7f4bcfdf73d8a1b22d0d635bfba772b585b4186a4c3e7a80d4d67bad34b75336ae2141802884775e98e1794c958cdf7acd1a53d320052fe0aa942953a4aeca0b910028007fe1fdcfbb9ec7912f4c03e76e5685791675f7ce6794372b0626906e76ae0b227e3f656e64b43c9b7740ec20e87384bc5772710a19ed8549f823b4f6fe5d95cc1fa8f80d5938e23ee60f81c0b47830c18ed587909abad14d718f2f661d2095e11728a7849dfd6752b5b0f154bf76ec61ab917f586d48e6d62af627570747cdb797d1836f6e30c50b64fae46fac54e8e1cc7a4d73ea4e653aeacd47bbe3270859267bb8ae7025d0474cd39548ee09d4baa35beebbb3ec36d61604d473e05a59b598d8e37035116f184e0827f05dabc554f7d9bac7980fe08a182200ab2e8041103594eb7b53ac8fa25c32685177e67cc5c1d51db1452f920f9711c7451e455cae00ccb0f5f52c6e737549c1941583cf8158209bdf7f7aee75835c31cc295ac934d077b4b1850524e67108b040504c77eabf47e3651f59f0e32c6aefab95a89e1ea0882762889578c6577d4b7e267a4c6d2c537dbb1cc258e32b3eee6408bf04393270b75191729e5f75bcff766825c4c36877ffec244d838cd09ef6e66cbf33b195d46c73a9cbaaef2691e3513cbbeaa965d535", "258", "-7bfaa447e89d31a33317733ef0be9d795c08a7e0f70f5ed9d0ec6816f5a42d8f9484d4be2f113c657e7f4bcfdf73d8a1b22d0d635bfba772b585b4186a4c3e7a80d4d67bad34b75336ae2141802884775e98e1794c958cdf7acd1a53d320052fe0aa942953a4aeca0b910028007fe1fdcfbb9ec7912f4c03e76e5685791675f7ce6794372b0626906e76ae0b227e3f656e64b43c9b7740ec20e87384bc5772710a19ed8549f823b4f6fe5d95cc1fa8f80d5938e23ee60f81c0b47830c18ed587909abad14d718f2f661d2095e11728a7849dfd6752b5b0f154bf76ec61ab917f586d48e6d62af627570747cdb797d1836f6e30c50b64fae46fac54e8e1cc7a4d73ea4e653aeacd47bbe3270859267bb8ae7025d0474cd39548ee09d4baa35beebbb3ec36d61604d473e05a59b598d8e37035116f184e0827f05dabc554f7d9bac7980fe08a182200ab2e8041103594eb7b53ac8fa25c32685177e67cc5c1d51db1452f920f9711c7451e455cae00ccb0f5f52c6e737549c1941583cf8158209bdf7f7aee75835c31cc295ac934d077b4b1850524e67108b040504c77eabf47e3651f59f0e32c6aefab95a89e1ea0882762889578c6577d4b7e267a4c6d2c537dbb1cc258e32b3eee6408bf04393270b75191729e5f75bcff766825c4c36877ffec244d838cd09ef6e66cbf33b195d46c73a9cbaaef2691e3513cbbeaa965d535000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "7b4fe7c6de7549f6f055aabe056316065aaa3ad9d5dfef650e18e7e7e6555055dad82ad6a9f03095ad076e15cd92a03919161f4b41c3104e3e28cc87d385cfcfb366afda9962a9429a44f587d78a47a932a7862d0beb94ef648cb71fa5849d5583b6ec2abdf9b19eda5905b13ab3afaa3bca23fee68dfe0ea98fd6ba1a7c1145b02d27fffcbf7c5d02cf868db347baf10ed05bef49636290a8c3a923798c83c8783cddb2f85d06867e145c19351f8c6033daabadc9840e297b775bf2ce23b4459064572cf2d1f71bca272e1eb40327eddc8c5f444f04b4a2d88886eb96c6d2937821e228e07a17b022802dc6c95a5e2506098d81749cb932335075717dd5fe10d94dfca544b7474a78a287dcd9a7091cab987bab21d57326eec98c879e4e98bc014188ce5b65b83359a678cb979f839e4e0a0cb291c220e4190ed659e97040d47e04a50a408254af74babab6021e1580197d31d799634ae92f022b80971ca1a2062c7b8662f97e903555f339fee6fcfc3f032f25c184afb1afc94ef5841295f6b6ece68ef41f375ca26c5779bafe4c2a8135681a50f6f0ae98f1a566c6f48f2966c54f0d32aad7ead0760341cd5b2d152f2403d5d963d8112ca03ad1db3cd785fc7cd03ef2612505ff1959a2d84482cb22c1402520768f16f4edd264115de2cc94c30de4d20a7920a6365ad2011f6cefa28387a3243183e08dcedc1265d1a17c", "1e0", "7b4fe7c6de7549f6f055aabe056316065aaa3ad9d5dfef650e18e7e7e6555055dad82ad6a9f03095ad076e15cd92a03919161f4b41c3104e3e28cc87d385cfcfb366afda9962a9429a44f587d78a47a932a7862d0beb94ef648cb71fa5849d5583b6ec2abdf9b19eda5905b13ab3afaa3bca23fee68dfe0ea98fd6ba1a7c1145b02d27fffcbf7c5d02cf868db347baf10ed05bef49636290a8c3a923798c83c8783cddb2f85d06867e145c19351f8c6033daabadc9840e297b775bf2ce23b4459064572cf2d1f71bca272e1eb40327eddc8c5f444f04b4a2d88886eb96c6d2937821e228e07a17b022802dc6c95a5e2506098d81749cb932335075717dd5fe10d94dfca544b7474a78a287dcd9a7091cab987bab21d57326eec98c879e4e98bc014188ce5b65b83359a678cb979f839e4e0a0cb291c220e4190ed659e97040d47e04a50a408254af74babab6021e1580197d31d799634ae92f022b80971ca1a2062c7b8662f97e903555f339fee6fcfc3f032f25c184afb1afc94ef5841295f6b6ece68ef41f375ca26c5779bafe4c2a8135681a50f6f0ae98f1a566c6f48f2966c54f0d32aad7ead0760341cd5b2d152f2403d5d963d8112ca03ad1db3cd785fc7cd03ef2612505ff1959a2d84482cb22c1402520768f16f4edd264115de2cc94c30de4d20a7920a6365ad2011f6cefa28387a3243183e08dcedc1265d1a17c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "eead27a7c7094439f2d45b85b25f6435747cc5135e5c3f144f18cc2619075dcec9421b50c1412ea2fd3997ad375a43cc219ae8ad6822c490d5da7238791a24dc3bf41bce3a7ef1b3ae9d9c4324a0ca2235154d40c32b07b6e20bc496d892aad4a522e413a7cfd2c40ca2f38f5a6be8c48d66aa561171a86cfbd806bc70a7950fa4ab01ccbaba58831d25773b8d876a176df35df144bec3c90cac6bc51571e929d391c2b097acb5a586b5cf76c5efb99a62708eec6f0a401a21e44d40610b6c55284ffd6a2015c497bd34bcc3f73c1fe2458826de42540d1d87c6cbe97534fe1fd10b949572c30d4ecf9c17e1a68d82a70cd17c0cb964c22fef686d12ca28950fc04df91c4409f078819bfb74bca7619c2d5f23339ab746bfdb7359d34809bbae813d080011988e4cbf9d7e8294189c28a2eedf116fb7398556d0a2fc815473f007d6e64305004d98827321d48fc9b450ebfb552a43a4d2ccae5a2a01118a8148b2dd1c08723dffaef827c7d1c55245df36630b23397f892527c8e0f4f091bc3f701508996aed79310e7a1682ce20c7ed5b954963cbc27792b6b1a5ca8fec16f47d39451a8dad73023294a3c41b0ae037e70e37003b47d2e18397d5098ebbbd3f991562f14d0f66edb4693e5a4e1ae84cf491007d1015b1b4cae21d7671019bc0f5e6b652938768178d57e9d183cfe7974606cc24ff8d709899bf72fe5537574e", "168", "eead27a7c7094439f2d45b85b25f6435747cc5135e5c3f144f18cc2619075dcec9421b50c1412ea2fd3997ad375a43cc219ae8ad6822c490d5da7238791a24dc3bf41bce3a7ef1b3ae9d9c4324a0ca2235154d40c32b07b6e20bc496d892aad4a522e413a7cfd2c40ca2f38f5a6be8c48d66aa561171a86cfbd806bc70a7950fa4ab01ccbaba58831d25773b8d876a176df35df144bec3c90cac6bc51571e929d391c2b097acb5a586b5cf76c5efb99a62708eec6f0a401a21e44d40610b6c55284ffd6a2015c497bd34bcc3f73c1fe2458826de42540d1d87c6cbe97534fe1fd10b949572c30d4ecf9c17e1a68d82a70cd17c0cb964c22fef686d12ca28950fc04df91c4409f078819bfb74bca7619c2d5f23339ab746bfdb7359d34809bbae813d080011988e4cbf9d7e8294189c28a2eedf116fb7398556d0a2fc815473f007d6e64305004d98827321d48fc9b450ebfb552a43a4d2ccae5a2a01118a8148b2dd1c08723dffaef827c7d1c55245df36630b23397f892527c8e0f4f091bc3f701508996aed79310e7a1682ce20c7ed5b954963cbc27792b6b1a5ca8fec16f47d39451a8dad73023294a3c41b0ae037e70e37003b47d2e18397d5098ebbbd3f991562f14d0f66edb4693e5a4e1ae84cf491007d1015b1b4cae21d7671019bc0f5e6b652938768178d57e9d183cfe7974606cc24ff8d709899bf72fe5537574e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "f19a078b12eb3ef03aefbc917054bbe8f8fd76a932256a91d414b1c439e710a455b72a6187bbc37accdd510a836e75bf738f4ce42695974ffdd262ad090c8f9aa312ee47bfe35c376affd866e481a4f70af67edd819dbbf3490f256e14c34b15ae6137499a4fb153a16c0e37e0d9929a2e8eaf285fbf7c02dbf7f8a2c761a728091c80b7493fbed091586bf63d233fcca9b7033d59c288368aef2ff0339e8ae2d153dbc5e83465549bbb18ce66ddfb8d1317ee59ba769682d16cd2d6ed6006531b82b1d3af75099d6f5296478053ff9c24e4ef497190193bd7baf314eb68574ab4938b5904f139d26702cac3c20c7bd40613a20e713476acf5ec24af9ba6e2d83d73767fac76898b551f2d74c4587a926d54637f27f8fee526ec851394ff49cdbc23f493988f82a29f8f0643d31d1fb279a5bba5fb1c006d17c75ad03ddcff290d93df537a31812261a8bd4a4b39ce7c81dd65f8ae73b8ffd04b68b3275c2e91175725b00ed92371dd7f9ed93a9b96622dc55d01ce8f43be09d364a9c5c7259e7fe383f8950c8263c568d35775490a34631c9da03c062cc89512b7bd2fb308c30a0930dc6a6869d1c6695bbb45505e8ff07ae2e6da1674e9fd7b99ca010eeeb2cf94a1127268ffc8acf12193e39e8272f7cc52d838d8921b0646fde22b6d88f08458e1c4d7562ca5ce07113d46f500eedc728109fb2a6d38dc7c79e583b66530", "12c", "f19a078b12eb3ef03aefbc917054bbe8f8fd76a932256a91d414b1c439e710a455b72a6187bbc37accdd510a836e75bf738f4ce42695974ffdd262ad090c8f9aa312ee47bfe35c376affd866e481a4f70af67edd819dbbf3490f256e14c34b15ae6137499a4fb153a16c0e37e0d9929a2e8eaf285fbf7c02dbf7f8a2c761a728091c80b7493fbed091586bf63d233fcca9b7033d59c288368aef2ff0339e8ae2d153dbc5e83465549bbb18ce66ddfb8d1317ee59ba769682d16cd2d6ed6006531b82b1d3af75099d6f5296478053ff9c24e4ef497190193bd7baf314eb68574ab4938b5904f139d26702cac3c20c7bd40613a20e713476acf5ec24af9ba6e2d83d73767fac76898b551f2d74c4587a926d54637f27f8fee526ec851394ff49cdbc23f493988f82a29f8f0643d31d1fb279a5bba5fb1c006d17c75ad03ddcff290d93df537a31812261a8bd4a4b39ce7c81dd65f8ae73b8ffd04b68b3275c2e91175725b00ed92371dd7f9ed93a9b96622dc55d01ce8f43be09d364a9c5c7259e7fe383f8950c8263c568d35775490a34631c9da03c062cc89512b7bd2fb308c30a0930dc6a6869d1c6695bbb45505e8ff07ae2e6da1674e9fd7b99ca010eeeb2cf94a1127268ffc8acf12193e39e8272f7cc52d838d8921b0646fde22b6d88f08458e1c4d7562ca5ce07113d46f500eedc728109fb2a6d38dc7c79e583b66530000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ccbaae56971ab1c77d986bae3a46f5cf8d6427e122991f89e3f5a98cbf35c9236c3ac435d4842ea5a4c451ad2cdf8520eaee29b24665d41f98aad0149e4becc3267ebcea9373780fd86836e926646e53e81fdf94eec0fefe458a32e1f7fb710d0dbfeb9398d676ec9cb6fff73b438bd20f486a5111a529d451afbc2ef8441c76e25bd64bf6c904e2c448f1391af2c5975000e4ea39bcad225bedb6749c02126a39a6e15bd57675e5720cbcd2937750433d1d198696d8a445e69234391e2166a2bd72b670144eb8c834191d317b443acd2389b66f30f9d9e7bd6258ae911af7a3e1e396a736c419ecaf97ca6f0f92d848896f3a3f5139ac2e586136b34d6d7930808b5dd322048c7c80e4fcb5d0cf3979fe13ad3dec731d0d9f09acdbd2620220fe0a1c183b3dab22ea7eb8ae4557ace7b12ba54f0696143360e1752f5340d183fd99f3e7d8bb491b694e3b22dae1c0b15b976642e9b1ef434a2e69df4a8c8be78f0f0485243f3e1d72afa60d2b09d0deadb9f7049f531be0916b1e5609411331504a6ef35fdc7c2424c7d9e17d428074f9b0873e81f7a570650f311fc889be69db247c2bd9535ea8d8655c8234f8bf35a99a901e22c6d61ced789ed1b994ca43d2134d2a1196f6fdb661da0774d335f3c4f71b250aa8a812372434840a0b6e7104c713923aa35bf1231121b049318cc8839ccac0698f9b17bd63d141403a353a", "78", "ccbaae56971ab1c77d986bae3a46f5cf8d6427e122991f89e3f5a98cbf35c9236c3ac435d4842ea5a4c451ad2cdf8520eaee29b24665d41f98aad0149e4becc3267ebcea9373780fd86836e926646e53e81fdf94eec0fefe458a32e1f7fb710d0dbfeb9398d676ec9cb6fff73b438bd20f486a5111a529d451afbc2ef8441c76e25bd64bf6c904e2c448f1391af2c5975000e4ea39bcad225bedb6749c02126a39a6e15bd57675e5720cbcd2937750433d1d198696d8a445e69234391e2166a2bd72b670144eb8c834191d317b443acd2389b66f30f9d9e7bd6258ae911af7a3e1e396a736c419ecaf97ca6f0f92d848896f3a3f5139ac2e586136b34d6d7930808b5dd322048c7c80e4fcb5d0cf3979fe13ad3dec731d0d9f09acdbd2620220fe0a1c183b3dab22ea7eb8ae4557ace7b12ba54f0696143360e1752f5340d183fd99f3e7d8bb491b694e3b22dae1c0b15b976642e9b1ef434a2e69df4a8c8be78f0f0485243f3e1d72afa60d2b09d0deadb9f7049f531be0916b1e5609411331504a6ef35fdc7c2424c7d9e17d428074f9b0873e81f7a570650f311fc889be69db247c2bd9535ea8d8655c8234f8bf35a99a901e22c6d61ced789ed1b994ca43d2134d2a1196f6fdb661da0774d335f3c4f71b250aa8a812372434840a0b6e7104c713923aa35bf1231121b049318cc8839ccac0698f9b17bd63d141403a353a000000000000000000000000000000", .None}, + {.Shl, "-a3a542cb7965ae4d6f71717a7ffb254e922d215f80cfc8126d26bfe873b975e39260cc2d06a252c12c81ac61c1c43ec60667ac53dc86b3b901d79ca905a2937e5ced17b89d8e5ffbbb9d4fd26ce01a22ba1bb2e3b693ad207446c7dc15552b4b5ee439be531c5bdca22ebfb1b14df29a4b71162d0b176290f23f92bfc2f57d8e260d09524a29c3f11752d90cd075e46b0b958614e61e248030dfd4eb24440ecfc05591e94a5eb4669dbb508f71d450d7b9c2e7922806866810f3ce8720e9b27f63f7a8cd3337d4064734954ce3d03c1cf467fe9063e65822cb92c14cb7e989362b95b0643b8a9e5559d998356cf2c1e544fb99cb96fb8ee661d05de821fae4776f545a7e99b6dabf88bd9c4c213b147e1aa22093718aa8b7e2d91ba65697b6053d934b0eda35cb9945a8b17e00ac515731a41f1d988c3fbcb271609308f5419b6a700f8e337b4f2c5feb91dccccd2c872efe5b7b447be849b0281d0f09b6f2ef7aebbc613d3bdd3733fe0ee137ed89c39ca9d459abd9c699cecd9f8ddb578e8fd626a6f1270d51996b24616ffbf98b7416d7e698f12c69a055132035195f4bacc5113d576ed509427294a10479adc960cf71634323924c1df7d002088174412f66aab8b5dc30eb654d15ace89df7f8b039b0c23e2ff3e0a334556a01af2c8977725a5cfe75fd124909794eacf42b74261763f92549cd049725e8a4ce22e20e41", "258", "-a3a542cb7965ae4d6f71717a7ffb254e922d215f80cfc8126d26bfe873b975e39260cc2d06a252c12c81ac61c1c43ec60667ac53dc86b3b901d79ca905a2937e5ced17b89d8e5ffbbb9d4fd26ce01a22ba1bb2e3b693ad207446c7dc15552b4b5ee439be531c5bdca22ebfb1b14df29a4b71162d0b176290f23f92bfc2f57d8e260d09524a29c3f11752d90cd075e46b0b958614e61e248030dfd4eb24440ecfc05591e94a5eb4669dbb508f71d450d7b9c2e7922806866810f3ce8720e9b27f63f7a8cd3337d4064734954ce3d03c1cf467fe9063e65822cb92c14cb7e989362b95b0643b8a9e5559d998356cf2c1e544fb99cb96fb8ee661d05de821fae4776f545a7e99b6dabf88bd9c4c213b147e1aa22093718aa8b7e2d91ba65697b6053d934b0eda35cb9945a8b17e00ac515731a41f1d988c3fbcb271609308f5419b6a700f8e337b4f2c5feb91dccccd2c872efe5b7b447be849b0281d0f09b6f2ef7aebbc613d3bdd3733fe0ee137ed89c39ca9d459abd9c699cecd9f8ddb578e8fd626a6f1270d51996b24616ffbf98b7416d7e698f12c69a055132035195f4bacc5113d576ed509427294a10479adc960cf71634323924c1df7d002088174412f66aab8b5dc30eb654d15ace89df7f8b039b0c23e2ff3e0a334556a01af2c8977725a5cfe75fd124909794eacf42b74261763f92549cd049725e8a4ce22e20e41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "d3c9c6fa0297edd8f3fb9ca346a7bfbff1e954a630c73148f1f1d642d38682dc7e459cdb109743aa6e1af7449302280ad00ae53fa19d8c3d6ccbd50593b9754416f7ffb301be21be04c667e260ad2d1378088c50eab3a997fab8b59706a4836ae57929e5d3b19bb73ffa22b7d7bc548fa28553117f06e116665c9a5ab05fe4acf0b7292559cc511cf7fb11bdb46b8814a9c413e372333564b15c4c41353817df1c325eadbdbdc29d8c121cf2c097ecadf70d83f9521d6e69efda98aea418c41d7b56d8a4cf04b3f193f274451c267b36c4208ffa383bc12c7130ab021a7d1376e1edb6f4c933934e213f4fc6fe2c74bca1403c87262b653c884f5af458e2c5fcbb81b763f9755c0254542fa8b3d13461cebaee3456f8572f933e5180cd35701cd7f61d3dd5a7720f8203a38a7ecff28e6d0085deb0dae23e846a8670b743b3fcbe8354d3d3752971b30fdfbec181808c907fec1a54d3a270736617f21de298acd183da20727ae8ac20075e50f6dba8f8ebddaa07ab3fd6dcc11c54da1ce07a6b31434051ee34e07679d08853cd493c912e49a74305a186943efb829b2c38cfa4e2bd474e7921c6b7958c522e4a075b96c50b8636c0625de37cac9127ae4e3dabe2bff552244d10504e7425c1492a1dd2e7815a4e9af8fd1d2f38330ebb872a30a866c3e13b40a958b173915b96107e0fdd810793b1085a9ff50339c85e5339e9", "12c", "d3c9c6fa0297edd8f3fb9ca346a7bfbff1e954a630c73148f1f1d642d38682dc7e459cdb109743aa6e1af7449302280ad00ae53fa19d8c3d6ccbd50593b9754416f7ffb301be21be04c667e260ad2d1378088c50eab3a997fab8b59706a4836ae57929e5d3b19bb73ffa22b7d7bc548fa28553117f06e116665c9a5ab05fe4acf0b7292559cc511cf7fb11bdb46b8814a9c413e372333564b15c4c41353817df1c325eadbdbdc29d8c121cf2c097ecadf70d83f9521d6e69efda98aea418c41d7b56d8a4cf04b3f193f274451c267b36c4208ffa383bc12c7130ab021a7d1376e1edb6f4c933934e213f4fc6fe2c74bca1403c87262b653c884f5af458e2c5fcbb81b763f9755c0254542fa8b3d13461cebaee3456f8572f933e5180cd35701cd7f61d3dd5a7720f8203a38a7ecff28e6d0085deb0dae23e846a8670b743b3fcbe8354d3d3752971b30fdfbec181808c907fec1a54d3a270736617f21de298acd183da20727ae8ac20075e50f6dba8f8ebddaa07ab3fd6dcc11c54da1ce07a6b31434051ee34e07679d08853cd493c912e49a74305a186943efb829b2c38cfa4e2bd474e7921c6b7958c522e4a075b96c50b8636c0625de37cac9127ae4e3dabe2bff552244d10504e7425c1492a1dd2e7815a4e9af8fd1d2f38330ebb872a30a866c3e13b40a958b173915b96107e0fdd810793b1085a9ff50339c85e5339e9000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-cf9b7d84cb5c3e92317ee7d83922e7e5c3236f8f1c2fd53729795e1302e00866ad78e979d1b881064c18e0f1a2871074c5e741563865357a40bd312f4116e25b48c6ffba95012a7a4a4a4537f213164a00164972f9566f77006e81739caf74ae0c41be11c9e4f6b11a428f580683d8f2dca8adf2ed91aceb112145e2e6a8a9f255462ce62ce266b09e0b91077c3b721418fa649572eae2e454f29af76b6871f59bb811df86a93fe73533ab4d044a017ae480e6d55c585d71ee755b7711b5e34639978b6e3cf2700fd20d8b5b59698e60ee0a9ee64dd3c4f388aa1d589645d5ff365e841d30846f12e18e52c17459c7fe6f52f2dd55f20f24fb4990dafb7f962d11eeb464352ae9240d0017d00a61ed0a7e3ea62ba0832a489b6c7016c822665607a3f780aaef5c7c8ce697723b973d0ab4b5067d45f3e2605306bcb5156f274771b8b9845c5fafe1c4a2a016c1682ddd85864f66a7d9a9bfdd6fe2a908e8bafdf964a72fcde2ab131b2bb2aef3478e54da8d41404f64d556bb665210e26405650cd37c5bc89be1c0642bee57f278995d331249a8eb44647b9a35affbadad7ae6888b180df3ed6a721728aaedfb12e795fb63e7fe76ab9520c71d62e3ee874cbd3e5c115cdc118af93e1ee451a1d2dce8775ad8cf0e07b7610779ab0669eaa81a11dc85bdbe25dbd6b366e9d2d4d199a2a145a27473f8490ac989df046a78e7b0", "78", "-cf9b7d84cb5c3e92317ee7d83922e7e5c3236f8f1c2fd53729795e1302e00866ad78e979d1b881064c18e0f1a2871074c5e741563865357a40bd312f4116e25b48c6ffba95012a7a4a4a4537f213164a00164972f9566f77006e81739caf74ae0c41be11c9e4f6b11a428f580683d8f2dca8adf2ed91aceb112145e2e6a8a9f255462ce62ce266b09e0b91077c3b721418fa649572eae2e454f29af76b6871f59bb811df86a93fe73533ab4d044a017ae480e6d55c585d71ee755b7711b5e34639978b6e3cf2700fd20d8b5b59698e60ee0a9ee64dd3c4f388aa1d589645d5ff365e841d30846f12e18e52c17459c7fe6f52f2dd55f20f24fb4990dafb7f962d11eeb464352ae9240d0017d00a61ed0a7e3ea62ba0832a489b6c7016c822665607a3f780aaef5c7c8ce697723b973d0ab4b5067d45f3e2605306bcb5156f274771b8b9845c5fafe1c4a2a016c1682ddd85864f66a7d9a9bfdd6fe2a908e8bafdf964a72fcde2ab131b2bb2aef3478e54da8d41404f64d556bb665210e26405650cd37c5bc89be1c0642bee57f278995d331249a8eb44647b9a35affbadad7ae6888b180df3ed6a721728aaedfb12e795fb63e7fe76ab9520c71d62e3ee874cbd3e5c115cdc118af93e1ee451a1d2dce8775ad8cf0e07b7610779ab0669eaa81a11dc85bdbe25dbd6b366e9d2d4d199a2a145a27473f8490ac989df046a78e7b0000000000000000000000000000000", .None}, + {.Shl, "-3075592d967fd565d388f2a04e195a3413df726639940ac4189b3595ba77d702450e72383f72dfeded32fbb5c15c966a939845f77b4a73878329ac39b5df7723903dea6cd3b01fc03a6a44f99fa1a2060d8f1f55f4813118c755260b1731ed505a272a57b0fe293ed1282b43d0154dbe0d0a2b1b4b1b2b9d3b7db568d8668f58cecbb090f82127c5b2b059fa889aa27c4fedbed06d9533cace4cadf8bcda5990cbf5f4a37a7ba4d851b010290eeca8c50226636e599e4dae01f14b7eb6e8281ad41d9aec4ee990fe3ed2146d909443fd2681fb818580e851c7a81d0eea9f3016a07022aea0ba862d9dfd9a5b03240d3bb805ca3e0ad725262c1cfb55251cde0d035769d9dfb12ba9051a8286602fb40ab4f0b2dd3f7e8bb38184a0818d209645d5442ed1bb0de7363b9bba1913edfdeb7c12977bce562de97f67b44b1c7a9eb021cc2fb9724b1900f18c529b7efe10d580f778e7c12149ecdc2c74f084d374262a580fc56e1689d15bc1389e075578255c96179b6505457c4b8b8c991a13f4cb0ee2703c073465130796271b26e501cc5abda93316d03c20c87d8193b8580eb9ed7b2eda86bb8b46d71933574c1c5380be232f164479b2c6de4e683baab6e584a407b77835d6b034491bcf200e2f46aaaf29c6e3ada011eb2afdd55c6c3eca6d27ec057fff42cd7eae92a4e4deea6308ac85dd40bf9661e3ac94e1f445fd1b6e", "b4", "-3075592d967fd565d388f2a04e195a3413df726639940ac4189b3595ba77d702450e72383f72dfeded32fbb5c15c966a939845f77b4a73878329ac39b5df7723903dea6cd3b01fc03a6a44f99fa1a2060d8f1f55f4813118c755260b1731ed505a272a57b0fe293ed1282b43d0154dbe0d0a2b1b4b1b2b9d3b7db568d8668f58cecbb090f82127c5b2b059fa889aa27c4fedbed06d9533cace4cadf8bcda5990cbf5f4a37a7ba4d851b010290eeca8c50226636e599e4dae01f14b7eb6e8281ad41d9aec4ee990fe3ed2146d909443fd2681fb818580e851c7a81d0eea9f3016a07022aea0ba862d9dfd9a5b03240d3bb805ca3e0ad725262c1cfb55251cde0d035769d9dfb12ba9051a8286602fb40ab4f0b2dd3f7e8bb38184a0818d209645d5442ed1bb0de7363b9bba1913edfdeb7c12977bce562de97f67b44b1c7a9eb021cc2fb9724b1900f18c529b7efe10d580f778e7c12149ecdc2c74f084d374262a580fc56e1689d15bc1389e075578255c96179b6505457c4b8b8c991a13f4cb0ee2703c073465130796271b26e501cc5abda93316d03c20c87d8193b8580eb9ed7b2eda86bb8b46d71933574c1c5380be232f164479b2c6de4e683baab6e584a407b77835d6b034491bcf200e2f46aaaf29c6e3ada011eb2afdd55c6c3eca6d27ec057fff42cd7eae92a4e4deea6308ac85dd40bf9661e3ac94e1f445fd1b6e000000000000000000000000000000000000000000000", .None}, + {.Shl, "8ce2ff2c6288cce038e442f6581b5829a3961df4f51b1b64abcbbbacaa2b9a3b5b15a017b942c26cc2659f02ec13cdf3650e2c203415907a597a29aba49c63546d27b38edb3cc249b986ffdbfd28a17628fc221fe3f8ab1a521d3f3e7ba4236cacf1d7e55a460bc3456c123b8780aa2716d55115251a18f5c2de0c3d8f72d724e027813069472aba55f212b10d55f8ef7dae0a65a9be366bf403ccb1f27f9e843560e111505b046fce71daa3978019dc9b9e475f6811d56bc24f6d4d8049dff52f2d810e53b99cfad5e7d5205f1bed4346c5ada1fdc36887beb88ab77eb2eecd3f75d897451c4445595fdfc81708fdf446b34f26c9d3470adeb49aeef31b9aeeeedbc2931631ac02f8ccd3bb599c260e6572d6e5ab1c2c8ace71d062a4c5490476813f3b386875075547338024ea7b322eae4d00f10f3749fdad98d3bee2acfe73ece78aa7509de5468c5fd723012e37064927f89ea156dea5662de416fcf154b843fa9a8b82cb447b4620f0486c510fb3ebb00bf4280ae888fe01caaf08908506d40214bb476b3825cba9513323e0003376205d4d75a9dbc4413ef254c78640c3a5f01e12d83a2aa0bb4907a24b2c2836b5c174b1c1a797ae5040a9de3e1356a1178f89dc01db53cbb87a1e58ace4b93a95b8f0d2afa0b6e350783780ff0b8b110e0f1eb9268f31c4f3aef6e9a378e5faa315ce5c21b69e972f892ba2230c54", "1a4", "8ce2ff2c6288cce038e442f6581b5829a3961df4f51b1b64abcbbbacaa2b9a3b5b15a017b942c26cc2659f02ec13cdf3650e2c203415907a597a29aba49c63546d27b38edb3cc249b986ffdbfd28a17628fc221fe3f8ab1a521d3f3e7ba4236cacf1d7e55a460bc3456c123b8780aa2716d55115251a18f5c2de0c3d8f72d724e027813069472aba55f212b10d55f8ef7dae0a65a9be366bf403ccb1f27f9e843560e111505b046fce71daa3978019dc9b9e475f6811d56bc24f6d4d8049dff52f2d810e53b99cfad5e7d5205f1bed4346c5ada1fdc36887beb88ab77eb2eecd3f75d897451c4445595fdfc81708fdf446b34f26c9d3470adeb49aeef31b9aeeeedbc2931631ac02f8ccd3bb599c260e6572d6e5ab1c2c8ace71d062a4c5490476813f3b386875075547338024ea7b322eae4d00f10f3749fdad98d3bee2acfe73ece78aa7509de5468c5fd723012e37064927f89ea156dea5662de416fcf154b843fa9a8b82cb447b4620f0486c510fb3ebb00bf4280ae888fe01caaf08908506d40214bb476b3825cba9513323e0003376205d4d75a9dbc4413ef254c78640c3a5f01e12d83a2aa0bb4907a24b2c2836b5c174b1c1a797ae5040a9de3e1356a1178f89dc01db53cbb87a1e58ace4b93a95b8f0d2afa0b6e350783780ff0b8b110e0f1eb9268f31c4f3aef6e9a378e5faa315ce5c21b69e972f892ba2230c54000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "782745376a028c297566d502062b6e486acf979680c64656c4b2a9b95c389522cd0f25af3d15dd89d9ec9eedef6d363a390636dfd4db9542616b6bc8bc3777afaf90e76510f0189d6ab1f442c5617c0717bcb82513d40af7ba3c0edbab9df6be8cee25c140c2f66c5bdacebd546f50d5102aa64c59e79f63fcf55debfad003c72060537d50bc7706cb6e3262fa82aa11988749579211d55336a8333bf8871ca27b4ac0ff0ff87905b009e16f710e3b47a3528f3e379cdf39e18ce3386515fa111b2b9745b041cec380a33485219d5017f4cdf7e3e4ae157aaf9db056c6f049d3eedc17a8dad8bef66bd9bee0b3288755f5c509a29c8474b8e0e543cac2a8658184b2feddb5e1a120aab274608e3bb69d5a567cd39a8831d85df8705fcfa2caf7445deb3fb132acb914561f1aa1a4bdbc7f9bbd6e99edf41aab2979b761c8b9e0ea9ad982ba178be1a996736e02548d34efd78dcdbb41fae73269a0518ba236b5fdca672bba40261f58bdfd67269692c1d3bfdb9f08d0988d5bc297dc1a64b085655dff686a79f39338d61ec545e80bf13b1383ef8fc4c8c3180ab428cf055545cf4a7f15d8d23f803f7b9222417765589ee7d2fde845ee7ec6fb75ff0381fef9552e1b16a64d13e172539a75a967025a5d715a79618baa482a058a703c6c798e1c12a15ed8e1d208f877f35a1ee177a5edbbb8519f40798e165112f8c3820c0", "78", "782745376a028c297566d502062b6e486acf979680c64656c4b2a9b95c389522cd0f25af3d15dd89d9ec9eedef6d363a390636dfd4db9542616b6bc8bc3777afaf90e76510f0189d6ab1f442c5617c0717bcb82513d40af7ba3c0edbab9df6be8cee25c140c2f66c5bdacebd546f50d5102aa64c59e79f63fcf55debfad003c72060537d50bc7706cb6e3262fa82aa11988749579211d55336a8333bf8871ca27b4ac0ff0ff87905b009e16f710e3b47a3528f3e379cdf39e18ce3386515fa111b2b9745b041cec380a33485219d5017f4cdf7e3e4ae157aaf9db056c6f049d3eedc17a8dad8bef66bd9bee0b3288755f5c509a29c8474b8e0e543cac2a8658184b2feddb5e1a120aab274608e3bb69d5a567cd39a8831d85df8705fcfa2caf7445deb3fb132acb914561f1aa1a4bdbc7f9bbd6e99edf41aab2979b761c8b9e0ea9ad982ba178be1a996736e02548d34efd78dcdbb41fae73269a0518ba236b5fdca672bba40261f58bdfd67269692c1d3bfdb9f08d0988d5bc297dc1a64b085655dff686a79f39338d61ec545e80bf13b1383ef8fc4c8c3180ab428cf055545cf4a7f15d8d23f803f7b9222417765589ee7d2fde845ee7ec6fb75ff0381fef9552e1b16a64d13e172539a75a967025a5d715a79618baa482a058a703c6c798e1c12a15ed8e1d208f877f35a1ee177a5edbbb8519f40798e165112f8c3820c0000000000000000000000000000000", .None}, + {.Shl, "-2469691aafa362d31d9fa6fd69d3ea3ea67b7f11bfeea361c6d8cc06587930009bc3bd557edf87836362fca059d16af5a5291a2d8f4e4996105d524a5ddf337c5cc15490ecede2c644f4e4ccca2fb2e383ebbc949a6915a0f0205b1d483b445cfbe2d000e0c3ab30568c693d2481a61d75f1d95d804abfe1fb283790d465003a098d8122090f973dafd173db1e24c3df52b4ec31f56eb53601bcff1b42a0add591c08340b4c6c09c3fe368c4dc5e2877735aaecd84c2aad983a01a118520e72240ff9cf42f60b7b7206fd2fc7dd670c9e7b37af5ef3c02607dfbb2281a32eab82f5b150c2680108e67628f358e0e2a3e6a001a4e98d7b78ba2a6f9346ba080902daa1ffd271866b1ae20096db017547650dc222a07857b6792bb3a03a7ade24fe69dea76e5217c4e228fd2d2c01cc1567a871e59f52e7738782cd48d7530015f5b2b300e3d21238d50c6d5137023f507f56b5bf4a782cdb5e89566b816a8b3f6b2392f82cec5511b679f1da28e87ad21612cb7427120e1eab305fcf739bee6eebdf61dc20aa78ff7cda67ac016b27326ceeffbee460dd3fc5da634c2d86308068b2642443817e8253c45f83ed68061759be00f1571ffae50fc0d82909b0734ee1118a2a046eecff267cb6b39dc06c40407a14aa6dd02382f73665f41d4b2816b3476766c8c3bd0cc11797faafc21ffe798a80d9d8710c511d4b380696b88eba1", "12c", "-2469691aafa362d31d9fa6fd69d3ea3ea67b7f11bfeea361c6d8cc06587930009bc3bd557edf87836362fca059d16af5a5291a2d8f4e4996105d524a5ddf337c5cc15490ecede2c644f4e4ccca2fb2e383ebbc949a6915a0f0205b1d483b445cfbe2d000e0c3ab30568c693d2481a61d75f1d95d804abfe1fb283790d465003a098d8122090f973dafd173db1e24c3df52b4ec31f56eb53601bcff1b42a0add591c08340b4c6c09c3fe368c4dc5e2877735aaecd84c2aad983a01a118520e72240ff9cf42f60b7b7206fd2fc7dd670c9e7b37af5ef3c02607dfbb2281a32eab82f5b150c2680108e67628f358e0e2a3e6a001a4e98d7b78ba2a6f9346ba080902daa1ffd271866b1ae20096db017547650dc222a07857b6792bb3a03a7ade24fe69dea76e5217c4e228fd2d2c01cc1567a871e59f52e7738782cd48d7530015f5b2b300e3d21238d50c6d5137023f507f56b5bf4a782cdb5e89566b816a8b3f6b2392f82cec5511b679f1da28e87ad21612cb7427120e1eab305fcf739bee6eebdf61dc20aa78ff7cda67ac016b27326ceeffbee460dd3fc5da634c2d86308068b2642443817e8253c45f83ed68061759be00f1571ffae50fc0d82909b0734ee1118a2a046eecff267cb6b39dc06c40407a14aa6dd02382f73665f41d4b2816b3476766c8c3bd0cc11797faafc21ffe798a80d9d8710c511d4b380696b88eba1000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-24c2529c6cec31e03691cf8080e592f19fb5641fa89c49235496e75eec189ca531f368ffd6107fd0da2c63748eb039df690123f16422e534e45efcfbb04e8d023398960af3cc71eb3e078d8185df5ade89f8b7a4f3bfad4b8311f67fc3f94cbf79e576feb06e5ecbef8b2f45009230b4ead5fc193a6e92436bde4d82cedf9b081df45b0734822789524ca881a29d7ab739267df524c6bfc922485d58b3e9dbd77a3015cd69212ce09857afdd0445f4b25d3cd92e0953950fbfa405c4fdeb864d3047e7a7e35444dc6480ec89b12291a623aabaf0eed994f96ccf19bb5d7f1e6f17d710283c7dcdf9f834a8a2eb3355b487af291b60634daa8daf7d83cdf990cba9085051a82343f619951c291c656b709e18150d86c1212ed359367377e254ae465e422f685566775a84a93cd59e0f1a6f9e773a0b2f0f4e653564da2892936d829575bb7cf063b0a39857b79465fca255045c7a630acc579507b9bbb9d105936f1922a0d3ec59ad0733a498c06971c4237d34e30547d45b3564d28aae5b933a1b1758145574aaa51bfcbdd3ceda20d10220a671a3725a9aca9ccb7e9e6a49e54b4390bb5779198771f93c9897e96c79a714a87d72898f5b2ec3e212a32b0851fff7bcffff6f2a1e4059e79634169c160bf4132de6a1ac546836afe0467f5bb85eb96b3d7c1ba37b6a553135b8098ba7f41babeaac4db106ccfcd6d165406a94", "78", "-24c2529c6cec31e03691cf8080e592f19fb5641fa89c49235496e75eec189ca531f368ffd6107fd0da2c63748eb039df690123f16422e534e45efcfbb04e8d023398960af3cc71eb3e078d8185df5ade89f8b7a4f3bfad4b8311f67fc3f94cbf79e576feb06e5ecbef8b2f45009230b4ead5fc193a6e92436bde4d82cedf9b081df45b0734822789524ca881a29d7ab739267df524c6bfc922485d58b3e9dbd77a3015cd69212ce09857afdd0445f4b25d3cd92e0953950fbfa405c4fdeb864d3047e7a7e35444dc6480ec89b12291a623aabaf0eed994f96ccf19bb5d7f1e6f17d710283c7dcdf9f834a8a2eb3355b487af291b60634daa8daf7d83cdf990cba9085051a82343f619951c291c656b709e18150d86c1212ed359367377e254ae465e422f685566775a84a93cd59e0f1a6f9e773a0b2f0f4e653564da2892936d829575bb7cf063b0a39857b79465fca255045c7a630acc579507b9bbb9d105936f1922a0d3ec59ad0733a498c06971c4237d34e30547d45b3564d28aae5b933a1b1758145574aaa51bfcbdd3ceda20d10220a671a3725a9aca9ccb7e9e6a49e54b4390bb5779198771f93c9897e96c79a714a87d72898f5b2ec3e212a32b0851fff7bcffff6f2a1e4059e79634169c160bf4132de6a1ac546836afe0467f5bb85eb96b3d7c1ba37b6a553135b8098ba7f41babeaac4db106ccfcd6d165406a94000000000000000000000000000000", .None}, + {.Shl, "-4c82aaad6ec61430ce756ad145ccf7bb915c9042a3d42dac5dfa0a40ebb31cf4c885cf0b13a2ef39ff3fff858a1d2571e39314b503f8d26ed4897ba1eacf91e6c5e0ab63659c53ab99e8b09bcfba636dc37870f328c26b208f3254266d1997570fcb845453722e7d2bf0d1c0133b610498110ddee517912c1ba50e859e57343239d2f928d0b8cb31b43996066aeef9939c06a03fce703251266cd9f28306c751609efae7217f3c512b45031e15e35b922d7c433f0db657c59400f78a67850374daa4abf3160bef63d3e34ce4bb3d18cc57eb799d3669eaa38a88d1feb45fd2eabbf2cf7d51f19ae00af6e9e7289d289a8ddd8b02512e70ea87d2b82751103de2f299ccf5b979ea1b0fb6cc542f6e86826ef6ac96353b5391109270c2b81033a6408cec551a1cc548b006f07f623132c01be7a9e75925bf87953b6a35e03914a9ca9b7193816abdd340217b8d5138aef862fd77c78daad78c9fb5172f820484b766e5ab1374ac442672eb851d5b542e1194b5e09876b0cbbacd7020c3e3a586f322d03c2781ff34e2379dba837dd3da3cb380a6dce6ae1bc3d332e8246524bae55294264998ec9f8c2fc8a175f9bd5049dc2300328d7c604ce8e2e421a11a0509567d8ea4104112e2b95f24f8fef144658a57fbbb57726c66dcb18220ebc5923b3f33c256df49b3746476ba6a5615c3ab0d37c1bb1948d4c9e97d0fbad634338", "78", "-4c82aaad6ec61430ce756ad145ccf7bb915c9042a3d42dac5dfa0a40ebb31cf4c885cf0b13a2ef39ff3fff858a1d2571e39314b503f8d26ed4897ba1eacf91e6c5e0ab63659c53ab99e8b09bcfba636dc37870f328c26b208f3254266d1997570fcb845453722e7d2bf0d1c0133b610498110ddee517912c1ba50e859e57343239d2f928d0b8cb31b43996066aeef9939c06a03fce703251266cd9f28306c751609efae7217f3c512b45031e15e35b922d7c433f0db657c59400f78a67850374daa4abf3160bef63d3e34ce4bb3d18cc57eb799d3669eaa38a88d1feb45fd2eabbf2cf7d51f19ae00af6e9e7289d289a8ddd8b02512e70ea87d2b82751103de2f299ccf5b979ea1b0fb6cc542f6e86826ef6ac96353b5391109270c2b81033a6408cec551a1cc548b006f07f623132c01be7a9e75925bf87953b6a35e03914a9ca9b7193816abdd340217b8d5138aef862fd77c78daad78c9fb5172f820484b766e5ab1374ac442672eb851d5b542e1194b5e09876b0cbbacd7020c3e3a586f322d03c2781ff34e2379dba837dd3da3cb380a6dce6ae1bc3d332e8246524bae55294264998ec9f8c2fc8a175f9bd5049dc2300328d7c604ce8e2e421a11a0509567d8ea4104112e2b95f24f8fef144658a57fbbb57726c66dcb18220ebc5923b3f33c256df49b3746476ba6a5615c3ab0d37c1bb1948d4c9e97d0fbad634338000000000000000000000000000000", .None}, + {.Shl, "-82fd7863ab12a0f29ea5ad26086ef41c0f1afd5fe4ccde0d76a548e973d69f46e03ae377cf503582d786c56f84a4b32ee9fe4c949a7de6e4f3583951c881f84d22b1575b3dafb954e4132a7daff00281a2de0527802011fd37b9758c251e54631b143f2dfff02150fbcfc0264edd76d9bf6e56e643ff8b9feb10ac41d5a1c8005502fe66f43611835f7590b8fd92d539135b3946202f5b025ba40b19a6839f47f80725690971b2ed95a9b16e59894913b7a8d502f571bcf550ba39fe4de0e1050eb23ecbd1baeac7347eb2b0d51dafe47b6a0bb31df9c44de1b5b18a422a92f9bd9f74b21defe1316141e1c1e88b78f564c04eb56b7959990b744653f17d15c5d93a730bb940fa83925aa47345b41bdeaeed15cf2f9395c4af913c2ddff71e91be6ab1c782f0946e16c7b7c183e989c734f53a0c23c03810bde88fc76c8c5830f988b449a6ff3f4a10eabedac9c98c711c9ae499097242a47d3548182e79dc32007158431fc002671503d5d25b97b7ea5482e325356253d41795c006c77047d720f44427dbc11d11265c6cad8e51e46f8968c01ed79d55e7924ef8cd61b0df42c244701064c637f755e3a46258e7a0b16efc5176a9d540433b678a4e411306e5e29e9991e44632be00e30e8b5938013d96b68c89f1c29f574446fccdf8f0c4d56311a8b2d4ab3d7485c66c70562c4e5d13c9ca963a3036302181cd1c4665ca9d", "1e0", "-82fd7863ab12a0f29ea5ad26086ef41c0f1afd5fe4ccde0d76a548e973d69f46e03ae377cf503582d786c56f84a4b32ee9fe4c949a7de6e4f3583951c881f84d22b1575b3dafb954e4132a7daff00281a2de0527802011fd37b9758c251e54631b143f2dfff02150fbcfc0264edd76d9bf6e56e643ff8b9feb10ac41d5a1c8005502fe66f43611835f7590b8fd92d539135b3946202f5b025ba40b19a6839f47f80725690971b2ed95a9b16e59894913b7a8d502f571bcf550ba39fe4de0e1050eb23ecbd1baeac7347eb2b0d51dafe47b6a0bb31df9c44de1b5b18a422a92f9bd9f74b21defe1316141e1c1e88b78f564c04eb56b7959990b744653f17d15c5d93a730bb940fa83925aa47345b41bdeaeed15cf2f9395c4af913c2ddff71e91be6ab1c782f0946e16c7b7c183e989c734f53a0c23c03810bde88fc76c8c5830f988b449a6ff3f4a10eabedac9c98c711c9ae499097242a47d3548182e79dc32007158431fc002671503d5d25b97b7ea5482e325356253d41795c006c77047d720f44427dbc11d11265c6cad8e51e46f8968c01ed79d55e7924ef8cd61b0df42c244701064c637f755e3a46258e7a0b16efc5176a9d540433b678a4e411306e5e29e9991e44632be00e30e8b5938013d96b68c89f1c29f574446fccdf8f0c4d56311a8b2d4ab3d7485c66c70562c4e5d13c9ca963a3036302181cd1c4665ca9d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-3ed80bc0b2cea2525680fb7c36507a1e329d0b3333994d969f3bdc73e1e86d5adf9da065b4fff22fd7c39de8b2d503a43de3a51c1454592e1f3c56452bc15055d6b1069472dc9ceec476216a79402d3e1b77075a1add94b17ee30c37e1a12a08a3014aa823ce1a931c095b2fc7863fda2e00e86750782863d99604aff81d3876a893140ec9c8b38607199c5018094d295f8fea279feed208fe2abee1656e1c58416bac9c0314aa3e53a9ba006f1109163e257baed3bc6f36429952a68e0730631f889a918b23a3361824ed76e15d0688e0735292b6b3b88427b84ac94e41bc79c9c0830febe026ff14e4d47ec06d723c6dcf73386ff90df7068c4027ad85a62a9ecfec8dd81b762c6990e3dd1000642136bdcd8b0cc7c3133aa7f9822e11071f69bb7a870b14f7c01b8a99d017d0b0b4a1f1a8dfeb3ab1203edbaa303e09f99ebc85b9da5d7277314ce8f4d81c035a3455468036b609dfcff024e311c85ed720382e53513710a70aaa95b8952098258aa15484626ddc21df5c3b624caab1616361a4ef6be9367e1416affd957860e9b0b7385983af70cffc06d5c1117a777103171af6b655f9561c81ac39b9c8d9fd9db2b8ffc9bcc81e8edf2c649baff6f38544f2c7b522d2cf28790338433ef35c18bd4d53bcf0c688e5c77468d8e02d98af1739a5216c78ff130c4e4579130fe01eb5432e96e72f7214b862a37ae405821b", "b4", "-3ed80bc0b2cea2525680fb7c36507a1e329d0b3333994d969f3bdc73e1e86d5adf9da065b4fff22fd7c39de8b2d503a43de3a51c1454592e1f3c56452bc15055d6b1069472dc9ceec476216a79402d3e1b77075a1add94b17ee30c37e1a12a08a3014aa823ce1a931c095b2fc7863fda2e00e86750782863d99604aff81d3876a893140ec9c8b38607199c5018094d295f8fea279feed208fe2abee1656e1c58416bac9c0314aa3e53a9ba006f1109163e257baed3bc6f36429952a68e0730631f889a918b23a3361824ed76e15d0688e0735292b6b3b88427b84ac94e41bc79c9c0830febe026ff14e4d47ec06d723c6dcf73386ff90df7068c4027ad85a62a9ecfec8dd81b762c6990e3dd1000642136bdcd8b0cc7c3133aa7f9822e11071f69bb7a870b14f7c01b8a99d017d0b0b4a1f1a8dfeb3ab1203edbaa303e09f99ebc85b9da5d7277314ce8f4d81c035a3455468036b609dfcff024e311c85ed720382e53513710a70aaa95b8952098258aa15484626ddc21df5c3b624caab1616361a4ef6be9367e1416affd957860e9b0b7385983af70cffc06d5c1117a777103171af6b655f9561c81ac39b9c8d9fd9db2b8ffc9bcc81e8edf2c649baff6f38544f2c7b522d2cf28790338433ef35c18bd4d53bcf0c688e5c77468d8e02d98af1739a5216c78ff130c4e4579130fe01eb5432e96e72f7214b862a37ae405821b000000000000000000000000000000000000000000000", .None}, + {.Shl, "9e9e52051876271269f7283fcd7db208b58e879846313496aefc616d920cf55fdcf94dc6778a25d56e9a757d3a91d03576ef4e33e49c2d88862f0251dc2a0626950b68bf8f5196a52d95e0850653243f1210359007c9a3c11b5bce5a9afaa001527c1c74a769aa719a902cb3b8a50170f83b49f5a9f21c993b6a14bf63a696b29304e14bdff930c658fc1a7fa0d448a6cbf0d41213ad57d48eb327cf847635ea78de4caa8915f6acf4d62f7fc67893f03dbf15b2852695cccaab3cdc0b74dcd6b6a0dd52d8091455da4ea11e2fa0dcb9de17e814b92db7a206a809ea4be5fc02463691edcc4ff6b287b9ceb767281004a66b2956c01200521aa4a153e4535e096bd1a4f9f5e9048f98c6099ce810f0aa705ca91367366d02f806dbf2a7355a2b0bf916f1516815aaa402a4f7d8f19059afcd90f33567211ce6222839d95e1cb7e021573de2fa783aca1f7ed61d1899a12677dba93abfd44de75db9d42472cf5de4d01377cbfc8d2bed2fc76050b3d6a2af1b126841878e246609b2a56aa93031fede0776164383add925eb939643f0d7f1b5e860c48bc4bfa44f431767b68ae1b6da14821d97ea212133a606cfbb489ba6d933d2ec7fed1ac2f47fb1051a3d44478f9a062828e0f8ce1ca3b9255f78676b9a60dedd18e739baa77d6a7c48f91bd3296df507b6f878d5059c7ac1ccf7e7b6f48d71176e54fd755de57f1ce14011", "1e0", "9e9e52051876271269f7283fcd7db208b58e879846313496aefc616d920cf55fdcf94dc6778a25d56e9a757d3a91d03576ef4e33e49c2d88862f0251dc2a0626950b68bf8f5196a52d95e0850653243f1210359007c9a3c11b5bce5a9afaa001527c1c74a769aa719a902cb3b8a50170f83b49f5a9f21c993b6a14bf63a696b29304e14bdff930c658fc1a7fa0d448a6cbf0d41213ad57d48eb327cf847635ea78de4caa8915f6acf4d62f7fc67893f03dbf15b2852695cccaab3cdc0b74dcd6b6a0dd52d8091455da4ea11e2fa0dcb9de17e814b92db7a206a809ea4be5fc02463691edcc4ff6b287b9ceb767281004a66b2956c01200521aa4a153e4535e096bd1a4f9f5e9048f98c6099ce810f0aa705ca91367366d02f806dbf2a7355a2b0bf916f1516815aaa402a4f7d8f19059afcd90f33567211ce6222839d95e1cb7e021573de2fa783aca1f7ed61d1899a12677dba93abfd44de75db9d42472cf5de4d01377cbfc8d2bed2fc76050b3d6a2af1b126841878e246609b2a56aa93031fede0776164383add925eb939643f0d7f1b5e860c48bc4bfa44f431767b68ae1b6da14821d97ea212133a606cfbb489ba6d933d2ec7fed1ac2f47fb1051a3d44478f9a062828e0f8ce1ca3b9255f78676b9a60dedd18e739baa77d6a7c48f91bd3296df507b6f878d5059c7ac1ccf7e7b6f48d71176e54fd755de57f1ce14011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-e6852a31b2ce3ee36ca9fe5f91eebfc72b1eac7b8da5768eb5d238637ea274108245bdf4ffb223069e0ac83ccf5b1eb02a9a1f89783f66682bf766e434fdd6c7841f16e4b70ba97b043872b0d1ae2fa6eec76631cb302154b8089f24fc63b090fdcad2a51de031abbdb1a72fcdc6aa8e1117c86aed800b69e1dd65477cc6b62c246f9233a40ee0dc4d7f787a6dc0883d14bf92a8b2016e7ede3f266c6bda661544182fa0520f50daed514467fb5971c50477a2857c2e78c70ec1f194f4658f6044a2dd488292174ca6bab22ed26db5c94698e8077e9a9cf4bfb0b730102d7da12a7612e860b43fcedcde0d9c35ffc8295ed2d15a12a49dd409895288eef9d7d3b0751a0f1f563d93c4da576d98e9bd9692850709d807df7515f8113af9adf54c5f1f996a53c77c9a9c7d4453736bf9a36c1daa0f29e2b2d4ae8cf14307c624712518601d6df35cdc6214ae64e774bd9742c8aad373a25fd332ad7647e1a8f12a3bb3344d124f225ad1112cbe0d1769a0d4af7947712ce02746754a5e2874308180036fd85a038737e6fabb14181e53a53d60d740e62d23b33b4a39bd2795fca317f169adea9754e5f13928612d42124e930587d6225c948a42c07e8fce13be205f7d3534e3bf00230d4aa655bb060b2fdfaf5c01d0e39017fe46cbdd5193b016dff5b3b284850ecc74d6c726c2d906c382da4e324d98da0e34ce91f263c7f5f3", "1e0", "-e6852a31b2ce3ee36ca9fe5f91eebfc72b1eac7b8da5768eb5d238637ea274108245bdf4ffb223069e0ac83ccf5b1eb02a9a1f89783f66682bf766e434fdd6c7841f16e4b70ba97b043872b0d1ae2fa6eec76631cb302154b8089f24fc63b090fdcad2a51de031abbdb1a72fcdc6aa8e1117c86aed800b69e1dd65477cc6b62c246f9233a40ee0dc4d7f787a6dc0883d14bf92a8b2016e7ede3f266c6bda661544182fa0520f50daed514467fb5971c50477a2857c2e78c70ec1f194f4658f6044a2dd488292174ca6bab22ed26db5c94698e8077e9a9cf4bfb0b730102d7da12a7612e860b43fcedcde0d9c35ffc8295ed2d15a12a49dd409895288eef9d7d3b0751a0f1f563d93c4da576d98e9bd9692850709d807df7515f8113af9adf54c5f1f996a53c77c9a9c7d4453736bf9a36c1daa0f29e2b2d4ae8cf14307c624712518601d6df35cdc6214ae64e774bd9742c8aad373a25fd332ad7647e1a8f12a3bb3344d124f225ad1112cbe0d1769a0d4af7947712ce02746754a5e2874308180036fd85a038737e6fabb14181e53a53d60d740e62d23b33b4a39bd2795fca317f169adea9754e5f13928612d42124e930587d6225c948a42c07e8fce13be205f7d3534e3bf00230d4aa655bb060b2fdfaf5c01d0e39017fe46cbdd5193b016dff5b3b284850ecc74d6c726c2d906c382da4e324d98da0e34ce91f263c7f5f3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-ed27b1865180559d15a681d6606a09e6720abe31ba1b87933c1d8fc702f4ec8f78c55d6e16c7511cbf1c70e008621802ab5d035741deef331ef89e32bc2d12c779cc0170d39143cac84a3be8f6ef76764c22d5c9e4d0cb14f7d28c01eb98584fd85bd3966129c3799a5553efcb840152a73e7bfac37fce33e724b3d90b87dd340671f342914c8d5bb0ddd2cd5f3c0bb34c3ef34d4ef7af947be283fbfc74d08c5cfbb4d234284f504e995faa9168a352896494e2bdd6e15863e57d7b80ae92dd3907f563fb99e894c93ec6b66dbe6113d0ad588aeb00e6d3c20c259814c1f5ea1628291433c2c1719d9864a998d20c0eae3789a2e394a2c6fd5badd6a29c7c0957294c4c64dba86073a2984ed0b323005791823881bcb43cbf874417ee1782c3ec671c231ec930459a37095be62cf4a7336f31c3effd3f2b51a09bbed087daf03334072f376e8972b13f0cd39845a17df0ecf188541e3ab6e943f195ccccbdadf52a15e2ff0ee68c51bcd51902adea4cb25745d489dc695d8ccaec919094af58d419c9e009736924faa4cabfc292e98c6230204631503182de55405836fdfc8125bda536ba56c5b1e7789d04b425b283993019f7295834ca2f576c4cbb2a9718d7e647550b3729d53b436a940e0b1ac2a1acdd34f1a475fd59029ef0472c2e79ba5f9ebae91f8af3361792f2ea18681f7bea93208d2e0787f4d4a047c996b9de", "b4", "-ed27b1865180559d15a681d6606a09e6720abe31ba1b87933c1d8fc702f4ec8f78c55d6e16c7511cbf1c70e008621802ab5d035741deef331ef89e32bc2d12c779cc0170d39143cac84a3be8f6ef76764c22d5c9e4d0cb14f7d28c01eb98584fd85bd3966129c3799a5553efcb840152a73e7bfac37fce33e724b3d90b87dd340671f342914c8d5bb0ddd2cd5f3c0bb34c3ef34d4ef7af947be283fbfc74d08c5cfbb4d234284f504e995faa9168a352896494e2bdd6e15863e57d7b80ae92dd3907f563fb99e894c93ec6b66dbe6113d0ad588aeb00e6d3c20c259814c1f5ea1628291433c2c1719d9864a998d20c0eae3789a2e394a2c6fd5badd6a29c7c0957294c4c64dba86073a2984ed0b323005791823881bcb43cbf874417ee1782c3ec671c231ec930459a37095be62cf4a7336f31c3effd3f2b51a09bbed087daf03334072f376e8972b13f0cd39845a17df0ecf188541e3ab6e943f195ccccbdadf52a15e2ff0ee68c51bcd51902adea4cb25745d489dc695d8ccaec919094af58d419c9e009736924faa4cabfc292e98c6230204631503182de55405836fdfc8125bda536ba56c5b1e7789d04b425b283993019f7295834ca2f576c4cbb2a9718d7e647550b3729d53b436a940e0b1ac2a1acdd34f1a475fd59029ef0472c2e79ba5f9ebae91f8af3361792f2ea18681f7bea93208d2e0787f4d4a047c996b9de000000000000000000000000000000000000000000000", .None}, + {.Shl, "5d9a966d327b28611135bdcd143d1048b50d51f35529859f352d697f56b33f797ef2bff14e02bd4271ba71d1566c25f2fcd18b0223628208c74542dd14cc968cfb50b002682a27068fc0454e577df6adfa98d3a62292ffb606d8ca89f882adf86d46d26ffdb5db73e7dec4c56e0dc72ad95201b2b58b17cd46b3d0aa1f10e56f1f716165d6def24a42f50b5db4a7d5a4d4d7c3c47de7f69e4142691c452750db7c1706dfc7b60e473a814475b3ae75ca0194d2738be4316d545d2cddbebe877508610cce782ed8e8574f3f9c40492e6d46c70e8d5ade0a86fea604ed6aa7bbfe86e5ffffd6a2305cc3e700efbd5a13ef1f23ea98f0555b4100739c6ac8ebfb358310f6b5536f3202aa610adb328cbeea19a440e723a67b8538941664053842d6e2bc480d9771d41aa95aae8def89def553051456d339a97ae101acb4eceb16169f0a0051b5f6c7962faaea4821a50190c9a0017e6337a4985ba2064145532e8c012b39d47235a6624ac60359921f5b0df4026ba06be1be2dbc439a2232bd556878b4dbea2ca3c728fc99864b11e91fdcb14b7332f38ffec4f55b4a0f84cb1cea7f6f558c811853276abeae991eb921f37032371ccf2eb814696b7914df39bd310f29a77f3134d31f53a03e31ef453f3eb5b5e1a206887dba139068dea6f7010e52c5e9873a7e31098083ca1c576b7ab5d6e77be69d9f2994ae2c1cea2522e958", "b4", "5d9a966d327b28611135bdcd143d1048b50d51f35529859f352d697f56b33f797ef2bff14e02bd4271ba71d1566c25f2fcd18b0223628208c74542dd14cc968cfb50b002682a27068fc0454e577df6adfa98d3a62292ffb606d8ca89f882adf86d46d26ffdb5db73e7dec4c56e0dc72ad95201b2b58b17cd46b3d0aa1f10e56f1f716165d6def24a42f50b5db4a7d5a4d4d7c3c47de7f69e4142691c452750db7c1706dfc7b60e473a814475b3ae75ca0194d2738be4316d545d2cddbebe877508610cce782ed8e8574f3f9c40492e6d46c70e8d5ade0a86fea604ed6aa7bbfe86e5ffffd6a2305cc3e700efbd5a13ef1f23ea98f0555b4100739c6ac8ebfb358310f6b5536f3202aa610adb328cbeea19a440e723a67b8538941664053842d6e2bc480d9771d41aa95aae8def89def553051456d339a97ae101acb4eceb16169f0a0051b5f6c7962faaea4821a50190c9a0017e6337a4985ba2064145532e8c012b39d47235a6624ac60359921f5b0df4026ba06be1be2dbc439a2232bd556878b4dbea2ca3c728fc99864b11e91fdcb14b7332f38ffec4f55b4a0f84cb1cea7f6f558c811853276abeae991eb921f37032371ccf2eb814696b7914df39bd310f29a77f3134d31f53a03e31ef453f3eb5b5e1a206887dba139068dea6f7010e52c5e9873a7e31098083ca1c576b7ab5d6e77be69d9f2994ae2c1cea2522e958000000000000000000000000000000000000000000000", .None}, + {.Shl, "-829ad4512b9ef9003815870d39e4f76d49cd3ee7fefe4dc1daa934d62ac2cee2778ede661dabe2e3cb7629571999d8370544905888cc5ab2da90471fd79af6bc8cca02724c53d36b0a962f0620fdfe4e55449a351bd4fdb0837ca0db98e346654fd9e5125991079d63acae7cd35df1a355a2ae113fa814786da68be7834313359a7346c750b29e15747f4ed2cb3d497a9fe81f8337fea741fc3271564c3e0a1108edc4c296c62f4f74a773d1f5e5b8123398a9b03f2cfa4e39f78bcb9725568aab4fc8bb718b4e496039ddc51b56d755d32ab259cd11f5476e6a672fe5859290809cfc78688943e38c1aa871d870bbbe0c68a849797512b4eaca79b971ebcc9ab1501d818c85efcdc63a1184f44ab1889e383fcf63621c7fe22566d409547d936e53487915e2c9ac8cd53a00388e0d20476f63b3b3422093cdf0b4b7b2b8bfe5612b8f4a1620faf918f51ab4eab373f030eda04ca0c09dca510217ad5188c0c0bd1de601c95a4b6f9fba1b340362c5cb14036603907d98ea9d1906a4caa4f9c8c911990231bc9315da2e66a219aedcea5c4253a80e6dec34dd259ac902bbc47a5b2ca5b2e338d69d1bcc15da2433be080f8a5c09dac850f05df8d390a12ce3f4e5f70779f30039126dced63bba399e2e7d79fd8233c3fe6f184b514e7f4da37ce31f8771f7347e35243b870742cb2c89a641b5ca257fa70c520620936e855fff", "b4", "-829ad4512b9ef9003815870d39e4f76d49cd3ee7fefe4dc1daa934d62ac2cee2778ede661dabe2e3cb7629571999d8370544905888cc5ab2da90471fd79af6bc8cca02724c53d36b0a962f0620fdfe4e55449a351bd4fdb0837ca0db98e346654fd9e5125991079d63acae7cd35df1a355a2ae113fa814786da68be7834313359a7346c750b29e15747f4ed2cb3d497a9fe81f8337fea741fc3271564c3e0a1108edc4c296c62f4f74a773d1f5e5b8123398a9b03f2cfa4e39f78bcb9725568aab4fc8bb718b4e496039ddc51b56d755d32ab259cd11f5476e6a672fe5859290809cfc78688943e38c1aa871d870bbbe0c68a849797512b4eaca79b971ebcc9ab1501d818c85efcdc63a1184f44ab1889e383fcf63621c7fe22566d409547d936e53487915e2c9ac8cd53a00388e0d20476f63b3b3422093cdf0b4b7b2b8bfe5612b8f4a1620faf918f51ab4eab373f030eda04ca0c09dca510217ad5188c0c0bd1de601c95a4b6f9fba1b340362c5cb14036603907d98ea9d1906a4caa4f9c8c911990231bc9315da2e66a219aedcea5c4253a80e6dec34dd259ac902bbc47a5b2ca5b2e338d69d1bcc15da2433be080f8a5c09dac850f05df8d390a12ce3f4e5f70779f30039126dced63bba399e2e7d79fd8233c3fe6f184b514e7f4da37ce31f8771f7347e35243b870742cb2c89a641b5ca257fa70c520620936e855fff000000000000000000000000000000000000000000000", .None}, + {.Shl, "bcf2580c4bd178a3f873c239983f9eec279b51a8f6df6d74b1caf47abd4771a9f5f4de9c1f9ea54a74a737fb6015eae181fe88d4d0dcfceaf598ea1cf38ea45b31db57fe1bda469281c91f47e1c2011629daa2928457f00611793f05daaeb5b7389b00b1cf9971cb0598323068f12ed22adeedfcba2efaa0fceebac8352ab1151b40b3fefda02f9aa437847c0cc64d63a417685985e20d73cf51d1574d0af1825a499149c873ac5c0d34dc6d1310492b3b3a7530cedc21af6c634d10252728e3a5a2da29a5ef606f129d7ce3c05f05f739051c5d63174780de08e293add7493361f18f66099c88b8eadeb6492c48c698d5c70eedbfde19265daae54e068d7b910e90766e1f200b2ed02622d62359b8d432ddca3da724014f95df67fa9e8078a2ef86ae06f6995322ad2edd13fa33295f634f92060bb3615d90926abdd28eca38dd631d03da4cca440ee9e6965e464f587cd3d6cfb8905a359e2fb2c0c0fa759df35ccf5ae025c73525757774f03d1a8537f4f2c7c504a93c072cb636d7de4fbe38fe7578b3afbd397fbecc0c72ca6353dbe5f0da3afed8cb7e424beb1b7d1bf39253fff645d7f36b12a250dd4b2b8ecedf5f335e5dc13649c7f1ee9f6025800f96210ef57797b81d99bb10a8307d5d890bd7f5829afb31fb29132101cc1cde2dcf3956db0461bb168b94966bcd82c5fc5d83dcd2ca0ce0ff94e6205d9fd1b002", "168", "bcf2580c4bd178a3f873c239983f9eec279b51a8f6df6d74b1caf47abd4771a9f5f4de9c1f9ea54a74a737fb6015eae181fe88d4d0dcfceaf598ea1cf38ea45b31db57fe1bda469281c91f47e1c2011629daa2928457f00611793f05daaeb5b7389b00b1cf9971cb0598323068f12ed22adeedfcba2efaa0fceebac8352ab1151b40b3fefda02f9aa437847c0cc64d63a417685985e20d73cf51d1574d0af1825a499149c873ac5c0d34dc6d1310492b3b3a7530cedc21af6c634d10252728e3a5a2da29a5ef606f129d7ce3c05f05f739051c5d63174780de08e293add7493361f18f66099c88b8eadeb6492c48c698d5c70eedbfde19265daae54e068d7b910e90766e1f200b2ed02622d62359b8d432ddca3da724014f95df67fa9e8078a2ef86ae06f6995322ad2edd13fa33295f634f92060bb3615d90926abdd28eca38dd631d03da4cca440ee9e6965e464f587cd3d6cfb8905a359e2fb2c0c0fa759df35ccf5ae025c73525757774f03d1a8537f4f2c7c504a93c072cb636d7de4fbe38fe7578b3afbd397fbecc0c72ca6353dbe5f0da3afed8cb7e424beb1b7d1bf39253fff645d7f36b12a250dd4b2b8ecedf5f335e5dc13649c7f1ee9f6025800f96210ef57797b81d99bb10a8307d5d890bd7f5829afb31fb29132101cc1cde2dcf3956db0461bb168b94966bcd82c5fc5d83dcd2ca0ce0ff94e6205d9fd1b002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "5c5beaf9a53496f3346b8081e3751a4e062e809b70700a798dd395cd7a4f7f833c6a9d1caa67531e5876330b2cde667ccaed133e8d5d664384b9bf883cdc2b6a5066a15d053337877ee1b46dc7155adac2a53e6cb5106019945a0676e9fc7abed750b66428572802008aca6513a41d60e63bf2f067d2256fd802408c249894d4b994465908815c920e7cf7e9960bb1db46460f3a6288843ea19eac0c46f436d22d75dfa285a8c83e3d675e672a66c55e8dae818295c2835ea09e8c219921060fe63fb6f14fc71272de47438696c93238adedfb0d87729ebb9dc8945616a80d5a1b8d87b8c928e931226eeaced99e2ad9063dded4cff46c09b55d7eb1749e5146da095d3bb4c99ef1270b1119906808b94d17bc42b0e00a723b752d3739924983e710216e28ac48fc5c56dc56c59694377e7ed76488a7105b2ed5ea873459d6f41833ee53681d6c679b216f00ba7ea3032f39e084598772698dc53da4a2d9361eaa1f730993a85dcd047fa3999768a15d633c9f489e8877c7115f113eb9ccc00c7ff1fe9638ab720cb0d1343d782c1b984dfd20bcf1304afa034252812908af4151045398e10a7383bf9cee065c5a0f58cc686033cdc3952c8a72aab1ed18f0164bb79ec2aebace93b3073b3e58cddb216f5f59498626f2a8b2c587f5583ed290d08dd7c436b4b9a1830bccc9f6e75169dad8704323e8124eefa29ed87424a307", "258", "5c5beaf9a53496f3346b8081e3751a4e062e809b70700a798dd395cd7a4f7f833c6a9d1caa67531e5876330b2cde667ccaed133e8d5d664384b9bf883cdc2b6a5066a15d053337877ee1b46dc7155adac2a53e6cb5106019945a0676e9fc7abed750b66428572802008aca6513a41d60e63bf2f067d2256fd802408c249894d4b994465908815c920e7cf7e9960bb1db46460f3a6288843ea19eac0c46f436d22d75dfa285a8c83e3d675e672a66c55e8dae818295c2835ea09e8c219921060fe63fb6f14fc71272de47438696c93238adedfb0d87729ebb9dc8945616a80d5a1b8d87b8c928e931226eeaced99e2ad9063dded4cff46c09b55d7eb1749e5146da095d3bb4c99ef1270b1119906808b94d17bc42b0e00a723b752d3739924983e710216e28ac48fc5c56dc56c59694377e7ed76488a7105b2ed5ea873459d6f41833ee53681d6c679b216f00ba7ea3032f39e084598772698dc53da4a2d9361eaa1f730993a85dcd047fa3999768a15d633c9f489e8877c7115f113eb9ccc00c7ff1fe9638ab720cb0d1343d782c1b984dfd20bcf1304afa034252812908af4151045398e10a7383bf9cee065c5a0f58cc686033cdc3952c8a72aab1ed18f0164bb79ec2aebace93b3073b3e58cddb216f5f59498626f2a8b2c587f5583ed290d08dd7c436b4b9a1830bccc9f6e75169dad8704323e8124eefa29ed87424a307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "9f5fa3b1e77c464d019e07d7de3265df1d6d511961e3259ebfe145d17e6daa95852dc0c8bc5fd6b679cdd119db9dd4ccd0d8a5bb6af398d84e9ce5431d521b2b48e90b28d69dc0c84b0d4a8e484a5239f9f8c9acdd90e31e03de7ece8fc67ed8193598b05a2fae3ea77f1d22679731530d44c7553e3cf3433787ade68b238c619b6e70995c7f78e735534c4a5b4bc70c1aa18af161285ba58426d992811be6422ec943f3fcee840634db91bdda6c51bc30840a894d87d224fe985e2e7b43f3f38f5abb68cdf61df3681d7b630cb9652a86fc9b57a3927ab913f9013c2d5dd85c7a289c2c30dae694b859aaf1a551b29eb4892ba32f053e8dca4b83d87e93a674520fc92935a1f8c463bf9cc717e01d5de8a41886b0c0510f4e8602696968d62a3783a04802b2c7cc76ed4ba48d9285d278b6b52e3ae4d910dc836db80d063cc263074e26c48d54486a9995de638412f4ec32efe164b14ef598603b3b0b4cf7c3634e3c6c430d7f117c588af2b30ccb49c46669646a487cbe7c2b5fff820beee5065a2b7aba86fb4452292f287375e768ca16156c36e9d9ae9afd5527da1dceb4ca8487f6f8ece7bb8973e9e6890da1abd4059062efeaec71bf3b684bef9c9765087cf3f96ae4a739b61fa710f040c39e6c114de335f756564ac65cb55cab5dea70e7b8c01c026dbb773ed90634572c20aaee3210bca42b47d42bfd010bfffd03", "21c", "9f5fa3b1e77c464d019e07d7de3265df1d6d511961e3259ebfe145d17e6daa95852dc0c8bc5fd6b679cdd119db9dd4ccd0d8a5bb6af398d84e9ce5431d521b2b48e90b28d69dc0c84b0d4a8e484a5239f9f8c9acdd90e31e03de7ece8fc67ed8193598b05a2fae3ea77f1d22679731530d44c7553e3cf3433787ade68b238c619b6e70995c7f78e735534c4a5b4bc70c1aa18af161285ba58426d992811be6422ec943f3fcee840634db91bdda6c51bc30840a894d87d224fe985e2e7b43f3f38f5abb68cdf61df3681d7b630cb9652a86fc9b57a3927ab913f9013c2d5dd85c7a289c2c30dae694b859aaf1a551b29eb4892ba32f053e8dca4b83d87e93a674520fc92935a1f8c463bf9cc717e01d5de8a41886b0c0510f4e8602696968d62a3783a04802b2c7cc76ed4ba48d9285d278b6b52e3ae4d910dc836db80d063cc263074e26c48d54486a9995de638412f4ec32efe164b14ef598603b3b0b4cf7c3634e3c6c430d7f117c588af2b30ccb49c46669646a487cbe7c2b5fff820beee5065a2b7aba86fb4452292f287375e768ca16156c36e9d9ae9afd5527da1dceb4ca8487f6f8ece7bb8973e9e6890da1abd4059062efeaec71bf3b684bef9c9765087cf3f96ae4a739b61fa710f040c39e6c114de335f756564ac65cb55cab5dea70e7b8c01c026dbb773ed90634572c20aaee3210bca42b47d42bfd010bfffd03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ea74472276fba105783823344fdc7282fcf59fd4fa6c602254cfe78da5edd04c6ede159827bfedc8c0471b78ed9e7d7df55acd88e7a38af82bcfb205933e66cf97c255accbe48285acad9722469097d713868a9d688bbb85f8a796c77cf2cb000747f84af0fb283a51e10da3a50844a5f407bb338ef97baf97be12bcbada1be9c6775f12c8bee2654b3e0788c7e058ec50e8c886f6cdd3443fce01d5fa9317863e98cab2d4469f44b0416395671d03532a82c8ca2439d65106d3b816f870021c4b3a6e64546575ddb8e152732c0c14dae7eebecb2bf304c6e4783e911f2b322c14310e94292d2118c3353d53dd8e438505e69cf5196551740646896319c475a1a91f6c5db886b631975693c8c6758a0a2025c0e9ae3843786fdf8c4d865e5a2a34c9d3c23cf499668c89fed92b8bcc3a87db6b84c10deeaae2e7dd67652e92e70a6f106374f3e05ac9fa17a19f93e2ef3cb6421e468d188512671a15666582243d01496d21f3ac1692f5ca0003974423cd400ee2bf49e8104558396bf4c3a3145a4d9444fc16f5b3927885e9139a851e34d79ed1f253ea33d0e57db74b889fff1929e5d2321208abec83deaec845d922a4af500e4a92fa67bf71228ec7d3891597f292d93819fea3739ff5386f23a2dce37d9ef14dc3aa257b0daa8955e85063b6df2bba46d8497c31168c23faa9c96d06981246dfc0f116b889afc435f712b8", "1a4", "ea74472276fba105783823344fdc7282fcf59fd4fa6c602254cfe78da5edd04c6ede159827bfedc8c0471b78ed9e7d7df55acd88e7a38af82bcfb205933e66cf97c255accbe48285acad9722469097d713868a9d688bbb85f8a796c77cf2cb000747f84af0fb283a51e10da3a50844a5f407bb338ef97baf97be12bcbada1be9c6775f12c8bee2654b3e0788c7e058ec50e8c886f6cdd3443fce01d5fa9317863e98cab2d4469f44b0416395671d03532a82c8ca2439d65106d3b816f870021c4b3a6e64546575ddb8e152732c0c14dae7eebecb2bf304c6e4783e911f2b322c14310e94292d2118c3353d53dd8e438505e69cf5196551740646896319c475a1a91f6c5db886b631975693c8c6758a0a2025c0e9ae3843786fdf8c4d865e5a2a34c9d3c23cf499668c89fed92b8bcc3a87db6b84c10deeaae2e7dd67652e92e70a6f106374f3e05ac9fa17a19f93e2ef3cb6421e468d188512671a15666582243d01496d21f3ac1692f5ca0003974423cd400ee2bf49e8104558396bf4c3a3145a4d9444fc16f5b3927885e9139a851e34d79ed1f253ea33d0e57db74b889fff1929e5d2321208abec83deaec845d922a4af500e4a92fa67bf71228ec7d3891597f292d93819fea3739ff5386f23a2dce37d9ef14dc3aa257b0daa8955e85063b6df2bba46d8497c31168c23faa9c96d06981246dfc0f116b889afc435f712b8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "1a9e9fe123bf5090fcb0765a82614c949fed2ea5f43321f8a0abf273a84aa347cc11cbf7c46a8aa90f9edc785eaffad7b2e6785b649460178f827373d1be39649132aafa2a5dd81fbb0650b2f6d8bf8a8d33b028016f41d82599aaa623df849ea5a2caae0360e4913094dd247eb7ef407e5044d21a8e0c9a28dce61eb95c12bfde9924c2ec4c8d9dfa8df5cbfcea61dd40afcbec3e779364cdf4b28c778d2d91f55afa3828244ee469bd7741f5b8de24e373581cf79a158ee12f133b024ea9eac04b420c75048beb033269c62037cb53960e41285f256d95c254d059e109c5cc9d6c6a02e6ff5818a47c2e8ed67b5f501e82f37ee568cbf9e0292a871a344033009b2f1abfd9980c117cdd847e30092d2ee4f18e67c582bc74f03d716dadb063dcc6fc5fb17bf621132408d9f345e97081fa06d8107d1a85d6b18c2da14df60e22c93858358332616a42b46c91565fef960033de1e6d9154b2ca1a1e2cdd145227e98b837df09adff581aa1944ce9ee4e6ea88f12aeab0a728f603ead0061a4851060c5fa7c7625592c5578da60e1d20873fe6b6a1ce911293373e5f2a9a55a92d90b2e39a40e85d2b73c37edbc6f84904a4d1e7b9f817d7787fd4c002f8157975604413e3d7e4c92cd4c122fab3dff92859226f070edf758459c726130317bd1cdfca28cc0964a23350f87a07c8f3377cf81f850ab422a3e3dedf4630d933e9", "0", "1a9e9fe123bf5090fcb0765a82614c949fed2ea5f43321f8a0abf273a84aa347cc11cbf7c46a8aa90f9edc785eaffad7b2e6785b649460178f827373d1be39649132aafa2a5dd81fbb0650b2f6d8bf8a8d33b028016f41d82599aaa623df849ea5a2caae0360e4913094dd247eb7ef407e5044d21a8e0c9a28dce61eb95c12bfde9924c2ec4c8d9dfa8df5cbfcea61dd40afcbec3e779364cdf4b28c778d2d91f55afa3828244ee469bd7741f5b8de24e373581cf79a158ee12f133b024ea9eac04b420c75048beb033269c62037cb53960e41285f256d95c254d059e109c5cc9d6c6a02e6ff5818a47c2e8ed67b5f501e82f37ee568cbf9e0292a871a344033009b2f1abfd9980c117cdd847e30092d2ee4f18e67c582bc74f03d716dadb063dcc6fc5fb17bf621132408d9f345e97081fa06d8107d1a85d6b18c2da14df60e22c93858358332616a42b46c91565fef960033de1e6d9154b2ca1a1e2cdd145227e98b837df09adff581aa1944ce9ee4e6ea88f12aeab0a728f603ead0061a4851060c5fa7c7625592c5578da60e1d20873fe6b6a1ce911293373e5f2a9a55a92d90b2e39a40e85d2b73c37edbc6f84904a4d1e7b9f817d7787fd4c002f8157975604413e3d7e4c92cd4c122fab3dff92859226f070edf758459c726130317bd1cdfca28cc0964a23350f87a07c8f3377cf81f850ab422a3e3dedf4630d933e9", .None}, + {.Shl, "4070beae3242a6b619eeefd0cc599befeb0dc8dce5267ecf0f3c8c7c825e2d41d0d108bd34d177041a1f8a80fe97b653fcf744a17a0097d4cf312703b2994d168ad704e0b592eeda733f7a333d6af4b87ccc2b60acc3123ce8cd2f32c2a0f2f17dc88fc0ff09ec9f15bb7b012d985064ca6209aeeef9e184e92b5210630dc77abd455a819d4b8101b53abbdfcac8a05b509cfff3058ce063ce4b23531ee0971032744a955da258dc2eafb7245567c8d8675c623f9d4ac0f00bd97a0b943681c19284961c247fb6b1b05a99450abacaa78b0e131a1534f9449ed96e00c5b9181af107783a4005c5766f9a01a0cb7e4d66f71330872e450e52dbecdfa55cf601a425d5c881c025dae13001e31316840eb85b2b1c6fa6897123e1f450dbe5f673eb6562d9bdc59644fd9120bc68445f20a166cae21ee531490865b82ea586864ebd950e657002d49a8c4655c7d1c622b0437932615038d008164b74666ffacd4a88259c3ae1e6d53f3ed8a669a8c572dbaced11ed42c3a062600576dd6a7957ed8a85ad553c4ae4c826f55a11695a2be4031b525d86102d4d8949a4c41944673b4fd66eba9bb0600c00fc6b7518e66ebf941ab3b79e6ea2e64953c03c259bbe7b202bf28c70874e43629012b07795e12303ab67fd01a6a1ffee612c01cefec7a6c21a252c902532c3084ca51f12242008569a0678a0ae70a8d852b2153e55403733", "b4", "4070beae3242a6b619eeefd0cc599befeb0dc8dce5267ecf0f3c8c7c825e2d41d0d108bd34d177041a1f8a80fe97b653fcf744a17a0097d4cf312703b2994d168ad704e0b592eeda733f7a333d6af4b87ccc2b60acc3123ce8cd2f32c2a0f2f17dc88fc0ff09ec9f15bb7b012d985064ca6209aeeef9e184e92b5210630dc77abd455a819d4b8101b53abbdfcac8a05b509cfff3058ce063ce4b23531ee0971032744a955da258dc2eafb7245567c8d8675c623f9d4ac0f00bd97a0b943681c19284961c247fb6b1b05a99450abacaa78b0e131a1534f9449ed96e00c5b9181af107783a4005c5766f9a01a0cb7e4d66f71330872e450e52dbecdfa55cf601a425d5c881c025dae13001e31316840eb85b2b1c6fa6897123e1f450dbe5f673eb6562d9bdc59644fd9120bc68445f20a166cae21ee531490865b82ea586864ebd950e657002d49a8c4655c7d1c622b0437932615038d008164b74666ffacd4a88259c3ae1e6d53f3ed8a669a8c572dbaced11ed42c3a062600576dd6a7957ed8a85ad553c4ae4c826f55a11695a2be4031b525d86102d4d8949a4c41944673b4fd66eba9bb0600c00fc6b7518e66ebf941ab3b79e6ea2e64953c03c259bbe7b202bf28c70874e43629012b07795e12303ab67fd01a6a1ffee612c01cefec7a6c21a252c902532c3084ca51f12242008569a0678a0ae70a8d852b2153e55403733000000000000000000000000000000000000000000000", .None}, + {.Shl, "-efd7efd9be958823a2d33e11e2f547f1982e1c7aa40556de9fae16e9734fe1e9a3d92a0751071755aa05d953ad010e40f04508e317ad6e5b2b364fce23e43f29d776106d9b90cdb24cdc9d08c48647fb3091e8d93ddfdb292f3acc8d27916940647d40b1ea77e5eb7b67ecc8c06e5a34d6aac5c5d6a6bb4a93cb1ee54fa352717b3b217ceaffc72f0d43e805c43f0a1760529de4115441d216799f94dccadffc45548b60afcec3e3795b2d5df74882b80c078d9fdb2ec70b74c115559cc34b0ee999d8124e7eb2f5173f5ef45c189089fb7901368b95875151e773045edc1fdafa2bea1b421b44ec9600974511fb4eb5a7661c5d35db56ae732491d0dc4355fdb2da3f705eefb718ca0c48f56bcbd09c7c51ea1aa16eaadc3e9fa00c51219e65c1286b150f07c1ef37e809bef2065bc35204d8e4d88d6babd9fdace66a82652dbfccfeaa6503f9d03b52d39df3990060b3f09d0ee13fb771b63bc2847bcc87b76c29108da710204a29829ae7355c4342711d2940a1630d91d7b2bd9c475a5c04bd6be1906380f4eb2f0058e356f23e33b0b86293c28d74fe91d517b954a0b80ca6c684366121fd97809b41ada3e64c3451cd5c9a9b88c344bed72b3c146f5f378a20429f44bdbc89afc1d5eeac9906a71f5bd61233f169dece75ce745f663f5870f616d70c976c418f51224659fe1db7cd5062f12e186d12c62d8bd62e23c34f", "12c", "-efd7efd9be958823a2d33e11e2f547f1982e1c7aa40556de9fae16e9734fe1e9a3d92a0751071755aa05d953ad010e40f04508e317ad6e5b2b364fce23e43f29d776106d9b90cdb24cdc9d08c48647fb3091e8d93ddfdb292f3acc8d27916940647d40b1ea77e5eb7b67ecc8c06e5a34d6aac5c5d6a6bb4a93cb1ee54fa352717b3b217ceaffc72f0d43e805c43f0a1760529de4115441d216799f94dccadffc45548b60afcec3e3795b2d5df74882b80c078d9fdb2ec70b74c115559cc34b0ee999d8124e7eb2f5173f5ef45c189089fb7901368b95875151e773045edc1fdafa2bea1b421b44ec9600974511fb4eb5a7661c5d35db56ae732491d0dc4355fdb2da3f705eefb718ca0c48f56bcbd09c7c51ea1aa16eaadc3e9fa00c51219e65c1286b150f07c1ef37e809bef2065bc35204d8e4d88d6babd9fdace66a82652dbfccfeaa6503f9d03b52d39df3990060b3f09d0ee13fb771b63bc2847bcc87b76c29108da710204a29829ae7355c4342711d2940a1630d91d7b2bd9c475a5c04bd6be1906380f4eb2f0058e356f23e33b0b86293c28d74fe91d517b954a0b80ca6c684366121fd97809b41ada3e64c3451cd5c9a9b88c344bed72b3c146f5f378a20429f44bdbc89afc1d5eeac9906a71f5bd61233f169dece75ce745f663f5870f616d70c976c418f51224659fe1db7cd5062f12e186d12c62d8bd62e23c34f000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "d257b3f513841f2970335deb3a01fc725aecc621df8853f72b568d2767a37ac44230a67164feba7deb19f4c5b2c4dc49344e2b9d4f2ae5df678d173b9a1d3739dfe733ef160d5f851c197f5d24e1620d8f222ff592a69c53ae8c64b180ef5f8582228846d4abebe4ad4427b45dfd193d77fd68bc273a480ad989bee0cf0d55df4f7abb191e7e84944d957c4e3ff2adc9d19b519636bb7b9ffd532aff4f2afe47422f8263d7a2a95de22ba526c5a054b5eccc9ec0b8f7accb92fc7aff2d5d5b82f25846ff86d6ea264683009c2b9a19c72e80dbdcc744e63633b6536f2f4368add268fb426b027fd87472dc05a109727dcfc3c8cbbe7299f20a3fb6bb1a63c216fb8826da9fb745840d2c3c86da3f6c5d9820aa6a44385cc766aa27c407a6ba46b545b60136a44b6165db131e5fb39c296e4f055863f112a4e549f2e946cdc1460784a7649ee79072c1ac4a8eb8167b21ba1a1fbdff64f161346968d298da21459a0fa9084d19da2fce33bff012beb378c9ed326fe1a72e88dab5eeadb8107496376c36f8891e6318551a7932b8669845cb680836fedd1561da776d3497d71fa83cbbdc3bcfdfe710a4c5784c43d9ce7cd9bc41573100cf4afa84c8427708149cffcefd297476d3f4cd57886f42c1cbfa05f7614398a959cf23952f1def25f94541d2872a1f6cdb9494440f398e871667f207ef8ff6f462081f5df1961593060f", "f0", "d257b3f513841f2970335deb3a01fc725aecc621df8853f72b568d2767a37ac44230a67164feba7deb19f4c5b2c4dc49344e2b9d4f2ae5df678d173b9a1d3739dfe733ef160d5f851c197f5d24e1620d8f222ff592a69c53ae8c64b180ef5f8582228846d4abebe4ad4427b45dfd193d77fd68bc273a480ad989bee0cf0d55df4f7abb191e7e84944d957c4e3ff2adc9d19b519636bb7b9ffd532aff4f2afe47422f8263d7a2a95de22ba526c5a054b5eccc9ec0b8f7accb92fc7aff2d5d5b82f25846ff86d6ea264683009c2b9a19c72e80dbdcc744e63633b6536f2f4368add268fb426b027fd87472dc05a109727dcfc3c8cbbe7299f20a3fb6bb1a63c216fb8826da9fb745840d2c3c86da3f6c5d9820aa6a44385cc766aa27c407a6ba46b545b60136a44b6165db131e5fb39c296e4f055863f112a4e549f2e946cdc1460784a7649ee79072c1ac4a8eb8167b21ba1a1fbdff64f161346968d298da21459a0fa9084d19da2fce33bff012beb378c9ed326fe1a72e88dab5eeadb8107496376c36f8891e6318551a7932b8669845cb680836fedd1561da776d3497d71fa83cbbdc3bcfdfe710a4c5784c43d9ce7cd9bc41573100cf4afa84c8427708149cffcefd297476d3f4cd57886f42c1cbfa05f7614398a959cf23952f1def25f94541d2872a1f6cdb9494440f398e871667f207ef8ff6f462081f5df1961593060f000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-1928247353623e7e40c6185da5c6f42a7865d6072c9d525653e7e0a742a68280208e17cd1c65c160a23d0ffd0ee96da19fe3753d48856f8514f3bde0046642ad1fc0e86b104601ed8e5bd49ad04885d4d7f1ab1663353ae1ba53013485ae85ddc7a2ed17a4ce65ffb37d408bad6443fcdd3d4ab25d97becfb606aa1aae84efe27d3989bb90ec993ca7cc73a287bfb675aab65fe1d97378883c124d0543d435da8d754fbb6d2128dc6f2fe023701f9ff09893ba02db2a5a170c3a80d590b0da28b2a659443221aa61571bda8bd3a668bc90b4a2f9d892cd74a78fcbed986158fdcef108421908d02629af28493146b771c864929bfefc70606c7665f37bd37751d58d08e49026945b0f1ad72da2ce9b90c6817d2a4f997907299c5d99d20f0b89a28d995f018bdbdee3ed61460ac5a717f86e90b35e98608d1b218a41f8427362589dc407ef19323ced73547705dc225bdb0ffc6b4a3770d806a4a1ecd14200b669796d3fae6a66c3718cfa67ba06eb4926daa08c57b1c323779d16fd863e2462a55b4d50925d21ea74d34e102c7786062dcdd54b00819c03d1122ac2cfd57a906f32922a0ec81f3fb0f13fd53a96b65833aa501ecc38a4fe947664f2b1d76c2a112e2a09ec00823d8c430496216da342796a0d3a4bd1a52f98be8d34bfbfa0f6b69c5eb786ea33831c95aef0e25190b727e4421f8556689d945cc64b9fc02cf0", "78", "-1928247353623e7e40c6185da5c6f42a7865d6072c9d525653e7e0a742a68280208e17cd1c65c160a23d0ffd0ee96da19fe3753d48856f8514f3bde0046642ad1fc0e86b104601ed8e5bd49ad04885d4d7f1ab1663353ae1ba53013485ae85ddc7a2ed17a4ce65ffb37d408bad6443fcdd3d4ab25d97becfb606aa1aae84efe27d3989bb90ec993ca7cc73a287bfb675aab65fe1d97378883c124d0543d435da8d754fbb6d2128dc6f2fe023701f9ff09893ba02db2a5a170c3a80d590b0da28b2a659443221aa61571bda8bd3a668bc90b4a2f9d892cd74a78fcbed986158fdcef108421908d02629af28493146b771c864929bfefc70606c7665f37bd37751d58d08e49026945b0f1ad72da2ce9b90c6817d2a4f997907299c5d99d20f0b89a28d995f018bdbdee3ed61460ac5a717f86e90b35e98608d1b218a41f8427362589dc407ef19323ced73547705dc225bdb0ffc6b4a3770d806a4a1ecd14200b669796d3fae6a66c3718cfa67ba06eb4926daa08c57b1c323779d16fd863e2462a55b4d50925d21ea74d34e102c7786062dcdd54b00819c03d1122ac2cfd57a906f32922a0ec81f3fb0f13fd53a96b65833aa501ecc38a4fe947664f2b1d76c2a112e2a09ec00823d8c430496216da342796a0d3a4bd1a52f98be8d34bfbfa0f6b69c5eb786ea33831c95aef0e25190b727e4421f8556689d945cc64b9fc02cf0000000000000000000000000000000", .None}, + {.Shl, "c3f287125baa7e38dd03cae8058bf7889c10422d8c196e01dbdfa195a92d942774a098d231b9e1f50ffe04e8e25cb3eda7f2895e1f34caeb0e8f0ca296236888bdd2196cb8a34fbc645f87a6e570a3147273396fb0e39515644c7df55861f4e4c451fefba07a762bdff510776820ddc80dc4b975e008075ef36f8749c704c0fdda1917d02042fd82502edae40e52555472f37a9a71b65c82dd7d2420cfaed1e1de3285fbf80af004877fb86b5a585f640230958506e242c77ba205c0c58a58ab14f660f00f7377bd6feb1f88f314813b13fdb33edd628a61ac8d3edbe1c28942311636280a0eb5432e01eced9cab8613c2accc210a965cef0d97b1d25cb6fce59f2de43926ad9df9e32b337236a014b257261bd1411cad21fa825d41cd12245873eec0ee1de020161a32354b51afa463296a5674f460d5cfc680e9e9d31fa7326a7ee08b18066b8e2ff0430ac03ea1b97b696e846f6b09a39c8790398ea905cc76222ac35d0c548d1b5ebb70b6f75eec992cc36063e9a58441ea4316dd4b62da46009d8223755b5121e2db02180335602acacdcdce16d0616cba317528c7650e7a75e3a140dc156e785e71f4e46678cda05b8a8ac460c7a3518027e684388b7ff3b27a343a313be506b05326669bfbf45a19faf4a1c880435a97dc00ddda4c385c51b4e624f5a7aa9939355131aff3238139c8cd3927f5c3515cdeba48754db5", "0", "c3f287125baa7e38dd03cae8058bf7889c10422d8c196e01dbdfa195a92d942774a098d231b9e1f50ffe04e8e25cb3eda7f2895e1f34caeb0e8f0ca296236888bdd2196cb8a34fbc645f87a6e570a3147273396fb0e39515644c7df55861f4e4c451fefba07a762bdff510776820ddc80dc4b975e008075ef36f8749c704c0fdda1917d02042fd82502edae40e52555472f37a9a71b65c82dd7d2420cfaed1e1de3285fbf80af004877fb86b5a585f640230958506e242c77ba205c0c58a58ab14f660f00f7377bd6feb1f88f314813b13fdb33edd628a61ac8d3edbe1c28942311636280a0eb5432e01eced9cab8613c2accc210a965cef0d97b1d25cb6fce59f2de43926ad9df9e32b337236a014b257261bd1411cad21fa825d41cd12245873eec0ee1de020161a32354b51afa463296a5674f460d5cfc680e9e9d31fa7326a7ee08b18066b8e2ff0430ac03ea1b97b696e846f6b09a39c8790398ea905cc76222ac35d0c548d1b5ebb70b6f75eec992cc36063e9a58441ea4316dd4b62da46009d8223755b5121e2db02180335602acacdcdce16d0616cba317528c7650e7a75e3a140dc156e785e71f4e46678cda05b8a8ac460c7a3518027e684388b7ff3b27a343a313be506b05326669bfbf45a19faf4a1c880435a97dc00ddda4c385c51b4e624f5a7aa9939355131aff3238139c8cd3927f5c3515cdeba48754db5", .None}, + {.Shl, "95faba481ad154831c3d3dec4a1d73d93645fdb92ea5b785f0417a9fbb782b3c8a98d8ac8af2970e63c4ef18c209101d7736ff3fe5c7bf95a0660a62a90a77be213913a68b0ae3fe6cd4c0bec411705f7add77a1cf60997ba100a50c3aa989905c904b9a7f60e8e216f0b2163bd65aa4775fce34b11afe1331d626a58ff35b44a479a60c67c5864f7a5d78c32e34370e263e061e16c44c7422e535899f9d414048243e4185d9af9b12f5f00b015824d0f75f030d92b526c52e4da2e692b8fff76717a53a145b75ff669830c47399108fd7261d035e9d2d28eb67af9e670d3bd6126eb91b171788b9d74d3bb9ee922a59e2412f972f5cf13ebca8d22f8cd63327467cef5f6740b730dbaa0c53388b5b7a4acf809f0beca85d0db9946801aace4de33684e4174586f92fda748750d642d69c42297f1d5cb6e58bb93e544161a6f71828441f0818fff7d43189a27dd79883db58864a44e0337871190ad9cb0393e2b09add1a4740040a30202d74cd1539b1d8b8627ecaaaba9798f283b3580c8b93c8bbfccb4b8251c73c015e6e849f302b4479a9732a0a7efd61fd719dab291cf2b923320abbf1264f586171c9e5d2349023ef2709cc2450b51cda1aa1f00257868c8188c8caac4cdff41780982920bb6f31a519ddb201223b75de3d25a8745fb9a5baa979c20a8524f03b00aa42dfe97bcd3608756fbb14a4507868531b0b84fc", "f0", "95faba481ad154831c3d3dec4a1d73d93645fdb92ea5b785f0417a9fbb782b3c8a98d8ac8af2970e63c4ef18c209101d7736ff3fe5c7bf95a0660a62a90a77be213913a68b0ae3fe6cd4c0bec411705f7add77a1cf60997ba100a50c3aa989905c904b9a7f60e8e216f0b2163bd65aa4775fce34b11afe1331d626a58ff35b44a479a60c67c5864f7a5d78c32e34370e263e061e16c44c7422e535899f9d414048243e4185d9af9b12f5f00b015824d0f75f030d92b526c52e4da2e692b8fff76717a53a145b75ff669830c47399108fd7261d035e9d2d28eb67af9e670d3bd6126eb91b171788b9d74d3bb9ee922a59e2412f972f5cf13ebca8d22f8cd63327467cef5f6740b730dbaa0c53388b5b7a4acf809f0beca85d0db9946801aace4de33684e4174586f92fda748750d642d69c42297f1d5cb6e58bb93e544161a6f71828441f0818fff7d43189a27dd79883db58864a44e0337871190ad9cb0393e2b09add1a4740040a30202d74cd1539b1d8b8627ecaaaba9798f283b3580c8b93c8bbfccb4b8251c73c015e6e849f302b4479a9732a0a7efd61fd719dab291cf2b923320abbf1264f586171c9e5d2349023ef2709cc2450b51cda1aa1f00257868c8188c8caac4cdff41780982920bb6f31a519ddb201223b75de3d25a8745fb9a5baa979c20a8524f03b00aa42dfe97bcd3608756fbb14a4507868531b0b84fc000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-46cdccd8b792bead4b1a1cd0cfcc41cd6704229a5aaa4430e35bec3347adb6dbceb801c315cebd3adc8d1fba26153aeea59c81261cffd35ae0d541c27dc3586a3c4dc8b41755ad2a9f3179f3ff6aafd6f7e37119928b2f4af3677d3461f9072d76d829cd9ad2d78cd8b356f736b145c15f0ecbf0fb61d0e14b0148d6a284da67a72915f8f6e9698cf997162833c715341f3ffc52873280d60d223138bc4523eb16d393782e38e28b92cd925351542d1c999db71c630b353b155c819e964d3ef4bdef2863d4bece009154121cae404fef386301aebeb9e72424bffa6e7e0a4390a1edd8a9d4a22e29799f3cf3471a16e93ef298f2a48d1f262220d11fbf993e9e85399815db8acd4573f1bb7d481f0c88ef3aa7bb0f39048b362b00220bb09c23c4a7bdb84e68c3f42488d8ba508a97df8740beba495f4f43b678d2f276369af65a08fe76bb7ca8561037eb7867b0615b04b08625bce1042fec85bb9e4f1f6671a9a2d4e65f72d79558be4376dc6f9800484c25af43a9adf8c29635bfdc7e928aa296fd778b5a379ba8ab79b5f62a7517a7de2347bb741a25f269b882ba290bfc221b285e8aa9cdbea6e998fefae84391e1f8ae697a7dcdea3addb68e6dd39911ad47d979a82ffaa82bd4663182f070630a206e697654a430a057c5ff20ca9aa52541c724df3a6b5249cd66aa166022a2f63e7f673dabcdf606e4716cf838405c", "21c", "-46cdccd8b792bead4b1a1cd0cfcc41cd6704229a5aaa4430e35bec3347adb6dbceb801c315cebd3adc8d1fba26153aeea59c81261cffd35ae0d541c27dc3586a3c4dc8b41755ad2a9f3179f3ff6aafd6f7e37119928b2f4af3677d3461f9072d76d829cd9ad2d78cd8b356f736b145c15f0ecbf0fb61d0e14b0148d6a284da67a72915f8f6e9698cf997162833c715341f3ffc52873280d60d223138bc4523eb16d393782e38e28b92cd925351542d1c999db71c630b353b155c819e964d3ef4bdef2863d4bece009154121cae404fef386301aebeb9e72424bffa6e7e0a4390a1edd8a9d4a22e29799f3cf3471a16e93ef298f2a48d1f262220d11fbf993e9e85399815db8acd4573f1bb7d481f0c88ef3aa7bb0f39048b362b00220bb09c23c4a7bdb84e68c3f42488d8ba508a97df8740beba495f4f43b678d2f276369af65a08fe76bb7ca8561037eb7867b0615b04b08625bce1042fec85bb9e4f1f6671a9a2d4e65f72d79558be4376dc6f9800484c25af43a9adf8c29635bfdc7e928aa296fd778b5a379ba8ab79b5f62a7517a7de2347bb741a25f269b882ba290bfc221b285e8aa9cdbea6e998fefae84391e1f8ae697a7dcdea3addb68e6dd39911ad47d979a82ffaa82bd4663182f070630a206e697654a430a057c5ff20ca9aa52541c724df3a6b5249cd66aa166022a2f63e7f673dabcdf606e4716cf838405c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ada3a37ca41ce2002d66178e380082865fb0e89e638b1eb924cc6939f5f236e00ad6afacc83086aba5cccd3e88e02122ac04fcedd9860c1f2b3114f7965019a3b6380490f4486043f27a6694e3b90e244b0cf9ed1057059f70e6f1c632c65cde5dfc3491d4c3a29fc45d4cdcfb33d44c282371224685f9d3c1169f409bfc7ad85f81c4e23e3bad40d6a0ddb6c07598ba71a65a5d608903e461c2a42f2327cfa90b2b5361463e838096118270075e818b7bbca2d8030cfcc134e9ad6e971ec5e0edf5411435d209d75493229243e35bfa150a1c47e237207d7cc9c577450668bb5963d8a4daafe2e6ce2bef2c1fb9b0636058c97ae21b4d6d0c3fc0865cc89693fd3f4b89f78a4028ff80c16c0f9474a70705cfa340615993f96c61950557ed43baf30fbbaa8a57ffecfc975e775504509d8a84346feb915ee850e852008dd902c0a557b9e8374a80d58af48248e74a877c297b7658084769a28cbf488cb8cb700c7121ec96e0166139612b5c68973468f374d72fd94a39b3c640d29df293aa11136907447fdcb6cfbb191398c8563f1e482aa6d338838ea5fca9ae70057a3b2281d18c83cf4b4b77c7cca9a31414933e4d79223eb408c5f9bf9f5bbecf936b346883bc892fb93b0dca0fe41bc6d4c2eaa9601dc02b455d1406a17dd211067ae579adf4133c646bc2dad32df25fb4810a90f8426ae74f4e666d9b49585e9dc6e8", "0", "ada3a37ca41ce2002d66178e380082865fb0e89e638b1eb924cc6939f5f236e00ad6afacc83086aba5cccd3e88e02122ac04fcedd9860c1f2b3114f7965019a3b6380490f4486043f27a6694e3b90e244b0cf9ed1057059f70e6f1c632c65cde5dfc3491d4c3a29fc45d4cdcfb33d44c282371224685f9d3c1169f409bfc7ad85f81c4e23e3bad40d6a0ddb6c07598ba71a65a5d608903e461c2a42f2327cfa90b2b5361463e838096118270075e818b7bbca2d8030cfcc134e9ad6e971ec5e0edf5411435d209d75493229243e35bfa150a1c47e237207d7cc9c577450668bb5963d8a4daafe2e6ce2bef2c1fb9b0636058c97ae21b4d6d0c3fc0865cc89693fd3f4b89f78a4028ff80c16c0f9474a70705cfa340615993f96c61950557ed43baf30fbbaa8a57ffecfc975e775504509d8a84346feb915ee850e852008dd902c0a557b9e8374a80d58af48248e74a877c297b7658084769a28cbf488cb8cb700c7121ec96e0166139612b5c68973468f374d72fd94a39b3c640d29df293aa11136907447fdcb6cfbb191398c8563f1e482aa6d338838ea5fca9ae70057a3b2281d18c83cf4b4b77c7cca9a31414933e4d79223eb408c5f9bf9f5bbecf936b346883bc892fb93b0dca0fe41bc6d4c2eaa9601dc02b455d1406a17dd211067ae579adf4133c646bc2dad32df25fb4810a90f8426ae74f4e666d9b49585e9dc6e8", .None}, + {.Shl, "8d54673297a4c160d694a94251db21020e7f891caabda8b708c24c2b16af4e78579aed0924d508d39d4674144a87a2d2368644c844486baef595f7ff8e65207f3fea313d8dfc52e19fe0e4316d008a4dfd089b58b3003fb22cd4dd6ed198eeed6f6b907b03315f9899a0125b2208609734c2535568305e8a02e1afc5ff56ce85b0c6be13be23d63b6d421c9661331194c18c7f9da48b2170c0c8d06b50d49e7afff9523f42a83b363e418629419c51e31e690b514e8f53a36951c5a5c7510fde5271993c0c7980c717b587de247b86f228dcc330c41969b4501e478061f89c6a20f06ee3b9f3e7a1e53abbcf8112eb38b049d41003eec6accf86e45120af4c0626d866d4f5237fd895ed8f3e3c1a2ddb8850f3e03ee99a3e160dcdec1483fbd1c42d350e1b3b9455b3065be19f5ba49cb16c19aa110ffded08bd3e61db63a9de760f131020ce94caed94d86608344d60dcd375de6735bcaf347fe96aef58acf7d0eccaa14bca9543df4b1319e5b7be4bf423e087bebb59e0af27e4c6f4d55412435b945167e379f07a271f32d5a557da83445513c17650c3dad6fd5a0b994153af3482e961af0ebabc37755fa933f1ad8d8e815bbef6e32a5590c6e192d83888f60b1cefd0977bebe70ab1a3b04d471cb392f542097dca48d073e833c3caa42fecbf3a4816e23e43a8fc22f88f24f24c26739d8dabbde6f91af7eee42a27563f", "1e0", "8d54673297a4c160d694a94251db21020e7f891caabda8b708c24c2b16af4e78579aed0924d508d39d4674144a87a2d2368644c844486baef595f7ff8e65207f3fea313d8dfc52e19fe0e4316d008a4dfd089b58b3003fb22cd4dd6ed198eeed6f6b907b03315f9899a0125b2208609734c2535568305e8a02e1afc5ff56ce85b0c6be13be23d63b6d421c9661331194c18c7f9da48b2170c0c8d06b50d49e7afff9523f42a83b363e418629419c51e31e690b514e8f53a36951c5a5c7510fde5271993c0c7980c717b587de247b86f228dcc330c41969b4501e478061f89c6a20f06ee3b9f3e7a1e53abbcf8112eb38b049d41003eec6accf86e45120af4c0626d866d4f5237fd895ed8f3e3c1a2ddb8850f3e03ee99a3e160dcdec1483fbd1c42d350e1b3b9455b3065be19f5ba49cb16c19aa110ffded08bd3e61db63a9de760f131020ce94caed94d86608344d60dcd375de6735bcaf347fe96aef58acf7d0eccaa14bca9543df4b1319e5b7be4bf423e087bebb59e0af27e4c6f4d55412435b945167e379f07a271f32d5a557da83445513c17650c3dad6fd5a0b994153af3482e961af0ebabc37755fa933f1ad8d8e815bbef6e32a5590c6e192d83888f60b1cefd0977bebe70ab1a3b04d471cb392f542097dca48d073e833c3caa42fecbf3a4816e23e43a8fc22f88f24f24c26739d8dabbde6f91af7eee42a27563f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-cede06bcc3b205ac2f6bb30523327b95d40d1c9bc4525656b4a269cd326d7961b8bedc12e674d6670a33e005dd5cce72495e10f04035a24722d60879b84aa6b2e6f0d07e87777f8dc72512d2b03e59f6407b6ac693eb0807684e44c6d2a660777e91425f8b4c3a009d27c6af5f7622cf7146567c5b3e75234d0a696bfc5ac0e25545b9e78722590f95ec07b76d754b4fa030fb995db46385c9ccd33a363ec5fe531f03dbd4abbd2045cdf18d85371756b9742e448df59f01446cb56a12fb830c96f9de625455329dfe014befaa28a4c1b576ae84d62ae1e3dfc98079625f591f56d0979ef5724e2fb244e908fd90029dbf0094831a43cd68ee434dc520e74a83d8ef8e07ba31f9903131ce06fbde2f2089d8e0f707a3b6738d734503abf4756009ace41d90ae8ef899e09e1f191b71adb4bbe3e4506e7640ffaadbcae47163efd66c772c0b5f29a6b36d8461e2fc21dd3a54201a4a83259e88d7d76021a40261fb6e1ab1b0c8cf702e54dd2827d436fb5147a178f7dc8fef089b2b50ba5a933c4c885c92f489fe952d3e99e56b6310e4d9aa6c9338d62ede25aaaa907f2e16dc30c0388865b7b63846ec732b1a2dcda79e28854095a10a7a3777a0bc93461011ca32a305e214ba6f5ddd1902be03b823d703ef8fcaf456f675c04c5e19696a32e6da9689fc8327afaef05e5880fefeae735a0f4ea02b49ea86b0a787b39710f4", "21c", "-cede06bcc3b205ac2f6bb30523327b95d40d1c9bc4525656b4a269cd326d7961b8bedc12e674d6670a33e005dd5cce72495e10f04035a24722d60879b84aa6b2e6f0d07e87777f8dc72512d2b03e59f6407b6ac693eb0807684e44c6d2a660777e91425f8b4c3a009d27c6af5f7622cf7146567c5b3e75234d0a696bfc5ac0e25545b9e78722590f95ec07b76d754b4fa030fb995db46385c9ccd33a363ec5fe531f03dbd4abbd2045cdf18d85371756b9742e448df59f01446cb56a12fb830c96f9de625455329dfe014befaa28a4c1b576ae84d62ae1e3dfc98079625f591f56d0979ef5724e2fb244e908fd90029dbf0094831a43cd68ee434dc520e74a83d8ef8e07ba31f9903131ce06fbde2f2089d8e0f707a3b6738d734503abf4756009ace41d90ae8ef899e09e1f191b71adb4bbe3e4506e7640ffaadbcae47163efd66c772c0b5f29a6b36d8461e2fc21dd3a54201a4a83259e88d7d76021a40261fb6e1ab1b0c8cf702e54dd2827d436fb5147a178f7dc8fef089b2b50ba5a933c4c885c92f489fe952d3e99e56b6310e4d9aa6c9338d62ede25aaaa907f2e16dc30c0388865b7b63846ec732b1a2dcda79e28854095a10a7a3777a0bc93461011ca32a305e214ba6f5ddd1902be03b823d703ef8fcaf456f675c04c5e19696a32e6da9689fc8327afaef05e5880fefeae735a0f4ea02b49ea86b0a787b39710f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "5805533d97c52a599289d9c39b63c6f3df601bbd1df2b84c3ce3ceefab505ba86e0adec168bfcd5eaa9fd6592359239cae9a691a2e8af4812e2a3d302c6ae583226929e277a6a715670994efe58d0be00bc68b6f0b32d0b77bce66073cc52332269d16f37bf4dd12723e1818c5828e2d7ae692d7ec16da2934f4a1d7b0a0e00752bb8cd79d0484fa5e4e40dbc7ca5c713e90beca33c0d8f77a8ee8f7143126a0248ca02464235fff33b671d2bd921a3650a697c9caabc842cb976ec0715acf0bcd2fd00ca1a73971deda0155f10225e6ec1a1e362b6f3abc5264c9d4fae7329174dcbbe4cae25629f8ccd4f3e7657992c07f5d3aef1d0f74240b7ee3ef8cc1dd53a3e93f9c0b519bdf8b1bffa434e0b6979545ac2d8c50403eabefce6eee2443c2148fda4471b383a0d06817ef66bb12ae6c6db9e3bf51c799bce8e1ec87bb5240726ee1a29df6c2c2c65f38c626cab4f9420149168cf9eab07415edfc422ee5c2b4d7fcd4aed461e868648a3048fd73b11a6d3f2da0647450ef55678fe2129d6fb686aebc79a84a841ede25a8f2b32ff4e55c10958c75bdf559b3a31e6f71e57014bac48e495c83e5988163c194b70817a1f5db4104cf825af7686b72c66d9ad0a5e2fa459b0c0cd28abe2155e83646236bb443a2c9bb7249ac3d1249f71e344d92eaf8aadf7a153613677b1349dcef1613d6cbfc5fd8b855d33d250a5778ca", "12c", "5805533d97c52a599289d9c39b63c6f3df601bbd1df2b84c3ce3ceefab505ba86e0adec168bfcd5eaa9fd6592359239cae9a691a2e8af4812e2a3d302c6ae583226929e277a6a715670994efe58d0be00bc68b6f0b32d0b77bce66073cc52332269d16f37bf4dd12723e1818c5828e2d7ae692d7ec16da2934f4a1d7b0a0e00752bb8cd79d0484fa5e4e40dbc7ca5c713e90beca33c0d8f77a8ee8f7143126a0248ca02464235fff33b671d2bd921a3650a697c9caabc842cb976ec0715acf0bcd2fd00ca1a73971deda0155f10225e6ec1a1e362b6f3abc5264c9d4fae7329174dcbbe4cae25629f8ccd4f3e7657992c07f5d3aef1d0f74240b7ee3ef8cc1dd53a3e93f9c0b519bdf8b1bffa434e0b6979545ac2d8c50403eabefce6eee2443c2148fda4471b383a0d06817ef66bb12ae6c6db9e3bf51c799bce8e1ec87bb5240726ee1a29df6c2c2c65f38c626cab4f9420149168cf9eab07415edfc422ee5c2b4d7fcd4aed461e868648a3048fd73b11a6d3f2da0647450ef55678fe2129d6fb686aebc79a84a841ede25a8f2b32ff4e55c10958c75bdf559b3a31e6f71e57014bac48e495c83e5988163c194b70817a1f5db4104cf825af7686b72c66d9ad0a5e2fa459b0c0cd28abe2155e83646236bb443a2c9bb7249ac3d1249f71e344d92eaf8aadf7a153613677b1349dcef1613d6cbfc5fd8b855d33d250a5778ca000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "ff59f250ce5dd8b0550507420993dbc26f21a18ee3fd1603755e536ee4fc3e9f617610849880277a5c5f56b7802f7a4b01de855e63fb51b7fedf2fa6fbb2ed98715160d7485aaf439b6dad668ec42f0b5458f7afe8c368a23795c18211b2b209189a5b88500a315b347346fc400d955828b40df4511a1c4bdcf2ce3979d3e1b633103546b60e95559918c917bc72f46b16aabff88d3e3a776f8e766170dfab958c4b7306e99335d22a70831db3db4488a70e48cd23d00e9d1da8335d4a5d001e971ce640b2b9afd936049cc8cf2743898636c62b4b73860813c024034d888e55f5a7d6915eec5dcb70ac82a2f9d2a526d19562ffc7ea291dfb61e51689ae89822966e9fe848055804fa38aa5ef132ef9f61b1ac2a91ea8f44192595a452250a8bfd44dae62e671a6d2ab96ad1a1ce4d81f1f235e24402701dd9a5ab01b8b7d530d93037de0fc6eadd67e36cd6574e95c1966ff7cfa8f3ccd2bdb96cea884f26ce2c4c196de8c553084689044fb431a62e94ad8547b77efc7251ef415a24b5217e8abcc373ae50f786edd2760f796a29f458c5255ccdc8a2abb6bf1edb260e339583ef84a6b8c34e748188b67f2200c5873478ac533a37f2fe914dc6636547d308816dc33f63182d80a954dbb29d347ef8bb6ad1a76687cbcb634689304a67300f1a943776b93fe28fda46ed528105501e94b93ede98d645e863b364a0775ebc8", "21c", "ff59f250ce5dd8b0550507420993dbc26f21a18ee3fd1603755e536ee4fc3e9f617610849880277a5c5f56b7802f7a4b01de855e63fb51b7fedf2fa6fbb2ed98715160d7485aaf439b6dad668ec42f0b5458f7afe8c368a23795c18211b2b209189a5b88500a315b347346fc400d955828b40df4511a1c4bdcf2ce3979d3e1b633103546b60e95559918c917bc72f46b16aabff88d3e3a776f8e766170dfab958c4b7306e99335d22a70831db3db4488a70e48cd23d00e9d1da8335d4a5d001e971ce640b2b9afd936049cc8cf2743898636c62b4b73860813c024034d888e55f5a7d6915eec5dcb70ac82a2f9d2a526d19562ffc7ea291dfb61e51689ae89822966e9fe848055804fa38aa5ef132ef9f61b1ac2a91ea8f44192595a452250a8bfd44dae62e671a6d2ab96ad1a1ce4d81f1f235e24402701dd9a5ab01b8b7d530d93037de0fc6eadd67e36cd6574e95c1966ff7cfa8f3ccd2bdb96cea884f26ce2c4c196de8c553084689044fb431a62e94ad8547b77efc7251ef415a24b5217e8abcc373ae50f786edd2760f796a29f458c5255ccdc8a2abb6bf1edb260e339583ef84a6b8c34e748188b67f2200c5873478ac533a37f2fe914dc6636547d308816dc33f63182d80a954dbb29d347ef8bb6ad1a76687cbcb634689304a67300f1a943776b93fe28fda46ed528105501e94b93ede98d645e863b364a0775ebc8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-5546d85e66d476cb91b5004528af4752956df433b0cc87c630f95a5e721a332ab2cc7ff38db61a842b1a58abd2c4d9f132778124187ffd5437e29da82da2388ecbe7e06469ac0ea366f8b4b01cd6b968b0c3c55b3615929d89b25f604702a2f183cac89aa438e44dabde63f2da84159da91f92a6967f82087ee974beed0baf6c5f9d6c814503f53f6bf5690261a582adb3a18cf5c284423ac7df3e5d6291e32cc4a4088480a2ad194972738e86342f60b99f9f9deb04a8060fc6ec23d3054ef2729f2d92c19a682caa131ef8b387094623ffbc887155131a1cdc2291905c8ac26fe03bbf03e303b6c881d3b318a990f1d6ccc0a66ce811fd16036e4543f3b304ad8f50fb70784472831fef40e40bd09ba5f28475f3c6415f5c8dd550008d19f8e8051bd0d01827ea2ff9a6326ee91f9e171ba53ffc6a4033d70382bc534c28d448944a35569738a488037bd32ed670df3ce9c86113363bde3dbbee7808127440b438fb9c7e052c8320ef70be56c3b154a0d590ee330ba30ad3505d7d5ee3613e984ff6708875c4f67c9d9b9d4640b1d85c361aabd3c2aa7e474a4f23963435783a4ad89d20b26edabf04d924e01e5a4af1d1ed75ecf0d27121ba72283488a25ed6c3176a5d473c12a788cb5f9365662e5efd32d7221505e6286c3564f89077e5ef03a44af940c281fd3ea37b9be3054a6adf1692c151d7951765db6af93ef456", "78", "-5546d85e66d476cb91b5004528af4752956df433b0cc87c630f95a5e721a332ab2cc7ff38db61a842b1a58abd2c4d9f132778124187ffd5437e29da82da2388ecbe7e06469ac0ea366f8b4b01cd6b968b0c3c55b3615929d89b25f604702a2f183cac89aa438e44dabde63f2da84159da91f92a6967f82087ee974beed0baf6c5f9d6c814503f53f6bf5690261a582adb3a18cf5c284423ac7df3e5d6291e32cc4a4088480a2ad194972738e86342f60b99f9f9deb04a8060fc6ec23d3054ef2729f2d92c19a682caa131ef8b387094623ffbc887155131a1cdc2291905c8ac26fe03bbf03e303b6c881d3b318a990f1d6ccc0a66ce811fd16036e4543f3b304ad8f50fb70784472831fef40e40bd09ba5f28475f3c6415f5c8dd550008d19f8e8051bd0d01827ea2ff9a6326ee91f9e171ba53ffc6a4033d70382bc534c28d448944a35569738a488037bd32ed670df3ce9c86113363bde3dbbee7808127440b438fb9c7e052c8320ef70be56c3b154a0d590ee330ba30ad3505d7d5ee3613e984ff6708875c4f67c9d9b9d4640b1d85c361aabd3c2aa7e474a4f23963435783a4ad89d20b26edabf04d924e01e5a4af1d1ed75ecf0d27121ba72283488a25ed6c3176a5d473c12a788cb5f9365662e5efd32d7221505e6286c3564f89077e5ef03a44af940c281fd3ea37b9be3054a6adf1692c151d7951765db6af93ef456000000000000000000000000000000", .None}, + {.Shl, "5e287bc0f618f8ffac92279ca376724aba0f5b21bd302a815f6d7ba073648662103610fa65db6f5b510a17c6f59c7b136e8182a365e29c3045a7812ef8df1411cc81ac438c63f2c90aa1d07c14aedf5de93037ca9cf7b802c23ce9a6cb83c2573ffb7cd54c7a3a24d4fe341c4d1c193bf9bb5b9a1a5b1b10a02aa7c08a94c7309962d81dc65139b3fc13c5c6d19d0b3b8196c948927f1b3c3d8b5888733db3cda51ab9986bd6777b9df5746505150d6a966d1cf0373158aabee453a754a365dcefa1c5aab133d141735c2620dc073599173a6ddd7db22dfd8e2d46becd3cf863a9e50357d7611518ffe15972be895e29da16fc5fa551ae22071a072b306c1698f87bbc25c39ee89b251d4efd092a7a3804b50608a34f3e94693f2c16d1217c44622ed016a2152aee74d48ce797fb94eb75274b31cf7270537c853d61b421d680431dd41779f83d5a8d4707f793bb63469c441a0d57b2bf1c3544adc49bd799ebf66b50efb6c2982a45f826e5487e6bc7e8465a90ab8dc2635bcecd891ba553a1a3341cd9d80195ab7b197a7d867d458884e83af352d01912a804cf20c08685ec91a11ae6b927a1c5b56af36e2b7f271f3d5d341fd33b64abbce530037abd253b3ee82a655574347fb70c1dd56a183fd732c22d6b6abb63cfbe8e12db43b4398416f54eeada0b1bc40e83e413a72e46d532242daf1388076b9115ff934ef00ab9", "168", "5e287bc0f618f8ffac92279ca376724aba0f5b21bd302a815f6d7ba073648662103610fa65db6f5b510a17c6f59c7b136e8182a365e29c3045a7812ef8df1411cc81ac438c63f2c90aa1d07c14aedf5de93037ca9cf7b802c23ce9a6cb83c2573ffb7cd54c7a3a24d4fe341c4d1c193bf9bb5b9a1a5b1b10a02aa7c08a94c7309962d81dc65139b3fc13c5c6d19d0b3b8196c948927f1b3c3d8b5888733db3cda51ab9986bd6777b9df5746505150d6a966d1cf0373158aabee453a754a365dcefa1c5aab133d141735c2620dc073599173a6ddd7db22dfd8e2d46becd3cf863a9e50357d7611518ffe15972be895e29da16fc5fa551ae22071a072b306c1698f87bbc25c39ee89b251d4efd092a7a3804b50608a34f3e94693f2c16d1217c44622ed016a2152aee74d48ce797fb94eb75274b31cf7270537c853d61b421d680431dd41779f83d5a8d4707f793bb63469c441a0d57b2bf1c3544adc49bd799ebf66b50efb6c2982a45f826e5487e6bc7e8465a90ab8dc2635bcecd891ba553a1a3341cd9d80195ab7b197a7d867d458884e83af352d01912a804cf20c08685ec91a11ae6b927a1c5b56af36e2b7f271f3d5d341fd33b64abbce530037abd253b3ee82a655574347fb70c1dd56a183fd732c22d6b6abb63cfbe8e12db43b4398416f54eeada0b1bc40e83e413a72e46d532242daf1388076b9115ff934ef00ab9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b4f1092062fb4c2430461df53ab456e469c1e7ad57ba6d78232a28dfe8732faa8be98df0274bc9c982d5c545cde2be20d64b271a23d3a529a946a2e74202a36bced6c4c225a016b854f65bcd50cbb0d5e63b09b8222a2e7f8dfc660dda74c5d70b21254f447412b60da95f2b43277987de03df90ca2af5437210b6c102979e2f16eabaf464a6b089e72af067e3cd67f3c80bb897b02c3c3879a2d9152363eef47d7475b3ddfd4b5a2823ed1df034eefae7f5693cb1dc4af65f48dfb991b884eb40606e8c1573cfd3dafa23a40c006f844b52a43a32ad3755adce2d4f0309362f3142e43619f270065bebf6cf2c295beced4fd41021e0d15307a47ca7516b101fec920f07a3dbf95f2cac35008dda9189c7196c043d127bf5c69ea616d8406cb4affa5f2061135aaa149f67b7ccee3e70e2a627558ca8395169bcb7f27cd494c62425d2a6064a8902601d660cbbbcac44b9acdd91c7b5f46265cc0cfcc787ec0fde3e2132e772e41e31985f20d265d8285e38e377ed8fc5ebe6c68aa91d9181347ce691a37bbdb277ec946eb58762d728f4f0e842a57f14dd5209749757da36b51ae53c4a5162800a1b3f90a9d06aef156bee04a82238c1248088f75121e8860697e761b4cc3a4e2f5aead9efcb3f18ab5e9e931c1cd217102059bf86b66a596adb77df132c938c53e86ef38fd631e3184aff138497b47dd84c73ea37bc10a52f", "b4", "-b4f1092062fb4c2430461df53ab456e469c1e7ad57ba6d78232a28dfe8732faa8be98df0274bc9c982d5c545cde2be20d64b271a23d3a529a946a2e74202a36bced6c4c225a016b854f65bcd50cbb0d5e63b09b8222a2e7f8dfc660dda74c5d70b21254f447412b60da95f2b43277987de03df90ca2af5437210b6c102979e2f16eabaf464a6b089e72af067e3cd67f3c80bb897b02c3c3879a2d9152363eef47d7475b3ddfd4b5a2823ed1df034eefae7f5693cb1dc4af65f48dfb991b884eb40606e8c1573cfd3dafa23a40c006f844b52a43a32ad3755adce2d4f0309362f3142e43619f270065bebf6cf2c295beced4fd41021e0d15307a47ca7516b101fec920f07a3dbf95f2cac35008dda9189c7196c043d127bf5c69ea616d8406cb4affa5f2061135aaa149f67b7ccee3e70e2a627558ca8395169bcb7f27cd494c62425d2a6064a8902601d660cbbbcac44b9acdd91c7b5f46265cc0cfcc787ec0fde3e2132e772e41e31985f20d265d8285e38e377ed8fc5ebe6c68aa91d9181347ce691a37bbdb277ec946eb58762d728f4f0e842a57f14dd5209749757da36b51ae53c4a5162800a1b3f90a9d06aef156bee04a82238c1248088f75121e8860697e761b4cc3a4e2f5aead9efcb3f18ab5e9e931c1cd217102059bf86b66a596adb77df132c938c53e86ef38fd631e3184aff138497b47dd84c73ea37bc10a52f000000000000000000000000000000000000000000000", .None}, + {.Shl, "256213cb2ed57b1f5e07cc48907c2ce3f15c155579cbb96f7db317427811ae0216ad5fa0ccf39c9ca49fc868927b5365b2e8cfe9399c0afe355ffb72301b6fb4925fa2daeb23c0fec493f9d76fcfc3c5b6db4d49fd7f1399438c0a1d32f3b86ca41d10fba9450d2e2515791ff5079e551b7041176887c4f6046af9a50dea9bf2c2ba33a3a6ecead45f7645a3f58470934bf71b5e7663a5908444b8094fdcd4cf683d19c512a19dc95ca5bf9e5f63aefe340c34bf08f90ac0cfdc4830df9f3ff75e1874e32f6826ef93e9d0a72686b7bd22636970181ff63dfedf1398f981dab88995ab6e25701835a8de7398da18e3a0f7b50bc68de6217d9a0a55825f8d2144542db04f5cf7331f291a877230b2bc6b7f3ca2f4aa49309414c5c3e760cddfd56c478102bf4ddee91bd13eeb86bfd897201b43d1d55e5953d0310546869c154a0ab19c392ff659a95f8b259559a70b9c07f3b520a4b2c57c629fcc4b411d39dc3dc3286326a4d4a95708d96f1664c122942f70e0597b7642118e4de2ace21d2520c31a716850bff08b45d5d04b73a02e6499e404eb766544436b10d85a7c7e8d6285546c1989ccbb59e5b8d932012b5db2cf386c194a5ae00ad02c92998d2a5862679bfdb8154d57668020c1d513b64f0c446e41e075bf4f1ae502d882c70d4b306cfe0d3fe66d6d891ad944eff7e0d9f67b67484a24d96be0cd6327ad486ca3", "b4", "256213cb2ed57b1f5e07cc48907c2ce3f15c155579cbb96f7db317427811ae0216ad5fa0ccf39c9ca49fc868927b5365b2e8cfe9399c0afe355ffb72301b6fb4925fa2daeb23c0fec493f9d76fcfc3c5b6db4d49fd7f1399438c0a1d32f3b86ca41d10fba9450d2e2515791ff5079e551b7041176887c4f6046af9a50dea9bf2c2ba33a3a6ecead45f7645a3f58470934bf71b5e7663a5908444b8094fdcd4cf683d19c512a19dc95ca5bf9e5f63aefe340c34bf08f90ac0cfdc4830df9f3ff75e1874e32f6826ef93e9d0a72686b7bd22636970181ff63dfedf1398f981dab88995ab6e25701835a8de7398da18e3a0f7b50bc68de6217d9a0a55825f8d2144542db04f5cf7331f291a877230b2bc6b7f3ca2f4aa49309414c5c3e760cddfd56c478102bf4ddee91bd13eeb86bfd897201b43d1d55e5953d0310546869c154a0ab19c392ff659a95f8b259559a70b9c07f3b520a4b2c57c629fcc4b411d39dc3dc3286326a4d4a95708d96f1664c122942f70e0597b7642118e4de2ace21d2520c31a716850bff08b45d5d04b73a02e6499e404eb766544436b10d85a7c7e8d6285546c1989ccbb59e5b8d932012b5db2cf386c194a5ae00ad02c92998d2a5862679bfdb8154d57668020c1d513b64f0c446e41e075bf4f1ae502d882c70d4b306cfe0d3fe66d6d891ad944eff7e0d9f67b67484a24d96be0cd6327ad486ca3000000000000000000000000000000000000000000000", .None}, + {.Shl, "-42e820567bd0ef8189775fc749e5c5ca3e4ff0ce616f46d83259c00c6c06ee4f6fcc029d7473795960ad0d19fb328632cb92b9815863b63c40710fb926627902701efd0c0c31784b25ce15cb619e2ddfbdda5b4018fd3af5991cb306ea6c52527c62d3713b98a71ab55e6df194e2c3899cf28c527910297974cea837da58f776678d613c61ef2ee5f6931621a09875cea2aeb989121894053c4ad02050b365672391fae2651608604a5ec85a6bb9d6235e0aa7416ec1a5f6dd4b785be4a9488e013aa7acfb9853200e078cedd408325bd2745a1777c11e39c778a2539bea173944b976134565600fc6dbcf1f6c7d31fe43e378f90e57b90d7562fea51f73ec4f6102c47fe869497cb4f2f7dc9fb04474ecef900720e90c61176e75c93014bb3489f3be62b77019de437b7aff89f9b2f63ce615751361aafc2ee0f5af6787c0ea7a7872966de06e62de36e6d95193bea2d56ccf65a2924ecbdcdc8dcb54b0bad79befc999ebe1b7f0952f5cbc71c35d73d6b9694bed754f6750280fe7f26ef010744149dc5a099f1db624a55be69a49f204f2fbc4d59c74dc584f11ad4a0a2abbab380a8791870d00dbbc3c2d4dd1f2b2684a53dbc8bf1df72f9a8fc0532a35d79e7158659eee01e6c6625a7de9ed880a27d5e678d4b0dcb3c228cd2e872d909d48433642be12618b06f675fff90227ca4ba6be8043d5fee63aabd489a8efcd6c", "0", "-42e820567bd0ef8189775fc749e5c5ca3e4ff0ce616f46d83259c00c6c06ee4f6fcc029d7473795960ad0d19fb328632cb92b9815863b63c40710fb926627902701efd0c0c31784b25ce15cb619e2ddfbdda5b4018fd3af5991cb306ea6c52527c62d3713b98a71ab55e6df194e2c3899cf28c527910297974cea837da58f776678d613c61ef2ee5f6931621a09875cea2aeb989121894053c4ad02050b365672391fae2651608604a5ec85a6bb9d6235e0aa7416ec1a5f6dd4b785be4a9488e013aa7acfb9853200e078cedd408325bd2745a1777c11e39c778a2539bea173944b976134565600fc6dbcf1f6c7d31fe43e378f90e57b90d7562fea51f73ec4f6102c47fe869497cb4f2f7dc9fb04474ecef900720e90c61176e75c93014bb3489f3be62b77019de437b7aff89f9b2f63ce615751361aafc2ee0f5af6787c0ea7a7872966de06e62de36e6d95193bea2d56ccf65a2924ecbdcdc8dcb54b0bad79befc999ebe1b7f0952f5cbc71c35d73d6b9694bed754f6750280fe7f26ef010744149dc5a099f1db624a55be69a49f204f2fbc4d59c74dc584f11ad4a0a2abbab380a8791870d00dbbc3c2d4dd1f2b2684a53dbc8bf1df72f9a8fc0532a35d79e7158659eee01e6c6625a7de9ed880a27d5e678d4b0dcb3c228cd2e872d909d48433642be12618b06f675fff90227ca4ba6be8043d5fee63aabd489a8efcd6c", .None}, + {.Shl, "c9024dccb2480661424fabb9abe9b44173e8ee7bfef1229fcb770b4cfd17541197f76b3574be033160a57f49deb2747f4e6c98c418ca18037e2a611dd5236f56a43d3f774a996da2669dfcd3fc4c9f58acba5b51498853b8b600ae86336e21e06c1a84ffed483bc4cce2e48c105a176b3d962f6ac1a48a3d7f86ec6f79bf627029ed5d9f613ab879705396cbb5ff3a2165ebec57bb7f34a29c81df0cfa441c9814b8fed3e6af349088cdc84c7d2a9ad042e694fe1cf72024b9da729d38e015e99b43dea9dfbe22b636fe7531bc61998c65a1766e2d90afd1b823390266bb8d47938ca8e0a3523a9f5930162c5f3db81fad08bdfcc2f3ec91e8fa05bca0cf0976c5cb5290e229902ea67c3dc1464fa1cb72388157c1fef67f7cb1804c8cbd397ef2d9bd9b39db47fc74ff94872514f69ea68b83f0bf69d66f5f1a8df140c518a17ce6f08367ef7442ea50f2cb9a2673391a0044457013eac70f50264031efd9155acf3e61e37e6e7530a10846c795272754b7330c91fe9f5a642b8960cb2aec2e12485206e6c7f95283c3578d333a8e78faf19dcadb5d7d46a6425640fc3dd712f8285455c62291031d40c8201a45eb9ae84508c2a5311062135bc6b8b0bd80851d273dc462230bc9d1eba68b969adbb2d0609d4ea4726173cfa6757fa77aaa13c660ddc79677607c397d8b5d04ae757351c586031eb4c71906f069f9e97ec100", "1e0", "c9024dccb2480661424fabb9abe9b44173e8ee7bfef1229fcb770b4cfd17541197f76b3574be033160a57f49deb2747f4e6c98c418ca18037e2a611dd5236f56a43d3f774a996da2669dfcd3fc4c9f58acba5b51498853b8b600ae86336e21e06c1a84ffed483bc4cce2e48c105a176b3d962f6ac1a48a3d7f86ec6f79bf627029ed5d9f613ab879705396cbb5ff3a2165ebec57bb7f34a29c81df0cfa441c9814b8fed3e6af349088cdc84c7d2a9ad042e694fe1cf72024b9da729d38e015e99b43dea9dfbe22b636fe7531bc61998c65a1766e2d90afd1b823390266bb8d47938ca8e0a3523a9f5930162c5f3db81fad08bdfcc2f3ec91e8fa05bca0cf0976c5cb5290e229902ea67c3dc1464fa1cb72388157c1fef67f7cb1804c8cbd397ef2d9bd9b39db47fc74ff94872514f69ea68b83f0bf69d66f5f1a8df140c518a17ce6f08367ef7442ea50f2cb9a2673391a0044457013eac70f50264031efd9155acf3e61e37e6e7530a10846c795272754b7330c91fe9f5a642b8960cb2aec2e12485206e6c7f95283c3578d333a8e78faf19dcadb5d7d46a6425640fc3dd712f8285455c62291031d40c8201a45eb9ae84508c2a5311062135bc6b8b0bd80851d273dc462230bc9d1eba68b969adbb2d0609d4ea4726173cfa6757fa77aaa13c660ddc79677607c397d8b5d04ae757351c586031eb4c71906f069f9e97ec100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-467ef30f007bbca9a0c8d5a62ac21ff51510ff9d43a2f5b9c508fbfac0d3afd76113750b7d75f8c5d4a8a70302cc34bd47c5e308790a265bb55d63333fced652fd2275c32d047351b9c956037d7e8addd753a2253a31537260a648079e47f4f9b48292768343aedbe86a3725d91e563c8d32b118be9b393c812d5796934e0135e06808047d53dbc84a11eaf0c728690e4f6b32ac0c02d3808d1af5b64ad1069c5ad0dd240289a31e147b264347bf500a5bb8df6c8ae5fc3f3a663714821b1a0ed30d0d78661d8ff2b0694f240bb493c4fda5ecdd122f885d3f7c26f575b6a8dda1ea019ae914bdac3bd58ba13473fcf98d72f29b960022785de2fb68a54d8091c64633fd404ef93b8551b9f4d3b01a76663cdba7123108c22ee70a30251a5e77c42f2622709b0be0a032524ac33a9920827d162c1062dbe2e1336cd2d1180ccb7e74ab3e199cb34bb0f798d875882f1ae729764d1e1273888be742693cf95a8a238df55becfa8facb052cdce2c4a38e984181ccbf7ec179ac86ef9f4811e31ccd84233a7b478785c769303da4f231dc29f94195106a56c42bc204e939b0aabbcdf5bc7fb7845fa3de7c870689936e76e41140f2d0a733b6285b94ae734c138325390c8f2a9132cf8c25983c29789536795b0cd54e448575392859a5228e208470077ae4b52de7905b89606bd4f4b1ceb1d9afbd17dd7774b9e08675e2967c21f", "b4", "-467ef30f007bbca9a0c8d5a62ac21ff51510ff9d43a2f5b9c508fbfac0d3afd76113750b7d75f8c5d4a8a70302cc34bd47c5e308790a265bb55d63333fced652fd2275c32d047351b9c956037d7e8addd753a2253a31537260a648079e47f4f9b48292768343aedbe86a3725d91e563c8d32b118be9b393c812d5796934e0135e06808047d53dbc84a11eaf0c728690e4f6b32ac0c02d3808d1af5b64ad1069c5ad0dd240289a31e147b264347bf500a5bb8df6c8ae5fc3f3a663714821b1a0ed30d0d78661d8ff2b0694f240bb493c4fda5ecdd122f885d3f7c26f575b6a8dda1ea019ae914bdac3bd58ba13473fcf98d72f29b960022785de2fb68a54d8091c64633fd404ef93b8551b9f4d3b01a76663cdba7123108c22ee70a30251a5e77c42f2622709b0be0a032524ac33a9920827d162c1062dbe2e1336cd2d1180ccb7e74ab3e199cb34bb0f798d875882f1ae729764d1e1273888be742693cf95a8a238df55becfa8facb052cdce2c4a38e984181ccbf7ec179ac86ef9f4811e31ccd84233a7b478785c769303da4f231dc29f94195106a56c42bc204e939b0aabbcdf5bc7fb7845fa3de7c870689936e76e41140f2d0a733b6285b94ae734c138325390c8f2a9132cf8c25983c29789536795b0cd54e448575392859a5228e208470077ae4b52de7905b89606bd4f4b1ceb1d9afbd17dd7774b9e08675e2967c21f000000000000000000000000000000000000000000000", .None}, + {.Shl, "9ca321cbdd1befb67724d84555f0286181118f7a1fa8416190ff946847c58bf88734d809c08b9d3767d6c1e471479bb4741a374e7a553ba11cf2dd40ce5687d3dd17b003b4327a7bb42eaeea9f940c76037926312a1482cd2491861aa94b2fcb7f4993fe52224ff950839c0e93d5368419c43f20d7f09331823089e27a99b4d06c1bf89569122deb391c8e6512df5408e94af33de33bc650c10be9038e8b52cd656a442c59ab8945b66d770770af86637d89089f00e79a6638568b766dc19af82ec599d3331203a3bb3cd6c86a74934b17f4eb7709df124229c675c06e62c118b562eabebbab4ed0a1708a2266d3f91533160f63ec1e5e6d61898e1f60cb63761dbf777a588b89f54e865e7c564e3d763c4d6846e94056d52c9da60364641cfc9c9b3a4a4029d2c52250b390c61721548f4b8060ddfcf8ce4769d836edd299dfe0008c050e4389985ed4e9d89f38fc7de413a40d68e778d3d7e1a4716d38b6e75b81fed705fe75ebbc33ad9fc1326618031552e0796ca5afbde6d1f24ad327c6ee2d849982e7275e6e349dfd89226eb300002f3fc6c897d61d9c6b6f09700a1700ad13bbf286b4138e2aa0aced2d50274e90a7ca7762201e9f61aee293ae5c9ef1c64ae0dd4bf5da6b6bea399277b2ec56c5c664bd33811e419d03bbe34abdd109980af2e273970314097b73a079e47022b2c5b74ffcb16e702eb6ca59e221a7", "b4", "9ca321cbdd1befb67724d84555f0286181118f7a1fa8416190ff946847c58bf88734d809c08b9d3767d6c1e471479bb4741a374e7a553ba11cf2dd40ce5687d3dd17b003b4327a7bb42eaeea9f940c76037926312a1482cd2491861aa94b2fcb7f4993fe52224ff950839c0e93d5368419c43f20d7f09331823089e27a99b4d06c1bf89569122deb391c8e6512df5408e94af33de33bc650c10be9038e8b52cd656a442c59ab8945b66d770770af86637d89089f00e79a6638568b766dc19af82ec599d3331203a3bb3cd6c86a74934b17f4eb7709df124229c675c06e62c118b562eabebbab4ed0a1708a2266d3f91533160f63ec1e5e6d61898e1f60cb63761dbf777a588b89f54e865e7c564e3d763c4d6846e94056d52c9da60364641cfc9c9b3a4a4029d2c52250b390c61721548f4b8060ddfcf8ce4769d836edd299dfe0008c050e4389985ed4e9d89f38fc7de413a40d68e778d3d7e1a4716d38b6e75b81fed705fe75ebbc33ad9fc1326618031552e0796ca5afbde6d1f24ad327c6ee2d849982e7275e6e349dfd89226eb300002f3fc6c897d61d9c6b6f09700a1700ad13bbf286b4138e2aa0aced2d50274e90a7ca7762201e9f61aee293ae5c9ef1c64ae0dd4bf5da6b6bea399277b2ec56c5c664bd33811e419d03bbe34abdd109980af2e273970314097b73a079e47022b2c5b74ffcb16e702eb6ca59e221a7000000000000000000000000000000000000000000000", .None}, + {.Shl, "-4e0bf87f8b7bbe1344f771c7ca98fa4cee84ef43133e6eca1ccaf73f9b835fdc911af5c5c7122dec60c62bbac29ff35e8fe67a6d7ad3abebcf23c170c3f127badb72aeaa7a0cbe1ce51b0479160a906573b254532c9d937c8fc3b4f115ed0d29fa0fccafc975e4043c3cf35a72da8b3d6af80e292e5d0fe4e0915bd71eab87ffa3b25b9941d3e230be2fcb77b93a92e73325f2c8c9c91048dbeaffe5078d9c881d56165eecb000a98f488e3f0c92ff3854132a3e20bedd42613bf7663aea264e74b32bd3bc588c554e2c5bad2ab89063e8b2858b8fb2f8221eeab473460d6f04a1243a44defe9b962ca17afdc55c11fde5e83eb902b78986231900c613f9519c583ea57f82ce148030307b64653c13294033237039a1e466de972c56356cac5a2452d5e72c7a7aa2cb51a84112d3e392e3f7d96ccf5aa514b5e4205cb7b7f99b963219d82b9f2023d9a17d3d13eb180fc81ab18aa2b0fcdeff6313c4430d36505e8a2f1e5b08d1c3fed5ce531e1489742fee7991172e3a46343272e3db69375acef081c3f3b108697bba9107bd1773e6754eff36dae17ea693d6565f830cf8fe42a4dc59fd618f94489bf9d4512edfde0f1c71bbc17a0910328af9797df2f20250e649a53c417ef83f349eac4187149cec61a56317f7df810937f00bd28b02b8e4a99090cfeddd4fa5e4f992f3513ead1370ce869b61afc68c24b1e139f735e4", "78", "-4e0bf87f8b7bbe1344f771c7ca98fa4cee84ef43133e6eca1ccaf73f9b835fdc911af5c5c7122dec60c62bbac29ff35e8fe67a6d7ad3abebcf23c170c3f127badb72aeaa7a0cbe1ce51b0479160a906573b254532c9d937c8fc3b4f115ed0d29fa0fccafc975e4043c3cf35a72da8b3d6af80e292e5d0fe4e0915bd71eab87ffa3b25b9941d3e230be2fcb77b93a92e73325f2c8c9c91048dbeaffe5078d9c881d56165eecb000a98f488e3f0c92ff3854132a3e20bedd42613bf7663aea264e74b32bd3bc588c554e2c5bad2ab89063e8b2858b8fb2f8221eeab473460d6f04a1243a44defe9b962ca17afdc55c11fde5e83eb902b78986231900c613f9519c583ea57f82ce148030307b64653c13294033237039a1e466de972c56356cac5a2452d5e72c7a7aa2cb51a84112d3e392e3f7d96ccf5aa514b5e4205cb7b7f99b963219d82b9f2023d9a17d3d13eb180fc81ab18aa2b0fcdeff6313c4430d36505e8a2f1e5b08d1c3fed5ce531e1489742fee7991172e3a46343272e3db69375acef081c3f3b108697bba9107bd1773e6754eff36dae17ea693d6565f830cf8fe42a4dc59fd618f94489bf9d4512edfde0f1c71bbc17a0910328af9797df2f20250e649a53c417ef83f349eac4187149cec61a56317f7df810937f00bd28b02b8e4a99090cfeddd4fa5e4f992f3513ead1370ce869b61afc68c24b1e139f735e4000000000000000000000000000000", .None}, + {.Shl, "-849bd0179537e278bde3b311e3c38e64f02b7a3e4858f7c68e9df29c21cda2e14814cb86150a96790c0e527119314139e165b00f026c90d2de0cf7e164bf21cfb653037971c620a9fdc2ab7111d0ff13bb98d49e05719d92ea875a16a0bf496722245163f6c4081c6154b15cb931684fea8e00b99c40c90ef789950ce95e541919f3a423fde5c5dfc1a8cc5a130d96404c894d3131aa968576a5f83cbdce13143140f1f29f61e1f3fe966b198b4971095db50035889aeae0ad09b76c016785dbaa18ea20a7ca873666be59dfdeab4583003f95aa9601818c92b0d0d9217421825d0c8f00093b03c1d1525d7b3f50037a5a95224e346282c70854d9f0565115af158d64615485c893dfbdbfac876d59071c72d8726aae8de4ab128212b0ac60709fa670ab23be6eece9c1e73067fd52e471acb97239bf40ee1d473af0d2d3bec49e7516d2de6ecb790f576b59bcf7423460eb04f3b194c98e13a32fe02f719b789ea3a87087074ceed6bc825696fe9427e898292a05e9ed3afe6781c0c7bc465181ddd8e3ffd8bb11e46eba641e4e35ea6222cd342ebd6549412586df264c735ff9eec66a3e85f524caff288fc41362307ee9e7c762d38d84614de2235838f2dbb58d4ba37628b9fdab825dca34f5cd17b0edb3c502236bf64d3de66ab78dbd7cc390380fdcb43a6e8c333fcff5d01ca1dba4ab3597e35581b6597532aa682f53", "1a4", "-849bd0179537e278bde3b311e3c38e64f02b7a3e4858f7c68e9df29c21cda2e14814cb86150a96790c0e527119314139e165b00f026c90d2de0cf7e164bf21cfb653037971c620a9fdc2ab7111d0ff13bb98d49e05719d92ea875a16a0bf496722245163f6c4081c6154b15cb931684fea8e00b99c40c90ef789950ce95e541919f3a423fde5c5dfc1a8cc5a130d96404c894d3131aa968576a5f83cbdce13143140f1f29f61e1f3fe966b198b4971095db50035889aeae0ad09b76c016785dbaa18ea20a7ca873666be59dfdeab4583003f95aa9601818c92b0d0d9217421825d0c8f00093b03c1d1525d7b3f50037a5a95224e346282c70854d9f0565115af158d64615485c893dfbdbfac876d59071c72d8726aae8de4ab128212b0ac60709fa670ab23be6eece9c1e73067fd52e471acb97239bf40ee1d473af0d2d3bec49e7516d2de6ecb790f576b59bcf7423460eb04f3b194c98e13a32fe02f719b789ea3a87087074ceed6bc825696fe9427e898292a05e9ed3afe6781c0c7bc465181ddd8e3ffd8bb11e46eba641e4e35ea6222cd342ebd6549412586df264c735ff9eec66a3e85f524caff288fc41362307ee9e7c762d38d84614de2235838f2dbb58d4ba37628b9fdab825dca34f5cd17b0edb3c502236bf64d3de66ab78dbd7cc390380fdcb43a6e8c333fcff5d01ca1dba4ab3597e35581b6597532aa682f53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "393bbd970e759fc35b8aa943fd92774c4a4315415909a054c9d18ca5b81119eaf613e0cea9f79f7cd8706da6ff566395b177f55c483685659ad856d9f5a5c814dde53a55e55377858c669258451a6d0f246e30141a2d4a41ea895b49444eaae50d1892bf0495bc12206da1ab50ab35f3a3f1978593f5996b4cb0bd5d814b8934201318ce8428d0dc2ffe3fc0a916509be24c3a0632add2767faf27dc90f23eb2bff7fa6dd5706e70a67b635a0d670feb817174200f1578a65022b4bb6c5ce103b4a57d84281e3aa17c445c07bbd9445b10650d645bbfcfba0db966c959f2bd9f3a48ae76ccf5000fb2e1d91e83e33aa463646b71e8a20e6e17035984c3b215f2566fbfe3f6d88f74f46cab4e9b414f7cb0ad61e3974fe93fff3e0af61e913cb053fceee54ff75c23ddc289a6bda6dd398d1e7fbb916a8e3f83d495402291f8195d4e4675ad501c4973fc59446c7060b5b6d1aab89637bf8191135dd926b17b21120a0d28a5a65698dac93220a118cc1d817a3af7d4e7c5028b1100cf368eb248a43335c9e2e13215e18f696c651e1a47e5579f0eaac21434406cd3042e00174ae7ab5c5e09860faaf06170e0151d90d734dd3db441ba2c7b9c12f0b1093684fed0967ca9ba6ee5297f10530025ee29d7d2ef0581c932cc557bcbd5589930f1246216852e0a87cc7495987ca4a8c35d4ec90761de2b441879a8655ce6638c7083", "0", "393bbd970e759fc35b8aa943fd92774c4a4315415909a054c9d18ca5b81119eaf613e0cea9f79f7cd8706da6ff566395b177f55c483685659ad856d9f5a5c814dde53a55e55377858c669258451a6d0f246e30141a2d4a41ea895b49444eaae50d1892bf0495bc12206da1ab50ab35f3a3f1978593f5996b4cb0bd5d814b8934201318ce8428d0dc2ffe3fc0a916509be24c3a0632add2767faf27dc90f23eb2bff7fa6dd5706e70a67b635a0d670feb817174200f1578a65022b4bb6c5ce103b4a57d84281e3aa17c445c07bbd9445b10650d645bbfcfba0db966c959f2bd9f3a48ae76ccf5000fb2e1d91e83e33aa463646b71e8a20e6e17035984c3b215f2566fbfe3f6d88f74f46cab4e9b414f7cb0ad61e3974fe93fff3e0af61e913cb053fceee54ff75c23ddc289a6bda6dd398d1e7fbb916a8e3f83d495402291f8195d4e4675ad501c4973fc59446c7060b5b6d1aab89637bf8191135dd926b17b21120a0d28a5a65698dac93220a118cc1d817a3af7d4e7c5028b1100cf368eb248a43335c9e2e13215e18f696c651e1a47e5579f0eaac21434406cd3042e00174ae7ab5c5e09860faaf06170e0151d90d734dd3db441ba2c7b9c12f0b1093684fed0967ca9ba6ee5297f10530025ee29d7d2ef0581c932cc557bcbd5589930f1246216852e0a87cc7495987ca4a8c35d4ec90761de2b441879a8655ce6638c7083", .None}, + {.Shl, "-cacaaaabf4a0f6bc2a220f0d2d115ce7cb2078b81b5ba27e53c197800351e59b7a31305b8d4a2347667d3108c98c95957788a7b0af7e3ce466bfa3ada704e75b885721313c9ad0fbc547b97c4a84f4aecce401e58bd05a590e5caa9dd2d0a2e46eb960f3571f91c729a1b493ede94c82149f74879bb438a801b18b6d53d8d4ceee97b382d71cb2cf4df6579bf9b63de18692013590a459c3f45221a2c587f8dff11d109b0b7537a69f8624cb5de4d148a20087d0531c51c81fff2cb92d19014d6ceb3305d8eab6b8bec6d35db2199f213bcdca0156920eab339606639ed58ac9e8ebce7a2f5e95f50e5e4a52b0d4c5513bc29c303e2f0d73b03d7b3eff7969ea377e2b2ec526966e7ee0bb5b6d7fb48a388823182fa6d56d4b9aaefc78ffef89825cfcdc894d55fd851476bdc0d7ebf52be8971b8c0337ae448e1117e087ad460f4f053af1787b0884e4e89d97858056f6f0e3d51a7806412eb799277e531a5f4875294cdf8c8c493a7512c6063e3d94aabad8a83bf4512b371dcec0f7ffdbed710bcc194f8b9864c9bf1877a9b6f1301ab9d8c44fc5d4bc6cbff3acabe2cfd18e42c35e47306ac1ade3f2aa99a059540e7425d5fa3366fb9e566c34cd7e714615c37ee8f45ecbd38db91b46d61c943a394227d3d23115f15a4da46f00abbb5b722fddb1a912dc219ccd204bd1160138b5339b08735881943d68ee4573484a57", "3c", "-cacaaaabf4a0f6bc2a220f0d2d115ce7cb2078b81b5ba27e53c197800351e59b7a31305b8d4a2347667d3108c98c95957788a7b0af7e3ce466bfa3ada704e75b885721313c9ad0fbc547b97c4a84f4aecce401e58bd05a590e5caa9dd2d0a2e46eb960f3571f91c729a1b493ede94c82149f74879bb438a801b18b6d53d8d4ceee97b382d71cb2cf4df6579bf9b63de18692013590a459c3f45221a2c587f8dff11d109b0b7537a69f8624cb5de4d148a20087d0531c51c81fff2cb92d19014d6ceb3305d8eab6b8bec6d35db2199f213bcdca0156920eab339606639ed58ac9e8ebce7a2f5e95f50e5e4a52b0d4c5513bc29c303e2f0d73b03d7b3eff7969ea377e2b2ec526966e7ee0bb5b6d7fb48a388823182fa6d56d4b9aaefc78ffef89825cfcdc894d55fd851476bdc0d7ebf52be8971b8c0337ae448e1117e087ad460f4f053af1787b0884e4e89d97858056f6f0e3d51a7806412eb799277e531a5f4875294cdf8c8c493a7512c6063e3d94aabad8a83bf4512b371dcec0f7ffdbed710bcc194f8b9864c9bf1877a9b6f1301ab9d8c44fc5d4bc6cbff3acabe2cfd18e42c35e47306ac1ade3f2aa99a059540e7425d5fa3366fb9e566c34cd7e714615c37ee8f45ecbd38db91b46d61c943a394227d3d23115f15a4da46f00abbb5b722fddb1a912dc219ccd204bd1160138b5339b08735881943d68ee4573484a57000000000000000", .None}, + {.Shl, "-bf9ef327d8275024f8ac1357a4daab50ee2df6c814d1644ec286e37485ddb0d04ff340671714e641ec8f141d159a3da1b548f054730e81b861ede530433fe721a9c577ccb557d75fdf7f5a07d2480010a9e896f9598cd7d9564c07f9f85b46346ab81aef26894d5f47b5d8158cb9654db93fe791d104f05e4f25bfb86500302fd33f256d034c4d21a9dd88e2fbf7ebcc16b9898d0ffd5e06d112648846282e9f7f2d9698215a3087d2b480418d255737d6dc2cc81ac4f1d7833da985dc982fc3f00a5b3d1d972f345da3f69b8ce418238f1a4eead96ad5bd841e96878c508ff625db11715e2cbcddc54d16f34e33f0f53bb75d9a5cfb414863d6225a6e92aee64c3a16d1911cfb503d56ac209ae96cace6bc3806e288a5313bf6f3e548bf163852ee965be7f2163c94510793e2850c0b0c2d2815eee2f4078b3c8652c0a39fbc84db095985025a9c422779ada62077b6d10479b5c7289f55d77a22691710b17110f5a98450af370d122b234d5e5c10c665a09a09d50b2e5a9f4f21eb9f1afbfedcaeed1b2733a6b787bca3d6464b917cd98069e732414e4d60759fad6c572952b07c7f51058ade7dfa692f4cdd1b0bc97db6675ed139d23f3f8e20386a7c04e8c61d9e20033495ee25a5cfdc05e2eb370fa629b39ce2fe0fdc3b1df22faaba8741032528d6f06f4c128e39fa94459c7737d750f90771176f24d7545d21a26aee", "78", "-bf9ef327d8275024f8ac1357a4daab50ee2df6c814d1644ec286e37485ddb0d04ff340671714e641ec8f141d159a3da1b548f054730e81b861ede530433fe721a9c577ccb557d75fdf7f5a07d2480010a9e896f9598cd7d9564c07f9f85b46346ab81aef26894d5f47b5d8158cb9654db93fe791d104f05e4f25bfb86500302fd33f256d034c4d21a9dd88e2fbf7ebcc16b9898d0ffd5e06d112648846282e9f7f2d9698215a3087d2b480418d255737d6dc2cc81ac4f1d7833da985dc982fc3f00a5b3d1d972f345da3f69b8ce418238f1a4eead96ad5bd841e96878c508ff625db11715e2cbcddc54d16f34e33f0f53bb75d9a5cfb414863d6225a6e92aee64c3a16d1911cfb503d56ac209ae96cace6bc3806e288a5313bf6f3e548bf163852ee965be7f2163c94510793e2850c0b0c2d2815eee2f4078b3c8652c0a39fbc84db095985025a9c422779ada62077b6d10479b5c7289f55d77a22691710b17110f5a98450af370d122b234d5e5c10c665a09a09d50b2e5a9f4f21eb9f1afbfedcaeed1b2733a6b787bca3d6464b917cd98069e732414e4d60759fad6c572952b07c7f51058ade7dfa692f4cdd1b0bc97db6675ed139d23f3f8e20386a7c04e8c61d9e20033495ee25a5cfdc05e2eb370fa629b39ce2fe0fdc3b1df22faaba8741032528d6f06f4c128e39fa94459c7737d750f90771176f24d7545d21a26aee000000000000000000000000000000", .None}, + {.Shl, "5134cc48c59668aa9068f5d1433f0902d7023c5f7af6394a8420d05b17a15fd84cb19535f2419475f190aa1826d6a31756d4cf67a4d8ffc600f8ae4e731217860f84ed45a407ad80d4b7613496ce4cddcea1ac38c0d99eedd614dc2c7e2ef65a495a9702bc15276d9ebe6935665cafb4ec3fd46ad2733f050396cc91a655f4101d327a580ab7324f445072e4f6cf0f58b409f47853c98e3b246995ecec4be5e566ec78f3ee5efb6cbe48c46766c3e2ba412365508e09eacc464557e1b97d1a70d177ff20f18d7a96aa05788d4408501a4b8dee312613a26df7e3cfb11da5a2299b436f825452d0854031abb6a1d9896f5104b6eab8417600331ba39bd0b0c82838b4e43d944b9443f1124032b92a3504db621a577b3eb9c34c7d1175a40fb8ac3f4742049def4bfec4a3e7085cfd3410cd4ba429c217846f1f1cbdef3b998c80a15e7d49c89e8d986b267053058cfe8809b2c8e4e5b8e24780c9d4b9f26d18f21e133f6df018e00cb8e6f6e8ad27b78e39502f201554a1eb2b250a2311d3c217d8595c23c0b95837d29791bf39344f56ab423cf63ba763c1499db6d72e948c46c639b51784be81fa11958a8760979221f4631db44e5140a75870cd4862d764e0786f65fc14ae0335d81c6ed141ecb0d2c864ba0a074e0434054c965b52643fabc6b7979f599aa7b92523ebc4a53c58c0568e3c34dbc8a3718a8841cd4b92eda8", "1e0", "5134cc48c59668aa9068f5d1433f0902d7023c5f7af6394a8420d05b17a15fd84cb19535f2419475f190aa1826d6a31756d4cf67a4d8ffc600f8ae4e731217860f84ed45a407ad80d4b7613496ce4cddcea1ac38c0d99eedd614dc2c7e2ef65a495a9702bc15276d9ebe6935665cafb4ec3fd46ad2733f050396cc91a655f4101d327a580ab7324f445072e4f6cf0f58b409f47853c98e3b246995ecec4be5e566ec78f3ee5efb6cbe48c46766c3e2ba412365508e09eacc464557e1b97d1a70d177ff20f18d7a96aa05788d4408501a4b8dee312613a26df7e3cfb11da5a2299b436f825452d0854031abb6a1d9896f5104b6eab8417600331ba39bd0b0c82838b4e43d944b9443f1124032b92a3504db621a577b3eb9c34c7d1175a40fb8ac3f4742049def4bfec4a3e7085cfd3410cd4ba429c217846f1f1cbdef3b998c80a15e7d49c89e8d986b267053058cfe8809b2c8e4e5b8e24780c9d4b9f26d18f21e133f6df018e00cb8e6f6e8ad27b78e39502f201554a1eb2b250a2311d3c217d8595c23c0b95837d29791bf39344f56ab423cf63ba763c1499db6d72e948c46c639b51784be81fa11958a8760979221f4631db44e5140a75870cd4862d764e0786f65fc14ae0335d81c6ed141ecb0d2c864ba0a074e0434054c965b52643fabc6b7979f599aa7b92523ebc4a53c58c0568e3c34dbc8a3718a8841cd4b92eda8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b7d42c6ca8783312d5d60819586ab645a63045e51cc0a1e535614034344dff23286960d3d2dd879d3683e8a6044b87d536c501e245b84e1f06528da71b4fabd72c1135374afc49ac39b15880dea7a50e7f8a76c22cfd160922fe661572bf5624f57bcc09085b2b4b053da1b9fd464f1eeab92b36be6106c7c7e8c0af441785e251e76d55fe6b5baf37e6d25333009596c0d8de82051f6b0e3cedf0c29433d86ecdcdd4700d8b032f20cba68e68635e8dd15d0d4e381c31c75a65781c3814ad4d97b2600fa47ac4a5a936a6ed6974032c67f05d8aefe2f7d013bef63d4a84e9ef45a259a9f9bd9cd9df1c85c457605b5ccd59930bbd54be635e5c9ae26f3fbde431c9cc228082188b78bca02194b41abe666b2f8f6ca13e9087bad10019e06d369bfbf45aa606ecded1493a5182f5f29237387b01c9c6980dcab0bb6900281969c358eaac8d92f7262c9baa4c8efd0307b467df99cb76fd755b3641bef5db96447faf1e714553687dc6a5109ede5f5215c13577bc129f22fd32bfd18121178039eef7893fef0aea2e7b0f7eef327ff38da7aa8392aef1bd6519fb98e43ab7f82fa2ecae0f04d1614568133ceb7598429401388995d384de700f2e35233400e4a1090c96d8d70ba00039180f4753618bd09793024d3964668a2732f56e7915b94e6ebdf61f7d4f2cfa04fb71fdd1cc0819c0f0f0ae8ac0ddf3edc435dd0bd15be0", "1e0", "-b7d42c6ca8783312d5d60819586ab645a63045e51cc0a1e535614034344dff23286960d3d2dd879d3683e8a6044b87d536c501e245b84e1f06528da71b4fabd72c1135374afc49ac39b15880dea7a50e7f8a76c22cfd160922fe661572bf5624f57bcc09085b2b4b053da1b9fd464f1eeab92b36be6106c7c7e8c0af441785e251e76d55fe6b5baf37e6d25333009596c0d8de82051f6b0e3cedf0c29433d86ecdcdd4700d8b032f20cba68e68635e8dd15d0d4e381c31c75a65781c3814ad4d97b2600fa47ac4a5a936a6ed6974032c67f05d8aefe2f7d013bef63d4a84e9ef45a259a9f9bd9cd9df1c85c457605b5ccd59930bbd54be635e5c9ae26f3fbde431c9cc228082188b78bca02194b41abe666b2f8f6ca13e9087bad10019e06d369bfbf45aa606ecded1493a5182f5f29237387b01c9c6980dcab0bb6900281969c358eaac8d92f7262c9baa4c8efd0307b467df99cb76fd755b3641bef5db96447faf1e714553687dc6a5109ede5f5215c13577bc129f22fd32bfd18121178039eef7893fef0aea2e7b0f7eef327ff38da7aa8392aef1bd6519fb98e43ab7f82fa2ecae0f04d1614568133ceb7598429401388995d384de700f2e35233400e4a1090c96d8d70ba00039180f4753618bd09793024d3964668a2732f56e7915b94e6ebdf61f7d4f2cfa04fb71fdd1cc0819c0f0f0ae8ac0ddf3edc435dd0bd15be0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-5eff0c9ba85d89b4f49a6996ea94e06185428baac85287cb4c8b9596b3835ff900c40a7d8686a633bb21c11ca6ad00cf81c4c045af06bf7de162f4485395c5768831b7e556aa9d2c5b4775af67988eb6c6e5874bf42f6cfbc4c6ca39d6ff4d759e0a75e6172df01305712b8164e806eff86debe670a8898fd346c1577526b70381225d4f63a10ee3a24fca424e69fbd0fd5c8df33d4a6e43a4b78975de1b674bbae7695bd34298af8b5a8ea7dae7e30fec4f53528166c5261f98eefc1587789e8eafb03c7a4704da66291bbdc66e65e050a99e2306626e3948903e0a1886335155d796d4c3266bdc04b3c712b804e72db9a98b88b7d711f95e1aed160961bf5cff5d09e54493c9ac1badce2a6135c1bb8122c19cb6969f8c0ebb8a4e8b4c65ecfba4464f1e961eed1644527bf9fe5160148270d0ca02eb40b8e282c910900eb6b3936641d28c0dd18d1e9429147cc5e7123e52b9dcb5daad3e430e5c238adec9272a8be59deaf1e0d6fe1adcd055ea65b8f3794d8fc0000d66c9dece08cc3e3f9793721a3d9e00da3006032adad09f0d73e709c95127b3568ad9240891e8f3b25bbe582496cf24acf1e690bdd776dc7cdb0c898d155e14727930643df4c5e4ecde8f1311f9bece4c7e2f143197d6a7e3b5c7116b176dd76fcb7e123f053b8d81534e71061bc42526bad4193db23b49b6ac03eb80bb159a1057fc7bb597713d0b", "78", "-5eff0c9ba85d89b4f49a6996ea94e06185428baac85287cb4c8b9596b3835ff900c40a7d8686a633bb21c11ca6ad00cf81c4c045af06bf7de162f4485395c5768831b7e556aa9d2c5b4775af67988eb6c6e5874bf42f6cfbc4c6ca39d6ff4d759e0a75e6172df01305712b8164e806eff86debe670a8898fd346c1577526b70381225d4f63a10ee3a24fca424e69fbd0fd5c8df33d4a6e43a4b78975de1b674bbae7695bd34298af8b5a8ea7dae7e30fec4f53528166c5261f98eefc1587789e8eafb03c7a4704da66291bbdc66e65e050a99e2306626e3948903e0a1886335155d796d4c3266bdc04b3c712b804e72db9a98b88b7d711f95e1aed160961bf5cff5d09e54493c9ac1badce2a6135c1bb8122c19cb6969f8c0ebb8a4e8b4c65ecfba4464f1e961eed1644527bf9fe5160148270d0ca02eb40b8e282c910900eb6b3936641d28c0dd18d1e9429147cc5e7123e52b9dcb5daad3e430e5c238adec9272a8be59deaf1e0d6fe1adcd055ea65b8f3794d8fc0000d66c9dece08cc3e3f9793721a3d9e00da3006032adad09f0d73e709c95127b3568ad9240891e8f3b25bbe582496cf24acf1e690bdd776dc7cdb0c898d155e14727930643df4c5e4ecde8f1311f9bece4c7e2f143197d6a7e3b5c7116b176dd76fcb7e123f053b8d81534e71061bc42526bad4193db23b49b6ac03eb80bb159a1057fc7bb597713d0b000000000000000000000000000000", .None}, + {.Shl, "571eced1adc355f12e629277b73027223c5031f2bcf5f1b64c6041230a212ac3b65781ff5ef41ce86aa18ddf6288b37f7ea66e0ba5a1f06e02e238d5f8c5d55175c7ff4819ed39f22f039cb349f962ea604ad5d97a15b4fe4ee973ec414c16b61e3d3798b6aef9394e7fb61eaca19d84275d891dd44a7dbc2c5391860796cda98a321ddd45b471d87ff6471f8c0f2ba0784bbbbb3c46a7a1cb2fc954d36d770f80e2eefd0cc2621ec6a627d79277796b8becd106ad8ccfaa681cf89e9ad40e46fca51f499a10f4f40971a579bea180eb316a6811c59a7dcef6a4cd84b87582132b3f16cc4bfb7fdd121f1c35028e20275122f7a20877e84411c05a9efe615164e1dfa8a5d686baedfface93ee332663aa02624df1cd25936cc5954a63067e91e4b697002139abcc7c836c5bcf388643d347519203b6a53d2bef771d6a21757915f17ba2433698ce4c48e6f65a3a286ca6e238e81c6b3b6da6cf27f48b9a853992774c343dd2010039a2f4331f4c1856fd3c1832352ac5b985decc7b906feaa3b4e24e667b8d7b2cc0a2c5bf295893f4efc71e26a25c4db1b45849065194bc89316ac788db521a1d6b49bf410dfbc382e49590a928a187c152816f99fcf96ba8f334638a00d8d6499ab3e00d01d73bbdea3300f41dbc1b7cdc68c52d69c1f09424957e6f51f0c32b9d8523d4357104c13deffbb8e13212a6b4448c067689c5317", "168", "571eced1adc355f12e629277b73027223c5031f2bcf5f1b64c6041230a212ac3b65781ff5ef41ce86aa18ddf6288b37f7ea66e0ba5a1f06e02e238d5f8c5d55175c7ff4819ed39f22f039cb349f962ea604ad5d97a15b4fe4ee973ec414c16b61e3d3798b6aef9394e7fb61eaca19d84275d891dd44a7dbc2c5391860796cda98a321ddd45b471d87ff6471f8c0f2ba0784bbbbb3c46a7a1cb2fc954d36d770f80e2eefd0cc2621ec6a627d79277796b8becd106ad8ccfaa681cf89e9ad40e46fca51f499a10f4f40971a579bea180eb316a6811c59a7dcef6a4cd84b87582132b3f16cc4bfb7fdd121f1c35028e20275122f7a20877e84411c05a9efe615164e1dfa8a5d686baedfface93ee332663aa02624df1cd25936cc5954a63067e91e4b697002139abcc7c836c5bcf388643d347519203b6a53d2bef771d6a21757915f17ba2433698ce4c48e6f65a3a286ca6e238e81c6b3b6da6cf27f48b9a853992774c343dd2010039a2f4331f4c1856fd3c1832352ac5b985decc7b906feaa3b4e24e667b8d7b2cc0a2c5bf295893f4efc71e26a25c4db1b45849065194bc89316ac788db521a1d6b49bf410dfbc382e49590a928a187c152816f99fcf96ba8f334638a00d8d6499ab3e00d01d73bbdea3300f41dbc1b7cdc68c52d69c1f09424957e6f51f0c32b9d8523d4357104c13deffbb8e13212a6b4448c067689c5317000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-d74621b612cc4868819f2339c41c6b3ca09854b1382dc5f08f50bee5aa10a0c2553eec7ec6581f619b0f797b164bda69639a1397b64d235bd8de22de4aed2a0938a5fcd31395b432793d52ecbb5a6c8e2a9b72991c9e48b5aefc79b9a16b4d627857fd9527d04c921c14bcb01ad75417157a64c45169ca607535b1d6e574889d17af876a741b624931ec9012488d361fc6a94cc0460e32f4d197d7a0a2ca1b9e2546eac2f8c8bd36e478e86d09caa194f97f97b57722f4bd0b42ff8a5c6dc48a547c412937d3b410c06219a2b4e12b33685992f348139627522596e57031073399a23e07efc1c6b1250bbbbd038472798d26fd3d526e725c469f999f78b5baf6f81cceca63064a93acff98005b1e60fd91ed6c4a6feb17ffad064cb2d1da18cc28005170db242cf033a8e398402afbd9b59a64d0671ccb7bb3b1c07757ce34340d09740a58f0c72e0bbf748e64dc346b80147c4d3fbbcc5042f8e8eda2fb2afd9f5417c720583784ef7614bfe972e1cf4867699f43b0ea8a24c50e29bf77c4be909cbba9213562f124eae920734d325c19d7ddf7f8b176cba91f39660e01047538263cec47388083e7f7cb5ed7a9c1e992042f80e1ddb057501cbcdb2216f561cb86636eebf810f7b8bf1956f23f29bf293775a8aa48bb9a4fec204cbe7b1e4d1054809c53400acea6cfe9b1a2a84897622083f44699f183a930b7aa2cfba1f6", "3c", "-d74621b612cc4868819f2339c41c6b3ca09854b1382dc5f08f50bee5aa10a0c2553eec7ec6581f619b0f797b164bda69639a1397b64d235bd8de22de4aed2a0938a5fcd31395b432793d52ecbb5a6c8e2a9b72991c9e48b5aefc79b9a16b4d627857fd9527d04c921c14bcb01ad75417157a64c45169ca607535b1d6e574889d17af876a741b624931ec9012488d361fc6a94cc0460e32f4d197d7a0a2ca1b9e2546eac2f8c8bd36e478e86d09caa194f97f97b57722f4bd0b42ff8a5c6dc48a547c412937d3b410c06219a2b4e12b33685992f348139627522596e57031073399a23e07efc1c6b1250bbbbd038472798d26fd3d526e725c469f999f78b5baf6f81cceca63064a93acff98005b1e60fd91ed6c4a6feb17ffad064cb2d1da18cc28005170db242cf033a8e398402afbd9b59a64d0671ccb7bb3b1c07757ce34340d09740a58f0c72e0bbf748e64dc346b80147c4d3fbbcc5042f8e8eda2fb2afd9f5417c720583784ef7614bfe972e1cf4867699f43b0ea8a24c50e29bf77c4be909cbba9213562f124eae920734d325c19d7ddf7f8b176cba91f39660e01047538263cec47388083e7f7cb5ed7a9c1e992042f80e1ddb057501cbcdb2216f561cb86636eebf810f7b8bf1956f23f29bf293775a8aa48bb9a4fec204cbe7b1e4d1054809c53400acea6cfe9b1a2a84897622083f44699f183a930b7aa2cfba1f6000000000000000", .None}, + {.Shl, "f310f96d9c054341ba10cd2b2ac63e274fdf68dd8260bfc9bcaf6ccd071f93d0294d138c4c586d6f3885529ae110bf6a61d9a8e9398c88a9046705af2444bd62cdeda26041785a600036fbc1c50599b8bdd2cfc09a7d173948ad75a70b4d9b73d2916062ba59c51fd17689573369ee5d991b1ce68df5dfaa80eb7a29bd656671d9e68235b19956a165bf44b864d00eb41576b16b4c87bc15ce8bb36611ba0a0c2e78c1ce06744900638dc4b0d841aa944deee2dea6133686cb2df26cc831a69e68a03ce2c4065e76ed0e9bfa92d4ca60f637a34b14f1f28071a2822c84e7e50bf733c452153a90f906462da79e2ca8a5c209223294f47058b82541851ad7cf90423a208211d3f1e985c0eabe0bc546eb1744f13fc8f7ed85aab72a8dc90edff379ec7da99096082217aff3e86debae93645258967e67e23e0342b030354ffda7a3ade8df9ad86c5324b2f36b99d9e83a19f5d8ba3ef6d6b2190fdf8ab044ca7a09a1c93714e2f330a5d98b04e3bbd57d47b9b745901b85932586e754d4ff81290b24063dbedc73a6aec1ef97336d783dce0e5ccbfb17311f539f38bec34f2756d65c6fbb32250f82a8b9f568028c71fc2511e47f16b07d221d33a797c80b02d496571f81714e50a58fcc4990a22a55c7baa8e093fe16a0730468fbf2d37ff512ebe4ebed469401a6c57ff9193e19a428edfe73b1df3073dca606ad70b3b41c50", "21c", "f310f96d9c054341ba10cd2b2ac63e274fdf68dd8260bfc9bcaf6ccd071f93d0294d138c4c586d6f3885529ae110bf6a61d9a8e9398c88a9046705af2444bd62cdeda26041785a600036fbc1c50599b8bdd2cfc09a7d173948ad75a70b4d9b73d2916062ba59c51fd17689573369ee5d991b1ce68df5dfaa80eb7a29bd656671d9e68235b19956a165bf44b864d00eb41576b16b4c87bc15ce8bb36611ba0a0c2e78c1ce06744900638dc4b0d841aa944deee2dea6133686cb2df26cc831a69e68a03ce2c4065e76ed0e9bfa92d4ca60f637a34b14f1f28071a2822c84e7e50bf733c452153a90f906462da79e2ca8a5c209223294f47058b82541851ad7cf90423a208211d3f1e985c0eabe0bc546eb1744f13fc8f7ed85aab72a8dc90edff379ec7da99096082217aff3e86debae93645258967e67e23e0342b030354ffda7a3ade8df9ad86c5324b2f36b99d9e83a19f5d8ba3ef6d6b2190fdf8ab044ca7a09a1c93714e2f330a5d98b04e3bbd57d47b9b745901b85932586e754d4ff81290b24063dbedc73a6aec1ef97336d783dce0e5ccbfb17311f539f38bec34f2756d65c6fbb32250f82a8b9f568028c71fc2511e47f16b07d221d33a797c80b02d496571f81714e50a58fcc4990a22a55c7baa8e093fe16a0730468fbf2d37ff512ebe4ebed469401a6c57ff9193e19a428edfe73b1df3073dca606ad70b3b41c50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "65c0b8136b567b40b5ab2ceedb74e0c59b84e183de29a7425042722d93ee0fd00802da12637155e0c8478c99ed546e9e19f75011a3d5387840ef26017051c56fe4214f7b603fd62357bc49fa2cf2c058e36e9d8bf14e702f275999ac3e4df5e4395cc02527652b356ad1d49d82128d61c5667d536284248075ffd5216a971610d65aa2d0be6461fe016f1100765c1baa4345e0ec8a540b3c7869e92ee6d513f7632c16ff5d05bcc9b10a9a56c792c0e020c1654729934c8245f521306832dc961838c1c04980846dd5b05c1803a368055da7556dbff71b0c7e368fc37f6fa2c634d34b8f343a53770c966b0c94708a9bebb58f200139428283c2d800417069697f85f72303f23e8c1b70a3ec47f5d1c6b97150650a1e9bb5667d55c0574c221948acbbab4c90a3f1e9e5204e71f79d2978902d0e874d7c3b6ca0afab3f401356e29730b6b6089499b6a431891ac8aeb9d4ee05315867dc507e338937ba5e75b84fd9aa112b5ccf8042aa1c48a07bbc9790a2ae4b9bd5992da50f165146b6736b94ba4f36d0b448390172378af8693fb7ab8660567684b78637b87fff7274aa8a305a79ac973facd23c8d490f6deced339554f40190f5714cb2107771a8071eb9879b64d8b47386f3b67b32f5a433e93caf15e2dcba6f81b624514d8a543afb1d7a915730cec6e62a1982e36a44d54bdd445c9ca9191bef1736b9261f6f96587c", "258", "65c0b8136b567b40b5ab2ceedb74e0c59b84e183de29a7425042722d93ee0fd00802da12637155e0c8478c99ed546e9e19f75011a3d5387840ef26017051c56fe4214f7b603fd62357bc49fa2cf2c058e36e9d8bf14e702f275999ac3e4df5e4395cc02527652b356ad1d49d82128d61c5667d536284248075ffd5216a971610d65aa2d0be6461fe016f1100765c1baa4345e0ec8a540b3c7869e92ee6d513f7632c16ff5d05bcc9b10a9a56c792c0e020c1654729934c8245f521306832dc961838c1c04980846dd5b05c1803a368055da7556dbff71b0c7e368fc37f6fa2c634d34b8f343a53770c966b0c94708a9bebb58f200139428283c2d800417069697f85f72303f23e8c1b70a3ec47f5d1c6b97150650a1e9bb5667d55c0574c221948acbbab4c90a3f1e9e5204e71f79d2978902d0e874d7c3b6ca0afab3f401356e29730b6b6089499b6a431891ac8aeb9d4ee05315867dc507e338937ba5e75b84fd9aa112b5ccf8042aa1c48a07bbc9790a2ae4b9bd5992da50f165146b6736b94ba4f36d0b448390172378af8693fb7ab8660567684b78637b87fff7274aa8a305a79ac973facd23c8d490f6deced339554f40190f5714cb2107771a8071eb9879b64d8b47386f3b67b32f5a433e93caf15e2dcba6f81b624514d8a543afb1d7a915730cec6e62a1982e36a44d54bdd445c9ca9191bef1736b9261f6f96587c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "da08a3e40647d7b373e761f0b3a0f919b244c5e4bfc74f876bc1e883bcabba9af1975b8cf6bbedb4627b79dda1abb904fb9a7204cf261c6c7872f1e2b9bbc5502685c05716c098c4723356ad6b913179e450a6c576022162e2cfbc30436652a51767e22ca12219819caa086b5b91b0cf167b101b0af043d35badb4022889c67b9c76075df314a26d4bfbd0bf0414cedf15ba5dd9778c20eed62b41246a7861505b23e281f6cb31a8144c08a389081ad708585cf552806bfb24467d5ff0dbd6cccbca36f918e06944e89a76e9d9e0b0bccd9c914b03081f9f77694038e4a0f0bd913e72d1c51ff22373dd46b0549b041811531331f138b1a8d20fb0009e5a177a81e57e1f58bde451d31498f0af4360db5baf116dd76baf6bbcdb0bc8de97013c035136e3d10ee8ae2567d23a676027e81b691817333c69bf91d7deb013df36f16d318f98f625f13593421a5dc0a566504f33e565b093e5222ed08157db1729b0043c839e0959f1ba5e2189895f4246feec31b72487bbc139f35a377c8ce978c8a66119b81c1a7a81f1e25df475a613bb4d4752c471d782a9aa1ae8ea4d507a2d9599c7e3d38cbad86156a0504f98abe8c1d5793998a0bee864a447f98e3240e19deb9860d19640ba483c5390033cb988e73ccd36a10001629ab1140cc2ff3d25d0584d2bfc49f4cc7f142022f039b68a55b9fb9a1ba3c025a8fbe1060b647882", "0", "da08a3e40647d7b373e761f0b3a0f919b244c5e4bfc74f876bc1e883bcabba9af1975b8cf6bbedb4627b79dda1abb904fb9a7204cf261c6c7872f1e2b9bbc5502685c05716c098c4723356ad6b913179e450a6c576022162e2cfbc30436652a51767e22ca12219819caa086b5b91b0cf167b101b0af043d35badb4022889c67b9c76075df314a26d4bfbd0bf0414cedf15ba5dd9778c20eed62b41246a7861505b23e281f6cb31a8144c08a389081ad708585cf552806bfb24467d5ff0dbd6cccbca36f918e06944e89a76e9d9e0b0bccd9c914b03081f9f77694038e4a0f0bd913e72d1c51ff22373dd46b0549b041811531331f138b1a8d20fb0009e5a177a81e57e1f58bde451d31498f0af4360db5baf116dd76baf6bbcdb0bc8de97013c035136e3d10ee8ae2567d23a676027e81b691817333c69bf91d7deb013df36f16d318f98f625f13593421a5dc0a566504f33e565b093e5222ed08157db1729b0043c839e0959f1ba5e2189895f4246feec31b72487bbc139f35a377c8ce978c8a66119b81c1a7a81f1e25df475a613bb4d4752c471d782a9aa1ae8ea4d507a2d9599c7e3d38cbad86156a0504f98abe8c1d5793998a0bee864a447f98e3240e19deb9860d19640ba483c5390033cb988e73ccd36a10001629ab1140cc2ff3d25d0584d2bfc49f4cc7f142022f039b68a55b9fb9a1ba3c025a8fbe1060b647882", .None}, + {.Shl, "744ab0263041f7dca789405eac817ba5b62d6dcf52ac91f2759589998c78f59e96bf41138ba82a4442da3dcb041455b90e092f9d0560ae41c7606f7fe8175f39e2775a71bd7d130c0d0d2b99e346f3f10d3b04c90ac04831f73211dff1c08580d16871e035a853b5cc4f0ef994bd3d7507ee0492477aa7655870e383769010a6aa1cf1272e454509e034504103bddae0ba6507b41c8848d2de512ebd171125ea1cb734ce7c18ea861864d0b5fd071c986d9263417ae9123109439a730b5d4a693ca888b05419ca3b1d3c3586433e04df4b1f42aad633df63e283babe3210f83413d4db3d386a5f8aa00304f7d8dd4ed98988a2225b724dbec83d552ca7bbf2c270a7a298e37d56d45c7d5b61e852b193fcbc7da5b51d86efabba3c6222508e4347fdaf4c10570372c9d882bcced2a753a5a87dd9f371727d0f516dafdb97dcbc683c67be56b3ba7b900e908a4febfbc727e77be57c21853191669d724960b33b8c9f3f1fcf72bb97ba9b7ed339293df827a10a312f806a7f3f125e4c1e480c032f22fe08d7378c3e4a63effc5d5be79cafe318dd114d8d43d5756a58061450059309e556031d914a567921ab88bba3d988b8d3b0d19fc3ab70b2fdf38150a57e381e76fcdaa52c0169cd9db8a3cb4bd7472fe1c6d1216100f604ecfeaab6d864979eb69555949c0c313c3afbd5217f5ed10a7a79f8521b366c3a6c8f0080d3b5", "12c", "744ab0263041f7dca789405eac817ba5b62d6dcf52ac91f2759589998c78f59e96bf41138ba82a4442da3dcb041455b90e092f9d0560ae41c7606f7fe8175f39e2775a71bd7d130c0d0d2b99e346f3f10d3b04c90ac04831f73211dff1c08580d16871e035a853b5cc4f0ef994bd3d7507ee0492477aa7655870e383769010a6aa1cf1272e454509e034504103bddae0ba6507b41c8848d2de512ebd171125ea1cb734ce7c18ea861864d0b5fd071c986d9263417ae9123109439a730b5d4a693ca888b05419ca3b1d3c3586433e04df4b1f42aad633df63e283babe3210f83413d4db3d386a5f8aa00304f7d8dd4ed98988a2225b724dbec83d552ca7bbf2c270a7a298e37d56d45c7d5b61e852b193fcbc7da5b51d86efabba3c6222508e4347fdaf4c10570372c9d882bcced2a753a5a87dd9f371727d0f516dafdb97dcbc683c67be56b3ba7b900e908a4febfbc727e77be57c21853191669d724960b33b8c9f3f1fcf72bb97ba9b7ed339293df827a10a312f806a7f3f125e4c1e480c032f22fe08d7378c3e4a63effc5d5be79cafe318dd114d8d43d5756a58061450059309e556031d914a567921ab88bba3d988b8d3b0d19fc3ab70b2fdf38150a57e381e76fcdaa52c0169cd9db8a3cb4bd7472fe1c6d1216100f604ecfeaab6d864979eb69555949c0c313c3afbd5217f5ed10a7a79f8521b366c3a6c8f0080d3b5000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-f5da30772951ff15e2a8278cde15e11960505e7461c5d5a2c83fdaac821bdd9ac3e975da587a125c53fe95efaa2f01accc0145d6fcdc6f231e9f9aba0d4f38a2cb301ed06a82bce75ce394178906b99a2f03ee674c26f2928e5279f7c951291714b7c9a0e7ec0ae4da9556dbd46d72fc953d5dc8bafdae7c5fd8715f0b05bc2c4fa3c8b454a3d3900d095f4a23aebc4f68b074a06ffc1d24ce1478d5c4d25f3d5f65280f887a836b9e753bd472e3ee187c400bdcbeb3fa94ea8137e7f8f491bf495bbe7e7410f1f439e4732c188d3388a501b6561547d4b712503c0204f6fd4bb5248bd98b9fe33d9f492c59dab6e1fd3134962f87fb67741e255009becc65545567068bfd92b8d016a8132eafc9bd6736577b578157f454ddb0280eddd0051619ed0b95af42dfb8d4ac8504ecfa152741a4d3891338f692bc64e1bb5f30258ef49c68c5e7c08e1afeeba34c6cf93884769d8d3369637d110f4b2645526827d13413cf980ec56eb9871174018c6793877cf39afbb7fb8bbd21d6be4f52482a77c792ec99515385a718711834a9cf6465e87a77167022fd4885898a7cd675c9ebc3d6d98bb122d5df50a6658b41aebb2ac5ab511a112c77a0aa20635b79b1f7f6897d58ae502169856e53a77642883077280e1753f6f3f407b1229004049b050d0e2f49d568aa80740483c3f1a00e00e13199120dea00f6d868d73beaca267be1", "3c", "-f5da30772951ff15e2a8278cde15e11960505e7461c5d5a2c83fdaac821bdd9ac3e975da587a125c53fe95efaa2f01accc0145d6fcdc6f231e9f9aba0d4f38a2cb301ed06a82bce75ce394178906b99a2f03ee674c26f2928e5279f7c951291714b7c9a0e7ec0ae4da9556dbd46d72fc953d5dc8bafdae7c5fd8715f0b05bc2c4fa3c8b454a3d3900d095f4a23aebc4f68b074a06ffc1d24ce1478d5c4d25f3d5f65280f887a836b9e753bd472e3ee187c400bdcbeb3fa94ea8137e7f8f491bf495bbe7e7410f1f439e4732c188d3388a501b6561547d4b712503c0204f6fd4bb5248bd98b9fe33d9f492c59dab6e1fd3134962f87fb67741e255009becc65545567068bfd92b8d016a8132eafc9bd6736577b578157f454ddb0280eddd0051619ed0b95af42dfb8d4ac8504ecfa152741a4d3891338f692bc64e1bb5f30258ef49c68c5e7c08e1afeeba34c6cf93884769d8d3369637d110f4b2645526827d13413cf980ec56eb9871174018c6793877cf39afbb7fb8bbd21d6be4f52482a77c792ec99515385a718711834a9cf6465e87a77167022fd4885898a7cd675c9ebc3d6d98bb122d5df50a6658b41aebb2ac5ab511a112c77a0aa20635b79b1f7f6897d58ae502169856e53a77642883077280e1753f6f3f407b1229004049b050d0e2f49d568aa80740483c3f1a00e00e13199120dea00f6d868d73beaca267be1000000000000000", .None}, + {.Shl, "13a8990a2a54f0d4486ab5da8100cb4d2d45a1515d0bdc2879ecbaadfe698470056b4a5a4cfb7581338b07184a48041cb833ed7f7a8bcb1d30ee8dabc81baa4c72397dfd5d4909f47eceb120ddd3c3ed5b6516e5c0cfa581a9e12dbc15e58b17acc0a2b55f1d6f3806fd8b17a05edc4903c0cf7efc65de0c2e468219e007f97b8fe4d1e1a027c4c03a7f1570436f7a2d938b7a26cb878888d3fc08a143d7de9a196f2b5912d36d64402985ea4ab9ee29a0d7bc0d694fe25601704d85830aa3f37bc44d8100db04d9944bbb3e33b14d152b1388d87bfa91e71b7a51b5b0ca123348bea846834e093b1c31d712a9045c5aacbaa1bfc3826f2da05098a9f50b771b9d1653df8ca6c6bd3aaf9ce4c84ec4f0b503c1c57988d760e4dbe28c8fb021f98ded6768250ac67e59494800a67889c64fde54239049afab519c42274a95a87d00318551f95777dc48708a7c57c066c64a500f47729e32735a9e53fdfd24f6c62e87ad9b29fa8adf487e7cf95a4efd4e87e45607e6f15327c8e47c934bbc5d574680ef0706c2596dad2628fccbda04320aa305a39f845819a272647b933c4f9c1aaabcfe75f83c61358970741f4c3d2c5b99f881b8bffb3b6846233122cba0aedb65cd3f80e1f24e9f999a86c2cf1a0cc1f661387412175da2f727242543a6f5119a2618de46d8366eafedaac5a593684943fdfa8c2ffedda72173a274a06f51", "21c", "13a8990a2a54f0d4486ab5da8100cb4d2d45a1515d0bdc2879ecbaadfe698470056b4a5a4cfb7581338b07184a48041cb833ed7f7a8bcb1d30ee8dabc81baa4c72397dfd5d4909f47eceb120ddd3c3ed5b6516e5c0cfa581a9e12dbc15e58b17acc0a2b55f1d6f3806fd8b17a05edc4903c0cf7efc65de0c2e468219e007f97b8fe4d1e1a027c4c03a7f1570436f7a2d938b7a26cb878888d3fc08a143d7de9a196f2b5912d36d64402985ea4ab9ee29a0d7bc0d694fe25601704d85830aa3f37bc44d8100db04d9944bbb3e33b14d152b1388d87bfa91e71b7a51b5b0ca123348bea846834e093b1c31d712a9045c5aacbaa1bfc3826f2da05098a9f50b771b9d1653df8ca6c6bd3aaf9ce4c84ec4f0b503c1c57988d760e4dbe28c8fb021f98ded6768250ac67e59494800a67889c64fde54239049afab519c42274a95a87d00318551f95777dc48708a7c57c066c64a500f47729e32735a9e53fdfd24f6c62e87ad9b29fa8adf487e7cf95a4efd4e87e45607e6f15327c8e47c934bbc5d574680ef0706c2596dad2628fccbda04320aa305a39f845819a272647b933c4f9c1aaabcfe75f83c61358970741f4c3d2c5b99f881b8bffb3b6846233122cba0aedb65cd3f80e1f24e9f999a86c2cf1a0cc1f661387412175da2f727242543a6f5119a2618de46d8366eafedaac5a593684943fdfa8c2ffedda72173a274a06f51000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-39dc9beb7322873e4e94be3a9de3cece73df8001c9f5615e2832d86cfed67fcdadc0d40ac259f9ce39b0da249a23dba76f19e2387056a9aeffc0c0de2c7290c43b9fa31cdf6bcca8412bcb9e83fac77e33340df37fe3997a3cc27e6392b4fd3105cb7fc208ee187d3eefd24f05c2efef04145b4dd5fadb8165d5037caac0a61985fa45f91cf94ccca50535635f850366a42f7ff192500130629540f95be70128205a6b57c8e3e098a721643aa885a84e01a6e1674abe2083ac95a90447a2b3d09c5d50df0845bffe0e2a531638078570c1601598b74f30327dbbed6913842e8a626a9d51fecb952b03ad472eac80d6df0b06f2599560dd50a05f1b15d0b85abf0ba9d5e5e63552b5e53c194d889c5df10bc18f7e4c91a6501ddc5a25a75854268d0a47fe481a3cffbe1cddbbd71e176dc5449fa6e8963eec1d8922ebd8fb5c9fd5416e2156e0ecccd457a78e31f2516931237cf4757abd451f27e973c9545172d3fdb1f5e0447220e30dbaaf0a140e0e52ba4e25fda6ea4b8ff61e5b4980bb983d8b760c0d7e5e214e1f94042c2d6628edea54d63d3ead8c10ede338dcd6cdced67fd2a2f7756b4b7274493cf00a2043b96b80c719f871e18c6a50825538ab0ad1c2c9c69a7fab5e3aba2fbf516e948b3f96b7a8745dc0f12fe34221353d1ef711144a9fbfd3a6b90c1d7d7e422662be85b13e59464b6115fafae206475b8339", "21c", "-39dc9beb7322873e4e94be3a9de3cece73df8001c9f5615e2832d86cfed67fcdadc0d40ac259f9ce39b0da249a23dba76f19e2387056a9aeffc0c0de2c7290c43b9fa31cdf6bcca8412bcb9e83fac77e33340df37fe3997a3cc27e6392b4fd3105cb7fc208ee187d3eefd24f05c2efef04145b4dd5fadb8165d5037caac0a61985fa45f91cf94ccca50535635f850366a42f7ff192500130629540f95be70128205a6b57c8e3e098a721643aa885a84e01a6e1674abe2083ac95a90447a2b3d09c5d50df0845bffe0e2a531638078570c1601598b74f30327dbbed6913842e8a626a9d51fecb952b03ad472eac80d6df0b06f2599560dd50a05f1b15d0b85abf0ba9d5e5e63552b5e53c194d889c5df10bc18f7e4c91a6501ddc5a25a75854268d0a47fe481a3cffbe1cddbbd71e176dc5449fa6e8963eec1d8922ebd8fb5c9fd5416e2156e0ecccd457a78e31f2516931237cf4757abd451f27e973c9545172d3fdb1f5e0447220e30dbaaf0a140e0e52ba4e25fda6ea4b8ff61e5b4980bb983d8b760c0d7e5e214e1f94042c2d6628edea54d63d3ead8c10ede338dcd6cdced67fd2a2f7756b4b7274493cf00a2043b96b80c719f871e18c6a50825538ab0ad1c2c9c69a7fab5e3aba2fbf516e948b3f96b7a8745dc0f12fe34221353d1ef711144a9fbfd3a6b90c1d7d7e422662be85b13e59464b6115fafae206475b8339000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "8d53c81728e5523aaa4e108bd7b474bec4fad74bb812b6542cf6fe92b2c2159a6329e43f561f6d52ec82ef51f0020995435b098e4cb2aa8bbfa7eca6a10fcd039a7c0ae98a3f64285c6eaab6a60cf25d62ac7a5ac6cd6f958163847f1d57f40bdc1a7e0edfe4e83d84e0147623df5fe387693a71bdb8a3df970772b3969045cf718df50810bd6dc0fa51626dadf590327fafafea26018d99036c894bf6015046f7723c6a26fe85f6a77e37dda1c0dab05d0921593809da35502d71db60b8e1ab2ef20a593b637c0f5ebac67e058718ec3cc2e8ef6ed4eb252f37fcfe0b114ea4d1ca219f925adfcf5a48400bf397f4b810c06f52c0bf5164cd2dc0504d312bd74507c34279e0c17074d785de40032571e880f9edc079dc385b64b5834d6090cc46df20cd23687c8c6a8ef713264e54955893dfba78eafec45d3071924b5ae66cad08495117cc4e59fa612c45ebbf898a919ed677e19c651d5ee35fd4ab01abe9981b7325e14a0e1e3c3ec75b7b57c5890168d791d47461a72bd2709f3eba5cb1e3db0123e315f96aa192ef76b0d80779e17e2b24e95d134e5ea348ec83817e6b63b1a5660dcd0a7ad36584e6f7bf8b2e437bd195cbfb200434ff5a6a55b0b76e87a491cb75acae93f67b9fb663f8ece88677c1babb4785b51266212b0f3a99a685fedcb8d9aeb599dd172fd9bd294e16731ee16915a6566b53e6c059caa36f2e", "258", "8d53c81728e5523aaa4e108bd7b474bec4fad74bb812b6542cf6fe92b2c2159a6329e43f561f6d52ec82ef51f0020995435b098e4cb2aa8bbfa7eca6a10fcd039a7c0ae98a3f64285c6eaab6a60cf25d62ac7a5ac6cd6f958163847f1d57f40bdc1a7e0edfe4e83d84e0147623df5fe387693a71bdb8a3df970772b3969045cf718df50810bd6dc0fa51626dadf590327fafafea26018d99036c894bf6015046f7723c6a26fe85f6a77e37dda1c0dab05d0921593809da35502d71db60b8e1ab2ef20a593b637c0f5ebac67e058718ec3cc2e8ef6ed4eb252f37fcfe0b114ea4d1ca219f925adfcf5a48400bf397f4b810c06f52c0bf5164cd2dc0504d312bd74507c34279e0c17074d785de40032571e880f9edc079dc385b64b5834d6090cc46df20cd23687c8c6a8ef713264e54955893dfba78eafec45d3071924b5ae66cad08495117cc4e59fa612c45ebbf898a919ed677e19c651d5ee35fd4ab01abe9981b7325e14a0e1e3c3ec75b7b57c5890168d791d47461a72bd2709f3eba5cb1e3db0123e315f96aa192ef76b0d80779e17e2b24e95d134e5ea348ec83817e6b63b1a5660dcd0a7ad36584e6f7bf8b2e437bd195cbfb200434ff5a6a55b0b76e87a491cb75acae93f67b9fb663f8ece88677c1babb4785b51266212b0f3a99a685fedcb8d9aeb599dd172fd9bd294e16731ee16915a6566b53e6c059caa36f2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "4aebcfb83de7bf3d8f8c4a904454475d67bf349fb55235bed7ce4ac87d5b56ccd9dcb621389588b4c6697142553bb1a482930648c6c3642b9f73fa573e2ed79e7cb2395642a60635e8d4d4b9d61db2b4e8af7bee2bdaf1376edc97aaf1289ccc109892eaa85e983ad0547370f3d9b7eaea43c5a2ca301d7ec55a8afc0e0ceb3e01f360ece14e08675ca475b0ca7ca937f51f61a6e3df80a3b9f2c9eaf9f2e91dcfe84455d1692151224d42ca99f6b3ec70a6db38bb335b16f49a46d5dd0f8b187def4e2c83da47ce2213fe2c73b146de5b0a114d5de92700a9e9f1074db45fc5621d664696bafc0f56898d864eb11487866d752efe132afbc0a122fbb23f355cb45d916fcf0d9cba966237dd7e3ac9c7dbb07d808a72a81de39236e24331d4fd1cc0e6e30438a5a60c74a94fad4c7064e8309e8d87f3045d2b167c528602c1dc891534bdf1af0d863551f611365aa2a426f416bf94b82480a59200f5a9a1fa3790d22c0dd58a44217c72d8779dd1d23e05a141edb0a72287b63b1af0fbdd093aa7e85590cfe72fd7ab68f85d4a599a54ffb4bbe0f8975d1259ed59e37a05af53406f50bfef92507d3fcf877152a75aa67b3f625d99162460bfdf9834ca871aa0e0d796982f70c875942b4e00291336b083443e505117c7a09f7980e9c6e4192f3a25f375879cd27f11bd3b31a7b534095cd0bff7f768c0dad1ddc70230a7a511", "0", "4aebcfb83de7bf3d8f8c4a904454475d67bf349fb55235bed7ce4ac87d5b56ccd9dcb621389588b4c6697142553bb1a482930648c6c3642b9f73fa573e2ed79e7cb2395642a60635e8d4d4b9d61db2b4e8af7bee2bdaf1376edc97aaf1289ccc109892eaa85e983ad0547370f3d9b7eaea43c5a2ca301d7ec55a8afc0e0ceb3e01f360ece14e08675ca475b0ca7ca937f51f61a6e3df80a3b9f2c9eaf9f2e91dcfe84455d1692151224d42ca99f6b3ec70a6db38bb335b16f49a46d5dd0f8b187def4e2c83da47ce2213fe2c73b146de5b0a114d5de92700a9e9f1074db45fc5621d664696bafc0f56898d864eb11487866d752efe132afbc0a122fbb23f355cb45d916fcf0d9cba966237dd7e3ac9c7dbb07d808a72a81de39236e24331d4fd1cc0e6e30438a5a60c74a94fad4c7064e8309e8d87f3045d2b167c528602c1dc891534bdf1af0d863551f611365aa2a426f416bf94b82480a59200f5a9a1fa3790d22c0dd58a44217c72d8779dd1d23e05a141edb0a72287b63b1af0fbdd093aa7e85590cfe72fd7ab68f85d4a599a54ffb4bbe0f8975d1259ed59e37a05af53406f50bfef92507d3fcf877152a75aa67b3f625d99162460bfdf9834ca871aa0e0d796982f70c875942b4e00291336b083443e505117c7a09f7980e9c6e4192f3a25f375879cd27f11bd3b31a7b534095cd0bff7f768c0dad1ddc70230a7a511", .None}, + {.Shl, "5320e0a8c24782fe7af0148bd61954a0ee318958f9c28cd2ead5f90833dbf0fa091da03fe7e4f935ccd3c9838836c178400c8c83e86f871ab9713ba29a39e80bf9f90bc34d472c16aeaf7a27079d8bedf0b6b391457e3da6bd57aa17d408068e349fed88bc743017b80bcec4573880deb116c4b84bf9ef783cc2c22771e78019b3e7bb645539bd3f0573be53f394e565b37c90c76ff840d53db405d59536e5105207b3a500b3c286b26cf2c05f24f15776832dfb6fadbb591e45fc438253492d0a048f96a0881bd23e9f995362087bb775d965e7f41ee40f11b844992ca94f65836bcef82d099b01131703d137b508757a17a55f321a0daf6ac183d0c1294b171b762869674850a5ec1c70289a6c633fb17fead74af6b236e7f2778879afaefa818ed6e4363ba4e16c3f0c1995ea4fae333e12c97f29aef0bc8606c0137464a2ce49c41df2905f38bffa09ccc5f447e364fbadd6c8908832d576648f4adad1a4580644f77755df4dc1930d1c1f3472f91d287e6819dd5a18ad09fceb54743c4a7c58be034c592dd36eea9d2d997e718cb0583914f96e040d51e546cc722c2a77d008bf417560f525821b6eb93a2627b7ad5a050dd48ec4536527261bff22ae77306bb59cf260bb58312b47ce4640974d7cebb2a56827ac55556a1a4f4d8f6ef68b4e4ffacdc97a35dc60fafaa5b61c288b08305ad7a2ee468b1b0936d6ce6deb", "12c", "5320e0a8c24782fe7af0148bd61954a0ee318958f9c28cd2ead5f90833dbf0fa091da03fe7e4f935ccd3c9838836c178400c8c83e86f871ab9713ba29a39e80bf9f90bc34d472c16aeaf7a27079d8bedf0b6b391457e3da6bd57aa17d408068e349fed88bc743017b80bcec4573880deb116c4b84bf9ef783cc2c22771e78019b3e7bb645539bd3f0573be53f394e565b37c90c76ff840d53db405d59536e5105207b3a500b3c286b26cf2c05f24f15776832dfb6fadbb591e45fc438253492d0a048f96a0881bd23e9f995362087bb775d965e7f41ee40f11b844992ca94f65836bcef82d099b01131703d137b508757a17a55f321a0daf6ac183d0c1294b171b762869674850a5ec1c70289a6c633fb17fead74af6b236e7f2778879afaefa818ed6e4363ba4e16c3f0c1995ea4fae333e12c97f29aef0bc8606c0137464a2ce49c41df2905f38bffa09ccc5f447e364fbadd6c8908832d576648f4adad1a4580644f77755df4dc1930d1c1f3472f91d287e6819dd5a18ad09fceb54743c4a7c58be034c592dd36eea9d2d997e718cb0583914f96e040d51e546cc722c2a77d008bf417560f525821b6eb93a2627b7ad5a050dd48ec4536527261bff22ae77306bb59cf260bb58312b47ce4640974d7cebb2a56827ac55556a1a4f4d8f6ef68b4e4ffacdc97a35dc60fafaa5b61c288b08305ad7a2ee468b1b0936d6ce6deb000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "35d724c081e45905a510a0705d63a2acddf20353b859dd0ede47fd6000bfae1c4e1cb794331b083c2439651be736fc1ee8f92d096dd2c1adecb11e74cf358e730c4354b8daca30ee899f5fa139f990c254c4358e1216d54d1a0c68e075e94c730ac89127fd576201907314f5b533ca250bb17443a23c2e6988f5474eaa06adf9d8ef7035c9790dc5df3c45b5a0581c19c28fbd17314bcbeb1a8d1eff7d60e6c43720093648377c8aa46bcb8a067f7d1d4ff2fad836cebe4c7af2cf91715520815e435eb4403d6403609086f5919afcb9c5fa03c1aebce29409fa8a3800de9fb03502fc04a0732e436cbcf68f026a7884da7b4a1b8ca095e4d7ddd13d187984810a1833bd26fbdef33e33a645aff2d64f1fdb6202cc31af92b0aeb9d6ff8f9036942fcae7443272957d7e309ff4cdceffd5c2bcce5a076897e3b827c98cda2aa03af74cde3e62e9cc3d5963a747e33e2f7a5cf5dde36b28d1b2b2c26d114ad7c29f20baedf1310dd713ae6e910bd5580bab9a1d46170219d438c051e4f542b1b28bfea612dcd9d9c171a53cc7dc96835d51801d7e7fe129eb13bd8deae017cd55da4198642a44115b506624d58d85f661522c1f2ab2a7658883b3f7748a774d1f0d956d8ceeda7c366ef9d4096883122dac04785821d654ab9a0932c753d274f6f06a4ba70acf99b1b6dadd4738a4d8eb68e5673566cc88c5462f981cc6e3e323", "12c", "35d724c081e45905a510a0705d63a2acddf20353b859dd0ede47fd6000bfae1c4e1cb794331b083c2439651be736fc1ee8f92d096dd2c1adecb11e74cf358e730c4354b8daca30ee899f5fa139f990c254c4358e1216d54d1a0c68e075e94c730ac89127fd576201907314f5b533ca250bb17443a23c2e6988f5474eaa06adf9d8ef7035c9790dc5df3c45b5a0581c19c28fbd17314bcbeb1a8d1eff7d60e6c43720093648377c8aa46bcb8a067f7d1d4ff2fad836cebe4c7af2cf91715520815e435eb4403d6403609086f5919afcb9c5fa03c1aebce29409fa8a3800de9fb03502fc04a0732e436cbcf68f026a7884da7b4a1b8ca095e4d7ddd13d187984810a1833bd26fbdef33e33a645aff2d64f1fdb6202cc31af92b0aeb9d6ff8f9036942fcae7443272957d7e309ff4cdceffd5c2bcce5a076897e3b827c98cda2aa03af74cde3e62e9cc3d5963a747e33e2f7a5cf5dde36b28d1b2b2c26d114ad7c29f20baedf1310dd713ae6e910bd5580bab9a1d46170219d438c051e4f542b1b28bfea612dcd9d9c171a53cc7dc96835d51801d7e7fe129eb13bd8deae017cd55da4198642a44115b506624d58d85f661522c1f2ab2a7658883b3f7748a774d1f0d956d8ceeda7c366ef9d4096883122dac04785821d654ab9a093", .None}, + {.Shr, "c321f048f686b1128cb9a4cdd9c9de0253c176c8644ca7b7422fc748513b6dd52d302fb1c7941449c4e09fd6ec91ce3f45c7039b9f27563da9339f43b43018555dc2c237af590e4b9275c8233a66b0479b2f4ba1246615461e5b6591788c0bd098f1fb89c125cafe13cf0ac95cadd64d4686eeb13f16f622866f1711823ddba57e724b06466ea6ed3b59e105675d52370ed3514831e5b8016902f5d3c55b3d05b7bb7282f15efc7617a0741548b3dbfa5ccca4b2c6351526d9c141f8bb3d2da2ac7874350fb5be971d9a73f59e044b5e5e1b6a83702f82d1b6fb8a1235f059a969aea719df8591aa7ccff376584cee9fd8901d0be8694c57bfc57b3c3b1fcd44c989bfdef7d4c0ffbac7c93ec75f326f2e944e8b4a130d0ad385ad3b722d4d66dc95c69bd6826906b1d508eec160ed0482b0985eb49b18cb2439a824b37dbc54a89d4fbaf0c0d6498e012aadc4a468b0629a558301bca9e03b1a20c769606711989c51ccb41a2edfe3916a9eb228d8d25c5c5d5f6c263521710427ef31a4de755bb1f5bd5f67222519169657626355607e08845ecb584f17c3eb8eb9702366f3b48e780b9c747aadb74d143e22dff046f65efe4724a69b1d2eac8bcb51a8cd4edeea00fa6c36e49d15d9957b815ba6d920de1090ef1408fffd6eccd89503fb965e382488ddb0aa64fae7672cc3d1639b3099f7a27049b58e74d6d1714124db34", "1a4", "c321f048f686b1128cb9a4cdd9c9de0253c176c8644ca7b7422fc748513b6dd52d302fb1c7941449c4e09fd6ec91ce3f45c7039b9f27563da9339f43b43018555dc2c237af590e4b9275c8233a66b0479b2f4ba1246615461e5b6591788c0bd098f1fb89c125cafe13cf0ac95cadd64d4686eeb13f16f622866f1711823ddba57e724b06466ea6ed3b59e105675d52370ed3514831e5b8016902f5d3c55b3d05b7bb7282f15efc7617a0741548b3dbfa5ccca4b2c6351526d9c141f8bb3d2da2ac7874350fb5be971d9a73f59e044b5e5e1b6a83702f82d1b6fb8a1235f059a969aea719df8591aa7ccff376584cee9fd8901d0be8694c57bfc57b3c3b1fcd44c989bfdef7d4c0ffbac7c93ec75f326f2e944e8b4a130d0ad385ad3b722d4d66dc95c69bd6826906b1d508eec160ed0482b0985eb49b18cb2439a824b37dbc54a89d4fbaf0c0d6498e012aadc4a468b0629a558301bca9e03b1a20c769606711989c51ccb41a2edfe3916a9eb228d8d25c5c5d5f6c263521710427ef31a4de755bb1f5bd5f67222519169657626355607e08845ecb584f17c3eb8eb9702366f3b48e780b9c747aadb74d143e22dff046f65efe4724a69b1d2eac8bcb51a8cd4edeea00fa6c36e49d15d9957", .None}, + {.Shr, "20e4523113796119b74c4ada39bdeb6e60c791048beafab4b3a347173e09af44c58dea53312255292d23193c76178ee9cb9e4709f579fdad990ccb07d00aae394ff67449e5f588b783320b0e2ec2b5c656b30c8cd9ac33ed66df02835d8c84e5e8bc6117d73d63204c8b01b448ad95a9faee4de43c308784df7d896b987a83318e28003010e717e13bf46a9861d32b322aed460c1c951a5fdfcd23d4586f4321882003d065df40d9817ad364663a490fd1cf9d8f4dde537483b9311f7ac3599f4b570b146efceba7004bf7d1e28073ac2b1918e5f3c75af885de68fe3f76ac03dcb7b39789716155221c59dfd88dfe6c37d878611a32d5ff23ae0f732df7538e3efa9c7c44dee89f1cc2beab82c3b857c6c8d4aecd4964bae31e7d7dcd6c02f37e05b89a301f55be748034b0b86ef2e5921e0e0f265f5e4625da2301069b0d6e6186b72b74a43db4094f48a92dd49b7c0859d4f39f8bf72fe7eda19ae52a259ad94176436b578462ebed549d9f616df3ff03b34c3cac2e708daeca08b20131508e23bec731400c70fec43473b6d84e24b99af80fdb06fe93cc3d430dea97f2370ad52cb5babe0255c281333e8c47738e917f78c629c3049b916c67f525daf7e78f0aef0e3f861377c07192f7b6e7f49b81bfd8ea0b7f830b9c6d09359dce948ef748ca8d2fb4cf1287f4f7b3d4400c17a8790ef37e2391c4f55bbb246467e09e", "f0", "20e4523113796119b74c4ada39bdeb6e60c791048beafab4b3a347173e09af44c58dea53312255292d23193c76178ee9cb9e4709f579fdad990ccb07d00aae394ff67449e5f588b783320b0e2ec2b5c656b30c8cd9ac33ed66df02835d8c84e5e8bc6117d73d63204c8b01b448ad95a9faee4de43c308784df7d896b987a83318e28003010e717e13bf46a9861d32b322aed460c1c951a5fdfcd23d4586f4321882003d065df40d9817ad364663a490fd1cf9d8f4dde537483b9311f7ac3599f4b570b146efceba7004bf7d1e28073ac2b1918e5f3c75af885de68fe3f76ac03dcb7b39789716155221c59dfd88dfe6c37d878611a32d5ff23ae0f732df7538e3efa9c7c44dee89f1cc2beab82c3b857c6c8d4aecd4964bae31e7d7dcd6c02f37e05b89a301f55be748034b0b86ef2e5921e0e0f265f5e4625da2301069b0d6e6186b72b74a43db4094f48a92dd49b7c0859d4f39f8bf72fe7eda19ae52a259ad94176436b578462ebed549d9f616df3ff03b34c3cac2e708daeca08b20131508e23bec731400c70fec43473b6d84e24b99af80fdb06fe93cc3d430dea97f2370ad52cb5babe0255c281333e8c47738e917f78c629c3049b916c67f525daf7e78f0aef0e3f861377c07192f7b6e7f49b81bfd8ea0b7f830b9c6d09359dce948ef748", .None}, + {.Shr, "feab06ea087b582d04bb46961eb624bb78e0082af2da8fdd820bb07d59450e600786c551b29987863f39feaa9564c92c5ca508accac9229dbdab5b3e9d633ac5b2b84c97ff552444a1c59e85e7bd37b51dbe5c3ec222d3ff357727a3389515a9ac951760f20e86606e7d839962e37bed7f91c642a3d1af53013886a4d10c750e602bfaa88a503d5421ff6b77f70f8f850d82ccace020a9f4bd71d3d150efd29892f99bd2e79146beb87b0586c1c7b505f53c3407ca33236c4ff74c9090041a1002fee6a7c03e978d408ab2da6497076bfaa52b02ceaf55050cabee2bec5cd7d600009492905f0700106ea33f320df9580cfbd828cf6aebd6ca6973ee8163e43bcca718093c27af8924ee127803aeaf4491190ba0bd5941b762b1436ca88862b976789651d78260de7550f9e56f9ed7a34e9cd5d5d82c1b8bd73080683241907ca80dc8144243aad370ddee517660ac31da3763333a5e5104c601cb7f57becbc4fa87ebb125c21bade77d1327d49f8ee66736550e0794db6d06225295b5848515369f7eeacdf544d200d930550a54657a7f6d5f5f19ec71c4878b6bfe768b0d16eb7392fa5198253b5c2d9cb740c7b0d3db4ec2beb0bc0d5b6998f69e8c5e4f1dd0d9ccde04b77af98760e769ddd87113fb2a85d24aaf9a69e6a3a7946acd815090d93afc3b0f300c9816a11c0d393d9606994192bf290b216e47e99d7fe26aa1", "78", "feab06ea087b582d04bb46961eb624bb78e0082af2da8fdd820bb07d59450e600786c551b29987863f39feaa9564c92c5ca508accac9229dbdab5b3e9d633ac5b2b84c97ff552444a1c59e85e7bd37b51dbe5c3ec222d3ff357727a3389515a9ac951760f20e86606e7d839962e37bed7f91c642a3d1af53013886a4d10c750e602bfaa88a503d5421ff6b77f70f8f850d82ccace020a9f4bd71d3d150efd29892f99bd2e79146beb87b0586c1c7b505f53c3407ca33236c4ff74c9090041a1002fee6a7c03e978d408ab2da6497076bfaa52b02ceaf55050cabee2bec5cd7d600009492905f0700106ea33f320df9580cfbd828cf6aebd6ca6973ee8163e43bcca718093c27af8924ee127803aeaf4491190ba0bd5941b762b1436ca88862b976789651d78260de7550f9e56f9ed7a34e9cd5d5d82c1b8bd73080683241907ca80dc8144243aad370ddee517660ac31da3763333a5e5104c601cb7f57becbc4fa87ebb125c21bade77d1327d49f8ee66736550e0794db6d06225295b5848515369f7eeacdf544d200d930550a54657a7f6d5f5f19ec71c4878b6bfe768b0d16eb7392fa5198253b5c2d9cb740c7b0d3db4ec2beb0bc0d5b6998f69e8c5e4f1dd0d9ccde04b77af98760e769ddd87113fb2a85d24aaf9a69e6a3a7946acd815090d93afc3b0f300c9816a11c0d393d9606", .None}, + {.Shr, "a30be086643e567799910b730a414b7134deeea1a223a366f1694d1d09b882f0c4210edec06b6ef6236921880b3ee2463a6f462e5d2b3155d8712f5f94669c1695e80c0f807ad29c9cc1736f47c935d8ad857f0b10eb5d3296eab4a2b928f99a92211c2a18ea87263c7c0270af19c173e040e504851150f36a793104fc5e0ea47695d97d94ae17e16004347864c8b6910867b4fd6961378ed1be5d472cd04280acc858534db5052758f5b9204ff8e0d5a781957f71a1a3a2ca2ca8714172d062b5e2dfb20db3c4aa9e31b6e06bd8144714dcc968259065266551935c7404c52d9592503447448d41d6b8d608b277ef7fa9980200b9987a60545cca6556695286fd6fe939fdb1194c0983fc3c67b73403a318048eda782aa3f6f03faa0ecb311273b3d6769b655fcb436207ef7b378e6eb60067ee903765282debaf677730f299e43b21950b51e9939f914f935d362d9e04d0e73fafeaf4666046c7da495fcfc6c4d4604caa77efff8f8831cf1e2ccf2731f8fe0a20a510b6a83e1bb1f431f177774083bdf182c5997dbe4087c70eb086e5d2228fb87a5e32a0590e2115f46fda8e546cf713c17e5214b1dcdc54d831bfdc00a60c5fca40639ad2853b647af58b4cfe165a3867bfd8a92d3eebc4aaafff8dc13a8895aff5b27ded243fedc41fa5095840e1b37554eda603f896dbe055702798379a6c6373a79549dae0f6fc2a22", "78", "a30be086643e567799910b730a414b7134deeea1a223a366f1694d1d09b882f0c4210edec06b6ef6236921880b3ee2463a6f462e5d2b3155d8712f5f94669c1695e80c0f807ad29c9cc1736f47c935d8ad857f0b10eb5d3296eab4a2b928f99a92211c2a18ea87263c7c0270af19c173e040e504851150f36a793104fc5e0ea47695d97d94ae17e16004347864c8b6910867b4fd6961378ed1be5d472cd04280acc858534db5052758f5b9204ff8e0d5a781957f71a1a3a2ca2ca8714172d062b5e2dfb20db3c4aa9e31b6e06bd8144714dcc968259065266551935c7404c52d9592503447448d41d6b8d608b277ef7fa9980200b9987a60545cca6556695286fd6fe939fdb1194c0983fc3c67b73403a318048eda782aa3f6f03faa0ecb311273b3d6769b655fcb436207ef7b378e6eb60067ee903765282debaf677730f299e43b21950b51e9939f914f935d362d9e04d0e73fafeaf4666046c7da495fcfc6c4d4604caa77efff8f8831cf1e2ccf2731f8fe0a20a510b6a83e1bb1f431f177774083bdf182c5997dbe4087c70eb086e5d2228fb87a5e32a0590e2115f46fda8e546cf713c17e5214b1dcdc54d831bfdc00a60c5fca40639ad2853b647af58b4cfe165a3867bfd8a92d3eebc4aaafff8dc13a8895aff5b27ded243fedc41fa5095840e1b37554eda603f896dbe0557027", .None}, + {.Shr, "51d7bc0a7d19e8ccf5cd45846ec03f40577fc50cb1700c76be441ed82d6837ad94f01fbae16e566934ec8fcc328a164c28123213e56042e08a90a1bb58035e6f93c55acb2d85ef2011eeb408914f513f1239cb22cd4fe71ae1b7e1c187ef22cc444cfe6672fe6b9b5cc30e1b3af64591e86b9931d90ded5b561c9e68b9819b068deff9e177d4bf73e49fa76103852bf150eb9347c6d5aab4e913b4b3cd17691e7771046a52eac9f36943b5c5bba4d6278e94fe9922873f94fc7bc9a67d78dec7f215d54386dfc37a89a71cde793752bd32b5278472a830c0dcd7c914eae3dab996982535d6d5bfe80279d29be6774b54037b93178c61a3d02ceb6db2cd2f735da0c3b5a90b13d6fa7785d9ab2dd924c7d2ce8cacacaab684e84ca6b9d18203b3a8d4f345071f0bfce09067b8023077de649a52f64f609c4a61e3fe168e648fe375c2c666fcdb92ba00b72622f90fe8515d9ecec7ff25169017dfb25d91e319df0107e98d3c11ed4acd7d830848d491ecf7da0b2aacebe34f17776af7c13aa0bc231d919d93d2da8c6aa8ca992ec39f608df009c135117a3e5a0b8822581931f1b17b3dd60d0642a57190a1e29c493b0c378a66810ab31c06158b80bc504568eb1450e092481d85cafaf3f62461139202bb54dfd31230fb13abba22571058f4ef17dbdf8bb167dd00d076e3002c39d925f2e7bfcbdd36d2c56c5d1491dd706b20", "258", "51d7bc0a7d19e8ccf5cd45846ec03f40577fc50cb1700c76be441ed82d6837ad94f01fbae16e566934ec8fcc328a164c28123213e56042e08a90a1bb58035e6f93c55acb2d85ef2011eeb408914f513f1239cb22cd4fe71ae1b7e1c187ef22cc444cfe6672fe6b9b5cc30e1b3af64591e86b9931d90ded5b561c9e68b9819b068deff9e177d4bf73e49fa76103852bf150eb9347c6d5aab4e913b4b3cd17691e7771046a52eac9f36943b5c5bba4d6278e94fe9922873f94fc7bc9a67d78dec7f215d54386dfc37a89a71cde793752bd32b5278472a830c0dcd7c914eae3dab996982535d6d5bfe80279d29be6774b54037b93178c61a3d02ceb6db2cd2f735da0c3b5a90b13d6fa7785d9ab2dd924c7d2ce8cacacaab684e84ca6b9d18203b3a8d4f345071f0bfce09067b8023077de649a52f64f609c4a61e3fe168e648fe375c2c666fcdb92ba00b72622f90fe8515d9ecec7ff25169017dfb25d91e319df0107e98d3c11ed4acd7d830848d491ecf7da0b2aacebe34f17776af7c13aa0bc231d919d93d2da8c6aa8ca992ec39f608df009c135117a3e5a0b8822581931f1b17b3dd60d0642a57190a1e29c493b0c378a66810a", .None}, + {.Shr, "a3b0ce1d6472aa0f73d7eb746ef2da6bdff9eb00bc4bf2a2d8e119eb7d35e24803a2a1a94995a96920cd16ef7ea553bdb26be19734018126fa3abc069f134bddf0d589df9574d97b255709f1e2855c3ca2de99e1f6b1233ce987917d4a19c36dc4499bef8d293320a72ef9608bf259134ada9c777a3037fb14a4fe4e6b9749ea7d39b338b94fac4786ef550eeac8426cda30a2782300b1095358977aac4ef3725dc8038b68735c29c664c66a883eff170946976319774cfff2786ba2f721a712ebf37832b85024ff5535e1cb73ebc6b7ccbcab10fcd11b12de45d6c33d9d32cf514c5634746a314aed3170c45228e7dd5e2f83b69236a5d4cfaa1ed08231c2be1faeee1e06745af724b1f00fb6ba146f74eee77ede047e3af7a8c98eeaa405a3ed3b19c345bf813cfd9a6505f08dc20032993f70ccf5a8a7e07d3cc2210efbff9321950e77bf5a81e403a4cc8bd21159a43b3c8fe25a0b45c1caf79be570344461aa0bace2bfdec49df2f631d36719bb5da84ad4119584c1702aaad544be66657f052e87602b845e1508e975db1654d4fa7d11bfd2fda55ed25875a39cf38cd8e6cacc8b4d4f57e762b483bc01e0161ffd2d54f95065cc0c6f728bc9d1e52d3267a2df1ac6537e7e03700228450202504ce5487dc43f99dc7b70ab433a5dd92bcc6a1440e7fcb30ce326ef7227f72e5ec18a9710d02293e9ba2fc2a1e2f1294d", "1a4", "a3b0ce1d6472aa0f73d7eb746ef2da6bdff9eb00bc4bf2a2d8e119eb7d35e24803a2a1a94995a96920cd16ef7ea553bdb26be19734018126fa3abc069f134bddf0d589df9574d97b255709f1e2855c3ca2de99e1f6b1233ce987917d4a19c36dc4499bef8d293320a72ef9608bf259134ada9c777a3037fb14a4fe4e6b9749ea7d39b338b94fac4786ef550eeac8426cda30a2782300b1095358977aac4ef3725dc8038b68735c29c664c66a883eff170946976319774cfff2786ba2f721a712ebf37832b85024ff5535e1cb73ebc6b7ccbcab10fcd11b12de45d6c33d9d32cf514c5634746a314aed3170c45228e7dd5e2f83b69236a5d4cfaa1ed08231c2be1faeee1e06745af724b1f00fb6ba146f74eee77ede047e3af7a8c98eeaa405a3ed3b19c345bf813cfd9a6505f08dc20032993f70ccf5a8a7e07d3cc2210efbff9321950e77bf5a81e403a4cc8bd21159a43b3c8fe25a0b45c1caf79be570344461aa0bace2bfdec49df2f631d36719bb5da84ad4119584c1702aaad544be66657f052e87602b845e1508e975db1654d4fa7d11bfd2fda55ed25875a39cf38cd8e6cacc8b4d4f57e762b483bc01e0161ffd2d54f95065cc0c6f728bc9d1e52d3267a2df1ac6537e7e0370022", .None}, + {.Shr, "4192a987b31c5dd163f385536f044779bb8f13a37601d8d35c65fba571320e58f6d96ec3e578e3e559925ccf664751a554ef4fc3c4c0f5258132b0c8415ee49f3b93bec03ad995dfd8bde3d3f001c5a688e7fbbb5f8098550259a0c8ea57a2128d63d19424a7ee78c99b31944a9c257de1b94e125eac3e7be47065b9fca51c4d53663f09d9b8e9174f59e1c4fe23c9030887673c8708b264ed03aa38523847dfaadb65f7121a10cd630a8227fc43918f1e724f76f6f929c94a51db0f26ffc81983d263846f998ba3d390da696624c06744993ba211829b267ead6bab13d8222d7c62089141db5243e4ad88e4d5a716f18853f94e6fbd83cc1fa3e9742090f137b2bf70fc91d1f525b58c3e71208ccbe8f0c1b81754afd679c494dc9b54eb30f30bf60a2833ba7be79d9e8e1559fb71e7da6193214edf1d68a758b5df5e764aa571a044cb1a436c846d26683b75e4fd6471d8e09cbbbb110c824cd4cef0f6c446ba322db03a7d774ce8345a4f29ee3b5eb99c37e2c38e4c8f9536de1865b31f4d3c42dc93e8347734b6c531e0c0b3efc000f16bab5dcb6c35050f6d24127bf8cdced94fdaa43b59fdbf4205b37469926edc1ea6968dcb41f89cf51fc58a4e100100f74c1da5320234622c55952921d3f3f2a494ebb22af83e828c3fead9ab5947f7655c414b19cb9bd9da86ccf8f866386f83f81f6274d3e0ac0dd3b2814262f7", "1a4", "4192a987b31c5dd163f385536f044779bb8f13a37601d8d35c65fba571320e58f6d96ec3e578e3e559925ccf664751a554ef4fc3c4c0f5258132b0c8415ee49f3b93bec03ad995dfd8bde3d3f001c5a688e7fbbb5f8098550259a0c8ea57a2128d63d19424a7ee78c99b31944a9c257de1b94e125eac3e7be47065b9fca51c4d53663f09d9b8e9174f59e1c4fe23c9030887673c8708b264ed03aa38523847dfaadb65f7121a10cd630a8227fc43918f1e724f76f6f929c94a51db0f26ffc81983d263846f998ba3d390da696624c06744993ba211829b267ead6bab13d8222d7c62089141db5243e4ad88e4d5a716f18853f94e6fbd83cc1fa3e9742090f137b2bf70fc91d1f525b58c3e71208ccbe8f0c1b81754afd679c494dc9b54eb30f30bf60a2833ba7be79d9e8e1559fb71e7da6193214edf1d68a758b5df5e764aa571a044cb1a436c846d26683b75e4fd6471d8e09cbbbb110c824cd4cef0f6c446ba322db03a7d774ce8345a4f29ee3b5eb99c37e2c38e4c8f9536de1865b31f4d3c42dc93e8347734b6c531e0c0b3efc000f16bab5dcb6c35050f6d24127bf8cdced94fdaa43b59fdbf4205b37469926edc1ea6968dcb41f89cf51fc58a4e100100f74c1da5320234622c559", .None}, + {.Shr, "85a16c5ba226e468a94dc39eebfc24cd59f6274f7043cf02f637261fbd34e8a03fac2247aefd0a18822241e0005948569943de0a93696c96c0504dd024c03518f7f6dbd95439b620a574c6d2a10f9a7106901692ba45a2d024b1c75cddcc3ad002c1cf74dd9d73720bff9effdd08a5cd2cc340798993c80b75281cbe4800f30705d18ea0ac1b7add282060b9a231c15a9027442f8c9893b214efdd109cb24d88a08187fce581238677ded065e1ff9f5ff20483ec86695b6ae2bd9227b36535d8bad3de86c9c2eef3b55d5a75d0ee16a5cda97145c6825678a076c359c7b7903bf34282b7674e53a18006f5d5166813bf512db184637e099d20c103abb69df0846b9fc91e02edcbd5c896e971efbf9f6fb2f85559cbbd5fe06de2344cf27e8a7cb858985e62af694cebcadf192a3209ccabfc60a189dfd30b64f2f622c07b884cb7557ba1a742b09663a043d09f0389e734c04d0b94b84c40e0b9d837001ee9645bf09e03fa094d2150c5da8bd8bba3d61534a1191c8fad32e4aeebf8a35629af124ef4108cfaa9e61b8b9686c1b56727e8d25e4872063d4d68ae80c4c97faa5a61fa52e4c094da3dddce127ae2252a658c3096427aea73a422ef5d1b4a8937943cae4d2feb82c1179d421b133dac8de2086840748cdcb4c691977caedb22341a3de937ac18a096a6ebae643d90c98159b2d6225017824e38f2118a72c940beeb", "258", "85a16c5ba226e468a94dc39eebfc24cd59f6274f7043cf02f637261fbd34e8a03fac2247aefd0a18822241e0005948569943de0a93696c96c0504dd024c03518f7f6dbd95439b620a574c6d2a10f9a7106901692ba45a2d024b1c75cddcc3ad002c1cf74dd9d73720bff9effdd08a5cd2cc340798993c80b75281cbe4800f30705d18ea0ac1b7add282060b9a231c15a9027442f8c9893b214efdd109cb24d88a08187fce581238677ded065e1ff9f5ff20483ec86695b6ae2bd9227b36535d8bad3de86c9c2eef3b55d5a75d0ee16a5cda97145c6825678a076c359c7b7903bf34282b7674e53a18006f5d5166813bf512db184637e099d20c103abb69df0846b9fc91e02edcbd5c896e971efbf9f6fb2f85559cbbd5fe06de2344cf27e8a7cb858985e62af694cebcadf192a3209ccabfc60a189dfd30b64f2f622c07b884cb7557ba1a742b09663a043d09f0389e734c04d0b94b84c40e0b9d837001ee9645bf09e03fa094d2150c5da8bd8bba3d61534a1191c8fad32e4aeebf8a35629af124ef4108cfaa9e61b8b9686c1b56727e8d25e4872063d4d68ae80c4c97faa5a61fa52e4c094da3dddce127ae2252a658c3096427a", .None}, + {.Shr, "6f7eb1234588078e323c89acad5cfe125dd9d42811c383d5f7357d43219b5501a086daf057db8672b59fcc9d36b87701ade9ba4dea359ac0bd8d02c4b40af39fdc0051f4c8ed40f58314f3d39a86972a2bd49d5c9d0bd6013c619ff0cc2b967b556681eb730f615924ffb671a9cdde9d4b2252e5c9e43f0bbc4b5193fb317ed6071e236db4218c1dcb7791262cc06390971a5a03fc42c198a9c53d1f3b931414b378cae1cb839082dd9fbcc3e25046a2465d85eb710b22e7986176005530a5f8c8d44482eefb71305bfacfcfd05b14029f16f967a54b02d2f5a168f1d8ee84549ed5a93b8ab85ce561cc79132b5dc614de07dbcc7a3876293e96d5aeac184d68c13c368a42c3eec10a9b8af59c815b9d2c25500dcd4e7ec2bbccb840ae6b5fef7d68d4c2989947ff55881a626ef1da9fa341687542c735b4eba37c9cad340422aafcb870ee2b66c16e19f18fa4c56c8c2e8258d20b4dd56008f102c6a5286635bd52f0b3b5057e6d0de69624cab4153df3f79c49312a6d41305eb0ddfbbb097e499777ceb3dc15bf94fb24e9d5bbc2ac84426d68ac955ca872fb387e224c220aa161a85b9df338bc8eda42d96109a1bb20f75f6c9353d53b155d590e90d3fd81f27c0bb685604834a7d51b4427f99156f84c91c8df1d9e9db96b2bfae42cc33f0bf33f915a1b4ef11bc0bc8c920f8d39772355cac9507e19ae47f7c6fe78984", "78", "6f7eb1234588078e323c89acad5cfe125dd9d42811c383d5f7357d43219b5501a086daf057db8672b59fcc9d36b87701ade9ba4dea359ac0bd8d02c4b40af39fdc0051f4c8ed40f58314f3d39a86972a2bd49d5c9d0bd6013c619ff0cc2b967b556681eb730f615924ffb671a9cdde9d4b2252e5c9e43f0bbc4b5193fb317ed6071e236db4218c1dcb7791262cc06390971a5a03fc42c198a9c53d1f3b931414b378cae1cb839082dd9fbcc3e25046a2465d85eb710b22e7986176005530a5f8c8d44482eefb71305bfacfcfd05b14029f16f967a54b02d2f5a168f1d8ee84549ed5a93b8ab85ce561cc79132b5dc614de07dbcc7a3876293e96d5aeac184d68c13c368a42c3eec10a9b8af59c815b9d2c25500dcd4e7ec2bbccb840ae6b5fef7d68d4c2989947ff55881a626ef1da9fa341687542c735b4eba37c9cad340422aafcb870ee2b66c16e19f18fa4c56c8c2e8258d20b4dd56008f102c6a5286635bd52f0b3b5057e6d0de69624cab4153df3f79c49312a6d41305eb0ddfbbb097e499777ceb3dc15bf94fb24e9d5bbc2ac84426d68ac955ca872fb387e224c220aa161a85b9df338bc8eda42d96109a1bb20f75f6c9353d53b155d590e90d3fd81f27c0bb685604834a7d51b4427f99156f84c91c8df1d9e9db96b2bfae42cc33f0bf33f915a1b4ef11bc0bc8c920f8d397", .None}, + {.Shr, "3fdafa43b10e3ee0e8ff68979f7442ca7426061e809a25e38a467a54d7f0fdb31ef2dfb72563a1872b49b2ff3c5d4e42195fec4166b6f327b13108070cf7ddf0420600b21391cb167ac3fd60902a13758c31fbd957192e62115b06ce1382b837d7819f183fc32b9937ec19706a8e1bb96a7dcd130e7d70a2a04e5d9ae8a2fafea00fea2e2f592afd6092b7582bc9b9f0b8e7f308db263cdf2f7d418e500b2d2d4f4ab1f1cbefc01b1904cca50cd83f8aeea266b6d2ce0fd69132e4e8c62ed842f089c90a76c5c2e889579726b442281c14ff4f6ab853d8bd95a90ca83267ac4e005c9996a0929c4b97d59bdcd43b5684a64a81372eecb3f53d1e40fb1cba4a2237a9dcb30ed9ea5fcd2e63d0c744a2fa744941ed7c0b48b706214e16dce692f633574e114babfefa478b1ba6b0d12c643e073a92cd29b683958caaf5d6ef8c7014d2513ec3f295be95c0ce5b7d52c9c940f3046b2741478204387019cdcb47937deca2d640013167e92b05f8b57a43f0b208e0dcb1af065bc14b2b1dd2ae3901892a766d792791dbe933cf103ed29d4031b9dd84c382b8aa1d340b2a75c7a8e166e42381a53cb357b27a5491709f10af653bfeb45915e8c2828f25b237b4072453ff62556ffbed518a9d497b6e7c11891f943b19bb04410250f73e1468960483bfd08681789aea2ee562658c5d00a64715f94725c13d32579de00864e874f7ea", "78", "3fdafa43b10e3ee0e8ff68979f7442ca7426061e809a25e38a467a54d7f0fdb31ef2dfb72563a1872b49b2ff3c5d4e42195fec4166b6f327b13108070cf7ddf0420600b21391cb167ac3fd60902a13758c31fbd957192e62115b06ce1382b837d7819f183fc32b9937ec19706a8e1bb96a7dcd130e7d70a2a04e5d9ae8a2fafea00fea2e2f592afd6092b7582bc9b9f0b8e7f308db263cdf2f7d418e500b2d2d4f4ab1f1cbefc01b1904cca50cd83f8aeea266b6d2ce0fd69132e4e8c62ed842f089c90a76c5c2e889579726b442281c14ff4f6ab853d8bd95a90ca83267ac4e005c9996a0929c4b97d59bdcd43b5684a64a81372eecb3f53d1e40fb1cba4a2237a9dcb30ed9ea5fcd2e63d0c744a2fa744941ed7c0b48b706214e16dce692f633574e114babfefa478b1ba6b0d12c643e073a92cd29b683958caaf5d6ef8c7014d2513ec3f295be95c0ce5b7d52c9c940f3046b2741478204387019cdcb47937deca2d640013167e92b05f8b57a43f0b208e0dcb1af065bc14b2b1dd2ae3901892a766d792791dbe933cf103ed29d4031b9dd84c382b8aa1d340b2a75c7a8e166e42381a53cb357b27a5491709f10af653bfeb45915e8c2828f25b237b4072453ff62556ffbed518a9d497b6e7c11891f943b19bb04410250f73e1468960483bfd08681789aea2ee562658c5d00a64715", .None}, + {.Shr, "960f29a78bb828913a7dac7117de142524ea1af7f43a179ba0e64e0e48dd14414f7700b58440c2c6099e4129c64150cfe368367d411290fe73270c4cc6f7a7b337ef7be49516d4acd8d76be235a4104e66f573cfdea385fe1b4279b5d213d4482c4fa8c972a1350ce65d270d7b442046bfa00d6316213f442e378ef0dfd7c681293c115728bdac5a4dc4e48a884c76f2fd2d8cae697c0472af257a8fb32dfbe8e340a613c2786db52aea052cb70c4b86ea09a31360b3c94b73497b29915ef009f77e7b9c0375af27876b763aa248809e58177b3e580924ab3ecce40b8de97e44b5aacaba4776bc06fd3e5cabb0bafa36854ae4446b3eb5fefa6a58ef4d84165d7c2bdb7c532ad284484c0cf1a9f19126dd56f8b370463a19af311e234058aaeb26bff51629d4e2fa5955b8f82c6467f1a10da836b729742e534956caa99c79562ed10bad4b50cad71b383fb8646a5f95d909aa170a52a60d2c92c3f2c3a2c669bc6f6d725b8eb1c709c7a97be85288e3a3e04d07683343587a74166ac740a31936121b9096ed2edaa1f5cccc7cf6ea0e9ed5d92c2cd65b4bb5d543918e44f4dbb31ad0cbba517dde215aecef5cb9dfdeb015af840374898b49a6364c85af05b18e15638f86da1be7d5656d9285049f04ed8a03e88aba7005e33c0bc79bcd737438dca5c71f107c86ff401684fcb62607be0ba6e7ad22d3b1d2338fbe4c025b0a", "12c", "960f29a78bb828913a7dac7117de142524ea1af7f43a179ba0e64e0e48dd14414f7700b58440c2c6099e4129c64150cfe368367d411290fe73270c4cc6f7a7b337ef7be49516d4acd8d76be235a4104e66f573cfdea385fe1b4279b5d213d4482c4fa8c972a1350ce65d270d7b442046bfa00d6316213f442e378ef0dfd7c681293c115728bdac5a4dc4e48a884c76f2fd2d8cae697c0472af257a8fb32dfbe8e340a613c2786db52aea052cb70c4b86ea09a31360b3c94b73497b29915ef009f77e7b9c0375af27876b763aa248809e58177b3e580924ab3ecce40b8de97e44b5aacaba4776bc06fd3e5cabb0bafa36854ae4446b3eb5fefa6a58ef4d84165d7c2bdb7c532ad284484c0cf1a9f19126dd56f8b370463a19af311e234058aaeb26bff51629d4e2fa5955b8f82c6467f1a10da836b729742e534956caa99c79562ed10bad4b50cad71b383fb8646a5f95d909aa170a52a60d2c92c3f2c3a2c669bc6f6d725b8eb1c709c7a97be85288e3a3e04d07683343587a74166ac740a31936121b9096ed2edaa1f5cccc7cf6ea0e9ed5d92c2cd65b4bb5d543918e44f4dbb31ad0cbba517dde215aecef5cb9dfdeb015af840374898b49a6364c85af05b18e15638f86da1be7d5656d9285049f04ed8a03e88aba7005e33c0", .None}, + {.Shr, "a447aceb43d77c95bd1c213922eed53af9c171caa4bfa7a985fd0b5bf532c5e830e2973639d9afddd1a5d57ba5ca40f51ee97db58c348a45fa6cc4cba3a0c8615a69a586b3a80c7020bba62358b7fedc56a8d03d98ddbe35965c934c6aa10e348032218c1cdc5f4d7c8cbacdd43c31424df87d5c6a72c27aa7b78e01b093be757cfa2de15a3d3670d59e69c3a3da03ba7ffa258ad09fd324552d787704265ef37ddbc89fab2cb867092439cbf507742c0112c9e9ccb5f1d41cefef2c0e65ba654521e8796da3340034096f380aea4bca5325a7590dc8163b11d22dc0a45cf689d3d5879ecfd37e1f55fc835ce77c20e7a1834911611df5e8419b36ecc2988161da8c0e38283ae5f3032c61e444ea3d63a6cae80205311c321e983d1e19e5d1780f97089ad9d81a0ab671bd3b916fa577d04c53a8f70310382c73732908f3731f80ec198f613084505002ab0ae0e85ff2bb191bd7b42abf29ca15377b4d87ccccaddf44849f0c9e90b9f1d0bab029871963b1da3a383da60da33f826090932747f54d41ea0427a244e9e6a07ee3560e991b6e1f81c94301c16a33aac0bb4314ca23128d791a80ca1eab90fcbf6ef5119af6339c2def4983d166ba92d8e34fdc7773b9c986ef71d51aa6597dae780d96204d918e33b2b5cb36a0a52767e2860dc0749afe62813a458a4b5ad9f429de8a41ae2326b3529b39ceb8ac19ee4d2eea67", "b4", "a447aceb43d77c95bd1c213922eed53af9c171caa4bfa7a985fd0b5bf532c5e830e2973639d9afddd1a5d57ba5ca40f51ee97db58c348a45fa6cc4cba3a0c8615a69a586b3a80c7020bba62358b7fedc56a8d03d98ddbe35965c934c6aa10e348032218c1cdc5f4d7c8cbacdd43c31424df87d5c6a72c27aa7b78e01b093be757cfa2de15a3d3670d59e69c3a3da03ba7ffa258ad09fd324552d787704265ef37ddbc89fab2cb867092439cbf507742c0112c9e9ccb5f1d41cefef2c0e65ba654521e8796da3340034096f380aea4bca5325a7590dc8163b11d22dc0a45cf689d3d5879ecfd37e1f55fc835ce77c20e7a1834911611df5e8419b36ecc2988161da8c0e38283ae5f3032c61e444ea3d63a6cae80205311c321e983d1e19e5d1780f97089ad9d81a0ab671bd3b916fa577d04c53a8f70310382c73732908f3731f80ec198f613084505002ab0ae0e85ff2bb191bd7b42abf29ca15377b4d87ccccaddf44849f0c9e90b9f1d0bab029871963b1da3a383da60da33f826090932747f54d41ea0427a244e9e6a07ee3560e991b6e1f81c94301c16a33aac0bb4314ca23128d791a80ca1eab90fcbf6ef5119af6339c2def4983d166ba92d8e34fdc7773b9c986ef71d51aa6597dae780d96204d918e33b2b5cb36a0a52767e2860dc0749afe62813a458a4b5", .None}, + {.Shr, "7e6c75dcb4b79dab0becc3377bb3d78ddac01e260cf88e5a22f166ea2f50e276199054946277a43f9ac9142e0d6af3c81de4de05c243be05ec9eafcb583e7be885e81393192ea4e8f9026b16715f931546de521feccca60cec27c2c676d21d34b4c03fab8c5a5e472c1a8691b107758ce5ec0130eda7d29da504ab0f589aa67ee88d6508c73b8580756a401845d25a64e45314b3cfce47936dad1930a91fbc28b8e7fc1aa3001848111ab01087e10e8819933df92f1ded38e55869fcae0977207367dd362a4229a83313e4c56cacfeeb2fa2ccdb12c8e5e9032e01e6d1bddd4adab0678a8fed8bf737f85bfed47557ce7365caa446bfca76319812d649ac79ede622c88884c07907610c9ee9995bf8b9571adce881bf7293a068be6a63b27aedfa33fed90b74f39cf387e53072e1c1837cd03616d20f123a794978f6c4c020fbee1e542d03371e142b0612cd1370ce1487d332c1c93246d710391fd6a8b238ab604bbd5bb5e554e03b6704dc87ef6029453ab41249ac8d693df911d521b2d898e463fda8780234872753a6e7e255b2e5b9bdec420536dd87b756d010ca674d2d046073c10933983607558168a6e5182548ec5190712fb5d301e19b8cb325305e21623732d083a1a9e3868b262fd314b2ea4bf9e123dbb2d8c5ebbaf339902768d96850d3748b49925427b1aa4858f2c8636690dab315205618c47b8c97b9e134", "b4", "7e6c75dcb4b79dab0becc3377bb3d78ddac01e260cf88e5a22f166ea2f50e276199054946277a43f9ac9142e0d6af3c81de4de05c243be05ec9eafcb583e7be885e81393192ea4e8f9026b16715f931546de521feccca60cec27c2c676d21d34b4c03fab8c5a5e472c1a8691b107758ce5ec0130eda7d29da504ab0f589aa67ee88d6508c73b8580756a401845d25a64e45314b3cfce47936dad1930a91fbc28b8e7fc1aa3001848111ab01087e10e8819933df92f1ded38e55869fcae0977207367dd362a4229a83313e4c56cacfeeb2fa2ccdb12c8e5e9032e01e6d1bddd4adab0678a8fed8bf737f85bfed47557ce7365caa446bfca76319812d649ac79ede622c88884c07907610c9ee9995bf8b9571adce881bf7293a068be6a63b27aedfa33fed90b74f39cf387e53072e1c1837cd03616d20f123a794978f6c4c020fbee1e542d03371e142b0612cd1370ce1487d332c1c93246d710391fd6a8b238ab604bbd5bb5e554e03b6704dc87ef6029453ab41249ac8d693df911d521b2d898e463fda8780234872753a6e7e255b2e5b9bdec420536dd87b756d010ca674d2d046073c10933983607558168a6e5182548ec5190712fb5d301e19b8cb325305e21623732d083a1a9e3868b262fd314b2ea4bf9e123dbb2d8c5ebbaf339902768d96850d3748b4992542", .None}, + {.Shr, "3182d4f8352b48b8a703b0706fe87a5a2ff5617eec97d79cf3ff212b8f965d51fe1d8fa4ce70f00312fcebdbeea0e9ffbf92636f40d0d51401f751d2707527a102a321a441ad90b54211efa86044719a994a043516db1b38b1bfa4dbc9501feb7321ea95685eac28cbc126e3528524714a843b7b2d7ec25d8466f331b23b508b77b80998d390df0034690c2bbfd7251a6ee29dcfcf00d66c0ff0ebba45630c98e4d24332d837db93cdfea72fbeed9d5288b2b97a8f5a0601f3a4fb5bcf600cc09de059efeac34ccb1b8ef22968bd2ca08f0c44b50b0ac6fd7c4f966e2c48c891f2144949396658419376a332a49e40a82531840ebe8bbcb1c8ab773e919eb268de69e32f7d7c2c68269f99d6019b056fbd6941205c43bface99a3925b60a710e8981fb5be7e0acc5986f83378f37a36b970e10d7e9dfb6d769e3a5a4e081710a7ccc87b5485e5a5a57ef7f12b7c15c648c9be9c1899f8dcbbc9883617ced17e863ebb381dc13ed753de3df300f86fecfde0b4e62ddb5100cc0454bde0701626039230106e41f7bd5c1900f77224953a45c3644a98a9d532d250887bb1dbcc6685bd99b26144fffce62152f7cff1097348f50750111dbdcfa6f9e239db51a5cd7124c5d62b820dc757e22dc448a14471509bfed1bcc39594ed38a606aa7dc87d49634d6634ef0a3a31e7b8664470e5b1420e8b97cc7628b2278eec4dde408b8b7", "258", "3182d4f8352b48b8a703b0706fe87a5a2ff5617eec97d79cf3ff212b8f965d51fe1d8fa4ce70f00312fcebdbeea0e9ffbf92636f40d0d51401f751d2707527a102a321a441ad90b54211efa86044719a994a043516db1b38b1bfa4dbc9501feb7321ea95685eac28cbc126e3528524714a843b7b2d7ec25d8466f331b23b508b77b80998d390df0034690c2bbfd7251a6ee29dcfcf00d66c0ff0ebba45630c98e4d24332d837db93cdfea72fbeed9d5288b2b97a8f5a0601f3a4fb5bcf600cc09de059efeac34ccb1b8ef22968bd2ca08f0c44b50b0ac6fd7c4f966e2c48c891f2144949396658419376a332a49e40a82531840ebe8bbcb1c8ab773e919eb268de69e32f7d7c2c68269f99d6019b056fbd6941205c43bface99a3925b60a710e8981fb5be7e0acc5986f83378f37a36b970e10d7e9dfb6d769e3a5a4e081710a7ccc87b5485e5a5a57ef7f12b7c15c648c9be9c1899f8dcbbc9883617ced17e863ebb381dc13ed753de3df300f86fecfde0b4e62ddb5100cc0454bde0701626039230106e41f7bd5c1900f77224953a45c3644a98a9d532d250887bb1dbcc6685bd99b26144fffce62152f7cff1097348f50750111", .None}, + {.Shr, "422966accd2cf4a70ae2abe7b4a656ee64e66b2c3a0ef6b3b6596dd595cdc669f11ffcd3209d4141ac25c95f809d23dd6e36a113875dd2acd98126c6d72bbda404b50ad4f8c9a8f2beec022fa9578a8a48f76189f9ee5dd1302366bab6a56f87a59c4f331d574c54c432f02b53cb3e3872ef42832078af6fcf9fb13a75d597395a4012cdc9c0a4f1eb191543a66f1e5f28beec7678b435ae9772a036f282c36928ae060278195a46c4f69607911b44ce03688f3e1aa34d517b7e8f730931a40de2f66e3402c0060967fc438d42394af3ddf65fd99a722216f1dcac0dd6fd1b2498829b1dca20e2632b5b38b609930a46f1e1bb2e17319380c439a1bfddc95eba817ed606f96544147145186d26af6a5e6b36d50ea256d396f398e465de984a0ebe3daecbfbf33b6d2e47bc58e18a3a5edb39becd66d588ba2a6160fd6fcdd1cbcf85b49d24b8901d0e57f36ad3389e7e6b87380a5d953128befdb3c7087afe2c35c133a74febf6ee7145268054fcc885cf3290a56f9bd2d08c90d0d2c9afa2079d83be130bfbb1c9886321b30115263e24e3b28a0f77bd82ecba59ee1a77fbb118ad726e477c0adb5c7ee454b650edb70218e6d8fc1abed90bb758a45eac8932267f2e786366fa21c538a2179c97d61f9b8a33382194b31875f25465a6f9102ebdce43c290df20d93b6353aeb286e18aa953e67c537f96cad74ef818c2f38d74", "78", "422966accd2cf4a70ae2abe7b4a656ee64e66b2c3a0ef6b3b6596dd595cdc669f11ffcd3209d4141ac25c95f809d23dd6e36a113875dd2acd98126c6d72bbda404b50ad4f8c9a8f2beec022fa9578a8a48f76189f9ee5dd1302366bab6a56f87a59c4f331d574c54c432f02b53cb3e3872ef42832078af6fcf9fb13a75d597395a4012cdc9c0a4f1eb191543a66f1e5f28beec7678b435ae9772a036f282c36928ae060278195a46c4f69607911b44ce03688f3e1aa34d517b7e8f730931a40de2f66e3402c0060967fc438d42394af3ddf65fd99a722216f1dcac0dd6fd1b2498829b1dca20e2632b5b38b609930a46f1e1bb2e17319380c439a1bfddc95eba817ed606f96544147145186d26af6a5e6b36d50ea256d396f398e465de984a0ebe3daecbfbf33b6d2e47bc58e18a3a5edb39becd66d588ba2a6160fd6fcdd1cbcf85b49d24b8901d0e57f36ad3389e7e6b87380a5d953128befdb3c7087afe2c35c133a74febf6ee7145268054fcc885cf3290a56f9bd2d08c90d0d2c9afa2079d83be130bfbb1c9886321b30115263e24e3b28a0f77bd82ecba59ee1a77fbb118ad726e477c0adb5c7ee454b650edb70218e6d8fc1abed90bb758a45eac8932267f2e786366fa21c538a2179c97d61f9b8a33382194b31875f25465a6f9102ebdce43c290df20d93b6353aeb286e18aa9", .None}, + {.Shr, "d6ff2ab56fe36b527977caab927abda658d4c13fde711bfd31721ee6a0e0125021c35a3eec416e32087667c99577c0871ad34241e72d1127e67b9fc87d681e1ba63ffc3de9d93008043ef25382dc9d6d7e19ed29951665ebb7e0c47f47d482cf1efd4d3d75747212974bab6769b589ce3217b130b7e288c5b3887d3ab73f14f0af373cc44a734ad855b6752375648bdef2468f9f9a984109efa50fe3db21ac877ebf796089bdf6080f5b4019ad368989e919e9b93dd6e4384d1f3b75228922ff26996d4f79a8efd7839d9b0e94a1179d414b3b998273b0c17190c7610f2f53f46d3ef2bc7158b71c4f7738cac6939841f150d4af34310ea54375b502ef71835809eb3d4e0b314cd07129e9e4cfa68559de394d4a26c3defa2c16f5ce58e2acd0ddefb2380b3f1be0ea098d91a3528449414eab35af997236e353a44bcd160b4f470b6e5fbbdb1d92e815b44bd11eb3e39fdb2394ed0a73f5c83d33019e26ca5f33eb1bb229d34807d28a8d37d6532defb4eaa1e7eba13ec23d3f55e9d0215e40927873c34fdef88577fad92ffca54d52dceb81916df6d678b7071ac3e95453bdc49034a737433bce456922993c71fc71f8e7b93437f94698be7e1e6977135978f7fe153d3c3baa1ad9151a13b57f8fcf10ef789da8185db39ba9485a791d2078c1468db894f9435081f0e5473a483f03f541291edec5734bfca044db020ada1c", "b4", "d6ff2ab56fe36b527977caab927abda658d4c13fde711bfd31721ee6a0e0125021c35a3eec416e32087667c99577c0871ad34241e72d1127e67b9fc87d681e1ba63ffc3de9d93008043ef25382dc9d6d7e19ed29951665ebb7e0c47f47d482cf1efd4d3d75747212974bab6769b589ce3217b130b7e288c5b3887d3ab73f14f0af373cc44a734ad855b6752375648bdef2468f9f9a984109efa50fe3db21ac877ebf796089bdf6080f5b4019ad368989e919e9b93dd6e4384d1f3b75228922ff26996d4f79a8efd7839d9b0e94a1179d414b3b998273b0c17190c7610f2f53f46d3ef2bc7158b71c4f7738cac6939841f150d4af34310ea54375b502ef71835809eb3d4e0b314cd07129e9e4cfa68559de394d4a26c3defa2c16f5ce58e2acd0ddefb2380b3f1be0ea098d91a3528449414eab35af997236e353a44bcd160b4f470b6e5fbbdb1d92e815b44bd11eb3e39fdb2394ed0a73f5c83d33019e26ca5f33eb1bb229d34807d28a8d37d6532defb4eaa1e7eba13ec23d3f55e9d0215e40927873c34fdef88577fad92ffca54d52dceb81916df6d678b7071ac3e95453bdc49034a737433bce456922993c71fc71f8e7b93437f94698be7e1e6977135978f7fe153d3c3baa1ad9151a13b57f8fcf10ef789da8185db39ba9485a791d2078c1468db894f9435081f", .None}, + {.Shr, "521898bc787145f834ef96744b89c003fd8f0940182dbd2f808ce5514c52d512f4110399b90a18ec985eb1be6d4c0b3bf270ab2a4fa9defed647c9f9e66810eb0c6f54570b8d8d476bc51ac4ba56d871c4ad8bb037caac52a3549ef9e87a763976d37bf7cdff787c89eb1e77ccbe1fdfc3991d902489f9a22e2f04dce46f21dd800333e223c8a455136dbda97e5fd3be557c0704a497ac1d92150993bec9682936cd27abba07d3b37ec7469f64da1e2c4cd98e1070df9f2f054908c099f9704449d8adb8b4fc91281643aaed6d9852fc8e8183199f4b26aabafad363a20561cfffab754d6d3bd0b179d9e870bab78c038a4656c3be281ca84b251d1b8c3133243155dc852c74f2062cba374f32d1ad63acfd25019b35bf82a9b85339df5cbc863bb300c14a792833cd3f261e95b41d3b568f92b6787ead5091ebe11522dbd1729b6ea02e831d719c97c06ec4910a641ebbe87c6fabf8fe8ab0a9f7aeafd6d2637812c4d54625d7eb14d47230600528b75569615dc9dd7f7bdf6b5c0d4d8f045512acd3986ab46044b0c71fb702f94549f98e57c5f8fae60e3cae0d5a8a5e046dcdd88918d148e4f6c4c999fecf9b4a4abd95ed0ae6261da6d245aeea4b20107b392202e2ccf953fdcf918120e56d32329488c9cc182d4fa5904d0002972580ee0ea43d9c2b65b96817317f2500e253b865631b53113f5bda8178a7f02d9e7ee8", "258", "521898bc787145f834ef96744b89c003fd8f0940182dbd2f808ce5514c52d512f4110399b90a18ec985eb1be6d4c0b3bf270ab2a4fa9defed647c9f9e66810eb0c6f54570b8d8d476bc51ac4ba56d871c4ad8bb037caac52a3549ef9e87a763976d37bf7cdff787c89eb1e77ccbe1fdfc3991d902489f9a22e2f04dce46f21dd800333e223c8a455136dbda97e5fd3be557c0704a497ac1d92150993bec9682936cd27abba07d3b37ec7469f64da1e2c4cd98e1070df9f2f054908c099f9704449d8adb8b4fc91281643aaed6d9852fc8e8183199f4b26aabafad363a20561cfffab754d6d3bd0b179d9e870bab78c038a4656c3be281ca84b251d1b8c3133243155dc852c74f2062cba374f32d1ad63acfd25019b35bf82a9b85339df5cbc863bb300c14a792833cd3f261e95b41d3b568f92b6787ead5091ebe11522dbd1729b6ea02e831d719c97c06ec4910a641ebbe87c6fabf8fe8ab0a9f7aeafd6d2637812c4d54625d7eb14d47230600528b75569615dc9dd7f7bdf6b5c0d4d8f045512acd3986ab46044b0c71fb702f94549f98e57c5f8fae60e3cae0d5a8a5e046dcdd88918d148e4f6c4c999fecf9b4a4abd95ed0ae6", .None}, + {.Shr, "5b69ee0b2aa2b0044201ff74e1fc86d96708b75fc5befc21f8eb9c20a30da8e1376c151b81a55389389ac7f980736bb92b3accaa7471650065bd2da85e18a063d9989420d18a7bd7a8ee89a687b482529f69ae8d79185edd460f74b6f55848c8b377499edbc0cba1483b9c9a39fbea476fb6c1522ca8a157870932c48bfc6e2daf27f17415247bb5379e0e65988e7ddb9f38445800bc38065fd88f8a29c5a140413f3ebace8714cb20093643563c83e47e0ff3e1d4d773f08335379f48372170675fd714ba8f5a980f2d854476fbd854c5727865c052d8b00100a9bb6d71bc8283b37de21502037ad41c935653d837cb6110bd9f4ebed0844b3731eca02510943228ddd4a91fab398631dd11b232048839b473b888b90d2d280c8704fc50efe9abcf308b35b3f793ada6d6db5cdf74c82268e3d982ac137c13555b1593c362ad7cb334c4e530cbf2ca2406e9e5fa96cd07c745c64cffd117a0970f6f15ad6b134d9204db534755b0a6a8676acfbfc90be01000ceb6f3a5396b31f2d56b8e19116e27405ee91b8d9e8af62df298c575226ce372dd3d7b60153a63e674b291fca30ca03b01dfc5e0a4692edd92f0616782c6312127f22bed3ed183948fad0b6c9cdb5528e7776e8891aea7f2e751801f61af54c25dfc87f556c82b3723ef0d4fa21b67035c20a4b95ddac9cba7da3b6c2c04cf24c2f66f1f8af0e7834285d0cdb9", "3c", "5b69ee0b2aa2b0044201ff74e1fc86d96708b75fc5befc21f8eb9c20a30da8e1376c151b81a55389389ac7f980736bb92b3accaa7471650065bd2da85e18a063d9989420d18a7bd7a8ee89a687b482529f69ae8d79185edd460f74b6f55848c8b377499edbc0cba1483b9c9a39fbea476fb6c1522ca8a157870932c48bfc6e2daf27f17415247bb5379e0e65988e7ddb9f38445800bc38065fd88f8a29c5a140413f3ebace8714cb20093643563c83e47e0ff3e1d4d773f08335379f48372170675fd714ba8f5a980f2d854476fbd854c5727865c052d8b00100a9bb6d71bc8283b37de21502037ad41c935653d837cb6110bd9f4ebed0844b3731eca02510943228ddd4a91fab398631dd11b232048839b473b888b90d2d280c8704fc50efe9abcf308b35b3f793ada6d6db5cdf74c82268e3d982ac137c13555b1593c362ad7cb334c4e530cbf2ca2406e9e5fa96cd07c745c64cffd117a0970f6f15ad6b134d9204db534755b0a6a8676acfbfc90be01000ceb6f3a5396b31f2d56b8e19116e27405ee91b8d9e8af62df298c575226ce372dd3d7b60153a63e674b291fca30ca03b01dfc5e0a4692edd92f0616782c6312127f22bed3ed183948fad0b6c9cdb5528e7776e8891aea7f2e751801f61af54c25dfc87f556c82b3723ef0d4fa21b67035c20a4b95ddac9cba7da3b6c2c04cf24c2f66f1f8af", .None}, + {.Shr, "68ca65e1a0169c47d6535d2749fee63d0300a91b31fc0a438632a5a722e919804e2aba46b839da2ffa20dea5df289bbb66cda6c46281606edfd2f54f117db75ff0aea1fd13550fa77876a0844f04ea40dbd8c9bf4119b6c5cbb0409f9eb53fe60e8d501ebae7247be51c74c0069432d2704e0bf3368819a37b1f23017f8d95494eecd821050101b049ea2c385f32d45f012bab31e4d2df660acd34ea32e9ae03f3dc0e76f52a7701630a013092dc8b9d2e794f4e10ac7e414a9ec345ffcfa3974803e6f1ef4ac392611070255f527ba217b1c83930b4a669482117414383333fa9d3f7cc5c8aac64cfe37aef9f1b07966a5f2e72d0e0fb8b36c83d1ec2731b5ebd06f635d665dd19f7dab4b5f775bdf1c0e921870c0b27d6538e1e6bf1951232c1310382326e9b70cd74cefea281113fce6a52fa941912233c650a3bfc8a5d615384e7e2528b106accc9dcbd493f7f18df7433d4d7446414417cb9eee82f29c792c870061ed0016cfb681f1e5e9938cf1ec5f60e5396b79716e3635ea2e9a36b20f0fced0441d4f7a23aeb096714ca666b5a4247fb50430e5f0a8f53a523a06eac0305c0cdef648e6662bc3772bff74355cf12c119ff4bcdf37df2ecd29eedd64cef616bb7a4e376bc7bddb121eb0f1b0540317e2b3b20fca0417fee0821b3c2cbbd980f0fbc33fe23e16703a4c17db7247a8f0052965a2c655e2a289b1fc8fd", "1a4", "68ca65e1a0169c47d6535d2749fee63d0300a91b31fc0a438632a5a722e919804e2aba46b839da2ffa20dea5df289bbb66cda6c46281606edfd2f54f117db75ff0aea1fd13550fa77876a0844f04ea40dbd8c9bf4119b6c5cbb0409f9eb53fe60e8d501ebae7247be51c74c0069432d2704e0bf3368819a37b1f23017f8d95494eecd821050101b049ea2c385f32d45f012bab31e4d2df660acd34ea32e9ae03f3dc0e76f52a7701630a013092dc8b9d2e794f4e10ac7e414a9ec345ffcfa3974803e6f1ef4ac392611070255f527ba217b1c83930b4a669482117414383333fa9d3f7cc5c8aac64cfe37aef9f1b07966a5f2e72d0e0fb8b36c83d1ec2731b5ebd06f635d665dd19f7dab4b5f775bdf1c0e921870c0b27d6538e1e6bf1951232c1310382326e9b70cd74cefea281113fce6a52fa941912233c650a3bfc8a5d615384e7e2528b106accc9dcbd493f7f18df7433d4d7446414417cb9eee82f29c792c870061ed0016cfb681f1e5e9938cf1ec5f60e5396b79716e3635ea2e9a36b20f0fced0441d4f7a23aeb096714ca666b5a4247fb50430e5f0a8f53a523a06eac0305c0cdef648e6662bc3772bff74355cf12c119ff4bcdf37df2ecd29eedd64cef616bb7a4e376bc7bddb", .None}, + {.Shr, "abe9a2bdc1f77a199fdf618b0a8e1492c30260559575b5d6c09a0d1451d725050bb9c728318269a1213e06b79bf58a56cd94862e5309cf58fbba578ca3e2918600024c048f75ab93820ba4c8c0f5bdc20402683b565dca14cfbb208b65142823bd8c967de3710d31ef4b7ebd568699925d5a792c5803981f3a27789d5c4f6ac24329da4792d3b00ca01633722b61b641d34ce7dfa85a82179d024d7773592d78ac281710d9fa3820511e60649f908ce0f90368f733d6292a31af3e97b6b16db1af0a5d5ea7a01772866cfd08293634378a21021bc0d7ec5a4a5d09e649126a04798a1c2d1f8d61cf7d9ac88030c15bb4c2ae9ec97804b36ad3cbd23e6705ef5c98b53686cf6469dfdb1ced5e90aa0c3b5c2cd7282caa5b5d38217a0b6026616c1bcdc8d22ecbda837f8ee337b7e442c9945b2ecd0d2b82708377e699f6f8ba2faa7035f04ac890400f3d9032777e3ecd0dd68e30b7cc0666fe6617bd56c1d1e742af9cb734256158d21c9cc37535b13fc74d5c3e1173c33f0bc3060bd9b99284def34f55c00e8501a104c1368b726df11542ccce8f9ee9bf6f92f762ec1efda4a9be3e01f48f67075494ed039acb26ca56b81be00f872f45df98ec1a023f9e9616d8d09c9d84d1f47b73e0986b5b11bb694b3dde98090cd67bdd552ca4dd88a04ba2a5f9d544089e456f4d3dbb982337066d41fbedc3fa2e29d60c76a54aae98", "21c", "abe9a2bdc1f77a199fdf618b0a8e1492c30260559575b5d6c09a0d1451d725050bb9c728318269a1213e06b79bf58a56cd94862e5309cf58fbba578ca3e2918600024c048f75ab93820ba4c8c0f5bdc20402683b565dca14cfbb208b65142823bd8c967de3710d31ef4b7ebd568699925d5a792c5803981f3a27789d5c4f6ac24329da4792d3b00ca01633722b61b641d34ce7dfa85a82179d024d7773592d78ac281710d9fa3820511e60649f908ce0f90368f733d6292a31af3e97b6b16db1af0a5d5ea7a01772866cfd08293634378a21021bc0d7ec5a4a5d09e649126a04798a1c2d1f8d61cf7d9ac88030c15bb4c2ae9ec97804b36ad3cbd23e6705ef5c98b53686cf6469dfdb1ced5e90aa0c3b5c2cd7282caa5b5d38217a0b6026616c1bcdc8d22ecbda837f8ee337b7e442c9945b2ecd0d2b82708377e699f6f8ba2faa7035f04ac890400f3d9032777e3ecd0dd68e30b7cc0666fe6617bd56c1d1e742af9cb734256158d21c9cc37535b13fc74d5c3e1173c33f0bc3060bd9b99284def34f55c00e8501a104c1368b726df11542ccce8f9ee9bf6f92f762ec1efda4a9be3e01f48f67075494ed039acb26ca56b81be00f872f45df98ec1a0", .None}, + {.Shr, "cd864e046f35a6815a4c4c9775ffedfd17b3186bf9d48c6f19287a37aae92152b6b708720b6f874c236fcb5c6434d0593dc1805851edaa17763ddf3ebb56355f98d23464cdd53d84fce8d67fe5ce685faf7714612def7b353d299ba0b865f17b035b2baa5f754d0c0ab768f40523d92837f3bf1b824163320dbf227e3feda008417ac95f786e02da765df9d9b6c1f767bd9420cdd82705c9b99fbfad778174880a8312c358bc296d8e2109a53b0801919f7d88f924c1644aab0c11c37ddd36e0d35a85bea538e56e60977ee4c9d7581cf4408adcaa2334b147dfebde1175930b5507d4778e40c767612fb3d004d3fa1787670e7065121f2feff23ec28949a1e3d24f83dba48ae8c5bfbf7ba421da8e10520d21e567cf0d5476f1ad4a39330579c0d5c1e1ae6d543cc4facce8b60e606930c314b2bf1d758c95cd3a0d0d6f5da048651da16f4e354db1c38d9ff70d6b178e9ea1cf97820cd105c7f5455a3a0d2526d7e695a4ba044479a6b70cfbe9a9a724fdbc185877c807d686b444ca41ea0ff811395cbdb9a942125cb4ec168e91c7ef95c46532404c0a3cd7aaad263d1c570a78cfac82ea038b9fa8d410506d59b69fffc3592283077f26a6eaef07eca9d735e1603f814465695e389b8a6eb7e58a8ad728ead03e2520e8692cd595d31511a08a4d2c3c0946c052d4c988a230dd08d25cabf20d0c2bc3f3ca55fb66d96cd6", "78", "cd864e046f35a6815a4c4c9775ffedfd17b3186bf9d48c6f19287a37aae92152b6b708720b6f874c236fcb5c6434d0593dc1805851edaa17763ddf3ebb56355f98d23464cdd53d84fce8d67fe5ce685faf7714612def7b353d299ba0b865f17b035b2baa5f754d0c0ab768f40523d92837f3bf1b824163320dbf227e3feda008417ac95f786e02da765df9d9b6c1f767bd9420cdd82705c9b99fbfad778174880a8312c358bc296d8e2109a53b0801919f7d88f924c1644aab0c11c37ddd36e0d35a85bea538e56e60977ee4c9d7581cf4408adcaa2334b147dfebde1175930b5507d4778e40c767612fb3d004d3fa1787670e7065121f2feff23ec28949a1e3d24f83dba48ae8c5bfbf7ba421da8e10520d21e567cf0d5476f1ad4a39330579c0d5c1e1ae6d543cc4facce8b60e606930c314b2bf1d758c95cd3a0d0d6f5da048651da16f4e354db1c38d9ff70d6b178e9ea1cf97820cd105c7f5455a3a0d2526d7e695a4ba044479a6b70cfbe9a9a724fdbc185877c807d686b444ca41ea0ff811395cbdb9a942125cb4ec168e91c7ef95c46532404c0a3cd7aaad263d1c570a78cfac82ea038b9fa8d410506d59b69fffc3592283077f26a6eaef07eca9d735e1603f814465695e389b8a6eb7e58a8ad728ead03e2520e8692cd595d31511a08a4d2c3c0946c052d4c988a230dd08d2", .None}, + {.Shr, "d95ddb1680c4a843810e0278c467286c1fa1243dc275f8c3460f00e8dde1bb2e678ac43a820ef70846601bb1661a890c06ca0bfb86779a1c498d62f5455501cb0ce0b22838998bd8a86a35b19c4083236244bca17fb019ad3df5245f66afd3a353b69e13b9c5b139cc27797b9320bd31d634c78ecc629a3fda5b47bee04784f876984fba69f7787093f7e11dad6e0de8b98ff367df76d8c1bc9ee7d4b01b95e41648e3ff8801247c0c991facc5eb51a9b582afc2b643d779a73a37b1ca6cac6890905ff69602e712ec4ce29e8abe980dbe171380f06594317e99a2b5498244dbbce5c19e33642edd3dd736df1d0932783a06eefd87235edd3b1bb12bd1fd470e3fda36b4e264191ecaeb6f327b03bf0e19e7267819dcf272b801b48e2a14c89f6e818d4cc297747464c325961895de54a09de7d4dd91d848f85a988887c206f9ed702afdb7d3e09e462d0af25ca2e98d94a45917dfcef5c018a36297f80adefa50f9009bbd1c3305c28d0e57d07cd33a5809299fe10f9e4f60fde97aaae0a152cd78df57c319a0d193687311e989bf45734dfb2319ff62d8cf5455f839865c7ba31acca9a752b85deed09e948afcbc1576a4a35630f812eb829cd3ef4846d263106ae20b0443194ca34f80fc844398f2dcfedc2a728a928dd9dfd9c4d00cae972693cc5ff73d61e28d97389d04357b60b93e71e8a53384af379a87c1104e7091", "258", "d95ddb1680c4a843810e0278c467286c1fa1243dc275f8c3460f00e8dde1bb2e678ac43a820ef70846601bb1661a890c06ca0bfb86779a1c498d62f5455501cb0ce0b22838998bd8a86a35b19c4083236244bca17fb019ad3df5245f66afd3a353b69e13b9c5b139cc27797b9320bd31d634c78ecc629a3fda5b47bee04784f876984fba69f7787093f7e11dad6e0de8b98ff367df76d8c1bc9ee7d4b01b95e41648e3ff8801247c0c991facc5eb51a9b582afc2b643d779a73a37b1ca6cac6890905ff69602e712ec4ce29e8abe980dbe171380f06594317e99a2b5498244dbbce5c19e33642edd3dd736df1d0932783a06eefd87235edd3b1bb12bd1fd470e3fda36b4e264191ecaeb6f327b03bf0e19e7267819dcf272b801b48e2a14c89f6e818d4cc297747464c325961895de54a09de7d4dd91d848f85a988887c206f9ed702afdb7d3e09e462d0af25ca2e98d94a45917dfcef5c018a36297f80adefa50f9009bbd1c3305c28d0e57d07cd33a5809299fe10f9e4f60fde97aaae0a152cd78df57c319a0d193687311e989bf45734dfb2319ff62d8cf5455f839865c7ba31acca9a752b85deed09e948afcbc1576a4a35630", .None}, + {.Shr, "5051d0ef22ee374d33943c22165ecba37ddb8001f52df08a127e2f1284792ea06448d80612fcec92b9d28f84d7c55878e5f611477e385cf00051653f3077c5d03edff987ac29add8d41d5163d7a9f299f8e762a161d62896aebdd9d135d04da96b292a1fe860127e80087a4cf4aae916b7b3e986866cc4735ceb9c7da25f7a1e14e3e740f188e90bdea11504f2e3df54e3e783975cc0df787de9d5aae58dce7b297c15abc658049544b57a3af55395588e407b9ae5023eb327517a8a537d3b131f57263117e652cbeec0292ce2a019045793c5e73856adfdc5bdeaaac6302def5047be4e98b594e125e68403932c6206fce86990e9ccbea5e25f0607f24053888181f397644b8e4d74e7f3d405852595f9d4acca6ee7900a36c2f7709014b54cfdf4b4e5545db1c0279850c636a14ed7cb9f49af42b0220e8369f1bd14ab3d5131d99270d60251ffc64126988cfc1a9b3d060990d66b0754ef6808ec6999548ac5852e35d3df49022c9dfeaa832881e18ecd6087f4acdadc495d9a3635a46cde5daf5dc7cff90b6f19989da16af474abeb02fb59ac79717208b1be1a62b065d00570688c36186abb5992439ab8a4391c16065b70532d111281b948d4225684f49f320c180429a219919480d4fdab3833aa1baa18f386d12f884dacdc52d482635e90e60e0fc77940f3c1adaa060772ac61d6278e95f54ab44966da6f6999886f", "0", "5051d0ef22ee374d33943c22165ecba37ddb8001f52df08a127e2f1284792ea06448d80612fcec92b9d28f84d7c55878e5f611477e385cf00051653f3077c5d03edff987ac29add8d41d5163d7a9f299f8e762a161d62896aebdd9d135d04da96b292a1fe860127e80087a4cf4aae916b7b3e986866cc4735ceb9c7da25f7a1e14e3e740f188e90bdea11504f2e3df54e3e783975cc0df787de9d5aae58dce7b297c15abc658049544b57a3af55395588e407b9ae5023eb327517a8a537d3b131f57263117e652cbeec0292ce2a019045793c5e73856adfdc5bdeaaac6302def5047be4e98b594e125e68403932c6206fce86990e9ccbea5e25f0607f24053888181f397644b8e4d74e7f3d405852595f9d4acca6ee7900a36c2f7709014b54cfdf4b4e5545db1c0279850c636a14ed7cb9f49af42b0220e8369f1bd14ab3d5131d99270d60251ffc64126988cfc1a9b3d060990d66b0754ef6808ec6999548ac5852e35d3df49022c9dfeaa832881e18ecd6087f4acdadc495d9a3635a46cde5daf5dc7cff90b6f19989da16af474abeb02fb59ac79717208b1be1a62b065d00570688c36186abb5992439ab8a4391c16065b70532d111281b948d4225684f49f320c180429a219919480d4fdab3833aa1baa18f386d12f884dacdc52d482635e90e60e0fc77940f3c1adaa060772ac61d6278e95f54ab44966da6f6999886f", .None}, + {.Shr, "bb5faf4e1ad31d61da988276b67be5a397aef740a08b4c6cb8980d8181d77896ad1411579867ed2d76221bfe25438c19f6c9e1fc0f33c5f5db3cba297d6d4e19c833d8e34737bed076407571df7c2edc4c8f13d3379ad2a221d1a1685c194ab9115cc55832b95ee3c488762b44a4ec3932dd0e6fef500de91a3dab48ca49eb3ba16dbfd817dfa62cd9e941942a09896516d7a5ba41ba6bdb81431fe79c4c49d51b3b26b66e5be91673954faec0740afae1cd659dff4cdb195f5fabffefcb4ce774246028bead42c3ee4498e470e5e668be4b0b64bb4036a0c3558172632f2bd80358a558cc7c6b69f19adbde14a81b7bcd07aab6d6535dc6a404d4ad3841eb2fec0064651adc0c159b120e75246604480d5e3d7d4477d0363846de40edc8a01e0ac1e0dabfe960779245a614ea88a41bde9e6270cbff7c8ec940f0902fd95a6abf757dbf839983db286163aa6f46b43e019839beb1408e7319dfc82ce714ccb9e5b77e8d9db4440919cbb5adfcc8fa79fbd0ec29558bc56823b063fc79b8568899957b8330dcd6c40d8c66d09fb0ed5260fe364d43d1cef22d167e9303d15f3049c0a794dc3d72b2014ae6b1f6ea32d37be5dc9e8bc89ebeff6b51ecd3dd5a4b3b9bf839f9e780005230d256b62867d66f94e0fbaf9f665725a4e44c0ed0f91638221bc8fa596e1582c2cc1a3d296650201fdb4a6bd79ba7356013508f9a2312", "1e0", "bb5faf4e1ad31d61da988276b67be5a397aef740a08b4c6cb8980d8181d77896ad1411579867ed2d76221bfe25438c19f6c9e1fc0f33c5f5db3cba297d6d4e19c833d8e34737bed076407571df7c2edc4c8f13d3379ad2a221d1a1685c194ab9115cc55832b95ee3c488762b44a4ec3932dd0e6fef500de91a3dab48ca49eb3ba16dbfd817dfa62cd9e941942a09896516d7a5ba41ba6bdb81431fe79c4c49d51b3b26b66e5be91673954faec0740afae1cd659dff4cdb195f5fabffefcb4ce774246028bead42c3ee4498e470e5e668be4b0b64bb4036a0c3558172632f2bd80358a558cc7c6b69f19adbde14a81b7bcd07aab6d6535dc6a404d4ad3841eb2fec0064651adc0c159b120e75246604480d5e3d7d4477d0363846de40edc8a01e0ac1e0dabfe960779245a614ea88a41bde9e6270cbff7c8ec940f0902fd95a6abf757dbf839983db286163aa6f46b43e019839beb1408e7319dfc82ce714ccb9e5b77e8d9db4440919cbb5adfcc8fa79fbd0ec29558bc56823b063fc79b8568899957b8330dcd6c40d8c66d09fb0ed5260fe364d43d1cef22d167e9303d15f3049c0a794dc3d72b2014ae6b1f6ea32d37be5dc9e8bc89ebeff6b51ecd3dd5a4b3b9bf839", .None}, + {.Shr, "d5c846a7fec2d2be6ad47d66034348d237eb2d26a6c6d1e709f9473f13cf08231f4ac98759164c0b2329ec5c93118e9bde422fe767919978d6fa3b8043f1234753d42dd39bb0601c3b8a2128a3e20beceddd50139d91dedaa5b9d6d643b6676baff0f17cb165d1fc07fd79e1cf73cf3bf573f8823825ec114e1182e896398b2f27cffe5bccbc73c715d8613d91aeb08a8d9a902bd3628508ef7b9cef5b44a4956e034e26be5c0f1e00a7437a4a293074877b3e56cb78fe9fbfa3908a9c24400d0e43df868f734aaf55889c100511a51806dd9c740a2ebaf17907e25711b7ea6ef8fa9289cbfa41da1040355fb8937b143a3d19ac0222edba281d4349c2763eeee8d2c1182b161d90f009668712959c52f474cddcd16d1a3a29703d39fd1ecabc3cdc242fada16357756b2cf973c88046913a837758dd2fc312800b69d40a231ad1ac911f24d2c12d61ab72044e18e3e9331dadab633c019640b9f8fd549dcefb1886d8ab50ba1814ff76f70beb2aa25f0aac8c77169ad5a7ead4f93997b213302c2c92a464a9179f95caa6e56ee1a31cf8a1a1bf2347f3d8bebfe77595fd8627f51482a1efbdf5eb7e19267c7ba5b35dcfcd024466fce64074ff67ef6add84c74e1bb130e17a82928c0b1161fb5539b18ba8fbdbd88bdfed30bf51295ed826b5680cfce9094d767a5a74de5e3dd8407581cc0eed674c414bee2fab8987871de5", "3c", "d5c846a7fec2d2be6ad47d66034348d237eb2d26a6c6d1e709f9473f13cf08231f4ac98759164c0b2329ec5c93118e9bde422fe767919978d6fa3b8043f1234753d42dd39bb0601c3b8a2128a3e20beceddd50139d91dedaa5b9d6d643b6676baff0f17cb165d1fc07fd79e1cf73cf3bf573f8823825ec114e1182e896398b2f27cffe5bccbc73c715d8613d91aeb08a8d9a902bd3628508ef7b9cef5b44a4956e034e26be5c0f1e00a7437a4a293074877b3e56cb78fe9fbfa3908a9c24400d0e43df868f734aaf55889c100511a51806dd9c740a2ebaf17907e25711b7ea6ef8fa9289cbfa41da1040355fb8937b143a3d19ac0222edba281d4349c2763eeee8d2c1182b161d90f009668712959c52f474cddcd16d1a3a29703d39fd1ecabc3cdc242fada16357756b2cf973c88046913a837758dd2fc312800b69d40a231ad1ac911f24d2c12d61ab72044e18e3e9331dadab633c019640b9f8fd549dcefb1886d8ab50ba1814ff76f70beb2aa25f0aac8c77169ad5a7ead4f93997b213302c2c92a464a9179f95caa6e56ee1a31cf8a1a1bf2347f3d8bebfe77595fd8627f51482a1efbdf5eb7e19267c7ba5b35dcfcd024466fce64074ff67ef6add84c74e1bb130e17a82928c0b1161fb5539b18ba8fbdbd88bdfed30bf51295ed826b5680cfce9094d767a5a74de5e3dd8407581cc0eed674c414be", .None}, + {.Shr, "3b5ac6e9a11cae85752d4171d3a55be164c2d585519351f43d08fe4d8d5912049d7cdb538fffd0f8eb4df07a0b2cab4516876fb12834a1a5a09d4d3d076c111e882afea3492ea8bb879e1db2af5fc2aa63b216dbf8c3456b19df44d143ef168283ff2ae3e6bbf5ee7fccf1cea9a0fd0aa9d9b2450a52c15b38d114461f1e29ad45d241a4bd93b1fdf266bb4995c812461ebe008e5d199aae1a3ac49c9f7855867aa73283cc227882a071d7fe041fab72447120c909ff366828f6ac83028d12ca0ba7c329f62486fb466721db7a7e9def1835adae2fa19c550446a21f14b4f1b6a41f5f64f05bce1dc4da6072c3fd5ec7ec1cc5ecc88ec065ef3c2e409d10e93f5dde3528e2c3c3e71268c10949c99f9b35785c4ffa5da0349975dbee9a7f72d493e961fb66c65a87f2824000ce5da54f103f606f5e63bba54e539f0be0133010378c42a187c93ba86cfe11084df42b79ccde8744871cdf2a7c0e76d2f88f8d4a3077abe76b2a3904d637c5f520a6208c5116185706701a5c258e6de36d012c565e41fd853bb019be1b0c991fce4584c07e9b4d92e3178bf43d67557e2cc45fc3bc2c6f88d08432c64f0b5acc831b3213d01ed36422e1d8fccdde16c31f080398e30d4358e411abe696159a1aa3949105a3ecf3fcfe99646bfe4372ed53dc6a834467cd11c293ff81e00c3a66ecd3f20600629d9adaa13dc862609897ba1ea4a1", "b4", "3b5ac6e9a11cae85752d4171d3a55be164c2d585519351f43d08fe4d8d5912049d7cdb538fffd0f8eb4df07a0b2cab4516876fb12834a1a5a09d4d3d076c111e882afea3492ea8bb879e1db2af5fc2aa63b216dbf8c3456b19df44d143ef168283ff2ae3e6bbf5ee7fccf1cea9a0fd0aa9d9b2450a52c15b38d114461f1e29ad45d241a4bd93b1fdf266bb4995c812461ebe008e5d199aae1a3ac49c9f7855867aa73283cc227882a071d7fe041fab72447120c909ff366828f6ac83028d12ca0ba7c329f62486fb466721db7a7e9def1835adae2fa19c550446a21f14b4f1b6a41f5f64f05bce1dc4da6072c3fd5ec7ec1cc5ecc88ec065ef3c2e409d10e93f5dde3528e2c3c3e71268c10949c99f9b35785c4ffa5da0349975dbee9a7f72d493e961fb66c65a87f2824000ce5da54f103f606f5e63bba54e539f0be0133010378c42a187c93ba86cfe11084df42b79ccde8744871cdf2a7c0e76d2f88f8d4a3077abe76b2a3904d637c5f520a6208c5116185706701a5c258e6de36d012c565e41fd853bb019be1b0c991fce4584c07e9b4d92e3178bf43d67557e2cc45fc3bc2c6f88d08432c64f0b5acc831b3213d01ed36422e1d8fccdde16c31f080398e30d4358e411abe696159a1aa3949105a3ecf3fcfe99646bfe4372ed53dc6a834467cd11c293ff81e00", .None}, + {.Shr, "90c68fd88a6d390e656821af6b5da88eb9ec3917e7a054f8ce5026174f912807a1e31c81efeb0b3aede567537b6f58f73ba563bb351218bb824ff881c3b0ea28b0f6e6a58153ac409c169deeef2a5ff0c0cb35eab6fadc1ff708949589efd610261906c075e4d35d4f2ad66005e4cebe8bf39f1655ceca74af899632cf2002dbc157a9ab4202caf485c01c7fd54a6e7b8764069b811cd9271cc1fc0b126ef99411099112d2492c13c1dd87a7e7e9880b6eec50f202bd3a9d71176ad2f1692af05fc522cbe0e525051236687a384155edd18ab680aeddda5c5866a5c36dfffd777744a21ff31140b83b03fc42de67c07252d536808b3a4ae55557ad5d774902bbcb26802dd4646949280d972a8bb39ad7aa64ce67a50f8dbac376869b3bdabe21a2282ddddaa92bc58b9394a6816260195420ec8c288afa310e03d689c7364e717eaf4eb477fa83be8cb4e147a066621d0b0609ecb6b2bfd9479111e8a8e4dda837398a4e95fe8cf53d05ec458901043482b41437c91cba09013ead677496be50d3343dd233ed3459ab498cc7db7a62addf802d5950ba7abf92f11bec2ff273d051cce3cf4c3557cabad2d777af91bcdafe35053d590654b3909b89e1db987dd5277620af0879a11ef99f84ed0e2d8dd1431ae89253564ccd5e510187a35977c810a38a08c8f2e47eb8ef6bd27b715c12769f0bd6a2426b47356baae5e9a79937", "1e0", "90c68fd88a6d390e656821af6b5da88eb9ec3917e7a054f8ce5026174f912807a1e31c81efeb0b3aede567537b6f58f73ba563bb351218bb824ff881c3b0ea28b0f6e6a58153ac409c169deeef2a5ff0c0cb35eab6fadc1ff708949589efd610261906c075e4d35d4f2ad66005e4cebe8bf39f1655ceca74af899632cf2002dbc157a9ab4202caf485c01c7fd54a6e7b8764069b811cd9271cc1fc0b126ef99411099112d2492c13c1dd87a7e7e9880b6eec50f202bd3a9d71176ad2f1692af05fc522cbe0e525051236687a384155edd18ab680aeddda5c5866a5c36dfffd777744a21ff31140b83b03fc42de67c07252d536808b3a4ae55557ad5d774902bbcb26802dd4646949280d972a8bb39ad7aa64ce67a50f8dbac376869b3bdabe21a2282ddddaa92bc58b9394a6816260195420ec8c288afa310e03d689c7364e717eaf4eb477fa83be8cb4e147a066621d0b0609ecb6b2bfd9479111e8a8e4dda837398a4e95fe8cf53d05ec458901043482b41437c91cba09013ead677496be50d3343dd233ed3459ab498cc7db7a62addf802d5950ba7abf92f11bec2ff273d051cce3cf4c3557cabad2d777af91bcdafe35053d590654b3909b89e1db987dd5277620af", .None}, + {.Shr, "8a2885edc32e0cb7232c84019faabafcf882483a97630637233e749366bf4e8439f33035781551644e96d4bcca0ce05aaec2762b515008cb2a7a9d54162213b21f964f6c91ee77330bd2628c2983ffe95ac3075f84009a124f4305ffb767eb4f9fab35bc1cfde6ac0055989a672b8ec5863b427c7851a3a6694757a0a1c9c0b9bb1794f06235dd751d9bdb3dcd898ee1329c6882d091953490baea6d75a57e8a8c3a438760cbefce4295c5af003c63fd47dce8cbb6ba5db37fb2a7fde9e8f5f007ae16ef43ff6a6f9a13ff83d8621b08b3f67e13ee276826a142af9dc19092f11c3ddfbe824f24af937c761b52e6fdba336271efa0b8ae06e1488a6793c15f0282b87c62f4ac787038affbef3e9819e71c5a75cb616a87c4c2c94fcb311270af83e04f913a90bc5d7427814066d6a6fdab7c57afc42dd3a47c91eefc6cead6b3c57ae2aca27a939af07fcf9b7615304c4fa0aed2d839f91ea2a10d50ca807657eec2499b5fd6dd6d9094cfccaea4a38faae51e3ef77d9d01c7a61d21526d5292757bc1fa438179afcaa1f46812737ab3d993cb4b9ffddff3fe024df47cb74465586593ee1754550c3dabda65730fa898c389e0594a2b1c6bb1aa902656c2e1d3196e4f116ea6c2ab4a882a529f1c58883f25d442baddf70d917bb8ca3df77690c04dd14a4d429e48d0b33743244b87b7a7e97fb7ee878fdb54c91451efb04705", "3c", "8a2885edc32e0cb7232c84019faabafcf882483a97630637233e749366bf4e8439f33035781551644e96d4bcca0ce05aaec2762b515008cb2a7a9d54162213b21f964f6c91ee77330bd2628c2983ffe95ac3075f84009a124f4305ffb767eb4f9fab35bc1cfde6ac0055989a672b8ec5863b427c7851a3a6694757a0a1c9c0b9bb1794f06235dd751d9bdb3dcd898ee1329c6882d091953490baea6d75a57e8a8c3a438760cbefce4295c5af003c63fd47dce8cbb6ba5db37fb2a7fde9e8f5f007ae16ef43ff6a6f9a13ff83d8621b08b3f67e13ee276826a142af9dc19092f11c3ddfbe824f24af937c761b52e6fdba336271efa0b8ae06e1488a6793c15f0282b87c62f4ac787038affbef3e9819e71c5a75cb616a87c4c2c94fcb311270af83e04f913a90bc5d7427814066d6a6fdab7c57afc42dd3a47c91eefc6cead6b3c57ae2aca27a939af07fcf9b7615304c4fa0aed2d839f91ea2a10d50ca807657eec2499b5fd6dd6d9094cfccaea4a38faae51e3ef77d9d01c7a61d21526d5292757bc1fa438179afcaa1f46812737ab3d993cb4b9ffddff3fe024df47cb74465586593ee1754550c3dabda65730fa898c389e0594a2b1c6bb1aa902656c2e1d3196e4f116ea6c2ab4a882a529f1c58883f25d442baddf70d917bb8ca3df77690c04dd14a4d429e48d0b33743244b87b7a7e97fb7ee878fdb5", .None}, + {.Shr, "294cdc9bde2025c88fdd0b283fca31f5ce36d9dd4b5f47e987f6a60a04a524a85e6d7c32bda8831bd993b5db92f38d9439d7dfdc80c4ceabf339b7f45e130f69bcf7607901f476370cccbf77807517f17ed2346e92aabdb89bc27320a440912240788338b7f475d3af629ed488cc056857f16375a0a21c1abbc9f2c7bb2a64c7e30660dc1df357b538bb4207d0697c733ee3c526bcf65b2b5de6bbeed007f9b685cc68df91d3e43c410f1e98a0f681f2fb287a229429bc8a956840ececf8af4b979519358c768fc9f802e5bb69f8b4566fee708d4df7010a1d20220849320abc0eec0c593be8dc219b66695ea1060b1b9a777cee74d04efeee505a1b1e1ad8ccb3e3a5fc93e1d533402362aedf1374514173946a6fce9aaaa1ed53a3d4f7ef40001c57bcaa4f15429c7cbce798d6e149ef0452b12f15b67e6f68b75354418367b44bf09d32c072e3c25a7d1830d37686c764042fb835be924685f44b228e9c890259e42fc58e6eaf3fdc11e37afe3855618bbef68bfcf4ac94acf8a4db58f4437ae8930b3f010019b3b992a297dce0323afcf95acc4864e1613da285d5b36b7116de0eed2d690691e317272b4d15bbe328bc3c5312bd6f3e61a09a3952790e5d552b2e9bcf10666eba78e9ddb5541c77756d5e6658853a24037f6a4f11877b25b71b3077f2f3726d3df09cb60c77669a34c84431753b5bcd1ae9057b4d1117e6", "0", "294cdc9bde2025c88fdd0b283fca31f5ce36d9dd4b5f47e987f6a60a04a524a85e6d7c32bda8831bd993b5db92f38d9439d7dfdc80c4ceabf339b7f45e130f69bcf7607901f476370cccbf77807517f17ed2346e92aabdb89bc27320a440912240788338b7f475d3af629ed488cc056857f16375a0a21c1abbc9f2c7bb2a64c7e30660dc1df357b538bb4207d0697c733ee3c526bcf65b2b5de6bbeed007f9b685cc68df91d3e43c410f1e98a0f681f2fb287a229429bc8a956840ececf8af4b979519358c768fc9f802e5bb69f8b4566fee708d4df7010a1d20220849320abc0eec0c593be8dc219b66695ea1060b1b9a777cee74d04efeee505a1b1e1ad8ccb3e3a5fc93e1d533402362aedf1374514173946a6fce9aaaa1ed53a3d4f7ef40001c57bcaa4f15429c7cbce798d6e149ef0452b12f15b67e6f68b75354418367b44bf09d32c072e3c25a7d1830d37686c764042fb835be924685f44b228e9c890259e42fc58e6eaf3fdc11e37afe3855618bbef68bfcf4ac94acf8a4db58f4437ae8930b3f010019b3b992a297dce0323afcf95acc4864e1613da285d5b36b7116de0eed2d690691e317272b4d15bbe328bc3c5312bd6f3e61a09a3952790e5d552b2e9bcf10666eba78e9ddb5541c77756d5e6658853a24037f6a4f11877b25b71b3077f2f3726d3df09cb60c77669a34c84431753b5bcd1ae9057b4d1117e6", .None}, + {.Shr, "358165f7567c85aee4955a2dc77e321e7877f39aa69f08a5e9bab5ffc6f65006c0e2972b6f9f8c7bd36431bf5de6e13298c5ec34cacde845f6f29fd9949654d05ee56b7dea31d4eebe77c1723cfd64216eff530fb3be55acd4600d848b91875e187381d013d0ec503c6d68aa717e1d63561a5c4295e45323224de2f46238110c6bc1ca436a5eb72ec8145979b701509fa7cda2deca5c22c18d16e62ef6770a1ee3ccc686a0f716007391f7b2185ae56666c6cf542a38e7edca2a6c15d105822180945556c76b44883e3931b5bc1e231a8df6960bd1d8420486e91bde69b808826629921890309ffc6b447225584b766ddfe096f11e253f0a6497264e08e0417b1f1eb95d312887312ed6b45ca3f8b38277c93660cbf66cee5dac7b64886be7d5232ee68e2f968a0712d2e550702f7a965987f8142e8cf254167e83aae0c790fe71cf1d44e8b7dba81edd947258d591aeaa9a8bc6240caa7cb2df6f2d5296f02bb04a0c79c5ff77178aca8c0d328790fd55856d94267c0faa2f274f11be205cad4e381659adc75788a184b6bfc7ca0916e9f217b2b7127f6ad78b1871a07aab56f4f9b1831cc08675885ff57e9975f4e17935daa101c52b308ff580ec58c791cc8138868585533a2b4bed885115773eba9552e27d36b33aa6d837de6919ab6fee9133ee3404f07f5b0dec0d8b30b8f24a51d371f9da6b470c4be9ebb49fe3136c", "b4", "358165f7567c85aee4955a2dc77e321e7877f39aa69f08a5e9bab5ffc6f65006c0e2972b6f9f8c7bd36431bf5de6e13298c5ec34cacde845f6f29fd9949654d05ee56b7dea31d4eebe77c1723cfd64216eff530fb3be55acd4600d848b91875e187381d013d0ec503c6d68aa717e1d63561a5c4295e45323224de2f46238110c6bc1ca436a5eb72ec8145979b701509fa7cda2deca5c22c18d16e62ef6770a1ee3ccc686a0f716007391f7b2185ae56666c6cf542a38e7edca2a6c15d105822180945556c76b44883e3931b5bc1e231a8df6960bd1d8420486e91bde69b808826629921890309ffc6b447225584b766ddfe096f11e253f0a6497264e08e0417b1f1eb95d312887312ed6b45ca3f8b38277c93660cbf66cee5dac7b64886be7d5232ee68e2f968a0712d2e550702f7a965987f8142e8cf254167e83aae0c790fe71cf1d44e8b7dba81edd947258d591aeaa9a8bc6240caa7cb2df6f2d5296f02bb04a0c79c5ff77178aca8c0d328790fd55856d94267c0faa2f274f11be205cad4e381659adc75788a184b6bfc7ca0916e9f217b2b7127f6ad78b1871a07aab56f4f9b1831cc08675885ff57e9975f4e17935daa101c52b308ff580ec58c791cc8138868585533a2b4bed885115773eba9552e27d36b33aa6d837de6919ab6fee9133ee3404f07f5b0de", .None}, + {.Shr, "bd6456e0ec3a8d9299d63fbbdfac1f50d74e06a809672ff00e290f35e674ae6f110a655c1609127cb96c52c4449f171da0844267e575c6cd2709865eaebbfe1a961e193409728db7cc6f27774851ba512836a334c0f48c7a2f8ca529a9aa0f14059dd30c5cdb09fe34d148cdcc2ffc14e6a4114ec1a344c48890b88f12a6c619586b46555c901e44b6d59256fe35d2b76d746a16fd97326cff90ac3859bcc6fd24dbdbc587a3a3b09f9712835a791de7718058f547b2c5d6e64fb66404afb3aa8cc10ae12bb322c0a1d27afa7c0b0171e6f3a1f9001f72a44c9dfcf7e1e123802de2cbdab65ec46a4e5e69e5db27bc0489b7a156be3924fda4995542c8cf0d0cefbfbc90e3967cea01c5676f3c19b705ec321f0e990f2aa6562842fe71b338adf1fe697813bedae91e55638a20062f6d18aa5522c20be9656f2df56b21d06447b3b5b80a2188980a9fedf8c920870e3ae9f06c1cf540484fa029cb91cf736e404eeb2e1c10736026875ab10040d0ebb476e7899f19822ffc8b5830e6ad803205afeaffbb0be211bab9710fb8fd0e54316f3e10ea137a9b6e3d8a5ec55efd93bb91740585abfa97372f96baf6a995122acc1755bd5f5418516a6e86d66434a14d83d2ae86ba19b14b4189293e5847efe49a18f0fb5f035d45b52bf095069e5bdfed4f2b465123fea084542e1ce906afe0a7b3f7d93de4c1f1a6d4e3ed472c89e8", "12c", "bd6456e0ec3a8d9299d63fbbdfac1f50d74e06a809672ff00e290f35e674ae6f110a655c1609127cb96c52c4449f171da0844267e575c6cd2709865eaebbfe1a961e193409728db7cc6f27774851ba512836a334c0f48c7a2f8ca529a9aa0f14059dd30c5cdb09fe34d148cdcc2ffc14e6a4114ec1a344c48890b88f12a6c619586b46555c901e44b6d59256fe35d2b76d746a16fd97326cff90ac3859bcc6fd24dbdbc587a3a3b09f9712835a791de7718058f547b2c5d6e64fb66404afb3aa8cc10ae12bb322c0a1d27afa7c0b0171e6f3a1f9001f72a44c9dfcf7e1e123802de2cbdab65ec46a4e5e69e5db27bc0489b7a156be3924fda4995542c8cf0d0cefbfbc90e3967cea01c5676f3c19b705ec321f0e990f2aa6562842fe71b338adf1fe697813bedae91e55638a20062f6d18aa5522c20be9656f2df56b21d06447b3b5b80a2188980a9fedf8c920870e3ae9f06c1cf540484fa029cb91cf736e404eeb2e1c10736026875ab10040d0ebb476e7899f19822ffc8b5830e6ad803205afeaffbb0be211bab9710fb8fd0e54316f3e10ea137a9b6e3d8a5ec55efd93bb91740585abfa97372f96baf6a995122acc1755bd5f5418516a6e86d66434a14d83d2ae86ba19b14b4189293e5847efe49a18f0fb5f035d45b52bf", .None}, + {.Shr, "a9b900ddf405aebfc80ab179c2b073d458637a7b83efed2121f62c52e90f23c871f6b9e3ef3fa16bb1c338e29f465908edb3be4afd83baff8c6c6b76a03c4cc61b7ff6aa61d751c673aef3fc4c0c754fe7213b13b8b65def35b2c7c5ca5d156f446b1670bd06163ec4a50e71da70da14a8b787c083a60e2414b837df310ea795be0b0a219a5738e087b1fcf2bc757455644899799393656fbf5db2d0f9b414b0f17139ffb40b783c4c7756954c5ba314b8c244027615ec3364ac46d4d4cf717f9208ad4bdc55473afc6b31cec8d1e3bafd4fd51001b17749aa79a764b883a1cbfea63ca08347f006c30e95b4bfe39da75efbc28cc5ac3f6f2763a250ac206b84c3532ada86d2bd8f638b430f5a931c2933a8a04e674a3db4b8882a71a474c983d5489f43511321d101e4f3186ccb48bf8c633960710fd6f2d08198d3c5b0e755b3f9534e04dbad9401720b232d30f69be15a2b14299aa74d6125fc7a1183f56047d10e2e7cf32a53384915f3c16ef8863cca771af65dc3fccc39a92ef6c74a2e439255f80e276ced3abde3fb2bde098585b8003ee21b1da714df3b7d0c5bb754b95b2b98790f520013a3aea32de92b53cc4dd83f802653f4f05888458c44426510d074032c7df5381a36f596228b96a37673a6ad94e9271cceedadfce622c5005de419b49f68c856b32864d80c5fbd39756a5f2e7ba3226aaa5e4db808d00ca5", "3c", "a9b900ddf405aebfc80ab179c2b073d458637a7b83efed2121f62c52e90f23c871f6b9e3ef3fa16bb1c338e29f465908edb3be4afd83baff8c6c6b76a03c4cc61b7ff6aa61d751c673aef3fc4c0c754fe7213b13b8b65def35b2c7c5ca5d156f446b1670bd06163ec4a50e71da70da14a8b787c083a60e2414b837df310ea795be0b0a219a5738e087b1fcf2bc757455644899799393656fbf5db2d0f9b414b0f17139ffb40b783c4c7756954c5ba314b8c244027615ec3364ac46d4d4cf717f9208ad4bdc55473afc6b31cec8d1e3bafd4fd51001b17749aa79a764b883a1cbfea63ca08347f006c30e95b4bfe39da75efbc28cc5ac3f6f2763a250ac206b84c3532ada86d2bd8f638b430f5a931c2933a8a04e674a3db4b8882a71a474c983d5489f43511321d101e4f3186ccb48bf8c633960710fd6f2d08198d3c5b0e755b3f9534e04dbad9401720b232d30f69be15a2b14299aa74d6125fc7a1183f56047d10e2e7cf32a53384915f3c16ef8863cca771af65dc3fccc39a92ef6c74a2e439255f80e276ced3abde3fb2bde098585b8003ee21b1da714df3b7d0c5bb754b95b2b98790f520013a3aea32de92b53cc4dd83f802653f4f05888458c44426510d074032c7df5381a36f596228b96a37673a6ad94e9271cceedadfce622c5005de419b49f68c856b32864d80c5fbd39756a5f2e7ba3226aa", .None}, + {.Shr, "938101389ed6951ad5f3e4c96a4b0fefcd7371a0a130ff5c71953f4ea5fbc3dc1c5d09b0bab6169a05961de4a94fb60669c72b19ffbbefdadb018a2504cfa4c67a5c64168d380a44f87dfdcaab2408adbc7f988c929fae91391bb19383a7f5f72e0871d0d0cc0b415d9b45914559aa6094ca95f6b084a385c7d2c9336f8d7ed5b786a8b218964b8e4a0fc3396d7cb2bcd512abf3e22896a96b1c3473dd0eab145ab1b2f6626d1dcf61d8a4b45d3baf9f1e640c99fa8050f19f919fda6e8ad226b0ed9d524ca67876efb210ba2b6c1def60dd8d547c91dd9981e43b87be5df975dad4966c71b855538367fcd7a7a87d8c00f40aefcd63fe1169d4a941a7a24514098e7c201822e06681d6adda4f4d05256586495a93180d244d4d274bc4e1d6613dc001a250ecbfd30834a4f22019a3e4765f99107d54456aaa7215479c2d6e857476cbb12eb02b3cd563daa6d42419f73dc82ca9ec572abd7768d32d24d6420d610c5c2c0ab98770fa8a9be278cc66a4b98338d24dc34b6d6b6f441dc470fb0d9bebfdafa536dff72527a6244c0903767658e49fa4f56eea9fe85944c60dfe316320aee158cad6787bb66c281079cae46b3b9022f993cad332cb86023ec5ebc52de1acd2ce44cdc2dafb14423a30ef8a99dfc432f350df62f4dbb86caae7c872aa5cfb38a347f6a62ebb0e4863719773428d2a022ad568af2377a9485d75e56e", "0", "938101389ed6951ad5f3e4c96a4b0fefcd7371a0a130ff5c71953f4ea5fbc3dc1c5d09b0bab6169a05961de4a94fb60669c72b19ffbbefdadb018a2504cfa4c67a5c64168d380a44f87dfdcaab2408adbc7f988c929fae91391bb19383a7f5f72e0871d0d0cc0b415d9b45914559aa6094ca95f6b084a385c7d2c9336f8d7ed5b786a8b218964b8e4a0fc3396d7cb2bcd512abf3e22896a96b1c3473dd0eab145ab1b2f6626d1dcf61d8a4b45d3baf9f1e640c99fa8050f19f919fda6e8ad226b0ed9d524ca67876efb210ba2b6c1def60dd8d547c91dd9981e43b87be5df975dad4966c71b855538367fcd7a7a87d8c00f40aefcd63fe1169d4a941a7a24514098e7c201822e06681d6adda4f4d05256586495a93180d244d4d274bc4e1d6613dc001a250ecbfd30834a4f22019a3e4765f99107d54456aaa7215479c2d6e857476cbb12eb02b3cd563daa6d42419f73dc82ca9ec572abd7768d32d24d6420d610c5c2c0ab98770fa8a9be278cc66a4b98338d24dc34b6d6b6f441dc470fb0d9bebfdafa536dff72527a6244c0903767658e49fa4f56eea9fe85944c60dfe316320aee158cad6787bb66c281079cae46b3b9022f993cad332cb86023ec5ebc52de1acd2ce44cdc2dafb14423a30ef8a99dfc432f350df62f4dbb86caae7c872aa5cfb38a347f6a62ebb0e4863719773428d2a022ad568af2377a9485d75e56e", .None}, + {.Shr, "9e3d5bea738241d3feb213de1718f773ef5e82c5c112bdbdcefa007b19463074065243125a10dc30f932a601ae2d2692430495261ab2b85fe902416d8266f15af89e08c61e09b0ef908e2baf84648ef38779a59360549710dee189ae1fa87893340e5d8c4749169180532ab947d419460c727c11d93f5606ef674dbbc96b6d5c7727c228be6619e5c151748dda390b44ec2381906c2b7ceb4a392c5831e7b66ebeb656ee3f83b8a80c2e89511f59eae302d8dc03786191da70b93aca355d06483a72b44a35a96ba84c81675ff5f20a7bc23f716377183caf360ed12b69902cf5def31181dc6d7450902805d8b0930600ccf11376f5f479c72cbb2321a5b15f2d44bda6522322f205735d7aef7340521b551b180965805112d7f8b57278e0e421f1736930b09e98608fe358f647776283961efc51e5329d30710db004ee5ede320e7204462f58abd0d007aa2976e10243b6cf86032b61641cc1ab47eaa5dca7399997a530b71e14d8bdf84d0f671a181bd8db347ebb0c852fa887cdcfea37cbd25e1a04ff4bb15b86594ff13f7b86b43dadf8e9388dc7b2c07cc39f83f89721d869ec2d7a2670e1e719a15d4678e6f5c6bd86608b34db01425c756712b20ad902079f31c4d27011a42159212742a9cb74376cb70f5c47a27057f450bf8e0b04aca5db113f09b58edfb21d493f5b114a0a32f28d1f8dea2cb74c333bf01e4bc0f2", "21c", "9e3d5bea738241d3feb213de1718f773ef5e82c5c112bdbdcefa007b19463074065243125a10dc30f932a601ae2d2692430495261ab2b85fe902416d8266f15af89e08c61e09b0ef908e2baf84648ef38779a59360549710dee189ae1fa87893340e5d8c4749169180532ab947d419460c727c11d93f5606ef674dbbc96b6d5c7727c228be6619e5c151748dda390b44ec2381906c2b7ceb4a392c5831e7b66ebeb656ee3f83b8a80c2e89511f59eae302d8dc03786191da70b93aca355d06483a72b44a35a96ba84c81675ff5f20a7bc23f716377183caf360ed12b69902cf5def31181dc6d7450902805d8b0930600ccf11376f5f479c72cbb2321a5b15f2d44bda6522322f205735d7aef7340521b551b180965805112d7f8b57278e0e421f1736930b09e98608fe358f647776283961efc51e5329d30710db004ee5ede320e7204462f58abd0d007aa2976e10243b6cf86032b61641cc1ab47eaa5dca7399997a530b71e14d8bdf84d0f671a181bd8db347ebb0c852fa887cdcfea37cbd25e1a04ff4bb15b86594ff13f7b86b43dadf8e9388dc7b2c07cc39f83f89721d869ec2d7a2670e1e719a15d4678e6f5c6bd86608b34db01425c756712b", .None}, + {.Shr, "77509a45f5c05558a695d8a947e5d9a5caab99095cf59657b633d48c2a164ccccb9fa2da5692c7d42a1d446bdc79c250ba4e47caaba48300770d23758ba641fa9ea0f52fec58a643ed0f9c610145af9cd684a6b286d6eec81a4dd922c408fe138eb4283d4d5f511a66ae78dfd9339de8abf133e48e414646ac6b3feb75bca1c97c4d3c147b2913d94f947f9647216fe9e6b0c0de0a479ea0a55c71d69ada053872f7dbee63ffc4ed19084e772174ad1d0b229dd5d3386c3846d812659d267765c4329adb29d1b23260380a57ff758bf725e184ab0fc8f0b85c922d5bf9c277b1c140851ed3546dbb1baef9c5e736e7d6be7fb7aeee1b7a509f07358e1b691432418113187cf8898e13f3ab9d0471ef38f828052d0af62b1cfaf7734cbc9193005026d984d257d925a1732c47660586502db296ea409cc39a9778f39778bdf63c37ae40fb09fea55da5ab38cb1ba117d58136596e99d6495b75630928a701fb9010073b39756c56427a791367c17b28b06fe2b4114b0fc7a504d7aa4af944dbdf48e08eb4307b028e420c0c50d90307697afb126a3a54e2e1a10b39609e86c116511503020a1a1a1bf9668d6ad1bef328729d29abf98a07799a1dc12680a9f1c5f904a7241a5a38f8e7846e9c57d65713f61ad6058ffaad335ce56060833ba5cee83f60b39d0654ac6f817cba4115a9178ed4d5dd866fd9875615e7083ed6a0be", "f0", "77509a45f5c05558a695d8a947e5d9a5caab99095cf59657b633d48c2a164ccccb9fa2da5692c7d42a1d446bdc79c250ba4e47caaba48300770d23758ba641fa9ea0f52fec58a643ed0f9c610145af9cd684a6b286d6eec81a4dd922c408fe138eb4283d4d5f511a66ae78dfd9339de8abf133e48e414646ac6b3feb75bca1c97c4d3c147b2913d94f947f9647216fe9e6b0c0de0a479ea0a55c71d69ada053872f7dbee63ffc4ed19084e772174ad1d0b229dd5d3386c3846d812659d267765c4329adb29d1b23260380a57ff758bf725e184ab0fc8f0b85c922d5bf9c277b1c140851ed3546dbb1baef9c5e736e7d6be7fb7aeee1b7a509f07358e1b691432418113187cf8898e13f3ab9d0471ef38f828052d0af62b1cfaf7734cbc9193005026d984d257d925a1732c47660586502db296ea409cc39a9778f39778bdf63c37ae40fb09fea55da5ab38cb1ba117d58136596e99d6495b75630928a701fb9010073b39756c56427a791367c17b28b06fe2b4114b0fc7a504d7aa4af944dbdf48e08eb4307b028e420c0c50d90307697afb126a3a54e2e1a10b39609e86c116511503020a1a1a1bf9668d6ad1bef328729d29abf98a07799a1dc12680a9f1c5f904a7241a5a38f8e7846e9c57d65713f61ad6058ffaad335ce56060833ba5cee83f", .None}, + {.Shr, "17ba8819b7621c7db68eacf1ca3d15c0938e49373b880391b096072c4c90370a28b4bf4b197883aa594ad647b3b121fb810c4302defedf0796019663e7dd7e31c3b541914ad6ac3f9c284bb806ca2e7d9355c740b94525d2e5185fee888df5aa9d9c79f2fb4ac68b2113e0535254b83cd556e18c13449e5c7675ae973467def258468ab5bcfbb951c1cf5437a5f777720b627a31f9a695e1a68ca6534d3f76af09ea56a48a1a60c5004ef8f9667a0e8de036dec605b549377cca059ad3ca2e9098b0639e331f2390bf553f7160898703f92a46eece76f0c24d55f42844d7ffa4b0d8edb791f326f7c4dcf15e3a0fca6d99030c44007f363b250237d81969535a4a42969adf07dc7d2fe252a3f28216d8267f5f76558f86993a1fea7a01dc700035b534b80ec280ab861a9845e765a7984bdad78f507832bd381104efe3d0a21f2db38230f48c4cf3494738a2b998fa1b08118a8feae5c8432cc4ac4cb01c249b3beb45df0820bac9fde39b47b1216034f40be02de94b8ee12f10254c1c5962d7ac232c75ab9b335d4787fdd749dca6520c43a3fe4f146bd9336d9654edea773dc510fc80ee31eb73abac8bdd75ca4fce3614c492b45072a2cb20cd32e07d9324f63cac2fa3d4dc98fae485088aefafad064906d24ffc0a6c71ebbe193d711d4748030e03d1d01cded3665de388fd8f21948bd84749bc243fd2c089e9ba56be29", "12c", "17ba8819b7621c7db68eacf1ca3d15c0938e49373b880391b096072c4c90370a28b4bf4b197883aa594ad647b3b121fb810c4302defedf0796019663e7dd7e31c3b541914ad6ac3f9c284bb806ca2e7d9355c740b94525d2e5185fee888df5aa9d9c79f2fb4ac68b2113e0535254b83cd556e18c13449e5c7675ae973467def258468ab5bcfbb951c1cf5437a5f777720b627a31f9a695e1a68ca6534d3f76af09ea56a48a1a60c5004ef8f9667a0e8de036dec605b549377cca059ad3ca2e9098b0639e331f2390bf553f7160898703f92a46eece76f0c24d55f42844d7ffa4b0d8edb791f326f7c4dcf15e3a0fca6d99030c44007f363b250237d81969535a4a42969adf07dc7d2fe252a3f28216d8267f5f76558f86993a1fea7a01dc700035b534b80ec280ab861a9845e765a7984bdad78f507832bd381104efe3d0a21f2db38230f48c4cf3494738a2b998fa1b08118a8feae5c8432cc4ac4cb01c249b3beb45df0820bac9fde39b47b1216034f40be02de94b8ee12f10254c1c5962d7ac232c75ab9b335d4787fdd749dca6520c43a3fe4f146bd9336d9654edea773dc510fc80ee31eb73abac8bdd75ca4fce3614c492b45072a2cb20cd32e07d9324f63cac2fa3d4dc98fae485088aefafad064906d24ffc0a6c71ebb", .None}, + {.Shr, "3826dca0702db81be70d0f453f5b28960d646b559762f12878cf4a89da5d590975f73075c608a2d569cd31d862ed55c94d9c4c4f49301cd32c0789a269c510443ea042f0c6184f14b8491428f1bdb122483e0bc19b42dc372ed6f4eb2f2854e464726bc7da280e2d5d8b4ce20cd8a06abfd5c22aa9605fa31d39034d3644164980271911bf35b6c53a6612f657b25a54fc7079f458f103fbb57b3b970fd9729cab973b1b970095b520669285500fc092941159307b21b27854f125ac10a6774abdcbb4fb72d02e0e0a6d7534b07e3bb279e88e18ea87b4d838fe51f547406012547b6ed4ffc7b59e3f21eee228701e6c635dda8c2232ed5283a186af65837e8d01d289a4874270b5b51053e3467c212a7dd98f18b92c17521ef45bbe43e4e1d8b907004b49b9357ad3814a18ae47e3726db170ca667c52745dc9c7b4fa72ffe14c8f9765f0d2911199e5c53bd83cf96d63332ea9cd72f9369e5d4270ddaa6b3b089c3e74a0ef68f5e363a71a72edf91614e1517ae4ffae91797defc0862ce8fd3c25c08a69c05a5a044b9a77b247df3fbf926bb2f01b9841df757bc19ae166b25c000370b038d9f731a0243301122b12ac0a523f0528a194af73f0337cd7c275191e44aac9cdbe57bf8a3e60b0303588f973563406372e2b784e83bf1b185c23bc47400edf78094c1d06be81f5f43b8531e2c07332c592a71eaad4f72d904a66", "f0", "3826dca0702db81be70d0f453f5b28960d646b559762f12878cf4a89da5d590975f73075c608a2d569cd31d862ed55c94d9c4c4f49301cd32c0789a269c510443ea042f0c6184f14b8491428f1bdb122483e0bc19b42dc372ed6f4eb2f2854e464726bc7da280e2d5d8b4ce20cd8a06abfd5c22aa9605fa31d39034d3644164980271911bf35b6c53a6612f657b25a54fc7079f458f103fbb57b3b970fd9729cab973b1b970095b520669285500fc092941159307b21b27854f125ac10a6774abdcbb4fb72d02e0e0a6d7534b07e3bb279e88e18ea87b4d838fe51f547406012547b6ed4ffc7b59e3f21eee228701e6c635dda8c2232ed5283a186af65837e8d01d289a4874270b5b51053e3467c212a7dd98f18b92c17521ef45bbe43e4e1d8b907004b49b9357ad3814a18ae47e3726db170ca667c52745dc9c7b4fa72ffe14c8f9765f0d2911199e5c53bd83cf96d63332ea9cd72f9369e5d4270ddaa6b3b089c3e74a0ef68f5e363a71a72edf91614e1517ae4ffae91797defc0862ce8fd3c25c08a69c05a5a044b9a77b247df3fbf926bb2f01b9841df757bc19ae166b25c000370b038d9f731a0243301122b12ac0a523f0528a194af73f0337cd7c275191e44aac9cdbe57bf8a3e60b0303588f973563406372e2b784e83bf1b185c23bc47", .None}, + {.Shr, "bca4298830db9bd355c61b1fdc0cf0c1aaad36b8b19df8b34c84b84b21be6953715f958f744621a81d262ef9d0ba57f721c7e650692c2fad466520097de50bd094f5bb7727bdd02a8f5266b47052a9011e3aa385b29e48591a35368e3804677bea9e830eb8bf9dbb5cafae5141561bcc63411eb18cc4d7281802e4379e5fb09680f8b8a24121452aca5b804fe1c411ddb6e4afa69f088c258ceb658392f3d551a1ae4243c6ec2a93059709d3cfd458494f4f59a8dca9f1f0056b00554b8f8e1b6475425c3530e38afd486089609b82fcd5adffd27571f17e860758b693fb83e4abb4bb2bbef0b51b0c75650b980128f72926f8cbfb9db3f3c185e2edb90a5c284a1a7bcdc7ce30bb6e9b61f6b70c63128237c5deb2cc7bb41acd3566f5b1cfa93f8672427a5b5b6c82e9e17ab7cc533108fcf47eb085e55ab79a4b00d08e5c224e30dd96f01a83bcb8c13d7f22704c9c92308f0965110e1caa85d3ae8dd5824487ea5fc82db69aba17c25a2999b95aafccab6284b7e378273672892c6df9335306508400dab6326322bb7c929ee01b8cb6b1a97da74095fc55bd985b1e59a0bf149f76f6b105464ab35e9765b05edf357b6b183b848a54711b57b541dbf7ab5d89e5cbeca40b13b686ab0b496e86eb3fb38acc26571afae2f81841f8e22e561adaa4d2f8c3e0c4c7db64b2f5ce63d981a3be9b6823901d22b21d66707cc48616", "1e0", "bca4298830db9bd355c61b1fdc0cf0c1aaad36b8b19df8b34c84b84b21be6953715f958f744621a81d262ef9d0ba57f721c7e650692c2fad466520097de50bd094f5bb7727bdd02a8f5266b47052a9011e3aa385b29e48591a35368e3804677bea9e830eb8bf9dbb5cafae5141561bcc63411eb18cc4d7281802e4379e5fb09680f8b8a24121452aca5b804fe1c411ddb6e4afa69f088c258ceb658392f3d551a1ae4243c6ec2a93059709d3cfd458494f4f59a8dca9f1f0056b00554b8f8e1b6475425c3530e38afd486089609b82fcd5adffd27571f17e860758b693fb83e4abb4bb2bbef0b51b0c75650b980128f72926f8cbfb9db3f3c185e2edb90a5c284a1a7bcdc7ce30bb6e9b61f6b70c63128237c5deb2cc7bb41acd3566f5b1cfa93f8672427a5b5b6c82e9e17ab7cc533108fcf47eb085e55ab79a4b00d08e5c224e30dd96f01a83bcb8c13d7f22704c9c92308f0965110e1caa85d3ae8dd5824487ea5fc82db69aba17c25a2999b95aafccab6284b7e378273672892c6df9335306508400dab6326322bb7c929ee01b8cb6b1a97da74095fc55bd985b1e59a0bf149f76f6b105464ab35e9765b05edf357b6b183b848a54711b57b541dbf7ab5d89e5cbec", .None}, + {.Shr, "2e63dbef7dd73fb8051f0c5d97a3ff1485cc8b397dc40a3418e0a745c9a0efbaf67d082358e496457b5464567bdf5e0c73ac191e2d6f2854f655cc07ab9b2464674ab2d4becff54e2aa65eec5697eecb38611527875b71065770becb6d70326438583b216d8d3d0932521c5338fe358d43227eea4b67ce3251fc41d25752be775769c4787c2c2c6622c171a387afeb8ad075d9afba17e2470964a6c52837b053c43369ec675ec8a38654a5dc03062f7aa3f7daaf927c13f681e785dd94dbd3aa3ad94044bf2d5527a3a6fc0ee6abd5a85bb5ac046eef6c64b34e50e5abaaca96d39d542c3afe2e93119454da134cc3c7321d34758f2179697b618fbc3d1f974dda6ca356a328d68126381e75da22773055ac15340fdbc2d70210c47f6ea591f31fefb853f4e847501079bb3dd9c15ff4dfac8cc3c66782205ba21ddef413772dac427182608e2b23c435985b3e77771541fdcd02c2a8196cf22f3a995f27965db160858ee73be995e4d6ac7d3f9d2400fd161b9772393d14c15d107105a09c8794ca1f7ed77385107ee976029820c874a7e32f7d3a0834e4933e658a60944504726d7af8b22339eba7d428e431a19ce030c656fb59f33b9749514ab1eff604ae92d06ae7475c3454f64990235e4d0ce446a2054ca1357bc555cb2dfde95cc7053d64749e6ff989f37d973c32f75b707d521371c7d4fa3edd35e247586828e739", "78", "2e63dbef7dd73fb8051f0c5d97a3ff1485cc8b397dc40a3418e0a745c9a0efbaf67d082358e496457b5464567bdf5e0c73ac191e2d6f2854f655cc07ab9b2464674ab2d4becff54e2aa65eec5697eecb38611527875b71065770becb6d70326438583b216d8d3d0932521c5338fe358d43227eea4b67ce3251fc41d25752be775769c4787c2c2c6622c171a387afeb8ad075d9afba17e2470964a6c52837b053c43369ec675ec8a38654a5dc03062f7aa3f7daaf927c13f681e785dd94dbd3aa3ad94044bf2d5527a3a6fc0ee6abd5a85bb5ac046eef6c64b34e50e5abaaca96d39d542c3afe2e93119454da134cc3c7321d34758f2179697b618fbc3d1f974dda6ca356a328d68126381e75da22773055ac15340fdbc2d70210c47f6ea591f31fefb853f4e847501079bb3dd9c15ff4dfac8cc3c66782205ba21ddef413772dac427182608e2b23c435985b3e77771541fdcd02c2a8196cf22f3a995f27965db160858ee73be995e4d6ac7d3f9d2400fd161b9772393d14c15d107105a09c8794ca1f7ed77385107ee976029820c874a7e32f7d3a0834e4933e658a60944504726d7af8b22339eba7d428e431a19ce030c656fb59f33b9749514ab1eff604ae92d06ae7475c3454f64990235e4d0ce446a2054ca1357bc555cb2dfde95cc7053d64749e6ff989f37d973c32f75b707d52", .None}, + {.Shr, "df412aa295a1515ddd68de02fec595c2537dd5c5e49ea4da3ea41824627a95e64208d91128a508ffec1839da2599037944c4813a9d95e1b9e4644fde5cfa694bdb760fe8b7a89c7a21dd365992814d1a7c15208cdfb7a8825bcbdbfd8282a463c426e0ffb6de57d72254ec2d305786377da3ee60647a977bd45fc17b42eab211955ab38d97fe13ee991a617b37f768a20dc758d5ed37329db721c0094b0eb7b4ca39707ce9cf9b6db6ac22f51e71f3078efc25c306d602cbd9b70beb1643cb959ccfdad694aa2274206e7e8736de5fc8201e3dccd93cba0581c66688639c7502e8b4d6eeebe12199d3dd3152d37097f6103558462a8c40bea2aba8471211d7190701f3cad194ec21eaef98fb5626e70a8bf5fefd75743217946d57e05e96f4f2c69e1350f12b30ff01926dd9b0e2bffd36d86de2c98687e5ecfbe6ab26d064900fe2f05a9b0474b9c3dfd5ed05bc216c2dded49c424e82c2a848549a492d6ac366375e05ed30fe1dbdbfae0854e012055a4ab402009d034fb427fcb37b29e62fb20e0340fe4a071436962d9022c510e80ffef7e5481c1b46a7336b2891d3ea3fabcd35fa3fe39a3cb2a125306696aa70b326482653ae8eab54b30ed733ea2f0772257634bd7333d18361d4b3b91d96d1e6402d37b800e5356c42e1bdb52c986b8e1ec0d238ecb4f3679e6836685814f898b4a5d51ccb455a27ea51a2b3a4a6e4", "1a4", "df412aa295a1515ddd68de02fec595c2537dd5c5e49ea4da3ea41824627a95e64208d91128a508ffec1839da2599037944c4813a9d95e1b9e4644fde5cfa694bdb760fe8b7a89c7a21dd365992814d1a7c15208cdfb7a8825bcbdbfd8282a463c426e0ffb6de57d72254ec2d305786377da3ee60647a977bd45fc17b42eab211955ab38d97fe13ee991a617b37f768a20dc758d5ed37329db721c0094b0eb7b4ca39707ce9cf9b6db6ac22f51e71f3078efc25c306d602cbd9b70beb1643cb959ccfdad694aa2274206e7e8736de5fc8201e3dccd93cba0581c66688639c7502e8b4d6eeebe12199d3dd3152d37097f6103558462a8c40bea2aba8471211d7190701f3cad194ec21eaef98fb5626e70a8bf5fefd75743217946d57e05e96f4f2c69e1350f12b30ff01926dd9b0e2bffd36d86de2c98687e5ecfbe6ab26d064900fe2f05a9b0474b9c3dfd5ed05bc216c2dded49c424e82c2a848549a492d6ac366375e05ed30fe1dbdbfae0854e012055a4ab402009d034fb427fcb37b29e62fb20e0340fe4a071436962d9022c510e80ffef7e5481c1b46a7336b2891d3ea3fabcd35fa3fe39a3cb2a125306696aa70b326482653ae8eab54b30ed733ea2f0772257634bd7333d18361d4b", .None}, + {.Shr, "1b64e8d3ff39230439035403ba35b4fe47c094137816aacc55924956e81533524c7c6c12e78e2563ca22e4c6931d1a1cc11c5651245878e0be037043290477cfe73e5d1380ec17b858f691509acd4021b8ab03055f6cf3d9a6fcfd4911542c938717550cdddfb5b883562f4bb9e3d2f238811a6af3952a824596593b10baa40c4842f8bcdf69cb983eb0db756741da579186bac18cf84e84b8caa5f6a04d02aa8e4efe03ee5dc97f1c5dcbe041b66b0c543cb01280947a914a348148164c237abb0760af412e2a6e4c82e1e4989feb8d7cc9ca6323de612dff9b443682e9b96819d257d3944eeacc64edf0836b2a4d981348bacab5bb75eadaf0b59ead81942d3ae10c13b773fb3ec20005d9350de648a75f4a9396194fa2184b50019ee65c8032ac00e9b57a0836eea647444849c5418cb3352dbdcb176acccf3d2ed02397337371419cebcbf1f3ead969b520daa98ae966af6ba101d4537ec01db2466e65b2d71c17ebaa1f7e03f9ad6cf3255233eb0829bee74dc9d1bfaef7d5ed10b2d35519fb96e9edbac69fe33ef8973972fc54f19620b8c65c5e08e2ecd712f6155386bbc6d0862cec5e0e3b7837014eecc973819e0684dba9e60d14285f1640490db54e9214240dea58a635832797d4860c58be3e03c478b1ad79ab38189c892998bc38d1459a45103d73c272bc6eb65095def78dc838e445eb83f8ae6b3aff6181ee", "f0", "1b64e8d3ff39230439035403ba35b4fe47c094137816aacc55924956e81533524c7c6c12e78e2563ca22e4c6931d1a1cc11c5651245878e0be037043290477cfe73e5d1380ec17b858f691509acd4021b8ab03055f6cf3d9a6fcfd4911542c938717550cdddfb5b883562f4bb9e3d2f238811a6af3952a824596593b10baa40c4842f8bcdf69cb983eb0db756741da579186bac18cf84e84b8caa5f6a04d02aa8e4efe03ee5dc97f1c5dcbe041b66b0c543cb01280947a914a348148164c237abb0760af412e2a6e4c82e1e4989feb8d7cc9ca6323de612dff9b443682e9b96819d257d3944eeacc64edf0836b2a4d981348bacab5bb75eadaf0b59ead81942d3ae10c13b773fb3ec20005d9350de648a75f4a9396194fa2184b50019ee65c8032ac00e9b57a0836eea647444849c5418cb3352dbdcb176acccf3d2ed02397337371419cebcbf1f3ead969b520daa98ae966af6ba101d4537ec01db2466e65b2d71c17ebaa1f7e03f9ad6cf3255233eb0829bee74dc9d1bfaef7d5ed10b2d35519fb96e9edbac69fe33ef8973972fc54f19620b8c65c5e08e2ecd712f6155386bbc6d0862cec5e0e3b7837014eecc973819e0684dba9e60d14285f1640490db54e9214240dea58a635832797d4860c58be3e03c478b1ad79ab38189c892998bc38d1", .None}, + {.Shr, "ca0d662918d5a62ca3420fcfa817fa8dcc7d46594c369d39c10ce74d1de50803ac5314956cd43be1acc3a59a1eb4bf57f4f31a696db8cdd4d75dd7aa4154ae7237b0d60d1996dbdb8d38738b8febfc22f8161582e75590a10902525a9d6eb7390bf9297d6ee63cf37c37b37f2372a1442d17bab5820e40732a1b8c507f743b4fefb0ec38dda89d4210a7970f238f0fe3e17d23d7a2666b5e2a50f4bd2fc63b79c8aaa2517004ccc4bdbc6923a4eaed2f3e48c4391482826dd93365baf7537fef9839aaeb3a84052e73449bc116bb36fc290cb4b82a1820bbf49e17ac6fa32e6c7fdcf77e843902998ec1e849dcb14b01806d9b8e2d35fbc7a56888a8ab45044dc44416ebd0c6b03ad6fb48d4dcdfe95394c30d8daf35e5ba23f1830ac19df3e8d406ffe09f437f9510b76f0499cea85c2919e9e203935f556e2c58bb0055a62bfd22b1fc4264680dd4e2feea50560144c6cf0b417a24974a24d90c4f7affa96caf56dcfdbdd09fd57a01c0e58f23d503f3b782ad851cbc3ef2a1683ea4772d88c218b5f963561cef4d1492d325c1eb81e213bd285778faa5abbee9afe180730909984cfca7fea8ae201d643ff3e9c9a0ea9026b23f070141d4f6acaacab8b9683d1d08ea0561f52501a5293687ad9bd263c915d8271e1cf8e34d0ef1d626d20896c6c4d27e12cfcab67c70a18db2c33b3ecd7b5896dd85e9cbc78aee65b5000f", "b4", "ca0d662918d5a62ca3420fcfa817fa8dcc7d46594c369d39c10ce74d1de50803ac5314956cd43be1acc3a59a1eb4bf57f4f31a696db8cdd4d75dd7aa4154ae7237b0d60d1996dbdb8d38738b8febfc22f8161582e75590a10902525a9d6eb7390bf9297d6ee63cf37c37b37f2372a1442d17bab5820e40732a1b8c507f743b4fefb0ec38dda89d4210a7970f238f0fe3e17d23d7a2666b5e2a50f4bd2fc63b79c8aaa2517004ccc4bdbc6923a4eaed2f3e48c4391482826dd93365baf7537fef9839aaeb3a84052e73449bc116bb36fc290cb4b82a1820bbf49e17ac6fa32e6c7fdcf77e843902998ec1e849dcb14b01806d9b8e2d35fbc7a56888a8ab45044dc44416ebd0c6b03ad6fb48d4dcdfe95394c30d8daf35e5ba23f1830ac19df3e8d406ffe09f437f9510b76f0499cea85c2919e9e203935f556e2c58bb0055a62bfd22b1fc4264680dd4e2feea50560144c6cf0b417a24974a24d90c4f7affa96caf56dcfdbdd09fd57a01c0e58f23d503f3b782ad851cbc3ef2a1683ea4772d88c218b5f963561cef4d1492d325c1eb81e213bd285778faa5abbee9afe180730909984cfca7fea8ae201d643ff3e9c9a0ea9026b23f070141d4f6acaacab8b9683d1d08ea0561f52501a5293687ad9bd263c915d8271e1cf8e34d0ef1d626d20896c6c4d27e12cfcab67", .None}, + {.Shr, "3a66b6f254dad4c0c579b458658d0b1ed7826819db20dfbcc7df22371a262fecd9b04e83555fadc2c97b941ae0df043a627e7957d9cd732e0df1dd8e4e9c266627277bd342eb5618ebefb0eeb3643aa50e6a8805b24ff90884062a7ef364cb415de5b2bfdf669ec7f72a2f71cdaa499487c2e8d54395881fe1b39d862af6018c30c6ff45a892cfa0d07cbbce71bf8816874766fd8d0925726d073241ab833374cbbebb0f8971256ffe8556e79b9ec3f173d80c2a31a44de594001eede9a9dbd7cf5ba7dc97dfc269e8a7744f5d826314e9f7d23107da6cfcd1fe2d3879f3298766ec894b13df240d928ebe28601ab91508a6509321d041c68f93bb28b9fd2237114e3da6c678cb4129da3901b4bd79a241a082ccc536be0d1d10b5c057b997d47bf8786e01140aab6694d90fce3a26ec8efa87366c15da1407d0a00fea63eaab604fede713fe48e7647e4163e611b56e642c80554859295c221026e7d28c2f3b81c470f3886c527f2144318698988be580574c403cb108019e00fc913c792f3bd54b57b7312c2810f84ac859d5503d092d663a84bbbb762588c99a4576756aabd2da7496ad384ade6cd495be30c5be63c31bf6ee35e4b32c18f4ab2249dd95ef53b7deced32296487aab24b405cd8e9d202d343731dd8026232c7b7c822b319d203215bd37c771b82e5bc6fcf3d32e42d2e433459597276137864271ced075f2", "3c", "3a66b6f254dad4c0c579b458658d0b1ed7826819db20dfbcc7df22371a262fecd9b04e83555fadc2c97b941ae0df043a627e7957d9cd732e0df1dd8e4e9c266627277bd342eb5618ebefb0eeb3643aa50e6a8805b24ff90884062a7ef364cb415de5b2bfdf669ec7f72a2f71cdaa499487c2e8d54395881fe1b39d862af6018c30c6ff45a892cfa0d07cbbce71bf8816874766fd8d0925726d073241ab833374cbbebb0f8971256ffe8556e79b9ec3f173d80c2a31a44de594001eede9a9dbd7cf5ba7dc97dfc269e8a7744f5d826314e9f7d23107da6cfcd1fe2d3879f3298766ec894b13df240d928ebe28601ab91508a6509321d041c68f93bb28b9fd2237114e3da6c678cb4129da3901b4bd79a241a082ccc536be0d1d10b5c057b997d47bf8786e01140aab6694d90fce3a26ec8efa87366c15da1407d0a00fea63eaab604fede713fe48e7647e4163e611b56e642c80554859295c221026e7d28c2f3b81c470f3886c527f2144318698988be580574c403cb108019e00fc913c792f3bd54b57b7312c2810f84ac859d5503d092d663a84bbbb762588c99a4576756aabd2da7496ad384ade6cd495be30c5be63c31bf6ee35e4b32c18f4ab2249dd95ef53b7deced32296487aab24b405cd8e9d202d343731dd8026232c7b7c822b319d203215bd37c771b82e5bc6fcf3d32e42d2e43345959727613", .None}, + {.Shr, "2563d06ea5b5ca6c8c65ab73cc9a44ca22b89e3e9b0c6919f31d47af1ecf85e115d8b82586ce929ec3362bef4ff0a9580de80a770dc580b381e2a4dad5e6ba329d67985dde01ede7a5847006592b367b42a0882a0446503f9e6c7e825123884f958fe4a0294dd3046ee1fa45ee0a977ae01fc3b67b1509c29cbbebc40b90044007550a637883b7545b60c0e63a26d771734e25f3dbbb12a213dd00f837f5b94ee898ef7761abc432e1e825f53b0adc2cee8c1d09ec1d7499f8939ac5bd3ecad9cf72c0290fef264dd6a5f20b0c01f8060cfd4adb91fa663ecfef905ac3a8187a87d1d20e82ced4438307c1b5f428a6445c4544b7825bc386c706954abe07550ef4ced8bcde7fdf6be78f6b156591e7ea67bfff8dcdf2aa82852afb6f7e78acc7fa56d560a38db455775e1a398d0a3cfdf479a2f30b0ab3eeb6fd675b459a36e1ad0c13862689a0f60c79cbd8fab06340a20dfc9b1e157b11241fdc431273914c42b94707c71dac7bb547dfa04f395ac4659c11ac2df3c178b1d97d886ec6990df6b9c78d05e645a21854ec80779142d7491f7158474efa3d2e8a4b8439e73ee2c87fd2514616c80d9e34e186c63d811c81d8707759d62a01fa00ba655f64c8caca8b65c9ed3454b2e754dcb98461d72024aac18e3372a4a35ab8dced852e1756b5eafc39db42c40831ad60d0f3f7b4c71f72bdd6eee0176581d10be1a528f589", "12c", "2563d06ea5b5ca6c8c65ab73cc9a44ca22b89e3e9b0c6919f31d47af1ecf85e115d8b82586ce929ec3362bef4ff0a9580de80a770dc580b381e2a4dad5e6ba329d67985dde01ede7a5847006592b367b42a0882a0446503f9e6c7e825123884f958fe4a0294dd3046ee1fa45ee0a977ae01fc3b67b1509c29cbbebc40b90044007550a637883b7545b60c0e63a26d771734e25f3dbbb12a213dd00f837f5b94ee898ef7761abc432e1e825f53b0adc2cee8c1d09ec1d7499f8939ac5bd3ecad9cf72c0290fef264dd6a5f20b0c01f8060cfd4adb91fa663ecfef905ac3a8187a87d1d20e82ced4438307c1b5f428a6445c4544b7825bc386c706954abe07550ef4ced8bcde7fdf6be78f6b156591e7ea67bfff8dcdf2aa82852afb6f7e78acc7fa56d560a38db455775e1a398d0a3cfdf479a2f30b0ab3eeb6fd675b459a36e1ad0c13862689a0f60c79cbd8fab06340a20dfc9b1e157b11241fdc431273914c42b94707c71dac7bb547dfa04f395ac4659c11ac2df3c178b1d97d886ec6990df6b9c78d05e645a21854ec80779142d7491f7158474efa3d2e8a4b8439e73ee2c87fd2514616c80d9e34e186c63d811c81d8707759d62a01fa00ba655f64c8caca8b65c9ed3454b2e754dcb98461d72024aac18e3372a4a35ab8d", .None}, + {.Shr, "9181e3680ad6dbb0ee41b6db3a92a617bb4b7e44f63471ba885fe492cb48db573258cd20438c944dbc10190575f1e69332fd581a4c2e3351e8b9e5aebdc14d4e4ecfe18e07827096d34ea980f7e44f24181b688bc0c3f3bcb898fbaf22596a534103f85370a28f3aa29a2916cdc53f919a4e4f5d35d33ef7319d4bd929148773c7bfa8ddf797757c222ed4a1e90845d3cb115b7f27fda63abfacf9f803775e3e1c66385b2c1db6a7abe2d7df5754b17a9efa21a6be728d72446b799b4347daee2011c878a97d3632c247f1b63749ae0b90893a7172559455e752805897d101e08e0a7cc7e12a4fc7047db8e83e9624a6250593ced8d9740c50fde99e227cf82c02c0214f202106611943b6762ebc5d18d0a418d994611e0eac5d5605334afbd1d3a37b68b8c7d4eabed335e25edfb711614b47bb89453d919f2e4bba50aa5721cc59b40514e10ddfaecef3a7ef148de240d85fabe76fd54273b2b0e6bf395c8f8a954327b08db9f5dc81e36ab6935af5e8089bb85e69ff3dfe2f30e85ea161f26f7685ea2f5697cae50c10ac3d4f5c8894a9c17c0513d9574af33c8333a220c86863e4f843adc24c21f353d721c43dd27204ee1c6c387a6f49d5855775770971f563436b04321cd2faaa3457f5e561d831110ea1a4585f6f3056739b656110dd2fe3eb9c84e6c0eea79dfb790efdc85fef8e8f716a1d2853712e30a451ec3cc6", "258", "9181e3680ad6dbb0ee41b6db3a92a617bb4b7e44f63471ba885fe492cb48db573258cd20438c944dbc10190575f1e69332fd581a4c2e3351e8b9e5aebdc14d4e4ecfe18e07827096d34ea980f7e44f24181b688bc0c3f3bcb898fbaf22596a534103f85370a28f3aa29a2916cdc53f919a4e4f5d35d33ef7319d4bd929148773c7bfa8ddf797757c222ed4a1e90845d3cb115b7f27fda63abfacf9f803775e3e1c66385b2c1db6a7abe2d7df5754b17a9efa21a6be728d72446b799b4347daee2011c878a97d3632c247f1b63749ae0b90893a7172559455e752805897d101e08e0a7cc7e12a4fc7047db8e83e9624a6250593ced8d9740c50fde99e227cf82c02c0214f202106611943b6762ebc5d18d0a418d994611e0eac5d5605334afbd1d3a37b68b8c7d4eabed335e25edfb711614b47bb89453d919f2e4bba50aa5721cc59b40514e10ddfaecef3a7ef148de240d85fabe76fd54273b2b0e6bf395c8f8a954327b08db9f5dc81e36ab6935af5e8089bb85e69ff3dfe2f30e85ea161f26f7685ea2f5697cae50c10ac3d4f5c8894a9c17c0513d9574af33c8333a220c86863e4f843adc24c21f353d721c43dd27204ee1c6c", .None}, + {.Shr, "48d5e3fa81ff191eec295339047ca809faded5e415d35f04135dcfdef43d8a95d831992ae3e3e93af6cc21f7f577964d3bdb02b03e5970ee641e81528839d180dbf32a13b21712a5014c7f07a28cdc3325c2b2384c8a374b054db8e3a44f47e2987b5a310edea4731100724deac3954ffe359ac371a23d6e22ccc232c4d183ece1681a9c65f7d44b86349c0a580fbb295cf18c0f2910b3256e2d7edcac5c56af7f035948a4ba0a7eb2736356d30fdc76fd818a16d1eddc4e129a736683586c762c5785ba0bc0fee5c2a122d9c7260fc264d16e23c18fde6da4fc4ffc8ac6697b17da44839e7434dc79ea2e68095c83e47496e0c631542565caecb2e92bc1b1b6543046fb6729c9f6999da7d815c32626b9bbd8e46d83e05e82c0b612ef5eb01ae9b23f5ec2c874d639d8adada608aa8ac97c5aa25cbe618df0dfade5f6af978ae7bedb8b7b14f11766774c2e23446784ccefce73d4eb4049fa884de6d669db2e2415fcb911bae7bc4ba8945c8772d94ff2f16830027a9ec463069551a5b2a002e485b502a23fa11cbfdf47a02d56ad1f85a53df4a2026b989be157ceb4a638cb533156abe19a232e2b47f690e52ff86ad3086de44db10b71ca695e545a1c3c65a1d28a42c79f46f87f195348b254805b8456524013ceeecd7264e513210f086707891b426ea20c6a3834fb08155a77eeac2caa53e726f8d44f7fe1bd90e88872", "3c", "48d5e3fa81ff191eec295339047ca809faded5e415d35f04135dcfdef43d8a95d831992ae3e3e93af6cc21f7f577964d3bdb02b03e5970ee641e81528839d180dbf32a13b21712a5014c7f07a28cdc3325c2b2384c8a374b054db8e3a44f47e2987b5a310edea4731100724deac3954ffe359ac371a23d6e22ccc232c4d183ece1681a9c65f7d44b86349c0a580fbb295cf18c0f2910b3256e2d7edcac5c56af7f035948a4ba0a7eb2736356d30fdc76fd818a16d1eddc4e129a736683586c762c5785ba0bc0fee5c2a122d9c7260fc264d16e23c18fde6da4fc4ffc8ac6697b17da44839e7434dc79ea2e68095c83e47496e0c631542565caecb2e92bc1b1b6543046fb6729c9f6999da7d815c32626b9bbd8e46d83e05e82c0b612ef5eb01ae9b23f5ec2c874d639d8adada608aa8ac97c5aa25cbe618df0dfade5f6af978ae7bedb8b7b14f11766774c2e23446784ccefce73d4eb4049fa884de6d669db2e2415fcb911bae7bc4ba8945c8772d94ff2f16830027a9ec463069551a5b2a002e485b502a23fa11cbfdf47a02d56ad1f85a53df4a2026b989be157ceb4a638cb533156abe19a232e2b47f690e52ff86ad3086de44db10b71ca695e545a1c3c65a1d28a42c79f46f87f195348b254805b8456524013ceeecd7264e513210f086707891b426ea20c6a3834fb08155a77eeac2caa53e726f8d44", .None}, + {.Shr, "91d21422d28ffcc851d4058defda30bd0db176f16ec6ad40a928e3434e96350c6b8c72904092e440cd63c074d956c5c4981e4c7ee4b95e2e7cc352a6e565afda3a8cc5dd092ac9ac093b1f1856cdb75cb51437a0667ddd1404001925da474e0a1b026019f7ace2b14ea015ee7f67a139c6454979d514c58848a0acf7ad45727dd56fe607542adc919ab52c5ac89c51b1fa4b693944e2ce8534d6a09d15003e869df063ee49fb5a9ff4826785bcdd9d5f59d3f4c8c1a36c6919bddae5d51245ae91c6c41ec5036c602d58e361088988527123d401126fca06b59464bec01f2927dba4fb24719131b51142b1fe53613d909e065ef7c69979b7b5a35fc0d1be1f7048fc7daa74306c6dd6bfb383d62f7485cc358e053004190a7a8933299ae275b189fa297a66201f16e36880820f4df282e2f50df96296c1b0a35cc2cd0cf3ffa3fa641f1232be6f07d4559a6971cae28abb6fc5017a05e478525f5684e4e63c0df640b705e482450e6e0ed6de7d84053760fb4b70dbe71f2d0a34dcdd145f1fdf1a65e04d05d6d6a8f086c24290c6c2e759b0cf7163d46bebd4c6170e3e884766914d22426cc8c89adb1e27eef5e3f9fb63db314379767908f91467f56dcd6c2f87bdcae9935f9c7ff5f5f5f97ddb4bbac67b6b2374ae5d6407fdbfcfd7d30674cea4b6e699e62c4645f670eac81e7f3ba68c086624a27377aba3a302ff7e37db", "21c", "91d21422d28ffcc851d4058defda30bd0db176f16ec6ad40a928e3434e96350c6b8c72904092e440cd63c074d956c5c4981e4c7ee4b95e2e7cc352a6e565afda3a8cc5dd092ac9ac093b1f1856cdb75cb51437a0667ddd1404001925da474e0a1b026019f7ace2b14ea015ee7f67a139c6454979d514c58848a0acf7ad45727dd56fe607542adc919ab52c5ac89c51b1fa4b693944e2ce8534d6a09d15003e869df063ee49fb5a9ff4826785bcdd9d5f59d3f4c8c1a36c6919bddae5d51245ae91c6c41ec5036c602d58e361088988527123d401126fca06b59464bec01f2927dba4fb24719131b51142b1fe53613d909e065ef7c69979b7b5a35fc0d1be1f7048fc7daa74306c6dd6bfb383d62f7485cc358e053004190a7a8933299ae275b189fa297a66201f16e36880820f4df282e2f50df96296c1b0a35cc2cd0cf3ffa3fa641f1232be6f07d4559a6971cae28abb6fc5017a05e478525f5684e4e63c0df640b705e482450e6e0ed6de7d84053760fb4b70dbe71f2d0a34dcdd145f1fdf1a65e04d05d6d6a8f086c24290c6c2e759b0cf7163d46bebd4c6170e3e884766914d22426cc8c89adb1e27eef5e3f9fb63db314379767908f91467f56", .None}, + {.Shr, "f87432f80314f1c5f1f1ab2f2cf41fd4051b3b738992b315a96744a6fd8593fb84c931226ee0b04c0f7e4838c3aaac7e38133aad481113698d85e9b425b2b257d71191ec9b678633614c76b97b21cf7885ea45a921f0e9c3e86b31c23c07dfd9df9af7a6750ad0db5ff6748011ddccfe6b4ff136da7ecaa942b15789eb8a9829d7936eab2bab7198d7ebc97d818df480026d873fd5aa05707701fd6043df790244316bc4dce4c1a4dc7fad1f19571a4e18bdd79b205062f1da02a7a830dc3a668c6567a336fa042edbde2604e7d8832085879429fc7d57aaceb45f0c5ac3ac600ecbe142474d2f7f14878d8225c8b5a1837a50ef21912f4b0d439f2509115c27f26d12313296604532b42502eacd0eb1e29ad5e265af1eb25f9932881700c550f954119745f51ff6891d08cbbae6e44e1e633fccfd05737def0e834c8ee440156709c9b25b4441fb9a600a5e357b982f938ff351c3f1cdff138befd5e0a3bbb920551ebb53ce5bf7d65845fd0cf812452d308e259298ed4b13de533e240d7b01813b3d27384aa0c191110858df4109f86183a2a073c2f74e26581744e56c9f25f0962486e5318cd60303c5f657234fdea12d95c2c6f5499f7702cb60a9cc1bcf17e9ff0f627271a1b7f7cd2866472628e7b92357a3f473161dcc6e5b520b67a6101a40a257f60e7b1790b2a6186f0860b64a9e283b7c7d397eca3a7d3334bf61", "3c", "f87432f80314f1c5f1f1ab2f2cf41fd4051b3b738992b315a96744a6fd8593fb84c931226ee0b04c0f7e4838c3aaac7e38133aad481113698d85e9b425b2b257d71191ec9b678633614c76b97b21cf7885ea45a921f0e9c3e86b31c23c07dfd9df9af7a6750ad0db5ff6748011ddccfe6b4ff136da7ecaa942b15789eb8a9829d7936eab2bab7198d7ebc97d818df480026d873fd5aa05707701fd6043df790244316bc4dce4c1a4dc7fad1f19571a4e18bdd79b205062f1da02a7a830dc3a668c6567a336fa042edbde2604e7d8832085879429fc7d57aaceb45f0c5ac3ac600ecbe142474d2f7f14878d8225c8b5a1837a50ef21912f4b0d439f2509115c27f26d12313296604532b42502eacd0eb1e29ad5e265af1eb25f9932881700c550f954119745f51ff6891d08cbbae6e44e1e633fccfd05737def0e834c8ee440156709c9b25b4441fb9a600a5e357b982f938ff351c3f1cdff138befd5e0a3bbb920551ebb53ce5bf7d65845fd0cf812452d308e259298ed4b13de533e240d7b01813b3d27384aa0c191110858df4109f86183a2a073c2f74e26581744e56c9f25f0962486e5318cd60303c5f657234fdea12d95c2c6f5499f7702cb60a9cc1bcf17e9ff0f627271a1b7f7cd2866472628e7b92357a3f473161dcc6e5b520b67a6101a40a257f60e7b1790b2a6186f0860b64a9e283b7c7d397", .None}, + {.Shr, "c8277967f202e1a02ed312248894050ceb29d0a72aa4403bf0808d81337691b35db83385ccc6b6bd6d043c470ccacdb46e7d77cf20288b891ca049d5ca913d0743479ab09c237ba18510a655e32baed725cfae6bd8e4349e4f3a5fc1eeae04ed354da4c7217d01e65242b3af87b2bcd5b9c423507927494eb8f29fdc860149f55ff413e1b7e4bfcb446ee397035cfcffde9a04ef01d662849e7e5f62f2e08eea586feb7d47b6a66a5abb532b561a94ec0425f4db97e8135b4a96fd22116f07ed192c854f615856d8ce5d4fde7e9ffc2ec97d07b18d6babc322e39c86cfb606a32507a0e605563988b454039a666150131b05db780e98dd0ec9d79ecd5679db360f075e47d6ecf2f95286197d775cdd497701463aa6f997e4fe9511c01621b9c14a3b21b17560d81cbb2b3858e8aa2a40fc863af178f096d75121200448c635b9f23b9adb47830f917aae3d0f7a6a60e8c6c4308b4a3ffa72a75a016a5fcbdd6d128a94d8f3c297e57f715d69fc0e62d7b0dd17cb215c9074f4faa20767e00e5fc11b5a6e6c64847f912e45c84a4faa79da76c532a04b26018749753189a6197696918f2a8e95a1b3921084b6281a56c488854e51bd865728c7e50cbfb785d49e1f2e97b10f41b624d0c80b1a796146cb70bce6f3b22ae52ab030695a9da9ccd6fa62ee5c532fb028fef9082497567245f5c7b1d671b07cc76168734c34626a78", "b4", "c8277967f202e1a02ed312248894050ceb29d0a72aa4403bf0808d81337691b35db83385ccc6b6bd6d043c470ccacdb46e7d77cf20288b891ca049d5ca913d0743479ab09c237ba18510a655e32baed725cfae6bd8e4349e4f3a5fc1eeae04ed354da4c7217d01e65242b3af87b2bcd5b9c423507927494eb8f29fdc860149f55ff413e1b7e4bfcb446ee397035cfcffde9a04ef01d662849e7e5f62f2e08eea586feb7d47b6a66a5abb532b561a94ec0425f4db97e8135b4a96fd22116f07ed192c854f615856d8ce5d4fde7e9ffc2ec97d07b18d6babc322e39c86cfb606a32507a0e605563988b454039a666150131b05db780e98dd0ec9d79ecd5679db360f075e47d6ecf2f95286197d775cdd497701463aa6f997e4fe9511c01621b9c14a3b21b17560d81cbb2b3858e8aa2a40fc863af178f096d75121200448c635b9f23b9adb47830f917aae3d0f7a6a60e8c6c4308b4a3ffa72a75a016a5fcbdd6d128a94d8f3c297e57f715d69fc0e62d7b0dd17cb215c9074f4faa20767e00e5fc11b5a6e6c64847f912e45c84a4faa79da76c532a04b26018749753189a6197696918f2a8e95a1b3921084b6281a56c488854e51bd865728c7e50cbfb785d49e1f2e97b10f41b624d0c80b1a796146cb70bce6f3b22ae52ab030695a9da9ccd6fa62ee5c532fb028fef", .None}, + {.Shr, "bc1b2bfdbb41b1fc33b0f9cdcf4ec141dfbbdd790f0b124eca182485bac89b981b576653fc5c83cefb5361c70ce8cc90e20365b9118c106cc3d466381402df47a4f7c94318d41d45cb8e6c1766ecadeac0b8351c62c805c3d158dfa53c63ecc4f7f3394f0e4fed52c217083e8f1df9d70bb6d32ea7131d92ad5095a97e16141a3a171e54caa1e2f55879f493352d5c95221ce559c1aa1300c6cb87404c7bf266896857d04736479c28ecbe6533ede4be69606666b85e3b60139328112d752a195b7e90a5fb997ab2073f4a69ba926f114564321c8360aa7f0cfc5c17284a998e018de958aa80c9479c124d94f15690df414ec8464501674491ef6c662c6419f49b33f7e04591462c0b6399b77ffeb72b445d4f3bd234b80c0edc07e7fdee40dd830ac3d35ab180663906dc79c31e539f235f6125c8a6cbc3d625796e690af48f70d45ce60b6961b752d75750b9cb187600d1f7157c8404ce64969ea4be1ca35ce3e964268c43db88dea4d21ac11c79bd5f19e7af6e17afae6f7d76bd889eb1c26d18fea233e75dc6be50179017f6d8774eeb9ab631c4d24fc2ba3be951b0c226a3c3245e259db41c6d8acd4091bb047bc70458021a3ad45b49aad83062283cf92fb04cb8eba1a64868a820a685fba78c5dc78352ed2e9f530a620ccc15bcd4ae15b887da70cc3dced6843ad0c431d4ee06cdbc0af09c30f12b87f54757459e31", "0", "bc1b2bfdbb41b1fc33b0f9cdcf4ec141dfbbdd790f0b124eca182485bac89b981b576653fc5c83cefb5361c70ce8cc90e20365b9118c106cc3d466381402df47a4f7c94318d41d45cb8e6c1766ecadeac0b8351c62c805c3d158dfa53c63ecc4f7f3394f0e4fed52c217083e8f1df9d70bb6d32ea7131d92ad5095a97e16141a3a171e54caa1e2f55879f493352d5c95221ce559c1aa1300c6cb87404c7bf266896857d04736479c28ecbe6533ede4be69606666b85e3b60139328112d752a195b7e90a5fb997ab2073f4a69ba926f114564321c8360aa7f0cfc5c17284a998e018de958aa80c9479c124d94f15690df414ec8464501674491ef6c662c6419f49b33f7e04591462c0b6399b77ffeb72b445d4f3bd234b80c0edc07e7fdee40dd830ac3d35ab180663906dc79c31e539f235f6125c8a6cbc3d625796e690af48f70d45ce60b6961b752d75750b9cb187600d1f7157c8404ce64969ea4be1ca35ce3e964268c43db88dea4d21ac11c79bd5f19e7af6e17afae6f7d76bd889eb1c26d18fea233e75dc6be50179017f6d8774eeb9ab631c4d24fc2ba3be951b0c226a3c3245e259db41c6d8acd4091bb047bc70458021a3ad45b49aad83062283cf92fb04cb8eba1a64868a820a685fba78c5dc78352ed2e9f530a620ccc15bcd4ae15b887da70cc3dced6843ad0c431d4ee06cdbc0af09c30f12b87f54757459e31", .None}, + {.Shr, "47c070c5516e300d0e079dc268e5ed03e0c29b8477bb23bfaa396b6588398ad2852043daf3a89743cfd9d6f6fc54321ca938a98f34a322fa4a708b96c1184e731c79e82e47d167a93ad3853dd46d636790e4ff21176feeb5cb7a86acae37fb76844824771fd7138ddb37e7c431b6b5490e3c9354e3cc3c727d88200eba5dee81998e9b7e6bc6931b40054f423694b736365a2ea9ecccccdcdabb383a83caed388b1db3d8fd78ebc99e49e04d0c0fc71dcc5e814b575e3075649453c1ce00286ee2823fcf8ad53d028251278a49d23ee654abede0ec2bc20c16159bbf02e8b473d8ae1c04544ce909c11267d1a52e8582f5cc7617b109e59c4d62cdbd7c860ff3786f20d7cef9eaae2f3f40dbd69d02801bc424b4f687712671698d1bc08e785a7099cd296bdbab6f09a3782d2c25c7808dd7878efd1c916513498f1d84e372df34b79088a047f958021f3f9c45eed3bda08fdc9a1524ff621b895d1c7b60c0ce77545d9e345eee199e50abfad107d6cebc1f3b42429820710d50e273dc1ec5cba1f80f4765ab664e106ab4d9b1f66132450eecc37adaa39cbd4f3808d9e103c52604ebf61f0e6a7684601bff251efc72ab7adbc5e3ad5530290b134adb6abce48732775cbf7533e9588446f84f99537353b19b22fae166f137618e2a46b4200d433a2941b4e92de3068e4ddaebd7f9777c0bc50b0027e2b1c35b8bbb101ec02", "78", "47c070c5516e300d0e079dc268e5ed03e0c29b8477bb23bfaa396b6588398ad2852043daf3a89743cfd9d6f6fc54321ca938a98f34a322fa4a708b96c1184e731c79e82e47d167a93ad3853dd46d636790e4ff21176feeb5cb7a86acae37fb76844824771fd7138ddb37e7c431b6b5490e3c9354e3cc3c727d88200eba5dee81998e9b7e6bc6931b40054f423694b736365a2ea9ecccccdcdabb383a83caed388b1db3d8fd78ebc99e49e04d0c0fc71dcc5e814b575e3075649453c1ce00286ee2823fcf8ad53d028251278a49d23ee654abede0ec2bc20c16159bbf02e8b473d8ae1c04544ce909c11267d1a52e8582f5cc7617b109e59c4d62cdbd7c860ff3786f20d7cef9eaae2f3f40dbd69d02801bc424b4f687712671698d1bc08e785a7099cd296bdbab6f09a3782d2c25c7808dd7878efd1c916513498f1d84e372df34b79088a047f958021f3f9c45eed3bda08fdc9a1524ff621b895d1c7b60c0ce77545d9e345eee199e50abfad107d6cebc1f3b42429820710d50e273dc1ec5cba1f80f4765ab664e106ab4d9b1f66132450eecc37adaa39cbd4f3808d9e103c52604ebf61f0e6a7684601bff251efc72ab7adbc5e3ad5530290b134adb6abce48732775cbf7533e9588446f84f99537353b19b22fae166f137618e2a46b4200d433a2941b4e92de3068e4ddaebd7f9777", .None}, + {.Shr, "5c50b4c17c86942ef71b71375134739e6bc7c3a811a0eaae270456985fa50e921617c40572d5f73c5b4006c4e796019a600817ce319e515c4792fc242b20a1ccfe4a4b6917ea832c0c980df5b56d5b09c2893fdbd6c6385ea9bdae2e2c38444dc86e24ea1229c518ea0fa2f03ba411419ff62ca3ac9d8397da4e06a061a52de9641d3fa8f7bad6366d493dfc4f71a998a820bda56eba7bf498230a67338acb0c19dc877bef1e40566b386ca3555dfa1a45ba8487eac550a686e0d842f743a9ff910312b4b3beafd2cc89b9dbbdf35304bab1e1f5e01a6b71834ef28f5ec9549f9bd483b86d894fd109536728f8e2fb0a7d12b84755c7a8729ce1db27840b2d96fa300060b24e2e7bf47df7ff5fe33b8b35d1603288ae765d3b66b20b4d800f794611355c00dd14b6d366cc92c71b860c44f6cbe02871dad5f9d676e64b9de72eec835f219aa3ffa2096d82ec88840e00d3a4bc117d062c57e6fe266a4c0a8ccfd4daef7e01147edebca122276bcc542634567296994157263bcac34641cc58816d41873d902f28f21847071ce3dc5ee88063251fc29900c70f04fd2857f1face9926baeff204e817f975d80d4733033611a04e2dec2d8a22e6b89edb96c0fd12be1b23ad88f4737c5dc1ecf4361b8fb2a6079e1d867aa9394eb97c0b0a4a7763ca6fe0b20acf3d574db072623cf07c5024035b8b95b2f0d74b68e95b4fabb065", "b4", "5c50b4c17c86942ef71b71375134739e6bc7c3a811a0eaae270456985fa50e921617c40572d5f73c5b4006c4e796019a600817ce319e515c4792fc242b20a1ccfe4a4b6917ea832c0c980df5b56d5b09c2893fdbd6c6385ea9bdae2e2c38444dc86e24ea1229c518ea0fa2f03ba411419ff62ca3ac9d8397da4e06a061a52de9641d3fa8f7bad6366d493dfc4f71a998a820bda56eba7bf498230a67338acb0c19dc877bef1e40566b386ca3555dfa1a45ba8487eac550a686e0d842f743a9ff910312b4b3beafd2cc89b9dbbdf35304bab1e1f5e01a6b71834ef28f5ec9549f9bd483b86d894fd109536728f8e2fb0a7d12b84755c7a8729ce1db27840b2d96fa300060b24e2e7bf47df7ff5fe33b8b35d1603288ae765d3b66b20b4d800f794611355c00dd14b6d366cc92c71b860c44f6cbe02871dad5f9d676e64b9de72eec835f219aa3ffa2096d82ec88840e00d3a4bc117d062c57e6fe266a4c0a8ccfd4daef7e01147edebca122276bcc542634567296994157263bcac34641cc58816d41873d902f28f21847071ce3dc5ee88063251fc29900c70f04fd2857f1face9926baeff204e817f975d80d4733033611a04e2dec2d8a22e6b89edb96c0fd12be1b23ad88f4737c5dc1ecf4361b8fb2a6079e1d867aa9394eb97c0b0a4a7763ca6fe0b20acf3d574db", .None}, + {.Shr, "d9ec59f17c854d2b2229eedc46e23116b2ecafe6e4a699ff678ae8e53001510268343d91677774e4829af556fb95a5359edbfbf89b0fa827392be3825100c2b8961fae20cf57bd25d17223ec3bbf46de1c263bc342c60ed942597cf2708a7f7b8a3aff7db2a014b85822d16cecffc5a1c6782e31cf53d4ae094b1f10dd4b212b3b4f1cff685ab316df11c28e88edce5a3e0c316eec15266c8f4fba076a0104ecc9b3bd5ca64728f23dbd109416c584fe45dd54c74eebe75613bdf634a9990f868e7248880abc28f5ee23b2f129335acc62eb1604d390eb1139b1cc3a13f6aeeeaecccc65a4223486e066c0caf65286c8971bf2c7c325c6d7c4cfba4a7d93fc80c3949ff0873acf5fd0bc968844fa1dd21d13016c3a16fb9c88d58b26a3b8bcd88bc0ccc76ecc3c9087e3563b539441241427bebb1dfcf398a9175c735106f183d23568f2db7380c00a8c92b455fd8429edc5e21ee1aece9bfcd79f22530579d1492cd4c9d02facbc24f8b1098ce2460b3ae3694147586a64942f65f59453bb4e2eee8bef9485eeb79211548e95b4bdd25645bc79738189dfe80f7410a16d9eb9a702a5f3dbe9c74c23371f2232a6ef0c73152b44c39d4ad4c03679a20785cc941996f61d422c3f663de67fc8dbb67a1829e3e7599365676ac0c7a6a7e653e5559e304dafab2012ce75a8c9c9d206b9d3900ad1f5da7f689f92dabe95b769c0c2", "3c", "d9ec59f17c854d2b2229eedc46e23116b2ecafe6e4a699ff678ae8e53001510268343d91677774e4829af556fb95a5359edbfbf89b0fa827392be3825100c2b8961fae20cf57bd25d17223ec3bbf46de1c263bc342c60ed942597cf2708a7f7b8a3aff7db2a014b85822d16cecffc5a1c6782e31cf53d4ae094b1f10dd4b212b3b4f1cff685ab316df11c28e88edce5a3e0c316eec15266c8f4fba076a0104ecc9b3bd5ca64728f23dbd109416c584fe45dd54c74eebe75613bdf634a9990f868e7248880abc28f5ee23b2f129335acc62eb1604d390eb1139b1cc3a13f6aeeeaecccc65a4223486e066c0caf65286c8971bf2c7c325c6d7c4cfba4a7d93fc80c3949ff0873acf5fd0bc968844fa1dd21d13016c3a16fb9c88d58b26a3b8bcd88bc0ccc76ecc3c9087e3563b539441241427bebb1dfcf398a9175c735106f183d23568f2db7380c00a8c92b455fd8429edc5e21ee1aece9bfcd79f22530579d1492cd4c9d02facbc24f8b1098ce2460b3ae3694147586a64942f65f59453bb4e2eee8bef9485eeb79211548e95b4bdd25645bc79738189dfe80f7410a16d9eb9a702a5f3dbe9c74c23371f2232a6ef0c73152b44c39d4ad4c03679a20785cc941996f61d422c3f663de67fc8dbb67a1829e3e7599365676ac0c7a6a7e653e5559e304dafab2012ce75a8c9c9d206b9d3900ad1f5da7f689f9", .None}, + {.Shr, "1a97aaddaad799fa7854bc475c8867d647eb838b7c53371a92bd20bcbc7f4516dde5b43dd697d87249e04365621302047cb6d70a6990efddfda38f8e90bc5b1ec61b858111917c82a5d0c147eb4900d9fe60ea8f8b8654cb8f81aff5ec6804f862afd2614e5684314b12629c8806ae562c5bca59a00b7004a6227deb5d429d821aab93d5efcf474c52136f0ea8a6854b33bd13092807c56039e3cb368c74f083606ec56e2a3dc83fbb53fb671fcb6992f711b0d639d6e1287f9531f860363e5b5c37017db6799ee782d26bfc9613f8b22f5641205eaea3b8b273383b68631be18d40dccc5766d90aff5c976230f61eafd6262c8d5e8efb6881eb0a443a8f1b57c65ea6718d845333dd007971d4b4839c5fa74d02bda0ff7899193fe7992ecb852d0d03ac047ee534dd020c6c443ff49aac3151480f115472a2b0d77d43410da95b8c9b3d56a6d508bea429728fc321624ce154bd91d9b0fbd558ec442fb6003213a0f4768c59757d08dee2bdfb344e6710ead99f447af25810a8c381ab62bbbbed5115532e31db851696b4ed2b66fe1ea542f2fca03f00239d750cc5210328f5fb8d95aee639e9002bfb4fc6b244e743c7ebd898efa1b8f31f39c57899e342ee0ea3f85db6edee89c1d726d725938269dd6268e969bcadb851e9b13e3a049e1479590c886e1696f1168c4b47a4d101afa35be3f68218285b358d2c9b1513f36e", "3c", "1a97aaddaad799fa7854bc475c8867d647eb838b7c53371a92bd20bcbc7f4516dde5b43dd697d87249e04365621302047cb6d70a6990efddfda38f8e90bc5b1ec61b858111917c82a5d0c147eb4900d9fe60ea8f8b8654cb8f81aff5ec6804f862afd2614e5684314b12629c8806ae562c5bca59a00b7004a6227deb5d429d821aab93d5efcf474c52136f0ea8a6854b33bd13092807c56039e3cb368c74f083606ec56e2a3dc83fbb53fb671fcb6992f711b0d639d6e1287f9531f860363e5b5c37017db6799ee782d26bfc9613f8b22f5641205eaea3b8b273383b68631be18d40dccc5766d90aff5c976230f61eafd6262c8d5e8efb6881eb0a443a8f1b57c65ea6718d845333dd007971d4b4839c5fa74d02bda0ff7899193fe7992ecb852d0d03ac047ee534dd020c6c443ff49aac3151480f115472a2b0d77d43410da95b8c9b3d56a6d508bea429728fc321624ce154bd91d9b0fbd558ec442fb6003213a0f4768c59757d08dee2bdfb344e6710ead99f447af25810a8c381ab62bbbbed5115532e31db851696b4ed2b66fe1ea542f2fca03f00239d750cc5210328f5fb8d95aee639e9002bfb4fc6b244e743c7ebd898efa1b8f31f39c57899e342ee0ea3f85db6edee89c1d726d725938269dd6268e969bcadb851e9b13e3a049e1479590c886e1696f1168c4b47a4d101afa35be3f68218285b3", .None}, + {.Shr, "3be866f368ae04fd6cff077b2388ebb8dfbee53477a5fe045605a60f06407da381a8b5c2c86e098cfc3cbd63041ee535085d9b8d823e880788dd2f82a8fe612b881868de7dc36b05b22d78cc74c8214719a20354d34afe61554c3fd5f697d080159d9be370e281c2e9cc48e0aa53a84b88cc855fa5ccb93ba513778c4db2ed6afa44afb3647ca6099ed60ba5e41ab93cf45195c54489391083af9c33d4b3cca89bcab3561dbc6025235635bd63daf1e17eaf0b30edc391e676523af7261f39f88d0cca064c5dc2369e7dd82ab62ae2fe95c56010f990102bf9f81ce361f0e34e6d873ebe8568dd20a02c0a9d9fcffb098c9efd26213d8879d7614e153f228b1b2a3ace0252e05ef71ecd1b39163ed6250b924e492157650a9fb82df10d0fdb51547f0b5aaf5dce2415a96d1352709c2b8a481b5c2c68399eb2527935f03c945b59ea2c11ab37d03c29d4ea5e62fa4950a74698a171d2d99b1bb261450c7ad8f5fe8895801dfa7bf1a5859ff9839211765bfcea60afc7b9e58990e0aae6c3b79ce6b8c36eb3afb11cb6fa78d06e7da1a914329b3d48bc9c098927d2b5322711a3e69f8311099340bd90dc1f500a1604f7181bcf680d33cf759ce4a2fdf0fa1addcc6eef8c2a9c58a0f4f591bba5aadbb466ab500fcee612dda71bafa3a65475aadd56ffe99b54eeb23b5258972d5d4119d5b0d94b5239b0d4b63f238c8346faf3", "b4", "3be866f368ae04fd6cff077b2388ebb8dfbee53477a5fe045605a60f06407da381a8b5c2c86e098cfc3cbd63041ee535085d9b8d823e880788dd2f82a8fe612b881868de7dc36b05b22d78cc74c8214719a20354d34afe61554c3fd5f697d080159d9be370e281c2e9cc48e0aa53a84b88cc855fa5ccb93ba513778c4db2ed6afa44afb3647ca6099ed60ba5e41ab93cf45195c54489391083af9c33d4b3cca89bcab3561dbc6025235635bd63daf1e17eaf0b30edc391e676523af7261f39f88d0cca064c5dc2369e7dd82ab62ae2fe95c56010f990102bf9f81ce361f0e34e6d873ebe8568dd20a02c0a9d9fcffb098c9efd26213d8879d7614e153f228b1b2a3ace0252e05ef71ecd1b39163ed6250b924e492157650a9fb82df10d0fdb51547f0b5aaf5dce2415a96d1352709c2b8a481b5c2c68399eb2527935f03c945b59ea2c11ab37d03c29d4ea5e62fa4950a74698a171d2d99b1bb261450c7ad8f5fe8895801dfa7bf1a5859ff9839211765bfcea60afc7b9e58990e0aae6c3b79ce6b8c36eb3afb11cb6fa78d06e7da1a914329b3d48bc9c098927d2b5322711a3e69f8311099340bd90dc1f500a1604f7181bcf680d33cf759ce4a2fdf0fa1addcc6eef8c2a9c58a0f4f591bba5aadbb466ab500fcee612dda71bafa3a65475aadd56ffe99b54eeb23b5", .None}, + {.Shr, "ba476c6cd817d699608eca9699a7a90631fb3d223aaa7fbef42ec0f42784955985f296399e9a8a561f2920f583b55e3df4a420bbe0a2491df940e4e2d7cb89be6277be6987ef0b9614533fd54c82a0806a734c66138dff7d7f4f68549926cedf2308752a5b0495d3ebe90aafe5da28cb66c404cf99a379e082b082a8a368d41b1e0790f8002faf838d0fb317c587cd6ff61c685bf68b2e1d6555e55e479afa2053bf594ff9a66ac5d814c9b1e32700d07407db018e8a3be77d487b583fe1818f126294707f962670c4d1bfb247990c77b7f0e31b13505bac195192fef5d94c05f58a24bbf3d5e92512c703dd10dcfb961c7c6c492ac6eafd221be5897b8192fd62dfa93e54ad47bd00a67a12fd7a3c0f4845038d67415907e90592b4dec578d878cb3f6584c8416512129062815b4244c4362d1a51233b0b25ac1b187af59660fe5dfd83dcb63f61b3c066d0ebf977db00932a025f076cfb014550eb91ceee5541ccf909fc21925a2c8eed751b58ab8d7d5541ed04441451fb4db7660c1240b5459b334d0c65ffb4649731a671b50ae778c765b0517d106ddacc373f2af26fe91fe63c780ae19555eafa4f3cf603e4a13289f8c41aa51ac8e35d304fe03ad979a6642654ec61c3f572499950dc3b7af11a71b5ad520e8e365bcc5550318c3ffa3f53077fb5e8cfacd7a4f54423c3b95d5a4fa1f4b4b1db696fdbbe80e72be45a", "21c", "ba476c6cd817d699608eca9699a7a90631fb3d223aaa7fbef42ec0f42784955985f296399e9a8a561f2920f583b55e3df4a420bbe0a2491df940e4e2d7cb89be6277be6987ef0b9614533fd54c82a0806a734c66138dff7d7f4f68549926cedf2308752a5b0495d3ebe90aafe5da28cb66c404cf99a379e082b082a8a368d41b1e0790f8002faf838d0fb317c587cd6ff61c685bf68b2e1d6555e55e479afa2053bf594ff9a66ac5d814c9b1e32700d07407db018e8a3be77d487b583fe1818f126294707f962670c4d1bfb247990c77b7f0e31b13505bac195192fef5d94c05f58a24bbf3d5e92512c703dd10dcfb961c7c6c492ac6eafd221be5897b8192fd62dfa93e54ad47bd00a67a12fd7a3c0f4845038d67415907e90592b4dec578d878cb3f6584c8416512129062815b4244c4362d1a51233b0b25ac1b187af59660fe5dfd83dcb63f61b3c066d0ebf977db00932a025f076cfb014550eb91ceee5541ccf909fc21925a2c8eed751b58ab8d7d5541ed04441451fb4db7660c1240b5459b334d0c65ffb4649731a671b50ae778c765b0517d106ddacc373f2af26fe91fe63c780ae19555eafa4f3cf603e4a13289f8c41aa51ac8e35d304fe", .None}, + {.Shr, "f306b6876275d3edfd3b66573289b0bb1f756996669c3238825a4affe914d9ddbe767c030d8ca333e176bd8b1f68ed18cd9aba8147d9fac83377f1a0700b254e7b5b8b2b783f30a2f6cedfbf93714c4c458619d3e14e5ec6e938e111ea147855256abbf4019fb074ffbe0eb9587f7837e3acff5323bb5c05418134aaede7172db8e286440100546c84ab3e0ba8124a3a940a9ae87836a902f079a82fd76c3831072c462cbcb1c3bf0c560dad5d686d94385c0ca0952c89a73bf6a952dc0e40ac6bd5c027bc2535d5a3abb9bd3b5f196b17f54541966d721d1bd448405889a2ae8f1aa17530801dbc608eb36d18ba01a2618901cece477ae41e53bdcae2d975903b59c66a2f76d89b68335e5b679aafa6e76034f392c7725baa2ae10dac6b0fe3dbef22de84a1feb95e082b1fb536b54de2703681ded3cdb8d1499e1b3786f4f4aa8382fdf38bfa90fb5670d1acefce2c1852e980cf119a547fa414083c7ae52c6dd43485c2c026137375d70f08e4d4cb4b846d1ee93eb4293d56d177c1476534c1c8cf7468c9db8bee6bbd4854fe711574876b9f0584245101882d5a4c6e2f4b57f67a27e099115450774cdf71bd8f9f3dcac820b190cccc68e0be7ecdd0830a098b40d190efc09614e236e33922011111f749f48558996faa32d5ad26c6afc5250c62bfe82a7abd11c428e64a058006fefd49a83374be126b15ecc72e32c3ae", "1a4", "f306b6876275d3edfd3b66573289b0bb1f756996669c3238825a4affe914d9ddbe767c030d8ca333e176bd8b1f68ed18cd9aba8147d9fac83377f1a0700b254e7b5b8b2b783f30a2f6cedfbf93714c4c458619d3e14e5ec6e938e111ea147855256abbf4019fb074ffbe0eb9587f7837e3acff5323bb5c05418134aaede7172db8e286440100546c84ab3e0ba8124a3a940a9ae87836a902f079a82fd76c3831072c462cbcb1c3bf0c560dad5d686d94385c0ca0952c89a73bf6a952dc0e40ac6bd5c027bc2535d5a3abb9bd3b5f196b17f54541966d721d1bd448405889a2ae8f1aa17530801dbc608eb36d18ba01a2618901cece477ae41e53bdcae2d975903b59c66a2f76d89b68335e5b679aafa6e76034f392c7725baa2ae10dac6b0fe3dbef22de84a1feb95e082b1fb536b54de2703681ded3cdb8d1499e1b3786f4f4aa8382fdf38bfa90fb5670d1acefce2c1852e980cf119a547fa414083c7ae52c6dd43485c2c026137375d70f08e4d4cb4b846d1ee93eb4293d56d177c1476534c1c8cf7468c9db8bee6bbd4854fe711574876b9f0584245101882d5a4c6e2f4b57f67a27e099115450774cdf71bd8f9f3dcac820b190cccc68e0be7ecdd0830a098b40d190efc09614e236e", .None}, + {.Shr, "4a1797d45613270853a6c254d832d893c99cb2364e43420f5f1991dc1f0e56498a79299b244f2b55b97f6523d542170e87bdac0478cbcf44d71dda3e6e98b2f33967c18b206d2d56063444cd95cb6d4af70b473eb1898da2e8e188ef9c185cc7c5139eab0fb1d377c5ddec3b599ec75510613de221e00cdf07adaa35319d27789737787c602356965bdc670af7ab89c6f8116e129b6e00691fcd043b946dc17a15ff61242a7a12741c05b353fcf94f8497d722bc4d5e0dd206fa2a28ecf9f4b1c6c47872b7b18f405dae5e99087a321cde184ed155f46eeaa3ff6e2f400a9196c7f26e03d6d17905433977315c9ff08e1ac1f1749e4811503c96e7f3646f18577aaf64cb361c22cff9e24cac5d51b651dd41ac7c4c832bb51633631862b339969ecb72e02b27886be6c245626c4edea55b4e6459362562b5b9fdfd564fbab8d8e748e8aec759ccc27b7de6fb9cc1361bee48afe24113c80f2c47118dbde0301953777a99c55f6caba7e8343cb25d4695ac037e249a06bdd9b7fbd5440b2eb422b3e0c144318f8434bf1fcd923ec3484753b56daa703b04ad24da19ed4fe437a78fb91681d8e2ac726afc50c93ce23ab908a2609e30aecd87a9b559b170c4fd47d52bde44bdc0efd59117b707585821dc98278529e5a5a6e3e00bc763dada69ec5ebd1585085154b780939233f33d7a3169d163e4ba1c8dab9e4cf4bf78127f53", "78", "4a1797d45613270853a6c254d832d893c99cb2364e43420f5f1991dc1f0e56498a79299b244f2b55b97f6523d542170e87bdac0478cbcf44d71dda3e6e98b2f33967c18b206d2d56063444cd95cb6d4af70b473eb1898da2e8e188ef9c185cc7c5139eab0fb1d377c5ddec3b599ec75510613de221e00cdf07adaa35319d27789737787c602356965bdc670af7ab89c6f8116e129b6e00691fcd043b946dc17a15ff61242a7a12741c05b353fcf94f8497d722bc4d5e0dd206fa2a28ecf9f4b1c6c47872b7b18f405dae5e99087a321cde184ed155f46eeaa3ff6e2f400a9196c7f26e03d6d17905433977315c9ff08e1ac1f1749e4811503c96e7f3646f18577aaf64cb361c22cff9e24cac5d51b651dd41ac7c4c832bb51633631862b339969ecb72e02b27886be6c245626c4edea55b4e6459362562b5b9fdfd564fbab8d8e748e8aec759ccc27b7de6fb9cc1361bee48afe24113c80f2c47118dbde0301953777a99c55f6caba7e8343cb25d4695ac037e249a06bdd9b7fbd5440b2eb422b3e0c144318f8434bf1fcd923ec3484753b56daa703b04ad24da19ed4fe437a78fb91681d8e2ac726afc50c93ce23ab908a2609e30aecd87a9b559b170c4fd47d52bde44bdc0efd59117b707585821dc98278529e5a5a6e3e00bc763dada69ec5ebd1585085154b780939233f33d7a3169", .None}, + {.Shr, "e7d4205792ec04af2fde99fbc59477fa9e16c10009900ad2237e761a78efbedb13c8f79fb59056a039dad2660c8297984310272624b7f3191f941ba55b3c8f58dc6d9c59cf286534ee6ee74170be25913c8e490c491bbca01798f1772ef802334e7c512d13907f03edfc549635430eb2fbd193c51f4b35f306b5b4c8f5d6adde5e3e1e91aa0e9c2737372c1b45a4af5ed3fabcd5fc2f168b646d09b642e099dddb39bf3cc493983d4dc13d4302b4a7f28a7f47add4b1c719a6191e10d1de9d039ffc58faee3ef74221d1c01f4b9125c8a1b148059453f6615c391275c79b090d363a2b5fe5df0afa1bedfc67efb517409341fa5fb2620731145a889072395cadc227d70bb44d844d1d2148a04c14be87263a404a7f1496012d9707f3af647daffd3397b756a8752ea64d35e33a1c58e333ff46e80cfe17f964d0d8b898cc07b36c7adf445faccdc00f6a5b46f6fe7a32e31864479f3890eac7ce7f8c2bcaa4758939a1a62ffb6a25ec8dde7e140d698a1e4b8b4ab434483acf30ea50749e871ebf3636ff9432b4850da17ffb8400d94c3f06a3ea52a6103a29cd9cca3a28f67af2c2488c73e9a1e1200d92d3282398f5ad805e6911441ba53965958921861ace74f4b2f0a739c202f9e9427eb808a8d02d9de861b807bdb089e19f758b352e5ee11fa800834fc4fae3fe12d0919a61b81dcdd1c18a37274d5859a17980685cdb", "f0", "e7d4205792ec04af2fde99fbc59477fa9e16c10009900ad2237e761a78efbedb13c8f79fb59056a039dad2660c8297984310272624b7f3191f941ba55b3c8f58dc6d9c59cf286534ee6ee74170be25913c8e490c491bbca01798f1772ef802334e7c512d13907f03edfc549635430eb2fbd193c51f4b35f306b5b4c8f5d6adde5e3e1e91aa0e9c2737372c1b45a4af5ed3fabcd5fc2f168b646d09b642e099dddb39bf3cc493983d4dc13d4302b4a7f28a7f47add4b1c719a6191e10d1de9d039ffc58faee3ef74221d1c01f4b9125c8a1b148059453f6615c391275c79b090d363a2b5fe5df0afa1bedfc67efb517409341fa5fb2620731145a889072395cadc227d70bb44d844d1d2148a04c14be87263a404a7f1496012d9707f3af647daffd3397b756a8752ea64d35e33a1c58e333ff46e80cfe17f964d0d8b898cc07b36c7adf445faccdc00f6a5b46f6fe7a32e31864479f3890eac7ce7f8c2bcaa4758939a1a62ffb6a25ec8dde7e140d698a1e4b8b4ab434483acf30ea50749e871ebf3636ff9432b4850da17ffb8400d94c3f06a3ea52a6103a29cd9cca3a28f67af2c2488c73e9a1e1200d92d3282398f5ad805e6911441ba53965958921861ace74f4b2f0a739c202f9e9427eb808a8d02d9de861b807bdb089e19f758b352e5ee11f", .None}, + {.Shr, "efd914f94668197ae786c10f161d017c1581e90d16fde588aa2c80ead065dd7eab06fa91f341f22a8f55b747d0d82deb51398994293c9cc65b0d252f399df23a3aaaf8a270a12667eee266b1bf8a60ca386e811d1d2951c422d77495c5b9b24004ea1ce09b668955f644c1d34536aba6ac82fc637fff3dd40fa80a0ec30cad71b0b6d3ef7d994069349df3ad79f9503bff208f6d08a89e73aa92b4c3f3f457dd4d9a1c1304ea04e53a58b2cc78226b431218c53f48783fa1abfce31115164388f13d41c8452a50f8b5c358d43dc291eb3d147f08919e8f1e6acc07d16a8d2acb7ace6cc327dab2865c1d20855ddeb1a0d9f5d04413e60fcef1dae0d3e1c7ce724d21014b2a008842dd1ba0ddcb9de9956211e0b2c451574270cfcf957bcbcbb368d2a67dd46e38232274087bd6b2c42635a1ca6ca2ff87f6fc05caa6149d7b556b0d2b411faa351fbcedca3a278b56039147bca6b922564d1cbc03df4876bccf1a1813e8f19fe4f4ee958876f5a56c9ce6953a436350af7041ad5108efc67c607faca8bdb65aac4815748f9c8b13d4b16b8fce7e03470ddd251fa0d2bf241cdc2fb96bee2f21df54430746db32f1f61f84289ae8f968834bd6890e6cf98172f292ef9bbd98ea01dd38f0744f869a30425ac6ca16723ff46c051ea35d163c7359ae9ca8082f17da9684cf20b6de9b7ec9793ef76f625f0197ba762717b7b30c43", "1e0", "efd914f94668197ae786c10f161d017c1581e90d16fde588aa2c80ead065dd7eab06fa91f341f22a8f55b747d0d82deb51398994293c9cc65b0d252f399df23a3aaaf8a270a12667eee266b1bf8a60ca386e811d1d2951c422d77495c5b9b24004ea1ce09b668955f644c1d34536aba6ac82fc637fff3dd40fa80a0ec30cad71b0b6d3ef7d994069349df3ad79f9503bff208f6d08a89e73aa92b4c3f3f457dd4d9a1c1304ea04e53a58b2cc78226b431218c53f48783fa1abfce31115164388f13d41c8452a50f8b5c358d43dc291eb3d147f08919e8f1e6acc07d16a8d2acb7ace6cc327dab2865c1d20855ddeb1a0d9f5d04413e60fcef1dae0d3e1c7ce724d21014b2a008842dd1ba0ddcb9de9956211e0b2c451574270cfcf957bcbcbb368d2a67dd46e38232274087bd6b2c42635a1ca6ca2ff87f6fc05caa6149d7b556b0d2b411faa351fbcedca3a278b56039147bca6b922564d1cbc03df4876bccf1a1813e8f19fe4f4ee958876f5a56c9ce6953a436350af7041ad5108efc67c607faca8bdb65aac4815748f9c8b13d4b16b8fce7e03470ddd251fa0d2bf241cdc2fb96bee2f21df54430746db32f1f61f84289ae8f968834bd6890e6cf98172f292ef9bbd", .None}, + {.Shr, "34ef93bd31efb99ee86b8b6ad5469d49abc522c9cf64724a53acaae87e70044394312da594fa495bc347c29df30c9b21bb5177c5b5c11d41afcf12c6b0a4c8063e1e968c2a187bb0bada4be8fd626b8b324f7c27335aef47789e7d463bda0294ef479ff80d3df97d2a820f6d91fd300d0dccd97bf17ce8fa023eddcbfad333e7a5dde529a306b81ac0a0ff37df02c746812505b94378a3651cc2210eb2bbf129c1669e316792d28cb5275f634bc4784eb3e459d932b280c6c52a2c37ba431cecc3bacc4de187f85541d57e6f72175719cfe9af78a0bbee6edcff2305966eb59972ed65fce7e56bf69d06a824becdd5e94d79b74bb19a60d32cc3240ae9dca55e0a7528ee3e4de390f19c4d955d5c91b513ad0ce027b6677bce900ea4ea861da61791d04395198098ea098cce8730a6ca92a49f04a0055e03210cde88fb46e716d56fda14994c055ab9a1c4f622a347f376652e4c2c6db8fee15b0f9c587d8018aa023741c819868063f7904d0f534a49300c8ef58bc6a286ed8804310a46e0fc6e57ac7f14a1eed171f520297aebc844bf850bdfc9d96f55cdff1c03b50f67582e8bfb75500210c89f198dcb9bf3e9c7856444b2a0520b41b35e6f092a3ca5268df7541a53e1c66b8a98cb9cd67bed03c253cef3d7a705a70fd05a561f2843a26cb4e508dc486fd1cbda74afaac861d5177407f070575c1aeeee71f87e47c563", "12c", "34ef93bd31efb99ee86b8b6ad5469d49abc522c9cf64724a53acaae87e70044394312da594fa495bc347c29df30c9b21bb5177c5b5c11d41afcf12c6b0a4c8063e1e968c2a187bb0bada4be8fd626b8b324f7c27335aef47789e7d463bda0294ef479ff80d3df97d2a820f6d91fd300d0dccd97bf17ce8fa023eddcbfad333e7a5dde529a306b81ac0a0ff37df02c746812505b94378a3651cc2210eb2bbf129c1669e316792d28cb5275f634bc4784eb3e459d932b280c6c52a2c37ba431cecc3bacc4de187f85541d57e6f72175719cfe9af78a0bbee6edcff2305966eb59972ed65fce7e56bf69d06a824becdd5e94d79b74bb19a60d32cc3240ae9dca55e0a7528ee3e4de390f19c4d955d5c91b513ad0ce027b6677bce900ea4ea861da61791d04395198098ea098cce8730a6ca92a49f04a0055e03210cde88fb46e716d56fda14994c055ab9a1c4f622a347f376652e4c2c6db8fee15b0f9c587d8018aa023741c819868063f7904d0f534a49300c8ef58bc6a286ed8804310a46e0fc6e57ac7f14a1eed171f520297aebc844bf850bdfc9d96f55cdff1c03b50f67582e8bfb75500210c89f198dcb9bf3e9c7856444b2a0520b41b35e6f092a3ca5268df7541a53e1c66b8a98cb9cd67bed03c253cef3d7a705a70fd05", .None}, + {.Shr, "5f6354aebacaa581e68f7058128ab6971271b33110338f4bda66c8d51130338f086be26f02d7e5c54166466ebc9912456bbb8bcb7129cb71d992e44c8ef7037236cc21962b79835225f6856c737ee0b64b3680f4142696d6221c220ef747522642fbecff4ffb6ac2c39ba3e4c8725060fac344140555395689966e9cc24e66932fe92bda385978a95cefa703b39cdec7fd4b746b780ef85dcd507a3b5d9961ecf64eaee3e62cc78ca89054f716c09b24b8ebed44405d7febee42af57de238503b8f6e5c605e3892ba24772231b9423d62f4588ae98f1940b99b694e92bf6009a14503a432ffa9f92b21a040369ccb071618cef37990fbbc16adb8339c17153f8dabc48e5af9feace088c2d2274e62abae1f0c9ccc1ad2c9da7c23a0d4eb032877f8a18538675dd4368bf3a8355c0c69c16848531f1857fb04e7d14601f59b137673999c5434a687ac2d5b3324afcd4b574872478b7a8935f92d418c24ced9e929c0a30899c6b9e00031dcf6a861758beddce7ab0b443ef26c7453b0f4001894707d7fc6f17004cc4c6d10cceaa541776e7da3d697e7378ccb44d8cd6723b923c5606bc14d45d25507795db49d1374e8f412386ff3ac370d8b525d8e3c2e1f270edb40ccc51e999a626949be1d9c4b2e1e27b07dbb9fbbf6b01c7652b72ff926c0615d8cf8263176adb2e09e5be28722ad52d7c6107c5404e73e6ac7e95f5a9ab", "f0", "5f6354aebacaa581e68f7058128ab6971271b33110338f4bda66c8d51130338f086be26f02d7e5c54166466ebc9912456bbb8bcb7129cb71d992e44c8ef7037236cc21962b79835225f6856c737ee0b64b3680f4142696d6221c220ef747522642fbecff4ffb6ac2c39ba3e4c8725060fac344140555395689966e9cc24e66932fe92bda385978a95cefa703b39cdec7fd4b746b780ef85dcd507a3b5d9961ecf64eaee3e62cc78ca89054f716c09b24b8ebed44405d7febee42af57de238503b8f6e5c605e3892ba24772231b9423d62f4588ae98f1940b99b694e92bf6009a14503a432ffa9f92b21a040369ccb071618cef37990fbbc16adb8339c17153f8dabc48e5af9feace088c2d2274e62abae1f0c9ccc1ad2c9da7c23a0d4eb032877f8a18538675dd4368bf3a8355c0c69c16848531f1857fb04e7d14601f59b137673999c5434a687ac2d5b3324afcd4b574872478b7a8935f92d418c24ced9e929c0a30899c6b9e00031dcf6a861758beddce7ab0b443ef26c7453b0f4001894707d7fc6f17004cc4c6d10cceaa541776e7da3d697e7378ccb44d8cd6723b923c5606bc14d45d25507795db49d1374e8f412386ff3ac370d8b525d8e3c2e1f270edb40ccc51e999a626949be1d9c4b2e1e27b07dbb9fbbf6b01c7652b72ff926c0615", .None}, + {.Shr, "cba282c43cdbb4d2301e1d25b51259f94a864e2bbffe042628931c27ee4a542ae8f36ecf8aa1cde91d1d9a7c98438a66976b01ed0febcb79907c2df7144f7ad58346cd80fb37f9b1d4a0c068e1aba5cc2dece943814d6c88387ee7cfe3e9c04ba89122ba63b762c974d1d9281d771da6e9a35f18755bc64cd72cdcd4435ce1720b899012aeea1522886e5d87b62ed031ba96200c6f8325b8a357143d8879a6cc4c31d08f07ba8e8f1178b5a457568349ff81dd0e1bb378a103e25fe76e25ae69cf0454f4904fb8a62edee66fa863e5fd6891d5da8775d21bfcc245ceb5c016f781d57bf540d2354aa7af9ca993c91d19a388ef80d2b8277390e5f9809ba918a0ecf19ce8a407924db5d5858773ef21c7028a41bc79b73dbb662f6059f4d2316bbb657f815de71f6baf048959d6d46b07953b4c1655f34aa8c087cbf8f4788ddc87ca919fb610b370fe67c5623e523f589c7f869dbfc6dde8b2992890defa3edefc55ac36d2d59f54f09c7da18325ffa2eb36081489c60db54a956e9dc586509158cbf9ac4d20c5009f5d74419a8c7f5147eea47b1349720c26d975f47731b8ad7c537ff52af202081e40db1dad4c9cca1fd6cdd40074479960f6a16eed1fbeb2648391ba69261d113c064453303bbdcdfafce11baf81ed0722b9107c005bd238adcda4074853abc2a19b2b7e94ab688bdbd57bca5bf8de053f3676464dcb8433", "21c", "cba282c43cdbb4d2301e1d25b51259f94a864e2bbffe042628931c27ee4a542ae8f36ecf8aa1cde91d1d9a7c98438a66976b01ed0febcb79907c2df7144f7ad58346cd80fb37f9b1d4a0c068e1aba5cc2dece943814d6c88387ee7cfe3e9c04ba89122ba63b762c974d1d9281d771da6e9a35f18755bc64cd72cdcd4435ce1720b899012aeea1522886e5d87b62ed031ba96200c6f8325b8a357143d8879a6cc4c31d08f07ba8e8f1178b5a457568349ff81dd0e1bb378a103e25fe76e25ae69cf0454f4904fb8a62edee66fa863e5fd6891d5da8775d21bfcc245ceb5c016f781d57bf540d2354aa7af9ca993c91d19a388ef80d2b8277390e5f9809ba918a0ecf19ce8a407924db5d5858773ef21c7028a41bc79b73dbb662f6059f4d2316bbb657f815de71f6baf048959d6d46b07953b4c1655f34aa8c087cbf8f4788ddc87ca919fb610b370fe67c5623e523f589c7f869dbfc6dde8b2992890defa3edefc55ac36d2d59f54f09c7da18325ffa2eb36081489c60db54a956e9dc586509158cbf9ac4d20c5009f5d74419a8c7f5147eea47b1349720c26d975f47731b8ad7c537ff52af202081e40db1dad4c9cca1fd6cdd40074479960f6a16ee", .None}, + {.Shr, "23629321e55723df89991105f43b8878c79994664fe0428c2c0980486b5edbed1985b18eede16fa6b5115cf136f97fc829b425c86ccef518b0615d79f39cbd14c2289484af1da02564706079bcc08dd8727ac8fb509f40c082376b86deeabd39290e042b9c7629e22dc4e3d12fa0154dd81ae1888efd3324789a9ab6be6b35e320fc22c5fdb3d8c84ac49da80cc6818261e9493f751bb0eedd3884a353ba2dd23d4f40b7ddda5f2376387281164cd7ebe9f7a3025a5713502fabb50f491b95379be4c755e2472c67b10c5729ed071c401049b43afc1d99526598e695e46fe188bd154d95ed11fc70e7b733c0a9ab61021e0bbc4c12b860c4b429d3f16db436ea55a2826f8b5ac2d8672cda839f3d6533571f71434feb278f526d4249b89d8924c9c7dfbb0fe9738b4fdc5a6facae75ff69cecfecb6eb31afa6ee8b30df40a82dccd4a36e528724ca7e0fc3e3eac3da9e1d9abd9930ff5d58466c45f39c36a2e5895a4c63e7782a52743335acf91bfc396144415621d255141aba14f50f8fd9b15869610543d7b02f6c17cedb46c9f7a547b87199f9425e2b4c4603dca0c96536e8691a4b01927080de6a23162203b182aa95b479bcca9554da56d0c957bec5d2619276b0671441736cd442a50a2a0d22ec0e0a297f24611488e2a405859553c7ba70e25438d3d93e7ee18dda0e5c0b2df792a774c91a6e5b2b59b47875b60597", "258", "23629321e55723df89991105f43b8878c79994664fe0428c2c0980486b5edbed1985b18eede16fa6b5115cf136f97fc829b425c86ccef518b0615d79f39cbd14c2289484af1da02564706079bcc08dd8727ac8fb509f40c082376b86deeabd39290e042b9c7629e22dc4e3d12fa0154dd81ae1888efd3324789a9ab6be6b35e320fc22c5fdb3d8c84ac49da80cc6818261e9493f751bb0eedd3884a353ba2dd23d4f40b7ddda5f2376387281164cd7ebe9f7a3025a5713502fabb50f491b95379be4c755e2472c67b10c5729ed071c401049b43afc1d99526598e695e46fe188bd154d95ed11fc70e7b733c0a9ab61021e0bbc4c12b860c4b429d3f16db436ea55a2826f8b5ac2d8672cda839f3d6533571f71434feb278f526d4249b89d8924c9c7dfbb0fe9738b4fdc5a6facae75ff69cecfecb6eb31afa6ee8b30df40a82dccd4a36e528724ca7e0fc3e3eac3da9e1d9abd9930ff5d58466c45f39c36a2e5895a4c63e7782a52743335acf91bfc396144415621d255141aba14f50f8fd9b15869610543d7b02f6c17cedb46c9f7a547b87199f9425e2b4c4603dca0c96536e8691a4b01927080de6a23162203b182aa95b479bc", .None}, + {.Shr, "ccf17abd74a323007af87b2ea5fe8f8afc1bf1692d90a5ec2e776cfb941c8885b21a13e572be9e85c5d4b829606aee381eadd3e33243cdc774996f165150426abe75f29b71dea3637f0d3825548ca7950a3fd5712c5cc9868d4fc864fe214cb30960c6079ecc388511e89d055b0e09365e2495f640144133938e188beef32398adfb50238ebc63fc5789baa1ccc2939140cc440ddca648faebd84d377dda7e448b91fdbef3af3168af2f224529ff55e123800daedaf4b2986601750b0ab79642aec48427dbba9f44607523814d881c8b74402d71791be41cbda788aed1d86e0569841e67d1668b60d9a873717532b4726d453613357200bd7879589b2bdd76bd555738e207fac78b50c4fbbd51e005f5bd5db3acec9705152657c94f1008797214802651057c66e02371fde0b33c80995b8a72f8fbac5a5b6bfbaf1d6d37b70e06c96fe1cf1d7a6b5be6364c0f3d95a06eaa0a586220f62e06653db99840d9eb3d6a9d89fc4d1d856b59386d5c44ad76f8d690d88873571adacf6e1e4b27c9004acb40914cbcd13491bbcd143f9e8f332ea928ce2e5dcc6e4886a864f3f972b8bd1cbb143d5cf683fa024dbac838c9f05297cd831386c22c9e560d70e8b2efb3f1a24825538aed97916a2357b04f0d93a2ef301726c8dd9f8c02754dfdfa2732b3fb8ca03907220c7063fee8e6b157255bb78f67dbe784767af3a02b5f1e23d8", "258", "ccf17abd74a323007af87b2ea5fe8f8afc1bf1692d90a5ec2e776cfb941c8885b21a13e572be9e85c5d4b829606aee381eadd3e33243cdc774996f165150426abe75f29b71dea3637f0d3825548ca7950a3fd5712c5cc9868d4fc864fe214cb30960c6079ecc388511e89d055b0e09365e2495f640144133938e188beef32398adfb50238ebc63fc5789baa1ccc2939140cc440ddca648faebd84d377dda7e448b91fdbef3af3168af2f224529ff55e123800daedaf4b2986601750b0ab79642aec48427dbba9f44607523814d881c8b74402d71791be41cbda788aed1d86e0569841e67d1668b60d9a873717532b4726d453613357200bd7879589b2bdd76bd555738e207fac78b50c4fbbd51e005f5bd5db3acec9705152657c94f1008797214802651057c66e02371fde0b33c80995b8a72f8fbac5a5b6bfbaf1d6d37b70e06c96fe1cf1d7a6b5be6364c0f3d95a06eaa0a586220f62e06653db99840d9eb3d6a9d89fc4d1d856b59386d5c44ad76f8d690d88873571adacf6e1e4b27c9004acb40914cbcd13491bbcd143f9e8f332ea928ce2e5dcc6e4886a864f3f972b8bd1cbb143d5cf683fa024dbac838c9f05297cd8313", .None}, + {.Shr, "ed578c397bb48353fcd91e595b48da0d82f194df80983866b686fdfd58051f930fcc69e7d06f4f247522dca47b7df502b66965de6f7397740db779d63fb66352f3eef8715f404a439c9621d4ddb8aeeea60b8eb679a02e925c280af2b9bab113fe82bbb15347ccb9c6e267bdcc714ff0158bb4e6722d9d40cdb075fd0b0aabbc9adddfcdc0598d43fe09d0902b88fc52748bfd169977884c7179df20928b81f774e9ca39794460832ee386039ce287001978e4dc5cfb2da381374ea6632fe7b43eafd5bc2202cdf7f2ab994240b89f80855efb90f3620d72b66e9fc3eb20a00cc8d0810207059ee786a4d668e4e1e57741ae5ce0fd85383e9a32ab4b2e0f6d62028367b9b8f2f16872a3a57ecf56ed9b44f221549cb93ac19fdc3c75a144e2dffd3ec0798b8c3840929136ab9bf3f55c2674934ca2193fa24d0e46305411c317edf660632878339fbd3ff82e05acbcc400cf4bf0a8cf48d1136f0675b69a9415a54f8a114e2faf8255fd2abe23815df913b0a62957ac0c3361067bc0170e49552c69f38b0a15584dbf169e32e50ee2b5077c0c49834ce9a72410d8ab4e2508d23bc67a037e4cd2f9206501db8be70a473d230626b302785d449ac174a43c294aebc0fb563276738eaa50e3b4b3ca54ef6eb0847feb10382c8076baca0ab58f30d26acfaba07bdd80ffeb127e6bf4732cc7843f132e1d5bc9921c1d30f686d4ac", "1a4", "ed578c397bb48353fcd91e595b48da0d82f194df80983866b686fdfd58051f930fcc69e7d06f4f247522dca47b7df502b66965de6f7397740db779d63fb66352f3eef8715f404a439c9621d4ddb8aeeea60b8eb679a02e925c280af2b9bab113fe82bbb15347ccb9c6e267bdcc714ff0158bb4e6722d9d40cdb075fd0b0aabbc9adddfcdc0598d43fe09d0902b88fc52748bfd169977884c7179df20928b81f774e9ca39794460832ee386039ce287001978e4dc5cfb2da381374ea6632fe7b43eafd5bc2202cdf7f2ab994240b89f80855efb90f3620d72b66e9fc3eb20a00cc8d0810207059ee786a4d668e4e1e57741ae5ce0fd85383e9a32ab4b2e0f6d62028367b9b8f2f16872a3a57ecf56ed9b44f221549cb93ac19fdc3c75a144e2dffd3ec0798b8c3840929136ab9bf3f55c2674934ca2193fa24d0e46305411c317edf660632878339fbd3ff82e05acbcc400cf4bf0a8cf48d1136f0675b69a9415a54f8a114e2faf8255fd2abe23815df913b0a62957ac0c3361067bc0170e49552c69f38b0a15584dbf169e32e50ee2b5077c0c49834ce9a72410d8ab4e2508d23bc67a037e4cd2f9206501db8be70a473d230626b302785d449ac174a43c294aebc0fb563276738eaa50e3b", .None}, + {.Shr, "93cbca16c48bd31343dbb8ef67aad4c44d9f875d2d4771a97dc2df9c0a2dfe5ae24c0acbd4f73e7c5d7469b59916f4f69af87f7681c12ed95196193a86da7595bcec4b3418c7c466dbbb8ea1eb80b2a13bf8446464888edebe60178737e72332ef693321ed1a61405be307a54a928dec286518b0f86a810c88da9a7fbb9859ce73a270ae9821e7e4c6b8587c306769c028218e27a3aa2e79284972f46c3d6bf1c0fe238f695fd46d16ad9f5afa66cfb2dc12ff0ae56e97a7fa32f0b2d1cf7d2f294e7fa9ce28d89ddd5b3c642411881b0a6e1331285db4309319d82998cd984971e6f61fd1c98c0610d0679d4968aa0f516260977330823bda1165216fb6084fb63641604311f13c02d8828d882c7e2966246a7f68db1fa612b89d21657acb24573faacae1e62e521b31e5f2e0f341278d94b5207fa7d66213921cda9d88335e50674a0f4e25c99bed90e86aa9c2b7d69ea4f6c409f71a3da78fa2c9c245ff2d87196f5bee730fc1d6db98c8cada50e97f47efee5f393e385458c6007a09fd38fe961f0db65c313afad233a5f2a3aeb0a5a94acd8f62dfd0883bf5d998ea55682fbcc7dacde6e7241962435cdf257259b95d8fb868bbe2b4da36f4895eccc97088dba115bd1386fd56f358a7c13af9fd13a88d980de34d9591b2626c33aeb123c960a1ac037db8f06dae15c82a4774bfe0d0b28b7677b7811d3d12fc24cd40a0", "78", "93cbca16c48bd31343dbb8ef67aad4c44d9f875d2d4771a97dc2df9c0a2dfe5ae24c0acbd4f73e7c5d7469b59916f4f69af87f7681c12ed95196193a86da7595bcec4b3418c7c466dbbb8ea1eb80b2a13bf8446464888edebe60178737e72332ef693321ed1a61405be307a54a928dec286518b0f86a810c88da9a7fbb9859ce73a270ae9821e7e4c6b8587c306769c028218e27a3aa2e79284972f46c3d6bf1c0fe238f695fd46d16ad9f5afa66cfb2dc12ff0ae56e97a7fa32f0b2d1cf7d2f294e7fa9ce28d89ddd5b3c642411881b0a6e1331285db4309319d82998cd984971e6f61fd1c98c0610d0679d4968aa0f516260977330823bda1165216fb6084fb63641604311f13c02d8828d882c7e2966246a7f68db1fa612b89d21657acb24573faacae1e62e521b31e5f2e0f341278d94b5207fa7d66213921cda9d88335e50674a0f4e25c99bed90e86aa9c2b7d69ea4f6c409f71a3da78fa2c9c245ff2d87196f5bee730fc1d6db98c8cada50e97f47efee5f393e385458c6007a09fd38fe961f0db65c313afad233a5f2a3aeb0a5a94acd8f62dfd0883bf5d998ea55682fbcc7dacde6e7241962435cdf257259b95d8fb868bbe2b4da36f4895eccc97088dba115bd1386fd56f358a7c13af9fd13a88d980de34d9591b2626c33aeb123c960a1ac037db8f06dae15c82a4774bfe0", .None}, + {.Shr, "b45afca5c253cc6823837db4f5bd77535785e5dd711af610d0cc9c255b2e38ce19613d6ef2edb3099a57807878982f26ada255d5460a05824d72cf3fb5546c264f7ab99ddb8193a0b7deec6746c22fcfc4d5991d8b471084851af89b28edca5b99f784b253bdc7d38c9d240a2b2d9d5b77c53719ae2ac4d874a046e9201f060ebcb60cfb055e7e59979e5c5f65dcab52e5ed8ccde71ef2fc243cbf1261766312e70297dffa8d1d2b5fb03abde19803af95ac94f475f444beb88a8460aee9329837f6994d4e9401c8ca38b5c2a2343168052204450d9f4bef832b25729db6ab8f1978c45c7fda590ea782886f95b6f967c92f80c2152b60c6c091b5991e5beb0aba416debcbf9f2804752dbfe40acd602e0fea22b6984c3841f475e9f8c12f4dfba6179d2646a1315551ff28d2147dfb3ad63aaf602bcdb26f2a01cafadcad7d6ca4b18416275735fafbc104485559e4e3385beba83ef5ba388c51d632ede7d7340806fe3705cd26a549ddb6d199a70521327834c6893680bb6c8ef3bf20cfe1d1aabf731f55785e39cc147f50f2e7ced1886535006a227a0228789edab68fee1d54134574e0ead6672b29a54683e0e6088709c4160664914250115c05731c65cbeba0311cbf3122683cca6d93d9f7b68ff98425af539fe3c13afbe2c989b1923a39b8ab8a01ec66b680eac3d31965e261bcf21c60ce6a622eeb4382637b759cf", "b4", "b45afca5c253cc6823837db4f5bd77535785e5dd711af610d0cc9c255b2e38ce19613d6ef2edb3099a57807878982f26ada255d5460a05824d72cf3fb5546c264f7ab99ddb8193a0b7deec6746c22fcfc4d5991d8b471084851af89b28edca5b99f784b253bdc7d38c9d240a2b2d9d5b77c53719ae2ac4d874a046e9201f060ebcb60cfb055e7e59979e5c5f65dcab52e5ed8ccde71ef2fc243cbf1261766312e70297dffa8d1d2b5fb03abde19803af95ac94f475f444beb88a8460aee9329837f6994d4e9401c8ca38b5c2a2343168052204450d9f4bef832b25729db6ab8f1978c45c7fda590ea782886f95b6f967c92f80c2152b60c6c091b5991e5beb0aba416debcbf9f2804752dbfe40acd602e0fea22b6984c3841f475e9f8c12f4dfba6179d2646a1315551ff28d2147dfb3ad63aaf602bcdb26f2a01cafadcad7d6ca4b18416275735fafbc104485559e4e3385beba83ef5ba388c51d632ede7d7340806fe3705cd26a549ddb6d199a70521327834c6893680bb6c8ef3bf20cfe1d1aabf731f55785e39cc147f50f2e7ced1886535006a227a0228789edab68fee1d54134574e0ead6672b29a54683e0e6088709c4160664914250115c05731c65cbeba0311cbf3122683cca6d93d9f7b68ff98425af539fe3c13afbe2c989b1923a39b8ab8a01ec66b680", .None}, + {.Shr, "4dd59a3dbb4623736b92d0f0cae161b826ff4ca48da3a7d1269ac391b931b32dfb9be82f09c440ec6d9aa7d244c1b802ec7f854e915d7c7b0856ead1de52514b01cba3c396ac6efc76e487d00c4d47311b953275a90726b7750c4459c00d02e6cde8dcc1692cfd525c6a58e030cde73f43c9ab2a799bdcb46bc071f67598b30c2cf806827863c52b83bb25965023ab8fc4d7369432749fab533ad51e9f773194da8d96faa578281cf274c6c9913c14bc1c1c8786bc09e948fc7fdafca14c6977db4e16a4ec935aa298ff73e01a0625089e37cd50ad29685d7a6f5a76c2f45f2e4d57d28b5a672282d7a2493e8d8fa7fc95165df9120a9396d9eb9a7090e3db7928a1ecbfde9d7ed0da07db3b3d675f5a3655b837527410524ea9ca814f2104967b50db25fd59bd23b666ce96e72da2ed6c4c06e2ffb5956b92018851b76629ce70e61a489272392e3d3fa9d04be65dcc14055e02085f6549dc598f20a681d7cc95fc11b2ba64b19a29348d7c848d238d74604c02eb425b2308254a1eae30a0ad2c3fb19ba539e5a86b4d44e62e92e110726198cc1e5ac208360143c770424571e396a2623e4f4c875d141eebab3fef2776b6295c5c8530c6d90433943722ca838349cf50e62ad4b62727ba965a3275b673cd17df6f87ed15797561539fca8ca5d74b18dd65857fe383839058031cfdd5eb25bf0aab1c3a6f32a55753484d62db", "1e0", "4dd59a3dbb4623736b92d0f0cae161b826ff4ca48da3a7d1269ac391b931b32dfb9be82f09c440ec6d9aa7d244c1b802ec7f854e915d7c7b0856ead1de52514b01cba3c396ac6efc76e487d00c4d47311b953275a90726b7750c4459c00d02e6cde8dcc1692cfd525c6a58e030cde73f43c9ab2a799bdcb46bc071f67598b30c2cf806827863c52b83bb25965023ab8fc4d7369432749fab533ad51e9f773194da8d96faa578281cf274c6c9913c14bc1c1c8786bc09e948fc7fdafca14c6977db4e16a4ec935aa298ff73e01a0625089e37cd50ad29685d7a6f5a76c2f45f2e4d57d28b5a672282d7a2493e8d8fa7fc95165df9120a9396d9eb9a7090e3db7928a1ecbfde9d7ed0da07db3b3d675f5a3655b837527410524ea9ca814f2104967b50db25fd59bd23b666ce96e72da2ed6c4c06e2ffb5956b92018851b76629ce70e61a489272392e3d3fa9d04be65dcc14055e02085f6549dc598f20a681d7cc95fc11b2ba64b19a29348d7c848d238d74604c02eb425b2308254a1eae30a0ad2c3fb19ba539e5a86b4d44e62e92e110726198cc1e5ac208360143c770424571e396a2623e4f4c875d141eebab3fef2776b6295c5c8530c6d90433943722ca838349cf50", .None}, + {.Shr, "36b14551a6081cdd2bce94eb8e0ff8d82951b5143ed48f34953a6531446f7d33b232dbd5f2ff507d710955aa45768b84227239e75044c447d84114cbad570564475245543241bc65da3a9a3a180151312ad434abdb4a1720b52e81e1e59467870fcd840bb1c5f8962aa03e6562ee1e27b6194572717ab1c39941dca40dbb1f73e918e3c29d4b4483d674eda15dee5a5fdacf51cd9008d7a438489a55c3166872a5dcd3aedf5a02d58fef812d9324b4b7198eba5637c16e62fd6404cd48d9f9101c1803609b8938417704d2e4c331c3a970836e565161e247f4afbddb39a2dd165a08eaece06194f6dd7c5682829675577d240744a70ee7ce8c532e2e3d78bb43ec4699b261b1beb26ef7b83273b59b96bbb18533996bd7847161ab560435f1bee9a3937a66a22528a24f13edc94947d1aeef9f925c00ce1cc5e4aac6cf2e64357f34f63e01c0965c144ab7fa71e0b1d17cf12b756d7c960dcdc81cb869fefe34b6c1aebab7392ae1f2be6fee6ebe656301e8f6183e9bab5b431d618912ff7c68fd2b0697fc7f086db7f5da0565565d62b2b8aed52d56dae36ccb79cf501a9ee35333aed0312383950b0faea686d69f1ee7c0f53878b7d2d700728cd183919d7db22d14542b62604b4f76aecff53a9a7d43752a1fce631a8e12f87294db29b184a7425fa626ca2fef2124290144ad512d0671e3051a1ed59a84b5e2f58e0fc7c5", "12c", "36b14551a6081cdd2bce94eb8e0ff8d82951b5143ed48f34953a6531446f7d33b232dbd5f2ff507d710955aa45768b84227239e75044c447d84114cbad570564475245543241bc65da3a9a3a180151312ad434abdb4a1720b52e81e1e59467870fcd840bb1c5f8962aa03e6562ee1e27b6194572717ab1c39941dca40dbb1f73e918e3c29d4b4483d674eda15dee5a5fdacf51cd9008d7a438489a55c3166872a5dcd3aedf5a02d58fef812d9324b4b7198eba5637c16e62fd6404cd48d9f9101c1803609b8938417704d2e4c331c3a970836e565161e247f4afbddb39a2dd165a08eaece06194f6dd7c5682829675577d240744a70ee7ce8c532e2e3d78bb43ec4699b261b1beb26ef7b83273b59b96bbb18533996bd7847161ab560435f1bee9a3937a66a22528a24f13edc94947d1aeef9f925c00ce1cc5e4aac6cf2e64357f34f63e01c0965c144ab7fa71e0b1d17cf12b756d7c960dcdc81cb869fefe34b6c1aebab7392ae1f2be6fee6ebe656301e8f6183e9bab5b431d618912ff7c68fd2b0697fc7f086db7f5da0565565d62b2b8aed52d56dae36ccb79cf501a9ee35333aed0312383950b0faea686d69f1ee7c0f53878b7d2d700728cd183919d7db22d14542b62604b4f76aecff53a9a7d43752a1fce631a8e12f87", .None}, + {.Shr, "fba0192939bdbcda15ccf56321b52af6046b5c0827d79e06fbbb3b3af78f3474b9eb00a3700bc55aba7248db2aac2fa7d9a1e5ddd0aa6c8b07855896efca30a96a2391513c5aa67f7bd8b89a6df393e25420057ce9ac89461a7d34201d38ac3dc5e851ad7e22659a864ceeacfe52293d14de5a6faa7bc298cb1f424e8b03cb8b04da13a6cd8cb77927ed53191fc12b1ff69b64dcfe874728005fd5e0e22f59a1ec8c239810ed24e48514fec9017a37986ba86ddaf3bbb3886ad663830f5cecec1e7e94edf724f349e24555beb28a8842a4fa6a6e585ac24da25d47dcb58c50b439dde4e7f7f672f4356cbf2284ea1aaaed076e37efeea86a86f5e8278f05991ee95030e681fe67fa4a7dc91240942ccda26961a1459e6753269957fc0b0ab5e2862804965822eb1eaa0430e781760e59ed6d038a8951e407b160d2dd6b797ef56739289a781b848bdcfc80ace574387abc82f502d4a5c799551b44c2cc212bca7f581d50315f182adef7ca7f0bf6c88fa13b081e5cd6df7c3a4d229e03f7f9cfef70770a28e3d5a4d988866e00c678519008d6b545dccd181db4b71f53be11a33f2496288a0032e881c6b2f98ac9e6d2be52be7a66ee0b234194bbb9e0dbd0c3bd3f985eec2065b0e07b0372894b3e1f93a06ca3f360f5c5098e06b5b1f3c5d2b3b9fc92177f2972149f1bfb709d9a0878d425817d042c60d271eed8944082be", "168", "fba0192939bdbcda15ccf56321b52af6046b5c0827d79e06fbbb3b3af78f3474b9eb00a3700bc55aba7248db2aac2fa7d9a1e5ddd0aa6c8b07855896efca30a96a2391513c5aa67f7bd8b89a6df393e25420057ce9ac89461a7d34201d38ac3dc5e851ad7e22659a864ceeacfe52293d14de5a6faa7bc298cb1f424e8b03cb8b04da13a6cd8cb77927ed53191fc12b1ff69b64dcfe874728005fd5e0e22f59a1ec8c239810ed24e48514fec9017a37986ba86ddaf3bbb3886ad663830f5cecec1e7e94edf724f349e24555beb28a8842a4fa6a6e585ac24da25d47dcb58c50b439dde4e7f7f672f4356cbf2284ea1aaaed076e37efeea86a86f5e8278f05991ee95030e681fe67fa4a7dc91240942ccda26961a1459e6753269957fc0b0ab5e2862804965822eb1eaa0430e781760e59ed6d038a8951e407b160d2dd6b797ef56739289a781b848bdcfc80ace574387abc82f502d4a5c799551b44c2cc212bca7f581d50315f182adef7ca7f0bf6c88fa13b081e5cd6df7c3a4d229e03f7f9cfef70770a28e3d5a4d988866e00c678519008d6b545dccd181db4b71f53be11a33f2496288a0032e881c6b2f98ac9e6d2be52be7a66ee0b234194bbb9e0dbd0c3bd3f985eec2065b0e07b0372894b3e1f93a06c", .None}, + {.Shr, "5388994dbaa6b5d19f105a64da12876e254541ef6bb37b73ef7c69b12e38920ee301e5233300d2876ff5d5d7c7f66e0d8ad4ffffa07a98749673c8e600b8522277b0c67f5f87f606c89662ed59895e2c7fe16c98a70d64f22e04fe5b434b161bfa7bdc47dc3ebb2a55efab26e49788a7e2983e45ac567435461c8f0a715cee0d2ffa522bd0609c08fb395d76cee40dd610a9c014becd1c3d1b846bd7d9abaf19f6bebd673efd1ca7a03f9e3be3d9a6a022cd0997e778bbf0b323d9c65778a0506b7446f5ae5ffd027b0b5e54547556a5da1dc0bd0a70f8cb35b0ec5dc3f74ebdba55250c5452a2c47d35209369a8addd2145f89ba0a93b5a2c3a7e9d74a14f80e6c61ff3738331d64b6ff278621c10834e93df61c100fb931a24c63731c200d99a644231e957c1399ad26be03324f5dd3b79ec5562d8f36bb0fc4bc6efff3df586ad46e60d33bf32d546a2c02969de5d0b3d02af5e2c2e961d86ee6c3c9478ef87ab74344b7d110e5781543f1e38b950f9c1c132c11136b3027a846b89bc17fe5fe129d31ba1c42d5d6932971b833a373fdda98433ae488bbdce4dee35487a6dcc325526828ee0c5baa56390b73ca2bfc468d75fdbce9ac480470cbdea872ca6ead98907d3733a1d6359505ba4c364be718108241749819aa2247633220939671b276de47805d69b946c0aa9ddf7baf3eda2d4e38f9e831ae0d4d163274f4997", "21c", "5388994dbaa6b5d19f105a64da12876e254541ef6bb37b73ef7c69b12e38920ee301e5233300d2876ff5d5d7c7f66e0d8ad4ffffa07a98749673c8e600b8522277b0c67f5f87f606c89662ed59895e2c7fe16c98a70d64f22e04fe5b434b161bfa7bdc47dc3ebb2a55efab26e49788a7e2983e45ac567435461c8f0a715cee0d2ffa522bd0609c08fb395d76cee40dd610a9c014becd1c3d1b846bd7d9abaf19f6bebd673efd1ca7a03f9e3be3d9a6a022cd0997e778bbf0b323d9c65778a0506b7446f5ae5ffd027b0b5e54547556a5da1dc0bd0a70f8cb35b0ec5dc3f74ebdba55250c5452a2c47d35209369a8addd2145f89ba0a93b5a2c3a7e9d74a14f80e6c61ff3738331d64b6ff278621c10834e93df61c100fb931a24c63731c200d99a644231e957c1399ad26be03324f5dd3b79ec5562d8f36bb0fc4bc6efff3df586ad46e60d33bf32d546a2c02969de5d0b3d02af5e2c2e961d86ee6c3c9478ef87ab74344b7d110e5781543f1e38b950f9c1c132c11136b3027a846b89bc17fe5fe129d31ba1c42d5d6932971b833a373fdda98433ae488bbdce4dee35487a6dcc325526828ee0c5baa56390b73ca2bfc468d75fdbce9ac480470cbde", .None}, + {.Shr, "e3b544090d88f8f39b600cdfc6cf467ea8f21d8a9e8b547ffed07147d2bd6a8d1439d89fbc880608c088eb90f368accbf8f2884086a08c727f442c19ded562e29f52018337e6d953bb4072cd0d3e7c17dc1dcb7461ae154d4a6b0b691b9c28c60c0cf94b013cac173742c3b7e5dea3fd0686b4ec333c353b65913fff57e8c6d0f245c05fa1aa8f9ab8d454af890fa967185a5610c07b231a9d284d53be845655ece0b72c7ba5d6089415c3b89a8647ba013d6ed75d2e1be33a0070c5725a9683a934318d722afde77368e3e81fb97d1a93f465d38b47e675017ba0c208830e3923ca84b589ec809513afb5396dc814c3009bca32be46f32c4fbb0cb0fd58607696a877a0003f6a8e84d2a0901e6f1ecc931af7282f7e3e3f176ef1eabbeee57866c102bdcdd659db6e1b210a3e8c25871ab8f62ac7d9c5bcd685193d56624f1218dfdcd951fd1a06a0ca22e5aed396969b40d079cdccc2bda737a0d9747bcfb200ad75369e128b97e421f22ac1924aaef730d4f1d77f4009b17d49c515a227c1e3656d6b3a2be1974043d505ebb39deb47e415ee038ca19a8c82867a737eddeb6e266c0c94863e9ec797955f3184f1d1022af2e46933bd626f6f6d396c23a8248d5fe7995f7187c8a77106805080731dcc5f9f555a5a96aee5f104ac2cba75f3fd5bd8a0a229bdd5ee6a02f50d04f27c8e7210049a1e82658bccf7e80597dd79", "3c", "e3b544090d88f8f39b600cdfc6cf467ea8f21d8a9e8b547ffed07147d2bd6a8d1439d89fbc880608c088eb90f368accbf8f2884086a08c727f442c19ded562e29f52018337e6d953bb4072cd0d3e7c17dc1dcb7461ae154d4a6b0b691b9c28c60c0cf94b013cac173742c3b7e5dea3fd0686b4ec333c353b65913fff57e8c6d0f245c05fa1aa8f9ab8d454af890fa967185a5610c07b231a9d284d53be845655ece0b72c7ba5d6089415c3b89a8647ba013d6ed75d2e1be33a0070c5725a9683a934318d722afde77368e3e81fb97d1a93f465d38b47e675017ba0c208830e3923ca84b589ec809513afb5396dc814c3009bca32be46f32c4fbb0cb0fd58607696a877a0003f6a8e84d2a0901e6f1ecc931af7282f7e3e3f176ef1eabbeee57866c102bdcdd659db6e1b210a3e8c25871ab8f62ac7d9c5bcd685193d56624f1218dfdcd951fd1a06a0ca22e5aed396969b40d079cdccc2bda737a0d9747bcfb200ad75369e128b97e421f22ac1924aaef730d4f1d77f4009b17d49c515a227c1e3656d6b3a2be1974043d505ebb39deb47e415ee038ca19a8c82867a737eddeb6e266c0c94863e9ec797955f3184f1d1022af2e46933bd626f6f6d396c23a8248d5fe7995f7187c8a77106805080731dcc5f9f555a5a96aee5f104ac2cba75f3fd5bd8a0a229bdd5ee6a02f50d04f27c8e7210049a1e82658", .None}, + {.Shr, "350148baea422641ab85a0b4ac64bbe928c8c5910487c0405ac60687b5b265cb4320b4f3b04311b854e94db8f45f1ae65087688445269b65c25fa2b61a429f23e0b0cdf2c18840dfc9a02f46d244938d5f7faa40659b3ea5f333c1c12744e0e8b20f3c934510dc47b1d558cb9bfafea15e41d63a7f90f93beee1c9f505373e9b870d72d69495323c313589ebe7f4565e8a6f93126ae872c791b65fc603b56e54cb8b89c01101a5a2dd961eaacb655de165d7bb5609ce9e5a564be78bfe3b602a64b912aae612374ac1af0f8eecbc5556135e469ab8876dc18fc997fd482dca62f8349d74d8f706aca0a4d26675d03b0a4f9629bcf1f93f273a218d41227a6cc0457dfb917a582a72e70784a94f3047d6c78f3ea1a3ee4fd628b57d85b820f816166df90440f5ea5017b463740ce6823128f95f787aa14236431cc6431a0f7ab05e7fb9459b1674f7b635144ae25c77b338da06538a4f7caae2781a9600378f20f7406c810aeaf326e3b4d494cc4ee42bf1f7780ff8fd2ff91f073afe578f479096bc49a1ecc2398b0881aaca27f5e387481a12ff1f9b36d852bc7f5afbcce4c9726a203a81c2c349eeaaa4206455d4f180ebf0f71be50ae543def8b5e378e8a2f90dcd1f12de9288a4b37e79f2955be636e7e56e86ce75a2c8f99c65d5fb82a92cdf9c7b556dd8056ad8442da94ae54eb087ca91bf9222ab42b344c1c8a77604", "3c", "350148baea422641ab85a0b4ac64bbe928c8c5910487c0405ac60687b5b265cb4320b4f3b04311b854e94db8f45f1ae65087688445269b65c25fa2b61a429f23e0b0cdf2c18840dfc9a02f46d244938d5f7faa40659b3ea5f333c1c12744e0e8b20f3c934510dc47b1d558cb9bfafea15e41d63a7f90f93beee1c9f505373e9b870d72d69495323c313589ebe7f4565e8a6f93126ae872c791b65fc603b56e54cb8b89c01101a5a2dd961eaacb655de165d7bb5609ce9e5a564be78bfe3b602a64b912aae612374ac1af0f8eecbc5556135e469ab8876dc18fc997fd482dca62f8349d74d8f706aca0a4d26675d03b0a4f9629bcf1f93f273a218d41227a6cc0457dfb917a582a72e70784a94f3047d6c78f3ea1a3ee4fd628b57d85b820f816166df90440f5ea5017b463740ce6823128f95f787aa14236431cc6431a0f7ab05e7fb9459b1674f7b635144ae25c77b338da06538a4f7caae2781a9600378f20f7406c810aeaf326e3b4d494cc4ee42bf1f7780ff8fd2ff91f073afe578f479096bc49a1ecc2398b0881aaca27f5e387481a12ff1f9b36d852bc7f5afbcce4c9726a203a81c2c349eeaaa4206455d4f180ebf0f71be50ae543def8b5e378e8a2f90dcd1f12de9288a4b37e79f2955be636e7e56e86ce75a2c8f99c65d5fb82a92cdf9c7b556dd8056ad8442da94ae54eb087ca91bf9222ab4", .None}, + {.Shr, "7cae7f52e32241126f991defa2f7d801db7bd444fa3c464088306bf46f35b34a15eae968ab90e16ace0433b940dd2f3e844e5de03a7200711fd1e1c00c51d403c5034e7e8e9a0a441fd54ec07736fd7bce5656b0fd5f3276a21ac698cec0505da0904874aba8aa4778bc8697ca4c485d6cd9422965c6fb4721fec252d31946c9c6fd4d936abbd5a96db5053e65f41b3c09fec82f067bbdc13a939de72de79ac445f260b10149b0b581b20d14a75539f1af5a07dc0e34e97df7d17ca832de04ef6856156d1b4f8c43104d244d27b9dcca4218021b261d2a989f5f008b000ab5dc6b9badff3676b5e6ee08e0c21d7f95c5f5159c6fc884f6ee9161a9a32331187bdba7bf3b28d0ab3378b0c327c70321954a4eb538e224c989f68f3f826ddd0e8e3565dbe66d145e06921bbcfb55ccbdc2d78ae3d6b967a6e2cadcb06fc8d7653ac7ee3107ed0a80b58d11ef281b71a8d5f76dc7e067ae4fa6391fc1024a2d7cb3dc61c2ab07c157b3956b578079ba20aa19bb4e30ab77818ed398ffd0285ae34da9231183914914484f97d9483e414243f63dcee65dcf9d4f156f4cc43cc34c8d59fd3d8dee322b1b8ff6c8653a93320b104f6e923c97ffc1437ce87da35087960acff509cb51f881da57f25476b60f9d6ad454ece008680f463f502abc1b318900500d2b790abf1d5f71ab3e33737916ea753af97314cf13f34a7969cc100ea1", "0", "7cae7f52e32241126f991defa2f7d801db7bd444fa3c464088306bf46f35b34a15eae968ab90e16ace0433b940dd2f3e844e5de03a7200711fd1e1c00c51d403c5034e7e8e9a0a441fd54ec07736fd7bce5656b0fd5f3276a21ac698cec0505da0904874aba8aa4778bc8697ca4c485d6cd9422965c6fb4721fec252d31946c9c6fd4d936abbd5a96db5053e65f41b3c09fec82f067bbdc13a939de72de79ac445f260b10149b0b581b20d14a75539f1af5a07dc0e34e97df7d17ca832de04ef6856156d1b4f8c43104d244d27b9dcca4218021b261d2a989f5f008b000ab5dc6b9badff3676b5e6ee08e0c21d7f95c5f5159c6fc884f6ee9161a9a32331187bdba7bf3b28d0ab3378b0c327c70321954a4eb538e224c989f68f3f826ddd0e8e3565dbe66d145e06921bbcfb55ccbdc2d78ae3d6b967a6e2cadcb06fc8d7653ac7ee3107ed0a80b58d11ef281b71a8d5f76dc7e067ae4fa6391fc1024a2d7cb3dc61c2ab07c157b3956b578079ba20aa19bb4e30ab77818ed398ffd0285ae34da9231183914914484f97d9483e414243f63dcee65dcf9d4f156f4cc43cc34c8d59fd3d8dee322b1b8ff6c8653a93320b104f6e923c97ffc1437ce87da35087960acff509cb51f881da57f25476b60f9d6ad454ece008680f463f502abc1b318900500d2b790abf1d5f71ab3e33737916ea753af97314cf13f34a7969cc100ea1", .None}, + {.Shr, "a421d2c4bcd4a59630859ae724712252e5124a83606742be764c7f0e555d338d95dac19fda218871da08e7c694dab740edfde0212fe46eb668a7b4cf894b2b8bcfe1b384b92c09892de099df1cef4932cc67a079712b78a8d57b509ad2548fbc7dca4a3e1ddab56b16f92f588f3a1dbc6a6ab81bd7cc25dfcd94c872ff3dd6192a81bcc07493c3e57c7b43c10f2cdb7a708d6937532f440b9f2044c60b37b7c24922cd5e28809fb7cbd4aeecbaa946ea05f303cf4c7d339fcd7809b47ac46e0eeaceab1e90ebcef32d23573950d5e2b207900513b5bbdf6b970b3ad0a358b3985f9df64c18cd3313d0ce32008972c310e3a88e62a40cf64d65f2b08130a94a75d6425401df237108700ebe90a08bf233f2f304c226a6d454550bb89972839d987c64735acac40a5aa698b7089d570d9a96c340ad3d1c314028137b209c8ef7a56b740de43d4ba0df8f32c9a2aa527343d4990bc3032661144802af35b3ed0c8b41d035d27523766719cf9e6d778bb11a4ceae3fc09f51775c29b213a99e3c9e7ddabed3e41549ee947d3181ab1862a0d227e0cb484db3c2d22465c0f03248a76cfbba9e535bc631676989fbb180da098a8137d91da1a58c4e4127122806d0001f3327040c689b8b5773b9d1a01ca4607f6baaa3163847baf70b012edb097235106e7476375da25eb2400619b30a767d5f4bfb707a4f58b9bcb4d7d5d2930d19c", "1e0", "a421d2c4bcd4a59630859ae724712252e5124a83606742be764c7f0e555d338d95dac19fda218871da08e7c694dab740edfde0212fe46eb668a7b4cf894b2b8bcfe1b384b92c09892de099df1cef4932cc67a079712b78a8d57b509ad2548fbc7dca4a3e1ddab56b16f92f588f3a1dbc6a6ab81bd7cc25dfcd94c872ff3dd6192a81bcc07493c3e57c7b43c10f2cdb7a708d6937532f440b9f2044c60b37b7c24922cd5e28809fb7cbd4aeecbaa946ea05f303cf4c7d339fcd7809b47ac46e0eeaceab1e90ebcef32d23573950d5e2b207900513b5bbdf6b970b3ad0a358b3985f9df64c18cd3313d0ce32008972c310e3a88e62a40cf64d65f2b08130a94a75d6425401df237108700ebe90a08bf233f2f304c226a6d454550bb89972839d987c64735acac40a5aa698b7089d570d9a96c340ad3d1c314028137b209c8ef7a56b740de43d4ba0df8f32c9a2aa527343d4990bc3032661144802af35b3ed0c8b41d035d27523766719cf9e6d778bb11a4ceae3fc09f51775c29b213a99e3c9e7ddabed3e41549ee947d3181ab1862a0d227e0cb484db3c2d22465c0f03248a76cfbba9e535bc631676989fbb180da098a8137d91da1a58c4e4127122806d0001f3327040", .None}, + {.Shr, "e3c3a88374613259d113c4a69695b9541fdad2105940af9879204ac0e1ae02a546d61c8002d9866daf821ac8443d3f3f121e46b87a4d4ad6cd13c5f4618acf86e3dfb84765b5e05756b4193de40349872e1abff6cfe5867aa571c2790b73b811b873365ab9d2638bf2ddcae9cc6945723d5a6c6d65c5c7749a34f2397bb7d26d11365390647580f3a35e7c36a99527681cdef420e42d7032b0cdaca6739abb53b5aec6a29128fd7316e809312bbeec261996ca3f5bef49918e5b9bcebba645a8e7d6e0962bfd1581f8cfcf7183ab917a22c4f196a17af656d5398142a723199a2c3a239358627722b9b8ac29dda1b012e145d46cd85d9f559f497c6dca1877cdff239c1ddc16cc8ac15788f92c1d78ffb2ac7c8b7100e2a20e6b8dc1b051ea1533f0ba49883f76c01d3a82f914b376e227538d0f67681cd5463ddeaeb55440f9605532ece04a29486d1484082a04c986051fd44aa533e9a0922e0cbf2325edc60e52db24dcddd33d8af97f16f1ff21c867c90b283a1c7f624d9b056449e8e8f02997185c4e05f4ac96ecf95bd29d73d8df6536b54cb2da18333a1db331ad3f99b48b8cebfad4fa6db2109a66b79083be2d293b04a752305f86549eaa2d3c6d3318a820d42adb313b614fe8e02dea5153ac9d665d6bc6129211f07d14cafc3e05b21c7763223a444935e940aa13694c09fdf602dca56f6948608eb0ed019ee4bb", "12c", "e3c3a88374613259d113c4a69695b9541fdad2105940af9879204ac0e1ae02a546d61c8002d9866daf821ac8443d3f3f121e46b87a4d4ad6cd13c5f4618acf86e3dfb84765b5e05756b4193de40349872e1abff6cfe5867aa571c2790b73b811b873365ab9d2638bf2ddcae9cc6945723d5a6c6d65c5c7749a34f2397bb7d26d11365390647580f3a35e7c36a99527681cdef420e42d7032b0cdaca6739abb53b5aec6a29128fd7316e809312bbeec261996ca3f5bef49918e5b9bcebba645a8e7d6e0962bfd1581f8cfcf7183ab917a22c4f196a17af656d5398142a723199a2c3a239358627722b9b8ac29dda1b012e145d46cd85d9f559f497c6dca1877cdff239c1ddc16cc8ac15788f92c1d78ffb2ac7c8b7100e2a20e6b8dc1b051ea1533f0ba49883f76c01d3a82f914b376e227538d0f67681cd5463ddeaeb55440f9605532ece04a29486d1484082a04c986051fd44aa533e9a0922e0cbf2325edc60e52db24dcddd33d8af97f16f1ff21c867c90b283a1c7f624d9b056449e8e8f02997185c4e05f4ac96ecf95bd29d73d8df6536b54cb2da18333a1db331ad3f99b48b8cebfad4fa6db2109a66b79083be2d293b04a752305f86549eaa2d3c6d3318a820d42adb313b614fe8e02dea5153ac9d665d6bc6129211f07", .None}, + {.Shr, "5cb35e51e2db45a2302e1db220e6c4802e6c0ba920f02ea491a08750730545d1d5e37d52ab74d6abbf8b6c65ab09646c35b0b0a15a73f81d16223256e59eb8b94572be7642fd3bf7320331ff34dd947a9f05da1a7af14f96e6e1828d25227a6ca6ad6309c6c0f9ba4ed89544dbf055a445a2137abbfdf998ca9a8ddccb5d6555dcf8ccee9ec8a2847eee5de8500b12fb6a2a78f394adbaa60be0745c90f0a56f6112ef13f8c71ec4eae40f4285966ee4c273ba89a5107b68057557c903248f6b4f73b9b397a035f80ea05ed78586343a409f80ae85c53c20c60d1dc6ca7d4b89fb6e4166a1938c015d2cb69c374e1fdec2ffde4ea747dbcd332ef9d1f8f1177786f688a4ce8ec987b61027bcbfff1881472aacdae03acc02a4bb974f03044748ad18597aa68578c0dbc50624b8d2669a2d0511be45599755fb5f0bda09c6e39da436e32991267c28363dc915c31f6d29931ac41ec10fbc20220eac29b2dc80c46bc7ad0b4554056fc923512da76ba71bf76ea1af131b6816839ff8f35ad2fcede058e26d2420b8b17d8a9fd64958deb6eeaada7c81194bc21197c63cedb72022bae21c8ad5ab324cc6e0bdc569b32373b2c4d86ee1f69e8be7daf21729a349551691ea676430b9ac8c1da39c9dde1f488a59842354984592a271b2b34c7e61f662ef95d8a874cb88aecb001a806615ddeda95a175cb795ba4b40cb9ae2891e6", "1e0", "5cb35e51e2db45a2302e1db220e6c4802e6c0ba920f02ea491a08750730545d1d5e37d52ab74d6abbf8b6c65ab09646c35b0b0a15a73f81d16223256e59eb8b94572be7642fd3bf7320331ff34dd947a9f05da1a7af14f96e6e1828d25227a6ca6ad6309c6c0f9ba4ed89544dbf055a445a2137abbfdf998ca9a8ddccb5d6555dcf8ccee9ec8a2847eee5de8500b12fb6a2a78f394adbaa60be0745c90f0a56f6112ef13f8c71ec4eae40f4285966ee4c273ba89a5107b68057557c903248f6b4f73b9b397a035f80ea05ed78586343a409f80ae85c53c20c60d1dc6ca7d4b89fb6e4166a1938c015d2cb69c374e1fdec2ffde4ea747dbcd332ef9d1f8f1177786f688a4ce8ec987b61027bcbfff1881472aacdae03acc02a4bb974f03044748ad18597aa68578c0dbc50624b8d2669a2d0511be45599755fb5f0bda09c6e39da436e32991267c28363dc915c31f6d29931ac41ec10fbc20220eac29b2dc80c46bc7ad0b4554056fc923512da76ba71bf76ea1af131b6816839ff8f35ad2fcede058e26d2420b8b17d8a9fd64958deb6eeaada7c81194bc21197c63cedb72022bae21c8ad5ab324cc6e0bdc569b32373b2c4d86ee1f69e8be7daf21729a349551691ea6", .None}, + {.Shr, "85ff660cdf62b184406d77e3b0b02651d094e6dc96d2bfcbea5b7bb6dfbb36a85788406abf43078355c597f50fbfbef650559b267f113a3111a6b764d36615c9f2b48b7d8a42784c0008d8013daffe5d0f6e7f3787ea5e609a55c6dceb7b6b7695a9c2dde0c2b17e866b9e8447d5daff6b090e8ea28fe59407702440c0b39d35b47738b62eb49f9e8839276394ca6d3a418b79ea814591be563f050dc3d8dd356fd0126bb44856228e12a1f0b8252c782a1ba015acab54ec735e1edb8f8469a056437e035d3d19475100919e0d353f48ff625d48073ce454dbe1507fb15af092201e0290f7f1cc2cc257a6d7a62b84b30af39851e2222e219b4672e03c77cf8c641ef1ab89be2ee62c9bfc8101c4b195566969b1369af7cf7b7a492cb6db236568384e1d7f9f20d562a23ba1a3247a561b12fa55258e38ec18612fd64b3a2f508b5059346dbfc515f031d4fa850ba3362a390a0cfb5c8fb2162b0b7f4a49d40a8cb11402cb594862346f421c759a591509fec1b9ad4767afb03765c87d07a48b04bdb89e3cdef683e1f1b5c1e8f7e9b3b91f4081a1b6e8168365be29febfe54240bef63668cf4ad276067596a22304558efaa9a86607b4c8d580c72cfed08e5fc224fb2039da8456e450fced25f7827e05db7f8c126b0fbfe09d0851190e9ae6f3dfbf2a9a1a3fca276b02dffbe9928a2e236cdf2238219b36066aec8908bd2e", "3c", "85ff660cdf62b184406d77e3b0b02651d094e6dc96d2bfcbea5b7bb6dfbb36a85788406abf43078355c597f50fbfbef650559b267f113a3111a6b764d36615c9f2b48b7d8a42784c0008d8013daffe5d0f6e7f3787ea5e609a55c6dceb7b6b7695a9c2dde0c2b17e866b9e8447d5daff6b090e8ea28fe59407702440c0b39d35b47738b62eb49f9e8839276394ca6d3a418b79ea814591be563f050dc3d8dd356fd0126bb44856228e12a1f0b8252c782a1ba015acab54ec735e1edb8f8469a056437e035d3d19475100919e0d353f48ff625d48073ce454dbe1507fb15af092201e0290f7f1cc2cc257a6d7a62b84b30af39851e2222e219b4672e03c77cf8c641ef1ab89be2ee62c9bfc8101c4b195566969b1369af7cf7b7a492cb6db236568384e1d7f9f20d562a23ba1a3247a561b12fa55258e38ec18612fd64b3a2f508b5059346dbfc515f031d4fa850ba3362a390a0cfb5c8fb2162b0b7f4a49d40a8cb11402cb594862346f421c759a591509fec1b9ad4767afb03765c87d07a48b04bdb89e3cdef683e1f1b5c1e8f7e9b3b91f4081a1b6e8168365be29febfe54240bef63668cf4ad276067596a22304558efaa9a86607b4c8d580c72cfed08e5fc224fb2039da8456e450fced25f7827e05db7f8c126b0fbfe09d0851190e9ae6f3dfbf2a9a1a3fca276b02dffbe9928a2e236cdf2238219b3", .None}, + {.Shr, "181d263b5a3cd991af1fb2a9bba83ad372c102d06c48207542a3b348df8b7bb3f7704d610b8be155593a18dba6d002904d0a84d0fa070a02b4683bd377b555ef526d65be8cd8abde241b571991cb821e747bc11a7e3e7e1ad2478512e16b7edba5c98308af5e995d7ab9ea1ec921c88eaca8e2f046654663c5d35f65c34e28092fcd14878a32489d23385b7b645564b7d6fefaf5dfca2eca8dd17f62750254348783544d6a9397214a0555c3636cf1ecc58c8d82b8a817cec8164c0289dc91c049376e3a36563a9f92cbdc1493274a8510d9807777ef75383aa95a3104d72a3752b22fd92c3916311323cd8aa772017cc42675636322f74a8e6745dc980eacf09747557e1672e89b364e1fd22799bebb3a3c79d30eab6d793e01ee173ecf5019795aae2709de37e735304dff318fee8736cd17b2632ef5c29ff6c09ea8424d9223b02751d89a0d4a8eb43d0d4a2d5394ca8f01bc0f8f5366bc277e5a7f4c06ab8612991f877896c5ea65f8ba2cbaf528477f6c3151bec5aefade5967773d0ae1f5f2bb1b151687e5a1985928009ab7b1cae9007583d2a522cadd6a192564e2ac753c3f8a2d5676c9dd86b9ed64ee0fead7dcc1ead74f36fddd82be83dbf1983b0c2e0b0bcb1271ede6c4a4f75f87165c251d58224e2d9e58e5adb2fdcd982b9be362ea4c9ff31e4a634bf69e495a02db9115f7ac715c3b56b14fe184e8e2db15", "f0", "181d263b5a3cd991af1fb2a9bba83ad372c102d06c48207542a3b348df8b7bb3f7704d610b8be155593a18dba6d002904d0a84d0fa070a02b4683bd377b555ef526d65be8cd8abde241b571991cb821e747bc11a7e3e7e1ad2478512e16b7edba5c98308af5e995d7ab9ea1ec921c88eaca8e2f046654663c5d35f65c34e28092fcd14878a32489d23385b7b645564b7d6fefaf5dfca2eca8dd17f62750254348783544d6a9397214a0555c3636cf1ecc58c8d82b8a817cec8164c0289dc91c049376e3a36563a9f92cbdc1493274a8510d9807777ef75383aa95a3104d72a3752b22fd92c3916311323cd8aa772017cc42675636322f74a8e6745dc980eacf09747557e1672e89b364e1fd22799bebb3a3c79d30eab6d793e01ee173ecf5019795aae2709de37e735304dff318fee8736cd17b2632ef5c29ff6c09ea8424d9223b02751d89a0d4a8eb43d0d4a2d5394ca8f01bc0f8f5366bc277e5a7f4c06ab8612991f877896c5ea65f8ba2cbaf528477f6c3151bec5aefade5967773d0ae1f5f2bb1b151687e5a1985928009ab7b1cae9007583d2a522cadd6a192564e2ac753c3f8a2d5676c9dd86b9ed64ee0fead7dcc1ead74f36fddd82be83dbf1983b0c2e0b0bcb1271ede6c4a4f75f87165c251d58224e2d9e58e5adb2fdcd982b9be362", .None}, + {.Shr, "ef1610fe1883956a648f15731b5ab7d0b8479756debff7064c9a947fa4f4d893931b45cb7a184cb343dd5cb084a1080d5f28e3e35ccbea4130cf45ca11cd1ef13c52597df90a0eb3f7e947af781879685263705705c945cf3ce2a08a8e61c6b8e6c85319c6579d3be0632cf3cdacfc9e32945018cd4d99a178aafaef77c1bd126cd7006a01ab8b7875a2b93d60a867a8ff281d0c1f90fab7c193591bbbe38755cdd57ceadf1ec566fb6323f3410ecaf9893c012f0c3a56264ef996118351fe0fd57be79ec0393107ea3865d50b4d854155658f9b6232e82d6f5b28307ee3af8eedc4e59df0ab48165a240dfd5027d865146337a55edf7025ba7d6ce879ec838cae86377c1cfd55a3c4f52f47b84efb74017380e95bff2db0de7c7b193d60fa8b72c4a95404433d88ace889bf7fe337801b31291f625613f37a192b0cd8536ec814cf567f2a8ee0e4ecfd2767697db76941d8e393a5e77091b15379cb1afa46c8d6c43a8e6d402ca5ff01c92e354e29ee2a32a48630838822480b1f9b40082e48f4ba7634b014e21bd40062cd1f83cfee62c4314c621d879448ed4e83f9a6bee2f848f7bf0d3b86f5ecd3b91a33de9baaa922b4f11e7a7e60b64150fdcf98e5ecd58d5027222ade2178e7b5461f618826df6a61b84b0b4f6a8947276e56e5348212a6b740651976831e190e2a82e9c50181c8b585ab2ec50cb70d0434f3bb7ee0", "168", "ef1610fe1883956a648f15731b5ab7d0b8479756debff7064c9a947fa4f4d893931b45cb7a184cb343dd5cb084a1080d5f28e3e35ccbea4130cf45ca11cd1ef13c52597df90a0eb3f7e947af781879685263705705c945cf3ce2a08a8e61c6b8e6c85319c6579d3be0632cf3cdacfc9e32945018cd4d99a178aafaef77c1bd126cd7006a01ab8b7875a2b93d60a867a8ff281d0c1f90fab7c193591bbbe38755cdd57ceadf1ec566fb6323f3410ecaf9893c012f0c3a56264ef996118351fe0fd57be79ec0393107ea3865d50b4d854155658f9b6232e82d6f5b28307ee3af8eedc4e59df0ab48165a240dfd5027d865146337a55edf7025ba7d6ce879ec838cae86377c1cfd55a3c4f52f47b84efb74017380e95bff2db0de7c7b193d60fa8b72c4a95404433d88ace889bf7fe337801b31291f625613f37a192b0cd8536ec814cf567f2a8ee0e4ecfd2767697db76941d8e393a5e77091b15379cb1afa46c8d6c43a8e6d402ca5ff01c92e354e29ee2a32a48630838822480b1f9b40082e48f4ba7634b014e21bd40062cd1f83cfee62c4314c621d879448ed4e83f9a6bee2f848f7bf0d3b86f5ecd3b91a33de9baaa922b4f11e7a7e60b64150fdcf98e5ecd58d5027222ade2178e7b5461f618826df6a61", .None}, + {.Shr, "951068d8b6ea1f2f3cdafd2290e31db7d0f44872b0f9c9baef9ad4c404ca80d85375a533e6187967f49e1428965ca6048a2e7a539328c2532e8df5ce33166532b49bb7ec21694533e8ec01d48554de62d896c06b7d804d102f14ff26bc2f0e031e3ba2bdcfadbfd80e3b9b6d84d68d23a9e67ee28df59b97381b6dc5ee0fefc71453067207e52110fdd67596e195f8910f54615c96e46bad457f0438f976060c043e1a3cf2d385ff994c70d69343cbd212f83e98c490fd5dcfab0dcfb0f8a75b3512f2f0edcff1bef3c4fa3741c6318fa890f3128b299e9bd3ac9e45e0e986a44da86a1b5a0f1ea2f04903ad87d409b440a0d664096606a5edb7fb82a410f063a684411932c78709bc781b372c3ebc639cd3a7f6ddb90f873fe3f041266b971563726d53efbc4b9ac94ed55dbcb5410fff5acf1ce7720738b0ab20b3cc3485ce6dd70c9ed6948c32fd5884f5a14917b164b882e71d82ee2a9887e4861ef5311568364c350c6fed999774e53959c07b00a73c3c5da2ce62c06aa4b252e3cabbe53bc42bf2d0a9c8f62fb5526f6f8cdaa668d7827c73b1624de2323fc96b726e626aba0b3aa962ccb4bfbc240410b7cf2f762de70817f070e23997a997d870d2bec325729c9371e05bacb6fec3c4fea6e094e49b792138fe792dee80dc9c2efbb7661184926c05ce8a17d9206711fe16387554299ab68e33553acdea4aad8eead5", "f0", "951068d8b6ea1f2f3cdafd2290e31db7d0f44872b0f9c9baef9ad4c404ca80d85375a533e6187967f49e1428965ca6048a2e7a539328c2532e8df5ce33166532b49bb7ec21694533e8ec01d48554de62d896c06b7d804d102f14ff26bc2f0e031e3ba2bdcfadbfd80e3b9b6d84d68d23a9e67ee28df59b97381b6dc5ee0fefc71453067207e52110fdd67596e195f8910f54615c96e46bad457f0438f976060c043e1a3cf2d385ff994c70d69343cbd212f83e98c490fd5dcfab0dcfb0f8a75b3512f2f0edcff1bef3c4fa3741c6318fa890f3128b299e9bd3ac9e45e0e986a44da86a1b5a0f1ea2f04903ad87d409b440a0d664096606a5edb7fb82a410f063a684411932c78709bc781b372c3ebc639cd3a7f6ddb90f873fe3f041266b971563726d53efbc4b9ac94ed55dbcb5410fff5acf1ce7720738b0ab20b3cc3485ce6dd70c9ed6948c32fd5884f5a14917b164b882e71d82ee2a9887e4861ef5311568364c350c6fed999774e53959c07b00a73c3c5da2ce62c06aa4b252e3cabbe53bc42bf2d0a9c8f62fb5526f6f8cdaa668d7827c73b1624de2323fc96b726e626aba0b3aa962ccb4bfbc240410b7cf2f762de70817f070e23997a997d870d2bec325729c9371e05bacb6fec3c4fea6e094e49b792138fe792dee80dc9c2efbb76611", .None}, + {.Shr, "c1219c31211ce1e9b587e1700c99b9d0766b014ee8a4e5c8fab11ceb1614db588b021d574349bbdc9fb7309d0a798158c01697f677187c01dbdf745136907655476e8ccbbdd2b37c51ee02d217e6ad3c9a47e3f6f762b1850a5650c832077010c0f4985c2411894c0d90252b2c0a1c1054556c64f2c5bee6a6b06dd8152a97553aeb7c24f6b0292395866c6103938066cacedba3a3542f379807aad2af1ba1703419a5dd08b3d594248bcc67ebb3b48dd8f8479eb0fcc5805dc548066ddc29d90572526ab9b4c929570e1224131b3075d077f9b7e6d146ef3324ef57a5db5d5d9fdc6df898a9465791dc2cafeba49433d82f3884a18c1a22f62241711171c4ced906ace7f88b9c21a36a197ebac8f91e5783ed7477b1f0e99a49bfd9fceb752499f68158889984df235a874ae88063a1e65106327067a1b9ad642f5cbabb62ef13a184a1a21ab17353712d2441e30e819bda197c9e49d55dc7ef969c8e92d1d26b428adaf8e12e00c530f1d014f954afe09c6bfaab8aedfe031df2588dba9ca2c4895359009f7a635b034eb4f290b14252407587fb0f366375360a43dca5ed670526ffe61e704ff6d05960cea17149ec220155e26f82302e2697aef7b33939746d998c04d91360c183434a5ba4af2727f2773dcb3e80544e0662d130315e4a4f406e04b7ba6c5aaccfbf89244636439f0f7ebae14a6923734adb8a9a20f12e0e", "1a4", "c1219c31211ce1e9b587e1700c99b9d0766b014ee8a4e5c8fab11ceb1614db588b021d574349bbdc9fb7309d0a798158c01697f677187c01dbdf745136907655476e8ccbbdd2b37c51ee02d217e6ad3c9a47e3f6f762b1850a5650c832077010c0f4985c2411894c0d90252b2c0a1c1054556c64f2c5bee6a6b06dd8152a97553aeb7c24f6b0292395866c6103938066cacedba3a3542f379807aad2af1ba1703419a5dd08b3d594248bcc67ebb3b48dd8f8479eb0fcc5805dc548066ddc29d90572526ab9b4c929570e1224131b3075d077f9b7e6d146ef3324ef57a5db5d5d9fdc6df898a9465791dc2cafeba49433d82f3884a18c1a22f62241711171c4ced906ace7f88b9c21a36a197ebac8f91e5783ed7477b1f0e99a49bfd9fceb752499f68158889984df235a874ae88063a1e65106327067a1b9ad642f5cbabb62ef13a184a1a21ab17353712d2441e30e819bda197c9e49d55dc7ef969c8e92d1d26b428adaf8e12e00c530f1d014f954afe09c6bfaab8aedfe031df2588dba9ca2c4895359009f7a635b034eb4f290b14252407587fb0f366375360a43dca5ed670526ffe61e704ff6d05960cea17149ec220155e26f82302e2697aef7b33939746d998c04d91360c183434a5", .None}, + {.Shr, "b267b4a9df920db387247067e4114dff76b32842efcae32f1687258c944cfd7ab9348deff4452bfd3c8286fcf08342b34fac6316747f339fb8283e6b17e8f111f09b170e3f7ee6659c178598513390567c4a7ce296b65a44e42a283a4fd0894a0bf5a41f132139aa1aea1874abf458d4890f0430bec116930e80d17330e603168c0c3df5127a2c153b050e8e81cbb5bcfa0fe5a1af84192e9e682ddaff705005b4a7b7fb7bbfb726ad3bb5b6a202901f12f807b721f44c2f204d5d0e7573e3c3c8d423a7fbe13716a44ce011154f8e5d36ae9942d3846c2a8d933a5d21347e89dc67171fe3c32ed07aa157faedfc3bc08495f11fcad3784f5b9cdc2283a3d403f064a16e84fc4351f4af8e7030662c0e4a347081e0eefc57d4176b3391e7a990e2d6398caca8cb64d6d3e3b5be04676a3473541eb4e4379df8ab4507e628cb4377fc3e17c1078d21ac4de602c3bebdb0d5b59dda5044fa374ee37245ebff817363199cfe0b326bd6cb1c0ca7be83edc6c22ddc7eb06a4b0ba2bb9c50abc88d322aa49e1d17019b770515abe134a5b03f5eaf6be4aed83a2ac1c71f7ffb946f32f06461402b85500559921c59129e790978f9f8e2df368e4228e3b5fbe9ef17a376aced2f552361a9d07566b0825f2b4b46f0ffe24fc8345b1445219a91df650b4b4069ebeb3f7c281d61d640ae88fda98dc6d59ac32db19570f2d7f53cef311a", "1e0", "b267b4a9df920db387247067e4114dff76b32842efcae32f1687258c944cfd7ab9348deff4452bfd3c8286fcf08342b34fac6316747f339fb8283e6b17e8f111f09b170e3f7ee6659c178598513390567c4a7ce296b65a44e42a283a4fd0894a0bf5a41f132139aa1aea1874abf458d4890f0430bec116930e80d17330e603168c0c3df5127a2c153b050e8e81cbb5bcfa0fe5a1af84192e9e682ddaff705005b4a7b7fb7bbfb726ad3bb5b6a202901f12f807b721f44c2f204d5d0e7573e3c3c8d423a7fbe13716a44ce011154f8e5d36ae9942d3846c2a8d933a5d21347e89dc67171fe3c32ed07aa157faedfc3bc08495f11fcad3784f5b9cdc2283a3d403f064a16e84fc4351f4af8e7030662c0e4a347081e0eefc57d4176b3391e7a990e2d6398caca8cb64d6d3e3b5be04676a3473541eb4e4379df8ab4507e628cb4377fc3e17c1078d21ac4de602c3bebdb0d5b59dda5044fa374ee37245ebff817363199cfe0b326bd6cb1c0ca7be83edc6c22ddc7eb06a4b0ba2bb9c50abc88d322aa49e1d17019b770515abe134a5b03f5eaf6be4aed83a2ac1c71f7ffb946f32f06461402b85500559921c59129e790978f9f8e2df368e4228e3b5fbe9ef17a376aced2f", .None}, + {.Shr, "7b39dc97e2af3b40727ea5fb472b2cc7d9bed1fa38faf09741138fda938a2842a01404e567092b6b2a697210239388407f22a9905c0f872b4f19db9ab81ffbdd5582a7b6bba63e3ba36e7975bbc95349d5066ba9549a88a5baf53b1b859a263ddfb2dc2832b91bee00f565dd695612d0240a842e762d9eb89f585f04f865375f1737bfe3a94e4c7fbe9b6d81c177154c5350a376b643b2a172d7265fc8af0729fe8a19fb38fe77bb3270b4b6746723a6cb969201f89bbb9b82e48f474f0b17aee4077e2c699d569dc5288bda4109767e406f1d17e23b3dbc7fd7efe34c575bda0982522877bf54ccc512233ec3121b454f34ccdc2cbc54978ec81daf9dea451dad69ce030a3b8b8524ce253d7d8b9a09bb2bea08e6f101a84e1c94f05b2a9adb51a3ad9400704cb49336164c3c9efd6be474be5212227ac28d3697943ae05ce7ec1f6fab18a068b85323f03ad343e4e82715519d6ca2be74b1c3e8fac3d30847161379378c6ad3dd14bb6c75d706b94d3c255b29380398e4b4cc1a67514310de15ff3914a3e027de31641c36126f9c9bc27b903acbacbf5e995d9c3b88b33008dc06b0fbd5794654e59da903403466dccab2d8ba7e3788a9cfffb01f24c6c7a851ccca8b594dcdf08a2a4cc0394616f92d5a9b879d4c71716a74d4e023d306a5e08807bd939720c5fed80a7031517f83058b81aa579c88df00baddca570c2a31", "b4", "7b39dc97e2af3b40727ea5fb472b2cc7d9bed1fa38faf09741138fda938a2842a01404e567092b6b2a697210239388407f22a9905c0f872b4f19db9ab81ffbdd5582a7b6bba63e3ba36e7975bbc95349d5066ba9549a88a5baf53b1b859a263ddfb2dc2832b91bee00f565dd695612d0240a842e762d9eb89f585f04f865375f1737bfe3a94e4c7fbe9b6d81c177154c5350a376b643b2a172d7265fc8af0729fe8a19fb38fe77bb3270b4b6746723a6cb969201f89bbb9b82e48f474f0b17aee4077e2c699d569dc5288bda4109767e406f1d17e23b3dbc7fd7efe34c575bda0982522877bf54ccc512233ec3121b454f34ccdc2cbc54978ec81daf9dea451dad69ce030a3b8b8524ce253d7d8b9a09bb2bea08e6f101a84e1c94f05b2a9adb51a3ad9400704cb49336164c3c9efd6be474be5212227ac28d3697943ae05ce7ec1f6fab18a068b85323f03ad343e4e82715519d6ca2be74b1c3e8fac3d30847161379378c6ad3dd14bb6c75d706b94d3c255b29380398e4b4cc1a67514310de15ff3914a3e027de31641c36126f9c9bc27b903acbacbf5e995d9c3b88b33008dc06b0fbd5794654e59da903403466dccab2d8ba7e3788a9cfffb01f24c6c7a851ccca8b594dcdf08a2a4cc0394616f92d5a9b879d4c71716a74d4e023d306a5e08807bd939720c5fed", .None}, + {.Shr, "3346079ea5a21c22e68bb7854aec8dade24989c1fdaf6e2750c0dc40ad042f0cb90ee14e8a062591867cabed9474eb416f670b0515767961d1c7972d26f1778609fd7eaee9b1e48246f90c784ba0fffb748342e61ad0023430450a149f25fc7fc5e6dc1aecf36ed5b69e343419e3bbe2407245aafcf6844312c090db6180d48175a1c2e76c9f74ba62ff782eed8d473e394cc5213faecec0ce523fcca8027ec5428ee3ecb41162dfb2a55917e186ec1b06658f00cdf24e4d8cb92169dacd62b0a9b305813a0cf2d218ad704512d8f5cf6bdd787c07e7442978e363e2b2bed50cfe6d7a1be6da863a3ab801a7341124bd4c548af9915d2354048ae88f000b27902811af0e9b4aa96100ccf237efab450c1c6ced5a3529f5e5a149680ce9d6c4ec840ef2026916892415b7cf9a96e639d9b227cefe3d143e7492b6ee88502deaefe646200132a8db3f531766fcc587d7632e2fd482e214e46c09646e50765a0ae4ac91f4f546b1348c578144c927a22a929da9b4073ef66b7e894197fe232a769afa19d0044637127a9f9f861b002204afde7f37a729941163b40243054ebfe12f2b8ebbdb49a433d650371ef2371db4c36aa377f257f494b9071307bf9548e5ad9902abe3290602ce15a0d12eb89ed7e7798c1d5d00ba7d17feb64f634d2e8470f6dae521650c456207eee78996d4e0ec751ea8d38672fb4ec6e995a9f6cc9b9e", "1e0", "3346079ea5a21c22e68bb7854aec8dade24989c1fdaf6e2750c0dc40ad042f0cb90ee14e8a062591867cabed9474eb416f670b0515767961d1c7972d26f1778609fd7eaee9b1e48246f90c784ba0fffb748342e61ad0023430450a149f25fc7fc5e6dc1aecf36ed5b69e343419e3bbe2407245aafcf6844312c090db6180d48175a1c2e76c9f74ba62ff782eed8d473e394cc5213faecec0ce523fcca8027ec5428ee3ecb41162dfb2a55917e186ec1b06658f00cdf24e4d8cb92169dacd62b0a9b305813a0cf2d218ad704512d8f5cf6bdd787c07e7442978e363e2b2bed50cfe6d7a1be6da863a3ab801a7341124bd4c548af9915d2354048ae88f000b27902811af0e9b4aa96100ccf237efab450c1c6ced5a3529f5e5a149680ce9d6c4ec840ef2026916892415b7cf9a96e639d9b227cefe3d143e7492b6ee88502deaefe646200132a8db3f531766fcc587d7632e2fd482e214e46c09646e50765a0ae4ac91f4f546b1348c578144c927a22a929da9b4073ef66b7e894197fe232a769afa19d0044637127a9f9f861b002204afde7f37a729941163b40243054ebfe12f2b8ebbdb49a433d650371ef2371db4c36aa377f257f494b9071307bf9548e5ad9902abe3", .None}, + {.Shr, "e7463e6dad18e70184768b6cecc9f5a2b35f3d04bfc57a66b0d4d8c7c6a9d9b26dc24d819ba181451744874111f1af6861d50ce32085674788743b573c38bdbea03d3937f62ec1e744d71cdb12394b8458784e8e77f79fe70420e96f063341cb5118be5b2e5ffb978b4603f57bd6f16d04f0decb507a148e3a874af6bf40b34c77f732b13d02b16aeaf825ec53159db21f91d92a126a04a78f2e5483be22c2174cd2eb5a496578f67e49ca72377e940050c2a0765a2121410aa01aeda75275e8858660030abdedb778ad942d52db5f548b1d536a85192a96c62a5b2e2865d2db5db5bf3a5cdb3c5a91e4eb5548d1857d1b4be35b447529307f1e76222f3f1dffcd6c69466f6ce12e19458d8d0e553e3f997adeff12b8fb8ca06ee6f8d741e642f2576ddee70e376c35532d3bf2d9cedd3596b0e662a2f20bdb2687d562219faf90c4886cce2ce48b7a37d0a303ee7ccc3e8d0bb43db271650d4a4b79246748a1c1b21475d5a07c253e7499fe4fe8f929fbca7c6a8ea39405fd693a97bd6b9a662be2efbc51516fbd0c2c593289e84f8712c267e3cfbdac28d49b3557cdd880cfb8a7bfe4b48bddfaa357672a5a46a41048a3c322f40a6b94c15cf3b9dc4ed3504eb9f846a4de5932ece2e4fcc6c3ed85db34e1996333725adb3ff9229ee93ea73a96c55587e87336cbbad6d04b5a722723ebd9283272c022aa5119b37fe25bac", "1a4", "e7463e6dad18e70184768b6cecc9f5a2b35f3d04bfc57a66b0d4d8c7c6a9d9b26dc24d819ba181451744874111f1af6861d50ce32085674788743b573c38bdbea03d3937f62ec1e744d71cdb12394b8458784e8e77f79fe70420e96f063341cb5118be5b2e5ffb978b4603f57bd6f16d04f0decb507a148e3a874af6bf40b34c77f732b13d02b16aeaf825ec53159db21f91d92a126a04a78f2e5483be22c2174cd2eb5a496578f67e49ca72377e940050c2a0765a2121410aa01aeda75275e8858660030abdedb778ad942d52db5f548b1d536a85192a96c62a5b2e2865d2db5db5bf3a5cdb3c5a91e4eb5548d1857d1b4be35b447529307f1e76222f3f1dffcd6c69466f6ce12e19458d8d0e553e3f997adeff12b8fb8ca06ee6f8d741e642f2576ddee70e376c35532d3bf2d9cedd3596b0e662a2f20bdb2687d562219faf90c4886cce2ce48b7a37d0a303ee7ccc3e8d0bb43db271650d4a4b79246748a1c1b21475d5a07c253e7499fe4fe8f929fbca7c6a8ea39405fd693a97bd6b9a662be2efbc51516fbd0c2c593289e84f8712c267e3cfbdac28d49b3557cdd880cfb8a7bfe4b48bddfaa357672a5a46a41048a3c322f40a6b94c15cf3b9dc4ed3504eb9f846a4de5932ece2e4f", .None}, + {.Shr, "100b7186598c885955cc0a0f0c1e6c8bcf44e5363096c1534627b20532e844b5827545fbb6508731972b878ace6af9a53395d44f5fee6cf4ada7ac3906d4e46d63a5c00950caa67c13f6c0c7357e9fd37002b5e42699ba938c91f219ed5a1eb9e336385cef1e2a21ce67b861081a3b058abec4f11202b7a941b17c2effc482da84398b603682511abb524500e45341cd4fba07d0cba4f3cadba8bd58b9ced34f8f0ccbf2397b8a55c954e9ed1671b7acde835ecd405ee4d353abd3380be2be78437f7821b8d3667b63265346a8f912335d8114b04328aaf7453dc91c12816b2ba91a403c6298107e7d6a4bb57c17da63e25b21d295825da63b5afb0d189c8339586c30e2cc6d6d4418f6b83e7a52a299b8426adc2b8af2e8aa2e8721046ad024335078383de6093f31193f3161a9d16f1686712503c4c51294887f39a69fc9ffa2a0dc962311a0c80392b5fe934cf89dccb8a42fd5249ac77fde4bffd7435ece4b035d2911cf802f00878bf18830df9c9ea720b56c03f8d164e9775edf2e04a9cbe990c5bfb68a80a60fdbab4667c83d37942ab729f51707108be3239d1d090f50756a9c6f3e0f1ce4866104d6f1b4fb5e65d49bfa22c3ae29483f3e890c38c21edaa4139afee848a8eda1b84b750cb71ada76c5d3ff774fb493575433b2f6e7c1bde997ac22f630f61d6b6f1b7170ef4d35d481b3c639462e2527ae333a9815", "f0", "100b7186598c885955cc0a0f0c1e6c8bcf44e5363096c1534627b20532e844b5827545fbb6508731972b878ace6af9a53395d44f5fee6cf4ada7ac3906d4e46d63a5c00950caa67c13f6c0c7357e9fd37002b5e42699ba938c91f219ed5a1eb9e336385cef1e2a21ce67b861081a3b058abec4f11202b7a941b17c2effc482da84398b603682511abb524500e45341cd4fba07d0cba4f3cadba8bd58b9ced34f8f0ccbf2397b8a55c954e9ed1671b7acde835ecd405ee4d353abd3380be2be78437f7821b8d3667b63265346a8f912335d8114b04328aaf7453dc91c12816b2ba91a403c6298107e7d6a4bb57c17da63e25b21d295825da63b5afb0d189c8339586c30e2cc6d6d4418f6b83e7a52a299b8426adc2b8af2e8aa2e8721046ad024335078383de6093f31193f3161a9d16f1686712503c4c51294887f39a69fc9ffa2a0dc962311a0c80392b5fe934cf89dccb8a42fd5249ac77fde4bffd7435ece4b035d2911cf802f00878bf18830df9c9ea720b56c03f8d164e9775edf2e04a9cbe990c5bfb68a80a60fdbab4667c83d37942ab729f51707108be3239d1d090f50756a9c6f3e0f1ce4866104d6f1b4fb5e65d49bfa22c3ae29483f3e890c38c21edaa4139afee848a8eda1b84b750cb71ada76c5d3ff774fb493575433b2f6e7c1bd", .None}, + {.Shr, "7df5b9f3e364bca13849d82428ac94be32760834c31c2acec5fbfaf03f4fb6dc563e3f3ce5dc3c3ddac1f052e9b917fcbbf0f2c2e9dd40c15501f04d7fa74c7b07932742131714208b18b1648ed491d52ba5e6d65ca14932e631e1492703428f4d22d7c844e447308c5619fd886f58777508da7b47a58d657d4b0e00aeb060d23dc8ec47d8dc656035a00e40a3ac841f9f311394a33edaaf88c5555d441bacc97044bca3be5d5ff6d87e9b053d3e6f868f5a5b123edee4cded0f6d9c47fb342608e779be37e63b0527ba3cac86f42826e4cd56805e4e3fc5702c65488232d3773b5bbf9f77793c43d2a5965efb92aa0b391c8a6dc3e37ec8c8585a3a8ec9e138635a308b7fef4666dde4bcb7bba0499c878bf0c23cfcd76fd6bb3a3cb0d54a9a8a526afe2a9ccecdc289b34adbc7d2087826e1d4719c675ffcfec077cb0a964a13bdc3a43c7f63fa0fa41ffaefea039f310d941ad30bc66d62d17a845944d3ec60a51e8d8954a02b189c344cb3d2101724bc4fee6f0db351da27b902589199171aaaed407da71c775c0d4827490715af552d5bbfa21fc7634374cd5b27ea69fad11ae23f4b0072c0042a578c870dbe51732de6457457b300dd7e3514bd27d9e66a72f2a9db584ed0235e188f4935dcef5c6e527cb55f406bd510c977430950310684c006772a6b6364a11737110ba606683ed0da728c659771d2797a364b6eec", "1e0", "7df5b9f3e364bca13849d82428ac94be32760834c31c2acec5fbfaf03f4fb6dc563e3f3ce5dc3c3ddac1f052e9b917fcbbf0f2c2e9dd40c15501f04d7fa74c7b07932742131714208b18b1648ed491d52ba5e6d65ca14932e631e1492703428f4d22d7c844e447308c5619fd886f58777508da7b47a58d657d4b0e00aeb060d23dc8ec47d8dc656035a00e40a3ac841f9f311394a33edaaf88c5555d441bacc97044bca3be5d5ff6d87e9b053d3e6f868f5a5b123edee4cded0f6d9c47fb342608e779be37e63b0527ba3cac86f42826e4cd56805e4e3fc5702c65488232d3773b5bbf9f77793c43d2a5965efb92aa0b391c8a6dc3e37ec8c8585a3a8ec9e138635a308b7fef4666dde4bcb7bba0499c878bf0c23cfcd76fd6bb3a3cb0d54a9a8a526afe2a9ccecdc289b34adbc7d2087826e1d4719c675ffcfec077cb0a964a13bdc3a43c7f63fa0fa41ffaefea039f310d941ad30bc66d62d17a845944d3ec60a51e8d8954a02b189c344cb3d2101724bc4fee6f0db351da27b902589199171aaaed407da71c775c0d4827490715af552d5bbfa21fc7634374cd5b27ea69fad11ae23f4b0072c0042a578c870dbe51732de6457457b300dd7e3514bd27d9e66a72f2a9", .None}, + {.Shr, "cba6d81c038a6a5aceb15a9f8c06aae25d978da9eee5e60e745f5509cdd598e3e09ba2d8f342deaac1765615d467fee125191d7ad6daa30a94c2eb933ba7e39ace20ab514936f86e284f5793602c002101fa58e99fbdbe40b0572e57d8d626834bcb9819b452b05da1ec58edf0b8eba5393778a895c37da714648f8a581b63bfeb591fc844ddd4fcbd4e696bf71e9cf6d992dad69012e6ed6471acb7692da45a67a2870def4a013ea2ff00df4ca6cae106aade979faced3e051c9b5fb66ddfd53634d614d8efaa632bf83c03213ede1c19e343e4de8e45b10394ddf91674a3600808bc28e0f01e40b8f396df88b452185827030cbf6d32a52a64e66b2bdee8fea56e0d99bbcb24ed4ad2215648ad14ddfd09f4f38cbcc4fb2327b759ec091bbc47ac722ff83f040369fa6356b3bff79b785bbd41eb17dba19c8f86bd5263c1f20c8581e0084bc90465c92aa6eba01d6fa3fa79f1e91a9929d2e87e83e3fc57ef219ec4032b28bde756b932f97a926aabaf01b2900baeb5494591a76d3e145b079db0d09dd4d68780aee9619ffbdecdf00e8241194d066091943ddf0446f9588ef990908705132a6b406555151de16829c8f81312a596627f2da036374ea7e5e578e6995feb240c1e91edf023be8f2b1c3b85b04e4e100a5d8cf87ead61a2ae514d6c30e2913c93190d7c2f867c35d70c768eabccb5a1e182617a829adc830999", "1e0", "cba6d81c038a6a5aceb15a9f8c06aae25d978da9eee5e60e745f5509cdd598e3e09ba2d8f342deaac1765615d467fee125191d7ad6daa30a94c2eb933ba7e39ace20ab514936f86e284f5793602c002101fa58e99fbdbe40b0572e57d8d626834bcb9819b452b05da1ec58edf0b8eba5393778a895c37da714648f8a581b63bfeb591fc844ddd4fcbd4e696bf71e9cf6d992dad69012e6ed6471acb7692da45a67a2870def4a013ea2ff00df4ca6cae106aade979faced3e051c9b5fb66ddfd53634d614d8efaa632bf83c03213ede1c19e343e4de8e45b10394ddf91674a3600808bc28e0f01e40b8f396df88b452185827030cbf6d32a52a64e66b2bdee8fea56e0d99bbcb24ed4ad2215648ad14ddfd09f4f38cbcc4fb2327b759ec091bbc47ac722ff83f040369fa6356b3bff79b785bbd41eb17dba19c8f86bd5263c1f20c8581e0084bc90465c92aa6eba01d6fa3fa79f1e91a9929d2e87e83e3fc57ef219ec4032b28bde756b932f97a926aabaf01b2900baeb5494591a76d3e145b079db0d09dd4d68780aee9619ffbdecdf00e8241194d066091943ddf0446f9588ef990908705132a6b406555151de16829c8f81312a596627f2da036374ea7e5e578e6995f", .None}, + {.Shr, "fdd2beb2698874a9bbfa15493bdbc350f47430839516d35ddbdeb61db686d89942601f4149d72401e1a6a511c560f86e3284b935c82bddf7bfc3731a16506acc060e2acc48bf2966b483be9a335d16e3d0add9137f169e1b8a22c90df06881bf2cb881148c4a13be5bfb967c2ff3aaa843d48be0f8ce6751b3230733060bc23b8764230dc6ddbcbf4a9d7ca7833f1a5d7682d29610accf4e5e2c18e75268648ec34812097df836e0718bcd7632723b9972b0f2f6e48bf747fb27aae57119117ef3252b169c476065de66e50db09a8443c26ab8ed4c04ae3d0420fed575f13ef3fac2254e5737288468380ce1c767c5906907fdeb5bfa6a8204b441edf210e844edcee88238bb64a46343631c8feafc7df5520a56a5d7c95883dc149bbe99fdd998eb8922a0c12851648da067007d78d4ef13dfb7b9f3b2c2eb47e327824f39307c3ff54f7a24e99b2a66b6c2eb089d6bfd1ee35b8b137e0957e22c402c6ebaa76c7e52be501d12c7f49b678a6a48d24375ae2c6154452e9165a28778c3d0e54a769271f14ec10502a1e1c9aa97bb294d3ae5e487209286afee128c0afdc781d63c3503eadda696182a56dd3a3f65db0a87c038dd8b82c0176e125aeb1282719fb24dc7ae04f48c0038c79b7ce60a669a39f4d19fb1cd9aa92c78c24617140b9fa13bd33cd27e13b78af5521c6c7b7bc25063c164ebf8b4bbee3e305f9fef7184", "21c", "fdd2beb2698874a9bbfa15493bdbc350f47430839516d35ddbdeb61db686d89942601f4149d72401e1a6a511c560f86e3284b935c82bddf7bfc3731a16506acc060e2acc48bf2966b483be9a335d16e3d0add9137f169e1b8a22c90df06881bf2cb881148c4a13be5bfb967c2ff3aaa843d48be0f8ce6751b3230733060bc23b8764230dc6ddbcbf4a9d7ca7833f1a5d7682d29610accf4e5e2c18e75268648ec34812097df836e0718bcd7632723b9972b0f2f6e48bf747fb27aae57119117ef3252b169c476065de66e50db09a8443c26ab8ed4c04ae3d0420fed575f13ef3fac2254e5737288468380ce1c767c5906907fdeb5bfa6a8204b441edf210e844edcee88238bb64a46343631c8feafc7df5520a56a5d7c95883dc149bbe99fdd998eb8922a0c12851648da067007d78d4ef13dfb7b9f3b2c2eb47e327824f39307c3ff54f7a24e99b2a66b6c2eb089d6bfd1ee35b8b137e0957e22c402c6ebaa76c7e52be501d12c7f49b678a6a48d24375ae2c6154452e9165a28778c3d0e54a769271f14ec10502a1e1c9aa97bb294d3ae5e487209286afee128c0afdc781d63c3503eadda696182a56dd3a3f65db0a87c038dd8b82c0176e125aeb1", .None}, + {.Shr, "3cfc4adc27af30937c7cf9d5e34240355c2ddbcd3ea96dae327e52beab855f4faa327d23f7e03fa517d0fd1ab1218c42845deb62ee0cc860f9efe73d7cee8768dc20492f10778c8705e462edf20909755fb1d313d73575bece9017221b3e7bd4d162a71409ed4c14769edf2ab8a499ed9444c86ec50dafdc127a714a648477efdc622619b27c7bab3067bfb7f141b7a14e4f2385770f4ae6e46b02bfc52b0b3fb937673cc980446cf8626e0b6943d622422c39a6c123b1f3c9625684b41b5f9d4a5e36a23a78888b8e1fe532d23b0e0392d17592788e9cc8362a53aa16ca298d5dd421f59a343cac9be3e16c14eba4a6d278c35277eafbaeb3d23bcab67b4c12d63c62e297defec85b3d3f2b7561b04421bfd86bbc79e9e963fb314308166a91bfcf84746cb9d81d5708feca3aab161be250847a1e471257e584638e2a4e529e59952ba6ec3706e699fff58c89957e27a9fd8489edf579d9e83b4f263822b63559b6085c461f5c267ca228ae9095259b252e9672b1455e7438d70077126e044193518b2283e92cd7a303dc8c5e63ec639a43d4b99621d7779d32a252ecc1e89db48789eb1f067d37378f966d2931fff88eecda2433d99f30fe5ea431ab860075c3d7badb2fb6f16a6265fed54503fb0004d7d60b65a3f66862d339fc11f233e0dd75bf1212a0ab4eb643530f6a0c5269fb030a62e6e83786323ff1665058c2ad", "3c", "3cfc4adc27af30937c7cf9d5e34240355c2ddbcd3ea96dae327e52beab855f4faa327d23f7e03fa517d0fd1ab1218c42845deb62ee0cc860f9efe73d7cee8768dc20492f10778c8705e462edf20909755fb1d313d73575bece9017221b3e7bd4d162a71409ed4c14769edf2ab8a499ed9444c86ec50dafdc127a714a648477efdc622619b27c7bab3067bfb7f141b7a14e4f2385770f4ae6e46b02bfc52b0b3fb937673cc980446cf8626e0b6943d622422c39a6c123b1f3c9625684b41b5f9d4a5e36a23a78888b8e1fe532d23b0e0392d17592788e9cc8362a53aa16ca298d5dd421f59a343cac9be3e16c14eba4a6d278c35277eafbaeb3d23bcab67b4c12d63c62e297defec85b3d3f2b7561b04421bfd86bbc79e9e963fb314308166a91bfcf84746cb9d81d5708feca3aab161be250847a1e471257e584638e2a4e529e59952ba6ec3706e699fff58c89957e27a9fd8489edf579d9e83b4f263822b63559b6085c461f5c267ca228ae9095259b252e9672b1455e7438d70077126e044193518b2283e92cd7a303dc8c5e63ec639a43d4b99621d7779d32a252ecc1e89db48789eb1f067d37378f966d2931fff88eecda2433d99f30fe5ea431ab860075c3d7badb2fb6f16a6265fed54503fb0004d7d60b65a3f66862d339fc11f233e0dd75bf1212a0ab4eb643530f6a0c5269fb030a62e6e837863", .None}, + {.Shr, "3b3d346797b8bdfefa0d096521385850781bea7a95121184ade90c33d743718f70730f70f5d8fafb327ebbd452958694db36e53cf4343b70155c0b02dbad8bf13183c65a7819c9a822d4e77b1b41e79980fc247ee710ec220d7d373e83a51eec2637fde8d630a068f6ba924d21555db95fef4f610607994a85a7e47eba0605861cdb4edf39e36783c7e01b43ba9c6b3e77942c64e5af28a9e29da4c8b946655a9bb5bf7bf26a70ddfd43a894d0dfd4b5b6054c99daac498d42b58ece91f1564885e2ce9b3a9c2daefdad0785bf9b97d334d914c8afd778a6efd3d225cd4d2df2b2b500332467a0de1eb0b9afc3e6b0544125541fd310d6b1c8f56ca549de5c7b8cf96bb7e451425bad7833375c2f265d17011e9f48c0a6b6be02bbaa00b7f524f1f019ed66ae3dd5810a525f3d7dabf8ac3667555943b7eb519880067ce9e2407d853cbcdaee2ec21508e50fd0250121b84eebd673588cc80f51dd2217af1cfbaeb068ea82dce9aaf499e05c356b1b8a0c0a52948483b5991569a551bb0d5462569360b423e03e64a2f5d567d1418ed1a4b74d6dabf26a3dad95d635bfb43910d8749e086941c323c525641243009533637c939e145522946821d8b4282a526d8f1e608641184470874b7981b7b7494d29f13cf70568a18b96e7ed0c2daab62cf1782a9a95085cbbe6701f5ee5abc1e13608dce1d9ef9632b5fb150c4a053d55", "1a4", "3b3d346797b8bdfefa0d096521385850781bea7a95121184ade90c33d743718f70730f70f5d8fafb327ebbd452958694db36e53cf4343b70155c0b02dbad8bf13183c65a7819c9a822d4e77b1b41e79980fc247ee710ec220d7d373e83a51eec2637fde8d630a068f6ba924d21555db95fef4f610607994a85a7e47eba0605861cdb4edf39e36783c7e01b43ba9c6b3e77942c64e5af28a9e29da4c8b946655a9bb5bf7bf26a70ddfd43a894d0dfd4b5b6054c99daac498d42b58ece91f1564885e2ce9b3a9c2daefdad0785bf9b97d334d914c8afd778a6efd3d225cd4d2df2b2b500332467a0de1eb0b9afc3e6b0544125541fd310d6b1c8f56ca549de5c7b8cf96bb7e451425bad7833375c2f265d17011e9f48c0a6b6be02bbaa00b7f524f1f019ed66ae3dd5810a525f3d7dabf8ac3667555943b7eb519880067ce9e2407d853cbcdaee2ec21508e50fd0250121b84eebd673588cc80f51dd2217af1cfbaeb068ea82dce9aaf499e05c356b1b8a0c0a52948483b5991569a551bb0d5462569360b423e03e64a2f5d567d1418ed1a4b74d6dabf26a3dad95d635bfb43910d8749e086941c323c525641243009533637c939e145522946821d8b4282a526d8f1e608641184470874b798", .None}, + {.Shr, "7dd848bafc3705539f7ea3c1cde250980732821780fd40da25fa0cde76ba3f22ce9955763d379f734dbd93fb84f475bfc35cc8380d443ab4cb485aa457b6784cbf784e8115220ea9642d8849f4a46655610819a32702e0060eca3e2687fbadc86dc14041b359e84516f4408c885cfcdc215e2792f8942826d5827c0d68068cb4571b35963d55fd1af184f1f334c835ca9f262f6abff2f5990d1cc5ce7c382e6108264692d5ef36e3d3374b507e1fa295e4497dc38d91f64b48e973b8d99c159bba6fadc8569c13ce5b770cbc72e2f2bab3e224c0967e43d4fbd0f6f0a3ad70f1b439dcf6169eceb2e750b7e08f21187344a804e336e0bb672dbdbd6dafd316e9397888ccf492330f3b06f81d2995f7d6970885ed3da5825a56f6a6c826fb5228dc8e5a89c600eb4f97ca6481ddc05cd91b379c6f76c81e148255be0f7be9036c5b88c9a526c5af33aaa7dc0dc210b8e8f407f561bb6608c739d39a176cd0e66b197326821a82d88b87ccc2465f5ef237892f8e542118a04060a6c363c09296fc774560b1c90cc255bf36f2f36bb67ab620469bbe92beda090f1b5ef9b5e8cf1593bb29a38430c0dffc447fa32871d7c118a7c89bcb01f5f9c5b49ad8938ae15e91095a006fd69e0aca2c22de058f5cae5f10623e27981b0d0537b379ca81390b7c4b460c4b8c4c9b1f37c6a819273be5f5b2ccad8b823ba4009432c60624abeb", "258", "7dd848bafc3705539f7ea3c1cde250980732821780fd40da25fa0cde76ba3f22ce9955763d379f734dbd93fb84f475bfc35cc8380d443ab4cb485aa457b6784cbf784e8115220ea9642d8849f4a46655610819a32702e0060eca3e2687fbadc86dc14041b359e84516f4408c885cfcdc215e2792f8942826d5827c0d68068cb4571b35963d55fd1af184f1f334c835ca9f262f6abff2f5990d1cc5ce7c382e6108264692d5ef36e3d3374b507e1fa295e4497dc38d91f64b48e973b8d99c159bba6fadc8569c13ce5b770cbc72e2f2bab3e224c0967e43d4fbd0f6f0a3ad70f1b439dcf6169eceb2e750b7e08f21187344a804e336e0bb672dbdbd6dafd316e9397888ccf492330f3b06f81d2995f7d6970885ed3da5825a56f6a6c826fb5228dc8e5a89c600eb4f97ca6481ddc05cd91b379c6f76c81e148255be0f7be9036c5b88c9a526c5af33aaa7dc0dc210b8e8f407f561bb6608c739d39a176cd0e66b197326821a82d88b87ccc2465f5ef237892f8e542118a04060a6c363c09296fc774560b1c90cc255bf36f2f36bb67ab620469bbe92beda090f1b5ef9b5e8cf1593bb29a38430c0dffc447fa32871d7c118a7c89bcb", .None}, + {.Shr, "5c09607379d369907af24a736d738193be60954190b53b54ee459889b0900b6e8b943fad649968c584428fe7246555c63e7316eaf0b2e73aa87ba83ef2a989fafcf5b01bdfdc960f2e6428b07dde3877ee3db60d21c07701cec113387ee14af6f0e1366c1204525802dee62a238a0e69788eb3a50f4b2148c7c187f60db7def2027d357a52a23a44d3ec89742b11d53924682d15d3d6bc05ba0d9145f698d331bbe0f129dee7a1babf93e249c548b179134a6a630e6e75008aa8d6bf063e97300c4e88de610d008cc26dc9a3fabeb2af5925344ee3b301cbc0132db85378f509c03a039a9561e38a8d3c1349354134497784dd8db5867e5aedfbed2faaf81e492901d8c61f830ea43dbcda99613e2d85e585c855ed25f727cbf7295cc0b161411dd9adc1c0118aa30237a57a755fc125459cbe2e391ccb72c743da1f620948688aed9149dc66502e37260a7e45b953aca640118a6d982bbbb1ccc9b4072ef36e2b7072877986328e7561d18660ef26e52441db5e17600dca65c5b511520d214486fa9defefc38f2d36869e877f8c0b71363f1bef344bf088568cd7a00a656ffabb9ffaff333e07628236259068aa8fc2d4388497f28af328cd554f4b420729c5765ac627784f8ef857f9fa894d0c01cf36efb6da9762e9442db55c54e7922f0e9693f27d58a420e029167e764268abeca177f24bbecc491900549ef78c0ed7a7", "1a4", "5c09607379d369907af24a736d738193be60954190b53b54ee459889b0900b6e8b943fad649968c584428fe7246555c63e7316eaf0b2e73aa87ba83ef2a989fafcf5b01bdfdc960f2e6428b07dde3877ee3db60d21c07701cec113387ee14af6f0e1366c1204525802dee62a238a0e69788eb3a50f4b2148c7c187f60db7def2027d357a52a23a44d3ec89742b11d53924682d15d3d6bc05ba0d9145f698d331bbe0f129dee7a1babf93e249c548b179134a6a630e6e75008aa8d6bf063e97300c4e88de610d008cc26dc9a3fabeb2af5925344ee3b301cbc0132db85378f509c03a039a9561e38a8d3c1349354134497784dd8db5867e5aedfbed2faaf81e492901d8c61f830ea43dbcda99613e2d85e585c855ed25f727cbf7295cc0b161411dd9adc1c0118aa30237a57a755fc125459cbe2e391ccb72c743da1f620948688aed9149dc66502e37260a7e45b953aca640118a6d982bbbb1ccc9b4072ef36e2b7072877986328e7561d18660ef26e52441db5e17600dca65c5b511520d214486fa9defefc38f2d36869e877f8c0b71363f1bef344bf088568cd7a00a656ffabb9ffaff333e07628236259068aa8fc2d4388497f28af328cd554f4b420729c5765ac627784f8ef857f9fa8", .None}, + {.Shr, "5287199851a7d5975b881c5c0e3aa9efa7ffa770921f2e5c30e784cadf1a8c95ba0ecf30441d46fad49d721eaa6e5e5ca22ce0a085e139a2ad70df666b5eaf1033517bf52a7395f00c3b020e209e82f77af7c85e7c2c1ccbdc02e57a36df25bad74a6823a26ecb9ec16818ebca138c7a9298e3bbb51f87801d7654da70bce10de778efcc1aada659235d1091a1864f0a4ed4eea3157c2d7d1b3ef01f4026a079ab0aa705933f15d84c949afa81926285ef9b077d406f490814a2c02299fae1cccf059d6eef98433aea5c495a17c287309423e3b94c3042dd5b8c96400745cf839b35ab94930b8cc985de9faf756ae39e72d107b3546f37600de4703a89eb5825c5584fdd08f0f34851dfaa9aa94dbe5e2fee486b0926a2adc18517f00b813e9a8bf599c7e43ef7639552dca8f31111ee51a7c1af7cfbdb4ab886bbfe7545d0331cff08b314fc568c5cdf4fa7b4e6aca38d315a4cf8a68f33b9e3cb7381b97a2b75e2d4d666a247329733a7bc6b5b50e54ccb1f83565ecc9861e9382ac17a706ecc75844006e81d44ccd726d0d555f178b9d3efdffccd553b4254dc943939e1fc2c6bab97c4087e514c97bbf1cef5ec6b02486a660570f826c0867f552f6e408826ab4139e99cfbea9cbb3aad71e88a994886e17b451e4e63bc1237abf3fc5a196e96729f6e04f966e61f32dd377edd0c4e542de75f5e9b96d4297fa0646046f8", "b4", "5287199851a7d5975b881c5c0e3aa9efa7ffa770921f2e5c30e784cadf1a8c95ba0ecf30441d46fad49d721eaa6e5e5ca22ce0a085e139a2ad70df666b5eaf1033517bf52a7395f00c3b020e209e82f77af7c85e7c2c1ccbdc02e57a36df25bad74a6823a26ecb9ec16818ebca138c7a9298e3bbb51f87801d7654da70bce10de778efcc1aada659235d1091a1864f0a4ed4eea3157c2d7d1b3ef01f4026a079ab0aa705933f15d84c949afa81926285ef9b077d406f490814a2c02299fae1cccf059d6eef98433aea5c495a17c287309423e3b94c3042dd5b8c96400745cf839b35ab94930b8cc985de9faf756ae39e72d107b3546f37600de4703a89eb5825c5584fdd08f0f34851dfaa9aa94dbe5e2fee486b0926a2adc18517f00b813e9a8bf599c7e43ef7639552dca8f31111ee51a7c1af7cfbdb4ab886bbfe7545d0331cff08b314fc568c5cdf4fa7b4e6aca38d315a4cf8a68f33b9e3cb7381b97a2b75e2d4d666a247329733a7bc6b5b50e54ccb1f83565ecc9861e9382ac17a706ecc75844006e81d44ccd726d0d555f178b9d3efdffccd553b4254dc943939e1fc2c6bab97c4087e514c97bbf1cef5ec6b02486a660570f826c0867f552f6e408826ab4139e99cfbea9cbb3aad71e88a994886e17b451e4e63bc1237abf3fc5a196e96729f6e04f966e61", .None}, + {.Shr, "11007065efc8180e46677ba92a504d3d06285fe4430c44456948310be426125d4ef2599a8c6dd04ff3cb1f9ee99bde3bc9271eee58332600671766aca74fc21f62cb30704ba519622e3a8c8b2fb18114afb11a7cb66d1db87f5ce9d0f6e2774d0819ec844d355b0de2f10e59c85ff9340821960f34bd29faa44ce30d4d1f3d90f46bc0748e48b782eaebd6e38aed14626e4a5b240e3ebdeebf1ccad0966f044549d5f6c672fc036724c6adbfbfcfa95d04cc9565d6ef17f1658f8d4533a181fd16413d26e43b89c0e6f9245a5b8ae3263619d1d8d1c5e206dc0bd1b3ebcf06e8187f594cd238b3204f7faa1f4c82c2aeaca5a3665083532f1eb119aae14313fd3737f635398483f21b2ad17855276d18b16abd52491418aa9c20a28ed106bb63fd5f3b00c7ed61667acf95711694d77245f41441955b0b0a0c5903ff0e490f2b934ea22c10db8a098befd01e0474d400a74dda25c82d3c5f71c375734f7bbf9c54172be30ef920f0bda5b7df426369dde7e07496fbbc0351c8b7570a316d95dbaf5a7825f7dd03eddca9251d98dee8e81d641865b74159ab8f7d7938615b2240bd6a4ba6af004ab9037bcf3d8879113d198ebdb8a6ab795da5d72411757a1c01de4ba524c3b3d01247ca4898306f1389e4e7a8fa8b96259c5bdf699456448b6f573b9b1c539779ff8dd34f840b70111bdfc6562b13908caa1b9ae9e718f282ee", "1a4", "11007065efc8180e46677ba92a504d3d06285fe4430c44456948310be426125d4ef2599a8c6dd04ff3cb1f9ee99bde3bc9271eee58332600671766aca74fc21f62cb30704ba519622e3a8c8b2fb18114afb11a7cb66d1db87f5ce9d0f6e2774d0819ec844d355b0de2f10e59c85ff9340821960f34bd29faa44ce30d4d1f3d90f46bc0748e48b782eaebd6e38aed14626e4a5b240e3ebdeebf1ccad0966f044549d5f6c672fc036724c6adbfbfcfa95d04cc9565d6ef17f1658f8d4533a181fd16413d26e43b89c0e6f9245a5b8ae3263619d1d8d1c5e206dc0bd1b3ebcf06e8187f594cd238b3204f7faa1f4c82c2aeaca5a3665083532f1eb119aae14313fd3737f635398483f21b2ad17855276d18b16abd52491418aa9c20a28ed106bb63fd5f3b00c7ed61667acf95711694d77245f41441955b0b0a0c5903ff0e490f2b934ea22c10db8a098befd01e0474d400a74dda25c82d3c5f71c375734f7bbf9c54172be30ef920f0bda5b7df426369dde7e07496fbbc0351c8b7570a316d95dbaf5a7825f7dd03eddca9251d98dee8e81d641865b74159ab8f7d7938615b2240bd6a4ba6af004ab9037bcf3d8879113d198ebdb8a6ab795da5d72411757a1c01de4ba524c3b3d01247ca489", .None}, + {.Shr, "342f626521bf1097d821d97b34b1993fbed688d3624f582e84778fa1094536a9f16a65ef87f1009a1931f543bc174b0943ac3b88d3b0c3edecf8af45f9aeb782ca3cf9cfcc9026545a377d4ed90aa95e9df8dfc4485ec7bd1256fdfc548decd15e086d87b6e634681994f8ca3886e61f92512a9a876259cb2afd192d4e0295dfe50b4437632bf8c1a6626c7412d188be408437d371cd1018c8cb8ff6cc0ff374bd8283df672f4960958ef3c6a792899815c33a66615ab9ba143a3a935bf4a877720873b173e332f8c7709b889ebf7ae16f9fccb9826634193e59719248818ec4059e606cab706e652dcc957cd61355d245ec8b3ee0913529161060f26c7044bae26a32d750459d4a0fa11e9e864c1b33ff2605f2f488ab0a026df2c06a86016f8d53f97085c7028e1d9e2b4f3a6ecc1cc8917c231e136c2f1fd1ee0ab8ad65def63d829c259c78259bc7b079c8f3699a406dc006abfe643c7b69844395b2719860714d834c32511826cb430dcec53c30482eeac53bcec08e4787ed26de827eb04f7b4c72ea67293c1f4b319e7aa258ec4a3ff8e4859334b1be76807d870e259928d408a480a0f5acfa49dd1868e3d9eb403109b0833c27d7bf908801154ea0c1e73b526665bca9d44a0208140a50be5044565db23eaeecb8297c07749115441fc4c09471f9bdcede0a20a98cac30ac56349e085c0810bff7d1f8f7190067378a", "21c", "342f626521bf1097d821d97b34b1993fbed688d3624f582e84778fa1094536a9f16a65ef87f1009a1931f543bc174b0943ac3b88d3b0c3edecf8af45f9aeb782ca3cf9cfcc9026545a377d4ed90aa95e9df8dfc4485ec7bd1256fdfc548decd15e086d87b6e634681994f8ca3886e61f92512a9a876259cb2afd192d4e0295dfe50b4437632bf8c1a6626c7412d188be408437d371cd1018c8cb8ff6cc0ff374bd8283df672f4960958ef3c6a792899815c33a66615ab9ba143a3a935bf4a877720873b173e332f8c7709b889ebf7ae16f9fccb9826634193e59719248818ec4059e606cab706e652dcc957cd61355d245ec8b3ee0913529161060f26c7044bae26a32d750459d4a0fa11e9e864c1b33ff2605f2f488ab0a026df2c06a86016f8d53f97085c7028e1d9e2b4f3a6ecc1cc8917c231e136c2f1fd1ee0ab8ad65def63d829c259c78259bc7b079c8f3699a406dc006abfe643c7b69844395b2719860714d834c32511826cb430dcec53c30482eeac53bcec08e4787ed26de827eb04f7b4c72ea67293c1f4b319e7aa258ec4a3ff8e4859334b1be76807d870e259928d408a480a0f5acfa49dd1868e3d9eb403109b0833c27d7bf9088011", .None}, + {.Shr, "652bb618e419f470a1ea1e79c5eded5b8397d79736fabfe4d254f93a2d2db348b3b5258bda545924243b94726b1c14e29fc91af30a856802dcabadb3a4d1b8175e693a49a554f2f59c21fb7cb872268d5c105ec23c96bf641c5d5dc3a6ce26d60a868e44b9ef65adafe3ee302ff5f7f20aea6bd27b2909b21cbcd4aaa2124e3ea051345343e009d39c83a0822c46619754814d1eb6fc2f6632f66d720d871c456ef67bf6be78e7c9d496ff62fb690d6c6443797e196b874b29ec874aebb8a61c650f7b9fc83933b4985b17a5ad0e15936925af088349f33ae0dae515226cfbcc180278a93eb3626b99d00562254bf8a10907194f08966cb81a3fd83c21669773b5a9511c74e076c2489d12c40f6362a4b5f83a810a6cb9ecc9f26dcaaf97bf6ccb61e9b5983f4d86764ffa1c3f71a58f4b148829c54b8edef783e535d6b35f2e79def6cfe501ebe158d6f33911e0c51bd9665296beb87bf272a357fb7725872c1c0148a047942cb71f3a6e4d2f7d6f1fea4be10cd129c3675345d8e9834374ecafdd2ab2c57a3086b6ef0bc0ddec88ae60e887e1099bd3dfc47878bbcf03421573aaecc42c152447c10041513fe9fcfd5d4cf02814bcd92a51222f4bc28a90ff1d817d4fe681dccc50d35e2b31a845f4713c3ab81fd03f250ec9de100f9123b02ce5af01dec32108e3d9dc8fa28d972de88d7e6d9ffbeff7d5ac702811e23cf8", "1e0", "652bb618e419f470a1ea1e79c5eded5b8397d79736fabfe4d254f93a2d2db348b3b5258bda545924243b94726b1c14e29fc91af30a856802dcabadb3a4d1b8175e693a49a554f2f59c21fb7cb872268d5c105ec23c96bf641c5d5dc3a6ce26d60a868e44b9ef65adafe3ee302ff5f7f20aea6bd27b2909b21cbcd4aaa2124e3ea051345343e009d39c83a0822c46619754814d1eb6fc2f6632f66d720d871c456ef67bf6be78e7c9d496ff62fb690d6c6443797e196b874b29ec874aebb8a61c650f7b9fc83933b4985b17a5ad0e15936925af088349f33ae0dae515226cfbcc180278a93eb3626b99d00562254bf8a10907194f08966cb81a3fd83c21669773b5a9511c74e076c2489d12c40f6362a4b5f83a810a6cb9ecc9f26dcaaf97bf6ccb61e9b5983f4d86764ffa1c3f71a58f4b148829c54b8edef783e535d6b35f2e79def6cfe501ebe158d6f33911e0c51bd9665296beb87bf272a357fb7725872c1c0148a047942cb71f3a6e4d2f7d6f1fea4be10cd129c3675345d8e9834374ecafdd2ab2c57a3086b6ef0bc0ddec88ae60e887e1099bd3dfc47878bbcf03421573aaecc42c152447c10041513fe9fcfd5d4cf02814bcd92a51222f4bc28a90ff1d817d4f", .None}, + {.Shl, "2662cd5a7037c1d5216aa5a61b2a1af76483fed3fdca876326b3681b225dd29aa0d53818e878d7ae00306f84ec2812f4fee3103dd4c90d3eb74bb1ba3e3d4be49d68e7309fb811a52e3c86e6d5ddaca303d56424ab5cdb50e13363d09355d8b1722035e907d2f4305c7b376168bce40575f5b637890a1cd9c3b1f868608c57e74c25896222eb977218fd5148720c611be8a04b7dee8ff5f4eae7ad50b281201f006f289d047c665b84aefbf7ccf322ddc20a119488e2636ac1af6f58c9b7b743ddf69f2dfe25f8b15684963b1dce6824241ccdb0d70243bfbf6d6196ecbc3f57f329803a3c65edb6a2e57f06c540012c219a4813b5ec7103d5854243ea54100522f361e6d529c8732adc373ed8b096aabfdd6c29068b3922510260252fe00fbd9fa26410adfd2482b985e40b670f8b280a4830e9f15bfb89adb6a8bd69fb2dfba85e08df2a4a921941f07c824137f9b0b50a14803d374c81c533095cfcfd888206fe639cef188447abb1e1b43fea72156df471cfa240a552bf5cef9123f60ea07e9d677ab4538c924dcebc056fa64580b9a78016447d1a746c9b1c5f600209402c3e61940f11b7112115dddb22ebefeee362912733c1ec92ddb8fe885539f46ccdd44cc1babb014221ef3a09a58d20ccbf4fc4eec0445e088f7b187e274f2f50ddc5baea88dc975070b733a0d40c5cb0649b5e0823a8097ec0e4623bff79e6d0", "45", "4cc59ab4e06f83aa42d54b4c365435eec907fda7fb950ec64d66d03644bba53541aa7031d0f1af5c0060df09d85025e9fdc6207ba9921a7d6e9763747c7a97c93ad1ce613f70234a5c790dcdabbb594607aac84956b9b6a1c266c7a126abb162e4406bd20fa5e860b8f66ec2d179c80aebeb6c6f121439b38763f0d0c118afce984b12c445d72ee431faa290e418c237d14096fbdd1febe9d5cf5aa16502403e00de513a08f8ccb7095df7ef99e645bb8414232911c4c6d5835edeb1936f6e87bbed3e5bfc4bf162ad092c763b9cd04848399b61ae04877f7edac32dd9787eafe653007478cbdb6d45cafe0d8a800258433490276bd8e207ab0a8487d4a8200a45e6c3cdaa5390e655b86e7db1612d557fbad8520d167244a204c04a5fc01f7b3f44c8215bfa4905730bc816ce1f1650149061d3e2b7f7135b6d517ad3f65bf750bc11be5495243283e0f904826ff3616a1429007a6e99038a6612b9f9fb11040dfcc739de31088f5763c3687fd4e42adbe8e39f44814aa57eb9df2247ec1d40fd3acef568a719249b9d780adf4c8b01734f002c88fa34e8d93638bec0041280587cc3281e236e22422bbbb645d7dfddc6c5224e6783d925bb71fd10aa73e8d99ba899837576028443de74134b1a41997e9f89dd8088bc111ef630fc4e9e5ea1bb8b75d511b92ea0e16e6741a818b960c936bc10475012fd81c8c477fef3cda000000000000000000", .None}, + {.Shl, "-65e61ca0526f9507cea023f1ccfac3d67c58cc51268a3462cbf8bccdf6fcce18e34988cb109531c11fa39448fcb106812e1eceb8174cd14e156c96853e4029f43c7f9aa0d93c810d672549cd9f80dda46a2572508e96526fe8471c96c30a26b7a09a9f6c014951537c32014140f1ce9019b4f65b3220b5744a39cf2d166496bcd87e86b43e4a4dfee1672b4be1118756f3a08c2133c6f17779e6ae1e9f4999b8762b2d7a0cb40f24aad50e21adef82bf2c9062eb83ae25320a7fc7ba98c8d2bd652cfe74f94fd937aa0f7384b94c412ee44294356feafd11b3717bf6226fd2526e3cabe39b6f95153f87667b887401e81cf2f412f4dcbcf9e25dc09da74c9c15492fbf1bef5500fde0c5c0bbabc198326b1b2d989c93763de0f741b8a64e80730e51c48132deb519f6ff12d154d1cf17c818412aa102d1a03a7d7c75b93265a1fb5f14a3e026f48d617dacd6a31f8d466b3abb710ae52d32a91ba62b59d89eeea4ab983db1157365a9a42ea0348025bc2449ec18b8517f7e06d05ec103a39f0079a4b87f5c831b555c4203e6e643e1a34ac6c27e6565d939d7361e4b5bf60ce715f21964980e9ac84a92512ec94c96e611a88c557eae31e65714117d0cdfe162581942393cef7382ad758cc19d97eb494422a27a757a088884147e0ca621738be16f5a7ac81fb7e471393ff5ddfe6986c2738fa7180895c0de44dec2471bce8d", "2b", "-32f30e502937ca83e75011f8e67d61eb3e2c662893451a3165fc5e66fb7e670c71a4c465884a98e08fd1ca247e588340970f675c0ba668a70ab64b429f2014fa1e3fcd506c9e4086b392a4e6cfc06ed23512b928474b2937f4238e4b6185135bd04d4fb600a4a8a9be1900a0a078e7480cda7b2d99105aba251ce7968b324b5e6c3f435a1f2526ff70b395a5f088c3ab79d0461099e378bbbcf3570f4fa4ccdc3b1596bd065a0792556a8710d6f7c15f96483175c1d71299053fe3dd4c64695eb2967f3a7ca7ec9bd507b9c25ca6209772214a1ab7f57e88d9b8bdfb1137e929371e55f1cdb7ca8a9fc3b33dc43a00f40e797a097a6e5e7cf12ee04ed3a64e0aa497df8df7aa807ef062e05dd5e0cc19358d96cc4e49bb1ef07ba0dc532740398728e240996f5a8cfb7f8968aa68e78be40c2095508168d01d3ebe3adc9932d0fdaf8a51f0137a46b0bed66b518fc6a3359d5db885729699548dd315acec4f775255cc1ed88ab9b2d4d217501a4012de1224f60c5c28bfbf03682f6081d1cf803cd25c3fae418daaae2101f37321f0d1a563613f32b2ec9ceb9b0f25adfb06738af90cb24c074d642549289764a64b7308d4462abf5718f32b8a08be866ff0b12c0ca11c9e77b9c156bac660cecbf5a4a211513d3abd0444420a3f065310b9c5f0b7ad3d640fdbf2389c9ffaeeff34c36139c7d38c044ae06f226f61238de74680000000000", .None}, + {.Shl, "db039c77f956b67247c6fc73a129bd8bfcd5f849097959a75e1721fdbd8389031cd29c389425301b27934e6251105197ac91e6e74e25ea87139520865b79d0db9a67293807553b392c09cd25e213b8e2a5ba5934ffb4705c2a36c7bd7f3c72def7a9946bf40e8ac1011240610f118f4fe4359d17c427885f59f127564e6d70d72b6113904f8eea6c8b296f5bcbc0205653eb0d93da418f6e64ea1f0ddb3d2f0a6e2c237a9ae70d4fe8e9d22dbaee4fdcbad63ebd9d25a02ead6ff4c987941839258be26309b84f1f6106193e9d383a3d66a386d08a32a7196610f6433cf04e1b8f6c677017dda8262693a2c0d59c5aa17fd589c653e9e1389b296af32214d21571e420dfb04a8002cbbcfa825e83a03683bebda52b1a6f548e2e973fdeb56afd2e72d16d621771fd53509ce0a3b91383fb09543e839d87c20a5401d378114939257f738ec2036e629b3578f710e92d70c137cf4e7c16e8b58d61c57d9ec9520e209e2c67420846fd89c33639d4e2e2c103d7a684d2d3dc1a67309991465b9ad789877e90aef4fcb4f2c52bb38379a431fc74310a756b39ca7b11c05b1d75a179765a0a04953abe6480295ab42c660b8601845c106d288c9b1aabc3e60cdb3264a79e17916f4ef439b05bfc5df5f554638854c3a3f3c96b039bff7ea1795b9dfe8a03de3c5ded766572b0979e3dbc0baba055fd4372bff2927b7cd7edf67241ca", "2a", "36c0e71dfe55ad9c91f1bf1ce84a6f62ff357e12425e5669d785c87f6f60e240c734a70e25094c06c9e4d39894441465eb2479b9d3897aa1c4e5482196de7436e699ca4e01d54ece4b0273497884ee38a96e964d3fed1c170a8db1ef5fcf1cb7bdea651afd03a2b04044901843c463d3f90d6745f109e217d67c49d5939b5c35cad844e413e3ba9b22ca5bd6f2f0081594fac364f69063db993a87c376cf4bc29b8b08dea6b9c353fa3a748b6ebb93f72eb58faf6749680bab5bfd3261e5060e4962f898c26e13c7d841864fa74e0e8f59a8e1b4228ca9c659843d90cf3c1386e3db19dc05f76a0989a4e8b0356716a85ff5627194fa784e26ca5abcc88534855c790837ec12a000b2ef3ea097a0e80da0efaf694ac69bd5238ba5cff7ad5abf4b9cb45b5885dc7f54d4273828ee44e0fec2550fa0e761f082950074de04524e495fdce3b080db98a6cd5e3dc43a4b5c304df3d39f05ba2d6358715f67b2548388278b19d08211bf6270cd8e7538b8b040f5e9a134b4f70699cc26645196e6b5e261dfa42bbd3f2d3cb14aece0de690c7f1d0c429d5ace729ec47016c75d685e5d968281254eaf99200a56ad0b1982e1806117041b4a2326c6aaf0f98336cc9929e785e45bd3bd0e6c16ff177d7d5518e21530e8fcf25ac0e6ffdfa85e56e77fa280f78f177b5d995cac25e78f6f02eae8157f50dcaffca49edf35fb7d9c907280000000000", .None}, + {.Shl, "c96078b0ee602308f6657e8b720e4f1c95042cd99f2f5a57dc887f64acc383c7321e5753fb53819fac7319f1cb3b6ae12f7c2c7b128047fc11138e4895ca17a8d4269fdcb06d33cf1c88df759cedc6680c9bee82cb6145a627d73ffea55ea51dbbbfe09b9964b35c6e789f18ccfc11ab4bc12710f5e641e518c5c36bea90b9d844db4863e1e2086fdb26c9ba14e5114c54c77b08bd4c829ea9301453ced2ac6aab000ac88265098f8f267d4de5f67f488c20d9faa69a942c26cd98cc6d31e0e7a81a5de4cfd7200b73009f5aad314dc19ec35cbdb5d14c5d6fbd611e229489a233dd95c48b711fe64f2c588f50e265a8488bd7ae6a2f04e5f4388c384bfddd24c89f12abb34e2b5fa76ca5189e5b8b4afb81fd16001a8a72dbbb2aebdbc6c3b9c8565f15b4e584ac6b6932af3bdad1fb39e5d1812ed532f09d5026b9a65def1faaa70aa2f1e651db81485e2a83b4322f9e6b79d45ab1077fb3ca5dbad5f8e15e2914b971fe80fce3b092ac5cd9e2927a9c53d7ec8572438fba1879e88a51ae956ac1c7058cbbdec5858b633ca0ef7e39733b56e70ae0c00f26a0e8d6137d2bc8d10b9d8141cc214a9f7fedbb0c0250a562fe0b349f74ef3143833c8459b177defb5b5850d26173105b61fcdd68251a36f26d0e52ffc67797260ca3e4bf574c3b6728d177a6a392f12dc4a6232305104703980a2244d9a724095533c9a8c28697", "4e", "32581e2c3b9808c23d995fa2dc8393c725410b3667cbd695f7221fd92b30e0f1cc8795d4fed4e067eb1cc67c72cedab84bdf0b1ec4a011ff0444e392257285ea3509a7f72c1b4cf3c72237dd673b719a0326fba0b2d8516989f5cfffa957a9476eeff826e6592cd71b9e27c6333f046ad2f049c43d799079463170dafaa42e761136d218f878821bf6c9b26e853944531531dec22f5320a7aa4c0514f3b4ab1aaac002b220994263e3c99f53797d9fd22308367ea9a6a50b09b366331b4c7839ea06977933f5c802dcc027d6ab4c537067b0d72f6d7453175bef584788a522688cf7657122dc47f993cb1623d438996a1222f5eb9a8bc1397d0e230e12ff77493227c4aaecd38ad7e9db29462796e2d2bee07f458006a29cb6eecabaf6f1b0ee721597c56d39612b1ada4cabcef6b47ece7974604bb54cbc275409ae69977bc7eaa9c2a8bc799476e052178aa0ed0c8be79ade7516ac41dfecf2976eb57e38578a452e5c7fa03f38ec24ab173678a49ea714f5fb215c90e3ee861e7a22946ba55ab071c1632ef7b16162d8cf283bdf8e5cced5b9c2b83003c9a83a3584df4af23442e76050730852a7dffb6ec300942958bf82cd27dd3bcc50e0cf21166c5df7bed6d61434985cc416d87f375a09468dbc9b4394bff19de5c98328f92fd5d30ed9ca345de9a8e4bc4b712988c8c14411c0e60288913669c902554cf26a30a1a5c0000000000000000000", .None}, + {.Shl, "-8c230243ae48c4aa7594d77140d1b793ecbdc2af18bba777d0c3c89312b7a1fa34ccd025bb970364023998a39c1960aa0bcfdb67378363f10ddb2eaa8e4991e44a6d20372d80dd56919fe0dbadce06ee1d2fbb45be07ebe2fcd9b6e122fe3232a83e5fad2f8cd5d7dba5c226efebc0f1eb3a31cb68201b8d81a6b2e1012fc9f6f486c1d543f529793a39eebcdd904265b4ac42af8dc67ae518d45eb2c0640617bad53019213c08ef72eb2ffd75ec761f8b8857eb0abb5948d429b4ac72b0b6a000fd0bbef38e998c8885b8d3cf667b286d9dff9eea49aa20fbd2c4c377cef4a7902c825c9780ee32c8b9115e698249d5058e2323bb83b3e662c655c20f931f02e632623ea1ad82575a1284579b0a10f88811eedcf81113e0014694d0532bb64c0c7cdc76c190a1be76801df8fa8e772335a6ea589ff8345eca6dc62020a3a95de6a4ea1e9ad5bb1b2275208ae58c7ebdfefc242c06875f5f3c5fd1aed2471f2173c40b71c8a65a60889c7567d51ab58cd68feefe8b718c59d2a57f3eff49c2a9de2fb9a660a97129223aea3c1413cd3915359860a99892ecabd68a6c5a2652efd2edc51b33211be8e29c70faa2d0527d65d3b465fb2ec1aa5c81398fc55957301388cb040caccc1064426c3d11806de8e2e5b4909cadfca3b35315f47d05c5ab9df960c6e09d3ebddcec1ec14816128d0affdc66afea53fd386a1a40e5561f31", "4f", "-46118121d72462553aca6bb8a068dbc9f65ee1578c5dd3bbe861e449895bd0fd1a666812ddcb81b2011ccc51ce0cb05505e7edb39bc1b1f886ed97554724c8f22536901b96c06eab48cff06dd6e703770e97dda2df03f5f17e6cdb70917f1919541f2fd697c66aebedd2e11377f5e078f59d18e5b4100dc6c0d359708097e4fb7a4360eaa1fa94bc9d1cf75e6ec82132da562157c6e33d728c6a2f596032030bdd6a980c909e0477b97597febaf63b0fc5c42bf5855daca46a14da5639585b50007e85df79c74cc64442dc69e7b33d9436ceffcf7524d5107de96261bbe77a53c816412e4bc07719645c88af34c124ea82c71191ddc1d9f331632ae107c98f817319311f50d6c12bad09422bcd85087c4408f76e7c0889f000a34a682995db26063e6e3b60c850df3b400efc7d473b919ad3752c4ffc1a2f6536e3101051d4aef352750f4d6add8d913a904572c63f5eff7e12160343afaf9e2fe8d769238f90b9e205b8e4532d30444e3ab3ea8d5ac66b47f77f45b8c62ce952bf9f7fa4e154ef17dcd33054b894911d751e0a09e69c8a9acc3054cc497655eb45362d132977e976e28d99908df4714e387d5168293eb2e9da32fd9760d52e409cc7e2acab9809c46582065666083221361e88c036f47172da484e56fe51d9a98afa3e82e2d5cefcb063704e9f5eee760f60a40b0946857fee3357f529fe9c350d2072ab0f9880000000000000000000", .None}, + {.Shl, "-ecb690041b9212903a228473e21bcae9c40d7a4fb8d761c57af93f044bfd325f3093ef170cb23e01277423691a93586237e9f4e31aaf46dbbe37782c2ba43da818a47356ccd8aac06528b433529fa7bd37f07427ef3240cce5adcc52a049e61343edd18d24de115998ae84cdeefc2e960ed0adc3b659a8508ada442a46669bf03bd45bc8cbec196c2d1f17502fe2cd395efe53b8613d580ba61be0d1cd232c2fb688372524914f6332f22e686ce1f614907e28b6855138a8b6d1116ec5d981aa7e299c606c5eb1bc196f73a940b0a43ff4db077c06f8c5b6d17057970094b01928a3f4009a342f7f21ae2a614c4c10bcf02865a8f2df6afe699f255c98d86b4a6de06ab84e1e46d9b090f55a24538cfdf47be5e76d86c887a6604eb114f7868878893cd57621d95eed678850b5c24f817cb2ad34838254dc6092308b101d2c795c925005f633ff8bd96e368071116b4e70f5273197af6fa44e484ce41c2fb7873f62c8499bd42484e416d5120513e4dd638026ce3a481b47cbe45459d11dabb6b727be9ef3511e00aeadbb106e244dfd1d0f16a842c8bad73b11b398de6527d015b0d3220f5a72bb76b47614d55b0e7651958e0b2f6269b8ab159bae0ced1a0c0e45938f5f17fb87162d080fb7e07daf03a67195e8516666366a5c6ee14bf7fdaf255ea793d5d0a22c93c47349c07d69fac79b8f8bd25bb68a8c1daa339d78ce", "62", "-3b2da40106e484a40e88a11cf886f2ba71035e93ee35d8715ebe4fc112ff4c97cc24fbc5c32c8f8049dd08da46a4d6188dfa7d38c6abd1b6ef8dde0b0ae90f6a06291cd5b3362ab0194a2d0cd4a7e9ef4dfc1d09fbcc9033396b7314a8127984d0fb746349378456662ba1337bbf0ba583b42b70ed966a1422b6910a9199a6fc0ef516f232fb065b0b47c5d40bf8b34e57bf94ee184f5602e986f8347348cb0beda20dc9492453d8ccbc8b9a1b387d85241f8a2da1544e2a2db4445bb176606a9f8a67181b17ac6f065bdcea502c290ffd36c1df01be316db45c15e5c0252c064a28fd00268d0bdfc86b8a985313042f3c0a196a3cb7dabf9a67c95726361ad29b781aae138791b66c243d568914e33f7d1ef979db61b221e99813ac453de1a21e224f355d887657bb59e2142d7093e05f2cab4d20e0953718248c22c4074b1e572494017d8cffe2f65b8da01c445ad39c3d49cc65ebdbe913921339070bede1cfd8b21266f509213905b5448144f93758e009b38e9206d1f2f9151674476aedadc9efa7bcd447802bab6ec41b89137f4743c5aa10b22eb5cec46ce6379949f4056c34c883d69caeddad1d853556c39d94656382cbd89a6e2ac566eb833b4683039164e3d7c5fee1c58b4203edf81f6bc0e99c657a1459998d9a971bb852fdff6bc957a9e4f574288b24f11cd2701f5a7eb1e6e3e2f496eda2a3076a8ce75e338000000000000000000000000", .None}, + {.Shl, "68900427fce083bc114c0c9e6f205b7f255197c1e434772b41be8268378979b99c7497f1d8262a945ec73db5be1fe245a156694eefd1f113731fc652cdaafde0efe44646570cf2065901f871fd4585b05a5e21570e40c9b68e4fd679464a30e3b1852a1352f4fe210b8a6c225ff95050c9fba30298928a782cc9cd476c8df8f2b1a13921696224e18c02f21e674ad7927a760895850aad2675542694b0a65c4bac34b3bc563c9d11431e3ab868108b042f30b1521467cf8a19573c4e9f4bab2a693e4dba1b5530b543023f71f87c7900894428eaab6aa34a4dd958ec92f35af70df4720c3b9265c6d9350ee1b3c9ddb504ded32f89e9eefc3a5f62522393ac525ddb06d460c68d7c902d59f2360794b3031b5956c510108f7f2fefaafa9f4334d75c86065551932a18b1ade29e8f58875ef06ce84ed6a5f86e36a6667d936f7a1b910464b25cacd7c9f5016fc133a76eeafc346e43dd00520be6f3d5f6b1b1cfdbccb07617eb9484adbbfdc3b5e22d7fd6b1e1ccf0cba32a4c741ff562bd75672c5911c125eff6d1c1d74c7bab8c9ff616bbcf558b43e771a55d8240eec72d02458c46360744b579329ddc27b008e7c4efab9f410a325eeb6cf23020d400755319e309105ec01af6289662bca9231b0c4c79bcd8100e047b14acddb41968464c937dc6528cd01d5c91ffe40b4c56363f4fbda1bd9fff2691792cb8860cb667b5", "41", "d120084ff9c107782298193cde40b6fe4aa32f83c868ee56837d04d06f12f37338e92fe3b04c5528bd8e7b6b7c3fc48b42acd29ddfa3e226e63f8ca59b55fbc1dfc88c8cae19e40cb203f0e3fa8b0b60b4bc42ae1c81936d1c9facf28c9461c7630a5426a5e9fc421714d844bff2a0a193f74605312514f059939a8ed91bf1e563427242d2c449c31805e43cce95af24f4ec112b0a155a4ceaa84d29614cb89758696778ac793a22863c7570d02116085e6162a428cf9f1432ae789d3e975654d27c9b7436aa616a86047ee3f0f8f201128851d556d546949bb2b1d925e6b5ee1be8e4187724cb8db26a1dc36793bb6a09bda65f13d3ddf874bec4a4472758a4bbb60da8c18d1af9205ab3e46c0f29660636b2ad8a20211efe5fdf55f53e8669aeb90c0caaa3265431635bc53d1eb10ebde0d9d09dad4bf0dc6d4cccfb26def4372208c964b959af93ea02df82674eddd5f868dc87ba00a417cde7abed63639fb79960ec2fd729095b77fb876bc45affad63c399e197465498e83feac57aeace58b223824bdfeda383ae98f757193fec2d779eab1687cee34abb0481dd8e5a048b188c6c0e896af2653bb84f6011cf89df573e821464bdd6d9e46041a800eaa633c61220bd8035ec512cc5795246361898f379b0201c08f62959bb6832d08c9926fb8ca519a03ab923ffc81698ac6c7e9f7b437b3ffe4d22f259710c196ccf6a0000000000000000", .None}, + {.Shl, "2877e5ebeb6769642ddcc4a7adafc812dea12c12db54745f37ae1a86a45dd481f69b28643137e904bc77ca96bbfbbedb06099258e3b43d377dcd52990be0179dc5fa44eb020dfa6f522215bf816bdb3c8c17988debb862ab5ea40c11808a99432447e3bb383f4518e0318821b39c49f4d824799c502858eaed06279246c7183ef41af0f2f831f9f95d2921ed70e69bd429d0bc1637461cb9c2c8e020527d12eea6283001ec2fcb5709c182fbff83cf01ac03d0fa9debd1b20efc8eeafd875f16b92c9691e5e770e5aaf40e6dd8c1b0d679c30bd5e0db192e3a7de66ae799df6c2c445d9003bde9a7d1dc4d9518c586a9b3968aa9ac6c9b20df126573ee39afcc6ac3d248be5e44fabc46181c3fe839cea4f4f6a2e1a1744d4216423f937dafa28cc538c8cd9bf0b95a8e660b4d0ef147ca4726bbdd20300952377a3f93f10c51cbd8235f8c7b1ac3f18790264ae3105f5c1a872224672e3cd139a6c0634888d3d6a73d6a68798ab20d61bb3b8b9a121d127809b794efd43074bdafb452494f5cf5b37c7606fc28041eaf3974b81800d8dee1e9ee05b0981d5e06b189e537a20efa02d8882ea47d09ce5e0b70dd9f953bde5b596b0869747c2eddd75c6613919f11cf2bb3365798ef53a8e3557f11262950d7b4fcbec3b1989d04bb42d0b3569107f3cb12afcce3e04eeaf08724f18e2039a478c943932970de7e4570ec8987ab", "29", "50efcbd7d6ced2c85bb9894f5b5f9025bd425825b6a8e8be6f5c350d48bba903ed3650c8626fd20978ef952d77f77db60c1324b1c7687a6efb9aa53217c02f3b8bf489d6041bf4dea4442b7f02d7b679182f311bd770c556bd48182301153286488fc776707e8a31c0631043673893e9b048f338a050b1d5da0c4f248d8e307de835e1e5f063f3f2ba5243dae1cd37a853a1782c6e8c39738591c040a4fa25dd4c506003d85f96ae138305f7ff079e035807a1f53bd7a3641df91dd5fb0ebe2d72592d23cbcee1cb55e81cdbb18361acf38617abc1b6325c74fbccd5cf33bed85888bb20077bd34fa3b89b2a318b0d53672d155358d93641be24cae7dc735f98d587a4917cbc89f5788c30387fd0739d49e9ed45c342e89a842c847f26fb5f45198a71919b37e172b51ccc169a1de28f948e4d77ba406012a46ef47f27e218a397b046bf18f63587e30f204c95c620beb8350e4448ce5c79a2734d80c69111a7ad4e7ad4d0f315641ac376771734243a24f0136f29dfa860e97b5f68a4929eb9eb66f8ec0df850083d5e72e9703001b1bdc3d3dc0b61303abc0d6313ca6f441df405b1105d48fa139cbc16e1bb3f2a77bcb6b2d610d2e8f85dbbaeb8cc27233e239e57666caf31dea751c6aafe224c52a1af69f97d8763313a097685a166ad220fe796255f99c7c09dd5e10e49e31c407348f192872652e1bcfc8ae1d9130f560000000000", .None}, + {.Shl, "e33f249be51e6411ed411976186db462f14b9a6533a470ce7f8d8bbecc3aaffc29e2ec778effa977bf83ab56b84a9859db8984aa3a29e0752ebb3f071934a3cfe5d01bb869db8b3c824340139acbcd8011a1da259f89c6a7d804d2f25bf19f540d0b4d0be4b34417e2a7e8e0badc0289438ae0b1c526a887c72952abfb9ab7ade65cb717ac4ca6e99e3c7c5d186273002cce54c4f3ef82c2362927a4c4428b433e166958f9a8f98149d12ca7c15365418a9eda9da7ef40b2cc22fc971a517f09107cee338ae75d52d04532461ffe36ce6bd8e189dbc9f8d002edc57993d8383f6910df434220488397c5b8d30f8311d38908b39a2199cefdf5866c128f440aef4a914a01c67097a6fb79208622c687dc6617d728ebabca0be92a865c6dd932327b0a71f30a1aa4a32b790484a3f89e50edc7c916175f069ea2e9b1eb8cab19f1d8daca143d6bee9e5b558753a14c27d6078fac030df330ee71e153af1012c81ce0518ec4896ff0f5c2637e8fdfbfe227d5b55be9fb84ceff09ba45e0871f9ac518fe1626730c7c580045937bb4ab38c5ee9b8c939473035f3a588f50b0611aeaefaa541ab50a6bf4bda757810d7f624ab3172bc70578524401e28a15e7dbefaa9ba8a00884fc589420cb466340c333142b7268c86ea4b700c2ae4918713c4aaa0fe49391bfdbfd46a6512e708bf6f885ad6c0a86dd41b98264f3cea518510f0a", "51", "1c67e4937ca3cc823da8232ec30db68c5e29734ca6748e19cff1b177d98755ff853c5d8ef1dff52ef7f0756ad709530b3b71309547453c0ea5d767e0e3269479fcba03770d3b716790486802735979b002343b44b3f138d4fb009a5e4b7e33ea81a169a17c966882fc54fd1c175b805128715c1638a4d510f8e52a557f7356f5bccb96e2f58994dd33c78f8ba30c4e600599ca989e7df05846c524f49888516867c2cd2b1f351f30293a2594f82a6ca83153db53b4fde81659845f92e34a2fe1220f9dc6715cebaa5a08a648c3ffc6d9cd7b1c313b793f1a005db8af327b0707ed221be86844091072f8b71a61f0623a71211673443339dfbeb0cd8251e8815de952294038ce12f4df6f2410c458d0fb8cc2fae51d7579417d2550cb8dbb26464f614e3e61435494656f2090947f13ca1db8f922c2ebe0d3d45d363d7195633e3b1b594287ad7dd3cb6ab0ea742984fac0f1f58061be661dce3c2a75e20259039c0a31d8912dfe1eb84c6fd1fbf7fc44fab6ab7d3f7099dfe13748bc10e3f358a31fc2c4ce618f8b0008b26f76956718bdd37192728e606be74b11ea160c235d5df54a8356a14d7e97b4eaf021afec495662e578e0af0a48803c5142bcfb7df553751401109f8b12841968cc68186662856e4d190dd496e01855c9230e27895541fc927237fb7fa8d4ca25ce117edf10b5ad8150dba837304c9e79d4a30a21e1400000000000000000000", .None}, + {.Shl, "-e1b31adc3e6545e583a737e25243660822a73850cae4c38fa7f21abb614a11cd87fbc01f92bd1675a9979a0f4612a6ae337c7d99f333ce71e02236901185f8eb5100f248ec4d35e881ee8e2806a4907a00dd62bc51af472150685961fe34fd3000f9cc74f122f2e68c34445c035bbaa052cd55fa04833788b06cb1b5b6405be5af76029da9e0e4188050288ee418268717d480a49e3694486419ae167375a61c6bfc4a313b1d98b6d9acf47be13c8d309721de6d7354a718f0347e1017d99065e0bbfca886273b61eb8b58b49dc0a4a9d51fd48b6bb66d276430e710dda9094bff03a50fc97d5bf0be673c204946b39e127aa12b00cd199e2c035456d54aaea97753f95bd711528de38aa235441e21d6d5cecb8dcc8eead15ec74364d8a78d0dada9d0a2fac40aeb2efc838db28039dd3af9bf027dfe17a1addbc260c89f35962cd73a73d0cd78e4d08f4869db16af72e76a4603ac59dcfce5cd35cabb2f63dc17910f63e0229e065095305f00ebb79b811f005feb97e35b1bd46becb61772762c5b66bd75d824ac62a9cd4b4961ffa91c94f448b85a5d88db18456f0adb9c9681a2bb962ea6d3322117b82dee1fc8de35a0ebab753870eae1c11b95afdf9810ee38ae0508c9802838f4fce003a1b7a4ff119138c9c5a165affd4d01fa7a682b2ba8fe832d53e2a45d98e14147f6a293e8fb354b3c479addeff0cf85106e6733", "54", "-e1b31adc3e6545e583a737e25243660822a73850cae4c38fa7f21abb614a11cd87fbc01f92bd1675a9979a0f4612a6ae337c7d99f333ce71e02236901185f8eb5100f248ec4d35e881ee8e2806a4907a00dd62bc51af472150685961fe34fd3000f9cc74f122f2e68c34445c035bbaa052cd55fa04833788b06cb1b5b6405be5af76029da9e0e4188050288ee418268717d480a49e3694486419ae167375a61c6bfc4a313b1d98b6d9acf47be13c8d309721de6d7354a718f0347e1017d99065e0bbfca886273b61eb8b58b49dc0a4a9d51fd48b6bb66d276430e710dda9094bff03a50fc97d5bf0be673c204946b39e127aa12b00cd199e2c035456d54aaea97753f95bd711528de38aa235441e21d6d5cecb8dcc8eead15ec74364d8a78d0dada9d0a2fac40aeb2efc838db28039dd3af9bf027dfe17a1addbc260c89f35962cd73a73d0cd78e4d08f4869db16af72e76a4603ac59dcfce5cd35cabb2f63dc17910f63e0229e065095305f00ebb79b811f005feb97e35b1bd46becb61772762c5b66bd75d824ac62a9cd4b4961ffa91c94f448b85a5d88db18456f0adb9c9681a2bb962ea6d3322117b82dee1fc8de35a0ebab753870eae1c11b95afdf9810ee38ae0508c9802838f4fce003a1b7a4ff119138c9c5a165affd4d01fa7a682b2ba8fe832d53e2a45d98e14147f6a293e8fb354b3c479addeff0cf85106e6733000000000000000000000", .None}, + {.Shl, "-96deab73d83c25279e3f74d7d3d050acee29bc444746b775b8cf4d6a8d824ed128cd7c5136ba5442a5f5aaf4fb2b9eb861315bd97aa68f9c7b070834b6aa182b6e897f6a5c0c81c63e2c8c774bbff3f28377cd3ed9035a372d69484f7a3e34a4167dac15b22c929d4235418fa602e825783f7dc2c5dd391148c13ca8d7483187ba3de173be6743384cd0a2c2400c0f0a2544e9be57528e6ab929a576e7f722edf64195052056bd29c348c22c175264e826966143fe305fca4cf6c04e5869b281b547cbb3526eb9391ea9d112854cf3322e8a88456558099c18e0786ed77c9cc44d9f33619a26d4ca838fe6c45e0bf56000c6188a99880cda2c7fbf8b6d67369045fe2a078966233d9e85d88e74cb4f94fc0dfca79f2b08eff7edf1b0af80c792e1447e9289386447e80c795aeb3b0eb789ef97333932619ff01e4bc6389a7eb24f5329ccf91b155eb596fa6c14f58592636d53473d229efd5f70c4e3034a17d926b4d6d75d71081b02bc1fa0e2993e48e94c2cfd82d6a25c12cf9c4148d5270eed2fa690325bfd434f6c4b87b797e1f87ef408fd617a2baec0fbd196b5023deb3b2b37bc9c08a9c7006a43ffa5ae142f7dc1bbbd2f73b3b9fb2137632fca265d4e4b1f80e0fb8ce5cd65a2cedaaf6b7278023edae9400fb311aa4018b41575492ba13a4b8d4adbd7348b7ad66199b7e5a28773ba1317cf5e702a4c8256b35155", "37", "-4b6f55b9ec1e1293cf1fba6be9e828567714de2223a35bbadc67a6b546c127689466be289b5d2a2152fad57a7d95cf5c3098adecbd5347ce3d83841a5b550c15b744bfb52e0640e31f16463ba5dff9f941bbe69f6c81ad1b96b4a427bd1f1a520b3ed60ad916494ea11aa0c7d3017412bc1fbee162ee9c88a4609e546ba418c3dd1ef0b9df33a19c266851612006078512a274df2ba947355c94d2bb73fb9176fb20ca82902b5e94e1a461160ba93274134b30a1ff182fe5267b60272c34d940daa3e5d9a9375c9c8f54e88942a6799917454422b2ac04ce0c703c376bbe4e6226cf99b0cd136a6541c7f3622f05fab000630c454cc4066d163fdfc5b6b39b4822ff1503c4b3119ecf42ec473a65a7ca7e06fe53cf958477fbf6f8d857c063c970a23f49449c3223f4063cad759d875bc4f7cb999c9930cff80f25e31c4d3f5927a994e67c8d8aaf5acb7d360a7ac2c931b6a9a39e914f7eafb8627181a50bec935a6b6baeb8840d815e0fd0714c9f2474a6167ec16b512e0967ce20a46a93877697d348192dfea1a7b625c3dbcbf0fc3f7a047eb0bd15d7607de8cb5a811ef59d959bde4e0454e3803521ffd2d70a17bee0ddde97b9d9dcfd909bb197e5132ea7258fc0707dc672e6b2d1676d57b5b93c011f6d74a007d988d5200c5a0abaa495d09d25c6a56deb9a45bd6b30ccdbf2d143b9dd098be7af381526412b59a8aa80000000000000", .None}, + {.Shl, "f23856367dea5c21977cc1d7a17f51a7eb2392eec252dcd968436ca96588270274be325369f8f5578e5875b611efa823452963c358f230d4d9e92600676f62dfdd48ba03023ebfac014fd61c0fa9f9f90237e4826a8c4aadbb610027f4e67077e130a71e1c7730707b260a7a90a0b32b61cbe74abe62d8dda0156a82fafe032802dc28cd0a35492b3a39365f9915e4c483dc5023bfb30ec6ff44e12121691a5afe503b8c97b68d6cb4a7572ae81d9490ac3aeb60549e31a7278bed28276e54729991bf6b2cccd3494041d1c9751264109ad7fcce1a6a01b6c669bd7c0a09e50ba3fdd16db1993b11880c2b03b9467a26b4e262f039f5164a8961287b86e5ade9246fd6ab246a2b5160235c157c5c12074fe7eeca13935664937daa830204364480afa5a9830ac096cab3714548ed2e14e8912de7a3196d6b0fa3105af2b38df7c6d01f91ad418bbd9fbd520680584ec2de90921f6029315cc5053f5e2642e450b22f33abf90887405ce92b79abc4b6de92ebd4a8f327e0add05c5fc6cc1c434c95fd79633300b36e3c02da0460b4e053d6b6026b7068ecce2789216753ab06df538a24ecdda3590f540bdadbf799770486876e81d365926e645ffbaea65e83e958c29ba7497c29d55a2106f09efcb4f37cefb65cc29afe4aa3e358f97de71d3fb5eb99a05edf674e5457905a1a489ee1ba6f1847a3bc09a9909a259e2ebd349", "12", "3c8e158d9f7a970865df3075e85fd469fac8e4bbb094b7365a10db2a596209c09d2f8c94da7e3d55e3961d6d847bea08d14a58f0d63c8c35367a498019dbd8b7f7522e80c08fafeb0053f58703ea7e7e408df9209aa312ab6ed84009fd399c1df84c29c7871dcc1c1ec9829ea4282ccad872f9d2af98b63768055aa0bebf80ca00b70a33428d524ace8e4d97e645793120f71408efecc3b1bfd13848485a4696bf940ee325eda35b2d29d5caba0765242b0ebad815278c69c9e2fb4a09db951ca6646fdacb3334d2501074725d44990426b5ff33869a806db19a6f5f02827942e8ff745b6c664ec462030ac0ee519e89ad3898bc0e7d4592a2584a1ee1b96b7a491bf5aac91a8ad45808d7055f170481d3f9fbb284e4d59924df6aa0c0810d91202be96a60c2b025b2acdc51523b4b853a244b79e8c65b5ac3e8c416bcace37df1b407e46b5062ef67ef5481a01613b0b7a42487d80a4c5731414fd78990b9142c8bcceafe4221d0173a4ade6af12db7a4baf52a3cc9f82b741717f1b30710d3257f5e58ccc02cdb8f00b681182d3814f5ad809adc1a3b3389e24859d4eac1b7d4e2893b3768d643d502f6b6fde65dc121a1dba074d9649b9917feeba997a0fa5630a6e9d25f0a75568841bc27bf2d3cdf3bed9730a6bf92a8f8d63e5f79c74fed7ae66817b7d9d39515e416869227b86e9bc611e8ef026a642689678baf4d240000", .None}, + {.Shl, "ed2d58a20077eb683b5bceb3a9795d3425a4d35d9ee5be0ac7323749b8217bd00cb0e275cb8410675b3f72e41248b0260deb1103857682ae4ea6ffd98cc251cc12aab2ce3fc44493609bdc92e72208237154e176c467d59f24f9d98f9d5294175264d9bb113c5577be8413eed8355ee8908b5cec8fec9d017687f0369307dae893f8bdc5b93f8fdf3e67bd1ae859096e7fb3da055bce2bf38375b6e496aa765f853282efbdafedacbba9b73caaa9a06291467decce37d5965e33bacd6a9f3c321bffafeb34ac06b282cbf80eb3e6da235ddc2015fe374df9a488135a247e15293aefce0e7a75a9d5d69f7862158719af260e9ff3c5010bb69122a8fe12235529263c1751574c0487b1223c7e73ab55048773c542c070b747a9d10f995c7935f31c3f9069c28050c77c8f467d1ea2cefcb87beefea793b30738617e91b2c8af18bcbc3e70578b8a319b14dc5ed5f366d99404620b633ed371925dced9e8de0a2d7460c2750f896083baccd4c1b8595812726bdb296be1a13ba88e57f5fee7d8225e2420c8462f11507ecd3da35eba7601a2005d83e26dc25e2e13f21a3da1b97825fa8ecd95b3fe859a8b5ee99128dec3d4ad6b3e0f460eb3c0ae3d21a4199fc62fe6a4c1b8c0b5f2e18f75f30f6a26654f0b0dd2e9c6a1a53a7857134394f982022cf7fcc7224dfde92f27e9da498dc7cc8bd32fc3054f2426246b5a945eddba", "58", "ed2d58a20077eb683b5bceb3a9795d3425a4d35d9ee5be0ac7323749b8217bd00cb0e275cb8410675b3f72e41248b0260deb1103857682ae4ea6ffd98cc251cc12aab2ce3fc44493609bdc92e72208237154e176c467d59f24f9d98f9d5294175264d9bb113c5577be8413eed8355ee8908b5cec8fec9d017687f0369307dae893f8bdc5b93f8fdf3e67bd1ae859096e7fb3da055bce2bf38375b6e496aa765f853282efbdafedacbba9b73caaa9a06291467decce37d5965e33bacd6a9f3c321bffafeb34ac06b282cbf80eb3e6da235ddc2015fe374df9a488135a247e15293aefce0e7a75a9d5d69f7862158719af260e9ff3c5010bb69122a8fe12235529263c1751574c0487b1223c7e73ab55048773c542c070b747a9d10f995c7935f31c3f9069c28050c77c8f467d1ea2cefcb87beefea793b30738617e91b2c8af18bcbc3e70578b8a319b14dc5ed5f366d99404620b633ed371925dced9e8de0a2d7460c2750f896083baccd4c1b8595812726bdb296be1a13ba88e57f5fee7d8225e2420c8462f11507ecd3da35eba7601a2005d83e26dc25e2e13f21a3da1b97825fa8ecd95b3fe859a8b5ee99128dec3d4ad6b3e0f460eb3c0ae3d21a4199fc62fe6a4c1b8c0b5f2e18f75f30f6a26654f0b0dd2e9c6a1a53a7857134394f982022cf7fcc7224dfde92f27e9da498dc7cc8bd32fc3054f2426246b5a945eddba0000000000000000000000", .None}, + {.Shl, "a1797c5afd3022f8351c57ad20330609d3f0857f63e04d0af55ddb4028ccb49a53e941121986eee725714e6a8f48c9b06e6940d82f16a2d50cbe335d58ca9c30fd124543c2b303d4330887f99512bdbe9c8ab3c9aee567b2dcf266af9d749c911717a90fe8736a0dfc07281145a949c432aadae0195b61f4898ea8e1527419e2fdccf12b7c1d57df89388b7574ab9bb93fe5289d4fdf3452c340baf36c2541faf6f9e825e0eda04113198d224c596d35a138f17876b95435f3a07b736f5f42b99726c270f3549df2814c83793594de34dd5fa429de41cdf191845ba4ac39d2a5dc60c15dca12ee622e6a4b0a9a0fd5f437a9bca459b60447451eb06d4cf00c1aae30f64b9b2d4e2a799435daaa338c2796760120638d30ec6fa1a2fa2a0abe4f32d5f3088cb8171de90371d1b2ff6535073e978d237829f09c23ce657187b676407d5f1d708564d2caebd4ba43dffcb8a7c0bd26e93ea4048fca805cbdf70752a410979b7afd0cb5e509f761016d39664019b884e853457cbd8726cf4bf884b4dde81de8b1db3ef31df80fb5541c3f9e6590f109e2b48b133570f01847b40a860f8abf53c76cb50d62b200b8ef843e5dc3d305a9ac444c4e71f28c502be7f20b5fcb3c13ef770bbc00c19389dd8b5493dd6cc45b010105ad3c307b01e4f8c23369f1f207e9dbdfe5c612f4ff2de319e8f9638e046ab8cafecc6a13b59c30c597", "41", "142f2f8b5fa6045f06a38af5a40660c13a7e10afec7c09a15eabbb68051996934a7d28224330dddce4ae29cd51e919360dcd281b05e2d45aa197c66bab1953861fa248a87856607a866110ff32a257b7d391567935dcacf65b9e4cd5f3ae939222e2f521fd0e6d41bf80e50228b5293886555b5c032b6c3e9131d51c2a4e833c5fb99e256f83aafbf127116eae95737727fca513a9fbe68a5868175e6d84a83f5edf3d04bc1db408226331a4498b2da6b4271e2f0ed72a86be740f6e6debe85732e4d84e1e6a93be5029906f26b29bc69babf4853bc839be32308b7495873a54bb8c182bb9425dcc45cd49615341fabe86f537948b36c088e8a3d60da99e018355c61ec97365a9c54f3286bb55467184f2cec0240c71a61d8df4345f454157c9e65abe61119702e3bd206e3a365feca6a0e7d2f1a46f053e138479ccae30f6cec80fabe3ae10ac9a595d7a97487bff9714f817a4dd27d48091f9500b97bee0ea548212f36f5fa196bca13eec202da72cc80337109d0a68af97b0e4d9e97f10969bbd03bd163b67de63bf01f6aa8387f3ccb21e213c56916266ae1e0308f68150c1f157ea78ed96a1ac5640171df087cbb87a60b535888989ce3e518a057cfe416bf967827deee177801832713bb16a927bad988b602020b5a7860f603c9f18466d3e3e40fd3b7bfcb8c25e9fe5bc633d1f2c71c08d57195fd98d4276b38618b2e0000000000000000", .None}, + {.Shl, "b52c32e64b162dfec7236dfa5406c1a2774d53ee1b8e978432ebdcfd3de750c6b8ae210f3e5131c7f290efc67ea26b939dc7c0adcb93b31a731449e0890c03c4694d60c4c60123c3892b177947be3c54769e4bf4a3d5200d10dec1d2491df8cf1d30227de72e9d4307a2366d6ad18afbd27cc9c0384a33201e6978e0c43b9ec931a03fec7816f4411a532e0cf72265a889797a51cced86e6b089807632ef1ce9379132fad0f59181ee674d5f7d3373c0913628b2e88d4971584e670860292aebba0e1659ccba59777e01d4e68d668e4f488022b85c212852a47f6721a171dc986cfc6c14e3d3e341e9772e7a5e93acde2f8d670636fba1888cf4565893ef5bdeb4dc449077ce7ce83b1d1a3eb3253eb4ee4be9c69fec51375442cd651ca50d52c55eaa413269e0c8c7f54ef354b6c10c0256fb0fd465b648db1e447fdb98027165275d8b02bf786e05a1ad5360d8289b749026bc1bec0157dc83eaf5768c9758a20c30d84ee840a439d3245bcc4db631c57a5117421ae3596508752e14376c6634566237e4af5c13cb6015f441cb656a2467083ec8095734c0dbb479f61557fc76abd19b199b4c0c9ea3fb26a5325df8fe1baa590d2f155be12b2a9428e78d5695b5d494183af3e1518316626adadc2cf2e32d03378e811a1e2e5dd388524e4fdc690eab15ed3c93927edf47080f40ca63c8d54000fc9dd9a35ad1035af3a01e", "8", "b52c32e64b162dfec7236dfa5406c1a2774d53ee1b8e978432ebdcfd3de750c6b8ae210f3e5131c7f290efc67ea26b939dc7c0adcb93b31a731449e0890c03c4694d60c4c60123c3892b177947be3c54769e4bf4a3d5200d10dec1d2491df8cf1d30227de72e9d4307a2366d6ad18afbd27cc9c0384a33201e6978e0c43b9ec931a03fec7816f4411a532e0cf72265a889797a51cced86e6b089807632ef1ce9379132fad0f59181ee674d5f7d3373c0913628b2e88d4971584e670860292aebba0e1659ccba59777e01d4e68d668e4f488022b85c212852a47f6721a171dc986cfc6c14e3d3e341e9772e7a5e93acde2f8d670636fba1888cf4565893ef5bdeb4dc449077ce7ce83b1d1a3eb3253eb4ee4be9c69fec51375442cd651ca50d52c55eaa413269e0c8c7f54ef354b6c10c0256fb0fd465b648db1e447fdb98027165275d8b02bf786e05a1ad5360d8289b749026bc1bec0157dc83eaf5768c9758a20c30d84ee840a439d3245bcc4db631c57a5117421ae3596508752e14376c6634566237e4af5c13cb6015f441cb656a2467083ec8095734c0dbb479f61557fc76abd19b199b4c0c9ea3fb26a5325df8fe1baa590d2f155be12b2a9428e78d5695b5d494183af3e1518316626adadc2cf2e32d03378e811a1e2e5dd388524e4fdc690eab15ed3c93927edf47080f40ca63c8d54000fc9dd9a35ad1035af3a01e00", .None}, + {.Shl, "-9034fe8fee8a792a48d320fdfb74b12e5648ef5b727ffb2475b071cd620ed977e739254f92427db85a8d6d38d2f46efad2abfb273d28834f807e2e5ddfdd0bd4226591e7f18fd54d8768d5ddff8d07b8886fbe98a78e0632f8d2d289487022ddce84a16b2e350ba52d888d92b7161ca0c80bb1f4bdb48faf530effa509ec1a8e182c4a74ad89faece0e9f67831bf76cfabada6695e24158923f6935f205e61b2f45066b5cbb7789a41c509140df72f28f8545c9e340c1810bf5174a0e2d2bb9df0955b9fe6b78050938a8b50b7f66ab1286ed60a17ed87d0d8fd19023eaadef7d3ab1fac7f7292a336edd17f937352de82b3f61f7045b8ead4ecca02be6ba198b19c98918f5a9dfbee907f6a2e263ea64ce19ebbb0b85695c6729c4544f28ccdb8cf9c9d93b39222322fd74baf51a992e5c39671bdccbba520aa884bc0fba1027e57a9741574125a73fbbdf7f29929c37fb1323b236c3aba8c6132ccbe7f116a28848da98802b6669abd15f63a3f57faa4a6956fc5cec19b1f269e7988eb412cf2409eafdfb9a3a124df6054b0c5daa418357199abb83c19c2a8cacccd15f9150e9bfece3655bf01bc17cb3cccbc1fa090ecfd70370b5d1cedb85bb2e9c7f8005838f2da3faee2966168010cd19236d8044541c53f007ce81ed17b615b1fd66725c78dc41bb26210472d987ae1821d330d0761053b34189a9af5708861d9b656", "6d", "-12069fd1fdd14f25491a641fbf6e9625cac91deb6e4fff648eb60e39ac41db2efce724a9f2484fb70b51ada71a5e8ddf5a557f64e7a51069f00fc5cbbbfba17a844cb23cfe31faa9b0ed1abbbff1a0f7110df7d314f1c0c65f1a5a51290e045bb9d0942d65c6a174a5b111b256e2c3941901763e97b691f5ea61dff4a13d8351c305894e95b13f5d9c1d3ecf0637eed9f575b4cd2bc482b1247ed26be40bcc365e8a0cd6b976ef134838a12281bee5e51f0a8b93c681830217ea2e941c5a5773be12ab73fcd6f00a1271516a16fecd56250ddac142fdb0fa1b1fa32047d55bdefa7563f58fee525466ddba2ff26e6a5bd0567ec3ee08b71d5a9d994057cd74331633931231eb53bf7dd20fed45c4c7d4c99c33d776170ad2b8ce5388a89e5199b719f393b27672444645fae975ea35325cb872ce37b99774a4155109781f74204fcaf52e82ae824b4e7f77befe5325386ff62647646d8757518c265997cfe22d451091b5310056ccd357a2bec747eaff5494d2adf8b9d83363e4d3cf311d68259e4813d5fbf73474249bec0a9618bb548306ae33357707833855195999a2bf22a1d37fd9c6cab7e03782f967999783f4121d9fae06e16ba39db70b765d38ff000b071e5b47f5dc52cc2d00219a3246db0088a838a7e00f9d03da2f6c2b63facce4b8f1b883764c4208e5b30f5c3043a661a0ec20a7668313535eae110c3b36cac000000000000000000000000000", .None}, + {.Shl, "-34fa5a4175130b0fcdc2cb6d268b41658efb68d537bbb9f40cfb205f3e1b5a62f7d079524238a160d9b98ee4ed6c10e43aedc5498300b29763c550664c61031652cfbe96037f16a87a503568b8c6e76b0ad82669dd44f6f521521d6f2754aa5bc0af350ecaea60673751e91904282adcadd828319bf9ba0722ba1900f28ff77d156aa0013e12917258982e278fb10676fe3745b08135acdaccaceb44866270d6d4dcb0aedf3e33daaee87455f511d869901a72cee13efc98fa3874954e1b7c5e24aad8df8fc1e430ef06c390d74b8c1d21cde058f617cd491cd513d77f2073dd9a9e99748d46dd63beb60f870533064f85be839c6400f22a1e8e09b66bf6cba2fcf0fe0baf6ff07908ce995cb68800b2fa640a31f298acb52939a04bfac5c5bb9f664e978a085032bba3b1157ce479e5d04c4af559d1c0a2ec25df649efce8b8132eb7e5ac16d40e7e58e06c2bf0f174dfaf0be96247de212dbd3d1d4739557ee9e2da9ca1d2488dd130ae541845973f6ed6a9985278030e97c81b2d9550698373fd777f6bb3e3556da1341ee3dfe572cc29f705c4688d14b40219191f5e66b661c0b464b88185532c2e3a2b20d845790c2939aaaf47fc08cb095a81c1303e72770964ff57bb28f930cf30db0d1f755713db882e743eec0f0ea52aab1ca2ebcfd806181ab7abbf032339903c818a0baa31af57ae14c3f8fca8ca481b6f0ee1a9", "22", "-d3e96905d44c2c3f370b2db49a2d05963beda354deeee7d033ec817cf86d698bdf41e54908e2858366e63b93b5b04390ebb715260c02ca5d8f15419931840c594b3efa580dfc5aa1e940d5a2e31b9dac2b6099a77513dbd4854875bc9d52a96f02bcd43b2ba9819cdd47a46410a0ab72b760a0c66fe6e81c8ae86403ca3fddf455aa8004f84a45c96260b89e3ec419dbf8dd16c204d6b36b32b3ad121989c35b5372c2bb7cf8cf6abba1d157d44761a64069cb3b84fbf263e8e1d255386df17892ab637e3f0790c3bc1b0e435d2e307487378163d85f352473544f5dfc81cf766a7a65d2351b758efad83e1c14cc193e16fa0e719003c8a87a3826d9afdb2e8bf3c3f82ebdbfc1e4233a6572da2002cbe99028c7ca62b2d4a4e6812feb1716ee7d993a5e282140caee8ec455f391e79741312bd56747028bb0977d927bf3a2e04cbadf96b05b5039f96381b0afc3c5d37ebc2fa5891f7884b6f4f4751ce555fba78b6a728749223744c2b95061165cfdbb5aa66149e00c3a5f206cb65541a60dcff5ddfdaecf8d55b684d07b8f7f95cb30a7dc1711a23452d00864647d799ad98702d192e206154cb0b8e8ac836115e430a4e6aabd1ff0232c256a0704c0f9c9dc2593fd5eeca3e4c33cc36c347dd55c4f6e20b9d0fbb03c3a94aaac728baf3f6018606adeaefc0c8ce640f206282ea8c6bd5eb8530fe3f2a329206dbc3b86a400000000", .None}, + {.Shl, "9a22c4e0bba696e560c7b20d808759d96c1c095272f51f3a352db4604a81be286faad2f4e5c597c1222de7956bd25e01a3c0a10ff017452b32ab4809d300ca1b262ebe80704148e34c12a69a9b4524f1ff2147df481d832b07ced228c4724e5e2d7a62b374633015b2e2ffd5566bb83b1e29f174b8a4e05d8315be359a812d60d6987813ca7376fad572395c1597a3de8984b8f87e7cc90e0d589cd54954d0b8a5bd41135e909eeff7db0a2e5208ecceaed7b5eed208051f75b907a7e6f21785d664264c9def3b3258c905fe7c4fb6bb3f0561e76e9f93add0bb0eb6afc2c4b4a147256c3842e36697f5001cf0b53cb61855f7384af4b0047a90265f3394014a7388bdfde6f1411776d3dbb60b4b5ef51b074102d98716a2012d6e2dd5e2ecfbe0729e825b4094db9a3005f2b6ed7d08fdf2545e99c3ac89bc101911471293b12fca4eb7c3fc6fc7c1bc06316e319913518113e51fed224a4b7c9d71b10e7878cdfc02992642d7c5f30474b8f3e5795ef9fd90160c389e323285969e4024686cc0f0e56fd931ed627507c2ee4b63fe0a2c0eabf6b7859a411102e0440fe75cc4cf9a7746d601e98f5af722ec4f485915d5554dc41618338dd2a37f55a23dea7b85b2cebd653539245d45713e200c81ea015d6b26c5765cad55be5b466291cef48c34ea10b0ec95e3e285edad9c854573d8ef5f751d5ce9be4291f2eafce4e8c4", "43", "4d1162705dd34b72b063d906c043acecb60e04a9397a8f9d1a96da302540df1437d5697a72e2cbe09116f3cab5e92f00d1e05087f80ba2959955a404e980650d93175f403820a471a609534d4da29278ff90a3efa40ec19583e769146239272f16bd3159ba31980ad9717feaab35dc1d8f14f8ba5c52702ec18adf1acd4096b06b4c3c09e539bb7d6ab91cae0acbd1ef44c25c7c3f3e648706ac4e6aa4aa685c52dea089af484f77fbed851729047667576bdaf76904028fbadc83d3f3790bc2eb3213264ef79d992c6482ff3e27db5d9f82b0f3b74fc9d6e85d875b57e1625a50a392b61c2171b34bfa800e785a9e5b0c2afb9c257a58023d48132f99ca00a539c45efef378a08bbb69eddb05a5af7a8d83a0816cc38b510096b716eaf1767df0394f412da04a6dcd1802f95b76be847ef92a2f4ce1d644de080c88a38949d897e5275be1fe37e3e0de0318b718cc89a8c089f28ff6912525be4eb8d8873c3c66fe014c93216be2f9823a5c79f2bcaf7cfec80b061c4f191942cb4f20123436607872b7ec98f6b13a83e17725b1ff05160755fb5bc2cd208881702207f3ae6267cd3ba36b00f4c7ad7b917627a42c8aeaaaa6e20b0c19c6e951bfaad11ef53dc2d9675eb29a9c922ea2b89f100640f500aeb59362bb2e56aadf2da33148e77a461a750858764af1f142f6d6ce42a2b9ec77afba8eae74df2148f9757e72746200000000000000000", .None}, + {.Shl, "-87ccd26073bc73f443bf7719930d53087f0a33f951a98b8384ac2503ddacea972daca274e359ff63cb3d0c3cbc58be17244bd3ec43370dc903f237b748ede5a84d89e53dc9ce2f0711dc9047b229f6d3e376e672e245eab6cdb2d45acbe9688dc0e8c6edbe9e2e40b5876d86faa5bbaffe387001911985755f14abd56ead351c2b6ca42c195777932bd91c776d771392642dbc07a04ad02b6adf60ffa5ffdf4b5e452f983c2204f6640a97be6184e7ca2e0dca1bfbaecff44cd6a9ae9cf4839da3c01dae16a5d46f1b2fb8f07cf9ff40755e580f4ef22e96d2c95d891df9a8aff2cc9d30a9d4db1c768ff8d08d3d27ff369dd7dcb86fe0b6b94c16c3a26721cadd7343c25103f299836b0adb0490ceefafdfccb0222da9ab9f9047957bff9f538078c7804d1a00f579b7ac85c38905ea0ef6b2d7f059b65cf07effdfc8f662e1c1aa6747c773fb93f6319ea55a798282a95f126dc3273597bf28f729d1b3226b2962832106281afaa55f402bd18281594c5a2165a1999faff43b00358d327424ef3258dd185468557a9be0ca52f2cf3ffebb961cfb8f5cb46d9f44415e1526594272f23f45e4ecb3e18c34a2ac3990aea7e75cf98dcd1047440c53a85698a3e0f473790b1259b2df66d615ad6a5643767138408b1e41c919a8dd9ebd7aa6e7800d4f2a5c505bb0e3603f217c9fb88422c9765a20da6f6144b06dc6d2bed7ab56", "36", "-21f334981cef1cfd10efddc664c354c21fc28cfe546a62e0e12b0940f76b3aa5cb6b289d38d67fd8f2cf430f2f162f85c912f4fb10cdc37240fc8dedd23b796a1362794f72738bc1c4772411ec8a7db4f8ddb99cb8917aadb36cb516b2fa5a23703a31bb6fa78b902d61db61bea96eebff8e1c006446615d57c52af55bab4d470adb290b0655dde4caf6471ddb5dc4e4990b6f01e812b40adab7d83fe97ff7d2d7914be60f08813d9902a5ef986139f28b837286feebb3fd1335aa6ba73d20e768f0076b85a9751bc6cbee3c1f3e7fd01d579603d3bc8ba5b4b25762477e6a2bfcb3274c2a7536c71da3fe34234f49ffcda775f72e1bf82dae5305b0e899c872b75cd0f09440fca660dac2b6c12433bbebf7f32c088b6a6ae7e411e55effe7d4e01e31e01346803d5e6deb2170e2417a83bdacb5fc166d973c1fbff7f23d98b8706a99d1f1dcfee4fd8c67a9569e60a0aa57c49b70c9cd65efca3dca746cc89aca58a0c8418a06bea957d00af460a05653168859686667ebfd0ec00d634c9d093bcc963746151a155ea6f83294bcb3cfffaee5873ee3d72d1b67d11057854996509cbc8fd1793b2cf8630d28ab0e642ba9f9d73e63734411d10314ea15a628f83d1cde42c4966cb7d9b5856b5a9590dd9c4e1022c79072466a3767af5ea9b9e00353ca971416ec38d80fc85f27ee2108b25d9688369bd8512c1b71b4afb5ead580000000000000", .None}, + {.Shl, "-622f549ecb2e5113d5bef707f2b6547d13f9d943e8d5b1c873bdb50af155384884f3818364ce68f7cffb905b62dfc842e80709933e40b29179a3d1476c543b4bd0813924b6e9e149101eb32dfd4390d922c240ef113c2f0a32c08d137a844f808d8c4890dcbb9c686bdbb5d73d7e558727d794453e4335d3e2d0c1fc9b4976085446b3a94416de75467d93a2faf91f217957addee454f83e93c3bbfea169db8ca327820cf1afa13a7885ced613e955d18277116889e923ffa168ae5ccb4b58e72c74790d91a9ac003e3dab89008fb333570c217b0c76165bfcc053a2fb77996ada69322586a035650df04bb15854d6a948c38fb6fde006596009e1afd6b664cd4f26d9e1a40dafffe0d0c858d2f7d5452fbd5345dad4d98961f6f79de64dc817f2d2839f3f60f47008357c09b57d7b8e8a49faca93a22aed783d705592f4bad2cd0e56eb50d9bda7063bea4b826f1b631bd03cf6d9c9e6d831b1c1396595f05d8369a878dd45f10b825d72d520676064bff1fdbcb34fd2ae49cf68a8805a42dfe5dc985fdaf05d91440daacc8ffbbf653305debff45a81eb8af2bc2774fbe4845073e06deee6a44919cd67022045533b9de26bb940c140ccdb237a9846a5b7bbc4771d27396ef45d04a98151cca8bd23dd708f938ad5a62f8d808baeed8fd0dcc87af2ef2cb2795a3f00211a959ce9ef7dcd511bc93f3d01d7b68fd503b369d5", "6d", "-c45ea93d965ca227ab7dee0fe56ca8fa27f3b287d1ab6390e77b6a15e2aa709109e70306c99cd1ef9ff720b6c5bf9085d00e13267c816522f347a28ed8a87697a10272496dd3c292203d665bfa8721b2458481de22785e1465811a26f5089f011b189121b97738d0d7b76bae7afcab0e4faf288a7c866ba7c5a183f93692ec10a88d6752882dbcea8cfb2745f5f23e42f2af5bbdc8a9f07d278777fd42d3b719464f0419e35f4274f10b9dac27d2aba304ee22d113d247ff42d15cb99696b1ce58e8f21b235358007c7b5712011f6666ae1842f618ec2cb7f980a745f6ef32d5b4d2644b0d406aca1be09762b0a9ad5291871f6dfbc00cb2c013c35fad6cc99a9e4db3c3481b5fffc1a190b1a5efaa8a5f7aa68bb5a9b312c3edef3bcc9b902fe5a5073e7ec1e8e0106af8136afaf71d1493f595274455daf07ae0ab25e975a59a1cadd6a1b37b4e0c77d49704de36c637a079edb393cdb063638272cb2be0bb06d350f1ba8be21704bae5aa40cec0c97fe3fb79669fa55c939ed15100b485bfcbb930bfb5e0bb22881b55991ff77eca660bbd7fe8b503d715e5784ee9f7c908a0e7c0dbddcd4892339ace04408aa6773bc4d77281828199b646f5308d4b6f7788ee3a4e72dde8ba095302a399517a47bae11f2715ab4c5f1b01175ddb1fa1b990f5e5de5964f2b47e0042352b39d3defb9aa237927e7a03af6d1faa0766d3aa000000000000000000000000000", .None}, + {.Shl, "-f26ef7b52160cd8b8d7b40831c6680e8305076010e51bcf72aa1d5f99585ac211e4047d9ff1f569a7d975ac87ae6e9d27a143cec404cabbe3b39c6c9a93d92f5040e2e85c1acbb9e2c64069f951e8ec8c743da5a8c526647e20cabf79c09d2536f9aad4c43af75becc7283c5e219a198a4934c1ec3625969d232eae2ea03d6e9c5bbe6168a80f878d5341708b5ad4be5fc84aaeba41a95fba508bfa1a0adcbe7474ddae2bc50d6b806605efef026718db8e7a3121b2fc9ba5cf4c7d6cc7d582f89453bf5355f4aaa4aa7d6b9b5c7f2be4b200824a10f93608996eef824175bddfd7eee8d64983401a1b81e0a74281bd5dc2f9ad6157fcefe834b519f2aac30b873e7b2d9ece40dd23da2fdd4495453cda28cd35c9ccb36ac40b91eaadd17cca1a4b5c86e5be680a7f71a067bb7957a2c4e5c50a6c255da0626e92b14abb96c4331239e0fcf0707eb2d4cdb1dd24f56e7fc54f930093e31653fe975a46c77a65c072c5cb6ab67de4758d5291aa6618a7ab338d9cabe709eeb2649de4bebd75535a4ff6fd00a0790067a449bc9e9891dcda267451d781d0caf52b4dcaa0d82e667c80503441a8d05e834771f3050384dd947bd34495b22d27d5624f25a849222b7daa9e1ca92917e8f4b9b2c3b899d870fa26bf5cc0798f940be783e69ab75d18cf6629dbee6062fdadbadeff619d84138de6caf24ada6c7853591e45d4cf48865", "28", "-f26ef7b52160cd8b8d7b40831c6680e8305076010e51bcf72aa1d5f99585ac211e4047d9ff1f569a7d975ac87ae6e9d27a143cec404cabbe3b39c6c9a93d92f5040e2e85c1acbb9e2c64069f951e8ec8c743da5a8c526647e20cabf79c09d2536f9aad4c43af75becc7283c5e219a198a4934c1ec3625969d232eae2ea03d6e9c5bbe6168a80f878d5341708b5ad4be5fc84aaeba41a95fba508bfa1a0adcbe7474ddae2bc50d6b806605efef026718db8e7a3121b2fc9ba5cf4c7d6cc7d582f89453bf5355f4aaa4aa7d6b9b5c7f2be4b200824a10f93608996eef824175bddfd7eee8d64983401a1b81e0a74281bd5dc2f9ad6157fcefe834b519f2aac30b873e7b2d9ece40dd23da2fdd4495453cda28cd35c9ccb36ac40b91eaadd17cca1a4b5c86e5be680a7f71a067bb7957a2c4e5c50a6c255da0626e92b14abb96c4331239e0fcf0707eb2d4cdb1dd24f56e7fc54f930093e31653fe975a46c77a65c072c5cb6ab67de4758d5291aa6618a7ab338d9cabe709eeb2649de4bebd75535a4ff6fd00a0790067a449bc9e9891dcda267451d781d0caf52b4dcaa0d82e667c80503441a8d05e834771f3050384dd947bd34495b22d27d5624f25a849222b7daa9e1ca92917e8f4b9b2c3b899d870fa26bf5cc0798f940be783e69ab75d18cf6629dbee6062fdadbadeff619d84138de6caf24ada6c7853591e45d4cf488650000000000", .None}, + {.Shl, "-349bc86e6ad3d83f7a72390258768cb390f6903cb663b65b3dfd0398548a85797e090824a4c80c39a91122374eb3be3cea2928d433f8202fe870340e029bd6667c4cafe41887f56fb375eb2fdef9367fc8a7cdae1ab9ad58762c42c83aa37c28f8051d189babd2c3e2d29092beafe9f1916164e9c282018308a4c3d1ed51e0667d6cfc63b37c7b5cf6b272bd61ac1983c73b5e54402285f671c4fb674b9d19eb9f8403b5b6e598daf748b0399f79d6bffac6704bd6e9acea97004e76748fd02348e5cb83b721c54966d33c6dde5d2154b5f077d2c74327db84d735ad108d4ae9660f470110d81c1053b13cd857f0232e0c19ddc4b636a112f4c95c4cab17f9eecb7d1c1a0d5e0ab84521290dc3156518025a9eaef6b3b27666c80d35b7919c831e76cc4e5bc44929ca5fdb9b6584aefb41881835947fa6ce300747b4c449d5673fb041e392b6b421044c1961532cadeaade2fab40da082bd139751db98a14ea7ce73e42c39b7d72155d82d451fe1f9b19fc128cd4adb0d79a814d6108c458cd3aca8a11d7eab1c57cf1e616e321bba24cfe62683d9df31e9623b150f22301e27eb70ab3dfe2e061034475d6496eda1e8a2993dc8d1c69e2be0294fbafddbe1c4091657769dc2dd5cbafca0b610d99a3432e44770be3b2e41f7bd7d8aca558586a82f2a744eb3292c41c6802de577f2e74506c9dba6f9c5dec1c1e6cf28aa2dee", "65", "-693790dcd5a7b07ef4e47204b0ed196721ed20796cc76cb67bfa0730a9150af2fc121049499018735222446e9d677c79d45251a867f0405fd0e0681c0537acccf8995fc8310feadf66ebd65fbdf26cff914f9b5c35735ab0ec5885907546f851f00a3a313757a587c5a521257d5fd3e322c2c9d385040306114987a3daa3c0ccfad9f8c766f8f6b9ed64e57ac35833078e76bca880450bece389f6ce973a33d73f08076b6dcb31b5ee9160733ef3ad7ff58ce097add359d52e009cece91fa04691cb97076e438a92cda678dbbcba42a96be0efa58e864fb709ae6b5a211a95d2cc1e8e0221b03820a76279b0afe0465c1833bb896c6d4225e992b899562ff3dd96fa38341abc15708a42521b862aca3004b53d5ded6764eccd901a6b6f2339063ced989cb788925394bfb736cb095df68310306b28ff4d9c600e8f698893aace7f6083c7256d6842089832c2a6595bd55bc5f5681b41057a272ea3b731429d4f9ce7c858736fae42abb05a8a3fc3f3633f82519a95b61af35029ac21188b19a75951423afd5638af9e3cc2dc643774499fcc4d07b3be63d2c4762a1e44603c4fd6e1567bfc5c0c20688ebac92ddb43d145327b91a38d3c57c0529f75fbb7c388122caeed3b85bab975f9416c21b3346865c88ee17c765c83ef7afb1594ab0b0d505e54e89d665258838d005bcaefe5ce8a0d93b74df38bbd8383cd9e51545bdc0000000000000000000000000", .None}, + {.Shl, "68c0142307955783e7887413fa468d514cbe9b3ec45f6372e9e5a58a97699e5ee2b2bd9f286d5a0d01cb5852d4acf1e7b8c4aa49ebe653645eeab73835becc46707ce081aad82edfb3ff6024e147336d7a9ee57807648baa66b23a716e9425991e1c36747df90451a9bcc7b0a267d98e13a5bfd00f3d09461d28991094748f83c17e261cde64121ba434357396f96d55e5483eb5fd3657c9efb5807299c17b653170a799f14c527a19cfbdcd042ea785bcbd499315ccf535455178ec62e63e6a43e6079a8ad0b9b9a6234c3f80092036a1341f7671c7ab56e7b977ea5ba73d37ded2c01abaf1315225f88c88496cb5d308a8bd8a803a6ed80735718b7ce261ab0985f56a7095d8b291159e409e92f756b997cf1ea79b82c50ae5342979615b5eecc9cdb9da2aae86084d527576a0ac40421f273406fe9a9ae9f7f2976a6ae92a34436a188fafc0ce16d3e9cde0a7d8c48259077e556e6cd38dadc6308a13b673703513d674f1efca6aa7b3c9c2e76bb3b188cb0bdbafe958c68c66570723deeba707971d7e29c56f007fed8b363759f4f4c92f1f0bea3001704049fca97b5570dfdb64baa72da4f0da498ae459f9cf6ed2f2308002d2e9155f4d6ff4fa6df8bc977b8badecdacb861ff2383f77c82ea11ef785d02cbe745cde20571307e872229b1f7f5a7a76530f14fc1b11395e43516baddb45649709cee57f4f71d0db9434", "8", "68c0142307955783e7887413fa468d514cbe9b3ec45f6372e9e5a58a97699e5ee2b2bd9f286d5a0d01cb5852d4acf1e7b8c4aa49ebe653645eeab73835becc46707ce081aad82edfb3ff6024e147336d7a9ee57807648baa66b23a716e9425991e1c36747df90451a9bcc7b0a267d98e13a5bfd00f3d09461d28991094748f83c17e261cde64121ba434357396f96d55e5483eb5fd3657c9efb5807299c17b653170a799f14c527a19cfbdcd042ea785bcbd499315ccf535455178ec62e63e6a43e6079a8ad0b9b9a6234c3f80092036a1341f7671c7ab56e7b977ea5ba73d37ded2c01abaf1315225f88c88496cb5d308a8bd8a803a6ed80735718b7ce261ab0985f56a7095d8b291159e409e92f756b997cf1ea79b82c50ae5342979615b5eecc9cdb9da2aae86084d527576a0ac40421f273406fe9a9ae9f7f2976a6ae92a34436a188fafc0ce16d3e9cde0a7d8c48259077e556e6cd38dadc6308a13b673703513d674f1efca6aa7b3c9c2e76bb3b188cb0bdbafe958c68c66570723deeba707971d7e29c56f007fed8b363759f4f4c92f1f0bea3001704049fca97b5570dfdb64baa72da4f0da498ae459f9cf6ed2f2308002d2e9155f4d6ff4fa6df8bc977b8badecdacb861ff2383f77c82ea11ef785d02cbe745cde20571307e872229b1f7f5a7a76530f14fc1b11395e43516baddb45649709cee57f4f71d0db943400", .None}, + {.Shl, "-550b5ed902873c74359b29fc89d421c4b1876384d5d5ace33d797aaa3f482cb58adc28be1c2d11ebd5108308186eda69891dbb4746a4020a9e812950571faabee67e039fe8aa1da2cc0efa52a102773e0a9b6aa1dc90e4f6fe52660d9a02d056f540ed605d8c59232085f59d59369408f6b0813744c80d289db0055ec134a6f5e9f9eca2416dd1ff82f2ecaab05f30acd123b7b5c35bb93d95976cbceecf6681980d31d0bb0fb9ce95b1423eb50c3f9c616f5485e0177e6cc8f84db213cc1e4d2211827dddccc79cea68e3c7b0745f4fda3c66fc4de64e3a652cda2f8baded35ff8a926661579992c5a69b2234b8eea0c496d4e1bbb357b6619c418c3300f3ce79057ea503dfb37979fb4a63c67e37931915fdb18cc322e140c408299f76f3a7329644b64571c094e343f219c089c6e1b07bcf4f0aa142d5903faa29f005beba5e6dae9f89fe102f369731b6589efa408b01de7a06ef46587567540bac001069465f0b31d19fbebcb59ce2bc5d8a471e1f7e04c525676131f09284fe4fa7a11d8cd2132618a2519571839ac0e318ee1cd0ed668bbf6184d82ca1bac2919f56ba6e5289539456cbbf3171ee17f9368d06fac2f65ed616ae8fa6db5451468ee71a93435fea3483b8620462da76a60d1f1ad85b2cc15652ff07aec0aee68897e06bbe5d0c361499fd71c56ef7fc0c8e5c53de887a082da5a600767be4d3faa97556", "3c", "-550b5ed902873c74359b29fc89d421c4b1876384d5d5ace33d797aaa3f482cb58adc28be1c2d11ebd5108308186eda69891dbb4746a4020a9e812950571faabee67e039fe8aa1da2cc0efa52a102773e0a9b6aa1dc90e4f6fe52660d9a02d056f540ed605d8c59232085f59d59369408f6b0813744c80d289db0055ec134a6f5e9f9eca2416dd1ff82f2ecaab05f30acd123b7b5c35bb93d95976cbceecf6681980d31d0bb0fb9ce95b1423eb50c3f9c616f5485e0177e6cc8f84db213cc1e4d2211827dddccc79cea68e3c7b0745f4fda3c66fc4de64e3a652cda2f8baded35ff8a926661579992c5a69b2234b8eea0c496d4e1bbb357b6619c418c3300f3ce79057ea503dfb37979fb4a63c67e37931915fdb18cc322e140c408299f76f3a7329644b64571c094e343f219c089c6e1b07bcf4f0aa142d5903faa29f005beba5e6dae9f89fe102f369731b6589efa408b01de7a06ef46587567540bac001069465f0b31d19fbebcb59ce2bc5d8a471e1f7e04c525676131f09284fe4fa7a11d8cd2132618a2519571839ac0e318ee1cd0ed668bbf6184d82ca1bac2919f56ba6e5289539456cbbf3171ee17f9368d06fac2f65ed616ae8fa6db5451468ee71a93435fea3483b8620462da76a60d1f1ad85b2cc15652ff07aec0aee68897e06bbe5d0c361499fd71c56ef7fc0c8e5c53de887a082da5a600767be4d3faa97556000000000000000", .None}, + {.Shl, "75c0e38b03178565ed8f37e654198ef3c2dbeb9f3b05cbd58ff746913e1cd54000690e34df00b2c6788a7679174f3d4e05d99f308166fb6c62fc105838113a15abb3a10b2fe674c5003ca8ecfa21046930e7c2db9625cdb0a482b115b8b290093318f174645610e373d99e0ab03b0fca0779c505ae987abd0247b9d91ce2a4780be83a5b27139a004c80e3bbe1819e0d670e50db711a1748faec811d3cf3329884c849d0e1130e1a3427e1e7c81a0a5f1c482692ec2b0887bb24ecbb530bfcd9bfa6663b335f2843457298c3d110e8c9349b65ea903513860d9966510701c5c72308ae79dbd02564948adf92c0d4bf0a271e2116b76711257559883a8d53ab699dea998da0e15540d32996e749c4c00d8c88081e1191ff615f8d63c61f963994d6c9ec348a933b928ae082952d31e674f92a87afa6132ee7b94978656269c29e03fc0981bef43b0386fb9c449cc9935ee740ca7589819f93fe7583b32d35dad80775e0eb93e416443eaa8c61c24aa6432d191c53a1fdbc6889d2efe29f09277b14e890c03e86c85d00636ea76bfd316110caf211cc3bfcef3711689b122bdddbefacd116062f8b426cf33e3c0a2c13c7bf51dbdb6189ceef9a3ffde585b2f30a7ef73b1ec4eb105286d457ebcbe27fe721437418d858753f96b8ed729ba6b8802148a09824e2cf88bf29f712b19d7b2235ee554d5d5e6b6dd3c6fb9d3dd3dcee", "5d", "eb81c716062f0acbdb1e6fcca8331de785b7d73e760b97ab1fee8d227c39aa8000d21c69be01658cf114ecf22e9e7a9c0bb33e6102cdf6d8c5f820b07022742b576742165fcce98a007951d9f44208d261cf85b72c4b9b614905622b716520126631e2e8c8ac21c6e7b33c1560761f940ef38a0b5d30f57a048f73b239c548f017d074b64e2734009901c777c3033c1ace1ca1b6e2342e91f5d9023a79e66531099093a1c2261c34684fc3cf903414be38904d25d856110f7649d976a617f9b37f4ccc7666be50868ae53187a221d1926936cbd5206a270c1b32cca20e038b8e46115cf3b7a04ac92915bf2581a97e144e3c422d6ece224aeab310751aa756d33bd5331b41c2aa81a6532dce9389801b1910103c2323fec2bf1ac78c3f2c7329ad93d8691526772515c1052a5a63cce9f2550f5f4c265dcf7292f0cac4d3853c07f813037de876070df73889399326bdce8194eb13033f27fceb07665a6bb5b00eebc1d727c82c887d5518c384954c865a3238a743fb78d113a5dfc53e124ef629d121807d0d90ba00c6dd4ed7fa62c22195e4239877f9de6e22d1362457bbb7df59a22c0c5f1684d9e67c781458278f7ea3b7b6c3139ddf347ffbcb0b65e614fdee763d89d620a50da8afd797c4ffce4286e831b0b0ea7f2d71dae5374d71004291413049c59f117e53ee25633af6446bdcaa9ababcd6dba78df73a7ba7b9dc00000000000000000000000", .None}, + {.Shl, "-39835f8587c49a45532c58673357727459bba2f9afd5a25a5386abe12aad29ef74e231391727936e58c4b4394f29d151049b2b82189631639f524281056a29a0b82c43c47ee2455720a6a77f7647144fadbb39791cb30db15c32e6975aa698bdd61fe6454ca78423a2d19d4b81c311cc0fde29982800944e42e92997002e9ef2d5724934852738115fd4432d09dcbb4a11a0fbb99d4b46d8e157c33f6f038384365c479e70d6514167e927b7cbe44b3ee382ab68f49ac7b5da1fc9952714324d19510fc52b3b8d6f8bc7c0b1bb7acb70a0ef626506b7da674942834c8fcd8ae3777be64ff6958532b70ec031d441d0198c9a8daf3f6104a9268860d0b3e4ffa9c4677b60e496c4360b1d29f75e305f183ce2f58ee09487b54ebd1a2de96357e6417083d12834a7aecb1b165d5c73f2f1a41ec713d9d9bd766e1573c7d435a467abd28e299ec534f14877e1c7f7f36fe9e869e63c076a330e12b1c2f0ada75771972048477cc8b0bd23b20b1ff7ff599e5030ebf42391d14a25b6bbb38cb903dd209e8bdd55dd8b38fe6cbfca2cef301a87bc30dc70cd2ccfd4a7c908ae728666df3d40c7cd98566b13f8a09fa19331fb549801f1d9627ae96f505bf606498f477d038717ee9357f12d16549866025651f203a4e9bfebccd35768eb1d3f4876ffbc7b25f8f98686ec369847c0a0a0768f91b09e507f6203de1d0c8bdbd02ea122", "4d", "-7306bf0b0f89348aa658b0ce66aee4e8b37745f35fab44b4a70d57c2555a53dee9c462722e4f26dcb18968729e53a2a209365704312c62c73ea485020ad4534170588788fdc48aae414d4efeec8e289f5b7672f239661b62b865cd2eb54d317bac3fcc8a994f084745a33a97038623981fbc53305001289c85d2532e005d3de5aae492690a4e7022bfa8865a13b976942341f7733a968db1c2af867ede0707086cb88f3ce1aca282cfd24f6f97c8967dc70556d1e9358f6bb43f932a4e28649a32a21f8a56771adf178f816376f596e141dec4ca0d6fb4ce928506991f9b15c6eef7cc9fed2b0a656e1d8063a883a03319351b5e7ec209524d10c1a167c9ff5388cef6c1c92d886c163a53eebc60be3079c5eb1dc1290f6a9d7a345bd2c6afcc82e107a250694f5d96362cbab8e7e5e3483d8e27b3b37aecdc2ae78fa86b48cf57a51c533d8a69e290efc38fefe6dfd3d0d3cc780ed4661c256385e15b4eaee32e40908ef991617a4764163feffeb33ca061d7e84723a2944b6d7767197207ba413d17baabbb1671fcd97f9459de60350f7861b8e19a599fa94f92115ce50ccdbe7a818f9b30acd627f1413f432663f6a93003e3b2c4f5d2dea0b7ec0c931e8efa070e2fdd26afe25a2ca930cc04aca3e40749d37fd799a6aed1d63a7e90edff78f64bf1f30d0dd86d308f814140ed1f23613ca0fec407bc3a1917b7a05d42440000000000000000000", .None}, + {.Shl, "-eb3a7aa7a26bb704416eafad1e8ff370e419bf8deee8738626bb07d5df77100dda5a86f2914dcb0bacdb9e6ec20c6332696d0d408e501fe9918ea818be823ecb21138af0965de796c1f3075981fb3abe36b84fccf724baf413a38d4a67b77dcf23b17863700be79d28e01305b14188b77d824b8b7c87391e1a3e4a4987399ef2587235e84a03acac5e16acb8c03d4945238d90dd4e40d34e35a3f1facab48fd613a424569065d3ee0f5dfcd8f22068431f179050eea7c7c89c7d7eed9bb8f12ece3161a2ad5d48bb7a692a29c2286e8ee1faefd7e0e6424048e6a676a431c422e5f008568bf8d42d207bc2f4e88fecc943ef31c0c8e089aea8e47166da45c5a9b2ec73d96b2818e63aedab6b37eea12cef33a7266f15cb86127aa7a4cf8bb8a9dab8f9aa79821938957963a386407c704e51959e1cc6447424285ba88310435c2ce91e8a14fc1fd0fcd584523417a299971c3c1827636514fae8565c5050c8fc651e0ac1fe2fc93fe08a7a379b9ade64fb96a312214bc03c42d7c37811df7483f8dbabc337e5530d7930277946fd04e2b57ec0d92283f19ef2f0a95854f989a76b0f30c1c30d1c704673e9c56a05944af5ad30efa887e9da8aa65c0a89a08b75cb6d4ba3368271078bba6323c956ad267d67691c2647da5bb8d28cc84a378010982420b9132d35de439b60d5da53489a97cd1e718cdc4552a9e1200fea780975", "54", "-eb3a7aa7a26bb704416eafad1e8ff370e419bf8deee8738626bb07d5df77100dda5a86f2914dcb0bacdb9e6ec20c6332696d0d408e501fe9918ea818be823ecb21138af0965de796c1f3075981fb3abe36b84fccf724baf413a38d4a67b77dcf23b17863700be79d28e01305b14188b77d824b8b7c87391e1a3e4a4987399ef2587235e84a03acac5e16acb8c03d4945238d90dd4e40d34e35a3f1facab48fd613a424569065d3ee0f5dfcd8f22068431f179050eea7c7c89c7d7eed9bb8f12ece3161a2ad5d48bb7a692a29c2286e8ee1faefd7e0e6424048e6a676a431c422e5f008568bf8d42d207bc2f4e88fecc943ef31c0c8e089aea8e47166da45c5a9b2ec73d96b2818e63aedab6b37eea12cef33a7266f15cb86127aa7a4cf8bb8a9dab8f9aa79821938957963a386407c704e51959e1cc6447424285ba88310435c2ce91e8a14fc1fd0fcd584523417a299971c3c1827636514fae8565c5050c8fc651e0ac1fe2fc93fe08a7a379b9ade64fb96a312214bc03c42d7c37811df7483f8dbabc337e5530d7930277946fd04e2b57ec0d92283f19ef2f0a95854f989a76b0f30c1c30d1c704673e9c56a05944af5ad30efa887e9da8aa65c0a89a08b75cb6d4ba3368271078bba6323c956ad267d67691c2647da5bb8d28cc84a378010982420b9132d35de439b60d5da53489a97cd1e718cdc4552a9e1200fea780975000000000000000000000", .None}, + {.Shl, "de5b972fd887ff18ce1444b39418de9482e4f0027f5595286bc969f0b5a1b907632de9bdb16902ab235e800fcf347a710cf49adbac676ef53f60163d738412bd232dae377f7949fbfb115c71628b36fd14eb8488144b5283e402f53b7596a875bdc42184b8c25266e726c700184f38f56ca08698819866d16483a4a1ade145770c21570651430f1efc6f0014f2f851f1c51f8214208eabd277a16e4e91bd1b8fc294c2ba924c8055942f380f1b1a4766e309b748c8809a875bf4bb740de7d87beee2ac67e8d1722cdd92339980a2cbf545a2abb63f100ef09bfbb5f4539b99cccdfe695bac41e6909eae374f4991d702a447e462a519f0359d3d9e154b0d9f83c08f0f9e236476323dcb68ae99b09ff19fda8e3c9bd381af25e3ff7218a44cd66ee30f71e5e6f47f1792a6cb6670d0656ee433ad3603554e8cef422190cd2013042ae573ee2547c03b637aadad4b523baf5bed03e535bd57392b22c07dc1cc4bd09c568afc5f60acbf82de3715a9db5ecda1a9a28d8111007cdf700d316440333c76bda0cd7e76a0361f89359849769e2762c4474091a70123594c069699adc7828bc19ee1882010b49360d73d612922eaa8174710226a4072b878ab617db1ebbd82bca80b817f9549c7095f6e25c91f3134760f3549905c88195a1ee190099e61e4d1518ac65a8237a9674964adef9072b8f011949451fc7bcc671add6674b", "72", "3796e5cbf621ffc63385112ce50637a520b93c009fd5654a1af25a7c2d686e41d8cb7a6f6c5a40aac8d7a003f3cd1e9c433d26b6eb19dbbd4fd8058f5ce104af48cb6b8ddfde527efec4571c58a2cdbf453ae1220512d4a0f900bd4edd65aa1d6f7108612e309499b9c9b1c00613ce3d5b2821a6206619b45920e9286b78515dc30855c19450c3c7bf1bc0053cbe147c7147e0850823aaf49de85b93a46f46e3f0a530aea4932015650bce03c6c691d9b8c26dd2322026a1d6fd2edd0379f61efbb8ab19fa345c8b37648ce66028b2fd5168aaed8fc403bc26feed7d14e6e673337f9a56eb1079a427ab8dd3d26475c0a911f918a9467c0d674f678552c367e0f023c3e788d91d8c8f72da2ba66c27fc67f6a38f26f4e06bc978ffdc862913359bb8c3dc7979bd1fc5e4a9b2d99c34195bb90ceb4d80d553a33bd08864334804c10ab95cfb8951f00ed8deab6b52d48eebd6fb40f94d6f55ce4ac8b01f707312f42715a2bf17d82b2fe0b78dc56a76d7b3686a68a36044401f37dc034c59100ccf1daf68335f9da80d87e24d66125da789d8b111d02469c048d65301a5a66b71e0a2f067b86208042d24d835cf584a48baaa05d1c4089a901cae1e2ad85f6c7aef60af2a02e05fe55271c257db897247cc4d1d83cd52641722065687b86402679879345462b196a08dea59d2592b7be41cae3c046525147f1ef319c6b7599d2c0000000000000000000000000000", .None}, + {.Shl, "9a2fe60ff4431db1de5d7ab01f823a15103e12907363f1cbac0f6a97e2c9a4d9a12f9ddcc7827a79ea1cce959c4ba3a5a7bc46ed8279fe29122a6d0da8a4ec1444411c908769e841a1488e238eed7188b86891f089ac37187b715badab4b292ff9e1769471072f09aecc7cd761e46be5a74a313326e1ceaeb7bb8b9428d363598aae76bb275c32cfefe1acf7843b777b3f4504d68e5ebf8cc9b6d80260230f1cdd16b011e3871acd633ca351778def64db1f28aee75a80a81f40d84accf9f824c59061d9b44678e65acf3e00eda89a2c85db53eb7cb042b683ca688b2e9a1b33314b59f7b8f51b99dab6ad2d643225edf7af979f58a3bf57a5d84ec72a40a1428e07e15553817a951474302ea111a4c6b3601ebca2c908f59cbd0c90fecd5398021d57de9af28e96b4fa60d758f156a9811005e5d4520a92c44301020153b1e5df10bc77f9711b11de1a9414c18cf269bfc2be6ed9e465fa3159c7dd47dcadf79da09be6ec9618a50ce40449756aa5fe33196848323d9de4f49322ee9ff17f2f41f5a880b221127f15279a35f7dd6578c9f9eb471db0db61c87f194ded8b10b99a3f669c7d94471bd7d12c8c27cded556b6b5d71aad1cd53fc259b0e76a5041e11b488eaf69f26ff2e53b7802f531a75f8f6daae84f042151a7cd87ad82cb34b091aed36b89beeaab9301a02fb3c53b5e8be8231e5b1123a584d1b24b381d580", "2a", "268bf983fd10c76c77975eac07e08e85440f84a41cd8fc72eb03daa5f8b26936684be77731e09e9e7a8733a56712e8e969ef11bb609e7f8a448a9b436a293b051110472421da7a1068522388e3bb5c622e1a247c226b0dc61edc56eb6ad2ca4bfe785da51c41cbc26bb31f35d8791af969d28c4cc9b873abadeee2e50a34d8d662ab9daec9d70cb3fbf86b3de10edddecfd14135a397afe3326db6009808c3c73745ac0478e1c6b358cf28d45de37bd936c7ca2bb9d6a02a07d03612b33e7e09316418766d119e3996b3cf803b6a268b2176d4fadf2c10ada0f29a22cba686cccc52d67dee3d46e676adab4b590c897b7debe5e7d628efd5e97613b1ca902850a381f85554e05ea5451d0c0ba8446931acd807af28b2423d672f43243fb354e6008755f7a6bca3a5ad3e9835d63c55aa60440179751482a4b110c0408054ec7977c42f1dfe5c46c47786a50530633c9a6ff0af9bb679197e8c5671f751f72b7de76826f9bb258629433901125d5aa97f8cc65a120c8f67793d24c8bba7fc5fcbd07d6a202c88449fc549e68d7df7595e327e7ad1c76c36d8721fc6537b62c42e668fd9a71f6511c6f5f44b2309f37b555adad75c6ab47354ff0966c39da94107846d223abda7c9bfcb94ede00bd4c69d7e3db6aba13c1085469f361eb60b2cd2c246bb4dae26fbaaae4c0680becf14ed7a2fa08c796c448e961346c92ce0756000000000000", .None}, + {.Shl, "ac5eb473b383b32dc057712cd826737344f0202183721b59f295fb6e59b1e3f2e41f2e0be3372367b3d60b4d32e590cff26f5c57f3fbf010f76d910ac2dd1cd27a389dd881e15aa2f858eef085d1600341a1d30e546a7307eb480485e6836751a46e1d659890f2ab141cce38ab82dee2808fb6c1e7f0f38a3e483b2399edc1b1065df62f022233a5b92e6adcf01c2c18419c9c0715865ae6b26efe61dcbe6e514f39d9c37fa8b11973610133995af05459402d1e5d1343152dff363bc849915856a80d550d0f4fc93528179eef37b8ab06a0817f67681fb398b469d674acdfcbfd306a46ef60c67c2a2c2d78116ed1c54a6c78f49af70db6ca7175d557e4fd7fccd5b38ca4d4a7b8d7ee89070d57aead0c7e13f4a3468acf20dafe8e79034cdc46eb1e10a355ccb153d17a4a8479ada56bbb400950a9978037e22a471dc88fdb6f16414e008545d338aaa2cccf08b61d4469d38c04642853126dbd007f188b5ecbbbfcd8b3f64ca3ee1aa6086123274eb4c2e31a208b93f23e47289bb1286d2887ae3fa92cee9b22150adf9d68ee52b0bb4d23d88e962d5424fbe708bc9587501b9dbbc72f9324d1cc61a6a9c27506aeb3b72dcd47a9fb3937047ff988883e7f1c8f34068f36522300e887058f96ecbfb1ebb01654b4036e2906ff0b8e67e9f02f9da09e54b9036ad69ccbea48314ac6937f6b91ad1435cb3752cdb8c127723", "56", "2b17ad1cece0eccb7015dc4b36099cdcd13c080860dc86d67ca57edb966c78fcb907cb82f8cdc8d9ecf582d34cb96433fc9bd715fcfefc043ddb6442b0b747349e8e2776207856a8be163bbc21745800d06874c3951a9cc1fad2012179a0d9d4691b875966243caac507338e2ae0b7b8a023edb079fc3ce28f920ec8e67b706c41977d8bc0888ce96e4b9ab73c070b0610672701c56196b9ac9bbf98772f9b9453ce7670dfea2c465cd8404ce656bc1516500b479744d0c54b7fcd8ef212645615aa03554343d3f24d4a05e7bbcdee2ac1a8205fd9da07ece62d1a759d2b37f2ff4c1a91bbd8319f0a8b0b5e045bb471529b1e3d26bdc36db29c5d7555f93f5ff3356ce3293529ee35fba241c355ebab431f84fd28d1a2b3c836bfa39e40d33711bac78428d5732c54f45e92a11e6b695aeed002542a65e00df88a91c77223f6dbc5905380215174ce2aa8b333c22d87511a74e301190a14c49b6f401fc622d7b2eeff362cfd9328fb86a9821848c9d3ad30b8c68822e4fc8f91ca26ec4a1b4a21eb8fea4b3ba6c88542b7e75a3b94ac2ed348f623a58b55093ef9c22f2561d406e76ef1cbe4c934731869aa709d41abacedcb7351ea7ece4dc11ffe62220f9fc723cd01a3cd9488c03a21c163e5bb2fec7aec05952d00db8a41bfc2e399fa7c0be76827952e40dab5a732fa920c52b1a4dfdae46b450d72cdd4b36e3049dc8c000000000000000000000", .None}, + {.Shl, "7ece3cc35c8f90516227fe5aeb05642521290d048c81039d2e679cc499bd5511830628a9ee275557137323a25a8c472f78efa518e7e069ebd576bdaa76b836eded0ba2386ccb21fefb7cfe336f754afa8f205560b144acfae900436171a07b039dc45abce5c08e98a0705795251cd10f289af5c7ff2d8c05e39a03028495c3c02d7f4a707dd7d9f7028c2764eedde5ea38e1d1d352a1ace64b441f4d7ca3643d2337e64b35472b3fe623e71715cdadb00334bb1b86bf9f2b632781421d25a44fa1d9ea3e20b27c58730ee0acfb3fceaf663bd9ddae339bdd31cfe99d37ac6e411724384899a25d835b77ea9616c466da1b7aa52e996bcca3dbba3d89644a23f0e94beb1b1d8fb91251d0ca1e0caf54dc9210d7d420f9b37cffd07b4942e9e7da3d851914534565071394a9b88d40b084d166efbba670d333b3022bf72c32407e690f28e397dd07cb366f4e345fbae5cd2bbd89931506a6468f34f016cdeb84d959dd43f05b6040d622a91d57ceb762aedb75f540f8a923ce240d6d3d15215c73c515808c36fa74f0a59ff88e55fde5526c70ef3ea0f310354181cd8b8712cd694d914df91a09ec3da2a95fc0b09a8c9b9f4ac10af66ee78d491c1b18c889a5e8c47f16fe39a5d1f7aa9df0492f96d66d3359d57483302340a946083016c3df47f940e03875245038d8a3eaf49efab67e1157e6132b2098afc80159dbdcc2d001", "2f", "3f671e61ae47c828b113ff2d7582b21290948682464081ce9733ce624cdeaa88c1831454f713aaab89b991d12d462397bc77d28c73f034f5eabb5ed53b5c1b76f685d11c366590ff7dbe7f19b7baa57d47902ab058a2567d748021b0b8d03d81cee22d5e72e0474c50382bca928e6887944d7ae3ff96c602f1cd0181424ae1e016bfa5383eebecfb814613b2776ef2f51c70e8e9a950d67325a20fa6be51b21e919bf3259aa3959ff311f38b8ae6d6d8019a5d8dc35fcf95b193c0a10e92d227d0ecf51f10593e2c398770567d9fe757b31deceed719cdee98e7f4ce9bd637208b921c244cd12ec1adbbf54b0b62336d0dbd52974cb5e651eddd1ec4b22511f874a5f58d8ec7dc8928e8650f0657aa6e49086bea107cd9be7fe83da4a174f3ed1ec28c8a29a2b28389ca54dc46a0584268b377ddd3386999d98115fb9619203f34879471cbee83e59b37a71a2fdd72e695dec4c98a835323479a780b66f5c26caceea1f82db0206b11548eabe75bb1576dbafaa07c5491e71206b69e8a90ae39e28ac0461b7d3a7852cffc472afef2a93638779f5079881aa0c0e6c5c38966b4a6c8a6fc8d04f61ed154afe0584d464dcfa560857b3773c6a48e0d8c6444d2f4623f8b7f1cd2e8fbd54ef82497cb6b3699aceaba419811a054a304180b61efa3fca0701c3a92281c6c51f57a4f7d5b3f08abf30995904c57e400acedee616800800000000000", .None}, + {.Shl, "bcea33f4f7ccba4fbf92a4df8852f6d225b7e6d8d0968f09c62f03e22294a490890ec1d57f0532bcfcdf9a83ff8f53874277063e7ccb0133554064050058b3913a22817d52e96f30248c57c4b05b1bf9bda749d4656e9b01105730d0714ee85c96c6b7b9252d89f57f41709b929e3702766c13ae9537c0ae2e099d536404252b3dca7b6aa5ace68d1ee46003d8b3b87df61fd6017a70c99aaba220dde4631bae42ed7f70bbe463a773fa2a493876f812db0be8c2cdef534e8eb02321f0a4b13ec9aca5f828fddd46c096720bec65657ad25e526000eb80ff2c07b92c9d284c1564fc9013ff275570da0475f96bad8f61126861c0bc68774a3f808d758176437eeafdaa5d22e029fcd7870973c4bc864ca4c5fe37e37ec93146d4a48f8a3801c1fd57287a5870c8dc8de67c38bf2b119f3cff97b580ebaa22e35bd366e2220325d4cea4fb39852be88d0b446e05ec31a324cdf24f6a0160e84dec416b69fa4a288dd6a608730611decbcbc96d45518338979f8c043e0c0e5102b2f6a3033150d2ac59be03ebe356c2f0d6453a018c2ea7b831f0292473d3cb9b9dec605ca256eda225aa58cf1e3d727b32594e4948e686107790f666209522e986d31109b9355ed301c2e31f0b4ebebcca68b62ab6071c24dd85e619190e02a075d4a266cff60c0e22f78512924f34178321194560c54612d8ad1a50c4af0f985b1c97724d975f", "51", "179d467e9ef99749f7f2549bf10a5eda44b6fcdb1a12d1e138c5e07c445294921121d83aafe0a6579f9bf3507ff1ea70e84ee0c7cf9960266aa80c80a00b16722744502faa5d2de604918af8960b637f37b4e93a8cadd360220ae61a0e29dd0b92d8d6f724a5b13eafe82e137253c6e04ecd8275d2a6f815c5c133aa6c8084a567b94f6d54b59cd1a3dc8c007b16770fbec3fac02f4e19335574441bbc8c6375c85dafee177c8c74ee7f4549270edf025b617d1859bdea69d1d604643e149627d93594bf051fbba8d812ce417d8cacaf5a4bca4c001d701fe580f72593a50982ac9f92027fe4eaae1b408ebf2d75b1ec224d0c38178d0ee947f011aeb02ec86fdd5fb54ba45c053f9af0e12e789790c99498bfc6fc6fd92628da9491f14700383faae50f4b0e191b91bccf8717e56233e79ff2f6b01d75445c6b7a6cdc444064ba99d49f6730a57d11a1688dc0bd86346499be49ed402c1d09bd882d6d3f494511bad4c10e60c23bd979792da8aa306712f3f18087c181ca20565ed460662a1a558b37c07d7c6ad85e1ac8a7403185d4f7063e05248e7a797373bd8c0b944addb444b54b19e3c7ae4f664b29c9291cd0c20ef21eccc412a45d30da62213726abda60385c63e169d7d7994d16c556c0e3849bb0bcc32321c0540eba944cd9fec181c45ef0a25249e682f0642328ac18a8c25b15a34a1895e1f30b6392ee49b2ebe00000000000000000000", .None}, + {.Shl, "5e2cf14f3bf45937bd5b882fb318703f3ea621896d5d00cb5cd2677f60450f3e2cade6551bedae931d3720b37332ffd65c6fb6a8512bd03b83077b1523dac5765308a8f3d10543093ae5789f497090ed94664f6eba820e266b80931cb9f4b133a2e8c2e2ae55de84c394492312c42dc11ccb57b3cd7df15267641e06e834b526f4f6954d1806809b57f723659688cdb989c50f17081a6b4270cfa8802e86c1e149ada2e23e4b7a6a6e955704df27a9018bc3bbfe390f3cb17ab97040039fbfa21e9079821660f468a6c7f9e3c197950e96e5cc607c0f7d918e6dfb42723f8919856dee8528dca18912e360515ee3992e7cd55566fc1ed494e2203b0cd9e221a997e66984ee75bbe41e7cee6937335508e03fd40cbe2d9d3a7ef6ef4bfbb8ed74512d0d7b0d809ffa14215b64ebb370044db6225d291aad46069d3974d3d55af430dc01db264959ec6eedf2416dceda651a046113ee5b773aa1798ed47a6c6092b8464a520761d2e15f7849a555c5f664e138be3a1d84f0240fc087d718fbf342d7a0c14bf82d03ba201fd50b20147013b22d81bd3bef85c5efbda7f4d3c8585a2bb0accb28139b3bbd1dec2860bd1fd3fae49d2156180e781517f4c8441aba1f5c70ccdf4d6b5984b42c740c2b30f9fb7580f8a7c6854d618bb2c74d438eb8d93ef2fff6b0c074a34c16bbb06cc7c4311d1e03ed5ab27fce7d0ab7cb060625d0", "6c", "5e2cf14f3bf45937bd5b882fb318703f3ea621896d5d00cb5cd2677f60450f3e2cade6551bedae931d3720b37332ffd65c6fb6a8512bd03b83077b1523dac5765308a8f3d10543093ae5789f497090ed94664f6eba820e266b80931cb9f4b133a2e8c2e2ae55de84c394492312c42dc11ccb57b3cd7df15267641e06e834b526f4f6954d1806809b57f723659688cdb989c50f17081a6b4270cfa8802e86c1e149ada2e23e4b7a6a6e955704df27a9018bc3bbfe390f3cb17ab97040039fbfa21e9079821660f468a6c7f9e3c197950e96e5cc607c0f7d918e6dfb42723f8919856dee8528dca18912e360515ee3992e7cd55566fc1ed494e2203b0cd9e221a997e66984ee75bbe41e7cee6937335508e03fd40cbe2d9d3a7ef6ef4bfbb8ed74512d0d7b0d809ffa14215b64ebb370044db6225d291aad46069d3974d3d55af430dc01db264959ec6eedf2416dceda651a046113ee5b773aa1798ed47a6c6092b8464a520761d2e15f7849a555c5f664e138be3a1d84f0240fc087d718fbf342d7a0c14bf82d03ba201fd50b20147013b22d81bd3bef85c5efbda7f4d3c8585a2bb0accb28139b3bbd1dec2860bd1fd3fae49d2156180e781517f4c8441aba1f5c70ccdf4d6b5984b42c740c2b30f9fb7580f8a7c6854d618bb2c74d438eb8d93ef2fff6b0c074a34c16bbb06cc7c4311d1e03ed5ab27fce7d0ab7cb060625d0000000000000000000000000000", .None}, + {.Shl, "-a639714200090ff6f6b4d80239657308ed02a6555a893be91caced0ca053a32f9afe00f959f8a64b7679a8b5897ee565043a0a5087f0413484d77d8cf3300fe734a03c5066b1b80b146d6737a71a6e4a342175183126c262e3bc59049f23ea321d21a06f0b4b6ea8748c0eaad6c92c13eeaa7c33a967d3f00a54277d4fb967552660389be2f73833c937a6de7dba45a7e3a82942d922254afe8b02908a36b5540129674d0de61744b9e9b93b5f58a7b6a9d37c5ea1020954b3d5e89338d8b27a18664584672ddc709a1397fa3b3677cd3b8735d9999d0221312c1f4f7252eda94c7b787165ae4ce63b3eab5bf913178fe880195c2fe7e57836573a9cbc70ad96ccd3cbcf891fc00cb6dd52aab1d97455b747e8f87af13edfef9658819ab3ffb2ad7c85e621f24a9d5d09071e39c3b2a7dc49fe3aa228af7ce5c701f04115cbe443e9cf2d0c982c928a0fe404cbf6b0c67b12cb2bdfec2cd1a6f0714b1290d192470073f6a4d68959ab397bd44619e8aac558624b4a0d5bfb5b6b82f80d15a42fe19a86142b569a81ade9350eeece1d792e2750bfa3d5c24f00e285963799d62bd1222cbc385ac32aae0d50e02d974102bbd3487d5b6741d54447cf07878288bb224f1d2c47a9f57d1cdc4e6ebe16edd75e935ea66e91c7c2effadb2e7f3bbb58e4029d7299f4053637c58f3e7ae6b519118c8c593d5301c99fc6b30766775ca5", "39", "-14c72e28400121feded69b00472cae611da054caab51277d23959da1940a7465f35fc01f2b3f14c96ecf3516b12fdcaca087414a10fe0826909aefb19e6601fce694078a0cd63701628dace6f4e34dc946842ea30624d84c5c778b2093e47d4643a4340de1696dd50e9181d55ad925827dd54f86752cfa7e014a84efa9f72ceaa4cc07137c5ee7067926f4dbcfb748b4fc7505285b2444a95fd160521146d6aa80252ce9a1bcc2e8973d37276beb14f6d53a6f8bd420412a967abd12671b164f430cc8b08ce5bb8e134272ff4766cef9a770e6bb3333a044262583e9ee4a5db5298f6f0e2cb5c99cc767d56b7f2262f1fd10032b85fcfcaf06cae753978e15b2d99a7979f123f80196dbaa55563b2e8ab6e8fd1f0f5e27dbfdf2cb1033567ff655af90bcc43e4953aba120e3c7387654fb893fc7544515ef9cb8e03e0822b97c887d39e5a19305925141fc80997ed618cf6259657bfd859a34de0e2962521a3248e00e7ed49ad12b35672f7a88c33d1558ab0c496941ab7f6b6d705f01a2b485fc3350c2856ad35035bd26a1ddd9c3af25c4ea17f47ab849e01c50b2c6f33ac57a244597870b586555c1aa1c05b2e820577a690fab6ce83aa888f9e0f0f051176449e3a588f53eafa39b89cdd7c2ddbaebd26bd4cdd238f85dff5b65cfe7776b1c8053ae533e80a6c6f8b1e7cf5cd6a32231918b27aa603933f8d660ecceeb94a00000000000000", .None}, + {.Shl, "-f8d4ba503afbf9a2c2435518f1b2dd6fd69aab478b277b07d303883d308b5043272c4869ef234d6aa84ef8ba28b1348f2f10ed399273ba23ffbe33460c2256497fb35dc20659ee8dfcd6314dd2e379073976a34011c72ee078fa5b750c524325da37a74ca49444a85aa85ce07a2e26f5a640d40820c75bb9be2b9fbf4db38c8fb10269b842854b4b3e3a9c8af0df6e2014a3d0872ba9b7cda0053b5b2b1ff533b8112013210031839b57768ecb9680a8987c498b1d42941b0614c9d2056764a080b7ddf1a89c099091bc0433fd26e22b1fde549be16777317b8ed45f5715bada5f0b860cf3d040571a58054b2bf4951312fe07cfc26a5fc6e2844b857bdab27270d13d20e6d284b6de5a480f9c074ddae4ec9789690097f95ce07503c04cc069fce02beeff7a01bb3cc444814ca2c65f543b4912cbd00a2c0914f09509da4ac6a712b09d21da5da7a89808dc94246548b06b82a191f6d06d6dc536588903d3e39f0885c9f9dbd645ef32c33f01b5e9cc7bc486b9a4a7acc3d403102ed5e5955fbdac3894339b76d528625f89eae8c0ebe1edbb17a644f0fd4ddeb86976fcbe7d0184b24e2d1e6909b600437bb094bd5d8a31053943b5ed984bc176d01d083a5df062e4e70383ae93c18ad6d52ba94afb46e9b96b49eca2d36565277410b91ac6f88109f731e7dc485e026eaa2fbca3725285a9ddcc95bb4de185141a7c0e2500", "3a", "-3e352e940ebefe68b090d5463c6cb75bf5a6aad1e2c9dec1f4c0e20f4c22d410c9cb121a7bc8d35aaa13be2e8a2c4d23cbc43b4e649cee88ffef8cd1830895925fecd77081967ba37f358c5374b8de41ce5da8d00471cbb81e3e96dd431490c9768de9d32925112a16aa17381e8b89bd699035020831d6ee6f8ae7efd36ce323ec409a6e10a152d2cf8ea722bc37db880528f421caea6df368014ed6cac7fd4cee044804c8400c60e6d5dda3b2e5a02a261f1262c750a506c18532748159d928202df77c6a270264246f010cff49b88ac7f79526f859ddcc5ee3b517d5c56eb697c2e1833cf41015c6960152cafd2544c4bf81f3f09a97f1b8a112e15ef6ac9c9c344f4839b4a12db7969203e701d376b93b25e25a4025fe57381d40f013301a7f380afbbfde806ecf3111205328b197d50ed244b2f4028b02453c25427692b1a9c4ac2748769769ea260237250919522c1ae0a8647db41b5b714d962240f4f8e7c221727e76f5917bccb0cfc06d7a731ef121ae6929eb30f500c40bb5796557ef6b0e250ce6ddb54a1897e27aba303af87b6ec5e9913c3f5377ae1a5dbf2f9f40612c938b479a426d8010deec252f57628c414e50ed7b6612f05db407420e977c18b939c0e0eba4f062b5b54aea52bed1ba6e5ad27b28b4d95949dd042e46b1be20427dcc79f71217809baa8bef28dc94a16a7773256ed3786145069f038940000000000000000", .None}, + {.Shl, "-daeec82b57fe047bee14894348ecf3c933501aaf9bc66a5ae68ae8fe48f21f24953e196798c7b20f2b20ce83c9508dd0879174e8bc90a9d71eea31e1942712afad9669de8414ecbe2abee5d27972606df43c3440048a2ca28335255e43b8054aceae701ff2e673d9859b302711dcefefc1107a65fbb1d8274fc1a27279d964ba9f2e2fa1e9604205855f63388c14c38a2ab8401064d222d8b0021ce82796d7adc06c4ed453b0d7fa74b3dd9b4832b46f9f80bcb7c177fd44ab532aa1ca0cf4641879d3e95efe7ca43d99661326fcdcda93969643d880146fa914c135ff88d32471ab555450182db4fdc7eab746b81ace4043738e18ba7a82a81c5da3ab526c1c069cdf3084aba44148085f055a651036ed0f1133f7f4ced3c212750c986ad542d454b9d8cd99cd63aa98ac27cf7a95c47621e1a9239730a6977fc35305cb289b7b1c7c3c9266d83a8dbc4ef335b3db1cfab12971a5fee0069758994fee2e53c85803e1d078765d06e5bbb0d351cd1c03f7c72f604aa7266beb8a46c68fbfabf4f7fe23ae6d98336bf4fcc7af14d0336e87f072fed9d9e5ee971071cbe322dd31f5629ffe14c3bb701ab08093791775fc3e607ad5957e330765ddeb74a18e9c0d9f74288d68eb4907c84075fc11a3a091b64fc58f01a6dadb01317870ca2156972b944efc1ffe969a00188646e29368293b14c57dc94787bd6a052934126113cd", "26", "-36bbb20ad5ff811efb852250d23b3cf24cd406abe6f19a96b9a2ba3f923c87c9254f8659e631ec83cac833a0f254237421e45d3a2f242a75c7ba8c786509c4abeb659a77a1053b2f8aafb9749e5c981b7d0f0d1001228b28a0cd495790ee0152b3ab9c07fcb99cf66166cc09c4773bfbf0441e997eec7609d3f0689c9e76592ea7cb8be87a5810816157d8ce230530e28aae1004193488b62c00873a09e5b5eb701b13b514ec35fe9d2cf766d20cad1be7e02f2df05dff512ad4caa872833d19061e74fa57bf9f290f665984c9bf3736a4e5a590f620051bea45304d7fe234c91c6ad55514060b6d3f71faadd1ae06b39010dce3862e9ea0aa071768ead49b0701a737cc212ae910520217c15699440dbb43c44cfdfd33b4f0849d43261ab550b5152e7633667358eaa62b09f3dea5711d88786a48e5cc29a5dff0d4c172ca26dec71f0f2499b60ea36f13bccd6cf6c73eac4a5c697fb801a5d62653fb8b94f21600f8741e1d9741b96eec34d4734700fdf1cbd812a9c99afae291b1a3efeafd3dff88eb9b660cdafd3f31ebc5340cdba1fc1cbfb676797ba5c41c72f8c8b74c7d58a7ff8530eedc06ac2024de45dd7f0f981eb5655f8cc1d9777add2863a70367dd0a235a3ad241f2101d7f0468e8246d93f163c069b6b6c04c5e1c328855a5cae513bf07ffa5a680062191b8a4da0a4ec5315f7251e1ef5a814a4d049844f34000000000", .None}, + {.Shl, "-b7d178baa0c732f2d3eb8818197b170f7721323101fb3d16e96e800bf1927679548034c90c0c29ebc4641f0c16bfb05cf554170b6b60b00085218a658d8fcdc3ef07315c27bf43fdfea34d50076a8b19a4c9ec5d2c77000eaa36d215e7bd962c6c2f59756738c141178f738424ca6a695526e77679ff86dcdb049dfee82a68b9a7cfe1e424946b0f4bf44ae2e0ba6aa629e9a51e6eb95f9aad87be548736ac1b76ca6d0a06159b02305834963418c406f19199da7cb29a71fd8da7bdef82fd4e220a85568efb74ef7897f935e49d4a8e486ec4ab6c2796eb880941867cf9dcca29257c1765381a78720b0099a9b34d531cddc30d6e892b0bf77b95c5984059dd3e3d7f5a841e2d5570cecc3e6726e232772ae6436ddad560514e5da9feab07a91752d4bcbd3caa28ba3a3def157179f7acdfed2f73b76429b08d295186c60354e32509a6ca767e4b8b4f8e888dd50cedfb67e5b16fa615e6d0bd18339f3586c23208c4b854a05924dd2e654075e4f10006a92e6ed29553de53c77852f569221dfe2bce46ab2f53a79dcbec07571f7ceb32337bd22d92f6c1a29998d2c447b084a68836730677f4201096c4a7bd0b9924a3fffa9d983b3b74b6561a839f09a20e1c47f9c394849b467f88edc1f812fbf3d6b3e30d3331c5f0ab8e6b08fdafcb3ba12c6c22ab69dba48a48631648d23a50c9035c4eb5e40a65b9ced2a731b48982", "1d", "-16fa2f175418e65e5a7d7103032f62e1eee42646203f67a2dd2dd0017e324ecf2a9006992181853d788c83e182d7f60b9eaa82e16d6c160010a4314cb1b1f9b87de0e62b84f7e87fbfd469aa00ed516334993d8ba58ee001d546da42bcf7b2c58d85eb2eace7182822f1ee7084994d4d2aa4dceecf3ff0db9b6093bfdd054d1734f9fc3c84928d61e97e895c5c174d54c53d34a3cdd72bf355b0f7ca90e6d5836ed94da140c2b360460b0692c6831880de32333b4f96534e3fb1b4f7bdf05fa9c44150aad1df6e9def12ff26bc93a951c90dd8956d84f2dd71012830cf9f3b994524af82eca7034f0e416013353669aa639bb861add125617eef72b8b3080b3ba7c7afeb5083c5aaae19d987cce4dc464ee55cc86dbb5aac0a29cbb53fd560f522ea5a9797a79545174747bde2ae2f3ef59bfda5ee76ec853611a52a30d8c06a9c64a134d94ecfc97169f1d111baa19dbf6cfcb62df4c2bcda17a30673e6b0d8464118970a940b249ba5cca80ebc9e2000d525cdda52aa7bca78ef0a5ead2443bfc579c8d565ea74f3b97d80eae3ef9d66466f7a45b25ed83453331a5888f61094d106ce60cefe840212d894f7a17324947fff53b307676e96cac35073e13441c388ff3872909368cff11db83f025f7e7ad67c61a66638be1571cd611fb5f96774258d84556d3b7491490c62c91a474a19206b89d6bc814cb739da54e636913040000000", .None}, + {.Shl, "c37bfc5a84f5cc317101953ad895728ad6525a3d7318b522625cbb0329c6842efdefcc516dcb24734b15f59c5f1965573cc9d313dc337a2363c28422b0d3430d6b8738823c941148d825cd549613733c741b74140c37744fd6e5fefe2db99e1a61711edca6081ced5dcb15a4ecefb970a047b97901987358961b6647b7dfe4a2759fb021d5ca44c667d34b32141e228a375354be6ede304de8ff3376232c416b6109a2781c450a07b8702bf674a943720da2fae5160ca893192f6bffd630a2afe1883367025cd771a477af84dc357f44bcbebaf02b3e0bbea931a4802263103acb2d59cdc9ba12315c351be306bf9d5d89f960f6cb7da07c5bc4367f2388d3a359fe7a5a4bfb9d14c908f5627b58a3c3e81458f255eeadba725ffbcfae38716e246c2e22d10154daeaeedc21937125d47feb3cd41920dcc01d668eb4f75028d88926a208e377356e0e56a2bb3c09337f33ec03c46f40e47a6628a67c7ccfe0211d6cd90415caca2efbf98835d1bd4ede31e10c13783685c9c1144c25190b004c61e5ca5f8f4bc9c4b2ab9d63460eaacc6e77a23e6f6d790088b9e55a75cec6f700d9dca98c05692c6669093348707686a492b479630b3c5a53f4265f371c7e615bc35750d7ccf890fd66cddd19c2b55bbdceab37abd29d443b439c75f0bb09f3fed886afd42ba9ed8fa022ab9437b1e88d3940c2d41f571b99cce944c5973295", "43", "61bdfe2d427ae618b880ca9d6c4ab9456b292d1eb98c5a91312e5d8194e342177ef7e628b6e59239a58aface2f8cb2ab9e64e989ee19bd11b1e142115869a186b5c39c411e4a08a46c12e6aa4b09b99e3a0dba0a061bba27eb72ff7f16dccf0d30b88f6e53040e76aee58ad27677dcb85023dcbc80cc39ac4b0db323dbeff2513acfd810eae5226333e9a5990a0f11451ba9aa5f376f1826f47f99bb119620b5b084d13c0e228503dc3815fb3a54a1b906d17d728b0654498c97b5ffeb185157f0c419b3812e6bb8d23bd7c26e1abfa25e5f5d78159f05df5498d2401131881d6596ace6e4dd0918ae1a8df1835fceaec4fcb07b65bed03e2de21b3f91c469d1acff3d2d25fdce8a64847ab13dac51e1f40a2c792af756dd392ffde7d71c38b7123617116880aa6d75776e10c9b892ea3ff59e6a0c906e600eb3475a7ba8146c4493510471bb9ab7072b515d9e0499bf99f601e237a0723d3314533e3e67f0108eb66c820ae565177dfcc41ae8dea76f18f08609bc1b42e4e08a26128c85802630f2e52fc7a5e4e25955ceb1a3075566373bd11f37b6bc80445cf2ad3ae7637b806cee54c602b49633348499a4383b4352495a3cb1859e2d29fa132f9b8e3f30ade1aba86be67c487eb366ee8ce15aaddee7559bd5e94ea21da1ce3af85d84f9ff6c4357ea15d4f6c7d01155ca1bd8f4469ca0616a0fab8dcce674a262cb994a80000000000000000", .None}, + {.Shl, "-6ab1744d1c5771c571f008824f072b6d8c1eeac1a5193254fbfc553c313763a59ab23fd51e1053b3d52e10bc65e66b400d189a2886fdc056abbaf7dbb6b081a80676c9ef1970b2b18845c641c021856f1df996d80265be8cb9d4846bc649d5a0e178fab49a1f5efcdffa3bd719098782931523d268287054305d6c990488ed20764b2a97b220bac4e92450a69a171a27861608b4e88c5ce85391704da1d9f6238614254baf32acff71bc68bdefe83e9dc73899d1088401b6185318d9a11cd9de28f55484990d9a85019d163032a98ca03a7ad5d6700c76fa0530248b246f2550cc9d54d873034b9da1308fde7d76d26dcd92e58b8def96fba1c772c3566f3378b009e3b423f33f35ff424941eea825f24a3dd1bbbf9f62484051c6ad0f2d1360a991008328f04c46fea83f46fa0e71fb96fb2dec6d49f801c8987920ca6d49bc3c9532d1c118c425e6c10deae2f2d18b08cbd21b52ceb8040af0328fde207c07f6796000d50a41ec76fcb30dc761727eb1d4d47cb7690091e1eb9534747c1e85d10b13af4fd3dcc8a558ed1b2940f31f9c78baaeaf16f6a3fc27c6b57e46def3d905e9f1171b9d50b978f71ece01d59b38399651dc4e12f72f428611b9c82ed9eed7a669057074a35bc475493e1fcaee4ab6b401baf1694cfa2da88f9efd62173f16faea0783e83cb16c7d408f0e495bb20d139c6632909dc5c9e1c80a9b06fa", "49", "-d562e89a38aee38ae3e011049e0e56db183dd5834a3264a9f7f8aa78626ec74b35647faa3c20a767aa5c2178cbccd6801a3134510dfb80ad5775efb76d6103500ced93de32e16563108b8c8380430ade3bf32db004cb7d1973a908d78c93ab41c2f1f569343ebdf9bff477ae32130f05262a47a4d050e0a860bad9320911da40ec96552f64417589d248a14d342e344f0c2c1169d118b9d0a722e09b43b3ec470c284a975e6559fee378d17bdfd07d3b8e7133a21108036c30a631b34239b3bc51eaa909321b350a033a2c606553194074f5abace018edf40a60491648de4aa1993aa9b0e606973b42611fbcfaeda4db9b25cb171bdf2df7438ee586acde66f16013c76847e67e6bfe849283dd504be4947ba3777f3ec49080a38d5a1e5a26c15322010651e0988dfd507e8df41ce3f72df65bd8da93f0039130f24194da9378792a65a38231884bcd821bd5c5e5a3161197a436a59d700815e0651fbc40f80fecf2c001aa1483d8edf9661b8ec2e4fd63a9a8f96ed20123c3d72a68e8f83d0ba216275e9fa7b9914ab1da365281e63f38f1755d5e2ded47f84f8d6afc8dbde7b20bd3e22e373aa172f1ee3d9c03ab3670732ca3b89c25ee5e850c2373905db3ddaf4cd20ae0e946b788ea927c3f95dc956d680375e2d299f45b511f3dfac42e7e2df5d40f07d07962d8fa811e1c92b7641a2738cc65213b8b93c39015360df4000000000000000000", .None}, + {.Shl, "-9ab822e2b1a93f73d8eab171e076bc0791a197f8ffce9f2ed0002c86082937007f79ca03239d845d4e6bab77cd970465450e66b072eddcead6c99040c93662836a141928eb7cad3b9df95cd16fcac461be45d3c8e8b3f68e39f7f66c18751f327eff19c92efd1636e52bca2245b7b384b6e16557796a96f1bb887f3bb6eafd80dc62e9090ca4fb1eecce82bfb1acc1ce56f4a7177383cfae9f4a505b4e1faad76bbd0b996ec91c74f9e815cf49d315dd8eb5177f97194b565ca92a24188b4f410eca9986800bbd6100f254f7b1de5be0f01392e25c366b1d14b518d9936efecb36d5115baca3165a15a7247d70124d84d1027dd566b52cb59ca134a2d6410d37c362c240768683c23b22107fcc4a26385ff30e584c54937898946ad340e973e7e0c4e2e8343e2e158236d84b1691c0b37699d25130bfff6dff1b4e73583925ff9f7ce8293691cd7f3f0a99ee31c12c3dabe0c2e17cbdc22c8d0a7c1a6558302a9071309e083e03f01dc8906250b634ec6697e9bfd2c21481ff8fd2439be480addf21741d44440239a8305ba5fd41ac87ecd64458b95ef04f288aac70a7be274a3c58d7faeefaf8ca7e5d68e9498da9fac8ca93964d68e6c05b984d2b7ae8a1c98b931a9c42967ac8e71d921adbb13cc91c088713981bad420e88c744dcdfa3b9bf4d242f408d666785961a203195ab1b6c0ee3a4c8030fede324409b8dd01e4e", "64", "-9ab822e2b1a93f73d8eab171e076bc0791a197f8ffce9f2ed0002c86082937007f79ca03239d845d4e6bab77cd970465450e66b072eddcead6c99040c93662836a141928eb7cad3b9df95cd16fcac461be45d3c8e8b3f68e39f7f66c18751f327eff19c92efd1636e52bca2245b7b384b6e16557796a96f1bb887f3bb6eafd80dc62e9090ca4fb1eecce82bfb1acc1ce56f4a7177383cfae9f4a505b4e1faad76bbd0b996ec91c74f9e815cf49d315dd8eb5177f97194b565ca92a24188b4f410eca9986800bbd6100f254f7b1de5be0f01392e25c366b1d14b518d9936efecb36d5115baca3165a15a7247d70124d84d1027dd566b52cb59ca134a2d6410d37c362c240768683c23b22107fcc4a26385ff30e584c54937898946ad340e973e7e0c4e2e8343e2e158236d84b1691c0b37699d25130bfff6dff1b4e73583925ff9f7ce8293691cd7f3f0a99ee31c12c3dabe0c2e17cbdc22c8d0a7c1a6558302a9071309e083e03f01dc8906250b634ec6697e9bfd2c21481ff8fd2439be480addf21741d44440239a8305ba5fd41ac87ecd64458b95ef04f288aac70a7be274a3c58d7faeefaf8ca7e5d68e9498da9fac8ca93964d68e6c05b984d2b7ae8a1c98b931a9c42967ac8e71d921adbb13cc91c088713981bad420e88c744dcdfa3b9bf4d242f408d666785961a203195ab1b6c0ee3a4c8030fede324409b8dd01e4e0000000000000000000000000", .None}, + {.Shl, "-ef7e1a1f265cbf77d4702e628cb42a0b1ff22b4317b11d64299b7b32eb00a7cd2732081c842a307ba4100980ae7c715ef040a72d675a3937544b8992da4d53dd8a48190cb8527f1c522cfbb9e86d2af57cc2316245d82e9cd5ab6deb8662477de2918412ffed2898fa7c0e23d6c68a9bf7b368889680ff1bcd04c3b89f2e848f9312141827ed3bc9a2956f2ed9ed0279edf88b77a3cc0489bcc4018c47284cc4c0fb792389537becb48b76aa9f0678f00c2fe710531da2d561649c344637c152998ba28a057afd0779f020d4a16f5b2407e19b044c05461ee32c018cfd29a769b79cfce130f08fa831c852e3ee998243a5a8da33ae3ad289223721e01fd77352e493f4e1163b5ff2e335cb4514035b3e4efff56b709fb346fd2c8fe4107e32b1590f794a68463147f0aafe187fc575afa796966063de5b128b1489818e475aa7b30f29195a333107da64a07cd383957d815607eecb268be3cb8df2a3c2a8f26bcf7f03a9893efd56cb9c477ad3df4db745bd4b2b63bc01fc409d332642f4ffb60a9cb0c9725cb3099465d4c74af5d806ccafdd9ca642428a9cb63396de20957e5fb4e52bcde3dfb24e9ec918b651a212bfeaff6c90fdd7e6fb72545b2335c228c2de3865a234677ebada7cde47cf39de748b46f9fb03e565d28600e99eb5e80abf1576f601713a40fd8518bd4a860956d5d8394ba450c5954a841e4f390cbfc1", "6", "-3bdf8687c9972fddf51c0b98a32d0a82c7fc8ad0c5ec47590a66deccbac029f349cc8207210a8c1ee90402602b9f1c57bc1029cb59d68e4dd512e264b69354f7629206432e149fc7148b3eee7a1b4abd5f308c5891760ba7356adb7ae19891df78a46104bffb4a263e9f0388f5b1a2a6fdecda2225a03fc6f34130ee27cba123e4c4850609fb4ef268a55bcbb67b409e7b7e22dde8f301226f31006311ca1331303ede48e254defb2d22ddaaa7c19e3c030bf9c414c768b55859270d118df054a662e8a2815ebf41de7c0835285bd6c901f866c113015187b8cb00633f4a69da6de73f384c3c23ea0c7214b8fba66090e96a368ceb8eb4a2488dc87807f5dcd4b924fd38458ed7fcb8cd72d14500d6cf93bffd5adc27ecd1bf4b23f9041f8cac5643de529a118c51fc2abf861ff15d6be9e5a59818f796c4a2c522606391d6a9ecc3ca46568ccc41f699281f34e0e55f605581fbb2c9a2f8f2e37ca8f0aa3c9af3dfc0ea624fbf55b2e711deb4f7d36dd16f52cad8ef007f10274cc990bd3fed82a72c325c972cc265197531d2bd7601b32bf767299090a2a72d8ce5b788255f97ed394af378f7ec93a7b2462d946884affabfdb243f75f9bedc9516c8cd708a30b78e19688d19dfaeb69f3791f3ce779d22d1be7ec0f95974a1803a67ad7a02afc55dbd805c4e903f61462f52a18255b5760e52e914316552a10793ce432ff040", .None}, + {.Shl, "-4b56f78d569fd473e0eab8960ff23841a963e6821c0e56a61ffab74584b34cc4f12360d2709b7de28edebfa8ffcde0bed1bed671890ac1ba634210aa6a6a6c17f31cd7dd95e7590def26108386ac5f67dd01014ffe84175f210b248bf3e5fc1cb2c1ab3a790e777b07a428914987af1e0ccee7cd801b6570e3228855041e0e31f1d5efbbb9093e15f2725bea75a2a1f840001ba97c4b4201678e13f381dc239ee026396163dca3f7bf17f618da5ebd5245696801122220dcafed35eb0d041a7bad3d0a726795a87ccdccd649bac9796ad856bbd767eea38f4eeb36b0452fc6c63e4d2d9c8cd015f32731cd2aa6e1e4bced734a0a4c66964c3ff545277dff96c7eac7967a56928ad2f6d190d83428eebabddd00e1453d02b6f4a53cdb1c2aa21062e417e63be5b1cdcffc2ce221df3fdc39549b276b390cee116d62c982bf2694eace4fc7e7a69b44ebed3f085770bcad918bf15fbd385cf47aace7adfba9edcc0410ea31a997e1f7355bf3dc396a3b00a180c9d106de07b868031ede1b26e1e924e3f79c2bd1f37e87a99b9eb4e5935761e4026674ab883aa250a478a9a5731b0e5e7b1300ff29055fa75398f8bea02214cb9734d523ae8ab363083781dee3b8b5a281a5c4ec0ae69ec710f8145196228a345882bf17e8baf7688328bb3e07fdeefc6459528f79b69e2bb3995739bdbd1ce11a5f45487c3c41ad92d5e90b0689", "71", "-96adef1aad3fa8e7c1d5712c1fe4708352c7cd04381cad4c3ff56e8b09669989e246c1a4e136fbc51dbd7f51ff9bc17da37dace312158374c6842154d4d4d82fe639afbb2bceb21bde4c21070d58becfba02029ffd082ebe42164917e7cbf83965835674f21ceef60f485122930f5e3c199dcf9b0036cae1c64510aa083c1c63e3abdf7772127c2be4e4b7d4eb4543f080003752f8968402cf1c27e703b8473dc04c72c2c7b947ef7e2fec31b4bd7aa48ad2d002244441b95fda6bd61a0834f75a7a14e4cf2b50f99b99ac937592f2d5b0ad77aecfdd471e9dd66d608a5f8d8c7c9a5b3919a02be64e639a554dc3c979dae6941498cd2c987fea8a4efbff2d8fd58f2cf4ad2515a5eda321b06851dd757bba01c28a7a056de94a79b638554420c5c82fcc77cb639b9ff859c443be7fb872a9364ed67219dc22dac593057e4d29d59c9f8fcf4d3689d7da7e10aee1795b2317e2bf7a70b9e8f559cf5bf753db980821d463532fc3ee6ab7e7b872d47601430193a20dbc0f70d0063dbc364dc3d249c7ef3857a3e6fd0f53373d69cb26aec3c804cce957107544a148f1534ae6361cbcf62601fe520abf4ea731f17d404429972e69aa475d1566c6106f03bdc7716b45034b89d815cd3d8e21f028a32c451468b1057e2fd175eed10651767c0ffbddf8c8b2a51ef36d3c576732ae737b7a39c234be8a90f878835b25abd2160d120000000000000000000000000000", .None}, + {.Shl, "a549f5083fbd9b4e95a10ab7ee373fef1e0c074ababd86187d78abfe0085705d4a4659b87d8bce5e47ce4cbcb3876453ebe8cffe6e8e733b17e2472b6bbb8bf91eed48dff67ecab26b7faafbc743736bd932d7bee2ce8f7d7bde4a8295b655760edfcd228bb87077bbd99aef963abaf6c2de6c5f31c883b3c291d0417e9720e6c95001a389f09e6cffa7d03369f9253dc7b8152e2e6907b3bf5c39ce24d44dd1ca56b3316dc3e78286875d088b58e9eddf60925c1196204b806164d487cb6d24d77fe1a12601c10aca3352fdb2c0380f337dfba1ebf7446e26c00b024e7ecedb51c4c48df3ac21ecfdde8fe086cd9bfb7660cedac2d7abe6ad1c67feead50d99e7de1aea0cad772d3aa1342a91ba4ab2381df09d9934b3df08cf18c493bd23ee768c0c58e071a045df77f821d5fc52bfcf0677d419f7b13f091daa833ee3378f8277c834d5fc164874578f6e28c630c1a196ee4427aaa51e1104cfee790e384fbaeada18fab53be4b69821bb24dcde89aba46b9faad5c720704601a2d30eee816f6f754f35f80900e8c71805f9f9ced95fbdcd80764f91f1ddf7a17881d776923a5b41020d06b98d71861bc30acbcac0659459573f9672d8b9f108620851f5da3ad9db806d664e0cb984204431b20bb8c9f7cbde1b70e9f0ecefb67710c952c68673a3f518d495e93dd436485c95bb51d4679423d702bd6ed72bce468e0aabf4", "21", "14a93ea107f7b369d2b42156fdc6e7fde3c180e95757b0c30faf157fc010ae0ba948cb370fb179cbc8f9c9979670ec8a7d7d19ffcdd1ce6762fc48e56d77717f23dda91bfecfd9564d6ff55f78e86e6d7b265af7dc59d1efaf7bc95052b6caaec1dbf9a451770e0ef77b335df2c7575ed85bcd8be639107678523a082fd2e41cd92a0034713e13cd9ff4fa066d3f24a7b8f702a5c5cd20f677eb8739c49a89ba394ad6662db87cf050d0eba1116b1d3dbbec124b8232c409700c2c9a90f96da49aeffc3424c0382159466a5fb6580701e66fbf743d7ee88dc4d8016049cfd9db6a389891be75843d9fbbd1fc10d9b37f6ecc19db585af57cd5a38cffdd5aa1b33cfbc35d4195aee5a7542685523749564703be13b326967be119e3189277a47dced1818b1c0e3408bbeeff043abf8a57f9e0cefa833ef627e123b55067dc66f1f04ef9069abf82c90e8af1edc518c6183432ddc884f554a3c22099fdcf21c709f75d5b431f56a77c96d30437649b9bd135748d73f55ab8e40e08c0345a61ddd02dedeea9e6bf01201d18e300bf3f39db2bf7b9b00ec9f23e3bbef42f103aeed2474b682041a0d731ae30c378615979580cb28b2ae7f2ce5b173e210c410a3ebb475b3b700dacc9c19730840886364177193ef97bc36e1d3e1d9df6cee2192a58d0ce747ea31a92bd27ba86c90b92b76a3a8cf2847ae057addae579c8d1c1557e800000000", .None}, + {.Shl, "-1cf41a7e8dbae094d1646512a15e6de08d20f8664f8552d94257889aa3c3b5b19bbdf588a38eeb1b3b2d375392960a1e17ecb0629537e8211224eaaef7a87e7aaea2f336c619b93736b405b7929faf80eec86cd3ffd48a1d588329d34405e40b4769f50d683e2b39d2d48b8c3bdbbb9d3ad41657707808c9aae47b2223c092302469a81b0a71cdb08c7e6b447dfed576a0018ccbfb2576d7cdcba7a71dbb4e10c9e700922ec3288acbc8a07419377d68d08f9441ab7f53384d38ef971198e1762a82f6e44941773f593d1ad841e38334b4ea1d2525800fbec2848edaa8d8e894d64e3f0ce87421976d9ca72ffdc7ae72866c3f7e6b32444fb6057f11bbe88fbae2bf11e915a55abd31f541d3b5fad7219349ef15c0defa6d196b456f21a06ad8a5d3ff81a12d0f51e544142853a5708a3ae1d99d8b2bf0de4ae61654a812321cf74bb5c86f594037d06319cc3d0393b278bc2e273fb52c2b04d05344659731b364f3bf8b0433507ba2d65f82816cd6f229484fb5cefd563acf11931108ebac3e93929d87ab5d493b8f7d6236b9e3ffa34407c89793f094829964d361b425b5289dc98525564261385dbc23344e60fd0c43317b147cd45a35d243d9d9324d20ad51c30ae298ecf69cd06df80f59b3859d0e667912bdb8f9897cf850dca2528b6e6033e044d56327fe8abb15c77ff0bfcd5f61934a3dbd630f601db5fa32cf9908", "2", "-73d069fa36eb82534591944a8579b7823483e1993e154b65095e226a8f0ed6c66ef7d6228e3bac6cecb4dd4e4a5828785fb2c18a54dfa0844893aabbdea1f9eaba8bccdb1866e4dcdad016de4a7ebe03bb21b34fff522875620ca74d1017902d1da7d435a0f8ace74b522e30ef6eee74eb50595dc1e02326ab91ec888f0248c091a6a06c29c736c231f9ad11f7fb55da8006332fec95db5f372e9e9c76ed3843279c0248bb0ca22b2f2281d064ddf5a3423e5106adfd4ce134e3be5c466385d8aa0bdb912505dcfd64f46b61078e0cd2d3a8749496003efb0a123b6aa363a2535938fc33a1d0865db6729cbff71eb9ca19b0fdf9acc9113ed815fc46efa23eeb8afc47a456956af4c7d5074ed7eb5c864d27bc57037be9b465ad15bc8681ab62974ffe0684b43d47951050a14e95c228eb8766762cafc3792b985952a048c873dd2ed721bd6500df418c6730f40e4ec9e2f0b89cfed4b0ac13414d11965cc6cd93cefe2c10cd41ee8b597e0a05b35bc8a5213ed73bf558eb3c464c4423aeb0fa4e4a761ead7524ee3df588dae78ffe8d101f225e4fc2520a65934d86d096d4a277261495590984e176f08cd13983f4310cc5ec51f35168d7490f6764c93482b5470c2b8a63b3da7341b7e03d66ce16743999e44af6e3e625f3e14372894a2db980cf8113558c9ffa2aec571dffc2ff357d864d28f6f58c3d8076d7e8cb3e6420", .None}, + {.Shl, "ed9fe1bb815a9555c41e6e742e543353f83647c6ce8d623190086f52a9a24e112a612c8f569061cfe1c7bcc1609016ce89be4106a3049e27e15fd917dd56da924cba0ab367bf81a7826c77ef55c969d32170e78fe1e119ac53df1292d166232d10b9867ef7fdc2a92132cf98398ad326c00ae5c746dd1e887f7a255b68d194ed1620aa1a01ff0da6a22cd85161a2c77f909b467205db462bd74f7d3b5c962474be942d071f517731764b1395beed44260b191a0b99eb899b84f830f96777c46ac896add695a2043fcaef6230994b44347461a822bb06f4f1ca1e0a4ab511de77eab7f540c7223d89d59fe29dd1acc57da5258e17fa761acb5d893374a8991be6a62476fcfc2e0cf0de885c8ebbdec18e0cd96be4353623d03386befb57c993c50abf9e18a47d6c80d8b321c96113fe0f4289d85c703a9ed9c7e562c3d2e8dde9e338ef688d61483e5f4bb728557245fd23911b8f94b4ffba86c5243f2bc59ffc2f5b115e6114b6118f7546a81b66434712ce7d1204e1b152da9d0307427d51996600b88a9f1a7f7663d70dfb1a32cb1c9fbe29c86c27dcec8ca89216dfb4db2158a1831cb4ca0225da7219c9eaf5837ae14b6fe06213f885592007a7a841073adc8712b8b1d6353f9781635ac0279fb3a3c8d7c9fd4cf95b8c1e4690df243df4f74796ac55a5ee082fb82e0a62aeba847ebe83398164dda58f95e6ac9b91bd0c", "4e", "3b67f86ee056a55571079b9d0b950cd4fe0d91f1b3a3588c64021bd4aa6893844a984b23d5a41873f871ef30582405b3a26f9041a8c12789f857f645f755b6a4932e82acd9efe069e09b1dfbd5725a74c85c39e3f878466b14f7c4a4b45988cb442e619fbdff70aa484cb3e60e62b4c9b002b971d1b747a21fde8956da34653b45882a86807fc369a88b36145868b1dfe426d19c8176d18af5d3df4ed725891d2fa50b41c7d45dcc5d92c4e56fbb510982c64682e67ae266e13e0c3e59ddf11ab225ab75a568810ff2bbd88c2652d10d1d186a08aec1bd3c72878292ad44779dfaadfd5031c88f627567f8a7746b315f69496385fe9d86b2d7624cdd2a2646f9a9891dbf3f0b833c37a21723aef7b06383365af90d4d88f40ce1afbed5f264f142afe786291f5b20362cc8725844ff83d0a276171c0ea7b671f958b0f4ba377a78ce3bda2358520f97d2edca155c917f48e446e3e52d3feea1b1490fcaf167ff0bd6c45798452d8463dd51aa06d990d1c4b39f4481386c54b6a740c1d09f546659802e22a7c69fdd98f5c37ec68cb2c727ef8a721b09f73b232a2485b7ed36c8562860c72d328089769c86727abd60deb852dbf81884fe21564801e9ea1041ceb721c4ae2c758d4fe5e058d6b009e7ece8f235f27f533e56e30791a437c90f7d3dd1e5ab15697b820bee0b8298abaea11fafa0ce6059376963e579ab26e46f4300000000000000000000", .None}, + {.Shl, "-294796a0b0b3b96a36ed798bc6baf24c4b6f4532cc026bc098a9265fa395d7a3b44d6a7588f3808282eeaf9e710a37fb4e52648bacd821dee37d8745345725daad31e4d8b7ca346756cc94670be70e348a27c5ee5fda3aac3fc9873111f9a0381f30297bf1487232a91e529b693ab78d7ba632206fd64b517b9bae4d8a8d0256f8e647b2ca70bd27b98036b888f24b427d50d9feb9705ef532f4b502bc037a9924ca441e840c444fb334346f4ec33d36937bb21a41c2f52749a6a56e5d1f7cd0ca23df6597db20b75a776f0884d5962b26b867edc36cf7c3a112b7bb4f5ae783becc20fe330c3215c5020166add7895fc45283ff370d201144339713e5d71442c18837bb12647224fc2a76c72ec0aa86b653909eaa0431fa52ca309a386721419a9c5b9e7d031d816de5ab8fd4f9aa04ede3bed2e2772e9c3f6d0c8861b7e3221376990b7ff5f16639683c781e7f4fbf61baa9e54ade0b831e60c8c58b128e45e5c984e19081540ef1ea7bdbb9c7fbb5faaa5fa7b04a210f5d2014230a1070a62f4c3a3af94d82c70173eafaab235c86fdc285c0aa95cdbb003182c7108ca47a10cac1f6b946bb6f35b1a48908963fe5ee1779d1d529a9a059a34837c28b858b1877ca6c3e223cbb7303085437fd6ece9e80440e498199426d85f5c05a90f0bd72eb3f6696a8a9755b0ad17e0805f1777e55fb90e8816092720f6097c0e43a85", "64", "-294796a0b0b3b96a36ed798bc6baf24c4b6f4532cc026bc098a9265fa395d7a3b44d6a7588f3808282eeaf9e710a37fb4e52648bacd821dee37d8745345725daad31e4d8b7ca346756cc94670be70e348a27c5ee5fda3aac3fc9873111f9a0381f30297bf1487232a91e529b693ab78d7ba632206fd64b517b9bae4d8a8d0256f8e647b2ca70bd27b98036b888f24b427d50d9feb9705ef532f4b502bc037a9924ca441e840c444fb334346f4ec33d36937bb21a41c2f52749a6a56e5d1f7cd0ca23df6597db20b75a776f0884d5962b26b867edc36cf7c3a112b7bb4f5ae783becc20fe330c3215c5020166add7895fc45283ff370d201144339713e5d71442c18837bb12647224fc2a76c72ec0aa86b653909eaa0431fa52ca309a386721419a9c5b9e7d031d816de5ab8fd4f9aa04ede3bed2e2772e9c3f6d0c8861b7e3221376990b7ff5f16639683c781e7f4fbf61baa9e54ade0b831e60c8c58b128e45e5c984e19081540ef1ea7bdbb9c7fbb5faaa5fa7b04a210f5d2014230a1070a62f4c3a3af94d82c70173eafaab235c86fdc285c0aa95cdbb003182c7108ca47a10cac1f6b946bb6f35b1a48908963fe5ee1779d1d529a9a059a34837c28b858b1877ca6c3e223cbb7303085437fd6ece9e80440e498199426d85f5c05a90f0bd72eb3f6696a8a9755b0ad17e0805f1777e55fb90e8816092720f6097c0e43a850000000000000000000000000", .None}, + {.Shl, "-ead482ad6a04bddac7ce4747d1c7b77e1d76320324b6b5fd506a792e0fd1cedc7175bf25bfd3c421c3a3eb475214cd968da01f78a2bb4416f7bfe148b12e0589bf94c7be03c658b9b80ad6c433bbc82b8b38a7574ee17d4da4bb4aa2fe8935b96144a1b7cce1b79cbeb35998cd01ccc455621a5498fbac762f200bbdf35028be613c896763529d50ae8bb99d369e038b9618ed617f7fa5f001f3f6cfa5f361a26f61b797b76d597a28729340b926efd3e905c4cc45cea6f0ae30fbce1a41086354236867632775c4af622b9a870603eeab9d860df4766cdd10ddbe25a17d3056bf1ddd62b06b6ed649607fe5e9318b76b2c7c087067f265cf32d006c24612e6270570f5bb991f757c9c2ebf5a7d0de4d2a06d5516d912b26a066acbaad614697d2d81ee3d70d0eb1ff41b04a6372c184983403add7f610061612d40a1bfa7bb18bea436079e6e55b21e0e43d7fcf2a748a27b6ac0184ea7d69449ccb9c3e4bacc86462b38ccd3c357ddfe92fa0650f81576257ec2616394867c850e8ccc6c1aed2c9f528694e9991a6bb30d672d6dfb1ea85aad8e0e15bd3377f8364460689bf79e5167f594186de80adc7f9c0042f38c7264c002f67656d803253a86211181604cbf83cbbe0041f027217503d29995386e89ace8ce530daae8165ca791dcd43e968f8412e10e9ef4c22a116dbfa883055d235ae01a8fae53cc3f7e844b1aadd", "e", "-3ab520ab5a812f76b1f391d1f471eddf875d8c80c92dad7f541a9e4b83f473b71c5d6fc96ff4f10870e8fad1d4853365a36807de28aed105bdeff8522c4b81626fe531ef80f1962e6e02b5b10ceef20ae2ce29d5d3b85f53692ed2a8bfa24d6e5851286df3386de72facd6663340733115588695263eeb1d8bc802ef7cd40a2f984f2259d8d4a7542ba2ee674da780e2e5863b585fdfe97c007cfdb3e97cd8689bd86de5eddb565e8a1ca4d02e49bbf4fa4171331173a9bc2b8c3ef386904218d508da19d8c9dd712bd88ae6a1c180fbaae761837d1d9b3744376f89685f4c15afc77758ac1adbb592581ff97a4c62ddacb1f021c19fc9973ccb401b09184b989c15c3d6ee647dd5f270bafd69f437934a81b5545b644ac9a819ab2eab5851a5f4b607b8f5c343ac7fd06c1298dcb061260d00eb75fd84018584b50286fe9eec62fa90d81e79b956c878390f5ff3ca9d2289edab00613a9f5a512732e70f92eb321918ace3334f0d5f77fa4be81943e055d895fb09858e5219f2143a3331b06bb4b27d4a1a53a66469aecc359cb5b7ec7aa16ab6383856f4cddfe0d91181a26fde79459fd65061b7a02b71fe70010bce31c993000bd9d95b600c94ea188446058132fe0f2ef80107c09c85d40f4a6654e1ba26b3a3394c36aba059729e477350fa5a3e104b843a7bd308a845b6fea20c15748d6b806a3eb94f30fdfa112c6ab74000", .None}, + {.Shl, "-5277c1fd2bdc0dd1db26af832e827cee3e198cedb3d8c712c282e4f9c246eabc8d99aa7fb463a01fd2128514118b78393cc8fbadeb9602f98393c9680e0b86624bffdbfe29d29c50133950c3abaeae704486986e4f0137c1eeaa94e23a866ba305a6568b027ffbfd228918a478958b7193d633ea5f2fdadca8e220aa5a561076f1b2d8540068d34c5a7918899e8e5a4b249c3a14e1f89d35c3643a0cebb6d8134161478296a1b92cd73f7ff1767b915f60bc91b6bb1fc9a2a422e75230c4245d3520c4ea7988d501aa0e93028c82a8cc3b677c93bc8fc7aa0c091e8d9e7a060027c0b578adacf85ef24d67c55e4b1025d5fbdcd0215521ff69678342c4e43e03c43f007a761d21c73a370a067f39f9eacd04a5ddeb8014d439026dad86c9ff051272ae258e79ce50e63d1f88eb293c1ccd26eccb56c84c0c51a10468d2b72399410476c48d633cf3dae0ff3a8b4ccdb36c75668a5c275f424a5deb583925bbc7270b0e27b36278368e4d965ad4eaf4f9a81c513ac58de6f7e3b5e01702501b9181a3a5483a4a3ae645f5a66c9b8cac8987b2680fe191504fd3a2aca4b7e0915955ee1a1e08bf27d2acaae9ef0b567c34cbff51be4447a7f9733e0f78b448436bf381b45f77cc832292c93c891b0a250c1eac586a24a45978b5fcab6e56ddef2bc3caf97112c40ca2f7aa6216f591d9ed7993be0853b51582445a104841940d0a", "70", "-5277c1fd2bdc0dd1db26af832e827cee3e198cedb3d8c712c282e4f9c246eabc8d99aa7fb463a01fd2128514118b78393cc8fbadeb9602f98393c9680e0b86624bffdbfe29d29c50133950c3abaeae704486986e4f0137c1eeaa94e23a866ba305a6568b027ffbfd228918a478958b7193d633ea5f2fdadca8e220aa5a561076f1b2d8540068d34c5a7918899e8e5a4b249c3a14e1f89d35c3643a0cebb6d8134161478296a1b92cd73f7ff1767b915f60bc91b6bb1fc9a2a422e75230c4245d3520c4ea7988d501aa0e93028c82a8cc3b677c93bc8fc7aa0c091e8d9e7a060027c0b578adacf85ef24d67c55e4b1025d5fbdcd0215521ff69678342c4e43e03c43f007a761d21c73a370a067f39f9eacd04a5ddeb8014d439026dad86c9ff051272ae258e79ce50e63d1f88eb293c1ccd26eccb56c84c0c51a10468d2b72399410476c48d633cf3dae0ff3a8b4ccdb36c75668a5c275f424a5deb583925bbc7270b0e27b36278368e4d965ad4eaf4f9a81c513ac58de6f7e3b5e01702501b9181a3a5483a4a3ae645f5a66c9b8cac8987b2680fe191504fd3a2aca4b7e0915955ee1a1e08bf27d2acaae9ef0b567c34cbff51be4447a7f9733e0f78b448436bf381b45f77cc832292c93c891b0a250c1eac586a24a45978b5fcab6e56ddef2bc3caf97112c40ca2f7aa6216f591d9ed7993be0853b51582445a104841940d0a0000000000000000000000000000", .None}, + {.Shl, "-e594fed61754c0e3fc4daa797547ae81f4997044bfc2679d3fed0f90ae38faeeecf1ea4bacf9fe61b62694d01aa619fd370857c7e3bf09a37d698945423a1015ea66442c01239fe707668184611fff055c69e9388c348f90476ba24f26a8af8dac8230b494f1e676612c54a9d31993c3e715d368472c35124a267fc34f45431c1d5b396277cb7099a4fe7e4434a2a8ca32a60270c7ff7748ce7a129f851107ce2333ee4481d7dd92253ed60a5ced25828308451f79b7c6defc5d04dd6fb840adb2c68f1b7b06b219277b2c6a473547ec62262d569143d9b360a92df9771c92512154361f5f590c43a84cbdeb4a6f580b94030ee6086ef5ea8ac4b00e937f4844e434b3ac7bf5f4f80592553e8b671c287e4d4f070df4db5d049371c66eaa84cca2ff0a3052945ae18eb6ad119c1be70ccab048429d051e2f696c00ae25b6598f22c14b6b19aeb8021fe405fda5f77b81493438f42ec64fb64145e40ac40e6587c062ad2abd02e8c2d8d66dc127d5c52119565cf3f26af93c9de6ceb196f2fc5a67dbdf50441e1c8c45b64c0ace1d8e57ce81308d8708332161a2f6bf9ca89d820f527b58cfbc6c93719b1e16ea922df20333225cd508f3b602033cc45cbb0e51b0be5c795b7fd53b56f930f183d45db5c0b0a95860b3a7ba5f336c6c431173c6bdc5f87b09e821dfec5cc2c86ab76340e9dcbd9167db1ac773f9a1fb0b36b409", "72", "-39653fb585d53038ff136a9e5d51eba07d265c112ff099e74ffb43e42b8e3ebbbb3c7a92eb3e7f986d89a53406a9867f4dc215f1f8efc268df5a6251508e84057a99910b0048e7f9c1d9a0611847ffc1571a7a4e230d23e411dae893c9aa2be36b208c2d253c799d984b152a74c664f0f9c574da11cb0d4492899ff0d3d150c70756ce589df2dc26693f9f910d28aa328ca9809c31ffddd2339e84a7e14441f388ccfb912075f764894fb582973b4960a0c21147de6df1b7bf1741375bee102b6cb1a3c6dec1ac8649decb1a91cd51fb18898b55a450f66cd82a4b7e5dc7249448550d87d7d64310ea132f7ad29bd602e500c3b9821bbd7aa2b12c03a4dfd211390d2ceb1efd7d3e0164954fa2d9c70a1f9353c1c37d36d74124dc719baaa13328bfc28c14a516b863adab446706f9c332ac1210a741478bda5b002b896d9663c8b052dac66bae0087f9017f697ddee0524d0e3d0bb193ed90517902b1039961f018ab4aaf40ba30b6359b7049f571484655973cfc9abe4f2779b3ac65bcbf1699f6f7d411078723116d9302b3876395f3a04c2361c20cc85868bdafe72a276083d49ed633ef1b24dc66c785baa48b7c80ccc89735423ced8080cf31172ec3946c2f971e56dff54ed5be4c3c60f5176d702c2a56182ce9ee97ccdb1b10c45cf1af717e1ec27a0877fb1730b21aadd8d03a772f6459f6c6b1dcfe687ec2cdad0240000000000000000000000000000", .None}, + {.Shl, "afc34d8703ecb7b8ae3523c947b1b315b847ebedb847fba4fa253d5f6e650ee32522f85fc6467f6a197664b772b6568bb0995d1df1e28df99f0d871b82ed64091e6b4abc93f3cc80b84e9f5bf864513be10e6da3d7a04fce19d4ecaf24caa1dccbc5d7c4f85ac1c85c3cc5eb8990ecd4bd55da3a86ae9a9c6f21e01555a53d6f43d374efd309ec10b47a737c042a6ec970b8f092ca66cd3db9c8f1c453fbefe260a5fac646a6e3776ca9cecd2ecb2cbc58fbd659998a06b592b05859e55a7a663ddf4f48fe2a9d684a7656859479ed4162b1d7e6bbfc35af7dd3f321371487cfe4c29102398f2d92daebefae00c811656b2511cd09f79343bd4d92612bd0bacd33aa13004adeff6b5382c805708f68b053183df5ff16ffe4f9a7791bb614335684e0c8308a3bc2f9358c5cabd5abe9bed108de3d48ec033765b480a24ca3c4e895c2c06b09d97cc0f84c243edd3ea351ddc4dc3e20706210a671fff35ae729cce3ad85d395e3d67c3021681b5bec705292fae6a9d7bf724f08843746e9bf7e81fd7cde6ad9ac0d98f93007b5b293aaf8f0c4053865e99a4e3928f60cd87197d1d50a134c1590a18fa6f85ec7da4995c88fff9fb9d8ff470b1908fefc9f4faf7569b27fa68b123d01cc16568f6859e3c41cae2f4059865cf3ebfde1cc7a9f822b0f1125d4e0d4aa62d71d48c09d13756370e0ee253e43a08b1ea9b62920aea57d", "12", "2bf0d361c0fb2dee2b8d48f251ec6cc56e11fafb6e11fee93e894f57db9943b8c948be17f1919fda865d992ddcad95a2ec2657477c78a37e67c361c6e0bb5902479ad2af24fcf3202e13a7d6fe19144ef8439b68f5e813f386753b2bc932a87732f175f13e16b072170f317ae2643b352f55768ea1aba6a71bc8780555694f5bd0f4dd3bf4c27b042d1e9cdf010a9bb25c2e3c24b299b34f6e723c7114fefbf898297eb191a9b8dddb2a73b34bb2cb2f163ef596666281ad64ac161679569e998f77d3d23f8aa75a129d95a1651e7b5058ac75f9aeff0d6bdf74fcc84dc521f3f930a4408e63cb64b6bafbeb803204595ac94473427de4d0ef5364984af42eb34cea84c012b7bfdad4e0b2015c23da2c14c60f7d7fc5bff93e69de46ed850cd5a138320c228ef0be4d63172af56afa6fb442378f523b00cdd96d20289328f13a2570b01ac2765f303e13090fb74fa8d47771370f881c1884299c7ffcd6b9ca7338eb6174e578f59f0c085a06d6fb1c14a4beb9aa75efdc93c2210dd1ba6fdfa07f5f379ab66b03663e4c01ed6ca4eabe3c31014e197a66938e4a3d83361c65f4754284d305642863e9be17b1f692657223ffe7ee763fd1c2c6423fbf27d3ebdd5a6c9fe9a2c48f40730595a3da1678f1072b8bd01661973cfaff78731ea7e08ac3c4497538352a98b5c752302744dd58dc383b894f90e822c7aa6d8a482ba95f40000", .None}, + {.Shl, "483550e98940e603dc2704b7241517258bb69aee23ff17f9868bd7049fb3d4d58af47dda3d5090d968c3c246360abeaec07bdfc2b0dbbcfd89572bc58489470b648ec0666f6a61579efb155a4201c476f6f2bc3588a528e4e46b510ab9cc089245ec9b1dd6cf5f3e329887147bd3023a51a312300d580e1d867d3e183e65a7b1092445a980e7ce4b7eb21daa7d32a4a002a69873a520792653605cd35c7c6dc309f394bfdde09223ffd91511b7e95e16cca914fb78f5e72af3c172d6c7a48629f93335f72d9850bd0ccd4512903d79eb7f0bc2fa331807fa3ed28fda3ba27e096e1e0e7d1e70e57723476db1e0f76ddea14c0e7fd4c9e8b61f15dfb0ee35367f79ddb3c421bc5aac678762d172fb3ef7e2199cb8731054043bb995db8bf8673a8c50542f895cff9724e11ac05c62981e54b9679b857b7f6022b22cc41a0013a902dcd151416c38fc916711396c35fef10b8b2f75f0b551b35cdcba44e0c3eda2f28a426785471cadd0c056cd9073bcf8d5f124728311a742dc75b4911b93bfbe345d31f48ac64504df26f24af02efcf3551f58dd8fdaec2b0be76b11c639556ae515919ab86ec7cdcc891e1fef6cfc1abfe232df63786767eba0eb4b33e901ba40759bb1598eb28969f49433749050510015f99a01c37ad61adc19ef4e8b2d9c3ff600454266f21137f60b1ac37f8f46604e55b896c5697b32291858521c238c", "55", "906aa1d31281cc07b84e096e482a2e4b176d35dc47fe2ff30d17ae093f67a9ab15e8fbb47aa121b2d187848c6c157d5d80f7bf8561b779fb12ae578b09128e16c91d80ccded4c2af3df62ab4840388edede5786b114a51c9c8d6a215739811248bd9363bad9ebe7c65310e28f7a60474a34624601ab01c3b0cfa7c307ccb4f6212488b5301cf9c96fd643b54fa654940054d30e74a40f24ca6c0b9a6b8f8db8613e7297fbbc12447ffb22a236fd2bc2d995229f6f1ebce55e782e5ad8f490c53f2666bee5b30a17a199a8a25207af3d6fe1785f466300ff47da51fb47744fc12dc3c1cfa3ce1caee468edb63c1eedbbd42981cffa993d16c3e2bbf61dc6a6cfef3bb67884378b558cf0ec5a2e5f67defc4333970e620a80877732bb717f0ce7518a0a85f12b9ff2e49c23580b8c5303ca972cf370af6fec0456459883400275205b9a2a282d871f922ce2272d86bfde217165eebe16aa366b9b97489c187db45e51484cf0a8e395ba180ad9b20e779f1abe248e506234e85b8eb692237277f7c68ba63e9158c8a09be4de495e05df9e6aa3eb1bb1fb5d85617ced6238c72aad5ca2b233570dd8f9b99123c3fded9f8357fc465bec6f0cecfd741d69667d2037480eb3762b31d6512d3e92866e920a0a2002bf3340386f5ac35b833de9d165b387fec008a84cde4226fec163586ff1e8cc09cab712d8ad2f6645230b0a4384718000000000000000000000", .None}, + {.Shl, "ad3a680767c80af0ca99624cf3c719c26ef1eb430d009bbe2f54048c3166551f680eca2388446df2f87067d92e99483a3dd3e77dae1752fc414dd259f6bf0d0449bf3914db95ac637dca466db82d2f134a91aa636abdb50872d364983cdbfa689a8a7791317017d6e42cf868d324dc6bb34796432e80f7ff1bb4f78fef3e4f592b55a32746b546df87065a7f2f435ea55854139fbf4dfc4b90a90aa460dddb1e1f18dfb6b96150abb515b96a538b4601d014a4fbee421127427bf61943e63648c9c3e62b4da4ee23aec896005485ee0c9675db82b22de88f405c366b7a74dd3c49c2f8c3e07a96ad2f043eb1c094492b42aafc29d9063e1df20f2419222683ed8ac73307776dc8692258d5738ac5ace231c4490effdfb199c13eed5c1fd779873a8ae20de5fcda17bfb15b17c40a638f6e2b68f4b66851e2577aa25e4eb2bd8a3a39c2ecc10dd5d3f70fdd6c5f075d9492c78051df4ecddfe2feb49c5037fbc10c2bdb57ae8d3d865625576003beb5b54aa303971e31b80c7dcd72bb58e5df88719ec339607ca5da28944fb5fd9c19a83141b4568c79bcda13ce0b45e0c913bf7b67eaffe41c20b86a28218ab9fa885e2357d2d8e4eb4080528d3dac5f86b39dde25cfc35cf065a8e8242e6bb2b1c0a69cd3061988870416d6773789e23228596a190dc9f4be0151d9d6b0351a32d4025e3167d74f923363b4139e75dbe9a59b", "60", "ad3a680767c80af0ca99624cf3c719c26ef1eb430d009bbe2f54048c3166551f680eca2388446df2f87067d92e99483a3dd3e77dae1752fc414dd259f6bf0d0449bf3914db95ac637dca466db82d2f134a91aa636abdb50872d364983cdbfa689a8a7791317017d6e42cf868d324dc6bb34796432e80f7ff1bb4f78fef3e4f592b55a32746b546df87065a7f2f435ea55854139fbf4dfc4b90a90aa460dddb1e1f18dfb6b96150abb515b96a538b4601d014a4fbee421127427bf61943e63648c9c3e62b4da4ee23aec896005485ee0c9675db82b22de88f405c366b7a74dd3c49c2f8c3e07a96ad2f043eb1c094492b42aafc29d9063e1df20f2419222683ed8ac73307776dc8692258d5738ac5ace231c4490effdfb199c13eed5c1fd779873a8ae20de5fcda17bfb15b17c40a638f6e2b68f4b66851e2577aa25e4eb2bd8a3a39c2ecc10dd5d3f70fdd6c5f075d9492c78051df4ecddfe2feb49c5037fbc10c2bdb57ae8d3d865625576003beb5b54aa303971e31b80c7dcd72bb58e5df88719ec339607ca5da28944fb5fd9c19a83141b4568c79bcda13ce0b45e0c913bf7b67eaffe41c20b86a28218ab9fa885e2357d2d8e4eb4080528d3dac5f86b39dde25cfc35cf065a8e8242e6bb2b1c0a69cd3061988870416d6773789e23228596a190dc9f4be0151d9d6b0351a32d4025e3167d74f923363b4139e75dbe9a59b000000000000000000000000", .None}, + {.Shl, "742d08a8bbff013313d95fa2d65d627aa8ae95c3b7e4c8524bcad9e7e206a27b38a1582e8d14aecc4fa5406b268e29c40a5142a9d3f481b3334fab4e8301f9218966f0a9fb32013a04894b694346d6ef70437d9b3350ea459db4301a54f3bccc116d99bed610a1ce7eb17da3f126ebf4ce158be6b3da4a85b77d1106287b27a49977cfaba5685b84229812c6b830d11015b24b5f924401845683794e6d07517b029baf80536cc2733c045d73c282214f3bb5907f3135932af1b14cc4d6861b0ad961b1cb2d5ba900756dc950aa9a36c777293b4e5a0cfd6a676923ca26bb106ba24daa09255ddbf98cbf4a409caf00c1cd34c9598fbf5fd46bbe853dadb3eef9b4d3a7b4244985cf8509675f520a67f1853d8bc81c8ea6d8f39893cccfa5ec2782b4466a13ff35bc2d77f30d1fbbea44aa0936384ff5c0aa0d4d10462ad5fb53a9d1e8a1e8f5ab63e8879766272193f09db2f2c52efad3aed192e0e683df5b3b3338033f38e8ed2eb6647f4fdc2872206b9ee788d7294b03227b33a4216f6d2a1b647cd3b7991feb068cf0172eaeabe6218815dfd3eab4169ac7d01d0237345ae6134766c91d2d09048780e263428176d58a7ec4eb79158f484e84530799d951bc5f424bae23bce7090f525a0a719c03015c5850164ace618cbd99ca08bb1e0dedd8f304579fe163bd2254fb778cd3bfa245fa5d13323f476569d7daad115f08", "3c", "742d08a8bbff013313d95fa2d65d627aa8ae95c3b7e4c8524bcad9e7e206a27b38a1582e8d14aecc4fa5406b268e29c40a5142a9d3f481b3334fab4e8301f9218966f0a9fb32013a04894b694346d6ef70437d9b3350ea459db4301a54f3bccc116d99bed610a1ce7eb17da3f126ebf4ce158be6b3da4a85b77d1106287b27a49977cfaba5685b84229812c6b830d11015b24b5f924401845683794e6d07517b029baf80536cc2733c045d73c282214f3bb5907f3135932af1b14cc4d6861b0ad961b1cb2d5ba900756dc950aa9a36c777293b4e5a0cfd6a676923ca26bb106ba24daa09255ddbf98cbf4a409caf00c1cd34c9598fbf5fd46bbe853dadb3eef9b4d3a7b4244985cf8509675f520a67f1853d8bc81c8ea6d8f39893cccfa5ec2782b4466a13ff35bc2d77f30d1fbbea44aa0936384ff5c0aa0d4d10462ad5fb53a9d1e8a1e8f5ab63e8879766272193f09db2f2c52efad3aed192e0e683df5b3b3338033f38e8ed2eb6647f4fdc2872206b9ee788d7294b03227b33a4216f6d2a1b647cd3b7991feb068cf0172eaeabe6218815dfd3eab4169ac7d01d0237345ae6134766c91d2d09048780e263428176d58a7ec4eb79158f484e84530799d951bc5f424bae23bce7090f525a0a719c03015c5850164ace618cbd99ca08bb1e0dedd8f304579fe163bd2254fb778cd3bfa245fa5d13323f476569d7daad115f08000000000000000", .None}, + {.Shl, "-153585e16978a36f1b4231b5d57e8f3cd1d92bdc13e90088a9c767e1fd7187e8a823dcf2ac33e5ebee72a6534962fdc4d168b181befa7d943d94fce9f2a46250a2384afe8dc38e17884b71f7138d7743432bb280580aa0887b24ad4ddc6cc4401c50ce3a3b9fb251f0f2f86fbda3866f85fec413b3863815b02db0839732613176c5aadf57c267405c4ee073dc6def55ccdc4bb026bf860f9479c9f0929acd686073a40fd8393de1f595ea28c03ee35c474e133d0a8a4431ca8e3dd6fdfcbd5040d1cef0b54ba9576a57c93813c15b6817a3afbb9d97f7c5493a4f4b5d0c6865bd6df15ffda341838bc42540b3ef184387639f5adde02e5fe594b1d820a88765a0f13de5cc05a383922712c53314059d7a9fd900c1412d7c1fcec09da3216c5ffadad34cdaca127c3bca8cc4e75a62c0fb2cf344e5832385af8041c3b489c58abceaf5661a18236c59024f9e8ea1fc3a96dd46562a781883ac3518516b5669f5c3ad69cbbc1d441330a85ac8a9609e4f1f81a3a78ba6830a5809524d7ed5ff0436b20cdc79825eb8b413cebc48a3fde39e67d80d1d273622472ad3b31920f0da829d12ca9cf09eb471a12f3d102b39124c89c1bed0c2150d8b99095b4af92be6f448992c31df6f43e192ea12934ed3eea833e8877c3d1418db8a3f8e7e7a402a25a9d2e6fca60413ad013d394ffbcb52d9849a5415cfa7e0eaa398a58424adfc", "10", "-153585e16978a36f1b4231b5d57e8f3cd1d92bdc13e90088a9c767e1fd7187e8a823dcf2ac33e5ebee72a6534962fdc4d168b181befa7d943d94fce9f2a46250a2384afe8dc38e17884b71f7138d7743432bb280580aa0887b24ad4ddc6cc4401c50ce3a3b9fb251f0f2f86fbda3866f85fec413b3863815b02db0839732613176c5aadf57c267405c4ee073dc6def55ccdc4bb026bf860f9479c9f0929acd686073a40fd8393de1f595ea28c03ee35c474e133d0a8a4431ca8e3dd6fdfcbd5040d1cef0b54ba9576a57c93813c15b6817a3afbb9d97f7c5493a4f4b5d0c6865bd6df15ffda341838bc42540b3ef184387639f5adde02e5fe594b1d820a88765a0f13de5cc05a383922712c53314059d7a9fd900c1412d7c1fcec09da3216c5ffadad34cdaca127c3bca8cc4e75a62c0fb2cf344e5832385af8041c3b489c58abceaf5661a18236c59024f9e8ea1fc3a96dd46562a781883ac3518516b5669f5c3ad69cbbc1d441330a85ac8a9609e4f1f81a3a78ba6830a5809524d7ed5ff0436b20cdc79825eb8b413cebc48a3fde39e67d80d1d273622472ad3b31920f0da829d12ca9cf09eb471a12f3d102b39124c89c1bed0c2150d8b99095b4af92be6f448992c31df6f43e192ea12934ed3eea833e8877c3d1418db8a3f8e7e7a402a25a9d2e6fca60413ad013d394ffbcb52d9849a5415cfa7e0eaa398a58424adfc0000", .None}, + {.Shl, "-423a524916f6025cd170f0dcfc3b2f72b167bae80f029d0f9406942be3589c31ba16e2cf1f82c0bfb4d1a319a723f4027103661b0061b20f653f871c1cc671e9ecc93b3f9ee62e69949cdce7852f2772939300acdab6540e159c18665b5b462f252c2de1b28e9a45bdf2afb4c0e55231bb136e5fdd2e3cef9d5b470e58cd3e89c0737742a1762cac12fe0197b56225d763c9324a9e6fd2d9aac5820e99b378f81909bc71ef3f7b7936b9097b6bb291fc24a4df41d2914d406af6e822c9ea2f332cdf9aa4f6ab93ea41b32a27cc8e8589298165f98f6306184568fadb9639103621b93a4d39c584c1d73c1b482e3819212dac1b5c48d10c0c34b8e37d810d096335e7eb2af1ef652b6c7106574b6fd034374a7adc463b3247a17acffa6f5f6d94198c977e1a29841b38bf4cdf4acbd9b7170f38333739c78907eed79f332daac1d43ddb369b3ccbcd63af69a37b27269db5293f7cb8f827978bc3fc9d288dddf4cf90e70b06c9dd06e2c06201576887f0c34b9a9161b0e2474c4d98c6b999f9168c7725fbf4e21cdd09d83356dae2a33d12dc960b543f77ef555e53ca06968461e76e60c356bd13c63c8ec070263b2d1964ed8c65b87b7ee4140e95751c738216ea949b88fae3ab8d08625d4d6cbf429ce09b81acbf19e32d3689248b8b73f03b87ec88c862bc92a048c0312c2e813f892791688126e261ff0f9efb3b300ce3d1", "9", "-8474a4922dec04b9a2e1e1b9f8765ee562cf75d01e053a1f280d2857c6b13863742dc59e3f05817f69a346334e47e804e206cc3600c3641eca7f0e38398ce3d3d992767f3dcc5cd32939b9cf0a5e4ee527260159b56ca81c2b3830ccb6b68c5e4a585bc3651d348b7be55f6981caa4637626dcbfba5c79df3ab68e1cb19a7d1380e6ee8542ec595825fc032f6ac44baec79264953cdfa5b3558b041d3366f1f0321378e3de7ef6f26d7212f6d76523f84949be83a5229a80d5edd04593d45e6659bf3549ed5727d48366544f991d0b125302cbf31ec60c308ad1f5b72c72206c4372749a738b0983ae7836905c7032425b5836b891a218186971c6fb021a12c66bcfd655e3deca56d8e20cae96dfa0686e94f5b88c76648f42f59ff4debedb2833192efc34530836717e99be9597b36e2e1e70666e738f120fddaf3e665b5583a87bb66d3679979ac75ed346f64e4d3b6a527ef971f04f2f1787f93a511bbbe99f21ce160d93ba0dc580c402aed10fe186973522c361c48e989b318d7333f22d18ee4bf7e9c439ba13b066adb5c5467a25b92c16a87eefdeaabca7940d2d08c3cedcc186ad7a278c791d80e04c765a32c9db18cb70f6fdc8281d2aea38e7042dd5293711f5c7571a10c4ba9ad97e8539c13703597e33c65a6d12491716e7e0770fd91190c5792540918062585d027f124f22d1024dc4c3fe1f3df6766019c7a200", .None}, + {.Shl, "e9d034cb84f5546c2a9ab87d3ad6b284882ec7ad26f7842781fab033e9a11901fca192210ad772131f329762b1c6ae1b7bc0073bca72b89aa1973e4a0cdb6bed6a059a674c73523122b7f71090d888901170065402e0eb1f7ae841a80262f82cd1a3c103546d8693bdd9360b403bebaef2e9f36cbac779583d1036c09f79ffe4a9f44dbfecfec0d02ab564d244bcef201d5f761c68ee876cdd863de6777d9a9db7f699ec5ca923522aec8de034777e94067f49fd79b1003354871045958db3f3271b0b9199ea3c6a368346cc7e9a0219a608ffd0d0fd09dfd2c1829c5f041f4dfd895f9d700c987015550f1c4f82d5a4dfa6a8e9b98080006b20354c767e4ff1dbb838f28e0184ad9e73b47055f2550bb03b0084a4f5cd019feeda8fa2cd340370ad772b36f44672acbc495ed8ac6fbf174e0ffcb8f36cfaaa682c3b0249cb4866db88c1547bd4287094cbea448c4a36d493eede8e390ceacd59450140e2b922254c6bd6d40958df8bd6d4634b3c13ea51313f51e3931806931d3437d88573219c5e9b38b2e1f45429221a1f8245cb99e9052e3f78425b78a61372c076acbaed9f67ceceaa9e86e233c3d1b003702e6939184657dbec3a2956214c15af273af7d856a5a6f5bdc14861ebe18d82b76aa3dbeebd98787d71e413cf4ae2a15dfe5576f8a94cda36c697e7f786e0a3afa691b821b22ec91b62da1bdefb011e89a113", "5d", "1d3a0699709eaa8d8553570fa75ad6509105d8f5a4def084f03f56067d3423203f943244215aee4263e652ec5638d5c36f7800e7794e57135432e7c9419b6d7dad40b34ce98e6a462456fee2121b1112022e00ca805c1d63ef5d0835004c5f059a3478206a8db0d277bb26c168077d75de5d3e6d9758ef2b07a206d813ef3ffc953e89b7fd9fd81a0556ac9a48979de403abeec38d1dd0ed9bb0c7bcceefb353b6fed33d8b95246a455d91bc068eefd280cfe93faf3620066a90e208b2b1b67e64e36172333d478d46d068d98fd3404334c11ffa1a1fa13bfa5830538be083e9bfb12bf3ae01930e02aaa1e389f05ab49bf4d51d373010000d6406a98ecfc9fe3b77071e51c03095b3ce768e0abe4aa176076010949eb9a033fddb51f459a6806e15aee566de88ce5597892bdb158df7e2e9c1ff971e6d9f554d0587604939690cdb71182a8f7a850e12997d48918946da927ddbd1c7219d59ab28a0281c572444a98d7ada812b1bf17ada8c6967827d4a2627ea3c726300d263a686fb10ae64338bd367165c3e8a85244343f048b9733d20a5c7ef084b6f14c26e580ed5975db3ecf9d9d553d0dc46787a36006e05cd272308cafb7d87452ac42982b5e4e75efb0ad4b4deb7b8290c3d7c31b056ed547b7dd7b30f0fae3c8279e95c542bbfcaaedf15299b46d8d2fcfef0dc1475f4d237043645d9236c5b437bdf6023d13422600000000000000000000000", .None}, + {.Shl, "3e69da14a4991c4c319000c4b5ad6d2cd67969dbefba4b5b837ef446ec1333f85cd8b46473d9e667a49c9e0a346c10e6cb96386ca22704e4de8a470935f980df1314b95dc89d965b0f7ab6d0c93232fd047b98820ef54f88371c480e89adc5bfe56f992cd8ab8ee9422e7610d24972c1a318c429b39602f922777e868fd93ed63acd30ed3da96b8895a4754e916bd47434519d3127f7b5161c39450876d14bf7cfb60bdb5e2876a2ac3bd2aeb718c168b2fbeb303356085335f920c4df041ad95f0686172aa188cdeb559b1fc0a7cb5bb296b53577b4c52210666354448685664ef4d1d3b087657fe8b8efd3084aa8105e842e88c0171cbe28d0995a6747a9ccbb824b3a5d38f941844848de561542e8bd8fe5bc361d7ae64b814c8c8674e1e247538335f07de65033a239f7df7eac582e552cfd8587acbf9035949bb6341e0048799b8d5eb77e65c2b40a575da1fbfbfcf15b2459d673ce6d4d26d9fe6f8299778a4b5b1273da5c85276e948850cf5f1fe35c67f9aa22046864cf10821fe8b565bcd53214a3b95ce792e8fd39ce115123e833243b3df3f7c713862607e92f439e862b7c06ce57802bdd27400a9657ecd66c4b7522e85a7cbabc61e6f1b9ca9895e92c2b18d2da49adb7036101618c21a00cf81d1ef2fb4714fefb0101d5da606cf2e2992a4aa9a27367e9c4c6853fd6080fffc3566c0efe0e8aec0e4741ad11", "26", "f9a7685292647130c6400312d6b5b4b359e5a76fbee92d6e0dfbd11bb04ccfe17362d191cf67999e92727828d1b0439b2e58e1b2889c13937a291c24d7e6037c4c52e5772276596c3deadb4324c8cbf411ee62083bd53e20dc71203a26b716ff95be64b362ae3ba508b9d8434925cb068c6310a6ce580be489ddfa1a3f64fb58eb34c3b4f6a5ae225691d53a45af51d0d14674c49fded45870e51421db452fdf3ed82f6d78a1da8ab0ef4abadc6305a2cbefacc0cd58214cd7e483137c106b657c1a185caa862337ad566c7f029f2d6eca5ad4d5ded3148841998d51121a15993bd3474ec21d95ffa2e3bf4c212aa0417a10ba23005c72f8a34265699d1ea732ee092ce974e3e5061121237958550ba2f63f96f0d875eb992e05323219d387891d4e0cd7c1f79940ce88e7df7dfab160b954b3f6161eb2fe40d6526ed8d0780121e66e357addf9970ad0295d7687efeff3c56c916759cf39b5349b67f9be0a65de292d6c49cf6972149dba5221433d7c7f8d719fe6a88811a1933c42087fa2d596f354c8528ee5739e4ba3f4e73845448fa0cc90ecf7cfdf1c4e18981fa4bd0e7a18adf01b395e00af749d002a595fb359b12dd48ba169f2eaf1879bc6e72a6257a4b0ac634b6926b6dc0d84058630868033e0747bcbed1c53fbec0407576981b3cb8a64a92aa689cd9fa7131a14ff58203fff0d59b03bf83a2bb0391d06b444000000000", .None}, + {.Shl, "-d7d8bb2b5d0a584d97e2a3d3368e0fb670bb8cff5b58ce70319ff559eecef9bdfaff7903774df4c124e274809ed317fda85d9f968e528ba980da32fea959093d4b859e89e1121924b33234bfc9fc0d482147e62aab7eaa1d361c1831d0221cad2a101c81679d716cb3da2d70dee32f5fecda35f6feb0eebc2286df31cc9f414f4aafcf60aa6eac48db9a9e980fb7c2b1b821e7dc31ab132cdc4fe2f30ae922ffa50b1b3674bd0a5db4753151a40408412fdcb93c7428d3f6a86e79605cbe6d4e727688e70805acd0c4ff89f07ac1797c77740cd440308b37ac593045331ac7defb8702bcc8d6dc9e61078ddec02405790f578fac2d40478072020904761f32d3705ef871b4298ef394e988c254d1eb4da305969a957ce0c6af60e8f2434a899a22ac634bbbaefbc87458207aa19e8111af79eb79ca41f730450df5d397068bec59f85bd490b93edc9f4a23a5bc41888164f7f09da83ace72545c375b1a4ac352945686b2b4284cf7688d5f3a6e878a4a210c5a9f2e46e6c53a132b9300cd01c9cc50d894ba9ccb3c77454da3eb08d5196732919508c61c5913ae0278664bd1dbc8afe139ecebd06dfcdd19d5334fef2391e3374a27fac5c041afa55b2a6c1779e8da58ce7402f2a67b18ac5d578c925960ea07786d9765d6932dde7bbda89c93a3f0e2bed6e4a3eedb5e826309bafdb6e4490971c2b570dcf6a5125ef5a213b4", "1", "-1afb17656ba14b09b2fc547a66d1c1f6ce17719feb6b19ce0633feab3dd9df37bf5fef206ee9be98249c4e9013da62ffb50bb3f2d1ca5175301b465fd52b2127a970b3d13c22432496664697f93f81a90428fcc5556fd543a6c383063a044395a54203902cf3ae2d967b45ae1bdc65ebfd9b46bedfd61dd78450dbe63993e829e955f9ec154dd5891b7353d301f6f85637043cfb863562659b89fc5e615d245ff4a16366ce97a14bb68ea62a3480810825fb97278e851a7ed50dcf2c0b97cda9ce4ed11ce100b59a189ff13e0f582f2f8eee819a88061166f58b2608a66358fbdf70e057991adb93cc20f1bbd80480af21eaf1f585a808f00e4041208ec3e65a6e0bdf0e368531de729d31184a9a3d69b460b2d352af9c18d5ec1d1e4869513344558c697775df790e8b040f5433d02235ef3d6f39483ee608a1beba72e0d17d8b3f0b7a921727db93e94474b78831102c9efe13b50759ce4a8b86eb6349586a528ad0d65685099eed11abe74dd0f14944218b53e5c8dcd8a74265726019a039398a1b12975399678ee8a9b47d611aa32ce65232a118c38b2275c04f0cc97a3b7915fc273d9d7a0dbf9ba33aa669fde4723c66e944ff58b80835f4ab654d82ef3d1b4b19ce805e54cf63158baaf1924b2c1d40ef0db2ecbad265bbcf77b51392747e1c57dadc947ddb6bd04c61375fb6dc89212e3856ae1b9ed4a24bdeb442768", .None}, + {.Shl, "212440fdc4dec86998c4bb1ee31a75a16396e5d7131982169f68d86613378b366b608960a6cd7c5424ad8871ad1d305ab040ea9a655e6a6f4ec934d795605b95e72478352c101e472dc482af822ef751da90439a4115e28b4b15b92db82c50f2694ff5ad9cba2f8ed16f17ea690da8336c8519a2228a5fa921bfe2eb47cdad1bd7d4d71126145ba77f38569cdccfd5a2050dc8f3de6257eb5dd2867443c76bc2e7b1a7f07d5df6b3cd9a219842de5377af0fe21a30c0869412f66902a9fc8a292b80e1bf46333a5783f49f74d00feff375089f10cc748ca58125793ab13d841b02febf15a93c06c6ca06903e5a8552157f9c72a8cd30021735d072f3d8d36771ac150df9dcc0beb59d37acfd0cea74212a5cc506735cbc40d207d65b7434e39b91ffee10c0185ea74e4025b300b46ecb9dfbc3c6bfd9e7e8180563f7b7d21e7a90a940c74bc17758d74c41726ab33bf57d12e85983ebff75835f81007480f0832c5af4802b2fe8338bc869fcd44abd6fa584cf1453da9bdfca4c14a23875e642fc3d98c91d27afe1c10f6eb52014997974ded0e86ba5d97a2ea454f675656a9a45fd8315940104730aaa607bd39b4fc0ec8367ffe11262aab9674b534f1a965fc9477ab8f2d3556db836b354edf6fa3dbb41823cf4695c5c1f55e768bb0bb0860b0caf90c58162644f08a8e96827aa243916c32caf7bd9046a8265fee8cbd6ae", "d", "424881fb89bd90d33189763dc634eb42c72dcbae2633042d3ed1b0cc266f166cd6c112c14d9af8a8495b10e35a3a60b56081d534cabcd4de9d9269af2ac0b72bce48f06a58203c8e5b89055f045deea3b5208734822bc516962b725b7058a1e4d29feb5b39745f1da2de2fd4d21b5066d90a33444514bf52437fc5d68f9b5a37afa9ae224c28b74efe70ad39b99fab440a1b91e7bcc4afd6bba50ce8878ed785cf634fe0fabbed679b34433085bca6ef5e1fc43461810d2825ecd20553f914525701c37e8c6674af07e93ee9a01fdfe6ea113e2198e9194b024af275627b083605fd7e2b52780d8d940d207cb50aa42aff38e5519a60042e6ba0e5e7b1a6cee3582a1bf3b9817d6b3a6f59fa19d4e84254b98a0ce6b97881a40facb6e869c73723ffdc218030bd4e9c804b660168dd973bf7878d7fb3cfd0300ac7ef6fa43cf52152818e9782eeb1ae9882e4d56677eafa25d0b307d7feeb06bf0200e901e10658b5e900565fd0671790d3f9a8957adf4b099e28a7b537bf9498294470ebcc85f87b31923a4f5fc3821edd6a402932f2e9bda1d0d74bb2f45d48a9eceacad5348bfb062b280208e61554c0f7a7369f81d906cfffc224c55572ce96a69e352cbf928ef571e5a6aadb706d66a9dbedf47b76830479e8d2b8b83eabced17617610c16195f218b02c4c89e1151d2d04f5448722d86595ef7b208d504cbfdd197ad5c000", .None}, + {.Shl, "7e04f0aca1b7d4c3ebfbec472b4d3d1108e4e77cab3a7473fcfb3dd83370ccd83fd87a766a98180678574960f5e2fc73831c4c296d57261c7e6855b01fdf036146013c4cad90bf3fdc6fd644c220ffcfa0806ef9b88a6d745c68c49adbf88f4d6fbe332af53376c329185909970d87676d0b292544d93a7d88854175bbf4776ea3e21b88f666f68beb9cd8a6354da1d838cf012f64ec221bff4de149c02b63de4dd9afe7ab5a350cc503e62f04b85753beb330180b011d1bb491132b9ed805e93a7bd734bbf0813a7b64dc1faefe8e5c27514cdb5ef954b4234e746b1c48a38478cb8ba19f2c9f21e37fae046c417ed7244dc83aab637511790edc47d290cf2bf0aba1c6629bf7804562997851f98b15c52d81a418ac7c5f718bef66867995a1e8287593c7682a10c9c09eb5fff1547d6c1b85ecf3637b69058e010618005423046d3e8538cbe2cab459e07fec4bd7113188f87f40bdb0888a5071ca54582757b69ea4ac02ad61ccb7981735f5e8ccbd9872b6f7c3f7168cde05be1f14b0ffd657293aea19243d551c3bef10809a547346a4f1632f66d43095bcbc1ac6138cfd45abf6f0e3e5d11bdad92ff06c5d0e525b5f8d791ddce693e57065741e8ccfb06f6839daa57c8f71a4962fc6c9ee8ab2ae1d6c64434f7b304890e5458bb24796837c835b3a71adf258ce8422e0f0e156e64fddbe78064546d6d9b47fadfdbc19", "59", "fc09e159436fa987d7f7d88e569a7a2211c9cef95674e8e7f9f67bb066e199b07fb0f4ecd530300cf0ae92c1ebc5f8e706389852daae4c38fcd0ab603fbe06c28c0278995b217e7fb8dfac898441ff9f4100ddf37114dae8b8d18935b7f11e9adf7c6655ea66ed865230b2132e1b0eceda16524a89b274fb110a82eb77e8eedd47c43711eccded17d739b14c6a9b43b0719e025ec9d84437fe9bc2938056c7bc9bb35fcf56b46a198a07cc5e0970aea77d66603016023a37692226573db00bd274f7ae6977e10274f6c9b83f5dfd1cb84ea299b6bdf2a968469ce8d638914708f19717433e593e43c6ff5c08d882fdae489b907556c6ea22f21db88fa5219e57e157438cc537ef008ac532f0a3f3162b8a5b03483158f8bee317decd0cf32b43d050eb278ed0542193813d6bffe2a8fad8370bd9e6c6f6d20b1c020c3000a84608da7d0a7197c59568b3c0ffd897ae226311f0fe817b611114a0e394a8b04eaf6d3d4958055ac3996f302e6bebd1997b30e56def87ee2d19bc0b7c3e2961ffacae5275d432487aaa3877de210134a8e68d49e2c65ecda8612b7978358c2719fa8b57ede1c7cba237b5b25fe0d8ba1ca4b6bf1af23bb9cd27cae0cae83d199f60ded073b54af91ee3492c5f8d93dd15655c3ad8c8869ef6609121ca8b17648f2d06f906b674e35be4b19d0845c1e1c2adcc9fbb7cf00c8a8dadb368ff5bfb78320000000000000000000000", .None}, + {.Shl, "4bbea4acd92dc3312769cfff24cd52d783c292fbe9248f846d95461634c9f7536f1e6c78162fd93e9ef8a569edef0a705d978d4868c48be2c04ac13b10226a58457a52f0406789db5878bcc283394b64a40aa063ea7e6239d639e6d116973233f31ca678f18819a5a1f19a2270a9e7e8161c8421cf6c72ac159e21498d669b67fc61197314294d90037c5ff392f7ac4aee770053c8d480d6dc984b80896f0d1d55bdd60aa264ecafba166676ffc716ca13359f00f0ffd256eb66ea0868e0bdfedf483012fc45bc9f2c425ed75b6c76fb448c1c4a202e82eb3394464a4c88bc6dee0ab7227a6362fd2e7e6ac29c5d76842ec08097476485306c7b4c99666c85ef91ecb5d99959309c55539910af5955d38418adf982b0a8536ba75f9c60a0c2172597a95d87871298f52d99f376ddcc78d484980a0d5c1b7e3fd9f3e4c45781b985cbc0c97eca8648fed85cfa81f0fa50d3ea2a2e021efa72b377adedec2008dde1e4b9fa7e03b804ad7193ba408a15ed083fd2e34972974f92a0dfd2687172e480ffaad2cd17b936440b9cd4f40216ae70fe0b2422e81f5d148094f57a7513c118a05b17855186e61be57896f25b334986700c9d72a5eb29a7e1607275dee389b9754a7d86f410057bc7063e2b9161a685e7245f3411add7f88992f34fedc6f2be914fc68e665a7dbfd4cbd059de47d23a5962f55f156a984dd03c4277b497c4", "2b", "25df52566c96e19893b4e7ff9266a96bc1e1497df49247c236caa30b1a64fba9b78f363c0b17ec9f4f7c52b4f6f785382ecbc6a4346245f16025609d8811352c22bd29782033c4edac3c5e61419ca5b252055031f53f311ceb1cf3688b4b9919f98e533c78c40cd2d0f8cd113854f3f40b0e4210e7b639560acf10a4c6b34db3fe308cb98a14a6c801be2ff9c97bd625773b8029e46a406b6e4c25c044b7868eaadeeb0551327657dd0b333b7fe38b65099acf80787fe92b75b3750434705eff6fa418097e22de4f96212f6badb63b7da2460e251017417599ca232526445e36f7055b913d31b17e973f35614e2ebb421760404ba3b24298363da64cb33642f7c8f65aecccac984e2aa9cc8857acaae9c20c56fcc1585429b5d3afce3050610b92cbd4aec3c3894c7a96ccf9bb6ee63c6a424c0506ae0dbf1fecf9f2622bc0dcc2e5e064bf6543247f6c2e7d40f87d2869f51517010f7d3959bbd6f6f610046ef0f25cfd3f01dc0256b8c9dd20450af6841fe971a4b94ba7c9506fe93438b972407fd569668bdc9b2205ce6a7a010b57387f059211740fae8a404a7abd3a89e08c502d8bc2a8c3730df2bc4b792d99a4c338064eb952f594d3f0b0393aef71c4dcbaa53ec37a0802bde3831f15c8b0d342f3922f9a08d6ebfc44c979a7f6e3795f48a7e347332d3edfea65e82cef23e91d2cb17aaf8ab54c26e81e213bda4be200000000000", .None}, + {.Shl, "fe2da2e29fe5eea81b33dd67879af1ebf2775e9498097c74bf4590760fd78ff509253c23f79795f1340e3f53a3b8f25cd763b3b2a3033245b2016d81a65f4c56e0f8fc55b6b3801e16d8f5da65caf7d36045ed89d47408963b5f38c52414c2f2dcd4640354a9041bcf3d816063f3433ff51f87e2e6c1e672553f4d65760f0ccfdee84270f61f7f7b1f8f034a7208633fb0578f4c31f17c832070f58532c5b053901096c8332c47119991cd6c32d576c64f527c2a2db2d6269cabaa5087b11c37a4100825a23329d534fb5ae2b931d7cf65e6d10b43488081aadb510a687a2eaab5a71523bec963e868b28d9245168915d7589e971abefa114d28e5b1e8148885ef118ff01b3e89bd3b79d6b1fad9626157eeff6cdafafc15d5bbb6ffd75a6d7cfd36d5ab8d0a4b8060b47a1751034e5dd4f923f101ed25fac40c8a86406c31c389c5c5c49fdbb38f43af8d6bf7e295c22282905fac195c9889d096909f6ee4438497462192380b623659b07c93b0ddd6bc439c01234369735474502e004221674fddb460d55d096b304a304937f074abbfacf2f38eb263beae4f1e9c5cfdb33b9a720ae4d575f2f836115264cdf42538cab8b7b868bc6263cd7450cf935054aea19760a2df2d7dabadf773c28cdb93031aeec4da5881881159796a49bc724e3bd6385a448cdaa7b7a329d4d6372e91100408819dcffdd2869d99c95ad599fe3e", "10", "fe2da2e29fe5eea81b33dd67879af1ebf2775e9498097c74bf4590760fd78ff509253c23f79795f1340e3f53a3b8f25cd763b3b2a3033245b2016d81a65f4c56e0f8fc55b6b3801e16d8f5da65caf7d36045ed89d47408963b5f38c52414c2f2dcd4640354a9041bcf3d816063f3433ff51f87e2e6c1e672553f4d65760f0ccfdee84270f61f7f7b1f8f034a7208633fb0578f4c31f17c832070f58532c5b053901096c8332c47119991cd6c32d576c64f527c2a2db2d6269cabaa5087b11c37a4100825a23329d534fb5ae2b931d7cf65e6d10b43488081aadb510a687a2eaab5a71523bec963e868b28d9245168915d7589e971abefa114d28e5b1e8148885ef118ff01b3e89bd3b79d6b1fad9626157eeff6cdafafc15d5bbb6ffd75a6d7cfd36d5ab8d0a4b8060b47a1751034e5dd4f923f101ed25fac40c8a86406c31c389c5c5c49fdbb38f43af8d6bf7e295c22282905fac195c9889d096909f6ee4438497462192380b623659b07c93b0ddd6bc439c01234369735474502e004221674fddb460d55d096b304a304937f074abbfacf2f38eb263beae4f1e9c5cfdb33b9a720ae4d575f2f836115264cdf42538cab8b7b868bc6263cd7450cf935054aea19760a2df2d7dabadf773c28cdb93031aeec4da5881881159796a49bc724e3bd6385a448cdaa7b7a329d4d6372e91100408819dcffdd2869d99c95ad599fe3e0000", .None}, + {.Shl, "-fb48135d4ef73ab62be01e94dfc52530c312587cd66c1fc23e76479fb6e251e1fe664add32edbb2aad6a079acbe8328a042d61bac1934ff6ecf9195d88fd732cbfe3c0ec4048191a1ee46a8ddc3fcfc7d8b37b2a7c0eecd880b94b3d71d409ee512e9b773ec09e561d0dc4c2088c4c2d12d8bed2a78509db93fc080aa133c3ebf099cab2a4e5abcdfe0dfb9e21c730d3123fc9c12fef398c043bdda3cf1890752706ba8e6fc67fc288b5aee33b30bb5d7b906859cd607d85c7940fcf85f6a0737c476f739b5089e98f1854e4d5050f1544b93946f9669b93cdbcac1baabdd8134511cdbd51d72103f02d079e04ea1e0fe348d95e609cee9f407e3ba35e287ff891aeaddbdd358043bc9ed856af17eba5a07987106c960dfa079911c1e5d70b952a83fe52b8a3ffd7239ade42a276eb59fe5bbfb94df9c0156c6aec56a5f5d8718b8f20baeb765d464775c6429cd5baeb0eca47d6aa77b7fa5ae52524d1a67eefe50713edd6d98978d7f8fc07b92077c695656943bf2eeca911ec57fb9fd9a30f1982c3e0eb5a1aa93b2f1430a39907adbc05d729b22a85e8cb3b7e029c4aea88d0b5bc2d850306780a077eb404c23ac9236eef02da0e561a6a10cc38e52df09d2c6eb219e469c2bfed00b4b0636e5e36e9bdb67208e4109900fc79fc6e8b356a6ddc5552fbb56ccdb643780b80a45136e583cb975537fab3d0e06f6c9b9101ff", "36", "-3ed204d753bdcead8af807a537f1494c30c4961f359b07f08f9d91e7edb894787f9992b74cbb6ecaab5a81e6b2fa0ca2810b586eb064d3fdbb3e4657623f5ccb2ff8f03b1012064687b91aa3770ff3f1f62cdeca9f03bb36202e52cf5c75027b944ba6ddcfb02795874371308223130b44b62fb4a9e14276e4ff0202a84cf0fafc2672aca9396af37f837ee78871cc34c48ff2704bfbce63010ef768f3c6241d49c1aea39bf19ff0a22d6bb8cecc2ed75ee41a1673581f6171e503f3e17da81cdf11dbdce6d4227a63c61539354143c5512e4e51be59a6e4f36f2b06eaaf7604d144736f5475c840fc0b41e7813a8783f8d2365798273ba7d01f8ee8d78a1ffe246bab76f74d6010ef27b615abc5fae9681e61c41b25837e81e644707975c2e54aa0ff94ae28fff5c8e6b790a89dbad67f96efee537e70055b1abb15a97d761c62e3c82ebadd975191dd7190a7356ebac3b291f5aa9dedfe96b9494934699fbbf941c4fb75b6625e35fe3f01ee481df1a5595a50efcbbb2a447b15fee7f668c3c660b0f83ad686aa4ecbc50c28e641eb6f0175ca6c8aa17a32cedf80a712baa2342d6f0b6140c19e0281dfad01308eb248dbbbc0b68395869a84330e394b7c274b1bac86791a70affb402d2c18db978dba6f6d9c82390426403f1e7f1ba2cd5a9b771554beed5b336d90de02e029144db960f2e5d54dfeacf4381bdb26e4407fc0000000000000", .None}, + {.Shl, "-df800f4eacb04b99c69f7bac0c35122b656220f4acf3f14f7f367deb0ad7ece05169a0785b352136b7f1c13be38c2f5ff0c4fe7b0537f912ad40a21e76832dbd323acd7e5dbd31dcb1b6d359b74883455e278b66653ad4147c302510b176f09f46b05e9e747e6818aacb14d8838b4d142ee8d7f02c8a2b503c01dca1317a69f8a4b7a6d7c851b0018d4dbee40232b64e99e6e02ec9fc3526983cc8464a699078ce225936eba9c038b74b3732f83ef6f97daf7624d68fd333d7387b155436f86382494f068cd110f2e7330055bd23b6901a860e62cbe8cae8be7cb85f8a7a4e4c1b23b3c7c0a519a1cfcb9755cbfac6501cab65779222a9b36abd15854f537b8e8b2ed3b72354a6837f6b3d18aa653fb3275c4bf0d2a4be4ad89c6f752c733ad68ccd0941a7686d0cd664d6f457a666ec75567ba009533bdb250d7460854de7ae0a1e92d0f458cfe17c8fce6064e2a4aa05653389c089997bc6cc5513285ebb7a1436afca9b7b541d5d439a8c6d6e5996d5f4470940b22bff224e57408c8bd372e22c25812778bafc01b3fa9acd535296b9ff2db544e46e6efc4d8188bac3eaab558920ab164ee8829aa952bf66952c2368e7daa342ddd80c1d65ec117cfd0b4f38b31e0ccef75e61d3a8c46538e2fcd76f2d26116b5c4b6ed05abe1ec7a9af5e1814d38d6de8f531bed5eaff7b180ae04eb515833e95b60644718c9aa2e42fd8", "5a", "-37e003d3ab2c12e671a7deeb030d448ad958883d2b3cfc53dfcd9f7ac2b5fb38145a681e16cd484dadfc704ef8e30bd7fc313f9ec14dfe44ab5028879da0cb6f4c8eb35f976f4c772c6db4d66dd220d15789e2d9994eb5051f0c09442c5dbc27d1ac17a79d1f9a062ab2c53620e2d3450bba35fc0b228ad40f0077284c5e9a7e292de9b5f2146c0063536fb9008cad93a679b80bb27f0d49a60f3211929a641e3388964dbaea700e2dd2cdccbe0fbdbe5f6bdd8935a3f4ccf5ce1ec5550dbe18e09253c1a334443cb9ccc0156f48eda406a18398b2fa32ba2f9f2e17e29e939306c8ecf1f029466873f2e5d572feb194072ad95de488aa6cdaaf456153d4dee3a2cbb4edc8d529a0dfdacf462a994fecc9d712fc34a92f92b6271bdd4b1cceb5a333425069da1b43359935bd15e999bb1d559ee80254cef6c9435d18215379eb8287a4b43d1633f85f23f3981938a92a81594ce27022665ef1b31544ca17aede850dabf2a6ded5075750e6a31b5b9665b57d11c2502c8affc89395d02322f4dcb88b096049de2ebf006cfea6b354d4a5ae7fcb6d51391b9bbf1360622eb0faaad562482ac593ba20a6aa54afd9a54b08da39f6a8d0b7760307597b045f3f42d3ce2cc78333bdd79874ea31194e38bf35dbcb49845ad712dbb416af87b1ea6bd7860534e35b7a3d4c6fb57abfdec602b813ad4560cfa56d81911c6326a8b90bf600000000000000000000000", .None}, + {.Shl, "6d0a3ffd2279b586bdafe08db16ababd36d747ed273287035ec85dd2c4fe549a76fba6ed0aebb5730a26f8c614bbce1614002a7493f14056bee6ef64d9c3723de04c4908ccea2ccb532097f9de81e0214b7167f7d78f0d9b8d9e05a58f49644d2c619d2634721a965b6664197ff6b423b6f71e1aeddc7f15cf8a200fc9c244ee56b4daee5bb0d1834c394b1deee9bfa5f998c34458642a797f2ba1b5b53216ea05959f948ea97dc3c84dfdba978dfc2002ebe3de868bff60f090388a2d338a47693490ec43963cab1fc3ade54f7b9f10635add61d0cdfc23d860b6e1dc2c3a68b2f4113c6ccd94de8dc5ee0d22d3ec125ea7fe06d2f6d6785fe7069a4efd6b9e82434bb08d46d496d23ae617ba4057e5c4842e2fe92fbce0723c736651a54015bb7fecb191c98baf16773e7daa9a91e16d357bcac0428bc06197adc7436bea1a396a0943700c44ac87c1028e65618083f6c5a596f29f88908ae1edc354ad346da5e579e67eca0c663003ef63ec8e983066845d2e0600277ca0c7fc18a98fc84b12c3331a163f113901ca53f521d59316ea6d7ae34de032fa6f561691924121a87b2b5bd74f3e46768dedcddccb1a884111376bc84e5a33f00e32655348e9aaff60a0157751eab33c7f3091d818a2015983b5c75926ed1c028286582dab6b04d7619ab64128d2f6abe73719de14fdb59469989b96e69e28f55085e9d6cb2b35ff", "9", "da147ffa44f36b0d7b5fc11b62d5757a6dae8fda4e650e06bd90bba589fca934edf74dda15d76ae6144df18c29779c2c280054e927e280ad7dcddec9b386e47bc098921199d45996a6412ff3bd03c04296e2cfefaf1e1b371b3c0b4b1e92c89a58c33a4c68e4352cb6ccc832ffed68476dee3c35dbb8fe2b9f14401f938489dcad69b5dcb761a3069872963bddd37f4bf3318688b0c854f2fe57436b6a642dd40b2b3f291d52fb87909bfb752f1bf84005d7c7bd0d17fec1e12071145a67148ed26921d8872c79563f875bca9ef73e20c6b5bac3a19bf847b0c16dc3b85874d165e82278d99b29bd1b8bdc1a45a7d824bd4ffc0da5edacf0bfce0d349dfad73d048697611a8da92da475cc2f7480afcb89085c5fd25f79c0e478e6cca34a802b76ffd9632393175e2cee7cfb553523c2da6af79580851780c32f5b8e86d7d43472d41286e01889590f82051ccac30107ed8b4b2de53f112115c3db86a95a68db4bcaf3ccfd9418cc6007dec7d91d3060cd08ba5c0c004ef9418ff831531f9096258666342c7e22720394a7ea43ab262dd4daf5c69bc065f4deac2d2324824350f656b7ae9e7c8ced1bdb9bb996351082226ed7909cb467e01c64caa691d355fec1402aeea3d56678fe6123b0314402b3076b8eb24dda3805050cb05b56d609aec3356c8251a5ed57ce6e33bc29fb6b28d331372dcd3c51eaa10bd3ad96566bfe00", .None}, + {.Shl, "ec9e34414ceb4d8b170cb0207ead60516175d0715078c8550f4da5d636931640abc50787984fd347589e06c77476e0bde27b0a7602914b0608d8bda696571d8ff530e5f664609cdd1599bddb5477f88f51a0335855a2e11201bd8549541a5803d3646dd94b3b7db4f6374fc9ad9f2a7312233eb97d5a486845bb52aafc9438b5724cd94eeddd4dcb707a48fc4a92e824160c544ff36bbe92ee8ed896cc907e78f59a06dbadd3d87c13a7820a611593fde0b0108c2073de512e997291a26125db2bef2927e1da7bbfc8cf1c68337dd492697febf6cdfc1f85807df00df6e1e20e0357c0554f30b1b9dc2817d23fbddddc66f0c873ad31cbe9c33829e6ec1687b974460ba44a2cad920dfa510b09da1a6c6104ea301ee639cfb731dbead3435476ff7e85e38cd238a47b73e04b5774a80f18f344bf5d9fb37f479eed91f0f759bac6926b2e26eba2b97b9abd09f7c70858ca75fe0441a0463082c0f58a3d82544f7203cec6adaefe52007676be32ce629e973182a04889df7e0c40afa9d87404bb3e0b984d7625d86f7a0e93d10844722bf68a50ae823fcc60507371c5435ac76348f69b30778e8e017442d90ed70801ee0db5f30901e73e599a8c289070927dde230acb07c4d0977468ad0dc042b4995d07f5c505f8808bdc35ebc8d6a96cea4cd608b93c95d9628db62e082b1adbc7ba67ff657d272ef09d437611c9c8976a81", "5b", "764f1a20a675a6c58b8658103f56b028b0bae838a83c642a87a6d2eb1b498b2055e283c3cc27e9a3ac4f0363ba3b705ef13d853b0148a583046c5ed34b2b8ec7fa9872fb32304e6e8accdeedaa3bfc47a8d019ac2ad1708900dec2a4aa0d2c01e9b236eca59dbeda7b1ba7e4d6cf953989119f5cbead243422dda9557e4a1c5ab9266ca776eea6e5b83d247e254974120b062a27f9b5df4977476c4b66483f3c7acd036dd6e9ec3e09d3c105308ac9fef05808461039ef28974cb948d13092ed95f79493f0ed3ddfe4678e3419beea4934bff5fb66fe0fc2c03ef806fb70f10701abe02aa79858dcee140be91fdeeeee33786439d698e5f4e19c14f3760b43dcba2305d2251656c906fd288584ed0d36308275180f731ce7db98edf569a1aa3b7fbf42f1c6691c523db9f025abba54078c79a25faecfd9bfa3cf76c8f87bacdd634935971375d15cbdcd5e84fbe3842c653aff0220d0231841607ac51ec12a27b901e76356d77f29003b3b5f1967314f4b98c1502444efbf062057d4ec3a025d9f05cc26bb12ec37bd0749e884223915fb452857411fe6302839b8e2a1ad63b1a47b4d983bc74700ba216c876b8400f706daf98480f39f2ccd46144838493eef11856583e2684bba345686e0215a4cae83fae282fc4045ee1af5e46b54b675266b045c9e4aecb146db1704158d6de3dd33ffb2be9397784ea1bb08e4e44bb54080000000000000000000000", .None}, + {.Shl, "90bef72915b3872161383ad73516cdc5bb37a2094b5a8494b797194f47ae332c336834e14694a99985c9971851f62116bb83c3f21b2cb7d7fb65b1e5d82a61656f8c95c88c9f867d9b796258161de3bce83ebe4ea96768356ca0d124189dfbd62fa31300dfc4a6f64f8d35530ec19faf683f6e3b6e9cf43ef2c0fafc06e3171950d3d485614a9d879ac46924e69767505318ddd935cc56ec8ccaf8b65fa675c100b59b45b3261223b0f6bae32e5c18a8840eeda47179aa821e7deeb5dae6d393bf37837ca467fc7a56813520c6d296feb0c16c657351bf32644a29bfca7341cc231e8c2bc861fa6f0770435c4ec084dce184e5fd21f9396ea6c886e7dadffc0de6774a6de62d6ce196f8062e849fbef1f63367daa63012e3858b46ed8ab91e73505be8bb753abebdda341d0002edb9afb9c66008d1aa40142b449472ae4f0c7ff44fecf283cc3a691dd34f4aebbc12c7215d45dbf6c8b67dbfabdd979efdbd4c3db652ddb0bf679650c4f718616d4093be462260574ef8d87921e1b40f51c3b7c2e5b44454fbf90bb0973f0cb187d8e015053ef3373538c9188d9176e0ec341429f59c6307be6b6c1156fb0b93feae2ac551f62842e0ad431abe91244d6b97b3b41e4c011ed36f767dca0e514fcb42d1f0b505a07f688c9edde9d6fa16fb2de9dd1b812fe0ad3602f01ba37dc8e940acceeba493667224e00130ab5f257a5204", "62", "242fbdca456ce1c8584e0eb5cd45b3716ecde88252d6a1252de5c653d1eb8ccb0cda0d3851a52a66617265c6147d8845aee0f0fc86cb2df5fed96c79760a98595be325722327e19f66de5896058778ef3a0faf93aa59da0d5b28344906277ef58be8c4c037f129bd93e34d54c3b067ebda0fdb8edba73d0fbcb03ebf01b8c5c65434f5215852a761e6b11a4939a5d9d414c637764d7315bb2332be2d97e99d70402d66d16cc98488ec3daeb8cb97062a2103bb691c5e6aa0879f7bad76b9b4e4efcde0df2919ff1e95a04d4831b4a5bfac305b195cd46fcc99128a6ff29cd07308c7a30af2187e9bc1dc10d713b021373861397f487e4e5ba9b221b9f6b7ff03799dd29b798b5b3865be018ba127efbc7d8cd9f6a98c04b8e162d1bb62ae479cd416fa2edd4eafaf768d074000bb6e6bee719802346a90050ad1251cab93c31ffd13fb3ca0f30e9a4774d3d2baef04b1c8575176fdb22d9f6feaf765e7bf6f530f6d94b76c2fd9e594313dc6185b5024ef91889815d3be361e48786d03d470edf0b96d11153efe42ec25cfc32c61f63805414fbccdcd4e324623645db83b0d050a7d6718c1ef9adb0455bec2e4ffab8ab1547d8a10b82b50c6afa449135ae5eced07930047b4dbdd9f72839453f2d0b47c2d41681fda2327b77a75be85becb7a7746e04bf82b4d80bc06e8df723a502b33bae924d99c8938004c2ad7c95e94810000000000000000000000000", .None}, + {.Shl, "-91d6f507a8d69a20a3e5f669f28fe538889ccd314468678e7f399114c135f22da282c4bce3378c030545fda0aa612ff36a299758cdf8936bf324c54a2d3417bcf851e40673986d739116db2c6c7cc0370890e063e8acd114d7f8a83c2e594da51f73decdbd099f1d4ed0a15058fc6aeeb4aace3a0641d7302fc459f85342861a3a001902e65cd23e7be47152f27dbfaac05f3ee00092f0c0cfa8f1a8739e2b7c1b8733d3e517fa607ff506a44cdef895b10c833fcdfa45f2d4e8622277182e6084f3e14620078eafb9e2577fe71a25cb27dd078619c94521b59f7351a3365b274acbe20191976b9c4dceba9fccdefa0c35b31d9bbb38ea034a783bdf34c630a2fcfacd2286dc94e6ebcd4b1ae47eff976ee7586f63ddc00620a4b977961cb97b5a975d6e033c85008d7235ede6c815f82025c88fbaea2ec275c613f60439504ddedc83f443b89213a959207bf1380a0ab5e08b06ba9e21d82f4c41afbd646a80fc1088d74cb57d52a40cf7fae7bb4ec2ffc45eda07a94ac87a9f827c5449abf9c55980dc5f4f58210b3eed4b64998d0c0789aaf5c5b9fb9a853a771fad2a071beec7107d53cc51fcfcdd85fb7fc7a522d34774f377ccce76cb04564f4fc42d2eddd8c2b4fdaf6dc9c3a7224d40764d6c010d479a2e411a8f191bdef959790700a974cac40ee02b95db22654f6ad76d2353efd58f3ababe5ec0a93ce5d7bc0884", "12", "-2475bd41ea35a68828f97d9a7ca3f94e2227334c511a19e39fce6445304d7c8b68a0b12f38cde300c1517f682a984bfcda8a65d6337e24dafcc931528b4d05ef3e1479019ce61b5ce445b6cb1b1f300dc2243818fa2b344535fe2a0f0b96536947dcf7b36f4267c753b42854163f1abbad2ab38e819075cc0bf1167e14d0a1868e800640b997348f9ef91c54bc9f6feab017cfb80024bc3033ea3c6a1ce78adf06e1ccf4f945fe981ffd41a91337be256c4320cff37e917cb53a18889dc60b98213cf8518801e3abee7895dff9c68972c9f741e1867251486d67dcd468cd96c9d2b2f8806465dae71373aea7f337be830d6cc766eece3a80d29e0ef7cd318c28bf3eb348a1b72539baf352c6b91fbfe5dbb9d61bd8f7700188292e5de5872e5ed6a5d75b80cf2140235c8d7b79b2057e08097223eeba8bb09d7184fd810e541377b720fd10ee2484ea56481efc4e0282ad7822c1aea788760bd3106bef591aa03f042235d32d5f54a9033dfeb9eed3b0bff117b681ea52b21ea7e09f15126afe7156603717d3d60842cfbb52d926634301e26abd716e7ee6a14e9dc7eb4a81c6fbb1c41f54f3147f3f37617edff1e948b4d1dd3cddf3339db2c11593d3f10b4bb77630ad3f6bdb7270e9c893501d935b004351e68b9046a3c646f7be565e41c02a5d32b103b80ae576c89953dab5db48d4fbf563ceaeaf97b02a4f3975ef022100000", .None}, + {.Shl, "eeac9d0541ed80e9e317ca70f6ca2e1ac4c9363cbfcdad129c9080fc294fcbab6d0b71163aae74c00e108d941dd4ac71935689f2348d462b257f97740b088b0e72982154e628c7dc98ae1422a147abf7696c8a8436fa80dfca3c7ecbef5def8e6642e72296afcc82bdb1ab872e49fbc26745a98c85915ca87b30580065f3844ff0a2b1a79da11ed0b0f716245b79537357172ea11fcd28850f31cae8d497b819bc555be68844f830fae7bcf217da8ad518cf8253e8b0d28192fe3ef225f736accf8fda49fb893ee4728649abee150551296960cb5487ae924ec538b650b2f2f7db9542430d096db07ce7d4ca6f6bb2ae26ff7fa5d3dad4df5cdf60b708d172123fd114221056853b82b707b246e046bf2b973857a6caab7e92e76124f260db3384f89cdff5200624b427d37c2013826f3570eedd92f860c7b2e5c31d60ff9c6431819078e3dfda44e90d096ca84a10dc6e58195d49e0ca96df5b8734554f1e7e502ab28fb5e328aeb46498b4ff4c4c2276af0d4c0f01eec8966c3c5feb1df3bf9f3760f49230749726f5dd0fb6b4a43b63330c9af77d6e8c533c6c25000dd2e702706978944ef868dadfe678a19f86ea69e9e9fd65df777be83cc738a7535a2733febdabca85ab5ebe377d06df75aecb877436eb3dc427f9bdcb863a260c610759ec9fd78407be5e258bf2c47cbb0c0f740c58cbffaf3c7224f738ceddce621a", "28", "eeac9d0541ed80e9e317ca70f6ca2e1ac4c9363cbfcdad129c9080fc294fcbab6d0b71163aae74c00e108d941dd4ac71935689f2348d462b257f97740b088b0e72982154e628c7dc98ae1422a147abf7696c8a8436fa80dfca3c7ecbef5def8e6642e72296afcc82bdb1ab872e49fbc26745a98c85915ca87b30580065f3844ff0a2b1a79da11ed0b0f716245b79537357172ea11fcd28850f31cae8d497b819bc555be68844f830fae7bcf217da8ad518cf8253e8b0d28192fe3ef225f736accf8fda49fb893ee4728649abee150551296960cb5487ae924ec538b650b2f2f7db9542430d096db07ce7d4ca6f6bb2ae26ff7fa5d3dad4df5cdf60b708d172123fd114221056853b82b707b246e046bf2b973857a6caab7e92e76124f260db3384f89cdff5200624b427d37c2013826f3570eedd92f860c7b2e5c31d60ff9c6431819078e3dfda44e90d096ca84a10dc6e58195d49e0ca96df5b8734554f1e7e502ab28fb5e328aeb46498b4ff4c4c2276af0d4c0f01eec8966c3c5feb1df3bf9f3760f49230749726f5dd0fb6b4a43b63330c9af77d6e8c533c6c25000dd2e702706978944ef868dadfe678a19f86ea69e9e9fd65df777be83cc738a7535a2733febdabca85ab5ebe377d06df75aecb877436eb3dc427f9bdcb863a260c610759ec9fd78407be5e258bf2c47cbb0c0f740c58cbffaf3c7224f738ceddce621a0000000000", .None}, + {.Shl, "-964a6ae1783eb8a69d70c33c14e271550d8d17ca394c4560b663794a48ff7bcb9c8dbdaf7e218b05078823ebf587723878803d54563827b2e8c782103640173cb4586ee68eac855fafc2648f888083725c1be6f01e4b9f0fc5a5851d426369c5e581ba6f1568e0548f988b94b374f75715941084fd272061129e4dab619d9aa7ba2d98a323adf77564ed1b4a135c0aa7b93e43797fe77af072b14ba8e3cad2bac4f7e250c70d9bb54cd2885dbfcfebadfad383109be69ed8fd0ca8145c90708b045aa918385ce58afb8a52a562c8c8397e613feb66124d5784f7615dc9b685fd5d919118604297c1db62974442f29d33142b4cb743d0e0daa1a3814f74a5cc643461629562d96e6be06f9eb008052b92672790579d6869e5f0f00f353f7fb7f84eca4db884442b00c99c67a0158c7749b41f9164ab1a5e9aa0d47e95215f48044154d7b2c49b52eabdcda3acc1b391d4418ac8c4472531883784c032b4607bddf7de0f2d3375bbc8e5ca8ecd9ede6b4e4f5695e797490d1d2b2aa01e1e0639e6670b1502437738002a34fd160329bcd2a02bfacc3631060ebdc8b337d4117b2883b6c55ce2dc2a5cbc008b55bc3a4a4095dad97b42ac2cbe4ea8c731802842152d789f028ff5fc134fd488d4f74f8c7af410c94c865647186d63fe3906cc8b1e9a57b7f20a861875f7f52d8511c12d790dcc7d45c777349c2c26f3d49882934b", "b", "-4b253570bc1f5c534eb8619e0a7138aa86c68be51ca622b05b31bca5247fbde5ce46ded7bf10c58283c411f5fac3b91c3c401eaa2b1c13d97463c1081b200b9e5a2c3773475642afd7e13247c44041b92e0df3780f25cf87e2d2c28ea131b4e2f2c0dd378ab4702a47cc45ca59ba7bab8aca08427e939030894f26d5b0cecd53dd16cc5191d6fbbab2768da509ae0553dc9f21bcbff3bd783958a5d471e5695d627bf1286386cddaa669442edfe7f5d6fd69c1884df34f6c7e86540a2e483845822d548c1c2e72c57dc52952b164641cbf309ff5b30926abc27bb0aee4db42feaec8c88c30214be0edb14ba221794e998a15a65ba1e8706d50d1c0a7ba52e6321a30b14ab16cb735f037cf58040295c93393c82bceb434f2f878079a9fbfdbfc276526dc4222158064ce33d00ac63ba4da0fc8b2558d2f4d506a3f4a90afa40220aa6bd9624da9755ee6d1d660d9c8ea20c56462239298c41bc260195a303deefbef079699badde472e54766cf6f35a727ab4af3cba4868e9595500f0f031cf333858a8121bb9c00151a7e8b0194de695015fd661b1883075ee4599bea08bd9441db62ae716e152e5e0045aade1d25204aed6cbda156165f27546398c014210a96bc4f8147fafe09a7ea446a7ba7c63d7a0864a6432b238c36b1ff1c8366458f4d2bdbf905430c3afbfa96c288e096bc86e63ea2e3bb9a4e161379ea4c4149a5800", .None}, + {.Shl, "4eb346ac6719c269e9f6297c3fe4eb5d07f7dcc6effda18e2fe2458bd599986549f6d66d25688d5f4cca1cdfde04b45c9beba44cf1e52d1d4385c5c9cc75f12de02ff098f5bf5239643756e376b967b6bbe6049e11ee716ef800a260fa732647acf49678714e8393e7128ab7f0a890243b564c22293bc7130dcc9827709b451aa88da911a63b30ea48e3ad85d174c7158a5cbbdd13eafd814a8f295d8d591fdf43e2dfc14a1882c93241f2c0a9308865d285876027d040f942ca3850d9e2d87938e01783f5da5453f849f3403110c83ee53b4c3a6872c57ab646d8f0b34ae8030c2bec7645cb0c954ef8b61d48baba7596ec6b41b32c3615f2ac6338ca16454d76806b72f5ed75e1ff8214096551b226ec2c82acdeafd6c94bb194f5fd5854de999ab0b98dc789ac13b00974011fdfd2a4b0dda223fb997f90b45d69119bdc1c85bb842f17a39f2e627586041f2d9685b3e3e4c69101e923c5da7ac1a4c933cbf6d40d9a9397e2c4f746e607b642c7f6f76422bf71abfefab5c7cd90ffe5c5c9c7549edf4eac969815d27344a1176f87934cc2d3f5e3543eda713abaa7fe12b3bb6497232cabce2094f7a2af96b178a9f9cba6ac69f211f056bc0b922e050f9a68f18ec575f2398034805de20f780c9b9b08722f796cf48b87599d204698090711c4b756ee5c6b1b1b365c38cc602912300ec48ca410e3b1018a70c220e360fa", "12", "13acd1ab19c6709a7a7d8a5f0ff93ad741fdf731bbff68638bf89162f5666619527db59b495a2357d3328737f7812d1726fae9133c794b4750e17172731d7c4b780bfc263d6fd48e590dd5b8ddae59edaef98127847b9c5bbe0028983e9cc991eb3d259e1c53a0e4f9c4a2adfc2a24090ed593088a4ef1c4c3732609dc26d146aa236a44698ecc3a9238eb61745d31c562972ef744fabf6052a3ca57635647f7d0f8b7f0528620b24c907cb02a4c221974a161d809f4103e50b28e143678b61e4e3805e0fd769514fe127cd00c44320fb94ed30e9a1cb15ead91b63c2cd2ba00c30afb1d9172c32553be2d87522eae9d65bb1ad06ccb0d857cab18ce328591535da01adcbd7b5d787fe0850259546c89bb0b20ab37abf5b252ec653d7f561537a666ac2e6371e26b04ec025d0047f7f4a92c376888fee65fe42d175a4466f707216ee10bc5e8e7cb989d618107cb65a16cf8f931a4407a48f1769eb069324cf2fdb50366a4e5f8b13dd1b981ed90b1fdbdd908afdc6affbead71f3643ff9717271d527b7d3ab25a605749cd12845dbe1e4d330b4fd78d50fb69c4eaea9ff84aceed925c8cb2af388253de8abe5ac5e2a7e72e9ab1a7c847c15af02e48b8143e69a3c63b15d7c8e600d20177883de0326e6c21c8bde5b3d22e1d6674811a60241c4712dd5bb971ac6c6cd970e33180a448c03b123290438ec40629c308838d83e80000", .None}, + {.Shl, "-59f18f20a059e4e91860c2920dc39625a943493c8eb922f28c6f3c75731acaa8ac44b9c115e881a39bfdb79d39daf4e09970700cccbd516c3a10473f195dad4aeb20f0cf9e8f3098d8d7772b8727ab1aaa898174847ee29b0ea9c22a934307fc33dabf7e75cf68eb769da02e0879a130d9f4f4b2e15e43f05a9ba6972fdd06e404e7c6c683bfb8bfd8fb955bbc077068819b053e78a3c984776f851f38a56de9d386e2440da0345b8a13afa605c0949d5033c3380aa6906120e982c574561aa2758fddcfc8a934c08b2fe6253a32d29c7b434ec0a4b84275d72a5cbd3d972a18202957e0ca66fdf4fb55242e141acdc64c53476f46861f702cab2fb22f07e5e7ff18594377345bd18921888717628887d039e005fadece5cd2d920728c1f5e62b0c248bae4ee59abf7ef0960fc5e4d13352bf6719a06ee1fdb29084fe8d37abdd10d23ed69b7dfa7892e91156260d33d8d48ed77267d21d6719d74c6578c3fbfb47ef5e533dc089317ea0f5510065f5a9b32d9557eb90f5d30bb6b61b784cff78c3a9aa8e7564408d1056e1c86ddd091422f6db95468ef54e4501cf904d03c3cd92f8d7d60e16c37d83c3afeb12370b2e033676926ddb6f60450acff2c9b37939e9f485257d24278df7df632a578b6c5126d797eb34b5385cafb225b3242c63d23668d6a6a6834765df8b11e31061d0fd5858ea63c9c417b76e43f42f141ea9c", "2", "-167c63c82816793a461830a48370e5896a50d24f23ae48bca31bcf1d5cc6b2aa2b112e70457a2068e6ff6de74e76bd38265c1c03332f545b0e8411cfc6576b52bac83c33e7a3cc263635ddcae1c9eac6aaa2605d211fb8a6c3aa708aa4d0c1ff0cf6afdf9d73da3adda7680b821e684c367d3d2cb85790fc16a6e9a5cbf741b90139f1b1a0efee2ff63ee556ef01dc1a2066c14f9e28f2611ddbe147ce295b7a74e1b89103680d16e284ebe981702527540cf0ce02a9a418483a60b15d1586a89d63f773f22a4d3022cbf9894e8cb4a71ed0d3b0292e109d75ca972f4f65ca86080a55f83299bf7d3ed5490b8506b3719314d1dbd1a187dc0b2acbec8bc1f979ffc61650ddcd16f462486221c5d8a221f40e78017eb7b39734b6481ca307d798ac30922eb93b966afdfbc2583f179344cd4afd9c6681bb87f6ca4213fa34deaf744348fb5a6df7e9e24ba445589834cf63523b5dc99f48759c675d3195e30fefed1fbd794cf70224c5fa83d5440197d6a6ccb6555fae43d74c2edad86de133fde30ea6aa39d5910234415b8721b77424508bdb6e551a3bd53914073e41340f0f364be35f58385b0df60f0ebfac48dc2cb80cd9da49b76dbd81142b3fcb26cde4e7a7d21495f4909e37df7d8ca95e2db1449b5e5facd2d4e172bec896cc90b18f48d9a35a9a9a0d1d977e2c478c418743f56163a98f27105eddb90fd0bc507aa70", .None}, + {.Shl, "97eb82316b12c7e599f9dc924c390801979b4aca660e76a694ce2775ade4e950feca3991f26ff9765637cc17842d3c6bc00774b6af2e7a7ab3b00507768e84bf720d0debfb43210e4cfbe81e6e142f9e6b7f4eeeaf2c3262025c962a13ba3fbd691a81ed3ede39aa511132ce3e6f9540b237e0f6dc338ac52d52c9dbd82888efb926f021b3908af82fe9a6ed7253a04d266137d51af16dace3b9a6f87863872736af619bfc77a824fc09fa6d49f72caf32fe392b20598c2aeee64569dbe10c89027d1178fe981c22696d75682f30fd145bf0073fb90c7a19176a02b8e0b8e35ad3258ad7656e2881b8b6475d82ebcea37e85a8cf3b1b6012569f310eec347ceabe74fb35df7beafbfa0f3a2342687796d2c07c609292fb1842d51aa1783a5090770316c815875b114a84cf71c708884745183146b3f86a5a1a9f8282b47859ce8dfe444b740efb4e22cf08883b04957622d7c6aa0ef303368c1c62b0c418746cd045a6bcfb297a5f7ceee85946759dc43de5f33bf2f1182de4e4f6d6035d52db3403ea3ba81595400ff3e0efcdf93a2f4888c1c77a09d68321460bfee35890f18b75e373cfcc5bd8882a6898fd580bbab1cca74528c9ce3982da0fdd5acc6cc863888b25da3971ec76e723b8142c901e71f36f7d43b08ca7245e4d02cdb763e90d8a107d881758f10e699c66a4a3530d39a9c22dc03f2e8fca36fb5091a3c6a6", "3a", "25fae08c5ac4b1f9667e7724930e420065e6d2b299839da9a53389dd6b793a543fb28e647c9bfe5d958df305e10b4f1af001dd2dabcb9e9eacec0141dda3a12fdc83437afed0c843933efa079b850be79adfd3bbabcb0c988097258a84ee8fef5a46a07b4fb78e6a94444cb38f9be5502c8df83db70ce2b14b54b276f60a223bee49bc086ce422be0bfa69bb5c94e81349984df546bc5b6b38ee69be1e18e1c9cdabd866ff1dea093f027e9b527dcb2bccbf8e4ac816630abbb9915a76f84322409f445e3fa607089a5b5d5a0bcc3f4516fc01cfee431e8645da80ae382e38d6b4c962b5d95b8a206e2d91d760baf3a8dfa16a33cec6d80495a7cc43bb0d1f3aaf9d3ecd77defabefe83ce88d09a1de5b4b01f1824a4bec610b546a85e0e94241dc0c5b20561d6c452a133dc71c22211d1460c51acfe1a9686a7e0a0ad1e1673a37f9112dd03bed388b3c2220ec1255d88b5f1aa83bcc0cda30718ac31061d1b341169af3eca5e97df3bba16519d67710f797ccefcbc460b79393db580d754b6cd00fa8eea05655003fcf83bf37e4e8bd2223071de8275a0c85182ffb8d6243c62dd78dcf3f316f6220a9a263f5602eeac7329d14a32738e60b683f756b31b3218e222c9768e5c7b1db9c8ee050b24079c7cdbdf50ec2329c9179340b36dd8fa4362841f6205d63c439a6719a928d4c34e6a708b700fcba3f28dbed42468f1a9800000000000000", .None}, + {.Shl, "a3eb5c7ad3b382776b884c031c40119b605d30c35e8e857823848cdfd4cb1b86dfea14da9eb6643ae3030dcbe6432dbac11835211d216b9fdb7524d40cc626d85f09a85b69fb8d27273df69c86081841fd44cd6c589ed43fdbac8a45f357819fc2837cd4615ab8a7534789820250005384d377a914236d14ac8bdd2179d12e59b6a77f5d8ce93c0fdfcff5f88807baecf3d2e7cff9c92fdd97f3f76ecfc86dbdbfa8906295c917f2e8da2442929caa250e5c81f51b3fd90fea16e12a07fa79ca0d15a2cb38afd8264356af6ca46b3a4d3f4ced4f14e8ccef53433d795f28a74ab78cfb5b86ea3d1a1d61e934bced4c93231484adb58c9159124f2a68ed4929bb3c24db1ac3f24298774cf9e92b77f4fcad8fc1b1fa29234679e088d2ca3973aa9e5085b19acb085abd6ba1a1301bff839de0930625675ba797579316ebe9bd847ce4e58551a8c193c4894975451ac45307628efa7f08bdd1f8c7c82efae8fc554313c68d80b6f1f46310e478833b001917c5f6369231320189a57f798cc34c6321e91292bebe31d4d3af77deec5c3be449af95dbe80582e5d1142d7750d7a96133f9bf6f53b65f32122b9c32ffe826303a6edf4332425122ee732ab3a0c87b5462a32b1e4761947be278178fff487b601a9ab8fbc35a443717162cb3a5ffd9209b7196b735e34fafcc8e923161ae68a9c6c665055631093e2a27fb564ea68fb5", "4d", "147d6b8f5a76704eed710980638802336c0ba6186bd1d0af0470919bfa996370dbfd429b53d6cc875c6061b97cc865b7582306a423a42d73fb6ea49a8198c4db0be1350b6d3f71a4e4e7bed390c103083fa899ad8b13da87fb759148be6af033f8506f9a8c2b5714ea68f130404a000a709a6ef522846da295917ba42f3a25cb36d4efebb19d2781fbf9febf1100f75d9e7a5cf9ff3925fbb2fe7eedd9f90db7b7f5120c52b922fe5d1b448852539544a1cb903ea367fb21fd42dc2540ff4f3941a2b4596715fb04c86ad5ed948d6749a7e99da9e29d199dea6867af2be514e956f19f6b70dd47a343ac3d26979da99264629095b6b1922b2249e54d1da9253767849b63587e48530ee99f3d256efe9f95b1f8363f452468cf3c111a59472e7553ca10b63359610b57ad743426037ff073bc1260c4aceb74f2eaf262dd7d37b08f9c9cb0aa3518327891292ea8a3588a60ec51df4fe117ba3f18f905df5d1f8aa86278d1b016de3e8c621c8f1067600322f8bec6d24626403134afef3198698c643d225257d7c63a9a75eefbdd8b877c8935f2bb7d00b05cba2285aeea1af52c267f37edea76cbe6424573865ffd04c6074ddbe866484a245dce655674190f6a8c546563c8ec328f7c4f02f1ffe90f6c0353571f786b4886e2e2c59674bffb24136e32d6e6bc69f5f991d2462c35cd1538d8cca0aac62127c544ff6ac9d4d1f6a0000000000000000000", .None}, + {.Shl, "c374eaa15d4a5fafb3cc14ac3dad8cce40642cd43091e3598fcaa7835a7d59a0ebce601b7dd57680adcb51a93998524f856aa7df100f193be833d1ee26d2c48746dfe784dfc1ceec85d50c9564768d0fe02adfa73c84eb77d652eac4b3a51c862cad42dbe58065e0a0fb2db1407d61dea50338833b1195dc1838e773109b6b25d9ff543794d49493caf4aa69897590f0ffa4c8a4354baed8793cdb473ff6c6dfb4e872a6ee5d69005066535e8b69e9a0cd532f71e4a2b643cbbcd4532d30b5af25983674f70eb54253b0acc8ac66a3981ae5920be2c9bd5bb604be4bc1f729ad05292a0edd56682ae150e46f730c9122c7d0c0510d3883acd5d142807dec72f8d227d49cbeb33ef67c391310a6bcccbe7dea2216f159b8bdfe74d2c8c5de4064d456c5101969b59d4665703039894fff34e4efaf8a2c0de69963615ccb7ed66190effd81c527a14251a37c2e5415ea3a4afba01c9a26fc47ebae2bebdacc2ccc785ddc0ef18ab16a0b556ababbdb47e4cb43f2b95fd1ef096843e65ff91bffe5cd80194d6c6b0900fc2b565d823631027df27de2e9177e5340d41faa6470907a23406a6816c9e16fe6a19422b4114061498da75ee23565b651c004a4d11f664d54e0f0bab1e878915aa29628c7716b7e00e3e2faf9fb2d702fc2df80c7959a3079ca85cb2d6f4e5300d4c6e5366e789be77928fde12bf9c59722867e1a6d2d5f", "31", "186e9d542ba94bf5f679829587b5b199c80c859a86123c6b31f954f06b4fab341d79cc036fbaaed015b96a3527330a49f0ad54fbe201e3277d067a3dc4da5890e8dbfcf09bf839dd90baa192ac8ed1a1fc055bf4e7909d6efaca5d589674a390c595a85b7cb00cbc141f65b6280fac3bd4a06710676232bb83071cee62136d64bb3fea86f29a9292795e954d312eb21e1ff4991486a975db0f279b68e7fed8dbf69d0e54ddcbad200a0cca6bd16d3d3419aa65ee3c9456c879779a8a65a616b5e4b306ce9ee1d6a84a761599158cd473035cb2417c5937ab76c097c9783ee535a0a52541dbaacd055c2a1c8dee61922458fa180a21a710759aba28500fbd8e5f1a44fa9397d667decf87226214d79997cfbd4442de2b3717bfce9a5918bbc80c9a8ad8a2032d36b3a8ccae06073129ffe69c9df5f14581bcd32c6c2b996fdacc321dffb038a4f4284a346f85ca82bd47495f74039344df88fd75c57d7b5985998f0bbb81de31562d416aad57577b68fc99687e572bfa3de12d087ccbff237ffcb9b00329ad8d61201f856acbb046c6204fbe4fbc5d22efca681a83f54c8e120f44680d4d02d93c2dfcd432845682280c2931b4ebdc46acb6ca3800949a23ecc9aa9c1e17563d0f122b5452c518ee2d6fc01c7c5f5f3f65ae05f85bf018f2b3460f3950b965ade9ca601a98dca6cdcf137cef251fbc257f38b2e450cfc34da5abe000000000000", .None}, + {.Shl, "-576047e8ed2d02648b59f8035f76082d9b305578f4d927ae51b25d6882e767ef97a94e7bf4ab92531bf95858cad956d5ac620674c693f202763ac0a3ad86c1ebe29b8a355b5e8735db09397fc2f22b99b3540ddfd2d46a26c31ed2fcd897105f40d386f8b09063572a87ffd48390493f7c826e5381f0d1940eb30ea764d8fd8efbaa04c7d4b7bc342729a4d07af73973ff62716779e3cff35cbd3a06d7dbb92ce12b7a388c7c0fd3d3c957768f021a79d79604a12c432dd9cde78e137e531f5f55c535ad1d1e115557e24f8c910a6a059c81aaae7aa6364f471c6eff989e5b50dabccb3f8a40b98f2793986e467187f9ec33cb19f945cef2849f13d705198ccd3e93bd706095866dbd8d2004bdfef1c89b03d0ba99de673f3d70d7324ab399b1efb6a8cfb0cb06362c86af168c9c4e8ac1acebf5950be381f04c36be4d9f26fc6ae26212502d946a22a2b29fdd5535c1e9f88f547f075621fff9eb47490b2eb21354038da9632fb039c2b6c89e0b960baff68f6a5ecd543e160e27f860c3930f7f68fbe1ff4e17b7eea735509cddea71dedc9b38b6b190261e67207768fc6c89aee3c083cbe209b6506253e5610ae37c778c8cc716b9b33185952efe02dc17dcda17841c093283f77b55d3e586dae1c0cac3377677dda92818464d42fe64a6e5c706bf880ed84891be30bd07cf713ee800fcd446972913d28defcb9e498e6d17", "59", "-aec08fd1da5a04c916b3f006beec105b3660aaf1e9b24f5ca364bad105cecfdf2f529cf7e95724a637f2b0b195b2adab58c40ce98d27e404ec7581475b0d83d7c537146ab6bd0e6bb61272ff85e4573366a81bbfa5a8d44d863da5f9b12e20be81a70df16120c6ae550fffa90720927ef904dca703e1a3281d661d4ec9b1fb1df754098fa96f78684e5349a0f5ee72e7fec4e2cef3c79fe6b97a740dafb77259c256f47118f81fa7a792aeed1e0434f3af2c094258865bb39bcf1c26fca63ebeab8a6b5a3a3c22aaafc49f192214d40b3903555cf54c6c9e8e38ddff313cb6a1b579967f1481731e4f2730dc8ce30ff3d8679633f28b9de5093e27ae0a33199a7d277ae0c12b0cdb7b1a40097bfde3913607a17533bcce7e7ae1ae6495673363df6d519f61960c6c590d5e2d19389d158359d7eb2a17c703e0986d7c9b3e4df8d5c4c424a05b28d44545653fbaaa6b83d3f11ea8fe0eac43fff3d68e92165d6426a8071b52c65f6073856d913c172c175fed1ed4bd9aa87c2c1c4ff0c187261efed1f7c3fe9c2f6fdd4e6aa139bbd4e3bdb936716d63204c3cce40eed1f8d9135dc7810797c4136ca0c4a7cac215c6f8ef19198e2d7366630b2a5dfc05b82fb9b42f0838126507eef6aba7cb0db5c38195866eecefbb5250308c9a85fcc94dcb8e0d7f101db091237c617a0f9ee27dd001f9a88d2e5227a51bdf973c931cda2e0000000000000000000000", .None}, + {.Shl, "c229f2764f657e1bdb0506472750ae304fe0b698e63b047afe9c868a124b90b873974948704d8f2d9145e9b2a0261d6f5fd645d0f1d811721f64168c188fd51968385edc5bfa41f76fc8c6e00678ae9e3d9d5bab9f996a20f5760596f48886378b3087cdc47af2d8650c24f8d732a0b2772bf4993d9f537d8fda39ed51a7c12e66cde7f3959f94d280689cef4e2976887dd3f322e85e23b3cefd9cb2ff9a1af153363afcdb55af595fc10fc16fc05f7d50d0b5f2e386a93d013aa1edcefe10bc89d60ed28c6e66ef11f300080ec0af3eb9b34f01ff77e66d935422c722f8a3d490c5203f0faffe5322236a1fc0afcbed2dc8647812895f9fe9ea72c8db9d2350dfe89efe0f3ca54fcdb7472a65d258c2051f443547272333594b12892afd18ae1bd67ee3c7dee29f209c214ba64dadf42ba45a2a76613b0087370f4ac1495cfd1acefc93fe871e55cc4a4a22e528594926ba5a6c0f671eb8dbfc94272e3f1dfde2bb459aadecf1636d5c7ce859cbf21f69bbbbefe0d8aee3f45a22db2bd304c1ab074bb716648c4eb854e937a992bbed255d54ba7480fb10613fb9abf4f41ebe38fc9e3091f8e1161ca2d6837c5444bc42db4613777f829613792b16f4b838749f642125337fb1aa539570c856ad46043057e54260ad21007a92cd4c60e71f3b88fb02b86c6d0a5ff9215406603882734cbbf67f3bf2c2262a1f851fa606b07", "42", "308a7c9d93d95f86f6c14191c9d42b8c13f82da6398ec11ebfa721a28492e42e1ce5d2521c1363cb64517a6ca809875bd7f591743c76045c87d905a30623f5465a0e17b716fe907ddbf231b8019e2ba78f6756eae7e65a883d5d8165bd22218de2cc21f3711ebcb61943093e35cca82c9dcafd264f67d4df63f68e7b5469f04b99b379fce567e534a01a273bd38a5da21f74fcc8ba1788ecf3bf672cbfe686bc54cd8ebf36d56bd657f043f05bf017df54342d7cb8e1aa4f404ea87b73bf842f227583b4a31b99bbc47cc00203b02bcfae6cd3c07fddf99b64d508b1c8be28f52431480fc3ebff94c888da87f02bf2fb4b72191e04a257e7fa7a9cb236e748d437fa27bf83cf2953f36dd1ca997496308147d10d51c9c8ccd652c4a24abf462b86f59fb8f1f7b8a7c8270852e9936b7d0ae9168a9d984ec021cdc3d2b052573f46b3bf24ffa1c79573129288b94a165249ae969b03d9c7ae36ff2509cb8fc77f78aed166ab7b3c58db571f3a1672fc87da6eeefbf8362bb8fd1688b6caf4c1306ac1d2edc5992313ae153a4dea64aefb4957552e9d203ec4184fee6afd3d07af8e3f278c247e38458728b5a0df15112f10b6d184dddfe0a584de4ac5bd2e0e1d27d908494cdfec6a94e55c3215ab51810c15f950982b48401ea4b3531839c7cee23ec0ae1b1b4297fe485501980e209cd32efd9fcefcb0898a87e147e981ac1c0000000000000000", .None}, + {.Shl, "-50ef35251e97dadc4339555fbaad473e41f73fb1c45d6653d65fd0a5f37e1e594fe109cf32c1a1bbcb48950b8021de4602d3afab037c9a281fcb15b49635551cdce469daac535359b01bc8f2620749d9e1867a529ba1b5c4bf5c7b9d8c64bd3c96e2db7a286fc4e7dfcea54311ba94b16d430bd90f46fbf4e0b38f9b6be28786c277adc9919264b9fc0589da0ce67cc86985e6911d41ef9dda6d0d2c78a9e9ac87f6fb30482714a4a37c962ec5428602549574151782d084e4c904d3e93db8702390f9a7ac56200f92cc98e4c2c20afed6d9b7b78cc492bcbe8614d375dd714c577e0ba26e69568ef664d5398f9207c1af9dd35df69fd8ebd59a77712d0ce8c0cba6d43b40c27ea470a722fe4fbce1723bfba6346aefccfd19a395bca46b39753d80217389ab10134c84ab8ae18bb059a6da010d209235e3668b5a3860017b3bf39a50b6a397d2acf04cd4c596cb2ee9af85fadf92d562322121e9b14e69cbc9442fd01ff5920f4e634935125e8829b3c1e4c3420140a0f31a537abceca81ea7784cc4a564b72e0f7051d4449ba19f01fcb4ec0963c9f11426c13d713a2cf85dc5c1c3ba4c3e4846268ba51f960a687a57ebdb72fdcabe9502c5d888a9bdcd2d7f58f4df77e3cb5cfeeea1bac3b6b0a035919b48b7d7fa05f3c3f422a77b00f6c8e647d7f7a3d126444081eb4548d9076cb2e464fedaac18330447b58203059b", "4a", "-143bcd4947a5f6b710ce5557eeab51cf907dcfec71175994f597f4297cdf879653f84273ccb0686ef2d22542e008779180b4ebeac0df268a07f2c56d258d554737391a76ab14d4d66c06f23c9881d27678619e94a6e86d712fd71ee763192f4f25b8b6de8a1bf139f7f3a950c46ea52c5b50c2f643d1befd382ce3e6daf8a1e1b09deb726464992e7f01627683399f321a6179a447507be7769b434b1e2a7a6b21fdbecc1209c52928df258bb150a18095255d0545e0b42139324134fa4f6e1c08e43e69eb158803e4b3263930b082bfb5b66dede33124af2fa18534dd775c5315df82e89b9a55a3bd99354e63e481f06be774d77da7f63af5669ddc4b433a3032e9b50ed0309fa91c29c8bf93ef385c8efee98d1abbf33f4668e56f291ace5d4f60085ce26ac404d3212ae2b862ec1669b6804348248d78d9a2d68e18005ecefce6942da8e5f4ab3c13353165b2cbba6be17eb7e4b5588c88487a6c539a72f2510bf407fd6483d398d24d4497a20a6cf07930d08050283cc694deaf3b2a07a9de133129592dcb83dc14751126e867c07f2d3b0258f27c4509b04f5c4e8b3e17717070ee930f921189a2e947e5829a1e95faf6dcbf72afa540b176222a6f734b5fd63d37ddf8f2d73fbba86eb0edac280d6466d22df5fe817cf0fd08a9dec03db23991f5fde8f4499110207ad1523641db2cb9193fb6ab060cc111ed6080c166c000000000000000000", .None}, + {.Shl, "-ba7fdd4d0fde7da6d467934ae22540e1e598e4608ab04a75254728c49188dfe30c7ac9277b3233e790ff874a8a5bef6906d6f6b5554cc2d92c2074fed10c99a35a5c4a5ae35f2cb49ab47f203a593d68513a3cad7841f0a85ac2ef00f13ce3ad051c109ba6438d49ee502adb99fef00623111d61a8a32e920304ae0cf98aa9a9768268d25216cecb4f761647358ada598a69ae734810f9f4d2b61cd0f9bc8ce4c4656bd1f5825ae57d9106ef57d41e3e5cc8d5b62cebb80e5cb97f8871a2f7ff236d8fe5f4d78f532dfa361c4f5cb544344c83f3f436636fde6fa4c63aaf1f879820b42fbdf3da94b0a42088c6396d67c5dd89a63dc10860ed2c283e2e484fc967906f145e9ade0c7b133532db8ad3978ff99beb89f5aee48454f83e3a06f68695c3bf3ec23d8287ced323bfe5184e8dec30b6d4f5c6f066daefbd746fd057cf73ae2f01f2a81e46a0554bf31b2ba42ecf6883d19a86c33bf96b6cfa27331a7aeb0bdc70bbab7de712e8ab0b16b3e857afeeb5b7280d72557702807ec2d3f29c71b4b1aac9d49b380d76de6bacebc2a2fb0f0dbdbf7de4d93bd56aac704c466818f9702cfb0ab20770dd9656682591a11a918d39310b53cf7114e980eca2e5287871933ba9da9ef71c63c59783de100b088b60861223cffd2791501c5d632d031dbdfb0a006e998b460665a2240622bf5a87423514585d5c073d6cff0bd81c3e", "3a", "-2e9ff75343f79f69b519e4d2b88950387966391822ac129d4951ca31246237f8c31eb249decc8cf9e43fe1d2a296fbda41b5bdad555330b64b081d3fb4432668d6971296b8d7cb2d26ad1fc80e964f5a144e8f2b5e107c2a16b0bbc03c4f38eb41470426e990e3527b940ab6e67fbc0188c447586a28cba480c12b833e62aa6a5da09a349485b3b2d3dd8591cd62b696629a6b9cd2043e7d34ad87343e6f233931195af47d6096b95f6441bbd5f5078f9732356d8b3aee03972e5fe21c68bdffc8db63f97d35e3d4cb7e8d8713d72d510d1320fcfd0d98dbf79be9318eabc7e1e6082d0bef7cf6a52c290822318e5b59f17762698f7042183b4b0a0f8b9213f259e41bc517a6b7831ec4cd4cb6e2b4e5e3fe66fae27d6bb921153e0f8e81bda1a570efcfb08f60a1f3b4c8eff94613a37b0c2db53d71bc19b6bbef5d1bf415f3dceb8bc07caa0791a81552fcc6cae90bb3da20f466a1b0cefe5adb3e89ccc69ebac2f71c2eeadf79c4ba2ac2c5acfa15ebfbad6dca035c955dc0a01fb0b4fca71c6d2c6ab27526ce035db79aeb3af0a8bec3c36f6fdf79364ef55aab1c13119a063e5c0b3ec2ac81dc3765959a09646846a4634e4c42d4f3dc453a603b28b94a1e1c64ceea76a7bdc718f165e0f78402c222d8218488f3ff49e454071758cb40c76f7ec2801ba662d1819968890188afd6a1d08d4516175701cf5b3fc2f6070f800000000000000", .None}, + {.Shl, "1999ccf991a8e29fe2692c6d3b96c540ba6a4c1a7a32525f70ece4a164ec489fb2d657e49820acb657112fd3f49006ac1469a907ddc9b3fcf856c9be517c3a50d069c8e08360d93343d5db8984a54d0bafc48b7be46ca76a42ce1f08d0db1cca43fcbea5fa5d0daf1f0aec9d03ae5289919fcd2f5e38ab77c2bb0852f6896297269844ade4d5e14ec63254da3aea2411bf704c6765ebc454f2bf63925983be04aed56b7d064a6e73657c3c77e8a8a0b4fffe7124f9df6cd467780351cbb0eb6624850ebc83a549ef4cdb2cd04ee4eec81a749d9998400ebbc2dc77105df87ea1256be3e5f151289b4b278d1236e0cf75edc070268f2f79d07ef2eb7be0a5a1756e3c1547750e57ecea852847a83a77d402ebfe6f26c67b4ac581afe3694f2d4b43535abf0b2e7f2b897a0503994e331eab554cfec197039e460841614f9d120baad7d693b66659b6bb8ef50178f9791b7d7ff91a2b0571a897e035291060fc903ae3571eca406b7559229048b142a9b9a847825a8d276a5d04956b441f1a963dae46b44fda5d8845288774d4636f9ad563a30ca460a7863f392b70296665ed15c80405a4a76837ee794896c480a4e9faa381cc8c4bf7219096d68f18238ecc9234fe560c9134867088c285157d6e32a47fe7982e4552381e3dee8dded6e3b6813b85fa75af2aa7992c45e0993f77aa99b399f9475bfbdb5cda61c905bebab77b", "1f", "ccce67cc8d4714ff13496369dcb62a05d35260d3d19292fb8767250b276244fd96b2bf24c10565b2b8897e9fa4803560a34d483eee4d9fe7c2b64df28be1d286834e47041b06c99a1eaedc4c252a685d7e245bdf23653b521670f84686d8e6521fe5f52fd2e86d78f85764e81d72944c8cfe697af1c55bbe15d84297b44b14b934c2256f26af0a763192a6d1d751208dfb82633b2f5e22a795fb1c92cc1df02576ab5be83253739b2be1e3bf454505a7fff38927cefb66a33bc01a8e5d875b31242875e41d2a4f7a66d9668277277640d3a4ecccc20075de16e3b882efc3f5092b5f1f2f8a8944da593c6891b7067baf6e038134797bce83f7975bdf052d0bab71e0aa3ba872bf675429423d41d3bea0175ff3793633da562c0d7f1b4a796a5a1a9ad5f85973f95c4bd0281cca7198f55aaa67f60cb81cf230420b0a7ce8905d56beb49db332cdb5dc77a80bc7cbc8dbebffc8d1582b8d44bf01a9488307e481d71ab8f652035baac91482458a154dcd423c12d4693b52e824ab5a20f8d4b1ed7235a27ed2ec4229443ba6a31b7cd6ab1d186523053c31f9c95b814b332f68ae40202d253b41bf73ca44b62405274fd51c0e64625fb90c84b6b478c11c766491a7f2b06489a43384461428abeb719523ff3cc1722a91c0f1ef746ef6b71db409dc2fd3ad79553cc9622f04c9fbbd54cd9ccfca3adfdedae6d30e482df5d5bbd80000000", .None}, + {.Shl, "-dade04969f7a3af399fa0e94cbd3a52af0b47f4fe3e61ae620c7b7bf9789b01f9c3c90e94d327f7fe4fd119561f94badb7a898c03c2b760b1922e821d7bb0150b86ca3c2ef6c488cb0558db9581f6878db9eee7770d54a44eb68ee6d8246094424d4fec67a39b47d9f104304a3b4f6fc14a62cde84af3d0aad455d49ce4c03b113710a419bfa7cee4ddce355601e9dea0120b1c153e35483dd78b2748f73c94d5503946f75f7a46c0f9e35e278b94ffb4332a65408c30859b6712bae071711edd6331756f3fb3e43c4bf13a4d0c3c6c103d4ea72d5c7049e1d3ca1390ecc553d25d9f7061da82e683eb00d9e0c0a3540d6c80cbe5c819f6e789b51e0fc64bfef893c1eae4f0a7f22ef76b440df7aa5849af3e803ee5a27671ec3717b5daa80632b341c0ccce5ebe4c1e7cbf1c64651c2cdf021eafa0ea95d12b5bc9d835ef8e6cfa798043d1a896ba71eabf5946d50253082cf0da1e2d0079969b9f064796d9a380e0b2f74b21beae8247a6e0df68c63e0df8839916a36c4cb05a42c0fb07341eeea993103cfcd5ce919c4c14adee174ce765a0a4633a88dffca75f7747d8afeef4d2a0fc84dab64aaf8293b967a0b808fdf99e83a5212e36b6f543ffedbd5f90894b347d3e10c2ab64579cf034bf358760823a84b194dab93af9b8e8cbcbdf4bf477c19f0a75a55cd6e51024f3cc434d6e5f23b4feb624da3695c81da886fa4", "6", "-36b78125a7de8ebce67e83a532f4e94abc2d1fd3f8f986b98831edefe5e26c07e70f243a534c9fdff93f4465587e52eb6dea26300f0add82c648ba0875eec0542e1b28f0bbdb12232c15636e5607da1e36e7bb9ddc3552913ada3b9b6091825109353fb19e8e6d1f67c410c128ed3dbf05298b37a12bcf42ab515752739300ec44dc429066fe9f3b937738d55807a77a80482c7054f8d520f75e2c9d23dcf2535540e51bdd7de91b03e78d789e2e53fed0cca9950230c2166d9c4aeb81c5c47b758cc5d5bcfecf90f12fc4e93430f1b040f53a9cb571c127874f284e43b3154f49767dc1876a0b9a0fac036783028d5035b2032f972067db9e26d4783f192ffbe24f07ab93c29fc8bbddad1037dea96126bcfa00fb9689d9c7b0dc5ed76aa018cacd070333397af93079f2fc71919470b37c087abe83aa5744ad6f2760d7be39b3e9e6010f46a25ae9c7aafd651b54094c20b3c36878b401e65a6e7c191e5b668e0382cbdd2c86faba091e9b837da318f837e20e645a8db132c1690b03ec1cd07bbaa64c40f3f3573a46713052b7b85d339d9682918cea237ff29d7ddd1f62bfbbd34a83f2136ad92abe0a4ee59e82e023f7e67a0e9484b8dadbd50fffb6f57e42252cd1f4f8430aad915e73c0d2fcd61d8208ea12c6536ae4ebe6e3a32f2f7d2fd1df067c29d695735b944093cf310d35b97c8ed3fad89368da572076a21be900", .None}, + {.Shl, "9047764293d698f0b33dc9ca107024c099b9fb776e542da23a72ff72bcbd39ad6e2c6aa89f28368b66aa91b510dd68d8fd007d1ad177b84f3c5d7ebb429c9eafcc4da8cc30e8259f1884cb17a8d71067ebaf7822d32788d1a23e497a9ec698ae4df63a72df08bb1e5a365dddd1d914333d659b3859f0821c2730a05adf1f73eba2534614fcca8ac004d25115345e270da3d78d9035a40cb1615c8185a10c9e30612e7819072789cf57df45e3bc99d72dd7ed301493433be0605c7d63b801a689330b02b62b2eb949b4c84cf1bdefa0b52183611d4aaf13afe1758d94b3fa07f1fa254f3f42557fd27523dea309dc01f3b3026d63eb5e41e11a6a725ca44ec14a23c456089692d00482029f7f3dea22581cde4513f994cac615504cf9b31e0a13ce93b4050d165a1ecf60f6e7788d5847c7dc4bedb576fba1270e70ab2263b99f61ae022e815aac051982aa8fd3caa36c259453c97a6166ba75fcc5e396d1ffddf202359423b4183157ebb272cd0e9f6c7bdd0dd15876aea78871b712b32766fae73f8d9257c0ffe0a1a1011b94b30c907ae68bd3c38a292e0840846a03357b7bc953130620e8033049153cbc29cc70f28f193332e171aa7690099553d404a43d225573629efe142034d00c06e224424ab4331f8dd086389d32d6de6fa9cf8aca439a3aec1ea2ffce7fb8e8faebc060206570f27460b6d5717fa5cef55d7c7cb4", "29", "1208eec8527ad31e1667b939420e049813373f6eedca85b4474e5fee5797a735adc58d5513e506d16cd55236a21bad1b1fa00fa35a2ef709e78bafd7685393d5f989b519861d04b3e3109962f51ae20cfd75ef045a64f11a3447c92f53d8d315c9bec74e5be11763cb46cbbbba3b228667acb3670b3e104384e6140b5be3ee7d744a68c29f995158009a4a22a68bc4e1b47af1b206b481962c2b9030b42193c60c25cf0320e4f139eafbe8bc77933ae5bafda6029268677c0c0b8fac770034d126616056c565d7293699099e37bdf416a4306c23a955e275fc2eb1b2967f40fe3f44a9e7e84aaffa4ea47bd4613b803e76604dac7d6bc83c234d4e4b9489d82944788ac112d25a00904053efe7bd444b039bc8a27f329958c2aa099f3663c14279d27680a1a2cb43d9ec1edcef11ab08f8fb897db6aedf7424e1ce15644c7733ec35c045d02b5580a3305551fa79546d84b28a792f4c2cd74ebf98bc72da3ffbbe4046b2847683062afd764e59a1d3ed8f7ba1ba2b0ed5d4f10e36e25664ecdf5ce7f1b24af81ffc14342023729661920f5cd17a78714525c108108d4066af6f792a6260c41d00660922a79785398e1e51e326665c2e354ed20132aa7a809487a44aae6c53dfc284069a0180dc448849568663f1ba10c713a65adbcdf539f1594873475d83d45ff9cff71d1f5d780c040cae1e4e8c16daae2ff4b9deabaf8f9680000000000", .None}, + {.Shl, "f6ceb8132cd090c2d398a718202719b7f759b9b369bfeea8e8623f8422b10eaac08f11845e231efa51ad11d86d8e4e8b33e3ef2caac9fadcff6f094a283a7ae66c7067f96d5050933c277d24c4800a7842a6fae40bfc02c3e22945764fbdbdf9c9fc3867d385c960bac7087a0c4724ce46a671cce7e9f7d0006c44e31291c919d8c9482f7733a7f2a9a6fe5a89ed9ee5f2a44819b2adc8c54d8d6d5b913c69e8d6a5bbdf291366c036dab035301808466d69270720b896e5ab5fae504601dd69b132ef4893e88281dd81132b421892c4f4db4e192513e43769b62a7cbced9419b6b730ca7b08d9e36820c6fa9bf7709134bc85ce2e83b36f1898d52dd24870f0df83ac7fd8dd918f1bc9c95b7911ec815e5e3ba4c2221a39f3fbda556a74527cb279b94681ae430774968f51dd59ed96f02c73c56596924af5cc9cc09ea55d2175ba7046d99097e99bfcafd1eaf6822c38aacb0d626b9cf3e7ce0e9fa7aa12105b17c68420ea11ec9a19e04d65edfb1576d0fb4f0268973f510c87dfc57309bb580bca501814d5c53dd70fa2eebbe5c71644e7a042c3b753cce97b03eade7f894d2306cee7ddd678ef53eb905378f6589ef357d47a42f2743234bc42b01251b71ea94acc11201f7b507a01c5f96187d45fb4b406e11c160326767dc8bbc1acbbd913d00a4a9c698a86fb99037ae70b84f3665a0e16bfcc84cba461515674b545", "60", "f6ceb8132cd090c2d398a718202719b7f759b9b369bfeea8e8623f8422b10eaac08f11845e231efa51ad11d86d8e4e8b33e3ef2caac9fadcff6f094a283a7ae66c7067f96d5050933c277d24c4800a7842a6fae40bfc02c3e22945764fbdbdf9c9fc3867d385c960bac7087a0c4724ce46a671cce7e9f7d0006c44e31291c919d8c9482f7733a7f2a9a6fe5a89ed9ee5f2a44819b2adc8c54d8d6d5b913c69e8d6a5bbdf291366c036dab035301808466d69270720b896e5ab5fae504601dd69b132ef4893e88281dd81132b421892c4f4db4e192513e43769b62a7cbced9419b6b730ca7b08d9e36820c6fa9bf7709134bc85ce2e83b36f1898d52dd24870f0df83ac7fd8dd918f1bc9c95b7911ec815e5e3ba4c2221a39f3fbda556a74527cb279b94681ae430774968f51dd59ed96f02c73c56596924af5cc9cc09ea55d2175ba7046d99097e99bfcafd1eaf6822c38aacb0d626b9cf3e7ce0e9fa7aa12105b17c68420ea11ec9a19e04d65edfb1576d0fb4f0268973f510c87dfc57309bb580bca501814d5c53dd70fa2eebbe5c71644e7a042c3b753cce97b03eade7f894d2306cee7ddd678ef53eb905378f6589ef357d47a42f2743234bc42b01251b71ea94acc11201f7b507a01c5f96187d45fb4b406e11c160326767dc8bbc1acbbd913d00a4a9c698a86fb99037ae70b84f3665a0e16bfcc84cba461515674b545000000000000000000000000", .None}, + {.Shl, "-4c25fe08d1d1b57e3540ab73377aa3f126428f1bc55482411ad83bee26353b3668fe271aa50c0b3a87b35fa48a69772771267dad37ee18b6cec0c0ceb50ddee6f63c17476c263ca0808a411db94a12cfd697c6646a6e574bbd653878d11afaf22e495c300a75c2a1b1ca6f5ad1a3dfaa1aae709cbd2b33e9b4a887aeb924cdb72f600d650edf1475a35f07bf9013370e6f384695e50b304ea30156c8371077c634a7439de20c776a6aaf849ac443da5f201b249d27267fb47593d28ec0d86b6bf54106a7c89d3133deb25cb609ddbb5de59dad748dbf38f1eb340439fdec087434cea189646a99f3d0fcd9e144627deefa479b0143392344da2c2d429dd67a48da17ef470d415350d09f9c9e111a5d43aca2bac0e1d71a11988e7da8bb301ab226540f3b0949b0b20c81a9bd0736d88ed2c6594e015b0a6f8732a5ec877ea6cb73cce9249ba0dc6d7ca2b38531551a9c775c4a1b0862f04a356658afc481ccdec389d7aea17947edc3efec30cdc2568da3ab71461da6b096cb26471fcda9fbf888736a84ca9806525bab9034fcc02fc539ba837775ee9561bc5b7d3776521449e8e24f0ac2ce606bbbff8283bbedde3fd1aa1ce31b8eabb5840d571d579076c189719344c45da3c44470eb369ce6aaaa242c36c8bb7a5c44538850a768bab04b17f3a59d8c25f1dcd4616939ae6d1926051f1e234a156947a276524250324b74", "1c", "-4c25fe08d1d1b57e3540ab73377aa3f126428f1bc55482411ad83bee26353b3668fe271aa50c0b3a87b35fa48a69772771267dad37ee18b6cec0c0ceb50ddee6f63c17476c263ca0808a411db94a12cfd697c6646a6e574bbd653878d11afaf22e495c300a75c2a1b1ca6f5ad1a3dfaa1aae709cbd2b33e9b4a887aeb924cdb72f600d650edf1475a35f07bf9013370e6f384695e50b304ea30156c8371077c634a7439de20c776a6aaf849ac443da5f201b249d27267fb47593d28ec0d86b6bf54106a7c89d3133deb25cb609ddbb5de59dad748dbf38f1eb340439fdec087434cea189646a99f3d0fcd9e144627deefa479b0143392344da2c2d429dd67a48da17ef470d415350d09f9c9e111a5d43aca2bac0e1d71a11988e7da8bb301ab226540f3b0949b0b20c81a9bd0736d88ed2c6594e015b0a6f8732a5ec877ea6cb73cce9249ba0dc6d7ca2b38531551a9c775c4a1b0862f04a356658afc481ccdec389d7aea17947edc3efec30cdc2568da3ab71461da6b096cb26471fcda9fbf888736a84ca9806525bab9034fcc02fc539ba837775ee9561bc5b7d3776521449e8e24f0ac2ce606bbbff8283bbedde3fd1aa1ce31b8eabb5840d571d579076c189719344c45da3c44470eb369ce6aaaa242c36c8bb7a5c44538850a768bab04b17f3a59d8c25f1dcd4616939ae6d1926051f1e234a156947a276524250324b740000000", .None}, + {.Shl, "da4b74ccc13222a793cc51730220f7bb7d5894f551a92b32be8bb5947de60a16819e6b92d9f1946b836f54c3ddaf9cc65ea124f245243ebdad8f8cd6e3c2c63a7e275f901e01ea4b598348ab34a7d3ad7069177da250c8a5e4801e18b4ea2606c58e6fd689451a2d52913cadb12fc4f363a5df978c9647715c5ac80b2f277e5ada88f493a41e3de42d76f94d203b4ef81338b8a1c4cea0d974a27f1aeb36d7184edb4b385c977d98569af6cac797659567670ba21afc8f0ccf4f9ee4ea8ed6f5d9ce2e21b69e8e4cbb66ccb35a84f875bf28092542bb2ad388157373a864a43c0e98e3e6bd43620324b6249c623fb0e4516079f36bca266d99842d8a729c91329f8a3a7ddcf86934828bf86143462723a13c2a1f3a610b6e1694a2a098a7b7d8cb3b1e6cf0ef3e755c41e3684113d881dda8f3b6158e6fd2f780e6fb6509efa5785620d0070a9c5e5a96f6fbfaf7deefa500e6b14a37d3867c1776b4d243cf7c3624d5766189a0bb7f96c565bd43aef92f0d720285dcad51d758cba2ab13259558930be0b2768d5bd04959ce91e40f6443b441806c57d258b948b3a56f5e30d253ff4b8bcc5328a19e5c1d355bbbbd40d5c59cebdd299dfaece869e1548678e78946587197ca1423930becaa5137e62f3823053fe235de1b87650c663eb2bcbb7c54072e15a305be0ba9081275d86019755cf0086600dcb59917f8321824621c", "0", "da4b74ccc13222a793cc51730220f7bb7d5894f551a92b32be8bb5947de60a16819e6b92d9f1946b836f54c3ddaf9cc65ea124f245243ebdad8f8cd6e3c2c63a7e275f901e01ea4b598348ab34a7d3ad7069177da250c8a5e4801e18b4ea2606c58e6fd689451a2d52913cadb12fc4f363a5df978c9647715c5ac80b2f277e5ada88f493a41e3de42d76f94d203b4ef81338b8a1c4cea0d974a27f1aeb36d7184edb4b385c977d98569af6cac797659567670ba21afc8f0ccf4f9ee4ea8ed6f5d9ce2e21b69e8e4cbb66ccb35a84f875bf28092542bb2ad388157373a864a43c0e98e3e6bd43620324b6249c623fb0e4516079f36bca266d99842d8a729c91329f8a3a7ddcf86934828bf86143462723a13c2a1f3a610b6e1694a2a098a7b7d8cb3b1e6cf0ef3e755c41e3684113d881dda8f3b6158e6fd2f780e6fb6509efa5785620d0070a9c5e5a96f6fbfaf7deefa500e6b14a37d3867c1776b4d243cf7c3624d5766189a0bb7f96c565bd43aef92f0d720285dcad51d758cba2ab13259558930be0b2768d5bd04959ce91e40f6443b441806c57d258b948b3a56f5e30d253ff4b8bcc5328a19e5c1d355bbbbd40d5c59cebdd299dfaece869e1548678e78946587197ca1423930becaa5137e62f3823053fe235de1b87650c663eb2bcbb7c54072e15a305be0ba9081275d86019755cf0086600dcb59917f8321824621c", .None}, + {.Shl, "-f4a609d2545509591a3b5cc5efd4fb1fe667a7c818ae6756ecb407894dfa8304ca06f0711d1ceecd5c176035873bcf0e7d0b77b7e329fd1162449baf45723db2b3c15a1a2100952932fe94962f77a78dd1f736e8f16d012e530c17ed84881cf0c8a45445dbb371e6f21d38302a5c32b4eb10b5f7c513695db08139af90e9faa70af4fc77e8f1a6a820092872c4bb477069004dc31a2327f183ded3b00ec0afac93316a07630a1cdc7c2c6a04aa2e2403027a3bfcbe762f966112ba97231ba39d3375e3c8d153b07bcb14d4b364549991e89885c8213b9b5bbab0bec232ec63b168a044a84e91ee25697ed2f4f341a087ebb145fcd56261e6694584dcfff291a3ef7e38a264a621509d68bf61e6780d105d637b3ce3f3626cd9b4e33aad681d9946ab661876c14b4268648cee9dc44b21c19202be3f04a6671b4e39e41050bbc57d33c233567d7145b89ad6764d5e12d0d447daafc5cce7290d73e1e21dd00b794575768b35fdedff8f833bee666f4aea58870c6d3a4b6adfdb645f7544b5988ec2f71d2a5a57133e1f22754ca563cf3f968b5f13430607f351f737a430fcea949111eca00ea37625f4f23fbf3387a673c3a248b47a368c6201be9068b5173b5bd000533f6f289cf336e279bac5649b099e3e5cfaaca8924c2fce8c91f2999c43c1d2a55d9a583ffed8c2096d9e8e889fe2b9285447d11e53ccb2d3f9e8c7276e", "67", "-7a5304e92a2a84ac8d1dae62f7ea7d8ff333d3e40c5733ab765a03c4a6fd4182650378388e8e7766ae0bb01ac39de7873e85bbdbf194fe88b1224dd7a2b91ed959e0ad0d10804a94997f4a4b17bbd3c6e8fb9b7478b6809729860bf6c2440e7864522a22edd9b8f3790e9c18152e195a75885afbe289b4aed8409cd7c874fd53857a7e3bf478d35410049439625da3b8348026e18d1193f8c1ef69d8076057d64998b503b1850e6e3e16350255171201813d1dfe5f3b17cb30895d4b918dd1ce99baf1e468a9d83de58a6a59b22a4cc8f44c42e4109dcdaddd585f61197631d8b45022542748f712b4bf697a79a0d043f5d8a2fe6ab130f334a2c26e7ff948d1f7bf1c51325310a84eb45fb0f33c06882eb1bd9e71f9b1366cda719d56b40ecca355b30c3b60a5a1343246774ee22590e0c9015f1f8253338da71cf208285de2be99e119ab3eb8a2dc4d6b3b26af09686a23ed57e2e6739486b9f0f10ee805bca2babb459afef6ffc7c19df73337a5752c4386369d25b56fedb22fbaa25acc47617b8e952d2b899f0f913aa652b1e79fcb45af89a18303f9a8fb9bd2187e754a4888f6500751bb12fa791fdf99c3d339e1d1245a3d1b463100df48345a8b9dade800299fb7944e799b713cdd62b24d84cf1f2e7d5654492617e74648f94cce21e0e952aecd2c1fff6c6104b6cf47444ff15c942a23e88f29e65969fcf46393b700000000000000000000000000", .None}, + {.Shl, "-26ba3eefde45fb86a09484bb9d06254ce862f9518781946c52a91e702358c7f9901fc68d2e8ec464cecc98b701bebe97b90fb393f872be1ac23fd2ef53fa66d9cbbdfedd80d5c87ba4442f64cb50e8cef6065c84cb1ccc552c90f02cda416d409bb295361c44a47102af0c1646a76f399543a52bb69ccabe8abe16a318c44d3855657e5a58ffeb8f24dcf9c4ac6204e7d3cf09af1b3d63ce3cb0588a707eb1cad3ef83e7deda620b325a1c905103e3d83dca701c72a895225708dfc215bd4b9c1002b903153009b7f46ef7edc68c8f5529cfd1a8f87d0d725fd25eae79798a43f54f37907d926530bf276fe13f8f9d64e8cf89dcd0c66504cc535aab27fe8637441d1e75d61dbb8cb9200e7e28bee4531c171db348747d89f691f1d5d3dcb0d7395e3831f2de4ba614744e258a37db11c4e886415e148ac3c5e3216ebac54ff30ba2a8c1d2fc1ada54d79ac8c93dc506921d04d1a94f1e206cd03cff0da23890384de4a66758e949863a9894329ce549f4ccdac231f71b9a27fa57028d8ce0ca678937d678d2f81fe176eb2c05813ee64d5a8f283aa87a863acae3f0668a62e88596d0a064160e1146474ad1acac302c022e51df0ded7b2db369c3d15e0127147510379b98eed6f446a1c798fba113e808d0024563552590478690d10526ba4009850130a313c2082cc8118bee7cab695a60577e89da38f9d1033187f340098d", "21", "-4d747ddfbc8bf70d412909773a0c4a99d0c5f2a30f0328d8a5523ce046b18ff3203f8d1a5d1d88c99d99316e037d7d2f721f6727f0e57c35847fa5dea7f4cdb3977bfdbb01ab90f748885ec996a1d19dec0cb909963998aa5921e059b482da8137652a6c388948e2055e182c8d4ede732a874a576d39957d157c2d4631889a70aacafcb4b1ffd71e49b9f38958c409cfa79e135e367ac79c7960b114e0fd6395a7df07cfbdb4c41664b43920a207c7b07b94e038e5512a44ae11bf842b7a9738200572062a60136fe8ddefdb8d191eaa539fa351f0fa1ae4bfa4bd5cf2f31487ea9e6f20fb24ca617e4edfc27f1f3ac9d19f13b9a18cca0998a6b5564ffd0c6e883a3cebac3b771972401cfc517dc8a6382e3b6690e8fb13ed23e3aba7b961ae72bc7063e5bc974c28e89c4b146fb62389d10c82bc2915878bc642dd758a9fe617455183a5f835b4a9af3591927b8a0d243a09a3529e3c40d9a079fe1b447120709bc94cceb1d2930c7531286539ca93e999b58463ee37344ff4ae051b19c194cf126facf1a5f03fc2edd6580b027dcc9ab51e507550f50c7595c7e0cd14c5d10b2da140c82c1c228c8e95a359586058045ca3be1bdaf65b66d387a2bc024e28ea206f3731ddade88d438f31f74227d011a0048ac6aa4b208f0d21a20a4d7480130a02614627841059902317dcf956d2b4c0aefd13b471f3a206630fe680131a00000000", .None}, + {.Shl, "-7f313f06a209b17060aea372ab2699acf666882d918821d1ed00c7ce12b8772c4919c9c998ff5969ba7ca0d99da928ba5ee2583b0d9863f1caf9271f59073a3e7722d1438b2eed712bb4d92b9eda34dda9a8ebe518b7e0e8f5eae942c4ae88c15fee1247bfc209c9803477024d2a92bd841e1aed564540224a8f50117d291439ab87c6149490938015c48d239dc462fbc0f50eac06dbd54f66d0fb920798afc64d4e288bdb14f241fe103ff37de173932f9ea96d36fbeb79a678ca3c586b916f7d29de9160e2a06e05b663d7abee408f0f7fb017c96c3f1b5b013e10585a21413133be0ae696f6e3ca715b9f9b1018c96f82312ebf94368e27e14238a8f3828b59141f47b0cc8496ac110a51082d19528cfca73a172b8506fbc260679b31dfc68e366148f2ccf6baf7b079c778bd126cc28f5f394bdb133730035a06594d965265cd5ba6d5e01e5420ae5a6a2758624cb9265867ff66b727a138d879fb9ed1599a6314a6f32f93221f9c21067d234f6328a856ad65554d71f76154b2716f4a78b7096007b837bafa5289c5cd95bb0824c00d28dbf804a091a7c68cfd1a2097e9faf40017690402a5e3b0dee5ba064d0d7f580b4f81614bdc14c8a5a91928ff0f258078f344d66b259235c4bf4127fdb430852f17fdffa3a759ca9316ea6ae836ba9739542b3455636f3eafe45af38f1008021ad2bd37259b2768647dd119d44", "52", "-1fcc4fc1a8826c5c182ba8dcaac9a66b3d99a20b646208747b4031f384ae1dcb12467272663fd65a6e9f2836676a4a2e97b8960ec36618fc72be49c7d641ce8f9dc8b450e2cbbb5c4aed364ae7b68d376a6a3af9462df83a3d7aba50b12ba23057fb8491eff08272600d1dc0934aa4af610786bb5591500892a3d4045f4a450e6ae1f185252424e005712348e77118bef03d43ab01b6f553d9b43ee481e62bf193538a22f6c53c907f840ffcdf785ce4cbe7aa5b4dbefade699e328f161ae45bdf4a77a45838a81b816d98f5eafb9023c3dfec05f25b0fc6d6c04f84161688504c4cef82b9a5bdb8f29c56e7e6c406325be08c4bafe50da389f8508e2a3ce0a2d64507d1ec332125ab044294420b4654a33f29ce85cae141bef09819e6cc77f1a38d98523cb33daebdec1e71de2f449b30a3d7ce52f6c4cdcc00d68196536594997356e9b5780795082b969a89d618932e499619ffd9adc9e84e361e7ee7b4566698c529bccbe4c887e708419f48d3d8ca2a15ab5955535c7dd8552c9c5bd29e2dc25801ee0deebe94a27173656ec20930034a36fe01282469f1a33f468825fa7ebd0005da4100a978ec37b96e8193435fd602d3e05852f70532296a464a3fc3c9601e3cd1359ac9648d712fd049ff6d0c214bc5ff7fe8e9d672a4c5ba9aba0daea5ce550acd1558dbcfabf916bce3c4020086b4af4dc966c9da191f7446751000000000000000000000", .None}, + {.Shl, "db486cd755c998359af7e9955fd7b60cd726be733eac9dd4b37e09177488a2418bb70a7b087162a5382483fb25a4373756f7d0e45f8fb6edf972450e1612d21ab19a4c47f4a16456e17d099cf1adfe5709b0b423700accc7af76a928dfeec12625a760b28731bb2ca882945f9dd89dfe5b18e629cdbaa4b5cb41abe0bfd3b25c91fb3c0eecbbdf64f47e8d48b80af0bbb3214d3e378250720b9b9ab6f1a9791d3eeabda63699fea9404617fb66fa731ca025cc20944c1ab6766afdd74a252e93e0a94c03c0bb3db94d5d0e5ee8b103b5b83147f1c5c4a68fb68343efbb06bfd123b27f071dbc3f8468d4a7bac89f4c6e583ff786517e9377a052739137f1d2c9fb8e77b5854ccd8e57b934b222e0ad32a563cfce527c888dd27f5e995b14f970c5e478845d24be43ce6b75474fb508d617b22aa718897bde733bc29b856c65bde446a81560974bec2f89429f05e74aaf71074040916863181fb9a2618e54eb0068de94fe45e794db0ae7caf574f196c7d2bac60135510338f7d430d226257161017173bd6181a5772e4377a1071241b66d9de9f2ab380dd0df03754660ba9f2cdc244d1e75341e780dc44478b2a12adc74a2f7b8a54c3c7638252f03aca808bd8ad4427677e0808bcaaefbb268cb7c8075751ca7a68edd10aab23eea40b521f829bbca6ffa3806f8c71dfeeea8c1b8c82ac27411aaa99036d776424bfe6e22da", "2e", "36d21b35d572660d66bdfa6557f5ed8335c9af9ccfab27752cdf8245dd22289062edc29ec21c58a94e0920fec9690dcdd5bdf43917e3edbb7e5c91438584b486ac669311fd285915b85f42673c6b7f95c26c2d08dc02b331ebddaa4a37fbb0498969d82ca1cc6ecb2a20a517e776277f96c6398a736ea92d72d06af82ff4ec97247ecf03bb2ef7d93d1fa3522e02bc2eecc8534f8de0941c82e6e6adbc6a5e474fbaaf698da67faa501185fed9be9cc728097308251306ad9d9abf75d2894ba4f82a5300f02ecf6e53574397ba2c40ed6e0c51fc717129a3eda0d0fbeec1aff448ec9fc1c76f0fe11a3529eeb227d31b960ffde1945fa4dde8149ce44dfc74b27ee39ded6153336395ee4d2c88b82b4ca958f3f3949f2223749fd7a656c53e5c31791e2117492f90f39add51d3ed423585ec8aa9c6225ef79ccef0a6e15b196f7911aa055825d2fb0be250a7c179d2abdc41d010245a18c607ee689863953ac01a37a53f9179e536c2b9f2bd5d3c65b1f4aeb1804d5440ce3df50c3489895c58405c5cef5860695dcb90dde841c4906d9b677a7caace037437c0dd51982ea7cb370913479d4d079e0371111e2ca84ab71d28bdee29530f1d8e094bc0eb2a022f62b5109d9df82022f2abbeec9a32df201d5d4729e9a3b7442aac8fba902d487e0a6ef29bfe8e01be31c77fbbaa306e320ab09d046aaa640db5dd9092ff9b88b6800000000000", .None}, + {.Shl, "-c182a2dabce0ebba4cc31488cfb12c50c460a9796ba8b6dfd04ab8ff81c322270e241d7cd919e8ee8a1b76440e297def735cbdc1cc7227d9b9d3b5acce7fe6f4c68c13bfc647c8721e60a5b653116e33ae640e049dbd378006fbb45139b625d4f6f9e90c09428184574a0aac5ebf79c3379145ebf6d56e7016f460f36952f7d7460e7697abc309eb735ae48bcad3f5604368dbc50506d3bb7f9b445f89b384813f80addd0284f86e4459dee9d565308f4e57079bd7229884802f9e755423116a75b8386f126be83eabd4142b969f2576a500540247d8b434caff08278ae001577ad3a04f0d9541171bf7e0ce7c9deb4fc1e31fe1aa41d68d6cf55a36f81fe81b52cf6b4214433e67a5312c604d8a6a08268ed36b260c9579964999c2f85ec980726685840093e90a6efeb8432fa5ce8329fa79700b61d46b698443fd2d8e695441f84f482901c0e1f234185e12378f6e6f3ad5b40d35a86ad379779194c04c60cd137b008c41490d5d9f502d6b0de13c5c7dd79097507bcdf2d2ad5876dd9879d8f0c033c26c2ef68a98f7200750345309a1cef6f443870f5f3b3bd2f5fb9217d5c4fcfd65dcb5c57b41c5c996d9f310d3718923738610d68d238d81684a49e1d0f307e27932e1d589ab91c2f636504be5201935dd2499d8210d8a8495b62a2cef07b9c04be8ba4ae7f7e96093c452050c9f1d8fa85ca129fb02e9f767ad46e8", "34", "-c182a2dabce0ebba4cc31488cfb12c50c460a9796ba8b6dfd04ab8ff81c322270e241d7cd919e8ee8a1b76440e297def735cbdc1cc7227d9b9d3b5acce7fe6f4c68c13bfc647c8721e60a5b653116e33ae640e049dbd378006fbb45139b625d4f6f9e90c09428184574a0aac5ebf79c3379145ebf6d56e7016f460f36952f7d7460e7697abc309eb735ae48bcad3f5604368dbc50506d3bb7f9b445f89b384813f80addd0284f86e4459dee9d565308f4e57079bd7229884802f9e755423116a75b8386f126be83eabd4142b969f2576a500540247d8b434caff08278ae001577ad3a04f0d9541171bf7e0ce7c9deb4fc1e31fe1aa41d68d6cf55a36f81fe81b52cf6b4214433e67a5312c604d8a6a08268ed36b260c9579964999c2f85ec980726685840093e90a6efeb8432fa5ce8329fa79700b61d46b698443fd2d8e695441f84f482901c0e1f234185e12378f6e6f3ad5b40d35a86ad379779194c04c60cd137b008c41490d5d9f502d6b0de13c5c7dd79097507bcdf2d2ad5876dd9879d8f0c033c26c2ef68a98f7200750345309a1cef6f443870f5f3b3bd2f5fb9217d5c4fcfd65dcb5c57b41c5c996d9f310d3718923738610d68d238d81684a49e1d0f307e27932e1d589ab91c2f636504be5201935dd2499d8210d8a8495b62a2cef07b9c04be8ba4ae7f7e96093c452050c9f1d8fa85ca129fb02e9f767ad46e80000000000000", .None}, + {.Shl, "bc3a12c87a6014d6c9218cbc8d7f484d8775ef999c9b1d5e87ee49011fd23bfa3ffa985cff071dbc234a68dde82bbf8586be647027163e7927b6816560017b2464412926e3374b50e7e2ac9f3edfdad164e6d19cac73240e0f66c08cb6106c74195f33697dd4002a1955e06be11eec16a26c2bc5ba0aeecff00b3ef4f0458c2d0ffef9f5c3428ee6dd1ed197d9b82b0d00781357969b59a96732b57a637d99cf3de8afcdf7bf16ae0c1e4380724f718da37a03759fc376c7cdfe5b86eec79ffe0b06e2db335c1799afe41c63a37ec0cb86e09ae7c80d55c6cfdc2857070bf2e1db9bfc2bbc5098d725d60c3d6b22b52b02ad2caadc4b223a9f9749314b917bc1e8093a3385850796d30c20d6c1f1e0521f9f15008903e89480e9b36e8f1f2de0691c6e1ef6d419cfa71196620b10ffd9cb079796dffe38e9bc6a7835749898a9431e441ad3e9ee31f3f428b1d7d3beb3919173b1d92cbf2cac158ae097b1e6756197bd0e4355246ecbba6b3105739490abb4651e420676a5a82ad819616d6bc5381116de0bcc5c040e9a1fb2aabca37f7ab1138758d6264657f669ed632dc53f997632021d8ee6dc6a97ba6fd2b90aef5e7ac3feb544eb00601eabe7f2fb3f36e0c8457d866befe1600ac57acd338e1e5f63e7192b53db5f4f25578b8d53fc0963511e230f50515a1852bee0ba640c33870cd13d74e9b320f66ea42af56b51c9", "34", "bc3a12c87a6014d6c9218cbc8d7f484d8775ef999c9b1d5e87ee49011fd23bfa3ffa985cff071dbc234a68dde82bbf8586be647027163e7927b6816560017b2464412926e3374b50e7e2ac9f3edfdad164e6d19cac73240e0f66c08cb6106c74195f33697dd4002a1955e06be11eec16a26c2bc5ba0aeecff00b3ef4f0458c2d0ffef9f5c3428ee6dd1ed197d9b82b0d00781357969b59a96732b57a637d99cf3de8afcdf7bf16ae0c1e4380724f718da37a03759fc376c7cdfe5b86eec79ffe0b06e2db335c1799afe41c63a37ec0cb86e09ae7c80d55c6cfdc2857070bf2e1db9bfc2bbc5098d725d60c3d6b22b52b02ad2caadc4b223a9f9749314b917bc1e8093a3385850796d30c20d6c1f1e0521f9f15008903e89480e9b36e8f1f2de0691c6e1ef6d419cfa71196620b10ffd9cb079796dffe38e9bc6a7835749898a9431e441ad3e9ee31f3f428b1d7d3beb3919173b1d92cbf2cac158ae097b1e6756197bd0e4355246ecbba6b3105739490abb4651e420676a5a82ad819616d6bc5381116de0bcc5c040e9a1fb2aabca37f7ab1138758d6264657f669ed632dc53f997632021d8ee6dc6a97ba6fd2b90aef5e7ac3feb544eb00601eabe7f2fb3f36e0c8457d866befe1600ac57acd338e1e5f63e7192b53db5f4f25578b8d53fc0963511e230f50515a1852bee0ba640c33870cd13d74e9b320f66ea42af56b51c90000000000000", .None}, + {.Shl, "328d4d9cc1aa4895116d1639165a4b2ed361f2dccd983f72c47b82b45794c3fbe18a917bf1c9027a4ddc4be056099a3c852e4b5814c870fb347bb9c8fbad2582cc5ee363a1ed70927bdda5f2efecdcce17755b4dac5927a70c398e52dc45d3159b3c6019773c403b82a678303771e452c8a25b66579ac5dce4f2ad68c91bbd7a988894536cea9f0f97742f2ccc666f80f6bd8b08829fa936d46d6fe66967d496515004c6e11609f898746dd43a1f54dc21f3704554c042b99113db8dab25daf74b1f5ee5c655af30297714f1e900e430b1ea64011be39cd7552c487f25d1020e142778a9936d17344ee34df928501214537f4169639348e45a7c851abd62c51b8365252c868b49e294f9bda30239f89d221093a4baccfe30d6c078841aa2d2b864fe1dfac8e47e89f6bb982e103e69826f8dca89a6fa10332255c27645cb30113efc8430a1f1d32e327362d9749dd51b8ceeb94d15996d8ab046b131401c451339c5a360432ce3468b18b6dbff21de5895fbbfb3351876833c10bc93a69e1563dd9412f20fb7ecf249efd8ba6ed4de0e888e2d9a7e36e9880cdc2463416ab97ef13457bbe0d996f2368efe0fc13b37eede0bc9d213d17acc630006cfd5211fe367d9faaf7dc9a3bfc1e42546c41924b567975b246ff98f9641cb15313189c2b974c1ce1c888b3a5025de76339f361477b7bfa4b86eefd5934e94abb9464e3a4e", "23", "1946a6ce60d5244a88b68b1c8b2d259769b0f96e66cc1fb9623dc15a2bca61fdf0c548bdf8e4813d26ee25f02b04cd1e429725ac0a64387d9a3ddce47dd692c1662f71b1d0f6b8493deed2f977f66e670bbaada6d62c93d3861cc7296e22e98acd9e300cbb9e201dc1533c181bb8f22964512db32bcd62ee727956b4648ddebd4c444a29b6754f87cbba1796663337c07b5ec584414fd49b6a36b7f334b3ea4b28a80263708b04fc4c3a36ea1d0faa6e10f9b822aa60215cc889edc6d592ed7ba58faf72e32ad79814bb8a78f480721858f532008df1ce6baa96243f92e881070a13bc54c9b68b9a2771a6fc9428090a29bfa0b4b1c9a4722d3e428d5eb1628dc1b292964345a4f14a7cded1811cfc4e910849d25d667f186b603c420d51695c327f0efd64723f44fb5dcc17081f34c137c6e544d37d0819912ae13b22e598089f7e421850f8e9971939b16cba4eea8dc6775ca68accb6c558235898a00e22899ce2d1b0219671a3458c5b6dff90ef2c4afddfd99a8c3b419e085e49d34f0ab1eeca097907dbf67924f7ec5d376a6f07444716cd3f1b74c4066e1231a0b55cbf789a2bddf06ccb791b477f07e09d9bf76f05e4e909e8bd6631800367ea908ff1b3ecfd57bee4d1dfe0f212a3620c925ab3cbad9237fcc7cb20e58a9898c4e15cba60e70e44459d2812ef3b19cf9b0a3bdbdfd25c3777eac9a74a55dca3271d27000000000", .None}, + {.Shl, "a09b18347269492b1e76bcdc7102ffd0d87b31ea97fe2a7478e79a10b93836a5dfa9ede4880ffc7770dfe2df5ad13f989f6b2067ca6baa121b650cfd6c64a65dbfffefa7d443c1df0e694e5cfb6c58772baf6a00846c92e1cd9fe7e32c9306db985a8608d55c890eb74a6561c82f03f51ca66cf38fcbf57e4788d6eafa41ffe69b485090939981d9e74b7fb2aca69f7abdf7073c5e7edea04fec22662cb21ac690bd83c23a79fe95e8c7c632ec813f45b96fb5b29bd54255070f69ba22bc45b3a70bb359d8f3c833ee05e9a344f7b3c9474431486f3c89f3dd9ee3802591c668bf4291f6eded2f71963368ebf5fe129d8c84c54d641287b31088c68432bbfa87d8b3aada19d787b2ee5136eab8239d1bd88cc84661d792d65ca2394c1ae4540912af03347b57d439a3f3f3ec23b90baeb7ce76595e55810f6a890a2b95700c2a8a4c5bf8d6c40b42278759cd922c51ace99f267eef55a67b2aa46890271c990041b8de3a9c7c71766bab687c8410b2a8046487b117d9873fd63900e5711de6c60430ab39106a7d1910d0056eeae5f3ab4daba2b1432adf0d2c1109cf880cff13d0de1d8a28062f3459cd7c6d40f237f059a5d251c9a6d971451200c4a77b3ba51adc5dcd3e9ba16525ce27a8cade6136dca6c1d1e41f20206c14c29076fbac65937f7e192d4a50c9e14d8d0d707bf27165ae75d727bd31ee0cdcfe917caff80a", "71", "141363068e4d292563ced79b8e205ffa1b0f663d52ffc54e8f1cf342172706d4bbf53dbc9101ff8eee1bfc5beb5a27f313ed640cf94d7542436ca19fad8c94cbb7fffdf4fa88783be1cd29cb9f6d8b0ee575ed40108d925c39b3fcfc659260db730b50c11aab9121d6e94cac3905e07ea394cd9e71f97eafc8f11add5f483ffcd3690a121273303b3ce96ff65594d3ef57bee0e78bcfdbd409fd844cc5964358d217b078474f3fd2bd18f8c65d9027e8b72df6b6537aa84aa0e1ed37445788b674e1766b3b1e79067dc0bd34689ef67928e886290de7913e7bb3dc7004b238cd17e8523eddbda5ee32c66d1d7ebfc253b19098a9ac8250f6621118d086577f50fb16755b433af0f65dca26dd570473a37b119908cc3af25acb944729835c8a812255e0668f6afa87347e7e7d84772175d6f9cecb2bcab021ed51214572ae018551498b7f1ad8816844f0eb39b2458a359d33e4cfddeab4cf65548d1204e3932008371bc7538f8e2ecd756d0f90821655008c90f622fb30e7fac7201cae23bcd8c0861567220d4fa3221a00addd5cbe7569b5745628655be1a5822139f1019fe27a1bc3b14500c5e68b39af8da81e46fe0b34ba4a3934db2e28a2401894ef6774a35b8bb9a7d3742ca4b9c4f5195bcc26db94d83a3c83e4040d8298520edf758cb26fefc325a94a193c29b1a1ae0f7e4e2cb5cebae4f7a63dc19b9fd22f95ff0140000000000000000000000000000", .None}, + {.Shl, "34483afada156a555533f5f65ca40bf61b5afea66c5557e13197d9679fa1ad0fe86547c61f185731878198fdd5b1d6c62dd19f02e03e26a79038af98072fcc412f6a5938b06c00e800674fb1df089572c57f6e6eb8588d9ed982742d16011e9ce245dc7998b19f870b9f0a310e9071be090c2133bac6efe63d49bd57f390c66134cebc3bedf8ca15538729c95f5bf8cf12bce2278cd1de7e2197fccc1de516bcfd0109ad8cc98ba19b96fb9d3f60bfff8098efbf978f4d5142cda1dcd60387c2d0b50d5e990956886ad553b471f6797847eb771278ae5a81ae085d663d6734a57677cbaab241fa48d0fc801d302cb4128794a6637dd6eef86124cb65d5a3252d679925cbe1d5f8cfbc764e47648f9609cf76e55b30064bc437aa5f1669a9160e2f3e670fae3fa6c43e3aab509066e644c59b5c39ac56f283f7f489fef55a0e7cedcb3c2cae0fa3a11ae673d805ecdaa018eafbc5c46ee83c752cd12eabf5cb4278e46cba0deb2a3a89fe5ca1f3d4348540e09e9eea0473a58d7fe7871efd8d930b5fe8b54bce054da1d5d9ad8f6a968f0b229754b9684cb2047ed28d5e7d975c332ed33166ea8e363abfd59a270b891b71e0ad0dd29b3a18c1eb8a5f3d30b406d7230c18e249fd22497977e1e153ef322a2dce510057584fbe8d23079696496151c852095d9901e3db50f5bf08e6e0a72a818cb6b15d19a67a187c41a155b7ee", "4", "34483afada156a555533f5f65ca40bf61b5afea66c5557e13197d9679fa1ad0fe86547c61f185731878198fdd5b1d6c62dd19f02e03e26a79038af98072fcc412f6a5938b06c00e800674fb1df089572c57f6e6eb8588d9ed982742d16011e9ce245dc7998b19f870b9f0a310e9071be090c2133bac6efe63d49bd57f390c66134cebc3bedf8ca15538729c95f5bf8cf12bce2278cd1de7e2197fccc1de516bcfd0109ad8cc98ba19b96fb9d3f60bfff8098efbf978f4d5142cda1dcd60387c2d0b50d5e990956886ad553b471f6797847eb771278ae5a81ae085d663d6734a57677cbaab241fa48d0fc801d302cb4128794a6637dd6eef86124cb65d5a3252d679925cbe1d5f8cfbc764e47648f9609cf76e55b30064bc437aa5f1669a9160e2f3e670fae3fa6c43e3aab509066e644c59b5c39ac56f283f7f489fef55a0e7cedcb3c2cae0fa3a11ae673d805ecdaa018eafbc5c46ee83c752cd12eabf5cb4278e46cba0deb2a3a89fe5ca1f3d4348540e09e9eea0473a58d7fe7871efd8d930b5fe8b54bce054da1d5d9ad8f6a968f0b229754b9684cb2047ed28d5e7d975c332ed33166ea8e363abfd59a270b891b71e0ad0dd29b3a18c1eb8a5f3d30b406d7230c18e249fd22497977e1e153ef322a2dce510057584fbe8d23079696496151c852095d9901e3db50f5bf08e6e0a72a818cb6b15d19a67a187c41a155b7ee0", .None}, + {.Shl, "-a282b6aaf5d1951ad244b5ce0ae1928b47e5293c123082b638d19a5d2b3394427a7fc420d013a8efdb7b81d976097da64ee29f0d2a4cf50d0748dd9be68820f5d4ea3a6a5988d907059b79ddfb3910c65293e8acc90661ffe752c7f478e912b82341d9355c3c78d49b4981ebeae458db547f01c1cb05b087c248cdfd02490c16d4c314361e6f5c9703f073c869a396b53cf5ad150b83b3a2ee59540b998ae32e0055a282f2e2cf6ce0f36ed7a0e2372fcbd3fb207b6e47b144a68bc42bacd399c006870c973cacd5167f4b0fc86c146de0b0af699ea226862684ec14efe6441aa47b24f749ac31b957bb665e1031fc1065853d10c48441af8d3418af5e69a75f78fdcb0aa1472b4e897c101c2cb62849b5efbffd28510d37cc64fba443b1c24c1a2002709c8d7d862e6ec47d51bc0ebc23043d49020fe30fc28b6e2025d52f74212b69ac9dba5f6469f5a2093d1ebb7f5d9b2e65e8b03d366e5a9d69ad74854068ef46f705ed440bcf62b0dbc61e0058f1df10866b6fd3b45ed00b702ae62638574f7ddf949d6a2040bbcdab72fc576c1e5201e4a2c11f1de32f2282f18725036234652921d0954912174ead51e48aee97b3556a9a967dd399dbe4aef04ac8c27b5b2744d8683774da45f09cbec3e84a879dbf8d0bbf765abd9430a7d81ea9213dc85d4e71bef04609d8569e31af64386ddda0db2b0994db28710605512620af", "2e", "-28a0adaabd746546b4912d7382b864a2d1f94a4f048c20ad8e3466974acce5109e9ff1083404ea3bf6dee0765d825f6993b8a7c34a933d4341d23766f9a2083d753a8e9a96623641c166de777ece443194a4fa2b3241987ff9d4b1fd1e3a44ae08d0764d570f1e3526d2607afab91636d51fc07072c16c21f092337f40924305b530c50d879bd725c0fc1cf21a68e5ad4f3d6b4542e0ece8bb965502e662b8cb801568a0bcb8b3db383cdbb5e8388dcbf2f4fec81edb91ec5129a2f10aeb34e67001a1c325cf2b35459fd2c3f21b051b782c2bda67a889a189a13b053bf99106a91ec93dd26b0c6e55eed997840c7f0419614f443121106be34d062bd79a69d7de3f72c2a851cad3a25f04070b2d8a126d7befff4a14434df3193ee910ec70930688009c27235f618b9bb11f546f03af08c10f524083f8c3f0a2db8809754bdd084ada6b276e97d91a7d68824f47aedfd766cb997a2c0f4d9b96a75a6b5d21501a3bd1bdc17b5102f3d8ac36f18780163c77c4219adbf4ed17b402dc0ab9898e15d3df77e5275a88102ef36adcbf15db0794807928b047c778cbc8a0bc61c940d88d194a487425524485d3ab547922bba5ecd55aa6a59f74e676f92bbc12b2309ed6c9d1361a0ddd36917c272fb0fa12a1e76fe342efdd96af650c29f607aa484f7217539c6fbc11827615a78c6bd90e1b776836cac26536ca1c41815449882bc00000000000", .None}, + {.Shl, "-48fda0d053ae9efef2e89cab5efbe33fed0382e99d01b62ae36dbc4e466f141466b683afd50fd232ec594df262716262c740bfda888616daef08849695d7bd651e54b740e9fc6bc12b6928e1976ee3801dac24798a71166c42002054408aaca7524816fb01e858f54c174003bbf8ce1f2f74bdfdc595cae3f34900ca1d6cbd5ee3c74dd4f628a05fb9bb16fff5eee154b1ff1648759dbc09c19a84448b663a12332ac7840e4b95c0127da9057906d674f244a6b55970d8068c9f3a4177101954b3c0e9d4d70dbbfa9cabee7a61250bcc3511bcf47b88583721cf0e11f0a599e07b1102ec09a06dc6a59f8d8397780139adb6b9be6b1f36a4de1b38fd590d162cbb628de8154d8ed64b1286056a6ae79462384c634eaa3a31b946e0bbf06330f50a5940780199ae1e8b0c65a1359841b379865cc1fd4eb9a56b1c5711a83fc6caf8d04fe2971873b05bf6dfb5db4468ebe8b45a622447e4f0e227fdaa31311f8419acbcd4290ae54d51c3d6a4f9039c0011ff6acd713e1e63a1dbd2a3dd21cdf6a9c0f92559a2a312792b9eaf6a286d8027ed5812f422e629ece68945384358ec6f9f1c7971ff5f02829dadb1681c39f9dfa6215efc440c87e43e38fff6ed73ecb8b6a30328c5b69b047a66cc98f28a3c842fa3921536ba8c74694d89f3215ec329babb1340f73312ab8c250cb71e33f27b4cc8a566fbd9a5ab233b45700f356b", "13", "-247ed06829d74f7f79744e55af7df19ff681c174ce80db1571b6de2723378a0a335b41d7ea87e919762ca6f93138b13163a05fed44430b6d7784424b4aebdeb28f2a5ba074fe35e095b49470cbb771c00ed6123cc5388b362100102a20455653a9240b7d80f42c7aa60ba001ddfc670f97ba5efee2cae571f9a480650eb65eaf71e3a6ea7b14502fdcdd8b7ffaf770aa58ff8b243acede04e0cd422245b31d09199563c20725cae0093ed482bc836b3a7922535aacb86c03464f9d20bb880caa59e074ea6b86ddfd4e55f73d309285e61a88de7a3dc42c1b90e78708f852ccf03d88817604d036e352cfc6c1cbbc009cd6db5cdf358f9b526f0d9c7eac868b165db146f40aa6c76b25894302b53573ca311c2631a7551d18dca3705df831987a852ca03c00ccd70f458632d09acc20d9bcc32e60fea75cd2b58e2b88d41fe3657c6827f14b8c39d82dfb6fdaeda23475f45a2d311223f2787113fed518988fc20cd65e6a148572a6a8e1eb527c81ce0008ffb566b89f0f31d0ede951ee90e6fb54e07c92acd151893c95cf57b51436c013f6ac097a117314f67344a29c21ac7637cf8e3cb8ffaf81414ed6d8b40e1cfcefd310af7e220643f21f1c7ffb76b9f65c5b51819462db4d823d33664c79451e4217d1c90a9b5d463a34a6c4f990af6194dd5d89a07b998955c612865b8f19f93da66452b37decd2d5919da2b8079ab580000", .None}, + {.Shl, "-6d5328ff2afca327ff7af474298564fa1a096c58e90fbfefd591934339bcd8a91914e2c6fb29eb340d2d8f38172d47520a0f7f8096e24479af44284f66b646841e31eb9a5f3158bfe79eeb30c43b95b71c1a44b20334fd94a755ed46356eb69fe98cacf183c7636677c6b715bf72347e57e007216a71e1a67566204b741a4cb208596d34327298a7598ade6825060531921ae3b79761978330640f3515261e791c91c3c2c6db6e01366be432cdd1fbbd6c39b5a07e3494b5e8ea92b2f7d880a38f3fb9d6ce452eafb344f6050a97bc2bae274b98f3522828be75656028bd729639bf02954894eaf20ef57d7194bb552b4a50c9ee3688c5d1685f9bce401a4ca84375e7250f0ad812befb723d8e7afe4fcf6e074d5294fd617af8f05bf0ffed43c6011adcbb2704f053f033f7c6e5114f5aaa96a0090d897ec2079c0a94b714c385463c3cd1d71ed251c067b7b0bf37f7a6608544f0d68400b4b386aff8d72d29872ecdbc880d30fa48f4d0c0bed6834344677754dbc2ed9ebcf4de25b278bff0df8dfccec7168e8ef6c6af44bba2c888b7c7cb72438f062e17221f4cfd5e4775091b5a1190dd09054de783a2c49eaa65e8394b417c92f927ad3d9befa004d73d9915b475e2be0b006cb400abe2c72ac74c41eea55e3b61613adbaf37a6dad5b093d8be91042ccb865a910499ded3cf78c9615b27e0a46e010f257d29becb8264", "6", "-1b54ca3fcabf28c9ffdebd1d0a61593e86825b163a43effbf56464d0ce6f362a464538b1beca7acd034b63ce05cb51d48283dfe025b8911e6bd10a13d9ad91a1078c7ae697cc562ff9e7bacc310ee56dc706912c80cd3f6529d57b518d5bada7fa632b3c60f1d8d99df1adc56fdc8d1f95f801c85a9c78699d598812dd06932c82165b4d0c9ca629d662b79a0941814c6486b8ede5d865e0cc1903cd4549879e472470f0b1b6db804d9af90cb3747eef5b0e6d681f8d252d7a3aa4acbdf62028e3cfee75b3914babecd13d8142a5ef0aeb89d2e63cd48a0a2f9d59580a2f5ca58e6fc0a552253abc83bd5f5c652ed54ad294327b8da231745a17e6f39006932a10dd79c943c2b604afbedc8f639ebf93f3db81d354a53f585ebe3c16fc3ffb50f18046b72ec9c13c14fc0cfdf1b94453d6aaa5a80243625fb081e702a52dc530e1518f0f3475c7b4947019edec2fcdfde99821513c35a1002d2ce1abfe35cb4a61cbb36f22034c3e923d34302fb5a0d0d119ddd536f0bb67af3d37896c9e2ffc37e37f33b1c5a3a3bdb1abd12ee8b2222df1f2dc90e3c18b85c887d33f5791dd4246d684643742415379e0e8b127aa997a0e52d05f24be49eb4f66fbe80135cf66456d1d78af82c01b2d002af8b1cab1d3107ba9578ed8584eb6ebcde9b6b56c24f62fa4410b32e196a4412677b4f3de325856c9f8291b8043c95f4a6fb2e09900", .None}, + {.Shl, "-58f75577497087d8f4342d711d6107ceb2cf8a4fcdbfab58f33410e366f8349e54fa0638f4a3a4aaeceb21b93cd5a8b0e264202e132335a69a8ebb82a5b88e4c06452455ad375f4c59254c6b610c90ccb3b15a0023893529161f9928bf72bc56aef3e4d05605d89f3a40fbc3d0d02e4c577454fe59885458681b71fa35c0df5e9bd07dd1ceff867ce60d8006ead0f0bfd16eb301b62a023bfe177ebaf502d27fc569ce592ae178a853efc9971c044ec9ecd75aa011ee89805ff6eeb499c5fc6188f966070d060e62bdd9a6d7a5ac5a984ac612db9d9f2fca4b8b66f3db4a15496acf2ae5883f0a5ddd9c7440807a94cc97e51c03c68bf41fbaa80d69c7acf0ab3551e7b7496669c5f071eacbfa08ae5edcb4c22e8e7a5b47b1c5d95ad658d9bf1585333294196a87920a2592496ad7fba197656303a71c0fd4dff8ecf79083f0b9445b1ce253e310d60706acb8a9b6a7af4a4a24a951e8fcb67ae9431be9ec23cf8b0505125a297f79c6f357ccbfd532951f2eb73c23edaa69f999defa89ed86714e52f07101041bceef2069cb02cee3a474446173feb124822118f6588203edf7160131c8996e2f1d8e359f24d9899d4544ccf8ac08981349bc8cb3c4ce5d1e1c716f36ebc205fdd155801ae20d08053d8d0604adeb3be9ac16a55fd86e3fa53a2b3e8d939b73d21533da777d7a80d0cd822e6b803ac98d666128bae1c96916", "32", "-163dd55dd25c21f63d0d0b5c475841f3acb3e293f36fead63ccd0438d9be0d27953e818e3d28e92abb3ac86e4f356a2c3899080b84c8cd69a6a3aee0a96e2393019149156b4dd7d31649531ad84324332cec568008e24d4a4587e64a2fdcaf15abbcf93415817627ce903ef0f4340b9315dd153f966215161a06dc7e8d7037d7a6f41f7473bfe19f39836001bab43c2ff45bacc06d8a808eff85dfaebd40b49ff15a73964ab85e2a14fbf265c70113b27b35d6a8047ba26017fdbbad26717f18623e5981c3418398af7669b5e96b16a612b184b6e767cbf292e2d9bcf6d285525ab3cab9620fc29777671d10201ea53325f94700f1a2fd07eeaa035a71eb3c2acd5479edd2599a717c1c7ab2fe822b97b72d308ba39e96d1ec717656b596366fc5614ccca5065aa1e4828964925ab5fee865d958c0e9c703f537fe3b3de420fc2e5116c73894f8c43581c1ab2e2a6da9ebd292892a547a3f2d9eba50c6fa7b08f3e2c14144968a5fde71bcd5f32ff54ca547cbadcf08fb6a9a7e6677bea27b619c5394bc1c404106f3bbc81a72c0b3b8e91d11185cffac492088463d962080fb7dc5804c72265b8bc7638d67c93662675151333e2b022604d26f232cf1339747871c5bcdbaf0817f74556006b88342014f6341812b7acefa6b05a957f61b8fe94e8acfa364e6dcf4854cf69ddf5ea03433608b9ae00eb26359984a2eb8725a458000000000000", .None}, + {.Shl, "13e3cb99f04f87ec00a3c95188bf0b4ae36a0c991470098e6ec765243570d2daf654319dc8c9f5e73cf1eb966c7379dc54130eaeec32071a1b48bac750c41e4681634cc12394b30716dfd452612c53a66ea8c0e85fc901709197606530b40d9620467472e725642b346bab83c356233fdf75d348caa2d5701932cfedef7ba8e6370c6f01f2671417170b61dc4c33b44ecaf8b98dea8b06cd7a20a84abda4906fcf6066b6419a3f844cbd491bf1dad6a5d46804612384055256c1decbf72e6b96bdefbf432bf6a109a8159a805f7b48f53049e478025f486a7d29a1faada61dcd20f7a95076428d454b0a364850cea32f9b2ef2266d3f84c4eecb634bc7b42147bf00d0ea02d8127aea959ccb09e9e0c9a9d66f8a87216e3a910d4196687608148a83ade5d7177682244457c95771f909973f19ee5e6f923f6c154fd07ea2cd19c177e067e08d734a3e86c3c514e8c4c5e90ac19b1d41d6615dbb32149d0292581505f1f7eeaa16257d3ca07f4e208f7dd1f5865f7234c6d01b5475019c055a5fbd1154d71d252778c8d3691c4e96ed9964bad3193ae6e73fbd4f925915cbe6301e60514a22e5be2c425eaf6b175e11d83816e28977e8401fcc97cca585f03d675bf2ae680ad2b7a7db754cfd14c694613ad53900a9aa64d59282a6793f425fd973cac77f6c1e8626a8910528af54d094bbe77190e3bc374dbc25dbab36e324af", "9", "27c79733e09f0fd8014792a3117e1695c6d4193228e0131cdd8eca486ae1a5b5eca8633b9193ebce79e3d72cd8e6f3b8a8261d5dd8640e343691758ea1883c8d02c699824729660e2dbfa8a4c258a74cdd5181d0bf9202e1232ec0ca61681b2c408ce8e5ce4ac85668d7570786ac467fbeeba6919545aae032659fdbdef751cc6e18de03e4ce282e2e16c3b89867689d95f1731bd5160d9af44150957b4920df9ec0cd6c83347f08997a9237e3b5ad4ba8d008c247080aa4ad83bd97ee5cd72d7bdf7e8657ed4213502b3500bef691ea6093c8f004be90d4fa5343f55b4c3b9a41ef52a0ec851a8a96146c90a19d465f365de44cda7f0989dd96c6978f68428f7e01a1d405b024f5d52b399613d3c19353acdf150e42dc75221a832cd0ec102915075bcbae2eed044888af92aee3f2132e7e33dcbcdf247ed82a9fa0fd459a3382efc0cfc11ae6947d0d878a29d1898bd21583363a83acc2bb7664293a0524b02a0be3efdd542c4afa7940fe9c411efba3eb0cbee4698da036a8ea03380ab4bf7a22a9ae3a4a4ef191a6d2389d2ddb32c975a63275cdce7f7a9f24b22b97cc603cc0a29445cb7c5884bd5ed62ebc23b0702dc512efd0803f992f994b0be07aceb7e55cd015a56f4fb6ea99fa298d28c275aa72015354c9ab25054cf27e84bfb2e7958efed83d0c4d51220a515ea9a12977cee321c7786e9b784bb7566dc6495e00", .None}, + {.Shl, "-baa2ce077dc3655f54543f90db3dface2f7c3e849e8133bf633eb12f8951457b8bda972c1b187a98402def08b34cc118c262380927ea59c8a005b47d272a5d0721c6be76c6a99fb0c97d49fb1bc2b16c22f2670f91bcc5fb6cbcc164335d394e197aba29a7a5a2a5ec1dd76bb6a131ce72425ff53c66049372f3bd5949a32a1dcaef95d940e3f2cfce1b8237786485fea918ead7850f19affc1d920bf2eb0d64696800f942626d0dc38951d9080e05440f5aba0a4a24c0bac03c6b8d5582c31b81860707785126f956b43f686e6db4039b7d4085197ec809fa1a4731289d4b0bcf152b74e222cf4bf8de252cf5ec4b54089ed19fe9a1a628154421af103a78207f62c25bacbb9ea82c682dfb16340362049e5f9eb09dff3cf5c1a7568c578052713f323458e4a2c30a742170fb5744762c7b02d0bb588e732e307ebf34df2e6798f51bae689f117ab02af4dc64b5dda65b7d3ec83ba81cc0af3221140c6ff056142abc9fe8eed220a8d7d014b167c62b89a4ccc54193528a2766363c2302663eb72e5d086c5ece5bbe333823de74dfbece76b161e32e3583bb9b0c571d296f49890f13a9d60dda06206e86151c9e06f44b5096c724e8b083ad0d28b8da67f04d8974859d702dec9f91b9225029aa3ddb2014ff6d0e282b6a747864fdef58db15407f3e71e35b58fd0890b5348f641cb49bf70a28d32a19f3dbb3e48776c2ce02", "3", "-5d516703bee1b2afaa2a1fc86d9efd6717be1f424f4099dfb19f5897c4a8a2bdc5ed4b960d8c3d4c2016f78459a6608c61311c0493f52ce45002da3e93952e8390e35f3b6354cfd864bea4fd8de158b611793387c8de62fdb65e60b219ae9ca70cbd5d14d3d2d152f60eebb5db5098e739212ffa9e330249b979deaca4d1950ee577caeca071f967e70dc11bbc3242ff548c756bc2878cd7fe0ec905f97586b234b4007ca1313686e1c4a8ec840702a207ad5d052512605d601e35c6aac1618dc0c30383bc28937cab5a1fb43736da01cdbea0428cbf6404fd0d2398944ea585e78a95ba711167a5fc6f12967af625aa044f68cff4d0d3140aa210d7881d3c103fb1612dd65dcf54163416fd8b1a01b1024f2fcf584eff9e7ae0d3ab462bc029389f991a2c725161853a10b87daba23b163d81685dac473997183f5f9a6f9733cc7a8dd7344f88bd58157a6e325aeed32dbe9f641dd40e605799108a0637f82b0a155e4ff4776910546be80a58b3e315c4d26662a0c9a94513b31b1e1181331f5b972e84362f672ddf199c11ef3a6fdf673b58b0f1971ac1ddcd862b8e94b7a4c48789d4eb06ed031037430a8e4f037a25a84b6392745841d686945c6d33f826c4ba42ceb816f64fc8dc912814d51eed900a7fb6871415b53a3c327ef7ac6d8aa03f9f38f1adac7e84485a9a47b20e5a4dfb851469950cf9edd9f243bb6167010", .None}, + {.Shr_Signed, "124ed2113dad496f977d6b6b18639f3542ef5898df3b840f460630dd325dc1214cf26e7b16b8820c7784258bdcb2902acc754f441398d1fe97dd1bf8f9a9012dbe408e2af1ccb216357c1017537ec4b7e7efda9eb7aef5608f92c23f4224b18fc4000d16a755f4811771b0c25ce8fdb82c6a3cc20c673a56edbaa758321c9f7ae90316ec74094be66204d8ebbc3a3cccf69abfb02fd11aba1ed31d1d3b0753ef4afd85fe4723820fde281736d00a9ff0a649c9c4ec2ec680dab6bbdc388449f4b5a2d2a927ba91e1e69f62a97fea34541b266f9d77460513f393f649a41c443f0ba01e228cba45c60a026a1f8bcf16c24d22d8a23fff992d4aab135e98ddff05b943e9577e0036ee2567199219632cd23d25a18949f37b7bca2783a928eaa3bd4c0c83653f0475b5992e7edea3e842306968cedf285f290428b31a031a2c427be5bda18e623365c2a6073f0e09c52d9e45d85c0286ac2df2292fd4bd99f7de8d910fe99591810596206ea71247aafaff90ee2df74f5f5bc8ebc54d02a84d53d1cab16b3a86cdd116435993f8617bb4c040760847616114ddca9e3eaac8a7713e1098eec08a46056bafcce99a698e52bac389c6938f4462083dba3cc2edf2213d4946f90fefbab7ebdc9e620133598c3e78006611582fc5a6da9b987c525d95389be45da3d70f9c1105c8072069002d2a27fd6abb06c54b771e177aac29377dda", "74", "124ed2113dad496f977d6b6b18639f3542ef5898df3b840f460630dd325dc1214cf26e7b16b8820c7784258bdcb2902acc754f441398d1fe97dd1bf8f9a9012dbe408e2af1ccb216357c1017537ec4b7e7efda9eb7aef5608f92c23f4224b18fc4000d16a755f4811771b0c25ce8fdb82c6a3cc20c673a56edbaa758321c9f7ae90316ec74094be66204d8ebbc3a3cccf69abfb02fd11aba1ed31d1d3b0753ef4afd85fe4723820fde281736d00a9ff0a649c9c4ec2ec680dab6bbdc388449f4b5a2d2a927ba91e1e69f62a97fea34541b266f9d77460513f393f649a41c443f0ba01e228cba45c60a026a1f8bcf16c24d22d8a23fff992d4aab135e98ddff05b943e9577e0036ee2567199219632cd23d25a18949f37b7bca2783a928eaa3bd4c0c83653f0475b5992e7edea3e842306968cedf285f290428b31a031a2c427be5bda18e623365c2a6073f0e09c52d9e45d85c0286ac2df2292fd4bd99f7de8d910fe99591810596206ea71247aafaff90ee2df74f5f5bc8ebc54d02a84d53d1cab16b3a86cdd116435993f8617bb4c040760847616114ddca9e3eaac8a7713e1098eec08a46056bafcce99a698e52bac389c6938f4462083dba3cc2edf2213d4946f90fefbab7ebdc9e620133598c3e78006611582fc5a6da9b987c525d95389be45da3d70f9c1105c8072069002d2a27f", .None}, + {.Shr_Signed, "845a03549a64a4f23ed9312624cd368a84bd66fbd935153ed9bed1bc9f9f1399b24b29ddfa231c2b8c7226d39c08c184b61fef5f6a1401ffcacf7ded6bc9108fe25522d3eb71867aaf2981f3d2e81e0b4af29993194529fcaa6016a54891ceb3a3402b6668d23550ea936b78a71ef61f50d8e4919017f6cc106610fa6d79c65d20688c7039f126b6e08e18aa62fe4b96365973218a3982fb33ebc939613cfe55b6d006f4e4d5f8eeeae523a3490fb2cb68283d1052fcb4ef132f3fcf4755977c7f8daa9e70301330e70cf06ef52d2550c36f928d5438f0c32ca39717020a6846c2dd76bc7b1cf5745927df3fce71a87a33144e2edee9a6ee83b801f1aea99a6bbd971cb58e76475b545c271ffb34d91bb2e45c12b1738fdbef535d64dcfd7699ad15dd3aaacde806b5caa9d500131499aa3509ccd2f130baf308c86b6861334833ceb1afe248dd31de98c4abb8c187bf227d6542ae81bd5bdd7ca05fd3692cdc530fe65366f5ef0ed70a1f222bb570aa999105f1bf7b11fbeb0dbe446b919f9221c74b13971913859299f8f8e630b7ce472852c37926182a86c123fc7539e2808fee85e6f0f635f01f429f54528daf8e296fa84fd1e4df229caf9b4e1b3d324f198e0e1d006817b064674d3b6ced5b204183767adf8978b483281c8c14616fc552b13a1fdace75979df780d3c63eeddf17d42be544bf069e33963d6a8f2c1821", "78", "845a03549a64a4f23ed9312624cd368a84bd66fbd935153ed9bed1bc9f9f1399b24b29ddfa231c2b8c7226d39c08c184b61fef5f6a1401ffcacf7ded6bc9108fe25522d3eb71867aaf2981f3d2e81e0b4af29993194529fcaa6016a54891ceb3a3402b6668d23550ea936b78a71ef61f50d8e4919017f6cc106610fa6d79c65d20688c7039f126b6e08e18aa62fe4b96365973218a3982fb33ebc939613cfe55b6d006f4e4d5f8eeeae523a3490fb2cb68283d1052fcb4ef132f3fcf4755977c7f8daa9e70301330e70cf06ef52d2550c36f928d5438f0c32ca39717020a6846c2dd76bc7b1cf5745927df3fce71a87a33144e2edee9a6ee83b801f1aea99a6bbd971cb58e76475b545c271ffb34d91bb2e45c12b1738fdbef535d64dcfd7699ad15dd3aaacde806b5caa9d500131499aa3509ccd2f130baf308c86b6861334833ceb1afe248dd31de98c4abb8c187bf227d6542ae81bd5bdd7ca05fd3692cdc530fe65366f5ef0ed70a1f222bb570aa999105f1bf7b11fbeb0dbe446b919f9221c74b13971913859299f8f8e630b7ce472852c37926182a86c123fc7539e2808fee85e6f0f635f01f429f54528daf8e296fa84fd1e4df229caf9b4e1b3d324f198e0e1d006817b064674d3b6ced5b204183767adf8978b483281c8c14616fc552b13a1fdace75979df780d3c63eeddf17", .None}, + {.Shr_Signed, "313320955cd4ea055acf1e3dff68b333ff39f22c471d47760e22bcfb76384354e00df20c215bceb370f6ef3349b1b7d160035cdd3d41545b462b5a223cf8bb87fffde2dd7e5ba978c89ac3e9f73dd966fc9a484e3aedf330a69533060eb0fedee9728d92490355fe1ea0b8b453876d6ed73c0d3b9c4ebb344f4186efc7f5499bcbf19380515c3f3de76bb9a4785cade1b9925894c96c0585c127b62b56b3afaf60ad50c61c27c2df1646113d04b208fd43aa3c7c98ffc13a1ec9ce409672185483f1510b62caf6c74fe2587c585b001a0dba0283022d7a1a2b2912baabc72e4c661eabd087b6352a03f425c0e4f163d6d0a242c516c154a681b51f7a7d10770faa264cbd9991ff527b70786ec2a906aeb952a19e8e5ac1f078921a462d0d7382fb5b38804647c43e0b3d6ad5a705889bab0d79217e68013912b084ed78fb39c09a7b4b718fef00d23c16a8ed7a383c04763bc31cb34f394499dc8f21b1dc4be01d67a9d64d541e327c0bb5fe419900d4f222496de9a5a4195eb081bfd7844956740658f06f0da8760c2b7710c23f20b48798a21eb647f2addc2698b1bcf83dbe2c0069f9e11faf6cf32ef55d1c48d79c5b272c52fe0620b1c4dd446e6a25d0ee8311e0f8f50b9c018ab8bb81ba2173855dd71cacefac42b11a1ff36a239aa9f56d5478b9fb7b3308eefeeee94403eb704077d7e235804a173776363e13366d6e", "15", "1899904aae6a7502ad678f1effb45999ff9cf916238ea3bb07115e7dbb1c21aa7006f90610ade759b87b7799a4d8dbe8b001ae6e9ea0aa2da315ad111e7c5dc3fffef16ebf2dd4bc644d61f4fb9eecb37e4d24271d76f998534a998307587f6f74b946c92481aaff0f505c5a29c3b6b76b9e069dce275d9a27a0c377e3faa4cde5f8c9c028ae1f9ef3b5dcd23c2e56f0dcc92c4a64b602c2e093db15ab59d7d7b056a8630e13e16f8b23089e8259047ea1d51e3e4c7fe09d0f64e7204b390c2a41f8a885b1657b63a7f12c3e2c2d800d06dd01418116bd0d1594895d55e39726330f55e843db1a9501fa12e07278b1eb685121628b60aa5340da8fbd3e883b87d513265eccc8ffa93db83c37615483575ca950cf472d60f83c490d231686b9c17dad9c402323e21f059eb56ad382c44dd586bc90bf34009c89584276bc7d9ce04d3da5b8c7f780691e0b5476bd1c1e023b1de18e59a79ca24cee4790d8ee25f00eb3d4eb26aa0f193e05daff20cc806a791124b6f4d2d20caf5840dfebc224ab3a032c783786d43b0615bb88611f905a43cc510f5b23f956ee134c58de7c1edf160034fcf08fd7b679977aae8e246bce2d9396297f031058e26ea2373512e8774188f07c7a85ce00c55c5dc0dd10b9c2aeeb8e5677d621588d0ff9b511cd54fab6aa3c5cfdbd9984777f7774a201f5b8203bebf11ac0250b9bbb1b1f099", .None}, + {.Shr_Signed, "d0778c21761ea1bf1f0a941ecfc4bcfe466aa2094837a60b0056ba36ac93157dbf1e5c7a2c6b150d111cd389f325853c710ce1506c055fd9fcd12268cf8f23744c0ab2f87fbdff0d6326266eede3dd8832cf09572c5baa4b3d0b4220de4a7fc4883793016f7cd8e92b570005acbe71eea1f630e4948d034fa5c01a2928a9c24053c7cb4f7b257a684b809c0001ba0b0d162dc84c63c6ca34469a5cfae35c0b3a8b647475272fedb4a95c2005abe3965d0916bf865ec8922f3393a15ba770a3a78e2092f1f9b1c630eae1c3d00b3cfd8ab030ffbebc7e2bb059d9cb2d27f9af849ab11e9eeb160cd7b44f820b00703847516f9e3461f8bc6a56fbe7e96f17142e6193fcb8e7f573f3675751a638d498ce20c229cdcba194579eaca8028d8e873d41c92a28baa774a8be44c3e2797abf42096f3f2fd1faf0ddca6718b450d42c9fe4d7cb070f8d01c6e1111fb2eca74c1fde480fcae9eb0808f937863b08938e3937fe8709d164237dcb4ddba3c0b9b9e6af37b8fcdc2e23572ab0aae3e60f989b105e71952575e9385fcbef9a5305adcbf3c787928dfc97d30a0674f72a33b2e5911329bcf5ac079ca3cf8d66572621940f04b38d766cd48577b14364000caa7e06e764571d5e06ae02298a1279a1b00184d62b2d0dfe75f33b1364116c79e3b21cc385c7bc1f5cc855af91718574b307d829d762207978d6fa46ededc95bc086", "58", "d0778c21761ea1bf1f0a941ecfc4bcfe466aa2094837a60b0056ba36ac93157dbf1e5c7a2c6b150d111cd389f325853c710ce1506c055fd9fcd12268cf8f23744c0ab2f87fbdff0d6326266eede3dd8832cf09572c5baa4b3d0b4220de4a7fc4883793016f7cd8e92b570005acbe71eea1f630e4948d034fa5c01a2928a9c24053c7cb4f7b257a684b809c0001ba0b0d162dc84c63c6ca34469a5cfae35c0b3a8b647475272fedb4a95c2005abe3965d0916bf865ec8922f3393a15ba770a3a78e2092f1f9b1c630eae1c3d00b3cfd8ab030ffbebc7e2bb059d9cb2d27f9af849ab11e9eeb160cd7b44f820b00703847516f9e3461f8bc6a56fbe7e96f17142e6193fcb8e7f573f3675751a638d498ce20c229cdcba194579eaca8028d8e873d41c92a28baa774a8be44c3e2797abf42096f3f2fd1faf0ddca6718b450d42c9fe4d7cb070f8d01c6e1111fb2eca74c1fde480fcae9eb0808f937863b08938e3937fe8709d164237dcb4ddba3c0b9b9e6af37b8fcdc2e23572ab0aae3e60f989b105e71952575e9385fcbef9a5305adcbf3c787928dfc97d30a0674f72a33b2e5911329bcf5ac079ca3cf8d66572621940f04b38d766cd48577b14364000caa7e06e764571d5e06ae02298a1279a1b00184d62b2d0dfe75f33b1364116c79e3b21cc385c7bc1f5cc855af91718574b307d829d76220", .None}, + {.Shr_Signed, "-6f50732e344b526e9f68bb89d84f59001b69140a9285595f20c8fe8f570e9ee220962aaccb5d0eeb47c22cd67b09f44b123a99ba10009511882fa2ed38db561a2cbdbe15f7434d958db288c33d3bd4c856f8795262d9a591a8cb9861b7b9c97bd76afd4286a1dbd48774a199070c914decaeaad22ac54fd56711ad71ab6c7ff8cae28e9b595473d98a228052c05de90dd3c67e7d181a60afb560fbe5f3cbd18c35fe45f0d60db890ab0179db651629bd94f3edb756c20a12a626d30a14317d55f156bfbb0a7b5a42c65d8f1ba71c754618882496b76bed76536b726061f226698c9d3e8e08a93c63d4ac9acbb8f57c9163eddfa51b1a9e1fdd16b0be05c5d78209dc13a2ff7eea05523e217ad1e38d382e5cdafd1e9195e9f08378dc15604d646466341c7c26224f425be7dc331e46aa35dd6a8d7575fb1e6b63486a6160846d8ffeee01a4c10ab20d70e0f145442efe7d0ccb8709eac8ad3eb8007916197119a67eacbaf7de706f7976d5a3441dd2624796c7b5ebfc33eee399f9ae987b3059ff5e73189216aa81d476c21e1cea24db7522de0f2b9cb6bad20d54649ed5d8dff32df1b513c1d243e7042cd556540d7e184819cfa423b498d312193e310545b63989545e972484f993ab21245f2cdc51f7e4e5985ab1d02c538659828cac7c639d56e0b2c89c32bd860bb369fc33b5f4879712ad74b025206bdce029e478b41a", "3e", "-1bd41ccb8d12d49ba7da2ee27613d64006da4502a4a15657c8323fa3d5c3a7b888258aab32d743bad1f08b359ec27d12c48ea66e84002544620be8bb4e36d5868b2f6f857dd0d365636ca230cf4ef53215be1e5498b669646a32e6186dee725ef5dabf50a1a876f521dd286641c324537b2baab48ab153f559c46b5c6adb1ffe32b8a3a6d6551cf66288a014b0177a4374f19f9f4606982bed583ef97cf2f4630d7f917c35836e242ac05e76d9458a6f653cfb6dd5b08284a989b4c2850c5f557c55afeec29ed690b19763c6e9c71d5186220925addafb5d94dadc98187c899a63274fa3822a4f18f52b26b2ee3d5f2458fb77e946c6a787f745ac2f817175e0827704e8bfdfba81548f885eb478e34e0b9736bf47a4657a7c20de370558135919198d071f098893d096f9f70cc791aa8d775aa35d5d7ec79ad8d21a9858211b63ffbb80693042ac835c383c51510bbf9f4332e1c27ab22b4fae001e45865c46699fab2ebdf79c1bde5db568d107749891e5b1ed7aff0cfbb8e67e6ba61ecc167fd79cc62485aaa0751db087873a8936dd48b783cae72daeb483551927b57637fccb7c6d44f07490f9c10b355595035f86120673e908ed2634c4864f8c41516d8e625517a5c9213e64eac84917cb37147df9396616ac740b14e19660a32b1f18e755b82cb2270caf6182ecda7f0ced7d21e5c4ab5d2c09482", .None}, + {.Shr_Signed, "6eb383b3812a23745643012fb623e55ae5ba069a50ee35ca640868f2dd5f82cf39c79d076fa5732f75f0e0125aec5bdaa54ef5f1e0871fe1936ad7e45524e34d542895743ab5cecef782f6de7750781214a82e8bd1af9255f34fd91f16f46e8cfc267b8299d494f2168330b6d26f985d761e594a29c52bb6d8ddec74054dcb9e58275d935ed3994eef011016ceb453001b533ea7d555eea686e55cd944f79ef766d76d9c6c068db7b390dde3ba4cf9601bd26f990945d65e2df18f38b411cb8f004ef89119a0417cd9c4d943ce009331368c974cb5bc5fdb54b3467d451bf736e67f80099e221f1eeb42b69e7ef4f5a6e2128f5c16d7db58d92ff67a33f0fa6427f3e1bc6efd8d0ea052aeb0d11b345bc956e10bf5791d771122d45e2554e17f46b9c2f85420f2c5225f28df66e7277c2d3d494f433a669e9eba4aa79c4fef61718a8805bf0b29737b77d826aa57f6277b51e34333650e81273e16a36ed0728ad4a97a44eb15b25c882e93e6350dfe4d1ba0aea5edb5da29d37f0244c50c981f023a9dbadb91ffa64b88bac573f7a0842816b981a7763cdc5bb19a68a795f5be9e45d14f3f44bd259a66ed998a4488faf1952a2c17a2f0429999f61965df217910e538d063fa5c0ae3a86c745000415ef04b88d0de4aa1278e3b8241c3a42cefa9ceffada9169a55bf4c464437a0db8d6aa8eba4755a087e0d510d5d300627c0", "44", "6eb383b3812a23745643012fb623e55ae5ba069a50ee35ca640868f2dd5f82cf39c79d076fa5732f75f0e0125aec5bdaa54ef5f1e0871fe1936ad7e45524e34d542895743ab5cecef782f6de7750781214a82e8bd1af9255f34fd91f16f46e8cfc267b8299d494f2168330b6d26f985d761e594a29c52bb6d8ddec74054dcb9e58275d935ed3994eef011016ceb453001b533ea7d555eea686e55cd944f79ef766d76d9c6c068db7b390dde3ba4cf9601bd26f990945d65e2df18f38b411cb8f004ef89119a0417cd9c4d943ce009331368c974cb5bc5fdb54b3467d451bf736e67f80099e221f1eeb42b69e7ef4f5a6e2128f5c16d7db58d92ff67a33f0fa6427f3e1bc6efd8d0ea052aeb0d11b345bc956e10bf5791d771122d45e2554e17f46b9c2f85420f2c5225f28df66e7277c2d3d494f433a669e9eba4aa79c4fef61718a8805bf0b29737b77d826aa57f6277b51e34333650e81273e16a36ed0728ad4a97a44eb15b25c882e93e6350dfe4d1ba0aea5edb5da29d37f0244c50c981f023a9dbadb91ffa64b88bac573f7a0842816b981a7763cdc5bb19a68a795f5be9e45d14f3f44bd259a66ed998a4488faf1952a2c17a2f0429999f61965df217910e538d063fa5c0ae3a86c745000415ef04b88d0de4aa1278e3b8241c3a42cefa9ceffada9169a55bf4c464437a0db8d6aa8eba4755a087", .None}, + {.Shr_Signed, "-344701560d8ce9f8edfd1d9355657cd13cff8917462a61cd1107fe9ed1c95e5a47fd59e0ccbbdb76dc03dee68e7ae13548f9bebf590580155761a7b9b0b1aac67a82cdc4835ec911ffc4ceefc676835367a4d9e0f042518f7a42e59100dbe134d6b903c6eb0de3f6735ab3ab693f9055991c07a6a2dac9d035712180ea71d291e0edcfc0d532e8e9ebc1d5e45ac5da42a5de6d11de7b3720ccd4efe251d6c3fc69a84baf915ba539c70bb482acb148a6ef4de66a2e9b5e3d2d859e36fc48c053c4579020a37c0b43fda07d309825af19c5d0bc97c6118235d11547d1aaa4fb16b2a64bfbcb33eff541c6c874929deb94dd7748bcdbb95fcdc5676a77a952b815b4421b54d96631454fec112d45f289e64774b4c47278e27cec4d608c0af388e18f4dc82ea5af96497a4f84c5436e2b994d373248930c86b0cf359a39b53ad2ac9beee08e4ff5705ffae76ab5377a8641c7dab4ada7cf91176fe418eafd276308a4350b855e240a0d1cbaf28b4e720b33aa56717473bec89e13e719ef4715347452386e9621a6c73608b935ead1e4f129d16b432ae0b7e28fa017e83e1c6eca78c0861f6d57ab2b5f721583f44a58f6a2b30d85f21193ec29aa8c20d3b94a7e173ca79ef992d6990328f0ab98871b5edb114ae60ee1b4e00e09b18ca9e07d02431efad6c036ee7292960c9614035f370c99e01c6518159230f3402ab577f8603f", "77", "-688e02ac1b19d3f1dbfa3b26aacaf9a279ff122e8c54c39a220ffd3da392bcb48ffab3c19977b6edb807bdcd1cf5c26a91f37d7eb20b002aaec34f736163558cf5059b8906bd9223ff899ddf8ced06a6cf49b3c1e084a31ef485cb2201b7c269ad72078dd61bc7ece6b56756d27f20ab32380f4d45b593a06ae24301d4e3a523c1db9f81aa65d1d3d783abc8b58bb4854bbcda23bcf66e4199a9dfc4a3ad87f8d350975f22b74a738e1769055962914dde9bccd45d36bc7a5b0b3c6df89180a788af204146f81687fb40fa61304b5e338ba1792f8c23046ba22a8fa35549f62d654c97f79667dfea838d90e9253bd729baee9179b772bf9b8aced4ef52a5702b688436a9b2cc628a9fd8225a8be513cc8ee96988e4f1c4f9d89ac11815e711c31e9b905d4b5f2c92f49f098a86dc57329a6e649126190d619e6b34736a75a55937ddc11c9feae0bff5ced56a6ef50c838fb5695b4f9f222edfc831d5fa4ec611486a170abc48141a3975e5169ce4166754ace2e8e77d913c27ce33de8e2a68e8a470dd2c434d8e6c11726bd5a3c9e253a2d68655c16fc51f402fd07c38dd94f1810c3edaaf5656bee42b07e894b1ed45661b0be42327d853551841a77294fc2e794f3df325ad320651e157310e36bdb62295cc1dc369c01c13631953c0fa04863df5ad806ddce5252c192c2806be6e1934", .None}, + {.Shr_Signed, "1abc58fb4bd4ae406e0d7bab3a926a37e6f8d3f4ef0f857d477731ad0f59c9dbcdc2a8d9a0d006c674156170122b43d44ad960f41689151593bdcf24498ab708348cdb62de5244d3ea4d6a706563e76f189e37c951020976d35e9600cb1dfd867b9486e1a86f4a03d23b415cbc6cb4ea4dc7f9b4186583f563d487624ac85d454aae151c241e1755cef742f5b243f7923f12f66395838ed16f8535746ee4c363da7e73d9dfb80dc9e13b63002e8ec9a4fdcbb8b57aca48df75845d0accba189e7640aa5861a3476908fca51720b83215468fa26841523ee628aa07bf4799e706e8c8d91b05335908f78ace9f0e01e80b5e24ba761e4d97988ca0ed41bef1e60bdb77a7568d4b5b001789b674ac635464f5a1ebcf8178e7b61ab28b9b10c1f97c2d43c4ab8dc7f9bc46cbbd2478591c411bc41c419a849ee6798e02b0f88707c59c7d7bd70b37ff0b754c37c389fa3c771f0c94478f3df3760dfb4d7bc600103c8bf39af3f0a97a107dea384314f92495910fca3f73170fda5663e2ac2a9a5f0fa4ef5d8b34a0f0b6c52e931e51c2b993fa52eefddeeb60ad10897426ddba7b9c78056dcfa41aec67def7034632ee918ef952025d147ac67fa0899a1163c043d6e19b0684692642be98a6be602ef1f7f2bf64c13b9580169bc84b92ee00169730d6004280d1db78ed246606c824cf468fc758423eb6ecbe2b164395781e64742d", "e", "6af163ed2f52b901b835eeacea49a8df9be34fd3bc3e15f51ddcc6b43d67276f370aa36683401b19d05585c048ad0f512b6583d05a2454564ef73c91262adc20d2336d8b7949134fa935a9c1958f9dbc6278df25440825db4d7a58032c77f619ee521b86a1bd280f48ed0572f1b2d3a9371fe6d061960fd58f521d892b2175152ab8547090785d573bdd0bd6c90fde48fc4bd98e560e3b45be14d5d1bb930d8f69f9cf677ee0372784ed8c00ba3b2693f72ee2d5eb29237dd611742b32e86279d902a961868d1da423f2945c82e0c8551a3e89a10548fb98a2a81efd1e679c1ba323646c14cd6423de2b3a7c3807a02d7892e9d879365e623283b506fbc7982f6dde9d5a352d6c005e26d9d2b18d5193d687af3e05e39ed86aca2e6c4307e5f0b50f12ae371fe6f11b2ef491e16471046f1071066a127b99e6380ac3e21c1f1671f5ef5c2cdffc2dd530df0e27e8f1dc7c32511e3cf7cdd837ed35ef180040f22fce6bcfc2a5e841f7a8e10c53e49256443f28fdcc5c3f69598f8ab0aa697c3e93bd762cd283c2db14ba4c79470ae64fe94bbbf77bad82b44225d09b76e9ee71e015b73e906bb19f7bdc0d18cbba463be548097451eb19fe822668458f010f5b866c1a11a4990afa629af980bbc7dfcafd9304ee56005a6f212e4bb8005a5cc358010a03476de3b491981b20933d1a3f1d6108fadbb2f8ac590e55e07991", .None}, + {.Shr_Signed, "a0d9a22bd6749165bddf3328315dbed3358783cdd367a9e0f2dc15aff2688f0905c8e3a2cdb903b00b308277917a26f5551b8240d352bc0d9cbadc25163cb031de38ba16c911b53885a9c6a0d9e03652812eca54d5956d059d484bb12ecab73574280cb781819c45a280dcf649df49b5dddbeb5c710575c915bff5d4a4990d65ced6fd41ac1760621e06476b898ef792acd0c2c43bba3588217741952bc72f69a930fa9c378329c5045037ee7a593cb073068add065e8d13ecfd46348171f614587617257c72493b600cdd8f3f10a2b1486d9cfa9a52a0f359020c5ab3b67f6139b05bc92676968bc1ddd8a4b50a7ea17a75cebd7a95c117337caf3fa7d306132635db6ad75f3ef140d1497248d29f05b099b4922efda1b6971b1faa9a4d4722a35f20ebeaa36e55f5a7b1b0ddc0a352baa4396020c79b9c9ed6d7297e6a50e7c3c8c7bf883441c8603c683f65f8a5bd8202786045ae52a4f5b8a71b4687d8bfd004bd5fd98b44eb52ea837495011a6649bdf055ee6b010a15e17f42729789efd15f248b1bec4a39f8b6ed5f289fa4d0239afe68a287e5974cfce01ff9f101efe6eb229784b2f7bc98c0487deb08f19cbf01f8b564883a47da68d73af4537013392d56d0f819504c5a313930bc04ac2c8adfa1f2e925d89c31cad5ca017e508ec05b765a54571fac6534121fd2d1fb2ef10aeb2edf4e26546aa5a470b926dd02", "5f", "141b34457ace922cb7bbe665062bb7da66b0f079ba6cf53c1e5b82b5fe4d11e120b91c7459b720760166104ef22f44deaaa370481a6a5781b3975b84a2c796063bc71742d92236a710b538d41b3c06ca5025d94a9ab2ada0b3a9097625d956e6ae850196f0303388b4501b9ec93be936bbbb7d6b8e20aeb922b7feba949321acb9dadfa83582ec0c43c0c8ed7131def2559a1858877746b1042ee832a578e5ed35261f5386f06538a08a06fdcf4b27960e60d15ba0cbd1a27d9fa8c6902e3ec28b0ec2e4af8e49276c019bb1e7e21456290db39f534a541e6b20418b5676cfec27360b7924ced2d1783bbb1496a14fd42f4eb9d7af52b822e66f95e7f4fa60c264c6bb6d5aebe7de281a292e491a53e0b613369245dfb436d2e363f55349a8e4546be41d7d546dcabeb4f6361bb8146a5754872c0418f37393dadae52fcd4a1cf87918f7f10688390c078d07ecbf14b7b0404f0c08b5ca549eb714e368d0fb17fa0097abfb31689d6a5d506e92a0234cc937be0abdcd602142bc2fe84e52f13dfa2be491637d89473f16ddabe513f49a04735fcd1450fcb2e99f9c03ff3e203dfcdd6452f0965ef79318090fbd611e3397e03f16ac910748fb4d1ae75e8a6e026725aada1f032a098b46272617809585915bf43e5d24bb1386395ab9402fca11d80b6ecb4a8ae3f58ca68243fa5a3f65de215d65d", .None}, + {.Shr_Signed, "-df3b76f2c202d625c01d92275ce735bdbd6b23d6ccab33e5a3f7d822858caaa5f22bcd55c5671d6cc92184fed26a1dcc314c977fc2e9b8e171c9e6e7e0de8f6efc7aed8940357af80427455f711828ef2da6930d116f9340db90b4859214080f640d2e294a9e4d40251564b74ac14fb68dbdb5a8a607bf34257496ffbb9fdac8ac24613aecc4fd2c5dbd4ebbb0d79904f84e351dbbaa0f6a11753b7c2a900fcf2bd9ddc6a5e311c2e73207db87f9936a14d8d7d8fb572c1917149e0455a419c60726f6c65d5b2f12ba1f028c82af8ed26a7f2fb13c40384190dcd745d796cee0d11d7a8df7fd2b36032dc6c6f420ffa12d8afa03e4288b57c83a81ea5f1bfd13bf59e01607993aa40fae696f1ad374921dc8ef8b57022b93aa31a78235624b77a7c692b6724fa5effc4f4c7773e44f120087141b3b2fdc85582ece879de87968a19973065bc4bee29dc34773d863bd40f8df9588925d8dbd4b557b6f3266ae84997b7e18560f74469ba2766d1a42a122d8bc5ebcfee3d6ac940619b9661f5a09977ba57e7cc48b88c26dec2f1393f889da384c398aab3ea6fd7162aeb88268fe427c038233dfb8a412e4c4e2b37024ae59ec3df17c0ac380f329746c6e6006d147cf1789b772fdbb245ecd36d00a4b9eb797e8284125fc043882220e5d3b09e754c31f05231dc24d1e3e31fa5ab45a5e971bd12ea2aea90b363b5f98b9480945", "48", "-df3b76f2c202d625c01d92275ce735bdbd6b23d6ccab33e5a3f7d822858caaa5f22bcd55c5671d6cc92184fed26a1dcc314c977fc2e9b8e171c9e6e7e0de8f6efc7aed8940357af80427455f711828ef2da6930d116f9340db90b4859214080f640d2e294a9e4d40251564b74ac14fb68dbdb5a8a607bf34257496ffbb9fdac8ac24613aecc4fd2c5dbd4ebbb0d79904f84e351dbbaa0f6a11753b7c2a900fcf2bd9ddc6a5e311c2e73207db87f9936a14d8d7d8fb572c1917149e0455a419c60726f6c65d5b2f12ba1f028c82af8ed26a7f2fb13c40384190dcd745d796cee0d11d7a8df7fd2b36032dc6c6f420ffa12d8afa03e4288b57c83a81ea5f1bfd13bf59e01607993aa40fae696f1ad374921dc8ef8b57022b93aa31a78235624b77a7c692b6724fa5effc4f4c7773e44f120087141b3b2fdc85582ece879de87968a19973065bc4bee29dc34773d863bd40f8df9588925d8dbd4b557b6f3266ae84997b7e18560f74469ba2766d1a42a122d8bc5ebcfee3d6ac940619b9661f5a09977ba57e7cc48b88c26dec2f1393f889da384c398aab3ea6fd7162aeb88268fe427c038233dfb8a412e4c4e2b37024ae59ec3df17c0ac380f329746c6e6006d147cf1789b772fdbb245ecd36d00a4b9eb797e8284125fc043882220e5d3b09e754c31f05231dc24d1e3e31fa5ab45a5e971bd12ea2aeaa", .None}, + {.Shr_Signed, "-19b0f717d0e2e1ea18be952473dcf64701dbfe308c89b5643e1007e0973cb3ac9da483ccdc7e829c678d1de7b28ee25795fcad82f43f54465dbcc0cdb75b75ed83cc9779837b5fbafb04fd418701ce521b3bcd2db71a6f52b2fdb1e1ef4183245adba9af5fda7bcc16362dd36d0d6eb5c753c828f10849a51c1d6bbc486bc0d295ae0cbfd1d72059f3c68f7fd9b3306692eeb11b8495e63e03a4c643aeca4321f514ce0ada3deea92328779fcbff6a17595d08ba4a6fd37b364ae9749ffcedc869d863ad69d2c4bbdec095f8e5e68ef49160c86d5e414712e7d2454bcf8d055ba54979826475b040f70346511ad7f43443dad4926700a6438428bf10079d135e4c9e9d217f5c7372954193c34274818e9ee6eecc34c8e22cb572ab8748b280994260801420fed7550753b4b92fbbcce007e0bf382668293881e090adb5cdd1293c384a81ed86b98957535e6facd63350028f1600572b962e059445dd1e6b8247498208d28de61d0c1344f96b67c7608f477944f686ab5925820fc22127d4349f9249a49cee88b0f42277273248b661de9b35fb7bb4775535c3dd02575fceffd078200fff2e8bdc7d44e29878f0a7244b068e3b375203c31209ad14c858e51bc242ea1a35ec6bc6a05c803d0a14c3822a19d371eddcc4e172180c221faef05d25002ec518b4e9d0c96336f4a19916556986b750641bb1abc89c15583895ccae5b", "55", "-cd87b8be87170f50c5f4a9239ee7b2380edff184644dab21f0803f04b9e59d64ed241e66e3f414e33c68ef3d947712bcafe56c17a1faa232ede6066dbadbaf6c1e64bbcc1bdafdd7d827ea0c380e7290d9de696db8d37a9597ed8f0f7a0c1922d6dd4d7afed3de60b1b16e9b686b75ae3a9e414788424d28e0eb5de2435e0694ad7065fe8eb902cf9e347bfecd998334977588dc24af31f01d26321d7652190fa8a67056d1ef75491943bcfe5ffb50bacae845d2537e9bd9b2574ba4ffe76e434ec31d6b4e9625def604afc72f3477a48b06436af20a38973e922a5e7c682add2a4bcc1323ad8207b81a3288d6bfa1a21ed6a4933805321c2145f8803ce89af264f4e90bfae39b94aa0c9e1a13a40c74f7377661a6471165ab955c3a459404ca130400a107f6baa83a9da5c97dde67003f05f9c1334149c40f04856dae6e8949e1c2540f6c35cc4aba9af37d66b19a801478b002b95cb1702ca22ee8f35c123a4c1046946f30e8609a27cb5b3e3b047a3bca27b4355ac92c107e11093ea1a4fc924d24e7744587a113b9399245b30ef4d9afdbdda3baa9ae1ee812bafe77fe83c1007ff9745ee3ea2714c3c7853922583471d9ba901e18904d68a642c728de121750d1af635e3502e401e850a61c1150ce9b8f6ee6270b90c06110fd7782e928017628c5a74e864b19b7a50cc8b2ab4c35ba8320de", .None}, + {.Shr_Signed, "8edc6878ed317c9f61dbcb4c6d9a18e1c768e2f8ab8ffe2a59762007f0b1db4f8ad50af30a139ffa026ad0cba0c2fbb931303ae530576eb78fd858887531e1a2c980c54c562252b4e256cca176fbc59339f50f9b528731b7c87f5d518965fef4a912ff8d01c6553c20f7f29453eb195fd76502954e22aa929bd1b211c00dd7378f42e698638ac98312149df0d3c653b4a31b751e5832502e3a81bdd6603329af90dc2aba8a517b8f8115936359643f6eab84c465eeccbbb6b6f1e2de21d40b90cfbeed0fe44357cd27098d5ec952291ee6b747b0675052e22aaa113c443396d5b0385840c930460480806e2c46250434e41623081d7d904beb04f8e514116cdebe26c413c1454b401aee720d0fcd33bab1f35abdadbeef77084dcc9399f01e58654b3983d5c4180227848fc5b1510de788b61ae0e0d88e4cf3e269c7e27b060e70c90748294badf1549d90094d3bc012195dff4d49d1bd2356f11b0b14d145cfa5ca7bc573a2467a076cf10abde17bb54254cbf25c6c972031f03ab81a1fe05796f318449df270d3a94e33c5810b3f4363492d0073fe59add4ad86f9fb60ea2d9c4d393d6dc34308fd65557e06a4dd089b5746bc0f64b2f21f2828d6afa1d80912be223e96b85f650dcaaf1c3d8ef34ea9f4e9f3125ae7baa2d1e315fa1c789b07bb4fb5fbbec875e742b5b88517ca509f72918c407b13b5b35b65ca6df7e133", "9", "476e343c7698be4fb0ede5a636cd0c70e3b4717c55c7ff152cbb1003f858eda7c56a85798509cffd01356865d0617ddc98981d72982bb75bc7ec2c443a98f0d164c062a62b11295a712b6650bb7de2c99cfa87cda94398dbe43faea8c4b2ff7a54897fc680e32a9e107bf94a29f58cafebb2814aa71155494de8d908e006eb9bc7a1734c31c564c1890a4ef869e329da518dba8f2c1928171d40deeb301994d7c86e155d4528bdc7c08ac9b1acb21fb755c26232f7665ddb5b78f16f10ea05c867df7687f221abe69384c6af64a9148f735ba3d833a829711555089e2219cb6ad81c2c2064982302404037162312821a720b11840ebec825f5827c728a08b66f5f136209e0a2a5a00d77390687e699dd58f9ad5ed6df77bb8426e649ccf80f2c32a59cc1eae20c0113c247e2d8a886f3c45b0d70706c472679f134e3f13d8307386483a414a5d6f8aa4ec804a69de0090caeffa6a4e8de91ab788d858a68a2e7d2e53de2b9d1233d03b678855ef0bddaa12a65f92e364b9018f81d5c0d0ff02bcb798c224ef93869d4a719e2c0859fa1b1a4968039ff2cd6ea56c37cfdb07516ce269c9eb6e1a1847eb2aabf03526e844daba35e07b259790f94146b57d0ec04895f111f4b5c2fb286e5578e1ec779a754fa74f9892d73dd5168f18afd0e3c4d83dda7dafddf643af3a15adc428be5284fb948c6203d89dad9adb2e536fbf0", .None}, + {.Shr_Signed, "e07316fc7d049b5edd2c993b89395eb55fa375e8b1b68fd524f4eb6dc6f820e0aecc1f87c5406337aec306e459ba0cae642705c816cd279ffb2b545ba6094549bee361b3e85f2a195767835a1581d1f650d7344f7fe0c265cb606254e55d473474912082897154df703fc174f2aa07c049b3a15f3a30fff363304c631e660d15f327f95bf7e2702ff62f02ef16e1c76aaa26e7cdfce76936e2c085d042c58e57667e54e49b32e3c35444136cfc26cf6436986c18a5dc62105f6be15019852c755f4b8d6a47b0db3c2494b56d2952ae4486664c80b00e1ecd32089a2494705a761f7a152bec58d9579452b3a6a11b20eb319120bd72cd2082f2941c0f9acf14a102433f8f0d69366cef8026f350927a5370f6ef4917bb1454ccd21c90900dd6a62efea1373a5013f3c3a074214b150b95e73aefaa1fc23899bdbab8167d6a4dd4af15ab5cf80de1f32bef40297469e08b0ba60bbd27e2605adc1dbadfd1e702c7a4044c8ec2f824f83dae91c7526d78b3f13babd76fa578631e1080e4b6a4fdd15ece969d37e7af31dfc4ed51230711bc9c873c9207ef68875b7200c71a4120a62e5d3b7d37dbfab6e7a04a66c6e7aaa43cd80e01c8a30d715c2bda6168eb4705b3beb6791f43c0376a0a5b49d0ea7b051aac5412f33f7da9fd0f95a0c32f532eadbc5307879d91ef0325736ac838ca0aba950d5fafbb2dcd803220524a1a30af", "46", "381cc5bf1f4126d7b74b264ee24e57ad57e8dd7a2c6da3f5493d3adb71be08382bb307e1f15018cdebb0c1b9166e832b9909c17205b349e7fecad516e98251526fb8d86cfa17ca8655d9e0d68560747d9435cd13dff8309972d81895395751cd1d244820a25c5537dc0ff05d3caa81f0126ce857ce8c3ffcd8cc1318c79983457cc9fe56fdf89c0bfd8bc0bbc5b871daaa89b9f37f39da4db8b0217410b16395d99f953926ccb8f0d51104db3f09b3d90da61b062977188417daf85406614b1d57d2e35a91ec36cf09252d5b4a54ab91219993202c0387b34c822689251c169d87de854afb163655e514ace9a846c83acc64482f5cb34820bca50703e6b3c5284090cfe3c35a4d9b3be009bcd4249e94dc3dbbd245eec51533348724240375a98bbfa84dce9404fcf0e81d0852c542e579cebbea87f08e266f6eae059f5a93752bc56ad73e03787ccafbd00a5d1a7822c2e982ef49f89816b7076eb7f479c0b1e9011323b0be093e0f6ba471d49b5e2cfc4eeaf5dbe95e18c78420392da93f7457b3a5a74df9ebcc77f13b5448c1c46f2721cf2481fbda21d6dc8031c69048298b974edf4df6feadb9e81299b1b9eaa90f3603807228c35c570af6985a3ad1c16cefad9e47d0f00dda8296d2743a9ec146ab1504bccfdf6a7f43e56830cbd4cbab6f14c1e1e7647bc0c95cdab20e3282aea54357ebeecb7", .None}, + {.Shr_Signed, "ceaeb4dbde11c22813575eff8e22d6c723a1f8eded6b122226f30cc4146a9799d02067ea65a7bd6938544f3488bde1dc3c29adf9063fa078829afd8ae72883e35836c54c26b8a4293e89c9bd712581f6d831f3948d88a2504e6a021faf923b3b21fffdfda1e07ad9522a1ccbbdacf41a8a125e11b3ee57c455371e5cadef448bb2307d0674f38e2c029a404bb7d90ed619a4dcc43c1a79a7eb9049747bb168a05effdb15bd2892af46ec4e66375db28147b4a131b262fbf08d1953cb4e5666b71d3f0c919f478627d8b0925def9fac777919736122b76b03752ea68d9f2452c738cab9d18d66a002649ee831ca8af4c15ff19cb6e2ae3ca9eb20e0ee0f64c52163844bda7ccb41ac609945e5613c46c6083113f31b3a61b9a157b9dfd8b6de9aded039ca7b80779da0d4ba36eabd4574ff15c97c37302110620f7cbca46c9f2c3509b2f7d6a94a9f227f43f8f401868efbf9bd7ab3b838f7dc3bfaa6b103da500f639fb9a468e3061fdfbabe39b2208f7490ba831554082488aeed8076394076671b934a1fcd1522f0d398ae6ceb6fb7005e25c33c19e448e6799ffb4810faa7b7e15b36be00a32f8ec30038ad94f31235799ab08bae5068a54e99923293fa613569b78f62f9d9f467f6a59cb662b829de46c8bf3ec79112811bb0d2f628092b49ce86047cc31f162fd7dacc72ba59f57755480ed6971c5ee3098e2c7a9626", "51", "67575a6def08e11409abaf7fc7116b6391d0fc76f6b58911137986620a354bcce81033f532d3deb49c2a279a445ef0ee1e14d6fc831fd03c414d7ec5739441f1ac1b62a6135c52149f44e4deb892c0fb6c18f9ca46c451282735010fd7c91d9d90fffefed0f03d6ca9150e65ded67a0d45092f08d9f72be22a9b8f2e56f7a245d9183e833a79c716014d2025dbec876b0cd26e621e0d3cd3f5c824ba3dd8b4502f7fed8ade944957a37627331baed940a3da5098d9317df8468ca9e5a72b335b8e9f8648cfa3c313ec58492ef7cfd63bbc8cb9b0915bb581ba975346cf9229639c655ce8c6b35001324f7418e5457a60aff8ce5b71571e54f590707707b26290b1c225ed3e65a0d6304ca2f2b09e2363041889f98d9d30dcd0abdcefec5b6f4d6f681ce53dc03bced06a5d1b755ea2ba7f8ae4be1b9810883107be5e52364f961a84d97beb54a54f913fa1fc7a00c3477dfcdebd59dc1c7bee1dfd535881ed2807b1cfdcd23471830fefdd5f1cd91047ba485d418aaa0412445776c03b1ca03b338dc9a50fe68a917869cc573675b7db802f12e19e0cf224733ccffda4087d53dbf0ad9b5f005197c761801c56ca79891abccd5845d7283452a74cc91949fd309ab4dbc7b17cecfa33fb52ce5b315c14ef23645f9f63c889408dd8697b140495a4e743023e618f8b17ebed66395d2cfabbaaa4076b", .None}, + {.Shr_Signed, "-b5779dd95282ea0cd3d569f9ab14b281ceb230b226ff27c55ddc2ca531481ec9b2f96049fd17c2137737c4c34d22a0a3088fd4b1c6bd8f1c975ad210b10014614c1560d4cd903f905d323d29b2a12d3d28d1a40e2d5154162fca15652a5c44a7fc107c0302ff1a05ccc017892e4b09bde0fa72dd081999abcf1460062855e368bcd8e278ac0d576f70a6332b116cc10eaf221e5fbeae3cc536d4b1f9402cd7e470b855d8fe32212c42ba1c37b6d749a21f38f2acd16d92ab5e460e27f6b87585b942fa5938e2186d730e437a78e7342799db232bb9893515f508a52944f81cce01e5a3246507dad81aeefd8a17ea3ad76422b8752feb4437fe0df43f0f427e8122b592f3b64eac4a1c2474e206597c5e758e09a7bf97cb2ae6989ecb3de05c2ca051158429cac323f4e9321695a1d282892d95138245d307eb04d469ad3e534356d1ee31e6ce51a94da3b8b1ca117a0f8ffadf74532197ea1272baeda5cb962fba62a98ae14bb14af051ff933b340919ff1d7c4cdab41fa21516955d6ef5aef78e6f2277f67803d7b7f5ea66d8dd39c54dba7954d00675a7527b3244b7b5b31e0afcaa9e18cd97295d15206483fd878decb7ba751447265388577a9a5551c3ce9b18bd44f8389b5ad91d5b9232749667a1d8b08e4615b80690bc7ffd820a842cae1597a593871a0b89fa003bfd283a476b97a99dc8a6a51271a41c410739694", "a", "-2d5de77654a0ba8334f55a7e6ac52ca073ac8c2c89bfc9f157770b294c5207b26cbe58127f45f084ddcdf130d348a828c223f52c71af63c725d6b4842c4005185305583533640fe4174c8f4a6ca84b4f4a3469038b5455058bf285594a971129ff041f00c0bfc681733005e24b92c26f783e9cb74206666af3c518018a1578da2f36389e2b0355dbdc298ccac45b3043abc88797efab8f314db52c7e500b35f91c2e15763f8c884b10ae870dedb5d26887ce3cab345b64aad7918389fdae1d616e50be964e38861b5cc390de9e39cd09e676c8caee624d457d42294a513e0733807968c91941f6b606bbbf6285fa8eb5d908ae1d4bfad10dff837d0fc3d09fa048ad64bced93ab1287091d3881965f179d638269efe5f2cab9a627b2cf78170b281445610a72b0c8fd3a4c85a56874a0a24b6544e09174c1fac1351a6b4f94d0d5b47b8c79b3946a5368ee2c72845e83e3feb7dd14c865fa849caebb6972e58bee98aa62b852ec52bc147fe4cecd02467fc75f1336ad07e88545a5575bbd6bbde39bc89dfd9e00f5edfd7a99b6374e71536e9e5534019d69d49ecc912ded6cc782bf2aa7863365ca5745481920ff61e37b2dee9d4511c994e215dea6955470f3a6c62f513e0e26d6b64756e48c9d2599e8762c2391856e01a42f1fff6082a10b2b8565e964e1c682e27e800eff4a0e91dae5ea677229a9449c69071041ce6", .None}, + {.Shr_Signed, "-e8f1d5e73ab348b2726aff666140a673cf06361ff6cda297601c25e6369af2b2145fc15d028596ab73dfcd0440670f0b1acec2bd16cb85d7b6f8e6a19187e50e40b7b9cfadc231c1eb2d846756c4fc05ec2f17afb63359292166ede012fa7e4f069515445a6143c4f042df5b95431f704acd9d511446349a248338cdece445db2d677e08d7a3050130c2337759a1fc951e6a8871934e9af9a62d15000227614c1d49c83a55a776a7469b8b53b23a14052ee741b42ec39a75c0c490dae9f525ef79fe3bc7112b32470e1de75607021e30a6da069387a7b9e11b7ed7160e5fbc4902de4ab60edc0caf9e8da1de433d85a64a9550ebbfa48639127ff46804f39886cff9467927f8f755ede7453e233a4be5084078c591633be92672a4c09f117602a9302330a92ffa8d9193a6ed39fb685455cc646e7bd58e8d081e7c758dced9718ad1be3099ca8049521284b2eaf4acea89004041f085e2f5550e98480e96c35df85495e11c2c36713f79c238e45dc77252976a2e3386e55f7d812a8ebea7f4d406baaae50584fb3a0a1eeaa5d66451102da357ae704146b1e70a8b91b6d4c9a7bcee56d6aaecb863ad77ee7be8d7f25c4875c5d47829fa1168907fcffc84490acf78fe0628a19c3ba6c035b31e40db697df707458fb69b4e48e8a4bb44288f329818240c43d7d5b78bcbf89b9a269a92d894cfe143fa54303454b9cacc67517b", "1f", "-1d1e3abce75669164e4d5feccc2814ce79e0c6c3fed9b452ec0384bcc6d35e56428bf82ba050b2d56e7bf9a0880ce1e16359d857a2d970baf6df1cd43230fca1c816f739f5b846383d65b08cead89f80bd85e2f5f6c66b25242cddbc025f4fc9e0d2a2a88b4c28789e085beb72a863ee0959b3aa2288c69344906719bd9c88bb65acefc11af460a02618466eeb343f92a3cd510e3269d35f34c5a2a00044ec2983a939074ab4eed4e8d3716a76474280a5dce83685d8734eb818921b5d3ea4bdef3fc778e2256648e1c3bceac0e043c614db40d270f4f73c236fdae2c1cbf789205bc956c1db8195f3d1b43bc867b0b4c952aa1d77f490c7224ffe8d009e7310d9ff28cf24ff1eeabdbce8a7c467497ca1080f18b22c677d24ce549813e22ec0552604661525ff51b23274dda73f6d0a8ab98c8dcf7ab1d1a103cf8eb1b9db2e315a37c6133950092a4250965d5e959d512008083e10bc5eaaa1d30901d2d86bbf0a92bc238586ce27ef38471c8bb8ee4a52ed45c670dcabefb02551d7d4fe9a80d7555ca0b09f674143dd54bacc8a2205b46af5ce0828d63ce1517236da9934f79dcadad55d970c75aefdcf7d1afe4b890eb8ba8f053f422d120ff9ff90892159ef1fc0c514338774d806b663c81b6d2fbee0e8b1f6d369c91d1497688511e653030481887afab6f1797f137344d3525b1299fc287f4a86068a97396", .None}, + {.Shr_Signed, "-1d8da18ba02af2a64476478c611af6b6dbdbce4064371ab2dbde2ec1a0a7e7e083b6d6cbfca5ff681871dbf84b70cbfe4752123c6d0feb9bbe4aa970be8fe93500cb26cd6eacaa88a62702186c731beb5c70cf53625147afc0177e95485f2e83bd2eca51e3c6e322ffc80955e45ba77d1f79fff8f901cae05a18ad1edbf0a0e329e7dc19da7b0152aedbf236cde38a2ac7441ca2b49516fe3422885d4a8fbf565c77fe6bf4010dfc0173801d78aec4dee60b19e4c2ef37971289808be636739704f26e4e6b72a16c6ca46d084b0ad78bbd0e08a6bc636eb5c90e38741632637036c3e3563205168f7b564dbe4ff6b14c7efe38a892fab7b8bd9b3df096e3f1e0f5a6d607b286dbca64d8e20badceb06c2f8fcf25ecb1ee06a63926a022f38603b18d22387476ad74f6901f5ba3932fed4db34378519dba033a9d71a6629d26f0d2a8b6fd8a7359a03a75c7ce2e44acd3833e14ef5e1c162e307653d0bb83de8cab754c24baac0f2b18c874028133c72250c4b1f432cd31c83f8f253b26bfe3b0c63bf5c0e1e31688f6c93755a646534cccefca5befb4b1f658d85b69eff433550f9493260c0701e7d3ebc14aa65e3d44dd3f87eadcd8a336b8d493dae1abaa7f5a806569ecb1a9e8f2f9691b679a21446302fdeb3872b0ce69e0ee9e08fb83099d5b1a6fd0eac7af461ce5f9c90237f75c286037dff74a2ee45357de7d1724db", "4b", "-3b1b43174055e54c88ec8f18c235ed6db7b79c80c86e3565b7bc5d83414fcfc1076dad97f94bfed030e3b7f096e197fc8ea42478da1fd7377c9552e17d1fd26a01964d9add5955114c4e0430d8e637d6b8e19ea6c4a28f5f802efd2a90be5d077a5d94a3c78dc645ff9012abc8b74efa3ef3fff1f20395c0b4315a3db7e141c653cfb833b4f602a55db7e46d9bc714558e883945692a2dfc684510ba951f7eacb8effcd7e8021bf802e7003af15d89bdcc1633c985de6f2e25130117cc6ce72e09e4dc9cd6e542d8d948da109615af177a1c114d78c6dd6b921c70e82c64c6e06d87c6ac640a2d1ef6ac9b7c9fed6298fdfc715125f56f717b367be12dc7e3c1eb4dac0f650db794c9b1c4175b9d60d85f1f9e4bd963dc0d4c724d4045e70c07631a4470e8ed5ae9ed203eb747265fda9b6686f0a33b7406753ae34cc53a4de1a5516dfb14e6b34074eb8f9c5c8959a7067c29debc382c5c60eca7a17707bd1956ea984975581e563190e80502678e44a18963e8659a63907f1e4a764d7fc7618c77eb81c3c62d11ed926eab4c8ca69999df94b7df6963ecb1b0b6d3dfe866aa1f29264c180e03cfa7d782954cbc7a89ba7f0fd5b9b1466d71a927b5c35754feb500cad3d96353d1e5f2d236cf344288c605fbd670e5619cd3c1dd3c11f706133ab634dfa1d58f5e8c39cbf392046feeb850c06fbfeea", .None}, + {.Shr_Signed, "-aa97e7f4ecbd16d1d075bbb1e1553194a117d24c61e7984fd68bf8e4738f6a1151dbb57ce56017d78342f560e0e05f97b6a0c4fc80b2fa5d78f878530d21202f393cabe7c6628f887f67fb55e78c7bc3383685391265270102ed93286977c96b5b1e181b9de831413bb273f6f6662a58c5cea0dd28f8754091dc788f0ca7ea0a10eeee8f33d5cbae1d80be5eda371952472b7f3dc39838deee4a1a70c212fd507dde97401a778aeee05388df4830aa9dd142a066e113f69cee3da20ea87b01ff7ef1999327401e256f83e31ed175ee367720ea7c65f8a790bab990c28de50e93c488a05424144abff29a53e5b70a9ba4d3beb4134d9544c404f27d8fa9ca5917aa78937c9caee880136db459f2b0c27f6aa22fb3031e5f1a9770d1e0b9bbbb65fb744474d43629dc20193ec7f517250ce0d0431731113870589a76d6ae6331a1f9e0c4ad770c7bd1933947f708e9de34754b191333976977456ff8d049ef3e9b945358e075429147b786fb41f45178b7a5d07863e0cd9334c14039cb770f6899bf68e6a37c546e51ffc2be2a4c2f4a664a7bc41492333c2c194aa99d3c8e93b8884848aab51d692c77af642b4f6ca52c05fd06be5e16379a903ba03e0cd97e855bf4f17bc0982f7e3a03a356f71a5e8f46eb600aa62f6540e5c31563e6f984d48d2a3bb8a75c0656764a12b51d6d000c04751dfa6b4a89d53ebc24326d5275ca", "48", "-aa97e7f4ecbd16d1d075bbb1e1553194a117d24c61e7984fd68bf8e4738f6a1151dbb57ce56017d78342f560e0e05f97b6a0c4fc80b2fa5d78f878530d21202f393cabe7c6628f887f67fb55e78c7bc3383685391265270102ed93286977c96b5b1e181b9de831413bb273f6f6662a58c5cea0dd28f8754091dc788f0ca7ea0a10eeee8f33d5cbae1d80be5eda371952472b7f3dc39838deee4a1a70c212fd507dde97401a778aeee05388df4830aa9dd142a066e113f69cee3da20ea87b01ff7ef1999327401e256f83e31ed175ee367720ea7c65f8a790bab990c28de50e93c488a05424144abff29a53e5b70a9ba4d3beb4134d9544c404f27d8fa9ca5917aa78937c9caee880136db459f2b0c27f6aa22fb3031e5f1a9770d1e0b9bbbb65fb744474d43629dc20193ec7f517250ce0d0431731113870589a76d6ae6331a1f9e0c4ad770c7bd1933947f708e9de34754b191333976977456ff8d049ef3e9b945358e075429147b786fb41f45178b7a5d07863e0cd9334c14039cb770f6899bf68e6a37c546e51ffc2be2a4c2f4a664a7bc41492333c2c194aa99d3c8e93b8884848aab51d692c77af642b4f6ca52c05fd06be5e16379a903ba03e0cd97e855bf4f17bc0982f7e3a03a356f71a5e8f46eb600aa62f6540e5c31563e6f984d48d2a3bb8a75c0656764a12b51d6d000c04751dfa6b4a8a", .None}, + {.Shr_Signed, "-15ac358659b6537def4c80d2310d0755051cec2fcd06ea71a9e8dc7dcf9ee124217d5585d9fe962b9dd10f0b6f21d2b0c9c231671e40db5cf8e32dce34c733cb50a7ea6566a03899e52b102ae37247cb65250c234e16f8fa87da849334191a009867256a5e3c340a0078902f62b4a84285f5c37e8e005e724260c94a307f9fdab30973a3c5a974e0187cb16c89d9af3d861a046e03d32192972c4396ac95ebe8551f439449d0b8039744bfca2de354671fc5852443f6dc0aed9a8d8add0454fe95dd141913432a1128bc2de2be9403d4c776642465722e88635e092e03ec8da1944eb0544623bad7b5ba508819210cd4731f593baa18c4070cbecf06dcd3a0dec5a6944510d475afcef9bb814188abfae450f298ac908eda2c5c34632563bbab10cd757e6f056d0417d01033f89b847fcaefd5abc8d3fd428bb2e7d887102971a637d7e5ec6fdccd3151175d4eb3bae1ff6764494778c0bc186def570ce3e87cddbc506c423cf7f3a60dc342b7240af6a8885b98dd77e0e227332314a277b9dcb7799122825a486420c3ebb334c3f48997712011e72dbcb4e14c56c86bd511eac79de0c02cf612693f7bef268a79932941f0e781fd5af1313295ca519857b7a83022bd385fb14732a17ef4e8161ca2e82bf88f945bff51b779d7b58ec2c03400a029fec9818c2d0687887efc8c44e09785867b0864c08345e09fc99fb819604f", "19", "-ad61ac32cdb29bef7a64069188683aa828e7617e6837538d4f46e3ee7cf709210beaac2ecff4b15cee88785b790e95864e118b38f206dae7c7196e71a6399e5a853f532b3501c4cf295881571b923e5b2928611a70b7c7d43ed42499a0c8d004c3392b52f1e1a05003c4817b15a542142fae1bf47002f39213064a5183fcfed5984b9d1e2d4ba700c3e58b644ecd79ec30d023701e990c94b9621cb564af5f42a8fa1ca24e85c01cba25fe516f1aa338fe2c29221fb6e0576cd46c56e822a7f4aee8a0c89a19508945e16f15f4a01ea63bb321232b9174431af049701f646d0ca27582a2311dd6bdadd28440c90866a398fac9dd50c6203865f67836e69d06f62d34a22886a3ad7e77cddc0a0c455fd7228794c5648476d162e1a3192b1ddd58866babf3782b6820be80819fc4dc23fe577ead5e469fea145d973ec438814b8d31bebf2f637ee6698a88baea759dd70ffb3b224a3bc605e0c36f7ab8671f43e6ede2836211e7bf9d306e1a15b92057b54442dcc6ebbf0711399918a513bdcee5bbcc891412d24321061f5d99a61fa44cbb89008f396de5a70a62b6435ea88f563cef060167b09349fbdf793453cc994a0f873c0fead7898994ae528cc2bdbd418115e9c2fd8a39950bf7a740b0e517415fc47ca2dffa8dbbcebdac761601a005014ff64c0c6168343c43f7e4622704bc2c33d84326041a2f04fe4cfdd", .None}, + {.Shr_Signed, "-37d8e27c58f7035293428173ca838668ad91d568148976480f26b1ddeb8f144ad4a3dd171123211a0ca04e1c541a09821184aa50e78237981f55064961d4140f87181a9cc2e2739c343b0c20cb1f8789e37d5e9a6198d329da2c2f9d8e5a1880369619da8d0f9eda142e308103fd18c86ac67adae1fafb52b508e48398371886b554fe6b463170f850ead4cb8c6b4f77384d02f74022dc1ff80bf41682c363f7d1a720e612db58a2c46620d5bba0e534a67d5e684b88dec766fc5493fe260a2109ea3b34b3787d9963fb52caebc2c0d3e098ebea4b1b2276e2b75ab75edfd0c183f157148f050484221b937ad8df587c560fb4a28a1a2221904737a0f7965f2182aa377dd2d5b5d87321125adef96e9d77a1c75557b7b06e02bbb83eabf85b6ebbfa37a53f3ec729c00423bf46f531d8383636ff1bf18586daed15a58d3e5058c1b90c10e7387d30548516e2a9471b7c2f11d76e56867e1cf5f0ba57ce93f4a23bd3e52a78fe520ade71107e723b24dff09c02dc4e5d2a792fcfc730da3c1e33e7872bb0c31e400e8cfce19952b8bab4be06107cffc3369e263e90b2f638c8b31df0c956446919357d9d060e56c0e849c5ed0a647fb4df1c7aa376262504efac97d20df14e9eb9feead5bdebf70d59a41461e98af0f7ecef0fd9bbc2fb85deb2cef02ade00f60544bea78bdd2c45ab04e8626bec01c06cbe778a5c79b7886ce8", "4b", "-6fb1c4f8b1ee06a5268502e795070cd15b23aad02912ec901e4d63bbd71e2895a947ba2e2246423419409c38a8341304230954a1cf046f303eaa0c92c3a8281f0e30353985c4e73868761841963f0f13c6fabd34c331a653b4585f3b1cb431006d2c33b51a1f3db4285c610207fa3190d58cf5b5c3f5f6a56a11c907306e310d6aa9fcd68c62e1f0a1d5a99718d69eee709a05ee8045b83ff017e82d0586c7efa34e41cc25b6b14588cc41ab7741ca694cfabcd09711bd8ecdf8a927fc4c144213d4766966f0fb32c7f6a595d78581a7c131d7d4963644edc56eb56ebdbfa18307e2ae291e0a0908443726f5b1beb0f8ac1f694514344443208e6f41ef2cbe4305546efba5ab6bb0e64224b5bdf2dd3aef438eaaaf6f60dc0577707d57f0b6dd77f46f4a7e7d8e538008477e8dea63b0706c6dfe37e30b0db5da2b4b1a7ca0b183721821ce70fa60a90a2dc5528e36f85e23aedcad0cfc39ebe174af9d27e94477a7ca54f1fca415bce220fce47649bfe13805b89cba54f25f9f8e61b4783c67cf0e5761863c801d19f9c332a57175697c0c20f9ff866d3c4c7d2165ec7191663be192ac88d2326afb3a0c1cad81d0938bda14c8ff69be38f546ec4c4a09df592fa41be29d3d73fdd5ab7bd7ee1ab34828c3d315e1efd9de1fb37785f70bbd659de055bc01ec0a897d4f17ba588b5609d0c4d7d80380e", .None}, + {.Shr_Signed, "e3df7d53616a91d97d4e05c44e7110c24e04d670270297c305e635b0328f239aa644bd245d9379ee5afcf0dcc96f271a411c1f930920ad61ac87ce587c301207ffcf62c6083bf52a71ef61f4e1cefa8cec667ca1eae75edfaa6c81fd93544426c8d2ad45339abf356595cb870097c6a1d389547542f7dc0808ad80214a0c7481c1a720eee494b58caf310c497d1916fe3e05b0f2a52e6fd9feae5c3f336d726c2e30cbb07870bc5c1723b76d45c43898ee3f2f555c8ed39a671203393306a15f8e11a437966591e49c7f12423bf3f2f60dc078a762b372e887535c47435d5aae80b0fdc990c6ed5f1fe782e77d911550941c0271b438d8bc6005acfda0bc433a1d7003f5798b9325fa2f9f887f5569cd231aaa69167a63042e285e6f0aa7dc5c95f758d164aca31fe0d02dd25f8779016b694e7b279657f4ee2131649a5718a5fe6d75ff3c1edbd78ba1da2b036bc8f5af3819315963f3ad36aee46858dca3abe755a9b83f3227da3b3bb648283576daca55191b5481f2cf7c09c05c94dc03aeb8e20b7c7599fd0c9fef22ba5e89a83dd5a8fdf95b6b2790ade852204dac7f2cd5dd2bb1f9a3aa61e3fa04c10b8c99d5ce99def84353efa254f260bccf9fdb55bb5a77f648c8bb4fb4de4ed3335aefd4e5dde619c2f56974f62e12e4cd411f72850cc7a9be64d25761a90b80a16fe912baab15ef5b70309d124e420b839fbcef", "49", "71efbea9b0b548ecbea702e22738886127026b3813814be182f31ad8194791cd53225e922ec9bcf72d7e786e64b7938d208e0fc9849056b0d643e72c3e180903ffe7b163041dfa9538f7b0fa70e77d4676333e50f573af6fd53640fec9aa2213646956a299cd5f9ab2cae5c3804be350e9c4aa3aa17bee040456c010a5063a40e0d39077724a5ac657988624be8c8b7f1f02d879529737ecff572e1f99b6b936171865d83c385e2e0b91dbb6a2e21c4c771f97aaae4769cd3389019c998350afc708d21bcb32c8f24e3f89211df9f97b06e03c53b159b97443a9ae23a1aead5740587ee4c86376af8ff3c173bec88aa84a0e0138da1c6c5e3002d67ed05e219d0eb801fabcc5c992fd17cfc43faab4e6918d55348b3d318217142f378553ee2e4afbac68b256518ff06816e92fc3bc80b5b4a73d93cb2bfa771098b24d2b8c52ff36baff9e0f6debc5d0ed1581b5e47ad79c0c98acb1f9d69b5772342c6e51d5f3aad4dc1f9913ed1d9ddb24141abb6d652a8c8daa40f967be04e02e4a6e01d75c7105be3accfe864ff7915d2f44d41eead47efcadb593c856f4291026d63f966aee95d8fcd1d530f1fd026085c64ceae74cef7c21a9f7d12a79305e67cfedaaddad3bfb24645da7da6f276999ad77ea72eef30ce17ab4ba7b17097266a08fb9428663d4df32692bb0d485c050b7f4895d558af7adb818", .None}, + {.Shr_Signed, "ff646e2a48db5d9b714d25a361d51eb9b4e751d3e6329bd1ba885daf2e4b39f4a53f86c47a4e65d5a1d1e8442b254a2bba3ff50f7e693051929222cfcb5c31c52cc0dda79b144b78054c7ab7cae0043f25e16e31331d0d5cf52ddef30775d600adb23d4a4ee69970a1a5af5c52720239b7ab8eb141f5577a2b46d98d2f0573c2233beaf1dfc4245c34a16f15b9e76e70c3eaf4259e4ac8b7d65505713f36401582a4bf485895a5f69ecf87e046b652b39aae3080e1d192df0d45a57fc8764d666543266ddb3f6fa71fe1f88969635d5e63918b33bccf00249f7af12d3634572902d6276c9d5d6abc933896096f00436d504a3db4b22e9e13143b694ac9f0788c357079b29de3b2c63a7da0a9b9ba4d62c89a51794654c11a8c19da2eeb63f3c10e4f91512026f520f7a273728a7730eb394258ad8ff8105b90ac8ede35a0aaade4f23db5ceacddfcaa2a82bb5a008933b4c6a68faf3864944d0284c0763d9e33d7fec3542bfb84370d027dec9b3af2b29087f1ba3d6e0d2ea1899f93932260279c5eb6f4bf060367c5c755d4b669fd36e120e44ac583a8902914c888b1dcdb931a94bd757b90a9bf1e12393468c9c2b9e926694cfaaf872b06ac321deb0544d4350af275a620d88d9c7c45d13916120652888c82ffe70cae4b74d43e1ff1dd77e4d847030b6eaef3804e7e2e9fe63cc72a95119fe51af5130310dbf4d0b56ca1", "70", "ff646e2a48db5d9b714d25a361d51eb9b4e751d3e6329bd1ba885daf2e4b39f4a53f86c47a4e65d5a1d1e8442b254a2bba3ff50f7e693051929222cfcb5c31c52cc0dda79b144b78054c7ab7cae0043f25e16e31331d0d5cf52ddef30775d600adb23d4a4ee69970a1a5af5c52720239b7ab8eb141f5577a2b46d98d2f0573c2233beaf1dfc4245c34a16f15b9e76e70c3eaf4259e4ac8b7d65505713f36401582a4bf485895a5f69ecf87e046b652b39aae3080e1d192df0d45a57fc8764d666543266ddb3f6fa71fe1f88969635d5e63918b33bccf00249f7af12d3634572902d6276c9d5d6abc933896096f00436d504a3db4b22e9e13143b694ac9f0788c357079b29de3b2c63a7da0a9b9ba4d62c89a51794654c11a8c19da2eeb63f3c10e4f91512026f520f7a273728a7730eb394258ad8ff8105b90ac8ede35a0aaade4f23db5ceacddfcaa2a82bb5a008933b4c6a68faf3864944d0284c0763d9e33d7fec3542bfb84370d027dec9b3af2b29087f1ba3d6e0d2ea1899f93932260279c5eb6f4bf060367c5c755d4b669fd36e120e44ac583a8902914c888b1dcdb931a94bd757b90a9bf1e12393468c9c2b9e926694cfaaf872b06ac321deb0544d4350af275a620d88d9c7c45d13916120652888c82ffe70cae4b74d43e1ff1dd77e4d847030b6eaef3804e7e2e9fe63cc72a95", .None}, + {.Shr_Signed, "-95b87472c99948baba5da5b3c87ec4c1770563ff22a337b6283bf621d9b4103182202d15660468cd9206f49a68cd96793d8e07b863b980c92a71fc7a3579f35bf2c8e81e5d2a8fe3ce1cb21f4cf88d3f6282fc83aeec6c7b035073d2a33877b9fd584d591f77233f9003c27f97885398c68e3be6d4db7a9e4d38b6e4151b046fcb5f7cd4f2f4b715d1d0e316a8a11d2380ab3dde0854d253ba3638bb20ff69ca0d1dbdcff29473190aaa7e3c6b1860df9d20a2c16403017479492ab6e2f6a740e75330e093c6fb2f2f7f6d3a885588fc12d59ccff4a7f216517648eb84855cb7e1ff7900f22081660385ba6054542dd0b4cf870e438f8fb18e0a73945c1f45f2c2f0a5f51448c29dc3a656ca4360ee01ab1f2d4032f91ad593d100646839eeaf5598cdf10fd306a147af12058763868b67de36833523a9e76fa645f2ff0f6572aa8654a3a84e2c47fb89d4f03a585b426d47a130c57922b5358d39d2e69e200bcc7b3e15ff2e51b97d11f4647d87fdca212fe3e3a9c8bac2e01b07a7c2a6da024bb310ac775d63c3c06de5cba002280dc28d924355ebae522f7d7f6507cb37af549525b035288115d57f295969ff21ad0eeaeb45c14b47310970227fb649b664feed7408667b58a6b1b1843b02c405fe148ce8957183e26fa3d3fa2f45a7c02d0050f5729a79588ef50282be4af606edb9a61a2bfb2c79a30c911ab75b33f5be", "66", "-256e1d1cb266522eae97696cf21fb1305dc158ffc8a8cded8a0efd88766d040c60880b4559811a336481bd269a33659e4f6381ee18ee60324a9c7f1e8d5e7cd6fcb23a07974aa3f8f3872c87d33e234fd8a0bf20ebbb1b1ec0d41cf4a8ce1dee7f56135647ddc8cfe400f09fe5e214e631a38ef9b536dea7934e2db90546c11bf2d7df353cbd2dc5747438c5aa284748e02acf7782153494ee8d8e2ec83fda7283476f73fca51cc642aa9f8f1ac61837e74828b05900c05d1e524aadb8bda9d039d4cc3824f1becbcbdfdb4ea215623f04b56733fd29fc85945d923ae121572df87fde403c88205980e16e9815150b742d33e1c390e3e3ec63829ce51707d17cb0bc297d451230a770e995b290d83b806ac7cb500cbe46b564f440191a0e7babd566337c43f4c1a851ebc48161d8e1a2d9f78da0cd48ea79dbe9917cbfc3d95caaa19528ea138b11fee2753c0e9616d09b51e84c315e48ad4d634e74b9a78802f31ecf857fcb946e5f447d191f61ff72884bf8f8ea722eb0b806c1e9f0a9b68092ecc42b1dd758f0f01b7972e8008a0370a36490d57aeb948bdf5fd941f2cdebd525496c0d4a2045755fca565a7fc86b43babad17052d1cc425c089fed926d993fbb5d02199ed629ac6c610ec0b1017f85233a255c60f89be8f4fe8bd169f00b40143d5ca69e5623bd40a0af92bd81bb6e69869", .None}, + {.Shr_Signed, "d1f289434ce4598b05914d7865478988fad3eeb28aa7d8b4edbafeec430722ce1876006d5967fd840e709a5382039a75f94976c76f5cdb5016e85c361e944e06d3d063a63a0fa37dc29e4e91ff12c39d4e2cef8216718092106d9cc7663be19ac86de42dc3754993b17c4ccbc544dc4e8fde0f3744a71b93a6199f6669243bed84afd6a3df2d55a11ad2bfea44ac11f206467587ab8a18cb59fd93936b52bbba87584e5f1eabedadb9457b6dcfa805b2a8c787f5ddd7a2dd1fb67f24f8c435974e8df0ae04ed739b603db3e9bcac8d5be311271130cfd22e145a4140b20cdb5cbe997cc7f5742498f5829b3a12d86158abc659c9ba3446f6930ebbb6ecb74ac33a68cd07f4f13961f49c1d3df918d24fbb7d5516dd83aaf9e78acd51989e7d9b48e895c369950ddf0e9c573796c3099d5d940ed2b537c0de444b59a4117df081c036346f337d585d8d27a71b80a6162d984bf7004fca7bea56bce23b1ba9f467b78e4f22b7e1fdb656361232848aa0c6514d3b9735db1f4bb03be91d364f08a08d248015adf51f4e80c8b1a3b241c225f97a4ab1a2398425354ce9d13b23815d0723c08c8a73fb9431c7897992eace70e975132b5a1d92ac5be1caccc56fa6205f95ff59677fab5b2befd21aabc7a2abc143da983af4fefaa69dd1c6e75360967634f8728597c7afee7a358588b87b82202003213312eac675fd9e4b62aaf09", "18", "d1f289434ce4598b05914d7865478988fad3eeb28aa7d8b4edbafeec430722ce1876006d5967fd840e709a5382039a75f94976c76f5cdb5016e85c361e944e06d3d063a63a0fa37dc29e4e91ff12c39d4e2cef8216718092106d9cc7663be19ac86de42dc3754993b17c4ccbc544dc4e8fde0f3744a71b93a6199f6669243bed84afd6a3df2d55a11ad2bfea44ac11f206467587ab8a18cb59fd93936b52bbba87584e5f1eabedadb9457b6dcfa805b2a8c787f5ddd7a2dd1fb67f24f8c435974e8df0ae04ed739b603db3e9bcac8d5be311271130cfd22e145a4140b20cdb5cbe997cc7f5742498f5829b3a12d86158abc659c9ba3446f6930ebbb6ecb74ac33a68cd07f4f13961f49c1d3df918d24fbb7d5516dd83aaf9e78acd51989e7d9b48e895c369950ddf0e9c573796c3099d5d940ed2b537c0de444b59a4117df081c036346f337d585d8d27a71b80a6162d984bf7004fca7bea56bce23b1ba9f467b78e4f22b7e1fdb656361232848aa0c6514d3b9735db1f4bb03be91d364f08a08d248015adf51f4e80c8b1a3b241c225f97a4ab1a2398425354ce9d13b23815d0723c08c8a73fb9431c7897992eace70e975132b5a1d92ac5be1caccc56fa6205f95ff59677fab5b2befd21aabc7a2abc143da983af4fefaa69dd1c6e75360967634f8728597c7afee7a358588b87b82202003213312eac675fd9e4b6", .None}, + {.Shr_Signed, "-226b67d0c6ba1e7b0e130344da64f62b2f3d49689cb0f06d082bab4a9873be6df950a5ef53e422a7efd7553fe0eb2a59af9ef9299a7fbee253eb9e9513cd15825e2e930ac475b93f9915c3b2d984e27bb232ab814163e49b2e4b8fee3d45cb3338b7c6d9581e0854787ac187b87aa4732af98aa018fe80c85eaa8435668aa5ebc670e29217f6f9cc2ff918cab2eefae3bdb795bca1f3d66c85050d88f297bbe4e45c785ddc25bd785aed07304ccce073d93416b81212c55db7c9f86db9521de37cdfc96b7ce255bab104f9671d006db90681aa4d25a1d9f2751d74b15f4fb9a1459394ea09e6a0a0e79069057adcbc925b0b4e18bd3cea1816db58b241aceb35f1f3269f9690362eafb0d3faca3899420741a20bb9d0381884e91a4ec4e39b4e7d5542d9ee9555f5cd5738e81146bbf7baa34fb0dae83aba7a186a345d100c73c61a237a653c0df192cf3dd8aa50a0ee2692cc87bc913dbadeeff1f090018970f2ac91bc76c5cc4c22428b1f75428e11d72951d696eca31231c621152e62dddbcf7267af605caeb816704864b1c860281253b9632547f5e39dff8ae385740a719f6d730f7d0047dc770dfc7860ea1fc7df418d430363e29686c70b5a72ed5bcd1502450fa9ccc9dda0d7bd6ba484bfeb916cfa9fd0e1062220ff34107ba94c47d61f7c2d37eb88325deda63cd3bb5eaa5ee0472d1788431327be0848544e4bd4", "3a", "-89ad9f431ae879ec384c0d136993d8acbcf525a272c3c1b420aead2a61cef9b7e54297bd4f908a9fbf5d54ff83aca966be7be4a669fefb894fae7a544f34560978ba4c2b11d6e4fe64570ecb661389eec8caae05058f926cb92e3fb8f5172ccce2df1b6560782151e1eb061ee1ea91ccabe62a8063fa03217aaa10d59a2a97af19c38a485fdbe730bfe4632acbbbeb8ef6de56f287cf59b214143623ca5eef939171e1777096f5e16bb41cc1333381cf64d05ae0484b1576df27e1b6e548778df37f25adf38956eac413e59c7401b6e41a06a934968767c9d475d2c57d3ee685164e53a8279a82839e41a415eb72f2496c2d3862f4f3a8605b6d62c906b3acd7c7cc9a7e5a40d8babec34feb28e265081d06882ee740e06213a4693b138e6d39f5550b67ba5557d7355ce3a0451aefdeea8d3ec36ba0eae9e861a8d1744031cf18688de994f037c64b3cf762a94283b89a4b321ef244f6eb7bbfc7c2400625c3cab246f1db173130890a2c7dd50a38475ca5475a5bb28c48c7188454b98b776f3dc99ebd8172bae059c12192c72180a0494ee58c951fd78e77fe2b8e15d029c67db5cc3df4011f71dc37f1e183a87f1f7d06350c0d8f8a5a1b1c2d69cbb56f345409143ea7332776835ef5ae9212ffae45b3ea7f4384188883fcd041eea5311f587df0b4dfae20c977b698f34eed7aa97b811cb45e210c4ca", .None}, + {.Shr_Signed, "-483b1608a7697312abab3bbbc09c6c1ed9e6f0fb946e0e84ac5905ea9d95c691ae3ea8cb2d07261447969bc05beaa1356eafa437c3f75449a922a0cfafcb5291ce07435405bf9a059c968d7cbc6c50e652a6a4acb6fc886e6900ad18ece558567bcdf3dfd2b8f9ed644bf3dbe01d788a5ba6c93f970a6e56dca83831befa69df61ec29f96fe5cb7bd1faf50067b6889bb18bf8dbcbd5c15f1ec540a1004fc840d932b55c92630c04304a3ad754207a12dd9b21024e76d569405b7894517b0a9c21a345faba63f4c96223a9833673ab6fa990caf1c479dac1a24fcd3db9f789e1a085446e655ec3920a749c057dd9d522ab8ab9fe3a8fe891fcfa357e9162b8b74b452bec8e0873b466002022200d8dcc4b4b9844527297540acb61d69dd32b8b00e7c1f20a01b43a9c155220208ba9e878468a4438a3f8573fb3a62b37692b3dbe2dad6c2996feb2702a06a3cc6099e415946b5a3a6b009e2c3ffc1e7d005ac268bf900a90df2f99a6c9947a66f2a47f3793704fb92562b1e22a7f5699633bb6d8ba79bc46a9ed06264dad8a122f5755b0e7f241bf363add8e932a6de0b3d272ac351451fc2e74bf722e3a3943ca4e2ccfd49957dda6c0c78c6fd0042525b785231158b84334b515a405f9af5cf1d182cd1f47109b1366077cd3497f2b0387ec05b2ceb36e80ef13ad13a5b22e7af7fe07a77d08939e013325dd15e969d530e1", "4", "-483b1608a7697312abab3bbbc09c6c1ed9e6f0fb946e0e84ac5905ea9d95c691ae3ea8cb2d07261447969bc05beaa1356eafa437c3f75449a922a0cfafcb5291ce07435405bf9a059c968d7cbc6c50e652a6a4acb6fc886e6900ad18ece558567bcdf3dfd2b8f9ed644bf3dbe01d788a5ba6c93f970a6e56dca83831befa69df61ec29f96fe5cb7bd1faf50067b6889bb18bf8dbcbd5c15f1ec540a1004fc840d932b55c92630c04304a3ad754207a12dd9b21024e76d569405b7894517b0a9c21a345faba63f4c96223a9833673ab6fa990caf1c479dac1a24fcd3db9f789e1a085446e655ec3920a749c057dd9d522ab8ab9fe3a8fe891fcfa357e9162b8b74b452bec8e0873b466002022200d8dcc4b4b9844527297540acb61d69dd32b8b00e7c1f20a01b43a9c155220208ba9e878468a4438a3f8573fb3a62b37692b3dbe2dad6c2996feb2702a06a3cc6099e415946b5a3a6b009e2c3ffc1e7d005ac268bf900a90df2f99a6c9947a66f2a47f3793704fb92562b1e22a7f5699633bb6d8ba79bc46a9ed06264dad8a122f5755b0e7f241bf363add8e932a6de0b3d272ac351451fc2e74bf722e3a3943ca4e2ccfd49957dda6c0c78c6fd0042525b785231158b84334b515a405f9af5cf1d182cd1f47109b1366077cd3497f2b0387ec05b2ceb36e80ef13ad13a5b22e7af7fe07a77d08939e013325dd15e969d530f", .None}, + {.Shr_Signed, "-a0dbb2222533353480e198cfb173d95a66360d3338acec31bf64e7b5fdb4117d6e84149c1240875b50de63eae945c4ee29d7fa6f3036c9d5f597ae3de8335de24498a040bae1248d2db9431563ac03077a1f997d01d96f284e72cd021668770a2fee6d0bd56c4e3285779b17eaed828ddee1a1d8e3a4987cb571180be06c6322beef9ddf430b517d1e8c6934bdabdaab1864dbf777a90d8b38621c6ead632b35ec9cdd77c3a695c4100fbd30cd12f2c3afd6492cf29f0a1acf850023c10acebaaf29144740ebecb89aee12d3cf99d33abbd80157ebb9d8e307a6a06ed8e61604a1ff08f7cc36f9f65625deaf6136621303797f57079393817bf3a9fb1ec765ec946fbbcb77833dfd545681f25d07ceddd4f6e0521483353416ff979c7accf0f552e47f233f1dd023b5b8ce1e1098bcea70b52b80b738c4e9ae19b059889d659989f38208903683b1922d5984b221e16efc7155f6193ade1e3eeac4de6fce00b17f95fc9510b90f3c25f52e3018ce0ea7acfd9be4cfa7b1f27351b1d138680c5d1d2338abe3724b465919f71fd0a29fae5d9bd48a86e3b47f009a3ad90fa6abbc6d208a32242bfb3cc69100cfd5022655accb2a45f1fba89865b88d80b9b579e0a213cd62ead7f69d996ebf1a47017aa4d0bfde293fd9562f75b532d39255c4693a1932ccfec504ff39cc8b98e4a48d7f7fdc0e06f5efadb24d55e65aca366b4d", "9", "-506dd91112999a9a4070cc67d8b9ecad331b06999c567618dfb273dafeda08beb7420a4e092043ada86f31f574a2e27714ebfd37981b64eafacbd71ef419aef1224c50205d70924696dca18ab1d60183bd0fccbe80ecb794273966810b343b8517f73685eab6271942bbcd8bf576c146ef70d0ec71d24c3e5ab88c05f03631915f77ceefa185a8be8f46349a5ed5ed558c326dfbbbd486c59c310e3756b1959af64e6ebbe1d34ae20807de9866897961d7eb2496794f850d67c28011e085675d57948a23a075f65c4d770969e7cce99d5dec00abf5dcec7183d350376c730b0250ff847be61b7cfb2b12ef57b09b310981bcbfab83c9c9c0bdf9d4fd8f63b2f64a37dde5bbc19efeaa2b40f92e83e76eea7b70290a419a9a0b7fcbce3d66787aa9723f919f8ee811dadc670f084c5e75385a95c05b9c6274d70cd82cc44eb2ccc4f9c104481b41d8c916acc25910f0b77e38aafb0c9d6f0f1f75626f37e70058bfcafe4a885c879e12fa97180c670753d67ecdf267d3d8f939a8d8e89c34062e8e919c55f1b925a32c8cfb8fe8514fd72ecdea454371da3f804d1d6c87d355de369045191215fd9e63488067ea81132ad6659522f8fdd44c32dc46c05cdabcf05109e6b1756bfb4eccb75f8d2380bd52685fef149fecab17bada9969c92ae2349d0c99667f62827f9ce645cc725246bfbfee07037af7d6d926aaf32d651b36", .None}, + {.Shr_Signed, "f0fda4d7cf6f6245502d094b75fc3bd0fc13fb4a8dfded7b9f20a1fd8c60da96457bb0fd5ddfe024dbb454c5ef751a806242d0c8248d6a75672464f9071c43c25871f81bc94523ab374026ddaed28906c24609346c1368fdd55580833011a5eb7ae3fc4a8ee4e52b5727e690f6efc3b04cb541ec5e840cfe3fe58a95bb9be45082f1f78ff9f83933d65611bfb6d85e0f912d44bd7f852fc565672e071ebf51ee02cea3e1ee5fdf8b02bc451cc430a470794b718398d60eeb6dff3ff619aafab4d8501c90f482334d61b16b12ee966cc03fcff6ef6645c108a7e15f5364b8385aee74f982e9fafc55facdd7b4e398a05b1caba537a9b4f2ac5d804c7595642a02017ac034178a80c337d9062a715b71299f082356e290150e791d1f4c259c1ba70f66b8fabd017bbabe03241fd642072acb4e663f793e8799d71a7385405be75b6bf8d46e7a6a26621468d3a82b51d62c2eb2abad2346056b88c6361f922f5fbe8d6cbf62a7a9cd868075c3055936aa3844a1ebf14d0d5a026c2778e198177ee4d212bbc53eb3d77db9e47acb46363d508fafe620d4c0256871a78cc7f200527e54fb9978e251fb154bf21ca4149a9c45ddde9f2d12a49b9b0e4060be3f38249a3f6569024d4e83e1b972f8bfe529b5fa3facae0336324860c106b8c71065dc9fed03b2c58731bbbe6120de40946c204567f46d15806671e9b5b48beb11600cff", "2d", "787ed26be7b7b122a81684a5bafe1de87e09fda546fef6bdcf9050fec6306d4b22bdd87eaeeff0126dda2a62f7ba8d40312168641246b53ab392327c838e21e12c38fc0de4a291d59ba0136ed76944836123049a3609b47eeaaac0419808d2f5bd71fe2547727295ab93f3487b77e1d8265aa0f62f42067f1ff2c54addcdf2284178fbc7fcfc1c99eb2b08dfdb6c2f07c896a25ebfc297e2b2b397038f5fa8f7016751f0f72fefc5815e228e621852383ca5b8c1cc6b0775b6ff9ffb0cd57d5a6c280e487a4119a6b0d8b589774b36601fe7fb77b322e08453f0afa9b25c1c2d773a7cc174fd7e2afd66ebda71cc502d8e55d29bd4da79562ec0263acab2150100bd601a0bc540619bec831538adb894cf8411ab71480a873c8e8fa612ce0dd387b35c7d5e80bddd5f01920feb21039565a7331fbc9f43cceb8d39c2a02df3adb5fc6a373d3513310a3469d415a8eb16175955d691a302b5c4631b0fc917afdf46b65fb153d4e6c3403ae182ac9b551c2250f5f8a686ad013613bc70cc0bbf7269095de29f59ebbedcf23d65a31b1ea847d7f3106a6012b438d3c663f900293f2a7dccbc7128fd8aa5f90e520a4d4e22eeef4f9689524dcd8720305f1f9c124d1fb2b48126a741f0dcb97c5ff294dafd1fd657019b19243060835c638832ee4ff681d962c398dddf30906f204a361022b3fa368ac03338f4dada4", .None}, + {.Shr_Signed, "-d9cb3719191ccc0b17c663a5f60ecae6b0aa8f409d8742b70f55065f3addedd1596d6df325f4db2a52674519831e06e7203f5b5446adbed7b01a1fbb7ce5c559932e56881462f82e31667b9e14a417d80d8c3b12f1bf50b096e4512ee3c21f67827c884d1d7ce34959afd3c3cbab857e5f27d8cd9f1c3316bcee15e2c77c89ac152ab111bb2cbf04d36ea1b4c49d8b987db53ce86fb4e40448a1900208faa985d6ee4ab71c48d522b27e4d195b95326a602c578316356eaed3cdb063c5482e4c594bda7189b0f7a151266279e9b431fc5fb95c899661f85330f8c42333be579470d6c926975dff31fc90b593b7983cdbd74b456453c43cfb075bbc7ce63a1895222cd214f8c91ae3cf323008145e4522b9ea7905e098b8711b29da0fa2cd5b0fa91abc28ccb717ece65b270ef383f830488d2ed34d99096adb0752c8eb00ca6684187aea9804fd84a48dfb4769f586686fc33f511055e9a0aec2e7704f024ff56c2586d13470a97ae616dfc37faa54b856d4625ab24849533c9edd78b9629800dc5a6ff6fa77a3a1ab0260fa7191dab7e8a4d8519d26ff57df6e54b65db3e804736eb6b875a5c7ad1d84e463101a3eb5ba030694b6d1ccc7c69013d7d17faf88a15e992359d04b1caad6b7e89a9735a2dd09c22dcd05fd6f8ee9d4f6be8a0d20b75105afc8351180e14f25366e4453bd4d69e02c875d8127870fdd6a055a68fc", "40", "-d9cb3719191ccc0b17c663a5f60ecae6b0aa8f409d8742b70f55065f3addedd1596d6df325f4db2a52674519831e06e7203f5b5446adbed7b01a1fbb7ce5c559932e56881462f82e31667b9e14a417d80d8c3b12f1bf50b096e4512ee3c21f67827c884d1d7ce34959afd3c3cbab857e5f27d8cd9f1c3316bcee15e2c77c89ac152ab111bb2cbf04d36ea1b4c49d8b987db53ce86fb4e40448a1900208faa985d6ee4ab71c48d522b27e4d195b95326a602c578316356eaed3cdb063c5482e4c594bda7189b0f7a151266279e9b431fc5fb95c899661f85330f8c42333be579470d6c926975dff31fc90b593b7983cdbd74b456453c43cfb075bbc7ce63a1895222cd214f8c91ae3cf323008145e4522b9ea7905e098b8711b29da0fa2cd5b0fa91abc28ccb717ece65b270ef383f830488d2ed34d99096adb0752c8eb00ca6684187aea9804fd84a48dfb4769f586686fc33f511055e9a0aec2e7704f024ff56c2586d13470a97ae616dfc37faa54b856d4625ab24849533c9edd78b9629800dc5a6ff6fa77a3a1ab0260fa7191dab7e8a4d8519d26ff57df6e54b65db3e804736eb6b875a5c7ad1d84e463101a3eb5ba030694b6d1ccc7c69013d7d17faf88a15e992359d04b1caad6b7e89a9735a2dd09c22dcd05fd6f8ee9d4f6be8a0d20b75105afc8351180e14f25366e4453bd4d69e02c875d8128", .None}, + {.Shr_Signed, "e2002fa30bf8485e04249647217fd880e27551e43009270103e89630bf1613e7b072f7d50f44efd23116bc37657f317dc5f6516b5fcf0c384e21598f083f741faf7e4e06968611089b72b437a83581d122f993245a1e98918ad67549de8aa3c44497e57cf75034facbdc0f6b25557d5606394404428f2814fca32919790c0c529504ff21a1bda763c467389a963904940fdef2b800542afcfcc992858ded06f97d98885c0a79d9b24bfc9d1b2b1978359da998dc6a278ca4f9c43ded359e66ecd10e9981a713a4c34360095e1507ef322b0fcc8441c497db2e37e5c266ef2d20268ae5ee466231dbdeef18bbbbec36f81ea9b671290451a96eabd8ca9b8bc8eac81bacbf4eba1e9384c772a805e3147a8d027b22ca394d9a9b308aa8ce4f796e291e6628d5f6de4a8e6c29a298a10a828650ebbc540bdfce3d3386e1f18ae309fc1960670ddb99b5687bd112878070a6694fa511551b0796623d7ce9064b46885b90f6c9679aaeac6880dacbe8f0c76fe254c7d5bee52bbb93f4674c734e88a1c075f30b2f06b866582a4790b39aa8d7494986baa2e6a7ab2187f5fd7369627703298d9e8c194cabd29de3885f8b13f7c14c8d016a6abf9a1f9af4e172b792d8a2fc4bb9fd68777f95005a411c02cc51e7a4248aef19a9e950561747a1d31e41421942af9cfa766fd6319e7bad42baed7fdfe24ba7213d4997453243bb27961c", "8", "e2002fa30bf8485e04249647217fd880e27551e43009270103e89630bf1613e7b072f7d50f44efd23116bc37657f317dc5f6516b5fcf0c384e21598f083f741faf7e4e06968611089b72b437a83581d122f993245a1e98918ad67549de8aa3c44497e57cf75034facbdc0f6b25557d5606394404428f2814fca32919790c0c529504ff21a1bda763c467389a963904940fdef2b800542afcfcc992858ded06f97d98885c0a79d9b24bfc9d1b2b1978359da998dc6a278ca4f9c43ded359e66ecd10e9981a713a4c34360095e1507ef322b0fcc8441c497db2e37e5c266ef2d20268ae5ee466231dbdeef18bbbbec36f81ea9b671290451a96eabd8ca9b8bc8eac81bacbf4eba1e9384c772a805e3147a8d027b22ca394d9a9b308aa8ce4f796e291e6628d5f6de4a8e6c29a298a10a828650ebbc540bdfce3d3386e1f18ae309fc1960670ddb99b5687bd112878070a6694fa511551b0796623d7ce9064b46885b90f6c9679aaeac6880dacbe8f0c76fe254c7d5bee52bbb93f4674c734e88a1c075f30b2f06b866582a4790b39aa8d7494986baa2e6a7ab2187f5fd7369627703298d9e8c194cabd29de3885f8b13f7c14c8d016a6abf9a1f9af4e172b792d8a2fc4bb9fd68777f95005a411c02cc51e7a4248aef19a9e950561747a1d31e41421942af9cfa766fd6319e7bad42baed7fdfe24ba7213d4997453243bb2796", .None}, + {.Shr_Signed, "-f535182fa1b9507bf0d2c13baefa6f1d0653e15f5e05816ad9db6615cf1535a37d20df5bc985a9d0d868cc8ac5f8d898ecaee7af11d2e01d3845cac885761074040fa64277f4f9f91c7f39c2a46dc070ad341ed8b0a5d5a30dc045df0afc25f103f88806917201bebdb3d2e33b2004a37d46a26b63b9643b5ee99ce006b82bf03ca72bbd46bfc0782ee066d0768d0549503dc5802fc9586f0f60cc7b62baf7aed89bb9493c3f6786a727cf0e0333df0aec7413c5dfb937bfa4ddff8960f45c9ecf180d0e2b63d6076f72f42d7dd1d3de8be17fa21d40f05079e45c32fd9113ed6cccdaeea3160b26f1d30bb85131062cb10cf489ee1583293c9b5ae2f2da303be3a2b0fc6833548cc3991754c72b965e54a10dfd8e27648f7c651e2d0c02f9574c88df64a6c4a40e0754ed8679fc7145fd7aa4a4856f91334c284a74eef2d856578ac1ce9e62fb2597c7474b9a7a077bacc9cb3aff5446743393662580052f797c279c315f8021201d65994d3961e10026e2bfd16eeb8435a6304ed54ca5cb0adbfd3ba615e587e6312d5d2fabd69c5ea1ebd286007a84fa32559166a13e3d32e72e8557b5ffb40c9779f8b8d34f9f21f260a5efd6728f8180a1624e2f260e48f9d374ebd675c7a03ce48ca8f2a01760ee80573a3fff12e0dbc42e9d6460dfb3fa535b849de04280bec8f101c20b80a50d4638b573a07fb5d5e5f461f05e8696", "52", "-3d4d460be86e541efc34b04eebbe9bc74194f857d781605ab676d98573c54d68df4837d6f2616a74361a3322b17e36263b2bb9ebc474b8074e1172b2215d841d0103e9909dfd3e7e471fce70a91b701c2b4d07b62c297568c3701177c2bf097c40fe2201a45c806faf6cf4b8cec80128df51a89ad8ee590ed7ba673801ae0afc0f29caef51aff01e0bb819b41da34152540f71600bf2561bc3d8331ed8aebdebb626ee524f0fd9e1a9c9f3c380ccf7c2bb1d04f177ee4defe9377fe2583d1727b3c603438ad8f581dbdcbd0b5f7474f7a2f85fe887503c141e79170cbf6444fb5b3336bba8c582c9bc74c2ee144c418b2c433d227b8560ca4f26d6b8bcb68c0ef8e8ac3f1a0cd52330e645d531cae5979528437f6389d923df19478b4300be55d32237d929b1290381d53b619e7f1c517f5ea929215be44cd30a129d3bbcb61595e2b073a798bec965f1d1d2e69e81deeb3272cebfd5119d0ce4d98960014bde5f09e70c57e00848075966534e58784009b8aff45bbae10d698c13b5532972c2b6ff4ee9857961f98c4b574beaf5a717a87af4a1801ea13e8c956459a84f8f4cb9cba155ed7fed0325de7e2e34d3e7c87c98297bf59ca3e0602858938bc983923e74dd3af59d71e80f39232a3ca805d83ba015ce8fffc4b836f10ba7591837ecfe94d6e1277810a02fb23c407082e02943518e2d5ce9", .None}, + {.Shr_Signed, "999f3b3db68854614a813f587837fdef20594e52190016cdff5f4865871695a9efd131ee659871f5fb0fa49adaf940189dc587d9c63080c085d4a632f90e15f67e9463079db4ac20593335ba07c3f15c02111c319394f0b9dc1f8295e272c258d596229874f6c785162d8b24c9da7dc0cc9ed0a5963d813bebf8320fbe3b0ce21842b1167af4d148923ce1ac40c63b1326d569babf19b8dc44738c7fc057a143368a32c32289cc6fdc6105ae44c43fe61c3fa969b7535ce50ab4134bc70b133bbf9b1ade436ef4d0e3981cc88c82e566f2813fc3ff969fa153b1e5cf8e663149e21c699e52fd1e731a7e5fc099396349d6b02e3842c17a302ecfb2216ac67a4cf7f88b984d7fdbb4b03c3ff5774c0ae350b661f3f7f30efb3df3b882507778b0ec1a23d052a484d56ffc4e5162edf44d1a529ac77c40e6bfab95d491c6d9e2c9efeb470c838475933ce75f77ea071603a47d0717898be66917f44d7a2a85bbfb577c23443e4355bf15c4d27d44c0499604414d3d39617ab4f2252efce359fab14bc29f170dd2ac77dfcb120a96079d2151c41a97def0661961830511c231e6343f58d5ca304995ad48928c453d58132ed88648bcad7daec18e2732ffe45407c10405cb1b3b34e60dd7f56c0d322b5f6ce481ada0010584100d8c9a3ef6eefbf6a55cab2d2faae5aec9687a15d55f11ecebd243dae0123f87ec0fec4b1f42346f", "10", "999f3b3db68854614a813f587837fdef20594e52190016cdff5f4865871695a9efd131ee659871f5fb0fa49adaf940189dc587d9c63080c085d4a632f90e15f67e9463079db4ac20593335ba07c3f15c02111c319394f0b9dc1f8295e272c258d596229874f6c785162d8b24c9da7dc0cc9ed0a5963d813bebf8320fbe3b0ce21842b1167af4d148923ce1ac40c63b1326d569babf19b8dc44738c7fc057a143368a32c32289cc6fdc6105ae44c43fe61c3fa969b7535ce50ab4134bc70b133bbf9b1ade436ef4d0e3981cc88c82e566f2813fc3ff969fa153b1e5cf8e663149e21c699e52fd1e731a7e5fc099396349d6b02e3842c17a302ecfb2216ac67a4cf7f88b984d7fdbb4b03c3ff5774c0ae350b661f3f7f30efb3df3b882507778b0ec1a23d052a484d56ffc4e5162edf44d1a529ac77c40e6bfab95d491c6d9e2c9efeb470c838475933ce75f77ea071603a47d0717898be66917f44d7a2a85bbfb577c23443e4355bf15c4d27d44c0499604414d3d39617ab4f2252efce359fab14bc29f170dd2ac77dfcb120a96079d2151c41a97def0661961830511c231e6343f58d5ca304995ad48928c453d58132ed88648bcad7daec18e2732ffe45407c10405cb1b3b34e60dd7f56c0d322b5f6ce481ada0010584100d8c9a3ef6eefbf6a55cab2d2faae5aec9687a15d55f11ecebd243dae0123f87ec0fec4b1f42", .None}, + {.Shr_Signed, "49bb2524080fb96a193453131bb1fa0236ee9b64c7fb11087428ab38b6e7f40b1f2d584a2856bcb2f535fd28b841d5e676a6229ae3968c41af7cbedcab942e460d3a0b337ecc595ef25a6830e1a169f559245acb4d9d652b45593d91cdfc5756fa3c7d2b08fd5317b57202e18623af1d594c3c33754082b0e5adce8550d07165da320797d3ed604df8b6dc5af801b0062e1311c603f417f1704664d4c49adf6bc00de334fe121be9fc1879b1782d7ae044de2f72232cd4e5f3d4e0149f1a3b7d3a8f908535170944c335e97685327fd72c3ed4ce4b721e640d281a0fd46edef7b82593b1f96da95e07efe75768606c5e9dce13231944bd99254b509c84984d2d0d0b630ce350c055920ada84b10d70c10e200b16313eff1b4f9a4ad4a72da4c6f68a3cc693f8fec2a4add35debfde20cc90d8e2131fdc15ac56aefea2e95af16f19ceb3d1a8beb03d977830993b404e809c44b810f6c1eefbf899b66d4eed28f495102d60a8a15fc171659771b4a03bcd38768ef3db65ac81387331cdaa7318b9ddde4103edae8af6eae4cbb03092ccd90e47198dc25f163907efdc8b1bf205a1009d95f99d28e8c9e2cbc92b245cffb398a0d456fea14a625e5136fc40fa139f051fbde4d76f3355b1d301433ab73894e9d0a921807a900e8ac1cb2d8260c51860f70f05f3dbc43aa960bee25add169c7647589c4c0f30c4acc4e396f22440", "4c", "49bb2524080fb96a193453131bb1fa0236ee9b64c7fb11087428ab38b6e7f40b1f2d584a2856bcb2f535fd28b841d5e676a6229ae3968c41af7cbedcab942e460d3a0b337ecc595ef25a6830e1a169f559245acb4d9d652b45593d91cdfc5756fa3c7d2b08fd5317b57202e18623af1d594c3c33754082b0e5adce8550d07165da320797d3ed604df8b6dc5af801b0062e1311c603f417f1704664d4c49adf6bc00de334fe121be9fc1879b1782d7ae044de2f72232cd4e5f3d4e0149f1a3b7d3a8f908535170944c335e97685327fd72c3ed4ce4b721e640d281a0fd46edef7b82593b1f96da95e07efe75768606c5e9dce13231944bd99254b509c84984d2d0d0b630ce350c055920ada84b10d70c10e200b16313eff1b4f9a4ad4a72da4c6f68a3cc693f8fec2a4add35debfde20cc90d8e2131fdc15ac56aefea2e95af16f19ceb3d1a8beb03d977830993b404e809c44b810f6c1eefbf899b66d4eed28f495102d60a8a15fc171659771b4a03bcd38768ef3db65ac81387331cdaa7318b9ddde4103edae8af6eae4cbb03092ccd90e47198dc25f163907efdc8b1bf205a1009d95f99d28e8c9e2cbc92b245cffb398a0d456fea14a625e5136fc40fa139f051fbde4d76f3355b1d301433ab73894e9d0a921807a900e8ac1cb2d8260c51860f70f05f3dbc43aa960bee25add169c7647589c4c0", .None}, + {.Shr_Signed, "183e5a81f39746cfa70cac5d687992df8247fc67e39cda4cafbcb86fa53ee58285a83651e35c46a72c64c2c8ecae3e8e1e4bb04c7994d8a06a4564f64b55c3b8c942aa1cf849f024d0a20b9b9879149b6865940ca317f27923e5405640a7d3452d433eca5b1ab887f0100c9828924c6e2361538c63801c4cde3a87dde91ebeb72d022d25e5f2be4bd133cee7c8ab589d159f8196be459f143fc9e58138fb3b25c793e664a42b0fef0d3146aa41f7d74090ec88a822a13c8b31fe191f5c0a1c6c6c0cf6a2bdcd16f10f216072dac5ada4914f2d8ff04a608b8c78fee00421988a7b6033ef241a4ef98866959aa877f9e09a85c2559a75aa218c601da6293b15f0481e418a416ec55ff15de85b5da30c9c04853ca325da61b9e3758568f42d6a47168011d01fdb7d38ae88c178bad3103118c9b5d20e4f89193105db6ab03ef24d9933c023dd8b837c4e0a01b8985da664beef51918e351e2b7fa7f8bef37796e7543c1b27a5d8925f61f259421f0fee34363d59dedce9fd0ce667a45dd4eec652a6d1addf40833ae3462478fda0f6c9d695bd79f9ffe2877259781813e5598f5f5c4155bb3002d5698b3ea2a630513c07c15de2e2b042f0c28c2d88889477a0bf5f566c35a6f2ca7d971f97ecb7db750759cb5d3aeeae352b8883dbeb77edb595943b9fba39f3f4ccab177dfc1dc268bbe1e367c86594b6f3eed26eeece62305", "65", "c1f2d40f9cba367d386562eb43cc96fc123fe33f1ce6d2657de5c37d29f72c142d41b28f1ae23539632616476571f470f25d8263cca6c503522b27b25aae1dc64a1550e7c24f812685105cdcc3c8a4db432ca06518bf93c91f2a02b2053e9a296a19f652d8d5c43f808064c1449263711b0a9c631c00e266f1d43eef48f5f5b96811692f2f95f25e899e773e455ac4e8acfc0cb5f22cf8a1fe4f2c09c7d9d92e3c9f332521587f78698a35520fbeba04876445411509e4598ff0c8fae050e3636067b515ee68b788790b0396d62d6d248a796c7f8253045c63c7f700210cc453db019f7920d277cc4334acd543bfcf04d42e12acd3ad510c6300ed3149d8af8240f20c520b762aff8aef42daed1864e02429e5192ed30dcf1bac2b47a16b5238b4008e80fedbe9c574460bc5d6988188c64dae90727c48c9882edb5581f7926cc99e011eec5c1be270500dc4c2ed3325f77a8c8c71a8f15bfd3fc5f79bbcb73aa1e0d93d2ec492fb0f92ca10f87f71a1b1eacef6e74fe867333d22eea7763295368d6efa0419d71a3123c7ed07b64eb4adebcfcfff143b92cbc0c09f2acc7afae20aadd98016ab4c59f515318289e03e0aef171582178614616c4444a3bd05fafab361ad379653ecb8fcbf65bedba83ace5ae9d77571a95c441edf5bbf6dacaca1dcfdd1cf9fa66558bbefe0ee1345df0f1b3", .None}, + {.Shr_Signed, "b76965fbea34acd833919450000dd7df3b0461c82b0f7194ca64330de0e94795c6d18710d1aab53eb3fa8102e45eb132378a0a3ff659d86930abf8bc522ace58d0cc2910f11e9d7c4db02ea389a136b9e353cd76e51bcb25b8bcd3c29733ab11e34a3ce036c08c7792461ce29ce6d2de9cc87662f6a7ee780803f58ee073b1e6d3263dc013c400afa301bef9bf729f0f96902ff245044fb8b6d7d90b0371bd4a35e901166e064d975b3c0b82d5332606f7d9e3c2f2a6263422ef006b8d870a0a0eb370faf838d06149e180373b8637ec00739333b1dcb4d327c384cca4d8811e2c25cfa4f1d8df6a3c8759874f8742f8f5043f3445bafa022ae479216f7e5906b51a3dc1283b31a11e4d82a46538c020a0423f6ab1c3fbffe82e353d51b04f28eaf6ac0f0484ef6d656c131dc33c6d74fc72752687d662a347f295778168e735b780f1f370a27fca9377735fd94aba68e34a9b9534fc5e8e6ea319d5751c10fdd1678d39bc72cdea7b39a9a0163a1d53bd99d2e53e6e54f8acfaaa97bd28f3514f2e49b16d88cf6b38a7659f0c567ca0e19fac9ba33497316f526ba51c13e12bdfa09f8cf735c01854bf6b88f3c4bf13852342e827a86fe18b616fa4053f52b0760d237b9f954bf66d2d8bf8ecbf171c613da55202cfa3ce0cea5dec6d518ddff07f4992dc03eb52985bc3a5b427dcf4f63419831df527b8e2be8b85f9f0da2c", "4a", "2dda597efa8d2b360ce46514000375f7cec118720ac3dc6532990cc3783a51e571b461c4346aad4facfea040b917ac4c8de2828ffd96761a4c2afe2f148ab39634330a443c47a75f136c0ba8e2684dae78d4f35db946f2c96e2f34f0a5cceac478d28f380db0231de4918738a739b4b7a7321d98bda9fb9e0200fd63b81cec79b4c98f7004f1002be8c06fbe6fdca7c3e5a40bfc914113ee2db5f642c0dc6f528d7a40459b819365d6cf02e0b54cc981bdf678f0bca9898d08bbc01ae361c28283acdc3ebe0e34185278600dcee18dfb001ce4ccec772d34c9f0e133293620478b0973e93c7637da8f21d661d3e1d0be3d410fcd116ebe808ab91e485bdf9641ad468f704a0ecc68479360a9194e300828108fdaac70fefffa0b8d4f546c13ca3abdab03c1213bdb595b04c770cf1b5d3f1c9d49a1f598a8d1fca55de05a39cd6de03c7cdc289ff2a4dddcd7f652ae9a38d2a6e54d3f17a39ba8c6755d47043f7459e34e6f1cb37a9ece6a68058e8754ef6674b94f9b953e2b3eaaa5ef4a3cd453cb926c5b6233dace29d967c3159f283867eb26e8cd25cc5bd49ae94704f84af7e827e33dcd7006152fdae23cf12fc4e148d0ba09ea1bf862d85be9014fd4ac1d8348dee7e552fd9b4b62fe3b2fc5c7184f695480b3e8f3833a977b1b546377fc1fd264b700fad4a616f0e96d09f73d3d8d0660c77d49", .None}, + {.Shr_Signed, "-5439338c1fa7ecc1f9e745b6ded534d4b4ec8274d813235354c828e91f3afb65a02c04c9d277d6a6a3b3a1d0af10b3737d5207c4a57e872d934e9bba974ff82864c7e91813c18798f5cdea34957654271bb8a5c3a01165763f3243f3b8a796ace5060325af6182cc89a12f8799a76b917405b0e868de10b2bde870ee8bb4365a897e9ae76e31b8aa240cea66812f3a7bcbcc91838b0dc50d71a5ef69875898b60670fa0597b23e8e6e333ccf64233d7cced24857b0cb08dbba75187d6209b573115339895f5200df49adef1e394a53a69f2b46a0af76679299ae01c5c04a60cad678ce3c3b16efabb6b3d2261a95d5d300f747155b475371b02307a61167896866e591b54157e8437ab89893a2a2f58c7e7d668f5228cb72a6e6b08199d63d4fdbbf26a03a3809a8408f84e6793573be070356d1c99bb6b8b8f2ddba3e7e4793b8ab4ab66ebef11e0dc2a0427acdd6615cb8244545d5f31b568d95ed1b94bbdbdfc2ab7d240392148f711e9b9c20751d0b4dd749dad08853fbcbe02b1a39800e37451c2e068836bf9011560eb68ea9829489191b67a8612b2439027c1afbce462c4f328c3e770448667bb7eb8e3f568ce6174d4bbf9f394be13cbdfc386d7a8bcd9b30733610b4595da4a9459a38f9a08d91f7aa42b45a38f3bb6173da3b490bb785aa8ab8f9b0f6e43c92de5928dc33aa7a1da9081213d65fa293e6d5fef8c", "67", "-a87267183f4fd983f3ce8b6dbdaa69a969d904e9b02646a6a99051d23e75f6cb40580993a4efad4d476743a15e2166e6faa40f894afd0e5b269d37752e9ff050c98fd23027830f31eb9bd4692aeca84e37714b874022caec7e6487e7714f2d59ca0c064b5ec3059913425f0f334ed722e80b61d0d1bc21657bd0e1dd17686cb512fd35cedc6371544819d4cd025e74f797992307161b8a1ae34bded30eb1316c0ce1f40b2f647d1cdc66799ec8467af99da490af619611b774ea30fac4136ae622a67312bea401be935bde3c7294a74d3e568d415eeccf25335c038b8094c195acf19c78762ddf576d67a44c352baba601ee8e2ab68ea6e360460f4c22cf12d0cdcb236a82afd086f57131274545eb18fcfacd1ea45196e54dcd610333ac7a9fb77e4d4074701350811f09ccf26ae77c0e06ada393376d7171e5bb747cfc8f277156956cdd7de23c1b854084f59bacc2b970488a8babe636ad1b2bda372977b7bf8556fa480724291ee23d373840ea3a169bae93b5a110a7f797c0563473001c6e8a385c0d106d7f2022ac1d6d1d530529123236cf50c256487204f835f79c8c589e65187cee0890ccf76fd71c7ead19cc2e9a977f3e7297c2797bf870daf5179b3660e66c2168b2bb49528b3471f3411b23ef548568b471e776c2e7b47692176f0b551571f361edc87925bcb251b86754f44", .None}, + {.Shr_Signed, "6955e6aee6ebb628879392d6c266432b09b3b07dd318c4e97e2f70911e14d8ed8d00a805a6bfd98de661e3ef45bd110abcca189f4ac2d81aa62f182bf00929c1c09c076fae4b54131b2a797f20b406adb7daf24e4ba2daed9a174490b8ab4403f072b8682ce4f5efa1766b50ff2f86dabbf09ff85899dcafe839b017d1e6e43ad861ddd1f7bf750aa389cf72e838458f64d69d4c36302f51557c6ba05fcbf045dcfc43b7a93129d66c3cfaee20dc6647556a36c820e2adb082f486c267f7fe7888b3fe20db94ebe41de2cfca677d1c0ffe3ea1fa94f6cac6a76f28535e94d548445fe88b35e628056480b107272af73911f7beef8cd3237ba417ac5e4cd222d8c0045e7ef7ccc1fa5b06dee462cf861331becd038ff1511e9e3634b07afcd1987757c0147887093e736443804ec8e4cc5b0168a755313fa626b38a57b868c0d579f2399ed9030dc88b885a980dbceee5a010dd27c58688c46305dcb8324eb0ca67e20d636e63d840888edac6d76a394daf733a2638a172c2a1557a893536e619bcb073bb56e059c54cffbbbd2e951917b49be09c3594b74423794933f9918d6230e865eb8989dc57a765f156781ece4e56ddcdcd3a664b69447e9170d5bbe5523de04198d6b5ebbca54e5bae173cf0b2724b6d7dac2b454539f5d9624340e85d3609b86e121aba4af8ae48e5c0a725eff1f4520b28f82757f7f0eb5e7142fd30", "34", "6955e6aee6ebb628879392d6c266432b09b3b07dd318c4e97e2f70911e14d8ed8d00a805a6bfd98de661e3ef45bd110abcca189f4ac2d81aa62f182bf00929c1c09c076fae4b54131b2a797f20b406adb7daf24e4ba2daed9a174490b8ab4403f072b8682ce4f5efa1766b50ff2f86dabbf09ff85899dcafe839b017d1e6e43ad861ddd1f7bf750aa389cf72e838458f64d69d4c36302f51557c6ba05fcbf045dcfc43b7a93129d66c3cfaee20dc6647556a36c820e2adb082f486c267f7fe7888b3fe20db94ebe41de2cfca677d1c0ffe3ea1fa94f6cac6a76f28535e94d548445fe88b35e628056480b107272af73911f7beef8cd3237ba417ac5e4cd222d8c0045e7ef7ccc1fa5b06dee462cf861331becd038ff1511e9e3634b07afcd1987757c0147887093e736443804ec8e4cc5b0168a755313fa626b38a57b868c0d579f2399ed9030dc88b885a980dbceee5a010dd27c58688c46305dcb8324eb0ca67e20d636e63d840888edac6d76a394daf733a2638a172c2a1557a893536e619bcb073bb56e059c54cffbbbd2e951917b49be09c3594b74423794933f9918d6230e865eb8989dc57a765f156781ece4e56ddcdcd3a664b69447e9170d5bbe5523de04198d6b5ebbca54e5bae173cf0b2724b6d7dac2b454539f5d9624340e85d3609b86e121aba4af8ae48e5c0a725eff1f4520b28f82757f7f", .None}, + {.Shr_Signed, "-26e367e25ae88c2da57b340debd9b4e009c9b85379f383c2bafde7b928f1c60ee382a8d6df43495622932a74f77211b01f1d1d0e00c3cc8da1623f227f69074778ce2ec5b94f12c2b988810fca66fee5bfb51c726b8bd0275eb8fca2c1a3547f106a0c3d8271d3a1614f8246298be7723b9ab147db3d6c28f1bbe89f0624fe59513b9f477ec5a1f4d93e0b6cb6bca8ae92aec59670d9c9b3ffc204281a68d97f90086502ce3a94b04df9f0cddb2ea52b7aa6a64a6241871fc547c39f2bc4f55c46984ed165e80aa6312582feecf168d6b114f4fd0e89d55ab4284bbe63b7793de29c701c55a784b921f2aecccb8dd2f9974646016f8b6a349185a73c163ce13dc045fd7fcdb9aa170d29e463329423f15e3db7ee19037a13d567305eec1e6ca2f5c35e186b7aac819d6655f87bc961c6ee98cde694b5fbdbefb8b7bbb1d7731a1dd4937b0557696918c0aed97a118f847d9040168bf01598e4bb2d6643d558ea25ea407e3c4aa04ef61377c6003c28916c0f9285f39900dc7bf99924c3385c84397a46d587776ebb302594c54d3e0d375f0ce0f146ca5ac7717d8c8000807aa17714c8447e62253891d26ca399a5687444f8914be058b3ec4ea5fc7930e91797f356784d0418b971a9d72015cdde20f9973c1c3a8ef39b9b37d09c32b82957fe8ca84eb5928342c666fe6bc64865a04e09b2cecc8c0362b1dce922c06be5d87f", "10", "-26e367e25ae88c2da57b340debd9b4e009c9b85379f383c2bafde7b928f1c60ee382a8d6df43495622932a74f77211b01f1d1d0e00c3cc8da1623f227f69074778ce2ec5b94f12c2b988810fca66fee5bfb51c726b8bd0275eb8fca2c1a3547f106a0c3d8271d3a1614f8246298be7723b9ab147db3d6c28f1bbe89f0624fe59513b9f477ec5a1f4d93e0b6cb6bca8ae92aec59670d9c9b3ffc204281a68d97f90086502ce3a94b04df9f0cddb2ea52b7aa6a64a6241871fc547c39f2bc4f55c46984ed165e80aa6312582feecf168d6b114f4fd0e89d55ab4284bbe63b7793de29c701c55a784b921f2aecccb8dd2f9974646016f8b6a349185a73c163ce13dc045fd7fcdb9aa170d29e463329423f15e3db7ee19037a13d567305eec1e6ca2f5c35e186b7aac819d6655f87bc961c6ee98cde694b5fbdbefb8b7bbb1d7731a1dd4937b0557696918c0aed97a118f847d9040168bf01598e4bb2d6643d558ea25ea407e3c4aa04ef61377c6003c28916c0f9285f39900dc7bf99924c3385c84397a46d587776ebb302594c54d3e0d375f0ce0f146ca5ac7717d8c8000807aa17714c8447e62253891d26ca399a5687444f8914be058b3ec4ea5fc7930e91797f356784d0418b971a9d72015cdde20f9973c1c3a8ef39b9b37d09c32b82957fe8ca84eb5928342c666fe6bc64865a04e09b2cecc8c0362b1dce922c06be6", .None}, + {.Shr_Signed, "-c5a9faa08a6d2a9947c84c6308118381158891eb01df33a2c5d07a333517089284af73895738f32323c6b0bb7c00b77ac58aed6a6039366a6045089f8ad029288b61ef691723e4200ce76257cc6fd7884e8dfa310c9dfbaeeadc6afc3c786efe016d18045b3473591e2d5a0b33e616037805430057ab7076e3274896cbfe4fd0f0cf2367f7e6c1ae5a495a1c0e317b44b376914fafe4916c20344413579f3b9cf93582bab69d2fac60061ac82183188b1bbcf8bdc5ef295e34ea54392aa56312418fa51b1b8cdb45aa26cc2d20da946fd3ef78b2d81f40258413bd9b5dcadb1286a35300459d38547743dd7b3ba2741624943a2faf953080588b87f8ac8eab5fe4a80707f54307d2860bc7b502f06e5dd5dc9a273cd892181d1cb0de3e9bea56fae45eb19d893efd434c6c7e2cdb595b39ab61f64cc6de0eae7bb94a9ded5f51ac41bb26196e16ba5721a2bf505b38be9f14054129b454244354768db0634a0b67ae2eb5b49927efcd302413f65367942217e40af0ea6cbf9c62fae0463844288ac5096a18b9b73cfb7a0ecbb7ed0ac31957f4f25f64e2bc2b3a9f0662846e83755d4dae312bf51832c7e79fee5b2793918201e3d1e9fc828827064e8917b765216a073b98cceff50e3b6158f4e988bc8d6fa99b03f337bf4960d289919bf1a6b9646918c08365f5d612ede3c0a2d4ac7489764cd7b96f99249b5c9161442f1c", "21", "-62d4fd504536954ca3e426318408c1c08ac448f580ef99d162e83d199a8b84494257b9c4ab9c799191e3585dbe005bbd62c576b5301c9b353022844fc568149445b0f7b48b91f2100673b12be637ebc42746fd18864efdd7756e357e1e3c377f00b68c022d9a39ac8f16ad0599f30b01bc02a1802bd5b83b7193a44b65ff27e8786791b3fbf360d72d24ad0e0718bda259bb48a7d7f248b6101a2209abcf9dce7c9ac15d5b4e97d630030d6410c18c458dde7c5ee2f794af1a752a1c9552b18920c7d28d8dc66da2d5136616906d4a37e9f7bc596c0fa012c209decdaee56d894351a98022ce9c2a3ba1eebd9dd13a0b124a1d17d7ca98402c45c3fc564755aff2540383faa183e94305e3da8178372eeaee4d139e6c490c0e8e586f1f4df52b7d722f58cec49f7ea1a6363f166dacad9cd5b0fb26636f07573ddca54ef6afa8d620dd930cb70b5d2b90d15fa82d9c5f4f8a02a094da2a1221aa3b46d831a505b3d7175ada4c93f7e6981209fb29b3ca110bf2057875365fce317d70231c2214456284b50c5cdb9e7dbd0765dbf685618cabfa792fb2715e159d4f8331423741baaea6d71895fa8c1963f3cff72d93c9c8c100f1e8f4fe4144138327448bdbb290b5039dcc6677fa871db0ac7a74c45e46b7d4cd81f99bdfa4b06944c8cdf8d35cb2348c6041b2faeb0976f1e0516a563a44bb266bdcb7cc924dae49", .None}, + {.Shr_Signed, "-b966c4afaa897ee62d69528345515c4fdace008046af06fdd32beaf9f10502ac6fd4632863669669ae3ed0fd0a1b7b0a5e4043046dc0d4f24fbddea0d9e22741efc1239c7a09779970bd1145e85cbbca0bcc0caf2add15206e83cca7dd092a4aec7a3d666ef0430ed054d806b1d50145d16be3a70199018e74c60052573395c277cfa2ff538a2dae83e1df52a4f26ef336070cd70ecc7b59060dc744cc7969f09d6f8261d7f01c62982e92db07197e5798be5b94bcd433cb197fe6e7da6c8cebd949c52eee4d2bb8d082949ff1813c5fc6be908689b6c1aa7279c043ef98d52edf218db218a5058f7391637a17c60d8840d77ae68db7a1a34f57a0f4595ac9500e408e23480628139338983b184851f5576a5e0a072c805c855556182261833e6383bd6268e1fece1179fd0cb097907a5acc17a8baed79254e0fbd62c78a85a8dddc383b859ca69d7efe41548489aa872aa107297cdd7ead1c82eccad152aab424a9b80741297d103ef67603fe31d9d08b027e426328cbcc35cb6ee8cd8300157c9b7c8dd0280712bfa7dd43d6fc874311b38dc425451646b3c48213d8da23305a8c0d3bd2263bf5f0ca659589db0c1db1a8fa5a535e7cce253f65ba799fec143dd4e9eef78438f847e635d2ca2077ea874038e0aa25c1ffb57aeb93570fb33c136c66ebf2f5c618def9edd5e7119e1b3c6837c3abe26fd7de9ae1ed440bdf56", "6d", "-5cb36257d544bf7316b4a941a2a8ae27ed6700402357837ee995f57cf882815637ea319431b34b34d71f687e850dbd852f20218236e06a7927deef506cf113a0f7e091ce3d04bbccb85e88a2f42e5de505e60657956e8a903741e653ee849525763d1eb337782187682a6c0358ea80a2e8b5f1d380cc80c73a6300292b99cae13be7d17fa9c516d741f0efa9527937799b03866b87663dac8306e3a2663cb4f84eb7c130ebf80e314c17496d838cbf2bcc5f2dca5e6a19e58cbff373ed364675eca4e297772695dc68414a4ff8c09e2fe35f484344db60d5393ce021f7cc6a976f90c6d90c5282c7b9c8b1bd0be306c4206bbd7346dbd0d1a7abd07a2cad64a807204711a4031409c99c4c1d8c2428faabb52f050396402e42aaab0c1130c19f31c1deb13470ff6708bcfe86584bc83d2d660bd45d76bc92a707deb163c542d46eee1c1dc2ce534ebf7f20aa4244d54395508394be6ebf568e41766568a9555a1254dc03a094be881f7b3b01ff18ece845813f21319465e61ae5b77466c1800abe4dbe46e81403895fd3eea1eb7e43a188d9c6e212a28b2359e24109ec6d11982d46069de9131dfaf86532cac4ed860ed8d47d2d29af3e67129fb2dd3ccff60a1eea74f77bc21c7c23f31ae965103bf543a01c705512e0ffdabd75c9ab87d99e09b63375f97ae30c6f7cf6eaf388cf0d9e342", .None}, + {.Shr_Signed, "-94562ecba373bdce84af5df668ccc3b81f05aed66968af0ec42e3feebe71120ae4d7b0cd985d9fd51136627d37c8e53c2513f88b56e17034ff9af81d476ef6d11d4345194cc3912fb9fbe831a0908730c2a31bbe06c6346be7a36154fea6596b8adc6229bb9a70d948f2b75cef13ebe92bff6f529c01da214ffb1ec68bd117fa7ba334534ae13f80c736cc6cfe4953ead061471b4249c3d783fe4e7b2566ab1b3077b3e557bb29a8c47ed0fd071326afa63bda6dce07e232f9bef07978062def104771282f65ebb21fa0984070f561f9d8e903bda7e9987d533abc2c27427207e76cd938a87e1ac0ed2c5f22f853cd4a69d104e624cbc28e384d28918b0166cccb716b086fe967e5d38a4ef9a7bc84531f216c24908434fb93557c67bd6a44b5218143d4b18259ea692af320a2719be947cf57bef88da6e1f009aabf0ec4fcde4f755f131422555705db2ab2d8a4863c06557440a9a2c7dd04e5fbe373d3fbfea662d7b7d788c593d273099b37ea9069c0373afa2281333511200c3c6f28a6e5dba960ddefce77770397a972e272c55fb86d84f9d0b5fbd4ad5b9fc3b33d7a3032833b22dc24805a3ad2f086ca252f8d191f1176063cfc82c1df981103645137ac9fc05b0ea6b8b5f65da60352346febf59d1f4aac2eaeab149bea20b5d1f673fa0a6635e37b79bd46bda6ce84b98529698a747a6d6164402a5f22d59e097bdc", "42", "-25158bb2e8dcef73a12bd77d9a3330ee07c16bb59a5a2bc3b10b8ffbaf9c4482b935ec33661767f5444d989f4df2394f0944fe22d5b85c0d3fe6be0751dbbdb44750d1465330e44bee7efa0c682421cc30a8c6ef81b18d1af9e8d8553fa9965ae2b7188a6ee69c36523cadd73bc4fafa4affdbd4a700768853fec7b1a2f445fe9ee8cd14d2b84fe031cdb31b3f9254fab41851c6d09270f5e0ff939ec959aac6cc1decf955eeca6a311fb43f41c4c9abe98ef69b7381f88cbe6fbc1e5e018b7bc411dc4a0bd97aec87e826101c3d587e763a40ef69fa661f54ceaf0b09d09c81f9db364e2a1f86b03b4b17c8be14f3529a7441398932f0a38e134a2462c059b332dc5ac21bfa59f974e293be69ef2114c7c85b0924210d3ee4d55f19ef5a912d486050f52c60967a9a4abcc8289c66fa51f3d5efbe2369b87c026aafc3b13f3793dd57c4c5089555c176caacb629218f01955d102a68b1f741397ef8dcf4feffa998b5edf5e23164f49cc266cdfaa41a700dcebe88a04ccd4448030f1bca29b976ea58377bf39dddc0e5ea5cb89cb157ee1b613e742d7ef52b56e7f0eccf5e8c0ca0cec8b70920168eb4bc21b2894be34647c45d818f3f20b077e60440d9144deb27f016c3a9ae2d7d976980d48d1bfafd6747d2ab0babaac526fa882d747d9cfe82998d78dede6f51af69b3a12e614a5a629d1e9b585911", .None}, + {.Shr_Signed, "62b5d9165dd4397822a303b1820abe8319c2543aadd7bcb9e8e9149f48be6c92e1f52e49f169397c181473a8a21da529d02092ada1fc1fbd9fe402271f76b30af63909a65d5e654da52749225106bebf3721fb7024893eb298be2fbaee08db29f4493adce213c6ddd3e5f4df4b5a9faed78590f0ec681c1cdd216819b31d60e0fc29c30e721dc6e779df26c32dd81c53a7e57809f536f0c1cb3a1741a86c55c3da7681557994771ec00cea0408718d4c0c3c6e53b03714d8bca8904d52725b8b40627ce21e8df903d1fe792397bbfff9c09815b4ccdfdd50ec9bf665020f814fe61f07acb0d03d8de7eb082b40f9e322db13277c4dc1e733d53f368354d1ed686929284b1327ab43e2e11e093d64c96f963900723719a028c4cefe3bb88f56be7d27afaf075251050865ac08a586a9d44dd9c182a9efb32ef30fcaa7a76314c2d2cbb847dc1ad19a77941a40457bc03bca25896f1c29b80d3e58b31af2b285554aa1d3a322d255592cae774847e755229cb75e8f8fe4e8b9be2cd55a198d165f4640280a80d36eba5769e0c83d203b37dc3f2ff0039c6b7c0d68bc86eef3a1e4ef08718708b087b90bd617eebf1858dfe28e3a5594d7a34f4fb77ee2b3f07008200be03d1d35e8755a308bbc9fdf5ad133f8cb6e91955e6e0d9aa1d14938363df2390fa817b1321f165f8a02ed3c59de055351701c70f2213d11637fc158ee35", "48", "62b5d9165dd4397822a303b1820abe8319c2543aadd7bcb9e8e9149f48be6c92e1f52e49f169397c181473a8a21da529d02092ada1fc1fbd9fe402271f76b30af63909a65d5e654da52749225106bebf3721fb7024893eb298be2fbaee08db29f4493adce213c6ddd3e5f4df4b5a9faed78590f0ec681c1cdd216819b31d60e0fc29c30e721dc6e779df26c32dd81c53a7e57809f536f0c1cb3a1741a86c55c3da7681557994771ec00cea0408718d4c0c3c6e53b03714d8bca8904d52725b8b40627ce21e8df903d1fe792397bbfff9c09815b4ccdfdd50ec9bf665020f814fe61f07acb0d03d8de7eb082b40f9e322db13277c4dc1e733d53f368354d1ed686929284b1327ab43e2e11e093d64c96f963900723719a028c4cefe3bb88f56be7d27afaf075251050865ac08a586a9d44dd9c182a9efb32ef30fcaa7a76314c2d2cbb847dc1ad19a77941a40457bc03bca25896f1c29b80d3e58b31af2b285554aa1d3a322d255592cae774847e755229cb75e8f8fe4e8b9be2cd55a198d165f4640280a80d36eba5769e0c83d203b37dc3f2ff0039c6b7c0d68bc86eef3a1e4ef08718708b087b90bd617eebf1858dfe28e3a5594d7a34f4fb77ee2b3f07008200be03d1d35e8755a308bbc9fdf5ad133f8cb6e91955e6e0d9aa1d14938363df2390fa817b1321f165f8a02ed3c59de055351701c70f2", .None}, + {.Shr_Signed, "c441447babaf69a129a9aa0a000784c2e49b7b261d0cc4dd4e1d5b16d9f457e83de842bfd164116ebe858b1efcfef473eab9d3c6b85549454e590b8143293719b547d44bc71944a07aa69db03e8c67ced0c60e4da5116e6e706ffe845f336b2cd932d45b8d7f26fa9702ed4c861b61db884adf09d76460b3624a7a8e2fc8d00c2ad6a0868d0550fcddc3aa4dba4b2a515b510d6f3890a7e109376cf17eb1cdcf698b9efbcdf0577c32569e5f8d0d4ab5df82edda8ea7a38bc65e6ad0bd8ac276aa9d3d77d87d7dd9f39103ff17c210da37dfb49d1e4be0e1e82daa06a1eee37c7ec3568bbe83ef410a9b7bc186308f87c4bbcf53e7126a0436331c8473096b10bb2f34c3dbd31df4b91067488f71748c494ba2d0c107d44850a21597ba4016e9a5ec3b89283720760d21313e31eba41116278d5c0cc311ef96d8f80a28833262c7b02f78881e311cb38e5bedb7619061c6b85cb9e3bf26c50046755ef3630a110d279fc2dc43f3b6537c593a9c318879c642f48f90ec376cac94f48cf541cb91d0e3c701479c2698cb2f6497c07fc7582efc0f80c5ab8f44ccfecc2d805c906a4a3de73a874e5a31537997501260004dbe7a0fdaa1c219e6ed777497a7147c91fee96abd6f3156a77d731d2717779b523b1edbd0b9410ab93edf01d64f55441549f71ec446971c9605fffd993b63cf1cb384640c44cfb4a3b241ad73247fe5d", "3a", "3110511eeaebda684a6a6a828001e130b926dec987433137538756c5b67d15fa0f7a10aff459045bafa162c7bf3fbd1cfaae74f1ae155251539642e050ca4dc66d51f512f1c651281ea9a76c0fa319f3b431839369445b9b9c1bffa117ccdacb364cb516e35fc9bea5c0bb532186d876e212b7c275d9182cd8929ea38bf234030ab5a821a341543f3770ea936e92ca9456d4435bce2429f8424ddb3c5fac7373da62e7bef37c15df0c95a797e34352ad77e0bb76a3a9e8e2f1979ab42f62b09daaa74f5df61f5f767ce440ffc5f084368df7ed274792f8387a0b6a81a87bb8df1fb0d5a2efa0fbd042a6def0618c23e1f12ef3d4f9c49a810d8cc7211cc25ac42ecbcd30f6f4c77d2e4419d223dc5d231252e8b43041f51214288565ee9005ba697b0ee24a0dc81d83484c4f8c7ae9044589e3570330c47be5b63e028a20cc98b1ec0bde22078c472ce396fb6dd8641871ae172e78efc9b140119d57bcd8c2844349e7f0b710fced94df164ea70c621e7190bd23e43b0ddb2b253d233d5072e47438f1c051e709a632cbd925f01ff1d60bbf03e0316ae3d1333fb30b6017241a928f79cea1d3968c54de65d4049800136f9e83f6a8708679bb5ddd25e9c51f247fba5aaf5bcc55a9df5cc749c5dde6d48ec7b6f42e5042ae4fb7c07593d55105527dc7b111a5c725817fff664ed8f3c72ce119031133ed28e", .None}, + {.Shr_Signed, "-94b3fda4bdbd457025acf1885916ca8e10dfc0a06d9931f86ec6991dea5a41d1e803a2127753b6284790d9f3cc01af719a8fcae6974fce5d53dba2a692a85ed577a784f11fb30c36f0c260d67bbf66b1df55d759c69f53506acd596592c84468a6977647cf685a4288d80293073bcfdd3db44f85c05f0cac97244b23b23a77446edb9fb3b32f2aa58d560ec5fba201f3a7af0fd96fa964b2c691764266891d594c3de5c75c0541962edbf441696466126f574b56c69d95532975db1f55993b8e35fe6489a22998b068418efb231414ffec9ac300d34c53ebcf6fee1a33c964efafdcdf9d5e832b839c40878b5763330fafa5bcc0f99198f4d7af0ccd0084eb3bf2f18dfbdeabf0ec864ea4839f4df03727d46aa9fe5d95689643b1085c7d593bc727aa34026c3d8bbdb2c5ee9b1dc49384a07b8b0b0689794e358c58f52e37352d8bb5ca47ab88838b00ccd03f5dbb42f8281c09ca93b2324fc42b5e3bbed371be00871af0565b5e2c9d32e042cc6581c10269106e595dddb941e8c411a02f5261901d7e27c81e2394f5d7ac704ea47c858abe106730cb2f14cb271b6f241e430343fec5706309b817ce844650fdc74bfbdc2609185c79796b3ac11ae83f347efd2ba3af1eac712c745a0c97631994f9412586c9ca0c12c1886c2d2edc027972deec2777f82e99cf25977efbb1662c18eef4b71a14de9c46eb02789d5f74219e", "44", "-94b3fda4bdbd457025acf1885916ca8e10dfc0a06d9931f86ec6991dea5a41d1e803a2127753b6284790d9f3cc01af719a8fcae6974fce5d53dba2a692a85ed577a784f11fb30c36f0c260d67bbf66b1df55d759c69f53506acd596592c84468a6977647cf685a4288d80293073bcfdd3db44f85c05f0cac97244b23b23a77446edb9fb3b32f2aa58d560ec5fba201f3a7af0fd96fa964b2c691764266891d594c3de5c75c0541962edbf441696466126f574b56c69d95532975db1f55993b8e35fe6489a22998b068418efb231414ffec9ac300d34c53ebcf6fee1a33c964efafdcdf9d5e832b839c40878b5763330fafa5bcc0f99198f4d7af0ccd0084eb3bf2f18dfbdeabf0ec864ea4839f4df03727d46aa9fe5d95689643b1085c7d593bc727aa34026c3d8bbdb2c5ee9b1dc49384a07b8b0b0689794e358c58f52e37352d8bb5ca47ab88838b00ccd03f5dbb42f8281c09ca93b2324fc42b5e3bbed371be00871af0565b5e2c9d32e042cc6581c10269106e595dddb941e8c411a02f5261901d7e27c81e2394f5d7ac704ea47c858abe106730cb2f14cb271b6f241e430343fec5706309b817ce844650fdc74bfbdc2609185c79796b3ac11ae83f347efd2ba3af1eac712c745a0c97631994f9412586c9ca0c12c1886c2d2edc027972deec2777f82e99cf25977efbb1662c18eef4b71a14de9c5", .None}, + {.Shr_Signed, "36e2ebab328f144401f13250ceef225ea5bd845412699ecb08d7ff98d26f4f7f65a40f8fc89909a145f57ebab333ecc0a9a796e2fd5d49199c37b44561a3d6cca3a0e602ae24cb1697cad1a851f5ad810b3cc7851855b03e39f669088678ead4fbf09384bbb16cf26d90c5c7fa6225a162b2a2115216e6d257db69ddf00829c1c949119820d0be44ce494fb415140d881a0262348e3ec2086e3970668f53e011773418074a839f898b0e51fbb620d998df0469961ed0d79361200b4e0cc85d4483f98eb951ff43a46ed03957e47d407fdfc25231ab7fd0f480b6326d5f4b278df5763a9ee6abb227017ec2b79826072f2b12d1ca05ebe520fce98095922f8ad79ea49ad704a104bf2541e1c904a138210f4eb4be80a92e05a589c4e21115accbd0a94b038811e4519aedf89560a1198adb3ad1602b6236c04088e22c09408529f9d9d6d510ca844a35dedc82c4768beb4ba051688f4d44a83c631777af21b1d2c2028ca7fcbcf04ae675e8683e9aa0fba3ca1ea669a98af5eb5ac5e65deb117eb750264161254d75475a443d64c00e5a833ef74cea4a39b96056e4b251cc9d4236f74cd351472e6d95cc122b4f6bfa03bc223f802044cb24d30a6c1526e9b067c7ded09fde6a3c7bb96c9ff6d6f131fb555b1a6ffa7e38ef51075f0f19b50f9f64e934447e1b9d6335a5e669c496319f9d4360b07d092349cab994ab36e59fc7", "a", "db8baeacca3c511007c4c9433bbc897a96f6115049a67b2c235ffe6349bd3dfd96903e3f2264268517d5faeacccfb302a69e5b8bf575246670ded115868f5b328e83980ab8932c5a5f2b46a147d6b6042cf31e146156c0f8e7d9a42219e3ab53efc24e12eec5b3c9b643171fe98896858aca8845485b9b495f6da777c020a707252446608342f91339253ed054503620680988d238fb0821b8e5c19a3d4f8045dcd0601d2a0e7e262c3947eed88366637c11a6587b435e4d84802d38332175120fe63ae547fd0e91bb40e55f91f501ff7f0948c6adff43d202d8c9b57d2c9e37d5d8ea7b9aaec89c05fb0ade60981cbcac4b472817af9483f3a6025648be2b5e7a926b5c128412fc950787241284e0843d3ad2fa02a4b816962713884456b32f42a52c0e204791466bb7e2558284662b6ceb4580ad88db01022388b0250214a7e7675b54432a1128d77b720b11da2fad2e8145a23d3512a0f18c5ddebc86c74b080a329ff2f3c12b99d7a1a0fa6a83ee8f287a99a6a62bd7ad6b179977ac45fadd409905849535d51d6910f59300396a0cfbdd33a928e6e5815b92c947327508dbdd334d451cb9b6573048ad3dafe80ef088fe0081132c934c29b0549ba6c19f1f7b427f79a8f1eee5b27fdb5bc4c7ed556c69bfe9f8e3bd441d7c3c66d43e7d93a4d111f86e758cd69799a71258c67e750d82c1f4248d272ae652acdb967", .None}, + {.Shr_Signed, "-d3e83fafca891f1ba6614c78598b8edb769296cbe24d9b85f0a93de69fb7e068159770a14d8e5f2f5843c9771567d8dddd840f6f1a0c7adb4bf2a17d77460e9fb1a6f27412eb2583e62486078837690a6b77008b9d0aceb1d354bcbd1f80f292d0f40136af96eb9f0abcf6e8ec2653a325883d37343cd6196de20e640f9c70121edfb525abeb686409208b3526f00ac90d0b1ddb6bdada3efcfffb394504cc797550e732109e505d453c6b39e043b22844e1a383fe9ace9a55409f80dee5733551f933dc957dbc41182f160c68c8fed7477249202946d7326091399f90d8340ab0f2c755e99b334c12071c9fe7d9231d0ec93b2aa33225a43c2a9f04cec3a6fe852734afffcc81d93e9d29669f16fa66c291663accf648da6b286e201fd96b5db41103ca5f800495a94b77a1e11b005806c7dc294e536f2245d3d08ea9a2e95f4167164f93bbaf42f36e47b8420dd00b322aa77fa006bff167ededd4ebd039d4c8329326a22fa9da2d194bcd5d8dff6e778c880f30240890ab6b42c5425c5d03e23824e675b6fb6b2193c875ec1e4055e3f9d2fa166460f3c72173e905df64ddf416539d34e1fabf3bb77d4990c55290007c2cb7112950d4e0a4726ff52cb5b023f33fcc865b577326d0da47bcd5cc42edc5a3f84e66f9ad42c6f0fd50a1fef2761c8f72815ac151dbcecbe5ddbe5e7aedaa8bafb20ea01fe3b21f1eec65cf4e", "77", "-1a7d07f5f95123e374cc298f0b3171db6ed252d97c49b370be1527bcd3f6fc0d02b2ee1429b1cbe5eb08792ee2acfb1bbbb081ede3418f5b697e542faee8c1d3f634de4e825d64b07cc490c0f106ed214d6ee01173a159d63a6a9797a3f01e525a1e8026d5f2dd73e1579edd1d84ca7464b107a6e6879ac32dbc41cc81f38e0243dbf6a4b57d6d0c81241166a4de015921a163bb6d7b5b47df9fff6728a0998f2eaa1ce64213ca0ba8a78d673c087645089c34707fd359d34aa813f01bdcae66aa3f267b92afb7882305e2c18d191fdae8ee49240528dae64c122733f21b0681561e58eabd3366698240e393fcfb2463a1d92765546644b4878553e099d874dfd0a4e695fff9903b27d3a52cd3e2df4cd8522cc7599ec91b4d650dc403fb2d6bb68220794bf00092b5296ef43c23600b00d8fb8529ca6de448ba7a11d5345d2be82ce2c9f27775e85e6dc8f70841ba01664554eff400d7fe2cfdbdba9d7a073a99065264d445f53b45a32979abb1bfedcef19101e6048112156d6858a84b8ba07c47049cceb6df6d6432790ebd83c80abc7f3a5f42cc8c1e78e42e7d20bbec9bbe82ca73a69c3f57e776efa93218aa52000f8596e2252a1a9c148e4dfea596b6047e67f990cb6aee64da1b48f79ab9885db8b47f09ccdf35a858de1faa143fde4ec391ee502b582a3b79d97cbbb7cbcf5dc", .None}, + {.Shr_Signed, "-b04f6cfdbf5a9a6b927be939de83495f5e8ad7ffdf45bce20fe087b0eb7a083f9a8c32698190cf08c4383bb7bec3d15442c58d8f249023fae709b2df2d9f1f0f84a73a63a0256fc82acdc53012736b8b3fcfd01a1bbaf82094ad07d9bedb40210c447e044f0dfa59343c4933110732881ad055161aeaab0af9688787fbb0331c6ccbcfabc7c7dc598530fcb4fa8596f40cac0407e1b274e844b829d05d4059f7ffebf8ab698f9f2891eaf1d9accefa90c3253e79c0f3b26e9235b5e742fc699ea35fd44f91827cd36c4f2fedb26f0553562ab963049747010627792285d14163890dac7ad38bad3c8edf59c880f1f4602722ca23412e35ab345eaab3bf2d0ad02755009efabab99cd9e19e9390b156a01d876ac35b9764fb40782a8cac948d66a7875d881ad686d827b2630385796848ee6ed644b1514fcc158d1fdf777336b9f783569972cd2f83c240ba5ec6c853a5dc1ec50ed77f5782a78c934e4c0511298625eb74eca325221aa2fbb7e878fa6202858a3f539b94679a7ff17612096f6b47aa810834a50f45ae08fe0a38d735e219b10234a280e39171514f11cb1ee4cfbc815fa9cd8cd4154dca346d970c22c38febe9449f158a2fed4d09646714686b899fc27f43129ae8992d3b1c692d55553c31a90fe4b766fcc47e3fc9fee068c963c8e753f945298abe439774b7424c07894047f237dbff066c19210913acfdbf", "1a", "-2c13db3f6fd6a69ae49efa4e77a0d257d7a2b5fff7d16f3883f821ec3ade820fe6a30c9a606433c2310e0eedefb0f45510b16363c92408feb9c26cb7cb67c7c3e129ce98e8095bf20ab3714c049cdae2cff3f40686eebe08252b41f66fb6d00843111f8113c37e964d0f124cc441cca206b4154586baaac2be5a21e1feec0cc71b32f3eaf1f1f716614c3f2d3ea165bd032b0101f86c9d3a112e0a741750167dfffafe2ada63e7ca247abc766b33bea430c94f9e703cec9ba48d6d79d0bf1a67a8d7f513e4609f34db13cbfb6c9bc154d58aae58c125d1c04189de48a1745058e2436b1eb4e2eb4f23b7d672203c7d1809c8b288d04b8d6acd17aaacefcb42b409d54027beaeae67367867a4e42c55a80761dab0d6e5d93ed01e0aa32b252359a9e1d76206b5a1b609ec98c0e15e5a123b9bb5912c5453f3056347f7dddccdae7de0d5a65cb34be0f0902e97b1b214e97707b143b5dfd5e0a9e324d39301444a61897add3b28c94886a8beedfa1e3e9880a1628fd4e6e519e69ffc5d84825bdad1eaa0420d2943d16b823f828e35cd78866c408d28a038e45c5453c472c7b933ef2057ea7363350553728d1b65c308b0e3fafa5127c5628bfb53425919c51a1ae267f09fd0c4a6ba264b4ec71a4b55554f0c6a43f92dd9bf311f8ff27fb81a3258f239d4fe514a62af90e5dd2dd09301e25011fc8df6ffc19b06484245", .None}, + {.Shr_Signed, "d3351c9486c85d1cef275bb2e52837aa97a62adc5d5bc708b16c54975f0de466aece90b192fbcbf59fa479ee4af10ae39636bb7581dba6718dac3ada21da2cbb859e6548d99e0171031a360ad8f6bdce263642c7b60c366d1f0a0c065cbc52a2887a4b5b5d0c1d3f7d57e3945222a3ed8d92879297010aada62eca622bf79f4e7d89e425abf4dfe7d47c7af365fdf26f2ac0ac7fadeb32d664ac08d4346ff610372b0c7c60e079034230b0b2a4daf09ab7b752294bba4c43eda617d40b8c590d7cee197f8e0886d931b2eeef605a36f2a139b5934e9770fa6b52219ba25aa68786ea9785701e68422206d4728c96af9e2d0e26bf31bea5bf588b4a1b6f4ec284b1f1c8fa4fa233e3b786e00e5e8a2b8ba195cf253f6350bcac7855fb811364c41bc08540b519a39cabb42e488b9f6b89069294388c61968dbb2d4ad92c7b363056e5143e2a47fbcf89e6a856ecfd7bde9c22f7de116b51af295c3e9a9c30c1c33172b555a24565a847676507e0906e1826a66341212d1ad4579e7daac103c1883b2bbad57f0ff185385519e331770a992b5e616258b4a2f812f8bcaa7cd78a383d3b50b5b3259f50265e68fba924b1dfe3cbf3d7d1db7ead3945b6880ff8277a98c58282ad4778c7f5f196790df164ce2da2832b9b022f2eff01694fa492a9e6b9ad58aca388b6093267a59982d2bb2c111e9728e68e769cafb58fcbacc46a8b", "30", "d3351c9486c85d1cef275bb2e52837aa97a62adc5d5bc708b16c54975f0de466aece90b192fbcbf59fa479ee4af10ae39636bb7581dba6718dac3ada21da2cbb859e6548d99e0171031a360ad8f6bdce263642c7b60c366d1f0a0c065cbc52a2887a4b5b5d0c1d3f7d57e3945222a3ed8d92879297010aada62eca622bf79f4e7d89e425abf4dfe7d47c7af365fdf26f2ac0ac7fadeb32d664ac08d4346ff610372b0c7c60e079034230b0b2a4daf09ab7b752294bba4c43eda617d40b8c590d7cee197f8e0886d931b2eeef605a36f2a139b5934e9770fa6b52219ba25aa68786ea9785701e68422206d4728c96af9e2d0e26bf31bea5bf588b4a1b6f4ec284b1f1c8fa4fa233e3b786e00e5e8a2b8ba195cf253f6350bcac7855fb811364c41bc08540b519a39cabb42e488b9f6b89069294388c61968dbb2d4ad92c7b363056e5143e2a47fbcf89e6a856ecfd7bde9c22f7de116b51af295c3e9a9c30c1c33172b555a24565a847676507e0906e1826a66341212d1ad4579e7daac103c1883b2bbad57f0ff185385519e331770a992b5e616258b4a2f812f8bcaa7cd78a383d3b50b5b3259f50265e68fba924b1dfe3cbf3d7d1db7ead3945b6880ff8277a98c58282ad4778c7f5f196790df164ce2da2832b9b022f2eff01694fa492a9e6b9ad58aca388b6093267a59982d2bb2c111e9728e68e769cafb5", .None}, + {.Shr_Signed, "-45a715c1d0912e58d2f555b6f3dabb3e495b877bb8b153867649b88dbb37b17ca6ae01428e18af550f08a0a872ecdc2176dfe3157215f185b61bf9ec2c3bff328ed142507bdf7ef8dd212574885d45bb41cc5f5591a5bdef6fe915ac391848785eac8b3d1e111787b79d0145c0e7a96a5db9008c07b1d6c0e51d3a6d3b74ee72e4269aaecdff2baff38890ab1a4f752d21126f98160da560244d872508921b00ce4d6fb567bfecf1c6fe19c9479c2b0ac54339783096123fd5e2768bb66cd12e3738bde3788a2f958fc1ffab10cf01630db7fcb28f75a25965287269083bc4de2babf63df767c959bcc43d262ee3cc39df46722db932dce79453798634dc175dfb0b7dfb9f37b4335aa14357529d9f49c66e82e5a9788d24b6d6012b35261452d6b53bda285671a06cbdcf882ddb7e9048db7acf8cf3662a711ef86b3e27c539c363192b53134ce785f833d6aa5839556c1f4a7378c712a2dc231e81035e23e1202d5e9e1b55d0a7e9680f5b33dda835b08ff3b0dc3ac27898d060b39504c69e141c5f380ee98d242e287edeb31683ba54450ee6dfb1cb9a5357a82ec7fdd7a5d0eb394c5567f58ffd8db90841569f56908cf2843f3c24a90c6c87fdc9105dcb2993f318ab093212f475e2a87a14a49f1cda5a065825ef60b2d445767a0966b61d5e9bd5bf6ecc968f2dbe3bff38f3e075f1fdbdc1e97bea680af58cd99ec542", "65", "-22d38ae0e848972c697aaadb79ed5d9f24adc3bddc58a9c33b24dc46dd9bd8be535700a1470c57aa8784505439766e10bb6ff18ab90af8c2db0dfcf6161dff994768a1283defbf7c6e9092ba442ea2dda0e62faac8d2def7b7f48ad61c8c243c2f56459e8f088bc3dbce80a2e073d4b52edc804603d8eb60728e9d369dba773972134d5766ff95d7f9c448558d27ba96908937cc0b06d2b01226c39284490d806726b7dab3dff678e37f0ce4a3ce158562a19cbc184b091feaf13b45db3668971b9c5ef1bc4517cac7e0ffd5886780b186dbfe5947bad12cb2943934841de26f15d5fb1efbb3e4acde621e931771e61cefa33916dc996e73ca29bcc31a6e0baefd85befdcf9bda19ad50a1aba94ecfa4e3374172d4bc46925b6b00959a930a296b5a9ded142b38d0365ee7c416edbf48246dbd67c679b315388f7c359f13e29ce1b18c95a989a673c2fc19eb552c1caab60fa539bc6389516e118f4081af11f09016af4f0daae853f4b407ad99eed41ad847f9d86e1d613c4c683059ca82634f0a0e2f9c0774c69217143f6f598b41dd2a2287736fd8e5cd29abd41763feebd2e8759ca62ab3fac7fec6dc8420ab4fab484679421f9e1254863643fee4882ee594c9f98c558499097a3af1543d0a524f8e6d2d032c12f7b0596a22bb3d04b35b0eaf4deadfb7664b4796df1dff9c79f03af8fee", .None}, + {.Shr_Signed, "71e222b1feda00a497ff80d9109a64311d3d4ea22ae38a53fe55c19b3cb1c47aebd7572b112410968df077c997fe9456b1f7de2b6366872676113e27de0674bc6b6bb3a2033da113cbb063f5b86b0c20fab74a7962324930e464f7a34e418e014952ec313c651f69cc181dec4d68ca5a1b04a2f9597072ef929435851ade3d9cf7627a71ca6b3a5ca016c7108d23567e4718a150d4d5c5bb38175afdc5aef62e15fd776ff863cdcc11fa2ed7756b6302fd100c903cd000e09d0ff052ad63acf921187752518817eb8dd0a7b03e008e59b1b7ba503e3c868ed8a9537560cc8bf2c822229cad32e32eec2ed1dea0cb8be7816ea581fb285b4c23ecf2daed25d1699d2366b0edaafe1efc7e1d358d572288ab9235a40487e692a22b3289b472f2eeeac53c504507125808d46cada1b1a0eb6f40fc8da0c63bd461a253c97adcc7eb9bf9f6d5d633d4d3a44affdb7c0476521517822154f5f6d3047762a9b146f868476c6e251327246e886ffe5c9695b87fac12711d126f5129abcdaeda51b379f486cb8182f96acd42c44ca9d381b8b66ec19546721491c92dcb284f95c2663087f378714d9f02b7970b4eab2177b2424c30f030adee217bb1e6b35a84757090383c63b7f194f5afb6f0604d7054b31909da9da658071ac460301c9b751bbd5e7204b677d30fedd7c31b3dec7e165a36bb751a0f925b9885720f4dba610951ba70", "1e", "1c7888ac7fb6802925ffe0364426990c474f53a88ab8e294ff957066cf2c711ebaf5d5cac4490425a37c1df265ffa515ac7df78ad8d9a1c99d844f89f7819d2f1adaece880cf6844f2ec18fd6e1ac3083eadd29e588c924c39193de8d39063805254bb0c4f1947da7306077b135a329686c128be565c1cbbe4a50d6146b78f673dd89e9c729ace972805b1c42348d59f91c628543535716ece05d6bf716bbd8b857f5ddbfe18f373047e8bb5dd5ad8c0bf4403240f3400382743fc14ab58eb3e48461dd4946205fae37429ec0f8023966c6dee940f8f21a3b62a54dd583322fcb20888a72b4cb8cbbb0bb477a832e2f9e05ba9607eca16d308fb3cb6bb49745a6748d9ac3b6abf87bf1f874d6355c8a22ae48d690121f9a4a88acca26d1cbcbbbab14f141141c49602351b2b686c683adbd03f2368318ef5186894f25eb731fae6fe7db5758cf534e912bff6df011d948545e088553d7db4c11dd8aa6c51be1a11db1b8944c9c91ba21bff9725a56e1feb049c47449bd44a6af36bb6946cde7d21b2e060be5ab350b1132a74e06e2d9bb065519c8524724b72ca13e570998c21fcde1c5367c0ade5c2d3aac85dec90930c3c0c2b7b885eec79acd6a11d5c240e0f18edfc653d6bedbc18135c152cc64276a7699601c6b1180c0726dd46ef579c812d9df4c3fb75f0c6cf7b1f85968daedd4683e496e6215c83d36e984", .None}, + {.Shr_Signed, "c75ddd5e64021fd68afcb5471f8bb994dcd547438d654c8c5d68f0d1735d2532f0d67b142db66d7cfb9e3ab8a12dbed673c3694ba406198d3769b271e823f2c3302fdfc07b38c1e72ea933658951fa3aac9ffad83a512029c4c69c894c4f2bf63f607c638a6527f890a18df1451d3fa70c174613aaf6f53c681d4256a9f18f70af94fcdd47c1c01edbb962d45c492ad628de1a89820dbda683ffcd96cc4053eb118b39f6083ede7401da6bbb8bec3af86fbf213ae60cb2df2fa86d510b9412dfad22c0dc2a752c71c93b1d9eb1eccf62e9563cbb8f757d62238d488aa378c9035db384774fd4276c6fb0ee78ca12a951f0e425163e142543b3d239e83e8b8c303b379634629fb496de53c72e387cc1710c90a0d3b779d6beafbb1a7748da8aa1d76123866d94c30745706378edb25895362585b15dc80c14eae54e325f674d41187d2dff29689cc616814075e96fdc2f46f0f674da9d70597ef46d4e2ed8b20d8b34e3b2dea1d5f4833a9628a352e79ba3240933c6fdb3394316f397fc73dbe49787fb015a151d261a77ad05c1a9ba0d9d47906eb4d345a5fc33f38108ae6310aa33caa092c0e3c1fa7ebb2a44d1b0794035f1b8e44bd318df388f0d6d3ffbf41d82ee93e92120bb4fc06df1cc781eb06afb50a55a5261378ec210112996103674a8bab8366c7de19f3c2da5134fbdae1de8f6a4e55cd6316c9071ef24b003a1", "17", "18ebbbabcc8043fad15f96a8e3f177329b9aa8e871aca9918bad1e1a2e6ba4a65e1acf6285b6cdaf9f73c7571425b7dace786d297480c331a6ed364e3d047e586605fbf80f67183ce5d5266cb12a3f475593ff5b074a24053898d3912989e57ec7ec0f8c714ca4ff121431be28a3a7f4e182e8c2755edea78d03a84ad53e31ee15f29f9ba8f83803db772c5a8b89255ac51bc3513041b7b4d07ff9b2d9880a7d6231673ec107dbce803b4d77717d875f0df7e4275cc1965be5f50daa2172825bf5a4581b854ea58e392763b3d63d99ec5d2ac79771eeafac4471a911546f19206bb6708ee9fa84ed8df61dcf1942552a3e1c84a2c7c284a8767a473d07d171860766f2c68c53f692dbca78e5c70f982e2192141a76ef3ad7d5f7634ee91b51543aec2470cdb29860e8ae0c6f1db64b12a6c4b0b62bb901829d5ca9c64bece9a8230fa5bfe52d1398c2d0280ebd2dfb85e8de1ece9b53ae0b2fde8da9c5db1641b1669c765bd43abe906752c5146a5cf37464812678dfb6672862de72ff8e7b7c92f0ff602b42a3a4c34ef5a0b8353741b3a8f20dd69a68b4bf867e702115cc621546795412581c783f4fd765489a360f2806be371c897a631be711e1ada7ff7e83b05dd27d24241769f80dbe398f03d60d5f6a14ab4a4c26f1d842022532c206ce95175706cd8fbc33e785b4a269f7b5c3bd1ed49cab9ac62d920e3de49", .None}, + {.Shr_Signed, "57e3ce4ab1992ae36aca75cde7d0f095670478907f7545ad78e31ff3b59fa18915f0aeafde57091e075620617f54e8e02dc844e7a391f32bc7e2d6e5e358b6bd69ed77f0c835d3383a9e128c671e5082753c4edc8cb24abc3ec32e6b669e388ad77afd7a8556a42b0062f911b198ed9b6ee51dbbadba4b08b0cc13814aa07294046825e4af6372a28ccc5b50a7e1601a561f10f52ddd00ab4bd8f8bda333171f6eab4ce8338ee559bfc22418ac7e3c00d91150fe7d2f5b35edf9262af21a7c36c090051d8cb6be5267ab4ef83d9ff9e0173e00a00a2bcfcd545d66cfcaa513728838d92aac4e3c4b26aea94fee80e22fd912e2a63f2ac3374b016db26fad108543cb5497ef74689b366f93ad526e06ec803cbb85839cf7b858235aa9976cef021637061c7ce6bb6fa7504823efbeb0e9e988bdb4d21aeee47eb03ebbcab22110b8654e46521a7530492245dfb33d835ee17f6d3f9287e0ed85df896611e8928bffefa8bff80375113370333678a2dafacc65a25b3ba69c554a7dc582baae68b593a410765fcd7b923c1467b918ff64e930238e45cfb9b3c0a78792059b6a955c404c3c9e122108374f88f9b4aa4eeb99622cba1b1de9aa4386520eda0afa371898926a051e5fe78560a27322eb86a1af0108a74dfd50a4749d881460ad4190c03cecf2888852208e1abc3d3586ca08c21199cd102956aeafc25b045b555e93be", "2c", "57e3ce4ab1992ae36aca75cde7d0f095670478907f7545ad78e31ff3b59fa18915f0aeafde57091e075620617f54e8e02dc844e7a391f32bc7e2d6e5e358b6bd69ed77f0c835d3383a9e128c671e5082753c4edc8cb24abc3ec32e6b669e388ad77afd7a8556a42b0062f911b198ed9b6ee51dbbadba4b08b0cc13814aa07294046825e4af6372a28ccc5b50a7e1601a561f10f52ddd00ab4bd8f8bda333171f6eab4ce8338ee559bfc22418ac7e3c00d91150fe7d2f5b35edf9262af21a7c36c090051d8cb6be5267ab4ef83d9ff9e0173e00a00a2bcfcd545d66cfcaa513728838d92aac4e3c4b26aea94fee80e22fd912e2a63f2ac3374b016db26fad108543cb5497ef74689b366f93ad526e06ec803cbb85839cf7b858235aa9976cef021637061c7ce6bb6fa7504823efbeb0e9e988bdb4d21aeee47eb03ebbcab22110b8654e46521a7530492245dfb33d835ee17f6d3f9287e0ed85df896611e8928bffefa8bff80375113370333678a2dafacc65a25b3ba69c554a7dc582baae68b593a410765fcd7b923c1467b918ff64e930238e45cfb9b3c0a78792059b6a955c404c3c9e122108374f88f9b4aa4eeb99622cba1b1de9aa4386520eda0afa371898926a051e5fe78560a27322eb86a1af0108a74dfd50a4749d881460ad4190c03cecf2888852208e1abc3d3586ca08c21199cd102956aeafc25b0", .None}, + {.Shr_Signed, "-103db04c92291076ff4593fd07f1814d3009193e78c87bb4348be634ecc865b8d4ad501dfd98aef802f627f01ef50a6ca656b920b6b5b891603a33db0ad01a49b9e6489cc2754bf7ac11cee15ce41e2ee9bc5f898afd4d7c597162ab88de46bc16c5ff4b43e4baf4c5b173ae8ff2c2471f2f2a7c0ca8ead2e76ee5d04821e2df8551828999e0bd6878f640422ff7425e820626330d6e35dd76a0186599d4697cc0ae2dd43f4f345f450ba9c85d32ae4345e3112fe34fe10a92d04c3b200b8927d88f78308dd78f49dd5c340d88eb6335be3381bbb7a003178b99a63f778554d349f312d1f415af4e2fca70af799373fd4bb86477603da3f8b6f27897cc5da253ccd063d36472fc0d128a07eb3d88fc601e884d4b17ec94f3c9f7dc34adc25e25e0091567319bdbcf07e1a601490edb5e6b74f6e73d81156a7824973cb3a0df589fe30d42c79397fde0f75408658b35c3b366c597b87d42e216950da93d28502fd80a08e4fd0f4ed16b07feb922c357044c1d61aa194c3ba24ea1064f8cf0a9e24073637200172ab061754df1cb1782f1a1ae8cd132fbff4b92c91995d9e6cc6e163be2a0694e7466709d8295630ea9e462368c4020cf0b0587ebd07d2c77ea86cf2ddf8878ed2ddae93e25e91fc7712ec5a49724961d621c5b4ad8d3e88cc3876d6ca31bc804bd50a5b421671b4e0e66cad009e7bb3d8fa5afc175ae878f8068", "10", "-103db04c92291076ff4593fd07f1814d3009193e78c87bb4348be634ecc865b8d4ad501dfd98aef802f627f01ef50a6ca656b920b6b5b891603a33db0ad01a49b9e6489cc2754bf7ac11cee15ce41e2ee9bc5f898afd4d7c597162ab88de46bc16c5ff4b43e4baf4c5b173ae8ff2c2471f2f2a7c0ca8ead2e76ee5d04821e2df8551828999e0bd6878f640422ff7425e820626330d6e35dd76a0186599d4697cc0ae2dd43f4f345f450ba9c85d32ae4345e3112fe34fe10a92d04c3b200b8927d88f78308dd78f49dd5c340d88eb6335be3381bbb7a003178b99a63f778554d349f312d1f415af4e2fca70af799373fd4bb86477603da3f8b6f27897cc5da253ccd063d36472fc0d128a07eb3d88fc601e884d4b17ec94f3c9f7dc34adc25e25e0091567319bdbcf07e1a601490edb5e6b74f6e73d81156a7824973cb3a0df589fe30d42c79397fde0f75408658b35c3b366c597b87d42e216950da93d28502fd80a08e4fd0f4ed16b07feb922c357044c1d61aa194c3ba24ea1064f8cf0a9e24073637200172ab061754df1cb1782f1a1ae8cd132fbff4b92c91995d9e6cc6e163be2a0694e7466709d8295630ea9e462368c4020cf0b0587ebd07d2c77ea86cf2ddf8878ed2ddae93e25e91fc7712ec5a49724961d621c5b4ad8d3e88cc3876d6ca31bc804bd50a5b421671b4e0e66cad009e7bb3d8fa5afc175ae8790", .None}, + {.Shr_Signed, "630a77d4df7b32d2f9e4bb75b54439611297a1398c109334439ad94483687b8d8fd8200f44fca18e729408c76e9a893b397f780fc147a144e7e99bb3a74e69002acc25c749ad81ff456c2901ddd7f428619becba0eac5105ef841f8e28cc046f3050da665f512ffea73a7fae6dd72015290f29ffdc86987ce38a69f574f04dbd449b0579b1ac60edcce573598f9e257ccf3a58bef1097f357d68c74d1bc5841eba521d3e6b956695e1b9b760e13599b33e9ca399fccfe9f51f1b310c479b8fd4734573a353cdd6e43e654843ec1599b68201895bbec2030068222f0db377d3da38fa1a956a5d086de0aff1f180a23c2944b6c8b95326a02bc0501bda7d2c5d0ac140787ee9c3bc227e7cec8ea6a62ebbb6e88519371f68cba27d35d149849b02647b1d7d0b192aafda4e25a186d0adb77d11f8379bbcbde241a9cae4eca81ebd3c3cdc41e56718e176da2a04fe3c69d38d38ed294dd6e7be6c886814a065ff86211bcb7b544e8eeee7ac7625f2210465a976b1371646e5575516661ee70c687e4daa1643d0d317b9d44d749899e4344a9920534ae27348f92980918f431d38f83dfe69a784fc8dcd481f3d48ed1c4e5d12d6f84cd9496ec4c59c6d29868244c52c1a8ebc039144f0779824277345faf42f6b74a54011f7fce9379bda0e0d23f6d0f4d13077aeedcdedbe1c40dd14a86ee1ef47ab4b9c5fb52610374b39498f4", "4f", "c614efa9bef665a5f3c976eb6a8872c2252f4273182126688735b28906d0f71b1fb0401e89f9431ce528118edd35127672fef01f828f4289cfd337674e9cd20055984b8e935b03fe8ad85203bbafe850c337d9741d58a20bdf083f1c519808de60a1b4ccbea25ffd4e74ff5cdbae402a521e53ffb90d30f9c714d3eae9e09b7a89360af36358c1db99cae6b31f3c4af99e74b17de212fe6afad18e9a378b083d74a43a7cd72acd2bc3736ec1c26b33667d394733f99fd3ea3e3662188f371fa8e68ae746a79badc87cca9087d82b336d040312b77d840600d0445e1b66efa7b471f4352ad4ba10dbc15fe3e301447852896d9172a64d405780a037b4fa58ba158280f0fdd3877844fcf9d91d4d4c5d776dd10a326e3ed19744fa6ba293093604c8f63afa1632555fb49c4b430da15b6efa23f06f37797bc4835395c9d9503d7a7879b883cace31c2edb45409fc78d3a71a71da529badcf7cd910d02940cbff0c423796f6a89d1dddcf58ec4be44208cb52ed626e2c8dcaaeaa2ccc3dce18d0fc9b542c87a1a62f73a89ae93133c868953240a695c4e691f25301231e863a71f07bfcd34f09f91b9a903e7a91da389cba25adf099b292dd898b38da530d04898a58351d78072289e0ef30484ee68bf5e85ed6e94a8023eff9d26f37b41c1a47eda1e9a260ef5ddb9bdb7c3881ba2950ddc3de8f56973", .None}, + {.Shr_Signed, "598dcd8dc43c7d3fb0c281c80817bf8e19b870c82c43aec37cf32b9c623bfda098115410ef2daef6a21ed9ccdd7af9c65648b99db12b0cdac6dc9ac75c6e74cef8757ad91daa8d9cdae32fb8aeff78936608d28c43c4e56d3f652e843008cf4343d38b3725550e6ae74e4262aa63c638b260feab86c744b142cae1b1652e4b5a65a5014f1e1664c5ec2164e6ea57dfb751203e4924e2b2db37a7de082714dda897f58d4e50b29ad093e21ecc8266f81e073f399f3990d72fc3cb15a5bd6d1e737b5def8ad35d2cd920182f2dce6d3a7ff0853c8b9f62e708c9cccd213679498193a6f302b0a51d4ba9906bf94bc4b2d3ba77f72be8d16ce8b53bad6f59e97f4a001a8783cec6b366ab0fdc84787e946f3b7b345ca537642a1879c0a88fc47ed0e790459de69c20652937d016315de41ba1eec14110383caa477ac6d1ee82a81fe2d75fd4372645b99f710825df2b047725ae2c572aef8e48a95bd66bb81e0c7c47141e3ee8af4efaa84794f1dc5b771ed63bba1a3238b6abb714ed28e985f6c7ae2584fad8badc5e53de84bf1d83626a19d9eebf3f81734470a2aa101ed0e44d009896b066f156e40f1f17f40e3b704019dde14ab728a69be5945f6187cb300bcf89d832163999458a590ac0f7294939f947d5c1c3158282938d9d8ed9ffebce65c066f787b29636ae02d6f8d5964c11d7eb60156cba230260d92f30798b50ec", "18", "598dcd8dc43c7d3fb0c281c80817bf8e19b870c82c43aec37cf32b9c623bfda098115410ef2daef6a21ed9ccdd7af9c65648b99db12b0cdac6dc9ac75c6e74cef8757ad91daa8d9cdae32fb8aeff78936608d28c43c4e56d3f652e843008cf4343d38b3725550e6ae74e4262aa63c638b260feab86c744b142cae1b1652e4b5a65a5014f1e1664c5ec2164e6ea57dfb751203e4924e2b2db37a7de082714dda897f58d4e50b29ad093e21ecc8266f81e073f399f3990d72fc3cb15a5bd6d1e737b5def8ad35d2cd920182f2dce6d3a7ff0853c8b9f62e708c9cccd213679498193a6f302b0a51d4ba9906bf94bc4b2d3ba77f72be8d16ce8b53bad6f59e97f4a001a8783cec6b366ab0fdc84787e946f3b7b345ca537642a1879c0a88fc47ed0e790459de69c20652937d016315de41ba1eec14110383caa477ac6d1ee82a81fe2d75fd4372645b99f710825df2b047725ae2c572aef8e48a95bd66bb81e0c7c47141e3ee8af4efaa84794f1dc5b771ed63bba1a3238b6abb714ed28e985f6c7ae2584fad8badc5e53de84bf1d83626a19d9eebf3f81734470a2aa101ed0e44d009896b066f156e40f1f17f40e3b704019dde14ab728a69be5945f6187cb300bcf89d832163999458a590ac0f7294939f947d5c1c3158282938d9d8ed9ffebce65c066f787b29636ae02d6f8d5964c11d7eb60156cba230260d92f3079", .None}, + {.Shr_Signed, "56e92812a6ee08826f66862d71d87eb97b2947e9c20a95b596bc57f7d381b6325aa1d3d53cc5a0d75880be65e5b3c543ffd0b8bd71d253debca5ddc22ab4bdabeb099ab6fe9aa5f720d45bf1b0f3b1cf1a809c6eccabcd34d6704be538c0685b7bb72f01a1381d936d73437c5e63faa5d604f1aecde8f067e4b93e8c87394888590f6497439420bcf13a7294233e8117d532ff4638e86fe4a074e18d41febf7c58030308b87c7566d8e4df56faae12ba84e5c40fdcd3b41d05287c92185a03a4c04b1d31c7e9b0535a5b28793902c52f59914fa2ac60db41d7f0fb3fab44fe8cabababc3fba2d032d240bbdbb5b408b8db964f4a81f27b79ac49ce58c9ee7e4d38b3d7eb0653ad9892b7f96d13ac414ed02bed0d51492b063d0bb20af8f6b7fdef0947c46dcde77b7909144d3250fd00948daffa3ecd380df43a9b1328465bb55a1368feeeb26b01d3435a812b0a3fcf97081b9f924c2043d47ded4b95bfe221dc410b090220ebaf4f62dc2fc1eca0853a91cd5c086e9dacaa57e7a8d1f48a5e130d3475b2df8b8fc597ef4cb827ee8116521201e374c3c663c919bef0a90b7ca9679891c0ac6eaef958e4c3b0f6a3c0105985415e29b33f6895b207a9897446c57738f3f051c98ec034964985fe0bdec4b0ef80b32d7b633c51faed2fdf833f03c37d278e506b5976b546ed765bcaaff6ef1066a7e49513c0637641787ec760", "7", "add250254ddc1104decd0c5ae3b0fd72f6528fd384152b6b2d78afefa7036c64b543a7aa798b41aeb1017ccbcb678a87ffa1717ae3a4a7bd794bbb8455697b57d613356dfd354bee41a8b7e361e7639e350138dd99579a69ace097ca7180d0b6f76e5e0342703b26dae686f8bcc7f54bac09e35d9bd1e0cfc9727d190e729110b21ec92e87284179e274e528467d022faa65fe8c71d0dfc940e9c31a83fd7ef8b006061170f8eacdb1c9beadf55c257509cb881fb9a7683a0a50f92430b4074980963a638fd360a6b4b650f272058a5eb3229f4558c1b683afe1f67f5689fd1957575787f745a065a48177b76b681171b72c9e9503e4f6f358939cb193dcfc9a7167afd60ca75b31256ff2da2758829da057da1aa292560c7a176415f1ed6ffbde128f88db9bcef6f212289a64a1fa01291b5ff47d9a701be8753626508cb76ab426d1fddd64d603a686b50256147f9f2e10373f24984087a8fbda972b7fc443b88216120441d75e9ec5b85f83d9410a75239ab810dd3b5954afcf51a3e914bc261a68eb65bf171f8b2fde99704fdd022ca42403c6e9878cc792337de15216f952cf31238158dd5df2b1c98761ed478020b30a82bc53667ed12b640f5312e88d8aee71e7e0a3931d80692c930bfc17bd8961df01665af6c678a3f5da5fbf067e0786fa4f1ca0d6b2ed6a8ddaecb7955fedde20cd4fc92a2780c6ec82f0fd8e", .None}, + {.Shr_Signed, "28e6ab4f8f392967609c261f9293a4329a1e301f809ea22faf6e83a86fc9e80ef8d659958e7374841658f0f90cc74a297c2ee8c8716e03052ef9c90128622dd81820f9ea823cbf040c4bf9148c3d613ca0425a59c63706037fc39cceebefe26fe2baf588039aede9c11ee91960a303c18c8d58b6b896f881ac5ae792ff4fb852d477e072f75b0911b0f5e188e09ba87dd0965e3b5f8880ea1a70956886c7753d147c7235bf93ada747ef3932c13bc02214989882eef5bd27b089333869ac68f94543da688946d2145d72f5106ae942610279327ee9cd4e5a84c4eb9af1a0eba4bf843b3fcd43f74bc6b08ba9e837c681d6ebecd7169d0aa135cb4105f8bd52ed5160457e8a5be5172f4f02943a7b1d5809fe69dbd5074145f85b3db0793cfe27f12573e574678f5cd3f073fc6230ed92736f16c660470afed1baff4fd30400df29b4d1145c791d88a7ea33366bdda98d5f4719091e6593dae7e54aebce53b9541b791bcbd3363fa33550b79c7aceb4779447959952643ff96e19ad7e6d610cfc241b9778b71bbb12961fc853837e757669693cbff894885e1cdcd318ef51211d2d1af5a08c26260ab91c7adcebe5f981ac17549f0d1b84408192f9b721c53b4a222060204ba56f33c07deb7be28bf14e77e2ee3856b1a78ae10cbc32de80ac7d7fccc0da8097dbcd41e3ede1881d118abcb9c659547c8dac8611d2413c0b415a", "39", "147355a7c79c94b3b04e130fc949d2194d0f180fc04f5117d7b741d437e4f4077c6b2ccac739ba420b2c787c8663a514be17746438b70182977ce480943116ec0c107cf5411e5f820625fc8a461eb09e50212d2ce31b8301bfe1ce6775f7f137f15d7ac401cd76f4e08f748cb05181e0c646ac5b5c4b7c40d62d73c97fa7dc296a3bf0397bad8488d87af0c4704dd43ee84b2f1dafc440750d384ab44363ba9e8a3e391adfc9d6d3a3f79c99609de0110a4c4c41777ade93d844999c34d6347ca2a1ed3444a3690a2eb97a883574a130813c993f74e6a72d426275cd78d075d25fc21d9fe6a1fba5e35845d4f41be340eb75f66b8b4e85509ae5a082fc5ea976a8b022bf452df28b97a7814a1d3d8eac04ff34edea83a0a2fc2d9ed83c9e7f13f892b9f2ba33c7ae69f839fe311876c939b78b633023857f68dd7fa7e982006f94da688a2e3c8ec453f5199b35eed4c6afa38c848f32c9ed73f2a575e729dcaa0dbc8de5e99b1fd19aa85bce3d675a3bca23cacca9321ffcb70cd6bf36b0867e120dcbbc5b8ddd894b0fe429c1bf3abb34b49e5ffc4a442f0e6e698c77a8908e968d7ad0461313055c8e3d6e75f2fcc0d60baa4f868dc22040c97cdb90e29da51110301025d2b799e03ef5bdf145f8a73bf1771c2b58d3c570865e196f40563ebfe6606d404bede6a0f1f6f0c40e88c55e5ce32caa3e46d643", .None}, + {.Shr_Signed, "5fbeed30cde1e2ba6b4615a86b1b2df0b4bffd554333ff238df10636d3bfbec7bf2fb94e9f87f1e1e38f24320f31f82d6041e9a5e86a6343d214bd149140e8a99c138c2114a4a925e2c32c681a0fa515c7058087425a69da41fee3f767b972d7a50f7bd9b69672d92172d6b49020dc1e62899b4ec194163ee02289924d23ad81f88ec0a672fdb7d01715beb1795bb31ab37d61ec6217934e11147618de19e562c3669c72bdf2819554ef563937b608f5a2ff7adbaa8fbcac8b5a4f8fc875c1c7b0667213cb88cb7e12ab4f712f59b5594ff17450a0a3d36735c7cd330cd529dbbec4e3d01b1d64a81b5340de6eb37b66750c49ccc3529c57554c7e3a7634be112f7c8aef02d5b8c6a393dc0baa247e1f7fde297e01f8310bbebdcabba7e8372e368dc32f447de7d1cb78d6f1804f21c94d07948bd9bf42eaa23eb04956ffa632b48402f470f54b2704a666c5127eb8eead168408d26a27c3b763587d3041d25b34e3aee36bbb4a041f716cf117966a76bc8d310d3a16ff30255876782be25bc04c78c9dbd251bf96894c1c016684453384f2887467dece79780403ac20e4bec1824fab9e423fb6accba2b921bc11bf595e51dc5fe719bac08593e5b0051cf2022715379a951f3d1676fb0c3c2e05210e5b596c03dbd5c29bb31be32e5c104e1f3a7b728dba19a977cdc869d430795e9dc5e8de79e5ec0ef23b25086e691cbea4", "4", "5fbeed30cde1e2ba6b4615a86b1b2df0b4bffd554333ff238df10636d3bfbec7bf2fb94e9f87f1e1e38f24320f31f82d6041e9a5e86a6343d214bd149140e8a99c138c2114a4a925e2c32c681a0fa515c7058087425a69da41fee3f767b972d7a50f7bd9b69672d92172d6b49020dc1e62899b4ec194163ee02289924d23ad81f88ec0a672fdb7d01715beb1795bb31ab37d61ec6217934e11147618de19e562c3669c72bdf2819554ef563937b608f5a2ff7adbaa8fbcac8b5a4f8fc875c1c7b0667213cb88cb7e12ab4f712f59b5594ff17450a0a3d36735c7cd330cd529dbbec4e3d01b1d64a81b5340de6eb37b66750c49ccc3529c57554c7e3a7634be112f7c8aef02d5b8c6a393dc0baa247e1f7fde297e01f8310bbebdcabba7e8372e368dc32f447de7d1cb78d6f1804f21c94d07948bd9bf42eaa23eb04956ffa632b48402f470f54b2704a666c5127eb8eead168408d26a27c3b763587d3041d25b34e3aee36bbb4a041f716cf117966a76bc8d310d3a16ff30255876782be25bc04c78c9dbd251bf96894c1c016684453384f2887467dece79780403ac20e4bec1824fab9e423fb6accba2b921bc11bf595e51dc5fe719bac08593e5b0051cf2022715379a951f3d1676fb0c3c2e05210e5b596c03dbd5c29bb31be32e5c104e1f3a7b728dba19a977cdc869d430795e9dc5e8de79e5ec0ef23b25086e691cbea", .None}, + {.Shr_Signed, "-e9ba1ebffba7506a033fae7d0ad97bb4f989364c4c835fe46281a555cb5ff54d7d71c1e3b1a6ac41363368d5d59f724687b9f8b3c6b1ac85b1103104e3ce8b01cd6bbf66acfa49bd973340e55f655137607a031aebb82c390490dbb4522ff444005791173f386168f358bc347e7a6c55afb5b532c1629454c7e654ba3f8ba316622a54295667493b4ef477f6e1979242b2ee2af461a54e909f4851977025c8076bbae67ad68dd3f8b93f6a45f3f894b3ce7f192211cd97418cfd96f0a34f80dc56e6b1157de94ba9954dbcd36593b606355e8d9234cebdf6ebe3b12830434d952b73f0a37aa39bb742915bc20b9ae0816472a476bcc34b5ac9d7087433432068b88e1253b80b5c56c0c95257161e3d749dca5a8f114c5d9e01dfa5a082ebb05ff11b63ba99f69716b4f74e147721c86028a080f780914893b859a792a442a9b8a026376ce5af73adddbe67600e65d225c8ed50343b8e295c1d328d7a944741ec6b5cc5da8ef0425b4c0f61b128c165598202cf1d83ff09761a369f4e95b1ce9ebf1c4be9078ebb1306ac6326f86994ee3256d4237af25560f8efbb1cff3cb3efcc156bc9a78691f9fe072fdd12674cee9963d5b94b4c2f5d6e6d8366a73ec7e96f3d3a0856105c15556a1bdd99ecfa84dea6704f125c34bdf3bb9d5dde27a52d44c50f9bf41b2d8a320fed82593c49e8dcc0f28956b90b1c8cd2ddfd30b8bde7", "5d", "-74dd0f5ffdd3a835019fd73e856cbdda7cc49b262641aff23140d2aae5affaa6beb8e0f1d8d356209b19b46aeacfb92343dcfc59e358d642d888188271e74580e6b5dfb3567d24decb99a072afb2a89bb03d018d75dc161c82486dda2917fa22002bc88b9f9c30b479ac5e1a3f3d362ad7dada9960b14a2a63f32a5d1fc5d18b31152a14ab33a49da77a3bfb70cbc9215977157a30d2a7484fa428cbb812e403b5dd733d6b46e9fc5c9fb522f9fc4a59e73f8c9108e6cba0c67ecb7851a7c06e2b73588abef4a5d4caa6de69b2c9db031aaf46c91a675efb75f1d8941821a6ca95b9f851bd51cddba148ade105cd7040b239523b5e61a5ad64eb843a19a190345c470929dc05ae2b6064a92b8b0f1eba4ee52d4788a62ecf00efd2d04175d82ff88db1dd4cfb4b8b5a7ba70a3b90e4301450407bc048a449dc2cd3c9522154dc50131bb672d7b9d6eedf33b00732e912e476a81a1dc714ae0e9946bd4a23a0f635ae62ed4778212da607b0d89460b2acc101678ec1ff84bb0d1b4fa74ad8e74f5f8e25f483c75d89835631937c34ca77192b6a11bd792ab07c77dd8e7f9e59f7e60ab5e4d3c348fcff0397ee8933a6774cb1eadca5a617aeb736c1b3539f63f4b79e9d042b082e0aaab50deeccf67d426f533827892e1a5ef9ddceaeef13d296a26287cdfa0d96c51907f6c12c9e24f46e607944b", .None}, + {.Shr_Signed, "-7c30674449df8cb9810b81b9dba268509f5c51ffb026a9f5daafa38b30a874c9461a00d7525588cac7e2cf7540cc1c6c9a22f47a30690ef8d238bc3d5a2f39402670932f3dd897e31bb4362e3221e53d70f570e07814a2c8bb12f4d0f54571394434da0d599ed08d5e280a30d1a6c69afa4d0f2a513ca5dca564640ad5fb86907cc7cb65beaa84137a17139e5289fcdfd53570cbd4a6d6a93723c2527ec905ad9880473892cf862576bd01d4f95d89815fa38887ed6ee55f16a1831c117239bda92bab9e14289638d46685e189e9f26f7ba96defb75e5354adaf85097794b8e988e54981510eefd80469e00ace3bf7e7d28370c9fbef6a64b388568588e183f882c147c6e70b0946f7cabaf43b306149821bfee3b258fdcfcffb24d3daeaee6cba7f4747ea0bb73dce04b89923507b650766c89bfe69543ea590e00c600f1dfb842b843985175f34597e3f1aec70a9df4210848bce45d539c9298b6388c17cf9fdf31a59b37635d63cec434a8902ab62e39e0ce85ae2686b3d5eaa11cacbd3b61a2960957edc891d36f7b0e96ad2d2fbf94076071a99d8e8d97a5408406ff03c58ae6507ce179eb77a7790247540bc0e69211224d5f1f09ed0ba0a13eb9ef53f97833dbea22b9d6d98ce4912a86bb29c3294080a1220600360a7faf44db3322ddd6fae002616f3236e36c7faf00436650880ee662f4086683f051ed379fb3d77", "2b", "-f860ce8893bf197302170373b744d0a13eb8a3ff604d53ebb55f47166150e9928c3401aea4ab11958fc59eea819838d93445e8f460d21df1a471787ab45e72804ce1265e7bb12fc637686c5c6443ca7ae1eae1c0f02945917625e9a1ea8ae2728869b41ab33da11abc501461a34d8d35f49a1e54a2794bb94ac8c815abf70d20f98f96cb7d550826f42e273ca513f9bfaa6ae197a94dad526e4784a4fd920b5b31008e71259f0c4aed7a03a9f2bb1302bf47110fdaddcabe2d43063822e4737b5257573c28512c71a8cd0bc313d3e4def752dbdf6ebca6a95b5f0a12ef2971d311ca9302a21ddfb008d3c0159c77efcfa506e193f7ded4c96710ad0b11c307f105828f8dce16128def9575e87660c2930437fdc764b1fb9f9ff649a7b5d5dcd974fe8e8fd4176e7b9c09713246a0f6ca0ecd9137fcd2a87d4b21c018c01e3bf7085708730a2ebe68b2fc7e35d8e153be842109179c8baa73925316c71182f9f3fbe634b366ec6bac79d88695120556c5c73c19d0b5c4d0d67abd54239597a76c3452c12afdb9123a6def61d2d5a5a5f7f280ec0e3533b1d1b2f4a81080dfe078b15cca0f9c2f3d6ef4ef2048ea81781cd2422449abe3e13da1741427d73dea7f2f067b7d44573adb319c922550d76538652810142440c006c14ff5e89b66645bbadf5c004c2de646dc6d8ff5e0086cca1101dccc5e810cd07e0a4", .None}, + {.Shr_Signed, "7998f400499c966d35597c6446935cc0da5351f940b5496959eaa191c6acc17ee4191531b6b78cc33240dcfe789c5eba5d5f2897492c9238c79b03980673f315ef4de561fdd4c911c8c739006bceb825a759c41768567d9a9a967671da28803aa33473ce3d6007729263e0b12f9bfcbe4f17737f843d0ffecb355ae5927107940093bd22aa191f8df387ede146ba4de6d0ac09f1223bf152898656e1b06089842ed828858afabca9d8f2ae233ff77b4d9b20688736a9b565e211a94d86dd6893dccd829af5f6960e1c20a21b77df993acbc5dfb2ec010729f8b1b7cc5d9f90ea3b6e0965f237c33d7d35bf60a3cdacb658d1099d4ff369e6bba1b7d2965cc37b550400a45ed0c7cf1b36858eae29893a7a329596d1ea3192b37f006a322040c9519b1170cc8a73727756623771777e6b2a5a56d4831f70d6a1a4108679ecf4d14b371e34ef662756b82b4cd0f829ab552631f3de5d9d313f819b0dba4ae0db34a87679448cf6d6027831917c329684c87d6096a1e40735f49c069af5bf64f247f2e86e71e9e7e31a238e9c9dff0be451f7ed1935b4ed63dae2bb7370ec68c0d4d51d68a8bbed7f7b1aa4aa6f93db55a8171a9a7a1ca440e2aeb3094b3d0a1b0ab477e31dec59d725e8daacabf8d66fb0634025aa1fe566a61a557d7fe0c887d01e16e8aa32e56e96aed631fcb496ec7ddc3d22088b2a9564022bce7454695e6c", "11", "3ccc7a0024ce4b369aacbe322349ae606d29a8fca05aa4b4acf550c8e35660bf720c8a98db5bc66199206e7f3c4e2f5d2eaf944ba496491c63cd81cc0339f98af7a6f2b0feea6488e4639c8035e75c12d3ace20bb42b3ecd4d4b3b38ed14401d519a39e71eb003b94931f05897cdfe5f278bb9bfc21e87ff659aad72c93883ca0049de91550c8fc6f9c3f6f0a35d26f3685604f8911df8a944c32b70d83044c2176c1442c57d5e54ec7957119ffbbda6cd9034439b54dab2f108d4a6c36eb449ee66c14d7afb4b070e10510dbbefcc9d65e2efd976008394fc58dbe62ecfc8751db704b2f91be19ebe9adfb051e6d65b2c6884cea7f9b4f35dd0dbe94b2e61bdaa8200522f6863e78d9b42c75714c49d3d194acb68f518c959bf803519102064a8cd88b8664539b93bab311bb8bbbf35952d2b6a418fb86b50d208433cf67a68a59b8f1a77b313ab5c15a6687c14d5aa9318f9ef2ece989fc0cd86dd25706d9a543b3ca2467b6b013c18c8be194b42643eb04b50f2039afa4e034d7adfb27923f9743738f4f3f18d11c74e4eff85f228fbf68c9ada76b1ed715db9b87634606a6a8eb4545df6bfbd8d525537c9edaad40b8d4d3d0e522071575984a59e850d855a3bf18ef62ceb92f46d5655fc6b37d831a012d50ff2b3530d2abebff06443e80f0b74551972b74b576b18fe5a4b763eee1e910445954ab20115e73a2a34", .None}, + {.Shr_Signed, "-937b061093c615d44c8d6e5884edbfaf7fdfb9e52e7a0d09e08f6ba50570f068333945e9eb8dc6e41d46b4e30b8fc0eb8028844bdaeddbf3fab1bfb0297a0da92b0e9e6cf678458c2d03044fd6b94965bc65d2d34c144882a2c8bcb9838908919269ea519b9379fa30f7baa0d85078b61a00b0e48180a575a79da6429b5d962af7b98b607e79407b3114f638bc12718f5e3e051b2dde1e8b2400d672dbe1210809489ab5127319b1d5dd18f18f23facf0f356a6aa59dc63288155871cee48a4d3ed5d4875a639b09ae82b785b9e61c5fb1eb352702ab8e65a1d20ac9ae23c8069752a1fd9b0317763199df4b2dd7c01ac354b32c805e3f260b4d1cff3cf2a4fb0ae83e7957842168b8a8b89e246e0e71aea9554ea91848d1d17b8e84a45c3f7281689683dda5592e097a0b7484016db35d4da1de8cd351333794739d2c11a4ef662155fdb51f9f39b5981cfd4ed26d0dfeb4689a04bbb2888b195a9c44d0c31019ebcfffdabb505cb781afced4dee7f03b58324484d4b28ad2e2ba1de35ea7d0be2dda829ea25ccc1ca2a5e7820dd7ab2c5441671045fd2b1c35370cbb2bbc77fec2a4ffa5a81f0beeca01b28ab7393a4b930561c7124fc8d62d4cf99a998661b6702ffe42b74067efe3635adcf28e729c97c6b0d83dceb7ab652426428448afbf9fca7188ef41986acaeb2148a4efa30937ba5ff288eef073d6a5aaef9dcae4", "14", "-937b061093c615d44c8d6e5884edbfaf7fdfb9e52e7a0d09e08f6ba50570f068333945e9eb8dc6e41d46b4e30b8fc0eb8028844bdaeddbf3fab1bfb0297a0da92b0e9e6cf678458c2d03044fd6b94965bc65d2d34c144882a2c8bcb9838908919269ea519b9379fa30f7baa0d85078b61a00b0e48180a575a79da6429b5d962af7b98b607e79407b3114f638bc12718f5e3e051b2dde1e8b2400d672dbe1210809489ab5127319b1d5dd18f18f23facf0f356a6aa59dc63288155871cee48a4d3ed5d4875a639b09ae82b785b9e61c5fb1eb352702ab8e65a1d20ac9ae23c8069752a1fd9b0317763199df4b2dd7c01ac354b32c805e3f260b4d1cff3cf2a4fb0ae83e7957842168b8a8b89e246e0e71aea9554ea91848d1d17b8e84a45c3f7281689683dda5592e097a0b7484016db35d4da1de8cd351333794739d2c11a4ef662155fdb51f9f39b5981cfd4ed26d0dfeb4689a04bbb2888b195a9c44d0c31019ebcfffdabb505cb781afced4dee7f03b58324484d4b28ad2e2ba1de35ea7d0be2dda829ea25ccc1ca2a5e7820dd7ab2c5441671045fd2b1c35370cbb2bbc77fec2a4ffa5a81f0beeca01b28ab7393a4b930561c7124fc8d62d4cf99a998661b6702ffe42b74067efe3635adcf28e729c97c6b0d83dceb7ab652426428448afbf9fca7188ef41986acaeb2148a4efa30937ba5ff288eef073d6a5aaefa", .None}, + {.Shr_Signed, "319b0af6190649a6fc8064f93f6a75f1c378c0c54e1817757e2b61c139877b4086d568eb1a1a3e09bc4e3203f390978af1d81194534c35f7caa73ff567c61d98be6eb81ce4e2df50995a59617a742e2ef8329adf13e0c0fcb99ed0f02c32d0ae7f3663de86eb9df05d50dd11947e087c9b19ddba3fc6e5060ec123a8a8bc0a1a22b5c967611d673e90f28648ee16b4cab7facdd79fc635fbc6501629bf2cd6e2410151b2a9da4982b32fd1ca0f739fce2d5f17a54871ad30f96c7bba75cc0fc5b7033e13660f29454d26bc4941206fbeae577782a48a88366e1c51005e9ca2d40be694741e87c193d92eb9dbe616a8aca2bb5e78ebc8d2f15f309019c3bec1e728b01aaa9aab9987642a937c8b42e51d954c5b470ca78f6bbb17b568446f96109a51ea63b81dad13deb8a77181df8751a3d72a36075ea82e7cbe75e747a2b3bee8df96ef50fa2aaa26ae08c792336928366e9749d734381706a49510d77da4fba22b341bc447434fdc221a3add16760611238e00b30fc3cedc98e32c55aab62969778c1355d44d5f42dbe79f8f823a9cfacda37e8911075cfa1641463e54032a684263c1cde0ceb14edb3e2721e6e077618d0deaefdb22d87c8e50f265f9bc251d1cac3e87d646e8cb14a83a70d21a39dcfdadb0da0da3304dceab47fba3201b21490b2c786559203de9ed181fbb0e237639883f858a634c940370069ee19680", "61", "18cd857b0c8324d37e40327c9fb53af8e1bc6062a70c0bbabf15b0e09cc3bda0436ab4758d0d1f04de271901f9c84bc578ec08ca29a61afbe5539ffab3e30ecc5f375c0e72716fa84cad2cb0bd3a17177c194d6f89f0607e5ccf6878161968573f9b31ef4375cef82ea86e88ca3f043e4d8ceedd1fe37283076091d4545e050d115ae4b3b08eb39f48794324770b5a655bfd66ebcfe31afde3280b14df966b712080a8d954ed24c15997e8e507b9cfe716af8bd2a438d6987cb63ddd3ae607e2db819f09b30794a2a6935e24a09037df572bbbc15245441b370e28802f4e516a05f34a3a0f43e0c9ec975cedf30b5456515daf3c75e46978af98480ce1df60f394580d554d55ccc3b21549be45a1728ecaa62da38653c7b5dd8bdab42237cb084d28f531dc0ed689ef5c53b8c0efc3a8d1eb951b03af54173e5f3af3a3d159df746fcb77a87d155513570463c919b4941b374ba4eb9a1c0b83524a886bbed27dd1159a0de223a1a7ee110d1d6e8b3b030891c7005987e1e76e4c71962ad55b14b4bbc609aaea26afa16df3cfc7c11d4e7d66d1bf448883ae7d0b20a31f2a0195342131e0e6f06758a76d9f1390f3703bb0c686f577ed916c3e47287932fcde128e8e561f43eb2374658a541d38690d1cee7ed6d86d06d19826e755a3fdd1900d90a485963c32ac901ef4f68c0fdd8711bb1cc41f", .None}, + {.Shr_Signed, "12aef241eb782bb091874f87ccc9341bd29351697bcb95bac2d9c1adad1070b9c2cabd2349768785b847294652ee1ec9ca288ca7d3a4c809b2251c0b46c59df1f420092c7a1b83fa17384af8634ab8f20b06840c84bd4660c0d0132d9f652c1886c3772991bb17b239e8fe6ed4f4dcda07201c1646430a8ef35cf5990d9a615bf78462562c2fe4c34de356ea000e9a7ab76b675e222929e95fe7b3391d78b03020388b63bfb97c598e153c6a9335ea1928b920a4adaaa60c76e97cc5c2bbd67fd8e9cad8864dfd375e8be245804c7922f86dd7460d41f37b7df62455051dfaff4a76bb6e028313174fbf195c8b17dbda7bd85db181c91e120585ca36750032adb918945fa22cc39d689aea2b455a0a98d66a0abbfb21d196c16cb7fee21b2f94059582c3e30def938718c2a69be002723462e4e2076fa5a6db53e98f5ecd0de604e1121933c94b780f62a9cb0120874ede9d9ad7d33c79c5ec50e2e4f200e079b202e7d7a1e3f2e8ac91e284d0447aee5896a16a24b983f235ad2fd0dd72fb569323848025f5d2f86a8493cb63fd2ed8d0732318ca09afab4cbf91b6669789b89e84f122fe0e9044f86e84f21e41297618e66bfbed0101a90e93dfcf7c7c666dabe27bb5ef03dda322e2744c861995414b3d01328e7cfdb380588d1070992c307edcdd28a6c808284a6f42380a085989e341fdb878de08031a9eb12df422585b", "4f", "255de483d6f05761230e9f0f99926837a526a2d2f7972b7585b3835b5a20e17385957a4692ed0f0b708e528ca5dc3d939451194fa7499013644a38168d8b3be3e8401258f43707f42e7095f0c69571e4160d0819097a8cc181a0265b3eca58310d86ee5323762f6473d1fcdda9e9b9b40e40382c8c86151de6b9eb321b34c2b7ef08c4ac585fc9869bc6add4001d34f56ed6cebc445253d2bfcf66723af16060407116c77f72f8b31c2a78d5266bd432517241495b554c18edd2f98b8577acffb1d395b10c9bfa6ebd17c48b0098f245f0dbae8c1a83e6f6fbec48aa0a3bf5fe94ed76dc0506262e9f7e32b9162fb7b4f7b0bb6303923c240b0b946cea00655b723128bf4459873ad135d4568ab41531acd41577f643a32d82d96ffdc4365f280b2b0587c61bdf270e31854d37c004e468c5c9c40edf4b4db6a7d31ebd9a1bcc09c22432679296f01ec5539602410e9dbd3b35afa678f38bd8a1c5c9e401c0f36405cfaf43c7e5d15923c509a088f5dcb12d42d4497307e46b5a5fa1bae5f6ad264709004beba5f0d5092796c7fa5db1a0e6463194135f56997f236ccd2f13713d09e245fc1d2089f0dd09e43c8252ec31ccd7f7da0203521d27bf9ef8f8ccdb57c4f76bde07bb4645c4e8990c332a82967a02651cf9fb6700b11a20e1325860fdb9ba514d90105094de84701410b313c683fb70f1bc", .None}, + {.Shr_Signed, "-e5c26cdf342cb5e680c5b8fdee7b882990fd1bc577038e5b587d0d1cc4bf4dc35f0f6a85a6a109b3e9563bc29bc11542a47b7f28c65d3c235b1a9ccc20bbb434ab5403b1d43ef16ed1066349112c9eeb0317a5150efe122de1e33195f2e19b90a0e785fd6907f532f574b07eb99f8a3805de9ad9de27f976404e158ac5cb0fc511f2be7745e8e2ea47cb9657cc3b79ed4c11fbe6ac945c3b0411dce2ec94e9630753e0307b59a4b6dd3553c2c5b302bc1d39531b60c5a2af526d18f71f059098f7608062e9275768fd8f6ca991bd4115d3d491053db513e52bc44ed36a1ac1e2eaa479865762079d5c7c3582670f8532fa37ef03bcffc1ebf1665240d5dc8f08898075538bd179d70575ce0e901445aa8a5eaab3d0549b207314e54fa7493c22dc468fb638bae9dcce7a3b5b22d8f0a5f7389c22962e50cea65bdf8c9fe3cf474f9a02e6959c6fb7cbbf3f2b672a5df631f388e15deae0e7f1111aef486c059ae652c52a2a555690c829684c56f49143b9a8f1c2ba3ce0e8faf91664764a426257136de3e9e39685052d8a542750932f8d689c5fa61879f4296594a99c9af98980fafcbfdd40a54105f8f5ea6aa54d32a1261fe7f835da53e81c0761693db627732db86ad0f1609783089c605a1212c6832186754627707d1d5c396367f716290643230e09f89efa2e78387ee50430bc3dca7a14e4abce0e3446b339bfbd6d84", "51", "-72e1366f9a165af34062dc7ef73dc414c87e8de2bb81c72dac3e868e625fa6e1af87b542d35084d9f4ab1de14de08aa1523dbf94632e9e11ad8d4e66105dda1a55aa01d8ea1f78b7688331a488964f75818bd28a877f0916f0f198caf970cdc85073c2feb483fa997aba583f5ccfc51c02ef4d6cef13fcbb20270ac562e587e288f95f3ba2f4717523e5cb2be61dbcf6a608fdf3564a2e1d8208ee71764a74b183a9f0183dacd25b6e9aa9e162d9815e0e9ca98db062d157a9368c7b8f82c84c7bb040317493abb47ec7b654c8dea08ae9ea48829eda89f295e22769b50d60f175523cc32bb103ceae3e1ac13387c2997d1bf781de7fe0f5f8b329206aee478444c03aa9c5e8bceb82bae707480a22d5452f5559e82a4d90398a72a7d3a49e116e2347db1c5d74ee673d1dad916c7852fb9c4e114b172867532defc64ff1e7a3a7cd01734ace37dbe5df9f95b3952efb18f9c470aef57073f8888d77a43602cd73296295152aab486414b4262b7a48a1dcd478e15d1e70747d7c8b323b2521312b89b6f1f4f1cb428296c52a13a84997c6b44e2fd30c3cfa14b2ca54ce4d7cc4c07d7e5feea052a082fc7af53552a69950930ff3fc1aed29f40e03b0b49edb13b996dc356878b04bc1844e302d0909634190c33aa313b83e8eae1cb1b3fb8b148321918704fc4f7d173c1c3f7282185e1ee53d0a7256", .None}, + {.Shr_Signed, "5190079832ee3f50cc7c991f6a72d8fe80fed12358506a71ccb97aa75a90031c472426ff95690ead0eb80d9df0efd7f93bde40f9e14a0fe83f20d1377208cd15b89a9e9f74c389aa8e3cec8143a4efc39d96d0609cfdbaeadd96542d95ca2be0f1cc8d4ab0436770d0bc08b0f0b1c01b116a0d334ca6d3920ce75d620afca557c51d7e35e14c455503a9bc1f0b436659991c538125a737f58c1855093e3cbad2d51bc4e45b97eeb65af9a24a293565be616c2b0d8fd7b9fa8615a00779701aad0c54737c8f4e3a2965bb9c6d7820d75011f8f9a40fe8150ef8a054261c523c6ad0235e38215b684a5e65a1d5e0bfcee3feca69e1489cd305b245ca4459ca630c2c2146ad018162bfb00238a744f1555a83d66a3a0a33ef7fb09eb2bc098436eb5711c628e19ef96a63377baf08ed272effd4a61d6a8495a8d3e5bc585120d7a90044de9b2bdd3310ed4dcbbf11506fdab7ef93a4b03c7ea6056c951e23c31e1f7de60a53a5704117d31e1588a0153fb6aa9ad4c4a67f1600e22926fb9cbe5544989d88d7c087ce8e3dcc191c34056e9bed32338d4282394fea8ee7fd80c29d0e5204164e126728022f05310c02da3b00f7aefc9c9393384724e15a9ab673747bd4bfa0ee2d37691b6a581b9069ed4fbed2211f25f4e12b3e522ceba6ef143fef12fc8ca23c9ca8f95f875a46e7a137ffc420ba944fd553b3841b8f28d9a1b8b6", "54", "5190079832ee3f50cc7c991f6a72d8fe80fed12358506a71ccb97aa75a90031c472426ff95690ead0eb80d9df0efd7f93bde40f9e14a0fe83f20d1377208cd15b89a9e9f74c389aa8e3cec8143a4efc39d96d0609cfdbaeadd96542d95ca2be0f1cc8d4ab0436770d0bc08b0f0b1c01b116a0d334ca6d3920ce75d620afca557c51d7e35e14c455503a9bc1f0b436659991c538125a737f58c1855093e3cbad2d51bc4e45b97eeb65af9a24a293565be616c2b0d8fd7b9fa8615a00779701aad0c54737c8f4e3a2965bb9c6d7820d75011f8f9a40fe8150ef8a054261c523c6ad0235e38215b684a5e65a1d5e0bfcee3feca69e1489cd305b245ca4459ca630c2c2146ad018162bfb00238a744f1555a83d66a3a0a33ef7fb09eb2bc098436eb5711c628e19ef96a63377baf08ed272effd4a61d6a8495a8d3e5bc585120d7a90044de9b2bdd3310ed4dcbbf11506fdab7ef93a4b03c7ea6056c951e23c31e1f7de60a53a5704117d31e1588a0153fb6aa9ad4c4a67f1600e22926fb9cbe5544989d88d7c087ce8e3dcc191c34056e9bed32338d4282394fea8ee7fd80c29d0e5204164e126728022f05310c02da3b00f7aefc9c9393384724e15a9ab673747bd4bfa0ee2d37691b6a581b9069ed4fbed2211f25f4e12b3e522ceba6ef143fef12fc8ca23c9ca8f95f875a46e7a137ffc420ba944fd", .None}, + {.Shr_Signed, "-388d31eea8125c1c797517efe2c86f1022eff3c40c96c074b72f2d702e6973274843be2b70d35960c7963656542b12e4912a0f18021fefb542eb775ddac0565596d98706ff93445ebb22da98dca55ea755bc8ceb9f38f7b20e270c49c87bad1b3dc742a263775ee91fa5168f2fc38f6b7fefbe7632aed7e3d887ee2d976c840518ba2c7bec962063f92130d8d239fa9fe280c67e2fc994a9b919b5408a4b0f537d9e06348a06b5be7172539799d346e4399800e079e6cdaf5f67b6f8f87fea6af472edffed5f9423234ee790fbb00c6125da69e0402730395b2a9432688c06d33dfe88ff24e25cdd664f20ff820c6785ba08bac8949ad527e999554b1d0b96067f57e062a4dae3e0d51f912d9af926f72ba30261edfd33e4326b71aa9fc0fe370c46ff4ddd6f68417515ae98e8c34ad70082af0d64946fd35890b0b8bd5c58de41fcf0712b57d72b5e8b4c1407f346b9afb24739a66262c6970c2ee58fde521319a40709a6fb516f4d0769d488d12ad13bdbed1126fb0d7d1807d4a441b7a4524d33e1d6c5b700fd5c79f8cc98545dcaea660c7e013abf2cd4880f96d2be29ea004683363a45dea1c9e377d9cc991d7c87a612ed45f4b9e34cc6cea0b9023129098388e25937d75006b69cffab403e76157a0c6dd4dd28bdcb72cb7d71d5a2e939b748dc87d1bad5fd8be73d442e11ec19513c66292422e36f88d71553e61f61", "46", "-e234c7baa0497071e5d45fbf8b21bc408bbfcf10325b01d2dcbcb5c0b9a5cc9d210ef8adc34d65831e58d95950ac4b9244a83c60087fbed50baddd776b0159565b661c1bfe4d117aec8b6a6372957a9d56f233ae7ce3dec8389c312721eeb46cf71d0a898ddd7ba47e945a3cbf0e3dadffbef9d8cabb5f8f621fb8b65db2101462e8b1efb258818fe484c36348e7ea7f8a0319f8bf2652a6e466d502292c3d4df67818d2281ad6f9c5c94e5e674d1b90e6600381e79b36bd7d9edbe3e1ffa9abd1cbb7ffb57e508c8d3b9e43eec031849769a781009cc0e56caa50c9a2301b4cf7fa23fc93897375993c83fe08319e16e822eb22526b549fa665552c742e5819fd5f818a936b8f83547e44b66be49bdcae8c0987b7f4cf90c9adc6aa7f03f8dc311bfd3775bda105d456ba63a30d2b5c020abc359251bf4d6242c2e2f571637907f3c1c4ad5f5cad7a2d30501fcd1ae6bec91ce699898b1a5c30bb963f79484c66901c269bed45bd341da7522344ab44ef6fb4449bec35f4601f529106de914934cf875b16dc03f571e7e3326151772ba99831f804eafcb352203e5b4af8a7a8011a0cd8e9177a87278ddf67326475f21e984bb517d2e78d331b3a82e408c4a4260e238964df5d401ada73fead00f9d855e831b75374a2f72dcb2df5c7568ba4e6dd23721f46eb57f62f9cf510b847b06544f198a4908c", .None}, + {.Shr_Signed, "833890ea04ba373472c681b2f180c4830ea9b5ac32480bfb718aa1e89f82be247df16b6de4af39f99fe1d15b66ceaaf9c9f5c6f6afbdb5da9de63651c712a8816a9ad55b52695e623727a5ea6deaabde2bf278dcd2e6d1873dabd3459bdccb51b09200b8209dfd1285c18a32aebf2ecd587512e10fa247ce0438bc4881c25e0cfc401f77748d229ab12085cad03920ce5639ef3047d3b7722a827994453c5d9bfe977ba1f103a6b46ab0361492db690e4ca7ee0fac4466f574e6ef02b28fdf4e98a6a6eacc11de2a304df957f42e7fc728c2efa76c7907fca15e221f8a1aa0278015b06d6fa27829a4a84e3783fe9ac59b441b375632ae76cc382237af7129922cfbf1026afce39facad281dbbc714418d3046daa52b0446442dfe2260a5e3fd0b088103d3be58260898ddb15994784a51d954d55d464a21040f023a72b32ccef326719ecd19e9149aa8e99406e21775b5fd0489af1dbd3bf9bcb53c20a9d2a208e8384fddaa11279d8d5afb498ebce95381d60b19951740480140166ac3c845209505dc2068ab834794d77cb0690ec21f984c8774f09fcf73dae809bb32f321cbf12881fa010ac2f728d9db70380d6d7e2f69c838a50184c3ecc12f438835f98e154cd79528ac0ee66ef81650d1b00d343cd7541ccefcc9da899527c0d892df742b3f43aa94145354341946b463a6a42189e917539b5e270e75df9448325398", "13", "1067121d409746e68e58d0365e30189061d536b58649017f6e31543d13f057c48fbe2d6dbc95e73f33fc3a2b6cd9d55f393eb8ded5f7b6bb53bcc6ca38e255102d535aab6a4d2bcc46e4f4bd4dbd557bc57e4f1b9a5cda30e7b57a68b37b996a361240170413bfa250b8314655d7e5d9ab0ea25c21f448f9c087178910384bc19f8803eeee91a453562410b95a072419cac73de608fa76ee45504f3288a78bb37fd2ef743e2074d68d5606c2925b6d21c994fdc1f5888cdeae9cdde05651fbe9d314d4dd59823bc54609bf2afe85cff8e5185df4ed8f20ff942bc443f1435404f002b60dadf44f05349509c6f07fd358b3688366eac655ced9870446f5ee2532459f7e204d5f9c73f595a503b778e28831a608db54a56088c885bfc44c14bc7fa16110207a77cb04c1131bb62b328f094a3b2a9aaba8c9442081e0474e566599de64ce33d9a33d2293551d3280dc42eeb6bfa09135e3b7a77f3796a784153a54411d0709fbb54224f3b1ab5f6931d79d2a703ac16332a2e809002802cd587908a412a0bb840d157068f29aef960d21d843f30990ee9e13f9ee7b5d0137665e64397e25103f4021585ee51b3b6e0701adafc5ed390714a030987d9825e87106bf31c2a99af2a51581dccddf02ca1a3601a6879aea8399df993b5132a4f81b125bee8567e87552828a6a868328d68c74d484313d22ea736bc4e1cebbf28906", .None}, + {.Shr_Signed, "-28e569e25eb0896740e990649712256eeddab13f50a0c580b077ba48fff65879dd4db68ce68b436d70fe5e672dcd8e347d750b06a1308484dd0520bb1a32455e5d78f19bc1b588e20a8d547863c01ab5eece29216b60117984cf8cc6036eb8b23785f49dd4cb8f7d68136a430595b747287960d038ee15c759b67ed175605148b37cfc72b93faa2fd8f0482311c02bff9920bfa09f0f4e0dfef5656ae45a60367febd4843c966782c265130dbf60af3c80252087ea2a3acbdbb4e43d3b29748a68fa60910e3f5a0847a40f61fe1af6911bc639f4b8dbe0556689cfda9694a31f0b86c2c26b4e13c7626f2576e1d155bb1305da24eafebb137f87862bb39611a33af48dd71529cd3a5720b8cdaac193b900edaec298af1f4a0d80b357d92cf7373d0b93539715b776e20148089d0ae4ffc1de967bce15feaf891bdd89ef809f5292d89a279fd91145dd269df41af59a4737c4834782fa7603ecbef8fc4cc159db8f7b7447cb7e5d9cf3cbbcafe6edf75330264b68832c18abf069d8346be8581ca59f93b21fb2c944d0410c1170a573eb513adf641a86e5f0383f0e9c3bfdc800ba45c51658bd63b39ccfff2ac08eb310e5dd9d76f7c0e40003d81e80426c9188ec2cc22620e2fed91c96b6324764729ca8742fdb06b9bff9df119af1d11b0d3e1add0c3a9d017d435e0913a37223846e7d3cdd381f0309a5be7d7a8eb7d88b74", "56", "-a395a7897ac2259d03a641925c4895bbb76ac4fd42831602c1dee923ffd961e77536da339a2d0db5c3f9799cb73638d1f5d42c1a84c21213741482ec68c9157975e3c66f06d623882a3551e18f006ad7bb38a485ad8045e6133e33180dbae2c8de17d277532e3df5a04da90c1656dd1ca1e58340e3b8571d66d9fb45d5814522cdf3f1cae4fea8bf63c1208c4700affe6482fe827c3d3837fbd595ab916980d9ffaf5210f2599e0b09944c36fd82bcf20094821fa8a8eb2f6ed390f4eca5d229a3e9824438fd68211e903d87f86bda446f18e7d2e36f81559a273f6a5a528c7c2e1b0b09ad384f1d89bc95db874556ec4c176893abfaec4dfe1e18aece58468cebd2375c54a734e95c82e336ab064ee403b6bb0a62bc7d283602cd5f64b3dcdcf42e4d4e5c56dddb88052022742b93ff077a59ef3857fabe246f7627be027d4a4b62689e7f644517749a77d06bd6691cdf120d1e0be9d80fb2fbe3f13305676e3dedd11f2df97673cf2ef2bf9bb7dd4cc0992da20cb062afc1a760d1afa16072967e4ec87ecb251341043045c295cfad44eb7d906a1b97c0e0fc3a70eff72002e917145962f58ece733ffcab023acc43977675dbdf0390000f607a0109b24623b0b30898838bfb64725ad8c91d91ca72a1d0bf6c1ae6ffe77c466bc7446c34f86b7430ea7405f50d78244e8dc88e11b9f4f374e07d", .None}, + {.Shr_Signed, "-2b420f5defb5fbf06550ec44986714ff42c33f8defbd17ff98fa5b9c80f6b17ce8ce607b0f6bd6f466d76f08ec77ca6501350db86177ce6388d75c0cbdb7d5bbea34dac96b5ef1e81aebd3d676c662a3e419be2af343bfbc0e061695e2283d1c15d6b9f95064cce19e54a655b6cf321d13957c810666b798d18ec4b49adc22479e1e556872aa04673f25c45bfe9ec3095d81608def5ed84eac0b346eee166756fcb143cfce8a902d7a565f042b15a2d8b5a356a4356f7590f2c81299de6fcb72316df5729a239d64df2fde7b5b7456ab1e1aa6d368cf400acd768d63a53df1daaa7ca36510f6b2d5c04a29fae49cfe9436467f61a5465d804453099dfa171d16a065949135868d86c20814e62c21d88df4dd71640144aa59a8eb0f165984f94744e5c87bddb84ec24cc251387d13071528e6a12324820c902a6ac8db06be507217b39efb4d862efab4197403515105dc521a1e98795da5637b4ed2475fff0013b8e997d3f6cff5c2da70e5378c3ea08467d75e18d25ddea7442500c0cda3a7dd9911a11df3429c76018bc88ad7309ce500891c4da07961774989f1d3b69c6dddfa9e261069958907bff7543c2a5c44ef464e88bba9f79debec190ff3644474974b1a5ebdd474a96b28ea3db278491215e066dd9839b7baf491673e569bf425642b3228b32483b1fe80d574aacd6878f9a78112b873efdf96017a4493cf466cf2", "64", "-2b420f5defb5fbf06550ec44986714ff42c33f8defbd17ff98fa5b9c80f6b17ce8ce607b0f6bd6f466d76f08ec77ca6501350db86177ce6388d75c0cbdb7d5bbea34dac96b5ef1e81aebd3d676c662a3e419be2af343bfbc0e061695e2283d1c15d6b9f95064cce19e54a655b6cf321d13957c810666b798d18ec4b49adc22479e1e556872aa04673f25c45bfe9ec3095d81608def5ed84eac0b346eee166756fcb143cfce8a902d7a565f042b15a2d8b5a356a4356f7590f2c81299de6fcb72316df5729a239d64df2fde7b5b7456ab1e1aa6d368cf400acd768d63a53df1daaa7ca36510f6b2d5c04a29fae49cfe9436467f61a5465d804453099dfa171d16a065949135868d86c20814e62c21d88df4dd71640144aa59a8eb0f165984f94744e5c87bddb84ec24cc251387d13071528e6a12324820c902a6ac8db06be507217b39efb4d862efab4197403515105dc521a1e98795da5637b4ed2475fff0013b8e997d3f6cff5c2da70e5378c3ea08467d75e18d25ddea7442500c0cda3a7dd9911a11df3429c76018bc88ad7309ce500891c4da07961774989f1d3b69c6dddfa9e261069958907bff7543c2a5c44ef464e88bba9f79debec190ff3644474974b1a5ebdd474a96b28ea3db278491215e066dd9839b7baf491673e569bf425642b3228b32483b1fe80d574aacd6878f9a78112c", .None}, + {.Shr_Signed, "2587020d963bc91e1b127de06d8c950efb61bd4aec302616c00d3eeb7e1798e0682a227eed8b47ecc1101fe682e72457b96cf949cfd3fe1d36c74a917a1c71b368aead8ee9700b5a43a2f57c8568be1d77fe76148441398b07d126453387983b92513771a5f05d58290240b74a51c9c5003714eff450b38383e6834ab3ed5844fdfa3918b0238b620f2a8465681b7f0209b92260ef05e0e6aa7b71bcd25d6b5b05d6910d830f6e04ba7efe913e03e92e0275af3dc619cf8573e57ee1a6951c3a9f104a312fec87d8c9eb6065df9de319dfb37f33735a17fbaa92869613ceba7b21171a60a565bf57e17f8de9bb062e0b6235b99b4740877ea6643780df92967460837bbff9268ef9bf3b2f2ee77ded4ab4ce2c0ccb5d5fa70fc36851ed026ceb92c2884dfb0cb6dd6bec703b89b857c56b22034933f8ff9f6c8e19a00400a89a8e350e8ce9a0c0cfecff21793b67450be2ee4ed2562302228867cb78b9307642e26618820b183a453f8be40d941aa13b68e1b271b0d91750d4b05e78f3e5bccc1397f883cd01d849b6fff23c55a57d2bc3b7290d5b23b2e2a659155deae849dbe98cd34361a96d53a75f5bb693976e049fac45b2b06aaccac8fcad18c903d06f75a472f13f64d81bdf6d7970f79b68f2e08b306144f80d4bda42570f0dbe5b3a3dfbe3d777b908ba6005641d365de7f74c4b1b2f7096a6fdb495a92fe7d312ff", "74", "2587020d963bc91e1b127de06d8c950efb61bd4aec302616c00d3eeb7e1798e0682a227eed8b47ecc1101fe682e72457b96cf949cfd3fe1d36c74a917a1c71b368aead8ee9700b5a43a2f57c8568be1d77fe76148441398b07d126453387983b92513771a5f05d58290240b74a51c9c5003714eff450b38383e6834ab3ed5844fdfa3918b0238b620f2a8465681b7f0209b92260ef05e0e6aa7b71bcd25d6b5b05d6910d830f6e04ba7efe913e03e92e0275af3dc619cf8573e57ee1a6951c3a9f104a312fec87d8c9eb6065df9de319dfb37f33735a17fbaa92869613ceba7b21171a60a565bf57e17f8de9bb062e0b6235b99b4740877ea6643780df92967460837bbff9268ef9bf3b2f2ee77ded4ab4ce2c0ccb5d5fa70fc36851ed026ceb92c2884dfb0cb6dd6bec703b89b857c56b22034933f8ff9f6c8e19a00400a89a8e350e8ce9a0c0cfecff21793b67450be2ee4ed2562302228867cb78b9307642e26618820b183a453f8be40d941aa13b68e1b271b0d91750d4b05e78f3e5bccc1397f883cd01d849b6fff23c55a57d2bc3b7290d5b23b2e2a659155deae849dbe98cd34361a96d53a75f5bb693976e049fac45b2b06aaccac8fcad18c903d06f75a472f13f64d81bdf6d7970f79b68f2e08b306144f80d4bda42570f0dbe5b3a3dfbe3d777b908ba6005641d365de7f74c4", .None}, + {.Shr_Signed, "6d72601a4f3ab2044904e4230b812d9f1872c1a8d1f1f0663bd9dbb84db776043fda70c373c65822cfd28c0e2bb1d8c731c50e7cf1485cbe6f0869c81f0b795f1c542bbf2c23ca41c7a94cdd11c3b75d76ee1fe01fbb70ecf81d2e31b9c6ebd34a4195dec5581e6a9caca18e286251517eab9098216f62674c1078e7f4daede63ab19c2c4bed5585dd2f02126238d1550b66f77b33f0af55d7806b06bd82d5db660f8683ab7a987526a7034b5568162f7ee49e57b0cbd44f1aa4530614d09db8dcbdeccbf4ed60c584dc1471823ed26f8c6c9c67f1ab7949f8c1d3aff3c67cd62b0959ddf0f16bcfe66a1c1aa3fa52c0136518d71885a21c3143ab4d6f818c54f9378ddeaee7f9a683df91861f65fd4236ab389c1ec49fa989002f569b0186a20180e35d32321a5691de67f50019fca72f5ee688cf4e4738fa3b2a5ad9a0518fffb6505e9bcdafc0cb0b98eb57e5e6c5ef6652d565fe55f6de138abb805728cba551f779622a2735df34b308bd544a9405962a8b9513d50a2897900ae5284a43182c47207621b66160c667b4f6f0e2531ac39e2ff895ec3409f2cf1ed6e2e5e80e1cb2a8b8924fdc2a48c9c291c5590140f230f920aee7a5a75b7651200621672a1406baf2ad3a78583c5d938a4828372548a6e323b46fbb34142a3651d35cd8717d137044db09a2a18d7182095c7bc283dc3413ff2baf0078f56481775c7928", "68", "6d72601a4f3ab2044904e4230b812d9f1872c1a8d1f1f0663bd9dbb84db776043fda70c373c65822cfd28c0e2bb1d8c731c50e7cf1485cbe6f0869c81f0b795f1c542bbf2c23ca41c7a94cdd11c3b75d76ee1fe01fbb70ecf81d2e31b9c6ebd34a4195dec5581e6a9caca18e286251517eab9098216f62674c1078e7f4daede63ab19c2c4bed5585dd2f02126238d1550b66f77b33f0af55d7806b06bd82d5db660f8683ab7a987526a7034b5568162f7ee49e57b0cbd44f1aa4530614d09db8dcbdeccbf4ed60c584dc1471823ed26f8c6c9c67f1ab7949f8c1d3aff3c67cd62b0959ddf0f16bcfe66a1c1aa3fa52c0136518d71885a21c3143ab4d6f818c54f9378ddeaee7f9a683df91861f65fd4236ab389c1ec49fa989002f569b0186a20180e35d32321a5691de67f50019fca72f5ee688cf4e4738fa3b2a5ad9a0518fffb6505e9bcdafc0cb0b98eb57e5e6c5ef6652d565fe55f6de138abb805728cba551f779622a2735df34b308bd544a9405962a8b9513d50a2897900ae5284a43182c47207621b66160c667b4f6f0e2531ac39e2ff895ec3409f2cf1ed6e2e5e80e1cb2a8b8924fdc2a48c9c291c5590140f230f920aee7a5a75b7651200621672a1406baf2ad3a78583c5d938a4828372548a6e323b46fbb34142a3651d35cd8717d137044db09a2a18d7182095c7bc283dc34", .None}, + {.Shr_Signed, "f1d6ff697aedd19b1b6dc9a67ba8684df7b83b08f1236d536e1edf52864494455c0bd39a0b0e181007963e21a476aef4a4e8de66ffd613a092d3e23fae8204ea038deda96ac73d6a254edc2ca641f58745fe66da303c92b6b2128148186868a0252ae79c1d2d0d4c3a38d59feab2c9434660a65b8426a3480436fefe1b150be50c85c4897298dc1bb185c51ae897834c3d6797ce920faa56615f40354e8561d26a84fe8a9cb3d82aa8a4470a2ff4ef51eef2b480d9092438f63605eee83333f1d66b9aabf753bc301c2e93fffca9da2c6e838844d51b6f96e3e3239d38ab7b01afa03342600984bd9c35c74c09936c74579b20f42e80cef97c0f92d5b5c7c4c28fd64bd0183fe17f8b21ba9757cf5868aaa6aa21bd04d7ae8743a29517353192194d52f7209c2800d309500252d278a08274127c7898ad94fad829f3dfa9b976e71f9ad4910703765084b3c33923ba2cb6005144b6008b6d621a6d79a45cd408a0a0917ac0dcd4d6053199c671b27300fcbae0e47db3ce25a3c96cdc0bf91f146f128cec93c9832314a93ba5fe5d504061b2de6b91b0e9a83a27b037deb779d3037de163d7d6486d070f1b9e025f3521cd5da43e67a134e8e17f40f3f18179a6df7db5955efb544cd51c59826578d25ff9027a05abe33f2cdec4e916d2477b3a3d17ed391c080300513815e98e5569f0e942ed01b3ed11b26b786590fba2837a", "54", "f1d6ff697aedd19b1b6dc9a67ba8684df7b83b08f1236d536e1edf52864494455c0bd39a0b0e181007963e21a476aef4a4e8de66ffd613a092d3e23fae8204ea038deda96ac73d6a254edc2ca641f58745fe66da303c92b6b2128148186868a0252ae79c1d2d0d4c3a38d59feab2c9434660a65b8426a3480436fefe1b150be50c85c4897298dc1bb185c51ae897834c3d6797ce920faa56615f40354e8561d26a84fe8a9cb3d82aa8a4470a2ff4ef51eef2b480d9092438f63605eee83333f1d66b9aabf753bc301c2e93fffca9da2c6e838844d51b6f96e3e3239d38ab7b01afa03342600984bd9c35c74c09936c74579b20f42e80cef97c0f92d5b5c7c4c28fd64bd0183fe17f8b21ba9757cf5868aaa6aa21bd04d7ae8743a29517353192194d52f7209c2800d309500252d278a08274127c7898ad94fad829f3dfa9b976e71f9ad4910703765084b3c33923ba2cb6005144b6008b6d621a6d79a45cd408a0a0917ac0dcd4d6053199c671b27300fcbae0e47db3ce25a3c96cdc0bf91f146f128cec93c9832314a93ba5fe5d504061b2de6b91b0e9a83a27b037deb779d3037de163d7d6486d070f1b9e025f3521cd5da43e67a134e8e17f40f3f18179a6df7db5955efb544cd51c59826578d25ff9027a05abe33f2cdec4e916d2477b3a3d17ed391c080300513815e98e5569f0e942ed01b3e", .None}, + {.Shr_Signed, "-964f09defb70ae4eb10213f7ac5a665d65e3b158737dc842d44d2425f0e5c21f08c53e3f16b8a3fe99757de15b320e76fd7e408418c3d156180f637e704b646f91f83cf866758ad315b612cf201d7109bdefa9a3538bea51a3d679c65b45a01b0ec81c5630322e9958677a430d744e10145882e8e706f6b211f35fad0f56fb03a89223c3d375ade4d105fc15df487bd53a1dcd936b7fbc052bae3f0988fbf60a9c7f26f76f5b523af8f59d6a7bf79661d7ba7a290bcfd2e08de28db5f22fc2adb73119cfdc9e8bb1cb2c0e64bdc29dd3e9a1f94a25d77d4a419203a246c1a53391dc2e1a484f6834796bdf4ec68648b618b110406eeea7a696e900f7b333e47c22dfe0e71cb74d7696b6d9e06e122ea2c7e7a1533421523c4f2d02e25e55168696141c87cbd39e9a1481670f1fed93735a4e6ca8c6e9f3aa80fa87c0be028e11cb76276c456ad8ec1715e8895fba66f563d01df187998c8ac1a448beb4e580c09af8dfc318c715d1532c2c6b36c1d7219d8a077ba77c3f4f8e2b2708cc48de0d4b92ecfca1313bd76a255d4e2bc81b03bad4cf990df687789686c6d9df06ce3303bcbbd21e3f03586d1182ded565e94afd06b1f7597941dd422e651299ec5978986f5899a9c72b98835e4dfeda45dcda68195e00972007d6a2d619d719a3795da935ba5784a3c937e27070268806b600c03fcbbd1fe2a255287738b895726047", "45", "-4b2784ef7db85727588109fbd62d332eb2f1d8ac39bee4216a269212f872e10f84629f1f8b5c51ff4cbabef0ad99073b7ebf20420c61e8ab0c07b1bf3825b237c8fc1e7c333ac5698adb0967900eb884def7d4d1a9c5f528d1eb3ce32da2d00d87640e2b1819174cac33bd2186ba27080a2c417473837b5908f9afd687ab7d81d44911e1e9bad6f26882fe0aefa43dea9d0ee6c9b5bfde0295d71f84c47dfb054e3f937bb7ada91d7c7aceb53dfbcb30ebdd3d1485e7e97046f146daf917e156db988ce7ee4f45d8e59607325ee14ee9f4d0fca512ebbea520c901d12360d299c8ee170d2427b41a3cb5efa76343245b0c588820377753d34b74807bd999f23e116ff0738e5ba6bb4b5b6cf03709175163f3d0a99a10a91e279681712f2a8b434b0a0e43e5e9cf4d0a40b3878ff6c9b9ad2736546374f9d5407d43e05f014708e5bb13b622b56c760b8af444afdd337ab1e80ef8c3ccc64560d2245f5a72c0604d7c6fe18c638ae8a99616359b60eb90cec503bdd3be1fa7c715938466246f06a5c9767e50989debb512aea715e40d81dd6a67cc86fb43bc4b43636cef83671981de5de90f1f81ac3688c16f6ab2f4a57e8358fbacbca0eea11732894cf62cbc4c37ac4cd4e395cc41af26ff6d22ee6d340caf004b9003eb516b0ceb8cd1bcaed49add2bc251e49bf138381344035b00601fe5de8ff1513", .None}, + {.Shr_Signed, "-3e21d054b016a174dc2e4657f154d6849f0713639dcc4e1478722792b420290455a1b6811ff7055dc07d7c5503f9ca201ea1dbb06d43f316f1856081b332a7f61b86757c0a832661c7ffd8ef579b96a7164e56b18226c73fadfc7a697b57c86d2dad0385ee5156f5fd257898f6315d1a711424a29aaa58b0abb66fd145db04ea43512f9c1e8e5bd1c47a604b2e76882bae35784aa09e0a99b66b0a60bdf14336c0e67f5b7fa0abdc6737550e73ea1ac2daa7eea92b4c4be0719d5efc188eb0ca02a25ac5eeb80c23bf84318bf495641c0200583022b752377984b922ce5a9e855415547c4e6b5c1175cbf955d88ddf9a0e244dfc0811ca14eb86d58101cfa815392788329840d4637f1589c056bb02ff39c3c7fa0abf31c8146f14083ed2d777f26b53e3be6bdf84d1e8351e3bd2356ba6f503c1eeec72c0bf17a0b36f25e2f334931df2464abbd26a893324580ac2e02ca81601b32c9b51834a807fa0fc24a5a223eafe37e4d866708424da189f9d3da7ed8a9a0fa80f0929f19fd3c663838e395865543f37a90c0785aa854ce41515f96a7a898aa69d8d8a50495fe196db3836f854bc9412a27871048056c7d5664f866d54c24ee89b9c940ae5c33ddc60e044dfd9e60a83746f47df107e6b67d03d354f1733b87fcedeeb863ce865f497b80cd9f9dfcbb073edfb8c4d8df99006de872d965882af21d988efd466005382fe", "29", "-1f10e82a580b50ba6e17232bf8aa6b424f8389b1cee6270a3c3913c95a1014822ad0db408ffb82aee03ebe2a81fce5100f50edd836a1f98b78c2b040d99953fb0dc33abe05419330e3ffec77abcdcb538b272b58c113639fd6fe3d34bdabe43696d681c2f728ab7afe92bc4c7b18ae8d388a12514d552c5855db37e8a2ed827521a897ce0f472de8e23d3025973b4415d71abc25504f054cdb3585305ef8a19b60733fadbfd055ee339baa8739f50d616d53f75495a625f038ceaf7e0c47586501512d62f75c0611dfc218c5fa4ab20e01002c18115ba91bbcc25c91672d4f42aa0aaa3e2735ae08bae5fcaaec46efcd071226fe0408e50a75c36ac080e7d40a9c93c4194c206a31bf8ac4e02b5d817f9ce1e3fd055f98e40a378a041f696bbbf935a9f1df35efc268f41a8f1de91ab5d37a81e0f77639605f8bd059b792f1799a498ef923255de9354499922c05617016540b00d9964da8c1a5403fd07e1252d111f57f1bf26c333842126d0c4fce9ed3f6c54d07d4078494f8cfe9e331c1c71cac32aa1f9bd48603c2d542a6720a8afcb53d44c5534ec6c52824aff0cb6d9c1b7c2a5e4a09513c3882402b63eab327c336aa6127744dce4a0572e19eee3070226fecf30541ba37a3ef883f35b3e81e9aa78b99dc3fe76f75c31e7432fa4bdc066cfcefe5d839f6fdc626c6fcc8036f4396cb2c415790ecc477eb", .None}, + {.Shr_Signed, "-f9a7e39be55b0dd7bf483e22c3773cf8ff76717c29e6c816e18e3e3b4916338be98cc5ccb3bde6ea2edf304c862e28a5bdff961593d65abfacb531b823141965b94b5cf01c5977b20486b88c3df6dc1954a0d47ba7ab5bcc74dda267fcbb847387eb73dff53c7bd1e513c4fbf7cb363ce1018c0362834d88af55d001d222dbf7f8cd432e693bd12aaa00887b980e9d3050cde340f8860ed4fa080c70838bdbed25943493944c6d9a4af3146246bb89cfa15d81fb0afb21c0fe985bf09f9e86b4228f8554393b5e1fa96f8292e15790014a7b2244d0fca19da07a870c3c930d78b66a395d727925722738b2725dcd8a33f233d5e00ebe947a47ff4bc8ce2f386e3e532c496804d2edbf7592469088c7735d1059b5047659c416eb66295c2bde8da0d49f607b67d0dc78bb3267ef9bba0bcbc2b673823b45fb24de279f055e3f55bf87345a837eabd1be1321bd47ccbd7a2f4897bad175419d570765458fdd4fc117f79bf0f1fadb82f7c78cf55d853cf5b9fb0004cdc1c71c14515aa0fa303a747ed3ce5154a1a366332678c8f68c5cea9118a2296a0b98008fbd4b13ab978f6b29cfa2ab1a59f9acf50ecad1fc55c14abd3508fd615707d42b7d4ee6cd97750e94716389ce0690b9a26879606764b1da0ee37bd2e0980fc7eea546baebaeebb0c507fe4a6d3ca5220468cc47903f7a7c59b8aef37058dc775f71b5b05034e958", "4c", "-f9a7e39be55b0dd7bf483e22c3773cf8ff76717c29e6c816e18e3e3b4916338be98cc5ccb3bde6ea2edf304c862e28a5bdff961593d65abfacb531b823141965b94b5cf01c5977b20486b88c3df6dc1954a0d47ba7ab5bcc74dda267fcbb847387eb73dff53c7bd1e513c4fbf7cb363ce1018c0362834d88af55d001d222dbf7f8cd432e693bd12aaa00887b980e9d3050cde340f8860ed4fa080c70838bdbed25943493944c6d9a4af3146246bb89cfa15d81fb0afb21c0fe985bf09f9e86b4228f8554393b5e1fa96f8292e15790014a7b2244d0fca19da07a870c3c930d78b66a395d727925722738b2725dcd8a33f233d5e00ebe947a47ff4bc8ce2f386e3e532c496804d2edbf7592469088c7735d1059b5047659c416eb66295c2bde8da0d49f607b67d0dc78bb3267ef9bba0bcbc2b673823b45fb24de279f055e3f55bf87345a837eabd1be1321bd47ccbd7a2f4897bad175419d570765458fdd4fc117f79bf0f1fadb82f7c78cf55d853cf5b9fb0004cdc1c71c14515aa0fa303a747ed3ce5154a1a366332678c8f68c5cea9118a2296a0b98008fbd4b13ab978f6b29cfa2ab1a59f9acf50ecad1fc55c14abd3508fd615707d42b7d4ee6cd97750e94716389ce0690b9a26879606764b1da0ee37bd2e0980fc7eea546baebaeebb0c507fe4a6d3ca5220468cc47903f7a7c59b8aef37058e", .None}, + {.Shr_Signed, "-a9496286229b74ce3f8204b996261a9e3a723019f149bd23cd2490384422ee918a0b6a3c5b82d3e0213f3a428d19bdbfe0f4f144b34c9e5ac8d88941a2c3b66e83eed36b325ba827fdf138b494a4f5293e0b321a856b52263a7a4f50b703ff1c6ca937219b221daf640c4d3651c3faa97ff93d2c58aa3c44ee4466117c25d45478becf100fdb87f1ea8ff7aa2c90d871c15c60f9b3c9cdec23ea2eb282fca1b40a29333d00c9289c10715f7140a0ced233b6815ef3ec46e8331e13f81a26003d210e507fbb9d316c1a6e50940b58e50638e733fbf5d19f5a924d012880b086aaec8ed21117881defdd35e15e5035aeee42c341eef131fba0e4e46cff5a15fd56439a31b425ca2d6a0c25606f7b114d7e9f737d768cfe0ca6ff08585ac54f6c4cc0d79a519fcb7bb2ce0418dc75ffb947e591097f817711b1bcdc67eb32501926d699d06ceaa8165bd3f2c4b9b782a1dba0684f27c7d9f3dee430455c465be82db37c5c73ce839b473f1fd52e6f494c4027f3155d42527e7e2f176b33bc273a7dbbe23714a180b4903c2e7df9aad787ea5a2c52b54b52019e439676ea702d870f5fe1f1d84c38d795a24b86729f7bf544d3c05ee047979724e6c4d763ebb8f0a0bd808463fa3482933c8780d8af0f94d7d928862512a71ed104782bc2b45fc79084c48d6b67688bcdcef9a038dcf9f3fca7b57cbca004322de63627812a675e09", "18", "-a9496286229b74ce3f8204b996261a9e3a723019f149bd23cd2490384422ee918a0b6a3c5b82d3e0213f3a428d19bdbfe0f4f144b34c9e5ac8d88941a2c3b66e83eed36b325ba827fdf138b494a4f5293e0b321a856b52263a7a4f50b703ff1c6ca937219b221daf640c4d3651c3faa97ff93d2c58aa3c44ee4466117c25d45478becf100fdb87f1ea8ff7aa2c90d871c15c60f9b3c9cdec23ea2eb282fca1b40a29333d00c9289c10715f7140a0ced233b6815ef3ec46e8331e13f81a26003d210e507fbb9d316c1a6e50940b58e50638e733fbf5d19f5a924d012880b086aaec8ed21117881defdd35e15e5035aeee42c341eef131fba0e4e46cff5a15fd56439a31b425ca2d6a0c25606f7b114d7e9f737d768cfe0ca6ff08585ac54f6c4cc0d79a519fcb7bb2ce0418dc75ffb947e591097f817711b1bcdc67eb32501926d699d06ceaa8165bd3f2c4b9b782a1dba0684f27c7d9f3dee430455c465be82db37c5c73ce839b473f1fd52e6f494c4027f3155d42527e7e2f176b33bc273a7dbbe23714a180b4903c2e7df9aad787ea5a2c52b54b52019e439676ea702d870f5fe1f1d84c38d795a24b86729f7bf544d3c05ee047979724e6c4d763ebb8f0a0bd808463fa3482933c8780d8af0f94d7d928862512a71ed104782bc2b45fc79084c48d6b67688bcdcef9a038dcf9f3fca7b57cbca004322de63627812b", .None}, + {.Shr_Signed, "19ae50f43e84cc2a273064a93115b80c78ceb40f2f3f9221094f7ecbf463fd55798544e3e82441508a52e25a36aed338322a6201cfb5ef2a5c83c48f36c137e11aac07ec701dc032e11afbd1a91908b1d55690c939ddc95426ad376f1157b4a4a8d658e5f6768a880a420f109e2a4a6f834079f388f7a83b47d86bd5a10179e6f3947c43e21dab61be2288ee9ca6076aa0eefde0937a93ebd8cf6ff1d42a11d22b9794671ba1b9e30bb1add3e6897d9bcbff833a4023b9d1d14af12b38699de8315507b3e97fcded57a8795c63a558f8a53603d30682c7921130d9392b176c330f6be95acca434f8d4841f07607edefe592baa17b74432e047579bd16fe0c1ac718f1a3b6ad042a061aa06b9849c90c4b34bfd424bd1fa74aa232f174ae2719637bd97cf7aa76e32358a57093d195ab6efd626ee79e338d39e8a5ca3b0c9756a69c072710869e83be70176e26ec0f03d41d51553dd76aeb140309fb5e9c8df51a8df9f52c1611d0fe4f9dff2cad1641fab967de0b7a47a29641b763d67bab0c05658a7b1a79a0200c22dde3d9b1fba797508e1c7be9665735ba8dd403f1a207ae12d9ec26ac4a51ff49c507050564dec6b6e5e39f15a1ebe0ee933933f25a03c743a8231103dec490f826d559fe6df2ecec265c39d0ece3eb8feaad7c7995195317a2260e3a5f3c89a6077a18abddfe1637072441d5a4f720ee956323f2141ea", "3d", "cd7287a1f42661513983254988adc063c675a07979fc91084a7bf65fa31feaabcc2a271f41220a84529712d1b57699c19153100e7daf7952e41e2479b609bf08d5603f6380ee019708d7de8d48c8458eaab48649ceee4aa13569bb788abda52546b2c72fb3b4544052107884f152537c1a03cf9c47bd41da3ec35ead080bcf379ca3e21f10ed5b0df1144774e5303b550777ef049bd49f5ec67b7f8ea1508e915cbca338dd0dcf185d8d6e9f344becde5ffc19d2011dce8e8a578959c34cef418aa83d9f4bfe6f6abd43cae31d2ac7c529b01e9834163c908986c9c958bb61987b5f4ad66521a7c6a420f83b03f6f7f2c95d50bdba2197023abcde8b7f060d638c78d1db568215030d5035cc24e486259a5fea125e8fd3a5511978ba57138cb1bdecbe7bd53b7191ac52b849e8cad5b77eb13773cf19c69cf452e51d864bab534e039388434f41df380bb713760781ea0ea8aa9eebb5758a0184fdaf4e46fa8d46fcfa960b08e87f27ceff96568b20fd5cb3ef05bd23d14b20dbb1eb3dd58602b2c53d8d3cd01006116ef1ecd8fdd3cba8470e3df4b32b9add46ea01f8d103d7096cf613562528ffa4e2838282b26f635b72f1cf8ad0f5f077499c99f92d01e3a1d4118881ef62487c136aacff36f97676132e1ce87671f5c7f556be3cca8ca98bd113071d2f9e44d303bd0c55eeff0b1b839220ead27b90", .None}, + {.Shr_Signed, "-28aa48be4e3526c0f637ac4a595c1f58ff6d837e86083e17c128d9cd08f8825bd706c52e8e03760b9877418ba77182cda60cdb0366ae74e23b34164316a4d30c769a1eef7a51940aafec3b8e424ffc27db495ed66c699fe28e5d06b7277cb8e9cf018ad25beba11c3410d32c0f89fe1b47371b8a7c46e38258b8167b867a4d8f81f38ddc17760954c50b909610c4cf43107aab7ac38d893e949d6ccf2689eba2c081c48b5b00d8e3caff14b486978887363eedb8f7f22a8fbd06472f0425ee63c5bb181259a3e53581d993c169d5370f874818115b07ba0a4d88bc055a9ae314ee1f11e8b2cc9f2003358f81c04d99cf595c29190ed78e76bb4fb73ab3929009b30d15186c7c283b59d4e08a306a6cdb8cef0b5d9c2e8778bca821a21e4e83896f513f65869076d39a171af9e0dae14b3159c06cdec9155971e5abe3dbe7ffe64ffe410dfbabcd75ec0e4835659237bb28ea62bd9afb4a6edb8c50d0e3c4fa890af488298c693493ccf72a3a791456ac623c7b2430ddeccde41d7440cf52f8a6c112e586849859be1b3a1fde6381a2229aa7f9ac0f7486e426b0ecd8eb7cef3514ebada38cc860dfebaff8ab4496c9238a3316297204a18f52e5c86e0200c975c1f711d67f7c901247865f00d93c59d68e55ff380d906ade83368548b17af48f2a44498ea94fc726a8b0552999e305da8119d5c61b7c42ea9708ecc0ca4fc348", "42", "-a2a922f938d49b03d8deb12965707d63fdb60dfa1820f85f04a3673423e2096f5c1b14ba380dd82e61dd062e9dc60b3698336c0d9ab9d388ecd0590c5a934c31da687bbde946502abfb0ee39093ff09f6d257b59b1a67f8a39741adc9df2e3a73c062b496fae8470d0434cb03e27f86d1cdc6e29f11b8e0962e059ee19e9363e07ce37705dd82553142e425843133d0c41eaadeb0e3624fa5275b33c9a27ae8b0207122d6c03638f2bfc52d21a5e221cd8fbb6e3dfc8aa3ef4191cbc1097b98f16ec6049668f94d607664f05a754dc3e1d2060456c1ee8293622f0156a6b8c53b87c47a2cb327c800cd63e070136673d6570a4643b5e39daed3edceace4a4026cc345461b1f0a0ed67538228c1a9b36e33bc2d7670ba1de2f2a08688793a0e25bd44fd961a41db4e685c6be7836b852cc56701b37b245565c796af8f6f9fff993ff90437eeaf35d7b03920d59648deeca3a98af66bed29bb6e3143438f13ea242bd220a631a4d24f33dca8e9e4515ab188f1ec90c377b3379075d1033d4be29b044b961a126166f86ce87f798e06888a6a9fe6b03dd21b909ac3b363adf3bcd453aeb68e3321837faebfe2ad125b248e28cc58a5c812863d4b9721b8080325d707dc4759fdf240491e197c0364f1675a3957fce03641ab7a0cda1522c5ebd23ca911263aa53f1c9aa2c154a6678c176a046757186df10bb", .None}, + {.Shr_Signed, "-6e4ee66a3e2f18faa0bdfe2f43f6d78e0014cc6a48330e1b313b1f229ac9f238c0304b593d497ec7a7c75160f5c050c27a6afc05a47cc8d6aff616ca6a75c452ae7c506d14801a169f61c8488467063d3e81ec6d3e723b34d9df8370181400c94d18a0e6dfadbb1956e8a5f8c8dfd18ab4902b7618cf512cc198b94411518df38e6541bbeff7b94bb31b71c020c5eab396889934ee49ee984e9f278dff9674562681a7081b2c66ec7d13951857732e899abf7a7758e8ed775ee005cbeedd8bc833d6d550378e303acacbeb9c949bb4b6e19542517b3b6fe72a835c4a8414fdb259d5d84d2000a8f55dcc02294c911763a66343967c9b6b00de5e8c218feae3efab34ac677b71ae2264fb0b3395f73400bcea698239cfb31c6ff079dffa90ffdbc1d9fbd5cc280805c422215076c382718d400daeae876e20029bcc4edc57ce50092b3bc860e0007bd68eaddb3929d839616e2c576945213c6708284a68e796b5f3e0126b341d7fefbfb06a87aab7c6d727212818fcf014e4d891ebbc912fc7f8f787b776bd4830b2457d65178b5ff3ea573cdad60de0ac509aae903d58283fe3e107d9779538af4b74de67f542b67da4ec046fe2467432b4732b229e8d7e54f2ae12243e1d6dda1303c2e741dc7d81e50db7adcc6f8f835f5fc534b8f8f4681df68e4013a5b47163e96984144e221000f9dfc348606e280fbbe815af445b8d8e", "23", "-dc9dccd47c5e31f5417bfc5e87edaf1c002998d490661c3662763e453593e471806096b27a92fd8f4f8ea2c1eb80a184f4d5f80b48f991ad5fec2d94d4eb88a55cf8a0da2900342d3ec3909108ce0c7a7d03d8da7ce47669b3bf06e0302801929a3141cdbf5b7632add14bf191bfa315692056ec319ea2598331728822a31be71cca8377dfef72976636e380418bd5672d113269dc93dd309d3e4f1bff2ce8ac4d034e103658cdd8fa272a30aee65d13357ef4eeb1d1daeebdc00b97ddbb179067adaaa06f1c60759597d7392937696dc32a84a2f676dfce5506b8950829fb64b3abb09a400151eabb98045299222ec74cc6872cf936d601bcbd18431fd5c7df566958cef6e35c44c9f616672bee680179d4d304739f6638dfe0f3bff521ffb783b3f7ab9850100b884442a0ed8704e31a801b5d5d0edc400537989db8af9ca012567790c1c000f7ad1d5bb67253b072c2dc58aed28a4278ce105094d1cf2d6be7c024d6683affdf7f60d50f556f8dae4e425031f9e029c9b123d779225f8ff1ef0f6eed7a9061648afaca2f16bfe7d4ae79b5ac1bc158a1355d207ab0507fc7c20fb2ef2a715e96e9bccfea856cfb49d808dfc48ce86568e656453d1afca9e55c24487c3adbb4260785ce83b8fb03ca1b6f5b98df1f06bebf8a6971f1e8d03bed1c80274b68e2c7d2d308289c442001f3bf8690c0dc501f77d02b6", .None}, + {.Shr_Signed, "6b55008bd338ea372bfa2f58a8e2a9632c6e6938ed5c915097fa65095f5363c7ccff03ceac079aad6228c92dc72434bcdd06e7280e405a0c5f4230bf7905064a16ab00f09dd86d30b649608b279cde56204f452db9e8ca0ed0842c298fa62379a23e91786e6a614c07618e0f9461fc7572eaba479510bd77a09f4e471c091e09980125c17672ac47e96a006b4257ef6f712518c48fbd082148bc687ab49429e1a155d13f9b9dc38fcc28feb062f3e9f459ac2c3ea76b8d52add3345e0b91d7bfa8e3abd29744b3a772a3d182802cf23072400706e7a386d36522de961d25ba7f2421b361e36eac52b491490d951e6ac3809288b8bb5545cdc2fc99bbdf118b4d9061fe08c2d65ba9965214600225f5416974920fbe5e48ae2dafc3e86e8b13507070149e10a67c1daa50c8dd71cdbfa190a661ee7d6f1c5a1f3a5828cc0c76fc2e65e65cf515eca86a5f60ce90d937dc53a41128e22311f60132b7c3a07d8196ab6e320446dc9ec79ef50ed14700ec013245423187f55548cbc3a512560c8d58bb62a846c989cbe19dfdb08aa9787976aff48260effe4d5d5a281202c8084486204dd2b0ec3836b8397f7008d889f10ee765b23d3aad3b9d958d13e69c5e780f8a50031d72bcfde3352c6d979253893dc8d34908ae547ef732bd334c20356da9dcdfc9944c26ceb42c8d6e70bafae2496af1d82ef4343fc916593561a383e364", "35", "35aa8045e99c751b95fd17ac547154b19637349c76ae48a84bfd3284afa9b1e3e67f81e75603cd56b1146496e3921a5e6e83739407202d062fa1185fbc8283250b5580784eec36985b24b04593ce6f2b1027a296dcf4650768421614c7d311bcd11f48bc373530a603b0c707ca30fe3ab9755d23ca885ebbd04fa7238e048f04cc0092e0bb395623f4b50035a12bf7b7b8928c6247de8410a45e343d5a4a14f0d0aae89fcdcee1c7e6147f583179f4fa2cd6161f53b5c6a956e99a2f05c8ebdfd471d5e94ba259d3b951e8c1401679183920038373d1c369b2916f4b0e92dd3f9210d9b0f1b756295a48a486ca8f3561c049445c5daaa2e6e17e4cddef88c5a6c830ff04616b2dd4cb290a300112faa0b4ba4907df2f245716d7e1f4374589a838380a4f08533e0ed528646eb8e6dfd0c85330f73eb78e2d0f9d2c1466063b7e1732f32e7a8af654352fb067486c9bee29d20894711188fb00995be1d03ec0cb55b71902236e4f63cf7a8768a38076009922a118c3faaaa465e1d2892b0646ac5db1542364c4e5f0cefed84554bc3cbb57fa413077ff26aead140901640422431026e958761c1b5c1cbfb8046c44f88773b2d91e9d569dcecac689f34e2f3c07c528018eb95e7ef19a9636cbc929c49ee469a484572a3f7b995e99a6101ab6d4ee6fe4ca2613675a1646b7385d7d7124b578ec177a1a1fe48b2", .None}, + {.Shr_Signed, "-e87fbd297f89143512dfc1cda8640aaf48bbfeaee5da926432a86d0547ed78b50d4a15256be1c9aa5e893980af5cfe629b4afee8594d2bce9c25e8232e3c59846c105f6a225b76fde45d78c87fff12268f170dc55f364f3c03f1063828f50ed947bc3dd5444e7ac9ffef4a8cda6761186637c490045b32183760c1fa1b528dbfc44d04d636184cd1b64348c7348cc0307f15c200e75a75ae7b1de53f07c46d15328b183e8ff35e3cce0b57ebe99ffddb91952ee2c84d37ca14383f42d6256b674df3e52a34c87dbb3c8648e0f2c7411c54dd7fb7ac4545c655fd131e40606e70c4d96b787c4388c2e52d80b06b9f178961c5cd4569bab7ed5464e2e5c09cd617d6001103edcd3d123950f2ec8406e7899df46112a92996ea6d616f5db5ec1f3a82d8883059e573853f1184be2dfc6e8c917d338d517e9e8e2da6441da68b781da74afbcfeaa2d0c3a30d61757b5805f1943cee76f6783ad948a51629dfa039dba53ba144b3e3259873dd9fe6fdc471cce3bd6bf34111d92401e770a7502b74fccab62c480e47756b265d5b082ad4e9808eff676fd8acb4629ee52fdc23fc5cb28874a3c7bc0d349382f8ada344a72a43ad1e523fe45dc3563b7c9545fb7d287dc19511bb74c4166388ab0e97e0a546a228a9079ef8ecc63991552d38533252a93eb76ff23e58e8e50db715b9553d7f1528c17e277c7b7a613172acc97b7979a1", "2c", "-e87fbd297f89143512dfc1cda8640aaf48bbfeaee5da926432a86d0547ed78b50d4a15256be1c9aa5e893980af5cfe629b4afee8594d2bce9c25e8232e3c59846c105f6a225b76fde45d78c87fff12268f170dc55f364f3c03f1063828f50ed947bc3dd5444e7ac9ffef4a8cda6761186637c490045b32183760c1fa1b528dbfc44d04d636184cd1b64348c7348cc0307f15c200e75a75ae7b1de53f07c46d15328b183e8ff35e3cce0b57ebe99ffddb91952ee2c84d37ca14383f42d6256b674df3e52a34c87dbb3c8648e0f2c7411c54dd7fb7ac4545c655fd131e40606e70c4d96b787c4388c2e52d80b06b9f178961c5cd4569bab7ed5464e2e5c09cd617d6001103edcd3d123950f2ec8406e7899df46112a92996ea6d616f5db5ec1f3a82d8883059e573853f1184be2dfc6e8c917d338d517e9e8e2da6441da68b781da74afbcfeaa2d0c3a30d61757b5805f1943cee76f6783ad948a51629dfa039dba53ba144b3e3259873dd9fe6fdc471cce3bd6bf34111d92401e770a7502b74fccab62c480e47756b265d5b082ad4e9808eff676fd8acb4629ee52fdc23fc5cb28874a3c7bc0d349382f8ada344a72a43ad1e523fe45dc3563b7c9545fb7d287dc19511bb74c4166388ab0e97e0a546a228a9079ef8ecc63991552d38533252a93eb76ff23e58e8e50db715b9553d7f1528c17e277c7b7a613172b", .None}, + {.Shr_Signed, "-b3bf3fa33fd76f090155355c02c6cf990b25af6fb0c15bec929c8e79034324bba2655b92936a300d4ee2c3de67243714c7ac42ac27a040192aed053cd746801f890098c9e76de50d89ca24c1aa47e6d61a754b8f2c35ccd6de520a656066bdb43874b0000add331a08e0664035671e8a38961112dcee9b90f9a6ca7dfe6dc985a4d63de094a1723b00031345229e532123b0325f4d8e6173e3eca3df6f4831501c6b454a5c13f501a029d7fd9ba7919fc3f94051ca4b0c626ba393c04e38b2c7f16abd3adc2f581344907d5a5b764b500c72afe31e84d43651a644ed4d2a3198b58bf59dc5fbcb1b8c4ed1a2e98642cb435b17ce34e99e48ffd2e63d562c4959e2dee6a2238834b38991359e40524085c718172be5f94d7e242f8bd25368d1c808b73df1beaebea35b264653a209935cb0552bde9f6088f8faa634e004552171a0e05d4671c2a521c04e0d93f17f039e1121a7bf92a5dbd1c22b61ef4d5d617155c5e6aa55fb77401fec20b73c4de9f863b8501416b268c8e7e3b87925fc42464e32a39b91dedea802c315b6c86dc33c756d1110f2b5a187e9ac78397dcf5f964576c82d0605f57010606fd28ff0e2bcd5a3cbf4d6d2ddc0e4285705b3b7c570020f8342f4454a94b1287d60994340d8f636783672893f81c46cf15687f6939edc79349d5b2971dad7acf1d96d5829a1a4dab1061cc479d39adc5ab533e35b", "5", "-59df9fd19febb78480aa9aae016367cc8592d7b7d860adf6494e473c81a1925dd132adc949b51806a77161ef33921b8a63d6215613d0200c9576829e6ba3400fc4804c64f3b6f286c4e51260d523f36b0d3aa5c7961ae66b6f290532b0335eda1c3a5800056e998d047033201ab38f451c4b08896e774dc87cd3653eff36e4c2d26b1ef04a50b91d800189a2914f299091d8192fa6c730b9f1f651efb7a418a80e35a2a52e09fa80d014ebfecdd3c8cfe1fca028e525863135d1c9e0271c5963f8b55e9d6e17ac09a2483ead2dbb25a8063957f18f426a1b28d32276a69518cc5ac5facee2fde58dc62768d174c32165a1ad8be71a74cf247fe9731eab1624acf16f735111c41a59c4c89acf20292042e38c0b95f2fca6bf1217c5e929b468e4045b9ef8df575f51ad932329d104c9ae582a95ef4fb0447c7d531a70022a90b8d0702ea338e15290e02706c9f8bf81cf0890d3dfc952ede8e115b0f7a6aeb0b8aae2f3552afdbba00ff6105b9e26f4fc31dc280a0b59346473f1dc3c92fe2123271951cdc8ef6f5401618adb6436e19e3ab68888795ad0c3f4d63c1cbee7afcb22bb64168302fab8083037e947f8715e6ad1e5fa6b696ee072142b82d9dbe2b80107c1a17a22a54a58943eb04ca1a06c7b1b3c1b39449fc0e23678ab43fb49cf6e3c9a4ead94b8ed6bd678ecb6ac14d0d26d58830e623ce9cd6e2d5a99f1b", .None}, + {.Shr_Signed, "-232c0b635683a9e118df5e0d5125f04753bc44d8b21b0075a9bb6d58e844d1942e3c316513b84752d30c541a83c6e80c644c62827d2d22711969a46b71f55e5bf831992d07d1e6183ba5603d497fe5d71132bd641562c478534cf60f445aa6534f9ba276c9b83457c6f1070d96ab344a4064983ebfea59a6de10571a2034a52eed52de4386e403c8f7c7d2ec0a5b29afc55fbd73484d6eafcebbf2abfd8d57ff0abae1e17c084ee186e6452f2806d6950cc91147751683ba34d9fb57d581791d8511a92fd260f417a8415da08e3c13a80bc8a0ac8b6330ead756721f2034309722553b060e07128f9b40a171d20096ee6e8668bdfb7a92f68a9718ff71bcdf0130f14611c4bb993b1759be2f4411964b9038ffdcc7174f7ef6d640d00db503b7d48286bbca53fd1686e1482ceff8b36f5b996ef84d6dd071636c4dd6cbe99e0707394ba42d5f739450e1fee1bc916337ea71172e211d7bbb11f5d97f11fef9d23089215857c5a5a026c09941f7449cffd169c186ddb55223b92e8a713218060fe44567bdaf1f14a048dc172138872b97a51126bf37f8371629a247ab7499d1798a95a710c6050c805b9752930700eea7838dabcf65ce921c4ac6a964cb2b7c697972d04aafdbf5e6df503e0c1c96f491f607a28d77927e06327e625f3652d6c7e805a79361c7299b148a09ea2ae1a76862095cb934a8551abc110bb0160e89be", "4f", "-465816c6ad0753c231bebc1aa24be08ea77889b1643600eb5376dab1d089a3285c7862ca27708ea5a618a835078dd018c898c504fa5a44e232d348d6e3eabcb7f063325a0fa3cc30774ac07a92ffcbae22657ac82ac588f0a699ec1e88b54ca69f3744ed937068af8de20e1b2d56689480c9307d7fd4b34dbc20ae3440694a5ddaa5bc870dc80791ef8fa5d814b6535f8abf7ae6909add5f9d77e557fb1aaffe1575c3c2f8109dc30dcc8a5e500dad2a1992228eea2d077469b3f6afab02f23b0a23525fa4c1e82f5082bb411c7827501791415916c661d5aeace43e4068612e44aa760c1c0e251f368142e3a4012ddcdd0cd17bf6f525ed152e31fee379be0261e28c23897732762eb37c5e88232c972071ffb98e2e9efdedac81a01b6a076fa9050d7794a7fa2d0dc29059dff166deb732ddf09adba0e2c6d89bad97d33c0e0e7297485abee728a1c3fdc37922c66fd4e22e5c423af77623ebb2fe23fdf3a4611242b0af8b4b404d813283ee8939ffa2d3830dbb6aa447725d14e264300c1fc88acf7b5e3e294091b82e42710e572f4a224d7e6ff06e2c53448f56e933a2f3152b4e218c0a1900b72ea5260e01dd4f071b579ecb9d2438958d52c99656f8d2f2e5a0955fb7ebcdbea07c18392de923ec0f451aef24fc0c64fcc4be6ca5ad8fd00b4f26c38e5336291413d455c34ed0c412b9726951", .None}, + {.Shr_Signed, "-1a98d72d2eb3a802d6b7707d8b9169bb98412a3dc2832ed22c73a61b629657a3d914ed3c020d0dc90da2a78dfa99f9cc9c1bbba98c16607dc97f2072ac9b942dd02ba60b5665a5400c63b1ede56dd9c7a439744c7d9e9fd83c3e9c7527ae182d879cb0266e1aea970b3dfde9c53cf9fe7850a9093c857ec5a61d50761d4813a523282b057e51c5bef1d7b7cf360bd44a9933bba78bd6068748e0f16d8ae313ccd495022b89f497e5d86cbf48eac4a2152132321ce09d6c13c5c913ecbcd8f49c053c5f88e6c794c2d6810d42db14fa1990c40bbc190cada895ebfed0117205486ad11d14acae0c992cad8eb8043c48fa9251ccfd898cfb2a19a45d83e4b33ad9e591c2264b704716b3a11db835ae989b172f4fbe4cceb7c9063aa8d97b12b7605fa894977e4691632b34d2b88b8d976432f841e1f96e10b951dd765c5b5f7a101a3e8b840baa7b11321b0e24b60d917f857b4d48233d5c012607c59ba97a7ed397c15e1f570da368383bf26c08090bc6f44732ea9f238d3b129eb8036591e50b81bfb3705fe57527b062c986add5c33d74887508ff24b782a8bb60e00c10eb34ed73d0ba1c955fb35837e289174ad7136abc90e286393817ed3ec1cae766324b06258687dac1855d71595766cbef63828f5592e588778b4f53e2d4d91b02e1814031dcb2be43509d3c6a1ef28dfe93e1126b7eebc67d30cf63bdaf87a3cbcae3", "4", "-1a98d72d2eb3a802d6b7707d8b9169bb98412a3dc2832ed22c73a61b629657a3d914ed3c020d0dc90da2a78dfa99f9cc9c1bbba98c16607dc97f2072ac9b942dd02ba60b5665a5400c63b1ede56dd9c7a439744c7d9e9fd83c3e9c7527ae182d879cb0266e1aea970b3dfde9c53cf9fe7850a9093c857ec5a61d50761d4813a523282b057e51c5bef1d7b7cf360bd44a9933bba78bd6068748e0f16d8ae313ccd495022b89f497e5d86cbf48eac4a2152132321ce09d6c13c5c913ecbcd8f49c053c5f88e6c794c2d6810d42db14fa1990c40bbc190cada895ebfed0117205486ad11d14acae0c992cad8eb8043c48fa9251ccfd898cfb2a19a45d83e4b33ad9e591c2264b704716b3a11db835ae989b172f4fbe4cceb7c9063aa8d97b12b7605fa894977e4691632b34d2b88b8d976432f841e1f96e10b951dd765c5b5f7a101a3e8b840baa7b11321b0e24b60d917f857b4d48233d5c012607c59ba97a7ed397c15e1f570da368383bf26c08090bc6f44732ea9f238d3b129eb8036591e50b81bfb3705fe57527b062c986add5c33d74887508ff24b782a8bb60e00c10eb34ed73d0ba1c955fb35837e289174ad7136abc90e286393817ed3ec1cae766324b06258687dac1855d71595766cbef63828f5592e588778b4f53e2d4d91b02e1814031dcb2be43509d3c6a1ef28dfe93e1126b7eebc67d30cf63bdaf87a3cbcaf", .None}, + {.Shr_Signed, "-971c9a4471cc4f38c957c9c348fc6cbc4792b7f1098c28337e2fb94e1bf6fed5e9f4960ea011067ef88f16d40dd8a8a53709e276e3b730b3653ab4ac337a4286eea87bd037e657917228df878698a4c776420d5ec7fc3db27ccfe24fd32ff3c8e88d0990d8662e8990cb845431c332d0df9ff6e6ad6dbd35cb5c8cee7124cb97f49f0f9ccfc609511b84b7e9d1b3d555ee998a0d091f2d3e2bf49282eca27b46e5bd52a69894cf335cd1ac13b8ab3842d9c1c8efd5a5667575c11b5a126d57e17b2c106ebab1852c13a1af1ffda858d6d3d90d01667d1dd210108cbf6984dc8f3f18ca3011b517e86f93091d6c6cafbc99de027ae34bf6aad9d42599f146d0fd788debfe5d0f73b2bd61461053add793575e68c42283a2ecc61d75235fb4115339d5c76e2475d31c76b117958a6e7c5581c354b4168785ebd80611c8c7a7c6620b7effd7796de78f2f1b20a9e7063d4e1d8835406a1ff08a9545cb5485ebde02ba49f60f71b280d1a60c20f17ca3a4d6cbfb1968a5dcf7ed23b470566a695217be92f2720053f7d3da8b9b3003ea6365aae2290cec1badf38ecc51d7461e55ccb24267e9d71c5bca810c6d9c367248493a5b42f7468d5ebc87b9fc33f29fb1f2067f21734a563648cd1effa0da4abebca72751b489a1001e39e042f4cb525b07402f73a753c18dc94f1817559691825bf4d9ca353b3ee1f0eedd78ffbc38034", "6c", "-971c9a4471cc4f38c957c9c348fc6cbc4792b7f1098c28337e2fb94e1bf6fed5e9f4960ea011067ef88f16d40dd8a8a53709e276e3b730b3653ab4ac337a4286eea87bd037e657917228df878698a4c776420d5ec7fc3db27ccfe24fd32ff3c8e88d0990d8662e8990cb845431c332d0df9ff6e6ad6dbd35cb5c8cee7124cb97f49f0f9ccfc609511b84b7e9d1b3d555ee998a0d091f2d3e2bf49282eca27b46e5bd52a69894cf335cd1ac13b8ab3842d9c1c8efd5a5667575c11b5a126d57e17b2c106ebab1852c13a1af1ffda858d6d3d90d01667d1dd210108cbf6984dc8f3f18ca3011b517e86f93091d6c6cafbc99de027ae34bf6aad9d42599f146d0fd788debfe5d0f73b2bd61461053add793575e68c42283a2ecc61d75235fb4115339d5c76e2475d31c76b117958a6e7c5581c354b4168785ebd80611c8c7a7c6620b7effd7796de78f2f1b20a9e7063d4e1d8835406a1ff08a9545cb5485ebde02ba49f60f71b280d1a60c20f17ca3a4d6cbfb1968a5dcf7ed23b470566a695217be92f2720053f7d3da8b9b3003ea6365aae2290cec1badf38ecc51d7461e55ccb24267e9d71c5bca810c6d9c367248493a5b42f7468d5ebc87b9fc33f29fb1f2067f21734a563648cd1effa0da4abebca72751b489a1001e39e042f4cb525b07402f73a753c18dc94f1817559691825bf4da", .None}, + {.Shr_Signed, "ba43bbf80256663a0e8df4f1e5548e87e62e66ed0862689023dfed10af24ff1d8928ac1b413b1fe6e90fdd6de64a0fbad64896c59233722338571708486c46cfd84f913a4500aaf3ba4c6d1f3648fc53a331991e647942ddfc91d46d94075564657637bc18533e8eaba4f718ddec9a4fb8cbd4c16250f41d05192babefccb5a3f34be67f1550370f9576afe8f7130e20bbc55c350b8565635127799b3e1297c99e2ae6539fcd9725d0872bac7fa427bcfcd03e5ad98365a7716d32208ba0b05ed39fe5f3d1269bdf29932c6fa316eb9436092f39264220f05d88c9365b750770718942e5a3bf3045aa0c7e762b2630f7adbe3b6260ba5b55915d3ce06b0be9e7bbafd4f6e1cfc3ba91d3ecb344d1f6efa63f929baf9217a35ee256a1a47ad3090a34652a337075ff5075ac9b1700e10f6c01fbc66397d05fc4dfef71906e2795d368ddcfd447f163b80e1538ae60e712af8fed586299a6c2ddd931cacb650eee7741ada7882840fce13560ee124363c5d9422304168272ed27b960a19f31bfe7ae3616595423e2f22ef6f3d3ca8bf010b63c9130b45e7575f656deb73dd91e651597eb63ff517312db7b42cb99da23bfcf839f4d9fa8af130060c486255adacc6649d2c8f28ed813290842b465c1ea5de5913231b197b182910991454b95322a7f878d895d7dd77ae3178dc71972be498ec667f2f6cbba7374bb074dca7315b0", "2c", "ba43bbf80256663a0e8df4f1e5548e87e62e66ed0862689023dfed10af24ff1d8928ac1b413b1fe6e90fdd6de64a0fbad64896c59233722338571708486c46cfd84f913a4500aaf3ba4c6d1f3648fc53a331991e647942ddfc91d46d94075564657637bc18533e8eaba4f718ddec9a4fb8cbd4c16250f41d05192babefccb5a3f34be67f1550370f9576afe8f7130e20bbc55c350b8565635127799b3e1297c99e2ae6539fcd9725d0872bac7fa427bcfcd03e5ad98365a7716d32208ba0b05ed39fe5f3d1269bdf29932c6fa316eb9436092f39264220f05d88c9365b750770718942e5a3bf3045aa0c7e762b2630f7adbe3b6260ba5b55915d3ce06b0be9e7bbafd4f6e1cfc3ba91d3ecb344d1f6efa63f929baf9217a35ee256a1a47ad3090a34652a337075ff5075ac9b1700e10f6c01fbc66397d05fc4dfef71906e2795d368ddcfd447f163b80e1538ae60e712af8fed586299a6c2ddd931cacb650eee7741ada7882840fce13560ee124363c5d9422304168272ed27b960a19f31bfe7ae3616595423e2f22ef6f3d3ca8bf010b63c9130b45e7575f656deb73dd91e651597eb63ff517312db7b42cb99da23bfcf839f4d9fa8af130060c486255adacc6649d2c8f28ed813290842b465c1ea5de5913231b197b182910991454b95322a7f878d895d7dd77ae3178dc71972be498ec667f2f6cbba7374bb0", .None}, + {.Shr_Signed, "-9f69d2bad3ac385f08fc4c6193292a5da01e03edfe9230a47ffe6e6178e29243403a8d0287595f5225fd05fa0cd03aa522490ba1fb6acc738db8478888dfbad0709efcd4cb0d760d56a6fdfd4f312881ff723b654156fe5d68ba8526dd9a8f2be6e9781b1e6626d73141a57be713168704c96f26445c5cc8e7ca179e823cef40018c855507fa6daeab80fed6a54250ee2a8672669918ca24450b29f12fec1ef9ee4bcec14830e981d092596c638846418b5447ac968f93c93bef5e095708bf95af11ce036d67e7c1d6eed56e6780053bc533744e5ac93cdea75e066d4e1d753dca900e49f9d1bd8d61b8b9f2742c9e34e3b6410590ff7c1d45aaa19091e2d241faa78eddf572ee939f8e2b60afed896ce38707539ad314cd36eb13b69cbfb70e4cb7875a3e5e621ab6546d7ff864fb6fbafb2b701bf7ea2c18480152bf597dc1f82abaad23a40dad9d902381bea4c3a9eecb0be6f490d3b92a5470d9b21b04bfbf2dd2fdd595b37b3235e0f065c7e5dfa028a1552be509b3e06b7c456fbd44114000aa51e426d8649ddc82e1d427bc66b9ce7bdd326b7828c42eb726bc0d39921361f54045829771d23dbfe4d7a40e1936da9d7cd945aaadb8c1ccc797f27abce82b9febd5fb1d563d49ba60df7446f2a423630c486fc27d74067ba6ffd7e04cb65586965e9153e54a09b3785cf60ea50137459c777284bf56973d56874ed1ac", "25", "-4fb4e95d69d61c2f847e2630c994952ed00f01f6ff4918523fff3730bc714921a01d468143acafa912fe82fd06681d52912485d0fdb56639c6dc23c4446fdd68384f7e6a6586bb06ab537efea7989440ffb91db2a0ab7f2eb45d42936ecd4795f374bc0d8f33136b98a0d2bdf3898b438264b793222e2e6473e50bcf411e77a000c642aa83fd36d755c07f6b52a12877154339334c8c6512228594f897f60f7cf725e760a41874c0e8492cb631c42320c5aa23d64b47c9e49df7af04ab845fcad788e701b6b3f3e0eb776ab733c0029de299ba272d649e6f53af0336a70eba9ee5480724fce8dec6b0dc5cf93a164f1a71db2082c87fbe0ea2d550c848f16920fd53c76efab97749cfc715b057f6c4b671c383a9cd698a669b7589db4e5fdb87265bc3ad1f2f310d5b2a36bffc327db7dd7d95b80dfbf5160c2400a95facbee0fc155d5691d206d6cec811c0df5261d4f76585f37a4869dc952a386cd90d825fdf96e97eeacad9bd991af07832e3f2efd01450aa95f284d9f035be22b7dea208a0005528f2136c324eee4170ea13de335ce73dee9935bc1462175b935e069cc909b0faa022c14bb8e91edff26bd2070c9b6d4ebe6ca2d556dc60e663cbf93d5e7415cff5eafd8eab1ea4dd306fba23795211b1862437e13eba033dd37febf0265b2ac34b2f48a9f2a504d9bc2e7b0752809ba2ce3bb9425fab4b9eb", .None}, + {.Shr_Signed, "-4e35d7ce37f754011b93eab952dc70a992982cef0f955c0346dc8c25bf1c49dff95b50be498a36c0b865a31cd5825811a07fed8731e7e90cd7b5bf7f8760756e24dfcbc936f83979928c74bad71e05f56cc101f368d4262e9a7dd601547147b4bd89988e79215c9f4b62a925559d4f68e8d14c4e431d6a413cbdebc5b53d5f477fad7aea636d1d87da91090d30e54c4351421a40d95bab31cce6aa74bcf817a042933ac6b0691b64686a43201bbbf9063079a12cb4b6e98e3871181cc72dce153ff26c3d5a4428cdc01adbb31d40e7dd57b4cb10631b21d1d814949a9dde7dcc03fabf3d25cf7d5f54c545aaf24cbacdbf516f66fef57f07ae50b9819b9fc1b125dba65396e956a00d12a8aa02b72425310ad9d1d8b6bbaacc4044ef89533029b64de4ec59b72c46c0c6751a101eea800e8e4ff5d12d8d06bc84bf58019b709a547c2ff17c455f0d562cbc0e927a48094fe6c19debd5440d346fac482819babe633f8395cc045aa343ba31ae3816a58d9c86e85c01e4cf66f2425c8be75422a71c946406fe8c63885ae595bc966a4cb07f9d7e2f9c9648fbcc748aab48cf2a2f1789e17841c926bebf483a6c043bafbf4c5d9a706dff56408945b80f1a4346db6e461ccdc6450be8174b4daf01aa6bd84873844325473c0433a46e08320f98e50ec52bbbe2bcf19a213151934a0ae18d412db1774e759ffd34d72828a871168f", "b", "-9c6baf9c6feea8023727d572a5b8e153253059de1f2ab8068db9184b7e3893bff2b6a17c93146d8170cb4639ab04b02340ffdb0e63cfd219af6b7eff0ec0eadc49bf97926df072f32518e975ae3c0bead98203e6d1a84c5d34fbac02a8e28f697b13311cf242b93e96c5524aab3a9ed1d1a2989c863ad482797bd78b6a7abe8eff5af5d4c6da3b0fb522121a61ca9886a2843481b2b7566399cd54e979f02f408526758d60d236c8d0d486403777f20c60f34259696dd31c70e230398e5b9c2a7fe4d87ab488519b8035b7663a81cfbaaf699620c63643a3b02929353bbcfb9807f57e7a4b9efabea98a8b55e499759b7ea2decdfdeafe0f5ca17303373f83624bb74ca72dd2ad401a255154056e484a6215b3a3b16d7755988089df12a660536c9bc9d8b36e588d818cea34203dd5001d1c9feba25b1a0d79097eb00336e134a8f85fe2f88abe1aac59781d24f490129fcd833bd7aa881a68df58905033757cc67f072b9808b5468774635c702d4b1b390dd0b803c99ecde484b917cea8454e3928c80dfd18c710b5cb2b792cd49960ff3afc5f392c91f798e91556919e545e2f13c2f083924d7d7e9074d808775f7e98bb34e0dbfeac81128b701e34868db6dc8c399b8c8a17d02e969b5e0354d7b090e708864a8e78086748dc10641f31ca1d8a5777c579e3344262a3269415c31a825b62ee9ceb3ffa69ae505150e23", .None}, + {.Shr_Signed, "533d4612597e519302b10bcf3555b72e8a6c0152824096e832975bb3d80e3b6aac7cddafa0a865034e1b83b12aa03147a160d113297438a5225c0c72abda238a958776f2f2c90aacbdf5e055de06738e5d609ad5db544720ea4e874454f0a4c7adac46296a2eacac4cfc9a8c798022967cca4a77d557cff879874aa44f5ecce164cf609eceedaca93c7f41d8994cdd5ba5d30c6c7509f07db1f37a4ca768825012db9bd86878b443314c7fb0550f3e83ddbf0ead4a7d05ffa7ecbc6ed869ff8a57cd62807c0be094cc54e3052b4dedb68c863b26265e54e275a1f3f91a8ed877496c2e7faaa8f0e0f5d5ff42dd73607304e40b0a1c6f426e911b68930f2882d61af4d7c3fa244f0be6cdb5ac9c0253a2e689c6ac8744a68d459caa230c3cc55a3f04abe206fb0895c70c1e146a233b02b5bd2db9e312106442224a1687bcd10e6e955dd6d84b29676ad83af5d7ccaf7e554255234680dc0270e1c04e61b5864f7ded6b4b082542e2ad0f2157f7ef1debceffeb2cdd39bc0adbb28b6bff079a00412df3308110a5a2a72798b19410ee26db2ac0eb4e7c1bbf30cc6b36b7fdefe2ee90220f9e7803db3d929e1d6fb6912f3db1f286bef85412db1cd99b124294a829cc32f4e7110ea0b26e55d180538c534ec6e715c5fcf638352e2ba27c8249b02c0f28f955c41832971fb28ea38c4f8134235bb41a66a73e725ac8c46f7e0ec7", "3f", "a67a8c24b2fca3260562179e6aab6e5d14d802a504812dd0652eb767b01c76d558f9bb5f4150ca069c3707625540628f42c1a22652e8714a44b818e557b447152b0eede5e59215597bebc0abbc0ce71cbac135abb6a88e41d49d0e88a9e1498f5b588c52d45d595899f93518f300452cf99494efaaaf9ff0f30e95489ebd99c2c99ec13d9ddb595278fe83b13299bab74ba618d8ea13e0fb63e6f4994ed104a025b737b0d0f168866298ff60aa1e7d07bb7e1d5a94fa0bff4fd978ddb0d3ff14af9ac500f817c12998a9c60a569bdb6d190c764c4cbca9c4eb43e7f2351db0ee92d85cff5551e1c1ebabfe85bae6c0e609c8161438de84dd2236d1261e5105ac35e9af87f4489e17cd9b6b593804a745cd138d590e894d1a8b39544618798ab47e0957c40df6112b8e183c28d44676056b7a5b73c62420c88444942d0f79a21cdd2abbadb09652ced5b075ebaf995efcaa84aa468d01b804e1c3809cc36b0c9efbdad696104a85c55a1e42afefde3bd79dffd659ba737815b76516d7fe0f3400825be66102214b454e4f31632821dc4db65581d69cf8377e6198d66d6ffbdfc5dd20441f3cf007b67b253c3adf6d225e7b63e50d7df0a825b639b33624852950539865e9ce221d4164dcaba300a718a69d8dce2b8bf9ec706a5c5744f9049360581e51f2ab8830652e3f651d47189f026846b76834cd4e7c", .None}, + {.Shr_Signed, "-a8c7fe49d52fb0f8caf3e300cd8e74b5dd3c7e12d7deb239e360bb7058d473f80f226dfb276592e7db0eab85598f080da3dd073ac4a8765b6170ee05c86173978d9bfce5a03fb4d9aca3d1ccf3a70228810b47be576e6536c7311e1c229a1bb77023587691ac5a848e63ec3dc111ef1ba7ee8089e5ee6bd0e7bf9e01761ca83fbc82d289a6fb74a3ad00a7e1173d000593f874b20239cc45f2347f1b34f4f2c6d9f9e978f80d588916e9b9c175ccc74ca145b9f243f838cb0c002f63eded461a7be2cf9d790b69be43ec2a241ca43aa829ec004b8b9e3a98b7e07ada6b51e7622eca9430602d5982de2e49acee169bce7acabdb6c5b95cb0e3ff71dc1ce5c1c085f4f561642c6026d5b3eeff4b349b783bae44a315a5778eb873d32c5a96c209ba22f046a9727b66bd6e4422050e7b85feca544ea900312268842e727a5f03d38ed5aeae67cd757375f241e149be83a53e656e0ef46f19fa0b9375765f939a52658abb94cd383409b8a035218720e4a3079ad095434772a707fe0b156d3bdb65e90d52426602289ed9410553996e047a7aa9f20f77c6c202d252dbaccaec519011f1a4a83d74837815a11f3d03cee7bb9c4f77f702668b4590c62f8f491436f8f354c38ba90c9c2e14aa90800f7a59dedf899826e2add7467b23233ad17e0e0d8f5f2eb61d06b43688637d87ad27820590a91c5d0dba3f0c946f89c7f9c0f7f7", "73", "-1518ffc93aa5f61f195e7c6019b1ce96bba78fc25afbd6473c6c176e0b1a8e7f01e44dbf64ecb25cfb61d570ab31e101b47ba0e758950ecb6c2e1dc0b90c2e72f1b37f9cb407f69b35947a399e74e045102168f7caedcca6d8e623c384534376ee046b0ed2358b5091cc7d87b8223de374fdd0113cbdcd7a1cf7f3c02ec39507f7905a5134df6e9475a014fc22e7a000b27f0e9640473988be468fe3669e9e58db3f3d2f1f01ab1122dd37382eb998e99428b73e487f0719618005ec7dbda8c34f7c59f3af216d37c87d854483948755053d80097173c75316fc0f5b4d6a3cec45d952860c05ab305bc5c9359dc2d379cf5957b6d8b72b961c7fee3b839cb83810be9eac2c858c04dab67ddfe966936f0775c89462b4aef1d70e7a658b52d84137445e08d52e4f6cd7adc88440a1cf70bfd94a89d52006244d1085ce4f4be07a71dab5d5ccf9aeae6ebe483c2937d074a7ccadc1de8de33f41726eaecbf2734a4cb1577299a70681371406a430e41c9460f35a12a868ee54e0ffc162ada77b6cbd21aa484cc04513db2820aa732dc08f4f553e41eef8d8405a4a5b75995d8a32023e349507ae906f02b423e7a079dcf77389eefee04cd168b218c5f1e92286df1e6a987175219385c295521001ef4b3bdbf13304dc55bae8cf6464675a2fc1c1b1ebe5d6c3a0d686d10c6fb0f5a4f040b216", .None}, + {.Shr_Signed, "afac5e1a6cf5a1f7b304eba87473bf549e2ea16d7bf8ed4beb1a3d1a71e2879eb5a12c268dac022eefabda9eb04e8d4eb4471b2f415b2df3ef12dd0825a03abf66b6884c1853c963dc5ff69ec647e921a53f924587e94e18a6d0dbd121b3863ef3bc13ccf995558a147933a99384970889a4cb0a8b49f69b0295769d84053d66237d1725ede3624403fcea08a1b96626c118c6219cfd276bb3b1dafd1bc27a453e0a189be3bab804a1b6f919e382536f39acc1aa33ef9107cf845fec7b376a8970e1f57f9a90972c0f44e404f0b13bdd194cb8e3a5c9237a0c4af48559fe5693e58ea11af64f9640f9a0bc9f2ba93e773a0a7e351d4bb197008b230de863820ac019adfd20c98d304480002ab0e90fc224077db707d2446df900743beed12df274db161788c950bfc650abf648efb2e05d2f546bffc3148714ceecaa7fcb87fb289236987d16c79d4755c194c54f66a59c203aed460aa7582254e278ac893b8b5285028306f52c38329087f1786a1b9f97b77c178d97867b3e6b84f0aac0df6cd325093bef0042d24283b9256ab0d262cabe957a80271f59b1b7d10c52ca6b81309d3336314925a9f1771a9d8d2f6aa5640fbade276e4a21f30e08215451887d4a1de5b096f45e59019c8ccf05070f05343f1aa6cbf506a52bd1d28baf380ce700f78c7273c73b25b66939e1dcae8371799c02aef6de73ca0c7cd17a82dbce2f", "28", "afac5e1a6cf5a1f7b304eba87473bf549e2ea16d7bf8ed4beb1a3d1a71e2879eb5a12c268dac022eefabda9eb04e8d4eb4471b2f415b2df3ef12dd0825a03abf66b6884c1853c963dc5ff69ec647e921a53f924587e94e18a6d0dbd121b3863ef3bc13ccf995558a147933a99384970889a4cb0a8b49f69b0295769d84053d66237d1725ede3624403fcea08a1b96626c118c6219cfd276bb3b1dafd1bc27a453e0a189be3bab804a1b6f919e382536f39acc1aa33ef9107cf845fec7b376a8970e1f57f9a90972c0f44e404f0b13bdd194cb8e3a5c9237a0c4af48559fe5693e58ea11af64f9640f9a0bc9f2ba93e773a0a7e351d4bb197008b230de863820ac019adfd20c98d304480002ab0e90fc224077db707d2446df900743beed12df274db161788c950bfc650abf648efb2e05d2f546bffc3148714ceecaa7fcb87fb289236987d16c79d4755c194c54f66a59c203aed460aa7582254e278ac893b8b5285028306f52c38329087f1786a1b9f97b77c178d97867b3e6b84f0aac0df6cd325093bef0042d24283b9256ab0d262cabe957a80271f59b1b7d10c52ca6b81309d3336314925a9f1771a9d8d2f6aa5640fbade276e4a21f30e08215451887d4a1de5b096f45e59019c8ccf05070f05343f1aa6cbf506a52bd1d28baf380ce700f78c7273c73b25b66939e1dcae8371799c02aef6de73ca0c7cd1", .None}, + {.Shr_Signed, "a47a5e2b3d54981fcc413d22a050b6c79183934ee9719cef6f2f10b1186d76c6caa1494451837d8f8948257343d19f0b66a1f3fcaa805c7b8e8cdee3dfbd4e0bdf41fff9ab0aba1812f69000bfc9750979e15e88b79b3e2ccb79f7187514fdbc2cc748a65d61b491fc084dfed7cb66e4e8e406f2e8f7878fbe8e1ed170f8b1f91c34d0a7d7122ea77f3a5799333152768378174ebd86867a400ab5a2858a96c80c94ec464f18474d55de498e0dc24637b4f76f892153398e48c698c54147eb083f8f81ee3ad1a88339f45af1f12c53bb5b723ea060b97339094d3dd0f8d40c0424543ff0491df22d0bf243f4b9d4de25b3757c26362d4d80adea5389a9621b5022b04585f8a74b80aa60b3adea1db9eab1979218f16436b5df9c0cd180f0177163c7133139773f716b94b6bdfaaae161890e19b583f2fa51796d1346f41366cc2589b2d688022ec95bbc5433e1f6991b8c39b627f1321e5c25b2fc870dd1ffe67a7c2b5b54d216bf56bcdd220963bfd42b2cdda2956707d5365532fba29880ba0c222066f4ec4b04e1dfb7d50a2bbd7b6bb1b1a6cd8a81d36fdaf0a5f2220ddc20af8cd2b388480f4fdf8506867a7a124e529eacad87c250944e6483fb00522385daba34da614b3799685540516c0e3a6de57cbcc393a5c286622af84326c34a3a6910c5f85dd5aece2b02eb25dc311b2b9907aae1d4529b2f243f1f62f74e78", "43", "148f4bc567aa9303f98827a4540a16d8f2307269dd2e339dede5e216230daed8d95429288a306fb1f12904ae687a33e16cd43e7f95500b8f71d19bdc7bf7a9c17be83fff35615743025ed20017f92ea12f3c2bd116f367c5996f3ee30ea29fb78598e914cbac36923f8109bfdaf96cdc9d1c80de5d1ef0f1f7d1c3da2e1f163f23869a14fae245d4efe74af326662a4ed06f02e9d7b0d0cf480156b450b152d901929d88c9e308e9aabbc931c1b848c6f69eedf1242a6731c918d318a828fd6107f1f03dc75a3510673e8b5e3e258a776b6e47d40c172e672129a7ba1f1a8180848a87fe0923be45a17e487e973a9bc4b66eaf84c6c5a9b015bd4a71352c436a045608b0bf14e970154c1675bd43b73d5632f2431e2c86d6bbf3819a301e02ee2c78e266272ee7ee2d7296d7bf555c2c3121c336b07e5f4a2f2da268de826cd984b1365ad10045d92b778a867c3ed323718736c4fe2643cb84b65f90e1ba3ffccf4f856b6a9a42d7ead79ba4412c77fa85659bb452ace0faa6caa65f745310174184440cde9d89609c3bf6faa14577af6d763634d9b1503a6dfb5e14be4441bb8415f19a56710901e9fbf0a0d0cf4f4249ca53d595b0f84a1289cc907f600a4470bb57469b4c2966f32d0aa80a2d81c74dbcaf97987274b850cc455f0864d869474d2218bf0bbab5d9c5605d64bb8623657320f55c3a8a53", .None}, + {.Shr_Signed, "-f2d22771802ae10c0766f72e6a6fd06e5c60a9c064935b5f5cfa5536e3e5d6bb108ce049d75a100c1b7ff0b5dd4fa62865b51167cbbbc7009ce222fbe992e7e4e44084dbf80851252e74707c138ede81a6744da6917c46937a632e061eff1e5f2023c6867518e721f6f5791c83700fce1854b4fc8a2c08a97dfe47289b7356d988718514a41c3ad24d146c7def15ba2a884e7fd05e02c6dabd6f4550ee9e3ec064f2e9e8c971cf82c4179fe87ba60f7823bc46d7b7adf216186e291d5890e1dbef1ee6d42681fed895a4fa2c7c9adddd652d1f30e1b8b1fe4cf515e3212f7f0a0f3bc63f93249e570e616dbe7ef5538f4b46e8ef5fd56af434c37395cdb9fa5bc6b3ff12a801f7cb3910665d15d5b87fc07b9dc7405bcf98499ff7e1799422bad9c1de4bf288fb6774755c730bf63949e40ecc49e7f0e1f32ab2aa15f2a19c5866e3e67745bb8206ba972f4f471622176582823786398c158fbc11f4d07ae126e087e0bacd415ec9b37a21dde46fe11381a2758f2de8214de21c3276e824bd33c4dcea045f2e8179515ae3647bd75fb8c7f4a967840c279573f82e42e87933c58b1f08f1da884aff47b03a9b8b36a5160e7ed8ba265da3b3b25dc9c234edec56dbb2ec0ffa9ba252fe7d5b1ba244b61f43bae369cc2b8167fd061afcdcca72effcc5c4d9850f8492c184242b36538c45ca282b9e85e2333f3bc422fd43256cd2", "0", "-f2d22771802ae10c0766f72e6a6fd06e5c60a9c064935b5f5cfa5536e3e5d6bb108ce049d75a100c1b7ff0b5dd4fa62865b51167cbbbc7009ce222fbe992e7e4e44084dbf80851252e74707c138ede81a6744da6917c46937a632e061eff1e5f2023c6867518e721f6f5791c83700fce1854b4fc8a2c08a97dfe47289b7356d988718514a41c3ad24d146c7def15ba2a884e7fd05e02c6dabd6f4550ee9e3ec064f2e9e8c971cf82c4179fe87ba60f7823bc46d7b7adf216186e291d5890e1dbef1ee6d42681fed895a4fa2c7c9adddd652d1f30e1b8b1fe4cf515e3212f7f0a0f3bc63f93249e570e616dbe7ef5538f4b46e8ef5fd56af434c37395cdb9fa5bc6b3ff12a801f7cb3910665d15d5b87fc07b9dc7405bcf98499ff7e1799422bad9c1de4bf288fb6774755c730bf63949e40ecc49e7f0e1f32ab2aa15f2a19c5866e3e67745bb8206ba972f4f471622176582823786398c158fbc11f4d07ae126e087e0bacd415ec9b37a21dde46fe11381a2758f2de8214de21c3276e824bd33c4dcea045f2e8179515ae3647bd75fb8c7f4a967840c279573f82e42e87933c58b1f08f1da884aff47b03a9b8b36a5160e7ed8ba265da3b3b25dc9c234edec56dbb2ec0ffa9ba252fe7d5b1ba244b61f43bae369cc2b8167fd061afcdcca72effcc5c4d9850f8492c184242b36538c45ca282b9e85e2333f3bc422fd43256cd2", .None}, + {.Shr_Signed, "878f08eee0115631aacc74c0fec660ca66b687ae736f624b638ac885c04a8060945578a5beed5ee5aac74fecbbfbb1ae959bde837575da635615e9be0d7c950107a06fc697732e6598bf98565f1b05bb429c78c628e9d956050fbcecd926c7b994ce21479bfee9afb09023397c98a4665b2b9fa116cfebb85639ac2735c0ea7782c04fe2e7761f380e6c241813958e0d4e107eff3c071ffc54f0f183cde7d58739b3d43bf92b3657c9e526631e78521ab7a9a408a21cd9d70cf8dbcaa7454e67bf8e862dc70557158a40b1319daf28ce18b4d1c523fa201277843d59539f197c26cc0c92ca35580d345e7c89cc72b9ead5a66275bbd80f4f1e1d2478994245d7907cc6a6267b953996c5aa3dcdaa4dedddb1e46d656463d68b2247d72d25d72991c5ba2546afd7d602caa8953782cb45890874f6a47e8c1b2ed207ba249039a453670406926676fe279e4918d807977e991cce8324430549f040eb86a8079df8e3dbb9390dcea5c7b1135414d5510509e39acd1b51e7873867e5eacab1aa13526a9603c3fcde7216d2acab76c24ee1e92b971598eb23d7d35e877350de884cd5db0c20dfd77ef3af265e32c20432ee752ad93760351addf88c3d0ac6bda6d95da6255e0020653e0b70384363a4b77621c4a2469c4bc37f3a36dc85f21a034dd0fece121cbbf077e2b9910e07150330e5bddd3812694438e4d60b0d85e2f0c554", "20", "878f08eee0115631aacc74c0fec660ca66b687ae736f624b638ac885c04a8060945578a5beed5ee5aac74fecbbfbb1ae959bde837575da635615e9be0d7c950107a06fc697732e6598bf98565f1b05bb429c78c628e9d956050fbcecd926c7b994ce21479bfee9afb09023397c98a4665b2b9fa116cfebb85639ac2735c0ea7782c04fe2e7761f380e6c241813958e0d4e107eff3c071ffc54f0f183cde7d58739b3d43bf92b3657c9e526631e78521ab7a9a408a21cd9d70cf8dbcaa7454e67bf8e862dc70557158a40b1319daf28ce18b4d1c523fa201277843d59539f197c26cc0c92ca35580d345e7c89cc72b9ead5a66275bbd80f4f1e1d2478994245d7907cc6a6267b953996c5aa3dcdaa4dedddb1e46d656463d68b2247d72d25d72991c5ba2546afd7d602caa8953782cb45890874f6a47e8c1b2ed207ba249039a453670406926676fe279e4918d807977e991cce8324430549f040eb86a8079df8e3dbb9390dcea5c7b1135414d5510509e39acd1b51e7873867e5eacab1aa13526a9603c3fcde7216d2acab76c24ee1e92b971598eb23d7d35e877350de884cd5db0c20dfd77ef3af265e32c20432ee752ad93760351addf88c3d0ac6bda6d95da6255e0020653e0b70384363a4b77621c4a2469c4bc37f3a36dc85f21a034dd0fece121cbbf077e2b9910e07150330e5bddd3812694438e4d60b0d85", .None}, + {.Shr_Signed, "b637bc3957a206678ecadee4aa5ae51146f9b08d9add071ff2b7f0d04680bcdab5356eeaf8d89f6b90ae7f9c0e530661a84c4551a0606ae2da5ea76e9ad9c032daea14982150ace7f0d0190597a792222ffcfd6a3d65c5c2057162c3bffd7ee71bf28669bbce36b4b04e2ca81cf50d9e1e062887033d62bee6aa49a67b32d3198f7d041d974087b1dd319251f8a88212a0a3eebff3480b0af39f4133d42fbba89b0aa5a532432d763661b77bb55902c062bb56d8f8202b417846667d5e366bf2e4a48211ccdedd36e3bcb68a8a1f16c4b9a7cb73315a7bbd1a2f7af8811ccc5cf3f5056f575f63a42dc8b5bfd469769359ddfc8b1021077808af5c944057d07e164b4e3ce83e9cbe4bcc83f1b030d18bcd90338e729cdf39e83afb07ebbcfbb25258768d63d39a787354b102ffd9118322f1982270b85cb87a08e36cd98d88fc33a8dc8a51c52ff1ba6a8b1dc02f0c06ce745a2aab47417499a045039fe1938122a81f9c3d98473253c121afb4503fee6942d151373df6ce8101ba16dd72d481902cd45a1995812fa77f25b1f77a2d7f1caca5ebbcfe42c52be1d7d390f60263362f27165a7c1eb274e58b2b0b3435db194ed85c320c13e3d44d091ef02911d92176a0456b74659f3ffd18f44232855d8426780eb6633ea090e4796f0ac49bcc969fb06da913e05fbd67ce9a1d3529e57164b6c2bfc64cd2d08a08cf0f02bfaa", "1f", "16c6f7872af440ccf1d95bdc954b5ca228df3611b35ba0e3fe56fe1a08d0179b56a6addd5f1b13ed7215cff381ca60cc350988aa340c0d5c5b4bd4edd35b38065b5d4293042a159cfe1a0320b2f4f24445ff9fad47acb8b840ae2c5877ffafdce37e50cd3779c6d69609c595039ea1b3c3c0c510e067ac57dcd54934cf665a6331efa083b2e810f63ba6324a3f15104254147dd7fe6901615e73e8267a85f775136154b4a64865aec6cc36ef76ab20580c576adb1f0405682f08cccfabc6cd7e5c949042399bdba6dc7796d15143e2d89734f96e662b4f77a345ef5f1023998b9e7ea0adeaebec7485b916b7fa8d2ed26b3bbf91620420ef0115eb92880afa0fc2c969c79d07d397c979907e36061a3179b20671ce539be73d075f60fd779f764a4b0ed1ac7a734f0e6a96205ffb2230645e33044e170b970f411c6d9b31b11f86751b914a38a5fe374d5163b805e180d9ce8b455568e82e933408a073fc3270245503f387b308e64a782435f68a07fdcd285a2a26e7bed9d0203742dbae5a9032059a8b4332b025f4efe4b63eef45afe39594bd779fc858a57c3afa721ec04c66c5e4e2cb4f83d64e9cb165616686bb6329db0b8641827c7a89a123de05223b242ed408ad6e8cb3e7ffa31e884650abb084cf01d6cc67d4121c8f2de158937992d3f60db5227c0bf7acf9d343a6a53cae2c96d857f8c99a5a114119e", .None}, + {.Shr_Signed, "a222f6951201367ccad6fdebc966873cdfdf6d06332be4e3665d24809df9ddba05fd7614d99abce1a56d67da94c6655d680d20e449cadc6e0b9fdf2bbf7cbc5cf557196f6454d6f6feb33792e103db1126aa17ac8413bef3abc2876d0c84fc20cc1b84f86b8ee8164bfefc9797d91d0869cdad42b814c13eae5d5f212724cd76f0a4ba0cd0161fecbd2c15f34809462dd538e5867e8d455dc6d32f14e4cc1faf96298df393cf4c329d479f9a16d4617759007572a1ba0f6b9d8df4c4af511ce1b597c534c011a71f8a8f655c365662b72e9b4146437fd8c86ef039fe897c61047dc4fccd314bcb6e22878e52ce25c45e49487729039bf7a92b10d01ecd04306b8a43ddb9ab4229ff9710db1d07b5f61706257b6f117a1f2ed673cc7b3ee85f42731ebac7287378d969d6744ff5b209217c7697d6d3f1d98a612f89327c80741b86daf05e25e67238c37ee3f51b6e9f2a27e9826e3905f07f234cb89f4fdb5aa75f48861507a9b00a7d26d20b81d88835bfba999bbde0108fc864eea03068ef08428681256b5bb75029c533e9ad60bccd77aece1221950d30ef90fd6a1d5b2b024d99399ba329bab5ea66aaf10db8552da87cffe3829007177665ee3cff0a06e1131b90c8d8bf73f58deafb9c3b9a9f85da2478803c0cdd464136e67f552d27e745b786219deaf4b73b0ff47b031cf34917163c3af842575c2ff63f93c371937a", "6a", "2888bda544804d9f32b5bf7af259a1cf37f7db418ccaf938d9974920277e776e817f5d853666af38695b59f6a53199575a0348391272b71b82e7f7caefdf2f173d55c65bd91535bdbfaccde4b840f6c449aa85eb2104efbceaf0a1db43213f083306e13e1ae3ba0592ffbf25e5f647421a736b50ae05304fab9757c849c9335dbc292e83340587fb2f4b057cd202518b754e39619fa3515771b4cbc5393307ebe58a637ce4f3d30ca751e7e685b5185dd6401d5ca86e83dae7637d312bd447386d65f14d300469c7e2a3d9570d9598adcba6d05190dff6321bbc0e7fa25f18411f713f334c52f2db88a1e394b389711792521dca40e6fdea4ac43407b3410c1ae290f76e6ad08a7fe5c436c741ed7d85c1895edbc45e87cbb59cf31ecfba17d09cc7aeb1ca1cde365a759d13fd6c82485f1da5f5b4fc7662984be24c9f201d06e1b6bc1789799c8e30dfb8fd46dba7ca89fa609b8e417c1fc8d32e27d3f6d6a9d7d2218541ea6c029f49b482e076220d6feea666ef780423f2193ba80c1a3bc210a1a0495ad6edd40a714cfa6b582f335debb3848865434c3be43f5a8756cac093664e66e8ca6ead7a99aabc436e154b6a1f3ff8e0a401c5dd997b8f3fc281b844c6e432362fdcfd637abee70ee6a7e176891e200f033751904db99fd54b49f9d16de188677abd2dcec3fd1ec0c73cd245c58f", .None}, + {.Shr_Signed, "2c6c9020a4b523c275bfca6dd483917856f183b2b69af89225c53963c2d019a133f24754bbc894584eeb4010dad60fa721c5887d3ab780b4f48351ca267681f0a68b931d25667992511e4d3b9a2f24b5ff4b446ac19cc3dd4ece1d455d1e32c6e85e0cb1e484fe6758986d95f45f64518604557d24b5c1a9c1ed0f27cc8061e2dcafd3aeb7f24df759702373aa4a7e91ca3636ebd893c8e0e6fd9a765ca17821d6fffde20f9125e2d6c64def515f0837231120bf2efc44fb950cec9e276283e16b2d35339ce6c47bcedf671f023402cb204ba178034bce0c500658bf5b05bb03c2d840483d8ee3cd5e64c50488c1e4897e5fc2593fe4daa09d33f1e16fdbe9418d801fe9c8b387219568795949f91d3f58ede96392812acf06e4ba27d0b6860192200fd7163cb907abc96f2881d2703d718cf378027dcc7b09cdc41021d3106176b7a3a778ec3c892c7094b38ca75b23d1834f52e2d496f3508ca074d640b187a7cc8c861b5a2ef3ca60a0fc52a9b030cdc4e76de158abacab7d22277e442701c2d077d5486ca32add5624e4cecfad5d62770d01486305482d018b5a34647cd7c799263ffebd26bdd6baa90b382ea835c5ea133d048e192f8d9ca41ce2c8b8eb02fb507351c93f5a316379084579a40c07aa1e7e55137c5e6c26ffb8435c217922cbb30633d46e8bfd88e599c195b9ae9bd476c7ce8bc23293436dd173d89114", "40", "2c6c9020a4b523c275bfca6dd483917856f183b2b69af89225c53963c2d019a133f24754bbc894584eeb4010dad60fa721c5887d3ab780b4f48351ca267681f0a68b931d25667992511e4d3b9a2f24b5ff4b446ac19cc3dd4ece1d455d1e32c6e85e0cb1e484fe6758986d95f45f64518604557d24b5c1a9c1ed0f27cc8061e2dcafd3aeb7f24df759702373aa4a7e91ca3636ebd893c8e0e6fd9a765ca17821d6fffde20f9125e2d6c64def515f0837231120bf2efc44fb950cec9e276283e16b2d35339ce6c47bcedf671f023402cb204ba178034bce0c500658bf5b05bb03c2d840483d8ee3cd5e64c50488c1e4897e5fc2593fe4daa09d33f1e16fdbe9418d801fe9c8b387219568795949f91d3f58ede96392812acf06e4ba27d0b6860192200fd7163cb907abc96f2881d2703d718cf378027dcc7b09cdc41021d3106176b7a3a778ec3c892c7094b38ca75b23d1834f52e2d496f3508ca074d640b187a7cc8c861b5a2ef3ca60a0fc52a9b030cdc4e76de158abacab7d22277e442701c2d077d5486ca32add5624e4cecfad5d62770d01486305482d018b5a34647cd7c799263ffebd26bdd6baa90b382ea835c5ea133d048e192f8d9ca41ce2c8b8eb02fb507351c93f5a316379084579a40c07aa1e7e55137c5e6c26ffb8435c217922cbb30633d46e8bfd88e599c195b9ae9bd476c7ce8bc232", .None}, + {.Shr_Signed, "-e059c1bbdea9ac7cc6e15684e38011cb7a93e936ee58d42d4efe4e2c188f9d8acee39ff528e690b637c108ec5515694798c6b3f4ac52ba3711408df061d1ac2ba5dfe26b477b21b0d490657827afc7ce2223de3cda94bf5088ddd46f08b829dc6db1bc97b3c6572dcb75bad07130343fa435f19034b4208579c48ba14936df53b9d722a92b68e9d7deb2a4318cdfa619dbc59967735288b582da27585bf7fbbf2d3bf81c9ef11672123847bd2f4a5ed090ca559ad2fe740f54cc2e203ec2363adb57d080735897e0428ee651c12f2864d1336507972045ce80171dce73663e825308972c1dfa0dba3b956e8166ffba3f2b1477fc1b75fcb8734e19b287667cb2257d50afbfda9c3956ea1125d55b9ca0dd51c67cd27aa5f36a0b5d74e101b509b361aaf57318d2be6d7127b67bdb95b3824a6cb81428339b36fa7326e3874184ae92db4288f7123490d11902faee81ad32e95922a5af0e707589b2128bb7fabbc6b9b87179e61514c00817fa6d5f9df15e0ab6138de2bc54613533fa0508148c8021d94e9b7a88b9ced65a373970964585387e5f5887b6c55bfb6d0b34afbde6fe4395653ff4cd41b1eab8b161f241e3ad888f8f0ea9fe5bac8e51d7e4cbbcd5fb249b31fdc438bddfcdcfa07654c2cd03b45374a1683d6573d2727e55862ce0d48a4f6acd290cf1f20284acc8de5f4ee1eb37132b0ceca5d9bdc3468e1bc4c6", "4", "-e059c1bbdea9ac7cc6e15684e38011cb7a93e936ee58d42d4efe4e2c188f9d8acee39ff528e690b637c108ec5515694798c6b3f4ac52ba3711408df061d1ac2ba5dfe26b477b21b0d490657827afc7ce2223de3cda94bf5088ddd46f08b829dc6db1bc97b3c6572dcb75bad07130343fa435f19034b4208579c48ba14936df53b9d722a92b68e9d7deb2a4318cdfa619dbc59967735288b582da27585bf7fbbf2d3bf81c9ef11672123847bd2f4a5ed090ca559ad2fe740f54cc2e203ec2363adb57d080735897e0428ee651c12f2864d1336507972045ce80171dce73663e825308972c1dfa0dba3b956e8166ffba3f2b1477fc1b75fcb8734e19b287667cb2257d50afbfda9c3956ea1125d55b9ca0dd51c67cd27aa5f36a0b5d74e101b509b361aaf57318d2be6d7127b67bdb95b3824a6cb81428339b36fa7326e3874184ae92db4288f7123490d11902faee81ad32e95922a5af0e707589b2128bb7fabbc6b9b87179e61514c00817fa6d5f9df15e0ab6138de2bc54613533fa0508148c8021d94e9b7a88b9ced65a373970964585387e5f5887b6c55bfb6d0b34afbde6fe4395653ff4cd41b1eab8b161f241e3ad888f8f0ea9fe5bac8e51d7e4cbbcd5fb249b31fdc438bddfcdcfa07654c2cd03b45374a1683d6573d2727e55862ce0d48a4f6acd290cf1f20284acc8de5f4ee1eb37132b0ceca5d9bdc3468e1bc4d", .None}, + {.Shr_Signed, "f6468bcd532987bc4af9b2727c087d9caab2eeccef6ec271fbca41b6b14a31f0bd76545f80404c86168d631cc583eb1d12bde6dd29a60f1d6705692b3ddfef723fa386bfe57e68a5e77ba65368f551ba7b167ff9f87950e36c98dbdbcd69ad7b7f2351ea43f97ec09f00c39cb49b912cd924b29fbe245da67d363cf6f955c34e7051f1195044f191941e7e7a0f6c77436dff06606294d8985957ad8b24f763dad54da97c54ad662cd8fbb3ec82c5c3d48fd532055c4f028407fbfb681067df5b25b0b738a71b12471a887ebac7940c4d15bf38cdf48e4a577bdd1e8a898f6d8e764cb546e1ba7f5f88f3715487344d29bfebddfa0cdd8040bd92b51774902b0a9f1e8a6b2ae5bc4b58e9f5018cfb5b4114875d0fa9d0a85317af7f57df3f26c0aff75cd498f1b96dcde35f1c6e99b2829a7371efd37d47616f5ec7b041b37d10a3e91439c6b9e0070be595aa1fcae244a28d1f61d9dc4cc5749abd26460359c61b09ec6d0d365db15ee53fdff7cf1ae0c047905412a83e97e7dad28684ab645103835e061274eacd0280060b3252c03a7fc1162e1249ee88222b2b789e9f0b6a3f48b9bdd9a0dbc7a92ca07847f3dec8e6348e1975b0a516d40fc7376299e883ab25bd8d1beb36504a5258f811b6bb29c432013719ec6866996a4001532ab46db11b6b636fd082bda397a292b2c9c7cfe7a5ace692088a23f28e683625341e71", "21", "7b2345e6a994c3de257cd9393e043ece5559776677b76138fde520db58a518f85ebb2a2fc02026430b46b18e62c1f58e895ef36e94d3078eb382b4959eeff7b91fd1c35ff2bf3452f3bdd329b47aa8dd3d8b3ffcfc3ca871b64c6dede6b4d6bdbf91a8f521fcbf604f8061ce5a4dc8966c92594fdf122ed33e9b1e7b7caae1a73828f88ca82278c8ca0f3f3d07b63ba1b6ff8330314a6c4c2cabd6c5927bb1ed6aa6d4be2a56b3166c7dd9f64162e1ea47ea9902ae27814203fdfdb40833efad92d85b9c538d89238d443f5d63ca06268adf9c66fa47252bbdee8f4544c7b6c73b265aa370dd3fafc479b8aa439a2694dff5eefd066ec0205ec95a8bba4815854f8f45359572de25ac74fa80c67dada08a43ae87d4e854298bd7bfabef9f936057fbae6a4c78dcb6e6f1af8e374cd9414d39b8f7e9bea3b0b7af63d820d9be8851f48a1ce35cf00385f2cad50fe5712251468fb0ecee2662ba4d5e932301ace30d84f636869b2ed8af729feffbe78d706023c82a09541f4bf3ed69434255b22881c1af03093a7566814003059929601d3fe08b170924f744111595bc4f4f85b51fa45cdeecd06de3d496503c23f9ef64731a470cbad8528b6a07e39bb14cf441d592dec68df59b2825292c7c08db5d94e219009b8cf634334cb52000a9955a36d88db5b1b7e8415ed1cbd1495964e3e7f3d2d67349044511f947341b", .None}, + {.Gcd, "3f1ac58fcee77a9e30856d3602c02dbc45c02604c502c3ed7150a03fa9518e5b4cbbe7c3baef9c461a92c94996bb76ac83913b709b667ab4e99ec16a89c4a76491d5c7da33d7f41b81314645f52aeadce0fa1da5cd8fb50facfe0d4bba8eb8e2b6fe1320a5f4ed024ecd4fd1dd9ee077ee9264614edf80a5864559dc7851707d198fdb406b858c9bf044f2d4656b5959e2299908241477d59da8da767118a659ac01cacc2bc480588f05718f446f114d9aba334a85ad9bfa5fd918d13cc16e6344c9b6ea3b4f8beefa13209482a60e8ce00290298bc53f4822ff900d6f863734bd45e0f725070bf217eb02578446ee31e06d4dc5a35598f3f3d760ccc49cd730b68f8669cce010e678ac12ff84548f2cc7864e64f0fb4c7d5f998594ad2254bc36fa01451cabd3b23423e50a0331b8b79393114556844e3869947b34927c1c3eb1d3f684fd831f9294be03d92f9c7bf430d97d93e1763c0b3113fd016a43e4c86c3700b365973cbcc82f9b6b1988a53d4e09d1bb0275b09ec8a48a9de89b78da053600f5272ca872c4e8747111b860f8ab35a5d5eefa4c7cb486a813ebefd26cc66da6d11f737d16e4337e09d106a72cd6a478d5a291d2ad1a9c677009df517fec99863f1f04193e2cc5cb921020d3566c604bbc6b43ba0a2994dc08a81408a57ac1477be6ac2dee0fe361b9281db0dab200842afc341ef6319f38458b93a04d", "db0cab92895f670509d237fdaaa4c094883c8ede25d0fec6a97dd01781834c1860cef9cf83e3ac070f4c5c5a9436ea9a7b76a88304b57cad85fc08124523633f3f740cff1ea69678ea7e4cdffa8e4b959dcf6e90d74ffc56a644c7e5ed00c26f851bcc0d8b48f7fec7f1673c4c274f72db96c9f8c7d740b445e5efd2ef86ed0126299aee8e0986c8b6c673756402675cea59142ffb2540eb6fa468cbfd794d63207bdd38ffdb6efd69ea1cbe5e775cb47145d849683609857e9884bd6467cfe7c11d57af2abed6385c0ad60c995f8747db2f96644afe8262da35c81b2358f37ce411d1d230a85ad9f35023b8f6554ecb71e08075a070c67d0f3d7666453653636fc362a338175217f362c44b982a53f65eaaf1782f28db57260332dff6d8e39511f1aeebadd47a7fb443f2b50b50132bd88376daae229e68e115260d008538476caa21a41b9c83e048b38979e92faab696311480bac62e527e7fc1e8272254870769ecbd1f2529e60ddfec20560b08845daff8a0c6c548624afc07575d5f09f342d5f797326a48f6fbed10772b232c0358bef90066330d8a3a3862017f1bfb9a0708673c4aca790730b4ce1236412681afcd080de378dee665d09821dc2c7af43beae81ecc0b0de4f200e230c015ed120e4d27e019c0bc983a1aa83734b9ca54865326b57e5b33ea0f2186d26e1228da39046657e9b68130e68dd8174b3e2703", "17", .None}, + {.Gcd, "6cb0eea9f2c39a6484adc39c16acccdbecc7f42119c8e7259442519d4b330d5e2081287d722eea0387753b1ab5c1804d827cc2fc8cc30541cdc572910d7de4cd50c12ae84e0aef70218513b5d190b1b9315ef6b9566b8280a4463b8df4b80beead60c3a5c7688f71cf9e51c66c16976de4fb4d68ccddf015090252740de11410ea2396ed4f5402121c64433647fd452710d1a42e89d952d7ff160d9682458a77b117056789ced9e548c9b5cada2f5c4a0f2c6e822e83328f6bb27f54ebc19dfe304c796e39705cf3d48b9ac15cf51abb0640a37963093d467337d402ac4beb42d17e5e86c146199e5ca481c7c02d2d84d1ac295c2ec8c4255443b36c0371b14d22e29c8cb84210d16351262ef045c880993be4457fdadce62e33f7d9d80156e47f275d9fbf81128c4e685a29b098b99d4963852afcc87177101044d6a094acab47a2be8962c368a0b8b5b74644f54dfeb3e1ca5fe64adc5e5971c96e4c8648fdcdfb95f0a7928cdc7a675f94ceae1e46604180670f9cd77383ea84284db4e36bcdb63fdd26f593f3b44cdc185feb7d891975c18b5f64cce90bf35ca198fcfa304dc50cc8ea27868ee6abcd828b7f51b8e56afa9430d1e8cea1938886aa7cfaed313aec422094a3b14f9a7dce66d68d7a9e74652ae536f8a0cc3e6b8190a9eceb643e8a7d9a4366c2235383e784e9ff4b0769d6cf3c14343a2d898df1aafe9724", "53facae91a5e025e78c55c60d969d80629fcd8a6c599ddc8b1606bf57cbcfb1b365aec7f621fb214868e0d83b40a15e7b37d51ab1eb8996c805983efe703c36e0532933e1299d4a3f1acc33a317ddbfe6a503eb16aa5d628f4b9b4e78094b14ebe5cd25241a0cabf7aa8a38b3e013d00031ea5b7ef292af02d05298629a9a087b1594e1bbddbe52c6c90c3fdee9c468a309c1bb058817e7692bda50309f610123de3ee243c7a9cc2a9d0fb711c7f893a1376271dd1f889b60814a910c7c6959aa5b07dd3f7ad42d7a6055cb2c61c146397a904796add7cbe47b6f980c4bb2eddd5c7faac3644c312ee42ea05b292495223200335990d66985c60500d1630e45031564f8e5c95592bb6310b7152c5e24dc8f2cefc96dd259ff7eb6a7ac22f5c42eff799514f94aebb63c243afdcc126833867286fc8a62f340eb988e78cc5c23962965dadf85f5f18a189b9e19fd89206cca9d2ad2523c400d99c03e393bbe7fffcde83aaed48fb0ea44a495e85a738e438eda279e409af7d68f71c33baf5c897d529f7ce4b19759d864f3fe5ebf221ecdf3230d27a3a7415f6e6a60b47f73a3761c70da501ec20b414e3dee13ff29a9c3ad2776a5760ba4632da4c2bf513c49f7895b0b021f0807e7946f3edce47cba07a20aeccb31724d3e50ccfefa78c8c23aae99d8f53e2eb29e2d83a72c0a61d5fd251a23b64b2a5cf34484722c7228fbd", "1", .None}, + {.Gcd, "56bc480386ff1fff5cb14bfdf12dafdd7c9ee8da97837a55624bb7cbc70a2b086d9345e7a3b6458e19dc5aff9b15b81af1c99cc2b5d8127bb121f54407b3339476619897c2fb1b53db7c5bd26c7ab37a7dfaa599c03d7ea05e9123945e2afdd255091561ab806b65ee083f25be28ac9e0b3c97c23d0594b5ff90e941f2d8d520123cb912e3ff2a862df2804cf6770aeb490e4c49e629d62c1eefc973c1b55775cf0879d08fdb8920791c0b9ca97ea12887dc310de2da8b25bd13b5741f2d06f419c1917991e3c167a9a7faa829c7e2a67f5f2d3ab095fefac627adfa155b26f2ef802b15d07fe44a39cbc890d255062428c1d988045f2d6062cf8e7d1139aef2c4b5bdd3ec985331efaad14f0deac067b820d52e1db9f890af1ded61da1cca29fc33fb18b162dd8ca2ee61a86fbf69daf349145b635cd34d9c91c465e4e94a1967f2d7976ce89af71c112996324ae097ec837df08ce47837b098e69f6d6c3009c7b963d0e30e89d080e76f62be227cdab6bd82da0948f31bf7b1b69b42bf17b3ecf851128c4e6c8219f1f6dad821d84294bcfbf968ce25ceead96db584ef558014c837c1b9479aa5b9cf4390e07f913d8494344cbf01162a314722ed24115fae0c49b1969851f0ea60877d9a8b7b06f90269d93e82fb0289487ffd335aebc47c36153bc274feb29518871115efb798aaaf120dd74e3c65735465cf8253d4f6f9", "9f6afec994719e423f369825c3ad6f26997f8bb2532242be786964b6dd9c08c6389568027afc62f295c34e8c471b925de115b0802283689c5e598811fbac3e888f6272407742f4657999439e7769d76343387b188f8f90721e7495f4a7a892bee7459e5e1fa96221545ccf7e203e335b9b3540717421b63bcba91928c5e26814b3add9f2ab80a64a4884620d2a9082b80a3c05cfd9094dcc4f7f5cac8e616110694e7cd848e538687024b9847e168c7c4f196d26678425d1ec8e26f9257921b3d0952918e0d339308e518548ab22543207d6cff924d1247bc58f5b5d871ad0486b49f632664d4ae29503e85f4ebcf240bad5c9dee7badfbc350b943367949896513e0ff44de1a353da7c60093f7faa780c14dc69ebf49ec094186581f35e51121d02ae8655b4be0d5ece48cdbcb2ac9252a2ea4d1c3f9b4f8a51910552b1e424a8c037ec2a944056bae74b993fa589a9f8a8aa3f50a558fd099381a46a0679ba5a4248fbc2ac30371b31af544d309da98f0ac4757afdfb1ce85b68fcbc877db98b29c7fb5939edbb7e8b874d39ec9e93f0d7762f7bd8bd9d5fcf89d9eedd2ee4d5ee4caecd165caee3b2fbda27fd429bc83c571e5b7fa51f11092c6f66f477b1c3c34552d3f602a0f85e14b36d657e3fd2c138705d0df3263b6e30822dee4b61b8e60d91c09036f7b67638c039c145c1ee723ec54b27a9929be9de0cd4f88bfc", "1", .None}, + {.Gcd, "-300d2353ab824cdec8ee64eba1f963e0c06a58e9bebed947358d1e0ab10b33af001b0829b17192fb0eefb07f9114f78a964b7da5cfc42d3bd64e1c48d52c204601820043f9fa967ad4a41c07e6078fa2074a5676443de1cb4e27bacc78cb6af6043af507f3700627dcfa79ffe28ff465e274b0f5118113cbd69806a676b4fdfb59dfc3906c1eeba1b7ddbfaaf911d6628b7f9a2e303e685817c4117c6251de9fb534ec7f948d4ac3b260ca46792ce46cc66e41c35953e1a4d2aa54555829fa08b635bbd4c538c20d86bcd1575cac63a28047f97eba96c74dca7542f2fda8b633e9e42e48f4acb3e8fd4bf7ea9449d4b8233135ea73b69a0751fa0d38488d7890503803d62a1ef0bc40d15516343b3905eaf1e6165816f5bf117af59c0077739fa67c27525b89a2e59404c915d1cf839467ab9364af55474e3b3c77cb30a6635a1f77d290855684ddf41407c67bda31a400bbc5fb99c776ee8db3826ed2a40a6341a9ba794dace26c0cadb62a32caae5a23cd66006eed14310d6659c0238ba6a41b65262703db2353181e2f82105d391b9f59fe9a708b8180d4fee03eea704f816be6e3f40025c030b6987ad209dff7a44931cc9b40f6c9ab3075635570c30ee1018731113b4188c9fa8cb3d006e70bcb2699101f15b6c97ac13b13492eb00c488ae3bb0f918db4a533f2d24415a98fef6633975adeee91a0ee887e0e5f17ff3f", "a4ddeeb31caaa20c154c4f120fba4b48acb9abb46d8a855c5d635e9056a303947834bb683ee91249b31f015cbddeddd6634c657c5553b6dedce7d3c6dc7ce65a848bb89eb27a7aa5c72ec86bee4759f9ea14be30282e74466933e02f05540e9cd548ecdeeee31f3530d00dbf0eb46ac299399c9edfa5260ea3238f681ce64bd9ff1104a07d4bf2c10e471fd9d69940c8894b41946f131bd4dc6418fb5ea260c3f625f59ed3bb3bb07788c4a89d966c5e8bc0d2c993f0d5712ea5650ca315aabad00d3f4c4496d082909bb73f694d5cb9210f4d836b89da79373903bfd344db3b0ffc1caa138cebe9ca88bfa05db7adc55426099c6dd215d6b4488d1f7083bb54b18482325c98c69aaeb644c650f13d81e7e189d8fc5ece97826992858df863c60b5225d7866350adee61b96993ff183bffb3b39caa066edc829c1bee2af84b164f2a4c2adc51b632cb1a6856ae4fbc8f5c288630cbeacddebd8bad3e087d808755dce2936976baf9a814ba02278924312ed419f24d1a27ddfc2f753c090192aed28344ad13d8e379209c530303f508923fa869a37d6489f080af5bce7b94646133eaac33c00009fbe2fb459472cf3f10f84f9eba86a653c7a36fc947f035a134e08293e624c71a3d3a15cf418de67e4a3e3dc5742030ff18bbda451e1006a5d13b6c1ada1cf0a3b98b369f3f685c34ee3987e3f12985f022121a4835f69cb9e8", "1", .None}, + {.Gcd, "2fe81ef712751659535b9bd4429454e14c2515c45e039cf5bfa65d2511e832b17f96ce3fa9ea2945e6a3ef83b0ad4e06764966fc905b0d7d0952b071d3ff84af9f8dc22523f8926f0f668ba68a127e46a9c849279cdf5826f8f1b18cccfb44d0bd71e2559ee87d660a0b39a9379f7fa82d256c369b7478c62a9b098c23c02aa39ffb650fc06e3e07a0d453819bb4dfba1aaa3b6dea5710c4f3ede6ff35469e0e4eb2a23cacca96821ae87315966d2d12aeb912edc93846ea79b6728e01809f5f9bd90b4f28eccfc15778dff714d1f55b93f6a9abeddb30646c42513220ce2418b1a71c589b5551a5a3cbe5b9b2d9b666411fa4a8135a4c2e9f6565be140f3627727db2213eff1c5c41bc98715813cc08895c79bba40aa620ef18cb3f8f5b6c874416303a973e5f542871caee582fc52343c2519c4e854d9d03ada803b03d81a74894bab124a191d609ec2b9f08e21838613c73fdb21b4d45a5d8eeedbb8b5fd57d7e26d96ab65656883f96670a4d6bcc9a8484ef09f3ab688fe9d2c0e81e057a187bb7e15e29cb28d15c4549d53a4c52c0e88a13cc46e9a0069ed90d639b1365561cd0db71132c31fca4aa11029c8740219bfe5d20e38c16088054068e28a7d4d8f5f1b8f6e6a26ce430edc36919ec6a2d9186cffdaf4fd1995afa5c7d6b51eb5f06779d12568f4605e8086478558ad0eff6949bc96c5af35d0cc75dad009d30", "583cd6a7331de2083db69c313383c390ff6c5c6c39fb0993afdcc1ef74a98803c1f7726331a335f08347e9d079e8d2f276b6bacbb500777c946ef2badc22d0acafe5fc7a7942d137e3d1482e37e6b16ced84d643efc0d07031d6b137b4a9a1c67af67c097fed56894913b747551cbdf82821879d05797ea902e4dfa10e9a7062f086e8c7b39eecd83cee70aa09676a215925ceb2573e3078b1f5e7c21f5f5529b9e709ecc4db0b689ec3e519e6294e7145b9831467db5cfa59a64290f4f5ab4a59663ec886432d1dabc1ae3f9ea755b865d6f23331d843f634a0e4872420932403bd8485f23fc239e3734ebb83b65426ad9ca85cdab93ad6aff9f81aebc7cc7627f7713912d075ae61b3efa09f11414dcc7efefbf6b54f07a03fb5823a921c9d024419808ae8c80f0ebd978e2f08ee00e56ec89005055bc9416e858538aa0a0a0d3f64265cc6539d7590faa6d919117bfb531d6beeeb6e832573bd05752fc63ba64f4b003e2d202a29fc1a5c7ebb447ea9010905b8ac7dae3cee80b2ed22453df80d20df19756516f58ed6511b43ee7229b450cc035be52ac537165b72638c77c07c494ad97cf44056566935b059e4d714f65dee91286a083ad6edc09591914cc54d4012d85ad6218b710af21760ece0ad37d91865953880610b75cd53bac04997bbc73e223afc93f750ed06d73204895393f8aa0c8c0bdbefd5d3c7b8a0f12c", "4", .None}, + {.Gcd, "b03118a5f7ebd1b2c1aa2aa56329aa537db780c13bb4e2161c196533290d772cf0acb3c9224e5935af77b554c28d23e4313806df54d06e3fb05a9e896352ce7690809a8abfa4b216f85993e06c57b832941429b497b717e43724ee579158afbe59a0c7c7c8fb95338bd31baa81897a821487b34094e6891ac2e9afa068b32c4da682140f24f2fbc1e29d10ae722e1dae12a7a0cab7e214cc17e6af615cab596cfc266016dddf26530dcddfc6a98b88e408c855591bc98eb4a55d4559f6c4da0438c8e2587e3273f2d5073e34d36c21cdd7d743906cdf85896297c15c9300d8dd531819d64c6a3acf000a5999e614210c16c054527aa1ef073186f205c5b868149471b4a34f59f035d4a3adc32bd7dd36fbff038d3fdd105c3681e669732c280d071097c7262d87a89b7868fd423b15b287a6ac9215ca55d73172d36b9479d83c6e526b6397f84d10b7753bb9449ac2e71fcc50676e4ad15765e8c76497a780a5f6ea9e015ed18bb5a136967df6c871245bec693a2c5b4035b68976b25ed0a59e9f9b5f0adc1adfd90d2dca10c7923bd010a4d987a8dc2990cce3e715a3145e480739c1ed3b4ae772068940dc5bf1c6f6323d159b78373b5f56fa60992212c91d814c828f48c3056e9c32ba3e604f3a9b4e042486b175f8f040cb9a0920f176c69c695ae2475d42da6a71498548b3216f6d5986b26b71d82dcddaa256f1fb6336", "8d470a3090e5ba8ecf18eaebff3684e1085853b55282c2a79b5423df925979822aff0e40c3e59132bf8949f3028ee174e6338bb9911ee75f055f4735462437624885b533188578e0a1d99f126291e632236315d682fa68a2e935d712d062a650dfe58d37b43fbb59b26fef732d08257f0fbc1ad49dea1bfd8dfd98204c458ce71dc8871e8c27093712adbc3aa7732e2af9212f5b1d4dd4a2dc1985c492d056c0c82f38427e1ab160b0f0955e916a20a5f40d7d2e71a06a4bd15e9b62977c08f06badb2b089d83d1789d0bf2f459e97289f2d4ed03f6781218e508f68fb997a5492d80978240481d42a6a59b3e9398ee256f7a0054115540702fc1f1b3f659f2f1d13b37a9e01549c7ebbbd0505b8f7516ae2a57a12fd89c84d3f308e4b35d726919fafbd17e3d922ab52dd79394a39d913a58c0e4e6dc133beb5d96e9d44dc21cec623eaceb06af29e286467d11b574f3d9d7eaa90a604f9af2f353448c355ea416ff224566882cf4b1991f6af5993dbc2cdc5893feea6e04041415bfd09db3d1a73968cc770ad7b1de1d258ce0d34540df2241a8cd02a2fd337aada1365761dbdcb0a7e9e80b8613823efc9ee34a723301ae8b18c188ccb1b0c68c83083a8f5024c415eca1659363e093fe7d9af43637918e5a87a781ba8e2dad6cd02869fd2baa07a50df87793ba8428fe9667adb844c87cfe26537af9e6f9143e7a4dbee9e", "2", .None}, + {.Gcd, "-b20421f6b3d36d5087ebdd753636a7902b0cce1e821da6aec4e5625336900574f2658ac4914e51e5e6875996ecb446c145418cace3bb72de313c6505f3f1e255fc9d2c059ac9f7b4501d251b960edefffef40b19e0e63bb044c88ccb0c7f217298cb4c08f9df550ffc983ffa5634b3d79118de21fddd1bdc1022975790768c2fbf2bbe798667159eb3ec83960d1a1ae904029ec1c5cab7a9bdb4c5accb0230499df638844dac0d29ddcac9f4e61827bee1a9fa74248167ff7452dae828bedffb1654727b55c8f766280a02ad728a6a346e171894d89c6d41bea0ffbedf61fc61b194ce772f81b493e2cbe93710358cac98e77ebb791306f178660ba005ce55c42521006c19d15b6fb3a8b869545111a4ff4f9ba55f068ed0f531e18de2810c1f83f9b6e22f63e8f800f746b006ddb60c6a1dc951ff0e0bb89a965c4bd7c01c016a4378b52c988f300d61156630db143ab277d11ed5bafce6578cc107004491a7d7f77cd4c539cc0f9bff906ad58c87cebb27da66ab7b0bd03ff5e183f180a78fd7975c6187dc8cc21462095a73d6976caccbb15757864031af81def9cf60a0bcd4386eaf9a7828933a76b7dc00ec3cfec11148636a30afe9c895c101b7fcc6add1ed2b743543583f7720d1618f1a8a13399cd2765c474d323e5a0d3a6add8c2e926fe3a3ac3fb56c3db7703776a2b5c823c1a2bd240da24e2b9d33003b349745", "47540d72b4a0f3e12e3d547dd2e7d7d771c4a142eb6097e8b5c38ac87d5f6e8e2d638c2d4be7e67234963a040f059955b386533e0f9d8f673552f895b286c638c99eb288ad3c642e8404471f1466490a0db67c7296a3348ee203f1be8e485203a6d49df2693a62a6c6bb40b16d61fe19160620a5e61f66d1ba285b0ba4a07feb6562891846042ab5915dec19c71d0111c6d284a1ea8eb71ca7954a4d86352042f2618143b419b7fafc5e1d7236a697f7c170b0c01dc2b8086cef7ccad09113b59fa14e148b69e4f41d5631b91772ecb7a18c62d0b6b732ba1ebf31483d4118cc46de500ecbc0829fbb722abdb424a2aa245c2af3ccf1fbb9fc285d99a7635fc9861fb42d5dd9787397b43026f6028911975111135f120f09c9ccc43b0d1396424496f86cd61d7b03000b99321c7532688eae9034b4a3629cf2c238706ba5010de03b046ba0ca66d96914fa5571852c88e377a771cbd35e87f4affaa1f6a0f3c134ebe5c2db8af5f67293819e11939048938f529610f9f46ee6790a545a776c62b51c838e12b2c1a569bc673d47880d16615edc4a5f6fd1a6e08c60804ec2d292472c56a54fcb11d50aad312b8218725e19d329563149a7372d9223e810ba0ef5bee00b379d2837d94af1229b3f5c31ba9dfb716e786395cc6a96a913b172df3069e1303e682f9b581cd20c13faaff3e7a37af90c327cac9050ef66c7ed7cf880", "9", .None}, + {.Gcd, "-10ce830a83645cb777c7da1ebf33ac6a662b954990df2b5289634308f5f1714f7b170cef31d7e1ac308286d3d2fa42c4d948f1d27c899a659b2a00fd3595d6dbf1b2607bb93fd44451e113c7d87658fa07be9edde811dda43bfd7c86a90976d200c99f3b2efc3bd7080d9f15429c537df02e8142034d230456fb39a5c13a9dac8808f834451385425c2045f69495a33efa0e0cca51a9fbe31659163a49d9eabd961b05e3e29f42264e6f5d69a2912c3b07e72b828603b7863b5816a090b3502e8a004ad4abc2df8ae1043deb370e4f841d92de947314c53a4fb1fbf132516b2b36b2d37a4555e9ce4a389b40f9a781c6818d30dd2207a572395a4e12630f22802e2ee01cd08a15d40aa16e77001425856134ff1f4826fe875aa82ae8a248437350b10e6ef1f465a9106c1d61a438bdae61f3babb9a35a1de5bbb0cac755cb2bb9a0722c231df2b7f0807f598004497a3b227b3b9edea8163f8a48cc6abcbe1a6b7177f1ae3d97f2a36977f51fa0bcf282d1036a84f3db991aa23322129351e5ea507ecb3884e661669e860ea561ae4fc65d58a5506ce36a9c5218d1048ed6b8f5399a712c335fa93e52d302f6a5230d6b45fd7b85379164ff7bcd4e073573738fba0051f649f534a895cbf18655d39fb1c1657647f22b9fd76fc1a8ffdfa22f96f3048ead39fb887f35cc1bce51fb751a902164c848be5d0d449defff6b15993", "562e509099b10fce4ac52f635e4d577891bb764ec4f71d438f152577c1ed732f544268ba6d862691d9d0149397f361c82758d919132ad885d10b8dc3339b35de3e3e7fa1550b1ea90d0be25cc821fd12b086a15fcc700115c0bd5b896343402b1c0b65529c1eab32e6dadd2cff77419634ceb3d70bec8ad231ee5c624eda7103e09178b42a43a61c90dd9543cd3b6c39818f0636a1853164a8862973ab98a5483ddec3942805a33a23294d7135fe2b03feda7125318b97be2dc73558cbf31ef834125c9a194cc0df64a13784b6c0fffb1fc7eafad4779a9b774654b36b51e58337098b3adf3aa40101855a1bc050f1abc4a322d12de05f9a1172484528463fc2692550cad69140cd2268b1e5fa3de8475ec0a5458f2dcf3f0e3b663499cea598664d2a0091f573ac0e9c1499eca807585ccf598b8b7a4cb26f26a3eff80e28615b1322aa6d497818be51bf8339e3b751b28dd2ca3b6ec5fa6c4522169ea3addc7ecd5c8bf9200ae8069b7d35c5c9fac7b5d080241652fc97fe5b4cfb4795ae0dab1dc2a8b05b40d43e81ad4ecc5b93e11c6bc7cc71986bb889b16a15a8624e690299710fa597316693cc5b4e1ebf89bc7f5f89a90af7d969152597e7c9c00214e8c53621ac5b1c53eba20c9e702a36ba6cd1b4a3dbf8ac1afc11dd698fea5b644310ef222b2df989081f9d90c5d158d0d2d3e42369fba7e86fba34a55df4f39f", "5", .None}, + {.Gcd, "e57fdaaf2fbd98296de09476ff7928e97a801fd207959a2ae83bb21cac1724e0915ff5944656425c60ba7e66c7aaa03da8e631dba896277f3c5807fc51a489aab2d5f92730ac66342e07c8e8adef6a8983346f8c30e69b1d3db18201ab7249fa8caafa1efac41ebb29528f5bac6df217f05d2e950abc5771e0dea8f7dbc3bafe9ec8d1cb710b5d4601b11a1ba13a4db4a9bc16ec59a5a487a93a86f7faa01ac0d8038e86c1507e7c35d0c66a503c8918e02e245bcbf69b6c854d5fe01a560650641ba0bfa4a9b092e7b86879a55863ec91be87b2681a7f0da9690db120e8abfee4441822fa06f380c14ed3f8d06f16878ce94a6cfb51810f82fb4e4eca1dccd3d7c2831e78b7eea09d248ad81455821aca9f0d82cf9c2788dec7a880a07e24367c1c716c8cc49e513abe6039217ab4f90ed2b3b14966b912c9202fdf2ae795f336205131f040dc0fab63348db2d5568ae3f5be2cd174261b126861aaaea85657fcf076ee95e4fa2000c631896c3106e6f87d40f3f2a2194d3a5a0c28fd662c6b341835eca62fdea83e54f592dd108298195e2a19935b1ca9b95ca5f750103eae10eed71517287d846fbd68fd93c39c86de2163da511b63023c1558e0ff57e21b1b17d0161bca9cafc87473d695a2c5c18c4dc8bc14624b9d53d74a275dfcc54d49b6db4f57162e18a594270db226a03855db1cc6deaacb42a47ba2cb084af1bc", "6a24468d697d217543c3a4ca490fd19928468903b5e681c06707597cd0a2ce9cb1c8c57ba3e31afc8aa29aa34ac0629a51a441ac56db10a73b3d71c296e69d515375aa9bf994488227764d24b45fbc90ca3e4835528536aa153526c68afc6bb45b6c0f1ac41de735008503d8a5bd33de030e77cfffdfc989aa9dbf92eae3d9b5cbd2e98ad1012735eadd38cd2e3938d033d1259ed99c984cedcfaa7a55d9a089749e03dcc61824d9c13e794427c97aa646a08b0a33ae94142e6be09d6e324ff057da2c763a110860eb8e3da66db8ed22070b976036d86055dbc28012dec9ec17b612a75da173b7b2aa759f36008b1ff179bebfa3ad30e0dd43cba647e4f9785b66c9a63f70072290c4828bcca6e5d5ca57496e5632ce2113a4f4a1f9e84c2185ae3883e8afeca589a2879059c31278468e92d234193ba90d304407f558b647cc1d5029eb76d698d947023ec2464e2b711213f5714e899559ab8777927ec9397f48916a3cf4ab91780f3f1daabd298e083388f2ddb745dc19ff481245bc44089434ce8e13b62e8393b4f929ebbdafe18d7a1b5caa978497a4c7fc5763bf3211adee27dfaf9d52af4d1ce659ce58965cba6f259f0953e2b47baf416483a447bc867e918b809875de18c6a2d1cd48de8b3c0b639343e06517e97da208db373d4c6a4e3308932a444feacfbeb7a502a868330dbc2665532f6535908b5c6e61189bb4", "4", .None}, + {.Gcd, "-b0f6ecc76bfd501e56ce363cfffdd9fef78136663b011fe3561db46a85ad186ec94bc9ae2b053aeee9abc21af22a4384307136f3abafd9e79bf5a60f8f4902f440bdcbb4bb1c9f6892e2c353295ab50c4317f53eecfd2d51292a3296c1207b90ec8894062d7e7a3d4be75867e1e622aea89ec13620902c7419095a2f573161e9aacd56cfd0cf8c0e8da47d6d346bce050b5dee1c30fed2c2bc3b7dc4977cbab0ac6c4f46ab9a16c6d84ae2123855dde037de1e6f15b1a4be49de7735473445559583c3046c27f9d2fbe5dbe3dbd8ce8c93f8c9a94b7d1c8ba4ac7b62d7cb7228532b68a927ccdbcdc624c22f6f4419759a35ce25ddc583fe02cff22b2bcd5bf0ab4c918c1e18b93d9e93923d262f352385c93581f55464919a4a9d5545a99aa18e0e4595494f3029d0217db93a66fc7b1df1ee7d5d1c0872cefaabab4fab0611be41f932779b18cedaf2b26a85175ff285658b73f587641299886189af4cdae2e2c5027347344f66aecf79c292b1d5191546403369fdf32f2238b12020ae3faad9495425915027aca71730b1c2b8e266187b91fabecd69e89b52b031588c9bf34b0db3640a8d765f81baa34693add23b519f607c2b09b4681ed68d48d5828b48e3a3596ca089a7efecfbe939aca8c07288e2b5b6c117ff209fc88a9a9cc7213ad1723d0544e0789b166ab932f066721d4edb7d42bbe036c72b0e70b375d1cc1c", "3e654e8ac7ae861c915dcf98d6071d93000df3dfd525787febc5828208e599df8863a69dec58a957650cd19bbf795388f1bd31b151aa2c34235572b174751171c4c7f45273a5b5076546fa4c25119ee93d907205a034cf2b6a508a771dbc027bb3077a341f309ca8546daabc6f2f56cda1039cf6ba15e0891a4796030ece0fce3a5b1d523994e929b4ca577e5a91a97f5599242641260a82af0974cd50b15a99808ab275573bc83d2494a8274cbb6797491e9ea2f52b4c9a0e21975679db12575fb96a99ef2da714bcaa5595bad528e7e778af9ac8b7af1d65becb4e716c72bb3e66c61d68cb712829637fb78ce8369bb97f0a26acd8cabd3b3ff062de296f17814245668b6b6ebf4f4baf66f5eb6e74c0936a296712a66eb641760f37234aa4ec7907ce5bfb302a35ef53a4ca04238e30ace72e026324b6a845f53716b374997c8ead2cf745e09d88953534192dd83f7ce6c9c4da9a3abd9b762d779f74a6938cb5b643db974476699ef9b30096ebc9d1c1dfb73876df56c3a45ad01a86609f8d8b96b1fc0febd3ab889417334bbade396643b60cfc3a79c6d4f6c6c5c986f5975b7cca6475f377e4923cadee4b3d318740a8296c5db28c81e5b5bd5c0cd53b54b47fde3e7dbc73598dd17517bcd375c2d6f8461724ad4b9d6c829d98ef8e457065439eb57a4ba56f106ccdb44dff4ec65a58ad8f7a9cb372a1b8a6e9ccd6ca", "2", .None}, + {.Gcd, "40db096d789febe63358817a2a5dd4da0bd348c77a7270904ca7b4bb354ad37eabcdc02b454dbb19701afac0fa82fcd1a0d75ac2fdb7e47fa41d9c50ee4002407812912894e31e22cd0bc5026f9bb670fa737fd1784a3095bf68fc14d04d266373025449c7e7bd3cb93408170a7dea4e299636a90ab415dc281b0bf785bcf1909a6333d647a58b03bfb7dbd63e55551267d1222fa640b6a510f305f67ce20574d61061021b86762eaeb0d4490223926269621a0309065561ffc58cf74f2abfa5cd099d9da8de827f1a57fb845715b78e5c709d58e2b177a4853ddea93d68eb54a14987f40092610fc87235649878053a286fdf77f8fa07d274809127da160481ec5226857dc028d19745da5a7d7cc1829c9198e7a72ee2e0f929c32f70ac97b46bd1fb9b6b8e7c808c520f1db735fbf5621eaee2eb05eca854c29fd9daddb86b08f076753483964b36717883256ae5006b39f88612cf7a6b4f558e89bea8839aba414dc0cef11e97f74034e5b3794ac839e278347ee40fe6f0ad7372400105d06f74a4e509bd7e13fb4b620dfbdae39369ce689ffcf295cf45eed5d946dbbb5060706accd644c574b3461164842272ac4e59291b73d2650bb23a704baec6c4e5b58d11ea1565d6bd3d997bb46fe5f7b7cca6c427e521cf68b215421bad0ce820ef426dede10482f3c203f2b1feae36e61557dd8559edaf41d5fcc013aff12647", "380f0e7227b9acbb3931c78fe8f9d51a11cc5ecc670b185c0b479aab4cbfb29f5b7215953ccac079effd10c67e02cd30a392672db5d129f27b4bce11d4fe439b152d662f035110350321cfdcf69b2568bc8c9ea18a00fcd3a10894c2007e74dd9dfebf6ed791575095b0576f43514da4dd74c2ff2803d1c21c081ab63c0e21761bc94bf5e998b248c2d644693238c3205f15cd3d4e733bb18e5bcf81b7cdfb60d312e97fb5246bbb594e1ebc2e4413f66c0ac2857759ef3b8a13a99e76f16db8435b3cbe04ebdc07c91b519fcfa6ba0aebd7a43e783d8df5f919b0b72d953ffc4c0519f11c1a230ba8e7a60237f2a1f28db2b21b9376c56ec4253c3e15e8cab671fde5323d5cfa2eac9c327bd18d9780da2b45bdfc68447e36367d1d3ecaccd6fa22ab83c4ee2f4de50c1770a1160d483cd0909fa13a09ccde3d40f41d424f08a728448c5c728b2dc6ebc739dc5a4c4919f67c07503ce9b9eaed081319c7f707a376943433cd05790947cef3f8a0d1d4cd831f4c3689becc818e7b6f964ee668dd2869e8ddb8dc3e78dda6277b92ae55f94cb9fd98ce916393569187b22639316a674edb6ea94220814b4e5a6cbb63b949b587d87429d426aee3b06c6d5021c24d0edb22184210de0165f8fa9ac192a32d68cad6c2d2f360fa7cc752bbbc2cda9b85770f5657389a6098204c4d4aebd7e64da89901ed9609e4dbf87a7f2cc3f1", "5", .None}, + {.Gcd, "-254cac9125c792f8e7c7fe6ff8d62eb6b8ab29f25e6889c96b588fa4915a2909a31129687791ac5d1c1d639e3e2e6336c4097649c72e5335babc263534e244bf845ac933ac8209fbed0744fc80ef39cf8e270b1b7ead9bacdf853d8974b7ef9c3095e9ba098a6e4de18bcfeb7d1cb08af2e7815965bb82f58fc658da57e4f52dcbf728e1b1c2e5a1a53c78d85f71a94aca5491bca3541c2abc59c3eeeaed66e9369e8d07f58c85d781fd1143daf984156ba135ccfbbdc42752ad9599fcb8ae3ba1f1d8c902a2aafc2180943cc7faee1aea793cdc37c25228a4663729a4d806786c2d7f1f34f76d01c501d815c52c83d368a3e0cecf9b3849295cbc12ba9728fb278c48357a05fb9099dbb85c2fbde1ae799a26c5ee852315e3fdfe7119c7e5fd025898dbe747680dfd9d0829fb543ab3266161b95f35f46d018a94fbd54644ee301c33a530b07b03fbc344c04c2b9c54e5ef1378a10c0e724414f342c1a6a46a1b16f95d95074e3aa75a5087fa9ac91df0f0f0f7f12b37991f963a2c3587fa176f5be244654d6f470c3c2f9ac629e165069c52476b3ba85d6838a87fb177e772ead8c12892f2172e551a658ac9e1879cb1e6c7512045d4f85353a5c22e0eca1ddf6c612eeffb37681f92523e9abc443962c1f20b712b32c546975ed9440e30c846499cd4308a737de9e3fc90b84f9609fa2c8d04fd2eefa27d968a3af7287866", "b66f5e1570595161bb8c506ce513b58c4b37a91dc941f44133e6de6f25c4159abbf57778d16e1b4b870a666bc9e2d04bf0786c9963cfe8c177567ff7d169090ca01f8de887937fdc5ef3ed380ce0c597d6f33edb87cc4e3c42135e9c7bbac69f8517cc0968c9416e527c2c251e323b8294d60af9cf5bcca99c5192d2600469cfe1f97b4fcf77fda10af1c560c1c8a53925cd0b54b0f3e6cfabe4733d3fdfa855d93d759bdfb2f9d3fcd7b005573755f3a21d7d14cd0b4a967a12fd71c97ebdbe3e520f858583e1b2f0fff5ff34f927357b4b025826d905c05ac2eccd254c2017cea95e262c3e35a27fd73fa5cdffece50174332ce0005f1a99b247d8ffa10fe4564bc120f45378b24758781623ec7d1e028054a309eca03e8ae35f1f8e01256659b3fc94365db6869ebfa61fc53a079bffc0e2b545813fb4b2dd94d8b6c99f3fb611e0af75ee37393d90f77e104a30c396c9ca55b384e12bdb2e44b3255dd76fd6c666f407eabd28ab67e3cc6ebe8f067b268a58a47643f89f2396eb547654f9a99876313e255aa84023ba0c5ccc0d5c8fb9f267fff6a03b670efc6e0a3d155ba2c0b46a091ce2f840c786462fc38934bb7b123fe9e095d86dcc602958605efad29d1f7c839a933bb17a0d804e499d2f25632cc8e8d3097731dbe2cad863bd9128e049b4268a41b96549a0ae815bb79140338640d473b9c023c6a9ca7c2ab2ea", "6", .None}, + {.Gcd, "-64467c06740df5daf08a21a340ee5fab8ffce38ddf994380c1f5b268ed4f4d70821cde9f51fd060e7df742fe8e4b01a0a3e5ee370039498aa535b61d4137e921dae6caed55c43efa0a03a9354cb59bf9220c6996f6dd2f8938c021bfede7e699d00229627baf46df59b77a412f4c5fec730b95ab406be82448ed4328901b0b571eabdfb00819427e19b0ecd31bd03f579947063be915760da328a9bc88691fc5ecb31142426b0e6aca7e4733faea34555d2216582493c5c432ac90445fbbfb93bcb83da5a0d13cff8f74f4c3efbfc3b8bb496055aa5719593dfd68f6963158e18c7081a450876988353855e228ee0480f32967cf630675876fd2d91ad061299ea2b43a7b276db5977d6f2376ae6150ca0fbcc1d1a3f146421085886e548a4ff81465474cd19d983d1d217b4c9b3cdccfbd521064f006f4c075993e54ed6976ba1681590a010c4d896d4b29be862495f33e32c4eb17c109949cca3cefa5012a1bf6d4670bfd453ee9eb731ad5b6f7bf9e27f555c732bed013e4dea75f935dc4303cd1170da84ce35643f91449f3084461a52393ab935da6ff316ed209d48ff4470be063823076311d00892946d6ceb3b93d7c4d399f418a73e3ba2ef70cef57c59603fc90297ef842d28a39ed914a7c2ee238a3fd86e1b8c704bb7a7c30e50abf871e4270939f7785ce71c9e24b651b0c523679f3dfb1e2af6b4f8bd1e7540c42", "8020335873d2f0de6190ef5337209ea176118e63823ac09cc800833d975a5123d4327974e6efc2d21f1407e7460b5c30fadadb269afc7ea5a9cac0a132a6b4cd8456e623db8faa3b0ec25dc6f1744550ad33b7922ab083ef3f1e4453e9452c3454229ce4a0852849ea646639ae063644ca528d89868ef5a3712e459768a9c12a9024c37ddb656dfc82300ffb4501eff0fa0d8426b4e130b4a6c7669089065a53508f4d4aebbac2de39281dfe7d61fc8b0e07d4ebbebc2ed0b408d255948d9c6c02403f5398543d9be3e26392cfb8ed82d20956260ae6a4a470a8bfaa460e83f21e11fbea5e93842cc5034fc1d356883b36297237dd19635b2e338401607c7a5af9159b07a66fd6c2baa72a92ff7ea42f2e8afb7558f7427a5d8d5afa2f7ce08a5bd61543b8ff4ff9e7ca48c9aa3a08a482b7df06ac719261a7566bd4315d63ffc6c7d2757eb98aa2d0592a404a8b3f6179bbb85d672338e6f8cbd4adc5c89ad3a54dbbb79705630bb72187c51d70b9a9cfc022b65a247e2e2516588e9838014dd3d99d0875778a25bcd10cd5a2485746511117af739e4dfb76cfba009b2858b6b6311d294c9eaf85f5fb846049b7fb38b784b9115fac611e0b7e6bcb2aebf2e11c833fe991750794d1df4c408885fa2f87995c513e72f6f0ec35f08e514a0b04b52723b36474f7458aa660ced7da9c502456376e40c7bdf5e6d772fdceaf7bb1", "1", .None}, + {.Gcd, "f0f54e81481e54a34d806e36e277ffed44cb49a0dcbea822b1294c5ce2593e2bcba40c56da3871d7bbcadc292e9ae08e7f0d4a4eb730eb4c645d886af6367ad7dd11bacc8d905071ce7dc3f4b3240c027320389157c545f97fa04da7347036c0a58429b4373584c5b06a3aab165f88281b3876543e10227efd751a931e72fed98660ecd92e0d2d40b6ab464f31da16ec8880942ef596153388cb4ed999ad70a39f45c3f3123105c269a792c2ee11a12ff00a4629690fd35465fdbd2990b225410b25dd74635b35781579c5a61e9d11b38a9df0623b58093d454b0d58644ddeef59fdd6308cd8c9502d878ffce5003365c25c4c3079dde8d4fbc6c0a9f5dadb9d017a6accf98df640518ec59affd1a60cc33910263337d0314403fbfcc0ce5ac6bac1d45396263998bdad12cb41f9fff8149fa25273fef795632ea7adb8862ae5569ef3542d4df247f0fcf1ac52ad9c52b422e0e3b76ec8bcbb5cf06f3b2462c9436514f488a01288a480b956b26419971c1bbf1c89d2a3014c6b0a3662f7d00b19cb286ac9014f9bb975d69b69129e633c7e37e55fb7fe37246dd483c632f40360470ad48fd8ee31c6b0681d58ccfef8494ea8194037779e23dfbb269721c545aa13b3600b69a7949ee4923400f3cf99c5bba7b38180bf7e731be10451cf3f68ccf3edfbdeb10daeea7700eef24bf3373399a38919c24f415b6c35e969722fcc", "f7faa695284af51ceba7099cfb702595a5fd69989f515ebac8fb0eb3135f98bd512379866d31bd4e2b77d90e089fa95b75be6829158da0f6f236784132a961bda788f19311ac72260e05b6857ce14a6c6d97a48e3fbbf6c66d930d24193213a7ce5b562c14109eb2b42cc867c0f9424504b5abbacac1e03372f24a120950ff1a7bb6ae070e00e171e76224675dd3f7223686e0b4a1bd1ea6318b71b590bc8a01c4fa000c2746cafc1c9c39c69cc8ce0b6e3ea18f69e4bad49de5d80b9c3c1e71b2d4e0aef9b2583855c9b1df18d2e11dd08fa5bc8783cb89d43a3f38efa4576bf792b5534e6b7fec6e275cf79ac680cf03132743e6ae3c26e67bb4ed5f84b6d202255f2cd123e3badb30ea754a144c12ca27ecabbf7bd84480ecf4129ee927b1c28808cfd0348bc0401a69257f82abbb3f75c3bf1cc0a1be70c77b2df2be6ff770a8ac7e1d6d0f11825a4ffcd5ae355b19c58af88bdda0bce207c80bfb7d10e7cc79c930125f0b0934f0d24dac5f521514d840f1644ed5232abfc2cb760f0afb438a5eb9a46aacdd62b6d61bd61becbf988e0f3c4c99c1d34fffe1dcf4f146e31fe01c0104626e1b93c29b5954a177cd2426dc66a61d79834ed794a2c1adbdcaa7a51b9f72fcfd80eb9dedf1c420c5382a94b48d9503bffac97c391021a704405cf85963d83bcae0d391d94aea2ad5a789ef1af21188939358a00038462803fd", "5", .None}, + {.Gcd, "19cc84e6d1a393cdc4ad79303dc73fe1f27eb6c29ba4f52764330b5c60f4eae23a282f75d65cb9eed7969536c89db3e981cb4f10dc6515715ffecded521eaf7e70779e232a5e627fd7a5649001fb7cfd060b8092ce87e4c8d33d0324d1e056d1b8711dca93bbec2506fbaa5caa15625ec128b40413a21933e34690f1ede0f2676dbc6844b6e279ca9f7925b72b42784d166606d088a4b38ddcdb7df1d0faddcdeff53dc4935f626adb20f8675a8f701a244385b631786ce255625818e25122fae91eb98f71472fd66711c68872de1fd0aaff68490ee8b1ba4a2fc9ae9e4d821c8ec340667a66533dcdcfd29b7458fee03630f5b060414811f89e948533505b20fc1b72594ef864e8584b1dfd4de7f47f357d29dbb339b182e95971514f5da034caa4f8f7b8087f1a57ed9dfa2d3d543fb3cd67cda6846551423b80493e806eaa100ba22c61eff63f959acd32ee76bad8d11438bf824d19c96c454a27869fb884e3768ec2f7ef11e2d209a5d674a2ec37abf91786e9664003c69c0181cc2edd932226fdeeb88c740ba4282c5242a99f7a25aaa077d98c52b63302f4dfdb1ed065f7da856879e28b2631c82366b2cc8b2c6629907386354b5a1c25b273333aff9867c0d457204e5c4a815f638964ccd24793d9c1792507532ffbd6d84a7f7659eea200e2b8961b91a3e1a5babaea1319a6709c922c22734505d2e2ee3f6888e087", "8c2c802d299eae4998ba743e2baaa294355dc04b9f2be963ef283b367f51c24f751a9f0add5cc531d4df1a00912e9644381cfa14a330bfe4fcd2fd74db30fa2412b45ea646c7a3dc5d4f6ba3afbd1bdbb079f141c84fdd6b2a2589e5a72986286c5bdd829e2adfedf2c2a5c8878d14ed91842157787a4eedcfaf197de33469d9435bdf131dd21298f6c16603c1b52dba508101c18428e011aa1e8820d868c8ca3a7719667f6495e93103dff21a330833a02c91432a8f82848ed74611cd28912f40795340f295e8216779609f4facae33e617ec3bf5ee25b7427cc78a3f65513786edaa6f9478be1e8bf979ef01de0f1d520737381cec24c58dc66b3e9cb65cd09011a20f45acde97ea60c04c520a9b9460282a97cd15edf47461636f01b1207f0e2d4b69f8e1eb434405fab775205c9ae23585e36ada4137f6c0bb0c8dfc0b0c3a81c318c40075ba4bbec38beb093bb27cb4c21d76062fb4c5fba72a32092d64af7fd12e96253ba33f26dee7924143e1e21f2ad224ba034950076683599d80d7d537164a18e1b6731c2f1ebc32445ad2db58885daa921c0ff12cc282db58682d5dff2952feb6bbb4e0dda143285bb0cd27d04888208b03f9d6c7a02cc24ca1bb6a26327c2b6f1e8e60fc3f10a5854f83f5362c6cfbc6b87b7f9c9529e51549308273465ecda222e0113a841e45a8d82881718bd70c9bdb2f6df8a45af74a4abd", "1", .None}, + {.Gcd, "-9e268bcca77e99b8d7fe5ca1bd49cd99852bfd2878c680f77360acd6b5977513dce9c8c6230a3a4252f312dd4dca0dbaaf8a83015ffefff50c2b58ebe95950249d91c01608b7c1ab4004eb2570f51307f7d618f1616d61bffb7959a223c1856734e300fc35c4158e9e27e7c94e37400d59c072d656d62ad595912517eb87dd2ebd27b6ae89a7d2087d78fb6023a4d6a36c3049e9b78d013f4242bc8e8ca3aa15ecd3d7b50aa56f00be8881277439ef306241963fa01346fa2b6e0d8df4d79218354c43dcb8fb7b1411e5cdb85c95a0339c0ae24129dbd52d5ec898314c287087c37635498eba326bf8fe234a151040c3d6ec72aafe876d3ef6fd870132f872afb92b6380258fd702cb1c5e2036a450057aa23ac8de02b694a7a0323a45e23a39154c4049618e1419e199f4f221f3d54609e1f39f3c78d129e0e18619de3b51baada4bc01ffe37f8625e781c50cac6aeec5f38217bb27cf612d5b637d51d10921ee3458222e9f21abab129d788f06eab65830f4e76da5ce845c2c175356bda1fef5653ba0aa6b393aa14a5b8b83be5618581805bab9f9b557c5712ce6fd7f861a361851ddb193d51780b9bb91b32246ad73da1fa61608c87146faaac67f4d4473e018a7c6f6bde71728714063b028db9d4131654d4dfcc556199aec1b600afda550c8d9026c0954fbc84050e540686e1468785b71efdf24c093ddc95d76568a4a", "4ca26006ddec15d25dde93939829664889ff62a83c47c600cb4f99fbba6d726283576a06b551e03597685dc78a5dc63bbf3254643e24555c1665f79cb0b0aebb19672972f10e1d28c38f6b5b68c212f09ac1149c523c19ca5d9b28b190c530458278716bdb6255272423ea82f7a2a039f8faf37a4cdae825b6d1311b23773bf68eab4d3d30ad9d8f9ea82ee577825d2cdf3dbf008767a1a87020c972ed627444eb95cf1c293ff2779d6d328c8988677de96cdb1b05c6ce380ff2957c17416e1299eee4029ca6aa7f3c1e30725d356afdefff5513fca50482b058c546cb35d0504a3b99d3e43cd55308d02bd5089100e59d8d2472fd090c15cac34626d01b4e28f25ea2c4bea6f6359486359998a26ec9cf4858607f0e3b0a8f83f9491c253e7b771ceefce05d2d248e78343c477452544bf14e13fd2c4d88d588c6e339ee889ef81c11986a277e772d2abcdfdddd36cf40d6b5e77eb79a519a72167ee5617b29478f7d27a4d0b4d29591c7dbe1c6d5c33f37b4a8b9d0df9ea6aec932c0c900aaa1938bae4c972e423bda3fb314400e22a180cbc262864d580a1b0234b5a7ef74244dd534e5638a0fb35d5d99feddd3fd1c1dd026e8868574f6ac25b6899a5469613d98af361e936fd89eae28189f7a09ed288af36878aed524bc347f08ee5cc642361c375a5b822d23ababeaf4ea63ae99a7345c43c2003985524e6f155eae0e", "2", .None}, + {.Gcd, "d89c6680fee017d0f1596eb31186e59d0a6c06f9b98205d9163353f8959ebd43c168afe586b4632a10d498096a764c200eda4a1f3d04c5b6304aa9194fe3745c7b3e8fc23fff84c099591af9f38b6e1454d306749815e1fccb4e6c425cc5d7302b53fdb2c5596e67fc873ba58d35ad679fccf14f2905f0a3c90efc647ba1c21bed4b88eb1e90aaf5e1436194d932ce036a9d2c58d8a656694372ca663044acfed18b1d1ea6b23169f2eec3cc84566fbdd28fba6a99de31bfcd51056d15a48606d33fffeaebcd849efd784e2ccfb2b5ba8a0d54103e0542c0059c2d1b52d07fc248cfc11911c865a6d2a102c25e22b6810048f3da0b6b28790452532326686c866760dc0dd32a7d99b3dae1f87c64bb6e4c891bc6a5a6134d0ae828694aeebfc41421a4793f908d3890510593e3de67f5b6dca97184367ba19e7c8efb74b4d45bdda89c7cb2b0344d77894f8de68cf533a8e13d2ac0fb09c11f47e38111c1586dc3336210099f7490a26ac1b78c42dc928d72e529ab22295684861f9e191aea75ca483633f3c45c139ac6a2cd5096bb35960d70f91a612d74c5573675abeeba143a3607e28f5ffe05fd6d4eda2e4a37f9af09e7fa0884d5f261864edcc165ee9841d347dcc0d17d4dc57cd88d1bcec12d19fe2076536f4433c632fc543664f5393f6ed0e4e89eb27cf59c44a6a05954fd61df5429cbeb516bf384baf036828b75", "f5ec8be8991974b016bc792c530a006c44cbc2739828c877a3a0ba885eb0f691e334498fa2078ee860bb06542ae6e84256d1db585e172be93b32ff3ac93c62909e2234cb5c82878c4217696a1342c57d7eff3311894f219b35fcb5bb9435c0e92f39f653441e16470bcd839877e715cc74bb34a6dc4181c7773bcb148a01bf7249d93fdee0af55b8a199cd0a6ac5d92a166cd2ad8fc4adfb03f8ce58c9b51e464383f64934396fbb55e2b9610f5f3267fc927ec7325a00e9e2ba798bf22df9fe557c6e22e78573322cdfa3ea095d4ec035fa393cea01ba3bc5a575df128168ccbdb90b06a7cfc37a6c690a3427dc9a2d753175d34bd6bc3c74d22f57b387ec8f89ce82346e71a7a94e2b091c6ae7b1e171ef34a67a3b2332294786d971a7eb959277f61961d7db908a61def2c5f73034cc5139ebd2cf238e064314078665ff6e03c1560e65afd1de905c84cd7631d0923c0a074a6262de4686d2e6f35139b60dc8252222a5dbcddf96ffad74f1d822b911c64a1fff1e8a0deee0152a72523ae7dd001ced0fbb0b2b58b5fa1898bdaa6640d6fbed9352854f993bce908caff4c341b3a23137184a58a8c29cd958a82ccbf62cf150ff840ca9911372846658d8b397fe96d55f59b9487933b94c74457a82c170e5e680827a9038b1aea5ad33d7a15ad9d5eab57db49e5e9088e2dc98f5a281baa24c64fe3392254db69166bbf063", "1", .None}, + {.Gcd, "-d91a3926a2f6f492bb68db18e633d706c513de7ad05557a58b9c3bdda6e2e191bcc9dc503d1e3e3115a2022606e916bdf6d30f87421a3cc99bfc74082261de1faad6236c285b57633b953d17e69d94993482fc5abc55d63f3080f67c759139b4c3f99db4ffaf2bd902dff6c07748921baaf99fd9ce643b9b22a2de5c486125331bc14a22e1df3fb217c5480ecb244fb3c929d8a7ea826e8c37c540ee998dcf363daa8e7baf2f0c9ab9d5c2b709d94dd8da754f914e364199f1aa00da9b2d1260c4a88ec7b59416355f8a5c9eb1e784d23a3255a54b6645ba217b0b72a2c23950b089d79b063e25c0aa37f914c7b75ebce0161034754d4e33d4ad598c80d011ebc2629c70ccfdd1c0c5e4840fa5f71296cbb35af9501aede86e0845af12a8d1b09bf90d12af8b9cbd97a5d912619efad04156a3fdf83b0eef7ee91748e2a5d9c5ae54b266602668edf5b28d599b04f4e0085c0b68822fe6e37119465da8cfcdb05565fb9931928f072e691c43c40219a465507a3f9f9be2a2fdbd539c2f7484c380c2f003b34613f65d1d118c23959d96270fc5c951bc678952caf1ad0b9fcbd3bc56aef481173be1fa1d98182c3375ecee69029726ced32d000ef442c38072f5178745691af1d9ff6393cd094782c6773f2c3d680aa52ef76ec923a69b0e3d1f823d3fd5a6516394bafb70e97f0bfa389e1c3ed713681fef03ecc56d74e6c00b", "8badfd16de70469dca9fecaf0159213d8f27d8e7b845f944322c289d8bae659240e282a11cd45c059cea1b2c03e9e4d527eef9a2aea6c1fc7dbef0c30ead4e241a0e57edcefbc784c00b6e7222d76406ddb86a6ea149a949eec419079d2f2a594d69fc112e16ebd7b7bdd2c1eaeec1858ecb0366876a157da9a7e2222e3ddbfdc0c5af06ec6a28d0c697ffed3604a0909ea9fb1fe89c90959135cd0370c11b10a395ef62d5644acf1055220a24815b38ab6a043eae6f749337d91d2573722c6ce84b4b9b04004f31b02eb05ca37e3ac3a5814b696e2aaf93a45f24a7df225ef5562207326a948d100b450feb8b134afe23e2b0a8c6e092fd914f7d86f489cbdbd59cc7210639b4c6ad9c1bdbe3c7b58c0374a088188a902a1d69290d96ef3e79a4575fa31de12f6034072076e7805266756ec2ad9e0241c63609c77ce5cd7c13f187692325e0b523f94a192e3f4289390b628bbf7594c3a765e1d04aeb627c0da945fe1ea8454ab77611447b89bf66cc7d9e98be5b5e11552aad9083d2791bcc21480894c4537a4f4fcf3c65f68fb6bdbe3380e81e1c8e0f4cfb41eabf3f7d45b642a1d62076cbd71c1ed11baf4d135942043b2dd96e170d2b57847360d57600599ec115cbff6ee80c33d87e77d722d6725cb52623c53e4be3c711bcd5c12fac1717215c24db4209e7c242250475801d52e4d7be5057a4f543c66454a1be1c98", "1", .None}, + {.Gcd, "-5f9b4fda44170d48e071f9a728550ffe035b1762b34d5604a8d728f5be30ee3ab798d05f260e7376b61c8d59be4c4cffb6af404664e31ea9f4706d56157d316e6acf48f1a4bc24fd979e40c134c34b5f56fa1dcbfe15e607e7c557a8e152f2d9a186787c7b69a94427de9310f59307fa61c9fde7b6ab11ca11e7af2d5459c2ff3fe11a859013188fda29718666bfac44d1caa073970e9e067da4bb343a8d508f9ea9f4c01337372fb6f0461f2ec73d2eef30ba83ec1091cb8301b0ecc82e661b4c1b8c9b3f191502f3f829dce78533e184e173189cd8fdee6e9d4ad4e4f3990cfeb284f901c41f78ba95c903033922e4893886147915a759be4e2f2e330d258a905d40587a8f130c2a3fa4ab21c46d7e7db6a39739019e4541cace1dc95862381c857516686ebe0e913fb3c76f83c46139b67df90abc5ffe60f53482fb40168fc3c3f52cd0934eff20c1c87ce8f54b18fa9119f49fba387ed7f762fbac82ad5f23d9ae58d4e6a1581012e21c72e80b8ef4c827284e55835a18879c0077e5467a4e613e816c430c8206d532f716778781ec43f783146e19491dd9f6753af8ccb666647c0412095efb7450fb7fd4626a66831fc2bdcc7ad83c7ebc6999b21d72deba965f46d1aa9fcafaa09c19609aa28f357ed6fb1b1f50f66f740c9422d9fd61b1b1434a36cec2e702875ceb40954d909023863d2ef8434a92cc392dc9ae3444", "ea07765f4e694823770e134dafbd3ac6a58bb51cd185d038525dc92dc62d06ac130fe5e859d03acd38d406d2216bcb9c7dbbd31e012ffdd72ad9c312685d1738e04e0db564e9aee322ce46ed17c5628fa5963fdc8a2fb7b8d24b8aed3d8977facdfc748c2afc70d2661e7fb76a29735ab20e81965d9f9c439a42007592ad69ae24b6e0463bf618e597b5cdd9bbbbc64c6788b7f7dd48f21f706df6b6f44d0a16865c550d746d694dc0b1a2434a34eadacf10065d7844f6aca50603129ed321802ba96a345fdcd7769ae396c417ab6ced359fd224308ade7d873afc5b324149df9227f91d3486c77c54a0918f205b6cc725e90a6e7842c7f1499097b465d3deadfd202a40412b2e8f94532205849bb9637300a480af87f6677a67d46da30ddca2a38165e423fb9cd6a4201687ffe8634fd9093c57c8bb8f3de462f95494c8286154d32e16e5099cf0fc69593bb540aa73f5d869aa3e4e27914f29333a157333e898d546deb62bacef86ad559702932db91bdbcc8aae80cbdf6f9ebb0bdc1c0e64c91efcd1db2af3ef5eb7ce13b6b47ab32b0ed165cc2fb1e2c95d4e0a2fb0476c93048f39aa09368a1a3b836d37649e9e6a58c89e07fc93ae946a4cee14b8e76cda5b4ac660faddb0b3615053ecd148a5b0e3b65e80bdb9a555b22187ce4d07a7386820946f8ec0fede154a51be2d86cfb85d1ed7935522453080d38139e43229", "1", .None}, + {.Gcd, "-9fdb71b378c8d52894e35462d64b17d714d1710dc17ae9f9c7a63c54c304d9184d97c088c541047ce05719a115dd009aeff7b0e383a94e4108edbb601c0d81ff833e8922c8f2ccc8e394cabb7e4a908202ae1f9a9faab713ef3b18aa75165e71b9964adeeabd8f03c53b7e0eaa52bac7c136dafc8eb2dc560a72670ae1fba1d344fa44047915225b4d52c5529a69eb725f13850727389b946c9eea0b7b9f9efc53c1b1b73819b66fd3e3fa97f46cc27b1faa1e0f90e07246c45ce6bb5a1da03d8311a78ec8a60e47c16fc4e288ae9bbe992157a594085b9186efc49c8f2323d3773d569fd40fef81dd65fb2ea919300b42c7fccd11c62c67d6a5067e32bf56c162514cf1b1159d3bdcc72875200ac49057f04b27a0e9641f98cc1bfc7962d210302d1b1d21269f5466881bb23122b602328de3a5ffb10976447bb428c410cd79fe3c03c4fdf5195ca9962bf1ef16c84a6115b6d57a00a4a6cc5a123cef4882688438617acf29c2a4c4691e4403ecdd975f4bbbc9842fec6683ef51164053f2c78810ae950fa3b58314b996ec21b9b1d8aff6574b3fc26fc17f2c32000ef01c850bf878dda24d48fc5d737dc3028b81319627766ab8d4eb946bc134091f462ed1477306e0dcde01f126321bca6c0a79be6020304c3f0dcc9eebb24f8b825d054563b090970c12fe578d7999dfbbbadffafd3212e3ede0a0ade914a0d252f36234", "e3522c06430e3d7cb4470fb9fb95df4316dfbdedb3f96ee4af007a6a7b4f51c93bd77ed6cffff13020c46f5489e85098643762db66a9e90ad0b653747d3c0a44adbe35f695f7a2c696cae4d44ea62358287cda7573c483dad7784f402d3572e5355d026e58539d058b8ca6c09784321c3279f0c4c08356e6abb0e5fde008388907fd471eb9420ccd3c59e459bebc1d2d05698227cd25e4795df8b107d76bf3e9aac58c395b3d56212f3cf082bb13a24c0d1d2f39c41726beace90a16abdbf277404dd91d0bf20a6a0c8b3bbcaafe1d9cfc41b94cbdab6f1f51183e45bec425c1873eae6a4b1ac30ecf15409db7dd6fefc523caae64d3e3255a1105ef3b7080005b0f7f5ba52389cc406193d921c96febc33883d614397e37200f782632823e22fa5acc8ab9fd64ec025ee3defe3aaf9b66574c6c4342da71d5c1718aa40ed99c09f0d76d21c6bf505e694f95f8433f873554e35d384036d54481a69f54997f1c82f9ecf2e66c9e0cf96664a72a66caacd88e331b6d6318916a364e51d85654b952296e83e361a1e68ce486040a2d861bc981aa6049c19b20410d29706ed470f37498c1b28efb72fc34dd31bbb538a7942b3f801effdf6724f7dcaa746d4e461a89645a2b9f1e6940fdab51de95752df775198ed0d66bf31184ab2a98ecbc1f55fe10ae4690163b577d0a9048d7ac104060a8f13ddc517d35748b6548db66db62", "2", .None}, + {.Gcd, "-8042f46d55e19590a14bbac24120e76d4f0b8b38bd50a28ce2213bb62a04b629cec53363839b8f1ecf2c0df47d7f24ffaea1af0bedc7eb8cc7acb6b9ad8f4dad27ecaf8c96b7521097c95b87f116924531939d5146447a3ac6dbc9c3ec8080250aa9454f2f09db0b197fa44c3c57c0e2ebcb2d6c8e877de0c260b5a025653ca9c839e8081bf20e4c79c4ea59df2dc35aa48f1aef3d8890709bcf1c0ef02c44a3330eb09103552ec5ea3cd39e32c668ce835743a641a28776d2e40790ed718a594acf64d35fda7cced45f905a55879e393f2fc29cb306d4c3443ff7b13b48f1fff523724bb6c694a358428726ac95d653c94f20d51645f5b971b75bf44d6182a3807b5662931f116f773481b2d2926aefc4b8029ce8b2f409c934b489647d6e39cd1dda17d45d05f8d8ae03484d67b635c9b77b587b22a91478b2ff90e45d44854ac270026086e4381cece3be4115406610a4001fa80171768d1ab769b281b5d6ecf1f4a11147ccaa44ea5635c4cf67086a149482d3da3b79a70fd035d3bbbdea8172c4c4417fe722cd96872f126f68ae51bcc96d019df89692058cf2b7cc550c9e94ab36f804e5cd95ecb126018395875f74e8e7a6ae7438d2f57c2a14350fb197b0c274d8875a801dbfd9cdd429fe7ec4dd636e9b6b296ec4eae3236e5891fb6865bb20233646f02be3ea77118d34c34071fc7bc7704c50878bac06ea578b08", "c88afa3514bd3da954929e27257305b2f95ec065b93847ec58f4e024378cb6506aaf4498d6b2e8d0b6f907dd3e0ade1ea079a0ff9d97714e613ea3418e1afd3080ca54b5d334a92f2694ed4a1b0ebd24166f7f3a40de707381dc80f8675edb9e18ccc3e68203194d5167e587b4047e907e037dc83c12d148aeb15a0ab7c056388352ee832bc286df6fadbd512ecc3d5988adf442c198e3dfad7d4028dbb8fd12651b382f8dea3f8dc52f9527a7e6e87f4cbfad019b8e374747208ae83c8fd1a26268698db54f8631cbe7f774906b9ec1ef3e26038980a02fa0fa1fe5531c44c72a9b7baf94c6114c32d43d4bafe2825486f4815bd8dbe8450578d6355b1bf21c91655e04b3edb34468515ba199e1c4c9a68e214711c031e8bb2f16c56b22436f81062ddc27be20838eef8bf4e7bda15317cfe1cd1264c1e5d985fcf76ffda020caa0805982e1eb63112f265abd526b2c75c34ca564406a34e6ad29223eacd095531e4fa62622d7b500bbe0e1d55529eba28bcfe4bf8404e865d4de09eae704271135f786e06a279ffb73ce5e050cf8f88dde059d8854ecc0759829547f65c48b57d674a66b6d436f15cacae17a927f5474559954332d5b8145db55b125059ebb54672b635c692eca0ee30807015a3a63d0baa10c21e15bcba0818f70056bfc85c426b393d7f7572abd9a720266befae621aee21471de29e6bf7e7e2df5089f7a", "2", .None}, + {.Gcd, "-24e41fc497d2f8553304a8f979af57b6bd5656ac67e0a745fca456b21e00b965d626157b323f43a8dd851fb7d79614d4a3698f7e135829f35c27d6a456e3ac7a2aab900379ee699bcf02207881ec048cb1b6f8b0bd801a0e27c9f9fc4c65ba01d35a897eeb494fd303cf5085695dcff55a8f1de7773300cbad34cfe42b26f79c2a95e156bed0b1bbb272f642841e01de0f1b57f8c1283e382261903af840b055e1c181e7642c9a7e101bc5e9d9b712c675b9d79b4ab3bcd470b8924f8b2cf445922a452436580ef60b825792ec90016f904725aa685bba7399c49b5e4ed44d82945fc173f68102b8c83b63f78f2cc9bf08b0f8a0d6bb177bbaf932b80e62c783296f091333fb5e8e2dd36cc61dd7e4d3030b646e78f39b007a5b6bf6f46b3bc028d9a6ba8cf732f7272d0a4fe1de6abe757b8ae3fc57efb7dbc79f05184f4b9f43da266337e8a49b94c9c8da2d057a44cdedc950b3ed53c221370aa9fbf1f2f05452116b1ae2a055976d55d51fcf7f8bd6bfdc5231da1f0de2557919993ce20aa141631a9251ebe8beae3cab58235cab6afb4728e422e2166a7cde8e4d0b84149574cd02f0f89acc57fd594b7cb830b1d27ff9bc1a644354dc9130717712ea825081829411a3fde0f3876234350252d04bcc01becc2cd77dc549e4926c68ccc961d931dbb66d558934f872a35cf80c4875ecb3e8fb7f6081eecac001474ca78", "97c0bf0d8dfe08c31704d0937cff094e309d46391057ebbb46e16e98eb045ff495d72d4e243e2d1b9c47ffa375d1eb92361144dc17d2f6a40191571c13af81b179fc2b439168080bd39341248b4626456769ce29b4c5bfbc2a699e3f45e6e3acb72f72d3f8e5ff25378d732d19ec2157bb16f1912b27e6c5e02c7df2bc42c013478e3779a0e52814bfb49f043cbd01ba21a6da07e027a01045a38aac47d98e131427cda83476eeee6e45f4dc1d571ed5d3644f3f1d7f7bcb8f2e6a7ecfda0b1bf318eff043fa2e7216d5aed1a74c241a3925f5e66136e9a9a3bf28bab98a08f32493addc483e6170ad2fd9c68b3960aef3137bc472281f74716efc70bf80e8521e86b2bcd804b011bdc054f503b4fe643e82205bbc73eba148f9ad6ab9a3b07602c0a665d110ff4f054352f44c62ac5167eb5dbc031716c8418bc55bdf8199f8caa7a91e0c03a97ede371a9de4d9c2b72bd4cd6cf5d2924244236034934fcc57bb9c0fe10bbec35ae3064540fd93dd1fcf8b9f29a1241ee8ae9b13430f669b2e5b32238251b70bd6ce44a90918f8e90ae8f4d1db3c0e3ef88bf53e4b113a1a76234a079e6eb2b12cca57cfbc88d9c25c6c4987693945a95949f690e77e3827c30015312b315a9fbc56c13308fb058e929c06dad036ed52431b939f84c6d68dd386da632feefe9e1482146b0656936bc31ed6bd9567a23accd8bf81b886c45e02", "2", .None}, + {.Gcd, "-89afd6fde0012308e775385c6e8d637fd2f28a13b845566b857be7d5b51cc839e3743508ad81ec6a8c09a3127e44cf48d4f0d656e45307c06dac6a76207d0ca4152de4c5c98707de9acc9f1c92375c44b25577cde34ddbfd4075b32f6696dfb93e48e64d7f3475ca62fda7ddab911abf0efa3730d4f752ef4f8c5ad177c66deaeaa4aab282dcdaffbd646cfc39314483ec430e6f0dd4a0d8699f697cc6fb3f265eb4702368a53a86956afb4af2470c6b1db19a36f278725836a3c35d04e59a941ac18b146f4a0b5a45414ef1ae56b9abf718477524a9b8ce106b477980eedec29123997e8bd4726a8b720c1ce9fd693894a9a0ac0699debb3bcee8eb285b21bd39a48d13fa619eb5435bd94955596d420429f0ef9c2744687fb5a91015f22abcb71602e6bbdf47917040e0c5b2a9447f487e9a9bb92d10f38aca4ad6e400299df208931fc821cae0896f12994916ea80e2ef889840b84f3f7097834ced536051c19dd614eb031f7c1a7e1a68d920b389fddaf4d2d24a5127d6691f8826ff861574b58171e4549517c60dab9953dbe9ab4ba3c154f5f7722a7b3b61846b418d1ed9d84b0f2eaebbf0273e41c24c94a047dcca23282c683c6f63aea0af7e1faa45cb34a91fd40195b2150df6713bdc9cfb351a5be62a997b689acb1da27d0ecbbe68265ab66fa7997400905a8d5d045858c8f7698107588981b83a3499c5bcb8ee", "1711fb6b6a8fb093c5e80e51445c3fe9650728ecb62a3eaa8fa6fae2e3ba225638c971f3b15e7bcab8ec5f352b4e21bc49f68e80f72762cc02dd02e078fa8393ad7dc41ee501c9cfa6b8ff89dc39a3f2ba559715b8f9225db7277d7d1de33ff438c62e0fd9a3244e35ec4ad712fc8db3d433cf10be8385af4b8b18973ee3e22f6416d4204829b4d2cf173200b0d58ef372ff6cd62570c9d2dabb0509e1751cde2c3669be0ed8861102fed4c08d6da30aa504db744f3e2b0c364b293b475e6c543e05c66f4cefc1c84a40517cfc25e8ef6c5e03fe928b2215d4363669e70d69ac1b257b5a34aac547d47af0fd444fe91b2553fa61497f452a4d398e4c896cd6a29d5f35a324c68103ab0ae919fb3e944c7d64d78678d186d00ec0dc808b044dbe4eebf1a2739326a6f86189683d2480343d5f6f4862a04d23359e3c3211459de11c2d5bf58ac7101fe1d3ac3d317d3ee92c12f51b691982f01c42c894cb822f8b40cc3f8e17a8914cac03b9a60e687f19ce74743995444db4ce9fcca3cc11fbbd91bf5d25e7566c841dc70a15ebdc66a7574ab3fe3d74528d9d17ea775074c07a32280ad46b74aff14a79ddc27badb1059078491b196d16da414959cd50cdad5165f6d45931c22daec5cad506f41217d1ea25dfc79f39a2077521b2a603d8b08d02d207fb775b14acdaf0ff2a66fbfecfdc2727d050b62a20032e3228c1ffef12", "2", .None}, + {.Gcd, "-c78113d6b07ec26ab6a1ce43049cad4484ab154cd00cf97f23d6662956882f7ff0702d6916acdafc764f6b47583cd33f75edca9a6f763c9334d3df7b3bc1b630378aeefdf32a2a23896772d1bc5a6a81196df6ec03903339f5c119a7e3277f2d37b9d981cdf324c86346fc996be5d0e62dcb881d9e5f0b53eb73e327d0f9c7879636256c417a6a45720cf960c080bfe2923f934888b3157936ed8df644adc6577ee9d89ffdcd07fcf27e7d7001229171af29c7ece94376a690ce9f6c305d0c0dd3324c88b93f8653067627c2133ec4e378fbb6c493dacbad212dca455757a8f6f230353b8fadf86a1124f612617f460fe5c972478fd87cd9ea8191e8c48384f0a8e15220c40a6a484f0c311b02bf822ac9a2f31a1f302ce85817587a65ab2b5e4eda68dfcf4b0f934950ae3b8dbb3b03b811dfdb2300dc625b588355e3f89299a73b64724a103759232906f51847303748887f5fb4e987c31bb458cca801dd68902076574db72091e6adc0a9846577390766b539b801574a63b991355a782055cf902ae675c4630f5371e86656e5688cbee2d6b9f0de3a61fbc05412ac9b4146e3797b8f7f0af5ce52c5d1b65316776d472cff977ed067326878410b23ce09f55aee6aded213117595313bd13b1c920ba20b5a391e5496a9bd8d812cdd72f598a6a7c0329b2580cbce528d192b378b121ef83b8abc2bf43b6b68dbccd7c537d", "7a386fd03ed7f8976e6cc865ca5572ae8523fea3ae510821b5fa1e6c328ef05d0aaac774d16cd89a622b71017a1337b93f4b135eab2bb712acad5de84f2af45ddf885dba878038f6a478d1e1a86b8b3af2af4843c5636a34689cf6be673ce0344adc0a1c3c3a3d75a46784ae0340f3874ed1d2f93c145b90975b76bda3024124de40ad394e765c9d60c24dc8baad832f6ecc938f973cb8b460942d21bd292bda553fab20b10d091983db592c731056027fa1c58f766f84b0b27a13c4d09fda854e1a0c3ebd3493c3280b471c79d3f1b895946e22000545470565a6f5631343a739022a99a0f8469916b63d785ad23745b5aefbb4c20586d65d1f69e5df2e559f727a1cc0f355d2e380cf69dc1f3eed5b5f6e8bf3f7c47ff4affcb3ff892d42c91a2271f6d91465610660fcbfbea5fbf034f1914105a37663a78126a1243a87fc9c16d2fc600d4a62e2c8886a0542a1258fab065743d08ba1ad9830ce125194967b541a40872f06267c0d53494a475a19a35c52bd959291afe7e1c2e035ed8212873416884ca20bfb19b6878a054daf419dc17561ea5ddbe15edcdf6bd680dac16852afb45aa165b589c2253965a52baf4cfa21ff575122f9ae892f9a4296f6e46311e703378b47807e60f22857ee621ea1da251252cda00476e5cba3e8da81fb7b446e5cde6d1623eb2a04f7338a0c0da49da5e378973d4b3a094f41900a374d", "1", .None}, + {.Gcd, "-e11cc4de4acb896648388d70529013781b8332cad0f49b1a9f534f50a7318d3df8553a864b65d5abb7e76db3cfaf5072c9c6d30cfac6c8fa2ce5dfca0eac89e38bdf2ba0a9070fe9aadbd171fd46b6ff7b74aa1a130ae9b1b5855fde537c77497e119076434e1400ca33cfca0d895e9cd5c3c70ecabf378121527ecd39426fb3fb892b6c0a30e5a1a3524175f5dafcc4b3bf161fb0705726fabd0330fe2b160e52947b8ef9d3cbc94d13452a6a0b29056c81a7e630826cedb757c597079556f9970c7625d9444d75685068cf8f0149e472a55b4f406f05879e331b2423edf2aa095e95f8ba9cc15408218165f905a94f479cf026ef6411c950e4cd51287f4e144fbf16a5844b66fbc1ad6bbd39a568be7a188ee652b1632de94da75ba73f663d32062b6154f7c79d650eb336cb5018b902befa634956f3b6ae6e265c5e7353a1e4fbb8db4f6f8a17d81ffe5bffe30c2f983879fc1e024015a44dcaa7b7deb2040bab3d2ba1af624abcc8a866aca7f3c6dec4221bc4b1ecac98c4e0ab0dbe72c7e9b4691d599e4f1a40ceadc8794d556ec3b844b8dec08633fec3aa85a951cd59d08b52c6f66ba26380c3b67faa3092711c9936636e49bfce9fd251e290e6fe528f32ee50bca30294d7c3fdd922a1da25788d1eb5160f65c0c9a755c898066557e74fdd5d6d9b94abe5237858f9fa24c1fba037ae8e07379eac92aa1f8d141df5", "3b7117b8b70f77a4a534e86b45086989685965489631c8430dfc9ee852e29f8d1be5e53df5bf1b21730125afdb477fa3fd1705502ad17a5de1e5dcf0ce0d78e555599bfddcc0607ce6a4df1455ed27e1cb33ace4c5518320b29f1c9e0fc01f151266e7061cf82d9476d1bd73a83196870210eb44eac25e866e809430ce54a622b5a43b77be9653edb79ba13db05171b6b3b18a06789634cc7bc954cc17a955bc714b575dcea7d65e94a2c36d48d9ff2fbaf3babaee7fd9c296689b69b6a793002d2f3937f193e0bc8f882025f5c58e119f428524ecb15fe3ebe8908debaac01940925526dd8df0bf68053a550a8862ea49d29f53aee5df6b08eb6c5444ce79db76e4561ca2ac272a3157a38fa1423a665116d1b56cf63dd3a78e603bf666d88fb23065b0be39d27b69aa1c77c93dde549495c6d2021b6c68c9b9f9f24ef0a08d07253b57a138991f2dcb4a087682f46347f3d2ae9c61df198442da2692fecd7ade8626b4529dfc14eca087d0e2df07dbaaf647eed86d42d026cc6c2ffa82fdf35bc018cf95475ef7ccbd6474fba19274f8044c622a85200980c73b6f21118bccd5521ac7a401aab58990e3482272800065d2c03b308c5d50c95e1133abb5bf5556c6efdb98910e76a562cc4097cace9d50d6027fff8b31496fb033a4fc4f203affecd389a6a11aa77eb5ec93ee3044c407f31c9de16d639db59d1ad4cc0ee478", "1", .None}, + {.Gcd, "-7c76aa8e1ba7e498a1f9aef271402efd4752488fe946cd0900548018740296d27312f6de5ca21044abc3805580f096624207a911aa9254472c7af0c84d06410d4fd770b1da9be2f7d47f3334783bd667ec630fc7c5e2e014aeea6c0c4d82d3d18f3e4570ae286f1c6aef01ae55ca230cd7bc2d3ced075d29d73cbadf49fb61212535d42f49b091f14a3e0de3e0ddb1212801b576323e376cba1388f2386d8e5b9714366e8305347fd8280593ab5ae89084c4fb9f25d69ce63dde7e668cc931229fa7bfc42ac5ae7caf83ffe7af69ce05a7c7c779e017f9b06b92b7a8197d0a3bdc3638b2837d4c3c4560af59fe21690a3a58421bac4a4336c2f893c173efc98390d832bac03956a9cfa058d2a211794afaddee9fc35809b2cd2202e205f52b122e7e8342357700198e16f8f545eda9c88d46370e0c7fa38b6a672faa9c480fa794b07e289b482074ddff4ef187efa8a1218b1677428c7741b4f8154044884552c7d06733807bfbf92f3e64011c8a3f80d007c222d6bb4142131352f033f6969d4c2c70b0d88d91763003a9164d437f11653f26ffe2163a6ffcf7eb3a395a4f011a1330591e8912368e8414350834d1b54b0642fb3cf881f7dc825cd22ae18f5925a0969c64761d709c3246d4b4a25e3a80e24c2fec071ce9b76f90a5abed6c1c72ce7c132b0175ae5479dfae3c5c7c6d285b82bf2b6738878fc4f7488886cf62", "36faf15c13749cd0c3dde2422adac90c4ee603aa011842fea914454b29f2e9377b75b951c8321d4d1d8a06d477543b250872520c565b218aa665935016fa3645f045b1cefd80ec12fd35f72b9fadd247b85c5b6e1e0f3f9fc417969ae26474644f9d1a51b68e2f08df79738ccb58ac1a6d5303b8f703cbb1960335ad75901d16d40d619adf189aaedf267f14a2508a73adb1f6bbd8bec3a991235a7c6a65db4ba90838b99065c65d4db2bc01c8bd27c7f4852ee59a3191fd0fbf238018d4c66600ddaf8337dec2483ef2e670bd00ae42650b912dfb739584b363cccefa298877533d398f0aad3de9b34c00742ce566c1592fec9a7297ff4d77c61c019faed3c8f0134cb2e9003e35e488b0ee626cb44a88da280ff4b727e421a0d84ce07b10bb3c7b802acb8c8c7a66ac8336e05b1d2d2af26c1ff2f55597e107e343abdb5541cfd85773eea6608aa61006dbb3e81302bd98c83f181d5c558504007ed7f55ec39168bf49d27dc20c3f6f7691f248d78cb931901798c754cef29961a65796c0ffd8f0ccc4bc22684816a0c8736dff2c5705b4da3506f6e9d069294a085d2b5221f9c97c87d074e7ee9421828c267d65d451f32205954fbf6eeb08c7286fa9ef093ba09f7076feb37e8ff3f5fc397f74c6e87ecfb973d7e19fe8c26dff70ac4679b154471fc441bb2f528891b1ff19d7846a2ab718a9ec2472ac3b53ba2c29d028", "e2", .None}, + {.Gcd, "2c6861c7ad778512403dcbd6ad24c468c24ff24def99dca8b387ba483c9a9a0a89eaf4bea5a88dfa7f529f2919af53770d1e3e277ec4285c17ad05d58c4a230f551c9012ad0f9ea9ecc231206519b6ba5f76754fe3d0c54bdee4a2faa4798e59c3bd62f332d714e11d0a12bd85b4e0c8baf002076b2ec5c91c80e5bb70c4b9b8870542a8a4f94d88946d258cab0e45647622bdfe1cbf3e09da5ec2ab1cd680936883593ad00d5679f2846eb3279a9738ec472b006b8aa7a11c68e209c07fee48710966355d051c4c767e86733423d6c4c7702b663fb4c0977a36eaa4279b61d1e8ed6f0fd204c6ffb914bfcb2006de63d2c41edfb58a47f91f403a0c1e377d5edc8b8036a4a859a0c69a375f26c3f8904b03e82cbe648bc779f2acf0802af7b59709cf81e03e8283f4189f05b3fc1ce5f169ef389431e57f6e9c51438c7795e3a849c4ea87633bd0f0296edc6265a3e7a3b0fd44102d849f2c24dfb1382678f6e0f241f8f14328f26b5978336150e1014884081acbc9f4edc1ebed6c1094b5d35e5f12458dccd229c677ebd9f667b559409f708d912675d0e11bf64f59c802ae6f9993d1c6b7f5fdf45a85773b9f8196931eef5a555894d8c348e11f39106e85381194d86643922954d845b27dc6b1939a91ae066e3fd5d19e4458928a420099f142d65fd476679f40a1d2f7d73288cbb7708b6a15e5f66a4640fcf83f66e690", "59ebbe8befc329dcb421b698176d236075142737e84ec3195877627b406f0a825662b2a545e7fe91c92c7752b1e82c1723cd576b8d1278ce38a2c65b5a7a93fd31d2d5cd8acfaad89938766a9ba0edc5849361aaf240926427bbde120160dbc169655ecf04f77ea3cc2eb3ad40bc7baeb95d35b60beb4271c8f712281b48196437cdd944224c4ae8389d2fdc5050cfc88f590d40c86404254e4125b12c58189b5a46946b4ece8b01bcfba21d679ce6ef931a17174b640bf517f7ab44567815a5028ba7deeeb946f27a3d3594d23ef18578efc4c3fa8c9c3f1c72dae5d1a2f3a2f5c91999ae9e4aefacc63ac4c463944d5c8edce02de59b85428256cd092540ab58892db09f90456e744558c868264ae1f34627b59db11569dbc976c2e3f83610a9a484663107eb58eeed0a4f19cc9a8f4052f91334e5ef7d6d2d392fb8fde5887a816498402e619081d951c9501a6f46dfb58c3c28d57d956b5eb034e0460d71ba00d537ef64dea2e74599e8d7bdf7f0b8ef71890204f4c525000841c119fe5b1371b3f5a38512157fe1f07630774aaa59f82c433ba57261766f85751cd92929da91b50d98a799bcd086a83760a07bce68ee7dd44332dcf210264ce6b3677f0f7eb30ab16e39477e4112095db0b4b39d97735b283f1b9e82b9339b4f51d78658693dcc3582d1577710930f12de0dba875ff3dbabcbbca715c9d8de33ad3a0f8f", "1", .None}, + {.Gcd, "-f3b63c7d41d20bef8e5bff0bfe9855936569d314c6541a35b2dde639bd4ac8f5bdfd0f1a02490aea0bf0fc3902a72c00fede3ff8963f61821cd07696869c2a2e157f55360750e69e3b11305a2a4d07e0bb4b145e54c32d6934187bbca77f6d066d63b280865054010a68e4314c1c6ce99d1f04b9ea13ecde37a563899643ee60588f4c78b59c9979360078c2ab3f47421a22b21db430bc2442bc2895735d0cd61bf7281d364822753a40db341385a86662e7b952e31092d4964eccfe4fc1936386503ec0830c997535491ce2409e6ae10cab1853b6b9fd9fb18a2b469a8b3def8ecccceff032d7f044b7f71798a1fd936b113818deb2fdea63222273b260959275a5b29b8a70b9884c10a490e499f9d1d5cbd507a1f9d1fd3e6c5ced2e20adb4df028ecd779ecc22c732fa50f4d62090efb765dc6002ef624673e374820b234145025012cc39aba417e00c45ebbcc4d31073d82712ff65a6aab5b3edaf9d0280e9808414967f91b3de9e9684d0b9ad0be57a11e418bda65d2e344c8e8ef2a468ae8c2da1f69f71ba3f8afb72a452fbc01d2be93da4d04ffb60bac8f50360e3d386164f3e5347651a2c7c807e98393f0ae1938935483cd6d4be4fbc8ff92f26a220d3c4d4553e7853ccf1a9a184cb9c2c542809a1d129ae9bd9623551dbfaf42db913f71d918465717e7a501daf37d8f39bdcd5f7b926d0260e5de4511069851c", "5fdfb5984f4c806d6dc36cdf32c1989551abaa785ad7af1827fbebe7b4d44bb9f8764d79cd3224d61568abcd96e138e8652fd34a8f78b0389eb7365c4ae3ff71ac9070a3047558f6333e87712f04e061f692a08508cb836e3eb7e70a47b579ab71a89c6c00aacf99991ff6fed6e700901d82fc833fba086efab36b0fc8707c465789aac21f93e5a6e1d58f5e87664a2a7615d82d3cec174ca4b8987c0ce550e1759f245a775b569f9519459b03b668ca97b0bcf39e1997d27981a791e40c080a877df77f0155544c0da5fc3ba799f9784a555a7a988d21a7d2053f8fc8716c1db417fdf539f5c67d433923d610c7a8659b61da16310ac133ba1f13a3fa6716c47a8fc90962a3257e240069891e75e96b359087872d5e3833fb111751b859d839b6975bf64e820f181b748c1499337514e5020bad137baaa00fa38d3b5d11d73acfab378c06d3fe0b7aaff60730b7860052a930c79f891407adcdbd19ba6990d8a50b51fc37820716364f7db2fcd71b5bfedbe2dfb3f717c2a10c86c6c503651ee01fae7e1f45d6c335c4d9056cbea4981a622f16157e952368803fc962f135c1ab6e190fefeb7463db06001fa43cb19adf689a7e8add3bfd987d1a38157355fe483c4dbcc7ca430b65efe342a9fce50e8e628571217bf038be38eaf85281207b864544c7b16d6caa0d0bcdba1633874e189cbf79e8c4409ab030cb0907bb59a9", "1", .None}, + {.Gcd, "b254df8b9d18473d4cc037e88792fb1170b205340878ca2a43f6b04fb5ffa8be776b66da9d818f0950df4aee5b6961aa1218dd0c216c6c3a7282ff3ff2f4c35ae6e4edb6fa6da729782daae43b616c3124be404c15c4822eb8a0f38a73bb3bb9a4e732f56d30da9314a5bdaadcc20536f5be3c0da3bb3bf1ec578feba85fec73a572b2ba138f5ae9f5391dd07bf7d8c39f2b58ca57372979bdc6594d3ca5476f888b062dc2b8fcdfcfc3a3aa3bcc4ce2be8f7a6d0eee46fcdf845193594aaf6217fbf93c5d316c15b7e3fcc7dfc280acc2a2067f64f5135aab8f26f1bd5dd0dd2da9c57d07b6218d16d07801dcc2f0b1dc4b3aa5514c25db4c6ea7c98032e74187b7ee50cf8e7cdc4ef525c7b1d9cd05226e239cb843f6512fa613b1bd6d176869c6e07087cf1b3344360ddb8abfec84f5d562c4f6c348942c74bc8f2786e342d9b923ada8f6f6715651bb8c61a613419b3fd92287497670670b6c93d6d1881fd31a2340510740ae821dfe2e2fc58ec0bb9e0cdba39be811813ad9cff61eb6966485de6b06d044a8e9d4235d2bdc8bfb86c433ea341d957f89ace2022f156d836e3200ebb83d80ad9f96deee547987f149a040bdcaecc0200abb0a638efa2d98d93d33b5915dc3fddac00f4569a537e35aac82d285c68732ed82ea2592a508ddaa8eab07a4e43d79bc114a810d35edf595b6179fab44180bbfe0ffb46ccb2b87", "d5ecf9cebed2778c065ac9ddf3839d39e4fe781302171a2cbe373b871baafa0e30783026dd145fa112ab8bf992a1fe32ba95f53b0fa67fe5a575bd6085a492aad17482ab055c7cea10f0b4870ca83593b29ca38cf4831811f8c9d0ec91e83dc12ca99162bbc030fcc09da8a4a5599d507caa86814363f21b1f3a0f8363ff51286c50d34f1c6062de3353c346d09cdbda7ceaea69bea0d0da8736113485678cd2e101cc444bc2fcdc1c5642d663e5b96829e9d56c692346fe6c3a8247eeba706e0e7ac632554acc2e6bccaea208f61a1c1d9ec07230f98f539e983f40ecd78883c0e99f917d63dbb41c64f7c334cd55582285c2129a3815da37a111f5fb24c2d066ec4a1286c99f8d5e3a4c956151b18e439929a55108c0c19ea45f7c0d06796dcb38e008d0695688ff2d91701e38fbabc9192c52026a0ba2e798aae941abe6f4363be32b89351c7c83f7e2ef6386df5f1706f612e42ff57b7b165803c65d92a8abde9aeb9cdd2ee98967cf165fd8f701f10b715d521f64270f6af0e6b41fdc0985a2f27ea9a0437392c0b44e4eca2c42fcac328ea27612f5c6f925d2ff9e3a5c839ad1dd5d2503bf19ed783accbd1fdf0ee83e2d555b986f131ced73417078dce6c3d1208adaa33067af36bd76307e5742cbb51dfe5e8104fbd8e2cd9443aa8d1ad02a72276dac901ef5f22ea1d4344309f4a344ede79d8203fe2b4e18a935a8", "1", .None}, + {.Gcd, "4d610e00ffaf8a20173ce90cbcfdfd724fe7e9bd06e02aa253ce74cc28c6efb8ba30b4929028c586a7845e8b5fae1773d234b0171df3448287749f0b0aa2803d30b0c47ad000f49f879aea4b91ec8ff489c951bdfa75c22900af08a3c959931af33412463e8dabfa91945083ee05c6839086ba395c159fcc555599b6b8aa951f7ed790f731964afe656863b3b5e3b63f46eae8df8afcc8176bf29df6b363445f484c86488a3fed382d08de0b163c0b1584c8e31f2ade4e9c7130651e3c46e102d50fa50fdc9c6e50677c73edc991209fd61cb9555157e32c93187017760488197930905db5727c2dc498cbb137d35f991f059a8e44db9e08ff5cbd9ffe1026ac46aaf9b070d278b96f641e4afab9c6b15ff96c8707937c965dda5b3f808f7979401c36206e13026206eb33a261eca784197dbd34b1073c9861e9cc55149666f5899eedab4f193ac0d19906cf4eeb9f5513d7f0629bdc54d656dadad022aefcf73b92d9a8ad1b0569455da646dff1e365929181806577ccb2b338fa9db4e462af6f9883663e8191e81bcb7a890a830c51ea31f2230a4b32966f63104bf21ddb80577c3f49abdeed550bceca53d146ba66944b7dc217241305bfee6f132f4d1e23e6e402373ec9b33e16ac1a4f24c246d7a3a95b30d1690ed56a859caf1897e2282e3d88879bb51f9bafa146806514919f5dd5bbba9732f10ada7c0eece4e75347", "8f73ce2b8c0fc8a3be2ce9fa92c9f7fe06e099b0e55f66570275af5e3f8d3674f8a166834830588ab170092872d22d0041b1ee56dd47ffd7807ba7f67332bc9a0b32a4902e4f819328ee74c2ff73f6439292fb500e996b88ab137b94ca69131e4d3022b74b682e0966551aba5f05190848b7b0181c5b53cbb2e32ddb4d04d3e023beefae649c3f1d00fff68b781def197c52b2ae58bb70b00db8292b6e8152111a0ac703280ce86d9ccba517f8e081e767bfd32e5c83c68dcb6005eec4d72f74d3a3fa0a78e927571aa70369acb1bab1584ff8002efaf0d093b34f8906cd703e5a1852965f4d829910cecd72b2e3dade866fce71b285654069fee6a3712f741aec225960469be7bdaf746c6da4a86bc4cb61630c83e8dbf62bebe590d63881ac5d4cf5a25cf3674295f34e08c7f65d7984d85bba6d6ae8a851d2d45727e88637189cc02e496f839bf528904bfe847aabcc45e89be947b99ab302fd9349729b5c758151ed2d791edd05003cc2ea56bafaba8b47be057ce83a1c5ea9aab1c1eb4fb968d7da33e2fc94d51d7aed9bace262c1d4a6f6c6be254f2c3ca59302ab2fa5c8338076ee840fa797aaea1c5d13862145935373199e599c0fdf13817f689976cedf25a03c2c65d858ebf3dc5224856b187cbb5a3c20ac12a24516dd8e108d3b338c5fcc8bea1f84c6ab11c07c479f8b79683df28d2dc2e5d45421f9c28cd14a", "1", .None}, + {.Gcd, "6734dde91183ea491a03d642f38e98ee9de2388ac39d455e5464df4c80a3989d54121b2e7aa6feae7e7efc3f3b99be249c022fd8de5bae960c5f020c133fcb808d52abd9daf550ee8f5d813151c68f458db7af21e9ada226404425e63204862ddae8a2b0d2dd038346683aa0a79517d3cfbeeeac9fdefd99e138442496f10cc4af9da3723bd039801710650c71f4580adc25d7abd5a1dea1463d8cfa17fc38db15f1b62556c524c239d802ac581bee2f0ea26f6aed61e85fed5559cfeadfafced9736ae6df092273480145da1f05d958ea718c03def156364de0a5dd530702b76fe6021ef9c05475254cd7216a5c30bf26d58b2476a1a948b75e939bfee1a7ab75aff4fc5a97c3dcbf58969eadfd8c10abe2f106a3ea843f08af92bc8803b2fa95ecfe8ca36f3f43cfb0feda29b847535f3bf84b3ee1c30b3f7172d5279e93fd6f6d8f748ccfb6854c483de8c8cd563f35e3727bb62ed733c7f9e5b74157b20af50c3b4937fd1d71c786d33288e7faa32c7581d168f0cb84e6e7be7266d88eada0f59663facd7b3c25f33bae4f4ede2bf07504c6389371ef3974ac99eb14d87e6f1ffaadfa4d8a502d5f4d11463e7a536ffcd63e5238bb830190b50f86c2596ed0fd1a3735539b101dedd9e3b8b093d854281c6125804f31eba4dfa99a7c607f5ac5548663706b2f278ab1539db80239512b3c2664a6f09e689f389a1947f480", "274776fce1e206066ab717a4e579e8db90fcfc31382e8466c95dd1160d5759c6cc5d13cf20974e53032b388cc34fb5376daa94a624e388d5d2b245d7498615d4900cfbda36bd0de8a9a4259d86f6332af154fa43676244218005c313fd7dcf96768e8c9768b0e88135102374105bcd35fe6c38644a5e8a13aa38da8137acb0262d99ff568547966550e03c407ab9291126441f5b7431eb6b820fac115ff676719c9d9226b07a083bfc1d461e08d4f055f2e8b5691e1469ca2fe2b46a98d613fbaec35deb012dc10768ee9868bfcc60c3b9e464977d445216680e1d4dd4016d5e0cc1d38059342f8f96186a1ed5c47b1c24df81125422757b4b01825bb4923f4bb4ed367d3c6e52075616fafb5f6e41ddd527c5030dd3c70301cf4d52997c4db2a77dcae109f6bd7584e874702b25c8fdfea4961e54119d5b25c8623093b9509025e985e160bba9bc1ffb1e13604f69485137746cfab17a69e99097e95191be0a420e2d9fc63c9ac5092de6254e6a19cfb1cb9c28fb91928f18ca485cd9d251a174b78904154fc7c9981e58a0d2d9f61f9101f5a470ecea3cdc9feb8e84f84f0786437ddff63a7d63e705d50dcc70063519a74dc0cf80e29327e90082686fdde1607cf2ab80351d0dc80caf35aa058d1970a2adfa836a0b5d9097dc641d8a3aed23440dcb1367627747515fb27a31d7b0675e9cb0f5450648cc93b0b620dcd086", "2", .None}, + {.Gcd, "5aae28e2db3dc2c6562ef2a96bcb1bc9f1863c6e378cf4def8dc6d13d1556abdcc42fc26ca367bd16ff49275cb6ac10973ff0ef704404a31192f5c8f34e1b5691c122810388cf1c490b979aee9888dfbb33fecefe2814cd5ba808aef19214c32b29de25ee76186e74801771cb8fc232f5b56b1743505498adc5e0d4d97ca80e1f083945cbd5241db4919be23d2c3c61799df1ce9348251550d3113cbb2f25891decb852c4750f4f84f89fe42fd2a2714b051ec9f271783919abd6d1e34cd30ebcaf3462045577f7c5fca50c6e863342e112b3737bde6f148c9f50bd889e670f3b0ee711183f520a7fb2f1de956955aaa60720a46842d18746091bc017d6dfbef1e158d33f903004da67b9de81de2b43accc8dbf14223064cfebc28f3cab7743be07980c9cc7f0aaea1a16f7914000c73aa73445ad2755e60bcd5162b81ea5f857ba059bc1e7fdb0bddb01227b38ec5b919af48feadc68d75cf18a6a4fb7469ffa2f299f262105fc627070b46be4a7f369df6a7e80777e9ed37f16c2238888587cbc35c4fb4a99a6b9e62e9150b38585b3188fb161c3968fe9b4f087bc25c88902d0eda97f1a76b9fd9bea244b61e4825c1c9adbfce71ad0a241700cce3688e53d4a7ca7febc78d88995f179237454296ef18cf93617c70bc259cc355857d987d12d72681dea9cfe5d9b93b2f5a1fb806b77124c980cb561478158157d8c6cff3", "1c1e5a3ac08ff470808541ec3ec3100b921cbdb523996a1828615292d1f92585644ca5b4e463aa18e3cca0e1edc073a3e074a01d0ae6824e0a9e3b786a38c0a1b996d8e34d76f56f777f2471f460d2adca007dea7a219e3b52bfed70de3d2800d6342b131a57cfb096edb86985f9d24c7b7757088de774bf736cc04f696e740a219339374f64ff779b11ae1696ae040c33972df4b6d4e032e1d259ed375fd016b8656834160d5c7578fa6cbbd63211298efc29736ff8bff4e7011e5388ed3eca7b653ebb5d202ba4fee1b2e4b1194748ff0a2a6db38a301810a23a261191cb1b8f90e5a208aaab4a9d32966b278ee2402f705d3eb04d9cc73be80bfec217ed550d12a17da73a5805e6933158b8389ad3265b3670b8f5159bc40404a6b4caa0a3d3c63bf6bc6ce2ffd93aecb65492bcb3e541ecbbe0f93bb1bb7b207d740451a16cdb05771edd6a25f028494e9d3d9b5377299d0b2803c1609df6bc5552d082195f80a866976067ccf5cad6bff3dd903f3dea6b22071cb2a648880ce439162b9f41143cfdf089292193f309956fca3000005b9a5e714fb6218d27cc7eb928f597935263e335fe0516de291e42c03a17cd1404329e82c103f9b92db161c1c698895c33cde33f40b567eabcf19bb63090cfa00130863293f006f51be1dcd929862c63fa09ace267192e4111c53827d56fb9d3c8f4f16168010a549c6bafa5e8e64e", "1", .None}, + {.Gcd, "-247c6b6ed8d24260e75c5c1ddf865c7ef4f39c4622ec6c04eff21b375d98c3e468a8f0c824f374dccb37e9e3c3196f5f3e0ec4b8504035bb9cf3f03447719d8b18590f6b9bff6f3f6bdda5abe7974b272ed2ce06cd291e4a5cbac5e3bfaecce36a27e931e410e383e13255c88b3b87e8ece504518c4a85afbe5cdb9fe8bc60dc6ae05ac796d1d72a4a9ed602d456ea345f85528657865208eb55aae07882b19361a0b86d652be2b2c49b6b273d52948d7fcf16bbf00b92d1304221218794dea6048a82dd27725cb5f0fb552e92bd47861191d79129008b0b5c287821d343384542a229bd1f4aa31efc2e6c02b40b9dbef8f65f6b5aafd15b842bd69438880b6cf24a2e4d0093c0f0d7f923a5d02a501f2bdc968d196595a5ca702908d1c0f013fe7e5317d1d18b5448fe004fea7754fd872f0d529b2bc15c3a774b6d042a54e3324da399209e6ab483747f05ce284d57751e1c01981a15e7c2765ecd175ed63f8587ac090cbafb75906f83da1edc4b6145a58dc241b3b5a9fef5d91c08cfdeb21c71483946b1c9997e506abacffaa82c2342cb5357b25f77261a86c5e34f2fcbf0d4318b838c30016d31285d81c4b211001687677c92c6bee9eddd0b2ab2afda63bd09ae3517a9f918e84f9dfb0cd8b3b1a635b441f6d245dff32742fe0d3e1c4c44203dd74644229f2c90f0c6d06a18da2bb8e9709fdce32616bd1a03633bdf", "f57f2be65de4dd894ff5b314a94761585a9254dc364d39808b2472cada311e3786b839f08acf03e2d9457bd0eb48bdc6d884923aa3cee2eaea01ce67394c59500da3cbd27429e2c05b8f7e198160b441176995ecc8eba7477eb8501374b8fd38c55a19a4938965c13de62f7aaf230382a20b96c2e79babe5c48afab697b6f57de76fb94f1e8bd8bc073055217bd40d40421c416b4047c11351c3990e59c9dd8fbd446e6942030103d5c896570f9a8adc448b0f960c0654c29f53517f8e9ad826bafbb487635f228d3abbc136e53f75408962c28c53de28f668edf378ff542f123f187c997320e5ece318d4ba0d590b0f7da644968ce4911016f5ddf3507d7a0014360c7cae9b3409ba35b731c028bbf08dd0b1c16f53e662678396dae4f2088de8788f5f121b721f5a9bddd070c19aeab72ca97d6645ce31d8b77844efe112724bd890b52646bb72c6908c7fffc0a8d293d96b4566b7819ff7d52541716dbc135edd1ac55d57b1f5d8649344c2b6c49d743a47e596e2c5f3267e6f4c056446ee33c5b9239decc46742664bc197598bf1e7dfbb185d258bdfd4eab1c4579111ca64cdfcb34d18ebc215ec6f47cc053d20463af0095748b7cb028b57003f13ea71569e2c0d24b6bc0b13466a0e50c82ee4b0e95970fef505107f1da4f4a0a7db5fd4f62e5edf293767d4d914465575571b94fe7a1b97c57668d51c964a3f44b913", "1", .None}, + {.Gcd, "-1bba6344154e5c6dc1fd4087975b6b177406e53588048aa46feb4ea63a4c93e0c1fe889128f6cac652afd71be96e16ce9a097241b93ac9eb4314caa99fb4f5700da1ad0fc726016fa4dd9ff68d24bc045287eb341b486e672d78918738d9951a25b5274ced897cd6db406b2c8f768ae0a8f7de73df80d35813d8e4eacc10f2a35c8e457c2926e7fd00cc4e23bba3465cae808e6909fa49f3dd7dcb20b04685d5768a450ab7ff34cb970e19a23cc9ecdc7eee99220a112d5f171dcf06b7de9889a93b981804b3d723f740ee2f70a526e2e0ff7c747982d0a3bd556b9251398173275cfdf06c83e13700838e9e7dd066d48da1f9ac423832944043e46874d207404163eba61454cc15b72142ed1462bceb001eb2f33468d055453359b01b6d07e5c6a29f5d2a9f9fb12ccb043b4612a210b3993fa16010af602eeb0b4ae46fdde8aca8dfc1e1a78ef12048e1cb1cd60ad38c4539490b641721614ae7c4ba3ce294cb3b0bb3edd57e24aa6c13cadbd6dc78521f11364be35b31f5f1907e6642b38157cd6b4fda2c21092f7129c9f30eb8a03befeacdb130526619d67577f7fc09c33dd8af4bf91dcb408a99acbbbba6610a8afa2e30746de7b1798369e3c7ffe942e61e8fa667ef2238f1bd0e1c2e8881e76e634181f4f6d7403704174f3df591e1b65de931b40337da279ba9ab880868c1addb6d77eec7b2c34100af0448d0ea15", "de0e216c92bd0afbfacef2512dd0e0c11f06c9c5ef31ac1d5e2d8dcfa2c5508b8ff85082872f21fbe9e604dcba33b80351e5e32643190a993e349fe305ac1e95a9af7ec6eeb35c1a040eca5e3bfc343ffdd8bb8a49c3845c29f041617e7f2e0c5b550ba2f42f922438dcc642fa62aafee90b5a1f263b30a8d7ab659af329dc7c77288b35fc37477e690b404a972952619376010b1e9148a8110ac04912db7059abed136fe1f4d9c450baf12f6b1a938bf4f4c091ffd53388830aa997418a0bd6188282723969be4c6d289d6cc4182ea83edc943eadc7d5e670bd94771c3256ce537bd05ea718568d195c0be781db0e0761f5846b0fcab33d7aa35b6b0be0a4b8034979b31f9ff7ae375f10d8593bb17b09e11d95d6628eeb0e26ff1b20e0bf8d7a84371e2850578fbc0f471aedf280b0079b999355ee0272a16afb0ddec6cf93e328e4007291e7cae2a6645620b251d4b3037b5c2ec3e9f5566fc12d2f59c5c77ead961ebbcd5f2d1c7a157b002d871cac6da9b46a68e1dd006a322ead341db96c7ad3ca9e353003cf57877e25d4b3964aa96c1cfef2f69659a0a7fbf9be258ab14c252315facfb8f983ae33a82a0237295c5e22341f34b25e4b34b0bd536b62cbbab38c685e0e4a078b409a0543b3c47ea64981c15d65bce7f67c3eed35e65c842d2038e9856c94501ff660dbfcaf21e696a1cd3374d2a28c535bda61526b6c", "1", .None}, + {.Gcd, "-1bd40bad4b0b384b1af8b67352e06aa5dbe250acbbc30a59dd1d9e0079b1a4da9d87898e7a9848b1e0682a6481f9e2978b2152cb4ce8cd92a60f2793364ad17fedb70ece29e317b41d34da74375822e1d34871bf4aae2572d7d611d50ed0bd337c5aa5f3a31c50d5d7062551f2e950de51968c8601b231688efbca5995116f165bd695793bf1245d518bb03f922525565430d6eb2cc508329e494412f62a5f25d3f1dfecb960db52785f12123e59349a668caf99e95cdbe6e44b6cf53afeb4c8fa8c2aeb3dbadded6eceead45ca4ed89caa2f18a9086b366894d2f2fde6ec47f49786b30d5859107a5054acaa262d90a8a52f84d2ca35ebaf3e92d51a5778b714c0db849fb0919f4ab6a3a7d23a8ce1158b58c01bdb8cc5a398c436ef9e5ed2a66b1ec2afc3a77aa2c82e5c1465fbb9a7fb68033491b1ccda06a95340a0bab52d4d09ab4ad5ad9a034ec3bbeefa340a50de23bd368747736cdf4c2c0404c055a7ea44b798984daa157f97ff5d41a967758dbcace86e88966fa86f2db48c41112b8d819bb6f7b1a1baf1e549160e7f02fb68cdfe1a87d18348ccb037b9573d3af754d952ddb2f01a18ff1f45555320e8c193c2b0d903540de22e3e42d03e1ff931609b6042ff9d64ec73653e4d36762a8947ea412fd40baae5a206ac7e17bfaaacf47030c2fb54379959f7debeb1faffd0eeba1fc20210d2251c2aa93aa2d591d", "dde19a226c235fedfdc93af9fac5f2e039aa61d81c270db16eb5f94ce5445aceb4d5fe0acb6f2c75a72eee6922781ac4901cb9bda65a93c0d268a26891b42997fe6421f1182549d48e1fdbee9f286f178c31dd2d79e013271bcee8d297bcf7a5e7bc3138ae35387959c745e0a0bd7e7676a1668bfcff056c5408c296cf289f63a8c618e5f1b722c3703645b2cd8b8f378f2e417ab56fb59d9a0e9b9cbb1c2ea72b465c337482c365b001e563b5fb0975d85330a70a1bf1daa9fbbcdb4b9d88dfc6ecce4d2a13214d91d83e99b451470540f9394abc275981eb932ea90de3305a5dd0cc7dad1a397d5da388f1c422fbf963cb3816d5eb242bd6ab1d36438bc6eee23b0f864217677e66c31fc6bc150665ab6a96b52cdd9af76809d32e6cea52b24cd2b6580a8e7b8bf129f5cef0e6fb86cbc4739adcdbfdf877b51f4d7c8348f89f118e0e32fe17f8786ec14a767d357511e38088f3d1fc05b5cc5fad49789dfa9773d7cd96c5e3c4e532a9d4e4ea084ca055c04cd299cbaf7ac34bf7c1dc9a31081fd804f67ce7e10d3f95ea11340ccb685ad3db22ba2e21c4f49461e7d02b58bbd457f26a89a3e0e67686bf8b67ba3a308ba9024e858563e439ec544e1f47413156e0421dba0146b8a85fbca52df8c5de630fc2f29c4f65e27d525438d0da814e0e11ea6b3abbdb7a54c039e3f7aecb452f686052e598ddff76831e52a4c3bd", "3", .None}, + {.Gcd, "-ac4df36764110d5d92f4b484787bc24b1d1dec474d4932efad798cf99733d802b7bdddb86b769800f41ed39976b28fef5c1de5a787c507b7fc08194200fec9717914dc05a27d2a3a031fcbb9bc1e55da935b91a714ec43375ed6bf5b021864b15ea7f6ec4b106c9e583ca13ed35f9a93d74c6d48fc6522914dc63cadb550aec546ea61e0679dc558e6ad4d3b0e640b7f4c16bab516246517d35070138d2f2f924ff4fac6c06dade2dff28b193ec828ed9581a526676424e1d13d88ceb20c2a62e1a27bfd0b5fa0c5ec99074adf4e6539f66168bdc9a04de023e90f3f4c41739e80f5f4a7539f671059d38d5728bc650470dc02ed9fc33dba70c9f45ad8b61efcdcbbaec22a367afd8b8e3c62072c7fe2be036475d03ec9ebb37dc3d2cc64f933dd231d37af7e42a5df75cf8ef85122c40c9dde8c4c627006b45d2751d660f4942dce24f6810ad3add0c1d244f1f4fb40e50bafdf2431e5578f37b5caf736cd96bdfe1cd77a0c0beeaae3045fbe0dc6b48709821cfe1a7f3a5d227a07a0aae739d07c0cd41de7d549c73ed7891abd1d45fb2c4d5561b584e028205440379d19399a6165b24954e27e07da2795970c1afdc384efb192a4a9a4c9455be1a0f638de10f8aabc7367ce708526fbdf9138e1d094dcbf7b9bd9c830fb85cbc38dd720c670259057e691adfe57fbb860d71499003a43a4b4e516abbb193a80feba6fc2e5", "b87c2ba2ada6f6314be5221cbb163e48a78a4f24d07c215f2053cb0c6d272f1dc2ae3c5f0b055f05989f2a2a66554e3f90bbead1213698465b9fa01c1723b50d570ce21b04227e1767e112d1731bf346f1e7ea47f9cc3687a418cfdd059b5e6f3ec7f005667e8f20c11de09b7618968569aa8a4af6e4831b933a40a724482e8c13ed2ca6592c4db38fbc73bf2645b81ff8356fd0ab8e543230afcf9f88641d66d2f2c150ce9bc3e22069e68e49169bad278d7575701e19961694b4256644be545bd5e5b737b34098e27b2d3f091c1fad075e4ae520e51304cce4c26df7bfa19def2f04503e9d0d68d1332a8ad350d8ff219ad77c3ef6083bac241b09d970b186f1f6f4296ad17ec22fe36b4a9db7861619710b8249cb94d7731e75a8523557ca71d8a1aa8dbd41214dada544f2aa57169ebe28fece0aac798aa9ae3c0c91abe4feaf0762a9e512d6fa368d4c16babe83cb68b0bc8b2b4c780a218b2a45009203ffb47f7ee37a786fbe362031019ddfe11dc9fc1e476e73b5cca101248ffec69922213ec2ea9e7cacfcbd6775022c458b0e7e5dc10ad961b388da326c04b3efde47e3f24a0cc5079aec440c3efa5fe2f16edea626a3684b93a73a80b493543b50d7391260081b275bb76a8eb2d8ca3ec974114d4e100e4713114bc68388a07976c7166cc39f8452ae6fadde02823f48bdc23447a0b03bc10516be4b84996175dd", "1", .None}, + {.Gcd, "-5be373e838e7caef7f61e18bbfef05f04c0a77e2ac4d911e58c6cb39c029700eba013eb0ec2739c9ab39855055a86e332f9d1b9b325ca1a8c3c1ef2c77d48aedf262ae3851a106ba3d98e955f76ee474f1f55e4366b8273b6c2c9f6f5eaf83007f85b5e90e82e81ec493bf30993e1a430a25a914ba308071a2f1699e7699be9883cc0ba02b99285a8730dcd4cdb5178f47c586bdcd8bdcbc77552d8a35f9de4057a6a7d0c5de9ab6f7553380053938e3f249255d942f7b286cb34cebf01909de92a86f074e39e8f7a550d4cef10e1b82ec89d6402e15f006ae54987168411af707960220a4025ce4ce31956df5720aa05a54a4a40da6564fc5ab38605a8368767269aa5ba86f111b0a00b36edbd1517d266fdcdf4d1f9fa9fd6be0e114373d5e0f8cfde84b2742bff7f80783e3905c6992eb087a18725864d59eff7f5c443182e48e2b8b6528b98b684163283d522a0132220c29b6b9afd755f2a207d40b787aec9b0b5a08cd3accbf7ead560b8aac2cb719da532afd5cc8838f07dbd7529344312b19792dc279554ea7870c7b00be23908ae27edd0c8bf426cdd43e746c23d0657c2545e2a87310232cf197e970aad29733a74671e5fba07a716db2d88917a7597cd34482c4fd0023c494bf253d5a94404df68f6cf698899a08975c0203014ad2d891c7f9794b249ab78c156f55f8223b89c87aa942118c24ac0cca950aebe0", "1ba192233283429b0d8c63f6001ff9b579f7f411e0dc53bdb031df284d1a0057e369a4589ca2bae6bad1f1f746bde513294275208df5e95dfcad657551ed2d59a479eb14fe12058fe87b2eaa0ffa5cf9a4597fceb0d4c0a55ef8c53cca317ca2697eed44e323919f2a17bf7ac1bfcaafe0a0500122e35f90a37f4b98baf8035c7bdba343dab5197667c763154ed223bb2b8ed51f97ffc6dfe83e09869b3287361d3572b3b1d658bb2c1a1707905e771634774f097bf2078aa492f2f6877eb0281244730d90bb0b1aad01168dc62947532fd5f4473284e2e1fea5f7ae62933fd6dcb3593902d7087df903c9ed9223ce8ce59bceef772dc57acc8de6bd30427e5f2ced87d7d1304d036552c18b14b1a833c288e3439c0ae6256c1925244e180639d77db970f5663e4aefa2c83eef8563018d3af9c7def7b9bead9ce678ea511fd92311b09ace48801df10d2ddf1df4fd2349c7be91b939b36cef5d48ab77585826c89560575e23c6cc158367060e84c90adbaea617745f36ac1550b4ba1666058924043d40d09a424eb548db25077a4afd26a9dcb2a1a38e2489ad92e95e20556f4ed87b4c7966dfb8b006cf1594da299e1f0fa09b3bbb443056e47a7e86ff226ca0e140c5cb073c99a3d559173798b9f735171ff5d4214b0d0043840c259926901e3017c1a771dca3d283fe64d79ac488a16fe7ffb3bd5841f20c1c33d65373f4", "4", .None}, + {.Gcd, "-7f0643951a53c64f29e939f369e845fdcecb393e3868fac99fe94997a421ef6463cf7cc3dc798f7e2caeac52c0a41fe6ef7370c4e80bb0f63cb1eeb2a293be315e857bd06fb7d609e02bb8ba7e1cf16806125791773df02433af82ec968b4114a13b9406c413c94db354be8745866414d7c3ccf0bc25295901b2eb6e1da1e267fb37e5df61ad48e967075845e0124ed0a0ddd0fb3317d87f938fcb98081d93a694cf995442e863e2399980a938a6bdffb58ae22c2a5e5b687012edcd0cebbb0360612e4a9e078fb633223de2775853b12e92e0c9597bac15524c68ec935509f45b00e89b3b3e6bd9bcfccadcda1cb3a97c9ec886c09e1f4ea0ed9f55b683493a947adcd2130505de73cc0da52eed72bbd2b51178642d9695f1fe72a85589febab27d338762ab99d8b8692196cd5798e3e1af973ab3d63ad8e748226e57a327013a5d1ce8f93059cb4ab23253974f85d98d2ba46cebdf558cfe6d880f1a92b3e7926e3095971882b56eaa1060cb626a0b549d7a6a6936b95da396f6ec3fc8eb6ac39c76f532f34d714da73b3e303c545c42f1012f074ae1b4a51b2f46bd0d681b2543caa11c9e4dbcd928c165941c923fd9bcd08847a60a8cf49a2c992913fe32d061260b5bf285108be0d79ab0c456c41d24ff0eba93f5a9975a31472045fadee3fa4d7e5a16fab01b175ddf986fc5411a836b8f212621885063dc2f50c89b97", "887ecc62a9c633fbbe03378736ed716ebacc1f8aeb6e67c7d7492824603363d87cc77b1440a593ed309bb3ebf01ca7dc090db54a2453742250e057fe1fba30e555a571dc55c2b7fe4f5dbe7f2e06ac98ba2cf3f3b3f85edbaac73c89820aff21c95ef152387cfd7343a41ceb90fb948985b5fff0f52f085d8516fdb78138b4c1ce69fb00e2040ea65948fb7aed6d240ffee51a3bb9d4b920b29f7e9cfff3e780b677652db4acb962969c95f1ef353a852d5b606d753e97e2401093efd419733e1d872550f095481167ac1021fc4477367cc0553fe049dda98b4b828cccc1f06049242b0c42ede062a490d2b62f4038b1a6671de26a753dba92b050ae8b96ff616fdeffd89b512d638be177e8f2c7547a0c7eb1c600950b6b97cf5a8fd9771d982ac909f0ac4bdb2e97f3d27e48c3f289c87267f86da5821a8de17f93da4af3755549a3355312eccb2838fe49122fa1ff39320e73b1dc99e0e2ac378f60c4520acf3cd0dfa9566b72541bdf75cefef18867f1849bb01593e544abc093d94fa05fd725a69e8a507a9f967f4007ac81140a3f73ea542b19ce89ec06d3990d1dae0735845080888379ae1d4dbe661d8dc1bb7ddee2fe6fb7d16af30862890c35400d467a7674bc285eb0a519356203c1ec2497ea579778066cf474e8f4855d0e312bc3d72d11c81c1d050687e3e6f12117065b01615d094f89648faa8a541d231ab5", "1", .None}, + {.Gcd, "-383fd42247c57c7307184214289fdca2dfe221b7d48a775073a0efdbcbe9b68f9c5557fe3c1d20dc5a1bfb0b8c551bf79a8785498c68bb88a40232d5188570cde8f9deafb35f119a2a8d3a0b4ce41e257b3866bf016b497085b57b243e9b7acbfae0cf6d25faefa0bd09bda9c5d68ba0e33a5b5ac304df31ab48ae9e452ea816224c2f0b86b80bf7c59667d46dceb0668e2c3dc17acb7a9a412336f62cf4c1d2e4f75d78dc09a0cee6321963224ae70c3f8d86d834d3fd35f3ea7fb44ba52788e37a4b9115bc6eee4b34e7cea6add64e1581c6f8025c9ec6e8aed3de39cc262abd217f473482a769fb8c1e163637537b2c4aafcff25a0d740d75c80a6feef762cfabc09d6b7735a8dcb9a5a6da28d39e459c47db857799c8d110a18b33f6da2af71e1b93176ffd37ef272f00c53579f7d125a9e4bcdaf26d3711a13f274d3f7012d8ca044c47da7c5781432cecf4761f8495f6393d287d9faf39626473f8781a0020eefbabd37e7ef5b4ce51f4b0065e655184f4dd5cc0629e86371510507273ff8e9e58fea5fb558759b2dc0a37c1cd8c96140472e837a2709d41df2c55d220b99f4fa9e12c85cdae61c92af1c089346dfb48e85dde692d9e9d9dad8f307fc05f3ea452df24e8853465d2886ae1976adfb22c03a9aea0b256fd45837281969c0543db83f1ea514c7578771d35d05fb4e3ec5b9650911cb51db549cb2d4655f8", "8bfe4154ebe27ab1dc5c2c8b4d4e160579a3b908a3aea63ac1cee72fc9b51bf646fd3c2de92e1a3660d1f3d21446a86cde865ee61ba73562f72b842eefe02507f74695091a1393ff833108118b3eb4bfb6d1a94b734a0acae2348a778f281b121265b7ce87ef0e8120b3f6a738f61fcc670812bc819b86dcb6ad69ed2d37c23a965e055319c6e2bb5fead8e1cd77d93cfa8411d7a4a226fb354a035280b06a25a3a56d11d8de41ed80c847f407a028d8ed770a94ae39f6126d15c333ce5e84dc4f3d654892c46ddefb430b214b81089b788d48dfad2ddb8e11e37be4dba65adb7caed9192fd103faa832228da93cd95ba32a6313d61c15d335b21f1381bdb5aa1fe051c21ec8d08118917814e00fb8c78a79653f4d02b2556abca3add6b01baa7f28a413ea16cd11e5c51178dafcffa4a201f6372909ee11c3649741ed0fb1153a1378c5710cdf73f1057cec4a30a375ed497a858571a0863aa586bedb34f04272daf04e82e9e27b6fe4a7244c3714921ad76dce144f2f53ec6b4d738735cda422d38348d5a059433d7da27c9268442698b5dd8d2f5bf9207a2216c9b29bdef6d114bf34421fbed5c1fbb11103563cd5eedab3da96229d5216b80d9e53745ce18baf872526a73fae0ce919277a5686ba165d926efb9232381b9899f8fe851cee370bc1d42e9575eb13b596d1ff702cd2de20a9af8177e65e83bca49e6e3057ea", "e", .None}, + {.Gcd, "-d324a2c90852b5dc0ebc79664e7ba606ea34d8f7efe9426e3e00661d030c4cfde5161df2b61eee432ed5d603fbe9f649b8327b6dd6ac447ab6920e89a9f2913b58ab7c522aa4b60f9ad5a00848487e5964acccbd16faa484c9aa42e1564b3dfbaf21a5a5ee6f1c8e02b6876d13cf406ee26aea890d9d8e4e5cc615e26e1193e8d2b1054af3611aa6a9ddd5ec41d26cfe80399ddf25a6f1b720c995e3177cf6d04e1b6380d33df811257b11f3210e068a063e241e43ddf85497bdf69aaadd2a026d4cda26047be5c79671fff6e6844fb5965623b9f9f8a88342609abf3449443d67469caf31f494983f339748bba677ca7de8a31c02863814adf7713717a6e10d1608895307047477bf1b51696d6a2a123a9608131973775004d07367216a263de7d412c747e6b3ff36bbfe5c5e54bb4aca61f79924d36f89ca079f86f9474f29d987d88a98a5d0170b3ebd2abd5e8879e41dbef7554b16e45ca109b1df770c8c500471aa04fa8d9771b2dacaa28a2bd903a8745a6bfb9ce8e42a1ff0895c80317f9e561e5cb3aa4d1df1c0e11b5e1ebf2c5e5bb4d7812406235b04cb908eecd67a6f45e557174842c6edce87a71a2385e27daf87dd8c293c428ccefd43d703e00c167d1c7575b344ccb88e3322ff81202ddb8144b609850b627c2c9fc2ab3f10144d1319ab3c283755fa482a24527b0b48ddf124473003a1940e84cd9f07e1cc", "3787dfc10a3bac2870d739ac2a253eb8746a5c41425d53b7b160ae891a7b15ff6f64153fe48c56a84d3dc1e57f68f4ea688cbf304bca221d01d293b92c66a030749d9132fdb6c1d9b1c94313e4f8fdec2e7ed8f28d19cab656ecff4ba61d4399f22186b3a8f2711aeca6623fa2e8499b65444f5539a2ff9016e38f86b23c594e90aa550b038238fb42b4e278d1a265f28cf24c8636eeb4f31fb36e0663d52009e10d644d1e2cf9dabbb3fae15ace4516d6a8cfdf64eb9bb4d42d26111014b7c89044c81b3691966cc658d7c56b43cd85eaa4e536e01b7142f0e4ebb9a23f2e4aed17b797b212c403aa594ce57436fae2bb5f083a7a161a21b854fe646a452f7b22397e944bd7883c04f1291ac58cc08a9f6272643c311c91e662ea107955e0f79334090d74374070246c4213559de22abfaa72ebb9649b429480e928656918ded59f430ba51170993362b982056abcb0ee21940864f17eeb2196dc6ffcf817c09503dbe57022279ab0acdd14e6a12383bc7209a6363785f9a41c1a187a19b0cb7ff436e637286c1c13fceaa5215047551d94753d74bb7a724838727b064c8ade458aa2257b7e88f4dad500f8f331a2f58d3a90e2202fc38e10a113df714494755c6543049527c632bfdf72b3eb8a7a7bb645498ab2307863439d9733134aea25dee964a4014fe05d4f00cb9822c1d068025bece8e06597be12db8ce5e05fdb7f", "1", .None}, + {.Gcd, "-faa58570f8badf420aa4ab962c03b24010d9e5f9b91fcd57e960d3c4eebb774468e0101230d4f202c098c690f4cb3bb52961d727021ff44f688cd897165c3218077881d3e4cce1258b30c060e8fa1dcda78c9709b403416686b07e59a83b8c10303d5549d6fd4539f76ff946413f8d28793df105fcfa2575d5548f2a58f24275e679bd8e3119f4d3cbc82582616e920eb6803699d2360f36710ce8d8cc7aaad3c92469b372862506ae2517cb9618cd3920c3daccaf89012a1b7a2b6e53ea876a65f8bf74521d8cd340acdb714cf9061e3e15e60149765f8255f03b32529ac03e8a6283db8bb95fdf131122a75b8ba7aa35bd427fb7f44b07a2945a8ba1c08745cbb33ef530df6fd60788ad8498e42ae4292de1fc44537086ff8eb0c8db623c2a5b5141e330c31b6f99cae9ec94c7d370911822de12da4e3907c9c5b5989e93a25d223015610910e30dd3a0eaebe5a9fbee5dc82bb3b39b2bff0e640a5cc5297d8f31b92ddd71cb7fb25fe2b1eeba73433e88c5b651b2a3f6c25fabced5a91fc01d31607a357dec05b85161b4e08acc7fe4c93fcd231379f9e1c6c1b31b8d250b484b62c65b334172b4b3e75b8df65dd6ad5ce5151f56b4f6160cd84c7697314b59aecc940d94cc4813df7c7ece59359fd85092e4a86863467a8dbdf7ccb2fd1e0ae0ea09facbd99cb9e9a9062689c6987b04bc91a3c3557de8ee52d02df6b729", "e23731aa408e99aed04283d3b14ff6b90fd07220828316551b94f406325771527aa05a4318deaae0b01d660af9872219c3af634d19528b6ebdf75cbc9ca971ed3081a0c2056df3e353cae7c29ab2d785bf205b115ae1669318bbec0242dc799f57949de8cc06de8a359de519afecaadc076a7bf58c11d2666805fd2805cf15389583b4da86f34cc569b41c66f2270a916d3c6c7e4f9984c1a77643a19100d3c930821f36fe76d2f6c2bbb77f66f6586439682f8ab9ab48abba9c0f433981223dab93f62058fd1dac5026baa37708575368f65ba8b2e296aa6c18badf771a7da594e28c07e3a2d1b22db9bf02488523433bc6f1ee36ecf69a178ab40a9c9302a78b0dc8abe98bdf9927f06ef60ce47d41d7627b85f9e848da8808efa54d05f9f8f7e28fea9578775134663fe737043c80824a7ec114ce055cc1b3a57c211ba9df7f268f125c442d882992daaea208da0cc8299257b7bf872b7c4296af0a824682e2080e2bdcec2fd5db2f82127deb70bb157cd4829ab90f5fcf453fffa3b3469d88977beac7cfee38f3ec2b37557b049eaed7a4732f753809060cff4cef04e23023066660e931e1954c44d0630ec16e033f16b1a9a2788c225fea6336a253d68584ae63d8bc3cddf4f7a74e722d0458a42a9295bfa55d734261f30e903920b7dd71800c81bbb1ca5db29fc2cf0f801e14407bb3f9aedfddec1ebd2913229bd23b", "1", .None}, + {.Gcd, "-1524e1463b01d2bca62f8fbf97b7ec8400ed4bb7f423bb5329aaeb91c524ed3f8ad8295ff0b8a85066db67da090f5cc2065ddae8a1c01f811c4414da12179ba5306df976965545e70229052fd5c4cca0b91b17910a427c19d9767a0ad6bb3bc1349da9c72cecd249abb9d42fff27c49a2f9fdd3b087e23dbe4b9a5889eb8633abdb3255b8bf7fd7e8561dd081f48b4d25d22d2e530f1aab269511445ac8901db0f100aa2a1b8491d9567beb5a05ddd302750f34bb4038ba08330b3b5225355eb810956e6738a63ccef595ebc2c74db996072350eb517b009d74655d13211d064696ecf3bb228e99c403dd7d8e762d70a44cb4d7eae11e044130d4b6347232142c20940fa249d4f60297df4c9e495b943df055281efaaab22cd339a86fcb0ae84172f4cd62296787c269875de5795badbecb033e999863a72ec5bb98cd9f0504285cbe9ce7716f26c9158d0c27a946e0529d3b916fd0fe19f06c0601d1634a73890a2e6a2fb8228ec5ac8e7e0b3004a20748a39d2b6fb5a01c166b7be0a2f8065672f8e45005156f8718741aeac0ad61a10c1e43f4bd900dbf2356313d1210dd9712c863e62108775971bc4635ae7b585c21dbd5fe34fbd71c4255add492b8411abbdda36621c5649737917793c3175df477ceb922174f6bbf726ed58f2b31ce572eaa90d6c7f8b32e1156e2d98be64ee3c4e083bb74bb0ab29ef92e48807eee8", "9dec6028a8cf7de84ffae74180394a153ba5d0694a1c82f7f75dfb5c421dec7ac8ff96ae071849bce1425044a9430caa2fdbf3d7cd3f0d523e427b47f3ff3af4cfb76c22b122c4139917c16304f201092b901bf7cfb3fe76a1a04a0aba82d3cf31362ca1f793df4780fc2216ce6064a90ab04d04baa5ccc136edf111819b29388eea705890a7841775dcced69e1beaf0a7e78dea8cf76b97cac978c4935305012799cb3499e44f16d7c8382c0527993f18c1551f450c2f8dfa91dfd9ba45e18177f524d829953e6b119fb95e055120e93f7614d9b43e98ea8fafaffa66150d3fa35e812b7ff6fa86fd75419bb5f6ebf9dba3dff105614780c7b304df567860ba3d298d5d486d2c84fd23e504bb6cd532bbe3745700626d60efc280fbc42c19f2409052deef55d43f7df5d4a015d6c32cfb1b1330097ca8f7cf61acd4104931e5ea8e39ebc2618785a925a212d615809d673a3cb4010599bf6a47b448f6733fd59d5f204af89f5477d9937bb884989c87ba80559a135588b81a4d03fcee5dc15068e5fd8a23c287618c1108afd7f105a22195b47d0d67e62b78854e652c6a2553ee167b2892b992233cdc20d25cc868a4b623d1e5554280cac07e49f643e196be87fcc915bd3152f23510fa24c116176a1dcc73619c896f56319500ecae7493d28a680bff7229f2ff5182450ba06df7028ba55f32c45989966dd40c96767e74a7", "1", .None}, + {.Gcd, "21805f550d31b4b7773a3ece4f8203312fa344417d78e872d6a356ab4cbe5cf85bfd70b34212c3748e9d7939ad9de7bcc0f809b36e1e6ada61a2249d977bde1d342ffe0297fea9448690074a4961a6ea3d85e9524f813c082f5a1b5e88a092343f300469661e7e6e37472bacc3c9a871e719a6fa9680f95fa32a2674c95747fe58168bcc4864c48290304a98440c58aadd1f31a54556c1027bf07a571f3ce81c0cd4d62913211627fdc6e7c68c3c30a7b3ac6f5f087edabe296a1efbeda0775aa3cff6e031c0b13d12410834e265691927fb362089cad737d0b06582dc92b539e705109fa3d41f2e9bf59e247cbaa680cf903052b90bc232635f7573d6b0c74548db705c4a6725a05ac92daafc9aac57998a61c893f91b04364bd13509751bbe2ae7ab4e6697b096a2a66e6926b80089ea0baf046b4409f47f4a482a27f2ac72c5a8dbc52e44dac71746a8e494659627390ebd0e6c4b6b346fc41548e645fca57322ea1b5d659815eecb814b58e4aeb4a7b53880733acc4f365a467702367f0f95a91cf6912c6df8fd19da9c5f7de23e88222e8de2e7e5c81d09e2d55689e62e8bf44d9ccb2de2ffb2b3e15c2f7a3493772e3139e252cd332ac0a70d3175ccc9462bbc2d45bdb16b44f47421f2658420355f105efc270ffa30c2d9b790f8f67cff175ffd5ecf4006a2d26f2d2310d1e81b8273b7193a44ccc3fa54cc9699a268", "4783cdc15eb58065f483351c8a2e49a312a3c54f4c7b9af542284695f089baab66321d95e70cdc53c8cb4f8fc1eaa48177f7bad9a483ebb6ef7f6b726ffaf3deaafa8511938835ef700da2c2604d9d71e60152a2448577cca05d30131e151207699bc02c40d0c4c554be7d31f377f1c792e9c20a0a1b1047677535dad677d369f726e0cb52f85ac7577c5cd6197abd86ee072c496deb16a4f727247989ef47576b00b2dee75554d8598bae36a83a2846848b42b63b93add36309d20f6b101a752b12d3cd7d50a71846569868f63887a79aeae2fc91cc112e67862fb8f4bea4dcc8751380ac01fb2f05e8f0946b2173feb336c7f0947df49ca94357032376b70ab9bebde1b7aaee381b2d21c3bd4b3cd47691b27b498fde8ce507e7520403fcea839e15d76e07409105f8bd1fa596c63be4404cc70c4d75e02cb20c249b4bdc2943aa50119701a590b54d37ebf1e0ce5f2ed277a49098fa9fd47ece0286a1b850932853444fab3976bbbb5bd491541aabb9d98779e2104b14e09ea02c183162a6151b1a77181197344a4bb119b607195bb4f978c8d1d5c0ec56e88325d76d36cf0947e3edd5cce8f9fe214b09aa15d6c8db09d028dff26bb71c01acf2cd8330ce4773ce80c09be13a61633b1601147d524ef3e42baface246f840f9c346e32a8c40f5a126c7b0d12884dae5dc1295a08be351ff0b5b7f15f1218b2e000261e99f", "1", .None}, + {.Gcd, "-5e28fb030642323c4073aba7b9af7e46ae117af140b14a84864fd370c08b0e18311b17d96ec7cc3c0f3a49571772cada1928d516b8cc552652bfc18910fa901ed31b890d60d89a4524ad17b571469384531e6b88d70beb29c037260db705360e86c7665a3f2b8294bad319754f499fe613c611a41a6a60c0c375f8fe1faec6d723577375678f4494e15586cc3815fac34ca65ba9013a5a189a4df3dabaa3d165ca44a6233482297d81cf2ffedf89c03edbff64c679c50a196d12e70811ae18f2dfe2408641c12a4eebbcf8e2f6f9d9d018a3960b7702cc8a447a9247e044e8183d21b5b50a78356d4b24006706935715d1ee7f7f22d9d8ef2bdde80e06e498914841b95bd4e28b7d21b6ec313c96ddc2ef8fc9ac6c36ed79f1a9d515cd6df7a9350a02199f96fe1fbc6eb9f07f7778aa02ba499abb6acb6295d3527f38c67954bb4e0a14925063f22614cbbe5116040ab1e78092a3510c312485052f7dec33cfb2fb2825737e277475a9e504a6699c9b8b443657ef1f03b3cef9ca8d06ffe1d313974ad6d3ff61434463afac0caae2798469c966ab04636fe4b0f11cd8be099d790bd8d4795d67958c3e8ac7c5ba2815ac59353ce0f2780c4c81fe7979752af84bbde85f94a1d22a38ac15f1166ec19f33faca1bed16e44b2f180e6831c078e2f336d17495b73a539bd84322031fa59619d34a5a9e021a9a03b0cf7b9298979f", "574de7c3605042f467dfe86fec77da49d665e4ca274a5f46edc5b755e488991dd1e3b48282305df9ef4d047eae491eaa6fe9c9d6542f84be8ad8c22fad1b6825a791d90f0a7d9387d6cd7803b0fca092355ab827f3a4a7a15d92c288d08bcc5093d135e7219ce186a08992383f9ecb1248c06a8dc5d10e377092c9e830732f52a7c222a7d3f152f8dba82413e69e06cf7794613c90507ddcc883d09af49b3766c05d310f8801dcdf85cbaf2c83d729ec1c3226499fe29183411c1bb72a3583b2dd8f35bd98a198a79d3be12937c333c1158e692a48348f41a7b522579a915b2cac2bf4ca8cf9d3e50ab5724182417334e48f0fa7d99321cb2f877ffd7c75dba4cf09a3c4d0531bc35ce50965839ba5f95877376a43876f34e09c381c75993bcdebf08f5ee27f92ee3fa57aca3e56e7c70bba1a0036fb3a87c32f838f6600a563565649053d2273c2d5c93c829aad93390caccf613faa31dd96dd1f1feee54b177eddef7a0c290040ec03532fac74adc57fec76d252d8a1c46e318c81737e84627bfdd595335fbd15deb44f1b740a5e0a734f88b626cd22cf19c87e5dafdfb35f569ee957f7c2d3ee026fc6428a242d0ca2ee9d01ccb8e9d6de1436ff2f0cb34f3dc540f88a9da34097f0b187e4745bbb4fbaca96af6db6ea0b40ac13c8a65bcac612cf3c525d6d67829c8fe267e5274ac6d70b9cd500f0b0753c55dce2139cc6", "1", .None}, + {.Gcd, "b8a2d22e8abea49202a19319f0d1db408bcaa1777d7e30af1793a811495ac8b0a9beeb69f29ca825f6e316d33a4893d7c510f12cd9712228faf9084027d006b68271f9c87985c76eac1d6771c4368800f732e3129dc1c36270422589a75ef8df0008319f4d3668f6e5f5244fdd0e234f3224c310681efe7f85ccc4f9fb5052b29876a3d693ed80f555429ea5c1f9d55698a70a4ea36265b921d0fd1ed4565e6a8ddb50b548e2e647cbc1ed229645f973641283e9b510dcdb5d61d81dfeed3fa778ce4ccc84edce5061565c6e854c7a5be9919e0c93047bf921f16dc3884d64e561f1d5e23db9084ff31aa390a081dabb1a13880db2d4817069b0e6f748da0c13c7b6daeaa75b47ae11bbfb4b3a7f5f2ac12a7a9433cf6edb8245973f024ce59149e45a0fc631dccb04dcdc2c5689186a237607d0e4d398f0d79ab28aabf70766914d487ed4134720092572ce1e29f5ca5b63856c750c2b52df0d9a64e56f45108c5e6eab7728980e83dfd3b453c5d34987654dbb9cbbf479cfdddf852df4ddb98f97a7ffb4021ec68e19a950bf37e982f39f41b2482e74e732fc3da7c495c2146bba7797dd7cc618989b11d30ed7157f8b4f566032dc38efa824bbaf4e50f86475bd3d01efa001cafda0eabb8977cc72d782877520e6334339c72bdb552f1993fc65f72796e4b3617ccb5e8492c4e7e5c3657a0eb07ee6cb9806607024c5744f", "e72a0ea6899551e5e29d378930b26ca7ddf2553ce34aef75596b49cfa7be3f0c0606bedc89c1dff19fe150c5ea35f1920077f3a9fd9e2b059afb7636481c411db6dc26593387974a9bdc9962c7662f663ec5548cd4c5b329db96c0eceb4a981c9d5fab9aa726d63106e0a433cee8a5c838ffe16c636781159739283cc2855752af9f6b69bc2edf12bb3c966c4c30f9b1698bbc2aec4154499274d1ba27368ecdd3d45ef83f5b89da22626adff914b83c0dfc01979c039c29d5463429867fc5ee5876aae5299c6a7f9816d23c52caeca1e442efd320b890ee492b669f8bfa2b9b481c66a57031c28a05cbc1bc996ac34da8426706dafae478630165a0b1e52db00bde318b3d928ffa6191e74e9a580bf4aa654f513e7ef1f49b527a7684522cb1f7402431d73b028f08a3002c4fcad7ccfd7980737cc08386af8a7ca122c356ab34d3a646a388d854ffba94b24eb0e04027e82319197a6f6632be928d509b594b917ae903aac677a3acd7b310c84d4c97ab004050dec35a77f291615c5ca7a0da47418322cf287c4da03a25400ac6cc1165d39fde743d60fb5e1a2b9fe64403e07c31c6ece4f79b78004e0b1c1d7bfb296207a0728fbd2bf34f50c95d4ee5e6bfe5521378a9e29fe624bcd3adce0e235f9cc7f85afdc438460b418c43d66bc8822d2fcad296758aaf5cd954369df98f3cdca2efaae478db871d0d99111d18440f", "1", .None}, + {.Gcd, "-1e9cf48724e7eda6e9ec0317aea36621955207b069c416dac83659fb0f6add2b07d9052a43c16ef065f9d66d2a2bd008aea4dba8ace2fa20525ad90fbaef82db3c71b294bea54f75aba38f8cef29f90712513198b7486a7cd8bf059a0ba0dbe7e1591faed3493cbf9cd9766da5c0c4e76bc20d314078237b9de41f6ab6ed4fe9f6ed4bc188a99d7128ff90fa2ce2d73a89821893932639d6c8bd55cea1e4aea631973e12eb8be6f39f2e9a86009d094f33248c949351e4853bf93f87cbe63e3df0aef711f394500603a0a71af5a11aa779669aeeb2a8444ac54cd50bf8677d7f69bd54006d3c698224a4224e410d238b95232809e7aca83f916036e85cc7fbe12f4d0af59d75ce9742dfe6e2697d6982b97d5ae8b95d3c0d68e3f4f4c0c90890ab04cfb3e51540b7ccb58b583ec5d586555eb962dee5c728f504769c26131981f536580dc63dba52e9fd9c7fc96ef77c9e5c658b5c236531664057c4bce8cdcaf8954050fd7d731a3da11a6943e12954ac3a15202ffc5ee703e776cbff09f3d6b4f15805acf7954df5fe828b89ccbbec2946e3259979797dd55931fbf51a6670ca528c3efdf4f6e4a5e1b34c7ae7f598cc3e95d2d443e705392c4130c86ba7ee3e9cd6437483393e31b99e71b87013e26caa6c3adfdbee6fe25fad66b6344c3b20be0f1a406fa65686a707679cba2a6d3280e9fa9721a39dfd01aa32440e4bc2", "d32f4d43ace4068a174f6c4cff9923c5218f227721589e22342a4732df1219b14243e42362eabed66562b4271d6c2e2966641c3d25026b8d6ae43f71154e322c672406fbef7c696226e097da866591734e30e027a22c41fe16d86fc2363c4218032dd9b62a51102a65f66310caec5bd1cfc12b9b4ac150997bc10c080c4e158d9e3fb5af49cbcad0ce20f24df22e5967d0965b91c4fcaafc743a5bf24bd8350c3efc0dc686eca3b7cee569838a9cf1ab1854b604ff3d4b29d6caf76088dd11118e31b11e80031141bf3a85ee5c00eeaceb1f3e79cc1b4bf73592bf7e20d946245a193f96af31c6260193888e7fb8dc05502c3a9c9ada651fb03cc5d39e3e3b6c00c93bab85907546f01ed3013f0a228ac094a0f75475919dcaef1de3a49a45ed5b398bd15960b210cb222c574905dd3aa56b962dbf769b69c6b51a9e5c9d6e22134d65364ca5d1432dfff6fc7b9f1be421c62d0510f9d8cf65c2efe4376d1fff1a04cb3c96c299cc62099ec480d4a01a43e14538604c0ab75c0bc5a225dfaeace3f3e845dcbc13b8195675ff6b2aa62efc31e0a80fb51fe12dd0de48a05144d7c166bf3167d874debdef8b71f5d31b100c19edd61edeae118e11e095d5f6d9cc3b553e123dae215fc40a0b2a137beaf3fc844ea0183fb41bcdfb3c17890fbeb7d6556d5c364ec0f55190ace00d4ecc9aca574f3a22c155f045e5be0470ad756c", "6", .None}, + {.Gcd, "4cb7c17de26ba04b8efc29c3381278a8529619987bb6cda43a97615b355ced22a350795f301f953b025ecf638c12cd07185b05397bb98fd8820622285ce6f6f873dbc8ef41701e35e45fe328dc65f08e318324fab019a3ed23c76b7c52bbff9869099d935c3b43861328481aa905f2cbd1c874e224961ad701c95f9dd4d6371fa6ab2de41b0fc44d9df54f81eb023c52bb672b1c3fd6b3286487db3a8e10925f16c493a765bb2a12a2bcf9f84a7234a1b6c49f174dfa58bd7da1a1cfcdf9e17d9d70a7c1d915c17d32599f4e33165379a4fd655e0380952339b3db11367a2554f3ba882abf09ed24d644f042e08d45c5e6c052939607cac5c1e4ae864933eca3466bb5c1cb12c0cfb0c57bc22281b7e3981bdab7e80a1a3d5a9cdd8a7d5d63c8ab1e87aeff5f4cfb2a0f22c37e655c83da1ccc24c2780282ba727cab27099a412600f09c0e07a802acc457911f6d40b3bfae6cf9d42c192b46d3d501c5147bec95f615b8dc7804e6968cf9ead9bac70df188bbaa0ce1dca9d549161607a80f720b7f747938f940695eb9cb23289e8ad054ce86a0a1ae4c2dd52d28ea63126511f33620abb6b4c89b8b61a5c09db2634a14ff49609f9ebfbf3e6fc3d6e653032a06213bb06be15d106aeded8b0fc97cdfecfe218a4af95f8a67f5f01b9a1666ae22fcf7e69c399f9f4d37aa9b2128699f953d2fede74363f2bf207353309005a6", "e6317ae2fb03f2f0353da2fe6d3c235068f5003648251654126466de190c47452e310704bdf91f69a71a0ea5a77ccfbe1d2fcfcb38cef2cf9950cbc44d850f9ab0aaa57676d698de968f8ce02e57fb0581cc47ad31cff8ef457c5098099daae7366d00c266c8a4f1e0dcc39f76ff9af699792afcb752035eefad75369276355cbd8289c27c1f9698b6ea171b78f814ca32680a7ab715e94ed9a998c0efce3f860b34777fec209eec526d63151ff1ac03d970a2d7f071693b27b9ff3bf91fc0cdd4aee6bdd110ea1499a3e8fe57ed908db717c03cbb22df913a663c29dd0d2d8f86c94572dbb29a729fe79fb3d950a9cb9258d0f695314d002b351659a3df13a0422ee9f951be93c824cfa3f2a98504b12220694dd113a2f31f8185da5a07eccf0837cc6d8eb194976b94bbba289a62573b077f1e9032d5a0b2cb044595df2fca9243f973a7c091f73cba59cbc80c9242fa993d3e49f5e2905b5b6a1d2d1be15c3139eb696fb05007a025b770c24e8d14e4fdbd8da625526b4871f9849ed1d99a63b341daef1049e4747e427b2cb16a387fc181ae053f29c6e2e1b6065e8a17caa573504f782b1fc913ddd387812b7733d2d654b03a70cb4c60f52bef97ec204ec475d600fcc04cd304a3392fffa636c69a0152cdd36a1d1526b4dee4d3d8f1c16fb38db7f64ab08670e44bff7c9e0a29cd224a90b688a15a93c5e3fdacbfbb61", "1", .None}, + {.Gcd, "7b56fe20e063836f5f36064de4fe268faa03a6ed2a455c2b65cdda41471d7a5126c3a3d12d1e0d0524f8bbb4b4a2ec6522191a3f45ff39d08da343fd743e8c40159f8412efd810d9a12804c74c1df463460f0c6da4e57d5940983fec644306bfa5a2d5aa52d9ef2e1a1abf52a890093958160cae62042922ad2cad747b34a97bd631ad5b185c3d96cfca9d299c32d02dd75bacaa9bbeb458f0e5f46cca4be8845b5df3740c3191cdd3fd8c610a4ec282ae7dfc4a87bf0cba9e6b52a4f744acbf42af6c87bc0c3c96de06c464d75ec0dd17e4f9ec8f0a12bea61fd78dd9c7f833524a33cab477cebc0e667bce2bd68c5ac2dfdfe2cdfbfb700d24edd9537b7ece47fab8854ca05a41e615b216ac07fe6c822f87f6d3aa267a49013041cbaf206bea324b210ec9321a1e7600b197bd60eae611910d67952f9a170e2285e4bff6e86a1e7cede669599d1f851e477dbbb5304de05b766171ef5f1a0ef1d2cf4fc57badd2f6a9e2311c99bb1e69f6001887754a3eb1076dff4910809073df3660bd1b2a258c20189696d2d517d3fa8e00bab19ce43a4878f6233c44e74830c35b122e3df78393f7197df2e833bdfc93f5d287da89b83c620899392ae83e284384446f35d78a0349b7edb04e854f21578bc24ffd95480426c07455f447bb4c3d47dbe7c547d3d05f675642c42f8ba79ea247289295b116398a5ce70930efe34657e0c4", "4ef8e77d798741ac370d60ad45d7623beb87be6ac1beb87188161ddbf66a622f4a67cbf95ac217f16d34879b446827d8cd2ee729ab945610ed7082e9b4f624bb52159307e617df4e1e3b9df378f82db99ed5efc767a6e5251842203ee892045e76197fc9823e5fcd4f67e62b1f806d99a5cab8f4fca5a42a83ccbe974a2d7abeab7d79862fda489d78f53f99e291f136640d714d5587965e62aa9101a67e7619471bd1f4b8e9693523c11ec5271b8d5d955a13f04547083b4dbb2b7d2d689d562a1f810764ea6551213ebd90d6dc122199cdd862a3f84228719cf69cf47fa443aa774db284d0473bd3539f3de4cd9c638dc25ac9ff51da06257783ee744a6a591a6dfe62c2b292bf2daaee24a4f6c9cd5f7433cbb9e75fb76ccc5ee351959aeee70a1c58635beaa9c42906c8173f6d1341448b55ef149eb1166a814490e1241ed970ea2fb917396e56b0112a6ec65c67e7e75096831747afa713a5f8e635702b86800bba761817ca67d8b5e0757b91d9bf3e9164789715df38231e07de1c10660f1e29116b9102c4ede4a607b46a8e75eb335ecb0e5fc023aa07934a40f0cb74a4ab6a299ba8f1395b0d1706c85e595dc2f0445a399abd3db788df48ae91b0bb79b7eccc2bee9a54fc1ec66b6dac66d8b6d236ce6f062baaf6f0a40c74b55c5e8f954c0bf872fdf2422bb1792c466100b36a5c9d3ca9d703be8b3bc1b2a40aa4", "14", .None}, + {.Gcd, "2543500d2472f4298d7d0e32c1025cd0a21e3e9dfcf3b2cc0b08264f8f847512f050ea17491e78c043fb142eff4b8c4486e8572e1279fdc3d40457cb00a5ee049f6f1e6a29e92aec7e7bf933a3663d9b579f1d509c2e670683b69d8cc47d0c5d39c4cfb201b9c46ea90ab5c79b02f39a0864e3e0b4350d7ce6e4b237c7968acfaa0a6e67188a0198d4bb04fbc46986f883125d26065821db5487f865eaaf1333d5059a1f95e4eba2fda9c9a9026f55c422bf734937d4dc04bd29742839267d64891da886276fd1465001590a7c6c5e4e2e12afe2b80555364d44685440d28f192f776642ea349488186c117e84cccac7212c96dfa8c37d766537830eb6d228ad8957bc0a2684f52ee3fe8f605d6c1d17bd94ad32dcce0c7ec79657f21a003dec048fca3e1ae110cc7c6984f6ecae3216873ef12b35a8d0dcfb6844910436b29edc04e5a8f988dee344cedac734beca0d459a24b5059e04b253bf464979d6f13aef05145519f24b3244be911a2ceba1bc68103719efadf3cc2b8efd37933065ee74824a74402bf53a4762851c95092267f5c0803ea1e9bc69337be43cd327480e308f1dbd63a34f339fc970d79aeb2a284fa6c7ccca1b36b405547c9d2cbb0c7e4ba5fa8ba2aa730408a8935707224c6edda1741da007c4dc4ace5d9c21e42912d8032bf298f696f589b50594c05d077f38b1cd99abe8f24c72e1f02b95c6e617", "24ef24ddedb75a140bf08c95718e41018eca078735fb2bddd20c966087f5a6057429683fe2e6a777b6ef4422728812c82d106f8489960ccaf7e56edc87caf2ce8c558a2aa59684531a72781c71043799746da45debda2fd51b5f952028e0ad0027602604e389e600697b44ac8cee8c36762d4d860f2589125844550a4dd5341a400cd2dddec391e3d3a0086c834c9ca017df1c3afab739bd0bd51b3236b63bcd07fe80bcfeed3e8a26f0bcb1e3fb7b48521c591b8718e468d3622ee9406c0cae605457b7e73f774e81e97ce5de31129027846a2cbc9d31ab4fda007436053994f1ddd4f92387cfc9790dbe5b96e4edc08010d2702f28ccb11855eb76ef6c47e82125542e3953ee5e367d8177dfd2f63987bde2772bc3108754cab58a8f0e5c58413d49f6c6e58ae13901441291146d8bc9c3ed0b3f97eefe79ddacefc2408b22f10659a2cffb970d570bca31303bd4f0e967177915938ef2643bf4d402e64239e9e146b3145e9fe9485035a225a26da5760db62f8b511a8bd01ed40a1780535a49ab7bd27b2e183c1b403a27228769e488972cd57c43630091285e74b5beb5c69fc7d2766170667cd3498d1239d59cf39fc897da42a4ca8ed26caf98211c0bcdd380c9f571505c0fde277cf4e6fde2112d1adf100c19eefaabec67806ee71f7bfc323dcbe327bff2e722fc599c28ba7dc13ddc309d95eacd6d6dabcabd055c02", "5", .None}, + {.Gcd, "3ec8f5729484e3a5cc3ccb90e981e1848ac8454f903a2db75523fd5c541ceccb1862ba130992414b059381252cd9dfc68bd0602cdeba5abdceb24439830a03405ca403bfa5a106baa47fd4efda6d2510c00c651586fcca63402c780aaeeff93817264d87c2b1085b24163d2a0678526234586cc1bfba6c8dae8e0bb6b004e02d00f6d72c9a801482ecdf781f1b4e7e41a50edb4c897d5eeaa0e47f59aca8ebd43addbe26e603df71353f5ff78f11930b28ff02606199856258e7206d1ab14d93be07597caa0f6a2ebfbdfdc291f4e40a0364e4f4afe17853355c915de246ad59ff712c94ed17c6c6688df35f261878ed6b4ae2e254ada6fcbaaf5ea2d5a0841b644754e3bc5accfd30f0743c49beea5365e63e11d558a90e96ad13a283d648b898281477b5cbcd95f21b3483f459a0d1b526616cbd27c6e76820f5b2d97d0fbf901018778b17a3e99cb0687a23ab444d44f4f250e7274c8751c60fc2d753779486222de6c8b08612fdcc56a825734287edb13f95cfc94f6ed884cadc4cc70c2557e3944d23b5eddbad5b6ea0fc26ffca6ca2d9f3ef1d8676a51c37c833e92543209a7ecd16ae64e8c53d36a832a9847b2b36be4c5e4276264ffd5a875124068d148619c1b03ad2772a24a1b98ad2c247dd4e67669ffba235843a1d24f340fe837d7efec398523e396d2970a0f48d784679b13f8b05e19b9f87ad4f57d586a3f4", "acaffa36ea6014468231df723670f056d53a59615932c4c724f5493c8d4576ea37b3377ebee10df7706a14e21ec5ebef51230a649b1ea68088ffbab8c44b997fe1abe384422149b227d11458e6c49fc86449286d720cbc97d64e61d7993873fbcc30c4ce0cb13b188c9e2fb81d46fbcf46f235682bb0fee3a2be0429bb26cd9974a02b0b1c0bd5ab176a6c587c9852400c76d62b0dceec6bac5f7f29f484d66ffcf788988db69fb4a22db21d82159d2641a83a94a3f8b1bbc320f775072b5d642b8aeffe1966742800811f5e55f29e08c6507c889a49c2442df6fa584b102d85f00e76ede38844b9c9b83727441ebb5312e51e2e2d210d47d4cf7d6a8a8b80b779f3354020f92b6fdf2554da836185488c84c29590fee6f302a68ae05086d2512fab0612fda617e39b3130dca0eb4bf1c6bf757ce6df3b712aadfeb43cbe0734e27a47e90e9c043dcf49667311919c42f9f95f85b08c8eb188651f21cf2bda67b4aaab38457b790908b94b4ebd5f9beb820d1431975bd32eb9615798b699d559238a466f2799628de5cbc3c54c2c314c615c8c324947bc9211f42ee445a834a24072385f5b3d2e0d8834cf1d387ec20a0443663f28f2b3802108eafa6d5aefeb18950b5b54db2d59d98946dbf9344dee949bf36f8befbc18bd2650d309fadc61013f06966a4539b5ae826eaa7699c030b0e16e83e8908d50d1ade680b94f08e5", "1", .None}, + {.Gcd, "-5e38ecdaff75865ebf93fa1d45b5172866701b9e2abedc7dad74236f1653817e6540cba0b1c0621e6a4d806a34c0771bc769de915423c6e02d3772d43fd553af29515ce05b1d5cc64c214b7fbd32039ef40ab0a7ed331458404122b0bc5b4c4e5536d009e564f36bf97e0388814156ac762b04283ba5225f5356b7fcb5859da878ea1228e7ca54c1b79d82e5cad75f25d5e12a67d935e27178c7b0599665d990ec02517466cdf3ffdf1f1f3872c282df2319d310d19e9dd0b57021c500849085576240e3992152272dd557f6cd9dc66e03b458c9f1c21fab85cb022cefe5076586242f258376b58c91c1bc9a756d76d12fc2164b4b90207b42f47501a21524a286242e9badcfb20ed3667f6e1c475e79e16c34890c230fbad042190b53de44f89bcb3194eb44036bf02fcddbc4716eb2d2ff8279a6b7c7fecc8bfe87ef75247f695e1be945ee6100d60bbf8932aab41e4828889cc0917eb517bd7f2ff515e77b1803600bc4970a99d41b9a8d4268a3a1866232e5aa4eaee52101c225c5dd1c95e78f194134ea3b2cf81ee88f43e084890234db85d172aec55bd5905dc3b10c7f99fa880c935e66adf5a27ce0b8070e6b7f62681b95d50da4558f805abf761f3bdf519b494d5ca4b97ce0cf7624c31a9307c37bcd64f17f62eef80ec12ca55908c82ea92e6f4682651c1c021f4922f189f5808f192381db771beba2b33acbc65d", "3fdc4ce237c9640867e7450605258d1ee7d801db5a7e288e2a0338887449057a9e38a38b16f5fd4adb9a64b2df0ff17d2552b29114322a12ac2cc85e104c60f817229bc25a1c47d35d64ce3944d09a8e37febf2e65222bb53987184104feeddf0f9ff00e264e7df2bba4b2a15b744458b85fd7e4c52f2e6713a883dea40a728e4ffa2adc1979e004c85ab5dea210277007040234ba55c91d6f58db0b7fa8e3c7a8979eaa96588ce921be52f1ce7e65fa1eb0843fc429e1846ef1a4ca4c7ac0d213b6e937b9ce8fd2708eab6129b39c54c3b18eead504c9606e833ba285cc6735129e24cc0bc36a1b7ffd4da49999e56da1b915d0f345d47be665b1067e5ee03f1fcd61aa881d4994fe4e7a37e5e53477a50cbec73d3307f9d4ca4ff7a3674ddd5ecee31750fea1afbb6e8fd9631447176817f684bea2777b75bae35de9a9d1e9a497a2347a97e3ca138339aadf9d33847f3e4a90102ba79703ff2f64743acb0818e64daad996d63a16b7df792d4ade057489e0ceef142a4e037f6bb94ef966b0e17942a6fa430f2eb5f679d9eb0ff06f9d40b2714be4672c2d4edeaa2a0707515efcd094a2c8cc796bb9b798ee5eb8eee36639b46d451c12ffd0b8506af21fe4eacf47d0089685c06084efcda0684754f89ee364f8b039e2daa26787d8b27186d1a933250a3dfb2ccc078de7c1f2bc8510fcab166e9678c18a3ab4839f0481c7", "1", .None}, + {.Gcd, "-86c8eb4d3ffcde7ea1b11fdead3259f0967464d79209e1515a4cdbd7cb2d57bf6eafed3db48074d207fe1bb08724a94f81efb1d953591c31f7516a01aa4d2569cf7ae4c0f019fe616fa99aea472fcf38b3d36f2cf40f34d9288eb000531c384081388a207a192210f45601302a16ece9e8f214876299e442e329a6477b05a503ce3802ba2b5cc24e61bf0817acaf0e387a3c91495905483915736543f8397e659e42af001113eaa078970915801e987ab02a0b70780c5d52ba67b75cc994d26a2cf9dbf14124cb4f19d574526756f11f83b9bb499fb6a7c9a71961668d2405d20e71740d832ffc0636f903343f0dc138505c6afc1c73b7d7ffb750f4d0024a138fab95c73e9f2bacac8400ddac75b34d234c96ff325134a88db96af628cc702c20a8d32393da790569a8dc470306d33ad80d027e7865c34ea34c22459781ab66f27569f447360dcfa74fb1ba04a4fd87a18fa899cbd2965d220a4c2cc819a50f6221c8478cd907638488125e8baaba51a964e1dac8bdcf87446a5ca43203d8430b67279af04afd620a0bf39902e6eb87a3a00638094e100026c694f502410cb4fffafe079105a1ea940b98dd99c4c86f9309a826c2c5bdfb1818906bf5ba1f621ed68fb2eeaa46b5ceabd59c469f2a8d4fc2165f486d58722c81af531e65c9bdc5f2c5aa9731898c498fad8e22bfe14643c60a0200576d7bee0f5f0ca96c9337", "67972f3367cd503d24a14a573d123b85c884048f7df0f517b3ace6f9806ec0b753acfddf055cfee81314f79ef7033059fd6e3e775f7ba8d3f94417662e031f6e79993919e4b0a1cebf1db1f106b4e365e09d131fd6e126402e89320570fb8a08a992d29a8de4713fa7e5a8d9a8473e497c2d17f653f70013331675e9af0c2a08c10f667d726f1d6f6837c037e1a075ca3f7d20fb537e080541f0ead381f534017c9c869f7a2606d80bebdb762987412fb4078bef7a803623a8be718485017d9ab5809632d69b259436880c0d03f4ba49d1050854540889e5944a79bc643c3e22cd1ced37d689eb7f29c24b383792ffee8e2fa1ce891547131893a2ed725a4bd7b11ad352880cd78aaa0483bea40044aed71ee9d8588df9d259b162cffe8ef81329eaf756df1343e07c136680a3aed8e126cbfa28b39aecad225ee64fb08295a813be2183d71960dc6dcde60cd8561b1875c5977a1adaa14d9034942c41ea1a24f5f9106be4dd932fd7cfeaaaecca12f49a8d19b7e4bf91131202bd5346e97de1435b3ed18bd34002213b85cd31a1dbe4bda27d190962c704e7bf1fc577413ebf13dc13a50c6782dac87fa820cf8c601810738628dcce133cbd77493d909155e88453755b38b73ca884e3eecd87cd6ec505e6413ed7c145bdc1920b149165dd00fcf197ee654ea3887e92259d2e99e5b3f2fb9431bb531be70fa574da39e19fe6", "3", .None}, + {.Gcd, "e43b805acd8d3b7a2373e9ffc94ab27d179732934d1bc2ce99d14125535b9dd09d8bc68873513d5cb49a54722a96f61e636e02f658cde76dc6be85232873f9afb1a965275cb648fa4c6236f49a7c2133ed71b374af9d6f888b750a01e88bd4426883406584de51b46b6bf130cbb425bae6113ea549454cccb31ec59be2d043c268d79270f2e23ed8edb311301602a6df93f59b4a5d9fc791594ddb2325a1a702fbe5ce2a503f7ffb5225e416335f40d4847c5d40f2cf5827f430efcedc24a88c0baf4e35582fa11993a2364f985fd0a5640f20c18f1a57f6bb92e9d810fed8fc18ffbab4225f564ef7f0e5e49aff9bb49a6383b40fdc29dc973da739dbae2c4d9655df4f4d50b0cf3134e4f9bbe36c89194ea716e50fd2b6cdd5baa19a5c309c21708a4670570add9034f1a9fb00390bc272106f4b3411acc081382fcf246745811ca5992b21f1f46dede72acc1e09dee6d5c6d0408c1d99b8ef396386c2452711d6c6cb4cf9ab3eab1316afee365bfe5cd5e02924bc57fdc40677c2e188486a1059b181b712e16a1fca693af52dcf7fc609968747dac35f5a1d34ad966ae00b1b671911816b74a24c4b1252525658b05c3ed865095fee3e1d29babce320c2659875f23e8846fdd0c26cb7e741fb958639e62eefe02970d445c0139494a4a1fa5fd5bce5c25c14937cf0df9b6667de90f196ed17839241ef32879032f02a8cbc", "297227ddf82a1fe88c99842747ba7910622c44e0292cb77e2b811e9cfc484a682815b2a2976c894033ac7809e635c2ae8c71503345faccffa2568d78678440230d7a680a69b5185a083028d5805093da38624a032fcb91e47fa6b43531d5620ee068576a93425365cc81dcabc8a42d330557fac26ca09a8bb71c70f7775199ac088a1cb244705d1f3813bcc48728354eb1a78a869e78fbf9c8e3352a6be25f59a907fa4831967b7d3a070cd4ad4bf07928dbabc345b92af9c29ac88759dc11baa34f339c7ea68319187cda9e60c53acc04e75c147e6e51a2d04f5fd012b59fe3da1b4f1d7dd7d7bdd2267c4346661beb0a1b3c815abae6c484186a10428547ce4796d11ed1c7f2d28ae424ecfbb93bb220fc50a7401786dc658593d6721c8bf13a635b5af0166f0a32424e8cd7a3d0ce8074eff10ae1f4f6bd60304c733cad53ed77771651d591877e622c28d78c566520ce8cafa3c31bd608fa09f9f4b1c318b73e1a0456b34d98539e443d097b107ccd949c717323a82cecddea151515a99fb32362f3fe98cd5d344c701dc1743df869d2d80e984862f2d74303d65152ec2e767377a5b2163795084d8310287cd41213a9599aa168535b3e052131eb5d22299c7e254fff4955e527da081aa77c000eadd2b5e96c1c9b5dbcadf4650a3ae847c80aab29b80bdb148242d205f845609ec33599cdb628017273ef84874d636b2", "2", .None}, + {.Gcd, "fbe45b9b4ebdd793a01d89466e7b2c6656488a71b4cb1bce767bd8213f717dd31c6459579be1a0ae8248940ceb56e4a2d46c185f500ddfd280a21ee0d16d87681362c571f40b2764281465009a18a1ae275f0f91bbf4727b97adcc9abc501409337daba72ad82289c03594a6e6f0d2fec9da0419ae98852290f33efbfd819dfde9bc467a115ae4c8963a793c93a23a7a53478cd9ee620ef1c9cdc300eca01865a8db82f4aed26b5f57ecd6bf70771fb200d15ad4bda15eb15009a795fa173179f182fb493b34c7a795572955f5dccbd323d6c9159bc1666924bb9d792383f52e938e6add9d7e0ae5cd736f74e32d325da8d11c0c592d3a838fe632a84a01bc7bade446a9b4cf2a7111fdbeb6d08f51548111295c7b061742b5eeac406f89c112d7dc04d808bf7a23ff85c931b8a8707ae71fd5a934a8b85509642fdcedb35077de1d285d7ec364a93875053cfe35fd4ed7430b6f78920866cd09d243fe7b160268ddd575d965ea3b5269fe5cb0db485c14f81b9967dc6fa742c1b53e554e2a3b7a562b9fa6c8742f73f10b381692fcf3a674f1ac498b5b5fafcb700c285adf71ce98c9bd1baea833e5592a1c31e745dbb0f324c668ddff8c5661c2a155941983ee9c70957f635bf1eb56616e6be331bbe3edeff6fcc31033ce5d48323e9880918fd2bfa5d7f06f9dcddbce1a12fbc8d2cb9733a5d24ac5831b8f4f6889a8224f", "3be5aefb8a8fae37af25f868b37aa2851c903725b41aff23603fc557e5bfb24dbf538ac9ec4a29ef0cceb88e6a941974461e09c0163d967b7660404237a39cfae933c0a6fc0101040583d254a650f03b3a93ad1e6da4cf4e6568af833d19e706f10634afcd0f79b34ad80902dd176e8a74182c0449a43675c23bbdeea80b38964d944819aaae0562e3407eab3803cdb48a63a4a34675ee88a4a3f0aee765e009984b1279f524e0889813a3a401fdef2e1aa64273d95727e2146ed488702ce86146c9b795f88c58ad8370e6f9803b8d1dbc0506b0ec806fd34e4b038906fcfbdd80ac14ca3d96ce99cac4f00cf7713ca36df750943aa0576c5dcf1474b2a0b827538d3475e28312973b1c3caa787627f1d7b5ab82aad91633ae0155678dead57ff230426fe8c381e80356ad19f7c28ace8da414946887667bd943baeace47f5e6324c0db1942fac153693956960410420d50ab87d76284c694e7740c19a1e5d5562441bc401bf4ae47e29247a7c74556b159de5ba8a50c03cc1a0ccc89b3805cc36b3585623b205387533d4ece3d2f7950506daa49a1ac393587e8083f4e56b85fb4e8452f7ff892fa7654828ccd8a8f885dfbecfe825b4ec3721a44a4b3e03694144d8ee5695bd9dbfd665e2166c58d9fe6b5cab413688166f85ade1832ff6ece23c17af57b4f345f15f0b7c44f37035a95725c70a2fbc8881e3270d7f8e66a0", "3", .None}, + {.Gcd, "d747e0f957dd25443f56cb387e5dbec45127f7f13c1f319943d80df2c23ecffa6c78435a82966ee8ce95192a72cff6aa2a8eefd538b46539c5e78c2b83e26526b672180ff5d1bb85b19352ac8cc290710f4dd8fa837afc714b902bea5e93e414ac0529cd4b867abeb9c1924c97dffec0c9c461a049df708e232d98bf16efa65b44fee2646ef64faeab47e328e61f6d67a2f9d5ff35f5657c61016ebf300ae8e5c04b742d60eaa8139c6d63207710df09abc531fd6ec0ebede6a6f24e189f105b0253e405d389c2f75564ee01f6c4e8496e3e530bc0a552fe53c8e7f8e46e643a43f458d496f715c0a31ebd0cb2b97f58482eb26eebe5023685230274ff92896450f6de1f430d4be6dfd6b478b58f47f4d43c5611e0171b7d529b13ebc03ced18af0d7002bdf4f88f6b9eed467ae52b26fb6005cd236c562fd0ab3f969d172e76deaff731a2914e4ab1c0c33607a18e3dd6ef1da0c1923e8b5cb77aee5b94246c706a10c2afd1f37b6f600f62da09ec23d6a34031e70debbce717dc1df4d675ec62da28a006c1ddbca0952b37120368d9c2485b952216a72f99922b0c5f4065b638748d5cf1146028928c0102ff251395ceb40a7ef056942854536442928cd33050c78c8591b9c35f6d5e01f41b6f7185fa19dc22135a103ee762cd46c317581ed27684f4808712ba13f7db9a47df38f49fc5c06f7b6cf1086212624baef21d2a", "11bf2d551df233f8fac58af0d93384c1f82b92b62860e8479cbd634da1e8dd51f8fa2d0dde43eac8e54cc3f81c4ece8ab66cac7ef475b551e720ca6f9d5f294b46fa4c8c7c069f0bb60cf3f22b45f44dcd23167663a9fab634113e45587c50af2c3f2438a4ee292bc93c91595fc790776f038620c7a2f23a68d6246efbe3160c033c30e9c7c622bd9aacbc0dd3cd703a36d759abea2392ee07d2ea5230c0eba09512e3fc3c8d450f37a537e2dca3cea85668f25306fb14500e24f86dad0e254d065655cec2d4aea6a22271647340f1fd38bb83ff28da6d1e5905a6815210eefcf1f087064aabec4ee7fcabf576655928825efb34e9ac0721d634d6d5b82ba0ccc637296ce62c030c0ab236eaf2b04bb45f722dac9f0fc396561b216c1ce7e3d42e6ace6ccaeca1eba1437296b8cec4d1618f67dff2afd00003d3a5c6512af1fdcf2c267de280a054d25cf60c5ff5ea11e10a000d2bf2556fbadc01a60d5f2a97a873c24425676f0865815f153ce85766e656badbd04dfc057183438394b99279a5bb4edd8fb6a7a33134ce202ebfcb3c29f24f62b4bed11c1bf91a20103736841ca0490a0a219cd7e7e5ff80b58c51ff167719710d632d1afaa57f9613f16429ea0d3f68c3d71e68983f87754a6c15d78f9bfb65bdb8c16f6326059313cfe06277b1e69af82c364a6d7f8982111389e360b093193b7b4f34069599585e7a9e7a", "62", .None}, + {.Gcd, "f9c28fcf9f3abcb6f798904620ba3311de4a6c688d65521ffb97085fd5000b34286cabb3ab43bdc8b1c4a0163b40c8d9ca2eda538b429cbec515c630789fa70138e1f51a1d04b4cbf8122863851dcf0ccad18a3824abae124dbcedd1adfcc0749ffd14b26ecf30b09a7740a1c940e6a1f7a3caf036d0dc087fe6ba7243cf19165e395a122068819420111d4c84f64c9c3616ce5e844239f26badcd181d8ef7cbe21e77e537da9d2d51cd63c6e173c130ca8c48623692f2646c34e34387c50bfd0a59f49132e2ac107e9887c453b4ab765f0e887a195c8b5e71e0a8e1fed4f44f4e24710ae1cc947c922e43543662ebc3848cb871770a7632e675b0b7cb93901af4ea41455a812c411373f0d298f3b82b5871326084473e873a7b3e29fe1a45c62a607a0c95e7738382942cf15efa61354bca993070a5ae742a94a41b7876c469c818b2501e86d893123e3b06152fed9c59c19486efda5cbe0bae88644f46ead3b3bd24a1521c291136399e6f14c6f43da905cf583e7422cb5d88186d5130c67430d66ea7d6f13d9ea80d2c8de9edbf24127f9b18bd3f2e8c700c063047cc64462585b405d268a4042caa28e5a9e7288b352ba89b3cb4bb9f8f5ff52c38d0ef0f97630a46ae5f1aa7a127529bef1d93b2e3bc0c1c883fb2b1a446a46894a7561ebb9eeb87bbbf655d6b10e1d8d96a001614a15694e7b5483627985e6d326b7e17", "a96d25b0b1d4fd9acb0c77a49d4538f7537d2587e232c4feeb2bb699e3460b4e103e8e881b9b5aa093b4385be84bf2c7e43a300b8828062e1de2ad9375b9ccf586085c2662d739f98d0565897b5550c159e1e3578555d780eb1675b16f06a9e95f66cfa1f57a5387644c71e0437f3fa62b69f990dea913477f0306202db879712b6e2111d15e07fa033f805b9b067bd1a0808e8c2a0ba80f5f2d6550392976a6bdb0b122d48124b02a501a45a577a8d154025f7c9b452b52fffdd1ae65357544a6e3e975a43466e48ac423e94e2dcf2e8c2e3b6da0ef98969f3f1b8d55a527bb14549968c99ee8d5a5295d2d68921fb82b7815c97c1718d25e6d31bfcf22dcbca371ff0f0d058064bf3afe86d5b04177fd398b80c288e05833e6df10ea45b8cfc6817f0cebfdcecc3a080168838a7dec803b486f8cfbd44b33dc059386da22cc952d903f00fadb26cef5b66eff4f9be185b7ec6bcf4291fc5a679758f4d15c05efa8cdf3722fbd8f9e9504edf5329d34b4a642790632373c968b1257d657684b6a5eba570121e56bcdf0b3c6e6063075cee3f95bba006a595e1455437b7f8309aec8f03cfb73d3b0e8a7bc46ce7b8ca0f843ff0491bd5bfed5767f9d0c979d3a0074f9f8707a55b5241ddece3b1031b58685ae78bfe15cdaed698deb2634134f916a9ccf159f73b7f9cdd2b788d9d940a9f761df8e0823f0c50fcb696a959c1f", "1", .None}, + {.Gcd, "-db23b81a3929983317f31e111c33f081a17b3a24372683d8ed6cbd3d2b1262d1a26d1466c97b2641b47d254854a76232bdd76da11a5f6b09ffd579ce64789b9f7375622c8f396d84b963d06051862c1cf9086a717fb8fac5722dd6961075a0769b04b601da6688fb3cbf94d455acd3e440fd8da989e1e93c75feb9b00ffe5d4442c619eca0a4c4a2a01aa6da462c9a5ef93f03d794e84b0a29dc2b6f9f5ab26cf3bfeca79d43f5e5f9c8e350ac978fc02748adc079847e202087ccc23263ca14137e3482e842ad4ad89b317f559d0a98383bd1b89c7688933a2cf19511942ad56dae01f8f64dd39b5c007d166f05211d980563cf8f6c91985505c240e208722887ef0c537aaf8e4158947955f60048c6b46c7ff7ef52d0480416c1ffde867538db2f0338d2465c30d80e6973bc0130ba8712f5a12a87076269dabc71e302f168ea8933f658b62454efc6d98bafdd3af34c47ec86ebfd76b3bac250805cc5df2e842ef77804bc98bf71adee8cf9e53e0f87177a2d9d0654bc5cc4c0802a0eb1159ecd8ae9a077daa1997827974e17937bc97bd9747f1534f4deee3a7242cfe627bdaa88cb1de3d1a0ce7699180343039352e7b137e57d3e3bcbcfba093a9420b37d524d6c88e6403297dfad0ec8f3f187074b585eacc0d9204dc620de1f6b4b1beec46182ca6c1d28afbb230cd66744df49d29d73d33d06f8de398a203c71809", "7831bfd387d19373d669b5f4c6181b79ea722376b1f5fec1d90b1766b64c4c077461255a51e5712461e14f55f5e6afd143ba73878a40bcbb842b0816aecd66c3512f0d55b15aff839f27dd2e8cab6b8787bda469dff0f35be690448726cc636da094d68430b6bfbf945f13564a08b0642f87cbf1b10bb2954eb0ecb8c582dd3e75f6ba60a225fcd85e6a32a3555c31a8017d9fb983c9060fb4c379f1fd7dcc9488e99937b7fbd3111b60549d2c8645502040e986430fbe66ab1f8e81ddc97ef8aedc408bac5d6198e7263415d57d1d8b87bf9a588b7a2c18bd856f266f6570d595321d23ffd103d21eeefaee1c1580cc56747257bbac2dfb62b7958a7c67486ffd46742b2b5e6b65f9081c37e76edfd95318f68c9985dc0b0bfb7a5fc643a1f9ce24d4d11dbc76244f557ab738b08024224af2929c13cd3141cfacbf6da4d1c76b37957b01268963e07886dc82695f6949203ed586e6ef9ed6373bfeed97355db4721a826af3e4d4d40f674e01322047902b119ff98871e4ef057e61ef3471768ac81afbe3d8a24b712aca7e81b521aef8548964f24fbc0b94c24ffa3b69c9a6666514a1c6444f40ea5b4dc0fc44eb1847a3f6e26226a21cf9ab7c50517c678710af9213796200dc3502503b102a3e0ef7f9bd63a1e103b3a0f5690fcad2f52c8dc115f385f3c48c95e0fcc8205b20ae4b8406dda57f792ffac4e63eb4aa4ebc", "1", .None}, + {.Gcd, "6ed77b9e5caa9df1f76c392581feacad6413e6555438d127fdb1cf2c7466c4ed306fa625d88a5d9513d725885bec26c36df1d48f64729422f199681fa5cc5dc02fd7c3c7072090ab22a520c7a1b5afe26bd23ae0428bebc1c90cc5fea70ca8cfede80eb64fbc8926ae859ca05c3a7efe19f1ca24d481ce95c3b93f5f96b0ee991c749641ffd34eb0d39e7bdaa6672b613dc690788083ad095e6b21dc4f1c3f6a61d03b04da54c3b2f47f3ce0ae9a73ac3dcb3eaabb0856ca8ec81efe7b2c24f99502de2cf399f8b4c6f0057d3dc001c0ddc30727d59681c0ae16f1775c0d6c7d5a23951997ddac77bfce220aa503395614e1266290075e632fae6c5bd115aad985b63c5d6c409fefdd5dfedf68b543ca028e307f5f53d551c90ae5e68f5e3227f202438a40fa7020decdb9388029c5c336c5f8fc6e26c76f324be32f0ed52950161719b0da4589ca8909b59406596c0ac7d270695534aaf9f81e3f6bce1e7673ddf433ff53ed222ac94f8b3444e3f7466450fef9f367b018dd0cee63c5d4acd60e201d4f7281849b72f976ccb5c049c0f86099c0cdcdc3a6a9f83dad6cefd5efaf1519ee158167d2740fe14160dd6f682637a65153a374fcffcb7f59f9892056ae6463171f4df52d503bdd1c6e1ad50afd0637dc3e640fccdf285992b41d55810d5791e05fb33c5b3d99d2dc8217233c2174827102f22b3e76848e1491cab38d", "4196139501a54cf5b169761f9da4af3267fed4be599f1ee611d5a96875fb9f95d7811aa39e9466626c693da23343f5c4ab83e0ac16820486f85396121676a1a46843d36b1ada578011e4e97b278ebf6b3e8c8c32acf3678069fd61e47c9429baae18ae275b7e9333c926829d05a0f264e06fde92708ffa30217255ffe4c762a77e0733b3270ba0d7936686be95f294babd0212d9c02278122a23083607b81aaa0b72cd116726fe8e3452a868aef76404f49a7acfed92322557378ce4f49cd8de9f977add8b4c1b4cc5fceb596719e9aa0620c15735c11fa3bceee3105d6373e13ac640b4700484eb53df48904f89576fcc527e540446929816a42478c123a59ef62dada3e020f5131715de582bee0c936b0c439290ef8dff7f2ba488d89e4bf94e91a42a0c227240c53045502166a9ed7b9d83565b1ae4b64f7e1a89ade1514a59691cebf5d56f8d096472762ccafca7146af28bd9dff5e821694417147a5bd24afca6db0f1c199120feeb4457447495d6ef05c3ce4497d6cff0c44b478463e712627d21c3e2da307c7ab6cc67d03fc5f62fd4617cf331dfb7fbf988e802ab4b1ac2d3f1066f2580ada468717d2925794c0d3b1c69848bb061b8c1df40efee70bd6e5de12ed6a8d62027c6642339c279f7cd5e6480f8ddedc8ad344f6e25de9863f4baaf68d9ca87101707cfa7faf2bd52d439bcf93782c21790d4920805f17d", "1", .None}, + {.Gcd, "ea0a299edc83c70eb98143d6bd2cd30696868ec5892befe25194f6da3e1fcdc68804d0fa0b13c95ccb9a7aa563e091ee7a95d06acfee149c27e47b61c586df8f50b7fcbc6c7dc071950cb38586f4a573f5a1ea45f8ec2eeb0b635216fa07023c988b6035871b74298be844637655384efd997329b2df2fb99a0d60e856a4ee7e5fd89e6a21e565d32e8e8e13be395da8bed1cbdf1142762c1f3b5f89253930ea525f5359c25de5243cfb0dd8f391e5cf99c44867e25b86260537f817bab300433969543b9c0b50e1cf68920d3de47caa3370604a043caab26bc9d7621db68c1a27b21ac98ec8ddeadfb220bf8358cd311fb99f8b0cff5232eb6c7cc9b9d6f86202a64d3371484b1edff6e893e433dd397e09f49961d5f117f8e0fdc98e999d961524c17a92d52ee10d0fcedb68a27b10c70fb75aa402aaabcb24a7eb564fab2aa4522fc111376ee5ef99de01abe08b416aa071a7b5bc52d1020cf348f43873283a0d420dd3ee78dabae7d0617b169732dda7472b0105e3de8a9456deef81715cfca143864757bb55318662be33ca23407074f611b1fef1ae395a1ab8805f62a95dd028ec8615ad4bae7ed007568810625eea95e32de9705c335ba36180680e131bfee980148f30bbbffe53cc997c0e480c2dd61da46e438d987c55e5c742f3f96791957f0f0b54854d56eeb4b38eb2c8bf8dc5e456cfce663f9d16a2e169658d", "72950ce76e4208528758e0b62cd3fd4f4c33dc0e24ee26f722ce92df4c9e1c5da57bfbc45e3d7293464488267ed24230b82acabf6e40c16139e6648cb95a862d5a64eb3086215fb04adad219afbe60ee0ec7aafa2ce28d763d77470673928375f2c119f3e7cc8350109d0074176ce3b7ebf9a2b9c81400a89f57384149389277c52075552940a8b941274d8deb8aabd69353fb544e8dfd0098717b3ecd56a7aa7acb787aac803c107b1f11ed226c7029e179bbbbbc8a4b4c240f95b669e4ca1b1c78da3c24240d8363d49b3373f496588528172f8d33702fb3df254beb853e595c91c97bdceb9476a8339ae653580ae01d51c73276c1c3b433d29ff36eb6dc0a67d84494bc9c33785ec3fbf0cd22deb5c9d6acfe7ecdb468fa59e3f63f4253321be667adf9202557b46d168be34e6ad4c1ee092a3d3e85a5cdc9d997c324fdbfb563ac43bfdbe91fd8bd9352e9350f51a65c2047da15fdf75987d61b6bb72aec87db343b4772645ba2b330fbe72182bc78e6547b262f490737a844f1a2520dba7ab30c714e4bef8293b787daaf7bb36151cac39ff1715cc2f06b18f7e6dcaade8e2869bdc43e305a43d2326f1b8cf481d984eca6bf06bb56e3badc6962858271fa769ace4b17bd2f96459a8d1cc7b5ce2a134f9e44600f1619708bd8f3cc4d10c1ae9b6d10acf81ac82a2bb2a68e8b4cf2a6fdf9af79b9efd7aeb8a73c156d5e", "1", .None}, + {.Gcd, "-557e781a86c018366bc521aa24c4c310378bbdf2ed0fca610c2672d5e96fb2208a79033aa4d20b745e0bd236dfd2fda7b90fb974aa3af3f478a743fae130171086058fdd0f76b927afb5cb36401c15d7019067cc320193cd690001455c0874b4bbd09e687e9fd50576750e1d9a38820f0cea0c0d3f977ea9efea0e0eaf55fd19644b4520699fa57317b13609777920afd47b0be065f4e6695b80be5e5cd8343a230fd75fd29141f82df3d5783677760bff154a24f27d371919c684d0817bfaf838918f0e0265968019a80de71ce54be13a79b0b223158d8e780b0f80bc8f63b4e8c9d234d997831c73bec9a0fa5668dae82a469ea2b588fbd4d9fe633f8bd2e3110f14c0b748087e3e364296a020c0a8e1fe061418f3e5fc85103f4c0b76bbcb2a5b3f88c66a826b0f9f5304ef52c3bcd08782b9c5db81ca8aceb31398d7ca7ba6cdb68a86dba8cb0086f86657a0e27cc9ac27e64551f233a2b21fb768dee8c6ab649f0d1829721077cd64a242fedb82d6048ac63b140616cea15296dce4073e32d15dab5e6ef42a0a72223bd2fe3fcbb9438f8a278d5bfb3a1b44f02799191741bd98546f6cedf78ed6c7bf91cf1bb7fab0adda620b6075f450efef6c982a2bfb1cd1584c3888dc59d18600ec7696c6fc89c2d525923c81a3b032cbc0644dc7ae912f6601d914c5fb42a81c500e802aadfa85fd2883c28f8397bdfc26fe41d5", "2844e3582355dc378af50f0ad969424d4fd406a6f076fa96e9224a6ae905e481f6555a16f0522605e693aa0b4c01756c0517a309cd04c91008c5dd512cab61ccf40db0ddddf18c57d7771a68c6fa8bc72c62099c433f0abd5ab1c63ea7e58015b29ad356a06529d9c86b821611eb75340c29a6f6a8e5d44696ae2c40cb46888ad20f54f5106b7073894e5e323ed2a7d6710fff36e028b73c07fa77f5c4401e59dba836a05f405f16c879b52fc3190803a46ccbde2686a4a95b9d1700c029bf006e99f708e55f922fa10ad042f66f964284fd03c38c9a21c971c356e1f94af217766342f2109c6de4041f53adff2907fb6f463faec3420772ba8ed834a6c25902ca5588d8e4666e062d7d735b2ee94faab47bc7420230de041a749c0e6cc7c96f49cfc3cb897deeff9e50d9498a153a35f1614893b6608dd4948af1f41a5fccf26b4c0323e2fc3ba443641baf717082dd84199988be79f32c4f2483164dc96c8614947d6b47b4ecf84492c28c2dad688d16234487517e26d01c98f948ee9b50ffc1d60613e143f13967c2f467fd6f10c9f195a8eafd8e165e15b9b3328a3a0ecaa2c214904325924141a17ac61f6416b0907e07280b3b8ffd6ec0a38f850ca19846829bd8c1acb5bbe96bd84dafe63916285084e9823c41501f9d23ad0194a047fd121bd7d2cd4ff9643e61e2b3df70a7c8739623e822dc8a66ea693cfd90bd36", "1", .None}, + {.Gcd, "-496fb467bdb2b8aba9dbdd5ad52306336b57304783b61eb19a72b47ce31c0f9590629617bba5545a3cacddf5705a6bf0bc6f9c4008e9bc51cbf69aeb68e1fa414b0dd48a62c93132d74a26bddd71841b3aa7d05d6c5349361a4db0bc456b3af02e78025edfeb1ffa4d724e4104812373773aaf3acdb5fc7635c1f946ef88a643c238f4fba5ce2bc2630dcdf124db6515fa74bc865908c15f0481e6ca9c2258d937cc875b0256d113eecd486f6e86f822e5ebd6688394157e922b765d0b466c05f55b160b4ef0f1bb01cba93760ac90d27646cc1574fcc34369c36eeb4eab45749cb954773285e71f01746cad271d6d512fd7b1ee5967cf50a6adaed241de575d232a43363f338c2e44bfb56187db2a8f04eac57a7c72725dbdc873146c80327bb135036d3cb3c2c1e4f6e13b29a1d857cc1badc5703cb9b3a1bda70daeb9fbcd4326623d7d8a03350d5e64b6a094d5cbe6f6674e57f859f70c20bbd23fba25f237bb9da3b7da903f98ed31164e0216f9505632fff9092b7898e0bfbe529959cc6f9f3949b164b1a46aa50485029fb246f4c576f4dc51171bd2602574e92ae86416c593706d0d9d10cc16588a756c2b71b5938b7d43f8e4c46ff0bfda068b7f54c4c8632246d8d97dba57f5bbc3035ccd5c5d87d70098cba479d3fe980ffe3bb938aaca61df97ac543fc8cb164e9f6cc2641992544df04ce3b211de621060077a", "a8c8f88855b8d722bffb9ad95c32ae160e7b7cbdbbd61c5a04ed067998c62c9e6c67abed737fb5feacc87a517fe5ebe65c8704b09cacea131ea4fd5091cb16984edfdd9f017fa5beef9b6bcd5e2c93007cee23af147243cd74f85594c81896808860ba7bf04716c2ca550c98a2d85293a4fbff191eb42bc7b266380a9a923d1d3ecc0ae1db71d078a7d0e0287219917e04319d61e555ff315cb0c63d529213d7a8ac03880c764612f574aacfdd3553ea6068619ed47b4095e886ca46f85ada52570db375f22fd96c294c002987a2e6449ad4ee51fdaa4a49b896e877452419d6f59f3515820d68261076a05b159e36d2bf559e02711dafbdcca0d2c2062f086362a06522d952a2a180cb3b9c13f817e43d52debb340d9fc898123135951424c044c36aef25367805b94659b29d8f372f00fca2a037e7eda48aa785d358cbda48f79fb3951cbae7073dc97f43868a4aa7e4fdc1629c289757001c23943fbe4f5b9e00bf89e36273a4e0dc823fe3039f03b8dd22cd5eb1a43c9d6df89209c5ffd42943a56e1a47a6f0a1c9eace97d961556d33364352e8592daac1c6b2970125d293f28ef3bd7cd2850ced34f5d40c3b73145fd74ae79cd76d925d5aa1cbc32275fe81ffb46e426fd6d0fcedfd22f7961ea95dc8ada2910c6c41c9a9dbfa7cc410ac9ea9219f8d360832eb18b783b51686ddaa4d051aaa72ffb258cc740c4893b3", "1", .None}, + {.Gcd, "20c600e0b0df947ea315804393014feb9bd01f26211700febbf0a91179b3892e70dd8a5ff8ab92c2559cb5383016825529d10eb85fd1320ee334389d87a9b26fe1685d22283710aca1b46f3ee0f6eac157525a8c5aa565946acba6aabd4511d0f1f87ae536bf3eb99ab80d0826b197d77129b891985accd72d79db8477d2166ce887cfb5cba75eb91ed591c7b07722026620f965da367c88b80151b558b8db4c64db781abef795e68b15d363ff359c13e2c11f75484826919128209afe5c4b572dadd97fc20895446698b41a2d3beffc33ac772fcd335d3761ab41918fb1076588a119884250de5ded638848942a82895c0c59cde91f054e143eec7db6a9ee3d973fbebf1d014ffaeaf19a8f433ce680b3b2751a4f72d36c9cf61af575b8549014db5508df1b7742cb9f61c176cba0b2f98d4d48b8a2bbe84dc6b8cd1ebd6383b440501ec66d372e0fa8550357d4f60a10d776ff81e7c9ec02b4e62fc7ca58ae03b910cf21e4c5222674f7ba4827528cbca1054da515f1a37d3aa713d2e7244c0d61ad2bc47be6e7c46a45a13cb7e80c0577273c719c6b6bafcc8aae11f7c8afdc6268b54a04d4c0c7d86ccd3b660bf3a7d7942c0f60caaeb0080ab30ae239dd80a9dc3c86024eb1095e50ecfad9d2d4d5d3f7a88a56379a84c66e88a355a4479904d0526f277a897ea61ba06ac863da7f5f2afc423f47f596842428e37f9cf3", "f2057c7dc66150980efafe9265e02f0e09630be92d670831cf040a73db59d8df0a054a15b289a27b6be660c47205e69e78b9a0d3672fae18b3c61c6d1eec611478f1428ecb37e2c521b1bcf538c46b4b9b177c297ca4cc177431ad8b8d451b413c0059dc078a0be3c834f8c7e4d431d96c7e1a043be46fabaddc221ad2b1c35fc9863c26ca19e6077723d691633b9761fae0c0e994877a7388d9942b6151b723561e15ba6a3842c679f48459d89bef4a6dd3107aa391771874bec848a71a8a14227fe89147320f18610e622d6b7d78acb840ec3ea3cb811f40817b20bae92d7b1f328ddb722145b7c6234ed059526e3abd2e09074bd66442c6561c2773dd1c25c66d1bf21e34fce68e97cb5e1f151b0dfeb69397979c3cd26b8a81fcb51fbd0319bb090175c0bd0206981639357a120c302ead4d246ad80011384ed9a39b62437dea8854b4b9cc7ecd25845fb916ebd4462affc01dbc4584d40464807530ad4db899960aa8476148993dca8b58b1b61c1e75e1edd6d64f5629e12a1ff31e190b0fa8fd21158496e9be0af5a0125c205c9ee9f5fa3bfa21594ea883086ced967ce17ffd2584ae0a8918f0845d6249ae5fa47a9d8af99158068d7060b81ce10ddd5a5e4616cf7bdbdaeeb8ef357a7bd57ff3893996535547033fd65b41a29fb2e2f9a02f4b12785d4ae03c9790d4129276b6f289e2d11668eeb0707e554b84db66", "1", .None}, + {.Gcd, "30be3c560c7790a33dc9f1e22dd56c829810ab3e9bbc369ff81693e2603316f280c4963883b374729add0bab8e52de106179f044ec73d901ca78ef51265932081f758309c69a5b95c174bd185ed5b0a3423ce3792d1ffb0fd1cc998dcd51029338d1c0c98c38a92fb2c805a8aef15333a118b5faa3aba0787899a54074cbcec2285016fd7abce0387cd470788f7f0da4f2efa0100ebe7d0e2422da979818cdd8e65f4817061ccd6514c0bb686cce230ac0f272f88cac221f7d0f16dd3d8e565e4be53e7565aa79db7bdb02ff8862d24efb0a65f0ccf93dfdaa488da858d38c1a9d6f7145a08e38d57988e3eb03587caebd705af3c377367184ab2331df1ab23d92453af79b8f537e402aa93e55b88f59baf4845e9b2d53fe24951f0aa7e95dfb9c7595eb309788730ba8c449f9191715bc8245e911aa038e72facd18fbdd4232c72456931b8ab7e8cdf9bc8c2009c7a293da3401b3c51e9a50bfb3fd84a049fd056941fdf41b6325a253f956e12cf2855c140b29b881f99743578ea380c368310bd8a77b67964724430f1c913aa9b17e25e6b5c4b22b75a370d33cb5ae1e1c9c09abb21097345f0fdb440f240f880e9c2fc490eee082d65888709c717c1edafc59b234d657410671cce2d4db75aaea0bcce9c097e07747c9423272b79667c47e472e43e58dcca74eaeca410cc33192e44c4315e34bad63050d13cac1702296b", "ff6b549ee5ef0f27a55c53302edfa8fbca439a0f3822bed4e91c77e77175fa33571bec53fce89e3099e74054c6f94f22b2b88f907c2e9d05aaf74f34ea07997f959fda4aa797fdec32b831d9863c68979c8c7521aa54a5971b57ad31619c55d22a03803be5a5a6f5304aeb51b2a69dc93c37523716e9698d867de045b6a05b84d32b39b0f0d4c188db381ce5a27f3c88fbcd320f402b9b9cec444b5be8df2f0953497cc5a36d394891f6fb3cb656830e84fe6ff0189c68c8b0f7bb9cd83275e9b3a9bb19c60ef18357c5eb937f9cf50859244695b0c76884c42162c35af247dcf26b4b5559c6503158a7761f77abcbd319ae1f38bb6506662472d36773e488b25fa8e84ef8d2947b8320a0b764da699b14fe8051b8a09dfc53990835859dabf30cf00ca8e6c153516e086dd6f10501f1d4b09c0064dd53781d83e5087c21af7e165517375e1819811af0f0d0d01c6b68cd59c63414fd6d4c7cfefb4ebab9bda6ff2564cf22f646f7892310c7e08e6fcdfa1b93ebbcbf34cc8e5d6c4ed6a94b2448b964e3d9d2be57538b1927e9f73ecc4334fc282c4aac882de4f8b1a4657f9c149aabb31033bd33dd384a975acc8a3524a8c22fd920bd2a87361cccb3153a7a739f5c7f9ac161512cc19416226db47ef4250bdea14bb6c1fa6326faa1ed74573ebf94dd279b9ff66a4696032e9b58463d3f19850d40f5050aaaa3a67fbffe65", "1", .None}, + {.Gcd, "37063a69ff76720d6bfefc04bc39d443e64efbe268a064f75b741a81ee7ddc0adfcfd1380ea4d7bcde731bb24cefaf0fe090775c6e36a18a9e8cc78fe9b6e10b32c31137d1f6c66d7da46e51fd3a19954f9e8a290410dfc4b107ff041224b7500788bae6b4b1ad3ed820e85a1be4fc519356f580e6aeda2c2019932d37e06286a56c0ab29c7efb65b0d35236743c13bd9e507a374cc8f54eaf71b1098b0a61945e375e1594e3f01f085361738fdc703c543ca80d983a94ba4d536506b613c9596de3dbd724073498e3ef69391c05a0f20e13dfe452a623b151006c990ada3224ea2545d1f4a157398f71fad613f21decc9814b3864085230b4e934b1723f03ff36def4af9bd6d62ee1a14c4c66ebd6104a4315f3145c9d82fe4f868774b981116731649e471591fb4eed48d4c33374761813e89ff17bcd8dc7e4843c96c4793c2b34043e562d8d26d6bea760eb3ee0798afecd6c8c24d0815eecd2d599d3b26de477cec81537605a6e5aefaa0451c7ef5f8dfc5893958c7d61640716d52d372039c20f32d47e03a081396e319dc16e891b9f1bdac3594581dc7b9bf3ae2f0a7fffb57de4df87deac779c0a4200932c57a7b94a78b052ef4728411b708cfbbba162f27dde00248ee34f31c6a58cd0121ef70319780c4a9022776c14f6fc467cf77db261cbae9565f20ad1771e3b8c7bc6c8b53b7483299e67f07e1974ade6e91c", "9ca4c02f77d6c91b48c76180e4d98c80e6cac216c326f403143b6ff4611294c0f32b2cbb2c77f5d3a911b4f89a88c36816c5cb0b858f48bfcec6961feeb00a3c42b62b63630b16f4dc7ea37f825c30c59c509f7047bcefeed13363e5fa785f2d4bd12433d2676e77176e4857933afaaf54e53cb9b37b79650b1f4afee41c21021f2166795db80479d327d5cda1208020196cc96a8edd7d3e139abb5c2b2cf0d8ec00747f661c6198dd8cd2418acbc14852e5c0117074fff6ee117155cfef05e40cf17f6dd463bfe49f7e97290f0bd2087e83713bf14909013e1d4939f450f6ed207a06767b15e56d5bb1e821e2e36298601b9d5d8fd47cc0aa793f250215fa8b9ef3ad74fe72b5d6592f42a612d90ddc65369d3d8e5640003ef7498f28ea3a67f327570ee916e4a935dd89ec18c24a44f71eec8a79e78c7a30cd2b5703110e65b5dd2902b1212ce0dc285bd4ff4d904f003b4546b31062bbfbbe9047a2df5603726c7b83ad83b73253ce9334ceb6499cf47e9a1c157413768215eda24dc4a4424e6bbbf47664b7b7403eeff3cd2b6b96812736d1a70fcf781598566ad7c15f2a40bd51ae3bb33f7e7cd6eec8a6d4a53d40cce0d71cff7fb59c98fe67eecc8d31eea7a7c31aa102783bbe0e3823648777d1472cea5ad0ef9ae234aaf13dfff015b33e28fae1970baef71157537a5f162c3b86ec342a389239929b028eced2f820", "4", .None}, + {.Gcd, "179440932854560b3c42d1f04e0e8bf89a77f30e103d3fd08d7a4c265cb8a0afabeb1c3589a3204b53af2f867804f23a8f755d8a67eaeb087bc64d9313c3b7a0b8cc2a5ddf94d6e7d3c26221b024c4a14dbcc41fa077e207cc6ee763cb0a1abf79b5fbe0dddff6367de6ace8e9068bc07fda80c6c21639badea5fa30bafb46e912f5eb7cf863ae5e84b976e034fed23d0f5d6ee1079d7d40518b055761f65c8fb92e413fef713eba5f7ea79dc4e6bb798bce29642c241b17aba27f172077cff66e026a3a483d55ed13e0603c5f020673b111116970a64e848d38f95d6f43dab58abb77dc508efc7335fb9a08318a20c1215d0c0061d9f63aff4e6efd6e1c57824a917e7e1d4f796b0f6af7fb230f2abbd0d8eb1385c97fe1cf8ed7b13f767f05c2c6ddde3df8e7ecb0ac7c0f2952468ca723415cac22914a78700d2fc6ccd87eb84a7d418803aeb71527cb5a27f61697476cf840a053f049f82e8b01e25de810b7e3bbf93bd3c9d1abadb15f1735dcefdd252337f508fdb5f4af9bac6182802c6d82a8b7e2b524d9c2264a6077291100cb51400416ce8390e82fb048fe474de0d4eb9fcc23fafd9fca2b62ebbe1e4d80e58e3293b48faa70e424b9f1d0c31a5ba0cfbe6d398a73bc96aac73303fbeacbe13c06e54daeebd1a960248fcea0adedc596df0f62c7cea2078158400ada6496277160f7c0d19c3440caa89e1941a64c", "98df0ea6a09dd8b8910a451473599b861b279bc62253659d0fa5ad2a961a388f9bff4e83f459dc9295cad44407b92250c7dea594bbebc9f2267ee38e043d9f72209dd2e18bc4b75a7356c817a7a4745c35bf7f56bbc428f518de3e13e78c62d4ce1c493961b804c6090540f6b3316146d62c16d558396cfc03f123db7b7cc1aa1daec4e2c2923d5e78cf28bd239fa1b7474a531b3bc580f32232700eb033b2828d6555e638d632f5a618f8da027721aabe5790cc82d87e78c3b34a77e0f0f8db94656afbbdadf9a7102af148d532d23f92014bcf33c1b2b7070bb5427a7c89afca644c59918ebc2bd754e245e41c1d40dca9e63f67fda04df646950afc65538bde8b6f97c1b8cbcc481d064de14af4779f7f2198091ff45cfe4147bc2c146bb4a766f4dea4301677e0ca910b4e19479dba0dc3f8e433503adaeccfb54f5cf325a9ffc1986f9737a9b54b01044edc92ca4eb88d06e636e56f1f92fe0d6d13f7d2784f45514cdbde5caa7bfd4cad7c6602a4515ed2816592a8964556f46d7eba1aafe554ff5188bbd79f47236da0268e4cffadbf9357dfdea3c81d8c2f4044ed21ca6e82ae41f4008298fb49cf31a6a870d5ba61526125e536fff5add3b78b7cb34c043de170c4f8d659f96540d5b82cb9512d6738607fc1a9b8eb7bd5abae7f3c25085498dd7354547f6d25271ec4dca41fbe082eea92a49034c7c170f3ea0acb", "1", .None}, + {.Gcd, "-5722963c4c484be1743279790e0900528ed16690f41247e4b223bce071abb0d782227b8761516f7f1a383901c50140b526b7b22aeccb907ff7354f6b707e83c97ff45abbb0ef91d7d43e02f53ef869f43ee812649b492b48b4f8ea007966ab3b6488bbab7a295a881d08283ffbf19d726797a43328a18aa9444532f6184ff52c5dfdc5beba6658e3681d43c3c7b0ad0d9416b35bc1a9f728bb459fbfe8ddcd9980a686d40ac0fa666345be5d47dd1ad4493dd6d3a05eab56a6dc282095257e31b6b0ea885e9e5415e08c841f9c96a648123a4ad6553cc029bfd7485a03fd03434a657fb31ed71c7f5cc1442b3f8f43b916dd8c1837feb711cec476bbce1829c0aed3dc5fb1915797e112934008407ca5c29b1ac5e4ef3f76362d0c24eea3a02009439b6b89357e3db6a0aa5bcb50a3e45ed3d2ec3a728dbb57b80a3dbf1235f2530639629b36b69f8da3673f3284347d06f96cad581a4b4878f769201648eef7c85fd969d98dfdc624dcb348255fb981b8322d6e0e514661606d85e39c74e95e1a7a2ef83614e2f5630cd849cb8b1d64251820a6ad8bc917d2182b4deda65b7331bcf0fb3313027aca6b5425c03d078bff81e982d6444b8c5b1694f2f7b019eb28d121123361f1d6b4ec5f076ba56794eaa8a91b3dfb01ce653af86fe7e1fe2d76b4123979b690d1bc33d854c6f579e6c14f2a242aabed6b91efa5becfa0a5ef", "4732ee61abe07c26fc29059079d1103cda26abeac0c632856640c0bb603ab5309c7c71646e178d047d02ec5866b7c29125055c9b5f75a4691ebe4b11a0024e4e05525c07dff692a5a3befdff98c1ac042ae0a8ccb19b8da915b4335a66a05c7e637a157ae817ba026110ce7950012df75a167a278cc420aca457a694fe9aa099378f50cac9931de22c334df452bbc0406c9f0fa2fa6c7d81e0c36791b5b1b217b2f85ebb1c86d32e6af97f3664f416485c94a52c3e6bef2c7057416102df4d784e16890d93487110fb133063c3e370f81064f4f354d262283f734b6b674fd6cfe36d7abab33ed8195238ca4407bbec16f8f06f7b87a8cf81a96682a63d4bf7ba1bf2a87be5354c008118def3c956a34f37ffeace6fc87ca208f0acea7961df92bb5c3989211a4c8fac7639ecb70e1e5e4cbff29d58e2f64a2ff0ba9619f43a2c7a44ee78e5398ede30a0bd982fe65c47bb96911eff8a583abcf92b7c4d2357b070a19fe1ca383f0edea8abd83b955bf3df8838407eb89386d6edfb73c5cd72330a66bd6c148923a65ba74ebee5b1ae7df99c5d586bde9b09ac21916e96e5ac8694eea07dc68e43320032518e5185372f33e4262957ea5373feb87bd3c7f138c451967ffc5219d3241a28bb5531fde79775577d55cb0e4d23150fa64ad901273da96660b42d4ba1028aa215355944f0530755efc7617c5d7096299c35707a34b5", "5", .None}, + {.Gcd, "-8130a2d9bf2ebe22dc096e730418cc23dc109ea140e1b05d5a02d9889355425abbc049c5adf2f8e3e91f9bcf1e6779c0b0e5feee33bb925585fdd5f1409b8d6171a4115b8a35599ebfbd19062fc0c5b2cd992fa57c5c314b734181a53779f9d5d4815b474e75660c4c2f87adf4a623290b2dd7fe8e7849d62cfc58032d19731acd75bd03eca263be50db1895ba18cb4f0600a235b71490e3424a56b8b8a554182ba65b9e96023f6c61ff2b69265dadb2590ab58b4f5140ec83fb62592e4f5f51d291b80149da50585473a7c0d94f0d8cf6ca4212e222b92b8da8b271931d7579e5d10d14175153fe4ad1ed3e2be9b487239afd016ac848c180d3d6bf0da9bed0780208e9b501120931188dd35942601126566f1e05d8523771cea047c46e173c3627e87ca28239b09fbf33a4bb5f9394ab30294191b6d9c8d57f9ffc0053e61cbb4c8f7ddbb4bca022525f661f4d1ee7a533b70604a72993edba77cef1aef19ac4969882635616b9040e1769d9f1167c31c811e013cc09eb71bfd24874f6b72c0cfd8be7a8a518826a6514ec5fa4deb1bd4aebf610fc63c3fca480df7b5e3b06d1939def51bcf9a9220b3b811e3f3dd6f2d75b5564cf5ae98902276d651f550128ffb1613b79a228df2ad63ff66979cbe6938f285ddb7a29d3a05286debcaeac32fbdff4bbcd378d80a95c6bd56188d8554fa1ea2283f8fb38005b8f15b4abe2", "c79fcad595f4fdc994262cbbad8840bf6ab24b8b0cb368624b4d6804a13e83c8fb73413a678b4fc1563a92150c3757a6dd32f2ca307cc01e3059998e63f09dbfe1b528639d11842d267b46cf56677bf12aa3e5b3f13cab2370ffffc1bc3ff62603ee2fee200b9ad66a04ab41ea610beefcebf20bd5afae93fe73a6790091181b499914de163d11ce0b9a21e0e3350f2d86ea887ce7412879054677bb953bd53c38a37268dde7f50c2edfc074bead0ded469cf495773ade13f83871584807a5682c92379abc67c0a6f124b91e557180724ab5b301ec388c8e3c8ebde9aeeb4b47eb08f6ae59b280095210ad81b923d0b7b3e2ea9e72bdc1ed1dfe2d20914957f5be8c99b3641b27b4d4e3bf1cf02cdf60867a8294dd6b9b35cd1e632b20fb859940e7072a698b7e3b7317e3650c27c413842f81236e6fddb5bcf94f0d94a77cb3a0b6c96227761c31ea9d650434c9cd430197920aa423018afd41bed6d7e0f09e64c9ec04159f07b5d818002a11f7d0f5647c0e89559bb2e89d6941490c2655dbaaa4b029cd5d76aec7f86875aad9c509ec66332c2b27b4d629c2d5c6edddf872c7f2af084b161396fdf6efb7b338bd4a00c7850241c769999b9f10440576c7d36bbfb3d4ac033de0e1668649e671486a2f5ea92cfc5311cac4399f86cf5d1feb5c25f17bbaa459f63458db7d6669363d7e22bf1ce6a2cbe8ab36cef386cb4efb", "3", .None}, + {.Gcd, "-5aa7d0d111dce477a687d0a3ea0e3bd75a57a495d11abdbfbdff6973cafe1c38707606ecd16a382a777a1f4058d043fe3028e0fbfcb7f4578dd2b9097b8136e20d659cccc92f0b78cb8f1f9667ca29959311d10d8de3ea8af54f76116450ea7eac886345df1e4b76a394e1cf9c9dde7ba1a9e41d0f3946667433beea0cd06ef4d8fad749aeaf47b84d01dec3768665cc5e95baafe733f6f74e91c0779561c0ff6c210cf8a604036108b18cb42e1088a2158041e18daa9c8cafb92558aaedbd4272e78213f7af7ea24e54c740b7e8eb0ab7104326cbf9dd89e936d3bcb625480b6df214bce08906d753fdbd6f6d629086a009ce72b4d6b4eb694db981a44d50dafb108dbff472fbc68fcfebffee4c982fd85aa22a3c38faea483f3cd55627f036464be66be6a9e491ac69cb929e06b02e413e1e95b1cd4b31896ea8b24cbbc44af5add0c820dd8f05c85211a1b5d678ddd9ed5432ba399fbef52501a0763936faff9eaa55a11b441cc075bbe0627fd94a1fddbc5bc91dea05aa8fa32b892b3dce8ff4afd143031195a16869c283b128fa5558b27ace0b49c580a386b60c8f87f905260a03424640a8b004d626d179e818e529ca27ebe1db8ca1d6b4fc07a301b280697231560e311d66e320544ce19bd6a245cd1d74bea2c95597a8470c6705fbee8a27ae7bdccc3cad41f9999cf1be3349243a262f0faa12fd1202922696b858", "a278fd8eb5b94a0380b4e16b327dfed532708ed8f95742ad9583535c17c04e17dc99ccf1e94f508883ec0b836fc03958640c7a285bb9103f89b3bd7ef22f3697236cbe500c1945ceb97f22f92b30f4a5c0cc2ba96aae4f6585ebbcf1785c9fc95d50ad49a4828dd638b9023a6f3046a78f5cafb292be3a5f94d78a93726e26d5ca708eeac6962a31b49706c74e82d2145284c8116c54caafd5b88a08b245d48c4be6ce948e3788d12bcb4ec072d014c7be9cf3d1797a8c464bdd177c7c767dff3058701a7cce5cf99c962e3c17c0808cfdbd5e4e9f6d1f7a03c2556a46c69bbf6250401b740bd66e0edc3b0921d0e590f741e925949a86b056e3ca3252c92cea10fd9220d7bdfe76ae0dcacfc9705f4ed8df573be2c3951ce4b9cf9baf48094640b6d78496687bd1c7ed7598d81f3809126e1df6d172ef25845798c27cd69299a5385ea7c528e604d0c561c90e609fe2dd3f0baa9f4613312552e4827118eb7f3e4f0c1749bfff4fb130bb5e22e9952a1ec8d19b67950a8c90575b90894479c7ea00484a9ef381c5e63b1df59d2d5279871958f955b414729f63ec1af1a14fc2c146140ac07af48c8ec9aa386a9af88516ed7864e4fb09d06e22052e5f7e1f22c5c6ee85c22b1df369f7287026b86a509a7f80fc483fbef341b5e3fff389bac7f383463edfb65b4382d186c05da505cd0d25cd80e0c224412858e19664f6e35d", "1", .None}, + {.Gcd, "925ee6f04c33028698974346914d08752a54c2ea1f9abc9b09eab5369934f72b163c2f441612c4f8bd8f445d805d37eec95524c4dc7b2a3d90694f52ab8044530cfdb27f0827d5f9a0bc16dd5782c14ad31f4430dd0c07a8cc30cc3028d2c74920e7628abbba64f27606a4f7e6acc7f470f8b1132738cc58e4358f3577c7ce27d123bc9908f5283195fb7a7e5bd56e50ebd92f9472ede395f070a41fc5b88b4a805e8d0d05ed056f3f666caa00451e60904bcabc883938e08b3a00f88902682fc05bf5b951a3861c175cfd637a261711a3592033bc87656a1e1e3042dac0533daaea9c6a57993bf69630f13f752a8894e6a7a0d4daaf02a8d78637961e4ff5152109200f2dbdba8640e04694701f26b2115b96b27af3cd5f27189ac293f76b2b427477817eaf30ed007c5fcc896bbfd9201cb3e9277b1a91f74a4ddd108e396caa5994abd5be57f09f64db81ebf6a2dd911d26ca8d5ec08a2fa2e6b01c2f19fea7f2a75e9bcf11eaa1bdca6c900dde66284035e836c8838a0ec18221cc24160a7ac3754930640f214dd5b6ee82bca028a88b7475df39be04b7514e70392addc08c785739fa273f7687304b1cc5b79c2d45cb718e95cc6fe5939e87f43437c3d00af793b092444e0e86b643a925c08bc35b269b0aa3f82fed921db64a0fd75f7f391715508ada726d317e96aa38194b739a1bdb6eff5072dc97957bb081668136", "ecd192be13b464d123fdef352c63c9fc6fe40f44007ad1b98ba860cbe8c8fdd4a28061987870fe7d8d28fa927a9dd1572563afb6dd899589e0ba34d03cb1d0fac47ca6d7c8872279b0c61f0372dd6b1094faaf92998d472bc15beb682acc21706bd6855ddbd5a7211fbc5d9bf4a46e0fb1aeccb758c8d4c9b22de065bdc4f56064a93ef38c2016de82ec1c057b7feb4dff26c6013ab7cdc8629bb23209c2c24254706a544df77adc46b518d0bbd2bdd1748d5fa34a5ff1b66219009d15a2e4d670823cffc7baef77a8eaa305f9cae806c0ea8aebc5478d75e538d9683a6db084a54cc0e883a494af1dfa7a65a39ea320b14383ba40237d89403d0c4ae049d6420441dede1421754c2a988fb596725b2dcd7658b5f0e424d0657997e009500b8839fdb6327bc9cab1ac57d3047635c984ac87f3234784e177efd621580073f0a4d8943d0ce1a30559beb249ec20bfd7a0c9bf8dc4218b08a6014c73fe7b27c6a6cd70a03960e23b20bdf913afb8964818f38955f05607fe76c68ef01a6af5cc7f785f4fde08d458f8ac349778b8bfad501d37a642411ca68217de6af94b943635bbbf39c0565b9db926394b53600c011de762b5c759a901a5303ad9ba62dc84c83a2f58f0bdf298225016c95f714ade977becca625e300d67ec5e3d33507237fe25605c9a3650434c7f08cc73c6ef4e42235ac2f6760921bdfd03e60f30ec4007", "1", .None}, + {.Gcd, "ec6c932661b2c3c8e723a091df333780b9d48455d068d6ab07fc55ab5f6dde50c5ba2677fdf3218a44b0ee9ed5a9c711051107918555d19910a8516fd7d869acad79f22fe1140e907c87e90b8afee98de9fd4c84e79b6644a1ae255a5926659dfe14f30cd60ad5e8c18876f4dd7b2b9ff2c03a10c1074d4e10ac05a91ed7cff7d63626acca4bc484f805a2b164e7451a22e8223d90ffa83655c4b4c6e3b22f0890f15419000f9dc7383ee67332958cf49817714fb6d4f71e30c02cce16d599b905a1a80c997a31db6a99ea332e13d401d6744b4a10965e9ad7eedee2f43e0bfe9bbeeca3b879af61f4183977f451ceaf18cbcb5370b34e4108f9305ec8b4c97e57b32f778fbdeeb189f509f1d76dd5d1be15a8f7ab0611a5f0f2e85a9b9efb65c67da96565e06a2548ef962bc375776e58337e3bed84691fedcb48211aca300b843558642dfac3882f8ae77575fd7afacc0b175bb1b25169f0ef39d2dabb3b2478d22a2082a628500146271acfe44334f12809ba9bfb052e92ce76f78cb0f5c8eebd5c509b131c515cf53cc2d8e873a759dd00553e3d1b0227a685f6336ed8d391aa53534f2764a889c8cb48ec5ce846a1cb3b634b7537aff3a9a03fe08b436f9600ffa75de962994c8808b279b852c4144335dd3c56b2075931a458276762090b66520e6b8bb092c6904172a1ec74010823488aae8a77eda3a4b52ce26ceb1c", "3a983603d251bbd8456795a59575cab33459c626d94c7d4a86fce61670afd4eb6438b893a906374f1fc1f0ac26df255e9dc1b43187bca25a37523ffef052247d4bf0abe8bbb189d58a2a0f2520d058923e41f84f97620ea1ec4ac88ef9c51e1ea4ccb525cd250ef505922c306e2ee2fda879442c59f9895cef8a367b0bb1fbc35eddc83af485dbaabe6ef16ef415b4cf5f6a7143cbba6dcf6e579cb5121b7a77c81bf1203b209faad9e4df5e814ee48dde63a6587404571fcc161a1c68f678840777ea8d268e108db353f5c175362f4d92e86dd74efb59d7b573b233e2c24e7553a12d2d8ea390e0de80b80fbb2aa97f2f558660cce1ae3ca2e3c379998bdb1c96a06f32858ce28426bb30b7ce20b7e9aeb34972fce2df5eb05e86e9f27d7af8f67b6b5e14577b3e560cfb2dff14081a922a5c8816b73fdfad15d4015c37e69cf51d713ccaa14608ecaa8ff876eae12f3f554c5f6aae1a5b02e441d11252deffa53322a3e415b24e79eef0841173b7d3d89657b26f7377de6c9f8e4dc0af6d5dd6b393470c855dce9c422809531292519a73134b0e9fcb8406d6565c0818daa6b168da1366e6d1eb8dffa555ff1173798279d6e4eb3ad1fde42407fbffd4760406783a46a22718ed81da3a32792e4fc82e51436ecd750bc4bbb08af6054cf90f5b715a843ffd0b0859398a93274cd1d31109cc1eacc9051ec7b12e571a490b61", "23", .None}, + {.Gcd, "-a6351c7733cecdc303923fef767e769eba70bb688a3783c5f14faea727bfba8eaabd9eb919b139e3463fb9e49fce617d112a3c7e8fbe9ae02163d78c648e46eece402c196c6d92262fd239a36e868441b2e49cfd5fe695d45361aeb8185466d25eee25e862d46b314ffd63e8f2017fc8b060d1f4054e3001cee20b0af05b7a1ce77d2fe96fd24f221011943b58b6362cc0ec95f08f07b05d2b41c70c59dd47aa86908f5dde375cc560f9115bed5d852c3601b86b51fd352ae9a99935f92fbb330ffe0b2c73806828c27fa0ce9ff8cf8ba63ae23c1c30fa3b45d9812b177f392db034d8dc3a2eccd4c8791e73ff0b3d547bd68368b121a4ecb982a4c3931f45ea66b1a0c1b95853a2c2b5a45f8932b78347d4c4fee6f7ffc9674cbc11eacd9b40e57a4e9e52c641a941d570c95f769292278ad98b665b0c1bf59b961cfd0d316f61faba4a3c93f3f84b250a95f39c76222f083479cb380b67e63a198b9c66a37eeb8b4d7904bca7ce76f58bc6daf4ff2ce6e72bd067e8c042efe57264bed8b6371736be396d2dcc28d150dfc6ee10f51d7e8d2ababcde10041102901a839e655fa12058ea72ddddf40926b7123a30168104b26c2aabf39fe28e9663c70f9d90a2e9451967ccee57c5b2a72ee61c6bcb5f875f039965565554c84b4aee9b3ce8d75245b7a9f040d1c0013c26316b52fb12c4b31bbf2f0ef896bdb837f28747fa1", "cc7cf6037b5f8d3e41f0d5d502a90cfcebbac3a1a10a1ae8a52943158665fe75b0cfd082c4e7adae9cc6b2c5db26210ebcae294a2a0afbc28ae177bb17e85e0aee5146c8031764e5578af85ecaadbfaf708ead8ee97ed462002d38a213d81d250d6cefaa7c25acf0356f7022f8be2dd305c4df733d247165eabfee8c36a438859fea4f6b1143d6332b28fb7251be0ebd5773e1093635959be4d7302b7b0cc6733c2e6ca9e28f883c8af64240413880195e9467c59c4a5e077a0ea1dcfab73b65b76d1b26580f20b72ed7b3fcbe87b662a197e7cefcd7dbda682b92d8570504d1659be636deb336ff8e598645a7fe1b262ee0b1ccc4226d26ed7c1e54dad50816fdf2801cb6128346013e1cbdad6b4e05d7e9dcb8a349fd7db497ce7a1a2d886287190974096b911bba897a2cf3b782e4cbc09cf63e5165c81f896fc92729e2cb53d9532a7bb6a6558a9ebc0bba80a00c9411d9b1af183a1fade1e31378cf2a15a66c2d147c32e7afe1914d55ca7fcc36af20be57042aeec7bd04fdf822f11b2612e31866687fe56dbd4bb6c5eb4314f5074587f3516a7132ad8ee45773ebef5ba8656206925480c8e16e10cd1a1857299f2267bb4daa084522b1708aa67f26c1089f3b9182ba26b8b0d012097c1401be8a5ba7b0cbdc51a6f1d9fce93abca4fd33e8e68cd44fb74322b3bf64ffde0ca0c0921d4bf74372a23be4a52ce7796c90", "3", .None}, + {.Gcd, "-76a2bb166c92754c60e8f9d9c31865bb247fe7126aa43610de4a277c32c46a7d14bab07d629ee015db57c5be09fd3ba4c775ca7cd0e06f9e83a73e97a24f7af6922ffc7a05b47f0cc380b3617855da8c166a5b48af6e85d25bae089da28fcdde4b30aa8a11112ef2b65de11c3e1efc47c5a36ce6668e5f0960fe199323f4686f21784602e03961e0efc7ac77178764a265c0d20447a2f29a8b5f0a2649db1c284324510a20255a40e5950f3fc4dfa426923108e837ace088e82f8f6da3f10ecbf0f1a864646ee0126e099132976be1035a7e46ce8092b0d00cd01f15f5d31eebb91ba0e1a160c44d893ee6cc8d155a3137233d8836823ca16c58cea59ac8a172d1a555f33a1a44830ae2041062f0b664c433ab1f2d9a4dac920b1ecb9ac049d746065df9323d29c98e352a07df4e6cb14eeca5327987bd138f22ab092f71cc8e6508a1d5a1d5b29905de9ebfc200cc8c1145597886c3dc3ba7f9b0cbec89efa5f956675c1a61de078447633c10432e1fe14541ef45b339eff8b4ed74af2c20619d645f7e9c6121ddf42820891e140daf0270dd37c907526a13f34a383a8e5df19d8926d20b2f2094998a2cd2b1b233c2b9cb008b5c5d6206bc63c1ca01954d0dbe4f43c0f7ad86d57a9b771ff5d1c822d2a33c83a2e8fde453359136dbe3ac356a13aefa51b32584036dcad3e3805a8ae86c8f2e8e591af915904fd4d1462797", "10dc59fc31d7dea204961078a13c82b41d3806122b355ad294f385835b880aaeebeddde81175cbf5006368d33ec106906aad42a613904bff5874c048de86c45032df0248609ffcb5c162f8bacd6ff1a37b7a01d7bc185e9ef2c80ead0a6c6702a3bdcb69009263b5e248d94c569914b925a6cd71945bbc458b926e69b3a7bd16679082678c50a08baa8e27bd937216e8d336771cd1e1e15049d8ecd355c423efb8d85ea0b073a8adcc0a2fd677140b98d97e96d133bedf514a381f8f1c01708f41bf8e7f4421021072647abdec9ef955aa25dde2c54bfdda866e445246613d950f9aaaca6288aa926c3a893f2794057183872d4f8ebec45da2edd05419305057093ddc3d930d6ea6edcd7372d780a2bc7c064115111bcdad0b43b083965a8f8626e5cdf6a4d334199a052d4c23554ce1cd9361de69f63c31ff364b225cd9cd85df44e82a178e056d13066ac929cd5e09d428507b5a64ee6aa8e5520d5dace96b68c435294251b611788601b7846ef5be3c2750d843201aaa9364db496004c46a4412962dbdce7f1097c89cc9d91a23d336466976b47ac54b80915a590bb608deee3b4e91c409968a8889ba3d74ee10651c461160558369750e5db0eb4290f76e3d4ab5888cd632bf583ffa646b87197819c54900bc5d44a495d96c72e44228b7106e807183e4093b49d6d4f80161e78c049c98eb14c7801a8256cbfecf67e6", "1", .None}, + {.Gcd, "-f946ecd580682687cd7c8035a6e72931aa0ba0bf47aeee278af77d65632eebe133f11fa60b9153f593181549d1cc9a519847072d53ac8b586d755eba0c00f8075ebf79e5788c843177976ca2e1a534a047638e8f645b69edadd620e86ce5d15cad6f7b4c63cbf547e7101a6a3c038d821e0e2d38441b7f85bcb150ecbd12134e01755299b337597f5a18a5470f173c24d319181ca6f97963243a3c9e255169b8c8e454483eaaeff242ffe004204f89027a5ceedd701c585e37c35a3cdd2d8b23c69492f09d0b92f03b164b125ad4802bcfc2ef410adbbe7d57cb4218febf03b3f91d674b79755c1f996c63b890edc425216b422ef4165d6eef8fe73b91b86a01ab3a045d0456e1dd4d27fa1230d2b052df4d9c07f67b45351a716a941a65bc43ceeb6234af4e7d1a29c676b3244968d72186c06a1460e49d2b00d66289e3d2705c02b6fe61836959089a9e95f868452c3f8e3d90a588660a99586850ab2594de2c57be9fd51765548f68429c1a206cfd9939349818c842b3999b7d0a48fcb0cf4aa7db785ed95d914212a6bd91789d066b94964d4157957fbd32148186bc500609ec33b0e732c6019ebd389e5d31c572f7a01e620d24c6edac7cb2a3e8dc13de27c3b9f0f8459c76315879b1052bbdeed8c7696279d908215316ed31b1c38466b5f60ac1b32ece01fea2ae2d433d06d5fc1af8aa0b19fa4cd2caedc97b63555d", "628fde2789035e86e0dda402117ec3c760db72fd53e8751f2276cab1a777de46d30189596175077d0a0f34a99acff9f6bc3e98cb5fdbda6cf065f44b830fc5345ff9beed46965992a1ef551dec852887e11bffa19b4e0171734440569da17487f9e07561b5ee32cd72da37352e314f9a6f970ed857e966452e6c553470864d5e48505a8f56e251f8520e76b32a100a99bacf26572587a7a2712655a7cc53e20506ca931e658c291c6f896d159ea67a3eea34bbc7a1d1674a809ee8ee201a735912940772a24ce08ed011eeadac437efbd9ef7628049216d45ad653029539a453dcdb6f394d05a8bd1a546b7f1688078860cc0fe0f78bfaf1b2dd5dcc81ab2454669aca7cd895b6c407d2145235ec38ff3a4d25e68b5a709d5b9d961a42fd1722c6e9cd5b43cb341df7d50e286f5b6e52536612828e71d69eb6a8432e1dc59b6832c2e6c95b55bc3fef5fbd0694643c842c68a6a42287b5caccf79aec357a2ce52edca747e915a38c389d7f1d5e94dfa356db178829feb7ae284c3f97cb02d27e2261593265f6e6f0f53d0471fc189f973b85e52fa25480f3b044eb5861eec3c4f1ac64e3261ce4febd277f8b51b391779053e781825e3cd91acaca99c99916c28316efbaae9361c06ae7cb1d1d1fcc7574750dd47c52ce48a2bd9981106d108becdd8ea45f51558f9c50323abcd26dba2a8722eefbb163dd01a9db961feda75a", "1", .None}, + {.Gcd, "-3cab795b96870ef10d3d3ddbb52772c8fb87f1523dcf5a8c8e3d1bfbcc5b883a1360617e37cd22195e52ef7e64ef76868d599b1358e3b488dbc2a7c6e6f9ce892da63dfccc2ca39869ad16b4b25f9ed2ce01123517e2a42f8cfda7eec7e09f4b723d8130e3083e3d068256087883717976ffe59097d05f5f418440aa50fb3e7284c1f1b82d7e3db2e260029ebaf3676e9d9b9db0a63202aa9842562e6a99ceb66ecfedf0204f881d473154e29c57146c57b06db1cb8406c1af52b6a16ca4fce98ddf3317e88686863bd424ce4b5c42b15b1b0bcde0bf5a2d3b1d3003c82f8f4b51c5f72e4643dda36ae4090be46eb108bcf8024992c20620e8d7917b3f96d61ba8f1bae1ceba001f14f64d85dd7d09d778e09f545b2ab9104b9cc71cb32b283f2addb8aafb99d39757fedf3952b4ae0b08f36b3e77fe6e382a3fbc56e0c6aa47d432a720d3aa3bcc8a4e3a0bf69c550185f419a8336ea2d2def28528735ff1f5e157f68daef9f4ae9a81a460382c5804cb86b6bffd0187d62a1832b66a3dd2715d2cb94b647fcd1b8de2a7704bd42802e2b7d97e17645d209e992d44ca143ab891f0620a5b99a069b6f05dc17a08476db8a108e0126a659c1c11d4110e7545acf900d589ce6f4879c535b43b318ca3dd97614c0596ba144ebd079e52c34b30f1c410ff913b208217416b4341c32098e3c67ce0e8b80d9e5a2c2c8390f0d36339", "5eab3c649eea73f669074e1d9cc5f657fec670dd726e6ca124547b8970fb00ed078e4802e3771d055abf8f244c901a935de16ed2c1191b49eb9d40ba9daacd558989fe18ffd07a9c4883db09d2afecfcf51474a30ea796233ba550659e285ca36d2ba837e5721de86cb507f1ff7d840d5e9fbaa0c8a5e2a3c2b88ef0665bb07cab41053d6217031b47d8b9920bdfc9b94787d9806249e17da49f32484dbed26f23db59cf3f9fd9984073c745a0b68c780b57a4a58c612e265e821b967516a8536f572e2d304ba7b24145328bc9584caeb7af8fef6a62454b5a84517f1bc51c3323091269b2170d116444b6baab13c2df532cc668ad288dc0974b32c276efcb591d104eed3a5a3194491c3afef9aa9dec29a40d8191bb142f32fe6754ead67101828efc69832e3b2f077afd0e38c72b9fb77b9dc53c43fc275fee32bf59fe1f5989cda8255216665390dadd3ff3d7177ea0475ca818253edc00db99144054419a4ac4df3f48951f5d6e172f3af7567c58468dbed1b2ff6c449888f97254d522c9c49fc22693f9fac6c00e72d3cf2578227ca6b8653b1f3d7e39a88883b9d069394a5b9e17e55d276f5640b1a162affe0f583d559070e480f2c60d1d56547ed5331d950208c898019167688500fbcc8b70c3e113d06fd4b0ebae1790376428e185d087c8e841ae7b76277697c30b05f5559b8b651ed52c026b54167ea7906ef4c7", "1", .None}, + {.Gcd, "-958aad3b8f46121f92e1506e035713857d164c4a5c2c48d75258ea88ad45b3660afdcb70ff22b71ae0c51fe92e58a5927587a3d45d14b759c6679ccfa9a74f0e94392a50f6b2188835670b0234db06c513bf0175c382e5da5fefb6dccfe5b2d2abe2b52f101f41b19e2165abc274b4aefb4e6f86178775a0f52a648114f20af2ac3ecba39daf1b0910a6b0834367d322a6c4e4ccece92f256df5385c33df9ab1c7dda8db1f9771558f18fe98713b021d7af0de9ff61010f06842a6bcda32cfdb3500907a10dbebddaa319f39e4f49bdd895aa8405b4bb91476c9af9c559d8011d53a0a92f4eb3e9d59b1bb51d3885e839d30545dcdedefe8e5bd453c97bf50d56e2f3b0b6cbcd6b7e80b0c50a4b5129cc479c115a5d0ba7b1f872393bdda8522570a2c32d156ac2d7886fe69a0b0ad8b560e2b94024db10c3ae6502e9f92b01807f5418372a75c184d813eb3d52d75b22d8eb6d67a967662df5db7485c8f37dce339753111eb1ad4aa48768e80dc8223d16a0b796da405b61f71673c797f79714787ea9d25c1e2d537ef0cafa48e22be2be17c4cf6b719a8b190c8ba7b1ca8270f3b779c2162b6bde64d5b02e6c6646b325a4c1ca09b9091837f02e801d55e6ae22de79e30207ab1ce28a9c768c13b3a3694905d45e408902cfa4bb18b29bfe108ad9c45cead4d2f1927293c5ce6b605f18755bb1ede8ce03898661de431221d", "87c4667a0f72ba077942d20b6515716e50b7af4e6b91fd5b2f5552cd8c4f2db9911fc1070f53b9052698b1d42e677ce2e5b8fa0a78fac1b25bef9c62738d10cc3362a34c7f8606a111a9a220628b8dbf1cdaf9b54c3498486db9f0a12a0283585aa36f92e39f7ace104ca03c4430004278b6af6f6245be59ce72ae003b1ae54c8b931a1fd1cd3ee8339b55bf91c1f7b53f6aec670504ad0ac97d3341b479783e3bff231aa7a49c5e6edc2c8f8f52e479bb5fffb503365689ad6364347241ba14a0f1eee483c5155d4063933f65ab2c72eff94f57640bb1cfeb40bd1f940318a625d42c00ecc75ed08637f1ddfc52e1b4a457cd6ca98249a5709e92dc4b1298dff1439250ebb35dd48b0ae02cbd3628d79ffdef311782b03ee4f5246a78f22c313212c9816c090ae34f682229006cb6de4c686644fc11fbabb6f362423045781ddb10c69983820f34ef4a7d5f5b0e647b31d44538073741e1de08ffe7bf09759dc9f65cd0530648eb84cd3863a0faeec0b7f4571e15f60725b6bea65f8a606c03b3b46ab92ead18965e89454f056ad02cf7d0a9e7dd590b54552aad4979dc2954bfca4c5cb5e1ac1e1fcd184c7deb9590aa5a0b422bb2b27df459fe76859961ec740c158cecba86de0097d04703fc4fb5c83cc8a7c1fe0e23db6630f79b6618e904a1a06cc05baaa314be0cf02567293917925800b731e8aac265647d81515273", "1", .None}, + {.Gcd, "-1d8a328e2a53ded8c8b282544ab356a5f67f68caf03b28f2db980a948555a5c9bb2ab985cc354e4bcf9c38c31f3f5059193c7201ed48d0ecc979e0c280b8ab2498e8c4db605f413f8d781146f058412ac653a5be16a1259b81563cc06f794f7fbff652f6a2ba678bd7aea158431e658211686acf057f15cf0db890f27f2e147d50f2e8df59a6cf3eea58502e3eea89594915e88e97a813a3b9035ff626140b4e901947aa334bb9a6dda87ae06170503d9fb6ae9ae8e388952df3db023b34ecef4e5bf7c8da5c862506e88439b37f44da236dd980879e4606bf8e7f092caae93c2915306e044a980ce6e37d1280f4f7d6d379e199da7214efc4c22395bb88d0565907b57985b606cb31a50300ec64ccc0315656d0b8e8df3986494270df8335aa019ed2b7382c06f14908f89da85778499d1615840db869355afab3aa861dedf8237555b9437d635206c90cd78a0d45fb54613f409a5cd7a0e4201ec07361df432773257db424938dae245a04dc1758ead7f6bb386e8e9852ccca4f82c9c2e7fd9138ed2f9a5219a0a3ce23fab04fd12a16d02846030af90b29f94a726c3f0bf256cd7a8be752cf379dda5a55c0edeb5dcf87feafc086dea2a6d4495036d85e3d09c3e35b1c11f54dc86ecc8e1a439398c1fcff3fdb680729c3103892b00135c0f1fa247208e20e5f2017108d0ee7663c42d440d10d2bf1eca1e8afaf017df58", "5ca7d0ee95a7fd1874f4930c25514a29f7486ea13a7299e168eb1d263cdad92b798b6fe418fd97c2e88fab99ef3b904925fdc1e3beeb5fc971d20bfeb894a433aa6dd4f2136a9eeace1e70720ddc5e47c2866ccbb389143c91cd2aab0c788c349dbf9a87af1599cf1191edb8a0a852ddead6b14aca1a501a2eedea4933029d3d1041960611c9c4b56385e5ef9fe07bc7005ac1deb4ed767b60caa39cd5189c08ce4492a150b1056782212bf495f6d43cb6d57616b6e21574551dc6fb73e4a48da22a0c39cd6fe1bcfd679625806f90b3aa77ffff9898583fb2a7a47d4c555ff8aed03461ab241e2ce7cb01693086486c9620e3445424df14cbd85df300f3b6bb7358ef3d53435e86a5556e5a0a938d95a09ddf8e7bce12d35b8326ac223aaa9f85bc89f80aa0d1265ef795b3fafdd8b9289100511c1a87e04f901669c291ced124cd023c338fddce3b6182205f202b6121665111313b23d39dfe28a45bafec4097c81e736cea3b17e1fd50424e031c76187b74e9f1d14c9f288cc4b316e81eac22241e743cb0033bb08dcb7737150a32022453e9b981cd9957258ef4673a12270890a8a71086e6f236de12865c9c2c0b92cfb248800c99e556c73ce973c6c5427d53fc3b405168267d7bd75c9737218bd20bedc516404c93cdbea71598b35f608b2156478da62860dc8dc14b5b8802ea83784d2ff6d41d99c8912cca8e67c106", "2", .None}, + {.Gcd, "-c56a2a1c03fe3662f4b85f3a16cbb585a3071d60888a08422fc951e314eff25c502faadba5332c5338cc57ceaf12f4694a5fa74888696b6902c83377205c43a81e28daa4b55727595fa72ef2cfdfeec33f66cbc3d2c40fc1b0413410ca58da00aa8d68048a9b1a342099c79626a2261bbeec8919730dedf32e3052278a50d52fe0daf21610c9da914ff2d54b814c8ab4d2197d79eef7bf70d619b73584f366f1354b567361772a0c8ad87e6aba299435f4fb193fe947fc15e9206b4925bbab104fb2811ee31365c033ffc06d4425400e9e5af2968171d7119307d20f1e2730abb66e72c1b3a0f1fe154e0760748f2d3764f3a6a0e2a85bc25df189bbdb6b3e195afa10ece55c209444b325bae18b78019134f7222f3d5583a4905bbab04c4ab4e3170ace05e6e5c0e292750d3ebd0e339582566ff80026b4796f2b93c2bf986db697d43a7abe360ee92195a42df172426372181613316dce2b55ac39a82f74a725148a4a9b3acbd63fe8ea580073af80a733db69d055004a29594d4ad15858692d0ba87922e40dfb68148c1510b87b47a18c42ebec0cfc06def2c3b6197359964e1014f575690ccee36dacf3a7bf40bc35e7e4ce54bac1295fd14c2978c0a2f586c5d7efba6661d1dd4e052bd5197587a27688875ad9285f50cf5c558585de962aa227537716c9dcc22de7881364fd7f23f481bfe4ec9d73575bb08aa6978e21", "7c29e6f3ef33ec6b62ddc35c7e047c5a79a03474545d4685599a0b3c37edfdd3543a63c319d84eb92dd13d71afeb8bf41a5ab3fa176f9b22a68da7d6f3e534a138bde4cb1bab5b9d8b843c8dcfacec053b03f5994689fb65390600cf55e32362514646851edd7d9a27cfce001b5ddb910b71a6e96f685a9fdf74811eb9803c5e2d4b6136eb381e8930c3ba813946b528bc8c811ab832c4dc8f47c0885e7e0f74ed738c77af6accd4cffabaec0e5e6ab31361174d03e49b894620436862988b8eabc85505b73e0e47621d04c2312f55360427545c651f14159c734fa40ad36a220a1b731ece13f272ff4e6b303e0f460f0263510606154f0c8b179c404f1b6ee674a774b1213c8ba759a3dfcb0aa1eb47556bfbef8f6c15d11688a9188458a6dc8950548f905a40e6771b542f9a67eac9e5dae490091ba34ec574d068e96ddd9e1ad2258e423f070905e9b300f129f657a9c3d34e13872e5ae336c7e0585f32c8eb69e1e797ee8012fb05a70445f23471ad3e45ed34dc84246ffa634ef527144a6d49598b0ca6d09cd9ffe5c54fa456a68d90dee7cb392df88955077d310a3458a683c1fd6c6089b0f0eb13e36d1299263f9da3ef94fd47520739f62a39b442de82c95a63e9824a76ce9aa61fdc2791de84b34b8032c54411d4f2e477ecc96e14d5118cc14ac1e74b5c1a44f9870b7e477eb263527ee0a3a564c12225f025b22e", "1", .None}, + {.Gcd, "a62d7bee74905a9f3bcdd60393d4fb6fc26835ab284aba7f89f57ab9d12f4262b6b991d4bdf4307c2f6036d8bace1a63876ceed0f75dcae36180077551fc875de656a628eaa5f6c65f47b1220ef6fdeaf383cc6d77f44c853684daef8269a839c3b6b6fadf475335e645e16cd2c5670d2656d686c702eaa1f39a5af1a1830cb8687246a04b923159da7285e9f6890681700f745a4ce056f683d9bb2a74f07710ae5e0f49b974a4dd2df35310905e2c67d728fc82c89efe47bb685314290ac217d00301728622f6f33ecbbf4c6bf321a8792ee95264769b3cb46f7d615d96496a6f157ad1d689f706ef5ff8d3baea461f1b55292f9dc0f597cd227e1f332fdee56c730b8d06d3ae5e85a43996879be700704ea1da917b6fe88b43d62f47d4cb24e13d7572ac65b4100e964908206cb33f26ce4cc872328fea5f135ac06a9622501b05a0855f3c7e7a3f560a4d82c43a82ad96d8f6da4c072a1bacfd1d936f2756889bcbc08aecc54795642b94ce3e20cb1e7f47e560aea2481888f008d5048e9c0d46ed98f02bc7ed99d93aecdd9d361cf335a7476e74778093857812daf1841c1a3e4078b33d14298030baa6c4d1841a1cd7cc9d5f8426bfdeed3d31f6d32533533d65eb1493edbf018f8b8f527de6a48c3cc46e8d7c6caa8c4e998ef948c8d09813f906b89c8a61b9bcd65770c7abbee35598b929b20702fbe462672c21b4ba", "312f4f2d2d52a4b2cb1a89922bc928e4cd1a303e114a592c33aaf351ba49c06be6d61aa052565763709987ea70c0f1b5b944cc0a83fdaeedc7dcf2b03499d0dcf42ecf141038a0e5e27901ad65878fdb2389b6cf5a43e65c79da1b52e3bb3d5a258a36f04926bdece4a0f9bf3edff822d9e4b94811ba1d15eb290acd07017cdd31147889ca790e6953a988b35422467440bf0992db00217bcc4a8ccb4d9f06851fced991727ddc42a3af63c791100711cfff9a954ca168b0b6b91ada1d2ff7b749e4fc57d94ded01dff65bf775d2b7391639ae62d6e92c3ce8e39b7f2e7d57c0a47fce323a8f36c6a9b410933ab96f2f72258fa139def98d50ec94a90b52f7eaa65677fee8fa6eeac5e4b4da7e830f805c18411f5514eeabfefbc9dc8d6802f3f7c4feb478c439ae54b8e9c533566b5114faa88b1e347988a6ca0e9ceef7910ab4a3d5477c77e2a4f2f6c4d6202cb97d5874b6345df4742cdfcaef02a40e2a66f947928746744cda31862329130e68bac9a1e14d659d69088be5a7e2411439b60805b262e6e4e010726a5519a52b6ec1e15b5f1aaf0521e111266e1e68a0466d85e56bf24540c12dc3392ba2e7e0ded41babf5e00ba946461dc68fb7500a4b856478d4888341caa5fe7837e6f9046592102681884aa6ade1b51aeab606e7d9d84879721d5a2af6f1cb3e28291ea63256ae6c40cd2784a4d302b7ef09b5dd56ee", "2", .None}, + {.Gcd, "f67646a94080960c7cd30eeee0017671176ab1c55d6b75ac3fb9f8c14629e55c7558a8ee0f8e09befa10e702890a688de226a00845e89b1285a4db3f5d3345ec2af6eb49045c146ee93b70807ec2d7a13c0f3ec6a3b6979b4b9a39aa9568a1dcd4bd5366dc304b0af8b25633ddd45466d1d87191b5be919d55549e5c141cdee13726ded4ce492afeb3949169ea1cdde95fcc9fe635e9e7d3c9c11b43fa91976a71fb4833ccc2417c3f46b5dca1a68f28f1beb29ab96ad79627e5193e38a08d809a4e90aa98be92d01185611b96f906012ed9d54724125029f29132a47da09a34749db7dd90dad8a7a45576f3c9d98420671e21339979cd1290ab900d19ad9d48fe52106f6c43ca700ff4b660799f74ce9f3f01a8ffff7c39c00fa82274333d7e749f7c10c3483544263b14ef5f4fa462dc3db6f6da05855f7e756f864fd53d82e2032dcbd67a41a10ef79fea421a55fb643bce771065029637e3e750bb6193ef2ddb74df82a9632f491b0e9b7cc87ccf5ee89647d213fa1bbb1b88a91c5ef524742ae53272408db47a0d2f868fd8991b70ab061874651254c825ea292209444a9224f9dfd1b0065ec15bc31732e5b05d8601680d463f5009d3f512ec90278d1103465fbfa23f8e5325b7f364c6b5e4bb869eb4c3641d2262e10d9ea43b12d0da8828466431ed7d76dc7b189f11984b9581a9c18106203ff2bc07b79671f4d588", "33c830489a9a5eb80d7573f2b9198803474712e0550ca23e49992985394d6e51e7b7cd2a042036548300a7d1af92e19145380cc0d18e4ad5b33bd7c1f1def915f3a0709033b8afe3473f4086c8d59b9434c8d7c0aede237b82585e96204d7705f2867266e0e88d6b443c006c0edf3c7f9afe1eb18fee7eefacfd4806cd9c7f47e495f231c87fe798115dfa654a25e2bef08c0f2342b981cb287f4bf4090104b59a2643ba6eeea8df95e987af943c69d4b382c25595f3405493c3b3dbef0dbf7d4d636ab81ba4fe85bb6e6c10079142e99a1ed9aaa76a2aaa4009230e374ed9e2c667dd98a638b5e956f3de8897e7fa5b4be8ea85008b563606140bb42274cb760ba770bed1a9858ddba06983533276e160bbf12bbc5892d78f4ff93936e3c90f36c809688c0ac6ffce31f7dd1af29c6d9c4304b6449fc8077f0f2dc98852b2cb7c8a1d7f43ea65ab1f33adc02df6996423b3054e938134ab3969c66c0f86662c26fd3cd93951466e0d7adb080e5f021103a9d996a94db79eb339289aa26098293362ab83a581f5eaffc3275b51ca2d1c1aa1c5f5ecc919064b664b7afab45d4d54efd7634b7ad658549bcba890709f6ce7f0e4bc3c784c81ab90b063bfd5ebc10ae7ade115c8c2ee427ee9f51840939d38a1c5828a6f4c58ea614952a1596b35ccabbfcb8136ac77c12ebf7bf5791ed6e61b321059e108b4353bd6834464c4b3", "1", .None}, + {.Gcd, "-dc2005c374bb6613381f9875b86782f0773bb0e1ffc9d40fa8ac8b37b2605091e42a17d6990cea699dcce5d4a020364dd7d5c847982ac6e56784dc75390973e847cb56d99de7c07d9d43cf938b9300975a8019e5ab7c6b904e9943023a48b71eca22294f19411aabe25c20452ff7d2a6106c56a3ae5ad1e4265c813c978f9394d12dc1178f9c490808dac44a272952333bbcd30d47ed960997c77591398d63ab63d941d21f9710ed6e879bc7b8e3a98223a067f557f3ca64c8db79e71e4ce30e3440a876de530a43c7e337cb9d8a1e1a429d65228e1d72cb7a4ecec41fb067a64092d75d7b80ce9a7c993c3af0374a5e54408b60c4487d927c9e3895f3d864550c7ead70a6f240b07cfda4a6068a790cb5405fad9b4083d630149be72a41a77e21f65f717fa541765c27ae2846f069b4a5f7cce987f410cd5573b26a3af0bddec35c594adde81cc3dcabd739ef09924d833a4ba84c3b6c9962532e39d9392265361c031bec0979ddeef6234324f19c4041c97653235eccbd7864551e45dc060f99eded0b4719a8ae0a280e6404d2cef75f401fe30b58dadce0cbd969ae064ec88d6d653779b591ebea23d75319e7a4cee18a3e27065628b4c2669752fd32d59e8d1c8e9108f2a72dc52c54ae52a733236967ffff50b323200c4521ae8531d1d406e1f3db2ca8782396da7ebfd3306f4da7ca98ef737ab8d01912b19a652b4f9b", "ae6671e71d97645049ab19f6d363ecce5f96b54df3743160977d6ff65477b85c92662b1e0e18d2233e646423dccb96b800490c3cf28541c08cf50570671ab1017995b43e0cc7b41225dea6c4296ca5db180f117a7dda2348c09e663b17cbfed63600bf765276593219b8da4b91f35e627fd73bd2e866541a839a3ce99af765bd45f4fcd4d091d2093fd8db0a4e4ab36dfe16b06133c6b4cfdf8eccbd50813364addb0f1f6f52ba65d14bd475998ce9d6011db651c7d21cc0ae70e133764064b7f28153b5cb9eee0ea3f5de8405ede32e19180cb6d291c7f3b0f36f74484ce23ad5857afb70a9c6dacf58ca2c2672ceef4776857de5055eeca615764ae47f655107bc8623a53f2b0d3bde983a3c9d89d34570c5db45135628b071e2c5855cd67214aec39a3ded4f5e43a1ad07dda7488ca324b150d9b9e0658c86d4bbaa9d210bbed0c17ac59e0b8521f4c15d19835896b02d7d9a403575924680fc52d41498e2d35bda1e64637352de5eab22ddaaa21ccc545f85dc33f8f6641cf26a3c7f32aba80df8b171c44040ecf7c172a384efcb7f7b273347a89b5d1852e011c84e2fb68015564c5988fb816b448eb63ce045ba7407477456de347e7020c60c0b81f22e0e0bbdb888d26e49d1a1aafdee3f5a99b09540c8dfd6b72c5abf25a14f309e88cdaf95f8a21b2416f612fffe832f4403cd4f9d39aefd42571d2e7b5b045bdb26", "1", .None}, + {.Gcd, "22dbc8b6c487dcddabeeb5335c6f470e97b40d4e1bcb3184e721365135848bdc75fa5507388391e1099fa815d40f50286543f3e0ebb616c87687e35140e573dd1ef26ea44a924a5915662ac9cf2fbf65960536ea7d2b95be116397b1afc359070292ac06dd20596c7cf65743b5ab760fea54fe065f4122dec08680a838088ece1e977e43ef5f4f2278ee4e6c08e36174388834136f6095d1c733df41dadac20c60573cbf7ddbe142706c442e20394d1fbbbeb14de7a150c84ea24b6aeef4332fa7129ce7ced2806f5f462e1a349717826d641777e58ec079a7640fb82b677dd2ab29f67db242e003f099352bdeadf2ac8b9b6bee1f9ce518a5129877bf6f42eed31256c62d75831602a42c5d10fba8bd8e869e5cd5b1a574efea54fe44f60d7abc479054e48dc85df07c77e8591d6b144809135b2f7765033ebb272025a26df4a7adda75393e87969743b0ae99090b8f1dd3d8f4e407a415001314990478ce671dbb9b41741b2fb995739a57f35cb0f2c4bf64dcc5b083f9a6035e6b6161f8647b4aab09a9c546a8e389db9fea1208cb71494e9c5d365553e4aab218a3c38e6b1dc3a98e263b925f4fa290aa26fd5a50c89b24f4d92b204d7fffc8c67ddaf7d21022de9f4ed15e57a2ef4e98f0e58071a751b74c4f8b62ff26a1c1aafdb4065a9d017ca79084c30783eeee1e5ae8c9bfa586ff37056a28a4934a2b77b9225185", "4346067ce5d9804f81f1330b1e3ceaa26f565f5fa7671ddf2ea8b79d828d73f061ba637940d52245d0173a38b4f9b6b4ba0d3318ccc0dcbd97188901645ea58ba6f29318f0c983779454152f0a8d092741af7bc386490fb197be7f2fccf12afc76df3a9ec20ebd0e89855ab5028220f2e9864e847f8de155d7de83ce8690180d510a19c6ba5cd20f960ce7a020b2aff63827e9347378ea6f3cec136bf4486472c74ce38ce93418d19c49c09e2f91fe84138c3266ddbc925091649cef462959b66ac142539921b8a9e99c16213513cbb2144b41f4e1c2b74b5598d3d91d13ca23b57dd51a745be9156f8e0428a5dd9dbcf1a1580e3dceb38d614c23d99738f325163d7ca8c6a07a5da47510b7a8978b2829510f3a08619d842652b96432f9a40589dcf471f67d67c7383b1809819f02f1fa5cf87b42289e1df8b73b6b8bb169ebd9cb0b5e829786115aec015614c732ea822e8d3fcd959a59901fe37f1cce74f6ba02c0532d4622025fb7fa31ff97762a3a09ac9ab59bd80f2b8f68c1c92175fe95643ee359171aade19bde545692fefa9cd8c4030503edbd92216c14d41aa613a8228ac52f0c5cec9eb84ab2813c8c72fe1873d48dab5052c5228462bc0f9cfad32fb85fc707b8bbc4fecbaed888c0994efb30c024720c09791d4086671295ce5a3e71c0f28d1f1a50ef3d912b3d2b161fb52a458339f3a229bc7be399c29c81", "3", .None}, + {.Gcd, "-18b2fd669e37db9fa907046084fba4d1466d37fbd2a747a2b5550519ecb6bba35c2f902abe4a92858030f912b196456b54d311fbf24c24e8c52a27345871ceead264f92b45c145658ad3d9884ca99204d610f2b43df311df52e0e0e6f862477928524524ac526569a1983ad8a7fbbdb654128d20a8f25bae4e6dc53697cfd677bcac3d8717076b37eab66fe593c307e8e810a835fd90ac3723bd085feafa3d385605b822a20ea3314c2d14bfe4333a0f2a7c146c052f00b11eccdb460cf10fee717bb854971c460d9371b04ead40cbc62c471ef76b6832b708cf1cd6b5626ba66dc63cb5337bdc50bca2c86f49ba98e890cdf53ee36eb594be672192e05e1cb0d0088db7014cf667df6d3ead504227cecaf6ebd3b01dcd61b1b68b74653884e75f958c5dc3c1feae2f468808f0ddfc324a5b53318fb3514aae7561451b6cc5c64400a897153306f0dbdf2bacbc72613c13e143d478258f696685f3daa7b81c893e1311607f1fd14cc6d60df1a9b0c570ab2354458b168607e741f35ca3a6181c536341abc78c27f4297cf9550723b9f9f4a43e3040fa5acfe4835c577ecda8a8341ebb9b8f6adf7e095d004f87a9caa7846c8cf861ec036c9066ec602a0aeadcfcbbaf7ed2b0cfe3ae21eba0ccc2a67b2efe2ce5371477b1777ee7421cb235aa415e80df7e59399befd5568363d7f6c1e6930402aa2e3f827954c53bf5b2a562", "8f241956ae60fe1a1b882e5295d2e99f96f42726beda0114aeb2d90ec3a5351d067d13df23920139a58a5d486a10ce6cd31ad004cac32431f57f57ec94f3103a8d105eafc5cf60c6a8290dceb67f6f320f8030922a8482b90a16a0fa64ba66360ea822fc7119a9ccf41ff156aee77d2000dbedcbf96e28331a7c313a2ab46196cc54a559d649a3bfaffb7155e7e9e91c4f0032210d8d4528733cfd5a5010288eeb4486120cb2fef0c71c451d0fcdada40ecec6a8cd00cc972079eb3cc580ee1d3adb13c972a9233f022c6297da66e3723157a5aaacea9eb9dcabe9892b120af1335c1e3283750047462d0e5470dae64397758e67a0ac4a3641f37f17136337739dd51b4532b13b54bcd3d62ea9db92517e1de84613deb810f91f4d70c2f75f67d5e3ac20db09fac4c9006ab06b0b3a25d3419bb510598790d70ce13ab84990d958513fb244b75a53783e952ab21f4fd737d44d94f7f490ad7bc04d5d66c153874d5322c685306284633b5c36b58243ea49243b7e92a2323ea0a17345dbd7f66cdce87e84c33f983b0a9aab0e7bcd905fde70c5d97ad2bdee08a988150623712305f688dc04a1589534a236f780d6ed4542ff1da5d0c3030380d395c9e115f4f2e29078f60887ff1497a57ec57feccf6a8bcdca02671828afcb1473b6f2d55c25aed1daa61e080ea0f2060f47285d8aed3bd6eb79aa99d9a919c1b7a3f7c43f9c", "a", .None}, + {.Gcd, "f4bc5c366f6898e49cbe48d345a996dd42e6a91449036f5c50d3ec246652db9d568215931001fd0366704d25b18b059908834f05bcd5da1bc3efaa2f5eae7fbcaa53d0c92dea767fb41cd958c50d96b41f18495ccef0e5a8c407da213a387b9701577d07d45233de5193fb7a7e43abe8c950662a0cec465dce9fce6e502010c1fa8b81125507c809d7aa31f3539612fa71353b9dc9bc677900b0c433efb0009a7a7f1cfce23bac276a082ad841c2b1056c45210c94cf53056b2f6ad3177daec0bf7177443c79d3bc68892f640b9c677180de69a4c0fc96579e3c93658952b2876bf382d47bf6568400d686e1ba990bb18cd9bfba9af35849abde86af0cbe180ef57fb4d0db0068b369d6954d72c9fb5574c2366417532395fd8f4f1351942aa90cf8a72d06de71dabec3f522b05a2a6f831b740432b3ef5d25a5c832e2e34c36e3f5eff0bef3613c678c6d0022d049b1f156a9c26b2417c1524c1c55525cf9b6e413156d7bb97b80dd05ec59029eb66cffe94121447d92f90f1e15c6a961daa095d9b9b4c9de6c64a96d2f1bb3276142558a67bed7065dcb6565c5a436c17648d544b683e4f8ea553a3db4399712d83d2ae631a9e36e7e0e178127d6a3b1026b56ced3fc2b144c3fc8ecd5df180b863c603533808255d553f876a3bf293c962a5dd2945415ef5a18150a802465ea08679973d5fbb4f19996a685a90f5636d6d3", "c4aa7289a13ee73639ee6400f6e831a01420fbb65a484462e8605642399e872e11a346fc66fcb1763b6fcfc47c6061c107393e281f1063671526cc1ec0bde08c5153bfc0b3cf661687ce0d0c74b4f8e62fa504f97d7179ac3c24f924fc6a8606996c105a35fd63cf202610340a84491ee2b0ed9a7f39d4225ee7f667a905a792ba578811db107f8fe3a97149b97186778c6fc383d622ce355ea084631b5e90deadcf08ca5636318a0cd335fa06b6498f19d1fcc5af99458e46965ff06162789d73c9e1ddf55b455b7d07560535397c97df22a6d1146926fef68d7e2fc64e309b5d66bd381a4ad7703d1a6b2a37271ef01e7928355e858170e35c9017e61f02303a2ff53c94dcee887a30f407ec8ce9657e394c4cc9b0440c4b8327c40e642c0a99bd016d644dc20052290c0be644c64d489f4117ac43f7be4cd6caaed1763c3d3140131bc3320a25be4dd16768b93894b36b79aedc14985068a27206c1d8ec30fbf27c043927b46c800b16c58741f5a3f9500ee81fb5181391ee0cb4f1c913785e2ebf72809ec9eb8326d26ef42313611ad2ccc206813f84273f983bff7dcc4ae6846675334621bf69f805f7368c2ab9ec4b2dd2a721976eaae1081fe24fa84b5c09402d0c1e7df2ab0f58d58261f8bb3f42817888eeaf917500de05763e4110439625c3376f8014aefbc55a48c7838c1c1aa0081e726951e306e22d647187cd", "1", .None}, + {.Gcd, "-5ccb15155d1949b3860c0378f8c426c2c078d3706268867011407a0d4a10b396b5d43a821ebb1d8c451f5c59424d3259dca8f1f43a41748276c6d2d44dd5899e6e916e1abf3366bf7117b987ff0226bfad6853196cbdd0d5fd99f52b063f31127e3920b932b3e9eee69c630bf3f5623fc4e96f5d58ab9c76d017b59ad2fc1a6703f420c0a858849a1f58381dfcc871df7d303e21ca965ec10e3eaead72d0342f6ce7c19134dd7e9baaebae8e8ca4a537ccf000375ff4353dcf10676fb3c0335550efe8bf4aef23bebc06d41dc913bcbd9e86b4c0ae42da257882a81c02c2253f509c587949316d769c195deb821f24aa2ff64775ae1abda8f9965b59393aa3875d6a63ce4d7b15bf11ae684459eb9ccc52092aecf51d118fcf0794f00959e80d1a26898ff48ff220c0ae783585613c3c4ade728fa8476f8b50ef848f9b602d2802f382a47842d7483df2f2d58aa6dc0947cc6384a7ca84a530ef4f54cf8c4982f7dfab3f688265ad09f9f44beca5ad6e264a65daef5d53a83b0eed69d8d9d97d821a883627e04cd6b7955f2b81efddd9ffab1db46bc91509820157cd81297b0b67278e6e81fa3afc68152c361122466d67fed35d5e9bd27d026d8100b878dd35f0e0d71c1481024f204ed3b6d218db5ca4cc0d69b9d2647c23c2487d64b94dfa3905c9a68ac77183d61f774a04c183f4016f76070be2011ae2d740b21b5bffe5", "996d0755cdbb18d8f26bbc411897c206a87a8a1cc6c06769b97103deb8c7b229348cc063547f22d8c5bd9b28dba8e0e28468ea14ab88b0288d8b681918249d345bf2e2934900b4c4f672cddfb77df464d7b098ce34357fc1cac9e1c0b412d6835e3070733aebf67794f33009dcf346a99061419653b1d4e2bb0accdcf50d03d82487508e348324988300ace9503e821520f82dee32bdb7df44575bd88d2e763a15cc65838b43f40174a33de46662a46266151af8deb75a3b095a51437c4b3af2f32315fa88fd53f87ec048b22f503a42d40c6b80b91614abc27f8e5fcf48626b94377cb7bb547574441d6c097c6c8dc38d4a689dcd2590c745ed6dbcedc74b1072167a21e85d958fe1574e20307ab72f2fadfb263c8795bdffcb58cb56c61718a2b05ce4e0ab9b5066e396ac1371bcf17967cae41d1ecf6052f9b1112d6807900ee51cee5096d274fc84ccdfe02daa86e57d7a39bf352028fbf7029dc5d67cc6e73bec9c16a3516eb2e43c36dba6e28f46322dace7321352102b181d99ba89d50d80e3a491d671a541dad0deaa3df7cb32ea94e4f4d2a8c63215c70f612926124e894ec146da83f870dc4ec2d08affdeb53fcbcb16063376057cf7ee31ce3a5969b7028d636803b49ad126d9569c502a0bbb548e2fe9de211857f3847281da81d1f9ff2a81d66e0ecc63da347049a36d2a20173fbea8201baf4f997118a7bb1", "1", .None}, + {.Gcd, "d34e998cb861d2cc09dd4221bbed408284eff5cb499d8047c7e003562d3e222f15a72cae31fb724f4a1655c6f5510b4a35b8b69f88ced8902f3bda247dc68190681496f4fa14f3337f3e438a1b00fb316f6ae56a89df9a420a2ff9844667b8f1112adb4182df0ed56e220ee8fe44c9d3337cb4a2d19c554b41e8c229e9df4bf214d80d9c21b418257d401c52572ded0e7cca20843bb58e2508b7c548a7d75e5ba36d95576315fca9da532a8275996e7b3f8ff5898ef6900735865f151180cfa56a25515f6758cc83d72b1b22d2f4543d6716e95ff3825138d12abbbca2f685a6bc56b1954da8fadf07eb10a10728bb70d468553bf24db2714eae8ff61308da2dd11ba1bea58437129839896958e59e6a413d2daf7c96221bc46592408e1f6d97c822a9aca4b915702af509374782821a13650ff22cc54e7c3c4a6c3c8af6fbfa5f6ed5ebd53dfc705f6035ddfbc781054b6ded77e03d10a4fbb4bc2f9375cf9247288718a275eaf413739810195b934209f0964039f582a0d1c39d26e8b68b75fe8f12a28a4b6cac0588860e4f58a58be11d909e89b365394cd1d841988af035159675d6834026332242fc693e5a1e6c420229f3b279745ae72eff0d27193237ed3016b9a19428d4ee993e912fb846d9fb61a818b189122d63f52266cbde993df51bdb02b80621ee648c69581d14ddf38332c50429c9b19175f7d7ba3426feb4", "dda7264f35f10b837597c14e0f1d6ec8291aaa95efd5e051ce611a77dbdbc58ab8b901a2a4ca2bf395e4aac6a9765ef240e53c7cd9e7d9fa1080c277a55d2a2154d9c0f8702a1a1ca0047cbefe11b26b14c7d8de2f90629af3a01e28d948a8361fc1df1fe7fcebcc493a899dfb7392ee62514c7e784eba76a503756c5e38bfbd5103ce32ace722e304edf412e02dbd0ac2ee80607ad4557188eb7bc59e2b7de4e8ac81cdd503e2122b9cc48b4ccdce29de41dca9e297e5ae33cc4f186aa51f98a9f10ead6ce5db45d884c531db7eaf3637636e5314a71d361f5a3b5e2093f180428f05ecaae4d6790da7c8ff2be0b437c682301c70baa873a3d1913b03343ae3a9341ef0154fe855ee28cede53a0db41fd54a31a8eac4c5e7824d5c903bc7258517ca6e83b4f48e0429b757c8a0e47f1a1c42827f2ad99d8a58aa1e494012ffa31d6a69f31cc86e828773f21779409b6a5038580f9191401d5a2f17c41aca2335c1ab262fbf298b3efb7bcf3fed01fc89ccae408af5119923d6f225afc7f6ce887820786cd6dc562ebed6f2a9a72eb1e451f1785d12185d4970d158c8238831609909c666d171455393513534e5e2c07f9f9a7bfd8052fe0c7d6e7e4b14a0d6f8e743ae18f3981e30db1d14f7e090c1d6a82e186e66e0ba243ea05fe9ed9f2c02964067a6cda4a93d64c7ac4bae7fa0da1f732d665bf295d194391c12aa7c0e7", "1", .None}, + {.Gcd, "86e3f02eafd5ace6257a7e10562520758ea88baa00256251c20b2be08a3b5a40a01b87533e8bee09904d6a530f720cd98afff99fe90fb0060906fc029617a4b13c6c0cdb1195606fb1d6624612996a6a4cfc0a2e58f991d5e96d761b2a6ba7fa4b893a81aa125d44eecb308169226c87d9b4455aa1818e070ee8c1389021cc641d6aa0af5e65d9e43b94f3cc50054fee5d3c686307fb5c5874442838406c8353517a87d0680e6dec8e62a8002a1a0d12d13ba2b3c02a686b837ceb6f50d49e7d287bdadc0e7f6e4509714c8bf0fa496431b12ad0293313018f85c0bda7c1dba3a71504ac0f2f0e5fdb6944a4b4ed0e7db308b74974b21989ad0c6153651931e58b7c33e900874c949b9a30e0668137959a57987ceb01aa917208baa5121bae40cf072a66403c23a893667caaefde638e08b3a3635a2560f1fcb5a61642fa0ebaaa77e1a346ae70e149cc950e5475b3a4763342ef343fef2f1494addda258f9895b5382d2f9607c93f902e92904764a3229956e7ed717173944c5373c881716f9f3a202fe792eb7d31d02590737a5ad8f77755889f4a214b3284a0258b1a6f9275079bd69b938e79e9414a6779345aff12ae6aba0f3003e99738f38cab11ab0655167643d31b163aae48a73c9176c5f1a7e28e63b3457a6f5b475c2a40aa0ad9c41b459f187cabff456c3bc7b5446035fede53f7e595d4ab521679e9fe3783ce0", "f1debd50be5254e0374176c93efd8353aab82ca3c091d8af6cee13426ad1956a8c4110d6da99b5b58417d362d07d5674fff550bad342a89dbfcd3e76cc75501186ebbc821906a328f28137f184aed5e256b6284fd104e3e6a3df35778a15d498d2bf2a8edae95b1b612d03efb6a0d009a94a672b17699dd741446458d4df46017734ac611357615f93c6a08be3113118f62f3c1b02b1e426ff08e9a6ed5e60ca0141c233a5eac09bf91e8e3199f07ccc4693c42aff619d7784b1e6d3f920bd258fa40b89999377b587317d6e80177ca3e86fdc8e5c5a44baa3d5eda3a0944288c12c121dfbca6045ff0565ac777815b92edbe502e5fbd90321b05b8201cd20d8108fc16c9a96a590563217265d7a9e5cd8300ec58a7c0480d16ccb1fe660ea0e7c20f3da836523de291e729af08130c0ff41585d48f5961bc0643cb4fdc27f8f2e38d2b4b32eb9d1bd34dd414d021d09ba10830a1adec685923409eb555a2795bab8d5aa63ff54975f48a731e2e463a2ed36293a42930fbd9ac5deb766571a8162f4151fa113ebddfad8b52ef54f52770ced4b564f90e20539455aa90ac5cdb98de5658099ce4df2071cf30d19d3726a1d0ab06868b6d5d9d2addad98e1561c69db0f38aa99a899717b4ddeed6a3f2cc0f23133438ecea9b35a2f4aac2d3403a86d1cac41311b7f1055219f0175038ad027422e56d0157c514ec9cacd0195ae3", "1", .None}, + {.Gcd, "-798fb76c0a6b7c466b5fe296d4b6b8758340d802b7bb6890c7b05ebfc1416c6e4e5cd45e39b6bb32ec4a91b5420b72562fa1c3c3450a553ab4b6a1c7fc98e8d4868d05ba626eb7692bad86caea107bb644585372fdd30cdf8a9a849d8870f660b75e4a1d8f1fec098b6a41ebc0f019955b434f3fae180884e23f286cc22e620c4c15f5d1cd2264cc5990fdcaff794589b11c06d6634f0e0655cb800a53ab4b48a61a6b4579ee547a3253234e4d90d3932036c0818f4277d4ce2cfebc9ca2c360da76fff7ba698b5cfc5848f04e33331cb3afc89fde4a0a5835b14d8a4c0d9bce92ba3d34e0306db60b6dc1f98a1cc66d29fd4a7d8cd3572cffe079013cb716862668a084f19a17684dc77494a69ab0a7b579c82bb50a105288cc9b362408ae97959a844597e0b643920d920c0715ea06bb07d702ebf14466e933148fa611131b660937d3f09899615908adca359e913e51375a61fbe59a62fa172b6eab6fa03ff558efbd716f77f73eaab3f8571a520cf724b38ca24c033b7c8243b89301f83cbadd2524eb778288547835b7a3be2c97d8eab64d6f7dddc1610be331fb80c239cfaaed85144e762fd03b6e65f44a8f4e8f879cb543fce576e95b9a6d651ff1c14052ce20c96da60c5a375148c8e4b1fe3f9dd6fa143d2b72b0d809fef7d0907fe26aaf08dbbefeb1f07ca731ca39bcceed2d68c02ea101cb2d576698746442d6", "344f25bdd9890c1a8e7b4c33b549740f3f43aeb27c4a4de73b7bd97e97019ab6e030de1b6b1f47c497a5219f93dfce58bf001c802efe777c7c2188a7883b142b41285d853e21f5ccd8594d0c112079e29242a7cacad0db845b386106935008e9251c5143e92955a5377e90ad1a42baf3b13426b092af4c51be2697d6d2f58281d974531067ef65f0c03c5f0b5519c1f403da29cf21246bd0a0c74b058347f6ddc8ca96767914cd847885a4182f1e7c5f8ac564e868e4fb83e43ed5504cad2859c74285eba6c06d72a27f15da57567e9a9035c37b2a90a285c6a0e8f4f0dbf1ce72fdd467a4678d80234cd2f305ac6c386b058c62ecf384c622462ba644c4f77e1b0555107dbbb648c74112719aac00f12c2c3eb3c733ae73062a796b4c944d9c5e22582db03c4bf2a3c782554c059e26cd65bc73ab4a06b48cdaad404fedfdc7b427f2bb3bdacd88ca71c4082427f5a324c28ddefcc3c23b78a54d28f93480cbc2a9da7e9305af01a4d0655e6a956dbcdcd2a0648955cd0ddfb2fe942b33116c6238746abe5aac1998140d4920c8db4ad814979e08a40cf8c6fb4e6c65bc8eea7bbf4b3a07a3d5f202fc8b91388ee79af7be6dcf79cfcc5fe62b6c58a3180d766ca7e209c59099426f37479416544348c425a627b2446526764547c10e23b4cc7a395db6a3f7978acb2ff9449bed944d5782256f1589944898a5aba8752ac881", "1", .None}, + {.Gcd, "-963bcd4c0127aaa64abac6c43c87ea6335d6d934d16348f57d445251f87252badcb286a6ed22d0346034bc6a31709a7879b0d8fb3d0cbf7efec848d84836e692a0a3bdeb2f2aa666ed70a7b15f8254a07cf1a05d3de457b8a2161b0ca37899e58463475601c2100bb5b8587b37caf3ac5aac7c5c664171b390e96b800d80f7310d4401c6ee468add426045b2fd0aff62074b85592075d9764144fc878e5ac159a55b223827111ec766ed4ab327309027410b27f77ea9e872a05f3d3d8d56400bd4955a50b6124839c9a982dd3596c1f8f34515e7c104fdd796e694737d08cae2d2d422a9d5a7d7989e0016aeb6cdefa458a47df868a75ba4d072e51d07672d2a675f16f2c61669a35f4d61e483507d05111a22475b1256e468f84afb9812b389a40834d4eba21de564aab3c4ec980b1e5b1c0980e4197d362c7d8df9ae4b92c9d0b292bbefd98feb87d92bdf0cefd75b07d6e5a6ee8b63ff743802af063b03f86381fd717c2118dc0e498a23359450231d875c30a933a677323bdeec57eb24ec1101f045f4100295d82c453978ec1379611ac96d351ac8b388146cf0c9603a528e485158e18fe79ed5cba67288945fa7ddb9b02a52133af2fad54a6664d01542d6099da0cfd4b6b07d356ca11617b9b32b68f06f9d4f89beeeba7e27d9120fc2f2b20a206d4dc6b9154ae7f1eba4fe9d917cf03a82eeab319c8be335551be0c0", "81ab99834620d6825bfdac24e780c69054d3feb35a0dc2a4bb0ffba1940fe63d4070c7b6f252fd23c9cb49b975e31b06eebea735e9f08668b742b9bfbddb270a132b2d5c06b0e46c07530db6e64864848e258ccb4c1bc13580b7ccca92b289251f2ebc7171a71a859ea9d0d22c0b8d6e7e16a8e53bacc2363c1f7a60db3200115ffe18915f7df3f97936b0656d41c449d9aaaa62bb67cda6b8006ac569a2b8ff71bfe398aa6a03c667de9ed77f12d1d5e31489bb1e125213d4bb9338a2f0f1faec9564859a3ac91b8a688d74451c60b5ea9a0d308cf52b3b188af938399bba15be4051a189e63f459899aa9b492a1837b4b142c1a2ea7b57e5da88f8146585b024bc33f81d1554cfd80f3a9ca7d93f729527428e8249137976a914673f99bd9f72bf49552f6368db207db4d43c86de5f4cabcb214a0a3c8f653dcc4ca36bf5b48e6e325cd65b4d2c920beef3232ca71d2f79cb931ef57ac76e674ba7a6b0a160d401271fdac41a432a98c1983d25cfba14a0fdd62a6a993fa3de756cd135c00d109619bcc0eb6a161dfab7b5cacace594d75064d59a5e7e96ae428c671123f031a526094a5fae6d415000c31197bc7ce2df589fd7f0a43b4c578a8eaa1e57892df25842579589ccb3b7e43feee37f03e161a6f3ecbd32a2d30753b4eb43200c1f616d4f05db7bb8ae1185ad752f2a4047e36e82c1fdaad5598bb97c61351a9be", "e", .None}, + {.Gcd, "3adf42b055e093b5122a123167456aec2098bc06207216d33a0f0abab26b6f7bad3fa41370fdd343615a0c64abf59c961d7f3ee72903d76ba2252cfc307a1eda6d1589d34b60f76ed4d91542af93d64d4ae276d1cf033d113d1f326d2c79f97f2c567bea20da9012238dd8dd803bf701cf8a67944502128cae3646881817280c9d40a6dbc2141caafc28b314194e16369042f37653acd81f4bad64b3624e78460accfc82fe57438ae97d76d36d23898d2dc6d4e33c6af4bd7c0c67235d48eb8fe49f3b3f676b0d4802de6181edad77f19a3a3acc593f45b86bf630837884f79ef9a20af0df2e09d47854aaa3dce464a4f491df4741f4256aa74f45f43512777abaff1e26f1a0be05cfe271ba824790a450ce66a1a7166d0dc6c87ac9dc13f42788bacee632b509604a0cc58d55baf73f481730eabfb8830050a7bf8d41c73a028f53f624d85d7354bc248040de1ff2961bbe3d589de0fff3d03e3a9a040defc59a4b955d2f30480c961c4d847acd9ca0872f28b1eb4bf000d2f95cd839bf247ad515d3be1b0acfbbeca9b4944fa27cff8502ec22a38b882afae60b649bba776c3435d48bfa2d984d8e0e1bb2488c1a66e0fd4bbf2b5ef85c94ac52eccd480575a65fd15876d243efdbd9b799b0ce9266cc81798c0fc7a1272a2fd5f7181b22521525642250dcfec65c1fb29cde6a5796d15c514e9e7c2850137e5564a453b033", "62cd89c382081606ee3532a20e44a9257bca8fc2d505cc864647076c7565e680ddaa2b003d789605b33c7deb58928c2d5e2c3cfdbd2df40f1fc265cb23784e4116b111514d6c9b482f91b662e66b3b1afbfde3ce5fd3fc3ccc19e062d7a498a4e721ecd3c3d7d60ffaf9e97b79d373f136522383fb2c3587b89c0c2c9417d9ac28a5691d6145d2bedd7e134358a95c35172a0953d77ca7bf0c1fa1652397d06841456755d3388a0350f2d009af347e7d7f6a78ef80132dc5a4eb6a7f7b283a75d02dd4b47ef8e8237fecbb1e0b88004294edacfe43234f5edf49fb3f8576e36c15043f20fd564a2abf98ea767d2ebb638384ad3ec908931b669b558bf29fac9a8e82d53ac5cf07b4cdfe029d31c570e7e9a608f8f9889d024d5f88ca213d9ba59b398a61364176a4fa35aa5ecaf56bd8051aeb821c8b383f71c6ba7b521bfdf85410550edbd74ae8da00586fc43b4dddeb2f2fd535e986115f705f7972922a09f9d26ca8d990bca8ffd1698f61401362d9f67a77435b9cb5291667e1d2db27bb0cb7d1387fd9727e8780819727de86092a22d76c26e1fd10da751a58a74dd0018eacae3aa375e8b3685e996b1b2434d7873795d4595e5ecd86ab0d021e271fc205be23c54a96acc640f29f8f3e4c864d5081b61b39ee8e72c64a19cb00dc693a26a6ecee0ec1b7c9b1dadf6c4cdcdc9b6fa0b697c8c2e77b83fa9536a7a6230d", "1", .None}, + {.Gcd, "4a469dcd2aa66a89f674bf88bdd7dccd74d816fd4a4cd2df23399b6aa9bbc62ffbc8e7f59f21de4bd55b2964f7eea25a297764ccad3bbc64c732c09616b943ba9cce48f97c3d0e8d49c35817d6b3005b9370bdb18b0afa305dbac200932f748390d39da7109d20ea91285a661ab0f215e1b0c828990dc542e05b497ce965ceb7c3a29ada643b27ed868a47afc26c9e9ff1a4b975851005d3f76f0d81f26fcab6ca8322d75de98fe9dc748c40a8632b5e9698908bcf48f84810fb27299644ccbbc735dfada9026f42c0161b31ae82eb9b4a4ce966706103864f0c99daaf3e677464fce0746da74dcbdefe1a25958df27f4acc24bbf07d12fbf2ce954520259abd0fb3b2dcc424320fcce028d69fc02c0c2d41adb5ee61efaa3aabe501d939e180a2d28a8622509729fa51033154629f2b15e3216362d262d030d94826c82372e9ebb01f85ed598af905d94ece572c84a27da6a377d684841c2e37fb418f224c67469e5abab02d3011c87fd0291cdbbd8128fa009c85a7674eba36dbedbffc25e37a3b8ef0e22fe8cf90e603a9706c112bd1fc2e73c56c954f7e02c2f435892461def6273d7822fa050a1a0928f729dd420bd12045b165a65381c6d51299cba077a4b87ad40f9c3f3edc2c263210887a028992e6e1798401abadc9d05f7844a14a83168f1cadbeba681ee2e92868beda09bf07f2a567b22479fe2ce7ab04b7cd46", "97349e541b68613ffef59e5f4ee68350ea11c6adc3436da58903bceb8f9813b745192b07e45d1426e7b4b350bdfeffc14f012afc7e55adfd861734dd39583d0267593be0c5c333b2d72172191edf4fe0e57dcb66fa03a37653c098a60e28a950a9d0572c79ee4113657129e80eb3f1047d8ac01ab66b6499926920831e514997dec808dbdd46bbc59128d4e662678e1414c8bf461c665b7050026031ebeb614c1eb97898f2442252308cc585cd23a3a1b82878731d7b7fee0a56bc0f4762a6c74667b4b3e60d73a0711e63fa488eb06af0c341679dc0216e22eaf3c1b6135d7d7d07a1cdc79be7e03730fafa2183fd9e9dbd9a95e19c024b265fedbae4da2002e9a3fd6ea0d66caa2fc56d915b5e51fd54020b072ea70ad8e716fb06f9ab60707cd7b00ca7bd958db42d20ce5d1c04bf8239c09baeeeac1154f5b99a09f9f4b114772d250580d7836f9a2f23407929edeeef09c5c5b5604972750ba2e1fd17bd619f7130b46f3d6b8a92c094a73c77b944c955265e412dbdee228eb115f3ae9317464eb0fe81cba7c839b1f4790f35cc7b9c3bfc4d5cd8f6b8b5cff5f20b4818097df7472004fe482daa38337571d5c2fdd0da1705cc921455a977fd21d6fd0a2d6d470b01f910e7d0e253c554d7589eae45b5f39c4e335f9dfb8efbe1400bb06b0d285c3b7fc2c7da70e2f65ef5c5aaff1da1ed55d216da4eac091dd9664ebe", "2", .None}, + {.Gcd, "c9eead0e4cbf13a57c4aef8d96bb505bb87c732296b3bdaaa8ccb8da61b3e53ce144ef2eeedadbbc739799c28ce845780453e30cb9f30d297939b4624c7febc23d18b324c778570ae5ccbd747c2b21a2149390d346ed02078a1dbee31c21ed330dd37792508d9fe3d3f9a811bca1ef56c6e9a04992880c9ab6e73de0d23b927e45eb7a26c3bf83c04a018cdfcc790c5067ac46c3020786e3c1164b39f22ff3d995842976509fb008b6d30443557c5c3c4e0cb33663b2b6ed87fb042ba02deca407f4d4a1f3c65b0858a3a37ec1bc6c93fc1dcc13cbe01457b04d89a53db4d87cca8d34730414fdf381f435ced96ffa452503b301342f16e841e9d7ae18192b9b8c3e92bdf981f97eccf63578a81473ebfc194723c84121525c0b29ddba9eeb5cd6c719bce354caf8db041aaa801bfa5ebdf4f6a7c950f697d0fb3482f1827ef30b96270bab69338f6181d35a021e03b40d3f56e2ed9edb18b2dd433b8f5b01c895be3b6bbfbcdba77e6f67e1d0d8f153d0b7ab911228ea8deb47be119148e5b76c8433f52e05994e3711bb1dc9b8ee55fa358191c6b1f815291ec82f39c527739036776756544a6c57e6788389d08dd26b281c8de75f6420344c1f77a379a992cefadb702ec10d68aa819e17770c80c85848cba1fb1b0563ae6c3d5ef0c8471d30a4bd284ee4d3f529e6210ef621df850949adf17a643322278947c9a6e83088", "83fb57c29be52cb579ec251c527f3cb0cd52711ddc17859cd76807b8e73913c72df98eb6f5e3b3659ede4230801e3029663720f65a5e7437bbf765a956df1bfdd50995f7749b52e0f38d8bca0f2b72d012dd08fe41c0c5f738c08ecc1ab3247f25f3ec162797cbd2e0ca50c880e959957cb4911f485b620b5a5fdff6ead89ff6a7b2a932dec298873f29df8ad821148ce865885112a6b5481f8f495750cd5a6e42a8c4fbb55fa32761c78927b1dafbe6279bacfc6eb3fbab0d52ccec4e030dc1b302c60979580caa974845bcc9cd35c3f8a56193a734c129e51fbeeca502b28d97d4a2762e7bfcfbbf9623a9fc00f5883d7f6db19201d468df27e6a6449c8c955932ec1067a70f20b28e30beed5aca6c41e78a1ef8e56f0a77f9b8d59c2b036b018ce5a85f9c25376b29b609cfe5f05de332fef0b565e9b1866fe0991854691d026dc49b97512068262a7a896eddfc28f560b99d89630529129380b9ced78dbcc6898536d1be4dc377deb54cc53c6922bb229d6617acbd6d9113e9044d064e3142cc886d7ab667c9ed77b0728100793c057799a79622ef4d6268ee90681440482d85b020051fa8a7f5f1f33912c92a6d266a35c461bd37c48e586139b6fcac337dad79ab77136887e269c2f6636ba358ebef4dcb38f3c1829268eaf02f36588fb96bfe6a8eaaf18101d52ae0e98b644d7e6ac6c5e775d7142b04d22811378aec", "4", .None}, + {.Gcd, "205def6c9db752043de491d230f1eea097fe3d13a6df16f5350728a728f8f1e599111562957cb17be9a370c396df013c684a8c192e97bb81c56745d3fa630e19c919130a5e2f460740f06209f5211028809c98427a4e2f29dbb4016e84928683dabab4fd866b980fb9c461b9d158c2558bfd7e6baacfdbf3dcb72322695b443f74ce354f2982acf827091be38aa3bb7b2135db6921e654aae017d9dc23b0b40d866459afaacb8b65d6fc9ce470919b577008f8dcf44336466efc2411554597d10376cf818f0874e5bea221813e3610ca9470ec6bfc2d3f1c6c0627ba3a4be01ca1ab00cbb470b774f5f3a37371b4d2e992e64079017c2bbc8b5ae500574b226c91b2ce7c8a3b227e5b181cd21affb08cd662ec3170c1d92a59f5377f0735cce7602f0a3a3a29fd2736782340dfc2a273921379e584ef23695feebeaf1db9ab751931df9a33b14f01ad9b84b22de9b24d741ff5becc8ec66ebef465f08004066d616d92d7aaa2d83d35ade1c55ab9ce683e69969cb894a582ca49e55ceace0b05aa9f6d4b108200b906e9be0fe7acdeb1bfba88f14f19e8bfa1f3a4ae3f0552526c641d847219ded8af4b55e1c6b91129b78d9252d67f5a9bae735f3e3a8f0763b86fa5a8e9cdbf9d1a029e0982df4e4b37f3dc4e18a962da28e0b04df61599b85096a5301ddf7ef99478ac94be9fd5181761ccac7b806e003bf6d16920989ca5", "69d2380ef534220baf487fdcdc0edb3dfc3c7b94c1c7d8cc754ae186dbc711cedfca22772d9f628c53097d4bf9240a48e394b33b2541699cca1a7505f53c02195881dddf1edddbd546817566c85649b39969e660aa09f51c25ebd02c14ffd0e97d3db63976715e1f71d13ce52c398dd4227d31827af5d96a4765c70a8fc26e94a9df13da8ed1aeea9dea45b2f6c17ee5ae308619019ea804345feca563cbdaaf517a35327d712440feacdbffa51e6cf23fefe6216c3aaf4f7dc9f26c062f329abeb9b6862c9295369b52cd2563b33126db9d2f97895bbdae96e21f5a33e19062ea69346cadc3c5df6cebbbf14a059ff7a6b09056e29696b412a407a1a050dc44fd5df6ad020212a563f2a14f5254b5ba94b66e833fa4cfc1df4deb5a7cd86050511a14475924376c62c7fbfb434c68ab375e39a50057c5a14db7a926df0deb0272157e75c9018443e3c80aa3afd5bb5e9012bcab090294c817b967a700cc50c5b07402b1d93caff5de8f2ff7bce8157980eead82ff5e3a11cb9e5b5632647194e014b46ae1d4a88e82dfd678537a03c1ad546425f41e7773d5f4c537f90be69ff8e9fc409e7db8d9f39a4a2fcf9bd8e11ab4b4e7bbffeaef72995d1689fde869037891504e00ffc67e7650b9a0369d64369d46f6cd9a67dce3727ddecc86356ca6e3fbe94f80c5d7d884f9b6552ae81552c2ec7d0bd4cfc04748eadff7884307", "1", .None}, + {.Gcd, "-784340d23590d8a58e0ebf92afb9f45c4d3d0d8587e6c048ae5aeaf79c625b9d41709c53160343659c341a3bdac5467480fc5fc61f3c4b9ea80ad3c0fcac1af78a8687d858af455c6cb5159181232f664865329aa2db8ad91a21f6c7646539db4036d5ff6f4255deca043d8430b2699c38adaf0af72ec1c37a139b9be80928178ebbaf51b0151ebd3d54e9a110d241d7a20469ad96c580fa0f9fc21a6489fa9f5b9c2e4d73d7ce12ce66d0b2a6145b3e3c08644c35aaf75339b03fac86995d7011acb7a551c0222525f6a50048db6daf83249025d625d4f139959cfe14a683097bb842454962f1f22b5ad79b9ab1abfeda5c25df485770a2394209be243109d2832aafe06de3316045fdd5ee30362c53377550ee63f67ab962ec20219f8b64ef269979241043712e0897c9ce9931d5a15ba58ace3ca3c7ea330fe6433dbe26a15a166b25c597a9975792ca13afc65c11b740688836361aad7baf3f63508c025802b35366cfe2d63347381c01e55944f2cf4f64f1e6febd4c98c77180dda295b3c3533f475c29c8f859d65e36fec3b9cee3a7034e5b46a1c0e6f876f190feaab014cf2b653eff0f3eaa7212b56df783196d0fa7b27c4d0ed34e9c546ffcac0eabedffa763cb51068130b101a51fb15bc9e00283a4d12dadbd3aee8962f2dff16725643927417be7c27417360924e3a0d4cbc328cd72ec1883b61882a6f9fd16b7", "1813e1847c84e4fa3ba6defd44c3036e80451d971010fb91e5dcab9c8533cadcc3ccc3f38d5f8f79bc3893b91899276de50f5143d13c1e147fdcb8c135460721f3c8b87e2ce183d1086fddf49119d1bca36e5fd88374df0256547d1daad78ab8e58b86e593aae655f6debeaee264f295de2a82d9ed2ada37ddae6c8b410e91f63398fc00637122ab7dcbfc13b1d9819699aaba1d6cb15793ff4f1e05cb82f1ec81c11b377ca4857aa393bc7b5f7b349873765bfafd23402068e485839c5c634e8dc7b8d32edaa2b25dcd744c3cf5f0024f5e813436fde06a1c8f60d2aeeadd02fa380185caed7441e12e1a624981e45f8c8a9b7fac95bddf5259c1b0dc542621c9045520bb26be158a1db18d030308b89b398ab6831eb0078f3a729e87a0daade93d1df15620c3f9ff661ee78f057687934a540f410f85dd27e3278463d9207887d4cec9f967b12a5ad7d8299a3ef11c339b35eda1d17807303fba6f44e5f366b5cd82a52f52eeb17bfa6bd00db41fc5340cad825b201e99ae2aa5df68df3a37093d4e2294afb8090ec79477d6f7b0b1bb0daa9be8e67e1ef25a387ba4875d2e1fe368aa3114216f6213803f2e187f50008b9382b577c95324a2b5cee7e6600015fe0b01977872e54149b21aaf7ee2098073bb8633996244ebe0b400ee6bf2dd18ff1943a267a8f28f7b98c33764c748f5339b9e4362d4942ca82df541cacce3", "1", .None}, + {.Gcd, "28be63d10d1941ddafb8f2b720a2068a67643835afada47b2ac400322372c8241539038b54a392dd0c77406cd7dfdd84cdd9a805eeb8e8e634f431cc8c5929662a2d0d5721caa7b0215fcc089b910ceb2cd71367e22a1ad743737041946faa998812c618832e5c4ac8071e7f054a1986d1f53f1b5290c27eb19eccdb0ace8b01e4061e7ee44c8fa7395c0c3656848f08d17bd2963fd25e5c779aabf96439f3fc6d35f9c7b85793e45c368713836143e7973e5c453d296d8fa45f789a8f446f481f057f8bf2489aca0ccb7740c4eb5f9b7ca5cce4b195cde5569a81b715d26304eab0dedc312d10f9f32a8221f53768c1e89f40a59424a43eb2708666992b641671c7fd93749c5a292bf5f514f13b461a254d032afc9a7327f9d8be65ef32fe57f5d465fba712c688769fd8f32aa073bf3cd8bd34087c9c0eede274e2c07a519588dfdcbacc9ece84b31ad919f55e0c6e7a265b8a4bc6b3270ec197eb5bf4162ab5cbfca690e780320707ce2afc8a688d8efe9857eab54a3309bad4a6f867a6f27ae272dcc0070f57b262fcdde8dbd3b2d8c7ec2e50c92598c385e687211d8bbd52bf52fd9b4011093f626c60448eb88321fb4e9c2d2e19d23aaa4abb1d78315370ca6929fa1819e247250f560503239ae50973dc61475c5806614caf40dfb2a6670417aba6b0316b331b0fad5b12724f122b8173e685bb4381d452f0546b3346", "bd30f4aef44db1b61a1290283a36c80bddae99c05340ee76bacd5f4a0ce7d07e53283b22a33ef046145ff78a5851c180b306b7fcbb723dbb320b8bc17c06c0fc6ca739516d5a0fe91584a45a1eab5075c8724974bdc22400025c23cfcc61061c6762e7e86302524f28d7aeea68da31cdc46a7e43f5b0552bac74491e8a9646d7a3beda6bf3907dbf3c3885cb882549a15a7ef29d0f3652f7f1dbef925ad42b211fefc9b3d63c51ff3f65a3993e6ba9fea1c230f2ad542a46f2a5b56251be29aa8ed9a2ac2e0ccbf683c1a39b52ec763fe7eff0bc91fce18693962ac87243199da5c90d4bc82de062e092e4ee54abe53af6eb2ebe6aac28eb2261d1a0f29032088c1188efc6f2e9cc1dbeb073d610845453883690cfc334f6996c3b9c8821c99c3761a9a5570c080bbb7671d90be27968c2d8ab550252197695383905d33e25a96fb7ce6a58d7c7bca6ead18c1079c96d36205ab51bc8752f50ae6c96f0ea312c1728e7bedd1c0cf0a63f93e3b9004fcc26f92500192f5905eebc340cc32b0feb8df60ec384c2fb87baef77695066dcbbf289148ead2ca2be7fd7ffd0ccd28f2c64c1b2ed14b85496d792049ff8e87dac4e92b8695867f955f83f2e24d0f7ee9d7c52ff9cc7096aaad8864a40760c8b0ecaddf1247e89a45c96523ffc126955d7a9a7b68cc6a5f433d2a0b2f7ee8c57f82a4ef3190ea8c788d139429236024a8d", "1", .None}, + {.Gcd, "-b60cfd06c72aa2370a1bcbf5554fdd75668917fd0926a1650e9d33e72aaf6abec6f4c03ab57ae34bc36cd5c63571ef80de021e33aa2a26dcc2a2195cab6656a69dbf7857f1c6a75c85a6a8e7f7b8d9f51e033a2996aa5561775963cffeabc5d46b9135fe03757ee5898f58644abea77198586aaf3dd5960ea5a7bed351ed05784e750efe533e064915ce6944cf1efdf5fbebfd3ed98e470b83912eb467183b8e09c70ea22988ca6eb354e2806a5290954887d5866d02546be567e136528924a96bfe3761e494674c5fed9d81e4f610958b35eb4134f4b15f97452a573806a6fa1855815fd0f374ec58cc51e847baf61ef71926870e10f1860cc4eadb1950f1e3b3c9438993cb733983590001a3b7340f50b7e5b5a56e4162e17aec7899e8f6adf2df640ac76a97cf6c3c6d610aa39d54d9fd440c7b063b15df4810e4546e6b19b5192231831227a5f01967f6fa4ac3cb2b8c2de16e27128bdb412e24bc7ca1e98c620c2f571ce9146cdf1af682b4d36219435dd6e39cc85b7b24d3a7917a1d22e4ddc4ff979ebb72d44a7aee7e7e892b9d853efe9dbd8b951564fb7dfdd288944566e28d1440068e8b77deb98d87ab98a20351b57dd1fe5d5cf21b3974c0969af9f15f2a03039143eca3d6ba42da8bd8ece218db034fb5e71b9b8e922daf344924d705d384c1e676ba01ab1445dc4bf1ae1d041a84ce3d084cdd32539b3dedbf", "783114131e033b55471a15df3a8d67307b5107eb0a3ac5d5d526a3135c67c7639a140428686fce88dad90ef709d6ec62d1b0d48758a91131264756869c87487cd9a8d07a242bd5ca4aff6b14991226707aad96e2e18589207e880d82798e6d6b1fbb6bbcbe22c58f3e31e075302f750d845c3d160fd47d237f8fff9e0a305ad6f6aee2ff54d7961a787c83479dd7d354d62ea8ba93b77e4fe0bcd14f47a6ea6d722836f1a1cb4f6dddd3adaf5f3c0fb58d69706f47c396a73d29c63dc6eefbb60b7466c2e64ffabde46e11563b0ca071f87482322603ab9692bf0dc22b733f633b9aa4bc9f6264048cf460d82baec91b274b2d752ffcfb210d27733d869504f0e14eca102ca7aced406cd51d39edceeb6fe269e7c2bff0b7b844c883866cea2ae85462443a985f8dbf63a5aac66450b4a7f64827ebaf23ead1b97c38e00a0b3609bc5745bb02f68c55b4f3c7a6ce5bc820e89e3dadd968d7fd6e336afbe30143bbf60450f07dbbc9591e5e3ad70f9efdb6b310ba1eb1a69b2e41d8c1ed01ffb2fed8aad4c8a74f9f2618afdd1d3f8b5ba83242b47bcc7c611195cd0f99338df83171d32b284c4f40af9ab108f4d20e6dea931b8e3a4323e2b2255f0306bc928ff22ace9ff229eecf1cfc18b023c33db0251adb60dd00da803baf24266c725fe2e329715edce0719cf4196c48ef3796c550a6163b7a336a00873bc2beaed8d0ef", "3", .None}, + {.Gcd, "-f1d1073cf266811b54719dd993bbf4448c85bfcae30d5548ed9fa8b79cd25d3468b7938639452f29df62cd2d5bce9f21d7eb56dd05f3dec94b2a21a87dcaec7c731f793fa531d4a6760206b28ed41c085c3b6b6beea5499ae879d1632ed49b7404fe9c8ed63ebc520a905654dd4f73c19283574f13623ab59a17cb7cb066a4b2d516b029039bea89004b5bb5f8fdca806a4a1b549eacee0f9b366a31581a3860e21b9fa0af3f574782606b2aedc09f1d4958c72f1e0cc8cb1bccb7a1f126e252336d2f2348042f568ae7f552f66db1df4c28510f9d37eb2f14ac7a12e3b963031e5527f0e45e68dc37ad672a91806d05e3f8cb9523ce732cb8881e7c5e2bed67a20f8d1f7029b4cccded4328e3938c183f61c3eb4afdd44ecaff59cb74b0a81641dbb42480ffc9a7136299d6a0d43e1418029743c6af35fe785c80eed38cd888e15c7fc71ec22dd7269abe7330c589fafb1d652e1f5ae51ef92279b8e82ef4c6411359d5641f0d856a378b0ad0b8fba4a1f5710b3fb53adcab84f2397b59584471243341158a92a28d335e565c53cd511304911b91b58c481d548eab3c463748ec3bd6efff4f6f763b4acfefae9dca7b18572220382da97d6d948120cfdde1841fa89c2f6ba586b3d02ffbafc8fd9e1100441cf3fd1c966112ba518c273e7118fd00ff4c8b858d818323088fb704e3e39094721a5222766a175d04b9cc3764b8", "2b41f0a4da5f330c09c41a4dc051f8acf21395347b197b7fcd7b4d0ddfddd8860d251aa5d1aee766dff2b2a69fd7dbf5ac0a7d38eaeecc0324bcd1076389fddfc17011faf18755048baf9d0189aa289077dc873111c6f1150aa35213e20e6cc53801df9042b8816979b06f4fc1fab8a98388f101dc0b5aaaaec7faaae671c7ff255dc58ad9a2e5fefdd5de8626b73378457c763af00eec41f422d2b92ed578cfd39bad4cd9bb78d47c64a4e9e94c4043446edef8606f4456e2146d697d7a961670a6ccf28f76e430f92f20a44318a81c1fef20fbd67318029409e6e22b93a61748ae6a5f6a5d45bce82572a2a09de43a3cd429df5a3c06317d1c38c19cf845d361496edddfd605e0b4979d688df2d6211e95acb31c22cb62ebe7925e84a48b6f6ff08eaac559edfa4939e787520d25b29641b4c337e41f1f41091c97754cf47c7767dcfe97d12df701944d94fe69aedf94f4a5b071630237279fc0aa06148fb18f28ac1723fde12a391e7a939907650e69328fd24adfb30b7e59c4c9123c558a394a993b10467552cb3d15a1b98eab90075988b12a40896f7ffbda0e0fcdb487a22acf2c13c576f88a2829c0abd9bf3a4e4d5f76c1f49ffdbaa5b744711f4ccc4b7b0a5338922b4ec4163609b471276bcab5273660eac2963287cff2d0ebabead577ebc438133c146722516ef51d33fc739b92e83c72d140100ecace13a0f511", "1", .None}, + {.Gcd, "-542dd1d88e7876c1edfbfde4a6dccdf9e0e3024b05b6213a70e97981ed69c9f7d2da6c8a14ebbc21e5c9fe60422ea8f4d948e6419951be19a2b7cfb5263b56e42b3d8afe509917b4a0e88cc185bacbaf9a1adc2e554da447d407156f0b386c7c86e3cf0ce8a0594e2816ae4edb52d6b2d95f25c2057e4e6ad9036ef00f3b8daef72317a374456060f7262b90632215ceb19861e06b4687c3d81c9ae673690a8b142550d15edf624e15a18c85956a387b52996e0eaffb76a80c7b172629101740225c85c00a26f7a204838b529928fcc1887ab5db0c4922bd3f0ec287744eb91bb878a92c74d9c61c3e27f6aff838b81024439db5bdba816738f9f90c73279d7a4426c88b5de9c6132656d261cdf978333391585ce9dc673c64a82f7dee59fdd5a6dcd1e01c8a79f7aa6e451fca0de83f8fde0fb30e147c09c749daf866079ba21b801ff1accde2c577c6a571381905d8cfc30cf822d86fe42ef56d6078088766fc2016fec3612c373069d549f66b9229b5f3c0c2e9446190e67ba86eeff9d3e9bbe360aad9c47b141d51b03a1c367bd60c7078e0f339d7766fc35e1c4c4b202435233929dc488a17eb85221ec1e04c3926690231c94761f0ceae1d45aed28825360a7c1014fa5642fef5d6f31e3e383fd0b2b241711ad8d8c3ade4f03ea69408681955264449b19daff3530dbbb185710e016d58c01a1da9483c187ab50e5145", "cba696e9f0b9b54b5c17c602e042d2d4df5b0aba45f65a522409252cd71269a6b2edb34124b074c80d971c1e203c8f69de6d7bdae49874fb48b46debfd71a6d45b98e309414b39a95fabf132e422cb3485a11c32198b0abf08365373c50cbd85326f13920e06dc6ef3e215b8d017dcef3dc01f63da40f61b0771887c6173244a26dadb332d98e579ea135410adfd019f10592b1ff4bd72f0beb1402dfc4ba16cb0ebf2cb68d3f9dfc1b14a74e3b05fc9ca2e22a5f4ea87886bd5c53083c3402a3052f2cfb050a5a08e564f622244b6994dbb68212d45c3ba861178fbb5f2df463c14ab9c78a4e3889719cc2d2f4f4604f83f4b381a20ab0ce347ba2c53daa9ab01cbfa347e9d069a231fa20d55051a0c9dafb4d7ee3a1d5f2636c1fcabeb4ab5f05bb50c4e2aab070271d8a276924979456169cf5432a665d6e936fcb4284df7fc1fa1b32c97d6f493c7ec2165931de55e5174556c22f6849ae6303d85c20c88e940643c5cbd6112de70b1e9b3c0e4d2f5f3153e94c7ede5a5f565276ef244e4a3449af07b91f0373aac626288aa543506f48529817bfd1c04134ee994d30a5e1a0dbf4787571878250e75c29e5fe03d4493a8c053caefe5a027fef4b30d90e3bf2a19279d6d27e39fab351b32dceb3e8e9f876b65179c72267d4e14a4d4ea4e1179a6b55f14a952dfd90d2b2debf784da8d49e2253ef0f2a530cbed5b2bdf24", "1", .None}, + {.Gcd, "-836529c7ea8a659e6182f40487687f484d5aee06c93fb5a7368a61d01e8fd08ffb0c6d83c14568375c390c2a1b9eff160f6b5a1ca09545ad392b183d2cf83c59fae1be6e8ab80a6d8bc2e469e9796a9718b36c2f4fdd8cc0240baf7c5d4aa495819e16eb57be9ac3c0091bb098befbce0ed63279b576d5588fb249d75152a65e1e86ad386876503aacd31f2b36005145e66a5712c03c4bd748e18c39250e0ba2819af1c8e1cc865ade59a22b2bb67033e32fedf3e6549534d3b0b15786097beeab2abcb6d6e16ca0d8c099af9099cff0d89b2306dea04d9b7a482253b24df071efdc03b8f17f7cbc8a77bc74343b8a5d615f37d483eb2c4669ae1f46d925c9f87d8dd4ba2a9a2d8fd690ae9f4b7c88348badd5080534dc7dfa261444b83e1e1e11f50875d09a13ed57128cd3fe403d5e39299ca401a367612a9102935221a27633397776cd8b0ce5976cd51c4d3d2bac14d6386960995bd74897bc35fd42774a7f788cf068d3373309f65befe0a089c6deeb514a278f388bc8a21d2c18287cb632b65bbeca3adc8e176f35a8cc255dfdccddf4b81d758566a8e2a66a3cb360a8c7c03751020dc05a7507ef6667d42a759485522648caa35c7a8fa87dfb3fe036b8aa151ce568295a929c2a117dcbb1edf83f7972d12745d9a8538439e7d6885fe3277947519cf74de2c69181420150f7892ecc47818c058629d47c759e93b268", "c68cc09c5d870a15b53f2626e943a74d7d02d6e77a8256dc1d41f6fa5d0153717ba9e01076f11683c5c10b15968916e526535c138e5f51bd71a15ab08dea7e4251e8bf93baa57c239a7aceeb554c9332f2c07e82c898c15e5453c26a05ea248f6cc90e1444c202d60fba3d0b32348ded064e89b982d7b35807d25db5d537c0ccc1901cb7f7f3bc559e5ea62d54146fd6b73cdb482e5fae8743ccdca490b66458870c680834d38523ee057f2a155758dbfa8e24285ad7eb292fd3334abb048570b38b2275982e3e7c3f05964b330b015bbc5b00db9042dd75b27867ccb065b58f65d59a47d40226ff1cb91436d0a174fdbc3a549fd97ea3f220b0f13b19ce4d557aa87efc5ddbabc91c91ee3d72537d6a2ad3d4f089c5aeec98b62422f402e2ad76c1a4c2045215da86fb08d63769547384160ac42af4895493d19a308d30f074357389e7b765c0bb1f193e8deafd588f5ca8853c80d026c8016532ae4e927b8b3de03aa8a80792232a0eabcbd1697f8a068491ae834ffdf41171a3df32a6564d3845099b949f5fed97deff0a4e5d392479767cdb6ce51c2e474c4edc6708f61e46ddcc12eed1036882870e388656dbe32559bb4b562b49735105dc8f45b112d4c26e8efbcbc38767d89c85956fa1086b349ec8bea6e3122bf0ba1eefb46b85470ababda5d1c571670fe9380eefc0c82bc2b8351eee738ba0e801a2f4f8998f4d", "1", .None}, + {.Gcd, "ccae4c31a527a58b780f0ba6e770ab9f299f6f99cde51fe975d94b3afb55e0232f72baf8c9162fb2478cfbb2df7e2635a743f3316ce5ef490c9d813a56fae4a8a5f3f518d69a180e6d27e67f402c7bd1c0c5d0714e1aa5a3b6b473bedf56061ff22ad85cb2668e0d38b86f2b13f0f58dc00c7a0a4fe3c81d1ef42100ecad4aeeecdf02d1e021f3d96b5abaa842b23a86d2852a26fbb4987de8fcbeac95d83f2dd8c3ba0394024741c5caa2bd898535bdd96fbf87478abf196ddb9c0867d35c8b630f8659c4f80ffb7246c65f9e9fd8d7155fdabb9f55492e29609ea12676f0684da68a09a3c6c936e3ec4edf87a6d5664dd28fd90e2573b1ca7c26495203af07459df75088b29e3057e7fcff0ccc9eedb01bb242269c91c60e5620978abab6a0b42c825ac1d6c1fcd94a9c05c8480c09e401fff550f01a73e5f65f2b2a8b5c849647df9b35abc389af9ec436c756554678436ca348b30ae69ff2efc6a14f30b5dbe43112349d7ec374ffcb9270d1a53d098973e9cb7c178006e6f9d2a3d53ecf157da5e2ac10c7b3cdd9427f2fc5e6711f0a17cd5ab4125d87601ae091a8a31b66fa84d38a406f490e5524db1cbee41f785eaef6ed7e905fb9a21d478086b3d97f375ae6e65fc1abd5f4ed7caf374c267145ac2f03861701de4af0f4bf088d1270bc35bdcaeb2cc1bd112693da9a7e3d0e00b94720534c1c2b29bb3e338fca0c", "b3ca0388a6ff3c9a3c3826842813ae955f1205076c33614934196cdaa79ad52227ee34817505307b18e0772b3b6705ec40cc3abc856410ef2792472dbf2c6b9ed7fa9cab132fcedca986094de2c52cb6c4b1f6c4734dd3c4a7fee7b5a019726caa7c24dd2761875ca1cd835e2575679adaf055f4e08968e83b4eb9145c9b8544c995b5e4f27ec01bf73bf7bca33c8e6ac888f8d88afc344961650704614bc7dc4a072678d8f61b9ca935514ee149a8f19b3a02ad4d7925eecea05a23991c751027a7ff126f9bec5acce676486483e466ede6a393f8018a3489ec7bb6c7af154eaed046087c2112fbce808f464fb8c92a7572f58f8bea3d6512843b12e448a62552b3c95a5a1fe565e4a863c83b7cdb0d81a9487658d1915660dcfca130a5243435366f66480717b653d7227a43587beb33e4d24386bd2498344f84ff8d1703f8fc2b6ae746a1094654d4e2f80633fcb59d60baba074043a4f481cf7a943b4e2c127647f0206709bdf8f02fe5aa38d8eefd86720be4a33b1e4c4af9f77ea483c30f0d27c01d8e5a3ed49ce4834f80bbeabd5417d04645bd16a3c1ae462590f22621102c5c2090accac4a19a30742f3765c4dcf66be9fdd514950098d8f119ebd58ce9900be4ec17a5e924edc704a45a63626fd81d207e659f459504de1379119fcc7c37fb182a7e9585fda596f0fc3aba9ea4021a5c31f67290be454707134db0", "4", .None}, + {.Gcd, "-64bdad10eb276e0513e1687117a774d3c174032060fcf2b8460061401e274d53e1d3383c278c9dd4a3af90b1279b6382b3d4808f5dafaee0142e7af66b09658d60961039fb56c9a5b651d70162e9fae119490e14c82f8477bfb0e6aae1eb8c0d78574b4b908b08aaf88d3ffa18b24da31dfff2ac016f1060a7aadc27a87fc3f48541bc463ad861ee68851215a51ec7be6ac63db2e0070c22d3d1c4f26da334ea6e7f77d4d8fe0919a3da54a44292d4af10c02aa5c979dc954f192addd81dca20b0740a7854b1b7ba827b05ed5dae02dd62376454a68a939ba07aa4e818101f84efd0de5fdc687b2c4b154e9631381c02c885346ad64aa587a31481f2ce47eee9739cba0e7f1065ff2f923bdd104d0dd727683bafaa738315d29213e7a8b2471a58cb81d28117286efc846f746237f8af1312ba7ddad12c1ef8403b93ffccc7833e30811952a9808d02f5ed2ddc9cd6cbc0b13f1d89f4c73406bebbb0c855a2d0832b88ac1485fb929961647b82e8ca2d0951893a0ab50dce7935fb2bebf0b1f5dd96ee75b24ee54b27766902712c31d56506a83952b76176a474a5f05c36e4c0fd177bae01ae4357e2cd0e22a55560d678996e3d1c4e3ddace12ddb32376accf841c1b76c0f43342262d7b6f7c0cabc3d123b61486f63435ca7900291e4412fe9b1eeb21d2b018d6fca9e6ab410d8a2cfec41122b0b8896e654a42ff169800a7", "a493bc1df182430b273c24b54366dc20391c89d25c8ec146280754be1c8d0030af9e096f04af6be5b3a63f31f0a0293ebde537954d4650eaf23b738259d632212612d9707267c492dd675bfefbdb5dfe9bbd2cb1159759e851116af553b4d0885bb192565ed045ff0b5a8308e65ca159a73d0f576ce3fbc4c1c29142f5dd92c8980fe8b54ab413098d3f533232e53741d51ad70d7e0eda229c73f064af64fcc85167d3e8b949b406186dc4e71327770a1a838b6f4589ba5555bdcb9ca63d5a49ffbdc8559ec4904e213177809d99f6b93d8ea18adad2b5ba22cca479aa7b54ed6e9f58804198e3f2b12f74f2d295a1684c991ea6756b149f5c52579d7a5d0bec98658fac4ff081285e4102c3ad1e09bf00e5cf24a242db83973e39c11a6bf4e9de4e983f970d202309a2fec271aad47831b431eab89e21da60a5f25ea0f87e9349654a904c2995d3ca60baeeda8aa9083b0484e09969fe2a2b89aaa44030ea34c06a673c29705a93fb6b0d7b4e9133465547c847c1c2507f996c1f2c44857069e5174df5f8d86d3631ece275d41e896854b2a96daf51a1862141732f37c6c8fb91a0066e2bcb27f9afcea5624955348116d15abfa21f4a317a788dbdb9bbefc669edb9323eb858eeca81a6fe0db251fa4c9f816e010a4e26d1bfe9e39138a488c74cf91ed48f6d04b27d992a84e0b4582173918c9245b6069b6099ec000a7de0", "3", .None}, + {.Lcm, "6184903280cfd109612fea50256bb66b9efadcad356932eaf78f4ac183fc7268a3d37eb83997960f2552b719b1739fa2b73bcf1f47100b5ed55f8ae30fa56926852e3325579dcd1d20916de5944ae0e35a09ef21498e6cf732887da48c18060255f384b2e88f764ffdc1f582860e4663b461b946cc84e10aa156a0c4e0d41dbcb7966a14afd80b9e0b03f136fbcc48197548b32d3c8b03384f1808af1f3efbf9974d9a933954b5c41be922fcffebb5acbaf383e87c76b06b5dbd4778c8c8431ef42c48bcc5574d44135ab2e84ea13ff4d96a899552c2996f4e0895f89898a21e3e5e0172c33397fdfe37751f077696d3c10a4c22949109482c35d5babf0c73842acf01cb18f3549ac2fc46cd884d9a71a36d7153882a45a608131f6af23527c01dd365ffe1c73cde9691a42ac886fa1ef32cbf7142c2a5aa76aeffae59727bae25f8ba3b42f81d611fb3875a9be53433e99a20ad684e0f9585aa705eb0878829587040ad676231539b11979a7d01915d4fd8ed002eddd7a2ca0401a2f8832f6f6c536b17c3367476904a830774aeab83ec82b999cf5ef0820cb385b6018af9ad1cd82a6d440ee87b3da96a50561c3bf7b328c62bab593d27e29661c6a9cffc38e7a1a0ab27ffb5e7b578f139a0464259ab753e26a750c02d2cfc55acd66c77b8ce530ec1b956ad757c0d233d8ae230fe43f7d33b6ada6172030fabf4e649fabf", "-5787eb5823222222d8068f2f1232a2b7800a981ff58ee49c14b2b3f992cc7a64d0bb541bd3cd4d3527e73cde2fa7f6e389e453ff833a4ca31516f57832d9cfa45a25615e53567de0b719f31ecf7dd460a843d18d68b49fd67c4ce1979131fe9fe9bbeef127456b3fcce291b511323b2365662605e759c749a088ede53ee9c9ec045ed571e04ddbd6d04f0eeec17f165d6b8fab3b1d38bbd6bb55aefcfbaeaaaf6ca3c8a60547e9e6908daefb366007b6a4027dca48fc51dad529afb48be94d3ef10085da4f530a4fed416ca172e25df163205977e1c659f8805ca11d7bbcef1459e6e9f7331bb1a909f473b304f8de2326dfb177ecc630b0b398b75d431da0fd69772c1f67d8f2ec1d08573683481164df91b1841a37b77e537aaca2ee7afaf8f3ce6682a2510492918659fe7ff1edce1bd96a3a94a2bc32836e5c8a5924daf47bd19bf11c120c5dea376ac934f5459d19c44c802925ac0229f87b4aca2478fab5dad9c69c74d13c23157b287d80d1b9e2bf82691277ab42736414ee310899cb619756ca6787d6b96fb05efc8243ea12a275f7ab761e171716df4d39f0fcb26f30a53630b9ab5e2e905a0a6f577bc2a3f66f11e3e654f0a0179615c564f80510ea9bf85f12443e3bd14ba89e67926fea9c9d0bfc40e597496c970f20a29e75c38c7ad8b34fd94322197a93378f309bfdaa5773288f6707de5bb76ec6cde60c5", "2157d38f77ba9b8f67aabaa5eb2094bbe95b800af416a8320ca59430704f4a16f26647ae7e98c141882ec2f51ebcc38004b82d567869a9ab70b15a690b27d7a3a24698b338405c7f4083632ed3dfad33f6402f5454ca5a940c541c0a86105a90fc1c938d1bde64a33842b3466d203eccadb75c92f2c62004969681a1871e5d11597eb340da4a0352bff7ee3b270bb57370ffa692beb7b656a68433b9554b3f72c1409e656f11777dc4db5f84d2e201c59b955952294f000a52e315c72b7b54913896d73cbdced29d571bac005875c27dc6a36ab7b7b0fbde1895ecb0092f90a3d6caae50a32d67639dd8210a65e6e5b46c2191f0e3410df32f71ed7302e7bc299ef71d85de83abc4ceda8081917a2a10558ab8eeb36d3e763dae85388dda0d26fc4f789a4e0c4da8372527899091d0d7f766c36725e7ad37de07d6eeedcd53c757558e8c16cb50ca13307f0d8b3bbbe6ec7444398d62985b98a1842d3a4ac4a3db2fdb819ea8765bdf06de937cfaa98c19b92f05970990290cb00226f454d627bd68e33925b3d81735b32dae4eb2e61cfe93264effb2ae7dec7a4bc5c661869f67858a93e72cf0e99b61f2a5bd65d59f3a867f99a8770083cc8cb760702c88266b20a86a2b4ba525dce4ef613ad90f985771fa7a850042cff7f23bd5aa48cc8b56932982fc1c1c82ef6ef93214051e9c40499e0de3d97b00da8150ad73a5dddd406d955b1391f10e2847db5f9b7a49b44e73bc0380c6946c946f6892a6c3c1d4145e59708261be6c78c839f957fa188db0657fc93784e82c572b04b70127aef07d1ec9f1743d50298091531e6e6c4347637fdd9623d574a1cf6856624a7a363afd08f20f720e2857d67c36c8acdc06786a3c8487437b51a7e78ac6da4f33e169433bb9d288d76592f90c7dc1a03fe321946c0f1e428bd4354cbc0c796602e698fefafad1bb467922e2f8927b13648f42922b8be152aecbf73687886560de50348b9296506aae4978dc6116fdbe8c3eea7b1abacbf09cd0f2e2478bb0e2bda52e30978e5413e1777091433443efec13b573917ef01dc1f96a78883b7c76c7608797f745f7c28a97919caea893dc1c034a755998d62bdfb491fddd099bc0f830a4f6ff0e0dd0360322a022742b337d2573b19e6092167b65a8e9c854799ca581e0432b32895325f1dfd3eb6ccc41f4d43ed98072328ec65b4725e4f76695db623171780fb90364b918296ca60da9d14337940a088ae482b002f4b61b2833b821435eb5d4bd31ee8d0d0f77fcbeff649b812600c99f9f8e80a687ceeae10e2a4576078e309cfcc29400f4f91d3f23abb4edb3c91f2b83022c90b8214a9ae161e6b1e97c0143655a0d20b6b25f50ed93d20cf30fb3bf705509b3dec32b4dfbf738ec96913821dadccfaf8532932f01f6fe82373b8ffadb7ce89155e45d4fa9794fb", .None}, + {.Lcm, "90d459f3c0a06025be58304b98a19dc7e6c7d377793d56b7965519eb1edd4bf8b23722633f7d197e30e2e89e08f025b8f5445e03c074b6310a18a2d9527b776ee3c2c05fae152abe149ebe31f3ab98eca2738ec417fe1ed43e7c3ecfd2087d7ed5b0e581dadf6b3b0f89ac3113dbb8948d91ad7698e5e289467c3c3ccac8d7a7844670ad8ea4f322fd269d6183bca57e8a58b33575dea3820c3108c7b33cc802416b51cd0ece294c3ba0105911ad14db3ef173d0ef6cc2db0b0a94fb70e820f19060fdf335bd8f9f97817657530cde5b05ed5b1ce5f62a914601f67c0fbb4946ee4f778cccb182fba1642ea0fa6e2163c4759a43bf4f463aaee07da592f2e80317f5813e6141310ccd5cd3272c494c1e65535099db09839341443f43becdee6dcbd2b408c4dfb1ea82ce088e4a8a362d9823df9d9d4b989be2735cf87128b9c5d18f9401631ac7eefc547f1f4922052b30c56f07b84b597cf0d6935cbbe122c032fbca764378f56455315cb3e211244febd7695cf34126bfec8fa7a336fc8bf400731e637ae6c308b83c830117362db6f6c9d8eb4c4a88a917059ab559a3084d0bec9076e5025a6a09963b1e4a649ba243966c4ce88605d6124945fa782a79787109fbe03dc52ba943d4e22c4d48dc6c9ebc31f169789ca7f7bd1d1f1d1ec6e86746d9bd97da801b8b3259da002df7069e29556cb15aa5ca2400a622f0e3ebe5", "-7efd6854a2afb71d446eaf95158ad64e45dbb232f9710cb4f4e265acb90a95b370ecc7126aa9ef4b787535d48514aefda157a6d1b6d5bbd689d7c8cc1b78742617f9cf5c0c2d5be0171603dfbdee80c54f089e3abbbf3972a61dc448a4af320f98ce2da7f81ff504466824e0f5c0b132a2d1652c40bf43b32e12a31553c26e830a01aadca4b5309ea801647780073ceef93581f7036bb1449402fea87588aaeea545e585975c8ac6f2f9f622c75042aae30db713af03e8a19e78a5b9e9244493bb94cd06d22101c8da08f54cfce02f1d99b2c124c2000ca0dcf0678c1ac6d8efb6560f6ae82786c0047cee51f6f49241a1a8f87279d117d36b6ce3b02a4df9cb255c8b77dbbef444e595f79ecb0415c5be20139a4a788b7ab37fa18edc8abe3f8b41b133d8ff809f06d1d12f98cd299a43a770a750be1ce5aa9c546cac160ff929bbbcb4716df93747c2e27ad00b5c8c6debc43785d7a912d29e1e5d9388ca5d429381a6dab4c39556c6a4b902a255829bab6ae38f58a4208b2dc899c2cad4abbee1559bcdf5213d57d4d561903b1313a6f92b7219e03d9e63ca1e682469795d2cba194a09f7b2aa83968821455cb719fbff84d6af246f54b46a9e1a5b045013b3d3bda996ee20abf0ea9ba1369071dab79d3574bcdd8bbefb8483f8867a7926f3c4770570ad8af842fe0e91018ffd9dc512a63358ccab1e260580a1b0e46ec8", "47d7e12904f6a1bc0d4406e532b80f78e1843211992878abc06683a462207f56bda908689405fb4fe32865ed5db21f0430725b4858f18d4effe57e7e445b2ced1635876e49045280b2099917a08b55f8bfe3baa9dc3e2fe44c24c1e21d8de7b6ece28476761d246528d59e7fdfbcf9fc050c15932c8847493631c7372fbcc8a9e89fab588456cc2d4c83333c6fca1a1311a3b74e120369182bf4386b9f00d9c22f8e04c7aec767454711c0a97f17d18448e06404a835f93189ff8dfef45edd13a3b122157a1830ee6e63a02cdf0b0eb4e60b49db82b9bd21122c5d2048107cc633eb2ba274f2ac650d8b34cc76a48e9a000a3d1d97c50e31563ff7c02ca3ebf0a1dbcf04f5b65558e662b031fd0f7b43b38a7be69c8df223c3513b6cbb0328687b3f3980fef0315ba628c1ca5bd815f6d4486f74c6b75d97fd534757cc3106f1f24c138086fecf3814a3d427aac2872223358d4bdcdc77bb4b942adc4d1045015a146a1f66d43cfb21e4cd414e61219ae1b87f3f86d8d345bc549974116fd4dbe008348414be542b7fd6528aec808dc2917df66fd278167c078171440bb7cb2016be6103904a78e73803c5d22c093520ee293bf81e05ac6e9558ab5e726a5999620d54a4825ff1647d446bc344063bf86e16f1d32f5b99c44bb473904fe70a3575638723b6516b0d093d803d8ecac2ab652d61414f8506e720f9684503d0b239bb3dab8d8882016a35b917df315009826dc9a26f8932e3f7fa3f68315d22abfd5a10c4f0512db0a1e808b8a4e9b9c53efa158138ad965fa462b41db0b3854aa11a8d94a65615cdf35dfd9569a6de7cb3a0a5288a10dc452512af4c8b905453887278b6f43c307a600c319ed97cd186528dec13670c872f9a4eb6ebe8a09b73bfcff318563c77875ed0a724443e2848fb892eb1dafcfc21a4629192e2669c4c6a949054f844b3857226e322d250f457f9bae07bee454b3b081217adb5a2553b6147cef0bea92ad2077a16527f222eb6570bd99413bcf907b7ea36365938d3f40d9265e69688f1788726c03a6d3063fec5c81e3dc6230d94d6ba7c1f8042b656fb8524d6a4f57101bcb8ce063f96c723fdf1466b14ae389c8af78eb2690cffa1c803f5ce39bbe265617b972cb536a4fad331b1eeecd96033921916222f8a5e702a97245cc7b3a7c17842f191c4864502451a76a6787b02a0e31ce8274bcb42e1e5a18a59aca078e244cdcb3f62a6b35174fbae40ebd8ffc41980c70e9b66e884b9bd989942614f77d34ee45aa98293ca3a099bfcf53f65794bdb054b69f01936e732164cfdf2a938b588ae0047ce09e9fe96a23d5b1adabcc4cdb95fd4c47f1f905101749b16973c6364bad5b739fca4baeae10e50af13954c848d2738e5d84a6ef41b83940c127d5dbe78c344212d899be21974f9b484fde97362e6fea960b0e8", .None}, + {.Lcm, "e03ea7ace1847a65d119c2d241024010f9a084810365bf947e94cb5d57f3394fb720ca127d8a5d607d301e8b5449802830e6d03c855b9c379d5e0f6858edb223c2f2dd316709a60a4032781eb3d0e3619ba5741d9bc789f34ef5f05633635571c4fe1cfef4a1f18254612b7c2b76b9cdf048d260bb5592f2e0bf6a554f688a52fbef61b9bd280b28ae7068e8cf02f74db4ee7c0ae2976bb7aadc9729a558ee73aed7b43f25491d9ed18616245de414945e3a0127e4753ee18834061159e10fb6fb62b13bcd4548e311096f126573fc007b0aea53963ad306c2f61b5d8360307d713e6f3028ec06ee8b4a645e91060ad8f9d21c9f554a05cf029310d8a492988bf1f3b63f9a17f5b2781648d1c2077aaa641dbc3f552eb671b7b5a1b7d02c94a29cada7949e007822f957d19ecc1fb4f506087bc5641c6b45e78111781f1bcfc4391a06eefbea8b5230b2e8e8c7ebc9890b908b02a9782a30f7d485137d04c0ed577f851e8fc8b4e6c13e3eee371ff393963da754ebda56f0c77a8351a837791bfc6f110f823845b3b578bee044e0a7172fcf2781b5de47fadc1541ce87e1993cd1af56d91c89965882410370b79bb7641f8fd06015f8429ff0bc63965f90f32ee072dbe3391f6731f1ab82a3eb0d80e3bb782d11160f1031c9f0873f82067834a3092191d1e1c006504796274e89ffd93eabfc72d87ae86b7512ddfc89edf33e", "-1c2a74143153349966257c0871b0a87b1a4e0c67aecb11e6347b6b2ff666fc513505597e9957cc08939c3967609e8a95af0a39dc60a604289aea287dc7fa3d03564e81b1b5dddc2facb86d7ac4fd9592777ca40add898eddd0ed6b68a4170a49e12bdd643e81fea50d380347fce1b3753f3e117972c48ea9dde1f9d4d9fbd1f5c41f050f453e67d259135eaa43479f914c10ea2c7d3c40c9e96198f37d33aed8a83778f24799acce00b612985f720af0e92d77d63e291184559bac5627a43a8627cf7004a56a95ce9ebdc15ad7e9edb9eeb1b3c639b68f9bd3ab78a3f3f7743e87dd9fe76bbae0fb1270dfce80ddc7374c312fbf5a952f93799b782e90764909210aed71239b8e6bf840b90e9cdb3c1529b09f31016a20656ad78af28e2fc816b17ba74974b793d3d18245b1a53a63a6935f58fc4ae9d2e18c74c70240332e361fe78075dbc77cb7c23e0833666698d329b55eedfa7a5d7d5cdc7922239b37db684ceb5b1598ac19dafd2a4843d177b36db9e34a7863ff7a7490aad7dfc879030a8055eb9c67f15adbea619819d8ac4ff1b0f787f1c99527e9603c9b298b5d2519cd08cd2a3e91d340c37ea74e717f459829dabc656c200bc0971bdfd27b79e2ba4238c978b79dab085ab3dfb923ace0dfc8b358160e6b895a035bdb1b495ce21e63eca0e00dc57d2cab70b4ab1fb89356995da44d5f270f4dc71c56e185051b", "83958c42a5e99c4238724163b30e8265cf895b20cc05b2d899dfe565c26d5b6a4ece2c41ce7ac5f7d78bdb854b9ead9914bcacb96525cb48f3aa3b91ae4cca22cc530ed0217d5d087c6f2a210a3aa0a50c04ddfc8c361bf9ec69508cf12bda693a26deb8ee3b4770aa54e58f7bb08ae915733a8c39399a92889d5619cd217449f2ef160451c24aa93cbc1a549e6655658610bcd7e2d81d0e99d6b86ad2021647081a68ac58b5ba4168cf06a032a42a668ee28b4cf8c2da72b671736e65658fc990fa3729442f815eb2b0ac118ef6e74e4a486f288740e6e9d6342ee18407340bb54d31a47b2e360afae3f48d36596cf4d48dcee55c2ad0844786efe33cbc09a690ae37c44078e82160d40f16c71097169645965c509878296d0363e9fe358b38381e2a81d2252f98347e926ff81824ce78095209a9153663aaac73ebb5dbcec2602ccc07b56bbdc1a141eebe10857b0c7e2be71af99495abf4f32bf394c689391f2634418032aeec71ccd3836373fd3a7db6ecab8272a6e7baba7d7a4d48ff65ef0b73bf2d5661d37b1ce620925c42406742866bcc0c3ed3f9cf4e89be3355c53764fc8d261cf45df191f76e943f55ea7caecf472ae0ca9c2fd39b81b6e48cd5a3bcff114f4758668e5a2ad27be772fbc2817cfda4ad74957eb54d0ffb61afa2e71691e5f036a2ea6b6813ffdd8d7bd06387cd37605828c177e04f33af89963a18fc7fb244c0552a0c81340017340def428a8016e20a95be3eb388c7d81e8598d0658cb76ff3fc4f60ed96815c991cf6545b4f44a0bd7780aaeca9f37637e34cdab61950fc9967c5f21df12fea13910a14ca455eef272eed238c8fb17f27e84b0fa2b5677ad187ac41f5a058f31441e380068b7c35f7187b379df14c48265ea1293320680998a3554ef9996d7f204234267d696a341acaee1917b5deeb093556843bb052bdaf2ac62b529432767ab8d7103c614211f6948c0c9c1cde42fc630d71b806b9300f51dcab2f9358f2bb35deff385f787af52eeb6f157437148e528303702ba1bf74ea81762f6d8f5b134b2b0ef473c5625e11809d04ccda08e25264dadf204c64382944115173eeb641219168deedcc9206cae2ef11a646cd78bcb25c5cf09b2b7d819a8bff247b11d9c7a9ec6bb34070b7e30a64199c7253949d8216859615f94398710620bc868b83a97331d058c5d787acc8ae0e7169108676429ec8f596f3cc67eb78eb439f07fbe24c4b43d312074f59a11a5f743f50b6e2738b3a2b63b51aaa42ccd29a66e7f8efba9a2bcb8dda1c3300679f63dd50bfcecd3685ec1a725b03f5c67f72035922dfff96102730b7060980027f6c794fe099b0c5ba1bcc0c7d1ab181b94e8a52dcfe6191dd2e0dab8d603456c27bf9ea47b7715276e2e5ca8042f0bbe7d0fa450be77197ad1ef31e1e667b2d48b85afaf9f2e", .None}, + {.Lcm, "-7fd3aaa2c18aeab2bd0504311af1cf449d3a540835ea2e5be508326dc10dcd6ba502806f18c2f792a25a179a4cdf0363dd770b65c13f744a5bb25433c561c8cde5621d34f73a802dc82cf9c9b0ea32033b32a46cacfe9b10388920c9752ac5dc09014d54641f0c0a36df6cd5faacb30e9cd6425623da1dd84896c2d6d8589aa4d4df1cace873611ad567aac1fdc697cecf3fc404163cee522ff5c2c8679cde8a2c5c012af131c3624aa26a3998bd97108491cf60f293100f43b3e9ad93c388426a5c8bff97dce870376d74ba4afc051031f8606b1069333002048914a850bf3816ca8e7e135cd6476e6f30f63d73c232d288f5baa1ae0c657b27abcccb41d4afd61ae5bfdba456cd815de71f67e937aa95fb5ee19080f30b5227d71bdad792c7958f449f97895b2f4e397941f46328fead4a59383015eefd8f99336578a7e1258be1c76f400fe75e094fae81a5801fdab0d51baae441f7066b4eec5e672c1a66960908c5f9aa7c9664f6e199e9c37358dbec2fd2aac1328382d2d86d7a68ff71a3183920c980c6cdc5331173b6ab5a2e36d5df50adf3b0c6869bbdc88672ad46359bc48cf0ccdd740f82f484d0fbecb94fa8447d0423b5d1e8cef34204cff41f6e7dedf13fcceec5aacb2e8f781df7e3996109470e0cb87f3917ff39cfcde42548c5e2b504da2a485e23335873245e634ba233c20c3c3a0d36164c374ea4e7fb", "18e778329d0e408be9c490e4cd3d564eedc806f438ca66d089cc22fa384348d62b804ffe88e22ff5d925a5d7a922a57fcb7735b0d6677ef1c6a6499466c6bfd8a89eee140d7fc518e16965902498e37e4d359016f8f3a2d9eaa82eba5c67801b0d0f25bfa0c991e49c6d88daf3ee727eb2f832eaf936c17b15e84131043885f768142402117fb343e3ba19526659cb5c32aba374cbf5fcbf67b2dd3d58d8d21c252fe5cdab0b81e313100feb95661270dc32b942aa15dd4431ce2ee53da45f018c2b07cc183e854e841f9222d3b5553d9f9dd29d8cfc377f26068c9b87c366b7b2743441b8e4170ea9f1e0a87c6d195b0046dd0dc26c25de83607fc672de4f0c1c7fd1e2c8c4fa551aabe052c6d5434cac6ee169da41d8e9aa346975f6eb8cede1b36252f0b4768e99987ebf430f66bcb403eb4f0373db13e3ba249d86d4b20fa0c049b2263ff5c430ab21c564f2ad52c229a098b3d0386ca582f65674c79394b458048f8318de3470f47640e9a830cdf374ea034c5b5558a67d7fa6b97f6e8b9740b85dbe408efb84dd96c0ea93751a7380385a329000e7d7f092d96e0c6c6ac480c9a80ae0cc890ac2e662cafc27155fe6f0d9366e0432c3ffcdc6104fe7f0b69c2b8c3ed8d6444628be3fbc6b5da9d80f03c5a348c5c205d97fdbde56991949f2cac97deff5c1d28f924d6f9ae8bd1339544c6e24bcdb7786884a8eca4bf7", "c6f6c02b8c13651610f926f02529df6b1f505f9cc093d2859ec4d418a6cade65e858763a87b4275f717c7178d010ed714c22eb7d4a6ea8f5f6531b8cc4c12226d6d43f6a94bddbdeea21d1d3e70468e36b7a5ab1ae4fdcf2a28a260080c78fc249377c856181dd1ac39796151712c209319b7aa06083122d12973825795912ec6a1138d970aad4662bc28bf5ec5af365fcf26c9ee53848d16aee74b33b6dd6c4146e0beae15607b7e9730111304ca6d609e8068bc6ac9e49b70901e28e53e41fd9a888bbe7682c9725c8be40919e2cec6c9d4a472cabc2384b454be3e435e4f4050cf4b0d8d0469306d665ea3284a7c99e448942ef960d95f23027e4b2f3c5172b2b887bd186804683dec9cf8b546bd6a8198e5d3a038e4c06b4338aeb1693f96f63c37030808f2a6d7174665f3dcdb64eb33dacffd8940c20803aa63bba25bf7927b5cc8076d59d8d42c16ccb22a24fe5a3c91c5e0e952a1325b14ef7459f988f12777ddf8ba4c602112f47879537458f337275fb3dbea20823d715a21e0abc24cc0cd3ce8dbe9df512adfbb5f0df298342064b684b1fc0af18261e2eb2b8f484286f9e3ea20a9925b4e8eb3894f91992836da4e04d8667e37d544331211e256f9c8079ce3080d8541f4bd06efb33348cd88d7d0ce09dd9aa705115b1b269e900593da4a80338602041ecd00df3bb2d304c006c02c783f7702817e7f78d5fc8386ee3cfd90810f1c59d5fab1a64ebb91805379a3a46ff2ce0f9fc4c03d002669f8c18e966060535ca45df6590c705ce0c93bc9e7f11fc322a4527494bb6ed99e6c5f0bdb8acd407e555e24e6c1587a8f3ee569a49032030ccd9ffdcad27f1034a521c9d0888c1bee5a54c6ca525059ce3faf24c51a33316367cd92f4a89c41853866a48241789bf4b7ae1f5917f854d174820f8352963f80cfda3e89ee013be96fa22ce0f1bf39c702cf14352b8c94c3deab5de65cb5e8e772c6d9140d4fcda2bab6e01f8239f6f0eeb54c314ab8dbc1fd4fe27d8b3e3308266b06572620d88e55c3f1852ac47d4c29d3d53a1fd873676021809456c874560c9d86d876990d7d34e27226e1fbb1bcf7e87abb52451f049d6219e85bda8166a3805b741d822eb6cdbda744678206417801cf38e9ebf67f9a5b494d862fb115dfa1dd1a38e0a27bc6ca4804d08250f9dc1e09018abc0580b7ebb7d207c6073403f8de6668ddb479723a1041d33666f7147614322b5cdf459a784f78c5d6cc42ee3686b6ca3f39851764d6d5cd9566ccd981fa8aa355cad751774b60dc7ebce096b401127217c21f9280b306be67b671f4cd6a0b5b7b32767c3b334b531c12366f16a842ce6d6d88355fc531b4323ccbffadf951d363e7559d2cc4fc062b3aea3ebe02c48e73661582aadb3156da8bd0aa470c81b11222e57349a385b6f11afa65aac177205c2d", .None}, + {.Lcm, "-64cd4314cc26301104b057502bf4d81c9baba4a7e785091e7304e958f03e0c9199efef4d4718be85172997e8e9e61db693a505de341faedcd3e7281a191d49e24e863a474f9f659b6535454f8ed2165efc0dd4fb46edd442c4e7371eafba2fc20455e82ddbc32f11eca50a439555a772d242cd7650114c369b59275af57b9b20c4331701283631b8b2a36285079890328df166a2a01d142af4b8235336a38c97f0ceeec7dfb88a4b2e49510434609a00ec38077acf3abef0df2efddc90e91a7c97ff4b2ab22af7a281aaefe44f92dde79abbf128164ca75d1e87b5d6cb496bbf05e90b89fe92da13efc7ca6f4d8032680cfe47a54cf5c9b16b22f2c8c6312c142aca04ced9ded5d0697ebed128146a24d0b0a160a394058387f058c7d2d9c4ad1a2b7e5869fff2711578abec68a76cfa445020ff17d369fc1dd8dd413abe200c0e676e8bf6e7f5d6add46192f8bf98e3369af807feecfdd07f6192cb38ef8448c6c5abd5ee2cd9402e21263a21920559679379e9ad6e87606656b00f6ea22e24509d6b9c43a88271c5993b3d2621f0be56d411bf39ceb2dfbe05a6e501b51355865f9239e08e44a66ca923f18820af4704a3619ce76c588df951c2fdb15d406b33ad4a0da323111566c45354f2819d3dcde16daf311e8423ac8b64f339abc4e5b277426e83044d5f6dd22fa2998dea6c78930ce2b65699d57e3f14af60215902", "-75d1efd3304bc25c8248415b3137ff0e009916420d58c10fb6a81d305857bc08895b0a43aba2a0d342ba42b3bae19a59ee49fd1e79d1104270c6614ed605028e230a73de83ee0a15478b2b02a2892d04b3930f7fa42db94a98e41c3b84b49ed7e4afdc3adc05cf24ad69f6b07dbc945a7cac50a9e705d1004c6aeeb01258413619c7145969ac4439bb043449460196411d8332236fe1fdfc47829aea9f14963d09c57d95f910c74f9abef20abaa7b8982f5fb0065bffe795d42881727a718266aa6bed23dc645e3146ef3e785d0d3759e9a04fecfa5dee4f8e4591461aa150d52bddda83db7e348e26f9bb4e5684a4c5076ca8d36620c41368052686d9664c78599fbdaa8d82955d9dffd482577e8380b4213584bb7c2ca217b59c3fde9b2540f6661e9ed83c43886b93934e98af982be670fcb0ae4d879dde11bdefdb0a83c75024532cd6690d8298b889a7dbcb191522daa5528dbb4fb5b6fa837fdc439326862a5d2e1591ffa8294880977fbe95b3194c7e63303c7b5d7294dd941e7d6e7cf056350f6186b74446a12bd94278dbc242046363f9d02a358dac793434144f53dee9d9f0d9c02abcc8ed34aa2c0f83e099b8186520a654efb97dcb229e97d35623ddb45a500c32725e380806e57732d16bdf1c8191e8be04eb02cfbb1dc2bc6bfb963c121d80d041b4e3855974708fab149f81cb074ecc6c55121c388183cdc2", "17323cd5878d928fbb543997b9a7bd9d060db296fc83a7f3770c608c346a28a70a02b8afb28748fcf9a90e86c30f39c623dd1f6c64523c03ccca771391cbe6b06e98346f1b4cb662de61de24e0f5d6cbec65c79563737da53d94ec4a601f78df72fda529cc3782757de5c10fd23178ff59417e6edb8e54ba152f6cbb40b112f53654bb1192ff729303625e33e107f0737cac121b67386ff07cccf7116701a335556bb50a4e40d1be0f0f1c84a45c7810eb243c03090a6c306a032435306bd14658c256fb368c682b5744e9ded477a4c1267d4fc2309eb7b936735aaa276d3faf6c29fed83d6bbbae93b3776ce7f3b5181140c7a80f43b279dca2a29486d4b5d37f93758c54f953ff2eb671c62906fee0a262b7a0e20bd3c5815c2e3973b8b6629bd748a0440bb8320e5f977070093d2442eee8bcc2f4537b066d54a643935d2a9a663fac2d9ef2c574001984220ebbd438f04b31e538feb716649710c0018183aa583fb7975d1881acb10175b170566dcbfaaebfe5e65ced4cc583a771070b43fae8edb42789d16c02ea5a490038a811592b04550fea5c04d1dace572f5644f9b03287f17dfc4af42726d579e6eba2dd96937436fe8c40b7276d65e618133a8e5a7b8c240de7867bc578de3f6a479305167e5396363801bb9dcc21ff59fd1f30a5cad9c1349b88b95d3abc54725f890e838c3eb5c7c8d9a427b5da48ff6f4810644206faa8aea3aa0a1b5d1fef46a2780e73452b67cee61c9c8b2256c4486e19f8dd1cf65d34b28fa55bc6e40fae61289176b306217ca13b8110b6bcaa281741c2df5bf3a75f727d5277d8d312f663c823ed5b84839602b9b3ef66241cead4d8296c05dcef715a4518f3e1a2dad43abbe35044f65bde3de8939eabf2d7437c6e62f7e830466050ef6f510b7f1ad14a4e34a505659f56e9d914da614d8cb5c6ccba7adc38afadf0c2a4af5779825f66952aca5bda96ae00e0f7388f3dfa95365b86200e0b6eae008135288923c8054e0221d7d332feac3039fbd85033806211c871cafd3428cee174fed0b48d6397710fe73860c184e181a0a1a741e728dfa3d0e1765db55b4a25b06c38ecc9fcf476cae5c9f8912c4d724e8b0ae465de1efadcd1dd85ac50a5082a103dbe0604960dae1fcce1c4bbddabaf6e98125520004e701b9cea0bf1a25d3d5ee7e973b1a9010f938be0b54a766517eef42923faa6137498e3c9376de24ade524504bbd09eb753d3b0edf332b61be988293df0c6561bdcb71c5d09ad014cd4e08bc499f6fc7c15bc214d18ee0837ef26bd5e5926f63c3b3d1f67b40bec6bc6d971838a0f4effa616316334ffcb386c26d8e201d7c6bb4bcf325d519626f24d2ede0e05d4cd455953847f954e8c44247a4e8006f596aac2fc54ba619b0ff3111efad995857b30150f85ac9e2a4c4e1a5edc661e0dc906c2", .None}, + {.Lcm, "87ae7ae408feefb502f9d328be8ac702d76a1afed0d556921b7ad71ea81606f86aeb1b6df73a6148cd25c31168eff67f6f989297ea648f133b1b9117e599a9c01d819c67202591e9d93514141ce1ac127804f87e52558db7ec44eee306abd2a2bf570e6ff1d148c3bca5e92ddab45bd7187b02858adaf01e9b780becd9822ea3488cf6b244dd4441f819b4f3005daada3d4223cd4fc0f3bbfec3e777e3fa48e9846ddbea1bcae073c4367d35bf5a42553b0e47a911b411fa36b87cd45d9707dd155d85b295e0a0470d8452fe1aaf78c212561351a625fdc88472f4b8a324ed7e4b69b8dc05ea73735def88885d2769416d23b2a398e8f12523b4682874a7fdf5f3a20f2651206206efc63410fb2296ecab2187a92eacc656ae878f6f3586aba58e1ea9838d7bf7d0d1453cf1bf7d32ae9f6730cbc06429e62494b61ccae7d7b43e7e8cd3c41d00796ba3631476d9ea0866852522a9238363dd31d5b94d3bc0046c8fd03b72fc2339521e73c8a75ae7c1ee7e83a6a49ed31f9f0ed062de9913f2ce4f19a35867084ee09e96604e152c3e5899402c7395f7feac2119c0c487e387c8c7aa8e271f1eecf9e3a55ccc84db1da38401db3866a06dd17d10859d8dfd754bbe30fdd72156e06d5db1ba0a94c1fcde5aab23324acf7df5ad69ac7ebdb340150c60982c859d61b8f04a0b431bef6e4c90fd574ff18463edaa643d7dfdfc80", "-bed379fdd4174a8df159502bc7826dc1067c6725db6be6318ca5c29ff52a09e7b9183bccc8c6a8bd631e6689feb4d7e301948a13b86791e238a52ef87512eb1b1fe5a67ff2eea4dd729edc498441f216e3b7c2cf59c1d518a64b1ce1f97b722f7444d60d957f76d6f1a43ba27d3f302ceec9f98fa2bf47c9fd11d2397af17b018f7bd9670632eada6d3e1149349a834fb77c9cee8601809b925c15eb012026961424c62a5fb27be68a3e50ba8a4d552e2e928531f787774980af32e1698751ec6cda62a029372b654573238d5793ffd05ce04b9bbe4e1cc5f1a3479a1b8923c1e5f63928493733229e0bb1a48840c5f33d3bdea0f543153f03f8948ee5f0862aa0b9f25811000c05aba4e869de65e50776b72eccb40db5929321166b2764a2f8ba8ca1f3c67ddade1b4df68645f7255b42e3582394c4e74e9f6a7228633f67a373da0fa9c416202cf80c1d366b97b081f7005981e29bceb0e028d11f7cbcb2e42d337f646f6515d3f420dc5cb2ae2baef5b65923e347061f1e9d5e691dae53f309ba845d7a32e69780df976d036650bc5913cf7ddf3d18ce46c935a8653c552f7584696d32d117dd13a58faa6d547288ea38c1ad5dc26cbccb6822b71e65cf437aa38ba79d5ee331ca07285a8b60d4e2c471182c33c220f225d5fad16c6877199598c8b1fe9083377a43c98a300dbc9d637870dcb854181a4375e65bafd5d0fc", "1948e52b2223ac66b6881c9820d551ff7285401f3c76c7740d98fd5d50ca9692168170072a478693bc6334f30379e8f8592fd5851641f06f98974804d251171695d88f15dd5dde22d72367c50a53cda6f1797fd5de8f8b9eba9bf79dc8a4614d61b97a2f8b78ac0db9e90818eca696bf6868436ee4e1ae6f21f4daa805ba2237a9487ed889a9ff0bf5763987dbc458371e97276942e2da427ff321289a44dc77a6be988b7fba628994f5123d384e0b315275d1345719c1a36014868920a74cd7813aac2e24b5f826d94571047ca6240f58d7395233125a42ace2418500063078b42c485b502351e332c296bb8c3576bd548f8589e0ffc7f41ff11406de1a3f50bafcde7348d9280d41ea568f50e7147341920f76a9324c5df38b7ed0e4575c320f9b63b7c2595f512f7aa8ee44f3d8502a77200e166d87f25ba993571e5dd43df457d05fd2f3c5cc8990ee4f701fe98143462a6958a1e84f2a72692484629e029c8fdb797b3f7a97b0ff9506c7eca3e7eeb0210ad088da69efb40d14a5a0a826b17cfe536d40d6ead42d19c00a77b3b4647e3def1cc6420c7a595baca0ef141f657fe7d94dbafd04be4baea1dd112b7cb1286875ef08e588bcece905a97b316389e55105341afa16df9d0d80538e7187549e0d56926af8c20a753d3c16f4a0560c8cd06f9c210c40d04b482a48c7d211d8fd674f33f351bf2acde201415310b6fd14ed5b579dd09de55054ec111d52c8f2acbe2bdabb44055aaff5853110d1597e5c968e5ba30493db4e876c26b0f8276a8de44b823e6ce974969321e3a6c6897133708b7d595fde149bfec3f5b727d37e53341fe15e8909f13a5212c04b5e7f52221b41e5eae8fc7fda524e9dbb0e2bd96e415b4345548249042ce37a374fe600eb661baeecc9b77900c6df92797cd2b5c08e737b094d96ff971b4e584b952b4f51dc1ebdf973c78e0f9a40c41e5ee836e9db951754b4d5ca7fb68b36c144f550a90a98a8ccfb43bceb3736c829f747a64e1c1dc0d555d45d2e36752d659ca917a55d5e8874b6139ee0b47bb60c51d8f6491793a981e6c55cc3c2b0bd7d35fe93c9fb3a12423cd9a559f952bea47d881350df2ee14d209edb06895b1a015906a88fc3dd3dd2faabb8da87b06adf30030ca3c2cc153f039d64baf46478203e4719cebed9ebcaff7fb3c70fb94cab8b87e6146803d20a6e17975ba888fbfdf28767274262d03f947a4e1311748d2d90840d0ee143988e81dc03460f08c35b56850e4e23168060a94f7d95b0fffd358d3dd2f732b5f04e07f9d3115b93b962b1a6f9c1d95d253d07b41d3abfbfa4c8f81fb098bbff26e645dab5c48d0b6c4809820a6b1d0ee1e1baa29d7fb83c6fe61555c7e9d68cd5459462242a180dc5292f5913559b9f7c01153585713a752bcd34834aacf4d914c6143eed86b6153e6b2380", .None}, + {.Lcm, "10163d80374ca4b45e70a31c83eca4e9d350b3c27a52290bf9faea90ddea0dde741ed6dfbe3ab6ceabc74cf738a0a232b4e8b1cbe813d8d9c3099efeb9062f8bfa793c233d5bcf83b63baca88aa71f65d3fdb44ca3f7bf41b3c2c7f533efee1c18773b10aca5b3c142c5dd21a9b2f68508d7a868d1c27a9e5dfbee10e7f1ffee8fbe6d800932666098982901f51f45e460467876ccbef9c2e616b6a21f606f1529c7b7a774bfa8ea7f71e5fd5ddeaed8a5debc8d8a96ba49913b742bd656ba2c99ff06f7e81e5ee01aafcce289e8c1ad284aa51a0e383c4fc9f3b5c72d96f373edd69cf0849ea98fd1973e3ce2263abca373f3c72750b09a8c88adb0b1b05707e89333fe80bfc7159c7c30787adee3aa4c86368a3c2afba9e1a0a5cb3b4e1f213f03ba4625b580f3775608372274e81b5ca7e5fd564a36b7d123dacb0b99ff8de2862a51f8b3bcbfac7f1e2cb0fd6023501d45d8fc4954bbdb8e6cec35e81bd2518000c3428c3ca4fb3859a4a22f4ebf8eb9105bd75606abccc45962c7d68bf4ac90e5d5b5b4b0a57c12fbd3936df6eaecb035bcdd9cec7330d198acd1e530abf0b761c86b4b96f0d8596d9b2eb191ef4329350fa41804e6b317557cb5cf1553550ae64b29b7943c5f338edf976bf4557c4a6ac98aa638711e34e8d8b73994bda298bc8e0db89668953ea4f64830e40ab0e7b5618216d2ab26728c3f2eb487f6", "-8c96c280ea13089197fcae09f064eb3a59ac7c7723f1af555e23f8dfbbd0dea12fdada519d4e2b8653f8abf72bf70a42c5ff08c0717a801b9c4824b1a852b65e2bfa9a7ff992c572e16ffa2dbd34fcc42b229b7bd44289b8c0185df85a9a952794d6603c3ff71b278be572ab1472b7727699b8d0a8b1c91e905ab56695588626b6c922e9c205e6bec8d14c445203de9b1231692cfe75a7382bdff4f15ab46d4cb7784d51eb6c7895e1d80249ee70762c3d4406aaff990f299af599cf9a441052d94ad7154bd7adbea19ee067f62111db30757582e6540c079b42284c43120f955ed894474a0ef37f2c6c69d5a38bb1b88384c3f238a6b2fd38a9fca35584357a3f72e2a50982e82afc1217e66c498098aaaa366e15326781e7c95817f8206c03bf3c65cbabfc6e01dac7ab8589b4762d4c5aba88eaf07b87febe3a9a3b49ea047c20000e345e1b261a6778e2e390ed82f87b1564488588f69a83a95988a34d0f337013cca1c7c7838e77d93b2ccc2411644ee06fa6bdf907ff0d2070f892c1253a8589fdd20110ad852877986c9a7cf0ecdcf3bc16015cd92d1a433849b08138b5a636b560ed8a43da9e6217d5b97d7e4ea2c51e5504ecee977e139f71e6533ba50a8781ebeb2d41d9f950eb8e43d1b4b788682750baf80b5919e2b525071c46d79d592c809a197e0c1b350b944c42265f2d61051c6262e8a28e7ebdf6dbbb7e", "178f07b2f4cf5911499a970e91851be4ebc9230e305f29f6b4cf74124e850ea6c328788eea5c62c8e2a52dc7f2b75dbd3a5f8be917b22198a67daabde19291181c17a447ef38f96812cc0741772c16ad4020e16ee1c9f6e426f4a4d8ba22c5ce7312691f8fba2041756719c9f3692d1b0431bb8c452704c2579a4ce772b90d8fbea3d1004d5c43ad897a8b56946e6ea69de43d817b7d81680a3b69c0a03fcf1f6d431ed298a7488d181924648fda64528846460c55299faffe1a5cbe302ec09bcdf1514af86fa981bba0dc9b745c8d9e6a6fddfe7c9f6a818b081d79caec000d6c75ab1abc3911e984efff2d5017fd47c694a78e929ff5943be25c77255b89795b89775e11ffb17f8431e6326b683caf772c52bc10c88cd192c85751c2d7121ebb897ee5cca6aeb236105ebeeec4dc85fd3f1317a07bd97a41d53c6455af5c3c5802a89e12172018c7f1fc6bf5d11977b4bfc59015924f12a21c73cab3948401dde92b10f6e381614bf1d47d708c1272aed0ddae9859559fed164053fd3e5bf2d356a7287eca0199dcc7f47b9247831e9f03017b382565ea09205bd2c01185ff1b5717829873ccf28b6cded03085eb7b2d628a21c0b9df3035b8fc6ccca159da7e509e0f2d32b6ed56eca3490df0113dad525f92e2c4c7df5fde816bacfab3c298af366f6f6bda911c52851c4c0bd6d9902fae730bb750c9155d26d38868952b0f4f434aa3e700c056dcacb89e5bc59e2bff53acaa508f26d4c352530ddc98db249e6f5e5c840f9f2be513b5083abb41464a2fa0f318ba02d9a2e2261579cfc012e9c5aa9acf7f2f385391f534fd46423021f369800de57132527759b566f01b2b0e5efd2df39e397bbf25ff8948bafca6b0b2584950e46ed709c725493fef7b75bd2c4ee1aee8f3e45480290c748a0c943d44efe3b9e293ed6bc121e662c12a20032e1e4eac721fcd34a98c3b7e52e6bb13cd5ec47eb65e8011d1039c91ca19efee65285e914aa40e54bb22be083140f1100a48660d9bb121969ff0a68bf0e2a534fe80cfc890686d13d3c38581997709994080980a78d9dc32175c03193ca8faede2fe98124db4cf82ca2a183d350627109389dd6716425a5abded5e30959defe4123b226f2d884b8313b9c9cd74a841719f8fd2339c56fe3c19d49aa51954c85b6cd36b98fe87045a1792dca45ee2c534a825e640824052adbb13d3617de9d1ad32e1a7cf9389e0435425f6c14cfd7908c99e10289a0b487b5d3e39a496b21621797a9e957598b502d8ac4c94358ffe2da4ecc96af2774193562bf45588dbfad9a75919531efe1169cc1f56909539e397bec0bd7d36c4c6709d4d4af1a3f0c24b703d28fdaa91dc9cdf8c5480a6206283c955713092dc0b9a2c92661d1ab2749892bb5c93baaaffec23bcfe14945e7792e1438157978c91182fc97ef9a2e", .None}, + {.Lcm, "823883858b439d997e4d4ac803e507757d142ce5ba225a756d07006df9cbe1650d838cefa4ddfa5e593b1ed911ac3418ced76e038f3c7b493354903570bcf9588c62fe3d777c56a6d93bc4a1a1433f9073b294bb698b2e6d15186a4c49928a97886beb56ccd86af413b2c4f23961470e84a1a892bc5c1d96f1a9c81267ce96a194267a30e6c53f141a5e66ffdc4d9d417d6124f09bde4e51b4bb5577d8c163f5f8d6a735bef03e2d1e3117e8ed37a7564cd02aa7dd2c516a6fa0ee01d311578c4ca179c3b1ae07ae9c7d1906e1a49c797f423cd0e497c6f82df386ad0ea35bdf2f92297ccd580fe604f82ddcc192e897417c1ffeac8905e0f8ec091fd56a77202031c3b9abfbe2e94f4e2e8579a4db724432bd456967b868b13f8bc076fe369325a56af40cccc6fe43b3f6df6fa981b3f5fc03d0efd132047c1a282ef03c246841a27aaf9ce6360aa3d176e0294055ba65a0bfd91f41e628183788e41f4b6c66248417f78ea902968ea91fd90be09d0802943726cf0a70b413d4afa62ef69f9a292b9aa2b813a96f1e0faf063c24c61ca8f92f5dce88e2fcca11b2643f70a427ace30d4c32c6834aaa2a4f0d9e95f3e144276072509d7a2cd346ef929a71e04b1b247ab7832c7a1df5c2e1ba765624ba93e534d19b58954f6f342c0f009d66d007d0e32ee74570dfda9a92a015af907ac82526380571ea34113c71376e268660", "-183fdad4b3ae7beeb29c8daf6508ac601aa6610f118affb90cd8d887f09d70ba6f25465fecf91342e6c4e73ff1d842804ed6016f24e216448999dde0253ff916c2ac1bfc1ca5e0e99f21fc05a4633afb0fe61f795b21ff77002deed1aa60677bd805d16369c2d5ea64714641c30674b432d7d6cdf9e2d2e251df5fe58060ce3ecdc14079102bd27c2d27940cf011af6dfad75ec6f167c75815dd76dc5a218ad964c618adfde305436cfdd9462dd2df3d0cbcf868f842f3023c3ddc6a46f43e430ee3f7ae03205710418df3342a4f21a7415c8a13f6fbf63e74ab23250717b9160f3089317dfe1cb5a286da666ff4f5bb14e4d77bbdcb0111a7e0e8b268639bb837480034e5719c792feb84063954d809b889f57073638cea8135eba3e9c460ab5f9e23230d628cfee5c654487549ff6a12885b0b933b1dba38ce7001bb76699e4933181ef02fc827a33a4b25dc419e753d3aac65e0978345f580acaeadfcfeca21a79ab6e6652f730501a74b532cf6d09a4d9c528cfddc61dde87d35e28f1f0c3c3a1e758fda60898391d2bc4e90298fb3e610f1bb2112ce7335da4e621f9228941b6549a09ca2645df5dc2fec827f104c391ca90b17838471229c3755533c7dcafcf3051f77d3e830dbb1cd2c518b115d6f9f4773f280eac92e0e9882f4526c6cdd8c1ddbbe9379b6fcc8beb7bba1434735cd15881218b38836b8b1df2309fb", "c55c78d351e85036c8bd9e0512ce35734b9bd96d80ad9cc211fbc98233ffb087a4611c486a7adf31192b459a36f4f68258ed50f9d1024d3946464531381a000e9b872a18f37b62863ba64cff176da38ce13292d92a0197c98af2dd7591e6e9aa2074020479d0b9a9b57d9fbad4d995cf6d7106db12ff9e289c07aa17dcf700e2a1e67b27f9f4377c6a4ebd999ce9633064f327a5017932b604461a1157f0e2e817bce4d8de15ef7be8adba1cad5d5872ea2f6c017df1d839c6e7e739864dad2fe53c2978bdaacc596a094c4485890e48827c06eb5fb3c521a3c4aeadd00a61cf0580af93f69eed7a5faa5b40bbb0a901c201cdde76c7fe5667af15418e76452d6f185b0aeeeabff8d56494d276c38f5678c366c20a30ed9dd1905e0c5e8046754e90969431b8736d0fbbe0f22467f320b2b6d8e7e450eafbe9b03c390657e4d55a650dbde012df1fcff945fbc14770112959b90842b16662a6f40dbb5ecd0c744e8c15ca43a45a4d711de07b7327c87396b091033873ad5b30664cf1418ad26b4e0e5691dea71229107d7f5aa789c93939b1d1160a7dcbbf329bf3420c209124460bf637d821da4a6bc500661c7e0b90de7825bfb3b66cab5563ffa976dc2e18f822c515ffbf93d8b37cebe95bcfaf73ed4cc05c4b9f63a7974e9229e9f2a827077e5b7b71a1cbcc835981b729d593ba0da41035d74772131599f76cd509aaba9b1b056d883342af3cd5a14b19db05416a477e17f8ed0cefd56d31ed2f4220fcc3807c8f8721b0da32ea53405b6d19e1b4c9b04db4d23f57378df3d094643e4e24018f664fa9f1549ad01c658bff4e4fdc759d8c0bcadbed733386cd942fa64e52b52689647f30c790b9ebe3f9a7a9f27810333d6464b1ea52106a0a1ba8d5a9256442933e1e879eb45e6222d51a7b5160b5cc0bd07009b7b6418dd363248ca985d4b181f3009df839dc2f0deb1ad0feefbeee8c26ba64716e1b424e2bc00175ea713bfc4aa11f7c68e02bf30761f2df5883ebe98702b751e8611e20a12c86359f6b79bf56ea2714f9a7940b3c938381c5024f4872681fdbb1a4ad2aa716b068d5529bee2f73bc5f8ac911e9f5d2f620c2a5bafc71b79bb638dec6483b60b790dcba23cb538d431f56f283ab03aaeda2a6c48ea4518d2d6295853290b453a5b78a2feb07c1e91a1eb320bb0cad67eff695106fe345f9d2bfe4fcc19e218b8db903303c8e44232471a76379de24b052aa38abad28c6d02c8b61db86ff261ce5c4b5e9f8cc284262d0d4aaaf9be23499db9b8ea09c574ca43a0484b9f28f0888a6ab5988e6511541514c7ded5ccbd26a2ff432a497266ce5812a85f8157f599837c18cc1f6441cbdf588b931762c2e1e57ceb59e64adc33b86d02621bdc89b0c8280fc2b7bdeb0aaed81bb8cb20ffb96dba55fc0b7cb73eacfb3d7aea599f2020", .None}, + {.Lcm, "-dc6d94f913c96274c10eca42f43d611fcd50d47bd57b2059c9d6eabdff9554a16e936e97c415d2f1eacd83c76679ad22c7b6c0b6d00ea5d19358cece428f17f972d4b3d1fccec59faf3b7f4eddd3b280ac28aac15b32e267934b6ad29db3fbdd3a30babb1ad7a6f45ae522ebd81a1011db991efc88000f28896570733bae689250b3ddfb38169715a40b061e65a78a2e5f68a3167d964d7586ba528fb7a97a552377542c96543a16637575cd94b8cc695e3cd1b4534a221535982fddcc02a254c4b3fcd1ea549875c9391c301b08815dd2eeab469024aa7b6a590806ab0ea6d7b418d6246ff7680356b035ff6325314bfb8ab04043bc935c9a0697cd8c968300961929ba2d7679c45cc1747c7cd557daef00fded3964fd07f381b3cfbd751423cb499c92856959266a24b2e57fd3c365f1289fc4d00322885ad9e1c1a751968ee97e2a790a5a680c8994b429f8ffde6f04dbb304439ccf05042bbbcee31f540fc967f00b4b5a3089ed8eb61b1c6da4b9f9ad6fd20ce6a318b324c4226961e504fd02c49dcf30e16ab4609b13c2162b881c0ad9f14e804489aab8186563bb4ef64dec4dfce6a0204c681addbfb77cad0ba768a60426d4d881c013b0539353451f5c6b208e65847ab74119cbdb066e8a99c4dfde9f83d7427766edf7b157ccb9e1d03ae0aed593326d3ae4807d13d40c304dd409f698f27732c24dc5e3ac589c70", "-946dc94ff9a6f5878ad03afe7209e9e23ed5b1ed5d7360cfc3253fcb6242c44cba9b671354c03e676569398290cc14974158deef438f8851f41c4ee22f6f35e35d9c6833fabb228d03bc3c988895ae9a88856e4e670039f704da4831f91ba9d8a04920b8603f960a4ee3a9eea85e559600cb3f7e34c3b94f7aab943fdea10ca230ce506bee245a89ec481905be21ddcf246f1b1686e922c15525382a357f14685c0e5429d9c9b057f87516ddc368c0e5e9e0ac17cb47b60c9be7eb503f1f19a1affa3830bf3e8998a31418890e6a4f593db2d24ea5ea4d72f79407f939e3e4fad0ae0726560cfeeb1f8094da596089daac556aeafa51483459bbb1b58527da56c31ae0850b3dc73f472f82510b0008089b47c4653f3e4224aaec96240635245d2c410936c3c5aaa5f5a6f8d19b304a0300d795badef352deef49df7d89d2565a2fa5e06f26ad19806c927ec78f125f8eded7d11fa7abe7148cc28376c999a26fe5b5086703735ad968db7044d77fdb5abc3d371b05f5273e27bf09da8e58b32b4838119e8c15f78f24589487fc45f8c84256616f3efb46bdea36f03b9977756881e04ad3be54058eca7fe981d575e7989e95c69bde5a10e95c08b72ce15458cfe39ad462e2770f69811740a6c20201904329f031b129ad213103471d2f8efcb1f9d346e8fb829a8f4007466b4d06c9e27d46ab2de0e04ac2f93a3583ea91d7ad", "7fcde21f543cbb6f1769d09ccfb3e7416ed601824d8abf0e5ae95793fedc874a7d1532a97e10adce87dcf83c6c633e746587c59e8a9a4f6895395cd8f106e4a2f42510b5d09e8d3e73f81678d252032aa55150c9066fe3b65d88af269676f95678c6dba2a4e0de3e53047b06ddf33bb8439db21771e4d63a75d2de9f5668a1fc98d89c72bd8ca2087f23f351f8baf766a01ab906d10a9833ecb6d22ca0eaef95d0504bdeaa3d9fed9ed2749e51b26a4be756f0512e54f4b975d15375244c10016053f69e5a0c63c37895637ac1b94ffc03b166ddc194faddedf3f9eb959ba4f64e5cb8753d3de2577251a2733fd6878bbd5ee4f5783aec312bdd4ba4f434d586351dbecab8bd471923cd77eae02f18b10c0a2d8bfe3a4cfc4509df80476bd0f7d3dc16052be0e84e9620922ee0c2e23c6b9d6711ac36f4da5c223f17f9249f8539ae17a7b7a96dfb894e46bebda2dbd310cb423de08ac44d611cf818c7fb25cdbe70af1551845c43c0a6e5526fab688c689817fd407d609265689eafb178530407a0e0914f68d19c6d724a4094f0a1e8a7baa19aac5c39bebde9390e2a70f77417495f72b7442191b7d7ea529f7f0e6e072194f6b69724b61fb27c3c504d67c831de45cc41479d93838708f55c65b20c7aeec4fa170dc95ae6a5eea190c0f1ec8ea7102d33cfdd5e4fe9e2268974d1b31ac146f3402019d5464973089ba4c0c2b2fc6964b75a2ff95f1372c0d8eed142316d2a82ef2bec55dd739faa6d2931804906926df3be8587efc84899b7ac77ac00ff5ad85d9631d0b1494ac9bf33793ece4d45b64c10fdfff6e03a1d4769810f6214315f0b7186b6650cbdb6e19fa1cf0fef2d4503a67b8178543201ae3c98f22e29841633a683cbdedf8992d8f20af3ad629b6790d6453226d3b6248e02b745a8a3059fefdbb058b5cce37721c4ea475ea61c3bf195ba0f1ddb3b6617c13e8ce27b2e71bd44681c4c3a4d8a7337eb4756be92488302036569375e0badce9cc77d9610daf2da028e20d7c70bc2d6f12dfceb1375af5746671f857ede31c2e1324daadf412160f0df29b8208ef6563b29993898ef9675153a9b0aa86c2dd01f9cc155a39df3a2552c39f00edadffd36795d0d87ee3889f3190308779b41a8d84c19e284d6583031e95da904196df9dfd21d20b46ca1a45af276b439eedcdc099394a4e7a11c63080c7427b5126c3508cc2ba2eca808f633077a9950021c56de0ebc4c7b09e5ecf04d17c0b4fa3517e687d6bc9bb5c043e6495c0af24dcef49d4d2374702a1cd4866521369498967bd8285fa907e3e3deb33ddecd203bf25cba2dc34d3d601946b3f019d534c55c6f91ca639a610853eb6482e7124725161d954ba5e19cc8a1673a863458675f6b21127f5f6b85dd5dfa8f9dd837fc628bceb6689b3bb124d1abe2b7bc59cb18deb3c7b0", .None}, + {.Lcm, "-595cd808b023f1ba7fe10a4e0e4eb7f3284856faee28f1199b2fbe7d6808d4c2008062b57972f50ab2d781a4404655a76086fd92e950fdbaf78eff29d084db610b59a34002064009205a01ce14c66ccd897ce58c54c34cd802c8c808cdd8b75a26be0dfaba2281197694f68875575d19080c5494297c48b67caa1a856ad6ddeb6b1c4165707810c949591d8d45710806c110f28d1ec1b127515eeea0b774f87e09b43d6d768f4c8fca694936b76255bfb5db865880d82e7bf9e030920fbc0482ba054d29b4320eaa8fb157d19fe830f2097bbb2e573dea70132b0b7af254f178101126b20a8982be323a40e6ef7757e085aa2bb8c306b9e9188936641158d2b208c0682ef27a9577df194b2744e7d2433f39294994b35d67445fd60e8ca1dcbb3b2efe58a1250bbc915c34e5b8862086c66819382c233681e437348cac937cdd8738fe2266df9223e2051722d18158c7f320ed17a280e5ab3ad2c2194f409023b137d365fa3d12e2f874ca79754b71fdd598cde37be3be2d465ed583ed682dbf44ff3a37d71ba32ffcdc20882af91775ac523ca6d3f7d9091f8a7723cc9e8c464b504d704d0de5ae69d2ad5fe22cafe4190ed7d1cfd18e500957b3ee76f0f3428d3fbf2882973b9e58c99ddacb175c20c6fd3708ad4efe44c3aed2578d39f9342106d875acd73f7de695b36a30c87f042cfd63c420700f31a42a4c19c2516f04", "396878bcc2d7593e1e25199e44059b5e6834aefc65416cbed1347f2df7d335c0e24bca4e4b451ee7c90675bc061631e4fe21e83e49685eaf5febac3ae217de78eff277cff0781adff045416fc9a74903448ad3e4e1383d8b73cde37b9e966fd5483fff4af5c2e64f4745f322109eec1443616bc1be880c515ab4f0948d9c2f0f94d2659ac1c08f6d4dde092ae686e0ac6abeb89ee1c6cba7738931849024032e18c73bd2444590069a324ce7c4b7e4e5d8367f68f097f6de7aebaf473bb2670f38606465013db2c560d43289aea7179ba5371bb6e05a99b44c317577792518fcdf5417f759056aca9079062b3fdcee5992b3c3a1caa6f706b92db7886883665b64a1ff38c8a754e86c50c92900e39da28e931b0aba66c53622aecd2b78019c89d713ead778aa32b03d9bd4e0babf3967ee24d65f4178cc820d77adfeddd1340317c32708958a87dc17db34b2db5ae08d920701f33767953e3dd66c3b37584c4a9d1909471ecd2c7d83befb2b3e79fa4ad32a791a18c52b8fc961a0f58e8eead53c9e8b13fab4966bd07fb8c40b7d1850274e60238f101d1db40deff8a6fb2dfdb2321f67f401083bcbd53365c209a9d4727c6b28f05a405f24439e92e12d99cca2fa129eb874048a36d3244fead7572a3e33643fbad3acffe162c7f9503f8ca845dc40aeff1ceb4e9764d6241314b9f929c571b1fce6e596fcd96546c1f27b0b", "140a23f71c35d035e8d65703055048eb0039c860258abee156eb08ae0795080e4a447e688df25aa19cebef15cce1ee1c282e85205d1295a4488c6db60e0fcf743b6e1a9802890b9992c98f40b3a3e6cac7307f81c90a7f7685cc00e5580241d8fdf4189e45d9a1821cb9f76a075a8f8b397bb23853fd07110fa3d3a8899ceebe5e46058c475dee835283b0abc9c89fbc30451c2197826190442b22cd4bf33444a76a4c0d4ceb6ab3c254387fe4524f7bd447f0f653ec1a08ac8aa6cdaa18ff4bde06a75d684e9ce1e5d2cdfb0ee33fd47fee50cbb26f928f883ef2e57b36d2a5a1539b49801cbc971cea632d5f29153f96b959c9e5e7acca6b77597ac8bd6d8397cbff5401dc4e7267c3300d852c35731d0344c03060d6411c5f8fb4cd1c1ddd65f5e6a48faa4c76328d1c37837cc144c0d568ca5004fbe6c856d74a3819e393e5efdd4cdfd5b04f69151053cedf2389dda2b8965790d395823efe47006b10b21d4873001d82510ec698cc9ee607e64ad501207145218c2aff254f997bb41b1701102e05957a2c142e6cb9828af5877b2f2575912de482bd52425ee7322292112171e0c06f25a30f467bcb8750e77e277fea3e9a4815b97e28dd72baea41309eb64393871d98c216a6a46b31dc5f761267c2702ba679f09b3f50a7fa1b2debd3b889d5cb2c8619672faf721b27ac2333c9d6942f2bc869f0b3384cb887376401b8f08b942dd01c31001d00e46d39a8ff3add8362b5140f9af00e3b44ad6274a4c77fd9f95553a52336244d519cbd88c154c41d91f9c8cc70b5fb0fddb4991f1a3574aa0a9256e8ceff3d38639a3141f5bf3d286677deabf289b2e80f0cf30669bc8d751826bd775fb913dabc3f19a458ff2772b3e366df14c9dffda389097968d5dd010459b3fa038b3d4ef995924c4f7c67edb02a8580bb915a75297eac7d911a59c9f07e2d1a9c3ba756d804a88ceb22d6eaa35b2e53a2f0078b297fa5acd0c08b543390998838021b3694a8b5b6f17e53433b2cbb4d1c9f2cabff06894a879e1b0fd1fcee4af5bd59c7e6756fbc41dcf30fc431476b95e24c7b3b85edc686b3155e078739113136abe161e23ca870752750d6874490a97c2812b54439654b2b0a8af95acf7f6295c64911faef3bfb9d0e01e7a96ae5b6365ac90f81fc912fb6747ab99b19635b8d7ec595ad23bbda7b9e247c345a23ab6a2114cd5518299548cacb4a18a6d523ebc20d7e29b1bce28eef6e055bb8d8ce1757c689eb4b5873b96b87412d595b0b5e48323301adfa7a5be287fcb56521ff1c51715534453f88bacdc073db329113f8155816c012dc6d3295b5b071d30d42567fbc68dd1f9e65d142af0e2e75abafb681379eecb70e82e8e5718a3c12b09c907672b0948421e5c9d3853ba94a7ad33179a1e9ff4f5baecca918a1d8210dba09afaa3d6f9eb12c", .None}, + {.Lcm, "-244dd6a871178bd264fa9b521005d4d51635b232cfeccc67cb1108a7f264d48289214367c7e3ed492e2a522f1db7393088ad985a367c4d9415114c8a5fde99315cdbb75e216a66603f43feca7cf3384dbf50f6b7c54df6af31bb76ceaab2bc458714316699e98d390990d521edc44a2b5f9cfb9ef3e0f2e0337291f3cb6e290eed2a6262389d638222cd817b118b08119299260f795d871b72dd43f5de0b7f90b5b548281af72fcee32f3a8f81244c1b265348b69bb4f3eb55764cc497b988557a09a4e391de38d1095e3432f36b659812b818abca6352dde7b2cbfa2fd100f1d8d48590a34405f9d2d76974abdbecf9d694f3e88b2d05bbe931337d9f4cd41fc0ff33eed58b5de56cd4c99a6b4e6b11d60f275931b058f762c7efcf6558c42df2df34c9190a6b1571eaf6d7737757dccb4af3bf815f0d71bf2d1840a5991f0a112719d45b1d0ea76faf63ae594eae50dd75dc9c57d04362e6b9b2fabdcc9580d33de4e512156bdf67f5cc64aa9b3e5e1da689c7a2bd0c617e325339ddf98cb96ca581e6fdd0b35ebb0d5505e3f2ccb2c1116c3c9f9ce5d40966fa6a1bad353c3810169e05598eca338402b85ba306530323002143390de9d2b8f608b64d8b772dd98e94565b570e263c9ae002161125faf1e6974d8ad2da27041f64760f69449302c8a1ff9f16c16795814c2064a60916ade6748bd8799136f9a57383209f3f", "-9a7fc61de6fa3839b5676c9a9e667d00003df6b1d9279dc4d36c4535a312a316476f6416b123cd6e373675ee4cc506339588058659765dd6ecd15013fb4875d8aa7227257a40ba75f9ee7039ff2d066b216748be1a3a084eed6c2f7680c8bc30b2d22b4c5e09bfc78d7c72cca488599e05f0d3aa76d4d217d4377f4502ff7b0a42a2a392a4c57073464bb2d02fa6d6ece0016225ce5a27f41dbe3bd57fbcc14fe35d4adc80cebda1af661eb739ee220444570022f7c88b103e8c7cb67dd06bc31d3b2f587d5ed6c48fdd2e6f7cfcb15fa596478023ec5b585149b828002d76fb39782b7433cba0450ee05bce3056a49b276014f1a069e84ae5d88b18edac0130072e247e484392cb0e1d99aeb8643ee115999d64b22c52776e851ced9db9f29abe50a50991a7af108afe69b0029704757713c48fa3f08cb1595c48cd8024e9dea3f8ecec481dec8eb00f0f6ebd0281a65a1a98f373eaab37ce174d41d38514efdebc8f930e3a325699590470bf86e6a76bbaca26c86ed3faf01b0a3931c3ba60622ce3fd98af06e59a0b63635979e71033f4fb719f0ef03870a2848ee4d24ed41f83ddc7e2d4c307ef0419bcf3609e92922c6869599b7997338127f8330d465060d379b7294f7a47ebb2e3e9aecd29ac6232b930c4d58144d4a2634dcea890f343d40f5a965cc98b6f3adc89f9dfe516ad18bf356cb991a05dac51f683852806", "15e8f1d743314830200b5b0ad0765c6c479cf9155c2c1ac1779d270b8e567bc9b58b0467811e21f0abbec2062f0b7170e66f0f31aabca6d1888aced304fba7cd02b4ca1b2077602a8540602e89588673c09e8704ebce658ba2da0ea78d8c0f59124ab75f3559baba41e8a2175e81487775b66256a5c25ee715655c7a41c05f28af89315844b02c8505fa8cc5709fa371a7a0e0f15ea0f5b58aedf4626e8702dc50893edce4d02dd81d023bfc8e041c82f03057f4912a5d82901682f1a2111aae568492f389592adf1b2a2c8fba863f34ccb075120f165dcf1812ac5790a3f4da6e16992977b0bb82a96a17ec77f4c7f7b3876a123bfc66a182c5455d34ca8344541aaeb0de47472efb38be78f07531e845b0b9d3bb85b44ae1ce8377f75edde46978b30c432f2a9ff0f5535b232f9c285b09ad1a65572f0ae86a68e6a424f3219d3d43248e731a8868b55811a0332832c12bb0686d04277825217558a03a985aefd3203a3d1f513b6e78302c3f4b4ac778e85a80fd7a83e489b457265bc7075b2c21016c0b467fde4c7f0ccda8d80a8f72c4aa8bc83a0e2bd4f3885049c382e5bb0fcc0f2e292a84a14b1362550ffeb48d552275416a955edc87b5112523ae47f6241d5e2ebd4795807760f71ee0776abf1ca51ec67e5f28f5236106bb0236632fbffbe7491625d84a2c8310ebcf1c367bdb7e78aff718a58a183b4d20d2721e29f759c21957ed22957e291d49a722734a96131de35ecb718a524742474262433428f4d4d5b18d0e7710b72fc1c51e8b58206417f47c7d584e1c6d07dd3c1cba1b7c12d666f9d78d395ffc4ce9b2ff2a82feac1e2a05fae9fff97cd95ab82b03dd259f5a1bcf3a3ac4b9a8b2f7f1e3913626eb1c4d20d0aab70d53f7901a0a1ffc6c5c1577a7279f8c7757c564d9d92d759ce56851049de58086f49433d49b021d4149a15c756336a526785866991901d2233190c6f4ab0d84bb6489fe00fa1d15d3d25fc23e8d5f4ff106d505977e13147be0be0d25acb90172a0ee48003e57edb3074baf2dadd1794fce02c43d04e34ee6fd33ed9db68a5464ece38aa56dd6e5307aeb0252d4649264124a42bd542793fa324591426cb192b2ae5d15309aee693e73ba1c62f85551939ad19bc2ad987907bcb308fa343dc809bddea3abe9b1340835ec209f0de0de069ebd0383f58ed2cebffb4b643ef6b7845afa4c1dea222d92acc962a80c597b669228a8d1d97c714742f9e985edecb8cb17a58c62cbcfd3a67788cc992e3dc08e7a018fa0964dd015cf25c90a4a69c191083b21e9ca5aa1f41e8a3180b1bf8a8881463defac302da4733d7de29c21f55cfca177eaff76e2a04fe0d9545974dce43ac0e8ef29bd428edc55844a92d6cefe00dabbc4f09263bf39aa2d3c1f6e3e5ac3e22dc01ad26d39c34b9a3f8cfd91e0b42c2460937a", .None}, + {.Lcm, "ec48d01d60862cd0e33dbb7256d83a76ff2c086ff90e1a3a99857d3b64790ccf9068b74fdc6b127c3fc34d99f88e605a1cb1e3f270800f4ad61ed6e001163155b796e7bd8812d45221519a646a36bbcbe7c2d3ef34e04aa3f275609685d768f89d8b6e9962358fd3c75e8ea6ff6019d32160ff7d73f0acbc84513731b66155b15597cd216808c7ca7eb44fe20962c6f6dfbc99f81acc6e2f428d1f5584eebc2e86270421e7a9ad5aa35e01b299b472aedb9c12795b58894ba3d8e796dc5dd8611a3dc4b2ee6dc42f173a217752be2c7492924a8ca891efd2c3c203aa91a25f77b3be77886beed5000476cafc7e59c1ba8cc89035f07a4bbd1ca2530325d3f5874d2d3993ac77f38aff231721b3ba7d0ea806f479b6d2551998fe9b0e5c83ba9a0e9236f3e8842bc100e49cbd93a205fdd2bddfd1cdf2beb8c32ae93f4ae419878b24a4299d36eb43b33b9bc026b66f51b93fa95d7b5fb26d5b05ec74ff646bcca9a5f96ac30bdbf214617811b4b5f15d41a6c9602fb16e59443108d0e43cd384b7e5ec9f866ce97d114f3055ce4dbe33a2b2e89a5b6f866b2f3c7ea3b320523908a1f52ef9fe8c1ea4794df66eb01992cff69ee74d929640cf34858e9db23f8456a2b3eae6a5843bac637602cf0fdbbde0283babe578877ec7d80c37e88f47fbbbd5997cbd1309699c77e188b0f42183fe27a9c321614505fbe106c3d2adb89b", "6bb33f70c2158c78e8aea2036b307a3d53880e6cfeaf701bfecb564e890f8858cd9cab9ec4d4bc53fcade213e9d3fb74b9b001d0d0922591d79ee680102de60379000e2dd60e311de9490c55568d886c5b3d10fe9e47a59149c414f8e557fd2857c7085186160198d6a0009a958a85b03a560bd51937290e5a538675bae0cb460e724e96d4a326eaf83cbeddc559fbe78837e2d545ebaae85467dcaf987844b304163572849a460993f21fdcc7e2871cf34857567dc7995f1680d3bb541592981c36af777dc727ba8e2c89e97b46e69b3174a5dcf0eb0a165b793d3a239ef8d5cb90be25920e46239aedb034fcda6b54a0a5cbb1a8a9057095e3d44df3193f692b72348daeba22bb5fb4097113fc3e6e7a6b927b6ed8f7cb4de8f3d05e6d817ddbb3e6aaa192fb2bf559ef7283587412259229debdcf12ccacbae6caebe0c5c51cadbce4bd07362d0903643d350191f496289233c477c2b6923144076a85d37a005f4a25d44f0d03c62bea28172f5fb70c162e7f4b890070c1a2d7875584c007e80e372221bd7712d6dc5ec2b2a6fe5232a3038459bfae2eee37c0c079ae371c10a505657ac275976d0bbc4369287fe6d05e14fd365a2c81d3d062e2e380479ff7a921a296aa8815e52911dc5ebbab3eb7743b875145e9dbec3cfdcdc40c18f32c0407cf2d84910000970f467aa3ea64fdc29a5d474c1ef641e67ec684791cd3", "6367e073ca17eb7ea50817fa5f0e520688d021bf2e8098e522d66366b7bec82b2700c25feebf3f624926d7c1b8d27a4b1b07da10a98e755634ae04ddefcc3fdcd67e58c04506477516aab41638e8d2ece9e2cbfe38e48b39f915bc140e11fc807d5fce892724369a48b10fbec963c59ee3cf77aaef5380a22f91738d4fd115f0908b76e86a4f9e8cd6f1d984cb798c9eda0ed666b75e21756dd148261f7d7780ca746c4d7c16ddfa90b3663e0174a8a3c990ef750069628e70f10041279671a7a403bcd4fa7a9206e4e82fe240a07c108a726cac63a79a24f1156df03bbf334ac4a77f8bda8b8afa77fa4d44b8e4059ce7e5bf8fb1664e5985c5b3a9bbaeea166aa0552c2294bb34058d6551f8ff73043594dbb1c09606f702aa9d814c72eabc70fbcefcd16a65b790ba530df35d659b62cb92fec0181e8921e03f902cde4382350b89b5f039ee8f762d92bc580cc264e39a27b7b8d88ef000027d73dda62f65188edb1a682c2dadd476cdd88bd5f9d7e2098bfe6502b703828a76df2dfdb28b4b6e1a0d033bee8be5ff7cbdbb61d9f8009f2f340b8d2e2502da28ee7adfbe1d28b190719d1c1f95ae6d65af9c91473e62612d4bec9dea2b1520597a7052bc6944d88320880883db6f724fa8b717a6c96422f4601bccac2639ab2b923bb86422c4d31354e7e2f8003ad93b6865cd3806c7e15fd14b23b1890946d6ff37030a9c87357c08444f2c254aca506d76e4abba6a56900d2c02f27d492facfe3c7e1eed9bba1ed908444f1b088e6fc6d291e01592bcbc48192406bd51d0abb993157fe05a3106219b1ac18f4f744cea711e9208cac4ca1e8108ea9eee6533920c23c4b730f23f5cbbcdbb0e70f56031e903e2d194ff20a27bb6f80de5a2e1f7724a6658f5f45fc5b8965a3c8d68ef010b71c6700b4fc91e9f86d4b3ac8c1b2925a00f0b861e57b75c358353f9fc06c3f8485ef8cce7e8a9fe1dfa5edcb2ee51feedc00fe268500bcf0d0fdbf91033e1e2a8c88a87ca5ddfce8552da71d8a60caa2a23c2898b0aa89b35ec9abbbc204abf845ff79d8e433953fb461ed7d879748893399ea10a0c126fdfab0c75cef8d13e485d2b93b55f7469ff89db5e888e5b82ff73e7bddfb9f4fac62b534ae21a97a01ed46597abdbe49690cc0678e00553fbafa530422954e85eb5df21544f93ed3477ce067a680bb18297a740c1974a03d4291bc33ca9b5dacf7363b5b68002ab909d869d000f8a713cba09134e1c08df6a13d4d53d81b4b426b84c85330646d246d2d8c4fc47f6fcd5311998c0d80aa1b717328a9e3fe6cecce73dcf6fc99cc8e8185d7f5a56ea4925890b5601c5bda7cc4372cfd2680c0585a0b54359b192edc11b0d8818e1d4cd81cf8cda33e308aa7fdacfa1555ca3e9b337cc9470309cfe423f4598be73707ad3cf30600be1379fd2a31bc1", .None}, + {.Lcm, "-c1e4f6cae9ceb61d66c8cc8cccdf106f4191a5e4081e6aa2f79f00edca878516665d3125dd836ccb8962a1652e37586b759c665b5324f411090a8242d75ce33ee2e01b669b300d39848c232bcd59402afc2041f275ba12ff2c876ec67072d1c3f1233188b594713cf8f37dc177959b80380dccb578372a1d71129e9f1d09f16e948da18c8569b650cca23b3985217e68672693d30a92d217afe3eaac2a0316f8f1af1f81f86221066a06e3958fcb0809102f6926b259cf4865a5eadf5560d9d2d76c5cf0d52713a3338b49a3d65b4e7e3a0ac7939bf38707837f7d3bf88d9787d820fb2ee21082ff0ae478432cf57f5501e4f836c907b574a40981d1912f54b364e1f0ad9f800de7908954e3df15b280d7c0448154171780ba5200ff4e32bd7a1517acdb0d8a251689e331ae101f16e8e81740ca535be4e75e297324bd18be3ee42fc7398c79c10b5ca13c2bbd739c66f83cc2c8790ebec9bec90cd645d080ad72d56581236ef1a986912d995d378dfae56f128430504380145aaecc47d4f9ee742b1ef51f6f3323248e0e16ebff34b2dc3e09686195e232aca211d545bd0579ed3f84787c88545f4102376826fcb59e18491a28d9aed5bb0d25ef59a457e0c6f550fbdc260598941f0b967d0e5bf566be7dd8d4f17cdf54b803f34c1fb161e2aaf5550a8fa481ed07d3dcf59006cc1a75e49682852716a7f5b536c0dac22205", "96b3dadf2af6adcc373d73e02364a727ef817b111db92b44b5366c35bbcc90a4f17f8b514795e2f0b7bde53fb36277c13906dba9f3302567060bacaf425e800e3257b38f65ef7747faa74548215b6ec084a4abbdca358146659b61d848f4583a1554da6f2d395ee38ebd716e944b83a37e718f2195823d5dd0ea75fe9701dbfd26cb273fa0b1970c778a8363caef95998bf45eeca4d7d62fee54aefc3bd42071b6f323e507eb4e4194bbdd9211b50b600100674c3fe7dd3355ca2b5afb359291a3354198770ce3aa93d987c9b4c1784de97efd982b35df7a74d09c88de5ee631a5325a8c02eb35b26173cd347a4cdeaf8fd01bbd5563c75b2468f00940336544d427ca9d6871e05d8824eefd9ed47ed54f0fdb9989d7fc96ba4868ef84ae222d973b1ba0a6537aa76f93469cc9b93d995e325e948c2d634385f274793317d11910db965d87ecae3331093f21bf6828879f613e7267c861352615228f717248002500fdfb5220d2c05b867d4525a44546d48a1b70ef6c0aabd42a1f4099b88b2082a310bcb2826920d7bc1adad02d25c4cc660c9d4ca46b9993dec5e721a8ed81b497ec7bd710489f21571b81a2bc90527ebdda7310af5ffc902005f12ad41e44c4f795d57bd0b60a84a665765ffa1bdf4a561971965fba68e8c79d202ed3e3fbf9294fd3cc489929839bfb4a5cbc632e0a1322884206f7e7a5d1710e820d1f98", "722461797606c63f1b594ff3e7197edc43f2704052acbd7a80d0788366058b4d0143d6a1e6e92c0aaad3da30cdd1f3ed72e47bf3ff67266539e084bfaff42df672460c7c9d08abd70402824da5706b9fb667243a0a162e86affc36ed72a3c985e33a8862f75aff038c0dfd9d9484949ba613d428cca222f412bb03dbd9fbc6b36df3dbf4bca8f1d8c120806717a1073ce00f16b46a13cf2b19acbdaadc3bb6ea438e71031ede50d617b87b4f034e9d9904b972aee777fc1069fa4c3669edcc4aacbfa2f74b37d64b895eb934de355d47804ff08291b95b67e8ac60db2e4a6f2de5ee14f56dabdf1ce8a13146a15e04e3dc88dcd54782ed445253ffd0d37f1307053230d629d9f4a8f18ed6cda14769dedc69fb3cd8911661f7c05227068f05f065aafaa1e98d3d3437a55d45a8e4d65f806e180780e0b394b0df03db16a2a8b9531829a141f0c9c4a04dd90f9db36950d5a41d702ab8f2c6869c44fd91ec9dbb887cffc300dfea4e1510ac25d90c28e1012787672f99aee3d18b8c3a28142a5caafdfb7b8df853155328e9a8cfb8c5778c85d4cccdd185075975d2f21f0fcf78f305144687b2ebd8131a9660b1a6f8ecc4cc71cde1a42c8cdc977fb83616a6b6ac89700a787f1cd247a1179e7a004fa6724df5dbdf6a8c3951c24d2cf0ac8cd484e149241f1702b1b29c5a6793edc671098f0a9756e092029554e5763c9c2a1ead1f383719ed345eefadfe8f1760ea216435c3c106a7bc769d11c4f36d3878eb35b888ddd54dfcaca90da59bcf13f3b8258157d7f5335fc63fdbf7e5350d106e818d0bbce10a15da1db30ba2d79e059751be90e816e90b3efd250c48a141e4fef47fc568597f96797d330ff6dbf5452577c0d4eb2b06bbf7243761f51aa10e9149e807cf69c88ae304fe4083461e7f5dca1421106f586f95d7ecad4afe1e2f42dd22143a214b36b34e2dd59878696062a6d88edc5524a03d8fcefbe5c3ffc80b9c3c34c0ca18d6a8ee48dcf2d8d384a049ed930c13aac2d1016dfa07a3b4210d64a8bb8ff994f9398ac5f252e93e862cbb33bc3ca4ae5e616f1fa0c0c1150dcb5ebbb02f4edb11f56df323b9d90a80aefbc09d81b8deed532ea21f9f75b89853409af9a35b175cd7ad8a787c44ffc2701d90fe2cbd3d41ec1221fc0982fd62881e51d03162444b009de71518243c162dd444915c6e3466e6cda383bd3964ab2eb1075ce5d36c15e79e4c5854a4e9e10ef0d62935d49547d90f9345f9596ea4f14f8808855b5970e51984053b6528f9d9a5e2161e7b87c83b5b696876759e936b25ef6eeb81e9e6282fca30e2ee0b4b4e612be678d9174300ed0de4181a567416dac8beedc593e7f5b15c9656c4688f436cab22408a8cc2913431ba354fedaf1f896d42215c471b498b664a4a8bcdbe962b1bf30d73e4a78632d29f67a9a3cdf8", .None}, + {.Lcm, "-be441d4e61d1466b8fcbf27e6af28fee9f8c768313fd2aafea25b40c5adbbc5875b551b51356bc902a9e3c3c8752ef3ea25b45851e06543f9ddbbe40bb7e42fba9ae5520ff07491ecb8378ee8e665c5eb3eac44fcdd8952048b4daf5bcb93e51239e82d7104e2d596041376a047d56eec84c9ad4513d1ac5a90d5e22cc742e8230bd2c6f0fb26f5560d3bd0a5a50d7eb33e166c89bb194af6a714b69241f3b5f9b0130978b796f5366072c18a0efc403c2a22a702f552e2bdd4c868b40ed37e3de3d0e59fcbc374569da1de77d896654e2aca4ea217de4b9d47e2e1a746d0d7d8223db03aa8bb88fdf23b9c7f0601e420280d8537e56f4467bb86169ba30eebd57e07b376e0da20ec230f76cf86cc27c772f2fb3f928cac4d2827cd63d75239d757bbffa34ef61bb5ee823a50f735f2dde0715ec0398a9aeeea613732f609bc352620523161a3fed281cb4fb2978fa15bf440c83a8a63450e54fa4b704a40cc8523f6c4117d3e22b86bceb68bcecc54a08488c0f974abc7013924ae04e23ede1dde7511315b7826c04107bce83ecd3b1e9ad7a6352c36a3982d6cc4df13518728758d73c2f2fbbc480c9b4a96b5c47b020adce2abcf090692c4d84e3787aba5cb71dd0e2a07d90dd579063c55e36f55d5845f1a09ee561c4cfb90e943ca9e4622ebf2ec7a1eb9650d4ce44333fec81cf4c4a72aecba8b87d8825999cb6734e75", "-391f60f4f952967c5293325abb919fa3991bbd5ab68a19e60b5c20d3a622181111350a9ec48f8d9dc238c27ee45ece22d96df7bfa84f8efa83fd56f490609e3e85a727c02f39edf53a99d6fc7b3e4694bcf70bc1d11e5925bc893d35bf1176b6ee8d213fb8c400d7bc8abb53783a49c21e03be3e163e9e7f3723df95e14f55b52d59e089debd1e81ee7a139b25372edd014c9deb22248af28dbd7ff99e1c43156ead18d0ce05e36cdeb5e57c8c3ae7d1caec8a9ac6630f996b326064050131ef4c59c177748845ceba3a0307c1d3580a1203fcf4930069e0b8b1c003df4085f58411d6530b4bb04eb5a804b4f82ad0e30526e9018297fafd4e6a7731e8eee61701709af202a02f4ef1dc342ad5f9cb296542df71ff8111401a779989b9ee6ed2cb51f85ee0f3a76b0f49dc99992388ff1520a5a73330d7fd8eab4c9a391826808147e7f22cad77418906cfd159d1c8bed4d34501a4c93b3c2e6ce598f12fe2282782e8b4cfc49ee055e66d8c3e5422c47a7044f3ac8203f698b80fc24deb8e67d5c707032908ca9a978d2c6eb27f3190ad80371fd23b9ff70b97bff806fdbc05924d217abb3d54bd06a256c166f818e91218f3cde85e79e0949926e50a1487dbd1158e1c9deb713f65d6bd4e74bed7b281375bc150a97be9495cc1c6e88e81ce38bc7eac05f3dede788a2b7311457b636c1510de28357c9b2c03282db3c8b5b0", "2a747cd59d7c66941fb380dde6cedb9625579601e5ede8d31980de758764f937697f544d94778a68b8d814a82285323df7552d9302484130ccca2aa4676ffd57500555428e757ad0515e9c0cc87b3179d545f77597108d3eda78a5578ce62192928415750ac869f674364ba196c4bb51268548f68d4ab9c365e30e15b4556b77697d629802009529c8ae2f483af077d5d845df7a01f84f66c606d2f7dc21317bf217991aa21abfdae1d936cf70fe0a49db361e23cac7c628f63038d70dfb37a2947589612e4d998b265adea220976efb636022380457ee11a3bbb9c929abd616330b58468287a9c519703dc51992b8d6d233022de542ceec97e7d9d440a66ce30587157911428bddd2c9127aeb4a3cc6b0b963da43869e782a432bca3e19646c4948109f377a220466fd5378e1a9eef4ffdd08fc3bccfd53208e71b897c67c4d67c16b639fb512914f9ac422d642b16bbdbd68fa68598d92fd7bb0fbb420978e1bb1d17529bcdccddd7afa99ba1b4acb636d7aa307c2ea3441123d5e7f85a54dfe301869b803a885daeb815087db1fae4b333dac4bca385480c44161b616bb7f531aee6c7624775cf5811152d4ed8393a922187d73eee42298d8d3e286f669b2ba8305c0eb7830e2344764e9d208111be56c6fdfd4660beb21eaa43fb2a5725ec7fcd2444f7c4fd9091a3a94b3d3b6fe4078baf8e065ec9434cc9cc70181fdfc2b874e0f32cfdf2742a169f87295a587ac0874628bd34859038ac1df6c1fe65a0a0700a0b13e2299809106c6213788a0b777f86948c49eeb1a7f23af4f44977da292c69a800dfcdcac0fa9d8ffa8564b3d821b686091063c5a934a0e109015015ff56b6cd420fcc8092eb1dc8c463f8ab5f99e8653638d49c7fcc4bd81241a08483ddef6093696375f591a780799ac52f8ba719375137c1974c7d31abeaa00bb2cef29ebfd1c5e338bed5e87af322eabfaa03162b186597f8a8c9523e4dcae8ee40b1b212196218d136c3af7b97cfbba003095c7f0c6c84c763719c5f3f59ae1b8e39b13be512b8c9a367cdd0c9895535617a0f622c3034830b09baeb52aa1ffbb9e845c9b5e69ece4a04fe2be0d4b6a9c9c49c8d2b1f1ecb2492d1ac9cd59155d5884e6d98ebb7ecae1fdeab54089877b7620a0ef4320fb9730e48282c6094b64bb7874658a93046080297ea267fb864ed8a52400d5d58e0f9e86e0ba90a5791bf3f87bd0463bdd54071b2429830b4016f192794f3695b6933cccf4238f2303756a75c8c8dcbb143dff181611e68b9009c8eda6ecb7a72f21d9f4b20170adbf49aa3321a045aad477f2b6fbb8d3ded0fd823a6f7d20000d977822721c19cae623a36936a9651165f4ae2b4a1a29a47a98f793fbea7177edba24fd8d13dcc3f393fa492b2b232475251f4184cd5e10e2f533ab02998cde13e35ca53f1026a970", .None}, + {.Lcm, "72bc9f47325d6fc97df8057af052b9e6d9fa7440ba22b171987c82bf317134913caabd694bf0676158f4a93ba461d5107f54430e5b273b443c16fe01f1bc578a197a6f711fe6ac3d2958f3709acaa8b4d1e92f711dbc9ae8ce11d5f1e4e6221acbe53c763687ffbfb7170ecb81e4bee7989401cedd430a60ad5f5363b67c0a6c37c4c396a55d3a42e25e3452a6cf43f083f92d6b5984dbb091ca00ec7002821b04af080bb7d92f697acf2f799f4fd6624015303ca3777397e46af95275f50f6552ec928397dff6d34886dc48f27808d86e4df00ba6f49a1c4364b856babc134fd84b15e7862f3a9ec3e90923fda6f44059d83d500c2ba88097ce7650323caca06cd2388fd140aeb99010e1b876210559196858c2be9197ab506804d303e091419607ceab0430b30231ed0e17f5f5ac52cf2ec00e9ee1f1b8803e344f1572ef6ccc4cdf5a7d63c6576888e8dbcde614aac0174f963a94fbdf736f6d51da80f3ab808458040ece759c8a68771613d509889193509281052970b6fce75c797c02efeee3547c8e44e32453f05021f62b21b6881daa6dfbbd6c9e87faad92f11f47a8697cab09d6aaf5987413dffa3d69657c33c2a4352c337c1e01d1b8d1556737e55c461dc90fbdc32f28a6728049adc916da3ecf80055a4dba47b2b6a94818d3da5c5226688149548612a2174d994be39d4388c43d216a5ac8a2a4a639a5ec30b2", "837037fef15343f377e160e86195acb571edc0023777ba5fd3e3533575474aae972cd9e80ac48b5e368af822fb35c4f7f26e7f4766376359b8b84da11790f14df4c0c6e1a50631f18b65fca4b7e6818034c10d11eeddaaa156bac632c23816451445234cc01a7345fac2246bd786079860d479f933683bb13e2dba2a8826e5a43185e455513697b9b657a9b349101a137d844041ab4652aeb5ea437df87ff1c20ebfa426e980973e33799cd74623d654f55601248175ca188d4ad35a38a6b3f795b69f8fe514f2b3a860b6dc45425e074ac74a8f945eb73afde8e3be25d220732b22feee01c99c4bea4bb32c37a80d223cb027ae821badf38cbc7fefd3383035bd92adf9aa670bcab34b25cf9b3d522866b24d7485da83840b9d74ee0392152a6944f939357e443fefce3ab1c42309752dc3cd5a8f84cbe2aa115ee1f61b6e36317e29641d69ee9f8230b256181a14bf5b4ab1d8abbdfaed22298fea459d0c31c9dc65a3052f55c2e6befa05ce21fae2cee13553e6158d81198ec4e722db6ecc8866443f635f0ac06bf5a3a187d20313fb6e972b39a3cbb899d98f2d89bf21ad2a884a6a18ce1c98d7c65b970f5cd961b033d89ee7ee45fd96bc90fbec4611bd57e329748e3facdc8e844746509ad8b30bce753dfae676efa4c20316388ced6f8fcedd50fb7afc134e329e22b8454a28701b77ce273d01602ddd1b189beb8dea", "1d74688ff3b9888c9b2584ebdea3e5e280dd4d525a7c75e719c358e2350f598f57715f0595aa5e59c22eada45a7ed03838cdad61df6551487f9ba4f415e5259027aa0ea6fe2678fc800c1a4151b76d2c4d1ef5034dc11b133103909a532640b84783caa155bc0f08c79a148a351b3c77e4f199171f3c06d80a12c4336b55e3a06da5e60ac213fedbedd2d084791124799027f0455ef6b0fe738ce264565ea9b45249a256796a73cc9bec9bf84ca58d3399e5b40f2b905ff29657e2fdd7fe44bc4e7af67c2d2c97edfa77e3addc8dea2753e2e046916575fa0355aa5873f4c04e43b2c45c1df82bc73533315204add7bc881a1a5c625fe323f59edf0ce0cdfd3372603dd527ac9bf4066bcf23f01028063ac6154ec3737fd5144dc51ff23b4822044fd4bba0a4ee850efd3cb423d60438689ddad1a2e0aff53a20400924c1f6d9b1d38b01ded9ce5d1050313d69efee93aa985d4dfd7dbb4ad2f4c22bc12db8d93f50710537f27fa8c49eb103ff08cf631af51e4567c6005e8d6d1a330e5ada8c56f2febb530b9481ddabdccab6610de8e7157db845047e3117e702b8f3762d761c81058dc5d916fc7e79e5d8b98203022af7dec9200b3168672f166a23108a32f21163af38c662ee516cea06e3d493e4b3966c26f137f7a27bd32325d51ac963ccc4f8d30b7b5e25cefc2130acc11ea0d5a599f9b39b56feb0fa6bf3f83cf72b5b40c1cf2a951667df0ea8e05e9d183b952f2d0caf9e0e95a66847229a9c04035b59e618bba7cabc03a1623de720a37682641fdf031bdae2f88e6db42634d03275431b6749a31e06fcddccaf45198ea0bc056974841245fd7490cf31efbc8e0444e9ddcc79171a531df4e55a0ca8daf8f7dfa1c8f4625a918c69cb34f54ceb513fa858ef01295818b7f0ac8add66ab4c7f1467887b9b0d058499dc824d6e215850b0af20755aa91ee144abec71a6f3b39e25ca06110dec5a8dd3cdb24c4ed0ebab3a0fc871f504ca83ba939b5837ba58835d5e6aed3bf67d8e76cde9f0e7b35cc4d28b0db76aed38bc70f7e4efeb452b07c2eae29a30ec5785b8cebc4820fac018dafd4d020fdad732e536224821ca8c329af993da3c0aea3579c7ac3022d627894dd6e8d1f8c958e91e45a9c43ef125f02f9419691e31fea2b6de79e53bde5767003badddaaf7d9bbaca9f5c5a5cbfa490b6a26320dd363f2d02a839a3a7a0998e5a3bbf0f8db95ad143a127d854265240446ae385fad4a02c59b9cc4958fb53d4b3d0791772ec769347e113ff137133d061391bd2c6cdea3302fef98053e76faa10b87b4856aae88964c67c8db9acf659c267194aa1a6d105a1208dad44517eea6894abd0c0dd0834207efe5331218fe0ba78fe46ae21ae5c7838f85ddc8e98cc77a7ada30f2c2ce2f75f4482e7d27c5d491b305f8ed6fd1b02c889d0e465a", .None}, + {.Lcm, "-f32e81414d152c62afef130a9c05bb952cc709b8e3bf92c2b41a6448742a3aca1f8708686c52d926b6b9d2957a1e2a6d50104f1b692a74e5b9a99ebf6d3f7154a85ed962b14d2870ad869724da7dd1109d546228351b3781efbd72b5e0409a82956fb42aee05c9500c825d7698a45babde6eebf65ea5105a0c7eb25877f067481a6f21bbe2c1eed222a5c610e32a8a8c574dacd2d5d261653b7b05a8a250955fe7b5ab42a2b8009b5fde9c2a707519fab2ecb7ca3d4998225b512f6c8c7d9987ef694cc0c260f811d63bb6f42a47a81be1886e3bb8d1c5c4de4ba018cc9ed15d15c1df4383ee8ccb251e46fa5623dae64bca667c9df7c7de582da17692f8beee4c1385b2d0ec8106a8ed73601f240be1a6ed7efa19a9fcf3891e1810c76c61460aab453e4f46da51625aaca68b6b053995596fa3d86480aad44c04218584d22faaa2bbd4abaa64071dbd35c0b65d6bc7dd4bfb4a2b69d7c3ed71a3bcba97de8e525ffa248f2a2dace918f72fb8acb5d95ef92e5228386d90c192d2bdcee57d5bf921c316a59800218119cc9e9103cacc8eccc80ed7346da4eb63f02fd00bd55d123f3c7f83a6b9235b0d9c90c69f8f6f3ee92e11fe962843b3d23882f286c796ef92691e463bdaf35a6354a1c27e30ee1e2974f3053993a4d4ea86ad390cc7b70c9ccc4c16d5daf2d821501b5419a80035b4ee004941691378361a3f105f3ed9", "-c8be03e4a30555aa8ca090efe65c02cde335bfbaf42364763ec22fc23fb6398c182c0894c04e8a7b94dc6660855bf8f69cf5f41ff190906d10a5bcd8d6b97dd7261a4bc8e39dd131444c704d49767b837ad3ff249d25620eebda4bb6b5d46eb3e14a95848c1b0865329f716e01b38fa82b9577fdb9830f0aa3569c692c0e00e8d44b2c373a163a83ab29117bcf90bc0feec4bb581136f2f6b08639a88a2e895d918852022545fc31dddb79b0adb6eb94e07712350eb9e811698d3c2be2906d7a58c1773662c0b18af15b72c1a0691c0b73add8586cf845dc80fdf247ac5b28eb55cc85d2cd0f13534522d9a36d4e1d22af6e5337ceebaacb25ceff96a98004a1918be7ba30fe7ae35eb8fb03221a6348d8ad89ffa66aedb9596fa7b592b26c352cda3aa659444f29efcce236bdbf48ab154f35aba485018277c1ec41d3db6c1fa4836d6b4f03e10979cbe1fd4b3b44c1556b2d24897850793ec77d72dee4f9ea2b0638f2906dc7fe6b78c65e7988176aeea020fb1e3f17012b3320e945813c111c3d6b894e2a0cb1efd0fac7de77169c6f58ebc993c999d412b91c45d10a9772ad3bf76a2646e425fdf9bc801a565cdc1fa5e66d03404c4e1525532e73bf8ba60fd91ae9998aaa7d9c71d9e29930ac7b5a235f32896613c196c357d5066f2b79af37e3a9d87b094aa8c0fa770dd57959ea8265925c533ce86afbc1118c2a541a", "beb0d531ae7a50097ecf805560939b28c61118c8ecc14420969fcd2f1c4d5f0fbceba11651d3612ecc15945aef86ca16589cbfbc9fd1ceb75def9abbae3597fd757a67601e70a51b0458eea101f207723f81d22a7da3171eee324289b74edf076cb800092d41f8d06edcc16640d9fd856374a05af3363f3eea19c81d659ca2cde94e9ec1da8527a81d0828ffb83fa711226a9a8a95a429b465c186f626f9ef08a1c290537f40ecc172b16619b39ec7ab1a5474d249a74e1787c8de66e1def873cfad6f3990a45405c3034a40dac1ad9e54f12b58bf269839a4b96a2fe7776c78460e95eb24b8005e64ef97ec03b6b5bd4293714e7b3ea162bd6eddeed9eb8798f36d2fb9ee0d9bbf0c95e7f2477c69d598bcb01f63ff68565a2c722e9bdf6b83dd0f9797b61ff181a0a2e35b13656a15762ae48d585a7d3130f97710c8a1f697c6287c2792d0d2acd1e2670bd6dd38f2b4b5fa93f6d6d629a82446438ca56de9a18b1c92ccc5b0d43976ef9a5394c051ec601f6406b1e8ff41c34696278ee24752e2de622b2e461a625c98ae4c1ff7aed00df2e9aec2ee8321f0dd56182cee1a860c83b1a702de838d9ee9cd75a2d9c17157afd47b9980b575326dfe86fe60956bc7f0c91c4381f5567157d1f5fe5e449794046a6324f7bc6ff5972792b0aef3f7cebdd092c71012beb13e7cb8f2634e9a8f77001dd5d96916d99042063ee96f85e25acec4d7e27a6dd7d489e9d112fbcc043948f8571ae86d833b721dcd67a0fd457883ba52a3a3e7e4a59e158f76fff100d96e1e6916e561d5b59dff7dcc24007fe0087dc6160f099bf0588b98d7415926f0439d6ac759e3b8aef5cfd6afecaba21ce83342cdefbde16d154a9ca19c90e2df86b6a649e2eabc64bbebc72b360e1067e54a6e14e82e55c8dd2783e2a1f8ff391f4e1ee107e13266d7f6864b36ac69b1e95957a39f11fa3a3e7f2c4c2ec5aefabac5e2b46dd8628f1363c19c478d8a29f8c5969588e93bcc554eb26814154375549c9b52c4a3e7d24095eefd0402c5a725079aec2326c6097b44d442230af56d430f58c1c3be623807f5d9b015b8be7a968352aa94d10903adf2d5a9af14b607ae0e3174716772cc255472a6e25aa863442e6d9072a398d262545f038bea7f527d1341f46d0d56dfd62e850b713cc7faef10bc81e0a35cea41582fe5bb908c1d46a5ed3b37f9e0d9c926507cda4efb73ee10bcf81ec4c84a41e0b253a6f9c6f8b66368665ffd5d7a42ee5eaaaa8e5b1f43b2599e3074474f1e4d61ebce4f196c24f4a2f0e7e088bd67bde41175fc3a4b536251ccc3fc60884fb4ef9734d660bd70c312c511e0d1505a9f38103142b1eb4ef82311b0c5ebb0015785d7c0a1719f76831972987698e60ce6f4b25e34b7636d678b09bb5b8f7544c22ea9d843d3894eed72f63f1edfe72ee5e5960a", .None}, + {.Lcm, "-8deede84c282e58ff1ab4fc03b974a335a988308d9226115ea99c3a631a41c89afa1b08d0859ffc34279e6a2e71ef9d85dbb4de5c5da923ddd5efd1f0baf7e97fadba198ab7d40d44d6760f87615b6c6a0c5f8449953d99894f0a2e21d8a4303c5bcffaa730c7fcbb0e5f0b807fee1fdfc9d3f7554ab82a71a1d49125ed5e9ca884a742c157e7f99ab18b687a5edbc9c1e18da25e8c4c121b701f2c19cc89e9c2c5b63091b16faf2f0b7d869bddb9d43ac4e59f319a7a25591fb585ee8fc3c2c683f56920231d51b70e9c9ab644fbc9c0f19a998802b5dfb5e2ed223319d570ca5c14fb2da0ccc10d1b69adae89f4ce8f469d43c5c8f7f9224e8be014f96518880122fc9a004340f6b6ee790734eff73c45e6ed6f57104bb39c9c035e47e4025445f924378c8d58e63a283cfa542086d0c85a9f4e5c3cf1057c729089f41153acde53c2c340712036898b996d102281a20ab022943fcea8067567bd43a3bf8b74d605c0eda54e4dd2b026d075e756698b6384319fd04342be451419f5ebc26e1be5ad7db98f003864d8b8e4a899e0bf1ea390de11b5fe0714f8aef055b524ec7349be6fbf892e94da9c8a5e4637e429a32d3673cbbb3c70769e3453356482bc7cc24e2942a5f0b789d6963c015178ec25d863bae9e4a086fde3300ad8fb0f7c974304487ccd44852722372ff88d617c595b04f9007250a3346d7808e4622518", "fb7db1d25ce5863ce2e7121e849c2f8813eef1e406ae0af42903b74d40c3024d6cc2d50553ba1a0f3aab1b86871a82913dcec23d5eb6c3ef31042f608b3fef13b210eb518822123f5bdd18419b86db12eb0d65f3d00db22022e5d58a85afb1d110d439c892fb0e903a6902365109e5f9f1264045430459e9ee64cc9d0e5a97b013ee81e71385ff679b7d91175864e930a484fa4f00f22731644f459658aa0f042a5637ae6ef04b20db8e582778593200240c046c4d199485afb122844127528da2b89e83c8fdc4cd2fa596f4a8136123ba9615f83352a6b8fd1010d524135b98973ad02bccc778893d90d69d4330a0c58dd2b89bb1a041e67dbe444e82d9f0be0a724b889ff0ffe8a0c38133efab0378f9bec3a2b6347f4c8b914b8ed9b9e839adda86301b1644cce51f6648870a07e04bb547f86fa865ac86065390dc4b77383555d9a0d1e1f6eebb1b4aae1a83650cde232d0fefc5407f9f7006e67b666eff27d1e53bcb611e893552ae2438214092896264e6e80e554bffa39c32f20bd1477c33b2f94e93825a3086db6d6a668d5bec93c23186a6bffcd1f76432260f63ace80d8c87b99be9b200ebdfd49c93edb8496341892e7adf82ff4f8c41c6260610f9fd3b7953083af61f8f121fa1b056f4d24bb7771e1157f1c73d0794c9b8cb084e67409eac0aee6c108363e36613a3769d08d32981485777b9ed216d3d2c34e6", "45b77232cd6b5eb9eb203cc8000af3a82fa5a36ff8a1b8142a3af78dd3aa09c702f69548a0c2c87ea535e20fd694b8cf6eeaa9379d46d0b9b9771bb94247fb5b5b0a0eeac4f781ce96bd01785bbf286a72dd009e9b629670aa47939e419fed6e3b1dd66d25b407ee9f0bd99e51bbbe3d71993b707bbc911d8a374ed4c6b37f9b5410351a69cbf93c52dbac547e785091324ab268929109e77227f6510c9c119bc8a75db798e7e3bc503f594f9db3b2b209664bf976626a578bd6c888f95731a04f94f1d3525ccb945afb2dd15ed1d32ff016da021f53e13ad0460d5637e04cecfcd7644ba19b363ef4a34a971f3587f2729b56af9c04b73100bbb0b1e1675c1e4a065b4133d0b4c0edb5039c050aaa18eb8769c0a38e15e1b29e92746a187726eac4a95a19697674d57f12311d3230474e15c169bbb297e75b33d467f337b346a73479c41d1ce67c1d181874796598982a2f13913fb37491f3a4d971c204db9051c92837b0b83a2f18f5451441ec3cf87dbe3a6fa39cfd9f269f4e8cc1a6966dd46336f6f331c5b57c613c3900da60a86cc8075596700fe22fa1dee47f5f6511a8de8fd55157f15752776f181a2308b88c21c5214c00c82fef89f2881c9c9f6ad5b64321538e0d1aae6966af1ae83ff85ef00aabef2ad6b29b603517b1857e308392e15468a3f0ef6244bd61c037229fc74c9c59e6dee9031f9e2d004872348d7c49bfdb2b62e9a5777ade88c87ec3908b4ed60976c396837d414d11469488ff1cc2a01283f2ba31ae9a65ebf42dcceff64a7bb82558668e1be6089d67aafa1f148946dc329970ad7ceaffc1203fbb1a86f101790cd24ae2b3c55584b62816cf05c68d4a905dfd739b9dc1123476e7f685caa3df15e862efb4e24696bb8148c17f39cc285d06dca79a20f1940801362f7035384fd93d98d0045b53fa380221d3e6ae1b89275582a43d410a606bed1adaacdfa22959b7941fb1c3c65acaf5d23b6bdef62fa1175bcf4b9c21a803394c250677406fe83dc77bc1c46a74b807b4d8daf06abe30764d40ac305fb09818f00ea73b49ceb7995e6ba174472f90012b24d38a17720937fd2d347f61a20085848a0513b794265c3ce7709bab8f48a72df9da29d4f1541df357c267f443f1c6676a9df7dd9a9dee73682687cf55a4fe74d219aaca4d3d1aa7de2746df39919071e1d3681cf1952761b069cc9ddfeeac0c9d52f5925294b329968d2e65780b5db3170387625cd890acb425194a28e2cfd05ca3685d18dbe5afe72bcfb2ff1a1c0054746e66b3929f8621660683586bd4b5fc686f544fe790a0212253b22b842865d3dd4192fa56de2c2c4499a7fb86950fa68092e4986665a33d8b41fc77e19d8861759a95a49fbe1a5c22cf88c675d139600aa3528fe824c31d9ad6daecf049f3051854df1b2fb5a5f553c16a71beb19c8", .None}, + {.Lcm, "-5f96eaae5a322ff3bf35db2eab2a1c9c5b4cf4064fd7acad418b05e95924f51077d684e447658ebcf4608838d5129be9c4b123323afd2f872605544ae3d918c9468ad607ad10ab5e95e238b388e9446a358671ac74c7b32a3477adc0bd95cb253cafa6c2b640d63dd70f39befd85eb56332c41697f585c9b2dce0a9edf476b16e958598db226d5f293b9ac1a73e98a9cd103fa30f5d3f7cbd7c738bd7f986220e27c24b4e16e824cf095357f37c52ee03661f9ab83f4774435ac56804965bd7cd392407d4d919f4b99c8a5b916686cf4753504c08a62952df1bc21a190a5a98c676ad18aa941b852aaa10df076fd35127e67de7ce8ef76d70d5528214c05a6b7306da36892beb1f2fe1d3a868dedaa1fb9267ed4b9eb84b80a740a1eb77291f4ebed886027d912b7df493939e3499743858d48d7ec558f8c0444bc47e731904bbd77055defd0bd7d81e7f3db23fc923aade95225ae7be43b2267dadb9b9503f7831814bab97fdc566123d11a4deaaf7f88bdac2849b103a98dfbbfd789389c1338cdea169fb87a77aff2f51ffc51c90a8949ff2b278a053643669a04d6bf235c1f6140afe7a12287a368699e0e47a89536cb6419166377c04328a6426d016717242877b51863b121b44af3bd1a7de0673e4ec10ff45044e8e528238ffc50fd64d1e795ecbb71326948400fe5bfe8ae54a03fbd7af0429e670d74fc513a709390", "-a974f265823448160780571b11321f674b05f097d9214705c8ae91684df611e106ac27e9730be6802d26118cefbdcf2e8a8da27875dbdf0b330e1bad884d33fe4cd96e1f5d23858f93c41b67907be5994e8703c25cf086f859216a8d2c0f6c3a073e79b5ac1e56e60eb2946164baebad45d9e2a21dbecc35de85b07eaa1a4212ede3726292aa3b48e0c975ec7cb1198dc7c0efc8dd77bc862b6a5f094adff33b5829d2f784d44afb5bf4318950e06ef14c69fff996ca421d95e050c7e85b280cedf40bdd67b4ce78782c9b3cfd7b4ce710a08eaaaf8fa0fc6e86bb3cfd3de8db1276d65b3df88bb5692623988af06945d8bcd9ec7f166537ecb477cf399180e68fa217b1f92f2aa5b1d8c1580b957fb5ff315c7f17f719a92f838591f130f0fa7ad67a9a3a1c926878af433f6aa75f3d95c929350e83fc8ceb80e60469ba34e625ca3fa0daa8bb0d8edbcb58b35332a19fd01f2eecff6c2b5398a0fa2ba8afbbac714d18fbfa3f20e9986f75589e7be1d47ffeac8b38eb75ac05370caa5742aa6cfd1bddd26db1e9ae3f961ac0958049fff4fb95212eaa84c3c3e6a6e9dfc23c8185f4186f8c2d3836bac71ba3e66f5f3934e26c1026834dbfec0bb9bef2ddf2d7ca649ae4d3d9ebe6ba6c79034435cebf743fdb33897c8531dbf609e8652ed2a0fb0e058987b5aea5e4295209d865487eb5c80e9e9fecdf9da41aa48162dcd4", "fd192f48063644c62f325d4172ec198b295d11997f47fba4e7c164355996d9ef0991f62632651210607a909aff93e0e41b5a208bf77f79c6572b2d6ab1a321ba3e0d714d4479494f78ec194e966e2e2a1c89b54a47818daf9d7a2f7ff0646c174129c986e464bcae8b3ecf2e9f285420e998a0d98edeca2a8c5a141c87b8cb99949a0f49558899ea7549500a7f500d6b2a52a21251dac579c3ea7864dcbf06085a8c27cf04098fe2a7e0537aad3276f3ea941e26edb3f0b8466219d25c038c7599df5548855324ca069eb2fb01430f1cf36bf5e7f13e7d0a9b282f0a815c4c620c3fc1b94fe05dfecc2566354dbf9f5328024d9f5e87f779c4199f384983e4d7f045827c9e8f21fa708dc8dfcee9fe091936874cee64d56b7494abcb5939dd2fd74481f07ea9b54a7de211617f220c1b8a7c4b1793b80795d531d66941ac6a33e6ff87429a3f3df481f2c9858948007358b3982dc4e34ef992ac8e1e65a6bb0a131362ff44c4877599884035a332bde964519d71ff58a87d927270590af82a5b425a48eafa774347bf8e165eca7f655c1c20d041bc9319ffff50c2316a1a6f0f5d17e0ec3946d0bfd2d46a5e00f5ed3092531d2830514a3da672d27014c76a43244b4885a227f4aeb0ee76b039d09e31f85ce26f0daee4d4c91309e823d2ce90afa6f5fe0a25084c0b86cfed7c961f63573abaf28792da5fc1f26653e513f09b36a1ee689ce02ef4a31db635f5f11edbef7724251abcb3bf5865c74df5ac51b988d235bfa53f208337c12668d59bff1a7aaea2a9cfcf54f567216ff82cec0c32a2743e9fc4171e5a1b4d41db2265011834aa662a8fd1f221f5c4047369623895b14b7ef0204c9d3cdd0c5d8483fa48ede41de233902937eef8a59c6cfb44e407b56d6e6d4c0f9d15506a0b618d4b2241af6094ab245678c6cfbc8d71b4f51d696230f4a3dfad79c6464c018c430a3238fb4beb6275fe8be5179f516e9188a8c9790566c8a825ba6c111be6e4f6237d8b658a842549aa85365ff05f72f24e99af5b43b84bf8d7f7efad98cb37e6bc71325a3de4a2e4aca1b19cfd21c8ee8ee9a635faff25866869f9169aa3357cadfd0a4e2e0c0b91f352e1b4a477ea1cc37ad1796dd3b4286854e055103a50016a278dd844904eee82e8c38e90bdb181e36034bb9e9ca7df5b6a275b9cf1df262f1d4227117c8116596d61e8b7dfc6522794350e68e18bac61634940189aa372d500aa82cf9a4e7943e4148f77e1705e9740e16de4a9ba0148c2c400c69d8d939258b147cb6f4f144319cdad3e0940783b3e0160197ceb869fc82d2a3978d5b5b4420433b1138d11a29516a5f93bfcf2faf542f343ede35a59558a0fb1739394b0ce306d7a0851b4bcb69b366883ffe98db5e6e743d63194c569b58953ca672d3030286045c0b3d209ff6faa740cc4c4a7cd0", .None}, + {.Lcm, "2399c6ae37e925a7d6478dfe1282eb79df743cc434ff4ac012e7ff59e5f4531471f20d21143f38284e2ef45be8e79bcf760bdb72fb42616e93586d546518b5451b0467d0bb7d0cce2945532ba9b14d70e57182d058b395a41bdacd1c95019803330446b31fb5d1a1822a0682aa3434a74728f23995d3371c70867bb85a7151f3593081d93cfab5aa7f5bbd492bd1694989a0387bc657bfea00931c5445fdd21eca37f2cf9e69f21ef5bdc1f206b962b100d67d88c85272388f3e03a6ca58eac31784c2887570bc15d39507cf0c5721684264b303e9a6300090f58aead332ef4f28322d44e6bc7cfaf29db6c137d21c3fcdcafcc212546cd76614b9129fb769a42809a7e8b110423e30f108cf1b4ec33b249cf8e6e25af87f622ad2fc81ce518d811fe717f27e3573bc7504ca50ed23042fc3727680a8893ffabafacca0a5b18c655fc3a5e12c37a0d7bcff13a1b598288426667b57b4349e5938b5dffadc37b2d61a48d12bd213bf3553824a5a19eab95b21fa756b06b564b5a5b9b83afe86ab4c7ba9fddcab16bd77a3a0ff8b5484d65277ee2fd83647405f5eb37631a5e7574c8b1c1d67790c5cc859d4caff8c414aa4255404d0891095346b32dbb56ab29b077bdd5424048bc7881a5e380c6dcca3d3b42847830515157b671333adbe6566e46d8c4a933c134af4eb27c73c88c201851e0277e3edf5d41ca9b4968d5acda3", "94d9a2c52bd124edb6bda807985e3c43783c9d45415419cae84cbd8b1b4b83e491aac71960f42cf6db0a01c9e03df53b47a94fd8912f9b7585668776e97d320df4c0ee60ce1fe1a38042a2a55bd7b57933d958a0ac08caad3cdef1aaa639354b0a2aec9d30d2c80f431c02882e6a6fde2a3f2c9aef5eae432ef15d2ac20cc545988d7d6cdce751bd6d9f46ca7d69cd58de3c1063b490c34db3a88ed2eb6199422c102ff2370c329430c0d2bffb2c306f33685e4b624d0d71e9a841e0defee5e86798acdef6986c893a72b60b6131a2327bf57dbb89f05b2b52e9e74768ab67f1d5b4cefd0ef25ec4f08868782b025b74a64248700058cea8fadc30dea9ff1e797d941dce6280b80d0d51bf43608cb1915e1e15f331755f2c29f1504060bdc1f0bfda7d8cb09bc64d26b762a8801f3b9d3c9066c4321af720704d5de3a183281c004ff912c5335ed72047cbef1cf1724c1320aef2d30e63e988178d643f561bba6ac99ceaf8952f32c01e9bee14decf4a13b463c6df074589868179af57f9273694224d56f857e811438e45c3eb81fa40b927e8104b1d5bed396091199ec942457644e1fabfa1c229c1c4deb8efb7f1ecebd7191ec5bd04d77dc1bcd7c53285fc42ef3fdb275902f3e1eb543b3a88f63ad0bab946bf55b5bd442ab7b65cbc910d06df0b5dc80d60e7366d967bfaa9b105ffdd881afc25b4e0e2044e76be6b9e6a", "14b32ad8dd283be5a9bb21766a4a0d49aa08c5cceb33c66a7f1aafdfbfa7f7bf5c97194170357a2138fb8c3f3d5654164fa049872b73329eab4e757d57f104e8ba45aab5b62722142a8197b264143c31cb37f454d666e9bb8baea5f74c08a96b5a81f63a8aaa4f39e124c60949941c8e7a61cc75ab5a3661c9e42291c8ef4402d63e4f682a4535468e16b669e3474b82ce00b0360f11c745b2155fead091eeb9716e38acd5323ed8c5e61f1a08b0f744ea207d6f548191deb27edfa8c6e717a99ba93d0d17e07c4be435ff794233929e911239faffe61337512767ed8d2e5256f7eb106c5e5afdc08cf95ee1a9517328dc563c3e619829c25dfe62332133bea9bf734904ff69de879a5e41534af37b8c3acf13dbae67110344d192f7152f8aeb0e2b4b11d03f7bb3e6bd2290d34f9b92e5265abdf986274cbeceb84bc3500b9a65e474e62f6deb58bbd1f05a883544a1495438363de5d8835b2e97a85c5c2e12449d3e0e68fead6a082ddebaa4c86638bc505ae4a8a0e9edf5d46dc450da38a4eea3ede1e6ea4bb0625cf1313f8caae656a67b696e0b74ebef8186c76348be6c54b7aa767bacc97ed5f172cbbe3d92d03f0f16004e0b0d74fc2961e8adaab03908b9b75f090a6249532f8f198d080976049d99ef86ec301d59b8b130648a0112ca7e086cb73e865465e789465088a8a9503def78d51436948232e9090a956cfb8aff6168dfa03088568330db14fae93ec61e0541cd890e556f9b5cf25dd8dc768b79f17baeb0e9f623e27065ba931c494bc4d8c2e6a90f976c3b52fd731e56b798bdd2fb01c22d2ca37461c9c6b9287b2ee15af4c0e7c2fe22efbc6198c932f85463fe60653808e253e92d38baf4301b8f0e957a1aa674ffe6289ecab80ac90cc63a2b1580748d51e34fad8f51665edd9e622cb2689e3eb917788cf0098f1d63221a67e48342c814fc0ad9f1207fc14433278a0e8aa83dcda7ba847593538fd0c863a8fde074ab77e87f2a675ece17a56950b99ec4476ab627f3f6aaa45f45f91c2f945fd840fa150a4a774681b0755a62780d2f45bb0b0936cd236022c69f1f83387d45021ec40d7ca93069e54da7a856e0863800cc038d87e06c9881be4bfe92f99a710a358c9d1387dab60ec947e3cb9642a191e894bcdc39b72749e508a0ed88b3b75d3b442fa513eac05e23ef2d6fecec115d5701d05427c32f2411d822065d489c766ad4c80f30f4f1d40106cf9f10c86171ef2ff3605274c3bbf2f0d9e05081fcc7a2e8917672154b1003e15efcaf0c389a2d13933d35424b9624f6987e37d00c1caf255970efc4a95ce350a8f3a852fb79bec4bab793ebd6040a4993055ce4543c0ede59ce79ba25f82699e150c00a052f9241efc341fdb22a3e07c60cd469811d695194340db35e8de96f727ffc4408c62ba886c29e9e497fa4bf7e", .None}, + {.Lcm, "-1a76048a93dfd3d5e91ee69f4603865287d2c8b6d844b7ed504df66648dbb9ff1bb70719d74809d2d1c7c6e1acd6b05f5e214285b59956a3bd9eb3214e256ad2fe40812726f13b0b1ee60ba01725640b87dd3538505e26e87db9f4073353f168baafae5f346a469442ce26fc7a1b1875d873854238f154aaee5209895af05267ec7987172896d600e71971aff8cd6e5722d20eb938e55e6c1ad3027c375173bd27a838d22e68f81ce9dac5b7d16bceabcee021d6d476cee90bb4d93cda3d1a65944d6f9c0ee99cb8929e588cf4fe8a6010ca16a0e1d463dd760c578bedf2c4a73de5e8457c26c344533566744d28e94018c1afa681f9853a601500a66f3540f003dfa5e72529409d130cde42e30e021f587fe11d11f9b35a800f6f32b229bde98283174f303c0e0da194ac762663ea0994c594171c4a97fb8e68a246fa430c3cf58d82ee9260f3855327a1f287b5d82725e9e4635c56ecb997cd454dcbd843dd9925c14e896c7bef6f86344a07f7c294445ec476c710372c9720251800b6957986f23a8ef7060668129c9635c72f49d67c0cba4db85aa1afdd2b4e031cfcb27a712a9fdef535f208ab921d8d726e2753f93e28bc5da25681523499f01f5fd2389d37901c80045d1509b11cb522e4f76ffbfc0a3c453abf65d5340a79f8635888310afd224f339efe92a5c6234bcafa2621c418b3351592f8f55ca93d0ff213b5", "e6b910bad0e1b3a166efe9747d8d9d0245d1a338da1e429effd9f72c6505e18ab681e00c682ef4384f1224c1e2ba74f09c8786d68bbfc423ada5c0b20cf50177fa237e1f575bcc796b6f2f6d99473ce45499129b51aeb79248a88215e7bc4360e2e87e0a86f493ab6c03497c137291287280353728f7a658736631eaee6f8432437c2e2093b7f19291d37ade1c1ada46fcf8807538e4481bed4e4472e696ff934ce5023c212eb74631b454c1d1c3af853d0728cfa0ebe69d037d4dda18a8eb2c1d726289aa6aafd4d6c21d653ff54ee37cf1bdfe3b1a3e307c8c62ce07c3034eee5c6a55655761b0e4fc7701138860133b7cdafa90badf8ab886e04c1f505bccedbf616edfad051113b1fb6fdcd0fa1c0e783ddd47906cd6c64104efe8126b64532ae59cc3881745d0ce65390ff17483f6f829c4435c64d96de360f9e126d95ea089ede6f7f934ca6fc25824241b79ac25c908dd77dad3f35c97f7bbed5dcea2e1ee4a017b592c281a614b8af9094ee1f3db9d8004f8375dc44a7f8d5e2c563e34ebc8dc57b1626568be3a30ef9e8c40c99d82d2030b92c51e9a22037aa9e2362a3baa442599fcdfa4b00e34a3a712558151f8942349c7b4c9c5cd2cc7d09b4ed7c4827827018c20233d66339ffe809a6641f8d347cfc36ea3d91e2eb755c6b457386dbc8d340437492e6ff7d64a6955ee624525a51f6a8b19c4d3ff2984f49a", "17d92918789f22fb7cdfe907770dc1982174f53cf1369456f9efceb082078254be17877dd6451adaba5817830843c87cc0772e23ff96dffc56203dc3491676a0c354a48bb64c12e4907ef112ba5d3bbd17215ee69d12ccd69feddfb33d9fc0c59bb1dfc38aded73506e37a3f6d8a615d7fc9f38c7b66c989cdb877f82889cbdd6e76d9f09772b1f4277a296601e8e8abddde7c8d2c05bf43d66c19c7c0058bad89d3763f4be9cdc3560dda514f78a35b8cc81f3458fcc9fb8a80eefbfbcf5ce339d56565de06b10d444cc5d5493191a88efcfedfa3508734661e6bc345ba077c788996235e24cd1ff99b63df702d31c32a7ff88ff471a501f5277b4b95b08ea70755f3949a3eb91c4affc4ace3117157ceb851d1dfce4f2172329b43808d8829fc7218997619e7b56bd25e6689800979b791c1090b02933d990df17706873423d08f90249580c31a808bc9993ef61d3869dc654f42decafa189d89a4552f6ffdea4dc4faddbbc9c4df1e20e67cead4f2e77e211df54bd97cd8f006bac7a0ee88c1a5fd2df3a9a5d556749eea9bc56bd9a0d4346f35797c1f330d402a163201c4611ca7ebfbc8eebf32398247fdeca0a5d7f3f5d249748ee6a95bbef032c14866ec96196b6309d271a80c43dce2de1e3228ded06f18f1c45d90d3678a8d9199f5cb02fc11c9984e2137adc8d5990c11563e08d42c5c02e83ba0f154da6dabf02ea70bf7a948492ce3350fd14159288ea832af64fb7b21ade8c98c6dd6e55de1c158a6288dafd072144261399efc42ae10827bbb024f99860170fe97ffb8fe95c98a0ab1dd3aebe79e0a10e7602b9f6ff8125adff949040a69d62c71ba8c2a3956dd65509990f8166d2abb81e22c3eda471f9bf931abbb6c0c3e911ccf851ed2313d1137c949c7f5588e1fa528e96ef868a8e2da05d4af08ff2824865688c8b22654c91fcb1976add636b6b63149fa5848c31660ace80128aca84af0161b539013376813b85e34b32a244619785920aa13d5a8f0b75360a33e2bcd7636cb11b48ea93eae4c0cc43834a92fe87c50a842f290d1bb3c14d212c85f867172523db36fca726c03fdb5397590452b53c601b76a6676dc8774e40d1127e493febe71310e907a0c7e2f45aecb01ed7545f789fb013630c25a7889f95acaa6ad3ef235fd31a11c0adbf2ae5b99a9c16d131a5ccc1ef1057637737d6b039e29f89439e7135141da1967460d2171d15bb44049cd46a1b6117481c2d2c5882025b4e9ee771eaf4e2eee2be4dd16eb58d24d12867d73a3492d16a61d0002295c0ad412bbecabe910a6c8aa107ce04719e43a4ab26e2301aac4a9b729047aaecd62ac6e77b64f23a23aa643e7567c580cf36d80d9fd1bb394cfb153c476d36ea011e02d23ed445c3e08621e073b1d6f3f5318026985e19af641c1af675775042209d03378bc5ee2", .None}, + {.Lcm, "-aa94d9cc0e70f1a32e73da8c60d66425a41d66a3675d53fa9cab4127c287e33461ba9be22ab74c400bfad48a106c267359ddf76d1ec597983b9f9bede89543bccb024843277e057dec6b84a23afc999a69ca84ec05c39762293115a109cd59efd8e71bcd12b7aad5b033a8a5f414ea4377b9138ca2213f0d7dbe2e7dd1c71f950be41dda1c0a5449730508f9de50eea37b2118e94f4076f8dc47a88ba04c4c16c06a171cff4e660caad46bccac439da5fc186a8c6250e58decbc0288961ef211ea5eb545dec13565e063d193e4e1ceea227896600872b81dbd7382f0848d5a2a9b75920c44d50b4785fb7660c4beaf750690d116b79bdd0189ce334038ce9d28f77592aae4aa1ef247641d16257b895a461f52c0e08e49398feb022c520c3ce925c6233c8769c7e215b192943619aef507b273b0b53877b9b2795aab38330c34dde5a2eebfca5088b9e1fa1fbd8d0daea78a257617d7b5ea10aa0f5aacd8807aa5f5dcd77f199c1075641ef9dd4c4c1d56b88e7ed5f320430ddd1f8d4d53bb5eb4d429bd110885b9e2bfb8ac81a3b1f7a34286e836e03202bbcd2bf0e0e8ec8f2aaa751255f7aa98d80ed2cdc90751bb86a47ce15fd8e57db6400b4c0956b0aee218960229836b8ec59693422bb2ef427ffda96c97cd4e32baaafd531964fed7ba8d1a4913882e6ec89eef12f55a07a6f94bad1c94dbed4d38b0be2df5e0d332", "42ca0cadb622e635a3c553634477d3a2ade793caf02ae5560c4c3a9ae55a7e360b313aa0c12665ddff7a4fc0e7012ada96cceb7e5ada8c7044220bc0df101395498ced5e421e4665fe1b2cf7b3b4d1049a4a706edffb82e4b4b5cf7e7ab4d6e4d8f1bf4084c6cff1641ee635ddb18edf4d6fba145678eda4c055cfa6f7da8c94d5456a0da5ef98f6cf7043b12ce3c1a199a204264eb68045d086192a7786788e3bb51a9d9188d4129a140383c6c45e958315334cbfd6666ed89dbf0b712bde3d126faea5b19d220448348fa615264de5691ff760211885e5beed7142f832ad2c0130954438d596c50d27c9ae8193046387faed70d3d756d103f4f663a3d7f2d0b246323cb74507e20483437ef6d92998b7efbbda8a6bec73c0e99a890d80d4a630d72ff88a501bd76970bdfe5004f31494bb141cd611906c3fec83496387123b31759f2dae8e32d6e6114fcaf3e92ce0f76a748fc50289df47aa4397916bee2850fdc683e899870e8f972175615dff7ff842bc75c8ea3888f1c7bc5fd0bdc59135988ab116199c7b86e17c4498a94a8be293d245329b6e499b61673cea097f078010d0ee794d179f3919be391ee4199d75c3a4ece78d12274406f203c7c65817eff75ee5bbc2e3988c4a3a726a46e1e35632c325d813205aef0b44cb39daad77fee0a63f8989c0533de17384b1a4fb52189f9c45f0a395c4f508d5957b29d2ba", "1640810698732b7fa1b02e80fb3bf58ca9ee53d91df41ebf91b94f5cced4d23542763018ab5b055691aa1ba4dba29b2d44769d06e58be9dc29b2d7601421d15746c867a3ce88eca89132fc4def658c39beaa2ca0dbdc6349658ca582be50cd4716d1771d1cdcf8784efbc02cf55ca1fe26384d18276272cd38fc1c600a221b02dc344c2c45b70305990a2eafc30bff7c2db98985c627c77947758b8bf522008a1c7378e0ef0555125beed3974353de59c5ddef6010332732df81d52a502c996fe3d4b2d4b30d837a1867947625a2dcf10132d607a96036b3daaaec701fdd596741acb941d4ed3cd785ee22bf42b98522ff0e9a7f71da291a10fed6b82b9aea19220beeb9f9f1d59e183f1b07aaaf7575102aea98611499679f3182b17cf459a1509b7a19bb6b3eb4bd1fdde67a7dc42cdaade4e6c9ae626e4ba9f67b4bfa38ea48e2285051ddf51cdbf747f403c8ca8ce6932eb4bd384838b448cf527cac488faeb82359a6623101037b31710ef907869d320e4d2e0257911e795f27891ea3f52fbbcafc629486a3fee0a548a7f812b1afa39de1b0b36051e8b0c56f24308d66df5a30d04a6a7714e7d33f7172a4329be0ce794062bdbc600496d19a4415fbdf7ba0c708c42edc3c918d7b5de12264c1a901e8d00b451b06bbad99eacb7f984174cffa62c891d8fc9198a5e46be8e1e1f18050adc971b7306146404d06d42811be7a07f509614ee001ff3f805a3e43b76746159646aba3ac7b7a438154f076bfc829e565f010fc63fb641ff10fcb43fd3ba7a6659753efbad9e62920835130c979dcc63bb232696f8b3c2d6c1fb5cc4c9c8013daa361d167ef9558f2f3b75fc8db67e4e5ab855ef30c0725832a1939236f0905f997f053c78e987c044ccd87b7d996e995eae7cc2557ca2c729f8033b08c206fc24a630c8d66ea6c9890f0011c84a3d76097b96a5605869af9d09a95fb3e9243b0a1816ea78d275d9b7cb9eac8a7c50f8cf9a82fd554cddcbc99847af21cca4132bd51951e6526a5ba5ec72e61ec65cfc51aa50eba2bf969cf3dacddc94155fb7be19f43e6cf509acb1d2d2e8ccec52d11e1b87051dfb23007cdace6508dc893fc7310a306079402641bc7000c18006564e0e870597c99ddac78894838dc5cff587e4c47082f7a39a5ebd7ca7858ff1fbb2010536126f38da67c9cc0ac9a56c3324b9ba04fd1e129efd41e14431d18e034218d1201e7b166c6848f6220c6108de65a98b5110238a842cd39f3237f504e3683d8b77a2d610497fb785f15e979c28d33006aa0b763791a776c6ae85e362153dc566ccf440444c6a8c879167f26cfe3461c5286fcdb449250569faa6ef485db19f7aaebde72b54ec56faef9e28ae3397fb1eec6c7e33f622b4ac12c3f96f6aaf62fa9d82d7a5132a9d9d119992b0c570d66ab062b0766d5f5cd3b2a", .None}, + {.Lcm, "a79d4a10e52e0c197295edb03c05824695a37b90a21dfd9d846dfff14d659bc1859528bc569e9e76b4762fa11c7e1c55a05068765c7df7b0898ff284bc6866556ed6e9036f2e82099b7a0e8890a76647161d90c206d8d720db3b93fed1ed8931435b418d56f872469308246cdfa084241cd43dd37d83a625119083ff8ed9991fbb81bd299cdbb752144ad10b97620181d669001249ebdc0987576c3845f712f1f4d5a0d21c58f795a730ae89e90da9438ba522ba8481b65a1f9cadb91b22cb572ad4fad0a296f785d38793aed498ff3526f2db02e7a4b6c8cf4f7e90e601665d3c2084cb4d6fbfad86828c0e1091567e79f64d1e37c50b1326ef7491d164eba00026b6971cc3887b528961992f8d51c0c14f3513cb104fbf8dac1cebfe3eb8aa3926a8da01cb366c72da389a41f44f1fb93ddc2788319b257f77240ef73f53679829d45593858fb03d1db8731ed66121f380929506ce98c279051eceb78c94cfe365209179e0f63cd13294e349c918e12f0b3de471d6d901d38125016f46b1442d2638cf2ae87a9a72a3e3ba5264c6c86b484f07dd0b17650da2545bbc6138dcb00d4965c6abc173e434ca45377eaf5699a10b0454c023d3a1f5a449dea34f817bc97d769257991fc877a65ac11590ce86fd3098552e8e25b1705caed94891baf649745dac716db0098ae0746d53ee6f4589461df3010bf8c223eb3427e62309", "-1fdd9b0251bb2b42d4b03e5dac0752a3a898ae32fdb64d146335fea0723b05200ab6a936cedeaa696aabc84f94330306e81b76c7caea3754f74fdca2bc8f53a621b06ab8fdb69e9e0401a800161d661460a83098a022e884c85df223ea6f7593aa43190448f4741747a7e9b3eb649288991f2c939efec5f85fe69cb156014a0c4c6bc490194c31e58feee83258e22a987b92eb618767046a2af14b3801315b1d26e89469fa07beccfdd604c4852ad3a81ae1f1716fab0e0adc7bdf4bbd821eeb400887c6b7fe8d69732527d0806459184fcccb925a7eaba119c0dc8d295d2a953edc59b1c69546a02c8c76bc3872fea2c062c746317a6fb80c16125eb117314cedaaf50b6da176c14ed68b886ad1f13730eb31052aa9464ba1a2e94007ece91e4d1b1887b4fa0fc8e588607a5cbc0734ee229540c8b748d7e2c9e291510864e10bebf762e3aa1a68b31a4352f249124ec5d0ae5e8a7a33bbc46f36d41e7c705369b7ef7fa34bfb50f10a88d8a1ebf1a2414b82f490b4b89e03e3bd8fd79c86268abdc7168d3dfd8f8d7d47b9784dd79805d1782962181a5160bb3f733e3473adc810aa3333ca1c1ec00445979b4ee176e70fb7058b71f8639d6dea429affa03ccc9ea9a8948c3064bf20db8551a4507bf3a227502646676bcbd2794af1fd254d4287e54d8a1c446c095386262ac784ce495c5b82dcde8a00ddfe5b65e87e2671", "14dd243ebcec8bc3d2a22369405bbe45a406a885fc2d398280f3727befa8fe005c4164b446e8c35e84277d3a8e0b749558af733968ba7703c2308e8f056b34eb7d905c7f965bfe452d5aa17c5fbc8e35b77ca3d817bdc2a4a8e18017d2421c3e093e298367e71bd5fa808482bf6301b876a3007580442b8c0f76f344ad5ee07ad546a92e6773427518776d778371fa8d92c3044ba7ca0d7a5c822d629c6c71064c047040bd2a90cbf7a40dc34b63fc8a2abc51045dac25ff5136849b788f3c3bcf5e2c759678eebac80ec24427adc3be8e45d10eed400926a6a9ed0f92c15e1088936430d44ccbaaa217270916ec9c1ab7d1d65ccf40edae5f35fb046b198ee1b70f9f10558c3bfda02f96cd5c1f2fb9142220c29bb6245682e2ade670a299fb1137e956637f8e8dcd7ac6138fc49f41e44ee9808452f26ee2b27ed01e83aef4404d0f0e4388601fcaf75bea207134abe1c438e8b64e26ba090183e20f32354a08bd6f399904b8a98447ba1c46c94983f5edd1bdac2c6936ea325416626bffcb30fa0aaec07e296721c2d9d49efeca61a73d8cc8a7cd387e1298ea760af6d569cd87fbfa3b2cb6b5a96dc316dd55980d4b2037d40faecde5ebda473b0a0e73eab3027ba5bb0a7959fe15cf5237f802bc4f68687acee0537ec4e01601f3cc037e2f2310dfdf7ddc190098d8f931d70bc24f00da4b5d85eaebe38aff47e893b5ec4520ada3ca9a54880113dd955fbc7446aaf98940fb613e7870094c700b7d4c947983123c3672de077bcd4daf59d5c3c770154877c8885ef851ed7580224a301f470ebd3f9475bcf8d939b2fa5c99cce2df1ef8f7e085d08217ec4786bbc28c1a0b92272e2987776711e1e309966cde07b2d313b50b49f7d09fd3b4912b631ef5e47ebef6d56520ed13b5bfcdbc358d144602eb6f8fb85f7ded3a6a88f61a577229de1d213d48cd459d47417913c903fb01b2d0d1ea9d92ab5098c9f6de3214be83fe2ae5e46ae810ab0b7f5c3d4e853a0f490ca51af0cf8adfaf5cd251ecaf0513f99e3c30c7c3a1c63e8beb0d5e27f685fd3b3f230a5e13e4e780870d900f0c60e9ca80f742a2e3c821ec1336e5d3afa6a92844a7cb1ee744077b9b01309a920f3c9fb21e6ceadda6dd5afbd7c651819b6b8204b33835db1d55c825993f939555bede10cd8d723bac21e61aeeafaac5940269533ce4b0635015c81bff457764afaeab37ab8682918553695a47b995ee5cd044b4b7e955e5f1c8519dd525dec79cf988a88c998788143cbb3d6a17a55ed4816e1ddaae78bf19fecc097e6a096d1827520ca5e77857eaf5239f543a523800f6db6d2ac6798ece9aec7c7c895f3a4402f9efcaff37cea1db9c97080627f91170d2cf7358f271c0c0b9c072b841829da3d4c1daf7390328227c628608cea6f7e83540ad46c2cc22c6c8842c36ccf9", .None}, + {.Lcm, "-92743df9c5be7b344cadbabbace4dc2cf464345c182c2a4277a085e9f44fdf776a091c2160a344d3ed22fba762c69d839e93e5cb7c30d9b983a9e05bc1bd66e544b936345eca035f2c05126d9ac170c9424122df83e3739ccdd50a8ae4973a39343057e705e548c27f8be875c9b071933d8976b5aea088425cf6cdd77e95056e439de66278e85aa1c631a15c3246d04cad35a9f0de3bcf56e51a9ad9be723c46d720032ee01a9458f48c37110c1055a09c126c59b98f1b7b9cd04233582dfa4e76d38f25660adca1c6f0d5cef1ca0c3e8045bc338324d117498023ef4bc815beeab0b1d5c5b1eb539334ad5e1a212a3ce1263791bee619987f575231f6f06605c6f939d9db7932c22b6537f608fc91ad0eb34f426ba0540774e101f14714e9f2c1c09dcf7008997829469e6f3c271169b58c4c197714ef3c3d5708536c22200a4f371ea589fd5278a800b16e1a480f7f13f20f1cee8cbe9b8e598a5a8faf4157441959cfcf89c9daaa0fe60f35bf00f52c6c4f9ca093aae901a53e4059ea004124031148b5d67be05d3b224d8696fc908358d1bc4656c1e76fe3d64fd1de689dc567af0de1ba46199cdccec96e7a197ef5b4166472d8c658ef41cb144d081226e6ded932f6aa76de9769bbd8b929f6362d5a31c0559741e7bfae4e38f1a1c172de0dc94f4f28b4baced6c8bd3d23b1a5701eec4fe9a660bb57003d0102a83018", "219dfa8513ce62b99998ea3ca3b3f7b295efb721a3268ef6edad2dd140de6b2ed23bc49279ac361c79f5c1259f964fbef47c3def2c4f927c1495bd2fab3158eadbbdb46d57c28327f9fe65adb51ef097ab31f5a22c0f970835f16047b113a5f52f74a55ff1c70c573cf4880f0ee53c4a7d23f84cf55f2bd7d0116d782e24d9a5b2e1a41d1e551d661b83bd9c53445e2871213f65c680cc9246912131acf2c3ce8a8436f61598730385a3c42a99b3f9107649b665b9b984cbb191f17a300c0214e1028eeea3fc9554f909cb442ebf679348c95bfbc975f34a9d69958a60273f056091cb873e2f61ddae90f96907cad426ff0d18f845de7ede588046f5e6b1628e14ab9e0fa4bad1c905a7cdc2e6c89a933cff0f21485809fa2f4f1e662218a6b0fcf86bfd164cbe529ee229673ed234f6972b2c68b0d2c7b21c493189ac4d6aa5c4f4a53a4ea6c9d7a0dcc604d14ccce5f9a9d09f96c2e3e7b805ad2fd7dce86dda3a7780001db95ceef3a8b9537432df7d2e9fa532a4818dcd33ff698f6341ed0082f8cdeb3232d2bc9699e3c9ee7272d8d224533d9ffaabd6291e0d62eac836bed91cbf4ddae3bbe2e1c34b36ca5047d78f535f3910ad819f9dd6a29b443770c67f2df7cacbe74a60df6162bbf8aee5cb7307568913791eb05e1d09b07d11bb0c90f0b9120733d093d706261ed6afa36f06763b3ffd8fbcb859664bf56bf96", "99dae4c6d75521891c00f2d08cfc42d67fb3a0bfd46a22e4265ad63a4115ad010af9cd3ee8ac2263faa313cd96af60be316fdc6a2369203d50a00fb6576ed7cfbc535b562bc9b9337eb884d47dd8b7e4d04f1ff8ebeb0a80b26d3aac86eea7b3913783843198653cbb1e54291be79ccf5e6ede7be21c593ae03e676cb8561644844809fde03f15f77631285e4f9b13599ea7ffb8f6051a4d0d29a948fa5f267075ec5a3c0ebf61f712bff88525adadd383713b12009be9cf440c304fee777b004c74726b4fb5e7cf24d968248fb5405952d98811a454e423735436bbb02584dbb67858af2ddb826a319e21924e02a70ed1992fbe3f6e3a6a7d7b58e645fbbbd437618b96ce74a95f528226ac5d643c7579f7d06204b8e437d687c470cc77d5592d8e7a680e41bf797084295da0194bff5840f66c9f7e1acff887240282df005f0cd0b3e0bc7bfad7d504a0151a44ce6a5443291747d345d97920997d2af1516377bdbfbaefb9493a0455581e352c21cdce148e672a9d1e8615f454e5a676694d8b613c374dee6be63bb09df7ef62d54a9f55dfe07cbaf0af2a8a9af6f4229308f931d6549948715a3bfb4b336d31cc48638d4ce3c005fb245ae2d06b72018265d8dcde1bba93448f18043cbfcc29b824f3d89d5d9466fe03d83a534ed1bcc14859fbe8888e072163897ba475f748bd4625eee02ce676775c2daff20bc5b431cb3e71013ea4b714304199e5769c206dcdacd6ff86e4f5dc5cb766e0a9a429fa2ae957d07a2e8753cbe5e649632a74de32ec68de0bfdcc7b1da92eddcf5c8477eb9c5165f5e95a368a9bf69142f0e8a52039c5bbc74a30b17a8e813ef040514e7bde870dda48f865a9fa6c713309cd1e8a9f42ac9fb7e4610d1ba73c21768ed5b13714815740e2607dc7888ef169e20644fb3dae6aaf7e25441a3b7405919dc163b4f4e4425650a7b08d1816240dee90bf6b7c1fdf744b31a5ea6edeec54e7794624747c01a7db70ef613ccbe66de96b9d765dbc0ebe8f8064b7e66462b886af0a1d1c7cd04785e45d036c5576f3c827711763df2444b3998c0e38f36e29494fb81aac7d3834951ea553a06098378d8c899eb5a37121d5b1e86ea17fa2c4b4f4d66e63947c4752ed8cfd213adb4d8b2740e189392478e2d2c8ed0286d997062d709df88be03ee5d35b64e4a5b3c5485fce13c8c0a26f15830b23ea4954fd30f7f77f651eb7affe59c7a2ce139649297ce5bda04a61b15e694a79c81afee875351d9427a5c5093727bb752d3d692d0ec6fd3b77a20e0b65d1873de5b62c4bf12e82ce26aa173eb8cb0eff674921fea07f689014bf4b6bc56f1ec614f7f0d44aa8a483ac018146d2e44a5b877f3a869a71cde0fde66bd5536d1bc5c24efb8f68bf9caa957d8d90afabfa99e1b4375da92015066945102e372300a95caa8d3f0b08", .None}, + {.Lcm, "-fb086b224072dbee9018d452a0c443de9c3f65de9bd892fff693c2caa5821ea7cc729ef04b19070cb2ce56ecb2a74f77b0122e88cfd399a97417c56bcc82369e6c461ff9a69ef10d82f9ada886887a9c640b601f7931d212585928bb6e3960b5fd0c09b83420bd29780cbee21dadb247f2f37530b649e370740c838e2dab7ee6140037adaa85c28f3b3fb5bc347be0b4624bf2024c0a0f9efb7d63c3437093e2898d8c6b1a761dc5c06241d6e83b8d21a09efc389e6b74d7014f335822004c35b9ce0282a2683a5894978f06a35625d513b3befa5304ac67bc486d304adfc8ed1c6229bb9121d922416897f245ff9655a76b6028a75014cb777951693fc84894271da5c1c285b775f23c0d46ae522b8be038dcb7b6e332478f960d3a3c097ef82fac6afa5f7408fe75464ead8233323367a44769f9e326f95b12adf1e20389da16a96bab8c5fb22a228ef9c2f00a16cbdf263c8bd70df5b11412330a9df4e59884d5320c3e8103df2036ba1d9c69025f1f0c37ab5c92758a0dad28d53eb6f90db83c537b787c4ab22d3e07c98ee6b8584fc887ab05e51c78fe42fffcd202518083de186a2c2e6916d5933b3b43430320a1ac5976200058b754cdb39adc0d910351599af71a01ab59702974cb4a0c28fb0c8e3b2c548851fee833e566f870240d89d1cc1c95348fe81c2b053cbf176e1f20719e63831d5f84d022abdb4f5b0a67", "74f8d52e7178d68e395c81b358087e28f02c86f9a9ad675575ca32c6f0fbfbf213329994d3962038dd3dfd9947e1d5a56f4e05fb463321026a82fe526684fe2e991cc70c0bc09b6879cd3fb3831eb46f3e1e16718a2a8a0f1947b2745faec7441d2bf59ac4da28f9a48b8c138820cc64c294b05aecfd0adef288f9265c58f2bf7f7e83f2e793599f8a05785f6384caae78b7a2385dad06fc19905c6d7d65e53fba9301241a1e007f43a394a9e7cd35783ed16a545a3f47a0781fce775e7ba2338f1a0f09b87a7bbe67a03a57a2f36af602f82c3df427bf34948176ee2435a281c897a5b85c7e1918add49e0ebcf39952bf78261278ada910eea3f2d7808c59335eef92b8f5f3db4365dd729f9cf4930d2284a880b9dfd5ee811f51c6d17736ab10b2a6ac1a05f8272dc3f70bc94f97e6473392ea57f9872b5c6304162e7f99f87c095b56416290a387440951a8226e1915a1b046111cb44494ec34192b2eee9bd81484f0ccce36d90f8ffd8c3c684facbacfd0c28c0896f93b4ed96caec52de60f7a8e904b7fda527a81a5b9c329c1bdb7392be3596e8ecfce9d6736fbff6aec558bdf3fc6daacc1edc31dd1e283b0c7c6edd5955a4ee50342ab4cf1c02b3a57028b47a0c7454c5cebc0ad2400960258f9944d96d52e40ef53d1dc5c143b737fbc43eaf8b6695972e97c664a770ac88afd215990cb6b62ec4e9e614581528651", "72b3d1beda4e7055250268e112dca01cfee24ce1e55278f8c4dc5f5fa445c2d4ff6b2934e4456ce24878f0f8e45c21cdeb79c00625a5d797ae3c2d0f89301763f5cf7808cb5ab12e0e55c2405f3b5665ea6b29ec3c198ba67d24d2ece7eef1a7a3e9e4b2d4be8e098dff64b8b220d6ff02b4b6dfe72c21e02f55f5e8d7c16de77f23aba3b473475f168fa7b0e73280b16d5bee76305792b55787f0bce686d4cdb7519d32c3f920621ffc0b44dea00a7959cff0b594eef2b2e326b03bc4b79b3ec3ce781ee466f8454ed541b1690ca4e1714bd844a65a690207e087b2e1005d17b63671082798573c081e18b2a065dd12139a8c7dcf741fe9b0d6d9fd56d96dd30c3956df65ab59cb2069254054dd8c8acf47462cd7108eb5e4671d1f22ba5dab69d55676e7fb504b49e08cae345dbc009aba05a9760a9da3ffa2368df40846c5c778665502f84548b54306eaffbb0b534bb2dcdbe48a39b3607619471b627cad8fdfcc269f5224c8090e80b916d03a9a07669bcb4c1d63f97e2f711d093125aaf024f54d5d83c5ebf493b18b8b618b6a497514d5865b6ca6c3eddfcb3157addb4c8fe97801a054abb342fcc83894312cdb63b91df5291598a493e0fdadc1a89b3cafc85cecee509e11d2dca9e4a16e14bd94437b999e59d325e70575091688970699dfa5f25bf633118c9ce7f6c2d14fa33278d50cb62658935d30e5d918c7612e104844e705c0dcb379e5c8384944830a8d1d05861ff693981e61362873e068dcd761da2587d27f8f162ff92849b20bdaf858f7567791a6ac38aa4125cef289729081e822a6939f1cfff10d5e3451ee867da9ce1b77108ea9301e7e68ac86c65f8c534ff67b1a5e9e407d23661c579494118bfb9ad87d13f8fc591c02a7f4092ff14e6cc6739e30e5d281c3d3eea5790981c1640b2edf244be412d993749fe27a782bab82c0f1cbc51b8a12a32403324659d482811dc52957c1ecdea9092b08f1909d78e6787b4587fe41191a8a77fc73bd7e8954beed963772791a54d957493769b5df494999ccfe83bd56db10b2b3f0e6d302d43a03f98c8ca920bbf65257a56016f4b069a27bf6b02e20ddc3c47105f0f0d79f07b63a9ffd1fb83fa73dd5790f3926d190f6914560c42967f2b8fd51d3edc35bd5a69fea187428a9019226f209d1e48452680f3f193d7988c82cdf984f440a3991b1136bb53fd93b20adefe5dc31e971de6179320e27834c99f9666d0d7c43004530afe19e3a2a528ee1b887ae4296e39f6a3a839f1afe94a3040852b2de46e7952462f4e9a90e89d5d909721ce7a0b97aae4776e517a73a5a8dde855fa28f3e2db09270eba624f451a7ad5ec04e6849ef196d39f03fcbb31fcf506ba914d154011fda11c26c70acd4bc2c4f92e4092c6b3e3a8a7c3b051fc0a124cfbe7fdf89ac092a40364c17ff3e3497", .None}, + {.Lcm, "dd7fe00aa171dc25117457e2a46654fc40abd131696f2685406eb8f5a5153383fe0b3a6513ce2fb13159a5e1b56a55466cf28bb5add04d53134f112c9a09e41e4076744cd71afa507e635d4f9af9b8403e3bf4a2ed30168e0172a798c66b0fe25ee05de2a4267cf2c693568d23e522ce76d117d65bdbf8533dd76eb0460eadea6546144d525469d279f45f9c05eebe89ffa2adee7c90c91c8ea767d897374233c58aaa33983703d665a7b0038f5446e31249729ffdf05969fa3410c53764eb32d776300d0211b715ec8a84c064787395b362ea7084441855533e57d58ecb5ec31d317587e6165ee7fb043c99f26f0077bbd1fd0a7a557c7220c6e51d6285981fbb5ca4554d2ae8c248d6bc09beb3f2d4110628920e6cbc944f3d0c8583e689d247fdb6fba79791b4fca655b28e262d0f1d4e645ebf199cb8e4eddf1278a40cac39214e4e42c53b20aa1c24be38b041fcf99ffbb9929eae1a75a39888bfdff702de03de433f4e2e07854b25ede36f33547208b4f090fc9ed0862a2a37c870283b89ebf497268ad951720da74dbf3f998b53239e18e14da5f15d3db41be72505cde9040a2853572685122c31526d140fe8563eef1529f8232ff5eae0e798334fd0ab3ec103585fd70b9d33de0583824320c2993611d874ca2cd8d377058ca082981fe6723c6b391abc51804d174c36fd5b377783d504c5af097a5dfb82ed7fab70", "b8567e7e7ac38f0c53440d932b2f140f6ecf472c678a625c3a519ee3d520046864bf12f46c76a1631b46d0f68220cc2cb8a007b66b01fc7cd5e2dab0707674eed2c47066e900f6c5ae9896df50328edd67d63aad6d3a3df2855e11d3d3a843f257d99867b59d291156c39986b852c8ad196f19603d633b8de3a2e187493ac0578d894067eb3732a2df9e0a3282243eeb1ce350a87dc110beab196fbf4d4ec343d9057b85930f9935f771e8dff2c66fab553b25112453c14a3dfcf9699dc2040151caab0fb9dffd7fcf2b3664d0690f3d654fd1c20a7700857071e46a2715bfdd6f44d7140ede7c291a79fbe90a9253f0eab3fb33b0993e06d0b3f6f6e80ebb451792b83675a126b6627da32d95afaeda76b18ba4924b1d1a3bea24b205c8a3719946609ee19b334fbc08b034a2dcd2a51a4cc3850dd945508fb8ea6a0e3b015100344a36a4ea5ee147a588b7a7299e3b7b61c37aff2c77e76b2388f35e76688fd20be56bc606f6baca546ac7a343f4effa8114850eb8d4abd3b8cd10924787a52da9dc6c1048b947d794ce75d323ba3f0053ecc7e0dde26bfb0064004e1ac3a5be2a8445ee5a4c85c8567669f1f332a03c8412768763a7ea76674623b8c2bd12e57901545415a6e4d02273287f98aafd1470ba3f49cae0b773198d459a379e042320f317c82cd07831f2f7c82f4731c229f09e346f02cc3b7993fc79bc00113b", "9f7ebf6f4709b81dea9d19c296048d4e23f494e75f3118158d746bc514856759ffc1ae20ec326e796d7742c4f0f3425fa4b614582e8f4a704da576f70268d0c460d7ecc59f286764b6a43ff9c44d80b5a3efd20f7c48b786993764d4103bc561922bbb877791a5af5a9e0bf730a4c7ca9558cdd3b26e8a28efacf4bfc5432525312fd20df790897325cf9cf7baadc1373e8fcad9c09aaa256254019d575a31217c84e98dd4616d1c7f83399044725034491455dee7a619bd15ee8f66878346130754d59d709574e4821100d891d2f4535e2582b4d1081329b00389ca2ba4fdf4031c9061e237d390b1643fdce1bdd2bb6592b0461bcb125fb05efbb3701abb2a3fe9aa5544dcb207060b18e2c985b1d411d845e17a9704e5b7db215ac8314b7a5b29c891692de37e5014efb06c4b5a31bbf2c1ef3065bf4865da5d0635c9b5ab8ca5a246f7a7f6627daabed81bcb98875489093215c105b7b880f8df16d7aaf72401f24688db3485c906d5d9e31a67bb715f91a18d4b9dce489423c1bea89855afaa50820ef93a31ff1d403c0aa818d893d0ac4fbc2fd1bae0f20b9cf5b5981f1c4e967497108dbd00793f6a3a0361c61f870893aaa88c50ed955f99a3d53021c17d58db4049bd867f514c8e014f7827ac000daeb5f8844bdd4f20151e2ba1a839a701bc5ab287b9724955da9ac55046d6c10a28adc977c404e2437a5adc726e1d2f5e12eeacaef156067f4e849f1cec5831a9ce7b815966049fd738e8ea4d7c12a9fb48d00b3da0543b8b0bca01bd817b76e58ac43a2b5d1311acd2638da6c9063894d6b0f57f578e9262775766e7ad41508fd7ca07b43f29ad2ca950fdcbf20b6b2827cf563a5a30928c73428eae4f05359f3563e91196b4d3e773f2965581099a6eeeea6f09852961cbd0de5c5d58b75b011e48354155a40af9917aaf3910dac6573025d8e6fb4635e27fe21c21b87aa5fb16d7128da7ca139b622d18f6bbbadd680931fb0ea18ef9ddbae75a1b9b073def3a6397a5e0bd4a20d335e603d1000b31818267c0a4ccda56b271067e77d304255a92376414a22bdaad07cf81c355ec79472cf32a35ed5d4aafeb34442d81eeaa7fb541c9c8249139cdfd8f27d844be50fc78f6abaa19e3afa13f2382bb050185856f291b582f1920dbe443a0d45d0be99d28880c707f613c8d04be9672e69c23b3669877ad5e27011abb38379407ae932e01093ea202169c8da7e2d38e86c538a0ff1834b81edfe0dcf992e7971e053ec0f5062b2df7965b885a544dbc16052a041248b54a74731d0bbeb68269255487e0f01048f833c0e21970d4c8db2402cc745655a3174b7bc099038cbd1cb81e3add6dabd093a4f2d4b75c4741d05747691164e774e6da08e6b4a04befa261b1ce5f694582f7e8f29a60b4f858d485a5e93f38663ad6e730b2c876cef2d0", .None}, + {.Lcm, "bb89286186871760f0dbc9a105854ad646b3b5a2f7e6bd93e2a60110cfa7bf831e99d4ce8bceef25cbd139c7df5dca4d49808dc35251bb5eb09fe8a7783525e0ce97429d504b577a5115330f01b7590985ba75fcc38bbc0142eb853354b0c6dea8ea88c874a9aca16b6c13ec7b64c59b0d256b5397d1ddb3cc6f323ba8fdd683656357246d1ab938d4c329b000728d850ec498cb5a87c9eecac619b89ee42a571414d7b505ba4a6a7a668e4df998a758b57dbde5b7ee2287161851b129cfd9b5ef5f9ee424f9613b4abd9f36b08e57fc7f8c9e402ba3be89394f60419b724579c48ce1cfc6b8ca487c673081a3d9e4a30acb734aa3dcbec8ce4dba6c2500b91ba5c8e08dcbe87302b53921bd9b874d6940b70f5c3747b75b2f57e79ca3efbc24b7a85719c0ee173e0109ea33a5e0ee3b5e5a2d16c933f56e2ce5349a9229819a7785d8e6aa1e8b29a5d3ceb079be33d5f8dca255b94b3c98b31df74396154867ff1d3a292b3a8c89afbab0779218a6ee906ecf50a539cfa311678e04c3c3c33c37e2797f5cef05e4d338a5339871d3ae7ef27b52a94a9fb2f83f3ebfa8be48a967392221aa8005d66f917bcd1a65fd02bca5c0ba75d2cc574153dd2bb14666adcb033b47f5502d882e9ed8ca05f1367e90671412eb8d30bc8ceaa77c624697262823fa591030ce8f0c1a8269901749f2aea731a2b0b91850a22fce403c8dc4f6", "ed9cd02ca502d5136230e41df5ff95c91fd3e1f5afc602d712ff3fcc47e82ec749bfcbf44e4813216820137380f3d388bb852fa3c82cddd2305080b3e00e23ae3737301dc10c595658545eadac2b38254bfa654ffbdb15fb87ded93a44ce45a4e4b17e2ab5d27283582934a7a9bc1636ce6142e10c5ae1d8a039d1ef0a9d809b619bcac82d73805d417de52b7adaebf0cb3a9a7a08eee2c2f185b960b7c31813e0e27427a72ce574ca7c5ee2a8f43f4d8eaf93b8b02c332c9d1d418865dc73a3707aeca36f071cc9d94b5d4bc0d0645724d39120334a65e42f1288764a06867efc0ea558c73db593cb40362cefecc79b6d18a2dc235c1a582600336231d6446bcc777eb81b5dab17b7089ae2e026d48356a342dd6e26d4e5dd1d5522b14ba8c2d1c2a662e7b4221f6a25aa36f12eeb1296a0b805c57779979c94170a18a0b049c65753443b89bb04462550308149b9a117f792a7c72791baaf971eedc80ed454e0cc333c1b6e0e7550aacff02571a7099a699d49f34592a992cfd20c9f127d007cb3db791020acbcc631e43a64e901bcb0ea568d07690dd9102922cec5a39124b284b1221ec1855f4750cb889a9a9f8322cd10c3af7fea700781ee823447ba0b8875a8c862e25b70c5a52f2ba30e642b4e96f319ac9f55d25de85f7a2465e2737e063e6e755c731c962f68a5035a97e0c0958bf1212d3e9444317fce2509d21", "ae10da770a3cb3385e729d88f8ce0d131a8a2dee25664c42237625397f9ae4c786338336777f5b3fa501cbe1757bf9f0237bcf188aa5e8c9039b0094e9f93a2f8674675f4c2ee31d03e008e1689be00761e313cdc6bb618df9033f06d7f8abe7a3bf92d0b1fc365c1aae76da71f13def609f270bdef31e57cb01129a6fd76fcb00d692a10ab47e69f89da27de12d742814c1d8670d2a2f16c12628263277f928732614c958d061bcd4fecf63aa4895a143f5be18f63c4d510ef9bd5c3d7c63029a46cf6d6995139cf82e677b7daecdc8bdbf377231fcdc3fe63e055655a0d08ffe7594585907a1103a950b8ba5de6f5b34682bd487b17c667065bbe3098e236d84252f4f78b3b788a97f82444a0e253e56ca082dca05ba8bd4f012a2710022cbf69fe58c193a9ed72db35fdf9392e98d83b3f7f9fb724004a7e36fb537e38b8e6bf6cbf7acf89c34b5fe5016a2f4dbd36588be4531ce852b9a4ad23a45fc80219e653c3059356bc4c641a8a09b89d1195be5a6fbeb20490f957939706d3971ff1ba8f89901fd0a45bb86f5bac357dd7947a0375968259ffaec51684444e7e876364b726130857bf60b36b7e64cabf00f61723036fa5e8b7b255f7ff61b93243beebf5b3eaf00a13011bc4fd8095e44c07624732e5fece7a342ac878d4d853a86a42aa10f89c1eaaa3ab8a81d9205e41258b6ac28f93c6033f4afcfff45a32f3696d1526c686e4199b20ebe3a069021790b087742f40c814b8952116e002494668d3f8b8c79c5e54d630822796703e8c3fea4a7de919be84b7460cb985199bf7aa167b3679555a86d3eddfa72958e12edee7c0fe545ee1d0090cc8cf4b04898f708af58b9615e114258f3ad79692372508c8312b1fde3e445022c4c2dbe3cb4d2501bfdbca226e0f146ff3cfd911302d21fc18239921bee566a3a0c042aa5aa6a1a35650534f6c5ef11752e3aa7a74dc2c4a706ef47744b9c88e563d3b357c925853ef7c0e885099c7de4ad9fd43fa174ec72052b0cad8b983047cbabb06ce1b9d503d133bd371ac1f75e6598b38b2cec96b8d1247b650097944cc5b06d344889449461f23e3f361c1c92d25ca248a1fe27958da45bc420df182f0fc38b70f38d47a865adc416630bdf2a0893804a954a9dfef71a2dc4ea5e01e9b186c153a09548c5c4300d8661128b12c56e6ab6f6e54a1da2e18d25ef2be6528136d65ac62057553c66c103da6f793aa4f553aa9db5c7737ccd7af0e242b8b5f758f95587ece2fec2d1d72421ddb8fd7af39c856a1c6d92354fe345f70eb270492565feadb164e4c26f51e0bb9de0bdb062e63f6f06313a7136b496a6f3d81e66e70b62537965c86d2d358e6c676d381eb5c6558d187d26c1e81b428ff99fd24ced6da8522b1ca7adf67eb8ca6e6adb0e0e3e9df5af6d388a22d4dccdf9fd10bc178f141b6", .None}, + {.Lcm, "-c0cefeddca41c426cabbd99229db3c7e6d15a10473a146f1d6ee6bfa309ef650e0281045d5cf00d203107174062ed41e6f0da96a7c2f5d3ff1efc9a62680408da279645d9dae8988c14e7a3c82812b4563660c05b224b08080a54c9b85c3df56768bad3b4a3baf483880bee624f72d8f2057e1c226f8300397a771f0f7a247fe0e85d94e083dab9314bd81612a0c0722346d0d750578285bf9d3d3c3755331c8e2b43e527121edbf6c40f48dd88d70a4a874046ff37e6a0b910c35f6d24e3f26720370ad7f1e4538403869ded54df0e28426cdf09296d61f3d83ad821c003f4f759bb4edde2b587cdb10ddc83f772fe15f3812cc7cb0f46f363472709748ac15ecd47a2a111e82373e223c430b527f74ef15b0d7a53cf3a0f9e1eb3c625b096cebdb6c7d5aa067c555d30cf35b8913086278537063cad708c0ac598bdf086fa50d667313b09df775ba1037b08e0e81a136772109d35627d02522b303a27834bd8eb9716cbf8775c60142e072bfd786ce296117d5a2f098dab3b749ddd4bc8cda770679ed596207b64cff2d1a31b8369df8caac34dcc8a4abefc53b4a9824f75578c386f30b3f2aaf09c1cb10a4b145d78ed60a95f2a5da8c3d00fbb19a298281e75626945f8b4967891fbad4b2526b369e04b22840451f41b7d12d3c1363646019d4c4828b87fbd4de2a00be04dac83af45a197537d50fe65639c245fcd0a91", "-19dc2a2a1094d03f23342c765b6afe8ebcdfa4e94c53194aa3bacc525ac5136340f33f0a97fcb10c5c302cee3a0eff5f1b5fc644b021a56ffda7edfcc37a8208d7af0d60b5896e5990e56d93797505d27a94c7df8b1921cdfb35494c9ef83c49d626381a0d773ffba88ae4621af54304e14868dda9ffbf12d563958b1505de3313ea2658a95cea576ec86a1e834c62851689fa2e501bb86a1e238c982e40c456af0b32be06ee3a8ab6425e8dfb9a4cbbb49f0c1f4ca1bf872dca90b49c7b720df46f3946460ee6b87f1eca01f4b30e3a2ebce7ae63aeaade5ca634c60a33b017974c11b57050840715201c161b797f2c0f94a4b2a853f034b0c91bb8c3ad7d9538eefb42c3458a630a70654073653e431d83bfae438465c81bad34c344e4ba238cb2d0b123b8736863fa0a6612fca6cb4d627fca9ae10e9bca7fc118be559c1874c24d01231d430da4032b42a35d119b8b014f8e7caa9e5c9381be23b2e61d9257569b38fa0a9c67f6b501d85d73b19112390647c3ddb14621406e817457e178beecf752fa54bf18138b1507779e6b847383a9ca44dc74fdaa8e7b1da874a4741123b3a2bafd9c95754073da088e8ac0df95e1cf0751292bb47d003aa1a3365a421f928f68c0c3eacd6b9d5ed024da8a551faa461563c482d53a2472928a8b98c991d9ec7ddbd2dbea5e2967ae8419e54408ca144dd9b5670458178031e4cf9f", "137a0888539d74af4580ace12ca3a0d3899dac6d209ac24ab49105fc5d4f107e9be9bfac7ca17400f12c626021a4edcc1c922d545570da17e0ed5d123cb60571b628ebb5b847085e09f5f5c08c1239d79e6b45ef2294c9e0168742e1a0d6a9c60cc2c4804d7b36be1d9d8d130ecd11a8dc697aa28b18ccfec58a4f3d777bfaa93ff0e3af01aecff417b364e7284080effb6ee0b61bb67c6ff8a754a537721df2bbea0eb82ec1d63b847e90c1ef9ff3d470c7f74ebed1504c104798605403161eda0b929abe62b0bc0dece6076fc35e31afd13ed80c39234a2123585c9767777d47297b6b623161f3482670d03933713d5b404782a342d9b6991ba313a6d67bfa35061e7531c87e6e8f099571ac7c97910073ba69a2b280c5adaa1e26c0264bcfc35a0249990519c707a1cd8cd3ce92dca5b04ac940789db0201709c4d705da115f59860a927a5dd5a00ce197232e7e85cf8aa69c0f269d52a9c574c5e547fa199d269b96d319e7d6954be2d5e57db7796a931beb4ff5d118aa3828faa64ef2fbbb33c5ff9b783d53b8779b5d577510b4f6f517cabbcc4055ef33347c90ef5d2092e7ebc2267d481ca1140092072167e8c225f65ac1d2b67a59df93b2b5d95260022c882f979da7258cb64dc6c5c934a73517319eadc17df4029018da84add22274fc2a4221cde300e3501186af4727a365754a7a0714c6624f22814ed78363e7a990ca5bb8f82ae434db63739881128ca229142a1a35210da440b1c5bf77bf57055faf2a284f0a1736054e66b94cc02c5699ef9a57bfe0a1425c36afae601527561e9e93794e8f1e8853441b3c69a0363068674beaddf337bbdcb966619fa9667e7f32eadf9c3f5b5e33862c65426410c9f31f0b7f44e7a777b0d2e031822322fab5bafcadf089bb7f77593886f8020d54031a07164b89239b4b84c95be12291c6c97e7cf59da0dc06971cc711872087b9312a953c654e7bccfd2a806fe2884740ce131a4fee496bbe326e1ecf7d6155d61999cd90cd705aec506e336f3a0d7bb85fef3ac10ae0d2a4fb561f87cde2035a429ab6deeb264ab32e4d7b0928275836c1024b04d5c7128a25ba14e5780bbe6d272b61a7f1b53a6c974f30bbb0ed16d1e10daaf62b5b973b1134283c6536195663943c93ac904b6a25e1f2d785a220d92518ed7c82e2ae875ab3bbc9df5474f9eb5c80bbe16d1851a71cc300f4c9b95c29f29e6fbebe015600b8f5c820bd4146ae10aad55fd3bb16febbc3e0a8e46d8de04a0428221e88e6db05efec4ffaa358a67045f76d542ba36b1439fa82c6b594e6319a5607a1cc466039c74af5516b4d332a086ce6f1fc10a2e4c2836a5709131afb400cfcbb0073474a9bc87efda5c54a8dd5101af3d8669dc62391a04bf2ad0705ec94e061922e7b119ecd46ec280a47d46fc039e5ec32b45317608cf0f", .None}, + {.Lcm, "320efaf1bb295d2b9d25b57d023c4f3381e7ea94c1f9128b798110b7ea2c89807acdec387c84155fcf018b46358f4b8b9b4bdffc718140e87abea6a8ca039c2ac4d806b52aa1513c64b51dce11dc6b31e58a4ffc1eca030e84e5ec2dc1d87c5f9504bd4adce15b58d1b93e5c720b876054f776998868f256d620f722921c1b26db88a8054de75c8b0c1aa7e4e81cfe06853490b67e9b22f34293d647189201e84a6c9b222b0677334059757c656232ae5409939848633af4c5c4923a432a90f782da3dd7fd86b6ad06429bdc1ea939699d9d1a0fc0810bbdade9b907b2f7fef26c055bf83bd88c41c3afc0063d562f53c90cc129489776bc849cc3940f9474b90590ef1ca5be41ea0d51e279026c6f51a7a8241678e6eeb16a3086f30a551829c4125ea9f8d691c99428d54b5e15060549fec60c45a8ab4baca3378b4550d9cd3f23ccf131ce942ef24669d3352bdfe7a6507a4e5b2f3dfe99840c0a4a869e0c16c05f62802edffcce38a0c317545a138e5d314c2d98e407ce434a4b8a64194af0749c12e749bdd8b9b64bb20f3e4a8a58bd66bcbce00022161b3c28c600960c44d770baba083f1c73fe1609b4de6b144ccdfbc6d34828cb9fe951fa7d60a9fd367732565e4050d051fa98a6177738c4449e6efec9ad3d7471b3b4033abaa0a45f55f1624592e7d91eb3c128f8fc517e870438b0653b4a21a932bdc2b5187377", "233b9ad4effcce0be5d79f3a39ff9d934c713560ad58ef43a1a8bda8ca61db6b0c38eab368d9cb94c8285076a4ed94065621135fa28c651bf86da15d52eec9248bb9ee8785ec2109edaa8cb8b1ade175b73a9e23e55e4f6e659f94c5808738f5b5fa642a219f846104bdaf273a79709c607a4c565c8125562734981f725b563b1d61abf496416b09848889d917d2c13d8b4eda032677c1da52183d58195b680e7f1b6bb137ecb1fc25409c60cb86bbc3fb3732d84a1dc15c3eee5ec18ff1421a26dae68bc21338f052a8951ab91628351b91e6ee3ddde98fba88ba1c9c3e746eccc00ab928a9cde43a5c770fa1d85f8f2506763b5b5dcc9ed43569d298df7f35f02bb00c62506097d9f0a2849b28416af91e8a69d12f948c7006499846de67e927dfd68b852abbec456176d062aaec7db3f405f0a6b9f078f70adae51a875c180e12edfd17481b345aedce0f3852c0df358d1314f839cb22bb48ad32ebe2eab87978ce1847f65985ccda9bf2b3f61c5bd828fb0c2707298862d3e7986dc9dcb1862c3e3ec39fe2198dec8e0b67c4bcf258cffb1b6df4a069a7b1ea01cd18836e19e2068646315180fb1edfd0bdc93c9aec4dd4a08d999eae471d5515cb3f0a8983d6779fda708e2ebff8111f95b76a2d0188487f585ad17b1afcf4ebe41ed3bac6d501060dfc5056a4b9c67f817ead686a85a94c5bbf5d8d24a5cf3abe8ae8ba", "6e3b4098897705c650b7c0b2df2c02f045f98635597124afdd0c8c28164667415ece3ad3a001aa0c592f24d0e6658aa5a453de66853d34cf9a6da453ef6bbfa98a9cda76c212c6c374269e6c9904ab223fef6a321ef63046c2633ebd911a92d083ff7bd5f396f339cef6feb2b604bdcc7dfaa4af8e91a0be61eddcf46ecc06095a66f0acf4e6a51214a09c50eea7280d22512643ce01ff2742216a35638e006f56297e93fbd042f922b8ab56cd6fe7b5cfc585a7452a884c4cb16f82441e32e6abcfd9a744d6fa26bc9d984c58ff65ffca4c6c8961904cdcea8095c920a7da3dc9d78117d2385a26e092aef3915cb08fa8cd2cf172d44fd824ac02c4b4537c2d1858bb4204ce2628bcdfdfec5bf9722b6ead675284ac6419af2ba9abf0363fb8d4d280a5fbdf8cf3d57fbca64d334cc7e524e7c2ee301b80c982214027f0e77462b5d66287b54af9ed1974002f334cfbb85b875135daccecbc172e596616a1bfd7ed29dafdbf9876ac1791858e8941769f48d6b62ce2749bd8b14c547101e4e036a0d2a849e2a28b5b887be1898036ad36c22a1f24439a9cd2f673c55ebd8ab9c92a4e7836bf083cf4647a005025afee0a0769d1e603219a11fe03278ba43e23f59643fee4c57bac238339147071bdbe8d96f25b5e9c0e7f13bcde6aa30932a0a1ee50022194ec0edcc6edd293d6a6d765c78a903ff7973659952fc04c210a5e80cde3ab38701c4ae35605ad3c7856370eb6f25eb89f33f0b3ca4ae6226bf0e2790fa9fa7ef5772dd4d90e0ee2538d24d49704d92b57b55a8a415a8a34797d9b6cd539885b12189ca3376735175ac9130b4eb9d6cdb9d3bb37a17bd531d713f6e0e966a2a748ee9a7cd6bbca060fe5370297054832dd14e38c7560a78e65726351869dda5659c7f4ced6fb82b8b4250b300e9f5851e7a0c34991f381bf94665915a2255719ff21ec8221bfefcf9a63ccc8b4b96d86a1ac47dcd34beab55c164ed2f87846a9983df4edaa01e366853f7e596bdd5b80dcadb84d7de52e715147865e676d343b1a3871fc63b4af112d915cd593fb9d669a59930db72b3386919d1ea0bc50655b1f0dfc3eb421a280ecdbd2ba207882c3450981f5b26cf4b292583e6a1bbe808272aa3f5288bd4c3cc2240327201b50c68d37538f26af339b99d6f5394658e95e05b4f70b3f293af790e91e479c5c6c301f1a2bf174616b25b16975bcb39e0c0021c9bd332c26d5cfdbaa2d9f776fdf0a7dc5bae8ead67f417da5c7b5f13fe9f725175c2d1b4045124bbd745401ae9c750aa4add7b12c71de3a2e43d75e7eda738e7097d460ee54f4f373b7655efbb9c939716df8a51d5cc4a63740653c7415eb05e7c6d0e76464976f2b8cb70f3ee134e540d409ef46daf7751925dfc467c2e547e270119d852252b97a05f5cb75b5a13a711acce7a6c4c8dbc76", .None}, + {.Lcm, "-cb515a6fc76e753dc3594aa2a5130a5ab961f30e3b448e8b0f85b626926ecba64a60ec6cc3f5e2bfb1fcbc1a15c20612b9b0c770ea7fd5a39af9a7953b1308d913903982e6bff4579889ddce6814463b9da16b1b5a4beb7a2be581e93d11aa43927dba2f93bd74a805a875ffb1af4a88fba81964abbff1e2256caaae6762a19e752df207929ffd877a2b1bd2ff683dd67a0e7cd11e2c09ef4fb579223fe8186e306326b18b406cde92b4c38e33a1583b97715a7a9ac7cfa214ed98f61533b38291372f95de9d622d2759c591a8f279ffab228b1287ef5ee28dab6169ab200375769cc0b7e9266eda0cc72f51a0db869bbd40a0198a9f2a8ca77e16a53d2f6c69fbc73733a7324695f1be224587992c8385ecc91408d89a188530e38eba1df4070d443f9dd5e9fee47355567a95a77b604ed91102245a2c8533b1705ae059262322d8a04f998d18b15768d4df2725eaaa21c3d6cabe9214a7283521c925da9507abce23832df1b8305794468b4c95506fb7b74d6fac39c0ca96ed33f67a6598776fa788f1137b2361a02ee984463728a59f8f2413194739646d747704316e0827b8ce8c0945d08fc87b15911533ce985a4397398a3f951cb1283f585cfd91de661ddc4af2662c71cda16d0d7d32240ff85da327e34d4324e71a7d8132dca01a6b76b67676ef8be04d1eb5d9dc0073b7aa78e3620f235b7d5184b17961f8592293", "-b20baf82177dd77d42f3c68729cc4fe1b32b3b5a7b6ec716133a28933ae42f2547d2649776f296a81017aaa79a9b86064ddcdd09be7edeeeb824088a7e20b40b723083344ad45a844b7e326478a1f29ed36c529c32c69eebc5ed251e8678ec40c3b78f6c857eb4627a9897e76834205901be8c2e4c33cbf6cba463a127a5e2bd0d130aa22253bf35b2bfdfbcb74cdf2d8be100c066ed21a20db14a5c1817530e1f74b29337f32f6eef6b466669c5b13da96fa4a93bdf36e8cc7a286044805193ab045617b79b7e7f142239e2a73ae1e2e5a58848c69281a942f6f4a744a85e1fdefe4298dab514bfe43150fc21fc051e2cc587c7e359125cf0a22a5749ff10ca32c9443ee2349d91bca5b84893f0197b7864949cdd909cb1590eb8f0758319ab2670c54bf6fd4383a120438c0e0f5d0ed4945e22b47ccc3b13b98a84261e1d0b16a162b3cc36c43dbc995ff2b6787c36073164e7ef96c4144ec9396ac977955e1e60b7bdeedd042f4f1c4400bd1835f77f9dbffac4d2d75e3f39c5fc2f9c7b4c75df743aa39d4876c6b9e4008977a024bd34c4539a82c417114e1c083d053879ea27ca110d0fb0ea5697906b5f3f38a4ecf8d7c731c91d03786c86e0deacf8062ab36523692c9b8ba34ac0b659264990b2e83703d1ff7a3f0e3bd756bf253a174b522d57d3ff2e517a8178981d7e9f83097bbc69c87c206432c4e4ed3606bad5", "8d67d8c48a42f659c611286268cd2a00f0b68e91bce11fa2120066ee2fd3ee3faa227a2ebaae15f815b99abdd5c589c5ed77b55b09cd2ec1cd5ddd0c7986184fcbd048472925086cd7a2ced3d4908e84a8175cf751e760aee4d8490d1c6fa2627f08432f890c7a918b743c418782c18ce08563b22379746318bf60db4b5d145c7e1a0f352612e3d8582cc957c9a3ab77d8b29215c48d4a271db531c4462e3344040cf6f85c570ccfccd3307fccfa81554e269b46754f0ba56246282eaaf79921561ee6e64c0ffd1751ca114ced160407127e396f28d7f07fd8f687a768250d2c76219db7379da0d0df7e23c863793a8b9f34d29f99ad4cffa5d4139257120a5f5f5994192a93bf852359f628fbdbc64f18a6f2fc9de16ea9db34cdd3919ec95cf6eb2573c17258da2054f14ae5031acba9f94f9a0a2866941bbfe14acb22c4675c661b16996de920a31563a6e0277662eeaecdf5fb8afc31386f0c1659ec1492d0327cf7c952099059b694de801fb230cb4febfa0161d18e7296155d4a7fabe72a436fa7c6803239bee2429bbe532d59764d06adde624abba4d2377f1ed542483c05163f322e043756b5eb3b0fe5b0b8b634a10609139b464f423ca14b43d526589cbdbe2fffcdda4fc063194733448e4b2dc9015b69108a2c1e3eddffb59a23778d90358e47851f1aa68616c96d0f6679472b20623afcd297883922bddd6f4f787db03f622b5aa44e23d21e0b1587a77ec85c077821e0e3dcccd81c01d26d2481a1db14e7307f0827238153bdf2b5f433ca3ec470db32b4fcd5641247356996426c8c1301eb8bed04d330a5e57e2ef36a9834bb81e3208fa5fdf801a424fe89574422589561bf10a0de34291a2a1bb8b060d25377ea9f5f950a8b71cd65781e9df6aabc2a91918503e273028b9734f16e2a0f72140fbdb85de5e9f5e02f8e37f6e031ddfba62669bfdc7a064190f1ac664f04f6aecd8725e2d16c363d1b07bcedbd836371c177778e1b6dcecb27ace8621a67e020dec2e6902a85c2f35b4868f894ea4f6950ecc476ecc8797f54cc65c0febec7026a8868b6852a26604c4a633e657a0eef11ba08d3ed574fecb06607847543505123e41cff77f1aa83f92eec633c1d0b43f91329832131edd998190664bde843ad405a065bdea86c6f3756cde77d273e1c53d01da920ef044c83fd62001692f00adc455d3caa9c4e53df311f12ac63336a57e905bc78d90814860eaa3e7534dec49882f0fee00e4ddbe24af40b5fd717b99e6a5658af7c9f54d3de7dc8d2b23cde86a9a8ba9b270ca8739debba3f68408d029980fc2dd196c8295c3ae67263d78203e5ac462cefb0fe51069cfa953d167891f6ace2e31195cf23b70a007bf27e653f8a0989f7608c85d0382f8ffd25ba7b283ff201de24fb7348ecc3d17150e3be571a4d5865ba6d36ba924f", .None}, + {.Lcm, "c41b91286e36d908ca7260840ac3bc3ae0f39f6953e834b1f22181311480cf3be31a9bba4b39d7d89e8893072942261dea9b808fbc9c82ea37437cffb267381c26ce03697951ca66b60077740dca3adfb7f664712a43a7e002c5a0167136c942e55d0137cff34c6734f826649063e020f709015fe8845a1b16d565fe265cc37a7b73e7a2e0da48ff32b02a4f09ee7eaaae852eba02cb1a663c7b42b1627679070bf807043f65a4bb996eb39db9f908fc85ec806d8965e780236fa7a0b03cb1de592f16dd7b6b148bcdbcbc25deb59f1525b64f06e4c08a598ebacb249806a6a2b409b92f5fbc0263691db6365ed5e0a3b894b0ea3f0f3b4c3122c032889708077c3cd15bd8b412b5f9c68daba255fe3775810549dc7787bd8ddfcaa2e53fa9bb5729932bc34e2548864633253cc9ca90bb03586b2313896d77bde3c5175c2e430be78e2c76155e9725233314ee37680ff8bd6f8a3af9d002f9b5aded3fea6e9f24dce3f92deff3e4d2b4f2db93567f6778249575ff1c926f145ad25e9a6b4524d6fa21175b4e0f66feed5386031b0dac8a45287a13e5f430b743ff1cf17282677588ac5ed395795d9a8d0c3a7102e27d99c078272675788a5c755386f4ead63d671cce5610125045b50ed445d3150eaf93d4248f79013e527bc7efa56d8f09e655f967944c3283cf569b3052ab88aa5b8c993ac7d7e2aa058078ce220f05103", "aeae6569fc6fbbc4e9a097c07b1fb10c596c36949504eecc2b942dbb3f89969399f691be4a21ae0454c7f6163a3446c31bbd0593755872c2c61a8b325f71f586bc6c02589ab34cbef1e1620217968d372df4426dc79ccf5f020f116559053c913f2ff310771e82ad88807f2e671c3ba5395c285cd9ca0ed946105c6806609b566f63c342cd48a7520f9c185bd3710eeaa8710e2f7200d7d2bc6385ae543db9ddc7ddb81b4af2d8a67207c40a8bce73f020547d803b4b8c1dd2a6c64a00dbeafbc0079db56342eb5aa8c663f1292a352b0c68c1ca71d62480af1e73ca69fdc02834cfdc70e8f2c86cbf1004137592c7ef37556b73a80cd6af6e13b6648b1b19f977f2bfbb89a8a5c2b3308f812b47a67e4e845fe244f0565258f785249e2808bf84ff5614afaae647353413decd7906d5aab0ff6817d21995172e5f7c52858bcb94c2b9e2fa221fc7e8f62b7564cec7710c7e2c636bebfd31f8f33dad5a4ea2b846caaa55c4f5f95ba9333f91998a7303ed826c3ec7191958d8942a2a6817782ec8e02504153f772761edf26d83ef512cfeae9b8c3a59e57c9bd3c5751d461a4cedfc8a40c13d7b4ea1faf6a3b3173ee895192b9c2a423364567fb8d42f02fc5226f00c580bf2f6d7016b7da0850459d20f965f9ea7a6199bf7a89b6057e7ab98afb6599f1cba60fec0a4cc2334519c92ffb4c6e1f6a2f05bc2cf676058b126f1", "85d055163558688b0dd4634cf1e00973274b233670d7fa9afa120e5c83d9c81805adab02a66d6c879c88737cdaebb0f6a05fae17ce64d6f9c360588315e89594675027b3b099962efe680b3a64564939ad31bfe1f77d1683d3c600f91689239ed9ac9a88a8bba5fcd809f69e63f5caaf508846cd2f27efd4d0e888028892168ca288797a7437f2b20b4c88c3b4a047556fcc4e06a14676c87c5465a796753dc6f649c4d69901423f7e292b04a41a0627b5ceede19b02c7858342b81186d9beea8cd33821acf8f957e439b61f66196189b8ebcbbe12bd1e5a2f7f8ef21f218180a37a771284b97a17095fdb2aa052838aadd5310580ab408e2d15d6c2f773e11b75e06ca12b4c5f1f56b5e4d2f6fd5a897bad344d1a848b51dea46e74b8fd37d260237383b52afedf51625e67994672a8a2e26d8d5d5588d840e0cefcf0b9d0ddf5f16419bcc62516b73434848c7188c04c06a2765baa555b275bf8d205ee733789858a24afb6ced1e3abd6f008326e1d35cea8f3fc6957b0632d2b2843414fab8239415a1678f770f7ec0c9d04a9258a978ce4aacb0d66931b22993aa22de21e7c3202ece91346f5d3bfd2179728f424e5d4eba367ba36d5187e542c5789284fbb2375bdb12122476a157c30c1c1956ff5e11a108bdb09c410f9181208361c8a693e11129955729d787aff295f344b150609dc19c247c20680f1d321446ceb28bd7d242b5dcd20f0112ff380c8e7ed2c541299bd4f55f1ab71edb4e72a067a017894552a29b78b26df37373e9888f7e8a065e5b056bef444fcf2efc8c2621011fe4939da4d388f44bc8e57ca6d38c1e6d6368e0d5f1b6fa77da4856e744ffb38e029d87fbb9a41597883b47cadcb9df8049d7d35b7a2024f5827a909e2090fd5ac6465014971d6aafee7f54c73ff5ef19ad25be203cc75ec2662f79dcf478d9d14818d7056e75080de6cedb2d9d8d29d5b5ec4d358fc2806bb2c8b0b6b4f237e15965bfa71c93e59a84ad740b9dffeb051538f1934f29608c9cf9c5678f43540181bcabb2a5a6a78947ab45161a7d2ab76cbf643acf3acef667cb518d33dc12c7b16d8a8e77cbfcfef79034a50b21d6c4e2b2592098eb812ca90366c8c348844fd60c293b241835f66bb59df73212a9008e39d7281dc645bad1adc0d1295677d66f59ee3ee066c7e55a32803109a983910bcf03d9e4b048176876ff6079565f0c1ce86598e5e3213dcaa298c590f8bb8326b1d316dbdfe9b5b631f9656d1cf53b7e65cb100b9871cc533fda7cf2a09807d31f63a0f4291042b1b6c42035e5300a27d1f5b212a3c3ffd8dfb1a097ecb7e688812bb0c2952d939f7821614e352c034215951619bab053b202cf4facfe837bd36b501aef88cf9108860b853878b2f7f285354084a73e2437b736e3a3c35aaa678821f0d18f7df3d429e5b955b5d3", .None}, + {.Lcm, "-2c2c5fcc3017682632f8db894bd1d491b470603b30bab0027449288f592eea150222904c9bf2ad6aaf727adc4e1b3348d0caa64190c42848b6e4a4ba910ab0a662dc87381689baba6dffe11124dfa4f75a4031fe6d269fa835e95ea750c421e09d43acb6fec70d1cde1ae70fc32dd75390c03485abea17dcee44409807967b6a2b348f47ce62103c96dc4bcfd1e98b03e09531ad4e21286649ff2eba69b715843af804698f6f3e6347bc32d8e344c19e359e31c398afd339157563e5b89a07ab2dda3f75f7ecdaa0c4dc3608f0f5ef611cfc957f4117151ed3d5ed41bf2777d058c6061e8b9ffa6b5caaf0e45e09a6531dcb71cfaf3a7d471e1251d91903ee2390e36be761dbfd3a9e63c00a4e1ed200989a9442140e34be829d913cff018463c1e9fa5d3a404bc6d2fb1c356074c1486b3c8299396fbafb21db3c5dc0a2eba7135f46ad2e373aa3339ecdf21bbc9a5c0cb438eb1dec8a0ef84a97a718280585b9b17dae4d3cfcc5bad8fe879f7582f318c203ad2d07e2bbe77f330c4be64db84c682e943b9c3d877057f3c583adddf1fda3b3aff205d5c0f6ca7738d367cdc1afa3d1d5416cb2afbe7d01b510dfedb905d11b284dbd0295ef7921178f3b966ab57f5ec15daff7f1b8ff9c7438862b37709da93aca48ce41c682b3425cc219fdff5db7da5620856195dd7df12448e8dfb424c38aa7dce127e0428dd45d6bcaea", "d43c3864fdf4d191fc9fbe107e5ee4df6f8216ab13e8fb407ce7f1d2673d0d6b6477332a74adef053650517128e5872b4e4a0762663eee8724b139caa1e57c7996c1cf6bc841913b345835d1a5e0c645d94b172f50583080d10df9e8b09da14fefc10d6204e31f6c1eb744da3c2666eade8b1064ab74b90a9f4f4f2c12f85a70ddd391fe0cbd02689d367b85a60f896ad10767b274bbdbe11b0947d6d778493e857a9c2e9ed32c4596742bae6bad428811f8eeb7a87611dd7dab6aa3358db8a6fa087e3ba41f2ea4c19a3cdd2e7f0d819d32aa9a433d5e461f0fe1bf0b5bee96b6e4874a9ebbe0eb9ccbff6b348920adaab999eefd444e6eefa22dcc3161fbadab07ae1c83fce028d89898b8c6e77127ec0e139172288a9201177c7a9cd4b57a472c70bc44169a3a2a95b760b768fde06eed6165d61b12777ad9cd28206a899a31c878c974c20a11f53dbec4f087b6a27b2c2d41cefddc8de2af0208b2fa3e448814f25fbd977e38483bbd77d5678fe39b1c5d17816986934b668a8e9d37f0015966ea03982cadc2dc95f4c845840408c438e5b3d4633b35378da7df327e1cc672e6746bcfe9239754d9e7d389035fa6d5962b72418b8f545502201028026186578eb96df964f01257d28ecb59e053e6b93a957660b6c8a66dccde31549a521a3b0d75d96dea46610c20341403b80365fc11de48f6e78d6aa5dc4aa63c1a72cc", "124f91bb56e56b92bc159f81928dd7a4b1c4feca16a3620f553223382898237161bcd6ef9f112d738613a13467c1329ea8d05c0f016839fdb9632fa1b6aef4106a5c0e5fa052d9be974a79ba601d4008a1caa7fde0c96dc135319e20ac7fff61ea576ae52cfc49c01f3885ad73e1c5ae637d0f0de8da66aa6f982e7783fe07a74b1730242f888422a5b2baffba496d04d5874dab32a00080e4b12255b8d2e9e8b4327b874369af815f06dde65e70a4b68220f7c6244d8a5dcafe5d0806809b50092fc00babdcebfc83566deb038e9a4485123652288a8b4ace58256673d39659dfbc0bbeaeca8f14ba3ea6b369da825fc807c5aa952812bf7dcc413326f3e3ac84d74fb5ec503cca7413a783ba56e31f0a2ee8524d3e1456ef6b60a49e6795c27d23809854af8af1574b44772ab87fc9e143a8a75ba91a842d96fede3674b216a4a1c10529e1031892ebefa535e1f46becfd83762b378b69d7a9a4aab762a4a1d2fee1620eb4290b4fb815ed4df7f38592767f3bc0658c9bf291241cb21cdb9885217712dabcec854fdb3c916cba425243da5334694a1e986906bf08038f0406188c4f955c408e7b16ae189557eb0d5e16adcd2adc3d279b9638fb00ca296a0498db8c8653bf9ca662638a1ea4ed7b18976ab3aa6fe98a83248e104c1cf21ef28be69072869609e6893efe2a7d917aa022d9e8d2d11588da34ee7d1d22b2c11bcd2555a2a1a8836d4274e5723bf935f33d76be83abaeedbb62c1eabbf8b86eab1934b56c97d4396e4aaf8d881929a0b77afa08fe7a5a963d29ca31c5beb33be9148fc4d905269e91f192b8d987e0d68f291d2eeb7bb2b254bd9cb1feb6cc914f166c085dba1ec8198f9e500f93bc2a21f64daa6c47770532b3b10b4b8121fefcf344b681aa0568c7dc23b954d64b882ab6264df7e3eb6b3f55390f7b308c20b46eb8e163b9872cdaeeea3d292b7c6c0fbbe25de46b8b08ea308de1341283e3a9d15ae1df6b91411a6171cdb1d1f15014f3a6fce632bca7763a14498165e37cf20df82554910b9b3222b6d9aa9d23959d93506030671f540bf295549a4d06962d2f89b5ff5d9572fcbd1846c6de12a032e65dc66d310e8e9fb90c50b97bac89f62ac66b5cb4852fd1df0cc54f8e87ae90e24fba8d4a2c651c3edd47656c949bfe6f5c26781c2114cb015e7b348033a5fc184720d411de38c5c010aa51b5ae09e33a81b172d79439fa368dfb175006f7d717088f9f832602d623e5a5129be5f3163c208db9821227b3c9498643fff7cd51e06076bb7147714dc36ef349ec285a8dd9664badd8e272745e80205187bec162d0412a81a05b4e444dce5234d71def932c971dd0ce6c4b7aecd33c77281e441e34ce62bbf19a945672bf2565c66a78ee797d543cc0feea7e7d18262af62321e0a6e80c18622648d4baa6c788f302f33c", .None}, + {.Lcm, "efeb4a7fff48e35e1d4499f57eeed46c0d34f15c0d0bee773d32610f5423dc73b94b7d7e3944fd176be0ac254a1873cd886a1cecb8af2cee953b14c1cbbcab8e66e2facf046bbcd6160258cfaf33ecac376b204fa732ba2ccc139b4ba073a7cc07f27fe9b05e64b96ead80b4b60cd7d60c149d38a245f8c5564d80fdbc6e68cc3a4acb50a382aebb444d2023147065572d33b7c27a3ed079a5dd3d8208010d63850d3acd580ac89f43261b03cb21dd22f22a083b1442db6367a9a9df316dac308627389a43a5e173a187db8f136c04107c3d902a4293a5a83770c4cd029e11b245f532a0a6e048d462bdeca81a2f54dc33656375ac1773cec1242d64d6499452230f8097351002f473b1204094511e2b7b14f097770abcd599bf12dc962b87e50e234ef79f264df98f03e04b196d333062c9072c43841e49e70830e4a3f13008ffcdb51ce42c22dcbfacd1aaadde1b688851d73bd501851bedbbada42f6f2693c056b6040b21e20c4ca521a5e9c980bffb48d1a7e04e6eed824f5502d51b9705cf28d0227fc89b0b9642e848302b3db7c3ebfff850e492e0afd1c74b54a0efef0c7ab9fec7697b39531241b436af2b81ecd430923425659c79f57487214c26ebe373d97defc889fe872521f58967b5b4e736662a2708fc0298b20684de3769b9acedd0221b24589f0d3eb8369842a63fabd58dbde112162ec1ee04bc6e59e3f7", "-e7a7caf14c46a8cd5e2bf456de8c60ed03524ee89678304d841a42d5e4f6e2df4fe3bec32ac3e36465e08ab4f0c2bb0bb33e5d3349c2983251390052c01ba4eea41f154150c88c1fe3202d9a47376ab91102d13abfad5fc998d0c71bd3e6581fa5c5bfa1d25d2977282d0041d9ab76327f2ad42e84ce5376ae62ee4a3f8b2cd3bf0b4f5d932fca5d1e6a1f8f79e5b5723b7a395e87e88f682896406f20c951573659050fa69a0d6481964b41539c03f806dcdb04a7f23772de65950387936ffdebbedb593b0885ff583cb284fffccfeb74b2c7da07eb5a14924a9c5413984bd91ef635af040e9c38f4bb2ae1c2153176c874781804c999c17f9f3e2a9ec8153d486da0ad48a0e3e33a1f7baba2c15f7cb3ac20096941e61dee6fa24737955a8bb9b31ad3eddc2ccbff74601e2ae4d92e2d86432ad8c1f4226adc6f002b283030324fda1b2ed073bf9eb8461bb4a8d431e539579e3c669d8b9e2996b2fbf6bd89a43f72e0764188b5f88069f8a4e63e90497d2d04748fe2c053bfcbedc5be918a038594084d44410828e491ea48c794800247c3e92cb547d36359e9b97cd4521b9c29c650606dbd42476b2de7045d6edb818f9ea33a83b503625cb01b28ad479d4b0b35aee56160369b7216684462f9473fd4da89714a6b6cb5f4ef4eb16c20c9b89b63819ae202b4d51b16892e17bff964c2c5f687156b2bb63c34eb765b8c", "d91a90e8e5a0824c552dfdb2329b6ef288a47fbe23641ef13672801b0d5b79df9556471ae7c21b1e327407dfcbee8ecff479b27f9aaffc7e38e945bb030ab3efa870a556033b63e28af29d9325f23c8ae92109d272d31ecc0583fdd77edae72151f5af1d7af75d2c8301fc285858d65e8fb18cf411c2b8fa15fc4ef8455d387d0c969de08a69662ec2a28a485bfd5cc1d0f58612c58c85aba6abdc846d8c56d3d7374c8f2a19e67735176f4aa66c090bccf2381abe0b9fa220182befd9e7d8486cbf47bc3c3f7b198572d083405066896674d22c4ee2e968ebde4b4acdc6baa9ecb5649abf4483516b305d9d75315db515e227fde2ab36cb4325eeaa2e98441a603651eb9ed229de2c5ec7ef5021b13758c851315eb76f7ebdb095113385ae3e25f0fad88d365ada4fd599f1616d6ab225c600224bf42838ee488029a9fa0eabab76d7c352ea2cce05ef4bb09932894a890f798529f30f1844ccda22ef7c87c680f3b691f588a7789051cb4d41e7a46e9375548d74162faafbc110630ddeeb0d185638d8d76000ebb9cc94bd7fcb5e9c212076f3a7c70d6ab69cf9440d1cec85e95a7e8e00002a0d09b14b5a07ca50293981317ba4d93b89e6fd26ae8a9c752e1fdf262e9f7e2ce8a8ffd6b4879190673ccf77e37a1de45b79833cf7655219710ae7e21cf4df9ccb4d64c03de9ebc4e069924ad57a7dd9eaf5b15fdf357cd4f42da49be90b9a182d3a53e06cee201258fd3f5b0525d50c26268a243acec2c93b0d71388f21856333d81c2f92cf605b3e8273b232f06e731f960357f1b75c21c670616201f353feb78c212f5795bb44970b6569f0fe5171a5085beb6e5dbae4b62578fa6edea5fc90f63a534e8d0c6dfdefa3bd41e6cd38c4d219ef04286f03ef784045613690910c746af8e4db71a25182df8696753b4854485d26052c5d9403607ec8c84f2d6eaff0d0cf8ad25e1d685fffb29e11e290a7ad914e94114d977d2dcf8325c8ac4d6a79b2dfa8345516a42bd0ab7ea4f05295bfeda813f50cc7351cdc69ee140afe8b7181bd0120a94945de4bca62a6ed23cc743e8b7cf57179a07c3d249fa5aa91e39c904917837f81a554ebce92cb4bc137185841eb788a7199d4350b720241866d954eba5e2206e4a8ff8d913382c2705566ed88120d69f5a7a8749b3a55f075118efb0c1516ba514e8d9ad4208b17011fef26ea5f3b06c644fa527a4e0827cb809cc1fc2aec339507614aaec342782b2d798943c8b19750a64ef8bacec3b6c8953b7d84b72f8f97f750133544ccd3974867e8e0f46583b0510530c419bc0a9848b438218755d301c05d716107cc6b83e67850c68b4e993869c8e1d47c090e7dd8edef7877d2b1e8eee70d65f892e2203c98d49597cff4a951f22544ccb87716ac77ef3c220a7ba295af49daebd4db23dc4b26251e0b7814", .None}, + {.Lcm, "-9160d499dc67bed1ef0c7d77f22cdc6d4700a23158f5b0b84533b0dc3abd8f69184d28582d580d63b92b59d2eb4df5c29e6e32a0fa9d1480f90a08707b7805884327d78589f09e853d33cb01677d3f05299e7b1c0b5c760db438bd3586d7d8754056a09f6925036ca8313c82151917b40e801fdfa035e63cac0486b7730e75b95cff36ea458469b71e2efa1d69dd030f45b4e24933989ebdc1a082f5a3491af3952663f4c90a8dfa2efae0add3d80ffa19842e065b6ba9f3bad27cc991d6402cabcd87496ac839d6e13963e83ca06e0f9bf6e0be516a35e477666395a60a47e6c5e9a7c0496399379b9255c9593a1d6cf0b1f4424215e15e77317836ef2a30e9a3517a28289392cbe29f5c960a0f7f500ee739fdfd308920a154fe7a4e91ec8dc0c35fe1b9ff3d2fd97cc96de98eeeea326645b5546fef5c86b811ad5fec7349113c09a4547c5c2ff3b696baa45397181ddd29381597cab18096bbfe5d19582d8daa218d8c900a6c7dff8db0ff5a07abe686a58bb3c3dfe72924262d60827b89e3861fb333b4c6e0480920cbcd95c9163c48c884b907c3f254f35fb939e76b431bdc31750598ea74be3ec6d02a03f4ae6378a4361df57ff41c8979e105fb7690b94b50330e79ac9fb297b1349351273cf2dbdf78e3d91529c2e9098568300f2e0b27469ad96bc67e78a5ad68964013af18c9d8ff48bdef1e112c1ca8ce4c27d5", "92c1fbd1777b91991e544fd427ca03563036577c15d2002847c0782f42e1169f31c38118f3e75be92dadcd864e4a3522a8671e82fd433ac9c4c579d37266f5b865d2f6d02baed8984ec16afe56c78725c5212917c32a01a328f522e154c902c172757957592fb334e10c57062154a51ca14a2b44cc31ce5b086ec167f1577c2596dc3dad6fb58ba9b5a3ac3ffc9b65871e642ebbaff6b49d0ad9cc7341c6ecfa9aa192238104a38c65e70138ea37da6baf1c6c883cdfb57077ab55e0607d0622620c5a1135f7892f60e8d6a132156bf7811c5c055756723a3a87542a48314bc576d4e12d7d530a9dd5537cfeb21b0c86f13341fef38850017204609a4d976cde0f6ed895b23d53efcfbf11bdae2083aa16358e2a5d314d7cdf51d5dfa5252f8334bd88d59b24329ff49675e7091faa1dc3ea1e1ca3f6f819af0228503654f38eae8da9b01acac47e295f6df14fcbe59f3754eaa9a68c43856505e2f37acd4b2e63e5777dd995d89bef17cb0c0309cb351df256fe843758deb17f6a7100a5d59d7218f4ad067d55ea81f7a66ead2165a6f1b976edb7bf9f202a2bbe258636712bbbafca7c67ec268749b891392ede0060bda220b4588b720d01775d47e1c6f20a78628ddfe5c67d09aea6b97c7f270c2471f8eb9b44dc1c09cf35a7e5c4ca65ee92dc5e6e004856264feb57163f205b45d896261bc96a819fa99c613a952fdfb2", "53576240ec0cf0c9b749861b50894d9e3670cb46c7ef2bb6487ac6a6ff08f1739d00511f9c951cce0e926abd4a17e44750ad823f0bd149fc6c16f6aea20405b86669f15d6c1a112b87c117f9d6a3a6e21238b9f9a84d559e99a217d917ca30a3d9505e6b4d2a236b2b027583e0d1586ebbbb44ef0672a2b6fc6440f528a88eba70f776a48e4afbdec9f0c7cf5a8ae3ce4001cdc5ac3ff5bad9b2d2fdbe211a32c663afe8d9d4c53286b490fe67d46f9380a433fe6729543b9d3a9c0e83c6e8d824328a3a13b7299922c6db29b5e3bada4a63534dca434e2fec33b5f57722a9a34e67f5a5dababfa38198a47edee1711cd8240f2758ed2e4edeaea71f98519a281ecf049b32e17b7da3152effd6240c5ec38aa34b20a3d38df2968c8ae30e8d8e14b3d6b6c337f788b0ed7e80aab6877a044a68b65ed774fa0bcee978c6aa86bca80d4f6d28685ed247d23a3ed5c6e779d21f1ef5b5c2908d7997729dbf833d06e5bf513133d871ddeb85d4291e2b7978d97d44c60866acc8c4c3257a861baca7d9cd3541401b53c4a45f3f49fcc73b3c01438b3f5e45678f7380860efc52495adc0b3dd7a59b4fea5473f6677134a8550f9f49d89d24f71a8785ae75b14919314a71f5be2a6a9c5a67dbd717743f305b4dc0a7ee218a52192cedf4bc1e6ed61d3948c11f0a2460305b99904a6c6b41d52f63a1df64d2b86167cdaf39b6053f2ef8ba1fe36113926d9d58508cb897c428c7b40f7ad37e9a21e4ce405244ff43feab731a55ef44777e1bad3358292a609ca82003e69295ae1f276ee3fd3b192ce7b7fe9a9a87418717e28d1b72bac97d3185b12c4f29c58488cd63fa97670a3ba571d7f0859aa3656e878f559a388d502bef61ef92541976694baa05f73c30ff9c1cdf390d772c36c3052e71d02b7ac45c566ae3c21a60908d5129e69b898f516689645b4f63a2e539734d01aa4e999be3ae809e7b9e111cd963a2cf5fd823d8e3d0806ad65f1c3bb53bab3141bf9c8d52d1532ef2f9feab9074060a6f74ad5f86a21b5ffebad667fc9eac319f917839009cbd5859238442e08da2014994c0ab6c068b81ae6f1df1f44ff0b52e7cde5e550453221ee8d682fb2630a3bf7848ab3b285ebbd8c0d893b7878e30e0178b116ac62cebd6e39e588cca2febc18fb1c8e1f4cae7e0d2e7e3b44f03c798286dc23cdf57d5ceec48d25907a8089702810a58265d3674ad40d612aa4d9d4741fd7f039b13ea18c100ee990b5a9c0e1051db63dc29ecb2d993efd98d7b8203d3559e89c58f23a6c8f248052892e0919f4cc6213e2a9a6ec75486a1275aa2ddeaed633340322e33c12285fbf144628dd1781d21c57a5174b7ce3a99eeee8504dbe19b1f4827dbd9d82d7f378c590214c35a775945c3c2a8fa80b737e6a969f1d464ecdaea55351a2c58cb0d5bd7e78010c13d1a", .None}, + {.Lcm, "9adf176b70c9055083e1c5eed425c4115f811f8dbe9e2f4f442a3782b8bc9b469dcacc4aaf0667e051eef6563e2646c4900dd7a0f16808738bcfda7973c8ac30294230645cb36713a7fe688b803e409dd0f9a732b8f122af2f83c5b1887fa791741377123953bfbd791c6bdc553b53d25585d0d2330760c4c5c140ff9d3ea1679cdfea55386da7a19c65f8055036f03436d8ae60b571ad1ee144a6dc306542dc35e7fa9cd80041d5804e169f97d46e20f24ba9fdc7d1f597614a11b6278f8813877af22a3462a210bd169d92ab0e79d29c64240adfb928082481f5f8f6737bbaa911ac8572230ce63f64642e71bd0e7bca07ba1e09f1da33ab169812aa9d295120492d80c4f7cad39351fdf7d9b8c073bceb97566a901b503aa0bb6df9eeae7aaeead3573d7688cd350c0a7efa52614b4945bf1236e68a9c80c15736c1056d34cf7892df5b93add914150a2195f3b98392e39ede7a751e6f4c59a319ffd43bff595836464f1be688de6f6baa32c6a58cb575190174592151790d83cb5b7548f0c08d95ed10f05e459b694cc1f9d03fb8d70acf77be083086455ef8d3d2df8a1841570c20b9d65e75ab87853094701f2dc17246a4ae5bf5b35b7ee950568abf992513a5a2fea57cce86cb8fc10f34e6d16b2508af570ba3104a70f713f06976434f8095af49b830648b891335a7ae770e239c4e7f03a7c2ecae0bd8bd157c2e3", "-3db5ae49e091a176f97d171bd6172021f55b695ed24bbb0a051153d924eac4ed3740cae7625325144a242ddfb6fdba77a35cdc97d6bfc2eeea46e1ca5e07163d76230af2b361afe94ef917969c932fa6939cee1e6adc6e9dfe3f04d8ade6c9a21d19b8cd2d7cf33e5a6e9cf3b3e72db1450ff9fe9806cc0259e8b17afc5d5b3176b60b53fa1d469b67b8d21a13d7e759a138e9a78df3471536fe66ac2202fe858b65d3cc29b9b437e8386b3cf0cdc71fe18e5e52ac114cdb570e6fa82bc0fdb9955823f8fe44f9cfab90264cfc63b10b64a9fefd091d88e43934e5dded4da68211e3766b99cfbfc8c96fae79dd1dcb09fbb8a9438ec2bb966e3d009c475220eb38160cfd7814666840c4679baac42022833c76068fe638e414cdf6f6281c7061331c22eac13af053151056e5d5667cad798843c1e7f9dcfa52ed385391f4c20ada6ed2d1e3189c4c06e6501d459cf6a02abf68893cb618165b242775c8cef18e0bf1acf6ba199938567a0d609973f56527996c47335c049b6aa06a371dacfe8aa6d72eb3d3e278f5ebda18480db19bd6a03b91e7c5fe877bd0bb753bb80da9b7ce70e82648aba626f3ebf5112fba91726a92609f6cf5b03a2f39777c7b3c57bc72684e759e20227ba8725300ceb6f12389f92d6edc3a972c88a01e954633d15e64d6b81179a560887667cd92a5d51b4240afda69d839239f915432e98958fdba", "255511c07c3aa7394a52170b9ba34cb101d8df267a8420e4375142245626f5c5c8c6661b62bbc9a105389479ee8beb5fc0aa542d590dcf91d3d68b5223d91da1f8dc640610a3b7b945f010421da5e350e3e6b06f6caf060d5a94c745341fc20dfaaf75898c2d8e0def32cafb8ade9fe1cd9b1f0cb8ffd80412a8f30f4d500ecdb2aa0455407507155b2bc2d003c6453ca72419c6e41e62424c71a768efdf1732b7ea91bc409541ea38cca4657931bd253e831b403fccf94adc1b9822b29d654338def9915bfe20356dd26f7b786bb89efaca85cc50995f0e04d8ae2e239d0a4205d2d5a2888967d08856f0c4bbe167b2c3a261e33272294b87ff2b053e33cf8531a9caa3dbfa34e0be1579f3e5c25fef74cdddad6b5b86950a24ad900cb21567251a746a4a75a77b096562b8963a96a59518d19826af21fa0175d64ad99c88e796c6eb65861466567a919011a6d57953175c81fbeea1d75d3c0683a61d841c9e7f35bae4b9cb8d1d608dec58bbef48044674310fc11ea0d65bbbc4f8c5ebf68446dbabb83f24c853a9fd927edd7ef04976c1e430b20f26d19b785de4e3495b7340a64dc306c76d5f5003cbc4b9d6e989cb16fd838e0b1484ca7f611a81da83b28ba75fd8331beb1ff7c47c9c71ecac0713b54e024c806ef19f15ba671a5d447f98f96cdadf73a9f19a2ec94bd216766dd7699a38a642db711f3a6d100a15f0e70b8e301d1fb876c9f387caf6ff8bce080c90da158467182b5a28efd552e219041fa2fc3dc9c9f2850537f850cd19df1174715f3a0deffe015f243a37b30146fbcb5200e808704d59244f87f7b317b6ff93a08423ae52fd6829e77bd3d948f66ea0632e4cc627bfd07b18cd510f4c2a2622f3f395b24156d39b46695182f1d83abe26721a4231cf8fde77e707ab3bb3bf3b4eeaa87bda3240e3d714967830bf19c27776cf36b7573deabc9ad57f4ed3574ec0d6acff6f5757227a31626b69033e1dc314078ca7f1b367acb8dd81b36aaef1710772aacb62da632cfa0dde43a4e5da3f967826323692278daa05b80d80516d4502809907a630e748416818f07ddaf831f4d466330fe7f0ba797e719f86a1b689c5446c10a11171ba40290e3a8ba437262e3c7aa0c7c3d509eb66d08f772f5771a325200ce984973840bf08532de1b4a6ccc5966c8e60f2032ed966d1510888b3656328d2a1307d1cd40154ca6d48ddb3cf1ab60acf7de56ae2851d96f8c209be9afdb916b2c79a780bb3baa3351c56d9ec0be558c35a8845d704c8107cf3e35bf98f9de5301097ac3ac0c3e24711f383099c9d72d7e5516a5435c12a71d839c511d42607834df611144ef5b264348cb67e1f5fe39715339b42dc6fac44e375fe1f56182771342d99e9930100bff504e04021f8f13ea49218c23798f39ff1100ee59f297c880b021898b4e65efee", .None}, + {.Lcm, "dc7570305a53e8cc12fd7ce273a66642fb518ce5f6b2d552cf3265841ec792ddd4059acf8462564e12e558ca774e8e6ca864e60c79a42724eb2cb302a798bc7579c823a40d8fc6b396408c8f7757d159d27eb14875e5bc87015d61c30aa64392d9553e488e380f829fb33eb2fafaf704b73d81e5e31655a84b00b2feadc6d8799986685c69049ac87e3e6aa437958a569cdbe9ab6336ec29dcfccd60c840c1cbbb45d027a48328c7067a76e4fd36da708bb3e45a1a84c99ec590bdf09615e1b61dbe5ede3529a1982a381563871fa423f99c792710ae38b49b331879295546413b0d19379b2b2c11a6179bfe262937b289d276e2d72cf46137b3d98d44d90d4d615760f581d850bb9108a1447fc7a73b9b81a812b846a2155bb886777f23310a67ceb4eb7b43d889c370dd254195e840f287a9d6ebdf692380e24c35285accb978635cd4b5dc7c7fd10ea414dacdaaea7d31894e49e5c08e343d397c982cec7c6839258d6a4ba1d51bbf53b3f71d622a47ec7a18f4611be54aad8663637ee84184324c4cf77ac1bfe86f906da8dd2ea145950d37ae23352384f60d461221930ea23125863d217da1a664ff1d07b153c81925e144a3041aee321cee34c245a1f659551e8d18530c10f26dcc2e0e8e99fc2e000b755e060ef74f739b163c29bc5232d2fb43c9b21b1deaf30c20315885009ae7ce4088351774e44f0d6b2e32aa69", "-6b2c12d1c0a5a0d42be1e05a747f2699a4b3e4bf81944518bc43e299c4fa06bf65bac8c16feebd9c154faea0e4e61fcbfc568314773dc9ecbe6bfd878607e8b8a36353ee8a921f65789b1a89c8fbdd772dbf5795145ae2de41ca1f6d2bf4afdbcf4b69399eaca951bad7c9dd285ad5f26682ea65b58406ca2325b82abba380cb116970a28a924421f8bfdfb23b72ca05d33cb35dd7dba862fd2443f110576a2149d1e3285521eeff059e1c23690f34732ebba0e925f3719ae4648e4c256d0ab795408b7fec650c81baae4c7b2d4b54a2693f71c9969c037fa582e797d166803cdf2be0c1fc1ff0bb8f6e3e80b5948cf9c394a16532382fa388a68c760f4093ab8ec4183036ba05a0a4e5418139c3ddfcb4d36fb35be8992a45d781aaf446aad83e5edab40b555d1ab2dceac5dedc3659b210337aa21a88d6331b6b37e756d7f8e6f88a153ab4902a782105f3605f98370c5d96911582e5fa5f0cc673a40fa579d93b6715dc18e7b70a8de244835203dc147f28fda609bb79535dc4640cecb99978f49e852884883784d2f6f630e30014f849114bcbcdc60f4b1e015ad223021898aadf9146d0f81c555374855e0821302e99fb95fe053850b23132d183f947156be46d13104b670560c7946431dd30c60c3f523c6b8c1bee65ec91497d23f7d55eb51bcc1527131285ed88d5aeaf5d889811b643e4a834f7557599ce4220b778", "5c4b0a4861bb4ce2a3f524272b31f07c8c9aa88bc6b1f06361293bb7e916074310ff81274dbdfb64d24b339589ad4cce629ebd871d881db66af14cd1118500687104b3a1e1669bfddd57f4c70649463f684a3c912934f8d7d3051e2cbdc089f71040dd408e70c795f6c6a902979df4dc9835a23e07bf34d328a6fc14fa6f7935c438f16f548dbd8a9165e7c58244b9798f4d7c907997f129b27fc89681515b2d5dfb2b413ddc6fe763a874e207871e7a0450bb36e8a5500d708ac08fdf6347acc5f0db9bc2febfdcd8e198ca24c0ffc3779b3a51e670bb57d8b3098d8e39459b73cd21c215295c6c9399335c3a86f22ec34348b27cd52f5fbea4f3e191ec218ef9161e630386b98fdf5cf2e800d73f15f90e275a4167c2e52ae5988a1bba8d0ed9475d1e9be6a0b06ef96fd7a004d3a95e368c1f85ac1a945b316b6cb74a0614db96031711c584de0d4d7897981a74b8eb82fa3771121686d689a8d72a2efc0fd62d9c9b31d0e9af28395c71bcc6be350763564ca4ea6634ec83d005d17bdfd6b551f163dce3fdd35b445f41e3930742dbfb4b4edbc3a5581fbd56dc5bbb528bd42f93f0647dd24cb46eaece0daec755c42b9ba87faf4469530e4cfb0742e1edf1aa5295f772e8e802f7dbbbd9a6a7b45523f594b0a2726527353232e8170c7afae30618295d43f50cb485c87b1d034e32e9d46d4fc4219a41195c5f31cb7db8afe469e4b475563f75d49dea840815b487a809289f043952b5e52cf6f8efdb9baa2e671c859d35c6762b0ec1e293a410b7345573c5f2c05d2b259f28ec0ce9f634863ee55d20a948a4b0681d88ef92d5f62750308f3ee9d171540263e84ccaec390842c5eeaad5c9e81b6d37cb2f7582e0a1ff3608e9d434d34c74390b323a9783114a0824096e7d7423b0c9de0a31d76434b5475ddc43f18adc34d373937bace28410c20b6a0d934fcbfccfc2c889ec7747df346a2f8f2fa4f340eb80aa351ef8f658377c06463d071e306b60b3f1404fd61f524828c7fe2e0d0c3d9b2cd26b83b4a37de5b00ace50be173dbd5d7e455c8549db7cb72b7cce84c804fb58573219c392c280101f71b72f07ad72411093f9d880e9b4f53f0bbbccb87000899e61618654551f2da8ea07c858d6ccf4ab6f6cef7b8cedf3c82b64cf8bb2949c0f3bdffcad9f0a88a6f1f5a292314e7167c130a9b396561b125377015f582126fc2c26d0e28f5b234eff2f789c8c65daf7a0a5dc3e85d255a152cd6c7f8ea27be58680f44440bf0ea6a7867db04b75b1ed7e6c30ab26bc548ddf6c3aafed3fe683a2ebe7fa9cd0b9d903236f2d1ba66270304855f96ebf95a004835eafee36607dbd4ec00135951bd731a26ab6007bfb6e270c921140a94b601fea02b5356b726fbc9e76fd9f0f7ec047b64e9b8b108376c2fa1d42b1c37d033e0a8fa0063eb0f038", .None}, + {.Lcm, "-5407f32c2a5453bfe68727df902493ff7e9b29fed9e20e10223196beaec7df1b58ff7d98accf13aa94c47dc249e436d500c366ed06fdc1d2525a4ec5e3c5e47f79cb68b44250a216d156a8c3375a2234ac90f262d2ab668cd7b044ea9581e43e4f7beeb6bb64c7e380f4ae15c1309663e627db0571e1f8fde522cb6e2ea7fca2b0194118ba43678eb58b765f8021d661e8856dca1ae31c7b7f3dc11d326c632cb7a6132da44deb6664267a1ef86040d91d14bb2d986de0d8db1709c60b96c23279b39bb10a0e7dbc26b6cf6aa46ae310ecca89db2306c498b6533200df6696ca5c72cdf15bbb40e9f0b942312201cad4e12b442cb99d7372c97582a342bc0305585bc0dafa2ab99002d5c9f1b67b5736e92a2ab5378e81e87474201100f7965abee89bae4965bfcc2eada382e6b57daf1912cf9114960ec0e7ed7b079729e3789b165d4cca02e207c239c12f2f4aee470a723dc36e498d31d009fb931e3acc69318d5090fca1399fdff47260620efee729c4aeffb7663e90ad6991bb17e01e1311d5ec8a1dfa51a1d20d1bf7846ab0829b35759e925a2a9e3a42046a49ca110a2979007593b54126c98ec42581a09c3a801cacd20a207a3bfede27fede68b5c182c77151f15d594a9fc8592551a1428c9da0f8e2fdf34491ed5aa5d4199364f6b297aca01f0b0642a3315b07b8ff40a563dbe5ee506b9a3212a9e1fe0a7e6f72", "-1865603e02a120027f818b0340186fa3a7e0af73baab6990d57a702c6c91458a1233a0a224538b9c61fa0e973e40206dd45ac17c793b9b8e5a8e9e6a2995e1887ac7557cecd89a617a2f380ecefdb144a5e6ecc17bc55bbf0c9410479794c4e89fbeb4530a0251cb0958e30d1dabcb4b1a214c22a615d7a64e6429a6a5405dd6b5b85f3538b038f7f5d8255edb2a298d7ab91e4fe3b5670cc4a6230982a28e892a2b8fef1b291d4b523bdc80dfbd134a760b022e35de05df2d28cfb1a2792e8a0fc0203756792c6c7e26020cf7e435fe955a741dc8575b296c4d7c952d6918993ff5c5611634f774c75fd8ca59c20f837d979e19842a30cea8f47d1cfd82aea07874dc8567f7074aa90c3fe78b2bf9b9c6151ef7cdbecd4dd109b8ea7993f4b4853e8efe1248e38a41cf8cc6f6137e1c03a4ddea72fac4060c5c4e6e00e95eff5c65c9a22a808cfad6ede0cd9ade6bbf9ffc5baa29804547e50a59be44b20422a8e249078353d62add8406988cc2b7823e64b3522c52972aab4150d7e4abc1a432a88a1ce3ba082d226c152f8cb80abfbe478df794a094569a60307c069f845cf31bd3e3f2bfdb45b58dd39fc455f5846593cc20afad2fecaf584c0022279bf20ce4633e399580ba3164822092f5f7fdee9aab855927fd1ced0cde4211849279d578935e0b917f7a4bebdb655dd0f430c9d28730ce4f7d56b525121175071798", "40102c3352f818c7fc9044a89b83c6d96d2da9e428ef482dcd75c2c8103b69b9d5d4f6606305398f002c178e97ba84c82a3fff13c4b6cafa8fefca0992dc6c70a8f54f570b53f265220a0b8db64dbd7b62453f68144c168f80c35908e2633fd45c771179cb526fa511c8f41f5375afdc933889b3f095781f7188f96adf571d45e621ae7b3b03f411094fefac085dc528d577c2a0b5e54ffa62b7cc4b173450b285aa64076ed37aaf57a1af24ddd5df200932a51ee4eb24fc43df9741257fc3c7afabe4449700d7159d1c00e0400da037498a81e905f606146d20dd2090d58cc8653d1c7c505c5a0748ac6e01f8adba9c609e5c95bbc600e6e0c0eb678299178686ccb86fa5b5585246b2951b54023b840fa25856eb3b4a85ebb6e9bcb563c7223706d16bb845efe82c414d98f1d946c4f692f0598f460c7ff085e5671fb97b2e013b6818474c12204ba60beef85b361f85a895e741fac71c211aa37cc87e8faa22d46dbcd49d0f0971c9af4168ec303b3f2c9383fd8d6545d3ee5084d1b469e5efc9fb1488b772c7caedce5d17f1ceaa24bab79a719092e5cc2487628ffd0061091ecf580ca1fe8fb40c5e77307339c21f3e1776c9dc097fbe2b49d5bc4aa0abc5b4441b89122853b41b74daece18eb0a473068fadb51570f530b768b79c61f1ef1b50aa04cf63c14d5c7905b088c7b324ce914c0010193c8e8bec9b32d9f5985b1d280a002ce4500720116ccecfab7a8dcbe16f0db9b1a74542672cc050b5ccb1bba13da4edec749f8826d0ac62d52caa620d7cc5014951eebeea31a262abc0c9686b3c5f8423e38cdf534515bb7e2e0d8873a3afcf0894f3f23cfb35df8f375b772ad61191f5cc791cf38e7329375ea0ebb4fe161e1017b25a9fcc41d140d1b92f9c7c09a36e876d1a4e0476da7e632178481c1053e0057a0f01ed8492f4b383b367603cd8d1b3a75e683448dbb927746956e9367d93703da7d6abb639533d9903c122ca558b060d95133f24b24394889cd7e8ada47bb0535a5d510b6591dba7f5207fbb81164931beb648861df7410b6d837eea77abf81955141f9a3aa384666182347053df6c32def8b1c89ba4064a4d0465e141a63aa794bdb3ab9d8152d0fc4b00df21534f4b0814bb7fc4184cc144d658559f49e0db22f7215ecaea09886ba5773a18ffee8618385cd39e8f0b1962a3df6b4e188c9ed579d7dfd40d26a8ae408802f8a64d3a9eeb997262c0370a5ec05fb4a7fc39c9c564913928eec07d3c0fa189ffeb2360db1752d5fc02c514cb52586b78dd1cf6d901c89b4bda01bcf912ccf86375994fe0fa92ff2086f442c645aa51ce597bc1fe95f07063aecd6990ba47c79904fa0aed790f7c3cfe3e1ef99865a8d0601089b2acfab53f53f15f56c7451a42bbdba9a624660dc57a5e694ead32f028b27f64fbf5ede99b4d8", .None}, + {.Lcm, "-7e2af2f16db8950c2d4c28e0479d0225d9277520f6dc0e5c0c4eacad548f50149a22395d54aee4e1dcdc37e9aa73e233d537b275076a0210cb28edb7fd77cb1cc5ce846a80997f8c7fd468601727d74c98de812cba47847491ffc4e4c9159c79ddee6f8108e9dcfb40725ec334434c5783149ceaee3a6a5f012f63014b7098b703340c3a76e54af276d8848181ae3d24b54c94ff1f02659d2e852d8bcc06de7f145f8a50db6ff97d170164a512567a7573d644acbf623768d53469e5d9d5b4a197cd9a7c2487fba0495074f183e734c15e32bc3ed8fd6e0e6dba7f5c75e29cd8e8c8123c7faa44a503c3141824dc54b062eac1319bcba9b32a964625cc84e84a010172bbb3b34bf44837a697f88d889fce4b0aefa0f066ab45d70130b6bb95454b9fb4d87660a89dbce84204a39dbfdbab616542a5dc7ebe340a7efb8b9f5c52de0b3e59c36db5bef634a3019684ac7691d4d04e004e9e587e39931b75866bac74a13c23dd99d1ca0afd34d32f73838e727527099e0bead455f15e2439d4d496d8757f36f1125f05035142ccde63fd41173fecc31a72dec113c49e9960a3b518f1e399da4a4fdcbb0c439e84b87cc87c11d2e18b30dccc172a4573bcfd136d895570d39874c6b78ef4072c289f353fc35ee5ef34c6c5a1770c86172a36065af2d031e4351efcc71bfc1d06dda5906e8855d571fe3bb4cc3db4c7a6ac8e9cbe67", "-f812aff3a6577e63db71bf5f346be8f333e458194c3278715ec423396a109084eb1d592f6f31c56308e5be476abed2d194f6a5483aac48d11b1718129dc7b404f8d2d81349a8225d7736dfa6b27f548001bed88f7138aa3af41ca2ad627289b96db8d16637cb317110b353ce6e0a461051a7c1ea7fc2d031641fa657d9fca68cb19df941f35fa6cee8e17bbfa7e2be0327298cbace4802fbd3ff44b83b34f4fdff66d8d298bc1dae041eea743b1e860d9575d21b1e6e0ac70d8db85b5572068a28eb49ea0f5101219161a3436c4b11fb4cbc463372a7a296562a42d3fc7a81c7b35623297f3dd002b90eb78c70eb0f5f4553dbfa693549d38b70fd9362740c68ead59f331ec6a54071184d962dccf600e616ad2b4ef7ae610cf7d6932acc8c8d82c0342d702eef5d50b556ae918c0274b671e72e8606b96c580958a13d19c39feab670ad503b0312de455cc4c52cecbd329eabfb26377f8a2a2db52db4bdf5901400e2abc3621b29fe88bbca32e1ebee4b6d977fc806c0a791c41e2c4a7993225e91a522ac43785b6bf141a2f29bc2f08da48707e3de45ea5b3f9421d8b693cf8ef0683d61259d9c12a767f5e0980f8004054fdfa8d9ae4dbadb8eff80486d396d10fe05998ad6a815357f5140deea3a7a1ef7b5705a2658fc19d3199763d916d7b338b42c57631761c540087c79087a27d6fb0a2402de4099aa48c95d3f2fd4", "7a42d116681724f6125d5353c51830e6744b2357f32b4619aea496f4d3c88ee58a4385120df4f8f0d24927a3293c8c1522b2a67b5977c0e6453800cac88813bac3ed1ab91cfea9b8c8c88ef85429b62624545d348beceee287862fad9e7124190b25605aa224b4d9560af45edf8448f7468b9f7e79196b1a1dc88549165be5bdf45de2409d8196d69fe7fa566d8a810672e66e2b11fa174fc7d591d1c607e1e70b23f4f878489783c0c52bb5f13594f332a54137355ea4f6eee0303f56576bfd57f46c32590701331371c6fe13e215ddf9c4406ddad59acb85024869a96ee587fc23c326492e518010d27b65f40e1c437e00323ea6b7fe1e61832de6504cd6c1a91247668e8b42dc5ff0909fa403a6e7491e10867dfe66a794727f90c462b5e56936b223df51add3e9f17bd720aa4e7d130e5c4f85e40402089ad20ff0064f0ebb71f94126a9c3bfda1e8557dcb978760ccab56b7df41952c36a39628d1cb730c49422cdfea5c8ddfe4d680770a9e6d39c3a67a7c0b074fb830ba37e1cabf7ee6203fc2e5389df0c67a04517ed984807d5967781c75d0f20cd7006c4305ac7571ffa96cb43966bce46c122b646276d88427c9a704395bb1d84fb61cb62d7fdcc629e93ccca16488b42bcb9bc2191740903b44ecefe73f8b18bad3a796f3af3250f22dd6c5f85dd54bf5bfb8cb4e426008e53d1e6942a8786e4f01f76a830f9c13905addf9cf431526f1b596cdd6edea30e8c14a70af097f9fdc96a07f6b9256db944254953ea602fef479e6c20de8ede638b36cbd28cccbb09f70fa33c19ced2f39282cdcde2491c02d5dc1299c79727e968fd34cfa420d81c7f3dda8905782d53ebdceb384698e3057b2c2791270496ede5de9465289e575ae9129c02f5497587d1058f09928269eb55bf2a184029f2c1c408976d1070c8afe91112ad5aa31eebfe59f44b9eab45fde4bd248d1eef606ddd5a44a5082548e26f1dd6d9455d501e960aadf182f4176459011ccfd6d8b1e3f2a8878399d7c425d613f459a33bd291e901d93535b2c8ee8a0e872876c79fb24f6d4d9f40050c162c66ca76194c242dcb678fe0f2217ee4c408a8178470c1247a078f926fbb208d99f0f4cbeedc095a24859ea64439aa1ad69998d9f1924716f7dfacf0e10790487edb78aec7c8b22c4dc59f69363fa044c25bcdeb01b96f1ec9b304e187db4b9ff489a83c1efc0d0c2e1132024d4dc6469fdc84cbecee9e4b9a701eea7f5cc3312121c82c5a4648ef5b0e976520efc16654ae8ffd2b05f7fbf3fec34dcbbfe7c749de8eb2f5d3aaf9cd07c17a7be06e1f53e84afc29ccd96afc688d6d35fe80d82746ff46f57a1aeaf90feb8f64b8cdb9f79a8de0f18a586cc5ca8bf2080e94b1774761635e83213c0c1bce46c42ad1b11a03569588bf03ec1f6d82c5a42f331f3a35b2271b964c", .None}, + {.Lcm, "-4805bdcb52963392f2d2d6786f5ddfe065fc3a075470976adfffab4fc5f89ddc32dfe558ecd9e00fcdc94f8c82ecf99e4af98a1aeb62805cd1df086c65178f36a8db3fd40a35c8a0914dd2f7d9564a00a507a651d4d9a10d7c356519277abc5d526e9c86d9cc2eea7b2a83fd9d02344e52c8a260c73ee89336de3bb911adf684e19863d31e6a0ab04c68d54485faea775aad6722468500903e4a6cfe9966e3bfdeb30eefe63591850b93ef42a08573d8768e9252536ee7c4a3e44a4a353fa84653fc6265622ad6d6fdcb8d25fa971a10f2e8873894a87ec3a6ba3249f2b3a789cd4ebb078284023413127bf2cd1969b03d9174b35ca2bac348ab4290a3d1fefb1d9e2a7414c91c72803cfe677f171595d9b6cf18feed3e06d274e34c1452a22519053055966f74681a537cd8c2e32f7327a0eaad7d3fc1e827a16e252b1b52feded0940e0f25ec5e07f2e5dc835681e4978a24aa634c90157ed115dfc0ea1c2507e39e4032451eb5eb8e50e51f2a979358db258353fca1279aebe0255807108f1ea15183933be547e634346145598cce05ba0f88810f1427d5958200f7fc96b33455e5da43b39d95efee5e7f86c36ba8c9aa9331119ebffb5cd8ee42c0b51c50186b712a4f8cbc14edf6a66173b0d10454aa5c9b328aacdeebbc9ff54ad92056d380b2141a0eaca5c0ebb0f46328a59d352eba606e43aaab6c20c9254fed3b3c", "e2a3b0edecbf48ffc556fcd9b6adf32bf6e28c640bc7f754a211de027a7642d8bc1a216505ba0a31a352de56feb6cf40a931b3b1d409838844f536af09f19ad101969591b7b5511ee5c330cab20cbafe0f49a5f9926616fa1bc049759ec061a2ecfe9ba1a5538f2c0b2721078339d5d6ff1c70e7222d57323c87cc165cef4cbed0bd74438352a394eef8cb0c9e0dde9b88c2100c4609e8af687ae8be08acd4d9cbd8fe89fdf905232b4641304e94cff5ad03f89bcc68700728191f71c6e78bedf81386f260e912aefe53973e18c87858bfd65788a26dbe338f8a582d5cdefd60ba3152679c89ba5fcd32ffa50865be410b28536d22fbecc913a9fd1914cc2719f085e470e687a1019a3f69506af06487e537479828dc5f754391b4755b5d33a827a75288d1fd920b929532d35d5b43f97d62f6d453cfea4d7c35479bdd8d1178500de83bb81ea3615f4b1a139c8e9fdfa50d3c61e5e0e3e20b4ba64b9623006a8211fe319c39c01a5f0a38e8c86bb6b110bc2cfe3300c28587a430afb26f442e20eb6fe29e56847fa878c0ab2de06515563a0b56a7ebe62e356771893da633ef8e250c26e28f6dfc20c64dd885c226c94901787be3a0f74ea1cf083cf5e6daa99b06b7c289ee9db4518b5a897c4be0013dbfdcecb687cb3bbf59ec90b3d0d1b04964378ed7d06a668f2c2c440333a2dd1cf3a95088e2c20e229a1965e8a7ae19", "3fc31efc39c5c8f6e6e4ba0c3631bf2d6599308490d9ddb1da863fe10557f6ec3eb2d4d44a3e2f2134ad72f51e0f6cab9ecfa0bc2b2abf3ede2e0e6a0bed0ab326596feffa6b8126a1babf6df7bae8a7525dc127c9819addb9b6511cf80a7a1bb2c8cd512fab4a742e6be80f301f5bffaff142bce4f0a4f7d62c28f27dd228bd811d18d4cfb44e2ada956a4de4ea09162832b3e1b49d7cd628eff48cefc596228da95eea162e4f89e96e1a192a3440f83ab0c41940ea3729c37c6127194c614a412a95269d82eff766ded1012d66b9a77f90219778ee5b82dbf025cb481f60b380194fb6564b35e82468069f16d3d9f6a9f569dc3f0f72a35b178de8c9f3e02540692260508eae97d681180525714ddd426759433a584d1d1b4c957830725b0acba4ae6783b4532a1ef8c7cd4db72ba6fbe5ee5d17bc5a522d69bd1acfdfd399be8ba3cf0a024ccb53211700dfae14d704d49a145c040b1f1217c47277a5b14b0b1e7f6ffeede50e626a13174991e2d6289a08c7572476ee20a5d409d8f5581a2a8ad3c529778a23bd33b0e702b19768eeeff24f0e633fb87534d311cda7b32fa33fb0732b4a4910becd9379564151753cee9ff71b76d1f0e4cfcf0137f64779c9e2753ef4e360169610fd73995f13cc4ca5fa745f8f7c55ef1947735a8a2e122b6107779ddbc5f14b3d5d12b20ac438a25b97d72f3c010bfc8804e7003f47e92f55f4c8e773b0c9604b6f45ebc361d3c4f3f0db28e4bf9c0bbbf73dabfbd016c1eac987aac00a85f798548ec357581853d4023117ba725006db632380b3ca6b636181c4526061c700f07392b14b4588e6d70158f8f946ad90c990b377daa91eebae2cc7e7bc3146ae4bac60e166d60c7ee1bdf63664c73d747fd4fdb54e39c6d40d5b518cad81fad4baed2c56478bab7fc07a2dbd20ae2cc4606e9b097ee3a607d3818c396eafd359bf7a2b689a6469fa73090d97c080fdb6ffadd81af8b92bfddef306efa28b2607a3478172e8e891330d2eac9fbd6d3b784599d0659a6aee8ad449d8a6fffa95276eb828a8cea9ed7df4fc298b15520d65c648ba57b5607e43c4fb82daf59daab250d64ba57ddaac5c3e00b27d9e1298cb29b89781b13f37b2de60f2674c8a86ea52795a19509342367e3dbd74aa7b39a82ef23d8edaaa580a104b45813cc9fb2709baaad65ff098cbfb599f6d0bf3acdd8867b6b68fe51cd02f37efa7b6c0a7871b01644da3b6fe110716b541d91ebe23416aa8f1559852f724d107177a28237337100c53f89b095a6503bffaa1bd1864aa6fd91dc3abdc6792c7e1737d225e89597cda945de2c4844eb2c9928cdfa8bbb38a36b0291a1026bd9e0e476bd8f56b0f63e983e0926c6e33375535197736ac995701d21b5c63404e09efa72ae8aecfc016f067d0db1300bc750f94e5ba4b2d2a5d14109190dc", .None}, + {.Lcm, "-cd8823243a77f095da67f0a4a585392e95b7d1ba83f602e56d812239255b25dc8d03fee344514e36f913db613a8598e146f940a3ea33c036f2c22ad722a5fafc0aa042fcce341cc7b83a574b3d6b5132f3ebd4529821fbce22120ac956900383e734ab0e51803fd1e0370d4f4647494b35703e70056f609ee03ad2e4d69b7bcb623e28d09a6ec0ba6b21a1677a1f16d950fab394fb772744de41bd92e93c0a2e4ff8a3cebb5bf3b9ebe00ff7d7f111d2482840cfce4a68371ebe6c230816ce8723fc3f3e001c30e8d9ac4a212f1568949bb1dd8013825af8873f78576a74c7e03f4a0b1b27f45f760d108f1369517678fce4ff8a3cb0080e71c724b39aa632529d31c9b6bf2e99f99e4f5cbbefd3a4feb28ad4ce4dff8a70f838ebd0f465ed7e471408e316f84460357a4698f387080bf8cb0de33d5d7ee533c1436a0e3375f5d8ce37694e7cf5a6b9f67cd723c633566a5a6ffc986578bb9fa99c875a49496a9daa911e26d6136c337de67c6b03406fe36aa9f8456d19d19897985ae3b5abd095fc34de3315d4c198339a95c9af512906123b6f04fb9c360a04dcfc7770d675a7f074b9dda1871e3b1a9ca189594aeffed24f5a7819eaec375b28e3a8e32dabe6d97a04ca4f0f6f490d8196af6a77f4088b19aeee19b223fb82019fce8aae912c095e065ba735ab58e79f69d54681472a2fa2de0973c5395eca06a063472286", "-4c7f007b5475ec8a7ad4bd83d660a6c34c326c963a07c2c03714ad887c95a174e5b2c1f7260d2f3a01ddd9981309f2acfc117f5b16382dbf5b99c7362a5ea96b036f00401ad87a999451f0ae58023777922f43d5fd7d647448368f8ca9220eec368b71e3211f3673d456049bfb7995d663f3dd7876c9bf12d47c1aa5b26b7f35620f7c23576e4bca33f93afe34dde6d2bb66c14b68fd0e4eea955ab36c543fd9ed7872c1354dbca52b3fdecacfe476b16f06c9119239ad092a023682d9949df22d2c6917c0018240c50372c303ee951affa06e5195e7657a4420feccf8feb203ee38cad970f938a16396946ae293ff6d957952651c8a0838c9c6ad20d178977f77467af276922846ad8f3c76b261983db3ff1554a5bdc42dadf434ba508baaec25aaa7cd30bd10643d06a008ad33eb857eb8e1b9e163dc9f42c242f96cc11b62e7b9e55cd3a4eb8db54d7296d166e0a52daf5a9412f1d2fca67f3d8b0a8edcfdb2290da3ca20cdd9264e315ad43545d78437b6336bf3a0935c007495fe758d6ca1062303e40035851fdb57047a4aeae5b299e63415a464f2633e2b8bb4a723859560485674ffb8c319854cd346ff2583ae32ee62432d27e83f16635dce0184a3b368d5734263b54e91b80e2fd597516f06d5dcdbc69cd8e7bd44e64852062912d917115c48e4b03cc23b593346cec246c83920b873ae7047b24cec399c891351", "3d6a615b348cd7fd8ff2e5d521f1c0c2f04cae5184cd3b346937f68bea0c0dd894ace745136bb3132c7abd7b8bee70dddf67d152708c758e3f8bf43f575085347b49edaab8ac519e39ea2b973e629a0dfff4593b1a6e223ce1f5c2a3fdf554d26f4760e5fe830cf88e6d978de7ce94c3e7fffb2117ce23ad6f185bab50c442b6a7684cb35e20e467b4385418d3a7f431d53f8f96abd70a3ee7217b2a5d6cef5618d6f718a86e39184664adde74085c5974725c6ee278cc5badacac492871e1110be5826a7974925e725c5c145a0412d218d6c364344f8f3c870ca4575822c57c7c6a5fec44fd7ab79917198b4b54bc050fdaacb7175123371f94ec0da69ee1bf3c36472011ffe57d797a5e386bc76bbe37fc27602dbac3f17c4d544d04f9d524dc7262399873325105079f35860c36075a7d618a1ae7a81d713465bcdee9badbb70b175fe0aaa82dac1da4140202f0cd59777cfd3a983585f66bf45e044b77d2483f4b28cce13e9fadaa63e8fd6fb618077e663f36ac9648ea1b1f4a28b16fb1cd567c4f6788e09606920a6e1d0a2c0301c4fb42b8fd005f92721f244a33e1a099a2a25ca3e6ec8b223551fff0a82c4d829b50595caf96ebdd1bb068deb62fee19c0c9e440ddbabcfc1f72227ba92a5a82f17a10a87850bb029b60fa0048a0a908f7df7405e8dee31c09502fbf7d7b3b455f444af5756bfd0b6d96deb9b6cd1be7a77bf607be2c4d7cc983fa699a845c9caaea5fa494617b53c6666a6af411fa550c3f0a805a23125e5bab3ee1c64ea45e95f543334bdf1bf2121f96ed201d41e782818255523f4c543f03959a2277931bc70b5478aa2f7c3e8d169da3999642f8962b42fc148af82aa39354aa62272010a7f242fc2a300ae08ae5f413b8246d2a4a706936668bacf50d54a281afa9a5e39fc3f719e950b82bdc6193b665c0a75bb93b10ebd136c2572aabdb868b5db97ae586a42844482476a29bd0e4707b7afb9959dc64713c3fc5752ff36083bff73430795f22cb2647503c9230cdaf859ef6e1791c58a9d29aadcde90f05a050187328025726cea66e144214d5115cd0c0a569497c5c2eecdc4084af07b0450069ec111cc1b7c1190876b32960a10adf6dfd682a33641d96e6ebfab33b95c16f9dfbbf3d558635dd27c070b3724a7dcb72911347866f8d0005283c5a0e4f56ae5342a730bf92ebecacfe8eae578581c8e2f143239088a815bb354ec5a282e91bf5a019adfbc4b9ad1b0ee51baa2ece191905332a0634f6bc8c2b2e39d7d20d642a515e98dbdf67b4dfb14011badf0fd84f3b6ca881a5127df9c6fc3b65a9af8ef4f8d13c5e5e8d23ac1adfc8d9d264cc7bf5d4536cd63bfa6f20fee6dd9dbfea0ac29c94a917f2cdb5941056d815d719ee7ee7e0a3208f4099aae731a809a680da781908ec3d60f6dc5f30b20ed2c7de66", .None}, + {.Lcm, "-e6cfbea70557f3ecb8856063177efda1d833c8dcc61a818cd51d7c2544e988a9e84f4061cfb7c56a399899339184b0848137b893796421f7bd1ede48796bc6c115dc5d7319813ef7d77fd65cec92d1e1e486199cfe3111efa1551487bdddc4cdb0067b66e95f4b4b6f791aa4d36de92ded4a7a1034a1ab59b95f15af6f1aa1b8da5f1920107d8a78150e98bf1a4f77eac5b7814d8a352e19e08ff633a5a0c0f48cca1c22e36a1008959bfd571121313f5c25bdc1b6d8f6fd4a196263950e25d67402289b37a638d6f3c7709a07cbe11602e852cb1296efb6b72376974c5ce9b217732e29d216dbdd4f0f72584ce82625d00bc6795840e2030e87b81be11ef49a7722a321c81aa9004438d711fffc98c0efaf216c784e43441c87af111ee8fff1602649c2f48f954f248415b259c715ea6ad39c46d96c8eaa0717d327dc096e22c001743d226f8b8a4f30c4fbfe0196fdfc5ca568401a81e5d12a18a286c530101b26da680025b2d2d76f9eeaa8f88086f05783c57f19b78c4e0bfd48455dead3b66816903a62a3d95840fb83ac10c2d00a273a6ac348ae4b06455d84a86098fb0cbb3d5d18838d84b17db139a85f7f834d0de283a17cc569417f5c8009454b10e0460e187c554fa6842ef9fdb8ac0a50c8b5922658c61ef1b332ce82d9c9d090bc735e844f252065f85eacae8167a1c952c1befe95806a496c1dfa596395b41c", "-b5328ea57c98bd560f6f85f457eea8e36c7178013b2b2bbe17e3f7106c6b253944b9e630e23f97d4d11f9791d49f463cc366053bc606d2b8e4b2772e1780ffb8f21c96a679e17e14cd1027f7a42578d1d7705b94750bc4cacaae646457440d470a2b3fb258e71e4181d73b3a910987c1e5fd607cdc168b1f1be72947c3a829c15fc1ec496ce6a8b424a71e74a7aed1b45bede3e8b1aee161e2275d969710c85e9624523679a8327426ec5051baca4681fc16190927f7c9c7d4e4e74a2001339162286016e925b8ce6d35239b6c852064f79f8c26f50c1f7bfb557563e4800cdd9b85660c0af074b14403352cb5272db733ab026cf4e8618185e52e936f28254beba3854421cbb8b1b48ca4859e7a2fae5560a57bad1b169903b59d6d33a12c3009899041045aa6a0c76cb0df6b3a173dcd3da45c22e2bb82ffeee3a9a4707dae7739b4876e6740c9511fcf5936f19b6b53f6528ce22ef25e2a0d848312509b0aa5a8d13d4d7656ced82ca19f83d2aa14d9a54f6813a05d4ad5bbef4d6d77f28180a5027d0f74ca139f55432411589cf83d2aebfff950267cd4c12c4de662cc5e69d886db1ba421d78af54011a243eeec2d37f53c790ac5ee48cf2c9c47355845bd967cec9d876cf33de29456f3406cbe4ebaa233d747ea6ac35bc195f6d920cfa1dd47077a521d0f2651f8759e3613ad89edf51bdbb95870cc571c72ab7658d7", "a35e76fbc36317a84ee7b792b40713420b64d9d3959b4b782b31adacb57523152bb36f9e01b8c1d4aec31fa6052537fadcf643dd910c5db8793e37b9b6c56277c6cba993105ca900bf69200ba06f1f2e08fa0666ccab779bcbfada444810b6125cd750511ac1adf1cc7c6bf3ecceecfeba1de1d05646df79a8c89a894f477862f02f6fdc1cf00f47900b8a300b7c2918eabdac570385c5d9f4c3c4d64aa50bac74a1515727199e604b7eca51d32782b4582521bec27a9ea8163e77c0d5a7c958602265014e8d441c10d34c6467f7e9db1e7ff51b4ba09125777674df99d306fe7d5c4cd9d1f35f22b3061671934b870b2e9abfe07229a52b50927ab2057071f1dc29aaf17b77ad11f50b508ac1f91449f373372abfc6fa4c7d359400678e6e50735fba4e61ed6d548a8ce62fde0ffb467d06230478f9fa1b87cd01ddd2c84f9ea50bb040c5cb4ef9569be2ed7383c3cdcec577578e0a8c587052b6270542e7a5eac8e1c432eb8ff7ef6c25885204809db20d2e3031c7eb473dc80ed78b2fafe6106bec9c911832ebd53bc6842c6436fdd79b1212c53525cd5880bb7e71d4842a635b09ffe9fd1ae265d712927128c2ac17fc695421b2fa0982e87755256ffe1f5304ee6ce11c040d061b879db4d6dda1c458cf8251921f04b7faf8ec30ba65f64ce9ccee36ec614c1549e5e335e6ba74f488ef1d513682461085ad7dd2f4d5124a060abd19690d148db66d2cd60b9216a46dfdb1136c3acd3f0d0a3626785acc6f0206525d45286ff2721df43f5fd73db84bfed63caedbe79bdaa93a285d00556133f83f646fae1fc8113051bf6433a0439aa687db14615a9b9fe0892b48f5e0da34a0510321be811ecb28ead7b1dc041fe0e6c67631f6c4900dc97e5c5becf3b90e31a6a4fbaa1456ab713bafcc737ae34f4ebf8e8df189be5286df780e91c2458bbfe00d3f28e0c8c3e78ac2ae2ffb062f7529ac30fc9e10c6ab5b4330f51d3d124995b62d107cbb1d7c7db21dc405fe10a550083e9be9fdebdfaea50bcc91c1402a8e3651168efa803351f297888b94534b10c57f1cdf7937c7db2feb1adc85dd49645cec5f96e483dc2a1198bb3a3a387028caaba9f26d4b5d8ddfe9fd07efb923bb8418cc29b38dcc802f89a1001dc313d5d09d2ded5ec574ac16f0caeb05451440ae6f2685302a0295a2f82b861c6b87395a2ce25981f791f6e970d44a06af4e681fdd176e0c7d6354b206a3e8979cfc12e7b1847a21d3593e5cce24d57bcac9ab60c11ed952ba97d59582b7ca65ee9bb81d4d137705997e43c37508608dd86e6d7bc540c88ceee4f9fe9543ee38601d073e3183ae787155bb049f986a410e503af102ce1df321003aca80058b2ca8d99b8fbff8b9dc95e5de4cfa03c2e7582867a12b082c9741b365ba0e3f38ef8aae269c8e2f3873d62615d18be384", .None}, + {.Lcm, "e99cd7566f1bc5fe04def00d3c2d7accd7c844f09541ab8927bd394a10523726fcef0a4a194bad7cbd01af0043c148dc71a99ef831d1e6cd65488eda5848f2c369a9800d5efc3da057cb7895474b8a6d76fbc01b8b5463666bfa2e13ebb46904dc01b03472b9c4e039c7f317084f6a4565305e53cbbb708d650ee3a493ad854821ecd9491e63b1b32d8d8f64806924487e77d3c732d05cd0257164e950ad71556b626aa314825996efdd3a5edc8ce73a2282d0ebff3e08e871da18aebf9d1e4ed88747bca68a918cd4e937cdc225a09f8cb1bf9b7cb6cf660d907bc156a0f338c2b054375ebdf12ca417c532ad5c25bd929a12951438663ce83eef3bb4da05480e02c4acb3e642a0352ba853f1dacbcb73e860e45ddd0f940f882360433f15b9384ab33b96433ff758d8eca8d46ed81384513a28f5191b30835b450b8717e3a3dd523515b0a7c2c1e592232c963218e95f22496cfaab74f0212bf3a61d81eec9e86c9abe57f57a004a0a26cba4d662cb7421db77a8613bcf6a3de9b030d64388407680e446f8c84120439288375c2109e36e351a0369a859938872eace4a3f8e3222bf5d8b784ab674ea59f4a8f789c3a9fc387019d3e6d0411ff8d3776a416e9bdd2d2e36e5a3b478025104ec367ee8a95514e6e9fffe88b38a2ec17db130b48d8fe01e168b9efd0e43966a02996206069e21453ea68a735797943de94ba72", "-2d1704c8d2a30c6af1058d6242db473d6a49a25295225c36bf2e9f23239c35b68acad568a0870eaeb088a0d06d453f601719b0a79fc83906083777befc00d048860866d4cddfcf14e8329341a6e93624c11d24c9811fb769c05c88f843de2c5940278123d32945fdbe8b929d4881e71bb50a15690f42aa37c3ada13fb633f3a7841364fbb2e8a1ed510774a183fb434becf5904718e705854d5619363596a6b5c0a29da64da43b89ed9bbfcb9111c128c8d84a9797d0e8635314e1e60ba8893f976a2e5e256bbcd0f8f3a5e13a7166c894064164860b5715f7ce35a6a7239d90740b4f26adedca3d53be99b9fa3b3acedee90f0db703dc06357a43738f363ce07e6be78fffd9f4052734d84246ce017481b57908c0ac7e6798eeab1b0e05827b83ceed3f33446b9cb8a97ec1909e1de8fbfe0aff342d70eee3bc136ddc29525b62aacd4ef714d28bcff590c87a2ed5727943960d8cec6d88241389f2db6fea19f7c3b32e43cd50b34ebcb8350cb0b1e8c0906d825ffa40f4ffa5be0fd6fa09ebeab986a2716bdef0d629500f048dc9df3b6107f5eed0eed9aa5d6c189fff5ccc2de4cdfe24519eeafac4e1e6b2a94f4678992795a1c3d5356240e6edbf7f6c5c129e6b232e53b328efefcb50b5675b48fac86f3d780a20090ffbeda2effd9d9740e347fa11f64d4be20ab4d8bc3e1c3194ec3c456effa60abbdb129721d7c5da", "1492c9a7a03472b350d05e53c7927492678556008f1cd1dea0c19a85105ca242b19ee7474ce2b5aa7222f5367197d5e764c531b65d22bcf4c0fc5a0f441f2666078d86c8555d687be546c90ed5309f11895ef0226fdb728b02c9c3c0f5ef5589c14e5f979f06d56501966fa7d5d87f1daa2aa56a11ceb2f8f3f5ae47d3fc674b84131ef18993844e49df588182d9d9ad49e07b89c8375d40fe2389ade09b16b332bee0ff6e1d9718b07f57a92beead47a42d2046e2e3fc1a7ed86a655aeb014da7d0c4a469d0eb7a008a1c6e8e7e6319f784ddca7caac0933cf9c745bd018948cedaa9a94a8f91ef343a568b3acf4f62d3b0fb08795c6659b07ab11656f1dd0de4beb8be612de72793ff8624f9490768f67e4f0a21e209c15f8efa5341e35c328cae1bdbd4d804f24a91238932da86ca96926daa24d575a771aa356fee167e9a394d422d577a1507de8ded12a59fd39fc33ac2aa8c8c2753801aa2e2b1d5745d41f84205bdf0e4355e9202db209e7279da10cfedf8b133b5e8a65dcb16e8b0b90602f1b6cd3981483e2aa4733a15e78cf95a3bbdb6d6ac0432e6177dd7f0f04d054a3ed243ee5c844b6f81a0461ae083b5f43e9b219f41e1c0ece654b37a10a4db7eb60a43b25e287b026156a13cd81f4463e2de1c77eb7bf6c616677e3ef5a15aef79d6946a21d678e4477ac23c315ec7b551de3d0fd59830c60e0fb35913d6536e9811502bf498de558a0d1566898c2acf97ae8b80064cac2bc84d4e0f426bdc8142fbc8c14f143afb3a6a6c89467c5f279f18bd8bb4287e52445fac9c833e78e41011bdc0cf973de9b2b44e00dfaf74da47cced428992b7af1abe9e63392dd91b68b5683318945d436f2db67a9fa0d4c8bba3eba7ca950142c6d36e8d022cd9dcf32cf10134addc55853efffb80384ebf51f7d2e9d3724aab031602274f8d3c69864c044a5aaf3ea4b773bdf5c7b821b1bbe09e8eb528d82d41c52a40e3c5d2edbc203912d838b720b92c19e0e6486b2b64140af91ec997c5bd316bb68ad9bfc645ef074a24f48bd015184c31016750bc3a91fe255814acfb3a648d5c3b02dcd7513656116d3672caa3a94304fc637be4011f13ecb936b6f1997845fd8829a0667a5ab9517e2a6d18c838bc0b462da9b0d073dcead579070a8b03a5a21318b2cfeae403805ee804cb2a235dfbdfc5ea29676f11c6f6f7332bef3066785f30e9c00b23a8e5260e4b9a2b25b5fa744ddb6b2729c63e24f0ba8b8e8f87eaa389b44f76dcae31839a9cebf9ea052e4bb84a4fea87dca3f0fdde2b523a0bd90a5d4fdd0d8e0a06ef4a21e7baa96c9836b6b02b71605af40606760ffaab65298110171cf231169ebd8aeda327f56920671c83096b183d74c5a59c0d701c30799f028b133ae24d3cc0e4168ed2c1e83891815a1140c434775600fe7cb21a2ef3f8a", .None}, + {.Lcm, "a5a4c2d0b4458b874d5825e697d7951d695144af34ca2166ee346bc47a4e9e8a7e42fe5410e53dd676d2ded601aafe11c5ed6c8fe2e2a2dd94c46fefbf5ac9434639bcc593da304b932707fe52b07baa315e0d1ab4ab8403e706b1f148936cbcf21ae22bb251f6b5a91d0ffb5ff08ef056352c06e9c8e3d27547ef1ae0c65118748b98ef2ad4f2f5cc3f0379839f5ee7d725ad12c4ee555633195f887af1b3b92849a572c9ca5b1ccd936f2a08effc2aa976328894deecaab1f26f9ac810b862e6d4506a7f4270264e0dd005e61d4618afe5279541b6e692001ca62a46acfebfe8e3f953ff03a1e25c98ccb31f727a84815968870f7deda6f308c1d7e5d36f39cfa85c56ea815abe62c6ae4ac5f3cd77dee8cd8974ac1219de1e1866da710096e344f8b4bb8d609356fbc3c4ad3ab7a65ae7861e4b889505ab90bd8c5dd52f9ef2082bb1bbfff1a4fad6739eade3cbc11d0fdeef10a195f20e3d7b9c9135969d9055b65dd8895bb042b64fd2909d618ff7dfa39bcec5b6556a0b0aa81d964d2733f60b67edd1595b6e33725d1e1053d887e014386f6e0b871cba44f86232f927ebd21f3d3cd0213da2b6a800856b3d5eb73f077e97dad8bd98c4dcb08bd807e0c6ddcb00f80500c1d02e27ce295fd96b080f90de7135efeb5861c8f5f7ffb8531472361fdb50e4eb7fdb302d19e089b89d73a04b6ddf0eeee204b33c13ddde4", "-64ad04a77ecbe2987926e6c5a2259d5fa45745fed56f7604313fc683f116ffa43d9f7f4f24424ed204b1c359d325864c0eb7a5caf0d583f9850368ae1afe8dc3e0a622c40af0d7af1cc2a57ab61cf345e18d56d04c18dc6f7ca4e4c2a00e50df4abe0ca5606ce696b7fa0b3dad532d936f914bdef938eccd062d3c16edd1e2e5ae79746d3e0dc1f8b21f52002ba277245864a8c723e270c57dc94bfd29835c9cace07c8298982efc96cc9233ba2c2776c88d25514f0e37e78503138885eedf4b12456efd446751d14e7280a13f9033f65cc23e8a592a127a90b87d4cc865581eb53e633970af78e0d63a7644e17eca39fa7ea95c19a446a68722095f038ec188991d3b0045c6eb44a3006120e0aa655d177bce0b5b2fd8c4472fb077ab0538b19f887192ac78a5d6055ce128795a2467a4afceca740b7cc5e5ca0392df1a8637ccbd4a2aab6a6d4f7f2cf2b5c981d92dbed4ae4b822dbbab003fb47ab2551e0778c7fa460abb1dfd062b4f3ab429b578054131830410befc385d160e323a30b4038b3c0dba604be50f02b92cc272e388461c94d8af8e59d5217cecb75b5661bd24ff73dd1f7a5b3a258813f46876f6dc66bb17d6a5868bae44ea49509e2357cd8a33131c4a9a3a7774e2a2ec55b8bfbd411d327213de7d0972ad1e8cf5f122658a8a04057ca2b4d29c4a9c983928b137c14e1626338d0e19eb4e4ab8f41e6e15", "41244f7421065a9e249efa96a7fcd0a9ff13afeee52b3fbe900974f441ef73f6f8d1e3aeaeaaf89f7f7cda4b8258e6171a6406551a954b0b84f764828a46ffa8e10933e54c5ca39ac4659e3fbb97366ba7a9d8a0a242390b0272e20c45ca1fb9713380d6f0a2e3bcb94336069f7a8d6a3cca342fa054e25c9fd3e3967389c4fe76419b61556a2c7f483514ea75fff97ab87ea5dd40e6f3b8ff501fd528e33a5b21873ea505290bfe9519fa7bb6e452ec1fcded39e5646af29b538ef93b95941976fb5a830234b3b61b710b1a9b53c1287882e256ff73ccea678c89ef918a9e3cc71cc8162f9fdd0e949c5311af5b48bbd56f2eca5905d10c7f8d6e614787143056db236f0ca721d44f579dec339903d2ea4896953114d41e73ba05d9b820ae0311364cfddd1f1ce6b3a09104a2b08446b245264dc60504abd55120b0af48d8f4664de63ff807338c2db2f25fab9f3ab988020f035650cffe397dd4e1ede12dc8a28957631101e573600722f2ae2e35bfdb92a1cd8cbb24ecbc9510f889762f7a3b5615ae080e8ce7925fb16ad169a1e1b4cbbda8ef0eb795ec7f0e485c6523d5750a584281c86d26db0722059515e9f68ec168fa1a9da6a754936caaf5d4c689978fea240cb8e9d4335d8529e874b378cd0858402b286162c9800685a9829080231bf57ec742ec1cff6399a072dfd73291171f5c196dae930066b01835a8616bbdf5db59a0d9504d6ce2042dc2703eadb1b14eed03b552f95a3473d972376310f48295ef4f064b7eed12b88178682c53fdf343a97d0622e5737bf3d39004181857aa7738380f619955860f04d9a00428ea7ed8fec626d5ac9a4da3088acd80450d0e6fc8da132794e031c7546b3857430f7dff517164016cab0ea725a84c4b0028ad48329cb2fcb03b49d753f234e4c067beb6687d16de93c70cb94f2cb37ab361846f41883505d31ff59b6b6cb7dfaa50a9ea0d6021a311543930bb5408917c48b1e90c123df44fbffc5751e9a3662ed63542a12a782c0d0553ce3298f7c0e4676ce71c397a72895bd3186f2b2632b28557cf20c8e38028d1475c178b59aeed53db72b2dae6f5c69885410f3be8d3734b92e4f07e086d6c74487586efd4099083b29f2ca8f0cc928f17a4e7f746e4dd4653616356a82faec04297a64d9a1189973f11f91aafbca3f066252a9967724e3dd356b21cb42f0af7d9a5c7f97d5dd53b202c2d332ce7e1453a1d243e007b088680ba845df3e3c82b0b6896aa01c5708c4cea9c018275738fbf170fd4046768dce22f1002855fff86c43c464398c23f8b8086d2f2f11c2d63ab2c5f1e2919afcac32ebd546af7f2268a5aa699f653d2f214ac26c36f4e1c734362cdbda41bf3e5f7c0004fdcfaf59b3dfc94de8fa289bc0e05bd99d6c6cacf173d6b9f7f914a8faa6cb218eef3e3b4968e4c0232bb4", .None}, + {.Lcm, "372c82261203ee5c2b3f1cc5d10975b897c468b5f2668caffa057fc4866de4b8d80a27b72b5923cbdb09a56706895f96d7252f3a50b565f5d602f94f2e553b849bd687a9fad0158a5532e731b014c957127f24854a76e38f633cd3d84b5ec2805eea00044655f89df8b2fa2df145b60808acad6b7c3b919fe5fdd84ccdcc1ba111c7adff5ed1d410b5a58ca8ead5d38266693c6183a2ca7414f30f4c03f524bf5167ed835314cf986ed0b197ef417011b6081d83959bb11fe49f11892203049c8f5f9234360a5ace368d5f959249e06c4403f7cf40fe026a62732bda63681662d500edd17a32927661fcb884a9dc817b803070b8a1079232dcdb21f57ec324a52549a435cc379fdc8fbe95c712e04f9f804e4ef8b4eb062658165a4d4f5905bb5dd28c3bea117ab05cb89a53ca9bd5e9198148bcae7e05e9cbadb387397e697b23c17245418684b74c623e4e667f2977873aae78a21f7097e04878d809256a557b8666fae2ad6d7b9c2d5ddd21a0b28c70d66ad327846f1d59a836eaffdc01b2e0b09aae218fe1ff86deeb19dccc04e2b04af834bb865cfe277b9f5157c5a756553cc03e2615201af1619017ffaeddd8e6fa63f995e527ab612875072283bbf002d17c5e6463d93d881d6e8a94ffb6415f1e218598be69b772b0696e21720201733ec38fc9a9ab9ca9a5c8b841162da04cfc3b4496a46ba4bf8fa1544a3b567", "2c6c8beea883769ac490479bcd69b235acb100bd91b90a2252385e2a367cf976f84a52e4bce794965cb8d971395b8bd1d6615931350f39e5714ff6804acec7b643fece8e2baa79fb324a9c3b51f16ec52626e44cd28c82fff733b38d93ea9f57380a8307c5e032cc8f722942c16d01c5422834d739eb5488551201a28ee68787296cb8472d4d4931ed3e2d6c73f4a2c923202c31b84dbfc75bcf8ffb54796cd9054fc9091cb687cd8336f4d336bedda5c572f00fb1d571ddb87a66db0f238457686b44b78180ceb3e1897a88a05b12ed6778f5cc7b5fb89f7ffdeefe7e2e087b428270848240abd28ec63cbb166be267a2a9de3264e88a3fdce171c77436985ec15fd8788b46a60f0f63ceaf0434dfd941bca346cb20a582ce3a9b513de85e3e1d62bcd420efa1b4c92d22746d663f1a375a0133113104ed096c2481a1f04a56e3117afd1928b9c3d0dc9c023cfe63160c6019f1aa4b533b1dff808def43b7587391d64228a101a5ae3c0a32720ae4948b3f522b2a59f4051a6d0352ab979c9b9a4f4a62013ae1e550114f19d61a3a04114bef92d01f54ab0a6fb48a57b826efc9050164653898893a9b70fd5c8ee627545ed876c228bca870f605beebf02f10099886a16c1a542bc54f45ccc101e65bc56666ecca0657b4c78f43292e053ec16216bdaf450806c812a1268fb1a50af6038b57c91c15f05c04280ad8620f6d45", "9930b4e0d857c8cbcd38c7efffb50d389b8a7ec751194c003a9b2ec08cb9a70c3a8ebfe46413bc71a7dd5fdc267c8b7993ee2ea4140f54aef490803bfdc931a3af1baa1407bc37137ab105eb282a1d9eaed1fa7896caf71e79fbab9773d74ed1f95cb834771b6b6e0fd69b04aae0d8b5992d957a1c5afbaac887e285c8d2ce51007a4ec88b333a3b2b6a1c896c755059d6492c210736483de824db34caee5cdad534130f30239e66df045bb283743c254c6f712dad22d49676b7887ebbefef29ffbdb79c6e0d2026f0040ec34081b539ba8664a5e6183e3e6e8c9a4ab6e900fcec5cb4e63868e9b92ebf6be2777e596e5066e50af421d49f3ea710089598597e22c711170eb2d4ed794a3d7e8daf1c95329ee9067f4c43e180412efb040fce6f76b265c2aa7f845fc03c3ec25aa806431bd41b0218a0c4f15542f8c1b28390f0e906e1fd2f7ba2c49365933a1295c8cce68fc321b967a6e71a0581a7cbc0c46e4ce47aef1edd96cd791a95dc864bc66c9df870251c93983befb457bef3547f5b14a9c0e8e4dfd594c72e7ffac0536c9717e178e36f1b05bbbdb826861bd9cea022649d20873749e47f50e8374985e1498f832ed22e9b04ccd9e262b4b26dc62b37efdd8232c86dadd084f104f2ab29f8482e8d94d9567df1cee20e047f9024cf412f2345e3425d8c7a2d77430dd8414fe370bf650bdd7f1715970d20ae0db2231c887fd481494d8a04e37bd0016fa1a6e7e8205314f5876d852129475a08909a977a2563967ca02fa47ba1cf21f9de22f48cad422a6378722836ed2b0d3ddf8955e8d112f7834d7a53cc0788c9d80186ccac275bf7377cae93b4667f6f569065aa5435481fa56d99ff35193a2f9bcb19c563c60861b4b0e8aed9db42a936e822e6abab36ca05c5f8ff08f3d2c7277b763e05be8fe7f8626115bd6866f706c4e7d4bc024cac954886ed563f09374101763c2dbff46bc571ba87fb3ebb1d0dc807c148c5d2e1ff311c3749bb579f1bd87ab271adbfc65db5069442e0b18799b859f75d953b13b3aaba0400e142e04bd49fd258ec3fa9cddf42b8000bef0a286acdc6b7486b407d21f9da886869a1fa0104db26caae061cff259497c711f462de2a091be83e167d4e4ce2d2f9222049e17fbd64b8c062ed7f9e12d05dcf0eba15c0780c6410996f5a8c076407777e1745ca4a50c7d4f2dc5aafa3a6ec4eec91e8bb85a5fa8acdb0235271af25cfa8a2d228b26231218fa041d3ea874f627a6ca3437dec31ae583677743323d3f3ca8a46137487807468d16b824265bcf28fc0d8e36b60da7b0c398a21d752a7da143b7ce93fa578e01370e4e879f393120af1d35f15a807734489fbb73078972c7adb08015146af24a9b2400a234912eee14641e8f3e13758b14dea583add3ace5c3b911703fe41065805f08b6b3be64365bfc3", .None}, + {.Lcm, "8659caf95d6ec23ee42144b22de99473df9c82c2d60e57633ebbfdf18154d398b4395ae3ff5735461aab947b2305197e8c00d567252f4363da326041b0a32e88631c84382f13006ecade290b361262ca17019df6879ca4caed5fd08d53690b82a1844c7d46b39af0578f3d1e2de1075ce15a8a7d4c0bcdd4a297981e52868ef97f095af644283ed0b445d098a70f7904e071d54b8e3e697293cc8d8b25f02714e334cec793e25bd54956faa201c06321d7292e88a8dad737071b01d67717afde140861cb1720d165eabfa3c9df1cbca4083441f60eb4966d57999504e42ac4c3959c5aa45d05d148659d942828c1fab7cc6854692cd2908e64bb5b77165e112ac5cf95502e30c9448258e6cd8673bdbda10986477170af7e6018d1636f493f6129b82a28c5388fa77568f654657361b85262519830738ef9a3eac4513a4cce2d67ace81a5440d73b1357623f24848f1a6fbb41d0c3d2b33514064bc83b7f28d8ccb66aebc1a377719648ac29b18a26af31d82cea498e4296a285e332b7d01914eaa2bef1bec17fbc366c4ac23f2e9b6992b47ebc26f904c82d5401d86e839a3eb95d7779286e73d3ddd8164b56803b3fbf979b3d9c352569cb1e3120dc1167fa2f021a75350487de839d23a9d13d3e9c6f395f5548c768ca75123211c854cf7c8618aeb101816f1d177e4a357ba513088bdae0ff5febc2a6fc439a475e7725fd", "-21588c488610acec79ccec20af271d8abef76b8d8dfef09d3e88c10161ff296fc39a4808ddfa423297e2706d95c5a5b7810f33d8737de4ebad6bba00ccc7bdb692fdd824ee55218214fde24c6289d64dc2685f30810b9b93a0eabf970ea63e610a0558661069b0ea2dcfd23b4688bb57bbc34f5fdb49ebfe0f5b598598d70a6f86f72f7846135af5781ffd540d92d4568154764cbbed0181ee66ab759891ca031d50e39c5e3892e42b55f8378bdd7d4f77298f27dd369910084ae6f3b3a711073884cb23adb77457c3f416c3eec700b42396c239ede0464bbcc8f8c11dc444e989bee22fc58a496c80ee439135b3a74d1ce5b95654d3155afa5c9aaf113c4aae90e026f99e672f07638c8e1a580b0308681900904557437463dbbec42acfd36f23a50b5059c7a5a3deb239c82095ab875165ac1099cdc07445452afbe577afebbcbd7e0bd46d8bf608edf776f45aa7b7cce05dde5d9cd63dfe98fb43b72c569e8b116925e446c1b23abdb4b08a8c1359f8a168959fd8eff78180aaee4bab75aefc2f27b6a0d1520a78f14e11b59fbe9c77e31c2cc8a899ca2029a324eab9f8da74c535f9a55151957c6706b36f3b170e76eb1a77ec1a5f7bccf9c2ad434b3c3e0d2b35353e8049661006ce762370046ef08f2ea5a55cd1b81f1c34c0462f3a1a26972d200b4069ca08ee35bed6a2e7ac809f2b9e90f706c1e1a045656e946201", "11800ba715609af35ff83168162f9f4082dd377c1da1279ac4f3f8bf0b36e2670d0fb4f8a1f0249dccb9008e48f91002b65b181ec9ba66381a3fe36b25951b1179d41f3f805614ee71623a1d3b283d5334ee26643f9652a32fc98d1b290804d5fa38d09ef425e2aad215bfa0a7a29bed805202069b45f7610c71de55aef328dafd6db61d0555b24f7ac103622d91c997764ec5be5e21f2c43f0a60f2236b108df4ca07b2bb06838af4d6cadeda764de4a2d391f7b9c21f9aa3837bbf479bac21c9c82d8f2d0b737470f15f3d0124302e083e390b76e0a24b25a1dd4b169752212dd8e78ad7438e19208c87a229c47aa89d2abd4ffb51aa1e999045dce3b5d6d4661546613e4b44fb2dd2aec816af78dc7b2d5a8fdea82b87f3e9acdf1518f4e55fa405d2e26f190f32f99d2e02c0d995fa8adc4931b76807e0a193a9da51284c81f79f8faddc7afa963ca038879e07922b4842ce3b32d44ee16745ded1fcde416ee7e8407c0d8860cfc5b54425a76abc6a93bda964cccb87b98d34b9cb787536a38c413711967e476eafa0b1a850a48012b23452dd1724bd42601413dc93ff5e055e4ccc8bc145313bffc920e3914821de3c6d60f31301941291d557c11e255e160125cc0fe6cde8a95d839d19933bb3c3f683487dff9ea18f6507aba6b714d3a55171233dee82835331ae11fda8288b26def2e2522aa70b7c394ca36e560b94b028249b0d0f060344d4e4f0550a0a9184fffedd8f8f0c4211454b6fe2e31f0fa2aa638756e7894dcbbbc210c555877b8a3f25c3d243b6750945c7f53c7e87d4723e480492a2599dfe0cc296f63f69ef98fbc521f250b6edd7629941bed94849b378e61c8aeff7b232ef6320c6c7de709336bfd8b6cc7a8a9fcc8673908b86905b20df11f02e29f647d543052f9f7462547c0f60b3496f626a2850c25362f064e7a4b94fd515ac631a6871c20314c81b6874f0d089374ce2547514de924bf3dfde607635e568ba274ca1dc0a268a92de812577eb39588406453d6d765ecfdce09ca4a04e775e1b86ac2b34fb7c6422fecc01e3bccbccf506d18a8ebaef7f7f265aeb81d592b55008cf5a255a6e7748e61cb52080a00408f709a78a3fffad5d2e3e1d258ea48fd9781bc8e5ca3ae1936aede26e638c967ca82931b2a15a84b2c99cbf8b8537a8b14260054ecefaa1c91f31696a45e319375f54dcf6e6eae82323296ff8695489b98ef79f661a2e90c86f3b0f3eb87f00a9461286ebf5d55f6094f3dd717f564b22c5b27758e9c116d4c860f0200e790d91af4bed64da1204da6938b0ed45756bfc789d5c8167eeba4cf94111b2188fdcdfcbba8df4bfbde0f0921da633671210728f13815b44cd40a36b275ccef2ec3ad2c05e3e28fdc5360eefa6d028305f0079f7476d39313ed35d8922095fdfc91401cf368be976a745fffd", .None}, + {.Lcm, "e9e0f47c10a7091fc93115d2a4614cf21835c51c349c4dd4944a81c4d4a364d17778d8d1acc1c7c81902281df42e6cbd53c24d7d849b9d9634fed79c574d6763387b2dab9434b0ba72df81b70d47f4f9e021f15686d42b6838f0ec0b8b6817b3e898889569bec1561492806f9c0e34815f0321ad61e5c0a83c726068a6af01b3cbfaa8520e5fdae8b0084cbe5023b4013402372449e86702290ee549dececd612fab3535b3cb113fc82f32c318f4f7e7f7e71c8967e96fe0e0bf9e15904e7e02d2b42ff4d367821494d3f7c113b5f74d6701444d05783e3f57faa4e95450620ac5f622dd4eff0bb759e0f9a85ea22f470080afb393858427a8e93cedf8673f60f25902fed2b812e6d286787db9c251c7b6f6afcd174df9345617704b1732afe4442193d6d8c6c5bb57996bb8e4e9273fb61c0de3335974e62163b479306c534478a32238ae02a19b8ca28a13d70fb5317cae1ff2905ab1e78aad5eae4d4373e8e19a30b83503c2a1ebd0d76cc051005f57638f2ae5dce23c48eee2e5a6b10ba6f1aa17241e2c5a12822706e6c497c6ce85e0e4dce41023355ce656e6300ff903c641aa3cec3182132d8369177208b43de488545f09a5d0fadb917237132c617079c14387357e627dde215f5b13c0f2930bb6f830a819d0d59cee24335ffd6a15ab7f0b06f2f43c0b5d4da582e984acda02e6c6adbe1e6b99a4fc9cf98d0f288e", "-6c04701cb37af71ee66993e3cff9f993524924aafab0d9837678ac1c2e4070fb67df2fe07ea26cc424401f545d7aa3404a03fc6e1141a96f7741fb9c96c009da17ebfd30e9989d8b65c7834cf81d3a9de1e59a33647e5b71a8561fae321f67f7b8c98ac0225e9f4a45cf5d57e1fd48e43358d953ea8bf4fa378110ce8595391bfb0a4214574f39b88186bc9aa06502dcf4705da28b224effdf9f21014222d3538d04b80e41837bd2fcfc53c42640a2a6ea2544e3f2dfb6cd1e3abf9fc6d12d2e4a54a8ae17a403d45d3ce4d538255d17a57f39cfac5d37501652fb174b17ee94205ecf998962a574adc4b7e701ea9d794b0af841db978a609bf0bba4de4da08841eeaf036794a2336d6002529aa49ac11833434613c5b39b5996bcbf9ed54dbecc2705278450ac9328d9999cd733502eb360464d9883b32282acf23e155a7b31fbe199ed82d68135b07d060b137f91fa2c1b31d244107bfd90d4a34fa72f237e4b0a1c8b02f9c8584094abbd03591961acca94ead6a11e86c6bf0bd7aaf2a20d285f28ed21f87618bd11904cd5fd056203d3b6bb3938007665ec093c43f5f0644623decda9a494bed4f3e7fb84e918ef93b74febdd8fd92e05647ce850e9656dd03e7ef702ac3be1440ce5b9520d5f629ada7a905d99150461c3035e888d844b9a3032159ce7e4bf30c3f6f084e6b8ddc2504340fc3c55fa731dee6b2e52402b", "62aef514cc80613bfd2867176a784d36ffddb937edba61824950cc8b0b736f478e011f2bd081460bca835b8ae1ec72481d487d8582531bdff3b700dc1913641f00f9d514d48f7db66ade443ef70c342d19426b0061045c1b5cbcc441440a31b4a4bb3191bc0cc78f2a97f84633f9f18975d2c4fa5da00d2a265f2907e215d1abf5442b69eedce324fbad7c7d71f43b081e3a30446d43cc225e9ab0673acd95dacb2ad1df5bd77ebe2a910bd5e41e1e3afa4057c5ed31948e263916843fe5ce23f4cfec5f0ba1594ac2bd8b4a0600df696739ff445eab447396d17afb5d3752ce5da7fc9e9abfeaee6cf1b828d9e0bfd81e076df6c00078f273eb3b114ead2e5d44778b585a5dfa771e174b1a32ef00158419a63270ac46f5f01b015cd032f20e1ebe8112042f6d4e2b0e8d02b0c3cabcf345c673d96870dcd36eeb719ee0f5347ef7eb9528cb36ce118839e5b304615d5e71a9b12bc99ca473392182e90d1ef136ac3d835ebfe9019ace138db998a2303a5d3590250e37ceba998981aaf076733811385b94a3a9f8fcd7f16683712b5ebdf5c83fc0950499f717550e4e3a3f3cd599f8ea1183fa6ca73a18cf58beb8bbe34f252d56aaa94066d48f645f046473c2a60b20c85cd719aab89fc48113ab546c96e57ff93c1ccd07793849e3bdbd290fcc840394fc5f4299cc5eb734e1b48e85ee0ae0f2e64fca17be259afff927d6662805a3efb2ef7b3801cf4a6c3ca2fa427120686fee23a8be42a114ab5f1670c3a03aa6ead5cd252862bc32448d82c6d6d7ba5ff7e404cb919c688d9124c7986e11a364e421298dabc24f366458e2e4be6df0d201bdd3ec522006806ccfe91d5956b8bcc128b9bbd33499f95128e0c952f6d6ba11a5e89ba417864b6d14b05821404c74c0384ee371408729ecac21a82f13f7107327c24b4b27dd4e993bc47ffe0962a49813542c99cf27ebf1349aef6776abd78c395ac3f299f0f4eced9424a522dc534191c700f2bbf32996196c070d1db787654c3f7d15e363b9246ba97d6ad755b0a16ea343904f88b2db2725c45f8c0271a2490263b608d5256425847fea1165313cde538baf9a54e2d065e35fd876f7b7336d13d4c5e62de0518ab85ea931bdae6935d582bafb0e374bfd634abebd2bb390a879b1f61534a04fca819ac1aae01c7c824f74a71fd68089b9ed40891e5b0b5e6f621a84e8694c27d9960bc1f35573e805f44e888f34a9df9da128477d67948ea2eb3ada234bee9c77fb059e0f71c7e35a2a39bbdf14395a69087e89c70802342b832c2b1d15b3072a8a2c35298a51864c5849fb3b484ba4bf99bed1d0140881c4bfb3d8a6efb73edb5c8acf02bd2d5c039270db870e377cd80edc04db524f57d1c4d31b4f9552c260a421cd654de082f222d3b7aa4ff253e35407f273980a6193e13a6c14a0acfd2b4fda", .None}, + {.Lcm, "-71f0f9a1fa2b77a40fa1fe8c739bab6081f052d7ce681f7aea86d6fc487e2079747fb67e79332669f97bf986ef393989be37fc72f958730e47c28c55e8bff758629883d12bc418d95d6adf4c73edd0edcbb631e7cc34a856f36e4a580024dae8edb45aa01afd65ed6ad20e133eb56e0191e8ba431e6f22e2d27d8182d4c282107a1022edd8d3ce4f69a4211c637e833fdd1ff4d8c2027f0efc464fc9fec03dfa3cd632b0503a101bd82dbef3be5426dbcbdd942b906e3f9b9ede5044a001960ea179cdc16479928d40a4fdf620d01445ddf51f6f729af9d1eef16e5355eeae732e038fe5373dcc29ecd3d9dd7c196dea514023b7bbe520437b850267001be59ad9ea96d50ecf26f194e6689e1733d6d252a800f0cf6e202a4073b7315cc20514c5c53e82e02f9e8cf403c69e4996063b5436c8c1e4d43d7a8cfdb502a965c9ecd3fdce39a525a3f5be03597ba29bc5acdfe618cd7f8ec6ac7167ff514977b981c16e552d8877a09e89b8ee7bba2d49a8a9e0bceb0088f34e63c58a1833ed8a0ccbfe9a558a6f7f803c0e009333e3fbf79d36e6f41563f71919f0f2d918755965689e8175141a20f7d821ac38a71c28a904ba91a1de0a833d3ad6075310af673708d55f06ed1592527af7f585543a0c16c9f3051ea3dd78f98c9d3b3f1115b58044f05ee362b21f15ff727c2d74085b7d34e042baf74efa5c076e9f7e07515db5", "526c57d17de5e468b2f12e6b420d38961039a43848838ce6ff5ae4b2765d7efdb631a014204a2d1fc67d346d668fe6afe304ca2068f279a2cbbbd28d9b241c005b9a4b292e3c657aea7d6330dfbb8e712ce9487143aa16d9bd90f6591dd7fbc5d0ada3f7ea421ce863dad22590768e5a97cdec7f16f8ef758564299aa8c33c6b936f7f997a6cf2d8c5d5f2f81b23c1cfcc8d33b010d4a7b618db32fc7ab72ae33c7f86f7f8c34c58b056b1c46fd8ff2e37b865aca8f88dc1a63f91c5cba0f5c9e659891a26c630b94bb2912db3abb3d4534995c9c4bed067f5fed11ff2b417303dec94a1a094a132415ccf5dd30afd93f187483652fbab5a65e3ce4adbbbfca37731128f08eb4c6c0d481542e0189ddcb5d6e7ef3d2460a0cb57ea86e2c0adc65c3581f797115e16a09648a3bf6aed3f433f681350b590e6969e5993625c4c00be5e13ea54c78a3076e60afdaa3b838ffc02e38e77911dc77419209512dadac25ec84242b77ea53ace1d188359ae5545c9c1d7d91210c3adeb3faa51059dc6f199d2765e5b0ad604695746e6a71b75f7db55e1d33df7aabe05c77370e17074ca27aea406744d40a8d213f04d2009b489a572807e21e7e715e5baf8368133c2c0ae75eacbac536b12a38eb74c8f2538f801aac856230404284c3aff43fbd9e5e69978d97ab8bab108f733f4896d03cd637f66cfb19bcef60980b5ae3e0093d4e", "c3a783c71b0c4028cc2d50b1caf644779aadde9219bf9cae45e3a6e64c054fc4146ee300ac956660ecb3252fcfd6ae4745ec613f1041b2f2c58b98611f503b57a766da077d987bdc15563e95f367b1410ef06842b19b3057588ace72e6cf8f0444cec15e583194afdae05a246933525d73bf43ebe29e49bf333cba54523d22babfacf8e2609694b9395100e5331751f624820c60131abf50abc40293614d7ef9933a201faf01a718d0c22a8c5b671519753094514d36eece0a4cffec3ac324adc2062aa03d926d4c4b214a2ed709a3d4a3e88b185c6b0f5175c600db2da09b932db25f7e817daba7426402a4fca293993eadbcc201ffaed93015440215100625670e212670cd7ddc64c4610f9a7a3cd26ef11e957d82057b10d51e75b3726f5025fe1d32c780ac4309c4b01b3f06fac36e6a5fe5ec2fbf9cd31893395e14618c505015404ab0720fc27a071d01b75db67710cfa5f27eb1bcff99d33f1b1af7b13e401e2f4a1a357a57eec36bd410da84ab5dea5e8f7095b0c01325c262afdfa1bb64ce3bf85ce8ea24b21100b868cfe9b0788ce71ec002651a2cefa02a59f38115e25ceb2c03abf1de96e1a48df386c34c968851022bb81ee14c379f1c2161f316bd7753cf8cc950535815621b0730f913b9a40a07c36357ceb5403cb20ea4071ca459884f78f9ef0a8284174181f6c268f5e8d563d32fb88a0b43ac35fdbe353b4d789a9958cb289cde59171daa9fa8b357666fa451be77238a9557314b2d82fe5702488c0c1bff2124ca40ced2a8e73be4f1f804e3b5cd75992177370add802e507010fb30130aa8b2caa545b57fde45fd99467e70f0b39b243f42fe0da1d603dbcbbb08440655779beced6d52a4714c122573c89e0b9fd087ca247e62cefc9f25501107ee7135cb39339a28ecdbcc15f71d18906dd050f8e9f1d8885761fb2ea4de820a871d5b96b4aea15cbb5293d1f18c59167a24bfc64498832030b573ddc934103982cb2223146dd98a8aaabfb57b9c0e3226e62ef24072e56aa7be3f0420441726e5096fe64c84b14d6771a3bcaa37ec4d9a0e6a5cdb656521abd78532faf4f676b08b28e0608a54a1015fcedbd3547a7cdb6da4d45ec0f664a0b0216620d2514fa3f5639b544a2f05e91bcb0a62d9b08419a63ba186c654b1e6a5fd3cfc21ce7b804074291e25a8bfb61ec19f159aaf5ae3a58cbe1cb4de9bf274d66870d56f0c051537b875077c09f1c7c4a5390a8461081973036590aa8c4382211c5db070c47ee8d06d0346f664114110c363d58e9f1f72b47a02b7563d53df13b26bac3eec8c5f827ab660f7b8255dcc280fd6e871cf44c9b59f7c2826942faf2554ae2d6e5089ba63ba6faa5c23d6a47da6eb30cf9db1903a655dc4ca786ce6b3e329a61b9cc7efe4b4b1e7c7081cf5d5aff49ec43f87b2cdef2a187e8f62", .None}, + {.Lcm, "-386b196e2514213102a9812519430c5b5f66c99b2271672da71e28bca7fe3ead58ddeaf2be331cec0e4c91357fc19298ef67ac4dd00cb97da5272865d95b0255158cd2778cdd9c3e1c87ba733a4e2cb656f536ca9798ee583ee570021940b84913796565ad7176ffd1725125d1b8b19976e78ab7565cb78bcda908e1da711cbe6d84b85ec0c23c6a7d6edc8f9e4c753285c9d07ef49c10aac0d01ff624a84b086d2f91eef39b42dc51dd1d9fa52f6abe95b82e1ac706f20e8515e7a833f9839e059318bb03df5544187b6d06c7d1250da39ea7cb1e01d53ffe59138d686c1a0207626d3c0c44fe40a124cb440122aed46b2da15027d50c3406136200cad396a83672f975beb59b8008ecd61da7a9a32ebf2c1792e16ce37a3737b04b34d2ce26ed4fff2bc90f49b8e83eaabcdedadeb6f7455e725731b8db3cf6674c719589529f693056295568faeae81e6fe01810f6300bb7368b656d3ffe809660bf2f69ae6375c2e58bc981ca35b0c5cf4778450db0a6ecf1963ca8c4d97cbd2b6c96605636fb71f125ad836a3f7b58f09240504e42b076d96134943ea33202a1eb26534f24d1ba1b7c4ff41e965dbd1867f7520b8f1f28b39e5b69bae067a81064898af36c16e413e29943e4effbdd94da081e6fda0a1ed128548948292347029ed260bc7968f285fddec48d3080497e4969f566cb82c74e094c42616f13d09f7b9c017e", "-d20029fac5cc444c28a0339517862fe886e2b21104ade9181814a03246d721f6a4430d24a50f51cda2adc3973a5fb54f2d78954ccefd3056e0a3a3e1daf640375f302eccecbd4e2b6662ce3aa34b8295173225b724f3782d2438903695da26e190a75673a688c6c5b8d5e989908fc3939ad6d55980c5081410e945b4d23f3706dbdee99e03b5ddab04cfcedab2e9911c627abb4e92a42e104be81beae94096f6ceb039989498c50a27e5195493fe0fc9a647f5351248059312c8ac55c40e3991eaa1caf87ebfbb99f24c095fc8b949b11bbeeeffe8a76eea03759073f6b300a72922e4426fd2bd4eaefea71c006558bbf12c3389b4db0206e8f4227b0b6e3dd947e505d95968ae7760b6cab4bae575dad1f49e01333ca60899300e18fa110e7a1360ef93a5900b0a8acb652e5ed7da5d1d98700144d885633223ec4d5ee447c31a343a88a656abc5dc4ca5af042df97cdc362846904f0338de394e6b2030a7a7d73af7047fa68d7ed95d4fc3afe897d5d78d1de1adeeb57f950c1bd29fe28c4454075933ef630113050989c7faecb14ee363827eefeb3b41f3f5ec5fd26c4f234e660f54d63af452aeb02a5890d0edb336ae50bd030816e9b87eb1fa953bb6ec716acfad746bd7f9432b255097e62b9c93968bac9e7d196d3e2d90499f555321736c6591db2bb12e72d2554e81c3aa15fb90810150175fa025bc7c87180070aa", "1723f20e62d5b5d8f27b98d17f86e024df94567ccac6f09fc552dadd33b1c7262cce59b17d11d177c569c2c6f4dcb429fdcf9aaef2f885249d3b2d7d9d1ba1becf47d2920a7d40433130182a8803b61f79ed7a90fa2d094b0ea11785a39db923db6d2812f61a809340f91a4ec367a6b9e7d06ac8956aea2f6ad9cbd720b8ddacefd4fa217792fd63751871ee3cc76bcfaf0171e46ca263d690a38b2c6ed4c57db72b318f70dc2d416ea7ecc38fa47ddf557316a28663bbcc11041b921fb428dde2216898cb009a819c68cbc84c1dadde23d018999039fc5273280baaa1866c56029eb92bfceffe05fc6de99c4cbf9e67c119fda243922cd47ad84dace8a7c8ec16dcf69661f0e6867c9f9887de7ae6e6f9c071f4737a903e735e57dfe10852ff8fc4aa970a1474ded1b714be03af0d8d44c8db2c14b1dfd1554860cabd426576053e88ddcf28b6355537bc50cab9b7c4cf33039dcbbaff56b5dbca906ffccc9fcffc87aab2fbf33963ce66145f9a0793977cafbd1338b42f89e235794def63e2319c24974a18ceae03e0f180f18e47cfa3372d524683177ecc79e6b0fe71b798573f13536f5165abf6d76ccc5e58f52132fa005e2da1cd9fe8e080bc4e79ea08c2ea687762465f092efa4b3be564403e8c0a1a007012cd928c756b6e3023c7e70abab3650aef5b3dacc77d5bdd34949a5b2e955bec6d2fef31f5d9758dd7f17f6b0f9b30774cc5b65c3f064820e395b6c9958f3e25688ae37b3142445ec30d8129b7e20b2c43cec4ac5409e2d7300c18ac49b08b51b32c54674d714205a6e51eeeaf40e80c9e59303b6db952622835b555e83e545b3d8f117491355b2a7ceafa51e50ffa7b9151971577a3f7b91aa0cffe4258e07fa25567b569f7b411e69e2e5701296a855498e531328624b45adc6ffce39fe7d67bc37da237f7f32d5d91f3178a9605afcad405766e66c3d331f6cbf9ac5486cf0f092a780d764d56f6a3357e180968fcfcdebfd9edeed39ba116a1c85b6a2fcf95e6ff3a840bab75aba87e77ef4307188cb88bac7b50feb07afb11869675d1a5052012e7c30dd7a7f20971b5d65ed1a3f09e1d47b70e9e80e72cbe7588e50e964a7f561ffa16ae4618bef204a01e5333735caf4b8396ba218df5ae85fe7d025a535e0e1f36159658a5996143abec9eb665ae226aa8015a6c17da769d91e91b324c8a6545a21c0659a1932c5fa1b6608d46a35c449d54a033ba7c00dfc9846bf87fd7e91b6866990f3e20cc5c12cac29c38587269422f0895c584b327f94402667d4ccb210f05a15edfc26e3747d8ad75758be09672850f08c7a6840e8035f48aa48cfef8193eb6bec230a7965e3cbfe9adbfa4f42139e0cd48e990f8a621b58024ee15a32e6d05fa28c6ce5c3ab92f560a61fb7d228a500a4c1ce516f11a42e17aec2eb84560c913200ed6", .None}, + {.Lcm, "13ad7bbbb90e973666407e161bafcaf3baaacce9584b9610a7f0159e11bd276907da7a045fa266d48734dc0e9f152549cf9b23bf07246d4932d3c05b1dff0ef4805befc8a421c7e4ee1d7c2df2eb8b85338b5829dcb8d5bc1f31001aa1d8f9bac1ff0d4522e02310d8ed6b1ecaf18bbf3aa781126916212b4699f7895f495e0d5c66265d1c093d0a8fe9b71e4b3d30e0c6fab9b8ee0db655651a75d2596b48a094bedca89b6c972d3935a4836156d2d4aea8c46d3eee1ce00195b06054cda7a53cba47a99be1c1b62ebb4bad17eb4db67dc1a214f93d24d005cd054638b3b02bc7388eab4d76bf0cfbfadcb50957ff04e0e05f0ec3d2cf84b4f37fb48c7c35feac3d0626b0614adba31e8d4e377501de6670d043a33ff4c06c9669e7ec8e7fbd33d15bd4340338dfab00c2e5b87fed0d3eea722f65785d45c3194e44ee4ddd295724220e703278ac3c0b9f541d13bcd2ae7700e3d5eed6ee125b49f3db31997832a930022dab4468760c2d6c5bfd6bd532c1b3b3926e229b9ba0f84f84e11f7755ad3dccc33897306ca3a314c48612e183e91a8c2790a0ffb5c9cad00ae80e34e954df3cfbd3a5b0d4759911823fe27a8a68e46d7201a5f376c8a481928657d684979d463a71b51f1374466e197f4e516f7814fab5bc90951918a34ff3b672c86abb0a3ebdddf4998a0ca456a3db58c73bdedd7d199bc56702249f5febe1c681", "dcd9bb5c111cdabb804fba3e3aecc8618d785ddc77b5b28da83b7f7781e3573985ab6e04f74789d568b3c4b51a3172d9ea585c7dc887dbb8b229317364fcd3827a9f8ad7bacf4551fbab78ecd8181fe544d06e68ba812ec6fdb0fb37230d79df5253e0365c470bdf368a09337a332153bf08441a8eac11b7eed718c333962afb6996e38e37d215d0a271b62548ee670ed83bc610c521aaae040952b6f7c03fd230f5f3a2f7d3789960f2bf16191740c7f498f533c8305818c2e02c48024420b16a1bff9e97f986c96bebfb855ad11fac9299e0fd504eccd16cb116cc82919f40998d3bfd3c0c58871714c5f1a58d1a454cfb566a58afdb6f656a9dbd5aea7bbce58a5a76959ee20b32e8af59f63027c9909d9d1fcb08dd72ca9525f8a7b8cfc3b2703f533c8924654416fc054328e21b9e1db66d1f79db27a6917557dcad44aecd8a5a153a4796cc72da706a57cba65b08e955e13769434f81db6826d6761ecffee93afe401d8a10f965524fc015545e741e91873c6e12bf827727bc7eca407b212f5483eb17b4655dbe45bc7c0027c1f728a6c7c35b0e0be9374898e48d807b805883ccacdb74967fa4d4fc267150af637dc7bfc9d4cada49ca50ea6fa4bd55014ea95de508de3c32b2686c7f42d7862b9f9bd4e9d51b4521f6d72dab3c3d3cdfe69374fb94c5c7ac65e2ec23ad9e7a9ef4909e5cd360941f1a7b706ab75c54", "10f9d2ca0233bbf63b757f555ce18439a1bfcfc3921014f5e7985cb5718e92fd2fd0dfc084f150bce29a1e3df9f9be84d4b2f7122ab9070b1575ce608aef4448ea907b5c93487faef9439bdfeeea4631d13c47a68fe949ddd96a8358dcf7467b2005810c5b75749333c0ec67d976153419f8061ea41193e4e5252608a887c0e3df685cedf0d9124ebcda39d914935b4da58d675d9bc8f6ea953cd537038e7eb9f917a28495758c700ec7f47b6e764dec17c2180d3cfe217a3680e221e021c1fb5a6efb049e0f725fb1e57639d13a74df37a9b1658fc750ec4e191b7be02777bd9a40b5c48f375079149f505aa115d3cd765f227ed38bd3c20841f71f324800712335fb68438817540ef5d5564aa7ef888f71962cd1c0e8a500c1b201c1c238fdcb141d0ca4b35a81dd908f1033c1e6ee3dab755a5de8c6d206958784e55afb0f56ced9570463b877e30c0f0eb6adf92b8225e27ea23890d794e945b922cb8553652cee83cb3dba01f3d3c2316ca02aa95a821e5929cc13ec9a11d82b208de9acfc24575a2a1f4434d5eacf0ce5aa4a882a82500e6b4fb90fdd905c10b9a302914116db4bbdba9a24b88700a21e3eceb2b3ca6f9a991a0b77405589ab931763309f25616770ded261795110664d5981dd9399a6adcb9e02dd47059869d5aad09e1cf37b0050d128f3a46c5b567e26ad2d0e40ec6b15935f25eb0d26fbf5f8568a9a3e84c49de5991b95edc0e88431e2c319090d29156f593ae9b6419dbe5f6d64a3a0c315f4413ad8c44fc9a34c36e3c5d0fff897fefdf97b82097794332a7202b5cd427f5dd4875950e7730073523906ae6268d35582d9e448a84b498fc3d0b16087a4f8bf99759dad79ee61f93634713607189037fdbd8373a87e06f39c26a2fdb3b1ffe878d7c4dced255127178e7e96dea0bb3f5caba13cf9cfbb8f9b2e45fd496bae5c3d27488d4db3c20be99b6d9a10688c70c7accd78e192862122ea4eaf5a0248c04a6441a023f9215e3c2ec365f9ffcac3ca6d6d6fa474addbdf83ba2bc41332de57d79b169cb45f3162d3920307457a29f3b8291cc29dcd50887811a270039ced174aaa5dbc2f47a4a90b5b33c076342ebd5f7cc6002867b9ba0ac4f2d27646d9b7074c6a204b2a2e491df82416d50caa6ebb991aed750e276c873cc12d0cd3610a87d8c5886f5d2f5b8bb879c4bb26270d9cd84c5da431413eb973fc6cec1b9d0a7069fcc1c443f873957506179bdbac61573d49242f1d43e1de1aafb03b1df6970c24559bd25d33180fc632a0d1956f1ebb74a5504ddc3952553e8752e997f18a3680c371c3eda45669307c7a16e164921dc9b7b7830cec93d1bd543f60de21e23d5fa0b2556035f4bdb5d12b1558070114c5fc61094b7868db4945c8ec30556337ea76266c7ffa1daa8ea332b0687cc4bb95f7c8b244d9a27e54", .None}, + {.Lcm, "-eef2452544941f7e7440a0ea75f6928f95441d6d8f60c3166b713ff0c4700e51c0918008702c8d733155948b59847040d9e841d82e1923ecd8a63ca64710c8cf5a0ef409202a1481e82ef8384b5acb3940f5a313776296dd7064f0a00d60b2f1234206f507ab487a9cf050f61916e199e560e05a050358b82ad556d6726feb025476ea11abc86231022b640ea0981d2111df8c6f5a060a039cc228c4b4fb6c6fd2c0fdd5ffa456363db1b493ae31643489b8b762f6d4f9b04ef7a4635074c04c69f5d0a35b9bb11523c3d2fbbf560a307702e4f9d9c893689b2b711f6ffd9a809cf00fe2ae46ef4c5b04747b2476d9ec24bdaaf85749f3adb3cf9a31a759f334c8a321ef8eb9370052c89db95ed848f8dbfa30eabb85f54052689d8f14b53a2efc715d03d3cd9df0cec196eac53f127e7dadb05547c4eae7f23101dc0e275d1be96b969ebdac22a6872f554a36404470a868ec91e97c48ddad723db25a95d53551df0dc59d4a462e8a99b94c434586289409739a4a7f8213b41ce331eb794db1412e5af72d651a81089b73990575204262e05174914e959771624feba15012a1afb5d188e2cad530748e2535cd119e0bd250fc6830149216c65636514a4ce0d4d4fc627d5a30a888fddf737af6d5b8e6c19669a5816c6a2c7109dcb991d7c5e363261d7567b2e78fdc27561a369704a2a4670fe3ba2842f8e785f22d71ae3a7a", "-fdb66b6f379ec4dd464c7cb6384535f7e2c104e7a52414d883ca89ac4e220a6c8b8e665dcab8b58910d69b2e2b8a233ece966d104664e4b2ddbafc6748c3678106cb88f97c39fff14bcb7a67145bf03bab28a4d7c83e0957fe33267572367eee0e0588320298fa83f66d718cf05698f2e2633f52dabd73df6937e21b8f44dbb6669828426ebd38bf4055ab3e94a944837cdefadcbfbf98ba577e3c0a94007ade51b3545460231f0df7b3699fbfdefca898f56cd3916a0b17b97785195b9ccfa7ad052be55e2ae2607eea9b68ce278f8e61ad77a242c4455ee85ba4ac65b510e34bae84c30033b8c4a86b554b35ca99a500d8f464e883a2e3030a31b03b682b8758242260d1cf18055de270bff890e207d54e7f7d87b88c5040fd0599dd968a097e60de3d64952f062b1e4c9ea7faa6ea4540f84c91b018bce453dbefda149574f03777361c1141b8bcaea29349d73070eae64cd97acb6a205b3e0b7f04516f6c91a94722fe731b0548a190e498452300d24ca7502ef98c1183217ce71658d4e35503cda68e9f60746daea33492b673d86b8ca6a964790c46c82f15cfe37f3e2e10c265bbdea1223b66a321031b67853c7e5b051aca8c41a7958422c54e545cc346358839ed0358ffa0943210d74a154d8a37958e81d09aa4408808f9f7dd9fc49e7104a10704125dcf8e422562fcb44741491d0bc100f19d31570a7698e43e38", "7667d96d0790f8b15b4f053f72cfcfeaca3b3117142d05d7e494436856868b97938f79d85abd2469c8690c723e36cced36a1f79bbdc134d5a4a844e172699ab9e3952923e80efe6f4058b5ef73b72cf5a7a833e20de0260ead793828b79a64342a371ad5c3f7d408dbc77290220f6aadd90d59fe733487ab01fdb05b142bdcaffdaab31492cc43b05847b320432e511c9713c5b3cb958c902605a4c993313b77216b56e3323086b183bf100876f99cb5c14eae2460a3605cd930b1ed170c9ffc6a1b5997dbe18fad37830e2345fd96aecf402dfb289414382ef1e84b06e3fc78142b53ef1dbdf9db10fa5613bae8c32dbd6b91ce1308a89aafb0f6a10f19ff8488566a173345399cb3195e5ced11df774b82dba2e61a790d510eaf635e1d89a9939f2da8fa4528000c155bce876d19d6411c3a1133b515251bec1a972689e3f50b1b7894e149fed9c92e9bc3363a0b8554b21463fc563ccb9aef14df5bd9b70f7bca083fd8f135f2aacdd8562a00f874899a61a795a4e3b7a4dfb47f5ddd9558d0d1c58e418e8a84b5abbeb8107733ffdc039e30a7b60d12c272522e212b9a9fb6b480fc647ac7e9f28b893fb4d5c076534ed8a6e198239a7fc431e88bb509ef8c52a0b3f198e0f4042482017b646d81e9329647d33482fd72ca94c0c5c08f175833214368adc709517c6788837684a10d0b2862f9af7077c813d96175849d97d88c86dff4473a83523c5e75e22ff06ad01e91973bac4e933605a1d62ece21296a7e5defc0929086a5128acd07d0b71611d7beb70e4fd63f880b82a2dc9237674fff5f946c89ecbbed2d15b24425cbf503c5b568236688db0cba7c1acb9fb933a1553c0f262516427d9b095ca7e3b98129d81f2500edfadfdd636fa850c7ff150f17d292d7a3ffe7ad877138b2ec5e6618bbfff916e6495207a3b4ef398d791c1d854c6f10deb18248111197e630e07e6f01beb50500e41ac42e5870612a22872f42d637e178783c7abec7dd6520091237e828b7b3a91123c30f088f1efa8d3f9e01d248c9c4975b3cbb0271c62ad3c3f47e7b19a7a23177150888ad2c525e5bc2dff7d483e0a0fc9b8f220befcb93af39a7a41667c60cd12efd8796529e5e648c55d5e2c4e766f6460eb7e1b070157c14bc0517bb9e4217f65c4bc4cbddeb5ed96b1c5b1796cdde5b86a098453e50a9a51426b117207bd11f11d4e6e4a9a0c58596e7fdf78213a8f978c7cbf92701d1d3602c25e251d031e7b693b5bc6bb6634f3c0ac9cc70c7869903c9823a774271f58a3c35bc67cbc1640456b615118349dd2295f9ecc31f9f5b919ad1275820abd54455c3b8ffd439b013c021cabbcaf07a74c471d8a4b5391e464f42d963f69ded40748c6f8455343e59041642a5e11d9c012b04aab3e3dd5a79625ddf4d655ed8479db1c93d619c17fd32ccca772b58", .None}, + {.Lcm, "-4e153971792a75c2266e6f822382bdbc2bb03474c0804276404c381b4df99652903c2a0721f2448f98cdc57489464e0ad611c574674e204c5b3571a08ad2f04b63890a53b9fe0d97c6d57f933b9aebd9aa14f2f5a0a01571fd1a1fcdfd2aa94086f05e63031bbdb9355db0548380edc65ceedc928b547ca1204997148976cf8673432c0b0447588941a64ea55d0074964d2914805114e5035ae1c4c33f856390037b61075060fb6b88d509c9365d85f270896d55e520790873d253a939209f2354d647b2c8db1e0cd23719b1537e4a910a01f887ad60e9e047f2ca85b9684c6c3bae3455be3dc3705c26f319a2663617164572cc0b01c1d9d1f47c5fa1ba3989fe3e7fd8c3055d43da8ee2b8f85096a7100fe4d6bb1178fe81d47c1b7b7943d4aa8a07f1ce79abdf2749aa7f6a132ee558eae0841b863989b1ec066ef42d5870c466074817917816acf5d10b5cdd3d5fd1bbb54529119b152ec6fc26b870049c6431e7d6937df00d89f522b3f5198393a57ed72502afc164bd04d86c461114289b56384fdd46b35b637ae560b83d2d63a22a4507eae238e6853e82a9528c101d0fee3b3e8c4a06990ea1ec5d80b8cd5fcab25e4a67662df94f72f7062f4c12ca0ed88b448191b0d9bb94b3fdde2fa848e1f69c8ec092bd53028dab79e030c60506eddf71959922e8f09325df3a1a7626b8f95f5cc73b9868d874b84d80ccff1d", "e0734cbc5806eae6ec4613a9b9718815f37dfd977057906889c3ff277a46950b3e7e5fd8935923d571441f393fd7558363a67c63b3bf5aae804957e553e4ba0991d025e7eea0147860213592604d0aed455578a1f356d4d045f25b6e327e87272a8d3e8a9bf24c25e592e9d7c95e811db679afb529da6eb73ed98c8b724b672fb136561591f4b07a3a5b472bf8eba2cbe50a4920615df4fbad4a156cf191e441ffc9bcf6449addb2e0e2f1050c7806cda7d0100e23a742f0870c786270d3ec3e806971b9f510345b6b35c6a655de72f90bbe45680cdc624829c6bffbd7562a3b67b778078e5a2f9f368d3ef43903429bc5d2bbbeae22d7072cc7af7df13574709107d29c0236db4749e3b5e2728f4fd96a247c716398604077854921027caae6e961898aa6b807568a92654efd08ddb9b697349dccd880acd2c71053666ff19dae0ec80bdf572bb9f2fc4508765391ac7e8d39ce1b20860531d9cf5da3aff38ae355f85b662834d6a7b443d674b26de9c558c7608f2324a87104f1e102addacb0b57102ca0e976740118c9b791b722c9b064cea0a42e02b12c693e18a0cea91367059e4e67c951b386ba349088e0ec5355ceec2e23ce129f07756fa35c6cd19888f25bd192084ad7c6565351994a09ed82ebd3cfac4d944b33edb0c21217342dfcfd74fb678a4cd5a2f82d94b02f2f1d9c6a6d94ae2f85fe716944055c975ad", "4475bd33d77bdc4e8defb819ccd995cd3ef61ea6642b83463e38f789d9a33f8dab5453203b9da529f91002f1e66d4c3489a493b2462b0b88c419c60d57821db632fc8462214f8c88d0f54169616873d808abe7cde777adc1290d86ab63e3bab86c9b712bbabfc5454728068feece473a495d531cc6353be7c3740de9a11c1d630039e1710ea7abe8f0b048856d39dde02ab060478cbd9a9b56f824c070cce5c4871cec48da5f3d55b39d283785d7a0fbe3ea41af4cf51c463d371ba70092e9a64d8565fc6eb78113de476e18be97d3a7f34ed92920e8d63b1fe1ff04626c113be35777f1d2e8b75300f7680152cb4957415dd9d343c5705fa05dba30dc1441daf7f714952cec1890b96e0317b9b0c69836d4572b60c5ef02449f8ade2613b441159152cc42e4cf0080e694965ea3425dd11954914b89d5efcdf1de1121c1ac42e07de11bbe7ac80ca50a1d334f3b6c4c5a1ec8896e4f2dbd71afffea22d5f48bcfc43af19bf67465a32fd43d885191244253b616dc6ad39fd846043f0408c6f0d4ff8165c939f3d47176c65d4110cd51a4d6f28031125c3ca99c6f61c53293f14e4d9b93b0587df6fc11ca6849330af17a86f5b051169e015cc1fcce493f1cd56e47abc8e703ba031e0eeff7bdaf3a51be708a9d53c432afd2c7d40a5ef5147e620bb19a7fde40e3bbbe83124126de09999c2b13cae282472cb3d91a12ab9fb4a6ac7b43f77c5fb662bbef5d89bed78e3a38eb7f8f38f5501d9b38c60102c8bcb72262e846fbad26d74f46cb5d3761035f087fb2eae09e41a21a76d3bfbc4d16b3f5186b6954e9fd9557cc4c6cfdc73b9892acf93495438810db421bc1b7584ae1dc9ec1ed6cb61c9ad751bcc2fb5d860b0071d5fb8787c0035dca2a569e300bbffbc375cc17955e2dfc3aeff6c6504f893aecd065a399d6ab62017cb2cb1a9318a875e024133b4e939ca7bbf936809d8b4fb9297c26cf651c892abb6bb75c9f2ce35c0cfe8d4b6b9f10fa744a26117d32ca2ba5b585b760f2b147ae88ef1e8109b49bf4de26be0b026164905c8cfdb5cd5b50d04e280759cf16ed0538f6752cd41269fafb4a8d214619f42adfa29095f512a12f33a9f418341d4d003047879207b55529487b7b4ba231721259d6e3c1c28535c6025b1a3ee9ea24170295e2fc36e522b1a5ebcad8a90daf946a24c3cb91bd98a48d48eab8e4f1b29a68fa7be34456f158dbed84d653b6cc2a014f0b9efae16da941123300ee8d1702d78231ac738083c60a74f45db736a0824901cc606c3a5506bceae6030c883c9cba94b7c38cd0fe8786ecef40fac8fa59c9c8fde5c15b41403675109773d4337ed88498e43da6fc4e587263721b3f8dbca82cac969ac04435db2beaa6607f8ab465ccf62e9e52801a1ef2e08abe393fdc4c25a6c209231abb48c5008ddf4b526a9e5a799", .None}, + {.Lcm, "7594b1713cee5c9e0cd66621bd30d108966ef6ce14eeb9009a84f65a2c9bbe9ec911fd1d78080c84bd40e5458e40ac5639e584451082257d4177b34e84384164b1e6a4397dcbef2f95f56b1864dc6fc64831038fccc11e7c2b275ca596ea7c700dffcbc1579f293b9ddcd55eca55ec45e1fe892d85a399cc85e0bbb8a0ebdc4d060f7226b758c193214a73d951052668483912cc4f1016349a5be1cf69759b70f9be6d0368792ba17310543265477d3066aa7b87c4171fe99c3968ce70f701f5adaab915d304c552ebe4c0f72013543fc5b8bccce50133ab3bc29aa110efbae4a90aed3639bdbe2eaf3fa79f298feb8bc4e674526af4e266a7f3da162f28114ff9d8a0c63396ef743174d371224a7e148e1ca52a3b1f2dea4ed247f2eb8edbf2a1d1f96889e0afaa4aacc113d01b2f30dfb408e6347ce9e09fb1128a87e6291697b12941fad20369e0862ad8a96fe195661330eb8fe3581a880d7f1a5ebfa784c0c0b1be0d887098364be7141cd5ddf12b46a2b746b5b474058971f36764a0d41a3118ac0efd5f4034cf7237e61e1b45ac438c8ce15345d347b2f7961ee9e05e3376971a799b6cf418ec81a7004d299d1dca3c0ab3f5c7e8d32f73e8ece71913a62f6d33e1a0c48278e91912106c88797cbac70e07234154944a825609bc5ff027a73520eddab67686364ef17a28969e26b88c4d9ce81d17d03c81695640a206", "-818d5b9b392ac4a418391950a4c1cbfab6ff9167ea73f6dc3602356bae7d77395d333a529f02be7b27f0bc02d2cd8c1cc7526c575d8b06b6177a389bf33219481687179ea3f6bb67bf04e1278f1b6edd61adbc72ec189fce2ea21377d810b6ab8ba7a51395376470b6f5daaaa1dc4920dcf5df931695658d68718c41b9b9761cdb6be5c4c84c78d8bba5dafe684bc20ac8bb1ab238c8dcd35ee6451d284935c6a165ec4747674fa90a2695b9fc90f15b8c2964c8edfb0f6ac01939c077e16504d0a8ed86e501de3c4394c70f70f0ae74f49b7bd98ec173f0b9877c5aae232a9d97e67cd61f11b41f6920e4593f1e2bc0dbe0838108ef92ce1b317c51b038eb48a8186965a5280b940235f0666a9cac9c8335cc1b8efa581054e3d2f3ac8109a77a3d3390751bdce22e2a4d9ea824cb8490d000528c65ab7d6a5c54681ae957182d8aeaff31bc403c8fb766fb75bb7b24f29949e67e6ac56278d45c4bf1644a5de83318eac08dbe07ae88b4b89d56201dfef974fdb5a0075ceb84ee72c3f0b8567f4edbf4bfedf9451ae0e3efc0a781e8606accf4bb6abe5b0f4f3de3c5942dc46cc16e13be5ec03b1c8eb24bcf5ad3487429bcfea8e21c6e1d48643d73bf87d341c373d8a2652e8d9e4a5a501ceafe330df26b1fcfd357cc2b3a10f22c3cf81f53ae87a22c2ec1374b41c87467412d10b7d3fed7f29522916dec5cda0e2fdf4a", "1dc06d3178b78e32e8127c8ceb69c0b991f2d98e5e917b471ca4195dcee14791c8ae10b7e7464983e272c6eca7698b9d6192e415ac8bdf82b8a901a3ba4aaf732616b9abc52a986fbc9afa9c784b9c14ddf7313df7dda22e2167c30f93eb196b0458bdebcaaa2d8a44730adf1d71c2175748101075943563be39784387af180dc1a206559bf5b7db92739b0221abeace42dedc089125041c54c6ffce34d4a3a5602cb55549911990b0c903c1c9f77989a3af08f2b37266a3c45323eb217abe0b5a56beaba4681391772a1a65f2866ce7c6078bb71b37599a9a64d21fd3485097dd512d724d94099fabc0a93379cbdb0ef0a791a8453992154714af3dad516ea4097fc2b10d5e1e78c9a0730cff10adca46b97b53a8be7bf1cc54994e3a128d8bbc3cc1e5048fbbe904c160b5f77f00760ee8881677f599671a965e090a42968989fdcbd87fe5d0f8be679f4bdd0c6472bcb72778fc04191522497ffdf4928596273e5605addeec91dec1e6ea1a193089a94638d4bea33fcc4ba12e042cc2784c9ee4e66adb26f716c7183499ad4ab070ff883708040636479cc373db27fed59d1d6a90a1446d989ac14dad8c6742d136b6633d43c2a6ef162a51d24b33039309e9da7aa035093868a749be690e47943242e6c6f55f731bab8f68c5ab7cda450851fe49ddc4eea102341cfeee3e561db657072b469e6b4312f9ad99c313655430e98867265aa62f0dbfa2e5661731b8cd8a8296ee554666525b68041470a9ed7aa8188eba759cb1f7eec74e3abe5c6fd1a9b67428a529aed10b0baa7e400645551f87581fca36d08649647af3a6497ba4f00893d94007ad6f9321e712021fa9356f7139009a9f32a4ce4c617422ce33614e7fd64caee810dc6307dd03de4e1827574b9e2be458fb687d51f2f24c93e996d8ee7fb584a789f75a3636a814147843d67e19f097453e88968b6a8f9a3236a50a1a5eae376fabb6c6d8ae2c5c8296f4c20934dd1227cfe248522d7b11ad2f6ac85853f1dc62cf95a16420e76ffbeaf7b580c28f687fdf5218f3c0f9867c25db34c21c47277872607a5eee1f26418bcd3734b1a7da8bfdc288fb5e06c1b33c333cfc30521e7dc65f691f092133d66471674f90004442ff603bca36fb226ee58d3ba94d670710425c155bc8daf67638804653cca8b39af35a4e2249767b80f2543630e963f4fd586c1004210c332ba82c49a2d25693ee4d3c9e65d144c6b467803470a7985cd1e094a2afc6c0dccbc454cc1b5ba5446654eeba00921d1ce300b34557eb74a93ac8189f7a669cb21272abee72d1e4518c206232f2115db5b739b4ba3d67f07a1e2985ba9656a9a5dc4a20b742f5ac21dfac201f623379fd2d97123d0c53f4bc23546f9b06234c353c643dfb3a45893cca9c8ac26321e7fde688071cb4ac2069d72d1082095535a77607de", .None}, + {.Lcm, "7887a17488a537be9a1858ea7cdea6b50ae006c65a8379a85c8e381842f7e718961a18ebb3d61e9a82a6e93b9916117ee4eb38af678b8a4075cfe1e9e166db7e6f06285e0245f0fa934d3e1fbd02b2a2922d2879d375b3d9dd4e8bf474b965686dfe84053fc6437f2ffa1823f02fb304c0fbe373d1cc547c6ece74b2da294a281927ae2926f945169786de368afb7bb1c0b37c16e665e8d70982557c438acfd2b109198d7087a80275caa9b6600fc84ee3e04050d9a26f73e465f8d49b5fde66bbdec2cc9ce5ce37ceaf676c0628af527069ac69724b54f2155f6a618fb56ffddc7783ddbea3b09fdf6255c93b78f5bac04fa80d9acab7a26f6140568ca132353adec486e8df1bc4ea48fc76835d38256e8dfbb1aed94d927f87c5a48c6673f72ee0e12f264d72d71707ee7d9eeac9d4b45e5706763b89bac5f7b39aa82ce08e78f8d200566707b9a462c9a0e940dd10138c36ce84974dcd65fc4665ed7fb057acbc960da4ce9c7582931d4055e8b7afe922e1d6d5ac612aa9865d778f8357e9cc5fff89c8a618a9505b634c28233c4dc3ebfbb457a44318b5cec7dc7fdc95c34be3ee5d6142f81cb69eafc72e729cd567b10a9fc24b343b223bf64b6f17e6838105ce343049940d558cabd385e1fbd5c9a4b872fc01d4264405389999ed5638356e33fb0b91402d893facf1f5bd6203861fe9987dd0af8fec3f2c36012e658e", "-b28a745a818c96efecad26af9696cf654eb430b8b8ea5e4d34ddc25172a2d509fb4b07506819a36de660b283dbc767020f119336c9b140d4b2e282a45d6cab9a68943ed868c2f4d6557b440b8b792ddf3029228d487ec99e280edbdb537d841b1234d362ccf713ce0cb0aaf30773a70c4ae67e8b453849d8b9556520d6bb11508cca17b9e7eff02a81173bb7ae5581520390849f9ee792e98acf44b9ca044e5ce90a5b9ca9a7666264d280f24036d230f6f87abcca1c9caadb19a84920473fe8d0b4df5b0cb83cefba5d727701b77951c4c439ed5891199c5e23880125df9102b96b95fb27f5bde23738fb801ec25864708dbbe5fded181284a48de42138b5171b1ed3548c5d19f1cb64e433596aaeffe02c425a0cee33fa65baf09abfd83f5d0378849ac0a7df64e76d46f30aabd66637cd57f8eade9da2356bcf4c6c908dffc2cbfe22269588f7763513425ece87db5f6bbb12bfd853aca7029e7288bf4ee2245fe4b0372f4d0cc5a7e7cf06f4150a19b2e0f767c7218863c3891b420128569d3b4b9e197def732e264a883d0c04d12c5a89deabc2d1ad4a4e018d7c70b35bb4eec4ca05f514a29848bd9284234d67b782c1441860c1be6f928f2f2862e008e30236c62bdde8e6476b42b0ae6ef3f295373900e635758290e74e00620b796c0da3bde38e87183f3307f14a39c405f4c4f02af300c53908804bf9969fc63071", "540f7e2821aaa44dee7a83cc6e2cb20404801aecd3c310a002ebb0a25d5b89e97fa23da80e5a264ac7ab6eb07cfb49fa2af20f6cfc960faf87f1d604a1c066763d80ee71cde185b53dd9474c00628da5d70985093ecedae051230ccaba4ebbf01311b54d95d9583fb3280ada504c57fea47ad8f51f952a5fae488ab1be1b1a6953ea3448244d008f8c7cd0c570b7635a8129ef6c34f4454774a4a32bf0e59a799e6e08b8b730bb6aa31f8c6df6532508554fc659dfcecd38a0b9c2cbb80874dfc38a56505803e037b13451dae820ad700ce0190e18293499d81e1d81128facb6ae6db1f97f256ba441d3b728aee9197e6bf59fd3cc3f44bcd6e7f5e4108444b33263f54d538d6c39030b59366ed2366105e83729ce3b405afcfbe36b76fcc38afdbc4b7aa2924d239b1c792c84d86e9f2841d9855cd768ec040fe7c1aa0d6f3fdb05166f0cd14564b2239ff7dcaa417826171161a87bf55a29458f0207a1da9c654f4f6da99451c443342436048f22275ae70220126373d50442bb95f5d4407189713486635ed9d407957db620d4b8b97f5172b4adb7893b48415105daf54e6cc98bf8c430be39ef4022eac3da04c2c83ad91df846605a75959ffa75ce65038636977b4c8bbeec6805fc5c6c93100f1628cddbf2b1ccecd9369bd3c958ac07c0960c024f7037bca2b48802e9827d47e215f7e67949e5eb24d87ce7b83a790c35e7229c31e3600ad9a423717748deeee6a72066a750e605edb179a787c66e01ed9dbae67611849b2148efcb4912a11bbcbafbb540a85ba19a373084434652e1b0e6ac1cd89a98f552072de5884f7dbddd570b0b7acaf1fb469c3b2722a79eccefb7b1d3de3791785494d7db77b775b40af576b1895a571072aa2194b4e3ac14152db356647ec928427213e6adf696f3304dc36b77feeff0539e6946b858cf1eb741613a37ec62728df276da2661559c7aea219edb00e66cad2d1f1e939ce27fbbdc738b0274ee22eee596f0871bba9e76e98868093e58929aa025595b44b0fe17b986b964f8f1e43db04d331e70bec97469345cc444ea50d2654f3337d1ccd984bb04915d19e90e81741391c33544bac94fe3d1868877b1e6abe13e1f0367fe960bb81b144f0180eb1f8117016fd90f1efddf367df04014768d63606be9415331fec0d6b22246fbba25fdb862a9221baf628e00fb75768d19f3740889598e92b7cc1d4e1c4b9e83c083aa742f97ee454d64b0b6fdc90b2494bd5723dae8b45bb76748865c4c6307238e5bc4fd3acb155bc004cf42781a015d04d15fedbe828b820dd087e61437df86a80e409e4572436c49e915fe54006eadf28cfe86e130f0bbd10a728e1a5fa55580b27d2dfc4fd190f2d51ce44bcc43b3eb52ad66ec99dc4b89782deff8cac1ee1955256498883be0cb804a852ed834be6f3dfe38f65973ae", .None}, + {.Lcm, "-efec6c10470adba6e4474bc49f451f94b8a3394daca8f270d0ead44364ffea48aecf6e9824e59259aa2feca26fd8aeadef49605526e77b4f06bf50bac2a95112a60786207cc6cbd09a69a59f2726900b0b121eb2dfcb7c1fb33a141b3695d49b8f982c12ad02d8138a05cb991f9a88dcddd95b8940b53bec5a652a738c753900821cbfd1ecff27559a05466f95b27e6720bee70c1bba5bf194b70090f6933ec992381b70635f9cfdf40df6b1707c7cca8fc2774b900e692ef34225c11121c02c1a308388a7ebcb12a58612862fe73f5cc169c376506c9491db4e4f44a65aebdcc6fc7177b657540eb4fb543cc0deb4580c2bb0b056683a3f1697e670bf7b09adbb77557f9ac982c8eb11ffe520b39ddf00a3cbd923bc301eef0e3c23cd62bbd6b0c773ca0fd90efbafa5b1cdb8f722b90e810d11b270cca71a022be647238c20f5d960ff8dd2adffa8b9cc71a2feb9c98001b7830354963f19c48b98ddf9b4c4f28ca8be23284fdf34619df0917d570921ffa467ab96f752c6a044c125e752fecefab81a38efa765045981200fde328f302125fee05f0971d82e52aeac318319e80d632946eab64e981e05bfeeb9413264e9feb2dd1dd5b239b7c2c15f984c827e9d79d9af67c11b6ac3abbaee167a64c11e6feaac2b6da67270dbd2cadfa24128f2a9740cff5bfa41f78ce3f895f7fab0bbba552e12457b58da18d08188ea80", "ee8c7b97ec258600826dab895a4a1bb0d41603908385d5ee9c070bb59ae6759079377701ac2d620e8c3077f08087cbfd7fa1859d3d3c47181806e8b1e06635c3eee93b5f61214ae891a042d2872acdadc44d1714c6380827d6a86faa23183db52ef0d847bb4b7e8ce32a552ecc208d65d3a239281f0bc368b145ffc9fdc56dfd133a9630c7c72be8fa8d7d823018013050d47009cf0bd4c057edd03fd7962fd388028f1eb156af229576e0435455e734f6972fee1d9764562acc2f90e2616417630a2fa0eacdb667111beb385dfaf89be0f2e95a6ce4ba00715849f624f1ccc3dd7abf8a2f3cfd54db6829b72b9aaa515b8909109f6b5909ddb2151274f094291d3ba584cee2ea9e8fb5ab3fe33e3bd8ed8b1a4f168bd47886aa6c84e2690aac0a7479b70791fee275f54b791b16233b26d808dfb42a1a71d8f0554859b6a06c1c76671ae0b6138d2dda5d5ab60f7be3a30ab7cf64cad799e1e432d91779ff97f8817d5d189e85d4e672831c45763263b6f8a436b7a39e17ebea66cd10b4a6d0eeb6f44a667ac770d8044d51f5f6571690be949dd9f7fd9297ce81b6fb483612298ec9b812ae18ee024ccd4d023dc6be735fb458270d55d483ea23f85b01b41fc685056313536fe874342f9903144ee20e1dd558fb52cdefc13061704fce853d8fcf565f9f594e6a7549ba8e4c7ce37537229f540e9ac475d222de88790dbeea", "2542e8ee88c5f00b0ad8eb0464279b51e5ca1ce0a036c2de468be4eced826476e1721ecfc290ae5f6f75a76e2c523eb055c391ce31a949f39ea73bd11178a038e30d775ce4f02de7542eee9b0ccf7c6e933684a4c9b5e5e16ebd3416d739cbc4ad155e73ce644e256e63431b773dece840e251b789a79b768fdcdef39ce4937ae1b7206de7fd6aebf9fdce0b1efff63ca2f94689b1aef06d3fa628dc4bba974fd8d14453e1958606634b58746581d840a8b21e52b5804fc18f8bc7a42dec07450a0f556e584d0370edba6c7271c032ba8f574493362de8d129f490d114f32fb041d597e55dba0702f0eac4da90cd672f7a5e430dacf44a5a6c7a3d9da2ec330e681b1b529089663324638c97701668b2ed69a3967910115771bdbb21593b3778acd30a91eb4889d50c4e4b85180599d2344fa059ee8673370651756b13ccf33f7993f3c6f31b47bcd425bc0e9c1053e2d8a3aea2c21e16dbd8c05031e16b88154ea462010b052bc466060a54528625e7d589acae7b7b72d9658b1f7c38ddc90c328908c71e274491381896b157f155e56120ddd14ddea829fc8bfe3e26c717b07c8b62d6cf183dce4a8a81c050946a49c1955006d4031f79036c6a4f3f5be5590b0c7fb1e30ab607e2ec57e5aecd6f6d53cec99dae3bc244e5b458748d2b16047d801127539ba866c354ff8f773d6a596da83509856a538274191774a19086269ecc66e5ff3612692a3df63ac0fc259938304d08647abc5cfd1fbfb415aa69760e98be5268fa97d7c945c5f2990b14e5b7fa947144011d83f4ad51cda4c3db0dc3a7e66f71422997a593f05280911ce1278d3cb9ccba59bfb0c5c2d29f00caf43acdbcef2bc0fe79bfef6a29fa4d06ccb02a8a24bd23dd3e02ca0c43d363b0b86a862c0c873a419ae893c9b696b8f9c979a6c177bb14ba7f6911e56bb41802c9355843baee6c659013beb4c94c54e62b532819d72b2adb167f71896fc5f81a6e23d46927b8e98a06174c847c0a8dc606f9f4ff409d3c74724c5623a7ed5d3be8349bb44c13ae3a8c12f557f999c133afc368439b7a0d453da9eb6d4afc0dbf5fb567213378f47d36250b46b040114f396a5370b799e144ac2ae2df3096ba5b7f8a74636bf51c098a98bd51250e2d6ee3615f546739b8cd425d391d597b249e815e97ff7e4edbd5577d426eb3992c3579613aa9189d83a9335f45aca1b6db83443d3c144d2d0bca844f84c6d5ae4ae808324310f0cfa2163e785ff7c63f86a06601ada311a8148882c6d964e07e7b53ebed06fd8c9ed1856196ffdb6bf10e3bb229c24bfd50a27f2fcd5df8d46d713424ae3e67e768bda24d61e88f6fa86e80c3949fb61137061a69089dd7f9591ba76f46589e12f6c7e09d66f1209ed1223edfc3fa5b65210abea9729dd2a93be7a692bd29d29035ff0e9b6e72379612483980", .None}, + {.Lcm, "-ad438016b32c5a0c3162d0e65c6ff5d07dd54c530662ff9d8822c85f05bc2e9ec51ca41a09383ebba7e2c7e7a86990bc514b26f1cb583cb1149bf26cf931af2ee685dbcccd33756f56ec24a2f13828714eb27087894f01647ede61ea988957895b846691140e92a71efe37bfde1cb0de75f28d6059c2e8420141a700d269774e62ba207db0c53f8b47c659a17afb4ff5aa2ed2018cf302501e73deb3202c6b24c5e9726dae62c872ec5738f3be82ade69098f480bd70f820e475f0a60907bce57b6ce134ca72850742bc0a8c810764a4b122d96fa42441ddae0902489bbc134ceddf6898add1b33e9f8c1cf660494ec45f5d12be60e038e8c7f59574b6811f4d03640a3bc94bd0d6c667bfa405a038ee029be5618a22ef5e49261781018cf9459290e2530dd35897feefab4ec0be58dd819a951716bc148e8927e1f8a2366203c30bcc5ac74f5727f09e0021ed26a68f0255a823234e271f086cd6ad97c62fb295e5ca63bea371a6ea6b7ebc2b407574a83089ffefe68526fdb5ea46ac31c361f1ce1d845eab3469e8cb433c06ff4d25716b0f1a94573fdd9dc4f5d7a7eea1938ece3afb5a34c571af48327be41b6ec3e0829f6b3f90c0ab549f8262ab30559319bb2ca0a218400324bc0f262194ae4e12fa5b83d373b930912c7718af7967fac84422c49787c2474104af0b14ec26fc9742b1e84292e6683e0080fb1c9a82dd", "-a90ce46cc2f96e9c32dc1f6d28e835f5847d66a5a471837456fb3bc5ea2315756b39a7071632e28f870080246103e1882bce08d27ba2f49f6224239f578179d8d8922f154cf4c4a352c1d8d9af4d67072885b9818cab8c3e95dc4fe620eef81421e6ca7f484f6ae99f63448825d077f8c075479b811b466af111a621217c6c1d277242ffc0f36e50375cd0133f7641b0fe1d05729e428dffa5010928ed1263418384176ca31a880b476a35b62c3df2057d74001ac41ba60f449996ae73339d63a87b51600170b6b750fd47fd3f62934fdd839285d33dfb3c4174e7b99bb0b130824842d088b156e9cae54679bc08beed1195c1cba92bddc98f538ed74e3bb44d8ea0eb21cfb52ac78c7bfce3ca47bb1a956109fa3082e45a028c1069fa425814ee3e2dcba98a633c417cf616cecf8bc6f74762ab2888143a35f0a173672ed8019b681568b27b56beb7e1dae6490d7168781166a156d487248a29fb3e671217c28b0031f734e229cc7e25a38512dbb7b7e48e6d494fe4a766186d7cd1fe5c05e16c0970cbbd887f5fefbd568f1b816a36870e28fa99a64f69b077eb7378af24814287855ee482ee4fdca44b77def1059a6eb10b1cfe249072c2ce678ea0665c9969dd3eeb7625807cbd3c6bcc13e2f727227f80811aa925bc8486e243adc9d051fe90d2a6a00ca37dadd023d580e17cc83526bb4e58f97dab00c15ca6ecb6297e", "726a4952b7dce742de894129570134e0615cf623e59f480b03f2530b51de4c30e562e973956c9952e94bec57050af52389ae32ccea0ec4a39e6796bb33190abcb3ce7ff0df04957b951b924ef34d6a2819ee4c80291aad0f9e3a2205f2ae30ca38bfc5335f3fcf78e24c5bba587178d4db87d304ead034f0710015f82013bdd3b590ba2b386d21558ee52f02fdd7a7228d240123e78b49752392775c9c0270a8fc1e62cda871d5f31f355ab3339a7cb4c2e52bc33b3ff01f83043051fd28f65bd350bda236be938d82dc3d88886dfaa1da83f83e9f74a92516c512235ea04f4c626ff0787ea7fcccb4cf58418bee09e4b61e5b34d2218421f49d6f6bea2f85279db06d615ef3ab00c1556c7794a7971564a88aaf1ea98ab8af68493a76c79c8309bd45693e4a77e0a21428108e039c594c05ce1d92f7ac25c22b96244779405a095f004e66fe55f8d2d508580e8bedcf443dc9216b17b2a890ca98e3907d9be6d2408c036243e4d8689226eaea1cb8c699c4ac3793eba9cd157148700ee3e1df52d35865001343ff7841c64ae3230758a72703a764662921435e5aba8ca141fc824229d29d4b33d9fc2fcd4d8757bed26c1750c11038bb7e4e8800a95fd3eb4c7748e51d2d66fc786516f60d3d9d3db617222b53f6adbfbe496c33ff03cc6582f4dec44574e909acb2f8d1941cf4f993f2b8abf5b08c5c2260afff65eeb69db75539dd7a1d1edae608a7f360fc605acf284cf18447077ef53822c085391175d017aa691ad9e984a844241ed840f3ccd7f386017ae401f0c2f1487b06e0969c5ddc378665be25a55fe38d911be194fa6a7070a733670433fb35ed0ce9a159322c2d229fe3847ddf14445600bcf0a49ae1a45e3d6b0c895cca064a5a13d8cc7197f624eaef17d0463339ba60532b90bc2523e160d74716eff81d37b11ad25033c5f0acfadf9d486931adb4c2646b7797d335c84c705b5f7d1d31addd7beb8bd4b10fe08576651e12bac7d9027018759d951bf2a017f1dcf94c2ab5e9f348c5881594c23f01db7a3eec6961c689ce25e352bc126fa60329f78d614572701a177c6b14ab96ad92df9df1b071acf2a84a8066c1c05d3db7ffcd69e4859e74abf7dc9b3817738bcd253d81a3044f7f4d877c5100ccad3341cb8de8e2b72bb1a0ecd9e7a6c71d04feb5ed5469304a06d82d87f967d33144a2a273c24786e247c8d74afb392be1a0a577a30911c370a5888da2e849a6a2f62edded44c1ca535b45bd9dbd3717d498145764f1da11b631f688c755d01474feaaab21387a77f06121dcfa4adbe845ad41ed0e842a99d251d56ab80451486a487aa9036fb0305c6387b58dc37f057e018ec50af8bcfa5870fdb4bc35db24295698216eb38e4d7a6fb9c521b58cd5a49ad25995914b8ca3c71b04371296542262a08768b785a1c0f7981fcdc6", .None}, + {.Lcm, "-ae934a24ee5135c3f191f6e3eeb574d2dc91ee48d11c61d5249d961a307a568b9caf82f9d00065e6f70ac23d7a57a84a9774c1e9288fade87a42bb479db71f6cf674fdff9993c5f164f9cc0e7b8637f54b3b0f474819e96eb0f2d724910b3d2ad80f00ac4905a68bb328b9c56987e85d85d817693fcd0e6d2bd23884206e83078d0cecd31ae8d7f1d42755763c7b3887b38b1b1d7623ef3a854e33f130431618fd30daef575d42f1e955f1914de6d9c252b519231002af96b0b99f8994413b5eae4de50df2e5412651eb61299c83e66dabb3b66f2c463275a03c4fd7b89470d1109b84c97776bc1729eb8d47bddd6227fbde2ad5aca0207d109500984713cec9725a20c9514ff5374e8fe04786c58ab94536010e301ab0c45ef880f34605780a3d14cb764076365529666c53a1f3ce603308263ba11325b961b72a11bb6cfe6669289a09fde24acddc6924c981166040ce565444924656afeb68027cfa276ec782301ba7263383ea1c1fdd8a641eb50caf4297af5f6ce2b6707de8eb4f1c361f628924b056f6ca3e2de3563b39ad5aac3dff0e7405115ad32bf031ab1f10ec3606f4901cf29ba16d2022ecab2fb3afdaa1d0a203443ac0e061ca8a0b01aa12ab4c2aac158c66c85eb2521cf1803a7b54a8cb1cd4e40e706c5cd0dc4a9516fdcc2c423c9b3ea0bd849c84ebc6f0657c657714750796167362ca814bf1b7bd71e1", "6664e1e9ddc013a206ab20378138558304eb02817fb3f7557481c1fa5afa54009af510a06271b930c58feb5fa40ec8de6b9c7ffe476694bb3ead70467bd2159e85fb01900228cd4c71312b4880eba8fa0b3d959cb70a606206b5f88e28bffc4e482b18b627dbc8785a43745ef452273d0ecb2b74c4c3304575d1e3d41da2b133a16c169bdd1b6ca67e810e4db0d353150b657519dd574cd6a9899f41b48665f8510425f323ea7be007dcaa878882541be9464ab3e3f493579d02241f233917c631d635309fe45881fd087cd93299e60407190486438e606b468d36fe37dab59ff0ce9f837b52da2b164dba5a5bf33622a56a748be3992dcb9e19ee01cd1842d6c8f47f581e5aa5819e7ac81ca78b76df8eeeb5e26c2d797436c8978bb1ae1be9ab369e711f03412ebc78b4040cac1493649c221a75a276bd31e209201d762c848e393cd3e34d31b5863a11f30b9d03eb32ce9a2fb0898878d59f0e3c179fa6b81a6d9075b5ccbca5a8966e0c6d2afba74fa93adb8cca5d95bdb5f83066223f99dd374ad1366ebffbb0f04c8af651ce2980eab46c4e2389c6cb815bd9d8413e9d523bd309dc9cc3a9d168e54cb1afe72e3d86beddb5c89cff42588480a9d833915b45ecd4ba0789988a22bd9f121b2efbc41f782f4537c7e3bb73e1fa04ba8316d7e80db71c7c60556351d839ae82801d706529e3e333f064ffcce65b0daa1835", "45d37b229cd2871444a6538462289c57f905702932a589f4f92ef080a3b0c6410c1acc35a7f1bfa253add100c3161e8c3b0ba7cb57fef6eb912960d7b097de6aa2ee53da15c77aa8a6e725a508397b4f9e87079b6ee83e5b19cef3c9765a49e0e23a4db5e4829912cbe204c56f8358858e368a671d57e5f4c70c7c51074fc930d293528d9bdafae3646622d242b5c143634c4fd7ceb8bdd8e9576e4ff21f97890a530c27d92f888c4b0c6e4297afff603f23209fa0e4499cd67ffbc642979534b2f4eccb6b9066d14d110e0dac5a6f07acec48766a56bcf554e6038a0465c5367a7b0ee13117516ba4308e292417dd8829eb3396ce995668dc5ec6db2a845e9cf045f3ae01f148a6a464da32b2a6ca40eed3a24f070f34adea747d16579e31088c2abc9e38bca6822f32aab2a6df1cdf58f8198973d7383af9b204f2d469bf3d5c2c065021a2197de213da67ae189fb8191f25627f2213a5e22742cc8bb31d2730263c4bf6ff94ebe9c56be3170916cece662e71cbf4864a7e79aff817b0ad6045b70254f645c595f6938248cd737ca385312f8d4785bfe4155f64b7ca8587b77d40df8108f27989efd10f3c20b35d3d15d529cb580f47b210355d1a30d8515e9193b340f466c79d66643db7d21fb227fa89d6acfe3361567b47cfc878e1c1e4c6a79eff647a2cf3c5354e8c030ec9bc0c41872faabc8a6616d6c344fc9f44a0de771129a21c3a3944fd973ee6e9ee6b020d8bdc4a4e89ea2652739e6adf01b2bb342b991118cb0e2e34c53b800ae790a9e02d5f7b58739b1ec0b096e83022053b4e9b7ba6cd63ab9e50ba7f74cecca5e6a3b6ed270d2fad26614a9c120b2ce4ebac96743985a24b55c891ddb0004c6d38a4f8ddb52b08dc7d538e9c85edb2998310ebfa1493fe28c3c9f094cd4af789856182725d885aa9110ec4ef09964717d428441ee02864fa3daabab040d077ec6e11d75aac4227e5f2b8ae1d7eef64537294bc5b3734b8bf8f304c7e7762f66128353d525fe504643c8cbec5ddd3447b94c1e5b010e98d141676bcd435ee67ed9663989bcee17486e1cd98be0b6c4176ed9dd75edcd67224b1ca2f587653655c2fb9a205ed17700c1c0d3829f27fc97ac1b6cfa33837f2366090059455cb6bf2665363eaf321b07fb9356da4b96beb11f8473f6d1cd00b4983821083b4110b48d9ece0fe59a6fdc0d39d2e52b9b718a9d45dbb26aa7aff1dae2fef712d552531cdb9e8ffe1dec5efe8b998ddb1db4b56fbd3c90da34301990bcf25198ff36f4e66e05c1c52b33081c0b34763a588eccc842098aea7c0e7b301578262d56750b5c042f26fdeec4bdbcdaa508a9a5a914e1b868c236bd5c1f0ae1d590cde5cb81d2ee141d4a0f3ec20e1cb5376adbc92bac4c885ec5cc4c954c637de0b1c79456af6ba900dd5c5e67223afa5d5d94fab95", .None}, + {.Lcm, "76b1a783fdabfe9371efc48fef2f87fba6e6b55bd53dfd4debf1c63b4c672e12a7e33a698873826378d332cb60d5e053d68b6adb5d9e53f925f76fcb9b653059d464350be6eab2bfb95aafadfbf78e296c98df77ee49191c063581ace0c509f7c1851e7e65b3858225da6bed6e068e4ce70b9c9f42fb594a11aedf29805c5c9a2190760a385a237b6f37a385b66ab636b96c46a6ae5b60f7620fd9d219ad39863e7c423b27e1f3cf5f4f61a9c02681090c559e746adab46fc11abfffc7a40cb4718d0d70e7b5d8aaf5b6d05dbb041039a3d7587256216830c5c66dc1f9350686390c10454e3cb751e77a69b0401dcf17e422a69b8985ca4947b086cb4b89e1a9729ae23407362cbaf4d25071d6fca7ccbe3679a1c41ed50bfb0d7135d57c2c4c4afa246318186e2d737e0783fbfbba3e757d2382fd1860f328e0a8b3dbd08fe221eb16d3c74065a34d1deb978fed8914852ab2742725e18c4c7686c18bda097d1ceb9a24307588dcd8d77b563d59ca0ca56d6b13fb59d3a18f0675983e16c59b8e689437d773d4c0bfcd2b2d195b50eee6ff2f045beceae9c6d0fe28abdab2f3ab38c1f80d535e2f1e5a5e1f50943813fdcdcc5154b75e3609eb82942bedcfa7b18bea6537d8f6c46a3582cdae251d5ed72daa6a995deb8fe262a26b433b78bf5a8240b002a1bea63d86dda23537038becc77eee1d456f58d2f175d2386682bc", "-29a621145ab53a3321c9935e1009c66c246a71a3944144a57c178bd1de02378fd0eb7cf3c82b15ed89461db2b06504b03f5f81cf2a5f258751dd9ced9d62656d9423b41c4df5cc3d1162ff21088192dafa81dda9ad7eee1598c020c4b7a8752ff995f7d738725023c5af393385db32daa09484d64c4b923e76510a6665078199d2fc2458fec7f13361cb30ca7c611597d0d1c5f8a762228aaca7b56038d54b26d23b39fc5dd2f6693fec002502f0fe2c1f143557e61699db7447184c1b06e100644aaf0e97df4f9c9f05ff331fdd7a91441b003fe6e45c4750665ec408f425cee55b07dfbd365bbd4ba154da1545beeddbd25d9407ad8e6e2a4b903eced4d5d3e10703d41b70a48dc2e12c64c90c97a9c17c24503bde0a84adacaf32bf0380b3e6e00603ab3327bccdf1a4c09b56eb997dda6095e559a5f7718535ba21c106e3679d7598d7a000c96415c7b947c1caace63daf051be58e26a8c544d860ee97b677af13b441bc002215a0db6862e656a06612fd5114f00db5d41ea0659dae5b42a14768df3998a666f910bc2924289c1110d9fc551daab79554c7d311954578608d101688bab0b1227cfae6e4fc16f704ee26eeab83ef0f03533e25a56390d1665f704945766b7d76bfbdc382084484c39ce380be7313a044e514ec893db4958c98b0453678104daddbe8698fc4737218681c1b431551513cfb085b8ccdd904c1", "134f7a5d19be9ecb7a9fa270d125df315efd18e6ea9eb8257f3ece7ca5f6fd155087c59a734839b5ae46f7e725d2ace8cb10f2368674760494530c2c661f61a551577e3005aecee16b903a54d801d0f59ef6ffdf653e93ab7c76179c1b1895b8bcb1ea62d5d9fa14ad8ff812150a791e28ebaa5275b427c66a64d4e610c230a983aae706bd36bd411a0d368063248632d5e184874f0bfcbe7ea9ea16288aec964f4b960704c781364b095b51a575cd27fe45b7144c5d77183abe455ba4673732d87aad751d53fe82872cfbe2c3797977c79391cd3c4b2c816bc43867da7efacc112f827fc7e0ca9d1462115ce3d34cd848331c704ab32b0a4317c1d23285a6cb8d342a6273426c7cbc4ae5bac12a484dbae1a69d56d75ac8fb4970579df3c607cb6252959e7ac267ae1a9059f9813af92df2b91d5ac842bc525589e263a1874e7622ff9f378d278da388f6f2d82d1459b117d446561b17586e9bfe651d439b64ec5ca8ba4cebb3ff17c3fb966d7559a44378ddc73a5959c5fdef3a0bc2836ecb41a43341e15cdda069a7b44d599eb0ab2e23379ccc82e11cdb9bceb98d9b38dacb70e61a1f7008799a0b8d35935aad33fbbe7bd26080428c4eaf85acbc6031671df7d681169af9dc57d11025823b90c0fe86f157f4bb21e956004aa2ab7464c9fb28235a6e6a8c4cc098167df1b19c7636de5fb9dbe47310476951a7fe1ae831eeb1b142082acc452885232831f15cca08bfd837a2cc551eaa8615306f9b4c58ccfd878cf248a947f1f6d8547ab4875dd446686e628835fed854dfb36223742607aef159b5d166d8f3b4bbe6e13d9ae1c89d7d27bb22d44212979617e6ab3fb4f6d905f161aff03bb72ac7669b2a08216e3b6a8df2e7e3a73d20a75c0bec8dac11ef559d47fb664ea53904ad9c4c77f07c3930f9d58a207949458f99bff013a472686772bb3258d94de832c2466c99b097fca1f1212b5bfcde7fdbd728c8780aec79d89d6c407aa62e62898f6161ed04cc429476b48d00d6cb1e15e75a9cc1fb3b6ba68e0e7a4fcf17a5b46fe2a82ea8cdee079a9d694c3250bbeadcfcd93ad18be3ee15f5f57921533afc5b9891203d10f9337c776e0e75f2f292803b3792b07d6023064d4c340815354ffe7d5685ba6028695b32f22be613d3340cf4eb2be7cf809f640ea6a607daac44bd1246a3a26734ab81fc7d1dac973bab288e928af9dd03f28cbf467fc23a851da317802412bb7008b018545f22f32f61286cf639b4a38c52d61d9162bcc5f74351fb353cc8d5639a67d798bb83f51bce67f71054c39296b1dce3d3489814bd716a5a52078bdb96e9172bb306a71b0c7be30c6f0744e93fc79dab890824d9172fb99116f9ed91a18a669418e3dbfa5a9f71b9b765aa9f424f444ff170adcf16cde4c7d3eb71c4020f1917f90dbeb6a554c37caf7fbc", .None}, + {.Lcm, "-4976827084a2e0824cb346743c39adeacbd4cfa46d81b0c76923d256b7a1d83084947bf00b769f9cb7ffa161e7e7acdc55ab9e61bbe0da0267ee50779324ce6a4b0ca630d1397d38202ca92d5e46578fb5565fbff92e1e61234960247b358c448520c222aed3e9170300744729df2deb9bc9e32e0de940c759f8b2f60244129fcc1aa030494946dec2695726293ff64d337cff1b28d826e3aeda9909d297a70d7efd4c5667429199fdfc296c51538c5ef22dff0d47854deeeed2770240a5d0ee68100eaadd97571a9a251f618ad66ccc480a283b7821550c1b534800612e3e5d78e0678fd55b49a87cef81d4aa7039c960e4290d81a4a2b76726d764e6d6e267b95af123e71695a90030500d97bfe45319afd5b8755c29b376432b6f7dc622946dca46e353e8fee241463d6d6f616fc7698fd9475e6702a4d83259aacce7dcfb3b1a7284d3cd3d2f5296a1cb5d1f5fd691071d58aa671c8c6a60b3efac390c255bda15d6ae61a8205c98548360f74e1061115885961c06b5f863958116c4c35509e8da5a18fc58caab33f7d81f137035e2d735adc27869934460aad161eeb580bebc7afa2def8f4f5e65af2bc9923ec6220092578794412f894fe93746462ace4faa7b6621b10ccdc4136b170c5ae5b2ef765efc6738fd034a5286763fc7573b493f8b5b3b4a8d991b5e7b69c4c08dd061d6fb0439d11804dd05eca75a5e447", "bed8b9e8f44615617e4683f6a28c950d0bddcb27a1899f2bca789cc0e4013ab8aa03a77e5123a4f96a27f82eaa117f7e48a61f371a6e7aeaa00f8fe182cf006840ce646d80a53fd6f3cc7e4929dbcbde8b129db290c5d05fb12d08d1447130f091d5af1d8a3fed49d0b1760413aaa8a2ada5d3d92cabadc0f8a230aed91375fd0f092b4e4b7fe39518138bc0d15da2273d6d2f373de72b664a0cfeb400252dca04eddf696ee05e9398d392aabf3ab2d986c4132d0d80607daef9bc479f97385e85f7c22792f9e873298d0a2841b73a8febb8694fecec476f5c1787d092cb0adabfb39a61724a71b39df99407ce230831fb70ca18945f2bb261d66ff30ee8686cf638be4c97a8b4559e0eac5873dde175038a82ffdab30eb551afc36569fe26a433e5c883bb6eab6aa68804b64dfb7689d4f542fd9b2421d4feb04e0604ecaf530a1d74b059b989cf79b7e12991083fe67cac47b87c86f0545945eee3a6dead7a9d09a18c4c9c671b29c5d85d84c4df297ba9c6d5497933f86aa3a0a3e4d858956ace549db2b470483c33d39fe8621cffda046a9290b32ddfca89b550ca52ef92f5cbb03b3e59955719d2aac91508170a9859347622f609dd172ac4e021ea73dd743960501aa150f691bdb7a53253d278ef1bb64c1454d5a1d93532348ecbf39ce23909efab65f3607b5c5f1af1f6a8eaa957af2b4a777259cffcd809a557f50a", "7d2e0e10229a0643c644da75955ae3a861e483e043dcf6f17f0c9f54a13a2c24ef8b3f8731629f27f4dc31ca0b398ba035eb665ee22faf210dcf6ced9ee8576407bec8fe882577e0595f00305a181525d005f006dde1d4e9e4dbc99d5a57418264f7b5239c422c7b52c8fbb87f787b8ac67a8755a3ef0750a46370fb5eb0e547081c91a5e5155e023750db5c930227037d7a681dbcdba6445662d085bebab2f710b6d9215f6c9f8323013a13c1c0050e1fdcce74e25a3154dd92da33d3fbfaf98c6b11afe2b763681344bd730ffa4e6459dc73f22e80b3563ecb3821d7f26e7278c76d3e298b75ae9e9528726a57b580752d5206b91cba77ce353c2927f2a1c73136129203808ba89388893529b81e9ddfd34a91144a31ef25c1d475a4cc48a21cf9edc9307120c632b690301b44bebfa5bff5a12844be75472998c818bd4828751dcb27dfa55a0ac0491bd429cee0ca1ef0b83637632a05ff2b81a8d773580d63962460cc133b37d7699822ff14804c331220929fc85200447683a379d3da11afca210fa49d94d0814b13b13380755a4b953ce58260e4727e0e098901899e663d5b07c563906a44ff4ed844cbfcd113e99de2bf2f3e999a6f241c9e1ad94e1c81aebbf4daa1ecc8d4112dc1f4535dd57f68179918289233ea1eaacf45dd54824b06f8097aa7d5738a67eb228088bfdf94dfeb80899f33afeb42134d0ae632569065deb203acca8c0796b310fc48b208d574f9d1e6c3309b18652de4df3f1b59cfb4709db1c18ec64fd4ab09f08e3bfe5f8ce192451636bc5c631e7b7faf86ed56905ace9fc48d5af8bdda51d0993bc7c50975cebc4146753a0641a0c00dc18b4e7ff7d44874458b0ab5d2c1f2fbf82eba33fda582e60991cd83639b599b3ab71200c4fd7a0a8d0434d629ec78d0d6b8992aee7452bd7205775d32b35addba0c0a83e29e75e019b862729ff94ff3a9982650bd171f85cf347905610740b89122057f653cc43b2ae6c88f4a488e96fe91ad28215dca97526651d16ed85dc67841c287a886cf3f17cb33e673517b62408224c8721eeb11653e17ff1db675a622c619dca0229d02326d81e4c3efb4e8ce3ca41115e1525c908a4de2fd213b36dbee12c51d8dac583c06348fb110e11c0176389591050c06b4edb2d2d669bac82c86c0d96f061aa77388d642fa6e3e3699a0185f5dc2852260f59450a9d28b40b96907e01e2ee5e1390a6b9be42c98ec9f844a4b0c7fbfeda62bef8bf618162a0d8b1036f7f7a61595ec558327374e1e7f58e6fc1250edaa9578c49c72e6098f3f9a588083c0ddf95720dc57b10a21a29add960d742b3895c88399d9f5c5cb7c742fa12fa4f61a2fe56bc6a8b507826336d2402fa2b9b1d22482592f32137b300a5cbb5757cfea1cf3dbe0cdd6a558f9c5d78c8cff5e62e69ec51e0aedf502d68a", .None}, + {.Lcm, "db8fed63ef540c27cbaeecd99545ab8cab1d05aa8e7101aa058c3c399d1761970bf6f81deb5aa2262f810cbfbd1ba984a92045d8c68bb7af834468805556fb565d93e5baa75bb9630b6aacf548071dca931f3676917a54068e657281ad486240c0afd2c7b5ce4f848bf44a9499eb96076108c5f12f9761b960e9ce1176cfc6e0f3b0757d37d5ed54d960b32fdd0e5ad57ecb1af13e96be91214f1fea221a42fa23443179542be1a8b6263588e77d87661c0ffc3f90d9b678fe7be1a89000e961237cce4c413db9cb4d9876010826c208d3042e776928d3be961fbe3495a438350b187374609137aae32ee2dee1f556e5148dcfa5d6fd9eee5482b4f4f5a89f219afedf7f2d76f77255a17df8529120f10e865e5b01e687d8746f261160e43c1ee3af3e4bfc7c535ef7df98159f1a045aff844c7980a5713cf0950264cc71907b45cf101b01ed0cf5d8e61093d9f777306a66e9f9db43b511dcce0cd927e48e998a19393fb25f20a7cbd89f3288bb027f25e931a32e4f544f411d96a95bc9718853b6de354a8ee705ea52ee20bc11b02f029dd8a2fdd4b3d5c373e1e70268cc3402536a7eed85ff68c6501368e4e7f99e92ed17157d6a59dcae752e74edcf5d0b1d2799196787da2a5e7e1eb45d5d8f95f68c9558c7ed03075707230a3c1a2a04ae84a57d0b877e9262aeb5deaf912c45d1d74f2b709a77dd8782a701d6cef879", "a7909cedd330ee815e222fa4ea1f64e9eb3ef34a134c1c4fd6b4df6abc64367d79210ea7377d36170089547b5ccb5c7dc75ceb1e666c81dcd1a1e3fc07b91c78781e77edc430e38b7dcdafad45b8015102ccd18d4e9eb543faef23a67df0fc02cf4eb216e65061a053d58865512fc19fc2e3774977ee4254c280d70b5bfdb6ee9ec634b7d053afdf9e22910927eb31dc43b59a6a49be18ed7066e53707fdbae784351b480a41986b68d41cda43fdcf6993bb5384535306817513d648238ebc7eb17b32bb96c2602337af778b6f1c7477889ff16b285d6b1a281057da0b9a2d2bfd08dbb3d7be55dfad126458d54863ff173daa5625ec78248356392db9acb1f7823da7a75a7247191aa074dd5d4cac818ac9a19b16f28f830cf7708b17e5fe5c7b84b154a6f0516869e7749b680157adc9dd16bf773a6b0b32604beeb8e789e934af50380f8952198aad22a8166b443a89dd8f54a8091185f8abb999a2f086ae353818239020f253cdeba362f725bfcb7dd097973699b9cc77256d447ae9e366a9d48737eaf3583a3aa2ae0c87a3a9679cb557fc54cb9915df2092783aaad2d94c3ab678d7d184c327ca77d60b0cfeaa18718c9c570dc665e4a7b1e203aeae727abb27a008c896a29d38ee296660e77f0ef33d0e55147c284748703b7b2d6cfb6e197a84fd5c769f3e036c99479dfc219f575d05ba6fe245a5133e3e3bd66f60", "8fb6eb69675fb6c5386e08a53bc5527ad57628a77b120e221aba8fb21767e3a6fef8ff04058ca7d45d11888959a19c1f0e49c8a6d416f6cebcde674299cb95e9fe49e1cb691636f78b68fbfa79362a485320d2681c06c2af544220fa7cf7b83b13cf8997449f494d5bcd1327329e870582ff1285fe0775b69c18b6f9333cb12c06394e1d90a701344385768b1a0f751da9f2cb78bc8c258b8f90d6fcab9434c4493be5b8d23b6f7a74369351a4d1ab5f66630a3ac6707a4cc670b14867b59fec6710ae05c2845c7793cded7c93d87598a079bb9aa9dabdf5cf2c40aa8fddbfdd807270d15c442ab2b12f88e92ea9f5d105cd46079ad164d468dc90e8a1a70435d437c1294491206856e2cd0197d8b18114548d2c613e00d1a65d3bfaf42685d6613f98cbf57909cf33f2f8625a73ecd6381f14fc8064c5ebed023cb70787c2e7b918b235ff58369a7d6833ee1a5234092d6edf2d8a036e5f9cc311d1eddb7ecf4b127c5580e760b229e681e7e2961f357b6eb69bd0e86ddbdd8190601cccd84ab124ea1e7b59082f78028af07272b5c48d3f070f59b8b8d002712a1be3fb616ccf7ac1b7d721f43ba92bc9ca84ba9330ebd0bbfb043b489177a228f58f6f5289c62d285b784d70fbf5f601a856f72cc1e8306d9d2d9781da254c15665fcf10b430f5363c4c51af506726adb9330bc0c56fc0e41eaa66e23e6380e64a3e8c4606be6933a9fb8e9a6342ec5b05b1dc2b0d34d7ed3cfd422f0c2d284569a6ad95fda0e5a452416cbe1597ba8c3b71fe6c4158460714daaf22a876f9eb804165310fa44351995ba7877f20fa712496cb05fb00488641e5201c736b531fe02bc5261166b7a100faa42e7364b4470645e170793a03be7a3361309f0e9166dc499aca23815a15b986ce24411b39ee28e3c24d67326e0d230fb2a883228d913d15d264f1945cb3051814e37148b0e1ab6f3cfc2bb67dc004af1f17cba91e541be952c1a676690e384a38265004be668f0b0d00066c9480a7424bb88b0ac8d651f47e7b99ffb9462033616433344feae175bbaf45b9fec775b222201b68018e4ef966114fb3acc3acb44fb9ed0de978a3cee16def550f4abb1cdafd89d2adf4f89f4a6d3ed9b6fc2eba023847756ae703667ed29709a38cf792b26e8171d750e958f729061151527e0603172f5f59c0f794a46ce5521a4b0ed9081f10e2c2a74ac67646d79b338e34052de47bc4e724e2e8b6fe761ebeabfe7f8e2f1651fea07e35bb09207cd95b76783c23b8b71b83e04c4dac5d9a8a6c47c2067fe8deec91ab37135caf0fcb73bd186779fe65f0b2363accc8a6fa3a288609dee5a6203e00263cf8b5db1f5e45abe8f826c87f208b4bc7c53921f84891c6a5d2608162e4d90bb4124e73863ff3622ff5fcec2bc4bea4bf2fb39331812a70c3986b2113bc2c69e37fa460", .None}, + {.Lcm, "-872a5e6c41332bf63fd05e5f8ff1d7547f50de0a1eba4a0bea5b52f641194b56f823f190562cc7834fce2ca566d9f57375dd4b8b014923acc2526ad3e8dff680119bf06a9bcf8b7b9a3e82aaa7d59d315a713e931399783de10984d4be62053f119f5e1f87a7f21b3860d6a7fc01073fbcc324ca3f1271865b50a77bd393695560c84cb768bb7f04b9871a3797494d70524e43a052bf2671878edf1643c04cb181173b302a9ed7ed72074d3d3c9dddcbb38b92bad5ca3e855fbff0d0178c3c1e47cdb8a55d80c4d1fe80bb54a8ef1003452ec4a6d4dea6fae71c7414f054b7cb431b35d07e32cf9bde0aa252bcb66435ba2a7f7a87ac33afc9b1799e055f00c21bc43de327f9d834dc7c454d84b4f55391de314d0c3e8e8a49e0f0577e7d14802228634f6f0dff59c2e6764d6c403e79011947c12ee90eb6a3aa4442d8ec07d654fda4b7979e8fee60fa278b07340c33de4095b39310783aff115a28bd1e526ff1cdc41bee1330381f2d29a304a290fc95a520063796c46cc9cbe5cae0f3b24c1ab0ccb59f6f3539a0b72957d182e4f57017754e27d5e2225e743b156aa63f4612a56a28a7af633faf522523955707628484e71a941cb917e8131fa2cd08c414567baaf0e167204868cbbcc51344fab813c5ef534e1eab670879cc4bd76f9a89c0c85e958aca8a44601f5f0771e8fe1de55102b9da79de1477bc462c570eedd7", "7c61c7d0ace69643309cb4b9afbe1094e3d5c1a24a5ddc73a5f2cb3adca2ac00bd6a834f0bd502225dfd53839a1dfec64770d89f6b5b696813b80c3de6d7dda9b3013266b8d7df09e95abe8540e86e9a5a4137d67c41df76848da0d8d8d359588485036505b05fb9c6cb71e8ab4c00ff7238862d40fbf24f6357df4e129678c4fcb57c4a00684fb2671f41f84e673723551555a6e98f10583695e80604354b3ec61f991a2f42d11f7d227b2d51b1c7eb08b384c2bb9aaae417724166ca9b1adb3fe5c07728d71ae1b9a0dc482b6476a3eac548f398e413f8a62003947c74ad64a1dcd6e33820ed0ea140c60f00d8efd5f3a58b792af2a39370481d2e497924c1e40a29cf5e658f1bcb54d3ec2aba2a0cda7bfc4f4cf6576629deaf74b5d21d10dd4478b386ed866fd6b199349b12a607c6769d0485e6323a0e13206963b1e64d9016a783147e52b8646e1f16d81198afe2927f8e550545dfc30c9a49f91833ce58e105edb8776fa45a0ee9a4636168ecc9e22d6a62e9417f1fb86654f3e81559f681b82c379cc5b18c061f65cb297cd21930ebc8a9352a6a0e9c56cc07cc9ddc2c3484306b4f3a41f8d169619315618f738cc6483df842d33d8109e18d3609808d94c457f88864094937ae39524d4ab86a8a2a9c5c7422bc4b4a8c2735b3cc5374cc539ee7f3d97687eb9aca3f80003baf096dacf1e53b8dc58f5e8179be0af8", "41ac264a53b6932a8e1d085687d9c32ca77c948509f796f0d8247b01ae7eb43762c05e77ee6478f4c5da8fbb6a9448235fab7e79eeba22ac33c07d870798dce32ae05640cabfaf97ce5854f7897d64419dfe5fce97111eb0ac59c4a871f5fd75760b6332bfcb601d5e0ad0e92053e835fa337f96742afec7f798fc3fc8b8ed14a4e62b7bfe068f2340e62cc2bd518601bb6418416e1ee33655bf5a20401640e8e79ce423e4bc9d8f9b019011efff8629cd6d38a6ca5b8776e35bb13019aee03a95691fe3ff6b81a590a91d93a282efebbf6d5c970b14a085cbd925574b9759069cffe45fd87df94195ba1eea5203a5a95157a9d421555b5d5f2b3a304366c37b42da52126ae90a60f5992b45011f106077eeb7fcf88b978b88cbe9f33ab068fdffbeb4b87b1c1c3f59e9f5f4331f504220ffae3ee0b8baffa18e0a0de155f0788c785c716f1a56ef5522647b4d866347fd9c5e61699fc8b96223d1c63aa50ef1ffd7f9586326debaa6f07d2b80df224f1afb3bd4f7f1d6a9ded25100b847fff8ce7b29768f368547e4c012fa33d659b7dc9aa18423bb53cfeb028ea982da7893f1e9515f700c1b94d79fe85e3ccef6b15f4d3bb848bd92e38fbb8edf136581e222bbd2d03ae165b24c979a7930900b28cf5c477c5cfc9af386e2af8546a3539a3ae1f5dc29b8ce9737bbfac63955d30583a2d9e0565a52b845511d986d166ec8c933e5c3b41eacafe360071cb9f92e81a7ef400cc41d58f7713a10b06cbc2105ef81991d5048a011d7b0f694a469d16399b21f79aa9f32fac2dae3249485c965c4e743533f5ed2ab27e12516ac79dc531c8c4249fbb024942319082b246ddc220fc0e957111088a3f755b34d5d3c94ba53a33e9fb86dbcb5ce6949d53e42bfc188d851b9e7fbb1815e048e7707e85ef36b95f9edc7c44260be29c80dc751f2896fcb8d91847fd5ba6d35b7acc5845969d6f31d00d2f6c6768483cb23e74569de3ffd4e57abed818536b5befaf22e1a47986405a8c1f1ce915fc8401835453b1b55f6bd04077ff96823077c12a49b3091b849a03e9f2644146c3a1d955a3de2e2a84c95eb4d704f8396f129d7e25ea19a7eb7bca06ab2461d938abaaf88c22f94c3bdb8cd1dd7bc4a5f63b42e2591c5cd842de1f1523b7fb3810cf189e8a783788fc4268f5ad531c72e798f6872d091eaa763cb678835877254ec268553bffb25acd7cae90e5f9a6403c3ae500fa35963d782c3338d36654f794c92b87872c221f9c219479678929d9d7b1b0905dcc5e849446ce5d3debd54ec76132e6ffd068081744cc06806183075a3852dbba3f24e439d364450013c2c087c5cb96a48fb537c412747ed0fe4ec2ed5b30c213185fdad80f9e10d9c33de3f906bc91114050d27a029f3310a9f8520bc324ba7b2c20bdca9fba43e481a800b242d311052ce48", .None}, + {.Lcm, "6209658fd4703f6add8d3f0faa8df72e5f6d42e65b9a42612102122a033d87bca93764974f2659ef71763fa44194ac5ee4713947158abe1e2dbc94ba44c80601479bca60932d983ad3c8edbacf105fdba21b1b8176075449697a7ba2820a75f8eab657e79335f884343eb404aeacbfeb0578e85c24652f2966a1925b7f338b13d150ceb0de41a0bca9f11b573c5b010c4045b59e097a02128d7ed77887deb7008ab5a21c2851fec4bcc591b77e7641f73356a7e66763db28ca643891d47ddb78326e6d4e716e1869b500af322c4a60fffa8f1d1b8c3fbf6aaefa0f817b19bea3850f98645ed710b3d32452e50df34fea4e893fa1537447ffabb63b20e9efd75bcc499cf9bb6f2716bd69c3a510548a535b1a2cd20bf8c0bd333e7aabb45a7b669f797f172c5a826a4711d67a928a7230645834760f73b49f2e82ebe05ffa6d795ca96264e3df8a54a1b579ed2513cc139215e120d653d96db106e73c37feb7b1559bf84c7c4fb8d5c3b98bd44df0befa1a664f6a6e2c2d32ba144ff03e3187260c3695bb86c82305c1a9d355572ea72121933628052492cf4ad1060fd50e307cba5569492034175eaa5e7201b1a68fe8ae4bc991d8844bb77597bb7f2c24fe59da96a713775b59c4740f3034b26236dc37f41dff70cefc8b6552317737398d55e08e6996193ea57a02e0cc9a94099ff27cbfccf34644639b5d2d20e9a55d26f8", "3d10fe5ceed2cc097c974eb4656237a88a256eef26838b15541e3387615b83db21c2250832313acb6c4a9dbb3e160976a82a4897006e024cdec7259bd57c12419cb8f5715e05dce5e98856c73709bce1adc9ff9e707af657150e9d5bb8589c8351b44cdb7133d5d737707dfbf4f52016e1cd37b2ee5c645a1266d6bd45bd0902334947de07ce702560fd6c7081d6773626ede4cd407dc4c5ae14a5d1540f5888d097c1eb047ba6d9c199d6973a6daedc4a5461819629741310606caf19f2d23d8ad713ad183d9bf3e02d41a2fca1c084a3b2403374921b9a6dbc6c0df670ecdfd376bb11e0cacd68c2b48d3cb49dfd395fdf841e5cefe0fcc972ac7d43c293424feea7ec36d0ea2cd802c38bd4eb47459f12b2ec5e903fe1b6d1488fd0a65c4034b73f41f7a52a83bd4e642fbb55ecbed657ab9358506138b465503183f938a252c9fc15fd4651e14e113a9581e24bece9bf9e7074779075bbf7d7e7208de1b96af6b1439ddb543d930ac4c425405915d00217ba00286e87b4e7c98c3ec52aefcbd17dde2a96e0adeea4cf1e5cb2d59aff5dcd3443307f3fc61ffb1cdfb62e950c31a3aa1d763eefe0cfb2e3eaea13d62290a484d394a1509bd2803172be5194e553147aca97771faf872090a43c991d9acce8c82cc7e6c8b40c9f6a16f3e358cf72cdab6f945098bc699e2da1549acd837872180b6a69f80c87c3724045c85", "1762bf328836b0dc4b31a0563f2e5e3036e53df22d0ac7df26ee2d5153627ecf3ff35381ef7c8df3b7c49792da33e34247fbfbd7c084c0a46582436061fdbf81213ff9952e08ec354c6121ac54a2dd3919dad110fa40ada27e33ad0f122f1e5440f2a4b1dd63ade41fd5376012171a38fb20da4d03381d7463f06ff9eb5aca7d0b17a9a78a57896e7b7977ccd927039bc0e882f2c4fc9d9dbe0fb96d31a3f173be81024687421a4523ced3b819a4d02e43b3b4078fe0a8ddc6651eea3e739e1476dbd604f92e57975d90812fc5fdeb4cad76d4b8b90194d3db61237179a6cedb76b8c5557dd959068fb1be334204c09b456cf67c15b355a6f1ced956c14bb6c4dbc0fb5f35265e2b06ede60ab7360e8a66c2d896b0c5892f7fb2ef189c25284778530ffa1407c68b67dbbbec021a25b7d561b1757586eab2f9e51e3493fc832fc8b8882d5224c53e543bda56c4e935db18a94f1408cd20795ccbba4c3309adede3a0bb83567d7a0240d1ad1c32b1b9c5860075a0d1dd12eff381b2ce57e44aea5162b7279844ce1571cf8b456a3aebe625e67ed4d2fe222b56710a26c626d8cf25329eed9029d8e77c78495787c254f492b19c4900a4bcb5865949a15f0c03a7a5dba9c24a18f499e5ffcedf596c5defbe78e37703b7209fb5793062aafdd21c735e2fb0dbc25605af27f1810050b7ee39503c7b4aa8ad626cc22dabb1782f60be8cddb2d70dcc3fed26ef93ce9512bad21f748ae4ae04a98f3e12054ef1863c9068f19d678e87063f5a098df73d80ef3b1ac32f86883a7ae0cb683fe932375e91f7c411acd56d00ca1797fcd05b1623f6000bec88a2e58b36cdcb49bc8f5bfda60edce9900be117afb64eb0856277de5610aa91eebd231211f075892635fd8d4188ab750035dff2e33f8d14c40b889bc93c38524692bffaa3b9620c942f76342f9d751d057c274d792c19a85db6d7e94bac8573310126aa535d8e7ac70e84cdbc96b696c4d20c58c15533c5c138d5c672a6c5bd7bafa09b02538a7103716842203543f98fcdce65e5fd49fa955dde7eb2762b40fce8930866baec5cae6262329833f16a680f47e15364cf98046a712426f93b09c0a7121abbd6c6b3e369bfe2813551e26bedfee8314e5087b4bd59f41c853725be063056b51bd522565007873459c99822f17c450f8f0dcdac44ba4add2d4cb3aa4af1150e601351cf69cc900be6ad1561f26eadffc56a13a74d06f1877c4cb1d153ed4911d94c4d6b2a263d9c2bb73963db01aba797b13cbf53a59ea2ddc7d143ca82605cce824cb5dd023cc0b43df1311dbb134f6032332c89346c310af422846d903dee14b8313e19d3173221dd74fe920fb8bff3a37f3283d72f523b27295443807b789958365c34b9c7ab23ca68bc7234e4864009afb8804754ae385f6b726691f16d13f07df465ed8", .None}, + {.Lcm, "-9f14537efb0ead5860015222804e8ad847f914145427796ccbeb3388e0b8162f160d6406ead2877e8ef8537ec749295df77c8e813f358153e122488b789230c5f92e7b026c1f1046115cf69d5e157a4a1bf9445831bed844124abc554372f5ed220f6994fce34a33d7ab947011ac7d45a2f3ee5a15c9152394533f84388d991d776c3db506f1e186e0b35a2343f5e31db68a36ed12b6b022e4e17bdb4ca0cde456ce25e6642457dc42c2b594a0157497c47b6b48a543652a96c3a8dc12f84100ef4d23aa5668217613d3f87213ecc307fecbcc58525a17ef38f8983de6129b7c04380d409d77534dff9565f76d4da121071b143ef5e500dd7a0f638b81dabb88d249cdbc53ed96aa126e96e77cf8d497655a088b8e08bd8ba0734a13937d40d702ff97c3e6b6d0463acd815febb6ff2caca8f82a404ea732952568702a8d041d0ebd38017974319bc8fcb4b4c0e14da5ee3084a3260accc9c3b51c05fb368638fe7330a998150b8b883be83dc3e8ca9b325438d80786b76b28dc51c08afefd9bfd7ea7a1329c278bdb1335f5578c67fc1aea0a9a49df0c7599ead948e2d70bacca270d76264edf19dee7e6b29f7971786e0603f88aaa45ba20a4996a425410327e6c9456ccbf167c27e069e2b131890355d32946cdbc047ceef801b9962cd026c18cfc989d126e32f98222c5c4d0fe5350e408227e0f23d805c362121054c4dd", "-3d7261af2a833ef23fea23b9ecef305edc0cc3c06718207222cf5fa3b59935dbfbe0a9de33da25c65bffe9ce4ce796be6c4f36cd3ef4adce1ad168ebb96651cc2c2ba37bf204712d943f1b1f151f69ba549b6f6fc1882f1af4b5e28a9839c7bb282e958c487aedd81e6bb78a6e9d6f5fe3241a859689caf86ae83e9b47ca50c12a6ef85ebd53483c9843bfc97c6e0627f9293b429559ee1bb86d2378f1e1190d36ed7c668e6de5c26de4caffe60882c548ecd703c79551683080a0b5cbb0b0baf2d6497924faf202f779f2fdce54b3ad716794c41a27d6d9f4169aab54241ebf2a7f8991ff4a27c3a112a06991d4b7e85d676f620e090253e8d919ba33ae670f8c676248f04cf34c59cfde8e41d7077041db7077acb7ea256583801f2efe8d44abc256a49ced360354bb7da833ac5c46540788be04d3b2d6cf106002432159bc9acad5e5f33790b7b2f507f047abd1977c372afe9fd2f00e18ddce92405e3891ae64f1a105db3bda2126d8ce49cc24ad94583065dc2dc8bb7ded5fbc0ac00adb3c2289f48958008f7bb342d13bf6970baa987d55abbf9e98022467cfeccfecba01af72aba2d67e714f38140d3266a0639591a04683095f64d68f958fe42a78fcdc6765dd98fe03ed4f612985de01beafa5691c6677b252582bfe64ca5f319cc6bd1767ff2655715465b9c12f17d4a4e8e67817611eb4d12c81881cc5f37c640e", "262eeba5fd5160fc73441c10e4fad960002c0571a826488ef6d15b3d0d2e59d6569496d16004c4b990f1aaa17fd60508d87143929f7d6713d3878a9de898439dee02905af3cbe53f7939113e17f31142218d3dc4e87ab35c37bcf87e6635a6643581aade6e9c86da6716b44356d0d96c78c10b7d1b812be7eebfe273bacd636d0ca82cc3902c067fbb5e956c169da117493662d9451ab23c1c7a86aae94d017320cc7f687430d97a89e4396561a336ed10c91ac211a6879135ecce242a9335cbc116d860d8238bce06c607e5fc65fbc8524fc4f687fd7ca40853ef26372c3a6fcab2e0fdb0dcf722a1e87f7b87c0cfbd6917823fcb1b90e5c5a2e9e86a4dbbb3868bc37e68fa570bd44d90cb19ae4aba532b60b27762b52c78035de9eabc8e3ea1351d9dac3469521fc027cf662c64aeab7465e3d320f795f9fe1c99f99de7f0b27a4eb056a1d83e4fad2270ff7b051d4d9971a22fc8548359f1fd34b8a7aa8b60228b088c1b7222bcd2fd9f344c049df8a1f51323ce859b28ce651a53ed10209d9f934c39b6e604dddaffc2215aac4c456b9fad86d7159a4ccd093d7908de40de3d22c5ced4793f04578cd4c196713c8e0dd332020bb65cc5d2729a1d5576a6eda839ace993936dabfac6e54be5503ddc429d791b92427adea0a1cef363cfc0ebd9874ff4d1b8a92f6e9e36e62a6a5aeca8d5e56119f71ad85404cb63fb73dcc77ccf339121663382d406f1d7840f2ac5dd74b0fd931e728500c65333ef056a47bf62c95bbd7038ca00f1706ccc5e2f4f687dec1f86bf74f4aa4fbb0aab3fdd36cf0c76684aaa9b8f23c5eff201bb57f5a4640f9178a6dd65177b9195c931c5722bfd09848bad0027d1dc50c4736e2ad051279049ba9ac6a4efc82f14cdf9d9f10e8fb4f62582c6eaa52c62f1a41e7dade20205fa242d3c5ff4d4607d63e1baad24e716e114d1439da4d2297d5cf131cc8569605e9af80a027f3062ff578053e4ae50f46d399601e7e9885c2972a5f2f3944dba968e3b1c241af9f9d1aad425a20fc0d14d70c287c542da9dcfc2a3df3241c5e39e95779ed768a71a7ea518ba5daa9962818e9bd389130f7917ef50d62283455d4977fc30dd9025c52860da2768c5de4c85782c05521622f468479438665953a9ec2719141fb30d53cdb3d7a5081a4c092a9f9c50c8ca5c058833a07bfb392138057b331402da15218e7950a2d695229c37672fa6135c3f2243e276ae3299ee352a65e20f96bf889335943fa1f34c63b0b0ebd21ef0a3724792be7298e7fd02d956a56865b6b8d9a9d58f491709377c790e5e2a72b6efb4b00f7f05a2374fd3fbff23c0057761669294b90e5379ce26f1f34ac6c44e50df4cf0ee3f30762ee2ea4ac492e33b445d7398fcfc7fad598c2c3b6f00aee33e1d97097ec5aaf3e98b6a8f85b1b3126a755c23951816", .None}, + {.Lcm, "53e4abe7d891af0c9737f71113f120740b2c0dfedf6171fdab07c4eac1ef1bfd82876f2ea5af49d38c3bd49011f46875869ea2c608c76afc1b9b17f107b7249307f75bf8f4d58433ad6ffd797df220d9ec7dca464328dce0b5b27e61c10cc77402ccf5c4cbf74a35c6e754e9040125299ccb2ed39c51a7a5fe0efb8add48b582850ce41831646250f59e1036ca7c06d70ae0ce9e5af974a00ed904ea20b3d9f7ef5e65d32dea7281d9283581ec7055139eeb04791eeba205a10fa66eb6bc5254b951965e4ad81ad7d2c5f34d893c8f4dc104b92a13926daf7fe19468b368226108fc65fd94f1b2cfb35a78b5f1fbee292e615f828dae82a69ae1b53a488ee3e60fb92605e3ed174a3fd24dcf946f5e6b92917f0ad0956d96e89f40054ed1d2faa24ae6e1d4269a539eabfa13a06d97247edded4c4d27fe7109bd2ead2c3b3ff18c15a88dfd3515084757658a38c1153c04bdd9d9d6f285efce76740d7cc79e483501c4d748f1a07d408200149dcec59cd15fd4bb37d0287d95b020aa329f294f681ab2c49472289007d8edef866d488d2df3235540dfc33ec5a715c9cdd1d9a14fb0b706843d6a90fc8127bcf150af7638a3c940766a7c781615f7049b475eb1b0e721773b1e1b8966b1e1fb38997d9e80ab626ae7f919e5e352fc81ab24d4025c3c93c92124b2f72f4991c14f101d7d3a773be63e5920a72965877919a853b6", "-74a50b45dd48d3f405d431beaf75b768e2c067999ede666703de5a3e056a6360a4ed659e218889db88ba663b024b87acac49fe398df2c7349dc14e2ecae634a49987ace05bcc549e557f0bda83dd46cfa86380d10021932db71e2525015352303e3944e0abce6a763aac9b7b12e9d54b6e24fa4a64fc7585a6f62923cae26863f462103363fcefb1d92521f75e73aba2794f6d9c1ff7d6703fae52f15eaca40f473b75346ed49c522765c7abc060521e17676b39ddb86b61afde88c1bd6c03cddae26d4fc0ab5767fe2cfe8d4cfd7642e026b2ad7366efce4dbdfcf11df4f6a1f9e4a979cd36cb5b5d1e180267e952b686a08433a5318b2442ffcee414410e5c39a31dbcd2f8c2bffc75dc1c8390cecd9abc96a4cd86e8700859916fbba24c0bbf50361414f05249249186681444472cf2e8ad0641a97a936c65513717d6da4d53977e6ee7d2b7be59ee84caf17a1af7c32cdfb7f4f146d0015c71611379f8623046a1678ff723f0d2d656bfd81b75b1b5acf71b31d1ffa243e76b76f9a20643264424511eb02e7be93f64832a974b1e377547d84d019c1540d4f770383d92732fb49cf6ef76bd981ab22d02b7665ad8808d55d53d5cd5ea07c21e3de7876cfc104d7fee966d39ac5f8210fb8120ad360669321e345a6cc93163afd3e083b0c2067f979811d5249accfb247695a1ee5122e2ed5810438ad5b20b4817f55fa789", "2639b3f9931a2b301a242a82e24f8df67158f0f6089806fc5867fcb27341ed587324d3fbf1045ae4116496079bf41b83ce96bdb9a823cc92be89db83cd26c925a0f07510c33babec04960ec15bfbc1087d7aa74cabdd7a8a756974c0228b5ceaeb0004d88c5613c58340db419535c6e36110d6de47c6c0b34325fd6359ce74e163c3fd540d43e8abc5d9c3b670f28eaf12bc3185ab30f0261778978dc9681eec19af69a110df36f4ae6512081e897f214ef5b4891f44edb08c76285a1a2b9541d124124347cb53c6678419d58673adcb1742198dadce0f45f295ed81e031b20f4cead8d84775bb1e03cd520d543fc0d9af6ae669513e966d8aee4b700b6c61f0ecc60ddb00aebe8211c60e40a801d3966ccd2101da7f424155d4689a202ef274c3ae1f7c80e6d7e24971513a64b0fb383e8d3812aac13efaef11ddb411084639ef3e11431dc1870d66e056332ba9e0a46b7fcb1a249f5f37f07f76112c1781c7b717ec30de3b5fac1847eb69cac5c629bd92755d0cee4bf76dd4efadb4dc4ee6e278638e61c08033a13ac03e1233f7b61289a73245dda94dbbe2f0e489addbb8108c3d0f8f96857944857ebe64448753a99ebb5e8beca5dc4a9d0ad6bf020a68d87bb3eb4b5dee3b8ab9598f2b42bd14e9aaf8a2ee28d002eca8bcdd9944cf642c1814a2b304ec293ec56aa4496c71dab29dd30e6abada11e37be4232226a8b34dd0ab68130c395b593cacc1319d215eb9ac370463443c8a2975d58d0daa1a8cada56eceedcbd59b8ec02abf47dc3ba5959fe2be28cdc70cf08aeff0af2779ceadc4df153f2088c946c484168be3988aa63ea90a813b7678f2f8bf11e454de5025c4a27d32459d863dc2d0b160c7118611a47d907a5b38c61ad346544a6d4b76efcb9c3400195ce950f7930c930e43289d4eb8c31a1402be355b96b5411a75686d3942a18426506994515a1acc3f970dff1aaaa55379014c1861d7b6a4ee187f45c282237569445f5a9bd7f40282ebd7517d971f60a8abc0f2168ce44596b59c81888af74cd62cc0f10f017bc9ae7cbf77ea062409ff69173f61d637ef07b796afca945b148ac1d02527fcff547dc9f6fdcfc8e18c63efb3ecbfdada382c5f1f3b7491154101a0da14bd17dd9568870621ed46c3bef77ea3060396a1d52d8f4a262b3dfcd8ab1c879018676d0a3e50d7371c7fa22dfcc162d90ed87105d0ded09e9f048c992bc9964fb8b52ad70095e4afe0a299dd17ea4341bd8bec0e492d72fad77575334964185dc7c0e0b734a130ca0c27b9865b225732de59ed43e3a37195bbb233655ab06ffbea2d1572ec44b89eb9a227debeedc298d1954f9f72580775c39511df54759cf49a6628a11b8e2b81ac46c5fdeb425084e3d455db299e78d70d73742b3e0d021a30be4c125de79bdffc82df45ba2ec158b0d279c83a8666", .None}, + {.Lcm, "-c0cfc94355f0663429c1cc4f88dc002759751c21b5cfd4717a2874d614f9f97a49545b78d24c14c51d831fc3e78bb0337b5062ec5aa7d28725271d5f9763997a505339f84ffda50c4c2a9dfdc26e12f18e066188a164c85f917fb884ff63ffe6857a54d341ca404661667b0106c5e40f0d82d8249b23a5c16ee671777b632f97048676155358752601031e7dfd29f9570ef4fb1eb2ab8b06d55d8d6b90102522a568fcf129ff98c97e2d973f72bf02a9d2729ca9baba3573ff4ce55a4651fa9eda904ce9e1cd630db9e0699b207b8342500e1d9fdb9decd4db67d5bbb0cd36c70ca663f2483c69611f9999e85211ac60d14230d67a2f9748883963518182bf3701390e35037a114b4b79ca1b5013d0efd6384478fe23daf5cab31f1e386bb04c4c95ca2bdca3d0a8e4e1c22debd02bdd7b32097626b46bee1bc1b7324bbb7d4ae17213cb31d7adca40e2540c8fb7ea36f7bda892800e1680811be5ac84493b0ba1282248c1b81239118c83f9fd80826428a60155f969600d2b0bdba9f3636017b82425c64176a76589548d75c126da449b88e2b646580853dffdd45038c5e83161f6be7a728721c696ca7453c6e7eacfa8381f118fae2d686e1cecdb58546274dae5999b5ceaf08ef7795d070c3f21ba0f7f8ac647dafac2f34cb639e930fe96d78afcd11e281480725c9eccba45aeb883e8ce8ede44ea34d2e331620d9366df", "-1f87c011909fbcbd247e56be89092eca8d47b9ad3bfc46e5162c6f5c03788f032447cee072feed38899b63036e7d2a0531e1cbcaff22961aaabcf4189d14b6cb56200672968f9108d5cfc4696ffa53804473d4edbea75e9baae14ab91e3eeb8880736faea97862b5a493e6121b9b524f5948d2adf0a73c8122617c244a7be466e7542b83dc1f132b2c6744d8a06351bc4e32898d91bf4d5c5c27b3fdba3c054df09053b14ef0d62efb72cd92478e16d3afd0a4e41d38ab7563e617e7361d66786f2425e9d4b155d82fdfc7fee3d846f7aa41acea6634b039fc1ebc142ece7127823b09aad987dd1b43bbfee46ff56d5c5643e24e73aa81e9e3ab7d4398ad4f6e9d6d9c18500f079034eb29024d97d7cc2604b7072b507c743d338a25de605139c092c370b737dbd6caad297ab4ebea5e71f3abbd06a02f66902e0660220da899fd70393066793e7a740f5e17c4ec60b84b3524700655922ac93dc95a512bb11e33900e3130f673923b17444e64e2d1c96b8d4caba084cc77e1b932f4dfd7bdb8e68e978bdddff1d11226e4fe315edd2b2714f8e72b384463580a3c6c793b7f23f863c022c9b1f05b6bea216e6f1c089ba68b769fd0ee7689794e53c3bbd7dd39674c6daf163615ecffaea2662627c03e644d3436f5bbbbb484899daa3ce8549b62cde611ae4732758047783985289c21320283acd4e3a623db066df58ab77e09", "17bf679b5b967c7e26096940244ef438e6ff1bba6b1c4d3eae84a0294852b498c725191d43450e97eefff0a0d4d313369d40e3db709e4730418c25519072d693bb0c9347f0d5ef237412c68ec0d294cf3f233c19fbdb34b6c2812657395c5cd55a687641f07a1793be35a4a93895d5bb968df2c141667c9aae15011bee534b9b0e72e01e872fe09e18f70bf0a9b11539da4593d6f04fe5c1be740988e9596c107d69a78863750da84ab8c132026024c943aa3d21295b6b37121dd26a3de7513cda28eff2e468fdef9f93a5f03d4579763a81afc638b53a73c67f65866e2146094c93d1a677f36d06daef54c9e8faa9dcd14887e6982699ed872a1726b93408f16099d4f5fa671d71cb692a90ad5e9f1de80920c55366f1e132319c26010a1e3310d8eca4e96bf8f4c09688305a4783780b0f07375dacb72cac4bdefdc3e6e8c92d62cb468ea327ec6c5286b153d796c99c9df0e2b4d00c381eab8da34b26be8e5442482d65f519122b9c25e5be72339e4cfc2605cbcd83f2c17efe75876368de91b24995f7bef59ad44f3109b95d6dcd2d733415b56820ac42e639276a5f5d92555c37b39f74831477a37a7cf3250c6c3e2d96178f464573a300a8f21c5c8ca6d7de1ed9765ae35168b6f43c9d15ed2113bc7acfe4ee288d605a7e27e65890a9d77f6ca00ae0d158e5ad8a235a8b3f54fe3513e6d4276d8dd0378f5761375050808313bdab8e99448f9dbe9e7e15329dc0817d46d3151bd9470df66efa5dfe438e2f13dfbc34f762b7e6adf7db03db08d14e3236f41f45ec02aadd4a6a197c82fcbe1db7972677015a28fdce41695e7f26a61c031dd089198b1c7a7cced9ef1c95f9bea0ee6c14a32aff816a2c896e6eee1287f2d3b22a907a7c7191a241244cfe3c185a01a00de4ca6201111bb6286713214dfa9bf3a2730750073bba2ecd86e6f2f07520e432c13e93f2d45418c10cbaadbc4c91ebf2065b8bb22eda613f5056fb3146e93273a4095e5e2715a3a4894875fec8af81c1cd56a1ad3e9f6470a8d88f5a7b9c8ad13da6dd97ee338e6f1d79e931a5dc7e57dd7267d01bac2e6413618cba08401e89e31f35d2d3df838059e06a12e05eb96f1ed678177a27fbce2f6488e4a0d88785bfe6da6f00f7d9c3da8c3b6e5c013095bca165a0d8b0da9d7320d27260385cfa054e4775de74ff7054bfa00ef95e09b7d3771ed6986661d60b7368a07575967e1faeeb81853a91dbd6b001efc891813452b5c17f655e12259ca4f74df25c8adad15fba5f4ff739a45e6704bb07c6e90222e34ad5d020467490a94fc191827124d3e2215dbe793856f7075eb889bfd9baa79fb27deb9bf7bddef1fe3efe915d06d61a6f69174aeca9a94c57f0832c6f10440566fdb60efae27eb070ec200a217b200456cc601e553ea7aece37c88e1a8c3f53cc8f5ec6395fd7", .None}, + {.Lcm, "-14a3b7e8a53e5527f391addaf37fd05a381a08b083741d81973423829d939a08a9474932e076ac7060d08d45f9b6fc21d30a1c114c8fcfca9073b4a92e992292f8ac7ba5f86a42625f0b63c42c6b6985cc115dbeba8ba30f728464bf0fdd1b6637c2916708149a3bd9fc602fa40da8cfe2263b5bc374f448b9b364142fa56bea85a8d5d4f67bec117739096948e928b61d2f710e6a2cf7b707a3533d206648fb5ba88810f2ff503b22437f2dfd2f584321fb432074530f1a797b5d663a605c04f62329095a41fb16abb7e8161c75207ea3bc31ae0a1c6ae4bdd9d87a3c86964ec406bd97825faa71fec2926e903aafca9b4b8dbe2a116bea26977efef7fe772ad460094c3a1c4a967b930000648fa3099930a8250b982183891368e63e839216b25a9f8608192ead2e15663517edc183a0209b6d6033f05201977bfa69cf7a1198325b4d8e1a0102bcbaf1d6d5c8979806bafc101662ad8a17362f9f2b1059f2f08fdf32c25700775d9ef4b0815cb74e3b683d53c3019893f7a9189b6c2b1621bd391abde765fc2e25b75a80de49942d77a993988ae23bcdaf9f086f5d90f67af78a6b724dbe4116edc3af4e5e801c42bfea49c0792d5c6c00b9658da4d235d2fe384da01039ca8a16c343be6045f46c7713e20f8a0236f2010b5d7d06439b79d447532524ebc41a8e42ee1e4f8b2a181d79380b64437482264d6c106a2070f0", "6e24e53a696cb0b80de1d2fddb2e58a4d985e37212486d398af639f315c82757527da10ec82b9077ea64c67bfd7db8fb686c90e127e91b3f1372a450d358b9e4611477da49d9848f66321ce541e3fd2e57e9a583147d4056af2f5c28991dbe960412852e63291aa683ab2ab7e8d93ad3a9770696c49b5b6f1af10d438430bf3a43827c72df9a9653890ed87d2e7cca169a95eb159e7398035c08e8cef5d56b93a8df3ff19a894fd0ce09f42aea75eda618394d7769de7cb391683b13a54712692623ad9ffe896dec0da2a22691d4909cc98881be80a6d5c867a6e1899a351bc5d2d5bbb606dc036e896ebd6a1fc1b2e7c8699259da94463a19869b1ad2a56aa78429cc6bb81d776252514730f5278ff84fbeec7ff934383e5173c70b87e2011d6a15ba9aae24b682660db5e50b16a6eddc1b48b6f184e99088c960cb0c4c138da11316adb4437d4f3ccea003452267b63298d8c9ddddec3eaaf10299928dcfa0f9ab58f263b08827a1e617c73d8f3015da4fa3ddcdd31b96efb8793fa5afbb00a5a6fedc369bb0e6d388faed036de7b7a49e1f80c29e4751808531b46d840e806a41b1b1493231ae70ae0f454d5f09dc1fd66d209967399f5ec122e0b6727e4a5399e205ec335689a2cbbe89949201d44841777f5b05d521cb1893488739444fb2fd1737a3bafe2e8ca559cf01ad7598c44663b1e63f3867876a0881b7abcf4c", "23854a1bf34ad682f6e739a0b8f9815389619a0382c0cd30124a5366d7943bf8d3783c594c813fe755f2c12faa55ef3bf7fbdadc24ea99d5f0cea201d55c0d98a136e568c1b95678bce04955f40b8834d2aae362a15ffcbcf476405d8975af0e65a4db0625d3c85ae35ff2fb7d9c33b0d235450de5cc4294850514ae5872a0f8ae6444bb1460c41cc4427797d30da5c660d878fbfa0c84226056cd82cf2be9e686a63761eec1b62427cb4976404535785c67c693bd3b00ca64b166d19a55b7110970830a40b879521c22798d9f1da1a1d207fd79ad7847a9dc100f565774d02d2c526d159439bf55037d52ea8ef02218b91fcc5361081743c075c1fcd98b2bceb81d58d29f0892946b23cfbfcff4c869be5ef3540114bb3e83fea51816562d4626b37d7f18928b63b03aee11638af80a6bdf113656993349ce6ef61c8c61c8cd3a02a0257eb70bbb016578839d0d3da24b8a09c84fe0166ef8bef6d07932cfc4f9b79b4f40dd1457de03210fe24cbbaff4091bdf532b0a0d9c1b2febc5119c0ffd84c4a824dfc09b23bfd0e122f21908f0d34d877667c316d8649f436f3f4bdb39ecc626e2face22e53febe72ea7cc9721a004191134349a20648388b42c3e81dfb56939a143a5923b81e9ee08688d49fa928ad894e16ca9ce1d5e94e0f0d674bfa2a08cc9adbaca7ff2668d9d5fb760fa5d3415d0bb4a7626325a2fec0d049dee4732b4a9210a7f3f1e980f4505e1fe8aa8f981505e25d7d8aeb51dec4d8ce47a9a75d275bc3aaa0f01e09f188e17cba47dabd89045e7d89ccd84f422845c98756f5bd129e18428f88958803178167083b5353b4e8de5290c2cfe19b991e38fb0d1402ec269732d07153819684330a5fbd4555ca94eb0c14d8ca2014a1fe60eaef338a3be80c31e0220eb2b7090053edad21ff3eb3a638bd38e9b860f9851ec9abeb54b0f50aa2599cf6ddd04efc06934ba37a3a81d34a8861db7b8259147d01560e718eb6a1f5bca36de8a9efced043ef01380569b489504a23ceed7744ee4edf103d658f50c09e1aefef28a355543cd4f1bc2944904dd8fb69780036523adc8386e864df9701160eec4d87c24570a8d5dd67884323c163572a4d4f5232120904ea5259401e80fc1945eb47f551aa59fe8259d78b744f1a14b69428b959a020ebd269188798068672929d7e9bdac27c6f24ffc668394471d440c3e2cae25423714a46194acead5ad807588adf713853fecb24797313c2c52133016ba4b6ac4f4880de0134d6d09b246c3ca4d03fdb75e84a0e4fef432af9cbcad135a54692bbb288127556e24fdce18628c50d9ce9ddfafb522bbda68efaec775fb1a0b6f1dd4bad193bba129c1530832b30c6e376c116540241de0fe08546169fdb187056bc29987abcc5b9e29483c856ec098118860daf3520616dadad5c7601af50e5d0", .None}, + {.Lcm, "-419e41fc8a7ab45b23c1467bfe7b3eae04228e6e0f347090ffc157be1a42aa8fc8010192b94212b83d239cd8965390937dd6d75ebdb01131e61bfa89bf052ef3d01b8c711e55c0f30953f598f05b77efb9afb58fd7b4d4f90169e2c951255c9fb700a820e2699c2694fdf99b452766755536871e5d63580ea2fe0e7c3a01a42b20fdc15365c8d4b1df30040a07ac16295aff75a130b4a808b806bef295fbb50a0f419f555e51cb17a5a7e000195648491183533d72d769d5b9b76988b2df48b2c877f2e2027ac4757b47d86895aae9bf722d33a4042618bf61860b4017a1a6806aaecffddfe991678ce6791d3244cc956734edffb138ee3fdac7e6eb57436538cc315c536db9d1c4766459e705ca4f4d55b3f09eb04bc728862c1f44c2dfdec8326ce94abe0b560760b863e2266c2f380d73d7075a01a932caa1a9ac050fb758b49ddb49d47bf99f0f85c952b8efcca2fae6505b66e5977621b3960cfea1bd563d6bee2a820e53de0466d32ccd1e99c57277b44bdd8d4e585bb5c231f4f1af7530331d58e39c17763dfb85718717107a561114acf9f625a5ba4f396f277dd90d9b8dbc91e668684a60eef61c52b2f4467594772f65ef795f96bab859452b0457a3f17cae10b9620f574bf031603a8a364a3c2aa2d2000e47281de7c4d238650485e06250f4a2e65bfff0c2dc39d2f3ed05d30f59bf96cbd0ed77b72cffa4c162", "-86a4d73749f7be368665647b92610fc1ff21c256fbc4cbe722bcaf308f3eb1698f41fdf5361315c06324ec2cfa678de0d19c9aac96c62af3a52dcdb7387d77eec5688cbb3a50eb3917c0625cb937006cd237836fb629cedd041f7992ea4688d2f4f6a217a038831693785bff7a33d073c94eab06afd4ac78b7d890ec896c67541c7d4ee8f9f33a99dcebbcb9d06764e37311f280f7e43257fa2b457491d207b6a6724f4485bab25bcec07fb893ac262c69edb9d08575dabd44a9282da5a7fb2bfe69526b5a3f816beda881adbb35ac2731149ae1fcffe716523123e522e218c96304c96c8abd8043ff024827f55e9b853ba243cafaff509f705a0a335712ae331e9c8d8e0c606d8bd9c8ec1f6ec57de3687d9ad7f294b83a0663a7c6ac8451788a7d0cb3218a49d46c284daca6d6f7069dd305abcbfb02c4eeb3c3ce577eb19898b619427c545ec43e7ab59d8766024d9a7270a87d51b6c351ba2c114aa83c88ccda94836a78626c711f166b089d2dd163fca24677465c0b835b601c883f1b017a029c8290a17caea9d5fc30b1af94539173fe132685c1f8764f7b1e9b4631212bf10e509f745a4b84f9ad47a8f8c7189fbede9f839c5a70a3a50aef4a11165420f5e48f8ff599648e42f45629869d84580ea29af63c29d8950f4ab0781f0f252b0710ef395d8377e9bc9f374ea0d4a6c921c58fa2728c2777058842cd4d100", "11418b8b45d2ebeb14f2127607d7bbad10aedf08cbe8fc587dfe4aaf71b7d3a45e10f661c198ca00ce8ebeca3de18548f1c13dd17984affb95784a0f247f8ff28b2f376e4e0e1813c354446f7250314ac4965bd2a80cd77a2f80167203c7f0db9d09fd4c9b926b3b0a1aa9f61a88a74627bc32f03d3369fd9b9035b0190f1a94bced6cdd95bdcedf2ec741516d378ee31f250af17fa4f1f40c5a6a1f21f8f0f8837c7ee5e5cd430e05218f52f5a2500436eec14052e040f65feb9a3abcf0abac0b94eef2c0e03d47d98bd8fb87866cf4987f9541962510531dc6e933efe524ac94f5b1d322d832973174acc34bffa60bcff4efe667f21e3146a5d32e8d10ed2acdf8ab02cf0d6c6b6cd006b6469077d1c2bb6e5b26f14779ee169139406e226775e1e28e7c403dda4cd34cba0e9d9ae4b5f21babee84f085fb04476bebb47c70a85e35279a7632effdce944a1e9653b82d02d39e623dd75ca4cf30474bb5081ebf421bca9d653e3c295fae4bb56db1d1540a984b923ddf3f0b52fe9e510d621e7a95cdee5336207563482ea17e8d3222edb194e12645b0b376192db143195b7bb9721794fd0df2b7b6ca6cdd0f36cce36697eedf48e77b92e4d521cfe33ccaa005b6ff548c6afa7c66faac4a739518643e2fdf0329a7e5a79ddc7277a4b71a0365bf740a153c9ebcae786e3129968500a1104a7a73b151ef4874a5d61099e9991bc5e62062a0a614b4b5c94aea13a312fa9569f57f499856c56cc5e7b897706cdfdd7b42f6886289127a3995113f0107b035d9974824a2d38f9c5c209ac0fb2f403e34dbb5ca6b794b4981cf381158319a5b1135c75e8afb72b16db363bc55f48499080050f5052f2b9fcf63082c35740661bf82d1df3ddc5826dbba43f308fa1c1be4d03aca52c5962a3571fda58eee6106dc3ac8cf4c075ce0f5998654347c947e81556df1eef5c1bb933b2ac170324d2047ab4d036da658a942bfd64efa3f4f8fbbeb0c98fa6d81e1dd48c73515ca8291e0314e2c8670bab964402ec2400fb8e20ef45a8b1d1306d31bff2d2c5437fbb02e7db18c5338318e0a7f10bea82a51c4116150fd8a522cf52ed08e73a1003db734671b392ddb1d7a7308490c7122697bbfbc199c0e1e483e98161a14fc59051d79070c58e63561ec4ff642254ea7528662096a65631059e1f1c820d63211a2c7b2bd52c373777ddc26df7e9e24ad126d50d44a4fb560a816fcc39655e7d82752ca2ab816a407c9c2b8c56d68268aa3fc0a9a55019595cea793cdbe80ccc60c2c833bba17e1d568e39713ef54f12e8937f7f48797ded63dc36f698363ba5826aa0fff2aa19b8a8162693047f70bd0c73e5d89376e34a48899615db1ac203793d533a630e5e092ccf95ced7052300cac7801d82a0fdda00386f87b2374571337596f18c3900e7e30694753f848100", .None}, + {.Lcm, "-8e9f5b4f5930959735cc847a157a3fd2fb4a7c8b3e212be9e806e30276504604511853bfb31fa42c22ccf86536c152a5d1ecd9e646d224162242e1b7284ef33f9b7a9f95134cb9b2dafc151d12bf8b42aa45ed4b355447dba0eeae3b0939f132603631a9a4e5cb6d3e0455a4fc3551f447b9362ab6c5f5689a41e34384cf035c83005ddd1ac91f28250b0e130b8d9f48797a8c2e5b221e465e7b54e522a18733339ea09c77d17f92efb64635f3943947f486d674f0e8517572b83307b7d909a3a9d44d82371514de5b0ac54d7280b5132855a7085ece8e34fb77440530dc7e70ff1eb09ae51dc94e6e7bec29373f428cb1b3aba446245a8786e7670ed0e5db1dcf93d531fdab6ec8683549b12dbcc880607eaf2cd6f64dc7b6a0989f40918eea0a5abc3feebe3ce9e8ba0397d14e3a69dbfa509d9d3b5215a8eeb6b9313762633d4a964fb62a911f7fd38a7f484925bff4b88979256ec620dd20d9fde096fe308115789f2424f407db33ef7e95c04548d05efaae7bc761340c5fc692dce53a8ba307e09ae130891096c5a3884495b4529dd841214e6fc4c26c63b9f05b5b81b103be9c99a879d17e75256946f98e69213f041d009499485426f52f9b30871727caa01223c4b7b4ec520cfe2e05f05d2726232633a81eea7bd760737d6589be1fcbc5bfc86d1ceffcee88651dff02c359c505d54a3efd84aa3cef3bd0ff76c872", "1a38f8a4537c2216e41674dbb665c18ce66ea326e1c02c3029a0c33c1d4d24302947388a072d6154d67cbf2e18c5eeb64f41fb9d7bfc72a8d8e0dc195fc08e542bc464b8dad6b283be1cf1c55dff7ce589795dbd7ac381627839c183a610e6017c69cab2d5b270354b9c41f75613fd797572e51ef5be60ff2d339c2f4b9cfd9497c96cef192aed4664911b70839f7287381acaf86ce0ec2ef1c2d3595c2eea93bb1f8d16dd6e6d70bd8e6cd894cd2fbf20d90219523491f0a1889e8f91aff5042f58b21f2c68ce1270553db8ab4c35d835624144ee4dba0790bb1a32eac6116adfd6956fe452e7c6d021f09bf5b9e98eac4f95d4d015c58d1e95594e3112c25f4492ce731fc97e012bdd4108ebfa951f6872ca4881336f4d5063d9acf64bd2117132789422dc7e98f81645ef2458e224cb554cfd5eb409c3419dcb0aedd7b833dea77b788e6c27be6579fff0ca72dd62b6190594b9e80b55620566ca3f560df4d98967e4f874cb8c7c6a1ebbb6f875aa9c4e5b95fe62cfdd163d72129eeb06ad44e70819499e95216072822bc09e71e619fe9463baead6716badd7431fd04fafcc2fd2a076347c0f45915102a2445a8beac33373627470aeeb56c9ac9ac6784dfdb910765b7cebd1c69d0a8fe022afdab70819b5a1baed996974b9f75911b845469de854b919610e0750e12005aec24944ca87756fc964580de8b2d6ce9b018f", "e9beca7f578a1d727d3a1ffb38a8ab6076c00a5506ffcf1d51505a93b7ce2182165bd4f43b88a6f44a3c197f48f7ef5152ba9552ac2422d6af50a9c45c84620cff4128992fcf9aca9f134dee0774c2cdd7be2f636da0ab0518e7e019004d79ec29cb33ebf3d41705735194ae136c12547c099d4b6eaad6db963f5661c852770c5839640298017745c0b27ad8214cdf8de5483884b19f5f2e463975c65c4d45efee0c6afb46262277277c9c1eb7fe712f72352e83d409c8431ae6c235ce417e7c275e940e1be9652d5e0567d06a8c020352fafd94e18934f1cc12b6762816b52f4a3afe784c4d47019497ca96558990f3ea4fc90f3d33273ac91269d6e9abe8f59b9ae5a94b31c7b926c3046231c161dd8a82ca1118bdaeb5316a35390b729236c8d9613c926c1352362555aff865577dc2dc40c9673abd7e744ff9b1b7ec8b64afefe116a9c0ad538902104d265ddd3d7372f301fc6ca219ff25cfb6898771c57a1c13f82e5d14531802531b66fdb5762df6ec279049d3b1f14ae0a76357a1456d75238e8340568f55235d0c31ea4de58b07182939431051da8a6f928616e1c6dd8d33538cd438662913a50eec180919a7ae2c278931176a2acdb2d7212b66d949fe8b6073180177b4726796f9db83339dbb7c3fa9d5c97ccafa6235b82869ee93a9d9875c8767e9f24ba488de8426d54bf03d405838a5ed9030cbae8fcd78ecd767a28558049d53f2ad4600b61f82f9d9dc191dcc5e5f36db161a172feae0bdd8e1ab2dae2b84975cafe070e9673d1625b10d9598d521cf01379a9f1e4c21287e420e1e6322867dd86fe668f84284d3220139b3ee4022c00b506a9584bea7d695b9bb47c5ad382b5bf7da70d798f5bc28669abb592534ee2d2f35c13de27c5a54b5a42565e7e63163f35057d2d7a7bc7199d97e35be904eda8cb5e9332466a4bfb21317c15a53639f4721390a9abef27e68f8ce8f6910f9c071da84131022aa7c923359f880564487dd794e78d52a853f51780e0717c7c19d7b066191dccf8f14c9efeba1a1073db3a61084712b16d0468a15c5337bd1a6a5020f086bee1b1d4615a9669f322224635fc189b4b13a80cb3197d5e4804711e23f76950063a7acb7e6d9d0efa4a527b0a0c5d0291d54da62f699203a3036a7f0bf74e6aa7c35bb525dd256b7f18851db7afdf2dbbd13d93f21db4479818a4ac99044b8ccd92cf6c0985a4453c05c7affc6a866e24c7f519f7ed92bf5657e644dd76d5d284dbe0402cddffc991960cb538c4fcd42f846dee30b9494d68b155209ba0c1b947d93424337deaa7248e61181fe05a132ebb898703cf13837de4b98550e9a4af94f6518a0bf57afdfccc669778f5ae2fa9fca238ed68196a1eced8bfca23f974819abe962b5829485b4d465df42c2980d33e3c96af39669dd479a9f3f55041432869ae", .None}, + {.Lcm, "-e3309e3c736cb1415a41ae0eae22da9d642e9bc6b93e98fee3c83dba910cef90d0f9d4caa4802bd87b4f19e7e93e10231ac40e214147a0c849e3803ef5d7a7afc67692b50fa3d72f9f4e8fb03b3f4a83679a827ffb83eee974ee4723addfcfed43e7d30200df2255ce4aa39d12711f904f21dbe9e4ca6779093a87d9f47de30d9cca9b4049c3c79b5389a05dda23d6123898d464a0df883e9814eb996aa689a66ff7c616dbf7edffdc126dc140311dfa81697747b55677adcb7be35c4d8c109e34b52f21d7270a7fec65c875bb20e37b60796338787ddb34e8692c00b297218d6f852130a4754b5abd028d2660ac4ff7f0829d322678e6a8bcb7ad34fb7ca867b0ef20d51f2481bcd56ead9afbc614db8f32883e43875915d5f67e5ea533134d6d5952b5b8b5f53e08e1754081ddd7533d30f9250624354fee255e0311826bd9cbdd4c35c140befaef2883900118897e1635c975da67d56a28f0de53634ba660c8bb4ba65f3d991400ea88c1a4cece33ec0f7c5e160072c801dfb5c2e64cdbd42db1224473879019c75e66c413ec0fe96e65b5271ef0e9866695b45661ae311a72608778bbb6db12a054662178701993f93b7d910efe6850d514eaf047a0ae174a85d9a728f7b5c58287e3e9011f630c87d94ee079dc91efec7b0046fce9437c01ee0aa7437d82cfb570839b1d0b7ab6b0f85b822c4b1458b31e220f95b6b82f", "899dfa5d293e221852b0ebe8969fca456a997c2e567894458f8767f6792e854410b8a89a348c1b2cfc0f7ba3d0d8121390fa37ea45b8d3f1de6d020b830b1abd4e0e23a324cdd53067595877eb72ccf52c4c397677a91a2ae23cdcc59a7cd0388b287242cad6ec5601f433844f3a3956d86710b2655d73f165f82dc45edc6fb35283dff35b59d66e91f829f1be8a66e2c83eb5859cecd1969ee9309da62f474739b5b989b6afdd0b631694601acdbafd9a05d4e198c2b3187722a401dc3595a467b759d848c6a0cfaf9ddee74ff02b494628592c326d6c358902e7d07a140ad713376b296f9682a023fbcd1c91f5417b25e876adb2c4723eeb39c4c406f728fde756b366100d860a458d116a80a400e300c991499a33720041d8cde5fa80ac71019774287daf01246ff53ccedd7fc04962ad3a07d9801d9e4c6cb5d66673eef1e89b0114ac3252259532e5706a5ac15024582f4a03c9618cc9152879b044fcc8ad6979f24ffd3fa8470dcfd0e0f8d182634689b98ebfbd930590b690ca80ca7ca8f8c1e8e9c7843f0490e5ba366efc76f4b177622981c1b5b75dd1b090403ec56aa599f037553166ce7d96767070ab4a45d39e474c90d4feb407b009aa55e824aebdad97c802120dcb77835ac3675468cc70be99957cb8ffa450057b73538f8d55e23881a2b5088adf289e691a8df0c1314eca8792662641b7d824cabd563135", "7a2137af8ca26692ce0d867d60910c5121cf506ce361eb12e1dfe703f402a005c7f0c82b2f1939f132ba4654d5d76e185f1370052936c688ca7317edb2f4c41bf3919268612f58fd39b466705533a237da71f4ae7f65c89aadb00ab5958a4324452df36db5075a8423a3f38e495e3ab9bd44afac745a473df596502fc24f2d8a036526874a33184783683b51f47893edc874ba54efe0ad09cae64e6e54b123b9e2f2bfe997396c21a508ee21c9cdab3adeb16640e1a91ea7b01d545674da960100b64503b9c6897a3151763021d48212ffdfbca53e0bbc95f66b26e7b6b8d1b2da5e2ef7e7d95d89a81033b58a4fa2774a1bf3a8630a4c985b1fb490d92b5838d231baacae55d8d4687b28c783c5297a67a89d584fa26940b8c78a5c788bcab59b05354ac727fa3d282a177febd35a41d1b70045bbd884de9c7bd0eec85a0aa9a77b17ddf138434265c327819671141331d475cedabf4e39622e066c9c4790db0ad9b8b7df34cbdb9e88a3079701d1b50d4799833d978ec8c9d0b5de534cd8d0fa35190be9d351e2674b421d17d920d6fc35c669ed04532ff5572aff7c8c306ec8f407f38dd649dc7b7f3495616e808be1a02ee5e94af29404177b9b5db7dfbe72edbdc54bc32da00bdd811bb73e074d771bf6724d870166a3b73c6104b569fb76dd7fd42271cd78102b14de1bd743d70d792287f3199bec3a9fc058fbd118c47ecd0dc497354ad9fa8404350e98f2a29de91c2247379599989c5e418d18596aba1e729976e7cb65e50dcca4b622e0eafca129af0ec376ad3cac97c23ebd42156d7bad50166a8670439c253a0f5f6aa213a6337695e128a856a59e6494cb117a7ae61e09eab0d1ba5f313dc8af72e25fc12d52d105095fd2cde5de1a220c82045e6163a26f9d0d4b8da1c2db5c81a4b895e572dad27201a6f4488c00cb61466d9c77bb71c80bf253906e3e5152bfb54d33ceaff5f060e75c2e53a48817f70f572691b56a070bf1054ce0439cae27eaea3e4db60b1401a76ca2ee6b321b922381e315a4d8254c0b7efbd9c980deac12f334d740a18039cc8e1b6b3618624f42e5006657cf2ef87bc40b3a20866d7c99514cdd9fdd7c2d034f1801db216149df193c532d3853300377a9cc73809024f0f00b1a353212d2bb365efd2f073d58f1290d8869507a5408f82e92db7e18624615d045836b497c81a14b85dc601192c0e2f30eb0333760432271fea5aa482320877e9295bc6e1bc216cc07087457765e62750608677d5c316b7a3b58586448309e93f61e88c164b54743cda0a21d2a3ac0056666df54da263956e46c39b8e1790075870e112ad207c29747dc8b9f0e35daee23cefca6ed7a29f0ea731be5e8d9a217f26cc14120d3ee91d564daee1c472612002e06cb489bb64d217cd1354963c6c1a8676ea3ac5b08a1422b548adf20bb", .None}, + {.Lcm, "-a0c9b948c3569e7c6844c3ef8738e4d752d0add34827d35197ef4a08da0abd68f4c0faeddb0930a7230b2277f98b673718a78f07a9c120b63e02366c298f3e30f4c43197a429fa5e4e1f1d150accc1a7516ed0f6a17a8be8c576fa282e1afb9eac710fa6efee84acfcf37f72f198a4fefb0d691ca1c01acfcb1791570ad24cd73024e0faacbfe506dbc5c89af482efa4657b1daa0c62ef2b2fd55fb7b9d4537ee4f9b428ca833d5012ec8f363bc807cc2bb415e0dc1e5285a0240100f8d686b3d89b7d9763205a55577a5e797ee58ee7e19ef01c8fa389b52f066dff1e597600f80fdefa27c3e31f855da04fa06b20cbbce7d60e518836e5c2e0b85be7af497b1957882e150705f7ea2ad8233800ff1bdf55d54416b81901c276fba10f938d19b92df3b3154e1f1926575721d73830b76a07c062e4966f09c8f37867c3d400c4ca894b8a5d863cc67cd7ae897823f7da0d9f374e7941d4c583c5d04417a4fd70b447e56701b651232742da15255bced550ca884e346b3aa99accf3a05c3239e11d62c9b71b4390e4ece6326c2e2eea6d4db5af564d2a3d592c5b7e3fe7033daee35460ebe854ae4706c912d11ca01f29d344a0a63690859ec53c7c3022591ae9c50718202e36696a24a9dbeaa1eed5d26c6b1b871b666f8bb13b77af9f024fcde234084e36fec6b6174dc5b247f6fd854c877f87e0beb1bc91e998ea4fb96d9", "-11de4fdf36f9513eb88c4b2067f5ea13967876853d984c0f816445aae2f27530b0f49e6f685cf4d7a790898285fde6a69ae71777f9f29ebc498bc711d10d61ec5cc331f80c8f16259e693daf45619427e0b6b3c2b8d7543eee31d29bfaa4656109db143d79476159c73baeced04da5e54ad5db2d965828d47aef57ffdf472155d4c0b71538335f1344675b08a438e8aa28b670d56f27d5bc24c8764a7075bed3a6081e975a6417d3e842c8514609b7a398189958032d50c1f122d3282a97f441521cce2ec3c452c208c184bf4beff6883d9f7e583bc648750d6941ed69e82f71d6a0d0530acf8568bfa11bf2e25827f15057d74dbe0c2387b09ca3d57ace72512b0bccbf765b236e5d580ef01c42248839e9e98e62d3893ffb9ce1ff553d4fcce18d99a8f8fed4fe0cac4384ae709147347475704cacbc75859b4da89c3358fd988088a7d6b3c045cb50d07be722996eb51aafa58bcbb545a68c1742993f7c0caafb4a9d55649940689e6e9bcf51c77f0e0d26d97d689c2ee8d16e127fd5afbce76f1017515161db64e47d3a3e4a7e1ed2f611bb98eee2e5409ad41b3b5b334c3b774ecae150814da5295d3eab071358539d80a5e0b9b974106ce21856f9c985e5fecb42b44603fe7b8ce9497de3222cb624205bea041d0642e68ec375741589312c6dfd25185300532fa8853c6eca11dd834f197d7a16387ef27634b6201037", "b390666f47f249f5f89b3fa0e2b7b7a61dcd9bf1c783d361398bff09c406973afc44b71f5518d6db28a616271d1059392f77d00db497f40152cd136fc1f78a05ddc718fc4dcbdb43efd29b704ee9abc487da835e1423b2fa20e3fefba76d3e0ae885df3e60e5795cbc1692433ea907be86f13920b2c628753667d4f05ab16f498bd9835feb890e1470e3aea2d9ff1228c39ff35f23b910c92759d1aa7183fac51ac490f0015bbfd4d377e648d295b4e74cd332907daf49f8c1e08e95dfc6545ea54b090e8c6857a06e71947088c2fedfeafd0b8a17632c25b7820bc8adf75ae1e7f88c5f46573b4d2a0ce5487ecffade6cc1ea6e368eb4af50cbbaa6e624001fe270183deb0e2eea43cc003b9947b3123433184d2cefd0934a7fc4ab9fb787754a5d99cb97db5219d8c1b754c16a4d973028d0fa383ec4ba729f4448e9b37f08472b181677713f6bc05a8de8026912fb5782a45c276ade20e0e728ee8a71245cc55b83a7e7a0cdfe07717d26096533cda3f508ea31353bcfadc5a0a114efe0b4563491c1b68927c71da415c81644362c82a2c6539d3e641de47a345327cc08e8944ea186cd976e7598e8275beb65324696fd2150b014a606a14c8aa1c8fcd8259edce43d7b46ff75d0348433f463ce410c928a2615b755b6747326e79d75d17a4f944231c60ab120d09bed3ac174e01353ec7f236f707c4c981e88afc735b9c7be4ae0bd33407a860d5b87532d9526f9d16e2a50b3ce29401e3786d0865a96de15d64b1278ab4f7b9be256149088317e461f2c0df087b14c7ff2b28e864a3d604f95b94d809160bb3f3f495bea94d19925a56229b54bfe91f5ae6a6f2ee3052e8103e04feb42e60737b6e235c1ed36ba0d1170d98cf30e4f499d2ea6fe67603a9d790389510d7f089db94199eb6ed9e2dba5fa36d073a09e26bc85229691bd897f1ec411c942fdc63100fbce4b5e08c0631544b7ae4d9557897d07e074403ab89a78e656cc7c75684fb9838fa0a06b86d6c51d54e882f8e2836833d5af295c5bab82e921a4ee49a1062121ad2dbe67608c7c06b307536994a41d101458a35e5648b95f2c7c3fd5853fb70ec25eee2a67135ae783a8ee2250411817bda277a0b97f627d79838403fc8c606ca9f31bf79728ff865e0280c69d0bf6fa2190ec9afef27eb74356f8d7bc466784da2637ae9e2a8c2bd7ad9ac22cfefe8103c6ad4fdf6f9e2a749f50f1902cef55f50e14410654bd6b6d2e986455db58abed3c5df956e1ecf0a5ccb15e1859c2af57df485a3163e5b037d3bf1b772f82b9dd638848cbb446cc837aec50722584e4e27ed7a1ac8011647151f826ddee838ef22d7b22230fe3cb136a9cea2be2af6a8806cca32141f9f5db59990c7d96608b2ae4940c00f4e2b2e47f07634a47306716ad13d427e04be1d92a85199c100eba4c9af89f", .None}, + {.Lcm, "-c69e78ce0495e633d9450dafc88898cc3f7654cbab752c2787acbe1b45f214b72a0d8588725f418191c41c4fa99f78af54a686e9b2825e63ea88261f16e4646eafa9936b10da464317c53b0327ddd712730e477ba983388b6b05cd25775d02331524b7d427c4348aef292b90cf27e6ebebe54302a390299a2d94bf31c3e21b8b079f16bfba1a4c68a89b0b40ee0623917ba0702962e3d83f991a96bb31138635d2bc15d0326caba05495bd073e47f73792b8d0a0043757b59e9801bfd5aed11d874d70106793dd77453ccf78da1c724354c10fa91f188fda21ba168921e22fdab1ac6d923d696a541595e038e270cfc6b3ec0b3dca16b3cbc82af788bceb0f5c16041568e421b168dbf7bfd8ad997af554695a40a6392ed9c0b4e4f6556a508fe7fd45943f2706acfcf5245a829a6b1e049b59b50b2a40bfaacc8f32aab948471de928f5cf37d4a3a09d8e9a2b98df69d6f0a6f67b0b0d577c202112d09b1ceaa45bbada49e6e903e370ef1ad4b63ce4eee717872464e63cc425ea094480b1d3dde6b7d009f29b1536ae84e19ded7db2f0a85f618df85a4a3bbfe36bbcc048ca2ce61894ff6874316e4fa0b82c85a4bf307ae60fbfd363a0b0dfa443be15145d68d042521ae3480831330f850a7ffabf9ef760f880adf66a436c144786944a686b5033ab6d912d716186d7af24c25888f879a7a6f1826d55242b5a81d6f6b057", "-88db7bfab88b657f52efdc7f02ee9ebc81ebfb70bbcf0f34293463e7611fd3b6a99f7f6cdac4b2abb03dcc8d2f939853d2d85c5b12d12c27f34a60f625f82519cfcc8e3511c768527a62c0eb3ef7f684392b6a9393be80f2c4d85cb47cc909065d0930ab6d0a92f651c9c2647550b76bcf29d6f44463cd6e3e8d940b244509ecf9f1bf83492ecdbb29a61535d97a9e75a86aaad225543a44bb1a949a542378a7796fa5f984cc69f2a46a91456de8aa71087291928ba6b71b21d8d77e3701f422f9cfa6c4377043ab9e72f7f6f133c773e5fdebe0f169ac1ddd1c089f0027be6abf4d4651e14c67b8f68e2d0ed14d423d670f0e8bb2c373a40df7b4138626c3410c7917c48f98a01e3c7d4810c85f5322890629482782292a508c6050099c0f99a2b6ba72bd94cb30fc2c632060db3771aa5df7e1e18f8751010d832dc27e93263d9b9f2da0a15d0133f6653c2a8d19966aae5291a86cac9e6885df65da09bd8c881723dd8b42754159cdaaa8899e97b076af8622331d2bf67960edd6473c33d3d6c50900889589f110fdc4402ea1c709dcf215a35cdfd5e74c7201d20ce382ea5086bc6e001f8c6f9bce8e368dff7c4a45a92b8fe948dcd2f03c70e2cc0e89832425179861615e03f88c9f43ea0705cd3a96fa92c5c5800f643044d69dd94b63d292553159ab2fcda57db542efbb8ee3f20099cd3b182cb4af6ff309fb292deb", "6a2e79ef74a8918af38d91f29fefd91216fcac8ac785e46dad49d6ab0cf4f2e25329f939d328b9348f022ac5044a8118e17b03334362352962d83abe131b011d8278f8641297fec8021752c1240bdbc9577ea34d9919811ccf6cf3fc49837edb15295aa5bcd1f1e61ae58d18953b4ec5f9134d8be4a87ed405a2a0ecaca1be3e8b97eb06420009f77f280a00a32859ce30ad7811cf463f28f34fb95ffe23dfb96a7d62fba228ac9a3411d075a078c6a60d52246f04eb6cc3892ab513d1404c9325ee1b502fbc5f1bf0adcac139ac0d4e624c0ca7b2b98a1ac5790e009ea100240534dccdc857b7cd91f885be98effdf4a0161dd0ce5bd7bfddfe637d32ac7d4f5f3deb90fa1c741ffa983d08e67b460bbaa76317301c5c4775e6184cd6a4f20105b6a0b7ad504a9b0a7e1ddd698eb040d4c637f883bdedbabe0ce79c40f1b7d7cf3e35a568b27a3d74adabd9b9789829880eacd9dcc0f4c1364b79c8b16359221c591886fa3884b435ec3176a82e6720c1b4b6501205485dcd12788ff8231b5e5d8e5dcd71fe31d09ab2bd8f17be42def4cfbf84e07d68e9e0e99766e918f2e71102cc0d74385c759e29ca8b5b2446dfd75eb5f6b37854c130b4a65698e9cd283cf384d795ec3218a98e2884511e80f9ef6f03dcd0c02634bc34583d414045cd09373baa9c9315f1e0798fb81c21eb37d785504bb6024f352db4d8656b0d856a89c71b2cde01051fc3a02d1175f56bfe0e3e0ec4522bf17624f0e64668d0b62e39ab0684daaa22af1b08b8e0cc1b91f4590dd79e4dd68cd1da18f74773bafefa84639593dba96ad9424097fed590c3b7e829af6ca879ce2bfa5c9530321969b82263f641f9b9df59639ef40ae1f69dffd834675e0ad8d1734ff85381787b21d8ad48ea1dfed769176ff1253dc1eae1d9a248f5d8f3e8993535f4b7abfd20ee00a513038bc16497bddd2ed3e3c9ad29f700f1ab42be53c78dcd630bbc583d7fcfb9064855c884b51f74ab708422d0f3d21beaf18d65bd968e0884d29568c3ac9a372fd1064d41eca1f20467a4e811a9a424e6894e470fea4f7c26a10ee18c6ab8b234f637595cd419f5df6d05c3f2fac23aba4a923c074b0ada0990b8a568a82020f01a475b37c81cbc5a1a43ae7d9f33a886a8e8633fbaa59f67eb535ea80077c4ba3a3616735967d97dd35b2a749bfecfeae0224a974e5d9ff4845a2820ddf0b059ae68afaf93df8414e0ab43dbd34d31171fe36bf476e7eff01991a663d29c0e8855530f64655674dfef2e909953f2fe5d80e748fd0b24b3fef42cde93f4cb79f72e6c63c12a0d5d2995e3f9b2d3f451f2b9eb53d79533511fb2d5b6f40d2b21bc0edff17d3f8485eb583d137645fa6f0da9ae67c17f54c8c47c6f28ead6159d23a133fee0e487647b847e9a5c71f9055ef3752aa4d77d460bfc703c622add", .None}, + {.Lcm, "-c0804a07fe4895669c274928869b56c5b69be7b0def2a38aaad27262f9dd7025f5599e37cf648d531ea7445a64370f89c867324e9547a937ef00e92a0169735ef825e1d8c19af110a0fde378783f50b78d72ef24b2a9457e495fade65c16d6c7e9a37f9b1c14ee29e033f64126f2f58358215438aeb9a6a8eded2cf2a0b973cb666ebccd96cb6039616da181b0bd2704a2d8487c040ae9df55af30040a60f325e3e5e5c1af5b9a68e3f31ed0f2b9d21b6d568b687c403da451ca79609141a2fdff2afb777da1508eab9cb07b09dd892639115632084418a2c3e7cdcff355305c21004a46728e8c3aad0863f4ba8c197439ac242ee1dfe41451c17f497695f44340b5654dc7a68ceb4708b4e03f6416448bf5fc7b644ea1ed704b723e7bc2d9978e58809cded8c73281ab0a028ce9aca33e9c54fbe5324e700e9f820f9fba886c30d8ec7a5680f0fdcc817b11f81f0f76eaa2e585317c5375a60543e8859edff31323727e9e393e01b8126d4c513b4fad5fe677bbc53b1e8051c9614f67f224bf1a4d536ead28fff2681b71badcc4ab6f7169b83860a6c615c25e0ee4818f69677c7e5ecf2a7b6c4a68a99874465fb3a26a3b365c2e026359c7befbb3ceb4e819dced30460c3f9853648cb519129cee9af94152b9125f194ef7e04b6032e5c46a7199a49680cbef0e4880980b21ebadc2ac69f31d5c70b067d30cb71bc7f7135c", "3f83e7f04cf864a788aa3cbf1a358942338e66d9f6129b388ff63170fe900ed9c018f85e96493c5d6224d161b67c75c71e428fe55f51d364e49e06dd940b68bc14e9526246619ec319db3f7f36aad374f0fbef1623b7f61823cdb7ba298967026e70889db80c729665502d8d2b6e3a1018c572f7a307e5a5b557c015487dd4b9539e17555d9a072ea8e42907a965a9e0ead057292bfae14decf3bbc819d0807535ae60a17b58de7c72c8b1d60cfaf27ba4b2b867d2f8ef37506bb507a1c9a991239dc79d326d0800051244bbcd5f307f9b135fbd258bcac3cd8f90048d832aa6ead49ccff426f1def489d0204387e21c1eee6c8404f89896ae0e64ab27bf041cb10d951c78f40a123e3ed67589ff7c6c307e3fd49509dcf2e8271098d0efc8a6780126121f988d82d05964ea577d7ba847d5e59e510c34b1013ac7226182e67b12c69c69b08dc6a954fff5db211bc1aebce6e88fccf7e580fba93c00fd171c39ff193706810167a9c58d4a571a49b42918c591e73e89859e27698238c15c82f30cad8f24bc2d49f13bed12492314b012b37be67b896911f765f742916bfd69a04434ff662f41783ee82417b8d0a71bb3c6d8c4a6d73fb25770c6a13e182a5e9517ae2f6fdd972fcee0ca6fac7ee9f4502b91fe30d5a72614e0303838f9f9313c53079b7c33e4b92b93822833928310c27281177d106d9bbcf04ae8c75f0e55b", "2fc2c2464e9e77ccc566b19edb598e6e90acbce474981624a9caac30b5218a8e71dd34a24c87a9bbd75d7a9a4055c18ff606ed1fcd5c875fb7e8e56a40fd54039f71362a7a36af743cf394964da41534cd353240739c9cb6781a651d5675c405d7b8cd381851477a8f241d99331fb1109bb95e9d6ed581fc9113c4c10afded29044e1cdc39903e8315715570a5b8174e517258f3282de9417672251c23639e043a8f6abb3e591d669b153ac83d9bbe5d56bb26f29009ac3cd9b733903d28c1162b9374103f3ed889bbe8d528e567034c94553e4454b8faef1a959925d784dceaace9a98d60d577debc9607da40a49d71d828aa8a699fc25cc120b255dab0af14eb5693365cd27cd6009e0732fb26e0f8b1500b4cb3919fa0ff3e9c1926265ffdda63238b95bc92a16b1d674151799b0be95ad5a979da9461237bfcfce672f893f72e43b1570b81a642f3df922e3b84dc33aa5cbb385102c899867941bb0c215362d3415a3a0cc8d8da49d0d064142b44b119a702c142cdbda2c81a9e8ba4d30ea658b22bb0d01fe533123f14c65021085e10aa78e22f75696a847e14b5e36b0010dca06ffabe852e39b9705df4576b2d7f8510a861aa2df1d0cda31d425372400ba1a0565c53df63a91c10dacdec0cca926da1ba1b129ed98ef45dd030c905758b565df4b50d99646a540c4ccdeee356b7939e26e0c59b0223c4b50011182f88ba6bcb2cc4a9f0dcad4149213a33f751adeb9077b848eacd15831bbd7813e6d4fb61146b3e720093524dcfb3aa7bb51756c707387a47330561d53e33f710ade8eb4aae5ff0d3ffa6219524b41078978f7f408d1a633c8c40ab8edabb0b2b233018e6d875d85041145c59d7cc897803266b136b625b3d29f0509ebe717afa621ba0c5d8d54e12b31e7deee2cfb6a29886c5d62843feb21b9e2bdafbceadd22de6646cb6af3d3b8b9d01900dc81e1db783e84fae7ce016bab1671d520aeae3b7e2c53f44c80278d370c9e2cf042858d8a2207827287363dd76ff797e70b1117b445be2ed12688a9b71e4253d763e260e58b3a5bd410935b325f7c011ca641a56d36aedc8265eaaac4a85f547c9082e05fc067f4bb6ed9743442d5c4f99ed42af25fc3d92b2dc5fee71d3b4736d1bf35cc613d56edbf557143586b83e4a307e9376a76b06086f235d6aed960785cb74c4ef368a51454661a63715ccbbe10b19fba42b320feee74eaa235a872ed5c90c858cf47caf3b379f6d394a1d46bd8e89310a0ef9fb15e74848c3e107642f760c050195c53cd20f3b430fa520efbf217622bd7209a6cf3f3f9e415ea76222ec6bd0fbd749817ca1935d1dc88d7af30af259b36471a6c8f17f98f15451de1e5dd7d0d0fd42bb7009d4a01a1b27c7a4c66a5149a299cff137efd3088d6f5be8105ffbe92a14809f23b4e20bd77728b4b652db4", .None}, + {.Lcm, "-7862679ce9c19aaecffe8a42875addfd34b6e211be37b3962d5454c31b0c84ac6e7c2b807f0aa5927e0a1a622ea5c34af3e62137ce3fb06cc5f0b94e8739339e04fe2449dd2bce5111f95910f11707b3d2829c3a097c42a9475f768de06ac43854f75b500898dde78f211371546468a8bf9ef061426f154e99ac1c1abd1315352f1df1bb03a350ee7f8e49c2caefa391be9b02cdac691f7de77fb0099e4b096ad7aa8a80b2f05d61620f7d0f9107dc3db9d9f2e192d575db17ededc7efc3ee50d3a7bb9b78c2b7fb39e88a1ab607f3647c5dc3b94168ca507c8fd157670b907dc3423a564b41b47bcd1f652d17539685767986afd87a57a14ba25cfe405e2558f31bb09e19d74ac2219f2725a17cfae1517ca19238a909083323628c53e940a23931a590162ba4fe0ad2c0b87d14033d45909ea5d666a57fe294c36c5fd2b6712895c66ede3e2b6b22d803597acd9c3ed9ada7935633f52572a935326838ac53ce27c61c0409c895cbf50394f3a9283d859e4d6dfc3f246710a2784d18c5b9eff60c6a175b96eae2c0cd4a084a8da031ace015143cdf023384d6f3053f621129c0ef32182dbbc7ea33f932d9399fd9625b4cfb92c08b79199b90a420b999f944024b70cf702dbd9fe14d7f10e64f8211bd3c0c730ae12cf1f36491bb9f4b7c73b6e95f653d2710d670cbe29cbffb22288701c97f2a98a35910d24894dd923b98", "6cee48e8c3b88212b93a97cdac0ec6472b14fcc85f706968111b039a75ac11933076df8f02d3b9ecaac87b9417b8f4c84918264e24ba5477e88981a113c3eee844279c6206901a033d05d68f43bdef458794d0f52cede98f1678c55341d0a729ef097837c2b8575e43e7a0390327991fd9f709f2b1c79eae48f21ffb368373a50ba10405e10a7c38873a80e39781cfdd29a0ad0cb488fbafb0e2ab5b5dbad1bf8a74963a9a14ad7c9e02f712037f12e2451030e56347ee0975c882348b1591a47a6b35e21c6ce8f51166c72fceb3c5527ead503b62e7a304988e872b21d59566573f9f0ddbd262eba267bf99687f9c3f65a8f7c8caec64601446a51e5928312485a5433e401e212957b2f7e6d0823fdec3b04e7ecd1c71f6f305d1ea48849d2f08e87cac4d87d080d92cf29e51a0994720b0399aaeb8089773e8d23c1344ce521cd0bd821a8758421bca20d520d50535ef0e904356ea935b6ea8af0395e72f63efc71f2b82d4f924195093c170db792ec00bc3a70021ce59bc918d6529c72062084d4048a07faf85d312c98cce22a729d9547478d60976f16467f4af8681a32de15bf86354f9cf808c8574780618b0a95e33c1058b2d8c6ae3afe15c41ad7cf5292a847237bf996cfac0b9c8404630cdeb7f35b2808d98c748bf4801122ce07b107dbc083621315f6abc799e3375b7fefb19fd7f0141239fc895a45641cbdf3c", "cce645eea36b000e7ad0e0a9a03eb05723dbde38520bce062157e2d15a36f68dce6d695343b90bb965b317a76fb23a4a97d522b8c0380515e6625bac3058125a8b1bf2631297171da0d9177aa3f76e39472d074e730e2ad1c28d191d7b1b44c055a0d87626b49ac09d9ee66fa020b0f39ce96af3a16786ebece3a51ea6e5e38464218536b25cd275b88ce32d70359b21dc6d650255f12dc324f967b7e460b03fc96e79895e41fa7594ec70594f70e1c6d936801353280c1eec04a5581255f5065f4dca0fe039cc36032e859807f95e6b340c893f928197c568713b4a6c3533904a0e1fab8fda3d92dfbec244d93c3d39cad13dcd0e42978a4f33a958900d7fc10586f95e148107267ef30bb23bc26febc21949b54a3a68e11014a73f2b8bed33119aaba6c1668c45556887a5130163b0b68fea6ea276963f569017652055077754531adcbf52448ade855354fea577079d863d2e1aecd3e8ed86192154437ae23791718b26b4b0b0c653838f109ed18f58479aa76ed45538a52b0dbb469eea15dacbbf11f61d943c1b9ee5b3e2f12c0f8535c6a62c9884987cc02f7d7e25fc6296549d860f4bb8ffe5ec848a35e8f1803603d21a47630a808b0e7415f74383fe4ed8aae9bf08c4b0f5576573d287ab464c491016153b9e090284eabb77f6cdfc97e070a1779a19a71c3d55848b41273c0c5a45bd42a689751d67da48571aeb50f97d5b866e5dc4761cdf21bbd4fff6be081ff4fe7881063545afb4d073f3b9305211f182761c464ecf45d6404cb6adf9eafefc942f9547f612b71c0d485dcc7fdbcd90915b6333a5ecfb6d046d46a83726f3e0da352baeb1ce7cb28256489715d7c0c30f82e69436ade132cf8a5ef2c06fc32db79ae39f82d62eb71fe0d1c45b5534809963b6be98a141deff737e1d62d8dfc584d0a1388a6e584d76c5cad029aff0e4991920fffe7cb1a630f060b8d872848942449fef56ab981ed0aa82a5c228efc8c9831d1f1a239f614395e444dbc244e73ba6d9b6df66d7032a695ea3741cfc81cbd8b10d333c995fb0b9795004572373a235b8b75bb34e38470daf236cf723e39e1137f1382ba6e8f4ca6b91298848b5410606d097b1368bcf87d01314491db980a9e0d4f2fe39f25814a883377e001fcf73b239c8ac871bfd7c7f6bb5a9b09e36a0f970a9cd93a123dba4bc41f928c1e32483f016692602118845ac8136d0e17a7c4cb41442c4685d65b0bb709998e70bea71c561b1dcae9a448dd149888a3ebf35b556e2d44dd8ea1fd06ed42f2ff7e1ae1d1565e733460c19267ac3bfd3691cc6a04898fe17259864b2261a38b7546547b76decbc31b9f91f9d3c44a0585d1ceb7894de0885a39f17974567038f10d23de189150b76cf574b71ab4c579084b3eb078d8782fd5eaa0742ab260fe656f155a966f01657a434a6dd7e8", .None}, + {.Lcm, "c7321e7340bd9aa22463a644fcb878f2fe7a3b41589fbdc973aef1b7210f5bfab609773124e54ff86929718f51c2837a706acac24c7266e8ef347cd58635f5caf5d5f876001fd8e729036658aee0dbd9d6d14ef30a27937728f6396af7c5102d813c00456c1d8ea74f26aacf22f04360b782a08698f8b0036fc3241b0c176bd76a48542178f67a70c820cca3712013705407008baa910200f35727a4c882b00e877ef1e39e5af087002d36baff983269913684edbb5e4b6118077d4e50f2d9123f0c0f0ab3fe9b8afe7609f50844f4b1e9e7b994068c9922c9f89979887a4d043c69869147fba1541d0f4e0f98f32baacdb5c4117ef172f176de9111f2eb756ed08d742f4e2263cb273f68cb9b48180830510c2b37b35e44632675ce5b1846c883f245da67b1da048f1238264f8e035765279de14c03fdc2967b3eed16b1233e1272127abd65585efefe8293a2b44e2d73a01d7cdcd8c4160f3cf8cba571384cddf4b65f866c20f0c8e3870a86ccf1c05cbad46c6d32d352b2f0e3cd7116c0dd15d62f8254e0489c873a0ef2605f867e7318f4108f22b3b21565b7ae42ad7cb34644461dabecb40a98f64e53dc9bb593d585ccc7fdeb9b08b10cd60eb85fd259bfdeb018256c572c6c99d54f52ff9cbfe9f389712b82174b1e6694d2a6a785308e17b21e568d3f83d77835715324e94b2f561ac67a51dafc705d3363f746d9f4", "-4e84c6aeec9123523fd10252114bdbf36e4bf19d0bac0796d825570a3696ffd4f418c8d8afa4f78881035eabba655c61d4ddce1b14d17687a134ce8d6e2384f7fc5271021f147af36b07195d79b0bb547e6b4239439a4a59e79f430ad02d5bfb256e9cc6ce993f351f9ecc0eea87c39ed155e62b16906e488991413687cab11be97bf216ac380eeee1a14ea9164de5566eb48a0300f0673a832acd573f5f1491043a8b2be4a3ed266bfa1505969952c5ce63115686d828603a05cd94897f1d19287754554da41072a59bcb60e1aa9c3635ec009c977b395870d0f8168bbea374ae153a7ef22408b6f7e106a5ee35ae6e45f2d6860054c40923380b368f13d90551f18f875604f7b37480e1dab72c1a71aee050ceea7020734d670e3ed40d1e86009ee12a9c49eb72377f805a1c9c2923a0a9c934795813f408cddaaf47737c20d02d571136d062e2b03c908d1cf13ba4789358c8b1df54fe59ac233c1a9052aee573117fd66262e135d50d38b25a55cfbc12c68c60c73050b4dc2c5dcac1cc972761990b2843c9187388bbce954e8c25324f6c4dcbeaddf3bfe36d58a2e469c225b350a01be664b6caf21bac93452e95ca74bd490415f77fe4b0816e08748c589d02ac0cca0dcaa5bb2022f0c768638034f382af4a325fdc846818339d7b29503255b0e0faafcbaadcab7f4a2be6445240dd3859fb94bdf45ca05bf37df66517", "3d1895b7b0d8203b21ff9252bfef9514223e368f5b70dfdc64e7ad0515fe0ba7f6a9a06da6ec7936c94e376ca9b6b96220aa4811ac7a1f0644f5a595b8f9cdfd2075b6d848d14d43322205c739ba53673f2db5d4e596c3cc24c45a0c6879e31afb151432cf62d3530144862f25d4467a03af305339065799cb78167b64f035a7c6e004ca0633ddf764997410dadb033305a2f0b5812888dfe6ff17dcf234f293bdecd1effce2b0b9327071dca8cc73189331ddaff543c31aface4a622f938afd4b9c3a21e3973644e18f0d5363433b7d855f1ca3b700e782478cee65f2ebf87c27eda210c91c6c6ae127a4d773b09119c5f5c2d9cd8a3d3913dfe702af5e7aac7eb907738ec615ae83d4a5f68beeed8b80f7c299740efac182652982ed81a553a864dc5585b918015e5fc6b12cb365f17912d300f3d07ca4ae18081a0cec91b6c5134294434d1cce56361d0a972bacdf6535542e72246931bfb52322df5d03f394092ccf4250de85cd0dbb8da1503cbe94917eedb81e76c007015d23854a9bac3ffe2ed6d4e12c9be89ccdea803cd9f5058ab4729ceb1617a615343911ba3fd4a7f326eb1825ad1bd60f4b5bad3e559c8aae63f21342e2e224984f60cd18e5571b35d434853c177b252154849230acd464e1e5d1f955fdc8603424f464b07fd79eb285a5350aa0769acdb806d0075748a9c3b630666b723d533d7f0b929474bd21b06eed4f619130206a0ef31575d0ab5626daef6b30e703fe24ae467465f73e629ab9bbf8d6952d6324cb6fb6623fdf02fb7bf22ba33d7c4bd1a0092f209a8d67b2861d62eedbbceb93f0cf58a485b9f8755b675763de632d6540062697915decfac5b9daf51364d3e09097ec83ac0c7942655c686f05cf1f937c64eb243c16c354ea69a69bcc8dd2e4d4ed11a478736f73f10e55465ad537b5a55bfdb211a00457a0a18f22d00f6c3caa899a381098ae378cd8f9429a26609463880273949acf07f062ab33022f2768abd0857c6ed948b7425802aee3dc9977486eb43d4ddd53eb172dc43020c1fa53dd86833f978fa2f42fbe926d2d822e34f846016a6bebb033708949a4cf7ef7e719b09ad37fb03ed8b4024819db6ffbb6fb59e99b30c2c898bba3504468954e0cf7d3ea56b883a8be6f3bc22efcbbb805a768680e5b0d38991e206b54e4395b7488337ca6bc01870a55999544240b456d79c227c82bf40573095cd616a22a31b6ec18585ac0dc5e3a9d483b4e9d1566ce1d4e3fc534fecdabdecaec978121ed65046cbe57bda34dd459dd31032cad6ae62684b91f82f75eebba2a7335f04ff39d61caea21ee711a54abf57354a79d3d93fa01b1acd5cc387e9528d5d6fd82182a64e07178d0580935ba4250c24c772da59a518eb9d120d154a67418ebaf9c4fadf0a84a58f677e868e6480ac6f49fdfade3a7bfd2d8ec", .None}, + {.Lcm, "-c3a4990db30a45968cca123c9844985dcbdb5916e6c36dc1e8b4c069b4d4c985ce71ef9516f6ad553604c96f223e7d5e3a20f8c16fc32670c37d1fd7920c0bb180c865d4206deeaf1a42d2851109a348eaa1f697b595bee6e706e20bfc0927206c97c17d9e0e40c80d591972960df77c8c7d048011c38f1fab937fe2147a76355b2c99dadf309f354349eea12f170fc8f74a3b38eb3d47754139350155afc520e33aa1abd792981832ef721547edf4eb636f9aaaf7ec95633230e312fe994fd00934aaaa1264588dc8bc73404c2e19ca031fda84619986bc839761361044f3d3225b09258931d5d1a98e592efc71cbfa4fea60104067b7f005c1295f5f598ce2127d80d7c61717b1cea61c83771b2ff6038ed2d1a9bb76083e4e376ea4dd5310787732c8772d82f293593e1f535c989eee32a97b9e70f605a54fce7e78f14e272a44d286adb29a4d0d9665adbf51e3bbd27ef58239155f56204129a71309df4e9d22f343387d46c9971e531daa67e79e7e064717fb380436bfa5d069c1ebdc0e9cfe1cd0dbf420148c5f76eee41411a6845048dfcb131ed535211f82b05dd36de3225000a331f5d2b9355fab4e964b5bdc8281379f69ded764a08a5b2b18886952155c5e4be979413f88b526644fe1f41bc292edd86b21ee2afa96518d8cf270fa5a704ab64f648db29d22c5a0a934d8d384e6051ebed2f5c470c5219846006b", "9b2d3098c1dd9009edef30bbc48248e69d2653714f3854fb5891be87571353eb716e8b2623e3465fa1ffd6983669b7faaf362508d68fa48ad1669c5e01fc6bd70d864da63ebe88c6a3f6d6606d59478dbfad413c6278166231dd2b12cc2c62b89b99a110e57b3980acad9646264124b463f62d39cb59406bebf6cf17eb73017d8512931a6cfc066c1e983f5c689a9b78c9afe32a9c69a08644181c0bd7d1a9c369865b2c5ef17104f01be672a64a36919f0319eee18800ef53864abbd4e7888534c5ac6ebe0dd6e0dd4591afc1c19e56cc24981ef0641730bcb2393149516e1f94aa3386e6bb89d1f72cfdcd123fc5e14e3d89d5730ed127bb4cf5d5e675116e92763c6b25a8034365c504e18844052327e9175b505e3d9ad575571d61f0e3f820f31cb8ca475a1d222942f60456fb7b0f68c168acda2757231bb886e89be63e48274f6a78ceca39f27bf590845cdffcdc5ca71cd0664189f92aa5ce8b6cc601e6371e4de6168bf0806ee8815f5ff66aa5cec9f36361ba9a5659f708b006a4255c5f98581535f5d7c5c3c32b4670368f1fb1028bcbf1d47fdb34381c9fc83dc73b9a3c6d7ce20a16f4ae68757c70a949e15eb243021480b160bd3398689da97426d589d31d3918e637b11d87ee975783a16f4a8e3b0d71c0448bf4f6f82bb93cedcdaf17d32ea62c88e114f207e50d871bed6e3ca100543ef3829e7c15f43992", "769731bdcd658d343f603679f4821e96af2f8a6929baaefd0d7d2f7cae10ecc051075d923feb4fe88ed2ebcf9057c83b1e8b8efb1fe9669b530185df10bd6cf3d4910c3c48e12212dc4a74d074e5bfa0d2f99b8be8f39ae0b5c29ceb626d0abe4bd1844c4fb937ef53ee13ec1ea713a13dde600f99f67d60be58e63bd9af2cc74b6e62546091e8f4f800037b86ec9288882a40bc3226605ccfc113b4071395f061cedfc39335ef65482f1adfe9ce5d1c79c66a7267ed120802ccf0ea596b07df367eb7e27a1e0d67946a4c8bc426c3d71e915b7bfcfbfa384d82e830fc251c86c0a16eeddba7c1b1c4ca0a6607878761c4ee03af7a588b26e7fabc6bad7559981eddbebc12693d261257e0516bd593df7da5c778ea9514077c8cf10420452041462ed0efc616519319730e6f28059bc012a9eec4e8f1ef0cc5cfc7894a796c89d4758d11a5f4f5f6d47b29c733f0955c5f5fb7f767554b0fc1c02caf550124a3b7af53b0378b57e79de62c7e54c3ea20e8a2fc41772c9bdeca7061d7d5275a870e64ae9d9f820887e5652b168de738915667f53e8fe77a1045f696dffc6016ea2e65ad7c63a475874dae2c15b16b351068e967b4723f73e33a8e27132d8449665709b6800329cc625b9c3eaf6cea5dc4927cae17c3fd36471e175fdaee06a143eb1825fc6d0b1bde34811f6b6c929e6fac4f0f124e00aef004508333d73bec66973a40b4a681e4679206d7b04653b5fefef7f5b6f81cf548badb832198b1284077d926e01d453071bdd089e06d372c3b9244266623eb118501ac0a6b5332cc5da26c0f1ae06eb2b081597ea9b037c41a847e6cbabd68d87d49811260c83a3c390837d137d9389f504202ed67169304e06038fe048208e78ee07f4947e89440fd1e735d918bc51a6ba0dfccf4c015d46512774c854c038ef28a6fd5a8b27055611c722671ba835ca3c68c6995e4e51378ef77cca80c87e543e9abb13b3616d8a794210c57c1e54decc9d27c4294752b9b5807d42eb490d023845a0aaca99c93f7fbd465b4f967e58ad544334c6d4032c4bf727c01e42ad07d242a403ce1d461b695718ca15bdbb6677124bf406a1ea47f7a2ad26cea83403fd72180e1429a8b5d14275b65a88c2cfb96f14f92bd1169a9b81ebc46eef28085e5e412b67a1986cf11b2feb8632eaf2d297d5b3df9bfe260cbc60ff6e6f192151703cfa078de81823780e616038d20afd8195e6b54c5e3d0c3d245adfd206c69f7f8e34ecc8320d9d772769d091b947c9f65c0f05200a734bd833ed7d100c204c5756e088a52e85f9a46f9913f752b2682132f7a3b7f2b2b8844d937533f790537891df12e8ef7de224a049f78ec3cbdfdbe391a428d0aecaa94088cf538e36f65cb3afe261ce5b5461b6ae79aa341b6caeb91ebec548c6f1bb7d0102424b8ab873806a59b001006", .None}, + {.Lcm, "-b53727baadeb489594b073d7f72ee2a91b299380472ace9b43c45f366ef6e3139f5f3d024ce154a212c1d7d5999f41bda815d5525f48f9a73a562dcc355a908fc287f580cbbe84f657cf2296da53e2f7a2b5b18fd06ba52abab85d2ba6012e21f5d16f179319beeceb556514c2f1dab9732b5c35f102dc7c73a563cca76d23e18ac16216462efc7f3f8da51bbc085ddfda05eedc3563900ddfa5c0aac9f8fc24e5303bd0c0c012dd78cdbb79a75efee6529f015d2de55254827752daaa344527847fc33d25ac925f7feef316f81770876af6ca07dae0823ba7789dcac5567e3debef0026205889158718bc4e65eaa141a554988f46b28aa14cfd379179597f92f124d8923cec4e2c30b5fea9654d8dac731d62990bf6c43490708aa47c8def120d9659e3432e0a66d7c42bb90a41f37eac60bba9ae1a71a12e81ebf9eb38bf95fe27a33e1b22a8bb41c11be7d5212cda422521046fd80dd94d61dba947ce6c52c12862e4241548dc829b8a0aae5623a33e54b141bd926fbe36bf0150c06dc14cac3f35167b7a6e00f223103a9f79a993003a810b3dbe42b13612a4c57e8be0eafde1702fe713e4b726acb6cb5998c40ef39896a7f834fdbbbab3c2df808edfee4903088d666d2a356a593152417db1afa26b92dc3da9746bfdb2a2ae7b8d8de9607475719298dd6a0f8d3014cc35b13c34069b8250469bba0f52d84e6956780f", "ad925b668e6a3a1bb77744ef40034251217ecba13bf0550739c4f0cc638b14f93af91a9420462a21007a41e053b92ee41574531dcf2145bad044b43fbb6dd249964b97feceeecef12081b4073ab567e975873ab254a213ed78fa1f791c9611528af61b29faa5328018df9a9934bf99411baf85667641f8aba8400a217752abb20705ea2d1c4f44236da23a3d80b5443979e80fa4ef0fb2098d2d53213a9dde4de3d293316ee62817c60e67b00099c5d2096a0ef5d504d1b1a1697255a0cc8247608bf2cb1fb799ac0258e45076250a54864b2b96866a1363580bf081a6f5ee0b2b2d734c0cf7b1dce4d7fc25e124567de00951b4de87768c2201446ad81b514da54bc5a74dc039577d90e87cd4416027d245f061c03621d62a11a701757bfcf6cf9412ed76f4cc5b1d191b5627b9ff404909ce2e679971414dd021c89caf463574dacfa2867bb15745cd23efcdebb5b6fe731ee542bb2269adb7d6c7302860398616e852940b11f7f9c36604d2f2adb0a8f464eefd4857f72b7c13d484b147b3259f88391879cf94b30905b90d670266bc402a19d030ab0aa51fedd4208bc2dbd78589099c92106f9d6a4565ecb41018548055e10c3d2b63df9225b25cbc1485f563f15df7dabd733d865860046d7f7d5005bb236933cc458f6d4ba3a8dfee88464e93399578cbc8ef70bc96bfdc22205db06b1b865fbd9796030cdf6a5b226b", "7adde00103e82a7286cafefb93d360de7045af8a183b83c9da44bed8b93360578340b7ef8113459248446888a5376f645619fa5fc67b5f83ca62ec1e468d56322ff960147a569c93e8016fbb22ee262e4ed9ff3e45e4eee5083d3228548eba8b1e6ac0a50c99cb881ed9311a519dfc7b751687227e842f556ddd132e5a764172583d1a75da6249973504ba13afed564f5d8f0d1e2f3a23d4a5821b136d13a23a8c4cd05f5c5988f97dc8ff5f143090cd6dcb06d375f1b57fa7863457537ef082fb403526a42a63034f02a9839a2d457005d92fd74b602adb950f977b7aed49760604407814f66f05b9aeddc415c9ed0b9e9a53995d9e9e1e554169e890cebe8e9362645c3b252915d9f1dee22190f30d6540a6316b9038ea8d3485002dc24dbc2e85774ebf790d879e1a0f350ddda082852e808a936a982c019108080210aec212e14406cc6ceb1969a0363fd3c9e3c0ae66a7f34c2aeeec2d7b28ecfc521b75fee485da88cc20f1ce750d08d698fd8c1ed8f12eb62bafb6f04389e4d09d5a3a00aea11278b53dec3d7854b9c596493acfb0e771623f384c5cfc87cd20d981c21db164c4b4b8b376b57fb530d5523ce3dd3f39875486e8b51bca1b96125a3b216b190510be7f5042dfe85139aa38dc45cf8d6572a4a47c3e25fb6c030c0eacfedd12204c4121ab01b30b279e624f54d97a31ff8e7a00bb3653439e37fd91109cbb5534281bc621cb60efd719c94c274fa155d946e0785f55a212f89bd7f1343d7741d8753103ddbdaf5e4b9043e2e639da4f9072d9166615dcb6ad60e55ed20261ffa7f3026ad779f25e6294b1f2f9093133dc61be231022a34d2ec2a3dc07805a6879fd4fecd73718c2af08e54620bacb7247725350bcb1d666643537f64f144076eddfacf3639023e416e05354f91bf493a618fa84c42ca5b4494b6007626b1c74065788240cf2a822a903fa19ac17a33ef80fc5b8d306152d52ba529b45bfc03d7137a238522edfd54dbbc425b3223ca5275dfd7ad7bb77c51a7b00acc61db6f95ee20615abe6b6b929752f775a0a357ee9a1fe165faf4e706417782124910ef688f0124a56f1301a1fc231864289af511a456ee189144d1a8aa242b06da7f00e4e2d42322dbd5cc9115b0954f10b400e460aaecd5da3f8f70bd29adba03945938d7f6a404920b0c6bed41384f37cc8c46b4ee8b6df9b30bcf293e28acdcf9f81bade941f93694a97d97c7b8f390399395d7d6ad975a124d6350748457beb3253e30ae2c75f7bba8e1d0faf15ff4ff4e9ca21eb3b570517ba7e6dbacc5f5dfaf854166035f16c484313febd5da8d9ec3d82af0fddf22c24055471c626ca9faa846f563daad5aece3f7bf3a5102e5e2d6e8ba831a7fc48306eaf303646e0367488849392c8c6a6e32cbb3d562ee06cb259eebf69d47043c5f85b47666b2c45", .None}, + {.Lcm, "-713b3b6b487669dec856b908d060a50cd5649ff00c2d0b7be61187129a3f3e986edfa64c9785d58cef1f8b7ee468a8eba8d7e503db0a0ebbfd204dee2af2b1be74a8e23b6a2cb168920894715372f63dc809ad7f8845d86e758b07ad4b8eb646fa5c02a84640761081bfac6bb43f951df1a3cab6385516294042122bc428f99a4a1d8a90fa6275ac2449929e8d3aa67464c7bb0cee9f5e6279772b680e237c97991d1639e7213ae7330a6c7c7158c331d1af5850e576a6161cab2b596e410d705469ee618d76b8dbbd32ba57ca046135da2dfb0c34102bda93286361bec83b01e02ae9782996c956bdc79b2c9533a4e1b9e33c515fad33b74f28fdf5fe443bda435dc0edaeb93d298e453077e7eb2ca08e468b782eefe4c6a3ba6970a21fed6aa28767c5f557d5f366f96eea9c96f07f3f9f5a5f030ae3f82d085c1b0efe853be7a81703863c828711681ec3f70c2c9d712f11a7dd1c1bb2b6b94d8704857cc894758ea19f57d102b465a111a542282351c196df78c3e04031cbe87a35555cfbb9ad886050e35185a266dede56a71055b8b4190258efa06f078a456f28dd05b35e81fe0b292c9bf8a6e8f9c5bd532d80a02c961dc5ed53f0fa9b9f774d55bfcc70ef0fe58203e21821f940d7d4f5027df9e74ea4b6496df738754bdc2a34af596d62c94837b8bd53b5096c176846a87792fe60a7e5ef15c2e34165b16f47af12", "cc3aa1c1537c311a32283795cbbee3d0b456686a2cac540bd5e3bc6298917bb525248f91e69b54a16ec13f25cc2ae93d2dcdfd2f17f048b7356c0f3402d926dc1b42f8b987654b7e46227d268b238a62070273dfdb46c47f42440836fa2055a82b20a9d7f1df765346dfb586c8d64357c2e385835b99f9c09ecfe0f69bc029cea3ec0a3e8b77b714aa6d3a0f1b7dd533cab275654bc5081e768a8d2378a41fe53cf964a6b63669d66cd1e4899171dae7d5211a8840ae7c9ff589848ba85ec78c514383677f0f168ccafa1737b52f4142f5b348027b5613364f0c39fb7f43dd28de42ad42a1e4e10fbfe53770903a23dd15dac805ea8355d53d71c1bbab9d6cb2858cfc974908b7b26b00f27e1318f3e2a803b866077ec5823d69631cec034d6cdfb31eb0cd24f7733dc8e79c5a67f63465db276df5790ab10cb91204131c80ea60edc25e86fb666272361d3b77f17668dcf4d1881d14ef038b1304236f11eba150af1a1f57c66e0220dc4bf9ad61980ca16712554865cd84ac00c825541bf2197110c01badbf09ec109dc4d06e490ef4e46cf0c17773fa90e3b66944bdec0d8cf8073442ab1ac54ef0f4221e19264884f13269e7ee8e6caeae286a4dc07a97125af0eb164114a3f7e191748105119dd300c28b8651d3d029937c3a421fd73b9018de5c760b249dc58cd9b52a79bd5d953b1153265d93ec75b7d0ec0503052148", "f0e3062c92ab26304804e7d8bdf0cda6f28139ff9ba1b7ef5b6825879cd56abd996314d7071a2efcaed3fefbf0b26ae82c3a40beb0e140b9472bacc02d704fb3a918439e7d24f9abb7fbeb65567d0c3e6417531664ba974447c4dd670980eff58e87ee6b41d9f638e1022343d1f81c4d6bc965ab691a31b5b98e49c6c14473de3997df16bc460add5396b715f0fe0922d6aeca42f6415d1e072e2a30f20732538f2f78135a7247a4eb33a591486538f3c7284cc89f2e00c4274d2554ad8360e727a29bc75658a54868a7a3417da28a88c2c86fb2dcc09c7e8a3f832cf149c4cb29827c729b3eda55200731459e1fd13561b3012ceb0438fa601e3bc401c2582d88ec8bb41ddd685dd66a56b96edb549c2b0bbaa6571af452b32540b990829f2951c5c7b7f15392e117307f77910b0151124418a2fa2fd8c408cfdd9ed497b23f8dcee2b4dad0e1507a2c832aebc4ede49e61cb6bc37d6fbafd754f6e1ea3aba4674e88d083378a96c5c61d64399063b8956aa695f0434890a8be4aba63f08040f0aae1b51e36986b034bfb12d081cf8b99e642c124b1aadf5d1e5b39c6b89cbaad98bdd2c779dc8164b5fc1ed3af641414f39246c0e77a5486397cdeb62056df46cc845ad956546dd16f12ef3ad611bc156af011cb9de853e34b8b527e95d7af82f67ba91e48e77f7a4912e9907878878261ae5a090463faf6f393f090aa02ea6b671c4c01f6dfeda0f8a576c40ea31d75541479c6cc7bcfd3ca9428a4048e9bd9844d67a0ae5c09281292b80cbe017357dfa62edde3701f756ed1a73bd5c2d3249ea5f9d3bc5876cad0730f109d26d912acae547ed057174a956955b716f02b58db30cf8324c3637a720886cd26bc704a4cc7822f307e6d4d6e0de21e7e5f4f6bf99cedbce56232334ba5dcf2a1b7cd866231863e68576ac7ba8c6c0e4c4fcc416156c73cf46c864418328489e0e37dd68bd23e51a171aafc22e4918be115476ed67bdd5e0596663b0eb1712cfc41baad8f0a94c04a309b4ab1c0e01a358cf0241914cb2cf594cd4d4c81ae2ebe0741b1cb0a104a6b683735f71ee56f1416fd3fcf07b7a6ebbd33cccce31d282e70c6de25ed56091ac4e72407cd082c58f4824038ba9cf79f13d2a95fd4cc1085c6df69b7eac90781a3c1e9cc1ddea81cda5b7d366c147beb5ae2901d7af37c85fd63eee604c56509c5d91710f976c027c5cb87601c78b464b30d40a3c00d7f525883f63e8e9221d6d4999c6003a531be0a48221d75c1ae725d3292a56ed4c54d44414990d06f6f966412e3b70e0e145bcee4c8afee863137dc3579f2aaeb76165aa04721197d06db13e613afa5f16e60877826a86b9de367b978df4191e27c4ade53b133635033dd1416b4cd53c8bf67b281193373b27c93b28109fc5c4aa80cff7e72ce70190f5363521481557872e17d8", .None}, + {.Lcm, "-bd284517b0782b4bffaae3da1d6285f26be65b5679a47338da86942137c955e404bdca677fe547b0b534a80034f4ff587ca36561f4d0fc62f216c6ee3b793b653c90aaf53b08e9d8a9cfd451e067a404966f9d32886ed4120005131729ba8c720f62b0e6c2e1f86e21c337539baea1b2f7889a7d9b1e268e07ce18119080d209bb95eeea0b5051146fb9b207ac5519a530cc7845d5fea1e2cfca7060d1f967c648a9e30ecb4011be09eb41242237927bfb4a2e4eb7bbc96d1924451fdc56809ba793ed06e0d1a2ab14617649e2c4a2880ccfe2465aad75107bed21991f1b91dd638b55b14e52fed82481e56339c2a8a659ad5826854fc553528b2ea67e0bf6dee42c314bc92dfde190e9d67c54bdca70bfd2cc60f7ae6f63285789b1df8852c8efc87bfb8281b64a4663ae89457244e8d6e25de30976ce5c905f7790972dd9bb332aef772c1ddcae4e97aeeeae2759dd06983a2a4ccd5abe7ad7d72c932e2b477a105ed12eca2c6ab59c55a4b80b4529bbbb487cf497bc97ba166ccbc24f7e0a7d086806a37f0389ecb0bc8313730721d59b16f56847d61102ad362f11874c64e5d026f62425276299e9569d90289d0d530ff662fee56b2dfb9960ea08705b5cd12f5538c6f7eaf910de6c5c15ccd8725b8123724eeaa98c7cafe97178af0f54a56b92823818fed2aed70c152f438813c67292758588f88abcd0c4ef14ef630d", "fcf8524ac80dfff6381d5ae0207a0638f84d936577ebabe4ff9912fe0e66fd47fda9865835decda300bd9e9ebb0c2e955a31f9db9d8fded6b34bbef49737e2fb9fdeeb52183d27316f7a026a331fd830d44bd7597688c9dc2a5b19c6ac651fdbbe5a5e96257ef3fd3822d48d82b95bda81c349b0e27708a7767decd512ae19826c23fd2bad86d604c0e2862aa65d376a2990b200ebcfa8a02075b843b8e00bf13d097a3a155b31eb8c6d984e49b72f93f0251da05380522c7a1885665b59a0d81d2746daa8033320b72e495fecc36d763e648dc78cdfe8b573872ffc153caaf363684ddf1044b7f4c3f84cf3e4719794b2cf3a11b9cf35029279fdb14a79a2679c21bc9f3a619aae3c220bcb3af2155e5f079c39fb6622fbd7ce2072c14b600b2c98240bf536705ee3a0c6c4b3b7bb727976fc3108e7df3340ee812c125d0105824e9755e71850b0a2fbce58f8898b4a885133c8ff31af38414641e605e188b6f448af9433f5e5847243446b2423fe38762753776103470b3abaa90d484cc4e16efd29c682381c625f2502f28709248ab0f8b6e2426fecd3e641cbb14f8e7cde5690678375de5e232d9ef6b52ae9685eb66fcaa091b3cfbff7ed073f57bf6e8cf1db2574bca8a12c797de53b2e81d8bb0a355d71ea3a211304ca3aa06b06895174b6f56b9e69e0f32c5dbfc20c0037c5ccf55ca58745b5d077a295b37fa2f4b9", "baeb1fd468409c8f50f416ffb39e3c6c6fce66c1d8900e38e9902bbcc1eb1f5a83d946e71194587d81e1b23f0b8af71fad675f90ab23753706ce96a3cb9b0acacd5950207ed8ce1962aa5b50677ccf33e0525556fd407c7d73f19f11e6df5e2ee4032c7479f823a912d2400ed542edefbfdab73e7f01ddc9cd8ff80a5a447735b5034fb8b510f640c4e960dc9a3f3a56233eb219e01c02cacb1e4499153f21c343a2ccf35e4964503cab569f1f7292692e397304769c97858853970322875f2e3667eef3f09f025ce9a7fa4b02c7bc428664d5d62dba44788cc5b22143cd1bb6b7ce00f9dc56316a86131548e84e44890fbfbfa4d64d9c0da97378a8244256a937f09655d4c2b286dbdc4be03e7db8f8c38dd2acb381856494fae182091646714f8886ade11286194a45e6143d244465b5cc40d740211ba3643b1568731614bee5623170621c0f5e21e5af55d79314d00007c1cd87235ee56008d179ea0ad4f05351e4cce3c02e1f72634ba820c588a570183ea4328e845d4a2d16e1f9c0f6378e07ee1f5f00dba16dfe98ef3071b742a24fcacf907d7648559dc6e11ec100c33fb166bc8b56ce7d2c984bf8563d367549ccbb2ca5b1fb020068950fdaa9139d6806d5f2895b4266e995240519845905efaffa0e56d43a409162470a72ecd0b5145bda287345f26c9d6f616682e6b002c7c1eeb0f81a22f709b0d956c02f85413ce2b95256bbdc13ee786519162577f62875d80e80827cc80fcadd749308c4efec6957076f5d7a9c674f0ac47961d4765074ac521e96c10850e5738538e150088d9ff4e2f497835f22c721d2cac0835eacd658fc754e68213ea087a01e48700edb92085f174fe52f34d41afe64f20bc38ea6af9abbe7c6bb1386c6b0bb9d7137e7d1e65047325e59294361dfa84a2a1bc1245952fe450708ff76ad541af59a1ff060ad4cc00d26aea42a0014419d4220a5d6e96c7a065ca49a5f0652694c462fe09d093b5dd982daecf4379c7f5d9aa6c4e59e1faa3118451f76c188b5157a892bda17a4ba0ebd8400108a31e019b43eb00b88270a7a4e69d0b42ca48ea66dd43f7d867567703cd0fc24d2a1690a6dad40bec98219d13ceaf662f2f7ddb7dfc14aee30f5ea7762c230f8444bd3260b9736725f4e586a0579203e86d76a61c2a5e659e659330ee69d13756d708d451da664ea84c19652e229e822682dd8eb315aa2ed4f3f9d7d3d9ca7e03c106af5a919bc34c1f356b9ccd3462b0e2effb74a64e1df9f8807eab356b742e78fa26171ffa21cd231bd782a0a7dfe6aa0a91fd0642da7c616ebc76fb2b61151b4c549934bf5f5b5b87b053fcfb1c0f5b1a16124cdc758b8ea86e3abd7462ffbaa822711cb67309a3872139df9c9a2c7ae887c938359ef7d155aac0157948327608d8f43b34faccfee43fff27b5a8305716ca0f865", .None}, + {.Lcm, "-f8139dc99822e32d6cfe678dff68c26b9dfd2efc61b500b7fa4c3cdb4093f10f29a95214b64df2210e92575b196fa4024d90898634ec66db488bbc2ab710b4d2b684956adcf677afd23fbcf48c98e5e6268e1fc0ed8793088d132ab6b1604d045e4a485ca7a2cbd6c0b4bca718af79a58e5428ebd286ce23584abd4e17942022066844a6c93967d3b47ff6441b7cdb8127f8b5fce3d61499b765c38af45468ce2c6b709d2cd425012ef4bbe53053086e020f85a96352d6a93e24e6617a6b0d500e6abf1d303dddaf52f6197bce4f9388c6c747462464ac15ec50dcb1ef29497919b04b6625e568643b3c9cd0a427b79d456592046189a58d1b2b2e19b6b5916479475527fd172357c2053ae9f722c75fd303cede6082496614e57f2dcafa0c7afb5e69d0209a6790bea4e0f291031740aadd4130d5e0015ac6d1c313f31a79fd3fa26008178c0df5ffbacf36690548759f0e3612357387b97d36502cbe47a34dba89d94a70be26dccde7c3aeb5e0b5300d6cdb6d2fae9492889afc5bc0de39177dfcd399bf69cf0156a90db5d8c47bbfc31fafbb9e53dd4971d3afb72a19df4158af419da4b9dbaa858aac0a6a0adfcbb4e67b213161889be9cae96e4e7768ae32b12a946a4f8f5076227a1043e5742fabd6b6953527f73fc5f1150bbff885e72351b7ca6222e0301b45246eef6a4aae8a32ee1ccf30ab582c99bf57ac36b697", "-f06b65b6fb737b5861d04b51b2dc6c69e44bc4d787ebbdd4bfb35423afa9508534606c85b88905abd91d7e164923f35947b9181622ba66e2fed550618c091bab0c29aa0b04c314c7d720401c9b39fd056b1f2ad4bc922eafabad3680fd27dc16ac9a0d260d0750e960dc3a35cfd47b9d94dba005ef684b3400abec14b4668ea0debccc99b014e02e1132f5a651b9a4265c6b6d8b22bdad94140514bb599d4df7ad36bfca21db3762b989735bf849e98cf27cf5231f0d943ac3c2909b785c279da80f5910de479cbca906e2e4660b32b61f1461e70f0c839ec41f59e8b05b271761c9b32b74697cd1e0a48a42606ee2c5f569a6f70de8756e811845d00904fe10049ac33797ad5c4068b71a2b4e0aaea8f412b02986405193c7e805187c03c2d19410d3a7a7837cec4456799ae512b67fe2421e352fda7cc2583e7218c8e22d8cde923cb0fc3e44d3afab0e8bc03ad2c66fac36d1d00fd043a893e1e31a5a57710292bb9d21d4c4236030d117cc4f149761f71a57af08e010040c3ac45c6c7e6799586d1744f51aed372ddff3d1a6811a9a025d03860dcf55cd85de0bc7908e84168c91cae84a0c57da8ca983890a0b4a2fe6c04196b47d6ecbe60db4a23820379e916dbad06b83ba313b8bcdae7adc0d304a22b1189bb27435473f7d9f42b4d97724bd9820711e518e1eb2ad115073db6a66b1837f4b6c47e8a741d859993b1b", "21485a19494029fe273ceabf587291919de8bc24b641dc78c7f726f39a2d9e1417be504858e1d614efb3db34a40a9affed264db1779236b06b06a54e9848649b58efb1f9d22f6f772e19d56b1935e75b3301f2f7fa46a04566debf7e2dee3cb9bf30a676eded738e55ff22b2038a93f3eb643bc19c94073caf0ea1bdc079cdf751c06fe73710e25a87a0b1d09836c93f4684432d84bf19c8f7258f38dbbea7583bbc0f031378868b6acc72a136e8d644d08da1bdb608131608b3f8fed319294886418bcc93bf2919cb9e78bb254b1ff59a62d62107d374e64c49bb4ba396ce642f7f2b00fc1aa511bbe76c6d6e25e471cd1a6f8bcdd99223c3215a85144b89d6e2a41e09d4aaa4b2096f8c2240dccfe2d8eb35ae498c8d7a52eb4d5907c4cc2f7b4e4af7da4798027192f0583d8288a56f232d7b9ab9eb26d09da98a7911cf706a95f76b4c297660b7d6dfae932c2b93375c56c01b0f08a85738a455e5fd643c609dad099eb07e657694a14b64ea6672b770fd58fec74024e644b23cf19d0fffa5d63cfdfcf89bb365ce919faa3cba5333fe8560ded32570ab33bf612e55ea05bc338bd19635edc7c55fc77a33e0dec75059af423b28cb6d64941194f465c69211dccf7af46d60d5d71c228da1824d6b54e308119cb1f7100fea8b9da247f8095255165de6d49bf5afc4751cd0a3c847d161b97b94a05a7b0d7eb9c08d3f61ef55b3ccd9aaea1d077f16c19c746a8afbf87e6dc82995a15617ff083c5e854e84c4e7af1e7035362defddcb74415bfa7a9c4ff0a62b464c4181d8d6808eb128f9348c69f63eb5edd14f5ab6ec8f086602cad99a7ad4e1f15403ac3bdf72b994da33a6f30991b6c2b85d28b1394f68fd6c46f252026923e4f34d332a112e3e6a4f0fd1b31eb696ae9a806ca6cff0171360aa19535df439367fd0ee15f54169caba5e491fc0bb9e2fc45d3766c9f1db5e5e4e41caa7a1083ab751165ff99e2ede5aa08fa25cf1ada51a0b75cc374bd59df85c931dfe52702105a78f79b65b30339f4a2204d527332bbfb7746e896d4460141ba457c6210dddd58dd90d91e2e77460b5be2e0f4a6a2913b36bf2b9131699d430518f558ce34b75205b50de48d0e335d70c0298194f82f4f952522635952fa172051acfeeef69d762a96244e368236b05d173e265126ae35d65e5ba24f7f117c61bb065e4ebb1d8b71e823b3b317b0f09d5ee0e0d6344744478069b64ea7fd02b88bb9c9d4c751fc1a9f683c8ce27b62902f1b729517cb59be325f44b55a118b760923005bed81e134ff976b84a4e36394834b68c10ae7815a7e9baa3396f17429f92cd032d2967dcdd5f8409909468f885a144dcd82ffc227b47566959670d5952e952944ec30a4c02bf0012466ccf94c29b19c50daa37d33ddf5a601b1cbd3720c4ac7967c83f4dcd3f5c3303946b", .None}, + {.Lcm, "c9c8ae511f91596ad1534b53a36b354f702c2573e1fdb75ce47a400047dea3e5bc8e16be5028b42ee75528ca5fd417b6e60625c211b3e368341ce2e32749e526e9b48c35ef0603865032ddbb3c3a9746ec14d2b129f20f1136bee5372cf6c318bd9f0613e37c7a7c75c0232d5b7f7cfbc97a5d3f37ad186a4cc76119c21b517a7d3f3e7bb63d7df84c236b760651875b81ab084d3fc46354262415e854ddbe2f8f68dc8b500f63bb63a45d9a28f6e36994bc86a65c307837cbaf9d1c2b2bd32013ad2d76ea7ec4293dfbe44929e407c0e387fa1d1b1e5acb803fe03e7e773d0f3770a702a947c3c6da825b746aa3efad4f0ee27eea4e388f2cfc2326eaf01207e12267452335c1c37711763080814defa4c39dfc0a13aa0ba185866b3bc04b27e12681491c3d64728b6e0576efa6c936a290328cbe9df18278ea665c2a9271d004427f181da7e1d15e5f2cee6cb93bef016c064be5aa41010f78ae5fa0b19867dd51ac2ef3c1223d5d5276fb1cee9cb1d9a1dfab61d614bca67cf2601c115bdf04a00e7085f2d779e7ed939146ea62392b7f39f59c5a25c6f2dcc1d02b7cf5418f382c87593dcc74bcc6fb7bcce0c455a1c0f73d251a9ab41fc5b72acbec749501ba0f9211edf5f185c5a2c5045816e4eaaf08c1a648cf25140d9299b12c01e8cd52a091d11427f19854bf24e9eb779506ec34d965d72ce025144fdb6ad874fa", "a37e8f446a949822c21f089be63bb06f364ae3e627157b9e66c75761bfccb7b4a9ae4b35c08b10439f57d6c621345f38f227655e72b3ce03f2e4f0cdcb2304c65f869bae949e536e2016a53e0fa36a807c975ceadf95c71c422ae7bca7c51f9317946a5ffbd20680853f348b60b9b750f6d289f4afbd49842d34112fa858a7174a07cd6716a819866f26bff7ebd74a3b4ea13bcb609b024fb604c50c44027cbc934afdaa942bf68f9a6d384d95cf2ae9d391ab56b2b99031a2e77f8abf8d8b9ffd0ff6ab80e742599362ebd2ff393a539c68923a3f7f38808a76fcfc6de5ca7c2ba1cbcecda3857da53051f4fb5299037bae5bed2379234cb7393bde1233b4ca06aa71b2a59a0a30d50b47ecf994ab1f950a6f0afeb6af65c7fdb291c150fb17f4a0d4a58a97f3773330c53879304761ecf8fae28f2e40a7992438891cd060268ca6c57851a4b83333f30466476ae235469e1be569afa3b06b7ce040abd893af460037f0ab60235454504bbd2e424d24cb519e8908483e576ed0e0980072d93906faf272ea820f474f8a9f2777e5328ef6cbdef3fc78ea13491934cdf67c64eab9d4142c5cfcb6dbadff5e4eda43c88627b619c6355b5aa3377a2ae71de3f956b345e0e279853046d6db251529c3783945424c42fc5ad123c10fc3c83b24a8fcc51b1242731de1ace9ab50eeb1ed9d0ade84ddceaa44ee3f34a677121b0ed7cb", "80de88b079b6ebc4848bc6049d6a9f6daaa7e909a48f3543eee1d39aff1be791717b4f657bb04e0297747adcf15eca6ef8a84aaf9a0070078c63f85102bd3a0ec7558cd541f2fc278d211dc3677737506dc5ea072240db1959a313ee3e3195484bdf66a63cc70e1ca2c1bb5d6678641573c3a6c11e2e93de96187a3a76f72054df1b4cd1be47be7feda83c34ed401bf1bb079ca589b09cd1e8330ed1a386aa4861acbf847d92f9d058f11cf39fb11350138e3be4e7406556df8352507e2a8d8f4a5a4593c018b5aab30e7567338cc789a809014e89ccd939b6ce9d42857f7139372bf66bae78fba51c0eb78c4df08d436dd8d405b19404b08642c4f3a1287588364c19d086428bbc7a060f44e41757a4af42c08e9d6c22d2e58b3d2e828c465ebf375a116616a2bbdd1c44c959cf47a98aac87d51db4817fefe816e6d9c6161fcfff5fefb3fe4218a958f0c8328c02e0b9bd6250b1c43d2e628b57d6bbf429c243bbb5776409b529535a553d598e985b4bd27e95da79588a61986a2c1907839a52192dfb9436cf247f402d7b7637a36a8c36c91272a66440dc0274c5ee5fb753aa4d806ed99bb299cc5cef390d130778574dde5cc707b18894e5b3cf62dd8ff97edd9a85751342d3617281503caf9de0d416efb70aaf189fa9a8ac3a79d591d25abdbc245ac7dac151b8041529736cef63e36ae588388c83e27e36ecae694656be153f169605304f5e335cdb8faad419deb01837484b3832c99e0c651bfcabe4163b794b74be96b034692fe42ef614aa0a7eb8963f1b6a52b84133cc055f5dae1941df2f4729931d75f1e46b2666a43f2d2aebfc5210276a47c61fecdceb012210f9b95d95f3f4d024252014d61fc0892e6ae26de0d0340872291b8a03f93f221f207de6d2a48aa0c84f601eb05c0a01ac52403bb14d363f422621ccc169b7d9fd621b4b826676f35fadf8559c964dbb66a4e079e3b844df443c81d38ae87efe44ddb093b60a955ffc0d19b4d811e8b5cc1272a949fe29c86567e47a59df824a0b310e3321d640e9339772e27874df4d7009f37a9401e90eca871631517ae6246c2148addabb902ee399e736c45604b559faed7989f5e5e202d37fec2714e94de838efe297cc99bd7960b8999fe92650606e0288e9a3f0ecec5f0ee4871c8e69e80aa4c6842bc68ccf83ba0e172b52c4d8e650c4f75f44ee454411e9631b18374d19211aa5da02247843d7ed5eb5c1d55b634de03dd9e8befe182afd753d00f0da9f5906d1d9e29ccbec4e27f0779902023c82e33179616bce84efa0605d1b382f8131447f624d4bb8d198c57a2d29f3de87245757c02bf2efb337d26443778e3e910c510563c76c8ee2d7d70b0f113382d0cedaf6f8056855d279ded074a792832ea3664fc40932266be3d6fc68ed6c60bafb7c95711226bc25b57a478eb83e", .None}, + {.Lcm, "-acb4a393a6c9fea86a91fa019e59ac81d311f4677ba3d7229c8ce33698ddb9674a06b4df74186a5bb45453d98f9f2d5c9a89e9482a384e3b044c73623308b4c1f736a4453179bd1a29d6ab41f6649f69aee6e9cf930c7fef28ea26a65f084435f81866967900e8d2b7092efa0452bf4b20058d471ea63ece402153db63987c74b19a3590730a12f56a0a06bcb485db2d310c57d0945f4641e0404d062cdab11df3c9670026139c3b2a72c49ec56acd257418ecc951a04e29099eedbb5028acc6f0aa7f8cc204d16baa32226bb52a636c8382394e25b81e75bd8713e23c4f59abb0b8447a2f4e9975ae62ec3190dc91b9c708c36b551c0eef072e051d208fe97c62e8144929c4ee58780f7a3b28f435e5180c7b731517a359f482ae33d7bbb8784ecf3def28018ca5e1836818c3b57afaf2e37f3a6055bd97df595aaff62dba75a9e40ff7c80aeb2e3e5432886589a9964947fb90a27a1f8d48debcb6ea947c977083a1f1455c12a95176a3db23dec9e7c121054dbe46096853e4b9fbbe8d4c197639e1fb3c4db0734872447c5ab6282de4e2ea92ba923409e4983990d92202ad3b10e22a1b0bb0c4e039810a0a260eb494192d984b7cceb00514a60201545ab1808ede0db2cd8330a061ab21ba5b1d79a255b2da476830342ec9a2f7363b3ef8af3fce7baa1e723c493ce159397ee084dce2eff21cc0d09f17d48396dd2d9d09", "c53c6c955151eb4071900da255da7890aeffa89d76a8a4e7f6a3971919101e5664a05830aa5cae18d089b90952f8401d47e9ac54096d21682a49bc0bc6b09ee84f65d19ef38736ea381bc506c3e1d59b0f12018804d34e0eb26007f8613a11ecefd5d58776a9b2cd70e58be0c9d344d1338f7bc54c18dcc67a3b3f4cd81ba672d1e783ba767f4e07780b2c928cdf8b7c0a4891b11da7cc80c238ff975a3c62f8ce17cf5b5afb4d7de3b04158be630b61b225d121bf9812b58c13ab87c519ecdf9992f553845ccc19c1c98d5ce0d4fab09208dc4abed17488e54197983a406e35623f6f533dbc4768fedb8cc05b35be1e1eb935b2d8c3e57f363cac655db455d1cea2ad810bbe191014a22f0b7d62b1d5b21b30657a4a707ce6e616d91e7c465f434465629807bc86792610a4d39c307b742d69997a6806b4ca6f84f363fcf8585d0abc730cdd95d960a50ba63be9ea7ce6ed5ba7da6d84c3e55a25cafa1e9b8536a85c322901daee328195966fb5eda2086222bee4bfec331f5b7f4fa51eb2d0771f72b8c859a7d4836ee6b2bd0b07abef2262ae684fd8e4a448ef17c4645b8468e9317b5084b48296bb8d86961ca456f9a17fa7e1b85a328ab68a4a18303ee0e7d2f0686d8014739d3acdb4b16018fe1589afa1325811a243e83a504f436a35a2003681f701dd38d520bbf9e7bfeaf0275d966d3f75d1822119f84332a6f83d", "850fc577e6f6733b59e79e1a5027d825956b95bc72e2c4b8f7842baf5aeca0a49aa40f3e136f8d766c095f7706e297b598cfc8c0c50882c5a85944b4ea695daaf69c6d666128b3b198672493fe9ae3133f2edd57eb20a9caa79863af4ab7c85ff63ddb2fbd5e2c2b1b362445aecf420124bd537bc0bda6abbeb82cb173bd6a3b5fa7a4f365ea9d5bf6d275ca765e553407addfdfc0e20cb625f8e7bd4928e965269c38e3e26eb602ec7cbd361a7291c2c6ef4d654f6fcc2d41247a112dafc04294d83b290abc6d8e9b8c2d65c5030e58c11eaa77bf716ca8c616d1dc3311a592febce5c338b30df29cbe662dc82aeb2d9246765278ef29e26a82f5f549d9fe5a0e2f1dd1c828ce92313780e3d305c83bcfeaf9b85e1853a0967a4324eb03faa139ca30c8d679297b0b0f24f4fbc561de4d1335ea0462c525dd961b6073eb1eb936ae79b4e0a86f9979b496bcc3d366ed9d16926b943ae22d9905200d3b5b209874564f764c4fb472812fa1ef414c8fe7d3a8c5f17281a575cdbd1cbcf050018ef1e194232a658ef9fd48effc116aa445a281d35fe3b188db6bdf5bab4dbb978597d154ea552e7abbed3acf5c13f2fbb25ebabbbc02abdb1be6f5482a08ce9e54a35468797441f9ab6cfce999be7b1334d5b1c6e5759d84cd51bbb00c25c23af2eb4685db2d4a1c0f2bff337ef5e0dce94a28efde7cc4b402e7aeab0d854b3a78b498413cb2d6a7c33f80573cc76179f54e418e0f6ad95178181cf314be3b58d7d2f553b01801f70de76fda734b36572df81121a7722fe7eb47320d0f873bd9b9324436fea14dcdb03cd6693c75d14b46bba40934b51960fcb5f061ca8dab5b38072fd05ab0c11da6b4c2202e23953315bffb0b7a55de78c13285ef5b995df0ad1c5d6ab69b387f6f3d0a7bcfb5f90f7aed7cd4342b93592b72b83944dcb1de042ad75634dd8efaac8e6862c27fccc22a509d5117364e76e1d237390eb16a51a656deeb35e2096d988b84fe29721ce359b28f3f8f9780e1c398055db0ad77426569bcfc9849b37180e6f718ef8829ba433e86341d04d9c68302ccd8a54541ff9fea110aaabf66ab62c46f64b34cffef233bc8716365aaa7ad955eb70f38d0518d06df3bdeb160ba15e0fb96c9d7b0de8dc8aea4c6988989c955b00c0054045135936d9dc53b403f8e63cb3ce2a3720474660c60b5268d39a0cf6c9e35d30c26c6a70fae8d9c76e058a330e90d27cc4c98161097d926214809923d4fd94a41235cdd0e81ec6ce9e77093cede1401ae995463bb52f5b3b304ed232c675a2f04a6e13342e0d19c8a8c58674d6691574e621424795d66f7db44dab7ee903cf783d3b191d53a1e6b460053a43f0b3661fa5eacec7290c0ac4981efe4c15af85b1aa4cfd06c25438bfdf96064886ddbbf22f51ebcbce743f0aef383ea15a6d179d52325", .None}, + {.Lcm, "-7b7b46700b96e299cbb482385a83104a09476cb31d0a8a343e35dc549fd7dadde4e4f4a2f3d0a9f20cfbfc57e0c2ba4ff92bf8a6a0ca2077c787981be995f2275dfe6c3752876fb95dd44341d5309a665d29f1476ba8cc99e50be8686c066d802e96e0c2f63b9b29acfd467b3785d9c337936ced441f014a7baf03e8a23a8c0ad7e46e100d95ff5646a937c5639691b7b681c600aa5f9727c5c159992b24183f96b747b437796abd04c159312bf20f4475a711e3b78a4282d7fa2f58f7e50576d1d078836e776e5ccfacdfba2e9dbaf43a31f5c89f3ee1e955bc358802a9bd07aa94469b86a02b140727f3c5d24a9ad08c70958466e4f9fab659201543a421161d066d1ed942a19b44d8209ff4f4c1e5d0b1d23c2b4e5dc608b95931593c394f818b8f0ddd73bcbf90e0b414d64601015809a0d23760742dbba5a8ca5b1d871b34c66bb737c49bb582e004b8ed5a1de91e1d2d55ee71647429c17d81d6049bf12ce5b67d03ed6f89f6c3fb58108702572ffc15c8ad0fa39f68177bc8c30eca6acd5ca091d9bcb9e0335deb91da18541890e7717c9f0daf3df8710e62202079a7b9b34bc1bab3c9ef4e1b385b73333be495a50b6d197e88089cd082de68480ad87b43ac64fd127abe93a745cffd6c9f00d3d5d67a6a60e8c478a7923fbba126f13a203f58c032585ff049c459ce5e270ece5ecf04147bea561fb9964193ff6b10", "5c81172841e31d5f3e5c9df13cc51e86ef511098369cdb5eb1175bb042d26bb6fe003d955159138a99aef1c1b8ae3c5b1e0dd21de8ef1dace64fdb43ad6a9dad3f861cd7f4081f86bf69d0fe729c57adf77cbe9f4cc83f96d1b307628ee3166508fa21fb5cf076ce2171aae193da27569ae969a96c590573cc2910850b6a1deb9e971db5f6766ae3784a18039b258c157f13b5c857d4598cbdeda9a6894bc6886670278e57214da0380bd2f670f3f95ba4bf91dbde89a1ec80baabf6bddc850f09c7480a03aca3aef924397f3854fff516f47f0ca26a5a2f045763c1c2565e738e102aa095b5dd5f79998cc5fb0e6e2d9700a04e475a145fd30133ac67fee8d29cb8bed796fc6fb33fec8b0bcbcee7b26a0af39c406780cb6dfa45fd91b678c91ee48fce4e7344c6c77fde9b7251248a4d3895216fdfed96a80c9a53f5c84a9995586c19afe24dd2825df13f777ca357085b5b9ea8c8a733808caa73198797350c16016309a349d9b2dadf913b0e6ff5457465bee0cc2d52bb8143ea5d4376f1d5f98a27c9252f1a2bc5b0800008f9d4b12b6c3cec097462c39b50371bb28161932c035293ea6a2638b54e8bac830b92bd64ee4a04e64fc626413b18d77bdeb86bf3c18f7d4aeedd5c7e5fea0bcd465efd1ad78ef629c5439163ef1c22c3ba2035650492c54ea3ac967b81e9bcd3e49bc36ed172852d945d594aea7f1055e922", "76fc2ef0ad52a101b1f9d79c8b422264781f883f726e7cbdbc2f729524606c9cea228933ccc71ece6e7c0167ddbda3dea32856fe9f3c7260b0d2abaf272ebac42db96f6e8be2c279e63ed1ef06dbf959f0402707b8d9025a48fb7b1b53d7010ee244f1017b3ec00b41e2f450e142728e71943192c13628ef1f006ef178de2eb73ed7c7eed393b9fbe2c460718abbf048f65214a949b8e5b6db781be72bc435de099c70defe9bc5415aff5f00feec64b67b78c5f32c5204dd3e2b3e03fee4b5dd1adf6835231eec87d666c06ee7cbb5d03bcb86495f6c448a09b2bb6635b1d8e6d3b05b16c7f3dcac4dcef78a5bccdecb15f5a30b543eb27452177b7091f7114493e9e8c41bb6a017958eb134f0a9687f1784ab9e0c90535f027509750a8b4a5a5703732c4602da5b4426e245330b1e9bf098bccd1da84e46a3dc8ad5e1e6723c1d41b493d44a58ba6704b291dbb18f91967a371fcd298b9e757b913b786ac5d84eddbcede8636ca86c8509d9b1638ac28f1a8e3858cccc219dfc766369f463b7513e9acf3dcb3020ba4fe550f1e8d460957681424f7dec30b71589d01ac0e216e457d448f284355309f09b930cbeb3d435c10bfb742716a29ae55b8f10f5e9070bd991d67f01b8d2cd4e909afd83ff2f35d9146b143cc85a753c838d44e12c017f11dc5c26c8a698cbbfb2618a75d23dea4ea5866b80a91400b64eaf361d64773962b6cbcf398d13dcc941b5d3bb95025084b1b762bacd9368245118bcf605b0dfbc653f10c1dc3cd950605add0c725977a163254834e1f5002f6a6512072141f3a06237482e545eff7203c1cdbf3c05bbfd887fe9d723709f059effd32f065fd9f6e393cf6cac1f72f41a71ccb870bcf46bd726569ad74dda813dbaa2c45fffd9abb6a1f05df1c18acbc8d64b07bf405bc2cf445e37f54e075f40912a73561a99bb95fbb4e697e6a98fe2ce6cb6e4c2a5918de17de975038671759b3231949d0af6ee390e0ba4725de5d0c11264b600aed6ce714c2b9b7cef5c31f6faf28d1d6349176603ff4ae4ba3154901f92a9acd1e41a974425f1a754b33d665c64ebd5dd5dc971099638071a7fad5180ea6e0ee96063db9de5331a9b58cc6318b313a13f8fd24002832f77f93adcd603aba9bcf1d190de50c167f90eabf17599f9d571a69335344e3c4cecc39e8844fee1d9b244c2c870a56ffd7dee1c7d6a863c7bfdd3c68234ec76040dae739ed8f3f87c2b6dbf4a372135f2f1db0003323fda823d00c9e94b2c1ec9ed8158153e48daea84348e18d8908d5dccf8ff2c052aaf20ec3e9c580f400ebe41e86071f120046a1f58260c007e1e4c8a28b434eca218be03cfa789fd7122b7bce8098bb1f7cccc29d55b6b15b23fc9fb4b821129bf7b19e9d0177332194819763793b63c228b018c953e51a24c5ced56b4569f9721cf6b0", .None}, + {.Lcm, "a1f788386dd241b0e3b3846533b30d2ff268c393183234113b114b19e1b70b57f4b8b825163876c60e4fc48c5c4ce5f062940acc7b3f3ec7aeb70a1584e92c542a534ff33163a43c892214f7e4d6a75fd2e1c4f3111a06e8ee6223295064623298a59b1aef85bec404a295c9fb69f8e81847e23c74a9396fc37568fac0d0c232317879bfb3d66f02a397d13868f6e4f6fd465a96a0028226a262c51b06c0f12f076abd5f5d32f66b5b3b3c00cb66e23951f0d1d0e01ab43551daa06f0a1395d3569b18c55f4675a3eae855aa403c91a6b2025178d7971e8730f7176e72ad2f5492ca8aeb33b4c1fada9d6e11c0af5730dcb91329149e7ccc8679f8be37e62e923396cade1315b78844fca8c3bf094da4ccdb79957a0524007e57d591cdb6b24f37945f21797a32392e8a1ec783f73fc470abe9fa3f92ab121a7f3ca36126fd0f4ea0c87d106fb8e1b99474169e73242acf597007572ae2eb340fb25763c77370a8fdac938fb847b449c8371182ba8ea3c4fec83b7400a21c722295f7c487e3aac6affd1fb2df76067f1ffdb5916c0849ec720455bb43952c7e24b2abf09079dcf9346519ebfc0765dba4f49da7eb0e37626a62acad8214e1282ec5f9d4e4999e839f0a22f8176f9259c251338c273fcd308e39b475e320e21f57992e92dc8db8a60e776d2d6a7f101f256eaaa29cea767829ecb71c2d104dcad23fb14e2cbaff", "1ebbb946a14e6dd195ac1e6b20cf8970a63c3de93ed6e67e19b41909161fd453af24d087c8ab6bb8da6508cba81b2cea0d247819891173abb447d3f12ceadb5b400ab8baa49d99f4d73eed855810b49547c60d15080ee51e0bb62772d1f0a69a5af8234baacba76e81a01e8e5a314181e7d2e9299def2f238d8b7f2a2102979d25bae226c52fbfd901059ef2491abf3155661187b3047be4043822e6320e7823d1ca2064d8f50a99a205ea7223cb12bce01da2501def4ba89cf59d89d7437ce01bfb80b765fb1daf987b4affc05ed5d2596d963cbd0769089640f4dad21e74cf768b72f7b54e54661e8f49780ad9d9dbcadb1ab6a855fe73e0627a10a91ddb16d4de9fa710768a78af459f760274ea3054fb22f0e4aa6cb359ae8925ea04b0584dbb1924738353f64d8b76d0230c03e8bdb2b3f885b20141546bb13dc4497b88db237b15c72ed190e8b5dde8378572bcef8244f9bbad78508c6e1417e5bb21acada9a8a46545bcf05c93ae7de0b6dd83f3d0c8d49be5e5fdef5c3b1d60817fdd52c10988e26c900b92a25474fe46b6cba00ffa1bcf1b23dbc6a3804b5bc7a78e802709680c758d68f565f6bbf32fcd21b117cb7ce5aeca9ee8671e7306244a85bab1e282c2302ffe7ca5f4235eb1359b932cd5dbb64e5d47057e95e6a0967b08bff1a48b96c6383a5ddac2ae9e49ebedd162de73a755851f4f9e7ff106110d56", "1371c6ffaf452ea5ace70e9c287c43c9abe14cb4a355c92f2c72a5c7ac18a6d99121c7211a41b28a2ab760fafe45d39b19df133421cb4a85b4f499aae94bca937d0760970e421b6c0d438754937f70d3daabb01111cddc7c5488758a087feff68547935e848e8bf5f385d8806b0f59c22a08087eb45d5150f8900f1d2dd2b06abc9637ae8d4d6e9fe05e860cf4b94071a506755e744c4da299810b6ab70f50b80de74ab707da0d3ec6f9ca22da7c37628e549a30c39468a8403ffabfdea0bf63fd789008f54287a43d981b8d67090a677704dbaadd77b5a6fde03599250455e951eea41697b959cf55b40f5efa7705e9c273bd4df85a4689309304a54dec58bba64bd67a4cf68c9ba6f5e06175b887a027bd4471a5f3c0c3370ab82c1569065dc9067104fd0f10c8454712cc83727c19c5836ced4c9c25b86aeece8c547ec0801aec4012606070ac216f2f78d0deb80e21fba1675e87ce13665d9d5d7f668ea37cd4f5a812ac1199fed48a8ddc879c0e8d9d23ed503a2f81a894b7cfbfc506b5307e606b24a40c63748a4e50cfff451a405c21950cc4910b1df1fec73000b4d73a2ff23609cf9e60276177307271cead842f36e596418b5baa5a8981756417c6cc6da207f83d804505094297ae440be253ba5dd539a176a623706473a0d88715f7cf03be5671190022a987d1cbe5c1c9e42e90895f41348dd5edf8249998e1fc15012749f71af307114bceb1f3b608c783922b0f780d71bc971eb170bfd7c18c9262fd8d538fa59c92ccf014e395640f41ee21fe5057e2b858018f98e0efa686f3490a366c193337d5370da28732b23812a773f39da77043e81134367f9bc12e8ca7af312171a25d4eea6174df3ff7b8407a579396aa83ebbea9454dda23a6ffb79e5fcd438fcc4b135b357ec543aca11016c4c6213aea0ce0da9a59f1ce10617c4e45a4424a1fc26ea55b1290d92197f154e28204e98bf205e23214a11722824d043b3711360abc51ad4e914352b4833d12c57f4c84a4482aafea70d1dfa869dfc151920f1a93e78e7f1b058545bce170264181faa73b047b0453ba14ba74b25c52d7c2784be907625d083f1affe649abdfa0028f1a7366c9089dee2b33fc1fd50810bf4a7d30430e67d0d163405a86f1c1a201e2e11f32971c6c687b9c2cdb58eecb142e271c254e2411ae54c87728359d33c02792f797d5919ba17a035fcdab5a27c6edbbf077e80e6a62b30ce3d5e7d0b7ea571dff543a97bc57fd9441266d7e936b8fa94b628d6de356bfb40955471482926c9c98c47c1a0c27e7e06eb38e580e926ce3133d5bd16be5e29ee8f6ae0a0c010e482208927db59fa4fd2d48cd43a0abd9db0f4716968ff54d60cf8ad2d86331eaf658adbaa8bcff5149a6660c6540c89c47aff80bbc81ae2a239fe3bc53d9101133ebc715bb2ef1ed74c4aa", .None}, + {.Lcm, "7aac4befd52c98a7e917a6d37e01c5005ac823cea3b484cbf189d1ec979a39f6f5a434b10ea95b2d7ecc5def982145b17c07da49fb8b340fa173f05c0139ab518fecb380cd950d917e9daa61cac61c034e27e561d7d90398fc1e2f03542b595b5bbf6f21ace70a9259ade098a23e174cbd6a94d298fed6a593bf8c6e5708ccbbccc0b1dbb3bda7dc8f8791022ea28627733d27c486bfd155e64a81f44310e6171017d89a8966d2e6340cb95f0ddda811402e00460adaf8206158beaf6eeb4dc17e8e00b5993beb9712442842051109512222f84983dff55475de995aded0a4df199632b425e33f45e815ca67e61bf87f8693bfc3ceb2fc44892ab6203f7ecba052a172726dbb5fa0cd1ccb2f4537efdeca12c90c045676afbe3dcbbef87d89ee7d0da821f081fb4d861dc6f00f39613396d9a9b90846a9da19bf823802dec0c0cb8cc08caad2596bf675741cdf2a33d5213c2f2a4a3a7b0df9ebd40a110361f7cd24a1c9e4385475a3f04a07d2d777fb633211b1ca81cbbc5bf331cb33479c09349cacea889d32cabff9b611ce1be19c20d3bcb88789c016748bb0e42054a6990206b81ea00c00bb5c8604d970931d949fffb57befee97924ae313714859184746b6911da5512351fc4f018647a84d34deaaeb115ff8616790344de9a746c2da132c999393955255b819f0e8f8a9ee0463d5213941fc66e0f77c32847b7d8c02", "-1e4ae945ad28bcbc6bf9a6c1ce7428daf297f7650b2b4d397a8dca642ea2e3ca699f0521d1dff7df0979e992c0e18956295e77ae9450a2ec1f3df5bc7d4c8434e58baf012103c48384e89eba87d7b3bde037a2281c820d31baa2e05d0cfb3138fe493c63f2ef65a0ca0f73470d639a48132f79d55ecd26714080a9a297a8f85a2c62396609f40c61d87aedd29c04d37305ae9b1f09d6698de45085787639536634d30489119918268de9da66a902f5c7ecacea5e7d385bd50c1e2a3015d6595aa31b04913948f80236690860e63fb3454df456b93cc7ea506f57d4dc513e8f434efa12995ff02c096c772cf28d23fc1c14de72ced3185508c6e1a535bdb380127728a9100a586b4ad91e2b8113ffa7aab2af980ad3de76ee98305c597affc9cb4b13ec56789b459aaf232e93540ff14fcde0e3318fc49d2e751651cddabe31ffb199b9d4f01089340ac122e35138cc762ce3fd976ebb7153aecba0a9837346ffcd5f21230c40b7cd09ba7f840a3fbd796f25e65e48daf973403f1c3d0d2ab9a62f65925c0cfbbaa288f9b9cc3402e9ca10348c9a59a36b1e4cebe0cb3bd0ff2f168446a7dfe0283ce6a8ef53c9b0cdaf7896ed91e3bf6528980e0c716077b00bfecbfe3e8c9922748b7fb51e4a76df88a78a10e5d6b6225784b739fe1752b3fb727b46dcdf2f39c89f8f5eb9ade975f99d1cab2c53c4fbebcc67692ef7161694", "7420b3e216b470fce310d6ad7157b97d0805b85dda209c4e6351e3de385e2d35d67443b5a67575c2863d5d45198e8982313f3516e3c3c0ee7a8fac928c510f990578dbab9700f5d762f96b8504bb5d9898402c6c4917d1cb40f80f81c906b957b688be4946bb07a6466606cda2a5859b53769d5a640edaf7c4636a0cfdf6822fb1e85cea81f6afdbcbfab89f3d743b7550e26c9fdf9712c10ea18a8be2dbd352e00353c15ed2af2d1710a7e6793bad2df51bb3c42fffc9795ed3cc77f8dc24bcda37ccbbc6d10da2cdb0b11959354502c17eab3a2848076168664f76fd1587ed6db81e1fc3712c79da814b54f0a5ad601ee7c6c14f4a38f3f05c05278cc69364630d9050ad66ec77d4a5bccf649595dacfb3d28fc699259cbfb6cd69a876b391bf4bb8293a4516d2f8d48273983b7dd18123b9a0b1e6537cb19034d55f55a278b7694b5590b7d0d59eb49490c071c3aef4c2de6a7d35c765ce5186546612981e15053801e5addf06a189e3ef34cf13e17a00394fa826081092e95e438b8f1a34b07613253ec59bc1b907757285b363b4ef4c14a584501452aecd9ee24e181e81481efdf9bb53fa0838fc567a306b0d0011b3559044c94a8c5332804c0063b9827f3fcefcf88cba08e8b426f2227ff6492e17417ed49b01f4f6d40e3fa81dc3742e83f955ab0e7e6e0587ed2f6c57dcb7b59b0c58485c807a5653c03145b932a39f703164bbab212aa6b1539d6447417cfd78ced892b8cb853bc4d92a338970d89d2d0ee062cbf5e6a74ad4f5ce222ad864065a0db25013ec6f1c309a232e7d80bc2117070fb6ae701aa6c4c4fce64c420afafd774a2d7b11cd8bd920d5d6df31976015a0d2b875f1b3989631c2731a980e0089559cd2e7ed926c821c650a5a4c64b19992e46ab994c63b5b5a61f774e52be6d2438c8a7b5b2d4c77731586df77f72e93db45938be5c4aab853bcad5b79000317c5826cc61cd00698de28cd6ac4989961487a2aea7484bfc4c37ee30963c3e7810889cd8225577c2b037962c65c29d0f39207e92f05567d1fccaf97b469f68f1354012eed0d5ef8a52e00572727ccf298cbb565e768b15173332a835b4203afecaf8b03d44b36622f5cbeb5b66455f5ec1be16d94458c816b8d1f70b0f9b7b406ce89e060c9ef03e52016a446cea95e2a2ac498416f8f8399fd130530f058f8a0bd3d354cd3cf97e7fd3334e03cbd8329b88026b2c06efddd5d75fa5bca0cb98dbd2990bedfed6cdb54f7f23a0e8060ac83aac92a44f5c07ecab9eb569692b262e4371b5bcb2a3f737233e69cb67c6be6681c95333526c936751850345fdc5c833ab3a5731fb3852dfe3928f0b29f09d1f19dd6cf6a06c076a03f458560eb07d0cdb5d6c7003bb751f046fd90930e85f5808c635a0ab1e1b26591c6ee731a1c637abd6c50ec33ba83812648e94", .None}, + {.Lcm, "8d4facd4e98f5581a22f6993dad8178d55cdc1f1028376ffcc7311866c6b60a3542fd1e94e967b0595d3e0b6a12e062f7e1ae66f5147e58a7c471465515ed67f41e9856e1795e7301e2351c917108dc1b52dadbc22a48b6838525712c8f9c86823a7d5c04fe647e7d5a6170c6547ecf4616e2f0100927ba999bfd8391cebb800a32aa9a4f246ea9d9352513e31ffcf12415add95eb2c581b368a856124f0dd111bb12272eddf4a17c092658ff76cbf633dd317fdc5eadf760ca91fbf411c025d509e242dbdd9cdad535a02efbcd2ad3ed263931d767ed9ea9be22cc6eb7c895c73029c6e0c0781dd1782bf9f61c31c8aaf0af293cdd4a7d1adc4dff5416d8b8323566a1c7b7383441d74d3e263a6299b843929d71dc60d713414562d67026dcef70979f623b5abe6f2ecde9854ad32f75b414359856fb203bf4d7c24e6a6f3e77ba3d300852070b9d7b5419a85c7cf188976f6787f6832a223378bed2d1fd549e84e00904cfb81c80af2362f137053b07819153812f2019228ccbc679dbdc33ca1da71a22d38dd72ecaa3d40444e10cb135b9d5c3a96ad4a2dfb78d567fd8a305d88defb3c75ec07ebd5a53d722a21d0426caecdcfe8d973ccaca4077e2d4f8c77dcc08a28bb0bd625ecadc7da2f2d708c3f79a35c827a061c8e953a58564ca800098ccbd189fcb719980571a1ed47c1840ef06a108ae9afa284664ec20c6fa0", "-760a6af0a0522ee43fba44c35473ab57fccefdbba86ab266239d9bcfdb15a7ce869c6c501e69996b007b37950d4cd296c415a75428539def59f8f2cdbfa4644dfa0caa12f63e54939244b64c19d590a9975c1e2a5d07d56584cca19f24b3674072b33133bf4a3506961f209a805feaa9814a50f86b09c1f0209bd490407791702a9429f6bd93905f7f98424064c26954afb72dcc9045917ef2788d924d6d32400df37faf2a561ca67fc5e73412cce29acbbc3a1071c0061fa1ae3e42d29ffb898e9979f00c93a8ddca1952cebc335e19ac9cd5278da2a1617fc8f88c459a0547581bb58917ea03200b950007b2682726e0c3d04d50779a712a16dc43f80e0d12bc57932494b36c11738161ad94bea42bdbc65a227a41a3a9e2373f640a4eaa1fa1477ee6e9ef3972ae4ce60330bc1f92d000daa06e55a1ab45f07cdf052796873755c388f9d9b455cd2a04b3830165720ae85c65628955202229da6e14cb6e9a31892481fcfacbacd37851ca025953ed08b1c72b1234d75051297f97c76eae31a80921208c14d93a466b157fbfc4f1459c573b7a64e3ef3d9c88eccaf50f8a7a9a492778ddc4530bffaefbe6b15a287f3e7ddcdbf755bcb594f4674ddb887a47337e33b66b27da8405528013d6665280378777ab3f4a17f9ad61d1b40d27935365da1abf42645cc1bc22e1aad283aee7ca8b55693529da95810b072ab083f04d", "15b8289a3c3e2e400c52add7b25ed9981107bced1118dd01a6c6b74246a13cc982ad4df086d27be6a6626ecc89404a5e9b0adbc0b29fad83cbc22647d2dc4b5b2b5f92ecc27a8d5f46e1d997023d6b32c452a7b201a63c3378181c67669d8d4b3f2f1d993756b02363f9a45d40f68390c1c5cb2fd76c54f053807877022887d6edc40c879a12ad36bd7bb98592e6f76be31fff3e9258a987d9f0a0854d3b9a7934ab3a366111e4ca0db45344c6610d9bc3e9fe624ff0466f892b5031f41170f4c2a08a6769a8cde8d93b37752d313ade23bb8ec8894c2af8c22a51139a56277d25b2e72e154465d8f950075f27055c4ae7121a62b8bb70e633f76fb8667656ebdb5f36c9d5ec3ebbcf5e5353d812444695c1fb24f4e5b3a9ebcd7de334a1dd49d14190ae646131dd95f8fc4fc8a4ad6922415d3075d0f4b5243ac682ecf5a2785bf9e8eb4112dd308fb485f7bc7356a4a857d547f125966a1517941e8ba26c35bc1a5f7f9cbcfc331db5bc5c91af9b86ee5845d11d3d92ab9811611fcb0a899160fa1483c380c04fa9dc581d1b13105c3d7c76de820dbb032a569503019e741bb0a137678d4f0b93c77549632e3c4e0a7e20c7a44b5f48e6e6e0cbe9b3f3db3da88ae791316e23bb10a5a8273163bcfdf13edff87c13c0eb0987189aedc307a1d71887d85d4f78fdb6faf8169a918cb26cc22685b28d015b5bf7914bf9d9d7d57507e3c5598a7aeff0e3ae6a4b10c9463ad2d4e29a3e09e3256218ab1cbc533ea82dec2c11351ae2ed5d8fb93087ca61f6d22a8bf9000c3a574a3a6251106d8d059bd3f3a446d0b8a79abb6925f645bd283e4e04a3c0004a6514fb915a049a5f40f14d5b24b375ff54620046d7aedae1415e3724076dca4ffb3c0a813ad3c814e81211c041e46a7fdaaf1caa6490a541c09b74f7eeb7d8168b2e2d65920f4007c0eccf956f009fd89af64cf8434fdc9cee00faaefe05e1ecf988b4e4fe2db80cce6bacb7d854629bd7b43d98349a70b06847c4c9c3c190fd8cd47aa492d6af3a9ec4def10c1ffd4f53deca857c00856098b880a04e53e3d52f04e7c022b69e513b75e2f5d9210ff6fd0f0e6f284f5a2c57c092c0bc0709549c02ef8fa65de993954f1cf9e4a4106415ee408815ecfacbee2ae96df8d053842af409b58e0b9c608bd2bd9369447a987252e0b13e8d80b886facacab2e82c78ebaddf7d88436d767a6d5c5692ef52358b6c0cbe1ea3676abcf8ffe9359e9c89dfb3216ceb3e1ed9708c5ba846a5b651ef24037561366f7be0bd3f882f9efb3e4d290525d0fb4ceaedcece59991fbc569961829d4e203719d453e90406a1b9ea3b395d825e262f5384847520cdee856fa5218a366868abaf8730a3ac0de058016d06b2b810da3b815a0736b0fedceaf04e0dafb23cb4e4d21c62e927d0064c785e2361a7b7168660", .None}, + {.Lcm, "-4852b8402e7017a5a9c44d70381e85b435288770a53288ce664f643a10d53197efb0df518ebcd039adf28cb135f1b4c4bad6e40ca2cf28dd335fd7a4453120162ac5654a00e99c3e814d911b2bcf14a5b4c3665795d9eba201c28b529ad481e98300c027bf59bbb0a3a52be69e9d34e2391b310731e321ea9d30824584871bad61619e3c9637b9477bbf2a1c497c4b48452e5c72d5b1a2866ce4e58148b785723cae889b0a22a6c46f8033e0c1e96ac750adbdeb4b6c0184913fcd7c21aabde0942f7d8a27a9fb3ad371b8db9f234d7df02f9cbc5f4d72e78e13e689719922774c226068fe6959666e512488d8770d5c254849d3dca36428cf05e90f948fca020cf9f8ae885a25a78b8e7de06f1985daa2b6237d8cf2a61b579ad7d77a01e18f7df23bd7c73717faf1e5c45266237b84215e4240d367b730291b1af95f0411d3997e6e3d80992b689bebbe9384a0f0dfb582f86ca92a361c5ed40b5e8b1c9acb93365c1422da2499151c7dbde4c736cf05a59dfc0ff61424261ef2e73030d056fa8f26333bde42dac2742f3ebacd12b5bcee01e74d28864caf6ea73ba26f0e0daca60d37607d06bd041083955585562a1e8c654fe0fb3e6407f1382770536bd79a22d40c04cc2d611ed736de03d77757d02433245837ba54e2ee4e954a71b85a25a8b98bba164d82dec9d76bdb9b4ff19071eb81bf6a55fc229c5e7fb3e5843e", "-7cd6a54177d98e503c0da889c686a01fd1d9e703978d9145fed6123cf5bf9414331c6d4ab2b33ac33f6627df62e5c202ddd2888804cbf7f3d27129ad5d920a5f41c0efec2d2f6cde87c73cd30de033973a827f7ebf5b557f99fe8499f31f0db04484fbc9b6152d0dd4fdf547d1553a7ee8d6089a86d33dadf288e6afc86fd33fab6f3124ab88b99568bb153574ea439715e5e0d109fefebea6116ce2178f3a98f168e58217e160bff2cbd051c4bce06c61abb7866cdea798a12b5e7a818fe1169f39ae3959cb32ed63b0f966874afc3905abde11caa585cdd1f3363ea14b06f80b5aa203f5416327d7dc0054ccceb35e4b7ef675d746918a2ec09c3c98062d92c6fa57a7779da22d361f5df332f8afcf77851da814877e2f96d4313a1f75c64069f848c9b08a9543c5e64b879f815ce491036ee7de9a63a917924121d5d8245cf91be4d1b290bf336fc7f0f799cb6480dcc49870c9bbbe7ddce8f6fac72e832af5f993dab677c92170c7da12a7b5cd01f46ebe3f6e09f531d075210220b584d7569b2ac1bc2a007de06f72da203395a46615e4cc3dcee9775e1c7b7aef88b5b5eff3acd5ac09340dd88a87ad55b5722b821239e17ba933b063bdf1d5bba21f75990b46fc454dda4d6c1b56e83934851a780f849ed469217e80ef7ec5235f64a4b25cb78c47fc97d72a14ecbe81bb2db29857e64d29031dacf997cfc4e5259ee0", "5e0c8d8d1f5dce46f921ca6d81b6a0fd2957b696265da96f45f764f01fdfb0ab09ccb211444f0fb2277e87e2bf4d65b070575d6f45282a0280d52bb381e2fa7fe7789f38c8a2b260688550e8e62d92aa90a81b4461bd2374d0929cf823baa36b22eef25583de4ff881100d9fc2902cca17f08c4239d8a628706a75692a8e113d299b7b182e8da4579d88891fb433c96dddad2e6e4082fb2dc704af670ee891ece598486541fb6c2fba996784fcc1cefa66785e8e7f778963a0d2213a61277765141b14246ef48dabc03fe5430e43ab6524ae82d5c97b030658df9a70f71fa5707be23a4db49ef4402829d2e787dd0898ce4c4a1ca6f8ae1654e2a43601cd1e89d845638855a46f3e181e18e6eda58b30d456235d6fa099fb106f9e872f0cf3ddf847cebf66584782ffe91e8402fe2a26723edf488edaefa2224ddf0892ccc3f077c34631167b553b279e4e421edfb94b3c5acfba09e50e835ad1f6f40fa410478648377cae654c1e773db2abfbf72d01094064c6f0f7fa68b01226be7aba0249f330b6d57b2519dc9d4ce4174e73c0201fb4620b91505142b9adb6044f0179f5f67c909aa3992c951c737cb24c75b9eb24b750110451a60b32cad47b3b8fb8b03b98664a03900b9e82870eaee8d3993128cfbd8ea4d7ec48b1b49de13dcb4d35601897b7047e9ce6d0083a9d6a6d78697a2a51294ab0324ee4d09f4dbb67b1188904296fa56c530160eccaf51cff54522c9f4b96426f0bddc83ea2e8990f6a27387becc13b975406e56f94be5aa1a22ab1c6b7099ce0ab08df3ad1a1bb51f1bb275ce3e54e849efd29a3ae7714096049f2d3ebb33d0a28e157ff468e1393bdd7bde58d965d23ccd731f5c711c339da59915aa249eae6c10b3549d6c7b157abed54af7dbdb8e68f9969ebb1416225e08f2dca5c5c134caca0c655f57a7c51d0526db78de13cc3fa30ff70e0f31b3db17fefd5bb969647007e1e737c4406adc8990e567fb7c33375436471390543aae8ae5d35bb54d7166d6b5c0bcee29b02f981d0db27a8da6d553dca5ee91ea5804a12f53c25ea9730a195575c7d54d6a40bb489385996d2ff98f2dfe3de5b7b5f2ca05f05407b1cc5456916193bb58d2052f4354fbd5d975b87733e1231c4240892120bac5182927cc0f3206f5412aba554478c1b2add6dde40d0fd0e7c36dc98af5a72acdd96b1fb5ade302fd5bb91de259fe694baaf2b50807cfdcf550d2832545afd31f2c76cb5f732ba1971f0516c3229445bcf3702499e4f031850e651ce14fb21472dadca87a403b19cdf577acf87e89f7494e4a5522abad23bf5a8a56f07e203c445d523ddb8aa78651b8dc481639153acd6ba84c366813402e92e003fcf2131e2a2870e70d0a28998f8e0a289477cdc85d57516ed9252c0fd51c451cc358a60de8a3387a182b0d4ab2f370915460", .None}, + {.Lcm, "3648016b0a4e8341d4b47351df8acbc585e7e2eeabccc0425a883766243b0a63ee940f89226c62aacc83f7d730d950b4687b1c6e6c0d2b590af693f7c28269133b2899bc4403ad06e03923ddd0cd85ea04207d3e5dd85c8edfd80a7a19d2505923c69afc237c07fa63da3a04726b12e97027ff609216ebe821dbd025dbaa0db24998c25f7e8f3fe018e7d14790000528112bb17980d9477cca57baaddf0fc4ac89c728c2970ccda366761af1c707dc943d6f03684438c95b05ff3b96ebd33c4149142a763f625d7485327e8e97a319780481c2baaab886928a03362e08c81c442f85d2d7b4bcb955e4f390fbfd407efe0d7dd9066abd85d63d6dfba6f4530f42dc620f75b82af402eaede77989eb2c427d5e770db98ee6a58769a3d55f0e763cce232f6e7b924736c7e8b04706199147b0f5ba0279a258899f0e3db55fd70a628c691f93246964c4f2bf3022bf95ed74405e548bf8eaabfd8fb214119f0fcf616bf17c488dd4b0cdae793c67066178e82aee93e02fcbc2457b154d0022ccfb95abf518a5faa41055399c1ff0cbe608612ebdedf9479cf0f197960d1e911ceb5a2d2a2cf8c28c60397b4b2cef94855076829e7bfd3909f70e204b7346bdfc9eeaba1ed11fd20e8d05b25ceb6f853e3d42cd66bdc9ba8ca36c65c6fd809a8c1d7db7c467cf64b71d79942f5d9a3339afec9a9dbc0e94b1bf0f01a17c286e23b531", "-3ac6cf40734d76cb8f22075241dea7813e76b3704134b6e3042dc95bfe4bcdaecb290130ad83bf98ec1e32e925dfa23a0a32b0e750b83e827fa46c5890f8e5eacb98ed937e8b309c141f3d6dbf23d8f1803b01dec5fef9b7a6ff5435031244d75b731dba703882430ab030555ff02d50e7ede1c9aee00293948262a197d5136941f8bfde4faa62de39fa34b99948f75764b98ed93c76ae066688ae4ebab9c31ae3ba919172d80ab526d4d6da88300e3e354788a8c25c4d3b439c541bc671cf6f1a4d05ecb37d7c394bc45910a027a830f7d10700208fd8140a9702b4570c3137c051159a8a0e3e8347abd3e8a818b6a7eccaded4196074063b8fbf9f2e5ec76f5320a8dbb85aab9ea87d39725e4192b04c253aa785b5cb87ef92196ec58765140cf0c0f46023305674afa9a9155c0537f5a4d0e331ab43f4e262df871734a73957c390b84f30d250f2cc3ccd492607b39de48a7fd8626866cf5e10bef8a4946938b76cfb49436142bb1bfba3d17c81b7431bc4811e7ed714d4ccd2098ef2c1337cfc7df8f6d0cfeb8d2e792f45368b91b8178437bd26c4045052573875e615e51798bc3fb96885f02a448362d89209532b4ae41bff1ba666c043de6edb88b58a14d62680925bd7dc12c09a8bb465fa0b2aef6eb51580b21e010fa859335095da37a475bc93ade48dd44bfe0f6dd5a133a54c09fdb6ae8551595edc27495cb4a8", "c7677f53cb8700a5bcbb642a27bf0b3380f729b9fac819deafd3c4c4358e878706ca1f506267660417186b1e18779277b75dcdeb384161dd0ba8874cce645cb0d05cf6b636827e954f3e41eaf1df4da60904959542694da668cc51063bb8a6ee394ca9f8be6dd81b828ee74bbe881f98c591561ed070125950dfb222cd8cef87cbf40eb46c627a431f0ae31d2512ba874306029946062ef362631a2a3392fb98281067e327a146cc61eada5eddbcda27b9d1f4d791565eb76ceff9a5fdfde0a679684a85a842f33b393934c4aaaa8707426f4c2ab7f1f0ecc10f479572e0040e9bd72c7a371e00508606e533e2fab5b03d9abd892f99100c5b933fe042198480e7017a896a8a959409ecf05ab3c9082b7a11cd19657c6bc6096fcb334cb1ecf4e00cf43d0449177b8bbe87a137ce314ad58ca841c425444a02a323d30674d69cb1cd52c45ca2bed1a9bda8ea6142ccbcd79eb050053663aca762354bf28b96927c2354d54a18472bcd33fe4ccd640775287878c819d7272388d0d1d5630141f64ea9e0a233b2ebcd8ef95db4f694d14525f74707dd7b9c949cbf75d708a933e3d35ae55d9b58174e32d91835e45735aedf0110eaac50fcd69898c5099731ee382111632f9688e7f40040295c246f27b4b627f87fc504d1836f7783ad0cebd5e9291eec23175bcb11e384f58c62057d07b0d65f839bed59756291a6424f333f1f6e5807739c64064e2933b9a774dc52ced57b5a6a6da3610e2c6c0bd63f99ec9a291d2b59fb28e56e626afdb9f3b605fe2fa208776001ead7a4896cf4e7172bd0b0f76d000b27a10ab596d5569c35bd01d1db20544c2200c6d15cfe1def26b4344f828613370012e1f96a07835a1fba94cb7952cdcfc7494474a829ee294a8864ad94a4f86a9e146bec4016d9833cfe58c958d50994ba45ff61d010167d11f21a1b77af739803c2bf4a8aa58cc49da6d811882ecf41d36c1f5de5221ee92a4cb9f6e0305a05e908bfd27619cc48d68b8aff1514aeec05e820a840277580c64580cc1c316ffd2c0d4c6cd44bb001bb3648403fb32bfdf106cacfb640608b24cbcf70429e45a8df37b035ebbbaf33ad50a8919dfffa420ba89f53cffc8fc17cfe825956f807f31129b91be3386921988309bbf119bbe75d0e80c9dc6eb49b940a686a25ec80426afbd751d250fac41474963f4f040ac38c3e8628ab8d2ed66082042518d11edaa806faef0c0a77fc59aea7620e140def79c45f3678c381b34a5b27d758c44c3e3518bb61d1f144b4d447bbba1affab96379af7427fb887409ee7825133b0a24f95b7eac0dcacff99d59ccb11e1c2556be317728392b226c1eefb38a807a99d40db83d8556cd65511198015a009fff5fab0721b8c67b4998fbb57fdbd49fb8e4966594fca81cbc3f01d796e950db268f03ded9cb5a61f079715c28", .None}, + {.Lcm, "-27501d2895577e606dba0be4533ef372a186c757fc3278dcd46341e214c2ce7272d8fd2071a6cb46ea5621f35c67759d554d6a8dcc424f16a3e536950105404ad6f2b01c39c8abbb84b28d88de0aa0b8714431ed78eb7703abee63fa8550a130abeddbde46e27c4d508b9f3f646a44f02f547cf5507c6439c6639c4e5bba0db9cb2ec5a222e1b33ea563fd75134dcf6892d319d4266ef5faf4beafd5fc2710b56d201fc2cbf2d52a04e99095495c7dc25dffc32ffd5dec49e4e0d6ec7065980a799256ca87faa6e70335f89019a25e540e37c8e1363623d82182c5b4a7c7c6f854128899468870d0e7716754ab07954359dca7335ff9908ac97442213f447d29e07476514d696728440517d231f1803346af226ed8e4c0657bd5a501c0fb01c4f62658213cc4bdfb38826734a133e13893f315499a7cc394234a607fcbcadbc2b6d25c6ae6c49b2919cc91cf5dfa1a5f57c6e35e33e7f8f7bcffa40473ad64ed28064420abca77e26075f689bb27b4899a6cef5acc29e98142b7e59d863e2d9ea99cd73dcf2fb5d096fd5cea022bcb06fe57733c15e120e27e61c6021cee2b8abf9d09c0c5ea0e5ed12479f1aa3664a9e8b0baf3d781c877e1e84fdc6e1eb082270783314c1148919fbcd49db1d4c9cedb234071ca95d30cb37c3fb7c34502086957c748e82edc967677a104e072781da7931cb5c5eb9b75d3286a3253b2a8bb", "ccc0be7ff25df029af6ce0d561955a42e430e0c6ef0014962db9b4cf0e8fb3a10f575891f341f0224f496a99fecfce4393a1b247bd2908e4bbd159a26ef0cc5aa2f0a59efd1781a57ecbdbcc007eae69fccbd3db44fb324e0cafc9704528558bd9ec0741bf8edc639d2df11a45f81ecd48a8db4ca87893012c3a04048ec417e9d1205674d34b03fe85ba813bd6e610b8c0216c2f9e3f95f54febd9542b0e33df16b7f48f9cb324c037413ef0a3da80788034a13e50911f3f04b01ff2ecc8babbff997d296169f21f48789249f7a94a9767c1e41cb9b6697059c55b6c135dca880b3bb0a7ba06295e8fc7347ea1f906a98e41eda67b09e4b61d5f2f4bba9f8352d58e94b9dc945025fcf03d174fd6f4dab521a147e4f8a044dbe9daa93a3241e69294cf8b8a028979d5bf533baa80b11d6e67ae250604bf51408832ea3f2586c129c4b8af2c92c4170d542d9e5278265c34ef45de637644d58acf8d3e977c928f4d0fe942f75b40dfd07d1418dfabf1671777a048cf0f992c4bed33e3dc7627e21d9390f0064501978f4c3425d89162bdba8927f376d62bdd6758b7cf38bb719c76a7180afe3f77c4cc4d4f1a0176f97f179ba9269a85018fff8adf1d4b30a7b83a986e47420065650293de8837bf32029b48b54c8e01968843781b25474660085dff6faffd6043fe8aaae4f515912fbed4b9a10043da93e0edc3a7e7dc148788", "1f717093510c78d91cfbfa4d4d5135afef68d171bc56929c66ecb1623362578afb9897605714b304a10750c9abbe4a7710d556f853a5aaecb829e114c5ec0d356b1a2b07e3ad3b4d241ef435811664e752331b6fcd8f6eb10086442d865b5d46842e6a98f34e1bc42975c401bb322d16f176e9375a87fd45c19b92f5fe43d5da3b6f9c41b8349de336ea873828f98799d391c091ee577d54838383b3003386350ffa310666ea9fd22554f8ebd4c059bdaec11d1c47f2cfe80215ad7817edee3edbc46cdf37e38e5a1368aa16573ace757886c8a6e74df68649a9eb797d797762b80f40be6ab26873309d74f6af56da0238722f5380cb1b0171a37c585b316adf1716b279039ce5c64e049ad77dfa039964adfa0b1af01f59e412adcb28657c39bd852c6af7d03d3b2f0eb55c0e31edbf7c37d48a836c3c812026e20f6fd3e9a8fc2a9787970547e3b4fe742afa28872ec93dd30dc15b57a5c532f7f5ca9ffc0fad89abe5beea7a0cde7fb2ee820c635e3bb190fc577f58d3f3e201317a5f471d34ec8bf3e0c1863f4cc8b5386bfd0d660ca28eedefc6b3d9f32165adcd7af5b0baf26c6490d8cb30b3950e66d38d4082a22438578241a1219b99d42decd108789fa5332552004131ba3307f1725a311e5667ffcc84490772425660758fd1c7da50d4a4a9164bd4c555860a65e750e80827294316b9fa6ba79c25bbbc4c632b1b1c7133a5c2353f08f3730fdb72dd2c6be4f28f01c8ed320f29f4243cef2d1d0fe16809d9b5d98a5cd70f80182a37bb07a55126a2839880b937a229d99983e2d8d49c5a7cebe3195fc928cc79f770b37a362017d23e5ecb9d6905d6abaaf71f111a6c110744f5f0a2784c0467a1f12555eea5ffd3cfde8d99c35c963bd22366f8d344e3d16364f3b142da434e8a07e1802982f6dbc95f64cc0251ffd846e0064fcec34897da74d00838daf0b461dc96951ac2c1e735b84a364d58373196f1bc5190a4f92a5c00bf24bfd65c83bab1ff96befdaa26691da34971c59198fc3fcf4ff1671189f1c14490f30578e601ea4889a7f0bf4fedd8a19fed2908000bedecb5981dc27192356a7e2185ff9c77431c9c8fb05d47dfeaeabddd329d823d55948930f915bd98c8a80bdde7c2ceadc49b6307990d58acc961b53a734af43b8a1cdd1e7ce9d63f82b1f6b89911ac134bec1a227d089be57f2394575a82c2e602a4f76c867d5738462492c0a8746fab6261bb6e0666281eb050234454fb06b5f41b77ffac6930a6d8aa162dcf48ce15cb52e7e0f337c966f18ef4b62b97b08b4884aefe2aef284118c5989c9b6feabf509eab284f2cf7936a613a686517042f25e1b275822e9a39d46e1482128c2461974e63907138c55fb0ff532d27c67be4e9265ddce606f626a56d70a5fc9a8528a20ea2922fe781a0d6c74cc10e459290804058", .None}, + {.Lcm, "-de94fab37eb452e9de741a711d5c91e9adf9635bfdd4e155c19234e53eac4a3e2a8f06d847cf4fb484c7435a84983b7d585bb2bc4868dc592cd8fd12fe4377faea3ee2bc870a735dd8e11014f0b49bd639bb244c077f4bb11fc1dd959b5b493cb924d2e81a848e51d2354ab297bd476d0e52d8d918d021d4b6502569d239aadfe3c48847f5dc409fffa63fd314c3449f54768abd25bc900f2390c581682156d28310e3250acf54fed446db3f974012d30ff393e510fee74446f147e1e14133dfc9cd6ebfe53f2ae55878c01f5a2292376b6f679f2e3597b4ca48ff8f54ef987cc25a474b0fef8a8b6044aebc1edb084638e845dd5893d9fd62a338cf3bafd2112588f527afc652c5c24b7f50581b47d749c6071fdc793f0f06e2700f1cc314583aec8dd7785c35a1811944aff1ed5b3796a4f6f6085750570dbb2deccd75a61d0b075966f09929c1d08ad68256d19ca5e3adfffe0783f13160b548166d2366dcead54a8ba51a2cfb1872cb58a925d92f98e83507ab8fe57db4e6e13b073ae433d3254acec2a276fda6cbd74e84fcee39faaee45c25574312956e624379deef36187fa2b3a135b81888a92fb6afe3cce8cc3853acbd09c4d5eaba504a1b251951051d2f47f637b13e36305c744ec29358bffcbc6515902269c1c435a36d66bed5f550bbc54c08bc87c3e7b0ca0e6357cd8da72a7a346f05a2de6adefca563f021", "-71069db9c1707af007f5962397fdfa329d2513ae743dc727150e8c0b4311133213621d54f00f57605738fd0a7ba4799867a220c7f8c000f6436086893b37e6f80886a062a8c141075c99fda08d676418c5d564ca336e8b90116e071d019a4c98d575800f424bdaafe22f9f9224d6f455b3bf1830e5f86d26d4b551fe2a1dd71fd431d70bf9ec1faf5fbaaea9597723cf22e08b82c56382fdd189f039212d2ac49b1e5900a78aa93fc64ea8449efa5ce2609da4f14aa0488bc1a5fae3dfee03e42773846479afd00b972d73f19ca9df70127566d35c083a6f9ea38bbc0944cd5e492663db4a586ceb060eeda451161ff81f06f3a1e66e483e99c77aeb512409999868cab2bd659eba2729cac13a0ff424fcae80b5c246e8dccee74c01b92a02fd55cc4c18ee1a4fc9c6701749d3af39bf5f12dcf6e6ac31ca795b1cba21ba4ee1e36a0ea636e6fe2f7ccaedc6c12944e89efd3e789a740aee9900cfebe6fa4274f82d84411faeababb12ffa49329473029dc59cbfc4b8824ec794dfef81b43662ccbe13af490c0d4573cd9180c3fabf6ee0c1fbf5617a91fc9b3dc82d9b9bdbfdeb16b3864738b8d4959ac18d23bd15d5b2ea6ce6a3a3d4301cad3f1530a987796140666322929a93e68ac5ece7ac4632e99f40000547712ff33dd64975691b991a6e58bb52a51fccc73b1444efde673ceec269384f551304d581b54c6fa65f68", "62458349fabbee5106f35cdbe5fc6797248b1f44e19bb2ada36b08983cae41329775f1a5575655ad2d413a60ce17b4abef5ed7b0dafc892be6460916498eae725d2d5f30ae9262fbc3d7f45879804b59f59d0d78d323c164ef525de05b9db98c547439c2fd71f0d7c936e7df3eb00b7f8c1a1d8012889fa21b0843752096f77c7e547fe56bce81c2f0b479b8710ea7dfd70d045b75c7e84aa5c1f9cfab47b45ba876f0cd13c803769be06cfd68e361e0a2b42a92105d080f86f72498c713cd3f7963c1b2f78fa08a017e0c2b8275408eb0c1bdf58322b8cd4e3fea9823ba8ca7cc965ec93ac6bf21153d7d9921d72fc0e09028ade74c20e738f7d3f0fe3b718f15f3c1c63d70745e7646c26a98f39dc1e51e1f7b6c023470b7dae4fe4a46a208bb73b948ad1d678aaa6883f3e9b45b93be548066b1feefda6b93eab647988ce748e509c31be1a37a8488cd5fa4665186db0e0edbcf589ba67729597f0545a10d4d8bad0e3729ad541d3446be37f3bbfa1da1a1598289ce753e577d287347c1d0fc2e653b2850d82aef2e1f8ded8ff0ea1160ae29106cd5841b765a790b636555eba5b1b8bb676ec656dd63120bf606d41aba5709ea8ad8ba28c54fbd42b73e2d3a44651dab4d468a99e874cec9cdc587a8417fe44adfe630c39429cc28a22d2997c4ce27df528a1de7c691a7c2c9cef051ad9dccc737c0fabea0382e8ae0734495559a7b6ddf8a0e770161cee26fa99c5a9bf2b87e78bd5bb2849e139c2d61e9809616a17af7541ae929293075da0c23fe234e58e0dcd7b8c068617bbb7b0fc5e439facbf89316a6a050a0b7974ec781c4828e08ab0c4f2801deee2376c6b07a9a6053bddf7f599129086c1a6b1a2ad96bd4b895826a927ba45c84bc70cb82bdf8efff9f023072e1b95f7fb98732afed91f25c8b457fc317cc002e2ea341bb37dfe2ec4f2fd0d0f1a07417e5bb80b99ee3f32460b2866a46f81d3eec494098911b197592aa771d5f72605814f9b879fd67b9e377ff3b7b7064aa09b9d217c9bf84cee5ffec59f3d2f31092e40d48d733a4c10363293ebbe72c578c3a16720e337d92912c3a801d201dd7feeb2cfa53500ffc13d98a5fd3783eafc252b35513b15f26b578da304e681b10754aef2a1ce4bbf8a5d829df3330e5e86524ba8d1e906fc3412747274c00d1fc90d4252140fb260a6fe91e49338ec2695b3257fc6a510f2205dde63cfcc2bdda1798abefbeac8bac2ca77c4b60778f70f0559802a1ea161583c1b8b8a5b66618356f4686203e591948b817e91baeca33a84a90dbc5829a5517b58ba0981ee41d0ac60e890ed392f4b63038d3b5853393c20a6e0efdd84a9bc433f8a38b61b94802bd47f756db0a4d9ead2caa2864f8d6e52f56375946e46cf4a74f31f381d37f6b97a9184e09c23a9f41dae3d04c5fc78abb4b1bcc68", .None}, + {.Lcm, "3cc92376c9032726f0ba7224b6ca01c0ace9a2d208dda70416570b991c8e32f0f2b2e28ee9db4e49dee25ab42d3f3e9b05defdd4e2106e872ba3945264e5c9d1084e7ea0dc57c7b98b29e740e2f368eb94f065e16582a2e36f6e64ce788e1b4646f5dacdd10a7cdfd002cf02c3f790d77ec45964d1f51b7a95e88b254bfbbb8e090863b8cef25b47f33a0a6a9d409d960354de5de4e029daa0d0c2039063872ba7a4effc8c536ad3f7dd5f28886ab73ff18f5e92ed83fd7ab7a5df78200699060f7ec507c328c50e2d44b450060830b638df081813b19234d230b4a1fab7ff7181f2b6dafbd0688a08189300e70198f4727b1bb8b3d51eddb18e1d4dd496e72ab061ccda97f7f70b7d37071d78c1ac61841b7c14da0809281346e260f74c0cdcd81bb15f2cec5963abdc8f0703047a835f8d37836e03968047c43dd8a21fab5c3e4da9a591907374310ff53d0adfb0e50c0248ec4a69814dbbbc87c5b9e511430920b0b52b00f204c647bf569625f9d3f4d7f4be4d992ced058add02ed8a3786ca6ba4e6d8701b53c74fa35294914639d84a7c16d837094c7edea8508e56c2f38667c0d46e4befd897acd0a94b705158eb98a3433616de63576a9e6bc78feaefd8c4fa54bdb2433bd54f35ed55a89ce814fedd117b8aff143ac0a4ca1854aade9825966e3b7d65525fe62811e82d34230c73e38f1c1bb762cb527493bc4ad64c", "-35a182d32707e17ff022c0dd1069b694db6c691a4491567a29acc2cf4af23b9bc3b4b3f2548fa9d68b1fcdc302a80c20683ac51998219d866b783647e4434d7b515fb0a52a803e76f86271a1235403ada6ee88b53301b6423fd9b3c761f870f85f177f8fa794683b7fa76cec085c1f214cadc735b10422561ad52e254ee3e0d16fc297f5fa4ec3ad47c6be76788f031684611f01a0ed46b995f0e9f25b61c2d8af48c68fb07a952fd8d9ce4b47711d488be8228ed7ece7f6490328c8f0077b61856b7f60a140c5169e7422d3d4cbad6d38d79c3ff4c7bc2e1e9357d2255a1b71a346cf136f51a14b752c8207ffcc265a0f2fccf1cc809d51e1c6945209bdb18d1a44a17c60b8b44d6c1f0e3a01c5876af948afc9b802975ad94458fec028c3170c36b4747b04a3a569999db41ab3f99282713c00bf8da2294ebef67e678cd614e60796f90424bd212f240972c9ce068044df255d1ecbb593c4b64ed03e8ec4c38e89f30cccfd29c0a664d1798970d2d9aaf690605cf8ce45e0e7f26cd2fcf696e76b6e68e2f9ae75f33ad4c0e1a451436d0ac0525084ec67cda173a6e38c10acb10df7846d3cb58a03a0887a6633d1f1bed6a6a00e9dde598664e1fe7ece560c69cad8fcf0f8e35e6628e6448f96ae00f0ddb57361b3bee2643c2b63667c3d150b8c4b410784819750167f6567714dee9feb9fdac5d78e1dfdf5917e996267c6", "65dfef39630914218536a5131d2152f136c9f29142c870a0a59d0c9b8c85af01911130682af17328976581d9f20f479ea681ee2c91a33136577bf0a7782b1496ca3c6fc254d75c9799f203e607fe97a55da7e5b72cf083e3fe53d8d298c0afe9a0f91c9cad6f8b85290ec1fbb4b1aca6134043dbaa5290b7afaae5dc62e284ee9a8c9b1e752296ee9d4786e9ef98c52cb4747c6933cd716bd612a38ec89b9cdcea1f4a89c685acff6c6be29ff866528aef7cf5f761ef72be2d91145515b111052a9f664246260755309d0d956e23fa572d70724a005f0ce02c24be188c1239e0127c5b76fba663f8d4d6849e9b847b4078aea81483c0056edc2ca9a7ca82348c6490cf2f36ad20a28ea4a2c2dbd31152a5c4eafdb3041c193c40ae38f2fd0e4adc658aaae6af1a7e07fec8c14e1bda9b35fb13a6e5515c78931b1faf3b579b560868c3d313b4640ef274fa94e1ded83fc5002c816b058b44da07fd039cc3c52c082e0856bbb259c8f61825cde7ff0b2709f093430444e6011f134cf67e28d8251a4a70e2d297a6e1b46cf7f87d8672d61820e80a26603bdcb9b0a40529721bbd65e6fbe9f0a809e2b34080200fe435e3432a809ebe21c511f97ebfcaf6a7d4bf3babcb97923a5c8e85b6db9e478f334e7a985315828d05472c10cc409a261af52da0d51fc39813880f0935ac0954e7811927321a27b440de7a541102fdd48ebc5b99acc1ba5234c9ead21a939e70251b4ccfc4f801e88a189ecba1c415d4b4eca6399be36d3cad410d47b811077db2fa0205889d45f41ef8b8474850784efd765caa35c809f200e2d3c9d99f7ec4a40c649695c1cca7924a08fb1e4cfedf07e286b598b276165a3ac0c1afcfaf0f8ddc6366489757502a172677732259640e2b4ba134827b04dc7da54ef392d8959248751896661fa7da8458bd3e9b642cfa666d4683da472952ef061effa4003a4cb0790eda28e27fc6095c660c74cef068ff8f3e669ce8a47957f9e801cc48a91dc0c2e15a272cefb512fef454f5e4d9d1decb626a98a20c2af3ab146062a88c19996a64fc352289b1d298ad1f2d24d08d103fd353ca54e118fafd111ae5c0a1a25e8ae5489ded9ab534c826b5f1ca04a358dfc891cfe0312155ffea2a38cbe6c6851ac0df1c00b835ac17c6c358c682f03bdd84cf7ab701e705088458f51d7fdb47ecf5091b1248428e13422581a8b9c62d95e03b8e402fb8f56868157a977e69d8e5b049e5c663fa21aa7b358b2366391d07d505b04f4eb8091a441f047467d2498b1f5f1992bd79b6d6f3f2a7bcb43b67c88a58088d6c2adb8b0c895d1a087464705c63d80a093ad426324f5913141bd858ae7cb0239b9d60ccb4c5faf89e090e52011957380734d5977bf640033e9ae8a416529b3d16e56290ae8e20dc384ded7abe26364e8aceacedb779399992964", .None}, + {.Lcm, "-c838bb1cc176c6a5e769349bda2051ce9ae79bdde63e03e03a708a94c877baa31920f1090833560c9e7423fe442a9e08c5d746bb0015a0b1dbaa31e9fee054ad5c92c1c58e7b01e690b0461d30e7ea65915889fcac684e5958ca05aee3f6b1a04711f1efe6005694177b34a734390f6237007aa5d238deeb9494c01eb40b307bafccfcba605bc6cd183560d82799dcec89ac367937ddf1ce674d39e20050809a6cfc7d7ae067f7ad914dd7a74cf49243d536d9f2ee559faa00431b5d96530fff4ad35f664f4e72dc627229241dd22729a49d162d9d809e2f21d7c31a05f80456a6653cc3a28d38c7414587b5746bae4737ea2d5ebfccc097b26b41dd46d4db2488a084dd124d0a97ca9d4f4cedf633532a78a048133b462a1b9736ba63915509b7180d15eedd3ef19492afdf1988d1dab6fa69128df369b2f8b2ac3ef2c9ea0a4794ab4fdc67b6525381d1ae9b43ebf2396585c08ea934163510d0d13b9a2831593a0ab31843ddfab71ef6dd3283abf092f64f94bb6cfcd6ec8d178b2a5bcf8df57c991936647d2115f4f09de3ca9df83dca94146c781c0d7d69c6b8f1473aad2a7397d2889e9fb79ff590b32ea3f353676050a1a30828e5a824257dff512031162c29f5564666183d81e5e4bd90d41a5ab41b6863d69630d2115289a8d03f087a60f494ae795972b87ab261df4b4e9ccf226fd7f18b362b81ee7dbb0a1dda25", "-d8a6398a411db776e1ce4e92cd6e10a4f07f21cef4efe1d6500f7d803a5651ddcec7b83381eada067c46512772c13c5ae2a9dc2e1e8f9539b7b5e8d18d7e96c322805c7339232587326d07cdc56147f861a47a40766f8129cca2d16c8b15b381baedd8e6c9ac637888efa09148f7f42002362018314591767dbcb1b7b47d1bacc383c94dc60e46aed2dfa8e94f337ed1f71108a6d6e20867578cd2cee39364d24582b5f5881660f44513c93c0a28cefdcec784571f6afefe91946b4c404f30bd45f1ecafa58d9ed93ab6f35716ee4f5f59625f8e72a8fb8213cb593eb03794dacd01f44c9c912d2486782afa67da0540f7051175adb72c457409aca9884b75f52c0f1158f69dec2d2740a3939c5bc9662f0768c403e6f8280731922e57b6ccceee561bcbac7cab6c04a8fab885450ca17e5927eb0f70c98c5f02b0672eeb4b3b96fd125b9eb3f0c88f0a727d86732abcdd313872621774e571d5f4add59af3e68b1dfaa3fdb29b8a79712bb1bba00ad900d2dd3b99a9a4a453b3eaec5d751f6502361347a04b39c3afab684ca6e5a10fa133357b0dffb2885586afd5efcbbec1084cda8d2242a56cb082e1b966639bceecdfa637b99de380a3570b7e3ce9ebe2eaf49f16ca8a25d5d530871ef855a97243713cc9831bfce985844e28d3879af8e184b067527ff095f8d1b5e63c1fcce14cef9c4e365705ce8cd8e30c035a274", "a971dfaa5b0d94a18efaf0916f0aea7ab70396679e0ed2a522070e0721f548748d9c230a2b84cc1afac2bbc23f8c54021b1e17a37c4cb8470b3c8251e223b2b0a6e741b8cac60219877c2886bbe021655cf3fdd4a50779f40e1bf07cd80839d34fcc9f1b6104f7a534d6024b7921b5bfb63ea7dfc85f9366a417835b1094bdc94118c1d7ddbafa7f8bd04aab86bbe0a18cdee25a8b5a82ad1fdd4a103e0fdf2b9018241faf6ff8d94b8baaa3c1979bff1bda4a359f19f449ce2c70ee52d6f64b718b46141aaf71e3a55b36718b999a74a6cc9da1755433e6df8668cb0f01780dbf7bd9785e5131cd116d2d8e3dd289029b24c30d114173ce3b6dd1eaabd3ec392839aa6510900202d992cc20a76b3b4e3038b6896ab9bbf1c9edb20e0ea8011af8d761bc03cdb0c66d2d7e0ba5f9d6329cca95588d0a899211bda4d1065478cae7ed8705335a7ef3a05f94ab2e4d2da4a0f357a0407e72d37b643f462baea8835cfcea7c7572425c9d58bc30a7049262dd8ac36d7dac18b30ff0f77c31c1497544a1136c04828512bac22bd3218f9ce8130df891a5bb1bb4e0b65094fc0b7d40783d757dc7f6e663a0965fb1bfe68c8b019582354b7e385e419f9cd3ca753b9544a9bb2d45706bb36e328bd7e5025b43ca4ef6187caec8791bcc25259433ef5463d51a72ab622427f51af7a569ff7788b94acde28dbefd4215dba51b31b83028ca873c4a541ef831c3d252f71221691eff24a37d08320ddfc56ee964a55e867294ceeb58e97405ae62ae523c14a64805ef6fd769cb5a028eccc36133ba86a4ce0110e910d71de9c8f172922fa5dbae5c010952468ef4e3340ccf2593b6e7d593e51eae572ee829bd559b3be1a5190f07e0939e9bc2ff6022b7f5f7620bf45a377afbb9a0e1417fbafe632b28cda4a6e0b3089e28c018ca69154ce53e09b09bce90d3c10dcf161bd4c90387d9471fe00d1d76d411703343dd34ff4a4f2d77f27e1365fbb640bef2a32b19fc8a808760a4d08bf4b0699e725187a73b4679fd323eee26781cd2eb22671fe1af5695d0c2c9350a84d0b9f2b7b31c70e2631e1ee10f13dbe4c04c6d72c5c1272a3462c1cf79693eca528a4e055877b57fb7ea6c103e79d1b701b0fc6f6042d957749b3a5485786af2e057fc843c2b62329b0fb9592fed6a2b8176b34a9f5adfc972e553605bc089eab20c780b2fc7e08109d42530e4473774631fae3d01dc25d61d86ad4269d4a86c0fb20182a9870d49ace7a93479c89347a526893a4f8ee509c07819c1df2f7eb72191c07aa48f1cdfe36a25771144d44d9ae2a49400e207579b1ef70b365410397000b15724b92706036e19130618b7bed568e0f5a644a9a81ac230b09dac7d00bfc49215ded8b7e359a67c818e9d82ae5a124d4b3e44a1f031bf2c21fc745b27bcbfbe82fc72b3de1633b42c4", .None}, + {.Lcm, "791707e1cecf444813a18001e39bdf733ad794693abb07512dbb557d1ee560d8ae97e1f22834b77db70a23b17b344ffc031655b1e09159281ea9db22d6d71a53028cdbae09163d2828c33950ebfef0c9f286bf88f908238d82c2f9001510751096f350a214110a4cfdc5082c7500490141e3aabbaab9c9ec008d68cce6277251558b7576a6e45159ac06c776790a5f54b88ebd5c37bcadc8cd5b1b73f30dc5244d27cf451adccca7c31b97640fe2f05c12dc0b721d87f23f722cf83a4debec3a41b1ace2322621eca202bb3fe61c52f16304a8f6c2fbf90d4fec8986f1b67c07e6d1d05cc3d9841d416b8751cb394a8d6cc6108318f18c5b5e8128489d71f3935ec9de65b5f8f562a3cab3f69a7d6ad8968af2a844172fe17c9aa7391dc6031b76d8f5b7dd103cc303ee8a46ff6f3e18233cdfa7555c52c079032e4c5949b03d9bb5bec1b919b31ea0d6df162ec777ade7b44dace3a146905078dde2c9799fe5c1043ff72ecf2365224b2b9f14403f996c9bb00f4a62c37d5ac2407d97e309a07b973e19f7397b971eb7741a8a503e132b10bd82c733e2202496a029a2775dc0edb87021dbea5156e3494f401742ec119f739f3f43523ece98ed0e236892f09e011dde3aca2d99cd3547f74b7e751fa1febcad34be63df52c97902fedb49ddc9c33acef1f4ab8fc20247ad934be59968f47116c4839cc722f68b57a3f315d5f4", "8d8f45a28c07e9d6b0e5eec866e9ed8508f51d85330035a2a5fb8ee574c6ad7bda16aca52e09f5bca11fb8b37ce4546519311b1e6b587cb1200c8e11f3a102a1bc307cc0cc1d442c372b9e4b74a872fa7632327fe732755e9e7ec8277c8c02850ff523210eb8778a1d62d489a3c3af9ec44b22fad9962452d9b0df402c1c0d634a9069cd73446e435c42dde9a6994ab0b62225e3b600858801ade61157cdcfaab28b761fa1289de047b5b2a36673a208a6e5a16169f169b318500b94f5a90cee4ddd167a6520853da7414d3f2b64439677e30536f84550e7d5e26a494e40b4a41ccdf7c3ebb49550d76990501031fe4ebdda1dd65099357d60771841b4edae6ea61f9e92a9be725b6746526bd8e55f916263153562c88bcf1d6af05f8da61ef3180314a6619241a1f6733bc7db1d45e6a4ef78c55f8c35b53df9d12721375165c9cbdb077fa647c62e842f0c4ae1dd36db6d6fcd17c439eee5e340c5412474e4274f594843feffbe463fb35b5b6b6df7bcd50db119f6cf6ac95b162b7a0f257017570fa94d538f81639fea410590c89ca4eb769e9edc6b4f0500028e1c5a84fba12b663c672140f5722e69e2eaff27d4733dc8032455352f004355557458c63155ebc04cfc135f301164fbb6dbb3ab2fe95dd1f72fa08879ee6ba29b110d262f38a648fbda8381a4a79414d0170a85f089b5d10348bc844e4fa38d0d9a6b1c91", "42f57424ddf9de91cb034295cd6873b48d79d20d27c5f9c965ef5bf5213e07a41bb28444b792ad62dbec858686c1a47f1f33d2220f883fe50d4587555aae35fddb551957e63868de88c5700f9911384f1cecb05a7f27c11ab20322ac96f74c95eefdf979b32b841257bf440e65267f761da89a7e5eb1db04122bb59e3160765023cf63a8187dc6deaf0613bb1d0b3a7b99d69b168e3bd5b6f23f70b4bb035c833ddb3f5ed17aadbcb3b125b3c275df035d757153df48ab14ff29724d9ad2336b78b7c49e8c955c58281535ab2fb6733799419ff85dae7e89a7ec4c3413c7dc3d28b2045cb616fa3b3a3a11017ef39aaafe213577a460fd66899681b27e40830341d800b58fd357ccfdeeefaf655e89f2d43c2eafa4203c7bcd2320ea85fbd25548a3f8dec931b1516339074e5744fcd5cb71d860947be0709a1f04ac44ebf2be3d331cd75df08a1bc35f0745ba4ca7b8e875b5cc24e7f426e0ae568d54bb09cce856df04b4be2f88762d185146a64f540e528f46f65e5c1de0bd0c2c31c1390a28ab7ec5c52c2b4e8b00c72c60ca99e597c852884a09d1924a6dccd347de4d9a6fa141d9e3c6f6c1f76566ff454aea0f4d29afea39ae672b436c78b9b945e870d3a36edb7ce5519e942a47f0584f576e427dc6460a445cff9c4f54b63aaf84ba4f34aa3b049eda525b0b4a9c60571420c0134fd4792e610ebbb9e29a5b36c757a89cf5b9bfc336a54200983a5d49fbcbd8a45410c482a0f9752e3243da85acbe35b8d633a14dfd4373e813b8aa54d56c9329abb6d924ab7aaafac00cc3e7e9de34f7b7b322c8132197d64b846018c5de82d75d7c2f0c8ca64476e4b603775aec5d69ba32b2910a42656dfc5784f77b36afc75314e63f4a187d38846a3aa167ab7ce274fa672be51ebd8b372ca4d37012007f46d47324f73361ec1d7a8cce373823d5bf7993b16936268a7098e21a4ffa3844216c9e105b43736f739df2f2331be9ada778e904beda74e38645a89464d6c3fa723bec73cce15a946c8df98f508ef58c17ba389d594f23515650eb261b576e11385d8f91c8358a896f38c6fbd7194598da72c92e7437bb9d962651e07735ab7e8271e15cfc1987cb8b1cfd54b4ea9fc73d085faea02b1516f5228cde931a3d364dbf500ae8440817522e3c03eed97368ceac07d2637f7f39ac0c972915bf70597d712f94fe3dee02589cd13b008d71f32336b9161e6d9d230376d21d177f6f05e0b9bb6e45a2fa73917e82b85ab0ffefaba4374efff6a272dbc1d2c96185bc279f0456fa583371e594c99cc49a41bc77c0ac58ab629db3b8c3639b5c86f887f6526f7bd5352fbf6a33e63806cb0ff9ce69ae6b228fd65302902cbbd4e1436bb88ec937f9d6b0a2fa23fd89e5e200afa8a1286e037cdb3fbfdf491492deb622b2aab8b16ac137099390ac47c0df34", .None}, + {.Lcm, "3f0bb33419528fcfedb7e0b823a21e0fcbfdd4fc3900279843f1328e60e3d3938a1951184034614d930d15702f8dce20f2c89b80c03421265d7328d60bebfd8ee7d646daf1e9ad7efaaf2108e2dcfcde5d3a77cfa6bfd687f3e63614fec450f3d675132792d27a067693d31075cccd0ef430cfcd37f80c7194a69ca692ec19c87d7dacc819c3c4b9578207e1fe9351124e24684d088ce49a1d36f76cb71c7e03df14cb02ff48d0f2c4d1692fa9b98f0e9ab422728bfe45956e7a3d86ebe3afd851ed7e025c6d48b6449fb2b1b09babc4a04962e0c1a84e0acbdb11df4554ae906ffe6715cadb618dccdc1e92641f3c305311d8a658fe5ba4b49e8c76c57a81e98b736d206e39c9495a560a5581582fca52e0ae8d14590fcb8302cea4a419309bc4ea0a8621307a19c10395b81b29569ef9fe6d31b2cce8e117d355825b9d30110b4fb9ae1d97fcbbb6f2ca49e847271824aa74435c8099548c56f144f90788c63fa552e3951f3600e0486f7909ae435f9d6b93d82edfd649b86aadf6c2ce5303c39081519a3ddf96a9634709111cad9d0b79e69d400c2887a1672f1923a38d108c03423fe13d254ead27afe7cb97acce8d4af5e0ebb16a6686c01c37c33100ecca198165a7e3e40a7794077441a3721a43e8400f63bf1467f1f17196bd6554c3e9d368afca826a68a6de2d5e078bd1a47f75be42aca7513307362f8a3bc22886", "5162768894c8e6cf62b1fc52e3f5b88588fdecac27f936bc9c50a5d01523f3f6c0f32d169e8458811dba11e3068fe68b3d7051b04f7f51b9953b3133103088b1f15193fafd26cec40a468a0a92391680c17efd98b97feb2516c053fae9e45be01fb0eff83ba8fb55c7475679cf64f11c40f0ae9cb47c2d477dc04e4b9b3ca726fc08ccfa2dd151d5f6e1aaa9670118d22abaee1fadb71f0f5b8f20194d6f17d61b408c28e9928003b641a8f9df98cfe21a135d2852206ce8c39fd53471d722197728e77c8a2d226783319739f5eb47755358e6bb9e3c476016f9cc38bb1e21e68241038a681ac077a29a9b10cb921b8dca51b67c797180f94e02efd6921e597ed26f40a22ba203df21950658f6dfd3027b77c2d46443b137ba69b10f07afacc0807709f68244d0b51a7eb11250d9524545fff7b428268da7d375cecb5f0b3d4dfd9a65d098228674473452e09cb8ed34838349725505924bd4f299059541454c4de721036c8b200c9c2d66522ad552459278217de9122ea5a2aff3155ff0383357f7b06827a2377e6db9a6bf766d9d730276bd942b824d1682fcbc54b9cb4b5549406d27816f1ee7763a843710789e4df97e858e03f7fcc029f97e74af176cd7f7ebc6958d7adca16a95c5a9d18d9b9e155cb4b7f21d24a0858732240a2dffb1d450f8757a2a30dba5086f9bec5d0052963bbc8e7230766feacc3422d4ac9b9a", "a0579af8eb5230587897af0a97080320128ccc522f782cfcdb006937841201a94721778c4381d652fc627f44303f7fcc4033eaf4ef1f32bbbaa549ebe26110dfd009b3ca00d98ed37e1776f74d00fcac8d9853ac217cf8766618badb448f086bf8e1d54e705e78cab929b9df7cdf12a9939a44f99ca43f78a4c39b7ab7b7a350a702626622a844aee00f0270a63a877822ef3d3b5523bc5c91482efef28c54aa9ba2d45eee767413ee822cc635071b327a9094b26a8dc0171c26124f9245d591b42ad886b2e2b9839805adfe743f83cee11d903fae7cd0cf5640aab8900cbf70fd78e2f5d41fe837c5a0ec6d6bd9ae51755410c06712cfc42f38a7ef9f937d317297a6d63d23ae9293d4d7c7b98f7eedab756124a6994d429b14e79b768f4b0c674f37123e5e90e8ad60903d3f4c2fb3eceb179d0bdbd0772e8904a7224ba262e340b70d9e020861b1514ee76ed76d7d6b5fcaf9734b4c8219870d3cc09962b387ccc4059196d848ac7b1b540e98dd5e2cb780d2ba7fdbcdc576e3903e1b81195e2a5821233cf68659a0c7cce5d4eaf10dbf3bd3502a3ca18d4053f7290e3fd9b2da2ca1c3a088ab9b1011e786aa5dd255d1b8489dfb78edd3db53d409a5d3a6d0d52093544b5f6d4ce820a1e7fc116fcd69c58e53016b123d6b0ab4447c243eb5c046b95f9ac4581eda6263a7f33e36b1ba5c309926bf52562c3a23eac022526bdc4dedd9785c54c48f31368c8ed803bf0d0a90e8ec831bd5110f7e9e80f7edf64ac2d2b3c1ebc90f05aa3ef58e77c8a11c96ca1d4cdafd855ca1ab46489bb9939bea2aa1f5a8dfc176abdb75ef3c40557c1f5162d1d6b573c3c1d4f5f3178be56a86b0643c494a2cb0ae96321ecdb8b55d67b2722e77548db02bec18899403d15c8162fcc72ee8f3f0b7086cc2a46fefc40566845d226cc2c885e5237401d88f2e1b598b592e7041b5bd60ccf7f6cd7d840b3635646c226b21147641f45612a6cb1261e36cf64e035672eefa7b7a8e6bebf53a45db3b2e30fbceabedfa50a4d1664b32fcc7f80226dca44027c0176852fb962357d9a1a778920b4b8762d48624de6e8483e628d65a902465fedf71e386c08c436c216748c31fe4dabdb126d21fe68bd87063982706c22a4a21e82881a694bbfcd10f9a49642bed2fc43fc20c772d2f6a7ee70c78e6e0da27977a1eaa21f4d70a6dd4ff8f9f5d93a2c73a31a60ebe3b54508bb812fb3a4ce015a09a02b71b9b4d208cfcbfe8c9a5a847b96911cdbe4986fc5ba0b283ecea1eaafc55b2e7da67340c5040922b9fc09730047d39f96b9685534c05d962c72d1721c64955193df9124e04a8473f9d1bfd02512782c3a07fd908c7e6d1750af8b38c461667a4352e246951eb4899e18214d2438738adcd5760288f3fc9fea90b6dfe86683b80658386dd8a4195b456a9259aec14e", .None}, + {.Lcm, "-845c41cfe9ab1c3e40c8628055518793ed65310282c439e18e4662e3464e6142ae909a13cd00384ec9a94bfd528482f37823c8efbed923c3ebd437749a0058f2976a21f9611d9b175657b7660c341febbbba3e24bcb1c1517a957e8e190e19d4219c74475cc9815dbbd3d6eb76d796515d269f16cb0bd8a8bdb9f75c652ad40e1bacc9344ed64394ec9532dabff383c1cc948634eb7ee2fc1739dd7d7aacc137fee3957afd1157d0f6b3ca96d7f75d1a2d4c9e616990e1d71a94515edfa4973c5e66aa7739c29bbca6cef3af077204d048e296f596224c5a56582fc2fefc58599f1c8ae62f1f4adfd3a365cebbf9880c49e93275e031fec2d0e7cbf4348a389ac93e4d37c976b3f3ced1aea4fbf6a0431de72d168d014bb440c24dbb465e991caa02a9aaaeca4351730cf2679bf656796fef8d31529534bf039590e2c90ba6df4b4af8eba626d3e8258e2beafc1f9385581c6b469b1cd687323f6a116c0b1033d26be716d6c51c67db80989aad67fae63da13fbea497a7331bb56e8867cea5cb09001a6ac163d2653358b6321d0c565bd485aa4864550131e5145421aca138830e1d9aa7ae83b75c98dbfe0b06e9445c1b8f4930438330f328c722cef45569cd418270847f8d7541e57f5f87a309c7a2b9355a7e114874eb558c0ab7b8db7d5eb8f2e1106e2a5f8f9a412b07a93abeb233215f2c5f2a0944f62962e017da5cf7", "e08e998a07336ced025e9385a3204db67226769658ca4cc0f45c7ba2dbe365d35d72ed20ccfa36d9e21d0d76845e7eb389287e024f41d1b6bab2b303c64619b3201a609f0cd9cea12af75706315538e0aa28a1181901efad51ee836079b8d9623cb80b235f3fa1bd3d610e9b1404013377f8794a3875fad46486728d3b2339c6af59930f05e33e66d47b86bf9482e4dc0264fad87842666285fcf2d111bdae576df6de2ac7bdd89eae4a453e50615dea55b04e236cb87ff273ba6ec7deef50f13dc8746c4139e261b92a42565a79168aaae72411af4c184a6d3ac7e0f891f910e58efa79597d897b4fba73269655457e449a2a5da72a03d1af7c32d3daad5c5e16d5904e35448783584a36766117ecc43b1c8a882a5360b2e87ff8f9047de164e2d45f5ce9a760fa81ccfdf208d16a03176db9d37ab87cea595965c4b062fc25bd06eedc77400948d4233df7effa48d844e3fe637e706908e48df0f941a846713759a3586c92d5e0f6a1465b25423a415570f3b0843c52bbdd24e9e304bef82c5639e19e3f3a1964d35b4e743114ea6c0b83677d2cae4a4c7db52fe96fe251cc9f4d5a85fc7c89eca29eba4538c8af9c9df631b841c4e00c858791d1200ea0f3ac9018c0e091dafab9dadfffa21b59db9c2286fb24d3e43d4323d89e3823ff295fda9ef657c093127f71c81ab55f72c404d9913970cf3855438948d4a00109b7", "26b37c0c4f8664f38a83bb111ad1ce2766752aafd80bae75680557c0fd3941f7a063db84e4dcf349a087d3527133fa3ebb526efb3a87c5bd4817451f4df093f5a6feba0e65fe54448ef607eca91d954da0018932f9bc4374d6a852cee433d9359453d13c729ac1779f43e4f2022c5e69cf64e924371fd72bc5c2d054f542028e4acb71120c305c3affc8cc8dff076f63bca4f6cfe7a05fe77ea281865bf55a95eb33804ae98e279cb67e76373dee33707eef1c3a0ec72d151a3ca1864f583a11111d4ca53b793cec0b019880fc9e68e073c333889cead5e0165beba6c8ff8ab945bcb5ffadbf97fe9c619b24af78bacf726d57d3db1ceb620e237f15a12cd15b05f88d7610a4f9a66d65027240c7322af61fc7547f3a4831fc098cae6e113879859f607d4c5e2e906c566acedc0388b0c307251437d593fb90ff3411e4b5319bbbf25b5c5e3d8bb8a52f86dde64777b24658433d8f41e6108e098d92a6fa5f065bb35d79362267a4a4e7d525b1c6ee68e601ae48d61dbfc617320b3c23f3be1f2c6ab1ec532d9d6b37c817de5bbc00d82ec87b5008ec7d4a96447fb89ac60155cfc070173d5c37017f541092dd0f47888b9038cee4acdff807c07489dd8a5ef91518d66e2aacc50727a0f7bd2be567eaeffba56817514958e720acf1a1071082a0662b673060c9e91c83fc89afe670bdfa6386bea9c1aabbac3ad9ae63b5799e7e9e13d737365367f293ee84a229c89afcb1f26b88425f9fba62644312d877adecaac5f006e1255e355e3baf44a44351693ff2d06a54af6ec22a3fb9485948b4d6707b2b1cee83ffbb9ea60c352d51596b744469f77ca95d0f9a2832d5209b7af5c6a9bc661234b476f82138db717f1227df3c2685cfffa4d4670ba3b7492f60b0cb73fc13ef208066bb03b0d2b96d663b0061a26c44bf6272f2f34041936bffbffb073b43c9e87edbe84abd80d10df3a3f575be1511d084dfcc310f3d29f840a293ce296375515883d6592ebef605e953a33297ce3bc38a3acddfec0e6468b0dd56d6ed2d13fd2c64d5a3a2b30ced25765c809cddfa48a839a584b3c054702c127d4fc2a1f5c890e923a9f69ef766fddafccc42f02dfcba1e7697f2a10771a97d75f98eb948b47498813924a7738c982ad5ce730ec5542816d1e37577ad3eca52bdc2e310e7aea0ef725b361761f1c251131e6972cfad61334961710dc5aca33e12ac7f9ef05a9e2542b6cabd20f6b24ee8c25a56d3bd8282b636f7bfee9beb1a290940920e8a81a27f2a5103388869de60091e9222b940ab9c71aef0b624dd3e74541c5547e46a676d79b231e538de5eb1dddbcbd86f23a1d58ff1cbb20bfc22f6bb989b06dea5ed19b632281402a57d4583752c53c596a210a252b0b49c6464acd063a8c6b05505f0ebde5d364e964cc0621534c4ddcc7a00872d7d1c0bdb", .None}, + {.Lcm, "-5249b5e8b8d230bfa895f84f2fb5b15268f0a4982b3fffe670394cf6e94c5a5bdfbe3b68e5214fbe0ad6afb13435f03d0950e019ddcc9bb12d967ef08691f97c417d0da1bd9c627f93036842bbbaa3f1a244a1167ddaf9aa947ef719a18156d0e94ecabf1ce284d8601fcc09414af0d0e0b2303f709271c0ab4d48687e851b0456b8ff34bcb1d83df75d45c935a9e42854ae4b3f9f0aad7d2ff163129da94d820823ef32cc2b3feccf36f4182d982a182f997dc83ab8084fb4d48cd84ccec4cc1aa405998897e207bd63ca9dc630a3391ed76c87c8136216bb0ae269526433f9551f9b0c1546fa2be136490c0031064d585afc5f2b804dfec962ff2b2f3e423a9f850ee6c0268220113fe55912d52cd3b7db7d5e40e028842f7ca6e5109d12fd427511dbef8bf53680c3d27b1983da3fd1f54114bccff61432f35cd49d2c8d8ba771b7be3120cd7c6e9b861a4bc58555788ce060707073dae4e2111222c235f70f0413ddd982e9e398ba39c07af355a900d1fdbcc083d9b158b3641ae6c1bea3eafb5be79046d337cd48e272a006e59efe5e2e6e6deabc1bc189216c851ecf944a8792ff77eddc0fef52595d77755fb2f51d953337e255095f116deb678fcb74d3a70c3da7dc890db9db16022084d1fadbd27223b5aa3a0ddaf5d4f6c3331ecd8b64700907bcabcc37a44820c3fa8730436062a67546ab0f914f86d0efbc13ff", "e5cf8f9c4f7d80489ded4dcfcc1a4d8dacc50fe20fc48e203bf05b068fcf6294ed379ee38cda18a0763178b418a3e15ff932052d4a3c22078b22e47dcb6bbb40ac4a866dca8f3c2c56f2f9c118e4c135535ab15b12d382b566b4aca11ed1e05c2913d774c7bcf726c3364583305eae6bd4e1f811091875329ca23ee1b047b6730c42175e09ac5ee64c267d891e31f04d03541f5328488fb58d92dd3e5c8887b859f7fb6e85e21243f916af09fd8a43f2da17dab29b0cd87366f4cc2236856d7e3bfa292bec490d2253cc7a743f9f966558c1e93feb08851966012728362c865ed4f2581a8fdd93408cbda3c8bc21e1e3342f96e2a7dadd75d228b8e03e059848a71f9af8e5e8312e3ac9c1f13d480bc61042b107672c128c8b237a24431219c8153c9b6cf12bef8171d36709edb0c90b3a31e4627930eb4a92130d7af69a24187215ba18004a4bc1319d64e0ffb85907950b2e6163045f7a68e019818e9c4f28fb8420f6bc7c49c9e75f8b8f244f5413eacb6555fe683ad056a54fd79792a5f0d808c15df4f0803b993366683ae03e098a1c23c487180fb04053d246f01ea20b95e15cf227c70161c4824f824627e8cf0ab01971e21dd1ab608e75cdad815616ea7b94d464bde2b5d6151e39b72437af6502a530bdf379ed60ba469c2a8275b5df65872852ae266c1bf8974ddb9214d24188df83b28cb043fa30c23394ce5ab5", "49dea77caf9666fbbc3659b33d9e151eb8357008c08598c17419ac92e67fe6a35bc33057538d7b85951f367fb1c6a4c667cff7f85f61f864ecbbc10ae1e30bb47473df9eedf1e1206be12eaed45d8a84b7a5b4d5ab2c7a0c9450aa201206ad6f9cb302e35ab136b3ba66622ba5e9498db5d732b756b981580f3551f43f1acdf1ae9dc933afcb45a4011275027e7ce03ad8c4781c873f5dc199bf03babdccd2195207e7fdaf5bc293d7c6d1674899a3f1efec8c2e3388a56fa93f8b2179b2612975f854b53d021893515cb6b992a476544f2ede3abfb26156960e2f4cf9eb586e15711502a07b2222f112cc92164e1824a8040b7860d9360da4269f7bac387995c1cfd7d08f9cda6d4dd7f24a88996f73f9d89bd2610082272585378776299aa74576f84f0608d3c48bc10022849bc45f8b4e090c644e78b74089aa0950ef2f3e104030d127ad2ced5172703dc6226ddda8a6cc616a27082bdb824184784f1b0231929b620f6c935e313a5d7409fa9a9f23537b06b7353d1c84bb35f156c35103c93619af7c15f6c233f3bb958d054e11930aa850bce9a7e484702775cdd4614f38961603f438a3fb9dd01fbe442a45fb40981431a423cdaa1494633f53ba66055a38487419d937679b6a0f443cd98a20f46b869bdbb44126503ab18f004f8faabe785081363eb9af682607c3e924139567e01ad59e4371f636dacdaf29a34c9f4bb6efb699cec7e05da522ab1b8d8b221b0ab64e042a753f01d4de1b8a8dcc13fb21b35319696c2eab381b836c275b16c4e0cc1f7c471f8960e6b729deba154905043d7f004efd6b9b05a3ba291a4eb0a7bfdb580d8dc0db27af39a3dc81595400b9b811273950d02a3a50dec4e72f9b0c41c43e95ca64898bb6bf8e43b758d37c303651e48ba5ca91ee35cdb92623deca7d1070b5e2042df8e3f6d7d233a2a7244381c39a39e4eede776ac2e7051e70eb575e176acea227a0ac59e380f23957d21201b885595371f70e8b86ae7bb54515e3213711031e37997d63ec1d027c236874c05f95e255500d1f849bb0efca660620a056f2dd0edd9e23444c451661d706a92c59b707a46b7bd4c8e97c100138000780b6096962ebffc526c5fb7c2d95f1e75737245f7e14d8b43276537cfc8d3e3e4c322bec258aea90d59783c27afaaebfacac8e2acf644695b45a8222853ffb4ba76082e23f5ca40fee9943d2056406e48dfd97c379ed2626536c1f3490b0e305f5255a22a359f25c8d222ddaf2b1c9c1b9823f5d28d9eacb2d1d722300a92db112663ce9949fb2005af6c028328f8c8a74d466b1e4fd2c6b5457cbb5a8476e47665d6437b999dc45a96ad83ae97b29df442b172826a6ec14907b7a60a7e7ff64afbb009e1b098f09034aaccddba4d384881c84b65e65cac04ae5b311f3ddebb172373b5caedb08c8a4b62233c94b", .None}, + {.Lcm, "22640e7d8331a53b53f600ff617b2fbbbbd30c2d006b5e9f0df41838e3037b03c2f6f6c6cc1301e2a0df35d1d0d410d61451bf3a6501ac7e0aa4adb63b1699be4203b1baf100f292703830489cb44633df309842fdd77ae7bcff93a1b9a8e238372b5f67d46fdf25c72fe8c764ba35f5f0e9f54351fa084dc4e9b8b122653ffb3bad23a10a207acd9c65c3f2b1e7c1d336f6ffcdd662335ccd94fd72ae4cbf32ca4d6cff01b0b832dbc056f9ec4cab6c3f0b5e0d2bdb0bd4b631a0e199cd24e324e97046356f388810e0bdb110bcd87d81edba8ae030b046f5c68813511d55613fe1c6f7d1e7e6d0482af65f1b38dbc6c9ec2c82703a41950fa148dc4b339f987513297cc4444dfee357d1d98fbba28dd3a54764d976b8e4adc900fb3cbea04bec042d2ac985e1a534ae297aee38eec425d36617018a2d82b7724e421fa5df0fce5787a07c74f7c766b547aa065355c1801cc35c72393d1b99ad872c82590842c7b7359453796b4441d6d77389a21e5c511e95a8c397df381d954d13870aaaed8703aa7154b74c4af6203852af05c18228f77ba346ef5e3f13f96cb0bb0257d6c9a71694c1fbdb0c6c02fbc3055115dac22e6b2dfd5eae2e0d6a04759619b1e126e15abbfd607d38362ae0ec12463ab036dfbfc1858259786793bf436c2da751afbd7f3c6779c72e572d5eee07e4ad467715eb081905571b0adc36e8bf0a0477", "4e02637f8b9e9500b33937eb3e6fc9cf8f555559e71a73f4b7cf9cfeacab5226f00f9f383fbbbde8835c2a3fdf83e1074592bba2543f0438eae3780a2df97066dc9c65cc926ea2ca2fa746dbe66686a4953b053a25409227cc27334120fda02a7545da8d54e6f80a4003c4e00e0560b344d0bda71ec52d3b9c508cf834e4f2fdfd5785306648f812ba93cc7d50be9e04ff0d1cd41be56f577a664a69d0eea127fb1ec4b45101d3f4ef0550eb540626976ea28201124ee08d949ddcc34404dda29d3a1d00aba56aeba5c214dd8c4a3fbb76a90d1d8b5ac50dfbdd18cc99a56f2ab4cadcbbd0732e34a289ee38ce4e64661017bfcb64cb69c14faae35de792d652cd6e93bc334832074956d7ad1417df30dc457c48e6b3efe94dab7c34fb4d131f12d4c26a48f2b1786122c9b35384d3a27b74ab4707165def9633502b7c1b51a55083382ee377caf4992e3144c67e3137a024a3ff8073a86242e5585a92eb8773c0c7d6b1493a970111da395f805f092d9e4cb2f1aa7165c519dc7af8354a9ffe58280019f6bc83e980a74e46440a415af16207e597fbe610058fbfd1d6acf9916c2bfe64575146b890e1bb3cbfff0a43ea5d851b8ffd8d233dec8456d86b112e390830125c28c703df9f5459fc529545b3d54fefd68b16e25e013a83cfffcfd4688881d7fcfc98e86271605555bc01d1849fcce4aa138ed9853216e9c2a80f2b", "a7ace902ef3825f12c826c3c786ea21871d659ab41d941d885dcf79e088c5d9c87f888bc797855b41c7e83a97f4421e72333ee1e2566976aba97ad6ef8f25630e07b030f5b6341645bc6c8863ef70ebd137705bbb31c62653c80faaa4c851eea6c43d1feffb2e98adfd39935fa64d27b77bf189de0252a234a3adc90bc5f71605d709ca3f50ed74fa7a07f151998741fe3e9457f5ac163b5b4459194d5c016d769ac9b1a706ea855bea86d24be4910538e26b7575dfbe215388da642dc1df5ce4c21b4d5355b91b2b36e2b693b64cbfd3606d1642e51d3f81bb54df0fc32276c7d4fc4ae98974631d6ff99f92f482cdca52f4ea46425a2f913c37610042ba618e4c474636062529fc256deb10f781f124881da03fad8273aea81c74fcd58ebb262330c9e6b307b42962e5372f4c58ee683a291e5553605b2bd441e2e4b064605339e306eaa32850bcaadf7fef455ac4a9e63c7c2529cbbcfdb418ee455ccfe0ef71c3b89c806f80ff0b1edac4b1ded0630a919c6fbb5eb6d75f9a09ed74fc262414d3cd39616201ac026cc49ea37ee853a545b2683e364004744715b01d3ef897fa5e8c0a6bb5a2c995b7c65dea8d097ff57ff14878fbab1913477ffd847c144daf27e4efd981ebf6efa911a6cd3a0fdd0060d7afd44342a426916003a4c14fa5d9ac9201d90eda55a74682c9f1473e20fef524c657746758fda8f698c2deaf5e9f46c305408003c964a267a070f95e2f3bd9590335b05bb0b03473c0699ed27c45d917b8c263d7f88e56c09f4f83a47c4bc63690dba968c04c50e574f2240b787d6df8ee47ebe9bdbc0bb09734ea8500ed886f15ed4e3089145db9b6e8c0c7e9e60b7f286e539f44445cebd9ecc3876c964716e9e5d313368b4a52f4d5d3ecfdbe457560d1ee4112c421725cf038c1eb6ba8d52e285ea33b734a257956042d73ac498a0aa348d911e71ccdf397cc1408527715580d2e87c2f06b3491cbcb75b820d8c6739efe5cf9123b2bd277cd4a5eb2936b20d5ab80027aac8433239bfa9f8d124616528060fd5d4335a3f8d31be207fff45256e7238bfdb0a9348b30581a5cf053f20d557af5eb9bf7162b533f19a5421d7c81cf7a1f9cca9c0019ed6cc898bf33e2ab24ddee53fe7db76270d7318e3d541651f3721c36dd3e12ab541ec8e43565ecf4094376605c3d4fefeb3ba43bd7445682dceed3793751fe60001b870be72a4a7ecbcc0f479f84b359c50a6f4f6e2a55938924d56b1712af0e95d8e76d1f69697e42b98a9378089a8c5868ce1f73dd1e1d3fd60234b502c69e71384b8f41ee2fd17aab7744162170bc94e5e4d57debbee556dd5414c545a79d1ad2dcb0265852558c9f2aab4790dbdbfa8e39c6626ba1c6de07750898a9e9a172bc936373f031431572d1a2c87fe05f721434a5d55f78a282b492761c8dc909b8fd", .None}, + {.Lcm, "482b8f683f818274e7aaf53458d1195b0facf91b6a7e67bf400298234f2785ff30760aa673bc593ca733d3a9dc29f112aa4ee8782a1360342ca887e8dd860008276b8a3dada1641d3ddb42b04eeab3b4e98fcee76879a91859a6aa29c0436af701bb99f26cec2d32ff795e5adae82398161c7eb18fa7ce9ede931c51d8e1419148c06022d3718635921ec713548603631095723beb33d7477e092334237ae71aab9e6a27764dd113547058e1eb48f2e5039cdb866f85627cbab9d581e5ca692ab6d2aea7affc97da3653b9065793e7c591be2340cd4c6c0a7853a64f75f9c3396587beebdcf45b51c3f356b7d1696eb40b9ae44628c800717b6f66e98b01da6c98a5e720feb45b52998e3adc835af97cc200405d43b072b789c373e58264d3ff689f90bf7984ce52843ddaf1881d44d7b6ae69753daf968a32c74879a4ec4a8a32c66e6e33a18fb4483d3dafbab140647b417e762b0113cc0a5a7ec58dfca7179304d95616714ec07695fc9dec2decb1b953a65ae1ccd885de9e8f1ed49e9f920fab044c8c2a34916ed9f3358a3a9c2eb0668aa3ae11a6bd530cacedbc72f3012c0a11c1ce57c40a51a04c835a0df98a0a81908a7d31c765db713f4a482678e17eb276ea133dfb3fab008ded5f94c67873e9da9c7acfe2a64c16e94427c6e21fde30697d0ed210050d0a4bc5f5da03a345e4a44db3a014585f2eaac307e17995", "-30d46b1e7391ce0e7a3a5dd7f6075dac77aeb7092c00b4ebc14566390867157b2ab7728b02a51eb91d660912665a8bef2e2774ac83d0c78493b6c36c262b48489edbea49c6f0041b4fd74c9ce4d931795b9d4f41cacb1afbd0b1c4fcda724e33394664bee52ab6d94734c38f5bf9e3acfff16b3a0ff346794232cececa1d95a98cb4bac65dbdcc0eb9866dd3829a9e1e698b182bfef876563409271759bace865cd82035e3d4bf6b44a91155e98e41bc385950aecabca5f3c420e65c665e4d19e0cbe29398c2a66c8e0dca26b4b10519f2ebb8b290f83b4e6017e97651d72dc2d89105c0f8f94de49def8e09f7fd84695c99b65599ba4437988017c0b6c0235ca0e050aa915726196950aab56ba54509c1efa17b90262182a080e13626971501ad44e97b6479a2df2b0db4e396e23d49e5acf51351347672d28c32dcf9f8febdec048131c4d559d57bf66f439f9f0a9a39aced320a21186c362a33c9f95875ad4973f128774acb7348719a3f06b8cba20bf7917f4d208902c2eaba061a57eef9ece3b62a16d9ef2a2370b8fa649a49ca0504a40ac2216c19075e5e32f82b8d983acde7342dba285e754a6b4d0545d2f58011d0b1e8c0efccbf13a6e31784b554f9503e7e3c2b473e0e3eafa992a43bb2bf256df0c2bdf21186c74bd6d7b45410692ba3fe6fa03cec2f6a4cc0b2d7cbd9e5caf096245b62b6fdcdab3e96e0e03a", "dc40d2918dceca7b7c4258273caf281b5b11f256668db66d6a88d2c3b346d0f1490c1aefea521f16b061151dd30b1d6eed1ec49b99df6071fce9c8b9a712e384593698e7f88998fe0c08af4e19e98afa220a277e96b5d995d08ac27083660c832d09a20917ee98f94bf06516e1f1c27acbd310cf423eeb12ad182bb0645603c1149935122b1e9832cab9adcd0bf873cdf1e623e4597a90f2cd4da1af29179dac2a027ccc575cdf6876927cb3300c809ccd7b61bb8b1eba8a31deebbbaaba2f08239d912e7625c4c3a54b90441ac794b02749f4df0ac492000d1380bdf66a203ab4a3b9caf4a2fe9a7e28d717114340e3684cfdc50b86ca250796d8bc1ce1bba6b2bb4bb4f174315ad69aa2dc2dd646d88e8e4b0dca947ee0fba07bc4fec71a57380ccc90a9bc93840ffb05e0f637813532dd7afdd9f234ef0735765eb2c5914d4aba37e637a8fffacdb5d56f50badb84b358aef2b8492923832ea46c48a51f68053e3c55f3f1a1470c27bcc300f715a935c9654e4ca98f7827ec511eeb9a69ee3cf8c13061c0f217e408fd9e788f7f778903d11aa3e8e8d4b35e3dd8dd63b4c2c50faa9ba391ed746fc4f8df79d18be43248344f8c4ce1ebff17d616be217a1604e79ceb1980b13443ebfde62b5895274300add53d8cc768fc42e70216abfe65cbecabaa4589c32237756ad35ac9bd7e866558071fdd3f27fd3f0f7b4f31d2ee41135f9f23a00f88d91be5bc4cbe627a6eb1b3dc9ced351001c2906fa8de6513629c4b1a23c11626a1450e5c7a55f99dad3642d772ca82f4e16f232a3df95e216ecf5d0984c491f390614931fb88121b38260381936029a56a5217ef26e9a3e46ab259be70af8a3f6c2db262a76cc29541f591cc378a9d5163ffd0a7129fb8e2c603f95c9fff6a78c9310ffd425b4bfb48bfc327c3b3f721cd6314e6af6ff68a29a3c336e9730706b1fb0abe9a76da7a3d77552dfe8d2e4bc5029b47c25f48bd75a117360455f3f1df4a7a1526206ef7291b248ba3fff9ab1557164faf1d58e805f9d1e2b28944a94359688949c4ca1adc311f09e82ac568691c88ede63c6124e920d8aa500f209acf30509ced6f1be8ed32f05216967faf12032f0f2790bf79afd3f9735b6ff18df76cc3ad1ec9fbf657e067d1c7c780507dd428b22f0052a2eece6fc471cf6f120b5234cac187966ff6598b57ca4332592ed1fa3076973da15cfd662f7d045963df9f1898c1ddad7090bb55f1b9e2eb74ed025ce72ca34104c6d6fe753118b0af53fbb21198caa6e52dfa7e20321061fd9b2c647d99a6d412a274a74b216478c8859103db88a84bff8f3af1519b0194511c5e903d28c059ea4c945fb677def83412af40ee3ef124e5e585a40deb3eb0650b720add3b43cf7b496ad36a31fe2ebee29df23e1b3441521a5fa1a264dd056396552b2c3d7ebc2", .None}, + {.Lcm, "-6971fc72bca140acc2a8583f5841200a8bb894072e3d15e8b03e902314a968e58912bd7195a9b7dc24163a5ab791070ee378b132869d87ff99a436dc8fd10dc32ab86f1609c455d148faf4dfb2a9169fa37f857542a471ba7d43c6241fad3540a66e21551fc166c20155f72cf16f87938c091a2cc1d8f5440cd3053a621420961101f48c5c947e22da9f95c58bdd5b51fafd9505c26dcb3bcdbab8aae5658d4b68ea9dfb6216b325f6a0301485c52118a877980ba39bf47828b29d4d29982b21249b4078d473702d508d80cc303e6114d3b72322992265281190fd1e7c893b26e5e1f7bc12b21ee1a9ad23d8c64b5a215ace93a6156189ae75077fcacb5449ab462d979abb1097d8ab419f237704208e6d77bd880695cfbc69248b7d8a9805f1774b5a4716045d26805a4d8acb339f19f10e153082649806d07303243c0ddaf8679ca1a62af33d3322adccf78f2109bc4e17e563f0c2393f404e8f291b9a968872528a7b52bcf03713925eaaacb7d999067d53ba588b2aa4c273cfe9f6cb47cc0b7a934d3c4d33cb801f7a368381dd1f27117a56b6ef8a0098a92297a0c3c006053fc13e540baf7ffab0ee3887ef5aed046fcbd93ee391e2aaaf22e6680cf86779ca6453683e70c821491d86f162cb183e085c8ef301b95e9840fa7384d66d0596acb3a355bd1c4b3399a724d56bd53a1c31886c17c1c95fee726cd6ef171961", "-ca84f1a5e7eb53e364d457f61934757d2b7ef0432ee42254dad2d6778aadaad65aa02dcbbeb9ff2e56c5c44885da8df7cfd7677f464ebe387f00eacce4acfb92b104e771fd3a032d3d4e957fc69fd3de40375df62c10edba2c45e8e9e6a16e7b80f1b581179eb14a541ed25f808c8f599faafcef3c58747535cec849d28a37e743e2e90488e0d6fc6d303443380dabe52fe25ede324f8c4258cd20deb9eb66dcdd073aa1013cc88e3997aee13b0ca245f11f35d7ec54542899a6645a725b57e42fd160eb01971bf17aaf136ab137f59ba1140d23fd6c69ecfe3e7223046a5433396ca16e9fff8eb4da5063367a051a469e0ad4ad22d9172a28d897df1a4bbb1c79737daf2030c8f5ef396fed5b2fbfe658a7a604366940cd4e709d92a6fadd32b3abab8051eab40b347381e08faa85f3d8629786792448022e3c6cc24a2005da21a7e201eded6028e670dd70cb8650602260be341c5bd4714c230887f754268e37de4a8007167e9d8640b96acab759099387cefc41b81e0c2686eb9020fd6e15bdec9992383267ecb74c2a01ea8dc2e30288a9a232fbfef03be08c138d84307284232d4e7d31f17bcd3c43e59a7699a56b0c06663ac62a5857d9d17adc22486e471de7031483bbc69159b124b48e70a9abb20ede3447077c9fdd4190ffc00edcff6b2b6b6b5746622aa133936717cd1bdc98b9091cbae45e5604cb9a152d934e", "536ab38158a702b0f07b3a8e367ae099a135da9b11763c2af0870225443f01cb1ae685c23eab07311eadd20cc2c246d33a87c5c9b2947b3a56cbd701759e38e83f6df947af277cf2cf1b406fcd5f48fe3692970da8f5b47f10dabc648ffe1c4ef87c417d3f9f512f8663558809fc2f2ff7b73367fe44da970c8f7f08bee6850fa15dc1d984bd0f37ddf6b19c4416f886930720e6fcb44583f216b2820b69f444ec4f15d5f9b2c0a9649ffa08eb3f2326455179fe6dcfd437413a0da5b08fc37e91fe20c8360d6ec01a90d3b67e36c5eae97a72f343d9b0fa38128fbe5ccef82275a1dee0dd1828b0080fe4f95425f0969ece0ae384775e957bd804b89c6db733e509ab2987fc9bad3811de2306543a0d2c2e07d3d3b9b40047e43d1c4b4b9f2860599aefb50e543aec8ba98f4b8344091f69db84e4ebb7918055fc5b5da845ef3331d72bb1030a2c0021934c5cbdefb727e8e3d7b002e9d01ce32372189cfc0936d35b6fabf1885695c4c57cd2e445405babec56950978e53794a0a0156a162844c364e82bc396696df6838c1b9383ba5e1752a17c7a5c173a985480f6e05a0400195d719df2a1a8e6a4a6f29615b21e92214d77800da7a37219c8d7419086576b9f0b8df3a77a24815a012932a4088a05127ad5e6f764860da6c9d8baddf19fb36ff84088720cdc3344cf120d64742078b8f0f3169c4b02e29543f9643896cc6cd9b956f846a051241582dd08da17e4699b2c61a02c903519b596a10ca3117568a2d81cfcfbc2e4bd1107a1323612ab027448e69d8a94fa17a32c38234f583d8909488ce6b098502540064e67f750a7f71fd5319006e2eb96ac86039d535cb72954b69112ed0ec060950581a8a96b1759d7e2d2354e4b9bdde9f5da51db66982396804edcab3dff57c416c7a146380dff87122e5eb374418d15cd0a2bdd75c938382d01561bad68ea61b4cb0352e3c107cfa6d03b1ddabde3555bb97229425a88f6398c79c99cb9108bc6c64ffcbb8378b3bd418bb14167b5e1b4e36d7e0bb646222a947f2a857c99d15ddf2fe6788ffd6ec39b7fbaa06b732926d0c9ff947b7ab1d00dcadbc4e536ef4139ff714744151ea06999ff30c1ff23cd32a181152e50fe61902a684d600738cb38fd42f30105586e4e9c92186c633e6d7ade9d8ade467d67b982d8efbb494fa1238a099a96f4961a07a6a0c3b4bbe9baba43e805694515eab22ce64d0030029678087204ddcf1eb74a3297b8527e26e1d24c86f1bfb088226f38d42159c7c4818e7b04874fd275683977f49666c73c402b2c64e29b5e6379e0d5e10ce7bb660ddc6760323aa0a8373910f705ad68eb73ed58f4370b683cbb97c06f4ef66d62631a8749384a42e5f9c8bd5fd809d37c40a86224fea6faceca86e713866c323245156bfd100eca3fb421467adb953f4ab04587a96e8e", .None}, + {.Lcm, "c2c46227334bb9b790a622f9c4625b57aab33b45204b77d6ef2195be2acdbbc9ae00dbf0092f1594bd704ce9b018b3fd882bb3d7e9bb323ba766d2fdd10516ddcdd262f4fa5879ac038eda89d752e1fa925cd501d4d1478f7773d07c61ea478e5b2a9c9624b9c126558e66ec4b6a76842fee462cca28d350f71bb3b24a040ddf933bfd1e0cb6df1d19114cf559eb424663e18e988db453d8a82b7c28c596cfa5e4bc8f362e99c1dcb2a33f7b7c26f74673f1867d8f7b013f1419ab636289aea878b9bcd0a8a3ed0fc32cbb25d8cb831332062428e0d395f1b7cb13f97681acaea9ad9716fa465e41f5f4fba61af87265344aa898e073e033284abcf3b5dc3d991ce5fbeca0ac0fe6c4c0a5810faefa9f2bf98a2869d27662800d42b941f271bf4b65fa708d9989bc159d9b2a090d6adc1c797190649438bd7419a29100ac80f364a2d43b9301d0622561477c068859ca69397131b3325ad374a0201db21e6cf844762ba5db27703d061042f0480a07d941c80e73d52d3a731de462537f68972e23554a6a0ef692d4b39f38bbdf650cd50a7db014d35cf879704cc079ced0afe93d55b9d9dce0c3e757a0a6c46d27fa340454f9584fcf9d77adbf5382959e7d48c112f46e333d67329ef9bfce58bce6bad1d5875e40074e9d7f8a413886f477b50592b9098d18d313d5899919efcfe7077c9f4ae7cd7957e0450bb3adbb0316ed", "-9e18909dc72bcef9f5a3afe67fd28ee19ee484183601ed4f4e3bd98810a1da8d8fe4e5401dbf7d5375658038d66bba7fc5944c24a7f60aa4307d5b3fa744dd6e19e68ffe4e56d61887b3c86d5e180ec55e5813bf419846a9dd8aab923d8353240a5135836f146d522ec74f7df2a8721b43153a1260ce5d906ecc9ec08efcd51bac5d909b102d79f1defc651d7d3f6a5f35e0b5051118cfcbaf7f69f36192d8089f3c25b21d51410499cac56a57b009a94d42006381878565f6a0486f88bec2bee309d586b572c9bc97c14ac42cb8875a7db35c2eaf399fd41ceb1495ed98034800ce123936cd348da3e5d200ecbcdd31570b0b48fa485bd22becdbb1c732a752fe3ab623f500ed626ce8de01338f292bf1a7fed46d363a9c0c16b9b93cb913f30d99252701c56b1dedcc58771dfc7af18e33c828c59e203db809c9aeaf04c1e51e0bd6c8028af4512aedde21f1cef4c0f14f0e2b978251240adca9c753eaa8b291f62c90feb279daad52102fa78e1a0164ab82aaaab451ee00e47fd95d5eae95322da84f40f07178fbcb1d1e2f36d8e6681a2fac8708c8c8a518e6d945213b0ebbc861b943fecd70784a3fade1138b6e9f64d955875e1de930827ebf17e84951b6836ee8ab0f957ce31995bd8a6c8cef9d9e4bcccd3dbcd04b86575f25725b53ac97e5124fe7f1053f23e01bbdf9277e203b1b7cd748b572944644bae6831ffe", "7847e503e683c75eeabb3965ef6496022c768edb00006983107bd7c41eb7f201c0f60f55c5f915ad981d34de23e5b40680ee2c16fba96bd78eebae5522166326ff863ca660b17b215ea54dcd8fe0ab881a0be1ec2dfd776243b5ddc9406aa840e32f67e7fcec372078da03642d663915d6fce805bbf5fa5f3ebbe68cee78a46dcbf5ab0de22c9bacffd1c9e76fc03a2abe02288351b28439d696b8556661a1ff6c652170e6d415a8336fd5fe24669fd0dc917424e1f0048a5760046b757ee1a0f2101b441db67b8326d6528f2e9d19f811b3e927ecb1e6f8b10a33e959f8f702f2bc4383ca6c2c14beca57738fc9a7028b120cdafe0f4f25f2c88aa37e248226e396a6fa2938acfd1958cd0f32337e71677b1d7d57fd7ba1a417b25e311ae3b8bef205b9f2a9bba5fe923222cd649eb3d3cdc184e40ca7e547fc80366cf813a89498a09115b7755dbe8c704332bce751f6e9551c902b6b6c4e0d02fc83c5d6013a212b0f59051c3d240209669d03bc620ff2af5833d69d174009d8fb6502fbda608fcdb973312d6207af560f4b211340c09d03995e16a3fc91dd4b8b0edc5b3b68051909132cb5401d439716203885b6fae625993af84687359f1f6252b95f6c99634dd87429add98996cb65cec6496c31cbb6bb9b4d6d1b4cfb719a193735b953f6aa6122044e92ac0c5d016e55b4a340b14a0e3e8c72d407737490d16a97a8d4dd40099545380b4b6bfadfced147d99666f627583d5c9d1be1c7cfa16fe951cda04e506e6df1b15545c5d053beffebf8b1d7ee40c2554120ade698e0777659bf29172fc76457c9892a182036ded32e2a9ecd6600d7d3a0047824975798ca608c8928b77845e9acce170349c743417bfb05beb7fc9c33cb577fd205a889102ba603fff896dd9bdf727ffbbfaf11ba630df11dcc864578a371ff61966ca4d784e63b7ec6555286af02eb02b8b1c8c2e684432806cc4a86d1f57c42105d926d39699830456fc315ed5e3fec59b2d5074895de50e74cd26807961843a06817d055521c9507f15caaa692efa9a8e0860f7d80ea503a174f1ba208ff6199b3822eff4ea70dbc31c4ccece4cc32bea39495275c043f901efc9d93ceb11290bd27b19d733bcd7057e28e405fc75e4f6ed0bf84fd25b04f252386287b719fe29871f64708b1c1bafb5576831434c6dc835b71143be875af00000436420d744492185428d1b6ea8c0b218cf3e3594b9c575e1bdceccd862d564442be7a623d199ddf718b0e811663ecf047eb04961710808a096f7538f462f150895dd646a4625c345a2fbfc7d98318bdfdce0e03106d89a8459b2d4d871a221111f5be535b85e7e44be68ce623cb52cb4f8fd86da8cb3fae1838573c6b70c934df43877201b8252346e6c5e68ac7bb5ff21a4c4afa8e5da7864b03cbc1c9d1ec95d5ef6d6564961e7226", .None}, + {.Lcm, "-60ce9e62727f556035b1838d5ebcd5ef36e97ce7c6b3fdabe0ffccfaa948ee813343b5e99c86ce3dbd962be9c597a3f14426497b7edfd91262457c2a184ae434d517e30550fd84274f19d73b7c620ff4bfe5c681cd36094235782d31e712034735eae4b897ad271f905e4d3476a99de04ac8bff89f6028c99f59692be161267282143d6cfffe9f7725e5f291bf32312d74b01485bf045196b7bb3f441714ff90b251a8eac9db4a132ea5070c39cf182200f80ac845be327b41a78779a7bbfa3db4227d6bf965623995adfcffa3ed73cfbb7a7a79ce5002aabb4fb605766de3ec42074145fd9721147fc5096ce4b8c19ab16a57b8ad7a58d483bd109cb15aa88e1d65cf74cee77b959d64523a974b29e7e315c0e8447995e8c4c2043bebd9ab2aef407adfc9e92128d53c888e291d0fa1f0b1476d9ca0db75f556d4a8b05199ee3a234852b4b5f60bf460d0d78d366460f2bb7c8aa7b1782d90998bc76c488c716db576355aab03e83f25cf79a84eb6d3b2b5909dda7a0e3e28fc997a7e8bfe3b5e6c076e8965ad7ec63e243ee8254cfc59d65017e92ea5c6e79374f363e495d90c339ca538bd7147031a51ade27f99fc27241c7dd4b6fc7acafe75eb6b18cb3eeff0b52652a477545f97555a81b028519457d9fc77a89a89a0e4d6777005d58b2a80231e8ec8c7565bed1ae1fb03b1aa78566ec8e7089f0b67481d8cdd45f2e7", "-9751bd68ac929f57bad9a01000ce1e5a8ca02363c64f367df90471f122ce7f8e34e8b72149550b79840bca1e8755595f33a9afa975cc6602c987f60f93cd77097b2523cc599d844a8f5f1e84182ea04f44e30223d25661d4af28f5514f88ecb64631e219994cd1647817809a91312ea4916577fa613f20a122cf11e7e3759e218abd93cb36ec97a7b1eff9750e7192b982622f99a3b69e3ec5d409dafb14db89e8efedc1716e98f8d5759cfb87759be92071f93991a85250d4e1b91ee92f609fce1a97c0d75e3957d6447310c57a5d91b45d64b69891a98cc3b9242ed29050dc1277a4184b91596828ebc0932cad0376d14203121f975fc8187b507c454012ff8b018935c2a3e881036dcba2f9040721461c2993d28028aae885226bbd5e25b884b0325a0c6dc9a5591afd7fee2370390a11efd5c32d52bd76d0716d8291861a6034744f6130ad42559049bc002cd15d317e83ad0063c9cad72c556949697a8bbb5a76d81811d851b98a38a375b7267f6d2c92f501c3f944be1c6550c39d94928bc2cd0eb1f541eee57c05e8708e454acd10e512612a4225ed0a79146d48a72ab9fbdf6c9a3988c8b375a8130ad43b911edd7e3191050780e18aea5ecff4eeb5d9b0ac9a5e3890deff2171abfc4745f4dee6f577d51a2a03823c5628fa7acc26e06aad23fb8a2e68dd6a430290233c6b65fd93d7228d59e387e3f33f4f6c6ab8", "3938c86c4ed0a0ae4331a5c92df0c6671d86e3d757d79d4b6bb02d195f789f8f3c00fdd941a29c4648d875ad16d689c0c9995bdf7f2a415fabd32d1d6f8306e8b50cfe5ec5fb35561461c6d3bd99db87d541a7b53d124dac7f34ed7b0e0416c33d6cfe338ba7aee38ff4e29b9b376e592036386169fd4ca1715c11ae201a540e0c0932f02f81dfb3e39f2e023fe9531133a602a5f6b15f50a64d865e1d81acd98aa38a2076248af8f59fdeff290a900e24118f5fa693495062e7269fd566d208c008f524e3a6ae73bb86362fca2ce2f0ffc0d5bfbe112f913195e8cf75b57e9f8077f11de7a0b8ca7752173e4743b7f38bf7a7279951bcfa170f699440f13346606680cc325b27bd9fd2d7686b0eee7491b7dccdbade3920c117c9544d3babc46ce663c61c8168a31f293121546e46195576b59b6ab7188dd47954d8a45c29d342443a0b114215a4261e474d9951ca07e229871fea17d856c611ddca82f5cb6bd03cbb68e42efd3245f3b735537e432264943cce2cdcf5d612dd5c5195744a72bee37e89e25372b8434b0ac2093881ebf35e72b0bf2c70bb90271eeef7c5b1a39b698ceb23a7d9cc51292ca9b93ea1cae2001d83386a72a949377112b8b3deb643b148cf76de4ccb0173ff3f40df40d179bbcc93cbec180dd6a50335f3f6d151aac6965abddac0cc228a9dac69b611a6d2303044a8871262feb57729185b228906bd2a6502f6279ef8f7eb70b6c36c6677a29df5cf744cb6fc62008bc5c77fa96b230a0078c0f1cc8ea73f150e1217da9ed9bf168e10c19b77669b6aaf543170ee9d37e57cffd3eb02507060daa3b0291118c0ff25c804be52af04e970688f9668d3fa037cc921ecfdd8d4e8e79403d2e9937c14282536acefb58d7740c89d03ffa721b0db9ce2cfb663ae8271af0b5a6572e0d42e9691e056f73ef4e19698e2dc6330c421d5953e1de81b284973594a0d47c1317fd3d97ec5ad1e27baf65c56d673dfaa9d9c66fed64f18756029b949abd1d306a5a3a3299557207efbfa5b38114af83eba2c5bfb81c2399f2531886177f98319a742a3f448d6cdd576c4104aed2eb2b3e42bae626ce6381a8cfe85a7f773e3424681bc96f06288c70129ad22eb746303345aeabf813e91007f044b8c219abdbd744bc0696e2e8dd0e42ede4dc55b76aa4fab575e26da0f292b4573b6224b49a92ce7356d0e82cdeba3b52007f1390e8cab375392e45e63c99363cd57817af80accb7f05727c80a30ca1b2582ac9864f3bf033fd69353b5d257d7b6cf01e8fcc01cbc561400dddfef666cd03ef29b60e77a0833881d7e804d253567f0927e680d09d102fe2648ff32263fd1bffc48bc642ccae7aa0e92ed0be41f3c060988064a6f7090e50bbc74017d858f360eae829828da733e89282fdf456932cced6c7fc696d3a22815648c2ec34e3c08", .None}, + {.Lcm, "-5e168a74680dc74b1efde672da6c140ab29a2b2fde3254f7f50986d7d48ce608064429ddeb8fad5ffcfaac261437d077f7694410bc489879640012abe58a55f7cb45daa80e97577eee9fa951c024b29bda2aa88d3e309518f9f25254efcada1f35dd5462501a3c28334c438508d53141f94e7d77ddebf4d5dcd1035465760ec00e633e977123aaa31effe498a65243e8d1667f688fa5cd6480e9b1c34f582b3cd0bb86cdf13790175e5a03bc4b06dfc0b66de1a73b7fdbab1ddd421d39586002d26cf661398837c3bf30a4b9582b62c6ce0928a287e90ea31d37b3ce69c1b47fd6f456ecdbe86c8f17db027067a0e533a3f3283041de8e2a97e7aa07d64b20ea61ed4b91e7619868d08d1816cc2cc26b69f12facfbd7afa453ab76a84203cc855d4a7e4adcccedbca63b117c34a46c9652ccfb806a295155c1e36b5e5c131d089813b0ca5201cd1fea6641d785cee666be5226aa80cd48f5cfa8cfab4f62fffb303ba17271960f6ace8ec3348e9e6a917af1341ac22b633ddaf776d759f98d20fe6c53c6bb5cde8bd725b7b94956392d88098041573ea39f7e0c65c21bc82b000df9b2355aaa5e002e17e56344c45092338af74936ca7c4e6e1f4638f1d9367c3a75b3581eb288d5650dca3c02b4ef280c94150c56b8868f6270224d15c9537490b2ddbaf9b421a03b7e81c13834a0aa498e5b20d2a7e68e94120391bf563853", "f310d94235ca8a2e75819e2e7b8f378c75a2299882b162f9eb18482c493ff0684ee09fdd0eae67cd27e9f830057b7497cf8e7337cfc4434dcd206b4dd709e16f7b80acfd9821aa055a32273e55403fea3233b10ad2b08d35c1f5d77b76d357875d7d4b0899bef6b2c5476ab6584ff14a46f581bd0e8061a3e35adbdf9dace3578483ccb7a7f758bec11cae13ce8eb54b0762035b7614a8ee1821f517a8e208ff82c0775ace336afda6ae4bba5de376b607cc1931b2726cbab2c14a8ff96f9fe1527ba35780e35841eba9f04524585600607bd2342f354b06274af3082e85264f61648d304cf2d76d42f37753ce55377164d3607b4e77c72391eae5083bf751c6cfe4ef831da6791d82e86f9514582abc270a259b84d58a16084757d8c8783617df929dfee7f82ed486673e76e15eedb2fc02b0e9a781f6ea382bbb2b956616a1454c197d06f89296fa4d0e7857d065f5648e46659c6a00282fb0cdf465cbd299933c4fa77ef3a1c6b890b64f49422b96ed648b812f5f388cf820c28ef0d7ceadf5a074073b81ce4059332eb422f04acdf433f5af07dab4d11da605b37eba7017fe120b4539f2d9abb2e08565e31dcc8d126eff2de4ad5adc54be4a423c4241107e01e93c9324b1eed46b0b0642b4c585d6bc19ba5f69fb306e2938d3c2a5b7aaae353fc2cd78251b7074f496392baf0ed552875dc980b3e8825c0cbc8bddd2a3", "595596ae96fd0e7bd7dd872a8809417d1491fcc70d78687ceb92dc4f232b09333a70ceccbf698f916fb23259863fbd6a08d1cde37faa4b06b04b8afcbb2725c12c82a25a328280092ba5da9d8b6563dc9eeab649146e30981943bba4635aa8537c90709b8d5634c27b625ff4c0ec20a1a5ed0677b84ab1e56125c08257d1049aec88bb8da81e958a381514cab915ecd1d24daaa1e4d8c1db648bb655d2c7897e387c5ece6498a649ac175cba8b0697c5171a9b8bfa863ffc693ddaec90cb7c44bad1c5bdc6c9d2ffd8bc25671dcf17a7eee531b7083d5ccd95e4b782334c27784eadf686044d2d2e7a7fa9fb9d640d45d80e6ef3125aaf3ae792f7f060897d4b80892dbd0b14572db958b3212a8463d4765d63e4cf7291f16aa9e53367238f45d525fe4d27eb60e5663c5bb5dbe57aec5371638b0697b12dee36046109ac99052156cdbb19e8d42a832fb11f01e6a8de38e28b99c613e571e21e2c4108c0ce0c3c0120b32d5e50fcecd814ef0b62c8beb4e6c31963129e242d08936a638c87167a819889c2a2a39426fa7552e904d18af97949384e56ea1b080b15b32383139b59b620260bacb93998b9dfb4de829378f5664b0529ab3edec906955a24b350bc270ed4072b6cb1a5bda7b3da5c34d777862825c9ac5c28a93d4546bf91802352180a34ddae21a332f463293730c6d51e5e3c9451718e3b86d10eff1f2ecd3dcda52847412f11a0f0d97767f28f37b039280acdac87a1d306ffc16a7240f1f2db0d9e72fb074c3fd3fa61b971fcc910af7e34ae7ef7d66939b61414a32071aa8917bab5ca134768325f6d6ff9412fe26368dc551c05e2c8901c166919548523bb2756d499f2ecbf8064b7b187bda69e7a072ca9d5dd72645ec9d450d61556c0676187d12e494cf0b81a7023ab6732966b00dd3377fd6b3b4070bdb38060cf2c38f3ea20326eb1a9a9323fb48bdc7700f2eec480176217867144aacd4d3abfdddb3d581d9c97b996b4b8ec8d3cf19a22f9f3973b3c8b75f35a29677bfcca8cf37bc3462ca0c7ec1139daddb8a436c481f478d9fb466f49019a41857abddf8abd7c1b65327c60f3fb1493379a3d2b6b8791d589a9081152c97a70194ddbd1c24b33f8423b11a3a03b1643aba08adde349c8d0a0ec2ed1a7028994ee21d785030fe7a29677f99bf218af930b18b27112148465701d1d866968b0844915d6cf89b112f36e26188ad47bea6107f37f0763bbd14da157a2030cc35b59eb456fa9256c89cc250558b1837a3b51215486a9eab63df27a9b71a9e799e67d0021aff3b80d2a27b42b884b8ec4f10561e755d269280aeaa9fcdae1160e2fb323c5c7ca6b1f1a3e3b0141929050dd87bcc1fa30b9dffbec338c91f6d4a5d37e2437df9d681f24807a7a92cdea4cb235583ccbcd3805f5032f111f3479718b37e513b93ec0f2d9", .None}, + {.Lcm, "-afc980d6304664e4ba42193b13535b1ea550d95f31d12bc97ead29768a48b85326191cbb69a8b2659f08b8b61640299c30dd74f6d69d9e5ecc9fabe5b2f7084d75f97865cae6a90f432ccc879fad437b0b3f5983446baee8baa1bf393421fe98676714b7fd7a935628f34e20eadf181a54c37c7a3c308f8a597c303ce1db55d10d6b7434118b38df911617d0dd558aaddfacec5c43a893e2c3af4e685fdc302caaa5f19e819a296bbd4e68eb5ba3502e2e1d0301f267c0f633b6efedff94ac594171a4eb0f6a36d45e6f972796c8f17227eaaf1e273fb414349e1fb3db063e4b23995fdf29c1d424fb6274954c2a9feda57ca2ece9111a53d49fb8966e5a4370617a33d7b692b714cec5f0bc34c93b54811b6d6bceb80e7c70b185f8221a3030c1584e6ba262fcb65cf3d397ab6b308d1ec6f3a01a128eada59e05637a1143b18b7f52c6e51bbfe16c24dc215f64c32f91bfec49986e42bd8527458cb9c705c9ac19acae77d07e96bdc2824a9325dd1f8ed5de604b3d1cc4f8b05e8063f9ab77fcee1705151cff55cb0e6a02b32b0c425ff2112bfa20649eefcd0c0e25295e469b955b4df8ab92d997c3b50301b02391d4ab3d8b04c56d511a1749ea3fc07e510cd177130520ff3317f184f6cd40f4cc30b6eb3c15629cf8326903b97995b4c0e149cc6517dcf8169b54e54cedb5420115a1470dcc6337ab88ebcefa2dd149ee", "-f4f7b57f91ecd1f3778e9d321916bb92625cb8cd152fffc7b2e38a360554dcfe6d45471dd301f59e9e1a819cf792bfeb88ce4ed8888692572545df4b983dea7ce5bd8d3ab2b00da7c0c4254a664b2f0e36756c2d9fa57b862526865973e4421fb4a2f4201453d6122b1943abe185765ec8e7170147fc795392acdc2606a0ca45cc39f977e2e85e16aba8118a654fdcf253721cd21e79d7a89b05704eb5524cd6b8077dc53f4e3f6cf944a06bdf4c62e217820723248e5e141b0d9e2fb170385ea2eb3490816da66ed6b3fea4c98857aef09821a6bf1760b629822cbe961bef71ee0f455470fa388c43709d4c3e5a96658c3bffc19f9b9f8ffcd936d87cf0b42238d417ce8390bc851e212e6f41338aea5c28fe6ca74a6185acf2c08ad07f5bf1e4754b01b7bfd46996935f5ae9eff2c229d7b34c8c1f107000457f61ce82a44cc9c7c43b0504a1ee0b1ebfd9c8ba3ad470180eeacf0f162b7b5e79bbdb3397e08ee7851c95cc2c56faadda87cd2d86eb8c50ce4a272cece4f89e183b6880334d08fdc6fb2517cef59ba1fb8b20fc14f15f1cb19e8e11dce7eac48019dfab1b4619dc19d72e9e0b82e191b67a8e90d39ec6a17966b69450b31a8eee06d86afa7badca2cb3dbc0b2441fe6045f6de6d25d67b5313d6e6596f55c4cfa951f0bfdce411f71a28314d4f39b0b08f2e42923628da52046643b5bf05a0dddb6a1f74a25", "1807bc681321f7c48cd4cd3160eb7a1aac7d7d678654d761c5a993e6a10f9969c20050a179175b6d1b5f235fe67d1d45885bcdab1276c5a9f370be513f4989cdab9ec8018be96f1a2ed949c4f34044bca4ac9eb78b2fa5896e156a868f148eccfa92a487c9b223e6f9de733edf90da270398894eb8aa146017a5918edc7979cd07aacbae262d87363d438f8d92ad5bf444ea2915ef7200df6933b37e43cc309bf5e225c30e09a63ff7ad5f8d37e9e6a195ffee1da72e3eb16b638623a845dcbbb45f69176f75297862987f59f1d3fe49708815f23f2f5707a0bd0e8802afafc5dda211d0aa099f2c42ac610cf7390f287b4acac3a493e7445fa8dc6b3d85182427efa9c013fd44547982363663e5f81907b48ae8ad96068c26ed6f9729ac36981bcc4615f39d22079c167e5e5889f76eee48c53b43365f4b826c0aa4e1654f4b4f80cdd6560ab84c0566a032d04b25a7bc60428220ca3a5edad637b8725b2290fa4e221a101f6714eb813fc297677a7daf3ba25adef34f01499d44721689f8155a138533759d1a367c53b64d231835d014dd4beec761c9fe3a7789560e731d09e99fed9e7cd46b0b38c9660aee101565663159950bf2ba51dbd8736296e53ac819a544811856485910b2f76ae8e6e0c12360607bbd5f9a8c8802f77ddc9b9a5a0f349e1458a51c3ba928594846a32f6cc1701cd668fa94c83b5967c97d8c1e82975872ee72d3d927ee7868bc3f924475e91958420b654ae482895ecad6bb99660a7e4a3cd0132bdcc3ea73e98699cb12cb127627d3903660b9153f47775e25c5697105dcb20efb6267be49189e3d60036939ad5998ca40b3000172b5c03e31d0f143c1d77510247ec3a389d2fd248e68374576c037ee6ee1ce5c9566ecd6f0b566192bd375bba85c5aa0294a11ec52f3dd714041b92e13805c45fbb7f16bcd917cee4bf830159cba3bf418a689473265976668db6c31d688e2b946acb9da089da19e8b5abeb1deb4b50cdbee9b9915b15fc2bd1ac87c9935fb8eacbf608c1c7d14740a1cd571c4e54b8c0ba69893a992dcfee39a7c074e2af33e4c7ce4dd71c711599da0464d603a830a905961c7976637e918dc528a75f6f95f4847f2be2917e0564dda745cc83e73709b6f386d5d200265dc613e845ab8fc795a7bdd28e8acd8b013db0625286993ad3e972ca6b7e90b26e75c8dd8c9dd8cf8df2f395c8f01b7f931323cf06b3fddce0a2453834b468b99740899ed2f43c516ab751258563cb263f8aae471cbf48ce09cecc4955e2374bdf7e3176bdb59fe1f4ec479857859b111701370b1dce13f188d237b19ba361892d8be118e7e67a7b83a07308a9b66953c0ca5a4977490b3b8a695afbc339d326821f0ff30b95be77a9d4f265d963f999408691b42f8bff0e04b0fb5ed06babae33b63cac9ff2c861d954a4de4a3ea", .None}, + {.Is_Square, "6995ed1bb0d71b54a31d6e50c9d19bb96f1ff7566cb125935410392b76efade2bc6e7d6f76e91b8f1b9ed6a6d1c4edf808a071092265d610add78a54e9d9f02775655b28b94d8fa478ed0257939d0a30c4a8e2eec340cec0980aeb96c1214de88991d521a000db9e0fc6b6fe40fa9f4203e4ee79bdfb1faca769c7f36efc5b95eb301c7a1a7cef1b03b7022d7b768e78e0fe69b7d28a41d091bc9049e8ac24ccc950850dc58ce8e9a3fb42ed14d7064832c486c17db4740be40db5adaf540d12df53e1b310017501c59aed98257755eb5f8fc1ed4f56c66405b9a485ed96433f27ca12014c789083a2e815cc01c6a3085cc034340718b64fcd0d583a4ed4f1af5d02d60efe208bd7f42030662c52765a3414f1b0f5943b568f6df0416a4babca4bd714b8213bac0b2fc00c68425b9dd705873e1a6febfe206ce8dc44a48b725a7b435651f51a33072cad0989b2f04255a1125d355fff0479ef0bf76876ba16bcbcb55b33bbccdee56967f439b5ac8b8333898b3964778a6daf457507c3e29ecc2323df74363834026d888aa9d64fd8ec5f2f797cf113052319b72e5c5bbd3dc8204ba5a28fbc5a1ba1b762bd814056481d673ac8d328527c7da97a888883fcc09c29d28c30a6af5c70fb8b0beb9eacda339628e75b9f36072abd4aa9b8359fdfaf3c3db5cc83cafcc771cc90d81921103ab21a25d9f692a88f0dddefa93e803c", "0", "0", .None}, + {.Is_Square, "9ab9b2ac406cd42c84dd884cb34ad2de1e6236ae330aaff71ec7f22562272e43b827324c2f07b73e03b0aaf8a2c7fb634fa7ab289db2775feb8fe07a22eb665576244c517d720b73fde8429593be1ce4e7e2896f900f67527ed30f85a29ee00fae30d7a4d9f49a4da44d56a081ffcdc7543ee3d0c2d6a33f2251b013a852552b90147ac56d98994ca12ba97fa24ea442f3cc745aff1c5bdf5e25c4274a147382ac95f29e83a97ec3d358d037bc24b68a90ac4f5c95ad1f98082f069c047a9dc28db340af8036a5596f7cb60b89c46a48b933d1752f5c8dceba0b559ad2fefe55f943b9c5dcedc371a03be1d108457627045ab093d00ff8d854ba1cfaa8b89250b6ecff235af0af9495c37c9ce038aaf137fb6ad2b4085e52126b9e0e6cc232543e3d950e64c15f44776d3bd1b6cfad89050a11560b8561afb62cfdf9a07ab4fd412d5f6c3cf2d59090a4e6f795c838ae1b4f845baf94cf3d651932fc1e8ae99c8510f0a93ec9c5256fd2eb9e89a1e8bcf57c64cae0b913bce30e8a92eb7ccf8f3a7be723e3476d35cdaf18232897bbb72fafd5768ad7bcb84c6f08ff57722d13e432642bc3985c003849e456b7a2305a265b9c0f8e21f0f7e47eb89b5c0461fe245bc8521b90ee4e093d7c2ac4606cd30ece45a3142d8c25698606e018dbbf9a204faf2ba52376ec00931d4d63e99fe4bb70ff204dcfdaa5231731e518df026c", "0", "0", .None}, + {.Is_Square, "c40357b9d9771ed8c3acc0cf1895f02dd04b9b6d5134bc71a6fb55f5c8f80493c22e6ac340cb5a67527f1017d97f27b7247639b6f11a455ad4e4509601feafc97ef3a178288902722f878a0b80092641e46c67d11e43ec95e2b162cebcec78d454eca645f458c7503c78dd6b807a9c2d588884f18dac1976d15af06cf1254e67990ee07bb7aac09254c2e78c2323d41ea334c4c45b3fc557ea821e980df9eef67130984a5506046fa984f67b565c9fbdf6bf4eeb47d9567697f903cde7f97aee5c198d70a32bcac30edbae53fa2e1c0b8e31f74867302026767efa577c20f1fd559dcaa174ea4a8b7ef398afa473af84866ff83859edf59c7c63271d1e5493012feb3e4b70ef15e0e40b01b73bfc8e1f656c5eb8e0e084afa3746bdc197acf89c3045b0c5a53230ef90d9dd6bd909f650ec5e0533e0505a0a62ff9a79e5dd364dbcf560f8ecc6741b37dfd1cdab369065c038cd26af9734302bac0f2c0759db8e6ba266045039665e466ad9adc818f9ae897d050e67e29bfe1422d882546c234a0ca2014ed2d7324d175f8de439e434ed7371911a1e35c387d6f5a13082d5dec26fc509b4d7469a2ed65691a9c0d5f5a3cf795782d35380a4741f00c6e1e43022d387638c6e77345c1dd3d821b3589fbd999b2024aa140528d22012a7d03f92e7b805e04b449af72e74d8f96b449a06770ae021669ea708c4f88253a3029bc20", "0", "0", .None}, + {.Is_Square, "504984f491a824adcf8b5c9400382390d861497415d780d7ecc679971b3b4ae166db99aee324330ce5e7728521c2698070d085693d59c59e43ae1348c4e337b1da34c5a44840a98bced4c779fd8f644383550d6c5cc179e8c2a95a47ae5955afb2604136c76fbfad78e72e7c38d18f00314ec77861fa9581daca0800701a44392e5443f7e7b6909b2046d3a31efdd67d9329a2fb04a8404f77562f39675f0e6e9c1c29dd6eb36a73d2d54c27d117fe710f5f1c3c173c4d4ef0c5b2fed442a0e6535649bdbc63b386e411bcd2a4eac4b3fec8750cf516dc43b0decb97e8271d678d99b04d67fb840828551c767affeda626c5864fa888a8ff1e1f2168fb228aab2e1b4dad9d573b6218ce0ad8e3cff04a4425b3b96b3f51922e902c13e639fffc626ee51dcd34b06d3539aaf6846aa87df44429cdae507a467726b8217e5dd6d472c2ad2b17258b1941df5cdcdb51424dd257956fdacb37a130171a76c6f4aa4429b0b9ed89076fde475c833bb187282fc33da48fe8b73a85db6ae62a3c9746e211b7342486989a951c69e580231cba43df72cccd908c14101d3d521e723d05f93e3a3baa768f792ad61f71eaba8e21098df5a4502466560e4657e9924fc9ce2d387602c6005c8cfdbf3bd26d4e7ff7be1d8e9eadbc5169af4e06b511888301a877b47edd4b30580fc9055fe4be837c30e8c1fe42ba85dc358a82faf3ebaaa28d", "0", "0", .None}, + {.Is_Square, "708723f3a41f9cdffb746649e028e8dca23eac61003e412d9c8333385651f080feb201337d0b60529635b5b53462c19cf51b7c132a86fb88431443a3dad2699a88494e7252cef59a206331f9f896eae3f0520225793a4414d17dbdd99a344e19e5b3bec8b182e6e03f554863dbe03a143c164d4c045fb8e01394b659fc987d09df35c1be0fafef725aec44aa62bf85bc27fff88508be430bf17eb748f2d8659c261c33c581e632f0270b1b8959c91d0eab1345d52d1f15fceba6dfbac549ce381d0e69b782d2e8344e851b7f92d4ddeea9807c8815d824ac4154f45bd696d79401a02f14fe36bc5db5199a2253c74015437cf31ce897bcd5fc2f7910a11d88596e4c71e37b6475c48f269b2506f13baa7c44e5ebead01b954096fb50a5e978d4ececf7562d53cdc78e063470a9f83e07f63f4ab0d6082fd416f3c810fd45a4ccbfc019c58abe7e310689f633c13ebb831403a90d72fff2152f7b0d909857465d651f9231e4c28256973d796237c3f50df0312ca6c7da5180ab589bc824ac148fbfb06e12004720d94a6d626e8b1061adf11f11d0f5c74d6eb08785ecdbd5328c93abf12d9cf52611cb29cfb5dc641216a458f946bb680f040574f363f11ef8a1c814a6662ab80b3ef20cc56ca393ed283255d0a148c23c43e19e5a8157b5784095d956ddc0dd136e8ef5af52ba080fde2542a853543e7858a9c99702ef0967e5", "0", "0", .None}, + {.Is_Square, "223dc4d22bf7ef11144bcd40fa571a9dd8e5ffc4be59d19a935b1bff6257752022b3fd64a21473bdf59130ee0224364a82c9ef631bef4384b673f6d2a3f5f2dff60c042add6c9a182c875363e9b2d74b4c741db0ec60c4af5f40927ab3acca91fb81bd311d1562f7fd1373ad3409dcc06e3500273bbd2f7140b9e6206df9f51eee7db51e76d16a70d93ebcc6d7a372b24e3aef44f7659df3c9ed3cca63340fb71997722931b3a404ea873acc880587abdd3e908c1298e251f1df0c5d7babae645c25371adbaa0ad8a88f233d0e4ee6f935d5d4da918a89300517bf6ec9a6a0b01f1cbe1e21b4c3365c2c9aa0c241b99349ffeb6732abc80deaacb6e2e0a0c7c22dec3ee7b6eed4a29fde280d461c089032bc2affa645b98ca5c82d69fb7bc04db4f4b2b88ac4def985460923337b8aa90aebd75526ca9b7f63a2b41cfa12c23cf4a3d21337edeaee4ae16fb2d4bdeb7654b0e14e4ccf18b38fdbd5a308a83d0adebd806b0d47879e3b94b96a98612d6911d9b1837c12e850b487b69ed4e310f567e7edae68a7a5b5ae815e7585edb9937ab04bd7b0057e4e2e4e0f3eb200ef0c44dfc5f059efb89364afa4ceaba8ef3e09d9d4570b1efe9ad5add37ad847cad98a067fc5cb450676138797ba72144b76ccbb78e6d984b746d3c5cc3f3df3fd9914899d68df3d76fe4c92cc1f3e95b78186c3d2c59ff06c495d4fb35a8cc94a82", "0", "0", .None}, + {.Is_Square, "dbce22195a26d6f9e89e8d638e614e87f1992cb77fa37ba3d1f7fca05b813a6e38e8dc6fd0b0311158ec351c9358b8c399a11898f092187a9077ff4a63b654f817cc1bd2b4e496616c193f91698b9d1dbddae492946edb6526ae03b108703922e952f49223a2cbf6c6bb5165be1a4d48891871b2fa70c59849a36f48d675814dffe65b08068714a6d347e01b3cea607feeea27fd97b89b539d8fd9fdcdd8d2b19595f8a644e7d1db59bf5d09f28516ac304d9d7c3794038ea482fdcac52c045c380b04291b055a07b7f70bf0dbce1c0f95f90567445a67f91eb303354ca3c93a60c2b2b70881f61c2946e7a1281fb2e6690db81417d4dcc2d77168ba0ee32006b52309511b6667c90e4e630bcf61071bcaa0535cff1b9e7daa0168445d55e208302d9867cd4eaa499e7565d82d7e5cdd1c1315e726093dafc92f2a3c69c25003db5008bcd5ecdf87cb93173dc1625b269130ee956dfbd692e5af503fd1dfed3fc1061990300aaf53cbaca8247809dc3c9970a68cc5ae9f7cf4d057304d482aa7310d61f4fad4e64a74b515cda67845da6f372f65fd9cdcc8a4e3b249e95cfc51694665f82b71c884f1de5897eda31f98e344f194c41b0096376d9847551dc2e29712a9c1caed477db10ea2cf14b937b7096df8ce7e2ce715cad561881f36ff2c2085144b3226bd9c58301078dc3afff54701d8d62ddfc33c9dc90b3c4a1e30f0", "0", "0", .None}, + {.Is_Square, "610f5b09129681ec72476c333790f0df143a385e510fe509ef802ab4323680d87eadefff4b9eff7eaceea7512f582c2366952204c9d09226c6b464f419424d755b7b0837f89f618c30346c3d7d648a5482d47285d0defc27ecc8648668285c916e8a66f2707d944ac34b83d11cda51e2ecbc13126b0d6fa6ce61be04f3089c81953f8ef71a77a8a3824144b26325982894b648d10b37e890734027cc21dd836ba8a3a28c22d1f1d13774f55e05224eef1351399d7a7cc31d08081573bd2f18a939ce13d61d639dd38e32a9bd3a7c2f465e60e23f2c2bb7f25f2920c2c1784cb5195188b5c293c2cd316b3ade094c307c8657ff91bc95aed037fcff1c5804bcc9381cdb4f88452d874faad66de6b2e9a4d811b66d3c1688e4ba4e3a4f1b36650e977351bec6a2e3fc5aeb4a8caa6fda013500171710e8cb204700309e3541dfd5a7df759f71862da3660ded6381e29c188959fd1c7f2d7935c2cc4f4b2615a8f39356f34af5e036bfe2b209e0e0e5c13b0226ae98c88efd1a7397af8f61d880908e5fbbc0091abd33f006fec3bf245d02e5b5e335efc661134eb5ab8ab6a9e2b0f03999e6e993b08eacf5afc54d9c753d23e78098d80102642dd30672326414584a32abf3dc529c50113c38541ee951b8f8bd868ed34c9c09acb6c23ca07ac0b4fa5f355a4b53db696190fa21a1fd9b87b5710c5688af790448f9cad8a938b629", "0", "0", .None}, + {.Is_Square, "19d99c4975973a1326d031f9b7f52a45d959b8b1922c71ad0a3041547b81514477f6408ee98fe5e8ad47a9b90398ae6ab54959592a0fa4b1d670ddd92f0a24581e86271bec2f4f68f0c58df6ca8b3891861032a2bd86ba5dc49290bce772a3a2115106c1ac3a439c7d02dbd25a644c1f0538f1af2ce76b8926a6f33e33e3c86bcd40625d507ec01d249468105f689c38bc4cef851916990a77cdc7789fb674c2a4d4dfa80dff00afd53b4586469a33e54ecfc22b9f1f6c824e97d2679a63b02085a00cdbd4b963ffdd84f58816fbcf3beb81d61b99d9bd04964739d9b8f57440593439769068064a0d34f6ac55d803e714fb876082a8667e73efec6c2a843b1e1d7b3ef2de83e5a31d66ed26b336500d2a0d4273e5c26e88701e3396e2d2aea654cc1792823a7e85f017ba59737192120c498862503c50f469ac8f195ffee4974483b9f7e836bf9a08336ef9d2008c9999c30734b4e3317f20c5c7e5df435b62fc1d3fdf2eda659477caf58257d368e8522ca55797707169a2dc70227b3adb64ae4d8dd946c4f1ebbaa66179a8625905eadcb25cb2b1d917ffb22c6b0891b8dc45506b8f58a6791b390d340404eb5cb50d54d3aa83bdca45fea76ebaede11a7a375889918bdd0b9e997a132bcda3bff2d4f3deb724f26c640c713d0b11b1fd002bae51a51b07a6b0480afc6cd6309d54990c06b98527689e2c0dc0a27525bc21", "0", "0", .None}, + {.Is_Square, "4348165491cde1126f35517227d7d65b65df3114c76d730965df89109238161e1d2360c079abdd3f1c4012fc0a24777c2fa853bc67d5b2dfb49e5e9bf29b2f4f2b25ca1d66783fb788700861b0406ce37997aca70fc0f1370119d6337e877d9178106c18eaa0471691fd7227ea27cdf9681eaa4207af7c5bee588ac3965dd70c166932ca7e49a6cfead7b7395a062c858c46205bdd6649f2341abba4ae69d88ab1da97cc2b8fd97823cedb6d91a7ef0134a1c8968a8b4f0dfa01c36316d89f760c52e4e8c4bea16718c63f5fab43b46f291596a988ba71f5dead95ef3ad699efecb676c4c9bde9db52b85f91614fb6ed59c68e7eccd0eb5eeaab21b0baa3d5c36bbca364fd286726cb6c0e994614a99c36f1a7889d516ca4451ecf85a589fa6f24659dd99231b5cad53c09bb8abc7a94217aff363f4a882fc45a2661ccac4c6fe1198252c1908d841078995081815847d5adfdf16b146bf47933dc9902b69e3bd7da401c0c5e95279b18a305f6f57b01721db41264b5d8b3806b9bc5eb61f46e7ccda9d96ab3eca21d0190b2e2dadfea61fc7f2f8550c3a5acf752c5a2cb2abc4c6b1e6846591d1a93a05dabbaa80d52da7dd22fe9bbed22f158a319f47688e5fd2ef4e38a7391f34d4df303fd39b031a7f2d6378adeea610bf958b94f9600df4da945f2e7393f68cd2c502aa281ad2b0d27f1139e54f5acedfb87515cf93ca6", "0", "0", .None}, + {.Is_Square, "ad9d114e2514d6e8cba7271a21036a7d591c7aa401b172fac87d2eb61a60583a1d27d31722eb854c863bef91a40452ae892e5ae76a793ee9cebef9f632c91841a57ab728135d53723bb2263461445aa918c90d27191888ec97a74223a0fe256b4f98154eef18aad58ff2c7cce25ff1b22e47dc17cb602d6019fa8ae8bcc27cfbfb3770bbeb51fa21d9b25b70e9cd352d215ad6916601fcdb70b0cc851dfdcaf43aac1f448e11cb903e9408c4c82430c87d73274f4e61afd8b47d4be2b4fa1390b7a2009997a555f956fd8a74e0641a13bdc824a2cb5b989bb7430eec6c58a3de8d37c2fbabda628515a9e9f519b655216612bb0505bb738692212db4466a6881268cdac930f51af3abd6f976da9d5df425de5955dd76e04086182c16c8fa01917d1365c645ecec05a3d46cd3410595a0c06cfd7f1cdd05f88ec3f49d0eb24a5776cb678dfaa2bb9c00d892ad86c0ec542812eee77ad46a73e51a28d856cbeaa00cfd60af4f8d6680c51b42d6019bd89a2a1ea0a1c625da584eac9404857724a5e9e2b8a9d6db94e1617fac0255c447d3c8ef1fe3f56114bec39f305f8128fe05ef041573c03a8debbb66cdb2c7a8a9f2e64f3692c8fbaa1b7e5cb242e5a971bb8d9583c6dcded5d3d0950612ad6a0a7e530d48a7e26bf46b7dd7714af0a1e3cd9cfc18ee1118713e932b6517d637328a2dfafb83c5566b398ad6c46fa358744d", "0", "0", .None}, + {.Is_Square, "7ba47b8b8b1faa3a53ab7d66de4226685534b0bcadd845d2c209f90bcd4d26d995968abb848644abea6452aa34ad804fd17d17da9f270c4fd98b89862e697f5ebee519fe95d01cfbb2768f93e3f8761141b3c81fa6600605c64b5aec0d1802acd89168f0189015fd049e82bb685a816b6a31527790a115c29d025517e3e32b703acdaaa39933859b92441ab8b0ff4378b270b4c88805cb406f0c9ef171ec6ed7035a19f6989c34117cc40c314885eab28a8c61b184bab8c6ef5ec2df5f8e3ef2c31ca20a765b23adcb215fdcb3388e8087d0128988ab122ce72fea81df0cb91663efe5e2128bf8825fc0f715f0c49f79b25f6d96b0753c32ae15fc045275b6d7b5447775ea31ef2158c86ede3561acbd5c3ce764d64b8f197915a876ded259fb353361b341833c3263a5139a79ea0466f05d2a647e41a386ec511989458c90163e0308bd088aeba76a88e3a81aeea8293357c444a05c63a6a12e7ffbb13df5d0d314beb321cea372eb91138adbc6dee12dcc07389f1ae3e36a345ac17b706f90768d3ced62c19f8de5a79a79f2742747328095bec6df571e273eee6390f92b57773f77a184150d12d4d22211a9a5fc688fd1c267caae0f944d5e4af5a9b10e4cb95805ad6c54875bdcbc840c87a641449b854f6dcf29189b5962502091592bd67ca792c7e86e0ac8a709ba91868b63cfb2f0146487670b935653208e77b5c96d", "0", "0", .None}, + {.Is_Square, "7fde8b0117bf57f97b22325641077a629ad6a033a912b26584a9b70749e85d919482418182ab4d35347c8cc5586855b900a14e24a8713c07a17fff2e4606c6a054abdf394f73b9dd2c71f59256cd7cf053afaa200f11e4230420c30d935837ac28806dac2e7fd743231cca6936f86d7b190040da6c40f37071cc6791c0ffab1ed8077eab4566b7b8d9c9cf914c168fd3b56081ec3b91bea8c78320eb481c422e38a09428c2e15192f34cb9dde23c4bdea8dbe8d07380dd141c66680f20a4c101783b50706adac135e83098ec5d19685d1fd89900570999fe070b62e3beef36bb270ad4c109cec92f822f397e9f0861f217e74a020df259bc1548948bcecfb1542c7d51123904b5cb6270577e4e69497ae0965f373ba867348604c293347e201cbee8de14733ee94c4e4dbb54388f153050c73a471cb4fe523c9e930bc87dcb19ca4d0cfe1a944d1807335c05f4291fe5674d79bb030eb0eb95b4a9413634599abdb44df2cc5d8b8f0d3859b05241841902e20956fabc924f00d093dca1f1a41768427f94928af8005c8c2c088df4b1c6b56221f40648d0af70245ad78d7547d991ea542629828d960fc667e383c6632fd208254063e54a79ea8638116c6a5f7660a445dd47d24575f697275fbe2e8b3bfbee7c9b1891e66461beb42e76ed99a9f97361ed9c0043048a8062810a300bd6e4f16f1c73bdf666c940620a24b39dc5", "0", "0", .None}, + {.Is_Square, "75b478c8970a180690e199091a3a30d91da347a3d1ec368a1e788c79b613a0b244390966e79c403a5798271e5a3e28e6bcbca22df6f9e323f0fee6dc1bf93f098aae1c2a5f42907e59cb9a089228a9d6ad3da98d6f2b923471faae69b9d933a7e1f79459c95e2fdd7df5279e423ae3f5c883d64eaefabf67757149d894f60d772631cf5d124e5f66a99296e94af76891d1ef4c0d91dd6d3b234b3223b6b5e83640fad9a56e72d9f3699a9a5743a9160fe87277ef65c1ee2673b59809a8eae396be45946e0686e3510f146d995450e7c1fe484880fb60250964dc46848c3130d058786a9c4671f215b007a8366490fd25f41269e112640472ccefe3180c42cc37d90f845561eb75c4123b3af2437cde62e83ed931a6298c4c85c891253aaffd536d83ec2431aaa17533c10b9887e950b522d13125bd2654c1662e70a1fd5a4dfd82740b88faf2bce9136ebf14c452d3b6bce54dd27baa84a5bf83413a1ccb3dea2534bcff6fbb4d28fd95455d2d677ff8cd47bc2c50aefaa2ca7db51a7522f2aa80d932bd035df20e0047d6c4df88ab8991992f7a3af802cf473e88cf4abcc1832ccc8d473b1269e2e73708a48575977308cba4bf6f49904577bc36e316c7e66fc9903e6d4d8bfb473601fd3deaa762edc67e7af942f49311546e11a02aba6f91159a3dc7315317fb47e317fd1860501bec55151eb3cbfabbf61b07cf0108f54a", "0", "0", .None}, + {.Is_Square, "7fabc9df676b8fe3ad4af0fb19398f83c2a7c0aa96c03e36e6fe1339ff575dd52a9b1317706a45e49dfed73c100f4dcf043a20f9e2d19ce4c6d9f37df8f0bda8f99cf17c26dca21c0cb2495dcd5527b2594fcc14199e999988a487e0787a9e421a1bebea6d2db6ba922e2d9d8e9c71e988bc8aaa29e729b128793a3094d4e343366ba1fd2de137a938b7da0c57fc4890c66398f5f1fa1fea6113dbe3a8c3ec609c6339f570b944adfa64ed431deec0c08a4291118f429a90fe5a11af47ae3f8ed311a8caf846ec03b09854737c575845c4a0220a9204505fa3ed3822cf4ca16e2aedf17cb001aa3ad84ffcc74d491d1a8896530d8d1ef9cdd3ffd8bb482d3bef301277f5862b962158883b5f9a33da05fd20589e3165b02c9b32b87f91ddf804e9853f0905b0f3031b49484e1c737f1146f31ec120f7509535db325a13b9ce228e765217108bfcdbf57920db4077f4e1d8543cfe347caba6ec1565aa8f504b9facd24974bb7ebe89f32fbc6a2929e5cb89ba164e336343d41579a03e5c18edf410c306bfe4c26d2be4a3d248570a88e09dd7d25fc957ab2800a61867797bd1ac59686fe837b20e843c241700bca8e3920efa3691280dbe7baf8cda6c969e266404fef010772f04f242d2389f21a48c38dde01d66a2305e9b8bd3f7c32671981e27200e14fa53cb5c2542dfc0ca771339248b23f33e8c4f63c3a12a24ec5178f1", "0", "0", .None}, + {.Is_Square, "d3171056e1278413a68295efa8caaae28747444658eaa5176f985409b74112a5681bf6123cd216a466b2f9dd6f232717450f0847ffff71704412a5660c753e04e40ad41a5df8045e4fb94d3c758fac6b958586970c4a026fc98be95a7af993653a9eed9fc60609fde78cf136acc86fac6983e7eade6c3814d5756c79fba84cd712db45ed35e4cdeba1f99206247b3fdd9fe0316f6b3f6feed7599e301ba6fcdbdd54e55f8d9ba18129eb83203857495ca83e422b4d0ca7d0337a6eda36af9b6a862d3a900cb613708cdb5c6bad5f14a5b9d2fabb3c0eb19420ffba206737f38d640048219892f4d62e437cb0c400d9a9552a5cbaa0a3c5f9447f6c67cd9720142788452dea88a08ae240fd46b9ea131c55ea7176441bd8bafe9ecb18f00c047dfe0c6e9b71bbcd943f8caa89a059f79f549f3e935ce18c2ad29cb485059ebc32e689911df6a0228516cd60503fdac32d2c21f307e42b47313efd94f6760564c4c4c26ca8b15f04152218cc276d8a1a8df8f27fdd2be71a9145b9fac2602febd18e40d9ac997b3af6cb2516a73eb729b8578aefb7f3f2701f35b1bfc6b53456c6a3980040fd7b5e8eb68d6840df29e2fc740e93c4e028783707f1c886cd8030c55217706a825026f7249bf6afbb06eecb5c4d4294d502e1b4f4d5a675459bdb438e38d6f368dc926b4698649bcd8b0add0ca9d72c8165916a0ef04569983419b1", "0", "0", .None}, + {.Is_Square, "ee533d46991e1963908b14d37224152a6807b06cce18a383efa72c9bbce365d979ebbfa10c0bb76477e2acd62428eff58ad33c840a09873ffca2840d7e5f222b8d885eaa082c3a0ee6c5e0bb84958bf998c159ac98ef674543e16abcd822a44ea844498b60d3872daec18484f6d877ce3a3b85db9f5c1bd2376b3cb80baa755754df649eabb32d9dbee5781f63bbca2861c69f5752e1a769fd80c8eb0ad12a7220e1293f0300afa1b9e565435d5726b216dae20d202ce6fa04a1a7d2ed9a0cc2216520db1d7321c3031c30f4d44d376dbf599f9638a7d5532231a0dc577b5b579d322f3006ccae8d3622976902139045e8133ea17f7f42fadea1d3e3383c4afdfa4f8485b76f47f3798cdb3eb6640d04266ee1dfbe1414bcbde2193ab0d31e698c78a57b79f7f99132d4ea03e81df23e67cdb01dc6c5be18375a159de2004c7405e4579296a0930af0cec9c4e3484b89a3f84eda9b60c6eefce14f4a6165adfba179cdca011ad369ba8fc5e296c6c6ecce7fc14f09e7b275a033d9b1d6815dea469cc4151702e157d5485b13a2f4d71c5c7d37fa4758db26dbc9204527014cbbc75c8843efedb67f3dcad3579f5790fafac569bc6e5af3ffbf8f34ae92cf69adb3126e04af185113165c6aafdc4e76e07b6f42d77c4f0b39a7cf809726944a15d5ccdb38e5e1d85406244cead4499d0cfb84ebc9dd86709febd61ab93842757", "0", "0", .None}, + {.Is_Square, "a353601c53a15e9bf27d14bf0d41f768a7f54d57b187b67480fcadd56c804b2f7962e113109a7cab5423931e34578d665b7aec978112a240d08369603824856954e28ae6bcd76291503c8f6bbd2b353d8250fd5de303fb27f9d6d9718724e97a0f35b20642beba562b902be2ddbfefa3fbc9b60f7014356ca6d5b4b6e0d57ffecda0431cbb18c1cc316ed9e2d4ca17a427d2f7782fb43fbb3b9a5ac9574469f5b33ba894b11277253e21c222512950f9d3574cc6e0fe35eb5209fd9754becac950ea9d4607f717cf335bf7681e65e2b6958b8261a59bfadea75daa26091360c5b8b44dc25f0fa803d7f858a05419a7f07f25f96ba1459893efc5eedbb35d9dd54cfd4c07fd147e54ab818ee7fa752d17ccbac12d2675ea64d972fb2b912de8a4f93950c8c6ea2e868aaa5e9c29eaab6c1e0a7e52bdbff887e041a072872bb4416a5a1492915ac4ddfa9faeadbb989f62b2144973801938d5301b5d637f65a94e9d0e84f5183170c2cd5419f6113ca29311e1eb2824071df567171bcc47a12ed55adf68632082a29cc8d6d8a1b55229b20a0c4a18546d4a034c092d96ffcbb1fb49a44fa35eba7d3c1c538ea6998eee0ddb4d3761e2327fd0811f264fcfaec6b78c33c7f35d609f3200e763fc069a4e04d375255e4af333d817218306dfbffcfbc8454624ad61573031ca9c743665416dc53c70d835e2dad65a888a7b1e2ea472", "0", "0", .None}, + {.Is_Square, "60a7b3d703580504ad79cc27fa7a95deb53db6d21fed140310937395c1eb1475e31f727d28a0f9a6065ccc2bc673264f0fcc0acf5f376da320086d5e73e17ce80cd80bb44bf834dd853eab4521a8fd84ab0f07b9c2859d52ae7364d98d9ad109ccc119829089ecaa93aed18b80a25843de46d806c6d0f0ff63844708c8769056902f841c270210a38fb2ca5069ae1ccda9266f5036c548430c32fcb79b2767c7293b298610fc6b5bda6b22dfce05fb2fc228f75d51cd1a5682affed4cb60fa224c3b69b5017e8ab573dcd66562d44f191a551852aa9cfc63913e69f09e0d44573686fc575f71901c2b58ed9bbc323dcb89284fd4106809cf2dc96b45fdd3f1f652bec0fda396172849a3beac4ee3d998b13d8c9c4823936a40e11507adb1a238712d735c5aed6f12a3331f3bb21ace43a129083a02e7e9160540c733b57f70a78b6dfc8e093e8c9da4de4efd4fa33e4d68ee4529d016ccafe403fd29784618a63a9f833dc9f29c7090024882866c73e12f4a561a31ecaae5784ff2448c6b9f8f7ab3ba5dd2647a425de5a6f803b864ec1d16642ad2f1de7e263e267efd6403b7068e5ab8f4938da18f8fde4aed8e941cac92258f6012b792af80c3e870689a18e28a1bd5ae9f20780c2d92ddaec25a6ff74e2a3d88682b9439441a72a555a9ffd3c7a46de29b0404e15beee667ec720bdca09f24f148b1fba914e67d04272529", "0", "0", .None}, + {.Is_Square, "2064813951f4630df4eb31c239927df5ed055dc12d774cd495242ce84479bc21ea04f131b9dd359db9741824a41401705ac3d004c0c483bb0f8c88897b41807bc73d2fbf33294634d8fccaa614b98b3cec73697f4f37ec3fbc08d71d7ed62fd29cc42217bdbfbf44cc0d935611fa54a19fc819d39bd68565bf1099e604699896cec05acaeab404ef54492b9031f8126ba1b5917719f9cf44a87ed4118c93879a2cee9e6e59b035385ae3f430f323cd15497d0258d012e20525882646a29e6a37a7582823c068c63cc672bfca8b29a87b42f53bcf1290b69fe842f9e29af6193445fe37149026d1a20785cdadf5e21a9ab1241d50342f4089f0d5c92d5b8c048299a399a50f1c84915d6920a901d6ca4b5b953814fe8c2101f40367c8d2a7071bc2d5190b6f68dc424327567ac73c32d2547b6f2e63c613c8e861e7491f5630886ffaac74e7916de00d67e104ba66ca9e7bcee4e7e4681f50a478273053ae4e574f1ecda89e33a2c4cd5b20d6638ec4b238e250e6b4f08170971be738f85ac47d6a92e278307a26214e2802ae34075575752ab957169d37c609495558923438840cac3d815f08062819cd504bea30385b46b51bdcb228c7742c3abd35090782e5fcb23452fd2d5c5f110a4d642cc1bf174185adc92319e36851f5b18cc876060bdb820666bfb4f84436b5b49958b064c26f4eab9a813de399b3601463280476d4", "0", "0", .None}, + {.Is_Square, "503749b4049ba9dcf04fc3f2852cb72e5b9ce3b6b82617873efe496ce41446ab84fad10e397e823b97cbdf550afb30b7480d97c01e6d7341c5fac38bd7256c1cfdc8dd51dae5ebd44b4a76cb688f61a9d98f3eb2ea6e0e45d2686b1354b4bb75062e2e1f5f34695debb1e6ac649b09778edd081873d064193f37e422189b86479937450e48ec69c3a601883dbaf6db802024a7a2bf75e2aa9678fc8379632f1d25c0aa9d3ed3ea01e3449f6d5197259ea91932a79fc54b067edae0aeb12788cf0fe44fbf73998695ae5a124766cb5ac738b532342c40de285a7c354cf9361111cba8a75a2079a03552cade58370a848718e2bcf2a4083951ee8811979748b5c21911a37c9573dbb909e6db97d0dd791f02d8026b485511e628dca51be60ebec42649fba2c1d9db982e3e0cf2236227567f8bf509fc3bf1dc98f475acaa5837b84e8f4a1fc16961f512532e163d70ab08ce5f44dedac14043f11da7ec74435125c03f1d035ff6686093e4c02660ad269ceebd8cdaa6e401f43865e7cd26511e91199ec955ae081db77424ffc27211c27c92d1d87af0de9a149c6e9500af880872db07ca1f432868c03ccf4aff6e9deb9165a3f13ed839f23bf6ecd69295430e4c624dae9427f8e6234c0fecad5ad3efa0b086a9f194cd02500e327ab65e5b7e0471c27d7157574896c80c752e6c7d26312619862bc60f4f12ba962da0c6e27814", "0", "0", .None}, + {.Is_Square, "a41d26a58002a0404e7282ebf7124fc690c9fc2cf9cc521311b8543a43ac922fa168ec43d62360ecde8a8ad3a39da86be77c6e31bdd1889f88bcc8d1988c1f9e71efcc28071e45a09f61efc7f3b54ac6e9dd5dd70200c7ce1a314d8875362c43e5c6737c6c6cb2021931248f05637303c7fb08fd059d4fb309870bfa90534c05238768ce011cb0660cd9816d026d4bc92fc9f54876d290b1d7d89d3d12c96dd0f17c8e08cda97fd5d6649303bc0d6ffefcd4ee314c6f0b704053168392562228fcd92f6a47bdfd5f5a96d875254f53eb01f38b7844aae1efe175fc2781a7516c05047dda3df3570f7c061a3abf48f909b5ee4bb92c2f3be9d809fe1268e256aff0e102bd24c2148c67ba568d372c5a326480e8c0d5ef4063f13f85b15121e73e45006b16570bba2d00f090921cc9746464afc84889841ad8965597f4ec2af492bca21e1080827b80c83af280032607d022d13018142040c98a5d7b510f93db4e07f6c6d42d46b28e7c51c8b461807c987ee56a43ad35c3a4882f408eb3328506ec0f39386ac4c9f9cfdf07fbba5cb09c7e8ade5b7ad7431ae790213325e7183a6b20373e12b914abaaa544475d536c461687682b29d0e387884ef69ad6fdcc442ce550aca2b9f3b73934f4b0052ab950464bb4224e65a26d9a3c75576f8fe155414032cba910866998e088cc2a3b6dba781775f23b62dc72386ed97030a1e29e", "0", "0", .None}, + {.Is_Square, "9a5068bfd53563a301ea9f6dc23eb73ea4e16c7242e8a20cca54d514487d7f33835efb52c6767509917ea3c8c1560deb57c61b52ebc24ca67bd0143caa3e5f82b6e1c9a19e24834ba0413eb47b58b77dd36d87ccdc0ab0a965ade5cf9b47555fa8f520da44bf27d247add4e751a9bc33c0e14110afd958959d0d066789a8c464283f87a6660ebc1b6d99fa1171031974c556b980f003a969037935a6cb2d849f3c5f6c2947c1498bd4cde7b3cbc6c9fb6d13eae477a298b3c4ca8bd119e9611deef39afbc3557375e7d37df70f59fb534ed3ed977df00ab515f95aacfb19728302919b66a8578d3049e95ffccb9691f54bc2cf4e7aef66ef14504bb193c04b9c814a414046ab442faa40fa83ad9435645ff631e2446234649734a1d9a8c5b0c58735f9e018833ead5d72247f2f35aee557106dacda7c52e54afeef472122607d486295bc1745afb4d20250711f9e70b702a1233d536d973dff414dee6c4aad57ddce870194b0a935510518c28c76bfc06e56ef9fc7cd240a83bc62b3db8135d0d29ae64aa6d9ae63686cfbbb1c2bc9413ecede420687511d5f3efe32e3057ac3f62f96056d7f74e35bf7995da69080a27ce0854f8832c4ac07de6abae474de248b5bcd499668d30ce93781349ddc78dd4c478da7ef1120f7283a53afe4623bba73cd62ecc125f9125d386875cee9b1e24e27cc2424ac1a6f7c243f8e14b4e99e", "0", "0", .None}, + {.Is_Square, "63722d42e8e9115fa8f4fe9117599b255873a1d1837adaa58bd04e4682b858593f04baec48134bb3fc851f60bb64c4b18f564743244c4b820da0a4c9499c0f822163164963bef850ed6b9ad38f473ab721988d286b4d4a2b9e1d337120ababddec5ae8ebfcb733d985a4d574f78edb86a32fca11a0c5471a058f8f39137300cead22e70d009e73e474a92d6e525a2e6ca75831e1f82aedb4adc5914b1947440d6c9f3758d619301958896e4427345bd6283bc46acdf2dad271a86d884bd6a8de046174cefb6c5ec781025e823a1b08d24152122dc6261f261cbe4038a0e06fbc5e10cef56686125288760f1968c787a367e8d46767c34dc384725da4dd1f989050e30ab44315cd6f4d6ed852b0cb546b0fff380b99f82d6d582c1d549184ca5eed65768b8ac7e9f0cf2d6e0ea74166f4fc85d1fe21bb60c4bf2563506a27def805c86cde358906a287a2b03597118d02a24a81128b3000f6a42033e70bcd47bef26fb3af3b7823017a50c458d8518d2c3cbe6b62f6aaa07ea0b05b79844cd635154d604bd2958bb06e0b1c2bc89065f6b010f70d8796abd7076b7ebef8123d65b16a8ca5b07be9e988da0857f1a7815b457340c7aa06d399316c85df6688221ddfd75fe7e23a98c64633a457448cc75f6aead5e1c920ddbdcfe249bfe67429a10f57f4106fc64366eba96f5036512d27a71389d70edb0332dd2b3fb41cba470a", "0", "0", .None}, + {.Is_Square, "9603ea1022b332c0bb2a213df530444a7d7bcac714fe39c36c7067b7db758e4c2e4858ea1da0ce5f984b0cd5438c123233b691280fda5bac695267035584c7650aa5be1acd0d71416112279764607e314f0aa67cc06cd4a78dadd079f8738b9fea195611655ac6396d95067da878412e1907b840e5d9e80a76a96878d3ee1cea28c87f97eed063da73ffc5a7575569dbc6045bd874785d49deb375f75b053f923174c1e222651cc47ac5f0a1f2d93278bbe9ba1f04cc0e0e58696c4783661c773c7ef99e76536c01e56e8f89a13f5e4b122c275b99c6cb999391ebaf44fa9748b7f7006b65e10f2e0a00c5020d4464f1e16bff5364d3144386379a5f16709ef8a84ab22994604b5c2ce7822d5d77da9de45a567d4aed7d4d9c585ce2ee3681e6c113673047eae33decc24b110be156f26b614a510d4daa7aeeabe35b5798bd10c7e9732e182ed77a9bed10e2f5e30dbb8b5540406af0f46bbaa8db6d6bc31b733c0e01a36be1eac87389d35a7394f979dea4ead834df1f2704a4073f64925426a818e17866dc1216d1ce8da478d1d2161f1ee92d4cd11c385678bc912adbc18047f87b6d2f296e211dfd10f0c1c188389104b77c1d58459a64f94c694751ed85399a78ee64e5eb5617f79bf96cc3ff7b8c369b5db6785068764fa3cfa3cf9b6e03277a7517acda44a7b04747cc87856f39f8b192130b3f67c3108f9e5be7a491", "0", "0", .None}, + {.Is_Square, "dd7478f68df82de850496aa886acc583d82bf5947cb33607314e5b2e17e6533c70582ce4356004bc26088eab8da4849df981e26581d54dee6c6bdf7a9216b3f1b292f530cf99b31afb34ce374c44c6d136405e05740b8233269664686225c1623355d7e96231b81d02bb9199f1987dafb2cc51861a17f0ce764ddb002f4fcac7f0c6a3744de30c0ebfdba1389af3e9e74cbcd50f4c43fdf2d292e9015cace98fdffbc4361560e72c882cd67b50fd67c89ca5d2d3d0e6f07244fe25b74f11c9d7bc4128a64073b0ede617d062d3d41d5ce4193461512cf826cdc5ded148630f6684a02d3d79e95d10d894d1d4c9b47d9d2ad5c882a6ec43dfb7ae40673eb4af8bfa24da73d588aef7da1eaff06114f7c27f949f27796649157f5fb338b0ab6e5f7a2584489b8647e32c8169a708be01a35b94910a6757a5c6b03f69b7f089856029a74aa1045a636a00258a423d330dd29a46081178b195e6e107196690502f8c1643a99a86de64d14274d06e0fa8b70ca38d0d147c4c320f6ff3a8cb3e81c71c5483984abf9f700d8f63c14676e0a76d41ae22477b5e445b264547a9ea160f1c2a50e27a35eb84e8c1b19fd9a31a45f6ff7abe30c2cf92cb617ef2d79163f09c4a5c0f4c44d1bdfb102f4201223b27429da6ea1970fcf9d8eba06b800b8ae58334ed1e8008867256df39c2506c3b072d0368fa1d78a2c8ba12e538bf75607814", "0", "0", .None}, + {.Is_Square, "2dd67d25a245fb0beeca6a7ec5ce0875fc3e33cd68a52c74f4befb1044b3e20000772119655744d13ccc433860abfa6a1a79581a88154d224c3382c2373771b0086cf6f4f10ae6564c98063c1ddd300535f25d79553ef872eb35fe16fb01187ae87f6b9c5f6a60f66a6111cad226c43b1926a6e7dc0e010892e6e536f801f1f808b7e10f058ad93d68c749c04ac5c42fc0081b7282774d92c4b6a7cdeddbb00b46374fb73b8c5617d869ac745c9d8884c81a8df0ebdc957e1682496fff6e9da6731ea3f7f7cf8551e41efea4923040e86fff7ab6d2be41891668953fe849f5442e97b595e8b9804e2c1583fcc619155904c51e2975ac330976eb7e0fb3306e61b4d53e4fe5881662a505a66b64931bd17e68d0f218bcdebcad8733bdd9f80d38da2877e1c934d12d4a0ff619cbccf169173c22c8190c82af115adb73c2f0466bdf97d9800ee733cc2ec7020af0190a37768db6b8b1804d18544f610600c2cd3ebe03795647d3d402caa07cf88ff90f5e27e0a86e96552e47f451502c3eb3a5c0a4257b2727261fb0cc42bd14b546a5ff679dd3612d3444082ad0ca35a4bba4de75f7a40d5051e94aa5435c3bc853b92356b6e5a531f6cb0762c6df3999dd988652cd139dd93756c377f1c1f8dc1235970314b4acad68e2b95e069d881d11b2fdfb23703e660ff21ea3217f48c716dada64e6b5966d8909d277edcd55c89787a", "0", "0", .None}, + {.Is_Square, "4c9127ec5e15c78a3a5e6ebd06c9bdd752916ad1cb59fb2dcc6d71d203842fd88fedc30daf752697d07cba20541bd84b6354bf89281a7eecff07dabdd132e0881b5dd5316619525cf634de9f53e4a712ae2c133f0b39057afad4d717f27bc5c8b7ed30c2b5136af949bc7d8f01c8ed16dcb942351f32ec623ed7d5eacd868b7e9b5732ff1c3a200929888198b80d312b292d3a966b20a3e421133b39fc4fa8c5afb1ae97567094911b7e3da7c9f5773bb6c4ba34b416411e9bc26a54425d7445e37bdfab98161531ac0b75ed570914a11bf568c0d689404f116d0e7b7db7592532af3d55849635ac859f63e4d102ca62535a60d394c9d9c81776554694ba8c7cdfb441cb066026ba66e489480e58314bd6c841fcbc0f852f2a9cd8945c00d496999610e28e871d5078239dc2882e121cb0a3f3370aa96234bb87dee93a35e592ff1ffa975006e64777664c021c0d45d2233a6623ea69b974f5167b8ec8bda38b55db022770c6bdb6933d95e1440d3f2f15936a75849503befdfd1ace73c5e32f744ac91d7266dc39267069bad45025b7ec5b2eb273278d649c7b88683f7546f7373d5c0f1190ab2f8eabf75a009c5c8a51bba0261f49935067f43435b052c160f86ce6a20d8b334e591a29a6ee28ccc1182a940051cbb9d2c2c451686c254b89a92701507cb3ea6e82e1880c4bfd0291e416d4ad5b1c39a1ff51d912730afa0a", "0", "0", .None}, + {.Is_Square, "906efacb7fb452ed2488aa71334ff691b5892c51a38c15a8610d9bd66bfce2a5ebe6c348c3b937549498675a42cc739bc2479df21e60ee8eb140adbf572337be97932f70bda90d0d54be6f83c8e199c45f4b038ca60ae9109c27c007b3fa61d3547cdcf4f6053d27e41a17c7c68d01a957fb8e8c4ae8ec9de01daaca45284270fd17f8fb70bdaba792e816d745c2bd8515e346cdaa61ec94108e117b26c89f77e8a10612901af92f39cad30bb9b3c1b74bf1163e5334f336e00b3dd5e3edeabefa4b27ceffa930d8a3adcfa63a2a4b2760ea7ae9653acdcb947259975b6d5083d03ac264e5894176c85a7f60a4370c6337b32de8a2c3821d9f7283dd80f20733e5a2c65574f57f3bc8da6bc8a792d926aaf931d606225392c52a7ac38312a0000652d036b14d19971ea83140ad2a3b9168e2d31f505c89481b9c721820ed939b0291ecb2659b82bcec731b6035b1404b0e3af305eaa49bb5d0084908271026249252951032069610db2957d262835bfb68cc3c5908a1f186a9992ad5287985d338c8a6440c6bd72a44335fb6da20ae4ad4fd8b164996ae4205ca58f3cfd3dcef1e6be6ce643569bdbb518dcfd638d7d16ca855ab4b5006586f2ff087c19b645fdcfb52f947f47d6b30249ed0b97ea3e22708c740bb62b1fe225aea78cb84d1f3e66941fd45c9313b5b374a2e0f691f1899c1367a5002362bb1cecf319be2c499", "0", "0", .None}, + {.Is_Square, "6eb905b522fd972e368b0fed29e948a6e86796b14d22513ec2bb538992b111e30d115abeb23fcdd263b5a3675eb627e780a6d784b45f6af239924d08daab140a5c898f019e53ffaebec6c169bac2b5f6d5a4577f90dd74c6a710a896e95dc11d1608b130f3bd4810cde681f8dd10f2feb6b61b8bdc01a17d25d52f514eb1b4c626dc1a8e2cec13f32a2dff006924b120f63da64ffbc4003c9ac29cc21a848bcd8bf49c81933020a2ff64253e869f13136d25aef0b37a07de3c7394fe695059bb87268aee993428d83dcb7684bc3375c260746a65c9708432d4e192de001cb1e3b8aa07a85a51b1c5964a9dc19834ef42e987126a4e48664b7b2a8c2d87586698a5547379a8af03ac96950d7e01aeedbc8425689af8715f4169542c4a921d5fd93fa4bfb2e70b7237b847893eb58b488c7cce615518c43013496ed24159f8249ad2e9df307fd81bf99e9ee0d7da19d25d4c9edcda160c77d7d60d572724f9cacd66ba87702f80e6a8dcb67f09a664490d48ec5edde87b828be4ba77ca203ccc4225fe5f39313624448ae4e76f0b3f33b8c4e75d540119e20e74591e756794cbd0ebf546e07239328d50f16252fa8f5f1725ae8a90e3aea3dcf964c76bf61a4e7383fc83428b632392a0374171abd3170d0f815248fa1daa9496685ea66e3c1658fa943c073ea2443cc704116c2f894c6b94492de2d1f10242e20941e7ea1ac3ba", "0", "0", .None}, + {.Is_Square, "a5d30f1deef69b7d9a2fafaa603570e5d674714fc65506c30ce42c2c9669b51059fbf21e4ffc282be8ffad6190d8ca555ed08a5e2b53793464655948712b6aa083970565c8e66840c0e9977f2e6c69cf1f3cf455a30c74ec3781e482fca4b64ddcbef9e10d832061cc9c113e0fb9aabba68185c27059c24a69602a5c4514b6185b42aa0d7839ef071b31b4f6513e7a6240165cd89385d19f3b282736def02bd74cc45643c01f0a81cef2b17426aeda4ee96d0fc1e282eca445fa55f37a9bab33a4ddec971b9d9951d3a8fb12b039f18a6e46d871eb863650e51e91514177442d7fda451e2e073ff0389fb6b6a11b4045b28645d1b2f9804987b9b0d82bf282f6e7d207ae7ed1fd2800cc37db2a509d65d5bba9e70bae74c874a1e1133e8e3edafafd41dea473ffe92502b0b692b4ad0db05e0deb68b387446883d05a91b20c8d81590ad0c72e3597c6a98b011e7d48c43981078e61cb4f1af8f82d636195e57d25491edf0ca3be8f13fc44ee088767490c52c36b4d06e48048909f4c00463b9f03cb2c48e6cb72120bdab7110f7d471ddce689ff7859c509f0ebe78ffb2883bed699d7a1767d16b3b6ca2b059d2eae9f88051c9f85ea4981a53497eb541cf3444b81bdb8d746154035c238921ac717bb4ef470327c1d66b805cbfd6b3329275ce21ea3ca01d24f20c29ecbcddcd2dd618df4270aa31a27444393d18a872ddb77", "0", "0", .None}, + {.Is_Square, "178e7c0015652293b2a90568c720681a38907f70e4f89d0a7b9f0562d1a331404fa337222bc1fef508275d1905f7c3608877a1d8f836fbb458b28834db1a2ef16fae4c2239549960c8c53de6e8a8ada09c22a89c362bd1882ec201c7444a47410dbe9de7f008443a8af69e8799e38eb5ceeb527dfc92f82bfd453ecd94593a8c45bf8e74c5129b8d86e9acb7b8b8fe1cd4d79c173cd2dcd3b70d589e5a6ce19186d7a87879a5c5188264a69a46fada6a9a880cc0096fceefea0fb22b13d09a91c2a5ebf58e6c4bb5c23d51270834fc46161f4df985b066d0f1e7d19e5f3b5dfe1da2d380cb87f9660ea2488207ce494f6f44f06e2b60f9d6f3113a1e5bc26deee1d1bf21da1d5717423f0b53a3494ec2740f34a2741b7f7a899124514e31dbce03d1013d50bd05d40b129ad9b27506aa3d60408ada7391c8ee7c153f4c7faebabcaf02b0359acbe3ef43726fcda5164f46608f568fc2ea2559d5883a525049a5ab3cc994673f8f0093e3b32f76bb6679d4b599ac4fbbb563788a9f9336f47ad4f9ea7c7812d1b6466f664fa28d86583bc0f85b9124a3ae9c03c9e2fcd728ec161e2566746f48bad2f681c8023b49450b2656733a8a1c106a1da62eb9e159e8e82cc31018bf05d1b4ee9df7e3efc7dd35e6c51aa9eb1e5f378017f7a7d2326949072b92e224a50fe129c21dd4216af992cdc1400344e9fb676f08d2b4363d3eef", "0", "0", .None}, + {.Is_Square, "e9b230c0b14a459ac6cd32b3e26c1dc3859c6293f7aeb709e14c16ad3e94a989ebac8ca16f5f78626e40edf6552f84fc3cc2abedba31c0e67dcdb4903e1b0446a73ebed51f665363d2851d2e1cc85b177f5cc539438475d040185ef831eac62f311553e5424ce9f796a6582b51ad13651b3526c2d7c53521edce78b3291e8eb74b5b7c314bfe1da53fac05fc2ea949845774600e02fa8e23ed431ad42cb60c8a7c543d6ed83d39067724d7e66164cb3a953fd9ac6c157183a5d13c2bc2d471ab3c416c6fb62b286c51cbd2c3a6434812c98c56de40f0555e770b9871d521c874a019acb5b0c27c7aba083e7ec120a9ff866fc58b31bf06737d0d007bc14d7a6237e43a481a745f7ec918dc5bda393e8abc5497e49535042d01c7c7e182d3f2c042e08799b478f502c466c4eeb6efa19b6a183e0e32784807aca8f280019247a81324f4eb8e6f22a51b9724ff7a525ac921a09c42bec22df728bdffc44dbf22fc385cb5e85764c21250d58586a5b4baed583e0cd258328b35e7ea449aaa10bdd655d7935fb892e01f083a632f3bdd726cc0260f5ca69735cac65819293d61b42d93a56a4ddf937de364a044af1d93b81a4b45c07adc38c2579c78f74165ea95579646d342550630275ecd796d61d50b8158b9fda099288fa64c7d817c643c72f681ee615502e50dbd05af1cd1547c20bfb726fc66bdfdea23b3b5279f82614a65", "0", "0", .None}, + {.Is_Square, "acdb946a2dcb47f43d835085872b5d6a0ee1868074896561b6e7462c384bcf51072b0e8f8364f1b0a94ed24ffde9267b363dc24ac843343f52ddf102c73e175b8392eace864e2bd0c2826d60165e85e03d0c1ed886b7c62924ad3ece4b18013ec682fff8e939279e06039eea3734dcafc5123aafe75807b1fd1c367f6f9c9ae7c0cb87d26a9668aaeab81d75d470a65cc714efc131435c130fe538b20e0cac70f4ab4723a5492a46d0bd9876cc8f1e92bc4dfc8fc6a70e6841dcde695cb4c470c7bd3f00a2889f8a422fecc5eb27e1afb4fc791aa77477c42291e6d8124c6f26f843683e97ca6484c753755d417f3c8570477ec9276b10cbaf5a6c41017c0d38f3bea629c39906b8b491c703f19626e784012b95ce75527448e328223e1ce08e95f20c2241cbe2b21c0eb67d0116a6f7ed928d9bdb63e6748610154065e18edb92e8a6b929418e5c834656d553d5c5050461af54ce5e8d80cba5f70ec7577cbb88f57fe55cf236c6cbf50e721d2d1b6380dfc2d7b4f0611b59d84e752d2a566258abdd295ed3a30b52bc0a7da22651913bec5d8e0b39aef631b6fe524ebb59b2e3629269e26a87cdfd34009a6837bbd3765b0d49d218318f8a9dbae3c56fffc3e4c0e41a8742ac7a3977924bb84b5fc98f14abbdd512e5b65bf453e92d28b09b197e8b7a8c988f1245c436a31822a27de3fd66bdec046a323d366dbb1d68dd74", "0", "0", .None}, + {.Is_Square, "c7e14289c1f212ebceea6ea2053ceee07ab0e27770974161975347a5cbc0f4731478d9d6ac03cc1436d2d1c3297d66016873c4f3e34bfd3f32c4cfcec3661d8fe7b21fb44b942b64c93241bbc6ad906480d5c69437e7d1dbb6de88dda5c58a55f6b5b2561b1b82890e52d992efdeb2c2bdeaa0e201716c242c79ba6e1889744192359d6f794228d0a799801a7c176c4f412970205b1bc5901e6780c51c3a47822d9ed45870044ec7b6eeb5d3087a0793e533cab5457abf37eead7e33fde29be3d5bdad9ccd2752fd5a6f5bbb391b64b05d1b2ec74fc9987cef8e2091d1e1a1595f89a6a92a29a586f07927844424f7f50e9d920b04a35051241af6795760b80b6a25199b16fa27541521ecb7419b50e2f1802ca9e4e157cde3f74ebf406c719211c2b8c988aa4d7f03fb1d693ae69f52c1862fc5219cd14a465567f27684c8394a18b89ed8ba39f26a7d48e25aa4860c6dc8028f2f5711568070fca3c0cecc3637979dc7a1106adf83480e16b2a907f24e34d39935b3daacca84cd80ef3e34d514fb58d7e59e58cc4d574260c43cc3aff6ae60c28afb37944d88d2309f81200e6f5193f33689badd3b7f5fddbc758b29b5d8b558ad7b3e7e0820211a5bb101f59bac744a4fe1f91b188134ec6f3d865f1b94b1c1480700b2c3fb080c96a94bd3285af02d27a2530d82e68e8f5acb200dcf632508bce7077ebb06eee0fea3a2af", "0", "0", .None}, + {.Is_Square, "70e21e9e70983f66fff43570a4fbc960ee74b68110bd9649c97e2de0ec5d4202f04f1bfeaefe83d86d3d99a21931326ac7e8427ef052736b0605f787e098134ad2c6d9972ad7098b54952cfea0d9c4b783f359ae0d9695aeac6279567a472f0692920e8aca5171798023e362a31c1e57e90fee5e7d515340c302afb54b436e5f8595daf67283f8c73a2ee8ee96ec50ad6660c8d3a26012ad1350aedf8b5d565d1c16296672041b14c26e63e45b79cd295a978adf338e3fa816a14eb92ea411c3622b78b02e03e8073b40c458d71412b7e2cd970e658e67c70cdc264aadaf36cf00583aced5acf3d0a4babdda785119a7d2c3a8fbb3d4a93512c50389cce86aadc8d0dd6d6b7f21daa0127529aa499d09ae5de912888ad04e09a6da866478e56f72025c080e264192f99138e225142ee34b8b8d5e1eeb329b359959262e2228af2e368fa68db34e197059e1aeaf710aab90a7c636c0a2562bddbb4dee74e67d809adcc3185132c1f8a70ad063a531fe6b8e124df6bd80c87ff40c650076145ef5f2cab4fe3f4a04a43ad8432a5a480144a8f4a4e71d87058ccdfaad5a228e83b44a3e8b1c684c4fb7d85c7f7d287c68deb86ffa78aede9a16ef05fc578b8458aec794047cfcb018f3446ec20222c8a621132341180f77213f23b5dc4e1e45c27b0787a0839b0cf9d139616d5b4c6352de14b26260c48f3bac106b40ba30d38f78", "0", "0", .None}, + {.Is_Square, "c5925c54ac79c0c05ea2c88864f1013c00d04e31c94a0f1267cc711223751bc56bbe573565658b4162349d8b8b246e20aa5d6e83be76c0d18cd5428ac0e4220a501b1da18792237a4d3969038f6aeb8454d7dbdc368af5e57d469444eea1b14ef1e459f6fea2c9ddaa84ef40054e61b3e9279f77c38b36ca7b7147ce906657dc17fd72b7054744c1307877f2fe8140077cbcbc3c36c3ecbc2c0754101f483162c27d3bc486567b0aac48ebab8cf9eb165d529287c6e2c601aef86bbd1b7796acfe6fa7419941e5610311e9c440cd7fbf570786847077ea96b77cd71e2060ac7211ff7124fc721745a61dddadfd53b76cc8729376467723df5f08bd20aceba1747787f5e4271929766225d828420f2fe1fff798d83de648ab45c5f904168c3a5127cfd63725cfd756a21881d7fa8d8e65e91d297c4661fcd1505a3db2f42d9c4cba2a15609444cd2f06d43752745076058de6e539b62285ea2e804b44ff6a0500f10c65e46089656616ecc2be33b1b7299d07dd2819520df4c624ea09e6b11a8e5413ed78fe2f3b8116f8070253a9547ec1ae23ec41871e0e4843b03f6f5d4fd3a28af041c2338cca547d93061c87c87ebdd697054092196ef42888387f6f95020534ecdb20f7ed429ab7af0c0caa279710b255b5e50ee4c357039aee8509a00066ddf17f9b51a0b2295b775881f4a6e3b6cd456f4f5f1fc728e6a4750368895e", "0", "0", .None}, + {.Is_Square, "f1acb41bb7e7dabfdba7f3c77e6cd3ff6792c219d8fdcf4a77b720a659fdfcc88c21599bf28401b3ebe3c74e87035ee5f54bd5cde922fdc93ffa296f37e889d8d380fc0d65ebf3e8870e7a267ad03645eb3dcefdf53ea6c9d0470c7d86125d6fa331ea98d1c25b7db65cf4bfa67d8511b08fa86fe6c59647388a1c6b7ab73a03982951df5341624eafcb0e6f2be785bf0e230e8b52eacf827940c34db9a97b3c6c0173bd86160beac70984332f3768733bf477bef9242c8a9b45878ecf3d3076120e3151738b38c6b33880a7801ba51ab2aad0b3edcf94aa8b451a6ccf3cc6ae16d1b1a7950e624027aa1e73da5da3d76b5e68b798290db1fd09338a1c16efd30310b1da5104925e4e7219e003562b8b90878ac3271c1c80efc0b8c48b3bb04da1e35d0e0f4faf0babfc3605748e64081a05fe3fc5fe34168e853993170dcabfc09c49111bf6449ade610a4407a498e04ada6f34292e7d9986799a6ec6e61c006e08739c6d22f7beac7701813a7648fb531aa3e561d912d45f53c79eaba6bcbff45bbf8a08c603f3c7afa3a7ff17addc9e5662cdaaa0fe5205ad69ee52a864efd9a361fb0215ee0a10fd09bf01bc98eade285d294ca6b0f204b88f2fff643fa12cb87dd74e19875de3a776cb3775cde1e492e2846a7d6d63d07cbf10244721db9b4a591c88b8f432e32405a8bff379f05d133a94650c5773fa7d0a7cc30f8538", "0", "0", .None}, + {.Is_Square, "9fb82389e017a5df1a973466a5b7c3567a33bfbc027c7c5bac6180b6919093bf369e9176357c243a3ea239969246a70984764f14b136659c502cf8f3a1386fc31ea3a90b25276a6130de4a4ccd38b486f069859bf98363e43d75ddf6a03b22b20921defbe91f8912a8b60ce8560950e8d384a9aec0718c985159199eae7e6a3428a87d4e3c684e9496fccee046b4a51b11f602abad106c71c1193b79ee79cb70d4101aa14216151cbbb5b0f498b0d0588f535c7b0ae1bbe26d95d652670d94b7fc790fa3df8e6d5aef14aaa6569327934ffeb56a9c2f00dd18f7bb5ebd94ee7a8be9b85246e82cadf7aef28555d198c1ab560e6270f8a8d8524da8870af70b33dd7b0c91aa0b973e9e6237e3b290eb74cc3b0af8b005adb5e93f8f3cac44e9827fa8e4e7c84e6ec360a65956f2e274b5d3c7367d44fdd4ed2294af7b015779f37b7793e51ca8a9f3099c4e2387324cd6178d26b2f912b7170709fade3434536c9fde8abc90823a6d91bb1d11edb183621247d095b72ad6174c311d348364994e8c9e08469c859fcfd4b161f821d1fbcd4f1feb9d555abb45a7da631203bbda5b718fbf63308c9abd4a7311eb023c009c7879858c63c4230699b2418084e914ba32f9551d60bcba9dba75ac28e6677bbc1c34e87c0849c6c797b2b7c25495fbbe2a5bd7f04abcdca0fa0c8e92bf7605a3cd90f69680fe49e28e0c0a5debd5d447", "0", "0", .None}, + {.Is_Square, "8a693488d48864709b379929fef73f4c8d8c0dcf5babf111a38c13e3f71d7b5b09fc05464a211c0e9901f7e58d01a9dc95a1cc76f65faec21df9eeaff0abfe2712dba4a8f1ee2bd4e66bd7542d14231e33e8936db375f83bb38e4a156ece8539697e0076e852653ae00f3047cba7a15c375f3244aeea1ceef96a5a91534e4b5d424e064ea5691f457f08e58056e886a8db5aea3b2f56038be381dfb4b0af570693451ec27e080c4ee58b0b35629f2ea9b90fe3663e8b4c014e8f5d90e86b44ac47944a8fe0f2e1e6a05621acb7991fa308edcbd47acad12a5ef8846a3fbf2a9488309b119f33b3467a96d7fa9cbd7ed87f1bb9fdb0fa7b1f13abcafc0e84a7772e26806c4031134a8cc7f19a557bdeffe57ecf25b7b50749186180cede59a6bd2f868f505501b706fda871899c89ec908c25ebf74865432a8274a58d5b12cccb794ed31b25c89720fab56d52a10cdc01e24a7049e57dec8e04aba3bcff819679dc1da8b4af7dc378f2cf913b1745e0163a5901a297ecfd8b5ae8f37205fcc77b14913948a1a2b43db313a9e505923d1a67e2042e20ab3bc39578e807373f30539cd9cff65e1bd7c7977255902fb93e454d9260664c6a9c654afe87eac70c17c30f52de2690bcff48e9e7796a7c7481fbff78ce60b90cae587601cdd6f943f38fc6c95caeb44238bb24a42f27cee0e637e9fd9fbb0d0b321bab2afd960112bc17", "0", "0", .None}, + {.Is_Square, "ced3d5389fdc6d5c85de69e2cb748e764c909176d52d9b2cf3867e167ca9d30c702858df0d888db63d977618ccd232702e703e3b686766b2a3c59bbdae7e7f8c348cb0924d762b7dfa3f730ddd5cc2d9003181e8be72b46e4fb72d1244ce57785298e487cf00f2b0c1a53d8f7ca2d750d42c75414d39c846ee5488806846a60e0f57e9dca3bd318ef32fe89828f0595f649f64550b47f75ea365bdd2c45274c4c8b689a1a03709eece18d47aadc1eb4e5a5c297de2fb43e06d717499f95bc07d1d515d0b4a2f071bc4172ed3ac92d2ee4e4a7b2fd4aea80d55a5e17c870c68c5d6b7586200b7a124f6c58cd832e43f26a64286e9e9e152ef3983c0f8eae2d2e2a39c66b09c94bac3c027838ec3f3d6c7fb2bc9f92b40cc5ff14bf3157e2da0795a3d4b05597d26551bf8ab0a41250e1ba4d1938632a88187a3e53c131f047ebaf9327fca0c600a9bcb3d795cf70145a643c3b097e927a8f4a01546b35388e6ab230dd30aac9c69dd3ef55bb2d3f478726571ada8e25854b4b2fc63d93d0f9a7b17823d0562d375717dac568fb60bab59c68d289b9b753889008dbf30cd7ff5b55d48d60f77b330d025161e1fc8b86092e482d20a5fa0b29a88866a7d5b93c2cb83e3d85dda0019d7fb71a9dd22c385851e55e7038cea559e0e54b463aad3037d24128b6b0b4a85d46ed73a6233200466601e9b8bff2b3b80bc7e492c20e557f", "0", "0", .None}, + {.Is_Square, "c206baa7caedcfa60356ddc755a77e77ede2148983a030b58e8d4b8512df7dc71b3802457481b7a4969cd95a05e7a3fd13c150f6517d61bd6fb1660df4f979df72f33098b76ed3b132a2e438fa1a0d9328bbe91195cce2ae353bd9d21858f72c015cfd42ec736fbda76832019cc8abb00f40001be1624987dd3b5bd3bd93b8afa151e49db7967bf715e26b4da26fd89a6d2eef62634eef73613d47900292f743eb08d25833d7a021cab31e1bfae345718380ee41d394783499bd112e7f7a9431f715879c07ebf2c2e79086d5bc0a168fdf615a80fe12b1615d684713c77c4393a40db7d187fc8b9d5671fb75c158c3fae5b73918cc26e1d1c1797ff7ca0574d0b1b73fb7090716f373adf073a3aec56dcd88d90366b59fd8a77832763d1dfbbdc448915de4ec6a745472572fb24c41deaa0a2431e4aa683041fb25189922673b34859f3a9da855fd029cc6eb85e2b4870fbdc963b723b77108119afa67cee992db4fd3284ae8650e2eb0b5f0f12e7cb3e22a36bf1b152ca4074b9bfe91f989d98bb2e8ef08b53734ec77e6ac0b77c1a792678edcc6076977141c8881b474acc1a149cdffaf0d3cc41614f4f8d955011519a39193793a25fca957120a1bf6c05d18796c5b7ca157c0303765b1ac68dfa8092838e6bad4193c439861db9dcaa0743e2c9873587494797617e2aed0077985272f0ce1994b1775dc9b71c3069740fe", "0", "0", .None}, + {.Is_Square, "f20848df6d447a35d477b25faf4e1ab2c0de64ec915727b26ba7ff461144182af371068567c3f9291e462c6c41cc67c0a5dff9211b20f2c23d668c1dd6bd4e63c4fe3aa4b467cbedc578f8d68728489b9fcb55c37899b35baa741ec9cf78676cb3bd1b6d9221969a6bc34403845f9ca3b10c30a9e55644be6881a9f5a2cae6b1c3757c51e6fbef40d0c634d8a1743e190ff207b7d984d8659f056a5af05b85ba32cbff9069049801d10a857c324e2a1d956fde60beef890ab547803ea2f89aecbeb95b370913156eb902995a7c2303d27c2a06cb5a94c0176c8018f429456f958857aad6d5061fd420f04a0b0f77e77e0cf2f04c915ea88d9c83231adc452992bf2fc1ea9e9b5e536a337f134636542c20d7dddf20fc5564c087573e287c3a9b915dec85b7498b7d82b00926115a896e7b502bbd602f5464f767a7f5a20a587a81cab2bed4c6c1b5d61bd1135ab00636ff6ad9e6b740362b1f50bf58c5cb734305667ddbb095965d79f8cd7f6559e2d41ceb74e9e8d3d8ec4ebefaae38bf552114c2134ebab7db486633b30a4b513b038d76d29565c52c77f9039d061adf4e03591a14180515c54eaf4d0e282d924d45e20810715e3adeaad3f7a64bf55db329d4920489b41c2e41838e31f38eff32acdd654079902782c604ffe42ece97c5a186bd1ced71b9e27590286a551c6c2b882a9f38552fe2a5cef74df4ac4b2aa8c1", "0", "0", .None}, + {.Is_Square, "cd1b42baf6a26f4934c882d9104b13afe24af5815ea43d31340e7103618e18c443fef8a33306f0cbf7dd4ab1d4d4eedb9fc00ddf78cc2dd6a7e482f926fa3b28620eab14177e2607ca413fd3b4762bdfd743d5646f00e6bba698764458ce3f5a32b837dc945afe0d5b806a8a4ecf0341978cbc788ed0fc90d7b5fc588147ac1ac89e7dfaf998b2643f7de3e5e40d7020b6924207361733d63465f36813f47b8be0ed30352e074fed85a9d40466a57ddff56da27d74da2e97e4cf60536df1e0db0d875d17716c0c12a99acb90e361d2b064ae2581f35d482793a6f6e70b7ac033cb060e3400635afd2b20bde2996438e0f134899ee99ddbab02957eedc8608eba0790b4b28d9bdaf3d04f2cfca2aa06cef42419c8d2e0532443d09bfe85d88744273c8a87bfcf22ac5e83db2ee451f3d51891d2f2c2e5ceb67347f76a4501967277fab8f673b3235826490609bad7b14c64737e93eca544c79727d9ac45c6b8896f20dc5607c7b627f778dc940ba2697f8d17f32b8ce8622adf4d83307cb50285f803ea01525f0bf8a8bf0133e99830bf186fe4f7377726c4a6bf529162f07eafc38bb163441187785bc9ef0c0b04c320f8c9bbb8541d74d9ff29049c118a471bda66766def3712ca5635b854571d89b8edb1cf9131e5b5910ac3f49422496eaee800307e3a9bb685990d71a42386d88663875ef25d80749cb874a7689237e6c0", "0", "0", .None}, + {.Is_Square, "df636546493cf584d52ba81e062830628d2eccb09e5b6cdf196070878e5ba90e87c24829ac9c4c9227cca37e6406cfe081c14604774817801dbb9cd846cf0ed55cb58b15d349000aa5ed672eab81f669e3cb9fd1c0b347b4ea28aced06279c1e20444906290402a927a8d95ed5b62100883304e3b7e7ae2dac216eb62aa87b3218ca2bb629fee2e805b643a36a287df72ac851abb2555ec8ac77d158a4a440022dc6969be9bd7d3e193b73732de3dbfb6b74a4369e5f12bdce3a0a7fd8e3fb4d13d88e80db1783de696f87df4d89f0b9603c72a7baf6368a065270c752400d104cd464657e02208e73fd441d4f2188a73b5254f76463ea769c59be05765994b23db8db1ef3bb6f6f3fe8036b42038e979b67c76c82e69f6e1f1b9e1bd91ba3b1a6dab2ef483ef39fa3f535841a491bbd90389c7c9a1586df6a61f32cc92179b66e1246d5c0f95bc0b2d641cbc8e8ae29d2b36ab3f431db4ee0ea66757ff05aa5200fb26355b0fe476a49c46a838aa02dd58eb8942743aa8bb017926d91d17c57d99ed4b2d6eeee7f2f5120b4a2cd7d06d9e3fb5569f8a847d8925a1a19d7af273c2ee6482689e7a965b270c919c9b815748dfeb9eb71c96ccd09e6ad9ebac0086f760d9b0ce47e5ee0bb2236dc8ab959c5741c34465e06754f0bca8e72494bf3ec12b06a81983f05f2ead188553ad2c031e4081b324462486c11d204a3fcf42", "0", "0", .None}, + {.Is_Square, "624bf60278cc65499840218af23dcbeb47b7451398ae0b84bb884b3d5d45191aa09d971d1fce2b6f4e7aab814062a329eb9d3c275d1fc110a62cd3e095d0e0b94525f2fa66530442500caeb72b404259952cfedcb8d75786bd0c2d013f5f3cc53f9d6d2635af6b81eb71da731044b1ecb5724e0373f9fdbbe1f73550a1e3dc34ad11234cd605dc8f532e1b4a69ec552dd26a84ecf02be436d96a715624eb6a35ef7bdaadb3b5e0da5eb5ffa78eb32cd5661030a2dd8524453633c5b726e204f59fec7b0b1ae07a034511b094b98e448c10e0ab57d59ce33833e3a6551205ed6f8b7e98d6e5ec835975b964809f379532bb8e072985778580bd0c77a661f54cd14b06e6c495d49c6b8aee0aa16568bdc7cb1d200a740b67f35fbfad3a47f92942fc72f8a0d8f8ceebd2fc2e34b07ae4495ec3ac30486c5f5ce955da307fbc82bc365171e2adda71a4b7700bbaa2d7fada4fb2f48ba2f935de2f172568f3b87c09f028228ec7cabf4c0604e01b295e767d7148d6864b997ca7ca6320a6c623cef528d00e8c968b77995db7dc3b1df50843e845f3c1287a9dbeae021703377e151c578eb8fea05d621547ae677ce434e9a07f5f2423ff6eb513e908f0e7745e045e99bb2eea0ea3e3305acdb0effc3e5351afe3b8dbbca20a0e6979f09897fba7a2b979b19e0ec3347cf324fbcbd318b0aa9b59b46ace57a6b71375e067223af7b2", "0", "0", .None}, + {.Is_Square, "f85d6d1804462a48026434a48f9ea220a964fb156cf11a04900ef53dc59b06b4adf8de2c9fe1a654c31717ed69ac81b262b47424c842a8aa16237fbaf8faa5418a38ddfbf6a0c28413035eee1d7da93832237326b7d897e50b3658aa5456f7347c3be02ca2a87193b2f2a52f4395577abde55b3277fa5a862f596763899e4d4b7f4aa8d2cd111c0014cb4f2a5a201f44577addf2226fa9a2435b495e4e993fcf55838875a3f7b28353006f69fefb98f63bfb01e18f405baf18efb90cfa4a24c8dd9673fb0e0d4cbe0dfbcd44c088cf11118af52bf99ee45cc464c40661764079a4b972a956c0a5d67d22ef58d99b993c598fa4fbd874d2ea311efc45be194a4ea9dfcd26e0ea8fc6f73fa250be04d3ec21385bae0d810d4456a75485ce6cdec3118c7b199bb4b998da792cad628df1fed42ad70fae3493290ba1425e6d39cf6a75bb4ceccb58deda4e402b348b1eac03b23a1eba44f1bdaf02f2b9e2345e0320064982a3a12d9ff69a8e45322d3d11ab746b2490e227d96bf597ccfde2c23b765549d70db91f815ca3442aa3de96a1e9444eed980f9e95f894308378df0d88c3ccbbf8059cbe86855acc8a6709ded00e77b098bf4a1f8447bd50d98a887fe88906fc998e529184abf8a3c3797954fbc50a0ce9ceb9c2ae0784ae74871eac4316e45bf3cd3825ee440c3991b44fa9d3db78a84f67ebe53a0aa8412667be0848c3", "0", "0", .None}, + {.Is_Square, "e0d236f3478282f8dfa421ed60745e55a31beba2cb907f372b1879b4d659e8ccca1ac72473a7082b25808d3c3784af8fb9987c12e91060c09f8a492096baac18c54bbed2021a2626f31a942d3e19446fb0fd0a0c355facec1f0ef34018f3d19869613be70ec75a6f05437c5752a6fc55b9f0992683b04da4ee03c72d79d2cd9bfb22c93ab8e3bcf5efe956ef60c8e2b9920741683beaa7f705750cf26f0ea0a3a664bc561f2940edc720944df89745921a81ef045f0bf7c3935101410e61c568a0475d096f1757b001ae774c1cedf4fe524f7fcf36b382c80a224db6356b054c2fbe6f1c32c811e8b22eefb44c1ce01ffe7477d27997fad65169947e3927a1d1ba2c449b77c2cc944ac7632306b77fce6dfd078c2f725645db943eea7957592e5e8630a7a142502af0b164c319a3cf42699a05afef1eed4fd99904edd8b570d983d5b5f2e344c58596299a5ce654e41a508e2c46c64e975cd31fbb3b4befdc81fb66fdaba80598e8e3728e4738f5dc762922ca142622c2f9adf831da281dbdc4bbc88904bd10f053b8e54890cbef4cc0aa2fc81ff6aa90ed5703e28e730d4b41d1ce75b17d0cc4ab364678772932cfaf351ddec0316c74b850d28e24d76f58bd54f22d77033d8421626f29904740b20b2793fd4112db33db11271350087d3481c3e5a135d9736f29e074a44f780b6c9fa76d7b71b7567d8b263c626d30023592", "0", "0", .None}, + {.Is_Square, "c393c87e828904e1e7f5b47dd79dc64a85c285c70495c54bfd9d437600b4940fc584b225e27917b21ac1857a526a8018238a4fd7f4a29c0bf9f98106ebb639d5790e01c9d08e0935878aa2c381ffd9ff7f3ed259b1406f0b8184ae16c85b265fd15f8eecb02c6d8265a5b0bc832839fe1dab1a0dcc55a1e208c6e70574d598b374f3d576d33222c3e2bb0da30b158b4aaa63e203f3caa99438364a039b9603afbf6e4a13af27d36efb7f28356235d511a04ef01022571175352e1204a776c9a47ccf409a0714a2df2d69911632343b851e36910d6d8a6ceccc60e2b5b63c880bfb16ffe3912a2de084c3800fc2518d9013a8b40e6d219c4fb97be9887b297df0300ec2df9180dad25e33ba8cbf7578fce19ba105e5738fc8cf3abfbfb2da39f4eee793385397127ea9e8bf4db93625814680ad79d146c074f8663f33e0c7e4beebc68908854953fb4893e97bdaa4fff5181bd611fad63e1e245e52071531f5bfa2f6ac356a1b72bffc9a775ef21ba94f75ea91d55a8f3bb92c30d9b4ea3b7beca48ab73cb9c8d37ba4dc0e56cbc0e0a0c125a48e677869658172c13f196d4c3caef7c568377e9f1aba449ec6e628174c303e62944dca71bdd5c1e4c7b2b6fd0648cbe327baed56477ff98f7c68097c8f2843ae2be92d285721ebc08d0eb66ae7f7e615e3de5235de5940b0bdb70ec31e19213b88d4b2c668b871f4b3eaa8cea8", "0", "0", .None}, + {.Is_Square, "8842e8feb3a3e183bde00a95db9ce420a4190234da1e9b7616457cafa623c1f8ca4c1d37bacb2e87652a18e039cef7109ba11024f21978223f6458b946ca55b3d0d1be238ba10f86f8319e5f3cf57ea2a942f48d6189c7c246d381ada11c4f93862c301379b14306560b9b3829b89d69341452b4e9f70a5f8f3c13cf433634459aa02d950c0323b70ba38b26e0431656c80af5184095a7e2617a953b2f84098882a814d8f7b1f45d07cf5c84e88ebf5828c672fc4bace6d723ea465dfb83652c7427cbebfbe1dab48a4ae2718a973970246a449c78c8dcd5f03123c8a687ac0065be02ad3607a92b21c5d003b47231ec2232ad992ad916f12182dac1011265eef3638cb4060003f9b3e9af9539836c14e524605878dfa47351a91ed2139e55d8cf97bd209b3b90f1d4aeeba7edd559b37450c2a24497aa1b8034d9652eb361c764dacf9837e42808bf55a9be72c077daf118bf5689c3205c00a8dd1d8193cd30207837f36c75082582d22a6c732dffcc19279b4e9130c0a56ad7d6944e3bbac7d69b8151cbf02ea10b0e97c501122b5bd0d357ae0b0d566a7b01f6e3ba78a663c76dfefb89f0fb2315fcf9d8c1f40228d7174eeb5f950d6f0a03be84984b4b223a0edb407ae1a66477c300862bdb4d21b423e5115e66f535ffe93381753041db8015c280fe7f1f1c7b19f59296e78aafdb8cf7485caf65b294fb53e593e8b1", "0", "0", .None}, + {.Is_Square, "8a7975b5cb54e275406d00b77150b5b71f0798725e0b664928f5631ccf52924fbcf0b6c9790e5026bfad9a0f706fb9167c125a18ebc869e02d0c4d06f57703a741244d87621814a7ce657998d16283778b50188ab43f929ee2198e5d8ac68ce6b166af572ff6776a83df0f320cdb1f926406009b7e8411112c6615f85016f1364b28122eb66a9d9174ee03773a2d65b73a710bce95cf9f03e73f9ce0b63a56cc5a4774b647b4b75405e81231e1a10799b06314912336fb37a2d0c7de96139a27601268b9d84f43578b1448b66474b4862c4f8db84d8ecfa7833cf1ed32dbe1322c0822d4a6620957cdb15f367103d143781afe6629e41e606cede958b8775641598b39a3c742ad0817a464787a07a2740e9964bb61c64ce5af4943637b9b61200be0e9353167f5d28848906db7a7b86a645ff37bb791c6e988d105adf04d200224ed030c5d333509611790bcc5101fdef97d2021b93ecb4c417a5c5b9808b12c0683fc71b9de90b8c3abdefd0c04f394f6d43f3c0667884d3a14078820832cdc65ebe80b590da448016c21f320a70b49f9c1dd492707357c07adb1754a548e259e3610698ee268050213460d1c1fb40dab14962ce5d28155182ac4547c8a1bd10aa74a229ab1d36903ae8d5a01e1d7d2547d5bd18b2922551d385ebdc56e82a16b08d97e9410bd6914ba0e8ee3704001096f9d4f1bea5232ba4b24a73c3b67da", "0", "0", .None}, + {.Is_Square, "98a6416a042854d41755dcfe5fd57bfe14b15e3dbbaad29547e8d048ec1fe8597e027c72c6a8b839bbdc86b909f2fea5bd74753efddd4a16e5423f389cd3446e02d7c37921527776353ea4635e21bd07a58c4888d0064132f9bc25a2e0e69e35bbd1f9a29f51c3b432fe8e20029a04b0c5654abfb7a5722a5594f98f07fbb470be80b436986a3ba5cbfbdbc141d77c76d9d3b31204510d8a4fce231b24c8b7ea8f0a47b0b2ed7a5f4d112fb7bbd4e92c1b4e8e3ca09d3d04c15254702cb1531a4811fc45c212981b029eda5572d9b0728c2ef9423e37087f47103fd75ab68b17b14a85443134822b7df6c5c596eb6d1f6073f84647c6f5275c66fb8a19f1433b3322edf9043f7901c0e070ba2ae39b88aad8b5f83e287cd2ef637e9eb326daa7f4c67451155b6a6294b56906d0a8d6709be4fcaf80564c2298ea98bc8ba13e3000818eb023f093002beced689a58415933a78be8519f24715b8ede841606658fd57781fe02b7e7ec0aa3e5afcf258f1effee4e8fc82ceb4b1ae7db81fc706b3accb70df94fd30f9d6af0e23888c88ecf938a6aaea921ef2ebba2ff13d7ee7547aef26213969337a4ea22797eabbe6e06c53f8e1a6755b2bcc36135b428ca3c0cfa46582ad11901318b1e273e7d025fe940acdf8013931346b638fab42ba68bf37b3db58992b806b1219c65537d12b29228c990ef64bcb81646d5e1b79ed81451", "0", "0", .None}, + {.Is_Square, "cced9c9290b5ee2c79d529b61ba256bfeea9e5035c0e276d69ca633bad6dd654000b98a5a28655a15d2ee94557c5838f72543cf52eaae40cf45577903f16231c27147c0322ef204b07bb03f7d9e4454dae09777c55354995de8a687c6b32ca1f57636d03735299a219b940922b4320dbc9f8967fab03e77bcace68de119a9753478e55006a4c1741c402c51faf3257a027aced602be1718eb6188dce6e296a0c969410f94d1bfd952ad9c650effaeb0cbd67bc84244cbb142ef9e47f4494e140c2f66b4f3208a3ea43a121e841260e128e56739be0c4b3c6bfdff4c3ee915f3cd45c34259c640e9048ea07152864d96e1111d0e26e481ce2bbfa4adeac7a50abee89542176adc38fb694f8b619aba6240a9cfe59e53d9f20de981c6f33ab562903754d4647f30d3970a8d29cdc3ea588f382a231ceebbf8761764de080b841960c6ebc90a7814fa09e5a8ae329dd35fc2be5bb53a33c40962fbb5bce9baad3a8c6b67ee86982fb478df54d9a9fe4ea627d98d68e1bcb6d3592f700352cd8f93948502c840c2cff7ead9dce8da4873eae44fe1540c3ddb2d6eb3a4b2015f262c22f39645f1f94b861ca67f5b69b7f5f09cc1c20ce4d5caa5729d0abf632830725b9d113396a557204ddd84cb8ed437a738da1ce4b1fd211c80ed850e8e7e83db344c4c29990f42f5cb756bc1e69bf1b039b85eeaf29f9bd688147b189ba6458fd", "0", "0", .None}, + {.Is_Square, "f54292431fcd5de14461fed68ec8502c03505394783f8d67112f2036358d3af605acd265b9619d2e482e49cc9f2b5b9f47f8e32bf543791a54940eb92fdba13434cbf6032999f897efa6f8ef8634be39887aa3e641fa09d4945429e86c1862f4e0155cfbddfa301fc6f552d23b07f40b521806fbc65298c2c9a38bb09dc5da8a7858b29a336ff37bdc1d0820306b2ea759aad11182aa6e34e5d247ca793f7efc85fc0b46856b242f7667c363b040c181675b8ff8e6082e3919f6eac60167b94f71e6bda9db9cfac87cde371fa845d354d5bcfe0592490c6758d457aad757fb80bf11ee7093eaf4fb6b02e3cef1b78e801a69895685cccd90c9fa6c5dc23b6187e76bb4fa909fe0f5e0175b645e640d905d6ef03b9dc8be5294156f78aa1eb4b10973bde4a83fe97ed786fe1f4eef261a52785c07b96f52fd155c8a265bb5b8d99cecd7c0740ffe6e778d1d719dd75d4060590ff233d2fdb3feb29c6dacc1c4d1880afaae8df5636c0f78dae1c7c28cf1e108fa7351cf9dbe600934d12947ad6b092e347676b627ce5f0d16fdab9cdae122161bb11e5b043dc2d43b1b62b90078ad27dfe1586bc34f9010e382b7685ccffe56e78ed58b3a655ccfff7e4a9f2c8e4d8a7c657540c51121aa126800ab9545125e70dabc96ad95f19fb01cfd2d1eee6e13d677bf54e6d1912b7860b1af0b45dce5cea5ec3670c98bd7e6849eeb81b9", "0", "0", .None}, + {.Is_Square, "f1293f75fa73d8bdcf4017a0e39561691b28af3802eeb1d3e0e71e470cc12efd329fb69edea3625a66050dcd41be485ec9f56174366ccab755b9b2c023a09f0c430e4a5e7b521be6d513deec0b882203abc4bfb8a88b572cddd8f1f686c8bd5ffab2aded47d32eec0e028721c15c0813d0e9cb0467daff95cb330d8e2c6a714c320460ec5535de0341b3c6bc275c7793e94cfa9923e6c3e7fa1c3fc0ad6d1063fd26ee347bda219b4c2ece389781355c85324de9dcc01197cc644e5f578c62f76c646a2f2a2f2f74ec1a37d6ba98d1a1e0b26f1b3e2e8bb1966a4d93a45bc23b0bbdc327f801df54e308e5a6341873932fa6eb069ac42236c3b09f14e17f4201ecd30ff07d9bb0b5ad0ec35ef285e1ccbcb03db0baf5a6027d36adaf47a83fd3713cc4733df2948164b3d912c3234c5c55b92505abe3a8abd0176899166509c42844efd67c0ce652d25fd137b6081b8b84ad2d4967916511b9c6ebe220163ae06a66672efa6bfe518df7c7ae87d26a2707866942e223f22cf5f3fe5ed5dd3cbda06a273843ed92a3d3cda03b2da42fadeb1689608f4c24effbff5f995f0c488c95c712ec9d62f0cedb06c75aa695bac0f3117fbd9557dde32ef3b6e6687ef068180cedf2abef04bf022994a1f0da295a89e12058e1a925b75ee9f0dde088e0502b1fd95ed873d088972f3d0ce1cbef444511940bc8eb27d33ae0517ef69e910e", "0", "0", .None}, + {.Is_Square, "344ad1b06f5f6adab883708b2308ea9d2100adfa0defbaeff9597286df99c1a6e1a8bde99be4ae7b49e0e9d306af7e8fe1e9a8403447ee65ed3521589e081adf85bc84a7c675d55550d2b7a420af0d6d74cc9d858ac14c92305025feae99df5032841df2a648bbde61de665ca805d188957298cf6d76834dd2a97b31156e9dd309fbd03558aa34885bc83c828dd08b6dc8c87f1290d6af862c32d268f4618755e37e9cd9ada331c661b525db497b567afa244abdaa48942e4e19753695de1d7e7fefe4b190c4ea98d75e2077608ece91a694c09c47ffdc353f6a59342770d6da8f600e83d2361633e3a1ad59b3cbe783717e53f1d736a9d4cf9025d687289e279a0dec32c4b57083a87e77b4928c80bb646be4367f425d8d7d1ca24ceede3ce9fe645d36ae9f7a07c4de5feff29c038c59ec19b5112a703fcdc024ed46ea5554f82e5decb4d42515a39611bc2b2ee09bfb2e98efb53883caf6e623c0a0f659dfc35a74260dc216699395f0523ef2b936b260e44c3151bba3e647549a01239301b5a7b6e8468f034adbc99261a32759af53172b9fed218a5f944c58a04e90a6a0b40ad81ee9a7c7dfdede3940131f38b117cfdca78484113f588f691b28a7ffb55efa9cb16557cf2bb3b0aaf5d6f5b98a0af7226c2846d8862f19f961deb51a71cba6d406ca87b264b9e99b418222c9d1251c1bcd7de8a6f354c962c0934fb0a2", "0", "0", .None}, + {.Is_Square, "a48eace7af3e5b124bc2405d06ac31025100fe91bfef5ff2383fecb7eab16663acb86ba013382c371b864dee06d7d20d65504aaf54c70598f870b564a83c5357794db1b0f8f878c48759ed687045b312f0558bf9b8ab310d267152f752a0b5e2ff6de00a1ac15d9fbf9fceb3be8ce30a7b97a5a3400e8c98937f9a4906592959f18eb5c765b06351dec4b4cbea2d1bf798387fb97e59555e7730b5943a29c919c0771aee0435cf1d8d9f6ac0c9e0acf04cfada4249beec8ba64691fbf14ebf6479160e68dd1e1524c3911e248f96aca8f6f76e0f4bf96586d72cac30456f54ba04301e29b1ccb2b4d2d0d847f2d826d0ff718efd7fba919e0f0631168fcf5b56a6d4a13e70c544419b53a054448a55202ea430fe79cdae18a01d01f22149d3fa5f428daae73485cd0e2b2221872f573fce06c56333832a91be9fbde8476a95f23645ba981b6aeffa661bf7c07a71eb51078274d3e55a07a5cf3b56936febbb80e3856a1f36d1a776e50f76ffe62c51c2f0f1e4b52f95590b789cbb0b140bfa119cb75b76a10eb7b90b11d7ef85ef0074abda5c7591d0525a12732b4379301a06b85d389fb0d9e4b56aeaaf52bfaefc1904d6812cac4c966e0df8f9c9a71078dde8f3434428500d7114f65f0415b86aa940917c88f4c0506e111835ff96e24443f1866e9fa08e412b468132e16130c39cc32bef69db0ab67c37b5563ef45735c", "0", "0", .None}, + {.Is_Square, "392ed29ffc30322e255fa63b543c7c5d7d0e425fd1a085e71ef38acdc3d933665f9ea48dd47f52a435259fbdd30b514f718f44fed6731c24ab9233c0907df5f19fed6f5d0b93ce41f388cec492b0d13f4c2b67b6e917a3cf74532d1d7b3bfd52b55a6d203f54729e6e022d11339022036556e5bb7d89cbf145e25aaa15c25f010cd1fa1373c7943ba8ddf8223bee996168ecb90d75e692cfb1e03bc8c3b394a0091c0056be2473f7ad792bdb7ba2a0f9f3aa375cbb3c854ebf5db1bb0422a2ea016edd5ccb2a34fdf8208b165040aef9863d75e5243355fc1af6e0ebc8fe5ab2a263bb11d2aa853b516472c2863746071582a3140f5cf18ac05ea01d770c3c86d231e95a457cfc2b664174ade87b6c709b4a264a7d3b54a1a8e24f8746149f046e388332c9c1597c0ce401cb777522ebb03937830d1e1f51983d93e9873f84aad6fa2879ba2b9ae10882059194f08e0fd95f9f9a4325153beffeb53afeea0e26246b907603d27a4085cc12be6e8ca2e028668915a8128e2dbcf64e75ed3bf595d615af5fd8a5eb4b606731eb0997ecc9761c9ede34518718ee98d2d8d8071b95297539203bba1676567e5160d1465fdb5702ff2fa35186950cbb90b3b4f2f307608340d160d16fc0ca43c35afd9c0ea4736b190eaa66c1105a306e0373b76ad3158755c01cc8f4515b3730532e86b8ff20ff711bea62272cac366ce715a2a2b5", "0", "0", .None}, + {.Is_Square, "9d1edf1befc70b415230ccb3bf4a0568566c78eff6c137bfc830f58943fce83048867a13c60edcfe61a679e007019ee906349986e13fc177f1450f5ba73f4453909eb10747076b0d3c1b7f025c52b754a135c8db3831c7c559c93d373a7ab5132611447d7fde4c7009d6a56fe691a5d48afae06b100559a92f38bbbecf90d81e0586d845efd5fe838f715a9bbb1f5f543f3b9c3593edf6ea6e0a9ac4da7d71255c067522031e5e22d4eb2baca6e672351e75bbd2011740126f17903a4d3827e99ce12899b7b806fb2b02be5fc7375ef1848af4803b3a75fe0e4462bd4a33615770d43f4a9d265a47e327ebe3e9473eda81cbe279bd2dd98a7a6828aa2a8cd39987afb9e37034bb9ec247fc13ee0c7a9c480ad6aa3763313fe2551af84d9c04b3899fc89e898c36a3e958e8e9c21924f8d9904fbb3be68d5bf0163c3fe68646c6370a39e5a1fc3d2060e9803b8d02cf9d936be73668e3be0fd8ff2e6de6cfcf15f1c5d5ed17a8c80f5c0f6aa59948324e86dfd5b791610ca371e9b57c1dc237bb2c4735239926d94539306c888cc2ce0ed4e2655347dff1b94cea76676e7c6df942779817e338f7b0174449ebd3e9ab448500154460a8650ef981752d9499dc5e93297ad66617b0dba547861091c8e0b11ac036c07271efd40565d082f23616bf2204760d5c07601b06e0bbefd0e643169cf47aa7c03e134287afa4022584532c", "0", "0", .None}, + {.Is_Square, "16458f0c767e449667a3beae68e097f890264dec958ee583fbad47db62a4344adb425349abf2629b6a2fee4d8b66f19de165ce1e8243f445b3c99a70ac5fc8ca1f220da13d79de1fc393bc42b91f578da7068733a866aad30fc040682a0e637cc211fd41206aa075c7e31a6d36a66cb1545688c25450aae464939a474ea78c59eb525885c8e88295cc42be10d35c6b47d14dda4a83e649344e3a8eaad42351bb37084f19d3c58b0dad34ea3f89a66f090aff1db3e2e0b9c62a57c05c38f2ce9e03e4b6892ffc399dcf77f276f3161c850d3eef895ce6c3bb1250296ec31c933bec335ed76d751da9b6e72799fb496bb46a42420a9f991e6606b97ab7eb9de66693aeb5f723c5480f7ff59326341f09ebc6f5c902ea878d860553c474975426fc14b01a833de84f88094f11e53155a8eba1543f91f20f3d17306ea903c7130a8b26ddfef66fdc4c7455560638d171c3059dc92f657f4e54f80107247cd9e2d931f67561cd22d529176d9ea31fa801dfa5538397b4823ac1b9abca14f9908e1e0b00e6afbd21459d64955a644d23244a8d6d5772872f80f539efbc6205218e1805ac1376d4a701472fc40fa97188a590aff31e3325fc6039b0c43329e6bce852d01c2258bbd83ce3959f3ee500f820da3a9dbb2340a2e4257ebf50ba1153f2d69c9ee01d8ade51bfcad89538c9cffdbdfa7b424a519f001ce147e98c36a34613b2", "0", "0", .None}, + {.Is_Square, "b069f752535588712d8de413294dde98671c628dee3b0fb967d28668e9f9c3d47344e5532536b43cb5cbfbc9e2d0fc391fc16f103b9d1e1a567266161aa755ee2ed4e7fad4175ca32433c2893a4be3d484621db537e2a53640aaa50ef4ca27e2ebf5d9bc9ae96549f639cd0661740884d43cadb8b483dba4eb9d0ed20c725a73e773ba50d74f47e6d7b492e9ece2818f45df457d90576f3c3e21d8436d657bcbd82ea56df53efd0293f9c578c3648e0c44d6f21006e03654eefccb02f17f53e3106d04547f305e02dfc4c43dc28dd774502e7ab3a0b94d4a6f5ff217e6d316f8930673b60e393fce1add52a1f0be9c5e395fdd69a2ffa59b43e736364612dba678ca3dd0bf2b685f14cbde9be932d2f4df6bd538fcf0615c987edfd4637d66fffd541d3be7bf586110abf0c96cca3703e6b9091a81b5071dfb9c6fd55f45c31cf332429f775b700e4c6c6156a0764f38a21d1d8ee51251360e2142d063faf57b0ce313f6ad2e311b21f1abab9fc55315ba3681e7acde12f1b4150615500e983c5e0ee0512f065f24d7ab0bd79fda93821abfe86febba27408f6f24a1b29b7e49ceb06ce69b9206136ab3ce93a8e349bef8a074717bb3c98078a8946d6a68718794aefd8b84af8e6d4574bf216f55f6264692f12081f62eb2d6b09f236c3bfe47f223e75cf34bfd8fdd667935613bd6e5be781bd0e582f1dc3731109ee5675f96", "0", "0", .None}, + {.Is_Square, "a7783804377d23223763150aae851fa880a9ece6db24ea6c464a739476fa7a84c8ef72858c19c1aee3c70bd05fabb534d1039cf9ad168ff9eee89c2d4352938208fab457f20b89e97c703548c47f4911889621c279b1ee494e302d546de2cff7af1703f52ef60145efe0df87132d63b29a567006700ba49a8209287f590142acb9070aa2159c132606bced31d143e5547150c0a0672117e1f0c4aa50ac9befde68019e0dd51cf4378a4929e6627fcedf8d42697d6b6c0228631a4f29830a6d3ddde57217ce96939a6ee3bd7317e7e2a8d64906f6ef57df13d4077e9fd161208137a553483b0a0dfd5b1f1d6dfedaa9f11cde47666d8d09a83efd4e08a991d9f2a604b0bf794443e3fea54765da7188595d02c867eff9e34ff19819b12c81e85cca8d51326a12a5530084427899dce2391931df8d185ad96fa00290319a33c9158a3653e33ec41140a36dd0c72c005d7f7b7db81f7546bbc5abe619b85f47c643c8db8a1eebb5be906d8ca1cc15acca4e2e5f3002c7e45ac66e3b725a339b82bbc2165e85548f30aae7ebf4252ee83c06a93d844cb702ca42bb5d92fa160843f5523d3e85eb8c037f7772b8dc8d46cee211614d75ef4de94324c2395a14444e991537a3bdd6dcec4e030f8dcd5e5fd6ec7a609abd8762c8e2ee3204057de617f7c96a0986da8444de3b1237c50cd5ff2fc5c67dd511bee08b328ef61ad9d2f03d", "0", "0", .None}, + {.Is_Square, "316273e812a4785499d309ea97b973a5437601d6092121f80f938635ae50cd9bd3c7dc3eb6f082bb0062c481183d360fb4164c51d839d8a1833d76b2bf6c088eddc578eba5da9f7528904d4004e64d15b3884957e6ba6924d7ffa28782ab358892d5205ed7702dfa931c57e7fe972a49599a95b08cb1abd5222cd040e94c920968db8afeed62664746d123038db04cb4e0f5638edb0ca6741ec8be915fdba1e455ef284dba36ee060a39bbb2f7f2678440aaef3766230af8134ea3a140c1848cdfdd14a3329d6568efc5ac9e62bbe44c4bcd8d15abb650a05861045aef5f1101ed0868d61d6ee9dd459c73d6bb7925e8bd37c9ab8e5ba7410b61bb9074daf6ee09eba22a04c2d5913e9f8255ba7782136bb4feb0f0694aceea208aaaa0298d4204e1edcba69c9664bf022a19536b7591fbc9d18b9c7e46d8847c45b2037115cb7d81c0d87f997d0eead99b13d6eb8b493efaf1d1dd94eb8d086a0aeb4059f5a48e35fc4d8ab83b40eaa78f5caee308f895e38348538df52cc7d4fc4fd37e687b573ad95d3bc05237844e89921ffb1dff75217b4952411792324207c366a6bf6b450445c3add93b2579b7cb929ad6302fafc6a4411a88c90c0daebc6daabb33a3c2a532c1dfbf62144674b0c370d4111331195bd4da804fe4142857a7fb328b997a5d176d8de8c8bded4272759d6b0b6ca7932e36f84f57214d630604664ce9b2", "0", "0", .None}, + {.Is_Square, "b9505334bb3ec6b3713ab05b027e14d300251b91a2bdf9065aa40659a9cef241317c2f19629c5ceec7fb3214723467067e1ad8d94c7f370c93f8b28baf898b14fd8e0880fb256b4b258e72f8a0810497329fbf5a3d98c01a1054af334b56a9f908740a7769bca1bf63a2b8f19adc7c76ed9e859b8b1095147904850dd61ed19f989910c485cee95f8a5e5843cfac0bf0e0cc61510f59187e19d88c8bcd1524608b1f9c3721838715efa1d66057b2288ee475e3e5adb3fceb92ef40bc4c8d49472f4ccdffe0918015ee8f1c3a61b6cad7d5ce2c8452d187952eed382e73565e5af468da088819ebb4132302541ad46f0efe29f618b934342937e78a102a89db4a9c6ed393bfb13eef2972133ed18e3869a8c38d2581e25ced7b752716c9c9b8ee65c70522e1866912a9517c956767b1544c9dde4e32d3228dcb52a895a855f0bd7c58cbd8c9057588b04bf976ee9289bf1b4df6b056566ae8c74a8dabf6a2fbd75a5058ab25246f308b3be658a66953de4637ea55269cdfbfce01ad62f0cc550340057bd34bd70be2de25c60b568a8f911a9f6288633b2f38a3118249021796b45014cde364a08b84d5c8d71afbbbb1094eed4cecafc24de943cf3a2befd27fa264948c3dbf25ba40feab619f35200fdea5bbd622b8dea6a71c365f2e9813d0dc656bb2779045252f0bfe1868f188a434b0ad8d515e3237e54e5bd649e509c52f", "0", "0", .None}, + {.Is_Square, "e68264d5ed1bba7ff6ab8638fb166c856e2874438e78e9d74b47b82cd3020d31d8fb2e0f420de02a06f8b5853f6a196e042e107a6f09299ffaf3d37e8f89270cbd979aee7eb5ce036034d0875d1bc110f8f8080d23f3e04717ab3d38b2c845683539b041c8fd60823326adfb65030411ba9deac22448d01d7ebccb66174a8aaa3a17b778a4d1f9dd3cef72561fecf691e6bd0782eef4d13804e707f7ccb656f6f117f4b9f5920c709fae92df98c12fb4c8b3936a652b18dfcacd126ce9b2364ac04f65af878519307a407c4a315e1a983e2a49f587c16b323b587ae9345087661ac1c57e466a893b2078c816f801101fe3fac04e8e16a9ac48b48dbd65097d788b0df66c87c38392ca1be11281e1b54eb5ed0c8d1206f03148d4a834e84b74e6f224d7f101ddae83e1f1f0f79a30f2fcccbb8fd7d86faa6bd4e448f5367145019e5ee3b0c41892c72fed21f73ce873ec4244f0e94d58640d83a6bf9e20b197815f09a9cac818063f26b7d578523213e1e6329932feb821b69443e88356e56daab00598d2b8c11e18fdf998bd507cfe16fe292d6f4ea4c86c019045b67aee6edd702f80843f513aaa35ac09c501232cfe2215e5c9e153c2678a0bfde14c2145a0e5b2012d1ac2bde6b05283aa54bd3c828bc994091f1f788a0bf2144edf4c5c9b569f8019d178c20b736f57a35cc10ca67eb2a85512175e4bdf4baa0b2afca1f0", "0", "0", .None}, + {.Is_Square, "ae3d38a20285c2c40bc05e1b6ef87ebd616c96f5aa3f68363ab3ab809fa852971016a6f39999686eb7ee7c8e1dfa624654f9166be4221babd4f172519a028e43c0484c94ef087f9481cfbf2939da6778d4a395ca1d808f5fb79935ab633d5e429e9a2f24a6dc9a5b613a1aee40542e8951bf083e04173532f934162447fa520afcffeff601fa51fab2bad3396f347a5966dd707a7b5a539583956b6a680a75f2758722098d60b3ee48fd5637afce9c28d765fd6638c5149389ae4d1885ebcfcc97e92fb1ea35902281d111d2f5e1a3deb086b65f9af6b30e055d61bfd56b60332effe92c4e562807d8cf4613fd54f62239194a2dc032743ebdef55d46d13722d588381ac7ecb8a527db267d39572d1444f3cc682cd750c2f7073cf8d15e7a460040b4c1c3eb8dba343f3728a2a74b0d6fa44073aa960e90f1a974c80e7a7b2d4019b57f480200584ebed442337e1d0b316d519ce1e5e525d69acfd8d5e7d00f8ea1616db5babb28f0f177b9b2bfd5d15680d28d117fee409117f6f00688e071e40433527eea226dc149c88eab34e8c2e4205e23398056762741b2735d451a806c6e1783076656c2316b5ef1b2c70e47a8ec21e51643377532ee8588d8fc1bee41855a1109f520b47911888a6fd68a29d32eba203628329e210def142b6e5ea01b15d1aa79e5a272bf0039487c3f80ebf0f0f9f11048717ae95a55e3721c43c81", "0", "0", .None}, + {.Is_Square, "52597de5592b577e97b7aae974bb483936f2cf9523ecfd5b0d126e9407313b248148ba7618c582c886038ccaf2b8bebc0356c4a28ee533a11d73ab950c5230ff50123e209d6b88f436a289cb750e59cc3960058430aaf3b0f3c17810d2e3f0aa1a0d9efac4e3d212eda438e815933ee036eeaf31e61bab648a4de64666f01c5c57d50122aac246eb688f9052aa7c4e7de74bcb0887227ae7122bbee0356079e6433b700a382d3aab5a53a6671a4636bbdc529cc055d4e738162cc476706f543fc71737d22c12097da5db285b4a50d3b04b1a037afa051c709941fcbaf70aaf908d822665262191dc50f740a90486b607e7793cb80c36bdc395cc5006dcb0dc611d9c359f70e6da75ab4de75caa607db1df3e7fe10a12bf5a3202b67327beb5e82c79e67520e27e146b1f94ad559b3daa3bc7fc0c4cc29e2fa81dd38bd5cc1fd5305112b4bf7e5100bc21f61f3cb07531392be82eae67e9fe4ed33d1bcc8af039ea7d21d6dc2733a205db45846e6dc0a86b531ea120013fb3ea782e54e5856e1c5e4f1cce183594f0b6f88b01d1ea4369ec77fa0419476318c20c8e467f2ebe69e190cc46eea8cc0743ad1865276ab92be9fcfeba642c5e240b0b6e8bfbaab47c2b6e309e5401edada972dafd59f089545864f78e3b17bc44a73309a14824a1b608ae5389c6e3d1dfaa095c83f6c14187c43d2cf2c8722a170452587b6bf86162", "0", "0", .None}, + {.Is_Square, "9a40251423a32cbf042d559906faae04ccf088a48d2e8420aedf03cec23739346147ba209a61cdcffc28a41a07115c1ee5a2b98f8b102945d20d34263c191b914b4e9cfddb30d1cebab9916a25d3b064f55cc3d9fcbbf39e184555198a53a23525747022ee3dbf37923eac02fe15810e6c8e1c1a29ce358993927c6df4763c4547ed860796f9b9e659ad64b7103bf744f2f75d0ab91595c5131827843c61600d7d45b2acda00be02f016c7e256aedc4167fab84b3e4a0ab6bab9deee0732ad9a1fd31d92dcd46313131ed1699545c6f1613cd18848187a8be3ea9b2a0f388182dc403bef59c164e5f0f175c06a7cfa335c55bf3dbfb33bcaa098ee96da368cf392b16ff3bba270609845643661926687b2e2158d967dec847e9d73434e32cf5bb5ea64f3cd758b26381ac09ec30a88b5b96d489e80917f1e6939d28f3fb18d68fc9c2b77f72b23b079ac74e0982fb24f76c4fd3a97f3f737266e95173c418529037b31d2ef3c6193e9b6bd8abfa77fb8aeaa235b687898963f00bb7dd09e2c967042f42607bac6f82e7fa2c9211d8a73f38ee164497a99ef607702fdc218721d1000899d30daf7cc1ba70da39673f5eaf1811d10b82d12e01c3283192c9740183c678d75d08e24062f83f33923fd232b0f9a1ee60e6397f196b90da82c5e6f4c471f0419ea5d08a59def1e056dce8c7881b885c69a43328ad8c5274a90563e26", "0", "0", .None}, + {.Is_Square, "63687b08cbbb0e46344c4dccd264ff394d5bc1f2bd4c9ded9d015934004912073ac871b39027f0e93d478250a77fb6ef3fa508348a17c12eab461b8c80056eb76194212a69680e5a1990cf95dddc9e65ac18de110aa137993b6d387c4234d321340d75350d1a0a07e3b4c1355b9e43f6df69143d09e9fd5f27b3911625e9604c3e118f82c6dfd99cf7c78f99dba0975d67f090c48aa4200dbb508d72d5d0e5474ec634cf7bf4fa634f5161edac6798d68486972d7400399cd41d24d043dc04b3c8cab11abcc15a7f88adf702a92bcde17c18e343546de4eea27fb99e31ffb98db47c45dc10382548b1c1fa096da9fae1d46abfa8e7f48bc3364d35cb8cee82261a604919d7206694043eebafef8020225df65a3a10bcfbf1721efe364f81631fd14e46e1e10c5bc589335e130a01dd309167390df41ffe0bb008029077bde3d5d69e35d550b7bad664d1d2c42eafcc7dddc733e5d310b6e0e17d35d821829b36e3fa026285a72251a0f0dc5a0769f960249e88effd506756de83747e35772ee1913f8b18b91102dba5f0e595119f5973cb241f47856f70bf5a48ac4a759a6d64d269d4c06b35fd94afeb55323b8eb03427a22cf2d26d32bad5d09d51d476e0989923ef4002ea5a24f10883fdfd6fedbe639d5ba91e6e03b8ab15cb0d4888becd5e5cbb10a109326d5c8800697b781ab5b1c9a2c7727dba76226b22e9434ed3fc", "0", "0", .None}, + {.Is_Square, "2922a476862dac1d6e5b47ef401ff17972389a36d9138bc4594cc88e25890bc76365289a73fd25383bf55b2d468de949cb178bbd5e38c76b93966c51b37f2ac27de61143c59132b8386f39b0e3ea3ef66d96c3636eb88b73f20454b11700c68821d07140a2b55122f808735d05afa92e1ae5b2199133d62ef7de337e1fa5535155e86db37084f6ea71e9c5dd058576df5179bfbbaee9c4227667c6179a8e268e19c7ac458a4c781e9811dddedc1646dadb66a08ed9962c08be6476f03599896bea28d9c8b58da5b33e42da009e5eba19b94912c793cb6152a3f8bc216abec9f7c3e6c45cda49f65928cdb7659d03c15aec3f9e1381ced7ca451a0de619cc70962c33e425649a4fece5b5dce90031a05f2a7c3cb99ae3e4657ce70408c6cfa8116e9310341d098480d5568c118cabc1cb5e610cc7115644831e7b0177b22bb55655b8a567d4dafe29349e167c8f1aaec8b8271817988aac632ec0afe528044ff3f417077daf90b034b2d4e69066db4e497fcc08fc6cb35f8b5e0a849ca889e5405f0971209ee582b13438c22259a165e8fcf052c256bd4d1b8469de81b0814df46cd59fb80a07f79df64efe10141e63be4235bfdd58c1518d184064a4f1fe03f57ff9568d800ccf2153ee51d64ad77daed6ddfcec0733825605e315820d23cb76b703e58124f8c8d990af288153d5f38611e9dbe2bc4e0b528bc0b12724d639c5", "0", "0", .None}, + {.Is_Square, "ec6c77f3e7038e5109dff6806f1185d9eeeaf944ea2a1330f553eeea760cbce7ee668c80891459a2a692932402b2d1be26981e9de7631af664ba1e52030432cb27597dd38c8e5b3cc95b7954ef1e5b586dddd43cf9cd4cbf48d4044e1e73b45bf28a1a3bbf20bd72d685db53609e2807e7adeae937f0edaf94be848ca4d9d7b560a21e3c27545596b6ea22d964a2334b203fe95539efa342c16bcf8d3e4a11e844bc102fc983dd63743f8bb3a84f5820fc705faaff209e9de2ab4732fc08e82d13b7831fd7d291657866ea034739b6d17e307ce2c95df0a4e657b35331e7868706f3f5e8ceb66e713669486dfaf99c6030174ea96271a9f452da6f0090813c07a6d7a31dbf57d8c654142d9a1820b17bfa20b389a773ee3f35642a6e7b299539f8e66daf159c8fd134edb855077b9b596dd80b4a99ca830e73e65f12ed6679aad1bbce65fa296b72bd24c98dc12d417079579a5e48219eab18cff4e3a6964ed5292da856c39eb87318f10cc29c0d6b2fbfb2e6ac9c298227f2c9e5aea288047fe84476f013991ccf1e04601995319616e8fee2e5f2e04fed62179f8ea61bbac5b8f1090b97f1b57d1cf4dbefcdd0b03b13892dbe5cdc5adedc5953edfe667b1ec4d7dacfe550d17c02d51db0b9eb5882ce49d9d5676791a99578206d3d6cdfe8a8a8fb43a053df7618fd0b3bdece58903b159804c1fa8a2106c993a37cb8da5e", "0", "0", .None}, + {.Is_Square, "a622662c0e8f94a44caed23c3c13c517200bbff11fc2efd980d55ab24abb8df7b294e9224656cd51adde99eaad51a9ca0b8351791768f665160a8f59eca10744f898f34481f4f86db231811adb417ff9c5fca3a7cd36c87b13958f7288bda64bd5c1ba6ffba525edd2ed6c15164a8376e3b46a3cd74310f0bd0c926a9e352207ccff7a149a4a256c84208666cc3f1b2d34bac0a77a821eb7c69587c329eefc4154ba30e56a182e98d4e85d03041680980a0b2fceadde753597b3f86874f6e045957ee9fde172e32899951c94c92aed3697b2eff573dcf6ea5d3ee662a02620cf47d7d83e3e216942af7b24ecee74ab47b9daaffbf0a6219adcdea0d72ff50290ed3f666af2248aba49d524d102feac28f50494812b9b7a07c29a84a5b9fa8c10bd673cb6e4c58fb0288865aae47c1e99192c66109177681662d4a3955c636cf39081433470d99ae32488cd8e620ed8905ae3678265336ffb3277198ea12b546c48c3ad9028fc483bd5938d71632437a0db8eb9e1f66c3a5dc2ff87b0931d3f550fda50c67a607713dfe6ac0f6ac8edea6ee8e8aa7c46e3b9fadf213db01f6f7e1965b7cca8233145ab943b72d466657a09839fb5000537731d277354ad1729338e67db0aec42b36a3cbd5c8ec4c8cd2fe80587d82fc5da954510452de40bc70c18d3cfe23610f3213e43bf663241dc2741ff225fb86db029978efde6baee1bc5", "0", "0", .None}, + {.Is_Square, "ece6116dcf17df756d17ce281832961ff0faa22cbdcf66ff23f79d3fb8c539d9e9e39b528cc2ad10e9f1b76f2a202eb333b90cccb90b86be994783f78db2a583466107999a1dd4bec9bdc9229b3046c34e04c5adb58594671b2c7857bafb9a483a0913a98a608c384573666c48dcbd89ef3b216da8de20de051d3e90c0549d1ee1432497f14308dcfead55ee46285dcb9dfc806b175eb100c28852f6587b20678963fa51dccef9ac3c84d078d8fec80d0da308be94a219f2bbc53f9fe6e5671ac7bdb9c21d5a90d07cfd8b278675a0fc419786836868dcc00fe1f8ce140774ea9ac90235d7f241e3d0c3c630a4f4a0a7bbacc6a2a5a341256669799d7dbe3b76c328f39808a22884c44a897084a7e38be32c07534814c4cdb34be0463c4340a775d1fff86415adc8a59583c22528232179892e84f0a5442beedb60a85c618e444912ff2aaebe234c8cd70e21ae665b0efcd93e41c47cd1c6e5de5f35c79d3991c7aa7eeb86ddee567c6e0ffb40853c549ff806dc26c81f1b06262fabd8843ea6e71d66438b8317e7b19f3e23e903d895d1c8207e1436bf5c74e35e5c5a86399974d1f3a73d806229f3ca11bf9e54c087e9c8ab8c8fd2ee3cc8670341f19bbe6629d9e640d0124315bce428b9b1215b22286ab779d7b809b1ba18b13ac128a7cbcaded33913398a38167f14c304c93bf0182786e67b7ec684f5e06c173800818e", "0", "0", .None}, + {.Is_Square, "a1c857bd48cee9eb7fa14d392a3767062cedd98e2a8701d05679b1ac22291d6d0c96c81535c2e553bd122eea6e8b9b244eb7aee86bc308d9814327fe33bb266ed5dc46b20a7c57bf2d2da6ab3df3cbec5f2b99f04429dded65a672d4c43f72526ae9e55803a2dcf2ebf951f93afb9f72f00514b4bb4e9c4c66525d71dfd8f846764b7bf87dbab88c9df178c3acd1f2e9834417ee04fbc045b8d6f9d22b8fa8f4ea5243869dad797254b0752cfe8dc48a42f52ff4b91d511f59a27110d27db2bd221d906d1150accccf0b9ffb7d9c39e861fe7686a220a9ef07ded1a5da4918b1aab68d5fac32dafaea6a50bbe4a4c4dafa4ab4d24ac7376ec9372248639939c7fd519991fea03ec9ce5726502719f71c1a35f204326c4c7112637b99d786c12b5784d2755043c491b9e077fe397eb5bde356811a0d0a0262538feccf24638a1fa7095d23a3ed705b041a1e3036ace7e30ac4be8ec917d8f149cac45fc605139e4822ff72b879abcda246319749cbda69f8162a5b9cf9edfecfc81718effdcc2195816b2508bb2df37675c6a08a122e2b44261f0b15ef0739c9cdf86063d155c7cc96b713dbd5ab1bd80a8a56cec7bd14babb2b5eb299848ef038c32f65175b8b0dfc39f36229f6c9e8730e640d276e53ad74e89bf754f54d40b741fdc77dd046ce1c50c2452e5a8eb15fd7a53de537c307da78b5a4faaa5afd54cf18c97f84fe", "0", "0", .None}, + {.Is_Square, "12157d52ee607dd082cd1120d3c15d4ba0a405746428a4f64cd86a0ac4226b08315ee9ff7902367db70bcfee3da6e66da59ee2313a81058411bcdc7f9989717c3d6889dee40feada7d611907cd7365ae635b613b8a59547c3a2a38775f73d03130b1992a71e519909a0cf606076056a0b679d5624e3476541b84275a0e15b1ecaf32f509f4dfe2385925f7c34a9192031147b03927c756c43f721e74f45477f2d785dd188e5b310f149a6a6687ff02af9dbeb87d5bd7001c5e06575d224bd563e0c765e6bde3b070adfb06960a1f57adbeb668d3c163b095e1be882a81229e39ddbe9a944abf979a782e614f8a3c27104a5e74df17998359927a5fbfbc35c813e5a6950850c12159bdd018be1aa455aeb9cdd0129baa44b90e6cf03e6f3987d1561a809bb72fc77b50ca362a10482bb3c2e3b52c728fc815625a6a8c3c3f6ad802d0c008a40bcd44dc31b57c4621ab5838e162dd01d46df30eb985881a18c4d59004b288e0650ac0cf27bc5498bde1593ac4b4435db4c1dab243405be8bdcd4302c4b761f0a11f037bd2d97577d8f1371f74923f2f1c17399e961ba1c9d1a438df215a01e9857dba66daf6f0bc421aa87833d61500a7da0e7dc9ca5e3f958f70c6181de5b2e36c85125d300ad1d13aaf776e88531763501a6b82b4b4f1bbc39894479cf75dfd1cb873b6dd05870f6f6759ba0d0ba7ab16b7d643ff3c29d9d41a", "0", "0", .None}, + {.Is_Square, "36b78613b432a35e42c0d0af492359e1fb57e12bd5f84e607c8ab7a4a7ff9a6325ec59d8da56024ed9c6e51e2767f7f3eb4ee101ac7de40e5b29f86cab56de06a0ade228dbaa2d691d7a6a91fe5760941c5a56cf0ef6f10eb8aaf04f937553ae5f4a9b760f0e44267682d9e8317f9a51465f27c569c32f9c71dde3d43ed00065515df0b4ea37a5b19293c564d7df6233ab366c20ac771e187d10f5f0a47474e525fbd3062c34db9f223d0be4c2197c22c2908ebcd08e20d121853d89b19f53143a824a3b7014187519802a47a0780b27d8ef5a473a980964198faf5d7f80c1ca764998869b92a4da206d4bc5edab5fca1c6d1dbe2a637688a63c1e4539952ea01a3a0bc85e36576b97b70ec38f690bba77b4dfae8048a0dec286ba040c709e7d0baaa455f4655c01a2cf54358076cbb75ef5ff0dfb1b6a0142caa5448a10ed1b467bfc90103745eeefff655d1765d9e65d25cad2b77abab11c8b3f6adb5301b6bb885f9a433b4a0ae53811979312e1944ebb7e13dc27ee4188cc76c9405ff690dd7a726a1d6e6532435248f5c9fcc5ed7d2fcf69c063dae158293ef372b17b9e47eb93b43870b3ad30fa36995ee6b016db1785025f016d5baf38b9a460fe677b45af316ab37539a9a12e1cd0411def28a47a7071f821d6e00a094c241e9487a8741cb767fb9f27a13603b34eac9845a86d058f662477d9c6af417d84360205d9", "0", "0", .None}, + {.Is_Square, "19effeaaed137989bf67da6ff3cc28f0bc8daf8b4bc5b00120c320e9a594fe7dc7bf80703d4fe7e25f71fc39f29b47b87465687373d38513574635bc63bb2203d99959a37c09b2ae47736831f8ef4bd7b001c315110b053dc10f3a8de0424588c6c97dec34e63049c7ee03aac89985ae96075c06a9edd55c7c6b24396fb7d6fa1f25b3163a5aa33b7b7bace51bf27bf2d72f2b855aef1f6130948e8b26dd98b2f132a73841e27b7c5ac22e765bfd10a8c52608f43cc67cd3a81f50905ae1be28b19d4d73eb7d4cd290629665df914a606357f17ce626693becc85ce2390901c6a29c6372f714c77ce16d334bae7e9e8a1fc330e123fd3710637e37774237fdad4873ec67faf660a9c201540b34f4c98675b47bb868a418671f60f3bb8eeadf1f159a3f8b6433bf79abf6a71fcfd22571084048d2d9fb7a74def5c8cad40f1634a3403a2062ebc18828f08b0e8b9bb0075c079c525762165686a569ecb3b83824f60e26b5f3358244d96bfa618e8dcffe26bb73f617c5736be11654edb309707cffa902e546fabb4ec79d1d9942351b3b20fc9a7ecae638a1c76258ab63a802d56babb5ac901746262448aba5e3e5ac8b01de17bbb6d94e935017550b8742ca488fefdd2dbea4ea820b52d83c1e84c8a91158d537ce2dda25d9f0a7e688c00e4b081a14656949fdcd18c618ddff9c27b7fead48a967851d33d6322833c9168266", "0", "0", .None}, + {.Is_Square, "957090822800f64729aa1574080f779e7b1a02d1e710d60fa281319afc19f030eea1041da5b615e1fc2d673531f24f17ee6d1f97d0eb5511e66b295f5d8899775fec22dca7b54dec2bea77d12ad8e215b3816ee596c72cb54b075b442ddc12d932b4ab1554737cc2a78723b9814fda0ba30b80157e6929366638b35acc6a5855eaf796cc2bb1bda22aa7a869ff235b8fc6d782b950a4805879edf70ffb1f91d256c4db8ce923082ceb30ecf89748917795cd5515c45619d8a43a91b515811ed3d7d8e702055aa27e0dfa4fced46f627de5d3d2e13746be0c5233f0bcffa5cbfbb5a6241290f6f491cd1ed42275170f5d716c90d1c88f384e6adc618b4f6c6a9378e6794c729bd6e4560932bc571ed533cc818d90b8ac5839963e387e214133ddcb1c19975be26d95ac5a1900df652a1f0e29a52c8f4d4f440fc02e6964b6dd0aa6f9f4048b78d0ebf0169c6ab182a343db6bc69d854b9d6124f7248321ffd77ed1e5eb376426d1b07039881fca9e3858d76768e558251fc898698db6ce47f2f4410b329e2ffe462fd09ef619fa8f0f1d675d2e83c74a278d79f53ebfd28bf4f75c1e5e0b32d92525d7aba061b408a3c36c78add3ee5dfa5eedc4e5205034bb6addb1ace530fcc2e56778c3d1daea69fbbc1adc4ca7a8ef77a8bf1ea96f90eee66723f8210c6fea816d124b7c1abc70d28d539a7fc56c1de337294d03c35db6f5", "0", "0", .None}, + {.Is_Square, "5e70f2c0bb02ad0007c7dbcc4dbbbd2b3667a4f4c95f924f3794cdd6086b9d893c2c3679668e2032234a9443f1c0efdde9055e2815682a57af6104a9b83c7db850013a8f9936c661a3b10a44f0b2fc6804404c56d6a42f2b527f6167f0af38f7b6a325318fb9eddb98d5abf490a4cc93ee4ce16a0ab53e76f42e97ebb8f2f051a4a8d4eacc0e9f0329cb753bbe2eb35d410b077dabfaad0e59397a6649a57f2a0bfd13f79f4342ce2045d7b02cc8374bcb6c820f7d4e51e5eb1c47fe18a492c698ca373a8c40f1ea61cbdf426535c61f0edee2e383411ebe13c8906950a5e45eea9eb8de1276d312aff648a3b3afd98282fbd49952143b48baab6502982b49d86c707ff8b3c86adcb34327e3c1c6d4d43ceabb39a2b5f1a2c578454b010193bd493aeebdf668cf9a7433bc6c1b28597a30aaf553065ac6692e639d5e7f353b4e7ed9273ab7610d8b1d934d1b9c7a5f1d7c21982421fd0bba442fbaa76bb8d83c08bb07d46dc0ff2827f4699dac8394df9702a457f1026de73f86d50e0ff024f2a5cdb9786f68558c01cf86f9fea26767e7cc11a2f3924c36461a139d6b7d1cf60b06a4c49260d4b73f1ce80771c5c34b7e62873ae2c6c821d71af8b06b35f6814572f65a9c67679a0b4f1bcec0294063c963e9c1f4b86a49d303eac76ece079ef7acb9302e17f4bc6d688703ad2e0e44224fe4384ffd9932fdfb8cc05df87db5", "0", "0", .None}, + {.Is_Square, "55c7ff5f4e7eb1d0ae6bfb4f0a54ef80d657a9915d8547580cb356d71c33ee41ab261417ef028f58f8467d1a981aff24097beea34caad62d8319595c534ab7e6c8cfa7fa74f37891254bb28261a2f65f5fa88e8172b32f303a8a574f04b7c2ef35398b6736921402857e54f485d56ee7d221a41dc6368d7b65c227c717dd6d70459aa815864d93956ebd7be7cca1b73c61c565b0d3d9cf93bff91f6bc7d9dcbf6cd1c133dd11c0ff1e3c68094b86bcb284aacda1585341c468ce61b9b96d88cd711b0f520dcdddc481170be0b8006433250484ebc92a7d9c6cf1a40643de21e11b7a8ca7550f5c0d83682e72f0eb5b0b00a043691385b1b91e4b7de4418b04c9623db028512801770110306919576a84d4c45db795edcd5a23cf6f3e130a829ce7ead06bb35b84ea1632875d7b512f920642038a33c079cc088e86707a631df1cbbe9ccce04c805de902267b9c2bc6ca8bef92880e987dd67cbb7dc94604954641af656a6948b769fefe61a6c65c155c7e8a0b372c70a8dc7d0eab828a3a53b8bc262b55dbef072e23c317f058ac1edea6433aeb58fee18d17a41055bb1299676bd1de15bcc46cff194303611dcbfcff82a8a43cd9e50aa7028c32c6c3b5efbf1319e55445da3a101ffb41a47045bc6033109db49c897c541f5093b14518a3617757915394c9be0d95ba9be1bc54950f5961469d7231bc13245cbc2f5aeb99f8", "0", "0", .None}, + {.Is_Square, "b7d7d755ed6d6c7409ed79b2f6c936056a0cb3114e686632dd9dfbc50d7d7c1b12a97f0281f30bc99b2f654ac336ef3af06589d9c805660032b00c5fac29efe771d75e648cd17d6c79f459b2b4a6d4ad8232c5cf90af4c8820d0e1e22df5cd5c34fa1ec1f7f84949d7e55825ee556e583dc23ac1cfddb2a041b7d9b6b3f8865def353feecbffe17ae07522e9dfd62849de4446ecdd493f3b9c5db4a144720323bb7f2d00733571721ff729ccfd8df354b6a3ba87527b799cee9291ca4a52c1fb90f1f28e31acc7e9d684a4aa6690531874720a693914bd814358080f31d257d877fa3f32f46ff4e812e3ff75632675ed85871e02f3f4de831fc929c10ba503f0310d1b8ee592396d668944ccb848584b40ba8ca977e3a715fbad0aa8b2159ac26cb6668a809d4eb1ef81c399009c2689003163559a123e4199bb679ed2e6d8de1541944d9bfa05d439fb2f3dda31dc7bb294b07d36f11df022af4a3285b9ee1774c2f8bd1eb4ef4071d6f87a6c22d98838b4f8e5a776c3b5dde617ec93c6a7b4d1509dcad6abcbaabce5d4e0ac903503acf83abe25bca71aaa86e660dedfb6d53dd4700a50923abe6acdffc0daea662e4525693e84b52c5eed17162c23237e17d8989b6c08947cd7b5d3d9bb9f12836d7566cea8bb9a9c41616821231d29e936adef7ff1ed5db0908559668befb908025a6d177820596b76163b60c580fdc423", "0", "0", .None}, + {.Is_Square, "cac14714803d4a9741b98fa24bc900218894e950f7d6ff2129c80791dda8efdc90ca7575b657f70ba4d70840dc6ee35594e9b241f9b5344bd705fca52d009071f9a07f856489830e8aba3fe333749cddeb3d06e996301c442b7b37b6b3eef57c230c7ed01918f6744c32ad7ba7176c6077a7edfe2325e32e4d75cc85a4bcdddc38080df4948417f2f9cb7818fc4de7d90a0177537a821100a42a6d8e740b4cd7f7407d39c22f05584fa293474c599018de2938cd5d166ba7c349a47e7e595b05e933a3f9dc089f3143bbba33909f25283dd52cc899ac5e194015e6aeb361a09b14d1d15d08db58ddfc1cbba18abc1957fdcc275d77d61483d99f195dda481b4d52d9063101648d0efeb79bb896590c8e51772c2ccb4453059f3fb95c5eaf4d815a4c797a540de0fcc6243261f85e3e4e9fbcd6536e35548d43b943b79a08b777187801111b4bdfdd60e996ed6e7f671f2c2dc956dc35f21fe7bc553e016b1a05e8a97288a03b4578148767fe1863f9a96567af01a3dd64a390585b766ed1dc4683b31fbadfe95ef568c5eb369736b71ae84f96d088f6d00a54b3b902d1775edaadb6fbed899f88d2309388fb9dc5a47d58184a6401ea09cd08a683825b7e084913be4416efe01809d350c2ae4466991ad9cffb04ff5146406fb918e8121767678d5831366a57dac65bf9f0e6fcdb79c3df01f34ed499d20e1b4800efe02325d3", "0", "0", .None}, + {.Is_Square, "327f14fef2236f276e94786ca7d2e7520c7fab6da29c43eaf8a7ad3c2659a78c75eeac55a9e5bb71e09d9eb78d11225d05178882383150eac32011f42c3ed3f258edbba6d86d3d0e8616384e1a5e4dd0f0ac3547e73bf8f03928bc468e1ba0567790f035f27a58c0ec011202de8e196f2f98142c31ebb566b4a6d915b78424fd8335ff9d569dedfe0be95eb53e0eeb49c5e7e988808f4d913f77f315b0f8a8ff80c4862e0b0d3e9ac5686cc99a0a429f8677d52a72b91d048229d0975c0aa82687a01ef5d6b299d428b7199b3168486a9f04f53bdc817709e8a2791ac52974fa204f81775137775dc97abc64f1c8270ef21a204bd093559277ae62788bb8e35e5c297e1b167a57a11634ac691285f7dd02aa9072cc7c7b091b9d807a8469207a51a1f5fc8e4080e21eb5fb6449c7a7961596c2840806771559b2dc91cfbae280fa5329efcd677a872f78d1153630e6a2cd4f0241f51ce66bc4e4812bdd85a337b0f86c4609c49c940b6643b19b14f8d94a7bfaea0a7d51c5027a69a776f0bec0e56ead85a30a135423dcad7bcb36652bf1d2a40af6d649755df5fd0ef1b11d5bb019f6183a8aacd7c115ac4a4108606bd3d5648ab0137351f1b6a967c500128c986171203348b70f12f7f0d49833fc62b4ea1e3cec356eeb9008581cd3c47c55ce78362aa3c4cffc35195df0ae8fc30851029c1d2d25a0f108780da0f7e9079d", "0", "0", .None}, + {.Is_Square, "42cee97231a718a983e1cc5b01393fc450f071df90777c7c36314f204873cc57f8153e49e73e350cadff0373fc6bbda1ee5f9b56b7f6e0db6fd8c730e02d0599f3aefe3f011039836b4a4724e28558eff94d808b7ad1411069dc7769f943bd336392cf6bc92fffdfda59db65bdab646314dacbbd8ad53e2a1cef6d955ac79d11476ff44828ca97f2d3c030643d36bfb41a638a3b06a0e73191f818861310515570cac7c5554fabdc1912a75db397fdf7ce49d27e1f01ef04ad3847ddbe10b1e4f397f2d5e971bdb5935710045154938680dc7ca4043434065f014be0ddd62c805adfae93141b33b4e730fab5f741502352b84535e2e8e7aede6d162519e0862288fb0d0f9016aa44d3305e9fcceaa0fcd870c33f14c2ee7a398fdfb7939f9cf8281c17401f3142a354514a2145631b89e83fc6627dccee36937aa185d9bfad94637b804235335171453fd167031a036b289cfc857cce8f944405cee5f7743faa2c4ba1a32eb9170bd9aa280318e0b2ca6962a86a0097c218538133c6602f8afb17c41470697ca122b649d14c94a86668e1db3636d031d02010e109805850ade716d1f3d061a9c780ca4f75d897540cd7f566cb633d5748deb73153f2b41e5a22a1cfdd4f86c4e2108bdae3635a4c560d974ccde7ca061cf80c8ac1f9b2d56cc8b189532a9329ad42c7fbc6c85afef04cea74539c4d0e2b02f35c1749a1da108e", "0", "0", .None}, + {.Is_Square, "36a6b34085aa60a958588f00b140a137eb20f007895ee1e72bd361f8e3758abcf992b9874c3939a07e72dfe21bb4e58132db4ee1f9754ea282ba26c7f2cd9984acf5b5a0352f59b1dc9e6240e09b5de8c3a6578e8ae02e2a050a4f60b6bca4f987e5c0fee3e02e88e8cdeb192dfda073a90d1564e7030132583b400c6c2da4b9ae89b2345b658b338be75b51f00bf2d768481902f50ac7ef671ba7c24f8d359fd581358c8163cc6927b4cf7219f3428edb22ac4da5ba40fd5752f8e0ece9093487280cba29a7e902bc3011c9749fde4c920ae1f090840afa093c07529598b7f0bb38dce6d9f43c7c670ee362d242445c699141baaef962a470f6726a1d7b19fc150a25d9a193b36239bcc216c91e1709713c5ba5e8f541791f1cfa104928f4ad3767b068b1ca3c13dca7767e27f7f1513aeb95ddee6a266df13ea59b0a2a1300f9ce305ccc98f6e1e7223dc8fbd1ded067403c3c78a4e437e607a9a4662088c5814a198c7f9525f03ae827046cb22cd9795557dc89b3ee5aca1b4e9b6bc23e7169945741482ce3314ba9103e5ce90500e95db05e83b7480ce5694338cf4d78d0c48c69765250ea91285a0930979c0cd39a29d270ad5272cb56eb783d9f04600bbe2cf92127f7876aff1db4829c4ed500934d335fbeb624b5bfce047fb25e3448de5da3cbfa1cab1005ad752dbf81d1d9257768b1d8452d324373ebe1202f02ee", "0", "0", .None}, + {.Is_Square, "3169f2d66844c185740fbf3b8870a63e99a900f1969dc0d17b9818c079bf94677235963f5ea38552e0a00021b4f0de7940238f32b046c3800f1f6bc17b724c9a4c621e56d0a092fdc034a16b115c076b07433f23ef78a45bbd0211325a537f182df4efa8c0d1c4b51b26625975bb3a461ed5bda696c35017d837df44a8c0236dad03d3a3e90c1c7cb07e4d4ad5af70782650201a686ce16410901c9f5f86eab655a3afd58296abde80b3aea58b019772e1954032586bd35ee097dd3bc549eb03ee21d4fa4bb65cd49c44c8fafd5bfcc23f014b1281cff6daad1eb9ca7e5bca7c1734a3ce0a35eb4c60d0fed2773208b284a2a9125568e1b09573850c6988082abdfb6aae8985a992b6f23e21f1b7d14e0540c98f077581d476fad17a2e9ed0005438d18c241b38c59cd20c6d82adcb81c39c271ca14710a458019ad4a064c465f2cb5d7df56a98f2e17c25b2bd57048ca3150e1f1a712437ea98a92d735d89d1605bee3f1cff123f2bdb25fec65a6312c02b743bbc69bf09e4fad946b9c40e3d362fb4638edf8ffb2a34dda31fc04ab4e6dee4ffb63dd2ab1a799362cee4f02a9b2e64a3e7785c77596312c13c2f0ff9a21fa5bc2828df97571f15612ad15a7553b7b4137c57fade05a022f3d573ea61d2d517e39da458ed5b968a399a7ab24b71175ea57c8cf7c9a8cc69caf8689b0f08d96296487484eef99b0dc10ca424f8", "0", "0", .None}, + {.Is_Square, "7d050a0633451f0380ce9477e9d7296a5801b0835b2f2b49e7fa4cf08ed44554a0045c15e42d34029ba692c3be97fe1a1d4d28047535bb943f01e2b48b7242d710ac96a65425d97aa7985768b39b3658114f362a50353864863cdfa167cdc9f3a068cde774ed6a17a18a16a069c5a76ba917304d027bf3fdf43f5fb426c29c047ea8e48aa69452cf84e11446a797d01fb0c620cb10048eb41cebf1e3ffc73625fe376bdac1f939f3dd03c24b60c4a35a55e92b388c09e78ceaa31574d4e07d0edc059a116026d662a0f649de791ad131b95d2d09b3bcb94128e67285b5ec4a935eb68675abb4830a30f331ee60f05bd7d53a9170dffa2c75df7f76844e69e09cc542cbba6dda9306c0391e8f2bad9410594b02ca236b0098a36664202610f09134123f117780a4cebeae336f89609e6852418ed7de0f69f66ed67f489ad8f79e0b2da4557e96ab6bcc94d81a299f05b04698c36211ec16c63ace26648ef8f5b460086e5d728d89140e140d1d93d8cb160c155f75cde09a3433e9cc582c3ccdf9f4dbbb3d6f1c387dd7d2a8b6ee62265d64453b09fb36b176e049aa723c27edf571c88c959da0198d6df42750626879b0cd2db03b74b4abf60400a0b35ec236cc2e20e0d59d3c59a8c9f53ab6e5429362e8388d0d9e2e166e67e764f54155d4cd972e435f6f44ed4fe05b2dbcf34d0a46c4c4bc9ac9a767665c5bc54b85e111a2", "0", "0", .None}, + {.Is_Square, "eeac58b594136f4c986d77b1afdd17f9c621282d02d4fc2dc5999afa3e7ec4433dd988d42dd92c5b0b71f1b9c52c3a27210bbf60ad8becc8a39d6e452893a0900b2fd3a1f071c91f92c201bfedfe008ff0db402e5e57af861efc33ac0d8452ec73ef9e5fd8f33ef59193582765171754c22abb8a2666da6284ab8ff4b2ff534a3b45cf031af8f0ca7fa0afadce70bccb0ad9a5a30825d5b248b42e1e5f096fbdcc0a4c549551c189eb04b01d88b4f37dd8b0c262de2787e798bfcd7c84046c1f91456a7b22ac19808dd91a5d6e949b31a0db4c3ec30c33bbbc9a5b000248edb268dd17c6dee9e8d19ae01319b9e8b7046b964e0bbae1fe71910e944464b06ac6803336230b3e1fb9fa95cdb38546d7c87a16b39c4c2edbf92f35a6abecabdfd3c9ac8556788b4ee016a327f6b9dfcff210b0f7cc55dd1385d452c5c8ce885adaa3152beb0870cce92c495e941c23ad078aabd22381b9503dabe71682ac3af1a4b912fb05b85548e2b7b62706efc11c8f2b38794628e928ba70e793cb904801efa12dbb91da90c1b97bf36e6be6a2431b6f731b06ae50992010c98b3f9a6f6a6d408c6808a129ccecb4c099091049508d8812df9eba6cfa40f389ba2cd33c06feb4bf1c72e3bff75c6f3ad0b77d9dd35bb82c1151f5859b211949dcc11a7bb423b336a9310978d7b88570d70476af43339985aff2ad2a412d9737c14be4e25a5c", "0", "0", .None}, + {.Is_Square, "910dcfb105bae462e0f81eaacd864f1d77cd8b0e05b3f6f7efa58a3729f53292d6473f4786e377393af2f45e478d419d8b199ab4cc82975e67d79051c383214d4cf5c31871e587c536ea9cb22cbd9ce0f2e8f36dd944b7dffd8fda3a85fd094823ea945a9d97abe8531be7fd8416c249b8b10eac81e4f0b1fa892133a63cae1ca38acb41849beaf6e9bafafc8760faddf46bcf4b4e47afd0b96d9f9cd14fa220bdd320257a3641e9b43a63aad4d5fbd1f113fe52f3ad4d0e4602a5e97c61b2268d2ef3de108bbcbb613115599eb48ff4e5f9cf542932380d9d3c5ca5ab88cb10cb4770a4cae94f9e022ef0aa58bdd1c9a93e4d8871aefca9d47f426745f729a0ebe46fadeaee7ac4ac86e8f0c16689471aaa2a671fd92f982db20c1a5585182c57b85bfad69540cd41f05cdce74327f90709f7debbe7031458c740eef6b159965e10562f4da4b34424c827ba345d4067745f4bef9690b9340df0cdb1e61793a5cbf9b0da0d16fede5ee8a60ae913b1fa49644d03fc1df3f05c012f368a24aba27a4152c4233d75334b0f86730fab7af6ebbcf8d2725c692ec76b7185acef3104082825978f2370106131467d6a6840dc3cdc00b3693607870ededd71871fa95b18e728de55cd784efca87807ec8ad36098f60bbd3a31125f9c54ea5a93a7806d76e99bce928e68ef82c303b6a7daab85ba100dbd5f9c1ff10986f767eb6e6f41", "0", "0", .None}, + {.Is_Square, "d618078e27b08a458b19fe4bdef243d6340388545143b57624c6170a25ebe9db3fb3ca7a32542f3e2ab61c79e89b444fb8eaa17d3e04fac48e5754cd5c8fa9658c490de04623b421aefd7f8070affe40987ab109cfaa1b9bdd73f0ed72de0b8585a16d77d43e8041cc2f568157a132f4524135fa2ca32414f68a96e53dcbdbc80ecff33c50d0eefd3cfffb2a642fe327c2cd94e5d71e4aa5677bd6d4dec90a9252bacbf7ee0a72f9af0e1494907d8486ee4d10d43787b1925cb65d536df591debb2d508a22546ef80ff1a9c8d01aa5ba5531fab4515bc68b7e59493124ffe0e95b55b7b269238e58a576d96a8b7009c3410037859733a82d38a69949c91a8da0b3d4010dcdd6ce057ec98d8791d0e0308405443ac77b9eed5d2d06d91fd3dd8d52a30082a8052b9ea0811f2caea88895390de7726559ed7fe30f59160dbf22a0e30767c5b0dbde413a5af2d820770f15007c63d21973f137f637aa2156c5e2dd26e59d1cb7f208ee73b5b6537bfac4e49bb933bdf374b7fbfca43892e35db179de876759c013c16a50b482cb4ac1290f59757b9827bb111dbca61d8897ba49a06fd9f7cfadeac5cb8734a1103288ef2adea1b88812d461781d0d578d3669422f03b450d48a1e50567991f41ce79739c24b81e3864c270d92591dac740a833dae03a3bd57a9106fbe5b400711e235496134cc74da054e4d88d8c6075d7aadd732", "0", "0", .None}, + {.Is_Square, "b44757eda6fe3077d654d1f7b16935248af8d3518160040d0b736872761c5dcf3171115058f11f2c00805033234c84f1b58d06302dde08a6569a0f590df9685a5eeff5ba4c2ed8686927e464296749017048e69dd27a265c148415152313165636a799f4c3f16374105671a280cba4ccfe618478d4a90e7c156a74fe1299e9ab05369da73ab8b27bfdfe187e08aacebe5299315d574bccca8e36869389433da35930a5be059f9762d544a48b819c24c68199c78c2dca302984323b7550a50326f198f69df8a6a030ab45a109ad4199b46944363f3fd183950fe600bbae57d4c8d5836041c41c089853a2d278f68556e86158a2bcb1ec1d8c047f4a58ce05d3fc51c6ed511b6306675f9f89c03e0b4978ddaa420e26b80acaa3eb96b0d8db1375a250e76a74e7588590d5840f77b7631295d78bd7d6fedab27d418bc56871af4cd617913aebcaf758ffa4e6a00f03b29e74de7174f3f3710c4660126a6b1701522b1cab57ad49eac9f5d67e4d5807fe31d1a46bfc1aa0bbbda9c6bec5e63603d1f3d816922f8f4633b82f7bc5a946082d7ab18a8ecd63567991254bd9372f1fa3133ff5cdf47929245b4de4830123d8f964d87a25e39afa4fd69a29e8da972624becc540545260bfc74dce8295aebba3e01c17665e90c5d4d9968003b9964b6574f2d64443f685a1dda1c306448606b40fccaccf544829581c43c9f356b602861", "0", "0", .None}, + {.Is_Square, "929adea6cf59b8bdb4b09d3e4fc99255dba6020a8fded0ef1b4663a28a4b8a71df9a3e99e743d5bc2910dcc652f0cdf3bafca6b4171e4b6cc23fe5a3a533be1d62ee2254bd3c5acd3be556b74d422721a538cb55b50a6fc5c622c65c5792eff0613b67800160855382674c415b4f0fad917a15dfb160700f45afc676641025daeccbd265c14e5d949039404189b4fb568331ba3ecea1895773c20f5552cef9b9db39ab20053460a81fdffbb5aa14ed69f23701f617d97f380365c42d9b3d112f01bcb58d651365606eaad357b52dcbd237793d4f3f84986b73c35a47015270661035db6568893ec406285038d175b3492d0b758d77d394613d7e751cc294b098a8f25734c15555822fa353ab6b5d99353d59141cc6ddec8d73b232d0b562f75a9b4cd20d0306d5bc6225b7023174cf6b4c4c51f2ae3458dafb965ce43af6c2910e37cc76bc77a29c8ddbe48fee5e62b805940807c4cc9c9c68ee7b91cd2a07308aa445912d7066c6aa9c42b6b79274d92d6a89ac00c4cd9a43b3844a8498513102d44c6918450ecc188bde96ef8bac0d3b25b189947a927cf5e597ba1faf4c0c4f6d12a23039cfda93184fa9061e416f8d7b24bd16c003a46dcf17d82fde6ce6f409e8bf85398e590b8340f5bfedf43f56e319f7f99bdaa6e3b58221e3cbfaa61657b03faa4a348e402b8126a0688827fb73db96cd51808145b375fc2e7fbf19", "0", "0", .None}, + {.Is_Square, "9f50244bf43dcfa4f8eeb497f0ff225f6e0f73c079094e4ba02f5cb68522004e939b72c3919334f96ebe1ec3abcc412d7f08b0e49f1f76db16a5f5e184c7173ba05fe8bd5119ec228fc5cb3294d4dcc4da83a028855d8476ec87e89c45136834e19aa4368b182c80757d0018e6d3f006e71d03bc9464bcc72b74e1ed7ad88a7c4ec7e0ceee7db9f14b7574b7d984c0cc49c1126b206cf3770e3d22ef6aca8b9d0971bda5c11752f1616e96b22850553e3a1f232ac8fdf8d21777e6bb1418651de5d44a559914ba1aff4b0033ca19554089c0cf7afe492dc4cdf5787441940d5bb7d3079cc0be0a90af8040903387c1a1a24a70e4e49bda301d5ee8192a4b98b4f96a7e623b9686459044f83631aaacf01084f4940da5a76e1ece462057fb36b03bb1b47e029c3069b93448ec709192663d0271d41cf69324605545c9a46c47aadf2117d5babc974efb93200c2377ba55316aef569369dd7bbed994356c2753b9c92102e1e2a79b8e72d86584e383fb32dfb8be3c4ba270330d060c2d2dde54fa0d42d5fad9842e903638beca6aaafbb008d07270d343870f44e4321fed1602b0de20fe4ee0f1027595b3309486e57eb27c770f78825291871faa2884df9a7b3d5e1de4f95dffc3f735a3ca41ffd2dd2fb746502d4d61bf6d31dc06e92dad63351cd4439d04532f2e9dbe548b7d88227495c0873382867b92fa8b552eb550700f", "0", "0", .None}, + {.Is_Square, "9b035c77f7ddd69575979830ca3529d12305398b55a80d46220e2374d22755fab98b880963561e5d885f402614f2d3792f9bf5dd5a9cb98acdbc98548ace5f3c57d48adc1734cff79b40dbd8045717ba3a9a98618a1912f27f3bd4b413aa4d718ef2ff34080e56dc16ab440a4c2c21e7d41c201a0d1020f9cd9d6cc672807aacb16910ec178ceae392ac1ee23b58fcfd15a81ef606231d628124811c3cef892ebb420681fb601d0a46aaf8e2bd462a447c801534b70f30a806ebf53b783db605aad92f3d427331b7101b3771228370dc5eb9baefb0d04e577bd56c15a47e16b980020bd963a6cc24359da0cf9dfd176452f2bb4c4c709b7f2d92e43953b12426c52282c9e2d346d08b5c02a46e3891f8746ce83f029ae63da0a2ea75de62b2747d83ef967f97b9ff4c4c460badef1be06c37457eb2d898f90a6b4aaf562e1afa5898ab3928c43cd177b2d4a86493f03d7115b73a853deb675e38d8091cb1b28af5fc96241dd8a111fed9c4ac5fd9464882687091b40f6d39ce69b1c88d40e27cc8f284256f08338c68ddd053d68afc4433d24e0d6c6dfa66f343f0bf2cc065fb7644a96798792783fe1b40a0475ca7fb329bfeaa30807ae75463adb55a46db940907c643af95ee9843418de3b9b6beecb798891077626e8e67ef8850c1c7c96c474deb53d0440e34e7198ce73e78059a91d55823c105f0d9db2560ee37ef5706", "0", "0", .None}, + {.Is_Square, "24adff5a22d0f4bf51e415bbc8540aee67e992744731486f2817077e59db1ce2ffe112e3b4210be89c0760cbee85852825a905370c1425f5b1d8e7ea796bd7ed6df83c68914f52b6c657207ddb720de916984d6d97554b6a635d31a54f184d11d1078df80a11064e0f5a4517a89774bfdfd65f22a46380cd9e89a6325786cb64e176faadab8fe47534e2d560c192caec05141ed13c38acf4f9d806ef3b286f66cd41767a442068d9ede9489739f9a11943a6eab827bf40651278f9f691a29e8188d798d975b1b8b4be3d7753682dd1d51e8cc0e32e4fca0d558a8a4019c63eb63205af828fb71db9c79667a4fa312ffe3bd85bb759f4c05212f145187ac7c419dfb6f527486e4a1f85c80e5e5ef78ed007749a39fd2ecd80c2986642301dd7cfb1404c9347fd09bcca33e7bd350b8af7d1022a091b01b8ead08054fae3c8972066ad7d7a3c0e10f3992f7dd6006a1fe3342d261ca5a6c29333c43f171bbd98cf52dee0bf651e772ab56b6cd62e5e2f4758e63ff28842b137cb3c750e5e4a222774279db74e9cf468ba61de59ef2a832b9478fc95ae03cc835fc0fb67814308d4a2371b43c9286095781b5634c5f6a4cdea41c341e95900fb3cb7f05988eab45c811b5bf4a369eb63ef934f632354b9f0c9ecff0423a669f49df3bd011e9c021b4f9c3cb4764b340ce9e5c9be8c9f06f626480176bfc0202fc9d2b57b9c62eb80", "0", "0", .None}, + {.Is_Square, "bd89c621d754a6bd3247a07944a58e116e5ea8e2cafdac2063dd0a69069dd69597a610532aa7ee4190c8ef70d5ec15fc83b84bd2017784f15b3099364e312ac1a2c469404112697d3989c0048453a7313dbf6349072312ac67d03653a88759a82e5d27e003226a2c37c64e08c76752245a1906750e500a1da29d67942601587f9783e83581ab45c8496de9cdd9941f6143e2294541053fe1297d12fc7c972e3eb0a438a02984bbb82712c9dbee4a7577747e96a58e625afc139a6b2287266e4c0dc500134ca930454fc3ed8058f302a1ead3f61c61a564a83f2a691142bfbe728f06b1594f2ea0fe67f430ccde006494e7d97e6831d457893787bf51c85e8b485bfa9267ea2b370be9e720aca7787877a2785188375c1be34b17b524cedeb876f81bd9ec1c842cfa775c194674f08dfe51cbde5b7812b727186f0c5099c5670122f1e032b17f0d936326d4640ae887583e946e29ba0810480e654dd98220fae1349b6d3b0514bc7fb64aaec7d48a809ab8aed7a2744b009bd8d4ca0a9756716c090298c07e40dc0aef62c4ec49499293e67cf03a3623e0d9511a28104e99bbe18bd0d49454291aa2f5403b1ebd0d906beac12eacda5cc2685ce02fef539d531bc5abd37c928fa84cd5e7a280dc498a6a12a7f16e6044ff2c40a167dae1881db97e0bf085d933f7d6f0aa6be2a4791634adac48bc0918428983dac3ba74713641", "0", "0", .None}, + {.Is_Square, "d90bd406137b9ea4006e0e59026530bd402e0b13a71736c0e10cb1a64aec1d13059e1050da8567ac7f17678cb043991e317c2908dfbec7792fd59e8dbb2474848c2c3572a7b0ebc623866d2e156baf1a3aa63438c7cfd3e524e1f1baecac12fff44c8a8184fe38942f2131010008f4d4a62c1ec445387178cf083f5761fcdbc35d375ebed1e4e0fa832d06a23321927d594807b43fd469d8bc00edabc675beb0222630ad94f93afcd94a36d2c3cf6b1548930b1b11f433dd9bdb2fdc6b1f098a1b8770d162847c52054dae94f7c8aef9458d114b60a7ff6ca1980b461e1aa711b3f6b3c935df8619ed0d72c010cd77211238b729568619a70d5216c15ff8611e9ce8c31dc85c9e11419746afa68a82af25f02c87076d060549119604720e2db6c1ea477940c0d5e89fa2831be63f8d50c0e47d06415e3a6804c79ab9d73dd7037649bacf84af1923d717182f6832598ba14f024cdc2cf7caccc0859ea4fc508536d6a8f97d1749378e27aeda4a7bf6925184bfbbf63973404714f675126d815189c7dd54839515586ad2d66dd630947883b25e65b6942d0b42fbd325ae7d6455793140eebf3eaf2a241807c7995378db863108b3138b50a1a68d8e56d64bfe5a1603ad5cd101936ee3e26edc6c1a58b1b8fdb2519dec01beda2986b7d0a6e258249c142a7139d9ec17476d865efabef9f9f779c2772a41fc72434034fb99deed", "0", "0", .None}, + {.Is_Square, "5fce2cc0c083bd4da269e10720f9241c770b74d3500e270a190f684b131efdf359f979b022cea6383c6259e35f634b778df2446afbf5fe85154c024e9769d9288cd249b1c3456bd2a9886ad219f394a4440d16ab6c73f101c4eb8cd0403b937c9aec169e3c8d06fb5df8fa14795696dd5eabb400200a7ec5938563e21c50e941500a4833d8be2de6a8c45902a90a84a3e87a2d42dfc8f52b640ee0b312423ad33f6f8d30202d77dd28f01b7681013cbe995562378718b6924745dfd9d57391518ddd3fef4bf06ec1f7586781541aab16fe02738c5f2ada257fcd1659c724876e4af8d76defc051ae32977e79008919efa61a660df8234c6ba0b69ecdc7d47560f50692395a5e2d7a5c92494aacb56b809f4d66bb59c02958b9c6c373020f3f9e4defe36a3945834e71d78a22ffdf6d97998af4144e261a2fedaf9c16d832c2a3a62629b966274f0279dd3e8077b351829c307b11a030a813b1ee6835333c5099ffbf1d2606b70a88f1622ebdb54907c9d4bedd2b40e587cf1d946ba8287fa60caead4f612d60a23185d7af59b1d06671a8ea0771164b4fe8fc045c264bc404bc52944cb568585c32a4326d65dc411d1cb778fc905068e1f1569367199e6a25cf866cb1ec303d358f01d9f0b38a56cffc7c568701b14dcf70a6cd629da0aded8fef4acda68421e269125ff50a5f652e2337e7a6f4eaed6af886a78c8bd94362de", "0", "0", .None}, + {.Is_Square, "42766c6e3aa7eb1b16ddd2fec7d87eddf09c61d1fc7a2e72e6aeeafdc8e3aab867b88c71c885b3c2fa826607fc30d88063044593d030c8d284ae3691d49b15ea1044e0dc4229c4c7ebff559145f466ae69399b92790eb193ea3665b94c0e3aab464736cebbf92a625e4eac67291c1236f2ef0f8b4ba894cb3084a47de90eb1ae67ecd1c2712b5ac66170bc18361cc52f49501a2b1127444d37ad359b556a3fe7f84848f2beb10fada756a5f4adc84090ca48bb0c3e7eb297921e0b3015441aea8c658569a4ea706f369c83838940ffff6809df955a5862d8e1552773091eaa1847d43397af35a95f2485c3e01f760e7b4a8582c17e327aa6c87360c2564502860a83cc95796699e17fc1dba9622332c9b8314ca6c4672d99c59ed16527a413b3f5b91dc0a49f5ef9d1276fdb4cba0e0b1f64b2f93db3b12ff1015dd8e7d2d851b55ee14b143acf99b0093fe76df79b7654f22be0db1c49e38c55fdf7472edfd6eb1c65ee0ece6c7467b759d5c7baa0fe35d77868751bec1ad3d75b9cbb09ded9b2eab185c99790f270e5790bf44528f13b9d9320346831479ee1e019c558ccef4cc5b785e695d93e1a26dd30efe86056987a877999853c1cec5e443e4af8f4c4bb311d6bc376ed77a985cc679d176e0ad45bdecf70d4db72fb0269c16d1822c3b1a735c2f622702e0a03abe32409a338df312ce286caab1453802a6c02ec2a76", "0", "0", .None}, + {.Is_Square, "77984bbb6355cf485230636bb3b27f424c3d4b2fd6ccb5091bb41c5fb0e2b0c79d6b9c5172dd3e78edfcd0eb84582d8dae38bda0b5874cfcd1ba558dbb81b6697b0c8959b3aafea46ee2fc6ef261a50359817d94a33f15877872bef542d5b117e4a6a2e5a70543e7f6bed5d1b52c155f4b8fc1235540d9a245818905dc586112d7aaba89f651438a3c2b1ea25f436574b8f0e4a331ef3375930ac7ee3582559850a29413ad9eff040672578cfb18f6209f04d0ef9ec85121e01e6f3ffe68e2f45be7f23906e86af0a89ff16c67420f1d729b3475362888431a2616b8d0f8a9cca451529cd9772eebbea03750a35a29d54f94e845e12ae829a47329f92f6dff6a2326c75d44171c58f7f1be93ff38b6da2a1c54c38d965fada7f88ff18fee2755b74c02467937060ab2cddc920e88f97ff303dee291e2149f2ea8654fbd3cb507f51ebda8fa28e6ddb55d199f2ab4a1ed65b1e7897611e753e1ac0b2e4a431570820e05b83b4cd9e7bb62702130f57540f1df1748185643a605c00ca67864dfc99691190ee39136c881f81908e816f394e317320b86d17ed278896bb7351cd9e8e4f1a5833e07df4b594c928ad10b51f6a2d812a1c4e9af31be0ee654c597e6125bc4fec1a227af757ac6ed77e47c0c10af8f3a6b9d034c2dc0bf9e94de2aff24f5283d023516e07aa2d23ed5a5687db445a052cd60fc9d76162a84105bccbabd", "0", "0", .None}, + {.Div, "-5f405f1e935ca582a578c30979b370dff6e192ce309e207dc08fa63dac190c60fafef5bf85817e217d147eaa16f3b7d2405a2c506bccb3bb19abff7f18e2354f6cab275975c78dc6bbc2b6acd26041ca2915b4b541a9415db91accb7c4e157177a6b531fa7a6271bea7eea416420d8be257f74eeb94f7b14492afc99f709e5927bf02119c92accc62e2586a6f568a4adcf050c66294480a2a9be31bfe39f23fc50442dfacea1a0992b74b577e45ca896286f311b501ed010df0336a9e342d7561c22eda692255255d9441e0a8c038d3064a5e41107cd2f6d4651e7cae9fc350cc4fbeb1b8912bbe2e68719dff3c5898fb5f589be1d9e92212baaa31caf58d203f9e8bad88f1228a1e96b5f3f8d1640daf70339bad86de63b81ce61ed44ef038a9e59a5b675f32f21c7be2cf82f177934a0a5a437826c75538e616e0f3816e52f070ba4cf4f472de2246332b27c6c55850a7db2706130a2dbd4fb1ea99f2b8062956054312696805234b310eb594d6c94297de1c2333bb246abfb6083dc64d10c0d6f4ebd24fec69d4697433e7c98524fe4539eccfbf1ee7ccd40f5889472cc6e2b3946df31053dbf9706f84b547fba9a85fcde387473c21af395497647e447a50636243bc4c926c8fee130a6c29876d325675547714d372c6af71db019da036258472fc1e76d778f193d6647544f107a8b082a9332b93b22ca7e6d6c8637ec71", "-51d23e7e9405dfbb3102273dce98cf26fa09e94fba8dcf8bf3c52934341435fad1f7bcabc1c8f68c2529848cacd4b56a83b473563805ae579e07e8f3f4067bda5b36c3d8170867de097e24bc5cc76c245519ec8586f92eda440c537b51a93b0cbc81afce292de50c4e22c3f8500f0cfc8fcaf380db166c370482feb5b115aabd9179b28a7ed6cb5dd106e9ab7afc3f2ff25289c3aefe75727d908c9f2827e5125416c9828d23151ff5708f10dd20fe3727f785806a72736d5ea3ba9339d375cb21ba00eb17529b1085203c4093deeb4ce65326cc5795cfb12bdda8699e69fad13387ded9362adef0021863abe6cc4c3f4eebbe6ab65b117e72984427fccfe1698aee871d71daecd4cbd4ff37cac47127c54bab9db135632566fdc808e1573dcdbd2195dfbc1e498cd474a70e89aadf367282ec", "12a051cfd79ea76c3ce1a9e2ad3c21ea1a463e5837b2e4d73479608f6d087d89fd6ddd1d3148173d061343c105838922f85b01db5555b826bb013b13a847dfa41a9a499075ab54a092737b3101708fe890c1f5c795a811ffbf041ea72c47e83d6a0aa7d93b95bb284e82ad3657eace6d20ff93bd4dbcd8c0282b6b74adfb4c17862c3b39cac82918cb9076f7e0508a3931af6f64324f320f2afb7e50da88cc08b7c60dba6d017fd01e5df05e7f2a89320b4704dc637aa8b93832d762a2e9e9bb9ec8835035e6194ac3cd1500eef", .None}, + {.Div, "-35ce4b916d9fb7f05b0c25194796fc41df4ddc795dbb56dafd6104bbc0fa6a3735a4e4fea7f8395ed736e2790db30e19b3249df24853d7b34968bcd56d4257a578bd78aa33f66a5db4d2bf79567907e2b860c504a24cb727bedcab36020dc42b1b9878e2ce053bd9f2b9aef193552852722d98d21951cee79c325ee648f903f764148dcd69b2d6b3b11bc59fd96402eaeb3c8e688834845ecc4b5e609df93fe9adcbe03a20b4709ae1ad5154a8a187950795924059c83f44ba95031e36e80b90b5f7081ba46b6c56a663b832ca7fa3d9dc570fce34913ed4f4ccb0a32aa423a1deec45ebf069b26f35d5dbf8b8443a39d4f56f6c8b44167e686115fdb05332236feb48927bc84f746d5ef5b5798916fb09ad3b81289a7c6eae878405eb54a0ebd0932b4438d68ac79ce19db556d3ff3da836df9b804418318143911908cea1ea48cab6b04df50f8e99e6ea55278ba6b1e4c1b99876ac76b4c108f3cee398c8bc372481a8e272e731058bda729d76df46b75264b12fdd4dff10c013dabf12ef3b30b4db44976c32110beeba858484151042470af3468ad6f30593efe2b1b3d7870b98950f9cb6ab906bb1e20938c0e4c9c6c17542fa03c894a581d7bae22d29d228e677d1610ce978a904c4725c0b50bfa015c8c5fcd12530c970c7ad192276b726d79e9dc93eb2b431a08210ca1b778b42c2397c81343cf96f6933bc04de9424", "149c7e499859270e0514a9e5857219c277e7e6f1f15313507d1a65adb259ed5541f199a859f3d9fe800c6fa60391c918e62377763bbccd67aadca1a48f23ec148e1663694e4ea0f0d5ac0069ca60b5b2c6e41975755b3970951624e9317c6e263980f531bdf0bdfbf658c7b7997e3bc942689bc8cd15cbd9cb28444cfea02163032ee0a5f4c9c8ba575dcdc9f5b4e462dd4a00f2fe38c9f808c29c6cd76d5d6f2f618004790f008587ceb908b7ae26d514f4b95db8f16f7c49196d35e4c48600acbcf534bb8fa78609194b5eb37f3a519e9b808add98f7ff632f345d5784faf76517b1045f221b40f41944c8e32c6bcc8de8da1f21d16c6f5961e8d647f26c3888d057d6fc367900027199ad972d68e04b4bf1111ae3d1dca3e9d2adc6924644c84161a9a6a84e6572765671924c3f68258c892", "-29c49d8424d0b6818d1d35d793e4de240b037345b96e8264ccc6f78537af2bd299e31411563a1b6013544060b8e83a88a3be68d17925c9d8f177208c4d2933d39182e874f81e64a6094fc4b1ed12c54b3f263b894459c9525a49caf7ac313a61ddc521d59da4334bf366681e5ac80e7532db590fecfe6fb1c6d9637241fa215d69e82b37992d9062abbe4ae8007cb76b49517bb97096ad3d70935a65a9d21d2f61b04b066a89a2672b195767c77b903d4b29c4f82697184e5af185e6fe63686e43e12cff4172a27f089a200264", .None}, + {.Div, "-5837e08343b1f00ec9df355a8b6b5ffc6e9cccc51f8c5829fd2799c41dddb4031db983b3bb5fba257bef9e4ea484a22a1b94517e0311815b4ff275e61e963cc9b657d11652e0cff1b0c8b567561a3805f7ee0e59f97d58ed128779028a1fc7323b071ec052073a4a057132b49f65bf23521a6a228540349b0604452c8801ab67fd1005074900c7cda9df7f3b586eb8958a204b76846c0d2584a40c37a13c060b88e6f9db2fc186e2243f8a4d559e079acd716e493735c6c791c557410280991f45bcde5b5a0d1a0a31df045b176140ebfb40081b518484e1b04ae4d74745130e17b7256258d2741f1927f346690864ba15833912ab557c1c943ce54d74e3c15b8f21734238410816f7177a3df2be5039a40afa664bf23599a6f51f89526117a278faa233b198da4e1b30557c829a2b7432ddfc001b0c21f3ac34b5a34bf5f91b9345cb88f6ee0b9ac33d80cc70ee46e48065b706782fb679dd29e8c2bd33d375cdb9eabd979e8e44b9c85217c88eb226c130117fec278ea6c68d04cff070d7f9abc7facc3549fa04a4747f34753458d6c34bef5aa920eccb7fc197bef10d056131327cb002473708f3b5a7afd468bd66ad1444f449c254d86e9cef71c88fc1d38472db2ae321570b5ea6d9d7dd08da40abaddd0166d23fb32ed71985a6ff064f2e0e79c526d49e2aa12e32b6fb5afbbdbbdd969933fe8e6ced9ed098fe61b810", "1c46738ad921910efc095ac206dd2e821961d0cf1ecab885ebea603835ab326456f06af9f7d5cca4c36dbc8fca11a1f1ad83a9bb916e16ebcd5b96dcc0c6398f0e4034b37c71672971993da199f99f000df1c32046c4e068901ab5849469b4691fbdabe0a917470925f9cea9ae0569804c4d0607c7ae65d8a3b417b7681e812680891794136ffdfff734034575d2b895593076c06b5fda26c886002bbb578951853a3a75f6e62272ab665a77c6ee800ec220c4dc77e0a698630fdaadc15cb241c26da0e31e5aba80a3810c4516d43dfcd3b7238e210175cf2e4c7a28302337e2016a57dc63633c451aee813bcf91efa52eccd7e2ea8cc28e749e090a6e8b4b4d406bbae69d7896e25d2c2a4e27463eb4135b643d1fc266b8a7b2caadc2b08efab7d10aaa37308d7672de7c41ad51445d84a43ce", "-31eb77e9b8882103b5edcfd6365691b2c3662e3dc9900b6d021a9d7ae7de1046e776544b90383ad8f669553f7127335ba7e6af35c002b8779c6d1839ec2280307727e4bfc2af01ff9bf16aa5342a07aa54c6c8c48e605784d2cb809b4d84d315ab365eb9e2056cc418b7028ca1ae70aeb429f3b129c760709e0e03ee7360c99b0214f4c04a520a57d937334323304ed0dd3eec2fb4c1062b730d2705f309a8b39e32e0e7147aa270e986372da066f3b67adaf17724bdad4eab2e974e8a31d57f4ea3cef0ee11b2f4a5418f3b70", .None}, + {.Div, "-14e6f53dc52873bf5c7515b4677d721ba9f91fe0e3afd5e38bbd93a96f8d63393a98dc2b13f679bed006cba7360d06460e78781b062c92818fab994e11fe9b3d7744d8e2b2f5cc86b5ee07e68d45f75bd1789371dadf2183ef9b0186915cc5cdc348d5383e18cab62d2f600838e0270c9727b01d4ee12f42254546e40176e613d5a11ea980619384afcdf67b167e73e1390f0fda4ca958e184b0c8fbe5115ba3568f09fa2761dda5d665eb85018093f3776f8804c9c9a45ee62279a45c327cb1f5d0d3693ba707c3f8a5fd8b725514b3df48e02f5936fb098957e1726c1f6ed64746f2864fd83ff6f2871e40e035f3af1cf2630f90a4152b9190870bf28e92d15205422c53526fee75ebbbda7bb7dda3b7e75690857cabefbeb0aea3192aa145c16aeeda664f9a8e3973c53651f3b7e67a73a6db0e0e39eaa895e9a750ca162d8b510ce0c1f0401f220c4f0647432048814fe8741a6bbca65bda1dc434a3882c26d0301ba37ea6b84e163dc09bc87bc28acd4eb05021e5a766c7e26661b62c91823d9abbe8d3a3ae8bdbc989ddc17f919f8357e78f67b9c82521178eb988bcf338715e616f14adc94cbcc4624a864108b1b212318569d2b2ddc72dbc9733fa9704e6483240b8cfbac8189b1443b17ca66266b4b199161c0374f774b1de9c0d6b74ef6364c7aa8248e0b1e10bf2e9baa66863de495ff0abac6eaa8ee4c6a652e5", "10eff5c12f0e938894088abf0ec62aa750542139abbc9db960acf14a0aeb7d2e04aeeaf7d5f1204aae711c712f8107166e06cf1192c6c02978f84d16569d4c7cac6ad0960e3a4169aa9ec0ed67ac36223d33fef57eb40cf7c0a809b78f9dc9d8bf7b21eef9d431b986899aa4a7ce74fd2555e2d95b57607ae508ae59fca591c2a56178d381ac397c869aa26d535c95311d904154556ad4af2bee77eb85ca5bd83a542a02a29add51cb71b6e66f29461e8001108512008655425f209aa453fa6f5e885bc8c41f2851b3a0ab041a08613d9413349afb4503e4b8c9c910c70bf8268cd58ea2c9e8f36f6204158c258ce9a22508ca49cf230bf6ce8294568e47046d42ccc4480a322e11abe2b825fea6454e01763832bdeac6610c66e92073b407c9270d0cb090d769962dbec02bb07efb6e46808a2", "-13bed37e2a2ce3431e60ed5eb5cfbb586e1bf0af8e13329d0fe930a07fba23a0af94b4c304121f9fa83356606d6917fca7250ff7c33d37c4df30081b2ee291e6bd7f6a4bddf5a66327a0e05204d70818b372f9eb21895adeaa5d61a2cd965d58f9bb839e5127dedc5bbee325b79c775b31fd2382a1982136117b17e219fea0c3bd894d45ac7c77167d8adaff70bd0faf404bd0f2f8ab06a6a947eb0cc4b66d75450c4664c7eebebe01a5bd903b815c6b5412a9a53bc2e1315a864fae3a2f2d6a8ee600035cfaab932ee8e88a91", .None}, + {.Div, "-8165b06cf3eec2117660e81fc4c88c6d41a5dd955bbbbe209dce96628585f9b3a035329db9229c3ffc3d548e1f8bd4cd786862a27e99bfaf0757076a0855e3af025858c8319839b49443118034420940fdedeae244b2f1afca1c006c18124d2c5999f6b4b5e8fe5e4e443234d3b1a007c7c37506ba33bd30faaa35fdd8a7f074dc424f63343beab49db487e273f048e3f04801bb6a124c24fa2a1fe19546539fffa51604507af7e4584b4e1cdb5a984998c7f539e862bb4a692854fa8d741b62adaa9a05b7d86bb037274b27797019c106760174373c3788ae490c0955a28ebdc0a611476e406aad072c3501081543c4f0534fa83469c2b1dd31fa14a81cffab0afe3d82226e9cbdf4832c00245eee64767946fd47539920ade433145860f1168785fc03f13214c3b9b295361dfce10833f5d04070e0743092df3c1a497445940dc42a8045904ca88a4a82a13e65e64251493175600219523194395584df4280d70e15a1a686220c7a4108082e02a109d1afae68f3d0b44bcf6578040dd35197990adfce17ac7b0a106dc0784cc457f427e2016d531a90c36444b6d5dac6abadc5c4e7c38c86e41a9b05569942b820ac2cacfef95711620601308b25132b3e0e00f85d4488236d1c2eb64b412343ba2d8f8b29890adcab28c881a9c7cbcfec4bb2aee8cde2828aa812ef1bfa3d45eb5eb5096091a8bcdd5a74b43df66b83696e", "1b12c81516e2be2577b4129a58a0beb3e30d6f7c4076f8fdaf267efe3426ee6fbebb2a83db0a32386a90555f893a31dcf45dc4a06af2627a9dcde03cc593e842ef1b66dac4049c1c5101b08f367aca0c77aa27e3fcde13d05d22146c438408ad1ec93fa680a805baff7860a575f41be38720a45edb9f12e902a5e9eb547dd06758649bb01a8c43bbd230bc3b303536c3793a7145582216bcbcd8ed0f01bf9e13d27f714a24124eb8b0b27d9f9fba9a4621fcdd1deca0cf3482a1a49fbeac68e3e2a132c5c6d51abc5013ce04981f8c2634487a7a71607b92c825399359339dd27597ae4da6c1d383b0d367ccadd5c05d019886bee1ccd9100c9d964f3b188e8be3085072f73a31c7119dc041abcd5f696c6c2a2e546f7779e0c91f0b7bcd08780ad7c9eaaba1b6848b43a08618bccf3ae93d64c", "-4c78d7cfe62aa3602d6862a4ca5c93a541eccce1f08d57c61b051c2f9fb3ac6f56174da871d8e630f21d4b35cf155b36571f05e4168c77d0949f4d708d68d2cb5cc0cd280a777635b620ccc8c3a4559614212dcf5f3b56729ddfd94da48addf0208c955ebb51ad262eeb3283db997dc96fb8fe9fc6d6be92e9f89b48946248097bda5a29cd5685d0cb69132d9571b3e652738158f7562bf934c17101c2ae476bc4ca4e1f838b0027f6a52cbab8adf9c2df861330136f69b9e360ea0984ae516dce3292b346287c3af35c1cc14a", .None}, + {.Div, "ed3c12b5956d249ce55d022b7a357c193cac054ba243118b42260878076d44b5481f0ca2f3deb7b636f9790933f5d336d2307d399addf9c701e5dc80db661ca1b7dc59be211fda94de7618e6edceba56c93954db40eac548931b5093c5812011c7ceedd190648ad6d2ae9e829f16adf7fc39c289e877b898b77141f179d8bb93fb9238bfafc2eaaf7e975400fa96c3b882e384325459791053daadd5ebc98fc7750feccac59d7e59261545265a92c4af2dac1632071277e466cc72351ef264208904b85255aa1eb76366f688b5fea91ed8db5f94ea8cde4347c978693017f73cdae9f89c16824dd290ed1d9a35166b936ee6fb28828b65f15f7b9b8cfedf87306776f8b115552b489145a62e6029eb31cc43608bf3072a046fa9d7f4f13ab377a175eba427e7a0e41561a29ed022e014136495ffd026e1b5b377de126dca76a32d7b0e43177f765609beda6d28d726c38d3f8280dff0277bae96d02b709d13c2da497a1e06f34c521667f70e162d9fd0cd63f5ee67a24b62718da4c1764753ab9fffd65942140e13e82aadeceba236459aead97459f4c01dfcee4deed4408e2c8e765b73b6c53fd5b1bc62d0bc7ab03c508a7c9f03dc88686fe262cf438652b03068af52601f8ebd0788e60402b2aa89ce90d10000ff3f7ba012b3e0495130ca09e0c6c80cafdd775016dd4fee712963363a890ddf16b237a9ae9d609d28a06f", "-13cde3f0eefb8596db290115fe8015d4c2fc9d934a88a2a1f2fdf687f31c5f7d53557057d38a8570fa66b477b322b67f916f71cd59bda4b03925ab30284694d1b5a4c06f78e7c9debf4b87c03f0e4a412d92a8a8ae298f1aa43e504b7537e5fa106a4392b915509f62c6a82a544a89f7be87cc710564952f448b44c83b1ac3a2807b064e53102e86d3995ee8ea169b7d7eb18d9ac296f84f60f6c24fc2b101d0bbf3f038b9f2d0312ef90590c4eb731657016de156e7d385b873cb178de22b3a94091205388a242dc4abf96166ca7ba4574df6d7881cfb3f19ecb21d21ac35677d5bd9c2d986937969532c4c7f72f7914c1d2bf432de8163b3ae6622a8bb64132ff0e24b09b0252c3b3bb9600b15893ce3c5ae5e04f076c2e0c426295b9745f99c7eeb65f0258cc41b734ba8ef9d17448b7c09", "-bfa9de2130c808d4abe6405c94edee475507430e3baf4286ad875e88e499933ed03f016853004a66db8d177fb3b32f377544ed51191e7bbc2a6fd4d754d217fbebeda4c7db936ded658e05e7e9bafc49175d3dadb5a6492e3267991f92a05f99bb7c4954fddc07b96fe9c68d9674c57b780031401b57bc76aba0446f887285614b9f3b0bbcd60eb51c5b02cc103da8cbd91cafc49f5eb6016d29e4a218e3bdb66c5d84f7dcd92937ea49a68fd977e4929c37f96db21469db4d8b8ef4de6b27d80b6715d2380333eb2e2fccc2df8", .None}, + {.Div, "-f7f4e8ca2154e47c9935cb121333946374a50b5ec72b532c0f53415a573cc62bab614af9dd8a0f92fa07bbfd10df04d0a7b3f779455456764e25b8cca8f2aade46e2bf3f0968e191ea9baf42214a81c01eabeaa925aa6684585d5d212664afa34f383e86e6a190f7289765ad3fdadeae393618c03a030e3499e48b81a661521a38d20067bda39f2ba190bdf3ece203973d1b06747508b9b3b5ccedb160350c04271b6a87a56ddccc9607c75c3ac300c0f501fcff1de04fcaf6a9dadb096cad9c852b00d360e033cfcff9fd3e34059d2a4f9599d80d8c2c8484c684ee6b76ce275515980d08f7b3ae2993886369d20d19b9fabfc48bda8582236e6bdd53849a43943bd9907ae1f37e67c384d53ae7fb80b4362364d53c6359beb1e28b2b0f2f1af70a647b1b811f8d3c721ea826b65aa83a152fc05bd8bd313d413ca6b8a9f8e743aa10d9d840ddeb46538be5192932f7bc355e66ed2e0b175411ef6729beab1dd5420ba22a24e06e80d168c42d7569a42f8628ddf21c99bc97632710aac0dbae2bf47ceb992641cbf83ab7507e2b0a649c328cd56aa9f4d346d508d469042f22e79643717494fbe0ef52287f0f6f04e5d44660f378b98c632d93960a0b355edb0bef7ef63eef524e9263f7ea61af3cb3cec27627ec57f01b7af144b174aee4afb1be25af87a48ec565755618ed324e3b8011c4218cad8a6aaa386d5fb04471df", "-15d5226909a6e475e8b0f14f4a3dc12f56791fb56db1ab95324b49de95a96048d4fae52cee11f642e33cfb3634dc59740e2968b5dce20cca3ca3aed5c42d93048334c7e9c2d00d1c27cb5890aef9ceb63d2a4c70aca30d56bb70bcef2e1d7cd1e84692f0525325776205734ed45816d4bbee9f82a4636d0e9d6ba31c3f7cc1dcf6cc7a49a321995e3ec58770d7fd7421befdccbc1f60c628345f5c007c4cbeb89523eab772b79c14fe893a3a07e261dc6aa0703c08b0495f6e0c08a9361d87355ed30d199de3db24ec66c245ae1e6dd804d5866970e2a48d593a8624ba17aa77e878f2fd456d82ebdaa8b0d37393c93133cc4dde93b440cf3a6d60e7e16cac5be7265d903fb6f8f8bfe91c50a4935c0510ba07abaead982da2abbd739a6e8eb0c78028923816ce00d76711e72fe68024bb8e827", "b5b715d66baf37f7cee64f5a59e96912e63c13b7f92addb9fbb3977829d41fbfb7cb1d57c4241b840da8f168216fcc1bb89b2f737085bc070c3ed2ea07c179ac425d8ccb91b4ffdb568b0b097f7dfc63d4973a3d5bcbf109480d6bb1c3feb232acfb09aad4f0be38274f3b9ea8537d60547df08ba0a0101b33aba2a36920fa141dace44694472545175e016798cb2c456e8f02ec0f85dd165ce04b45267245c03efad3e635dfbebb64528b977ef39496419057f7954093733fb31f5a0f3adc437844691c44a9533f1650ff2dc3", .None}, + {.Div, "-2eb20b9f70e7ec975a12691844ca60d0ea7b85c0e0a7d5b48ef72dc7cf20241d49f30956235b2b1bc5d7992d19d48f2ace6aac17d4b5132861994d9b7b1a3a8d17fb653240e3339a149a87703400d24d39e01d5d5a13eaad43faaeb3e1c1e9f855ddf7d8904ee05598e1228cbb20bf5d6ba3e4acdc31ab8828d20650d473f4760e38047c56a03d0f7190344b8db7dbcc37b66da20e2894a825386ee1931363a1b815734e1913aedc8118b7e514a21d2d3e64fd381f149d36ac1d0b20ac5cb2c650cb9f7ed412537c89340cf70e58238a335916752a820086b9ad9be2ca4b2179a594e86305ef8751d3cd59edcc576c5c898a2c4a7c93f08718df762ce46ecd4e5cb3c8b720db06e1a70db8b49a6a8aa69bf2d0ef6c99cb82344fb1fc8f4dc8f7b80654f7eb2a838f3942d703510a7f1f2aa48d1fe28d4fbb5d1478aef635ddf9220d56d0794a62f687131c4a8059291101b810ba0bcc1d1ed8c2d901f6422a4f6a1de30cb2f6886a362cd13bb70e834a56f2dfcdf3f4b1da653a0e786489e9a0cb842dc8f580d2cda5ea28fe36591301333337226955b915837b7c7e49511db2d2160d1c2eee22b8b3ceac4076e44caed278a26e439e449893d076aa6e0476734dccb3468a4f3996dc0693f4d0c88d6675485ce058d9a505e3213ddbcb0f3cbe48ce6fdea155eb71f942e3dafe7189a32eec12a425885079d7fad4e7f5bd189e", "b0c228ebab99a458dbcfee31e291df7991a15227183780e89377811fb3f78ac884ae1b0fddec6b541b76730a1654af83b57f9f07ea9522e21a1b78caea9bfcc5cc5305aa91a2a13254d8a4de6bdd557416041cdb839d6cf28bd15aa96dae6d5128d487887caff21fa48969dde13d6f8ba4c3a4d2388f04e3a8b1cc4266b505dd351af159dcd236e6900ab7fa0ddf16b2b37a0cbcd6311efdb1d1e09882e99739ca6f00a28a6bfe58ffe25184e934f14e01664205f89ffb1b8abe9e98a771e3ba3a8afdc03f5fd933294ea9604f7f18b8b46d53dd64860ca0957fae904989041182c005b734acbb2c39081d7c4f27af3ace2ab80a2af7f45380779dfaa6ac5d4ffc90bfa8069d5451c1d9add17b3d5cb04ef85029ebb48f1b88932bcde19d1d2b0524912ec252f69996e8b29e4868cb50abe05b", "-43a11856a4b2f6e74488ded01841e261dc34b8d53dd0df3c3ba1ae9725f3d6637dfcc2f0a171f906b00a0d2464660a289fd50d0ed2ac916d7a0d085007b02023a5640d5d9a2ced94a387e5a322583a027ed19ac2d341f37901834b36adaf3ee07656de1e4139f981fde22f03fbbff571120728de1df61ec411f1ef51d30298fd845013bec9779d7d82c7b24479b431860f375cf618f1d1d2c080ab67c83ed3e739a0c04097eaad6b07e29d8c7179c0ab5f99562ad6e05c6d8b2864a5787841d8796c48caa8c5f537f8d651dc9c", .None}, + {.Div, "48e5580a631e2cdb66a4abb952702084ff869f62a34696322d485ea0c86209b503661efdd50a4bef18125d11391b1739f3b7869faeb74880237aff98029d7f04fcaaf22e2c9ec20f7b93cc7dcff74c6c13973ebe34cef70a40cada3609a6cb5e123f21681deb26da78de123aac41dd0676720772c74ac1d94616e018a143b6addb2b27aed994a6f0bcedc1749b1530c810c0be3ec4f089abfab41dce11f9b4f50548f2fcd30c43c3e39a971006e1a3359aad65ed657daa991e185d151b72de40640f312e3dad8acef5e0100f9d88d1d42e4040f3d1cd657e87428cd13237bb49b07aead9b8f55b6a31e2c8cba82ee4f65197ae4490f520404e319589afa87abda0817b54f2e9363e65b027532947dcde13dc3fd2c8c9d103ff21219bee6c1a7b582a245888487368df033949062320f5d24085bf76595940fec8c30a59956a88319088e3c82499c0d679aac5b97f61c4a5a8634cfc2efa5df4d621e8a25f7c115b2bc07457888c627ec5870a1b9b4f7441fdc12fd6a7745de8e5c0d9adafe642ded87548b1087d85ff487bd410165b9d8e89c72e2a53f49af5071856d5243d8953bec78c24d6d08e8bc550421c27599de735218355294d6a98bf0d591cca29dc47e4dcd4f5e389b6e0d3dc009d6f8439631b203289d44d8a39a4dc03046b3158d41e2c89357ffaa04a5f756a6d592e2f368ceaef977c8573652cc6ed9b5089ed", "-2eb33cb4c5c95610a5de342637a33b9b044c5298dad3d3f33218d0f4115d6dd56051e7e85ed799bd7725009e63872e666c234c36b624cb46eae50a4b67c58e729defdacbd928881eb99c81de4f5f6dcf399a6a4bd922eec17f8c96ab7e60efca128bbbc2743dbdd2b2aa79f5942687a40c4b6938b0bf4901942e9e1388a6709e8c3a2eedcca9356cf05078167bcb7c645a86bf5596cd83c031c8c89e16123a24329c926bfc96da86ac82f8271f93e8b10dc5fb7548f875875e6599e116332a2abbeb83b7056cbe67f837dc02be9296f0639b4bb0a805b2a6f7c6b694ff73708c55449adfa01266b38e14883e6d1d720d51576dd44fae5d80aa59d87cd5e91dde89e31f57633eb8572a5a5d0ec74080fad600ff646e22db88a99b5087e994ce9b8ef94dba25f01daa6c336a59964755cbd6ccce", "-18f9969cf6d86f38700833320ef0fa126133e892e78281c22bbcbe60432a9b3534dbd77bf82437887d819844d8b04cc58a21fe6bae52223edf471c884dfbda0739dbcd581b3e68d0d7862f45263cb64a79eaf4c8ea6fc458fdf931f45cf4878429fbf8d4a623bafd602c84e242058be923b839f81113a702d859e2fead8b576599d7c64c3825e913737ba5da352ef9ca8443bd63b5b25a675fc4909c1ff5130b66e7132fe02b83dbfb58eb5b15d53e49a56a2c840cb3d93aaf8a6b7363a48239dae9e0b696c6a926608945a811f", .None}, + {.Div, "861af0873cf289eb1de0ca8c4c38acb9d7612ab67b36431572ad7019a9c9061e336a5420722309b7ec266f34d20639fb3cbf4cfd5fe9e744a46954b2c26d320f876091b41d5c3d45fa40d9ca34d9f596bf679232972e9947bf855322cf82ff51923dd52e0ebe389f29279eeeb91a7aa6cfa4718d6d3dbb294fdf85c354d2aa3a0546b8fb0b6de0b6856be272ef64aaae146178765a0097fd3d725daed9dfb6df8ff2111ca27c5aaa583ff51cd05c20b84cef3a1a8fc3d74b293509b8132eeb43b2a0c8e24ad16cce7d9af521c66be16063851337a0186ca5d9a5a582f8f9cdc93c803d5345369fa84a495b9115a80a011e99386081738eec4743c208d807f702c07a5a6d93d536e6484b703def4b6f4a9f5a7448988aaf4ff7e6b6a4d29a4605ca4308b3f53954e1b100a5a0c6cf6f218e103b617068b81fbfb6aa11f58d75c80a0129cda03f65e8dd7353d51873c9e73a7017b37e72cd2c886d5729d85b0911688683ff4ed1e4abfeeca59452b664838e6efeabfe0da1265f74c330e87e9070418eb44ca555ee748e78b5b58e2f4a746c39b06c3f577ca695575e74aab96e283d2a07d18340824ac4b6955df5be8a1eff9992a038f226b9e3ecdbbd922463e04988bd8128300636fc016d6c560892eee09c9e349fabe2a04f2bbe8839f08a6755c1f81b1d576b2f0a66068d5d08cf649c3e3d35c61a31256f07376db3861653", "-a8e357b2df8403c522745aae242ffe9f0c90b59f98b38d85853daee218eb30c46673714ecf0c86e5d0fbcb854abf988ab13e0e0092ae461aee1412bfae0cc6fa7b362cba4ccffbce99bbd76e949ae6550ebb4d632d90f07bfbf197d156d9d5d00743a90973e3667c102e5e44058318d620e6b68e89831cfbf16cf74543dc2d09d300d847b6a9a19280e7182b7076cb6fe301de330478ce287e8871ad553362966ce300d3191ea8aa526b62e0322a404ffffda63148b98ab42e5264d3dc95fca58fd7bed58753ec3ac8e96270f5771ddc3471293bb063abf224af127ca545ce77f2a7f8c8330de199fda29fc7573fc75fbf06b22f4392e81f925853befe83faa46e822ddbe2abdec2a549b2894a4228f17bc205512d15776c0c255552eead84fda99f82a6dd7ce69f2759b37d632690708ae6a6", "-cb46bbb05d20204c3fdaafe2e1aa8716fb197d07929b01f08c6e4543dc9c7223cfef374015abf3de950adfac3119a5eee23559363e8d175b385b410874ddd1152e434f78b081db7cbfc73ec396399d53a9e7c445709da7b6f6e4a0593b51ed6a3ffe5d8ac7e249af01a8d94bcab4d36dd7d395483cb73d3814c050ba67968460837ed728443b685158ef88a55a50ee19eb54b82a72af044a7adba8027328d5f08f04b5a6789ff7d1a6cb6bce791f02e28b0969354f3c6398a873b748e85bcf3f29d0474b4aa42797bb92d227d2", .None}, + {.Div, "7b8151bcd1fa5d97476fd7d66d297879a45154b26e17ebff8643baf33ff1f802e91864cd41c66a77a29729fc2ffd34e5c3ab20872a20b5e472fed78ad7899c22b5e41d63e6377d865eb17aa3045b468f38538d9fd1704f7e0b5053e97f7140b017b7ffcca7353b71167365dd7854c7c9a6f378622f6aa6ba181fdb5171886ca17137d4690dbd8842f624e03968b5ca348a87ef938619389442888dd2875f403a4c010a100bf96c7c2ea149d853322c31da9472bbf881eaf1f255f95152a84edda5bbdea03226e17e4a9578bea434601bd1307afe70bec949a32cdc567ae23b8cfdcaf6644d89ec1cfaa86031c389f03114cc2b7173651349c058dc25e23f4689d80b218d59dba701cb4699df91b6215d0f6c8e2403bd71c723aceeb5a09895740bd00a24d8b258c7b100c74b80afa5813f0e68a682e0c2689255bf0248cc9d24e9135fe43d31b3a1befac04f04f6921ffd46760700234495888a77bee9f55a48fbf1576835ee7230946227fc5c69c732f0550419ff2ef9c05cd4ae803e3a8ae3d68e36f78cfa4fc8b09e654b669697afb2253fd3a10525621c7c5ccb75dfc7ee5389b265138ff1deaefc8ceda74e002716df1faecbd1b0eb08ba9b282935b529d6e766470a305c2fb33380f6411162fcb3a73e1b39a5f202f5bb614ae04dcf49dcc4f1432530d53b634919413cb4a1e70da5b93ffb39e66380c4d83dcd4b903d", "2d93da8136c659c1e5398810fd846f48af630e7cb2d4aa5f7521e7de7ddcf0f38d82ba972e1e492efcde16aac2375b00ee292186590e9cb4d6bf2f1693e7892067b05959e42608aa4af270ff38842e49f130ece5de9bed6272cffcba995f4608696b520cfb5627c1e2730f3fc47c39bc860753ec2d8c81155783460a4975e758f5b1e399c5f0a8a814dc747bab2b9d10e5a5042f17f2e04ebfa8d021ae27e86c3dd42427884850517dbd37c540b3ae54fe96d3acbb81592b3da92621c3d5de29e96a689e5e34bda90f95d27e5a62b7e3b67f388dbbe2b203c9a3dcfc7ad6d095a5f3f86c58aa7e08c8cb8673289c20fdc4787f831d078e46a52f0af65b12b0b0ae5faae676743b7bd13a3c5e5838b23c2a36b6b6a6fd5de3733156ad9023cfa1ed348eadda8e80dd043474ebda57bed140452", "2b5b428e25541e313639b5844893b767cac79fa7cd1bf27432feb2f9e5a702df01d276494064915b713b06dfcb3e29fdc9520f9971054de6034ad9cf36aab555b7c840eb7cb493622352b8205343aa7ecc6c54b7c35ba4b983e7a261f6af04c1e7a26dcb7f150cab5afe3b2620aff5e985f2e414c26eb3b648fdc4f41272e1ac42841c3c2707995b6f8f97a18a093d207df2241c1fd6e9fa0aa4265a5856eca7b03445845d08d9a855300d5dde65cb2bb292f9cc03c6c7c76612357f2c63f36a10205bb17dc0705ddcb4a8a9aaa2", .None}, + {.Div, "-3ffc5387f4023e950cc56aad6aaf94140de1f7a68d6c4f14a9f930092e6a20c5d42b103856d9b4fb7bd26c15862e944e7c4132c89ddc81b83eb421f78d3565ff02dd88ed9728ce45089ad9880d6245b425b25ce94587b573a48185f8d864b12b9e80aa5152c399448c27f6a9d21fe2b76d994d1b00bbed0a2a32294ead195fff0c09b849afc353e0b7cd46519584372c09d1cb4caadd5265ad469a445b724e9f064f39891e5b99ad77db0e8562827e0fbfebcbdd5dca7d27e0c8d0a085d69f28e3ce263d160491c43353d58f4d519b88483eb4de1d5084114b9d8547f08f43a8581362ac7a3b3a57b6c538aebad1967ddd3a6a3b105ad3b7ccf4fd99073a58171fdc65a15a30a5baf3d22460c936404b1a0452c29583f15805d00e522c85032767747a2fd9daef15c40d306be56a5222112c86f96ba284cc9ce1d426ae2d879ff564df7c7caa8b33e52630eecca894f0af5ac1538c8a3c65d5802f8428b20d8d306f10b2218d75022e35ac913aa63b783491d5f041d44f8b59e23b6e753216d9e3faf413aaaa908163e66c39badee9926e4ee74f1f408be963635c5cf9df4a9ef119734cc6fff1abefe6d900bd8f2166e09f543d3bde538a87d86d350fb3e7d759241951bb20c4e6019e25f1caf4c140676bcd5e85330809fc3a643671457d6c2504908297cbec9da0d1f04098d95c0d4bdd8fef14d24461f7cea9ff5fa18c3e", "-166b67b5602ed5a9a926643487042952e0e3f8186443ac5eb54ff718a7d2bca010814ecb0ef224744821993e29ba6b91e4d8e368dbbea178a87970454b020dcdae7fa2784f3a3f079d23ef1e4c8f856115849086b9f88c8d1e5cd62805d194b496e90af3feefb71521a140da8d7338516ad6e33fce7af9016c3132b78fcd699dddbf8af423b9326788686bf6bcf14a1fe4f3afca07bc0e38d92b6bef76cbab408389d5d10456b6cb31d38bc874bda94333f41dd2b73c76707d1c9f98836bc60f96cd8f770e76e28533df9437d4ac9458c1a480763044a56b1a6e4ae3290e5bf44dbafb01d4219e35129ad5d4bbf9ed17a07d9751ef666e0f722534a010d669664af5343bd079307b6ee19b2c86850a7574a6e334d63f500452ee119d5af2bc166a74497def4d691b1294c1c05bb7664f5db8c86", "2daa079dad7c5e8a224b27b98be4ebcb419b1186d8d3509db48a6513ca634aad41dcddf0b8284a6dfbf521e6cc6e8cd02b84d57bef8346bb9999662d1c021b1a142eda876f0e62d71c2bb45c422df362b8eb4199fce1331c3cfc1b90fd9941f31bfcddb8a3c944ab066b4f07ed898ea172587a637235f6080df4de2a6557f3203d49e55124a2a0e34220c4c577ebc6032a2c7af527eee276aae086a2bd33888fe407890b8149086a51f0b512f42420b357085105e5008160900dee5305a09339ffd9f110543461d6ab7994b1f0", .None}, + {.Div, "-1646a54f32a0cd31cb8ed73e681fe2f6beb3007141f8e47cc3bef5c7b375eec69e65eae7001c949cd6a7da9a336c2f39889088397fa3865f2cf866b0afdfaf7d8f28780988b586c89fe7fba074146027087e4d49ffa2d1a6aa9f968a72409099d6ed5b2713048aac7e2015bc63f1b8f26b72d77483aae8b3e84357d303f8c739cf71a75c1ae8acd0c8271c3e7ea2460e7b53999c962724141e595d4515059d32f3f1ef9fb0d531b5129ac560cb32fd70cb996859a47447b78db464f2df5c00eeebb3c4770ad297f567e23075232caaadada0e7e76729757e452cf7adab8b60527e3690b09eb162619d97394c939d44e3d86fab7402f28648a57e3a31f4034eca734ff35391a103d887cd4a2f663af6c1c350301281bdc6757bd2641ed66141a01662d88cf51f6f853d711eb474a5c3fa86f75d619b72c4a91dfbde966d3279d10e506212ae91bde2ffaeffda45ef042f99698e8a0544a6c2d5a35de3f39ea7f8810dd5621f8e9dae18dd1c5a3f793d2d513cd1291fd5674080bf0c4e604425498dbb7b5d680c2f7d433ee6b13ecdecf0c99cf2c285f759da024982b4f9b64917f5671c39fd23ea0f70d7415d116905c39d1d161635f4e1157a1b5c48560d6394a2def6f5219f0f6d859e4c4e512c94f545d058e9cf0495a8092ed6e4a5ba7281c941eabe6ab3d33dc485792f6d2822a4d06db1296eb95c2c708a6dd1a42ecefe", "17f3532a22291e662c9afad415fc51a71f740a83551108c88c4fca54581c4f422b6a60514893380acead4192e295bd9a88b58671ac4e3c1d2216902c54ac08ff2c114259e2ff688650f1004e908693bf11883b584fe642cbe0ddf06d1b05a6da48ed7701f53866726f8f377573da213641db0952a38a8fe78c884ac58b855f42b556bbe2dde60bbcf1bfccac9d0abc263e378d72a164b1bee4523988f736584c5ef06ac3c15562ac8924273761dd0637202eb259a06169a8c7603c811ac53b64498714636188a47390ccce6aee5e32388014f9126fe0494e285b41dbad01d8f0133cfbca9f81f708bb8f3f18e3869b09a6262bb1d0643272d294b088a291d270096e94a5eae0fa41471b24d0936a74a9c4311cdbe48ec84fa84f52fa602c72ab43040f2c3d0ef04a999a4204791c52ba119aaf5", "-ee19f84cca92ca42214f436ed7d6c4b64fe211e1f3a47e294ba525c8fbe3b017445c23171ddf16c892c04adbf87d766f5583cc5d0691ad55994c36b666855b3f47cf4b1ec26ba26b80d53bafd5711b072da8c91c70d66feda9fa947fbb68fa7deb33a1627c5498811eb40714ae18f58b7ea5c6374ca86a27672d72f35ed855b5ffb0b51e6111a49c108f8f8461dad3f986b35e184595f846359c1eb11483f253ad5cdbab85cc204144c808f18ac5aee22c00b8b5ab9299fa2bbc1945d61097e4234bc55c08fac345f72bfec48", .None}, + {.Div, "278c8e5c147022ba62b829f0b073eadc27185e48ba2d64d1f59afb88b0bbf66b4424915bd9123baae674ddd1305c38d732ca54879b9ac8e43d9e8c27fda7cb9f8cbcba58584e67d3f38bf6e117fc93f3ab4ca84324bed3ece6f9830209f2865e4afca7b975bec9f69be68e3e4e006363dcf1a9be64699df2f73a933a62fd9c680488c1882155e49b047c3ab9fae2954557e689c2003686584d36babc41ecf47e5275be0711dfad1870fa2ea45de744142f1c8a8badbd98bb4cf1ec64b3b85d0ce42b49ffc0917f218a0eac4f8fc3fd4211b4a582258451b4ab2105a820b3ad8882af45308092ff2678163ed8bb76be01a796687c7c7e9f4b4ada6cd5a9d83c783cfbceb702ba3b0a2b0c4351835e69cb2693415080b81a2bfdc5ac967818bc2b3b07f61bf99f403b622ea64bd7e733e103d2d755032f92960ae4e00bed2c2eb23fc9d96ccdd9af800dbdd21fef5fb3fdd47a25b4d68ba93b0b35e206f4e101eac372509a32f7abaa1f551e48af5e318db446c313c8f4b65e7eaa708f616f045cc8bc8a6f1159037a33036a2d55bccf6ff544494509f0b802c4c8f3db6071933d7a5f371bd54ecf7518b37b04e62de8b64db109153ad0caccb72d0da96415cbffefb0dccd1a30ab30c4c17bb9022303a268092dce5be041a8cb8c77f5ef5fbd2d618660a40aa0084f18e292477e4dc030f2f322089ba67017c1c85ce2c3013788", "5eb366d3668d90d28c3fbe652313ec982d7bfaf851e4068fd422354785d24c8d218a8775b4040f39cc40f1e97c8ec0a86f0b0e25d03b10e6cbf49342c21c15111f3245f6c6d271d9a0ce361bbe1955debda6d25350aabeba14c4c1da1ed99fcb3f045b9b4848f7c3e3f88b15bae743c27f90edf721c29813a944b7d834dabee3c8a4f98f09ad4ce800447196977a3f01a5b3fc331945776ed3f65af9e1fe653a374bdefedf8d3bd5d84c25f14d64fe8d8dca0d58271a3d0c49bf42430053472d327b5be7aec08dce45fe4476dc5b40aa2599d7ec344e2c82b1ef8c1aa55672971d2a09e81e7c9bec5928fa826f3570122779b777c033600b18cc3e02167d8fb276d09bbefc244572980be15c9b7a079734a8e1101e31269e51e04edc30e27f204dd4fa89e78a672aa938e7e3cb0ebdcbb351b5", "6ae9376a8d16a3000b40677a48b9c4087f4e93c838f22bb53f93e00ca66c475cff6e196a440e6c748ae5ca0eae25713ed015b91c0392d5c147794336fffbbe129bdf0d063497818f8e7498d60027873cd414de75f68f4683f3137542c4fab4ab2705a2aa35b40c3809f30d4d3ddcc5c84b17a00be940eedcf5480cbd73e746e084311ffe184f9db35f3cedc035c9bc21a489421f52d3c874180fa6f774131ddc39ca02d62984d61ef5bdfff9a9ca3f5d36ee9dd3a0f9c774f10416bb3c472d5b33740efef161177e57dc8d8453", .None}, + {.Div, "-44088194452a28ca8bbabf31f87af539c2dbc1e96dd8ff6b768296ca9fb3b6299784bf26802427e1321547713e8be9c5db1559e59956ebaf7414e7cb6165dc33df5adb418b8ba976e71cf855121ab8be1ed43b42eb361d3de3e95f209a97a3d2027599b369f3e440419a0e628ba92334e8680ac4bf035e870f77b517d85d98b20efc4277c7746d40a87899b0e5492be7e86f9dbac75c728e481bdd4d829afc14e35435101af71e01b72782174bfad22a05273681e762c115a21209c44a3a351df32da8698fa0d749a267ab002aa15b240f54771311d2a33228eb9ba598985cfc9e6844bc56c94a874e94bc488db1fa64a6fd7a8034ddc927146dba7961cae4d89516f56124269cb8092f3752069506710023d91e0915efcf7374c8d261250e3b0610ff4556e6b1866ee039c8e920f0cba00ee3e168018f77bf9344e3b03a5ef1c9b8ed12f4c1d710216efd97eb8ff139b911fef3cc58b1b4134005fc93655e40339d200e267d29cc2f82d90696d6a1346957b1323c89fa43b9e748e8b9e47988a1dc4704570cf1575d111495d763b0b5ebd9961af2fe0cad707a86363c949a9a3162b0544671d4c3ee14446a74cd493d7e658cd19b451d784c17ca234829a94f74e11d6484587f20d6e2496d8c630df9d0ff594bc113888c7c1f128186c7e8f4d7b7d8e678f0237ae91e40c73d6ffed61aadc28a157e3a3ab4a587ee5256bfea", "-44491216daa06d40a09f9fea54e86c3cf2b6bc777b7ec31a01f3d28ee0764061337c4f20720587837001992f60ba4bad4ab55b9c2e9c786f133a581509c4ac9e104e88e14c83245da36caf2b00055fcb9239a32e0d05519714d768bfd474a3d2340b6327264a61f809ce8b964e6bb7d1396e7a43ea1c8c517bcce5f9c3749ccfe9771543cb4212c7fbca49426b4708d08a13f56fdb9bdfcff723a62f2fb8c38f66beb24cbbdd0e3826673f6faf7d5a6eb4f31e164bcdef6789de3fc4a7a8b31e39db290f333d923a8c21ecb219a736d49301010870981b3ea3b3da49ab1101b4442e749bb1095551a32247ce58fbacc7861b1ccf82fc33cf29926f84bee932705630d5ad29d23960f5522e0c0043a9655a004cb1e00f5ff6bf6fb1ffada40f41eb0a39a13fe717fb801f0e1dc8d26bf081d000", "ff0df31ed78ebecb6dce43f8d3a99a2f9403cc7d12ad534a188cedff1bb700d21a1ee0f4e5b59bb8e95dd38705e687fcecc97a31678e614fbf79b5e34636b2989940b3051cd8a8a0e33ba27215d0a484352982edfa20a46cb4328028e887285644a1734f54f77375d90330a4a6bef96956182d82bf84e67ea337aeeb785bcbcb810fe8fb4f8f6112fa2296d847e7d5eb24e38091754dc0d92b365511d8890d96a165860e3e772c6e17d74e26df88b9f4a2f3fbcbd1b7a48ceb9e03899ea50952dc38b1dd117790f3cbecc78c50", .None}, + {.Div, "-ec1f9d88e69faa890bd20dd1c83d554af0306a678c5a5c8497f1e41d22000e54db8df9fbe88c94ca50bd44afc2f00ef29f7ba140546037ffe6d13b790981859819b85b298bf249c7591ab4e610361abc334a05c3ae17e41acc59d8c8859bf9824b03b0870fe6298d6bea6a8837299cd70ddf41fcddaf7fe1d3ca9e7f525111e02aa922d06dc3891117ea0c1aef4d0a360937d57bd484a73a6a4d45af317d69ab9de0de0f5f3950ed2ff513c801286a65d83078bcd9c332d3f73b3e74654c31f4fe8daed3a2c21d51e32d39a06731bd1f373914e2aa522779dcf9ad9843d9fc7015773f317c3221c3b184730fde63afcbd8fcb70c3baac36b8732f0c1c1c77c23afce58556feaeeec6321fd2619d062e6eab88b232a9485bc1804de2dc0bdc9554a0b243ba81737ddd98296edc94a94fa4b3ac277865ae1300f74c22ea9e2713edd655271dac63f81cee934a7362c42b59b0891f0599203d1c674aab17c5eeb3a5b68a5674a90b9ff199f893645ae27d6a29f2a059dfe0ae0175fa11bedff33dd72f745afb85d88df65f57a02679a09e8aa5f23527577f7cd7aa8c9534f2f12acb0b938e8edf6d1b67fd9931727ce30284016d604fa3a5ea84b90358e89a5d87a618599fe966e55618d8e3c3fb888e530753621436029978783fa194ad7464d0e588f0d69a9207b3a22b40a7cdf3dc90b53f02f5810217cbec52f33e980dd56a8", "-1df1a550f3251f67029793687284a7175131cf96aebbb7f7fbfc88123b8dbf4fb27a61ace6870415fc0a1f6fad1d8ce1679b0c88b564b7343ec80794ba4652b7516afb662054299a504f17bddee64f939fedd504b480d9c5e03877dca061f658720de40338f039c8a205c9447d3a40c1198d7cb6faf6f3bb31826db00eb50c0c5488a2d7b42890fa7e12ba14bbbe5fb4e4260f20504d883dd0089a0cf2a1fafc9dc30496fa7441fd8b9da230d0c169305a5ba4ac0ca8e9fd657d2a2fa7b8517dcaf69146be7a311cd8375be54d7486e8bff79926de12879d1e775e487158d0912ba8a440263dd09404547d0ee90aa1a0ccad608d272226993fced8d734acd9cbea62e7837d53ee79353ef83ce4a1bf82777ef55bb1b88b8cea35c80e66f5d48c32d733cd1a06400d741827c01fe7ce269ddddaf", "7e2b18b6074599a2ec4b31579c7824dc5269b2a996ca58f8c4618aad0b3c30fba5290ca3264febc54c868b14138bd6af4ae1b43992e2241f8e5327106e04ef1076b0fd1d1ec8b0a1409bb9974706d6bc5f6b2062ace2a807f107fd816cf9524e938f61f30aa0fe177aa9c7c8dd4d1c81f54b87091dbd4bc92dd2fa1e8d92440f32808f04797e6ddbd209f645ce4972931d5f1a839139ecb38f6559a2cc11be59e9d5f6ce08bac1c15e3efd47e9e728bdb0abb166afae4e95f56073b1a246a8bb4d9f3cde9ac17cb8b3c4188e94", .None}, + {.Div, "c0272dc3c920a9d062f9a5c2b23f237685e9f85a97e7e4b482d21286bf6baa7851cb62b6d204affc9016ab2160752628f95c76826f248d0ffb4b44577463b20e73d056568ac88f16a584a116885ebda823b74f1f89143c1fd7e10e873f39cafa402441e0b4826a8b29c487a00b1433070acb8cf2c6eab82dfa5836e7885187f4a337408c76e5fbc08cd4fa01d28a5dfc9ce368ed645ead2b5f3943eecc97ea8341611a1f3554cf014bd4566be154369c7049ede948d772e42e48f8f3fdd35d5002d7100466ec944b0ad284492c65e13b474250ae800e9b341602860576597f0b05c5a19313b2efe12109e10513670aac893b22acfc93f78613675a0d13d02c87693e31cd243217ea6cd4dc144a47126e33116019574fd72fe0d3950da123312929d8eac1ec5b546ae6c8562e13532997caf8666d686b368661b664480025253e651d2e32bdd932868e20ad3a1a19a3a8be32590e71bca2ef3edd9a3c2e374c58de40b04a1810e05109d018a2a52b38b539d3307c67fa817a23ef3bc1861690d64d5f363d85b40643f6fd3ecea96ae1bae04e80a2afd049f70b8e6e708465cdb04aae57f33a5507ed1c5cc48aa33571f11c7a75e0165dccc1814aff0bf634ea2263f8ac36f404407cea762334c780024e8d0101744234914ee9972b88b385d23095d18d724857afdca3ee143c40bd2e7cc8a4257cad45e24e2b42ef2d9414c1a3", "-1ed8bf499ce8512651b29d5e8fde7311b68e3105e6689a506a0e7301194bbb20022fdc6aef524413128f08ad51209cf76dffd70b3092e5cf1f75b0f76a056e35b6da5ffa3a62d27a7e1538fa69b8fa35a563926851ec7a634787e1a67eb003422a979e882ae8f8412080ad32423a849754fc3bd6f50a3abae10e199a2b58b9cecc34bc9e961f862b5aab71a6281d70df4a0ae6097f35d81bc47edfaefb7726dde19f2c9d28089ad007ff4d3e056c9b8c03fbe7d1a8df9ba868180985f668167e6ea35c0263cac557901dec1ac9e4edb8aba87d829d94b0adf88e9ab0b8f37064488df0fabe1a4a1109e3e2b30ba1bf1dfc2d514bfdb16cfc995e29d55bcb56e70903b936a31131b3a59fb44c1aca7a9b78f93e31aee2753da16bc074bc3280c67ff940b2db06ac81de2ffb251ea550cec8b7d78", "-63ab32ab78fe46a80f3481e5949b58e1aa91f9cb6dfcf0ee17cb3920c363cfc3c1484816f890e63d9710e9f5c327f44e6071da77a9b78a070e2038fbcd24e9903cd68dd819b9d6837fee7481559d525c5c6206614729413604ad078a73034e81de18250ca79a3c2d3a47217ffa2d3beb74600967659f8fd4bca65d4819f4ccff680080e828174ef3e7fcd88d7604c297fd59d6916233214dcfb0c3f416d77b9abc207272f86f0b87c09412c319f9937ad7089ae049d2ffecb319322c9f2ca49b47cd48f16d4abed07d5b39e052", .None}, + {.Div, "-46cea1fdc090cb183f9b4c5e4cad9529f66f32216f3090c5228735b1b42a975dd85dc4fbced83a1a04a7bd31222de91e9e27cbe8659c714b8f7f40dab334f1610bd197559e4a120287f82afcc86b989c28e43f44306e966b40424c0bd7f32f3aabbe6d9f058392c0a69de5148e299acfa95150df15e8076b864b0be4d4e57e2015a91b8edbc2abdf7069ceb696f7789cee772be370477f5021253ad5e67259ffba0e3a2b2bda51d2535323e57dca5d8e4bd573fb02510538cf26c34ad48b76815ff4dda6cd8450c2e68c5b1d99202be45196a5f685ea7d8ce51f63b0d8f56a65695d79f92b1775098f173a2ea69d61d4599b576b026259ed1167fce603e85a671b73ae9b51c8cd30966928788b77daa303d77f37e8937f95bf925186528df562bb02bee22ec8a16c91edd89d0197442808b3224bb8f1b6f173d52a4b1cac55b65cd767f15271b67f80dd3120f736b51b63100c192eaa8d1b1da65b9c09f91b1dcbae1c99bcaf077e262b59d07a44eeb384b73dc8c398da4e5ec31b2a8856070dac4661cef5a63a205dbf6766e2cbc0b95777a32b41d458deec4fdee7cf7265cdbafe534192aa0f9e129e10162163ce1545bbe8df1ec8dd7c34eb831648468f8bf8b82c6fadc991b194204751fbfaae62e5476f4a6d099e63ceec56fc2019c1e18188be09cd62bca25ee89f8d2037912b8151e2904d32646d61023dc387f8d7d7", "daefb3755d5e3fccb8a39efdd81f154e739d1f0de2100b82a7c03f53555a45c64af79ee33a3d6442c5a117a5e3217a6261293dd97c6818fe30616fd009a8a991472031bd1a163478cfca55c0f22601bc75c692b9bf0a967356001520bee7a29fdd81bc24e38501940b93647e3570e40f316d11ca027e479a122e881c07b61b9234f9568d4ba34361cba495040a38d9e9555480d9d6c59159e2e654c882fb20c541c90fc81a578f7dae75478b9043ec109792ad3003e8d02b32b506ee07ddb352ab1e0af197c2c7211761d88cd7724d9542deb96f85089cc2bb4b8e1bbdcedbdadc1099f83e043eb02840a8eebb7ea4d7cc14a05041ceb7c22abf6485f0b5720d2c9f535d8bcf0e9c48ce7fb2e46b75676ebf4d14220f34835a58a6282584ae8f3ccae96c637ab4dc3df1c863712a604c16ce58", "-52cb4900962883c54ddf5ec8aab56507b467193de68366e4740e1d5689c0d1bda7efdb05e48d7212cf5d59250f37730d3fe4fbfba318e83fe3878543eb302a58da23992220e4e2238d34492cd9b92a9be86eadf22cfb59ba5a8bd1d678c0c87eaf445aa4e8258f01321a7ca43ed06959fac55e76c5982f72d8b72de2d5edd6d83e467ce3d5b94a8e311f39d8de7d858e2f1bf704f2e799e2db81940bb07a9f7add252de07947689adbdc7a04ac390105c9ea4e002f131e5a2aa6b4f9f5c1cda11fa3c4764d965c42d1d0a7956c", .None}, + {.Div, "62a46904f01edc0dbe107a92cd68e8a7a0001fdc1fea0adb609e3bf072a8aa237a7d88b14aac8db9c9e3cb20d6357ece4fb9344c4a4e22c7675ee2d9b428446f9bd0505caa2a30af5779d58d3c92bf7254742209820970e96e50c38658f5b4249eee5e92eae52ef5ea5c8c63e59aeed4fc9b964b35c13375fe444fe385cb4ef750b25af335792312038f0ed60575c3c891bb0a2d35f582f13ac340bef99769749b0541521b80a3277203a07e0ce6b5236fb02ed764afa9e3d5ffd615e0dd1b1456e798c1e90bcb3df26d96e1b24e5bba45b2176848eca876f6cc1d05505f48d3f39bf456b5cc4449c436a27d977b687b14cd9ec30ab01efb21d28cf43316aa0a93a7d1c523961aae835f337d37ec7bb2fd47f5e7fd56bde02edc238b6d468ad12e6e1418d3bdecc5b44e6ddf6842e32ae16212fa5f12e7b259e6c1cfe9bc70c9dc358bae07e92b53e2b3d03808ecb094eb8efd5de3889f8fb80b3ec85243b3b112dc310225f32a3981b2cf95804209d28ca2f48f2914072002488e110be4fb0b6192e4734a76b3015c95a84247fde3f8bbc09eeda611e481fc186ef6d7fbaa885dfc285b0bc78c442c54cf2b1a3675d0e4a36bd23748065a504da52a7fa01a0d808dc566bca42318a0ba9c774f4d38ea72782060dfa24346fd3761827025ba0a46c99b64c5c7f3da9f1702b0faf97eb84cd5c551fdf2c0c9c08c37b43b4279b6", "-2b46c6f3efb02d7a529f3aedc3147ae7832f00dab5aa1fa4fc74d0ca9514f1d0109779803575e77057464515a8358e5d07f78b3b865881c2a5383f3c9f1918571b7142d98c6b9ab7c52ab466838a4c4ccb38bba30d42bea8d2c5778fd4e4999629b9d19e1f89ff0c7777a725b2a8ba7f24fa4911ea3f9fdbba2262ac8189d1e24091db7a62cf10cda1ca73aa4a52f82c3512278a73a9cb5059248504361f8404ea4d1f9d92204791285adf7901a5b482958ff3807a820de52a3fa692dbf86dd0f17418c36366452224516938f1b0670ef906883e60af6e1ae7262350d0d75fa1b0227c96c739c960e18be13ba1d6a4c619a5a142bf9f320588509a64340ddfee06a6335f5b2f1a57bfb88135af90203769c8ca917a9f1813501b434359e452564cfa496b5d8f0447b3e6935c01d2c19e0be099", "-247837a8d390e32c2a8003c07fa8dfcc23388e1f9824cfee830c0be53cf7edfa3f84a7ccede3bca7ec9c60c8f004c96014a8d7cc69c71b9bde56dc4cac6bae72eadad313114564ab5e29aaebbb7101914c019b71a271ca29826d48ac51e1bc01fb0ef7c75faf38d88a49c521d0065d757a68dd881d99286038d250ec513409604a6581e01744b501f17eb52544255dfce5651791f8aa87adb011eaac54134c0ae27d977233b2a9aa6830bae3a86d02085783c699cb45ca1de6e3d82e23d100baeeb66cc53b02cdb3fdef753a136", .None}, + {.Div, "9499be1d41fab771042d8633d54064376912572b6f81e51ac84c81831c980d82ca7683f50b6386a9fd4eda44f621f83048f4dd239cd38cafd68d6def5ea3ac45dd2b3011eb1fff577bf23a9f068f34f33a978b871f11e6318c2a38f621d32af290d2d80ac8b57269b512865ef5ecc7f162225bc033f8c1772d0d5393407c8b8fd397a1a757857e96555482fa493e348c9763c9fa6007af0fcfbfd46cc46971c636ab7d77ef63858e2813d61dec1dabfb0cb7ed57f900c050b9f80a8ad928defbb8efe2bda7c7b01b369a8e1efabbc7d19cc579144c97a3391f1eb5d81438ad1704c29ddcc5284f89ff4ed28624bb17e94395d7de1efd628c372a281d180b6cf4ec8cc23c379491d6541adbd98715aadce6dc915fcc01db1a9f065f3654c0ca4377956479428d69572c84a34d0dd527ffdbbc492928dcfca1c41ff5a075f5477612d9fa3720e9b69bda4e939fc9d1233aeee820bf71eb3e4b2e24779315772f79bc5c4868dfcdc76049e1fb6fc1f62a41dd56aa51899ca30c755e796a5408edba72e028fb78615c1b0da25e77ff7947df904f150eb890e86731e4a1d6e098d6719964f23393da2b7c85ce03840d81dbbaceb54d3c44dc6d63bce84fc468f0b6558565607c78b5c033252328f213f38bffa268ebb12864843a3af0bbfc0085f5b8337f9bb10f6cc9f8c978ffe647575780997674ff15e64cc74658a0f368f73659", "-24909dfcea7eec331b5dcb0ae6802988ef6255bc7adf7d285326355972a53fa34b95b598e129ce97e3e8b876e99b85e5f5cd02b2c330a8ff8154243a1d8b53d783b4760b4bab3fed281381b0c1fe3a3a0a891a0e7bed37b0cbfd56a41dfaab57f80a988f786c55b4d568e3c2edd04ee1e0b89cd9607b16c6a5c688d3c28cf7947a48f635bc76609605a2026f8967702c6cc7ac4dea5bb59162f7603a2bbe290ac9ab4af2cdc92ba58dc0ad841b8adb322085a29cb1481dc815d625554b02c06a7874800108fd3b14954ff2af31f4355062aa8826ae033e781879622054e693e33bdf1f1b9a48144c3d856236453342068f184266ce962b7f9aeae201bca746a1d56af05d9680896914144807f8a4c7e27fcdb68df7b1979976206e8412ed67ad1a5463a08831843805e8210b41935ecd8771fe", "-41063aa909bee3cf4bd205dd5ef2d20b8e85d33e05b47509e3be9c2ee8d8fa73640b2565940ad9cc3fcbb4364cad836dce0affa41bcd10bfa341f8ff2ae16bee3514322e1da0bbc2f716a3dc74c19e672f9f20fceef4306226f716133a836176461701e99dc204ac53b4aaca6b127a42db53826ded40aab7d558e3bc4b2e760aecd54f50b9abb485252f02fc627a0c03eb4a17248311c66689ba5a93d75aa58db06fed1a887410cb0fd433c65e779fc06edafbe333139d9905673d97f8f32b23eae362d7a6bca50de3a3e11f9a2", .None}, + {.Div, "-a25c82245dfe0045cf9e81b5b52b20e41a3416e2bbde8634fd8c30179e9065fb230f2ced6123a08a19b4af8220adc65b882dd4a54076ca3bbe9da842406df8a591512f01ce90309a4d65fed3bfc05109889e63b60f5bc903800cd1fceb10b3323388798972607c39755388b218364e1e2370e8b54a92fe7f3ec35d38e9739cd95f948d1eb92f613e3130df0428961851c30fdda61445e436f6c51f15d2b1284acd82bf5c885e2cb4b0402ad95e1a151fa341b023cfecd2fa9d1d213d86c5eb520277fd9f906d432ca49d3471771edff628103ab3a47ba92a185d8d5c5ef83ba026cbffcff58828c341d45a1669a75eac7b1e899d5bf3116f16ae548745db406e95e12127d32b03feedff3faf293c58e826b45e3ede65c8ac394602b5d38cb1b0dbec16e38c51dbac6b38b571a2f582e3c3cff102a6577b276306b686607581f91d1b5342b9a862dc37c38a0378099608f29f4abc65bac149dd641c27967c856935a23cd214a3fd3f411e5558b785e800164e3708abdd6ccef5cd077eb7b4a7e35859b006a809501e4780ddb7cc20cd10dcea25d81a15bc444e0ca3d63eb4a757b927a250788ec0d9d2779c77fd2330581bcfefef9e5f9b014cb2174e3e06bd475de640a56740d48ac07f3aa83433c08bb8d8c2fdba4a84c2fb1b57eb52c720190a21c8a4d9f80b231c46c4187f3b3d0921b6c4c3fc1e36955ea78a437756e12c", "18dc281c6f7ca0995f902371238fa35a8b4370990125735dce1b5238f8aa92fcc4112c88dec17f4ef3d785a57cba0a4bd14db94a1390729277d30cc4504a683b7d87082f6dbde48abbcf7720bf593a33d3a0f258e44310093c4a9bc47412fca99c79c44a0eec3b4481c561def934237ca28c88001ce052202a3d5b8a2d51bd2f07279dae44454f7c2a983211b99f240378ef055316d048e74f6611853dc66108fdd2da891cfa53c2b18f5d520f9d0dabea12ac3935148d1aa771b716cf58b46eca86ab3766f97dff7340b03f7b05f079636b844d29259b7eac494a70f74288b3502f3bc446a95b2f9964473cf7444fb1ef2efc94b57c37a528cc0e075b9ecee32dfbce9f2dba7cd9fe1ca0b66433ed68776d48c6696ff9104616dc40475d6de3eda8776bb463d304a7891ce52261f70b6a341c9", "-687f1afbe82b4c580bfcbcc197a465c674fd355ba89ed080073308724abc487890a9f067c2332d1e1efe4df502259f5607dfce4a82887660a255e648dd25b4f1dfb5c5b470614236d263727389de78c84d5cdbf021b5c130877a77afd1f82f5a445ce6b08e2dc9e92df4133a766bb7b8e73513c5430254e4842a26a6b5524b207f2d0364870ea8959d84d7fadb1957f1bcad9d7e247c4e75556fc5a7d985174c3f87fbe8d536471c175fd9dcb718fa3ed54421d9295cedccc6c3ea1049bb2d4b8411089fee62897a30f13b008b", .None}, + {.Div, "20d5cf139f0e23ceb199d3457652448e969632f49f79de24111357f7a2721bafbeaf7dbb011dda5ada01479eaf43ba97edd94e88571a2d12ed64ca7e2904f368d80a3cf4fe6b4bf874adb7db0486e47c24654c4c4c51053e7c48e7f39bf3bf2c8b7964a76b58bfcfdc6496ffd7e771a94dd0e2539b3b0613ee6aa70dcd97d363e48776e8e0fb9f3b8c464b606781d723068975f8c36d8877aa7404c402785c9ed67c3acd0c40371577b6eeaeab9f94ab5a91189c5f7973b3d417f6fd53b5ad8732bfa2f92eddeb067d1d35219cf64a6288bac4fa31f0bd7ac5b3eef644dac7a348968d4523c429fe05e8be0d06955a0baa7fb258206d429b0c7ea866ba53fb53a338e2cc77aaae7698fe72bdd610301800fe2c6b5f4a2859f295847e378960b2e900d9d14f87e2b981021cb672aa956b121670dd312c85a0fd616e1816ffb3b7c88a69964e070c21b4a304aa4c9270c5b98487246cf44354982027668c28642581105e5159bb1cd04eec0fa813169010626cbc987e15f3176f400c5b0823fcf7ae24ab8f8b975b5a0c9acd9872e5320603b161d6d7dc6c262d6ec061e5c90334673e6ec405575ce952d9b7ce5f581bfeba5cef35a29c5c4aa7b7985c3cc20fddc3ba8816433be842d6b4b0a0e05fe13e4944e1b471a36b0878d58dc012cc55f7f297c2930b4110bc107a50af679101525ed6a4f2563837049b40923dcd4608bf", "-134f3682a5bad54ab31a8970846af2eef181361f13c80fee445b5c09a37b9e5c03733fdc6dc80b07102ef2cf556248cd488aa019bd938a59406fb3517701d6a9a5dc30c6478a4d13700f3ef37809dd27f4872f528f8262b98e19341086549d5f1268f4c3b5e2817e1f9878b2c3540650183df8bb1eae378679aff6dba1fa2aba4b9b541a99cf77b88c7b0b0c9dea6582d48ff2c5a26cd5e175889850113abaf0db6be5ad1949b6cf59bfceb1e4cdaac35de8c3d29fe92f12347a778398b66a6f3b4f06b9862f48942713d22f995b5f3c2efe01dbe4469102c1a0a01b6e7e213fc52a1287d8171827988dbfd503e6e8be4082010763821fdf2c75612e25a8eadf2850fa46a51f0278d883d7e0f2a528cb75a67cfc625cb6b428736ad2c24aa3abfaf175047fd8dfd231f8ce657ba7ee34917cc09", "-1b352509740252287c8e8e942be0e1c103633463521b7b9a7f33f9fab82bac90278628e971fd57e11609772d51691b83058e0a623f5dd66ae0e26250322c74f23de111283f8e347a041c12afb8f60ce57dbdacc92803547c2086da000593d8b1df3023b50a02b55c2c25118c266773f4c665176812bc224f1606c066d36de961bdd7ffa0e5ee48f19079f3c855bee744db0c183806b7ab2a7dd1ae3161677771d5ca2bd091a1e6aa2ddc5b70ae81625e6284a3825983c0444c43bc7d39b605f2deed19a2d2bf185a255d94ba20", .None}, + {.Div, "-3b24a0852b66a5ff44b1ac39617e7d5faaf3f2cc96331738a044cf2db30260795973cdd05182569ff713c44c166bf1e20c714616c1a920bb9c26556757a098d6ffcab290105d09b8a135859becc6b411fa3e7f88b6594bd897d1cc6e709ead7558a83064d06c05ba89d531051a3068a363c0b75a170c5e0dedb7403556a62625a79665c14c3ef72cbbc553b4a512c565e7f78a9b0c7b75dfc14291a17d2b3d3d8659d74039ceb3a9c2bf7644936a9a0c27d34ff066e53dd279e05dea9dcd6bc5f510e8168d5725fa49df74b242a1c82f6a67fe3ebddd90a3cdd3b7b3bdf08ef046cb8675370103ef15ba8ad789b2ee40e81d73abab9a81ce0c369ec4de0fc112aa7549fc5da610469cd48649519023891d6e854b2f2d59790d94c4c81bfbd4b1e7e15db7983870710095268bdd83797d024ab8cc40b8d2fbd88f4a7f7d139947909e685cab07412d87bd62abe70582faef5607b21ec84d83eb737c7c4c76e09fd54060df0b5b0667a2e93f583533ddacf7f65e9425b1715e423f51aa788b83473230856916f5967530102555e811370f28ab532972937a2423c0a21e262f39ff81128bc9cbeff90ba58c53161635af7279cbf8dc7217ed2448bdc6750d54c6f39404e8046bae9b04e202842248656fef9770c727367d8f134f9757456028ee2dee6c5660c6c422e498876a7d7b534a3d7e45b9b763e80b8569a10878d7c7cab3", "1bc39e34778cdf9019a89d8e8ebdd3d2ec7e86c5fa1adcc2a8f15cd6568c1e6cf296e582d37a4212f32e95ee16e56f1ab2e302ba832959218b254a7672e0743296417200d89886c5af199c7913f91fd9af47ff35095f6a68b722019f372eb20b46324b0b858483fb5ed80b58601b58c6513cddf7f6dc022821d2d10267fae72234fdf72cd557892b585c16897ab17097f60bebf1e2f7d990c064914ffec548f7b99978bee7fb390511e568b1ee334cd453b9374c12e488673d2c154bc2f1e394ac80d13d7214c8c0a71393b62e7f88df8a881092ba8ac2fc7e1414b6263b40ddff633afd7a2d552af27e3c2bf219393d9cc79fb1d35a164404a3b3e90c8421dfad1b793108938673aa9e1213ee906193feca7422dd6a1a8f77eb8146b88a7b0a522ee93ec6bd823e3dbb47346711836ca4d2c14", "-2215498693bfc8d1aa68af67106e15ea8357612b1b3612f7175c935807f605048476047a9f6c91e0c645905f1160a5c8ef1e9c892ad8c1dc41c1b1db995b8b1a4c5bf5a9bc7a113ba74c06af4ea549baab34f25a6671bc15e22be1636697c7dee523c87b219d712b3c6dedcb80a6e78d56f3919bd3f39f2180727756cd9e93242548246037c4f3ce7164b7b5fa67e612bf5f74a02ffcbd648951a90a152d2413e04a962124ee79e46476eef817af7b10144c63e9c4f69ba4e957b2552f93e82073b92028ad010643ada6581944", .None}, + {.Div, "-98edd753d58380f3575fe651663addcc4e5384d58eb352837eb5614a3eaedc0bbf0d041bdc52c4d5d7fcf9108eed5dea95e792b1ee56299ec3b686aeb10f0660b13d256de977ecebb3e627a231acf4fe067ef3971c10e303de066604e58efd9f07407a67b5ff72c99712829bf3b66201f95c5e5698358e32038b8a7d46d26da094af27b5af76e062d1375b6bf3e7bd7f96063082b1e8ba3a06f316c5bdff02113337b1e392ddfa1d701fad3c57e961041f40ffcc17c0995a8cdff3cda4d379a9e5b03cfdbca76938543a88cf98817e806f8e42b84891ee44e1b17ed2105a5aa04b3282963c20a5a0b8a7f0f3f470de5c89af65ab5b809cb3038960bc91f60ab2a4c760e18a57cfa9c253bc5dd5b939d2deef4b512667f83afaf8c0d4009234cd8470e2b3628ba0f9b8f26fc7ab80bd99b8d5ca2abdcf1baaeb13617133e9724d41a30297f8d1a0195c744436f1c9d1b0c758ef7d2040a2bd8e57d7b7b7f671fa251951d4a80f7f8a371d00f4bc96b4bedc075080d6f9c63053ac8ec0cc31364108f85ef5eae27fecd451edded664abc22bb736ded46e7d7a38c721557468d1bd8e67eac5c17432138681c13df85babc47c56b6ada0f54e6f4315e0c5dd13376f7d1dc33a529934ee3093dadd46497878f817dd3e15fec098514671fb81e17317895a46ead5b055997bb7e4ceb09df5da5211197ab012e395a0dd248ba2bb627a", "82ca100d2a9a4810ad21c638dcfe06347076e7d2183b1726aa72095e34b1c624435569d086cd3f8ffd5c828c06cb93faff26934d6c7404f974c91e4dde6c990030b887bc5c16bb8faa7ac833cc5da509bcee87311ba3c8d26b0e2ddaf87d7b28f8ef5fbf5771f1c6cc09df5e0a233aecf222b2f5eadaf513db4dbfc5b23868bb1e749afc507550c80d5a5c372c8a535dbb9f4da69fc295d170a89b2369fd59de07157dd41a6434840c181c1f23dfb3cc673fc892adff16ec8332f4fe02dfaadc6e7d3843106a291b28f1be4949e5856d26ebea2fe6ac4e2eded1788ba74f3a5ca393ae4143d27d779aa5379d47c81f80f1179eede33f4172878e716061d0a02d263d4b4a78abdf3bd142a42d26eff04ff0b8eac810a4f18868c264a20eefbe86051b6acd44bdfc31d6f135d6a1075a69ee884d", "-12b55ce7a6429144a5971ea0353143e5827f21c0071a56e53834e76c970444599e9bb2cba5b41fe0400c6376c528bf19a671eda9893773acc28470826a16846483d1d2e822e605d2a086e7f095405600458cd59e8c752ac995800affb929e8f722d0117632308828a5e991aad20dcb15f61724c879f6f4323543a02a9904c01040c8ee56feec6503ffd2195a7b3ed0bccb4f1f8d7001beddc96ace60c044cc182aeee579a46dabbdd39e6859e50cff195159bda791b69a5e1fa5f943f94012aa434b001a6df0b1fc8079805b581", .None}, + {.Div, "-3eda2aa4b023428a22c1e3754cbf8dd87590a12747579368acb0b5d61e56b8af3401cc5555c698b63999aa8917912b021560cc33058815b6d5e6bd156aca39dad0bd79012333834b72b1cf9318b4dce8d467f3abfe7dfe2eab8c443fd7504b0d33376aff5da67a3cfe76168b37e763cf5d10b7895c0692bc8d3819802e88a9bbc0edeb4f7b028ca7107a236f6ffd634666e66a7d39fa3258e49c2ef2d2c0261a2bb656a5e0d8309e1f1102d416b40e981fc8f47eb17ebc5e975d47e89dea391e99d24c6ebc3dfb90318f47529466b374188e8b0ef506bbbe5dfa43061b8cd187b03388d133bbbc081bd7900bf1e71e08766bb1e05071077ce26638913f30dde92d9b92dac4fe5f70d43258b2046fb04ca0ebc43968f4cea90f85eab8e260bfecf8f2a084cee5efd8ca9a6db6217387a38497b6cf1ebeb879996a951cad33e631fabe8452c9967bb9e3292c379a0d2126e09b613ac14ad8a564a50afa7c92ae89974928aeab2de6c3a96fdaf27d7cb01091ab8be4b3ff6366eeda31ed10da567b314a451e201bfba12d1e6a369e46570df635a398dd4a010940b294a31f6faec148cdf5cbd5687c10884bb61e8bbfe2f0e3ebbf7913d9baf152c80c34fb196a4c8259c346dabe0933eddcc93d3e6ac9a5fa458f3bd81228d1476beb701884e3751307b03d9f20a1adc0be927158e7695f7c481be9481eae8aac3b0b57917dfdec", "34e0f4c1c85375d4d3f9bf65fbccc4dc1ba39ae9a3ef8e60a41f8459f32fc88ff228d1e0c89880599a6ccf64d61e85225e7d92e9408a133ac4acc9cfbe1569dab2c083f58f28ccc217ed295218443dc761051d1d81da774e65520fa2ea3c3dba96fd908def2205999a16b5239d9d2ee3a3cf7e5955f8fed1683b1d436b713fa2e3943cc1f67b69a282ea7c753b66ce14a46331d51c9b21576de65cda76a534017a38829872e49a68fa23e2222997bf75d407b1a1e9a453aa84a386d431386827ef8614d14d0c485f75cbb632a1b8609d26bf2cfa43b28e5eae3563daf588908297d28c79805b040eb78e665f70192395dbe20104379664036ac067d8e59004c9b003bd20e33612bd092a9ec086e7ac4466b96217ff23f8e567806e73040a487ea2294a69b441080dde51794dd233909c49a22b", "-13048c529be9d7aa3bb8b19aab6efa94f27da961a014b204a438b3f2ea572d7ac15b997252d6d6efc9443c5705e4c8c9243426a68fb72eef663bd6346879831b07182b62708e0246fb5e1850a7daf509dc8d792950f02c27f1b4c0d3f7b986578f1fd5a21f06091cdc673310853141bebb8d64bccab5bb1c4d01929c128a95ff2ea7026d15e287ed7d9c82bfdfe99e25391d5a31e4b259af33756cdcff276713f57692297e00d3dd4563a64f185c08c724aef380b689f3529d17186c57130c4c33f8bf22b71ddb02f96040cf577", .None}, + {.Div, "544fc682053d963604b9d8805d80d37d35e5847d046f35179a9265aadd51c27dceaa1f51a337659b8b155cb000bda977a3cf1a440f2f8bd993d5e17768f20a6c2f8a55ec99d8cb1de2eb85fe9b0da41bfa80adb882b7f73db1612276177fbe1da5cb2aeda4b69d508d5236ec4d7274ffbd1c232fdb768e9ce5c04e185b9581866deaf7d39f99e39b5dd5678b66967f4bedb3472f38c77edd8c0d50daa17685e7d17de6437690f7714389bedc1dd6e63e482bcf6d3f42f6d48814b5e7d1b0607e6ebb5968a21c43168a02a9fb95b77ad87e14a13c24f33a45fd194faa4a70cf4148752b1c9c1641e33118637cd1b3b443c731f74ae0bf5accf8779da9090625b2b8d49f0d1ac890ffbc2ba779482c2d9ba7845f195cdb9c6e97f0602a8daba200a41857bc0bfe5a6f11a9dd470305e95a0bb7d6fbd86e3ca12c3d98bbbf6d7520fc0cade1a089fcedeaf9387362155527f59790507f57b3d9c605ac23e0b3958744e4cb1a998adf72e4fdb4424419cf14a1792365c535fd6d4a7c8771beae1bc2956aafe0f98469099689c6c4b6aceef8ca734b94b5fb366f3fd1986b3c8a279a1bcc8461216d2d399702bd40068b13161aa46878beca7f4f08574215b982501a6669c6447167671c0055992bf6fed3ebd1080541453e7a47f8a96084246199d41bf1712c282c168bebeb92a577542ae9fece22296616af661615439ba101ba8b", "-8ef4d4507e67ad0a39a1898255691e784388f92ef47ea00f8ab69c3ab807dcf80e61df9100deac2495ff1de880747f26775c39a36d21d67944c7d597f854ca3acb826848974d67bac8d4f38d1bea600ce40a8504f51e59da7f9ae4768079257957970b4fad4b4d92461b4724b1ac5342d30b04545e955b19bb55c7b1ae8ca9f11d97a02e061c82f6e7455acf3cfe7385c6ae158264973ada99d7a3269685ad240bd998c8d1e348cb7bc92acb9489b415edef82bb0d76c271a9bf6b50fb7948f5a171f712af4d1327ed628ab55c434ca6795013568479ab77d3c10b2bd9c9558191efb695c39f32c6c905c982cb0d246f16da3127d8fb286b9e9dd0c972c7053112182d7318872eacfd4e25a6814cdd53e8a870b9196a048e6df2e87d6a2ed6e00984be6d761d0d545196268e7b609860fc6997", "-96fb47bba5b284f0ea2bb270b32edcc81f59c3c1607f96637e3e3a248ab3c66bf276ce48c5d1786730bb67c840e8b1df368275c10cb7ade080e803992725bbc0c1f877ad50be1700cc33fc44a0532ddf477843df16472e48b311193827363770d8cfe436a2b3040d99526e19d7ac14033022422faab7dcd9526ed0a96675a6b62f7145d71a1dc1ad3fba0e02431b8f49957cd52ae09602a21c2751271f6b2b4af1298b42da1a46d073f58e8926a7c857a54d2dfe80fcac41da8e40f2bddaff88a50d9398141e491e86982de1fd", .None}, + {.Div, "5e8b560b54530e6a5d6d7215a226248b22a55433e882a1fa3abf10b2006aeb38deecab682d140734cf01cde21ec13bbfde448c7c2ce8352b29384566ca806d0d9b928e254baa4b49e718565d2ca958b6f34e3d365ad0947955aac21063040885213bf5e5c47f070951ad693c53de8a6bce52b750c68f53d0312d9193384b36b7d6fda65ac4c0e9099e9e26218e427ad4f49d2103cb9f424914b5be0eb25cad736d2b07bb602d6ce0985adc9ff5faf43b50dd24b8aeb81ba43d7c31b0b5ac5593268507374708e517cf45a16517bd55ef9185b38e74bbd13f64643c665e69b34dbb56ba5f328f370dd1ddc6873224d8ebd7c250c87c050a2704885669ed923fce637e1a35c14e0ce12f1fb4ca1493da8bf5215258d2edc1389cc0c901b5d31ab856943ccfc9d7ee13a663d0a3e1f9b5525c711f868371e6629ae7d4406873c3ec61af1711b6ebab11f86570d6d41bd0f4e95b2185557d2d3c32c92165316aaf2c302eb0c20240a31c02732fd8a6f2c92d5e49fd3caef21a6ed3ccf5c8c5d6456ed132eec6e67f708d23381f1ba9d9892b3efd4ec89d1fe5d361a8c2335c7c7810874b87f62335540a7139bb5f326f8f1ef9f0d78abab795c006f3d5bd7e0116ede238fc1a26548344ad8580c53dd331b0d02ac553033f19ff0e4fd6b6d10459aeaec9c1063c9bb0e5983192e58477d22a094b04ddcbcbeb5188a23963862fcf0c", "-1a690f23d8370892fc4c0738b1e870acad2c515d7a0c0d6e830e36e0df8dde6d7d526a0f69526d3cb08072047c6fed9af3608431dd2e81b2a91233a59281c91ba66919d65cddfb43eac7efaac7678574e9ca09a713eaa67969f43c45e3719e8580e4615083af135cd74780e5c92ffcc54807d82ac25128ef26dc0fa201135c5af73e905d100789832259c6dd0a6d6cb283ecc76e7d529262a2f9f3717348733ec142d8623ac9bfd3f15f81685fb7e7d0b25acd5bc14612228b123d93b2d7e43f3784f7cb472698f45daa2c0651ded9dfe4bc9a0345a0ddd088ab78072d6aead07f661f8997168f60fb85f8b9df509e0707315fd3d3b57f467c3314ed94ec12091a6e17c7eb574ff1b266c139c30ccea0e84a43b7aaf071d21412f154ac39b1de0d582e41c2b29f024f14a435f9aae56d658cfd5", "-3946eb58a7d6ecf0cdb88c06db9c23f23870eb7ff4962ff9ff17144216e3ebb1b35f8f11c06f2b6b00827c21d5eb5de465d4db3b8b777e0204206a549081eb3a44f506917bab30f3dc2a8929c45c3891b0e024d1efc59bdcfafefaba1e8dc9c06b3172dfa9a161542be1d19bab79093e80fb9dd900cb3144dd9d723bb4186d1f6d46b64611a7e974d935501691bdf30824c3fca0c28c645608451757a1f161010e7bb32b0cabeb4867374d58d24a9e58db10d82d51bea73aab8046038e267937d4c3b7f2fab49c30cb367c9bdf", .None}, + {.Div, "907f38d443dbb91f3d2324885c2255e509343c28ff5643c211bf981fc41283e05fe7090c2bbdd52c36b1918497417875c401abf8d80800da3b035f8105e65dfdaec777d2e4b5598d45c24b81cd03733e316d55c60f17ac300a546686fcf6ee4883f90244ea22756d195fd35203e18740bd890fb71fc566975a937fee167e3eb96e392920767db670a70c6db8a238729f65cb442dbe179966f075b0623ea28620d7178e39aa3ec1226bf1aababde51063b9453ace0235f03e35eacd5f21d51f2296c86405dd06219b4a0330d58ad534ffe9d71b2be58ba87947a0d768464b852e8d132af29161d13bed6829b1899bb351982281072f576816adcab61bafe09622f673c58a8e6e03d8a67998870faa762d05ba30b45b45ad29db08639ecdde786b78d4496405487d48528015e2b0514f7a456498bbc0980ed08e4924d81c79bf87dc95e15ea5be5c935052823bc47ceb1afde5ee12993db851ec4ab2ff5a94a3266d9420135deab2790a8b8d6c01e3529f1165c9e54855da2e2a9153244c73f749e026835a8ec7e07c154d168362a12d0a716348502ff4bb9509db31f7c6f071c14bda3b4fe3b308117ca3047cf9c671043387cd376ce7f6c2081fc76fb0c0c814a97f84aebc67240e009ea06367822ff4cdfe254b5787d68c8af9461b4798d1fbe3cbeff7c8a9cb5b8b47966a2122ef2b2aca9898ce4620ea3289a021afe8b90e", "1b1b313d07ab54b3e3e7eb0dc88c172ffbd0c273dfee96b2ba36091c520ca59e0445f1a704de18a392959c8e6153be1d2379c436d059fef51f662082ca16aa3f8f34ad953eeda5cf171d43b4a205d895bffac1126b3cceca06f8fc41067cba6fb9ff8291bb54b523948ea7c87405952c8c751bd1e03b61d5b48dd7ed67e96416a8662206e18b8ad8099016cb308b95741b62d7ffaeaf2e3ec39fea8c6eb749f3e4b7f362e6dd0871f7666d535d32e1a8f9e32c71ee5226b8ef7ca4c78c426f9baee4ed854cdc2c1a63cc3c3fa8ee679dc0eb5e730bbf236651684080381aa63e8d58d2b7eb9f03fbe10e5e173d54fb6c488f66aa374df575910d4ae71680d105e105e51e60efe963b3858fd1be447906e0841a1e39bb3a29ef230395d20366b119d6d44737771ebc76874b1d4b64a4e73ec0ad7", "554ad3035fdf70a08b9c52c6ab82803519ffba2cf6755a59e5b5dd9a619d5bceb49f1945e250204127ff6f1f7a4fba5fa08fd21feccc73bfc3f655580d956a06b1f6637300b651ddcf534670b09db8ba1bab15c53fd20472e1672dad7fc86cb427148c4359d84adca2659e6344e41e773e0b384316aa127d7d8cbd26bdd689aa15c3aad9203acbb2992ffdfd911be7315b47ff9d2e8c01d307507ff52a24e731e5e1b790c359efbdcc2a7c26c9cf0f1ec23f2bbdb47c4982a04420c8b91521021dee82efbf5e996afd5752173a", .None}, + {.Div, "-f047f653523e41e9eda91f3318f2b398a09241e679c4c587ac60eaef57eeeff277251aaab748f17abc4bbc45f20caa4f79bf1fde7dec9ed54c5f878c146e66186dc763d1c2ef65ff8eb088ddbe0f8bf7a37e7276100681bb5c90562ae2be541d6f11c751bb4b1dad6f14a32be8a7ea6eebe6b293df0daf49286fa9e17d5d2b88e5b5489c8492fc2ea62ebe75d432f334cddeca59fbd0e84f7c9326ac2998af0730cf84df563a3af66ebb870f99edc9f49c320d602d67e11802cd0db8b32b1321992c41acc519e308926d8c5e57d5ac3fff1edefc6c7a75d88ec0001d6ada61152ec0f98b2862ff8335de645f370d289588490626b497b2ccbb2200d26529021439e72db9e0490da084948095778fd8a7745b990c6a0210d4a3fcc86f466dd71936de79c2c6df1ecaad8b2fa8a86f4ad339deefef7e53b27860e9d38d6828ad592ff0bf8a0d4aa702f7be62dfa3a61ae196acc0ebc258b95ae1c9c42533657058208533e86a1ec569eb5111a407ee05b9e2c75b9036eb51b7ad0eab4b579ec3105f8cd8efaee594221921b859223e82dc3a69619fe7c7e588f602cf708db4b39495decb5f8d54ed594d8b0e771d67416bbb90962b10b0fb200c884491b3b19a549654b32581b659060f76176c4ec9c2195d162a35642817a5f66c8f2720804f29453fca10cf71e2e70773e08bd78f220da02ec8d408cd7d1b8181749b7a7081e4", "-1b799a2b0cc12d506a3651f074f8dafd0be689f240c1b68c743b2e8de85d0384ac6638b6d788e1a74fcb6d272478413df2efc479d6b14f33e107ebbff1aa77e7508bf5074545e1b4f125fbfdea453d6c259fd4fcbda70078605e1a251e1b03b99a81ee3321fe8964d03522fd10d34345ef9d5bb8959b9b2d8ef11bcb45915bb69ff21a65b073c5eb2ef335687db2b1dd9f597ceb97b34f57344cf7913612f583a5ec9d1dd045dd7dc4a7b3cfbc0174ae2ad14db7fb874143aad4c074a1dae7883b8d329a998926a64bacbbd8dccfd269cb0f947ffc93591e0ddd707fc8b267e3682af5e15c26a53d603acd12e076ff92ad9bdb6601f0706509aeb477be43ac024b5e7409ed4eb5d1f29776139fcd26581ebda3c52e42219a51932e6ea3547e0118945442e35b265eae78376660d3a60b1b450cd", "8bed54e18acd26dcd03c9d3492758739dd94bf5467bdc369d302418469734b280ab6c80ca849339ba9b839e8cef4cf84f09ed0cfe2cb1e096a3594a89bf9dc3f4dd6652f86e4c094c16457e953117bbefe6aa1237b8d28135f1bd73e8ffc1b6f8f6e633c0e255aa08ae6cbfcfda0a0b4354fa949dc20ce6c6f36e737f6ad79ccbef206727f9097715f6ba93a6fc6cd3b9b341094064f7e6c916756f577bdac1d5c269bef93c67b969cbf1dbcb33849918e8a03240c38ee27426aabd08b283ad3b3446d34b26c005da9eb83c47a", .None}, + {.Div, "91edd6b0daacb91b1ec380a91443ec900a6968285f1fb5ab03c35ab3ed8798adbffdc949cc28f5aa17e1ce71063d54803b6ac772e79b581e4fd9dd89b448bebb1d1ec3bd9ac5171f27a539d7c02356719171db126856e6948d7409f461faf0ea0ffd4b53ca6665c9450f36ab20818310ab574be9cd36fb77e8ec23477a6c4347b663da497608b56077fd5753b8e69216603c81b58e6667cbe5fb1e9baf98ccc8871bffed57e754fd7eb10041a0db3b0e2c87d16cc8f6ac037d1edae371c0e28130a318e7be931221ea77584f992889de6eeb00e3ad588034aa2a555f822758ab6f21eadc654b53af81a8917713308bc159cd34f0927fd1b71314c44280a02d0944fd55082c356627c3d6b683d532fac9fcb3101bae2e0299244145da3716a0d27eb8ee9e7c8a2fec647011c49f1cc624e37e4b8fd333bab7a85af2cbd353939882c6fa2c3e1a348730d16546825248f45ab0b056e170db47b73900a71d368c04c6cd18e9bff92c8b73e61cfe1f7c11edf377b80c74db40f7bf2f750b3031dee0d603f4b5f48c527d61674b23fd67fb83c8ed63ba3d0481b5c0df5ea3651742c1297014aeaaada0b3569ae161ecc5c3ff3d6b9bd961080692fd7400e0445ae234eba47827f1f2367176f21aee056cc1a8fcf5bb37bbe67e6b59ca8bf98330d51923ac03dbe28c1bcf9e8f1c3896f9fb1a83427ef3cc4b0ec35a8ab249f788eb4e", "-f00ff2124a684797e1c944a51ed8c635c71b65166b7ca39d601737dc52fc2f336638287971c71511d0dd31e40e02d977869493d825c4f7218e952f68c24c37569ed9fdc9c69cd8f18910eea164cb72c964ba4621da6ff2f4172a9a0977b7f2c45ad8149341675b84e469d877c999e70e59b22437f430a478210a3c247e7100ec459a7bfab9f29cac98f67a9d5359559c033b61e80542e87a823ff1ec11f86be6602ba0bd877bbc432ee44ca57ff1922bc08cb312685c7c8cfdd3295ee1fe363eca33bf1ada55a89ae944c27d4139f41549c33d71926ebb545a7fedd820c525c1add8ad08a464f4f0ddbcfe92d3fd33178c4fed1e6fda633160e829eac3e64b5bf3e91a0805853c27ad7117c179faf58fbc4e84c1c1b25cb5427b20ea0ce44f56c919145058e348b1a9380458f7f27cf324f8ad", "-9b9e05a22912bb21541491363bcc475154dbc0026b26ed537714bfc7ee837da9ca4cdec28721f69b1324080c78413d2e1dad4ac06a70c6201490937cc6cd4292eb1e1320551a79c14cf57320e1314b473b775a0bc2152d1f9d9874871c7c14df84fdee177eda24d20ed21d3b95c99080dd526595706cfd57e7a9fb14073761ffec32540dbfee465b2404470961521c188f51295f2ab93e2627e9417f72c3dbcbad73e67df8d709430eb00c57c21af8a4af875cb4d7698b1b03b9c19395891e2274354ab29cb9712139ad189e75", .None}, + {.Div, "-3483cca9068584f8f80263d732df0368a662c16ec5931b3af17f015471197c9abd508cb9f30aef59633b660c10a1bba45008cf6029702f0b164fd908a5fd39c0309644abfbf9922e967c4c51b1c1e11fa15e0c16a30e4f7c19def334f849fa3205911263469da5d8d683035d4cfd37a5c7cf1d26319ea7ae3cdfe1eb85ac32975680196c9be92d6f6d396c9c3c803d121099122302ababf289bd297c64a19060cf319ed280eb2c80df1eba419e056784cc52d034b105796180e5e0d65dc4450d63bf0eaf3fade12fc319ab77b1b02d84543bbc440f5a5071c38417fbcf2d92b3a39c25d5dd06b72c09e5db042567260963c2566f2ae8c9be2dbc69e48bec9ecf1ad6c9205927ea1665656900f94b693d173cf97c2d51bc15c91e682d238f44047033e5ba76b7ade084d07b2944a01c00076ab27979a5559e22cd7e7f20e400fb104017e3fb55e90ab1503f887392ac40ce91bc6d8f90df8983c113f7eff551150b799aac484493a4697ee7b51bf5fba6cbbe1133396c52c00f42773170e94151fe463f98224210a1fcf9c3f3bc6937e7a39ec71fb1c21203849f09543c28a0ec0081fbd9c828e08253137bd0dbd551d8d2450bdd9e89dbf26c6cb3318fae8a20b9838e3d8eb670d0d9d48b6f7bedfbf149aa4c47d8f5541ddcd17a4a4875de6cf3948a87b04a414e4fe3638ff6f09dcaee9c1e52a5a2218a0959f55e49c92bbf", "-f2c3bb9dafa55a08f3871c025f144f208d503eefe5738a66d3ba6b49ac06525308760242d29ea1bbfa0deaac2b7cceeafaea28f1240d01753fdc661a8267d27417cf7c719c2985daa3b23f2cdeafb21451057e40da4f56059f587e2a550ae8bd8db49398a4b5bce2b60ce73cab7a3c3253bdb32631aa8207114cfaec78175c79b2563c88e05bc7675f721874cd22acd27a9284021794fea07dd75b1bb252391dc1f97e3b5f85a40714ee749d4c066fc026c43d76f8b09d7ac5216421f0ec501761a158d5c28cf19383e84e9b4c27d6881ed64ecd5292585b5302513ddc490e2a228d092262839a96bd3ed63b2876ba10e3e9ad3e42e55daedc35c54ef8766134c8d871746783aa9094ea142e7643677936fc4048d7b4f65a6c067ae9f22bcd86bcf12c9af648a0e13d4a7317aed1efcbf0e2fd", "3760bfdf4d294f8c48dd306db567909cf11a28e31fdcfdf75c0e5e41835d0fd51725ac5dc886be6745d458edf1b11b9adee4f7a60941befb54ce42c3d58e644d1535845456636cb4de1650b2877dbf3f3fde285225e48d7dea5fc979bbb1b8b39106f0e5ca2f7742fbd309ecbc7acc71133737b24d801e795f12719a1c8247c2040e718f0f1ba30d1281105ecbe8080fa45d0a5f384a22a9b0f4e2db2fa68cd34742e91e29c71895c76eee503f8b865f5e3a6ddf2f1b34ffc3df82fa40d0ae9e17f430f9b017accb389f789d9d", .None}, + {.Div, "-8b526b239c6379bbbdc20e8c3f3cf6c69bcfb3648436bb73f5c4b060e42cbe09a4078dd2d43431fa84b04f5e71c9b64e4a7a49c9faad4d69c811e22602d42d1060a76f92d26c998dfbb23746a7ca4221c752a285aae965fa4bb0a98038046d9c622ff074bfec0a65f6fd1245f7d37578129062002b9cddfa65126104b0a26d58495b0de483907d4bb64b62defdf784a07fbe90e774f83498d028f5f6569dbd857eacf9d9dad4d0f81c6af20752c5b0a448c11df3a57675cc261484e9982f2434c860508cc325a40e2d0f9540e92d6cc1481f7f10d49f856d44121f6c215baa8e13d747e40ef95316caf3a34094471e350c25cbd40f1090f47c2e13a0e278f1caa6e6c4d0f336cda35724a02e7cbf16e5c8a07fff2cb77a03c85d0b4c0d71a3c8500c8bf63a8e478fc5e31f769b70eed7f6298de68f321c80f12095d500b0b9a8ae8e74c0e6b4b14ae7dbd34d6fa4e3ce1b8e0922b1558cce1bd0afe9d20469ac9a0ebcc6331390d1aa8ea57e17d2ff0094c37b59f6286e4fc7d54105d370904951f37bf76ed942b9f9f3b95b932fe29d71ece74eb59a8ba41f6f3803ba00d17edf6b2a9c57e9b8334a43e651718550175afb2a5f0110e356e2a39a38409b98d57111a8229e5e64aa881ed263dc01948d629ee0957f5f8656f4efb2f754e02a5ce55ccda5602827ae90fec146bf23a66cb383fd4faa6943bafe1b7a285d7bb15a", "-6d2a37810c6713ea9fc3bb999d73bf9664068cf2282ed0707f122e22add636575357eb4cc049d4060d0b32a27105367080d1bd13322f5152e75dbc0994d9ec3c771950b76bd6ef3baced12c542d5ded0e2c661281ad772ff039e47175f21fd8ae383e7f64e266f49551c7695f0dacde7ef49c5b8e18f49e7082b10276345d04f2f025bd0114c7cec7037e07718ee406e809e151daf143eda8c72cca6442848ebb76fa9c535bee42f16ded94c1013bb9ec64b7a16d570a278e764a0421dc18f6f3fe6c2dea9fc57e76d944ca6df1289c1499db55696fbcd568cf1422bb40d19d11bf8054fa4e6df5234920cb144487b11c8a52ee4f6afcfcf8672d8a69f2c27da384ad86cc90f81a047fdf667014c8a644a7035603498876f064d6960a9e5b314d82987542ce48ef3a896e38208380c95b39884", "146b87585e00cffac6a9dd51643d1a88acc1ee3e64ea1726bd4692c55be3e23eb2971d88e7e9471299a712e03e1b5a05e55eb8779a8987e874c81bd8fd20ed6fdd7dabb1598b66a09f5bf0bc3fe772250439356e80999b7b6bc0f301e25e2969106b869f0cb26ed4e68d7129f6ffdf15e324e8165a8bebc25421e9109a567bc5c257347110650b2c5c9bdded5375b6aded635fc59a427cf5a615206eb2af0b2cc33704d94d25f4610efc17d2d3ad932bd3c7d506ac90c15f675a0ea1a30a9c9af3f1a915e1a0e1f92fb928db366", .None}, + {.Div, "3c6876e8240564380016e9d0740eb1d5465bbee2ce61d005aca631e9bf01a52368929c02de06d2da0fdd3a37653df3e32030934cce8dfd7c683201b9b18ae431998b26af87c3f646579542907235622858f6f0ce7bbf340878d6d6e160ad004fd121d8aade8f5a1196d6b175c1067c7ee87c5b39544ba650f985115421e2e2d3fb6996cab214462296966a16f0416c578963f4110869ec58228c92727dde0f4fae890a33415c6a5f107777f6be5ce6afc6862c34c9a3cedd8a8ab47297efde449f90df4c181211f49bb9749445ecb68966f69c5fd114efb3bd0147e027ffa79bd5621ff021dc821ec5280b48d9fb465fb839277a3c98c61c50f5e78a9ffa3757a8891ba3a74c5d005f4344471557a7abd0f6f5046d99e001c3b4ef35f1ff1908b9bda3ead41f981c60dd5cb606f7f31d6760b1d433fccfa5adf3cb0697b0c0e99e4d914072c1d6ba25851941d004f49ac2e0cfd8560fe0e4e6b3892705391bd37833bfed4a5751db30d5a7ffb092231a457cace1bde4e223d6b8b34004d15fa0f54426873e98620dfe34e59924139e95e87389891a6e5fe4348ed116ee7ce12d252c909e683644dbdb522bf43f4964b623e40c9e1a3b55b33ff1b6b1846576f7f7a7477df6803285a54ff63e60e2c3c0e60f33f5e1464c6b888dbb4626bf55d5fa16617dfd320833f34fbf0f00bd04f32307471dd9129e1f8f75b5aa40579b6e", "-33a8edc30bd8ad3d6585b8cdacecc68b5b1c79c4317ddbb62901b432c938ddb801c0efbde62d9ee631785f5b5f46ef84af376ebd30645bff0003d1cf9f0f8f52ee615f41be003506294d5bbc12e64735ac2a2b9ba6bb5e764986b9819c1d580908f367d38341261bb3f548898793fe28d9d423654ff19a0a9253b7f42f0f44c0adeaeba15580bb537a603b3004c95289e413e19ce4b0b281128cee2790ebc276e05369319c728b56bc7c05206e9ce4f7bd742df9a82316cc3b6f5ba0c0105a28b586cae166d9e1fe0c83d786eb0a033a4372008cebaf03ab51987179742aacd9792405f82a5b44442daa943afaeba2db63390ecce5623ca439eb4f47bf08e1dfcae1080d7a529de96c4854763eac82ced8ea0347669871c948ca438f5d2712f5600445057964e27996798b2dcd3f417a8df06", "-12b59ff1ac821aa89de8dd6ec116081b4d45430502c10046df13ddbd65b3b9b51a7e0757d84d812b23ed450bbbb5287dc407bb27d11ceb814609464a86e1433c122a1c6678e913cd1b26e315cee27be4c09bfb5736edefe6c14827f4e6ced8758dd182e97ceccaeb7dc2bb3dd7185737ba0fd6f0f691fdf9ba19d17be68d28858acc118df8b63343dd3ac58e6c5d2b7fe8be936cf15b0383c6cee0a76800131d903e8fcb9f2060877755eaf0ca7b5b99829af9264913966432085c00f86fb31e7baa6dd60edc72b87924fea025a6", .None}, + {.Div, "-394f50afee258177f0e458545d9807705aec672df33816b79a8992f71f23073df33e4aa0c78fd5c29dbf565318e775643b8df156ddd11f7fc48aa58e14fe68a30555ba38d4b03658e218d9eaeb56243650a870f3ef2b16fe2cba010ef5560ff5fcaa8fb296d1a4acae366a45acd04be0916e5944d6276f5dca1ca1580a30c03c60104f98130b30ce9aa5bff62ca07c664743d54c0137b66d8a967ff1279817d0f1eb30e90dac97f383f1ab208b11db00a7f89f2105d3c2ee327180f13a635abb8ee8646d7ba9da42e4d1fa7526180fd51d380a8fc72252b830fde54499f050a2e097b9cbc706007ec542393949251507314015e4826929aa00116f711844fa8a07de031d50420610be5e0ea9abe2efb29e842aa577f62234ad92283d03c8e95863e3ea184783a2d025ac2d2b743a7fedc84ab5d449a1bb704833739c15173c9bfcda13404ef05fc5f2810e96430a258a2571e15e26b0d496da689fcb7c50a370836ba378344508bd5b8eb617ecc34f4ce185d6642608a853e16e8337dacb695e4514d24f396b2810d1edd47ce4a013da42a567806997a384f916a8d5aff2b634347b7367f3a4487703acddf513ad7ed392484f82de4e40ac62bf5c710822de7984f3842d1b446a2bd9a0b69a3270c76aca48354d6c68c9cfb97b5a9d3f9c8d28cf90e1b3b22ce9e002ffa36971bb6c938e192d372c7003255abcc253594ad7d2", "b22aa6031e6de3fd1b91eb4aebc7aae12c1ee905b798f07fe5c37699be0e0b5dfc8f0eae7fc16777fad17704b9e5886e63be29e46e62a9cc8a357ebf1d35ab3115a3856f72d0bf57e407257e4c886650735cb97cb308ee21e1d73466e0ec9fa4fb450a660f5c89b7318d134b3fbd1f33109a84130a78c5657dc8696e9345bd7a9cbdb43b4eee1cfb6ad3142558f27a9f8085dad68471ec4eabbc3764778dafad6441dbaca456f71d1aca14dd9fd9121656a7923772292722eb85b05b6fdcd95e39986b7ebeb9e888c8df874ac87a9be89c2023ea9a02ce345de359e37923abf0b98f9a1f3107ccf0c983f788f8186e88547eed00b8a99556e92a08fa8744c650db4ceee05d3dd8582f19d4aca22f69ed69ab42ce2a526c0b5118b567683d80b0ad92d017402bd069af67d6a259e2e514779fa6", "-525896a7eeda818657719800d53a3204b2df41277d94bdf71a379cc3106af1300be5f765eb979083f394d98ccac4d20be441f42909759713ce9799761d66e06376bf5391cd32b927af2dcf6583ae516db64c821e0d5462885fa9b6b879eca9627c1a12a38fd7e69eab247fb9d974796e396800cef973d7fda4019de8ed986e0b7c90058ff293675ff16c83c3dab98656374112fba772ddc82facdc3d7d45028f2697bfe41e0b069c216fe010db1be19354b1c28bc83fcd175cb6502635e28c9b0219d0bf47a97bd52d2da29741", .None}, + {.Div, "-5652ecfb068ff542d451af195a6e5526f441ece0f609045de2c819f04b4ab101571799b36a6cd37ea74db038bd393354fc71bd8d787496cc2cd0f2e9dcaf14c50621a7d056e27f696a4e6ace7ae7f0d5f19fe86c72434d18acb44e76de553fbf615d51729226a59f4daf01a7b1cd28f04e5ddac93c0778c49466f876f59a37009d4221031fa81655c61e236f9037c8088dd9e0ce794c37cb11855dc10747fbd850fb4cfb067fbbbae032af6c311ca05fc4884ef87c3d487fc645bee78ee96c228780a12232fd3ad0d165dfe7023c5a5576d902b39523c877b0bb238d6f9fe892b7e6dd550af43c4f7bd354b8f41fa354e905fd65c74343503fe24c3205970bf63b0f8628c15a44fb96146af37476c036a3020ad2c21bc0b9d10038613d898ce73f50befe8fd35a7b2a4feb2c913e838fefd215c4628c6205539e56e950131d2b8611822fa61755e94f5ca0fc027523e42aca53b4797bcf7201143145864c9c7047760f6daab9046f74029f5d0706d7f9f9a8e254295ea1fb0e2298bab7af3a6bc8d6326433e58c44193435ec3e24ea36cd08c605481746f2cf4eb696290b53c0d388c7d0b2c27a75f8662e0ffa80c4b8abea89528795fa490226b1b931f4c4ebe0a9b25c92fb3785d0f76c9793fc28d67691efb88f53dc1956958be2cca512bf387c43e780187f449e7162603f6537434a48499bbd2a15caef7e1c385da3136c", "1b7e8950f257c0dd4f49307e5ed382c6ae5c0ef7d250dc0d1057007cb6abc09cb8b33ffe1419a3339febff9ae72a44dc34b1ce0c46aeea9ba84d163e99a196277ccdf36f23cea694f3b9c6470509d2529f2a5ef8eaa4f09ebb5cb85016b336789d0bb6b592616df15aa803d04f797e9428800197b6f7b88cbf9e55599d4055684fc3775bc1e7142b0e468fe231b4590e6fbbf26ffd5786b76805c7e360a467967c843743e4d8626d3db0b6f15cfe5c14664d70e72bdf401361ff453adf44b38f3f76d838fed59764016525b8257886fbba7182d97f22e7c1d13dda98888bdc38a7746bbebbadf6405c98969006f5c7a45a34eec8d8bf82a6742768b129f2cc028a838b3e671a2b84f892148c4e5c2345dd91be61ac6980937878c611b335214c8b6f350a8d9e561320486f25e15540ab57fa4b1", "-323c3afba6f267f291b9c48c04ac8fe1d0a77898cc5146982028524533958fd90f730ac1cfc969e5c4de3b944c331024ee18f4da2052914581e83bbbac1ce95303283b9027686fe15f023e46822e55f477c7719acd36705cfa6d3bb5586ff2275befa99699ba232023d577ed41b01f360d9175af83b954a79aa3911efd6f00060523217df686aecafc1fbb404a268ff582435456c8a0b07bfa86892a68e2f6b0b5e4965c4e352351acb7aca1276e88a2b0d0e86929670785321c925207edd3951d4c14ab77ba7aac39673bb7af", .None}, + {.Div, "63a9970a60b9936afdb44c606c8b53f127ee70fb6490385d8f2fb6ed4df7a58846e4a558cc9168e927f05fb67a15f9afd6863cec920896fd4f9eb288cd9d6930b1f5bdf3355389a52c2ff0e2b762df0e5a1ca12438c94d8ef24116ad8d9d1f46cc012e215a8f83b3a7bf079460eb69604dc8e84191c83129396281f1413dc25428df4e13206db55f24b21c13dc740e051187762f8238a7a3100bedb9e3a2f70463cd0293373ff188b411380d4ac6afe6de682699d006ebe8cb8d5499f6746f502dce9e452f856c9dffc9ec3002c80eb4ee1ecaa3f99a4e90c96d35bf5c1fb2e540491060ffda5837ede5609941e6f508f93066ce6b044f6c3eea761b5a35d3da19045dc79640e5f1a0ce114f439616616bea0ced6b527ab85e6261740385caa3855bbaeebd532873a5b5d97da8bcb9a40f51559a58d032181c1e69333df15778b332550ec1411cb3ecbbf8a6245da2ff09e37f106d851fb34259946ba53d5cac56ec818caa5c5474fd669bc125e96eb5c13181cee830df1523fa673bac446c4078d29ca39cde30e1169df4c70a33f6a2fc968b06ccfc3d3ec7df97a8c8c0087edd3e114a06478a4e77bd698c1fce39d74fbee6b2e5603ba6592fab9d1d242e77fc1a26125db70caf3e9c848881289cbbefeb3113d5bbd104796a817048c2644c0ac2f004a7ac1cd0f3ad17c16743025d53b18f15b4b18828051e0f10eb5e5d25", "-1a25258614b75920405f40e02458fe1d839c4e2f867b145e538e4cc220d4f9a4fa955f8403826b3c89ddbdaade0f46a21af201cef96c3685ff5ccccd4d6f324f71fac79e333ac8f9e05330ba73ce7a006daaa337e43f714605a43e16b5d1398d5616da3e3e5cb6cd9cad10013cfd08d5eeaa26a9a65baa3280c56d70f8abb2b4a68aa26fe574bee635f85d07e6729c6551be7aeee646faeb63ed07480b9e71089e50abe80e37b155e38b473594711c99fa4b351b937d6ee21c84c7d10f214bdcbe0d9675a5aca167270630f2b28a4b34419b974db5892c4f2d239e1aca15d6af153b7baab23906cce538edd043d500090b258fff3ec4316f7420088f4b795b82f0e4ec3b5e4508e8ff7b32b386e578b358879e3ca51ab15e93c5eadace98770245a4a28e7f1e66600fdd1e40b549d51f0520b56", "-3cfd886facb70bec83775b6e2339394a7a23664f7d25ad54dbfafc3aa18c9f733ca95490dad09d48b6f912bd9cbfadf2acf31e81b9d53dcbc202febe30be4595f919b7241f859a6271811a1b0d1ccc801a4361e40ad35d236f8b7089136173f9f81521294fa645bb53c5271b33b35a497d5259139ee82ee69a67e6fa8c18e6a7421dc282f7285e6141fbd13500642909c9f0f21a38d29b487d1789886558cc5a6f425bf1e9d27e9e2e2ba40994aa2688e347d6367058e7b8a9ece33b5c74006bedbba28cb0dcb5a9a1dca9c422", .None}, + {.Div, "21d2a8df42717b681162ce4032a6fcce1ab9c2e3b2758ee4b56417fd0f298b1fe5ca24139950bee8396561822a39c7ad9abae83fd70b75ce3281f45f584eb8f4cc6aa778bd73553bb462ab81db2d6cd25bd9a54ceb0bcfb7c4e58ae656ce3f843aa535e4b51436897b66c6273d63145a2c793dc40bb9379ce85d7a9582f1e4d65186db80a546b74f59cfdc2c8789901ddf1a8e4b1a0569b62859bb69b2d3087ba048da3e2bcb172f5b4693a40c1fabaa2e2c9a6728a2edaeaf100cb2b262121d04a25807abd634fe0d720d00f3271b20c5eb83c5a01958470a31ab40d5256a7873a9a93847990cc9989b44c006d6c3071619f2521e656def825fd62ee855e7d312cd40da18597ff1cdf342a31c4daebaf0f71dbb3b18e5df85e6fe823fdbc85d0b8c9f2f37c5449a20e6582f08ba22daaf6c0877ae5b52bedb23245ab317f50c33133d93966bbe1970975e470e8559542b4f960c0955c40e3d934042cac8a6ecb4dc63711e9c4eb09df93e277b20f981e8e17bd2bd14fa4812cb6187d4aa57fba79aed8150539f9468a026dd3968e82b3723e8c12952eb91da81d07e23636bc252c9bcdcd4dde9a01444e123944823cd73df534fcd7a6c48c5b708380f393dde3eaf0cce35fd590211b7e931219a89a54b25977dbb3d6dfb2465efd0bd374df0cfbcac8043fbbed28d8d714afa106687a2944958a9341073d20e7bc3f59ebe45", "c468e368808bc9c858207cab01bd26923d19aba178c7887a90100ceea141a6af31bb306e92912e2ef08f3d570d4d95995450d6e824e17e8554b0c91024e8debba226c9d41f3b880b72cccbc1a3b8311c309e5dd0cde2539ecf4b42b454756efab81ab72e0b3dd6247d70708e2f6fa1e329042069b8f7db0bc4245cb819118253f81cd5919075f071ae35d274ecd9a6c1a1bfc0d99df36787f84bb73509a406d7f63364f08b06000b2388d5dc35c7a4675178c4b713dc167c7642d442259094e704e4e3ac3e5ede88097b390442567cfb9f8762e75f376ef29193a42d6e3914b12a1f1d4ef110f2f812cf1fe1247b2dc7f35ee17e11e7fe220f141d8895dcb58a7da0f15d18ffdb99907aa012c11e87b15bf340ad84a5698bc94b671347ab714f955f587cb6d4b9a4db029bb513769ddff970db", "2c15ad96e252b24e8d6c45d639c27459c9c94839ceacfd968271387adfbe2890b954a87425281288bd9bc64ac22c1390c80f80192972051c74b5ce9ebd3466045129a03bdb89058882b9168580cd269ce1339b2067512687b975a689f77b2c9340c20b07467025f4ab77cf9c755374defcbae907bfbd35d2703748d0283045fdafef5104971d62bd4326bafd8240259bd362613b569af7feadaf1624c6dea6eb8c9665870f4e4dc330663d510c3a87b5249a219febbdeb470eeb6ffce312a27743acc188eb2eaad031c22ab456", .None}, + {.Div, "-d6f2d202db19c0f2bfb2492aa500fd8b1c4b8643b56dc03672330837c2d634cdf1fd4b42686ed8e230981b7158425c527847b4d6ccc9f75e2989cf6216e1bb8b09dcca00cdf7eae23f9488c069f3425e19f3951e48f3e20a0eefef1da17ee1e8f96f51da1f2c3952ff86127a2de523ee9098a3b7d1ba44e57ecdbeb682f3db0eeb5ae3521a8d82f76db342643bb9ed22fbe0e229f3f163b6abf6e5937bbce0269219c6e2e73d14921ae49bb8769d12bc46cd1acaffcdfa8b10cc375a74b4f776efab29140fcbd9a58398c06e898eff27d340394751c1c1aa6db4c12fd4d935e640b0229a62f6a35e863a8a6d062a0c54483182bee9ebde4bc6f412a22df785d05b2562baadc00441d8c85e043f38c2aa7584f62f9cd380c308d44fddce7a663d70abd9ef145b7eecb0ba3645cf83e68be7c577e1764cb3e10c42789d356b727b00f224e6e4567e7dadf0de7c03b8da9e42b6db24011452be86d6ba38f26a9d5ed86a1c2319eff5187e7da04077f913216d859eab4b4ad3de5d35810c0f8eabbd84eae1831dc92de0deb7678b59837cccebd350ffa12ae2ff14a13ea0ceeb4a48ec0f48cf54787953591d4ae5fc7e707b68b1ab0f14c17c9d1897922e84a05dbde771388567b56a904dcdded308b434cf6f93b43ae2ec15611f92d23e91b9d7ff394b9b2002143ff311fe932dc7a1cdfd666e22f15ebe92ad9fde581311f5b397", "-1a67d84464cf56b98407ddc907b6c45675a4069cd0a65c523a0a3b5ad146cdc234b68db692102d558338a9fdd8ec689a308b3a4aef7d4634cd3f392c18f501906f1b015f060681b457b9b0383a9a4ec0df4e53cebb4925583364f90ae86c232ace9090674fe48c84a250abd6ce19cc7d4fefd820c8ac15d60ed24641b822c1c3abd4f9d3eba49cecb385dca4a5aafd1ff1162757feaa38d94add74f235fe3f2e6078a3af9df5ea5317d493bacf6371186877c8399e84c44477981c8caefcc377de5535eaf92984f6c971c85d095525b8f534414c71363ed2d1299d81b9e45b2e66e157df05f2f916fe4a2a1a7ebb47d4ac26a64e5cc8a53e5967856a08a049d1ae292baee90e7b1fe30932a0d3dda3d09748fa45bcadbf3426878ae7bf231e1251019f40feaba0cefc44814e1ba64c0f529269b", "823e75d1811abbc7db9ab077ef5d477b33b0bd0b84bf4bd2d43b8d42e8c9d377ea8ac49121c41208bc929bc8f032ba09aaa3ae1d9a98491abdd71fc459a538434e85df2c4e688c811ad342bf612ab25028d175a343ca0ff4a86fed2e774af7a2a9d16a3b5158d135fb5c662f0bcf922f9095188ff18bb6b88c94f8b1e5999e34352b907af8f1afd8243296386f29d2640c8bce2f169591b92c7be38a8dff107b2f83dc996e4c6ac0a18e0fecc78a52a088d5f365f1fb3fcaf6c166e6acf43568893f993510cdb856558c4c7094", .None}, + {.Div, "-20ac7bfe9974bc87219cec86389315c73afb5220f5f25df890e27a892d355a5edbb88dfa91131c40ae245bb8c5d336dfd94289c6b3db330534a2f412a35fed5cf6d4d91dc1de9397fc5bbb424ecddb0bc44cc9be12c3f65582edd63d696f591baf2eda4b2168859b9c0e7277808c8ada338c0b33ba2154e66e7ecf8782c2494b6eb5855bddade055bc319ceb07ef8ff9b42cefdaed1c7dd051f79b13ed196ac0c368ce43c13440317049dace6a9ea2eb45510af7f91e5fad8e5c6c92f2b9e189127390d4e9c67fc6ee8c76727747ffe19f4c9ebc4ed3890e03da69f132a900a21f2481eabae0bfa2bfd0535471e277ae7436339aed7e38726fe64e3770575c7c5ef7cb1a47bea09020b45ddd262a1d1a6bf7c714e5d67c26f45dfaf461db2eb10aafe6ec735171eacec98ec62676ac5caec0a358338d5ee8dc23d8ef4aa5434cbc9eb90cf69a6f1aed1874999b8b2a4e14216eb316b1fff7acc2d58645383d050cc0a0bb290a6d831a401df34395a360d34c8eed2e84d04f321d9a313721ff6bc4bb171a3fe131e096b85eff80f01db908cc70d88cfcdc050dab70128c720e9b7a9bf529c6e81dd883798bb68b918247a92a8ca4aad6a7b71cfcd53381235ae2f3ac9a350c240059cef0f7c717047bd73d0e34f3b2159f37a7d76f1dd3ba0389c6f8189c0a7e2f8cd01de34a06464d111c0fbfade670f6a97692e433f21700fb", "164dcc59fa7a68382972ba8cf98d687b6b280ceb3373def09646fae18df359f23f3e276df3dc8e9186e7ddbd825306b6cee89b442284aad9b76f895f6199be53678f0d340752e6df240fe80b88db787414a3b87204f755575443f2fb76d23c45cb370bc4b516c70c4f53a81cc21209c037e6ea4fcdf408b372056128b66a2018a9abeac78f8a6c0e1f006166b2abc668f554b4ba1fff698c18000cea82d75cd87c17d5aeb5148c9efb18544226914b49184ed3fdda6a3adde456b6456933c123f3d066884a90fd9ad8ba6f26a9757d0766c7274987e3b735bd1923339cac6949f13855360751dd2afa8eb2258f8135e6895eed8808371943dea7c88966d4abc383a1fd4f6272488cbc7081b6543f13eeb743d81e44afb8d02b312a065dccdc625efe45fd9932f310f1f65ba54d25b9415731a58", "-17705fe070a631bcc160961eda0e9f970e6ddaee87f4dd11560de1dd7db141610923a0aee52043c4884a162dcd0f69d681e8c2404fcaab60e8dc0af3683bd32bab56d96ca8bdb7c92392d7658994dd373dd18a41ce4328695abcd41c960d3a26a0ad1473778df58410f710b421ae345a002dbbaf0ca23236af89e18683fe7cc90181bfd9b3f9e2b01f2a8f474ec0c7215d26749aaf70febce3a9dccf86ff905f92c19f383ec93369610cd4ddd544c1f908da02559b6ed3846c53b98d6028f3005a873b542d7664406e845355b0", .None}, + {.Div, "6b5615533c3c548cfdbe78814dbf54863e313032073379b513d69ef9af20fe0fce878c2abe7a6228f60eb5185421d171c23c0224b4d81c603149547f32d7d30c84abeb48a4422806a4970767c20543e4b32f6da7ae7ac1ae2197ee25cf08f574085c4a39560d0d97c57f06aa981cbe4a45442709e10b1f353f567e9d0e7dc29473bc04209e50698b581892274a454df67d3b62ceff2eef44af506c785a2f19f5bc46fca44147b0f124012995ecfe5b3c222759da912e10807820fe5d44e7ea3eafb0e8212ee4275e625b554710eaf2ada117e636c9e0ca376feadc01d7eab9d50403572347e36c423305cf8745afbc0dc845acb40c5f353737745f9f724927913a0753cb901bd99b431e12facb0ecfc7d6afcb53b8bec71a093dbc454e6cfdf21a78d1f393e476e41f370a68bd5e38461ce2bf93702fa792e09bab9e9e88104cf4654c2ddb7ec9711472795f8b19ceafaf34f9e3f1ff61e847081e9ed66455805379f528a8ec29807d852f44ae8bd145fcc4e286ace738bfd5b94e7f9c7effabe21f043950da2cadc276558b0b9b947eb25d0563569a79ea3cb70fd120989b84284e5f26e2dafe105fd8a86e4a33ff4c22eef1681efa51f63a52bbda347f5cc8349b1aab66f77b13905b403d2565779c336e6e62ba15973e2fd9507d9d0f08d9f49730654753a6a72263a5827d194b7a06bacde50acaeba7c4b677ad4b1e481c", "-1547000376113557679c2184b980699d73ac175707b8601a310ec5801930e713e5b2e545b51d7e1f9bf36b0796722e41ca31a91710aec4983e04bf02304e5da11b379e66709622ecfa49b97c7a3ab08dd3e97c8f5d4bf35930b86dafdd7d983a2d49d6fcbe9241ce70a56948ceee83761f6cc9a41531e692e6eeeca11984731dcb8edad7918be7d8031390e18d9eb97e591e8827aaaa141174dd1d7fa91be544465f0e216e7d8c85a5e146529e62bbed430e732f394612ca26d6ad361ffc7dfa06ab3f0f8a8c0c46068d69410a0d50cab76ab78b8e44388ba2730e18bd2353377b6891d23406d6c08a0f720ce6aabd97c5e170d51deb8e452ff36f6cef5f70e07ef3e15c7baccfa300e40446fff732e0174569c4499dec6aca681db9a400fd20cd7763f82e96b1fea3b965ea4f87cfc0160da8f", "-50b6cac18ed08350e1f8129b255140647a63745f4343273d5d0bb5f9426b769c7c44b8a44671352e643c490bf55014fbb9711b33b2dc7409bef006ae207e989451274cf9d5c4dec89008efe537ec07cae8c6fd69214905eaa34ba1b1eed5e44e5396685f83ed23dd99935ef07651aee071bfa08d5206d93d42b683cdcc992f63378eeb3d29c03fda6f62e6230b9563f9f1107b59bb52140309e7f2f5cb190710a093fe1b198edd4c862075e48b309a020bdd73550b7cc2020647c93eefbbcb1789c9fe8bd0dea518435b6afeaa", .None}, + {.Div, "ecf864049f238325832dd3fddcf6e6784641cd2568450c29d3def1240746bff615efd413fd331befa82576edd5ce05459e04930ff8937fa261ef7e1561726b0a5735a830cae27b0aa323750e11346fc5e6b8fa5233c35795019ed7ecde77a7514ff67cf98b9907099a423cad187dff40adbf953df7e77cde7141f07ec6ea2f6d4c22125b1e796b01e50dee122a76f3ad0d080af0f21b807c926b42b59c9c23b71b8ec6672c3ac921da8b211f25733d52c0c76e37da20a6d26a8003fad1bd7cf0f5854939d5d5970f55191090b28bd42bc95b4d737f0227aa0c560f17068499b571b5be196f9bd0ab92468a959e8b1059e3a8da2215566f8a921009c1ebac1c350c3e997fbff723b4ffd28185969e7d3e9ff672561ede229bfaec1ed48f3c2f5afc2009c01489276c8250edc54eeb4cb3646f8325f36dd745d4a9c9c2dfbd4882aa0b8f01bb38bbdd6d63ca5925b29d65ebbdba4058eedc1dd63567dd83eb396c43ac5666c40273b41dc7957a227d26d312c88e218a34b3e6f78f7abf193c61ce32d25d9fe27b1e7fb131657854a0b6235a031865f514429e59abc597bb310f3ca4a3ac62a30f8d4eb11f95b500cd8291d470ec29d67af3b7c5f35b35ada84c9b866653485b9f91b3944a24b17041f1825fed5f4db911d298e893d87e4ef121f56c99d4e23e4cd7b95ac799e345823b4d98735c60668e27e48c1c2663e6eebdb2", "1738b6f2b5c7887c669848615b5f6265f9255e0680199e31af165f9bad5960584bc43c3afa5ca3b9f647bf92431e108a7f3ba6b83790d20a4a73907ea37f7519d2b38f879d7a7d32b57effe93490990a5a1f1c3bc594113ff7928935f4e4eb4d237fe4a8dd55a962f2b8423c46eda75679f32e2470b1173c864f1783e7deb296f3552f411a32c17d46aa8ec2aa5beb0e5cfca446f34963f9e1c1ac9779d342070cca0171ec5c8e1728b17c7a1a3ae2f38fd89200421d6a40a83d72a8f230a5ab9f3f286177ef947c5ceebf610f6bb2d29f99df0c27d0e8e7f92ab8ff4947d060cce461182209b8d0bc0ff4dc82104f647fe26e5bcf8a58fba5732236d51058b333b3eea1996df92395018b102523b97c11a52824067327cb88d6a6c665b04a988bf15e4902db622573028b425e647f7e9aea5bd", "a346b337e48eb15c7b02276441d579682a0e5cc11e1b7487dd449e6ba0376836a8410c32f0e2c5322fd281925dcab20d0a89bfb288e5227f77eef9d3b15105e6479741c552dce04b17ce5ecf083a090f1b1f7ebc5b0d166b6836f56b6a822fd29df2f28c99abbce43fa35b36611bdb6680f32fe1ca18ff3c925b20967e6d9b1a5ed658249500c5d8cacc28e9a2e4063989b7e8a04c81067c1d163bd3b1d9f28e3015fef34218c8459e9c0f42f604de97e41142794e7b30ce96e9fc5f1ab55ac4ba016d70f115aa443873e8d38e", .None}, + {.Div, "84a78b22e8bbdf05811f3d4ee5e1626e54ec4d887ff610161e74a9181bf4f795db3b48f4bc0a04416fab44de08f3b5f36f492d0c3c9dfdd03f700706f704121d3bda967173d7110971b7347967ead9b01037b25d16719acab45553cde8317337be2878ce0ade5f2ea63b7adfe85e38163a6cfd454058d62b13a3aeccb0667f1f98cafb57733feb382fb83b25a9b3fdf38038ec5ea8012843a0941b09c755774fbb98f6848085041aeefa430b54e3087822d63796a5169500c0c28ff0732e409a5fa7467d600acca4d25e4201811b77ce1a8d3f78e6b82a8c6150eff4efda7b5f4e01f688c34e8d68d31d4e8927c6a2dcadaa92be91b7ee0d918bfdd3db8272962f6b9bf0812a65c8c741d498eb958cd1debdd911df3e63b054a99331aac0f75da4a94152b9bb631f0416320105f3cf32feb4093dd79a4e21d3570b4fb2b973acdb1689bd348f28a275c01d8c0bc0fc33145e1ff212a35081027f3a4328db08512dcaa0386229b3643984e618d940e9251899d32727a4168d172c1ceafc3c1f9e36306debf2f7cc89a43bbedd15a97b29522b4e25fa69eaf6fa6cf6c7fcb7b7af216a9402f2a5c1a89a93f3d3d0728fdc3e633bbb5dfafd3646d8d6292d7cc8729903ca4b591e08d6adc4a7eb8e0bdb3a70635ae652ebb0819e4f77f224facc9dcda6cdbc646a449c3ed3345432deaf4183b7b733e1de0c5e70b08c9c43c4fde4", "116ba4107e942b4bdad44c3949837b06281eaa032d94d59dc767db825f1659131ce65a8bda1350386bd9e81692dc8b09b6712c086b47b875e2d0cf42cc21f0059c34fb20cdb44ded041376a6f2068183ca7e968a07040f07888911dc0bd9f3013565877970f71fbf2870721a93c5cbf7a022d3bc949485db2177a7f817a83c7e1f3cf848abd74ef76026f09247d21a4b2de611731f67a0475e7d5fcb668b13a1b0dc5a4d0bb7ce730b6f44eb37db35056a69fb603206c8db14f9c61260378c1325ebdb24a8d2cc7bb3b64cb914d590f9e1d2319eaea27182dab2c14fbac2b6ddf62d0a68b6857548866204358d2ca70299cebafd93b649f8ea4cc83306e08bd4700f51cd4bbd096a098d990e17d88582b25627b9260f4f8fbd71f32815f9da5a4911fc72959ba1c1b475c1e4527aa32198c367e", "79d6780b7b6cb53d1f8287b7d750ac8718d14d2cbb7ad9c92bd1b5af29f8fa44ffae4beecc51f2469401f29319a7dfd63af39665e97a5a1654dd7a34da5f77254a8c88351cd12ade2e783f47dab66931bff5276ba3d5124fa90ad6c0943d3142dbb45c92b05e6a4feee9c15ca53e0065daf079327ee7c7555b73a86b7935126e90fd8759c79492e8bcb853c1836c4fb3823c25d82afbbe79d8a51c7d6c2d831fbab68c20ac392dfcc69e4497ab7414bf6aeecf14c4ade8addaaa4dd2cea6a8532d6446ff9bcac27d841c51cd33", .None}, + {.Div, "-119c98aba545db12841e3d73c34f0c7aca1c98dcbb6c509abc256f8fcc8afc8783c6e310eea0763a5fb409f75116f647673397d74cfefd458ce2dbc93e6ea2b52a1f723a6b8030c2a4b0f45f9803b7cb14de4100dda50e63ecd3d8fbd6f99a6828672ae404baec7a8bf4367857ea1892fa1b140b0653ca891093100a1bafe05306e2990243ac738bed8f3615c25789f1f4247568650d207c66a1b0578a8a82e79e091aeee2da7c29d507baa7dafca0ae491646b09f77712c7d744189cbe78ca3a3553502a8c6d90fb7ffb068eefb69fdbec0b7a410cb343e404cd4aec46de7a71b28ce351ca93f487f4b7404e72c98542011b21b80ff5797830fdb38c641c345496dc4d46d64d1267e5253e7195cd71a3f443632f34fff6cd77c9f8f8d63cfe7586096ed95cf240c129d0657cabc5af97b279eefa6a46f8d67e6509fe86e27abeb7358de67dac05234c34895c539aa6e3d5fc64744005617ff2d77ceaa5d9cd9965e3152ef8b2c3813954d46c809b4725d548ff526593ca84b49f59954dd0db7b7657864a4dd0aab43a00d0aaca03d84fa724afddd2710f695f1c3ce26e35265d8ca6bf191662c164a1cd4b88da0a411df1a60ea2e5e0c2091ccaa63851b8ec70f3f71c707f99c176b4a5d155c1511d3dce31fe3ce44671021c922824439b31df8f7f9a773f0e9fe167f6ae02d0e2fb00101110ff9404af52b8a1c585931c068", "9979afe4445effdc71e4ad010480a08eb94d66a14be88411e3038293ce635413374f5fc157176e3bc71b040dcad748aaf37111f463ffb00e2eb7c17653a07174595a629ffa0a1ecad6b9ce7ec0f0d08616a341d4f6d408b8fd8af492a92b46d9cf6934beb9511f10630abe19d3444c583d3ff9246166510f299c46678efa8eeddba44052d37ce3ee8237d448163a56c09e7c273d0f7f0d57624a6efac67bb043a0354de9667c29e492877e0b0d439da0f2d7762e342bc3361a84e0cefd7e191cc5c205fe905cc39f1396893995deba46e4bf090d06717c091f8bf732c548128e842d85cac4a39df493002dc2016fcf101ccb337e2139e8347f64c19dfdcddd59e8fea555f3e08ff9244191c46d974c81bcda492c1e62ff97722252e3e772f9f03d96048b88c6f51a5109f44a8f6924fe4b0a88", "-1d606e46f55318d27b3b8dc88509eec3e8cb4a54edf53f68528017d6477bc3aaacab9360feacac1623e263d9b915861731c769d8e145817c2252606b264bdee4680024df13c67f46dc3aace225f5df40f232fcb75be5f346954e895ca2186333c6a0a42258bd11ddf120b2defc5130f14fd0edcf80c4c63866f918c8506525f1b22b35bbd93a489a3f4197da3967539e985d51f3c2e90170b3a9c2af4b02b3fb49f0edcc7c5c16f58e591a6aa341fdba7997621dc2e0757cafaff16ac5f8403e2ecb016ada6a062c5c7a410903", .None}, + {.Div, "-58d292704c3eb657d41c3162b302f2e78671089d70053511205f5f4e3a72ba962a02eec1d1c815ff62419fabd9c136dec87cca1110193dd79db9921378b72897fdfe7c5e36b5b58fa18c7a30e69c89da74931e6cdd0983f2c6c21f0ded298b5c613d84e2bcdfb515cac46bc6f350206813fe588d114892ec70b75e7af55ff64d792d4aab1a949625409534f32dd4807358e0d13b818811cee8596de45a7331960c5ec334d5cca14fefe2d85a2fda239b6a3b180d9d566c5b42304b2415e1859841f46fae27db04351333b047010aafd79b23bc507af3ec3c27f77c4dff30d60281b9d6e3f89084f7ac8fc722b4b37d5d840be7ee9d6a6dddde1daceb51f31aa15a69b8c35952091b9852d1ea861be2bd4192b679b859f5e35ccc89c2b70884597db83dab673e98c9f49c75999757830d0ba32125d6d6d4181ae3be29acf076c303729062f3cec58f3b76f68b51dede888378294ecd77f0001f26e307df1c153577e43798557a689e8b64d8ff7cb9d4c688475694aa6838226ce38208c15fd56900054d491ea08b118f54648e42a43f74081ebfcfcaf524d3dffde5693453538beb471cfd7d95d4406bafcf5c24154e9e956af92eb95a10139d12edb553b469c6a2a795ae2f0993b1e0a265f2008f4058f2e8837b61a5f9e34380e6f5d7e2cc59f1b59472ed84ee56d130bbcd104bbe503d3d54d9baf5fd3b6d683fbc5ea03864", "1e75b955b0fbfccbe3f432946e7350d1a93947ae1fd42b4f971546242f165a70ec008d0725408eb10b1dde98918c32d0ae208bcd8b89381cde9f889c1707afdab6ee5a257f5fe4bc66edcba121a7eb6a10654cdbeac8638c5eebcc872b435d727dd63ac922cd05dc611717741c2844fead07ba30367137d2c628040c3e5d45cf59373da292f305320abdc35e27d6221e7f2449d74248131774a9009baedf63611bc60c453f43b7a1286aa08c93a7e11d7bc8406d18ec26659db2acc270850a14698e9b756d2dca52e68db2a74093136a0200b94ee2278068c00e132c571d8fb5d7b1a5af6e82e8e8b1e591143a0176ab4513f0479ddefc180b78e07ed9cf2157fc3a8a6b975a33f426246639ea593f9f77fd93b33c22a1cd42cf61ef1e3233278969c9e4aa2c760b597b3c469ef2b979c0ef78d", "-2ea8269ba7954be407c2d5beccaebf83d19f446a15b9a5c8723f70c11d5556e5a66982243d595a4587708f190e9a57edd8af626f272d5f7a0b3498d7b1bca59dfcf036745a1bd36fc0de9ec07084da627c1f1741fab42940b59dd70d1a2d49a8801d4ba65b05b1f5fb228ac912d06d1f769956facbc3cc92896704f0a6fbdd6e3b14788914421c09e1a19e0ee2763cb7ddc82fdd3f5a8700e84017000de0f376b0d716033c8981fb574d5343ea674313db20b3003f073e680078c58d3046f2862b87e98e3eb0bc35fe1d076353", .None}, + {.Div, "-d5eed8b70534895bf5234ca0d799c15a8ecd571dc13873120a051b56e23573af79eb2d02e6a3904ecf6035e1cba3056eb5161f6590d198bc4eb325b1284395efdb175155eaab9cfc6e35c0cfada6bd57d0b0a1f909f3de45197cb94f392c411051d75db7431a23229ea05317219249d707d3269d0be02702627eea563e0ab2a576927a99ee394b1983953e21bd54e70283a9063899334fe8ca2acd562e0ea1771cf3b5bce41e54632a3d99b8e0d6c3a0cd15e732f31cbd0dc1ad5d7bb74e02789923d9a6f19fdc1e970eca3c8b2ec9733c2d0d9c4e8a800d315615d72d5adf6bfff5a5d426b70d09ddc7aed29ae24f76b5873eb398a811f5dd776b5d6dd0bb887524d773f968df76f7fc799aae27c458132bf16299b96339a2080a6e4bd5658ca02791f7ea1cb76b572ee0ff53d5075edc58cf4c7e756894ebea62439758e4dc438ef4ed5748f7b8278dd14a3fdb770f53ee131c5735136ae86cb3c4b96af71dcce413c9798864cbdb537baca9a62aab28c050b3b31d158bcb8b09372808bc0017f3a30fcbfb051ad95bc9b8c706d6841c36d7ba5dbfd4ef5598f782917ae3034008bbc5033c75c3783ebb5f8e1d17e6d403b3b7f5b02be031deec841abb11dd418e73c76ea7b50bcaf14e162ea2041b8c082b77cd9a3d5b42443281da1f2bf3e8ddd5d5e57efe78e3028697d04a64f9ccab0b91015fc0207beda5d3ea31985d", "1ae3ae2ed987bbd5363263e1a16091624e6215c8ff073ffa1ea513c0fca4f319f746e547f0ebbe34d07893562203ead9bb591c516c100f68e77a246c3fc2e0c5f475b1fcdf2f8fc9fefba8962b469f4227008abe18a6c849dc4eb80084c439078dbb3dade39e4164cf46c690963ab8093add567b538940ffab1724f8da182da9bf821d92b1a364d6c65be6648033cd460d732595cea6dd4b28374da506879527790296dc28220ff7d977b8dec0ea6fd6638aebef28a03346f7e389f30f18da116546cc886bbe9ebcae90cf8505507a0834458f8d02aa7375bf67a804433c26713a8d54b30050bf8033bd154a6ff9bf0703219e8a134536986762ef9f4dc826ea7d52f958f18de4d088d4c84d90518394d69faf369dd50b62fb30906ce3cec95752bd5b419dec382c98b87c02278e0bcf5933263", "-7f4bf21bf7aa40d08122256fb24de1719e2444fb9b0d990d643ba56369f76f11265805d57dfa6f19dd70e50f48f13e5a20601c79641fc27dfe98f9ca43f843b970be15d9b92f81a294ea642f99867713954f477cca82c8954f5d6e0a668ffd6b833f53533a9d2d52463de87294f0957b00381a7d562a77a9aacd5e86cde65a917b05b24f1d5ba84701c4c483bf0f89bb25037417020d5ce0986965b0d366bb3323e5106194a3653b7ca794c4ea748fcfd9e609f4426df17dfacf061cd952ebbe3d41706430b83040728a791d4a", .None}, + {.Div, "915f0ea3706b1d84590b58ed667d86e639840da0218d77e18e33925a5a29669e847a464efeb9ee6664ac7f7a1bb63b7f95cd19352158e625a55b6d4c77848e7fcfdfc866100183b7f35b7efcfdb586fc0d4f46d6450ccd5caffb21e17f0bb410bffaa6964a7add3f0f81469f739045437efc22a265cb7af5ccb0dd8c8d66ad5b3b62f244a9e47864ad5c6509f2f9f69ca1f6e6bd3e0ca2141b807f4ff4583f9d7497e0758fa09649342a6b0e1f003397558e722adccc2498cfa12e37d5b3d658dafb71d41ed6e3790dd2cb8647e49b44f949e3f9e4512568a9773bd3b6af9d075431d45e4045965b32f3b2e31ddd0b9399c607050d0f1d268181d13bc19b97e1948bdfbecc1404f970e9c0c1e5800d170c9f2fb8c6d8ad47ca40eb6c50e2b81db90c7b7aabd149f4a176ce6e07a72aaebaed1b48f8ef5d9ce154e8b712315f0e609809f931325f3d233749f3ae420144552bbb31b39698d7fb279e750bbc39f56086fcf5762a7fa45cfa7ef0f96969acb1b01472db951976d47b4664e84f9f4b7f6bc7cdd274b08b469253dcdb74f55950d981834dfd32d8038a5a89daf31218add3acbf5c0873df9e332b47f0029ac9b187106782a11c086e520d1b29233d989b070c0807fbb194fd5c8bddcaf12fd0a1ff5ef43dec00ecab121cf05a71d4715c47d17b14d7452bbaa30a90e11c9257c95d4c51d373bfcb7f1542f152e51211", "-134d7b83d38510523b4d93b780aa750827f6f733a034e8b223e0fec6ded130baf1a369c3aaf204629ba474c8b2a60b3eeec6a72c0457ce0c8f160c90331d8e3dd8f6ca2e49ce54e00b1602562f26db04df2919194f22a6637cf96e6b395b525e20fc84f4d530a6d102358fbcc8ec815d58c563fca993024c7b44a35ee743409d8310c3cdf531defce97db6fed78791b94b461c97e0d37e2d817b358529b251ba653ad41142cfe469bfe1089bc1990d94af2a883b45dc0a4cbfb27045ddf2f4db339b22d110c202bf556fb8246d614a68af83e8f820a045cdf8e5206a078f8d97934ea6ad749a4406165428e97d9f36e8e21f56c6bb900b9ee5daa2ebc061d7f3b8ccc23375b9ded3934d7f35e65437d015d69f324ffffc60a552e35ab618fd722f906c4a3c2fdec486d40f99c3f6520bfa410b7", "-787f998fbeadbaf3494d85a6393046a9009586d1379a3635e86c4bb0ae03c5a71846748c27d951ae845ffc56b9476cacf57c8d21d40801273cfeb90c0b3b029788ba38e9306397ce04fbcc4bbc724ac9d4175249bdbc188ba9cd92de9a126763f216fc3757a0debba0c36a6909ead85b1ec73c32a571b7e7c9d5552f4837342eebd435007fd13fe498baeea0efc229e56eb116f0bc1198d2f791ce0758908a57fb9c1d650a47d79ba140ab60ba28e53f3df157db5bd169d30235ecc16661e7da0b862f3f0900e8d3480e7d2322", .None}, + {.Div, "-abfb8f17991b3f14645d5118112e3b2e1ccc4b0f9d75676d295ce2bcac859cad2ed4909adc59841c76f18f0266341f76d506e6f31b01b5dae1ffd1ab7026f5b55203f52c174633f427625ac8924a03465064250acab48e311ee17d1bf4465be7cfc3205329cd28c2f608750fa9135f77cad272ca7033578604249fc293b26f5bd14a9f41e17156b874ef3c1b44921324793a0f37a1530d5b715e2ff1cc866d0ab967fd670d1dc57f8611cecea09411d6fbf35ada287b7965fa2358119f2ccf0fe9f1fa862388ebaeb78d5735114a03c906e1f78e2f82a4815c878369bb746df4829879268d103769b47eddd78327242114dc3f8bc7e42dd450e66ca7b6bfd71d3d867592d6b1ee4c95d14c4b3ebee1744ae3eddddf52b321c032ce6622abab62d9936ab8a0a9e250d5bac3de8ffbe2ad034e7ed1ddcc66590a94f61562fcf71bb719446eb1688b23a910ba430403f460628618b06e5eadf419d4e856c14a4966a7912c0e5c09f2e59519e43a2d0b6b5e10f5016dfde45dc0e9366c2aabad6fb20d0a555d6bf55fca7362b46193c0239e9cb6d5baca0fd3b089350ca703ec0a5b94a32ece5bb1bc24c79ba0027235b1666bd85c4fea409b5f4ad08d2cab6f37251086543cea741cf4375731d7a566b4702b650a1768dc1a32c301bff589b2d9a51cbcda80d459a9116566da81de8da19df189e573b6f4f952fc8b4036e2e1ec01", "11c7f36ca1fa27fa94b7cbc7ae459956a5de0e56ad1c43ceb5d0ce34923fe5bb6d4e0d97583ecb004236270aea09aea86ebcbf62ea0599341b578b808645652450adab4eb419d8a40b24077dcb020bf99ff93dc7611705ac82dc7bdd9cd355ef43400107c738057968464e896ed0b0ee162aebe00f5adf3808948b0fbf89215c05c7b44caa7d3ecdeb2475f26ded35e85701a4bfa180c98e8fdbefa0a1fecd8ff8a9fb72242e75d95f7be30a51b13cd984bd9a8d931cab5910cb9e46df3cb727fe2e01c6692d6ead27f8597364e36eaf796519c9ed14bf60819163741cf3ac443dc5a2c7b7578a64aa38fc957b233e362c0c3ef3499656ff8b7b0bb092fadc46a13713644a201009db0e3943b607db249a64062682e3b739966a6862f217012761c142ad460aa48f8e2da878c7c07b3608c8707", "-9ac17e2df8aed47ab5acfcc513e6f64de727d0e76a57d79dc4a92dc31cf0af410d5e49907088e76218f64172105aef6ac3c0959a95659395299be5045ba82f8f21f99840ac77dc1e842ceb9eeac6ab91c2a59216c02905e21be8a0223ae63755138506d396ca4dd819bf522c06087baf3eae885c5715c5e0f3c3866355541d3f8a14078bb4d22a5d1b994dcc416e753e00aaa1869e7bc758760f4911d0f0108f2f11843be5eb47090c846fe06c829efe1eabf70fd1fd4e9baa6c5f832296dea9676224538002d1dc9d70cd5ca8", .None}, + {.Div, "da43ba10fed9be304db1b70c3231202a4803455777c1cb9dcf35cc55ca0c197c7c0a6a6b08d1fef425954e2dc1a323687470034aa46fa96031b87fc771ac6a945e9206ff3302120d4a0eadf3c67e73890ce91a513fd035cf4e62ee70d15f0bb82c9a43015fd8ed9875c195691e9c9c55d76762d5b0c142a0ed02097e3966f2f35c48dd8f52c8dca8f1a5a81bd98957f5c1a8d660afe9c2a8192c1c09c39e180d6ac275276ecae959e687829504398594cefa7db2204a1ae302c5b2abc20b87fdcb23f63fa185813ed7a8012dcc7e87dd4ade40388c52d71ba2c300322e0d3d59315ab74a76da8c54fb14c31e846205555ad7e93f0b2ee34b0260985088c94a401919993132e2ba21cf1980ea2fc5f13acbc7f7f7e218fdaa183267ffa3c53e686b6b415dc9fae8f8421c71007bad4f925bf32bd67008233408c53e5ae79650fbdaebc657fd590a2f3f1f92f572a380777b0e568a35c2003e901a08d1f661e00f6a297b3f6352aaa83dfcb02f6fbdcca67a2d59839947bf128b67586558660225a673ac741164ea66050cd3faf534bbd247f108c64a2859c880907472a854d8e455368b503a20bf18620c2fd6a08a8e5a459d24108f930dc7d9de2aaf599aa42f3868f80ca4057a5a8a559c6b9646aae7b7faa01d1b5e65ecbc04cb235fb15cf31ee878a263c598d15e4db6125093fd471bbe8ff5c900d41dd02a1334f4f578fd", "-1b83e48032af0cd68803276dc53c70616d2e485d7ba440ef18eeaf2756ac4dad2d96ca89059ef480945875c8389b29d0f452a0c05dd001c6d628a3f7f82758a6ad30a93aa2e3794ff3d10c8fc4a6818e99f87a3f61f436940ea95eeed430bc1a73049d83c54afd1cc015e476eb67cea75147348439125702285a18f514073ab40fa0a8778ba17d050dbdbd306d223e861fa9bc8c4083a93454d580504f0b21756384b012903762e5aa954eba4c34bf73215ba4f1030bcae81ee83514bb50cd5b35ca5a9183a2010914f85680c88da8e0183b72a756b90606986ac42c106a04cd9a87108374b4e0e5c3e6df38195bcb4357b5074168fee181ca6545cc9cf65d8d14a74393cbb9a0b22d717ef35562863da11904106b11a84d1a18014f62f0d9436b7d30bf229e1495fc765747c48cf4dc349392f", "-7eeb8c671525ca9402b2ffc2f0c00535c7bd5bd0e03aed27b23b5df9dd584651474e2fde5c26a847da0439236354c013be8e8821e21541aebcd7a002dd2641153c3f1ef1d630d0a75e4586fa593e04f3747359337cdd421537c573854403aaa0cdd4cd9623b4b66eb2b23ca57f6b410784bf071fc8d43e9e30c42500214ce49f02ab0ab4f2c5b096f53ea34d830e37bf8f5a62b22ec6d48ffab671d5fb1917723d548fa129aec6f0d2496cfbbbe098edf15c0584b6f104386f51e7d68e5f9d081378a5d4e6c12777266b9a5e80", .None}, + {.Div, "-acdf1e1514f2b42838b5a575615d7d3a99c9335737e65a2ed10a6d4730c05846999a2688c22035c488cd8b89ab50fc192f8c9851695d1a9746e0f581dfa1810c7b33d75f9bf10ec1a0a97aa7c121e27c024d1fb601029a0d50c51d9bc4ffd1b3e4f23fff4ea1b2545972fc810a7908297ac540faa77af154b93b343fe553a834678d084c6b46dff640a439e1e44bbcd53af502c102d3083b4ea7ab354e54bb94df15df07fafff18e7cb7277e0b8dc449c004c46c0768a5e21d6906f97387decff4a84c5b162544892b27774bb7f5ceed887599d111b4e285626f06fae43a032f8980ef87ff966630524073ba47a492a1c946a2610c661b00f9b249d043550e9fb7bfa095d94b4fdde2ef0caf1793f96c19b9b7b1622dc090fdb9d3d87a29635ec49a1e5c6cc89262ad9845e9fb3b62af9d5b202ce92b6f537739aec92b732c4ecd5677f4a7f511d5644da4090ec611b17344db86751a05a8e71e6dcf4c73406909d5facc9c5cf17280718414febf130b114f945210556da41c11aa51fdaa3ee92b191722ee0803fc416453b701dc03eef824689c2776b27308f314e203daa3e0e4e777f556d6341cdd99a0f9c1d67be12f551f30df5ea45faaffd951009e97b2ad55b7e5f34ec8c375073a8f9932f0369a9b066bb55efc9825b23f8ec050e2fe6a0733753ae3c6c636addd492abe48ac0c3470da539c82584159e3c4d69acae0", "1bbbc5b6d62ec7b19c87b08a75fac3e77e1b9dc28b3c385289006cf29241e8771ecf905a23281e2f3f8b05127db3531b8a763847fef8b9323314174f782f6d4330db315a7a4ce01d74ecc0fb9b0a7f13914ff4094c3696e3812d99f00207c95878bc11cf5d51c8e227abc4eb1af9794bc851b6ac497a16506da46d5a350c0facbadd5758efaf1aa41481befb72e7bd07d055a6e24ba0043bfdefac380f7a1943ab60fce3913be2794b788ea4236ea6d54fb925c28c821dcb3661f676c333606fa5cb2ae75cb2f20e78f10b6948ed4d1b14e383280a811fb48f03d07062f4b24201f432b59bf14fdfaaf86e5fca6dfba8f6b41321352812c88a73c28e94d88d4038dc7b0c112d2a10473d1e7d034abf79bae91acd4d5f5b3ab0780c89a8d8968cf3fa1fb6765be93557557cc5c010daaab2cb0cb", "-63bba88a1b42f4741021232dd8e22534413c9a8002acbea68d3d2b7b5450db824590325d2a8ac85279a2759dfce6043ba82cdf27eaec4181987182d097d06ef881cf65a8e70e8eb9daa672e3f3d77fa9db5cb6e83ac4b6181bb0c6b7d186fc141d4c3e24f80f8e0250b2ec5b5ea9ebd42fa2d27a2634b4dead7b396cd7c2efab34baf4d6fe9a295cb8eff973369093fda9f8b8dc5b20af7b87c50045df2c857f15b4cb289f2c92b33984a1c4f41a5b5b84fac4315f1b39806c2a14504cb52baf2241ebe3c66afee2677eef622e", .None}, + {.Div, "ea3e23163c91775765a011665f66a812c2c0f67ae1a36e1f5e8176409a35a5c5e665dd9715280ce99357cbcab5dce5d5bc43650487b80f893dd5eb31e65e220649deec31838b86535684f9f35380b79498d184f613db40220f62b372f88d181aca6243bf1f0fb17978fc487da9ba67603e928cb6eba78e2b9b84b217e33651e6abf555e036eacaa72bdd1abc328a1c2c56f6daa7d29c44d57288256fb16c49c35fa9abb45d0bca44d910228b00bce791bb09cf7aeeb1c62df105ad7e02975e8e5c0e0f74632a8ddedc09ef96e1f1d4d28199adbcb350bc896a6066a0d35e904a94310753c1519f545ed8d71a7cf94242ce4270c9b604081ae8cd49377ae292aa5655dd229494f83b7b89c166de8e8d70b5e6faee46bdec0ef1eb3d5a64f8fd7601245fa478eb46b9b5a28905897a167ab10062e98da0815fdc5f8f7bf5b9430af4a19f867c2d0ad725be041cabcdbaaa40d9fb6fbfff614cf73fb864e5aa7c4f35bcc441c67991aeb876471084c8e5520cffe42bb7defc6ce79cd2c2c212f1a734f854d1f6a392cd3e5706be5a5e6945ea7b034680f806b39d63fb1447bd5702bc1d58a1b8820ea2159b4c3a9f462f6b4e3ec58d60859c4ce7668347a88949975b6627cc14ea02c3e82ad61e9751be7bd39fce1f88a5763f5eae4a549207c2dac39789aa631534a855595467fe26830f092843c6bc1f5676de7f6e1fb4b3e826", "15672a6973bda1dcc128d4a4d6720e9ec0bf85ea1ae60687f2cf637c44ed2a768220f44e1ef4fb844d64051ff5a41c43133c4548d2a87f1fc19a83fab879f763fbf1b5c0861bbe6902b4e137ba9cba7f44534339e995a7a1b5166be8ab6c7f453a7fbe3be17ac8288166c9c6cf0de5006a745a378341ac5981d32ffe2ded5c21382ebf995f8b338cc9d787c2fb0da5c419deba2379fff330cd3b4f7351931432c25942b034cf02e890adedf1ce3174c04a10b028c86b6998ee9c16a1ef095e608227ddd54082a58c4b1a37d865c06eede4549a7e06ca2f7572908e590eb6fe619a78d4a24b88a32cec97a009e32694abb9815b1b460d5483e0dfb986641df43702444bc3e2632e880fefb14c4642ef6b35496c77ed5ce1733399fc8eb92ded55a30c8d560a64030344bdfd80e0abf861aa81dca", "af1c3aced16656d890adc80d6617af20829c1d2ff81dc1e1d1c982f2c8138890aa3d44de5822c279a0b18e8892503f577b1436108d1dbcf64860be3d7691ecacc8b35dacfabbf0a0df02ab1e9845e12c374f8b4d0b86ba0fbd133961b31a9ffaa1e75e29f51e9f54835fd254f0a9e6c37b7235755baa90d966df19d3bee75651c2d74be5c4e1b2790e3063865745effd805f4d8edb36df269ec7dcaf90b35ee0c846413439510bb5ebac06c480cf99c150b722c552343519835e1a91a45493f00f3b2729cf93ffc8fef1b08393", .None}, + {.Div, "-45cf54eea00b220f6ce11cdc863878dfcf88a781fc1cf58f42667e38016e938390e88c3dbfabb807c9c5659acd551d1239b9608538dba16162ec1ac42ba9b212a3db9cb344733f9e5b53c30b2cd563c032325ae4f10a1fb8c6df30ea50c06593565b663e0ee2a230478803a67f42c77e1a7c4bf7c0d02e16ba894323735dfa76a378ec3c30354233a4f6ba21e8f7e9438c2b2320b94a82a976fe734584caf95cac1c20c740f587cd0badf9a18b8c12bc1b33e3b2305d096084d84a4124f39fd7994e95378621a9b60ad7eaedc8ba874a39e378f278c56a81078fa1389ad47b03461fcb524c2fd1069e82cad3cffdcb80bf2fe4f03986f78680dcfbbbb143f392d9bd6bb7dd9a3957b9b921d8643d9c44317235b1131f99f25e1141796df3dc321b36421a916e5ecd078114d03f68149bc5737809758ab7ad39dcad295cb043460c54e79642d5e6d2da82862965c1370b428b8d7878952c6ef84deaf856c750b58268b1d37aceddda761034b5c5831a6f34c9e459483403e6c6cfe7be3c14cf2c5061c86c16f37d9373c18435db73342f6074292651dd7fbbba893ea09305c505bf09f6f4018192ca41433146ad770ec6d5c0fd88e4433b27a1030ecd2c9d97057eff260f4bd286ca9e5c3665c6063138e6e1369007806b25970cb91497fb2b5156175608dd9ecc5d8b4ffa92cb0c022559f80989b634ae5337b83b3f00811bf7", "-7a9f1e8dbd604b861e1c706d1380271b89696b6f7e9e00c9d84e962dbfe5ad4f5a7ca776e5dfbae3ab57c61e1ff22c64ee75bba2c1482baf272fb14aa75429a7371f21036d6f7ab70a6a098d313371e03290cd49b9421128c944c0b446e26fb34e5c9f5990e251c5ef852d1eca2845b3f3666ab5ffcf5aa5e077537a8a58d804b42f20fe0cdaf0bf1fffdc52652f2f6ec30f34cc0880e572bfd40b8455ed702a6ada8967357694f6142b00d0b90abab397a8e55cd244614cec6c9f33443b13939f437e920b7696c6c30f1d96342c97e01606701f8dd07416ca765dc2c5d74cec991f71aef4225855f0fa7803e9bfe1650a2242de73f8fde77b1a71b88a4bee00fc966d551672624cb27685abda862f91d66974cf0864a732320773a35b2e9dbfdadbd9353a579a7e497b384b2c6f1b88bbf093", "91be697e1a95b2d6cc6fdc3eb542c4cf8b9d7b034125632f4caca674071865a160c53e53c843bfcec108b52c6fb6d3d2ff6bf696ccc82f395cf8eb1938f9ec32fa99e5f0723863ff9a7a15dbefeb31abce0601b08b5d744d4b8eeae794d99c8bd5f22e957f5705c99cc9e822a158c92263ce7413d46f79cc3ce89751b8ca5dce0b3966a6ce8c95d2f16c653278d378b2fcdfe8889cdb237c8662798327c9625bb711765d2b1aa74e1fb72197a1d61fdfd3c119f0dcd0e9eeedea4220b3d9a04704898252637c1eaff8b0611e4d", .None}, + {.Div, "9cac167b8a30147a842de9a96a492094413db7bd985e8f521223b2d185ce6a6d64e0e8e2b3c76d67f24e7bd8cbcdf68b87f73fe4638d915567d3be80ec056f15d3e9bc57f29bc928cae4b1b19265a5971c923ea2f6b4cac348c794b2496a6a8045b9f4d884b9a5393dd6d2ffe16781c50d1152364b0207bafc084cb1f40eab127e1bfc12f5fad64f0209f0dd0ac4e6ddc1e0b98e061a30d0a9932971db55d8c140d1a574ec3619a2535bcbe77b3b425f0e3c84086efe8dcbbe32a5a6b43edae4f97fdda36106a010726df8a1fafbafc7b52a9f72e18d3aaa701a53c0d1680ecb2e7abd1ab85ab49867c6c153e487cbc98616f92490da22da921e5b22b12628c9ceef4f904f849560497fc4ab64fc18f87366eb71721b37824289dbb4e1faafa5a55d4854f10bed1784adea245267500176d6f0e725d5008a9c3ed67b6439ea5f23ca9ad1c9f8df706576e7a666f992813620ba3c10df5f2d9330348f59a34573724562b2e32065c7d6d23387b51514d4a4db0a9041fdadda7c2d2aa48523beb9fd99fea2c31e32f950472ab45835aac9f6a841a36ecca969ece56ff71c55d678b3a71c0e4aa6e2ddd96fcd76f222c25ec5d9092883db1b42f3d7abd0ba13fcd2c0d1dfd1f07941953d5c91bb691b8d102c82fe6c99c5ef73e9497ce1bfcac261a54f0385b51399b16f6a2f30d612ff2a113beb64882319d8fe3ac5278e9db764", "-1628b39ddf36a2b39afcf4e6c498ef2b3420cd6149d9ac495e2d01e466934cd8ff69ce553a695ce34597960f16c57fea7b90848405cb8339478d787b04ca94f07bd329372f22a6e1b6180231384a296f36093d2da32bd41f92fec184f30a39707324eac7d2fc76f248aeeef466cd5ac9d5d9bf74f543f7b426f5c1eb4f313eae5eaae74397ecc5e4baa996206a6cf78dfd1f76a31f6b28fa3e7976af3e3b0db925c0c937ad08d7a0479c4cc1de9f065b65d6d0f9926d259a4086bf3462c6bc1db9f4ebd66542f33a03ecf0c19b2952439ca54b448afd4dc4bf5ae7b2d7dae0eac8be7bd8eee7033221d295777dfb13e62cfae7d001ebdafbf49fec9b51c1f748fcfb61665d43b1f7f25194009cfa207db1415db49dd0f92b1099c2c2077e801b1177096f777b23ccc3033d07a689e469510feb4", "-71203a26d755313faefd27bef5ecab744722aef7bed77610e0a01cf77cd6072e296b913b55133c7d3648b4527e17935cb8505a9fde08d7370b293ac83eb6d9d9b7a1a6f8bfd43f8353fe3aeee7a4a783f6206e50eea7b6ae6bf9004aadc597a3c412a8333c8593409008e247838c0537c5e4f7bd2bd43660a61d8bee111d505a08ea981a2736d68799fd78932f887a63c228dbc8e43d9d1588d49ed77a5210233eab44e0e7cb82d51fbac91d87fea36f9277de75c264a91e128f5a59a652a24e08adac9c773023d63f72bdb042", .None}, + {.Div, "-f1ec5b000b487d68ece1a72f0058ba932e9f98c27c967bec10f24e93f2d5cd9bb35f3326f87a95330b7ec1d9b7511298c3394ced99e4d5ef6dc4dfd7178b5bd7efc46f4d4445ac33606cb9e8c7955ff3f096de7019dec62ff92d9960e0feb3a947690ddadf215176a58a3cfa8ea94803cbac3762d2df2d911ca1e421f45007aefe9fc7fc419e7f56119897f953b52d1307d2253b12fa0a978a5ec5defd43b908e25f34051a83ac9aba38b3bcbafcfcf1d6c8f6ea68d772ae16dab030f7356fa66e14273efb8e1a840bf6e357bb4bb1b39412eab55d4757bb915fc1ebd8c00a999131efa1e40ff68d8d6c9da757d29ad95c9feaef27b7397d4972a3a56349a8ed02b955fbb060b8d3ec30532b52059719ba732901245dcf54d9b957976c3a0867c60712479b2c185bfc49e783c87cf8bfaab94435e2a96d65972b560943c748fad39c368cd31998b00c69bf5040898425a1b0a421ca8fdca1bb803e9aff03de9dbe5df56dd656838cbef4e0a103f20cbf44482637e61897b1cf1e40f5b343a61999dfe58fe970b29298e597609feaea42cc156df3a7367407f0b6b9fea02ba7af8f4341116c1ac068b68b645407f532f19468c0f78c43ff6e1a5de61b41bd466ae766fcaa7ffebe59fac3c57f47fb0335ef8c614c4a1708cad2e8a9c8aca364b300b56b06aebc356e17a91ca4684667aa86b89bbd44e2403a1fb606c365411232", "-8dca3c8da410edeb42f33a8f736adb2c40674b980de061e7b71065bd4e58956ee1d4f18e5ff160f137ff59a61fdc909a764af7e36e729dde44ecf277bf910e5f9834c242575959fc0ee33fd65b837598ed29a54233ae241b4455e92270af6ba2808005b8c967ca8d556bec89f82002461c380820d6585a451105a1b7471d872a5b3842fb7ed486d696e144f6fd47f54693a55329deca1b3c2ba477323c55ca186b5a453fa58a57d28b0c4e1346616fd67db618186fa5aba10654db44ff51c169fe3e48d8881daa81caa50af3d301a91cd028dea60756ce6c7069267c60eb602f061115f8e1ed21b8318235fbfc7e71089b4deab1ac1ae4a7fc017cf831b76738a4165011633eb6f7da69ef434b2fee44877804de20d9fb7561b4c6de0dbd78cb73adec3c2ebf233242027cc4e3b7f17f9e404b", "1b4ca1295840884646ed8de41efe55a34a0d71c6aa0ecacda5bd446ba12747344c737b442fa5399e467d5bdfae30a9b6e85b2b0ec141716b3b4278365fc129bc18c98a42797b70f27307e69cb54b256ab3dd2535944a016e005564ffcbd8ed3ac85a4d423f801f6da7b00feb5694a5b477af8db7a87489dc3c876241399c11d0f168241e9426efc7e2fc1d09b359148c27e2dad6cd78484f3bb1c64430ca16d7ea3de144d588a5726a182bbfd3cdcbdf7b9bd4a61aac2f6318bc414dcf1ec08777ad7f4f5399d3cfc2c160d6424", .None}, + {.Div, "-4a1d8bf561198b73122019ed472f0e24d5dd196cb74aa253ac5a0cc0ec35bc281fbd8a384877bf42fcea1c1721c205dec8df77c26432bf6fa95c78bc5e5db7fdcf23228e0bd4c0bad54fe87d2a351de25d7b93947e9366b7324e92b29f1df8e105977b3a3e8f5cc5d23c52cce83d53c63d184990a77b05f44dc4b4b3f7e3eddb4eea1504ea2c4521750a4635559b91cd9a573680b97bbb8103a9570470401b4b9c7a61ce0773fac101e31de7b745950a9a1536158a5c836a81c054a451879635ce954225e2a124dcfa7f125c98f7c4234c50f3225d9632ecc395569631dcfe22bf753b2c328aea62ac15c21ce3c85777ae2685c99ccc3fffc90a455afda5f3bec908000b3bcdad4ce7591cd5c76bf1d5ad538e28ddd6b3711010f50b5ec8c181c876c49fbaf3976a8813cd46c5b64b2877a24ac91471be0e318c239746b3780b02389277a7873548ecb37128582058ba1d3f3f7046fdf200cb62feed220c9c018292c30f277f09019b608979811fbe7d6350a5b042af0065f990ccc1bfdeb2abc9730d6986043ddd9d5e20e0b576820e05d87cdfa8774cd4cecf94057f4c644d784cd609111c66813606386e535d2b3e611006e1f63ef744a1c0e090742aa8524456e2bc491f6a3f1342a4178fd7a0644bf770be6ba83fa3709ac134c78ce84f7dada1cf15fe6d066d50242a4c3aec891d02b25a52b921485bd680cecbf13a6e", "-175996d2d3182edbe9337efd931b6eb21708f4b6bb0a0404a85de41c43dc3bd49bf32498a480e8c6e9925457e52e9bac3f72b185f2b56319e2325e19ab10c8cfa495ff7959b0102e385ebf5e0839765587f76c5a1b3bf1ef3aedbe4123f510bf7ee0e2722b00fe881455748b1e00607f68cb65c9e8b7b963c3635c85dd3bce4fa9c79a88948516d9794c89ad1eb8fa87c870008b336c32624744b8362b2949abee8a61f6623bd21ef09b8af35f8d740f1f71db017342260a925b88e3b6b3c1b602575c7bb3b869bfa376a3036ca3b4ce1197282ac254dd3af0b91b819e283012839edeeac67bb262b2eccdb221eadde41fb5affe57e8c173aa53ba59317bd7db6ad79123f7c62935f3008f7ff8ac0498eb8bee63c50e466273d422ae767c9b45ff60579d59fcb4793472b005ce50b4d0e3c7c88", "32c92b495c685129c0aff05f800bfced2dab948f59aace4a3865e26aed7bd150a6eaa5cef4c411d8d0219611e7b7f4f22387c0c9e596057cbfd4f2f19ca6d59387e1acb4682fdb19eb17ba558da1561cdfe88ac6138de63b8a1a87ad289b378d58801163513d9aa9c4c40e465f0b4128bdac84f6df36fdde4e5d78c743e523890cf569923cfa0627dd879a2b620dc3baaa4e44694b18ed74c433d711aec5e62648e1bf5f160579c837c8a28a340e03fadbdc5447feed7f5ced1b1dbb41b903c8386f5e92fefa8e66092420e54e", .None}, + {.Div, "-96c246aecf32f95721fe690fb781d3ce10ffcae5bca531dcdd8727cac31df5b6c97edc011b661fefc8289d3e630d5bbfc3d750a3ebe26f6f2db5c95ec683c510532627f50d1a9e9705f01f97617aa19048e67049ac470502c6459d96b3d5713c82359bf201ded3e2f930939bc245134048b75a5f9df3a4e430b11c2ef80414e5fdf1826d075048bdbdfed4bd5ba7d9325a0b3453f6685aef3679de5853966d5826219f006c0c9ed8fd1eae676c6d2bd42ab4b2cc03fb4588de035e227fad86ac4e00e3cca5bf35df5297d01739b84fbb628a1d595911caa895e5e1c91d27ccd7993727c5305631f9f787b15624411021a7bcdb16586877391ca82c0952c5aab5259434579ef9dbdfef0f3f6e12dd37ff78c873f25dced394c343bf90f15bbbf2bc2dffcd6215b7f3d7d78dff613e0318144c5141c0da3197c2eb914c9edf7014027cb87f227d14cef1475fa2ac515c54e283f8a7ae9c85d4d1ce98565a9d73bef2c470c2d9e47c38ff9d171edabe15235d231f2273d2abc127b25701ab18b800a72c844f870684e7b2d9ddca97841f32812f487110637a5f01c832b07bb2624d4a6f4e183988aeac10821faa63fafcfb5937ee34100e03f68f064507c026c00485e09fceaca520e893846f63c19314f23b6663ca19cd7932ce1fe9865732a6181f223702861a121789cd104c749a2c392d11627d2a802b346f9035d58b7ae504", "-1c03f19b955ddc59aacc90c4cc221efde3b8856ad3568a45840833628d9fae3b9794d50e82054f06aa3fad603239514e35b5edf0a669769996ff9731cf79bb97a4afc1013017bd814f12113087a43ce56fd17dee41f2d2bea53f1a3549ca2f277bcf3bf7577e77918dcc1a9bcb87cf6bf736edaf0b09854500512745ea5891b2ff4d68cdd803ea385246fd8f1b30b3de0e9ef780e48b4248df3c743b12a968339a5dd632eea283a232981716b158512af6e067b53a7735a186c31da001f193e00f2ce26b9fde44b041ad37830a44dd9c13bcd23b5c72ac03108a8c635d8ddd72baf7ab4ead9bffeb87ddcf416ce6450cd08d873bd52ac3f2f125d48c3314fa2a48aa60dc91457f36177a73336912f242e2680d405d7a3b10e88a917738274c2fede9d356375054ace9c96f02ee210ae3b482542", "5619beaee09aadb1fa0a958d02560ca6a21cdb16ef9dff517e5882ee9bcfd8542f9ebdbb456e82bc1ae13491bfd4221927497f8e59fc87d8e9cbe9fa0d4238aaa3bb8e81c5f04529a1a39994a6e3b86dd30f7aeb473ddc19d25bd88e301f47d660c30f8a625400dcaf7afa932260bef37215bd0ff547e32662cc59b44448d11f01569feab2d2a75f40fd9750ebe2a4bebe746474ef9808c14ab06706d4119a85413f62ec3d94f5892a11175782b35a43c8c38b494987afeb1c232afe9cc2485ff363b3f8da1c99318d06799e4d", .None}, + {.Div, "-2d971eaf3d2c9e02402b2c399bfc46197008e1f5e75d28c3fbeb942828ac259d875df9e5b54338672e24f3d5972d8e075ea99a26bca24cb0d8747ab4bc019379fb6d23716159bb5c7db178cc6f5bdc22e65a8c146c71a4a9a1ad816bb8015bdb3749a2a1df6131f10e58f964ac83467b3607944313f6ce4f309b9bbfad68326d0cb9e0a22a3d411f510560e1e432596d9947cbe611e758b50223b1f0934e40e2866cfbf7782ecc849ce8678583d0dcaa6398a38dd8d8a5e481d92417589e3b7afebe60a81d2e2c4664869265a665b46d31c234c8d1e6c4c2e024fdcf14b2f64c2632ee4b88217710f834b4cf52642d591c84f052c7b952b2e118f05b23e19769e18f30da61d169a169f7397ded1082985664cce6380ffb5e2fc4116396b5f78f852f60cb655902f6ebbd24859b53ac0c92cda0533050fb7d2bd2b8db144d1cc914ce805ace1da4ab7b5c3aed96499884e90153632e43e9bff0c101e45072e39574c416ea121e21c1df7e1818a50acf4ef6753e46d4fcce1bf0fb0c4d5d0824958c3c8e048492eabdd723c23da2fd46971884ca4f02df32749b506395caf735bece7816ec11f4d592cbf61e3e60a3c865ef75be92312e5702c73ad58aa97a0693a2face75c89b10b1e759f6e8c70918fa50a754d458af09bace28e822520205ed8346654aa9cc0cc268872f78607f1b09fce7f191ba6251057b4a167743decf4c", "e10874c4fcdfb28e3d2c5356f8da22adb116b8284cfada5c4c01303426777c61944d176d781ed9c61f728970db773878e931c9eb818809e1f0f92ab24632fd8438128b5b4caafb8bfc36e78a792eba6ac4053e09431d7f4fa604582434ebad57c2dadee85bb5ed6b5c5370b9b088856305643d148ce8a4544ee177cd528cbf01114ab95d1b8eea35003ff8fb1109674d219428a80e4650796a34d9be983c5eb7ad217cb48de00e43ee4d32998042e80f57687dc939131d6051907838e7390ad49740d2d41afee5e5bdd0026b167b3cd959159da6f573bffd62ef91d99e0522f1adf151e7983309b7d6dd6d7a64a113b973be30f1ab57495c076a59cca2e2b1274af8487599d44fc0d86a52ed001a054fdc8d3fff48b5f72d6341d13faac6c53933edea6bad054f5b0cb14295bf0b3b4eefb67", "-33dd310e4d46aa512521242641a1281e185f2ee9e48445ee757a661037dd3f4fcf6238b2b10519057e9c7b3c29b700753cb86bdcf36da24b26ecc8e0f8b80e6bbba0b283d6dfc0255f9fef2570bedd1f10cb707fddb57d07e29bc1cd82abcdeaa248fbc7af578589e737838669f6ac40045785f66ed1a09204beb2d82a0cedacdfed16d0d25628ed319a25670067471d7cbf2ff8251647ebef043a5c52f0aa50fd5c78c8a2e01031d0b13618758f27c8f97d6a4ab0a24cf512d2fde144ed88fe70be4bb50434ecf71049101c89e", .None}, + {.Div, "-56959d1b7227e90c579b2f7ef7a778b9a874f86ee791a4203094f55a3ac0115afa4a09ea58c281e3595db3a5ffcd5942e33871c00780cea8ce301faf359db85c3440d26cce7231736554958f7cbc47e8990ca911fb2dd7ae391f7f49b3fb28d837ef1c7b242fdea2474aab13bfa318df34f38e62fff7d0ef678b7f278e9b0151633f1516d8fb3eb27708e58c25639b99ad6e5ab4cf84128e4afd1ed36a0b8fb42fe1911dd6826322deeb2f48fc49d79be1b33a7535fd09bf819e9a6e1a3f3b2809a1f7cd2c43c042831cb5857a77145473e9ac0b79d0b1b7c67aa67e147a903107e6e371ce0670c1579207843520a51f33098648bef2c31f11003bda0ca558e62b2490e79cf1ef9644d57ef0285a03db6386dd9a66ad08142f29f867202a6fa1a5b1aaad784a71a39d5546cb846dce260888477dd5601ceecd1a2d4247ac0593d644cb8640abcc65aebca1e3533c3b3daf3685a7420b864394161ac72f5b0e07de94e162891f5020c32f9b2be58b5fecaad7b14039194866e283051ef5e23ae0e02e0022f78003562e60458eae138f7a43416ce58919b9b7d45dcbd4ec5515857d93f2d970346640f85ea4abd8388014857bdd30a2ae57f0c26e4449faf9f3f18543a06eebc76606c5e07f9a58f1bbf689e7c7f06971232efa2112e5925b173565766140ba41e25681869cf906e43f7ccdab577509bd90b1a380c0fe69d40793", "107e5b8a7db372c83a197cb9ee2497cab53f8b3efc7543b0feef0f0ab7640515af2e5857387a891779bcdeb5997e2bfa827c17a61d18098a4ac6e2ce9e23d569c9402a80ed96a5eeaf09ab33d51496e501d8b4f037b3cc42998804b67949bef0a4cdd9a51c8be4d08c87aa37e3f485d90c8d45cc5387fa591cb1ca6ee461ebe1a1bbe3d888a680461f30465416560a48c7f6f6e5615327b757adc436baf913d17fad3929d7043a608080277987018016dacf96876ce675c663aaf7e4c7e7072d6f29a261e8f98219f54862eedd80426c5286ba6b3cf35f2cee960c68047a084579d1edac4501d2cb5cb11610542de777aa729b72f2a28045e93a2bf4904ba352da3e33a7bad05b63dda82bcdfcb5a1f37fbbc80bcb35d82060de2927a24b451d6e403b8ade5aa75fccea192a84a233e38f70b0d", "-53fe4a072f6a7d09cedd57033b35915a384c8cd5c8f8a01a0d4c1fed0a4f9d7da4c2db9b21ff6757deb69c6494d99109bb958e9934c881c1f1bc7b3eb2c18b751350e4b5e86cff30f72e0da83574bf8ae22cd7ef49125a9c0c77eaa299da2e6d5545c6bdf23ad50f95d73c9952c8ac9f9ca53aa72f6f82c07f13fd1cc5bd32f42d21c71ef2cfddfd08e7910ae5918f6aa1bb5c6e0e923b49e96e37c5d0f32f4f13f3cf53481bff770162b605e4b9cf1c3692bfab4fb81aaa3741fccd35e34cb7974bdc0aef65669fab2e5974b7", .None}, + {.Div, "-98c9c49d63da35fe23554d80b33a7375b97d31f2cce9eb52bb86e424ea499c3a65e725e6a3711c61d66ec4931c0bd16f28b8e7c91693b890e3b9cee8061c1d76b1748ed0ffccfa4c38c7f60c30c357daeffaa77b12a824a826648e4c8a6a54edbfb227fea443c0c8185a77110d8002af8116b87d5efe35736c487ca9d6c78cda2b8e632da3ede792b3a763c675352719be732a0cd44c3b4ee2bfe62efc66f7f2902677737d93a646baa13a1ee5f4922049bba80bdd7db359246706f59976a886a834725ef9f78212ffbc3593745db70c8bcc181c20e730df630c04732892dbf56a273e759aeb428243a14911b0b7b4105014a9b2d7476988a4d89a8115815218640d0972b8fcde88f18b8ad2c01c0cf5a12a617a9fd25efcc1768610c8452a46b76c4e511a2cf194d5b791d04d1927b2a0da38b69ea225d0335b5f2948d1a7f845fb0bcf95b85b9ba6200fd4bf3120125f126307ca3e544517d3efd5e1d93f1fb08b5bf32f0740d02b0d5eea7da0e1f10c3cdfa37aceaa2f87142ca7665b8aed300b31ed5aafd9e1f4f1affed3ce2cce303d98f7f64373cf4c3b126168b924e11b24088759e1764efce73257990d0f32219917094607dabe54e94302c8f6b4bc3e1c81d18fb618b3850f67e05b7bc1a40938efdf89b8272e3ef93aabf5dec3f22dcde35567f889675c7dd0ae3491e8e632e22cebb1b55772a403de5a420aa6a2", "119999d8b67ef8c814f1d8b394799d1478a3de636e5fae7f351a65821b19d1a951a8eaf1ebfde972d5790276848b429130583a127943c7a8814e069cadb03853318f16fbe3d375520e2729fc24516e05ad2ca96504d1432a9f4dc5c671fe0011cbc9f7d9dd231bcd68500783b116645ba1103eee73bdc9e376746f8fa6265451938c6d35b274b98741ba1b8a2e7c4dcaec50970835bd05e5129a193f25ed1a7665eb3ac792689ecb95317461521550d5bc53b7c70c97b0095131056e1d86b99e885af51f7c2ee52c9c9f9a0a647a85652d07d8a6d7dd88a973500a44f427b787b1c5bf1adaca5983e60aebac45f6bed4b9024733852d75f858a87e833e94ac1099829b074c89a3d1fc973a93fd97ab5391dc61a862cee2b9888901c8dacf3a3748e1c4183b955018fcb70e4f66f555a70f41009", "-8ae5f69cff90a8e9923fc998de204b96f1ee7b049b7082d878b1ffc20c79f04528b551652e5aa08e1a41885457485dc77cd0fc12caf01e964a1cfb67852230fb381e9dc6b4f687ed874642c53cf2d65d3384a5c4a6de8d22be18f822a757cd433ec4af4b3b69d0699bf12094c184c88c3928b8ed71a764efc4f812b5bff1033ca5c5bb6bbb1edfa600f40c70285979cdf1eeb9fab4ba052fab9530fa8b9811275d6b0e2ab905e090dee76dfb0182081e76a17fa31c26950a855d58f9b2cf9146b8a1ddce09623e148768a25a00", .None}, + {.Div, "9da217dfbe05b198cb4903216ac227699e8bd885dba257ab391afdfe4bd899e53ebe44b8b7fda4de491a93684f4f3fc2a5693e952b2679f51e65912447b42dc4197ed03e5d4971a5b839f12008f1269f4f52731287c385466acb271357615a9ae210c07b810e21fa2f1c0475c986d85cf3f30c38d8f9e1feda75019086bc5db61769563344422dee0478cdb76feab5593e12ad3ea9406742bb2e54216431d0fd59a4e7b20dde8b15a67c6823067ed23847747ffbd2881f943dd250b8a3bfeb0ed9bc38c3269460ca70cf47aeb66bbfeb44284010c4e578bd353c4998bf59eee0041950325b1a71f16aade2701e9e06bbb3c9ab7d04c20ab6ef56659eb53fb1eb3451a992957747be3845b9a4e06108e02ba5715b770b1f516efab010e757b179e0aaad30d8abdcd73bafdb078c7a4b618731e70b3ad9dbadbaaaa9913cf0cacc0dd0057ccabbc1c5f1234d0a740cb2ed6eb47ea413e698689fa3c27810a8fce9008b43b1eded54c332da72fb4f89edec66d2011ef8955e0f8f318fe6455c937a317192aad44e7ddfc494a912921bb3c7161f91e19cb0435520207923bca507bb1c7e06cf308c09300d849f3fe3069e44dd32ade718bff8eb99dfc51d82ddbe000bbc868c43b37b9d527ac1ceb592817d4ec89bcae0c5ca04ab82a5684b31ae46462bb97a94790ddba9514413d7c4122e9982c1ab375e2617efdc411a2cf02b69", "-1a4fe2a353ca898b803389eef822219808b4012993a8674622bd19640f482b2734a676a857b25bbc6acf8945ebfd55bdd495e8c1379baf3219b3365df5408b03d7799e5fe16ce6be7361da8e43b60f2c051a46667199b7e0f312e882fd0c2d15040fb4267421643490b9d7256fddb2ca8762d20ed2dcef58d097d1d28b9e87e3965c358f1ea51f13450d604fb7c1a1f88f600e521c5689ef39b26552ce954f3ab6e99e2c536517521fc5761cfd2208a51df62fde792d3c87419180da47fc015cc78b848fbb84dda36c1847d020ba60d935183cbb25d66123d022088dd8a6acfd60d5b3d5e4a7f2ae22e97ba77f735b115d4ac3960af415ab20b7b89e96434d8de49bd0dee4d9cf6250d925dde70ee8375b3b3f716a1a6c2d620bafefc165ece664250864bda0c922a99b4ce7e484124c3fc4296", "-5fdac619368d6b3bd9fb850c40fde49470fc537670fc77f0d855eb03b2b3ffce32f8fa3126d9990058849e663ebc834429c92c2e33305c07b15e464c9c3c628de54d9bc9e3529c38889f280406c9e7b480512fa195f1d4f74edee2ed57d9df2943c8bfdaa981434f5415eec388b220bd77f92db60bbbc2be50f623d2de5ce01470994af55cb7530d263784279d15f4fbd1179429f667ff23f1d14e5d36eef6f4d6f3a0dd0baca911d2786e83ca524d8efcdff5d0e68332863eb6e4a19b757f85ab02f99ca57e85ca1e86afcdf0", .None}, + {.Div, "-c0fc82f5c0349d0ccb8d4283c855e624d22e36a36f71e18f1be602a8422cb6bcaad3849d48fdd721d637b510c7a2da8b7031b3f2ba8916c1126238194801dcd0a9c5d2ad168303f00f532fd08c979a81b609cd106f0a72dbf6f9e33c41df422ff319bd16d31dbc59155dce1937ba82fccb3fbcc5fd12be9a73f01fdee751f8976797f35e9f150112daa40553a41ea44b74b611a1a06b2b2109c2ab52f901ba51ceefe98aab956aa2fcd5339590150c2ce07b517491d1d9458875b759057de0083a3bc0cb9ba295e5c6c1ab0c74a80daab67f081cd1ce334ebc42045e267ad141a7daafa928cced8018944857cfc07df41ee18806f7dbf6b8d6885f73096076d6a0ce622a832fb5c76a12e35f1c661739a77c20cf16fe13d86b2ce0c42a8ca35f360d3f3a0a1a0d7da10eed733f119c9f2ac99d9eb98a8e381d029b17e35b6bfe381515efaaafaa2793da3ca122a082a48b2f1afff3ae1063b24f90cf2b72aa3b3636dd940d6c0cf7dcffa744a91f5ea92e1c6096892a92434552fc0ec5817bd12fa9ae37a1f089ed5eff181b378e8d330bdce7f2c83186110ea22b2b05f37092619184717634fb7b50459ea5c28cd4c28e6c3426b3ce772229be9d6cc6cd3b3aead26f2fe31cae89fc945e5c44684496e22cbb4a731a7754b84121423b7e1993734c6cc757fdfbfb8d7bcd02a37746178409b41fab17ca4e7bc6daaa525067c8", "9d3389422467f522dcad2b5f0e4650da1f76d96dbc6f35f14636e237d4e15248270f260b56651cac34719ca85e8ec13fd4d8fb23b3ce39e3c0703bcb913e6999d21ebb4d29f11e648a7fed175be6233831a5b0510908085f07fa0914d444df99467641fa01a0d652d5e3b6b06bf083fbb45eb668b609f1ef886c575d9a0b6efd143f67a6650e412e6f644cf06cb8db1f262ffcd3f55da8d0399901448cb146b06e5d704e7af3ec2025718be63359518945769056da2c81c17c6b9b51569189a70228d563aa56f433cf2cc7d89528c62d53db04392b039340e2a0163fe1dbd6865de48c80e3511395979088f891f094bb2de4bfcb2641544feebd2e42fab781bbc1a27bea38d6cac1de53548392c33f38a4772eca8d9139acfc02dae0cfa521cab9187a978ccc210c8f7b92c9cc3b4dd28f6551", "-13a46831cdb2ded1df8ebd8389431e245d70fc72a58264a78d1f049fcfe38b53eec433fad4ecfcdb630dc4713ca5c5ebbba11b823c21fc700f06bb556b2c9bd0bda32805e2851912794281a215a7c1fbeabaccef69db106b05e7f7c790b9777f64be3b7e179c5557ead286cf37de354e8391096a3114b4cc026567e0bb1592e61b9c6cc0d010c09d275c5a5ab3b88232f5dc62d07dbdccf252d1a3e08f0bc1310401de23c963d9fd614489fc25a492944b8a6904e4cb043cc2cfcb971053a6a985892b555a702f31457d5f73741", .None}, + {.Div, "-6f4165ed1711de486e08640426e7a0d31f08a0d8f7bb0a999f2a4cb7567601a82a1047f26aecf3cf1936a6586424fbba4e60c5493453eb754d605437eb3fecef7db2b6a247be7bf208bb3c83b9e8f3eb6ff72b6ee1777fb756f7b11a6d500738fde131899c84262f2f6d559cd8af9f997614648279d58eee747562a50e3cc784fccdd1679847ed5cd8ffba96709f7e7dd056b7556ffafd42224febc555f81b46d237d639b39d3bd925672e1168e5cf3a01db66688d5ccc98f791814209dae50cc07577f2c9bb869ad1bfc195222290a12717cea9cd7bbcebbc7f52d3388f24cfeaac4f5c7332192d64fbf83db5e12ed1a375cc979d9953283c2e06db051b71ea20a592f9409993199ba10671336af90900751060f8642d9367935a13bd03d562c7ac2be56e7773a5e9dcddc6f70c4bf488061193036425a4942cd282a0e6c59868d496c99a3401f78e6c7d3c30b5a3cdf377d32b42e3a5c02ad5b847968cf32f0ab01662664acfb408b7e02e1f287e345c9bfbe73ecd2f3a9313f4956aec19d1ee6a18b16a294071422edcf666a8bf4dd1e773a8b01e474949a179bc28074614ff599d727cb874a7b793164a5f41a65cbde1220682e936bf73c2c2eb5903b237a216d4f9cf9987f13d499cdefd555572a4a642aa7eccecc10c8497f1c44a896e8d0f4db0b45249d32cf41ff1f7f04f8360b23296a5b9fd223515f6e5a92b060d", "-4d2b84208723b6fd958729d2f0dfa0d9919f17a7700a3a9b3a05a69f10f31c43632b623978684f153857137db20143b204b808396f04c1b0f7e2f0c1aca719ade8aabd10f5c108cb01e4bc570ec8ba62d3914a1feacc45386d79e37dead266ac2803ed1a2592efa8bf3567a83833073f05d0ff180ddd7edd9d265f7dc3e6e2b9019d2c756ce3f4ebc581501a15af99c0cc3a41c9be4f62eb68c5e20f879e39a6ef09be78b9efe4d2f05cb82848ec563e9ff187f6a1c2cd397daf69b1aec9a4029ce8f4d73523953882c64021565a7f1b47f6cc240889803cf1ccfcef8bb1815cf49ddebb7e49f565327a25f5fac5ecaee327a63447f8b6232f6286f1ab4a3d02858bd49ee243420163003c8211416f63b90975aa726939b2f2eb0db2d604b20c74ac964ba090f67487e4ea346e14bb9bccde90", "17112d260ec7c883eebdd9bc328033f66f689cfb716bae5677a66ea3658437c145567a9ea09338414557090df11f4f30821400b5372b2d56280fb971ef1623d28e7a19db149f67b0d6f4bceefa6713d8036a0dbb3a3974e9738bdb094b24a84e0538956ace7c386ca278c1fd04272a46db2f807512bb3faf81e4b7461c3a1f8a07b13284cd9c7930f41a01cc45e21b1254e4a07cb26bb3cf1b79fdd21678bcac2ba2b41e6fb81b5b028b563337fd5ef0d9a127289945f9edf5ad5cb88dbaa66673923deefd6aff0db8dcc640cd2", .None}, + {.Div, "7fc4363fe1f0031327d83f600305c7cbd4a9eba691886c2c3b44dd6d945b5a5c421693a8f8e3fb5278e520a6a3b91f93218ce845a58a60b33529ea3c217b5f66b5272eb612ff1fc65f12b5bc11f8bf0ef4c0632f3fbf8c762f56c119388b9ca011b7a7e19834291477f58d3df2b6ba42958a169e9a383b211e8587841793f86ed0e8bda63cf61c8ddf4cc81e35283dbeb023675cd039ee0e254456f1b42374e8bd6ea31290fe507dda3f4d883c36e5ae140dc92adf9c6305f37e1f1e737572b28af9a6ca63cf07eb08a813498ac1d866a98607da39c1fe306d4b70926acc241557c7f51bc027fd9e8fedf3d03111f2232c40ed68a51a5b4c916e9c6dcd0401a3f79a2520be1260715b7857e74d6cfc5e1b49829f386a97e8578fe91351af82eb56e993e07182b4d14e1da5a75706beb938a588f006f03167c6176bc24b7f6c1ff98d123142df3fa25303b977d289a18a62a2d11cd63a5f7328ae6cc8f197eeae76687d384c87246bc65994071a05aae037643da0dd5270de0ba909823d1116d77f69a29b32ec34d643a93365b3e9ca62de17f09e4f5a14fc078575e50a88904156f33a650408d98c1e5078022bc0e8f4961a37ce80fcbdac9f605717b945fc50d93e48625938da2fa9fcc80805007636b78c41cc4541756e6f414b348f996418831b3c5295c2e4180f05d0d8e2655c2e039290707db08b339564ab992a44444", "396f21be296d00abce846553a1b0217be904dc71cc36a0602b3171b5dde3bdf3d654b0d3a83d6a0e102bd61c9616459a59d5d8613b7809d8349b976251dff13f5ba9700049ddaba81e560c819c35c5292b38bf5b8cf9a456883d6b3b4426633c473a55fe8cbb84e516f668e33a85a83fde64c9e33e6dfeb5fc72ab19e133230d3e01174a53847fc207f010aae461825d10177cb22f33661e4c40a57f2c1761423ccefce71deff87924db1156bb4813923255122ad65be22589a19e0236f195ed08164bb10fdddd9b4a7afa7af3bab367d298b32cdcee8147594097c1b9950401e3c821ce41992d03a53153183551992ae75b427c245f3c132801851a180e732ba0b8a41a7ffc9758842166ff62791d40d5ad77fb6f4ab3b1db06ad2e1e3ce606e9b102eaaecd8d047d8c44dc9a72a484b11a9a", "2397db6b11b8fd0916b9b3ac922f7aa23de79c227d2a0e4d0cd8bf377174a993a0322662c0cb6a79b00c1d082672f4a78720c0388489f4570d2f0e645c8ec55a1b9891c9e0b92f2630c25569bf16427c0db989d05743515b92df8e1c0a05ff37b703360ce3303411bb93ccc9f50359652519a829b8bce0528349e0d85272aefaf4fb68d97bf40760695a28f24e60ed5f232426c4283405c22b8f0806193a7770933375e62c5bc55c629922e3366b0898f1c6d4ae4023c26eb36d630be78b24cd739aae017bb7e1e5c738ee2978", .None}, + {.Div, "-67a88d37126c0999850f7299eb1810460e1db3c52d0a96c3ff8a058134ba5fa913b84a2d2d403fdda9ae221cf2029bbc0a86e31b08732448543e079e8aafe231de1dc0537e44b7525bd63cf64234c268820aa9bf1260ee85b514190ac9a5278eb3ecb5b30ac48a76f2b95d9983a1df1acf267808c347fa91d10c1fce685a41a6051103212854c84e19280255b1695f32fcf3708938d6165089b3fc6965b6b091b0ed7e507a3a82c76b74989cc9b728315ec73346ec1429b514e1ab91b696d0815620637d26b1b0e34b18d1a2d5adbff2e02abc49afbd3cbb7117ba2df7cb9bf6062914be4edde0bc61ab3e18d092f2db84559de773dd3b81b7f7093e6fdb0917a4b32ee06f98acaf93443788a0a68022f8d83c826b0c86db4c6c371fe95800ab64710d5c5bf0dcdb37a8b41d65e1138589fe5b24f8a374f2551fefb7a247b2d18701cde357fe2fda56094a32820384e7352afa8ad0e7a1c96513b9ec528636f7460b866afdbda504b67990ffb147dc8ed357ff6eb1f406abfd3ff82f835a848e5366dea9f15e71d19d0eda6edcd62dc206d7b283da58158362cf2e41a62417b44c895952f70f93d18a3074e59697f34068b6baa0cfe58e241bc1df174c0728a05001acbcf1bc53fb0e48fcfa09012429c565a997a681b2fe27ec8a338bf542b3cc7d24f524e05296d13a21a6f88fb23f69e1402d1105bfc7f902e54114b9e27e", "17dc9d425bec70beb174b9cbd080339fc7b59439874df55f14c2cb8f710aff87d98e1441fe93294d96f509fd994f8ef0e9fe28dd46874fa319a29dee1893e10764ee176a4248d8d8975412e45e59e192a151cc350da42ddbb13de97eda697a24cb3512e4c09ea79c4ce14f0f6828569914c2f5fb4b057dbea0431bd0cd9c1b68b99ad498e01a03ccc0c32475c95772ba9c5523de59af8d3abae78406d3b2a1154b1ab9ee655b13d24246b5c8f22a47896c481c4ee9d49f6ba2893cea831cac425cd93079c3d6f71e8700676876c013f1916edc183729b50a912b1794942c6b091489588d05ad767bccb4553a51c087c874ff04ff72004c7523bf22f34b40485ba15b3b83c0d0ca9e7af10242fad0f37f7b1010c76a31485fa4cdd57116602385f4f3565828fa5b8d799673f8a73295a6b42b818", "-458183a56e31454bd78514d7bf4c2e3017d81d599db27964febf12b36ac7a9188332e6a124c1224554e19201794064f157df037cf3149352152dc8d135864421cf69171446ca0cdd69e96b2f71129bdf98869ab35c5616620689cbc9c64b20541e49d30911d8a851807c5db21f33708b04473dabbe701288a7f92858d9172f7bbf3ba44afa1d4d62be7b0a618fa59020aba37835dd1765a5986dcbee4ef44fbb05d03fe2603720508e3ee36de13f74f4d8ae932cf0eeebe00a464bd3240ca4e1a8c2d00880aef5d0e16392d17b", .None}, + {.Div, "-5d4625d9956f83426d3ea721fd9668c6a4ba75435767fa4335637b6ed7165e418322babf79bdcbcea3d5e3ea621f1d16891799cc930e6e5ad39845f21de60eeb8b23991ec0ab886ae2daa00685dece2af39474f569d388b6c435682d172a57d2f236d89437580316ed61227ba9947c27bc6129dd9d159de06de0cab77b2a02d2b0759d87939d135956a00e7909488de7237f93d033913da418ad2e86c81e0893a974934fe84c4c84b5e14fad155a2fd27e2de0e7bfad93858e0e4cf68e013c7bcb53d6c0808fc30e102fab40fa7a4c06bfa3207be688abfea865b0c6bb2ed236751661f9885652fc3a19383c8825f71e8bafe5e6225d49e343f18765cb6964c09be81bdecb4ad1c119b332afab4626d2d92a8628c921eeaa9000492555ef97537d7f98dd8f8e866468465c07852edd1e2a7f16896bf588136fbf3864ffa9d246f31fe08bd154c87d053735ca7a0c2470eea1b38ecb2590891ecba4607cd06d70edbb44913463ea0b7999d53e96a4e112a025cbd052f2d9095ae639c1daa21fe91541426b5c27757810550f2d39f7efb5e37e9cb727c60e39a98685b06f7612308f2311eda8d1b803902ccbd82b5b1e89e5e4e1c415b3c5d77fe06f749ab360b25342e867d40bb5862ce294dc2b8d1adc4a9bd2fcdbb6b858f420c24d28012fc45c605b990b9533fce7f502a18033404202b079fb6dc3a0b483b21bd6039a6289", "-82d8e703f9e9ee7706cca587b4d2c64f51f0fecb2f632e748d5942775792f4cca32eda90f241a8002c55ff816c03c52d2eae1fa0321b7dc087dfc040b8b4b8ed509d02e7a062ba75c21e9dacb25d76573b07ea71601c5cf838f478a7979717ddb127722f31275122a2f4fd4ce45d474fe998f65047547094bc0e29c1eebf3454cff96e69d9ca40d7212c5287dc64a9e70772fdafd223a1a2ef3bb179f1472225ab1d1695bcf23c07db40dabb31111dd3d7bbafa789a3a30caaac8f8f2fce268da2acb4f1851745eb3fa027f4f8558b828960e0c4286a0878115f8171ddd0aa395fd1ff35bd1ae3819538d1842504206e5039845073c2df7e6aaf2190f3dc72159c4bdaa3ac26a742f2f5972e20ed1f104a9cfe31602b23178cf2b29ca5225613837fb92f01d68fec26b41aa37dcc17ca0527d3", "b67d1acf3e8dbad2c8654e7349562954ec287111c344d30aa1c314985424aa275a3e7015978d678f3c63fc570a2889ec0a47ed252c7440bd7c89d0d83ad15a7a27e34fef66f48da57db1168d8644425aa5c98558b959ad4bac0cf65d444c991eb72db1f3d2c8d0b4d076550366b321120d5f55a9241294465bb9dab0a0321f903c0b0b82b090b4504833f254d1f60f6c9a30ac770f0cd9989737fffb90cacf9612f6e46e97c620fde424589503559ea30fd306fc50eb8ff2ca994fa88287a793c91c82ef29d61da3536e700371", .None}, + {.Div, "8e050d7ebee08b7b9490456cb7a9837be2b7a659569b87fadf8c070bd0397d4547a830c89c731f61b377149d51a75d9ba181f929cbb1de65ac7ead31a38f312914fafa6df66d8215c0f62ae3ec46d5d4c918459d54fcf80b52bd318916189198fb3d4400d9083ccc28d6d9367f4796d2aa2016cc3774c66be7ba1baa393439d2b9549e6a9212547d0aa1bdd349d635a24ad4ea93ba36eed6d9c94b204d0e03ae822a3aaa21fe5834cd894acde56f87879db4212b3f6fdf705eee61ab54398e87af9ac58609620dc11eab1d8e65c8c91c3cc1ac1d5880d5bf64745a645080ea929a6a167fa2dc041f5dfd434cb0a95c774d8671ae9b47663467ef86ef58c00f567d7863c473af537e80ebce71d028a8d0f6028cfc2b92fbbc1867c5346fcf971cd7713de1bf7fc8e6a86c3959f40e73594b7cb2b9cb578e53a161b7e98ca5220373af3c81e30a945ae9d87a5023a3d1eb315d9ebf1b9c4e80a2c25ec941d8a93d36447fa50d12b015d2e037cdb169f59ddfe373edc7664e138cb5445f4ac6bb1bffb5695f41d4493fdbe6bdb2e9acdd20c38c3497f698803fa1b8c306f15c8818de5d66f3edd40e81072e3a1f7e355c4677fd76c5368190b164e5c88bd709ff4aad789234d7925cb2766d61e8c77926eb7d5741e234aa56465776e43e241a91b6517a26f053526aae473ca6caa6a74bbb316615901bff905362ba24280aa5f399", "aa16b4f3b707be853a2706dacea736e2039f4b0af49f1c928dff3e8f767bb4f3d029b5650b1e92fe3abfbdf0c9f4c42367b170c6e36ae95e7c0e8057f0f202cd4535e5e475b6f0a7575320a788059d6ef7c1a006655d819445d9568a661144875df35ad84620dd498c03a7429981e9fbbf449cdd2f22068fc0ccdc2b6ec114767f0a2fd4d22e4511ca8d15f2123410922b3b73bd4940382704c8849f9d0d8e4d2b9e6d81077fdbd87055ad77fbaeb6ab45404bb6c9950ab0f2dc1e83f2073c6c6f5c2e84fb31db5d38e8b7c0ef780c78c525c6bcd76670fc337d44c27bb78322ce7f679714ddddbe3a700675177f9c948d2140a1f4bfc8620fefc14294f98515ca2684892869bda7af61d19fe47fb5870c2eb393940a419f2e4bc3b68c78733100bd8cc0cf81a0b2cd08b13ade7401a6e66999", "d5c0e4a2986d8a2ed9a6020e6a4de31a8b310f01fbe80803ad6f2c3b31ca443e5c4eff5096d212fc6e1af1518637c855e246446283bcb6f4b9d1415ed09a0c911bd37b75e7f747aaae1b86effa0869949ff4be259df25420e69418e19d7dcd46382e6dae649ae83beaf3c2487a6e8ca571aa23c334556984fa9205bf22a0c1ddffe933c8a66653a6d0172b6f58a7451d819e29d00bdb37dd2e35f82360f0865d0d4ee467c0e0b3c61237c6adf48231a1e87752d3445e33ae08dbcb8931ad797e09bd855192b7d54e89ec76e619", .None}, + {.Div, "-c191aabe94b47c9d96275f47bd0c895c5414c16490f4c5ae5fc3814f9626ec1f35f09ee92a6a769e4f333f23597eae37bcfdb906ec70055eb8c92e2b2435cd971f02c4353e6fc69f4f1f30b61decc26086d1949ea8dca3f60c742b362c7a3600414e3edf60e7d27f304a8ae32d7fff0da27e08d5288f1e6d38b59fc88bd0a768cec73792d5a0323b6a2c88e891efb1cbe1d14bb5b173c80fc4f026fb4be91b51a09385d1dec4cff2fee60f6012bef17c5a7375e301f46748604a86aba44ea0d5797e23199b2e016caf2fe316ea98afb4626eeebb034c65d2c2eb81ab3856715908e462d9d22c8712515b0932be3d2542e631c663b24f62881f7422f210bca245e1ee3354752c24021d4a1d9c7b97d3de17f3a7504b6297766c3f59c91b9c1d96f2658c3e10aeea083960ec2a84149e62d78589b2cbc684fafae7eec00c9d8e533b232e15051e0248f963b2cfa6ddec7190885ec11775904afda53d05915e98d992dde76a62ae554099c648b434d62da290dc8f1dbd83498a64eefcbffd81cb11cd2a2a60808a011c62c2f241a769ae23dec4f29c0d6dee2ea246f12601c0b29f78bcd8960e8af3ef0658f371a3db0decaf786fc4a349af735d56cc5499ddf85443838f0c5ab18158df589c8b870f67fc4e77810fdbca2493c483f21bdb398405d8beb233406a342b63af05d7db89cbbb9ea2b4bbe08252115daf46d03db6dac9", "-8e88c825f3e6121f40d896106696cf15c1c913ad0efab87464e1af619ee5ecca2dc062a2a4a4fd33cde17311dd20c98c2bdeccaf10d6b6c5fbcb597f7f5d634cc506c435c15a6c08c1cb9e4e34ef0678dd85e893a03af014ffdc97b936a65e3cd308c25d9b4346d2355596ac11d8674f17dc4f04ed24da1705bc27470623d5e7d4589725d6f3e04d0c925c7e4eda84d7e8a2da52fbbf38e8b1ef760f91d42a546020261c4cb11381db4feca8f60614420573bfb4a6b745dfc9b7226a14e3e9a7d9b7130d17409ca7aeca56e4d11e5e674e13c5ed42b5fb61d4756903c106dfafb0cbc554274222f4c9d935301e021a55d4b96ed196c730df8de959daf06a6420d88157b6fa96ee6fd49f6d9717e5e988353e284a0c4eb29d258ada084827258950487654f58017b98fbf518b622abe64f669ef", "15ba94d8113a034b2a49ed9320e187a37d9612fafdb1db33f6af794ebba60524f6d08aa8a4eca96dd53a3168c3a3f6fb47b57437727a9067c52a9530f2787743b73d85603ea919060ddba5e9605db189cf78f0b830b7830a84f4e9d3cbfc4867bef253bcee136d4629f9320e5cfd12a4798744b1d371cf0d8ad051ceafb5da6f362823e224cf346bf2d5547780d8bb3695642be591c7d107582f30b36434d025fc0eb6ce924c7dd4cf996aee0182afe68b4ba61790ec308533b5fd307893f14c8da366633ad227242281075eda7", .None}, + {.Div, "-c3e671306ce5cb836d46c43d405c0d25342128d90449cd4e939b3d81d20168dc15d28252789ef29a9754456a151e56aeb33cd78dd3871d918cf8dfe17c4e98521f1e437331581a6c87adce9a2c7f5f621c25edeaa7f7689fa3a9d0c2384de1591fa7eba5798d4c6228f3f85db3dea9084dec66f22a915bceb7007da1261dac1c1f975e1ff1ed4934f4470a5119df62d23a3f242000257517bf717b1b8ee82acf348c11dfc5327b2c4d598d22dbe41aa30ab6cc10b82f1a8a9789c6cc8a9df372b34c1642c3f8cf13fccc1ddd292f63abc7bc39339a2bb38b505993b6775f810a39bcc908759f6f9a63ca2aa8aba2014c5b739299f62f47881f4c3c0c1a154eea6efc11f8c4d6b4341d2328e56dc55752324263151be563cd965c201944c45abbee04b81bd62f1d3f7d5c947f76551514975ef042a9408ef56018fb845711267cfe4a4f8ac99d3086c41b64183bd72be4fcd15e36be65c46bdc98ad792dc9d3a8989e6466a3679fd69066b478fffbd4dad50fe07e07acd46dfdcaee1008f9b9d8bc32d655a0c4986613a67f3cac76064f311fb1817d24cda4ba990385172ba02a013fe0506ff23e878edbfc64906a065a8f24eb4df52c1de5855c53d392663cf0935cd9e85b5d0da58fcf8e0524a28bb0d4448752d2f4195fc91d2328e7c4380e18e20e60ebdaf71abe6a1bb5abf716ee6aeefd5e4f1c2ef5824f4c619fdcd1d2", "13c102377884ef7ccf39716dc36b288b2ce4a45f5a0ec60955bc6d706aa08e5eb8f540729d51a111a141f103b81862fe2153dee9a84dc3cfaa15a9d69878c1e69cc6bc7acad31f4e3ec6724b1371ff1cffcf7eacf0d613fba40ae8c489215b780f879395429f9c7e9bda5e844a5b48327778c9c5f592ba5370cdd5d91cd80cfd2992b3dd5ae59d62767b57a1f9f13ad45daf5667e5f13b4c536c34e05343f7df992dba20b991b469140f4771350c300db6c6d6d7c2eb58a41a80460596b777f90fe7a663f4300a3a30df83a7646c79276ba13d9a542c6752209b773e0545f0acd4ac3795633c6b95bbce8c651f18b84d850db65428573ecfd8875fe15bad784e4a0990ef013ed13fcea5e35e6c66fa6bb88bdef1fca8350e32965e40ddad538ec97c0954b4afdc35efb8256d8e529b9ed898e4f", "-9eac1a49dae59b78e67127100240987b43f1e769a2361eb74cb86eb7f8d1e601095796736800d0da234817749ae252067a7a16b2058e7c4570882d3d07226c3fb67cc43504ddeeefaed2b9fe753f923a214a1cf9e6bf653cfaa1f7212012f05593be02c72797c458b7446323d7e80f6adcf5388ae82c15f269c8c09c44bb3ae77ef6fe4caebe19ea0451ba2c8b189db7a21a85e758a6651fccd01a9114aa2f6b7345cb48342eaafc4b0c26fda8150f98bff0ef81ed5d0cc6c77a5d5c63502893067ef7ec87ba56c85464949976", .None}, + {.Div, "4d2145aa20c8a283016c2ffd3e6f737465ad45fdc570eb81083755702ee51912f44a1907850545f426b458bede71aa3751098d5704492ce668d68aba07260602d4ad880695683a3070a5450bb3691247e799ffbe5777b1f20744a0473ee5b611a421b844a4fc3f1a3c0af38ce6b7dae4991878a78c42cc24ca11da8f05071a24f9408c4b5c5b89848a3c9d4784bd15396bfa8074f6dda27924ef0a5fcd3c77dc2cf297f73b7d93a2e6325c056e2efff387500c395ad5ea1a813ef562b64baf4c89ca80eefaabf459c19850edafb5f3a636a27b54935083b5b5410c5ae8343e2b5d9677c4554cd0e02a70406d8959ec2ec8c85cf4d09bc901207f167483b36426f2e3d1c9fa46d74e4d39bce3732a22d0f17c913d23360ef6a373184e8d6dac4cccbb44f100985c467c1e4c88ca53c420cfcc60c97a95a0f698460a4903cc24988bb8be8dcae789cd72fa0b4fb83392995e4b17bb80f4a45468cc60a3030f05247bde0a1ce55802cdadc9c717231c8ef01a7229120d01100a8af03ee4f5404a4c10374bc5d50c4f4f4c22fffc38b50570a9193d8fb5feacd124bf8189e8e78831eeb6b4803008d91b0a1e048c00e0eb0f6ea13ff2ad764be74295e640ebc7d8aaf0e50b0ebdcc23c7ba2099ce70eaf5f56cf6a186b92b8f78a8d9c6c57ca8081c666b9d782405584880a2170cfdcdead3d73de437f5e3fc4458bcd235b450f905", "d5e8f6514041a4751f246bec863ef2eff958e39e88ee5957b899888647022dd8fa1252b2e0ee838edd9ebfb933223f6a82140f03189709cbea5e91bf07461a0ef0230c11728c1a668cb9e17cc57d3076382dd1033f74fb6e987fe0130a0613023591cd9b3aef47b7eff9d18c96111eb7abaddae2e1238534f3c040ae32baa95424ea54573f6dd2e3cd861509ecded0041e5f439a3cc433fd1c420f9f33ffc6e8a68f539a87cb680c0eefa48e13407ad55b81380b3e80eac76753e308b9371e2ea6f4c38bd83ffc8a917c20809a56d259411a461b489db286d84f98d6c97f4e8a041c8dbe9cfa0ad2c472dec8d6624c2217ddc84b31302fdef829dd5152bd621722893dddbde66701ed6e001ff181a7a077ae4913b1463dcc476e6a9bb39533c899331bbea67d7bf29306a87c4e17433122f6ac", "5c4e7315d0724438cd40138a5f2b8b1ff22e40c6cd92b1ff3e39c7fee0655218b65b0af925c73e6c1161f84f9d20618320d79c29c35c73a637d559eac65276a65164741f1e3c7b09e19f4aff2b3ae7f50ce5d36225d6fd28eb4f4866f0fe0167bbd0469b7939ec983222e553537938af2563a1c6a27ba49cf9bab5bb299b42d898420e0ac177b6a46e5113888531242e44f24fc60af91fc053f988c02f7e5e65f223b8f3943b6ffdda2513d11f2c82ef0e8b359ff8ecfdd92d81d508f06cd1a9b9a86fb7a95c3b10a3d08e8380", .None}, + {.Div, "5ce5def4957566785749f2123c886311cd64eea73d30c0d5eb3020db0900d5007fbec8c34d1f8187f2652bcab1d69f990418c46d3124d69628eb31af6a0d48bb538858a6ea0ecf6a2030851f291f3dc6c23733aa2048dc170212314ced257d98529b7bc5768b6d27deb6899a918d5b63478723a8adff2cdeed2fa488113db7ced52b21b68b64304c3c37f525117ac00c7250cf7298ed2ed674d69af1e849535d1b2dfea98b152320181cd18b634a501190b4e220cc15d9f9b935dfd9cd364672d837eaed62a4a8447017d1168f35078d5886c5a3d89aaaef0b5b0613afde2749e69874cd0ac970c4ca26f2f103222e8182a2d250fbc0155bf1b916df2e535fa31384ccc791945417227c9862d9a4b322f836d625864fd1526dbb7d69b3101bc60e0ae36dbcb9deb08a3baa511d06ae130e74122ce58dda00846f85bef8fd488d34ccc2f44da528b3d695db247bdde31625edd7c53888d5c9e4759e6eafa9ac85c07d87ee00fc197b07158820c85c766ee5d3dc445b8e3dbd120bdc3728a1d78e64478436967837db62508b773759ada32a9317b5a4a708f1550abcfbfb46e94299483e871b2ea1e6081466d05e1a63872f218e305b509485a49e2be5d7487acb9d6a445898a60f8264b705501da401e5ca7b65471f148c566c1c2a56f33d8fece9d7e702cbafd5e84ff02f126ec0a4f0bc478dbeb410e3a8e4fed375374a659f", "-724c5822db26fd04d85767177e85870416b6add32e2b765b79abc0c81db62b9bb932e76047f50e01b35ce3ecc6d0ceda5724e7839ba948bde396525e2fec5332ecd0aa1ccafbd21c73d78772bba767105ee3838242c5b5d8de450a6ead2e6870d2c816c05d29b42dc22ae601b953071d3e87da1106df7d939d7b613063bbca9cabd9800c809a89b8169f08a9e16328567f4910edfa10eaee80d20af636dc75f61f20149e7d38949868812f5ea9754fac34e46d33f13dcad2f7d7847f62f972c663237e2959c80a61b83bcf0496e54dfcdc0c5b6759ee837cdd6d632c6f1246e5357c41dab616986b1970e991666fa76e7384d4750ae1db6d8efc8f12e9ee12e46986dc9588989a582d0b93a3f4d8697830cd357aba5576a1d0f036e0d1a76483bc7b6f3fa66978ef0cddfc8c4d9e8641bae348", "-d0118ff5d8c730dd674375d2f066280506fea8a0a71a86e460420c72df22e8f537dec68aaca4fa8b7a6bbb735708271cd2ff1de6fe6f4d1d904713dfb103dade10f6b9f755ad96f5e2e6062313b125d4b4e73ff28e261840b0e7ea6c3368238ac44283088dbd140dd4bac7d1f10ed8fdac35912aeb4fbd33b9de1a93956a75e3db5533e3ab5054eb5eaa25b288b497e7ae0f326611a865f3b8355193f9a8c4711ff63731a23b974cad1164104694e38595d81c9e5825b471ca2ee168b9eb39caa470edb8712a67b361127d4dbd", .None}, + {.Div, "bbc72ec7fee116b6d268b43dbebce8e4f31ce7decb6b67032da5a3d558f3abc0f83605be789a13bbe6239e8a78fa3443ff72b047c35606c9d0d65da0ae4ead57c108883db588e6c872c79e7b177c905252e941f043511993be448235bd0554ce27a257ef29d9303a3eed3bfde7faf31deb68c7644271d40514cd50a73c7bd9a700149ed839028b1d56f3c20be2332775aac391f0f196a4ca4b771116aa4d6b421b48cd698c07dd672bf6352b22ae042ff147110562876a8416c1cf31325ba5514b7fbe09fdead06f0b0147bafab817c4164fb3955c8d2556f4eee3a24176110010564a86535d3fb32c299774eac5ca1c401b812d96b3f576ebf6c08b0bd02c5f85091f64d906b9639780fdd37866759332c7005e6c09c05adbf32cd21c6b9b9e4f4bc532384b023633892a7fff743f9b8192ca0b3fa76127a64aa370c0aa0ea8fe39d67bb935ef0ec740ff11c58ca16aabf53872f43946aa5453a20ba2744c86beb010469f71b2eea613f9b96280e4462ef97ef9386d656034ee7341064c9fadcbde8b320adb785ac4eca642e2f907aba9dd125a3a89667b1b5fbfd407a6c1e63fd4f8820d21ec929fb16e491446756f4b283e8c7ddf31bae64d980c7952159abf74d710b163b3daeaaa81bc1b411c76074f3277b200112f56354450814c1fb8fc72cf2c5c6fba19dcd11e3b0d02517823969f0712d0c54dc50d7a25983a8bb7", "-140acd95b2a09b8ebdb6b18258ac699ca0ed964e6f8a4a3d005e42d9ace1bcc02d5b77d8fe77092806090f81b362b139eed172870e38a6cf5c6c359d1b86b045622e723337c98ad481fd876bacab94d31f4f6975ebf7e829e97a04419654934bfb5a5f215eca95c484c8bb519b32ed9f57b5723b3e5043a9bca910c55f6be5f02c242bcbde933bfff3bea2d2368ce4d3a467b0ec8e9aaa8d638923d444c9d1e1dff85f486ec5b8459f155b1874972a5eefb503fab5ddc31526549a49b36de20b8c828ebe6aa925afcd6a7a6ee33518c779b25a70d7ad9519c20987dee0ba957a20682043740a256a18d1ea2fd15e9b73b4162d55f4aa05599f7f194b382037eb18c7e6888afefdb64c63ce77330ef53b28b81a8da7bd3b124aa084ba28956a620b3a925a1b95486afc9611c8acbe859e91623f5", "-95e7f9512cbe4632d50918f93489a8916e24e04ce0ecb4d0991f71a1721be8510a26a15a86fe1cc5b207004765c3e0003bc516d14e86c25a2405cedad778a8ec0077c7bd97c894637057b1d10de365dd9d44b318d8f8c4ab190cd8173d7803210449d32eca751c9a1ad8a906beca51e9bca24d53f334fb80c770aaf4f5e7600b9eb4921b5818dc358b2d9ef199a0a2a0b75f42c93fa56053a30dd76a993b13c4aa70e87052e4798944255a42dd4d2130752fca46308b81bc215cb6df28f8ae42442b60fbf90df3920c57985000", .None}, + {.Div, "d9a93925d7df00f9fef51a9c3b22a9746e86f1b13bd799797b93f33c226c59cc93ba0e9dcf363318252a6dfc1861b68fad177b34605c51edd49c2d137e7252508ae7f3594fb0f86a6eb333ff1a8d40ab52ea400c1eb714c56f364b88bd02c9807c6fc2236d0e60617baea9fa05a2004841172a1544698ef59aab608f57d75d8bb811bcd10b78b8254b561b0f73eff7246c72aabb71c88d7d4f3f4f3376575247904736aa3c42b0a43badcc25c6083a7ee11a0c657631ea1e3753c01b589cf7a99170921025fffa02d2773c00d22ea6713ab79c0f8eab47565623f4de50c13631a89a9ceec5cc07cc80e69e79d2304dd4e5da1e87188d4199a61062d736813978b91fb23f9fd6588ee137827c87b9d1efe82d36062d5384b1aa85046d6fb68c53f15403c989ca535a25cb6079818a17c8ab42ac328612e8485289f5524d2f3f5a72c0b11f6cf39cc2d3d00c14c9597e2d67d4d74464b10ba4640cd12dd5eea5ddb81d6018629ea4248e77ae9f0bd561b86f2f1003613ee19633c616ae45e311c22930bce6440370e440cf037c213dab9fe4cc05e8fec00152d34a105c79e5c982af084d9a8910fa575422783eae7c7dc21742ef051921310fbdb0f9f13587f0c28c74f66d27adba456018572212b0b5d7e848d9f71d147826f68749fce82f0aec54a75b2f2a5963aa39b3bd9aa109541c5e2a453b4ca3b6cb21ac34f76803f4fb", "-1950238afaf096bc920189be7505f9a4a74343665691ef8fcf8a558ba2cc67e96e5a23385619f77d1f37e9c2be23936d48e730139046be01125ef3392b52b8ed4c74b53f1c9dee5cfd6d661fcbe627ea8e7cb5e2a8828222c8429b5de35668a022680d89241a891085bc6dd7c8ce032e67ddd09ed07a7acc820949b6ce1e424bb746bdf6582abdf117ec92c7c1ada7515a48668010b6ad251ffcedc2c1c10991d790ccdf504d94daaef18944328ee6143a2ea6aa0da54bf75247ba744daeccf2bcbdaf140a8ada615da1f89c8a77a26fef9d87fdc577bd646ff7999f0adb71e481c8d1b3d4af68f9ebc25ce26b427efeecd2f17e86391fadf8cc4a69357c8cc125940c1edfc99e4d0577d86597c71d702c8edc1c26dc6f40b57a2679b9c305f19f99577b01a86776683b0d2f6387de7a9528e74", "-89948fd11a033ddb3ce8b3ce6e1b5cd990e7f3d0371133f5493c72b35862837fc52fe3595d499743d44c2a85053f3ed1400966a44c4574b538eb595fd453e201017187a88f7ba3999ebed9d4f54776f90638fee9e00cda82f1396eb42efa52875c5b4d30f76dae383d0e5f4754a6f7851e59c3c899da89379a1aba136e1b64405c1476d514ec68ffbf90a5a732fadbe25e3fffc349cf37470a909d503d242f214c4b407640b380fc76e8738710eb9fde851dcdb70c6649e7b2d8fe9c38bde0f254a4e2a8add887fda533fe8e2c", .None}, + {.Div, "c2243d287d8f8f2c36b8116c736293c843a6221fd96c4aa44308259455063aa274b56476cc711afecf526429e23f3a8da4339f5b21b93fa03e657aa388b760163efa8f705c3004e0af0834c5d0dd7b208b69ac7221e96d570a430132b8eab5ab72a3eac7642dc350a1c9197b59a0fae52dc779f060ee16253e50b1eee792df9bd52412987ea0d9a3341060a63e01d7cb5406237f3a515d99c02e341e8818edc54156cf569a41af0c5e8676ebeaff156731184237ef81b7aca4f793ed1567aa30247c9bbb9490270271b40a8bca772d47093b4b2a09837446c330cfe9995c1754aee8efe78f8b905f5234676e2121e4e580a55b75d42766ba73ca692740f4bd2577e3577ab708ebde6530df355d8cd5ecd05bd238bda2da2a180016bf996d28f027b35691ed165e70d8d0d7d2dab601e485886f8f6b7e56df27ee6a5199331efe40c33df112404d8a52a0b0fb57ad7101fe0cb162ea2582e3e5c7261cc14eeb62af5b2876a136dca20b44ffe881bc8a177c60ddca7be34b151fc0e5293b436667a200785ec5aaf35a0fbb9c196740fecb0e43dc47cb6161841cd47998beccb33a3ce01baa09ef4a7506ab7ddadeafb0041abdd58feaa2322b4562e055c683d43a9a65e546e2733964b2d4e2e1ed1c4c62360fbddce78e8a62cea9feef48d912b54901819725be37c37197870c93ae6a505ad202c7fc1d314046ae816c476a04f5", "-11fa690e16c37b06afb5bf0796e18a1835f3f4163e4178838d135af9cb50362e5a0cad86ece589991718e75a5688d8a122873ab8bc430b9bf6822919ea89ce5d261c53de6757b246954126b9779bc34a12095d75374fd19cd8d78a8b1518b1c947df70f1c09dd79f8431bdb0ca4d5ff1f8e896dea9db93c3a897d60f9a8419f12a349967fe9809b12ffa8e45df1e05f254f5dda3b559afb40c3a67d83ed74a8bb907220861bf835ab472823c39399f229121fa93aad8c49345b8a612927a8729db035dab83a417b3a1b7b1252e26b532706289186fd475c75f673bb46d05b1890a130348034b6193457ffd6d62fb61c1082ee94ff0520ef137a91d5cd319aaf36f6e41ae8f8dce6de414e9bc128d86dfbae52cc4b2383faf60b01b7bfe9e39e5ce66e1a6f969bee91e05f10eab52052cedcbc7f", "-acc7a4f1cf5d0824f66b3625dcd05414ad9b86dd0fe2d86a95abe57cb9bced43b26613a598d1e405363d294eb30daef45427eceb12f6a3b919910928d7e4541f921d98d2d1371bbd794d331d51bb40c83e12263eb8b8e518436ff9eeccd76ecb7cf28b23e2fc38c269bafd916e6a103ab7557e10652657ba542bbbc8d4a218795496767566be1249480ac03505b7879912a6a61a1c5a7d2d2a31becccc8aab00d4562e2bfde49d1c7d21980513ab6ed28106eccfcb248857f155c5efecacd9a47eb1af175b71230f01b5dfa65a", .None}, + {.Div, "e4b271d9429f23f4698d610472beea049c4266f817efdf9080b1cf6eb13689cac67e54f22ee1c4002836a4aa364f6c73ba8a256bdfad6d4f9a32328ca871f088282ccdf60c699c4b16031de2622c404d4f32136bceeb70b36ffc1d8b22c7c39ee008875aca2a5cfd2d135b08871ba0ec3ee2499125bf474eb881f7a86629bdcfb33ef2272ea84a804b888ae59a012b99c7b3051b7a33a2e54d592c201eeb41e07efefd896a87b699d10a20e3fa0024042b5f7d7915d9e01c38fedf4a7ac231d404d2b3193c0049de45c3baca16093aab864193fae5cc40fb9cfd310b2dfcc1607886dee028ca76e912913142e70b4ff6c1d385430d821276f6faed30a620f089f1ae3717fa9eb057bb3d609bf57ab0e2bea7418656fb8e138da431a0c9b205145da66d024d1a8cb85a296fcc6fac6a1f89248a29388f6e3dcddbde7600ca3e1a260a3f5db3127007b7024c525508917e06eed208ad4c0d344731c3099c199a18cfc098e1f95bf5c84723d1771d30a87861dc190cc6c6cc32d66509036187903459083e0d8b069bf33764159c321f0b704b48f18c9d947809b60ec00c2df72ba59613e57054e19d9abd88db655c474569bf21a91add611cf659ce2431c6075c5f04d6b5bae567759e97c4d1aaa77363b8ffea1c0842010c9ec229096d7287f58ea96c043ed9d6682c3837f2fa0382c790387d78b6f58920c0ef6ade0d0e46a711", "-1278d51814fbe0c8e0127492f09a702c69c25708e15580d65ef373e6ee5d6ff3d39e20d0416eab6be1522d22736591df42ee2c28a66f3d680914026330a224b819f5354b2cf1aa3f79c67b72fe5b92afd92a70f821a95290eb9d72c29ec8f1b8434402786492a16739a3dce3601e381408afb5693a784e75eb8a93fc1c6628bb29e639eddcbd0cc3aa08af658acf9b8be3d3ce83371527489bae1173bddbe200a944b417586ea488114c925e4ebedce55491ca818c88e76b052607f3ca44529c656f5315ba5daef4e942b32bdb0dcde5986f43b3443e6a4780e8a7ddf4bb13d565b8c0555a54cdba0cb38174b047a6917915f1505dfd63a0c24898c4cdce56507d5bdcacc251a0e86e2e4ef03f4b135f6ec25dec83481ee903dfe92ccd502da7ae2c1e218b3cdd66fce961ff2753bb58e34ab9f", "-c61782e3f1577dd17072715d0bcfa25b8051453f2f2bcd34abcfe66f3af18ade144ea9b9df121d7e8665fa41e12345ed5986c00033e336e208e767b54a4526bfbab4a4b1ba68dcfc989ef783e8b97d59ca63ef27ce881fac6f6e60b59092548d430f229b536f7d734d29aca69afd2aa003a39d772e50dbd61dfd701c78f93c6fd382aa2916f379e5e3e5fb20b7fc91bf83387f6231f3a97615b16234f980d6b02b40f8c0424a1f8a9ff584d27765807dab1ea48615f2ed7a6832e0b16cca9da990e3b890023d85392e27f8158d", .None}, + {.Div, "-cd47b51cc9c00d2fff233f750aae606de253a81176c59df1d880231b83a6344f46b31711df9eb65041c417a5b9e26895c4e9a6151b539cb543e61d3199d09b6c626a8f0504dcafbc437fcc8e1cb0c9f8efa81799fbf7aad432ad3635d7a07f2d965218f9c8ace55bf8c25c2e27ddcac70c031bf4d6f3781b3817e4b1b2443f68a50cd2edbdf89ffa6314717619c499e011dd3856959921df130f934a195ec65cffe59333d647f4381c57e125e1ff0221f26909ea20421e86ce785419a45855a16acabba76c0ae248c3faa3fb8101e07875c5eca51aee6b0d77693554d246071ab4d345994c21b207635ed7aacb1766cc64d51b3ceec0c111b63824d911fdae36d22ba7e9fa55b650d1d83cb69ea1d9a2e3526ad646d4f4fd398d8c6aebb66aea534ba83e04b42e19ecb51357136fc1681dcac3aaf9fad8923237541ffcdfcc61a573fb36c7738a9c3c2a4dea4dcdeed6de4bf8903eb77ee2092c731be622f408c3810b40d69598caa432f50d4d0e07f6b88aa09176f2d0b29130fa481026f4f1bc2adbf3f98282154e00faff86061366e1ff5cc5b54b1b763d631015a62a90eedaa2f7b536627c1610a8ebc83a99ef7e7979700b81f78282fc9a76267d01a167e7404603a895263f8549ef04d41fbb7c0f3c7f9a865c97773cb45240532adce1e825b590f09a1f48d9e310c8aa0555ac3eeebe15753b51dcf4d7de74e25b098c", "d1c92197d8ab5a614cc1041075894275283e43d7222f053da6ef49a7a4a947d9bea93191aace2508ba4e1c7d9cb0b81b5167940eefa582bcdf7e92cd55f4d414a58012c8b47e23122167237d6ec1e20fa4f57d2e3181880bd3d7d17caed3940470b75af0e2c84ba306e3f150629aa2e08064b700f776ea224fc1148999b4086c764c1418bb9a03b6e41c5fbf0cb75785a505674ab8eaeab5a476cf127e541f7e794eda389f6bb4448b89ec0a2d6cd323e25be00ea53538193393b9b6374873fccd75ee4617368238bda96e03e0e6e13926c86a46fe44ee870efdf1bb0a056c0cd54ad5754ae8c2c3b792e05737fb73428f965e8ee9302fb01d8b0f6200c8e117bd9b518fdd3263780335943ecd9f150c68338fd6ececf4dd9b1ebb2e04cf96c58d6414dd239ada936b3070dce9cfab9edba561", "-fa807c2764755320d3d2461c2ce68a2a77c98ba8178ae48c313fd67c92868797686d69e99e3b74e3f7075c1c6a40b333b1f1828045cb3fdaf0123d8eaabb79786ee05238db49ed352788f25d31c755b35eb657391f89f24bb5ebcb5baa80866c0893f8904ce95984ef41bdc3f7a2fafdb527503380a63e2bcac272862b270ef95c7be5293db08b4bbdb053e68b67effa333b1808344858fa9a5fad5b3815a1189e30eb9b8bb787bc7e714cd3448a75c3d1dbf4242979810a879423f16f0e1b1fa2cc96b43a8347be1663ac31ec", .None}, + {.Div, "-fded79218c5c2f290e45addab1b8db44d8accf9485c27205af520523eb24a448f804e896548a1bc496680bf4c61678ccb04f00285fa3b5b3437ec88ed7a18fe00e6d37a66976559704ca0dac732b3ed659fecae1cfe5aef6e305c78abd442e2d20fd21277b88d64b36fd78f44464ca1bd5fc8479b4ef9b5c409dafb5857ab12ae3ec130a74ba2de1f5d7e7d745201445164e01d4d1d751b7813e065f598a7454026977940bdce12d65147e9eae53a21747e3076d43ac0558f094bed590f4d85d8fe0a98d85112d867ecf67e791092f1467d32c8fcd4a447a02a83eaff39a4b399daf0fe04a291b06a20c5d640386adde4dbeabdbed35a4bc4d7c8165b98ecdcc3134d75709544aad97625af343f14f747d32b71f36f71bc0a119e27028deb7d198918f502edf28b6a06a0fea7e005de397dda3305b1e9f3c8d10013541e453cc219d09eced358177bbb9d309de8098bc113e4ce56e1968a874d6927d8678b5b0606dff0078436a026930c81ff25ecd0c8426e257150b8fb1623abd8a4fcd642bb7a91904df23df8cda0adc4d8695f25b04ccac4e509db8ebbda07859576c77c09b7b7ad938dd547d1d5922e887cb455851602882bf9872c3fe2aa556b143f76c1f63faa0e2a1584ed3b07c7c9ef0f4ab002e84b6bf6d1c5604d67bf53fdd01d13ac0b416f4ca6443bb80d1648ad764353dd955d6d7308d3a97d93e5bd58721cb", "-12e8cb938fab1aedc8c0aaa51d005a2fb27e233135463b2f3f1d414faf8dff94d76a3713ee6d3f73e2c96c29160760014de530ffd66f9a7de4507eca02f130b0d86349cc253ef63806d8aeb1782e5ed7789040d64238cb6fdb1d7ab5cbbbf7d6d716eb5808b0f4838a0e273a1e38ba09dfae0c9293cb5e0911d4f0abf11d86ec65081be08c359335daa79045724bf4ef2350942e1f90e25e9450d8d388f207d6742b375717ed2627c3562fb0d5802a87bf3a39f64bcb383b8cf11fd1e1ca81e0c82851e7a11eb0497ccb0c9f9d0aef0728ef1791673e5364e7a7d88f21020454ddfff28e7c6075a43e1ecd70ba02298b002538562ec188ae3cdefc8c9e5fb0ebaabc09c784ea9e3ca6b896e5678a81d981c51b0f103cc9657eb0d38bb984d2a3ecda8de6bdb63ed3231a78cc4978b81738ebdde", "d6dbdbec244626795fded046b7927ef126a71821032ec8a950a2f9768f8c23a4e4055143630834ff505a5659ce8a04783084c06c4d922fad35d37f0de50ecce2556be44a3dd0afee291b0cd02a0d4afd1fe0469f89aa59b189b4ca63bbd0730a75ad9c6cb10c14b815ce91f28da69c6e122758985310bd50bff4af522d2976046c8fd2846748cbbadf879ba41ee6aa3f8576e195b1780ac28ed2dbc899628ceffef37b1f044d360278da7275b3ab91972c2c8bf58bad8894915ec46a2e94ed3a1b53bb306408580d8347f55d3b", .None}, + {.Div, "991369b8f00505b416477c102a92815a7064df65932b02611477ad3d5d2c823150b04d2cb5e7f72384e0310621b637e869fa6b61698fb031b43ed4e59bfd093dae1414cfd3004761e3bb16339716d67388728e3beaadf15a8a8ff5e536035a450cba3e1bc627e2f2064023a9c7c7b81c9b7f0f1ce47881a23ea6eb408b79381dd4260052fbd309d31c409607b2cd9438c1c0202d73b926dcf225a9b25799e834fe83b70f11e110c993650534557d49140aeb5c6c45e0b768a0e2dd1d9be39acce7e1557d19d43a589c28f81329f2198f1b8e05e72bd124621022e881fb3cb57083726f8f70e4cf56d7b63c42e673fe32c16614345ad6888bb60beb17adba718e770da42ad1af8c2534e8e66faaf48f73b8b1b7a14746e9fcfcc409607b501cac6e5afbc055134e3f4a27e870f418051229f8a8a388a087d060910d515b4d8905f0e80a858bc97268acf83f665861305dd5dde366fe30892bdf58806ca92373528001eeb04caa65ffcb7c2884da2d4a84d85faf34f2f3f6afa48f53ed65832042a7122520ff5aab7e561138538419f98bae99affe584304df4988f2811b2fae6e24941d3899f9801c7fb8843b3c56e39b380927e51871c6369ee92721fce8fb1428588389ed7ba86df6348533dd8aa31b9928647a5a4899bcbfe6af85e24d0c761d84e646716c663b433766a5ef75780be97b7921912d163e7c56846ba1930dc", "35f31a347907b0b13a92251c300d1ab4977e2c1f7a58274399ab31ca8f70af09bedfce972ce29b4f1fb0e4ecfe9ef7bd2b6c3196489c214d1be9ecef3e40b903296e0fd495bc8510896e741db83b17ed80c4dd5e591778c2bab5817592f9dabcc463666bcdba16399b9a5faae12511f18fd294590e47a0723c261399c9bf76e4aa9a6419e922305abaeff1e61dace7cd40300d8b65d0555209621a2d253ab187ed32221fa379b1adee41ec0d144710e4eedc83bd4e34438ef5384dea5eaa76dc837b44457f201ebd6a706057c1667b6b1222ebabc1654ab8157c6cfdda6b2c261924a3475d6ea14c3ed6cf011bdaf3b8e02983580c6214efc38b803414230cd5e7c0d44f1e4c09b69fe949a1d7d99b09512e9e8e42f0c2ac6240733c6e65c0754df29fc52ef3402a986aa1a78df2a5095e5a1e", "2d65edaf4530623aec2a468cc7f4c4c79d7a512dcd9e10fe926b12c8091bf44b4080a1b7ff80e83874d0e740fe44c7d0a72d5b8a1150f5d9dd6261a00e9c0eb636eec68ccb11b6ef28589da03df544ffb6247f44999120ff45477e85cc354b6a062ad5d326269c23411ac26fcd578cad5f392e7cdf8dc2311aa1ddc4b7df31a44ffbceb02ff1f92eb05c445297644ef630d6bc816bd133770bc3e3abb84420a0996b08df0f0729a386e395f65b5c9805a4028decc1d753af646aa217346c89279ebbd2023609b4cc4a40a6f904", .None}, + {.Div, "-8179edf73abdfefd8b17af9e2eb025574183fa5de8d0adc45da117268f2cbac692710d790f4745af6e940ddc9da670c4ddaa814939f3532fe58c699d8b3fd9d7ab34c9f399b9602d59126d0a913945e070df38254c9f5e560a942249a0fc62bbb319764b46509efa76a51c53a7abd3ab93e48434b679603a5840726ddc0e5926d990d31ef398b699884efafdf39c4292e733247ea53e95cc2d6b8519b80522e7bac2bdaa445ff2bfee763a8ec83868d9c1dd14f571aeada58e4e76097817e0f43195ec4e5de91d2e67e71990741852d2ff170ff19ca14e12385bd1b5687d8b107c5f7a5691969bb82759473fea0cbf2f415037438f1e3ad9349fc047b6f0f2736d8aa2355d0502d38cab9ced3f4406563bacba218b72bb33652d9e5b8f3da0893d1e4676652db53c8443e25f3959337a81f30e01e37fc9dca5a36c770a9baa5ef633a6ca42b80c580300be679956bb5af43e85906a7aec1f2d2820c6b0260336f66b73030d5cc07d4c47b3e30c27c7b0a2a4dcfc7b7470fa152898233dac7bc7623684bcad0d422af0b58f225f041d3aab26905808eb397f4b70ac74ff464715c7f9c03101a0aa23a7ace5033c823d30b3cf0999025ef6d1dfb3e8fa33c95c81214bd8af7b37dbf5fb3399ca6adafe5e6e6c425d69c79e2ece0cf1f5c29de1f84c5e0e07822e67717036d557e2547e743366b8faed8c44ab0686a625baddad01", "19d4d0c950bc28843593038ab2d00a8daf4b5b76bdb1a5baf7ff01779718a9d6c7dc7bb6b8f16905f73c27f134320a501abf03e504ff8579e7ec287c12ae915ebc9cf65e215aed208013f5df63508138d6b6549fb355bd55ce68d9e08280adbf9b45bb87a2f02af7c68db0c22a3ff03f192aa2dac04e267c1ffac35b0abd95de82462d1399038e0b3264ff679dd554ff277f49a846d6ac62a6d3bb4a4f1be590a081c41912e37790d3728e26b6e41d0810ea56b21d151ee676dcd2cc044b1322819203cce65b2f281307955f5fd6576ead943a69852358a2fd737dc7bc2364eb10c60a103e4fe48ebf63604d745f08a159335e29efccad9a88e80bbdd90fca16b1ed77e9730d81a0ca04d0e0d9b862790204d74d213db106b454b38092e5c7f9113341b6703528f5b2f993064e4fc05e5ffc86a", "-5032b2ff945280b9512a601097e124b7cc53f252d0f46d5faee8a16135cc4b2a45a646b478274dc3791f9cf60af8bcbfaad2af5bd5ba0df5e3c629f4676a4dd9025e9a690ec5a6a1a3aa32594b7f65f8ad259413f76d90dbcdea51e695d443466f00fe6c7b6d830a45ec29eca88b37d69012ef7eb65c4a0d1e8a95ee3cd5ccc9d730e3fd08b41d947131c9de0a02f0ff73a5977b6e0430ffab7888f317ba2af94e5696171f3d813d50beb0eadad767198150716685e5079825c602fa85eb1a5aef048920f8c5fc461be622d964", .None}, + {.Div, "71b883ca90800a1d9c24d5b50c7c1eab4ed159e9362a7a4f893c4230219503356d8c4beb5d23907100b58e8cc524c82f627f44d47ba65de9bc3e79def5a6c67b94a31b4c85d30301ecd9085006574839f54f62e41795675ad4d67ca962b7bee7ca5244b7dadf7f5a730952d34edc4cc5d865e61f0741274d75fba5d62d4a945ee468bab2ebfd8ac93d940708266cb717e516ab022a262900f4d554480c3adc3e9898332acc273794442048878b854607b1d9bdaf03c24d25bd534bf5f4456091aaa32a5aac15a47c2895280603da144c28d9dae7d53f0272f69c19d1309a2f31287d6f48c261e46810c6c8573494fed5a198f6ff880dbb1fd102b7c5963abb5ac7085986fae973bd95c52e36455f16b1e1fe520426ef3b7e423c670a648bf4e9f81d5ca5ea4c921f9c7553daacc498d31cdc82aaca92f5f6f3abc3e1ce254341398569c29ced41ecf8e4a2679b7e0303bb3a9b4359368457362c68becdf87caaacaab8b7238b9369c2389ab77e4b7bff13e251070b6092d4c2f3f6dd60bf1d6cc20b98465688b8bc5cfbb6fb236338a664a73aa3cb7f3bfea3824302a828ea3907efa292d0681d2b807bf86b51b3efdb655194155bc577687d805f6f38d7fc08ccc98be55f6b5ccd5fc2f8767371f2558316626267b792f25e47c6810608d4da2ddd58a659289cbb9d21127d317180e9c08134985a891dc09eeff6aea0abd56f", "-1ef626bc60f317e06e2814f839108a7a94db4dfe16402542299c8d57dc9a4227a4515770f45bf89b1f50858c5ec2889f842cd36b1606e1dde80c8365af6ef358b5bfca919417d411cee81494474e1b5e02367c57c0b4441a0852b37b285417a0d88877f3cefc1f75718820bde2087bd42d5adbece86043cf2c42aa88793df14d8ec5910c98de11d2f0feccc4c8435561b2facf0d3398d1c45df447ea135aa939017c7be084f987fd7e4fcd28405f822b15634d486cffecf343f3db6be953f86578af201df5aa92f8e50c82fd7b6de32699a670500c7ac6f7899f2f044f4305875b00596a75ce6e1b3f53a9ffbf00a2d5d7a51cf413ccbaed4d654367de8fd697d5cdc6eb738a4fa03f066f8ed00aba3bec6eb5c11ec7b0c9ce3feb40a20dfb39a38e5696eaab1128afdcea8b5b2a83839b0a7d6", "-3ac47c090bc26e23f5158a7d2640e6a66e4c3239acf9ff5ae22b456445ac41a8e42ffbb2ddd55a22f82eb9277724ef3fd54941ec8e5cf4a6277a1da20b522a565c2549c1682c36572da0230d0272062f95782697734d80e1d2829c1530c30a07849b21143eba07fa1720237d812095ba87883e91639c3a917ecbf41bed662338bba9686a25c7a50b1ce3e1a5848512073176ddb68a2dbb560afe4bddd772218dc5475b6774e44128659defd5193f4ad8d61445cdb78b2b991c3721f51945bf9bca770c61bbfd3019b056774b93", .None}, + {.Div, "-514a0727aff4101f599e0103daec994cab8810346158cd90f3f9dfc27b80c059d0c5d8f649edb108a2d14b2fc158fbc02694f5ec61cbac15b73592e234e55c38adc9ae673e86e8f97b0bb471fb24567b5760413693881dd47842dee754d1872f0b4948f92844003b2de26165970977e4b67bb10a0610dcd6da59a100d3aa25629d20fae42d99c814c0798d524ff2862137e39295e75ca3c623037711afa9c651df0b81c33e1fe31b01530d32cc71763ae6268ec1be5fdec11f2ee3ac2cb53a77195c80eabc780c365ea93ba2e9228c9ba86362ca84bafe78808baa986124ce203ac9a2def1470c701564a6d080e6420c1b6030b0382824c1cd7e921003ef5b124853df32ec53d099602c94ceaa6b9864c82464ebc9326b323b69191ac8a2be7c556d4f0c1879f02051f28eb9f956b2389e1f67631cd70bea14c57cf4fc219032ac7e47dad7b483a451fea60e8d46fc4e7505bf1b2e563d55d3052a9bdd6e656ab82cbc23dcf9450a162843bf2cc2d78ed2406fab34dfddd462ad741e62c0c809abbe584cf8bec0c99be16da8a1d79a5986acf7e2ba2ad4da624201bb72911fb2fd5055c976eb752270b99c02a73b8a7d7105df93fe7bcd106f8d8225ada1f9dc1e97a04d5ab455c798a412bc374d7d1b8b5ad7b709fd61e16a77634b2faecfcde8b06a1abe1c32292416fd6e13c496c7b19ce6a810ae1da198df27af6ce94617", "-18d00dcb337b61dc2d50832a8804062413658fbb7b205dd8e649d25701502ccb6c7937ae351db72fc50ffcac160ceab056cbe7c457698265d1e5b6918b17ec443ba38526bed30465963bd8076043cb37c2cebf012afc1c965a81e25102fb7f834205965fcdc63fe14e7d976bea837e3734e7e716460b3072e5866f4207ef7ca56b5ef752faf475e29f5ba48fdd7042e36df44677d386426597285c5a6ec20ffb55b737ea7e90b7db391ace966fddc632e88b565b98ef4aa98fdd8f98a5a322cbde7ff8ed2a14bb7b036efb152e3fcc965d5a2d49850134f3539ab7aa5af3ca08be4a86ec6bdc54ce286110d89b87b7ee4433349cc4e69f138b62b2e5065eeee4cf1713f7e47b7122fb6110e0f01d43ebfb74ba593b70389f10aa28de86d9386877336dee6903e5e15d865805167a90db8a994b2", "346af26f9c52c64e641daebf6b2e5b420a885608c229441b60a6399333ae9e886514902716117c0323b82d24a322899b3a26cfdc17c128bbf5f87a20dccf2df1d366daafb8065c7af0ceaf1d4f06b979abc94286867c0d6e62be24bb0863a6d121806abc1fbf174b109a2443aabbac5cf4259d95c2db1c6fd6a67b1fac48117c28594c7c6bd7f433a39706bd5254b94eed83a8954cd463a160c770612926c518d0622a0de970b6f98bb8a9dcdf7970d27f630bd82da823255c7a4a3b61199d04ab3eb1a2b9b7e57d52112913cb", .None}, + {.Div, "fa0890260bfeb126cf891f3fdc1c5cb45ee2cd10dd6659ab1b95ee3edeef69764eaa55ef2b29bea235ba5d472bc7ac28534b5b9b562d45aa86494e8a20c2aa48dab2398c12c1deb7cae63ec9112b67366cdcd79356b42f03fff0870d1e61fadf711c39850f1080a14c96d9bde53fc43b6fdef81133cb076ffe2eefdaeff4d497d4cba61528f87681d23d00366a7b474adb090b7c1e35ea581010cb89bf0ed2aa859feb01911426ffcfdb254c2349e26a9daadb8f9fa8c127501251ff86415550b6f584b090d9def42e343100237ebc3471bfa594e6770ecee1e0c88e449bfe17e740620d4b3c4145d98bd69a9a174015f9a11fa2fbac0586efbba3f91b8c7cd6626021b2db253da4d36eb8fde15abc89b3e8ea2b573bcb3cb63c1181e48871ae60f2dbb68f5060a6feaa4bd7d206717e6c299c8d6119f50ebe9474a31f0da0254779018d8131a6fd956c98122d0ff77e4fcf056c7547e7a0bef76dadf20da6aba7d7d157f62efae91f1b0a9cc1823600ab964ef975463371ca603f807c0bb909db4f3400eb76812207f55467126fb6f72897df3acbeda9336a57d0de25d96133b80f3f68ec0eb0c527865b8a83da49fa16eb7b6171623ea16a4019e997b21da26dfe3baf4f83f22e1a4fb7f6f8ff89669adc198a87dc0a4be99279a3668eef6acf5c470038697a35474ba94ecda1a51ea17c31bd5371459d25e515b9f16f1cae", "-1e5893eaedd07b52c6e79f15c782ab3074ea976d414185b9a506c3cb538cdab025dbd1e04c1a014634d4e65413f4455249a30e7548bf7e4052ebd509ebc400253c53527906b97b91859a74a1e4971c0ef9ecb849a2baa0eeb54fa5e417e4e30bc00dfde22a18151960fd6755d3d5f912b45def07f26b93342376f4c5685fdfd28b3a3c540c1f65a13529ca364553cc8b701725d621549bcbb1e0f53751acec3f2d9bca0f1006e2b28d3f0c81bedb3a34da4ffd09fdf259c402d9535b5531dfd155001f982b1cc41c0ed8946429b48a2c62a740e901957e9bb97e88a55e8f1efe4f5a689081ed8eb787ad2e3e9853c47c3295456d64d0df6f52a03a83346c01049f727fd7b2b96a4fabacefe65c6ac99d6b67aebae9107aea9f036884f990ec6e4d75bcdb6b2e1018de2f17968c48dae4a4bb8df", "-83d4a869c2e688cf847be6cbc564aedd34b0de327f7eb012ad63ea343bb4adf9801820e33b29bfc3ca8e0b3157fef1e3e1ef939c18a3f91bfb4e8a3e219a1a910152317f026c30f8f47c4d86a3bc1935abfe4533deeb55b687afefbaa80a2544032566178d77942a0d6cf5a98ecf946eb88711a30858228a9cfefc19a3f067900eb9a9bbc9a238ca00dff3c68af1603506668bb806f7719ddf038b36500bc6eb0c581d1e663eea877131dd5a14ad13e17bb71eb9ee15a85f47eb9ec3cf6b8d46e2f5d397c5f849cc5d1eeec4c2", .None}, + {.Div, "482aa0b501b51baf11b68797a234b32c27fe36025806aeae194203bd88264a078c5bb0e0e10cd87f2310fc9c2f0de4eafb4ca42774d9ddc71992964cfd2642d5a7fb8004559522b30146a60940599c5dd4a74a7d134935560d5a3a6ad558fb791a23598a4395ee2ddef7b2b17f51c5487ed19bf0d267f953a413d566daaff73a6bc91f5f15655e919e082ae019a771fbb3890504410f5feca2f3f9d0e62eb66c87d584af507bf6f3477516db7e49ba4d19777ced69e26fba3710c9911cec092671899337a963a05e06bb8310f79b67ca71c3411a62d4f449be1f0797fa65142c94a552af85eca4da5f31f35ebee6c080fec35be09f8b6070decd583774be75a26d2665166498e42bc29a36514961ad2efacbf6f3da7be69d4d2746c6b2d60856dc5dd6619a875f14796a6820d553d3ce23aaf190d6bc1e3d2cbe3c7b5e176305b4678fbbab7bbac1947913ff891611a10329c572dce1cb5218b471b0fe5a6cec7024fdfd6e7005b956b232a5445dd6f34457fd5df035e3b6a2ed781d77c0bb98509e17d70af39c2b2e1cea902d1b574c36081799a6c4ca7294651fec2e06d7a151e59d5d74c34f115a07d5211a1f5c72b15fda709363183a159471f344288e687fe936c626fd735d878f3a33c34a009add194fb6ec148929335f76bb5d32ffcf9b8b0b1f06c3d874d2792cd744f638816615ae7eaa14fb17e6fd39a655e9b448", "-12ab264a3270a6d56b520b6ccb1ec4b794069ea7f5f4a3803e94a3bf2029de0800f44a4ad52d7d285b14254a2c12c02142566e41eebe0aec8299bb020386c02243c1d8880577ad60e1586e3e0aa410e434f76a65ce30c6f53e5a9a2b7b37e2f787f0f6af55da1f7c33ab72e0338f5631abf103cb2aad82ab8bb5ea7857d91f7844b1876138e964d4164b652a10b28150706e2c3a337523fb66beab7fdb6590c1fe2d2ca43d59828119d1b58483a8ded0cc2a525902ca8df4326ec744306c9b2391525036128133be3f0db7003d22fc7c6786e1b80486a102e9de63eb8d3c3fc34badd746b4f3e67fd857c3606e9e3499d3fcbb69671be8690e5aaefaaf6379bbb499af6b899419996ee8a087d9bdd9cb7d0257d4d21093bf598f3743ed89b84a8c603ccb7501a98285990532ee8aaab1e3ba2db", "-3dd9cb8f70d62c2cfb3512488385275e5bf456a225a79314d24c1fec613fdae070b5c78e77140dfec625854ee618caf13c83f543b386d6ff1acf7331457ebfbff143b9b2397418102fe9ce600cba4efcf7d38bf8f0d0ae4d2e7423b051ddfcfe51df440f2983682227398fb3bf973c44f8ac59bdad7f85d15d84630721e794fabd06da50b8967b454b14b927bf032f6f145c4b105c794e37e28489f31b7e889c9251676b6cb7db987bfd7a0268cd244a645ffd620e56aab4575732b0ceb7a42a3f20afe2826730ff3e4f4b92e4", .None}, + {.Div, "7bebd0c1c2556408694e80a72f1561c8c5fd4d6e1ca153028f0321e4911643e39de9703ce89ee1066404e3e97d94d84f5e968dbf84742c2826cfa35c57a242c60a5f0f603cb1193488e647300d2130d974b71faca98de9bca1a78882062463658baa807e0f815926842712ae65bc486c9d1abc805f477e079c417e8aa5c12f9da7124ad2c91b2e8693293399d649e5114f75f0e1e1606db838a8f4565255b74ef0278ec20c4d48fbbe61ddf572fb96d30c51636da1034b758774154f0e0c2c68912d81c0e709a233b1375ef23c2589b37b6f5e8ffb5b66eb96d4b875de68859b1d861309524602f699d31fa46c09d5635358a860566c2579e62ab48597dd80046086b6a1be42e4096c2ef0195a2b4bd6ee481f40023380fd1c59d8d52a3305be7c8f2cdf5c1189cf134d5c3af8be62ec90035bc8f3aacfe04c6148815b61a27e9900f3cbaccb5ebd8d553c06af732dd6105c27629b1ec583a039ad3ff3e0259fcc285d241adfb67ed3dd690d40ce389f89aa5f9391774e4972a40d8b5b9daf6a5a26c768ee69c4070ba9c42c282bda22e6a1c8094469eecef1623c5522cffad985f1e2c375f6431d6e164405e632fb7fc190f280207935c8267dc062a8ace3aeb9db59ecef0ebe2c855ab56e26c56a1fc1e975d6a278fa41557fea317719a7e82068264f3151ca7d3491d6659d26a493db97f640c6b0202a84e1893f77d5c261", "49193f10902972195cf90d0d18a3bb21c9cedd8faa8f639b0b6223d550c5fdb20673d941306def33f7ad46c13497745e775c26da8a101ed212833c449b3f56766eaa2361a0fc0101187de5e8318daa824d3d347fd594a1d394291af9c816ef8a3573729d4e439b1446b6504f7faa1636c5a66b99746f289069cd65a57dc9585115a16e80ac1293bee290e0dcff6ccec60090e6b679b48bffd70a780b1204beaf6ed58372a1abaab6cfd2acfd9971547a065a3f26cbc47986f334927bd214f72b8b708695b301e97841c8fa2604ed928b039d04f0aba0b88e6a8797c976622b70f23959f9a612e71327d62ddb66c4f9a2fb028a3d8afcf2918b266eee4be6e00281c30ea582b793132101eaa5f81aaabe175cab10c0ea095ee851da5e1c048801dbc2e1c6c7a2807d1116053c7eb2d79525cddb", "1b1fc8cea253821bab5a8f1daa201742e33f95d6613793c9ae8004a2a79a5f41a0bb0f2620effc22c45b46edeb4f9ab7c4ee9f149aa5d43f722e37bf7a56fcf4f4732ed41852dbfacc5f303b1ffc294abb3fcac501d07fb959d772af970f87cdcbae95bdcbc36e491b1cbec3904d9b9e074b637fbda049e71678ae9794c6deefcd7b76d3c309ce06ed499e4f418d4024b5796d99e038fa4f58608286767ade99f38591041fddb1adcb3e77ad60eae28ad2c14da6fcf12371efdc97d3b3544c8baabbcb0fe502f705adb49491af2", .None}, + {.Div, "-9d81324d600b6940394283306ba72cdbb0f15210f1d28a788381539b12f86939d01f0fa30602bacb15e6b35b93a05eecb92ce5b1c26c985169ce2f5d0cbc57f9fac2e8afb4244857f6001c463ea28d6261bd0729a9317136ed2b23944c38413bff32ab9667f68c28563ee3fbd52ac51327dfb7265dccced6aca131db1f968b387b15eeecbe6d9c166576b2b67d97e739f9317e4c7a5a531c29b2e98de2bcdd5b8abd3b20fa965b8a26378b21969936901d22d2e13f9f71aea5780dcd3dac616abe6a42d7fcf1e4fa749836989e42113dcf549f0cc44ad6ab127b04e2708e8f295e9350e9329dabadde1efdecd42bab34b378e6c65af07892a0d950cb9547093c4b1b9e140bd6a704cabb6e90a9d05590c1a37119d7117d6bedb231bdfcd991af0a1bdd143665a82ad607ae86c170447eef6c3bdd817ce648fa72c802dcdb465fbf67742e3925ed30cbee074f47556a372c9d3c7de4ea029888aff40db3cb76fc1c0b7819218a55dd5ab56265ef98fec108c1f95bd277d65258440e3db3ec0ad0ba33550c9426aba363ad7cb00d578b53cd963f284cb416d6adda18ad5bca47c0c6fb9c807ef41b8f3e88d93615ff43cfba6f71ae405ee7affbebff00f64760b4fe14468dba715fa7288a3e90f837e6a648f0a204f384c4da028eaeaa34abc799be663958fc66b940e6dfb21c03734ba669b624d24a4c98fb8076d938c34b37e0", "-1c74893ac6fee237d3733b520071137f7407440265f912c8285abc1bb4c76334a664dea2cb1a9e26a2cdb3547b316d4fecc9084c389717f60a4e43c5a18c23f88c0b9d607416d7170099d364d9063d61f07b0e303f7c0028d11a20cf22f7f6de8c169cee7cfed7d671b7b4f4cb2793c24fbd7a2d2df91c9b74722605054840864e8a21919230e26a2eaf5ae486882c332956ce15e24538a21ec03155777fb74dad59f4c7f41349924e2330552d28c1ab7bc2dd04002f16819e8d4a0040d0465996ff12762b5b85bded3755305a2e929f0fb4419516eccc0bec30862dd140acf89f2c9c8c5dab9956ee2ab2cd1900d95afc4257c14652d9bb0163cf8685f54fe6934cc8342fb3000cab54a4c346ea83fcea03d62b07a5a32db288999957506071350c17f93fbd8a553c4769a754b9e4ab0bac3e9", "589015c4d86b7a8e5c7a37d87ec8873630a76170b213d74782d7d9e67abd713d77460e954393451b9a673fb2a786ca92468aeda0fd8c67513d3e892b68ac995ed771d3a3606353bdec5bb8cf3ca966a7ebdbf2e8945ac9c0c962f695f5db76236d6506baa0b6a13af8c8ad0c6bb2a4ee052016cb1a73e21296f26ccdecb6e581e0c99ffa593f8efb02016e607503f40c30133e4aa31f5cfe2283226fea7fe8db1c61fb834eaaa112f7fc392576ead4ecf49ec36959b936226f0f610a9220c1d93fe4c186d27c87cb71b0e30995", .None}, + {.Div, "-e31b5cdfa9fb3c0314c969eab62ee4967f5e0c1bde79984667c2ff48c8e0418364363d39346ff2b12f5bc30d957ec53377650ff8d14b5208dab95473f48df7bb93e82db42af0de8e1e3da1b314f16aba026a65c9092f65dbcbe7861a30d5bdb79540aade9076917d375aa9ba63db3efefbbf1ab0a58689cfb63fc94aa3236df6e7e4a738bc996b0e04d0ce54498f40c9764cfa19189eaed070bfcd49f54a71e5dfec4b4bed140dbfaa1b2069d01b817be1963fdd1ecc03c3b3746002f524852c4429fd1d25d22d678abd5ddd49835909e7e1500b5dd43ea909de3ccebeed6c439f4e73035b5924b0bb38e5505db84cf052729a19111fca3c9e9b4c4eb4ce46eb14149d7f6466771569bb5007e8c2a388285eaf92bde4de04c343c13d75c5ce80be5f32969eb6f98434d59b484561ecf6d8f1f3bedd9998cbe51ef24f7a2b9e0a04f7711a488a05863186234111234284c6e624d2604989ca1136d74a1b7a5db97f8855e443c17bda5246ae93b1c378c1641ed5f809f0b4f142b624e440f39c0c5f3f464072bc5b658e08ced5b52ccb5857a080e0382aa9274ffca9641928ed85d0deb85751b4f3a184fa46090575a4dd9688972d1640604bdaa65230204cf9c81c9ff5f6a4c26bfe1b438b57ae3e7c5dacf2b9d2edc7122e2684712e245563004d7b0838ce572974077bd07e4f0645dd70d86ab1e1ad76dddedbba4dc81cb427", "154bc72f8c573e6bd9ab295209c860d33f05a2ccb15ae0b2c9d40b4cb51ed8b94cfb44f7a9db20490ee5d7e14983fa63a28f08795619ec192a13cf9f177aa2fa8d9336f218bfb11a1cc840dd2450ff300a090e6d729d0ddc1b4d4a3f2a404036c163a44cddc71789754f5f004e72fe451d6178dc76dff763007c12b9a673bbf51aae8eca37e954881b5788007a288cc64055ae8baec86ae7d45dce1bf73a74e753fbe777709924e10100fb8fbf06417aec6ce2eca984f8548f1e8d56b80f16e71b2c83e2b4173c48cf5c152d1dc1aafea1d2ee5d5ef311b514afe1282eaa7bf4c276b0a0a1bec36888ea3ccb9c5f757df42f530c481241305acb95c43091a257d95a0dee9a0a43c57ab986b9be6efbbea48136a85971784a8d12f986434e79c9ff1bf6227cf0ee6a26f2a55ec8d9b35e61e5932", "-aaa0f27b905d80802cc63c6a771dbfac602a48b03bcd836730cdbf761a657f977c584447d243d4750e3228d07a137be9db71644fae4865dcf25e47059cc6b0b9f2049bce8d2b4e783fa8ceac66de5c738588cbd2fa19ab8310b6f0a787f824d7bf753e58f1d50c55fcacbd535aeeb15101600f698e5239ca789b243703931f135a69f7cf134ec7b5569295bddccda76cd39d60a5513e8f9fa1f238e6979d037719f3b3711fd9243ff8175e324e3170f5f71fcd658b681f939a78c39bb537800797f4041cb65fcd8e50bd865874", .None}, + {.Div, "705ca6986945e42c196c0d8602a0664bbf231c50edf83bb34441c2aef0d01c7e7864978bcc3c217ecd50255ab72c0f2bb8ba61b20f79281ac350d61e23af478ac7d3ca16f6d34ba84a9aa53e1d1ee56f6498e342983a1ac783338a8a5199c3849fda735900c1a88f6a8aef59752a66b986c1a706e9e0f1ac4c610519282eb0f5e3eccadce6a69ca7c1ea26f5673fdde810767ff1b69318a3596f37fccd0c000d6cce88947e20dd4e5ff8fb57b734ef5500ddee651145c0f1291e6b4dd8a98b302eb48847342ffc095748f37884534a5c4d97f22a3cabfdf89d2fb1b306c312e3f5f1f4c8a317cb9a4240bbce74dd004d7c208238b30e5829a4b10018c184dad87acc62886fcb9d92c81dfbb9a58f6e6b010b9a6b05c48da62c75426e06a0a38e3f529aa49ac695d0559ff9ca226f68dbbb2943b251724302528e454780ab9c8c856d0e3eba6104151bfc0c0c8ab6c27ca9d6ebb2a86c96c82e761359ebd75293eef89d25d5d26b4f8b0e1f9d0c9caff9929632cde1e3669a70d867a1cb96d9df09d6572bca3253c8c7c7c53f9dcc8935a3d952ffa4e34d23ea47fd76b2952be18af231883c46dcac7bb16971379c613bcd1a03c84c17fd3dd3ff080efbb982276eac6f14f387ca6fe0eea539557fdefff5edee38c0d3f94f13ba0c9025612144fef53a15c876d9c83d32e04952e89e8558c2aa7e72f50b2ed367faf160acb6ef", "-5008a2a5da46560438450670b053756116dbb47a6a6a8f0c1b1dd5487cc7b51ad4f2d813fdc3a212029c773409dd983f10f9974ae2e83401f83876d7fdd9b730fb69a907dd48297a2cffd33e3e8f3a8ec0c01bb1a7221e67463019b3c58fd6240214cdc6b1730793799576bb766eae9e703996f3c0107c69ebaab93f88845d4cf2cf89c3ced805d882b6fa358106629064d7813590ce08dc770e2af19acbb14f53732eee04807f87d1bcd221950b025a1237c6d24550ffa01ba01e420028417cbc4edd5b29604dae1c310225110037e9b11098ef084a8a37fbc07996709702fe1917c31ea26f0d941a0192455151910af63ae702f5a25da2b69e02c9d92dcee158ff04f45a6abece3c99f95ae18ec03a5f41a095ab550edd3a821f0b4ed9c7cbd7c302db5b6dc4404268c44c948db53685234d", "-1676816633185a166b19f5f536a13997224958a4061c4c60b72f5ac66c6280b0296d35bdcb3a41c4bf04cc407d72d64b5b15de003e09f3f99f470e7fcfc49c374f31e2c5eea507ffb2d4831eea7dc17fa9b319ee04d911543157362971ae6a57f6a0d0aa453b58ad76eefdd4ebc6cad8c75d58f8d2bc1d36e61cff1c39fe01b8386a683fcfa5366ddd0e62b7b5613e335a44186d4d0daed0b94c180d25383b6b1451ae00428a5087a49fc57e271315b268e091c4a8df261775ea664617334ab9ac1975813aa0715421778072a4e", .None}, + {.Div, "-df798d7c9335da6cca30d2d2080597fe8d61dda2d40156895e2c33d475376c27ed95322f3bb57d772ce090780992a16cb83a779d11240826590da875c1cb74a9704c8a96cb20215b5ef183840cf9220e524ddabd744f262d6bc0fe218d76d3eb389d71f523f52bf875d43d848cb08fa852fcbdf3d54bd0f7e2e4ca681a12f08fd53a76851ac4073ac2027b09135d131a0c2e47bde5965316a076aec05b01a7c350164df22a88c9f66eab392678f2e389db5ab487cfd949ec36b159fcafb4da5eff0fd054a31ac32b6df733a8967bd9a57e75e4aba41b40c9a09b5f3a45adbc0335baec40e361490292d41926f7ae2f81dcbac6ff2a5cb9547650c6a36ec1145c3eab9b61ccde7f0e8a7e8a6cbe03d4ddf829c66607c75b1e620e4ff7e0f302f46144cca858341f27bbb9c7ccd95aa7a83e332af0de4095c08003909b4269c965d45f438291bba019c85aca4276eefc542a76d3caefad11d266abb4e2fd125d69aaffb0807966dedb19090568a8299c1e148f5b1ee4717f8f6b992ad0a42aab929c9dcb80955e9bfaba5af09d02c7cf3cb34e8d70cd422c693f0a0851751995511ef7547dbbf5a690df1d51de95f6e49c2a973f51f1dd9aa161efe9c42c1776c85ab5c4d3417c4d643b3223d1520ad256b3dee80d61bd15ec660f0f8b4df136daeaec109429cfac0238c991102b6fad1241943e3802a149805b35e993849bb4b", "1d60465751709c9f072df4ff2f31aac78dc2aa611c6e56b6bb74ac4c5b246d35f9ce23eb7209413c348a5e63f0d77938184a79044c3111d2188c1d6de1f307b1460e3ad40a37c371f6cd358f915247125edc18c7e23b7f08e72d38539e360630548898d204888513ece28c6f7739fc5f6aad0c184848168411e73fe369e7e461c8004b4826b48e1abbee5c54c0afe9efc83563877a637c058234f76686201a4ea38362be74b9733afbc15a827ce8c5bbbcdfe1a1e62ea754c6966146dac644056d3fc4a5cabb9463a0fbdb34fa702be26d28eed89a38e92d6964dcf26387b212efb3d0ebbcbb3710d3d7641e80789a3c89054373678a350771bc7f911c363b414284897ce6e708879b1bd8ee378cdb8cea0568bb7c32b09db44b4bfff0cf0ed16933ab432c2a2249643bc33e8cf54a2d9916d32", "-79b7cf2eec450f9328af9a2c786a5fcb56beaafde1b0cd66c48c131e032bcfa7227b4489f6d1f17bbec52c94bcb508673f5d0ba29e981645d8fde608872a34674d9ab0813c633ea1ec6add54a65723207e677d9556262666446803e7150ade4de558d79e33b3cabf3fb2a5c6f715203e1ceb3fffcc252a419660f8e8e9c32da91ac98e63cfc59f1eeb0dedac99357466197e147a5e626ceed3e68ac4ca73e55d91adf7da6e173e06bddb562382191b5e15263a5824cf9faf41dd5bffa69ed9738e72426b6ac468ba27ea7fcac", .None}, + {.Div, "-4ceb4a4c5d5125f3216701a1a5ad158d829b4d66ad210ad07323ce291b112dbbebd7ba0b1a60b6eef4931190ac190d0c10c076cc87da9224a974fdc739609563fdf6c9c1b5218cb0eceb7aa9c3fc976368d744a59ec30bd9924918c197bffc21c56c3184bcc0235cb2d0cd0dfe7197fa6da9f2c9ba8b23b77fdc9b58dce9f74eb31879446f54a83234803c0b92b1969f4df72d66e05f5a651b885fcd96e230801b35833e3d072e184a6ff76eb9969a7a254e97a30b1bb7958339584d659fa5fe636e38da26dec75257b5206ea639a0fd7e607e16f7a30671c62d74dcc0a0e9967727e640438e2028b6c17a193b69ee5bc29033c1a32eb31681a3f4643cb732fd645b825b0ea54354347acbf26e8af47171cf8477361598939a1f382e729e185e0764269c194bdf6eff392be9ef9eb4a604a12f392172212f4725c0051273954e6551442bb78fa5381a27154b8a342c0e327ee22bda8de844b1f980b35a03853dd6a4ffc71946eaf4ba5bf3b6e2997404d163f0ef9d41896fb07e4ed7964e3c212873531e3a34f79726766a958bc1bc631f0681424a2208e40436f3f2801449928902f41507533dd72082ef0e8b29ee28f1509c70b36edd4e68ae6c4d536620cacd3467b07c1b80f39f6f11fb6f699088bcee0f96ad9566cdbbff9c3cb96b9ff2d40e140dc43a7dd1f5885b92b936fa04743654aa9fd9b1d3759f64616288ded4", "-11676f2acf7054c5d49e1127e8affd540200fd74d742ea122b1c49b61e907111142cb4a989254e41ee7ea18bd9dbb224066d557b2488d77fe773d4467dfde724d841ebc5160322826cfb9f3699c8d3d4afd168d18447727ed7b2270a60cd5820f630bfd43a49b577bcee763c51e27146c9ad66730f81ca29cb0f294dcbcabdc56c0b13a6a162c99190f248bd369ab5aae512ad3aabf59398ddb18b485ba4046fcd6868d6295a68aa5a93caf84f1ffceec915c39cc9425ccf2b1bc25b576853303d610e5c54c14cab0687764b9012a5b56b42f13d0b5be1627222721f51a6feb633e8c2f6b6a8ff5cc73ac806bc732d9af8cede83bf9d45d157bd6b987d765d8b3546228bba85fa9982ee8b4f222f2b231bc772fee1db5f286aac854ab8b4a8a8fc88ad87d5eadd23b4095a1cf9a6f793a8ae62e", "46b6baf853e4b02ffb63a06ff222f7356d4930b61a31b9ad07397f9a12eb55034d413eeae2276af12fb81199fb2c340feb05bd952d65542b4fb92599f99755f1d3e371e16f951607f27013ec2effaed56f895a20588682b5c9aaa3f5685221a630457e40f67886b4ff573ea30abb4c2ce5469752a6dd40995a9d6642711767736c4dfddcc0b141537d91860691b7a5c5cac767bdb7c4f44f53ceae57cd0a599c0be8d7156f5d97a2245ff61825d5903aca0cf19a6d5cdaa0f4368295201434c2d09839eef24679bb0e1b760d5d", .None}, + {.Div, "-7f27a88fbcd8cc015aea50627814ca15c249ad7602b8c35cef8d5c16c47a85eca876aaee9c3b280f2fa9c508e41e89e42216fc2c70dc1393f8a4c11dae85beb77537b4014a31c5fe53d456afc62c3a2a77f21c2c02c08d5f361525575dece7a929177fbdc9a529911da9405bb00a80e8d3949f73f45075edac97baf6b2e106f2fc84cc2d170e1cd3b3f45e5ac96de7926e98167ca37a3bb7fdb253faf865ba85d08b0738c2de4567696150c6e557b7e10e87f17f43cb531edc27ddf46525aec475061a8ad2268af43a9fdc7eb3416cf3c1add7542a1f65533cccf4432e7fde4fae0454e758d4b1d3662989f1799af11ef5dacf5537478f1a73bab5cacab45b4870938e91d09ea3252b19ef8e3beaa5c6ab4c5da3b309a8025a8bd143e9c5fea75421dc5aaf9c457d1657918264ba4f360cd1574cd1d118770bbc0ce96e679bb395478082b35d2893abf5f08e0a01181bf4457b2d4c4dc37568552e7596497b18e792f5c1f8cecad12f5cf32317b0a08034a36d49a677e37228b4bc9851df949436398ddf492b2827dd5136bfc0845b822476089c5ce529f7daedad1a0c09a06925e72221a83390ebda0a072e01bd57eed72443cbf4c311d37904671e64278703ed7179521d86fe4ce3e40c6da8a29618225dc83bf7ac4031e63e8ba5f168b6497caf1a551c598f42bb6a14d484bb5585c26a47736ae01eb1cce2e77bbf032600", "-76caeb97982f958bb98acd44ef8d6524b2b0b90c99ec6a23609d2802f2119a5939ff79ab8855d35782b7152d2ba0eb2c4c235a6014630a6aaf1930665374d824580f9a8592ce89616cd78af841b31aecd353174188575b7fd80bad4ec64e6c5bb24e7808896e053886c11a6a68aace2676ebc792de7d7180a988817812d314acf633ac5f5d03c0b9d29390c527911df39e3d37d6aad74fdc88450e16c2c6f86e3baa47c0f115289ec0b2a3fb84f2278920b8a4d60f9aaadae619e8247ddb29e363b929f6cf7885848de872df0f7e8d43911be6092a8318c82f42798afad9f7eb65908b4a299fda34afdc170cadeb32930de68f3a6c99bcde0d29c3c597f196a0c78e050ddc2a1e2ad5f226cf44e7dc84a42fea5ed31af6faaa97e8f5ca3f4db947139858b2a74da1d1cf849cd136e80f28f4cb", "1120552d740e60a38c3e28cd67a07b9255fd661f67fad1e9ae04e2dafbb682390289e23c6be22992bf7f0cb3497e33abd3cd5c7c008d719d71ac5ce0f6edfbac1a01458cdcc75269635fc2dd94fc43a2deed6671fa8370fb7a42057eb4a87f20a6abeff09ed62e5de463ad3a5c0240308c6138c8d21e897b7942e738ec111e8d35972f9059ddf00da0a36bbd2459e7c99353ff3c30cef29b0b5f22629583b1d9d24040b0bc279485bb4f34946b86fa810faf3253c412aaaa7b94618d8b847f521714656b8ea8d0cbb71f81652c7", .None}, + {.Div, "5acc544ac15cbddeb6e7203d54464c77449f214b92c7382aa3f0198f2ba869d96c8d97093c55fcd223d68ec8cf3d0bdcb36e74a542eb02a60dd3f75f813b76a038cdd65a141eb9817a821816cf31dca2a5b30a7c48aea43d213b0775234f03670e71a5bdf54d6bd6c314aab268001802e43cff3f860e9889c38f0f10fe6fa6a695475be9dd1f34a2b632f9ade9c3fada54754bf3911bbdbbb62ed565ff91330646875f4cbbe8a80b55e3c716aa817a7d5dd9e5a027c82e7a368bce9dc7cee350548007e4a39ab80843de9609ea18189072fc9809c7c3a4af851826340f00ae197051740b023a340d745ccccf10c06f081ab8033703e0e6473ae2d93f88062bf65be5b5e6df91771c5b30b554808626037458c5755aa03bc443204b0b62d31b61c177d1e39cc86934389f7c183927646d668d70559663d2cba50628ae700f0025581322a4bce18f72d53f769ccd085761adbb0a1a0419d1790b70972b5c3bddb5038e50bd8a8677ae9f0926702a0ed22dada890cff771a171a3af88f6b77223c02faca1b0f22fc7ca358c50fb0d34bbd1f992a67958b4514c2d883ee2cf7f5d821b6e0bf5e65fbcedf50883dbf362c2a333a4b4a1d83b03eeaa3834f31f9fe52e79033effb2d0b917bcd1b26d26d6465fb044bb640c74f270da40f2558d82a5bff49fd207bf2ef3325ad39e5b692c0f45901b4ea50d34dbd7c9f427bd55bf4d31", "10413e32410b19638b485ac943c4ba8b6960bb0e452977481eed67479fbb942e29a140a654e4d5e8ce45f434306185311fd95b37c5922be0511e27dc476dbce1b93d3a545df4bf9c34d97768d35bdeeda9c8727e068d6a36927ce56215402d69c06a3ca6914380adbd36e479292795f6b12323a7b7d63faa968324619cafe7339a6714e677b86dc16fa46fbf48dd2e6c13fc983d3a97bb229284ee2423933f90c1f9f1f1fb39b270e7d153296e6d6d35cfaf88ab2a19f523fd93b153043aec0c613a2c4f17817aa660415d7fc466c00354ef6034dd5671a4c70cd7172cdd8513d356c02c7d3a06392569ee44d25a809d8d870f1b47c87e23963a50ab74853387c122fc798d6284e03d3dc4fda55d14cff32ed22d39c329a3d8907631e604513b2ed41964c0ed05293e2e9a4242d558862a6ee04", "595fe352f870058e77b02ce019eb53088cbb63a77c76c3dccc4bd26dd53382bbd7ed2875af2ab293b3a5ce9159f4b4f26e7ae85e34ce55b01527eb71a00e809637bfa1255487599f6b39a6198ae12f3c9e75365a4cc97d036cddfa599f3a11cd1aee861cde49f7ddc3a5cfb3229dcd281c9dcc37dc5428e6f125e21772a7ebc0c1d1ddc657b05ae4c189e2aa9fac510a5b011661fbd7c87e74d1fe61ca9494a2ada4e996f5ee847471d2f7e095b8cf2f95011b33bcb83a9d1a33e221e91bfe8a75cecb335bb43f32f036135286", .None}, + {.Div, "-f89be345f34d5b9eb2d853d1d62e9cc7d536cd08bb52ffde0a829bea2a5d3ca08b3f18cc4ebbabe80713f970d6c3c45975af5328c17cd9d7c5aca1ae4e51f033920202553c68f1eaa6223f4d4cdd332277d661c2fc4e3bceadbc9ef0a2ba4445929a75ad3375274fcebcad8cbb8a45fdf03055948757003bf93ddaa556152a4440aa953d978745c739d511c12848fd0b7982886528f61e5f2f4ddcb9581f008c5173fd58e4428163409bf8a6bc66e777003eab8bc22c913db5c543c716ee0ba2aa205254aebf61a5a0832bf20638b673b187f9c4011d872ceb991b922ab6b8d56b61cdbda1fd31ee6389e0f985204ca2cc817a3a7e44d8e1ede481cbb15908861431dd5fa55560da9e0ff56929c81bb4b471384267dd9e95dadaf3c9abecbaefc878e642d3f3acc807922f9fb641f6518cc78c44f00ca125f06598897d7fb5a02f06f260c51b09252bd2bb61bff4c7761838d22b94e21c327262f49011aea9327819a8aa042819e7126a14b74706ca86345502a951659bd7025b746ceaa8a697b834043969f5b9eafad0e285de0411660c93ee2fc47961f6eccf6919e876926fa4e0bf5c584b92ab9f16e7e8b7d7f9e6407dea9a25ca6c706f961be7fea27d5575fe70d0e272b565ab62e4135c8114978cbae48d4dbca46c0faebdcec16bf35f37f18a3f756d947ccd0a6a4cdf7c8900a37768af5c4741e050e144ba5d40181d", "164a1a2522b1650ec15a20a7e442e0349be5f0d94b428b18bf855b8f20904e9006e4c3638630a3978502aec22f233c159301c4f5e80b63d1bd4bfb6a68fa45e49996301daa07a055a816c7d79ae0f30e007a7d9ba0d1b898e8fc822850d03d7e69d5780c365deba881921979a69518c40ad6fd0d3ca10bf11efb337b8f0a4e3628db3c1fbf37b04a423d67ba8f8738ec58edc09e7a42daab330cc0955492ecfdb45b891c858301ad225438eb3c72554569a7fe289509c4cb1acb6702a43006c2a0b7860eaca3eab222e1dd554c1de0fcb978b06d31d701e8fa4231bdb7734d6cbdb92ca571cd3345afa6557d4a6f47a8ea4239d836993f303d61ca74340ebead3272d344474fc3e54a1e9e89c0271e89e85521c73faea88c7f23edf3177642246cf79e3243007ac403b287adc8ad36cf1daa950", "-b2755db41cd6435f9994cf5d7ab083cc1b2e25e8a20fe95a8d76b80f43b8832ceaf440dc7bbbf10f819741f7dc6bea22d8d060202399e4412bc4a666e6433ae36abb6d480856d057cdefa60fbb21e611aef7246e6e9e2a20265046e0b4b51be39a141bca4af0d16108c00ba372493968e4a74b087bcfcb0ea896f825cf4ac36e6041b88eadb9c853146ee40b236c9b7301fab06bf3e8dc54a4029af1184c5e4ff923eef185cfa55a438a0e2b23a2b9711177124bc4b617a209201be2a8f5a03942c7ffd7d2f796959abe7d4358", .None}, + {.Div, "d5820aaf27f58d5e22f6979b03275dee513e15b884c57f0fb681b6ebe2fbe0fafb2713b5f84795285770158db7ca3fc7ce7150d87ebd2c05b84f01446a5ed668414f47e01f061dd78f6300825f9004bf7fe5af4818242e23e269894792fb531b19b359bf7f5b75e3f33435c4a12ae5a26755c3a4e6ec566f64e62501d19a746e8691e33741cdd73c7a7d899d6c8391c055137921fce9750aa15de5fda3d5889c183d0204e1dde4368c00e41c22f01d1a2cbedfc7f75f47406d773f8e036940adeb3526be63953a8f346d745e57b1f3d8ac65a6d315033d2957df1dd7e458658321f9957d01f162f0e3940e40e76b386a36a6514642f95675aae3969296557db5fc4a36ee10562c500554c7d58943c292d1001b31a48cf20c6fda676ddd69f5c0660744a68a234834573de3ce5298295a110ae5643e6475f141cfe3726bde9eb80d9d8f6bfbe7d395ed6a2662f73f68f2cbf232ff08164d0e8a0c37536288ed614a5e748b15a8afb4cb1323afbb3f49baffdc3adb04421fbce19501ad6682b9b4c69d16a21b8304e1eb6b04511c02dd6af4b1aac3fa90deb21f18eb6af57155fb9dc7565dc0cecc997ce3796b0e930b3be2522716991d1ffb84c3a4cd8d89ff8c4d6cf9bfe6102c3cf190bc9034e73c3286198b1aa40a0043181be49d0d408c20df1ba2d904adaa9558f86162b77818cc6f187c602ed6ad1738411b6997033099", "11fd9201fcfd4ed979e30a9d7cf414a9b094dc641f3dac9d3dbf16d9ef167f333216b2f5386745b936457a18405b6a6189817e29a311e0a49ef2c7473be3727f1142c3d830e0714676247c585f5ad6891bc5754496efe424a2e00ffd9c3c46523f3e232524577c66e7a5a1a4cbd6acbf5e6afb394ce78789b34fa8789fe86ff64c23636294552c551da5fdd7dfbfac9870b4331a9781a13139286bcbca53885a320b2b7f4957c29bc94e3e5f894fc26f1497299169b130d94af9ea0d796226c19fb32e55602550d0071b7096672f916b46ee2512460f2422d7d62a96047dd4647e83c34906693ce69cf25bfcf38638b131685408e9b948849a60243a57742b444ea28bcd740b0fef59070346585393d95cbac0dd5e7727cb96ea72c5f14ef2f62c58c22b9e2e6051860763f7298df7a9ddbe4d3", "bde28e8d4b9f20d41360d82049575934cc6a2959a52521a1f186c163793c8e9d673c95c7cfe6c9df948baa363f7dc9ba8c394a2d5fd0da92b51997ab2122c6220f57bc898990538d820510ce0da035ff3489ae8a417ab41d23f26d3dcaadb74bb8410de2623e0ab4755540524cabbcb8e2ed07745946073a740d98939f2a43c4f4724b6a59e34a35e8b19ea73cba5faffe04562bd859087d36b1b46f1e105aaaa0ed2e9a09172b738136cc4dbf0364dda9362f1f630ff2d8db64be544d21a03b90db942ea6ba770ac8e708c9d4", .None}, + {.Div, "-ab61d7bd239e8f1c6b2f0a9d9bb7d78eab279958181286d65ca487474c3dc90461bc5f5bfb75cd6b688650ad026ba40ef9196fe7ee505566ce3a784ef5994ea9bd712fe45d961f36717a8bf0a2891be972b01d859fa26528f7dd1387c721bb8bb3d85514487d120872a94a1c30ce9390e4840eb18d8be5add2f4afd3e0d519069a90b3d4efacede78efd414962f89ed5385905382d4e471dc50bcc97fe2a1fd334a7e9f0fc3c6f38e2c02b5e02cf22369e9c3df7ccaedc58989554c3ac2fda657e7d8653940db947bab594e3c19e40f10499cc4a2373182a83fe25bd11ab534e3bc20692af7a3cf4196c00508c7083630ce00b968e14021dcb138dc22270a6e750366cb5382da5b70a3cc68489e3ffdf681ed39f9e5b3a057fe368bd7d96a7cacad6ff1c2769c422263a98979748da64839b278492fb86849293f3ac11b366827874ec9710378f81ae543b6a4bfcdb33d9a26c11122dbee2a652002d3aea9a130357c678ea1e6610b8f37f3c3a909a217e70f6f288ab3e005f8447700e2589ab10f000fc2833510e019013cda026ce0fbc005eb18ca6bc7e4575f9e69aaa6f086a7696425ef92cf759193c4987629a0b8a9e4478d9c34f6470eacaee9341e3f60fdd13fe2a75f61c572b6046c92a4f65d9f11d0bb8fab81cc32c00e8ada004565fe81df92025f941be25c3a257410f6328e6dd7ade3810bd6cb1e820bcee4c95", "1328ea606dea0a3231090aa49a8733de6e633a07128143fcfe19b1fd739f44d298deee0fde914b36615b7b121e3e47b0521835415cb67424729adca6739c3142cbd23270197231ce5f7949cb1d526d41a0198bab80ca392f10bbc245885b7b9254dc7bc8e21adbe4b409f9cc396a54c423644fd12a0e6d9a12136af03aac3e4cbb1449c9e5ad11bfb4736ed85f917ad46a5ec4a480fc69e3cd2e173668da088128f44d078da247a74fab67decf27217b772d6eb90a5e58f3d9c63da7ee1764762e2d7b77c6b93d58c1c1bc447bc93d98885822ed7bba1a8665ffb6dfe95806e94dba1dbc7f9f23c932302487d5090ed677029349f40e8bfa8b995995018ca516129b5981de45973697fc3e0140dee422052ec7c91f6a0f9034239492780788c9f753a946f585bb950ae797191aea80e62589b36", "-8f1e3256d5dee96d6adab8513f1b060ed85afa06eb552cee34072080ed06edf730c7384f971b29792f395cdc77be599a1fb84e04d41a46137f7a0d49b1389208b4d310ebfa7c4854a79e0d79a12977217e36814abb7b76d206e97d191596655fec02b0e9ff16e5a2d9137529ca92418fb4f259001ef64ac6cd9840f32b2db8015240fcfba45f015b1ed013339529b07ce0d163d5dc9cd42b07e9580a742ab58c65f44bea3dc0e73dd472c3e86d80f76b722387a31813d28a3f988d0decd3247662353824de2bd9f96f83fcd1e1", .None}, + {.Div, "-5d6aa483caf66d6528166b926fbcd28ab0d4f91f4f89894c08e1bf5e5dcda5bbe69ac877d3b390d26bd785d6d63cf03db035724f45df8221b53d6bed245d648e2ad13539431920e0eb336d8b57da0e7848f6623bad31a07af93fa83b66b2c1b6edfaef1f3bb410428d00f44bfb714d46eefd1c4a3093511669b62ba8d762b9391bcdc512ff81a605b2d2401321d2fb5f14ef5aa12006ec537ce409bf1fa3d516cce51f6a5082b16992255e9b1b4163d4135be0202e4dac488a6320fc83b8739904fae59bd305764dd4f5569def99ecb47ab63fc43d1814222fd142db9c0a168751ab32a193dc99b581cbf1f0835fedc92d1e95d4b68c1ab9c39ffc7f88d344bfb33b45be4f8d9cb29e108cb170a9ac43ea5562c6cb7709706d3b95ab1007582c337bf4f88bc551637a95287c535c8ed79abd12656990cb067478125c9f059367505986c9ac86bd1116609297bae47c7bedaf7d716f6e91743b706952d265d1b3d47b791da38d775e5d553a88937e00d54dd7f453fa6f97cbf9e5c5e078c24ebfa6d0badabdbb02283b042908822cf0206c950ea373e3aee471698ea3082cb631246a499b39b2b09c07d2b5d036034453f4f1dd6c0c3a3ee6fbf02201128c666940bd10511eb9873f297d07ef5f22a383cff44c24a6510b3e048beb9274a5a601437be981fcc4120e78c359968a5ee525f6f9b250a6c471be50f110f64bb2e410", "-8a1724737f2ee82b3f1587a7812eba06155feb9f2c142508949bd7c2f55e1a87bcc4acd7e2136b9acca7b1d01da41724105e63f14456f7ebecf862f97064f49af6e09e9d1f407d524476eb1f519e671bf96bc937b0dd1c8d7b2d134a86385944c24b3be74ee9ea83af3019eeb90681ef14281e35299e2a085b2e935d35b145ecde8044a8da7b609a6deb84627a022c078687934900553c2871946f4a829c8ad4d5b14a1447ebfda97227e73dd93bd79f235b7938f691159f469316b13c93147628b5eb2f3a1dad2fce61fc68cb723b8bb7335a8e6fa85667e09613d1a343b2d50a3f4dd65b95a673bca38d52d5be44e92f6fee5d73574fe98e9850cec08484aebcc4edc21df77a61aa2308b646649e3d4392bb9897fbca2789a6ec0b20ea273f04d14b58f06390c8b798987b175d5360b9fbcd", "ad2e5a538739ee4a0fbe74d2b6f7b43054b3402f724b9a14f9f419a3248574bc56808a5de70c3029202dde58de9729d13bef16ac5e506da38ffc4de6e811dd1d5315a8cc2c3749283090bd7eb2c33f3831b841414555dc20670a435683f154027cda2f1fe6024473560e2f92b092e53416a01a2bd852f19cf481550aa089ed975f004aa3e06ea27854705d7647850b7d8eedb8bb989928e5b7859c36821a92bb23969bbd15dd4bc95f7ddc670c7052363ea8fd098dd572548dec33da5d2bc7a10457e51e090f570a0b54b1e9e0", .None}, + {.Div, "-563ea90c54b6b5113d778a747a2692e0365dde7bb1bad3abb00cf608924078e9fa2a2cfdc8ce7a40fa04ae02a36a563c607ec1d0c8e150448bde01f15347ebb72aa7e0acf02c8654313cb20e8a48c79d813a11991b1f61ff7c6d20d8de79a8528dc385b149a63910ae08265a0d79b964ff47d258f51ebe6c5b67534fe327aa318a0d046699906e08cbb063462a47d6034be1966f9be46b80685c6ab04361a3ecffd701230f6cc30826042e5b6df5245a4012f17808ada00f25f96b1527dba0f35c0c0dfd4f4149a9d61a1d97019dabc2c4eed9ada321616e166f097714964cb24c57d21c88a1a3c65a6f144cbf60c214cbd9fc76979a6477dc3b33cd40923574d9638f040a6b072a992ef8ffb4debbb37c4783993e6a75d88a273b57479d39a2a795babb74cfd03324c350340378380f2c683741b696be3fe0741611fc436357749976c048ee9a5a8abc8f5cbb2c897ffe67f29a48c395fb9a4a0a170552ee204a22d50b26f8e1c7185869d8bdae4782eedb450b7ec6654ffabbce9d0f18b6b2a04a6c531a695cff7200de50d5a1c4933fa441b840655fdc0bb0e18652ee1017ed4884deaf03d40845cf1d7e473084029db7c2a9f1fe0868c52e7ffd733d192d989a3466de2e05cc570d4a86100a14e0c059a80e29b020dbaab26c629fc71624a269bc088dd7fa661189f5a673e0542d2c40025dee6c0dc03931c6de203da16e", "-18f9bbcd51a2c8c96f7c606ca905e02a4d4b185b28ce7bdb5891160f5f1e49eae01c1ec78c7033b4eda21c09c6d832a9a3841545fd09af23084ccfff318b14bc1fc63f019db7638946b056ba08b6729a87eb07ea88fca07e7b3363fbc501b57b3396f21e97efdfe00e164b7dac525e8b52a63d5123b6778b9bbdca6f8a875d7b842b0b098cc90ee9f46c3b2ba9ed56a0ab44b2846d6487899e282d5d7e4b041f37c02676cbeaff6e83c2198efe8fdb987f7afea028ce3681c628cfad026d7e28af59a22b92352517144b3b91f8b1e2abbb4c9b93f96e16d9ec262c840ef70b896a85953a3f82a0716ad2e7f4f39c1196f32c113bc93e6b75c26d65cba3d85a2a37249bc4dfbef17a880bc19098ccdf83a4c3a6d3301552494a6da98aeab2a4fc3966e76ee8901d00a8b4a4f19cecc5056081fed", "374031094eec353f6553968b8b931eca9c440cd95173de4db7ee0f2f92515ee3af239aa13fc57ac5ae5b717d9d5f6d6a80acd1161c61e8247b89c871b60706cb9404f0240161b0f935f529e2f2d22a424dea6c2cd2a7bddd2c92c45a61cb19d30d050cd7650bad764795ddd9a1d567a78e784661070aad3affacfba9ee8767ed5f960c34c383a737a8023d97fd91499fd9d8c5c9e283ac5e131582f7636b5e1e901f6c7e8cb44bc504fc854a449dd829a622050c81c54c2526c89b404d3536be9bf605f4c3601c9c7eb29f4b33", .None}, + {.Div, "-bc7faae9c2593861741145d645a1ad9b677937d9350f8d310c246f79263ac910fdc5364496dcb38fb87ad1f55ff46ba16660d6a587a8bbd3ffe51c19bfe67e766d53cc98a3e491876b205a1b346d6e04f7119bb06eaf0398f0486402d3e5c4c5636ca3bf344f6979cef1a0394828308550ecef9c92d5c6e1c73cff37fc7989d68149c4d344e97eb819153e2668e4b1d0dc660d1ea23675f3b398baf5d69b29211c0d18e7a5faa75e658ecdcfe0cb826672b56b66f0583d5435450025da283480e0a7f19bf6d140911f12490236f06460f1b2d9cb6269f1dffb840d03ee92d94cb4ff9d0466c1fb0534e97a2ec69e9b15c7a9b3cf94a6f65e400fe98f1d4c3882e21d1a1b2c0f9c41c57bba7b8bd0f9c477b3177ab166c28879e4063d66e86e0da34034aa7c0ef500b0b210f29c45f5545dc02d42036add343a23c62e5f5c9ac8c8be207b803419f1d275711527bb90aaa28630663e290abcce9cd960a15acb65beb564822559981f33f0f965b6671d4816f8fd578e8834cf5b7f833e3e9322524a35d4707b1b7fb091e6a73907010b05e4eed2b6d1b7940af7cc53c81a6510ec84a052050feb4e866516d70b99e71ba99d6f228f7697c2999069efab13c6829af940119d99c262c8288d45bdcfcb4de3ac38183481abaeb576de70e7fed431324f8c85d05ead6cf86817e2d06c7a2e4b4ef3ac409aa49f7ed490890a2f97f98", "76fd9e7dfd31e36e37dd11c34b06b04588a78e22718d46c9f674f8c193ba8df33e1f003500739e2f8706c8c6bc899c6a7508070ac8a6d3f11607ad871b39c98f7da7feec34fadc8c3d435c9bfa87e6c70e9d8c80ea1a23b8fa5829f2224e99299135df14365ebc0fffd60eb31f1c6f550bc975949e22675542d4081f41827e41fd3da43d096592ffe06ebc7da9ad6bee6bcac33d5c01538f2ffa3a4cad976eb6bf6c9f0316558d770c3adb2a0d3afefc0a0170dafc21cd271b538c3033662c4b32094ebc87b335fb7689fe2525061734d96a0adf5b4eab76371ad2c4626d847719ea40a42e3d70851821c5fae5ea921eb519f232216e619646fe55f65147b49a6a7b950016f11a7698128aa56f3ee481a4c1e0dc46f6fa88fb2bdee22ec9cb3230c5c54b84662ae87d4906984847ca40ca1689", "-1958aa0306385f6e65247c2b9da413a95bff7001bb39c15724b5d64bcb09322a6046b4ceedd48ef5e471eb73ba070004cbb7c58046f139fab8d2cbb0085718943e25a5631db29d41385cb39a6493d2403560d5d7096dccaba7f4bf00a5984736363f8c2f6fdf7eef1899a9d4c2a54096d7e371167682c2d03898a66bd4c7dfdc42e637ecb62bd9e78a3d5ea7a294bdce399579e2d29e6903bbcb077d34bc586bb7d44aa91a3e626d407f572a9ef4cc5a58c78b0591138c7f03a92f561b5bbe29c8efec017378f1fed8a6cca60c", .None}, + {.Div, "-7eb980e63a183745d6779c9581b79e506d6bffbc97519ba366860d75d61049037c8d5e28b4f7ed6308fa58871fb979ac7bbff25dd79bd03793d6008511a2d7ddbebca27e16cbb3cccd3aba0e10157014d36de7ce96e1b9e58f1a1091bc2af12c847c87438ec43058396a62de62da649bc1625fbc3e2b1218613c153246505b28a72a7a8938b10f301b47b75d5e4c2dd37d2b248732940060b52db4c5b61d05f2a817ed544d3363af315b1498e581d3716a3d01aeafd4244956cf57944f1fd2a3b9791e1a3482bd6cc7d9c61d5548fec9694c118d7c7b2ee752738c3510e8021202b514abcb2bf23ecf0c0839b396a804f481a9f307a5e941d3a0d18f8bdce9e3669c6c5eea56bd74bdf7ab84ffb6ac4cf2c08afcbb6182b5cd6af751af4d9569ab9c7bdc257450f59305a121782cd32ed16a488b0d41d09c2967a0c35b270f7fc1d3fa52030d03c8bd8dffce816b3b46d5574aed925cc3210cabab9a4a9c51f7a5326445cd96c1598c985be75e6e25cad99fa95acbcf536454848603b4b8821323b6e274a7ea11a68f5c4595bb3de8061827054084d8bdc53bce4ca062ff7dc703894449ae91f2f968f454a9fef10ce906f144be13d3d63fda7ee0e28f09430ba7de662a33d68ebd90772daebe63d8cd64f4f62171cec8719cfe0aec27d3f3160f3de99f645605b6bd42f8d78391b54efd8054117d574d0acb3e7688b8dd02f7", "1fcf3b7862354fb147e82a2674c7eff380ba62c76fe012cfe322a012153fcf3ebba045d14d37b5441f4613f482e27324cb93c3cf1c0c5b7198e84318fb6ebf2fca4a0bddb8aa85466f3893acf7260bffd693ba02b775b4048d20d719401d6a6cd01040d973b14a4862ea3e28ff85cd1dc5d173d40d7740cdc57229d0613ff0cbeeb5f24d1e666e197c59e5df5a1c27946f61655c6852796ee6448652c6a8ce917b26eabe79e98ad1e095c85c9324e721612cfd0fe4273bcf3e2cdb37cfd55ecf5b937974f5bd24f0cfd4c5de2c2c7b74e8f4e3bb44e95ff44ac6a9f57c837a41a9941e359269da2357ef8358e91c3924808db4250b32aafe9c6931a3ea184f37d0464b3ad948fba7e84617a8db52cf0916126aa187899f38217a8b25b663f74b15c39a530285fe9262a73aa8d775ad2c98bbe83", "-3fbde4c37ee45c680105cf362c15822fc74883ddb1dbf1e4687c2f6861f30a7362ada9907e2a75444ee9ecd12055316aabaf58b03ab096e160aed9a31c0beb8c83b4ebb1e77f6b3e1ac94cce710c2bfda8dffb49bb813782f9ff58d6ef6147097943769923f7f4fd8b0fa2b9c3860549197a4074112deb7e3ca348b39fd8d76d31a10afbfa5c9b1d1e93d4d778852e257d4d0b93d299abd33b2462c5ef839cb6bdf25b9807d04185b09ca1c5f8c9abbc6b7b606fcc7659817c166ae8615b7f1d5e74300f1491e587048587ea29", .None}, + {.Div, "-bd5783adac58322fad970c6f5772c3312c3718b66f7f9889bf62a7b791561d3669787a7e8d88e0819b9ec0a75c9388d7f56f373825fbc614ede279cdb62aaacf02ea7bd941b60a230ccc7edaf59a0250d651539221fb5030f576de0e6478fe32587fc4c478079770ecc2e3d76e51a778b265c468b569c12c4cc3c3134087339e42731ca5eaf435a2a83e16fafbe6b525b95b9132b4437101c9f44a10b5622406020ea9e6e012c8f3ce34794cd6dfd3fe13770dcb0c7f43179c9a7d9e33426c872c85824980d580d5a156b6aca0ead7525040bb998d22e430ab4bd4218bcab86afffd94b38f311bc706b9767bed0d7dc8a16d01a54a86712ba89c1f7d942487ec5f166cc0d226224d277ff167b195499a08beabaa05603e4423437f226f9a11e99ed0999b9aa223692b0e289843210307c98531e249be3d2ed8dc679f581d0ebbdb517cfc37bf7a9d67c3fb0a32b176a2e1d2d241e1163c2e1d9d3663884eb1e982c083a09e4b98d30fd7cf835012272cb1789efaedb3c72e05f4fb1e0aa3cf48ffa3c2ef38130d01d8cd22b770747e87edec047dfa37a7fdabed95d88c3d20fdab7f2ef7855618991f23b126729aa1b7cd4937ab2a6d6cda20fb35f81c1668e35f1a8238c4d9b8b5b0dee2ff0109989248dca31b5a2bd2c8ba70bb4196294c58c1146072a4956be852ab59418cfc08c08d3aa5524c36201596635c7d45312ce3", "1892021206a231e9f96d91236d99184cc0bab12e08866c777f1a3ccedba69989810cf89f36a192b439f1eb30747cdb730cf58f90aa4d00e5da247d62c86ac34a717a3fe9fb0eb7975f150721c189ea2f09ac6cd1538629d529fcd7fa848b5449cf56df20374802c5a141ec008b9e8223fb75d3d5e1d42d41bab48acc842186ad7762f86e15bad43ec99560a881f252fc295b14e307ac932260027444371d31e6cc0010b6fbd86a2e43f071e74afad54240da19d5d74fc1b9b01e2597b707003f117885272240c7f24211b6e084a1cac66de1ccc644463cb3291def2e7cfb2f2e57964ac68cca01b50b0ff2b2797ec47c2e46f4df97f3d229bbb863608276c24c0c2ef438e0871c3d19bba4ee54cbcf8b9b9ef7bd22386fc90c4af0cde31417d2ff5d874990e1e90af205e12ec41d1404177851e", "-7b4c3d5b902e642baded394d4a366971489ab8379c38f4019e4f3fa0211cb86a5ef1c67a61ead8980e7643f64bfa432b51ab4f3153e308d158353ecba76d0f18dc8fcbed692a566a400e35dfc65a5b02b91255b601dcb9ab4a239105b976cecf3843a68c1c0b75540f39c0a5a07cef4e562e48e449cfc931cd8fcb1ae1bfe64c97e456c3526103030acc7cf734629e74d247644523ff4dd2ea6b3fd0a4f854ad66d0afd419f5a26390ddb2e2dddeb51909f4045a79a91ed33455c367a8b299919bf1a901ce8ebf5f5785b02782", .None}, + {.Div, "28597b0acf9a3a8d84f25951af380c8415c9d7d63585c5099bb9e3abcf450473e2ba59f2764bafcacb618e0d6b98da5818d05a4973b65011f36feeaf9b8c881395947f5735d3075f4b4f354a0b0a93290a0fae125c09da8b8ca84e54c60c02a95ee072246bf1381a209d31b4df1fd9a0479eedd795c86c7510be900fe443963e832b318222c66c86677ed4dddad8da79e0cd80f762ef4e52a5695c11897d5cf9f592b3e21626e00a6d80e4c7d189c678519c0f61765797ba9d20de883beb81ac4b33763fc54b2c66b82903333c4137b79fb5bf4a1302d3ff895c62df6ada2f8a2b4b95114fb38b7c39eaf13c7b28c7254f93099aa5127570f918a715a1174782ab4cbefbc2183e95772893453eeab1041d04e2295b8ef37a2a3ee395951ebf6986e239761e570c4f518b9c1ed59e266f9f2ecceb975bfc1509b81273ace085b1710875fa15440e452a97ef14b0493ce859b8084dcb9d92fffbd236013f5aa28a193be18fd837720fc5bbb29c919c3ac196be369308bec9531543d929830c0b6367d3d7f4f8719d7125eb2cb6fad9756cb318de2f706239263e7343b89a95b8523ad84c69119d23a19446e946ec25f63f1169df93efe5df7d3a80eadaa2f695459166de9e7be46dd486eaedd051450db56783dfc74754d645d065f72efc7601b55d546071ec3f172aacf97999e6fb407a22214ad3f7f0ed6a94b09112ff695989", "-7600b9b18b5413f4f6655da3ecbfb93d2800c95d53f34e1a9f295225f23800edba28f4dda54be3113a416c75f21449c41766900be3fb79346aafd90365ee93997d31be436616f6e78cb276d9ec7c4f3aa3d6bc7d477feaa14b68f38887a0afcb416c512f281bb58b0c5f46c5d4910b53ee414904317ff65f4b7507cb1b73cfe5fe04ba3d5a4d2ff86d5830e1fce747af260740a8ac9e89fbb0def22fc3a85d11bb5ee45cb562cc080f04372504a3a5bf83e02ada69e7c7cc7518104e237ea48d66063e4d1cdad3bee3a51000249a4387ec30f5b813358eb9eaf99308bb3efca1fd52d4513b1bb1aaeb78f8d3d77cdfdcd54d16538bc216101798aee6b67e45c9bdcfa08219133cd0cde5cca1f6b9247856996bcbc08577a22bddb210cdf20a97db31ad0d225b764871c47e53cf30df436dddd3", "-57892ebed77f7ae935fb05876fd75128aeba3f22bcd38cb0c612e2591d995f391e0a6e9507fe52cdf9d62714711f1214ff3a30fa27914e56f7af826f6529b96151ce2037bc803f333c871617a49c67df5b3b0110b624f24b1538be2c73fb04ae9b5bf626333dbbb019df7d21eaed9aa9e348c522c3fbe4272d04444b27b71d18f20353b9a568071d4d4f2ec1ac36c5b8e0d4bda406fb488a44287a1cbda3a061f667eca65c461c6777f23676b5562278bfbba5e7a3be72ba5fbe484fda2106e257dd0e668def6828509237c176", .None}, + {.Div, "1b7e96dde4a34a9002392a5b31977cf17522993f3345d8ad6802ba2dcbcc9fb2a29559b5856495df2e00572db9dcd8d0b090246dec2862a9152f5a0f144dd1b8041639dbc76a883bc3327cf9f51135faf60308caae8c7bcd2c8c28630340128123dac0e231ea42e4b5cb321e5182f9479a75ed5a62214261731504a5eca2b27c94992310a90bbb30e74c3a79345c33508d1113ed8c6b82e5bdf938de2198497bc7e113e2d17081a45f1e5db2787fbcbafe8bbc49a3d9bcddb2818e2c9b5aa23656b1157c52cfca3351b21dd359df1454976b6281849977ba7ea92af60b730f6ed6c851f66548f9647a0609ae8a7e1ff0c3813d8ab0335632334c3c5b317e64ba795c1dd28fd3be53caf7f0d35aa389a511802b3fa2c38f80cc4cdd66973dcdfb41d51703675e842d349d447690347f76e6b54079e1f38f2e3305200b50498b0c4a30dbffa334a6e8c7a06e340ce4b8c7f757a3e8cff3200d5776be978fcf179ccf64e62adde98e75a0d9d1ce6f7c5b232f834385a6b169a039da78c440cc06429c4c098a7a58f7d79dc14c78bfe94cfedbad6fe0dd6888dccb242a4cf745cc4dc590c060a9e872fff662326c27d3d4178d6cf6c9cd4139fe4dd0a69b74940e3660493ed5b23b7709d22a07bcb1339ac50aa006f82b083019a72b7573442577ac5793f9911e69926d8f42df218390c3e89d79a859b1b099787821f6ac2d803db5", "1cd55f5275dcf14a826c51b9b9ff913cc00ae8b56aec06f9f41b37dc00d055515e56172e883d26cbae60de03d642e3b65c0958fc5e390788f6843fee6de40b8c3f781975eb5940e8d2a317707e3a1208a5cfcab6ffe477d00f815d7e40f5fa9822aefe7da049575da736a6124b6a7576f7e076236be1e9457da77b7787a3e1c16f73bd8a72e57e00ddf02a8675ea417f5c7e9c0fc5e7df53a5f005028d9b00181a99f9916793e792cb35981df584227da0d9cec89820d264bd998a97e5572a4623f0225c8047eced0d7cb7d080e525eccb2b62f810419a940e6c3fe24e9d13bf406c513e848b2579ff8dfc611f1cf5130bb9ce34d50d1a0c0604c404ffc7ee2c7799ddd15b723736732db9443e2005b2c4cb45b5a01a96127a41a2b071a4464aa4c0446300b9a061024eb68f001576a74e2e39", "f41c940d766a18e1861efb4614852a4840f3be6f0912e01ab2baaeb47c9cb0f793a9cedcd788dfac732543682d2085a1a4fa39f779e88af9ebdecb159cfa5d0905c10c915a4782a8303a8b0a3c853f218180872894a215b1655565d6d84cf920ae923937859e4b9024270de8b59188f46c52640a058396b917dd816b1e990f7c4811519782b5fa7347fd1d7ebf08c417a63f0085b2a286cbad69919a152cc886d37f035b128039e559e3393e6484d2495eedd881bf075531a8ef5f910f42b6f3f575f6ceffd30a29ff1b9183a6", .None}, + {.Div, "-211e72590f7fe7fd212bd80998e9611c91c84cfe661e7c16cd32f5b3e58bc1788cec70569a1989a3e6f31558d750a633de573f09819ce2cc8ae4fdd5486c10c5b5a81d74e4b1e80545c7d32b70e4ec9a87afb6971d061c9dd996d053244c3a1535e1bfeda82ab6442df4a70d846de680d8613b442fe5a1f1a5ce420673f6a52600829bb1cd440cbf619eb397aec786d9613ce7411e41c604a9b431d93d1adf45549e6b8bfc35dee2c9310783c0c2fa56636c96045739ada537b254833526f22735928c49c268d191be8747fe2899230857ddc2012cc13832be41bc4c20fea9b79e11906663d1d681cc3a2fce60682c0988ccefac2d56fa6f8274d1536bb4a8842bb98e62ff02b59e4a751331140e93a8ce00dec7f9bb3f21f1bc0711123959a21f690d736f90768fd6ce6f807f135f8da05807a119d86a1cb34beebc2710cfaa662ea0129e05555a83746c079c76b4b5ce42a313410760c61bb683c1038601bc9465f6325dab119fc0491daa352b8a7087a55ada23431a310f1e1dc6dae7843c25ed707201cf74bccd408eed62cae65b9bd3c6a6511e3716a6925c94c33689b3369fb82d73a4ccd7374f3945687cc01fe982076df7160243633226849cb1dfacc9ddff3dbd1bb16e75f444a51c74b901b415efb5316b7e40b5dc2efe01a96fceea80901869efafd582eca696327ff55145f75e4b9aa1b740836ee9fe5fc6ec73", "-1fc8fd8d77a8211da53137cc42b9e81899256494b820051bd4ed3cfe1bcf439f371c4d1947bfdc4947fd6ad5d882be3d8714965744f771a0499d7d781c6b6362e9ca4a0d5db381291a06c1fb972b88aa44734873c34dd8052a3df56a8ce527cca45fc139a73dd3d707c96c8da33afe2a2cfa095f5bedfc6bdf1f0713a06b2001a54629d9b4dae594010b9b0eb1eb20fc5cb04e2e7c00dd93cd40b62d0b24486fec81f44443e581fdbd13c20299d8759344a28d7c6734129a922bf1aeaa24031978adc54e1d6780d5db82fa35c6a4018140147bca85f78447ae2484706477592fbbd979bf99485e8fb28329abebad8b1d1f5a8c27ceba93c226f2eded64c0159b9d00f4a680984f578a96f7461f406f7a4c6463177f22e20660b6e88d950ce1da054e78b0c4a9aef204a08c3aab5257ec773257d", "10abe1df28c8f24dc18205c676a5209ad4adc7bc404cf167b509649c56ef923f09e0e79ca597bcb19470489db3e46a456d0ca2d6510405e77133d6f9fe74f70a80a74f7d2cf9770772c6326364bba22b18ab40c810c0f65d8ff080f7179f274f373d2f0c7f37ccf546d4ef2b29b87d4693fa4da21312374ee740a6a8151f83718fc1a8b94d38b3a9d6d489d9752080b20a609791f3d49cc81ead9c4880ce8286fd4fdc9d1b6bc003188bd32387fe05e2141747f0c0de295e06e2876e8c1c2de2edda6d7a4889fb426cc08201c1", .None}, + {.Add, "ee66b730ecb84a217de1f7c98fa6121f4bc45d5e7168e14ceebeb1fd188b82a8be90e9bb00b97e8c39eb66e6824a834a2f738b0d878780387889f88f32c21a89269a5b0aa0764c4a1a2096d62fb7b9ace960816b4c6523ff6395b7f5279d3e437922a2fcbde10010497d3645257a4a2e55443d91fa0552992451087e7bd9878f5cddd2cd2b35e5f09b1710f03110083f0eb5efbb4f7cf84e8d479f437ef4a3b9dd794dbdf99a0657c406e7cc98331b4306e0c17b004383ada6fcb0dcf9cb8013d280e33d4a822ee0ea867e51da00abe0ac801c7e4dccd961aab5edbd2c7b5cc3803b3d37420f78e15327f72ccb2ccb48fa7c84624bc69312beb3b56db3042077ac14ebbed9745396777d6e6bb2e7dcd3601e0e0622bff3ab0cd90184b3da7042949783e827e0281f48d88ed0e4e7755a7712ec30ddd41f7a8495454518f7549bb55752c3a4a19586953e9c46fa9f65ffbcaab0ce53a72d6f730ba9eab53a71d5917a8d0790b16c3ac8da7aad025efb4f5cbfcbc0f635feb02798fbbd4f43388d9d12626375b5ae7a57de9fed0805ed895e4b553b917e809cd064767720e6d8304f1df2ccfdd16eaf38e858537cea62b8cb565c1ceae18547b8c8989ae5bcb9bebc2600216dafcd23c18841c37583b5e961e1fb245113fe3751bd5ba39d9e50caa606c576a3052d503daf6e86421f7cc29bedd4f208dc82ea2c6cb1650d3147c4d01dfbf748902e8d7b528bce8193f4cd81d52608fea0cd1663a93ff4f10010acb9678543b0bb46c00fcf3becd86a8f1197e34f89c0657e90785bfa82e544dac1c8091dac6bc85d9e1dae65b0204491ee4987345b35d9be998626a0b24709f4df0e2dcc519e64b580ba3d673ced0c1f54d62367a67ae45b41de9fc030fa1a1c40921f014b1bab4d8ec9f8f53028ca1b110131aa71800173c6fbf30e3aebf2a87c06822ca8758d4e7011a677c016f5e7d610375115f850eb32993845e377356f732200b0cedefa4442be2387e5c94b69d5b4512fb59f6ad64f98dc27395d692c31debb5e5cbfa3c1f585c9f478276bc8fa871ab46bdd43808c5b1e3088f78c16c22d7f15eece7c183e1dbde9f05579c31f02c7c71e07dbd12e1a9804e12e18e3b582a5c67ffd5352a02028ad724d37416927d5b4edba5b4590bd8020220a36f3ab57a4c5193806dbd435a38560c54bfa24b7c80e06b5dee6803768377fcbe4fca2ffabc5cfafc3a9b10254396c3cb86127b5c20e3f7eaea7c6ff0727bffaa8d33843e586ba380882ec933e2b0ac00d9e0c9b48a2a00d0a222a1441688695aa667b10fe47a6542b3041a8d465fb05b89d9a81bcd2097dcfe1faad5ff90012c6c63b4064de7dce11624b2a48e451dc8ea491be928f2bfef957962090dfb0fc39d70c4213040e2194ff685bad3e20998c63ac13576eafb13364a85d9a7dc33928d530aa4aededf3c8ea7f6c06a20c88dca62a42b9e0b975dd373a795f9e495e7597d469fe6c62dfb664b2c74a2010e90a27ff4ccfb5c90b1ae44c00b5a6b433acd13dd2fbf2fc738e170d96aed98744a86eb5f42aa4e3207a10bfa7a24e8a5ee2661586d7988bcc4e98cd028b2c8aa6c4a0cd01d5009802650a20dce5e6953a822d90a620b75fe90a58ec1016ccbe87c1b6508f1c22d4cbe798fe1f8c71653edf1f37a56b56424093195d1764bf38f44a62e1303751f06936a2c335e4d57384e09283b98e55e38cab503bd6d274c1451b3b5da16b57150e8c19498ec0c88f41d637804870d58529242c2dfb7fc4bcf13c83ecc6bfa62f96bfd44f4b79a70da4a7bd673dd43a3175085725590809b4f8c0915ad9d08c5e29c00ac335f6f3e41eab39f11e7f0ed0160dc6f3930e63ff7ab724fb2c65183441e25179e6715025606d951723e57a81fdd4cd02c40c9057924b27b71f1bad9b564c6d46bfdfda89a99e1eff3ee98271a8ce5dc037f610e813f65e62a5a2adff47ed6bf7bb4c9938115b7c6318e69d80927146d116ea92cd9ddad2777eabc92437134763a5038aec20d2fd1f4b15d02adec6abe1a1ee973cf2b3aaf0180754023eec97b453cb53f9619a51eb498f29ae70d33ad1f886921bb3ec005f7e7eb2084ae15cd132f8dee3", "bc69725373ab24ab7b55ad9c5a54b981f4615b877edaceb97cd10b0098a5e06fc1206fef1ad9d0cb211c8aaf18c4ccde6ce8e6f6886494c4acbb3485cb8ae52f126c8a712386287bb90242dea6c74a940a508180ca350816c5fac47d8702a2c70327e836397286c2c46a07c83d420acd53195ada97ac98521fa180cc1c93f391785be4c5cb76b9447f880f2fde3c35a52b5fa5114d27a145720261de422015a673900c14966f5811b20f9f408c0760229e33040e5167d0750f7255d05dc0847768adbcd4e30cbebcdb4ad3361ea926b7deaa925dd38565c9f9f4e429b452874d13fa88224e968a6febd937eba0c6489633473599785758948337f69850a2e378cf3ee97a8322f2798fed574d7b98ad78963aadaf1c7abd2f5d9c2174a7959d366491de22ac17abca35ec0b1d85658e99d936516d6c9f887ca4b16966d5ed7ebca5a1017598b919d3141314f36151616709facd9ba723be4c70b25f737ee986b66a7be6495ed10c583ac63b0a359475926fcf885c4368d9639a96e7cd037fb86bbf8c91946d207269475a53c3b9ec90d918c3385e3046dc59e39f98e9163e6faf75772d01815c3bce7f83f64a4939279a753cae473434127aa767c2695318f120ade33a98ee0d8dfdcecfd3d21146e65c5964b67ddca9cee2ddd0f89c47d2e83a19e6b6ff65b5129935833d893c56784f98f489e64ee82f0e644708f7c41b27438324d19cf6dba67ada62da4de76ad3270c712ab73c1bbeca611816cd40941e00c0e896fff7c1fc694aaebfdd83a8b3a7ce2d69d58db6bbc90d5ab7a96c576cf4d4a60cc0dae8f340898fa1034c55be0acd112e63e28ca01ae55f27cdcf3fb4f43733cad3a118eeee1368b5f6e6c9b05bb78efbf3f4cc98d5ca15a89d70b11d87eec39b508d4cafa086807aee084c4fad51ca991e35b8d257535a3369aa35e9b21a620ffe9b72fdf45f63f156ce2de5be824eba0589de08d5ccb75ed9462af8505fff997c8a6d0c5b362defcf54d6f61ee760e59e60f633446cc0c7c64eac5d1a76dd07c7b9254528e62ce2e0cdd4b728bb8e98304f490a547466ec944603c6b857232ed9887a1a4c4be260f9d6cfb0677f53aaef1010089d18d066c42837e5c38878fdb4828b99c48ac9a6294fba699b2b6a3e9f9ec04088ab9873c8823a85f62b0d749aa2767382d0f8f987b70cd158a96b80fa2930704d543842c987dea3954f5bf48aeb4f1795b4472f785eb0c7e6241f1510d41d006567398c0fd230d9891a4225695ee0752007410a59dc855a867a30d2983d002c867c2b2969c9a536a66371d0763d2aa474a6a4f9ddc8d7af5fdf78fc823355cdf17acbcf9a912ef903a10890afc73e85abc029ea225b6970f1ed98558aa2bc9f41d437084e4a021b84425ec30e8245cd3560385d4f51ace2dbc606ba695722ba58786d182915cf074ea439e02c4d9bd1f71fb080147904dceeb14bbd40a616fe8524cd8bec51c900d21a6d8bee00352ef730a251f74e6b05823cee3211c0d2c4eb961bb7cc341485073bbc56a39dea985d5df0086b8c9c510ca192f7c3ae019412024bcdafc61adeac9dd907091f4ebdae42c874f055b92da9c4b1a3a011c15a596ed9de7f1976d8ae2f8a44f118adaf339c536e35a786debc6593b6b62654fa85722a16392c7f527d39707d5c562dcf2bf995d2885ca056922f4e6664431f9860b26e587050abf1c5c6c6432ccab575e7762c6dc362098c7a03084d9edf2cb7bcfa7c421e47ac83e4a10279290ef34dd81396098a34b74d274d2b98ba4c406fbaebeb1c4838aa1d99e6edf07d6d00c2e22bc4a3d85272ce4772018e38305efe4361ea80e07daf501cf918f01e7f3a131914961a2dc97d7a3fab3aed2fb2cc8704ec28af6c009f5edd7f6307e6116cb9b314c276700ceafb7443bffdc21425ab57b750f75fb226ac2bdf566c8e41cd3793966d709cf6d5a6936a84dc942af220f6e122a85989b0181b3486f546f6bc8d99e63fb2bb7f852065466ac442abe04a23848433c406c09829aa82f57b36db383685b2aba925e298318173724385981bc17d6dc811ae9454172a149340381d3e5419028bb71e5b1923f0932cc15a7992154c28e3ba", "1aad0298460636eccf937a565e9facba14025b8e5f043b0066b8fbcfdb13163187fb159aa1b934f575b07f1959b0f50289c5c72040fec14fd25452d14fe4cffb83906e57bc3fc74c5d322d9b4d67f0440f3b102ec169a2c1629907c72ae9fe10a7c4a8b32f75386d30de73e0d62bc54fba85d986c91b1eaeb43f2894a986d7b20d539b792f6ac9f351a9f20200f4c3de43a1594cc9ca49993ff4a0121c114b960510959d290095e697616870d243a7b65a513c58951ab5422b66f06ad578c048b3b2ea0122d8eed9dc5d15187f8a9d2988b2aaedc21523f2ba4aad1e6e0cde4109435c55990a603513f012f186bf313df2dc3b9fbc41deba741ebac0603a703f07b53d5395c974610076ac5b92e808a4bf658bbb53f3ab0da6a7522f95b700d78f929620ad3f7d3e97ec499ee6a4d03f450493d9e4a73a7f72946aeabeee4d3585af854393d5aaf59a951b13a5bf0c766c6a57e69facaebbbe3be095e3423f88bfbf67350ef82789303a0b5b737f370e1cc8f541d399ed813c22fe38a52c2f0f95c9ef3f7e2d620e39f38f3b0c1f27e62770e8d99c1c55cf6b4040f60372547dfc4951fce7f2daa7db86c4e9dc6238a5340930a641f1597c260305b0438d5aadf6a093aba5bbd5b219058159586ca9c45bb46b1a22dbdcd1a2f8e543fe5713904bfed7c7608ba3fe97332ac0f7e75f51234e25ed857c4b1f890b3ba5cd14c6f085342cd943f6bd50855b5661c68fec7f48e4650c03abc8be0c4c156c231942ead7a501c43a87d43295a7dfbca5c1342b96610b95f4e1c3a5985b6b22c519c47b69caf2a6d46b150dea73e06b36c9a4ff9169862bf18665eb46b85c8801649a9d3456197253f7da46ecda61d33d3d5cfb08db2639a6fb0f417a8b568ce6acb39c880e29c9ba8f7fd2f5079701e31166abe52fc438fb5ba461e4f4d41a49628922e20e43ca711004c64710a6916e523cd9492860b1b822ef40865efa4bcbd6067c382004a4b6967509df45177b51e225ff49bb2155400610994059ceeffac15894c5598662478c9071e6bf6d758f540802342a94c9c2c8c8ae0cf851d1d3d8fdd7a84a244c856f6328a69a04aea2c497386821b720d17ebd9cb33686ba55650c9790b1ec4347fdeec64aaf2539b9cf1ab04533ff38d591b8619691893ea8c7179a182b239b3da7d4f57069c7ee87c58cb7d61338f00df0f56cd8ba07a4953c3a0384f07ba5a9b12c146b69b68e49b69290dd9e1235052cba82c6640b3cfccd9acc15e27ac2396e8f80c9a7f35649c92f893157975384a0a4eb0906c91f05f4f9d217470181c9155d4b64f795fd8ce904cfa6135ce8bb125afec282bc89aa3f5bf3ee16d6f2d954fe7f6ea72ce7437f81583ac2ae4b6a1b5f6d7f4c7e7ff463bf2908471c71ca3dacc9dbbe59b6feb394687d95e291908561f00d60795ec4ef7dc7f4e84ce1a4164bc768bb7222101e18318f4059dfa1bf435bf9e2d2a35b03e98a6846bf850dfeb93a9f7ec720837752d8189bde7dacbeda93796d15e8067c156450eb849a01178af6af49ee1f2d144bfc295bd9ca6ce7ba4d1a9ee1c3a24fd44c224b09f94eb9d567b4553a17afc7dce76c686a4381426647a4bbfc51453f9063ed5aafc5101b8081fac6a3af42f48950cf4afd98af23c938391b6879e6b5e71b4dedbd39e96c0e88910fa91c150eab9735f85b854ac563b23e8532de3d58c8449805499105760c6234cfee284a724c7d7a473a4b3edb8d106893d0aad8982bb64e9734eae38177a060f15ce4725f3d11413eb3ee9e300440a3764c355dd51db0124c22aaee2091a0784ccad8d4b335fa24bd21a965a1f090697e174c49c5a8a0e1797feee9547da0ca7a47e2d44349f3ad7a00563f4aed87ed299ff91610cf3f4a34882680f4186b5d8cf06c79f36232b62dbab5d6a72189e7730d1e95bc4cb2b1e3feeffea9b9553ce6381850acc04f610278a9372df8cee9c6f41919b0b947e4d6d92c7892dd46afd2a45891d5ff2dcc5168d66e2f391872987beb027939548f598c5a615a1e41827a142e618964321997ac645c484b375d1391c0b102ea60273a3bceea8f0792611891dd2d24719836f11dec9a55aeee67f21c29d", .None}, + {.Add, "e19ec0eacd34eb071e4f3252416bf4be1ec54b14c98611cdc18487dcf6e39920b55429db2590f6b11d2dadbb9073be68773f5718154febb00efb5a3ef33eb565c0fd3d678b225c633058a8b281bac4843c88e6c43c4ba7efbaa00a8002f5dcd6f747a6bbe172226edda63bdf7b9faea73a033522ed29f4c723f7ec2fbbd779d4a015d31801e126717afa6d77b61a5271da1850c8f139ca3c7067a854d14791d198fbc03b09a531269660deaa8eeb1c3ce41cb35452b9d7b5c1c42183c74be31237557d7f1ec65a8302012e9aebeaff4f9571abda93c20732f24c3064ea8001490877851ceb863dbec412aa6d856b2358a20f653f5be0119cff2937cb63721e99f0c85e4befe475e543cccfdd2903a02a9d9d6f3fd7bec2042e74c275b1f67382dc0e1e25ea845dcace9be3b85af47bba39b40449a3c6d62af4a0aff62b1a09a3110f5f297c0d22498c8c627c54a341251bde73640ccc82f15d72bf0aff35522b6cad294488392187168a60993757b631f3ac59c4fcce2cc69075ca839115108fb1bc972571d5b6b83389d53445fee6addadf19795ab311ca9c8c6ac9b87bbe472cfc4b9e9f4950c6309b38e19dff257e9dee7e596db0d9e91a886a2f130ebf165f221d468e228aa9cb44e2370e651f3fb1ea4c4d5d3620b8edf4c444215a537c08a2ee3b9dc400b4bca883b0370cf3c607fbae70d8e01e854a98f19c9d1bfd8968b0235f2b94649e9b5fb4f9c8662497f65bb130ec9acb67ac2264aebf29c28dab292ed62d84287d0b880fdc2f6b3f3332cbc7ed537f8a25b69e53bb74a4317acc76af21d239dec803a1464b70857062a05c062d4460e04663b0b3a74b632598975714ad3da572f2743eb7cb45368d377dcc8580c6fd8b8ebeaf3dddb3403372c8bb80e1e45bb01749153e7468601792e840d9b3bc6e36bc1731e5fb9507c629fe245a53bf47e0da68c59d8b146a60619f212e370ee427625d8e40b125b178254dd1d8da1a11cb26f0fcc9237eabb3ff552e32e5646ffc903db37b8a06839754e5d109545b5f5b3a4bc8d307b09504c3739d10d99e1ed9c4c928274dd38ae2d11800b7775781012b3505cd5a9228ccacb47b776518fc13cbc601cb480c9314968534af61b80bb6d5aeee04224441bd789faaf1f8a914283214f94cf838bec7b5f43c91af762e50d9719a3d204f234d434713f07f37511b3dff0f34384aa289f1642fa6b058b6349b46d5a227cb8c81fedb20e6649536ee3310a6b998e14d3e0ef5ff53df2b841809c772d666e1a317c3b5a451687a293bca5d00b5397ff6a33caac6656a473f5b2b5838445872943c1fdec5871ce53396cbd1b2965d59c3854a20f77766f9551b34d3759398b3ed76f81d2164cc29e2a522db895c33222d7e857a88a1cc56eac4830eb6fa90b0ca16d707c2bd40d9257fa9481c7b0e3b49bfc2692220969e3f02aaa9d18571fa95d491cc8402e719d9edf6c42fcd7b51b784da25cbbea291bcfe173588ec9a8cb4c2bf04a300198004450eac625a59d3ca4f34148213eae14b556a8578ecab53db6a11e36cf44a532d79d078abe19a4a66658d3f01d4c239a26441b70f0772fbc73e0650cc6f38835bd3fbeb19dbd97e1469599d26b351c2bba28f37bd03ae187be642d333552721a13dddc780d065eff095baea0d768b4b152de414831813358fc23b7661f96cfd08c6c9e228317c6af6d2208db79e8da4ee7db9d5c5eab8ee447c7c2fa30e82305658bd850336896a0f5066e33151627b596efb314ce493eaa63307affaabd42deb87420cd80f6aabefee440f2ec367cbb25e3ae540e62e1a5969ba16762c5e5133c0cc3830ca28cc2e30a74a97c27b233c5d0693eabf8a8f49180f5b363fda1fb4df0f62cacd5b36643d33ff1a8fce76c777ba5334eac291e33c45e6362c5d12ad3cbd3106af13c7d6712ea9f1966beffdd4e610bbfa9d39a06a68220e14be5af07a61451e237bc436e4a40065f97a5e7b477ec80680aa3019ac0f471d3aa034d7759d4a678201c026c11ef735fa3e2096234be282484d3dd641924cdc6daf106d9fed6e2c747e05791849a661d7aed0f20bfa57840073f1a1704981ee9cceb3cd48332828a1d1", "e722c2e1da8728449d18eff9e4408c56c93d9224001ff530940683f242350686cfb0195b3efa598ae5f936fe020b682b764a6a446423d952a6e64ef3c00f9601090e311a028fed557b6b46049909fce9903733d7565d21b2190e6b5b20ae972f5095aea9ad4b43ce904ca9f7b7d666b4a9897a54639a02fda11703a733360825d91fb727c0e045e407b3cc411d7b3443aa2a3a96cb205625423d681f78ac7001c839b46b0ff401a879df8c21380dbafaeb96d6ed82f470bec7540ac8f10d308f3b96de84e2c2172939dcba73ea237234586ad010422fd414894bb42be15d032480d9639e66a4ee720d4ab6074c68e8b4e995bf50f232670e30448fe6f61cca1ed342313d4e3fc2c138ad99a1328fb6944d93cf8cb62a4a4018b3c58103e0f869c4dc11abe8f4c95e0f2dda7688c590ba9c9273643fdaee8aa79577065ec74fd3e776c003f90851034e3fb9de99bb55b2720c4f0ecb30b3555a3ea1284c1c524c1a56bfa233c6386af416eda93315cddb2df8a800ea143276f6bfdce9c0770b1c62428d93e54cf991454ebd69f9fe89ded461afb0a9e79b9dcab748f79e05b0c87e3037b9122ca462af0576dbfb3d47d60233baba2ee2dab7df4a584f1f3247c3a7f31cbcb98e13f86519e17145cff3368ec1510c5e4343e47e9ad543f3c8af336c9fd19b1a56287bf9126e3fd378a99ab3d56cf373740a011e0a0fb7f71468a2ae82dbd4f4b7d48d3952c9c68157e0adeedcdcf43953a4a5b424ddc83eb794a77c4cec8f37fcf140c84ef917e875b83a64148c7903166afc8e24b02d8d6c8181a695c15e0bcbca03e7ab11473a5631f1396f57a47c14b3efaf3b06c4a05573c29c063dd143b73741bc92ce2e2b6585e916be9727cdf0f0075d4453f12e92bdec75429debe118ba2c7418c30935ddfbdebaa8439884763613820d75229e62a8efc331e684cf00f83e5affdd39b5cac5d813d7fc38658c14828f11d9c760b30189410f5e52bbf8b1eb6ddb712718554c596986abc3faebe817a80dc853633c15ef40d34eaecad0338e98e33ee2ecd1deecf98c4685edf6535dae91a35fe803c52475c6648fe7b9878c36d0eaa1e82a893c1a5f7c087ea04bd9e3ae7cc9a28985170d1b9369ca6b3c3c19afa9d95ff17981592591c1a75e7dbd1885ae555987084ea5f6d5391a1d73f143562d007b6ff086abcb8d0e6671fd7d90fc71005513d78f107a2fa2d699bd2e81f97cf7ee40cf45b36f47de29924ec7d65e0d86de32745b028f7981c6fedef24988f5f1057581ab00fb52ff83aa3aa619137c51b34e919c06ed0b84b34dac1d17d6dcd656a5845cc54cf4510d715dea48e2bedb4a2a043718b58965e1a0aae10b3168998308c9680fa87d4da578ef186bd325e8433fdc775aafdbd7b2b4b5b27eb1373e9427814a3e850b2fb15113fe4f2a9f8a991eb97c4f9c92534a7d062978ba243e7dc9fc7493f89b15db36b0c4d6fa3f81fab2b4e9390427f7e07ff5f3251b5f27505b43eb1045cfc712b74a3c9f2b2fea8b6a17c95d2ec82c716e14b64ec3c799b2efcc6f4e019ef86698094fd7d47e1a0696a752214004abca9343c66247c2d073ebee60167a5ba560fa4ebce099abf85d1658324a628fce5134bebbb6abe1a208cc26784ea78b1cf8268f6cf703fc1ed344f8658aa2e80ba3666b44312f16c07966d0889c48f7589c50880e62d5cc0425382d8c3d83ddd7122f44d5e2c5791cd385eb70c4b01e8f2ef0f6229a6042a73363499435c6c2a3c2ca0b7d3c62993d6729ee145fd5d42fd1d8b040811a8657260da18836563ae04a299fe073ec7d78f84ad52aea88e5be3c59f865564d37c22b4dd0f72325e9fa18bd1e4284572300100b9da41d9de0e32aa94852c23151b529bef753361d3f5688957e751ca9bd450e00ecd158e337ce2dfc84b6768dad06f48b10b8b013021d2a66274f54fd803d833b7a130acfdb979f0f9bdc129133e689a16d7e6601023ca2b80a9d98d72aa6350e62caf27d91df526cf4939bad466125a552cbed6d06d152bf4bea0ecb92b0013c7b5f6b1d42dfd5c97683d12b117446fc00fd5f24952576af3bc82ab440a403bd28513ac2ac3f47ebe3d327871fec", "1c8c183cca7bc134bbb68224c25ac8114e802dd38c9a606fe558b0bcf39189fa785044336648b503c0326e4b9927f2693ed89c15c7973c502b5e1a932b34e4b66ca0b6e818db249b8abc3eeb71ac4c16dccc01a9b92a8c9a1d3ae75db23a4740647dd55658ebd663d6df2e5d73376155be38caf7750c3f7c4c50eefd6ef0d81fa79358a3fc2c16c5582ae39b8d39586b584428b5fbc5a2061b2a5107449f401d3613574a6199932cf10406acbc6f8d737cfb38a41d5ae487489182c4cb85913a172ec5c04018871ac3bdde90ed60e7183eddc7bead5f1db477b97e490cbdd046d8950e8bb522b2c30d15d6074d1d40c0d8ba524904e1278ab2f6dc7b2598ee8b8c40a8f893e2438a67c7a697e5b9356beeb313ecc8de90c44472887f6b5d76beca0ea2fd1d3792728ddc9be2ee3ba0c74d64677ade3a1c4b59c3626fc89e15976f8861f2d7515734cdacc1c5aee5e96d78deac272d7fd3646b7b160334b51a4778703e8e6bbff59f20aa14e426a6d840d21a501c5e6e25f3d8735a76d518c1bac13ff24b95722b04978d8929e3ffd708caf40c92a049aad686743b3c156816f0fab2c8357b175f528dfa0afbd993c6d54a02239139c93b4a0f9d2c27e324106da07153a0347b09ea2305ec3a85435127640ab9d59bb79649d6c8f9988152302af7542bfd6b81a2930b5baf1f00a859d60bbd11b644c54288668a301549430662c1732ff34204c392bd4b27ec049be0545e5388e2525ee700d60474276fde1573527761b65658119bdd3d708f417e0f76d96e054665695f52244c303e90210b2fc730c707fde05a8cbeb4c5792aadba253d9cb5dd1c075943612ebba6bebb8995b335d527e815caa3430d185f9709c1320948b1ca894ee7b961bf391cee1d2f15f3dfe1ecdc5746a43bd2e017d9e3e1371a2e91d4c40e46ccf993f5b1e336a6f19c15640d88e48d918c3c57ac4ca352639b2f92a6f74703be4eca01a78866479ae8ee1372cd60a7d125ed83a4a97010058beb4dea95f5be4a7e5c143dd69bfad4426a45803262f8ec8e4ac11ea9d66e3b06d29575f8c152d2277b9caadbb8ea7f58dc71c073f3a88b76bd6b7fc7a5355e8cedaf36d979c5fa5a9b04811af1c99ad925042cb8276f311c89dadfba43336f9f8d083ba5072a5ef2d7efb4d9245d0049a3366e8904bc4cab4f06a20ca933dc9f2df7d8d9dc318bb900ba5389fb6618074a9d6532f4ff1c9c8cf1f1fb9cd51448e902e42bec93cfae704c71fbf7fb269f88ecd60f282f6fc10fbcc57e718996eb69fa467fdd376707614318b334534d8b1b370eefa8d0748700f212ec939c07ca4127b6df2a4f4b61a955538a3ed898139ad00ccdaf5c615dea6fc3236f640602cc9e219cf5b943b475c821b656d5afcd5387da4099f7a358d6831cf44f198214647c8708a7693a797471a98d468793eb8beb2e9e8bc08d4228ba9b0785fd106607c9dfcf5109ebb9b2a0cfd4c6a39c35ecfe69a723cf40a5aa44bc1dd1006aa14e8cfe092bb8f4b4b8d8a445f3466fd71b0dc1752b96a20d43cb44506cb3681316e9342b9c5832050805fb450fd0cdf6041d96e0435a8081956ca436fb32c666746cadde45622b8cbb387d1db2ac18be789432013f0614aee68e55021480cbb21dae04419c7cd4abe84cc84c3358e2074b05e96ee7b992845b22ed3aef692c412aaf0c599594ed844fdfd80902effaccb3b7c64b71dc28fb88b63d5c1ca67ecf4532d115f474ee01f6379309d7299fb18f814063e237a786daf7dd151d0211c0fd08003ffc437828df295c1d1fd8fcc4584fe4815dbfe1b592d63a712a43ee500ff121c8d8db9318e7e01eaf77c019e6dbdac753bf97b491841e28a9f54b5b378d420bd4a5e276224fc1f10602334873537cf24ff5cf62f6fdea8079fe429173f19642b40a9c173a7945c1abc6181e75a0498891a63fc3565b97adabcdbe47b2cddf055fa00163d57af57624dd852226666fbb70133521c60ddab5065280eda399acc7f87446a30e614c862e5cc13eae4a3010f73556f35f14ddafd3f12bcf1b7f9b08ee63716713f5785f24c75194705866cd447a147c282384117f55e989abcb1490dfbb92c064fafc1bd", .None}, + {.Add, "-1423aacf9a323ea6d5119adefa0dea57bd6c12c3c9b145cf959aba3cb92666e8f0756be9ace927bb154456b13ab93e341ec032be46962c295aa4db3acc86f48ed94ce1d6cfc5d2061cff1541b4b49ed8442b22f4367d7a064c183c99ccef361a0a4e02d96b0ff3909d47f1c5c7e14b18c569417cf3b275a0c9f39371c1556f39ab91ce767897b0b70c7b5599cbe76611c544bae9a529b1268aba6d2f03cd114c96c59caf19e965ba5696e055a5b3f07a8c0824bf1009ba10a4b973f523ab93f50844c0e4673606a7e0fc871bbcc06f2b20f739db201cdd391646ee13369b59ebf079a0011eee8f6e79093f6611a5c49650d0f2014700e80324a78ec28c21ea0b090c34c885b4a555727f9d08dd85d69e5cfdff338364e6dc2b64739d98d161dcd4658f61baa7d3d3d51a34f7708f37eefca851f2f825cc2945c31be8b34c209e61c0df25c3e5e0f47397541f22afbc7d678882fbe12d647ffbc8e7f68c54668ab3c7f8c549a56632ab15927ee226d7f1dbc388fa6822e18b5bcfc4cff8377304c4824ce3ae0079d159fa5be1b4073a8d3a329483aa7b358ed00fce725750154d14b4f310a9f1ac4ec8b3f3b349235d1e40d28347522938fe719d5f95321ae01313ecf9a89d21f784806ddee31fcdf21040f6421cde98107bbc1b3ce9bd6ccff7f71d6bf7a83c5ddb76aaf921df83c88e50a330827cd371de5d93c7a01ab0c819f629a05bfac88a34a9c3b39b99b93fa6c45319abfaf24fbfc672f6e7e3f2007c9c5c374f87632f8f03a949431dc74dd1025cf2d79957a5915a516679c229db19188b89a5515f8fa6447321b5494f1473c95a08ce7009a2859d34888a6bb84e7f577601f80c506ab19ae57f3897a3d2f7ca7b285d0f137057802eed02e6cc6298f1047a82604ebe68f40867578e2930a43278e8ce7c18867364286de41a8f0e51b9a976fc7ec9f6715228936b1c39430af0eb09c568f0fc14b0171a182f9fd3bb009e64b746e453095168cadbfa62fffe25483e44ce052f1952e311184788c58e6ba7540fda43fe4fc68616723d21f9966991492f1b47ecde29c2f4ed90c27bf9a041f7841b716d4179c108c26b58695499280d5d7bc1f0ca7985c06693f6b0fb31dfbb8aa5d0b34cb2a028b5c36ff534abdf4f3a4e6e5093db00efca16af85fc7c46818fb7e764c8097cd1ed4bb779297e84a6d27c9e6ac6a0c727a222dfec4d07bcc9c4caee5573186b77c41bedc2a6ab0a425c7af28dff894d0f606d86bc0e58109cbb6040419b64e5e91819248f8075e8c30d0541cf90ce20f691268cd5e4762ec2f6d2bee6c399f33bc57ea3b1ede7a18815182afe26b4b3f400353233f575e4183cd1431013a8572905d7cc88dcf21d9f8c41ec4376b766ff552a15f081459d9a0c5b89e3140b107b0f7ab4dce483a905daa4550e5be25117011147f2199ed06a419503026fdf58fa2f3afa7183c4f28beece1a795b8dff2ebf6b7f16273172cf034744d5d0b22b6a4dc26ae9effe54e69956ea0a9fbd16fc5f66e9568a1a5dd3da4d79902bde05ae741a71f517b8043b10e1c6261d600c6bd00dfd64a8046b5b78dce0036b5a9da99c8d606fecde1d9111f8597c64b1bbf6bb9b5b690d5934c5b307a4b9a81e00c0ce727f54666dff228dbd8cef6e0ab21a0146eda92afefa1293619b45097a823b9f94a1f3f1aa803bc4d4b5e87dd3329afc5c381390f9ef61421ca66a5f874a717a0a001c72b995011244a1c94b17b8b0683289211142a0e8072fc99cfe5d4847eeeab51fbc2b23e05e18ec891591db721fc8d1330855b4515dde32d42def2814673228aacee99ddc313c0bdcd715e135943a036ab611b33480048108d15a6a80b8089fc23532696d205b38a211a06f381b1060fa8c84507ce4263c77925cf1f65051b81676878a76180676e7a871ae1aca36bac20502efe4b2a6250535dbf99dd41acd26bbf3295f19fee11df6a65478a707f9d483ef4f55869d1406a24b6f041439653968b1fb8d2c66b4c33debfd9fe17e85e9742483459f8507a428f835493401816eb4074bc257e2de824d329e748ef57ca6429497e88af7bcb9af8b1d7f38376c51dd49d3312027f3b22e508a5ea5", "6f9f1968f5048d6cd39150484781ddabc03d90cfa56ad3c059e159bb1894e11b1c05d0d69447fda97516165e14fef714b422d1b777e3bd0684c0c462e6d7cdfee2cc3c9b4145f91094c38de87f9fd92e13248f44d32e7c818061179e72853874cd3dce402d103b37a8753007aec6b7df8d6f56d611206f1a361e5a2571563ff0b9ad810341960492d358337f7ce155651cd416cb4239f24953777f39a9a2c77f3fd9de195e2493bb7b3a3c5bc2b9eb55ccc1f5fcc27cc2f3a32bfe03ec51bdeb261a61a2e2ceee1dac95526d0cbce9dbe475742ed2e3076b20ecdcb46d8e9cf57feb0559cb8a327ed4482a4d43384400d6153278c73d0b4a704e4c7db4dc197127a9718fc5449522b7c82029f26ad077547c6a685cc31c4fda785d46d4b00d5ce34d4345c2a99d20d01f6e29cc4d20fc5b6e5d34ae6fb7603685451a353e579f0e9ac14758f1b8d2d036271eb21e4b32d85bcbbe10685c712886d6504ea600d242de87a5d4bab7f66793534ba75ecfeac69aee229db8989ad31a3deb9338acd998545d93897deba609f9a5d12a2a619f478153c9ad9243099e0236c00be05ecb8050a62797b8f1b3611425264c89e2f13930bd858636262a94dce91672cc76d7d4d1f74df657a1e69a66ca8da4621fca5ba15a174a7c11c36171755c7e7b15561cfed79a29cd075551614140da66059f3c2fc7f47b96aef3171f0575c6b3141c211ff77443ee1eca818f4f4ddb9ad1c1a62f63e58513098e6c8c4d827579663815ac576ff27d29034effed522be61a7376d495b4a808079835d43ef285f36b53620352048800059ecfd250fa9399d3670e66091f065354eb2a57a3bf66422bf64f0b0dea1ed264e87e874f45109f09d9d52c0ab32278cb4c923a430375b4f7357a351a97bb7bdff53fbe034e393b5e0ae9d7234e10054c1940dd8c7723b2fe1b11ac5ad7b1f3d1e2ee4bf1e005839f66d2db24fc88533c785591f7f6e3fab06849aecc2c4da4e6a1615c55a7a4eab31a171fb0885d44a229c72234e9726a82690dd01cae03415c1c588ea423b92c544d290ab2b89805457e5ca4b813f3a2c942046e1e118f1014752da9bf9b699b740eae73d96a319267b4b71829a357e1841fb5845dc58b8143a9b47c23e08364ff7877312285d8719a5d61db03ee3ba2991f6e4e21515f8625273d42a2921f0f8380d9811f24cac6947f4f1cfe16654f6df03442ad3427acf0220c938fb5b687581d123b594f4aeb614707dcb4e2e234c6472f147dd7ae328ac55999ccf91cfc3a2fbec8d7b4e1d98533805e616b24b4d10b13b0a8810087c6786312cf1538813d2a27edbb076d92f4046bd1bdab611985b547b981de734f3d925a6e21328fa05d3c76bb3cfc289fa576bf29d2d0a1ff36c5c91181961ff599408497f3a8ee4706445a089d68c80e48c52a0cdc3342d4ba86939e820ad905e84e01d642c9f508cfe0d8ebfc86c092500b9a25b471da2cddef16796f24665b9358d1a81d1e2b379375ad1a9b4869a85279bf710e08adf37b27894a9037b80994e3bca8eac7da91c8ffa97bc40f08fc28e5bc696b23e54b13437891e98be3bc34ccf8590abfa536380b59abc9370610ea5bed747b073c623b0617d4a39f4409e612d1e842c1e0a7a8e4dc117ae83c039d24be51636a7aed261c9e13c7f7f0450f9904d661be0c8dfbe46d50348d3fde84a3ce992a9797e02fbabea3d97e0d76c4c94d50202744f22d5d16ba884740a05fc6402dd7c0e14cceaa22fa45433e4b23a4e5d33812d7a6abd0ca473693d712e031d5984814c0e8500b5fcae2edf684ae87162e3923ccee29f3097481e41b9106e2848fb7ecd10a73af0d89a15e4f1fce29c12083b140bdefd28125e690b234ae27c4bd5b6763dec1a1605af3a45889fa876ce1dac5eeff4ad2458b7c54feaff791c7f87e52cf28ce8940d239b2f3463e9424e880c95a6da60ddc9530e6a7e47336f7a53c4085fbc7c0e03a49329ad7fd14bb91d4cbcf31ddb7548fa9c429ce95684731245fb4dba91579373c1783aa2b01893516318bd732dd195518b00c0d57c269555826a37ce4aaf604f53df0e7bfb07a33313a587c3f79aaf309d0e4776469e7d54666", "5b7b6e995ad24ec5fe7fb5694d73f35402d17e0bdbb98df0c4469f7e5f6e7a322b9064ece75ed5ee5fd1bfacda45b8e095629ef9314d90dd2a1be9281a50d970097f5ac47180270a77c478a6caeb3a55cef96c509cb1027b3448db04a596025ac2efcb66c20047a70b2d3e41e6e56cc6c80615591d6df9796c2ac6b3b000d0b70e1bb28cc8fe53dbc6dcdde5b0f9ef53578f5be19d104122c8bd120aa5d5b632a914416a443b2e0124a35c061d05fadb40b9d13db27308e2fe728a0ec8a629f61dd5a0be7b98e775cb98cb514ffc7ab0c37e3a53b2c62a320aa5eea136f343098f716558ac9ba3105b3eeae731927f6a85444077803c23474ba6bdbb28ba2f661e9d3cc73f8fefcd4548832114e4f9d8f77e6b34d95e3573af13e9a93bdeab800ee7b3e40801c94cfb0539325bbde90d5ec60b41b649eb36f0c2293181f23700acd9e221950bd7de5c9ed2ff8f6e8eb570d348c22f3af7f12cbdee59c2519a478f168ee08b1551c3bc7dc0ccc537f7f8ead765283595b70f774a791b9b0139d4d3d210afdb7d71d4afff49ef762327120d4ebf4603170d7acdf2684db490497e6b9bb316edc7456498603173036685d2f85e3a3e340ced2c233f898140b196c4c0e4fda55935aa6219f8ebaa84942dba1aab17fa6be40147a5563872c10e455e25e16ba28190a979dab6481efae23d10eb8c9771fec33d14b98b3dd5ac024c022af6571849259495d7cb9bb241e1921ae1dc4a398a20b9cea619569a918765bb795020206b19f9744b56a40f0e1ecca27477a2dd0eb06206db82d878c3c9903a4977c85f36a075f88b5f2f454a4abef3450c00509649b2658d231b34fa89dd76f7950bf21281fa36e3a1d00c78fb36e20ab0e25613655af5120b56008ee8949c8930a0155b2d218c4bb59bf6ab122d66b75e3a7f93ecc5a5dcb51e930923efc95802e3db3329db719c235e74e94a5c5be1f01b371f624063a57adddeb45adcad4910677506c093980ff38acbaa87b31bf1d772438f3f7310743f23d12ae1bcdaa228c89e28fd5dcc92088db17c0a5ab6bf7969897cbd58a032e1c32662e04d48642c268d739ea733b3e8b6d8fe430aba154bcc0cb5d076ea3d92693cc3ead32483a4a23ae5b0905d01dbfb2abff50a43cb51d34b8a0349c986da142424f31322f2079fc1a79ec05f33c5d0a4d3580a575afc78524e2829b8ae55d674426f81a32c85e36f5cbe9aaef42817f19a999576673116f2cff8d3477e8fa58274ae0a38d703e11c4df24929f4b3e3e103d7aaaf48e014a7dc97b5a2b23d6ad9fe27fb269d81e58a2dc8dfb4c91f934fb9dd8b3c404c32f25567f5ddb71dc9ab2be751bfd1d569a1a20c2d7eb216f82cb7d3d45f849d9d6fe6b3620007c2d37b77e946448373e789c46bb62c798778997392295fd65f978e23b93a6947bbc532318cc86cf4ce17c94402e5de227d489aba0e5e5d13f97097f277d6b00c2685b26eadc7c7e506a0211f16bd881f7cb2d068cca985aec5b4af12be47da025a11a9470a249d6eecbc5d6a9004b7dea33c53c01fd3e7f17788fe273602c85c5cff53d74dae9b74268e1306dc31619dbb612317d5c81e7b8e38250db76df73bb8844ba106d1f8be9fddec3c652c6ab3e781f36e28547e6e12585a7e76adb6b39f496933ff7cf19f19b5648ea9ca8f8a54261e77ec07f2c2cff8c86b289c25fb668f9b3ba81c29c4b4783bf0d05a69c605aead3af210ea5d258734fbfe967b28752758aec3ad98e0595d3c0e8186a6888af023ecf18c149f235635be26571c43bcd5f4f8171d030a1691901851da59270624bc9ac57f241fd6a5b2df852a0b6eae8258970708f8fbd66cde4a9ec55866b602f9381e2d9d4ebc797056fc0c16244e234c537dc714dc0a76c0324d82f50fefe4759d47345bbe01063cf8390fe9564a6388986e0c843de255004d21395e48eee2f53fa07f51e96bd1cca90355405150c3997e01f33cf0eaf3abfdc3f6727022d0b795cca44ea2941c97c319d22a5b33847e3655bfa154b3f677fea286d890ffccfd8a55c42912095658292ed57536b6e397ae003e68616d0cb2f92b0600ef15b202210fed9c611fd8b0bc83b23b974ae7c1", .None}, + {.Add, "4dc3d5f0c42c0bf0e256c8dad6847ab0cf725110a14bbb492d8f7919087d86a5732c58e817028d02e30c52112225c380742001674dcc2a0d8136844644cfcc5b32f5e5761abcaf04c1dc1b9fa8fc44801a391a870cba65e6abbdcdd9f89b2a9f52329b5572ee8e66a7259709ee4c89ae70a088d81524e312771570d1e22ddc5ee61a9f260f603bcac066e4fde30d16a8cee7d4934f0b1901a1fb3c821e2e6fd25e684ffa5a97bcf69a83fc875efe92d99382433719b84fe535a7c5eaa3c1a943a75ce4748ceba76b3b4d7bff3113154f1e821cb2603cabc1739bf4754195b3f07ca4e2bd45aa5037ab7d1f68e3c9cb4fdcf69a1d26abefe27acc583be3ea115320d3067f80af37f4765eb290a4aa27d0b5dabbc4dd1cb067e73572d6aaba01f6ea0d3ca0538e50da893e98cb2f0d8156b873d4469391193891306173a899939b9961a945720f8cb8010fc82552d9af12829f1de2039ca2932565497ce3d6410810f2cea38b98b429a2281469261c1acffd9e171410ab6740687b06c80fdc222c698d3bc53c54e4dd50e350d64a65ae35a4829bf394b2930eda87cd50584ce6df445402b1b5b8f59b0cbbacece5ffbc047a92951dfb0423c7ec037ed44f3ccccaf99397873ea0e2ca804b18de9c30f80bc9e5b44fd9941509dbf6cc3f3c6d2833fef2ac7d10a469fbec886e8beb1cb6824ccc28e959fb1059360ba471b3c875eb45e8c2b38eed6d362d8eb18e217c914b07be85dbf0e572180085edfc19c8a9e22bddd78a00cf7969fac9ddac300b9c9bd0cc596b8bebd5b4a0b07d17c17a1dae70ceb10a3911adeaf7ac7d7702cee65998f247a738b412bb78c336cdc681585265de4709fef3a82252de5bda3a64914cc1f70d179ea4181245fa12a530e35a83503a41ee1b3d951230e8f2a4576db08dc4f30381559ab8c92361e40ecbcb82e7275f12fec21da45ca387df86ea27bcf7a6d881fe45b92d1fe025bcd9167db28a5dee14718c13cc9b808c990e02d26565a137111efe3d69c2251cf350466dd78c47c65c8a2ca53cff364d9f49fd291b7e169e31c8df6061aa93a3aeca4a230bf8b80bb33abd81cc29df92d346c890f2f01e189fb39c2812576e02cbce228ca22cf532c8ee88f7ced8fc08d32670c3ed4e463e1d8abbcaebc9488a63a4eb16470cea43ee8f83ad9afcfea482fe3d4255bc1def00ec9cfe3424d16d959848cbaf21aa4895c51ce5dbe709cafccd5d960c6bd5090071cf97bbf55a4ef7f613e397ca2647519dc5834783f8e096287901ee3879ae97151616459740492e3fe7b45a5948cdd7f4ff28c17e361b1639592b8722f7bb9e72e4fb9e7cc775702a3f5ed3ad4958f8ec10bdb68c2636e0e7d19963c75ed7c51b1738eb6a5bf841c8762349d66ab6d562058963516f8fa12f9ed65dd177d187ba2631d2a91bd98f6ba50546254cf4d833e603d4197c31c654da73ae516dbfda9c526ce8c982cae60efed1370ce72691f14cb809369f22f97aa042c15fe0b7d85b2c61b7fd5486db8e260b8621cad5129d8556655c0cc3b5d33f9ec388f787fa2b29dae00fc9aa8525c63d4da1fb00c2c52dabfedcb01c521a3a15dcb52009a51c3510859e02e4ba5c52f8b60c534cff88ae83241f76ccb8b134aaaa010539920d09095695feb0b28d0f08278e83de92ff1d704ed6b8ceb0f0e16a4d98cb8ae041099ef5c1138b2c6f6069bf2c60a1b12af90c65f6f50fc3ced77613fc1560a7ff665abb351e4e07c2685b6809fdf618d850188ad24b05e590c6a6f0dd18b66df156ae0b3e729c56b868a49b37d124fbe5c709a6e93096e7696f59d2815e4ae4860f6e0cc60a33938f3a0a8cf07e7dc9b95f82001c263380eb4a1391f50b9355f49270f30b28d14d525f44f6e689b20e80760b9bde35f8ff212f6ba7b017087c3a02621e182d7365a1af94d8326fe4585cd89686952666909ad6dc861344c9e50b7d8aa03339c825cb8ec2a3766099f9f08e220e3fbe55fa1168f1ec980d37f1067d0139b2e0775073ac30116a25d0f53e51acb9e0cb1574662da182e274a5a230eb40419ec06c994d4c7ff6b68de89b3e0628ec88f5ae578f37868c69d808a463a607eb4b49586705", "db97aded0818db256b25834157448445396d5c2729954730dadae36e0cb3917bfe68d079cef64dd1d7a8f88161e2cf64bc8ce1d1ddc58acb8ce32e9bcdff27e091c4c56d57a86064dcbac111fdb813d35e75314a3df474e45574845c5848949f9ef44fbeb342ea999ca806bf76c4924c31f1954b8663fb23747cca85f7d8058f8f2618e270904d91692ab9f3cd104b94cf39f448c878fc3ec6564d7c7d904e672b8bff2a3137f87058e7b4803e29061e59967cea0fcd9ecb1509331fbed14f8d0b67a393c9d61469b9f5c3de5cea243185822a1c362bad487ffe1d32dc4de23134fc28eddd66ce811477019e9209b287f47f800c3d3fe0d3bfc65822f1cc325f00dd9c909a4dde3d418c64a40d44f9de32179be7b94d98f4a6c29d5a0072d715680001ca3536d859fefa6f1d16c18da68b3a2a98da6203be2147bc9e5887e3b61f208ccabea9946d351f419327687fe6de5baa5da7214aa4026ce468216d16426d8a8ad19f60c1cf6f6429eee42cc8753e323124797349b898f0be1bc5476b1f08c8fa412517ceeb1e2a7a5fbdcbba13c2a528c898acf81ea11c56389f20c4da3ca0b9fe489c3f50a0692e56386a19f33903cbde8078906e2bc4b8e106c25fb7a0b3014e7ae1b5af6b06f9a637c7dada56fb1302d4cf804e171315ef9654055487bc0470ee19bafbde0af24e112e4e1a0853a267a72c888a6843604f09668e781a343e70055b08c84122350300e723b0fbab08f073871592e75ba0da5189bc21a3174c6b5f566b8b7cbcc4da0eebbe9d4bbf2f8451c36a9142629f919ef82fd4eec435c731f95a4dcf1590ce6eae4ba4989c0d499196e00809b4b2d6f6fc446baf7bbb55e3aa6a96858fbfc3a07e6d08245f4ec02d96f298f1768df5f907f64ba6aef511390f035335f1fe819ef803a286cf238cf9d529051c6569be3c9ad96b0522ebd4cc02806ad7763be7edf8374cd5b07e3e997d007b11304dd71e640f71c304fa23097b1477a4b453b24d89c89210f344c67d3f201c0f0adab3cd85c68bd080a8d229eff33abd8169f4e2b94df0c56d1e95fa59874b1c5e3bd13bac78cec1604a55d415b3a3850e5de2ee1a3fd12b7eea7be535613edf2030cf9c29fd80d02ccc4ac74f86300d4601803d90ad517d85bac02b6b8612797e0d61aa22bea70304a2c486c20db0ed6afbff3e8df87a78cf851d710e1a4ddec227accac047decfa00dca59149104f032609eb1e3274d35785c6e743dec953547aef8a26b2e886a6862daf7d90e81be941775c82b7bd7a45f082a282c4ef9735a3e927552b0423e887ff9a5eff6d5cc99a7098da67c36bccb8efc5300c7e86fd620f02e5a3c168b9e50ecfca089e9615d26728e47831d0de651a3ad6b451c093ad491655d2b3709d03bffc9f9aa59a99d6c520e873a0cf2b5083449deeefb225ec55faa3a6f1e56c7be2e20273b79e4e0fa37b567c46c09db9bd363e91010403bd82ffc824756dbd2b255aebf4027a9e4c9c0b8ea63414acc39b92359adff493ba76b35719ba3840d5ec287fb6807adee7fd6e6fc59b31cada1fac6a4a500fa023dac8ece07d3c8139534d6b90350fbe9f07d692cb7710beb6ff0faceef063321d648438202e18ab53bc6bf49b9193e4d3aec0ca31f29b6b0ca1ce1244859f607df79f8b50b48f0e02e05f346ebde684e6b8678273ed7483815d17c7e96d36c98297a75de02a7bf666603346fd10d5ee4090e8ce6703d5ed88cbc8e1b26757729ae9710900b0c52ece32cc5aa4fa7ca9e137e375ded3b57c7d934fe87396438c416c8eed8aae5ae8b18cd4b8f1d34809714418022dac0d10c31323fc6af40de0ddb91d2dbda6ac6c773111bc04b099442d27013ccbba6ec788fe2e02c9d4d484a32d84e730f7f97b01cc55e7c1388c63eeaa861dad8bd9faa78c147eefa8bcda2ebd4262d90c65109ef9cf8fb951e5f4c3d9311694b959b1dbd0c2d22411180c11642b8f0f2d208a54344b2cac8db0dcc56f48babece12d62f66ee9670e4e5b9a88225780159497d2992c69d323e954b50eba01aa7f4b610b7717effa90935e23e56260200ca8b91bcd8e1d10427cc5d2d703a37dc4ac4cba32a8ba4d49c80097497b", "1295b83ddcc44e7164d7c4c1c2dc8fef608dfad37cae1027a086a5c871531182171952961e5f8dad4bab54a92840892e530ace3392b91b4d90e19b2e212cef43bc4baaae372650f699e96dcb1a6b4585378ae4bd14aaedacb0132523650e3bf3ef126eb142631790043cd9dc965111bfaa2921e239b88de35eb923b57da05e1ee7540b8087ff0895c29919ef1b01d623d9e21c8dc17841540685189fe9bbebe3989f44f248bcfb566f36bb1079d2798f7ed18c0212985eeb04ab0f90a6292f8d0b2c4880856c1bbd4f5433fdd8dfd3980a40446ce96685909f39a11a81de39621b1a10bab23111eb8bff4210775d37dd7d1761a2963ebd0b63a92b05ed5b643b221b0a3101afd1631b7eb1734b1ef21aee7f257ac966a495c8df81030ab2cd90c520d3e6a88c52934883907e845cf0efd43adfedf6df31cf6b2781e1201217751b882361030b92125362f09b87a422ef960fac83faabded3727d22de50543574a7e7d59752af975f9118c3e580a48e3453bd048388a1eb0f9016bc4e3d5238d4b72563606616cb3c86f0dcb36083168496727c4bc2d5f8b2d7ba42388f76dabb980f4bcaffe5534ebad24db431e69d5f7b39660fc7b7cb43617c837b555ff2c829a4698d5b9829879eb521284d3f8d2e620e0c752ae639557f309e22ed2c12d8886aeb0edfebe24f7ca9360d9fc4b049c551fcb51012798e39e4f04c0bd2f0463601d0123944875fe6eb0e6912263b4fc03698ecc646c87aae7e18ed66b526603cef523f56025e4f57786a2863ef75b391c8b88efddaf4045e3131ca960724d835f92e6d16b0b0838c6c20e45717d31fe318e54f0ca4af2c38277e9a4bd7d9cbe155a025fe29e12b8d86e1b9ddae2fe54e6565bd7cc3b0aab3770a09b29eb50cef6e936ff544c986566daf125f665b4304bc2270e4f6fe1ce3fc74dcd08665c522c81fed38e2024c77afe1b6ed81ff4447c89003cdf362d9af1560ab034e1c1fc20f30e94958ee1132540ecc0505c2df7b22a55e57b7c89de3427ce0413f39e181847055c56953039f3cf093edfe2696edc0b505ed9b9e8f5b001ea9b85cf84c7796bfd9091977fcd64a13129b6ab32c149978a2f815d73964d22fc9dbeb69fadc55f953950475509094ed4a6ae549a9fc3c3d84ae73671dbc2087106953905b3ed4891540a6fa8adec0f7efd7bd04e3696be860a0e0c4e72b02fbd45138bf70079e8a38f75fa6cebf9fd5d6c0f7933b90a815ce043d5a88a8f96a6eeb64ec65290afb478bd5c5605b774ad9e412d6a101e0d9f3f3e429490b3a36cd25d070a9b875657eea518b85402b4bd42e6d20359b4872d6f37fc6665374b911a6db90fc3d4f749d90d5e40758794075a5fe0e6e46cbe16bec4a4308665331659db80750d74871161cf830dab192d0d81ad5d97de6a868fee7010c1a43e3854cb4f3fb543a3bc9662062b0f936112c08c8fdb72bd779b766fb655f8d9c306be3efb537e63c2f94446fb77495e4907c33b592d24a12b8412144fbb65fc9dc282f95b7d21c54ee271600d51cd63bab235aa269b1d3c14359c25f07f8510c3acc2d2550b5575c31457fa0465022dac064297a34294262bf5150d2fdf74a4360690a4967ab8edde023b4f6dccdd38b519f39d414dc92abbea5c29ea2d9eeff4b8920707bd32d774bec10510b73ab5211d1c7759918c7013c2f612861d8c94802355e9d647c1d42008172e2d7c370453f3ccdd645c8439743934bbf475e1aa9577b65978eb731650e2fc0515c2da7a15a3f90efe04de18707e4726553544a2ab606d81577d461d7fb014b31298c41db12dfbaaef7cad422f5715b84f34bc06e8416f210ce6675b45453cca7b424b25ba76535b5de04d9bf80be5d7729d9058711b802aadb8066621622b45d487af66fc37e9c99146806db6b2f4fb4a5118a3fb165175d5c268f8c0ee47f9d1921bb385b2ce2de845d1a8dfe7a217aaace144ba893c0e47b39648693f3d3540ecd71acc225105f49dd9793a9ae775666848013c11d89603b026febda38e6abb7fddca1fca83202f4c022dd5b11948db3ad2321e907eafaca0035f470468cc23392f05bb812e92db04511624c2d70c6055351349efb080", .None}, + {.Add, "840fd3cfb954636595d6c50c1d2912849de62a8b57cbab69e299e7874f39051fc25cffd707355e3f5f9460586def397a8fa9f2a9630f511bd47052ac63e3845d18d5a5bd4dbdb68cffd06174d02e060887053565d1e5233da7255da9939c6c8e57f898aece48914d911ae1e8a8b4e48fbae890430747ec881b1edba4742806a0aa4ece6c263f5b1ab5c80497ea6f04f26ac916ee4b8fd6cf45534d29419be5229b9000566485fb7e0942a71bb3d5ac8911df3629c872bdcf8d66b2cd1b31f5c95b93e8ad8295b5379a9e7967a9ba9f9ccb6a84f6df04c3e23e62bfa5a31368780297bee800e8aaf1f5392adbb03c2380a8dc423d589001905926da1906173744aa9ea76b2455d4812d466dfe922b81103d38d0b4d5cd78366c7d4fb7bde11a2397d91b82b2485518874076ecbd638f0784a20e617589efe9b3549e842e8022acbcb562b6a13663df59db0ed40ea2a0c44ba1621face78ed28994fe2aad8b1024d97a77c6633e634a48bb06c1525d453255105cde08a1716aa9ed878a76d0d3cff961051884a496c006b8c72314749f527e1ed3199734476a3c2c3c0cef1cfdd26a48ee1143764f661df42c0575449ab568e8f5b08223a3ca68af533a9b914aa3090a35511557bc912ba3e2423f0c7c9432a7b23a88b5df084f07a59d4bfbc76b9e7e9625bd1cda509e01cdfd4386847994625b82fdf154c287f0baf55c49b3c2b339c339201cfce341cb87232bc2c42213d46e66b5155410fdfadbf5bcf43982c84e0ca5262a53fa0a7d3d5f6d9aa803950a4efde9e1222dc6e884130d865540af10d0b02de115bb724e485e6a1a38881d0d157536f4311778ffb4efc570358bdb75c4aa50406c820d47ee2e26ddea8c456e3cf33ba63c3f73fbab1b174c0ab7042fb8e27970a0bac1d539645633fd215a24df86c1584262afdb691bf6f4e88fe010d116f25cbf547927a71cfac3548ef8942826df16ee467e0e8ce4f2b37ca0fca404f11d597a1ad5690eaeaee97a12e068979905b988afca6844f423d564689751568eb3c40b050d9e6580545a44e1c6d8b01a2214d8523a59778605c2d9b689c35a4728e1428212a0e981773cc3a371db80008f592be03b6cc28f85e1eb291651851949bd08eb7fc40d29e6c4a8954ee88599180ec6c5cc92df05d094bf067f95858bfbebabd6dedbf96016ec21cb8154cbf90cc3c71e11d9bb5d71753a10930b1ef8c8dc587919131670cc9cdb6e2b998bd3215eac8a2c12ded0e5bcc5cedc42525fbe3ffbcb932ebc0ec93bf56515485118892da2f2536450292dae8108d43a0b624b84ad6992569f8539f52fb861f462cf15fc2a432606cc757117c58f4cddacf39ed4ca0083300606afe20d02b1fa58834a8e42da4d3ede558080f2347aaa674eb3a17e68dfed2ae4ffbc0abca4d97509e6333a428d7b2e6c12914c36ca449e8727dd7b9083f6a7baeb617c5f37e86c4c06b17d4add09c79b35d40c3e3a40f38d54020bf5fe8042ea15ccb0f759c913db01aff91a6f3bacb39afcd5f743e5f2a0d4c95361c5164120e08ddfa5e57f76e20ac3de6b9ea5e9fc0de1d5acb6b1da3d768508062431162dd2e9deac349c9658b814180c7c852b432adbd3094ba7dd77dc1056b721a7e18fc7d3bab7dba6e7b33050aecd0e944390dd8b169eccf5ae64ff0ccc951cca43134b4a863be35457b79603b0c66c8581f44f716a543f9ab43ea1189e1bf5f017ada85b1f86d762c10e8468cf768d73c99540315add986c74a2604b746fe3ae593fcb438dcd2ec95f62dd58ef29882e13ce6c90da3625abb3266c32bad0293a540367f5bae5ba73f968b00bd6f3374f5f91c26536c2864f98e72541f08be533c9dc6ba262c1cbb47702c5260460829941e7304a19adaf5e31a7eeddd71f66eece641e541fec8d4a0a4521577d10e55e80bc50348d19e67dc6f96e5bfca56858e9140984866271fcb2ea1ed8a4344a0818575190c65d870f0ad92b2610da933fdc1496e28ddf3a7bb3441173bcf63cd31e6c01a6c460f1a8f6160d19c4c07519809112812c58c96f6b97a56c373e04e1f6a3baf22abd5ee604ca6789a0289810235e0922c4af4cf8b9d4775c42efa2c853ca", "ac01f6ed39c560a568ea91bbef32f5326a053cd94a60d1f1b239188198456156d9c949c03b264672af307e918ba429d1651d0f16dcb9209d3889c6d2f1e806766e9ddb7e99dcf46c7d50075100a98495faceb3d6220a20f22a3871a0bcdb7a1d389008414510aea070b8fdf314b87717a4c87eb09d9c8bfefe3c39fb415cd98225939a6e2517c660d775a9139f41d82a0a5688f8185be38938918d8d8fc506597f4a888904dbf99defaf874e0616ca084ff46a72ceb934222670bc030903389adc559c04153a6e3d9a40db4b0d8a70ea033e8d651b3cb0ce8025c2864d044312dd93bf5800b5a86859dfb3fcaf226e4000aba0cfccd369f68cd1a81d5ba0b1e63f0b267bd099a4894e51fbf221911207f86984f4e00a890d449fbbfd339d34ca3c1d01c311a4a8f36ab6306e87b7e693c0012886e21b83c43bc33b859893a02e8bca0a45451e7cb3412ce7ba20b65d1aecc44ff57fee3a9e29545fd693124dc7285abd34402667ed10d4f102d60bb37ba2b64adf41b1897c12747d3e854c0cdaf2f0edd3cc72369c5f4d8022305c36fe95eb357f1370896c221ad84550d2c6159e14a4245e815f5c29f56d85391fae707e11513f8032e45c4282caa6837f3003e1e654f6cbcb15b3e8a6aae1631e2fe648e6334133766079f0a77c2ef611290f3d08b61b473b27f7fb54111f43d3ab05c888c0aba61b9be557d2ee3e92cdc94b1a620ec7b9caecd54987c9d5dd59880ee95ff172f33cfde51d0272ed63cfd2e57250718be5b593ede17c61faee918650af6abbc9b41c86ac0f31c2823884a2a1ead0c8ac2cbd108f2b0fe1f3130175b61e895cef651833ec98c4840078da6efd4c6682ec114dcf1ba2bad7f4a94ae0e150071925187a8d36297ed4b14b7e2c0fba0a1d2fcbd707d74e68b86ce94e28add601fe0500a77c8d804e25545fe879f58e9b5f93cd9e5af939f213d47ba15450cec13239076fdfc18bf51135e4e86dead66c2663cd4772a7c471a46984d96102e17d3e53b480aed56f84934ca45a6147ac3f25ed8e86d97c6f81b4ee95ef60b98da36360a77790a6cbe2c25c4378e3866fe217cb9380262684f28a0fe3c30991236f2c3c387aac09834bc40545cd90c92a36021b69702f3eaf89f8e727df0b24cef644c0fcce666e0582869ba5e7a258e3b1de4e52b3a38289d578e3eae2b6cdbb181fcd86cf8fee031e417a987c2855a96ab735df42e5623f7add1f6205e9ce46eaae9f7298ab000f097b3ca8b98476a23ad41fee4fefb52e4b50cc74a478eb2fa5b8140e895571722fdf11a98ad5f25b083364b4187ab0c888a041731163baa925ad0e3e420178bf2662daf07fa2672ce6c994a0c01ace1c0dd994690cf1cb58109c75c734ea2a1562a19577141e9048b006e078f2ac4b8179e8454df3aad412301ae68184525107c9157a9fe4e1d51d67bb6c27109c5b9b3d118fa689deb37dc386c9552035559fffcbbd5ed7cb4262953273b16558c76e02298367e81970f93b34b645cee5b250653598e86ab596f1e1e9befb6d3d40a366e4997e2a9427af8aeaa02250c2a1f2c6ee5e22db946de84931027e65a6f54c90c5964883c67dd7ceabf7e79f9dbff497cf3034b860f3920f4fd87b47302a64e088e4fab2bcc9fb070e438d10764dc21cfbea3eddb680ad07bc4bf81ba2034a1775bceea60e013a59fbdafbe032ed66620cd59d744229f402509d477d507248bb318e583b9ba1972844f7f63e3abcb99e9f1f5eae2836d59bea6e2b39d9b0dbe6a066e0b713e46d3a630c63c1a0353fa9ea248b0dd2f4d06229ee9371e727721767747ddc8fa0213422aafa5f01ea2b989b4c2b7d72f1b0dc7c63912c0b92710a181a2a4b8ed7d21b29dd19f5f72ad7a224ea6b9935cafa792c610f43161e526450717cd6666639eb271927fc250c7010e29db239171b2e3381c67d2a4ad71e4907ba316684f6eae08e35f770545bfffed5c2da9f946746dc26e3393c7f7f0642bb3729e4cbd301dbdffeb5339c60131ef7e3202ded002ba664f3b821802865a154ae0be0f0cfaaa1b788cc80b9fc6b6ed1b1060d20d0f53fdbcc53180564ae90d8fc9ea212a248cfb857bc914e25815c8b28", "13011cabcf319c40afec156c80c5c07b707eb6764a22c7d5b94d30008e77e66769c264997425ba4b20ec4dee9f993634bf4c701c03fc871b90cfa197f55cb8ad38773813be79aaaf97d2068c5d0d78a9e81d3e93bf3ef442fd15dcf4a5077e6ab9088a0f013593fee01d3dfdbbd6d5ba75fb10ef3a4e47887195b159fb584e022cfe268da4b57217b8d3dadab89b0dd1c751f9fe663ebba587de4dab6d160eb7c1ada88df6961f51bf8f22e69b9ec769161d3a09c972bf1f1b3d76ed024352e6437e984b197d0237534df54b2b7451086cea9125bfa4174b0be88822bf017ab8ae02b7e40019e535a4f18ded85f5e91c0a987e30d25636b86e5f8823661b7e92ae9a9cde6f4ef790a7b9869f0b3bc931835a255a9b5d80143b11d0bb4f17e4eedd3f61d45c3ecfe0bf1f6a75b451b759b44a336e857a573adef17da09c713c2db487f6cfbe654e0929b07f68e2f58fddf3865b2152cd5c970b2e95e01409d5dec01d534faa364cb37598ff7c42868f8adf7c6a7bd4a52fae6bc6204c8fc1ce0aaec51f2ec5116cd5c6606474544d0d651140a0898aaa4d0d65e4714523fefc3e8085d9235a1f7aec247e9998aae644925e6fa46f002568826ab321de11f107aa6eaf08a47e122d245144a8d23a22aac7a7b8de57bbc2c3f823faf21cc420cf07adb874c41045802489955df1c875a2f7f5ceb1c2ea40cf0a7dfc3a933ef177d0dcd9bd200d9e7e9b88b5350f9091c4c30fd345fd9a85251f61afd4ee320c40c683a9e7e310bdfe7e7ebf99f5a5c2c2e5444750ac79dfda8d9d61a4695460af7e299e1995c5a9e264a9d5e2a517d1bae3e3b9672649c0c650411c438f03e4aa48927dc4796618e3b9db002c622d028cb6d957556185420c9759d7a7fcc62ca36c6be39d6124547a892103df1d13f8225cf3026dd8bc1ffbef030298e7056dd62856eac30aabffb1a4db319baf17664a8dfc7555a5fe686ce080a039e1ad79bea8bd3102b54eaa0ecc299dab31833c2db15c1e5d5ecba3a378539ecd840c82fc5b043907c7c424ae4817d201a6eea49a59b547c137ac98c68f9063c39e2493bbd3cf9a57212bc6168a8979373915affcd34954aac3cc7d3d7e9beb88694cbaf7bf240878734b32d382a2f4e06110ea3b3ba1ddeca5a14dd2d33d21565a1767c615f634763da4e9f4f5968b1724401ced8993c6cebc69393570c14f7fcd809f162663c75d62ea81f3ddb588df3902ea2c53c72843a7293f7578a3b1c5a0d8e764a457e7d267fac8feb80c17a0cdb3de06e5044ee092c97b6f863c5942f3ad73956fb2f423ec6ff9d281a5adf3fc6ad0693730b1a0fdd543e2bbbe52d2f50619767f679c476883f94e4ce9f3ddf9b18eefece0a0af4f911c32d0462a17feaf79510c4c35a6e2f2c942ab46167132a4dafb590b7098ff067b78c93954443e6b2762e0be7ac59f34eee17ec1f33b94a91eb5b12b5abf3155bd1b2a07d09935894abd7809cd62601056764bd6c826c6d7db4ca6853044891477edeccbfa0e24c83678b8e35c7dc5fd03690a2687d25ba5eb873cd950a61822d14a10d916cd85a30bd6a1a9efb0b3ff4eaaefb70c1dbc41b6da52a0c6b42509fb3b5cc711cfa735f9433fcddb72d50575786e186886a74c2867781d6adf5f6bd61251ad0b13f7b1c68cd1f79fd6ab0f7286e9866e1b8d039f0943d1dae539291e3e3b3d2e78ec9ece5ac7e339d04dbe895ee8e3eab493c0096bb286e8b06067aa70a33471268b49edf83146e085f108b854e20bf94f9a6abfaa1b19c03c26f411a8f5ec7d7fdf2f79ead2af60ddd14ffa4a1f79b51bb77e5d24a85dba81c13aa6ad8dd62e7faddede2a9b4372c154ab66dfc1e563de1f695edf1999dcfa0dfdf1bfb8b5a3b66d19be34f78a9d75e08fe20ed3db9531ed59b2a8652c735315e4953a21d556f635a026da43514b148bfeb86477c86a1f0ce3aeb0b595cdd41201648f8904a06ee1a2c305ac4cdeb31bc646290599982974bc0c759b23c579342c6a759564ff2164f21d4b1611d4f5b09c53b44e8dabad53f1e621d287411232071ecf13a7050c854c0ff4b8e5425e096baa1a58d46a0fc5aa7c4d75195c8722c33ed91152424def2", .None}, + {.Add, "-58c3589ba761c273505553cc1325ccbcf62c268c5d016bfca88b0ded23c17bd78c164b802ac1c88711d1106ff6fe38cf3c8248aa7d27e7a9eeabc15c0042c5756f5c55dbdd2113e39fe4a1df203c56be4f46047d999dbfdaf7096eec74ee9b13039273c059e74b144cab76b200ae5a0e0bed6bf42470b5e1dd54aa2abf986a3141de38216f6d92f64d3d9434de4d835bd86bc4494edfdf7809cc26cc7a9b2653bac28cc3105653470ac30e575522d62ce4a1d92bd6f1efa20512c0aefd8c9c20ca141779ce42b3c081c69fc747e63c238d30148dbb2ddd559f68f3bb749e30a9422ace73ecaaf57661a12dc827d2fd27bf6de067ba41060ea8b211ff2be44caf4f7614ec22e329764e9da48d64549c01731afb26f5aa95ec5ca4b846c9322ef332a032dd03ad5cf5f7b63f9814d9c5b4d7d4e58c26cefa3638a9e6132f36c0e8e511d6bfb9317acc2de4167adc34048edbff1abf6814631f564c7bbe00a8565b2ad674dac21dfc60d71d21c46f62d9a089f0c1cce799f7eface11ef7d6ec814eaf1b6c000da35f0b8950e6c6fe4f25f61ee854c2f41a5349e2cbc6378fc745becb3342b92d3c26f27871888dd64bef178949b1a91f72a81060f9c389bde1e044ff47c9006d301fe53ce7823c1cbb7e4374f59acaaf6d1d466c8eecc5b7811271c37128dbd63a560f714ea1d0fcd0e6523fc8cea19c96fa01af0b584445ba85e9b5a095789b7cdb7beadd426c42ea3c99d36d658756ae1907cd4b19db655d7954da69a3225810886a47d470d6f72ef3c0c0c7d64826b57387519fb12f72bef430049613844a0da8e065cd9628d6db6ba075c2d7d140c18dda87588885e05652bab472da9d8f8afb44673e129607ff8dfd7b4e5f24297ad625fc11288c5c6af8add8849fce4d8cbaae3f32e7ecf45d9fe9866cedad6f2ec8c643b12a2b71aed1cae19c11b24f5c308442a361ca71aaa1180ef031de985a67aa4ecf7a8f9e84b1aa53ab5de2ff07a8760bc680565cdb2935ffba59860401dda65a59c1be35c61d74e928bd301b120afc57e3c79170fe9cf2e501569ee55136ba060cb44e397e554cbe3e759c77d60d40f2ea315f14cf447312381d16a1f1409b8eff75c9d0dc51d9b300727ecfb988384102fb6e74c295cfa138fd062e727baabf20d378b26dbbf251a9fd422cee71191ff755b292e3625c3cc43a2d15f60d7b98ea06e332a88f2de03d24bfc3f34029f660ae0ee19951e4469acfe5e63686b6c4a703ad3248ddf6a232529b2a970439dc27654df6cbd2ba269f0c233ad12d96ed68e6ab82d85a2ce6cc87f3b35d3e006115c126fb42e90a045ae532b31c37d3de60f948eb7d37d4a148502eb1b1369d894f01975ee0aa0fba1caac7df3b2e27a77a9be7bfc218997fbe3f2e7ee9f3fdcf6bb03b6ba39a431b56c0db2be67f25d9af1a6e3eecbf6b0d4d8f8f37cc0d9fe4bdd906de7dc5642e474334432c1206c0d6166d9b18deb271939ea9bea7cd3aa7ea180c7a3e0a1b689f8c18b686aafbca4fcc19a9de674f4e1da4110a055ce6e5a986df139a4508be2924df38705ee864fe3e70f84cae4ffda7b218cb1010a638365865d71a51ccc283583b88b92b5141a0c822d924a3ab304fac1a8aeea378d387760be519b1b082037b83627c1b8ab3fd322d4c7ce412e8726b726e4f79decf30795dd0d40ad27ef4e591b9c54470b1f3d80fd8e06ea31ea82dd5ce8eec2d333d32f6bbfc749390d598d66ec39056a93d0fe0d46bea38ebcfb984fbdbddb00db11d1c0d8676d14cd39e25bb4dc1b71c78df12a9c254e0b021db39f971012a9c653da977b757e8eccf67bc5470be009afc618705901f8bf0fcdc3fa008a384c508da1a4b73568007c0b7ae19f3e47518a1883eaff3b052d582c02113c14ed14fdfec59abae9b365daaf507514a930e0708afcc7b60cdf465807c2490d9a3beefc439559fbc0ec8e77da9df142d0d905aa4e2639b51bd82ec5a2a0037dc7bf80cfc6a8e4ddaf48da747232422535222380d82d45621971d1fef9fa7d7ddd069cd34d05830db25b4513c3e625bc796fece16b4d7a3ddd9f2007348dc1747de671d7ec42f1d15a5387b3266a3c877fe2eac7ded16", "8bda7183d478adca2f990ac085d79a70b1261909070adc5151e10747a38c56b460fb201d045b3b50bae4a4b710984f56b9856b9fc3bcc243eb3f7deaee96e03b93c0f66f8ede3c6d839e40ef60a64963ef3b748ff7d08402549ac073fda542728d62fa9c0740667b2e882ed9392c56f3503ea684207fbce495d72a4c9d897cfaca6a6331cb5266eb1353214ddbd8f899a9ef0c1f5f4704d6299dd1d31e18e8e52df63f5b464e4cd6807eb0318b1c18c1c581845c886e6592b06043e6664ab7a64190c43b9ba152a6dcd1bd0df0a8ec15fe3a5b44bad1e48a9b35e71748ad011d9836a9b6ae4fbebc5c2d2c87efec051e847fd53805bed953190e8171e8981990afffe30dd03e773df18f4e892812e6c847f961c27ff7c4947eff88e4434360e4feb387134fa66c58f6b45674ee6a2309f559d9a9c554b615a9556793daf5cf5df9917c81f6ffb87ab169f04caa8753801d71b41e29a65aa1f60d9d69d64494272f58023ad681e22c50a7f2f0d9195f7f75c866cb305a904d786ad16f0221f8aedde8cbb0979d63fb62e7044d15e4a4bde8201f951dc6924adefb2feb8cbcfa918237a37f2b21c95377318b84a4c0f78cc348fe85c53e9ef8e71bed817f815768d0835b47b398ae9f21af092c018e564cb3af3c100c1ad9918fa7c8dc20c7d84362b799b8aef99c26d06baa17e76d66237f216c0661f5f0ac30ffe792b11b82b1ab76495b557a9f0b0868a1b90e20d47c8133120edb7fa9a40b67af0f18e12c46df25507c4bf92108d23174eb6597d731e30a5a4af10adca291fb2765de5211b3524aa1b8080bf96dc544beadb2cc17593ffa6cdc7bf82f374c9d2a8f86ad55bd34f58feecea701c5f92380ef36949e774c9b150d52a5e1932ae0c0b40cdf1ae0a4cf3fe2174b4cd1481065bd6068c3bef384c1254c748ce2845aab48257de0dec20f2c05eabe0e46b700966af1dbc01ef26cba9bbeb32a770a53069548ab54d1b37fae2f3287b30692de0bccf54c9fa02a95dab9c8d07a974bf54b9c462c155ea4070a91139f4536b76b3c366b22925ad1b9d5985e03c878259089666a10b4f7830fd2108f6da3e8b157e440594d36f40767c2c3a88259bedaacf60eb7eb8b536f3942344b831bc95033c7b4f3be5825f09ccc9004c1c5e632db7cce60585b4025713525bddc4be30dd6de4d18404e913577e25039d2eda803743ae796b6580f2e6f71f54bc74dc5043ccc2393c99a3443fe118f81ca209e868977f0c06ccad7026f7c421d081ccb843520ed6bd03bc415e9628c47cf6925b0d29832f18266948b91942d069776959b08f51253a0a7bb1f2e100a5eff388aaa89396a38fb7eded540c259f746c3417601ce7c5d819afddd99e375c94b30702e8f046d69af5aaa3e041aae36237266c2e01c62887483c99259cd71d371fe6efea2b2eb0ba3eb0db67d4c5191f0d90901f22fe1bfdb946bc714ce525d53d8df4fdac4c0cb541bbffc60154150757c47bb93269d575c61aa03a5abdf2aa9de60f9e82565733c3ebd693af5bbc04e85be24d3cbf476f36ae1d3b44c7fe1e1c8b8ef7449cef512273739d2969839d6a6a55901fee180c361cfe7c1ac35ed44963884696687003a7d7c0c1317f1e6a9f916a1f6a4e9bd292ffce2cb91c98f592d9268f9f1cf2a4cb71b8e899ba18e37d6f9cf16e894a73b04846f8d1ce47a3542577fc1686c09d35059ac65f0b02081affc4ef91b1d8afccb993c33f4ec717bfb65b9fb59268445e210c1288a058cf21f1083ca837b43c47272779c67b6b2fb7c535e8380794835f830e6444e77c7ae0c471952f921e8a553a56b475e5c34d82575ab1c2f1d8183b3b6502b14c6f39a5664dd41ae71af8a26415e0d15c2036a25c2aa56846416872ab4857bca4a4a7f36a2fcbfb4866cd0261a125f68a8698d3302fef864648de15dbc5f1ab3e7e86639e10547eb02e673ffab0ca00f8b5d773a539780d3d33b2f9261b4a41268bc1c9e9c2662e7690f769cafd7c3bdcc576ec3fe9b98600bb34184211fbe10ae3d195a1a8b81d1371b08b7e170ae9957336e4741d473c90eb855273289f2a6e3dd43bef163cf08dd8145890a2e11dc44330f827c7121e7d3", "331718e82d16eb56df43b6f472b1cdb3baf9f27caa097054a955f95a7fcadadcd4e4d49cd99972c9a9139447199a16877d0322f54694da99fc93bc8eee541ac62464a093b1bd2889e3b99f104069f2a59ff570125e32c4275d91518788b6a75f89d086dbad591b66e1dcb827387dfce544513a8ffc0f0702b8828021ddf112c9888c2b105be4d3f4c6158d18fd8b753dd18347d61067255e1fd1ab06a37dc2917333b29835f7f98f75bba1da35f94294e0dfab30b17c75f0ab4d833768be1b85777cacc1cd5e9ee65b0b1d46a8c2aff2710a46b6ffa40734fbccf35bd40ed074560bdb42c1a4c945fa8bfebfc81907f6c511f4d04b7dd344705c6f72bcb3cce16089ce21ad5b4dc7a2f1a9fbc3be4ac6d4de669b8a4d2ea8225ad09d7a1131f1cc1354364bf90f62fefe16dcd9905d551d84f41d9e85bbdf70ab8180abbf0e75147fa5c23dce3dae8385d9d1ce534ef14172995ec191f7829fc121abd59c3dcc04818d601463e5cb798ad12c69b685deebd7a4fe48c0985dcb89b2772b3577602ecd5fb089fa04efd9961d8617957ec7c937cad229ac3f00fc2f69b3fcf5b4d2b70460c5fde5a260fec002f6ce75087539ff4cdca5cbf6e8862229f7c19f7723d13b924746688eb9e4c786efe4d2d8093eb9a1455cadbc4b2318dc166946c5d19f4670dcd8bf46175f1d0846ea9c7fd13f589d64c55ef6aa81f48f4e6b60fcc7f5d5b3e2b9fdc38f1d8b5f4ccb3697e2adc5ac8784d1909c3e1c9533b383b2f204bbad59f3e8989e8a5d04146e68e37122428402ca55691b405b76366b931d834db48e33bdfe508d5f772884dbf0abb8ca37950b3b36a15cc544a209a65703028082b5513f1c068191e56e592e951079d14cb5e9292b0b6d2ecf9827b0742232cc4aa013c9be922308dd7dd06c0b23d56d17d377dd45c41c40a9811cb3cf0f13e0731a539b61ddc2745d34a080311f06e37c88bd2658c2ccbb838c05aa26a3275fd4504c33800a9087178b769871766a2adb8133c4ce9cf0f19b89de1065f7e9bade4d60f88d3a3a5f8774a4fa23f567ecb87ef978b291be1f83d51830925faac4d15c74179796a7be6db2e1447df280f52fa5ad069119234bad8044e70f3979bc38cfb57bc993910f30cc467efbc2564f63cf89d64f4a3b73baa955adea9f4dd3c737e390eddac9eddf889a855cec34f8b3a82323dce02c6a8a3404640dc8e14e324d3587d40d9b0ddc1e14b230484ffd6341a99b9399e7c1e274438e23ece0603d29a6f2711891a80dbb9f75046909ef4a56690cfe3b8ec369b1876eaa0c67a4c50c39533a389539f333eb585dbeb11ad32ad7abe300b6cc2840214d7e470a33f8722b45958ca3ecb2cce4fea0f0ee237d38adea10024887146885a9ed4210be45db7fb7397e68f3746c271cd0e98677030c96a78b7f4924f3987cccb72ba2a92fbcc25a24cb691d3456dae15dcf0798cd8b1e1a27c6d88f04ae53303b3d0d8acc769791cdaf0d13a90e90dd1e578e9b061fc6742333652f98594bc95dd76e1b1d51aab64928d73f2a4515635925d9158b27a0a97169d08a760b5dfcc578e73c2ae47f6ec695ff20cba67ba9a91003253e53fa648b6ae742c89e642715d9d0dbc36bd75bbb559dce6f2eddd80f7e4c60c816462cdd1207b4fcbfa1ddcfd308a617302f1fe85d1affe66f36d666f9b1f0983752c06ffde6cdcd905c30f2e1b68dbdc2da51f2c3cf1bbbe826cf005705ab5e5c1602b86b0f10be4945afd9f7d7d558d080911641607619665f363dfba12ac8c990f7adba9c420aa1669e73a3503622733dce3d0b1c7cedbb7870edfbbc7e77f69fe0676775101fcd967bf3942a5f2e38875391b2e01838d4576416cfc1564c5e13e976414d91b4fc2566937a61aff90a2936bde7d1acdfc82cc1218ae3b4b473a118429ff4f7efb49812808fc7f99a37c3578c96221583b1ad46b7f0e2252265ac494a2cc33cdbf16f9fddd4dec849e868844022a419667cdac19ba822307c9aa8351b71dc638add375d1fed03ffce7106653b89b0be4d00deea2d922d1f725af4d7a6b043065d143714774d40897f5e07c5fbe08a465044ae642fe3d1b2df75a06a97844dc4a3fabd", .None}, + {.Add, "-b50a080b9bb03518915eed0d84afb55fbb1a0c2d24d67e117ebdc388dff1374d64b2eef165254860a9c24fd1065358760934cae01e0482bffeee67551641ae7135eaf4d7191ba20f850106cf1d0087c62b2eea649b66b723f800c643afd4eca86310ec1c2cfc2185049c1b4ecad8d8d207954c1e9a35860d473071f9655266cbece5c59b53468a1e70a37bf05791e506ad4f4b1068c20dabe31d82f3b42e0844e20fa8e222098dee9c2c539d7a566a90d181380ef6d8ff003c58ff9c9db444c1ca0833ab944642e5400adc139a4732a2567753f1cd1c1b23ffad36109ad81fa1337b3de92dfee95c0ad092aa5a8c844403c831d1bb546a5ded4cb0c89822ed1c327958ae8dc21699145835324932830ac50d5757033803cb3d3b0375034bfca6f8715b9589ae93b52bae33144450274f7ef97d18d501e26454e52dc7ab383734853913edf45a354cb604ed62318e4c35a8d93a8df824aa774b8f49460b5befec666ffc070a8e115278dd77e7b0a75cf800f27df708f68ff2752b9e48c17d85b80a39a408f005e359cef14ecc385e19cc4a4e78e59ad8d9b6433d4881af8268ee749c2821dada40056bd381a6df2e9bba8e53fde4c816c8dee9d6135b56e1d22278634acadda79aab443e21f84c61f1fd25b3848523aaae60716dada761819555b06cb3a109d50ff7f6a44c9689805a2b61144b911e517a7fcbb0c779c55a2b78d85a617fa23e989ae911c771b4f544f5b2a013ea9a917271a8d811673a75c4499bdf3a045e722ce133d4cdc06937b937503c2baef6731a1c3206af607ee3a719ac3639e636ec01b20cd10ae69a4f580686dddadc52cd91ae1fad30da01a544612deb8f2a36195e3c0c6bab4d7c4ae5375bac49bebd55754fe7578d4d356ba8eccb20b5dee9e8a2845d28e1c3a2a9d7b60508c88cfff1cbb5e360b4f53815587612250f98ced5adaac1b2b74a3e9b56374883a178c6a8dc16714033bbb4b0a49fce18531d0b2f6ee0bf3f7c3eace339a14bcc63614994089a7b822c5b00ccd8d9bb38e0488103e45fd6b4337f478d4e4a6bc71dfd16219dd951cbd20fd3486c89caf1b913dee8e76530f96adbf27b7adf213379ec1b11eb8116202299515a062879b75f77011b4d92ea26c66e7064ea8a343e747b91098c359f92f638c84e94d74cbe52c0da1d1a383811d5d68ff3f3eebb50d72ab578bbbf7ed9b7130080b94172007fa12a320b3e4465b0996fc2834e9b2cf9e50122ee3f1c5bbd31ae3b17ee18fdd8ec4e077303e3fadbb00b49f1cfc740a2c2cd61e3b3d48812d56bf1f25365ca287c80a6e0a3b886b66980df9b1b8c2132e73df615e3e84decd7faf6158c6c3d67fce366dac98824090ac80ecab9fe2957f47aec94940036b0fee66d2e84d5c6a74a7132d6e56e9c5b257b5dd0f89f0ce61da7a0842e6d8a5670434d8ba74025647f3075d475ffaf34640c0ffc5f4167c04191dc9e6bbf2bd13897f5ec5c1d49f4908f80b7799896e98014efc4155a8a3aa3df5d956ac74e7ef3464dfd504b294d0bc6916d4263f65bca4e6705127fcacf3cf1de9199edc9c3a7a667616f65c253a542694f6af7ba49ed852d5f084a3a68ea82afc3766e02c1c4bf07380122670ada7163ce2533b1a255dc7637156de0ee6e006e70997acd7915ea96f6cae390ca6f13a034f154b114a48551912ec762bb9fcdc86abd9db819d7f3dc85844302fef0b4c9a090d601e30fb11a8d94605392ccb20c34b318320d2ea6d25f51b5380cdd6ac5b06a3499780b25e8d0a6738065019b3ac235ffcbfeadd4bf1466327ac3a6ae22c1dc07b2ea20c92a5781bab893c6f3f34944ed8139c7ad78f3b4e45593ba72b823ef79df01d62dcb59f2b0502613f79d0d404601a363402a16e25419169afbb1978598aec1e91c6c2bc9a50aacac5530ff545a7c578ecc1e0c5b876693e17c2d04ba4c5853c8dae026fd94b45053edbb6a6872da0e2b72a9b94d921662caa02f398cbaaed1f62ad021ba0f5ee738f2a56dbfc3709007706f4ad2a5823715f61cf996e5d017ff1856100d4f424935243a44982526eeb49df9b42e784333a6e3461e2fc06a97203aba140a94c690fe1edfa041c1187ed8", "8c1d5963873fa8a3269910b30443cf394d071f572ed5394dbd725e6781ea33794c9a5febfb89e585199c7badff3fc810ff10c53a6ad910addce7ab5d46292de6673d3704cbb695a27c964f480321d80eab49408dae358f43fe70181dd02c429a13f01c4c65e68d9de4e8ee4e1ca1f1d3e8e9ed3485843a8ec73d05da15b9624cbb7084ebb6a3095e3154c0bb767d1e56cab55e50dd5e003ec208a265756da1d10e256c4f14108b92246160e1244103ca0c69eb0b85f8c8406f6a1db78dd805dd22d6345ecdfda5dbe36ef0629e3fbc726c915ec85822277713fa8a90314ffef7ea794bad1408bce9db7b071d749b9a1a592d20311262d2ac1587e2f11196e7d86b2c9e5925372c08f88ac33e5ee4219f5bc1884e33a5eb2416aa825f103ffe09cadea6e702b3b8f97594645573abdc122e86b7d685381afe35b31df7bd24028568e1ccb00d72df35490e589e6620c8dea7b65632607c234e62d0ae68280bdb8cadfbe68199adc5861d3075368e29b536658b3509ef4605a62d53826ef593aca0c9f866c4041d43156df80ea7c1db9b58900b57891a642c1139951dc551b299450d2b1ea595de0aff598a5af851e4faf7762e6a34db64fc58625c85c482f2cdc1fcbe6c5d2e97c42daed92a2c869a126f57fd01368bcad7b20b880d80e92fe58f82e842e77c2603c8459c22b28ed2c8e02565b147ff0cc57da064134060146ede47b2a7e172f76d3294e9547b6616db3b32d63bfeae3708187ca9a9b0e84be04dc4872f12d025508e194eb77ee23f46f2972da1e943b32c20be1d84273c914adcf089859c873a4215c647bd910001ce916acbae867b98de7357620e83892ad20c9205fb77523b211b3c09f9476855321e1f4c50ee2d8e2b8187b7fc75bafbc90e306e43cbfcf226ce719fc7788bb9f3b03df1df8ca2bbc52532b07f3cdd40599066a65abaa2c18cbf94e53d95385dd52a6cb53bd26bc380ee6dce6c4dc868f69594bf263708d9f0162404e39c372cab4e24f83ee6457ae9a4d9e36d64e8e9560d30576c0de8831949d9bce1b7bf543d2b873d9c75cee2ccd3b4c1046b9fdd9556fe00cca603141aa37a108797836a60983972961e9dc2247fdaf62e61d5175c1814ccdd32c555bf2ff9189f791c6157b2f9a18930fd0ceb77c45bf8cd907e48e5df4d7277260d883269e6a5acebf669d873359e6beed2c48b0a0a01824b7376c88fb4af6b558b1c6249d131091decce5e3793b81e5a6d8b8934c13d4dac5ff6d2cb577a7389ed70c5afc5d5f7fc9bb470610c8f215183b868e65f6bca6d06d2fb1bd1f79a47cfbf0e0fd7cdffd885c100c4997fe66d5db6ac9c9095c57ddd01469489c6d0f57b034258ac9c7191a80086f26c0cd286524e3452dd56b90d244f007c6e529aaf32e6e202fb2da2e149850e7c6743bf164afc91d24f645f5cb7643182c4f42c3c5c9ea045581da2385e4c9092530822c4f8e195c54a91f4644b461befa382f01ce01d9e789bf51724b3e1ceaacf276cb7dbc1f50c6b23b588c7659f370c990e9b28d4a99ec823de4c7cea0afd157f9a59acfdbb95435cc3c8d516e53c7434af9ebfa4976a7cf1535b42000fd74b314660abeb83d84682de775dd8f0f0c64fa34553a382a969960431f1a316e0b333b27e4978d8902c0d5b0410dd8ef5f06c57deaaa75431250aa04170718042def4d44d1f5c386d16da3ddba1732bd472d602ed5f1da44f9ebac6abbb1a6fb0156851e91272e3ec8f34886221c231725ebaa0bb1faec13ed6b61607f288dc5f857dcd8d29907a8aac33926a3b1577c0518bd75b3d84f9f58891bf1bd92baae7d3f1bf547c5583ada1d554a0b072da921bc89b3fc42ce0aa81d841e35c0504401d58ff73fa46f34c7829ee8de8ff7c0daf5a8804053f86277bce1e89ff70c0068f1e9b6323fc1df565722f8c977f984986e97b7bfe4890664ec33a0d392c574cc02755392819c19a0b9d3f7ad000df5791bc9f3afd69634c7f6f58bb0582e5f25e536f16b28feadf50008e7a723a88dd69d59577cd3b6881744bb776672bcd539c008d268d5edbf80987026c645eab91a8f0f40319c9894578cd336b3145fc95148859c832f1a5dc6da520", "-28ecaea814708c756ac5dc5a806be6266e12ecd5f60144c3c14b65215e0703d418188f05699b62db9025d423071390650a2405a5b32b72122206bbf7d018808aceadbdd24d650c6d086ab78719deafb77fe5a9d6ed3127dff990ae25dfa8aa0e4f20cfcfc71593e71fb32d00ae36e6fe1eab5eea14b14b7e7ff36c1f4f99047f317540af9ca380c03f4ebb34e114c6afe299ecbf8b640d6d2114e08e3ec06673d3ea3c930df9025c77caf2bc561566c6c5174d0370e036bfcceee1e50fdc3ee4a731ff4cc6489d095c9bebb0fc07762fe9e5f52974f9f3acebb2ab80698820a94901f23c19f62c722f558b8ce5f0ea29aa9b11a0a8f197b1d7c4cdd7868c0543c74cba55688aea901bcd71f3ea4e616b694bcf08cf9218a726908115f30bfe9d2d92b4ae86fadabbb619cebed0a44b3d5072c5424fc9c7661f320fcfee1434af1c57473de6e756176cf694c3cb6d83570122e45b97a88728e8be9adde350145fb874158570e04bcc5bad02b1227da7c19b6748ed19b08a4c47d81bd9cbe9d91740413d44ebe8a04460f9402476827e73ba43215c8074ada509a82abc5dcfcfa96771097c44fc3506124926ae8d49a0c3182593afecb1cc8687798d96d3ef04607ba4de6daf0fd67d9564f7cbc5c7df8dcdb6834e97dfd6ae65e5a0267851afc62d8470b98daf0c2fb10829e3faad914b3bae9a491f44b5022b4cb4396545bc9a90a7b99e2f472b68542872f64ede69ba7fc9d7ebec5a6a592c2e67b65229e3fbd7580af18e4cdc531a86164186f87244b90e89c5b2bfedfb73e92b3942525c3cbbacb449afb1bf9c46894d559a4d89751c122c55d734b33ac84b2256787a72549be593b2e3de3d20d061b20613f5b3193c5ff8d08fc749ce5f9f90d77a6fdfde9ab27212ecf67bb5eb891a4b16efe405c716e9005d360690b0b035b85ad4fee5ab7eb4de2c1420eb2ccd79b5063d810cdbce65a65ae55b280371c76dec47ae0a39592ce602557eca9b3a98a275b68e5326d4247b04191ef5a19ebef617e382cc8ae1743a9880cb15fcf751c78839111ee4898187473ed1059d0acda4336ad732ccf0ec6ddbd4ccc1b6e8e3446f111a46e7c0e3cd7d4fc7013b29f4377c42aa1064ea82443bc58e62f10e26f5540392d73a9ceb4a93fca0bddb36fd6b37d04bf16d70e049b40f9205ce2b3029a3fd8a16481b38bec6a5f73474cfb590b50d4278e24bd035d4a6eedbfa947f9051d5b4f0639941c6a6b562b5e79a7fe401db211b4da65e78c41a023e343505b80eae3d5f663413a17bde2b4aee28a70afeeb1f5849f830e238d72195a8aee869a859da1ac787b300d0985f374bbd57127d191445d7b3a12bedebd7872f776c993666ca330bbd4b21f49a465fad595a45d948df84595854afc1fff0036ba12d829a144bea22a5a25e9155879c9b3af210e6962775bd607052f41935d5ba5716c1d3b1afceaf14b81ecce3bcd5f9e13f4433aaa6402da671a072a099db1ffaf468f03be246afbb13372781d375bae35b3dbd8697b1141cb3fd2b689898c52e37ec01ea1b0782b54fa2983193de588666e3dd924a8a294e1ef5a3a9aad38d3d589a29eb5ef872ef37a42203d7f295bc3ee647a95f1031a0bb372c102aa28a480c51aa8493fe8d2dbabb8224f7c0eaa16bbae686193beda05e1734f58d9d238c0a0443e11fae8483c6cb80a90e8530a13f9a183b12586e9028edc76a82ec86632849055f7324b03e2a7ac8f9c1cf2ba2d8a644b09d2042d9523cafa601a8f5c2c1f51df647ca13fae7340e1131bb751fcb1b6a83feee722937cf52e53ce2122a5861ad512bd6d2e4a2079f76f3c13fdf64730cc880da5239cb1f32f3f70ecf5d29944a6f54ee7032cd1483a2c64cf9897974b24117664669bc12f7ac57ff7132f3ca926cbb099e7b8e10f20d03366516e55f3f868cc33ddfaa66002ebc29e609908ecda6faa647f428feb49350a6d8ce70ebf7d9b86e3a84a62b6531d0296e2f629d6fca9ed41d0093c9dbf2ddd4e4208f78f5fd1049c81861807e4fbe2e645bcc47a1eee43ffba648a7fdace5bc2d1d67b231955582e69a42b2e02c54a67af1c9eccf88ce0dffb208a456acae9be4aad9b8", .None}, + {.Add, "-89cf17c9f31442e4dc8df114e5d7664f19e11d33cd27fab4b958bfafedbf9dd6a7a944391bc7253bba151aa7ad428fe3f0a7bfa0c148b44d0fdad26e98c5c75797eca189c8267d18936b9b25e208b0f4976e50192b0d36b28b99374b9e481ab70059abbdf6e7dc4b4110c2a1e00ff6749ef288d376609cb9ddf429b79e237ed73de0fb6e6796550dad348be05af1ea8aa088f990e8fb1597c727ac04a6e7283cd8db7e670a54f37a594c522e680b2c4136a2bfdf666ddf1b55bc6521b1573761c12e915b0fc3d851427011d044596447a421604efaabb28fb9b39537c1dda0f85b07f61ceba6dbfa21fe55597fc795437620179dfe8cd2543464a2f5c9e937d9adeacf4eef16daa9d8e140d3f667c1510a402fd9a75c0644b2c1262065c633ed2c46d8850f2414e27d4d3830e95a2836014f78d73ff468722b79bc2a17d89eec80a84295c77b1c79e2fc5e066df8293e351c8586b8ef975df2f4c724884e0b7078ad145994ee2f9327d8f2ea386aa53fd5b80a519b1973e3df9cf6581ac079c58f1defcac5d3137ec8a9bf25922509789c8a5dbff3e48f27500ffa3eca85ba4abb8bc204bc4fe1a592635c0f428eea50e5bdbb4f703e85140b7c98c40ef0679c1ffc5af335905cbc76a8d5483233043d27b1b0fddad2422dba4622621ac5e3d435eccb4a3de51ab0545756d1af709019f9ed3136a490b24ed9ae9b3489bab37d75c2697fe2b0d7f8553d59b83858663300da99d5b93cb40781fc5948d827b6cb947c42d0b98dbae1cc1c589ada9857d46164f41f7dacf73befda68f222f6d88b278e153917d1fce59119e1d46f5ca4157b28e68e4390c230bd204ca4695b6b9de0ba424dcfd007b57b54f1c19eb73f0a6afb5b09fac205fa058b98c682a39a8a068388ec93feb9caaba93a01079a22863a5350dcf3c6a34b1db097a756b1026eabd172ea025d666f21222ad5be4f65b5248e59caf7036544a627bb2aa127de785bd2714e6ff605b3e1eda4d7a9a9acf9af9e6bd6c30ceafc9a6c26e4d6ce903a4902465917cadd4ff224f84be136c29705626cf51d0b96129a34d33375b3c0c98b9ad1fe4f208dd23b8ae28e0c4f32a2a480b05596545578956c99a11ed2b3efa741ff1dddd599bcdf65774ac9eff9a229b0621271716d66189bd65d3b82e91cd8205993d56d9ec30c3ac57ecc007235a3f2206b7e798d49d0a41a638aa34ffcd25c09191226c1c8c09da3fee2ce693bef4b05b45b2dc49b7bf0a4a53f75d2ffb7970f8fb3fd3fc100c00141565f3649fb99264747782db7982daabf1f62973d9960bd3f610840b31c3938d1f16fad06302f9586fbe1da883a46441105e6773a3f01e54dc069545ef2b1a4193fd4910a69ce18a7a2f766d825e318d642fda98c578dfabde1012e656b036b3bf6d35c483168b68e20734e41c8f53235e87c59f3829f1429d12c2b696d7cba099ebe75d1ad4dc3abc4cf1c02a253050d3e5315c0c3ebb81958ea3a63b69ab2cd4614d287cbdb9e503f30a75a6ad8e75a98301b4e20cb2efdb35f6af563d096214164ff8c54738ee84e67b26386e3cfdd73bc10471e2cc15f64f378180feaafc91aaf145750fd146aaa222d5e74b2ab4e7f5d8dc2b99b74bbf989695474db02c9e073e87d89c4bdc6468fa6cbc1ced8aa3e1b2e5f29124c889c71b8147a13858d596acb3b484e881951bef7977d069b46f8a48503fe6059bbd16287e2e1a084251b9f74a396d9db5f020a13f3b8a8fd5a62d4da5dd3cf15e9f1151ed315dbd8243f2a6a3bc25c1b47852e919dd1570c903f2d412287476221e8981cb3482d9745f47e8745a271e6d2fb97a11df2987443320885d3c595a1c9b9f38b448598ec5a602e165137f16b373f30b1b55ee5b7e08c8bab59402817a437511625ea8bc4e682d7bffa76ea798cbbb5a4cbff7caf52f790df96f9545879d514ce0ab17c80f3f2b2b4c488e3ad772bb0dc4f397037a605f438e13ba253451a278242b3f858306c9876e48eeb34ca2044b56f3204f8f321efff6f96c66259a64e1d482a04bb208fa8a91560c4ac06a67e07f42010c6115824598e90d24dde114215f6c51ce938bae228e1474158c3bfa9e86b97d0e0d2", "26e3c7436b926f342cfebc8301ee34f9b5a62ec9d4ce0ef90917648ab388aa539c378c6ea975c6e91c7a33ca74e126bc6f1f5c4ce1773eb988fd6713b826e061488e2a086098d244c8889594e7347c4a4c2a691d1df67a9d3e1c6230a1c1f7591676609580e4a95c6414d084e971834011f61b24cf880cc292a156865316e15fe850350ffc1ccd2ebf68bbb942bf2c20573292b6a84e4700268b9f575d1ed4fbf6feedd338f5b6bf33cb51e54a0f0caecb5776d1d56c027adb03b27df39cc87326f7ab90b931312f92a6775ba39f932198b4cfb7e40bd7162a34d4d877aa728e8c6ebea5f7b39bbf1f8be4aa053dae8109c50ac6640a719aa8780d6777f69d4138ed5c67308c508658a62e40469fb348b2c2fd82c4d2fe5a6a111fb677fbd9fc946a7e07aad51c2742e20c43d520076fca84b903ab04923f2f572cc1668a1f951f576ffb2fae59f49275c2b29ff5e97897c86ad4d0652f5cd9c5e865bcece233dd2e2af82b62f2073305fe52ab733b31587a7038c2b519559eb9112bcbdefa56e9ee371fd24948a927572a5fffdfdbc06f5aa6139ed9f9edfa0f96b124e8839ec37656756ed512fee9be8b8f558b0726a8d43e2866d8a3229c930de79e9958ac4c151347f1459e8ace7cdefda34781b97d169dec4b733e10f780e7f769a1f1f97e501f42adec6bc5b297c56ff7eba6136967912d1bc25fec386f8fdaddd7e0169ad9e853f6f53e24de685cc72622e076fac3983dedae1db7c7b444a8d6b48a7b02e15d0f5954445e78d3c758ca8ccd35e388241edd12520c2a7a9595497dd599ae7c632f1a55b0a4c7a5f8808735569060ad77882a09d8e2859f3374e249d7a51ac64dbd2cc4c9faf3e7d137fb27922abcdf7b6a262a8316d2be181cfbe4fa605c2bb1af56785fdf5b8aa0318739dd4fcfa7001f9a428a58e732cc388950dcfed81c085a6841b947ac8386d70568d11c61870cc108e54a74dc81cbcf53ceb6e5a1b2e4b56db9297e844df46e29f4cfc0ccb193aae3cfa436bc3c7ec851e867a55a75e09152a3b2d70852b3699b843818bf5557ee633b29eb4ac126be4bc2c3f45df9a0b696f2618bbee3746504718a469a5163d230dcd06953bbe79a85b96cb7bcee2da69d14c8e5bb5b14c9a35ad08a4424e63883850eaa985bbbc7d6ec078db4b3e27d82c1955cd5b633e0424ef090514070e10e74c0cb228821cc018150cc864778dd10a3ab739b63c78fecd9135ec567b4f3d9b9fdbfea2715b69c802be98fa61bb3dd7a35f7704fc011fba56e69f8bd16b693a905a6ac201b586056af3eaa1e152dc77800acfba1fa6464ec3cc1033f33546147b3d2cc82474eb63f6af0a9388ab82296dbb47d8df26bcb30d71dccaaab4ad0f49ba62944dd922b52e711ea48a57614ff73910702ea7ea2b882e537d575e1e4d59e7475298ab577f2f78317a588a9b726c480821130f89d292cf867386aa41fcd471504de8fd999437724b4908110c62c66ff3a15d524c12a5187c644bec63d514bb9650499dc0b8fbb82ee823e4de73b11a2fa8cd259b00b2c661ab7c2b21f6291085248bb1d696c46f839278773913c94f40d41c3d30e101dd2b76484fee2a8553f85bb50a035ec637de169ccd2afcde293759679d995e2525617a5267c114322ff1be17454cdb363a0fb24b830f723c8524896080cfcdb96fed3d92dd2a3258d86a8b5bc7c4db99d39d109b110cd99d8765d24ee3aaea44e4b15b6698cd83d45f547318a411e373196f4fb549c01f9cbb92f43658223f356f8205c5bff2a5623b0e911e00456bd7c4ab56557da3fd79eb1119ac141d0aaa3f147070dca154cc14bd6d09d581fdf26791867eb6bd92df0c54cd1dbf0adbb5339586cace41ae02363adacfa9d783b1426cf199d9d3ad9d2a0b01972269ac1ee7dd7215eeea364d6c61a3efbd30558d6d8dca76a0aba16ad2ca70d8da5916535bb0f48a1a9b36b03bb2ff8c1b8543b392d41175d972d37ee0be4b05e15d5572c2f583ed6827d38560a6746def46d266b90a7431269f4f711c6df5b7cbca86a9df853b944cc971028845c1e4f4981a2820dd311e5419d7bead3bbc4d0b23d200ecb3680052857e0aa106897da0e", "-62eb50868781d3b0af8f3491e3e93155643aee69f859ebbbb0415b253a36f3830b71b7ca72515e529d9ae6dd3861692781886353dfd1759386dd6b5ae09ee6f64f5e7781678daad3cae30590fad434aa4b43e6fc0d16bc154d7cd51afc86235de9e34b28760332eedcfbf21cf69e73348cfc6daea6d88ff74b52d3314b0c9d775590c65e6b7987deedcbd0271832be6a495666da40acce97a09c0cad49c85340e1dc9093d15f3cbb258100491dfc1f926b4b490d9101dca07ab8b2a3bdba6eee9a36e5ca5692a721afc99a74a0b9d1260b6c9097169fdb798f7ec05f4a332e69ce993776f3f3403b027270af7a89e6c26c5b0cd79a8260b98bec958e51f29a9874fd72e7be8a8a23803b1293afc80e08577d3256e28907ea48b00669edca59f097dc5a7d644ef8bb3a6b2bed143a20c636cabfd394efd632fc228f68b14e7f576150d29a97ccc28550869b53ce023fc59d541ab1e88a6801192edebecb61293c9b7ee961698b3d8bf4d2f4978cf76a0e7d3d9a18d8645a8e40e3e52c4ee17f6ea52fb8aaf389cad5a15294c592452db82d2fb7ac550a95395600638da59d36abf8156b8f4d7acea6a8a4d07fed03e32a3ce97d270965e1f16ee98adc70570eefd3e747ab444abe31a82bf64a8eeb8283aa9b13118f5f041cc2c53a6ab123f1dab79cac078ff8aeeaa1bf9161b784ea069085a00988ce5262a13f0b59abe2d366dae8812bebbb99d376d4fcf1123585bc06170197cb8e964fba4814a001732c50919ae5c16039768353489142100b8a9e7ddcd000a09aa52fc55fd35cd97902f17911b209fd7c4c40c973e953e8274d851a7b6f061986e94e3781192f871193f8c5f3f490a30b3dba876d2089a38facdfae1bdf9fd49782e332cd80a986bea029aa57d73d3d8659eb501e99cf806045366aac50bd598418f2367dcb6ecd60256fd3b56a8f9a1bad27749ea3feb8e69498c3074d09ee1e1acfc9a5ef5b4d592792ba1f8c99023cdc355d9fb0697fb4dd38e2ecd82bdf3d46c5de2fa81c84e62894ee8c65c7c5272a78e9d244e245b28a7e460d1506b9d06c274f73ac7529f0fcd52da13147b82e2c467ca76e2907dda85c0a2f4c836577850f41b0b20699194737ea53d17740c0d0d7240a628126952917e58b7bd9edec5ebb80401a956496e18f236c771652ac09663684919e89b181a552b1af8a7004cc7eae1bf8978921ff304c14903c018316552539dc6ef5f555dd29e350c08173c6db91c98eeea2f5a71627f0f3dbd68309c99070412f5ab9c7e002dc0f90b3cf2810ec0d8f66bf0be7feef42a8119990400620973e6d8c8370452cf062329a9a26b56dc3fcc24fa70c4995c95a959dd278aa7523b1ad74a3b9ec9d236d5cd202cb31fc9e3b4417aac27a6d455547cc01bad4640080bd541ad962f99340ac3b9dafcd53cba780708962706af98b801a0566e8eb6b8911019548d946155907a501d4ed9d747533a50f9e9c0f5b370892bdd3647c84dda884ea81000596df8a01df5ba105d44d7e8ca05fcb3248f0afcc2459526943c3c79159d32639bbcc362f05215b349b14c00a4fc94ee50539ebd3b6e32402a8ebf60c9ef68499988f6bc779d81eeef75aae49712a44d831a7e949bb86c0ff4488f04a919627721f974a354c83cca5ed64557067cabe2ded9457a54defc2317d7d805c8f343c74755a46ae996a10d450decaaaeae7ca2d56a8ab03c8af6c847b95ea6cfb2658812371d229cccdfe71777319449da8c6ded3c14def1b5319e69872a21b371343a1ffbf485ad86dece8452c8be86fc4d7d1e20a47a8c07e023692d60423d3e3545b6ad908e64adfd21bc7d6eb12295f5aad2db65de0c59a7f38c71069b272c317df84be5324508e51b138bd4314509732710e7a06fc7743853a7252bfe815d17c9fc91a9e1850ce05e53db37ff23808be1cacee6f1afe20de0a6ef34e614d7f09799b0bcd7845d894097775edb1b8ffb3fa8af5adecef9436cf47fa1a97414ab536ac5e47a30c5f64cabe19feb4c993deef834fefb1570b814aa93e63e73e0b1d0d0b673a0f6ddf6fc3f276c7d681d780bdc0689c73c62b23095818867dc21a1610c1539b67c93e5b2f3906c4", .None}, + {.Add, "5e19bfac21375c4e70f2cdeac6abf2ccbea59a436b1f08e1b99b8a26f6053075c1e7716317c33d02403f099802eac0bc1f1a92921a3c93ad2f83f3a2ce5d446c4d6c21c483d012ef6deb5f591769d24f0e5dbdb9e699cd5af6a0058d3f81479b30bf15bc8b8a30a1e4a746eb5f80ab8b9a3e71e1b3f8cae5866fb0e3ad472a374d093a73b466190f857f2bdf8d5bc45df45b6ee55dff4fd738e4043666dea921253b7dda24396b42c98c0deb5e8ebbf9cbe9397017a2fcb46f3f3a6c2ac44588703a439afd2107b34332ff3a6f7bf410751a23cc40f9ad25b187e4e7abfa7fcb49d04848162814cd683b77a5a9dcc70a30021a1f6d14c7dab82a35a815fd84b671a15f41c793edb24d300eb206c3545027cb191700946d265216b3fd22104a2ed9ecb3c60f8b327320f045578280087ad64b5707e862429b914defbea67dafaab7579ff413bf55becf3e05ebd3a4bfc21a06bb5208d7a749180817ae920e2be43309b6072945adb5ed79ba260509430b63fd7032335486c7e3190937576ad21aaac10476f8d8a3d4f0f424428f5d41f323ec484bee7eeab9d86d8633913ddd0ac73cd972e56c4fd9cbd45bf37c3c597d16154a0d2a62051c1ce2fb473a2598db4858b957d5a4b0b3b2258fa7cdc8ddd009943665d6b5b9ecb15df39d427d5071065294624f83f1ad72c4286367c4e24859674dec092c72d1bc68792c32aaf214edc69089675b59b046cf3c09e23556f654ce96e5795a04aabb853bacd8da4705db18b37f572c720c8306562b41f3e14e36d5030a75256a6931970b9070887fbdd81e9b932cea16e6e5e070cca0898798627f6188f9db99edfdea7c370986f7b1e275003ccb4f734d6d2ee83cf962a024ede7d091ecfb013e4ea320cf059f3b57d91805d39d47f62a2ef020ebdc23bc28def6eadf52e1cef0a9535dfcf58271a8d4718be789d90386abe49433dd2ae8b6464ce6bca51a7bbeb70f674ed5c3b3d4e5ac3674301bd34a5ecca2a5aa2cbc97304f31dfed2fc400fa08abe2a25fe288d9823d0a46855ac742ee2ce6bab8ddd61957f52559f9b251c7477d24cd6854ea0916e74ba49ace76b588793c0a289611113389eeab85abbdf72afe6516280d018e7bd080a096979e3c570b8b9e3d4e8bab15f43cc6a0bd549952008b6ccd619a328d6bc8fb1f88521f735556fd9ba178c2828d4f33ca86b3fd139e6693dbdda2120c2cc6a74087e25b93131891b3eb1b8f7e95351c2dcc935de38d7bdae359c94c5328bab0232d2ccda735394e4b8f893a581905dae142583dcf614a8162ea19b8e96c387ce39b390e3f50c51274a6a728eea3e9d013715cc8ab0c7b24eb54a4356aace5fc23d4a3de6e8d192cfbad416c8b66fd479466c72f57af8f678b3778f0acc1bede0e4c97842b17c15133ff7b951c9309b708be08d979c203e391c4ed3fec0d6eacda1860016ef60807b16397f22e555bb57980462bf9e5e2f934d02b32496c4df28120e7f70431e979b15267618195ea044f70f744f2bb7b6c7a89035510a8ab5049f8c2d19c6c30a1272c3a596ea728252488ab1ca3db088e26ee2bb356a010c5308b37256e980d6cae0599bb1201fba5847b2b39e7c98862fde7a5aab5b531617d54be4b173acc96ee294673600c11cdd89bfdcf2d26c73ce25e5e52435ff38c42b374bb3bb1cfae7856902f57ea06ba152333629aa993f2fff28e9bdcb2dd83ee7901863d3deffd40563803246514020fc8b04ffc75d9686c8e8d54ee7995c7324e068ab938edf0577038d95d716574a2df9f7b94e242c3ddc789b99e011d3181fb6bda7af0f9dd16dfa97bc515f8e8c109709d47b5247097951ccffd2e15efddc86cf34dc9b3fd0eef00a6ae0156c86cc4f55f3f5a086b3a740a696e4b1ceb687388878813cc0e2bbecedfc72b9fbce5ec44bf231a0ee7d939960f3bdd8262bc3678406fc8da60b57b002782494a98930b5eba64d099c1b02f62ab974b48ed1744a63423e74320cfbb1a4a3458d4436225d33e51d595c98673d14945f0d4cc200f1ddee5628df4e6fb0fc83b75e77b63b3295445b67dbfda76e15bc7d3726bfcf1e8711f14f118076c20e44d11bb607deceac6cd2ebf", "9ce6c0d303331e9fe77a6db84b6797b5bea71057d1b67ddacc5ce370e2d197b4c52c899d860baed216a19392bf35b1a80c0bad212fca799eb5a9d04f62e78dd03b9a74943b20945d38081bedd393f3857b0bef209ecb97684748470418e454092a968bd669d34d03fbd858e7058ffa16cacb25467b833b23c4245fde815c5fc5bbc4d07314625efa1226b899f27729d007d6fefc56fee56f9bb7d6f95cd141f28cfaf6dcbe74309f943b28dd98290c0c75c9c6474b6e71d2ca01fc7e9dc27e867c44d566acb2846c8648cd52a70bfbef5eca1896945dc1ad8ad3a1e4b27436bf6ea021eb4d4717ef389047e46b561bef1002e2badb1e001d0c2d321cb486206c76e2e045899d71b1a994ee0c9e6682d5327a92528c27f0716e1b4fa18e0525e3393532330777369996a068cfb942ca78cf571ff057254a0fa7b8601043797ee50d2b681160a80bb6504918c76b90c7a0ab6bbc45d2cb9ad6eb7ada9e49b5b5c8b89255e67ad73fb823c6b9e9e74d81699f1678bab839f09952d2cef3c7aeac173cffca444f81e7c2f849032b2f77a23ed62add6b1064a0cc12b64daea8579a4d712c7267cea4b1678cf8779846c4d15c7400d4aa8f48404a4888e3473c2a1c6c3a306b881d9842cb5cff4417d60ec6076c41720639c2b5afd6b3acaf7365a1e6d635d25ddd22572e48b3cf70b8ffa4106dfcd65168cd9b6105bea4ed1d0829596046163e7fb47c09a12c397a42b936244921fe04cfbeb6fb4b12f454dfbf9541081dd614155492492f758881285b1274c8b01ebaf198506ac9a543e3feb2aa7f868f4308777b34d9b5196af0b769ccc868d7f78bae73694eb297311b485076cd2ba7e39de6ebabc8d4a0687a00e3644d2ca6f8b9f77aaf001ef7a0470f5f83b4b85d954290735b679e5da19a7ef9323f26e90d7b921097548935fce504aa7f3a7e5cb0b9bd6ddaf00cecfd2ee0196c1401f52e792010526d2b076210e40438c982ab2f8a49618bcbff1a8aaf73e3b791c42ab889342695fbae60504a91849d5180cf8ae822a162d92a90cb1da2b758f12170130fd5c40f53361fdd3aa956e1a5ba293002f67ef6f65d213ba5d5e65c08212c8d3d69adcf8c477bd08da77186708f95fbde705d3bd40527c84dc8985c7e15bb702bcee44dd334da0133f1e8f8e3aa88c957171b6ad18a09f0bff3bd14ad594316322668206a693d8c7cc0d10638de024ba108dd89bc7c2c501c244fb91d6f5b1a64faa22434ba53cd974b8f5b2d2a4d5b69ad05aef2f9fbac9bb21da062885e885ffec410e9b2cb6172446d676e80b29ee06c75f7f93c8301738c2286a5bff5b87d901e85443c69bceb88f3e74f2f7fe61b93386dae2c46e60052b1dd923620974cad3aca7984e3ac99c2a72eea8af4ebbc30827a9d0ddcfd69555448b4c56c66398f190c0df10a371b2b662291366dd501c7c255c55d38379a1972042793953965f8ebc54098976e5edba51c21828c1c8d5f279387d664a900447147383b82ab08dfd0c0bbc3374af84263c611900d905d7f0e6e65e628e633e26aa8d3c87916a70445f51e4901b80433bd05c44bf7c59a516293dd60300dcdca65f7ab2f38cccdf4d33b27fd962f24cb1ca4439c7ff3928353bce3f36a24f2bb6f5e355c5808507a6d4fd0cfa9c6bbc897f6fb126bda97d052bb7f1aed2c8f40ba665b980123ed14a7347f2f830b7b61e28249344f600d64125a421d6db727dc1ed6076ad14d6597d83c03ed5e786678d933904ec9f3e0464c37fb445c414b99cb2c348669bfac132ed75e8171c9153e95992dda55bce6d20fb83eb84e58b04deb816c9d65825929dff24a95b641259e3487224e54dabaa496fe512e30a32eda874ceff7719c5fc1e599818287613a1ea23ecfa9bed97bd8cfbc276f6ee58ea5c2be2b7b9066df110f53199b73315b93e263847035d7ff9597dd3f1939cc241c5f90a59d2f13f20c557d7a400c3dca41e4fddbbd3e01bd6339006f95fe73629e617116b6dfddf9c4782d9231a64ede1747789c8f71d6fb0aba2a009a92049cf15c83f42c25fde2647e442f147a21debe382667a7d08bf2abe04f992104fe1bca8453c9d0969b7f4011bda0ae6f7816", "fb00807f246a7aee586d3ba312138a827d4caa9b3cd586bc85f86d97d8d6c82a8713fb009dceebd456e09d2ac22072642b263fb34a070d4be52dc3f23144d23c89069658bef0a74ca5f37b46eafdc5d48969acda856564c33de84c9158659ba45b55a192f55d7da5e07f9fd26510a5a2650997282f7c06094a9410c22ea389fd08ce0ae6c8c8780997a5e4797fd2ee2dfc326de1b4fe3546d49bdb2fc3afeb13b23674b6e2ad9be25dc736c8f6b7c80641b2ffb763116e87394136eac886c40eec7f1901a9d38c1fc97bcc8d1687efffd3e43c62d5576ed33c5b86cc5e6eb68ab8706a33636f2cbca0cbbf8a1532e2f94004fcda4832c7f7c45767c4ca83a522e8843f8751315f63f6c4fcbea529d7255a45ab698cbc5d97c032039eb01570121321e5f91702690cb790ae273bc2d2f3a5a276f83f878cab39064fcee9f72e8fc4830805746761751f871eb33f358762c5727797dba342200382f24cdbc3e1aceb9c0beda41ced6e1140740fec56c4750313e8eceb8e776135ebd82b1f197e31e7c0cebb485a8b97e93d276dbed4e431fa1725b6fee38b85eb23d3e23995775838694bdab411014158ccd38bc3012ad98a161eb7b9aa4566656bde8e764fb547828924dff33cf37f0f24d3bfa3d7a3d775d5a86c10786f9c8811a04cb5e2f257dc8866c02ca648dbbb77f7d420c48658c764243d71fa0e32c2271e194fb31b6e4e0ca6c7e70fd5b9e7fb758424ee8d1a9df094ea4918bba606983001b899dc46e33689936c810455b27bdeac6a4ef3c2ff8521c566bdbad3fb3c4f746f3b2a3d5eadde9ba4654bc09af9dbbd57f35460cb575914a84f033cb081ad5251d76e7f0e1ce3dab23b1f1641cf50b6fa4604721a8ec94be475b03e6d9ac11614febf0c91759b162dbb5191cd4dc2865b1cee6805dff85ae4f2664532895ae1fa2cf0e352ce3ca14746de76b8d19162bd4454ca48421535c52ace2be216c95fb9c7ec9e685765fe797d5f165de72d551e107428f479ea69215659fca868fc2d33e47fda5a51c7f26926bda06d7ef8045d7036c73ac808352fbdc1a4fd675a5f76bf368fc340174e9b19c56d12a9b4e1e00ef2193260172c15337b4a3ea6cef2bd9993721e11cc5f10f3d372417ed3d966d5ab09c0d1646895850b27ce2c01bf5eb65a7ddd163520123af323a97d4616f158b6261bc5a3815a32a71e66512ae354ace3daf00e7867b01e119ed7bf6334b603a438fed9af9a16cff0c818375b132672b4f676a084245d28dc1fc7a2e1d500692febc2b6a165d9a55341f09ac2bcc5d05188399c0b18e95993324ac252389e972d4ce8e45c676031f6a10514c966addf3bf364ea93018f5c42520ab573197fad8ad3a2abfe49f4cf3140b43b5c292a3266637ba1ad7b0e90c7349208152aa68848305a88f9434621ca16ca83f91f0ef7e77e7659e270749c6e255ea72da2212367bf85c38ec1ae654586c4915441d4d9ec4cb4d588db51a8b46fcd68dae9be22999f9d0440f2e42031b3082a0673aede4f14e51e3908cf586728b7c552648391d50e21e7bdcf296a7dc965a5930cc1e3f3efff4e65ab16931f14859ea5db3713fd44ea4acec99a57b653377df8ad2e1a8be94735a8c3e4d111a23e815fbf525d877bcfb814624845ebce9ed6ed83057a555964af3a8b5c956ef3d628de5eef32bcebc7590df3cebc57b2921db50f54e274d7d02c12eae800d343a3aaf517d95f2c3f6df5b27999e804b43d5aee3fe145c21da3b86d760d7e8601cf157a398a229c6d5fc7311187d1b6fdfd06ab58027360b793f3be040391b3aa92c949aa2b026116192a985212a0fbbb32fdf64a0ecc1c3f1e5208d09474c6be217e6ce2d7963bf09e1f9db68a525e76e1c6bb4289dcb2da132d2498c4382faff6f6f95ab3ee7cfa5b57927ecdf53f5e5a964b6a7bbb9d1a7f71b581f85413b759a994fe7d150ba5c4b15d3ca4e888d8fa710e6403952d3e68d54d0650504515ca225aa5bf312c31011436ce07da53656ff82473e0cdec6dd8b7c7cfd6da391e7977672ae6437f03f46173c9dfe1f75868bfd85c7e129d4903985f6517dd41819224130ce28bbfeab4e3ad3aa08faa8b753ca6d5", .None}, + {.Add, "c8747c0eddb4a28771289da10ec3fe762d4d92ec37800dca70c605c19e624c036de16987f6c3cc376bc56d749c5e9f572040876c8f0b0a2d47c1b3985db87e71fc4768836001d5a2bbd9771b33ea30d80f08f6817267ab72201ccc5891de613cec7852fb4691c3bd1cc96cefd504bb9ed70ab92763779a06d2661477df0ffecf4f4ff6374065b229fe7dd1016bde851d160a064a478978f07fef907c069a670eba2d2cbb83f3a19fe6e6b772aef2449c8d4a3dc8ada438d9b6d0cf0df72e116716aa853d61b2384d7392066b6aba849074eb1bafa05319efc1f0ef7dc439a2721fc146e1e3baa3a08d3a655c922e9719de6bc025957d963e03caf938c2fdea4c68f4c07caf24f5b1941b4b1d313470fe61fcd583c41eb5e71228a52b79700e3b67f8c48882d294ba2c6379c3efe998733569f9d38e00054c93ef630e3472cad7fec5ac2ed24fb69553a1df089febfce448b0ddfa5513443e9cf93233474ecbb2d4ca77232c7f40c3f909c908d1df36032ec663371cc2d4f117ae94e4add51512e909fcac2ceefa077c0bf6bc17b3994f97645e5c7c1994712628ad1eb9b241b14ea0dd50269230ffb4a4b81bd632b357641f5190252932a5e1f431776147494a0e184ae1f6512ffe9a6fecbddbf33684e69c60208f310236ff348a33a43322d64c0510329d5586e02e601825e0d5410d824aebdd33658fe2cbb7d73f2714a91174a9b867759ec149689523753c3701716d480b023d36e13e83268748122f0afcedd24eaac35c64b503c7ab3d28115b533c3829c5d960a43d73c48445deaa11de6a098e6634305601b3d7cb4101ead11bc6d582bb61363952df2ddb85f8ac21094a53a1e44556e11e663a74e2974fa1a6e9df43131666aa88de2344b2f8e432c269dfab38e4689c74d8c9b7818cb8bfda0abb27ad42ca4cff8489f5afcd157f572f3d00bf01ee5aee19c8463510e4991935bf61f722db31853489f018eb42aab3325c6a6a715147aa0eddb69bb3fcf08c2fde76d32aa22fbfb71fa4126839a1c33cf36e12d102b581ca873376e26a27c90360a7858a7b8327bc965b91033b504bf2b1d60b5c9c25a213d67ab349f480c263d8e06c8640450ba8eb0189dbefb3c1747420e7d9abe99684ea01fd3e6adc3f66309183da88331e7ff2a7d02899669d0b8a611577a7672b4801da3b381843375540779949b1601f29f1f2f2934eb62943a07eba86bdaa9c6c96049d3a8a2641ed3ea85b177d71ac96d737c36bb0d91f1d7e907699ab624c15f4b8f067fde80dc67b75fda6d49e404352979dfbd5d1fa40f9b66cfbb735710e7119eb2dd07dafc42cdd0844a979f598606e7bf12d8ecaf0fbfb11db423585883dd3ed00aff2dd109b0b5a98a3ac6259de605993bea6f726a941fcac9de51f2ac2dfa1a04e7fbb4cfa0e887638f2493c91772eff8fcb6276f0d4329a2ddda2c433e96bf7cb34430c77335e88da1b63e1e6fd33a8db52ae9ce29822535a3c98495e99d6f0258132e7c286dc0e2fbbd2c1c55b45421c8feafec3722323a632355849611f06b3839d92bb1f80dbdec64479c318547eacca0d9372ce91ea6e28b1c01c27f60611f48450427c51c7e207c9b22a8f6f4bdcd5c862be812f2109a03253d683de837cd084f6abd2321da2b70e63908c3036da54e9124d42e8fc22b223e37d7915903dc7748911bafae87c569352a151f9ffeed2b0830541c470305fee2a39ef61ab9ee0ef2899503efe5fc2cd53a1b32708bfb41738741a2f6782715820f136503a4829f0431d679181c117301a509bc341db479dbb4cedcf65fd775d78123f2937f260e578b276691da1d332f9ca8a2df897e2f96a2a07e19fd6d0df9001d8302a870f412ef3191ee885fe4a5a409e05b84eec430028070b3d6cfc5e7c61629898a775e11d80865947c1e6019b363ba97470538a1973c413a99dfd01ecb6129715a48fa768433e6f1d985e2b24231f9d5110b7bfc25f65c8d0ac6e2b7e05829ae6c0e9a8ca2de8ddc0e7f1c775c325078514b77bdf239801f6831e45500eb5e754ae930493398e3f0b56971403fc2072db1af92991fe3768eda5f216632f35356c689692849cad67fef12b1b5af88fd3", "50f86899ee4f5e706290417ebe3cef4ee7ca67b7dfb7292a11a67945a36f312770c168cc0c4f650e38b9b1ffb72e18687261037dc83e56a340bbcc3620c6370f3f72b861eb5900cc39e96e981b15bb35864990098943d91d1f7f5bd3b8035bd08be09707903b8142295524cce429c6acfcd85c9722d024e08870b8c22904ec11c37104450c8d1e7dadb1f84e46d5d5f363c43b722a45e01c16a980d5800756ce331c99e3b5ba345c760a1154e1aff5bd728b95590ede3e5588667c0dfeb758a3ab2ad110446a1179ce050fdcbbba77ff7e994f5cdb0cec9f32ad62ecbd2cd13239d5c2b2de32c205ce703712ef6ef1e98bbe1da3ee2f9aaa83568f2246006bdbca452ffa61735fbcf29fe5fa661749163b96c8289c11e7ba3c8e558fd7796b79232bb46713a553b487390d6bc2c11df6507cb2ab01f7df12dbd98bca77cafbb5ff8d11db813c7fcb3e7df760906e307fdd3bc205b409230e64d69258851835b76cb56ccee25d4e3ced45130226d338f77c0a3a7e86d6a6341efa344f6e9a48b6942a0416ea3969ad8891a9b603702f9099e8bbc5517bcfb540fc58237c48a8a5dec8894ea1dd2ff61115e300b7f6dfd22fe305531033fdefb519e6f1467368fc77353a2db471b9be8542d47fc82ba9986fb4171c880846d44d3813e5203e62e45d4ebb96f08b187595cdfdc9ed2e5df7541fb4da8c0ec45b05d972a20cb21b93cbeb1375d113181f1dbebd0122c59a28c39592e174c070268d7152ace5bc7296522d06749a51fb836afdd69b73cd4d80d8d401e987232c18350d2061758e4e4976e59b8a5b01e2a6c2a1e674a7ef279744d0e2d02d7e637e995053b050300f18c42f86c7267d5e754d8d524f0e436771fe0873f87f2d1fc19fab31579d6ffa48f702752f4c57870f1980fabed7c09e193a6870f719bc2691bc91c0b9daeae4d2f637f1553c5a843a35d31fa0b740b29a988f47409c6d69e572cbe9bdd0516d00081095069b09e8f41e68a93e17aa4effad0e491b403dba6c65b6213c234b7701471f15674d444faac3a2fb19ac435d2b06a44ac2f6c4045b800057d8dac79e8d96bb8df954a592215f0598de2e24f69746e5c3061dcd403d63d76983749cfad0e7738bfe857a80b4fa645a76e101231dc4175612f54ee09abcf466843a06948b98659b618a2a60d3609f3d66077177aeaa7d8f0b2fd13df8fa1c830d937d8e0aee3e5af08005003673a36f2f39c3c3c46f99380a3cbd68dd439f30fd13d1eb5e4c4a9b30caa988ee4a15c8365f3e274928b002719183f2aa4d8d1e8b3e664c7186cb14881aba550df7ea8a022e75ac17da060a116915360fc755802a74c2ae605cb4fa5a38774722d2ab6ea1abab9a21dd0a34e212dd138677b28f60347b608a6ed6aac16c1b3a129208caf488caf86a6a3ffe31144915934ed9f1e6037935c6b1c01018a1821a1f19e64a30ddff210cca77f8253357d039029875019801d54b3f6f433faa0d135fabc4debd7f10285738b0aa43c54020a8899c1c22255a872cc278596d00bf8bb74eb63dd727c22864529d506524fb78899fdd0f36146e5893964a57062a46fffb0a62c6a753f3b4b07118b3e2a57a205bf72e5ba07ab0b2553f5ef8ddee80403e0b6756f90a96245450abd82918d5dcb2518b9aa79b1f07735e1f439a32cc3fc84fec56a69eb29a3d101f9e4df5a673a173f26bc9884b5ad0de0e10df0dae50eae7972a2b933b26a3144baa1f0b1af323e8b607c4c64eb11b602852d4ada8e79084b65203b5b7c7a38f0d03f19236c1b4e5697bfb66c5748992e4f17065290167c262b0425071390e0edbb5a09af576f7d5a5c31515b4d3b20b9d9ff3741de590e025407316d2a17058876a8c9a794628aad449dff257c2e2341ea92706bba4223d336cfc7a21b0204b76be41f56a3040bd8c5415ac02b444382fcadfac7a1e8c86a78dbf7915494f6b82ea4c7e1f71ef52ab826e896c84b5b8692ce32da682343ccf2680e307c04fc602d66d946499b23cbc9b2f64b86875a8349c61858a52e65b4abb535b1ddbfda7c3370839d69559ea99621d189f5983b1d92c520aa9ae120a124bbd6af25fd28a846225c29a0a4a06270644", "1196ce4a8cc0400f7d3b8df1fcd00edc51517faa4173736f4826c7f0741d17d2adea2d25403133145a47f1f74538cb7bf92a18aea574960d0887d7fce7e7eb5813bba20e54b5ad66ef5c2e5b34effec0d9552868afbab848f3f9c282c49e1bd0d7858ea02d6cd44ff461e91bcb92e824bd3e315be8647bee75ad6cd3a0814eae112c0fa7c4cf2d0a7ac2fc94fb2b45b1079ce41bc71cf590c9699115186a1bddced49c69f39add5fc5cf0c8c790a23a59ffd5d321bc82772f3f374b1bf5e56a0ac1d5564da61c49c7419716482674fc8ff3846b0c7b60068ef49e526a816673a459970994c1ed65a65baa9c6f819d89036a29ddc983ad30e88721885b08fe56283339f0771098556e86bb3117974bba149d939dac60309da14eb6fabb50e979b48b2478ef9677e86eb39c872fb2aab66985e6ac7e8ff7e45f6fc8eed8ac3dc68dfe52be0a538c3660921fd669305a2d6425eca000091c674d01cfc48bcc67016a417fe3f20edc8f00e64edc0af8b26efaaad09db5a3997b2536a8c9341c6f5dc97d3400c3172863b5049da0721b23c8e0314d1a21cd9564266725054235faea572d69669ec86f60f5c5ba9b1c8e299329940256e3355d3095970e1868a7bab246854d850faac2e9bd1fb2c13da41ee01d5650773d1739490b4c6c9e18c47185baa953cbc98de09f55c42e15efce039f04d66aa0b7bf74543dd19149e133c6c4a54094cbdd46b1d9688653e0765efc9b9a30dd9de3b1f751651097d9f4f7eb7d933fff551f5dae60386ec581d89bdea8d4150c2baf6083d055a8d1a4a754386027e0ef29f08f3238a87679b1b5a9d9f8b30ba6658b8eb49cd1787e2f3648dc30220e8328ab6bd43f93b3c7c731a5930918e7e7b70b9593ca4a7dce760a96542d0b60e2206830c02383f24ab24064795df3452398a45c867391411bb669a800642a2574f2143e48df284f9b65d5c8254bb3ce4ea937bf489b6aa755d9d6bb9417b33a6cff710c5b309e2d465fd9cba73f8bdcecbfee6adfea2c1cd5c54e8b8518c48412837a1e47052c8e2a2e908ead84f40a04f248813f87833c96b369de02eed9896d6404b141b7c372dc139178197759aabea372a40d85490cc26b0d508cae925be7ace65f266a4b7f4e5c741f6bff5d2a47e796cfd713b93ce70e54629ffb28a3effc7701d1c7fea8a117a13f89bae5ffbe06a479829e18240e760026cc443431ded9ab06c2aad2e03973cc744dea065cd7e065543ada89da7668c07f82c47d69c92ba76454eb3a600a8126c73c0f56ef2b786f385890ea90dfb6293a3c1e6bc7c4caf516718a7f065ba3ed5c4629c79e32e719adbeb0055fb5eea665f03d2b4db0f56c13b97ca85ae9428eac5b8cfeeda5403cab80bfe8d190efb9c83a0781957fecbe18b91f31bccbaa9629197825b73a0cb98a8207dc8b6b69150309012928b0e44b3baff7c1de1a339cd5ca554fd6ef2b83bc31eb9ce47f723540dd27f9dc51db61fd674ff7f52378946f35a98a2073311fd36fdc7b4b61776767771717c13bcb902465bdeca6ff9ef62e75ac01e5586fe600da3ece19a0278a931b22a129bd259814b528acca7eee9d5a05a934c15b30346d5c2825a958eb0fc68d881da21d7a0d0f89e0705f3ddad78e12f4d94757aa5b367893c0b51c26d7d1f95c5c706c86832eeef1ec3369cfbc2ef061b199315948de22ca34c693bdc3883a2d81611352a37ddeb0d911d1198d3eda07923ce4fa5e097ab5f13c57baebcf0e6532989c6d04152b58e8a5a78853effff193d22a6b8313f7d8e4ffba17bea8a0bc274e31df3fcb2678c53a74ef6b886399f3878e2c09b8974a2acf704d430e4cb6ab75c7a7d513f4b670702718a34159b0b1877a83ab82ff44730514e7e5aaa6af253446b0324428a080b994cf9512c9260168f7449b3d2c164258c28fbf207307ce51a38ef356181b8e735da0568eb9d8f6d3c628bb9bb7d01a76cea20bda7d3c757ac892abfe52f05fbad4a91bc9c8a9f89030bf4b554c8b79b27fc036e9cd1ff1875834637c0d712bab59713aafcc6f023afcc547452d2c6dee95828ff3ba52ad43d763baf84fa0286d4180f2d75af6650f210f8dc18b3565611f9617", .None}, + {.Sub, "-1cefeae9b99497212a7a6fe63cd20dbdd38c0ad10e38ad267fd626cd6bef4b79566118387076d741a9f649aaf42618bb2532b56b81dd7da92512d335a352e2ab6dec8693b5d48b238d5e87c3b59f8ab75c3c5f02b5cdca7c365a9529f9610b27e4d98616338bfe11399bf8a555a5e1b05d87f5b007c2d1f56232ca73c89503d10edd5bea5efa769610c2cd9fcf2467db24022cf548d8c3e2cfc2be392ad868b0e03f14cf1745b96bec57b25f19890af37d700b25be619fafdebcd8848e13da228cca39720153525d79518d2f7f527ab9bb1300d7a93bd82c08235a390023727c4a2831a3b05810785dabd7ccab48bb3e2eded5880ae12b657af0066a64cc651643019d6aa2a4ccd9be6b622d69f449f13641f83f91e975eb317d9130beaa7b36412301533d532ec5ab1e152c0524d609e859378b3a087793827b249021cba243aee6b53c1ddde01e6093db5db7e11c1acae1015eb2edc6e80ceffaa4f06c97b881d92e3badf115434cd8fc9f9486709301b3cd5ecf994fd1805ec502faee2cef985474d76a6a82aa837c8fe254c8263d3403cf6c6677571f53b001798b69107af70672facb8e40567fd8ef8e9877d4da87248fcefcacc9b219be107b12533217d5e8616c2d9299d51f0d95d04eec7197b3ac652f9daed43df9f93b9257a872660b0b89e40ccf9389fe2fec8ba6f3e80087e9ef1f60fe0dcfa6886ebf38f1cb96e8ec3fe3b0d02ae68601c3f9b829b04a7983cc333a65cbf475a82b75569828fb840a9d6380ef0d3023e1c981a2f008c90228193bac0aba5076110b039799c9d41ce1b3557fbfab36dfe273e5c4dd1cd085e9a89dee0cba84704b034f1afc8bd47296fa0c249de6581bd6b5aa319108e6899223348b3f99ffeaaab53212506ab6b6a88f0bd01a818bec56571bc565e4a84a0d2ea11a9dccc357c670781d0c6a31514d189d6e94a0f64d482e5023696fe9da5267f98cbbb231194cb98bcc8ed89876084abd9229e06b67cc5e8a8589f17148b66aa5cc6161a9500c3ce4d547cbe1560c0280f13f951055f75a61c6f12d5f6a61e6a285588f12be4a21f1b66b8fe3c7fe1d80d5b10857ed13276245d16ba686a35ac812a958339d5320c5899c08b6cc66a35d56e6719ed5604cdfc1b965979f123b0bb7bc2a35e58a6509f36ea9a7ea35760d824773dabd8d63b98b1d0228fa08f33fdd1dccc6280b07a97346fffadc996cf6055078ff1aab76a3b49ee8d14b5fda0545a2b792526ec0684c3803c526d6e1dba4c6bdce18b13fa5f068442df44eddaf4754ef8074da2347238efc89060a8c558f8811aa19b2dbe3430feab2ea67042136eb4b88ead864099c0bdf27b62b15de49f42baa522c1c6f339c1fc9f4330262585ece977dcf879c3ced6cc24d49355c54d5f78f46f1eb5c2d748251f20c45eab25a18c1992f803ee51da4e458f0e5e2d0dbd66ae1c3dad5df5495fcfe3820acc5a85bc4bca25a0d5dcff2ffa81881603eeabc37a722e7ec76107bb601e4245bfa775f5a487ec0643cb729427fd9a88247d6e1cc399763589a433a2da072243420dea01118a452efb09298cddfa77e4051f7318a0953233f0303f5a8f21c6afc118aa5f30816cb70c9d84aeb8c9fce7b47ad21fdbf398c36c96734e2575b374a97b46e7e46fe6caac37d575bc2ff4da27553ca5c32e681961ab904394dfec4bcb516b1eadf5e2afb3dbcc26d22d845deed5b744e8d712701c56b7b2942da53480b066aebe31468ea15cc46706ef224164081d742722c60bfe1631b7994b0ac94d3c9818a1e0ad38f2db27ea519bb41bdf6f94dfcff47930f24b91175c6486f9dd06d7c804dcce30262245f710e6f01b3ffdc397e29c9f52d5b7768584f14e62291393c7d5e9ffb6b3db43f87865f18f696ae66c21b79eda3e038157783dea8b2a3df4459001ba959f9ee995a1da9442a7b7e7615299ae296b18d78caf2335dc27271a3f6dd6e3f2482fedfb760ddeaf523de142e17de724a768a6934c0a28fc50202d5746a4f420739679e0f35fa7aa88fdfab45eb622a7bedf8cc657436c7ecc94b97c4fe24b1e745dea9d2ed358135548ca25f10d91c5ea6a63c399580acc821c854b14d14b1c", "1e416c8b222e6670f6b46fc4297240bcd5993e870c0e7348e64ff8dad767f36ce16ab974b9208d562b3734c7ad18b94953147d3d9145304d7efa98a92f57502349de2f1aea707863e2d7dcb8ce000fc7b6d65b42020f26faa32c7421eca14ceacb9ec7e3a5cb45a99c4edf61923ddaaf39beb771f30ae709f28ad05752c9b89bbcd434de42e3a2272067c9689298eb35cffd422a75926d917bf0b7b04a43b58ef888277dc6a89b9f0645767ea5761a333de70d48d54bd399629160d65c24812dd1c161ff7c56795cb6e936238cbc62c6084857e160b02f9e8d27fabb19c6d4ae084d929b1c20be473fe662c7f83b8d7788b138d132cbbbf1f01ba9ac37bb7fb7aa0f45d600d1b25de3d7150bcca3c61e253f90f8fd0b48d983838eeab9a520773fa66c7c093caa53c9ce12caf5703f0c9f2c21b915d61d852a734eadafe90f3f0f9bcc0913446caaa44698ca06909b3333afe2f4b9b77e281547b40d32f2b708f3cf11b76198b82a2e7ed15b4cc212051908d995e15b52e3ec6b00b48f1a9c13c47c82259fa4d88ab7e99f672407ce28a06d1cb54c5ec78631740c5089f25bef2557ed35a48d287ead579d3f4b5f81b31fdd220124346e8393fd08658819ab767d400f365cc096877426f03b474b75f14d67780d00dfe74f7268be118e41937a6f4593ceae48ef3b61dd7410d5b45db9f8186fbbc3ed4c71b61a59287bfad7b25abf6379a869767781facc2a7619b0820633feda848f29980f9c4de95106a45e8b5d228fb939b1936658ad13a10c77a8c56a753c1964b8e51f1147f6b927b400d63170a0d6b999eb8964ce13c62b19ad470093f6185c2cc54e09bd0e9e3bbfda31e9c258b15a3f2c65f15d1bcb79535c9567129d9cddf001268298f2a4142f279d32a4be78be71336829f7d2e98c4170977ac6051983bfbb648e05f4702e4ed1af250095f16a2072b24d3cf4054f3385d6ad87c95639d45fadbc2d727d19029a55bfbed5626ca64c4bdca9271b89cf001a96a408426d7172d008c4f9ed32e03934d82a7d74b426601ee4203d577a1a30bb745d82135031842ab46b37eb6171fefdd13063e83bc462c64af0e018b873cea4c6c84afba866c632cdb32fb64b758420edcdb5173d6e7eeede44121d5112dd97d115a00c78733832ea0617c26ba7d533e59dd88028df4af274b1ec1e30fd3152eb05ccbaee29e69697bd008347f2bff10a0971127cc6cf8c587129b24c0d739d2a24fea8a40a8076b4a6a7079449a79427a99c3e085568641fb0f82748484e7cfbdcd892ce3f2592e06a7ed8729ede81443eac10bd10d0b854a72cd12766e73df488052d34a398963471b52d3fbf64b2faf2af05d3cce9e32f082b1e0b65ccb5e985f9ccd1d0b25396b595021883d488210a8f6d6d89961cc798351d770a36e47e88b9f2a18e9644f60c6c9a82d98a5a2a849aa0ebf9451b4c0ff19979f0d99d9f79d1fb56bc490bca8e9d3e2ce9f29b2e4282278b0aba93460fe6a865c00218286aa71f36648a15cb205672e27153064a183f8798674ae68ac18fff6b61039c0cd78a3035e37def083d4c50a15445acf54f5a4bc04008208c5274bb1b9b3c8ca3520873d2c64a098ae66927d7c147f7e887d8332df413e86806e2b0eab4f170bb7785857d3fa4917a0bcf4e17eba8e1233e82eb85ebd3043a91c21c2c710406bd1efcc6f4dc34860d78c8d9800bf0a7d3282d52cedb2f64f24dc258f764da82110459ceaa995ea545765e3e5640ca6919103160562ea50b9cb887d80ed40f10e2d3b4ae894da727c93eb9fb9371a64a68e3872f79eb4730b1b251a023c62d159fe6b24d1221535fefb8411b3a0b0e404002b26a56cd42e04a7717754aba1e098b9dc6745c3ee1c85f5a6d2137273a7e22305cc0362ed5d33e368dd666f69c8b8b9b7439b96c0d41ecda1192fa337f93d92be9c8b5076662dd3f18d33b3cee882641d627e2c6b3f7be5399995b199e5d9a5e2f9432a38e200dc47bedcb4b842aa26da9a1cd4324bdaa7952db60103051b81bc628dad79b17b22a2ad65fa89bd1795d9848492a9b53d14a7eb5fe681e6e1ad0154e592255d2a779e442b4e0efd685105681bd18eac0b9b174", "-20106b39bdc7afe3095c16c28d3f6198b2d1ff341cf1fe1b4e4d5b47ae26e82476d0caf84027faca45d699625c5b1ad50567a89449630828114bc5dc898c7e4e00bcf78425cdc1161badc535095a08732c9a21322d6c03a266921d748c375d9d49ec60450904058aafe89eebe79838ca3f9736ccf387142948adfcfe8f5308d8cdc20a9ce8d349908173f6428f8b31b3823d64f9ca1ff9cfa8ece393dcf13c1a068c18cab81cf735c50af1a4970eaae275be0dfb3131ed94607d2e5ea505becffa8e05969c6bae828e7e4ef684b18a71a3f987eedb43ed214daa305ea9c90bd5ccf015b557263f4ec5c12044c2f0192b6b9f2629b379cea847caaa12de0846090e3f5facaafbff2b7fbdcb2ea3430abd38a3b07cf629e038369b67fdc58fc82aa3b89c913d11dd40247ff41db5c28c6d3db1b531c976a4fe629b00f6b205c9634a8a375cd5224aac8a4fd67fe20eacf4e05df30aa4e65a969616b3b781f980847beca49b1c77c97e634c6125460a790e4924166bce54e7e10470ed04bec97ee2be01c973164b80b5602168654954508c73ad59ac12c63cf826af0c6822a8ecf6d4c8546551460c8415552c3834e6ff00c84f6afe13ff3b1eb598e96d393ede97fa9e954d1f99c024c617c9984c3a3d0ac8a23e5ffabad493520851cab3bc1aa0cff64c6cef15e87401c072d990239c3a00970eadb9fd2d4eb082e0146f89f46bc94e2777e3767925ea5ae86a119c4b86adcc3b9db835865756f6d0a0a67026ee439dcc65f148a2666896c9abbb3b7835558cf6cfd425648a267258a6f2a1509e17ff8bd62eb5949ef762f5522278eb7a4f5f2e7ff73cf86d950e6d438feb8897791331f973a41d91e7aec8766e9263eafe0034d0e591e9a1252d4445c53935d3089d2daf35c0194c26ef5d44a5e29fbb1c1b98ef2b2d9c879a0a6cfbf1ff1574c439d21fc8536a821721bfd90785ca847452ae48ef058f82bf50f90b39e1f023dd2043813b8f445302596f0fc3e26e172f220ab29f33878d650988c83a875cf74a38eaa583c81fb1244395e373e92d06b21a7bec3ba5ba7556990d5706c82afd3a51123bf596d4e8451c23563d158a890d30fdf77cd2fc496ca2e53c0ee5360f8db437eaecabd598dc3448e0196ca93711c23950c7f435db9142ac6861a2926fb288f539584d56889e4d8827b6e2cd53e28b9500b8c006b2f9186d7b1a7c62bf9ed3a04072d1ce5f7e032893ed95fc00b1e0229efcfe35f99bdb92ad8c57c9e3e69517b9f854c14545aac4f2864ecc915c40cab387438e1d9a2e0cb34aab8ea711a4e77169b591eb59efd4eb055865926c9af84740a3585124e1f7f5c7007d572e5da40cea730fa48851c9f2114527c9552cb61ff257bd9bcb73ae0ec5e75aa0acf59de532bae90f1136b6eae04e525c039f4d189dc730225e89047088d4b3d89fb992f8cdf9b6abc9684d9ef76f3a396d82fbdcc7b142055794b43e1409e92295afca982b79b67e0db83e656fc6c7bd7846acecdeddda7fba530c5cb6ade3e72e47b2c7ac15d567aa2437c5890f94a67613f9cd7243cd7f0092827b4baa7dd28aefc73e50dfb320c12184a8ab4bda971bc518b834eb70a93a0c5320347545f6b0b284bfe7a8c633c45b9fa61d81283f96312afa2ef8868c75e9f299fa4fc11e9d53335d12db2878c768f9db7dd801479b9d0b489246475334035b788d5bd8177a00ac8b41a492744dc96032754e1c8d163ea98e4f5b000d6376bcecdfb3053170083272c45e4c1932bf7e93d62505c6aa2dde7dfbc5e5bfc9a9ebf2ee6e99909c0497a30ee9802700a62b82926f574472046dac2a18f91b64cc8671415c51055126f2cdaa5490dac2e7166a4b0230a38e7cec289d6fd2a99e495a23d5126b32f68821ec29a11541f4f5d568146a77f403c985ff63f76052d1ee94a732991d1535b3c02c706ceec7b576ed423e54147b374977b24f09e0f36595378be18b0799d3a83cdee67084d1018baba09533f21776ac96a5f1ed707c044f6d734ef68a114517c370b1d8d24f76684cd2953f356228bcca1714dde417a3b3959d2a5c52bb9cee2828a3a1ec7bc3b50baa2d1f44b36fdd1b2303d99e35d58afc90", .None}, + {.Sub, "df41d29a019f0ecd73d5d51868e93322cbde48f663629054adad27a56d3450e441ece6416fcd3267be82905f5dfb03ce36f3a4d22d195efd2f042a24dfb5611354686bc224f1dff7ddebb76a942bbbbff70d67e574d5fcfe0a4d2b6547286c83c580fa11c67dff9bf288c7f8a5f4c0420544f7608b68b0b029ffe36471d7925c5031f5ea688adc6f66163f5b2c88bd63be2e6c66d1b778b7d57f6eaa629b74e74c60dacef84532c99e2ec671880f5dfddd8e3c93c5aa4aa41fecd5878c66fc0244c02cf0798833a94e38533ab9b6362a17d0f3f8ca0a473c0acd38635f9458799692da2aac4ecfa26e4db2eb12c014223b89f77cd480890b1ba695f1e496adf9544e689637a6d330f9e39712df37f2f4990f740aad4ad454434c3a03560fb8b3533bf5badd7162cb8470494311cc8d3cb3cd23fb20db7484746374c5fb0c4fc669fded9e4279aae14871866f394dac19c5185615bd9f81cde1947184aab2f3f3ac56d68aa6541f141edf14ffcb4f70876d9b025cce6fbceada5ebbedf3e17a0d26722ad4f64ffaa351c7b20f3002c4bf57cbef22b148021f6488702f7543504b4b7eab99fa86a2b7d73e105e74f2afbe92524eaed93c7f16dedf66736fb98c5811920e022261a1016cfe37ef9158ef714061152e7731dba8006644e8ec4d47bf80476a9d512dadf563674547588cca1a39be57ba47f267f19a04b100cc3279252e674b3ecec3e52f803b610fc63cf587dc5ede63b521dbad4911bdb48c714feb0927a0aac7d8c1647353839f3e7068acc4042408be96a40ecb3ae2ff47ac76fe3fbb511f9fc5f0ca8bedeb48ae65a3f0c17914e3654c105e9fb5f39b354fb9994a66364d6558eb0c2c0cdd4032120314b9e917fa5a16ede6e24c11ac2ab413ec235e63c3f98d884257ae00bc3a589e8ee337038f31799cf1c811b0dda507c065bd876791294eca5a003f082eca94f61b4aa3470e784116d804881bfa314686b8a1bd77fd3d9ee0983b17b0038319fd8588b53cc46217e870dff7b7a6064ab999647b5a0a687fd849439fdfd72f64cadf6a7f1fd47b24138b473350c35617d181ace4cd3bbb1ad0e99051c103621f4244ca5221b0a79e04be55fac21fb34462a77b3635b8af5c9053940daf1f37b8169702dd2a60aef3c4bd511b10104d7946dd90a67fb48e01cc1f8d28b448320a83cc87b8a87ac9e57f5cacd7462bd4453d4b53bad9ae9d3e2f1da3684ccda891c834f9e4adaeacd716fb39ecbb89a813b5a1503f6eae8ec9f64c27cc6ee53629fde9267b47fe73f5d87fd0219392042050357a8ca77c9f98ffb7c94ed65b0ac816d4407c7483871a0b46a41f71a69081b284a339ffaed03a71a57834e24de3c5dc1c417111bae3a26d549fc0145716c65b138e65280d4a88ae7e0bdb71644e03b6c463fb936ccefa17fb481aae6fa047650c897ec8313b4c99392bb5734a1dffaaa63db142d2dcd20496a6898708ece00be12f76b79784c6ef52c729da07b5daf93058d34f7d00be29b9c29ab86d09315519eb926976d03475cce97db6ccfe60d70eae7e60f88886c68c5cada343ff180644e70ab71514a5097da5d0ba8d036c859d6e9cfef38c325df3bf5c28baf894b24102ad3baeef64c0bb2be0852a9a3ddc2ccc7d553dc674afafa2447dd1ebb918a112b2f16c349e60fc74b35b7929b7c971d7607d81f04f75090fab68db3c77de474f81cbf8a4a0a977c5b22e7d9bdaa7f726299224be105095547c24def68b8d1e4ac11ac838cf2ba9094373b2181211e0eafa6ed5237a20fae91069b1a301313870752a276855cbd79a6d1ddb3938a3eff56bcd6c2d5a9204179ac207c54392d9d3ae7e89610cb362e6d48b5cddf6b4962ac1c24273608fc105559ca2f452d2d5ce7afc4ed4e971dc20f0b8963f122ed6be8fe9eece0038c6ab7a879a1aed8c0b1679d3d02c68d3ef29502c74b3303cb0fd6972a45ebc5759085c09c8cf9402919dd59e43bc66f0d3c102ee44c4b7ab912d0f41af7edf803577c46735f067dce981e18abdffe1cdd5458bebb50bc4c5473475f67a16f8e0d85cd2309e7aa1a1f58bbdc4f7e88de2535ba3babe761f18a22021457653128e4f769e422c", "50fdcf494319b6d34350bb2127e9b11cd8e1e23c2d6b41078605ac8493538e850667055f5ddc11427072b3c28158f839d728c6d5794d3d656c48940f919f35547acb43c0cd96cea6d5d7d9e85fe79d41ef626c22eb6bdbfdbd5bb771422b9402444f534f0fb99c3af93c7505a63a213376891ce13145dcd538e8ccd745bd6e2cc802e9100bda292d8dce13e3d76da3d23f379694eab66105c1b11091bc9cf2da4169d3eb05741c4e239c01a35e6d94610b80ffb0c5a83e495d8a713adced778b054bc7393b8db698bd8681c8aacede65eee77ac498d4a369380d52996a7204e1eb9f1a26cb2544df32a2942e8572c38d5ee96b6ca11ffda3a7b6dcb2fa80196a04b5775cc115fd7b5e03caf3d91e772d6466b302e7e0ca9e632a3172ddc9b857523225355e8e35c8dd8793df1a4dc21ee0a9cb0ec3516ec573b9a6acf3fcaa4b803aa1197529e8423da4ac5cc9a3797e3eabe255a659335faaecf4f1f6cc0a07d213e2b4e2e74efd3ba6cb806361e7c8be7ad9d5353b061913823606631450a44e16469d6c1d82578cc014dab98fe8b7a9edb965c4920df4f397212cb1f68c43e2751221db1c84ac43cbb7a12fc46ff45f90f99f4164cd9cfcf4a6506068b0b4a4b218a0bb0fef832040f844b71fb7ae23641e96fb7ac985b9549161b6d12fb350ee9bce7a142eb16924d415b00cd7738e8bb15a65bbdc96e71f2390dd37b46cefbbeba08189b16e782e2089b1a0150464077aa57d83b370aa53b5fddc1d4b95f795ca6adbc54d53d87b5ec4f66bc285df7eaf035e94df5667db9359753b84c2d065ffbe8e2e0409312942790fe210d4e08bf768a1a5449e51666f61b9e63e27d4824778ae1fe8cbd3f5a51185ac54c7511bb39b7b985f448023bea6aaa4bc84a47344187bc183574f75f08338eb011dd983a11df6c287a3bdfb3124e1ae6bfb29e6420e1c1362147510950abd87c4c9ee420b2177b8f2984b4c8aa1ae1a84d3c26746ff531a4803dc82802712ee59abef462e51d67f8c4295cf376cb85ab42c0ec90954c1b3c000df0613f2c56daf67402a7269b054a817b073974b0dd8984ffcf37517953eb6027ad3695b0720045dbfe1a03a8b7db1834d57eeea53a72a839482c272250e53d52ee5e396563e0f4df9d4be5e8e9d8fecab71a7836e10e8c8c18d9019988aaaa819f5e41c925cc170b563714fbff77c394dd4d8e30e34b9fa1e4c3bad89a99e092e839e90224290d571e267ae44b843a5b85081cd45f8fd2803499e64a5fd5533905cae6a487e44bbca7d24f96052f010ed40ae2618c9333b068499177eb67960f17e51ca6f07e6aa58c9dc8e516f299d2106ff4fa90fed981c8b761fc787930b87a9e3b857d673e8543dc380145fd95955434246615c905583d0428d6469a25a3a8ffb40785a6e89db6bfb7f5d7e288181a2ed88d24603b236757dd23aeb810baa6a63738cf9153e718738d8dac8d2569c83ea9494b2f1a2cba1c552084082ccb11dab0ff39d1cc9179e68baf3fd13fcbc81812e5bcb8cf272b252a86730d51ca6a78821ffb40c7bc0eeaa19e16755aa8dc441d923a0e17bd876a54fe766681f060a736144141c6bc45faf60533951545e730201ba827472e09bae3df3e5d60783b7269e9bb1a0d5a6cfbfcc9ca29aec8a01510f497536d65bf3a064061eda7424dd7e424e41a1266adda6991ed899b77563a9634ab29e994b8f7a1adca17ad83fac9d9f1ab32e0de58ec87dd28d616543edbe6a92b4355f99627eb593c4217443d01bd0a1ac80d0f61d2c92493deb7f6d92c847baf2a2abb8823afa8d88e385eda78fc1620234027770f676f0c8c3253a8d02ce7ad75b2437d5e3d4d519733edbb462873f25fbfc3ffff83b270e3042247f53f71a0b5c51064ab452f6e3dd38ef2e467c72426811ca7386698734e7254c25ba71b9633a41874fb0f32bc35736c72cbe10978a31eb50c7033c86c8d78a959e199f06cc81392cdfed992507c4705c3c6a0bf79b16a4b4ec65b607a916a565d6e3b54bd5f7e3ac484cc0d141199151bb0558a3de424dff895144f02c881893560f42d43cb0794b7c391c8fb177be2087c3a555c4e264d0b96a82c2d462cf2b9869e7", "8e440350be8557fa308519f740ff8205f2fc66ba35f74f4d27a77b20d9e0c25f3b85e0e211f121254e0fdc9cdca20b945fcaddfcb3cc2197c2bb96154e162bbed99d2801575b11510813dd8234441e7e07aafbc2896a21004cf173f404fcd8818131a6c2b6c46360f94c52f2ffba9f0e8ebbda7f5a22d3daf117168d2c1a242f882f0cda5cb0b341d8482b77551b19917ef6d5d1e70117b213ce5e18a5fe820d0af706e3f2d1167b7a92c4ce29a1c99cd20d3ce300020c5ac262644caf7984773f7465b73dfa7d1090b1d1720ee757c428e979343135a3d2d2bfe5c9f5225397aaf3c003e1298ac33bab1ebc8d4d5094dca08c1033608b6773efb93eea16948f4f98f1397690d5b59bdfcc1f06197bc734a8c107c56a09b5e02208907846005c0109d0857ee32d02a6e8b563f77ecb1dd32358ec5d8a05bf00a9ce19070fa57ae9c34c84cd4fc29f0accda126faa329b866c73c017464e6e36a77c92b3e6e9ebda42f3d5c36cd016e338497f67ed88beaf2028879934b6d1c6dc85e790cd2968d85be4378a32784bc5079d347672dc07adde35bcecb5f42a70f14f02c34cc407690999781f6a1e0b937258bd452e3fca32c1550f97d7b179e1eac0230f50dba36cdff5616751b17e4cbd3faada3937c31cfcf6977bb712224711b387357c180c2f58ceced7197f43fa427131a87ff2a6ab32a65fe2368b5ab2e58d6feefac4b83eab5f9e4d3a33c1080d4086149ce083785763be379e283c9ebe07b6b05404551191d63fec1374109ad824da4804a626e48575056001c4b8635f4fa5d270f23b6f5551611197ecc15ac4a8cf9e83931be0ed1d7ac3a6cbc04e4f84397b697b7175e3eed4b73902405817382eac65ae4d68cd645ede7e8ea262285305800f57677eeb1fab7dcc04eb08381039016d9d7109b362713ab7154e0a167fb8c359546a93a125830d3b68458b2e73240d0d31515c613bed0088243fb93b9158832c01e4df5630fdea8498945e952fdc702ba3d9996f0e728b985c2e4a2880394df0056d55b250b5a6cc18486499cbe469f71b782a54ad6acacf6b7396bfb978483f3931aff1582425dc1ae7157e57a85aff3de70a7081761c20533b08a2d3355f9d3823e6b373468a4e3c7e6527cb88e17a074909086c02205634d0a5a9688cdf685e14cf18ef9af57721777332d02b9fadc25bd255372b09ee03235f026d48c6108351356e9e011394911474e4ae3d864f375f88024600681ed355819c39bc621ab8794cf5d049e8cca118976fc07aedabb92d5bfe230513a2e86ee2e0e56beb571cfa74080e6520e28656d7d084909bc03029e7b297f535aae1a983187256e771c4ec86ae898f08b2de99f08afe958bef6833ed334e3acf4293fb4a7cd210b569cabe0a94e57fe61f0c23d14b7623d5a9483a888f97ed717bef79c677c0e6ce01615a53094a5f0061182d814b0fd691069567cc2a09fa020932400a059c74582d1a3e63d4f2457c866c86160c2ef7c23ddc674134e6c20cc115bd0619373ead65c82778e016ce6903a0b042d62eaafeacca92ed8fb6dea71f70e1cee9616adb7724c90e9411c52d3ea15e9fc6472bbf586931aa3d4f9338f90c9f60e926b93e123dce22118d70fb7eeab3a8295e8bfe8c3b5725ad957129d214c318432cc2a243e1cab6bf51082e7f86884fd5dd36db76284b6c82d6e8d176db519a47bf77f1c53fae03f251ddc7ff2e9f860590de812779e9409ac9a6eb82ef30108e667463d757beb15e9c12a50b0a34c57357e17665910ff4dd4242da3c357b7b7da169e80e8e8cb7f2ef2cdacce851acc58e19d7366fed7dfad6f53c91cededd0dbf394a6c37b59bd89ab48bf340240b2028d59ed0b899eac1ca074c525f7ee0d648abda477684c83047fbde0594a331c27219cccfc6c4f41c638546cb51a15f54cd28618a51c98f2a22dd00a57cb862236e641ba60ac5aca26f67d7f37fce72bdf029c8c7815870f5b0aa975f2c6364c68438cd1c94ec7822dbf97736699011ed8380a491e505d5993dfd2ea0b443f3d0e65c67e682f934eca53526cc58bfc97c215ba664f17c40418bdb58dc6a953b1bf719205a363d4f67daf3903e2b804b05d845", .None}, + {.Sub, "-846cd32e7c43effb59869e6b6fb7542a3c51d90075e4ac7a3fe366f1286c7f2fec9c8f7b0f5168e3b338d9e5415878c4a9f7f61bc6c37e41f8f7b796171acf9bcde78afab211757a04f2f27f99659c6fdfb7484440f4ba9231d0af06ed4c7396c7296e8e5e6318844367dd72752ac0c3baf41a1b7d31889e36c326b1a55a723d8907b0626f25080c765fb933c3b1f4a55c2db713a00ee4faee7ce0e56e3b614a614f5bb40200c3e400c0dbea0a9294423b955486f64cffcdf797cb9f08381af5c6d9d53d9c511dbcfa631b8a243d0b15bb6ceef90201ff4e318f8d0eec24cfb3e5ae4c71c4dcaf0f92b2e22c4ed296843c03cd3450cda129f89c987ce2ca22e483b7bfd8b88b80c32c3b88cdaa99e943e7b3f6742e3c11996df344422611c9d6ecb9703ca60d892d35b12f064479ecb96590e28bd47dafe8390426d55f314e0af80141568eb3261fadee9a12b9b11cc7fce3f671eaca0954cc649e5f14e3850604e990adde6c772774a047c13b0480c4c427f8e4880318378c6add4173bed94b7dc634f6667a442508923d6802d63787545e577ce4bc9505ace1dacbffadd2fa2dad367e31b9d16de01f264abb8934bd58e9b99050458bef56be2a63dbd8f4b076f97f4228393e5a9125177f089e09cdfaa2a449191f18986ba57202ca527038c5f5e18171bb3e37c46dc0c9967c529d1b3eee4171c39f3830aa21ec011849bca86307bb85c2173de7b107cd5e08e530ddd769b4b7acd388ebbe37c43184f1771bed7426825da30381a5a8d724c130b1f606a5c5efd3e1a77a7389d160dc0d1935ca8bd1d05eac862fdf98c0c3484ae3b5054ad1548368ceb80dd898475d0787a930b61d9560a39df42fa167cbada272534886d8741b938993a785e2f60ccfe7df41c4dc4d3a23803bd8ccf11022a8d67eefcdc0c0a601f0735ea775f38e728db7800f4fac82cc57bd5d8cc26835928e38e6b1c1c323c28913f81f28bc2f3950c20d463071a928bd6cf13a603de2157b8962b1b34e32f360a15c8ac6d2c3e92d0cf65d3554dc520c8919abe3ccb10a035462bf2242de5c1a288b043396078642d29e2e1712eb1689e1c6164d55ffdacf1b478c2200144cb52899cc2f49bae77e9bd10942918ebad00db98e7e15bd83ad3698338896e1153c422b914dc6b1a1edf4ba60f62d1030afdd69bd73059798b92c3375db53a63b0b1a35b903f75284ed9b47c71998bda8891cc72f51394eaaaf07055f3748dd1d67cee80f04b3c186c071a09f0ad9a1060ea1d6d3cee6a08f1cfcafc2bc1a98030c9528c8bca11e169529ca14e3083cd420473f7a0b7c6fd816122ae65a4dc36dc32cd71f13c914a06aa6a4f844419ad2bfb8d46fb2bee008b542120b6e8fcfa5de6bcb3360ee38ddb07ebcf6ee8ce3a24245f05a77ff66ad9dc83ece583bf9913de47e811b06cc9c17cface1a83686cc99fd907d5b8d1e54240065dbbcfe0dc2448244c569eff3119aa449c2591c1bcf789e30478f71e04676cb26cb29d2eaf2d63c02f356c9e6520ff9de0ad64e55ca0d6641f96cd49c96607834dbe96f25daab135ec037d619017fac0c035a91461f358d61213f81483e125c3af44315cc190b5829c7009067af741cff8f2a862c89facb32fb92cf060dc4ec81a0f73a6f1b93b87aa16952b456e18cb801bb8fcc191c1aaf12e118a8fbba19274d43bb2c751294adff91c963ff76eb10682fd090d3b28f64c5698c416f8721ec07d158761848cc33331282cbebe880b499295dd633fa67e9d9f9fc8dc2543dd1652813518e7d9af30eeb9d2101ec51283c0e3f677fbfca1daad630e389f3ecea3358dc0f0265a691d8f22494b4433e4e497f182655afe4d4f658ac9b76f6bf172811c63aa51b131bb452fa71815ed9008cb806a4114bc52e6b2442f11002ca7941a35ca7e2bf4486dfd04e3c45faabb0aae06658dafd6d1e09e0c08effe4b2674be19fe96881a2b4db6d1cf9f17a1fbc02f16103d5721443c863309bfe4ef69a0feb85b2f3c1882bf4b93d1aaedd590bdb2f79a8da267506db9f74617b46605ade59e27e16714431c6b56b241012d09e3bec936ccf93501db967994782c6a1ea979bb45bb5ae8b24f9fa", "c1744b30b46e7a13f7ab6b42d25a1643dc02bfb793587d14a83301917a362945b3f6cd5b502f1185f7dd7ae21e18627f412f82d81d8eec952e591bf5b5e1b800c0a1b796f7c704e0dbf5466fe0b23617203b9e1b6bcdab759c85e153a694f098fe5db6585f6d2c861788b8d745501d81872364bf84f526f398c244fd7855dcd341a411d3314d5c83468a661488bcfe202d9f0cd29f222fa2f07b8cd155a7dd930e91040af26cff7c08da3ce4bbfe699d539927e0dda287124a1a3e3aa523bda6ac2916dd9277f59d3779f6e086a9d63f4b2170d9d93178aab03d0237f9d1eda6eeee465a7bb70a422da83ebfe8ccfb05dbbc70fd80258aac0e73f528710887d750b12a3534b0bf088391e8634d53d2491d8705bc653c9fdd65c878958325cf85fcf8c3a595469071d7180432d9da063ae208a9f1d4ec21bded88108fec909ec2b49d5871dcce21a582712a8c6481011361f8c6d83b882e4116e8ed3e9aad1ee91b4143ec05798c8c0098f0c1a67eaf27325bb48fe1ad593bf41f25b3b4f377b7d059da0714353f7b41af08883500e5048de98be60d97fb8b6e7f780afc9daffe7b50cb002d57ce571a24c4c79e0f31d89202a17311093f3cf0f78922f2a0616130fef8021452c44357cf09f7c7911492c070989f782cdb345a907b9976e03f259da2d2c582081c4e79c8677e74f6f033d49ef3e0bb775a672d9e5e7244c039cb2ca069cb3f0a1992dd263b6abdf6dbeae223a1f1486bae9a599d88ec379a9679c693a68467dc3f2e0140a8e6563f0acfc981de0f7125a2b328ce1ad1d0eccafbe6654237845ca37dffccbe0c54941ec93a8bea5d4d084640261783cfaf1b7b9ad532a4560791165f43eb4de5a63ef64a728f9890ef40e98c0b5256e73f014033e0fe7c909629b4399e0f45f3eb3cb4ad7eed520499516714c9a6f77076d609e4d709601ce023caa8853f449f1ce3f4fe4e1f85b6d95e70c458e08d62b3fbcd567e38eded6156d8858e3a6035b0cfd9ea1ee77ac62141fb58c7250a2353cdc820ae63316c0b551672c30fbdc1cc68494028b8574965837cc5c7ca470cefc5d31375a6b234ac38c8a3208facf37bcfa11f35bd7d7a75b2474ebf8826bae5f43a92703c2165d6a03fe41038122dd3e42f208a71d674e6f184f3081eacf1d2bac2b35e1ba91faa007719fee0467fb4f916c1cde3a2b3bb1ca6a73978ef666c091b1925ad20ec3cb05700930701e34ef023ffb20d0fa61ca6e6998e151fd61ec166aaeb81b026d7d9d480530d1ce5ffca1a16cb31627e3fba8be45809fc00fc7b9c6f06ffc49e9b8685eddb96a02b18ccfc2bf30986c510ffb7b0260e5f1a5e456da26feccefd94bea72351de1b19dcb859397c8f2da1acce8ebe6f87d5a061374a9edccaae1307952418c51b690982432a34544c7746e14390ff577a6d6a95d7f0fb1051ecebd2fb3cdedbc579bc9585e4693534dde0e850930b5e3ca07855efa1006905fe03d28724be3ee9af1db458bbd8747f21d06bf4c1898791c31e17474bcb5f859fbd1d784b7bed89bcdd7475c36d962579b5e18ed20df04562dd6d4e8e12896ce6f5909a7a058d76ae0f031be12f66fe86545867cf9c09c7530c545ba429cdaba30c913bfd50bb4145ed83648363b43923b8e807da2c815d957ebb7098ddd3e3359bc2c88c1f0160bd0e9b241205cdd224a574d3a11d8094453359aa515d6fd6da1c8a1f5fba220db5c4184781b21554a3cdbdc4d6cc132a1bdb925cfe2d480eac6448572825c1fd12e4a3d462c57f43646721bddf41cab3c165f26df54e70ee2f06ad0b0bcf0ca9dd5dcf9732be4ab4523d3746e74376fcc8385ced6c32a63ebb94567ed5d300b02953f12ce8890ffc6da8ab19abc78aca659948e82cbf5ed06453d77904b1018d8c12a1ae98c93cabdec9a66a7d3d6e329a306572a96813fa093c8b049217d0fae0c2f546120b5e00832f669d0330efb06762a01997a2549a7c73e878873e31547c9021459cddde466c1a00415ddc75d58db4377841210b6423c30d94df088f15d2c17b85fa095eb8bf800dcf0e821219d7d93b5e4e515f8a2c4b8ebc8da401143be56e2b9035674fa1914a68c1b67bf8e4bd", "-145e11e5f30b26a0f513209ae42116a6e185498b8093d298ee8166882a2a2a875a0935cd65f807a69ab1654c75f70db43eb2778f3e4526ad72750d38bccfc879c8e894291a9d87a5ae0e838ef7a17d286fff2e65facc26607ce56905a93e1642fc58724e6bdd0450a5af09649ba7ade4542177edb0226af91cf856baf1db04f10caabc235a072648fbcea1f484c6ef2c589ccc3e63f31149ddef86db6c3e33edd6fe05fbef46dc360099b18cec690fddf8f2e7c67d3ef86e041b209d9ad5bd89c7302ec1b2ec9135a31dd126aaae6e155068e5fd2db3377f8e1cc8f46e5f6bd5ad49c92cc4093b951c05b20ec379f918a17c03e31d0f32bd607108da553d2aabbd468ea0ded3c3fcbafcd7130f7edbb8d053afc309378b176d3bbbcd7a937995ce9b233e23b54199f0cc933391e53f2f447998c7da969d1a6268c37654bc1eccdac9e99c86b8147c5305fc49f1e321ddb5edcbd4a26523795e34d8b9daf90a3ef202ad499e3e603b375393882e1832febf683ad7469b07173808a02f528b251034e200efd7aaf83a04a4145f037d71c8be247e362f25490911b6152d6fc4b82f8a8fe017e5f119fc4fa43eb1259986695eaec5b03614ecb2c47b5b386ce795611a7f877443c8c029de8f42176d02f1e60bb133ce8914bf3ccc635ed9c4132af5e6398b446f3c35a863e3628480b7342d0efdde2222d3af99f5e48805e45d88387d5037186c4cc30d0c4d743381bffc11bbffb0ba600188223455bc0b0691f87f0e2811aaaea39e23182e651bd7b003b81bf8883d560f9845aa341a4a331c8d8151c2fce0954bb50042fac56cd17dc69acef91352ea18baf0ede255c67f67883227e635a739cf1b9fd381aef4d71ec98bcc5d81f69635c7d159ef9dcca350e101bc040416ce363d7b9d9e812e4fb5f5d83fddd1fc559f769053d059ee66a647c728e896f6c8ca69700429cd1618519878c870637789c82334d6cd8ac8b702b06a74046341dd3000142fb2b9a95eeb1ef65a84a2c796f74eeb9688194ea2691b14dbb598ea16031687f4c2969a5991953437d1b166ba861d8dff0554b4085cd59564844e04bbf23df2d0255c340d1cf7bee5105099c75c69403e821f2ea2faf22110c0d2aa8682efab41df1a0abe9a1b2cdc10a09fd7dd29a2f4a4a3e3f996c64a152d60a15d710a7c9dc4a03f2ba90af7afa17188f0ec2e1b253aea86a635ba006c0f4e805d56dff89afce3134883eceaeb9126edd658404015cfd2edad282ed6b5d224f31b17ada8ef4e3f0b4e66aa933c7e1253a5a528ef0ed32c4bd9d99b30430c9d981a3c35a0e22d61a36953cd44205346d1f5ec3257352e57e2e275a0e0d1691c741d65979e30ab28acc9b9861eebea139103c9e349cdb5309014f70284f5b87a5019478c65b0b0bc38181a9d7d21c8b459f1d3d223d3bf8ee859ca48d12dffece9409820978d955f71822a4388d359ab99de65e554fe08165e245e2b29b0d4fc05ceea2f436dd19f6ad2639024f3fa5ecfa3edfb45fc394b674e12d9ddb5963aa936bce158953cbb64a491259ce0e5a559f50b4acb903a4231543678f923578ea5021e0993b1ad7cf4e84641f41c3397a976e33e8a761f11a0ce4c3539deaab32371768874b86744180526a9128a0bac4b02276f5c039d836e80e24efbf609b37575294a53b1c0fcfefb3cd0dbfe6f971e930001630154244c5230e50d45ae7424c5ab0336cb1727b2da488f1393740ab9f163aef14df5d4eee1528ea15c8c3458da62d5c2029e6ecdea0622519bd14c98f350f6dbf65a6d0518f8ef73ac2166b14ec728b8ed6c78834007abcb2379e85961355e9a91d8ea12a81822075e48d05136ea52b82e5851fac9dc85f7fcf1395ba715450e29de619ec4359ae1e37d0f10bde1d15fcc6bbf736e49fa8cc0725206d03125ffcb2b97a00b3aeef62bfaab41cf15d6d153e18eaa3b5d511f01067cf1106866bb2926542cfbd13891c74567f65497c5cb0459844f351e19b2cd4e07c0585f4519dfe01826d7492effe646ffef2873db92f041cae60efe7754fbf139dd9f04d24f3564b9e8ea6825e643028683822295d375131f54d077312fc093a392cfec47765071ddeb7", .None}, + {.Sub, "-29ff3b28035fe087bddc8f8be7ab824801df05a13e5ade5f509a38f38a55d1a111102e1f2e861fa189e10140b80513eb6b88157ef1a0077c7aa8fcf39851d0f813488a58d49a9bbc68c5556a6144d1678907fae3f54f7a66361b730fbdf75e46c0c1716140d451fe1df7859e0e6471924cbee1d9b157821fa29a8106413ee7e1c650a22afdfe3e9b9ff679489542bef6c2d1723d5a0074cd9abb3fa4103b451d828d6814af13658a9192e0b2adff1adc7249e610a8518cbb799d5d5951a4805b045213ee997e87a6e6429ef874d227db051d3f63d1b7a74b6d6227c9fb899e7d99c4ed35d5e98a703c5d62a07763339e836522f76b08ee120428c5be44adb575baeffdd8d2ee04cc660d6b29157ba7cbf4fb4a90ca753f6b31bf951133521d3035abcd841954b7e8880fe35b4268cd29a41d7ac0c30efed97f21534bdef72ff23f4586a498afa2a3ecf4226ea31882b376c38d821a688fc26905899c6f602cd80e869d29e6cc34e5eb42173f5870f831c3667b745a7d0f1ab40cfce76eb52d29595487ca0c1b00167116459d2fcbab92f16de8b1986f6bac06a150b99a16a9d94e2299092c9dd4021166e2d656842b8cd445c05582aee58392c099a0d7eb90f7d9e6e071285a339c40446696e201eb9b2c7f7d721ffea3c81d5eea7e3f25981933654a93db27fd70ed04caea38e21c9c32f749a7486c27334619b2f13212e65bf58a74787b8391cad84b30370da7b27e23db12c046f46b14cea7c40c4da86b7b545e0e10ef470534b10ac77c563cb92e54e12f04477b58a25eda28e6a6ff76982dd77fcc0b18e177e9af1ee0064edec077e4b5f2e7c0953cdf475751fd287fa352ce85d17df0dbf537a37b54c619cf3a329738c8bf1d65ed9470d153dc37f7ba7d8cf475f23f4b142fbd328b3ba60eb34a8a16ec2c7ae07e529d12fc0ae431c2fb3c01e2cda7901539ceaaa7c41ea5e4214180b7b7a2a4dbe1e8e389a77009779b5429752305016e3dda0fbe9f6c1c0c79d98c7dbceca9aff0d3232ac832a8fb1e469eb72d66177e687631282236b5dc23796c43d2a3fe4506dcd480d52e9829eff3e2fa2ec0794757cefa1ad7ef2dd9a3a93201e3435505ebfd56df5c06fbc18c697bd662ac15e32f3c59a35a93b100e6fa815871fe855a96e19f659a3adb4c42298e30cf9498930a3be7ff6fdcd95458de72277d77d86d3cf51c7ba643f30e2bea6a769201647d5169a61860388a82333601e2f43447b8e7d7a49a455858243110c9c3319dc97b333ee075609bbb73fa5ea8ca33dd287e6ecb77c5f92caf83b46b6c4edf7e37344b27323d1e3422ecf7bf4c8d19fa04944c2494b4cd9c9f817561fa9821121f64001b51109cbc087451f115a4513768ea425f243089fe9a005b433783f6ae7d1de90aae19a1e81f918bf9c1a5f8be53774f904b5786782bbcd163287362466eae1526d7aa098798e36b9474e2a90d0e73b3fe3e187e3cad45c4b095d00d5df96ccbd8799d30a008dd6a9b825afa578e190de3651b82b882fa21dfb14afb4eb96b92fb045cb5223aab0e1ff9cbb543dfe55a7b29131cbdfbcf2f119a2ed78f492c66941806d26f42832ab5048adee9f51244ed7b0ad1d9f2992b0e02d821e5eab6991c39daa77e8fe1872e343397b243e88ceb4d268628a30c4061a276ed595b8e2b854026e51ac792ae8f113804665e891e9dbc2e398ad4df28e2c6aefd585e9403e47b8344d2c1077c982f7bac19c50b87f397cdc4b228832321121bbaa7b22cfa93d5d31c2846af0ab25b54433fbf5efe943c5e93e7242d13a0dcf1e501fe55c91e5d964019221b82fe3f47e17bf8603ed9ce8fba4edc6c05888bfdba40e07844b26412560deefa26988b1cbb2d2de1ac21abe50c9a1323a3422dfd50be06bdd5843067159bc3b17074856c35c3e9f74b3c3f1e36c52748d9f00fe9b6b83a09a7853b26296e5d6afdbbf044b5c5712928b0d37187ec385d06cf770d5ca917cdbb67982148ae3ce344ad0fbe5c7baff60b4de5d930c4c76487adc790c4f64fb0d9814bb6256aacf00d7d24e9d57be86e88df485c7cd14bb4b428a9ff32da3b9d2f83e436329c3beba08ab085104d0d19b2d86f2d", "d637c6aa38378d0f9a7aeacd690eea2ed20bc496ef42e695f23841998571e1844562f94b9dee3a4f0ba33e61bbb1015d5f6716127ddc8e412659eb728248982978a6852aa5f2a540d52ddc70d640b579697492ba4cb70caad4f161e7f9cc926814091ffcd0f74675a7a7874a81436654710a51cb37f8a0bcdf56d1d14bf98149a1074789f0389abf40cac646236ea85e315aaf2f51fab69a9ff1c83b606ea41b45e1bfeae4b2b27dca2ba1d82e0f46348f924700351a40d2a8656aceca4e42cb959acdc6a46bc46eb3ef1098f939161cd33bbf84446aa2751fa644e7b58ee15c329c1c3abd56042a7ac66210d8a787b652c5bee98595ee3a6ee01d0f4a5d2e01b304e73afbcce48aa8a8d270bf5219611548f89c3f8b9791d0d0f1b95a86304ea34c52ac902c156932fbeefd665290b80a5a12bb3695f95b26da45d6c3a3acb7f195d432e9f33168294440bef21d644d46ed69b3d9f5035d619a3b043388a3442c1ef0fcf281e42f5b26bae1d06ace4df55b1dd994ba69d5814e0f0684019f6d47e0b5b6fc836c5f8a6086d4d37c92a4bd3762b79db64368887c2b061e258c3923e0cc8a9770c16bb7587cb8d460011d521b0767ed0d750884ac429f35cdb2aa0b2b99774673f2582924770fa0c0562580b934306ced538a051b6925981a21b3f492439f5d25b76bbf1f510ee7d6fdd2a27b790eb3b4686438c0c33b28847a31fde3d5ce839c134b48bea38902ebd6d4f7cdb4db6ffd43ebc0da124dcf735af086640a43f24102b2ad719aaaf45e8e7e1d2868d8eba433a1555efa889589362386d4989b22aec837c22b18fc7524fa847ff086643eeaee033446acbcf8543193ced30532d5b0667d6f554fb1b62926a89515b18e483197c32bbc4cddb246d311be07960a783d3814c2d9ce9d933cfb5d08edb8a78d98757b1f78e758f187bf00f601739e582e37413bd6ebd646184230914feeef44c3cee50f1606bc756b2f510a17cc6e225fafda99a0928b069096ea82625934164370c6d0dabe144775e1f1eab922afcf1f4cb43c5aed4fce095ceb15c3f1dce0cc08ae39d4d5a091f2be83572763b79b4fcd59a76c17d7b798e9055194f0acbc545cd6e25342acbcc1fe15dd2c3241220aa76c44a877f5a579e8c8da6f47a5513763110bf0286727dd9c010611ae2f62e7b01b098d1c9abebc9202877c29b78c25bcccc7229ffdfc265532ea745b9e7d6c8000ff7cddbb885f497bbfed2f06bf8e3cffd00ed7d361f1e1e310eff478db7beb73d702379b2885bdaec22bb65c190001ecb6aaa4de453af8da0fcad3bdc6712f580b6b86a28b711d70182713812b2d1545a8ed5fb0a87e54ba9243723d697378b82c9b00bc5f9439d197f75f9b0d92eca86d05d04e832d3e0f7a4ed1013468a5d481a0828cf79f1939838a5c4b4e74d6ab4065997555d765cb1a180195febb859ac951bbfba35353a771f9c30158de9dba35f16c4516091e46fc8ee41835691a0cc28fb05e7dd2ef3886dd4a3dfcea5623d9cd6f8169974083dd2af59ad4168afc09cb00b063cf76c3820a31432214ea02d1b087768f7994e2d819a2f6de27d3ac4593bc109641aaef7fc195df19cdb1ae5e57f536e515fdabaaec221685d695f1862cd517f111eaa96b20e12172de35a819a0acb4747f8490cc30c555885c5d38dace29068fecf62805a9ccd31787ab027e5158ca1bcb9f53378582317ab4d19f9107e20aa5faca2cfcdd0b40d66790fa04c9cd890aa744cc5ce74e0fa281b6075ac398bae1b4e68d7fb90e3b4fa928a80807de6e9d88d47552009b9bb28898f032347223f6c4e8c142f1bbb7b23a2c68ca92d7531e64f0ba317a0cea8eb00c31ba5acd1c39a1c76a1c2132e19544f015164fab39c504cad9a6b8a02dc4275689c2b9fb8827cb1a33883026c26851e3bf96e12c2610fac6a48d439cd9b4097126ae6e557a0519ec76a5dbd6985ae112587d6cbbf1469a649b7f2fb967fb15d47068caa8ac4f3e1b38d4158f3b51505d2dba08fabaa2e272e961c288c1ab4397d4ec86aa1ce22fcac7934340dce878eb8390108a81d0f6a1e354176fa70a5d79aeffe6c0bcb4eef2759e0784152edb817ee160107e", "-1003701d23b976d9758577a5950ba6c76d3eaca382d9dc4f542d27a8d0fc7b3255673276acc7459f095843fa273b61548caef2b916f7c95bda102e8661a9a69218bef0f837a8d40fd3df331db378586e0f27c8d9e420687110b0cd4f7b7c3f0aed4ca915e11cb9873c59f0ce88fa7d7e6bdc933a4e95022dc81f152d78d38692b6757e9b4ee36d95ae0c13f8eb8b16754f42c216cabfb2b683aad07df70a9e938c86f27ff93c618085bbe828adc0e611101dc2d10dd6bcd8e2202c8281bf2c32699ece1b53dea4c159a31af916e0b3df7d858fee8162249c08d086cb1b1187fd9cc610970933f8e9ab723c4b1500abb54d62ae1e0f09edc4c7308e2cd8f0ae3776df4e513cebae9570eb63d99d4cdc12d0a44432d0a00d6fd029086ca8dd84d7ed8f82030a980cd51bb0bd258a8bb5de1ae778d7bf9a4f834a5fb9922a29adcaa30db5ad782a2d40c1638632d9535e700bdb0f735f45d931fca9fc4a0a2e8d01c3aa58e26d94e19154668d22128dbc67fb8c1994def3778f0355b0bedf2b6cc96a1353d81089e6c75fb76cc7203483e37aea54b693625af148f1d7bbfb83c361272036593c40e956dc8bf5f8f2ae42caa2660c7bd6fbc5a8c176cdc400db943a1e51279e86ece25f46968dda682c241c0ad38b1a28cebf752227a53a3d73fb9cd27f78e33384db4dcac241bf920b91a6ed572c2b5fc208f977eda762c5a97608df36e4a46ff1fa5162109d3c0109389531ba8c79bb6f1af008f81d65a1d1bc66bdac21854e18807e75e7c62274a9b47ac720997dd331f8c43b439236f3c88acbbb4ac18672dc7a9afabda37dc7b73d944f7d53c5726ab8340138e040ef57cb13721a18b0453a14272a6f8cb067c42f5e2c7acea57074efdb0c02d1e318e7ecacc3b948a806a7c8328f2970128cee30a105377cf93ba1355f97215fa54fc6bf0c3f13d758125d5c75675a5967e0a36e814b2916fa6fc6673c0f0feea461cdb38c8a56bf5e34564b148d77aa249a5fcb2f6fc3be5b1d3301a76c1ade13f0fa88aed08ffc166fc856432a4d11e77f04012c7393d5e20b37006f340b1aa21672156ad471b46b1ca1046a0ff3b11f28f8816def53e22ae9f97b1dcce50998c18c8f9d76995ae1784b6bd4f73e4d199000d99c9c169c8fdc335e86ba2d1c7ccc218774d483b3c60327c48ae13c9049a2e996b56e05a9bdf099d953a0417bc79a26a4841165ec6150f6de47e50e683d3e897d3fdf32330e9b3c284b8b7e67c6da74a3a074200be3c0d19b4ef0a41181089217922bc8a5f264cdd2a6b25761ca43e67a85dc436400ca5ef668c5692b8dfa9a5405d0fe6600e452719d9f511f465761af43c07a56cd58a85981c2cb651ccfc504245e9e8753f5eca5592af64f47f0d2bd80fd59208852b1722f26aab30a6998738cb0f841df147332a228ff5e4ccdc4f9187eb7b2a096101f448de7893a5acdaec8add8e37e401ebac2de9efaa5d9445cb8cc13f79e842c713798e6829fbae72f815f178cc98f741e43ce7b0d49cec4fc37dff0aa6e5cf6544679cc6050d18f1b16e902a2b0ed758c9e82c2bb089ac3790b2072b3d25b5b71cd8ac27d41768b0ed72aa769a69f8b7a6c0a3457041b6eff044d5fa24eea7bc80a81f490ef298907a8af24f15550a907990a68bf9dafaa8279d0c9267cc75b5b8c70653692d7507bdbab438de0b1bee098b9cef14f855567432606848e0780d303394ec5d8deacd8b3479753abc828156058cbd6556cf596d4f8008602b5d29683455576e8dfddd2d3c8a6b698f92e8e807069c1acd316ff8a265a1788d978a9745fb52cfba36de0adcc5effaff93b624c9096ca5e2d8b3cd26370298e848f0eca9ff0d312e8fafb66442b9bdfe50721df6c271571ed19eddfd49face2b14e55d47983e2bef3d66dde4f8a4ac2e9e15cdb6e21d6b4447bfeded6733acc36ac1ab3055f390a02e8849e1a397c6dd10a68381a61d8f62ce869cf885ff307557beec3e243240cd97ec581c18c29ef9adcc0d23c556e093d3a73a4de97050527039e785c607f5d3079a77b7a0c065c6bdf4d3f218efd2de4dc7ed98084019a63d37b54c2f6aa4f2e78b2e613e92349a3f288e9894387fab", .None}, + {.Sub, "-1df87a3b08468a2f8298c47c7a5ff0606897ef72df233751f7b7ceefe94031a8cb02e3e5004371629d9415135c7aa8a9ad19b7bb4465edb6db3573d2c018e501520be3d0e835afb292e172f00f3c411885a0188240bc61ce487e9de687687956ea0f5a638b49eee46ef603845ee3c928c255497caeee4ef7f0c70a151505f6112cd8b71648010d0a7dcd18782aee02e1f5038cb3cdc5aff8191e8ec315377c624ac2c2b3ef1296ed58d18087dd2b98a5a0c0ee327f940a42f51496a2d6f51cd7207a34af7af922393c45158c9a183fc3547a46f5f91c5d55e35c8b092127b3859d1c2194651fe31bf358729d410eb82fc829278202f974479d4571997e43c1df1311a91bf42baccb0e4d0424b50ec3458b1d535cc99aadd586740623f9d3dadebbd8dd3f4c8c66b46f464a126711e390766ef80e22b4922ae0c891b9aa4f550c872d7bb070ade5ea1bc3e134e836cdf968edf8fbcd405a1fb1a0ea0e81cf05fe66ade4719bd804f0d766647683bcafd525c8bb87d336583e3c585f73934eaec3ed964496a4d3c23679abce4ea2cf1bb84a0f4da17276e979050cbd6438ea5ad2e53ad30b9fa68aaa3d9a568871febe82aa58bf0b738aca5ee32a1c7eb1ec1e333b4739cc87267a76b94dc27bb402a4e222f5d0b53330714751c5ad6b0abd0c2727ad929ec408a5aaf6f03d1a55852a80bbe66a06a956297983f92b1a7e77467955fc81adbd1caeb0c95d393d9f2b26c42c4a033de63379ef6a6c2368b9c11b4ae1c8129219c08d8b7d1fa23d2c0e39a9b2bc58915275d9008bc17fd64c638e61c46e78e75da918ac63bbab58892c17b006c50bbfc0e7b71ccd08c1d084d4085d902cf670649331587110ec67509415b1525a7c1401c31e3e6b313890637b4cca6b102e852fd89b8c9858d4a57867117502e7e55640295d2a3fb6de7188509fe5217118f5a84a2c9a7e0acdc1214b6046404b8c1bd9c7af5a22a21e09d6c16f8c0d375305f6b359e501a860265d0728494ab57752d68f4ec59adfaf0c2247a4096e9c769d936cef533557f976c2e05118a16b101f98759a4f820ffad55cf7be035b0627a9d25a92f16967818dff6e055b1055532615e6faa76e81e3143d0afd84695f61c1f2c3b216c21f75d90b4b23597c1359d50b7c3b4f01ada0904ff6d697585354af29ea3f53db942ad4cde1e9c2eda53ab82c2dbcd9ddd144d34fe555fc0b72791cddfb6248758af22b15883c9acb2ce74f0ed43c09f970b2d35feadb5756bd5a6b63d4fbacb22d431bed0904bd3b6b5ef7198fc3ac3779a85c0b13f3eb41801f95298412ff9b20251f5737852889b5fa7d8772c17300ced8c46c421b8ae3ef7c6a0258308201b559a8ae318406fe45a7e22d5b0ef50776d60a2466cc5a9552aaabb1567bb29f98acdcb3280c318e27bd315d07a649d5c2252ea0732d077f969ed4ccfec350042f120f676cd48a5a352d13816c9e99549a612c9878ac46b45b980d2d57f49daa39c514af8a6479b738580efdef27bf9a219af39927ee34d6eef3eef496413536648078857f0a772fd27b250f1e3d7c9c9145c91712a65e6908618231448c9c8fa4ded791a0cd51466071581135c013bf2c225b6958f16fd096937556166ef2dd1c8abcefe5cbfcc9f0ef6c408bd3e4f07d277e038ec49804f2a522d07f01283a3ae8d73a46e14d9e07b8db8599c856f18e1f4536d562d9891d9825acf1a7031c018bbc9e854a2b382692c291bbbf105cc7ba9abca1a7836c53b8f083b9ff63fde232c73ceb6ba7ccfc59df49c9196b5963595c68080a0cbe2ce4593d2d0afd08ef30a6ad1c95d1427ed0f6fc4a7aac697c5f2bbdf512ae3b1a2b88bcfbc0f39e5a2b5c0fff3f63c7e9ae826601d655f1d0f5327f48e128091724db374a7b9c981ec1711aabf1c666525ff39ff55a1501642c37d133adc9118868a8247c1da170eb1587575d8f56279ec95af16157a205ac64a0567837cc371cfae2f575d6d5801de6f3a4a0c280d579f1b330ae8640a16faef5f4fba12e158bb80b88f9d1667f9a7197bc7cd1934e081df98367de3909ea7b9d68d560daefb9f31fbad5a3c14b4647da4d0c0a22c3081245a1edd0d39cd48a94", "35dcf30cd4d31527efd05ce482d7045b3cba714604b3fecf06edd45d25382591fb517740483d617192b1672be3f1194c2b2a75a557c09d3de2ab59aeed6e87cf78bb5c702f841877f88a3c3b9b7846a51ebbe284116201edc34588fccd3507a87a84635e946a2be462650ad9e1be328d02d3c9004448dfafb975b3f7313187b1d04dfe58344059d08c137e1209489b8ff5b9a4a8dc3d6e469361eeb595eb9fbe3d983a33ad3e0411554a14a6faa8f727f17013613600851127a3b42aa0b9db84f087c42a2609604d2b0aec9d94b661fe84a029cdcb7552ce39e34db17eb572f8e4496d8b48c1f793ab53691ac8e74f9d8c2f634792be27da8223ff594119f5c702861799faf1dc338d958ed87c00cf4d5c57e0533b44335d0ca83b7be4913d07813a5b7a17823fa29a29d6906972e94056e82d0eac4e17b8d776e6159eb1d7aed8669e17bf4191df206a8e14e5de74558c0b6bf6c89f5d6761860cd9892d6a19fe9aa42567eb24ba8244b5b8a95b514086ad438929ab287bc70ca69194192af848bd2d5aa7aafdeca2c8a73722a89586f12c40b7c83f141f67ae9c0eb3c680147ae602db53d428b2607ced91f9a633ab60f4fea2cf68ebad8de2cf811010f75d55abc808b9ac41e123e26d33dc4cd4c069e56c8412392072991ea8344e718b2a6162bb1849f9ffd8ad106fce3a087f1626ef206692966e20e5e6cafaf57ea187b69e2d50b22c278cf51362c25b5c1160f2b65769ba87c7ac227ca70a23753c06d78eeb0a411c5a20db6a41b4c4b7ac175838146e4cef9a794775048e9e44acf0e857788a33d8aad430d1f9bc5081a5c632aed99588d65bb0775b1b305da2d0b25221e15c7543802e125b82e822cd74d6ddb6fae40ec4e3a397569ead94e75f7fe4bc3fefd84677e438dbd9b48fbe70e6a1e1b3dbdf8a9ae785c91ad3cabc4c2b71531499108722164e5cd62a0e5ea3b2d702b6caf7d03b538ebb2aca89ccbeebbb3836a6e0f1b020ff5487914409e8e03fc2d5d846364b5ad811c82928f53b7ad1317c4b79c77328aa9dcbae52257467ce0bea0d0da499f924fe454a7f7e67c4d9ff6a2d946168d54bb57094b188eb87245eafcc1195aa54f6f0a5833d357fa5760cfedd075416d8ba46f8d31d7ddb1acac32ff479299aefd0b4c8561383ca0c4b0a4f4fa19a8cc62cf6a07391449e9f5676c249071274824f885949586e0bec8eb9ce680f86d40e3a4b52f46021ccf29ce1b8122038dc3427712cbd906ac24fb6736feab301343201159b5fa56e5009ba9e65388bbe4b71579b3a8785f3eee4b48302d01fb4e688e69a61bb7934e9046263aa9abf89c4408390c3b36db0168f8a35caf17eb1a7c3c9ac21fdf22661ef78a6cc16ff9327a3c15245a24ee11d28b2cfa5e768b331aef81c6893aec7705a228c995766c1bf02879e7d549c246abbff6b250f96cb37cca7b6f806fc299b602527dc0547624f42a0eefcfe9d9bc78c0975b7ae48ddb3ad5135dd9ead8c0f29b98c491558360651974973b30c72d01459c97a0e161bc4248abe7b6783c9b19ed025add4b31d97b4703354cdfeec709229ce14a3c142b189cdfcc1fecb3a30384b01edd41ce61d7924a0ae0b24d02f33843f97744e48236c38abd3d87a558d897038c177b9af94ca9b7722018974cb6f56bf5ad5c2c99a939ae222549b8256b4c47c6fcb3f080801ad208cbb1ad540c2f3bc6bde98b697078e619f8b46ef9bf006aea05491969956043f7547caa422b6fd129309405223f7fc19dab545065a4356317301c7a4b3404e3421426d1ed21dc658e8bb7ef6ec6b1db56cb8f4115ceea1f4636f7c5f5fb44db42e066590b362e8269a42775fd8e5d2d7217961dfa3fd7630141a3bb80443d84dbb1b40b70d57170c71764791f1deb86e2fb7eb1d085807e2da273a603755625032dac56c5ef9dab144ba5665066d6fd37a3bec351baaa612c200ebdf391280c1ed3facef8bc6c435a2bae6024de95f47651679f8cd97845000aa4e2120e30876daabb9b7cf2524f3d52cd0dad463d2c1fe9fac6718ba64c4226b4a49a14f62636841b9d9180c3b5c0471b86d53deba4f8b70f21ed8621d794d3981ee66b00d18fd7f", "-53d56d47dd199f5772692160fd36f4bba55260b8e3d73620fea5a34d0e78573ac6545b254880d2d430457c3f406bc1f5d8442d609c268af4bde0cd81ad876cd0cac7404117b9c82a8b6baf2baab487bda45bfb06521e63bc0bc426e3549d80ff6493bdc21fb41ac8d15b0e5e40a1fbb5c529127cf3372ea7aa3cbe0c46377dc2fd26b56e7c4166db09e0968a34369e71eabd315caa031e3eac807d78ab231c20885afce79c509afeae1b952ed7d48fcd92310193b5948f541cb84acd77aef85c1101f8d9a10282866750022a2ecea1c1d91a70c3c491b0241d3fd8ba9fdd267e81658f1fade1daaf9eabdbb809f607cd54588ac995b79c221f6970f2bf5db7a61597c0b5ef1d88fe9be292fd310f9292e77533b004dee132931c419fde6517e63d1338b9640ea657097020a2d084ccd0cd57251ccf02a9e3b83f77cf49012cbb5f9419c82fef77c93c2e6f49ce15424ef4f964f295dfb7871326f6e80afc70186548889703c329ab59ab1a2f2d180115ac75ff10fce180ba036506052767d9bc365371f14c7ec0231c747585c577b13f3b3b8e593ab5fd986cbb5972ecb0dae76020d5e6f37ab35c9e17441a6ba4f22e0b4dbdae42f3b60c710cebffc1fd159090f301d540d2bc57dd302faf904f79a28cdb3d39456991b9eae4559f592e975189104db70e02a583a400ace88f8da996e2d58a6d3bec979a69dff61573f5e8010c9aaefe6f48d63dbe709bfffa8738251f005aa7a0bb419b8ce8ca72dd365751b956fd9c5adce7ac5889e3f1f0c5e5c10af46cff9f657379d3368464eaa83b52acc5f1719181c380948da514d9adbd763973e55549be12cd4463dd00e276d90fe24ed7ccd9d6b186836c6f4f73618a88301176f8108801e20287d73df862ac4a4fcc6e75081f1370d134ae5a0825825ba4c999321fb3f811c57ff945530cec1092c42d8eb8d14eb0cc67a3eb2faa03f9174e42e6d197eaadb15d48d4608e2e77c86f89acd7a50a0600fce7b7a11111298a784d2b1cc59a2072f177354b3cdf843fcdf2e90d34627bdff5c5251505c5806f76fa2ca61a3448a70e401fdc7625c8350591d766bbfbc6b51cf222b0f6f0e234b402f2277ca4fc657288977a407d29df6c609efa17c8ef7c666eac28c8fe7446d689c984a5d63ed26268e6637aa0a3a35da3fecb84cc1a088acb485f268862441bfd013340315c2d599e1ca85361e89a2c4784ed823656afd6451f75aa098d680e9f612f0d183e20e1df90f0559da70d30ca5616d62fdeb342de7b927754c6f609c42fa54e0f1d8f14e2e39107e2cff60322654938f98881ba86dad06c6e2cec19a51846fc85b3845f9c77d9f2321a6e25475b8109d845cb617ba6a057e5f676ec73f92cee3698c8c91bac7347e983482250931a09ad6197b5157061ef7c8bb0b45688c3c9654c5d60a2833c9797c37f01c3e463c9fb1cabe60a1663966fea7f5d0918c8ceeddbf5895e2b361473d2bdd14fbb7635a84afb6fa2b35d1673a370c4a12456252e11316b0ea6a59abe4930b86dfd0ab20559c122fbe00948bc15fff828f9c23bd5310cc49a9715ff16f092d67625f2873e265da1a0d65cdafd8991625f2c2e1bdd8ce3ccd0668e2920a354d62ae9a45e925f15c85e956a3b59863a29b0e3fa3b68af8bf4497f8d0390075bb1fff893489bbbd51d0b2bd5c93802628428a6c4a1d0589eaeac0051aaa39c7cda040445a83e0aaa632b47e574e61b3ed533172352586661072fe28745ca3a69664bf9c40c235bf9fc0d7c81f1c5eb232dcce1116dccaba7977a9ed526dc2a8485cd14bc23f76826a49d5fa12df2bfe473346678a9da60b7308d322385c6112340c5cb345b99d971314cd571dee3613e19c29ca1b9da99ca1eb04dbfffee7f202396517edc6d7b508cf12905c8fa1e6e353a1ada55916a63b45f1296a00cc2ec39ad627ae1240ee0be8fc34392ab00cdb18b5bdd4090b4866e51e00367c392fb529d9ddb7824bedf654c0a1e99901859c9f25d7ecfa723a9e689a1aeb370533a7f8d3859d4a5ca525c703768e3ea4db2cc4064cdb17f886c4de3df22ae78e72b15f7917342f7a00595d34b3f2ae284e0815f7f23dc3783a9ed8813", .None}, + {.Sub, "8fc53b0bf8b0092ecc99ccc0a30a132bc703ea88bf593b663efc596d2a45137d6ccd269f00f4b52343c7826143a29a893462efa42276b5c775721304ea2fdb34c4829a5cf4191a487250ef5cf4504baceaf1374f094fc3351d80ee69d226b09b977ef72cafe6f5f9297028f33aaf7f305b129ed8ad5f792475bbe74a908a03507a5f50d27b6a80392de93e665ef85b48f3a1c0bcec10031e7a9db75568c22b3312c2dad580fd15647df7725931be41a1e979834c133021d779640a28bc548789e8e4b9c87b0440eef8a5f624372e942e2483b6e137e477fff7a78c2663f4980f933d5f2cf5442a0b1f38e93fbc3e343e31b8299fd52c20020b00aa79d5388b4d55900832f99bdc0632786ab0b96013509ac81fcf7965c6c9d5dcfcc4624e8376ccb30e0c8c5bf63b092896e47e65208a355f2100112764bc9346ada2ee6f233a79336b76f18d852e5e44c170ae3b82197b8cb21b2dc161494b1f1ae281c559ae01c7dc66fdc053ea4f62cce2d0a23ef987fae22794c9489d74781aab9e0ca27a7f75910a2a0df4802afb9c964185e718879b00f31721c0241233b9d675872aed0c97517a3a83037b1e88629cdee2cc7447a660cb3f1fa574a83456821dd2d11c1f86a8603857bdd21fc66e0610196ee2b78c1c686a12b33ab8156ee6fceeca2f6f8e8bfc0a9becf0b8d4e5473f31e31d132a783d4f3223e04cecd4883b7adfa037c2ee3b1ef0e384de15f03f8cda31aac65e45d0b3fa99bc5dd5d41d818b85cf42809bf65bce1bd1b2360e906abea6a9e8fded585095a33f00610a057b29e5d9fe84d377b91ab2472fb05d660dd467d047b266b4e1dfd5c933a63d7a4a24b9c415824bbf691898c8efbe14e86d5d896658db5c00638d951aac5dff0f093289f8208ec1d5a267ad3080c90b99b6109ad72705b0325fd69190b50bad6376f0b7f1cdcae9bfcd8692167e2922be1f9030c0ecd1564419e8ff9b3596c0a7323819b29331585b1bc17839a94f5fa00c4afa7c8ce0ee816f139ee8be3680d64de791bcd3844a718605f6bae32e3a7e100f7de79a8a06c69877c6639577aa519f7b4bda04a74978731308300bdf9ebe80b658873a3b48717936fa21e37db4c0c5d58bf40ca3102ad81df3d6dd814601c7b6626f40012336535c8fd571d019c3c17231cae1757a75427700db18e43cbf4267031c0b94abab8cd3ea687a68adcfa2b8f244754327209537715874eb56eadd84b8f9efc05efcda879181ab6ef4db6437d91aaca56cc258a3018822cc89272067b55258aafb5cc0214d5f60ac602c36aa8f7fcd25c62eb969baea55a38773760c4f96d3bb8c84b67b1696e2ba96fa54bf39bf79ad85282102e4bef9346ee2f09d44bd4388bf3b3bc7afa8d2b23da7887a8fa90334eb6ea3d196f027d091b2a5b7f7098f2281fcfe620f254309b2065e27fe93fb45049988916c31c8d547b11e232759f8d4ee4a779c8a2522d35ea62c2daa63bfe7ceb3e5ac78233e2bc914c48ef1f9cc37258d9d1f95eae5eb3ec99784b5ea5eefa0045b33c8f7b97d630e0998ef9476138590eaac41c3a1da13436aa30dc3c297586c2a3b27ab68d1e33d4253538daf813cb55cbcbe96f563aace7523cac1a37f9807e4e218131803541a5a198adfe58b7636afdb71d7404fddd54fe55c90d4efcb1c294367f2109b5392e907eea598b068ea4984d3e750a2967d50e619f5696305ff53e2749862b2552bb3547dd0fb7dc15d93878180549a59e4c850335e85c710cb512b19d1889efb32e91bc938b61f0618d366af341600ad4ed5cbfb20a39ff1eff6926155323994efab5a7bbe6cdf29dda3d7cc753137be6513a321097fb63a4ccb103f7e374627e217a7f15825fa6d7cb2ec75e8c3809d5cd85e588c30b31ba696f7b2ef4e906e95344672d8069c83248ce1dd77c1e70e07d260e734822cc4cedf73d8eff33e2e3d49c5d0d96ab5d1ead4cc2cc3b9f621fe50637831d5ddbea1ef5e3eff30a107fc508c3ce83bef7c776ea068db6bb1aab181ccffc301a24757c0c981227dbc29b1bee47209afde3256667ddfbd479f4de2313127f373cbed9f238257dbb0e526a8bc3b6ddb989a0e88b790c26c4a9a8606", "b72e1f2f77bfb12b6368956384068b8f87f388450ef5407f7f06a6886e4cea3332146247d55be79cf9f10217c470fa6727176d2de0980eab63694938e98c2f305355d2e67f6de49d38541e242c01ce10d9685cf521671c912eef0dd82276ad1ed85e9ba25fb889fe8cea259c7277c188f14ab5c15b77670766c680e3ec3d0b52912ed3e9ad7c074717fcebefc7c03b51951e7d63641808eae6cedbba4934eef3f71d5091516419ac2c6955299765210102c409227c7440e177c55187afc78bcf84c3ca3567b4cc7f9af611f6c8c08dce565e387faaaf342ec4046919b2d229de442cc5ab427ce99df7f5dcd90dbf18b59943e42c00770cb057f4e332cf9e09d50f66889dd67b1cb291f5f614630b2c0dd74b19d178539c00849a0245212807341505f6f57318b389ad1ce4159f6893f3186263bcb8e3e43f25b9c15a7a126e7691fc326d803b87e6dd80f659eb271df4309f250f2dbd21e1a185c69c94c1e5b53bd895a0bea8d40ee5bf2a216173934760bd0bc678203d14ef275400655c9a4da0a0a7f0fe96041a015f131e9d5d4454600f1a5b3838761674c66414831565d8c7c208ef8c018f4344d3bfd09f735f794007a53dab3c95434013b404bc7dcb370e4ff55a6f403542f6aa2e0bbef8a59b94a6cfc9997fcab487cfd0c89e67ef1843f02a2fc73ce025246693a9f01fd71ba307b943e7aa75ddd77f5a63d7e266d96d91fd5491f80cfa4d14fa9381225ff53df1014c33ea78bec64642d3d772b07bf448aa1871c571ea176ba4adba250f969c78ec2730c021c3fa469f026c4858a24fd5f46cb8b765c2aa71e2d15116758dbebf48dd7a52ac6258a25c3a9a06354b642f120b1282f87713f053a352e37cc9053d1f1eecd1143b35c2df843212669c8baf83a93f9d115e26914dedc60ce26cc468a964d37f7185cac97b3468b550fd52bc005485a1670db0af4b95d9687d0cf1f099ee0da3b4061d1abe9b1770a89892327e3c3d590bb2bfb0e46a89483530de09d6c2ac804cffa70fab3a7034ca73d02fdf6a8ef25701995dc30ab3745ec8a158959926493f5ec772e0bd4e47d58f9524a92e19acf69bf3a3760f9f224760ca4f375aae67565565a54ab7b59ee5a655ba34ada04b5193ae5407bf1a252592c048b03d6d70362bf0325f10da78184f6712e4b8ca7eddc7ea58550eddfb64a3a134802d8a5dbc5d9f231cbfd32e32274048f2e7d67d4b58b0c359875c06eee346c75ccafa16f163d75cb3068089f5739345fff9a07f81a08ab20bccbbb602f44cbce5cff49c633e89b4f5f10b862fa4a7bc072a0d7fdb6f77f3801ed7342139a410028e98afea258178f47899380fa32908ebcd1cfd0658151a8f16a1601be65dbeeae47caf4382bcc6460f272ba3d4755b68cefaca3197e6331bda5dd310776c144a0f3b151e145ae7bedfc5fda88f37b2abd451ae5d9046718a306fadeab88a696284beaff5f5e527756e000478189a3fcb709145285dfa013b64aca46ffc6dec4f354a0f2cfe0bdc6b8e749958d807abf249a4e7d2fb29512f62aaf4bf050344a6f0c0fb0558b7a5f929f4fe034b88b8492736fddd9e0ad3e62c183570d06d5ac9b7d416f46a72404daa7bbe8e060758752b23e83a42bf09979dea00b6cab410eb0f6364a915b813f7bf3638578dd6442d319898e46dc2287de1fb2d4eb32cf3b6a7be2ca88cffc323fa34ba76372f4bb270dd1989a42e911c63aede4a579d61159b59d50f00526d7b9325163b7284aff10cf6cd457959ce71ed6d4b0af98e1d81bc5d0c313fad5337b40b2f5bb4eb2d29bb92e30ca3b23038b12cd3631ad02a240e50830a6c67ea76d3680cc9bea79cdff71e67fb2748d9da5acb2af85ddace7ca91079388252afbe365d4474080db35f6c97dbbdbca2c0489f28b79e788c8ff46062aac62cd9d14a123c2efe6d9d3d2ff43ad76cd912452e0d502e503d0e023aaedcee27528b9150e4090f680539d70d27c3b5a5a9e6558f8b823f979da3f365ccdb048416c025c9c7a041b6ddd44e29badddee26dd760af9672ceab0692076b85d5e35e499e5aebc1f21b8acf777c6c721a93ad1a487f4283941f7f8140ce862bb73c27a5df3e5fe3", "-2768e4237f0fa7fc96cec8a2e0fc7863c0ef9dbc4f9c0519400a4d1b4407d6b5c5473ba8d4673279b6297fb680ce5fddf2b47d89be2158e3edf73633ff5c53fb8ed338898b54ca54c6032ec737b18263ee7725a61817595c116e1f6e504ffc8340dfa475afd194056379fca937c84258963816e8ae17ede2f10a99995bb3080216cf83173211870dea13ad8968c7e008a17cbca6780805cc6c312464e072c3c0e45a75bbd0670447ae71e2d065a6df5f194a85d669441f09fe61475ef37304459bdf106cecb08b90a2501bd29191f9a031da819e72cabc2ecc5cdcf34edd91ceb0ef667e4d38bf92d8bcf3995180e477678bba8c2b4aecae4cf438b8fa657e87b9d6806adcdf40ac5f7d8b63a9ab18bd3c82fa01feedd536aebd0580bed983bd4852e8e8e6bcbd4ea3f44d3121037368e30342bca7bc7f82927313b78ba34b3c18c8c6f68eae02b87f3c34e93ceb9bdab51272f3fffbc0985666abba12fc8c073a10b939c0e88024965c5d3e90d1544dd8c2299ee356f4777aaf3954c74ff7d3212b16e6d4880f99d66376885bd75d3bd87419682116b5f26292aa3e0d8e3aebbb2ab775517e8bc8264b5d33c0909304f86144726c1cefce97df5d829eaafa1aeec94cfa36e87770d6e3c005aedf36b8dd1ab3612f6d1779cfba61e1a17924e8d4619e33bca0f3346b91ae62b0edf3fe8fdd4106987851fd8a9285db9c67873935cf0f19730729756eff0a53f4482e4a7792bb7b7fefdf0268706eb655e72aacb1c80e2215f756186535961d4f6668ecb37afecee02a7e84f9e594fcf11e72c8515120f4ff9cb37b7ac1856b43420dbd770ce2289872d69924fc1ec04fe17b874eacc64ba96a5fae24323ebae585f362ac61c31e89437f208964e07528dfdca46b20c1d39d35642da5c842540ffc47959d62f93273a8dff515bdcdd0f1c4990b84f11694b81ad4f7328628d7b9d84c4c051f43a9f3bab46ae783fdf3e5388ee5ff0125e121979379166184ca7cfd3ab45128e8413d6cae16e8d92a64224d38b6fcab94f908ec6046b62f888ca364e0e106ce8ed28dd178fb31fb366baecc89b5907d5fb5a699ee6be7c3d7511e6beed99013eee935305c33822795f6efc959b249172482c82d5dbcd0d2c1bd526ec32380478d071a13a6567e62454d1905e684859d6a438807dcecd174184f9b946187959fd481fd89d1f524ba6ef030753fe2cb05cbc74145da003bd8029c7e8235e95706fdce1f8f5fe22bedbe2b1c521c58e6a0933747dc801867e582a59b4e4da1f411ea73347b15df290895c4d4dba024da9640fb54162085224ff8ab6127d1a2d0547609e234d38e9ebe5d7e4478d5e3af5b66a4fbfa21991be62033b0c2d7291a362ba940e793d9ea1408679eb1142b72267d6056f89aa7be628a27b81b196ddcf1c8123cb30eef17de0cd967d5a9fb3c6da73ac91cf15e7d9c427f518ac35e9194743a47136bd0c25416c7d3d6cdb4da57fcbcab98b03abbd5724fe8157e02a1b529a7acef971325f12cc4dd14a2eda8bc524549b40a036fd3cc54a15bcf708d31215fd64ec39515cbe5e68a5af587c620f0bb0cc2b5f2a20202eed5e21d42bdd98d02775a35d37cdca2dc069ac34463d8dd233f06222fa70643838fe72beace8574d8b389373e77c419e9e652fafd015462156f557c7bb18d2a4f1225600d94434dbd74a7d4a5af208d7ce3d45c41c5e8ac718937150bcbdec737fb89cc86a1e3543dc64d8d7ffdd321ae5cc60813fee8e041a5a22ba7d12f76ba842f41c0d7fe7ba389a5820b97528a6535636094478d37cb9c50ab4e7ff6a3c18178e75c634afa30acab3df736b2b86e5469a8b527e6a5aa5357bba91193b278b3830705b4d40f2c5d8cc2998f2f20d984e61b7bdd0043c600e40acd542fda09f4712ba085f3713bd5c8e8b517ea3c0a69ce17391b106b255b6393e91f06ffd006687f63a34c68c40821fa8ed19b2ee5b8abefd363f94e85d45766aab5b4878f31b35ab56803e9556c641b3b54741f161e74b71ad2abe2631d15614b59a485e4b3ea38fce229392f6f657e8c56bb9ddfc0ea62dc03b07ed2f711553e979a1bdad7e411a5a83477a2ffab653994a3d9dd", .None}, + {.Sub, "6586814dfde6aa2aae71c04d1ace9763ac989ac300a411ad78a5f0f87cf878bbd8f6e4a1eac4c2c6c732c9ac6ded957c3848b55651d098c83b24401171c4dd900336c43a43366ed52080bdc9640aa1f571294b09e016aee3fee31d50df94613b8248d7bd6649b5229530e5666a9fc48d70477cb37524f3482c91b5879babeea4018e2a27508f8eb149c5bb82ce342658b5f7e0743e8da32a032a6fee3de31929f69a207f171eedab96ea6f143006720ce4caa8485f5409d9b8a19c5b3e51621aafb03e9c657d7b293a7ddf3c4cc51e65e63ac7f140a2e25cd757b7f0a1a562754fc1068b1280920120814d82278f7aea571e244135935320f067122789872fd9762554ecbee2967d0229bab727c53b5de53926c797938f1cc8131d6fdc9af16229ecf7e393f92c35aefa25c35e08a3c54495efe50c1ef45c80026ccefe84bdfc371ce5f0855465cdc8c117b298139ea0ee896c3e22e3401aa12e7ef8d714c3160abdc7c90fd30b4165a986ffe46634c0672a6a31829f609d4412c5211515837c4ee40491354ad7ac260ddfaf1edf8e92fcad2bf443936760966c533510f41f63cf0c93f39bf85841b799d65dcffa8d06a4902e1cd24032139d23ac773d937194f589e76bf0640ddbdd5d49e4e2ccaf6fa2c15f15460a7d6b873584b3b937dc433befee548155f4f9fbd239c7b59b2cd8245f257f83298bbef26c9bcf1e42c191f8ed0b0c45cc83a6a80b37522ce90be33370501c1754bb752d635cfccb2eaca308e99e511e15b7822ca8330479a964411a333b13b6f81e48773da78b86bbc415e56bb2eb6b0da6c8a19a90f8fdbd8782b960ef7b983af68c5420fcaca96619cb2ae211458b0fb0404477cbf352cead64a34c7ea1ae6b06122f5a9ebd7ddcc30e5d518032e6be0e5ca6ba89d764781310d04b5bc4f0a8493bb2f18c2635d3e2777e19c414f2b02270f4e672de0f15858a81d295a4426ea6e70f0d4cb1cf6d2f461199d0dc7b690f34d5d4a3492a4202e7b239af62f2acb76c9218f729f1518c8f75e2e90e2bfd7f38f47e97292283d319297bc61f9e1fb73370cfed79db4b7b3320a3f261c35c3bd67992f7e0d60b41ab66c49dabf33dd6a82e21abc30a01c5741066eea3ece3b4d877761b7211e9dba3d070b6bca9e5531a2098577dc400dc0608e8fe8a6d97979d285022e8b003cb9f40ed2f653800a80fb8523eb2f98ad4770b94e6785d664095ebc3e91f7911347656af45aca2ce8619c348edc99011c754f21c6c125a4c0d2800fc0f01006b9df0b8ef65a41c18574cef122ebff2a16e0c04fe78bef8034cf9c7609bee2889bd0f78b9b945fa8c6bb7d059cb8e466df3ffab26d6b34113737a919c6a551a3ada35d76135b63d293da55da481256c4e7b7a20267001da73b60a87ebea9129f6f7640b441f70cf16abc7bcedfb43472157b66bbe8fbe40bab8f731e6cb1eaf7e03a12ad1c5e291934dc754d9d6afb9d04d53282702f9ed5f984d5d00b045d5c5789c7f1805dd0a227d7a29f59d9f23371a5b2aab822aef02a0557a19065c65ee01ca30f29f5397ce70fc119357450bb858ad7a1d76fe91af51444c86d7b8ab1a66719060d3a19d5f8504ceae9a8175d96400c3d43259d8053c8ccbabc8d695e48d8e15c3a82f16b2e63df7c759128aeb286fe076ba71e49018717916bb38d1bc18880f63deab07ca6a0b7a9a58f65c27545e2082f679d85f31b69b642e19e307f468cda608f962a23bbc34444883f45cdf490a5a6bb91dba3fdad95bc5c2421b900ca0075bfd36a64e99be473b9f405b49ce47a71ffb708c86c57ca63ea323023edb962da2a14760ba8ba65dc5b5436f2b9f16cef269268b4f788b2c809563cfc92982405e4f7d627f41da2a83b44e638ba9262fe590e5e4feedfac2cd27afaa2fc599e911ac2bd98f019717eebe08bcb659810d7f61fedd9658456265f43dcdd1f17a456ee24e4cacff8301ac306abbba050b7533ec9e2f482352d13aea6ee19f180791b696c6a17285b64dba04662e23cf923f48b50e60fdd36eb11ed3c31bc8831483b883726233395e056d821d4a7130694163eff7f2f2446cb0da033a3c9f58920c49548ef6c98202774164", "44c50d979904d88917f80a51d8c64aa77764750c8446cecfe215b36c6e61c573edc92799dfbfa17acc467d1cc39d74e6b065ab731cef9277476893500abe9be1206cd8f5b76e5ad55aea58d731ad0e297b3968edfc38de1cc913144f3c193f0cea4dee4de1dab571ae5a66ba5eeac0be79a5de2dcb1aa12fae004e9529e6af64c56dc35246006a2503f34e5aa9a330d9b1876a9602601d19469e62d983399bdf88ba2b9fedb59ee10cffb593a9f5d9859f25b83bd91a5f1928596764c27a5eb4eccf99b22dbb282dfd18008f410a1e6755747a5bd18a3c7eb327e9d1e0d3fa040a0e6f9feea5b90287ebea2b5e7c3c7fb65bfd945dbcc1aee842576342a3ee0824ab074258e7f5dd3280737c4e8f35a00cbbed1b4c64a65500cc00775714cf33a2b187b85e3bf572ddbfa29a822c80443677b45e872db88b5e2cc5ca69e9ab25599c1a916b6663ccb348963fbf278394884b1452787b1376039f3cd33d1b55b17c39cfeffa613bb3b0a2e7487732cfd01020ab441e52fac23703de988c9b6b28a72a2c75ae1cf620d6e9d57395799321e5f560eff7aabcf455c1ba0e0f0ca6c7cd5ba8b5737d4c1f675ec679704993a84e037b0c7f48e51db55ef2eca8a67a0f5faa4f0c8a1b9b21b70037d70ffdce5b277d96b0aa4302adf09016d7804b0f822b5a4e32f46ddabe928d7ce2830452a82652bd9c43ebf492b7256abfffffe0a4e477cf9ff6dc5ff91766d338ba9ed719ec0626bc5fb62a1af62039315326aa6cc3e6d809a91c341504675085a3703d05d9e1b6a9dd8a9bb85ff8a0b9bb3b3101d945f3ded272632999c5bca942218eb369159996adad2d659aaf73fdfb3121153705a797698174dd1b0d7cf641bdc637f3f11d4ba671eae723fdce210e760a0705162d4c8b11db1de1596aa1188bec6081fe74b36c7a3676587172e873e725ecb891d26675f58536de3656b6fffb1a9c3ce206e22d879c174d1f14fd4b9a73b9c2664a911d94032fa1529931628b5ec9ded9c4afb6df5482484601ffecc5522bf29693b38c2e051d2c6b7e4abe5e06d393f69da4bfade522bb297bb7122374ea093147c913a107eb75df2f689ac5afa84b46b0eb8d698bf1b63a3163803fb9062ef8f7e967c4131351dc2a3f66646822d85cf4f17683a041560783da3d26a9aefe7a68dcd2060018f77d52a2e02f0b6bdba9e2fd674b2c977b0a017a8a375cd348f8af2653ec5c4dd96e1582073debcac4dede8ab9efa5b05694adde3a099a0239ab53d570e75291558e020a058180a906997e6fdb683cd3b7f6aa733c03ef0d1b640e9abaf7ac59f8d7812428c8eedb70ffde6e0bcae1e6f87a54f39edb84b8a94e06407aec3afe3b0213abdc872be8cb7ef8a234f3d88114054c216c7495ed7f45ecab3b2349194b2611f3078ed80560475d97734d31c8742c64e975fc4dcdec65ecc2bab270b6f2399e2fae66bdccbf26c155dd0452e66eb164e44d9ba62daf1ba6e2910a2f2aa11e95f3f2471804eeee1632dc96ca746bfb796b0a7d50b433ce4dfba63b6a40f2f9ceff42112e5e900e2d9b922d4fb27d099e04fd486c9fac2dac190dde665727d0c2091b4876548f7d12bb45703e0d95a067f95b0f6427ed31f7309674c0e11dda7f04d8613baa0ead7f550508e15f0d2291a82a237deae8c35b40c1de313a7f66747f8f5858da83a937724c27b0de9c69988bd987d4c90add24b16af72660e6cfdfc8fc4befbb06050aee766d0780516995a79f0cbf40c6c0da9c9c1e3e8f0d2db42809476e02b4bd159e1cbe511986cd750fe098ab8c6c09637a52a0964077c85157a208b9109b16c6cd8ce5e2a3131ba136db4dd4a4997a126cf587d54b0c8cf09fb900d5e8a1ea410cec1bbe891df2621c61f58e229d3e94efc1896302df5e0389a69d34aeedfaff81ab9a94667611c3e2e285c9425816da123c31d81be8a5a9adeb245af381480f2c307beeccbd8b19d2a2399dc56adb3f350d0c1842d7055dde4c550c0b29e5b6516cf171fcbda6fbf652ad74efedbcc39f79243520400e5e469127c7a26425d649e73424612e516d8a4bc98423c4fd6239dd5a14cf2e92c2c56c27dd300f859e6eca866a1d4d5e0562", "20c173b664e1d1a19679b5fb42084cbc353425b67c5d42dd96903d8c0e96b347eb2dbd080b05214bfaec4c8faa50209587e309e334e10650f3bbacc1670641aee2c9eb448bc813ffc59664f2325d93cbf5efe21be3ddd0c735d00901a37b222e97fae96f846effb0e6d67eac0bb503cef6a19e85aa0a52187e9166f271c53f3f3c2066d50a8f248c45d26d282490f57f047075de3c2d8610bc8c0d14baa97d4a6ddff4df29694eca89eab9808610988745a4f00c8639aac0904834f67bd70365c2e0a4ea37c252fb3d65dead0bbafffe90c64d956f18a5de242fce1ec0d1687145b296eb23dad8fe98956356c9133e6aa0c226acd7d691720824bac446e341d1517a4daa65faa09fcfa9473ad93605bdd87d39ac4b2ee8c7c7471cf88586222e873b702b35bd36c2d13a8328dbdc23810e1e3b8684f13bd121d5a704949b12d6dd80cb5f19ee020115788172d8ec1b0c663e57ebaa682ca49d8f422599f96d648e83f7d91571cf8db5069fb76d3364f05709beed644c65db0d0ee688887a1853a7b9d81b872de18b4f240a3b8965fb7116b7cb044be8aa6c40aa992701e7789c01b0eb3e287b0c22503b0fe45fb0f95e568cb31052f74cf5e7c4b98a94ecf78595df985f664872ba265d120dd2cee1147b43c8649bc77abd96a56ddc38ecccc11095a0218ce81a3b6944bce53296da2ffe0c67e33f3d972c3b47310f1e42e0ed14753b6c4ef023ad90a46419724a34c9476a295fb79e915a374323cb780802364502c64774f9836d2840e27ed639273b40518469d96d8290174506d1cb8093140c25bf0c989b439f07d4d44fbb9bf8cf504b55e4ea8dc926b97188aeae34f8b5f3dc69ae218e3b63296a4efd1110e72caf5b615607f91b2b0b5cd09c6f66b907583b52e65bac333ec5611f364bec26b04e4ce711842e12c55a80193dc1ecbc8ac587f1ae7cba9d3a16b01c270f1a6aee44f08ec214e70acfc1ee37b483d2bb8c4f33864b5dd50c0534820a17c7b6a41dd35feab33bcd62ea49d2f52a048c3a63834c555a9fcf7a1bc81318de6425cc459585287ade71d210b5a671c2c92806491772aa98afbb33eb03b3c8783b4592031b7decc065d44ab677e77a5f89c20c6de16df6ba851fa1c52599f132ab857380f813c1cb3361b2d8ca90d3a386da32570a6e95ad9b91978430d2d045cfd4c03365434c67d0b57b783d483d386f5377a3c29c37520979e4481255d39d71d348ab91d06721e8dee0696cb43feb56082d52b871183ce964ba96ab6e0cf6faea1d47b255e73440b01a79371b844cb69d7efee99a6a243d0ba09fce891ac9ffc0ce3407b9dad7eec189d0d7df769aa7926f4701d8d072c627387c569a56a93db3ae4d0be23d1408356524499f3503ffd9e58ca0e083569f506cf13cc5d89e22681f5eaafcc1d95bc979ff48c19659d12509e87f58a2fb860848403fad2cef011745d46bab048cb48efae0e62871cb6c34a725790b5c175c556922bbe21a51e37e60979029efaa2d8bb305bdfa243418b9c9a6f6dd342f48c73614871f375d23dcd36ba0e471b805a121499489b9400e6fec0dcdefcae583d0eaed24b615af8fd1f01d00e3c0e657ef46f7390e32881ac9ffd8d6a23b2941907babadd149d1bd8351e4071628da11aa04deeaa4c76a60c7aa84f7b35f3122b1e736f9b046b94263bfad8bbaa738bba2b92cde30c06a829f7f9515a5d1c86d680b55b4944e50e6bc04adc7a0fe0aec35343be2dab2dc555020084399911c819c014bcc2e119a38d42209eb4a465f19e7fd803779c68f5fc29e41db9dbc811debf08504dded4b80f985cafb16dbd3ba7ad7e89342247e682156fa7d54dffc31037a2d7e9f8ff5aacef340e0561d429146c0b8bc382197ec6dfd8688f150a1245b9beb1b64c99e090cfb16abee122a803efa9b21062adb2636ed1728f6a54fc2abbe3c5cbcbc4652a976fdf8fd5fb61dd0be32c576925dc8821c3fa099f4b791232fe07bcbdd0c228c930cddac004559b00088f8a6be0e1380aedfa4828515953cc8b32ea2c08d31f400e0b05de2398b2e0ed82fb3fff7d180ed0ca44401b61a98dd753e1e173dce14c2288286aae5c4705f64b5193c02", .None}, + {.Sub, "-a72a6fb89e33a0b206aa4aa0769964b80a7235975257a5263b6e842673c3d5b3afc4e7893ed47ce41714f3b3bcd6ed0f2ec7b7c2b5965d332fc3131a8d4957b10b3506242e85949e52e1d230b6f3e683bc101ee21b56234cec1e12113bf8e3d528d5a16e97932fa75b1ae8571655c160dc62ae4837ea926f7ccecd18ea2a25e6e565a0a281c7bebbe1da399b28a8da32ac1c12c1113bada3507d45313ea911127ff5ee413f9783a38925d488f3f95de8b0819e60c31a153f91547ba5ee63093f65d46727d2018934282a520b2072723aff4b56c9416db7fb11572c699f023853b743396c2c86f3a4f9376faf523a0c1b22ad9bfa679a23aa9bfb7015f3ad776f243f02b3ff5e627cc4989c8e03c696892f73342665d3de7481e38e2dfe04ef40e09877ae4a32eae1213e8023f37f3014c9aeaef1db54786c6cc558c8564b485733e8c1802ec41a6d267a1056a883e84b475bf405da808a7e170a44f825f823d5141cceb4d9f89337331854a79ef54a8a93d8ced3cffcaa57516d9a8770474d00037e0425598c18c3c16bcbcb17814fef7ad80159993c5cf7609b5d4bbd3a93dd04bd4a5d575b2b0c554ff62c68781b0a4a1be0919d27a2475d0236739577f3f26a7826b42d605ef107ef2ed63db164c0f16fe5f4ef9d327865177ee61613b53c14cdc32be4162bad9a9f8718338a9765f25afd393580d43bb94af6351ebef53c0d6cd69f05352ff2f587bee71680bbc9d9f8a3e49d20a80ad954bec4d1ecf570b85fe35b0002c255dd93bb1bd787835f2db2dfbab829f1d3104a5dc6e6c5a41e87bd71baa9189819be01a05e4b5a78891b9a237fe4fab57ba3c86d148c9eb0696eb5ecef12bb4dfbce3172321fb6cd6618fb4de4dfe879edb7883a58d9ae22fc315bcf793fa841c969df10d492f51d77066b0605bd6aa58884a60deba21a34db933612eb5e6455357e0485cda72b4274ac26317b3b1de6f6762db92713c211c514cac0cf3450f583573f88558a7b5f2a0a74d1bb65dc3a23d8f6de2653a5b78e0f01f50870847c817feaf0cedeaff2ede705a2cb9f3be9bcce1b48af5cbd32c65892382212b6dcbe68bf0986401631a6c8c42a0c8a2698231f05b3ab68945cf54c1673c0ed33b2c95e06337cf5062ac9650bc0a8ab29480a063fd1c2b997786c6b80c0657627cbab36ef7264206049fea30c57a455353df8983aa8ae6bf792051bc03e298e1bfaae55d38fad92f0a6f16a428bb907253cf296332b156b4cf6812ef9a82d14f5e6ca3b1783aba391c0a7bd72d816b58791c337ce39f0e7761ba5979d571785018cb92bb787dfc05ef8b64e250abc240c01b15dca0c586449db0be18a1a7a2a306975729452abf2974760a634ec6908714c691ae3fe5d30097fa7878b52ffb6f30e420c27cfe1ebab1064167bba101d71fce3eb093757ad1419f8ca53cdcdcad639423ac780fed86f020f72bd056c7032b238035fe871b9d10e719f1b9ad07b44f95e764d26236f44bf56abaf88dad8b53a1b78ca5f9d8750ac840123a64eb062f3efcaf5a423c41dac64f863ba5d325425725fbde4d3d0fc21a2cd1aae630081ac373a388a95eb9f22464c36ac4289ebf8b6e3b9ef86758fbb6f0fc3c5cbc904182ece8330d30164922df60d5cbe3f2dcea75cbff76f93814cba993ca41e5a699e542d4f5ccc5d1bacd296bfa8b76de13f2919a025b1d4695080ca6f0c265cfbd08a17cd2387192307c9c42ae3063dd43f61b8572de973d9ecf1edaaee8fd2c6f68cf30ea9917c932a789668644a6dccb2a25d00a091e1843c809843154e9932d7d06ca369c3d7649112a36865b15589b5f12e553c11d31617b7ebdf0a70e86aba9e05dcdff58a4e16cd7649240073db92495cbd87f4197e3e4754ff4625c4c7402b0b71bbfc103799051fb0123d586f54c2c7354c031b2c76519f224cbea3be289a74f1ce4281b2ec15d9ae1989a70108ba5b6191af2e7ad0247f969cf01fa6ded0ad84ffa811c63fc1b182af09dec5148b7e37a3460f88182c4a6b9f60f8efd982ed1109d081bb989fc3d51f7d78e2345f8ca50c6a41960c5304ef9e2ef3cc094744fda89b6640b8ea3ca4b24da88097391b9e133c", "1f2b82acecf47b0470a31660f23769416e14875d58ff2159c3e753643f4ea9eacf47ca4ec4ca7fd44fe9543c5cab55e67612b03fda089dbccb5fda036d0cac14d5328ed7467497ae5889c51ddccd15819e6460ad6806e3c75fef1fdbf060df66668fc0a2bb8e720aeca502a5f9fbb5ae47812055fe907277f6308b1018ba50ac1d42d87a3fd57a5553e08b399b95cfe39f4350652b4d93fe33b359411daf685d318cf0967f10a51fefb0b6da707536be26d19d05acec5774e5260547febcbac6cd1c5d0a5ebae61cd5b49c3953129d2547997f60cdb21da153005c488fd135a3118a95819c1dbeaed025e956c6855083d1596edd16b22416b853e55de21d223829baf7d3fe710c0fc0d5f396ad20c34ca15ef9440c3d06084b0fc04707266855b94251fc94e8c1ed5ca172bbfbed8c1b8c603a4fd3643f79cd0b61e9e230aedc6348b381f9bc6df8887b703bd3a3498390347b12abebf969cb1362cf9b75fc7acc70cbb8c9d3795a87b5dc2e4d4c242b899236202dd349a530988930033ed59ccd8da9e88dcee4e17740dfbf40a007f8a4c013bf00a2724facdf378f3c4b56715ec6b002465d89327f0eb9214257929305202a67e8187bd25e1af5b1006600626275da519d73f823cfe6dd6b83b17868a38472ea021da22eea5ac944a77138bc85654cd0eefd94f258bfef329838d4ae56b5ed400d55f56cdf1202ab30922d5b68207681038ae671c366355022ea268dc27d50d758e267d5987b5f95efdba9e8e120652f26d93461aeb7b41538074fa9686b0a8e6f6a6f8a1988420a9863767fa3debf87822976955430c5edd9f1a98ef68af965771aeffae93acb362ecf73f4c993f3dfb5afbe7f20b1c72ad9a898d6d77dedd10d3e5dddbd88eff275429a4b16feac00f7475cd3ee8d94c364eb254010c17954d6c18f86deaeea9ca1475c85b7bf0895acaedf5e76399bfbdd2b4625c34679ae6cc6d9b47389287362a9a81f16166f3736b74d318f96ec6d66c1b115af711b319371fc55d290af56b4af2d03933b0ad153c203c62e6ea54008778a947ef477351ce5d7f3a033c5e3fc127276cb056e76fe4d1de2645d277c1638f50df753f509970f525191d423d34974853d408a3f7cfb867d42b78a4fdd82324ee36d1ee85bd37b509580f56718809b8317714b27ab20646834bad9f8e4613c5b335d778523e1986ae31941334a718bb712d8a5097e70e8ef60a382d83001aecac2033c649ca0cdb7eafbc39a3d9be75b3f3e6c7d88810c32f8f5430391640ec2dc010de2f4b727c08f7762da654f1be2d85ad7894db11860040d37592e27c74fccc3fb20c92329ce672c0729bde2f9b36953a7156621a51dca2bfee885fd9f4d6da3f727759fe9930a50191d82154b9b5900c9a4537b53e908d428bf169a41fa361a786a4371ea130fdfcc1c2e903dca522776fd29fa088461408efcbdadb4a351c85f5ef1e7d5cf411cc48e347093c27df4c1a787c623232a47ce2c18da62f66cdd56559aee6e8364881c61f373df7dd5012a3b66d35a218150fa97e2c16097471380833c8aed0dde74a7fe7ca94b2b64cb00b7967edbd2c43d2f4f2b02c5a4077af9c3017e31f975c591b29f3b416a3646f6009bf167a0a1f7974e0259cf56ed6416aafc942b73877a9eb9869c097540fe52abac977be7123e5df2626fc2d4e1113904de7eb0cf8e5f9ed2124b618a370e8b745ab0d80500f07f8d8785bf1c8efba4b9c6f163c9bf4002119d2517a8054e5dd8947791d6326ad998b425f21710e8fadee34b09cd30a6af5e25cbaa5161c3a9d4573f3c519b7d8bbac0300173f10ea4ba59cb77c8e3befc323a0bb59eac302173a615a9e03f232e42b1119bb49cc576ddf8878aa8973a1f30e6a827b317e7e5723bfe59d595497bc8f2c9feda7ff52bf881c1c0350c21cc4954bc481800d7eef899488abb680e292316a3cd67cd20b411687809e142ea40135c0d651ec28af20adab4d5c608f225282fcc753d46481bfe652f4ab50d6f22b0faff21468f64db26d7a2d32526bb3bd1a7c9641b5ffadd4c15d209d39b66280bd08ab3bfa5d2b84207d44e6999ff3f3b5d0b45d7101f43feb222d54f426751702b", "-c655f2658b281bb6774d610168d0cdf97886bcf4ab56c67fff55d78ab3127f9e7f0cb1d8039efcb866fe47f0198242f5a4da68028f9efaeffb22ed1dfa5603c5e06794fb74fa2c4cab6b974e93c0fc055a747f8f835d07144c0d31ed2c59c33b8f6562115321a1b247bfeafd1051770f23e3ce9e367b04e772ff582902e4769302a8791cc19d391135bac4d4c43eaa164b5f63263c8941a184309e725c58796fb182ded7bea828c378d68b63646e94a6d7533b6670066cb4767a80eded1fc40632f0c43230bc6f50fddeee4473850f6046e4d62a0f1fd59c645788b22ed36df6c8cdceedc8a4b253c95d590618bf5c9ef4070ad77e4c47c1544f5573d5ca99a74df9fa87fdcf6e8c856e9024b0e759d5d0d22d6a7210e47cccf34e75052b579699dac9aadf1bacce7ddff2dfef6cbc30560ee941aeb8b7e639d0bab2387bf7339731750228808865aef580927c2731ced7906f18866c83e7e21da7c7c16e204fe08d9a6da3cc0c91bace30d5ec416eb61d6b04f3fdcff3fc820623b77386229cd10bae0de75afda538acab8a582157e81f98151899decf470d7a94daf985ea4e6383fa5f9db8b43ed45eaf4daacfad9d4f3c0af985401e19bb1d2c2495ddf454ccee0105cad45714d7d60c41c162dd2994f458def1bad4a74f72482abd84edf89a330ffcd313c09ff35f764acbc36c144910ea7942d6c9a8985cf8e04f512297758d4d2008c01664b8edf437396ae2579c75f4bbf6030fe071d01e5ac1c89f599980488a26dbf6b78c4b6f310f8ed308961dea492794615d29d29fd17f291a9e2b9c31422b420eaf1232664c254c221812251ce55c15a5768d03384abb6e245e3849e0cec86b0c7aeee3395cf95f663cf0793bb5ed26d7cb75112a4b4ef0bd47485a7b7a36ef9e9d586ca597f7e042b7172c7f5a942c350f6354f888436191614af51b810b133493f43e21c98456889a6f6cab29a7e4c0aae9b6e19a766bb9e42ae130066b0842b4e6d674c2f13d103fb9e5ececf94e3679ab878d7d0854e491a23cffd9c4468047ae59960ee7277d8265fa1a00bc21c1b06e4f0e9358cfa53d2397a6991103faa0cd1c3102564f26b4c0181f162135ea74b0d9d77eb208e2328ca0b33de8ba300c1590835a773879acd22aa9047ea4989f873538db3a32fb83dccbe810968c33dff1c96b48819ca5320083dcc836cda8dbb17bdbf8dd834917f46547a7ff04ea0ef95667dd949f71b36d7ef055a7f2f4dd91f6c553073451c06d6625b5960219c3305a873d07a08383be80bb0b6caf5252af3114563691fe7df274e0653619ecbd38eee10de826488312202b854735d01889d1361647438e7535312fe04bd5873f9e933b31f03694ce4a2c13dea85adf736afd1bdf45551b008854f7533246f74ae0508ef885ed0a9a30f424538f5c0ff3cad553863d51e44af1cacaf7c4debda37b567dbc8623a5613b1c645e58088179202476a62a64d0ef93dd425841681c88be1b523c49a7b5c38905de75c723bd8000e6c190fb302a59024de1b583bd15711bf03c06857e43ac0be43d99bd413350d465e3507a474d07981b65f97f5d7efb7767d9c0ee64c64dc7306f44081df22ca94ba225b0d125a556b9c667ba6bb8d0c61a7ed55b33e91b5a2407bad359422ed75eb0f62f8ac1fb978f4fcaf1e585666bad4f2eccde81b3a7f8ad95ec920eb7793ef7c41fcadab7d8fa80810dd3d58b084cb10e9ee22458bfcf9ccd2f380920f8593f8698f194f73c08c7244a58ccbf5de84245a28541897f63432db8d67fd303affeb7ad2e8de25bece9a5d86f296bea2f248407660503b20d200b21017ed4ed516e4bdecbb6641c007e16fe149add290b22a69be9cb6a3bc001f8fb663ae096dcb8dac1a5f15f3ce4b861c32115c054ed84eeda36738514dc0abf1a2f89cee9019557d7748e5277114557ec48e402831af159258053e2fa622af21f0ae9fd45a1a50b3bdfeee70a88a7cad47ca4d99faa27d7de3b7d07f99ead6f0e0fc998ed5a54410ea95ebbaf46c6389bc2fea9a84cdb784b1fb3ffbeb26b934aec07faf2cd183acc49cbf8d7a7e036c81a72e1443ce3f871868ffa5be8b0ffcb55e67b82ef8367", .None}, + {.Sub, "-3f08bb0c6cb0871b45bcb8baba975dd15acec53d1381ba03407d0e4bfcac732a332c1af982927b2a64dabe075399720ecca89e081d742132e7daa1303a41cad83a550163fef8a4225c0ac0770c331362d690a8592c019736aedc560d73cbbf0a0907afc5c03eb08af8beeae02b21d893d2dfd846116fafeaa7b62260b54f3fb6b911b7ee1e6988d6405145ecf15d59b92ddf468aba7b60d1ec0cc0fe9857f0500063852459123f8c52ac7764200c8b4ba5ab2d52cee46b22124b5bf13d3429c02de11fc3ca8828479bf5385061d010e1c24da28903a0089de65fad43d4104368376fec7b098a7df5bbcb31caf31357f265b81d1da7ea453f74615c0c4d8808aeb48435262c3b56d936cd967132e5a7c7a7f7bf7c6b4ecbddc5ade26e134aa23b7d640e6682676f29594d3920a35f704a5fc0f7d8a2cf71ead2e61998027fce0a1bf8d5d99a19c229c0686b502876795ee189a2b091a239b92ad02a4e84cc66fc67e2c1fca9362f72f5f34bce905b1a4671996c20545dcbac7463617ad8924cac1ac4ae250b5fb615eef1f6fc9999a1b0f69dfd5df9a048d30c1ce92decb9052d0c15fd38866b670ba5f71da6555c1df5cc418f90ed316311d1279013f27ea999c4922e46806e96f77bb46ce6866a8efcad0e112da564147fc481023d3896d37f1f5ab817464e1fb17c378478053cb3d62d1c1eb2bae42e075a16f1a9546a90ecd360324945d911233b405ace05c68047b03a77cb8ce181033017c0984a95170b94b8a1717e9e91bc350a6baaaaeb73d971646b73b0f5d9916177df1721a48e3dddd84cdbdee7bdf394cf4a652fdb44c777a31fc521ef0aa51a71abcef80b624979186df994f48ada1fa38e3c33bcdf948d67e0301b4e8d726a4c817128d7796c87a8567ddb5f4b4713d81dbdaf613dba3c93ff78f361b8da834c7e058dde057df5fdaac55d959e40bbc047926653cf17523ff92697a9ba9842c5024a316918903b97a285f58c6f61e6c84abb96060c519424af50fe6471a40ec96a5b3097ce08389066137f91313fcc674fc5571d0b25afa638d6d5624a41e9cb12938ea4b01a9a178c6a5057b6bbadffcfeee1e1b464dc456c3408ddd4d25634ff888b268f1cc158163342bbba64faf1c43dc7d966aab1715b4289e99edea4edd6fee9ea1c63b7ddc9094df4c2eaa45f043090ea7207fe970be2a22ec34ba2f9e7237a755732b718925cc08290c9f45bdba15b74ee1e2794e5f519f6ca6708f17a5519a3a0950595254e94c847b216065aa4dfc0b9b2f8ec487c4998355dae33cdbf3c3ace1a8a8abf6f3988bf85f26530362e15dfd982ac3c5f30033bc9be191aa1a5ca1807572f691e4b3d5c533a873a625eb2c33603df5bf0d57c96b2cc3665562724c94eacc442e95c242b0c667733d6a7afa93710b70577afce80572ec1ed058d1af9f859255e5fa84c1a25462e52cd65e698819584bd06d4c2daf13652d04ae1e08a5e7350f1849608314383d36b8ccfa23d27313fb1dddb1e723dfe3e5cf4d9a9b79d0e6b5ebddde7c21c175ccdc37fbdb2f59c92ae944bc9dc39cee99895ac956fbea59f5013097ff61a944a6cc41e9c33b011fc695d58e0501b25b8de94ef5a2c5c86d6b26e429627cb1a2458cb43af884c17e00827664212392b7eb5696d859bd670397f67cd6f7327926b8d7d73497ce828a6ba876253d8841bdd31725e69c14313837d4138a2d396bd22ae5f10182941ae621960040608e898a0b99fc6079ae72d8269a3c2aa29aa5b51f66bec81bf62d8393319bf2259f25cf23873dbd432b341107cda9319d2536d352896043323d8cc5ab9e592c1389c7d2ff89a402c3aee47e11aa13fb59f2e07358f61afc91fc210d14f16e82d434707a87fd2cbb2e8c89cd6b1998045cee4129e5df1cc41e11195a9543637bc48e42d5d23c571f773100762ad2f2a3e7b17c0c6f0c6fcb92e2b602a253cb9656ea015c0c469e931405090bf80a0089ece7953bd78265bc837665d9d8a1c7ed81552afdd9f67ea77d26635bbfa29685a4d95e4564b61dd0b1d8750e25f5a837d4d5ee43cd86f4e698b74f4a2e276fd9cf4664c49a6a04b7cd322517b3f534eab71b56b076a99", "8dbba03c483845f5b0d6132a70e9c6c36d2bfd642a39b3003724b61cfb518654657d95bc9a592608ab8b26243606831425eb5a18e9dba1d46bfc2355f6044e63ef20c8fd334353702dcf52bb039f5f0bf2d9b9daf8d8a54831170fb1d818afc4fbe6afe0001f17de138c94e356eb66a4e1ba0b60983cb30de6547e0953a51a210570a5babcffc6a43437e1b68b53d4362c3182318d16057cb723d13c528399917574071aa7fc3861e53ef6d3cf07ab8b90919054ae5495fdac6c45120b1f77fa24307730cc4aec3bbd0ebff8d9e443ecfa8e93c3d10345060aa4d16d03b7fbd63dfdc5f36a06882a8c941eb91f6130e501c3e3692fa6f97c32bbc4970d1dc6b04da5829df1cc27512c096d53b4b6a338422094287784eb0d7b12583c0d5e6c3142fae15548bcfc5218eb43d10af4420616c80c7289773dcf02c1d907484e14bbd5cf8874de290480ce27d9da0f97991a59cda3871cd95aebd27a6f5b8a85c3ff49e93dd90d10c7af6e48bc39b564cab522d2651616a1f59fd37137ce5f37fd996855549c8c46cf282a4f3a80a64e337fcd5e686f19e2a53144068bcd697d24a9d6dd1b634b96d385d788704313660bd245af942017da0a57228d1c7ab1feb03ac9ce0fcd299703093f1ef20a1325afd2c763e2f2144db487782b5ee12ffff6cf0df43ed92be1fcc294fc686e5dc156f4d8342de08a9bc8b08458bb45113333bbb3aa7ccce389af4039c09356b94360f41c0229e47a2c32000e20c626e69a30f71c7f6b5fd609cb7bea38ca5e7edc3d514b3a97f0b29cea680bdca27fe8cbdacb6b7e58c2c5536d9aa0039f3031332ae4a58bec6164cb0b90ab500d97889a95d04de63f3c1f1c7c7d0df02428932b267448f129083c5cfbb2970d5a9c5bcd23bd0328700ef7ce9a7ac0e511c127a2989424d555e97360585e926172541d198dc0c75bbfded841af00893bbecca43974e3b5e761fd27dba935c7a07165b016a38dbc380dcf6de34d0d12879d968264cee78988a5a288b76ff369bcad729b70b8db2e826fa72c373751d60392731879634e955efc3c4ff1c3c81223eb09b5158d3ac1279304c38e6cbb1cd19913dc1705bdc63fc59a0a82866e0eeec08ee6deb979c252979185169d6c6e1db81467bd2146d62c7dff84acd9c4993bb5c2966a2484124b53486e604b41cc9953e3217b52b3959dabb0639ee5c7e13952e72108e1691df512143ee21c16a925a206951f8913dce35fd30c992a0e35a0754f086e6529127b0e5bd06536e5888e571af25c179116ddda9b72cd905a7b966396f120afddd4853522d26b4da78c65e23f5534f4d59c3bef93b3126bedd3fdedc96c87a1014d1ef0afd976ae795f8b21c97eae1f5012fd9d0668e5703f6555a9b695b01820088cddb7b851c465da5c907dbf732b6c2ef6b551b21276065723e74abfc8273b3e802f88c439e08b85cd901766f018c225cd8926546f964cb477a0e73460ee0ef9d8bbb7277cd5c706f80fafb1817593d1bbf367bf941a231749acea3eda59dfd7ab24fff6128d0b638961be3043056af7900369f3232e7b48fc03d50d0160198fafabd755174c4c739076c06ab51b86dcb42bbf288743aca365aefe5fedd371445ab12f4b9753282aa657dd755ca1737fb3b67538d22dec79142ff825744ac92309eea90ba657c3de66601fbde527551888e8669a70320ab821c27f53d5fcd625ffa5418f81e5707c78007ecf7063bf78da87a1ddb00b299b7686b4f5c7d0336c7a742e0d474bc11bc8897a56d655d82cb17d77301a7765b5517d16b53054e74fc540491cebd5e4bd219c03e547b572e4891164cf49eae67f952740e27ff3356170e498504910355b1e0902cdc96718a2baa7bcdcb5322753859e7f66a25dd1e93f98d8f4c929d028aa2f98f86c6194a867fa6c45d04c09e9cc28353b6b09c68880194554f55dff1444a09e3218fef243a38aa607a00abbaefaadff20d416d68608782861dc15be1bf4af763a3a7a1b551309018e3fe83b13d5abfb340cf214255218d16ee5f9a65e7bb1ac36fb52f74803de29cb4abb0cb4dd05401b91e8ae05ed39a595ef9a4d6ab267b6032150f1084144a581275fb79fdcf7a5", "-ccc45b48b4e8cd10f692cbe52b812494c7fac2a13dbb6d0377a1c468f7fdf97e98a9b0b61ceba1331065e42b899ff522f293f821074fc30753d6c4863046193c2975ca61323bf79289da13320fd2726ec96a623424da3c7edff365bf4be46ecf04ee5fa5c05dc8690c4b7fc3820d3f38b499e3a6a9ac62f88e0aa06a08f459d7be825da8db694f7a748927a37cb12def5a10c8bc4791664ea330923aeadb89e175d78c3f010e77ee37eb6e37ef1436d7363cbda77d39011fbeb7a1034853a1ba521196f496d314835903f8493bb454cebcdc364cd4a34da3f1047eb0d7c83f3e756db26e73910620485f5084127488d7677c0086d7913ebba71d20a35aa5cf5f0229b7c41e077e2a62d703c4e79c4affea1853a4e2d3b6eb40c03aaa20a90e6cc05eefbbcb246b7b72387cf1ae53b2507689044b2c46afb9d5a7f29f4acde2c5f1c85e4e7842c6aa8e90452a380e12793b574637ae7b94a4fd4a99aa0f522afbb1cbffd5b646f722643c080845bfe4fb946bd1366affc14c47d4994937ca4a45831a02c197a6853e1941317d3fe7d530c3fc65cd1382ee04502374fb563629d6e2f3189bd2023a917d7f8de968c229c811f123b1050b6d68f3b4ac8ea47d59d48e603e13aa059a00bad35ef099903ecf7471f41fb9b1c9073cac611e6896ca4e2d4ef6f072301c741133ece662fe0acb05504c93457ff6b7de6facee659dc4a8870aaf162962c0637500ee24bf09e13bcc3ca1b0070db3033e3886bf312f4802b1380cd154a85d381f43360929c7b12abc9f03646392c3f96d5481970a7069094956a59ea43b2b8e34d2e995610e6fac1d2f0c2686ba1635c5c1b96680a5f819c6fead35b41107572d93b264c6e80608d659093857ab89250159dc0d84a49d298ad0c68cd32de5c1d4bd2f7ed703d64e6169556266c2113915adf059aaf7933ebd596aa435d74d4144fc065f0a8d43fb08275b23bf8563ce0a6573afe17fbc1df7cfb055636fbc6ef94fe852186adb391dad54f3871be197788617cdcc0886e36712d5baabc86891a26ae2386f966e744505351325540e09fbeefd9d43ba3d555b3f1f6f13e62376cad16902bdf8ba22a28531ce13605b406523c0177205489683aaadc4c7d257d1690f7c522f9687f1879dd9420e9678a33e298cc1805440e7ca291c51bc550e2c70f85813b265c4bb9434b79305cda91384333a0a9b7e389bd50da470ff64ace09d817da7f0947732047845c8268ff4753e91efa4221205be181033aa652d7e979e94b1bfd21cd1440fca2317bc65c5b829ca31562d5b7df85f0ff4920bf40d2d7ecb1275834ad4af1ee82bf2e315a7b79217086b1251b908a44e59ce24b40acc9a125c2bdd60e28616dcf8f73e6206f2318c0f0cbcd4e16eb55120a11475ef7240d3c4546722d4a33fadbac961e0f65d85e5d4504ce3213397a58de86c85fab0cbfbe2e4ccd6b143bb52462d2932713deaca71321641786d6d29ad3bbd85070a8acb7b3c8123b2bb02fba5459ab28c61158809df1884117ce61683bdd3fa4f277ae62f81b000b8609422b1fe3eed0ab517e59c6ab996cfd8354efbea5e97426707dae38489514f36eeb0951c816793c7c91e8d934f47ffcdcb31639d8e2d7af344cab0a8b90c29bf9793be9c9f144025a492e56192f9e69f93436e10d915caeb70d1ed9d312ea43d412fa2edfcc40a8ed3fef3f1b23fbe1939832282c824b907399aaedddf888d01273ca101e1b6141234174054bbcf6b1a99fcddd1cff1756b771a7fe64358153b04eab090ef3cd1581243b58a9104879a90d5bd23b005a8382a56c499e97ad94bb0e3cb4a620b2382fcc51fdb22ac2e23a951ff398ffeaf63625398647d9286dab38bf6d3c4e2756e5b2e1e523255469a86164a72750ef8b43b488d8ac4ae42a63e114ea27d8c94ee17294bfaad627cd68fe2c6747f33d916d50b91652ed22d1da3cdafe2c105795bc4bb72690a05572716c7f8c86a7ae4376fb2279c9602b181b2b0931e0d17fd8dc3b34b631e84c47a5b0e12fad740473c42d1fd0e1406707e98e63d844ec8086b9919ddaf69fb7422fa901c1c938c8eb3b6fc0e564e9e241359bc83f8cfd2d16d0ae4623e", .None}, + {.Sub, "-854e3a3fac0e8149bcf6185a3c349e359dc19e023561ebba864f2f9c0bc391be3bb77024136cd815d9c105029a7003183234ac73013f8e984eb72ec88fdf6a47c7419e6b0b42758fd946d8bf8577aefc027a29fa80a644f2c4fd738d738f5f350f42e52c2ab6ea647dec287675c46646bf6c284edd6d0eaca057c231c9be8e68208a7906e3a2f67feecd23193bcbf753ec89ec11bffe8b6d43a2b954cd07c5f33207d3cd32f996fa1a4fdfc93fca418c89b77c2cfa18dc34795cfd389b65e061e548a1a8970e282500814874d78620a479606a8df0af3fb5ff1741c3885329c44fe91f0d7fa9321d48e01e4ebed8ebb4106d39849c08f3fea80d8f6bda320489344e732f382f41289394ce73c48d4e0a068a79613a42f0d60d6b5744dbeb72bc084d64bf41902576ec0bae12d429337e6cd3e648f784b8e64bda7f2e2186b61202cd109816f1ab2fc6df43084ac2438ccaf2c89debfa5efea9600764d49dfa13349f420ac51cb720fc83703c042ebdfaac9bf7a5a4af9ec58f1331d67dffe6f5a4550d8199081197312982b10daa574687932be43f480c5e979c678563acc5d503e4d760c9acb67dadccf0ee167f753a3b72726f7ef12687b6b4d400053e35c3224821c6902a4216693664ec25fc412dd4492eb29cbc5a92db2b913c7de5d5880801ee075c43e02c730b8ec054feabd0e954ad41055349989c1182c907405d81b5ac0210b05cbbaaaf26b5e592683e57b56649d9d3f0ad1c80fcf7f6f6c4c894d42349b0327c43fbbdea324ece0cc3d4f446faed287fba5d6ab94c29c6d39fe6e799ed799f4b606de2b4dbc64249ba891de98e3bc3a69f456da3342406948dff6f403f615e54ecd0fd4072bc6130b7f0714f54fbd99ffafb21b7a0e0c38cd2baefe69bd7c40f65a72f5b4543a447ff8edc9cde1375d598e886726522925c168bbcc5103c4df1ea61959abc12e47c8d2419cc44dd52f3f2d0ef040bd47d258d67e22659313459fa371564af24a124876ec83c289b5827a9667cd81acba64a71a18faff48d94a0eee4461f53852ca9b282ff4a6034c41b27d3c2cadefce480521bfc9f55a4c491e5696ab53c7ee1b2b2859a43fffe9dbc1a10672f47f91ddd2ef41a783240214790321057009ce163b3fa87838e719347299b40f64bde447fd4ecd717245aa7d07ff93f0799d940577f6d34fff309e6a1ead5a40d3f816f05fcbd7c63d38e759816af4ed030fa6aa703df6cf39ba941eef0d5eea7d4f5a8bd757bddf5a7ccebbe31e9594551cc8d3ea43555d59d3f810e28d95f375f5a3669a91a234bad860dddb59489755405b08d6beca3f4774f73e231986888bfb8aaa06d64b279a54422dedfd9bf33859160c6820a8016ecb11cff39a546ae6571240917fd097f63415b10b3bab875bab3cf2b5d1c0e7d1919c3d7b548f38ea0cdecf3fb8b8ea5da276b2f179220103b7219a3520ef3a6e20d6529f50751b4804fc99c513a42a6aed43998886183b2686759bb76637250ce76a52c0630e1d45dae4aa82d47d9393fe442c117242b8a56827ea64db74f9b4588b0433be3f8b27c432853531a139d26c0f9a7b6e50c0dcbf89c0dcb26465be1d3bc5c429b680cc0d39227569c419206685b4fa665237a0e045d0cd84bb09d7f1ddb4b5bca9a46706dd01b36535f4c9fad9fa3e0266b6f71b58556ddd136dc917482210056ff8bc89ced08cb31f214bc1edd840beb9459134627b4a1a6d205c6ec0208ed94cf881f2862add4dcc6522ef71195977d9dc22a3246b92ee4ceb69304411f553a5c6796e0414b512958eabfacaf33a195297b1c206e8517abb115525d337df1539ac7d7b17a4726fbf2138478fa8d36174e10e99d50f0d29ebd125be34c5752f6b7a93c5b72cc977f43c666973febd43398d60b6a2705de2a427ed437cca98bf6908c226e8283e17e42fa70e0fcf19170649fbe16d5132af89eba29f3f0c12fa838112a7b409bdba3d07a38b62519d72c2bfdcc0ada40e93434377d98a6a6319e7cb9353a6f567eaf5047f5b0178cc2402d678cb7c55f2880961816974224a7b3c7d9e9dfe9caa8be5efbc18747207a726bf817312cfab5f259b49ab5cecd2ae3274d6fbb", "c94d5c9bdaea4e215f9c7fbafb63a252c3493e7178a4a02a2c7e29f1fc6dd258734c47b89580b3b29d9e8329b9fc7ec4a17f976b54c40f75506093667b1f1aaee7110b861b82ebddd67194c29e43993d391d4ab68781d77ca709d4ed6773731963e9b11a2eb785bc01d8d2c17e37e84f9d06bd3a5973ba290385a81608548ce3ee069981650ea88e9e3a5351b90b31821c865eed9f5cb833b9b6c448d8462ddeb786fe2da2a87f88e7b9ebfeea8649bb4a51973a7b7f0dd984c6504598b7929ef063c41b06b474b227730ced8a500bd38bf28a0b97d755b625d9a7ec867d5a69f94eec8313d40deb8d0e7ab96d211bd35949e9c5fc059e42d9253b76beee5828ed84c9040648d5541d4ab0d66434ab05aa38c9ed81b49a8699f8862c7a50e14853bbd90fadf85639f8520cbbaa89de7e7f429f6c30933b5ec3a2f95ece9078d0377f8254d59c8dedda026b4a76f6353e13372ab18844af3959aee8283fdd7b3769244ef34a7244ef9270a6c58cf162e8fa93de0c6fcaa191444e18559076bd73227f5e40dc81faf6a5e0c4b3ebf16c5161c09759ed0c88db1da4442aa1fdedc4db3c4bb3e153d643567a21af29805e60ea75c5d8a781dd6d314318112d89a15e0edf7c5f53cb7296db0128a5d0064f693649bdeac789be9815c6faebe22d8ab4e26495f295697647d9c9d176a2b4a0f5d11bb8785cdf010993412c4a118a2a3c1d282406e2454f4c51ca0b6c946765449a4942c816e170cf34ac4c4f1fbb2327a27dcff4b6f779de0fbd195c41bfcb206fa22416f21895e256b2635260d61d789c9f77ea8332f468043a1101ccb530d3af6a7cbb9471a4008642e6c731eea10333dc95c0cf233fefa3d0e136d21e056bc1445a084d0a56708c18c77785f856f1d1eaff8e370e8f69d90f3ac604b055949314dd68cdb217898257053cbec43dc2fb6b5842b04fa908871e4a4ab8b8a46661352c7e0bbeeee92c8b66b52acc78f9cc51cdb2bb32e237edf12f6a61ecf57bcbeff3d67788fb10fb8d8583d5b6312e1d1d7747a52292799baffc5b811d6d5266df933ea22a238c74bb94ecfd6c1f4e5e972e3f9737673dac8b111b271864cd44722bdadd833bde084e855ef0475bd8828e9909925f51f0e926532aad9ff48e088128866d7de1a40b0a7e425d1357ad1fefb50f9462132259178add382d290bb9f918a70fd792422deef66a57ae54033e2f6e4c7da3945145732c7f751294d2829159e0e5f0557bdd0a9bb728eb0c8f8618e89ec024af7f28af414757aba9ae96750c2aa6e3d1973c1b0c1b67bcc9684ff35ece05c486b6f03e1f6ceeacefb89c2841925f85081c9e5460f24617563a74fd69ab1f1b71ced2477d8c4ee3cc1f002bfc9d7be4595501d88c3acb698affa745a72934c2341acac15dab1e4c8f371c80fe5e2216a90d47743b6c4fd4ec16c1d2a5bf3391ac3f65ea7992dcf0f753c121eccf33a6a9c73aa7e00fc7cedd3301ed3b5aead22be996a5d7f625133ff416d22394f23a315f5dfc3f4973fd04a6032a191263762330763c16aa104d9c391386e6be3dbdc16fc7830be60088190ba1f9dcbd329b7db114401d83da106989d73f8901e2ce61c55d72b6593ab86967f0cf578e6cd62f29e16c71065554d92730c670273f83a72faece9e1be6944b682a9578d5e3693ce8a12012a981b4c404e84cd57046035cf4e8e290b7954f60b219ffca66fdb0281c54330d7a26a24ba721406dcf5fbc06875e1e6ef30929336fe68dcd63b315e49d80505052fbd2e3ad192f9c603797c1e8a56a26fcb4a94a169d5358bcaa3228d3a1b9759e105e0437008f66992bfce493a68342eb66ad18b12f219245e4bf55c99bb917bd7ddc654ab675813f26d04c5a387218994eef42bf9937fd75954882a41f3da3ad595aea80591551d7363a5dddfbdcc829576bab7195f26ca57086fcd09856a2ae488c0b3763c5157dbb3a2672d7372dd78c30b794abb373f97be50934df84a50e4741039c4eb0888fd401706e19451f2acf06eecac76e734d03a49930d56ebac1c443be0053f10af7b1258251bd38672a645a58777f091af4b71b74b7ba590f30577abdba239c8b36af239210fd5c2f39", "-14e9b96db86f8cf6b1c92981537984088610adc73ae068be4b2cd598e08316416af03b7dca8ed8bc8775f882c546c81dcd3b443de56039e0d9f17c22f0afe84f6ae52a9f126c5616dafb86d8223bb48393b9774b108281c6f6c07487adb02d24e732c9646596e70207fc4fb37f3fc4e965c72e58936e0c8d5a3dd6a47d2131b4c0e91128848b19f0e8d07766af4d728d609104aff5f5b43a0fd597d9da54df3d1e98ed1fad5a216830209cbc82a508b47d40913677597ea0dfe234d7e341d7300d5ac65c39dc29cd727f4556261d62c780552f4998886956c24f0e9b00ed0842e49380b90937d4008d5ee99082bfa078769b7234a980e92418132cae299205cb221d33c333e78167cb0df7f4a28c1f90fb0c3434ebbf78b5ca763dd71563c54045c093dceef887bb0e45dbace7eb311fcec1685b52817f4450f7d788cf0172ee23a4c92ecec8e391da0e1ae52c1b878cade29f34f743f0e38030eef8d147b754a9dc390fe0f8efc108ef41701912020e3a72fd5b2147a4056d3614a2c0e76a468c6d46bc2758a0c8dd70a4764f99bc397e953c33e2c549539b540abb005aab399df212314ab008cc10447129d3fffd39b25e83848267303f4e7f7ec1132c7d72131279e25e3f5b4ad44378d91f60290970a92ec9d6446192af0f28c286013603cea6683f9f1ad56744cd56036f7b34cc6ba7065b962324aa22f52af1318ca87bdd2d4261792a20af700f0c15226cfa39c4faf8ca1ead21debb5a94446167febbc76a119a4e973bdd9cda74bab0fcc8ef563e91f041a98503fc16baf7c27a9bd5f84396564227e54d5e6eeecc80efeeb5ccd540af758184345f3e61aeb38832f02a31cd5222d782cc0a11153f3334ebd5c3293af0426aa516badd06858498529acc1d19b65fb1df511086a8009a8f855236fb1bb7c4387b07208c96a5f5120544eb830687efe41936a1cb9065d9d35318a7b01715b5eb2e1ba1b8f7289a7f20661ae7826e3ef8cdc6f0355de8f03117cea942c1c71cfb0a4777865a04f7c00a2cfaccd6bd539c3815de1cf4fe0adc71fd56629f37366454b60378673e9e1ec716a5b3683e45bc94ca717404d9a08cb1752deb62bd97b3f55ee6f7dcd580e248acc9d06cb49b3a6e222f97d53c78f03a8889004b6f800c50b3f4c00ca20a1932c99f706d96a3c32931b981f24b67884a878eef90bb0f6797d17d1fc35ebc6b450c0ba9341daf33bab0094435d79dfb998b1ef84f58a27df4651cbb270acd1a8820b640e906babe2e16881f49313e4ea4de3ec4aa96a27f1fa709b526b759e267282733f0c5413a23c4b79b373729f3a5ba5401cb8e1d36739b506dd20aaf0b7c39f27770eef41fa51a8917b031dafaa4e298042e94e98e392fa4886f1abef72a2fcb0c50a6a8fd2e7d58337185eed77ec532afe1777e5ee5e563b02dc3a3cc8e7a250787fe69ec0c3d185fab504f6944962b4c8cedc98d09ece8c5c605f916b2e6d4493ea2f246ab44b1a58405d7eceb6578922f20b976637903fd09cf7bea531eddc6358f6a6373a54a1c66d2c8ef3e9f063222c46ee00fd53c035882928db6c25b597037e2c433496204de97c761e34b01d9b6ad59f2aa460c57f772cccdfc00432615df6c825d58f04e67f0ab261b172e163ef451acf02fa49150e89b6af81bb89e21883830d1d0f0c8f845f070ba1d61f2966e4c8245d4be86e595482582be40c148685db343407e88c20c04e56ed4df34634bb61c4f41c2da68e1b6bd7084cacdffc5ac4ab7c1b1e127a85428c1291e7e62f6478b7172301d1bddcf5f49b3ff63e18695965ca68cb3491be7ee31be2b1a4b8f65f7ad5e7414b1a9ce0f43fad213516bedf4c8be0e9ca015acecd37e97387dd2273279f50f01b54f4c1bbda3edcfe640cd53456d7b813af178060c8aa9b94260f02e3e9d48c68ea97d9ef8cefd8ecdd866d788e40fcf660c51d9f3630027f3f71abfb561b0f485852cccc93387c2dacafa0fee0610b8271192181ecd082e806287aa7a20c95fe54653e5d6d7a17b668fd1b315b7102d6477989a2e680ea09218ef34a2a058512510a4e250135de04dc7bfe3bef2a26512661847573ac7d5125ec7df0bcf424a99ef4", .None}, + {.Mul, "e9619c587d44b6e5a65ba51e84c9b9ae0af090120c2410246d5d37acadf648b8f27297c7f3698145a0fa5751431615338dda734563ec8f52888c04a690f93ac0915e918c3c1a8d2cb2189945117f8d4a7484d5f6ca5092fae7f52356e0088e0b466f660053c41585c8644a0cee65d2d257abd4fd481e4066f3baefa53f224803e6bc3be1a41772b630a9287c6e575cb6515bc3647e2f37c8f010fff0ccf11988ca23f3b76511cd263b77c75ed8d2cee807dfda77e9a9ba3912815a982710bd54c444c7e0257aa164da74750a2fb4b2e87863063338c8f0f4395395765c65fe927ccd81ff94bfd59ccb50e5451c140210641d34ed7694c4319846297def65d0e1684ff8b74f821bb2f1d5827c24c6b91ff841cde5a21d36aec87d6dbaf75cf038e5f632ae1bde91c441ca41194f22128e5d0bd3a35fad3480c3879e7f9f8620fc4be5e1492ec0c238226549ebd5f42abe408ee3af4bbf556e4226e14b68c27933e27755a3553baf9ac9945d5ce95f18af43da260f8c09010d3da7e90632b61611d210e14f2c8a9873882ef1c0fc3f991777aaefaba008fa283069f640dda93eefd2d317465e1939a0f391b9d7a91d71eeefce5a9890a9b4f768f051bfc398469c662f753261b61cc22ca44cf42cee46049ff0dcb4e41bcbc7c15d01b4d99c24d8d7888814e707eb92ad9cbb23ba5892c760b30d5126009dae5e32d355af05dcbf8ef031e378620f6e03cdef53eee3f9677da5adc8a437f327849b164d689dc9d0f399378290800da16ba480e6af76ff9ddced4c517a46e7f3dbf9b0c529ba00021ef89bf08af983f2d8e57dfa99e101be68f7f53def978523964b2ca710cfcbcbff70822f0b556f3292980651e4c4e95e32d5d19bc946b959ce87e06b2e80922565553453e3f9823dabeb1edf903a2c743e521e4371634cbaed92e0e65390f1fb6a9a13309564d92dde9db80e9f3125d82c8263ad92db78d28af746554d79050f77818fbd7fa798af8b358695f2e80b5f2f14c6f6c2485d865b333352789384ff178df8215e89c065f2c0f6fd81d4a3b1a2826f1bed7c947e45c3e4422d583d97c318bc090fd611e7e7fda830d8e8f24ddefa81d511000f9e4e9d9f48b6251887167b0ab0c4c66a75898732ba2056044d5052b9c320ec78ae1aee387498068d535a9902f673ebded07844f1e656bc47ea17c4f09338b35c0b7f15bd3a406a44be8b2ced2c15ac95cb0186a4ed4658683644b7141d386ca355681314f9bdf4b3cc59782340747855c04e6606c36d799d45996fa1da40f0c8a1757083c4bf5205610a8ce5f8be51e6e202627a45a5caa51802df72446a7ea15de44b34902cc302f4bab083cfbbbe137d8769e1f79ea4015bfc619dab3aecc696b4d7bd86c6269b4fa126467e99d9bb3c50b9bbbc5a100c3a68e763a15c742bbeb560a8c10ce706bb69afd9acc5c9d07029bf046e84e247a2da2452d229b62639211947ec8e50ba60446bd6be2da0b9a79af13dcab4478f8a26c1254c2f0e0807fff44386a50b887b7915a59d231c4611dae7b0fdf13fe298a32425cb03131883d0915d5810068317121b20789d5a928760dfa53bb1459d646771fe6a1b8c86cac75d70301c12ff60e7d642271d9058bcce6a6c51785dd828875336afc9f6a9111c284bce979119b46978e1a2c61da964ba855854c4b7c4609b42a35e6599a9abf2d8ef087e330634af91421b574ad57ab805ec79d8f70180b1ccbd3490d9eab784e307db09f034e7a4404509ae2f813e48cdae7b9a0677745489db23e56d7819e7a1d1a1422fb8d0fd700f53c6e11e779d15731673671e87dcc5d4cc31f9b38d4e4f2e5f4f7c7d5d8a46c234bb43fdd40d6b571bfb48a625be4fc87fdad5bc699a9e2db92df027785283a12c39a9bede0af351f2b24e4e6f93e4249d6eef9183d9188d7d8a7f5a5f652e9106a87e1db9e484c3e50925e74f3ace13fb8f9f635b8b0d67c1daad6ee48ecaa2347d357378b17d1fdf0d32c19e86c69ae98b1c96d79ba810f9d574f8b582d0aa203352c76386d2665f95f1c80cd7359e631480b6a78251b073a2e91d5b594b498548a348172cab84a5c603985eecb554b8f68674ab429f8f1d", "ed0bbf654fc0393f5b985c99a16974c12f7a71a0ad0a772b67c008713d426c96c41aff5f6e887fb981384602e3378f866300b19bbe3b1d5782e508d1a915d5cf34b3e8bb30d72e6da214f30e4045bafe300ad389a91218767b1b8b04eff8a063bf5458158cc3de686c82f0bb5ddc111a1b078aa2fa38bfb8fdf275ca939bbec1c8eb741e82e686043086896ae1dcfc39fc964dea042fe7a86462df72023dcef5c3083caae8f5720f46635f44f6bc19963048628fd3ce95ded68923d97e3af1fb732de9d858712380bac8c0f05f27ddcc7185e396cadc5b79dc8e8a5ed5c5b7222e093a8224ea4c3dfebb15dbcb3785a7c55c5309c254d6987cde9ecf45db34201a2f0b0c11e583da5d771708e9af9223fcd5d25aba6b834f36b0f218a596ce88d09073ce631de162f1e2bb6ef4d2a6b3eb8ff692775ee2fcbe63629bfb8d49530a44c081211fe52dccadf7781cdb376319fdf23dd212943799d19bdeb2c7caa7dfa51aad55197eef914613888f5547e51e723e5f3c718cc53ebe892df46672454f95b11bb34fa6233ace75201fe7e6f984fa7f4356eb4f4d1bfd4d49179ac0a14e42329cbde40403aa35ddae9493993e58a29b8c3af5ceb6d5aeeca8bb6471c0f8a2862d31584be5ba2cd5f22ed61c56ecf0cf14ad41b6c73c502fbe18e77c137cce70c1c238905a915496b3d96b36df4d3675d9f6e205f0317bf64c3cbe82b2cb4a63b4271e6b352f2f5e961e0aa0fddaa03b6159502ef87940f65307df3d6ff452cbdbd63153220f59e2e7d6664debff84fe9b214869cb534089669106844b801728b9d4536649e229351a9649dd192ce6dba3ab1494b3d59185eeaf93680911a6e9cfd0037a21a9b5c7823104b520a1166209a566c843da4376d106ea078311122bffe67f77f2f8a2c86d44b6338d350b16515ad40695b92098cad8c1ab101f8b9ca28bcbd92aa6eb5d751eb774c6edfe8d27531bbbbb2b4284d452e6b02ff348b5259d0cf7b3c26e8d65b34b692d6df0ad9adbf0a82e5ebfca719e5c03db4f014ec3e34308c0034c4f57ef4e43d34f51526bfe41b47eb890e90974861b01db41ed65eaf364472c31e99178b3c45a3d1583b8b4fe6c687f496ec4f8ef9c545c420143271043dabcc673c6b6d11d195a081fe339b318918b10444d53fda3c5b841caf57cf8087fba64cc4a609503ef2e59787c929f5d130295f33e7ffa3ec4f52c3c70f68f80a26d51513fbee0d5cdf0aa717aca8adfb37f6e4217487c3d64100d886645de337f92277a56930db09009f8f9ed6d8abd2eaced9234db19f4494d16b10ed8247144cdc3a5b8404a96441fd11e9b847df74c9cf9b3f6fe83316a220dad44427245cf5c9e2f7743afe6f9dc047bd865a6bd7b8ea947d963743a3cbf8b7edfebfaa94c6856dc7c985e1cb663d8089ad580460ce2d88a24abf9e07c1784dc4424848521c9d0f528664d75fd5ef52f130a737f12c5aaa56bf3cb64c2af53d1dbd06ac2f8546710370985ada2a2324b4e57a3e4059e05bcc5727242c6eef6f65a91ed13d6516a3e0725c9e6908f98d53f9fbd42a48cff9787af864138fd10aa6aa619911cc3c6089e943daf60c45edcbd2debd42cdf1f4dd26907a4b5f18dd745f75ae1fbd3423d9067587d05517bcc5a5ab187e6b34c00486147329ad408225fd62fc753e9147f63960bbe933f86b6e8d2b1c312670e9c94940c8c7e72b0d14e52d0eaac8e28e73f9a246cddee5257dc3e49cf3c16678d44d763e7f6e2f0f1b688b32728eab7b24a09858998392af6a7a0af5954e41206fbbe4632a99433f3bddac7314e0e5f7f04205e64d8f6c3091ca06b1816ee229f25cb73c99ed87d490235600a4445549a5669b5f3b79a9ba5c67dab996beea1d4fbde10143ebba392bffe11a0c35af167c739fc2e231a7a37fd3f2020af975212b5b2bef11f4103b00a6802b9e428004957ec35f2f4ec7f43a527cc5282117216044696996927b8fa6029e4439159ff1c3adcc4e548280c8b6973e56c7a1c9a7819fb10dbabf02b41b2cbcc9fc7b019a2990a971d77009e311d92bc3fb41bc13841360adeac1a99bda6049a88cdbdcf0d3af3292d6d076e5099e350efe1fa0aae2b", "d81a136bd3a3104b36ce6c1ef28c237183fddbd9d92db68a9f88458395037a7902c54201d8028b5b8460fb33b2bbbf21c1518ab1b65d0bdc92ca70ee2a7d462a1e8631707dd8b357a22e664b7a913c6cc2cf51a1821a67ab8b680819f86bab9d62a5a674d50533c4631302d2359a8803a1341097abcf08df62fa81c03b8a039451c6df8ce36897e5a4c9c1036c3d9a627dff618df4bb5564015da5638341779f3cf99fd36fb6620399d104664c13a4b4d3a1e6a4cafc116210a7bb1c97574b0c071676377f75db5ec8d0d85f88e4aceaa0657a3551e7277591afb0bd0a5669790b702acc607e98242f0dd06dc19e952d8774f551193a5573efd5eb333495c0124c70b2b93ac5dd656801df9fb5b73b2fd4af8e3148ed68a88eecb045323bd4503b7b3f46fc5ea07f15574a986d96600a3e5d4fa89a5316f1cc3ef45c6df01754a8f956f805852c786d54a3ed4d08ddccd39f01d9661675faa99163dca955c5e034080c25d36628404c6594206e3e4ee5222b96907267acc801529b73fd3fcb3e2243fd5af60cbeadc16496082437bb2b6a0ed3d35e0d22c1dcb0c23183c04ba69d09192a8c3d2622c14acc8230ba20054c49ebfa056336d4c2fee4d69f22712ba1fb090f4db2bd8771529d8623c593f5b2ab1c5b4c68167d77670cd4471fd64b71dbab5acf2263905fbeff3859bde4f67fbd7a50d892109634495d08cf927bfd4a4256f82788b428bc558dc2f3bc5eb853b3bdb7fce2ae846e02a2d026f1ffcef93506ee264a52e9c64156b0a564e0259170c0fa953704c3169f560b55d94bfcb441e534f6644a60c10139b041424d08219264468cd7b1148d2788b2fcdd504b95c9cb831742ef1290010cd294f0a1122daace6caf6c00a311750b18a65a1073fd89e1137549eb1ad806862f29d4dde21b96d6a3f70a304211fca2e2e738d4973aade0dd625f786873c32544d36006bda8bed81261bcdf247c9b3be72a3eaf92f27e5b69099a3a44ebb730ca4149566904fcaa5cd481c287ab28c29d3d40e9b2eb1f9bf9722520b69fbe3005c49156cd445717e7e1a86c9433241a8277dec65aa4633e6d3d125797580830b37310889121f24d8bf4300a6ed5a034de2b0614a9c6ef3bb148ab2192605f871130e5f30de8fd42f174e3b16aca3a13e482f6e528f1d22535a7ce8ebf65bc248fba6ef21bbd2ed214f01b5cf85935bb45f5a734b2ed6509a4167123b5ac4609e001ed2c196a10b4c9883d76228e98eef33aab02e6a12d4fd0adbd2c95b13bd9818be7be2d2d16f7ce6f067d2c6c16d01b93fdabc6df081a37b342739b19de5c7d67bfd12914f0978cc0845d097db3ed187e41163a1d7e91c7afadc3342ae0008efdf2f1c7b74f37da62f7028b0bc5a52e2357b723eee969821d162da58d750c8aef2a17f89032dfca4b8c38746b6656a890dc16042fda55f33df5e11e119c4460c03d6712fdb46f500dc426aea44b5ffe2ee4eeb2ecd17d5be3e6f60fc701c9ba4310f7ea652018176e98c5783800150eacdfd67035dbedddb685ddf9b989914c209b53c89d5591bfbc073ed611dad3803815592bcb705a4242b9e8096dd3bb9eb724f0d955d8b432680ec1354dd89ff0728cc35bdaaeabc2b314ce4f2831bbeb8752d3153ef6aa16a64346cec5d242719a946285887cec4183ba3a302858f12732967e8cc210998e0830b5524bac1cc430f8a36e8cd06bf173a570dedd2eab172b6d48726dcb59fdac98f11cac1510b8e65e02464a9522ec60c5cd63a8fb30434bfdf64c3897318d0a4c97a1b0d084d662fc45229b70e39fdbc85bb40a0b3167668c0cda263ee42736512f2cdd6f8efebb9603e8469259b40a02517091771148e37e3e1051701ef3bed7d3c49afce43fa1d24b98a64763c38f6956773c03a062b3ca29b5bc0214583fef4f8017cb63c31431edb6b742c76f3b1fafd8fd8b158988d45a05c7d2da3056bc92370663c4d0db9ca56fef9cbdc21dfa3fa99934fdf92af2c416869e2c7773b7b11068c92a5a8adf0a378b7d6f0de6234a3fe6285f2dac1c4fcce35bc34f5acc9564a235800afb3dafe931deb47fbda47bd9da14ed501219c23f481f897d0d9014793e1d07b9333ff4ab92b84389944e49d496463e99a7bbb2f965d1440810c05a75816ebc3abd173bdc89174511a1f8c5ed3f4faee2dd2391540aab0ebe8d79d46a319ffd8644a83b99e5e02f5647c0685e6a540dbec12f1e994f0ec5c2e083e187549b955218f9fb32a9f50d50bc9c4f230ebaffb26a59b6e62eafd1287a3e2ac5a3927df98797686b4813a63a2388e5ef450fe11d9c93e4a0e6f6aa47d13363dccd89de7af89e4b4175a371f4460413eaabacacec0010815672fd09149b956e0b05341925381e996ce4f26f5420b95250928984da8c8e6e82e2a19c201fad1ba77701ec6ea1e9a71fddac62569a6adafd087ebc5dc3859ed2264ae9127fd1f8f4b1ba392c252551c613bf89747456f9e7c16fc9d5b32a6dd760d8f3c1d2aa1f9a73ec7f90e86472ec686f5b667db75411f5b9e57a4eb397e6f091500a62eb4fa13056bdffef375d4d78701f313d4f65caf6d036497165d8687b779f7a20989a8bb8f70cc81df8383bef7b892db876ff55611dc9586e6750fd11f59e635d93420d33b73f6f94628622714d655b70f22f8a528b5d34e98230db275173a62385621f3997d17c77e813ce171ae29193ed958eb5f69aa43acdb00677fd053ee137a38a1663e05b6134a449a61dcb2ab9600b1a191d344c15b5c40001eaffd24018671a2c68cc72887657a853b52cae504a932053f0bfb65ae7e2ab8b35eee6883cb402bce270953451f773e99e5012cccab6008d7676a15b191700d0c63b6751777d8ef062fc2e5151720ec16082879316967708217f26d597a2292b8a764821d0074e1e86ae9d3b2938fe8c2a8f5b38cf3cf2a1a9ff2c3c00406f790a62217fc2177f0f6a8eb15c47a9ff52e9fab53a72ed568c20f0a2b6ba62068d6337a99c794f199e80be48b4f9d8e7bfdc801f38c764ebd9d08df3290ef0cc84ff6e3a12b2775d59a2c1ded4dee1431add5876afa8d02ff1539e0f02f46efcb1202de242f5cb9be986df8ff155d9563c7dacd1687c752f9a3d71bf820c01449700333c3b55f25b07f404d96305ba4bdc20b97bb05e8283173224dcb879a687b393c548bceeaa620817908c1cd9d99de2835cf1cddc694566e5a4becc519f17677c4ce0a0a2f246e9362c44955c96d15003b4c03f87d19b6bd6e463fab4c2d7c17bd22c8ddd1224d6562df19461537f82021f0f65013c78a1fb64a721209732c577e38dd88020530e69873add6f76acbb47e6a85aa4752022407a60172afe86c6bc7ff56e4c12accfa5c6baf4103e9ae079298bee2d1360e649963b44603829ab25082d37dc7d9bf5a2488d44c211a378ec8db1c207181012794af3322878566079846eb68d39430ecc4d4e6dc498ce7de1faf5d5c2a04ff10bc82f12af5d63721371f3d835d27b8e319edcd1a0c0fa3d2a472e76cdddaaa0500f2cb4f8caf5ff4af2b4536f427783594d71e2ec629cbce36b1f9258e5c0d998e2477cf5b9b18aa1f45f748b793c962b29846a51a25a5e18ff90fb1a9bd1089a76feb1d88e9fa21598edfc88dbdd438f01c0fd6ad9ea18273c0e12d5f8cfc5f576e494d520040933d9589b96ec1fa4dbf0999c832a1cc022310e9239127298fc414302033b64aba5a2d306bd32e3f7c84ced1d88ba2718e9c93183c247c8cc36cd5f5856312a5075686e234715e887a7e8fc8cf3fdc98d71f7929078975c3e8af3e815369011f9c85a994f3ea9e1a99a71513e1b8d7f8912686f7db16bd201c74948540d76d478d5f8e2a2beee043879808f46a842b573e766e14977fd2c32f32d3ba521d609dda0857b78dca0cb2888f0f4e01dee691b7f3aee6099ea56fa3b9d57a72a7a6f61cc0e76e94caf931249f00f9bb7e875f0c5551e15a21c985e0e889875253135896ded8ee0348aa707c7971dc6910a3e2749bf0fe0d45ac2d1ed3184add9002e71221d5007f4ddb29e71a69634bd375d7911a3d87ad55b510c4a96cce3cd133c13aeb9bb4cb1866235f4334aff50572964e65eac327193640014046a1a1c980b2da46330200a48fb95baaf5fd95e76d1874a9f9baf0704828bf2088035d34aba91cda47317ec3bd8102e0f85ea5a84d2eafb6cad1b2558bb34df1dd66e4035a18e8b47878d34bfdf", .None}, + {.Mul, "60b4fbff419bb56fed716202ebc07a90dc207adaaabbf843a709d549e0e3e3a524880b892a66a76c117011f64afc527f381857658a737c92b809e8c8f60577f78dbb8ccdd62499c00310059686e9e4bfc62409eb4ed60b7e0448ba3ea1270958a5f659933d22d444cc17cf2e9edcc8130e2bbb54b20e2f5a5d4e95ccc74cb15036ffca03fd510bf9e12c91bf5ea78c20e64ed6ac980de80cef21ef34d805c6df24caefe5cd33c700c02cd0e17fbd5be3d7de48819ddbd75565309d7d6833dc27d5c8310738f2a257644465814ae1acbb3de9e926472821d4ac8bae5475d001e249bd261fcea7bf7f334506451f03576ad5cd0ccb3846c8ac9c6de11c359751b022fa2705d3d1a5ddbfc96eb68a4d96ce699e23aa0cb34d18ee47bb1ddf37e4ab99f728eb3a8c17d29dae31a35189583976cd2a601491b93a1d863f13a6fab943ae38bbb01978bb6651038d41a81e13363acbfde4068f7403b0eb2058cffdf88883a5c22e9d694b5b035609c79a13a6c8ce7fed67efa4b6bfbce69c6587233675da5b28e67abfc249c81042dd784c12402f106582f03eaedd7571a8bcc84f6322e4040f76906211880a47da3d51608eeaf8f33e06d43b8ba5ab918f7a4c1a9bbeb122ba772def64e747699305b9c5420e43366f7e78cd9203936d87844bd3881e56e58d448110c15709495b663dec9336b42367c0fbf60af10dabcadc4541560ff103a806f1c99f4b41cde4704c22ba2fff4ed209f3553c9926cfa651fc8029f153ad6a1a9168490610618681dd262853d4941372bd3d6f7600dee1229129dfb4d972bea09199bc903ef7524351e5e9a388eb2a32361594ac8ccc5631e20ab22efef62ae10658579fdb3646ec8236580561797d6685935762f6644f50a27d8568ddf39059fefe6967d5f23b8932d5bcfe2414d78eeaa485652b5dc0bddbab35c9dcc2dd1c661f80d58478640e7b537744c5f49fc322f75b77979be676a26b87ae92bbdcdbf37c1a0ba7f09475df41d4b157ab0de88d4d33624294f3b834c5c6bab777e48de7c5333bf09fe76a6dba94503665841e202b7512fb1d25eb91ac23a9469e73c8cb2c6654dbf3ee784d73010c406a0a9e9149ac4e900591e0ecbaf137a9eb6faf9d2f0fb6535aa9056821853e234c2851f098880f4137504f8d2dd68806bf5585de02d789718421e0f290e53fda57dc540a4bceb4145b24ac980a65cf88b74562c415c6b37505b36ae5167984bb50c629623a57a01759de1d9f2752b92005985ada5b71edeff87b6a6cb924855144a1cffc58431195433e445aad4e697ac1082238d092095bd3b0a01ca1150bfb2063e67d879982bbb68dcace65c54d52ed2a2b794cd2972efffec0f1c833c9b1f989b97ded59d8e48ce2788c3b490485b8ad8dca00281a3a91665e50115f47748af91d5057efe11c691d995712f722f6de51429e4fb22089a754b6981d15dee2b00f16287e5b2614086e3521231b803d770a4e162b6b5d690d72d786d62518f311a1d247bd631a2f9e1b4b0e918d32b0dd3116a70035d478fbca98608999f2c37c3713b74049654d32c65c555a5ac27351100ed001f260953ddbfbe48424af9cb5b58a161b741eda0a09323857d2ce8ff5c36492002b50f12bb1b1762507ec46d3a4985b119402db4a8a75aecd5e8bec22c543744a8da8a5466d413152405e3209f2eb26b714138c58d5c4f5192d32624917daeea54f94ce62f873ec730603e4d68b8a82292a4c4451d82d6d5f686c6762f5c8761127ef8fcb6becab4e6000c54fb6b9932593b8542f513af813309b9441c8370025dd2638127a49238a144adbd62ab630178167289e8756ce833013e170ef1a700e2d52a3edb1af1ad445a41460fd869f0076d1dd93ccfdd8b5636bec5d9d89f384f4b7be98f541855469543954b315d8a8af6f4b11697dfe8bbb78d046ec3c7d6dd549491d1bb5fe19876cdfe99e200951921cf59b004ffbd6b52e2f0692a59a26e9e52bcc0db847b3ce914df4f5b98638b8eb8c73056f644a798d661089e0b6ec5a299c7286b6c4b8a594e1429a851133a75c637989964c859b595a2fc33ce08692463eb5bc5ba02a8031dfdaa68805a3e107de345b23", "8a5e127030079f7038b2da3514e80439bb180c65514b909766cc0a45338139478adbfc3bd6daf393d9dc1c3c91b5c54e5f5577b0b702f14665cbbe8b58ba2369916d17f0ec652200df776db9fcd4685731b85c11827bb74b249a6d3e2d4101fdc15cd00a18a8f27f41f556fb2999f64b2c029d8b698e4d613eb98f93e8eedc0718505bd6235514dc3946942613fd7dc8b894d898c5721e1ca7d636dfb1382cac51eb19d55d3002a79628d2d91f253d87b801127969b0884af5db97258bdc65b4b9e052cc972faf8208aeb6b27320a998fbb4bdb4163ffd532ea7a1d053ec8a268f7f70d665f5fd385a3b89a749d6c6954579c42eefcd91c94213d7f303d7c6abc915bebe63fb3845837eb6db268de4b9fe1193c5f2ae755d188aaee3e33e5b6b3a4e31d51a94b7e3518b33c2d84fb0914198e5a878fdf6b0fe79d95cb9abb142493c107bfe9514c90e30c8d763082831acada9b4eb9c5e1b3ab6e4545c7bf0cb9d8f9361f8355aecd46b3f11460fc2bd9b08bfc45948a5490962cd20791c79ad007af80b17a651556f0c3d2f7e1dd0391657aa10939435e74fec5db6d314b737c23adbb0f84f45df36a286683f17a25affa308867b38363b4955cc914c72632f2f3b6f4abe31b91e972b96e6b1a212ea793dc5fd2dc7a2a3d87bffe73e1beb13bc2ac322278d7e0f1b833350935010c0808f2d082cc0b40597f14451716fcdf1df2da97ec1793941a4a6a18f0cdc3ff1f0eb1341cd3d919f8056e695f9380a56ff035b368a6a0f7fe9f6c272d2c7be2c9cb62fc5aad95739eebda01e4beb0ac2f104630d8ae9396c7852393661b25852a9968158d682215102f6157353fca52753290b4ef825012bb7f780323dae736aa5028803c1b284e18c1a5864cf09893d00897c563e269016c969d14296fb397f47ef87f1bf91dba73232721142413231576fddbff1437ba2283f40970299341b12f0c1b4781613a0eb4de039afc1054a181d3d27e70cff24cd24f4050163d32b8dffcd023f69105e856e8bb312fd49b78e83b3eed5c23506b3c05953c7ac954c1e3048d6b0d29cea64af9c7c666b0de8755582b20d5107b7fb184cba6e3c22ea66861829a7cee9565e2552adcf816580161b08631b6a1a7535c7fa7a5b78d550a06bfc2a8a95fcc60878d5cefdf8f7aa5f3f4a3a986ddc4fda6298efbdc27e187fa1a6d17f67b1f57d19d85a98985ccc7e9a2b9083616f67ae42c1d825121d797b09b308974d7b0f6e5d0730d3dbe0b6b384749cb09fa97cd87a8ccd3605c8dd0cb74c28774819cb6af2a8e6ed5e397a8e7f6f952f7e2b9ef316449bfe531ed2c9cf4060da6d895a05511954c01b6dc4cd5564338782418e21b4b6574f645b87197a1712295499076204ab4790ea076283e038d763f848eafe3aacb1e81aa3d4844ab9b20662061caa860a42f5cfc00d6df651f4aa5d07162035b02eafd57118ab25fc03b1a155ad6d91f2e0813505398a463c9ad6477f46d56a84119a8db340a309ad08ce59d594f2424b8c0de0a42c071c99e30b9c04ac68a244a818ae2e6823e5d4aa674bb9c9249b7ec00214763491cf18940e1f0642a11f2cf1101c736e2212cde2ca776cf567d1ac0cb6613f5df45d47c93ae8e3e0db8cfcc46899a932d43dcf054f737289aa1d09001972d74b347fc295d848c0630de0ba31c0a0cba1447970c0878ae11f888bebd78a59eb3925be6256107159f409fd303f5bdc7719cea0d67de3b14826213742a2b92fd3016bab91f336f74054fae0ecf511d9f7d2e37ebeada1f14201dd6aa07af5c562568dbc0114bbde69a8297b716a23385048c3c219f248459980154cb001bab2ec2346c1e24e81a785687c6a38f7e04908952c425cd37a7d6587528f898f785b6cb842ce45a6be11cfb39bf7defeaa2dd1230e14e83472c51d26639ae446b2080c993bd63c4744d39a6d84b8ed79c66091c0269134897e0d19e139c9aa6172103353e771860726920ccfc0a301d59357fb083c200e458a9e24671ae2b41caf7bced3fed9bc1637a6b0ef440069c42c8327114c8aa5277371861e7b756a2282cc91aed24eff3ed4e0b0eeda8504aa02531d3604fda1e6f05b41f2c811849d", "344519433c2309b2295e7c3a00d70f7e11502878538dece13cc5be151a800ae395649651654897f3afef41eb97f97f17a88382a386d7395d5689794dffde2f81d78ee03c7d87e11411549126dd181d70961ccfe4320edfda5fe51f38d884d249b40aa33060cef5e32515d131030238431a1f1af51241d2ae163a9c88c9ff3a515a81f0f3a7a64f27122ff7f426549433a8e9e067e52a9a412ef5750558524a30bb8d2c402b361bd6a9451d39e6fb2002004b7d8ac368f2f557daba266e78adc973074eadb74c3973f14a65d296d6f416fedb6bd5aff5464530b1ba37bbf41fcf8c3cb0e527c0df8afd6ef1b95f23e235e2faef2a42970d39745bae2313c4d82e1e4c5ef5973ed7cea5329b2b783afc33b0a26c5711d1af5666bf1eb108b3eac3eb0eecaf79b0c7586ed6e49445cfc60a2eddcad5b605b67c1bce1a541f6c097ad7274ee6af4dc25de5bf068be0278b62077bd83f1c1afe392a3720e360301652014939074432032495d5fb35cab87ac5b5ff75b97573ad535a7c64e5630eac4fe23eb1c21b1fbf63f0fece7305c4a406571cee79eb6a622db9508086499fc05293d6bb8405d24845d84baba603e1b1d6a62f62b3a3a27e9f4eaf3cde88a5733ae6653776954d33081ff2142976dfe1a84bba058a3ed5526edb05b78dbd9bfc51426d84a2c12fb5490c9ef61781441bae0add5dba64395607377f9af29c5af2a66b6816f466fcb1dd2df406a36924ad4c6ac2d32bf68473c6602c0ccf2be92439f27abad8c5bcf55e6c8af911408c62a068fa69fee05ba1980ccafdcd3c6b8d548e0ad2f23e66a6e5fc0ced048b8e6d4a8adf199b149404df98e49ab894259cf7372a92635356e2d9b5697c8645d3307f5ba2ec5f57d3ef1c3783b26da602f30c8e8b1a91d74ff3b0508cffecd4f1c91858572b225d7d5c36101f2e534d0acc7a3eaa57649480be9d4ef73b23577e6a08d8bb855fbfaa5e4201e261d8bd0f4f74f119ea2c66e22ea8d8a53d305983eded81953312b5a182ece0a721653bcec18f74ab29c3b3d0b582bbe84cc6093ffaa80d588efcf01eecdc1928e5f58eef2119598bcf5d0a5a8ff25b06d80465d1a91720a5866d47f47468271d31736099380c3192a2f6ad2d9e4b735e4673bfec5bb6ead7d957f3ff42c55d92632641c6f4dc1bd3ff281764637d748542b95ea0221257f1a6831cf23ee1cd12b0e5e2802c8beeab977ec2d23853584bd26bcae36b447e5881287dbd554a2f3d796a99ab172cbb242304254752dadfbaea81a22d8bfaf2dd74282336f9f0e80e89f8c5782ee9f6950ae13127492db197a644c0359fb51a6da4b98aa1d65b19439f28d0c39a9f6a9f8decb19cfceeacdadec47ce5bf3d81f442649311a83a2390e2193dc27bb9a43edd2586ead04e2124359c7ef10c17a62821432052cb8821cb76a8ba8b41e98975368759d537522bdda8c3c1ce2bb2e4da099abfcc708c1c77a94438734a52a73c3fe0880c15fc28ac97e44517ef5228b1243411c9e27eee2d62568960a9c892e355706b1c692e5de852d35dc2247789576ba9bbb6a80588c1e4aa1088b0d176eda835db57f2ff073010b10a1ed5de1e4cf2ef88432a250a8d8ef78a4974d158f3ba050ca5c814df13ceaf5fc64b0b53c7defecaab005da5abab68a097529fc3f321e6fb2aaec5041066156c295c63bae2c021d98c4be7ba4c81a7c8288f5e799f3585e6a7b82fed479ba522a246c5605898c0ffbc8dd7cda04f81cb4eb2a874dabdc94292a81f337e25b17479445f5b633d66b30332eda84f0440ffd771a32bf969745b5a462176f42b3f3a982e36827ae7f05257dcdfbe29f533bc4a4eca13eb79b550d895c187c2e675d428a0e081670dae22feb7143ccad779553a400cc32ded6d8d34394b669808df04cb2903efb980fb9c87022d18b47caf11c8a85ea2d053ae56fb2ef0a203f1d1bbfa06ae2a8c300f2e94850f3e7feed3db45b0db6762c251299bd1c39d9e2fe98b8d2038e144b13fedd4d79eb362c27d2efc6acf5a3fe48be36fda0ae2e41b31994f5edb08177b3975ef32c446a3c8583b6722f58ee656e38e3a171041b264d117593e52fc6212970896df15f566051053504eef13ee1b765b4929a6169d25abd6da2bb0cd5c6498c7741e1213fb951dd4dec3008eb4be691620c75eafef9e7aff0f5614b10095951f2e9239d4a133578ee45cf6d0149722880df21a739e35679c4ed20d1e3fe2a4ba53ade819299739f511a1d79ee03224a3194c7091ff6732f8e1c97dff2d41664fdca0576adac854f9622fe677893c6625e6de504f6c1aee2255ac74737257823e8de76547ab6d1da7bf763277862f2b68065be0001ed666ce604dcb9fa223cfb4d072f887c16c97edaf5090a2a8458481cf1cae9bb9c7af28e7dd5a4119ff8d6f81cc1a56c559d225b6c7faee5c4ebe8a4a010826ef4a2d96293b536bf667e9cb1befc084b88a0ab4b725d92fe4aa71f293b28fc3955f01a0a98f3cc911c06ff422ebe072e468596902678e8bffa8f003aa9f991fdb8aa9bdbf42687f7f151679a0a478a89500e094ccd091814b8a7fd2b0df0d4604a74e4b8ef57ce654df9245456319a1a5fda299252452c28e0e5d065f90cf1ed8b8e114a3b5061b8b2a938f41ed4637c57474d77d39efd78643caac0d9124cd1f6e8d5ad18e6728d62f0eb4bc06c2492fd2f33921debae1110d34c954363ee4e176e35ddcb9ae0b5e5d616da61ff7cd0f462a834e981099d4089490e99f7c108580bf8b1f5e690bea461fa93f8293f2cfa8e765c63929038a9c20ca1f8f280e06a7d48bb4efcce3ba4744a3873960adb44acb37ebd1f450360f99a0e68b95542f8134940490d302d3b4b11715fa6b9880cb2bc0b08f316aff75818e03f108949b407f29ac1cabeb0f83a4696df45e716e9927790c934440bfc95695ebb883c56e2f668eadc58cdc3b1d899a9c11c23c39bb51ad364f43d3db017d716f452382844ec52c63b14508bcbb671d8f9df3fa5732b064d71424f0fe48d59c287f702c9b35d7629c641915fd07ad0a6fd85c2439d0d3ae3d76fdcf934f6f319be8e030bfc743e79c8366180fa9250c813be8a8805d2b43237d8e5ad18354e507fd4abf90b1c61fb64b1e23bd49b1c36fa540d8bd576d2caf90889af18c67184864cbfbfb68208e63b80bcfe582ce2096eff0c9ec08455e4a22420fea48aee2a6bc5d7d1216d203f48ef07a3bf8ba2d0bddfd296bd76d4e97694d826ae9fd0875dc919c766d9993c9709260a5cdac806982a2813a8ec44355b980738ff2f29688d91246da20bd7c6ac11ccb8a5f6fe11f14f7c20b1ed183568fe9995150489b2975e607149e2c0a7abfb669940ab743352248661fc9f726b57bf244a6eadb71b75c4e096c0e54edba03a12b071e3b85962e8cde7b7e8f1e86fd6c8afe9af6aa10983da9f13971b5fa90ae2cccdecfdfd46128880415cc9926b5d9a5702037dee1795f27b26dbf61738541446a022d127c54cc0817c9adabcd24cd9b88d26b0e459dbc98e695ea64a17ca67f63d615011c3b6c164e8d5b7d09e09a5b6527c32fe85974894e29632762f595a60eff78e640151db4dbbabdce7b78090a4ef3eb9f421b8751fe18090819b0b9e6f17b08026436c4286eb523a81163862041c382631ce43a1e0cafbdd435ddb7e36cbbc85fd75795894c7fc8ae1a053098a544ba0dc165e0715cc3342005ed76851028347bfcbd3754ceae7f4ff3bf2f988a20ef2ddc4b5c3c2ddd304ba926be1941fc2dd11d1b0173e14e3875616df6bb42277beae4e37922d706083c6e20880cbf52b1737ec9703c2c039add24655fa1d33bfd8046e707caeeb3e6485fdb92558c07eb2f7faf956eb151c03d6c6d298d0191b5c0885e041346943f8e969d739c0fc7329308a1a6fc7b054087e01c88b7016622b41847a36d1731c60d676546c3574a7570ad337d223e6c11f3e0a861bfb90c5d194ba789fb55c47536137a06c9d1c87d5368a573fc08567b0494ad32eba2e61316e423037e906a9a41f4a988af2de31f003e727e100f3840ff26f1393f4c49ab8006bc2caf5fa0fedbd255c7d29b407e7a97479ed2f85b8f843528e686093db3fd983bbf1bffec42c68ba392757852c2c4048245bb437ddba41a1513b4a96928679b843caa034653536355588a5b3335f3b8eec7020c90bab11543fb524a61c26b862e92bcb35b3bd7835b5e9abac329aa6cf077", .None}, + {.Mul, "c42fcc0662c11b74d3a81e9d53a5d6e03ae93c9477c4f04e90ea3ac0c6f4a0b127cb483c5307703c8a0bc3f28ba8bd15a9f37a166b75aafa5896f0e3bca015d6c6da3aa1c9fe20052532d4d6c5fb813229821ad82f1f4a6ac9004234380babf2d7361ad8c1af83acb28a358e2f8fa81a14279176386b9aea26891c410e05a1bea9f45a9d6ff824500b05757ed9c2b6278cd814ce6662efa4ad9e1cc6a004288ce4f99651058394fb05524658e71b5e40ac5ae77d236e2e5210b871230f578868ebc318e2602778ac42a5396d061e6d9bc1b78c3bbede22fe1fc7cf42d470877496434defd62b3ff1d6293b0bddddf02c251dcc6d391be4708ecb75e7730c193601cf3d6f1ed47c0f6806c431637442694ac2d86cc592f49fa340119aa7bdb55fe3e890ffb3797d4accf7ed6bbfa152e1ffe1e06deba3537bad48306da99507f713a6e112cd0889cb4b829cd02ee5db77b6664fd904b18a603e02456b923b7f06487ce4d4165fa2515f62dd5b2fac6d47980cd92f9fe7ada01348b138db9b283e0cf7e8bb8fd2dc3c909c23240e5d4fb95bd909202551c779ceaa64b3da72bb95b0369280f5cf0d22a883385e79289228aac5e0dd6a0ff7beeb0adf9c9dc4834d87bbf2b032afe1191c32a40d28b4caecea0bde1ded079c177facf78b9c3d4c2b13702564681aed9cbf6afe49e0e040d4a94fdf34668ce3cc0bb4f28c9c9c162f3838d7e156660e4e3b67b2f045bb406e2c90efcf18fcaf9e5e41e35a27cc1882d8207d79e5cfc45d0127f00b27276f66dd1447ab9db15bbf65d4bc15e1aea1c3296f60758cc03a289e10296eaa601cf4898073bccced39a6627dbb2ee166d57070aa26a147b662edd2735fed9ce6e779d12db980b7858ad5880d28af2df3195bb31d2d9ca6150304594998dda7e52ef1b923b0b53dde24078000324903736220e181314438e4f01b195e888ded8fdbb3b924f01a70ac16dbddfd25abf33ea10620382fef0a9a944c946dbfed2bb8223eba1426c5f193bf963426eb2e6a4f83b851455581711fee7fcfd4bb47867f2121ae883fe0923a937247d775ff66bf8cd8d802694b73d2c88f9ec0fcf93be958ca06e7b6f33ffb24ac9236e27f3fe4d87caca9fb333a0ac554ee9ac505fe79ac9bb90bd0c977742bfe4f326eff6f22ad6983b4103e3bb9b879fc509fcb84a99e4e20c2ac03f1aae1b387bb6f58092edb3f26d75a4606952b80d8624465fd6da7d5fe19d138cdd52ca2c7f1a106903895d11f502f50bd01f100e99362d5c3415d388dfdd0251ed6d58137da3ee9b532270b48ec4e9db76251e08057b9a8b8d3ccc5f0467de8b1071bb197c84edce722dd94ca308c0719e2d855676bb6e6e745fd7ce198d09094e648085abe8e861f8c856afb5c18565ecb410e92282abd1974faab3a952d394383ef605c74bba49ea29736db60ad8848d8f318403ea50ae7c27e08e1f4806037aba9f7a02fd2cec8419355499adf69453791d8f4f09b4d4b7ff0db1255cca838586b379ab60df8323b5c6faa9524e0d58c8584253852f0879f0ebef3450e78aea54515c84ba7a3356a59c16d8fd34593979168053ddfd4a73ceca73b7a5d799ca42a1572b4879f3c9a837bf85ef38bc2ec3b42d6fb59b5923562fd4bb7c89bc8c712b5512d1699bc277507d1567b5e8d28473705374b2403debbe80d6caa7bb9dda64ec28bbd31ab16f893f7800072af64b16eeac0cc42cb26b7b59d2d19bd9876cfa40bee4dcab4b403a7d6f71099ac2a986d264000c72bb86cf250b5fc21e698fbb7d2225bac2210627cce6c5513b7d8885e21d440fd2238028cddc5fd60b2dc4f11516e0b9e115a8ae5da020f7bbcece3931eea7c7ac4c618dee23183f0ee8586e32ed442699ef1577e63995174cb6231af5c2cc365bbaf6e73a9d36e16939d4dac8d97eec6f5dc63b0fd6c370633d1cc3c8d653a8b282b167cf4aee627fb47d829fd652b39f70bfbbdde61dc927eadfd716590f7606ea191f4335c6921d72c44c9133ba29cfa41154b03663f32309727190431c6d09ef9b2170ace61f3417b87041ea1701c68bd8cb6d22cda302e101f623ad628614a45f22556e505a02f929b93085113b3", "b87b0a0199f29e5c43ee43865c9c965bcdff36cf2836d64f4192a98bcd0e6578b8fc31a2bb39bc8157d382243da23884889d467ca5b09cc3310176ee8f468a10e3004565db2dd3d4da756a448da0742d08a8a5e569b8a93112dcb01b0d73ff3044ceb7953667dec26905b5ebef679ce8ff470ed8082d02cfd5525bcf47b9885d03f30e3f2c936964525dc9e31a7c3145e745248bbb60f832b5c6e0b6b350a7fbbeb2546cfa018b2553597ff54f6626bc6cab2aceb90b4bc95f078dcd92f4d3491a9acf82b6cffe82ae7310a6a1d7bb35b9bd296907a95172fb1719503c358d4af3189545b43d3687a534dc226c32898dcf07d233c394d330d346b0a61cdc40e64351e78d5c0829d5ed5d6309c9036e9580673e5b6a5684c717a019704a179540ba28df3c6d6e5ad8fc2696cfc47c48eaea23d28bd208b38b22338019709329cb95d7bbc035aa14dc4f106b9838f3463ca6e85e72d07ac689898ea42e700556b09feb05d47ad9eee872bbcee3e07dce6c680e6f8b760a6d21802bb17a94c817993304d81bdfb845d84981adf506f456572b1290c26de1591501e3c69da549f74484158585780c3a7ddc8bed2db5e0abd634fed4f550ece3509847270d04bbcf9679952711ad66f385857e62746a92510b23d5751220d1a58e8e7084884371fb7e4273ba0b93379e5972de6744a3a756ce846e0652d5add71f7c024457cdcf7912841ee8eec9fc7b649a793b9e9a4c760b789885ad985d10129cdbcfffecef1600dfc8cb2e50329f5f547d3a83effcb5ab5e0bc328e6aa72bedd4174e0144871e8259cdfdfd3f95a492cf76107a4d9ff7cff6cfc64144c51020efb8bacf85bee0b79c7bd93fc869646c85aa34c1c09870b71dd59340aa3f793c8d7c02b4cca19a104aabd8214c39b14b31351a87caf7214f23bc0d78435c26fc88db72a4c56ef50af17cf53ea36db4798520f2a4a6a4b0e6216a6f774bd522b49992503a3e6b71d76d002b7513e89c287e0d08064d7bbb61a4a6a3f42f77d16a787ec005bf8888b0562767217468392af3cf9a53c937d976ab8b1778a279b1cf8036e7f4521cb521c8e138869cbfb86deb36ebae5b160f7a0674ae705e483a94173a0fa09a0754b39527c97843aab4d9f5c8b61ebfcf7683dfd2d0262e0bd74c79f61df995f6d83d3072759aa5e5b2e708b45cd9d858731192fe2a8b5df2b7e9df86fc205f06858c4a05e7eb319458998f7de2409105b2a41d5a155af48e38ceacb77e4ba75fb7a7fa59c532ee6f1b6a440496838386d470f332f7ea5c175c18cc22a05937f3b2b41596a78187cf6d5cd522b4781b0a8e168d6f6e8dc4ef6d527ee6b03f34cc8c7bd6f457663af1939ebd66c7449777ad1c5377f3dab29d50c6e6381af0cc7f840eab214e6cfaf78a10045a83a0cfc37b8f9242d6a299cffc097d54d6bd0b3c3309b15f8c3badc5cf4b60cbe4eff675674070f713ccbd842d6eb7c51f0bed707102eba369c128c774174bb4d1503c202e48cb45b643783b584bd81dbc6a9c4654ecd8fb52c3a9c165a2cb35380c91f42f5dd20a16a2a665e54551540be1ce9d94b07e5c1ba045691a37f30e8ef4eb40bc192ca08191992244bdf408a52770535ffccaac6d04ba880aba996a5b139d84ef66f56618dac488461ccf5fea9d8cf43f05d6c393751a60f512b2140e24808fc8191a5293303da1500bc0a613a36e9c64c9bf37128282707e30208ac752ee621f7e817c30ae46accdb9aa495dba83f6ebf5c1f256f3400e70434b6853887e6c9b302d937e6248c4e76278325f8ed4b4f06eed2f3d2988e8558ff2de45f2ecb304b00795fc34a25bc7d8354b3900206eba52e2ebfafa8569f87744f9d3da5607d4012ed32ba95f3d5c98d05eeac89ee457ccd28f02f09d95c22137716c8aef9f75e3dc150b55e0f2d3a03dd2c8de3dadd70388600944df8dff798a05e089c2b1aaa628f988091f41f25a2d600eb7c51ef830e7ce89a4383a142527488a53ce685945648c34fc720dc2af0cf44503ffd807920ff7be45e6ec44d12f3cf3330042c12b83674397d4b9ff0984d04ff190f159f851c0faff5828f03075de287a9bbdc29bfd4f4406a5bb058d28ee8a4", "8d60a546b62ec9e0fb4d554976042d6c523441aa4930a06b01e30e2166a2b6cd8684135c4cdd1a1f0f5821b8bc2bb429a35477d698450d498e4ec54c7c9b812b3942fb116af2098294d728ab13d8e0eba940023c1551d91e55310d34ae0c7603f67f3f62d0b93e91cb63f351e805b0e9cce6753f9920e354d165f54c2cd35d358bab536edab362260ee6f03c52205f5e43c2291ff570c789032fe4635d5ce5d1459c11f23ffc8da866064bd43586b771e7c4d76d7914f06ac874005b69d5b59d472dec810d55e6b49204bdb608954f6802d5cf16899d3026541dd507ce8fbde9251a65acb530bafce0ae801c992beace83294cf6a2bedcf32ba53aebfb63be31379a8e54964a87d6762a405c15ec7db0e89115a008a88ec959e881ffc6ebd1a057dfc9ddb3e14516505b9e8b3ec406c1968b45b25f9112498d7576434d0b2b10b58aedaddeda81b6b06cc574e99d4bd674f4eee2b0de29b45394ab1799a35cc0c2ddddf4ca2ffce919f6bb2c051e0bb1dca0df92defe52b4ffc71a86372cedb5fd9ca5b0fd554eb4055235c033b968fe593ed65f1baf54a8c62efee937fc6f88161cfc73dd677be045d65dddfa1ccae079727d645540c39404a824f416bc8f8386378dbfd202a2fde3008c87549b65b930a951cde5a08d01796f3b2e2ff0317ebe0681dd39f33e4fcb74babb6084a8f99412073d71d8c47177587b3de2f5745dc6bddb5d316c5a642e758f40ccf6116b4ea4e36d893a864defe3e9a72959e435037af537037bfef25c29a9410a2cb531c6135424accf33f2f7aeea4500e2724fe14c57ca76fd5266a6898a437b27de1931b1edaf553e9da3dd22eb6b7a7ab2bd5e990a15a528f2035ea4ca30f8e08cfe5ebcf3ef740294c53ce708cc683ba555cca49c58c17c98950a604b44fbe56454f1afc1b0abdd6b7a8e024800c7839ab974da94f4cee99d466abb299afe25ec6cd32936849a63117b992d748175f134e8679ba8537263eec9a9c5cb414d704e305f61dccb62e0d2fa1cb7dacd078f8b9a341a076b96b2debaf3765661ff4af1e12e0d1e6451eba306c089a805836d39a942f4650bf8c7cbde393c4b66930acf8d9438ef4bd24569f7be728123e37a5a5b927525e8ffcc4f2d23f73714330415feb20055a611d4f9bc591936c0e6129747247cbcdbdc73450c3887550f3d1dc2fe83f0669578caad6adaf6ca0d0e4f03830625d0df52d2a7cc4105ab97eb215ffda95d69f35276e23a10cd414c2dddb76b02d49fa430e9c879e6092137b539a7f2f05275aa01aec47168278b750798d0b5d7d25c84c4b4695b406745ce936f6bff197e3aa1495edeac5bccd857ea01b50742d4ea6c2883ee6288817e4713945853f20addd558ee9dc73d261824d3518853d423c91219217a7aa765450b394ba6b1389e1db4efb099e00e51c09760e761a5c5ed415c905f343e8a6ed163d57d62731cb6116e4212c76c629e4b26cddc87ed30a495c77f7c598a0daf2d088f223fbd64e47ac3c6b7f625970059109563724782b54f331ae461467111d79d55c6356369833d652432621187dfa3c405c18e2adaa0e89d1ed225a65676b7bcd3238f7e99ac91acecee942521112ca223756e17323139192d040ea593933d02b9a6241d0d6c749becd21868d7c7d57b2901722add7560836edbd85079d85a3986130088c64290e004c4b67851906972cb6921bf1cf47a7a5bdc0b4f984a609c37a36233efda5f85f4511d3c306f8a6ae1b7f92625eef54fd04af7677b8d9259daf81b58c45f45cdaf6da2ce25fb9964da6735261c15d154e68be4cebb6f84574d1e0da64cda8e7d17670f9a0c842b6760d3a7abd290ee7fc929aebc0862eefaabf8c5e273b65d6965b255e8384d1f8107812d69de2bb0a4d4f52779c2c38217091c475bdd86e07a1f8d771ea37c13d6ce1f8da322e3cc2177dd0b934de9142b4367894426baf926000f8de6e69dda1b9526153bfae77cdf1e06d2dd2ebe3dc80da82394e76fc04f58949b3f2df0b9236bcfd220f270ec3d90194132e1ecdd62f71f5fb2829b68f6cf4501e919288030262e0cfbf181af05d8629aebbde7fa0772d8a09a7e95cbfee983b7f340dbbc803ba1ee2e3b32236ae69c435f64ace6229f135630dfd278a0439de56d2facbfa6e912a3778158fc27055e612d0860d281ab5f7234353a09fbdc0a3cd375e7afbbf8d1b9450215eb61a8231d40f5d78d27d8ffb3d6b209680cc581a5684d89b46d58f3d5d72eff10c53c9fcddaa4575282b7d06f2422cfe7c61bba01c33fa9522e6876e01d3a5cbdec2c10440207a0dd9d3c15a7d9c7a7c8935278cd3befa65cb9c88bb08d0771fc4fd74cf8b8018454c5a3c9e05d0e4f2d44ec975f06f2e90aef91013e85d9aaf8119ef207550ae7dbcc63aa89f0fc906bc9b8b875e1e5d8724ff247a6dbefe21389f3ab3fbfb51c10bfa9a5ce5ba5426e7dc8cb29d56ad6acbe9974dfeceedc23639100c0b332859881fa4d4ea1622a0acb9e19888e2594029ddd814880b38bfde0a8a874f4608bf8153b6f6093f8ce3ac3ac3d9c37d664c58d0bedf1089139d5babe2002c7fae032d581290611fa9f6274f2fc76e9c04538fc9d442f135679727a24a4ce5fc4f938c36b45c8eac0d222c30d85cbdf48b7c9af44749bce230a6ec263440924506fac9639be1f2c7d5c8bc2fe0358d48fe62aeba81700b20d54ea6aaa6be6a0084178cfd6d7a421427718003a07f605dd1ab90560b84f4bd3dc57c099c350ee564479fa5e8354f24cc6e846aa28d71296e317be75e1ea8a1053b000227013825632bcf63ab7217f732e9f2676b03ebc9da99a9f63c1490f99a34de9a8c7e1a42554837ada25e805dbefdd3a918e45eefebe407c40ba5fa79a92e4b25dc5c1285064737059d9e22566c48819f1232d4178d48af1c45c4f3c797177ef59ac6ee7faef4edd3a252103221d31790335a35ab1733514460cfed80146b0d25a7bd3c74001009b2958aa0ac3fbfb02087db51dd649f3e4f4cc0913a82ee434042fafa0a251497896903b2e843c10ea2f4fc8cbd204be96827e2f586f15e44d9100d1bf4d876f8d7a9a2b7d5af7feacf85dfe6d2f388f4daedc19fdd93bab3a048526f4d910fa34570b486b143068f59b29df5b8b8d7ee979e0810fbcf17dcb987a1594bad5d021dad648c4d738654271d58c1fb937df0104918883418e2fd4747ed4bcd168efee7ffdd26e5d82ac28b490ef59f455d0adf2bd933745c1b74baee03c9eacfdf2cca2101a38b83e0de197b3399000bb3388206ee4fea5ca1aaf16933680d3f8a7615c7eeee6563f8c76c04fc62ebb9a82fa0dc02946c67c65ced87a1dcf48ef5ce08706ebb0c2e3ef4fb1f4511803827f498cbd0de890d458f43f258fd2fec36d0364375e3a0b2598cc23537d7ec8051f4168f232857a54d5f472cdbd4b527b09bbc0ca4d323107084bd2c4dd1de9fb6c7bc1112248cb2e988437e0e6eeee40bb121e0ae0eaca1dc5f62d168bbc0f15d91a2e8ca6fe7a0915c9b78669a7f3b81c9855df1c9a69a6decf4eccfe52a8125743d91b41b5561ea531f50f845490784175516dd21ab47fa67f24589fc8bf1319cc9bbb8202381e4f7896a89cfae19d66d2064e5ef9cb13a091a13d8a91b0668b01c88b79ab7b63151987cec1d2127b81eb552b7090ee6ca925adfed52cb5fe1b955ad256a61ccab5a27c8202d286baf85021a36f9dfebe138c9c28e81d12fd1f2f5bec8a0eb27fa9dcbc89c35b6081f3990087c41a2fded44079b2c70e0798d24fb505c973be68d62be4a6400c602185687ec662d9bf561ed3accaf2f73fd01f761fc7c7adec6fb1451fd5072982a2e798e82a6ab72d2b30920322217ab7a7cd2c865f6059bf2b6bf702599dc5b2dfc4f9fec93f7fb311f9c9cb5e01d76fca61ddf9a2382419d847df038f592c6aac9102c48cc5c25076bc240a134a95eff6b2790dc45aeb68a8f6385103cdea8c10006b3047c837fabc09c1154a326ca27adb795763bf7282ab38c9c22f1bd610a28e3ca5e7fd085ab41e1f10b5e9e790f01d495c8a46f66b15c988b8c90628de775fe3b5396c8106741aa2b4b61053136961d6d78152c23a4f9174f140c40940e5aa1b458fef94c2e405dc454cdb4ce2deed75b54853b1cf1165013e555a22cb345b12fc078f2299497cdee8a3221dd22c45b329f493772a59ec1ca57662934b0c1ad04a090ca8f754de649114d6ac", .None}, + {.Mul, "-9a07f79dcc92683537fa146a8df7fefe85975b933498c7dca5ff96c82afc9d8d6426482354b8b2775bf562665835aa797b8b848178b20b70b84df6899527bf21f8632951003cd680db85c8593434379612bd22c7153649ae9ef9e580a1c2c85e87c78eb661e726af6df506eacb8fb683c1bcaa1f4b8409b6220fdb74c476959ae2d2ebdb65d11252af7d71a99e8c783cdc6a2a7f5ba28091272227072fa171b9427eee6d5a706dc9c84f401da79788e55464a076c8f949426b13c54ff2f290ef7c84865e31a04202b0071b27c039233e9a36a1975d3898cd71c2b83524712cefb3b3b290e7e80a70500784382c5b4dc7051845e84d76ca66efb0c7914b44679461b4633ea5eb233e9dc1fbed3c81ce39c8aa58ed6bf2eb66f11befb07f93b40b50d65aa90c12497f045551cd3d65f772b691562806babd0824757cffa2db0135924c471e317caf74e7160b9d4b7c81dd464ac9ac05550107f7960505020b62a9933e186d472c07feb603b61a912a80ed0a8ea15cbe37f7d7c8ba417479f5106b417a110ec32040b6c21f4791c50d994691dc670831722cb583fdef837ef3938c57fb4dbbc40197d92b12b5ef6e2e535e08cb9328020ab409041e09fea358cd87f8ad2c9973e0975141f0a2ed393be5bb0c90325e41fffa99c177aef790181545ace3d579ceb07e4b5a830982cfee5a5dc097929b433738aac430cb221379c7a534a7b29c3cc756958befb661f759c282ee556db1de5ed13a0aca160d014b53126b38f8b9b274b9d2a9b3f7a27eb68d9cdf51e656ddabc201cbb1c39ce75beb60404a6c5d4576a8446e45053b98725b7db5fa8e09ce490c95c866abb4be3609001c435d921414eb2af9d46ec7d49800c2d8ed04cf56440dc4b5551bc42bcd63a6b31c98556c1a3f6dd0e4a2636dc0f011a8280ac5f617caeaef1e9ce5e9e2497d6e67bbb39ea2e9cd397052aff2e329795d86310e22db8954895c692e2fa42dad498f20e8ac038b6ea9f92a3e4c889666229967ead8d850486ae0b8c2855f5bcf327d3860f279a9ac54d759aaa3e96edc7d85055f7931368a6b09516329ea13cd5dc58a29159006b165a037c26aee6f6fe776685f1868ddba46034ebe5dcf2c7bacb94f1fda2251c84d99566692ef2fe73095db260bd03849eaf2c8f52e0e6ac4756a3e29366d5e44344fff61bf0c8ab358f2d479e29186f4aeeb9e45f55e0bfd2109652aaea07684798e33e07bcbc03bf033dbffe75069e419139b51f6f0c95d2fd11071c6010668e240c16a0b7c2b20146c3ec87b70091954a868eaae5940ce5d5e930d67e633b968cb5c539aae271aef29ea9ecef322f5de23e53075bff263ca17e2dfaadfa6892e2dbe4c2071415ea212306c33b7985f983ff84621ad18937d6ec0674d7aed12baf15cfba8561f2e643ce7a21a98079d48889a7327a6632462cbbbbcc535843267792bbe6af3cf9e678ec053d33a731abe33582c029ca8ac21149aabdf24c0fe6f914627709a45ac453614afe1cec482e24d4064cb4f6ce78b96c2143ca099440a419f73940b539695236de0e5ec22765a6b27cd7dd00a4852bfebbe1184b5522a2b20709d844eaccfabaa472bbfad75f1f3238f76a7ffed38c01010f69251250fbb5b25e16ed90efc8d5ce1eb589999b423ece666ee8aa6c579b37fab56e3933f084e8bdab0a8ca220f11d9ffcd68c338a8360d60bb8343bd47103976b8ea5a1fe11d4cae6eb49430d8d197bf24cf8fe5c52adb0068b86a92e1bb53205843e0abbbc1d914b0a18d0741d124803c50f5c60cf34fb054686a57b536f4173bfaff2c5db4bfec70ef4d26c4dc3a906e982a727946c43d477dcbe0484c928001c9d6c9548c53ace61f1ccb298f62907a58efcc88cef4b6cb79f887fde67a174ed2d1fc593e888fc1a33360731d1e61488d4da9f54ca44e601a6d78dad80dd75b95c0fe9d05bccab7486d2c9ad7d5d26cb0dd214aeb7bd7ae9e21248bc2cd4ad0d445bc24a68f3b2bb154bd2fc1201eb4c7273e23a4226a365117db1d3eb2bab491faefd6b8cbe3e4081acd2dec8a07c1f190bdcb02ab8aae4496b3368a02e028da6d77b85b8f276371372352131645294de6ec7efc53", "44725d53be0d1a8d6b24a9121ed355eb00ea2a309e3b037b8abc3fff54ff70fcf1e11621bb1e7aeb12003bf7b518d9c075a43d47a9974bd616c71a2c16abeab95a23a604999a6c1806e013e0fe28d6b2cc7e05a44ef03a4c788ef1641d9b7a69252ceb03406036575fa1c352c82e380a555372a6caa9853cf2baae415f0770ce9735c9a7c017f190429c623563099d9ad5f51ad3a25d6f9bb686d75dccc78e4a0cd00478e0ebae2a4249491e5a454f29cecdd704fb873539f5c5498327a60b21a45e20e99bba1519d61d37834acc788cadae00d2bb40f26373a42c7d421cc6ede233e2a4dd8da2a7da5b4b7062c5968aa2162083e2654581cd47a4c0148bb0a5547a85328ac882ede2e3448b5e530bc98ff25c2ebf33b15c5b0cee131929a6bd53b4d0f177e5050a8267a59d125c6e275d1f961b0ae278b8167f56b84cb15f2a31f9127131fbd6daec34dbba7cc8d75bf4900e41a4a0656dcfe16269e517dc0364b19b64b43f32ed7615f6e55addcdb2cb85acc3a6e80d02c0437c96be2d2f435bb98451b3c6cf6944651e007d71b31b2de35feb99725ca8aeba7b1537af48f9431072e76255e799a21008b3f723bb3a196f004edda29d03b8a2c86ae15006a4510d67d621a907ccf2dfc507fd52fe572edc05ae6952ba363e97dbd21433a0b72f874b65b72f1759313c5c2bce8dac72ac599e07788ea87561a35cbc6b33bab3b4facea62cf78ea067f38f387eaae8f6f7ed5e60f7b108abf99acc64627f48d682a29fccaee5aa95d10538e37a5b40ba1e326c1b7e790b82128acd0f40cc3cb72965e605c4b56d4ec6c3da46046fae5560f38cd3ce8775e0583fd0804fbbdedab41da95d310736359be0e0e59079dae50f36c70ee139e475c8f13abecb8c5bc8d51bc214a51e5fc3dab204df74ccf599785ad6ec597828e007f925c44b979d9f6abe70a6854a5b892fee6c3b3fb3cda702fe24f274be3fd1c3cc477fde193765eba5b1ca47d330e7c9edb30e15bd913f22fbe5554dfa46ad5f206dde922d9ecce3fbc4524d8357feb541533ad3cf064f40df3f63267d0ca332d53ef202dfe3db6191e07e60b05a7a8b5b14a765569a29a4c86fa022da700c2e5c49275c42a16db29b671afa9e3635dfc5a40824315669d61d0e153d1d7657ddc5767c9a5cc0dce56961904d257fbdd6c9b9194228720275229c882acd6f6ff91ee9beb8b23fc5a7e2d73a4b8bf5b62825f3091f8adc3ffbc4a33001e726e82b62f22f1eb34df1ce05677bc22c6d17bbbc751c2c96c3a298da7ad6270ee112400af5af98043bb5dc31b5bcc6ea9271cca26d8143da58dda59e1db824a044761f15bba75cc8976b3045146902165196b9916930d098e67d2b48bac92ee649786c37faf7665e97acc73839f5f0a68ae4bbd6ffde43a744871fb2df95c9cb73b3409b85dce117b6ca8c9d2a726b3d2d9cd62af714e25f7dc9d4b59ebb37866eb8213c5bc41d29a7e291832b0d094b9ddbff83cd12460551d9c2cbae01b7b1206b24d37a30fa769a46c30b190536439e0930bf231257ba5e46547259a40425ad7810c4e730b71cb95615d5efb59602d190da0407d96b98984ce70dc307c4153c8d28abfa6f51ff65188ed9a7c77687a179ac27d9dec1d044d9db927bf2119d7906d29f27d4aa24150eed959b2f952dd9408995db4139ed05860752ecd3a70c1012826a8fa990864e4e848d634a99ab68801ac9a27b5b456c282216bfb7d0d16628b9ed204c4d34ab891cd387c95409b3417e17f415e8a2f0a270cbba68c6b8550df84aeb12ac56f6606d527a1e27f69595db958821362a567db498c9c6f50144d44c4c1a5848de03dd0c7187a305acbed8f55d92a53ce76d3eb663279974896b05cdbadb740a233c6deaf35e2ceb6b3e8d8f0426e37e977adc690675eee876713cd3051182844ab7ec01c536035437d10fa77d1b525901a1788108a8b3d1a001b42da08a65dd68bb25243f03e9c6c7f5c213c3f4683dfd1aaa6554b7d46b047e0bd1bf5963ec753f66f4e8d0feefe6413f4150c9b8c23a5ff85aecac7cefdeae90306b9619f7e4af64a54d220e12205c41041903b7948914d9ba06e882b911832c46c097", "-292eed79767f6483a4bd522faa654eb5308a627545cb7db735e6bef850c7ba83571b33ee2c6e122f1cd09b4279b5ef02c1dfa54bd8829589353dec4b3bb755cb763fc250009286dedb3cab96ec52b9d17d314025b183c079e6421bbd93e4e7ec688032fb8849f21144de7e72250ea20bef46f6defd8af49a38acb23463f19aa3dd7eb9477a28e4595ea9ec3bac1e36c83f332d9e82b83ec3bc57e5fc096ac91e12c1c0cf17931a41441b46d871f9805ef182ae98bcef86e82fc0bfbc473742cbff43c663f6b9be4cea901ba9781a834e7714422e233a012b07418595506cb071148f72ec7294723ae7e3b373dc9996891f4a3ec340fccf247560e66eb64626693cdc4281565a0a32bcedcbbb96f20683173e5d655a507f60f03660086d9f94ff160c562e2cf2478ac112b50c2d9ad2a1a748dff9e392c9bd20079ddbbee73ebea981bd8af5dd6bd186e38fbad9ee5238f71df0b85c70b3d7a97d180e15609f7ed19ce9c3a148bae20472964443110051ac160330178f00bcbe6a10bc7b8a84b7f49dff4f6cf5ccf5aeecfd3f46cb527d760861d24ceca9c76b15848d828e9f79190eab5e71575782d7dbaf25f206ab830e50527099b01ac5ea7765e4ef746494888bbd7a5121d996159424a2ca85f32748a7c0805894abfa978e8434be87df6ebfd626f7f656a10c50127a7fe6db0138eca9260e43a002c702efea1e29d15bb5772f63e6da2550addbb1f7574703fb5971f4feb7c36b65fe14318e90d1b3fa996f8037d47af51c04330c9386d877bd851f8b2043df88524adec2df500123fa27c6bd0b15114c5c6ea2c329f599d53749ce5ad53ef8cb853ec45608464cc1103b5ac7230e343dce46ac1747da21d8fb482b61a819a13eae29b0d202e7906fd18564f7b08001fa3f791fcfee89bdf854e4ef49ca4608c1cc0b49e20a63c3f26aabc01143c43306a4ac006572e774efc3dfcf1c87f89a485dae4b2325dfe23e5258702317da9315f13d9df8ed1eabdc8d745e574c265c92681a980f3fd63dcc5fd7420c13417733ca31d3b9bcaef3fe93d5e0aaec3cfc424888241b4fc17c50a3a13c994949b299ba50ffa446d91f5d97651514da21d36ed3c6de20e9f95973f706480db23207c58ad33e32771860419d4234efb5a4fedb44ed88b603ad1cb8e6323b18a40870b83c218880ca3f884014cf1ddd7a32d970755ee9f1c5caabaa72bbfaf9ee2139ad00c5df83f1022bf51996e5db597990948f9910368b3a103ded5a6c6ab32542f16b468b6556f18b740b28af6d0979085a1ae9ece8c385ef9f6b7132b0368f4e0c40371e5d9e3d9a55acf02abb0713cacb3091eaa0693ecbaf03bf8623da8787bd62b5115e379f493dcdac354b5cc39a2d0106f372b8d06bce33e50caa663a64d8af0f9b0eddd9fdcbbab26019bd4b23e25b9d7c0359e128e9a5a67022de111e92c719a491cbeaba580854c6ff1339246f88f1933b486bb10b9c2daa72cb85a630b34c5c6c2e8655b503cee1bf6524a956adaa145eefbf731acd1daa521be2ed0e22885ba8dd4e2b6bcddf337c6e245cdbdb8238028d59570ff28102eb09407935a178c5e5e01445aadb1d4a6b9ec90a91e8c45fa219f9b6adec5c1077e155bb0819bef7b866341f61c15aefc25c977651232145b739266d0033265b65bddc5ead6d9cbe12d1f0b602f88e8a50432a9e696bae444c3bcc23c46a4cc77998e426c1919c01543f37c6da03bf5793920dded99db8808795a424e1e02565665ca7db23a901139e1b3053e0c2583d250cb22cf2af51275ea228e10db72de559fa4915913cd5317a45013b662c64c6dea2b75423c1fc10f2e02aac1c6634dd74d5ad62e2ce9dd3e3a3a9f73ee404d8138b23ed931bae87622f4564e4bc6611bde1d7a61a195526d5abfda646e374dcfc65c11aef6c7704fd4cc0a24810c087fe57dc3fb05a0d1b49683ae27d4cb1be189fe2624e7f38e5df12eeaeb833be1662c0a0d80e53072850322ff8ee71ffd496803b6173164d51fd21fdf23442aeeae0a5f9228db340457cd49a94e047c825f361b5f834fe4c0ffbdb60e9fc74093759c230cd77f82b2ce23ef2600a8408c8e9bda1f867e65e90f89dcd0fbf31eca27787a78a941fc05874a5668cf8909f5b8382720a690688e3cd0aa3dd27d6c44c21ccc46045cf5473e1c38c281bb6410e00e32bdd0234581f3fac856980c9f6c416b675dd7cbacbd835f7bcfd6b400ddb7c3750ca85bf9b165fd0665c6a9a1b9992f5051ac28f5993f7e704e96286edc386e421bb65255d72374144c85d998f1faa5d36d4d62864de4e33e53f9542da315cb101f61069c66d4407da7c1fb5e7a2359852e3d3068da37315dce05b2a66cd81a0d3e6370f4952ea6c8fa615b570a586c847704ba7f382ffb89322c18e6e08017d5a4f0e7033fdd25d4868993e1d2dd1f088e7a82c8cb1fa8c2847fc1ea370cd00156f8f66aa8b19c5392b3a91233bf3fee5c28cff56bc919e45ab2085ae51fca84ac8704f713e2ebb90a8e2be79cbcf2994d7d65ea4569f2f5e091451a4991f98b9dd9bc8d036b4c1c86ab3edaa0f8fec025a87c189a96858dbdfa7f4702587de8928454949285866d4bf365a0a1d20ea1e286e953e090ea1fe8335bb9b99a1f1598e6886b76eb1cda728fac09a1668c8c4f6f9c57eaa424bf0d6570d7f2a927cd111a58e345858d61996d66c821ed32fcf337e9112ff3b9d5ade14fdd6ef048438cabbeacb006e96f3aaad83e834b4531499ec9c0ff2f04fadbb9bd915cc1c936470f958e615008c25363ecd5e0c689d23fa0aec4597657739d8438d1474cb9d4a8465f3b495d069b0fb9adbc40ce7215924e9d607f7474f243be63d34ca83e3c62749a65ab1ac8927213500de782be42002e2dc0037ddf470c84ccc5d60f10a9356835e418e2e7ef78cdc1af126a5836d0c3999a9055be1ed4078e5bc313b9f942650b5ec413e2c25a030d72d6a079450591b1f3f8d2b20d66329df70a2772afd975a9bd76cfa55c938593b0bffdf69377201e6f9c0bd19e15008ae81149e16dca6b74e766041ec12c49ed25cba4e8f76df5fd51beb14c65af8708ad0f2249d917b22a730ce6df3713589564ad4d9d11a539dd37415c531ee211a8b31657e750190fd55e616cae3141616de1fec96d625d742e69c9a854b4d5d5ad107506fb7819d9dab65c4edecd1641fe05d2eed49c9b0537dc242c8f15cb9f857cccdbc1efa718e145602dd3f7b21dedc96bebccd048bbda180288b91b77a0f9fcb600e5e1c89d2c4fda42105c168ffa9aa273fc2c43e6f10bc772c47eb0328c1003e155a1cbad8f5eab4eac0e4935027c5e24389a0484b34b1be5f598ac366450de8f2bd16fe3b7b785f247d808d8500562591f76f415787c61427af14b463f1b150ce30dacae48026ccc4bc2bce3842dab0c8decf43f794121a5c28957c667f9c893240448c4235b7a4d8cb999c5b07f116d069a277c0d7d341afec23f5027372834aabc172ae8e2159c5b0d1d748fde6a235b5b532ba508647872f97b38e910a8c1e6248e82cc064c9b6d5f4d08c721ea5581d14b9f81c17e3da848ed620295d117deaa165935ec6585857a9a14e5f0425286a63d70ef5007e690e7326d87133103e50119d02f4a79795f7855856858ed62aae1e6b6045f643fc71f6ae48e7f4fdb8a5ba5f101ecc9633f405c3aa953bc4de6514caed8bdc2828dfacbead9347a26d98f7c9a8463b0e5905e5f019fbb23a66734464644ba918234b3d1f5bad4311cc15cbe0fa51d1f83bb35baba78c35de1d089663af6f5e99fb9664c2cc022a8e6311dd2df36e85d9a5b5026dd7312705dd47fb527fd94002b8340dec8b98af501381417092e8bdb9b35a42e392b4c15abc9928cd17b666fe92d770249fb6582e8a7cb7f2921c2c394044d4863713ea1a02510db62c1cdc3ee348a811c6b51a4f40d7bcfb6feba94c8a1e710b0b3e734bef240b9f8b4bdca1dbb405016a35869fa01747370365ee2da70eaea4778aeeb39639c2247cd3cd87b2342dfff61e5cf805f5f1fc628794d9ba7a4b001a548109ee3109e988660a9844b307b62dc1d5cd1d9977dd5b038d109aaa5412dc5fac41d49a0a3374011a0ca38bb763220a7d52cff7576fc8a9a8b6dc3b02b98303bb8cee0b43a1bb6d7e7f1f6dad163ba18ba8fe52e8d726755abbe9f9b6259e2343c62f56960c576781a3b5951e492caeb54c4424fed714f5", .None}, + {.Mul, "-4182bfa107c5fcde84b4f3182facb14ddc54fb9eff7819a456841f414a17ea2dfaf77a42a4d3951eedd77b364d5d54ba651638d304a654d524020ba9cb0fb84ec2e7ce00a45d6db1372d047357f1feb1cd35267b248947e39c71bb09989b02840e080ea0ea4720f481147ea8b7ebe7b1e30de6714d78f77ac917131d21f0f6afc7ba225f0a216a6c2a2cf23833bc617610c3c17f738238424ef58c80c347febf6768559493abcb4ae418c932f2dd1a4927dc07e351632f02df0ac4c745b344513d92927ba7d1a77424b9cff7d466cb9dd3ca4e67e8daf4d38fd75bb495da368ff832e43102cc5d33f54751dc36cde27933a6adffb42b3684db388b465ab0a9caf72fb66e1884ae2b4fefa3100412a30d5344a3b894f8e9ea0651b404c3249499bd8891310537e8ca5c5db7c3d8131e2e417b7205d529a45bf0c2882178d835c534b4d04f953c8929e1398305283a9cbc27069c927ca013890a44d5a5a4fe49a2f35eb4a108e76ee6a72a1df74b72c36fbad30edb22a13093147e5bb701dc6c02ea91ddeda888a039df6ce74a2d132f63b0d1f8324f06e9e22af527db488d9a1047f16e355d43f265b6549d872f85b562cc845bce2deb6fe0f7adf0327e91a17111114ae63c3278257658be4ba6a6907365610eb1783c0b499c2cf7c83848450bcc51bd2be41b6b74430d15f52aa2ee18d95674767556cea8b53d9996d1175d5e557a16c606c835791ce2f06db29407edd04598138d84ea85ae9057ee30009b3d2c8e6f3ffd98f5c1b538930a7796123c57163ab5c0d06c48ff0d4b4bc817c3d1c0c3a5f2546a7eed9d8eabed3065cdae38007378eabedd33924935abb084ec58d3e35d33c0005931de21a908ce3e5260fd0e85d566f6595a73c86772ce4fac2ad5cd48a1dbc653195e47cebcdc455e0dd8ba93366b9e702179ac36af94287c5c619084131ae0e2d8f2315cc3be4bdce3447abf13878a8ded4c97cc00371c93f5bf0bab046f0a7806c9179fdcf9c764c1f8f6dc6d024aea2e8486164fea727b0a710c1008c496b9c8aa7d0aa1c95de20e44374773589923554c12dbd60adc379188d54aac9086d37421c5cc420983928d1a5fd1da7357562921b629794096025d8656619b5f4f554fb7af9efd43cd010996d960991807411be267007b50a66742de602400950925045f1bca427fe74622df12f45ec0ce9b859ee675c6d2c23dea7601fa692a7c028834249a8e9f7b58cee315302ddfca19f09818265c886387345d047cfda1951b06578c5e0088b7372de02b687d74608139824b3ae168a8f4c2fb4059500a0489a1eefa05da026551096283e264c88fc28aa45ff229393fbc6584d96cb94d1e1fd96f171a2db572910c017cc3948aabcce2f46e4d42d16a0572cbb3338e0ff50cf896496b79edbfa0e737bda078c5b480e6bda52537bc01fd8c83628cb0bc27fbb180d8ac80800800c3fbb9cd01f46a45abdb24facbf8a349349b4201f9fed7a21e875b6b87d3bb630a5522eac11a0a9327cbc1ebf663ab3d3315a6815b984f822fbc85e8cfe2f86f75dad9605b3282a906976da2c5608064695cf2d311ae4586f277071bf9c41b535cc7df7ec310fd469698caa4eebef856f02b311ac0a481a5131a6b6e1f9e4bf60aa4f33fed663134b362f4b540898a11f17a54cab05c34b964635f23de34fcc51f69928fc204e3a18825b33cce793adf6a4dce572fc51e49dfb614b8f6a178de3393d7c7fe413ed5bdfedad415c45b88ba8c9c672ffb031eff0873faecdebdc281282a842433c47519e578f768d8cb3c650685f0e94240cbc47333f15681b58c4852cf38a7ab78a6a2a18498c3ed327fdbedbac59927886dc1c22c73c3e70e5be7af5cc3fa04745dd6fa19e49d12daba20cea1cd5e09a99d9847dfaa852d58f7362e68b5d6b64812b27f90dae735dd5cbd1d84c4150b810d9def576e5f3a5eb8d1ae384d9fe4519f08511338e3abb9b7d14b52033d1561704be6aa455d759a09b13e6cc63f370d7e65205a292e8c1945248fdb6fae1d5e298fd840e503baa2f6ef47923cd6276039962e6fd1b481c1d09a8f5568f08cd19cac6bc197ab8409fd779deee33d0937c6af279abfd9", "a9e18d845c821413b75494273d61ef77519cceeff66c7a03c5b69e20cf9cdb0074fbea0e695d34101e15d752234ba6b9e0ccf87abbf4b9be08c5ffd4a97b4c72f099d3ef9983ff81fbf6cf511eca4306f97d33522294ad4689581f2c0ddde841020c9c1d8d7a6a7c789912b7bc3d225b41a9cdb080bcbb7bcfe65033ff61ece0003694289454c15a8fde19cf523158f1fdeebc81fb2bd2efa69fafd1be3e6305f562095d83f9117145d7638281f3efed7dd0965b98ea1011aa46393b59bdb1081d55cef7d3d49037ad0c2793815a733d3c5b769a6728fc561fde166e671a9151b7c4ca86c6146c1d646756bd970ffab787d52efe407b71bfe1eed323703d48bb6dae30f87eec2e08f4a164987fcc473e19673f064a92d682e80f6dc757ec92b51d3d7a41a4f5a8fc17db5b748a4e7f15e04f01ecf51d6d1da64bba55d7f14f2fe6e3aa1370eee79e0db232b827835a4ede82beb9df1504556c2339b911cbe577e70ce56699dbd21052d74dd22e1335b036a30574682eed12709f394588791e2dffc90ba8cc13431bb908df3d7a7af5959e810fed020a269dc6bafb00ed791b5121abe6ac59e73cd5ac7e48d6d3d330ee21dce1372a17b366654780d8b64df028c96127cd7350c1658a1eeeb2cf3aea1e408c9aa17b0b04123880d1e7f9ba2ee45779e2e3ad7a99a76b18e4d1dc2d925d181529d9debc362a0b9e43a587301430f61912112b47a3dd32d4673b07c83a1ffa8051d511b058f939712fbd97645c190848b32b4ef0fbd59b24a8761e44283591d65065bad8d47feed1165f2e540d867cf33bcdb8a5e4bfcbcbf6ea76bd25ec92abe128bdc319df7663e2b958bb31fdfee399a8084b0b87510f9815328fe5786d93d84ad9dd5c835293e056e80e68fd4f6eb1d3e6a35733fd70e52f05866d3426ba7fa00b50a4ec4a1cb635c31c7eb987563237fd5b6ec4ca5bfe00288b6792a0b4396abe29545000c356244199396c9d4f8aabf41e3705ca44409fb279ebd9d1380ec63c8f0a08b608fd02bc795d9156fd3230b8e4cf7c5753b8ad6960476996269109e37065559a94bb09786f8c20cc6bd58d5129659d5d3bd6b3e51f934708f8a5be7a94c7fa0559799562a8529fe2a3f01a1d777f8ae6f6b961cfb3d74c049794910e43bc0811cc245719d429cf31489cf9daa1654662e2ee07e3c4b5a3719d6ba9c6b514c00c98876d0369d6aa240044ec01f4c6217292ea4688d4009d4a6e0be3325d9b21dc7c7d26d03e22f75b2a3f8134c8747c1e3ae59a05797df04577e57258541a3f3db637133429b0aefc3392b08f9db3cefa942bc70c2dabaa677791bb7c9552dab7b8b61dcbd00d9eaf3e9371aa801fa6b1bb5ef1767422e97a454c0e3d1cadb6ef0fa96df76d80bd087332ce3bdaaaefa55d20b5f68ddb6318976cae22568afe0c5c793095a8cce5cc4fa2ceaade25b772f247e0e1c81f4b93989c310ff6f584181d5128e3ff316f0f70d0f6689f24553f78ff312c9ee448fad8c0ccf2d8e0fc1d55c85c5138b94c2ad8f664dad651dc00e18788af99b3f8d6bc6d70222d4467135ef2f8a281f5c0fc95c3b3ff658d07235189df8e46d38a4043633ad412d3174ad2fa30ec4d8ae18a9c648ff6482236cc825b6a8a4b143462e915157ce3aff55ac0efaddb85f1947a48e81dfe60bbb9e3b3edf78618b2744056d64692ec46f54258757bd67f95dfce21a10ef5fc1c6f3622d0a7fe0ef142cdff277b3435fd03a12f1bdbb2deb2be19d79f1a0a97c36b482ff455eb0253fc3c269bf911f88407f32a8718ad229621a5a7a1b0563add05fd6cc1de85d7ff0aed63aa41a2535535e29e6eb9be032288979904590a065e9c0a4e0511a58bd42e943222b09dc622f0e8d77f5bd15adcdb9a2a3aed515c462a42a36898d0ce035b7683c8dfeaec2dad40e400bff792bdeb001d7703c0db91f9b033e594626ece9b0925f5d1e0e1602b6ad35c959fdc407f134c8cfaf4a0fd221fea47dbf5447bce3c59db2aa1e11ced2ce09bb4cfac91e29f94fdc1b8d71e52c6e727dd73db89dc3a480d051cbc4cd5ef09c4d6b38147623cd920a83d7458f734fed241c4519c3c090d77118fd7bf821c87f70a", "-2b7908a29d4c4fa8a4b30c1ec1debaed52165ba71845dd002c54f93de6eafc14b951d69e913f9fce159b36bb856555c9a3d49c6766e0151040d36df33076961dd95f1df1f3b9610bacbeb4877635214617628ca8f6307da87f888dce1e29d9970df718af4c6113007107c0af91d17d60ac518f0594dc43a993a5f71dd9c969de2b3756541b28f11a183d95e5efba98429ec460c98c9aa142c218b9213581a7732e2e649ae825d69d3a88a421a96f20849f0e59e6d4b77d4b2978f08efe790fdb686f1610031d3269bcd16166adfd6fd8e211fdee37f2614ad6652f1fb758eafa311b87da929f447a6f95a7d16bd016fd557f7c3ead11676d665eebf646be17619e667daa191a0646e93ad436d360c498bb161bfe2d5d33788b52ddca6c00607a38cc17c2e2c9e8f59731008886a8f2f83d21e37ef8acada9dc4da4c9b1ba5ccf7a0418a1a73cc266fef5d4793b956bab768d39a1f1f00b1e99e40bad0c0d8313e342b1ef817a11b758bb0a8fe64b1376aaebebdb4c75391fb08e80320e9d02764a07e017095e8b84059f00838e12f31aa48b6da3c19baf6f888d78c93486d18901146a5609fbbc4ecf91bcc89af2c2e318f08ea5233207aa7e779ef1735d486772ddf5c0fea96d72f5d792c4f3f3a4d0c9096a2c0a58c77e8d34f022687aa406ef733c9746123473e550f0450b81c9a76b9136c1e4f3e2de69ce9f108f2cceffbf8c7007e47bf5c449c3ef0a19a7be31654e23b14bf9290e8892e4095b657018c030ee5d1b9ed9a349e36f8ff11f0423a28d60d944108db4435a1f7246531d8a1eb059b65414056710f6b4b4307cf649c5d4d1b1348b8cef991d7971e1e8152979c5e78891a3075f0cd04ab26f1d185c7da4718f57340c7d25598cb018de5c8a7ef2ed43f90109ae67ceb2ec7f6765a4db79e76c9c948a5359e5d86242e92d1f6a0e8f9f02ba7af43da054246d0fa6a206d9be48f118d7d0d879bcf8a0b0420bb5aabc9f058f5b79aaad9e80b61dc51427b9283838a4229dbd3f479fe853bc7d8c70ae0232a95cf42c49cdd99184722354362a0a56683f9bdb0b606fc5c3703ace3850916900e89b7590fae338df283076ec2840c35d89f70c0660f5b4fdb08ef2451ed3300c455a0dff28b0a428fd3968b62516689f7f0c1536c75cecedfd88d59e975ae1000e66fbe0a7c5f4f9ad44f29610cb4fdd10de4c437814c1901d688e1be14cc30c1a1c9761b3a6b23979593dd2d8598b068363f55294eef9b31aef529875db32f70dbf6232fcc9458e96eecabf451c40944efc0278d1ee81bd0954a17d04e868619eef32e93f60c5eb832c7d81561c1ee71345dd3b149549fd2c55cda3d41d808ccec6f4f7b6bfd992b8cbeca2f6cf5ea2134e6367a4ed9add521dc19247df92217beb06c8d8daf098570285fe17228fa0a1e55f5fba71ff4c11927b286c94f92091eaa11a5fff9a4687129bd7def91142d67124b6e197612eb7e08f780184b23ba26126ab49b46fdf30bdd79daa1c38a6f508c81fd52b5c0ca4b65ddb6a2af3e8264f5c51e67b9718d8c3ae4e174b4233cf672ad26f12c7b28af1fb6ec72714f233a2c70d43e9cb9ccc1c8ec17ddd4c6dd36804472fc1f768de638ac54abcb33f8eca764cdd323fd268b80c9e105feec64b249ba224f0db2e7b447627618acc585b675fd53668ce00ef346305ff6f3cc418530e31f44313db02c6d01c45e6adaa3d24faba5871b47949aab52f48f73098cdda07bf80fd250e4802f7d457080014d5afb4d68a2ec2cb050a46cd6743b9797c467f14181aa93b9765fcad39733250107292a4e3d3b6d43492b55288e2aecb2dfeb3b73f0f9138868252f9f673d301ad8d471ae856db0efb408f59f89926a3895d2e08c1a146f1a394f0ebb85eecb73a273a216f33c376577a938ad9d9fcbe3c5292ab641b30c989407f7b43a3b5f077c51ca9230fc996b150d1bc3a78c3ea597f768076556ff4c79baf9e0ddb77adfd90a5a70ab697d125b9b0772c06bbca1d6ba01a203ce052063ed6daeed85f01b3a29ca1806d124b557da5ce0554e5b15725ad825d6f6fa80d967f6a125d9eee805b015010efeb70b152bbae1d231d166f3264d16c98f35d0011bd87cf0614586c681941bfdd8d09700bceabe11057961f325a88aa4e7b6226086a74f2144586305b9e4ec364ca1c9659a55882612d0243b777fe3c5ab9e98bce51e7d5cf5e9e2973f61c1421f513073edd09a9005b2133cffc300577254f2bebe7df4c03e0be1f612587b66cbe7c169efa3eb06ea146c97178582eb72cd7e895a459692be3fdd9db0d7aed1892cb4e61a9e4b5093db3b2f3197e1ee3778255e2ef48d80375debedd0f533035faf89eeb74d5fd140671e77d85fcda999c08c4e424021b3904e9823c5bcd016a82607db5871a53bd3a13df486e0104511ba46bda4008fab6a5d951580bc42fbc9bca34af75d1d6750057327757daa0fa97e112f16d4c87de5b1b1b025286244b46c5593b399f856c34c20b2a36140c212724671bd78e476d1e7b2b1e4b131e6d2668b1754c495edee45133b7452d9f9a7fcaa1cd805e59b9b3a2a03a0341711ff8076003061a7b1e167797051c563fabb3a4608e596f644e1f951427b19b018b39410e12df7d8f059d1130b1809f4543bce9c7a085a5ff659ee93b4507a1eda5df3abe030ced1777a92285ee1b36c81b26d4893ca83b95b3aba21459cbf8dece3bd2a7b5ea22c9d073aa4f33b03c0378ce58a02539e2e69e3add1c1c3691c7cbc2e2e19378caee00c5c842954fe1d12e05a6e806d2e5d9c36d45ac983c7565e9e4b52a8013367ac25980841d3b52158d01e47a824d46634989ec391f8baea67f77e30edaa5a3c7ec00718a233e4fe1eb900b09579a234b1b7690321582479d24468154494e5f209a461af0c163c92788d5514a33a474c65e577a7bb72a1ea7b8a8482a742b1d91d031667bb200d86646f0771ed5a10cbdb2f5ba29d51fec2742270ae199e926e9f55e9118baf49da0aa1c773a422c7d4a7370338991100ee5dd36e4ec4261b7fc64bc2604e89c426e6a16a1539a3917adb161b607fb0e57114240e5fd2cad97d9c167df2cad8a8bb1ac4099303b7269b6bba97e5ac0d245d674e837b970a9c1b79e3c07383f0bd9a380141d08fefb760219511164ad8bacbd8b635ae624a1c259838414fdbb6faf46f2ecd9d726d2f08e4e737f8ed7f6cf89736238a2945a7abe6771b234065b875047c4ea2362b6681a6dcfb5f042432aafb0af6fc8166835c70a4fe06aa016d8843a87907edee3ab396f682b4573848d3aed26bf57e8a854d65b4184ba78730d635745cfceccd66bf321aac8babd7eeb0f159ef01442a6a7e509f95af084263f987c3ea780c5fa6970466b3b20f7a8ec600ba8941496f70dfedb46382a0ed25b72562df49647a813a375a3256c3649e929517b230d8e20543503364d17eec82fc2894a36a8a52863aab2cc5aea764e3f09f794eeeaaee895ed10bfe110668e9b7f857d4e9cc428e602997dac6cbcb20c5201de0a69ecfb7948d822afbc4c625178acb159816a30b16f9828d42b50b49c5ed95e28fc73d1a47a5c0000a8b8cd4fc8addd31e49a959d1abd530183b664a9d19dc8f89d6df810c37eeec2539d1f4cce9160a0fffb593b3638663ea5a6a91d9582d3e59e8203e4272589908b3cdd328c37a178f96c034bf598233592a52cc1fa12e78c72e85d3e1ea870608ec83587cb3471248821bc2e485036001b84462114794746f53366087e0fd8e1ba98158cdb33d525a77463bf4719ccb8e187806a804b9608516a03346a2b4b2edc100f56585324c5ea211b663174193a0980120d1b898cb805078c4d00ba3e01684648810114532c62c1bc997ecb644b682249623025580070c4cad535e4e3f54fc5492d1b69a6f0670db487a96c0f39dacf44f892765635673e85bc5c20b170e71fa874f11382a9d3650af1a1f4471dfedc7209db10331df6f8b694c9932e46c66bfab8ab92365366e25026e5455dd57033abb8951863035392271c26ebe944aeb5d4d6f1f46b081db8c4b12a84e1df8a05691d6c0e02a815112dc910613aab6f3197741de8618362d87fbe1dd4a10cc45d72309b245ecd7ab3a15ca4f2749dfad67869ea18c789254956a771cc0072b847ae239362160dfe1d499d415fffd0140bd17dca18b6563cd61fd76af9b16e188320bed2161a099e75038ae4d6c294dd7a", .None}, + {.Mul, "c6cca909b36447dd35000cd976d4ae6aa2afba085f505d706c309e6babbc04f7911a3c3ea2f85cd94b04fe67bd59b51c9c35db0c91d626f66f923fae296be867356298c9e23ae14853756ee5b9254d6807207fbb26edf8323ab5eda0a2f4ecc58fe91c3e4d9661a33892d7db9be20495e972c385163ca8f8f978e9acda71b6b58f1f5c28a75acc803ce710f3f935c6d8fe741b91ee4c271565e18e395ef302ac8405a059b00c745bce6aa393285e634f48ab8bdcd0f0c32db9c0135d53385343e5c94906812be42ffc74cd6876847f3024a63e1ccac5a0f1f7db5339f328ab59836766272cac931704a083389aada86a4b35f2570989d7c6166055a46389b3d54b26dafa3d7a7c123f1ddbceabb936cda97f63d704e89386ab30450920d977343fd85d862bb484ce4d7a2c245ba1693ddbd779d5f1f067196f898fbc20b13d099886a507bfb8255010fe4f6cfd44dfb79df4139f75f8b0eb7b72d2b37c2353bfa53d769ab160f5d2a3b7a8e265fee39826b75e5b0fbac6168781f790035829a7c56636514de412904616bc13b75af207e17050d9a0a3954cf58befd640c806279d81cd5ab64d77d6fd5af3b9adbe244d7f9bd29652bf55237b91cc3ea715d7a1a95d78b31e9e322a8dc0a40f47ec21e45220a45392cb19954c08607b41261d3d467a368b1dc60b1cdadd9a97a204539d6d342abde7b60ed38f8da66e8bda9469f602ec389d0893d470b69e73f06aeff1e71cbef93efc7d81b4102b474fe658778545dba00c0143d3f7abf1170c8da314a939f0784db886c3d818b59861739741d2ffd7c18a7efeae328f4b51b1e85aacdc131424d6e077a2a5494783a1a2203e8e25875aa90b1fd3e053702a6153b7ccb33eba61f4ba9cbb0d8a1a99ea94ab029c865f28af98cc48c6b19d5d7ed1e69c3624b7b8a3d8fb822328fe6f7607c6a9b009e8ef954d49aa6637793ba3864ad62483328650d31ca26be617f13fb84be2355775096b3d37fbbdea7dbdb9f519b846b2b5e5ed9b9dd9f5ba61bfc732a38e916137403d86a28e3357bc511799d28cc5e87b7fa6d73dc7cddbb3cd137ce6bff2d7aa3a89d779c29250ce793ab7d68f5a1f41a52f5b94e9cacab1488c3a84923b7f75ad1c38d370f27262efece585570cb17823ae86e87799616f4a3480ab498c5e38496d07fa090377407365394c6bdff587bedb52f787a59cc34826ad96d7d087a607b14c330b95687400df0331053307d62a852bcda94d08fb7f24a703860c5cd89623daba8a7e3a618a0b111d4d77a1da05f5594a83b69fb74064769d97607e327763ebe4689946c9d3cb0acaf454c529b1ace9801c6cb7f9c953cd972e35c29311aec54887a9bbdf4d9abc86bffa6d1301d96b1a920b5fd508a08c58275bf784c94bab8f42f3ebaa0ff680c12cf12bd12cb779bfd57f869254424ef58cc88273b1254d41d7dd37e5b359f20a6a915f1aca4700e2e519ed5eabb5b355ad9d221f92af9b3e271c86923ad77f10fee55a4a1aa8e209aa245a91a2077f2afa41ef287d7aaf3fe9e8e0b132cfb1082b9fc94c59d17cac7a482e2b9e6569ce5fa502ece942638bb9d9aa1f06016f53cca77a8c68f9c53da0f157b5c3403752fe04688af5920b8d3936358e3b39647c67f6fd2ecd28089a255f53ed589afec3e0bbf81f73b8f03d856e9a4dcd09fb76fa587e9d599e2aa93c7d0c1e94e84c728572fdeb168712430a47230a629d9ab78dcb19e567047a41031f9b844185156f4870cb0a30aeae700d580e74cad3031e13f3a6d290031494b4a1aeb7dd86cfe0b8f589baacbf2562fba45329a6c5c182f630fbf755bf2dd63349cd4d6eeb68ec16b6a2da493e2280bcf321a18de84783ef944ec64bd27298f6a6cb2ec0a9db14c0f7314e1799d3beed72748bbffe2cc962fbf0ba2a807a06928789568666b2fe2b1515a9202d30214877027f77f2d8cee2914a0f39340fe27611844d42b13683295464cc0e2c0ea83ca7e69afa1517f5d7a5145579dc5c1d69b4aeb8d765520ab88bbc92eee8a34d1426ce957d461b3b8377c16abe0f0f9e5ba443d5a3fc429ab1656052df8a2723e6bcaaff03b9de7dd1a9675d60cc4e8bb1882abe13", "8c1f5002304e9ef7e11ca3c28450be1dd6e65028b93606747fa6f860ed64863d0b31fb1c76934c53ec354d69d085bf91a11751ef70a69d298e96a2ed22dd6d4ba2cc303e053d6cbb47f23afe40265b2f1d16281b6bd31cfeac0220a975e7604a77f54c8ff3facfe46e6314710eb1f5c9b9f3a3929e863b7d6289fc200e1d4c7d655c8e95552a47c185e7d06739eb66390c54de2593859a43eda6b1ec365fc182a7510065f57d3bdf7f29bf074bfbbce1809996f2f7d7c3e19c66669ee989021b8267db22d5487f1dd7d2184c0a7e36abcd2174c2b1ea56d0a847486b91aefc2b67eef8ac55522f7e9c5cbdd26eef63537e6d23d12803d047c016972f8848ae42409cf54f53c0b2d471880dec5df873843564e8af408ad31fa6aea4661a4c45a4e911dc5afaad68905e40427a1e37feaca47e2a0cc68096ef212ea85c59955c67820f716a020bd67fa7310578df707aac8c9c799b83acf2edcc585020ee8dcf53898d67f3fd31a27303993f3f98c66af61f0d44c978d7ca8a36ca9447977db5584774b4751a2508350431509ff519446e33c32c3d77b3fb1d8032b5489487ef4acaee2a855dd62bf2f0d1e39fde2d12b01dc2d930bcd51f5dfa6ef275635fbc3bf89741ac821224a8dd8f8dc5d1dc02dacab03421363caae8c3b205c10fddb377b84142ee1cc1acc6342420f6e967f260b54c935cb672ce0aab5e6a49a9d156145d9c2a770063e60366722a833b4124dffc643bee00fa22338abfaf087730145300a0b1a4e2c3886a42449989d031027d7b210a021a89022e432ded9b9e10e34932a53196ecae97b847721a06cab4d5fe91dc8e54e2d79a4140c34dbf585ccad2418ff3a793d1fa9278e1dfccad506581e03a814b1850a72440ed3e84ad01583f9df92e20c59bd1492a7c4ebff9c5edc6f4e60b1ed734bb5c0d1da60e4c9f5f90504b9c91f4b9131fd6a8c6b946f767ee33ee96197b1e801f018be2856fbd5c988c1af971ec82da8c123ab3908d8606db14d54cf095434402431131811c847381f8e22c0084219c1fb7f82c5d75173b7c7b0446c2ba3f96c76e9dd64c4effc92ca73faa2fdb8f96f3cc9cf8eaccf9bc5906cc87476a896a2fd856aa120ff823a02f9e39509cd70ee109aa8a0f3e96f14c802af7524f06ae1dc733b82c16f0669585ba0832f5d81a8aa150375ff6db81627ac6ce437a88da3efb38fb31ed517515b72b30ae313dfc3931b7049155fb13e63b131eeafaec135f2844c42d0568d608c1c3663ffb60a462ee0eda9939ef97bbad456e5cfa51905041b89cd35defdb16e91975c446b4432bee8f64df2b219db3cb3c65a4c214ecac491fbb2a8b5d468f9f9e43e78111e946bb321e7aad54efd03ba22a6ca2b743223bb0d1816b67d8471c0c25aa7f949f29ad14a3db7008142f0a39294538b348ebe69d8c99346bf38fcd6a733d7ee2cdd4204a62bf0efff9f6057b4cbf7ab9036bca439c9827d0eaeefdf58f97298280697e29a6c36f4c02927b3f166ffda60198cba356e1c5f77372d62a429fae67087e459cb0b06c189d5b595b15f2d0c328977a0c67dc01924a6a2c595adf22c9ef39a803377ceb51d1d1859e433beea92477a38abfb5ad9e04a4b0aef8c92c48fcbd24afe878819982c30dfc6a33861aa7ebbc2d7323b1aa5bc67ce515e5091cec39aa2d2368ae8fe85bc9d4a9a0fc0508426c6004a64e45a4a61e7a1e6bc9aac369ca9a28a309533d85ed98b54fb48252b1f64e8ad004c4892efee0e8fa6736defd6ac65d6c8105796efa2a722de67ff47a42dfe8b84d4c73a3a1d299ae572b533d5262703b9ccb0c8968b0316197af0135a3cb267344c2fb928f026643349e0f9b9630ead5551513d22341e096e47aa3486321e9ec9008f0b35b45d9aee499a1a40080984bed02ce4ccc6bbf98d61263b138af571da6d7650ddf34aaec3b4b6b59fa1901d8cbde17cff566a61d939f65af2878bbbcbf85250e540beacf1597369dae7f352556195ad8397dc37d3af3645e95a15fb6ab0cf344c24255f785f916e36f0c3964e74711d543b70f597f5d74a27a1abf08a58e3e7e803595c220871a670c501c5005ec0e46dd6d7026e08848186ea9a538", "6cd03d5b6e3758148b35cb8da3fc0afea8266217e765818990baa084229bb6e9b8ef804bff254836ef58f54d371094842e2392640931a003b88c1054b083f9a5a6ef20ca6bf4b73d8de346201f6df6e4ed91c4c199cd7e0cf46f88f6c779afece8cc33fe24c050500524ef53da73ad1561dda63ebf7d0ea362cf67b8fa6fd412cffc4f86968aab84c96b5adf256fce5838e016f4b50a233e4391d135417b0a6c5efb3412f700c8041640525132a70baae38a35f6df85fbc3ef022a71576785641b679a22779bfd4c955d03133275f0b9ad55d1709d6326cb61d4652ef655112f7b2195a3af57e4cec83066d9f99da277a3eba6520bc37fa569e480374a3e16edc4e9f06df2244465abf3bdf9b5844072b23c42e6e223ad8285cd08ae874aade9c32396e3ccb1d889599a483e36e5654814547f8ae249d969d39162338853d3fccc59f313c68d2689d0a282fd4a3882baca5da138df7e4bed64b177c892a86a30f011041451f39983d2c2209dd5da12f81373ed0ade712287c3f34fb2e1b1919d99297d854c93afe86aae90c21fb0046d7191d1f35a697ce7f3528a3ff2bd61dff4f798f6bf4cbff642241fda87c038b436369df580db4b4bc2f1da1626c16ab0451ec612b1826560b4e58fa99974824bb76d89b5126ac3edb926d3a23aca50200943329b482c3c5e2dcbae3ea3757dacf49927a0ad501ee847fc1e8468b6ecb8036900422297e2b438de2fd113d23fdc281cbf790a9e886448ecb25b0d385670332a40b04cc4f2c5650216a26fdfc0bf02f8bc1d1dc7af875e6bfe13470d0af8e23c7f3bf7e70b2db46fb6d25f9dcad6abc34e4228646009926563ad20d65a07254f2c7eff848d9d6f3ba0c6554b80da5f643378d54b0a38005356f0fb34e684d903aedcb828d129255b7cbcb4874a909d1a428f7e416704a0e99e890cca0fde35522fef0dbad626b0d0c7590ccbb81274bcbf010d83f2900ce93757a33e63b235788e61f270628d7a6ab790ad82a5cb80de12d0eff467b5bc09904c53e2fa53f1dbe427191226b284037011fde3b442132a70d48ebcf2e0a9dedd709e899fd143f1fb837c869e92816fc057b96f6364955f5115dc31a66d673b3dcfd53a33f0d2af2704a37af9411a9134d47039e328547acface9a493008fa6069ddcc81f49eab9873aecc161f67ebcc0ebead943678a525b4fed0c537c23267c65a24d5000b69cab716711450ccfdaba0de626054c8434115335dcf790c390b81b03da33c8938433f4e80ad7be5fd6b6b087b9455c310cd97d1a45bc3137e761c0e3384f7bde4aa832a235f269b04b54a91caa16cfb8461ed5215378719609705efa341588c0a9a4b4a77f6643630654401506d3127f0b3a75c4f47debca68d4557b564c603003e60a1c28a3bc0141e0112c9bc4d92f984a86d40b2b52db81ad17a1091bbd9ccb442cefb31691984799867ab53c9fc1d23f42f85439a572bb0e0cfc6efe2a8e182d1470431795e765087d2b9aa08c3024cc5bd77d55d7932a573cdcf79bd3cb47949cbf65417eb542e4432d3913ed2c0f655e2c9811c4c4670528964484dd98c28f66e86d1e06ef0c103d29d8d6ed242368e7b25eeb3a311aa88cb69dec790522e363b22f1bb4cc6c03940909d7301d838cd3cdb0c7a3921b5322120dbf71fa813376ec027345d6de163e9240c88819793be54b6b0e771c73c20adb736fb0959f224bf8f3e3ed45b7a3002a3fd30f8a9da403b505f496bd6bc0e7089eb83b6d76219e37ee470bc3f134ab163b3eec52493577ec86dcb52bf0e3f3dc38f78b14d9a906f376cdb963ef006333b4582526946b8b4ae8175e72a9d0ce69b440e57dd8521be69bebe38e051d07b3888355032fcb175dd75cb9d084e9f4ba59264fd0579620e6b86e9f0cbe4b2b44c8a2fe783db8e70b73e547708d5b981f41a46c3a8d4c380207985769088728c463c658a57c9c603e011333b3de6c197d1f81bfe18d44c20ae89d5b3e30dcf88511c627dff6d20aea3b02c9a36010f4e669664386293d64328c75b1788d743ebd30e379dac7d0c16bcd68e0aebd81debd095f2047c67148e083d26aff3d2b52637111e4957b818e285c6be4bb2586da0a9782403c44f63f5511dd46c217aac6bb72a8932a06ad9d426dc8c5b90e030b65aa9f9b84154b9bd3d232e368b31ddce7e5f6e01e13c720ce52ee99a3f6706ca790312f08616bceb399822ad1271e829e81c9a39cf55d6924e5f22c69f1b6ac60a56bbc520c75e963575076cf4e01aa6d00f1577245c05df88e17e568761d02dd9ccf27c95a7fb655c5d44c54f96934af0d4ec730320ec0004d0197f6feeaaba9b5c5dadc92467fb268e34965c46943d35cce1eecf959f59f03d088918626c2e349639525b8fbd4dd5498e602f22cafa8807f34a41d513ba38390caab9728508211972f776fd9abc8e1395991602a150a978b64e5b6f1be427df28bbb81b44097909392ad60f5ce8d61039c7658705c83b81a4d03568d7a88daa5bb03cf8e31f18b70ea8d72dcd603551bf536aef4aab0349deed7445a586d1b8369bf8fe27868b7acad2006aa1113eedf5214a297417461fc3c0eb78db5625018774d7cf5bd6763c1d8a3c923390745842f7e6f1e47dced6a00e8f8798b8fb4851ffa83dfdab6a8566ca33f165f631eaf37552f56168617f8ba39882e27f963460b3ce1723633cdc16d7fc5ab8cd25f789b5985a57936a32e588bae83e3fdbe57497123b10b7c92fee00468034e047af90dd651cb40c56527b9e4ea9653b9d3a68751423d45f366d35dae948c2ef9c1b61bc24f55d0f0773ac1b333e7318c82cabaff8b8144f226c2acf16895dd1859e8c25dec850846fc43ab9aefa608c77e82985375f68e7519ec0ba19f797c7dd576b96353252a2dd1068b75d0c23bb86ec003ed2f3c0f7bde3f039225318db052e40d39c4f0f6a1f45008198043b91056e4e7dd1a49a9b4e233b4d2183f55e694c269edb12c213a1d3508de3ac3f4f8400145d473ebb171f46b170a58d149770a96459b27d74595e9e48093f508491932e4b27f0455dfd7cb3067ec74c6d4b1e44e4c4441224cd7be72233cc64f5fb7b29087f50637b8daea7573d98f7babdc9eb39759bd5ae4833024270c77b6d5374098b28afef57d615863fedb9718f11d456fa064e4de0f756ce2c2366c24a9f341062f1644fa3d4854e9f26d2980a6e0a97415a263bb472320988269f9436aa9ccefcb29b4ea4e7d2db2a768aec250baaedae381b1bfaa54f98a68f5aabb881fd49771ce853328ed84922c7fec35aee7f3095fd82487d0d7b078fb87b9298e4b0dfceabf3cf167a3679d457a24cb5e54846b0630bf5060df940cf566f4dbe02e8253804de23a42542cb2ae7ef236d5645dd607616ef4288d222d990b63c310ab12ac4a906320c8dd10470c12c438adca949b36df24c85025e5be318e81bf1b9fdc692c75a855eea1af001ece3a5814d1be07bb710450f43dbe45ca605c1d221b3c06f08fe05bf562cf24f343993d98d80244cba1ab8cea4b3b6931ab20c68471d498baea86ea77582d967ae38f552e5559950c8fcf537007b5c61937aca581ce1f77c2642c2954d1ac23711b1c97af2d633a085ef9a6246a000b4e7bae727bbf6213ce6bc273e7ab1a2ccd9d53810b12ad7201fdde7e7c6e0cf56b41683452782308fc3632b3f27717399b8c726755b59678012d1a134d232ac54a85e2335b2aeccf752143063a92dbedc5962b2ff1215ecb2dac20c4136b8264cff330847bdc2fe01d822788d61b09752e3c1e11edafef00ec743928946076a27f0765f9996ccf85707f2dd8124d264a61bbf1b1167b2e755a13fbc8e0923ac8eea4a32b5a1556ad7c2ea19a3912d9ef36d5d17f40fadf290a7a4a605ebb49117f0fb554d217416d558b35c3fbc4d9b7048ec7b819dd5e4afca24c9303eec1e1bc878f8f578e39bd688cd7ede16f3521271d18d9976c04aa8817eab7effabda2fcb81d1353cbe15e371788068b8f4b1d38e227173ab92bf94d58513cb56e8e62875ee5f1669cfdcf1dbad4ac1931878c8a777f61c42065a2e58ce8240f6f67e5576e0b8b77d979e2241486c83a893a8caa96b8fab19edd42817cd82c0e115ba888756a162c1c7764b3ce16b2d9c157ce515037f4782e0960ce82e6f7352fd7039a6a9b4637a3ddee3ebb0186318de0df7467d97a5f5842724f109f714ff530bb84357c6744fa66d328", .None}, + {.Mul, "b7b40ab6047ec9c842db32a33ebf16e6cae6311c6400617bb8531691adf3b7494dd87fbf8cc5e74cc0cf67e2066440bc0b818179513b9df50218fdfd485d15cdca391040f59d478b4a5c216fa7c1bfc47fa51ac19c1ad14b4a8c39615f6c7a2498103dabcf02e3c3cc5983c98306865ebf207fbe3b5b407b8d0318c3c35217e4c54b4bd744647c98570a49bcd0a60f8464a47ae71a81b9bcdff4ef3a61744d83857fb3a9d97a7c725704433cfe2f88a8b0d140bc041cebfbbf5172fd1d8dc30d15ddf34908c9bf2b85d0402d7df1ebac1ded47bf759aefa1a93d063a3bad9d1e7bf5cb35dbd3f2f3143ede444aea38d8839ab98471f1e42aece92b44ca7c8e941ebe8ed6bd1b229c35eaf62b7b48eeab022a8d5421c993f94f1e7037f71d7a23fcebf65ef6f853dbea12ed6e2414fe501accdbaf0a8bcaf8538fdf021b0eda522f7bff0c9efdd10abf7a4bae29aef79161069a376daac829df7153be090ebd3711a7e62dd510fb4519da3653b5e97c22c83ed3dcda0904e4e17cb0cb2cb267d57b24c5339806f8395eba7469a440fe73b232119ed49f0d0e1af75d63ffebd5683a9f138e49d1f35a7e70678eb9fa8ca2ad23753f07a67bde402ee4a0b7e91e12b56d4cd3f02e019b2de81087104509e7a4e93700514909d98f3a309dd1946d623822b4333d1343da153ac2ddf1c5163a153c06f8d390f1e3f1368024a59482e9dd4e8f99df5025b1b2a42577ce78678b8a2643d061b2a4144f4da8aac997f84591d94dcb122015a3417e128dcb4da9df4f6847d6dba7eb6f5680b347d6aa953daa2dc135bc3fd9f2cda3a5205d0ca5feb5784af6b329a6abd7c24d776a05c92dfa992956ed615586964ae5674f1a52da42156b15e6449e1819de5ac6180d0179591dd1d1eea1b627d1c0ddca6b8bcd71cfe676d24356a6c5041f3a3f82867cee31570aca27713678b01827ad8aeac7cd445515f33713fdc6af05eb0b3d0d4fb177016dc6ba9852c0396047fbe3b45ba155d7ecdd268d4d5178f022170e1474b2b9ff7b79ead4c105e07aa67de7395ffcfacfea7065551cb5fcb59571e31c7faf7727d502f85e2aeca4e4c5d9614b18f5bfdfca1e6b3a1a5029cd63c44a550f63a909a579f7f73a63297d43b1000560bd694e99cc7c8f029a09a6defd63033705a438824e6f18b2e896a1a2f841f946026663a006d5b9dea7712e044a33f635c289d2d042bcfb1f26d14ed72358524794bf0f6ab0163b15e076d98467f701699c11a5a0f336034f5e8280b5ef10c2e7a41258d555df9fb1ddfb62465e72f9324d6de1736f28f3801a76d8169c8c72b5dfe2b9e520cc98c1884afa6f8df3c3a7442a3c7d8438f0f9acb5d6fdabc832f086cf3fa9d69e2f713738ef34eb4e86bf20f13f66529c66daaa5da23d9afa2aa5e264054281c61c9c221085a7953a86fdf0774fbbac2489b532c9135c1b6fce90b8d1e77415c3a10ada90bf197586b003e90cdb9804a818fd26a0db96ca5fcd176d307ac18a80ee9198a70bcfc1681cae9da1f9a7244f7ae1c86e16acb61c3676ac431bc8f86cbec5806a12e72c9ab92edfbd7fc5328ef831e3917500bea7a24a7b3d419aed729c0ae4ee343dada2957a6f830fb7c16181a6df00a39742753420b21284e713f3c5e8388e01701eb3e36471e3b059bd44bacd6ca10e67298d61e64407cd43fbcf725a8d694202ddfa473a90dac09a0cb63294cbcd4168c1284f7659798c8ad7491f8f201890e8325ce113c5397938beb2a3106104a70fcf99bfa233eb42bbe77ac4c255b9db0bdb010eda16457110b2666f421cfaa5660247769532d7a6cd0142785415c19cf86297c69336d08710aa69a8b1108187faa280a174ff7dd885b77c905783d1ace02384e75828bb62fafeb42a81193d56b4523e2f9649b7c65b12faae2e917aaa0bcf0fc188c8022dffda280c04e3eddf867e36e70c054b48d56b4eb84c9e88e656d09e4a9bb2d3232f31d826befd8d96732014b44f9fccfa32fd63f10af87300883e92ee7a72afcc16378810810c9bb3be64a225cfc8114c0313ce7f0c744d3645c3cbd843b8f59a5cf9bc93f9651331725138199cdbe3b54890cdcd14697952219f", "917474543617c86ae9fac0d7a7d96f84ae6dc2d19f407951d66e5ba82aa920693ba6fc438258630ef78f161ce362f15a0732539591486efd666293edc4f4e24970f7f5211e94eef8ad6ab75a9a31781b832d6d53140b11bfb11737d68f336c54b3f4d9e94dae8861cc2f8ecb138a80eb2f59d5479f35463d823216d73ec4569b3bf2745f533a8661878cfab666d52288b06d407ac9d3025f7a1ad3bdad922ff8be700e470c1bae464d750229c812f66a9609c4257134eaaba1919bc0b3cc3661a80c70d3155fd1bda36321103134bec78909f66584ce9cffba95ed24b5accbeb134e38add2887b4a39726547fb29de1e5566c5a6e77cd7c962afa4b2cbabf400387fac3f6e4b13cd1b4b4960c59ebc510cf4b5f8eafca9d577288f3717ced5b3e8c53659ffd47e509380a4726015730373967e08c1acbbd6ee52a6dfc78352b22228ca1c8a515de623d1fcdf09ab0d804d9cee8c027c1b442e8d2fa66bf23475ed985fe008d64dda76c91f12a808d19cdacb8d487ee2685e60b88e4b2e3174b1ea08f9b8837ebc27721235666f1b44a51efefb5fdd62e1602c91c5a887e2949fcc7e0546ae1f95af2f655325abf242b2ac5659aee55e61d6a46c485f8537cc32c150d9f405eb0bbd40aa34c857bc498ffb3aeddb02b8c557cfc169ab748c8b8cee2ca9ccbd9eb95a7f8836a40417b7a850c5c5f5233049c719fb13bdc506db5fa9ae27baf8c40c1036002147f2d473adaa2a8fc9a67dee7eca93b3abb6740e5bfaf94e62554308ff40bc1240fae1a8b75371f620625ea67a1ccc8c0c8da1a9037d31b9c526c88a0d36b0eb112f282889f4c42a9f09b34f52d031887b98959fa147c9b42a88f53c61a2ef4d669537a56ea1ee9f24f63c0137158ffc39437f17806c2c6da1a90af211904cf1671262fe863612f12602329dc4230650d13402f4bdb01f3f4c84d11997c658166855d7f1f27a9673950327c28b2630381537bea51bd7898234483b19ea0d3f72f520931dba67b941c952c44de30db063019f989e56fd1150740af8dad822c00c7e141988544c24bfdd1a8ae1e9f1b29ec3f85d4184062168f0c955de658a268ac9afd2c39d23d9a013a66b9181ab42da84f563fe5469cb6c905d4c9b6fe301317bc5887de016d3b44466b69c45fbeb0551feba6f3e2e27f94c56ab422b23173133c32ac80a652e79ff220de2db2c0ba47c96d1dfa69c20400c96c34c8bacb1c521292f1579274f842c91e560b6723f07fc7b3a1cb7f08bc026a90e7e686e349292d161fcb532afe0a72453b3ce9b88a3ecda2b06b24e91ab538418ce0d103fb69b66f445cdddbc2a1b873e6479ba4f48f61149f6c8b7eda612c2655c650cfd5a4f22d6d82e8589af23ad924dda700c572ff58f7f681a8d28c69c6ad24c6bac169d39c671099f4a5dc03e5c7c891d19fc23497d4e0e0acca885b6ee756018e5ac0a5a2c90e41d5d212b82ff347bc2a6bde7c4ed41885ec934eec6c84e99fd1c4a3913c8006adb7ed9a91ac4931965db12f76454fbbcc2560e22234786feaba23640524cc4d2b6844c970d57fca8d7f0347c94669ee52b7a4d7e4f289034a821dfd652d58d96d6114438eaee28a79e0e52234ce87a5aa5bc6c6be5ad799f8620e48240b4dca30364123fd1c6379bc11408bdd8f3978dc7c01d18d0eed0c8214d3c452026afb197aa2b6bbe619bd11b3f2a5ff885f728e47b1b5cf69af1b014d8659a8e28d0c6561ef81e46057b59caac465f98e9bd23b8114ce96a6921862930a003d607164c66c75b03ce9d6fb473bec6128a28cff190856a6ef1ba0ca41ea6516e89e06be4fbd3e0eda5f7fda2981547dfc66672194e4d5f5f82ec758bafbb8f3d41dab69eab1f83a46932ea9e17f6feec97e1be50ff74300129eaacf411323a7c57065947cbe7fad4a7ccd73164ccd5d5aa430498870b1e5b345d336dff0b16d003a9475f817aa1eaa4634806b09cdca96627db3dfde1859317da33754ebe895f7f03b2efbee1af0806b79ba97cfcaed29aa61f25061111ad4aa4a3f98ef18a7be687e0d733f3b39c091893488a1bd2adfb23d469dfcddca7ff00390343300fe2ee3363c6f1ddefa774c3f9b86ec7fc3e", "68608b1ff5c4e2c185c3fdcbdd25466a78e86a86e99ba3b22f6bdd8f45cc847345d1302614c1f92406d7e6ab0158e8c1898f03ade8d9c6cd5805ff2ff2199af584e8167bfde8acd80f5a08ae32700d1c0a0a80957bfa21fb1a3a886cbd64ce1708d4fe45e193a4e36ee8e1286999a2d90b7b205347e761a1aa1ff1d031a345b5e03b00847ba6c4cd6ae6236fa401faaebea814e9d909ba85a3e49556b58b0f72207656d6447c30f9e0df711149f0da114c5895f5a5e92c40ea8f5285df63d6f904ee4a15469f0d63b054ac6a88e1d4491a0c53b1f684a7cd94e22732398ffbd0f0b864efe8dd662b91f48ba8637d1a24ebf427efaaa47cae25b151b51b9a915c1f710b3aa5c0f25b0e8edfa43f35dc6d518ee5949391aafcc74f2c8c46ba66f0a25cdda1c73918e4320d6070c3e08646621e5d90db0544fdac30ef1c679d8eec05ad504fd2ae773d7084d8c67e0388bb21f3a915b51785ee13b2432bd6a584836198bf31e50a7917c52c90a9bef3718aeada0732a5eed5f76743428add4abe96629d4c1a8f79ba5fc57fcc465aa560e7c984f88aeab37cc9f21c508d52c36e808a9e8193a75a2ec29c728274efb2a885a69dbc80cd448306087fd5636a6abab35a44c983a50ec7d9691380e596443af114013cec398aeb9ca8f9c3e62245489ba5dd039d77f5b68feda318b2b5309ec33edde7834e42d1c49623fa909d500a4aa6349b9915edcb24ed56f085038ea6504a2654167b2110ba91b40c181517a93cab365ba12588f4d9df52f610024a7d0d6922b858b5b137f3d315e9dd426fb5e2dc73552842ce2b018ac8dda8ec838b684d624ad840e7de48d1e92a4f677295ee2efc5034cf99030838b3aa6b162168aa49bf61bb1d78c718a117faa2c7d47daa9f6f4f7dbbfe0cd5a4472e358fec5268d7e646d2a1d1c997264d9d29261a78143c30e43dad1250406d3d9744f47eb1317a9c568b2cdee68377e8bc013fdcdfc7ae3ab63f9a1ea239d7b7c22edc4931875e0370636ee63da59f52c65a227eb447a4fd4cdf9b1fb28c3833777a56e947b475361fad66347f9edb5cddefe6a5e725e2b00d3fce610c2cd073283dd2bbdc4b922e433ad646279a9f09b962cc17e7db29f849ff3b41d7e9cde70a4eeeaba89c2a411dcda3b3b62ea21362b93afaab612001a185e998f5a539ff1507ccca09cdd520a0d976c823410cbae53b74a13bd1a5c7b750158a090d2a725f93a42109d48f7f67aa08238dd7fb2183fb184cf84e17e463f60ffa6dc34c662ebb1e4a5b9e952eaceb4c099816b82cd54eacd6d98ce654299d1d09e07ce89463124bc6bfd04a5f381d4337fb292fe70987a985bb1caa3e6a5f5c96e39da749cab43ff6277a327cbad1874033d2b3ecfa3d2834e1e731c6efcfab12e9477a0a082471b789b6444b8abacf837650d6d2a92a5c340fe9cbe76b4e9825f0f2e71aaadae11cdbc4ca0be1fa3c729b28de61d3f5d8d853924f17d32fd77ab6c4d4d53aec427e0923dc0413cea8d84012909405263472fcaa34f7623670e70ebcbd9585c06fe42d8ea7919a67ebf7373a0947845114bc6593010d4a1f02ffc4d8760ba27423166e121a7295bca007e02b9664e824089c0867c48c3b1c0ccd6f6d569dfcfb48cb22ea5fabb289d0ea5de84bc410bb11e6f3bca05faad3bf81779dbf65fa3f31ac0dc7ca9104cd5a55c68043c911742ce16262ca55177ba66fd2a564bfbd78a0366367612a09dad842972eecbacdfaecdce42defc48e6eb649ccca1322406bdd772a862bfd5a18d3fb063b4a0ea071766f7e6f787886c9a97af54ed256ba2c92f99c6de24a24876cc335bb906c6b0d54f4b955d121fc9b97ec192e30124f331c34490a8bc7444f8d8ffeca8ebe7b0f8ca9abd125331d5a2547a55cb116b4232760d44120385567143af5774790e9888145631ef8e196dcea5407fecd039071151393615741136d856c7edabcaecbaea1da52fc72ba7eb71667e77024aa5faa3a1a6155b50f96ecd461723bc78bd1e33200f230f45e8aa47d5c066a8480b42fea230bcdf7341a90f4aab7aa06cd761f7d826b440bbed8c439a391415151fa2101de320eab31374f86f8e411d2bf91fa848692227b2300d185aa81d3f312c2673b3265aa9b71228b1b8618c245144ad62eb831c1c3465327be4c83d37fe250919aa1877fe667949e2dcc965b2852bf1840ec865e8dcd63b015bed360d92e68aea773465a3a942960d0b0881bc1a1cc87cc45143d78093bd5301f3e2ba10401a1e507b70d4a6354fc96cee5684b0eb6177fe9a14ce04c5e9368c4f4c454c65faf07ffd273fd07099cb32cfdc7a8100f0ef4ad4ed7751a6c73a3669902068740cbeb02e86bfbd2b861c236cbd0aa4c57f98dafe8cf53386e273b5a4cd83997a2f4cbf3e4994770bd8d9dd99c2f020ec95093022c59a2ec748e77491a7fc6219948ecbd129790734739ad092b5bfef2c7824934c0dc70334a346d41f7fa3df4594ca2e493fcdec209c9a1f0032e66740969cc7200f8835dc08c0df560326c4bf1abd3004c082c26b67c07c99ce7d6e322111c13f4172d087e36f0cfabe4bf0b0a98b472664d54bcbe574c33d2112ece57bf35514254b0ee9a5457518cecc26be79bc2eaeb5217bb29438bd679e1d7daa649080b14a4a9fb8067ede385ccbebf4ad3e9cb1883e66691d02959c27536a56f8e737c1ba30a35550324ff5d2bc28fa99382c09a76aa91f570bb5b68628b43f35112a489d5ac2801d8b83f08554c75165e43492c3d241613031102e4349231e252ac9dcb18679047445d267489ccc487c14bd3bc783a06ac0fdf1c95866e2ef4355a5a2d0fa3085d0446af9ef0d24d6fd5fcbff7767084e0c069cb5159b793e915bd3f6e4d34ba2566ef22226a2115fd646cea6e914c9cc32d003c539b594701f2a93740154c80db1892a55aa4efdb8ef63bf3c1e6a22faf1317c624c924e5616a8a76f90f4665e2a499872eb3088dd64b3e6d9d7207b099222caff5d422dbc32787364cfb62b69126ec4b429acc89cb488d2a287e26b95c202d519e8c9116e0e8ce3b8cf334efb42513f53d7f1d826678334679219d8a7fb0c90eb0b0b0ae13cd19117475c023a7f81f318892c6acabb0d539130a1aad525d6d0a74fe9268c84c825029179b26ede970671935b639943a8110011379f4e0d2e1018ee860f9e0c1db9fc1d985bb2648307b0b33156bc896a2bdf4425d091f6c09a458341a4da45c07b50ff191dfcc9312f12e0c63574cfeadda8b3071f89d935a86f5534155d01c1547786a4e5033c7eff0eea35d8f8890368745876e066cfbcbf57bc2c8088c0cefe2fa503f3ff5fe50384f36935f4be4efe0dcaecbef9c61d067d8f2e213539bdf4db28cf34de73480fe9f86e42b0b06c7a9da86a999b0f1abc1d7b0a981343095c869ceb2b00b13be3e9755d6228a5313117b49f14742ea745daa449377a9c04ce35318bb6094ecf22a370c7dbd683a023ee06181622953cddf41cd52cd5b3b4b0dec471f0084b47beddddcab10725f14f1b461291df8b673dfb2d1678e27f19eceefa7a9694a542bd0879570ad2402e1f4dae69bd3ffc2ce4a88a0f7db03c568921ee41aa0ac9c00b760fc2f2750cb386c9429bf0b2ea1a72e7b0be3a0fdf8409f71c436f245f4876ef2e55e5ff3ff1b590ee91776a9b9a7b5803f965c56b5fe898b21cb91860b14961fc86452d3994ddb7808befb783717b1f51c19c2c0229d47ebc0d300841b4d75650a88c1bbc5c54881f3a021da9db2e4487cf6bf7b55793a2033dbac25e697c6bf651f83939551e4c4c37b6f25ac75134c64e9e3b1e6aad9d2aa93acc375da3444787aa5a3e405fad420b4a6da53539122630d525f6d49ce03968023588bc4d6bffdc0b89fcd2ed10368efe0ca676e343783ddd9e7eccc5f54e049ca29d2e92632f04c936fb57560b1f439a91863efc96737ba7574353318c76cd7dc00b066c529d5e8acd8851b8f1a7086d3f73069d3c7b1c2730e58aeb9892ce70e425c62122ab2bf9f6810f7b9f4b7e026113253e999b2897bf2d3c0d1435c4ffaf2d2684a1191c879c3337fc160625744881f383e3fe85fc5070deaac12c936d1d026388f0ffe19c67352b5c92547513936425dc27f1ca83c64eb5ea03e7fb0f94b054bea2d712dedd8eb005ec0d8b6deabd5bdfcc72721871e627e773a13d92f7000a1c1d108d71f5dd17d207a2ca5ba2f8aaf95a882", .None}, + {.Mul, "-da98484f8724f2cec61d67c3cff08c329b41905c8d61575a79c54674e26af0eace930cb3f7defd30d46a3347df2eb9f78dc31925d40aeb80856060f4237ab96c13ec6ac626f4acdba69dd2f9104e64b4d8571bf91e272a32b445cca02837995b45c265b510f5539a0fcc98f7f8d11fd027eedfebf5f3aed0182117e413833e15b6feee2526443f766459b735173851aa7c81ddc09991c4d10e6e62727da6acc33edc7a77174a2663810924c00496a468d5b18cc8dd3c1158665b6a949d8b18bbca3451dbd71c57b938609118d7814825770d41e736bba3753b512fba8ddcaa85e160694e3b157f2a9cfd83f7eb6b3cc5a99317876d977f9dcd87d468963dccfbc01f70f075b025deecb2fa605e7bbe9c9bca4252fb6299c68edfbb3bc2a4e0e9ef918dbe18381678e29b5b9889d20ce58935e11625a6a70a0e75f65d4c66a27d562563bc0cfb0606ac447f9ba8a2c95e026f1a96752e9df5b0c1de54635470abdb4b786f0c8192ebfc6ac274d210b1e1e2da85bd5a646e5f4e6f3a60de4969b510d98d56ebf6636facfb13e37c38fda3c90f6084150ca981ed510b6bea386daf76450725015ed4ff556aeefde45ec20380b1fce7bec7fca0524b2fad27901238a959be7035f98048fd213f08db64d08682a5d3d14fd25eb7943ad1acc098a4c2591487f7d4ff5923cdc64e304747995e90311e84eac02af2927158011ba632f39aee12ff8d5b3d951c63ef9374f399806b3b67d8feaf640dcd6907dbdfae6a8b376e08a0743ff88f98b17430e603eca45d6758fc8bb02c483cf04898f5ee9d6dbb3a08496e76dfe9d723346e044dfc2c39ab9373811883ff27c032f473da0fc9c4235460db89cc7d54b3f723aaca69f21c997c93d7cb8e52896e63347ec338e3a242cf422ae66856303da8d8ad735d86ef3ddd7d84533b54bda6d8640d4d3b9125ff00fa3f7c6fb96af7e48ac1a792d14eca33210285f27a303542a47b5572c00092640f597cf488a3d6cd7b8042ed3e2c87ea006865186e1756dd62c7175f16a06bc54f1301ac92a4ab17efd9b50331a9486367c200f35a56d06d3279b5d15c6dd99dd5ee4f2c56510d2b343553203e212419cc053dfba44fbacd3da89982ddf36cffe9d1fb7880b6c1f938aa2305ea0c1e0c0368a64c2d8b948a422267dd201677ef6d137ac9695fc115e6db85f9d5723dcc1fe7bf482905dfe7e5a8b21839565e55e0f346ee333650f65d77b6b6f182c9917d311e3950acfb6569eac3d949a7950b2bf35161d2ed76e6c4149521eb63366431b9e15db3a796907965a9f96c00e5c4b63064a914910e9bc504b0da141dd01a83d3dfd8f414e0d1bbb0f9070fc3689ff5133b0f100c05168ebddc0439747a5462de1ee85f597e2d364ef7e9d685674cacf84d5085b80b8cd94c689d32b33d6679c3959a6fbf57512484f1600d9e5c953b96f19a8a7d84d39860bc471328c8d01195e370983777a373b54c9a01c4b64754c0ce157823840485953cdb4fd4ad4d6f1ad92d32a66567bfcda9b8113317541fffae4ea1cf11459e254204a84e2f3c26a7cac6b98010f333232e1189a098ee155b3c529631d10c1f6401aa1178fd608d4dce079e50e2a73325271dfa78e712fb0a505e5cd98e8fb4922c91b65730f862cba41932522fe6e867b566a1b7565910ef81d0a2a70148c0b673ad4d7ae3ce97ac7acfc6c12ab60d4f820dd4c02e3fe0a332ae7c58b15ad9c9bfdb09e98f1199090d28cb29245fe183897312843e46951d7ad132c3f08f0bf031e438953cd57519a00141bcf4fdb9f74d1b965eeb055963369e8586426f2280b4cfef5f0118f3fb25b241e37ac17549f95ae1420af1d4afcfed63bc84ea317c71e8f9e3917977521de238acf00bc476c0fd4e3c397c89328a74d53609aa219bbd130db76bffd333fe17f7f6cff7478f7857c07dc21e1c2d06741b1aee1b5c7205ded529b0b61b23facc890a4b7e64763bdbe13b15722251c1680ac02ec5f3f34dd28ec3e9267d6db148d0de94c60dc81425e34eebec3991fb3fff80c8b3c24bcf47609fbb46f228b91dfe90b4ec7fe383a64d6b32dc4de42f5238e5ff345a88e2e54c7db26a96ab462a990752b2ec", "6379c84df32c5722cff44fac37e32bf9521a4ec8aad89883883ad02b8c227c968662f6269f92521b1ba949dbcf6c05c943116e382e81a44f11e8daf7a1538cc9835a7c7a74aeb60832defc6d0d0f97d4434eff93939d1b82fc4c6a7685b9d3f95b11a59a3e0473058fc4c87a948a8a8a0fb1143106573d6a3b8e8954e5061322e9607cbaa0373ddd22531dc0c1afdd4e019b2e1b11349625a581654d06ee023f5f979b5be518885fe09fe055945b3a05b06f6bc4201c5aa2e85d3a6c6394b439c1f80efdcbd338f1590d21f260ce8ba35deb8f4ea8e92fb85ff1c4834954a83a839d8d9524011c63f12b0eacd5a3ee8b1c8eff829bcb0bd08d844e11c226e2a17870c8ba321a42c597cbeff8f65d6712d212e38f4ee02a5ca020eec196f5f893828e4607184c18b02e08abc1f682d7bde60cd975729d549669441ff59955cf725dcac1d1efbdcda9ce2df8d6ce0e4e1e7a5d960db4d91448c1b338e4d1eea9e31e01154eabc790afcb1433a980b2f93174dcee6808233fd9168d5cd5123958aed2876bba1224238bdd35f1c99997ea1f2655b84cabeaa30a43adfdacb88446d4cc5f99405cd029d9dfdad244451bd1421f45198fea33001fa13c20305a51adf44937d40dfbc64d464a903c93e0904c8ac1b971c28e9e1f8309f74c63d53533181897cfc386176664c238756d81f6345a5708b1337f52604af04770b7fd23abfa7b6da25ebbf8799626e6d7b7e5c1c1037793e68f1ceb3a92d3b5b54c94e03592fa99390148ec1e774747aba39ab413340aa5f07aca1f09fe8847be122fa53e8d954f5f293a15ab77bef210acbd2600c12a95549c1b97d0f122331bb4aaaaefa8bb5781e61bf89807aee7449642d2f7c0f250c1552b28fe401e4d7efb376ff4d9c89a422296f8ae6d2b1015744691373a8208e7b24c052ca12ac45760ccd31709fdf66d846d042fb0d61d2b219b7aad1cf3353941111fdea15193a029e038d5b3bfcbc93ce547810a9e723cdd132b77620fe816c3e5baf1f548217f150d41c16a4c6b64c65366e571a8e52e30180d4668d1c1f67ed239a40b169f55e5669c0555057dce341cc1f9853aea7d49e86e0d6b59a47d29ced062312d695b708f8eb4b2ec7967aca5069181d41d02617b9c88c82d5536c5bbcbaec93b5d4e91118e87d2b063faf439bcd20568702ded6af9afd28bbedc445f12923e97ce9991c15400723f4fc6265163456416d32d8cb9f81f07b18d26b32bd5b2c8dedadd00668c7dcc9e5b56a603f75a0ea8c247b14ea123111d9df7c73d31fa130baa05f57d20ed9a7bc7afa239583726e1ad0d9debd6a6ece286f6ffe631024130f1f289561c23cef1c775ad941088f300203ef9680556f486eaf62a915c07cc4885ba4b2ceb27e3984fb46d008786162d95b524139fe682b94bd163505af0bd8486195dcab553ec0892f5d08f38e113aa59377e12acf2ae402d3a9520b9c36d944799c00d4d3ddf382592325ade99c2857f462498cd5c4698b9a4bd6813a6fa7fed677b5db81299006b06ab09b32aeacd16156dce5282b3e7da70bc42cb614f291a2110f14c6f7578f29c7ed8efbeb16496ea8ef6feb5567a7d117eb7e38cbb8322f0943e983619b1e4f636777221966fe06b086c2d73497866e5f97ba2bfff71cf2073da133d76aabafb2fc1de042491e3efa950a899018f93fb4df55e91cf1021da8b518af7c4f5269aa1f679e8ea816f48b8c9157d0f4ffec5e06d43784ea1102cc6a43dd30e313602363ebe5ac53933ede33c74a26e9d81a4bf3540e20cbebc98a20ece1bd4dafd1aea7bc0215e54cd72f663b7d030e509d26954a9a71281671ec0f53eab9af34f78789f7be328193ab820f27d2c54ecb747f3287ecd68b123e1147d5b02ff06c73db3266a684311fe0fc9eb4720c0be89cb058831261704bb9720e3a30ca6bcaaa160a4d2f69fea0a02a950976ebaa31f7aab6ff167687c5196eb76791c56964306427ef027c1a859e602738746577ca625c17b7377403aee9e736fc0af041a9754fccb911c81d94e4d5e21e300e9dc5550c9462ae25cad61b450699c38e686f54f0178ed297093d036b406ab9597aca47014ce9fb92f012bc2d5", "-54f0e0fa76ca7514a37943f61e527c67d100194dce060590e794f4e9a4ce65218b742a36e2cebf59a5923c3946bb6f155ce54340412564030cf7f0a2d31301f89f8681c51c2089a8f0962a5b4cf8b090279d313d979693428851aaca8678245ffa821c94f9410ea8afa541525b2a911192dde7d5f4ea4ac4a4af1aba878172be0569fe7aa174fe388a10fd972122a602a72bdca7dd867b25c7950671d19e2e28dc702777dd511c89113ad72079ca2df158d2cb0d5ce8f819c99cddfd038eadb29e4d1bc3a6ed7fd3cce3acbf8f840b9ebfebaf2fece1215656d496606d954c282e1d2d3ab8b8c952f97f8047155d8477ae718646bf3fae94626536c04a7cc7e3c3fff6a57cf63611e955bcef7206a9f1bc442c8bedbd264b8346cf707360277c5fbf959478b062f17f8227388daf94bac57ec5548e442bd2d555c34f9b38528221352c830c1bfad6559855b4379f8c249cd8a5238240b708b3e3862d8e87fa9e46aacd04962ef3144d3ab5c4344d1f392ebec1a3fe96dd7b2c6b84ab4492a30c309ed5a94bf99e8b07b55b87ea2e7d956a3c3deb39e646a2296d26dddbae57bffefaf4e8dc5fcb08228958d447f3c5b56b88fd88432dd96d3ce8b4f19c90cfbe75a65244282eace0db18608286db5f92896135501517df38486f3dd614cc537b3f909e4b2a99e51154d9b7e59009d4e13e7aad62fcf2557732834209ee10a5653f40f3925af81bbe24097bbd14a36ef922b4fc0897dedd44009f33bedde9d03e91c985ac291e8f5675a5cc026ae1e726d60e3e2b88160b48b454a004324074f3fb86ccab75f3cec7c4e18b51673a7bcd6b8bd50fcfb0eea2233d60010496f6f2481b5ba908b47dbb18d5c0e7c9184f38587faccb7e64d8cb45c5f6795f5e4f99f2a8a5a3d2d35348dac08a61f7269a97bdfbb0822da660a4f5abe61b6663e27f77b5ce190d7158fea7e1bcf686214fd1453ff82f4e4e2498b8ae0abb57027af757f0ab07f116ecc101026152e97bd8b7dd1a98c2ccf25727f2ab391307c9528a155bda3a2d1f69db3fea631168f52cbc5f86d38d1d1a91478feb7e08d45b0ca3599fe29f86f180eef1a1d979bb297c0d4e12a70f9d4e5b2d114db9b3f96dc7262faab988b3be67067fbae5aa4fd3c0cb59e81bc133e4eaee967522ed4a1ce9965f51a5c80138e56285895ec87689f1bf003cab59e2244ecfc7340d5fe7a2dae985bf0e11e8f437de5f1240b33c259667f6b9295482bd42b0640239485232cf6f9a290df2eaf07424881e812167b811479cbd3f2fb4fe94cfd817842d7300e5453610b0d9b1b917f96aab04d2d4ffa8e90b7fc2c5543c4b2ea609e52b49fc4c119c98d7f1ff25f6d9fc1e98ddd1af6563bd21c3902f8ee2f1f40803ee13cca8a91454275faea7d5c8ce139c28c2bd9cebef4d6208ca3f78707265daf916029f49c66f192835a2d9ab1fe42cb1b4ad7cb65df1abfa5c9abe7793140cd613e0e2fe5dac74ab61500d1ba45c3678aa5382f5b017cb91bf0f0b2fa27fb17e04f1c1a8830b8982128117fdcb1ab660a99ee5731f9183211ff40d33b0b62d0fcfb9e7357099cf9c61d0d22963c38032273c6247ccc0894fdd8ada320f06e0366d5022ead713811d7775f2c677cb6314a9b0946855367efdd1d333a004dcd637cd84a6407b276e86d576cfb0578d31703db2a66e0304e9ed573c6345c4dfbe0c371e7a291c047535ad4b378634e6cff8eb320d8b45f4a4d694e3e7a841f7ad6e13957aef3c9266d867c88cf7325281912b7dbbc904710ddbd205fda6dd69670be6e63304be2b66400cc3205be0433ac74e6e0e83045061cfe9e92074ee0d6ebbe70403db8c78edcefc75037f2047b7fab2b5c4a365ab08666189bd52b7d2ea10d5a2c19582511afc613d83f65f2f8184a3e75026bf63954520be26a5011cead5b72ec4da1f0c618d20d43aab7b73f9d995d3cf7d8765d1050d193342485158b72c86d6d2dd1c9510ef6666e098ebc84579e60992c4341e98442cc11a71e8057a19fe327a992c515a51370e19f25fcfce26661f567309c6fd09c08c8b9c826946fcdd41488b37677e1df46c1b02d4af41ea3bd7d576878cda89c0bc2c8caec9b5a2cf76ff9c2054669c9de7e17f7a214ec3130825eaa51ac397acb276a8afe4a0dda62cf8be871386d06b75cff5083e92d22800f9f3bc436863037f0b053148bd6355e44b7ca8479d260d48c950cec5e2c087d9b68bb063cd139deb85751359d9d585f3b87970d889374a80be78af0776843b6b2b4e655fdf12e6389f3b2d8a4127b897fabcad9be705fef8c8b5352a5bd3505dced60d239837bd64d77fb504c100c7f1834f9c96b96260b13bfa8768805f104381dfb97435152d34495650afecbc6cbd6897d8270a72087a4244a1f6c5378b9eea8cd8e725ece11c2f64d582f89cbec460edd27a07195197edf98b591f501f737920d5592fb7afd39c9c1a9ea6c17562c0384abb91c453974658a9a5bffd147fe28370b25fc5c220b5420675d31b5bc92ddc76a6eecf142dc6de6cea4a63a09a64526fdaeffd5339e4c3f6551910712dfd221c157f4f6f9768c773d20efcbd15c8e86d644d210e1ca78240df6a41aaab664c379ea5a595cb63972025182397811fc03f2f6300244e85818e05415af2601506a103a1ffb6fe34775e71bd860efbe787a9b793c78b3b2674dd01124664b14d54938ca8fe1709cec1965757e890bb87ef50bfc0a4d99cad6f8d2d1fc75e593feee78cd0a5bcaddf2db0d3b8103a540114ff7d44100b2762db8e05df9c1c764d8fbf5b2e0d2eb6c64fd7dc1a1620fc2146453787e22746e92be594678e7891fd09576194332a7f5d6960e2f79ba9e1198cc973e8586f7a7563e883ffc7e6ec888f10d4fcbb25f08645f847dbdcd17de86c5fcad000006278b3a060af5031ad055c8cff3906682f941ec38980aade7a39ee446b62eb38f436f3045ce257e667a2fa8350a371a9e02fb86e3cfafb6ac03609fd1d6e80faad65ce3437dc7feb91b77c4d7fe990c632a733f0be1d0a82f217e59f0d33aab4cb588ae1191efe794f4c61a5278960a7d145d8e751594921c1042c744c65f7624266f69d071c9d05bf2c36380b567e5f277d8bda0bd2f6da30584512b20ca604ced602b3d6d8975712bb06be9d67a638385d74e681d3cc6822d27479538bdeefad818f01c6aba62f6978a21070c88f44619e0ecaf16ca1d581ba53bcc7ef6d24cb0c28b49c05903dfc751ccfdc2601fc0eb786b25e30ed12d4c4083eb2fd06353e4c74755ea93fafc3132c6eb4b91fdc8de8480dd93c86e8de0591cca34abb460599aea2a0876571f92a4c8535b67e5e2d3701a05d95d7155f43b0a1f689f9c433191338d61eb8fd2e9c843ee2d2e77d0754c8e5508432c0bc446dff796f268923cd26f76cc445364485c38cc174c7b3a63752d629c505d505fa579b6d96e1eb310fbeeb89e4fcfc99433d17309eb1672ba1b2e37af838607c73aa0fe03c16264fb2a52b7f79bdd1c5f6dc28b06897e7c9c503239a81ebc0327dccdbc6a61773be40c1c9a585a5873d90d4efbf4d02d37e7effabbe8d2d47870e8de8992b2bb452233fa6446cd4f50ba324d775a60c610c627f8c70f39d45f46d3707c0e870b798788a04c64413053c941e41c4435ed8fd06aa19fe7a34eb8cbb6a7f2171ebf2ce83e28018451a54fad08470de93193d9eed75850c57adf7210e9243b75bc0002964d140dae37fe12a2608545d91982206e6a18d7a5a3cb78ddcf874474758b7dbaaae354a82ca62fc609acd8bd00f152d25600f1f1c3676338c8d81943d98ec09db381117687fae8e388bea48b991a25bd1e063248be0589a906307e978e87daf059fb3b97ba08f5f5fd7aca4b28f282911b1c0279ec2fe32a8fb07776da1cea8351293d6d086019a59e2962a49bf03ec95eba64c9bd1ae06e891c80f347e695a8e029d0801cacc4db2f2ebb799f875c5a8b27eeff12a771c00cb4470d5c978d65c3d420c85c653a6200ef9d7eff36d65a15300c617b1ce23b2c1c0f0e51f0eaa2ddd3dbf840131b060074d842091f6947524f26ee43d2a11f5137dbb4e9208fe7b2472e47ba0eb16001e3a506c708b7b7aeb7aa24d19a1a30de34c026c4c1eb0b12ffe3c07cbe7659d0a6417a36b8325a981470607fee59afe0a6e79d53c0b6a85dcf172fa85a068a128d1ee51c125c7b3c9b44720f7baa34592745bcabd09b65c", .None}, + {.Mul, "e9c7409d088359c4d0ef9819fcb8701703f19d25fd6e30dfb9651b237d33a00985a0e99a54de52306be8de5af331fd267cde3335db3b0dff33c24184ecc5dce2060433e1394439450ca9cc313ec1b3b0855e7a53773b17bb7ee11d536b972cf34c10fe34b1a88c8a62801911bc05a3b22c7339687fa0b5ed2a54388bc4840ce9b0a7726bccfb75dfce943d2ca72a1784f5d85c9aecfef76992e81dc4be2c3961f0187dcac30765a2b367e774985420d89c85ccdfc96bdf407e82d8f5fce4780e33810ad369e29a581d60d8234cd39493fbee8a120d3bee4944a50130da62beaa08182ace6a13774315305be173073d7eae9f67c63266d2a04b0677131297da50e3e950791035564a4e5321eed73454e971234e0f841f098194fe5edb001f4487f228cc41fe5235af24a9b297593b414afa49b921e1dcdd31f1f5688ecbbae349dc79167015d680e77da953bda03b00b1df6a69a88a0f3a6f61b1d55bf5274792350bb90b207e61edf6458bd90e22729af2bd4a3e41894401fe09625983a25a3279ab0c7cf8ecad42850f4b40d5b4f127e19a2f4903dc03b1852d7d5c6960e0d3b9b710aff6d914404326e0321c04257a49ff2329cc72c56a29c6ee5cb5adf05a314891a46173487748e6bf7c62b32e9185a62a88d350ac4ed6cab06bd6006ebdda42213b27832b62b02c576b1ddaa0c73713fc804e4c0bf28c603057568b2c7a690bb468858e896d1ba6dd6b027a9a3cc62e553967fe5b096563defb13449c711485538660d1dbffe83443ef099b96d145e8cbd2d32993c93f0f8cd59124c83419e2bdec3e552068546cd2733bd6d6286d4f2c251fa88d6ace2e845801a33692f7ca008a912fbb5a6bb7503b62d40231c06cea6ca85df9f9e147ab9eb1b464bd86bd912e1b30497ceb726fb50c1539fdc14bae085f7f70b1a9fef580be91fec7a0172368c4739393e482d0274105676a3b609fa2bd5020c6096552ff6e65091f5e07a57d4556602209dfec50d6bf14fa0dd9425b95ef7780f91c38ec2d30a9b0e20a911ae75b0102aed2d96a94bd95abcd84a4dffd909eea9b3abfb6d6e120114242d01502164bc2a087b3fa462bb55957ff23969f85bb35f70827b752af3fd0632975aeb18fc26ae19e2957978a4cc998b5871767bc5e1bc065733af2d0ad227fea18979b56461fef0fbee9acb4a1cade2d0b6b0dacca8d587f0ae79de904b744c81859a5c45f38ed5639b0b0c8e370074ad07f3d7ecfa3b8c58797f23e10b5f96a17169b13e571a45fa1fa00d9cc2babae26038da7cb908ffba33e1a56f36bae67282fe4c5ed973c87a1eec1804b49e6feeb7c802e5e7fa11554accbcb5424486c19ab75c3670a516bde993f7ac476b51c5fb13fcf078757cdd487d376f890877e08405a9f0e3b1485b98379ce0734c969bc3b9662a183440df20c1b6cf4764bcd6851a5e4d8f58e51f771f08fc14b49d2ef22120f0300c6ea072adf3b1f452ac0f8cc32c5f454b599bbefbeb089dfd5972125749c6fa4f7801573bb69c87ce1932ae38a1aa7442269749152b3207d7395dffef0757882d7c8d0a3ddc068846d8f0f561203c1fbc79872abc6dd8af0024d1701b7bb218fa43e05f15afdb58ca633a2ea1a3b39261d7c163eec4d68ad205fdb12c9bf0819684b4d6c661c6b2706f4832697f3187ec2b07c6c1865f8bf6a520d67ea3fdd8958d8b2cc96a7e9f5fb4bcbb5f7fe9827a8647cca14c5780bb6779a9d04d0f3503f043c7860724acd55b644782a4e69a44690e72a2811896e279947ebf42698f50e7bcf04ddd8d221dae2044f050a63ed6f408519e7be1a4f5d1157ddafc4268604a6a28eb94276ea0f0a0af1536e3660816bd4360f352e3b5f8511ece7552960e775f2c708b2e410f1c141d0a373cca215e22b9156f861d373c3802bd61959eeca6c5b9aad69c6abc0cecc27cad86fbe66d9dc0876c8c8aff943bcbef9fcc50789df1f98a32caa5b47ca75f1b7dfef99b2603666a5532b91dcf9a6f07d957c1adb197345414fc7a168b7b135683aa9f7f7672062b27330745425d09d84083fdf334953bd838d308b7086395c6093c04cc9c3b00b3859b7c5d7ccc81186c9db8b347d992f", "97b2ee8fefc4dccd0fab4ea3ecd6085ed2bb3274877db7a35b869b009d37e9eac87ba890aa974e6aa8d11680353b2bff1b41822cf6412ec19a45da08bd447a374d5cd29c646a0431df450d3f5f1f9471d3a34cee64edeae54840afcbaf78ad4bfb2740cfbcab8f5806211201b55da69b3105d06cfdd15b77c14114b7cf8880639c7f23c27326b6c912a03e068786a2a77f9eb428f8e9d8038d346cb5264504bc55704008855099e4c1685c06f672322949c7cdc39c863971adf437feeb26c5c7eaf4acea750cac6ff7b3e1ce41f71cbb968ed7afa9bcec71fc58ab47c36bf2608134256345b04fa452f11173565bfd0759571f4a7731adc6370f6e1ae753281da0c796750cd725200ad6da99f3b235d5ea14cdca3783673eb8714201523b091dcc5aea140854700dbd920a97b065e9fe36e3f41bfabda71bd095ce9a1c7d4be974aa9f812e6c95eae4681455a0cd35b2440a20139c4f218aaaa3e002561131a282f27744ce32d4a1bd08842c8bd0d2a0a22c378f32acda0b0e1a56c3aab963c1abe4dd153c571845c7de1a41e3f43d7500f6a2d924ff126cef08a6177cc45cabea01bdb9f6d1fa22911342ee28a3972755f33db514f2c5a4f8e53b57512d3240de0e08b42e408a784b9d92ed840f50fad0b7f4b3c714dccfe77b0374b6fd4a880ff3d20c1a813be0009b12a885d709a56d0b35d00b6deed144bffd166ac44569223485eff865aa90da82d5cbec90e7038bf6b66579b2104f7df78daa839ee184b2ef057a189317d4278cf8a84d0ca99110efa04bc5413b3714c65b7b149e9e7844cb711112b4f1131c694631ea29dc9d2aade10b30474f651198b8c7a35d455d7559fdc2ada097453832f3e7c5c7bb596fc0e3fa7e8a8fe1b1b4e574c9d7359aa9fd1553a6b3564836b1bebbda65f740a37e0b616f84288e2da93f230735dbcfa264f60427aacc23c4f796411e2b3866dd70e2770f9b9a96c5397d3a57222f804b4fa19d7f352a162f4398eab79b5848514f339aca955e2c8e3cb52a07af75879254ae027288906ede87b7ea73b741f3d9eadd75253e3ec3cf2d63a33510b1ff5fcc11b57de6a5250bdd2fc3a9cd5e762d7ac08bf32b240ab9be77525b8f3fe88a4c8a45cb20a4ac346b31bdae3e82d96876043ef222ced298daf64615a4414a75540437f201dc2e4196d6e12d2585e88dd655da12ba7b2b4e6573ff5fb295df467c9a5f2108d0bb2b023444a41cdbba2dca68c77f4542fb0b46bdb8abc8fcfa0c7eb4edd1a637817dc393a10bcbde420264a57b389493a155a90d6b9769fe8821d5a8add34416b3dd927566fd0efee27060e303b92925439af23f114b263f04687897293cf5295a0c9cf38709d91feaf5e954aaaf10b600a1757256ed98ab076e0493ff0b50856e05a66ec5a336b590c45db591624cd996d1b6d8c024ddd4444fd3953323077f6d15a41f21949a928514cef49a789f459108a3e593fd017f15a6f0de34fb41173d41d066e6b2933076709b0968c8f2383f8be780777aa04b8a8ef3811209b020599cc03d8770fda27621da91719669f273a3681c4642f100dd2491c291a1af96154d96af3e447afe6c2167e1731493f343f3c8e7c761ed2f1dc8e478fe7b566b1b54b21f3c8ed21f1a7f328968735e04cdb82c515e34cbbdff3f45bda613fe2e0e5e8d2a6e7e0d3f5b7e774f05028efbe6a3c0a7ec25fe11f1416c7faca989fd745eaf3d03f223e78441ca76d7d4ba4c7d956e41b4eed5550996da698b1bba203bd4f3860ca9769c3fc595c00f1eb78b9821fee86971c965a4e211cc616cd73537aefefe9f823ca3cec2fcae723ff849fe387301631163cc46e06f7476bbf8b6d7d6f5ac4fc8121fe1b47eef7b705269894fd2eca84ea8a43172c3892e76fdd719e86a67157ce4c9ad58f2653cd2beed66cb046260decda4058be0432f13fae7dd1430c608c11c4efe458252c603b337dbf64c9bc768454803cd8cb077458f97e7aefe761a2563490b3d56e7159d154e046989fa473551110bcfc4ec901229abaf57c932894de67a0f3e8fb91f1fdec81428156394c8dd4ebef9c3f28c59f26f6a8993b4c86b5605f5bafb124fda16bf13f63ef182", "8a87ed823c89466bf27caba07badd0c69c680a19e5da41e0adc13462c27647942827d6efcbbb5a0cb8b36112a45e67f170bfbc3e7e39cfeb58546e78878495cd06cbd0b73ddf85764cde5844d5dda4a8b1b1e9a91c5aa07d6672cca7470d8147f8aeed486f77ef8df1e3e7e89ec146279d0f4c8a36de422477a733b7839558e92aa9381718a306de895e70a0e0f06c7dadd3a877df7e0159aa58447f6d7b6029764ab77bac4de7e0aa2630086d50fb4de7ff2c2a003757f7e45cc969d07c44e77cb17304abc413fd253967ba16195420a83cbc48a7297ad38628ac23030bb7eef7f0ae9c3d41df017ee0ded92061eba7e4ce1e789261d80ffd556a48b3593cc315e44e132da5d07132ea297e5147e746084730d7117290da1dcdb2f25e5fd40459fcc6ebbbb90b2cd9002bb5a92926d8740426cddf9553a53c64d439ffa54caea83b7fa991f0d2e8329aa3537352fed3fdaa0e14261bc1ecac92e033a117e61e36ecd2c35eb1cc1104874d72754a634efb92b364bf791a7227d1a803711588557a8c04620f85655e2e4d66b3352456747fc76361759a23d9316e9099f64763d6976b32a308da48c657a9b96845f17b666f23c6749628d0a451f5a7fa294b46092e00fb188c03fbb7b3e88cd51027d82314405a133a479180b1f769db65a1fa03e6daff3bb8992ef8362f024d921eb68afe5906d7e95ce299b0292f925d0eea6179a54f0a894b52c0d57968a2bfd48267f1dbd505ac3faa53aa84faa28ab20b3e48f5d9e165e252bd58b83ae27834fd30df17f879edf65eebbcbfff41516278a192a95d295391fca8dfa7460a922cd7c32e22718ffad7d74d3417aa7c19e259bd28b92284d8c259e72faec96424a38bdab3dbae2f0bf2a32bf4956bdb9138fd9e3f9956d93f4eeec56f93f9ea6f1fcd944661abde8e06cfcbabc488d79a42513eb160988536854eeed5c1fb8a3576f847732cff6549745aef773e28ec2aa62b8b054126ade5ff337077bd1226f55a3d5fb9f5d4da529f106832a1d758fbecadd18dc67194e8a2693ff60c3f456b0c591a53e68d0c1d01884d82a9e03335cfa1c62861a7934efa7d0b95b7b2ba4caf8750414e4ff418e0d0a3c8a946636b6e0b21c423d3c5bdbe659d0d195e8ce9188d3528a9852cbd9483aab3831c3bcc55053db48e06d54365766bbcce415ac9db6e3204b261eebf16d11a62ebbe0b0cac11d74cc59a4c31a21247430e1fa26432df9b8c9aee1aaaf17c23abbebf0a38251c4b991c8f36a7bcc5ee5f8eb359afa3192df00a2cc3da36dfea89f8d9b5fb7b650f0bc47f9ab3e15d498b9d2cb4f15561e214edc6333d1fbecb3cd32d9dab50dc86d135b11bf9695e9b0f4598dd4b2321c9b4cb07ed4184293d8cefd75015662c5dec2679102b090c7f0d0e01d65c6819693122a925baf0233155229d7060cfa1ee8d25092e045d9ac82f3ef7f536b846a36d1f792b3cb7253035ba58953f7e85d6aace1563c4e2e0cbd30d6e84af85cc8e7929a714ce460656136a9a142b821eb13ce91a885e291f166adb33fdd0ea956762d5abb38f38634b0304caf6c1d35e2fd89443b481fb8ca26f11747cc37e7897675b1ec077018140e1ec7c0fadf7af0acc69ab4a6720575883121c1dc447b5e5ee4dce5ef3186069d1ceaeeb55bd13dba4cc720c43b9dff920b5c3b512f1fbefb6b7162f5d57e4df113eeae8cd9c072cb78fe92a67ab52a4880681716bcd413673dc04a5b846f2312ff897874df5034bd916d4429176cf9c9d1ecdc2506b38ede772d01f665dc8cca45ac98bc4ec79c337b0f6e8aa05aeb4bae4cf96e771935cd7afc886300ac668da0f319f72197d4b62721e2fbd721084a480c2c366ab4cc69c7da19fb3aa8eb098ab109780d7157886f191dfe45be4bf9e092154279fa04b592fe627d6f5e93e48c2529e2315018cf8a1ca14cf79bedae892a4f52172e7cdc9eef6caa6bab94f98c142863d8b545608341afbbc30ea3382357ce256c9cf9588af0003a93eae2e0fb062ee7bb25156a1c39544a5b9003f77fc188b68ab1226124974f3389bf7752119c4709379fddf96db8b030a264fc46a16d2b8c55d4c6e09119decb6b0c7ff94dd634ab2b20974a02b93b36c14301153410393d4b41cd103d104457c2ec85556e4b6d4ebbfbe5a037c15593a04c2228865f0b2a033d5d0b89520f8c22d58736eca29a49147095abd3ad816c0daad95f5ca45f978b9a35c5d74da10bcd8b86a92efa73edd5af4088c4da69f6dff5b32c62d30639622fe51f2a39220d8d05ef16e131f77a9e2b40f4af2c51d1b1cbc79ffed49e681222ec05621c846219feb391af15bc2902e948b7a9a52daca2ea6aa2d23b77b782af33c95e2feb5c9142db2ee11b0dd76712ed2d67e1451edf48de69976bbe40bb948e1ce8bd4df1e3356c60e1893770dd9600b01e53b9380fe1cf0ac341b36bc79e10d809dd14e30f85222d432611fa8ea6444f147bb4305187e6150cf43091346b4d25873cc45a8c56847aafed2433e420dd82df338eaecdde161976a1376fbf1f7704cba01a5763d4c03d1b96033dd78c50c83a45c85bfae852f9ec14bb092307426e0f2125644d34dfc984e7d70dbdda27ebc8535de5bec9593c650128844e24bc5c458866d9e1ec4c5748b2d3b55942450441019b2dbfc0a0234aafe31565fe231a237169d392fdc5478a21e92d995bd56f95ffa66a656b05fb7cacb7abf4386ee08b024b92ba5a1f136b5997ce3e317cb8c163531ed8acbe2813c3ca9224b053cacbd19f8ca983b19f496ad18241cad68f85cd606a26abc8609324ffa7c5ed332ea8ffc62345a194c9eebb7131bafff63a9ac93245a0ec12eab1d9863ee80f6870e6a5e9ed2bf7c68f92608780ff6cf7b288fa15c2d4785d5bbf239d25dec88cec94d0442c10451b2c5e73d6883d1e1c5026a65a362297b054af127709ad7d51fcf8bcd7d1d229736d99fd7741d638270ac6fc3fbb177632ef20157123d76fb5a47e97307d28f65151691f08eed1e7854d3704f0f39fbbd12b20b4166bfef23661b6524abb358fe6f78ecde791c3cbd1948b540be1bb8ba50a04b35cc51714c67edaffb410092af846d18539706243113444349e65564b38d9a3588e58a41db860d2287d0b0eecb5a7885b600317a4743180c5cce1145a36d64fd14fb8118fb55e8f678642d023272eaa125eb365ec0a5195266b46568f245633843c67cfbf002b340ddd836aa72ff6fca100d95eda5eccd334945e42b02aa076e08fb98bcfc9acf9a2811a8dbeea0177947607a497cbe238b61e6f395700471b40921b20045baa4b8ac5d6d9f1da3368375c60dd38c5fd62b646c16f31fe6af610b65994f614e517d673a89a72c6db00befc9d9af573a422ff65a14626c0e13a15ac00066a0ceb936b07cd8f2f9838b8622a8ff3c1e3fa1ad694c3833a9fc53394b8f91c84b11e2a5816dbc641bb884dd6e5065f2097a48e12077113ddcf1d7073ac0bdfbf942251016243576822a06291ec1ab920b94466e5606dbfdcf1b338695ee69a4332728b3b0cd15f8dcc90d816fe28e9f9c9c8bb5baa7a0951639abaec44d3b66086186495988a71ca32ffd8f6fb787ddc3e662ba0a8dfb5d842af9a7b39a8b0470d7a1b16dc68ab0a9c6c561e1628b3dd9253cc4f1e9d94c4abadebde9977bbe26d7a0d32739d20f447de7a5c624c746814890f9ff428e11d9b862bd1366c07edd39859fa00b3480166fdfd8cf8bc3baa62280e0a9bcc2a61ff9c693927a5d0f0db688e38cbe7a301af7795aac58dc309ed6cd1a4f7c89a035ed60a8cad4865f2f33f42daaba717b33f599583b1304a8e64fd1a68feba66f453a9cff28bb89094211ad1bdb2062d3eaa3c4294446b931da9edda5b39de014c5d534c5b923540313fbd4121c3a955d58c9ca0d572f39c43e85054cdf464fd66d63fce1aeb02d53ade9eba3c5b869b1e7924da731e8d4c89c160e0f0effc53906c3142bcd383c0d2658c7880cb0de7cecbbf9d9ac81a26e186916d7cbe9b7d05a7a39dab7ccff082c66e660bde1b820378db07d78b0eb3c2096eac3350705f1efe433e740ab014429e44339f73d5d600ffc01e7088209b77b15cc2a541d233c91fd879247a9f329f6fe92e8fcb6cb33a141b7b25580fb4c809122c30757132adab97b041a1b4d593fdf8ed17e99c1abce000e205c4650c72f33fbcd8c25aee1783a98f0ccb60d28e8e234fd6036285f08de", .None}, + {.Mul, "a722280cd9e8c7a7ae6714d21a075fae3da31a21a825352c609941085059465049ad3bec6c22946aeb2b7c2471ad3433d96aafc4248f7a58025da3a233ea2642d184049391399c5711cbf0e5a45e3ebe1b09784b010b3202045267f0ed5cee74928151c1d504cbf9c44b3c2d3a60a48debbc1e700801ba5f4063a7bdac7e4041c1a430b51b5e71d4e4a1f0cd5b95272c5fc3459bf6c58bcaac1acb12c799187c5636fdcead389e92824769e8420aa7db46184eab30272adde8f6f37b92235d04f75396d4ba09431438a8d3e4764850cbaf25566894745ed3e4dfd2ac62cbd703f54330cf1d92aff7e6c61d51f2ccee1762297c3a4382117f472a4335b3400bfec2813bfb1a5b2559f0eecd5be4a1b5b2c8470a1755719478428caa54b40d92fff8a3cd81bdb2883439b0b2d48103a0d00d478cb4436af29356866c5c3ce08c35a2f7b4ac61db2bbb35d82364919fd2d8644117fd563fbdcf6b3817749b4666532ea1c634980c5dbb905564d00f828129f38c056de2b5e6cd9268c6f276183a108fd2c0668e64764666e3b2f45f410cb50dd5b8433413ec397225e578b2caaff167a225ef3bc14bb4effc56371a61fa669d530d5b8781d4837698e0d7e5e2aba641217ee6f4965911f78c6d6d9be574420f5de2d20e22bc5c5f4afa702e35076735c0fa1ee1fd8a88a3bd0aca1af4258ecccfa2c44476563d560e7db3779a7157f4c9e8b3995de2a1529e02e7865ce8af49edf6e4c9df293809ae6e67181ecccb38cd9da7f887ab0ac6cc9952c6e5fec47a2d276677f8ccc957183ee87a0d7f8e45a9af910135ed9a94d7da28b04f1ee894c552b7f4b5a4ad8c1a33d8712e47c3e7c86edc53b5542c396e53df363be29e72c4f777a07c55a4d1dc71a4b0f5aa7b7d43da7c03b04d660ffc2d57e17189ace687a93566abb42aa379b2e0891df11c6113c99f004de61a7e39778e0f9fce200a0bc13a8d6affbb06458c1b2b66d35c6c3935d6a43b9dcb4ba01072d25d51443dfac5756ae4224d35ab59c07ebf2a603f7a597575867cfcbd5a1cfdf392c2948a5ba99f02e83def6d3821f55e3a30d915ba51a12e1edb100e0651bdc373123e231b022337b5842082df77b62ea64880af3f998729ac80539d2b8614068ae4e0cd930db5de0bd17024dedaa5bffa3a308f5506a76720e91b284f51519c556627511e8db8ce663adc83f3c03b04971c1b5381f7c77f60752abf070f4cf5f65322aa8341874d469c29ebafaaf94af723953959f371632d468f0456f671eceb64b6ed0004ada5b287b7c58f5a4ebfc45c04d6af3fccd99525fdb12124b6ea420bda15ac812fc8867facdb1e8784a7b1e4bc7e19534b29e68e22b94798969fedea5190d679a1b0438f78a55984da3fc8e635dd20638d78d5c31cd2caf99536ac6e4e5f527aca65450543e3733f474a411c8c335af673965982f586f174baebb0b0f82df1ddb2142110d6605fc0aa94148703588ef2ba89c5d3b557d832afd9e44c125557297cb2c7f3664e4bda42bf968adb61dc714f853c3fddc81fdbc09889450c5451bff90bd364ebf9ff2bd5847c9330950120a96d78a86f22251a1966208d108ef9e64da01558747e4afa9c6fa2816776592fc31688f36a2e89e8a4397bcb48c2914aea0b2c00e0d4895bb8b2f42e510bdbf717a57f1b381373668274e40e5edfbbfcceead4f1f085df3bf665850f075f3ac60f6d71fa3eba4476f96d711843241efd3be866a75493aa4487673f056876478918802662950d7b40e4b165c724febca648cbb246930dde44ce23ca7ad877dc1bac09d0fcefd7d011d8c716c72a33c6fcc3dfbd15e1cdb87828556a446739a18d390572923c13add2fb8b8dd94c6d55c3e0d53d417d1bc738a2d144325c2039f87b2da20f13344c12cdc6a947bcc4a0b1ad054bbbaf9fe152c9b408d5925e8bb833c7de50c8d05b728eea71019e624ee13f2bdeda5a4e6adfd9fe32a297095ac8da56d0d1e1f6cb39e7017d46a50fc838dd268cb125eae5aa4c1836d5ffa201f1051ebc9d83f471da08ff2805d9518ab939c0dd3c3ca497aec21f34cbd75a0b00e901c73b2428a9d3fb0e6bff7571d7b4838575b6d6fcd5a93", "6560017a97c51248030ffec52b367a08c279b6674fd0755d10d8eb1b5934e16c4627249124ad63215836c3029704749ccde2bdbf7e5550e39e8aeb9396055a496876a1e55dac7f1ef0c40b2f50a096a9f97fb60fa8e29fd367598d406566ab8c085ab0cc42ed93fb2dcfaf960efdfb5d6de83752a2b0dcf6dc10a1648539ca78131d9e9741cf566d329f7bbb3b58ace9c9c1b7b3c5cf153047425d22ab66b46b90ed1e1ba872c287374bd92e40270f458f5054a18ac1acaea2e5c86d40146d9ccf34e905f96b88b59d05e25d93d587f476d423d580bbff04c5f1ef3a42ce299a38f4ac2891729976d438d647c91eb76f38ec90b1fb02488073194dff4148b5119d794206bd34b779b141fd193b3e184d81ba060b60c4208e76a1b4e8a2d807ac48f958f7131707cf0def01f0e2e40e18256a286ffbf774aa03f12e88ff75843eaf6f1a90c1cef6b02753e9a5f7422a76f73b446c01035357c38e9524606f76622e8eee9873cd54e12cc6e1808260b8e9acbc27f135f0764afbe4e8df54adb9bf9fb354181c95f6a3dc0139e2af19677af9fa2932abb7aade9bd94ad8e48f5624ede665e0d68868429863bbd7f74ff99ed1771be02eeafffdc2ab96a07c43713ed7c1c70bb7afa7eddbd51263bc4c80bb33c410d222cf16f674de47410bc68612f7c3f9c1d93723a1b169149eb27624db932f438ff8537a912045e53ab0a92bb5853960c71249acb7baa5507686f5c7d881f0cccbb2a6e97402743a638b456443de8d8b91f28cbacf0ca624bd634ced448ce23479d56f682cf09979391993875a860f43100da29fbe533c1a1b84d10b9a9827afce34574e1ddc37fea72e5ef0d28dc5fae838f038ecb98ae756bbdcffb9a0da83176e15ce90a1aeaa5ee3ec5d16ad9204418a50cbe74897e75a56493f7e4c0d25eb0618c2d5744592b58c192d08755075506c19c7f808623b95dca1088630bfb9c12af902317c96857c3fb80bbd224d903c7d22db59cc24d686247ef9bb3954da930130f3c95b5ce2b393cc620ece94e564ca3f3da419b43d7de16ba70b2bc4ac8cdfd5c01a4695637d145d2f1bd5b1dfea1de1270775d81f8bb2ee58cff27566531d8a6ef427b4629b19ca90e0261f9ff6b6c978bedab4638c98564c1f0269ed69f8c9fc7e2fc29b8b3d15562fe863405acfa0b7588893f9669d65c6aa2ff8dc9f5aff72f103b1e0e146727a588f6018c4da184cdbca9d45091d82455c0bd1599cb895be8cd93ea757438485983be99fda4169c6481d03af9b36d2446a935c4d3e00d060b97969aa2bffa345c1f52489096bcc37a085c32970ba2a984b5eac3dafa69667566430153fd8b40a9cc914b92b46e47ba62cea54fa399b690360500954876a6c6054bd686de7ee734ba55a605c318eb39f1ddf9b6753dfc641988ef975a9656bf6316f763e8be4d20e790c88b5684e61296169e4e8cda5632bad3872065740af76cb43329206f7b9f929df59ee7a35104dc7c3fae04af1efd245b7bf5c7d0fb0cd5b55be5211c4e7dcd8eab66e5acd7a5fb59d23c2fa88cb45a39b178dec6ad82bc609874b845165eb90e024a908701d43815d684d4116b32e7b6b57917c7f48b56408dc1b7950c469d1af4499d07928478db4d20b8433c4b958e96e1431c48fc204a2d070d5998609e6f8d8ef8a0d18f5f4f92f3d85359e2201b8ad7f17ee30abee7e9704ff0ad6a4c02102f44e22ebd7afb635887a2b67f6dde89318750ed668bbbb25fbdd8486c32f96597e8972445bdc46abc39da2d497255efbad6c3748418617bd75bc9e17b8f34258ea47a13d6681ba6647b920cfba54069349610797eb38349c13ace625832a34d10f219732a6a7410f5eeca8e1df1c63564c70d61f79e2aa7d4897968f6806d8ccf45720a6b591b8a42e99ea32cf42c0ed49bd67e368f9c1fac2ca96af8a4d3b8401351cb5476d07c36630f77411f6ffb502a0852acbcd6cf6e42f9be767b204338db56100519b4a3e529261fb5bb10f727ca74900b4b019a667e3549458268f8895bbb38ac3c17aa32e61b87b4379df73bc07a326746bbb871507221ff406ab257db945952258b5ded17b0e9c7e6c2a5e29279d6edfe9e7e07d", "422f2793424f7fe1993ee0188737bc73388ff99bec3fbfb23945f26a19018b5976391c4c0ca38fc2e3fdec484f5fbce5e22e7ec48f1a3fd0dbf0b2abde754b813778e9e084923b811a19fa337c5751aa58c3fca0bb4191429aa7ec18df8df6ae59950d266dba75460b9cadd23a87fcd0bbd2c7ba21060f9b371ef1dd47413ea7c25f3b8cd434ac2c1185ba7d91e7067d62521cf00de315d81878abffc8591ffd6f0195739caa796b843bc9bcb227e53c6304e7ca56e9412866b0619299f3ac01ab637df00b5d014485f72749016ec29389b9a2db0c89d73fcdd49e9dd9d71fb76ac08749fb812122bd999f21fce23792821ae8d02943756ee7478d151c903bbcba4af0d158b485c2f57c445caef28da971ed3a0489addc68b66c6921ba15e7d9e6cf2345c5db5d752db46baeeb3d6a53f637ad1232557b9e5f6318e5756ce5508db7d2969751f445831fed3c543be9fbb0e0ffd6f99ee522ddf4afbd21d94243d3647e8538274b1eae50e828d45de6f5e05a7f97ef75ac8117767e531cb55681447f80441a062d7bb3175ced833c2d7e059c9ed5ad9bed713b7cc9e601b8af8c9d608116c4e2c55405343dc7e8df658c1302faaacc24fd17bfa16ec2b39ed85bd747c2b21354b9ec5b284caea68b45e026cb082284fa22bfe37891d1895aa2a954cad4b8c7dddf339e4f8971c86ba09a5d3a6aca61a90bd7fe70c2552450746bbb941deb46577ecd415dceefbf8501a863fc38187a3ed3f30b78c35c5df1a56d6fd389c93e364bdd4504308bfb283ef61f9318b710b6d64b4958d032c54bc36090d1749682c9ef80a7f60628bd1e0edfbd22a7cebcfd3a632917144e6b54c42703c1bf24ee470eb72fa61c00ab3fee7b1c67ebc4cb95fcb3d57cf2cf22e738e08aa05cac2397e3d518251dcca79fe7bfc111fcc29ba57bba4f9afddb3b537c9096847c6546adb2b4948949db83c7fb2c569b7741936cfda2beea8666df7840b4753e6fbb0b816ad8725517b0c8bb334fe8e2facc9a4a39c1b83dd84a4aed771e1b5010c24796f001d411ed8b85ff42ec4935bc27c0c8035cc255420c72f6a8248166e7373e1d41875f06a3d087d14cb81edb225f7e0645d64d13f64c72393d857e1dd87458f21763c6081bf2c50cfca4c92c8d59a5138dceaf2447ca9f37367e3a3377fe8fbc2d30c5c903641f4398084b7a332e4d4022db6b67a517fb8edb8457be4f45ba4718e130f679aa1acd4e8ee40968d6fe11ece7581403044be3e43e1fe8ab2025b04ee473a87adba784e638429e1257b6e5a29352973014ebee7747a71ec4f820fb64255ac97b0d1ef1a463355af27f5e6f21d4f02c1cc68cb6fb615a028231c136af29a06ec41ff74188bbe6ab4291f3e2c60bbfa1b44219fff6571d8df8703f399c597fff8435c0ed290a8274b492580f795f9911d3962502d3baebb18496f215d309b6e3c1205e37bea1e8d0cbd6ff491dc3445e70217a889fde86a03895dac019b79f90b59772ee4d242faffa4044358ba2dcfb12686837b3f4874c930c40a361e47e264ff3e84c93d59488e76144343ea6baaa3bc53a87517f3f5500b51197a9334ab92b5d40ea09b8483b9794de4b0f4aa8155e4299b46b3121d1fbfbd2ac2ee3a220a29ef45e4e0ceac463f66b353d174e929418a71bfd5476ec6407fc6d9956923636535eed55e11d6e86c9c75f9c42f0101a52c511a48c6e8928ca4d744e68f3d05476e2bc67491bdca1df6be8c9c759c9889a36e07cd4cadec3abbfd5afd9fee45c9c4636a1752aa8b83b30ca8d215b33b1b763bc5c3895077aedc732b940ee6e3bc45309928386947d37572ad5f1164632d6a5be53ab2652d15377216eec008c1e684a9a0ce2ffd6e14bb6911f48a75f2202805dea05dd0d51cf8f6fb5a31e463a807d9e9ca59460c6ebdf02bf3f5d0d7169b52a0ef1100abb20322520855872e8959637548348a97abb171a98ad62fcc267566be69c75354eca6af2d4546150f59e31765106e8675de8a0629de68020aeb384fd12d077b418092b158cce8e22902d898a9ea7ec3e7265c0cc8b01cb4806e263b69d067e354bf35d7854997b0d011e5470ac07da55cb9f7e18484bd8adc8da86f9cd75cd82ea53fefb4d65ab687ef15577c734fa25bbe1bc4dfe08f95e9c65fef25b7a232efdfee6ef4de8c9272f82feb190a35a307832ee4f070c55f4b0b75cac260e118a6bb0b68ebacb0f1c0e73d6b423a9f92384b246d9196fb37e8f79eb4e25942b5724ba599b2b16d3d06aad65cad932f9193f70c71bac8ac4da4a760a50760b984b877df2073592300918212e19f3767881f22bcd95e8dc2230c34ec0f26053c075cf9cd7acef901d39acbdc164a63d09ce9c6c01647e0f08df2838352901220286410ff0e8da9aaba1f2582e294f8629e70037b7a31954d96e826dbb3d5649a6969298b2abcb09cf0baf083468f048ba266bae51c376a5c8fa96d047bb48fe75820e01ef06623fec0b7fd394bb5f50cf860aafda6fc3d56822c54b74d9a6cf1e329cb9d1b81c1da034c05c4af24b9719d9bf1e034dbef24ed0751a8b7c84aa3cc9af12aee17dea83002ed0d446767d0e43843a7df98de8bbd04580f02deca4758aa3f0b8419f6da7bcea23bfc42b696f05d080975d338bc097828dea48878732c890fca0d54d8eecd5b3c0c1056ae5acf0934b32c44c84f2bae766562192272cf10bd331902f34d40a011979ebf34e981082c7aeb15cc722d44c2e8553f003ff454d08137f15ced38bb274a0ba8845f3c6df9d0809d37c503c2770fff3ea92b3b22443c759f9287021d027c627bcf9f2552ff1e3328caf791e0058157facd5d2a5afa3080a680f3be251395bd312cdb584ce91b5a80ec719403e50e90f2eaba6e529e579392ebf63bb828ed120fe354799e97cd0c7da77ab82262920ddad8488d6799a54d77dd0ecdeb63a650c3789c77055260bfe20c95a90d1e2e3e8dd59a4f89c77f7c2eb33526d0541200f7b97fe16f71be8972cc2df811b7370cd3f466ae116ee49519a2f9c1c0d8646424743a07486d6766342f65f1d1dec1028a1b850b59fc79bf5fe8e51a61c4f137b4c51f2527fac9ea9b614ce77f640ae162d72d3075b323b43bce58e42dab4d91176d6bed356cac305065cdc642a4b5e4bb7d3095bac85c397cbaef2d002dd00a9b22d0443ee2815b46716f4d0b0c4943fc3890698479754eedc7b8eaf837c47d9ef918a6b28eecd0f1b3063baa199a75377032be599b7074c224a944b544673ff7c09e28abb9b8493ab0c6bd9d01ca45f8330f7f058eb68232ce28d4887a174d4593601190d0616f4cb11f95cee60e843b5c90487642f18c596c6b127e5137c37be2910c1620cd7ea8128844c62f4a90ac771b21f02f50426eb916e5fd70945e0b109252ee64447ecb46cfb33a9eb4784ae061feeb875b2ca9329c797a3b8137eb2662c2f7f7ca8c08c890e8a13a697cd26bf309343000ad647194a9885f513aaabdfb95738ae555f6c151e9021b4274866c29d3db1f04c549e0e1e8f2735b19d71cccd3d854ed521e4fef65ec80490761ba9c9afff512963385b00dbea6d9c260dc0257c7ca8e2fb3aaed1162502e11bc4d7af6c35ab6456c7771888604248e7d7eafea53022ad19ea07b4cde18e3def9630e5c09ec43997b36687be5ea8f237928ced61a9da05b420e657cce020b53432efdbc66a9f05fdb88bd94d33a92ca4eda2672ef735e859a3eaebfce2f9c16b1646c8cb4f86bc5573fd51fdfe17885a588aa92bda50723287b6d9b9dfa70b1c1d40d37d336c1516d43f3d4f47a94f6db6f18b3e621d172d8557e91a2bec308878edc68a054f04d5ab33df16b15da3a5d86d9e68065bd0350d07e162183ea9b47de24f9678165c3135cfcb057c0ab8a4fb979ab065918fb9f3c251cde700728e3ad1605d0a18cf4b562bfb224bcb19bb2d5285845f3153bd7ef336613e1bc894faa0a800db9253572dd852f5cf420b935b2a31a0614d0a7e1bd9cb0823e7728d2b1b040986c3ecaf5e89d94f6d5daef6c094024a8a01089c51c310f8852edeb92b391d39888af1533dadbbcebc4a69e186dbe898959a0b242bb0ec7e4cc49a88f653868ee51129c1e3a3a128d71a9137eec94280c36bab788f3ff065607049a9daa0645f37509625f086b036cb44b51a70a8949c2044347f52ba7b1d91c37cb01e3c85177e53d5ad27bcca1d742d981bc409f1d400ccc2ad9c7", .None}, + {.Sqr, "-d31d13f9ac6770895ffa82e4a6e7b1844c40349b5cd8b8770db6c59d6b49a86013e38f7fdf892e11c76290e613d27690c1b7e12b55878bd117a4e6728d4e8c2a776e0f5d890f8acca2314871aeacbe70ae3fe355624de72120ceb129379b14c50a4268fa25a44eb19d1494afb4b56ae1dff002275b4f78d542a160b809bb4d9de5c66093ff9027ff5a940d486afb797c26bbadbf022ecde1d72d029d2dd12674baab0d5ca5372fe167aef847c2a3726f626f7e0f54784d93a9f0d29cd7612e861ee3c661855dcdcc0467245803a70ce8b933b2478bb62c15374909e2cb523568f71ae06df5903ac10276619acfcba226f28d6a8fad8643fd80fb66f2d36f8c018d93da8bb67d82f3358b41993f46e88766e53778168016d11a0c8bf157f7a0b4b871d144a79dfb37b9a6cae2868180fffc591bebace91116791497486ce0199b24a4413ee05482442e6586de09a23622008eb4c4a5ed6d9fa166bd5944b84128820b0b8f57297693dd7ca5f287e9b1c8632b62033684ceb6105229d41fe4193780c01bc8d03632ec1c21918a370b51dd9c7ced3fe879ccb715eb862f64906c12e504d2fcd5fb1b0a479523cff3114426554c28e6ae2d8c36eac35417d613524408cec26393e773a60f60c716f4d504ab93f3e7ebe386981936a109150fa034dd514840ca9f8e7fec83754c0ccea35f21e36fd304ea072d28aca518c217bd2fc714cc1d4002d14d254ef50bc41121a95f3c461631cb57d04b00db572c4f69caa4cc73c36a96ebf67698adbfa6825f95dc209405b1734cab8dd72dea6d74c4a031793c0979ffcf5d16e1430d00249538bb6af2a2ed3e06995e567cb833f531d906637fce92352446de4cd4fc3d53e649d3ff22306f7f821e49a579e38c22855e27082f5176cae223c6103b13bb812c809199f662546ecb9ab6e8cb2fe19c2d3e53b30ab048cf45c35bf87e8d4d7a6a70b195166ffb8bb110ce146a3534535a1905c0b2d7fe34d767b4f8ddc532cb2c4dced9e9ef6f47d2c6c54625c690bba01da08e4d4a5acb34db99810826018fa2bcf663e9b2150d344caedb26af0780d5e958a9d6a616ffb42d6e6a8225cc6b255aafe6710ac2ecffd1aab1c5a49ed7219999b027fc8c57700c073581e824ea1112ad2b655213a867f376556e142137eb8a045d361684ada126323c26c8f5595ea9d0e4a36eb9d2dac660ce4500d8b2851fd12657a6a4355fa606ef3478c88c3cf84d00c397d9d50f97e2b72c42eb247f826e6c6161e6e35dd44ed10786be4cd3e81b18103991b6aa9a4ebaae7c9eb462ce4814ff451c55eaefd48be2c171bfdb148304c5bb705e9bc78544b764d9b83d47e8c1960738cbc070f14ab0f83da2b6f70991c3b43a8311f759eaf30eef6f3c7422482016e2a5922639127ac83e022e873eebebfd41dfc6de2400c71ca600e516d1ec58b2659a384b463bb78a3a040c32170f5bca8cdc6483d26b03d98f1e5f5fbaebcef6b59bfad2fd146efb9efabb884fb69b7aba2f1b854f75087eb68cebfa34b657c08f2ec92b022c842cd36dc1af971205ecf2ffb14f5f298bafa29ed21dc8265c35a771a583b875a3485983f3052dfc2a4998f180148894838286c19852bdad85dc050b96497c2f2553d9249615d2e142bab1bdf37144a32c603d0fe9090494eb73b6128e7177ca6a75ab0346334fad771259460542cd6d4b64103a12f3498e4a4a9a3e4529c9b497630989b694ee5304a3d156dbc019937ba253055a10c27dde73705b13062b6392c7daead490f73b3f5bb72b4e69c98515e15715ecade121fae9d5f0d80ee7b740fdc7c0782cb1a1cd41bcf41a22cd11639d94cd944c5350892b95e54ed6bacae4bdd987c4e905d16d81e01ba8174d4191918f23268a5d636d3db9c824919dc32daa7bf06fab4d2745d395a7dfc3a7d253cdfba0b166a4ec937df9f05a1b2c3c247f48eec1b87fc83eedab173e1d2e2ffebe080c65a4d856459d20c57ffd2861fdde553a79a3206ec3e9b41fba32b394e85def5f46041be09f84b4e730830bb39deb426e59e1b3fc47c2f24cd3dff33cffab4aa11908f0db1a39952b5d453431c4469dddfd742ef6fe0cfe0b59e8a9f1719d0f", "f35351340b2e8dafb6cbb914ccd0748dfe0cbaf5f1576fd7329e1580f8a653c907975d775acbbc747b0293b63a312aef8f44728c8337d5d3e480d1643f3b3d2177b58ed47ddb034a94f58688ff1c2536c5632c943080187f7c233fa3e96fc226c529ac590c3d93efe2da795a5a4f56626aa4fef72f6852a65e2ca31dc9d6c40694ad37a28836a6acf8ea1002d195d5f3a421c95be2d7b7ea679afff694e9c6d95284edb043a2f2544b7b7466bc9dc070e2df137d51a618871de06a0a8d447b4c8ff702ccbc4fb7db3a25c8845aa620058301a1707ad3bf0e4aff9970061ed6b86cc8e844bd8e7c36e34b0e7bd391d36d81ac3b9d95f679e916fdc5ab777cebaf53f60f63772eabe4e3eb54fd2566b81bb6ca4c840cbf75dee2f6590da9c486871734a8a1f0a7c75b77a4364b97998350246f9ad9b292f10eca32558f679a4e2c73c02918c7abd2a363fec41a6e77bf208640b90f9cfc1b0dfca15a991d6d5fc880d3599d85a83ca0459c02812dbf9ad0ec19e8d6eef30782606120474eadc6ac835feef1fdae181c44746db461927bb0cf46e8d25f2ad8f4299da0995fab2495b5a8b163762a881a6cd76c1bab9cab7774ddab919012a50a5be90599bfe5a1729d04001c12f7200f716a6d3ba2f681189b95ba9c74b520a414948098f687b778ddb5f2d45523f3e70b05d84ec3e862e97dd59e7fe21ba3707d9a76da94e4f542d12072b8c8af14dd2e17d9ca635377f5210502e5eb4e7d1ac4922d924ae37b3042cdc24020ae9016833b615f99f431f00cc533030b3825a4eb7d7761b4898b4d89c4cbf81b09188921cb3bafe5744f7c238e95819b3a17e59f7e1b488dd301e5ac110b23efb9cc7b68d260baf083c2df8130f50577407402118eb2409ab5d88f2e69f5ea4b6038f5f59ff20b3d557a399de6673f7c8cc3142130fc7d97c7eaebbcad86d726c020e977e41bd5a947edabc65071a006f4d1793618d009f78ed03d7cb442d600f4da07e2732d70306e2de350521b9960004359e370940055a54f9b4ad325700a76e0a0f6752fe3521e2cd9418cce3365b26a511995e41d5c02f67249bd74416e0cff95712e513e5cf468edc4423c5e0bdbbadc458c030748d9951eb43d1b68949e6fef7c435e6c0842075d39f3ef48597589a331a633f10ab783e050debba4bf825cac10ef119428d2a8321cfac6c584e9cd0be84f6cf9d784fa385a280dda1549497d6517ec21744f25ea707aff04067aa7f9c8f38e3207f6f0d6d6040b44d56606326c81a0e3c5e3f3f8c6ce54ccc22816d47f0a246c93e3f2819323d1a1c204a6f8baf16d1be248716f9f2d611c08216cdc142a28e61a57a78c5822b26bb14081819c0bf1608d630388683780161648405847f4c89510cd71e65746bd41d2b9d38b75799166af469e9dbd02f10d8bf8219dca5628ebdaef32ff3d37f09e7d7b919d0be5a3fce945c5b967d3f51a5bcff76d28e226322ca6964cbf556a248fb2e64ae09a515168a12cde3febf80829758a79cfa2a2224879a043751104329012fc40cbf61adf14e075c91708944f90942f86b40cdfe30816589f47fdc63cc9a8d2125e6b19f7287a7b614e769abb23bf19d19986fb91efdd4f32e9fbb872797d63179b52307099a19288a49c5b61493c1236b446304b21f219f3e5bd65287aaa99f6c69aff9a39978a7c5048c59b2c7f5a3af5c1ca87a338143d8fc0b9e4ca81ebc68f259e0b8fc5f0f9a5c806fc498ac3ea5406398a2058c810e932f058effad2e402610edcfaebfc99b150b724419d95e38fefddf4d907a6c0b5fb2489e7a5481159251e85547e78aa53019833154b902e2f34064e6c672e4d3a9b5be7db630841ed5e03e617144ff51cc0085390417a4740b573abb92cdf2552a3f75b4df2d989c15a8ead287d2cdc52345e3fc51ba60ef524b166e2b17797aa9620d25cef17fba68694472887fe3638e465f8a940cf2a9209abfbbe4074086ddc1e3eafab3efcf2c6825c9ffa5b3bfb36fdb68218c410d9facdae57472b945e92cbff6a854c30556d5fc5b0cc3f07df3ccf5ce2ad2ee2359c97ca519b46dff56f7b57b27b1447333c522cc30b7d83d64e41f261ad645547283b18", "ae18f23b1a52960a235f2b06d0aca9dd05a5c5fb7e940be1a9e1880bffe2879362c1cfc5d3d24d16ef1d0eea07d517ff8bc12dd7e91ea46f5aa423fb93e12982c5aefe6df439c2dc467830eaa66d9164c3dc93fb47f4a5d02a5a775b347484b014dd5cfeb2e2e8612991a30ebe2444510c82c7565ad0185cd1721575fabca090c7c1a346f3e83a9a19a156c2d47d781c83d05f8953e598e36616ffb331a32516e347d1f48cdb5ac971a5887f7e4af6003c0ad02d3935365022c4e830015931a5eb9100aa3dec3d57c133e3e01eef87d1cca0d56eeada306d008d834144e5fb8b22ef20da45d344ae3c57b99a711427f1b2a5ba9de78eb3eadc9be389ec4e7d76da6506ef5033dbfab70911db651efc0d962310debf2118dad711cb8d033968c436014a5f19757b33594c64ce71826258a974b13883a2eb6e383f57e1aa02bab23b2de5bf579c349fd2448cd966450f2781d1c7dfa2e296bddea4c3dd8cf99ae5eec01283851aa09258be100c57cfa948847a3b7db5d2eb47dfcbb4804310550f49b0f68559ffb8a765f1eade9bac4276c9580446b9954a571d1b82a68f649f96dd6066404d74c8a151bd3a31d9dd719476a3ae5f52c8f81d215022cb9df72b4afdc1998f89a89413da17885660e940c3d1285c2aa110839871504d15e690caaeab41235f1c094c033d3bfb4b977a79e5d53bd530ffe38cac8a62dd632dc165902ed4015326104cb31fb38e96b52ab1e8fa4757568fc2d8d5721308c148530357b434dba523489ff19a7e46eeca25ad5a5b3ed5a5ede6ba4aa099e488c0fe0a4c10ea4bdece5cc084856b2a931d2e0bdb0e2180292d45ffac76ea4548c1c99886f01a7830325435364861a2ea02303a378537140281ef2287972cd23b1800ea7c3af92f4b199e859fc7cb013e8bc1ebc3c9d042ae51095429eccdc8e2e378480861937df56ea028d4429644500f3fa2ef4fc1d652d23a041974f9f5d32f456801362df9290daeb4822b3baa49a3495d1e55ff4a65eb7ac87e30b28a949737e9075bdeae0f7ae7024e15704ffae59e3bdab3de5e8c7826579e9178f63a8c0c79dec6cef91c5c1dfbfbb141c28df58eadfcd0eed06a956f5c9e12a147f363d7f462fcedad8e6cfca3f2cec1a97102b2f739ac9bc2731a872e1282c9caed0c437f0b1cf763e9cf98ba46574d621367fc1c7dada7a782d0e5ab612430808e8c0eaecdc6582b707503bcb0c123192911d5fdeee6abce3c0675f50da51eeb361db83346140b471f1d400614cca8043948c735bfa573b2cb32dc6cffdaa2b4f29ce2640615b066343862492d9ee984aa6c69c725d18d415aaa61d2eac73a044e289365823c78ac964403b3a060c923adeaba8fa8585cfd8e6d1d77257643d2c1615e3d86b7e3e8a892e3ffcb6009516c0979331f8a2308ede4ee994ae9803fd11123d5dd5ea516459fd5d440b27fa94057acc109112bd082a2b6702815ccbfceba2ee5f4e276f5afda0893b6b0907cf732a7af2e9ebb170ef586588da8ed0a41a8af40d9c8c64a27ab7c3f6d17b793d1c77f9bf7a2f65cd30b68e0179c024c0c1ccf89f52e7a376de0a7e61b6f8629d31c42adc90b9788a221b2acd19e1d2ba2e8bee0d35deaf2b4db86b1f0b8109ea3e7c89bece7bd8e15e2ed891f8507f5e164dec7999d33e5b43fbae31bc33398a100bf580ffb46c4cb4317e88ffdf7cfd5066c5e9df63120f59f4400019fbcba291eefc0f50466995a9e58873a250943ef1f0b665551073df0fe322241a01cf62849c5be4b26c42786087b1350a1d3b5dc79fa9b5434591ff39a5a6403afe379722224c957fa7a0e8bf3612a1416b6668cc990a464f45b7554ee8a3c39c679fbe9ebb8883e146e531fa2e736245fee8f03a61a9fe549ae14ec44afaa2bfc8463c32837ff99e389f85444e22556ac201d649e2701f6d46de258de54c2ae6190dd848900fe14adaee578ac920f06b5694c8a68dde04f452dda81dd1ba8d93978ba12620909d6a96b6730f77d34724464e5af0b8197894a0a6ea317bcb5f414800d7e4d9defdab11546b4bc364c52eca2419715d142cbdf9b81c2c1202f727bb3443cc35c430b096294aebef7b2303ee8496f3617636a0cd8aeac410b755fe87dee49d620517652422327f6e1e62be967d0b9b687d93c1189071af989b6c0aa681c86d3ccbfd369f389db5e601d2a483e52642a3cdf7800c264bc73fa9ea3d51adda68d586149f035bce10b6fcecf00bb251cbefcb14a89dd0db52eab5f6be14e1140f3d2131f29d04327de4afe9c1252ad9d7736cf3c4f105b7ed8df0a93e986e319a8d76cd741e3f3416cffc5ec4c1ea644b31f39d60e722b6a8117a2cdae6f71fb07ec6396783d62c5268d70bd31190e12399ed8b6cd7c41865cc9bf8a28373859cf62ba21dd360b56fd5a3b256fe03fcb70d9a8d9a6eba1e53e0175fb544ada053b0235fc3b87f35733343b56997748dbedba677cfdf63de72593904289bce1e1f742c8a9373c164ae40c3c4b8cc57ca4eacd13fe3564011d7c337d6b7233f0abc1522e7b4132a3801e6cf4cc6621c00991f0d2b298a91fc75a4093b1a70696034ebecfc77c9d4adc472cbfa8327cf9461eec6845ec0ebf3fa9994c6a44544cf5b99664ad8098ead9b30ad7b75108c53bc882748ebe9d98f301829c2fd51468537b029c434df9a74d4fe5f5163d8a34da569b1be8af219fa284fbf1761e9872c3949e50754e4360294fde9b039353ca0758c69d31332e870e5982b3bf79f853783bbd026a6047a2778e6e56d446ad26e52d1da5c5c55751ae8523377a01cfcdb25a98fe2aa3742561aaa8186068f31752a4f0f73e955e040a89597839f5e7e74219702b262957bbb1678b8a9d377d79c5b10dc8fb4c37f24c3f001cc5eb6dd71a1ecd2fa11a70d0c5ff6681e618d7e1174eea4a21a4e5e21942b8de6c84bced3d81b266ad68503d57cbd9d69de87ccf3bf5c564de986c4ca24772ec74b2129dc70654410bee2b717617f32ea2451ef3d152977c6451d1c56f51a69213cfa20f4131fa298023fe45b0440d5ed96d059276b6c3cb966fd5184ce855b4b72a5690c724b6080916b7a8d22ca7e63306d7295db04caf257df34fffb55a81f12cb4533719c145130fe21c860defbd126dde1641307845ceb9882c7c7932b3c5ec333c4183df587e3de94595bf0f1f9b6f6ca13381eeecff1172986ba2e34c6537bc74ed2d4c8b6c437550f9ab9da48944d18019a3a188fa90a09cc7b2af85fbeb0450b44f2eac358ceca3237fe2135e69b97da3f6c27a1bbe6ad4368d4f318270c9c965018dafb0c6cbf77107d9cb4e94c5ae0100f848796f57b50466f5735503e60f190cea83509f6c15ccc8df1fda6333e16a396f4b4afc31a38981b42b1e21c22c4f0a9585012c4ffbd23299780b853cb52734ba88181846338969b673c8faf88f7068a128d669ce873132b950ec770b6a51cbdd72e14c399dda62d653932e2ea9019f29667d3c181ba7db6708dd13c2747d7bb7849ca3d7d527ec0c6cf0d83f028e0c8d75967ef3cd94e9ce9ad4a1bbed21520455a311347d461bb3118d8ebb6d37ae41a16071b426028d68a856ecc9ff9ccd78ceb91fb64baa4bf0ec977e94a472e0529719952c70cfbf9fee8ac862023848b05e9cbd28c6027a94f591d73c89b54ac9145377d65394ae36448523ee32c3942f8477184739a82b9dd21aaa2ec2fcb3c4ba87b79a54d4d7b929987a022b642dd0cbe4ccc096bbca6797658aa8e0a9aedfeb18e8afbf50a1fc423741e9ef6a07e5c72d1c026afdebfff9039d0e556f5a1f9309f8bdb37a940b384caa5754905ce67a0f11bbf0c730363473cee63c37991c2d668134a8079d9fc4697a0a3649f9ffbbc79ac048c17807de95227d85293617bb78dd4ef16240feed19cf140e80aaf39ce581a1cabfff4b1a956b2ab686abc24e6e7a887317700549d87329b09148cc7ac7ba11b8b0e457839fe565a1320811df3888b75654e5bca042931ec23091503b8266abb5fdbaeea8570f0c772cf2d8ef1c19dfd0cf140792e422757641cb2be19d30bbb717274ed94ea5f9ad6fff6274bd4ce396c8aa947d96cf303ef2e951c28a6a22ed2b9b059406b248b5599da67933b5bf286c3a03f487d6576f26880ddfc3a92d1b63266df81b521e14899bd3a484a749957af8d121c339a3464565d7518b20ff36c364bdfabf52cbfa20764f2cb116d1a9f0459966e1", .None}, + {.Sqr, "4982997fa8f8d50169e323f46671feed5a172be932cb369933ece1576f8951fd5365698d068e88241cc79e4d995f3d707a74a48118e9725401fe24154a965714cf49005725d3dfaae1ca970b736bebc205665dc5613e979e6de0485c02f8503eb1074fb947a6eec23d0349a30575649f7f4e38824118b545e598ac2c5adcd1c8c785633253f5fb92a9b36d42426b1f6bc06a4fcd02d6e0e765df195f5fa390c52317a689e1bce02d92f2ca96bf20d7348d7b961de31c23b1f196a612a2319c2f49dfaa4b814ecdf686cfa828854537a09ae97ddea59c5e6140baf20f6dae6e660f2399da5cabc814e819c92dd685e0228d8b6509414afa225582bf149241fca6145674f14d6d77e1d24650be5502a0c756d92cfd63811e6a4b1dd432c823af07c45f9983d10be2c467fcab933a76f27ca72d36dbd3156326a4b32ae433e77fc6dad2587ae55f784100db361e23461fe5246918ea8aeb12d9c377afc399c43ec07db24f46934ff3197da8ec96b5c09c2842660337db593d0457f0de7face3bf8e700453e9820da4e781ed588c14f7390da8ac94397bd53c571a70fd30d5bed6f4063c5fd8c1817fdf11635e7b2d8db334cb5e475acc6096f4120ba5f059d76d30393c64813cf59d4807d332dbe06331d70583c02fed4554cee580eba39e84ce3dadff2a81e59c529f45d44b8a712c0a7b45c5ed5b141b792b901ba07a5a76f53bc0a3085472bb736c61ce94ecfeb7e26ece740cccf81a26af8a94608ccd6c24a795e40303d6664d12e4c1e33e90b470e8e2d044ed7cf23a758204568f7957a162c37b3a8463a20d42d808025a79533f7bc39af554ac4ad5646eb114c46c456a0ab105ef7c13fceadfc7e45588f2fb30e09f78dcf83e7ccae36a64b87cfa1b65287a15495e6621a1bcd8fe4e2b9b35ab9b353888535c4330031b132ae5d5ffdfdb70a2a3f35062ac8c3fcfa4204369ff2e8c6fb7866f98054765bd2793a324bc9e1fa6a8f83db596edb67b6fda6bca036d94d8a104cc9dfac42e8f3980a4955314d462c34ea8d48f041106911c4cbb0286bf3c01bba960023db5666030e0bf85178dc624f3ba2f1ada1729f2643c269f4b72e9464b4a50077f3840655ac18362efa6ec3ecd49f06e95f8c4a95db64bb1a2d2667f1b3d346281a936584e340c8ec6a2fd8f96ff2cc5b1e07ccedeae675d0bbb0db9b3400fa1eeab44a2618c3e069ad4532c87bb1dce15b29f3a12b1ea13555fe30e6c8c215c08c50488c474489ac9e7fcb1fbe1d29621d4c58299ddc8d43059246c2c8bf7ff6b37876f0a78a1aaba70e401c902d4ffd60a1c361f6c897641b9e67fa9f9226a90f0b7cbcb55369f81ef728f9dff48a270822f00044703fe28b32dc3b078034ab3ff6633a724eae6c71fffaa50295dbdacbe9af8dd406971b852f48e55fe7cb61a1ec2a38b02919f7072061464f3131226d451e7b3f690f4ee478d8c1d2d5b92c99798c20f33436907fde75df2321c9bd96701cf4615fe83bb1f23a329c89c6baa7b3ae3c5394712d98400e1442d99dade4a25bb28bc318cfdd4d2e3aca3f84a3c56612388ac209b5675f876acf9442db408cb3ea1bb9ae7693858204fbbea5f458faaf64a6a44d511e65f633a9a510ef4337d8bee3bac459b937862912ba6d255a7c8c9f4f81ad2e99233853163b84add3ed31a9acd8e224cff4bb5ac8f9d21f46e70ec28806bf06af1000188f433817c1935585be5d1356d74700d6016b787720a85db5f8cddcd507737d1efb01c88a2d85bf56248a065275856822a3ca1bad0007aff2f39df458b17de4060cee18f8d0aa32d9dc83ef16206e4fd4bbd443af4e6b620efa8366afedf33d9ca27baa316db8f05fefb0c36ffa8ee1aa81945484150192d83e066396a675e887b852236efe8b4e059f28a7b22241ff5b1e98a3efe67c9ef547bce6b0566f9d243735c81ad61837b423a92cab045ddce51536ed39516eccafdbac1b1c32449c88cc8738c773510459aad05d76ab3e81d004aed4bf278fa12fe6a44344cd3cdfc61a9ea08f93fda1dc832998629ff548b5a671e99d030b09cb49e47698e7e90664846cfa0b4a9fffb2a4d346b8d74346946c2284e0a145d4636", "a26d85f7cc9692b7f1742a2454570fe39bd5af67ef91d4ddab7bd90104da7744e77fdcee6b7bb0d33eed00994e6f19e8d728649d723d84a03fd59786ee7e73131f01ed06c8c60800e7bb9af83879eb1953765a2c6599c5a9113e8cb51b00bff310c2420f8f294914b8e5c0db25e7cafa9086054ef155c8c069b7fc8c1f6509860ba425b0d6f0bc537190b2ee3f857ab966a043ddf6cc5b0770137b74185c0b6d8191f5cf4f6a0c1032341969c2da82be989ffe9ed05726e51309136648b4d0c00190801764f109fdee1f9e00799b447d3d9a7f9d03df55c14fcb6b8b56b2db834a640b28f4c53e48071d21b67046a12ac2da356650d095134029009244a83ebf076b3407e68e3428d6e5ecbb560d2b32bda85ea6a201334cc430f8b2f7480a5de7636a8ac8618d5e800fbc2410bb8bf7ff96981e92713d9db4b162a189e6811da065f4dfb57266b4028cb8b1660b659d35a98280026c7d94f97f08e8bed9833ef5d7d85de5dc0cbc64bd5c629c301916c458fb95730718517e5939ab94582e8c8d6409a34c14eb051d062df0d49baa2e2c5301c2e452fbde3b27670efbe5d7bb08f10d6b0da316da5a684505d202a07c3d1395b650cf5e757a6e5cce87578c6f1cb99cd0f3dc6eeffe3e8bcfced8c99b25f31e7696e22292b5096205f9b32964c5214fdf65c342241c449ca2458acc06a42b75fcd51fddda6bc260363c79075421b427547a611691a8176f8444eebb11f170c31c655b4d3522b43ad5840b168d603d388eb503488d2ac3b5c0d401a28bbdda622ac7ff9be3df7a1bd38bc55fc44b40fd4a5bf635fa09472e6a9b399ad6581d1be83fde110ecaa7ad1bcc21126b5bd69fde3a95e55986fa4f119576fc0e6f367aaa50d1e2d037e6ceae7fddc6bbc148f7a83c728f07b3326b92c51b7c6c93a4b0c9acee61b9175975fc30cc60920f22678ac29dca70dd19d0141323f9dbed01fec02516d03b18c8cf5daf50c6c843190576f3d2d36fbf4babce37ad4a1c481f1f4ecda0f1a67fa80e94ea96bcedbf21f16ce47f90a4a14ccca65c6bc897352ebb43c4861572380a5bb78693f2663f3049de0c68c25970493f9b349f500fe2112e90d1d4d88a0c29d0efb735f47d3f8bcedf9c4db2945c9415da5184add1b98d2636b6bc1b09b508269bf2c7cd1a955ac053d6cd1119d750f5f137902eb515b07bae069d2ba34e5a916412bf8df3df36cabd0e732894bfd3bea2440b3803d9739b3fa287ece9d5e059fedd45e58f05ba5bddc010b0bac3114857230e498becc4ad2f4cd4fd610cedd85070fd152410991840660bc5ad4630c9cb631e1c618d6516fcfa52a332e7be1829d214d9b2900fb6c2e0ec5a54831670d13a9c7ef26c497260d0448e6de7130842655b475d3186cd6aff150376767fc18d9f09329424d078f30a5d27e50dc1415d129b7b1fa9640a3e77974409655122199125e55d35a1c3ab7a28faae75e90cf4bda2615fc4dac8cd02ad6e691ded094dfee2df1af669be580051d0a89e98675005656ac393a23b7c6062c695409dc90e3a351d3e10f48e43d7a2b52ea3e7db607841523f374c1c97bf4a1b049c3aa678aac5a73a97084dbac7c0a29588a5d56cad1729c37109e1ddd023dd25bbbeb80cfea703fda2b1f3466ea021f806b18156db37f1c0ceaec4145778fde7c7d73536a2fea3ad8a146b59032f04ae90c7bd2b15cbc314dbe4ffa360dd88b19d2b308d40c52e1475561203c2ecbd630281e1c1f6d1683c88ee7a2ee634eae72b0b666706a00dee444689fb99296b1c622ba551c9fa09218994389cfb438b1c15d535460a6dd3d4779453d258d8be5d47418223acea7d6a7f6942ab7197c14462495a662c35f5fa4bc3ce871f08c0f2e24638188f549c51ba0e3eb7513fb799fe1cf6342bce3ff8ea1f9b853f17c8504bee906aaee5289b079d8e8b66d89a588df87ee948d967c16558629c03fdf33cc59165f6d88b754fa284880a21e6041c173361c442989426385f26516a9b9831e433bba9e26c4823934c624f9f947501de61ca8843b6b0a378a6904e21d8674ca1cd2e463931720ae3eacae86ac04043256dab928bbfa3edaaec0477c663c34c63f55a50", "151bbe2b100f5dd5a8d9a699b5ef7f9897a68ea1e305a689f4ad55023cd0aa7fe669c9d1e5a5ebb03b929ffefb9a1c49dcd14e3514841e4ebf2f7bb98237c72328dcbea86474a2df1e1db641fa7c59988a3c3fda397b770b281ccc9f00e350ed84bd66a8dba5d54bea59cab81961e20ac422797820ce2c9ad0be6f8fe49bc2377337f1614c4015eb764760971b9c0eab844e0be9644522b26520aa58a2ab3369c2f588a9526f408fd1250491aee2773884ed6458e3699edc5c32a1d7a1bc89c82cee6fb7a6d8605f84a43116ab7dc9f95732f7ea601dbd3c2bc43c5b18a7e9f76419c0930204cac852bdf88754cd3fe834c4687007baa711afcd42f3c4c06a6ee4940f2e68e38b4a5e6886cc5dda80725cb993ba1bf507a85f4eb5335a8b6108d5d3b3bf452465487b274dda58c10ddd1945ac6f753e8d82f16e257e9df5ba1c77bc73fd974d18479af30c85b52c3cc8f10f16db8052fbe0567871b344a05cc73ad513cccb2b0b36d7dbdc9fd9715217aa15358e650c4780a5f58062e0cb41ca5a01f95072b35fb685eb6bb170c199207acc0d7e9df7b0190c491aa15c80e401891d0c39ab8e6749c6a123bb4bd49166550845459582b6120e49a80484790a72515be9fdeb451a77e2fb109c58177de8fc79ce96d979389ab3d74fc8ba95959ada4fd08f9ca37960c3ccb3a6a98fc320ddb4dd55d84d40101b98ab9fae873d567f0180e73e7b62dfd1da1b36a688ec00c42109b1915bc9bbb06c365a2c5df1af53694f73dbd97e8f8fc4c9eca33c297e0c3d4091f4c9588e4da33521ce1907a2c75b8d16828851716290b2fe630f288d400e9015515aee23d4385907386aa1cfcad9eaa38584f15f31b85dcaa4042c8b11b478b75613dd9d5660aa2e38bd87b9923d60e70965a2a729283fdf17500a035514fcbb14000cef12a213c9ceb0a048e95182728f5d37b98f6ab4aa1266de51d235e3d37b9fc3ab5f8a42bcda7e75f09620a47dc6ce7290a18c754846e99edaf8a6e7a336a2b9c6931cd736f83f6e635b61f2332770fc0d298dad2b86ed08fe1b42d87853c753cbb69aad7e49b2e88ca2db80d97ee2f85892c4738cb1f1c35f080ca979074b5eb94148289d659414ff7f271cef28a09ce43eb63099832be25de4d414ecd2d1230b5d738777a1b89073d2f27e58351d3ed00e904f29fc17bc1ecc197d94c66a7ab5b28e78be3f52a024b7841f70ab4a81f608a86b6c68152e6b2f85a71d56b8870033116daa07135afee056bbe193a5a8015f7f8dabd8461804a7c5632b89373ea460715ae97e1da44de36bed515242c091a6b9684e9a391d4fa92fb7815b26d4479c76dd916cb6bd560af846533129babd813fd02ed0d3e992dc0e973d9bb53f239651a4ef6140dd09c7d6f7db2002e24ec350b10319961e6697f64e82983a91f08c5a0adf8eb697abb157db07a750a27c0a24a8a7d8ebd5fcd01a4d4d1c774808defb07a77f80cbc2d655bb287ab1096dc8c188938c7ff21a722308fa2b66aad0e02cdfa08e7edf9aba75e356362abef07270ffaed4f0a3c67804cc8c53424e9ba82cb04f1461645af62cf7ff4688355c9aa15617a0168ebb09045a3fe48cc2623c29588062f60b49407bbd307f6c1364481c2cc32f2f4c8744f00f4250ee35fa67bec53694eab98e70287507a24a578a1ca7f377635927a5171cda55f828219a2dfa2075b1b82a80b84eecbb2210b01eef57f9bc5647018753b8db32be233556ef518c8932ad9580e1c1ae03c14ccb10f55101ebc1683525cf4a00e2def5cba5b079fd1bd4fa791863f362cb07e25819ea4c29fce2ad4eca6f995f1c8c18d1778d8e518c314c182efa34fe38227fcc5cea33a103382f6db5f90554aacd6f20de8e74472a39d4840298d4587fe717dfed4263ded09fa8ecb46f6ece32cc292b61117f3854fedb0f6371af0ea3a2485acf69d885a2c3ef3ed577771937a8ecabba0893d4877e4a2fd6349bd6c3683ef42c88e7bc9e33eb4ec15ccf6c4b31806b9ef69928e94f29d9e81da2d2079e8d7d7c9d9d4543815142998eee7c818a5e2465908bfb7a7cd1410d30167a4a1d64292957ea153210d8fd3bf61da76c81b2055ef04ea5bf996c273daa6a4a3a48f562ede45efce1b3175a626138a096e646861708b1acb4c421866ca0a81b15dee3298818940fab5d755f7a53fed001079e296200afff472b14438c64c6a6c98b068eff5849d93de58a974b9614efb2afdb9853237a7d842532c677d957f1556dc8ee300b394cfede5bbb7cf6161bacb40804a3e5cab9c660b6909d5db6fa75b558351ada6525c3ae79a2a5455ebd1a74afbeb45a1bc18e529f217cb63e4a39fa6b66f65e3dab26110a6a43b35ab64b03c1c35d7ad64f4021b6a1e05f43ed2ff894091f85da82826b6e25fb6fbc0ccd20d039622019fb41f61fd304311ce01e417c2da9d7f95e0718b2e52aaff76dc46f57fcdd59e2dce7e81f66ad915fd6d2c899129fb222ca29cf158522d54d8551abd9ebaa160913152e85dd587b87d73016e45631a212a62edf242adbf5aff8fe69cc1f93aa51b1cc530d44d8f9dd03206bfbcf9614b433f9eb0b3141283ee4fee36f090420fc37ef59ab4d512e334c166666bda0fac6221f43c2d498d0e04c4e92a0025aafd42332446a57cac52cd51f7dbce4d3dffa296e9289739c96fa037e59e9f884ae5d527c758dc4d0e889f20ad1ba18de86cec80f2c1c64688ba8c083c00c52b2c3a047f28467d1820549af16588857a037518d67e7f53e2e782c8d046186a29d952d777257c9db9cc34fe817e356d298cab789ea43eefa2dfa03dda72a6b4b754ffd8ecd76baee5aea8706abc1b3fc6a2c77423b23f958cdecfb8ec429c6b1d56fe576354f8305e5fdd713ba0b2511dc58204b8fab201e590de8f2403f5afa24d8691f00f018aafa8d029004f8e560cf01d61a947a950fc008d45432322b0324ea4176df8ee179ee9c473eb5f63bc25966676b091b683ca0731d4b670faca0c82330cb7e2a757769f68dc3fae02fad461a0daf50de0b172eae0929c863776d7a4a8af943f9d94a972ee1ed9e9a4978ecfc0e439f755f5ed8d6c505d3527b665e0678e948d6eda8cacdad59bcf5252cf256c54bf412f6944e6e3859a3cbeba6bee70e8fa2797104e3e1e2d091878d28e9d6c858d0bb5af0d2234c6e2cb24758240a0e2b880f43b4d65d428e4892172a812ef33b25bd975d818cfa5a24fefd8c3805bf90dc72a5bde882e3dae1e7cceff0b4c786f5d449a25c0184fef94afe899a6ca43e70876cff8ca6f8c3e9d9122ca473cc485a3291f47d7ef3a70267277f7bc584687b600b00e15b65d6fb751b8ef9a16d3c90c024d2110b8c90ed389a498976614fa000e78cae2ea2978a7ae00b32b7f913cba9b2b38859113b6c5aa82f39ab645dbfa5f5e3d3caebab084e8f627adf888267e646b7a898ca72ec979a6ef94f72d20c4e4a5c8f2fb1325d0aded3aa0188923d94d216603e385824d7ec2fb6a6f3484d31d5c6cac27177c1e0664fedf2c3f410a30db831d3fdc57de1d72132f25bef6142d48dfa59a9fe6a1faec4253b187ad19c2b2257fde73332c321cd5f66ac34c4b7f5c6128bbaf2d2ae081620025c3c165128fc23c285aa09f01c99bb5cb27f90528710817ce01a62da05d7c39f4d9306ffac280232df635989b88ecb88c30b794dc7658aba6a0edeae7bc569cbb7a36e240136f495039475ca22cbdaf247f45d222d5ff60035a5fbef94eead12bdfd5eb086a9c09a1111599b4325d927a7ed5005301293496f63b3ec2265c37c31268453ce8bf016fde8b8ff88dfde633c7be88252a7e7af31864711e31aafe58e0f358758728df8ac458b7427ac24d1745a2a01886294580843cb21d007e3d1d9f03652268850f8890051b162510d37546ce59d5b581da5c59658144b00fd689a8622042c459923e89ac53e4c90fed102ddb06b984bd709d3552a8ec921edf90ddcac0498858d2db029ab7e550bc96ac4bb280559d4707cd75f3511a7b8fa97ed62df8fe699fd4b11f036126acf9675357ad125226e547590e3594621602302cafa6ab65bc167ca7a6bb1dfb9ae1adfc2d4ab72706d1204b02b45d853f7cb6f4e944040042479af4cf80f7393fa5f65a726b5ef0ba3ac2a33fc643057269d5ab35baabcee409f9d050bb413a32c3cdfcb510a145668722f831b6727d639e6113d57d8de5891e63891192c867d9364", .None}, + {.Sqr, "7b50f08053b54eee088fdd9add32f013c02b1d875b462d42a87cdbff81ce4357b04fedf214ed441391ba56bde9b0411eb9540b1f02b6864a139ccc3d5ca9db1df10f04794c6f4b37747be79e1d5b605412430cebcee879a334175448958b6fda9b69d39e55c7de73e95661dd3c59042a377c851f484e5acd49f1744ffc419d8202a3dac33b5c2942ce4d142f59203fd872c7b3cdc9c4c84b0840abd309e0b8a01a257bb3dda5778afaaa83a2b6589562f172fbeafb780d42ab610ead3f496cab31fe68d87449205c3b1482871a8ff86bc82c0a174a190efce6317a2f854ba85ddeb21c22e2f6a7aa12b7cdc89ae6f05d1209a4ce0b4bd01eb607d935b5b7ba841fcde8fb2f58bf065c2c88a9d47ce83dd7df301619be30b0b57c33c97c2e512fc464737c1cbc85afa24cb5115495ab097091c1cd4a396fcd5824b6bbcf808ef38556b9d0cd956ae3e076e2de220143c8ea92968cd5e69d5f483c1b62e7c87c4a4426f22e2b2c13f28381b9016d3b06e3b2f32c9addce55c43c573800031f21abe2eb4b1dcdfe406fbfc32b4d23c007bb12451249b298ff5efb19ad0e81d3b2d7d9e286ea4943b963d600dc6c12ef1e5144e4d92696de180e832e087aea1a641df3832586b0600a1af94632923713299b9cbc9064abbe2cbf378758c823a6e8c46ff32f0418ecfc38c08a8966bcded2752e3dd53a8c96206f4e51f6763f5d3b34a351631210de180a603bd740007545c4caf29e8389078c31e27ebb0325e014745abceb3a53d1ad140a47271c98c88682fd5cc06caaecaa0c6fd5c7a074d22972542ed41e9ffba1d8f146b0cd35e9fe5a9dd7e5ea7af2ab0c2de5a136f5e29e8b4e5ea3d75fb94233a5d1c5038d82c78c67dee45543023eba5b80d5e300b4c53b3ee1bb1e68d118142fad5b3aef2a47984ece5beaab25b33b36a163c15ee2686fe7f1f2bf3e18b8890aa19428893181aeb5a8d294f124e327b45c192ab3bda9fb330bf9438d7f6950e67132b48707612ce58f9c816300065b57dfbaabd5999c4b339c77cd7baee96da020df8193bae89d23b99cf079df2417bfc22480ae4f98b87f703f1ccdde39b04378b3ef08ace0e606f7e5e4538ed41ea7fd10e79e61868de975aeccf049bb263462d5fda0762b02810c3d91c111c399c8da28df3d0ac38a6c1f25bfa846ba8b310710bbf2113c172d3748ad044f66ac9c39e804a5de02a373945df344d9810e2b5b4d4baa0cc773bb56046f49580709a6bb8816e13de4e9cd4157e3f09d70756f19f60af7a8893241099f4d93f4bc9424fb24e861e2eade45c096892081e2b00427ea7beb2bddfe930e4c1847d2b6d1d794773806fb817e6fa3bfe7f2b18f64c72c14bb7e112d65dadc4ea6374770b045eafce377f24d561b84fd99e33aa4dd2e3d89855c22e6482da1aaa00bf437736f3d9427dd027a99dd532735406ed2826fb1d1bb8657a160e76c92a5971d2d907dd02bdf06e728c0aac92dfd17919cd5800cc570e7c0314075e133ddac100bda3447e654343194d94662b771a3a8d0fe1bda4c3b925317bc3bcb05a3641918514a1baba6edbd027a6434549910a829b23cce0e31e2393cfa6472b626e3881844289a06e194efe66ccf2fb32c00f0132db840e440138d212fd3375c1ed3469a4636ddbacee35bffdd4cd084573e28377e056a101a6cd1e477b9c76884f87c087b01230abd59ce52fde1bc4ff7daad2fa5bcf3d25f63286a2e25b85759ec1f67140d00d47240488bc84177bec9718c3a9628dc9ac253081c6ef3ae20c86454f1d60efce3425bc46c92c329c27c0049918d99fb9753f84651eedd840f8ee5f605b7124360d0bcc30b9a0ac14964b528c2eadde8fe5936b1b0818649d234e6f73a6ac4e699d7cd274c5fdc328f1622aee491ce82a5295a911b9e29e32a34053ac8b6351593927d8ee98f1d167fe6cd3d1d7b24554762daaf78b9997a749d2a9c825a16ffec900c0a5db6a44cd976b9e507f1e209713ec2c4806203bdc12d65690e7d52c6b7341cd446363baefc36a26abe327e1c5e3373342412539271cb574b42f985d018306fee4942556f32fc9cda381ad4f56aec5d1f159e7e4581a35faa0b13095941c1", "e5e167f1228d8dc7b5715824160c79c5ef6f44ccd67c00e0a14d6627c11aab9656d19318e33845becbe88dfe6758aa363e3f4646704836f5885607b442d0eaf17e8a7678a9ada67ba9936e79becd6ec0de05b4ba2430deace32d2afaa32497911ad54b772a10b728b004787feb7a252600b62940bf73d3a869568852080d32d5fde0c6f8b23f900b4302bf5507699d93c4b7f197c1361e1cb7201201516b1a50ea951ada822a267fe36627c4bb43d15fdc71fdb7356be29699356534994b1ca3ba16d084eb95591910bf17e026b788cb762a58702b37bfd72abbaa05322a4818693f2a9fbf58fd7ffa03f74abad615bd070c2fab4a3281544d57e33d2a96790c35148b4edeb41cd0197e6d617ddaf7c7ee0dabb09436dd87645e960f70a76c3b48ea78ca334c6cd3981d664880f183a575a5a8cb104a8c53e6d2a61f9fb801c960a2f73324bdbb3e05aff43f9dfec3b02c957864fa58c4a31eaef15d2d26489cc97ff0f053e92fdce8146cc369549ef793224631440428c3ff126fee4affa47015e2fc44387825c784133a21e863da3bf9dbaa13732d558aa01bb5850258b233511b1abe084fafa451a53075d13a237acb563363bc189c118e4b9ff524027a2ab97ef78f0fa1aec412b034a82be89bc0b096c2deebbe9c88f5a0489e822273a6908276cd1731d01d4f99a128af7c631691a6ff4c0cd30c11ada0c09cda68ab7ebb1aabf7ff8b9abf08e717cedcd62e305e833d2aeea2a5ece8ae5762d04032eaac794624906879c342e10160c62c90d9b342aa07fff075e65876f947e982962c7a449c1c016fb6d97f89c5e439f3044933ca49323845a92ed21fce0b3bb490b2bf1a80fe6c7ab920f693a1bf35fd7f52f66516256d28307733a21e628cf0af154b323535f4510764210784dd457456ffb086c110d3b2a78bd84049ca2e82bff429f3adb0c7a9fa5536d61d5b0c0586499cb6a979cc45a7e07c359452d716447ebd1808a77f924bdde6d620c248fa8b4ca109065d1936d9d8ec11c0735af06e1d68f0e84327b46e8e539d7eb5b8cd037eeac9866996b33a4ac22bc03bca59a67d0c0e726e4cc5363484e21a8e2e12ca8eceee5bd9ac7a44df086b8d51f857727d1e2230a1f6a9cd27e7f4438a3752136482a280efd5556e4ec40360643bfc8d1c761629ba2a6005c77756ba40239c0ed0f0f96e2bed6de82c8a6e40adc4038a65b9c5ca4e888ea96aea6a633f022513cd992ac68dadfef8ac520a49bc518a1fe728f8f281faefef3495340b8def46b98845eb7a38b61da42ce5a285baea94abadc4d4c4a88a4d72f23bd5d76b7be9ac43fd9326cb7f77bd48faeae706e1bc6ac2dae9dd9fadcfc299bf94478c5bb504f9ad4c88dd6a567e05ec6c16f23eb0be19aca5dca953310475a8a8248af167afd278e3c3f44c4e925bb17a438ccdcb2e01155533acfeb2b1bb53ef32208d8a11ccf95d1ea5712617d902b9eea92d46c79b0785ad30c91442233f60621bed3df137c983c8968adc9ba477fbc3f00f195463898f1facc4411037f67aaa4ffc9e1531348f1c72db6b4865722f266b5a5168455cf37420630b96a82f73dc33db493380a73be17b639c8455b12f676bafd8bb96ea47260c38cd210f33977530c1f17077d90e12f1187e1765dea720e39d36c729e1400c2ca59007c1eba9a27a5e42cb50b96df9dd192acc21f25529abb34e40811a966fa0bc0b451323191cd150093ce66e0e4c0600e817399c625f3a84ba8d3cc777ff31b76f689aff9de45b82a8345e194c236c621ee5d8c5a382c7de88fe42a27879584e16b18db5238560048f9134cbbeae031ec95a3fdcc497d85602c5bf515f11b8afb746a5057965d1f2a0e4944bddc1c32f4e8e9912529bb7dcf7e69bf941d99eba3fec2fce917c4c82f5023acc3557d08a914bf9a5ee9f13ccca12ecd2c10320075e26d3ffbe9a7cb050f70c752bc881d5eb2212e47686b78742400bcb379fe8f63e4bc397ed5cddd4e84ff3fac1b8573d1d0877e022bd82cc69021877890e9a8f0654cc3b37af6d2dfb08f9ef482b29da2d00c6f3564cc2e0685da390d6005b60a090249c04f5025176a7fb3774ce8e22e94e83a541a716", "3b66e0b282956871d5abe88aaf347bd31b5630892900fb4c945ace1b2dca87aeea84191690016f22d6fcf33867abba94bb174a74b9f5ac3f05c02d9ed925952051647f0d54e46dff66f54b6b11b9d62ecaa342419e77f26a1bd46b8d63a3cc9bc3f1fbd316cce4990477bb13542f2ebe13402882dc113d347ab9f6e4008a3979d9b59a9cff59ff6c972cc020e5b490ca4de6527104936186d84f8dedd3d26c82b320594f56b6ce0ebb4caec6b3c9d81250a3888e40e58322a0c834b4353e93fcb72eff70c3129b2954969da0b0c3a24c802d41c0bb147fff217951908d9a9dad000213dddff0ebc09ab61ce031127568bb905ceb8de4ac9da107071e0750a6c2e42d1c354eff1aaa2bfaee47706ec5d1cb58dfaa96bab3cc0089815d46984be2dce71f0c55e7c37b95ccb5b433644bd1f1e3afa1bcff0b27ed6b03d642eaa29e2fc9712091965b13ab9c1ad5fc59ca2631991dea8e917274f0eef732f8aff40db52dfb1c9d010fa8a5a239745bb066ae3e2b4a748e01d582525a60be762db479a83123b0d719d1e98e6982b667cd851d44e34a28ed401e593e1d7e7c37f9578c6af86618f0a1bb0b2f9da3ef1f2a36e3502c7f9e94580fb473911ed9c1c702d2e10c6798ca5f69f76fe8a09d80d5470b4ca737f3de8956dfd65f4aca9b0d91ee262cbaf57aed03659d424a91d0580cd367ba1c1d3a2ac5aa370904fc9770823ab219ff641c4073a26de619a4b4da48a5005085e1523488959be41413ea8ed681885b250268b4247a91f837121381fd2265c2952d5dd8107b40632762a34d122ea627c6133d7e9897ea95b3de9dcb0752ba8f1b5353f3a7af8767958f18a5a97130bd0ba008d181f5010cbf0341a2176aec4cecf8e04ddd4cff7d77ad2f48a666e5afdb69c9e220125d88e8cc4fb3abc0b18fef6fa4601df9f5a2c7d3a734c96f9598eb3d2a8cd3a3705bec0e29bc95941b90f9005ea346697239624b2acd9c1c63112676a94629d10a12e81fcc5713354e2cfcb96f95847fbc332e065c536b7295b3da02fa35b8b95528e0ce8ca17091bda8d7ca16eb937060204d25022647a3d853ddb158fccb4efd11ddaa5b6bc7f9b007bd1aad9d6cce89ebf25fd971c1aad7830aec4c0e6ccd07c9f1226c78b1fd48c80242f8af124b0f343b0dcc4b06587ce5c1dcfcbeb8510679432e39a45b827a9d2326759e893ff59c74023729a338910b80ca608394bebe6b679ba37ea5748ec6b18515e6ec7f41ef6375e4e0324185f289ef6403cd4f5cf214e09533e601feeda151bcc7eb29feb2abdff12a9777067f078336c5a0e8a05c00b415e9e34d45cf64f3980eb07aeab6f88087f63377eae228e84b7c7efc81cd70c2eb628297df32a5b74cd2d7754a047a3fb6e326032895b39a0d1a7df9fc60cee0ed922b9d952443e712baa4d3ddf8d622eebc921286f9233c714f5f90f662b59531fb52f073888aad219a22ef8c6a06d727f91f4a769815e275e950cbd01a6875625bb9ff2e8fe36b6511429c0d053c301f4139109d7ee66d9da5f0b4987c7d6117fa3be51927e19fa67a4261814714df533f4e9b2961e2339316cb9afedabd20f3a20119ad45127e000fa1e6ebe012b3a088513a6148f3bf517190de6b19799ad2c507a4f8f9db0ad2f3adcdd6c4e8e5344ef257b88ab454e723d07afa7818384eabf772828a50b94cb34c821aad789627f39fb1466ccdd3880b262c2e26e21b28e21a7082a00e4d63345aaa12bd4009f86e2761143000bb7c2174176a89085e73f662ced73b297403a6f99f2664bb80cbdea56e74b206b8b8f5dfc5850e4d259c93e9eec890a13d89bba616a273190f1154581cb4c6559b1bdcb0c83ca62885b8ddebb51eef84450090192c83cf4bcfb75cd40f40c9f357cdae3a523cd4b0e710d59688758cad01f0bbf6f0e3d52f5b2d291bba5bc8c8af0022e10fd82b45a61d859feda358e2bbd60a34245b4d4997abb5b2e0735b56401eb03c059a11937ee344a31adb9d882961cb32bbb654240c5b5fa5ec133a8463d30c4a7a7ea3937f195a8b1f80569ddc336872f3afc8a26aa866d44864019177ae2cf910a49ecc8d9eafb7ac59ba5f01cf1a976ab434c484b34a20ee28d11b0400d507d2ed3ce00fc0eaa4ac730f040160912a30f0598bed154e6796f18fe1672b3962ea688fc2954485e019929d047a158c3d71d3fb9566096ceefb22becab6d0da90f6e5d09e1967c043f8f4cbdbed3da3fbd9b95539ffeb19a1b517f5dbefb75dde4ad587da9c7bd1b5f63f9db8fb3627b769a659f8d83ba83167d6c9a85283a06e368064fea4d8f7fc2277db6d1b4ac6ee50eb16a78223aafbdc0ac1414531acde21d06924224d17c8af147b0b8e9f17bd33323882b2996cbe2bb7a645b802a0a7a66a2f6432db63d83463c547c98afac37fa4b7d0b507f5e761132cd04503dac3cc49848d2dba0a7a637c9b6b403944d38dd4877ab595a469522e12f8a219deaf075ef4282727464798fb897133f0ae1757012f30b2b6b97c13a1c60668ae7b814fa4c828e45da9e05ef90dbd6676dc0b794333774c827a2eb16a6c7a15c9a5bc94ee95c763cb3192de82aed65a9fb128a34ab77f7a8f5d8a6ee726f389ec88608ab887f0b40fe6905f92de607487f298c0fc60efbe9f35fa815c8bcb65e21c056fbdcd310e1ba6f687f6b3053601a7fd31acfc3a0eea9fbbf6a9d4b42681934583e4440dbae7a5d370379bf756ebd051ab42a7405e992b94db56f517fc7c680b9a47708787da4da6a561f48ccd8d704cc2fa19134be58f39b211061bfce7e49cc2f802909c90065d503f20d2b42a811868509e690402b12fd2adecae6870d266203d153e3fce2e6f741cd5a55a74481eac65c504d8c2c6d192bca5caa071fbffecf8aa0bdb12e039cc5af57f25e5d76e79032ae7a28a91cba7460134de6aefbbb487aee63fb3e1ec094b84ceaa1e523d16baa3c389bc5d6bdfeec33b20237f8a8484d47d3903958f3203c0d34609fef8050797463a245fa65047a8624c0c905fbe92017f25fb9e48ef55457c532252ad5ac0e81cc814a61af42b72613bf156284530419d47238b9ef9c84f0ef5fb34359df2f0c7ac15d7172852f0d3b6c1a25fbc53fa02d62253f0d27e295ac3f035d3f790e6e977ddc6bbf121ccfbcb19ba33bc0afae5f799fdbbf623567aba546f86eb9150ba036c084204fb1a9e5f7d6a9bad969bc8aa52d9910f917b2df4a9b6211993ec47464cf71efeab2c89826e178b70687193dad77ea536e8a40c277e396136d69d0377e30e44f4069b9cfc03f5b13666f2ae99a5a1c9a434aab316d42bb6c837de1e97579f1b141542995c0790d1e21a7b3eb60b957ff6542ea49bede0396820b2feefff2d710db55652b1e9bcf11db99057448cdefa14283d7d14a050ccd06828149a591f0bc77aa6fa939ac26568ff9b348bc4cfa9ce377e6ea052c78b6f71282b62aff7495b2cc28302d840a79673591d1bb95c50cdc765849505a26c872aa4dda8fa21e70be7a592552a4e8102d7a4ed8747ace63393f6f7f7ebc91ac37feda7fa608b868de9f981ff93e447d3af6ddf96c58d55570ed1e7a354d7321dbd9abc5ec523167cafbf9d615da03106cf63f26200025081522ce825cecd7df2bbea07b3b82b3bfa0d0fe14860911473ca03ce8f83c51dd583a94100387aacdbd3c760d1f3753fd596d0d5d3b228297fa9825136ea81d577ef3114539050f95bbbf2befbec511b5676784377ce5be25276aa5b44feb2b5548bf5e8bec665adfdf5f2847da459bd9cd6be1bd9090274e0904213a87afa74b5a7f3482b1e6b82332c925fb67627529c04926813355193360f16c6dde2acde35a65dacf1b4234c7c4783f169322e6aaa3a5952e3f64f8ef983e55f7ed89596db3baaf2298e2b7a1623cb28be648c03d61d867c20d91f13895f95d0389e2362b5b626be6f7dd40560f6a1f161d7c188fc3156fbc669bf9d595ad095d329777b0dcc3a067b3f4987c5f58d70ef6402373039a58226ef86ea15aa47bf3542d90c9ea55516f98e4b022e4e85f94798066d9b4c96230851901de0fc61c008bba975260b0b0f73b35de2be03c221d49ab78fb806238c78724357334cb89a51a00fc44f12c4414ea158911da0965a5507a3c6c6ad5c9012a9fcb0f0d40b08da46d7eea7e26392678082eecbc57617e0d697a633b0a1bcdd1f6ffb81609ea9e820ab8b56a191be645b159381", .None}, + {.Sqr, "5585ee6ba15464a111bd2e144e3808314687a05ab69fa3b3d8eb3b2392079822b6fdce475aa5b27751e45cf5cdd695886b5a49994f6b422fe765c875455f014a67203a96419626f244c2f07d7c2a138940afc5c4d7b1f8a6f835e0c3de8fe2a5b73ffc3372d3180f424a79dda40716689af8ad7af7fefc521b9f0b6d83c49579c80658e1634f8bb29767ba829113eab04c97fa644fd00bf1487dadf6a8eea4bd4ec5ae47f16988587d9a464b246cf89c3f3855399afd55e2b51e6eb00a5161031ff3cefb6f3a05e113d05d69756180ff2f21aebeff8183034db4035af5b0afcce61c9b80d07fa3c11a7acede2b937a8ed8787c0def32905877d86e7a9d3073f9b70707f5e6a90e76719efaac3fc7a11cc2cf7fb3cf1eaa36248e81c72141e18b75661fd7b25b4f8ae8d360ac5be163c5f8e0a651f319ad9544716472e828a5fa726eb18b8d64cc4b92deed228de38019f67fb817123ffca66a5a847a0ed4d84e1ad787036ddc80f6d7a85e5c1f0526b4aee1eb4737aa41c0a828eb5fd097359e9a7f2e894fd9a64e1f38cff2119cd6c0adaf76050e0f996d9286e7e25d64d7008bb845364565f8d9e09c883903352e11e4969f31d08e6942353fd28900624c6619d2593ff786195dacf24eeeeb231ed94a0301c394e75e550e8cac8c55c0c8f11551216ab073b4662bd9edd3ea8ccfe3e048c96153ac46599b1fd97123b420b0fa8764b433fcc67f882910a97d3bf9887c0f1e4383afa6e4b030ebd2be94442a6dec55a461422e6d34ec8468a649144c362711921593ec0943ec229016c8c06d0dcc258560353fc6254fa26861f49879a08e346db4aa62110bf3c472188683d56f4395df0770fc4134ffe62f7a21b8946f418731c3cdf37b1fb0a25429550de6b16f27b12ccc78d5dffe2ca74f94268d9f68614a1d38e6f11bb5ac59fb56142ef09ede88c81f13dcc54cebc7c5c70bdfb479d8fef4f7b276aeb1bb3a45d487d031ae8d36852271fe5844460b793e047880f92d6c8240cd7c7abdc1ccbd9e25c1ede0e4c3f26c2eab42ddd7b60dc89acf758c4c2cebb47d616c259aed5f7037e1ac2db3bc760539624e0ab17ac9232995d01c52dedf74e6273b10432b436ccd62971dedcd95c4f70d4d76665ea2a28bc62617a27c93e78962d5b397ca56957ac686bd2da8eac667ff447de053e6535ed7346c60f8f5b6b5b89d0ca0c65330e34f814c6b3fb8d5ae9725077efb03b251c5e6920fad91b5bdb345b46d59a0f466dfc8d3ed29b38b6af99ad2aa4534d0e3a4a6912bd9ef0195a78b56163a2263e52fcefaf705bef3e74845c33bf35751d11c6cbced846d4a31159e52d38dccf185ed74b9e0222d409b349b60e00696d68547aac50b47b511edba56e87f18d790cc7ef0b7319cf9b20da2a18913e3128a37cc3968108fde33a790cf21c64052ef5abdf8bad6222eddb4a2e8612ae0b410ecccd83c84a9d09fa18045ecb8f1a7e0c3d9254d2d052de5d649be7499c2399e36e8c1e50f751afb850d6787d4851e80dd9217119d09ff7afd5dcfc28b4242d9b083b208e0daa4acbbedd3a341072515271ad276023d9dc36ab28448a1e47b6d9e7565bfdb7399f97f7602d50a5d614fff32b984ef77c3f428301edb67924223bd7c640625e2c5a1054361063672a139857dfde5d9d7266e8a103a517758f32822b49b061cbec7703a403545713143cdb018c955d470ff2ea5233add0c3a301d3181b7bdcc83ce00c9f82eb9ce01278f383cac73a2e6398a57e24c983ac5056501bc243d10e935a87ac55267ea185c6d922e138defe7db6736626e578c53dde75a000a8d48d39d8168979387e04fd1b9408c1d4a27997964dbe7fc121d410572d7e00a4d54c1cb1aa8fe6698c269ded8bc86993074d7c8bd2271ff3484bffd316d4f6146e9512f6fe18637b74465c4803729d0b08eb41d14d745a1aee82124ce86d89046629561356f2709796b96e52af86ae3727f07896752b36c7fe5e1d7da6385342e5095eefb820e663b89804d69af3a79a76fcf141e67a7ab7b05d8ca718c6082750eccb584549e6a49c3298d14318e7e2c0b3f1d8f25f92947e1ad51a8fd408d09d8088222c29764cc4be6", "93b5db41ad1d49d986c44ea831bf1b24dc9393d5d574fa81c215735ea48a8c4dd24655d015aeacdd778c9da99f5b9b47691d9c4b83bca1b966d96efee3f86ff02624497719f6cdceba34bc2e1202d06501f86bd9123b256b44d78e093297f3ebf7c9f1abf4b10d326cd8534c5a4914e2deede4ca53a984818be519e6f362240c89e6ce416ad27d083f46d34c91a7447548c44e45ba8d7c67b90ca832ccb28c4c268f3f09dc2b739d63fd79c959a84509597047e053f4d537ec032a34d6c989a862658bb29fcfb0569ef1f7d3b4d3c77ac5b027d9f70923948f674bd59dc1fc66b1f75e70400d22452ed803fa73f4fad51f93c43b774e9f4c567f095b7ee3af26dded1cfc8901cfbfd4b9607592017f7a434eb81000b045c4d61664f40183e5e8e585ed29745a3edbf0a89afb1f38dc8b86683704072d686586d1b0696bbb635abe91a6ea38888a0ec144258c5f8aab4884bf2d0c5d14def76bd6c105d465dcb847359986fd27b77f95d27132cf14816400429110b6e7c4972c2367ee23cc5dcd242b4d7e1525063945d7d467ee0b9b571a889a34300e4f65b7a1e5055dab427d71568fe16720c9a0e19ab0507659aff64f1af357f7ccaf49f702789a2b85edeb71a806fca7ac27d3ad93f1382af4578c87fc240f0f9513d24b4c32c5a19c239757aa34edb30eed312ecae34895cb87124079eaf1ca8d6bc14340e49a03aa6daa4cc19bd7b2d931920380731c4a15c8cfee2db3d38ed73d7f8f6119b6e6cb753211f0005d1df1872cd346bf822939a970533a642d82ae1fd9a1a7ebfaa570a909ae72175deac19faed546ac32dbfa86f32039ae156eeb8a298935575705b9984333c193dc96a46cda801f30929dab02d602cfc92372387d16f26477a5998c99f0177fafe4abc31cc0e3f1cd33c4f480817913c6f55856852f7434608f83464d7bd5fc52321191462796ec6b84c8e492ff973204941c79fc4b8cc919295d4732eee4e97ed5d614f01fcdac266540be1740ac44754cfc2e66a9f3a3da99614857e60018b7253301e4fcddaadc5f0f5daadff5bf995873e9ae82db8420d666cfb09550d0de81e629de053c4af145b91f699c8d2def52dd511a5d5b003c44f5bb171549ae86f4b59a3e58fdb557551325daab2a69e169467402d41bea2d5adfce9dd84b7d2454d291216723969e208937af8a381c59bae3a724cbea166f33544c51134e61547c7986aba55547493e562b217fb3194884c5f76d1ec160f841052e70fbd73f3652025c5b915c7cd74474b606d5e778d6502d8f5799eaf32b8957c0055c0ca682c694fbacb09d9ba0a1fcdf2f69c4cb3df20b65435a1b24fdd94ddcb79eab62350dd0eee4e863b1c2762b8d377c17e4f8e0106a4829fe2c158f844effd5d7a3805f183c31f9f62c423a1cf1de406c9d6dd66cf338f6eb65d0163a8bee60c401ea55da02e023cd7cc1204974128c3b52d2c27157aca151ca7c42f9ab1e37de335b40f204c15426f1e9fe4899f2a7f82654c7e96ac3152a238cb2cae97700f8f338f1d0797afb5920c45690a1522af1b723357b23207b41cfe02d94943cee64a1e784050b7752ab13846dab58487b83ea19022bfd73abcf270ae62e149f4ad3809335ab2ff8fd7335e5660264133495413db8ec499e56370272fe63d956ea7ff2bfc205ab4ec6a8c6b21b339e82c3df8c9fe52d5c93e606a0e0c843ebccfde44096b9edf19b5f8574a4d52a6676acc7f7f740e39dde4151e28043ae97e550530fa6cdb7cec3ca99e422e7d5d38d5e5be1f1f054e76b5f62035a3e9ca0e345ebbdbd50ba30bdfb6206a8fa902a84aec35a2b920487cea6035cb9a1dff3e3dc58cad392ab93ed5849f0fa36592d864382f8c2cf1149b215165e38faaf3a39b14f54258c46656b29c09ec5bb49728ff67c8b4fc42e20e99a185eeff1a2a66f7ec72a427ace7a66a8ef4979d196d6b1ac9d8921c78a706fc4b06f0bdf306f6bf46f31219d1fbf5871086c4fbbe2d785a188e5a7a5da63d51c8aee58575122bc044e0189f6670239a624fb40c3daf729034f573c75cfc0bafdcbe0dcb8d7f83ba2be1356e6e5fa29d91730a6b6490f5477140a99bbbe85d68452663229", "1c9236651303f9bcb276ed30bc6e9561b3001f6347a8674e1d9564ac0be820d2fc6665ab6d8960a7ad212348608150819a36541b2be6ffdd2a48690f489e4c8f5a864dc1893b212fcf3e7fd4f9fbae87b1d71aba5ba9b7294b76fba575f456dfd84a19d56d7a3822d4a68fe983cc402962d4455c3d776c70436db30a082c8eb105313f8dd99b650a218c71dcb2b9c8ba014547cfaaccd9eb7d9bb913d0defca6d7279e199304b5f511aefe39a3c037f664383b97fa4bb1a7f6ea57a1d5d7b3bbea2151e70f4a8269ad8d6754dd7dba8207c2e98fba258fe40749c30e34a5b9c80519286a904af3e3e6c6dcd048aa460c1c03a16f8b60f4caa9456281d75c0d53f79286fe9c581a24856b61a6a1e9ef05eedf0d0bb3844acd8e7802025d3bc40fdb40576f34a38b12d8b58ff0237b68a5aa791979ba94b571e86fa8b6f2d80460045af11cb4b7d4009110897276a2b1f0845527f84194fa8c2bd4603b0743da7007c30dea7dc433cff443e5fbd1902c560aa10d3541205fdb3a7231de4f8225cf17ab0c45c2a9aab82d706e72b0b7cb5ec3fa3e806409ceb78bff5b29f1aa2a3327870cc8f866a174da3252ba0c2d644e007fc7760f839ec8c35cd62c678a26f9b566216c21f6f510b133cd8269aea40e89c594357d1023e1cabfd83b160d4a92365d9dd4bf33b9da6b978c5c462d67f31e63cfa6a39b4b478d1cb41040b6e012a55dbdc3cb9043595f561b9ce947c1716c7e67b3bd7f85ad62ef1a2354e7aa8c15b0c01bdb39a503e488ccc4bf20947a3bd84799de675a4323eafdb44390d6ca3acd2f54a7b15aa18a80174e393e5e8d0d10c27cd9048a5e877dc415148a8179ea710cfb3f9ecc2b52d7adbe658e9009542d5b1c9b78f6f246e9f97f474ca94a9dcd884c5cd31b39129b14a617533aaa3d0b501918e7a970a9a25decc59792ce5df0c54ef9bcf2dfdc7fccf988082ceb21300282698ff42c30d89e2e43920ef3cdcc1f3fb67b4a298e45e3ac1690bcbb571f62ed073e46de1124e075979195e542d81e474ba790760dac260c22a3624c0e6985ea220baeea5bf63fef606baa1b6776b689daab5a2a2f7ea2b268f935547521136017dfba0933b6697a1ca8ff7f454773cd121f14ccf31a7f5115bd02c87cf1639bb4105d45a769c98230358dfa2d4aa3123c2c38f58b19e35b19cccdc32d0f899c901c73fef504160e06e7e4da0e9dc005c67dc9cb2df998491fa5b4a97a9bf4cfd4d475b47d04580507ef97c6b1406631fba773de37a2049c06a6eae3f3868e77966b914fb7a887fd37e06a2bd8deea34afc8b31a35c3d3326021e78a5e5f5fd730430d12ec960514e0795fc811e769ef389ae0ceb554a28ecac43092606ddf17a463bdb8f7cf7e69aeb284bdcd29a9d67a9f258e34c7cff84978ff13be3025434dc59549966f94582813ffc62b67da1c0043eafe693d40113900883ffca7b4e30258446a0ffb50d6d3008cde0f118235e55161cc31f3928893a0b06b28474af3f10f3d86177a6f3ab8eecd31f714218cccbc83cbf891a04dda3313404ed81a6260d75000d66172d400b652a91774e00022d63f27693fb66accd4a49178d6764551505cf5f69dee67b6420bda9cfe898ff93f0d949dae6d3c836f5b84fb89d36d294b5fc1a3c12b98cf15faf29f43bf5a011cac1725d48bd605d0964abc9581acb077c555c59c2d3eef5a30be993630bb6151df335e925bafa1c4f4a17d84b1c2e04e3bb3f31d2cf973414cd064b90023a3eda5584716c711b368460027dab0019e78d7634993ac9899cc68bbaa6198077e8ac2e292cae7d0f05716f3a3f779a444bfe6c27170135ab9df275219676d24ffe15e75254c17e742ebb3eb38487adae69d50eb7998d1f66cddffe19355f8c67ec16b8fe02a64c01ed5af4e32e32885d4a7cea9e78b93f45e726ce486d11590be7851bfaea2e1c9d6ba92d6381a8e3c79520603fcbf48e7f4eb87a0173d42f2a7ae898fb1c572564c2b96be53ca3cedf3b75b3df59e80ad12ed0030c10faae3fa8e874eae9409ae9e53001917c3a9fb426a51f6e55fb8bb5db5e3e804ccfe5ffaa560d10e61fea648613c0cda53ddfcbcde54f10abbceacc766f98b94fcbfcb4e8982be31a32f97684d1fac08d0fb23b2fb3e52e5929275a55621d619ebdd82e13fbe72552293835915900fd92408a0632915e5a5388e66cb3e3abe9f38be9b58cefe8785959a8c5f4e2c19d85f39c9b464eb221c52843bfefc17a22858a26d1da55252c0bfcf1f40b3b28ecbf17057b6454ff39c1f46caf0ee4cb49c0a4710cc97383a720ef2a2b831ee0e54222f14810e7171c2408d6a7aff86fa28c28f528a7aebf3d2cd8105f3cc62211f55c2b441c58cd75da460048ba86c30d15afa0e52ca0c041d0262c606d96975b9f0e7d68f0b08d05b4b280671e175f86b3ab3903009ddca1ee7619844332413e40f3ab9f50ecd42726f3eaa6ef257d547fa440ed0016a340aaf3c11d77526da7707ae7c48e5c11d042e29da67c1abb3c838a2fe8d230dc3eac34c4d0a6190bbc4a369e1874a544c10547544c92f32bdf149c989facad37d48fd59022ace10b8ba91687a8e17feb60ff4fedf0858c9e7ffc4406ca06822987f5c765d1e3e044c7c177103a5ce3ef7da0afe5418c6eb19a67f3e5977873b59c8ee7961527123d1ff654bdb84fe583125609e5ba70e7dbb95e993de8c7e61cce78736745632a39f3acc6e2078f2b77543018acccb4ede8fa6ec6ee03c3405518f529c0cd470bb54aa84598066637d1de67c5923ec307c7868ce3310d7e175ec553a35a75a0f884b2f3e7463dd84647476d4204f3027dd5be4ed81a4a58ed0bdbd3fec59498d957b7dae5d974fbccb8d228b71aace2fbd6a8f37b6082cd1df56cc3f338566a8ce4e01f650a3ec40ff6b34873cb23bbaa9aa1242bdf3fbb912be0a5cf225f7481981cc692a8553604b5e51914e7e3f7969ea8d35a2b7419507347cc8d5468751f9309c8c9dbdf0bc7fa1d899bd67bae4a78b51d97ce0dad36ede956090e3973665f85a8cb14948e1a3b75dbeec9d01c01632d9f665ef19d3d4b14d7b01d26531248857483e6117aa3588f75633c8a5afb36283427df4f8c246a274a0975159c54b33b1f16409b48fff21b9f4a37e29451b39e4a56be6f10dafa16f80481ec55461595989c5a345d2ef9796178e34c1f8ff20ef62674d9b4376525bcb903ab13904fb74c9264acd1d61859d0a6abbfc6fd2276a3526f141f75496f9d1a3b3b3a95f490f65d6250392000c9a8b2ff2ef12174cbb8d5b08f753c328722c9c08cdc732892add9a6550a177ca8ed7f86437515d054caa5c8e24cecda85b3b3ba42e842b0bf765bd1329132dcd448ad5454e479c1bbce8113663cf68a80f8ad00d72d66de8c32cc91da143cf161afab48436be182b83df06c62af6c9fdc0124bd6c16f5c7ea3a3c0e63abe15db80d82c4b25a37e40ea4c20718b9ec0a11e3329a11f23401093565b7a60f588eb32c69567545d4ae7b218f720bcd274f5972ca5775bb826da552d788cc1f02964a8019c86bef647907fd13f82f941641edc35936b71a639631dca2426a93abbbba4da65ddc059ffb7329ed16b0653e7dceb468983ffe21df490cacb488119ce766e28e110fb9763698ce83e3dbb6b123f068922a4c3d11b287271e5b2d4cb926a62f22fd9085b962545b407385e55cbdabfe9cdeca7253da3953ad6e33bdc98831b1c3be00d04292220f29aefb370057d1eceab84b270862a0c26c0a648051a995ed2637d519128028917b73ef5570eeade059c9b47a62df6e21907f6e1794e2a82867e02d59a1d6664257b026ef29f0de7c62701a0e6d3564b3034f611ef9a684ddca0daa9c297d41084527c368f96f09c58babbcf6b6a61059cb50ad4118f248bda5f3268624012002c4449656d95a3eea57629ffc403550205461971c035b9aff9d220be9bf441b1c3fe93ad40cd426733447cd9df098335849c5a5705e4035f0a943579ef131e83c4c64c4562c6502f338cba3df4f8703b230af397730130521aa223adf9720a79d3e458acb743e33cf5f7d4e6cd6eae9bb1db8a3cb6a8e9d75ccc2816c7f516d35286f50d01ab4c1b8c76659356ea7e1ecc420951ffaed2f7fd9b6753ef29600a8b7915aac159e06594de35203cfa3d28b0e7b4c1abfea25dea45ff43f092d2aac215725fdccaa4de6ba6e1c584f00774d25fa8bd1092a4", .None}, + {.Sqr, "75df57121da7affd64739f24fed69dbf03143c97225d635a3473ca9dce746610ebf5ed11a9235a8ddfa8828d29c37b6ddd59bdb5a8659561d2e0e62ff4a716f24339871e4ce878caabf5189e50199016623fe68d3f7bddba680f3fe69aabb3f8790750a046ba011e709ab4e8910f81e3f19206d994af4f3a333abd99cd4a4d824339a8cb1399fbdba26fc05b3bfe6e539745d1fda706fa598c54f8846dd77325671bf2cdb5c2201e7d200af88d34840ed6d3618a6bf53426ca98d1ccf8d328e45baa31b65d76ab58b61147a21b4526ca9b1bb6aff52b31df242fd41e78de016a132966ccef9b7951f1258095424af0aa6444bda014b5c7119b35de2045df0139cabd7cca7fa85a05263f655a3fed4efd5a4db2afc2218b66f861f98ac44ee2a62441be4a00c34fa4acbc198a55af6b8b8ae9ee034b2f6269b55e79e076984f9603b60f2233543d06c59f9dbabffe1d5a65342ea18dd91e281e29ab82642b77fa69b6b2964503c2b2594b54e3c8a8653e6eb778fa10359c6fd60d60c08eae99d4ac3dfc87619aac0aa9d901ccd5f8a0fe16d943c06c33431d41b63abb56ca5f18dba99064e46e690c5031fbbb166fca57b94c273006308febf19e5cf1b149d356bfeeefd4293584fc9b1da951491137db624f33a5e7213c6bcfc5973d1977dee29d9ad162399e66168f7839bdc58722088fe807f26dee3e81731c022f808ccb9b392eb2225c7ee51ad5386d69d9d32ea8e8daa5e222a1a110ca384e45e619e682326d61264bdd37631a7a270a40c73d19127adcadbb80ba3182e0fbe7ca780fba879c5562007aee2a97d1fb76f200ded121d9885dca4632147c6e47ffa16011f8c14658704c4633bfc0e6bc7498b93a02791a3e504628a602f9fa3c09bd062edf98e21676b4f03de1685e76a16965f4e2e739a38283bc015d0ca443e62f3304c97af2f269f20a26f77f96cbc29b8c05dcc0f302f1c6af1cbe6c569a0e52ba238be1d9202577b3fce42f8cf8993e46ad7c38f76b1d2c7ce0793c46419a5f832be241eb1c15acfecbd4d5377868a5ec3613839c12eb4889a925a4e68715606c0f3d6e76246a45d1a76f4d000c3755899a3c8251b7afdff03bc662238c6826b172b2bf8fa4fa4ebc5a2306286896a27885f9c61ace80eca90e0299677da432e95f95924ed27955c8da792b370b95a31b446a636e3faec19d39ba287cf51efdc34d7d000da4544417ca710ab3ad277e6ee50556ccb4b3919ca00ef5ad22a6d56824596b0254867821848caabbbea555a4d4a64cb32ca3a3871deb17690101e35bb53a9527e9bca3f20e18ae959a8f4aefd0ff360ce5ac7271ca6acf1806244c505896b033f8ffadd61c9817d41636c4eed6cc235ae4408877ee9d3d8ebe9b08630c1a0283d623c6cecc784e56495a6f1f9b7b49fd45a0419d069b6cead215639a99da3f6d6b2f2fd2fc7315cf4345cc86024869ca3319be7e78570a626869254f10203cda691bbbb51cd6e79fa4e0ee588b3a2e0f0047bd42de7ba763efc7495fd3b693f06b1a740aa883231ab940ee59bec441f524ae546fb1eb9ac4423f3ce804086e1197db328f91aecdb604808da85be637b950cd9dad6366e0e0fac4816f42f9d944cf3a9d2dd03c3ed279272ff66aeb9acebbdb08e9e0fa35626b91e8464ab87c76c23e16c96493ce3db9ac8faf1a8e8358e15d2146dbc6dcc7f86520f2689ed70919c2a9590dab435943dd52602c0e2fb930ed0f4cf4999f7471dd0982fd880a89728446f45756e200e4cf09614b1572b5e0331ec80112b8f5b3aed443a55bde06eb595f69371048dd7072969b8405d43c01f250ae8dc3201c1c46c90e1a7976d6cfb62e9853dca94c821b8df8ba8e52e8edc538012bf858ec426eb480bfc9205721bc202ef85f990a087929435a10ffc5b4b26e559db065dbc557d25c28b794af0a1166814de339b5b1f26a69feb0a9d2737d45f3dfc52f7b158a3cfa852ccdfa81d1147d8e252403dde02b7a5961f0b0fc7436d9a875969d9b42d8c96ab601c3f557e7bd20634f73895b538e701d452a7dd0080c5e64e24b697ce91a6ab445be14b41cda468753c9e9cce56c984d40875cd9b2b393975d49268d", "f8b92e8e2ee4796d0ee9e1e370a940804a07e0ad2a96e28bcd8c568017559b4e81a21592e17675e2bff9f7130f8003142bf11c5a9515b2111b88e98dd4b8e842fea73cfad1d70f83708c9c79f7d8856aa8fc1bc7f5004e3e247a96c3ea677230e581d51411c438fbf0da2f639419908c8286d3ccb3ae3610cc083a25fe193b63e4a213ff4c180c903870941568073cd3d95cf557f522181d518b6f1ba22f7e7940f059b15cf867e4cb5de5f11700015ab1085881ec844512713018ae449b0d30682f6e2582152465a6ecdf2b962ead11aac8dbd09783c52d35704160817fee6f5eb0188486bcdfe42366b5656142feeb9f5b8422fa07fde635518332f7163694fe47cffa0150111e904bd6429f6f28a0a0f9edd20d3e84eea2713fb82a3e6ed03ca97c41d5b17e9b654dffe0f9ae134876386aa393bf4b3acbefeef8ebe217ac167ecbb125e350897ca9ad1094aa8a2a1fda8ba638bf7ee379e1cd04b0a51b28f06553b2653af980360aefe412cae3df550f44f1d0d7baef6c35b1368bc44446d3c05af91ca02b07727d0f43e614822972baa146327f2de75c499e00a5ecdbe9692a343910ea34550b0082b92d389e42a34d4a4964658104f6d7cd3256cf8b9d8a3083fc00b9d800e6bcca791d718fbf2ad1b9377b4c698db39b7256d53b0760d74b9296cd98ef5f14fc902d67dd433de0bd6c9708f4865f633e3f158f759c5ceef7282cd126b3997c8f37a6bf61b76ca504b99b29abaf0d1c5c73ff08d24b1511454ad1cff4299e0acaa6394cbd7cdb89a119b38e48708947c475887c78a5592573075e422618182bbc8fd45b79708866d76ca6760fe72071952ab892a87696faebf67db188a9e1336218b857a70c11b11072145441115a336688095e0989eeb635cc481f4b2cf1417cea7e5698e587eed0f73a1ff6ca105fabcecf49a2d81d81d297868228cef39e713b1796e1070eddf7e8f83fc7ee5bf1dd8bc3d4787dfd21a96a0cb9d5e7edb086530e3d32b0f3083cbb3da9570a579ba1467da09fc5a029df0561cba030caf816682330362532f04261ab4e34bff5f2fdcf2d81f544354aca29f7db01957537787f6e8357edf219f53cde13cd9f39e6fb81bcd15cd5e550e01132b6ae7cc0ebc921671b01990c2d11bca90c79b09c72ca0c0c6dc03a9de424325ba99e2e1a206d276d83d03febefad7f7b190f4d81511c9b25c3c45503cff49a2b5e6d3e35cdda1a7b49dffc73ff4cf1715373ad94ceac260fccda83dd5371b1ad4b01c7c72e899466fe8b802ac10761bbefef7c18bbde266f5ca21541783d521fab090c6528df9a40d05c34fbdf74945e3811bf6f2a1c233e1effbae4d2116524617aeb2b933c56022ad20bcf58e1844b3642bfe5da2d51d60e84d9a163659cd701bf164424b413d488001113a41ebbd85714a4359f42501275f54737fb07958c998dae80a533d9479a32e237627d82fcdafcb5e4c54d3a820afa1cdb1a2e9187b1c79183c2110db5bc0bb260838207fc41a959d38ec4a5236b548f969f526492263f4074adb34582eda02bf136651cd3f3c4e98485597e83e68d0b56b848740754c4ee81df37c5aafc012da6655517c4301749de4925a9ba429f9a71839d248fb58fe3b684a22056eb93815ec4546d372107b8e40796479541dfc15fb2e3b56ac24ccc49710f7f3296229f5fa7d7b634ddf78c264a7eac0cc5bad694c8ff913a49f93e4555e80dd413bcdb78f859b894ae889dccb5f3fe993c65d80c89fe2904d4c8aef8a4dc298000ccfb1ae60be63c21a054f2917418edbb138f3d684c75efb4218088949fe034f06fc349429451c74b3c9a54c7b05d8ecac69fea9ac010809a9dcb5a5d1cdb6d4295a795e812ee5568ec0a61625a88563c59f1f30d65698351ee50aa47d7f17fdb3c4358a943262de4ac83c0d7193c8ffd28aad89bf576e45de8fce33420a1fe659237226724900159e13c647bb8b6db4460621599cfdd4a159a0aa645b23e28c3b284eadbdd7c9cc72e768a69e38f9cd0e0ef81df87c19c91515455db6567b850439863ff016a01b78b2f503911342c1eafd2870e59785d5c9e348820bd265425d10478d22f82d9064ba63c8d9e8d8a", "3645e86f5e48427261e916864829578eec86a76d5fc99ff91b93af58a5e1f6aa8c9351e59c6f526dea437dd7e8282eebdb8bce0f9a3074c7284e8d7097e3ce999af79d125a524dcb281242600cbf005414cd3e2209843f34fbabe933301f3e241765fcee5b5040f541c083f48d4445097939806e57af21799216b8d2519336a9167d4d10c5a86436da07bc3902a53973d34f13f9380bb2090287648842bc5d17fb9136709f1f12139d9804f8a260001b86994bc7477c313a194edebf10d18d40a153d06dccbbc5286795aaf08390844d5454f878e97f65a1baf836b74e930294433495a284cf84b679f60c209682ad88aaa9e2c2b9aa46d98a789b23768f99261669e674adb95bbe45ef13a70609afc4acc3720abcf94f4cae2295f415cfa5efe6a5c8d41eaf751146e815bc5a68d9a612114cee10fc9b695d86d451e70d9844c6e02ec87a496a6c77584620f20a836067c669ac6ef94bef620635d730be4cd8b755784432d81958bb2e4eded01006ae7cff06a6570fe1b2b0e0d99b7035d47022bac5e7c7e81bd85ef903ebca3c2774ae771962463a21071f9f8a7cfbd1133cc2161a2685dbad463d78339db7e52cc21e5b167d12f1be68d3dad749d1dee80e589bb6a90b672dcfb13ee8c85033a7ff54289c94e0470e23a36151bca737e13e2105d7cc2f2dabc72b0978ee6663c5a7a029167ee9e3a251adb64c2a1791236882d095c599cc6d7ce885aa315d0fc5c5a4a021c469dc976b0746744542386744d1326b9e14e1309772b7315b0fe8dc3988259051955b90165bc0de7cf05b87f3b724b91289cf98c42b030ad878019831fc3a260ecd25ee3e121dbc9b34a5b911f14618ccd1d1a69b2a329708416397e45c2a6fc7f2e0cc36584046971bdeed99cfdc93d6db03cafd07a9cdd1871c4582ce7a27b3d4313cfcae7fb62667585024123c8ab8be3246503d1676b72b7ffc1e7160e60cea209341a84dc48cbdaa4b3f13d7bf4eb59f67880ded91b43c747cdbbfe81e7f2d5033a439bc7c3bf09aec82dfa225f8f89491606444941659a602803ee30d8b76ad8e5dc30cc0ce149888764d2ec500c5810538e5310d8c2e275b47b6e3f1f159517b4b529e1db059e3846dba31a40e9b8caf9e7594256c6c2c527465b1d2b2f3f6f87694608f3a40a17a6d958ef6c2ab51d8fb6fe021a48a7be80b67e6c32df7a7a450cd10a92171bf22eb838e5ef831aa09f16851d66362757de65d5eb39eb8f72a2d1dbe5d0a4133ab8bc1d820fca406b0771e1fdb902bef4005b312663f99bbe988542b25d2840df8c75edcb0af429453a72f719ec7ae223bcfe50793668544ccb0c307686f2ddb3f6b313abb384cd5872ec201e6a0aa23fac17c2408c718f5a5a6edbc9c04c0c60884c40e363cec18803d20f389c4fdaf0ab60c88879a00f8753227a1ab7dcb4aa7e763ca8438ddca7f00de0d649b264eb5ffdc4848d9826892eb7f9df0734325d87648cad8c435e6c7cfce9084b8235ccda3644c20c418b19fcc4f373baf809fc4542649ae1b134a69cee93906a2b98cce9ce3947616f60af61f06f3fc01dd041abc29a32b68e0d2c042b1249c112c7788d1247890500076d487164306d40285eea6932d3937e1a3fc6efbea62cc57211b97a4f820eb04c880d387a686dbe77c8110eedc911225663f99b4d96065d5c43cb08b07bb62579bb8750dca2c966bfe2068862c08c6680b3d38ba539e97ab4e43c45ffa4042d63e3fc59e27427c9d37da6834fd36ae9264bf02ff6d686423712527e3872fb481ac8643d3366d8910cefd999f0bf797e9edd1e6a4263a19a2445ded7c3c797e4a1452311e6404fa096766eeb8f34d218a34e7f1712567c6d3794478a308d4ca781c952e3d7824811cd9ec1b6170304657821239c6bc599ecdbfc98a9d19408ffbf1a3edbf66a0f9e358307fd6068678cb0d1ae6f779abbd07654e585cc8cd1ab04657f2d15e086484795aa4d5b10669735396ecf00d1fdd88315bb3508bd22ec8daa4f44d841dcf598b9b3d6d60986cb9ed080414213bd9eba0f43415c9241737dab5c6babf34af78da8de5f289c364f6ef40f9219650e2c510aba80607877930c412475c4c47d64121af0ca91c9989e20e5654a4a25311cbc98057f76615e1b66d04b72afe989f9476c416c41c8681bc3abac40400a2b3a794bf020a1e95d55ea299e3b17a709a1fe2f3a33ee46fabb4b3267c485be46a61aa1f69e392216c493102e77d43a96eb64b919588080112831af519658abaa40cc86fe425eefde1f40ce550425c38e4972b6d6ddde3e364d41f16f8cad9de9c7eee8f4fba1d5acfc0f4e3b6ee5b5324fab23f53062d835fae089c453a0b4c9cb57d84fb9813632f14e8513012d30954472ec2caddb2b6d098e1d7c5685c04b3404fcc976275cafd6263f4f9e3c70f947bac245e7d8ded31b33eca17e0e3f6ad16208394a9a1f1ade789fafa5e0fbf12cac264aedf8aa633a3613f6ffb14a030703ad0dbe37bb966227da05e2266030b149b76a9553412241166de97a4bc4b5605da07f53f1b8d6fc366621dcb4e170ac6f6efccfd4003a3241b8611a6dda65abdce508efae2e88040d9d504dd3929d542a2386d9089b72386ebeb1f72499680d68b0d8211fec98f7e191e64465db24cf7374d4e8956a7551460e8d681cd512f838e64b36f33f45717bb8ea3f7e8ea273f85a6d4e16e9a35d9e8451619046103fdaceff19e828b7fb5b083dd3d7884f0f45b9ca195719c9ffcf99890fe94f24b068a543fc7ddf9d773d11b926485ef04cdc2e0dd787d1167410047c04abedd69a609deb42feef3a9c7cb42629a51406873fd531bff17ee8a1cb508070433adb15f1d9aeff72558c892f3820a3f766519e45d9c527057d0fbdbd25384eb2ef681027017a712a7ef1500b32f047d0129a7e79ca1117183da8651722be9744df956c7a6db4afd6f8323e7efc128ec00a0519f237316c4fc1538707f705870651f8139f5a79a3687c30243749eed9e457467d60c1f218c55cc1150053bb4fd7f7f9a517901e8c1e1a88a4d6a28963f4cc1c0eff82aa78f28ba8274d9e9aead1accdd30262ef6fc6c516bd4d04b9ad563b03e847fffef82b0b2f29e0d895cc91c1d589b74df37dc00cbdd8b036879fa0f1cdd22e1d0dbf0270a015affb545133205d8de7652dfb9a8aa2c21e01a3f3eeddfd40f73fc28bf21576d18f907a7b306168f24050829b4dad6dd536dc23a246585da75d7033f07fce02dcf619becc5d6d0e32c815888f05fd8940f656917942db0ab4de3bf3e0dad734286f70761bdf4d3176b30e2d63a9d3f7570acd191face651a50c8a280afe14b32d5719cd8752d357fa16667964884c5df199fde25cbe3a2b38ed9840326c2f221f823cce39411b452b3c7e53e876187dbdcbe0c89b9d30e62cf63cd0156dcdaf079230a3938f2394f9d17b9c0d85902b99a45a503a2d82a3646dc3fc932f867a546da341862a0ad4be44a6c7b8158f4ad1f0bb8f8fb42df88672a9d8f7b792c96158fc8b34830ccbc245dbacfeeaa84041416de5bcf44b95c62237cfafaa69e0019f5e9c7e595ea9274e5edbe5601ef78c4df191bc83f6db9b0764f15caa1dbd27ea613aafec78ab123929cc107a0ddcb832ee3a256d828626d2fda8c323372f7b912aa711e4c4c80d93ac3b0b44a513d564ad2e76459a32f8a75cdacc36fd2e8ca8cd1595ab537857b7561a6d0204d39ef2251ca5633ea404c48574c7f56586dd5d7aa4e914e02ef1981039924ceaaaa07b7236dbfdca9b40cc383dbf1a0cf42f48f93ab0bb3061766ac6a72a29e3bcf12fc2b58ba4c791629e7b60df0a34d9c5950e7d9fb9794255b1c8f5140972175737caee2870905767e060bf06b57f78742d181e21f63712f0a1363a28f17f17e139038095f58f70ed8411920d84ecc0b9f2a65e3cc9e9dcc885910675ce4d718b704ffbf62cbcd840c8fff1cc2900d5121333bf6148b2f3afda6f46122fd50239999e227ff5d46f05684c24872936cf23efe11df89a337d721a66914d2b58900196ec879271174be1fbf0d8391d64ea843cedc65a9641f1c13bf77763b1599b634394f74f5452baedf49ad4766fa96e7232bfc8e168e4881f58f711a2e87b9dd0eb6933cea9adf1016168dba2a54150c2105f4140f8aac4b966120b3633957e5fe4e5a6f82769e6e4837542af0c2d45bc8b3ac00a04cd01e1aec0f932dbda33f743829a9", .None}, + {.Sqr, "65cea168ae9b2bc2ba6c4dc5d21c36e34472581e5651f41e430e75542afd09cb7804ccb0ff29b45f2347de848c10bf1d946a85447259d71050ced18d651b235f05b118addbfcea6f3e7b3068f613bc1d305fec1db87139e61ecd2e95d873567b2d98e47c70920804ce84248db37a47b5428922279ce6ba0e459965235fe04d71a62ed2952e168a0cda532920297049b696ff9e56a774db55676e3c7116c9fb521d238468629523238a71cda9326adcc2c9e8188c2db4be09215b78733b5cc9bfcc2bd12c6e994bf596f4bfc2138d93229bdede7f376063f3fd9393da8e7f87029ea3405a660d7dbd61914f9ac70f28b395c419ec60c99dc8d8668432b9439899bd33fc884b1fa3f2ea4b861d6f1199b8b88b31495f27c1a02fb432fe2b19c40f4ef1bc3bc4741b3e3a407bfce026e5512fd64f57f4fc1de5bc6ac0d8f1b109a0a02e0ccc5c7301cfbf01901eff0d2120143c98f5acbd266c32507ef626ea5a8f49f92ca64ebee5808fdd61f50cb985b1e7783685149376b75489d15c5bcf90c10d4d993d9c3e5a27a15b8eca220aa36bab3c59fe72d4d01fb817b59038a059fc4c145724f75d81854e1b7986d910c99eb9fa83f0482b88f19564565b6f430800b7cba5a8cb552a781aa9676fecd55b5c7055cd4c7565ed38bb77e048779691d6e9ae74e5ae914e503a5146aed19d5955628c675db480bcb7a963bb6598c77b1f47a83750b34b90886fd921855f2e37b16b98e2194cbfb6e3d807165f7d1d49d287cfc315ab090dbf3a91851a017a17025d1728b025367740c250fd55104b01f25acd74f3595d2f719c11e35ff0d6ef64ac3516f7142e2c85c3eb76ad8848e328973edd865ed4e26f3689ff8a6aca809b20d48537d7bc91daa2b61e419689c7f50dde684ec04cedb1e7f5e7b03361d9abb96a2748201070805b4981eefd6c819caef731d9da21558da716e92b9c3729bb55e21e65e27ab651c77971e3d1ed22ea22bfcacf15cd0cd09738200dd4669f244546befdf4ea2c235f2942b93aee10284f88266a779f6eba3e704faf69613f0566a63594f619ba24a818e57bb9556fccd9e59f98fc6956e5efa8aa76ee1952e5581edbddc01bb0532526a101411f06fe7037d7e439fd5cf112098d573c1c8599e678ee054e21383a2c2dd3563388d735660497eb63aa5ec33450d89393ca2c224ff6d1b1dcef41025060449effeee45a8fe6c7cec77ac44e537a55ee194d4981dcdb691f9e75c42f88578f3744cc226128c479265ec9b6080276035354ba230ce3d992d48bc22fb4a701452ded82e8ae8bc9d88587fad3a348dd75564cce8ca558d0db2d04f14ba6df03392527e259550fdc7e4445fbe937c28b20478fdd16047b87a359a58977cbc0fc60a74c9b1f1ba48f422e305d79cf3bcaedce8346c22327fa93551fa68bdfb0e856cd7da5cddea439b68113f6b3618f84c4ae6b33da4a3a7aeec9473e7b9a00ebdbe1c12474a8c559a786fa0f7f7c248a7c9dd508a06f373650c65ded917b348292366da1ead7e49e9a0c212e46d488165ddc5944a77ab84a34d40aabdd2b077a79c8eedb45162fbee375764cd215d1ae74e9b7f8b915aa6035c3ec5e15908b5f3a07d30460b69d2d63b041146c44624ac7d13356caca1887b9883a2127051ef5f2e506b9decec9e135dcd0854adc60505741de0fc618650524ee687eadc3b52c31ae56c7ba2c6b02d3528c6a7bd1431388a8d7bd3670a995e0c2522c0f1ac8a7c84ea4ff01a3d835c7eb1bb7bff6e46447650bf7f4f440f61208b1566cdc9ad76055236df21d4dc4b06ec72e2078efc228ee3bc74417684ca3d3c10bfe8716c1b69fc9889128a3161033110d9706815a00fec908488c1b51a00b74e3119b3297fe090484d8d92afaba6a6734f9ec53fa287898f1ead18c393fd497bb5dcd3ad5bec2c6c7590f2f924f6c29b5733681aa7d4f604a97d418c371a129c6845aa99a2a35c8a8a9eb3cc43c2710b0c44b0dbc691f4f506079a9513ea1e99c69591bec6a38ee394a4b944142bd068b2241d536e249e9f40e6a04ec39698677f0681ff5a6b9c28b97ea05d3f6d3aae715da5da24516997b74b0e88607c470356f0974bc152d", "bd40e6b2ee40756bd4540eff3b1b4b3076e51e71466e3decee56c4ae341b5437e24f44a35c6a5b3652b360274efabed617d3089a4e608fce27ef2a23e9eb63d156aaa337cca6b0a3291f48184bc97392e853c46359bf2b337d718bf8e96c1af8f4615b4a213a57cf7644b47e019865df07caedad7ee4e5a269b393f2572b6cf4e63d078c962b9185d345d86785361863dea69a61d9934f772cc674c8dd0044bc40daa71129bd3db4c2a857f0ac2f07a729652336023d8e7a79ddb4b58465a21f4c799fd760c6aeee581169a019fcc89f98b7bbd7303fdf34b74132ac763f61d031453231a4d8aa336cb870e537dab6dc9516c2ffd841486b4bbc2e8bfe858c18cd7ee176d7e3bb18756db128ff8745d39650efb0b9471fee70218f70fecc58608877a8943f123541363fcba4b94f02e8e304f76c866b362602fcbee3d1b811ffa18d81b3e7eaf6bfa37905a8cb3b9c95b1fc9938458bd823f57ccbf133b4bf67344e883395477d53ff8a81320577b213a98e69ea45e3384b21c6d2b6d0a872c258146e420ec3e58160061ea54d418e4ba9590718c3d295c92543874cefb81701fae91db5178018618275cda846f3f1e5eab8bcf748c49b780fef49a1d6a81352b82b96ae0ba4e40191ccf0103b05c0efd332e3c0fa8444108d013fabf6933c55903de76810b4d7fccd1a61c7cbef56b7160ee618f374fe6be61d87a2e40cc616f4e4830222f6625f9d24801593dd42d7f405d363d954dbea7712d1191ca1c878698eb558aa720ebcaf0583956d509450e14b5411576d6e8c2e8c0cea6222e85424bc1969346c63424d2bf7dd55561adc3f52802c67f52e710092b0313d9d2bc1ae71349fe1b7da8854a9c001115593a4893f07bec56e5020025caa6fa74830584a1fef3a6d1aa841ae850a602aa97d7f7c7676d84be68d1862b62f77e8cf9acc24482b3aa687296ea0e02c343becd583177950f483e907925029ebbf2666b3740840dcdf35e9b2a7d18506bcbee5d97604bc6f6d6c2848e346fb38456f0f0a040e84cc6d37841384d65bca0e32cf9989a26ee2aefcfe25798497dbcc7ae1ec596c066c2384f8fee741f2c9d1a2196704f7b84f1d0f233fe839d88e363fb6867ec521488195e826d8597083c54dcccbb86b83713284a57a55c80cee8ce82d84260338009856b56985c238594531645ca5be58675f6a8cd27162ea25ce003a368cd9648cb5fd59b499e1df0c95192623c9936a384be123d2695d960e9b9cb92f2f880c14d1325333875ad3d5b304d5db6d60f2e75d3056d357263e943cbb9698d71c8255939b9d1f98a70bc53ec4164b9b77ab9eeef490c3eae417405f9c7db1a5ee298cb10ab6553980b28b5ebc4972548a0d017f13c90d87c4aeab1f19ded096736c8a9a62dd1e87ab915e1f8b28197779b4d95cb76b29c098be05675ce3c0bd51fda86f0a8545b12c074f9c66618c2a15aaba340cce3dd85b5287080472882fdc7d405ff94cc513153397726a132440f633749d1610e94c93f0a5ac98cd8a35fda0c89f757ab3b471f4941dd966cec397bb4dae4a218e4227724eb5088d94f792d33b35ce106e69438d4bbc192aed5c682c18610f50318feed279f403b5e441c8a4150ccaac50bdaccb34893a883f9b34b1df350d91c007b30236bfa36310af1aa7d49176256dc8cc477cf4ef12ed39766ddfbc2186fa9978937ac0fd10b4a35c83f7a6458ea0549d052c647b570566223707fb911b4f7d5c9600e4bf4b832466b8f74c68fd8844c7549ea1f59bb1a1fcd84f1b323d82f96e66bf72b01a240a8b06f82f474076d9ddf780fcd1c61b2355151d4bd91733be9f30d8d212ec8cf948d8e66128d29bf2e552e2ff73a41443019a04098b3746c0111418f4bb6af90d6b90c639ed5e92b69627d9a14f4986028eefaa39a6125560a7dbab8338db99b02945d136eac49a876afaaa52b0451c73f2a79b1339c013da0b4f24759d70509ab5f40cec425de994ab7b50f29357bbc4008dcbf5e45dbfccf060ad7c8cf20ba38ff0aa3080189ee042936f36227e876f6aabfeed75b21ae8ff9d4b7779cf74fba6338f404a9499500913663fd1a1431f144ff2470b0cd3e0121987a0", "287cb224c40448af96b345e9aeae63586aed8251b1fc1442a658d17c7e861588583bd165e0621b54632782ea4cde91f44d81db5e58335fbf74e0e28fde3061cbf77bc1e3b7209930835af8c6158c30c339718c2a2f5ce6c8400909947c9555f3945589cbf8573d9840494681d4cf9f99415844b2cbe798c58f0b131fced6fe1069d31e04efe412b06370da9e2d1ee542886b1cdb473b3a8d53f63ebfa8bf3572bd95b67c7e513234dac31d287e01e72a50a977a0d7d933f79bc21e3be7151dd43fd49887f735cc5d30856ece6f1be07a45d14d168f4037746bc76b737b1eaf4e099a9deb3d932a3da2f967475cfc76ae7558547b2aaafb7a077a8be55544b92625678571a46412c94d544b1b4283af3bb4c2742baa5545b091a0d688bcb40d85c4bd47e2c8ddc38a117baabec969fa426c7dfecfaa37db7d7a0d24ee4af3b739e779002a352306cac4b5a3389b19b3d55840c7964e9fce58fbc70f537971fc73f3595effbf86d910c95e77f43f70a20a35676d9f9d38fd791d227fe8fb7f0f15a87418c76f9e76802fb2ae236b4347f56659cdf886459a5f1ff394cbd46f013514de4d2a9df39a02d3f6395c06d1c6e94204946f6e8658c4deae0733d101c7a092921de32511393fbf6bab66abd955c8da4cc9941f44e117979be47fd129b8d0200b4af0fa689f532000618ea4e3705883209f41e980c46f642568ff7e67a821151552469f60c6af4978648525c6571dcb820075cd51cef7b55e3d30f7d07ae9d14194d3e37b7246c920cb16c2f6d75c22cb4134699334329d5e6b8864c17d375afc697bdac4e573f5ec333b47d71a103d10bfd93518d098860b38a2def5b148a141095ad51662e8b76f22ea665c765a6bf638d5889c221584927d50bc5da24013272d17034ac025136c135b0016db474f038e721819cacfc913ac1bee4062d7a5e4743c11f94e379dfed99c13f919eddf65376ff3cca11fe995f26f7834e9fdd6aecd114f294d3221e6a3a583b1d0accfeb6ddb9122ab13f504df345b26eddc4e9f3b25a8bbd34fb04cbaf8a492c1062e1add934b784ac978e63c343cf68ccd0a862d0c87d79d141d410c72e505a5e4cae6237999f1da5bcabb3d06f4e8e5eca088e4c42fc6ca16c30e276bfe3fa698e5c682f2c2d66a86bf176b813e593862191a9a09497df4b41e7760f78bc443dba6bb7f44d5f946c8c8b1ebc2e5fb68671e43d4664c51c192192b634a1dfc152e280fd8422415d7b15dc6e573e4c0523f1ef9469f5ca4f89f698456bc97a61c6768ba5952a5c9b31cb503922f85a64b2c64a5a65be9d8809fa750c55341093b2b1e346994484a4f383e248b30032113395c2a657a2bbe942286daace1b8cde6757cd8339a3760ddc429faeb2823607f77a24cdffe5034865860ecc1bb536dc936359a5e4b7413790c1e45c12b4d812899c6bd823b7f2044fb0dc2fb176f7e430728dd0b44c59e3dadba637e4f59095c2312b31b283d38b6713b920cc6f2f5ed07401caff6344f41d0805324c511ecad7597ba1738965cceeb06a80e68246f7e216e88a8873793023dcfcaea5f43c31cf0c32c828aee66ce15f3f3c7b7577e5d250c75cca351416ef9ebdf02c22be8fc9c3a691dccabeacb8adff243d7697513d87a04991abeb485ec0311f3ba16891ee2cecde90b5c1435fa3a4530e16ee2f145595603103765d93dd57fe69947caf9c083960a5c8957d582539a3a304bc1d050d53cc41dcaffac5d76ea54d2c594740ea775ef6d6e250b17825816a3a9ffa2439210653cbcb0bb734308a0fd84c5feada548ba5a6e3fff767dcb4ccc61b6d11aef92305dcc66540cf34cf089c308b95b7507d294a43de2d0e698cd09aaacc430aea6f6cede3597a78ed687a83cbf1ed4d259192ad487b21db8b5509f19bbf9bc5ec92a29e0329498be3e9afc42762e94e2f1bad2beca883a7f8b466be304fb8c8f9072b2497562a2a4f33f82666f105b0357661ea1a0d2f23bc6afe470a645f3f4f1f1c14adbc54255db38dd88b58abf5262d751e2e09cf6a83df74ca6452983096ae72a5c276e93dec129cd2161bcfd6b9da83c1e52a5a8a95070176db0a9faeccde92e5d8124255d976277ed166835badeded516950b9d86d68faf3fb91a08676cd64b19ed5a212a43e6267b6e6d83b2e4092cf2273491973a079a61fcd9ccd096f6b640aa5cd72c49e38b2fae763a1181da05dcac481a0efe1dd523480698e072108c800dcecb8cc5f8f35571be68f712ea06d22145a89ac97435f98d303ff0c19a3034471e184b0063c9370b505e04b2a343fd0a529b473dc364a4c8c3748920c7678975f0f634fb77fcac145b1b3a946193b6e059fd74bfa2ce21ce7ed369421ae194f66b785118e2d418c65de8d096fd72d0dcdfdfae7a6f371ff9a7a4fed54b5e7273966e58ff7ae11c70dd84f5c89dacc674addda1f6757aaae112909fdcb3d1fc25ccfb1fb9d5dedc9668c378b3c969ea81a5a0dc596846ffccc63131a67af3b90196aa6e43d6673e7da7f2384f82ed8ceaf6ae749b206c3e62c15a78f2f57d096f2d3cd583c4918720dddd68cfd70fd34f4507d9b0b528dcf5eca90bcf233159a7f91050366757d614825d2148a70e53866439c6c6183d40d1a96bfdc49bed44e618f43bb5f400cf54890371eb14f238ad7bd00bd449a4e3fc6898f592b4634f660a4b96aff126ac964306c007307f46e990ee3603fc625fb1b4aa94d3ce77f9e0fe0fd1d1c581c18c1df1913ce7159a810a30542cb5dfce7c121f7138d995ff73c273b592b880b93641668e26b45bc1ba2570e634f4d6554e20fbfa9c974f9c9ade7b25b797d79f4027946474bcd6f4d8a8a14a793de636b43b1e3a6755e59aa992fbd6a0f195ee82a5d6a41d3517379b8dd89d1c714c086b1905949b4fa71941ac073b687b2be9f6f2ce2cfe4e96ebff4bf71e8872726e3b885d34c7e589ba65aef86e3473919ce3cc736e6d8029ee5959ff163396f7b5f7d656076644905f9ef0be709076b5bdec18fd3fc44a2dea64e5ec0efadccaeb6985e2fc3444d5248b06072f689b511f71de1970eeaf937db09c88f3d829f5fe4741508a188d0e4f41c785048c647b8944e0282c3f8abf86b583f223a18ce2f2da548239eec892c130c39ffc989fb043634acda159fc177ae0c2fc25d51e0ab27045fa4ec9dbf8f551d14294e86f600104cdf5cd43ddc3e216179909ff7c3208f9d89f15441c2b129e8bd770506cea993ead13b6a08d0b74ddb2743e3f82fe5de28a27926c26afed4518e0ad32e3f746dc7be6e92a9b1c2cccc678e5c528810365d396b3c14fa7071dfade95b9c9ae36c55ed24b9944f41177035da0967002b87ede14f44e046b7f0df21edd164462d82b4025930cc1a87dab9fc537bb220cd002e93dee4372cbc57dcdf13e878421db90a62952285df058807fd971dfe1fa51fdb7e3e65d3771b29555423d1a663493dd0833fc7b966ea63ee525ec5a066d78d487b161411601beb17b81f3be673f076d31c2e404abea06e2161154bed2112089333ff7cb21963e9b6c7b614457573cb0a8d0b99f58aa72a433961df9e2b9ccd98dedcca115aba08dc16641d38d035654f3e7261446f74d0c60476dc4a78a09d86e50ce281d0e58966f1c4d4a9896144b79c174d09de3eb6d36a0b545b5c3027cd7cf9646a383268c1f6d0535f8c1668010132c6bb2c2722d11762d4987abedc224253120a4ad53b22cd1c72e7f12109a4ed4407f735b7da0d45727ce6adca1e93d869574f1b0640af3658b09d27f2a30bc6bb3e28cc3b927cb92f479f4d8e10f5a2c5d826d269238373288019610d13481a8edb786bc8eb720b8894cf23bb3661086f7c50162aca153b2fc61868f062c26c48d90f8be47dfb91a2c233b8202ee16c506d6c3fa836600defe5bb4c47439cd4fa4c6d2be1f89298ac963d6992c593561576e3a9d2621bce1f614353cbf5cd5eb18bed19f28a4dd24b5554018ddd1c13cd529df6b9abf249d8c80111989b6bdb84325a413cebac13d5e95dea9d812fcd1d7575d14afb5c30bfe260f9f4499eddc0fe7f87c6a90817f6d162afc14e2741e540793f92a0d924a083f1fdd6b77fd2f2e514bcf311ea52e3665199e31eab7839af66ac15a2adf300d0a076d1351351b9bbde91d2c0f0f01566c370d4bf558aa6a969acda59edfabfb6199fcf4bd08996c41a0bbd6acc8a3699a5854347cfee4a9738089e3d869e9", .None}, + {.Sqr, "99a1ced076e435cb75f59d1098d17f46bf043eb9e5b7e407f60eaa215152e23300eb73edd375efcd11ff783a94ea521611ccef8267b80749982d0a65dc3517f72928b56a2d9f2c78b3416071ccdd27025506f9110ae026d2b4663e098555908efa052f3283214ee38ae6c91e84e8ca59ed073e0231dcd4fd74906b0c7db5903be235674c0592a7d6bc0e9a23dc1d4e5893d56cbb9d7ecc73cfba822d042df9c12cbd96348e8028de77bd9a76d01e6ae6e66c8c7bb840104288dbebe08987693615514b0b0fff62cdf895f45a8dc2c4974778f1150e33f786319f1d2e50c2f9dc786c3365ce92816c5c91076f34d0def41d13ebc34c90ffa883ae8bc488b30186a8942ee4a48433395d3d4e2345a0b67b27de1346d399eb943c203395868ee79b0485b96377e946ffc7e1f64a7f8b8732088395be2a45b9fe23afc3686a75db87b710f59f5abafa82c03e2c7cbddf7009ebf135ecc53e558bea260cdc67345494fda7022c939d818c64a9e864a7eef686b136d3b783aaa987dbfbc5fffb783f6ad8da65fc1145f0c3366c93e2a3b5d0e08fc2db47690b70a602769f197f85ad204e3d3ace0b92846a666dca9d7e4d654e8168adf6792304d0ef559b1750a2cde3499bdab90744123d4ba5bafcb4f7b9decbf4c9901987a58c48f704a35538ac5ef899f2869057007c318c337bd76b4b91cde975174cd4af913ee23922bcf19dc4d5ea664f88a95bd55f1794a447ffdee7a6e99385d8678390d64ea677ddcfae646f311213759516d6f9bd6fb285ac30e9985a7154df50a7b7e62aa2ccd5dd9a074ff1d480ad126ffa4c336bbfed122e83fa09a511de113b5a1086c458d5c1c7b8e843a4f70c1fe6321907d088e2bfb5e273931dae3b62093eaa48abb756b16aa3f549ec0aef465ebe6d20afecaca1aa2ddaf001dabbfc00d9033adc0f8aa67570163bdf43ef272958830bb39ed140199bf36a57d91c428d78518a0ff08a7c1a2f6b9ae627335d3b42861a6159fe321ad3d43412535e4f4663fa9a656e661c55ba64bfa5bd1818a881408de50d37cbcb7963a45ddddb5982f93dcf7e6ab4a0a906dd21cfcb4ed3fdcf4a8549f401d6ed9038ec02291c44d03c8cef34cc1544c3544d528003104416ea9dcecf8b54741770b68d82f08bf824d437e27c8a1e3b2e3e941a5d1c344477cf0e0b9eb65632fde6a919e388140af534b4db7d19c82bea0b21c80d54590dc1ecbc23266caf18de2052a554adeaa4eb2d3e08d043c34759b04733b392486431b877abd4679cc4b89484b1912773b4908ffa4967b3b07ae98352501ad285a46c19ec51cdfe116145e0826da8d4d4a8d90f3ac38d9c2498f2878b1aadc0871a84e883cb6380c6c0d92f618d72f335a801b38cde13638c558e25758d52ecc8244cbfa730cf9acdf09a09d4f4e59fa83d93a690b6730c39fd9ede42c6aa69fad5b97e3ac3c869dae891a177d55aa39ba0d10db325d09f7bad13d2f3534d64604126fdc40bc23a45da42b9eab93f8b6c2bcf419a9e9ef161dc8e913b0f95948c96369ed857529ea5d2cf0243f000066650de060ca67ac1df562fe10635c49fb9c8d893ab7a89debc42e08ed9c3f7e8fe70945c038701d943db46b0deed5003f92b5e70d0264a4050ddd9162210d7cc6550b8370bb58114260e4f6c0e0818ac6f040295fbbf1e16c1af41b3335b421112cd9a5165eeb11bddd0020aa4297bf429fa3d7678b54df445515a90f7b2cad40effd40b60f1bfb8f274b2e79161dc8dd78ffae23ff630a209d692031058b9069f4d54eb418dacb1fe99aad05622faad6be6d098c3c81fd55536df3a7f8411c7eacafa492ac67bdc84d895d90ba74ee0d2399f47ea46a318b9f18abdd5e8e2510f8aae9108d092d537735281c08e38ac6ded40a48f90dd250457a99544765826a41c4a900069d53c37a0c212733db957ba640de6d34dc570b36a2079831e6972554639325457da38f27c54b7b3f198d8cc6db1d6596bbb8763b28bcb7f10abc7c80bb7c411e6973f56c610021211117b0a7e31ca833fc395f3930af936ea10057d33282952280dbaed2d24ded51d9a00af93b93db458e67343561bc5841b4c1f2c7875021fc929c4", "d9b3af80bb9d3658ba4eb94d4e8ea178681ce85161a1b8ff93569389d9b6b7298633391dffb478d8e1283bc1b9872077d6da90ad13aa146a4f438cfae4d70805149cd43dd7ffdbc1cd370d6aa34273df25533bf55d6fd6e82d804d786a1f65a3ee8b4c8b780fbdca7ae23dbc7395c79dcb0e19c853b2e2e5fc359b4db8d8e9d0a592a4c1f256cdb4fd8cf0bbaee457552196dd0d4966aca72b7da8afc77a3afac99f4f5688e2893a42dd1b66772dc11605b2dc0215fb8d2a74b7e1f5acd3005910317ca9cff8b541f93efdf2719162753e44c9513b371263349341d9072801d9185cac5ec5147e6a105d83650e94a0bf274353c0001ac3813ddf7a15382f1a9c7f55b558a147da43622b7361112d3eb888dd66c71e2150c87545d4655293f3cc309cc1c4c7a4e5738e9cb2508713b8cc4aaf3c475fdf8ca3016bf68e551abb2ff32e30dcf266fd17c0b36b059b62903c4dd6356c38a702fc425ae30625415678330764c22b36df5b768527caeda3fc921b38d4a2ccd2a5073799f568b2d0690deac68594c1b86c5c8050d5520ac5de676857e7bb4ffcef30210c37d3b5734b93bf78fd3def2df4d4e4908368dc3c78d965945b806597aaeeadd19602822d5da24f1ef09c3c14db1fe304e190efd9b3a9890a2d766087b629fb469116ce28f18f2feaddb042737e532846c8b68f7647e7a055b279ddc6510bc0932e14bd386dd2a96cc46619bea93c7200f04735ed44a6e0bdf1eefd97fb562f1270160f518425b876d9bf4bba10026a76e278d83988c36bbf8222483a1f7d4b6824bb38c453cbcd932e0d6b500256aedb677df0153b00e8ed92d888a00478b032cc398da7619008fbeeab382b92ff3ea759532084ee3d48ffd4434966c5267e0355e6c7897fa44c1f5d5caa08c10b201ec648aee20141356b9f3963021c76e05f4a3434bf72a597d805c7289570eff0f53c2f1b01cd1ae1fabc0ed38db682422550fab089873981177c286f8ca0f00d8db124c97a2c237fc5f05e880dac36504eca50867f1b16cc099af33cd857e6b1aefa89e2fc61606a027d72ac868b01c3b4a0eaed2b06f49d3af34c8e2d9b51c0d25aed7bcad67bfefa8a2f026a3c6c4a431457b7e12f3008f22aa92270752198ac2bf0b96c908ff32f7a3bc09a1fdc4652be1bb3f05f3448824d81f7d0241d50df3285456bdd42c351bcf293ae725a9a9169d8bc725387e803bf7bf18c795915fd282ad229e90a90c9fed08c58b1281c4fdff12507bf908a5535cbba51eb756ac8798f45717b76806495fc2d999d15fa8ee8792dbce33141edb1a2bab32dac633a675581be9fae02d0e8e1083c60b67f2077bf39464b4255465901f69ef14339db943afecaa33711ef5c0e03b9240146c84fca39d6b02b4564ec81680458c0068f94e715f130fff4c71f0f40d53ed4b1159043e9406b837fa5a2ac69c1ae5dba61b52368a1ba9d12c23051a279c30b2d4ad52bbc3f751a2502b5979682b06d824b232c78fea581e6803c652c55cc79db9863506beff67d028d191405487faffe1b226f784d3fdbcfb071bcec9f9557532a07bb021e2abd73473cc43ffa4297a311e24f863abfacefc41171df56e6f1e69d90757fc4b9226bc45614eb8958349a0e4ea0425d41cd236ee3e828df737357a48d8a2586837d8326b1d2f010698aa0e4025bb17a1fe66f854a5e25a415bbbbecb65905a7ec340527668464bfd30d73ecefc98ae5320311491804f0dc7e7b5373b7ddc23050fbe58bdd457d5724c71ee80b1bcfec2f895058e3ba53cbd025a60b1ed656b376518c875c05081daa114e6024a067b90a0288a064782d457f946ec3520236a04f6223e1c2354612b74f39ba90f32b45474f91392ac342e24a18de95f6f2493c3f520ec801622f3a5b08801a2a7c306dd0cf9ba131129a71f2bf9a00af48d7fe8181ef11294126bd37cb9285acab0f8323a69d23d5b7588c1fbf5a2e74452f61bb4ac6cc0a54f9ec67e8ef767bea3aed2ad4ce3ec128095d99d7c8a4c8e089eb5733d47863c11b4ccf51793126294735f2685c49a2893001d3f6f4263d87b0095633f6281d22fe9876f1741e7833c4bc747e5997544a55fb3f06144eede6", "5c32cf7af7667c718d8bfe2bcbe6fd6533efc0028d22862e15152da162b60907803d5071de7a1f5ca4dc1130a97c72c5c559042a528a7eea1fdafa3478c692367f61caa42bd0d0498c42945739592ee40e802f4dc3de1c8bf67660a848865c15276c607353b5130ebd627124b037ca29ee9cbcba08a56dff9095431b9744c610bf673022c8b5ce2c1c8279f3d153ec2b5560a2e2aee10ab0f55992d4f3f33e7a92c2472ce6fa32a2773824305014669061a730984a2b3b57f6587b0c68c3871f54bb6d876c483bf6ab60857c07f241489ef233406f611e4661b7aa12f7ef60dfa1339379b03eaa231550534c10aa4a2a377ffc16daa7b2bb3f0ada852d93c4c216bf12f796d0bd141a5dde7dfa430476d876d163f66c7a196e73dc07c0fa0e1631d2270b7bc2b0722eb44920abebc023b4da63651050b84a155c18c52ee73994c66e85d83d45de38e3616ae9aab7b2219f548b9a03cf368538c3d9c1a170500e5f035ce3e46fa7a948d52d2b7aacdca63fc6974cddd83c246bb17ca966b7d23e6e4dfef1f0b09c906729c2362e4e7a0b276e5750cd786533e998c6c37ac3fcbcf266b6b2e77f8d428a867c17d866bffdda11b728807c037b60b81d2b53b51556fdd5a367c52bd7ade11f9067454c0f06102496a9d5c73505a636cc9a42ff1ee7c6aab278bb6acf68f3df1aa66b86e41350d76fd8a63b15649284d2fadceb01f7a9192528738c3bae586bcf6bb6535676d3112b29b94ad57a2567e9c4b53d9180256d065fc9b67010b237318bb2beadf46dfee5e93fc152907b13ed4a6985394528b4c880539fd607afbb3738ba76de39d0f3dee91e69b10a2323d5b2a32d866bf725e1ceb86929bfdad921408b86854c8f756c377f2506abf47b9f14b8fcb8c5330edb505d1997a90104e67902cfd2bd3a719c8e025d590dc70dd151d0ad538b71e8d42a8f39191a1d037064b0f76f139c17e911d5f73ee28d4eb4e217278b40350876165eee1e6a26b684baab66ffea0cc5589e911da63e2d05e2b99e13208c06bc51b60088fa0adbf657b66518ed29ced48401dc02109213a7c833beda5fcfd11a7309e91cdbe42d22b86580002873e82a38bd98e88010f7e743a1d029d3b4099fbeb88114ecd88b13e63c416df37a5386dec9916a3c95282945d8d4c403303edba77915d461b5986630f2bd3166698c51d14080779cfb830338f3c24d6e7affe6195ec8a1ca8ac99eb595f190072fdbb4d59c18944caee5d89e9192a108248fc5e9c1e34e8b6e093e39d82e59a97cea48bd1239fe167849d1c6982944532d19681b19ea68c6f4a6b575efa48f385b6ba8126984df615988cc0fc7e3e8090a6ebe48c4907fb0efcccd93f4bb2557ab868cca04afb4add061d07f9002237decca23a72e1f8675eb4de20596638683697d6bde67cf17e5671a59caa399d88236b9dd7b1b37e729dca05dc1daefd5534eff7b709dd78b6410b0c782197fec0eefa0154fb5620703d579864a76f1dc84d327dbe42dfddb1f114ad9f1bb01b11b5434d5d180fee0ddb07d6a59bb495197cf7c76692e54c922338218d805de398b02a61f6031f332af0b511569a477e283cfbbd764e12628d7d1ab6a71ba6b6f163186f4d116a8433504a94d610ad41053fc26ebd192941536b68e39762aa4d54549ba8158a898bdd4bbec712ef0a957048c7b41dbce566baf52c73ef86c1532a220c430ad2fdb78fdf7e885237dbb1b0dad13fcd360be2342d161f455141cc8852be1e6ed15e4e69783eda145707d448b95bfff1d9320c1a5932783cd96b79d4fff9b16c3bfc8bc46c7d752bb71dc37ab044d9f888d66af6475151e25924e042834bac4fd1e672d28b7d6f2b37f8819ab5b0a45adc5863757ecce04b980d9de573d978bc1af19480ab9e435caa94a049f7ada7320efb15f47a58f25814910a61f8de2055ef44dd390ef4e52d58830dc2dbb1c03309050e93ebcd719f62c3a8f090f21d439f83cd9125931aa66c45a8b24593cf1ea7fcf4c80c7c66d70be6c9df3380d44599a3424244d6da68e906804f6b903c5ac5c75a48c5ffbe12f5df078792e4eff6bf6b6b5f2e320ba01a73940f3e716000cc18cc9ede69a6df28a9de765419ab1daff2477536537cd94e8eb2294dba9fc3550039a8d2d77b6476599b9115bbae4307c374aa538055989a8e1bca68cd99d30f72bc55037da0b2a3039fa6b5a8449053f57813f50fee9f496cc9c6df984dcc61e504e4e28b6ff807939843b9d5d0b9eb0bf02be720799439b09c6399e1871128442086da0ed18f38f4549bf91164a10ec35ccd58d45ac99b98e09b942ee78c1928e5918410685f7df6f54aa23efb669787ae5627d4f6c1e98369425e223298e540a001235bb5ed10eb333f5fe9c5b0db6f55e2311b4a0850bbc77f378effe2e893705293cc80b4d4306eb7c767724f46a49adc761f3839c0901d4c7851ec3a320160daf8b819f63f65b071f88af44f1ef9f51148193c31077fe01f5a567c2f0dd7db315e252e3cd79e42dfd8e217fc0ac56e6fea9e30df3cc64661509abaa99edeb31f4a185a4aae2171193ec45c1e8eabffe22ad91fbf05bb1f75cbd3879ad4e37aed0bb848c45cd9e01e770b98d5d6db6d44f1b90f57b0d08e7321098ced6676c1210beba9077557dbdf6e0bcfab69caa76f80230bbe62940b280dc9bae1e1cf6363114e34da4184f2eb891c8ae68e1a8c65db2708222fec19aed51a94f0a6577d827792bd90346cb21282156627ff5c29eda5b13a1b0fdd850ed09eb2268a8bb2dcf59d3032e790554d6ddcfc92348f76197563de5fb9ff63416d17a119a1011dd592335b9ba4343c243cee4294cb504653ff142abef200fc6b59833007485dff6dd3c7cb1eed5a84106c620edf8480c2c8f212d982cf7057afb0ca30753b55ed1e5cc192bbe1f4f75da06770cdcade6415abdcd72359c35df0ab323c283d818f5033e97ef70dce0dbb3520ef2540ea3ae52c191ec32c89c430c6a2caf8820af0a5a49eca4a526cd4df6c9640d537d622d351a1e182f94bc4a677acab5d104b8291a0483ab010a9d73e20a81afd036ef57e3ec54461c533b9153769be126a1a9ee4015af3df2ac47fdbf45fe00e8faf890fbc28fa9c99af2d2462ba3df3d5a282a3fc964b85eef1b5be45383cc54b3e21aab888e58cbcfd7f3fb635ec48257e03433b59302bed5d26564e5ac623dda1901148301c6747cd19bad0b2543d2f02549c87505bad2f93665bee6f24f4a99b3443a4d27b47526f5f0e1f0f22cdeb57c01321bb1261a6f4a35229d2f6b5ed05c933ade7efdfca76e5c56856d9094aeb7cb7022a148a3153a3ec40adcda8b16d08898bb217c6daf0704ef950d458de84dff6da2eda5bc53d44daa84ebe11366c387876fee6916ced066d38925127efae2fda4f268fe9b7e00d33c47cc9040625bce9c1af5c08ad6d5793ec2087ed7ace0ff1b07b2ac62c2439ee54c45a767b518f68a5acbc2d785cb7662ff24636ac8219a1a5e14dd6bfe8456ff893ae057c67278ea4e3529fa50dd985d70b76fea5e19608a89aea9218139bd9f90ee0c114a171e6bd3d64a52038148562a3d438cbf17b84812ab0a62c174118d73975f8698330837756b87b31858fc06afcfa9ba7351bfeb5eb5e6d405292696924612c325a2b79255b46c1a98cd30b8a4ec508eb8fc4cabfa4fa64792e476b25b841221a79c1df0750423873fd133ad72eb03aac5924003ed330223d3c553d9e14e4f567c649893b07c31eee5fa9f733db572f14b9e6a8f524a116b47907cedd8ca85036664ea9bd50eabfec217eb52a5b52a5da297c45c0949b5f474626e573026dd4a7b9c030335714fe4bad4905a60c841f512f3764ed7d59b9ed2c83fe8b981f9f039ba45d069c0d317eee72a10137ae35c01cfaa93e594fdf2d3c2af5c615fcc8d9b211118156b15992690daef9ad5be4654ee126a6edc6fbdd9e2ae916c764c22c2c6eac069747c0b023faf062ceefef68e4c1cd5ef9927470281592352ae515e396f50a8fddacca1fc2f6ba6dd12899a5e0f0c8d5e04da77521117bfee704404ceb9db493ec0395ef7b4b3a6edc149536f4255e949bd8726eddc0b8ef64724222310c586bf8d86643566ed8d7ffc8798fd46a0590b587c3a97b3298c65633b4ac4097424e1b490943a96270f51e680bc2315e43e9fdbde6ad82f36dacb766bb0693bbd055c33b30172b542617ceb04254014985e10", .None}, + {.Sqr, "b20721585d0e06ab5f2293d22d56d5bdc90e0b79cae52743d2facb7cacd1702912718dd1b1a974b070865e05041fd257ea44e91f4510e4facfe0f629203e1fb7cb2c4db56a9f0b8779b775d12db5007b9b6be74843b61783f8a030d20d32ec0621e537ec0e22545f2067549d325285b8f4fcc5d465eaa645f0a68113ad4cbf7b3827fc3760bc0ad1fe96268fe8a5139fb3386689887472b2494c2948d6b6fb350511547a3d3ebcf234f38cc7deb2a84858031841aba61206b9fff4b8fb692c3377676bd80ab6b9a1893f057178f9bf540b42e2da4dc44218c361ac168590dd932cdedd26a0e5dc0f869a960825090d3f324e45dc555fc7a591b90f8bd70f1187554dc254f47ad199231d6d4dc711a54363ecfefb6aef076f632f53dfcf0cc9e133c0a20c385181d329550079b42cd14b52801a0d45f0ea4f67a11a40878a6d9be5254ce08c15796f9d968bd3e250df02519051247f48ae6a70f98846816506d2ae43ca43404ffdda1c099451f32bb9ba85887fad80f76879a5d0be1415d8c4dcec5bc2f6a41d421d5563f7c4972feac69ad3ea721be50877afa1adbd55d3adb36d4c086017c0e94dda7abb99f8c1d518353eec8d02f32d740338c63166c6826d9ea9752ce31bc696ebf194c3703bb3a6d7e48c6230c4ca29b4a342bf0355dc33c509f428a69699a6bb80ae052e39a7d292af1a8568e877133558ea6b063f5d84bc8a1912d4c567c15df1bf1a11e15a5bdad56a183ad6a0d5c1399607ef1a686fdfaa6ace3a691c293c7edbb06303afdb378a790fccafbcedb7c685dcf97decad5cf5468f644da280bc3d32bd1490015403b8e780abf31324bdae1b6cff5474683bd96fcb2e681d8978df358f9d6b5e06b8a75ebd624805a8eb797bc96a2de0d980fa385953062150b4992af3b88991418bb4b2c7e779a0bc0f619d7da5c0f0176e11d1deb66da442197e7bcaa05699abf46833b5b35e1a2250e7196182d52cb0e0c9ce69ee8baedfde34108411aed9f6ac5cb86298c712acc3525a9a35e5dcbe5c0447215e01bf6ee75e252d66652ac9b68fa4e2fcdc2136adf1bc35c8a167717f38e29a1853ed783d94dd277bafbf7449c100f97f59e759158174577aae78f5c3270b962cc4f53e227b8af070428511a6d9841390bffe874fd7b04f5cfcbfd69956e2e5332b368ed5f078b6c90a18c5d2275ddb6281cf1247f790c768589d1db1c697405d840a626f7782a569188d22f32a35675aafd0c0dc2d53f373a9e3ad7559bee8f92cb076c1b53dbc22c0af9a8fb3485c8c007514c3bed42869ff97c009f3caedb6f1a1766bb36d5276c9c2f86f31fd32ed19cc0af3f43e7d2f1b89e8307c4e380d5b4e236974eeb702a4fb76b70612c075b70cbb40b95ec528961ad4b520100f9065d5153e5a01ff3b5759e0f5c02f8a49d42d1ac1d346891512b3eff9ab13d957444ffc54a54a143d48f0294354d685201faaf95cf7b24c15b1a2addc0b67350192b6c4e7bff1e9268b7294c0aef0bac794aa3282e2324f06d059b9b748d435f6b1fd42c1eced89c8dc9045b53a460fd6d572611b797cab1bd67b3b56ba553029a03830d6aa50d87b94361c82497ece45b96b4e84d6a04742a6143d6b6632911fb67afec715498fa9e27655bf4a6afbaf3f0e4d62716d10d8ed3baa18be7693d9de53489701f5499d0c425c3c23bd7446b497a79e17769075208810e130f1f497e400ef06085cfd6fd8a494122b1c84b1807a80ae09f867d4b0500e7d4f1a129436b0ec6a63be3636d5d08fb54f961802b5d956b666a7a14fea6f0543c77bf970dca64f04794ef4b480fba4fe85549fa9c67f57fc5e2cdaea58ec62cfab769a78b4c49803cfa2dad301ab600794ae6d327c0102df23c154a7c77743ce17977de10d362cfb3e63cf89f55eb41ef74786fccc818ca88212a65f5f27658f31919ac0dab8164408c50395a0f58d6da93ab6db35a099379d5810ce77b7ad61bfacacf263886e8d38ace4a3feb024426722ccfd61fb3bd25ded2edee67cd64a8b50aeb44829013d1c20ae50c388e662071c120c30ffd4402ff4dd423299fbcc7dc4094f786acc3515f9ef10c3c647784509ffbc5f5f5895cda9c", "b266553838ea5d18f14a2803ffba7f855f92695818253465ba64cb846b798cf69c208af81d9dbfbb3f0b803c746d6ab4de327a19c93114aec791b185d1c910ef1d166c4924735ec290e96f32186f9eb885042c8da054f05babf4922fe5316380b006cf0c5e497a8c323a25ab619051b9bc485d6235560e964a06dd2b2ce4cf3a35e5e2b43dd81680a048ef96ef34a34dddda6174ff8e38d0e03b373931a440bd9f1471d267333c277f67f46e138baefc5ddf3efcb55eda65fc9b42356d09ef85916d3acd92d456af8d1b389ec4b177677faed35709992210aa23b388031dbfe89746f045e7fc15829ae773f32721749fc2832b27371c2fb72bbcc5a0fd49ab1f641430d7e6d54e9b98cfd9b610fc5518c12ac6b782e7cd913063d14847b9591ed70b414dcd0e94a1a122caefaf106ac48f87e60b96b9ffc7ed144fc62232efd092dc59c867fb4ff46a103fa80c07ef952ee1217b26011755f7d05f127d29867b7915d478524f2275fbae994c48d9fbfbea28227afd42a4c2d33209689787cc0e28612132055020057e6ebcedfa88743a18a8c73b63f99b8e9c6b6f82b67ea70c2f8c017f436ac5c6b44710b456bba15c9edf39c40e60bcd5dfb0e8ef1acdc6f47fa9dd897d3c394cdf5b66de5800036bfdbe7e27d3e9c69bd164ceb94385dda4c039b338d8420ea3981367eedd6657784f216202c4cfc7ae86ec6995080d395caa0e019dd493f83afc828f301d138b024f084a73d0f0e6a5c3843d6a4018bb7f6975ed63198e4990e4a78e7082574301d753d0d297f205c2d263dad1300a3b7d09360abf04d518a0605247209b38e07331bf5ca25fbc116883a31652fbf5c545690f095354f7aacb595cdbce5d29fe8599acde8719c95684cc305b620e46bb1d14d03d87e8d6388477808170b56eb82aed672c9fe3eef26326e0ca5b777b3c30048dd3a166f32d5d86b68259959fa62af93ba5e170619bbdc51d2af0224adc2cfcf906e8761f42774da229e7532dfb7f6465767b514b4154b0accd2afa1c03daa49e825d777647236f0d236ff4db22772dc47fb28aa313f9fa95ac830d51fbf5ff66271a65fb787cb35c6a76c8390469e1a748f415f39ea2c3ba7d1adbaad77642bbeb6770459a2742aef169d8c7dba30cc4ef97630ff5340c677adaf325cbd08ace2d99620521996ee0a9943447fe7f2c15fd5d199f579165871e5b1069e7bfdd52ff3d2e21ad9ed14dda2c580fee01621335ce078c9662e574fe88e5aa2f0900e4bf3181169efbc62b09ccc778d52f2721cd9200068c1db14e24cc35fc0e627ba9daa25a0f9e64520fcd4457151537b0d056343018a822daddcde85d6f27a55e238137293e80f7f7f6809bca258fc44e1b83c0be3b19a29b61afebb8f62a6af71dce0454ce658649425f720a6109e2006280c3f775a64869127341ab21f6e89a04d5acb7e2e9ce7bf7830e07f732603383268b9dce06042dce7f32e3c023a8c4e3bf4724772ad723e303d2344067b9e1f05736d3729275f69f5681f2b3de534551f1e36f481834ea9cd112af403270b633e1e485cb2c74caa71376072e8d0486562ac0be4778ff76b0bab405a7194be177ab5355bdc7f3ef9eef6a257172add0ca3f3187345f8a362c76fd88cb811bf3f980c49c4f8eabdd3321e6ae25c86ce72dcbd4fab3eb40f4395e92993946f21e484c441a5ee7bf905b5ff85d7f900f13fdbdb09131beece0e980ed072d97a10e01341c6eb9f919fa4d0106bee0b1ce640f9abbd5448fa5000a1f909b6b0b47f169bc916fe88e20401a84aea2bbce69980d692cabab6ed7eba3f5c05c6339981824b721c7358d6a2dcdf39ee7a8ad986f9368d1a77625147d134bd2b9572e09649335807defeba567d9c0b94d391c4f7346c3dc13a599d18a6a78dd19cb230cb087550cea33ba45a8f0436d65cc13baf88555be90055c8636e30cbfc7a611f3202b19bbbcb25c672353ae6e72f92c1677875447548b54f4bb12c13511f877f9c6b5971883b78116095349f49f49ad9292d1d90d67c7f66d6ce543e0e22588a67c97b3cf7c082922611e3bf1e2ee21a6c1120b7216e0c309967755db0c2892e0787d37399f48d54d6bb27682", "7bcdea91b8947e8866db3f69ec770e87e52e771f571f3a57ce669aa20885b90bb5216cb6828613f71112e04b2a210fbc0b94d0ffa95d09da6303f9a4345529a1f7825f41b8132c2081080736bdf2549b8ce46c8711e47f8ecb578a6a04a0e62e149b8b886416e424c6c6f4c7c7091f28acb32a7ce53a370abcf134206e4810c1a7b30c8330400e7719e80462a91150352b07553b475df96f301efd90899af394778a0dd2f3a7503e992236da1f258abe5028d1ad523d8ffc300892e2f90d7e487dbe77ace5e42580c9ca77ef98ea1c50e8cccbf079aa26280cd7aa69b461b17aafda9a1de6286931093a1b60ffc43e8e7d6c5cd09e794544c64b0851c09a62dc0c40481d0086d1f51f3c71889bbe5899be95ed82f51e215d8ba8d724d21782463a13a6406274740fe2e78368b6cf4b5aaa0e9d4e2cb15cf0aa409886761ac1bb8158aca552c6dac15e47918761f3a805425e6eae87918962b10db0fdd1aeca54a97362eed4b648a168d2a65c8c033637a7263a981f0010bbb021121643f5dbd9846e7867ca38d3a94e44250f318ed91cfdbf5b266c786dd34b2ff56f5d7b2224fd5cca80db4cd4fc1f100074339077cbf34b6c80397fa6db1e274fd32d69f78a699e65611e22b8470334656bf4f16eab9a501e3fa9a672f4856724ba96fa4143744ff67e619c15ad4655accf4190c8e69e02a9c0468d4ce360182fd4431609903b82e58f8e65cd0a7b4f3e59e8808a4a8f0db2312c6631cd36f148123ad4d43a433577c5903188cb26523938c89e79e5378703e99a65290238592304ff7706dfcb8fbcba909558aa79495efb54b99edb1f8629e7a73c2db8086aafc820dbc3a00c4457e79c6de2408340906f44f0150ed432c1a24d97db28bedd9854741086d856509db3956fc8d6f79825947dc41f0d49d1640318f7855125e98ddc074ceff307e26d989125bcf67f993309406653886e71bf57ad31ef7c19cb5a54d5c194ead8c9a8bb4758f703603f54af1148c130cabf9692ded163f02a45a6127ef3bca8f72897bac5056cfab0305a58fe2e0da37eade1f789c17a009a68a04a488fec6ae82cf93dce084a53bb6a485a4b89bc0c9d8655922cf4845b21eff8f90eaa8b005ed4c2ad630fad4cef390573061f2b487971c33fcbf4a3f932ad1da720f9dd6fd0e65ba66b549314fea7191d1c20438790254e23a83fb072b2b82825506dddb7fee96a5bfe44600f0fd495a62670549cd138586317801c455a24193c63da072ec3192bf1da5f615076e1a225ead83c109c5691849daca7c17434e751c125fe7f3007e9efb0a4a4ba88e40f5a3078a0dd17f1242d83a9610b39f0b2f76e46aead4be4a6f29d859cbeefe6cb8c5a65c259de3902b39e7cd1bd0061fac0752aa07f21a5781ab3f0beb126084cb78f5ad27b985955ca4400b738350a31ca3fab883b877d445f6fd196280b6496e86e982912247a5547fb897059d6251754d3c901eb4557bd8affa406481726b2ee19e4cfd95aa6f2d19d1758eb3f26142f68e0308005d3db3fe6788fa02f9bd6af9c8caa1b160078949eafaa9199a0d2d6ffcb7988522e35ce9be2ee842a57ca166f50a37982f4af3e009ca2de7deb5147c614bd392945c6d704ce92f47af3c5487c363e793d66647b5a6a5e9639a67f6de73f84a0a8b20c0ceea8ecca91aa08a66ef1f499ac9a3ab9534cc545ae64c816b144029424900ead832a5de84a10997c30fe4893a59ddca3db6a4b9975effc22f4e2a29573cdd3908a79048d674cb5bc963f5f367499a8259d039d6ad5b0721a5c24f1e410b177a55f6a4f5357b9ce85fe61fdaa8dec06fa776de28963fbc9792131d4bfc804bc661d1a99f164c5777b9311c73be5ed421d4695650985ea34d08e1bbf77ba1113db12195a07f7c63f47ff90ede879ae6da209aa71d5a72248501530dbecd3c9d6976c14beaac76d816f64d963533b984a502a0b27b7d0779da1177e1e951e738b05063e048b1a96cd0687170e23c0cf80a1801b1375646958c1856c71d0dbcfa3df2b5a140d5e87a3e9c260b1d1848dee4e2fcaa3137e7bfb3537d9f624e2d2c1e656d34abfce8b19965ca155737882e441f793aa29dd868ff7df3d4b58362e2c25f2e3f900ac19a00e8462b675927639f4993eb8914e5f57afb8f6c7d363ae85cd2456e82bbed310fb7a1d2f2682d5a374ebcb6d0fa841cd44356de00ff6cf56aed41a17b328d95499f68b8b2bb694ddccaafcc008ec1bb09ef08acfc36a9d8402c55fc15cf11944e02b34c495b807f7e34bb4edaa1ac939584880ac56acfd3d413e8666a2cec7ff38b18c293addee3d595f715538223c528dc0c049a38abba2d014d5eb56d535afb3829404a0c850703b56665d2016737b9cb5e9d3b5d96c3afea8afbda83086087035fa0366c8c207c7912457aec9851b641759a208cc55411a0be1a2d88b61716f85dc7c9cff8643efdc5d7ac31783c36f831f97b153e1e1c661c4920284d40d59810c8074daeefc79f89bea7f1652f9186948eccb6bad4d9b1d8efe01e0151584a24d85d73d1cb936e8a1decccbf03a34eebcfca36cfdba8e3f4331c73d5deb49c2016509a87a7791e086fe7f401b21bb5c70f6a138ddeb2de448fe36c8a33183c4e49cd18c9c2eed7446645a3b3d876ddbb5b8034b0572691a67c2f205469d9c58e37de59baa84936d8509076e8ef1c00e67a411c4278ad3dfa5cccd3f4a9c904733bc885cba4828092fb5c3cba4e178344ef5cc425c55255013d9231346e37ae488e8b1d4f45d19831762d8447e3b2633d4b27d10dfb994ff4e3ae46e829e55ecde69bb6781e929c90552ed421122fd09bcc9b0e60c1dd0a9174a7e11bbcf7cd3c7a13778283b2ead3e4264fda5c5248a883e3d90d7a4c54df8ac6dd70066eb8490b9e3a9bae188e2bb18ad3a08a8091a07f183a75aedb955313eae2f9ba6dc565372be2ecc4c4a3617a6df640bea034a378d9dd15326fb8b111cbc4b9c9fabfc24273ae91b4decfbd6d6699a3e9fabe54638e18a1ef54ddc55ac187f010b51e90d4651a61b1f8c79d0236676e0775acc2f986974143cbeda6e4f084d477f23669cf91af9096313f3dc5d060dc1f3a1510e89164d8300facef233f8d69fdd86f59828ff0f2e475595649e6ac6c80f8c4ae96ac0568e51ed78d8fbf9bae5b46c61dc4a22d3a327d6e7b8eb962753579f401d9b8b8ca9679ada4e53c2f90a1822336c133ef76207ffc9487c8972de3e2a11e55b586cff7792e85d7bf3fd7105613687bb6ed6c77b3e33a9f6f5e5068fe572938d5c2d439f65b9eec93d3516254dcb20eb6ecd449110674068818dded2bd39a1df30c29838520d941b6400f98a8467f2f195f62d07c9b4fa3ab60ccce760fc690e4b25b8e9fc12100412f82f8f293474b436f3860831e3ba9341ec9459c7c9949dfd99c2fba4ddc72238141af5281ec2675da1decbd2f2d01fa7d805d44e0bd248b6cad9d12712107b7b1627b579d473626bdff17d2d2eb9ca3d5784130f3985b45efc77db29000d77ed97e32f80c06a685cee0df20d2e8fddda2c7e2a80fa9b0fca9b3624218e1d540d1295be48a00e5438bd63e5f32ec0fedafb424cb1b12ecc4fa3e8c8eec2a5ab3ff0d555902cbfd5b7285661b14224e4a43ab79a758db5493b5b9ee4c8fa5969b8f3bf38b018ef519e4b998c604d14140fb3ca1b7cdd1e4766760913ad8a2ffc3bb55a2e9918171293328b2e4a9bb2afec4a7cb21144b8eb8b299f9b81e7a956a96057ac98af90986f81510d92e9f67e2c510e34b5b6b439a0ab8bd6fa4721e4e75c871c04a7c3b5b3b41fe9b0c8d6b527e9d233c7c266ea59656dc6045d3ff95a3bae5c953db13534c5d583b250d950d0b63952f35a3e3da84bcb6a85a04691a1425c3c67a9e06acd2e5c8076287cdbe0ee54c87f469a9650a76a92228310fe016bd40508571f2324796e77a13d17de86b3dcd5f372225292eb0b2c7ccc7a85a926f50ebc7ace655d7fe8efa4e86ebe6e256dc090c8582114f4957f97ed7d8c01193c790ddf5a65ee709627d446f02f892fc40f6dcb41cc59db725adbe85b998babd417eccd0241144246871d317ca9da089b76a48053d006a5bdb9ba9aa77a892058000a7c580d8945128e192f0549c01ccdbd2ee65953ad0c96f156d40ca1dbeafa4d872e1d43ef2b58d8b1a1c20e23cf5e98b57c27a9d035e0754ba0a53b69ccab1d166a6fca4bf58a40d2ce0f10", .None}, + {.Sqr, "-70105cc788fb91e3cc7737ed939d5cbf1d6d2064cf2ad265e7ddbd650e4837f745eafa59541316da8290742cfc92c62284a4daeb7c571cab35fab6e4a8dcfd4dd7389d70fd52c02ce24011f895cc0612d4072534bd9e30ffab40b848fa02771f6bf49c3aaef4e7707c947dd82e0db153076212decc2b2fb66d3c401bea6b000c42f7f1170d3d6ac28bcbdb21aebfc3fe12f7c1fdee4c108d1f812729b944cb97c241a04bdf39e9a01c1318db84ea975c3c4a3db73f9bd5b797845dae39277383169e640b4e8b2d8d2e5b26c656e8bd10cbdfb634e8c30fd1442489dbdcf798478130f107b21cf4c75a03f725ac6ad17bbe97acf983e333f9ede8ae5b1dbc1584334507db722103b3d33c38dfe7dfe9c3205e0add843de1c4a115eab64d2e319f77cb7fda0af664b0ade84b93e3c1fd74570da851ba3ebb664024af507b1242186a581979e6c36d1df46edfd999bab09ecd763a3f5ca0d309f64f262a03a3de69ffdaea0e303d2b9d10853e543dfb7541f603c3aaad802286086fcc2870d502298321445861321762255eecd6498724b060a58162aafa02f24207e968d8e17ed2ba730d9ca5b2c8e37ed6cfea7677565dc4c333efd2fcdc0e219712b8641beb249c87525c5b890e5f1d970a05a2d0a67bdff7a6b5c156c45cbcb917845e3d33994f71f4555e5f9f7ec8191b141a02677bf80801ebc6e7a9eb1e88951006b34fe0e55dc2647821c8cf89933cd06ad5f8069f8517e1d7d9d672394fde04335a44b48ef8ac83fee597b13470194854067cf7754be2127564edc8934e755bfea7389b2eda38c8260bac863053d79d9d9d739542daac1153ec6fc4a056bb7e59f9813ebfe93c523f2e8604896c746c827572ef39c1906dcb379b8ef595cf764a968b42d355c3797a57cf3e2c823cc28d658c57cdfbb44007bb07b176c7cfd2c273a93fdddbd4aed6a0c017ff3555f2812c15c54223c9121e671e4d2c70d839a632e1db56314e870ae156a11bf8dcc6694d34d4ee6e835005c6057b576282832d9b8a3b2a73d57b1d801596137e8717eaf282940f1d8ef135a305dac1db7aea4f78bec8c0081d9942d803dd56fbc331eec5354cedc859136fb2018525cd4374844fff093124982f3db1e6a448a4dd28ce1498054c783690542fd43fbdb699d3c3a3a2fb1ab8df304ede0636b3bb86c35f99e2b7017c1945e6e194192ae7ec99c03ed0faf12f0578a297a655fbfb0b97a5478669b51bd93a232b2def4a54520f7a00c04bfea46745354b0cfd45a852c6a1dca475f170b489bdac814b897935aec86ddeb96166ee7080a3e3c85fdf0a8fa731811286d3ae25b6313004418e1e2f4192c1ddd6ebe9b9f6d237a511f1a8859fd473dc08c8a5f61ca34e49d565f1566d1c4b0b6bcf2cbe6463032a0d83b0ed5f281ba6aff86c57a921b2e1aba12f68e51a1150676489d0cfe5da2456f8dddc51a912c44d6f8fea00fecc4fc79f96c0bb368449bc243a5674d16a330b3d0bd080b44073dc5215012e44f6b9f434b64b7c47851a7f1a77ea768c84bb53c74276d1c02e9dad2452d6deb76b0826fa8baad61d212aadc2eaa744ea58fde89141a5ce3186ffe50378ba56f1a085142994263ed224e84a4c97015ed23021cdc0422b81404b3178b5a3cae1cca5f832f98f1448a81363346aaa747619d913a90d664938a75deb23e99a954b13d70d6076a1112bfa9324a9eb7bedb44ea6ca2ece6170bb69e63ec39ed74baaf1873da50dfbcbc1d6c192b95bdb083fe19bdda46fed26c32d22b4bfcd5110383705f01c4ecb4aeb152eb8745f06984f97bed07d6c403fe69c6e6e0eafc474a83f6433cdd2b3fd2cdf8192637ee9201d08206d64dd0b0849141c31138853f4e2803096b4ed53dcb20a80afcd3638ebaaeb1971eb6427f1c1a86dc921e6bd07e172dbefe1aa17acbb579abca2130c8a74053ffbca188bc8dd66b6ca3f38c2e3c4b99ec02a0c961f17f480ac24e7f3c5ff551eaa536206b87343aa9e2d72771af9f573e1a4a76caf851c8d3f3b5fea5951b1fc26a897d8fec421a0186223e56c708c5a7d3a0277921d4544deda537e96dc778845997136be6985c5f8373e902e19a22e57ed0e3840", "9b8ac7e7e4584da88636579a588ec6256883b64f1649adfd6208642cfe63766fdb0d8afe1379093e5daff36a5aecf355a61bc62ce4e36dbe9977b6cd9dc786e07c8dcc71e78c392740ed62d509d67077dc8b25caed38d3451140a6d164b9ec5aa924fe8f4c553f8787e1a0c24a6b6bc709b8cecb9ceb1c862f355f603ce846931e4cc6b30248bf01226c0a44b80b07d5862f6785a4cdf60693672db5dc99c817fca24bdaa70f5a4f793669533f3cb99af37a858149610c0f2d2d750e6716c5f85a4468d044506e3b9526b112f0aa6905c2c668b5f7f4f3e2c62bfed2117c3ceff66d924ec5766aadd593679b4eb1f58152583a0bd41db1eda241f19033798d8d8758fe66b4f0a1f2e52231c5fd6e696090cdf23d9c1e1d8a5a2e6ba69cd66b740b23e8d3a1ded0f09bb673b7420efd388a22929ee78d7f37f289127a56e6719b419aa8e0b70f6fd1d417317d97409e83f0276fed3a5f8ce40c5602ae32df9461df69b02812bf7f26a53afb9cea229f9feab1128b96fc96e1baa36856204b040a3755ef1c514ad278cdfd004bdf36361203a7831c870e0bc85f2ee913c597998a6fcc17789798e66044ed8e679c8e3f341e579331a01de3ae48542ff71f04fa1a4425a1be5e6df000cdf4f710f259aac555ba21ce93b55c129558b577a32e89218f76065ff8d24376c04e1cd6a0811afb014f3deb738e5235a75bb94fbd115bc93b69a7e4b83821ce600e9230497ade9f3d40769f70c03aff88d2adbd23aa51faa01e425323721f9b22a1668aa4bc506e1b7272c9abea66f44ad3dc27da333d096f967ff71ff9637497abbf13dbcf156b349ccfb595366792553a568c964985005109b108272ee752a6bebce419ceadfbc766a4cea98b058bfd24946744ca7731898e97666e9e2d20e96f09b3e99ea3e3272049ea46d04797717b3a1865f28a39c6d8bf64e52efec6d6f6207f5554aba48f7fea6f126f4fe2dd6337c50c8d7a8bc218de1e9031f38520052cfdfcaff5daddd8c6ba3a35a516ad21a113d72d6e0983f3085c1cb370e928858b9f0373e5741224de79ea08f09aff5c1525a995c2645f97395306fbda297c718fc149a5d373c56c1b3342d53de4e412c667190ba8eb7328584ef11ae1ad64b01e40787c8ec761403f913fa740d55e63bf5d05e2079bb5bdd48f2f2b44a3ab2c6c1a64699e8c5216c939d5fd6b30596c262cb5294f44712bc5bb3b855e587f00ff5c25878af2ee4e8c139cc77469cd61ebd7c03ea0241049670d5a3321d63aa15bb9ab024c4b8c4ea1511bdbae9db4475741c8a77736285cc5b0ce2a8e6ed9084f3c1f5c7c4cfb5b27bc9d52da746aadfacc2081354818a54a569f9182c953f29e71c2140e3cd84532075654690d69cc6fc8736d8a3abd2969858edae2a463ab0fffd04b91f91d10da465de3603865c336d92b0efc24036f20153fe6b63cd59d03def40890e7853adc9c524b8b443d1f56c10e707c7f733039163c905e4f3594b47ec21225a693c20962c98460b35c75dcc1ade18fca30008c04b4ae487627754c6c2b6a50cf4a7d8d685d2d10ec2d92a1e7116b434e5ca7fb1f91e3c182783a92803cfe45f6630eeab800ed3b186897e8bca5669342ce70dfafb1e3f5b58af6b22a5e0802b96159f6336bf5aafd5de3eff6c730d8a9e8d4a6f935d5027b5c7e49b4ea299a4223052193a9f8da9db785d0d1a85afdbdf414d3b47164f499300373951568afac60c45640780181c90c9188aa1be424e0a46d06b0f590e89cfb91ee70cbef016730a77a22826ce7d0f5117d7b97af3e48c86b736fb77083a91c5a4ccae79058bf8f79af607f8b2551836eb3382a98793ee20b8d6d664ff733d839673d0acabf3892e91881af24b4ef0339d7bdbd4daa471b93853727069fccef00a40ce6dc3cfa1cf4a4441c19bd10b81ef9d4c91b8b3250d3aeaef69a26a60076c6e0f5e268aaf3be246131c7d6c1bbe6e041a0adff5672fb94aae915eb36fdf39741a6741f672639607da3a91079f6612b92ccd6cf6a3d1a2ab8537596205aaef42527e342e303e8940b6eb7ebda7cee8f771ad94812130fefaf713662937be00c496ff951c464fa8ec7c9d4b34a48928a6f", "310e523a526d4514a0a6ad2de17d4fcecfbfea951954c9c5d859f6553e24627d7cc2793cd692f79947ee829f0e21a8ad37337ba2ea877a0e0ad3e8189ef538cc5bca005ac17931c5145a2c050b8e5841ef500b3bf8881d694edb6dca3c635b46fe3ca853c2b3a1b6144704fa59040de7860d7b99f1e0827559f7ba8e4d431171d59fbba9dc9abe38a47f8d62a1af2309bd6f58734e3cc49ae9380efe52f0804079478c3de5dccfe6c6a7a77057b4d8d0fc40301b4c554c22c8a3f86ee8a0d63ab5fce8a0f5085c29dea968825973287f7e06d3ba75e035c57fbb7eaa5f838321e335971660e426581da091a4f8353535cc150d1df89a794c9e8decef9f367d4c574aedcafa43c6c7d7e034d13a9102874af03f43428848e5e1cdaa9186c2f3dbf365af0320a13523619bcbc6dafbcf7c25e755f1bb6d19d2ddf4c72bc5d27cda514ce97a3253676b9c009babd9bf554389175279700df3f3a92611bd0677ba8909ad440559e238e870bfd904aa912fde3abf10c676943a94265b92fe6b93b7abfcc032bf8cabc19da963d55ae5b58ba9a9136b4c4d7bb6675a90d32bba0c63dfe8bd17f031decc849b17aa4dfa32534dd9a3c3ba904dd7b3a955cc6c6fc8ecb1a2375c919cd4fa39317421e9d87f7fae6c2910f0f9aadfaa8e4d265c94f19ff318fb006c74c7b45a1a8e784fb5343d31acf26e0eedfea3aa14549e9da3f7c5b943893a4167c337ab4cdc19b7b2a9eb090b53d2b99a20e9e9109ba5e4e31708ceab04a26a1dc7a80f2e0ac7b66d8dd0f2dc4ef9e5fa5a1324b434d0563d3ebf96e1eea66d4d97cbd7d430fc172949c6e3655d1447e79acf3df4770fe3ec50cdf187f2bd5d3a857754266bf7bbf7cf9918c4594d6f10b2471fc46cac95bc7fbde93e78bb6e50525cac145164a3df1a57b14b44a62ab6d08f2a2cf2a2bf08b16e0492cebedf9dd394d7b74e0a7b2975639d3a1cc98e380da9e02632bc709ce7d9131e701acd56cf85ef5b23b23ecfc17f2cbb116da29141583e629127fbd7c22c92c17b539c648b7def7f895fa9476e74661962d4749291a8e0206cc6a9438426e13e5d5463913ef04bacd8938c2c39476685d479030aa3f598a9c7aa8758956d8f25878b62806be0bde60f4778542a4733b9a5fb9115dca1b6a032872c66358b3033a4e604497ded677a13c375fa499a9bc6b5ace2deda73ff0717aa2ab00ff95a4680ecf825a8dff1d93cef0a644b994d5e69b4162c0d740b223b32b64187d398eb4d53a8bf26fd4a4756f02198c66a00eb404f7bf888a174abbb90b3287c4c955ad4be7a7ba3ab692383bc4f75687d42d5241883a6617f3362e793fe0dc594f27b46ea3d27d7394e49296df1f2f3de4c8deb51bc38073086a5c74f70627fa9e6949baa49f833fe0977f34175cf7941a705e68e8465d2ff95ffb6b375ef700d888d7a1ea7eeca1f3cec36f4ab33569501f06e87d28a27f4438e446fc9009dbe1aea806c7f33b7a5f2a000311bd7c01ef7e1aa78339fab8e4fabec838c70fbc6dbb17c188e3cba8ee21a518a79375e037dbef51824ad43e28112bdb2c453c4b78a2bd369d90bbb901450e8314331931dccb6a95b3b71cf2da3b5659e75fb8e45b9eba907d79712615caa9614c04b47f18845ce6eebe9aee7d3ece241e9e1573e88c8a299223f6208564d5400676c15dbb70a8e132b3c223ded745d563ac0793493fb8b0aab9eb495d1876f17b36b0ca80df8adb6e45650819e85f60dd3a9d31785e574d56bae90c26ae63456db9e675363a47bc082c4c97e2f0f97003b7304d6de4341eb65eae88cde01dde8285965deead60741be03369569908c33255c13e0f02672650dbdef4ee7606a89921104d6a616391759a96082290058054d39e44a9ef1c8775b0ea4a1e19a5368b05851c5e2495e9f9e1d8861932c6d27cc2966a1e4cb2128680d70480281f984e58955c2a49c809c19fdcc2305e5b81803713ee945657d27651e4c9b625b8312e98537d450d273d9717a3f8611ef34cf3125b90db8caeaad31bf3736f84ba0138a9d7ea77a467bff81def7f3c41f2e250ce75787f3f7a70e1eb9284f995741671d530bd6071ec7bc37ad1e9840a201700776f60c2f2f37f8783a99ea8d2b78b2b0aef036c85bd530ddb3b0066827f56d5ea6271801d1d5cefcaec73fccc49bbc2bd4c87fb8822afab00390918e6964e5b447a8a43554a6f62ac1ed7f50da825b4edc029027461c44b91b9c38ff75a671a65cb7f0293fe2d9cd570ebbf8d2b33bb8f524d5c1c83fa0858d6690da19c8d68fb5efb6fec30d85ec11add766d015a37b6ff6cb3f691de7e4050c130381e7723b2a8db68d9d6d4736f93f9d64f9f37e21a80d652d9ffde1c4c7cde342e61abd53b07e09adf5213b362c600404effb203627a32fdc1ec47f2cd996b9ce9dbbc7ea74c63e6a54df2a8de81f1ad24da0b79626fa280e81bd42ac6edae700c25218bf7788574d47038e0e19f12d6f6ad5174453872209c8f3f3cb950144fb7ffe957a8424760703a4feb0d1435491be49f9e5aa5142ecf8730245983fc56a08f1c26ff9e84fafce7b45a12be4f9621abf994eebf8ca8b141d7c3433415cbbc6fbac2a54726df9b4efa8d14b74d374461c5547216feeadc6f591dd72761c5deda840d8e8207c9eebb71ce4d4014e3dcfa1fc4396458ae3185a6cd946b6a2011ca73db7f59fc6b09bbe8ecd1d776c46f2deb0096a26665428c639aa4d098ff6e7b70f7ca9c3c5d29def1d2c619746d5ee9e9f67252cee0294348a8a0b8f05e3e32c97ba3bf17ac286a986a4fc0e36bacb398a2925a15fc77b0d5150822dccb29f0d83f0be7c9336bd9402a440136ba40e9252897f30b1e9562dc92c91b051c5c3a61e70fdd0db08a8e2e1c3c773144f53b2c007d9186cbc39b1f3f3e3aafd3dec6f8719a0de35d4ae01706d9c955059e4b02128ee710b83a21afe4c31dde70d2060e4db707754a55c8345d7778342b2e43cdefb39eb3367d36b9439fd29c3f41533e357f518ec28f5e1051aa8a5d42d1cc02c2c169da813b5bff607ae04056d292711a5e0ae1429e0f9aa165c997369185c6571cb2d7976ecb6fd5338c0f546718c82870745904b0c93b964d8a8c8026c4be8b168440844dec137ceaa7f7960130cecd26b9e3218b194742a2c5215e6fbffcf75abbf164a88f682d2089e7661c7a0fbd56065e047d7a82459831225daa3f9cbe5f722a43a267ba38b6791e4385ecf2dbfacccdaf9b497b5fc3b6692644643dc4f2be2dd7c96143e8623ee573c49122f9ec6bcf5c3b8e6881f5ab547136840ad3e31617c7c7f04cf03b8083da102f07c7bcc7c52da799e1358b1758871610b6f0bcdf4fed51b719326ccb34ef9beb06ce5bd7eb705986ce99be1d0d3ecac24f4d44680078d79d5728201d0efd443464d5615e3353aecdc8d740509a66b45e9b1608d5bbb2beaeaefdeefd046582806ef00207f7a8bfaa6a1004bc8174f9e2efe40688692ff3d92619330afff889bcb35b80bd0c3d87cc494e6596dc7dfba875c7d5de9fa2b344bee4d3e608ddb3bdefa5039b511fb2d315d4e09b0410ddee0d367dd99b62d6ba0388551655612781292a6edfbbe41302ab1bc5e16535db0a93f5b55f4945d663b5b756cc3ce2f62d693740e99530ab20faf4958eca830ff1aeb2849eb241d3b5c970e7388b5af9d2236284a6f3cd77c38873508b7e49961cc58d93f06074885b45655554ce354e45602f1872dd2400273badc08d549833501d8e7f535d8e57cb2ae8f3b34c9d08003be6c60fafd7e0533a61edb3cb1dd2f41e530dbba9113daab8387096a0e5a7734515e6dcbe1e0197e30e91e12d83fe309b3907ee4eeab1d7997bbf30821eeb716e14a7fa7e716d1fcc34bd3cc47bbaa1d41b494957c5e29f31f6dbd15e1e0ca3b92f15336f8f0b1f689cd8e35e2447e22d41efca1c881494182a5f8a6fbf555f60fae8b127eff58d5c81e09a5c078098b62821275bf21fb44c1e81c5a6af864f1a1955b54816919bf978248bffb76d1a3052f046d423821dc578ff15d65bf41ebb5f8e3531b071cdf0a7760aec3d3231b48774669f76ce9bc9d444b6c8e2cfdcbf713e09aa387e42c36fd50660f11f5ad307cf59109227f8f969aeca1be9b94f9e8e45a5f3f767f7ea88bbdfa3e495a2d159288a83fb9ce4ce0aa016c368b3e0cc68d50bcc8f4ac2a655b8d4196ba080f1123cb5cbb5fc8649070b35c1000", .None}, + {.Sqr, "-679164dff75203f842ee4abcd9f0fcf13b72f5bca4e013961c042db3a97f83fef79e15c49547258af7bed6e7511d5100000e5f80835769b05c11a214b40846b1896482db71edc7b2f26ee42c8df9bb5a511547ba3e7ee177e99fbfd6ea5d6825b3733047296741758ba974341059d501f26f4ecfd0dfe1bed9304d32dc8e699e5f8a952223c22d1c269654f88a4c31ec2c78d4aed908d884e109db3b4e78cbc0ca779384ae0ce4d49d8ab9c95fd00c6bffdb8c8e2c0b7472f1a355fd1963462de9c80325e8a9a07d8d901851a1fae13876d53998e13a68cde41caf1ffb8131f3b9b03dc290cffc1cb2ca0f0634b9ffea2072eb56b390c5a884cbf3caba1b18bfab58720cb93cadc869414c3b49b86ec7f57fdc2e2218fe2bca251ccc7416f2c4e2215c995ad02bff886abc6b6586a6acaf1e0f31a45388b525029cf3a188087f4ce4940c250ae0ea0575520c014102ac491c346a537f4ea68512e3d41262cc73c84f065bb6e4ad6b66c3ed0208ed0d05ca8220eaee9b3f4a6bcc32dd0a9bad431f84ea262018272c56360ebfa5532ad25bd1c38fef6bfe50039902e2df5f6d4d2c419dd85238dda2238f7f72fedff7aa93d3388c1f3f85ddd22c87c95ac03995ddb03dfd472b2f921e505baaf5ec89adc2ab0a05e80c8523b65192710bea0634724b9971996118fddac57eae788c6c306ac04c81ed05d0e98d94e36838ef1d3ea9787a106e77dc8256fe7c3775c4c1ac2cc932e7d789caea9a5b902072ea6df9fea1071b704e9e1ec25e9177b79a7915f1aedab32fa91095b9338266e1a06e59d3a4be91aec9e577f9f16ac09a9fae1819cf2fbef76c618fb0b0f6f696ea9faba80eccd8cbb0f78c94cc9b30670ad9e59e85ce621b1ce35f4b1a34a650fa8bf43df1c3acf05fc730ad3de43fd60fa7bdce1211eaaf7cbba64e8af979038bbeeba67cfd79d58b503493e9a402ccc036b46498c14df462540c25c3e16c1242873605dbd9f461434a3f4eb5279cc7a819b05c3f4ceae161b8200a745400ff1cf77f6e68b8de411af4f47ab300310ae825c5ae05d069bf1e7649a827a7a0e5237af69a9053aac1c0d68ea59fc8b03878ea88e155b7bf5bbd01175edfc4f4600ea77b8a33843a90050656888325239c6d9d364207bdd9aec3f1cf53e759ed81fd9981620976ab04ea8633b3540e4211e421a9c7fe575c099de4f21ae386da66d7473a82950c5528b2ecb0f067a254081eda02c8b0686ba8b9526c7a4e909770a8dc30f3c43f60cb0f4643cd6efd0ce0bbc2aed92ec09c5b8e1db1fb46cba26a42ecc5e66bad6a93670c5349e1ffd61563c3d0e0065a19d219c2384ad728e261d0e4eb94bbfea6624f00da2b6f75217e4d3b8fab7ab05b21954877a2c208a91104053ca685f0cbe44204a4b906ac281a59c7706fe30c754803095f49cc3a314552e0e29f616280f5483938aece61c29c60ab438d55a949fdc69399afa84a724da62944163d97b310580e7263db7b3112fbef52ccf6513d5509a66097e1254c90c304f9953c1fb19b47b4f32e46938cebf3d9fea5d1ae251ab88c7b3d3217ea519d3fa7865ef0580a643e470db7e2e3366c93d8da670cf8776d9427ee867aa5baa60e5c208ce0efcb1093acc32e6dfd3105e39367d5cca3d2184d1a75f288ad1b2acdec3523b8f467b787fc04b15621536d979969b9cf84e1ab82064b3ad1619023304bbe366ad9dcaa476ba04fc7dea09c22dca7c35416ee23a1ba360d402511e000abebf1b5940255a624be0dde0c5ef03eb0ca961f0eb7b87dfd11f0063a53df64004ea1b42d705bae9eee561d8999dabef0972d6782891ca57f0ba031e9e11b5f0d6b3121205009db11a51d6226fa27d613cc158236e2a6c22cad869840c86aef3b18c9a276b95a1f04a3cab492229cdb0cc1c70278393c3efc9a8947313846a148c7e84031006c894234d98fea22ba337623292183df92382f2ee1ad209c28a14aebedc33e0867d9cba49d9d263ed305c6278c0a7779bf60389185333e5577450b213b18b17f9b91eec98d54f73c67ce9190f7556e1c4f8d4a7c724ce66c99f689d06eb03159a331812c8fb15ac85cf9aeaff358106f91ab732c800369", "1983f67427a28bf59db0a4eeb855a0b95fc4057d099962bfe7d56e54971ab4312e7cb1385acaf98352936f7676661787c9f0d751606d0c122c3d51b438da52611d8909b06211b5d1babe1caefe851abe9f6e004f25cf8c5c89721bdb9e0e9434eeee6b7ea568b2d1d7d77ea56636ee32c5440a88f793087a5694affdf71d61d5324103640c61e9b55e1d83c820f4568fbdd3925679c54c3ba13937c1e63d2f400375a55ef7af7cb33caaa7ec28e5d3879a0411ea640f2c79a55295daf08ea78f084491eebbe72cbbd4bd18a220585c99a3cd0ad5c9e0a4494d8b1cc05cc104b2e18532372314ef5808d64e57e2613042b13df7cbba1497a9f15359d111eee1ad0bb5f8552a53175421b03a1218dedd81221478ef222a9a3b75d2632d09bb05a7ad85089b85a93cd5249afff4a058836d16612c6c04cbf29cd1cd1a5ff417193522e5c7e286a48dce518f22721aa8794f286b570728b7c7812cfbf369bed7ed14fd6a6c3d631c28194b945a110eae4e0c5a24bb90fab45d3079f761376452fec552d19952a56f20be8918dc11f6cc5e2602c7b75b8b53fc050ada1601c66e8482f076a1376bdddbe4c04d333bbbd6ef4c819c2063646edb663636cfa150b502f3f2c4b4fc97695de31a65c915b09047498c56ab9df3676a745a0bf77757cc49e4efdb517e51bca9696e079a21acf63a0bd01ef7eb692e24d64ebd0ba96bc3030cb0ec5b89052e848ba2c67a7dc11048598dc04598f16f17a5199495748f64b591c657f1ce1117aa28e2fa61d6430bc11e8f865a48f2341d1c931c9046abce5e67e1662960e515d2875affc62bb5048aa96cc05878e584898c0d567fa2632d6d4f4c381566f1035bc4c04cf1ef3473c354c1e103b607cc32abd2053fa4ecb1335d9004307479605b2687950374985890e13d5a4db2fb86d7d5941337ebafe03cfb1815757149fac9a5a282073dd3250c4bcfbd1920bfa739d5920e6584b434f14bfe64c6a40e73021ccbf77ca4fe629b7a4d5797f35e3e758f5db15aec4476c99b6bff858cb47ddaa9f42fc8456e3e1a9ff6be7ad35a6099778cdffbff872f739811667568e6a611e890bb105f87c901770fe3abec5e3d7d46621c7d651c832a5c183f233a699d40d7cb00cde48900f72cd3523b29540ee0e426449f28ecdf887224bcaaaeec2551a179945c3a3825e84ae57c0d7cf2617e1bb16e08af5dea7dcf17a8ca4b826a32c03599fc1334df73d6c9026f69c0ac010c0d718d52abc3b811ce612c8ff1e3b8aba18d315e37ae1be2b4a5db62cfd8895ab6f3f514e8f11d2b626cb3866c7e8fd0fb895335c0c5cbaa1d8abc7e0367a766a01afdb3e05f6ee1fb4097ae2a76f8f9922f69c67568b2c1de948844f84f79ec78eea6c7f62df84a9ba1306e018b3ae835b431e1ca43255a8ac89231c79d2268bc96b0ce26ee105ece0591270ea9c9101a975f1767d0ecacc83f94385aa0ee3fa32c7c72f0b42c310476e0fbdec9f40e2535f05b98dbb33fc6058f889e12b176f57a86e772aa01ffe5a50ee9873ca93a4952a8310e61c5364015a5273faff6ba5ae80b121618c2d12aaafc4b42a17dda2201901712d29072b39ca49511765f9d68a19abb00420ee3eef0795d426aa7783763c57a93008d02ca1484006c6eabc957a00b1fafec2c1c9331d5df62fb5d35216865f0828dccc1ae627a11fb6b0106f21cf0749f5257625244f4db98cb3bbcb71800b17e340e1007b5c37e738e572b934fed51d1eb4215d6496ab077cbf5c034c8512c2ddb5ea7474e5efbb839c12cb9a235105145152eb6f31e4dd672c55aeb820973c20816307afa84ce23a51a19e4abe5196752993a3e7b3fc2bfe6b89089cc0c5cacce6597786d1510c923c39d000371b527856e76857ddfd9999f3dd5d56eef2a43c5586b8e0a6a7e2d3126c345daac13620f054ffb578eeaa8fd149b1a62097ad8c06941db0974ee7edf3239df7a8c939fe35701ed19a50501820f7586538405d8d9913e8e78414a473c605c18e392e6f7fb0a590bb439eabbd069321bc89c2af8b257aea0d28fc15ef23a797b291a92a40e63c9ea869431407b996deb3ae59ba853a2342e2fa5c1d9c36e099e34d4b7", "29e651bfa679e7432803ced3031b0504410c9a857013738174b2466f7f7058175df75abe67ddee4fafabaaed846af7139de291b31bb4804a11528cae5e01dbbef4cc00477e6a55f4237c2c0234fcbb501d076d16f71aa87613d964ed9f628e0ba186cf97feaed6047b9ed0ec617b715f9d99338e6854b376ba92747bd80deb39d9a3bc2ceb79bcf7212d5d0ebbf125ecf66f43ed61d59e32820e7c6b341dad6facf0c0a74ac640bc55634eb2a3bdbfde718fe311d6dd5c5dabd8b7bcc63f2a3714464a617e0d25243fa4bfa024e903b0e2dcaabec3ffa9ea1b9452a45a81245fe08a4d738046d58b637452c76891f2deed746c42354ace6777b13a07687982e26742882771f2dd988679c88d7c39ef2a46696213938a2e20cd4e446040be2fed61df49e0d215ee0887de3f56603fad6c221907cd3afa3fe5f4644251e3fd88fa3622a34585f138345a0dd5a587386b6106275cee5a4d2ef77885dc29cf19adb601b6adf5eecfc2f74544eaef23f484395aca816521796ce1a7ba369a998ea6b236eb1348c309d2ff69b277e1f97d82c713e1fcdd104738265bfff2368bff1084859cf7b17f0a8321add20b0b3e952392b8a8f6789dc5571565b916749560289ef94f9a5e3294ede4590152e2f632a2ea9313f3afa3ab35b731e08a096c6585d570be150c117a062e52a7e1c19e5d1f0b38c93dd51fdb8165b141bd0aae09ed2bd8e8343b205f1681ccef53b77bae473c7740647e597ff56e57c03a101d367778259cde8bf5588b5381d2db06c3bc27410e1ad353786de55974ad1b23d1ba760393665d83739e0789f55d1fa67ec5968307661ff0c0fdd34ffdf8118f5eab4101ea9a3cb04193a7f738c11ecf1b296c17dd1aeee348e5c48929c0371f83fd258644978170877c23da4ab89b140b2f7c4f5d84b260489966496f82c475cbda06deb1ccfe9fd0de5e0caa3fda0bea199d3288c33dbfd1de8b7979290d9ce4671c7ce21a403c05022604079cdb24922d1025c49ffba8932cc203833307fa9b1d2537d411423515840675bbc904fa2d88c9d53ae46dbc00da90b8c67ca07d5e282b6736f5be36b39f0e7aba9d830cc68297fff3f4132601d3e6296862a8b81f436d8086a8120eb164eb074d50abb7ed8a84792ee3372370219f46da795b9f49cd50824869ac363464b03ee16e55f4f24248dfccce9a33e08f5925122d3aa51073a5246d88232ec84297fabc87d1fb7d402b894bc9ebee11bbd460f4871e7aaf64ee87f23c82ba3296e2c0cd645dbffc1897e925616a8ee975835e7115877701d9ae68f98e803450f1f48f86e5310ad18daecf10206de0abec74504ac0e4146cf15d5abc8beff026d09644777655165424444a2f186619142c3853f2637d73a3d9e8c1229aca01dbf3cab083e9535957daebeca1a1947b7bf16635376fb4871a4ca38ac302f148d88bd26514c1648fb0bb6ac7921eb83266de676058a463bd447785d8030bbbad5646222a5a21292b7d60cc60fbea81efb655934c737bba5b3280fded829f95a708f168218e1021476dc57f1e7c563c333a6f919a1e76c9eeb739adff1c42e9a719899f22d6e0488285a54cd5347170a5bd97d11a7a62cb404e52bca1365af04a073456c511e60ada27ca76b57d662ed458993e13dee02e6c14ca98c8281c1155612a0bda05afec4f289273bacd4e914886bbf8986fe14f92e7ba9450a4cf20a6356c799072ca77c42e702abe869992d62d84d865215249e4239cd5609e5cfec0cd0a089ffdf6b26f1375be80aca6e71a312ad710e3d2b0dac84955fc3d72e1e5c338d495d53880f5d9f40b9a9cce788875c22988bd45032b7dbf12740119a59083a3b162eca2b84a5d5e8b3e0c6af4c14040e48a558299d23fd0c5d7c2ef5cf4a6ad41d5ce542cfb4f0c9962bb29cda145ec2364d0d08423b394cbb5819d2caa4dbdbf3b8a462da1c5016e233450c5811364998df9f364d6381938987f60c440c2876425c3b39eb302adeaa60ee65a66305653549a0313abd2eb63731c526e333a4745c5968f6e4bd542a313e7c45048d0b9b7f02fa25843d8926452486f7e0ac542b20d3f8d58123bd6553bdfb0c6b2a9b01d0c090af97bfdd547e852d28923cd0ffdb1114ad03b32316e1e0d990a64b9b2a1b5a17c9777568378e324520d2b5dbd449e6eec08a780114bb1993e06364f2326d1debde7af9c3fb72ea45e2d423b6096dfcc4e32340376a296985e19d29a00eddf193158359c6acac7ef2864d9623a25593d1241eaecc88f7ebda057b0615c89e4cf4f11b87436d17a4301e19912d15d43bf8fab055d63f222eec0f248c6cffd430949b7b4f94462e2d912724665c2a621fe777e298832f6d647d4323267dacf3cce1bfe6946ee55e49834acf247eac01fbbabbc7abd417d079694aa029d8cec9e3d756266225232477a23ab9e0cbbe7e85ede86174db2dd29c174ad52feac572350053ca61d9a8a428ff1ec9611d3d9f7f61c27e7e42f5df369b85338df149f5134d116bb451191ae937b2d448c0c786ae9004224c184b94a1ad01c614adacd5cdc3bdd7c8ddc213c179b3c908424793ba9aedf1563e7bc6ef801d755b06663de0f2a0d53265b7f4d5effaddae7b2559c0f64163a473a73efafb70734004ea12d1ca3e0448b6ff5016153bc469a59b21c0a8a8701872c598819fd65a37d1109bfd98638be170cc6466d2a32fcf59c9bcf4a9b3bf573d703436b29c77ed28e7a36f324bc459821f3dff7181a543312b43d074972a836c0bcaacadf84c8b0a0d0abb515000a4bb15d5efdede55f914401e701e78c59a60d1bdd1819e9644b836958e090002bddb37e44fda29fbc4b0249ab14c60393dd5156c22fa98a70959856c0def059ad4cc0ffe40d9229c1e482ecdc95364068c0c2e4749a563d0e12df7ac9599a62b54288e50ac585fad842e6df18cfc48eb7d7d2ed335a35dce48eeefacdd4f3f8f6e5f355d340897f03c2becc50f01c9502be09df6139bd7a59cff852495fe2aa502b3c16912c3358e9629a09c8025d12ef15c2aba894f0bfb50c5381a8e75384205ef89c5e1bbebf5bc4e032d49552a533f903497b60a001f0c264f8bda41a3217f24353057bae0dbb9785c6f28e3dfce5516b7d05d1e04bd2576896711c10c78d2d16b130d195ecee141148e38577e992eccf62685e6e83027b265c2e4d81552044ffeae3eeeb485e4490f32086c255a21ed57b31720a1cc7975b7066442672abd3fc18e3f4d514089e7818c3af525a648c4439d270de359c031d9873a9081e77c20ea4416551a845d5e1842f6287d5d5b71b660da5bfe5feb5676497f8d1032b93ac590b3b0cfbb09e59635f181c0d4051fae0f5dcba936d112f810e586662e5967fea87af2aaea0903e2a629b6719aeaaef0df1a5748b3bb297e71c698aac56db4d50e1d8891a75e386a8dfd960b6fdff697e9da1817dd3ceb5f19e2ee84a55cd288323c40f09d27e15eaa81361353993e4ae792de8e6d1bd0eeb55515d10918458b8a740a680a516614a035914a52597e21d02e7474ba10b602a7e46601c8223662b3983b02abd4ace2d4a3c9da141a8a036df0f0bd2d119a38452aea9a07dec43ff528cc246e85b3e6c807c30bd8682513a4cfe4d51d06cd38d8897e7002c55cb6fd1394129bb1ee75ffadac1cbab14d2012243c177394894345bb51437425721b94a090e04be5f11cf1e63b77ffd89c70043cc9b5f82733f9827aa98a38df810aa314bd38653324cbe3944233e175a8a458090e27613a8d14ce9d036611c41fc1e718e04b4fce2088205778a2fb73210055cc035eb3c3070ae173b55165ff0e7823270a53c00ba67cef4c8331412908154a38269181cc9a2df89067828c95f81a25c2e54f86a7d6b91256ba56bbc53d9ec59f3049eb97c7a43ce2a550fbbb6b8405b65216bc479f8a2934bb5a390023136042934c0b214e4c7cf3cdbe0e2b1a6f3d58c18b22193c69eb4fa648f7879b422a417965d6632db42eaaf12a44b451f549149d1184fda5eabc5aad6020e22fff562c1e12b04c81c64d545793bfa3138ba6adebc9adc076707f14a4d56426c73d4803f4c635eb4e463bdb2f2ab668e9253c18b016786dd9bbc034f902ca481a586a9a0175ea7c3dc55afdd0679885825dc80bd9d4a1634f2374cb580977461388ded159f450a511baa54ee6edb5cd59194303aaf403535eafb014450a6fb25911a5cf23f9785810ba111", .None}, + {.Log, "3be88a1fcb510843cfed84621b7f2dc86ab66de99b3c988ab7f6200c07fec4f6075a975925f23161d5eca8d61778a9730e45190af0e60acbd06736fb2df0973d1f8b39b4e52d09e85d30328598ea6be5792037e8c2f773e0deecad053ef2ba1a68a5e33040e937cafb5cba4e71d2a30d085a1f7b25927348dab35a5f6592ea2bbcdf1075112763673032f0fbf419fc9d6387f810c1f2714cfbb10205045db037eba935d39f6144fbdd0ba9f10cdaedb8352165f69f594c768276de7b79ce6d313089201677c9c019d77db9067ed62bf157bf7f36f273ace081ab3389903d04369dff7ef51a208177d9a6e0100c5a8fdc70c8cbc988a37be8cba504f38588dff401d67924b833a681ff6f6fea56fb78dfbae8b9dce733a8b94df38b91af7cc298381ee78a60462c0b05e311441fc72af86918202967848720e1b13c3fd1e0e7bb55fcbef4ad058f6d32f176e0f751001e1403d9d2579860f4e38d8b5409e68637c49a2f3424126679cdcd5d9cafbc20dbb2e1f2c679628f2c43ceb405f329e67bb90c4de19340d5e9888b3acfe912fdd45bdf99a54def1837d896618ee32a8eecd5e9cbf49809a22cd0d7d801543c96ec4bc5102f716f639e0afe7bcfd60c43110ee429060f27ae14577c6f0f970eb0d39440ee953fb404ef222331233c8ddaf70a65cff0786671cf02b4f124168fdde6e9050fb7c43456533df98499e5a6ed26bf523622c3bee82959d113b208513d2eb6129dabf6406788420219d90a98e1fb79a4f3718431f8937df9da3936317e3ecddb0f336eff952981a386b82407b9cc86ed82d7e5c823e79e4bc1f2c194596e3c8f31a4b24f8dfc67a77023867f33a6281a00a374b0b036f34580d1d98719f54426834764988e0a5200ef15146d9d1a890025204de984fe507711662e2b9e83b68b245e2b72a592cfb0be7632e626ce9fd2fc663102647b4612c92eba4839e5403e70357ec32ecf2ded89b09f912f021c8e657df8b9c0d7a8a891c0298b97e8640838bdd5664de0459c4ac2bb4f98b1420e120a51c83e6594ccfe6b03af064a7515ef0670d6900fd70110cafd341adf402648df4d9018d8b9b4d787d038890dd75593855c8af5c02baae0e00f7dd4b3f9a7d6fe05f733df5fa2c4ad23609e297f933949ba3f50eee039dcd4e42a227a403c58de0d7784cb907bb358c3775223228257c1ce89fc228441fcdb0cd389bd512555772bb51afd22ebd5fd248926525777aef5aa0d40055f9f978e4bc18a5fd1f62d45c89d12e25ff32a2e40597563be72604fe453b818c272f9b535dac182b7b5e955d59d530750ae06d4a210eb82b4b98633ffddac1f7790be1c175953b4fa967b61bcaa01dc4d193a6d99c70dd079b7c20cce4bff68b580c819921bee675ffb2e5b822a83b4180f5009e8683d3404f6fb6ec87ea85f896bc953f97df424129a91ec65b49aa62a771a1a6912aac1e9ab8c2ac7662526552e02bd92cf7ef6b572ee8cb4f9dd56d7f4d01bc4fcc6ca8723c15b3a7e129b3ded0aac0489114ada4f3eb08e53a7fda2dbd9c75058c593bc6dd61e6196ce3c4e4798fee00d0e40639553b972ab38b06785c5d72500468a3ec5ce36ed4740f793e7e82cf8c49ebd702fa5b4d7f12fe1121a4e13facf155cf4dd4955b9b4660f4a4b1c92e2c301a9816aaf98c074f09fde86aa9596e01891dd6f7325dd4dad7c4bbc02acf5091b68f4b61b6e2949d9a8fc20c065e79b1dfe5b4ed383090ecb6708482a8e4b36c0b09b5eda21113e6e995acb2a6213b4e963cb81b1c0b849e4d06b582984538b02ef2918f38d17bf4df892fb5c72513976b6e1d9b1f0c796b01b630ef6a2e885747367c6ef7583db36f12f2df336b04fab01899c22588eb2416c02f05212cd4dcfc0ff46b0354c0fe1177d7290c2203276589c02b78548ec509678e8b65670de116905d0f8ac00e81ad9309462984ba4eaee65287947cea09b0132f028c1ca48b10fc92ee5dfc27dee013abaf3d272bcdf245446585290947d7bd01dafca7769229bf888461ba95ccac20678322f97565de14bc12000e0fdeaca0baca0c9b1fb24576c597658645c1c70a54928dea29e7cca195520ceaad7408edff02eae", "dc37f228d28812c", "c8", .None}, + {.Log, "4ea4b13914425df2593d88b39f01e8fb749688fffa33c7c6ce12c5194369fa23758ee6a6b88c6ef4862437e752b1a1dc6d1a0f0e32493552089a2df4834b31bf46e2b3a22ccf0d4054daf2ee1669e6b02bb8eb22ac2d59020ef33dd207169b4f5121edf94078a76be1c05de836ec9ecff668f397e2565941d418dc57bd4f90344cb79e89466923964a8744b6490432ebe52e7c3653fe5755ee2a96a76f6962cc08d4bfdbf8ef1939a07205889bd186fac39aa2d91084ee42597b70e9fffff59dac9c373b0bc338e9f25aff97d2133c5a21211dcd4c5dc3d49623b1fd166aaba22bd8a7cdc88ed620d0865b1e0906d262eb37c27feb458980ada733f27deb2f7791ef84de44acdb7947a8f0d617f2e3083f17239cf3bac29e64f7a22183ac5250a5a019d6ee1f92a9a1c028aa6ff4a9bb5de46381000751533f666a345b7a0e67e8f563d37b8a4d90dd09f3668b94ef4bfde91349965ec472e8e525bf9203dfbde6a14204caf9132da9e6bd8d1c9dbe4285ff89c7070eeec22c2e755bdedf8586efad49b26f18124775315e61224cddc550f22815b307f13cc05c86d68053fcbedcbabeeb02eab148579e886df93ffe53e87db1b8ffdd86e9f910e5f32495195f6d72987369f346377eeebea391401492bfaf162d10e92e3de4809a22aead02fe190bd054a0c6565ee5a5e9f8cb290fbe22e69838b973a2d30e7ef7873974b285ef8880d9d03fc80b1cd60be54bd537b00ac6fa5e8058007fbb46f4ed42952141748d91084192f216824bf03a5cea8fbe5d87dac24cf8e64cb148765dfdeda41993802a58fb668827babe0981e7625c12c786db95e5dcf5fe34f53c8bd0d1881907257d1992526410e68d29c08b0b3bf1dc02f00e01dac03461ac29f65e897bc90cd6b307bd2ea6004c5821bca01e4486cbce3359d9def8eb8d0270f1b9a9487fb64aa5432950bf496ccd39e5ff2a94e7ead864f56d93087884423786479f1655138acdff4c75881c301bc015e610456f9a5456d70e4e4e5b81f4304307dcdb99a579549827fc227b5fa090bd3a7c9edfc2f41e6945fe92a7ba5b53e26f0bb7cb638c2439c2f5de6f9d3b8f3e2bbc55e922f84a9c9b00f264d0c8f1c4e2d2459cba4ee72f186d0348ac347a17a382c93accd1df064e9a76cc8b02210a589afb0788bca46a21f73df86a5545b4be87daea0a4617d20cca4ea41eee059c50c387f270cdae6b3a7989a7c414b865b4cf83ba1b37d5fa88dfcd2a234aa078262c4779ae390eacb4a4890b7699a61023d2dad88fab34ef5998f7dfd39e01a2f8fa39dbd51246d3ed6bae0252608da86764933bcde41e2dad73ad8ac6004dd725bd44870d300823e38e44561e31ca6e8fff254b1f75ecd29fbeee60336e2bfe315608e79127a1afd16a52d3fb0911de67691c7a2b746e188527a8031d4e71ca9dbe0799124a24df00717d062bef314ea5d01d3285bb691ce91bb37d11ab4e90dbeea5bf13d8f29b0387818a1627940cf8dfe1dceb19f35142d77aa14a6af8af02b5c6e61c63e499ee7d1c92e2d373cf378683f5208dbd5384e245c7be64c4694f295b4ba1599fcec69f168ecaa8f3919e807d3e94c4947e39c23f4afcc90b171ac296842160959087e4c6cb3c778ca74b062752912724a5bd33ec3f60e2f77dcb1ba9ba69c04c697e89b3b99dfbaf1da6acfd649996e21da9ab147d16852db5ff06aead89d0e099dbec6849758ef298de3cb0f7b804d37db5f4fe7683465baa1886933b15e2536ea4da945f56ecd2533f45f39d21c873d3d645802bf36f475df3d60e5b9c9583487fb9fff1e110884f3daa9173a395f2e578e7aa90efd2b3be0327786638b0486ebe61859d9291aacd2c3a2f9a387f5f85e94454dfe07cbc0ab63db5779cb09d873b432321929a1624dc5cee9e953780dab67385124c3f777dc947bd90cc6f01127c58092ee66310ef077153a47f034447714c3e6403afb701e0e9938323c3ad2140d249f8e4fca7ec1be63612cf2ee4c12da02e49a59804452676e529f9ef1de5f549589680d299f8c4486502881099ec3bf27516874451bba79b584911f805fa763de5d328fce2ef6094a8b0707e5d9dcf4563bced93f69a", "b080f1bfd6f66cd", "c9", .None}, + {.Log, "c42463e04cfcd0c2eab2718af58e956f78ca322c180f54a4ad2c13f5d2f853b30d8294aef38a3b7338365684c5b3906a7a279a06bc5e602bc14bc2a6f7236c76601ff182d8c217c9eb7eef047e0a3ccc08933a67612f11a7f2323d2499c27d9f057eb610413697ae8eca03f841ef7c5fae296360208f4c5b96d9df9c5c91e436fab65cf2f68ee88d6d3135a4a8671c3688cd8358baa550eb6d084b082e491f110e876ee1d867b58890d330b72f383f8fed232165acd484ba24c914d2fe9b8634fe353a84a537adf41c6df79c31feae83564ebf6f5b31d01fa01ef703bec80c530158ff9af7b4ab502fa4f1a63118e87c0cbbb3e6fd5965ff4aac68d271bd177631a5392043fd87cb7acec8098462d941d20af106e159ce7ef9bb4496115bd0f457d1a64a01ec0026c1ab5fe58190455ee446807738dcc840d1b824275cc18187dbcda98596476a52905affdba06ca586805ac5da8762cb0273203c57e21f309fbf3ca57221e32b420739c455720c40cc49baa8b216022e12fab21360e414e02a537417cb770482241247d6c06df9be4998ebf8794e433cafd34088980ce92974bb31a5b377881965edfbd65bd19f29ac0b4183ee3c7611d2c40b1edc422857574f260c20d6c0364249cfb85a49d9ba00c6cd6e54131e0422448d0bbd9405cdabe2dac40a0ffcbe4df4e54b8405bdf66ab90263b660718bde6234bec62b16a4f3d08d3420e1f45bab1a90cbc52da4b98baa9c0ba17345d0efb6cad8f4b9b5964bfe2b707eef285923b62a7cc29d58f606a9b20cb9718f7f414b2cef041bf0cbc4804d04e73d3e318811272a1f16f884f9fc77773598021c5264a24358121d9343f36e6c6031041d7c618c588f7ebf9ea241a4837081155cf6824b1dc3508af1c62d7baf73dc356f86027064415c3836b33415bc0f9eaeee40c4ae7b3f5ce58e17c7b6446af4ce254efdf10f0fb50df4248c36d882886cfc366c656cc6d2f57b5bbfa583479cc84a388b446f4c1196af42d63f5cb96ec55b3ef2f1952f0fe3520506af517dfdd1ec814ee79278de79e84e3da1497a6afe35fb9cb7bbd4578b7a41558cc75b30bfb260877ff0f3b14f6666b172da00d5920828aa028a47d1893fa1f32412f7b83d933a29ccee356ba972e6c896da0312c39229c111ec4c50fed9e63d231759501c4eade87dc63a22a309af60bf46bbc4edd33c2545891f1f6928c8da5559098e34162b6f4eee00f2350eebb148b437b3048e5c860e4cb8dbb9b6ba9cf4d743e8ad30a4a8ac9ffd2c01df8b57aec6df19693e3b5672e0b82d11c37c5d9c197cbbbe112d4523c4f443cb613544270f7158b9e1a93a7f01183f6b1741d025371b1736c6aa6fb15e7f2e1923cf3d14fa6567558b6ff29c4afb323d5f2e1768ac3a0ff1f9aaae4e2afd51db0faf337a020b0e6de928050768f2db7ac1f0224e9351e4fb7718e0c74ed8ded61dce532d6104ea353a3fb7477026f44f5cf8b3a0d9609ce4cb45b310c5d9d4020a2b3e159b0611c23fce7b6b395018535f7c5de4548c19bdeac2a6f83f7c2ca399d8835cc7dca47ba6354ec128a4dca5ad3cb0e00a943c7dce10e17f9ae32bc1f89866aaddbbe1099784103b701b81bbd8872eee2f8c0cc8c4c76a1e7d013d1b4c318642aff56e1bdb9c281c2f5e1deadbf64bd8eff3fb847546973ce461b4ec2e30c8ec09dba30d97c538db6a02d5ff16919af9a4a513e99e9ab5b646b3f2f17927b72f85406a997c464042029e0e9650c920732afe97ffe135e677dcd488e5f503cd736acf82c769a02b94b55ae465b20d5a979ee0b2cb1cd716248fc8df3a46e2c28a01e20281b5e44e1f3952983f83c6f6f510578dcc49493fb0ba059110b395d4e4fec4e479a15c829224d24acd9eea409729bdb51f9248ce09bd45669a1942b2721a1d503eb3841844696569f4265953b8827189c9a865770d64e7e7993d455e45e5c2f4cf2aa882d4f4f35b7ea4b196e0a8ef95aa175b114fcefcdc7582bb7ce9f3f8d550c7e537b2e58c9fc516bc1437516d1615d66469fb05473d57d244e196260e6d14cd70e4d14b40fc36aebce94ae866e1ee9caed22c678d344d7e81554ac7d837739f38a406656e", "4f64b8478240868", "cd", .None}, + {.Log, "3020dd69182c9845a20e0c43173b7a51a16b3b8b0bc08388e35857ddb419163bbc3ec5bc7ee4e47f3a16fc16e0b6f962fabbfe8ae6d8c280fd8294c7eabc38ceda50d807c23147e538b8b4a8f84908e8a0d2072842c6ecd278d4ce3e550f67c85f20bfd43def77451980b5411e63eb9405ab60331dd37a8226d412cc58fce7f7e0af7141fab921b98866420f0582817139272a6a72bfce271cd1138bb73660b4252846ee135184f2384fb3fe3ea5dd006c05a46d7ea6f3c512848b9e40321fb42864f11d3426d2bc018278e3da235a1225f0a116608d4ff06b2082ffc2372a27672abcea296247ababf2dc342e54fc6f0412d6977c4ca39e9dffea2a788d86ddb5c399228a276d8c7a27e77c9315351b9186b4858a1338e210e69d1eca920a89419ef3ec53e2c2ba27ef8323a22edc1ccb617255f5868a9c3248fb1831031641ef00cdeea78d229046a99c28cd662ec0cf3eecdddd8ec7a66d54541a780ca9b12348d57eb9c48d80ca0ba5d475a7dbc35f61dbcf32280428402aae82a00678353cb344e749d822518d00eb62750542e783079f7af0e30a36d2acd46c6644f787d9981510000ed1b951e249ed3af65cde61fa6b93109ba93c8b8e8c76c2057cd37e972892b7ed4e6d066993908496b54ae9e949c902793d5a0632b706cd4ad0a6c39998bbf330e153757c368241930d89fed6af50f3d29c7d60ec040dc4a28c526d62c8252237b7b0d4afd2cf2cf41887945941bd2908e0b591788f0deaa067efdf6f4fd6fab69ab247712a34771aefcbc8f603122888046f64450c3c19e060df1f00adb78a57bfb2cbd98ff1c072c48ecda9838aa2e3e20d31197c9829395aca96214f151d90fd728d259558e6a01489584cb1e108a583c324102e93d13a37c6de962ac0c708b0ffaa0fa8962c4640671ca8c082ca421bf5f91a2110cca9fc59c36160b803dbe510862196eade24f8e7798b189f2916801653fe2b9a1cd3ff86589ee47422837407fe23fa7ff9fdd6789f75f4200a38120eae2e9d53e74d73c532be0a86e7293922bebf262e10ffa30904276bdec262d93a5428a14d7a7253762694585cf731138c5a64c9a3abdfe53309fee0845e57ea18b8b8c11b57d8288ea9ac6f3d3a04a26d2d48999000715f7f8711f43f65f8c58e93290c7e68540100a0d063f53994e5fcd4053d0d3083b8cb2d633e7de49ef18714491e2f62da942824850d0b1b70d7b5aaf9d15db0639506594981f44a9c001c67cd99118525e88ec52e928b88bb5eee53c523ba148136b4ca930273b19c95bf59c9943ec747d249f7c8cbab4ae768ae256dc69e611a93d39da3aba12b26a6c242521377cafc5fe70cc82dbddd593c940ee5a1dcc15079a3cd709be124c135c785fffd84a573eb0fc784b2caf95a85685f8c4480a4f286ab29b54853094fc879b9334b33363c5886b41f730613bf02b860c21d3896047d69597784635d9e87b5449d3745099a059d60e31426376b4018735dd2998a8324bf45b2ee17038e0d15138ccca32de7e6727956425efae14cca177221ff14e67c43e08d7b6621e18c06df1d74048461c29dd034c287f68b506fd6c3830402c0525619842768acb4a815282feb3e32a6fa89374886a2cdb353904dd1aab0d481849804f492db5a0cb42957a76767530b6e01b4e567569578bbbc836dc2e30f1670175c2de0c8392fb4361a2c9bb042ac78843ebb22395be462ba6d8d820e050ec4268df15cc69c42a2d33b61d49d90d1ce4a58f985d49593354a3aa7bbabb5973df618017425a688e2d07d2f2d5707f7226f67893e29f233f6b2b8ff9ac6f6bf7607cfce4e1906d33a9da7ee9a57f3d7c7842b32a6b8fe83b70a0ad3c8ae002b716fc8f00aa6f3e927ef73e8a0e5a31675494e8d1b5ef127a26fd9193cbc1583942ec4b9f8f52d63aed69a89f351e189113f6492caeb1419407990b345d81119720480bf49124e16f3bd0cad570dbd54dfa6d54481db8f8673ba136ec91ad2f62bff3aeffcabda2b21402cc7d2d2c2df904941b9033c0ac46b6b1cb0930ed1f56cb879b0fbb4e394cb39e07b989999e8f89e290b7b3cbc138bd3fc8683d3d6cd5127a9cd9a9fd3d2c36f3a909f35", "891d8babd1df6a9", "cb", .None}, + {.Log, "209eb0c1c8f9f930feaaa4fa40d02dcb1bbbbd84d96de8e48ee1876732691ae8d62f8bebff8c90ca1bf4c15fc94488b4326bbb19a407b3b95ec89424f36da8bab99ef3b259f5dbb9890f96053f334773a64978de42b173b2c3576139f1cd50c3e0158ef73f73ca20daae211569f68cb28095c7b6a1072f9ed3930f94785cb8337e1ed30dc3425507d88084cfb8fe5d42e7c11dfd8eaa1a34076c4a4f3b2b9eb8b6dae3dd3633e86c8360cc81648729dda00699fdf615a6e520690abf5a48548ea34c6ed9227c7bb01527d3afad696f95bad1aeb02bf90202e8eb2f441278611ee3e0baf5d7ab5ac1dec33a494eb4ad4d2491a1f2252db981e385078be50a9104d79617e9cef29174d5c6ffe5f55b16f8d5cbea6c26077409369d96100e1a5f03d0104de3f7bef5483bffef06552116f388a6d4edd8d24d5eed02fd2c7759b315e718b33a49962a7d40be502e4c6770f5326166605d807f7dd87e6c05586e94bdbcc0358e21e4e437fe757f23476d9081f63df6a534d04144b6327553c8ab28d22833ad2ab2c25c779a4c5a63a2ecb0ad999e26b72924de615f73d7513ca2843e15d4efab1468c881fba7735f848361881239ec2f5104831ef4f2a9ce61c43d471256479f4c55affcdf922f8340919053e88d214c3cc01ffe06cc3515e2256d091017cf5df377ac80e129114ab7be9fc625e131b50058a8f4897f5fb5ae8a5c103d3d840c79bea8a5b94674dd4e8814f4db6c8aa4cd44b9d9e6c476d3b62d4487ad058cb392e3d44ed46d7164a398082bf18d0179d570198148adafc415897ea5f87bfe85f642af122fbafc9ced5bdf7ec8e8104943310484b44e11d5cb1f55aada80dbfff85f4a37331861a0d280ae05f79d46a45f3569dddf7221bb32b1cc3c9962d08c4ae28893db35c1b0bc967c807bf2e8a8e1765c7749182cbb7ad910914409df9b22904675083892a6485543028909c2f0633a42f15ac22ff2bbf082a442ca6a5fc069e912ff43ec28c840e7ad4609cf4c9c36449e8d2d587640c6495fca7ab1ff733b098c6360e6235f78b5ab39017b362adfb2c564baa3817931fd78309a3684148638a7c6c1b85a1d6269b19500e665c211239641020161d3a773ebbafcec442069e4ac56fd8a5d6ff7e5b077112bb91f8fbd0128204c5146136570537f62ea35227d28a9ef04ca6262f209c81de2509202076f399bf9a3e2e7032481fb592bcdb5ea53897dc5348be5438f798ae6f03ab67c437adaeba819543eb52c13152b922a03e5c6a8e6e1edf929f762021a2085e888e827a978c17ce388f90f26ee4c574ff3426b6519ee58c5ae727f6dae1e41c51041a132683a7ec1fcec36e27d4ace7bec39c07a16b6284d638bfbbf7f8143e20b523ae81a3521e072710c93319787f92c624f6977ba86dc3fccfd41864145f74dda5548bae740a0cfa1fff50fcc4f569a0ad69a2fa00700e50e5049a2a2d0689ad0b128d11348df7021980a60fe31ab03b264d750d3275c2094161865f4e65a1583220d6c40668ca0fa99cff210af81f9d0d21df11351fb95ab52b2d6b4355d0f661d30cc525dfc39e49a8d1d5f70613053b1ec83b65e464195d82d40251815d236e1bdbf3f7fdc668e9333e34b7d3be79681e27727d85505a15e80a8d3bdf99fedc77c088957e1ab23930290a6a296493b1a5fc4cdfa61f0747a18dfc86c5b8a1f62a9e448350d7020050f8044e3ab72968d388296951102e097acb66c8eed4a2404e7f13d28d95d159eb9e2fa9797386131154e5bcc62d431e9341a409b57f5346663475e1cbe41da8d8c696361be0a66f8e31c60d530bda6d0afd1633a9d4c36276c72a32cd263d479624845882a488dff426a73276a819ec8da54d9c51a6f176d142020139ad76a10b4c832d07045030eeb7cf9966455cab246c5cd696c5647bbe70d8f2af414f219891e14706a0a86477f37f99f93165690e11cea34e4695f69847095da6bccb1fd7576f3ad6b95ea4c517c982f7085a581aedaf8ac508db1a3598dd84bee64742c55483809a24ac8c9174492bfea7da1765631079310744d128af9b54a430aec3eeebc03a97ee0db267fd76ff13c57256af1cc9bea6435235e6b7c27", "6e143a69748fd4d", "cc", .None}, + {.Log, "698891b1331233a9e4e27239d2119447f788d7c808dfd9329f53ee3b2d753b3533ee5c06f2bd68f15311d559316aec077e2cea0ccea333896dd07c434ef52ba3cfc6ce55499720aee31d7ccd14592378f095a14d935acc95fcbce153ba38adc4f4177e1d666502a6371d40f020451a77ecbbe3444e44b7a82e8a024ecac087a0d1d76d7d109d193ef5a45ada2b1be73695a73ba044de4387e1a4c9ed82cc8dfa10dca6c761385e58b952cf2200ecf8ccfa3f50d169acf406f1d2c20ba5bd2ee1090bf952b19db6c043662e9c8f8f5484cec31f87c16cd29b00df2bb4f713ec391bb1202b3d3496ea2705804a4bcecef237e7324efad5bf24cc61745d44b31a889c28ce82e05a868dca7619d8e34c3c11b1ef56afdd1489f6e320bb4f9ca84f75637c39762e3406e1e99c34da3573e0aee75d5fb3e73ae0a15031033e93a047a1d0c15b65c02f892a03e65b13b7b3f8fe14d5afde99156e9a3fae9a4a9f7037681278586917280daff132acc48fba5253b0b84c69db10d9669ceb4ff1aae4ebddc25ffcbb46f47462e5d1d9b1aae6db55eb6fc63e13fe1c29a849a906527924dd54ee344078b7d852a68b650714faa16f1ab5acaa825ada152e7712abd1d160e8b604fd68aca49fef8730c2fda72c8924a9ff54e8dc157dd40500aa9ed6386906a93c72548ea05b2b5e8c6cd1aa2d795eaf9612bec1622e756394419069310292806bfa0db4ec399863f91878cd4bb8d496d9d40cef7bf2278ee4b71007407ad5d62740a7d26e0d70313922fbe742afe3309f7926fce8c852260af4c470460fa8ede32a3d9f07ae55e79aeb1acaece9b0c06c9d8c375ca8ece3cfdb0bc417257b036386b7cc5be6797741fd4e8de04a8314130905cd996b4d58021e5872adbeb40fefb536bb17f2946186dd10d0501e021f8cf5c093e933410544d6b12b565fd5054f98dd0b5d5e0b3e09c06b808ecb1e25653fd0da869ec9e5d7f9613e01145b930f91090e6bb69163451727f1ef95511a0a6a9277e6e20b23b796f8e926d4ef14f03849ca5edce00b78fc4b0a684ccbadaae0e13bbba96cc81fe77dc9deb58215ca8e2d477c60605a785f1877ae283fb038c4c252d5bf81f45e65c1b0e80744e7a3d6587d353957f8c12676dd7bc1df4431bb2d6cc63b96556c96d5580d4cde0b8d0a2c0b0668d3ecc1646606613e42dd5980757a98fee38aa750949157ca80fb730f7f43a3092a306db3c3283ad1b6b8af9f3157dc27937112cfa04bc96e254431310ae37676dc12de27aa38611841af169abf45ecff0dfddf6c103bbfd447700ab4b603ec74eb5023df1f9560d8d9947942b556b4e10a59edd94f403d46f0eadbcdadc003880b57d01730669e04c90e726d88438be175407d00dbf94f13e39c699064cc44a1f5df739390bfe1eb31613343af28a015ac3319772c3beb7a576a6f15ae231d58a8c33c7cc09e31f317725c152334a2885caad1126f75b47ef020632ed66fb60f5a957da051a90e5ed5eab9c71834157dddb85a7dc7240c8a04f99ee52fda81bfbd342d73229d4f3d1cef531e0ea1d721af80201ab166c9ec69660536dd189ad15d4360d660e321d08c4d8020b1d1be3963d500b1ed863ab1bccab0e95c70b2147935d420e3cb244cbe51a2beeff955e8b77bc671685c6ecf1c4e9c5304bff326201ac68fdab855c6c6e7938e9dce2c90f247712b5847fa0b8525b283eb538230fc1e5b1b000efa4c7cfde257c46f42d55196b90bfad22b5a6c7e17cb671007dae03eaac750b3b959225d1fd60d38bd9cf07264ec8e8b8ad65c565e56f5e169335f738894b56ca2753c5fbdc28ad2ce6a5e186dc8865404d9c08bb7a6ad5b332c19cfdf8c803e8964cfd03edcf03411ba4d5e9e9dfe733469a28b0672d14ec5752e744b5f6f67e88e1b4079d2896d753959388f925b7a5dc3a28df44939865514c1d145b20c0be40b3852641afcdced54c4d2cc02e445a811e757080b2b8cd80e2447df194d4241b77356b5ef0a9bcccfe48d338bc5c572fde5e54ed6c760dcff7982eba460c9f6b19ee3a70fc4f6509457705978fecb02fe258dbb9b7a7e8eb40094fc3b02972fb96882a3fcf2dc9798dddfbcf7a1", "c88b153804c3a62", "c9", .None}, + {.Log, "3982c0b05f6d0d45df788f06542b8ac934ed4ceb3eabdbceb4e175103da41be627179b9260e4a20d5db860661f6bb9264a20d869d676daf5751447cacf97f47128542b192f605e90a3b3f387410ef7903f54136cd7f803313379fca4d021ccb1ca9029c382b01a9c7ce1d0e2384556e15170d6f356352f40fc64cbf0e05a8a41acaeab3031d8e294d961c6bd90b9d1f97d2df7a2c047294a33e172d553b05927bc88b6e2776bad8bdfa81041a6a66c11f0d666c1e57818ac25161bbf562d6bd6dead9d3b54ea728803ced5dcafedc8c2a4bd100874fc3979dd987d043e2763fa790ace03e429e23ef8e87ea36bf51cb308e0f03b844e38c1a767c9a046d4b2a9b2caa12cfaafbbbe96069f16448fadd374f51a85f4a9c92cdc19e98fa9fb2cf913c62c32ed526b9aee1012861270330b0f6c26f70898a7955c5023c94fc892fe7dc1ff1184e3ed4ddf122485aef37e961db43c5eacedb407ab60672af6e0d7835cc94aac579b9d07e5f81687ada7323f184af855e01a36c213d538db44f9c53e030cc27fee59b20203c69dcc0a4472a22595b92d79f4f63501fff7320ec52b6db78601543fc984d895f99d703c66da38aa11f310d44a995e6f0287fa289eaef9794dd1ea765711bb9632bda7e76763fe1e212c5461c17d081a138ff6a8367c95a7b8da07f66b91861c630d54f0236660b578eaa8a116b253cc7faa6ecb787ff80595cf3e242301f9d0ed8d3d96eac09c5c8dbce65a90b5e8059bbb1cceef1554613a30277ee6ca00091149ad496c710fbc16aab2744aa80d04fa452c34a29b8c715c9866376c6bda16b0900f8036be0807ab9d59a82a825a7ade1a6867e296d0c52f7659a4685c2eeebccfde34c632ac104a4d9f9213ee401883d16fca29418bf7d78c203fb45342b95c6d533a6ff24fecf7e9098249765718c6ee5baf7a8033bb732737f9306516a28c9ed90ce5c34406ee06061bb0039c36ec6293097f261f594c751f1c9b3a407819098027e4df5f21ca1f3c178aace66917ca55645da4467e9ac525e15b32d5bf7f5c5b6f7520d5e958f67e897572ef222c093a2358c63fabb7024284ebae765561a3e4e6cedb26798a7757c12033152928065e007ae2167324a295f3f9a9d6485d3c14330ee76ba4c4ce50020bba8aa30303716416bb2ff6f3d701c333c827fb917647b03ea1dabac68135e0fd1b8675b7c0b9c678821af19d768a072ce3f77f370038eed69575dc5220e271af3522bf6fc659bb6f3c1e18c0e4f3842d6964349e5aeffb232e04e82517fc20832f0f50c888434629b35a2c70fd28bf7ec1b58feaac00a07da6efc16153baaac3423ba34b9fcea00cb118992e23b225ec72acbcbf5e99efbe4b7317cf32bb07773e812340cfa8bfe206a8045662ddc82e03eac17f9b87ae863ec3d9ba5b662bebe15a21a537e6ef1d2cde3fb29924b6960508b5d6ef69bf71bcb84d010accc25c272b9fcf891a1f2b58aa532f9a8ecf9d0e7b4e30063cf3d6661f43b4dc8b7c86f917d4dade9c10d20cf12e353ad5f8386fcfb482d5896b1df146c771493e60de8747aefd1ee56eca3026d75d3a81de1ef9e1949c8ed61ef7cbc432792eed1a5c5450fe09fd8819d44611784fcb3bdb670195ef09b9a16240251e44cdfbc98bed3ba3ac30067ad9425ba67d999718bdbb0ca1b419a8c92f5424693b2a8e8270cc14fbfab511648fa3f49ca34790825f2cee173386cf88b2ee71b6392e500f2579a17f1c0c6d1fe04c50d19b2c4903dac956fa8ba113a10d1a0a9b0947b2fc17470f3224e4f4a3eb88fddf2b78e6ef295889ca1c5c6fa9132b3973695c664ad064e0846b04a47c8f5f0e0fcc4012983b159e4d759be0a5c5c495cbc22a6db85a49bf6599a9e9d28ced4c6782c7b45a998394d6cb2362c1a02884515cae2d79b80d7f783fcff37a0cf2fe9b5a10c8ac80535802a9a6b8f5c74af9e4434bde3a6988f73e253f062338721188bff96cd78c2f1ebe49576a3a5edf43827a1ea3f2b2e355c615b8824673b30c77bbbdd56dbe992d236a6cc75e3c8e77bf4d44a26a56ef4d0a52fc482743600243cf52c0691adfac65c2384065c00f5e9a370123b1c5426d07a38c6f37", "548da721fb36886", "cd", .None}, + {.Log, "fe612ca1b417995af599794ba06a24ca35a9fed364bed02f4c84e027b11d6dec070ed437bbc8996c9b475e84ad38babc21863923574185a6ba59d20f79604382be24b1132e4cada97832dd3b87a783321ee0fabcd26c3db9f8dd480336b3cafc6875e030eb1f103f7eb25f3b79dd78e27f5d3c0ef42cc0ba62864281cb4410e1f0f28e537a437c482c51e1f934e787f7fdc871a348dbd66e697b77869e82a606a4fc699c9a277099fcaf1aeb1142487fc7d780e53d469f31ae790de74983d950568e2c07ab0b78c8cb53e39b4f1b951c53ef693abdb00348de8c68e1da2c8e5017a6d496b129bcd8f0706fa3870687cbb54bbd2063e226224091f8d886dc39bda6e51af7eafbf67d4f31164949945dc84787c1c13d7c1ae9e39d95459a7691ea1661b02c129af88e938436816354337e874534591f178f8109e358b8fde952fe450e134c6691cb65a9be6c395ef4274242bac079cc45b3249b14aca75c97baa35f15f475388d1d7e9eb7e0223ab236dc3a07772da6d85b851f2b5856f5a38868b8acb48175948f9fb7e0a1e7e9bb65cace956d749cc938296c4ef323efd6d0eed8dd34c2bbed108adc6f4b33f769de7656003575a44b27b1cb920eed2836bf8232e11c2d69c3af0e8692f884ba994b05d38137c0d67bb7bea8f20e475808739cae9cb21b40e670313a8e6bfe3c5cd4bf2e0e33b58482f8f098d84c2f96ca7f794e9dff82a652f990334f3995200a0a40d3cda65adef20f79dfb127966edbdea7e61875e279a4c5b8d69c9f9c0d456d3e97a5bb03e3668d97b82bd00ec625e11f3e3340f46be19b69b6fafdfba69625ebc1a38ee287c9163d4491d58cf36cf7aceae2608b2b84139c1faf9033bbee4ce7f8f289811540f7fd37f0085665ce38747b0d5a67c4fbf894eaf8866dc360ed7c41c33eebafe3047a7ef89f4e63b18a828f6fe50e5971e591d4b8846fa3520197d030ced5c22fd8bdab9cdaa3f465214cb55b0215b2406d579e1f5b52703da4a68b3ca0309d88a9a8a9a46c0d28889f7b448cb3dc24cac085a0a3513cc97ed0cef3695695360a93f9c7d523d78f87c7473a4351b9f54c3574fec96aeb261534e1df3ab8e5f88147fefa8b792a9682c5d34f26f6de2d4f58dcb8cd5ab331c006d2a342b737834b2c1c97112e29eb2e4406c86464ecdce698bc257171d865c315cdb5c1b3f210e83956204cae17455e3814b6542cda9ec201f311c4b1445ba401a83a89f596a6c20e66ea93df4040a03ba1ccf3de3f1f29e9e2abfd99aaeb4fe032e2e7b6d018c35ed53a9d3f3a8d9527ccd38cb3ee75358d53ba675dc618e3e2b2034451ada97bfb42cc585d6e1c7d62b9ee95014c17a0dcecf94d7a9c8cd1d2754b3f5d988f8808a7b22b518e28de0ac942ae5e69531c572159d8dcb3129587172f2a4f87aaebf2a9b931a57ce94a973551e078496a327bedfc1bc71892bf3ccf3d019e0c7b82124cdd5d9bca5fd666337de9197c76278435a8d4b2170b74d471aaf5a2a916cdbc44650831adfc187028e9c5fd9009351c16a588a29c4a366d1e9823b30fc1113abdf230ce0d5dba64c86eab8fd5c458a22924fb609a4bb8b3a9e4cec0a48f597d918276deabe1cb220166bb6f66ca546acd964a7151bbd404fe2344593b85d75c66d94fd261f5b5dc4cd90c397d794a8fcccdae08eb0f99e76bf4614e80a56aebc9287a757807142ddffbb70ffd2c71cad917fe4839b3324151f5097edf89a25d649401a4e147b377a1c50eafd53e6e3c55147055c826e14033c9001f85394308ef54f9e97563b61e9d394723445712623ce30a74e65b985c5992654cb45d7703f23adb37df87ebc2eb3ee84d5991abf79079a57fcfd9aca0179baf02cf68f3f3e4442cd90397092a2d3e818fb95a3774db7b850a55882f7cc78d9cd2d0883ef99fc61bb441eda4a27eec0e9d3d82ae6fd050f451eaa7d56fb7c20b4623ed7786dd26b624b17c726078784bd282d4490e1c713dbff90e95e931c636ea646659ccca4d099c8eee8d5fc19915d5b6abbcf30580908f31d8b9d31c8f46d9d7473d6982400a51f5df891f556970e986a0ba3d64047a8a67b169512175ce0d5cdfc4216c65f78c8a", "45f338d7354d3fe", "ce", .None}, + {.Log, "2d4c4ec9669a0d695d1a6e75cf14bea8867d3c6ef7c6c45f636757d9bf0ec27433764afb7868c2ab2d07a31ebca75a482c14a1b0f5d43055fdee81167e35ad5764de7446003323875d5e06309d35df73eb5ae1ee3ab90c4b650e2a29942852b25cdf96d100dc0fcd2fb25dd7e070d7a1f88d7b18ac6df99d615717988b350ad3b220206b7bb03f86509aab0be16f28b83dbcc399f087440f0967819396238810375be454c6be3efb64fdc902d5fef4b8d1fb6f9886b73be03c93b846c46b2bbc95756f05de7effd31158517c414288110a5cd21536bf350b88f2207efb99fff37560497e6f2b80583bfc81475d6284430bea807ba218dbfe385ce7c3e1c4ca66087070133a91d7eefeb43919609b47d702615581fe9008cb4609b5b2feb1976b7190d29570a3976c3ef8fafe88484e6dea8c08e1e606e066e7d7a168a22020974b2986131e069bdf83529f84a40890b6b778db112583d6d1655523d2f3895f328061bd551152d1d7944e213f98cac291ddecf0879212a9c25bce429f06166c18bbfe6a6dd9e9f97f1553bb5293d66fbdd607385984ee912f9dbf811c4123580eba249765a1f7064f18f732d47ec4bf51c6336a588397658a4edf547a7eee9e2c8bbd7796e487ee72daa0a6a1abbbc37d0ad93334af3dafc3ed1df90fe319689ab226e6b1c88d8e6873d27263c3bfdb2085eaed9a64559c1bb3993619aa712386258ef23478311841c701dfe0ec1884fe354daaaac04ecf29b4a44f1c77e80fff783010bc0458989f6f5d98d2ace29d7206da98dc63715f3d9b8a8e45c4a2554f6ef5ec9d891a52705f9e4d778ef9f6c169e283558dfe7332f046468e700104d7be22e67dc27595392eeffe5f149a4811acce0889d0e90061d3fd793abffdb3292ddafa179aa4cbab964a5b82c55aed3a52396e3758a503ea248546ae9b14d2ec120c5ca2eb1b7ce99e14907e11de39e2996e32324f80b8622fb70ec5d5c0f6a2d1c05145ddc9b0e171b7501a931c908e778aa4cefa99d52fc2a8cc5ed94bcb59c52faa88270f84152530b1cf428c4afe04c755d6b039d1d076b8abdf1cb1ad8de47fece6e3f40c016731fca3110c2c9ae42ec07646a5931009ad53977136778e9728cdf71a6a9681fd4b679a2d46cd8b70f263e5d5fb11a633419c4443667978c45214419d094d0745b81e4132d765887876a40c6a1c3d960adac769c9eed5b77b62135fa4bfb034bd78e4e2b5ff858ad5bd1148b05cc34f67ce3a57f57d8d42a53322dc33f6f2f262cfe179bcf6e4034028de1c5e5ce7863da5fae1722c37ae315a56a8fd87eea0e4398807c81c36fd5caae00a8db2b1a6382aae58294e6813bc61fc68e275016691fe9394fbbebadb46e286c2471a293e23024e95345402716a532c5fd90a514b3f8bbaa6c9fd8694a6f2b476259bae9614c380aacf24468d8e9ab50e4cc8d9f50ec4a541b44b653841e801cac63e43a846f0fd50f63f1a1df0e431ba23bc7b2b98f3dee76d09d25f788ca7c72bbe805951a27c1311db2d83ce74282c2164b8d5d4b4f75e44e744769207f8feb411b5c4ae0ee397583e21bf008768206fd916899a1b10c9f08dd62e4ce31e61461c0dc5c253ec38f9489513ac8ea9f8e01d336f540320ae98523a4432bbb08d996e7697d5fe960285af9ec0800ce2935e49bce54fc17034f0336a29806f3d605e59ec95dd802c1cc464e2f16f9b1e12a8e3c5a7443aa7863aef53a562ecc96e84378236ea5dcae0d653943aa6c4d7d29bef7bcd8e93ef2cfad0ab6f9f233dab98a1b35cd2893d5274f76ffc2f2071ea8af1d88aa1f7daf4f63cb5764569cf461be1e2bd7b3a57b9a46f82b711d8a5a24644b370fa760be93bf99a5eadcf102c7201778e32d5dd9269a146e4b0a8d63eb18c37add2706f3285e69b0b9eedc4722d77764eff3504d137be24e24f5e41de400f773582076ac82ec45936c245916bc6109a11694d6a9b1d33edbb165c0b0118b894fba489b98d5d219884af8638b3b625f35de1c0b4a7f8ca8e7a048ead5e162ce64f51ff66939ff0a562db661cd15844acd9c2b749481a1ff8070a70f2b665fa141d078a04e6934fd31d48d95268fe0fc90e1910339f", "c00d084bfead5db", "c9", .None}, + {.Log, "104e36e65160b07eb51943316fe4b5f6b49799c0108300dbc0e5a04409c63cd5063a13324281b156710eea65b086e7a1b334ed022668d6ea77ac6e25f9ce3ef8f29178563ba0c3d4afcd38931d410f3dd631b176de5ca4e6186d29edc4edb779957316f4e09e2e1fdddbd18568c66554cd0bfe39d092e2e3b6e97b9b3f1e6733862334ce9823d3f904377d757ca2ecb0d0a8b9d478b3c250f1bd8df4b389abfa26c1e5032d6093bb338a9096ae77aa7c018781e5e3b3b368eb7370ac6556fcfa82de94c9d9acf3356d537956d92913cfa8b14d1fbc2baa08e560779308bb3c906095c26408de2a745275e3069a2bd0752e4a91ba6466f37609b30d914b8975cf9804a6db6a7811cb839beb3421da5cdd23b6916626de34e79e39b1563ffa42a6c109c5e766dd600657652a0c39abd67a2981117c3b6714fdde779f337231f964bd82dc0e13538101522140b7fbc2109d90a1c20a1d46bf38603f9eebb682ee358daa581874765a48d22b2df39378eaddd68a490e612d933455a75b86da5fef51ddf93feaaaaf2ee3fbb01bd03d5098acfc03a7a1c378923412db21016313bfecec34d04b26acb939978bf83d2a5077804d6d649dfcf2f1a53b9a948e24b5c4636d73aaa5b37cd79636635d6792e9eeda1216651c7db344637fae14dcdae3f7b2e4066d3ba5601dafe001d76743adf9df89aa96c6ff1620d947550341be8b893025fbab08dec8d1f58e1948df50eadd85f9719d00ed46deed5ec87bd6b309382ae1def20872cc026a1294859c06e1c5fe897e393bf282c09001c1803489d8a180a85cc1d936169e0c123a3bc36604fbe7f8dc171d2eec95520083297bf289ee4459a5419b1c24b14aa45e457db2fb58a858c20dce5d246ce250d13ad432a8aa4e623af7e3c0802b961bca9756f5ea399e65efe7c43344ed0b53e12565dc45fa59fbea4147b6415097516ef23243371e15226b01355f24cf9ad46c97f2b868f9fb395650e4968b462e455b0e078b8cc1605384d49b6914446aaf1b71288f690e348bdf67e3a84527533f254593b88788282889755f758f440af5bfcb2efb06656ebfb0828fc0d376ee5e598bd3341bab06168c418b0d890e05e392b2e370ea696fcb3d762888257127285fc420aa334a86bda406a4517fc510db1b0359a1d42431a54726984a38847b78891df587ab40351d8900f32e4277754aabe8c330849ce4cc4a533ccef67fab0b84628518c981f0301a4d50052515e1d389e4987e1e0e1662be38b1df169e00fd9a7a3540d3729401bfcf98e9c7d962d82f465fb9efc571001f113da4098b22ae096129468d9e6bbce9f551dc3431197ad7991ab448c5b794428ddff7b3cfdceb353476daa872eb8d5644734178ef48a5f3d4d3ef889334b7c3f4f8819eaf266e84373ab5341183dd16618057a41eeb1c3f6b12ea87ae6ece02125e09fb8ad5a716bdf6148c3a3fb53f1279e474d2b552a287173b28a1dd06da88b11c1e28f8f79124b01fba56baf7c26fc8b7834a0e60d4892d10b4512d4ed4851fe6c8d77e7830a38667226c978e2c637ce47fd36e39a5757cb3ce9f4d6b6dc1fb6449e158168132dfcee5018868616f216c5548da6974ea6948debedfac25991412ef621f5e4f77fd193600457cbb2212804335c63b1af31ed657f468a4538d0194719ffa5f5c4e690dbfdb06e09cb4dcd7d6bd77db4971671d89c236cc40275d81c921c73adc5def0452a5a70df27d9bed65f973f35f58692a3bfb8fe1d5b480e69309d38564b4c0523d7cca75ba555d58c95ec8d86b853daf8730c5f7e6c88361a9ed4b1aabaa9d5beb664e42a81bd7f50823957b648e34a9153d45025e6c13a9e7c8c0348d4b0344caff9c9ab80fc0811d546dfbe982d4d867ccaf123cf954e7c4190f25adf76c1c1f1a543f25175a77fd09928dbf0c52f63ff1ff348820bdbb0c01d91c8e97deeb841cbac9a726cb33800e19eead44241beb2b8454452318db21c2c02d8085bbf4b15264c1b5fb867f0308243929bf3d338d008783d6134a07525b075759f4961f4da744499c95e229be4243fa2c43ef3dd17c086ef60eb8acf0164d11b4592783fa5828282cd4e9210086c753870c0d", "1d8220b3251d963", "d2", .None}, + {.Sqrt, "61c8aefecef066eae4155a6915c3a232762b9d45b307a9d4f2355bce419df3622be96529d0dd42cff6bd16e8409938abe7e25417a9e15fa6e9ce3ab4f0f7ed62a7acb2e427887336264c0fa02f0f77e773a3f7f7a291ed7461fba53732689c452e4bcd605ceba705f6f86f13f9e8783fe4046e009a60f16b9b47a269ba2f7d5c6f567ef4fbe2f6ddcccc86ceb93e2b4f7c2c30739c651e87e8f62812902669de631618d17b0c1ddf0602174150acaa5f94fea2b6191d96e9c40797a79844a79ab2628f6c185a58beb08198267ea1ea9dd43c309de578834b45f33ff040f241ed981baca278141ef356b60f2500b09511d92312e7c785fa0d3c1ac5c97724fcdcee29ec2469bb7fda27cec8df2f84eff049a6d6f79edbe710dbed267260d22543ae3987f697051fe6db440e48daf558413c96747140cb97794f9a186226dbbe44df2c7c67aae6b2acc9bd8cfddebb458f49c759bb6854ecdd4a16fda5e325603e87e886cf6866dd65bb61d2a7d6b8690d426d55918d855458931e043c0b533b29d93903f5335660ce2f521d4e6df489c995028582ad1529df994c3d84853fcf202da5c85cd1eaa21a9dd3ec437b35dc221acee51858d52d7c4e2920294b9e1c096b0a6c2835757b04c6a336de213cf3f3e8bf12ab66044924fb4fa99644893741a9f70a2146c60b341eae8fa8c1df68932477792d0b0fc45bec9831304d52693ab41012b511ef29c75995d74d7b6230fb13ab17cd932c079e976856abcd795c5dfbe677f4b27d09b01c78586d10a198f2584a503d9390e8092f97ce410f28ebbdac73dc0a43e108c0d08da303a316da6387b6c3ccb9c6ecda8c868fb30086985cd5f4e4916c1bfe15fc73835b79711ed114a2adff449f2a83c9956347ead77311831929836221088663d051f93b43eb95bc38f661c277372934f927266e450217836d0cf4066a501ccdf94cf1e4b3af61628b1c4eeda8bc7a87327bce0bf034a93e4392b1f36d3269d588fcc9a6ac9a846a2cf6adce2f2cf2ee878735ffc1b166f68c306eb3671d60a17dc8c2b1cee8b3820e41d490273f5f366fa0a3d35f729a76a466bcc1ce0759e91358cc2b8cfbdaf370f70065d27ba90ab9f761061a7e3a8b77b979ca71ee976f50eabc7115ac9124785b8cb75f0c64c06616f68f0744988434c34b509c02fbd056b72c540fe193439b05cb619ebe9ee3a2b9253b9658f99e63c34d900452b0e490df64b12409424851f548336d814652c3d1be2decaab59173034c8fdc19f9ae690e65fa37cf05d1eebb106f453c5be60b9b68aeb1e84cfc66ca57a31a37d2b8d84cd666167ad07d7664a684acd55cbd04da69f808d95f07af77bc854e6ec869046288bd53891f2b760c9007ee4d6df2b642b855cfb02ee148a0aa68d548d2ff88b2f33b0ae925743e0ba8a6cc0317c2c6a0aa28ab1e9aef75bf82197abbf98983157258383fdde7093ceb59cae2735aacc38a49de87456695152480f6bf954181a13455a0b1c35f6afc69aa204a3a2cd540b7ec4067c3f6cf4816dbc537f8858502504bf1c368e305959d7708e7f8bff2e8991c91e5ee8804bca332f6797a20cf2bf0b0629aefa7b15d09309773ea2c0ff28ccd7f54d7e470cfa285d9eb2798b003f291164a84f408b40ea33522ff56a8e8fa3e9ee011dc75a2a034ad7de2fb02c3c7b94a121e2015eac577cefcfbb8b96598c5f2e7d0c91e96a27150039b4fce8a05575ae73ffed6f7d9f2f37c8d3cd6a5bd570bbda339bd7be75c1f1d36f4080278720627dc297cc50a0b6f20bef23ac8e25c02a6ce4d25038728536112142240156f9964fb8c7a8aaae32c7a17bf8225aadd610c90e4d099c6ab2cb9d6ae88e59ee399cf49b8c3d6f12bdc8b12025be0098845988b92862569a9b951a90e0e2ae1a36a63a4358592230fd3c2f589b2a6eaf4d7f1bbab74edd518762aa3d48197711e678c0ab5428744d70f7fe3a6a3cb641324d054260c2068ab4a6c791121962d2aabd8c6f4533d7b0568862fa5fa4ad9555508ff01d84c69aa479fc085b19a983053b1b5233c592308da1b89105dd31e743910ca1adfbe91164c207eccf169f46e776dd0c776d6d691f30b84213efaa9", "0", "9e379aaaec98d4a27bc904e12f47ea848083ecd746e1833f04f35ab1a4a297573442b273e7c28a93223268d5574575a87a226b99c4d92a9b1c784be3225e7a369c4329cf3b2388e10384da0eea8ccfaf5bdee86039afef18c20aa3480d94de34614272742ee3772dca1fdd3774d2fe2df9bae5556952373b9a8660ed4f1449aade8c7d620c00f2659d4fb7578d2cd9e9d611d1cbbe0c0e7e570623b891d3e19c03fdceb88813e2da518a1b56e0f93db13b5ed7dac552d8ec3d22c9397d8678b983736daebb5551a39807de107709158d0a136bd7169a4e31d396cdc8cb218f67019c5a6f2ccd09351c09b3d513b74b276b48c55d5759d261297a9720008b706d69f8f552eedbd466a75146840b9d43415839fbe58c5161b27bb8720915864fe32b9c9222781c29f07d1a1d1b1cf7add4f260fca5f090f655bb025e5b38f109f063a68365b6304184014a693b2a917cfd5a74bc4ee66f8bb39d8a920a509cb3880a01ea8545ae333f6b56ed5c75c2c06948ba79b7624010bf62a39cd4c8a6d42b943fe9ed4abfe01538f87ac6642dc583e5ba9e4f6ccc968c56cc33599e935e8fd4f5999cd4cf5c58a2f983303d53bffd6093bec0ffed753dc9019442efc83a0a252a4b72327651be2a19b2cba4e778c808cdb55e73693924761881aeb85917f1da6fe2f4c88e94cb9105a6c3f91ca5eb9ef08ee8696a0dca71148fb01ab05123227adbd961c03bc43b806521bd0e1b37f2865eb2d60e7d8a2958028e2bea78d7e6b778499e7cb6e429cf7e06b975135c01a1e87b51213e45ebbcc043ae1799aaa4b806cac04b833a8810b75587472bea0919846fdc3e09e20c2b3eb72bac5c52734339d855b30adf20ebf8a469b730261f8075f03a8defc80d73397d823946573443dd0e28c88509321fd40c1e65f2b7cf1274c3140565e762bd0bb9b71fa5db75be8f5dcf316215e526af79f9c419db5582b9e54350c9f7a5467a80782f54a90043ac0b4b656ce818f50761315b397044418f28c90dafe0a2dc793c323915b653668f6dcc2858e70a3fa687dfa2", .None}, + {.Sqrt, "a51a4385776a5526da514991a743792cefa715fb8db7b2a00206e2703055a05d1bd2651a5bdc5687ac3706fd6b367b6822f9592cb53ad920d95958cc89839f739da58dd2b265cd72c336269cc7dba1ef0490755af1c821e1730ffed199e392248c346e9b6dc73dd69fcebcf5a592efa61c7189b0422a8c1512980d8ed10f80035bb795271d59df7bb000c8acadf73d2d221a882bbeb8b650c8f995d063853217776ff90d746d2e6d1b11e0fa41e37f6ddd0fa3b5add296591628e33429c3824397a5d3c74ed9f73874edb93008714775c9554c3f3b9a8dbfcb38137c8e266ec32a288c37641f2439ecfabc5c7a4ff48055c3abaf55c929a19345670951b81dcfd72f45cb076ba64407c23c67161f3470c0765ac8320487dced99cc8848f73d490b84cd14b593b406c2ba93b05d4a6327ae949b40984026293f1fe1a28d223ed149c0312b5ddcd58138b7dffe612feac8728cbcd9081eda4c859ff4e55a822124fe0226b186b0463eee6022d67b54ef0ab971883b10a6038e2e555e44478ef9fcf73ea6329b1f71eee6281c4751b62c2625cbef4eb2c624c0f8ff309c68ff625bfa97c32176762ba75ec2a09c084140ab04bf372222c01407cd9104bf2e414f0a3b8ff831733b6d5405d949feae0d4838f4833916f62080430660ab577ea4fef59ab3161d89ec0c2b12d593fbd68b9bf1ab19ed9af330c57255c2c7183b6ac9295e5fecd75009f2191effdd285d8fb2b916317f1a0af023f30f6fa30c08da23514fbb54336805710116c8ed75128633acc78ba0e87a56b1a9805e9caa70e7650bc5dfeeb16ac097fcfd2a4f3bd0f27d48ff3c982c0b5ae62f69e00ee57dcf1e8ddbc3cb2049eaf1dee351a73dd3c753ce50f7e046e411677a3606c7a1bdb4d00e524a414b7d88ee02bb6907e5ec1dc356816d7d557f927ebcce39e828683304a4d11deada6fcb9f9fc3085d6d8d7c22d9caea2be9e404e2743c6de903734ac3775064fa73ecc11e3befc5a72fd4cc3fea56b22eac6b9e4037d4cc00144b18b48ac5bdbb8ede654ebff19238ccab558cdc3706cfc4f949c3721259034e98a8317b1a3365450bcfaadd9afa96bcbd4fa3f1ea42685833a98037a9d578482313d5d8cf3ccac1558a2f10388d1babcea48cee7f060e5d330a81f0b320f633c8557a0226e551abb1d1ad9caacedf40ab8622cbecedcfc2aadb6ad3d9a6fd15216ec26d40be8870548e7a2c4662e9a4e951325e4765ab701d4a7ac4b0b3fbbdba104a5eb2400db664e1884eb8b3084d8a4d8fbee8c979ebd60bd985d6fffa6bc339c3b8337d9313dceefbeb9befd6f0aacbf84ddf97782ea7edc28fd47b9e01b2d3364accbc7c62bb3a880c4b204316333e3165633b34ef5307fe65c0eb83ea252b2b944209b070c3e2e8cf7c96f813692acdbdbe246db53d0f1d879da2d0e8a4e06795d28e465abed0adfdb3042b3c58a7bb483435db974c66687f0089e7be34fa42f4d1d340ce5cb91becd3bc7364702c74df159f94bc8699041a5d77d482473f758adeb23cb109cd09131edc8c17da11b7f04ef0a998443ef039e35e7b29f3d8bc7e901eca11fef26a229ca2be6fecbf3dd56b3506c52b3ed3c4f615e24787bdb75d9ba2cb2ca5721843be8182dbbc6da52c367c14d03a0cf5ec34802972f463e26f346e6d678e8d5c9ef3400d9d526b3a753381e8d87a5012f5bd844a5baf062ee3b8af2507b8920159f3203399d381a2c6e8344926d323a255db3fbdb936e5d4e8301a6b0f868c1ee8ee5762b35c189972408ffca768b2487c9802f47b621fda0153dc80843260b4536b36df989fc04b54cf21b1023c8d999d71950a9dcf62e76e0fa16e55737b3651137e9c6c633d582b6009d261473c981ea55f5f38884e5782a1e3ff0edd68b5515519c9e3eb2cdc484197cbfcebb12b7d3c7c5230c88cc2eeedb101968b8c5fe9994de2ee12df10bfe01f399551bca4469af73a887099f3cbc6b0bd4f2a516f8bf311bf4c6bf47ab93b5cc73e1745cf5c2fc68349071f007e2473dcb14dd910ab0f1eb232c2ac016f97559e4e42e8254cdb9a22e9e2aa05051505db339ab3778b66c61e516826f4384d1e907a9ec7cc3c17909abf", "0", "cd966d5960233dadf09c039de5a4fb2cb1a8f9618ad3257d2eab770df92a1696949c1e201632a3c66e604b8b1a6b570599d29d5f0e92f153edb1161a4e761d0a687e16f5301ba8ff3dc479e41d6725a42419104d834c93df99a68a033a51b228e67c66b57d26e9653b659a513f4ff5d5ba6e30e302978227118856cd54fef0e197b064f1e8a818ba255a359190f51687d1894f299e2d4319eded6366bcb7da2e9aa665749d7d75b1ded47cb1b56e58d7f41f1e58d147a421c1eb6a5373749eb7cc6edbce76d60820ef406055ed2e1b5da930767f1a88870259f629279415f5ccd8d5744e13759881b793ffe4a0d44ca8082a41425d64a86df7221b83ad937763142fe5e639ddb00533743e83872a09491ee6b04451641548ba710f3c2060b82963de9d95d99275520621bba7a0429fdf99240ae8a9fbbad86c41a380bc95a80f49bbfdc0ef97e8f826b9906ededb3cce3a0e31e6cfc287665429cf219b4863dd5a0d4ffbc762ffe9967c6068997f61a0d58685049577868eb256c60d62bb32a9d09929c36ba93673a1ccfacee472e0325edb6bfda78e09192d3faf50c5a77c385b7c6269c022fb717d976685ad8e59ddb88e344e6647cd885083057e8175cbfa02a1b3a3bbd3c73b7986b0d90e0af79bd1cd68191ad515bb1e4c245ed3e14931b07e243af84d5d4730e4d6f5d5fa753af267aa238b5f1c893cddfba1abc34cae39d2ca2bb9b82091ac2c2d4f8fe970f6ed06f6fd62d0213d50256de62970080448d405afca40af40a0289adb1dd32b3851fdfe8cd2ef91f38e69847b1a6f162b830e7573186e3787ab7dfc51c866f208d80d0a82f5012f045184dda2cb93d75d631647db3c5c3aa931ce10303648612056ff39213def8221a83e81924d8d23a17d9ce5ab94c2deb240729b2d2808f6d56a7ca9c96b7e374ef59c40123a40e0dd6f1b8cfd70b96216104b60d809005ba476fcbb266f574bfa65e0206db41599dc0a034c5458e8656415b2ef5ec84d90027efb44c347bd0437bb13fa06a2a62ac08acae9cbd3f0d88d78e576e10072", .None}, + {.Sqrt, "d558def98bcf7b1f56ccbfd6ad6340a5f2c46f19cd21e43e2401684b9997e8001681eba7336b28776a29756b6637c75721c21463c92a043382274c3be12260387570d82cff1ac563d790c9af53d367575c2fb69bf6ce45df61a6fbf0cc56075d5503a69763023ce4d0e8fd4d6dc2c33b269e4d3e00e6375c6d58d5c3266cf6c5a453353de8d2a28bdb406afb40cca986a9675d8861943350ea1d2321a5d4a05bcb5e48f3fd91fda10a7a71eefe1f4a7c2f71f1abe4f7f5b58401114304077d38a4e74baf2e5a546b69433e2a6bdce3d3e42258caf2715503a54cd3cf93de1da9472aae8ff1aecf1d6c9c087d52c8a4059033dbc784e2ecdf1305fce8ba967be73f37a34ec691411fc731c52fdb29cd4b9acae26d02a4f0ecfc33711f6785eabdfdfc38d5a8d054575ed6f305f712dfbf6a07aba9437dad71bcc1a470f9839f335962a560597f7c260e630fa147d8f5768192f7facd2c4cec76656b6f1fce52632e0939f75fee54d20b75f03980f82197ae8e4ed494d23188f7290851f2946e6d292e118046f689ab37c42a615340bb6016dfea0171153788fbdc89a9e7d0be8bbeff4e7d58b51e0b135fc39296af04a6c8c008194a8582e1a9787e09eb1cc4dda76b551658fcb4a463ed9a300dbc310c404fbcc9a6123a9d32621e7c69eb8aef46e79f547b043f259c1feb8d2d111b157a93eaba27aacf505865eecd5e6894621d7f39558843898110fd2dad7e7dfffbfe2843cc9b61b8c27b3f2339544bf214b6f3e1a826bba88337d573857cd63211fb0b5e88c2c6331786641f564ac761fddf18cd82466abbb67ed6973cd2cd1e89d2d63745b9cc9818dfd837c6b7d8abf5956d477736e7f69fcc683729cafe274da0216a8e7815bae8f5c2227a335a47051bd861b3c0b7b6a0c712d427eb4f123f0a418c45d28c8d683495fa6a197968053a4dd20d9841b216ea12922f981e506c07e826cde6d7434c35cc03f6d9d9ec4eddf644f4d9a8e1103d3b99ec1a563d9b7ac3df52665649608205da7d48ec8bb87840351f453bbf9e6c532fc2f92272e26fd5c7454ec8972c7ee57bca7d58b8bdc1cf944e0df75acc3e1764768dd3b49516eaa0f35a9c1818b1ccfe9d32fcef8559357145c89f7d6458fb4cfed52bed3cc32b7a4be62131d49fc6302bfd94e7528eb00fffe72199f9dc96c8d6381fff44cbeae6aede82e11a10125df193f09131f54f4d7bcf8eeb5a2e7dae7ec3d5a8d5f22758aa0964f1380afda21ad14f92b2d0c48d7feda6c1b0318305103521c5f9b3791ed3329f732111305d80b9b0d213f3d843892bab6e4b43c4940178fbe4c938576acc73ff797e85aba499fca06c2eda5e337d314abe65b26a5d257e29ce78ccbc2bef8b0fb13d005dfbcf87a45319643e0df212c32065c920e464788365899ac18cf1fd47c62f1fb81bd0167b8bda663429fb3c9915f226974f866a1463e486872f8bcddcac9c8738cc9ea90708cffc5ac20a0989f0a2621bc7d5e0ec2c2acdb436f3d2398f06cbbc5c6dca739dcd17efe4c90cd2fca4a54b89ad027e7025e9af638993d9809df06da0fe572fc7088acfc0b06511044585a18e00d17814cf4da47862ed8ae895774e5cc520f8db24f6523eaba8c867811d675b01de0b1c09b3178f5a18098146978aaf3b953b8f129a1f7f274f4261432e671f28f4c2818438ddf32ad01bbe741c42f8ecff99afa1024ff6ea3fae78511fa6ef7188580e36f8461f57503e7c563aa65a42326a7bd231cd700f98743847e12abcc349942920e3f3e2aebbfec094c76beb991c4b6cded25804717d6ea73ad369884e7806a59ec79a3c63e571af1753b7184043320a60f0fec5e716753b95b0deb64c3e746e6f506d9d75ed6116e8913845b80419a9c84812cb6266bb9b35aa20757e3c1f5999ee9c3919b0581062326b38575c9685c99e14450be7290157d7502a834389c8bac55b11d51e5311ea45bed7dc414d4c65027c0a9f9d9220e094cdaa97b5bf2a660020dad41359d56c229c84099ebcd4cfe1189a5293e3166d7933d5dba3592ac526f870b29e38fe09555c880fa3d04e9eac34c0a846d2c4f9ee4532fb6d62e03995e3422c629e60c6d22577c0", "0", "e9b3d8ca869819dba577edc6dce72f97b61789ea1a3d2f173eff340a49d0b5e9763b79e202bc1390ee19f20ac19201af09b0af5ae550a37a54fb2f9436bfe1a596441ac374f4838f396479b5d08b8a789c6b4549c327f92df64bbb95e52b6b8fa3aa08db906dab87a11f94ed6b5be151e61d6066e73102bf1e9262f3820d1aa6409c7697ae7fc91c9bd42cf727b1262c5bcc4c61ac90f88ed13eda2366cf03e84557c952ffaa19f08bbcfc03225cfc28040fe52919c2b3430ace32b530eac8c9bb62fd0cc41666319436ccf662ef5aaddce3d51207185dad06250f9aa6a5fa7bd1633a5a63da704d852a480dbff3ef6f523c15173ce8f15a074e05c0f7fbd8d2db7e89aa7d8e2411dad03f17c33067080626feb505c5844859248d9e17151ec39bfa4ac4eceac604b5c848228d0f865fa66dd6c6e76652ffa94d2dc0a9ab2f4e42e19e2cb70750c26b8af15a637a82c157c1f850a9ecdeb24ac6a330ca5b0f481b520c37985b57e38a3738202e344a9d03ee244b59d0ebf321bee9773f17b56625e9b5635c0f5ba3d65213456f84d7087d156cb586e1780640e89776a98c92a196a2de938508578160b187139ced4167a1655a721541ebc6853c626170eb5536a98b744f6e8afdf8f7ebe9a356dfd1f692c353085861a9721032ac57523276708d89fee1116ed84a91d38cb94388589f0ac6506e3ec8dd1389be21a0668fa131a0ef1ac1413aa3195ce117bfe2d223649b58376e9641e09e4e5b662c9adc35e452372ab1212f80a93890fcf23fd8c277bffa34daed46f566d863bcbadfcb16f0aacd72cb296529fe90eda490e4ffa61f213823e6d99b661bbada2de231e636e16f081e23c6b48c1a4b09be887222af05a00914bb245c1a4af66ebe38322c4155a029dfa0f0f14898aaeb5c0ad1a5a2645040e4afb39067ba98b3682929c9a2079f3238614670aec7cc5257b98b259c8a189828241617335f26ab9f3ab43a67d6589a8c40ca3e34ee5e66fd219a98739047cad31db9d9905d78eb20661fdc3785e12b7f5f9fbb7e74688aa60d8b41", .None}, + {.Sqrt, "21f0c71b7357110dad98313c18e8de686ae945a7e5ff0565e3640a76c6e59e29f703b112c711346809d9502bed71493f97540e1f3c34930d3e5df3f7e2e00324a7bf67380d96242e6d919e72f5d8a6d8ca2b0fd40a4efabb5a8891c1176160baadc964b86d11ed7b7695f4ef9f2417f02a2dda74d7ce1dc6f640c324a0da9e770e46955785499124130ed411d11031ed482fab7b8e544de01034c80873f917660373cd405b59e3e7b6705a7455edf2d06171749ecf8be816d080c4f7051d9ae31d1b569b1e3f0181b6ce2c6a89c6ff29b76e4fafce459ed33bb2644b2d392fd58702293c01fdabc86f278bb1be3b140b6793d22e7de2ff3550648bf3fe3d3bd3296368df15b5f9cba3787da55b021db43089e0e7adf7ec6bf8648d3f4c573b1d5ef0d4bf11ced13ee6379102cce10a11a9c72fc551822383ee3202157bb023f8a25b2455ad1ac2b70e3b91e678a5abc9ae93a87ce8bf36eeae6c606d8cadc7baccaa828a322476081ea6c5c44d1178e7d77d237557811860e133afc110ccdcde787895bdbbd35061b4b7acf211844780a048c64516baa2bcd40f21f1e85066439673ddae16954ead2da57f9470115164a9499ef87bc2dc64d65c294b97c9841dac4edd6dec01b6def04761609b92297732865d0e26462b3ade7b10c8f7d69925d2d85cd4c4a715997230dc0eccf06918b95036614293ca6ce496b300b1ae191ba52c05f4f2e879f166f8da0129fbbdfcf5012147bb37df80807af8c1fcbd2d405790011a876e2f08ac15b4ebafb681ac9ece535a4d13f9548d76f98b3b9bb768f0790440697e4ff017a2b0054b927df5bc8b90545a2e81707101f79f1882aed7349e27d11bb20c0d36a81e10d9506a3f017786aab8d8636d536875620cefbed82b57d13248a6f7c550743bb209e009f21b6892ee6eead8d1d3ade4023ab4b5e571cd598bc63c54fba40ed526df02b5de366bf63c5104ec9182e2dedc74e19f498d07180db59b6399abafcd38eed3e7fcf66c74253d4146c0a2ba0c89ecadf1b9d81050afa469e99ad156e0095b5ff79d46e9d7130687caa91af0d8f2fe8c5fff5f132a43e2f5356ef6bd8bd9d2c83860a5f5f9f674b6019573771a35c54c20a941f26d80fe88aa4115fcc38b16066d53e4db9a4288b7fce8bf15c98d6639cc438b8f29a293b3bfdebeacbe59cb4d762b64c7199366cbaa682ad87a76d5678341786d51a9dfb2ad2ff2389260045c828a5ea93e71043a6ba6bcf78caf02fd566ed394b45992195bf71f3feb98ae2d459486dcdc324bd14bed78e3780d161a33ac0e27a576f5f5238f5bbaf1d72c80833df13ec84da5a65450c38bacfdb50bf64d5eeeb80893b39619d39bfcf1bb8ba7830b62a8cfcb6b4662cd51f73825a58d3f31b0abe347f2f8f462918b00f1c3aafbdc7b31c6091014b074be1fee2c37802ffa791dd8f2f0b38c772b14352a944325c2210ba5f37b33773316a8006af16481cfa849130bdb1e7cd03be999251eebe3459962bda75d9ac08155e39c18a6fef5d61c84bfd855719a0b7a61bb9a07f9bc6f481d2459d2d23fb33bfc831191c37a2529f9a1ddde7645bc18b42e203c7e5103a8abc115833847ca831c1e2723ee633beb3092bb24544c2c40a5ae03da5d08da90146687c6908179683ee0f94974e87340035c0f8095a293e4d5ceadaec5589436589c5dce7352fbbab8a276d6e7a75de40e19730d351ca5b8cde6abfe3208aef9beb4d5226f80f074733cb0a05802f86c65d80a8ce17e6c1ed2f2cce108827c7b1cf1dcb1fabc450053b61cc71bca9499448d2d93c68e7b990371974ae84e082c02e107922814722a7ed83cd29f7d969e95800a13dd95d628d11485bbe8ef52525bc1263f03f814d7f6c0fc0aa150845bba92d8462cae4b1da83e54c0149f00d666a6e7b4a1460fc56bd045ddb9513d0df31037e88246e37e2c7afc735cd644de74c80444b2ca5ee8a6d417198b7375fe38402521a152abca3c935ff9eed521d815b5585de94c803af360a7f9e7eb1bf2e7202d3e9159455df5175e407879ded5d5d6452ba0b6675b20533e32a7ebed0b8aeddeaaea1deb52f52bda7e7c415d5698dc802091ef4ca656b3", "0", "5d36af61b5a2017f2f24e1fe6f7cc471a3f720c27214b5dbbb049ddf151f70fbbec4542e31024bb8a74070f9287b9602c2ba68f1f14b1ce8d65c178b50b948a831758bdc37101b0ef547fff02c92ab9bc6d0640142cb52e32b06031cf03dcb6722fa1bf409e9afce1c3e5eaf71eb339722520fc2cb58e362a24a32ff9343d23a08cb27e08a2a0a666e9873a5717b9dd42ab49b4e38445f663b8ad3436ef1a70e5ccfd47a571cad08cfc3d28c35258b5eb0a0bad509cfcc3a364cbbe69a60b27b56932e4be86410cf2c6fc5111cfb3110cc228d4f24702284e885461290398d26bbcd25f7ffb04a9d143233a03ee25dcdcba2a89cc4f78606f385089c8888e33ef19637f8440d67ed8f11c09e667c9d39751f61bf8db9722bdff41ea9e6929b98bda484baa107a36e57c996d8b147f82bb7e4e78ff87d63d1fb6a474a008aefe846cfbaca372998581620b800bcdc7b263d1347ab275b307df6c4d33c95c7a8581f4b7df583cb5344617b1e6f07126d557bff73f1a36ca55808673ca77245cdc4d054698da338810dc8e1661a32bff75c528e572c9e6510bb9fd2741fb7e5009f750d7135c6f3168ca9ef01f4d260f38e099dc9ada29216dd920d01dc561f032b02786c7844b1a32d37a3ed6e4b3f9361bab92bf74dc88d2c59d9f4ec14e8a7f4c1133c321014f6a8acf59c8df8f580fffbf6ff10636a33f4ccaa2c1281b30276d819eb5d9386170b130b3afe5d9db37573985b5460f3175d9c0d641c21d267dad5d8c47c428362b3405d38e5aee6709d7346b75f5f27500c4574f3ce2ae058f328f5eee229242a07b8c952c6b734b5a4747249cc7994e356a444274764cdbd3c85bd84f8e92071e4260530b6c5b54eaf22128f72ad3b34982d97e5ad041e64d3ae9286c2f57ac6a74172b920287efd8497d337f249990bea86690ccd1d72ad29e4457f42061c50c779fcede83e7975b82b7f8b6b34bba87b2ee4633534c021550afe7d18c5263c183fcc2fb1df259979c3d527a453d91d9ba9913945d23dd992433be747bbcbf2ce7f557f487de1", .None}, + {.Sqrt, "a3a05332eb6f452543d70e3312abdf30ac2a5d31530cc70baddf8a12165d29509aad90104cbbba152043289360ff000a6494e0ee607e18cb6d149fa7732f20d092c91b66f49c53f570426d9dd5c7b2e51420493b1803f3f129300efcd63683fb383ca38407ffc51bc14c4394d09c54618055c60446dbf021acd512cd2556cbbc203e9016a38fb16a0929566d577f50389ac0b70394c050ede81cfd142560a5ecc73b9323ca1b5aaf66de621cca692205cf00e6e5617ef797a2cd20fb3ace369af9fdb28e9d3bc54b6b3d7c93a97cdaecaf35c02dd6135f25acb0d3ef63a82633d28c27ce6bb4f79d030d55229ab0b0f1bd7a1cca298891b3a9a3a4cbf66fe5fc23e637cf7344deef303a09396b6c76546dc607f047f8f0146e479536ff08c99a86ff0a8f236f72525369ad02010ad277259aaa1cf77147aa5fb4caa6ef274744e31347bbc441ace06c93dcbb236a7b297918004c0c8f60840c31bcd7f42f13dde124811e88555f0f77c64d065da0e3ad18ec5d852bb1e28d5cd6d3d78d7358aabf38ee29113e3cec40d2380f510ee3cc150f4f3475f23479fd30088ce836546a7c74e8272196c4e8c892a0d4cd680a43b26e5e3a5c07aec2fd4c974773eaa10f8629f36ac27d1de140c7a7dc1243f11fbf0b4da15d424da1d54f10b32db8efaa7b13ea755cd5833625f82a213f8e5ed9b113e65c8d08f8aa881e606a5753573476d41d834bdf30ad59f3f778011e7473d4f52864acfbe8be864f021d44eda81ba9c97fd6d7f6ecc8f823683964e84e13682a58a6e8799a2d2e4087df896e39a9d9ceb52ccdd63a0a8c4fbd5d7e0bf1a2d0e6be6e9c0a6ab38824945c81e45b34e5ffcc5b2e3d5cf5c2e72e41c2eb478281071a2c6e576a0c259fa2fa4326394ccd8ea0eefd8c291b0fcc3c817fb7efbd89db14311e49316ff4c97b783b152cdbb1282730b1e69121001cbab899e2a458ecc0690aa2c7c08dd0c21cfd21a90a002c345cdb3747703edfc3ede6611d62664268875803a3d74314fd2f5688cfeb0ead5dba44a2e654ff355627fe3e2de2994652004bec705834469b614200fc3243a7519699e0f4054fccfc504651e3f88c17905022056cd989c5a52f4cd9aaaeea07945b335ebb250dbda131907566f23f5aac64a0b43873bd7415ba7eac69065428390998ac00b99067c3fe513fdff4f967a0ad2bdfa6f88fc7586ce0b2ba62ca9146767c45ecb0ab3b5c73ed2976538ac52a612ac0a7ca7b4aaba51052f4aa8fee3b970c11deb3ff6b704d634c6e93b6f84c683cad192ae3523e6e860f071be6fcbbc305f14453ae4d010df4714dde3b94b3e079a60ae0f0608094bca330bb25056b17ea0aca71cb34b8fed9ff32a9f0727a755523e676809c9d52ba7c8b0f1028095cc6042a01b6642e5eaffbcb9251e7caecc4fff8c10c76ea8cd69144c6c54c95efa45bad0a6d1083d836adc5a1d74dedd160bf9391e480e8b241fe1770d7714d882427cebd05bbfd024c8655cca87c30981d45eb6339338a2a68128aed8d2a5e96b1bea9ff93796fa4c463a27f4b58999f3e47fffd77e06ff1986b1e5a8598b0fb8a1697b21ae36e073b35cd09faf1ae46cb34d0d6e4a46fe91bb92191a06bd64236d72b4ee2cb36134b40b7109f7801bcbba9034c8934f69ccbe3cb14673046b834c32eb32296530074081ee6449308f1e249a64d964aa13679e7ac468afd203254c201ccb7dcb2fc30b1a029b05e6b26048a820ac2282563a795e7a27d3cf8ca4e9a62124886e848cb40b7e2d640cf5ffdbae6d3c28016ed2df8eb6583fa6faea2a2069c6e7171aa93d2aa458b0f1fc20115733349937efc6ae041f5d6641ed534b9667c336d9141d2ca3b932f094ad293d0d9babd40d33bbc01934e8ffc5966f57b5553dd6d7e8644753ae4b689e4a0cfe6ed04a9827c661628b92911d6a274ba5a01de0678ea223cf714a9c8babb6b09642efa400d592c825494e3ff95023762ea05f9693a68a70d555ee2d316a2aa0978b034c867bef89002fabc531e3183fdd36e4b8f2600483a2ec98d36b1e6565256045ef360e6db194dc54a78cc88d42f3ec95b314060952d089794f1fe29afed4e4127433ffc1070", "0", "ccaa978adb2c991f888798a84bd454f66d2f2fda7d746cf87e64a9aea9e328ff3c29b85f295f62e20a3f2fcd877c921f0d42cbe01763ecff38384d0c01222223988bec6794b8c5bac3e0d35a4c5e76894cfaae7d87cdc0059b372d770e4893437d0d70330528d47bb7c517409c5bf38374bcfcd25ba048feaac4dcf19f7047fa856dd25b54652597ca63375714cf821500cfb2434a62042c55b860249ac95045a4216eb7a2b897a9911e994d2b12d47fd21d23ea490358088b59454d0771438e25e739a4f3362a9ff9b8af7a58c3fac1f1fde877f7ba1a642a9a3b94d2dc9e3d1890f032942cc7bf0f45745a4a4b66ab4cd6628ab48e57bbc9ad9276596fd842eba45af3e4d9aea26fd86871884d8dc2f8bba19956790f31d77c773c5a3dd18cd2d4dc5526c57c42649eac8dc1d8b9c18ca8c41a976b551d149b30a80d0b40335bce7f1090fe13e5dc040eb8a1c7811d66080d928eedec9f21b255b0d20612dedb29316a880020c77bf4851d94e8847ff75f142d65dd9dda03a92a7c0c7f835d8e405ae5f1535cd62f2f83fdb396f5c739b42b8f5255edbccb5b58ffe9e1d992528f390c74f0af5a17d7457deaa7a342b3dd35b5f3ada4db5985feb076e5587b146469e3945515c4d7bcd7ff895a3d6e6585e437ccce7c2d519f158c7ab41138645cd6bc9797d90f6d42acf1074a582b33bc8d9625298655ad1176fc1a9e4ea22fa84a74902dcacaf2ad3959fc0431db55db8b4898871cb903db6924ce024d0e639ec7a85946519c1ac37f439203984a9f77460639220b17bd0ce1d551178fee7fc29e78ca4a9d1494ffb2b3d67d8942d4742b89623495b33ab66edc7e0f8c268d8eb5f6a4a98213388abf72b2d1f4643926c89c4048b8428d49488957f3ba133e6804f42bed527f3f63203d4ffe7dcd3cd3a3b238ccec4c8123690a315aedd3d2323779cc73563deef88700192db7a6a6dc1696d9276ec97ee64323f5735d4ae13f8f8a2a1a6fd774abdb890e0aaa715b49f6eff13042f5ac8f14b02440a23044c377c2356e0f08fe20e3d91511", .None}, + {.Sqrt, "7f45e9ccdc30bfa7b6d9f0aa981dcfd85b5886a61ab680ab966a70c0f6d0d87c76de3680b80ed70fd9e90d0b65cf58198168669ee8214a9392934e049fb9206c84521af31474271c0cfa391bdc559065c560325f134e0656cca825566871e092ff8bb6b161faff5f1d72d41e0142fb9acf91970b8fb8aaee0caf00635a4ddd0446329d89242367e7ebfa2106bc6b0de29b6c195e17a528c680f345e98f7eda855661e03e91f2f36006d0e1381893d2ca4ee1311ef0194d91a749334e02b6f416413d9b2f9491d76c507e00310f4deaa379b810c3d20f81d835502c76bab34426665c848823b7f92bdc323c4a10aec47f9ff96c24e0f5fdc04057b530fe7b63872ac9f9b353b13c7eb9444052a1a33dac3b4de6d2c5eeff2b013f15b939cc427ed8d7d9bc29a8ba9f6124194cfd71c07486a7f133d04ece5b0d018bedab8eae3646f5920d9abef9f3c3fb035d51df7f64f823cd9659c027524067de2bd542f89cf698a78fc437db1ef7ed5ac126ba6a7f08846380da1f8e3f2ed3337f8d4abd44e592c0093f66a1f61bc7ac292713fec1012d6149d2a75af872d06f5ce1b70b856b465e4d5d89fe2fc9aadedfeb0f8e55bf47e03ab524f9e7d2bd9190b93be3d6f2340bb794cd2d37a316f73688377de33f4379471c5341173641bc08ac1fad8b55b9e75a89263dc6a3cfa881e9b60282c5014a06c8b038ea56f0634be43f67d884f7ad3eab43a03d7dda3953e25a6097177e7278516d9d9056feb4c3c3469de0053e3abc9d4f91c6ec7e2b95ae1651fe30e0626c3e22ad7a7c27aa3e197bf194974a8c3e3f463cca13f432105db4dfc6de153beee618adab9b0a16c447eb986f34dfbeb482503eb595edc22fff9f8a74ca7bcc95c5e30470e61025a5e3338db9a272f5022042454e6ff405c8cc1569394067b743e103a0c84e0a73fcc8e44b46818dca0eeff96bf0eafbb4f7925f6be492277efbe2f55b6f565dd3434d1c82b34b883b5d72e2fa797b9ba854181916391317766237af62fdc961e1f6a434284900a4ad6beed608ad32feb7b9e948a7ad8933012dc493c8ac9c2d469e6f076ebbd7649b9357c62835c19c01b93f06ecf8eafb6762a43987601367c7abe3f113fdd6cca25df2ef98276542de7902b69725259e4c7702b8b5a0813960a14768c1509bec1d54d5642de216ea6f6f45fdfda352b54e080e96af1b8a6d865ec1455658ada395790535dec21409efb4a5ee799397fd0ac0d1bb6e43709cf069dbd24708bc67b36790b3350447b0b818054018fdba1b894bd5c58cb58e0efc0463b5e2555ed6a1424dc24511c01027741f48e22f3bb8aace7efdd1789ff60b6a71e6e78549d757c8f503429f949a9a900ba7ccfbb94b2efe9ea7a4f5976183c1ed8a22186c7901e479e58a6b98793cf7f6106dc14527a7ed603edd7018787d560634f0306894951ee46f06672a84c4e23b4ec67b2d91fde134b48cd93876af115138900dcf445406d0b2cdcddf14c8f9c30b441d662648d027f13dbee42f8b37c9813e2228222e4941fd1e0cd7a5afc59a7d24d97834d424f0ec0d33501107414161bfb72bc0f64e6a134f96033149d6a1ace90a8b073654b6523de77ea9d69b7941e2c7bc5cac3b693e1193083eafa0cf5057805acac17a716f3a516a1f76c62a496db80995119a4f955d94e3e5841111db95b54588e108f7bbad34d77c6d236fb979c36fb32b2688892a1b2d3ddbcedfbb531f3320743f4369e55eec376974ffdd0cc532d3a9a1fae0b500c04f529b94049bf1784f25d3570b36cce7d63bcced34912cad596584277fbe533c4f10ff5460a6a08bb95dd10e372bcd42e82b2176f3fc725c0cddbae0df5124f49a9ea41c8c17d59676470e7779f55b422759bc9bb159312dad33f88f226dc351c6e39beaeeabe20815013be883dcb64f6fed65e1b4670256072f88e50e7e09741b06b575f677983a86da879676d596b690d80903eae0a7968c8a18a1705e6ed131c589aae9812ce5823f10465e1062a36215ed0a29905ccdf788072ad00615b957546c1b423b516660e7ca2e91ef9069362906290d40e871e80a883617a1d43fd8208c55fbf813a13c2ff2a8f6173dffacaba2", "0", "b4812df2dbddc8da3d43382b30bf2551d663543754ececd1d64661096c279f9b04a12adc83578bcff2974f75e1d2a67ba1dc9526214f19ac509ba46b6a4f3d185ac2c601206fecc8345bd2756168c95e3ed6cd845ee528974337f4604b04abf20331df4b9178ef60c8c4a2f84ae14ac5737c7161801b7c48a89e0a62a0f47a94ee5b74b7f9fe1505f799ff86037944b22348f4cc84cb6f264138e6ec78cc66f385acb893a30a11d87de5e28e9fb76a25b16d5ca800fee560ccf3c304ad469dd0b858013e7f9e444d8eed00e6afd0774e01aa7aecc28999f66fffd03fa8b2dc4901b1fd12ffaa42b9b86b23e6cbd1ee8eead704850f6799a8fe973feae3d8f3498d3a8c1b5b8c8f658d59d0a90359819853afe197998e5bbe48d1aa32759231b11b8de2ff8507053b5ce6b8e0362eff4da503e8acba84af86d8d7fc3c6b06b8af0037763b2ffaaa5924aff4752390a1e9818a3cb29f7e9dfdac52fd0d2018d1ac02ee50868eea08d5fd05cdfcd2a9f3149e0510ab6ddb33326e445486ff9d5b64ccbb086e37ce97a4c9115b5fccba5e7c300ad2dfc399218c03326e5cc7143cb215022e5bd2245cf9f4492729ee748594c686ba150f0f3925fa609ff53e04a9d6bb31118e92f006e7e82a9e9c4f6b5ace5aa4c9fdb83e0d1749659431fbf7e8843e5747552eee0ff2cd149c8cab2cda501e2e67ddafb59041cd17ae58edd6a8d324ed3e72528db2c95701a1175c4a2b0f1bf9ba6201a588b239cfbbdba290d53dd8e959cea778c0b1c7053f42caabb1b2c95149e2fc84dea5945d44a354a20d70ac1908f0af1b6f7db4b91a7ee11b97dcb14208d8726e0ccc9b21f8604a30193fa3d961044037b5630450d7ebff0ce3527265b2513c5b0b8a45a7509fb928a6f07911ad94a244a9b45d50196ceecd161e53b6d2c55b2e2b20389cf35218393a3a0b19120f5870dc5fdc15a68585aaed2837a6f7cc9dc35c7a80dbba9e23ea3515dcb44fc0b3bf2680be5907f7e6ef9b551c111cbba24f0f0cf80bf52e2bd18c802d3d8082bf3145a069ca539bbc5b", .None}, + {.Sqrt, "e8d9573ca8a1d4cb779c1b706b5df1a12d39f307da9c2a2775280978e03f8e086ef34586b8e5b7cd8405b72a07128c53f187ceff66f93a3b1986afebe9f985e3b5fa8f0603ed78ab2683856a92d6069761cb6711371fed140d79462ce5b9547486bd02b08aae6d32f64408ca8684522a55a8334d93e6b3ac29b30e0271916399d029f1e47919224e46099bfc1b4370241fb7a7280c5816dcddebc9b48d4f8f63bdcb4c0f7abccdacdb63aeda01fabcc95cba22611ee593153f71363e9c817ebe5b686f76941acb8a8bbe8a26af06ac0b5e781e9d126b8f55d1b0fa05f52a3892ebe86a21dd7a377d788d6906b3bb0052c8cf0eb9559261ef9997fd8e1ad827bba814030b594b47c691b9ddb072ac4b9ba71c8336aa6bb5394bc7d695a65cdfd6cb4cddd7e5098cf985ba4b88e3f176e28c79efc26f81c4a57b3563eaad4c45277ffc7be3804bb67e55a993654ee04044c47e3034c7c2562d1d1eea7672e86185e02178916d294dbdfd135afcfc7eb9f6c69e6621e6b0235c40047d866dedd0dd95fcea38cbf014e42e1057485e32bab97c5fc3bede3e6e969de8e7a1b9fa7c35d8ac0748d4f29bb5e672864f2a99afc2aeb7c29735276c9e4642032e9e8f084cbe1e78e341ae1c452d9ce7c348e80ccc1c2e1007e0a75fdb0b34fadc8df6a1a84f1be0500973a69b2c606c5388078ede2919aba15cd2fb69148ff8a3a9c41f4a4453b7dc91cea04cfbb3118d2e078d911071e63f69c1e44727e424188a425e56eed69fe151ef25c8749b4c519d36deb6e39bbf3977a7e3c07b30c1ff01f7861972dee5a5c924b6bdaf770705fa1eaf79a02219b31d23b87de3600945d696e918aeab145132fd5c67fba6f2c7d008589a0c41411ea60bf4ad9601cc7b27d07bc2fe2472ed9b6b897d034f7cc3fd5d8814a389ef74a8fe4f26733f4b7010fd68d87debfd21afa82ad993fad24438d6c847df550d1a1f9ce48511b3a52c8509ebadeb702e0ec8eceb9864799ccbbf5265f3785729ef3849c10e64e25994b4da3291fb7d72bca8b5794a5dd31ae2be0dbb9960b351c1fe3d99eadbdf1b93845217e590ea423373cf1e29830d3ebf37402416c7b86f5572b8007b803aacbb0290fcd5dfa180f44b6b95e7591e5f828503b700c4b9d8f18f0a1bddd3ca2a898f31ab7ef69aafa9e377b3c0b02b9d68f4776efb34351353ca257c70a44a51ea7d05f1dbb5905002e331f5487446b813f4f9385fdfbbe1cdbb8cd0996f2c01a3ff2f9c480a1d76de44e513bbe13f2e443c2a632c257cade09fc3220ae35b821d486b55355fbc0f6dd5e7941e473fe88cd38ca7537bb6c1cd23ab27374ded7aff376c41d495f43b313bdea79c6f4bb933445b7b562ece273ac1e44e2114d68cf40a6da282b05a65a764c3a5f1dfe3aaf357f8837ed51a098df610fcae093d808b3d951bd86613ca187c435381103b336d29fab2b16eddd57d2d8587d624f8ce69bcce29fb9e6b52aa049fa2fafcf8e80d51e809c18eb0b6a196354ab4873384c83b6f2420aba3100326970039bbc8b05e2abe0c3dd6a12e0e05a9886ec06d15a71c19e36b16bfc0e04081b6bfaac402970be9073517048789706dd4a409e5d7d0ca5aec8716cb44d53e7e482ab90cc438a16bc7deb60881046f69e28494c1e7f8b18de94cc4a6b2cecf1e1d7062d85d0686962469978ad65f2757f3d638af2113daf58bbd3b6958e48927141c153dfefd874999f300276d5be71dc7caa4ad5f956429df8d810d3e7e6ad0d49cd15ba540d3cf65f4b4d7a18db8a139a45977b6568d0978a2c752909e4cab9d49fc63fdb6af6b35c3a512aeec081dbd21a4577a0ee7666c172587c76296a35784f03c0ea504e2885e0eb3585f7ce4de3a72e126e9a3611f5123b4ced462252fd7057a34f4213fd023079cb2cda2e2892ba33fdd07312dd09a14d7aa7a8b537e3b337363130f6af7f470c6fd929ff8916c498f6ddf3e9335d7f77bc20e0fd65d9ea1d7130182bf587a83c119aa8933d553e76285e33ca5e880ac8cf878bb497935bd012a78db1fb73743a6fbf98ba3a8cfb48b150eefce4b443e9a9d0a54d8630686a8308fc16b5644a5d21f0acfa8cfd6ec476e45", "0", "f4267645f1f42b17be2ea255f29b33e66c529320f59ea2955a06651a49c73e8f8f8461e224fba52f3dcb19b6ae06118ec83d0c5756d5db3412bce3259bfc312e9192d857e0ecaae2df97d19d570e92ee32c9f04adebb6f8a89b88ba67dbeca53be9d5fb7b78e8dc4b5e79e4572b9b5efc4c631e58bf0f47b2b656ef2f3a1926558cd4314354d616ae55b167b5ac3e8f2dabfeb98c72ab370da563889db29234a8f91fd3676616d0fd541a152c7d0df419e3ea04c8625b0628c0b72b6e2df59ad4cbbd5c79c0613d411c5698c3f0191daa2e4f8030fde6ffc400e20e5cedd8b35f4229294549e97fdbdff4396447efb8b46a2eeaa6be5fb77e531fedec4b4d9f619e37f5328e66ee3b65c7484152b888f6101ad1cd86dfb897398c730cea476c5c97b6ba0ac38d59426eecf7478c2cceb08a24061185bc74f3a602a3f3de93d16fe539845db904887a1a8d4f1097fb6ecc75083b426985bfe18ef97e514c4e5e5ff2ded7672538d3ea066d62c32c1ba19d4af239a31998c222167ed7cbf61af8591b92fe62660d49cf1a89cb361eca4cd95b2d732cf584c4bca258acd7f3d0c27164f4784581095e48359fbd5bafaa80a09671ff1e04b2a6cc552218b0c26ae25f797fd03104c588fb4d34f8b1e43d6a60887ebe3f9a0b4da0ba6ccc4ce20f01ffce976cb324d4f918e18edf7e64bc8d9051045fa99ec7393d8ad534e91ec0043fd764ca827c1faf806848416560a7c4cae35e8d30d78f84ba44f76db7e5fdae7af705fe3ba15cb49cf1a2132e38d22648fbc71dc0ea8523565d5633c9ad016553a5b21dedb6e1e85baf6756768f6767433ee1f547236508ce3b5ebd0d0a1b14e476a11db3eb40107a9f68da19e122315dfb32a2f02dedaba9932155204639fe5c1bb470ad6ac124af641cbaa7b5bb91da1076f33cbad071cd440cdacbd48101518b1a73856131708d6b81b5fb5ff097aed5ffc056b83f9077debe891e540535c00592695812fd77b35ffe7b4bdb61104d60521075f13f784a729b29893cd43f60e4703c174162a62ec439f7da3c8", .None}, + {.Sqrt, "aa877a6b8eaf5614cd2724b848ef5667003453bb5fabbf9f389e6bc9c03bacd80ded7eea605e0f0f3ecd5a691d7a911452309efd7fbbcc0fc61f5cd8888255dd3e0a7537d327de22caeed3f24049cfa7bab91a40fed04965b103c161cfd0f1ddc67e8b82f4b70e66920a261b629255c8e2c6ac9838b63349a631ecaba42afb9038c9bd3701b864a28334daade6f9ddd9d40c5470a4c7b35d8e8c9de82df5972b3d2c87a8344508bc57ae9da87cf9ef6ee06437821f51fddc8dbdab7663e44aac8412c5f98a92dcb336d95526bfdab94aecc65ee561cdb06d3be02394d6134c5b1e8165b0c9f2a0258e96c79013354d5b1ca3c6a78696338f93654e2350b61c91f4cfc2d818821af2e6c00e8050c4fa4db262386694a486bd86276f0884b0ac7e4ebc079565ccf66387ec269e827e4410a4e15383074850a122b817fd36baab732865e49d0299c9e364b991501f45572f8f0e58c473405bd58ec4399119c6514534ae62db09d5e7df5a3345f1aca40eb601cc0f985f91f421ecc07c06528ce404dc36293e3b0c29ff890720b6ad2ace16bffa83c7c8bddf142829db9b909ff3412b9905a2cc099eaef7a3e95485fad3faaf6e918f4d36682b7e4ef1842392536580c1b14560adc3459a169796b741d9c98554dfd7d9141137e098f71a48324ea706694346186a4aa2acc63ab05b9f8b8961925858e1959e3527661024342ebd82016989a9172a1f21225b19d23ea68696e6d3f86fc12c336ccffa58a5acea17eedc4dbcc89c191ec927e0b72caa44fd152fb2beb88f439c2dfb742e82dede2869c1180d259a0b5c20e4374d33ab9efce1632f9f3148aa435facdc3cd9be21160433735e15f4efebba399300438d81119716a1e2b6438157a6104c53f567a937119031344cd4b4e89c338e4cf423e36354f901b20c05561480bb6f762f22a95452dd460ce27127b786f55a51f30472abb79bcac4790457a8a98b71ab2022e9f457e0212897b73614a51a6938ce0154b242fa89dd1fbac2f0eddbfd691259a05ef19c0d6d20642674e5c1ded4697b13f2e76a0021915d7418d56b5097f65d521662cf59c0819eb20169a1a0f9afc9321fd5bfa5287d57d6cd5fe7706b1026602f188af09c53a6ad72b06f53c384159474663ccc0cf40dcb2555613437edb5d84864c3915e53d458a7453e5f5803fab8adc2d14dfe9ae6cdf46d27862c20877725aa9b4398e813c9ff49fe7321f1d38841a369af4f45fd39503bf1ddc1422f5058c40027c402ef306b064b2f32e23083cd1fe32c2fc076ee074e3bbf9f6732e190aa7da202c28f736e76ab5907472e60ae268647b780bb2c6ccfdce9f2ac3deb60787fe50b32ab66695ca2600b9d3a9eacbef9bd558b6f0d05dc769072b37278785ff25789136756ed596a87d50f5712cb3dd3cd98b9bbd02d13ad0bc22ccb28b3907805b6362ecf71583774c01368502f0b20a78c3e14e1831293cc24246930fc18161f39e8039b45c59fb359ca69d5bc4b8eb5f09afd2a142abe9eb18f7795a2634210f5aaf211a5863df3d3965db35ed2345014c726558b7bd547d9209f3d3d3f1d1eb62b1001ce64d686e80aa690c22c1e0f46ecb74e49ceb55cb0e5f8c3d14f6c99ec0990d331875619b16d61a1df4347defdd10f2ed12f7c3abd30c78036bed49fa084f7eb0fe2a41b5d20e926a4a393286fddb1872cf4e125d17e4d50bab83a1b168de14e45374607adeb3806353a40847b9211cd6743f751c33f2cc980834019c9d52ff4941815a7a2a7280f182dab6b54f2601a514d7a7381e5ee08a078ddeeb9e6d8c7e29127c85a79682fdbbe5ed6de97f1afebfc0e73ba376733a2d53778a6257dd00ce13a1d9ae8f8f1f8e812e5e895bb8a8b905542db54d02fff1b743a7be331aacc5c69f045d50fc39f25abdebadce00e0e0ef88c9d8acd122a53e6367d015954691b589bd4ffb55cc867fdb07ce530aad43b3ec34131122415224106cfbcb37fb0324ff7603a816ac2312c5da16df237a1e5e204397ee5798bf4f76e4242c3a4bb9f4994a468431e0aeda1d9f936d022e2529f4fd529d60536a7a01db64ac50a9c1f92fe3fd294c424614bd6a5a1eb1661eabdf34a9e", "0", "d0f05dfd0ae80936635028730cc0761545c8c1a721ebfd83055b61faaf25ca34b798e9a86db2eb2306021b7aac41cde19540e846f9e52704771ce9b3a513d2efb630734c68526b402d62d0fa9eb5a251d7a237d1803ea3582458762dd817acde0679995acb47c1439caf5979ee74f81d175e8c36e0260c6d1d029e205877312ec0bbdcd714fe02747c58e0fde36f6ebc512fb81ba3061223b38611dce1f38da4e55e769635899d3910118dcdbf395c98e8d7f972fdc80dcc10626f0b43ae1b86e29995c15ae8c8b28f6819a73802b4a7483f3eca183053829cdc1acadd5b870548ceb2a9be3ebcf31dda5dab442b0ef8d0babaea58bb942d45278fbb501c5655bc9207d5b3d2c9d1efc94bd5818366449da897505e26d5e8b6688b1a4e4b70e7078b1187fab2be987fe971203440c838f5dceb4b889faf85c2f4049b815c2098a06a0f69429cb74ef73fc5113b18c3902ebb1bf891243310f9cbcfbe3bce0ce462c2b5ebc17587bc5e657c4c1c2ea9989aa46a79f9daf91fe285cbd446c3b375abebc93ab35ee3c628185535f8c12412139f87d918b6649d51a0a68ca96e5e2892597df41eb3ba80b1bdef464557a0bc8a057ca2c771fe58c37278d8165b793ce8b92fb470d4cddcd5fc847c4bbc18f654880b3c55ec749f314ff125fe09327d0a9871fbea7bf868b6025ad8f10e7c1f99f670169a13687d12eafc67538025e7e0c598ac7c8c6e2e8b9ce48986a663fb4fb91b62d706348c19a2f8ff616b0a5edf1f33b46034acb29b6e7ca1ed4c7ce0ced8f3deae1784f07c72b6e81788b4b5a3e2ff1b584d88a41341b4fe8943a5d850f037c3d85a790a59b05eeab4a1c66c11cecc3466d6b056705cfbb60a31059a5b8c68e1b6cbc56471468cc190e9d8291b248c7821d97c5b72c8f939d2901569b50baf13ce351b0d784721bc133c2bd9877719830d7b18571adbf876c8f763344526fdde21674fe4b170ec28c9c4a47ac17a303bb8322837b904d53b0356808ef1fa65a76798b03b87960646a130125214eddae83af0b5038166cefc72f9", .None}, + {.Sqrt, "4e8b3915d9f8022368d87c9da5941d962a02777f3d716e3b755c3f08f06709ecb8e775ec64c78a9cde8d4780e2ca8f1978ac28b3ad7b39fac9c7d362878363a39c1936e600b694542ed45a6f1226f1648e3a793a5bae5df819e982a51e799e6df4420bf77b894ad9d65478669c1fe999bcbdd3b0330e7cf2309da54ae7e8c5d6a65d59ebac1038517d73f16c69874c6f83f88e91fd7bf0dc9b9e4d7043552f5fcfd7f4ed12b72261ba08dd370a357e0f36b5adc74cd74c0192606360804f3154fe56efd809a9ecd19ddb3946af84c3acaebe354c42d313fc3728e3bf65da145d64c82747a40c87d17b854804fe87038d29788ff142dfc999659a3e2f1cb5dbcf197b9c2cbb4630ddc95a2341092b36892c49bf11204a2ad8b02f6bc233f29a404b5a25d403e3f611f9bf03785340b25e8474f121c4a2b1d5217f87e0b2a39472506dd9d8b4925204ee4dab6709c2a87b1f042796298d66df83fb1921f94ebcd441980c4ca8235cfda56edf4e46dc8749429c07f5d0cdae00af50325aa3adce8ad33e006ddd09f590a88155d1f3cc7161a7e56ac6f14de5742ed82515571eb4089382018ebe7eb958f9177fa2636e21791b4e35e92b413d511d8b62d317811f51e6e703cedf61b569981ee9f3a8c2c963f48fbe7d69b17bf228cdd469ff39d793f00a21a1da54a35949ef261438f2451ed31e5b1ff12a4ceafdb56236955da8cd2448f94f9a4acff9f189286116d6a43d482898a047ea399fd616fab4dce5778340945f8fdbdf2690eed3381f0dcb668928cc1b61dddf3ae133757bebef3d33a93565f8f8669b9e92c7e1fe33c41370f3157686a71bdeffdffe062b1dbb2d580a6ae77752c49eed6dcced6c5aaea3bc7fa31f179d33994e4ffaad06891c308f4d6b6ee16e613e450de502939642474746d8a436c58c99331d8ee3e5b7d0f833f7c618bf7b3a72489e8a22005de5bfe663340048c2331d74ea49d01dcd8f02014e9e636f265866ab5aaa072a7b42b2924a94de5956623f5fe3027cafca8fc5cd50ea5a11e49e5682945a7be993a6a006e83cac556dfd47beaa6bd5e8392270006a3a263f16c943fcc7b3c4a28087df7c40e9af8d39016bf8a744daed543c8a0cee7129778dfb711d1e02541e49f1684f532a1a3d196cef6d409b6a638c0cf46f6c322d0b06fdf0bb82efdd85a087496eaed5d0c1cd8add2cbfd62c8471eb1436ae8f9ec8311059d847ce95a5063f926decfa3d96f347b4fba4567088ee546950f970250fde78eba5d8fc06abdde43f539081d6a0a4f3cb7209df5107f3d42189889e1e3b391c4902f4172dafdd9cf9cf4012c5fb3c76710974b47d1a5d66391af0620e686cf0c08d33fd16e604a718bdf47fcca373f26800b9230137cee3ec26dd052d38dc737fe86475c8a321b8bb881180bac4f2909040277bc99af56830bb357ced8ecf5552cda9f5479a2033b6230474adc7ae7b0e4b37f15aea0d2372e722976396f9166386563e282825bb087a108e1d92ba147259adc36e250c3cd49a14cf9698d3a95518cf8d3d5c63e0c57de1739bbdfe457c30fc54a7b6006bd73dc2cca591492ff6c17d0cf6d9be3980af852b93dca6bc923cd4c05224fd0ec49bf07ac3e43c45db15f27a76fb434c93e72fbf99c0ebf8793682f856fa742c1ad4da3e7e42b08b320b01405eae72872874465fe45f3ffc5e69d145f2810f43b933bca882bd30890a715c0e7e63404c87e751457cf8e86ac6dde91ebc3790d6f20d8116dc6db21ac18da72e3dc9f3a188f6c9cd5458e0c87673b40457bc4a8c9bbb8822f9926be9bdb258fac942b0a9cc78efe9ab62375cd3d602cb54aff86c0913ec8225339bbbd3b9df6675d5d786737e4cac0b7b74d74e7077510676fda7cc5add3f1b85220f97f3b6f0622f3189e88dae25addda55ba050f5d887ff27c85299db4abf8f27b9f307e9048dee4a35f9f868e82d1788b2e62c1aa4e56ea5d97952c963ec29402fb4f5f72bee2294c9e3a0960e4226ea6210b4da98a4dfea40bfd73c71ad97af66f3a7369aa36dc3c88dd527096a154015a48bdfcee645262a9e7db1a2e0543af2f8534ea95281f8b8986e82fe32ea5ca5d5f8054ef79e79", "0", "8dccc8de80acf357150fcc8982c3b17c6bba84049e5e473a622fbeefa7c1e891c461f528fac8555f40e6ff2321b3395422dcd8feed806c95fd4a266acd201a47dedb2915dead4ef573942e092ae46eaaef652d0398cb520a5794228979b8ef198a15fe25ded2038f0d5c59066becf746393b5f87093320b6317973fa6f07163f449f08995f916757373bdfc2e6d390e54cf303cd0ec72b8b8185008edfb5e9df3e7b59e8a163fa78cbc118193dc1cdea4ef19680e1fecba39f26c7b16dc63f6d4710c043dc34aa20057086993e1114132591e5e4433ef2496f21f0c40d7b6a0f33bcda0bdb156c4c7fccf5bdeb9c1a7f87b885473960d1ea8d43467059d52746d359acd78da5b8315ca6e3517f9fbcc1e4736b41938af8bfef249df987811b4f11aa797ab5ec7756bfa546ab68d3b209f776054bf7881dd98f11809d49b275e3b8780c0da371f1ca7e9326c088f3ba675f6e46435ddd5e66627d1fea0aa442c7630836eb7d9c1d822465900115273e7d8c9c3642281a9bed191057abdd75076dca1ecb7a8e37f00dd25771a8a7659c29068b144475adb680e7d47ac9bb0ea6cf361f83b6d5dc807ddc40593af1d0fd368787899bc77be18f3898e9ebe690303d4df8f83c413b8cca5e6e510af8f1f28719c76d0d80531c1a0ee7ad96275cde72cfd8db1fc7a1fd92f37f61125f089ad44d7f69515cc1296494315aca747c0fb4381eef6b9d2559cbccfd3b52edb0ccf602b5465b0286da79bb30ee33b46e631b95b805e9d566cd3fdc1b21f0e5b6bc477318a0282496d3228f9ddc5581605ea60027a953a10ecc6d34ffea7d461b008b8b493e678b11a70af58fb74753260124c56f8cbe83318ab8ab82588d7c57abd1549d175f1a99045284ab4b327b3e5a06cb49eed86a65f5f2909c8fbecc9d5a232bb87b989fdf5a42b47a7fa11cd7e7b34389dacfa687aceaa7173252ed39a71bf2b12551e56215077afb0a97d92300cce574ea197318fe5b7b747215f84497b6fddab38e380dbaf0b647ada03f48d404924bbd17e7cac7e0c948c188ee1d", .None}, + {.Sqrt, "603dd71767d7e75cdab2fffef89c874a5479cc01286dd6884cc68e018e31a1b15de6cb912acbf30e16c3cb324aee6ad5de831437dd0d897019f487c436c0f521fc5f92b14933caf53745552688c52905736d7b02dbdc9763bc88e46a1d879020171eff1ec9c6f0c454219f1b3a68ed8ca01cb4462f1d517c315c21106bbeb3145163cbf780ade2501c92d0d09774521af9d3ace6ea5853eed4fe0cef488c914bc951731222957adb1cb0b78f32cb15bf1344b0adbc0041f88914610738573d9a74660aa067c0bb84ba064c2dbda14d75d7410f210ee8dde7aee29b0fa0f0fb8b2a5d0b21b6ce3cce73595e2586fc5b10e45e70cc0c156a0ae52af81cf5540768320cf5f27e569c150c640d0ad2b9384f62b3a26b2a3505391737398186903555e9795be6fe30fe03a9f20fedde996c1b830d1d0ed644dd7c5f841d014093c692a1bba471ed95dca5b1de5e525773eaa081b0084188d21e984936f769b7ce7f0aa52e072b70409540a26711b310cc68f5beda089978b2814359e014be89d247dabce608291d47a09d8733d48b3812079bfe057e5189bc93d9cccbaca9396d7db93e9505a45f0662506769332e19d40143f542dafaa4fa7b724cf430309549b2d5637dd9ae554f94a20774bcf544d2d98314e3f4983cf2ec4b95276993328e647d12a5cc0721dfee85805a06c497e2400b3ede8f91508e17b2cdd1e80b24558efaebc15b75d31cf20df5b4b2fdb9a221de394d830ef03ff9e53d5ee7d18edf36e10bad89c772662f3909d6ba5cec338a6687048a2edefeb3876ba5120d4d10519c7b4cdabf8f9de93665ea77121ead63befc2094dbc35b1fd86ed4a6f36cf9aac826edab700302a917499837fc18bdb2df2d176b81d881e83eaa0973cfd703c3e12430da23c5b93ce6f03291bd09f741b36fa2a304d8aede74a40269b2c0b94ea682cb24e98d68b0b98996038fa9b1dfc86300e7071175e173a16a4a3921597edc8333f23d14990ea9ed73228df5f6d7d8647d029423926bcc04ecfceabae1d3bbfbe88a0109311a1ec614114748003dc235509cca6ec5d6bd743c31d476c9b7a0626c607e8442a3dca9b94ee3ebee32c0b5586ae8c6c516ddef1633cee5fcb7c27be6accbff8a41400165b0e29463b56eb5b10b27fe12016cdccefd026c287466c8a3c31342a93b88b94ca87ec297acb4a331d6ee0f5b946dcf821b5cf138b1973aaf13df5eb966f6f5d9abe2424d18c889de6b588ed12d77ff2e45112aff89e079a48c272bb5b7239bd0d8a0c8eaff98781c809bccf19d9b2595ac6944e3b229be14a64c291eb8306ff4422ab18ec48c375a846b938d04468b49471c628b7a1ce1884836d62c128bce15e54d25d92187ec43e2ba662861309fe4665c7aa2a77ed1b0e94efbdee3ce3abf7f31afcd7ba8b1835c7acf45444cf78fac977dd41c2e410d5ce2796d9333f995d6367d029f285877e2c0058c6d3f969ad40aa8eacc062b1fbbd64ba6c85ac2473b7f314c23486c3e51b6a5d7c2eb71bb745965a4aa6c24d9342c8d1b5dcb95e8b9e2e297fb7c0b3bf4d3371d4adb6b09eb7c4d51074b626580517488d163c9182c7100ad3c0a5d14117cb5b7ea699cdcbec797859673f1d61caadb9cb19673e261dc592d89c65bbc466040025417f7a9f327d35f67fb90b210a3b9d32b7aea6ea8b476e74d6aa6bb41a536b5590a3663f145db28a26edff5aefd54c672a8a75da9b88b5121afcfa20961eb197a6a989bf999441bd73f61f1f732ea5f205091c9f196d32c732f5055a0d7ea523b4c76f4ce751f59abc438f6c4640ba2aea4ae7692060f353f9686ea2d7f6f93f3dfbdbfcfd44968d905415de8f8c354fa6ee28f1d57e6f1bca94b5d536b3e7c37154113093c841468f57e6de4f3395c6a70c322b353bed0b1430998ac177b1bc382981203463dd31fbd0e7fddb0190a88df387b58edf6d4116da83da5d502bb76f12e5ea4c807b7b1e5853027fd5382bc2bcf785fc0e0811996f6634aa8608b3847c1e4a7129b81020eca903f67b49ae3a707428a838d816364a8d1f02bf4f100b1998543a68f4c6ec66c9792916ede963d5c6e5737425ee418c06f08aa5f1ccb210ee29371", "0", "9cf6e68976326c84e58a28dd0f8a12f3f66b8ae1859e2b80795bce5579cdf7893d173cda69aaebd8ae32bf0b6676b9556550e7729054f6c86f904e1f5d69a98d139a9134631ac6f1f5f4ae413608c560af5aa875ebf80f5ce3ddb9475503e44f451bfbd9c5438cbbaa65ba1acb2220cbd563d750bc45bd0b6e71ed4b728cf4d6923806e604f23cea089b7fa62fb3000ae2d4a27e8f97d5255bceb80c63440708deddee87f3a928bd3986f56e6261ae72bbdea2efe8c3c524ca0d88bac6c27e4cedf9ecd204d471198230272b521ad8fe3da6e42acbf1310cfb5d5b00c3d9c7c6bb683cf75e96b1b03c63bdd550dabe227bb35a6eee71fc5d3c5bedd38ba0746bcfed6d5090e956a6ce5c43e2e75ebd1bd877533576e048d7dee1d8cad24c80c47ec2ede5c5528be8e503e4df2d38ec8df515297510af905036a1286ef42a4e8bfa15284fca86a2d494b123adf5ab38a3086665aaca0bbf15bb14afb146c6b7fdb3d0c951ef4c4fa80b4e30c73d576ab1e689bfca5a5fccd123699b37850e3348506b1f6d381d65df22941ac9dba7c71b661d5eaaba0a7e0e32ce18e039a4e9282de90589e29934d345fc3fb37edd6addfd027495cefdca8deda65f05d5b8d5bbac4c299897f3073e9a964ab3000f246c150010a71b9b0e70414c0c6bc754bdc961199ed9c5530733d7555f8b3cbb9e0167bd53897c035aadc80be3404d874bd75ab882d1e3e70010eca1886fe86625eb4ce6409321c5d298a8af642cb2deb9d9f615f5e45a9b692374de01e738b48ca354c83a3552a03da91a9efb2a7d370cf435b2576e1549ea3148a28e14cbdc7ec933150fadbe461e3adeb4019719a76a1524c0f5ee2cfd940bd3d71deb9ca23053d273c749c4b7983146da39de8bfdfa4cc288b852ae76f1cfbc4402ae03cc1b35e538700ed41fbb66300feffad5d471151ddf0ee8a190f5cfafba7f6644a31b678e63947c1f6ac88f378627065eb59ffbdb7c6098e6b5fb9f3080c245a200fceb47e46874b2c180f50e9136ffef631cc163d7f5fe4c2b47912d24e50a00ef", .None}, + {.Shl, "-ab04068b1b21c08b2dcb8f5766d1c6edcf2ddee33c5e9fc97052578a50042312c77f167ce389e09b7470bdd654f3504155343ed4432cfc78b70fdb169dc3df3790f67ee71b3d4b5f7558b21d7999931b0f397e3d923bdcdb74749e9e59f2e4b55c7881fede5422635142edfd62e70ab0c59912602970a44eedebd209ed1aff3a483efbeed7f1772d820a54c2887500da0f3228c5c29ac618c937d2234dddc1edd4cd89415ee250ef3f16756fb040b7343259a2a626f1e93385609afb326d9c103e3e16733a5c6e5388ad7554243cb9f1103ccefb5e9df3bd4e893faa7b0f2d9ec426cf9cb6cf710a1e52db933fe314cde8dc073efce24d8aef84be7ed853d0ed6dea6a73986eb36df079cf6998790dedbb0ba62cb4f3d7fd424ff1361547c21a556560411a7c614a6d072b635edc942f161c83a7cb535052e64b2758adb7cbb2a1fc55b581915282622042b88731305e71f43c0ececcd2b2a91e00a049d41b9175612434b702447a4da600e1050491077d10b597a7907d3199addb3ae1805c7d247c3c2f6b3f7660c2dea05d3845a9912f763ed777cd683156da3725c36102f87b5a07b6705baa55535e409b4a785cb6aa5a26b6a5a45de7eef31b9398e4e720d85ba5dc1218e90946c3ce8f6e6b5b73c1cc73c246fb92047661a8f18a59b54ed5575d941f871472e5656818c18c6b31023c7391428864c7efaa27f972782fe8885984bf915a1314abc9849627d619e19654f2a0a835b4531de476eebacac809f038541d37ca653fb6497b56d5784ea65cd9e3df3c7b909adfcf8d02579c942794e8dcfffffe5ca8c3a2090defea99241b73a70cad39af63558b16f9214b69ca1660d2134ec8950155fafe7c9e24fcf39f0f71d7c0f34b11aa5ea201bcd325c3564e49a77c688c475f6054b48e8b46395bce00964411be5e589ae77de021d2d7ae954b7569cf1725d26a086c9ece6a5cd3b72b3648b6761f9bd02506771f701ceac70699bf0fd75346f37c4b05e8a23a9a479d711254879e9a475209270ffedc8657a297e4f77afb477995efac27c2c2f5c89cb61d9eac848b6f4482b250c3e30815a91a1586dc8dfac82f78274482f24b3c2c15c13218cadb034dc588c4ac2033b074669dca3ba63deb2b6e5e7302047ccbe83dc2614e207e9edf2b5a8235c185a5f42f34ab5b72bf2e4469de4a475ce508afadf207a772cf87c26d936486a561073f3a38d1bb4c41aa4ea0877af339eca1df9a8c6c266579a05cfcbcc9046429177fe7f8c916170338100f278a0cc33c143a1e0b1551752ff4dca216877464b94b0201115a640f826e8232c3c1623ef9aa9d4af1ec02053e5f8a03a01d5baa4515c7911e490720c3980c3eb1a1dde5db9912f7e8ca21a94dd6b7365056cfe2dd053341e3c7fe747ae875a87b0465aa327ec36461e38a9a1492a828da4ea0398ddf866242781f630b4486bb7fc359ded74e5e2f236c2afbeda63b75c576ac049693290f66555b79953a1265d8c4e243de7ba02f837bb0c5a022c4be915bd1a90b5ecbdf8d3b4a6f3935bda94b9f3ec4e9ec41389f1a66f787faf1d7c824911d1302741fd4aabab170a1c45bc13478c36f1fcbfef01a42c4703cfecd1020c47c3f0eb53c25b6d0ed8e5eb238e2dc53ab8ce5106809bd6dbbee9c83a68523261d5b8906c218da937f9035faa203a7a778373eee3f92e286f56029839f14d029f9838555458964e44e39bc122d93b89c023e6488e8d2d407187b5435f4f0b9bb97994f0a8c85c5e21a394c02425f4576456f0ed7cd5c411f4b5359819de937c225246236b523049f7b8949046e0baa7ab7d5744a6ce4433ebdc61bf4f6a9b5e8429e8de10cbed556805b26d3cf7229ddeee2ef81e0d0caf192a59b54c19cf8030cca9664fa24b8553a006ef277b87dc36bb0a542cee18b5514aca38fe1171de774286b9426223a6261a3ea5c01cc61cd5a1d5bbd1f8b47809c15bda2628155fd85aa19cefb0a6f497b7a9155b6f277ff559082e32b89207e5476d5c61c7d02b2454bad7307efa5a4524d2ace475b01f83ed246d63963b9dd2c3c22447361cf04f7756013f51266da45f4f8c716a2c43d2dfb8e9b35884d7a8639430a6d", "168", "-ab04068b1b21c08b2dcb8f5766d1c6edcf2ddee33c5e9fc97052578a50042312c77f167ce389e09b7470bdd654f3504155343ed4432cfc78b70fdb169dc3df3790f67ee71b3d4b5f7558b21d7999931b0f397e3d923bdcdb74749e9e59f2e4b55c7881fede5422635142edfd62e70ab0c59912602970a44eedebd209ed1aff3a483efbeed7f1772d820a54c2887500da0f3228c5c29ac618c937d2234dddc1edd4cd89415ee250ef3f16756fb040b7343259a2a626f1e93385609afb326d9c103e3e16733a5c6e5388ad7554243cb9f1103ccefb5e9df3bd4e893faa7b0f2d9ec426cf9cb6cf710a1e52db933fe314cde8dc073efce24d8aef84be7ed853d0ed6dea6a73986eb36df079cf6998790dedbb0ba62cb4f3d7fd424ff1361547c21a556560411a7c614a6d072b635edc942f161c83a7cb535052e64b2758adb7cbb2a1fc55b581915282622042b88731305e71f43c0ececcd2b2a91e00a049d41b9175612434b702447a4da600e1050491077d10b597a7907d3199addb3ae1805c7d247c3c2f6b3f7660c2dea05d3845a9912f763ed777cd683156da3725c36102f87b5a07b6705baa55535e409b4a785cb6aa5a26b6a5a45de7eef31b9398e4e720d85ba5dc1218e90946c3ce8f6e6b5b73c1cc73c246fb92047661a8f18a59b54ed5575d941f871472e5656818c18c6b31023c7391428864c7efaa27f972782fe8885984bf915a1314abc9849627d619e19654f2a0a835b4531de476eebacac809f038541d37ca653fb6497b56d5784ea65cd9e3df3c7b909adfcf8d02579c942794e8dcfffffe5ca8c3a2090defea99241b73a70cad39af63558b16f9214b69ca1660d2134ec8950155fafe7c9e24fcf39f0f71d7c0f34b11aa5ea201bcd325c3564e49a77c688c475f6054b48e8b46395bce00964411be5e589ae77de021d2d7ae954b7569cf1725d26a086c9ece6a5cd3b72b3648b6761f9bd02506771f701ceac70699bf0fd75346f37c4b05e8a23a9a479d711254879e9a475209270ffedc8657a297e4f77afb477995efac27c2c2f5c89cb61d9eac848b6f4482b250c3e30815a91a1586dc8dfac82f78274482f24b3c2c15c13218cadb034dc588c4ac2033b074669dca3ba63deb2b6e5e7302047ccbe83dc2614e207e9edf2b5a8235c185a5f42f34ab5b72bf2e4469de4a475ce508afadf207a772cf87c26d936486a561073f3a38d1bb4c41aa4ea0877af339eca1df9a8c6c266579a05cfcbcc9046429177fe7f8c916170338100f278a0cc33c143a1e0b1551752ff4dca216877464b94b0201115a640f826e8232c3c1623ef9aa9d4af1ec02053e5f8a03a01d5baa4515c7911e490720c3980c3eb1a1dde5db9912f7e8ca21a94dd6b7365056cfe2dd053341e3c7fe747ae875a87b0465aa327ec36461e38a9a1492a828da4ea0398ddf866242781f630b4486bb7fc359ded74e5e2f236c2afbeda63b75c576ac049693290f66555b79953a1265d8c4e243de7ba02f837bb0c5a022c4be915bd1a90b5ecbdf8d3b4a6f3935bda94b9f3ec4e9ec41389f1a66f787faf1d7c824911d1302741fd4aabab170a1c45bc13478c36f1fcbfef01a42c4703cfecd1020c47c3f0eb53c25b6d0ed8e5eb238e2dc53ab8ce5106809bd6dbbee9c83a68523261d5b8906c218da937f9035faa203a7a778373eee3f92e286f56029839f14d029f9838555458964e44e39bc122d93b89c023e6488e8d2d407187b5435f4f0b9bb97994f0a8c85c5e21a394c02425f4576456f0ed7cd5c411f4b5359819de937c225246236b523049f7b8949046e0baa7ab7d5744a6ce4433ebdc61bf4f6a9b5e8429e8de10cbed556805b26d3cf7229ddeee2ef81e0d0caf192a59b54c19cf8030cca9664fa24b8553a006ef277b87dc36bb0a542cee18b5514aca38fe1171de774286b9426223a6261a3ea5c01cc61cd5a1d5bbd1f8b47809c15bda2628155fd85aa19cefb0a6f497b7a9155b6f277ff559082e32b89207e5476d5c61c7d02b2454bad7307efa5a4524d2ace475b01f83ed246d63963b9dd2c3c22447361cf04f7756013f51266da45f4f8c716a2c43d2dfb8e9b35884d7a8639430a6d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "c71f16c06840abd28563e67c3a345e9796afdb2ff1d85819cb23eef36fbaa60a335fdaa0e95013e43f600d422f87572886d6526e46452b8b6cbe7b101e3c5f8facee518d19e5bc9bb2722d42de54b8c9e1466fb3e6062abb1a0d23d466777a35fceaf3d543537d6cf5249d4696be1d2fefa6764c7e37591b48880f4ade85c9f77b951603961a4573fbcd67a7e2b32d019d021bbfd5bc84bcf673df2f1c78f7291de35f6b9ee4554e096a28a3d12ce3e4944be4a83c7a153d6fbc063d01edd87f79d72ab5da401d286268dca7941ba45b7e442e5581b31b535d0fa57eb9f4496f180d90618f74a79c6fa59f7e25082995a1016bcbeb26fbb29db5900d9169abd369cd5dfaaf447a24240530de4c2ee7db7536cbfba3272baeab5dfdaa593a9413f58e6caa291c36f0bbfacdbd85b4891bbea8ae25b39a760d9e596a500145afaf9f784fddb1ab260d6056df4748a6462489e4063de5ab4f79b26610ed040f304f4cddbccec31cf1a701b8dfb263a5d2f1da9c55db04e858bd26e756940ebdb14b7576025209f540eb56e9adfdc2dac2df0d10ce4746acf57db53ddb2c1587b9ab5ba4f59f35fce763403044b88ec37ce47f5f2ca0afc1fd62cb5b390db01a90edd7b5ee22bed0f9f32e40a90dd2c1d468ca69c757f13349515225d2be9b7219466d0fd37c48b839161eee22e4ebae29b0c3437b384036da0c981db9a63331e95fa8ebf952b8db500b20c0e2a93eceac74c70f996bdce3e3e9f602971ec2d5277d2bc3ef7926555af312075bd908f0fad4aa96c27c2839bc946ec6d461947a507c057f2142df50bd3e9c3d340b871f80ca2de8d87d3cbfe4a4c9aa01044ea53203016d225b13586f5c413188630cc04c4818e851d071a3ec36e2f41a640c858ae8600c1f17a65bb7cada01053996a89ffa9b5cca4b32bb67d7307e11157d96e3a8c45f8ce48e058b14d24b296431e5e6cffdffb60debe8cea8872a718be73561bd3de58c0afe6c3ffa972b22209986c7e2c29610b6f3d76f68be2573a4641b992570393265d8df74c9a656806d54ec8c8977ed5f16f0098e30bb1d2f854787a97262e9717f40efcccfb55fe8714d0dfa7aa856b14bef910188ff9d97caf4b1d53f1f567414d9b34ae032e478f2ab14a05912a0cb1bade53d9563fa280433031164b9fe3bd7d2a771845e380abefb9d83442381b0d1b67de7e9f7d74993b2fd4eeb1b1819fb96466bbaeca68fb1699d5d722dc5edb3bfe061f5d4150e209e9712e274c21eb61fec83ef0abb6646c97d8035f432a8473a4006b195741ecfc55662502d5dab18c1ae85d325c72dc75cfeb6b0c4d0bfdd8e1f57948fdc087b007a976309a730a12e10c8375ed08c84d9232ba8e1a511e6b5567c9539aa241e0e570256798f5a7614c504f569f62e41a9622e60651b4d4ae28e28fb544637f8cd2cf7b4f4d6409fb67c31c9142d12256b4e42bf298f6058404de7fe19f6c384a2d2f66132aa013e19d29005bd0bc7bfb69bc7e5bff8711abffc0dd117a959095853ddfccd059c4a12b90ffbc28b95b65c40e4e113b350f8ec72d032c85ab626968d759991c0c0a82ef79db964be022df458c7ed8249b5636fa80310c172671f828ef519049f3b9e6c772b7d4ebdfe3e1ea89688051f938f624632c33a391f32146ba1eaf60ad5d32a04bbc25edd96267c7e5422a391fc190974bcd1b58533cb574cfde428c17e08c645ea6fa9460e20efacd42a3f40f293705cd76e039f46dfa070007dbd89d48b944010605224067cd53ae9dcfc993f449895b546899dfd7ab90c9b2f149dbde708e23d371ac685b6511a9aaf26b651be51e1253a5a021312ded5acae4aff62b13b7d482b191ce7e381d75ff5eec9d835ea59e1889319e6f53c106b79b4984ec5d93fd50a7540c21bc7da17f66d4678ba9208b50cdf26d3255e9cde2dfb39e3d8ab5508092a63e74a95193bdaba37682d57cbce3dc88fd91f3d1cd91823d3ea6ac99ec859d8f967b6e7be6390034ccbea1eeb0f482c099dd7dc032564250efabc92ca61ee2e7aa1a6d7ba1e477a2ba6385c622609f67dd275e640460a57853b71b13c0c674b7527b30975b979593a4508e7a512ef39239fac", "b4", "c71f16c06840abd28563e67c3a345e9796afdb2ff1d85819cb23eef36fbaa60a335fdaa0e95013e43f600d422f87572886d6526e46452b8b6cbe7b101e3c5f8facee518d19e5bc9bb2722d42de54b8c9e1466fb3e6062abb1a0d23d466777a35fceaf3d543537d6cf5249d4696be1d2fefa6764c7e37591b48880f4ade85c9f77b951603961a4573fbcd67a7e2b32d019d021bbfd5bc84bcf673df2f1c78f7291de35f6b9ee4554e096a28a3d12ce3e4944be4a83c7a153d6fbc063d01edd87f79d72ab5da401d286268dca7941ba45b7e442e5581b31b535d0fa57eb9f4496f180d90618f74a79c6fa59f7e25082995a1016bcbeb26fbb29db5900d9169abd369cd5dfaaf447a24240530de4c2ee7db7536cbfba3272baeab5dfdaa593a9413f58e6caa291c36f0bbfacdbd85b4891bbea8ae25b39a760d9e596a500145afaf9f784fddb1ab260d6056df4748a6462489e4063de5ab4f79b26610ed040f304f4cddbccec31cf1a701b8dfb263a5d2f1da9c55db04e858bd26e756940ebdb14b7576025209f540eb56e9adfdc2dac2df0d10ce4746acf57db53ddb2c1587b9ab5ba4f59f35fce763403044b88ec37ce47f5f2ca0afc1fd62cb5b390db01a90edd7b5ee22bed0f9f32e40a90dd2c1d468ca69c757f13349515225d2be9b7219466d0fd37c48b839161eee22e4ebae29b0c3437b384036da0c981db9a63331e95fa8ebf952b8db500b20c0e2a93eceac74c70f996bdce3e3e9f602971ec2d5277d2bc3ef7926555af312075bd908f0fad4aa96c27c2839bc946ec6d461947a507c057f2142df50bd3e9c3d340b871f80ca2de8d87d3cbfe4a4c9aa01044ea53203016d225b13586f5c413188630cc04c4818e851d071a3ec36e2f41a640c858ae8600c1f17a65bb7cada01053996a89ffa9b5cca4b32bb67d7307e11157d96e3a8c45f8ce48e058b14d24b296431e5e6cffdffb60debe8cea8872a718be73561bd3de58c0afe6c3ffa972b22209986c7e2c29610b6f3d76f68be2573a4641b992570393265d8df74c9a656806d54ec8c8977ed5f16f0098e30bb1d2f854787a97262e9717f40efcccfb55fe8714d0dfa7aa856b14bef910188ff9d97caf4b1d53f1f567414d9b34ae032e478f2ab14a05912a0cb1bade53d9563fa280433031164b9fe3bd7d2a771845e380abefb9d83442381b0d1b67de7e9f7d74993b2fd4eeb1b1819fb96466bbaeca68fb1699d5d722dc5edb3bfe061f5d4150e209e9712e274c21eb61fec83ef0abb6646c97d8035f432a8473a4006b195741ecfc55662502d5dab18c1ae85d325c72dc75cfeb6b0c4d0bfdd8e1f57948fdc087b007a976309a730a12e10c8375ed08c84d9232ba8e1a511e6b5567c9539aa241e0e570256798f5a7614c504f569f62e41a9622e60651b4d4ae28e28fb544637f8cd2cf7b4f4d6409fb67c31c9142d12256b4e42bf298f6058404de7fe19f6c384a2d2f66132aa013e19d29005bd0bc7bfb69bc7e5bff8711abffc0dd117a959095853ddfccd059c4a12b90ffbc28b95b65c40e4e113b350f8ec72d032c85ab626968d759991c0c0a82ef79db964be022df458c7ed8249b5636fa80310c172671f828ef519049f3b9e6c772b7d4ebdfe3e1ea89688051f938f624632c33a391f32146ba1eaf60ad5d32a04bbc25edd96267c7e5422a391fc190974bcd1b58533cb574cfde428c17e08c645ea6fa9460e20efacd42a3f40f293705cd76e039f46dfa070007dbd89d48b944010605224067cd53ae9dcfc993f449895b546899dfd7ab90c9b2f149dbde708e23d371ac685b6511a9aaf26b651be51e1253a5a021312ded5acae4aff62b13b7d482b191ce7e381d75ff5eec9d835ea59e1889319e6f53c106b79b4984ec5d93fd50a7540c21bc7da17f66d4678ba9208b50cdf26d3255e9cde2dfb39e3d8ab5508092a63e74a95193bdaba37682d57cbce3dc88fd91f3d1cd91823d3ea6ac99ec859d8f967b6e7be6390034ccbea1eeb0f482c099dd7dc032564250efabc92ca61ee2e7aa1a6d7ba1e477a2ba6385c622609f67dd275e640460a57853b71b13c0c674b7527b30975b979593a4508e7a512ef39239fac000000000000000000000000000000000000000000000", .None}, + {.Shl, "-5828305117ea024d01680e37bf664a7e0e430ebe42d365abf69a222bf4e6b5e16374fab2fa27058928e4a71ed5cf258a047a7871daf42dccfec7d9414b67b0b58477c64fafa3f9a41dd315082d546efb5c0737d74ea843fcb074b98f5c14526daad414f17540bfa77e3699318e2f27df71b8b5852dcae0323b160c6c85d934ee7bd1e1241a14ead2efdb654ae03a1ecf551c78d83fc23d1cc7675cd922e0031eb69450e9d2a80369b1e7f0c23a167c6e05de0b1e6069b2887e6ba8011414f6d5967295e6a9aa7ea46a3dd5fb4271e82dc0ca6f9d690ee7cbde2fe606b41ddc6d4d6b4d396d3123a6c6c73ac568c26a79aa5ef0150fbba5c2c8ba4c63a20bc2848888c9896083c5531de24b162b1abeabd93c71097ef00ed1439182a0273db937592265eb0b5f559db7193be104818847092f491dd5b9a8ea09ad0af12b9ade1d478baf3e09417ead5b128516c457e5a6d2a57168666e349c6d0c0876934244973468dc074af70f735375e7cf246ca8447a47b761b3f14851b03a3c185727c869e7d9a383561258d866f0a2dbd7379b171dcd3cef61b129cca565f1d4e90748d382cf506a2d95c274dc59bfaa93501affa923f7fdd4d13d2e1d8ecaa436bd8380c6a454e09a303573163316d1c755461724c6588a4973abde9d229f6c9153e44a654e5c2649979608d0c2e0939d848c7764e4cecc406e166a6dbf0429be20a0f245f6eb05a0f14f222eeb39fd91e4628f0c23b9baaf8872a52fd12233c2144faccde3b8ad9466c4125ad09b0ef9e86a3135a40276b68274f3930f2bb85b2f8d0017d6045015041399f1e1dfd6d8240ce83c9e8cccc463eb984ab039e6615bd17b41b8a8af481d83e5ce634f74d678d80482fc4dd7625c1f9c7e46e4d491f566aa743921732b9d5169619c082d62b27c8a7f6efa7f573e6331802b004614bbee5039de88dc7fb9ad5cbec38bf96c34cf15490c7aa6f6e204940d93475ba5c769f36278506c5424e3d4e4c5995bffdf79324ae3cf384944fe25d61c79603308019cae40d5551a99a50920d98c9c2381264bf72ba29fe3deb20027d0e10b43a13eda82a9acd0e74fd3f5973ab31e8953a358b73761d3e77772a38a294a3e683e2f1c8503b8d3db0739d213247c7bd191156e9f60cd11eb3ba356169dc97593f199cd5f4c6b45672811fa41dce9c80d080d6eb7e369ad0c465b9689f4a0bc13a26652844b7d458c2a72d0f6e052829fc0aac0fe2a27fa504901b7323f2f51513d4b0fb42f2eb649c8f0dc0df66fb325d6fd236e354388f1a79d31b243586842a772e0778dab5d02af70de158e03ec1c947bacebd2b4056f3fcdc2d4ef5a44d2dada4eee157f3ca8a4e4890b898c3c95d565579cc362add295014ac21c0602b518c65945ed023e2ccbd871ae986a83e83863fdd197c8985bfe5fab5b3b22fad7775b2efa234180d1df3bab9b3c3977869f9d55ba54a6a1b8438bb9043f431cabaac30e4804b31eb7c891a0b05880a6bbc9dd28342d12f0bbb5a8f9cd7cd1f35716854c9f00b5725a379fe244deec3b9f83f352540784556608a19489d38ff4c643920fef3348e789089bebf02a8cc6ddb15c99aa50766ce4f959985a734d166dcd473cb780dcc373025ac237adc24d09a92d137e30798e44993c952386dc16adaafe6437bbcb610dc6346fe594a8fdf9025439d73c7dcb38f2bb90d43298231e7d211a2a6bf4f5132f3c82da7051a70865675ad23f017b44f13216c6393e6500f6e9f26394fcc1a81d828f658defa7aa172678bd6b9f6e45d6da1f69cd3f7715b0201f6ee89a37063e53d888dbadbfe5673dd87f1f25bf1526e0cb1dc73887c5afacab467b48e1d7e575c9541e5faa471e8b3a33ffde2255648b9b16eb7efd000df0d9e4f36afcae6229beaf1d163309d5a41fb4c244dc875a08d93cd12d3f6b12a768c76bc1a0bbea5b66c524bddcade3db94899d2ca463617e2ffdc52ce2602ecfc2c6623bce0d57c328c6a3a6fc3bea966bc856b7ee5cdaf913272568351a5b9445b51f0bdbe6973cefc1c89119f44ebd3123192b101a96aceda9aaa8dad2a596276e4e670df1e9586c92270726edbaa346c301ee8e907a3ef96823e57c", "21c", "-5828305117ea024d01680e37bf664a7e0e430ebe42d365abf69a222bf4e6b5e16374fab2fa27058928e4a71ed5cf258a047a7871daf42dccfec7d9414b67b0b58477c64fafa3f9a41dd315082d546efb5c0737d74ea843fcb074b98f5c14526daad414f17540bfa77e3699318e2f27df71b8b5852dcae0323b160c6c85d934ee7bd1e1241a14ead2efdb654ae03a1ecf551c78d83fc23d1cc7675cd922e0031eb69450e9d2a80369b1e7f0c23a167c6e05de0b1e6069b2887e6ba8011414f6d5967295e6a9aa7ea46a3dd5fb4271e82dc0ca6f9d690ee7cbde2fe606b41ddc6d4d6b4d396d3123a6c6c73ac568c26a79aa5ef0150fbba5c2c8ba4c63a20bc2848888c9896083c5531de24b162b1abeabd93c71097ef00ed1439182a0273db937592265eb0b5f559db7193be104818847092f491dd5b9a8ea09ad0af12b9ade1d478baf3e09417ead5b128516c457e5a6d2a57168666e349c6d0c0876934244973468dc074af70f735375e7cf246ca8447a47b761b3f14851b03a3c185727c869e7d9a383561258d866f0a2dbd7379b171dcd3cef61b129cca565f1d4e90748d382cf506a2d95c274dc59bfaa93501affa923f7fdd4d13d2e1d8ecaa436bd8380c6a454e09a303573163316d1c755461724c6588a4973abde9d229f6c9153e44a654e5c2649979608d0c2e0939d848c7764e4cecc406e166a6dbf0429be20a0f245f6eb05a0f14f222eeb39fd91e4628f0c23b9baaf8872a52fd12233c2144faccde3b8ad9466c4125ad09b0ef9e86a3135a40276b68274f3930f2bb85b2f8d0017d6045015041399f1e1dfd6d8240ce83c9e8cccc463eb984ab039e6615bd17b41b8a8af481d83e5ce634f74d678d80482fc4dd7625c1f9c7e46e4d491f566aa743921732b9d5169619c082d62b27c8a7f6efa7f573e6331802b004614bbee5039de88dc7fb9ad5cbec38bf96c34cf15490c7aa6f6e204940d93475ba5c769f36278506c5424e3d4e4c5995bffdf79324ae3cf384944fe25d61c79603308019cae40d5551a99a50920d98c9c2381264bf72ba29fe3deb20027d0e10b43a13eda82a9acd0e74fd3f5973ab31e8953a358b73761d3e77772a38a294a3e683e2f1c8503b8d3db0739d213247c7bd191156e9f60cd11eb3ba356169dc97593f199cd5f4c6b45672811fa41dce9c80d080d6eb7e369ad0c465b9689f4a0bc13a26652844b7d458c2a72d0f6e052829fc0aac0fe2a27fa504901b7323f2f51513d4b0fb42f2eb649c8f0dc0df66fb325d6fd236e354388f1a79d31b243586842a772e0778dab5d02af70de158e03ec1c947bacebd2b4056f3fcdc2d4ef5a44d2dada4eee157f3ca8a4e4890b898c3c95d565579cc362add295014ac21c0602b518c65945ed023e2ccbd871ae986a83e83863fdd197c8985bfe5fab5b3b22fad7775b2efa234180d1df3bab9b3c3977869f9d55ba54a6a1b8438bb9043f431cabaac30e4804b31eb7c891a0b05880a6bbc9dd28342d12f0bbb5a8f9cd7cd1f35716854c9f00b5725a379fe244deec3b9f83f352540784556608a19489d38ff4c643920fef3348e789089bebf02a8cc6ddb15c99aa50766ce4f959985a734d166dcd473cb780dcc373025ac237adc24d09a92d137e30798e44993c952386dc16adaafe6437bbcb610dc6346fe594a8fdf9025439d73c7dcb38f2bb90d43298231e7d211a2a6bf4f5132f3c82da7051a70865675ad23f017b44f13216c6393e6500f6e9f26394fcc1a81d828f658defa7aa172678bd6b9f6e45d6da1f69cd3f7715b0201f6ee89a37063e53d888dbadbfe5673dd87f1f25bf1526e0cb1dc73887c5afacab467b48e1d7e575c9541e5faa471e8b3a33ffde2255648b9b16eb7efd000df0d9e4f36afcae6229beaf1d163309d5a41fb4c244dc875a08d93cd12d3f6b12a768c76bc1a0bbea5b66c524bddcade3db94899d2ca463617e2ffdc52ce2602ecfc2c6623bce0d57c328c6a3a6fc3bea966bc856b7ee5cdaf913272568351a5b9445b51f0bdbe6973cefc1c89119f44ebd3123192b101a96aceda9aaa8dad2a596276e4e670df1e9586c92270726edbaa346c301ee8e907a3ef96823e57c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "16fcfacddfdc335e161fdf86168d032d6bf86c3f5b95e32c3a8fabe02139bcc3ca713d4dd61cb2271f696ff914d1353cf86f52bd9983e34bfc4c7e31ba288c63f259f8d84982126f2dc1d8299d589c3951db8480886a9276a6e8f3d1766b230b35cc0403e9cd7b6dfa1710b2949d45bf8adc078bfebfbf28f519adc93890fded174e65e9f28bb1dd2d66cf0576134943119e263bc79e227b87edea360a3b3f985f68c687fd78f2cec45975035f7bf9fc791cdfc3e032c3ab43aa31f3b932b6f246ca4c0e57888225d2705fc3fd0f5ca17bec71bf04b9962661f2e250266eeb78fd113a4f8178b8885b13bdd2930ff2bec9744f3b15831a1285e3a5f4d714546105e80a8fb89086b7918506996ba06f557f120410d5f0f63da9f3372a41648764c9f3b2561135bd9c942b911eae280e984f708723774052a6e035d3761ffc5b4baf9c5ae64e0ae0badbbf4d4035e47bd2bf65120aafda2d001f0681fd0cd11e9e8a4ac48a5201810d7d117492386095ced568237201246aa30543f95806ab031ae3eb265b3fa2f749c033528d32b9aa6c3f0d1e527b96b0088b9f62241c49f83c0812ff16d655438d91c35ec3e6d937e85c442dbb285df24520d95a4e94c0866f269a9a4e2a9553fcd2b4f8a8c60b9e41d8272369da3a7841c2ee2d262588e48e730f9b4c95d923436b63141c4c96ec16c2c433639bbf0afe93ca24eed69d4294ac35b5179d60d0132a2b9a14376dc12c097bf27f48a9c7e661126f37140571997a5e3ce6a1de9e1330974728631d3de410a3c4bdef251e044406a8cfe3b23b018feaebbe88c4a9b3252520390ea3e758bec834f0efc9a6173ad2703b7b095311995fff8b10bfa12d0fbf5a79cd63587aee10af2531a1cb57dd5cd4009d7a6550cf91a388f1da4179d5a497e41251d522e98c9d02b20b0c7347d16c8ef9608e7e8f524686eb18ea72e848793c9b81ad2681f6d74e402a50887d38f945b912ec1484385083e5210f4429c8ed5453ee3d20b0fbaff0b5799392412ffa33e68f7d27f851df00ef277b8d8bf3c17db18a1e53da3a38a4b7beecd78363748e015a0549627277b480105c15ec9ea41d07ad7c13e869fd962e356db3ad2a04ecd09f73559f5aa3ce8e4cb14f45e14a3b9ead5dd0a8bf589ed37f47ebf41b24b656ed95e98107f0c410ce7d7da0d098551b52d1995fb71f85244bfbd112d5c9aecbf83355889cf173715751a2cf7f224cca0551f10af1fa8d1ee0b39662c125343795a41b3e880ff18758b54d9fe3113ff0b12dc185f1e3ca55f57dbc0301d3d5f246fbe955b29a75cb45acb25b2819d137af026f3a4ceb12b467ed95567c882850a59b6111571ae356f56eb1e6af7b6c36a3f249897609fe7e1eed2fb9e0973fffea13a4de5758c14ef6609ecf7768a2803a20bad8624882080c42341382670da35fe7ff2e3f10c97084c66fdb28f3bdb046ad54ca8167c8c673e7a7993cf4b67379020ade8e5db32d1f571d68469558a447acd21b679efe8b8575941d2d9a636c0d13b9400e43eaf9c87ff2f938ed717ab8874d8d61c04384318f957c6f2e123ed1cbb53df151fffe2715927d180318f083220c83d4173d5efe659f75c5c50720917b844a56315e768f2acdefe2067b9498540dea450bc6f4b5b1498c36a2af8cd23cb49eff78d77977415953f452c3f24b2fe80ad6ee66256589f40d0677d6e8a5ebd0419611b1d739cc648fa5377dac550c0eedc07671fb149ed21660d322a041b61942697278eadbd03789edd8b1021407d530e0df540a9c200aeb72be42f1677f8a2bd485ffbb566a85b92082ba4446c28d14ee9047405709c68e98ab4b7f7d6187198508f147597e36a30e2746dfa52b8fff567f987f2fc16cbb329fe4c0e2b01ee7f6b9e8755c845df0556f8467d478654d3d96978620bdf7433b35d5722a6a9a6644688dda4212fec6060711e8170762c3d5a968eff2c91f0f6b0b337e34e19c6e598d7cae01749beea7dc8248d19511fafeb008ff2468ba223a6a626d9b353150a45af6d228b9a7da71a8020dff8f88287c2c17819416d60cc31b9342ed0f7d75294cbb1cbf1b960c919131a3d51a800399a35238ad60720413289b", "78", "16fcfacddfdc335e161fdf86168d032d6bf86c3f5b95e32c3a8fabe02139bcc3ca713d4dd61cb2271f696ff914d1353cf86f52bd9983e34bfc4c7e31ba288c63f259f8d84982126f2dc1d8299d589c3951db8480886a9276a6e8f3d1766b230b35cc0403e9cd7b6dfa1710b2949d45bf8adc078bfebfbf28f519adc93890fded174e65e9f28bb1dd2d66cf0576134943119e263bc79e227b87edea360a3b3f985f68c687fd78f2cec45975035f7bf9fc791cdfc3e032c3ab43aa31f3b932b6f246ca4c0e57888225d2705fc3fd0f5ca17bec71bf04b9962661f2e250266eeb78fd113a4f8178b8885b13bdd2930ff2bec9744f3b15831a1285e3a5f4d714546105e80a8fb89086b7918506996ba06f557f120410d5f0f63da9f3372a41648764c9f3b2561135bd9c942b911eae280e984f708723774052a6e035d3761ffc5b4baf9c5ae64e0ae0badbbf4d4035e47bd2bf65120aafda2d001f0681fd0cd11e9e8a4ac48a5201810d7d117492386095ced568237201246aa30543f95806ab031ae3eb265b3fa2f749c033528d32b9aa6c3f0d1e527b96b0088b9f62241c49f83c0812ff16d655438d91c35ec3e6d937e85c442dbb285df24520d95a4e94c0866f269a9a4e2a9553fcd2b4f8a8c60b9e41d8272369da3a7841c2ee2d262588e48e730f9b4c95d923436b63141c4c96ec16c2c433639bbf0afe93ca24eed69d4294ac35b5179d60d0132a2b9a14376dc12c097bf27f48a9c7e661126f37140571997a5e3ce6a1de9e1330974728631d3de410a3c4bdef251e044406a8cfe3b23b018feaebbe88c4a9b3252520390ea3e758bec834f0efc9a6173ad2703b7b095311995fff8b10bfa12d0fbf5a79cd63587aee10af2531a1cb57dd5cd4009d7a6550cf91a388f1da4179d5a497e41251d522e98c9d02b20b0c7347d16c8ef9608e7e8f524686eb18ea72e848793c9b81ad2681f6d74e402a50887d38f945b912ec1484385083e5210f4429c8ed5453ee3d20b0fbaff0b5799392412ffa33e68f7d27f851df00ef277b8d8bf3c17db18a1e53da3a38a4b7beecd78363748e015a0549627277b480105c15ec9ea41d07ad7c13e869fd962e356db3ad2a04ecd09f73559f5aa3ce8e4cb14f45e14a3b9ead5dd0a8bf589ed37f47ebf41b24b656ed95e98107f0c410ce7d7da0d098551b52d1995fb71f85244bfbd112d5c9aecbf83355889cf173715751a2cf7f224cca0551f10af1fa8d1ee0b39662c125343795a41b3e880ff18758b54d9fe3113ff0b12dc185f1e3ca55f57dbc0301d3d5f246fbe955b29a75cb45acb25b2819d137af026f3a4ceb12b467ed95567c882850a59b6111571ae356f56eb1e6af7b6c36a3f249897609fe7e1eed2fb9e0973fffea13a4de5758c14ef6609ecf7768a2803a20bad8624882080c42341382670da35fe7ff2e3f10c97084c66fdb28f3bdb046ad54ca8167c8c673e7a7993cf4b67379020ade8e5db32d1f571d68469558a447acd21b679efe8b8575941d2d9a636c0d13b9400e43eaf9c87ff2f938ed717ab8874d8d61c04384318f957c6f2e123ed1cbb53df151fffe2715927d180318f083220c83d4173d5efe659f75c5c50720917b844a56315e768f2acdefe2067b9498540dea450bc6f4b5b1498c36a2af8cd23cb49eff78d77977415953f452c3f24b2fe80ad6ee66256589f40d0677d6e8a5ebd0419611b1d739cc648fa5377dac550c0eedc07671fb149ed21660d322a041b61942697278eadbd03789edd8b1021407d530e0df540a9c200aeb72be42f1677f8a2bd485ffbb566a85b92082ba4446c28d14ee9047405709c68e98ab4b7f7d6187198508f147597e36a30e2746dfa52b8fff567f987f2fc16cbb329fe4c0e2b01ee7f6b9e8755c845df0556f8467d478654d3d96978620bdf7433b35d5722a6a9a6644688dda4212fec6060711e8170762c3d5a968eff2c91f0f6b0b337e34e19c6e598d7cae01749beea7dc8248d19511fafeb008ff2468ba223a6a626d9b353150a45af6d228b9a7da71a8020dff8f88287c2c17819416d60cc31b9342ed0f7d75294cbb1cbf1b960c919131a3d51a800399a35238ad60720413289b000000000000000000000000000000", .None}, + {.Shl, "9c985b3c93915dc604fc3019cff4d0d1535bef94dcf85e95f535e730aabb8f22cd3607a341d65df110c5bdb0079f8ad8c36b4d47e742204b21de844f8319b065c9f8473ce7b473951378eedc8c545b236315027e5ae0e85ae2796677bbb15bc562ddd5ca05003852744688b91620d7f9af12261ab330b7f9c468d274523a682257e9156e2279ae53a7cff9014349580630abc9c00371434723cd56ff611fab96c9b3620d0a19d60ab047605c9e72a85d3aa55f79867aa5bf4dfeeea3809a0d461f8efd1addaeb0240cb7e73bae60c37a194e97ab77064137522f840e44976e9b7a79079e43aa310240f32598d4ba61a790bdd635733430a27726ad3068f3e5c7731114bd6e5f739d09c4e9c0979cc8984e037c50e3727c93055ffe51c76565f8850047a7f836e53ebd845fbcace4a05a7d03f148ad8283e6415993e5b038dcc3052eab3ebbc54ee0a95f06ca9e68342b984cfc2814aa8fc21e3e826eeb8eb36e38c68aab96ceba5dd02552f09f103a5e31b3ffd6b53ba05b19490fe5e5cadbf3702e85eeda2cfd2efa777b3fa197ec7734029386e8e7e1eb7f35c14c047d88833fcdde2f0b2f8447b53d75ecc64892f3e9dfe9e41d7ae838ef0ff39509e2cd93e99ae597f8567779a26406ffa7f7a56efde2695d32608c328112fee6c587dac7479bb68c1672e5f54778650670510242fd95b348994fb04ba1257ebcd2cb82ef4c3e71222ecb46e2f42764d6461ac81825b3c7734a8a8155fab9a63da8fc7d450216a8525cba10fad4fde4b1990a42d5822e05e60285d9c99c4cb388beaf0427fc146b00c5e64073bb56add0ac5f247a7fb34abcdda492b049c2486f80dd8d6a259f509a2a9508fa4fe50d7e3e66d0561b78b073ce1cd3b763e1445334c795ff5aba63e1d208babf2345e1baec5bf56837a6069959518c26a7fb376b2c9e2cee87c16fc2418b1551730a5e2a4fc99c0b2e539051b4fc17d4803cd98525535ea85ed21158d74e972d93427a1e8e27de2c9e048b0388646c5cefaa4a20c4b89b35cced0d60a5de89182cc5e8c5479ee0cdd96d154e96136de8078c3304ed8ca5f097751b132a075004a7bde121ae4714e0fdb16788dc489264634041056c3bbe73fadec05ba9e0b8daca32d2f483b3b2153088f249f7e371e1001ac7d72488e31da1a28ccfef46a833eb6fd743c22fe7d4a1ced93d223383945e76f0c66be2251e4a7ef1cc5d78283f9ad9fbe14d987a65e373ddc9c54a30e95fc7276fa7c82c55e1a3917ab93abf73487d0be85d31fa41cf86de1c567e14b3f5d8eab101b1bc7260c74f98120b689f51fdd0df8d3d471875df2196bdb90bd9b5cb7e65b1ebfb70fe9c63e964aefd5477e337c8815a276856dfbd1a26e82141828ccb6a867942577efbdd1c6ed6b1f32578fab06ef3a7b9275c2a8131068f04e1c718d61ebcd728a93486dc7563b1738931c9da5055a22e3dd88232baaae5282782e4dd51ea5f0b72df2ab7b7fb961df07f3993359f17ac229eaa81f34a1dc69a351f011b30a60b5a4909cdaf8b215d1664a2660a2c560a2bcd27a8efb95c467a293867f835371c27f47cf6ad6cfd4d9d8f0defc42d9ff0f77259292c0b0cdcfb3b7aebd59d2102240ab1fbe402beb8dee4ca45cc0dc294d2b08e89290c9769da4df4cb28c12551d8120c50f9c3a11168b81c895427dd375c58bca78255bd4a145a1a96d1e81283c68353a822e4d5b00a08281110a5dcb2cf4cd7d282d682e923659dff3ac4f0ec4b8ea42b85135562cc4ed3a9ad0b9fb1fd2846ed3b0334b0dcf1c1851d53eeb4424ca8a73ccc333a31ba724d7758c77769bb15026ff51587d6b3b2570b544943cb7ca866bf82b95a80b636a2fb268dbe4987c1fa088f75fe842730a05f9046593e264b5344c0ac8614c6fad15945c1de21a6d50f8f276770bd85d7f767b3468ca8a8b2e6a5c6a2a6b195710a8a05df9de7eddb942d5c1c9cca80bfc0ff8e14580b1cbb6329f219dea5e780bb126855666b5e1ad2820e3258436ceaf652b357791b05ad6fcbbc00522667c05fddaa3dffc198e503cb05b719439352238bbd8d61c2e06f8f2cfe5b6c79c2b1195f54878564d5d943a2b08ca70037108f", "b4", "9c985b3c93915dc604fc3019cff4d0d1535bef94dcf85e95f535e730aabb8f22cd3607a341d65df110c5bdb0079f8ad8c36b4d47e742204b21de844f8319b065c9f8473ce7b473951378eedc8c545b236315027e5ae0e85ae2796677bbb15bc562ddd5ca05003852744688b91620d7f9af12261ab330b7f9c468d274523a682257e9156e2279ae53a7cff9014349580630abc9c00371434723cd56ff611fab96c9b3620d0a19d60ab047605c9e72a85d3aa55f79867aa5bf4dfeeea3809a0d461f8efd1addaeb0240cb7e73bae60c37a194e97ab77064137522f840e44976e9b7a79079e43aa310240f32598d4ba61a790bdd635733430a27726ad3068f3e5c7731114bd6e5f739d09c4e9c0979cc8984e037c50e3727c93055ffe51c76565f8850047a7f836e53ebd845fbcace4a05a7d03f148ad8283e6415993e5b038dcc3052eab3ebbc54ee0a95f06ca9e68342b984cfc2814aa8fc21e3e826eeb8eb36e38c68aab96ceba5dd02552f09f103a5e31b3ffd6b53ba05b19490fe5e5cadbf3702e85eeda2cfd2efa777b3fa197ec7734029386e8e7e1eb7f35c14c047d88833fcdde2f0b2f8447b53d75ecc64892f3e9dfe9e41d7ae838ef0ff39509e2cd93e99ae597f8567779a26406ffa7f7a56efde2695d32608c328112fee6c587dac7479bb68c1672e5f54778650670510242fd95b348994fb04ba1257ebcd2cb82ef4c3e71222ecb46e2f42764d6461ac81825b3c7734a8a8155fab9a63da8fc7d450216a8525cba10fad4fde4b1990a42d5822e05e60285d9c99c4cb388beaf0427fc146b00c5e64073bb56add0ac5f247a7fb34abcdda492b049c2486f80dd8d6a259f509a2a9508fa4fe50d7e3e66d0561b78b073ce1cd3b763e1445334c795ff5aba63e1d208babf2345e1baec5bf56837a6069959518c26a7fb376b2c9e2cee87c16fc2418b1551730a5e2a4fc99c0b2e539051b4fc17d4803cd98525535ea85ed21158d74e972d93427a1e8e27de2c9e048b0388646c5cefaa4a20c4b89b35cced0d60a5de89182cc5e8c5479ee0cdd96d154e96136de8078c3304ed8ca5f097751b132a075004a7bde121ae4714e0fdb16788dc489264634041056c3bbe73fadec05ba9e0b8daca32d2f483b3b2153088f249f7e371e1001ac7d72488e31da1a28ccfef46a833eb6fd743c22fe7d4a1ced93d223383945e76f0c66be2251e4a7ef1cc5d78283f9ad9fbe14d987a65e373ddc9c54a30e95fc7276fa7c82c55e1a3917ab93abf73487d0be85d31fa41cf86de1c567e14b3f5d8eab101b1bc7260c74f98120b689f51fdd0df8d3d471875df2196bdb90bd9b5cb7e65b1ebfb70fe9c63e964aefd5477e337c8815a276856dfbd1a26e82141828ccb6a867942577efbdd1c6ed6b1f32578fab06ef3a7b9275c2a8131068f04e1c718d61ebcd728a93486dc7563b1738931c9da5055a22e3dd88232baaae5282782e4dd51ea5f0b72df2ab7b7fb961df07f3993359f17ac229eaa81f34a1dc69a351f011b30a60b5a4909cdaf8b215d1664a2660a2c560a2bcd27a8efb95c467a293867f835371c27f47cf6ad6cfd4d9d8f0defc42d9ff0f77259292c0b0cdcfb3b7aebd59d2102240ab1fbe402beb8dee4ca45cc0dc294d2b08e89290c9769da4df4cb28c12551d8120c50f9c3a11168b81c895427dd375c58bca78255bd4a145a1a96d1e81283c68353a822e4d5b00a08281110a5dcb2cf4cd7d282d682e923659dff3ac4f0ec4b8ea42b85135562cc4ed3a9ad0b9fb1fd2846ed3b0334b0dcf1c1851d53eeb4424ca8a73ccc333a31ba724d7758c77769bb15026ff51587d6b3b2570b544943cb7ca866bf82b95a80b636a2fb268dbe4987c1fa088f75fe842730a05f9046593e264b5344c0ac8614c6fad15945c1de21a6d50f8f276770bd85d7f767b3468ca8a8b2e6a5c6a2a6b195710a8a05df9de7eddb942d5c1c9cca80bfc0ff8e14580b1cbb6329f219dea5e780bb126855666b5e1ad2820e3258436ceaf652b357791b05ad6fcbbc00522667c05fddaa3dffc198e503cb05b719439352238bbd8d61c2e06f8f2cfe5b6c79c2b1195f54878564d5d943a2b08ca70037108f000000000000000000000000000000000000000000000", .None}, + {.Shl, "d03d911effb910633a3c0dfbb46c4380ee50c78b6fe07f7b5698a6f7b5b8ec0520d8760f0223b72a8d9faf4cc16b30afac3dd8e68538463edd9dee27fc46928ca8a60f67089e3bdae1fd1f41abaf0492e403f41699ed0478c5390875d19d4c64107a4770a60eabd6fadf7d78eaba98e5dda72687eff0529bb26eefae66cb46de49d98b0f1fe548f765a41e9a75adc363e53ba9caec55958538487a78d517b82ab106a56bb6bce35c44e9bf61b319bd8359355318d61c015a727b376c3015888e30f4b398ec9160cefd6c78c714d62433137d3fadf64225ce63061ad07b2af6ed0fb196ee86d771897639c4bdbec55afbc084b5b2e70d9dbc6cd23eeecce1e011f355befe0f607da9631f5d8cd0d019a8e7f4448d6b0d6de75ae78682ca6b373359ed4a2cf94e2b2e136dc9cdf8187ab24bb8ded7cc9e70f948dfe7804168a56e60f07e7deab06d0bb9ee4ea20c968604323f9853a3aac13160e99f13de17c68f064dc3caaa4e4b0fe0af1ce260bda108ea0ff8789681e307e8665d8e575dfea77437d32893711c9f2e7103b24294c20cd80c4d62b952b5d475bb9572067a1b010ebf66f75dee3f723bb8d6535ed7342211084c0057905335b74054abb145be4f8a07b1abf75a4af443fcdae5e7f90a2a0cfa63ed04db4f1bb5ed73640d88803a6d155147d527017539ad902b336533f4845bb580f39d18808d89e13aa9c562a7e07f6df7c9ebb8a31e2fc44cc2940078e2527b47c644ed31a1bb8232c7cb28c752ba7cc6aeeadfe523133d92a44ff7b1495337d53975318149fb6d58e3c60ef154da356caf93bad49f3cd8a951f6c5e40ac6a9a9efd327ccc6d1f0255007959337c6566d0570d75f8b6d099021298de2a5c86b9fbe3db642f8cf901b856639938c39afe64aacf8533d6cdf0220b2b22005fc8a1f86c0d5e333c3afdb556cea960cc173a3b4499371e3bab0206acca21771ceb99073d8b31e957c1d0dfdd8ba102bad5d3fad814ad82b946e10e91875bca6caf797336b51250be8f12f39612f1e23b39c746b215839f9bdc5acb980c809ed77e89a0905a8290f251c02c6fa8d945d0fff4c98ac1ccd6dc12eea596e3e5c399d09e479226be5bb4632f204765e77c42ddc18bccb36778137a4e169dacf4462fea8f0422a3e3d989256c24d76d376d59e3881726edcc9a1cae72127e0786060e002c936fcebb0a9488c0321d576a58a4d1c05ea38006bc8079235fd741c7910a54969f7b780b7e50210ebeb225a00d0606ddb578523a653eaa108d0f31f29d805be467049fe92898dc92ec5bb4a5514a4cf62dc5c321c19afb8258eafc4be257da9bd5f880720e76472f0cebc44014c5c99a7382259422a85dea158ba0b3e4620f85b0db74f080b547ad6b82bcdc4f3b4b6088cb6e8fa1c9b70dad53a86439980fe01874a9bac736ec09cc75267e36c5f75c84605b19689794711b4002d20d9b1caa5bd6f44043508e04ec00ced5a12e64add4384ab8afa6c57c34730f8d9ca0fd032bd5a392e0194bfbc82e9e46f79482cef9ce51fc6a30a2763c542a0a40efa2501903f4689147048dd9979f2a11858ec9015146a5a770ac25e7168982511e555166d01df0f5a6a9200acba60a4da8589f62e08921c6816c8f5d91c7cd059ae4426724efeccfa7d0003a558b95718cb291b7d87950e696b7a30f5cf92510d5cfa61edfa456356a3985601d064ee5cd90183af5615ebc455782a56542b955fd98b2f6e946fb2535cb2d31e71b43b2014378ad7fbdcca28c43bec064b3e3c74f598880f347edbe5db7948ea367f348f8c33fd64d761ea0d9f0ed718951eded8f1aeda9719ceafafaa509625017074692926d4fb2f2e26c6da0a2a1eca8916286002576dabb19dda3655cc26bbbb6ea9340c90b7cd44b0b32c754e2969b9b3b106b233f14c40a7431ad742ebb172b2070f361d1b33873eeade680a7871bcb3489a0744d9efb4380d084cc5b7f71c472d12f04dfce36285e474b8f8b28d0dd2b1a108ccd2cd82de691b32f7e726df44d9e3179b2e028fe325b8d2fc97170f5f6f8adbdeba8ca63af8c7c629b90d4e4c94459ed3ece78b6e1dd5fdd54795d7530cc45a98110cf4de2d1c4355", "258", "d03d911effb910633a3c0dfbb46c4380ee50c78b6fe07f7b5698a6f7b5b8ec0520d8760f0223b72a8d9faf4cc16b30afac3dd8e68538463edd9dee27fc46928ca8a60f67089e3bdae1fd1f41abaf0492e403f41699ed0478c5390875d19d4c64107a4770a60eabd6fadf7d78eaba98e5dda72687eff0529bb26eefae66cb46de49d98b0f1fe548f765a41e9a75adc363e53ba9caec55958538487a78d517b82ab106a56bb6bce35c44e9bf61b319bd8359355318d61c015a727b376c3015888e30f4b398ec9160cefd6c78c714d62433137d3fadf64225ce63061ad07b2af6ed0fb196ee86d771897639c4bdbec55afbc084b5b2e70d9dbc6cd23eeecce1e011f355befe0f607da9631f5d8cd0d019a8e7f4448d6b0d6de75ae78682ca6b373359ed4a2cf94e2b2e136dc9cdf8187ab24bb8ded7cc9e70f948dfe7804168a56e60f07e7deab06d0bb9ee4ea20c968604323f9853a3aac13160e99f13de17c68f064dc3caaa4e4b0fe0af1ce260bda108ea0ff8789681e307e8665d8e575dfea77437d32893711c9f2e7103b24294c20cd80c4d62b952b5d475bb9572067a1b010ebf66f75dee3f723bb8d6535ed7342211084c0057905335b74054abb145be4f8a07b1abf75a4af443fcdae5e7f90a2a0cfa63ed04db4f1bb5ed73640d88803a6d155147d527017539ad902b336533f4845bb580f39d18808d89e13aa9c562a7e07f6df7c9ebb8a31e2fc44cc2940078e2527b47c644ed31a1bb8232c7cb28c752ba7cc6aeeadfe523133d92a44ff7b1495337d53975318149fb6d58e3c60ef154da356caf93bad49f3cd8a951f6c5e40ac6a9a9efd327ccc6d1f0255007959337c6566d0570d75f8b6d099021298de2a5c86b9fbe3db642f8cf901b856639938c39afe64aacf8533d6cdf0220b2b22005fc8a1f86c0d5e333c3afdb556cea960cc173a3b4499371e3bab0206acca21771ceb99073d8b31e957c1d0dfdd8ba102bad5d3fad814ad82b946e10e91875bca6caf797336b51250be8f12f39612f1e23b39c746b215839f9bdc5acb980c809ed77e89a0905a8290f251c02c6fa8d945d0fff4c98ac1ccd6dc12eea596e3e5c399d09e479226be5bb4632f204765e77c42ddc18bccb36778137a4e169dacf4462fea8f0422a3e3d989256c24d76d376d59e3881726edcc9a1cae72127e0786060e002c936fcebb0a9488c0321d576a58a4d1c05ea38006bc8079235fd741c7910a54969f7b780b7e50210ebeb225a00d0606ddb578523a653eaa108d0f31f29d805be467049fe92898dc92ec5bb4a5514a4cf62dc5c321c19afb8258eafc4be257da9bd5f880720e76472f0cebc44014c5c99a7382259422a85dea158ba0b3e4620f85b0db74f080b547ad6b82bcdc4f3b4b6088cb6e8fa1c9b70dad53a86439980fe01874a9bac736ec09cc75267e36c5f75c84605b19689794711b4002d20d9b1caa5bd6f44043508e04ec00ced5a12e64add4384ab8afa6c57c34730f8d9ca0fd032bd5a392e0194bfbc82e9e46f79482cef9ce51fc6a30a2763c542a0a40efa2501903f4689147048dd9979f2a11858ec9015146a5a770ac25e7168982511e555166d01df0f5a6a9200acba60a4da8589f62e08921c6816c8f5d91c7cd059ae4426724efeccfa7d0003a558b95718cb291b7d87950e696b7a30f5cf92510d5cfa61edfa456356a3985601d064ee5cd90183af5615ebc455782a56542b955fd98b2f6e946fb2535cb2d31e71b43b2014378ad7fbdcca28c43bec064b3e3c74f598880f347edbe5db7948ea367f348f8c33fd64d761ea0d9f0ed718951eded8f1aeda9719ceafafaa509625017074692926d4fb2f2e26c6da0a2a1eca8916286002576dabb19dda3655cc26bbbb6ea9340c90b7cd44b0b32c754e2969b9b3b106b233f14c40a7431ad742ebb172b2070f361d1b33873eeade680a7871bcb3489a0744d9efb4380d084cc5b7f71c472d12f04dfce36285e474b8f8b28d0dd2b1a108ccd2cd82de691b32f7e726df44d9e3179b2e028fe325b8d2fc97170f5f6f8adbdeba8ca63af8c7c629b90d4e4c94459ed3ece78b6e1dd5fdd54795d7530cc45a98110cf4de2d1c4355000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-11698132a61a73fcf5422c993918f269b1a552251a7dd105e4527668f47ef0440c8c525276fb6be0672c1bf97b89282c5fb3843ee9bf16e96da8c8c1fb7da7bc32ab978ca49e8568b901d9c177e51796d797ec9c6e171e9d3b9348e65473cea758901fd0b497e5afc9da748c4de89b3bb0be7f15f01988fd678bd6b5d39d5fcf6c776be85899d9aed0f52c08c8e5f6dcfe76c10449eb04b069326ffd7953be4c301239efd56f5ac3acfa6324b0e3780d6f0e3b260ba640a65678fb754806d5613ff7d47184e929b60fa42cc85513dbccb938a58f560e9f253ef34f912802114fe039549c38962ac26fcb9d806491f791d913812d0ac01eda18b62dcb336253b596fca6d08d6c125ecf0bcb7bd25cea313a2eb081de3f72fc0b507b7c97683c51240932e4c846d68fd9224aefae636b95982f2974ef98508a70b4500db125d17afc636a18f049f3085666c33099d05e84c49c3a85f85f4089757727aa04f98a6313c91ff2fd49b48c464cde33b0acbc6ff4e2604abe9ac69450b8bb2d71f2270b83ac6cc9ca57fe0751ca9123242a8f65eac08595afa820f0ae1af07125c5898ef3dfe3a3285adc65844994e6f727cd6a83ea19f3e242e938600499c5ea23fb8a2dcd1142d3ebd6798ef2a9a9669782484ffbcd8074cfd47d253f34d4062f961d7474308d848db8a5564717aa01e0932ae5ca1b65a5d96405b645a209810e4074e3481a5e33e0bb31bf4322e2443c89d6bf9863203efce6168f3d327cc5e8975bebe9c524f2a254012fbfbfe412692d6b5b4ac0bb7cdf9e008c5f9be0bef7e66242059f1041b02408e1e57339593f8341a182f2a870b1c44364ac932f0564cd6740be612015b4a30c3cee944b7a5c79ad2a499f4a6c9fc4431c8e6ea97bc02ebe6f699cff86f15193ee65046bb00a1f4f21bb1f184aab41a38126cf168ae8a6015512a9d00d85f7a357380c2ea223aa6353646b2f16117e2d8fc342a4ca52d533f0dadba28ea1917ea5db39be9006ad5ca4ec1c108b24e473f4712331c7634427da9261e17483d0e36272073bebcabf798b4847e2e2388dbb69d2ed75bc374aa3eb73c18e1815ce4e7515f818547ce0696154b66b1008a68433db3bbd1f152f6e04edaa9d6abf8219b75525c24acab5a2416dc5b09cf197a643a91e8269b9c04ee53d8983ba0f66dac750140e7c0da63554c8cead2df679c9ebf506e8a25a323763735b48ad0b35377e392f5d345855810362852ae040dfb99d4f12e4932fa6f64ce03a3eff6fd2c1f3aa95d51c5693b1f5103205ab7e5357a68f99df61126e72e78dcbb3a7d167e7caad4374a0284cbebbc3c97ed8a762640a94f69cc16618ea544d5fe4a01f99c1a4aa1f4567c09a39c2e168d2fab5e6f0f0d5f679d7695fe9da43eda763946dd798510ede5eb6730edafab21116edcc754c0c85b52a9218d485e5a79b342ba646bff5495a5bd3abc322e222e2c02cb0cd78566a8a470b4f693eff4c494a43b64b3d91da7545aeff87eacd103f98d13ba39d452a1181c7fc27f6653b2b21c0e15743843ea5c7cf10f45d0b94de2a1e8ee331a4932b7d8abdfc6f0987af326a766771a0fb5b5cd7d01a7e3a9b2cdc130f64b3e538149cd6de29faaf5fae54df1869fc1906f24ff261deb02e733a241a46f4c7cfd5c960fd4f66401288c2502a4c38aafe2c815c945466aced1fa63ba66ef71c9025c301aa538b217fa95fd55cc9bb1aa7ad1a8e27db640b40a76dce2ab4e506081a681d5ff1f155d0d0330aa2f411297bbd2b17550a1f5d9817802a602438fc99d2a52c425a7e97c9b6b51a2e116dfd21f0ebc8dc679c91480e50f28d1abc21bdbbb88e47b2bc1576bdcd02ce22e8d7315e5fcf7737bb7b2f8368a180a89889af4c3c1258f4a6d80e5e1836206bd8c8c3a2c14e3b71dc0b6aec2758040a0896921f2638fa945ce0becbc492506f3de0c0881dfcde8bc02db0061c50448e0ffcd14c732d8ddce783bcb897cacfd02ae5c0738619c519da399ac0dac4fe5f8c7b5485c38d83331cbdb4f5498ae5bd8c54f754d49806217e6f81be750d4a714c153f4aa65c7f2fa3ac58e252bc5936554a77b4faaa6ecce3941c02ed51771c3ad240356a", "0", "-11698132a61a73fcf5422c993918f269b1a552251a7dd105e4527668f47ef0440c8c525276fb6be0672c1bf97b89282c5fb3843ee9bf16e96da8c8c1fb7da7bc32ab978ca49e8568b901d9c177e51796d797ec9c6e171e9d3b9348e65473cea758901fd0b497e5afc9da748c4de89b3bb0be7f15f01988fd678bd6b5d39d5fcf6c776be85899d9aed0f52c08c8e5f6dcfe76c10449eb04b069326ffd7953be4c301239efd56f5ac3acfa6324b0e3780d6f0e3b260ba640a65678fb754806d5613ff7d47184e929b60fa42cc85513dbccb938a58f560e9f253ef34f912802114fe039549c38962ac26fcb9d806491f791d913812d0ac01eda18b62dcb336253b596fca6d08d6c125ecf0bcb7bd25cea313a2eb081de3f72fc0b507b7c97683c51240932e4c846d68fd9224aefae636b95982f2974ef98508a70b4500db125d17afc636a18f049f3085666c33099d05e84c49c3a85f85f4089757727aa04f98a6313c91ff2fd49b48c464cde33b0acbc6ff4e2604abe9ac69450b8bb2d71f2270b83ac6cc9ca57fe0751ca9123242a8f65eac08595afa820f0ae1af07125c5898ef3dfe3a3285adc65844994e6f727cd6a83ea19f3e242e938600499c5ea23fb8a2dcd1142d3ebd6798ef2a9a9669782484ffbcd8074cfd47d253f34d4062f961d7474308d848db8a5564717aa01e0932ae5ca1b65a5d96405b645a209810e4074e3481a5e33e0bb31bf4322e2443c89d6bf9863203efce6168f3d327cc5e8975bebe9c524f2a254012fbfbfe412692d6b5b4ac0bb7cdf9e008c5f9be0bef7e66242059f1041b02408e1e57339593f8341a182f2a870b1c44364ac932f0564cd6740be612015b4a30c3cee944b7a5c79ad2a499f4a6c9fc4431c8e6ea97bc02ebe6f699cff86f15193ee65046bb00a1f4f21bb1f184aab41a38126cf168ae8a6015512a9d00d85f7a357380c2ea223aa6353646b2f16117e2d8fc342a4ca52d533f0dadba28ea1917ea5db39be9006ad5ca4ec1c108b24e473f4712331c7634427da9261e17483d0e36272073bebcabf798b4847e2e2388dbb69d2ed75bc374aa3eb73c18e1815ce4e7515f818547ce0696154b66b1008a68433db3bbd1f152f6e04edaa9d6abf8219b75525c24acab5a2416dc5b09cf197a643a91e8269b9c04ee53d8983ba0f66dac750140e7c0da63554c8cead2df679c9ebf506e8a25a323763735b48ad0b35377e392f5d345855810362852ae040dfb99d4f12e4932fa6f64ce03a3eff6fd2c1f3aa95d51c5693b1f5103205ab7e5357a68f99df61126e72e78dcbb3a7d167e7caad4374a0284cbebbc3c97ed8a762640a94f69cc16618ea544d5fe4a01f99c1a4aa1f4567c09a39c2e168d2fab5e6f0f0d5f679d7695fe9da43eda763946dd798510ede5eb6730edafab21116edcc754c0c85b52a9218d485e5a79b342ba646bff5495a5bd3abc322e222e2c02cb0cd78566a8a470b4f693eff4c494a43b64b3d91da7545aeff87eacd103f98d13ba39d452a1181c7fc27f6653b2b21c0e15743843ea5c7cf10f45d0b94de2a1e8ee331a4932b7d8abdfc6f0987af326a766771a0fb5b5cd7d01a7e3a9b2cdc130f64b3e538149cd6de29faaf5fae54df1869fc1906f24ff261deb02e733a241a46f4c7cfd5c960fd4f66401288c2502a4c38aafe2c815c945466aced1fa63ba66ef71c9025c301aa538b217fa95fd55cc9bb1aa7ad1a8e27db640b40a76dce2ab4e506081a681d5ff1f155d0d0330aa2f411297bbd2b17550a1f5d9817802a602438fc99d2a52c425a7e97c9b6b51a2e116dfd21f0ebc8dc679c91480e50f28d1abc21bdbbb88e47b2bc1576bdcd02ce22e8d7315e5fcf7737bb7b2f8368a180a89889af4c3c1258f4a6d80e5e1836206bd8c8c3a2c14e3b71dc0b6aec2758040a0896921f2638fa945ce0becbc492506f3de0c0881dfcde8bc02db0061c50448e0ffcd14c732d8ddce783bcb897cacfd02ae5c0738619c519da399ac0dac4fe5f8c7b5485c38d83331cbdb4f5498ae5bd8c54f754d49806217e6f81be750d4a714c153f4aa65c7f2fa3ac58e252bc5936554a77b4faaa6ecce3941c02ed51771c3ad240356a", .None}, + {.Shl, "-479fd8446ddfd3439cbbff6e1321190eee5e2a3a47ac8ac8e3d7e8ff98f2b22d01b01ce29fb0c8d88801eae7a4f175efcf11b6581bf9298487cc1c23a07c3d9953be84f0fe7fc29978be329474f83cf251880ef118cdb8ab2d3f263551889bebaaf01d451b6ddc0a25b07595561b2adf0c41278e6612f97b3b9da09d56cb27aca00fff42a94d323c6cf02f66335959b2a93db855f204ccc74f9cb354269088da7c15040091647171b9b7a31b8a1001b263d2f3a9e62d69c9ca8ba0d82f045d905f8881a75c35991ea38b4f0fd570b8a7f9c464c6dc82c49f29abb7c0bf4bd70ce0cc3c2ad3fd2278779fc7bc6bb9c8e11e4e1ed2ee142432df37d2ed548d6b8e9b9e6b7535e032917c2612f04e471d96f676f9a2f3a34484b8689ad83eaf3d420083137b93860bcd2156e8a2121f1dd99aebca1908d001782603485585b33c872d18f01580719368c04afe8380e8b6de4855599485da1aef7418b8cc9da0f9a0fce7382ff24761494b1240ba442a915d349a39e7948d745d6fd1b1ca0b3fa255d6c3c948bd2d4bcb535ad4155c250ae287216a74d91193c3c67e78c29cb33687bd19eabf2ad010fcd9e208898fc444c4dbdc5cc1e7f757df726eb8af35835aedba211387902abf434383444db1bdb767a4b446edcc8bdbd635f2b824a8ae4a900a6ec7b975459c90e86fbf4d8fa548f6579bf53ab36f91cb23f6bc219566c4f7f11e638b732b6f353793f0bfb67b919df4f69233564ae0d7bc63e395b1eb72f08890eb3bc29a299846524c133660f27a996870a10b6985ba7073be00b496e4f7399d89f77581084543119a15227e6bba885ab81cd866d43bc6e9c529d30e74762167a84716f9d694f123a85d31b9ed2f88bf57362ff8c625544a6c6c17379bbb1b49656825879e18f296c2e017a957f2bdbcfc50c92c5d320a319b4f140843aa1cd04307cc051f28665f40c42a2b6535823aa7235663ff356c1d7fd18674db0575a61aec00b81c1fe8d4054bf5f578ec2e95559731cec610a1584d754ef5b6ccb1c22797a64b0d3c8a0e7ab68acec3fb451cdf47350a0020ee64ad08ef002520b6ff918a6ed383b7bcab599134da3090874c73f687387dffe8d8e0561dadf0cf97280d41cd09392748307b582a7093f099b0c9f49de19c2b818a0ef9d426138ae38ea7d990d2a69c28477510195a62fe83cff039db02fac225f3fdcc971db2e6f5e9c0e5fbddf3f6f2bc48f36883ae3c9f7a25d17fbe45dec0db4c3cc72cb9da9a36fb80bba9e69a4b53c98c2f1f005227754f6115d4946f90fc1265b366a056160d8447d01500f11d3b2bca7106f773c1a1980556933b0f86e914014fddb145a9d4f629d1e0168be9b14a24b9bfd615e93f0fdc37229302456f0f5a8a422eed85d4aef53eb27139e6377ab91d75e94ec78c5b3854a732472dc0b72466df479f1388c6f42936f94cfa537369f66e2981c7b8acc6db944c84d38fd9e80e249409d36a767fe1a8cd8aa357a785dcf6ea280be1824b67ab2ea5791dd1e5aa5c86693c605643ed2eddd33866641da248ccf94bf5185f719c654aae745ee158f47d2e70e03ea812d4ff0e3e7c39337e6d3c8f1c509a34da3d385715da4a10e94d4edc244fe96f79d36478fe68a013c42e5571bdf07cb6a239767eea2efa14f3f4f7a30ce7296fddaa67743cbe52a09c355557ef5258005613ef35def8ac8aa459bc861e95d9ae849b75045e52c8d7c4abd5108cb3fabb880fe2828fbe528f95456426d26314c2bdb0b9d01d8a13081866e716d178fd51c2f44ad70d607d5bebd1f0725d9fe472e8c199a0d627b10d532928d476edf49b3c795bf5dc9620bb7c08cbf2e6c79016f79ffa30c8cfbe35d546ca435664d5c0a992a167c17145fc6ac3ade09c8d01c7d449c9b0f9993bd72ccd4b712dc0e81166bd1135cea4666e1ba61d80b973d0c0c283fdf916283749b026df8ebcdd140d6e17ba8a4f5ec00409c1f29115783c66e9ba5e83b85d6130faeb6af40d27814efa40b97f85ef4cc51db010c6927db3448feda1504c49f79c94f6a3d5ad0cc010015fe928328fbdeeaf6245f39b9beb611f39f8bbdc627c40eec9a87ece0a72d685e0cfba351a3cce", "258", "-479fd8446ddfd3439cbbff6e1321190eee5e2a3a47ac8ac8e3d7e8ff98f2b22d01b01ce29fb0c8d88801eae7a4f175efcf11b6581bf9298487cc1c23a07c3d9953be84f0fe7fc29978be329474f83cf251880ef118cdb8ab2d3f263551889bebaaf01d451b6ddc0a25b07595561b2adf0c41278e6612f97b3b9da09d56cb27aca00fff42a94d323c6cf02f66335959b2a93db855f204ccc74f9cb354269088da7c15040091647171b9b7a31b8a1001b263d2f3a9e62d69c9ca8ba0d82f045d905f8881a75c35991ea38b4f0fd570b8a7f9c464c6dc82c49f29abb7c0bf4bd70ce0cc3c2ad3fd2278779fc7bc6bb9c8e11e4e1ed2ee142432df37d2ed548d6b8e9b9e6b7535e032917c2612f04e471d96f676f9a2f3a34484b8689ad83eaf3d420083137b93860bcd2156e8a2121f1dd99aebca1908d001782603485585b33c872d18f01580719368c04afe8380e8b6de4855599485da1aef7418b8cc9da0f9a0fce7382ff24761494b1240ba442a915d349a39e7948d745d6fd1b1ca0b3fa255d6c3c948bd2d4bcb535ad4155c250ae287216a74d91193c3c67e78c29cb33687bd19eabf2ad010fcd9e208898fc444c4dbdc5cc1e7f757df726eb8af35835aedba211387902abf434383444db1bdb767a4b446edcc8bdbd635f2b824a8ae4a900a6ec7b975459c90e86fbf4d8fa548f6579bf53ab36f91cb23f6bc219566c4f7f11e638b732b6f353793f0bfb67b919df4f69233564ae0d7bc63e395b1eb72f08890eb3bc29a299846524c133660f27a996870a10b6985ba7073be00b496e4f7399d89f77581084543119a15227e6bba885ab81cd866d43bc6e9c529d30e74762167a84716f9d694f123a85d31b9ed2f88bf57362ff8c625544a6c6c17379bbb1b49656825879e18f296c2e017a957f2bdbcfc50c92c5d320a319b4f140843aa1cd04307cc051f28665f40c42a2b6535823aa7235663ff356c1d7fd18674db0575a61aec00b81c1fe8d4054bf5f578ec2e95559731cec610a1584d754ef5b6ccb1c22797a64b0d3c8a0e7ab68acec3fb451cdf47350a0020ee64ad08ef002520b6ff918a6ed383b7bcab599134da3090874c73f687387dffe8d8e0561dadf0cf97280d41cd09392748307b582a7093f099b0c9f49de19c2b818a0ef9d426138ae38ea7d990d2a69c28477510195a62fe83cff039db02fac225f3fdcc971db2e6f5e9c0e5fbddf3f6f2bc48f36883ae3c9f7a25d17fbe45dec0db4c3cc72cb9da9a36fb80bba9e69a4b53c98c2f1f005227754f6115d4946f90fc1265b366a056160d8447d01500f11d3b2bca7106f773c1a1980556933b0f86e914014fddb145a9d4f629d1e0168be9b14a24b9bfd615e93f0fdc37229302456f0f5a8a422eed85d4aef53eb27139e6377ab91d75e94ec78c5b3854a732472dc0b72466df479f1388c6f42936f94cfa537369f66e2981c7b8acc6db944c84d38fd9e80e249409d36a767fe1a8cd8aa357a785dcf6ea280be1824b67ab2ea5791dd1e5aa5c86693c605643ed2eddd33866641da248ccf94bf5185f719c654aae745ee158f47d2e70e03ea812d4ff0e3e7c39337e6d3c8f1c509a34da3d385715da4a10e94d4edc244fe96f79d36478fe68a013c42e5571bdf07cb6a239767eea2efa14f3f4f7a30ce7296fddaa67743cbe52a09c355557ef5258005613ef35def8ac8aa459bc861e95d9ae849b75045e52c8d7c4abd5108cb3fabb880fe2828fbe528f95456426d26314c2bdb0b9d01d8a13081866e716d178fd51c2f44ad70d607d5bebd1f0725d9fe472e8c199a0d627b10d532928d476edf49b3c795bf5dc9620bb7c08cbf2e6c79016f79ffa30c8cfbe35d546ca435664d5c0a992a167c17145fc6ac3ade09c8d01c7d449c9b0f9993bd72ccd4b712dc0e81166bd1135cea4666e1ba61d80b973d0c0c283fdf916283749b026df8ebcdd140d6e17ba8a4f5ec00409c1f29115783c66e9ba5e83b85d6130faeb6af40d27814efa40b97f85ef4cc51db010c6927db3448feda1504c49f79c94f6a3d5ad0cc010015fe928328fbdeeaf6245f39b9beb611f39f8bbdc627c40eec9a87ece0a72d685e0cfba351a3cce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-b430763810f3d035195159b28478793fd7c1e0a9d8642f1a7d04ce277174dd08f3ace8e812f875b760d116a3745d56fc8eb659357beec22e8fb845cce220b3248a72b731a34a5e78e5cc5baaebe3787632329d7fce8c479d1e4bdb46150047a25c1c805d0186bbcc4114e35d7700324eb5adf3817bd4d498383e09b3ed2b741dfe6f0c0947c7fcbe5aee9ed35858defb9a36fda38daefff7f0b4c804782365541caa77e06a4a7ab050c3325d7bb0d75cdc1e4afead3769eb7ff4481d5ff2a78898e56aa78bf081318d8ef95b5b3a0dbdba0f77644260ca8572ea0bc8b168535526dadbe9346b3faa33cec07dc8ce181d15495cb256a7b1e652cc324e064ab0a0503a6b78cc2ce030ab267297ba1443a1e29e9e30ccb0c7101b6191925fa5e90686cf7eb0384d139106207455297139b006e19a597c802bf473500c3425081f4295fd9feb2f016b9c5b57d5f6edc754bef7e7672942bdf291f583a1c2de267365841a05e6fe9835bafd33dd98b06c9d531c3b6143dcd22c8b30a7aa87b8efeb87ff4b4e01498de5ceab3f5f15946065ac98761220e3ef1855bb59277c8c7678f0438c873438b7afdb6758a6acb668364d62eb0b869a44c171ee1f1cf975c2e02c45ca8e1e7d7ba790c557a9c01d564003ccb86fa70a552895bae97a9f3c16fcd6f83416622205b1f2fac1351e39c97ea94123b4a84a012ec39aa38ca75e094095769a41b1f80827d2f212c9e5ade53c3d3d3f02ce0550cae9eb27eca7655357f4be7d2fc381f24c59c97a8d0475ca4149e4399888dbfdddd92d5285123bff468d1d2b0a4d86a590cc4991a0303614c10b96ecf385e3edb511c3fde9c7c628a71e77817eb87e9b32ef14f691414d8f28623cb70eb6750f74ad86d5fd4b2596777c05147729c9042105f2d9a10940f9490ec767f84b0a6d79f89220f34fcb2b8056d4fa1c23cfc1455e22d67c55aa67518f87f0baa6c7413511788b8353cde6f33a6f9b114b814c827b871d56d95be3f61d505bbdad2ab0f2369df5747cb5a7ed7b132b4037f1160bae175170b55cd79b34de3174933830257ebd34c4237a05c8f95fbb6be473e888c1e68e8514baf2fe05de34605e9692c01030158094499969a0ebf732b77d68bc80b7b0421ec3027428a5a4242358494b3d23cab35915a96a1c13a5d95620b5e6bc6b741dcbf120adae2ade442c4e074456d147ceacd7a083c7d3e9c458122d5b81dbae51297355b324e71c593319a238fc6b1cc13978667c634290b99fecc1f3e51bd50d04c10f6653ce45c08a7bd7dc09692561a6123fd395155d5f4cb4d92b73ebe80795e131a699d6575b41cc9a7ee9645bd4bfb7d5aa864af7e9e46844862a1160b5af8667dd064bf2ffc75b9448499dbe1692ae876104f3a6093816a3fd46338e2735fcf4cd4d499c4a6969144756b8a0aa6695df77e9000180364ef9cd18f5a5614bbe69a06fc315f8330bd59a269a8048722459d656f81622924c03471af245a8afe2783657f274320f1fc447aec943073635332a90013bda13b4d6c97846f63a25788b6782e512def71f75e70dce4568b07ce1591b727287f8507eeb0ff283f42a08c93ac72ca54cab225b999ab7ca9d86107e398ac3582b3db0d66a82a3ee8149cceca7d96d2fde5219ab94034c0b1a849ecc3593221e9a86a5000c0c0d7072901f8a8e1c0e7477a7471891df5212a2573f8d555b8191e485ed3c81160be9df83ed8c23e867e83357f2b154a59e6d2c07f7ec59ac57c224d17d71dd51cc0e0f973bf33131475ea8079de3a3eafab6bd04746c07ac9b6525c879c51c53106e46ad861d9057c23531e71124ee4e18cd17e1b5f940f3f10deaa26ba69d3a8d5739391cc106d6d1953433c33a76ee97c8e18d06dbf4336ea9bddc8c684877c1fe86cb2b1905d36b917aa994caa8433ac2ede46793f264a38f36e11e4992ec2dbb00eef6416d9e1cf39831dff0269aa306c459a2ac0ccaa565ac8968ee57fa7a1b726685191680dfc4f8dece7d050ee51b0db36809e0241f90d989bfd2362bdf8909bbb9f6b3f26c51607b40e70a5ed52d271e1187d75a55502b11c8b3e06bf033fbd9fbb1eded647e65553171e9edb16052a9", "1a4", "-b430763810f3d035195159b28478793fd7c1e0a9d8642f1a7d04ce277174dd08f3ace8e812f875b760d116a3745d56fc8eb659357beec22e8fb845cce220b3248a72b731a34a5e78e5cc5baaebe3787632329d7fce8c479d1e4bdb46150047a25c1c805d0186bbcc4114e35d7700324eb5adf3817bd4d498383e09b3ed2b741dfe6f0c0947c7fcbe5aee9ed35858defb9a36fda38daefff7f0b4c804782365541caa77e06a4a7ab050c3325d7bb0d75cdc1e4afead3769eb7ff4481d5ff2a78898e56aa78bf081318d8ef95b5b3a0dbdba0f77644260ca8572ea0bc8b168535526dadbe9346b3faa33cec07dc8ce181d15495cb256a7b1e652cc324e064ab0a0503a6b78cc2ce030ab267297ba1443a1e29e9e30ccb0c7101b6191925fa5e90686cf7eb0384d139106207455297139b006e19a597c802bf473500c3425081f4295fd9feb2f016b9c5b57d5f6edc754bef7e7672942bdf291f583a1c2de267365841a05e6fe9835bafd33dd98b06c9d531c3b6143dcd22c8b30a7aa87b8efeb87ff4b4e01498de5ceab3f5f15946065ac98761220e3ef1855bb59277c8c7678f0438c873438b7afdb6758a6acb668364d62eb0b869a44c171ee1f1cf975c2e02c45ca8e1e7d7ba790c557a9c01d564003ccb86fa70a552895bae97a9f3c16fcd6f83416622205b1f2fac1351e39c97ea94123b4a84a012ec39aa38ca75e094095769a41b1f80827d2f212c9e5ade53c3d3d3f02ce0550cae9eb27eca7655357f4be7d2fc381f24c59c97a8d0475ca4149e4399888dbfdddd92d5285123bff468d1d2b0a4d86a590cc4991a0303614c10b96ecf385e3edb511c3fde9c7c628a71e77817eb87e9b32ef14f691414d8f28623cb70eb6750f74ad86d5fd4b2596777c05147729c9042105f2d9a10940f9490ec767f84b0a6d79f89220f34fcb2b8056d4fa1c23cfc1455e22d67c55aa67518f87f0baa6c7413511788b8353cde6f33a6f9b114b814c827b871d56d95be3f61d505bbdad2ab0f2369df5747cb5a7ed7b132b4037f1160bae175170b55cd79b34de3174933830257ebd34c4237a05c8f95fbb6be473e888c1e68e8514baf2fe05de34605e9692c01030158094499969a0ebf732b77d68bc80b7b0421ec3027428a5a4242358494b3d23cab35915a96a1c13a5d95620b5e6bc6b741dcbf120adae2ade442c4e074456d147ceacd7a083c7d3e9c458122d5b81dbae51297355b324e71c593319a238fc6b1cc13978667c634290b99fecc1f3e51bd50d04c10f6653ce45c08a7bd7dc09692561a6123fd395155d5f4cb4d92b73ebe80795e131a699d6575b41cc9a7ee9645bd4bfb7d5aa864af7e9e46844862a1160b5af8667dd064bf2ffc75b9448499dbe1692ae876104f3a6093816a3fd46338e2735fcf4cd4d499c4a6969144756b8a0aa6695df77e9000180364ef9cd18f5a5614bbe69a06fc315f8330bd59a269a8048722459d656f81622924c03471af245a8afe2783657f274320f1fc447aec943073635332a90013bda13b4d6c97846f63a25788b6782e512def71f75e70dce4568b07ce1591b727287f8507eeb0ff283f42a08c93ac72ca54cab225b999ab7ca9d86107e398ac3582b3db0d66a82a3ee8149cceca7d96d2fde5219ab94034c0b1a849ecc3593221e9a86a5000c0c0d7072901f8a8e1c0e7477a7471891df5212a2573f8d555b8191e485ed3c81160be9df83ed8c23e867e83357f2b154a59e6d2c07f7ec59ac57c224d17d71dd51cc0e0f973bf33131475ea8079de3a3eafab6bd04746c07ac9b6525c879c51c53106e46ad861d9057c23531e71124ee4e18cd17e1b5f940f3f10deaa26ba69d3a8d5739391cc106d6d1953433c33a76ee97c8e18d06dbf4336ea9bddc8c684877c1fe86cb2b1905d36b917aa994caa8433ac2ede46793f264a38f36e11e4992ec2dbb00eef6416d9e1cf39831dff0269aa306c459a2ac0ccaa565ac8968ee57fa7a1b726685191680dfc4f8dece7d050ee51b0db36809e0241f90d989bfd2362bdf8909bbb9f6b3f26c51607b40e70a5ed52d271e1187d75a55502b11c8b3e06bf033fbd9fbb1eded647e65553171e9edb16052a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shl, "-f1edb13bc59970850afbda4008397ea3b748fa369e9558e0180bb1718c30b3e0cd19d1c821dd33e6d86513b38ea51a2cda35763ece414704e880022030fe2670ed4896d6ca00023a06b2d37f0e968ae184e15b9bf77da6fbdec126bd3942b70fa225acec392f13e2d47b544c7c2ebf7fd296f00a46e70e0e58a466f6475c8d76cc0ce87e2c6d9d003ed986d4e315278e169259ff2038476681f60804267c902cf8b183d75f58b84f209cd3fd6bb67f78575d78d97b8f11d986b8a8b01805f670cfb76db55b7875fd99b72b6c55c65656168061f33402eaa9443b5380e9ee19119848e9cea54f14dfe898030e41d8008d0d4c40fd1efbe4fdfc47d7e83d02e2d5807d3db7e330a6f1927f5cb3f922a8488e66eb7156b805c04e0990bba56021ec060e90fbb36900b1b7cab3ce7695d7c3a967609abfc0df3b485cc48889e1f0f1632dbb5bcc5827bccabed6ec3083f14850b037e90de0781546e5a9f26349b7fef3dad85e299c06425c5d1dee48b88840f0103e3ae4802935a6ef89b1df80377e09e89d0379cbc11437e32cb79ddd90ddf7117d018e6ebe83b25692ca20d82136ce8ccb907827595a56dcb4f3b453a646e2cc5cdc1a5461ab0c6f0d07c049b4e579c5d7e63262a24a3f31474552cea0f7fbd6f775a58b247581f0a5eed767d2ee065fd0242a3262d0a32b007e3f8a6dec9738ac62391027c05d4c50cc2f345644bf8eee446cf73715664bb686850cf99afc56ab4b8c0c1d88b28d5d61701cb6654487b93f1aa82b1a437a8f19b9ddcf2df1c1a914631de55c53161da374bbd011ef409ed127e289ced4afc35a6b38c3adc5413d63507eeab8f288dd1f96fe1ba9a6006e913df04211028dbc1ce4e296a375faa5271e91359adbe13debc024a1d92a183cae611ab6ca54e6fcc942315355157d145a7138aff4c70f8a1eaf0ac5993ab3ee1d0966b48301e393d53c5b90014704e036185c81ce9f1f7de538c2be000b0c250413d21f626c3b44f5b818559b740c728ac3609d07461c94450ac68a30af9552e6acb9fba659f865262dc68bedf71e34cfe9ca1007968db1ad731fcaa04dd3a234ebef553db6c5f1fd449f87efdafff5f46da1d30ba121ef7727d930d9f36f2ded813009793ea8f6d217742a9026fd75cae8d30321f591f8e65eb06a0b78b351723e75c0d1583dcab426b518ccadbc04adfb3028d25e1be7ec1d2a8a06204abe414d786e61432cba58289eff63911d9c49cd60fcd18890f11ddd40d5fe57df602d8df85e8134b849987da7de2466826a14de5adf8ae185cee4ad29784ec5da5a0d07bca36d96b9e23025848bc9d518976881234cd3ec69e553cce95ca2a4cf82e8bc149f36816560e8d17aaaf4c5cb5e437f12e7e1b3274d083b258152ff77095771fa375b617fa31c4e6d6f5a61ae72cff1b121a07ce7a9778a518d0cf878acf7c35b0df4eb6a22b34fdc5f38ce5915cf2f3d96fdef6c42ad9c0299b49d2cc6b85c5cd7594e68f8dd7facdc34d2a73a9cc090edbd15f8b90fdf3be424c2843d20e811e8d5a1e9547f0ec6fb6d6dadad41c10a6cff11484e00061bd33d298354c9ef95f4c21ef4c1e9ff4379db9c58212841f9a79d5a55fbe1fe86c18521837e65515c327549df442f09489529a27c74c4dc09fd541e8510473af4bd4783975b09c8b17b6393840860608a35593bd25e5afb9818ce3be5f74c5d49dfef8d8124c8601382fe16ea596d65c4387d935ca3fa4f7f2b9f9470b101d26ece0e750fd1ceeb8d64baeff0abf9d5fa6a6526875ea77c42e1688ad2d41ce7b259da1bbb763044ad13567976e4835057d8d51a80ba006b28c53ad8e88b6d64293eb35330b51e392a4a413c0106719ef118f54f752e8b43c5b777e60a044fa042ea638131aff1512580dd8639a0d8039aa8f8a768a2d36e5da0a665ed332852adfc0b7f8dddc4f1d4411338b6b1e825cf8c4bbb0ee07b04be960221b71c3e75471d29e69c898b6fc130d337b0eb32bfb335b9c97ff1b85cef9d028b93350a25ee179748bf6a9e168c8b997c367c4baec848df54ea096fd1c34c4fbb4c32dbf7d9a7f54c066791c32d2966e6e5cddaa6cccc795a09b047a1df35c6734878e0", "258", "-f1edb13bc59970850afbda4008397ea3b748fa369e9558e0180bb1718c30b3e0cd19d1c821dd33e6d86513b38ea51a2cda35763ece414704e880022030fe2670ed4896d6ca00023a06b2d37f0e968ae184e15b9bf77da6fbdec126bd3942b70fa225acec392f13e2d47b544c7c2ebf7fd296f00a46e70e0e58a466f6475c8d76cc0ce87e2c6d9d003ed986d4e315278e169259ff2038476681f60804267c902cf8b183d75f58b84f209cd3fd6bb67f78575d78d97b8f11d986b8a8b01805f670cfb76db55b7875fd99b72b6c55c65656168061f33402eaa9443b5380e9ee19119848e9cea54f14dfe898030e41d8008d0d4c40fd1efbe4fdfc47d7e83d02e2d5807d3db7e330a6f1927f5cb3f922a8488e66eb7156b805c04e0990bba56021ec060e90fbb36900b1b7cab3ce7695d7c3a967609abfc0df3b485cc48889e1f0f1632dbb5bcc5827bccabed6ec3083f14850b037e90de0781546e5a9f26349b7fef3dad85e299c06425c5d1dee48b88840f0103e3ae4802935a6ef89b1df80377e09e89d0379cbc11437e32cb79ddd90ddf7117d018e6ebe83b25692ca20d82136ce8ccb907827595a56dcb4f3b453a646e2cc5cdc1a5461ab0c6f0d07c049b4e579c5d7e63262a24a3f31474552cea0f7fbd6f775a58b247581f0a5eed767d2ee065fd0242a3262d0a32b007e3f8a6dec9738ac62391027c05d4c50cc2f345644bf8eee446cf73715664bb686850cf99afc56ab4b8c0c1d88b28d5d61701cb6654487b93f1aa82b1a437a8f19b9ddcf2df1c1a914631de55c53161da374bbd011ef409ed127e289ced4afc35a6b38c3adc5413d63507eeab8f288dd1f96fe1ba9a6006e913df04211028dbc1ce4e296a375faa5271e91359adbe13debc024a1d92a183cae611ab6ca54e6fcc942315355157d145a7138aff4c70f8a1eaf0ac5993ab3ee1d0966b48301e393d53c5b90014704e036185c81ce9f1f7de538c2be000b0c250413d21f626c3b44f5b818559b740c728ac3609d07461c94450ac68a30af9552e6acb9fba659f865262dc68bedf71e34cfe9ca1007968db1ad731fcaa04dd3a234ebef553db6c5f1fd449f87efdafff5f46da1d30ba121ef7727d930d9f36f2ded813009793ea8f6d217742a9026fd75cae8d30321f591f8e65eb06a0b78b351723e75c0d1583dcab426b518ccadbc04adfb3028d25e1be7ec1d2a8a06204abe414d786e61432cba58289eff63911d9c49cd60fcd18890f11ddd40d5fe57df602d8df85e8134b849987da7de2466826a14de5adf8ae185cee4ad29784ec5da5a0d07bca36d96b9e23025848bc9d518976881234cd3ec69e553cce95ca2a4cf82e8bc149f36816560e8d17aaaf4c5cb5e437f12e7e1b3274d083b258152ff77095771fa375b617fa31c4e6d6f5a61ae72cff1b121a07ce7a9778a518d0cf878acf7c35b0df4eb6a22b34fdc5f38ce5915cf2f3d96fdef6c42ad9c0299b49d2cc6b85c5cd7594e68f8dd7facdc34d2a73a9cc090edbd15f8b90fdf3be424c2843d20e811e8d5a1e9547f0ec6fb6d6dadad41c10a6cff11484e00061bd33d298354c9ef95f4c21ef4c1e9ff4379db9c58212841f9a79d5a55fbe1fe86c18521837e65515c327549df442f09489529a27c74c4dc09fd541e8510473af4bd4783975b09c8b17b6393840860608a35593bd25e5afb9818ce3be5f74c5d49dfef8d8124c8601382fe16ea596d65c4387d935ca3fa4f7f2b9f9470b101d26ece0e750fd1ceeb8d64baeff0abf9d5fa6a6526875ea77c42e1688ad2d41ce7b259da1bbb763044ad13567976e4835057d8d51a80ba006b28c53ad8e88b6d64293eb35330b51e392a4a413c0106719ef118f54f752e8b43c5b777e60a044fa042ea638131aff1512580dd8639a0d8039aa8f8a768a2d36e5da0a665ed332852adfc0b7f8dddc4f1d4411338b6b1e825cf8c4bbb0ee07b04be960221b71c3e75471d29e69c898b6fc130d337b0eb32bfb335b9c97ff1b85cef9d028b93350a25ee179748bf6a9e168c8b997c367c4baec848df54ea096fd1c34c4fbb4c32dbf7d9a7f54c066791c32d2966e6e5cddaa6cccc795a09b047a1df35c6734878e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", .None}, + {.Shr, "cd1155fd3d6cf1026149c0637d20a62750cc7557ef988c3417d74dbfcc5176d8259176f8fc67ef7b2f386a5c8d2f9829281417c41900cd19f16e91e31d7b36b2400c2e0a5a35365aec2df08dc1c74c5491d37d7d8218d8d000d87b278bcb01d117120115d13bce360f94a580736359e80f766cd317c3d94b5069dffe3468aa29d3696191402b06b9063fe1c970a47f061f742edb72c7c75ec5d3aa03c08456d77c25bf959d9db480107ba042976c3741cbffd15b5b72f74d4c849f7745f1a5cb02dfa2b3c03f4d60740629d86f873ddbb244e5f552846a97a1e0bd570d8be779201ce9d8eed48fae891db6c91431fb144d2624275f91c6f22c85fe10cfd0a92b3f434e93b4a79b02d93e705c24968f5fa189ad686fb1403524f90f01b9264fcbd2eadc954e8f3a6e3177f4601d01debee079610b8dac0b090b007a66b7a2e5baffb70455515ebbab7083b33dcc31ca33add2deb002163dcd357f6782c0ccf0977672220bfe5e0731ae0722c5626e16a3cb3a71dd166524b85e300f1ac54296532ba8d432f4a6972ba432ed3e5924f1cbf42fa666e153f6e872a2f703b1a91c23be1030d1f1441f156f020f310158641744158a6fe453179eab8c449811b017fa955d5f1bc931cd83dddc01d0b897a3b92303333f360693cc9c95a240467b702ed9b0bdfd98ba510171e69ad94ef7b801b188c13a47456d2e9687832edd0a9009040d42a658ecd01acc216c15724320776a4c78db3d5cab16accaa7482ab8920807471cecafa48f0fe2cfa01cd562b57a0553cbdbb9925ea8f051c5115870641c463540fac6e1c48281e7d1555949de79ddaf6a6aba1b6a42f803b212a1a9f21487821011a214591d5496b526d0c81659c9b25c29982cef9e946ca70c059d9c540c70515fdb893bc6e214e508f8bca057d9a10251990f1f67ad4313f3c56f742fe28e17f6dedc42075d4743e86c3f2c2c9daca831cbce4563fe86db69fd0d5c1e26d0ea470dd89216c5e4ccdb3597462e1a346013ef52710119a36cf8e571c599c0ef24a0a29d64744168e25e3eedf509c4b3817acce3b096b680382639bd9740ef9c0a647eabffca597969e31eae37a6423e3e296e3af8d68d050d9e89aaeb438404286deeff989fed0ccdac6623a31ac4e3848709d59f3541bebc96974bc30fd214487bec08df6dfa7d48fe875e62e970c0989f15a1d2fdcc010f9fe5ccad3d01697474a38f257a13a4da6e4b9b089a2deb9a751fb0f37ef0a0441f4369c713842d0c886b2b3479d9f7a298655771bc91f477d9990452faa3f8a3e86e23b112b9c8f42519a8eed33d0bde70e056b15ab7c41cca75d1b27ca003b839b33d0ae1f50b2e5bbc1a80ce0cf63bd296aa65b0dd07c18145771d37c0b82fee2869cae635af8d3dbb9f85a97740692c85c33d6c7d3165818775291f4ff625d534c9b5fcb4971f1b831aec82f19ba06a7fe9d5e90534153cd4bcc33057645632a1f089f7a19712fcac551e191be57e0acf617d9083bc0b3b82dee6c3a4869ed0672008eb9564b667eb990cdae9443e351f08bab1570e601a7edd4b1b89dbd3161cfd6c7ca312170ebfa73cfdc8444640a26d6a41ae83bc97f56648360162b6d5e96538223ec32404fbbb3d826d92f75e854563b7f46c6ecc78342733e19b56c2d5681aaa71e16430ddceb4914775fc509fd891fd81754c7eeec69fe009ba45340f2fdbafa54c3c8804edd8ce555ca7daf1b313ca1dc4b4e71354898460b58635b9adb7b3ff9ddba0418f6ede34c1d062375ec9391fc02d4e606a594d9d1ecf59c909da258efd968a646261a125f3725ddded9a3fb3733adefba7e1ee3070ca806f4661ec87ef879f57640f1e4f11a29f350454a7aa87592a796668681b1fda3d8a0fc72a6215113365cf2416b3b490e52364a7b11692a778f7eaef25e7a4f98bb8b7ac6b36032f13a6157f4e40f48c679dc80888c8ba806a31a5e393594c176506d221e48edcdd3c3a7427aec594704a0ac1a6d6b64ab361e0812757cdc83778c874c87d4bfa244b5252a9063be3bb7093c4445c44d6dd2fd7f4eb672a3cd4041128fca678bfd9a93d05599fe0b6a9594a5209eca924f7d32804fd6184bdeccf", "f0", "cd1155fd3d6cf1026149c0637d20a62750cc7557ef988c3417d74dbfcc5176d8259176f8fc67ef7b2f386a5c8d2f9829281417c41900cd19f16e91e31d7b36b2400c2e0a5a35365aec2df08dc1c74c5491d37d7d8218d8d000d87b278bcb01d117120115d13bce360f94a580736359e80f766cd317c3d94b5069dffe3468aa29d3696191402b06b9063fe1c970a47f061f742edb72c7c75ec5d3aa03c08456d77c25bf959d9db480107ba042976c3741cbffd15b5b72f74d4c849f7745f1a5cb02dfa2b3c03f4d60740629d86f873ddbb244e5f552846a97a1e0bd570d8be779201ce9d8eed48fae891db6c91431fb144d2624275f91c6f22c85fe10cfd0a92b3f434e93b4a79b02d93e705c24968f5fa189ad686fb1403524f90f01b9264fcbd2eadc954e8f3a6e3177f4601d01debee079610b8dac0b090b007a66b7a2e5baffb70455515ebbab7083b33dcc31ca33add2deb002163dcd357f6782c0ccf0977672220bfe5e0731ae0722c5626e16a3cb3a71dd166524b85e300f1ac54296532ba8d432f4a6972ba432ed3e5924f1cbf42fa666e153f6e872a2f703b1a91c23be1030d1f1441f156f020f310158641744158a6fe453179eab8c449811b017fa955d5f1bc931cd83dddc01d0b897a3b92303333f360693cc9c95a240467b702ed9b0bdfd98ba510171e69ad94ef7b801b188c13a47456d2e9687832edd0a9009040d42a658ecd01acc216c15724320776a4c78db3d5cab16accaa7482ab8920807471cecafa48f0fe2cfa01cd562b57a0553cbdbb9925ea8f051c5115870641c463540fac6e1c48281e7d1555949de79ddaf6a6aba1b6a42f803b212a1a9f21487821011a214591d5496b526d0c81659c9b25c29982cef9e946ca70c059d9c540c70515fdb893bc6e214e508f8bca057d9a10251990f1f67ad4313f3c56f742fe28e17f6dedc42075d4743e86c3f2c2c9daca831cbce4563fe86db69fd0d5c1e26d0ea470dd89216c5e4ccdb3597462e1a346013ef52710119a36cf8e571c599c0ef24a0a29d64744168e25e3eedf509c4b3817acce3b096b680382639bd9740ef9c0a647eabffca597969e31eae37a6423e3e296e3af8d68d050d9e89aaeb438404286deeff989fed0ccdac6623a31ac4e3848709d59f3541bebc96974bc30fd214487bec08df6dfa7d48fe875e62e970c0989f15a1d2fdcc010f9fe5ccad3d01697474a38f257a13a4da6e4b9b089a2deb9a751fb0f37ef0a0441f4369c713842d0c886b2b3479d9f7a298655771bc91f477d9990452faa3f8a3e86e23b112b9c8f42519a8eed33d0bde70e056b15ab7c41cca75d1b27ca003b839b33d0ae1f50b2e5bbc1a80ce0cf63bd296aa65b0dd07c18145771d37c0b82fee2869cae635af8d3dbb9f85a97740692c85c33d6c7d3165818775291f4ff625d534c9b5fcb4971f1b831aec82f19ba06a7fe9d5e90534153cd4bcc33057645632a1f089f7a19712fcac551e191be57e0acf617d9083bc0b3b82dee6c3a4869ed0672008eb9564b667eb990cdae9443e351f08bab1570e601a7edd4b1b89dbd3161cfd6c7ca312170ebfa73cfdc8444640a26d6a41ae83bc97f56648360162b6d5e96538223ec32404fbbb3d826d92f75e854563b7f46c6ecc78342733e19b56c2d5681aaa71e16430ddceb4914775fc509fd891fd81754c7eeec69fe009ba45340f2fdbafa54c3c8804edd8ce555ca7daf1b313ca1dc4b4e71354898460b58635b9adb7b3ff9ddba0418f6ede34c1d062375ec9391fc02d4e606a594d9d1ecf59c909da258efd968a646261a125f3725ddded9a3fb3733adefba7e1ee3070ca806f4661ec87ef879f57640f1e4f11a29f350454a7aa87592a796668681b1fda3d8a0fc72a6215113365cf2416b3b490e52364a7b11692a778f7eaef25e7a4f98bb8b7ac6b36032f13a6157f4e40f48c679dc80888c8ba806a31a5e393594c176506d221e48edcdd3c3a7427aec594704a0ac1a6d6b64ab361e0812757cdc83778c874c87d4bfa244b5252a9063be3bb7093c4445c44d6dd2fd7f4eb672a3cd4041128", .None}, + {.Shr, "4778b7a3b38e8ed1a2b8f408cd478989b7267fbbdd13f85b99dafac263cd5b546137e5a6dde402bd0de0bbbb97fb5fc494e5f145c43b763da3f012af59dfffb4bf067eb6f20ba88c318db30014c277a14e9d60e0631cce1d1be1b5e6623986cb6d73eeec488439c5e0b979cc775ec26ce4b3644c33a115da59beb67056a79c49e86357ca2d2734feefbfac888c2e763c741a6ecc807e11b1cff43902b65218cb41c5e52cedf0d385e5b594c17710b0b9ac006ced2b520999e5fcae0f22af16bce209a1155d1b0928382a6b84b47c1f08ebd640c6bc078562571eea74a964e4e897702e0f635b47a3d95e789dfa989303eecc8ce4d86e4cb419257238f804be378e5fa71c9775054e8da9029203aaa3ed918033aca405c3702ca940985f58ebe95a46f6a9fb0a3f0a129b2821dd003cda4dcd2d2e74609c7844b2709e111751321c988642224c1d563fef9093ad722457828df6b64910b27e7a57caace2d38265b078dde942ad582a0cbab811ae3f769e4a9089769d0cbfc7fcdc821f8dad91d4f8dffd1b9d392cb6e0ac1ecc4a70dfa2c6231f394447fc7cb8535fe591fe2d34389fcb228d65f4f8e7d56e0a019ab2cb848e95c4e8e021fca804af36c625b078f5a889cc01c876c835a4666f7d479b532a4a6528ce79a4131b890fa7247e4cca996ebfa773541dec15f6b76932bdbd5208abe423149365b58053be1097943942e06cb0babfb515daa708a6f4f8ef0ece6454fa01d8514ff5042aed9e51b55491e8fa1797cbc7b47dedc2afd75e3fc71666822a37827f38cdbf1a09ba9816b15bd673e481bae8e48b361ba3e30a47b56a826fad06f52497ef37b039e95e007340939a54909e1b9fbe91373426b21008f3d1276f06be614c527d777a58b9a40fa12de5be5fabbdca72b4f7eef60f348710e62139d8e1690b914ad6c16a70d3bc3eb80d5ea538ad0ab371b320bffd0e8534b7ba37902ccb82572b2f79f7e58d77ccaf4c30027ed147eaf3975dc02ef3b1e8efb71ada7f300867b9d49ad2e8391eda181e890364e3daa7088ec8e7a159c00dadd7b94da792c38214c185a3f4ecabb884edef2e0434a30d81407b551267964e5d0881940f0b4607909ef9dd32f18f57cc8f4a5f9b40f00306c4a28bbf66304416789cef7f6e75007add1a6990f0d237ef1c1f86c1155376dd028d097c98e65ed1ebed9a1823add55168ea5dbab77f2bfe31a04a10adeb82bfb52d0f354983c4648fd4ac8719d4f71f3e12048fd8b4f9b27c15d0331b8b8b297aa9e7a6d5ee001f6d5df648b785b6e5ec1d9dbfb69509d44eaba4040124d1d1426bd8465d5dbdc6b9cedbd160847bf62a664435cd14498be86468f70b80f55e3063bae85ef261b7b70af1b02cbd89e72af173b9885977f82ff7ba87138f0e3c438857c5988410f67478fbf294211fbaedbecc821417ea9a8e1fd044219fa517bbbb2131b633f08dd3c18055f7e5d5ccac46ee7029534312e915366532ab037e00a86640e520ee504ee4e39c5425c7f61b38ea1d1850bff11dc6e82cc82b32d830b10a71a58164d704404d001e38af47b005f54cefaa4ebc8705ce33e8f55f9bbe451584c7f59b553b42f5df58c4c4dc76213d233f68ef8cb460a56fc11c014e5be56f76b711dc9918b76b2e911c0db4d9c4ad1d37ed13232782c148ee9ca2afa797c7bbdd5558e6003bc29bdcbae33d2f0573b5661932ea848d5b139cac2dfb5d8e562fefe3db6acb5dacccbef5e6d3aa59f73e4844f599135e7cff4bb8aaa2894d5f5ca249307226bac3e84b67d902723112708cec2fc7f339a78d8626c7714c8443efd87d9c8de04dd26bd16bb14adb543c041cbccd386b8de0924c055b2c7a0578d14db64aeca1d660a0d75a6f39f526d608558321f34b2b7dc14ec525951a3b3d10042664aaf67db1b14b72a8cefe0832c3e850d1430150e29731d58f68f6fab267fb76673c0f716a6d61306598332af33c1dd2f03a1b1d35160ebcfed3187429c650b8397b8dbc230b2e571006c7b95e8f9dfc8599f91df7e417ebfe08acfe29a3a4140e7d74e66d292f16b8b0013237ffe01971784a3a96b9247457a9bd94f6afe9ff735265003beec2719d695a9d32", "12c", "4778b7a3b38e8ed1a2b8f408cd478989b7267fbbdd13f85b99dafac263cd5b546137e5a6dde402bd0de0bbbb97fb5fc494e5f145c43b763da3f012af59dfffb4bf067eb6f20ba88c318db30014c277a14e9d60e0631cce1d1be1b5e6623986cb6d73eeec488439c5e0b979cc775ec26ce4b3644c33a115da59beb67056a79c49e86357ca2d2734feefbfac888c2e763c741a6ecc807e11b1cff43902b65218cb41c5e52cedf0d385e5b594c17710b0b9ac006ced2b520999e5fcae0f22af16bce209a1155d1b0928382a6b84b47c1f08ebd640c6bc078562571eea74a964e4e897702e0f635b47a3d95e789dfa989303eecc8ce4d86e4cb419257238f804be378e5fa71c9775054e8da9029203aaa3ed918033aca405c3702ca940985f58ebe95a46f6a9fb0a3f0a129b2821dd003cda4dcd2d2e74609c7844b2709e111751321c988642224c1d563fef9093ad722457828df6b64910b27e7a57caace2d38265b078dde942ad582a0cbab811ae3f769e4a9089769d0cbfc7fcdc821f8dad91d4f8dffd1b9d392cb6e0ac1ecc4a70dfa2c6231f394447fc7cb8535fe591fe2d34389fcb228d65f4f8e7d56e0a019ab2cb848e95c4e8e021fca804af36c625b078f5a889cc01c876c835a4666f7d479b532a4a6528ce79a4131b890fa7247e4cca996ebfa773541dec15f6b76932bdbd5208abe423149365b58053be1097943942e06cb0babfb515daa708a6f4f8ef0ece6454fa01d8514ff5042aed9e51b55491e8fa1797cbc7b47dedc2afd75e3fc71666822a37827f38cdbf1a09ba9816b15bd673e481bae8e48b361ba3e30a47b56a826fad06f52497ef37b039e95e007340939a54909e1b9fbe91373426b21008f3d1276f06be614c527d777a58b9a40fa12de5be5fabbdca72b4f7eef60f348710e62139d8e1690b914ad6c16a70d3bc3eb80d5ea538ad0ab371b320bffd0e8534b7ba37902ccb82572b2f79f7e58d77ccaf4c30027ed147eaf3975dc02ef3b1e8efb71ada7f300867b9d49ad2e8391eda181e890364e3daa7088ec8e7a159c00dadd7b94da792c38214c185a3f4ecabb884edef2e0434a30d81407b551267964e5d0881940f0b4607909ef9dd32f18f57cc8f4a5f9b40f00306c4a28bbf66304416789cef7f6e75007add1a6990f0d237ef1c1f86c1155376dd028d097c98e65ed1ebed9a1823add55168ea5dbab77f2bfe31a04a10adeb82bfb52d0f354983c4648fd4ac8719d4f71f3e12048fd8b4f9b27c15d0331b8b8b297aa9e7a6d5ee001f6d5df648b785b6e5ec1d9dbfb69509d44eaba4040124d1d1426bd8465d5dbdc6b9cedbd160847bf62a664435cd14498be86468f70b80f55e3063bae85ef261b7b70af1b02cbd89e72af173b9885977f82ff7ba87138f0e3c438857c5988410f67478fbf294211fbaedbecc821417ea9a8e1fd044219fa517bbbb2131b633f08dd3c18055f7e5d5ccac46ee7029534312e915366532ab037e00a86640e520ee504ee4e39c5425c7f61b38ea1d1850bff11dc6e82cc82b32d830b10a71a58164d704404d001e38af47b005f54cefaa4ebc8705ce33e8f55f9bbe451584c7f59b553b42f5df58c4c4dc76213d233f68ef8cb460a56fc11c014e5be56f76b711dc9918b76b2e911c0db4d9c4ad1d37ed13232782c148ee9ca2afa797c7bbdd5558e6003bc29bdcbae33d2f0573b5661932ea848d5b139cac2dfb5d8e562fefe3db6acb5dacccbef5e6d3aa59f73e4844f599135e7cff4bb8aaa2894d5f5ca249307226bac3e84b67d902723112708cec2fc7f339a78d8626c7714c8443efd87d9c8de04dd26bd16bb14adb543c041cbccd386b8de0924c055b2c7a0578d14db64aeca1d660a0d75a6f39f526d608558321f34b2b7dc14ec525951a3b3d10042664aaf67db1b14b72a8cefe0832c3e850d1430150e29731d58f68f6fab267fb76673c0f716a6d61306598332af33c1dd2f03a1b1d35160ebcfed3187429c650b8397b8dbc230b2e571006c7b95e8f9dfc8599f91df7e417ebfe08acfe29a3a4140e7d74e66d292f1", .None}, + {.Shr, "1862e1bee372aff3dad5d8fb3a1caaa4cefb93efcdeb5723ec95f27fa043d746fb03a4924844c60c3dc10b0f490681c6917fb509ab77b7b313379db2d6b12efe7dac95d3dfa13d217041fb2a401fc4f56bcc58c08e660de9e3f1904a152a0939ac196ca98d6a5705cdceb202815917418f879594c44d8fee645ded9c2933746eb6a127bc8d5e55a020de90ddef3760877d5e461c92131d81edbb157b518e1e56ba771952a086b72c312696d4e089c0ed67eb5313cd054a66121f95d13d084b32392643ebd1feb99bd17a3dd6227f7ec02ef83c16a28633395c28367331aa0e1d49f4dd7e86bbea6f0619d7d76bbb3f988301419c3f0cb224b825d31a1fb61a381f7a1baa4749eb42b686170a426ec9cbe762bb447b5af6ee5df832eb168cac4a777ae2904778b1dc9dca7bf3ef7df7b2e58fc79141b2ce71c332aab8db611f495721167e59b17d81c5a2fff1971ef8a48e93dac755ee45dc4594ec17e6c125bf8532fcc0c5295a2725a8acbfed55f47506ec89f8ae4ed970cee257bfefadd5c049b28952e21ddd48afbc0ee54899e2d8141de2f4f5689282b7148645de8072a033203875d34d3e6bb2a568faf64848e952d35c6cd39c4c4a6983102d647181b6f3457e47a107a8a7c9af855a2ee21155829a6acd4ad58ab877084ed5ab9b8682da6cefbceda68ef362206fe2100618bf720bafd53efcad686512b71fae4ca2234aa92c5e55f2497f9fbf57a91b40ead8d0502e6188085341dceda6b01f110ec7c45ac6b3213f5bb7a259f3aa8b0461cc46b8d1d9f24bb4c6d7248f59df82c06bc2691023f6cb0694cf75435ae6ebaaea87d801344d136250b6cbd28c4e62620d266eed3e4eb134b98492fcb03d4c5cae153c484c97467a510125489bcd17c19c188baefc4ad1048873b2ba40f12fa0ba888698cdd2e417f93a074c8405297de3f67841191e7a7f4a2531670f2dba971cbe180616ec7d941e360d5123f507e014bbcb1788da0e4ae696137cc33f2778967ff3f8211f1bdea78153e7d4fd088f6cf2a5826e6bfa5f42127c6c4699d6b3ad3011b8ec2d4784612793557661dc74cc8406a39eade9cbdc1b2bc11ed13ff8bb99ba5d73387e66ebd084c5834abe859b999c36de2cbb4816cddae24c1052eca5ad179fb0bc108edac0b21671b6529f303fcc9729e3758501f58517cf77ae1c4f5fa56adc06c906bc68f64481effaaacc6a909c7a677e295c0ef1436e34eba87e3fc8f47e7ac5c2c0da208aaeee55066767930237092f40ea204878223b7fe8289b5ca6efc31f118be3dcbc12dffb86cf5c7200f44c2baf08934758b187aa62ddd30df4afb9741fbd60647214a79f9c8846520c1c8ac6b3c8bd0e002483b86965b8dd63cae7435fa3131bbd35d94858b1d63e21af92fecf59e11784deb629118d052b4c0520e99b016d42ed5a8142f4eed6138b9840b0e697c31202c29cb617a00299d9146541caa9cc8dedb2e9355f6c55dcf7c590b21e002f110929c44c5945407fb5c7e2ae4c44a15825a8f876958d050e35a05822e573adcd82f0d53b3dc8760ad98d860d2b2c674816273c7bd9b6c5db072a1d2b1cfcdd2da475948c818c67026fb1fea6ead0f34d25fd69f5bfc07531c51a55379740d9dd36c36925bb186b7c921d445dec0f5e0f0d7882e45a418df5f68b39965dd9b9a1fcb52e06b6b89616ee29a86c8b78a575db09aba3d98b2b4b3169f64446cd878ee62aed8754ab6248ed959d0770deac6d3a45b70d2c6564c210ff3bb0622a17c7f1c78b119b3874d0556cde451397b113bb41b00f69c5df315b33ddfe27f1c04c398ba86594eb1b877d823db40f8b96b27c59cba8f8e7cf60743ad0a4e34e3cb8feac9d4cc31a443f8e4615094193aa0078ddbcee2cc5c7af02a43217d92de0d2365fd6ccf94f67ec56966a2e5c2f8f244bf61c8b6e2864cf0763b4f255bec4e02986c53fadee72c731e1bfbc60fe357318de43e23c95093dc799804dd81a49e0d1bdf9b6bf227bded8b62680b47dea6781ac04ba49fcfe9130c35bcb249c6187a8b3a416819348eeafb8174e0e523c3754a5c6e36d53e0b9440cdb3e6a7d765d946f4915351a79652a64ae682a1917420ad5", "f0", "1862e1bee372aff3dad5d8fb3a1caaa4cefb93efcdeb5723ec95f27fa043d746fb03a4924844c60c3dc10b0f490681c6917fb509ab77b7b313379db2d6b12efe7dac95d3dfa13d217041fb2a401fc4f56bcc58c08e660de9e3f1904a152a0939ac196ca98d6a5705cdceb202815917418f879594c44d8fee645ded9c2933746eb6a127bc8d5e55a020de90ddef3760877d5e461c92131d81edbb157b518e1e56ba771952a086b72c312696d4e089c0ed67eb5313cd054a66121f95d13d084b32392643ebd1feb99bd17a3dd6227f7ec02ef83c16a28633395c28367331aa0e1d49f4dd7e86bbea6f0619d7d76bbb3f988301419c3f0cb224b825d31a1fb61a381f7a1baa4749eb42b686170a426ec9cbe762bb447b5af6ee5df832eb168cac4a777ae2904778b1dc9dca7bf3ef7df7b2e58fc79141b2ce71c332aab8db611f495721167e59b17d81c5a2fff1971ef8a48e93dac755ee45dc4594ec17e6c125bf8532fcc0c5295a2725a8acbfed55f47506ec89f8ae4ed970cee257bfefadd5c049b28952e21ddd48afbc0ee54899e2d8141de2f4f5689282b7148645de8072a033203875d34d3e6bb2a568faf64848e952d35c6cd39c4c4a6983102d647181b6f3457e47a107a8a7c9af855a2ee21155829a6acd4ad58ab877084ed5ab9b8682da6cefbceda68ef362206fe2100618bf720bafd53efcad686512b71fae4ca2234aa92c5e55f2497f9fbf57a91b40ead8d0502e6188085341dceda6b01f110ec7c45ac6b3213f5bb7a259f3aa8b0461cc46b8d1d9f24bb4c6d7248f59df82c06bc2691023f6cb0694cf75435ae6ebaaea87d801344d136250b6cbd28c4e62620d266eed3e4eb134b98492fcb03d4c5cae153c484c97467a510125489bcd17c19c188baefc4ad1048873b2ba40f12fa0ba888698cdd2e417f93a074c8405297de3f67841191e7a7f4a2531670f2dba971cbe180616ec7d941e360d5123f507e014bbcb1788da0e4ae696137cc33f2778967ff3f8211f1bdea78153e7d4fd088f6cf2a5826e6bfa5f42127c6c4699d6b3ad3011b8ec2d4784612793557661dc74cc8406a39eade9cbdc1b2bc11ed13ff8bb99ba5d73387e66ebd084c5834abe859b999c36de2cbb4816cddae24c1052eca5ad179fb0bc108edac0b21671b6529f303fcc9729e3758501f58517cf77ae1c4f5fa56adc06c906bc68f64481effaaacc6a909c7a677e295c0ef1436e34eba87e3fc8f47e7ac5c2c0da208aaeee55066767930237092f40ea204878223b7fe8289b5ca6efc31f118be3dcbc12dffb86cf5c7200f44c2baf08934758b187aa62ddd30df4afb9741fbd60647214a79f9c8846520c1c8ac6b3c8bd0e002483b86965b8dd63cae7435fa3131bbd35d94858b1d63e21af92fecf59e11784deb629118d052b4c0520e99b016d42ed5a8142f4eed6138b9840b0e697c31202c29cb617a00299d9146541caa9cc8dedb2e9355f6c55dcf7c590b21e002f110929c44c5945407fb5c7e2ae4c44a15825a8f876958d050e35a05822e573adcd82f0d53b3dc8760ad98d860d2b2c674816273c7bd9b6c5db072a1d2b1cfcdd2da475948c818c67026fb1fea6ead0f34d25fd69f5bfc07531c51a55379740d9dd36c36925bb186b7c921d445dec0f5e0f0d7882e45a418df5f68b39965dd9b9a1fcb52e06b6b89616ee29a86c8b78a575db09aba3d98b2b4b3169f64446cd878ee62aed8754ab6248ed959d0770deac6d3a45b70d2c6564c210ff3bb0622a17c7f1c78b119b3874d0556cde451397b113bb41b00f69c5df315b33ddfe27f1c04c398ba86594eb1b877d823db40f8b96b27c59cba8f8e7cf60743ad0a4e34e3cb8feac9d4cc31a443f8e4615094193aa0078ddbcee2cc5c7af02a43217d92de0d2365fd6ccf94f67ec56966a2e5c2f8f244bf61c8b6e2864cf0763b4f255bec4e02986c53fadee72c731e1bfbc60fe357318de43e23c95093dc799804dd81a49e0d1bdf9b6bf227bded8b62680b47dea6781ac04ba49fcfe9130c35bcb249c6187a8b3a416819348eeafb8174e0e523c3754a5c6e3", .None}, + {.Shr, "cd77b4f33fd64972981f3ff8f95c35e3b06cad5bcd6e92028b241657746f47b36d7437410e9ed00a0c994bb587057224aee681ff0a4c556d34b84d1056c04c7ff59e95b403560e043ef62f8d7bd717cabb55d67008995f10a8733b15e82edcb169cd308f2a5719ce3f119b0ff85ce863246cbab13b124051fb1977dbeea2b71df733fb68bcc25a333e1d3dad7500d46d6af385710fb8fede22dc939ea31bef4440f7f9bfc6db5a3debdd1ca64d970d3edbcbf492afbdb5f40bef44f431e0afd6ef765b3c0e7765b706a1e3f6dcc5afa753f1bec562f799926b99140d55563facf0477ddac25f0ef3e34866a8047b2acbe137064cf8d9ef6e49b182f05e93b59dd2f174ee52603052f4ff5a49b3cbf8ee24ee392dcb05260ad1f94907a5ff885e2fdccea16d189182261e350a69682cc0f0874b756d907ab8f04e74cb89a0455f5f2a31b11f33f7298b1c0772a957c937490d33bea1ce87eb4303a064861590f12c9b337c1ce7fbf5950fd708c775059433ccc0a3bc9531152bbb5b6777741b414e5573e31e9a0873007f01983387c1da273798efdf2941ce3525d137402e3e8049154f5d78ba703aa9b68dd2d4d0d6decfb98a572622639018d88c472b38b1e3c0f5a369f856c830f1c6e420fee9c8969c6f26ed84d0f7d7f83bd433f84c4664dd7e052fc8ce3cb468094017431c905f867394da5bd851c8471bc69f534853e3a9b93a48bb7f6ee66b279dc769abf3cdaa0f536d611c3cb8c440826b230f6f92e0727626406357493c66a74e2e7fa8307033d9932d2bf20f69239ee69ca8545e8e8a89afc01a503d27fd81854c947810be532a55be27d4b4157395d47bac88d9b3c188d8c88ae8aa4093971e224eb704abe4afc4e56984041f69e17008ee14d120d1055c2b6c8d204b70dcd60055d83aba8371298ad77846e6692449c321cfa5cf282ad17bd39a7f29a423a60742b8130dad0e6b245e047ffe92f19d54daf882dc638fd10f82c65830abe69cd349b8ac15e2289575a0e4ed1eb799959aa60caa5566cf960b74fefe14304ecccf59d2e9d6ec5c5a1bf4baace304ef13dc692e2105e875c7c7db7bfcb63433905a61900b9a4a3d8fda79c01d9e93db7db35c395d7f10b7aeabd4cf009869beb467c6099d8c1dbdbe632923bcf0ebb02256f26a02578a3a0d2a120c038ed2a2c7890b36e191041a1543508386a1f43f10e1ae633a40fec08ca3e39ecdb0bd3d5408f090769e6ddd2f7d290f951c9c663d528e40bfb005cd975bdc33f5b94670631e2d28fe762a578422c380c00a0b000a34e436e949c4a84e1256cec94e5b26cb1ebcaf69200d382a879357e993cd087358ad3396630c004942c47d4047dbff7dbf3ad3c6dd5ff61ae4686a29bd6208c75f5810c924b6f95446b9709c68026791bb1f6fd5a944c679191396f98481123057f514bda6d4e5ac7aa5e66c6cf587fd2f543fd64a33c10d388e2614b5d52eca99518dd8903898ecbd65d68ca37995374a45041ad063e46dcb1d546d254d639e318662b5d1f71132fa88178757ee677d5f392a274dcad1689be585df0fd1d18d30c88e79ed3aac1e93fe28a734935f4b289990c95552cd88b97d642e0a4ae799e565639a62d939ca9ea2e304f650b2f289a4be33a0b788304bdfd67cbda04431a838ae92d515f6feb33c592f34a6ee6f0812af95072fb5e207d427fb02b2f270ada6ce379d2b4e143b35fec1c4fcd5827864e19881de1cac5648594e20dc004125dcb706e30e508c22c20a11d29eb55b1ef095f2d58d50bbaa8c01f27bc7d12a2e80d6b592aa40150c63c909b6884d9e7ca672f0bea8df9ed3f2eec600444fd5c9211114c1a45f388d2b11eab8d4b51fa7298343928b56a39ea07e27c89249e84119107b817165282cfb50445852e866bfd5460986e80c2f11f9392a8bf68cd7b1102198e73c9d0e9cd86971348ca19cf878c3404ffdb10735fd91750e028e6d75aadc1634369a614b29007a0fb5e8924f8b0692c94815fe883b87f7138ada12ceeec32631fd3a0001eed00e7cef95edda4a4314966e58350a9136a43c086099485dcac4228be3cf84827644dac63efa259d4e92261a75694ac14ac324dab97b", "12c", "cd77b4f33fd64972981f3ff8f95c35e3b06cad5bcd6e92028b241657746f47b36d7437410e9ed00a0c994bb587057224aee681ff0a4c556d34b84d1056c04c7ff59e95b403560e043ef62f8d7bd717cabb55d67008995f10a8733b15e82edcb169cd308f2a5719ce3f119b0ff85ce863246cbab13b124051fb1977dbeea2b71df733fb68bcc25a333e1d3dad7500d46d6af385710fb8fede22dc939ea31bef4440f7f9bfc6db5a3debdd1ca64d970d3edbcbf492afbdb5f40bef44f431e0afd6ef765b3c0e7765b706a1e3f6dcc5afa753f1bec562f799926b99140d55563facf0477ddac25f0ef3e34866a8047b2acbe137064cf8d9ef6e49b182f05e93b59dd2f174ee52603052f4ff5a49b3cbf8ee24ee392dcb05260ad1f94907a5ff885e2fdccea16d189182261e350a69682cc0f0874b756d907ab8f04e74cb89a0455f5f2a31b11f33f7298b1c0772a957c937490d33bea1ce87eb4303a064861590f12c9b337c1ce7fbf5950fd708c775059433ccc0a3bc9531152bbb5b6777741b414e5573e31e9a0873007f01983387c1da273798efdf2941ce3525d137402e3e8049154f5d78ba703aa9b68dd2d4d0d6decfb98a572622639018d88c472b38b1e3c0f5a369f856c830f1c6e420fee9c8969c6f26ed84d0f7d7f83bd433f84c4664dd7e052fc8ce3cb468094017431c905f867394da5bd851c8471bc69f534853e3a9b93a48bb7f6ee66b279dc769abf3cdaa0f536d611c3cb8c440826b230f6f92e0727626406357493c66a74e2e7fa8307033d9932d2bf20f69239ee69ca8545e8e8a89afc01a503d27fd81854c947810be532a55be27d4b4157395d47bac88d9b3c188d8c88ae8aa4093971e224eb704abe4afc4e56984041f69e17008ee14d120d1055c2b6c8d204b70dcd60055d83aba8371298ad77846e6692449c321cfa5cf282ad17bd39a7f29a423a60742b8130dad0e6b245e047ffe92f19d54daf882dc638fd10f82c65830abe69cd349b8ac15e2289575a0e4ed1eb799959aa60caa5566cf960b74fefe14304ecccf59d2e9d6ec5c5a1bf4baace304ef13dc692e2105e875c7c7db7bfcb63433905a61900b9a4a3d8fda79c01d9e93db7db35c395d7f10b7aeabd4cf009869beb467c6099d8c1dbdbe632923bcf0ebb02256f26a02578a3a0d2a120c038ed2a2c7890b36e191041a1543508386a1f43f10e1ae633a40fec08ca3e39ecdb0bd3d5408f090769e6ddd2f7d290f951c9c663d528e40bfb005cd975bdc33f5b94670631e2d28fe762a578422c380c00a0b000a34e436e949c4a84e1256cec94e5b26cb1ebcaf69200d382a879357e993cd087358ad3396630c004942c47d4047dbff7dbf3ad3c6dd5ff61ae4686a29bd6208c75f5810c924b6f95446b9709c68026791bb1f6fd5a944c679191396f98481123057f514bda6d4e5ac7aa5e66c6cf587fd2f543fd64a33c10d388e2614b5d52eca99518dd8903898ecbd65d68ca37995374a45041ad063e46dcb1d546d254d639e318662b5d1f71132fa88178757ee677d5f392a274dcad1689be585df0fd1d18d30c88e79ed3aac1e93fe28a734935f4b289990c95552cd88b97d642e0a4ae799e565639a62d939ca9ea2e304f650b2f289a4be33a0b788304bdfd67cbda04431a838ae92d515f6feb33c592f34a6ee6f0812af95072fb5e207d427fb02b2f270ada6ce379d2b4e143b35fec1c4fcd5827864e19881de1cac5648594e20dc004125dcb706e30e508c22c20a11d29eb55b1ef095f2d58d50bbaa8c01f27bc7d12a2e80d6b592aa40150c63c909b6884d9e7ca672f0bea8df9ed3f2eec600444fd5c9211114c1a45f388d2b11eab8d4b51fa7298343928b56a39ea07e27c89249e84119107b817165282cfb50445852e866bfd5460986e80c2f11f9392a8bf68cd7b1102198e73c9d0e9cd86971348ca19cf878c3404ffdb10735fd91750e028e6d75aadc1634369a614b29007a0fb5e8924f8b0692c94815fe883b87f7138ada12ceeec32631fd3a0001eed00e7cef95edda4a4314966e58350a913", .None}, + {.Shr, "993803b52380ac6fd9b30603f62848ad05e4a989cf15c3d6553f14b1607cd9e3a49cfcf028f653b77d4c0aaeb30c3eecd47a24abea0e46444cb8d28b9db1f7465520de625430a873f38795edab91325b274c819cf1edd33432c7b89274e4a94a441dd23e0158d305827525c8b96e216f0bf8ec35bbd704c2969bcfc676191bfb3443e4037ac0bda53a39a3fe9b92ffd9572e32f79b0585430687f5d7d1af97c0d39d83b64eca79ace01576a57f2fc022bdbb904aab7ff98b109babc3ced5f50bc5fc30245265e1789136d55d94fb5d91c0669c5a4f19045f87ec6bcd043663cd7011e78f60fd1f7823ea38173dd7023e13f170b2aa8a7c4fec68f59c40ded21f325734242793ed8b2a3300bec43fb6f3e9d9cbdbad575c6264559599d4a750c330f440d3768fcf818e137125f9bb81bf1df8af69f5067d2711c3a8545283b895c9039f072348ef0284b26dcfc65c570305b9488ab576fe103e1efcac8b31d64878c6e3346f847299cea1f81eae0a07211e09649d722dd2658019d61f7d204b069f3e731f99e9417fba28a270845e54e66e9e4221fe247257b52c4a91a35d031a672101b79286b35f80858721ef4d91c82864659321dd5de387b10042d0317bec7e0d62119126c3b01c366fd87be512e707701d4f1181904e6ca7e2d1103fcd7b68306839b6e8c75ea32060549d24a3aad22b7f68117c3c48bdd60dd3187f51352005b142fb3b92d2337fc5bc0c5fa09491b82d60687285bb13ea0562782862477856a67023fd7ade682ba3ca36eb9898fb1b33f9eab71c6beb20fd037b32e2d8e91a73c6679eac95f0730b711a644702ad021d9262201e74c0fe4d6ea982cbd64257ba74bcc6739a6ab0a7cc09f50bd5a0b1fa5568c20f3e06ef8896321ecd7d364deee60bb9d316c29ad88fe1d429334a01023c6b2a5090ab2b2f68147aecc9ff3a70314e319653d7c6211c9e01316b9123de9526610f4d7aa5f4dafe6b086222f02ce23e608f7e1f5bb957b1793515a81cfa497e47ceba3d6a4d7e6006b7b115e38cf29bc6d822962ef63366ea1043e729841c7bf96242a4fd447eb1decbd357e9dcb00ad003abfcb9d0a598592b1dadd386bfe545607b1f230b82303bedb7f4441a3c6102846c5d0a8fd6ce1ee880eeb23cc5dcff1dc9bdc11ddf3a6fb5a4008bb3b1ee6dad42205844bcde94d88bd971b90a0d1ae4e9d4c4e4623eb32a2e7d1f5746c93d86545fda8f5513fa081930f6732935e6a4595ad2338798fb7ad2e6d09a9fb5820650188b7da8ee5a41f7f06554630ce7ae72a3e7bdc34231607ecc0d0677dba5dec7cf0d0029ffc87da8a908d2031adc188dd9f4df5b09adfec1d78f4edadf687c10700a74bf7738b71c79f66c0c96170962f15b56f8e77bf3d22c4ad90b8b38d216f23513222698de6969bea991149fcd361e7ca7413691aaf2e01fe420c8f1b702e7c2a74366bdf723cb568af929086ca482d2a613f53f00779dc794bd1deee6c452a49fccb793fb9538b2fa9e9567952954c96b0f79411ad6fef89b4f71fd1d9b65f07cdddec92e7d35e9d7758581263464206e94021791cfc37e5f124bae9e8ef5c308db7ed38897ded290a5807fcea2d21ff6d8438baf802abd4c93282e7a18ceb7b491e2e38f534edc3ce492a554b2912583541bd28b2b9acfa0f04d241c5b6010b09c5ba3b4e736c2b00c19790381183b1c1fd0ee7a9efd38cc88091701c1b8690e5a8f91148d24ba50176c13c1d3635428b5386cf94bded7a9dc3b8a6c57e19b152ad131eb7bf101559e98d6bcdd8b121d672524cc15ad5d788aae2b4a1c6b5441ebac338286bdfc8c023ba670a8a5e1a075bc54953f6ea895ab6e422e81aa082c8181d6335b444003172173ade71540530ff4a31bd11fc77b4aade6d8ffd99bb0b40ebd5b7e645623f1c17ddc5217617a91c0f68039919fa1f7c5fee1c366f839c0e4ba1c45638123ca0ef9acf12b521bee3167129e7f38a52b43b97c2aefd00b4600656af9703e6e39cce3ae97846ef6c3aa1a6699e0d34ead8dbcfe3f39126e149061696707924a99c6b3b7e6f39b0b4bc47e9c8020ba94b14eaedd401ff251a078135a2198ea7a0c755e1ade10290773", "b4", "993803b52380ac6fd9b30603f62848ad05e4a989cf15c3d6553f14b1607cd9e3a49cfcf028f653b77d4c0aaeb30c3eecd47a24abea0e46444cb8d28b9db1f7465520de625430a873f38795edab91325b274c819cf1edd33432c7b89274e4a94a441dd23e0158d305827525c8b96e216f0bf8ec35bbd704c2969bcfc676191bfb3443e4037ac0bda53a39a3fe9b92ffd9572e32f79b0585430687f5d7d1af97c0d39d83b64eca79ace01576a57f2fc022bdbb904aab7ff98b109babc3ced5f50bc5fc30245265e1789136d55d94fb5d91c0669c5a4f19045f87ec6bcd043663cd7011e78f60fd1f7823ea38173dd7023e13f170b2aa8a7c4fec68f59c40ded21f325734242793ed8b2a3300bec43fb6f3e9d9cbdbad575c6264559599d4a750c330f440d3768fcf818e137125f9bb81bf1df8af69f5067d2711c3a8545283b895c9039f072348ef0284b26dcfc65c570305b9488ab576fe103e1efcac8b31d64878c6e3346f847299cea1f81eae0a07211e09649d722dd2658019d61f7d204b069f3e731f99e9417fba28a270845e54e66e9e4221fe247257b52c4a91a35d031a672101b79286b35f80858721ef4d91c82864659321dd5de387b10042d0317bec7e0d62119126c3b01c366fd87be512e707701d4f1181904e6ca7e2d1103fcd7b68306839b6e8c75ea32060549d24a3aad22b7f68117c3c48bdd60dd3187f51352005b142fb3b92d2337fc5bc0c5fa09491b82d60687285bb13ea0562782862477856a67023fd7ade682ba3ca36eb9898fb1b33f9eab71c6beb20fd037b32e2d8e91a73c6679eac95f0730b711a644702ad021d9262201e74c0fe4d6ea982cbd64257ba74bcc6739a6ab0a7cc09f50bd5a0b1fa5568c20f3e06ef8896321ecd7d364deee60bb9d316c29ad88fe1d429334a01023c6b2a5090ab2b2f68147aecc9ff3a70314e319653d7c6211c9e01316b9123de9526610f4d7aa5f4dafe6b086222f02ce23e608f7e1f5bb957b1793515a81cfa497e47ceba3d6a4d7e6006b7b115e38cf29bc6d822962ef63366ea1043e729841c7bf96242a4fd447eb1decbd357e9dcb00ad003abfcb9d0a598592b1dadd386bfe545607b1f230b82303bedb7f4441a3c6102846c5d0a8fd6ce1ee880eeb23cc5dcff1dc9bdc11ddf3a6fb5a4008bb3b1ee6dad42205844bcde94d88bd971b90a0d1ae4e9d4c4e4623eb32a2e7d1f5746c93d86545fda8f5513fa081930f6732935e6a4595ad2338798fb7ad2e6d09a9fb5820650188b7da8ee5a41f7f06554630ce7ae72a3e7bdc34231607ecc0d0677dba5dec7cf0d0029ffc87da8a908d2031adc188dd9f4df5b09adfec1d78f4edadf687c10700a74bf7738b71c79f66c0c96170962f15b56f8e77bf3d22c4ad90b8b38d216f23513222698de6969bea991149fcd361e7ca7413691aaf2e01fe420c8f1b702e7c2a74366bdf723cb568af929086ca482d2a613f53f00779dc794bd1deee6c452a49fccb793fb9538b2fa9e9567952954c96b0f79411ad6fef89b4f71fd1d9b65f07cdddec92e7d35e9d7758581263464206e94021791cfc37e5f124bae9e8ef5c308db7ed38897ded290a5807fcea2d21ff6d8438baf802abd4c93282e7a18ceb7b491e2e38f534edc3ce492a554b2912583541bd28b2b9acfa0f04d241c5b6010b09c5ba3b4e736c2b00c19790381183b1c1fd0ee7a9efd38cc88091701c1b8690e5a8f91148d24ba50176c13c1d3635428b5386cf94bded7a9dc3b8a6c57e19b152ad131eb7bf101559e98d6bcdd8b121d672524cc15ad5d788aae2b4a1c6b5441ebac338286bdfc8c023ba670a8a5e1a075bc54953f6ea895ab6e422e81aa082c8181d6335b444003172173ade71540530ff4a31bd11fc77b4aade6d8ffd99bb0b40ebd5b7e645623f1c17ddc5217617a91c0f68039919fa1f7c5fee1c366f839c0e4ba1c45638123ca0ef9acf12b521bee3167129e7f38a52b43b97c2aefd00b4600656af9703e6e39cce3ae97846ef6c3aa1a6699e0d34ead8dbcfe3f39126e149061696707924a99c6b3b7e6f39b0b4bc47e9c8020ba94b14ea", .None}, + {.Shr, "70b2d450bca9707fdc1b6639a1263eba42aecf5f03499f9621e1e2649be4b73c3a7ec296d67b64a6bd64d5f69bc13119433e783f4b8fbb0c8cf345aa88486f190a8c884b4f4ff6ce7b862b80b2dedce4865c0250cd99a603e4a1a55f544b5895bc17abe2b4c5f124981fb8b94707adef19273a246f97f148d60fecb4db94ab2ef1876a7a8c4cf5daa2b874bee5eb00d19bf380269b2bc0fc6c24846a709496b9f5fe15c8f50c924a0005bfad21056cea465f1638d360568bd2cf19fa34c2222b6d31310ab9be16c71be57a101525cf21f3703c4e834211942beb863c3cc18768fc2ca4f3aa921a7cfc8ece943e405821369625bca40ae4a4a422cb2f8a28b1bb106ba1fcbc3f25ec754d33bb11b5d8f1c4b0fb982fe8e62d8de2704d7f62ca29ed278eae225f97022f7ffe230de80fc714b4d66ea457e04d2a1618c442508bd58efede284c654709fc285ec7285ee79a6f3bf42d8f619050d3b08fd495858205c329a1f5ef5ffd7ae2a100c7f32bde6820019ee55d426e6496021f1c3b220405a90d16657e2f011285af5b46ef7ba10267103dc73027ad8fe1787ad4188b587413cfe1e51f4fc3ebc84472f675ec1805d8682d9472449dda6d4f97b300337836b1e99dfce4d606c8dd8b750d8e794c663b13f3e6ff0116775144cf52a4558e47e2564cbe286c3ec5f1dd0d84b9539daaafc3e18fcdfb23c60609e542687fa63cbabdde94fb2c5c56e7fd5138e3719ccc96b12d5bc684d28ae93ebef21444af1ac306be59f36906febbd833ec38dcad59c13710283d632881d31bac45a5e3cc984d0d61809c1fe0d8119798fd1375bde6e86ec0257cc2aa9ccbd24d8565070c1061e82d05c07b8ae09ad227ab97fd49b306062b51b54ad22adc1ccf3b850b739901b74ddccb8c2b80f2c0932064f7c3af66195d520b27cbc0b17d974880a288404490f28e639472ebc78097836b8211a1c6294aa2ca1205cd389e3b3b8b1188bcf8322fe964b0eb1b68d2a4dc5ade3c952e6bf1a399611be0ffcd5cbee2fa170100093d6fa17576e1de5ac3a2bc8d6953427080067f3046c6cd702697a1fe2291a91993372d88c0b1cf85b1eaffa90ad6158e8894a1b88d9f3ec793bf6f8dfbab9bfc204d09fbaa48694d49202547cd48d5e670b2e5a460bb7a19520c0427747f77b885fc1fd85918399c0f893b4a19d19c458f27817933fbbc1df49e0fcc438889560416dbeb3903513ec872ab54f778a404d59198017529b2c5782326ba9c1e14e59463fa4a5008e09e07fe323680ef77b13c5c1f1eb7302e3d5d1470039e36ace9e84429313642478cd6eb8603633dac84ace25504d1ee7719f2f724490eb9e1fc91a1ef2be49c4f50ff222de3bf1482cb2797029ed4cd58e324a285c662d84c66b701124ebe519c5cccb0579dc01dda46f452cf023156f14aa014a21e6d05a8ba946f038713ff51320e975c8ee196e512f06c6286770e6ab61dc3fa153b63808044746b48cb3ab3b443f8e20a28d72a21b8fc8487f4c48cf4e08e5a8d2a7b2e652337bd4a4a86a67ab25fe0f05e189c9e2b773142ea6e43d8335d5a500a12dc4b4f595f21caa7df4c6dda7ebe67296da1360783066dd27ad79d2e4726eceb9d58973b67f4bf8373123ab6dc68cc4de4d869372c6eba60f4e26c9d148d60d3f178b0ce9fc5d2e76469ac4335b0a59d1ee46c975682967a65e8beff17672054996fe3d9038a20b3816239d37b57b9a9e3fb9df71e964bf6a7a06efb8e962747cded064b6d58904e7df41e0d01fd358cda5455ab0a6d816b530a049a4e1bcc60db8d8570d2a00d4e35be1055c435206221897567411333fc9ffcfddc47e5bbc6544771a75cf5fb1f456ad3e6153f3e8e9486daf1d1fd2fd196e48b03ab4df1c790d37dbd1eeeea9dddfda56404c7a354137a227d293352dc4c2396bf5d94a2b13f9275f24e32281687444c9fc972b4c7c921cd75530885cdfe0cbd7f4e42bfd7251576d5d78f0b0d1f07a74613abbf01aeb05174a72d2d07126b08abea11923ec8858d8b56cb02883d883005b02e0abf8784f9c440d764263958095595dc5ef0c1d8bb72ab11211f96705314e65625ef3a09c6e31f391be0d3e7bd40", "78", "70b2d450bca9707fdc1b6639a1263eba42aecf5f03499f9621e1e2649be4b73c3a7ec296d67b64a6bd64d5f69bc13119433e783f4b8fbb0c8cf345aa88486f190a8c884b4f4ff6ce7b862b80b2dedce4865c0250cd99a603e4a1a55f544b5895bc17abe2b4c5f124981fb8b94707adef19273a246f97f148d60fecb4db94ab2ef1876a7a8c4cf5daa2b874bee5eb00d19bf380269b2bc0fc6c24846a709496b9f5fe15c8f50c924a0005bfad21056cea465f1638d360568bd2cf19fa34c2222b6d31310ab9be16c71be57a101525cf21f3703c4e834211942beb863c3cc18768fc2ca4f3aa921a7cfc8ece943e405821369625bca40ae4a4a422cb2f8a28b1bb106ba1fcbc3f25ec754d33bb11b5d8f1c4b0fb982fe8e62d8de2704d7f62ca29ed278eae225f97022f7ffe230de80fc714b4d66ea457e04d2a1618c442508bd58efede284c654709fc285ec7285ee79a6f3bf42d8f619050d3b08fd495858205c329a1f5ef5ffd7ae2a100c7f32bde6820019ee55d426e6496021f1c3b220405a90d16657e2f011285af5b46ef7ba10267103dc73027ad8fe1787ad4188b587413cfe1e51f4fc3ebc84472f675ec1805d8682d9472449dda6d4f97b300337836b1e99dfce4d606c8dd8b750d8e794c663b13f3e6ff0116775144cf52a4558e47e2564cbe286c3ec5f1dd0d84b9539daaafc3e18fcdfb23c60609e542687fa63cbabdde94fb2c5c56e7fd5138e3719ccc96b12d5bc684d28ae93ebef21444af1ac306be59f36906febbd833ec38dcad59c13710283d632881d31bac45a5e3cc984d0d61809c1fe0d8119798fd1375bde6e86ec0257cc2aa9ccbd24d8565070c1061e82d05c07b8ae09ad227ab97fd49b306062b51b54ad22adc1ccf3b850b739901b74ddccb8c2b80f2c0932064f7c3af66195d520b27cbc0b17d974880a288404490f28e639472ebc78097836b8211a1c6294aa2ca1205cd389e3b3b8b1188bcf8322fe964b0eb1b68d2a4dc5ade3c952e6bf1a399611be0ffcd5cbee2fa170100093d6fa17576e1de5ac3a2bc8d6953427080067f3046c6cd702697a1fe2291a91993372d88c0b1cf85b1eaffa90ad6158e8894a1b88d9f3ec793bf6f8dfbab9bfc204d09fbaa48694d49202547cd48d5e670b2e5a460bb7a19520c0427747f77b885fc1fd85918399c0f893b4a19d19c458f27817933fbbc1df49e0fcc438889560416dbeb3903513ec872ab54f778a404d59198017529b2c5782326ba9c1e14e59463fa4a5008e09e07fe323680ef77b13c5c1f1eb7302e3d5d1470039e36ace9e84429313642478cd6eb8603633dac84ace25504d1ee7719f2f724490eb9e1fc91a1ef2be49c4f50ff222de3bf1482cb2797029ed4cd58e324a285c662d84c66b701124ebe519c5cccb0579dc01dda46f452cf023156f14aa014a21e6d05a8ba946f038713ff51320e975c8ee196e512f06c6286770e6ab61dc3fa153b63808044746b48cb3ab3b443f8e20a28d72a21b8fc8487f4c48cf4e08e5a8d2a7b2e652337bd4a4a86a67ab25fe0f05e189c9e2b773142ea6e43d8335d5a500a12dc4b4f595f21caa7df4c6dda7ebe67296da1360783066dd27ad79d2e4726eceb9d58973b67f4bf8373123ab6dc68cc4de4d869372c6eba60f4e26c9d148d60d3f178b0ce9fc5d2e76469ac4335b0a59d1ee46c975682967a65e8beff17672054996fe3d9038a20b3816239d37b57b9a9e3fb9df71e964bf6a7a06efb8e962747cded064b6d58904e7df41e0d01fd358cda5455ab0a6d816b530a049a4e1bcc60db8d8570d2a00d4e35be1055c435206221897567411333fc9ffcfddc47e5bbc6544771a75cf5fb1f456ad3e6153f3e8e9486daf1d1fd2fd196e48b03ab4df1c790d37dbd1eeeea9dddfda56404c7a354137a227d293352dc4c2396bf5d94a2b13f9275f24e32281687444c9fc972b4c7c921cd75530885cdfe0cbd7f4e42bfd7251576d5d78f0b0d1f07a74613abbf01aeb05174a72d2d07126b08abea11923ec8858d8b56cb02883d883005b02e0abf8784f9c440d764263958095595dc5ef0c1d8bb72ab11211f96705314e6", .None}, + {.Shr, "4fdced961a9275ba41cfc440ae6b92b29c31a203764f19ca2511a46844c8768db91099f693a629775b0e16403d530468c5f858c0a52a1d238477643bd06c40971284f5857110b93043e6a60bcb5beb707e536383824bff582e2e64fa2a674c8de8dbaeb40e66aa19b32f940b44d2b896173df6e8fc2fa24035490c4040bc0e6a725d0f864150db1f5f2c727cd8a328f6836955462762402a318c7458004f4c4b7868662a5acce9680199ee042fe3b85e503b47a98ce487a01db2d8e8ee11ace87e682aa563621ad3c7fe719f9ba88b8e9859e11a9a6f8a30239d1014c08e10f5c0380a60c84cc9c64000876780b90f4c32f518c5c7cfc691f24ea91cf11fe86573492185d9a2759e59ab1960b1fb813720327b957bc90707552bbb0d50770946a9616d44b459d583184095996a3a07a8bb4501b1eaa630ab8e26bb1f8ba1bf98b4ba4b918ffaf036b25b57b847c133e0c3b8f302ddb0edc01c8325d18c6e356044ad3b86706b83c2a6d056f076c5072b026821debd88e8c34a6487045b872ac70541737dda3722d54596c617141e224236101f9b459b1d741c82683513ce2ce4f527a107fcef0054c2df26eba90315dd1dd700bc4d871de96b99c129327ed9335276ddf71ffadf8d2a18d4221a4c30f4ce7ca58165767faf7dfea15bd205f4405a087170ad1181df0558f3a97e7b751e8fd2d3dca2738b190974b4d5b6cbcc943e28035ec697f33acc9bf57625b2d21ef34eb59d27c21d97b1f638af5933984b7a1caa95067f5ba887f30f3464211aa6249352f1837fdeabf39f224e3909d49f311dcbaf38087b9873a79701aff34e4ad25c6f44de403bd365a265ef5504a40df84d0072a01b5260b08161d5759a6057f053304e07307471d50983c6fb50eeadba12c7a6ee201888e13f45bb2103f914988300118db565f7d3e57638f47fc58bd971b098754593a0b93fba9ad3d16e78e418499dda3f00ab7f581b66351d776a463d16e03ae4a480444ed636ff74d06878cdbde2a63210c67c89187fa2065ead23dc07356c4f08dbf22b7cadbb1f400c3b0060b58681be9438dce9ed07ff669b6d21b5c8ad1797cebfd9627dc92a3ad38d973cfb07735333f196b35a2371ee63c71ebbddcdd0dfd49af5e3de5ed55d37897b9aedeb75f5adc60d22272ad5c261b6f35dc0e2e52aa7c673edb422ac3461ae1d91ba6b943b083561e644e5fda1e290283873c6c8f7d953e97b8df92b9f3969f438487eee55ea317044065e17825135155a0fb1818b805ca430b208e9263b54620d57f5b22a0d98280752906633caa19ae066b006176bd40f77bd635fa2cb72ca1f32941e7d53ec4ca0ba08bf8d0ffd56d703e486d334f57046b82f06bc7e59cd2f0e46bd7501d1415be469666d11483f84917fad769912a0652f8732cf4be2c90fd9e127cdfc50875902e8afccae3d496bd31a351155f1a7cfdfc2386120583fa089a16c6e4f027d8f40d03b08b66bdb3674102c804ea32ac604271255f017785574b9be0a3e542eb19398b976ccb17a25b753819b740a6d3d850ee4d19f34167b1eff6aa74fdf89eb3889d514a6992fd718a1593054288f7d6f5b8da836eea43cb002ca8bac9552670fd9d95d5ee9b1ad13b0f5ce815ceb0c52b39569a362e4fa3aee2d4e34ea715d88fe328ed2a1d33643943e92cab85885e0bea1651ac301f1b02b546f1be8cac07fd70f55654df82e0b4a81fd6b6e13544d62361bb22ac6221316011c448a2af812b5a59063291c43d12b7b289cbf68c95f0189eee0b0b2b40f238723a3e1e790e72d1709bf4541c6fc9ae5ebd1200a48420826911b4d7be747d6043b328ed96a173d483bc50f5197cc71d7cd4a99698a0905778bd90d4a2febf8e6fc2de2e52d554512efff3498fcf60887a64d7942b97ba163f43172d578ef43ab4b6b729ebcf59e32ff5bc262be2fa70d119d0d6557e549f21ea2d802b9f582f6bf997d097d76c1ab4945b11f40b9746138a79103cba236981cc3a9447684da21ab30ff8495960dc4caa08343513fd195624f0248b212389b94fe07b983bfa4e838555bcb11bb1eeaabb142094033c46fc1ed1e2ac1099b8b4608f38519174cf6b94ff0962287", "21c", "4fdced961a9275ba41cfc440ae6b92b29c31a203764f19ca2511a46844c8768db91099f693a629775b0e16403d530468c5f858c0a52a1d238477643bd06c40971284f5857110b93043e6a60bcb5beb707e536383824bff582e2e64fa2a674c8de8dbaeb40e66aa19b32f940b44d2b896173df6e8fc2fa24035490c4040bc0e6a725d0f864150db1f5f2c727cd8a328f6836955462762402a318c7458004f4c4b7868662a5acce9680199ee042fe3b85e503b47a98ce487a01db2d8e8ee11ace87e682aa563621ad3c7fe719f9ba88b8e9859e11a9a6f8a30239d1014c08e10f5c0380a60c84cc9c64000876780b90f4c32f518c5c7cfc691f24ea91cf11fe86573492185d9a2759e59ab1960b1fb813720327b957bc90707552bbb0d50770946a9616d44b459d583184095996a3a07a8bb4501b1eaa630ab8e26bb1f8ba1bf98b4ba4b918ffaf036b25b57b847c133e0c3b8f302ddb0edc01c8325d18c6e356044ad3b86706b83c2a6d056f076c5072b026821debd88e8c34a6487045b872ac70541737dda3722d54596c617141e224236101f9b459b1d741c82683513ce2ce4f527a107fcef0054c2df26eba90315dd1dd700bc4d871de96b99c129327ed9335276ddf71ffadf8d2a18d4221a4c30f4ce7ca58165767faf7dfea15bd205f4405a087170ad1181df0558f3a97e7b751e8fd2d3dca2738b190974b4d5b6cbcc943e28035ec697f33acc9bf57625b2d21ef34eb59d27c21d97b1f638af5933984b7a1caa95067f5ba887f30f3464211aa6249352f1837fdeabf39f224e3909d49f311dcbaf38087b9873a79701aff34e4ad25c6f44de403bd365a265ef5504a40df84d0072a01b5260b08161d5759a6057f053304e07307471d50983c6fb50eeadba12c7a6ee201888e13f45bb2103f914988300118db565f7d3e57638f47fc58bd971b098754593a0b93fba9ad3d16e78e418499dda3f00ab7f581b66351d776a463d16e03ae4a480444ed636ff74d06878cdbde2a63210c67c89187fa2065ead23dc07356c4f08dbf22b7cadbb1f400c3b0060b58681be9438dce9ed07ff669b6d21b5c8ad1797cebfd9627dc92a3ad38d973cfb07735333f196b35a2371ee63c71ebbddcdd0dfd49af5e3de5ed55d37897b9aedeb75f5adc60d22272ad5c261b6f35dc0e2e52aa7c673edb422ac3461ae1d91ba6b943b083561e644e5fda1e290283873c6c8f7d953e97b8df92b9f3969f438487eee55ea317044065e17825135155a0fb1818b805ca430b208e9263b54620d57f5b22a0d98280752906633caa19ae066b006176bd40f77bd635fa2cb72ca1f32941e7d53ec4ca0ba08bf8d0ffd56d703e486d334f57046b82f06bc7e59cd2f0e46bd7501d1415be469666d11483f84917fad769912a0652f8732cf4be2c90fd9e127cdfc50875902e8afccae3d496bd31a351155f1a7cfdfc2386120583fa089a16c6e4f027d8f40d03b08b66bdb3674102c804ea32ac604271255f017785574b9be0a3e542eb19398b976ccb17a25b753819b740a6d3d850ee4d19f34167b1eff6aa74fdf89eb3889d514a6992fd718a1593054288f7d6f5b8da836eea43cb002ca8bac9552670fd9d95d5ee9b1ad13b0f5ce815ceb0c52b39569a362e4fa3aee2d4e34ea715d88fe328ed2a1d33643943e92cab85885e0bea1651ac301f1b02b546f1be8cac07fd70f55654df82e0b4a81fd6b6e13544d62361bb22ac6221316011c448a2af812b5a59063291c43d12b7b289cbf68c95f0189eee0b0b2b40f238723a3e1e790e72d1709bf4541c6fc9ae5ebd1200a48420826911b4d7be747d6043b328ed96a173d483bc50f5197cc71d7cd4a99698a0905778bd90d4a2febf8e6fc2de2e52d554512efff3498fcf60887a64d7942b97ba163f43172d578ef43ab4b6b729ebcf59e32ff5bc262be2fa70d119d0d6557e549f21ea2d802b9f582f6bf997d097d76c1ab4945b11f40b9746138a79103cba236981cc3a9447684da21ab30f", .None}, + {.Shr, "1a0a5b453c877ec81f6a23a01b452fcd90e20bd6b6a9a08798222403f556b269c62048513cd1c57e9be2e17de90f1cf4725f0bc3990b0de84748d4ae569a55f0f5e0a71a7e59aecd9e2b139ca32636c3615239f0e0ef13d1dba91ebc61ef408fdea858a992cf132d47dfb97ad09c6f893a88a6591a4d2b2a89a42fc1284b7e2d6305b5c2f8a8d5b56a50219ffae0d98c4a3c83fdbe3ba84250e5e048491b145afa4a392f1ee38e742874d3c5e001bc30083db2802f727d18c6e1236e369a25460b2a8767a275dbd9376efbac5dfebec2277b88364f306eb313c99de0ede2fed752b9c375019364d7738579117dcd1287150be559415b48e9b4b62c3ffb5eea6adbbdc0c84112e8dcd88842f2ad69d3380330582e1299d56f7921aa075bd7fc72e421d077d09569c71a8e835cf7a043be5eed181860ef2e72c29825e391db4ced0f10183cd963f6ddd524da525f07ece60fea69b4ac47df9afbb71ea6ac50fa3ef21b4586cde5ac5f8b6d1b42512b4d3a65679a6d5a2c8e38791195136b30a2cc445c24159a8ea7e4d447af3421577b322dc030393a4807781b2d6dd98a120a6d94111d0dc3ebb13a786f2a301e283a2b4e1937fb5459f0147c087212ddc7e48cbc11ad271929490ff2f70bb4cabe03ca8fac31ac649fe01b0ea818e9eb6a65fddc23c0325855a9022282691f211f30104261c4ff2fe5cd243f8087027cf8d2080c68c21698763b94bb6a45d386b7177bfa9c469475c97e941f43bd78a6916688c7233fd3cc6ec3ede49d10d7e15a6815f9e200f891b57a7f1a887f4c1a0a11834988593027a4e27a3ed9a20f040620113627b966fab532429d16898190d2594b9a11fabf44ffc7ee2e3555b65ecb552f17b5788d8e12c56d7bc8847eb49a463b3398931f68fb07010839eed4fe0d1b7b74d67ae65117a2945d911b5d15b91c2c56c58ac99b523cb814a3ad1e9351b15fa957d4fdddeec5dbc787fe91675e8e77872976e9ee025e4cacddf10af98aa9ff4344936b50892d17a5c248d0fb69bc53c1a9a325d59c103cc3004f46208f27a506c1e03d84c4696dd4284f620a8e2a127f35288be641251dd2590bc0fafcf317c4e62fe50b58e8ba5c62efef001c6cd672194eb705689637b8a7328eec1849bc144cbb13a53329da4a25c7110b323c93f150da62627c81741769d2fc2359e616b8f06538627843632b6652a7e1448e0555725900df0b07ccb020ddcc5af3d4a277229912e3a9ef2a2cce8c1e5b3275890bf8614c435f9226e081d32568b6eec0d18edf3d8f5263257f461f2630a0a05e346c140a917204d97ae485b9d244c8a23d22178af6bc6a4323a02bd246f54fbc8f9c359d3a98fd3f41b9e05a8fa1045511002776b3358b28b73c8a85050d3b0b290a11f48d90fbf8f1e3c734327fa0df2558ad8510b3bd0d0b03dffe4e612b2bda53cbe431e98289ab5d9cefcd54b970e8d8b867b3c8b277ef10f035b50c6e7a048c453bb4ce24e40e9902606f2db0c5862a8622fee83b1bcb0211b24ac38f9c4fcf2730e77ba8f8c034c62bf82495a52666cc5cf46e76da03b24141c89bb6d219d092dcaf0122fdf14312b73d70fcb4b96e78378dbb1ff35a690b4b240e11b551b160eea8a94d5e020ceb683d576b3dddac5c02fdefbad6c5b136440b4c05562560c453e661e2020b6a24f8d265e5c9efe0336752811e92700bc8fc6191705f3aa34f3fac4979b6cd655f2db03d74abd955725eb91ee3e54df46743ed05e391acb7b6bfe4464179bc0a3eb46169dbc5d44e4b41306b727bbe993d235a9e58290c64061b32ba93552d696ef100936430907e17e368824464a79217d5f58563cd89061fc3da35baa217621dde692b59f1362027e31991b0c15918f4fb46fa6c8329b612faa96e95dfef64aab59e6d811b7f2444a4ef742010731c1cd910dd19c1a3c616344cfb2cf4b68671ea5f41cc0796588e1f020e0675c80eeaf7dbb683d1e1a98b9ff76010714e7503274ba1adaa33e1128b4bb3b50567d6eb5577532d2f0736e27107fb224e1571d436fae79ff118410f153574f3d9693c1fe21263972327505fe7c7343608214d4f669f85ced6b094ba45484c7bc9218b0ea4", "258", "1a0a5b453c877ec81f6a23a01b452fcd90e20bd6b6a9a08798222403f556b269c62048513cd1c57e9be2e17de90f1cf4725f0bc3990b0de84748d4ae569a55f0f5e0a71a7e59aecd9e2b139ca32636c3615239f0e0ef13d1dba91ebc61ef408fdea858a992cf132d47dfb97ad09c6f893a88a6591a4d2b2a89a42fc1284b7e2d6305b5c2f8a8d5b56a50219ffae0d98c4a3c83fdbe3ba84250e5e048491b145afa4a392f1ee38e742874d3c5e001bc30083db2802f727d18c6e1236e369a25460b2a8767a275dbd9376efbac5dfebec2277b88364f306eb313c99de0ede2fed752b9c375019364d7738579117dcd1287150be559415b48e9b4b62c3ffb5eea6adbbdc0c84112e8dcd88842f2ad69d3380330582e1299d56f7921aa075bd7fc72e421d077d09569c71a8e835cf7a043be5eed181860ef2e72c29825e391db4ced0f10183cd963f6ddd524da525f07ece60fea69b4ac47df9afbb71ea6ac50fa3ef21b4586cde5ac5f8b6d1b42512b4d3a65679a6d5a2c8e38791195136b30a2cc445c24159a8ea7e4d447af3421577b322dc030393a4807781b2d6dd98a120a6d94111d0dc3ebb13a786f2a301e283a2b4e1937fb5459f0147c087212ddc7e48cbc11ad271929490ff2f70bb4cabe03ca8fac31ac649fe01b0ea818e9eb6a65fddc23c0325855a9022282691f211f30104261c4ff2fe5cd243f8087027cf8d2080c68c21698763b94bb6a45d386b7177bfa9c469475c97e941f43bd78a6916688c7233fd3cc6ec3ede49d10d7e15a6815f9e200f891b57a7f1a887f4c1a0a11834988593027a4e27a3ed9a20f040620113627b966fab532429d16898190d2594b9a11fabf44ffc7ee2e3555b65ecb552f17b5788d8e12c56d7bc8847eb49a463b3398931f68fb07010839eed4fe0d1b7b74d67ae65117a2945d911b5d15b91c2c56c58ac99b523cb814a3ad1e9351b15fa957d4fdddeec5dbc787fe91675e8e77872976e9ee025e4cacddf10af98aa9ff4344936b50892d17a5c248d0fb69bc53c1a9a325d59c103cc3004f46208f27a506c1e03d84c4696dd4284f620a8e2a127f35288be641251dd2590bc0fafcf317c4e62fe50b58e8ba5c62efef001c6cd672194eb705689637b8a7328eec1849bc144cbb13a53329da4a25c7110b323c93f150da62627c81741769d2fc2359e616b8f06538627843632b6652a7e1448e0555725900df0b07ccb020ddcc5af3d4a277229912e3a9ef2a2cce8c1e5b3275890bf8614c435f9226e081d32568b6eec0d18edf3d8f5263257f461f2630a0a05e346c140a917204d97ae485b9d244c8a23d22178af6bc6a4323a02bd246f54fbc8f9c359d3a98fd3f41b9e05a8fa1045511002776b3358b28b73c8a85050d3b0b290a11f48d90fbf8f1e3c734327fa0df2558ad8510b3bd0d0b03dffe4e612b2bda53cbe431e98289ab5d9cefcd54b970e8d8b867b3c8b277ef10f035b50c6e7a048c453bb4ce24e40e9902606f2db0c5862a8622fee83b1bcb0211b24ac38f9c4fcf2730e77ba8f8c034c62bf82495a52666cc5cf46e76da03b24141c89bb6d219d092dcaf0122fdf14312b73d70fcb4b96e78378dbb1ff35a690b4b240e11b551b160eea8a94d5e020ceb683d576b3dddac5c02fdefbad6c5b136440b4c05562560c453e661e2020b6a24f8d265e5c9efe0336752811e92700bc8fc6191705f3aa34f3fac4979b6cd655f2db03d74abd955725eb91ee3e54df46743ed05e391acb7b6bfe4464179bc0a3eb46169dbc5d44e4b41306b727bbe993d235a9e58290c64061b32ba93552d696ef100936430907e17e368824464a79217d5f58563cd89061fc3da35baa217621dde692b59f1362027e31991b0c15918f4fb46fa6c8329b612faa96e95dfef64aab59e6d811b7f2444a4ef742010731c1cd910dd19c1a3c616344cfb2cf4b68671ea5f41cc0796588e1f020e0675c80eeaf7dbb683d1e1a98b9ff76010714e7503274ba1adaa33", .None}, + {.Shr, "56aeadf1c137c7b8eaf4c7c1ca73195c36ca1708a87208433b202b3b54abd8f33679713016c20acdb6af8edd5a12a76902d601c5c17416ca01c18de8b6a5364d8de31908b7b63a352e2bf054d2627b9b17554c78c2401b4afb48ea32290003fa6ef1698064e43b375df4f80745612eb1fb7ce7e0ae5f73a546558fe35e1cccd1c14f096ecfa5ad5537a82d2f40b3fdf3ba30308b80e5f4bc98289ace24b4e3d74d608981e7daf61fa223dc165f7344250aefa2fd4d6a3177821a2632d761834cc3c9fd4588675239c41752bc0d9f85dfedd708d21b60662f6466e2fe1d3932fb94ead4a5cc98ff6e3735ddd3f3eaf7eaf31ba4768472ea240aa93651b5a35ab5c3a14fa2c0f2a100359b57721aaaa735d20cb12c5b3c07273255b29d7673b0b05a1e7f7a82de43089d7172297f50bd98c75433d7161a16024ea34001cfa64d01e4484b826e6f8f9384d0aa335436dc7e42c3d3870fa717d05a91a0a8bc356a18a474822670300d7e35668adf16cbcd5ff6c9137215261fa4346ba5e8b6194f24360e061819144942d640d73251510a00f7ef3f1f6bf620c11b6fced98fa115fac3e31fcca5ca8ee7d776db530808a92b0203cf748ff6dea7145eea643d0f430948a4c19c49140ba9b4a42dc5046dfc9f6ddce6cefddbc5a76bc5df0a998a0a777fb36c91ef0304b56bea5a69e683209fca08fdfc8b804bc321c2e864f2189dbe696125202451e137a919085397a1e940d9ae73053495ac7b05ca55f949600bffa77cfdc8b9098deb0733c9be89fe3fa3f5c2a0681a197f78f812198e03dc71109c3174895fa2cef754c7fa2dfd310ce5122b4ebbb0769052732e34edb86d58cc57dfccf014fe0151efc629b29685d9cdc5354bfd38fce06cf681956eadb3af1f1ccec27a9cc963e861fd86ec19c037c071c8fc469ea03f461566eac0f855354e8cc550ab5d9d18a35390c3f61a8ef174ad5bcdcef61f5d930f6b9097ceb59b01b2c3f84d2f0c29d22cfa425ea76658ea879369daac0dbaa14f7f030c6ceaf277f9df0f75be5fddfd6e0579270d1658fd9e093732399ddea971b5fa16f523d6cf75ac2b24130edef4bdac83ff2ee24c6397c2a6b819776194f8d10d68fe0770165dbaa364c5f340511c4c007bcf46cafbae368015b862e51f8cbbec216d20ef7b9857e4ba56dc61ab2592d0963651f87e7df4d1915999868ee6a3edd00d0a7609648600092236fbabaa71d349825f7f3993ce7fb51ffbceb4ba80d861559c67d282aeb0a20e47702bca769bfc7fdfc6691eb31dc9c054442fca53328f19adcb8c99c6f96d5e4f691b6de297d3ed1ccdbd6f3a02b21e2c40fd7ac9a95bb04d22e44d004ee340bc29d77b19310e75a874be846713b4ed01a939188d31cc1b91dbe045cf995f51be6625b15419d2383d3ca572a2880fcfeb1e55b4c0c339d58369751e25b4904743c24579ef761432dd5f1a9be7fb7a93ffb1880792d29134680b5f4af2dbd15362db3a8f7f2685bf7324bc333af984752bf22bda503002690a8457860b48fd9b44b5e09dbeb11d770b979c9afc2692265f362ff5657eed53cb0f832287eb011b5a1cf643c095a233cc0488eb99d163a47f171e0c8aff95374473c24c45f9f3ed614ad76dc928e193b2432805c5c8cb8aab22c8346325a786b46270a67ff5ade280754d9e0179d95fb9bcac4c076f29de89a32c49d094df5fa51718284be38a74cb244b8fae21825591bb265e3e64e585200d4cf4fd3d38ae3c8594688e07626aba15473a22f252d8720778cea20330896ab80eb84216ffd844333b18bafd2e9c42d1b76b01a29d9bb41379140497b932c64ddad436cba9781da17782a4504a912be4bf2ea8b082dca170a9c28966e8c5c9f25ccf329f8334d690a77408e9b5856cdfe02e75c764bb5182d8b726a96c70c2ac12520d18f7b876875272c07fb188c46e8212294f655540eb0d3fd287f88aee4501117e2a251a5a26f4eef9fc746431fd6639a7746136c31af1f3d16814d53719f0237c5d91f9d70634776a639e4899c4d356734b6cfa6f9dcca599236bfa193dcbed0cb149f0a1b36a407939e2c171c4bc1dae1d2554ad0d4e1d85f85a8b5f81044d8e9c71", "3c", "56aeadf1c137c7b8eaf4c7c1ca73195c36ca1708a87208433b202b3b54abd8f33679713016c20acdb6af8edd5a12a76902d601c5c17416ca01c18de8b6a5364d8de31908b7b63a352e2bf054d2627b9b17554c78c2401b4afb48ea32290003fa6ef1698064e43b375df4f80745612eb1fb7ce7e0ae5f73a546558fe35e1cccd1c14f096ecfa5ad5537a82d2f40b3fdf3ba30308b80e5f4bc98289ace24b4e3d74d608981e7daf61fa223dc165f7344250aefa2fd4d6a3177821a2632d761834cc3c9fd4588675239c41752bc0d9f85dfedd708d21b60662f6466e2fe1d3932fb94ead4a5cc98ff6e3735ddd3f3eaf7eaf31ba4768472ea240aa93651b5a35ab5c3a14fa2c0f2a100359b57721aaaa735d20cb12c5b3c07273255b29d7673b0b05a1e7f7a82de43089d7172297f50bd98c75433d7161a16024ea34001cfa64d01e4484b826e6f8f9384d0aa335436dc7e42c3d3870fa717d05a91a0a8bc356a18a474822670300d7e35668adf16cbcd5ff6c9137215261fa4346ba5e8b6194f24360e061819144942d640d73251510a00f7ef3f1f6bf620c11b6fced98fa115fac3e31fcca5ca8ee7d776db530808a92b0203cf748ff6dea7145eea643d0f430948a4c19c49140ba9b4a42dc5046dfc9f6ddce6cefddbc5a76bc5df0a998a0a777fb36c91ef0304b56bea5a69e683209fca08fdfc8b804bc321c2e864f2189dbe696125202451e137a919085397a1e940d9ae73053495ac7b05ca55f949600bffa77cfdc8b9098deb0733c9be89fe3fa3f5c2a0681a197f78f812198e03dc71109c3174895fa2cef754c7fa2dfd310ce5122b4ebbb0769052732e34edb86d58cc57dfccf014fe0151efc629b29685d9cdc5354bfd38fce06cf681956eadb3af1f1ccec27a9cc963e861fd86ec19c037c071c8fc469ea03f461566eac0f855354e8cc550ab5d9d18a35390c3f61a8ef174ad5bcdcef61f5d930f6b9097ceb59b01b2c3f84d2f0c29d22cfa425ea76658ea879369daac0dbaa14f7f030c6ceaf277f9df0f75be5fddfd6e0579270d1658fd9e093732399ddea971b5fa16f523d6cf75ac2b24130edef4bdac83ff2ee24c6397c2a6b819776194f8d10d68fe0770165dbaa364c5f340511c4c007bcf46cafbae368015b862e51f8cbbec216d20ef7b9857e4ba56dc61ab2592d0963651f87e7df4d1915999868ee6a3edd00d0a7609648600092236fbabaa71d349825f7f3993ce7fb51ffbceb4ba80d861559c67d282aeb0a20e47702bca769bfc7fdfc6691eb31dc9c054442fca53328f19adcb8c99c6f96d5e4f691b6de297d3ed1ccdbd6f3a02b21e2c40fd7ac9a95bb04d22e44d004ee340bc29d77b19310e75a874be846713b4ed01a939188d31cc1b91dbe045cf995f51be6625b15419d2383d3ca572a2880fcfeb1e55b4c0c339d58369751e25b4904743c24579ef761432dd5f1a9be7fb7a93ffb1880792d29134680b5f4af2dbd15362db3a8f7f2685bf7324bc333af984752bf22bda503002690a8457860b48fd9b44b5e09dbeb11d770b979c9afc2692265f362ff5657eed53cb0f832287eb011b5a1cf643c095a233cc0488eb99d163a47f171e0c8aff95374473c24c45f9f3ed614ad76dc928e193b2432805c5c8cb8aab22c8346325a786b46270a67ff5ade280754d9e0179d95fb9bcac4c076f29de89a32c49d094df5fa51718284be38a74cb244b8fae21825591bb265e3e64e585200d4cf4fd3d38ae3c8594688e07626aba15473a22f252d8720778cea20330896ab80eb84216ffd844333b18bafd2e9c42d1b76b01a29d9bb41379140497b932c64ddad436cba9781da17782a4504a912be4bf2ea8b082dca170a9c28966e8c5c9f25ccf329f8334d690a77408e9b5856cdfe02e75c764bb5182d8b726a96c70c2ac12520d18f7b876875272c07fb188c46e8212294f655540eb0d3fd287f88aee4501117e2a251a5a26f4eef9fc746431fd6639a7746136c31af1f3d16814d53719f0237c5d91f9d70634776a639e4899c4d356734b6cfa6f9dcca599236bfa193dcbed0cb149f0a1b36a407939e2c171c4bc1dae1d2554ad0d4e1d85f85a8", .None}, + {.Shr, "167c06ee9eabdf42d040ff98bf84e12a964e8f383f7fb5bf32afc1a4842f288932e22a7b97d92c3aac728256a3a46598803e7d2acedd62edfaa6add91faf7169ad29314ae7aa262c3dd31383eccce1fcb622381c97edc30dd0e6e259ccacc9c78d22507171e8b4ae7cccdabb9febc6d1f4f41689b7aad58d2f5fd975e461c86b726441f209fcad6390f8a1f24f1f65d6aa37bbb56b6ee3f560c0bd90ea4f23c22546abc1d835b72080d36518413d9fa25494456500c1a1418026b861fc34782ef3668b144ac3cddbaa0bf08f225572eaa80b1d9c7ed3b97b53b9e42593cd753973c6b73a6e3adc837c579555db26251442382173b1d348846016c60c6755c629aa94fdde2946a252a9f6cec2c8a23a0b16d2a78892308ed934fbd4cf8c6850b6e3c94dd904118216f9eeb305279f661b2fae05d692bcef1e680150df25d196c200a2b7eaa8ee518b263421ae77e89a70baf70f29f6e821ffbcf588afcbead6f2b37bb23921cdeede783bdbe3249f9301366416b7461b2abf86150e55c7cdfaf03f5f12258e9774197d794689018a33629da3adb559ae016e99ca0740523efc5736d0d441f2e8b1bd44b28332792da67bc1d1bcd1193fb5e6a32ae6a7d5f9757432be78025d5dd599f9b1546e36173256f8b475ac68ce1de65e343b4d433cdacab533015fbc3a28bf1a55e95174240b8dfa7a423f069d204dc8b11f7fa6e4b1d024c144893266c2417376f063f484c398839c078ac35b53d192353d4c14b0c1591de864c65c5f15c1e4133c7c0ab888c6b360d5b147f73f80b341ec7f8eacbdfd59ccec786ae16d0e66f124f3b9d3b940cad7dd95dfeb3221fe956fbe63c64a5303cd015737fcbcac55ce2f465147aec8474d1003879b2134c8a3d3d196bc8ddf22bffe4482024ee136f67f7ad00d8b510a516fdd872b8b0440e79394ac2f196482d9614ca48cfa8ee4acc8257dc12e277a97173814d122e8c3871b9bafac4658742e7414dbe83344e0dd5cc34b5859eae762c1297c88b839efc5d4bf23decc1710d0a1dcadf624a01c949d183dde8cae114cd6da37d76f75161a4ba7d0f5b63ac068ddc99fad202bde4faf748a0eb4b1515b9f1f436d36526a7f7ee4ce1d4d83546e9e7d2052184002c5de49bb7d46ff1312505b0fecdd5b823031ca2fe731ac6b2e1fe6e1ab7295db97bda3b99edba2acf9b393e960fc2c6282e7e301c10d7431b233838e1253fcbf124aed159177255d5df069f93f7c482585c0c928cc6349143093392552c69dea77a13fa5615f59a1c36a05b91c54febef75c3fc02226f9376980bcf8a2ba5bdf848ba0f81d0a44b8b8221d57d0f7b0b1486d444e428af855ff7154899bffc7a9cfffdb132328d2cc56e2c6bbdcd6e4ec28cb1191cb5fd279a5801f37a58fbcdc8874474cfbabc0f17387f62a68728be3ea6958f21e5be3e5fc6f1de44155ca3635a1435e20d35b4fec5fab6f33e56b73b76e29ac071c034506c7d7c8876c9219f6f1cbffc4240779d364b15137aef5d480296fff3531d431d3632021acac66757ff373c0fbf95a118ce0a73ff3aa2f5eac78cf860619208ff46722b8bd5daad82e151f87b47134e0800d78af8fa34dfeabf0d9f50495b882f87d6528898c708de1141cee25a2d0c149715a8cdbceadf4d0b8ff4f48ebeb42d0fd1dab95afc4fe12cb6fef558f6020d8b4bd35d6a68aea575c7304fab07d6094a19a127aac31a2933c9b6d0fd7e4c81de3bf56055e5b92e4f8e084522fbd5c0dbe6ac2edb63ceed40340d8db9e3fa738e2ff766d89e0ea9e4e7a275e298ad82246dd976b32096ec2eed45ec9cc62ab00ef68a3b926c280409061b0c1e2c037cba9cfcf33cd43ddc3b77415cd92ab8927c130ded7e85e57ccfa04e6f471e0b8dbaab69ee6d3b37061666e18efb5b2544af4702ae12207e05926092422c15cc2fb1fad59836497d697bdf4d9cce7ac0c1baf83b7c79dabb2657a0fda21e1accfac7374309e85bf384f237acd511001303d77fd42fb7d7971ad90fd1eadbbc8e555ffec1fb18d501a8f102986f20bc0577214fe1e1934964e4c480dae7da65503451cbd3f523874bd66c25db0684e02d24ae67af8cc2efec3ec3084", "1e0", "167c06ee9eabdf42d040ff98bf84e12a964e8f383f7fb5bf32afc1a4842f288932e22a7b97d92c3aac728256a3a46598803e7d2acedd62edfaa6add91faf7169ad29314ae7aa262c3dd31383eccce1fcb622381c97edc30dd0e6e259ccacc9c78d22507171e8b4ae7cccdabb9febc6d1f4f41689b7aad58d2f5fd975e461c86b726441f209fcad6390f8a1f24f1f65d6aa37bbb56b6ee3f560c0bd90ea4f23c22546abc1d835b72080d36518413d9fa25494456500c1a1418026b861fc34782ef3668b144ac3cddbaa0bf08f225572eaa80b1d9c7ed3b97b53b9e42593cd753973c6b73a6e3adc837c579555db26251442382173b1d348846016c60c6755c629aa94fdde2946a252a9f6cec2c8a23a0b16d2a78892308ed934fbd4cf8c6850b6e3c94dd904118216f9eeb305279f661b2fae05d692bcef1e680150df25d196c200a2b7eaa8ee518b263421ae77e89a70baf70f29f6e821ffbcf588afcbead6f2b37bb23921cdeede783bdbe3249f9301366416b7461b2abf86150e55c7cdfaf03f5f12258e9774197d794689018a33629da3adb559ae016e99ca0740523efc5736d0d441f2e8b1bd44b28332792da67bc1d1bcd1193fb5e6a32ae6a7d5f9757432be78025d5dd599f9b1546e36173256f8b475ac68ce1de65e343b4d433cdacab533015fbc3a28bf1a55e95174240b8dfa7a423f069d204dc8b11f7fa6e4b1d024c144893266c2417376f063f484c398839c078ac35b53d192353d4c14b0c1591de864c65c5f15c1e4133c7c0ab888c6b360d5b147f73f80b341ec7f8eacbdfd59ccec786ae16d0e66f124f3b9d3b940cad7dd95dfeb3221fe956fbe63c64a5303cd015737fcbcac55ce2f465147aec8474d1003879b2134c8a3d3d196bc8ddf22bffe4482024ee136f67f7ad00d8b510a516fdd872b8b0440e79394ac2f196482d9614ca48cfa8ee4acc8257dc12e277a97173814d122e8c3871b9bafac4658742e7414dbe83344e0dd5cc34b5859eae762c1297c88b839efc5d4bf23decc1710d0a1dcadf624a01c949d183dde8cae114cd6da37d76f75161a4ba7d0f5b63ac068ddc99fad202bde4faf748a0eb4b1515b9f1f436d36526a7f7ee4ce1d4d83546e9e7d2052184002c5de49bb7d46ff1312505b0fecdd5b823031ca2fe731ac6b2e1fe6e1ab7295db97bda3b99edba2acf9b393e960fc2c6282e7e301c10d7431b233838e1253fcbf124aed159177255d5df069f93f7c482585c0c928cc6349143093392552c69dea77a13fa5615f59a1c36a05b91c54febef75c3fc02226f9376980bcf8a2ba5bdf848ba0f81d0a44b8b8221d57d0f7b0b1486d444e428af855ff7154899bffc7a9cfffdb132328d2cc56e2c6bbdcd6e4ec28cb1191cb5fd279a5801f37a58fbcdc8874474cfbabc0f17387f62a68728be3ea6958f21e5be3e5fc6f1de44155ca3635a1435e20d35b4fec5fab6f33e56b73b76e29ac071c034506c7d7c8876c9219f6f1cbffc4240779d364b15137aef5d480296fff3531d431d3632021acac66757ff373c0fbf95a118ce0a73ff3aa2f5eac78cf860619208ff46722b8bd5daad82e151f87b47134e0800d78af8fa34dfeabf0d9f50495b882f87d6528898c708de1141cee25a2d0c149715a8cdbceadf4d0b8ff4f48ebeb42d0fd1dab95afc4fe12cb6fef558f6020d8b4bd35d6a68aea575c7304fab07d6094a19a127aac31a2933c9b6d0fd7e4c81de3bf56055e5b92e4f8e084522fbd5c0dbe6ac2edb63ceed40340d8db9e3fa738e2ff766d89e0ea9e4e7a275e298ad82246dd976b32096ec2eed45ec9cc62ab00ef68a3b926c280409061b0c1e2c037cba9cfcf33cd43ddc3b77415cd92ab8927c130ded7e85e57ccfa04e6f471e0b8dbaab69ee6d3b37061666e18efb5b2544af4702ae12207e05926092422c15cc2fb1fad59836497d697bdf4d9cce7ac0c1baf83b7c79dabb2657a0fda21e1accfac7374309e85bf384f237acd511001303d77fd42fb7d7971ad90fd1eadbbc8", .None}, + {.Shl, "-256889d946b53ddb872d4cdaf3e502be650f6a1bd02325d16b820b6072ed5dccb800b6dd91760dcda5328ab0707cef0855670749fe54630cffa7ddace44180ab9e6062cdf33ff54e3339a65ad0a087898fc7dd49fc45873fb87612c6b5c9548cc25066ebd6c03d88487af9769f19e5ad8991c901985752bbd33f16cfb00b027011c6c44a3c9b0a3c527291c0ca20244c3c6b670dc73489f61f6c0379777a84cf580a497796006a566f69e55c7a0a3ad367fd7950501f23153f5af82d9ecbc582315b7dc4775facf32ffb53d85e458d6fd499973a6083543ab1a5d34f4a5de13eb5eec3d42daaf1aba7500afdf6276d9ac51339be45e65ea2aa76bd2037e04efee55cf1f52133017162ed93411267822decf041f06e749375313fe4eda8b8baec8be23a67baa70913847dbc6655542ed3b42d8fda5db36f5dea73732b357c9ee727dc4f1aabb05bb82033d77087d28b176626c78039aaf5339e89251215812ac3fe5978033ccdd0f6ed76741788649a0028486399a1fea9280d24ee6a69628542890b8c925d71c03a5efe32a3977e5c8652d4044b781979ab5a8de8a17b3a0e24753aad4a24fe4e67de238f457236a2a85cd6baa7e1767a1c14c284a65eef2f29e64e4e59fd1a552673480d815c1a28128cc049bb383465a0d451a3950eccecf69b3a323e2a57b2ac55fec206801cfb2ed375c83af4ada294f7768baba89c45bb2be2b3295bc78800b619141b73141284485c700bf774d7b016aa8496208ce43a08db7fe58591baaf3e7a867998fe8fa01d186ea97859b876bc310b2556be97fb5f7755d3975e836b89e829028e105169cc9ad0e66e0158b3139b996fbe26da3ddf3390d86548384a7e5dbb8f832f098bc0d966672c7ce213f5f4881b5c5308c847b734431d4a41cccbc8c8007fdae9663567fde2dceeb0741a8b45384037223f22355377949413c1b9f8d2be5ee34936eb3c477bd12e4bf7fa3ac3fba4a5945c73feabe842f6ccae757f9c880d44db84662d3eb3489f51f607c8cfe688fcc577426a643ac790a4b3bbb96fe3c4889b21bb8450553c8758c765f7f4a8a5fa38882844fe35f1709123abf9e54319f6e2c12895b4bd861519d0f66857ddd3ab39c10ceac15999c5529a237fc657aa6842f3d5bf6bf180062d6bae4d7a966c422d5c47b7fb490b069bd18e42417cf2913003849dc109c24186f1f021f426a85e74aa89cc7f365bfcdd06fbb3bffe6c20f157e9338c222544cc3eaddfbc609a805da13ba586208ab135c4544399d6f13402799f5a8ccf993ee3094c2e33673ef74b3a9090354e0e6a51c150c2a570122b4a37bc2d930a19f5a79868b1c613a87eb4f58db029ddfed94a09b68dab152a6e7c4bb9ad552ff6397dbc57530d182ce60fc1d958d6f2aa4ccc4d337e1f3a1006b937a8206ab4785d7a2710f8da341deb70ad988f737f5ab2b7fd8fffc93c72c34dce0a9764d26b74ef296bfaa81fd4281e697fcfd170a4e625ec4ea9b588597bb7cf3b75eb0e29e22bc8a4a3498bd0f64aeb5349963ad68442df57753174beb25717e819473920a45ee606c1ca31df5ec66d018ddc533fd828755e74b68857d814d3d203260c83836168bceb5dd0a3121891d4182a2de2b1aeffa3a911d285816f8648a49acfea6cff4e9507edbd235755bb61625dc387a8b4f8983830aa091038642ab75422094c65cc3b0bd9ca30b4a5fd3482650add62ddfea6713966307f872e4fbfc81de6e7fe619788ea3ded86b54f6ed4c1ce63a15b15a89c7e87bf118a52ff3c0fb7d1cd9679fe40f95cb8f7e431cb0108557687a120a1099398f73ae3dc5b7423a6e4a09832a619e9fbbe39735494a22e1af99ccff65ba9529e61dd10bc61597b179b4dcc336474984f5113658d53cfa251be84613f0c153b9e1a3c07f5a7c0d6587fa1e58b3f1a7f4c978964314c17b0adc66d12f2773abe79fa91cd60bc656e8e33caeb6dc25bef41745f79121c33e56297011089e0897e174fc54ace39f5a21239471be0cd86712fbfdceeedfd788cbecd1a26a05291310aba24d1de40d708d56d6276412dbe576ac722d61c2e82521a2e064d952164ee1d96651bca7ae8bb4b913bda8b02912cf4", "24", "-256889d946b53ddb872d4cdaf3e502be650f6a1bd02325d16b820b6072ed5dccb800b6dd91760dcda5328ab0707cef0855670749fe54630cffa7ddace44180ab9e6062cdf33ff54e3339a65ad0a087898fc7dd49fc45873fb87612c6b5c9548cc25066ebd6c03d88487af9769f19e5ad8991c901985752bbd33f16cfb00b027011c6c44a3c9b0a3c527291c0ca20244c3c6b670dc73489f61f6c0379777a84cf580a497796006a566f69e55c7a0a3ad367fd7950501f23153f5af82d9ecbc582315b7dc4775facf32ffb53d85e458d6fd499973a6083543ab1a5d34f4a5de13eb5eec3d42daaf1aba7500afdf6276d9ac51339be45e65ea2aa76bd2037e04efee55cf1f52133017162ed93411267822decf041f06e749375313fe4eda8b8baec8be23a67baa70913847dbc6655542ed3b42d8fda5db36f5dea73732b357c9ee727dc4f1aabb05bb82033d77087d28b176626c78039aaf5339e89251215812ac3fe5978033ccdd0f6ed76741788649a0028486399a1fea9280d24ee6a69628542890b8c925d71c03a5efe32a3977e5c8652d4044b781979ab5a8de8a17b3a0e24753aad4a24fe4e67de238f457236a2a85cd6baa7e1767a1c14c284a65eef2f29e64e4e59fd1a552673480d815c1a28128cc049bb383465a0d451a3950eccecf69b3a323e2a57b2ac55fec206801cfb2ed375c83af4ada294f7768baba89c45bb2be2b3295bc78800b619141b73141284485c700bf774d7b016aa8496208ce43a08db7fe58591baaf3e7a867998fe8fa01d186ea97859b876bc310b2556be97fb5f7755d3975e836b89e829028e105169cc9ad0e66e0158b3139b996fbe26da3ddf3390d86548384a7e5dbb8f832f098bc0d966672c7ce213f5f4881b5c5308c847b734431d4a41cccbc8c8007fdae9663567fde2dceeb0741a8b45384037223f22355377949413c1b9f8d2be5ee34936eb3c477bd12e4bf7fa3ac3fba4a5945c73feabe842f6ccae757f9c880d44db84662d3eb3489f51f607c8cfe688fcc577426a643ac790a4b3bbb96fe3c4889b21bb8450553c8758c765f7f4a8a5fa38882844fe35f1709123abf9e54319f6e2c12895b4bd861519d0f66857ddd3ab39c10ceac15999c5529a237fc657aa6842f3d5bf6bf180062d6bae4d7a966c422d5c47b7fb490b069bd18e42417cf2913003849dc109c24186f1f021f426a85e74aa89cc7f365bfcdd06fbb3bffe6c20f157e9338c222544cc3eaddfbc609a805da13ba586208ab135c4544399d6f13402799f5a8ccf993ee3094c2e33673ef74b3a9090354e0e6a51c150c2a570122b4a37bc2d930a19f5a79868b1c613a87eb4f58db029ddfed94a09b68dab152a6e7c4bb9ad552ff6397dbc57530d182ce60fc1d958d6f2aa4ccc4d337e1f3a1006b937a8206ab4785d7a2710f8da341deb70ad988f737f5ab2b7fd8fffc93c72c34dce0a9764d26b74ef296bfaa81fd4281e697fcfd170a4e625ec4ea9b588597bb7cf3b75eb0e29e22bc8a4a3498bd0f64aeb5349963ad68442df57753174beb25717e819473920a45ee606c1ca31df5ec66d018ddc533fd828755e74b68857d814d3d203260c83836168bceb5dd0a3121891d4182a2de2b1aeffa3a911d285816f8648a49acfea6cff4e9507edbd235755bb61625dc387a8b4f8983830aa091038642ab75422094c65cc3b0bd9ca30b4a5fd3482650add62ddfea6713966307f872e4fbfc81de6e7fe619788ea3ded86b54f6ed4c1ce63a15b15a89c7e87bf118a52ff3c0fb7d1cd9679fe40f95cb8f7e431cb0108557687a120a1099398f73ae3dc5b7423a6e4a09832a619e9fbbe39735494a22e1af99ccff65ba9529e61dd10bc61597b179b4dcc336474984f5113658d53cfa251be84613f0c153b9e1a3c07f5a7c0d6587fa1e58b3f1a7f4c978964314c17b0adc66d12f2773abe79fa91cd60bc656e8e33caeb6dc25bef41745f79121c33e56297011089e0897e174fc54ace39f5a21239471be0cd86712fbfdceeedfd788cbecd1a26a05291310aba24d1de40d708d56d6276412dbe576ac722d61c2e82521a2e064d952164ee1d96651bca7ae8bb4b913bda8b02912cf4000000000", .None}, + {.Shl, "25f380945d2c7930fb03d8a7e9c9b25feb3ddd160db3a5e87736c7d835f4e6301194dd5b231dd52c85f8ae6a08ffbc64c8cf2631b6f2d142889a540fe8e10227e7ecfb3b3dd2f81ca3deec1b24df8c21080079914e74786393deb493b81be143b93cd0aab982b41f529c4fb82e10d70e314d4cd1a708519fbb0716ec6114c95f978c6c91e07122e199431e36d7f20b3f3c7652b70d9c5265d29a30406dea8afa484107a25bd3d2ea12b058deaf9b7b16b7e0dd81efd099434806418612a084ed094c682de153939b638cff332a332330363b0203d53c2b031280e4b8d5c90a5b616866fb9982db728f516392d3ac06c8edce656ae9480a9685f19ea76de16a1d0b0227d183d360352c10fed8b61246dd6c10536b32dccf3cd7076df769a10ad7fae6234e62e88c7501d13b46414872c93e14e5af71eb0e0492224e91509cc9e8c2a86f89e8e76cd15bccfd4261dcf67405a0eee55b530dceae1095a09e009746115b50167fb59bac1d839295add83d6090a5ef0759b971b11eba9e22e65063f858eb478c72d0316045b8d79de0effef64c239aa4e0cd65cc763a3ebca7e5c54334eb24396033ed94fdb979a95622bffe09e3c00e186664b8f8fef6bf7eb81511cb99663d88df05740cf53c706ea43e879f0b52a01d5ca2e25ab510c8d7af9d8cb10c59cbcc081c90a0b01a88f25067b3c2fd20bb9e56a3bcab3a8aa61e5f583e5e5130b42c7278303b9ee36dfc68a2d1c9b7716d0a7e824d1c7993d0fa723a46716ed6ea9bcd86e3b949a4a5cbae4c05e9638282337c9fcd1c526eb93562eda15bce9aa370ae456cafc90e84a4ae28a07fb3ea4b2777aa06236e1818ca5d93550e02bfb75c24b038567054fa9f52f4c023ad3fdeffe6e72071126c957e8a223db67956e14f85a3b652034879cd13104dfbc77f2690d1e2a4e572d4613bca1a1bafe31211d1c6652d7d3482ae3db949215eab9c6ad3f27ba38ce23ae9c904442cd69d82e4b20ae328b5e1a749843d4e6e9711272494ff54dcc9f48149d52781e10fd851ba964a478e19f82f4b29998f9c1e4682b5fa4c726e5c278a26442da165b9bab603f50f7fad6c1b12b122d160df38c220a7aade9cfb22c3e31f1d9b8922919c30e4c72623ff43e2afed8ef8bdb22da1cb19c73058f8f6094c214c264cbec705835ab83a214455a01273352153b87b62ba87c5e647a7ed3c12745116be5e4e370b225c95b11c07615d930718588ff23103024de385b69cea8e08c6e0bcff7f3daeb939da38e6a7d61767d83cb92f8a68a88a0727b787061d6fd9867481e84381ddc68045e6f108f5e3b2368cb801b2b2ab80e7d7161f062b9d38abe463f33226d404ab8c28562e80e097408ad53661b346df9fbd7d3214c87c4696251daf9ea535dbd7854093fa1f397439f5088d4a0c28628b4795c931a9e8d201f8e507f74f62c68d1d83350bb1cfd224279c0b66608371ad3797668fc7942e8b13fb19d1b46c5837177df517c1ce0194bcfeaeca8aba18d62c9c4a6c0534aa2f97d5cf3fb43c7c178f540ec461fd96303a7fe271924a5ccb55ee0e98bd3c35ff824f6d5d0bd3aeaa464db245ff1443e1419d4c87044da6625bcc982ec0d9dd29960c6b501cc91dfd6ba2345d7568c1d7a4b2b4bce8365edeafd110019e6cbc713a2c6fa81595697f61223699f7c42bd6866437994acfac6e534e8f2dcef669e1392112519df28f4218781051d024f8410a33b3d3af058056ad118abf0d000024ac560fd97cfa27b562f067d8ce9afe24f6346c3b1ceb7d431dda3d5789e948e2e2f3609be3f00b4d3b12091ea8ae5b6eaabcb72c9b298026d5503d6702f336315b2fab3fe4d76258d054efea3feb3fb0e8e7ea5dcd0908ec174d4293cc1f47b587ea78e237e4be6dc762a2d1d4e88d04ce1cbc45bcaa600ae0fef6ee8e09173ef14dd8a508877fbd3ddce387bbcb48ee03d7065e1b15725db1d59c13d19e05b193d132836a3d1a9491987d07887ad25ee882621f9cb3318143dcf3e96f5c40cf71cfdfb39cddaeeee49f469f2ff63cdadf64d1421528e0c2b990d923267fcd2ea0c800864a5e170f6e181a4b52d5fe8e72d29429d27a6478b444f311219b22", "6b", "12f9c04a2e963c987d81ec53f4e4d92ff59eee8b06d9d2f43b9b63ec1afa731808ca6ead918eea9642fc5735047fde3264679318db7968a1444d2a07f4708113f3f67d9d9ee97c0e51ef760d926fc61084003cc8a73a3c31c9ef5a49dc0df0a1dc9e68555cc15a0fa94e27dc17086b8718a6a668d38428cfdd838b76308a64afcbc63648f0389170cca18f1b6bf9059f9e3b295b86ce2932e94d182036f5457d242083d12de9e97509582c6f57cdbd8b5bf06ec0f7e84ca1a40320c30950427684a63416f0a9c9cdb1c67f99951991981b1d8101ea9e15818940725c6ae4852db0b4337dccc16db947a8b1c969d6036476e732b574a4054b42f8cf53b6f0b50e858113e8c1e9b01a96087f6c5b09236eb60829b5996e679e6b83b6fbb4d0856bfd7311a73174463a80e89da320a439649f0a72d7b8f5870249112748a84e64f4615437c4f473b668ade67ea130ee7b3a02d07772ada986e757084ad04f004ba308ada80b3fdacdd60ec1c94ad6ec1eb04852f783acdcb8d88f5d4f11732831fc2c75a3c6396818b022dc6bcef077ff7b2611cd527066b2e63b1d1f5e53f2e2a19a75921cb019f6ca7edcbcd4ab115fff04f1e0070c33325c7c7f7b5fbf5c0a88e5ccb31ec46f82ba067a9e3837521f43cf85a9500eae51712d5a88646bd7cec658862ce5e6040e4850580d44792833d9e17e905dcf2b51de559d45530f2fac1f2f28985a16393c181dcf71b6fe345168e4dbb8b6853f41268e3cc9e87d391d2338b76b754de6c371dca4d252e5d72602f4b1c14119be4fe68e29375c9ab176d0ade74d51b85722b657e48742525714503fd9f52593bbd50311b70c0c652ec9aa87015fdbae12581c2b382a7d4fa97a6011d69fef7ff373903889364abf45111edb3cab70a7c2d1db2901a43ce6898826fde3bf934868f15272b96a309de50d0dd7f18908e8e33296be9a41571edca490af55ce3569f93dd1c6711d74e48222166b4ec172590571945af0d3a4c21ea7374b8893924a7faa6e64fa40a4ea93c0f087ec28dd4b2523c70cfc17a594ccc7ce0f23415afd2639372e13c5132216d0b2dcdd5b01fa87bfd6b60d89589168b06f9c611053d56f4e7d9161f18f8ecdc49148ce1872639311ffa1f157f6c77c5ed916d0e58ce3982c7c7b04a610a613265f6382c1ad5c1d10a22ad009399a90a9dc3db15d43e2f323d3f69e093a288b5f2f271b85912e4ad88e03b0aec9838c2c47f918818126f1c2db4e75470463705e7fbf9ed75c9ced1c7353eb0bb3ec1e5c97c53454450393dbc3830eb7ecc33a40f421c0eee34022f378847af1d91b465c00d95955c073eb8b0f8315ce9c55f231f999136a0255c6142b1740704ba0456a9b30d9a36fcfdebe990a643e234b128ed7cf529aedebc2a049fd0f9cba1cfa8446a506143145a3cae498d4f46900fc7283fba7b163468ec19a85d8e7e91213ce05b33041b8d69bcbb347e3ca174589fd8ce8da362c1b8bbefa8be0e700ca5e7f5765455d0c6b164e2536029a5517cbeae79fda1e3e0bc7aa076230fecb181d3ff138c9252e65aaf7074c5e9e1affc127b6ae85e9d7552326d922ff8a21f0a0cea6438226d3312de64c17606cee94cb0635a80e648efeb5d11a2ebab460ebd2595a5e741b2f6f57e88800cf365e389d1637d40acab4bfb0911b4cfbe215eb43321bcca567d63729a74796e77b34f09c908928cef947a10c3c0828e8127c208519d9e9d782c02b5688c55f86800012562b07ecbe7d13dab17833ec674d7f127b1a361d8e75bea18eed1eabc4f4a4717179b04df1f805a69d89048f54572db7555e5b964d94c0136aa81eb381799b18ad97d59ff26bb12c682a77f51ff59fd87473f52ee68484760ba6a149e60fa3dac3f53c711bf25f36e3b15168ea744682670e5e22de553005707f7b7747048b9f78a6ec528443bfde9eee71c3dde5a47701eb832f0d8ab92ed8eace09e8cf02d8c9e89941b51e8d4a48cc3e83c43d692f7441310fce5998c0a1ee79f4b7ae2067b8e7efd9ce6ed777724fa34f97fb1e6d6fb268a10a9470615cc86c91933fe69750640043252f0b87b70c0d25a96aff4739694a14e93d323c5a22798890cd91000000000000000000000000000", .None}, + {.Shl, "-29eea0c3a94d3114ed1d5a2e80fbb144e9ccb833cbf9bc69e48f975e4a6992d463afc7a87e46daa83ad89b2dae04b0c84b2978d2e643985204a669818c7d880b59074004470a3376fb774b6037ef297ae4c31830db877f6e21c44befbcda02f9889e770ea8db00006ba980f75f03ff425b459cf3cf0ae2e783d745a8c297d9cd4dd61e89c812381ada848c04c9c0b3e2b8b52e59d155193358d574b0562d18eceab089297c529e6741beab54493efb0c3b0323dd31868d45f2a29035eb21f81746aec63a226a5a53d691e0a3cdf0402c9b2827b049ea68a2035309516bc51777ebf3e1a9494fcc9ac2f6199510855c61eb9b92da554040b89675b30c7bbffd8d2a1ca48ac465e64790c12f5626541be33b265a46d72954048d26ab2d52023d891b326735d735acea391df1ba67f81e9471d21cabc7a37c3406e26cde0a58d868bbb75686f789a8acb12389b1a0164301394309329c460fe9b48aa205d3187609f7cbac0c5bf6e4777af5d5ac058d6017a907760f6ab8ed27eb4967fdc4c99caed99d02e6e995390fc62066c6ad0f6ff0fa7eb67216d81417e4c2ae01a7c0e3f0174e7a6072d7789891b088e0d6a311781d61361d051a00b45285fe14239527a62994ac64c1e5510762413204ee274b56259941eda72266bda2a421a59a08bd504c2bc087383adbdf35e6be67ef4e6785834182a883cff780261efaf94bd0350376ee29148ec564590ab972b91e88eb009327c662a69917b710441e0aa320a97a0e03bd4b3b06471465a3054288aea96a4746af0a216469fe696d9279e101053799366343e690ce9e4b737230cea4645a6069891b8ee3f2ed821b1a81acc265f5c0ba1ac17730b570edae276e3a73713af0425bc48fc9b6b54f05e91850b8b8920c2008c709cb1af9c216f24e34081581d594f6680edd0d3aff8a26aa4da7de382d14728ab7f613391cea37be8e5637695763058b7c38d6bc1601172229a38ae09b32f190af681f82ccb0ba7b1a12039d32a351eab9712b345db85474fde59fcc898936796bca6606737da07452b9ab1bdd2e9b6bfd241d03fb7dc4e6ef83bf04bae51093c7873c28c11e04157875df9cac2fbbd6a64245f2ffa6d686e1692699404d81668a2fe40c0a85b99599d9c2136078ddbbab0eac3c3a48e7441562208e9254274adbd4094bc3b11f26efd9893cb0ad8b66ecb6b89db940a906284cc3e37d5ce94591421a7d1235a6bec35e11039e45640bccd36a157007fce8c91cf2b786842078b8e3eb62d314f5c3f30ccca5f0a4802d819d4af405c8f3ad414573f7605fc401fe8c3a7e01435f2a7a507de98972fdc727fe72bc8b08e7e555aed3caae995f043762eec28072272bb89d42f41b19a8853a9c2050f883d5eabab858b5b27fcfc4020cefb51f0c825de27954206073f510eef06d8c0a09dc7a4d5e5989f952c7f12a1e5a2b1c2121ecd8745e1c39c0fd282f1ad2345a8c8609739a0a4033fc3e2f0d484cd089214fca076854ddc80e2921d44c44e94cbe1b8a452b81ffffda65f3c406d0bcfb87b851a2453590122b13fe8ce8fdc023679d6ea8076ce04c04b699ab46688389c6b3e4ec1d935c6baa76073e9126e39492a935a2d803c9a393d6ba3ceed5e981191e5872375e252a2f747c373c85c613a6cb56755140cab7e6b256f66c89af50ccbb7b20a5096c37400af9ec0b750cf7239747daac80cde4d086a881fb6bd32a9589648298d24662b7f70b315b43cd0eff8128f4b1d5c7622c6f121b95c4935a5791eda84f0a59d1ea39d85b88db4de02cd1b99d88e2e80b4fd5c288cf6d2416b164d9bd15dda7e6cde720dbdb616bda8b0744d070cebf3e43bab687bfa56cc7ef8a223fbe335ff5e7d0be9c8b02b6974b66ff9be1993c46efae12fef9e38b03d130bbaa397d99c3280c604586804cb022d22c3134c3ad2b9cf7d33a7d79037549bc9fa2c17b09c3d26ff06d8c8308ef10e34d7ec83bc5bf2f49cd6757b5b3909ba174efb2d6f43eed8f470c4d1ab9a750ce8b06d8fca7b8d9283801cebdc487ff8746e137cecc7a4886e82489e15e08e5ea043095b074c8726d1fa25dff7d5220bf493c648c0ab428b6b6a385196d0f6aa2d5", "78", "-29eea0c3a94d3114ed1d5a2e80fbb144e9ccb833cbf9bc69e48f975e4a6992d463afc7a87e46daa83ad89b2dae04b0c84b2978d2e643985204a669818c7d880b59074004470a3376fb774b6037ef297ae4c31830db877f6e21c44befbcda02f9889e770ea8db00006ba980f75f03ff425b459cf3cf0ae2e783d745a8c297d9cd4dd61e89c812381ada848c04c9c0b3e2b8b52e59d155193358d574b0562d18eceab089297c529e6741beab54493efb0c3b0323dd31868d45f2a29035eb21f81746aec63a226a5a53d691e0a3cdf0402c9b2827b049ea68a2035309516bc51777ebf3e1a9494fcc9ac2f6199510855c61eb9b92da554040b89675b30c7bbffd8d2a1ca48ac465e64790c12f5626541be33b265a46d72954048d26ab2d52023d891b326735d735acea391df1ba67f81e9471d21cabc7a37c3406e26cde0a58d868bbb75686f789a8acb12389b1a0164301394309329c460fe9b48aa205d3187609f7cbac0c5bf6e4777af5d5ac058d6017a907760f6ab8ed27eb4967fdc4c99caed99d02e6e995390fc62066c6ad0f6ff0fa7eb67216d81417e4c2ae01a7c0e3f0174e7a6072d7789891b088e0d6a311781d61361d051a00b45285fe14239527a62994ac64c1e5510762413204ee274b56259941eda72266bda2a421a59a08bd504c2bc087383adbdf35e6be67ef4e6785834182a883cff780261efaf94bd0350376ee29148ec564590ab972b91e88eb009327c662a69917b710441e0aa320a97a0e03bd4b3b06471465a3054288aea96a4746af0a216469fe696d9279e101053799366343e690ce9e4b737230cea4645a6069891b8ee3f2ed821b1a81acc265f5c0ba1ac17730b570edae276e3a73713af0425bc48fc9b6b54f05e91850b8b8920c2008c709cb1af9c216f24e34081581d594f6680edd0d3aff8a26aa4da7de382d14728ab7f613391cea37be8e5637695763058b7c38d6bc1601172229a38ae09b32f190af681f82ccb0ba7b1a12039d32a351eab9712b345db85474fde59fcc898936796bca6606737da07452b9ab1bdd2e9b6bfd241d03fb7dc4e6ef83bf04bae51093c7873c28c11e04157875df9cac2fbbd6a64245f2ffa6d686e1692699404d81668a2fe40c0a85b99599d9c2136078ddbbab0eac3c3a48e7441562208e9254274adbd4094bc3b11f26efd9893cb0ad8b66ecb6b89db940a906284cc3e37d5ce94591421a7d1235a6bec35e11039e45640bccd36a157007fce8c91cf2b786842078b8e3eb62d314f5c3f30ccca5f0a4802d819d4af405c8f3ad414573f7605fc401fe8c3a7e01435f2a7a507de98972fdc727fe72bc8b08e7e555aed3caae995f043762eec28072272bb89d42f41b19a8853a9c2050f883d5eabab858b5b27fcfc4020cefb51f0c825de27954206073f510eef06d8c0a09dc7a4d5e5989f952c7f12a1e5a2b1c2121ecd8745e1c39c0fd282f1ad2345a8c8609739a0a4033fc3e2f0d484cd089214fca076854ddc80e2921d44c44e94cbe1b8a452b81ffffda65f3c406d0bcfb87b851a2453590122b13fe8ce8fdc023679d6ea8076ce04c04b699ab46688389c6b3e4ec1d935c6baa76073e9126e39492a935a2d803c9a393d6ba3ceed5e981191e5872375e252a2f747c373c85c613a6cb56755140cab7e6b256f66c89af50ccbb7b20a5096c37400af9ec0b750cf7239747daac80cde4d086a881fb6bd32a9589648298d24662b7f70b315b43cd0eff8128f4b1d5c7622c6f121b95c4935a5791eda84f0a59d1ea39d85b88db4de02cd1b99d88e2e80b4fd5c288cf6d2416b164d9bd15dda7e6cde720dbdb616bda8b0744d070cebf3e43bab687bfa56cc7ef8a223fbe335ff5e7d0be9c8b02b6974b66ff9be1993c46efae12fef9e38b03d130bbaa397d99c3280c604586804cb022d22c3134c3ad2b9cf7d33a7d79037549bc9fa2c17b09c3d26ff06d8c8308ef10e34d7ec83bc5bf2f49cd6757b5b3909ba174efb2d6f43eed8f470c4d1ab9a750ce8b06d8fca7b8d9283801cebdc487ff8746e137cecc7a4886e82489e15e08e5ea043095b074c8726d1fa25dff7d5220bf493c648c0ab428b6b6a385196d0f6aa2d5000000000000000000000000000000", .None}, + {.Shl, "61b0cf45151b9cb9c7757b9019b3a98c6aeaea49d8d8eb3cdf3251835030b8d5c1d58335401215929e167291efeaae602502ae5d316e8f3c03b9a35487cf03ed09e308b82b17bbd1ccd387fd66c884cfb17bab11d1f82c709bde13392a035b1586b3494dec5b0bed913283433a4be8fe3a814e8e3b8c2d3c553d20a840738ee19b93e843feb2a581b4e1798b5d4d6975567065f0cde9d490c4161101a2482d157e27f3f560897d93f873a1319c4040f693c780fc2983cd1396788725261d7844daeecd3bcd9d0b498d46e5e3ccf240b2c85cf76632d49987394c54cdb375404eded46967f96b49d1b034a1b5e394ad702494d9e4a465984feaf16eb5c73db3fef2e26891021a997639959aabb9919d0a4cf18678cb9525c7ae7400e0333fa3d893a9608d13c988480d49d5e9fe2c1a1c2140232707bcb0f45c7703d32b8ae63e8a14e75b3c42f7528e7caf31136eba44a87d44c2ddf48e31dc019dcfb4540bbd388584ce698cd75ef175eea1ad90e318329a4e57482dce3ea4f885d02826f9966b88b8eaba6482daedc729b895d0f2dba0262602036d6a40b08fce22555b2fbf732534138ec3c126d79c10fa920e97cea9811c93d6bcd64180b94bd4b6d7cbdc66172e9eb176c44cde46d6213fa8a882b41aa4e2b77185eaa583eb8f66065c83f8585a1d46c6fddd6b46def1b9589ad5a47582dd3cc91c8239088957bc602f949a22f120874344c5de9cc10b1f21253e33c4a64ed0f7f6835d75b1fad256ffb00f6d502bdd1441380872d299c5ea0908dd4b2ae07c855e3b54bc4e2be5596db34a79811147cf6e489f4f3ef591606b7f8e2a3c80e3c61a7534e4343f7e678e748f4415cc1da073870e6d8d52610c08d86a02d9a13287ce7db5a4eff5871e3e894652f14e9c591f4da24b3f52ea7b144edec9ecf5a50e9f0aec677938f6ea0e6fa8aad9d6606e348e3e6045fd4dd27e6ac4076343e95a7844ccef5ead502b799aee4a16d5d41a249094540529e058c112b8b5e020bf258b937c0cb8b9e58bf4f0c432cfb6bfd431acd4fa83012424390675cb854c441b4213c45b74125920617ac8c70d5ea41e32fc859e25a780b779e7e92fa24f361866fffdcef42e4d1de21526a25ecbdd513e6b478435b04246c4dc8bf9ddf5446ef6cfbe418a376bafece35a76e13abd0874350e7a49ab3c01852e047cdfc92059a76fee3c0e205f4fc3b8e96707cadf0fdf29530d60336c4cb2e5b202319ad6dcd2f52f2fab3d5e20b1eb6f98ae0c688e93238feb4ea07c2ed678c6d918d2b8bee93dbdd21eec6262af7fd1721477e6d8613de23cafd012f7c520f500dac145b4a41923d19af773f8d19ebeb7d418d73136a6053eeff4586d17da0ebb960b8b390ce47b7843072ce6f825d1cfba4678cb7ba5d9e387e3e3beef88806d562445efc15b03d41f29b292466d1b62ba20957a99ccbc756f85299fcc2f8ad31f3a5d98fe30d077ae6b2d7083ca406f18887a28e3fe7dd92070ddf284f049fc93bbb110750d44b383f04b78656be57857f8d52f0819185fa9e0b60bb35e0a47c84e8264fe37e0081667cfc0a2d883a67e511faefda2bac7a7d9ae3943c6028f7e596a3a6e58fa87eb3f505da64e7d34cf44e58c93113b91b2ec5426b2f3f969c9256d0d09796a66e1d55d6a859f44531693a4048a9eebfa68d3c38a2b7331b89045f4c9e1f113d30f3fa74027488ee28758a6337798253a8888195b63c0ce2eaf2d3fef31b36b5e75c7e5c69a062b49b337ed378f92483a9755007ed71d60b2a510acf56c69a44bc76640aff22ed9bb24ea5eac8d4df5c9fc6be45530458569daec433d00265b798f86004f468ead3fe95167c5578ac86d959a51b65e9e12fc5eb53cf10b6e83d3b8e3d76034ce4cd1ca759d838dd72c941fe444eadb41cdb5f0bf0a1a384eaf9caf21a9f6f36dac959f6fdad20aa6b263ce6399ff9272364ed0aed540db83e871ae11310ad0597d8e19dd7b82d8fb77b56241675c9519bb03f32d79ba719ecf9b0d734d0d91081121b2cb4efc0438f43501ea7c4593d6df0e701907977b48d8bd35c89f2cd4740665482e95792f567478dcd34150aac67f0ec5bb100a6746141f967a", "51", "c3619e8a2a3739738eeaf72033675318d5d5d493b1b1d679be64a306a06171ab83ab066a80242b253c2ce523dfd55cc04a055cba62dd1e78077346a90f9e07da13c61170562f77a399a70ffacd91099f62f75623a3f058e137bc26725406b62b0d66929bd8b617db226506867497d1fc75029d1c77185a78aa7a415080e71dc33727d087fd654b0369c2f316ba9ad2eaace0cbe19bd3a921882c220344905a2afc4fe7eac112fb27f0e74263388081ed278f01f853079a272cf10e4a4c3af089b5dd9a779b3a16931a8dcbc799e4816590b9eecc65a9330e7298a99b66ea809dbda8d2cff2d693a36069436bc7295ae04929b3c948cb309fd5e2dd6b8e7b67fde5c4d122043532ec732b355773233a1499e30cf1972a4b8f5ce801c0667f47b12752c11a279310901a93abd3fc5834384280464e0f7961e8b8ee07a65715cc7d1429ceb67885eea51cf95e6226dd748950fa8985bbe91c63b8033b9f68a8177a710b099cd319aebde2ebdd435b21c63065349cae905b9c7d49f10ba0504df32cd71171d574c905b5db8e53712ba1e5b7404c4c0406dad481611f9c44aab65f7ee64a68271d87824daf3821f5241d2f9d53023927ad79ac83017297a96daf97b8cc2e5d3d62ed8899bc8dac427f515105683549c56ee30bd54b07d71ecc0cb907f0b0b43a8d8dfbbad68dbde372b135ab48eb05ba79923904721112af78c05f293445e2410e86898bbd3982163e424a7c67894c9da1efed06baeb63f5a4adff601edaa057ba28827010e5a5338bd41211ba9655c0f90abc76a9789c57cab2db6694f302228f9edc913e9e7deb22c0d6ff1c547901c78c34ea69c8687efccf1ce91e882b983b40e70e1cdb1aa4c21811b0d405b342650f9cfb6b49dfeb0e3c7d128ca5e29d38b23e9b44967ea5d4f6289dbd93d9eb4a1d3e15d8cef271edd41cdf5155b3acc0dc691c7cc08bfa9ba4fcd5880ec687d2b4f08999debd5aa056f335dc942daba834492128a80a53c0b18225716bc0417e4b1726f8197173cb17e9e188659f6d7fa86359a9f506024848720ceb970a988836842788b6e824b240c2f5918e1abd483c65f90b3c4b4f016ef3cfd25f449e6c30cdfffb9de85c9a3bc42a4d44bd97baa27cd68f086b60848d89b917f3bbea88dded9f7c83146ed75fd9c6b4edc2757a10e86a1cf4935678030a5c08f9bf9240b34edfdc781c40be9f8771d2ce0f95be1fbe52a61ac066d89965cb64046335adb9a5ea5e5f567abc4163d6df315c18d11d26471fd69d40f85dacf18db231a5717dd27b7ba43dd8c4c55effa2e428efcdb0c27bc4795fa025ef8a41ea01b5828b69483247a335eee7f1a33d7d6fa831ae626d4c0a7ddfe8b0da2fb41d772c17167219c8f6f0860e59cdf04ba39f748cf196f74bb3c70fc7c77ddf1100daac488bdf82b607a83e5365248cda36c574412af5339978eadf0a533f985f15a63e74bb31fc61a0ef5cd65ae1079480de3110f451c7fcfbb240e1bbe509e093f927776220ea1a896707e096f0cad7caf0aff1aa5e103230bf53c16c1766bc148f909d04c9fc6fc0102ccf9f8145b1074cfca23f5dfb45758f4fb35c72878c051efcb2d474dcb1f50fd67ea0bb4c9cfa699e89cb192622772365d8a84d65e7f2d3924ada1a12f2d4cdc3aabad50b3e88a62d274809153dd7f4d1a7871456e66371208be993c3e227a61e7f4e804e911dc50eb14c66ef304a75111032b6c7819c5d5e5a7fde6366d6bceb8fcb8d340c5693666fda6f1f2490752eaa00fdae3ac1654a2159ead8d348978ecc815fe45db37649d4bd591a9beb93f8d7c8aa608b0ad3b5d8867a004cb6f31f0c009e8d1d5a7fd2a2cf8aaf1590db2b34a36cbd3c25f8bd6a79e216dd07a771c7aec0699c99a394eb3b071bae59283fc889d5b6839b6be17e1434709d5f395e4353ede6db592b3edfb5a4154d64c79cc733ff24e46c9da15daa81b707d0e35c226215a0b2fb1c33baf705b1f6ef6ac482ceb92a337607e65af374e33d9f361ae69a1b2210224365969df80871e86a03d4f88b27adbe1ce0320f2ef691b17a6b913e59a8e80cca905d2af25eace8f1b9a682a1558cfe1d8b762014ce8c283f2cf400000000000000000000", .None}, + {.Shl, "-f3ce7d77ebea75b4411bc0d5226dc8ae0482b6d67466900c4ca65caafc99fc498004f0ea1bd708085da07229a732980b090ef5c255c35e4760e50e39733615ca4d77b6382024b72ba3beb8a91464c7c9772f669823885608b1872f7f20b3a0347a613964dcdd1b56015106eb99b9b8c2df72b9628271058f16a5c7a627ef6f4ff44eca438e7aa3a4014c7b1d5d1b8163addce57c2919a4d51e300d42e84562dfdbde38668476a3163d8a1d163c83c6b293f6fe96b3e7582a7ae928d97954c6eb29ec4e6fbd7931132538eb00e70b36c5ae2c5a4d3ce9691d23633656ca199805294dc34a4031f369ca7996b33476b1895493c8125f16dc77fbb572a7c17acaab742d02de695005ce15083a541b7f331452aed1a42e1602e4b3fafdd41b281a108b854ecc7d87925b92de593eeadd2caa927fe2a99e23e4ce0642283ffb447691f14e3f71791ccd96d741e476782e64506923ccb05f5b1a90938cd7756a05e1084b8898adafba22af6d16ddb6560eb436bfbb39641a64b9b7580e1de990b450196f45fb8edf588fcb16782eb64a976c4012433aae501cad92dfa4d02f93bff2821228360bc082849425ce7675f3c8de3d8df893e3d13bbf342b1860d8f54da722ab02971019faae45ef0a458e58463af26522f27cc817c3942a86f8843377abe5deaec12ae78837871eadc2e73479125a7b9a981ff85dc0771cf39914dcf7a6c6251404efbd8af0b42be26ccabfbb2f8b5e6ad1607e88fd86085acfee6713f7f7fe95ed18338d59c97e9178a2a12c623a7fdb0cdc853d823b1f8daf56c5f73b743b89c24e666456575a58f28de614c612bd131773c55de2a7182da6474fd500f98eb45f0e3a7110f9346e2564c5ebc3eff17aafee6c97d0ea9c093ad17adf99d27069c0d582554c5f1ba398b98583d4ecc3ac57b999d1c0fb93d202747d8abf2aa4b952e060953060f1481840f83ac21483545d3e93d8ba700f5d2ca4c358b0cb8ce06aaef356da238e9f012e6f614a4a28358a56bb0fb24cde51b8b3cac57178a01b90c06b3787478c24b04ff2782972f09305828a0f6b58331be2a5243b8262baeddf9c56adcdb217c692e3627b9aab3063dbc1a049892f9601c44075dc8ea800a0ed1640e3b8392e7063404e479da85b36dd5c289f0e960e93ec6b4b334751fe3c7ddeb6468b229934a061a6ef0ce662560c9d25795a8893b39f4a2ca29ff7f77a8ed5989c9a6e171c5a7f7e3b28924482e726eb152a5c8a2d564d14f27e72ea4231cb9b3e864538c39e8cf07bc97494431b7e2770f8d202dd904115719a1625761b122f7b73fbd87ab494d8184443da38e4b3a3fb2c8e2d58ba73e5455206d71f7b305a2fb15eb1d7beb2f3f4c40c0b2736116a69b670afa9ea02af8d2564eb2d23d99401395abc3b4434f964dc094a65cdb95bd793bc8ad0224e7d42fc881bec404462284d43643598859fbb0f2848f797b42e89deed1712ec5754617c33a0d37c1f6a217bd09ffeab8070f642419c9031a6c3c8e225560c8bf314b1c94ea494e25ecf75fc7fd8c0c78d6076bf0b630e5a43c0ed6810044917b3ae69b8221ac1abe1e87bd4c05a7069f61e2bc0748c503bc580d3b8e04b498de2e43cc21e5e67ec77e4ced81180b51fc1183ba7eee16d559af0cd8fb3fbf7baf61be5ca4aabfc2cef1af256fc93c1a16c18833e1338fc3d4f4dadcafab385db4932b3c7711ba659e77a344fc9456990899c9ecdeca5c0f52c1969162aa765921b40b7e9cff1ba55be3afd14f09aa5aa203ce0e55c783b96d960282a3a7316f4f5ef73d962aa69bd638b3f8b514a1642b409203b38958ea1b0ccd4676a8b7159eedbdadceae5e1e521f11c2968f4cf51e4ac5511884f30f6961a3be7a86f0c0851a70e1039cde4c1d3a84dff17d227be61797b469570febcee819f617b4311852079d091c985c63df197d03e2e8037567a2176ed557385d69973f495fd0bf3576071b3ebdd6cc9d096626b3972e51a00467e314204176ed65b9f8ab407eea04a4f83bce473da2ef0e93223f7d937b5255e2e284ce7a293a89d35e81fa7ba7e01e7e2cb6cf07d2658eee871ecf9d77424ee655e8a4c9a1921c9763b4db4219b9cf0", "4f", "-79e73ebbf5f53ada208de06a9136e45702415b6b3a33480626532e557e4cfe24c00278750deb84042ed03914d3994c0584877ae12ae1af23b072871cb99b0ae526bbdb1c10125b95d1df5c548a3263e4bb97b34c11c42b0458c397bf9059d01a3d309cb26e6e8dab00a88375ccdcdc616fb95cb1413882c78b52e3d313f7b7a7fa276521c73d51d200a63d8eae8dc0b1d6ee72be148cd26a8f1806a17422b16fedef1c33423b518b1ec50e8b1e41e35949fb7f4b59f3ac153d74946cbcaa637594f62737debc9889929c758073859b62d7162d269e74b48e91b19b2b650ccc0294a6e1a52018f9b4e53ccb599a3b58c4aa49e4092f8b6e3bfddab953e0bd6555ba16816f34a802e70a841d2a0dbf998a295768d2170b017259fd7eea0d940d0845c2a7663ec3c92dc96f2c9f756e9655493ff154cf11f2670321141ffda23b48f8a71fb8bc8e66cb6ba0f23b3c1732283491e6582fad8d4849c66bbab502f08425c44c56d7dd1157b68b6edb2b075a1b5fdd9cb20d325cdbac070ef4c85a280cb7a2fdc76fac47e58b3c175b254bb62009219d57280e56c96fd26817c9dff94109141b05e041424a12e73b3af9e46f1ec6fc49f1e89ddf9a158c306c7aa6d39155814b880cfd5722f78522c72c231d793291793e640be1ca15437c4219bbd5f2ef57609573c41bc38f56e1739a3c892d3dcd4c0ffc2ee03b8e79cc8a6e7bd363128a0277dec5785a15f136655fdd97c5af3568b03f447ec3042d67f73389fbfbff4af68c19c6ace4bf48bc515096311d3fed866e429ec11d8fc6d7ab62fb9dba1dc4e12733322b2bad2c7946f30a63095e898bb9e2aef1538c16d323a7ea807cc75a2f871d38887c9a3712b262f5e1f7f8bd57f7364be8754e049d68bd6fcce93834e06ac12aa62f8dd1cc5cc2c1ea7661d62bdccce8e07dc9e9013a3ec55f95525ca970304a983078a40c207c1d610a41aa2e9f49ec5d3807ae965261ac5865c670355779ab6d11c74f809737b0a525141ac52b5d87d9266f28dc59e562b8bc500dc860359bc3a3c6125827f93c14b9784982c14507b5ac198df152921dc1315d76efce2b56e6d90be34971b13dcd559831ede0d024c497cb00e2203aee47540050768b2071dc1c973831a02723ced42d9b6eae144f874b0749f635a599a3a8ff1e3eef5b2345914c9a5030d3778673312b064e92bcad4449d9cfa516514ffbfbbd476acc4e4d370b8e2d3fbf1d944922417393758a952e4516ab268a793f39752118e5cd9f43229c61cf46783de4ba4a218dbf13b87c69016ec8208ab8cd0b12bb0d8917bdb9fdec3d5a4a6c0c2221ed1c7259d1fd964716ac5d39f2a2a9036b8fbd982d17d8af58ebdf5979fa620605939b08b534db3857d4f50157c692b2759691ecca009cad5e1da21a7cb26e04a532e6dcadebc9de456811273ea17e440df62022311426a1b21acc42cfdd8794247bcbda1744ef768b89762baa30be19d069be0fb510bde84fff55c0387b2120ce4818d361e47112ab0645f98a58e4a7524a712f67bafe3fec6063c6b03b5f85b1872d21e076b40802248bd9d734dc110d60d5f0f43dea602d3834fb0f15e03a46281de2c069dc7025a4c6f1721e610f2f33f63bf2676c08c05a8fe08c1dd3f770b6aacd7866c7d9fdfbdd7b0df2e52555fe16778d792b7e49e0d0b60c419f099c7e1ea7a6d6e57d59c2eda49959e3b88dd32cf3bd1a27e4a2b4c844ce4f66f652e07a960cb48b1553b2c90da05bf4e7f8dd2adf1d7e8a784d52d5101e7072ae3c1dcb6cb014151d398b7a7af7b9ecb15534deb1c59fc5a8a50b215a04901d9c4ac750d8666a33b545b8acf76ded6e7572f0f290f88e14b47a67a8f2562a88c427987b4b0d1df3d437860428d387081ce6f260e9d426ff8be913df30bcbda34ab87f5e7740cfb0bda188c2903ce848e4c2e31ef8cbe81f17401bab3d10bb76aab9c2eb4cb9fa4afe85f9abb038d9f5eeb664e84b31359cb9728d00233f18a1020bb76b2dcfc55a03f7502527c1de7239ed1778749911fbec9bda92af17142673d149d44e9af40fd3dd3f00f3f165b6783e932c777438f67cebba127732af45264d0c90e4bb1da6da10cdce7800000000000000000000", .None}, + {.Shl, "-a1a387c7436ee2efe94d9bd870295fcca67fb9717a19e2b3ae28b2dfb529f28989ed4c7821198e65dd226cdf05be8b30a07005c23dac2d529a903548b0ca63b3f81607b805cbbbbc4c6b071c825d9a6d0ddb6bd64572f10846d45ecfa69b88343aaa547e77af29a3b0a6f4ca6ae2780254696ec606f982d00c821b9efb38e017da8af9f73ea20a40812f93d78f11dafc70dc479552d538673ea4a630ba9cf3c07e8670c2a6ff042d308aa8d7498f58df0722a356285eceab4505f07911ed163effbc9ccc02f2f407425172b9f4687c170836e056e8cc0030b24764a38338c4589f906a67c46b92693d6f457b9442e51183211505d1afab48c93ec6b9d87a7209887e0f2ad61a5942940163551f044b07e63d71a74812fd7cbd7a56bcf43d306e2dc94ecf1a9d5ee1c4a33884dffbba2dcba3a3e956e17795a49f66dd6f1adaeddf6667054912fc31ee2c9f964e32f20032c0b521480475e826cd7fb8eb2dd30f156f0df298d6053c85961659fcb965d20e70d7a83bb575c19a6e6595dd38767824f01074c8eca015840bdac2f173c902c8a0e02a8ca336f67e7e9d85e98fe14cb38877189af3fc796c3e752069ebba4c0204d826b5ef412e5534d0bf98eb68bcb617b72cd3fe8218c74169f51cd1a649d02ca50eb82450cd8bb4cd163e66d73c85c2dea381d5d16ab844149637eb8673cc43e01f8325b629274392d16dc09ad6ccdfee7fc53d903a80867c1f2b735cb62dce49fefaa79fd30115f5dbfac71c7fecca7b4e363ac5e17427956ba0a420485135339ba9c4c79dc0211a94caf99a5b22dab0d81d8f2a7637b425ba103e8514fc4e6adc15009b706eeb4a26b8c96ed99792b8f7a8c154d70e801dffbc1e46974bfa4153fe71d7617d3d75676507d931c8f37eaddeb48db694dd37217fd03a9ddbe1b5dfd9f75391bc1e0037b6724f44db6f158569fbf595f45c8659883c1f3fc29d4d82557093b20c29e67ce7bb8994727f46e3c9e50ace29bd1eb97c3019807273da2ef0b2e5944018ad9656652a5649a895c3b9502b3d698b98bc93ff7d88487c1ee61c8ddc9f03734e82e58eae110b6d49d2f6099319da275e7ef5366ec5bc48fa706cf40b8253eccfa41c06b210316784b7e3d7a36c77dc9fdf19eab8dd8ef35a80fa964672aa431989efbb30039beba3acdf35e30dc254dc74a5f8aea62d8948fa580b10a535323854fd8eb76d3164259ba7c950d2d2f968f7c72ea14e353c4595759144d0ae9451bd7f4cfb54acf510a1c9510edd973f10fbfbd6800788fff5842fcaf1ad163b6b735e6f720b987e320b5735c91b461856e324a1c12d827db2d78cfe425b777cc4561d06f1c68dd1ead8d92961a00cfbe5a6e59943781a388bb65bf986d2683803d071f9cd2cbdc291ce9a860629840ef748c876f14565439ad380c55831060cc0c5f8e9be4a090d09fa34edd91870d03f389f17cba6ac2be335f559558f8f52cb6b7876600a2e838b00f364b3f883640cea218443a6a6be42da8b2c1ac498ceac527d0a028af39c636fdd016e9351cd3dc1c02aba175f40e909458460d7d8c8ff7d2a811d46196446cb6ba3a13b4bab2c4400b3c2e3cf27600ef4a56646062b6d3bd97b5cafe7c82e7a692cc77118550978a81f954569c6ceea4636d4240bbddf1992fce98d1f4437acc714961b29c07c2adf1e35885bd1404e5c5aea71f2a93a0aaf8908a4d7c70b364249bf8ba8418818c9cb1cff9363a69108b7f0b0aad233d401345adb7aa1ac3d7261865d06fc60566e914e27bc35c8bfacc614aded85f242e9ba2ca872654ac9ac5ea79d02f612307491745b7f7bb318c6c6adb66f2c6feed62509b29687cd7cfbf74acd032f32a0afa282a8eb4c8a2561e4e325dac6d982cb3e64f78eca7a19c51f60b7ad30a47abd0973c4949b9d41f6971889518621784802821c6875d4d2cd47e32f8b1f4d0e6880dc5c1090332dd1813830f383753554d904e5872ee5c99213d2c62dd86bccd8c3f9004c93ffefd3e11b2b75af2c3ffc3f28e2248e022def4ad6f78fca6da39106f9148d3853366a6b6a99c387cf28474251c7d9446eba57e336131600e471f11959e0e304241bb5f71f6986b63cfb", "46", "-2868e1f1d0dbb8bbfa5366f61c0a57f3299fee5c5e8678aceb8a2cb7ed4a7ca2627b531e0846639977489b37c16fa2cc281c01708f6b0b54a6a40d522c3298ecfe0581ee0172eeef131ac1c72097669b4376daf5915cbc4211b517b3e9a6e20d0eaa951f9debca68ec29bd329ab89e00951a5bb181be60b4032086e7bece3805f6a2be7dcfa88290204be4f5e3c476bf1c3711e554b54e19cfa9298c2ea73cf01fa19c30a9bfc10b4c22aa35d263d637c1c8a8d58a17b3aad1417c1e447b458fbfef273300bcbd01d0945cae7d1a1f05c20db815ba33000c2c91d928e0ce311627e41a99f11ae49a4f5bd15ee510b94460c84541746bead2324fb1ae761e9c82621f83cab5869650a50058d547c112c1f98f5c69d204bf5f2f5e95af3d0f4c1b8b7253b3c6a757b87128ce2137feee8b72e8e8fa55b85de56927d9b75bc6b6bb77d999c15244bf0c7b8b27e5938cbc800cb02d4852011d7a09b35fee3acb74c3c55bc37ca635814f216585967f2e5974839c35ea0eed5d70669b9965774e1d9e093c041d323b28056102f6b0bc5cf240b228380aa328cdbd9f9fa7617a63f8532ce21dc626bcff1e5b0f9d481a7aee9300813609ad7bd04b954d342fe63ada2f2d85edcb34ffa08631d05a7d47346992740b2943ae09143362ed33458f99b5cf2170b7a8e075745aae1105258dfae19cf310f807e0c96d8a49d0e4b45b7026b5b337fb9ff14f640ea0219f07cadcd72d8b73927fbea9e7f4c0457d76feb1c71ffb329ed38d8eb1785d09e55ae8290812144d4ce6ea7131e7700846a532be6696c8b6ac360763ca9d8ded096e840fa1453f139ab7054026dc1bbad289ae325bb665e4ae3dea305535c3a0077fef0791a5d2fe9054ff9c75d85f4f5d59d941f64c723cdfab77ad236da5374dc85ff40ea776f86d77f67dd4e46f07800ded9c93d136dbc5615a7efd657d172196620f07cff0a75360955c24ec830a799f39eee2651c9fd1b8f27942b38a6f47ae5f0c06601c9cf68bbc2cb96510062b6595994a95926a2570ee540acf5a62e62f24ffdf62121f07b987237727c0dcd3a0b963ab8442db5274bd8264c67689d79fbd4d9bb16f123e9c1b3d02e094fb33e90701ac840c59e12df8f5e8db1df727f7c67aae3763bcd6a03ea5919caa90c6627beecc00e6fae8eb37cd78c37095371d297e2ba98b62523e9602c4294d4c8e153f63addb4c590966e9f25434b4be5a3df1cba8538d4f11655d6451342ba5146f5fd33ed52b3d4428725443b765cfc43efef5a001e23ffd610bf2bc6b458edadcd79bdc82e61f8c82d5cd7246d18615b8c928704b609f6cb5e33f9096dddf31158741bc71a3747ab6364a5868033ef969b96650de068e22ed96fe61b49a0e00f41c7e734b2f70a473a6a1818a6103bdd2321dbc515950e6b4e031560c418330317e3a6f928243427e8d3b76461c340fce27c5f2e9ab0af8cd7d565563e3d4b2dade1d98028ba0e2c03cd92cfe20d9033a886110e9a9af90b6a2cb06b12633ab149f4280a2bce718dbf7405ba4d4734f70700aae85d7d03a4251611835f6323fdf4aa04751865911b2dae8e84ed2eacb11002cf0b8f3c9d803bd295991818adb4ef65ed72bf9f20b9e9a4b31dc4615425e2a07e5515a71b3ba918db50902ef77c664bf3a6347d10deb31c52586ca701f0ab7c78d6216f450139716ba9c7caa4e82abe2422935f1c2cd90926fe2ea1062063272c73fe4d8e9a4422dfc2c2ab48cf5004d16b6dea86b0f5c98619741bf18159ba45389ef0d722feb31852b7b617c90ba6e8b2a1c9952b26b17a9e740bd848c1d245d16dfdeecc631b1ab6d9bcb1bfbb589426ca5a1f35f3efdd2b340cbcca82be8a0aa3ad32289587938c976b1b660b2cf993de3b29e867147d82deb4c291eaf425cf12526e7507da5c6225461885e1200a0871a1d7534b351f8cbe2c7d3439a20371704240ccb74604e0c3ce0dd4d5536413961cbb9726484f4b18b761af33630fe401324fffbf4f846cadd6bcb0fff0fca388923808b7bd2b5bde3f29b68e441be45234e14cd9a9adaa670e1f3ca11d09471f6511bae95f8cd84c580391c7c46567838c10906ed7dc7da61ad8f3ec00000000000000000", .None}, + {.Shl, "b5380d0bb3d6031217f588ddf64f2242f5886f7c80b04a89f0211d342582f08a59b86c09d600c0490b30fc8787b135cd866cceb4c316ec46f4fabe9ac250eb45a759b9501d6afa82ae8113558b53af1707644c482e38de9079385410d9c4dd92fc3023004e94415130b0a5c6436d9a9c7828b28a745b1e04ef60ef532e888cb00e5b6fa5c24f463897d38eba8b20d7da7a9c68167309352e95fc23fe39785bb9f80b3c1afd4bf0b08d6a1f99e864bc14fb6016d2e62c7881389d82f5a76acbb138431e13e54821e5f3b36bd00a7d8a1776a8af286514ce1ca44cbbf5ed50932398d667d6aaad132244916547f1a014a8b64eb5cf8ac747bc56ed01c0efbc00dd65b24d6c6deeb21adfaec41a96b50e27af488c5c51ab33ca600a0c641a418fb744a367438b71b4f2439f3ead2607c51ad47e36356e242a9899c965667cb0645311d63386a04b2b67722e8cde6c413ce076f664580eccc873b10e885a1868f53703598ddcfca809cd3083a5b0ee8dcffa7852f41acab4c0878df03897e077a883ca4209f569f81c32c77750e6a2969f3a881a986cce591c4be03a22e8fdc7a839dedc5c9c859b266fd7c5b94fb9a9845965747dbd73cffd5fcde3751ddbf8a07849907ab2bbddce9d84ddb6683e5233b3bdb4784b54795101fa35d1286db3fb4ec03c0541e0362cbf663996ea1f3adabb862045de76afc705036f9a4a44f862237d8d01c79a8beaf37296c70eb5a290a753d6b9ad02a46724691a7fe44052b747fd8034d22bf3e5915d6145590b63b9c46798df320634154d8acebf2746887750f5a96cc2e915109f0a404203bb6da8cef20f11f737976653a9b7a386031a0f523c5d64a1f7d890f800e32f6ae07975aed034a54dcff56079ad4f09232cdfd77cd6ad896fe7494cf767262f26e5be184c7c8615b87ac02c88f2d0f9ec922d99c3c8106c7c15f0cf1605cc2ebd250f4174fe5b03d381463d196475665677f10902d1b872fded3f56bd4de026ffdb9e0385b9ddedc10f620303e2d3412cfba47e1e092b1bdfe8e8055dd186517931890a9baeb34d944c9f164166814de080407722be03da8cf591f63a2a0df7eb9b43f958a6ab2cb71fea9737e4179eee7db7d39230e8830813da418a7e851403806a70173464f559b40d3151436a82c7bcf3793e438566c0040b59e2812dc7c3fb377412fe1eac20576850d6eeb9afb8754d8c0650341e79b179c0a34f6eb1781f6cefd3d617f69bf70e83b73ab12e361b86f13fb6fe57ae02f299c3d659f8031757128bbc21d770cd8ce455dd74cc93c9929ae055809953fea49e5be2fdc21196b7204d7605a572b20e961ba8d2ea3249ba74cea01f94bcb363ac8875fec944c3d0203d1b1ca2f98bc27d0e721fd0757233cf5d932cb83dd2780d16a41f9a688e33c4dc321726b6deedf728ceeafca9a4af259662b8f6c507af0334411ce40011adf6209669396aa9821b94474092b9512dcbec04d33e8ee1b223394d2b43c70bacb67fd845f2dfb51b69d7834deb8b71f258b4cf1ad898d10c68d3808ab9650f1b02c89f465f3859bb7655dea173c59eb79a90e882fe6335ec634e853d582fe0a5fb548771f6f54a8926c30e9345e230f9f14cfb60b4cc2db652fafc3384ced4e8a480acf5363eaee892b8f0f74fa26b52b6231db192ae5adf76abe171777dad49b958f1d3cba25cf88b1f8b7cfdd6529f943dafe8aaa69e4fc0ad83c245568377242b0c5a0362886f5aad4540e618f8a1237cc161d1a2663b4a93b1c79ef550625960dea6b1eab426dfab19cbc575011e9dc5d50a2bfe3caa7d6e317bc8ad35fa5eb6fb829349db84941e2d30031132cd6144573fadb0734917640314c02703d16e47b054863ad24015bfb48dae779b7dc2b6671d1fea03871f57b23279b141615227ac62bf59ca1fe4bd7efdd8c89f3454fa629c9aeb522c4682b37d469dd636be71c7240c1770805de995c2d86d24ccbdb5d6faedd15b357521d6d5243b4233512f6e5e4b269cdf6c5827f7ca25c79b08a460050f89c328650b1f6464349f7bca7f9508c68cd2e8399afd98f3bb8f2beecf7115808e033ed8fd0880e7bddd24bbbde5238364e34f2a89848616aa", "21", "16a701a1767ac06242feb11bbec9e4485eb10def901609513e0423a684b05e114b370d813ac0180921661f90f0f626b9b0cd99d69862dd88de9f57d3584a1d68b4eb372a03ad5f5055d0226ab16a75e2e0ec898905c71bd20f270a821b389bb25f86046009d2882a261614b8c86db3538f0516514e8b63c09dec1dea65d1119601cb6df4b849e8c712fa71d751641afb4f538d02ce6126a5d2bf847fc72f0b773f0167835fa97e1611ad43f33d0c97829f6c02da5cc58f102713b05eb4ed5976270863c27ca9043cbe766d7a014fb142eed515e50ca299c39489977ebdaa1264731accfad555a26448922ca8fe34029516c9d6b9f158e8f78adda0381df7801bacb649ad8dbdd6435bf5d88352d6a1c4f5e9118b8a3566794c01418c834831f6e8946ce8716e369e4873e7d5a4c0f8a35a8fc6c6adc4855313392caccf960c8a623ac670d409656cee45d19bcd88279c0edecc8b01d9990e7621d10b430d1ea6e06b31bb9f950139a61074b61dd1b9ff4f0a5e8359569810f1be0712fc0ef5107948413ead3f038658eeea1cd452d3e75103530d99cb23897c07445d1fb8f5073bdb8b9390b364cdfaf8b729f735308b2cae8fb7ae79ffabf9bc6ea3bb7f140f09320f56577bb9d3b09bb6cd07ca467677b68f096a8f2a203f46ba250db67f69d80780a83c06c597ecc732dd43e75b5770c408bbced5f8e0a06df349489f0c446fb1a038f3517d5e6e52d8e1d6b45214ea7ad735a0548ce48d234ffc880a56e8ffb0069a457e7cb22bac28ab216c77388cf31be640c682a9b159d7e4e8d10eea1eb52d985d22a213e1480840776db519de41e23ee6f2ecca7536f470c06341ea478bac943efb121f001c65ed5c0f2eb5da0694a9b9feac0f35a9e124659bfaef9ad5b12dfce9299eece4c5e4dcb7c3098f90c2b70f5805911e5a1f3d9245b33879020d8f82be19e2c0b985d7a4a1e82e9fcb607a7028c7a32c8eaccacefe21205a370e5fbda7ead7a9bc04dffb73c070b73bbdb821ec40607c5a68259f748fc3c125637bfd1d00abba30ca2f2631215375d669b28993e2c82cd029bc10080ee457c07b519eb23ec74541befd73687f2b14d56596e3fd52e6fc82f3ddcfb6fa72461d1061027b48314fd0a280700d4e02e68c9eab3681a62a286d5058f79e6f27c870acd800816b3c5025b8f87f66ee825fc3d5840aed0a1addd735f70ea9b180ca0683cf362f381469edd62f03ed9dfa7ac2fed37ee1d076e75625c6c370de27f6dfcaf5c05e53387acb3f0062eae25177843aee19b19c8abbae99927932535c0ab0132a7fd493cb7c5fb84232d6e409aec0b4ae5641d2c3751a5d4649374e99d403f297966c75910ebfd928987a0407a363945f31784fa1ce43fa0eae4679ebb2659707ba4f01a2d483f34d11c6789b8642e4d6dbddbee519dd5f953495e4b2cc571ed8a0f5e06688239c800235bec412cd272d5530437288e812572a25b97d809a67d1dc36446729a56878e17596cffb08be5bf6a36d3af069bd716e3e4b1699e35b131a218d1a7011572ca1e3605913e8cbe70b376ecabbd42e78b3d6f3521d105fcc66bd8c69d0a7ab05fc14bf6a90ee3edea95124d861d268bc461f3e299f6c169985b6ca5f5f867099da9d1490159ea6c7d5dd12571e1ee9f44d6a56c463b63255cb5beed57c2e2eefb5a9372b1e3a79744b9f1163f16f9fbaca53f287b5fd1554d3c9f815b07848aad06ee485618b406c510deb55a8a81cc31f14246f982c3a344cc769527638f3deaa0c4b2c1bd4d63d5684dbf5633978aea023d3b8baa1457fc7954fadc62f7915a6bf4bd6df7052693b709283c5a600622659ac288ae7f5b60e6922ec80629804e07a2dc8f60a90c75a4802b7f691b5cef36fb856cce3a3fd4070e3eaf6464f36282c2a44f58c57eb3943fc97afdfbb1913e68a9f4c53935d6a4588d0566fa8d3bac6d7ce38e48182ee100bbd32b85b0da49997b6badf5dba2b66aea43adaa48768466a25edcbc964d39bed8b04fef944b8f361148c00a1f138650ca163ec8c8693ef794ff2a118d19a5d07335fb31e7771e57dd9ee22b011c067db1fa1101cf7bba49777bca4706c9c69e5513090c2d5400000000", .None}, + {.Shl, "5fd926e1d24796a653e18b824adce43a27e0074d0d04b01e2eeebb349ca423f1083aa209cde6f616bee6b67621886b3ade3a93922860aeadbb8ccda4974abee516a1181ee3debb95e58dbf2db6fdbfc316d4a813449ca3c2e46fc8b621c8c9289208346de3ae905c0c9b9959bf2c19c317aca5d4e0828168e03e57963723a3d65952316e0bca798361dd1ac7ef6281252cddd212a956e0cb3d53099f7d8fde148d29c407c5c1b5d45103ef853ea7788a5b8eeb4fb8160acd89b69106dccaa471ab7b42fe9b465db70f230ccf2af765142d0e629c4bc37f3b859781722dc297dbe2ea72c7416e5bcd66e4a20ecadec31d9a24329a6751e9490a06e4b5a99ac6ddc5bc80211f3aee6fbbdb05e4b85cae8cb66a05dc5a69744fc18f38f5e60613d07b43dbc02fde90bf034d1e9cc946175bf595961b0b27df954635918ce7863f974f201b49486d48a73cbf81d5aab1a8f77d19b5de1be2079c29f578466e448c9b90155cf2e829f849f2cf108cc3f8be1f964c8191a8438cf05cf1e9d1f44564a7532d16cea8a7f36b70894e97cab71be19e9efc8115315cdfab353a69fcf0871b8cc3a339f441b73e3955ef64f463bd0c26b442b22c0363b8d70a9e2e3dbd899bbcdd5cd7c0f868a6e7e2d2c15d7f3e8a2ed4ee95b87361d1ec5486f680b7ffa8278d3a32166ebb1a2a6671acd3faa6ea18c5a1412db80012c4651659b18d097eb4f086d75fa8eab40bf23a4b5f52f1e512bbc676f90c4eb1c3b5c3345ff9e6a9616c82439bed43a9af8e36b26e5e06cc55478d756a3590395d8bce130644da4b11a999afae48f2fcec1f7e4db94035bef83bda37d45986f47320fc7c306c7877f9d3b1f6f1030ee9b4d3f01e35793e1e62c2a94506c422fd237410cabbebcd6693b59582f4f6865e25eda68492c63900b9fb311186f6890477f3d08c12dcf865e7049a8a8bdaa197134d96b25412f17c4d2f60d1c20415c6c1dfd0a87391e1d2b3421651b77ba3df0b7e235ff872f63501e220d7e7906f6ace4b7d2c308a10c44423a1e7cd83cea2ef24ce6e66849936eda800ee23004f7601f2867566d62ce3ff6457e0c7ffecaca9d8e1bb9922d08f27a77e82bf33b7f00158228d9407df53d42fd499047404045fc4f47803387ae1765ef25dec5596100be80e89d338f043a34716506995308d0bbcfde5b2a98da50f291a08eef1656efe9e1ec9f2d54564504ea13ea5a0621a19b81f9f97d3cbcc0909d9005609816c26014b5fd0b1d5263756dc6c85dc39c76502644b40b442748ff353b5eec98692f9099cdf283ef6acdb582e5f90fc95daac76939c7fb6122894d455f99f7da9534b0caa40c760b953434931da5cbe045dac04d6713a6efe602e250d16d392c324820b0b7552c8acee56f3dc5615f9d657badb7f2f5765e7873869f52cbe6ee716dba0c640e57b43f77d33b71e7f8175480001fead7b633be6149f23a3e8bc2dd2d8b3260edac2deb3c358e25dab6ea2255d333478ac4270f606fb39538152259b6ae2ebe26388936d46923db3274ec17afdd362208645e1c2378d0168e79fee78085b8bff8253fbc67d1a5ac17c4b7625de15d4f9b55f09ad536195ada68870e93b8307df0df06e0fbe1be7364879b21ac4fc587953a630ff28b4670e134486616715b6d1cded3702fe01b59f8e4dd9edda0ad8036827364341f7774ef84f022fa9340cf884ca72d59f1f76295de9ede192e310d01d0c6c8e3e61540409f5b1972fde849176fc9496ec06894c74af9539f5f7580cd6d11fda1769f32792c3ff05d9eaaee8cebb531a831c2f1d7557b1bc5705e66740fe830e1963b824e28efd6d4c86a8b3d34a6eaed1205bc6a1d65ff47060469d1870d11ef93f617828efc33aee73a89f6dc1d107dd4f4046e6c52b50a053cebc0e84fba315fd8bf735c1d929a7ca29ef9e24c0ed6a82d2c90fff1cc479a8ce3f23b4bbe11d311a27b8fd05a432d92738801ef6ae6b23a783579a55448e75716869e86f13c06064712de0c7e4645ab1146f635790288da1792e2cd4dd6e0d038fb0796b9869ee7b5c54190ca4624e2f6c06bdd66e936ad9774d41013f5f8277f20f45b6c63676ed5bbfe283713fe4cbb2", "1f", "2fec9370e923cb5329f0c5c1256e721d13f003a68682580f17775d9a4e5211f8841d5104e6f37b0b5f735b3b10c4359d6f1d49c914305756ddc666d24ba55f728b508c0f71ef5dcaf2c6df96db7edfe18b6a5409a24e51e17237e45b10e4649449041a36f1d7482e064dccacdf960ce18bd652ea704140b4701f2bcb1b91d1eb2ca918b705e53cc1b0ee8d63f7b14092966ee90954ab70659ea984cfbec7ef0a4694e203e2e0daea2881f7c29f53bc452dc775a7dc0b0566c4db48836e655238d5bda17f4da32edb87918667957bb28a1687314e25e1bf9dc2cbc0b916e14bedf1753963a0b72de6b3725107656f618ecd12194d33a8f4a48503725ad4cd636ee2de40108f9d7737dded82f25c2e57465b3502ee2d34ba27e0c79c7af30309e83da1ede017ef485f81a68f4e64a30badfacacb0d8593efcaa31ac8c673c31fcba7900da4a436a4539e5fc0ead558d47bbe8cdaef0df103ce14fabc233722464dc80aae797414fc24f967884661fc5f0fcb2640c8d421c6782e78f4e8fa22b253a9968b675453f9b5b844a74be55b8df0cf4f7e408a98ae6fd59a9d34fe78438dc661d19cfa20db9f1caaf7b27a31de86135a21591601b1dc6b854f171edec4cdde6eae6be07c345373f16960aebf9f45176a774adc39b0e8f62a437b405bffd413c69d190b375d8d153338d669fd53750c62d0a096dc000962328b2cd8c684bf5a78436bafd4755a05f91d25afa978f2895de33b7c862758e1dae19a2ffcf354b0b64121cdf6a1d4d7c71b59372f03662aa3c6bab51ac81caec5e70983226d2588d4ccd7d724797e760fbf26dca01adf7c1ded1bea2cc37a39907e3e18363c3bfce9d8fb78818774da69f80f1abc9f0f316154a28362117e91ba08655df5e6b349dacac17a7b432f12f6d34249631c805cfd9888c37b44823bf9e846096e7c32f3824d4545ed50cb89a6cb592a0978be2697b068e1020ae360efe85439c8f0e959a10b28dbbdd1ef85bf11affc397b1a80f1106bf3c837b56725be96184508622211d0f3e6c1e7517792673733424c9b76d40077118027bb00f9433ab36b1671ffb22bf063fff65654ec70ddcc91684793d3bf415f99dbf800ac1146ca03efa9ea17ea4c823a02022fe27a3c019c3d70bb2f792ef62acb0805f40744e99c7821d1a38b2834ca984685de7ef2d954c6d287948d047778b2b77f4f0f64f96aa2b22827509f52d0310d0cdc0fcfcbe9e5e60484ec802b04c0b61300a5afe858ea931bab6e3642ee1ce3b2813225a05a213a47f9a9daf764c3497c84ce6f941f7b566dac172fc87e4aed563b49ce3fdb09144a6a2afccfbed4a9a586552063b05ca9a1a498ed2e5f022ed6026b389d377f301712868b69c96192410585baa96456772b79ee2b0afceb2bdd6dbf97abb2f3c39c34fa965f37738b6dd0632072bda1fbbe99db8f3fc0baa40000ff56bdb19df30a4f91d1f45e16e96c5993076d616f59e1ac712ed5b75112ae999a3c5621387b037d9ca9c0a912cdb57175f131c449b6a3491ed993a760bd7ee9b1104322f0e11bc680b473cff73c042dc5ffc129fde33e8d2d60be25bb12ef0aea7cdaaf84d6a9b0cad6d34438749dc183ef86f83707df0df39b243cd90d627e2c3ca9d3187f945a338709a24330b38adb68e6f69b817f00dacfc726ecf6ed056c01b4139b21a0fbbba77c278117d49a067c4265396acf8fbb14aef4f6f0c97188680e8636471f30aa0204fad8cb97ef4248bb7e4a4b760344a63a57ca9cfafbac066b688fed0bb4f993c961ff82ecf55774675da98d418e178ebaabd8de2b82f333a07f41870cb1dc1271477eb6a6435459e9a5375768902de350eb2ffa3830234e8c38688f7c9fb0bc1477e19d7739d44fb6e0e883eea7a023736295a85029e75e07427dd18afec5fb9ae0ec94d3e514f7cf126076b541696487ff8e623cd4671f91da5df08e988d13dc7e82d2196c939c400f7b573591d3c1abcd2aa2473ab8b434f43789e030323896f063f2322d588a37b1abc81446d0bc97166a6eb70681c7d83cb5cc34f73dae2a0c8652312717b6035eeb3749b56cbba6a0809fafc13bf907a2db631b3b76addff141b89ff265d900000000", .None}, + {.Shl, "-c9412402a4a668f2bfca7c4a9cd81707c35170472eb36c216c281f42f891f45d76a2598732199c2c8ed93be9a69c06bdcb506d2b841f9f2e2d2320500533894c5bf75ccf44f57f6000a2f4089ea21969a89e1f6e0b7cb71249eeb5d45396654a4a84a6b66b8560e859ba44c4860a3534c7f87807815dd24a4d9bcee0f56b6a7f491612494c5594b67a70d9edd755a6ae63e4cc4eb3c65a0f9bf35719a745faf52faefb0f03bec1453c1d86acd02fccfc6bc351832a9b0798da973d63f1f4789bb969aa834f9068e96abd05b7f8c91363ffe615dafd936a65de97cac057b18dffe7699fdcb43813be080db0df45f050ab410c95b8a68d73a3bbd58c6acdcbd9878ecda9fa3a41b62ea319c677ad8855f96095f3ca675973c8d0e010b99f99f513ae9fdfd096868d6e91ee87df598a4f5b9e875d357e2f2fdf64de38375970c2803d74c2c1c4d0df64a917502d8c78b8a4cd68cea09e70cfcc10821b661d22c3d3c8c02b4074c59e1bc6393904207a393e5eb970ab484fc2333465307aa7b214a68df6ba629ae129a39e94a8db5aea44286b42b8b4b332065129e00026aebf557b7cd91b18010fc898909e8af8ea1bf94203618a57ff3435241147a83e6a3e09b68f035040bd3e70b94b8dd26e069baa5619584df0d4c310b40ec4c4e2a8837b2e7f48fcb3b2639e854e1e631fc407359d75a5bc7fa4d83c6ecc0db7d9cd7b7ca351eba84936c5a2101814ee429fc50f8b790c40d24ba040c92ca5a3936cc967f05e59c5e88776e76e2c18b677a9e1cc17eadfd54fd5ce1433fc20b081bd0121e4729ca56c965c125588a67231c4bb797ab3979e644446f61f8a1647d4a0e51331108f2598514610ed229b7ed01f564c4db2d9473bf337ce74bb17ca927dba461b83b82ec0c98f7e5c7aa8094f64df8897fe70e48bcd671be7765003dd6c22df57b35578e98fdb879b3bfefc087f4d82b9cff71532e42df606855a4d0036a902643da73cd7088c5d7fa3720a242cc87db4b3a182e5845651983758c1dd9e6212db1ac999e2149132e29c5046626c5903c386cd124a400785f03b71e324f30fea402607e8133b5d443cf13fa5fa294b2049535b02a63aa20e118c9fac96ba79f1b04a35e7fee7dd66af61fc95e0e46d376348101208bd9403b2537f2e54629b88dcaeda9516c0ca394048019d34104c9e46d747d5dc6efd7d1e65e69db30785b7cfc6ee5d0e283baaa0a35ce2a270d330e76e9fcfb519c0dc269cc9f743be24f58dd57c8d64a5c5b35ddef82211348a17fca96c01de8985c2e3e06fbc333680633868c047e35c9fc83f59c2f0e5ea73dfa0056291f6aaceae56778b051216da29e0ceca16532afcc8af03e697e46eecf54b2723f719cf9d216e5ab22ea78fec24478a1a7c8e092e062549f9e82ac619679a96c1dc79fd5883e3795fd6ac6cf78d0ae2321bfbdced9bcf26cbae09a65a61bb4c97a1f41dbb3610d9fcc614a3572db58d02d519900d119ed725e677b11931e4407e20ec71e9c3bf0e272e259e210f4122363d7af8fc04e6ecb900aa46622f8525902f0ae233e46ffd45f05ba223120226e6795aeeb29e6d9a94550fc14ceeea5143bc5eb314b2a9dc52c767dd68709fc6d2cdd2bac23ef1d251524065c3d028ca6731bfad5236fcd0ee28328581266bc6b88eee09b39d22853e98da4a46a1ee948c9d235bf5bdf5bbd2b2adb6665ee2b53f06daf15cebabbc0a9d5da6e5ad3fe3e88155982eac76fb02435dbdca010c3dee5eb729342a433b7d81793db3e9e5c50526f4de32ac222111a85a6b49e5e3fcf8aab54852944153a17887b22a2828d01272e0a7c848ff875f9301fca904854c5afe3671dee6ce537af8cca2f024bd5ff7264416c985788c12a08d10f6ec8a302156d09529b782efb775c406e60a8ef496ebdf335253ec891d884d9989a4ed19ffce6e9d094fdfbebf0e49cdb8f4b72a8b1f244ef1131d6ff48a9aede9b4eeabb6a2fef354b6a8da24b3b5bb7efc707abb826d526bf920ac4452f6bf141427c434bbc6ddf0bd4ecb3d5888c7d5eb7ac467353d8f6e3fc025d0d46924ec870da2bdf560c3f1e2370b0c8385e339a2465a483c86e5c084ac8f4732bc", "26", "-32504900a9299a3caff29f12a73605c1f0d45c11cbacdb085b0a07d0be247d175da89661cc86670b23b64efa69a701af72d41b4ae107e7cb8b48c814014ce25316fdd733d13d5fd80028bd0227a8865a6a2787db82df2dc4927bad7514e5995292a129ad9ae1583a166e913121828d4d31fe1e01e05774929366f3b83d5ada9fd24584925315652d9e9c367b75d569ab98f93313acf19683e6fcd5c669d17ebd4bebbec3c0efb0514f0761ab340bf33f1af0d460caa6c1e636a5cf58fc7d1e26ee5a6aa0d3e41a3a5aaf416dfe3244d8fff98576bf64da9977a5f2b015ec637ff9da67f72d0e04ef82036c37d17c142ad043256e29a35ce8eef5631ab372f661e3b36a7e8e906d8ba8c6719deb62157e58257cf299d65cf23438042e67e67d44eba7f7f425a1a35ba47ba1f7d66293d6e7a1d74d5f8bcbf7d9378e0dd65c30a00f5d30b0713437d92a45d40b631e2e29335a33a8279c33f3042086d98748b0f4f2300ad01d316786f18e4e41081e8e4f97ae5c2ad213f08ccd194c1ea9ec8529a37dae98a6b84a68e7a52a36d6ba910a1ad0ae2d2ccc81944a780009abafd55edf3646c60043f2262427a2be3a86fe5080d86295ffcd0d490451ea0f9a8f826da3c0d4102f4f9c2e52e3749b81a6ea958656137c3530c42d03b13138aa20decb9fd23f2cec98e7a1538798c7f101cd675d696f1fe9360f1bb3036df6735edf28d47aea124db1688406053b90a7f143e2de43103492e810324b2968e4db3259fc1796717a21ddb9db8b062d9dea787305fab7f553f573850cff082c206f4048791ca7295b2597049562299c8c712ede5eace5e7991111bd87e28591f5283944cc4423c9661451843b48a6dfb407d593136cb651cefccdf39d2ec5f2a49f6e9186e0ee0bb03263df971eaa0253d937e225ff9c3922f359c6f9dd9400f75b08b7d5ecd55e3a63f6e1e6ceffbf021fd360ae73fdc54cb90b7d81a15693400daa40990f69cf35c223175fe8dc82890b321f6d2ce860b9611594660dd63077679884b6c6b2667885244cb8a71411989b1640f0e1b344929001e17c0edc78c93cc3fa900981fa04ced7510f3c4fe97e8a52c81254d6c0a98ea883846327eb25ae9e7c6c128d79ffb9f759abd87f2578391b4dd8d20404822f6500ec94dfcb9518a6e2372bb6a545b0328e501200674d04132791b5d1f5771bbf5f479979a76cc1e16df3f1bb97438a0eeaa828d738a89c34cc39dba7f3ed46703709a7327dd0ef893d63755f235929716cd777be08844d2285ff2a5b0077a26170b8f81bef0ccda018ce1a3011f8d727f20fd670bc397a9cf7e80158a47daab3ab959de2c14485b68a7833b28594cabf322bc0f9a5f91bbb3d52c9c8fdc673e7485b96ac8ba9e3fb0911e2869f23824b8189527e7a0ab18659e6a5b0771e7f5620f8de57f5ab1b3de342b88c86fef73b66f3c9b2eb826996986ed325e87d076ecd84367f318528d5cb6d6340b54664034467b5c9799dec464c79101f883b1c7a70efc389cb89678843d0488d8f5ebe3f0139bb2e402a91988be149640bc2b88cf91bff517c16e888c48089b99e56bbaca79b66a51543f0533bba9450ef17acc52caa7714b1d9f75a1c27f1b4b374aeb08fbc749454901970f40a3299cc6feb548dbf343b8a0ca160499af1ae23bb826ce748a14fa6369291a87ba5232748d6fd6f7d6ef4acab6d9997b8ad4fc1b6bc573aeaef02a75769b96b4ff8fa2055660bab1dbec090d76f7280430f7b97adca4d0a90cedf605e4f6cfa79714149bd378cab0888446a169ad27978ff3e2aad5214a51054e85e21ec8a8a0a34049cb829f2123fe1d7e4c07f2a41215316bf8d9c77b9b394debe3328bc092f57fdc99105b2615e2304a823443dbb228c0855b4254a6de0bbeddd7101b982a3bd25baf7ccd494fb224762136662693b467ff39ba74253f7efafc392736e3d2dcaa2c7c913bc44c75bfd22a6bb7a6d3baaeda8bfbcd52daa36892ced6edfbf1c1eaee09b549afe482b1114bdafc50509f10d2ef1b77c2f53b2cf562231f57adeb119cd4f63db8ff00974351a493b21c368af7d5830fc788dc2c320e178ce689196920f21b970212b23d1ccaf0000000000", .None}, + {.Shl, "-61c7d6ff8daa88d8ce4ceea29e07e99543b7459af93159992d79696ca3cba33641237e4f027b5e5aff80d3ad5b2a49a204b1b2ddc85450e191b8a2bb3d44e49509548c570e4090b5989282734a3678df7718a01fcbbce7b30573d5f55720bf77a7d96670f8d8353172160db0138125d191826e8c98ead0603aa9238ea4bb14b5159d8e213891a98829a031e96ac237b7732f601f29d8ff69a869a7d1dde238d0bf9aec1e4d4de07125529142f968e3d7ba01109c3b343a1d69e8d1529273526587174723ded79cd25a46de54e01845515e3593c57db763104b3ad2c54705e9b355b08fff0c40fe51b8f515a2a1e71b8ea6c3563fb63ac8501eff2b2ad40df8ee75f6876109a91aa19a4cce776ac148e2fddbf2c3aad23d8d8c5dad8eb08357d50705420d57042960bc3ce7b23718a0abff3d552c61be657229dbefd278cbddc01c54e384a5ca268ca16a8d5e3b5f0a34290c2608f4d058fc4f5143f93a13012442f48878bd90fc47eff77173e1b0f8e26fc07d91fb543c7e5b6a3b81eb80cb99f5183aa8c96be513b212de8e9dd6ce704759404f50ea741f03f92e9a8d51a070d7e4b3c5aae8e41b830ab00074d27d7f8f1a4d90dab3f8ea450084bea408e977718fe30a4c75a98568f00d83cb0026c263f7ebf8acc677add4c0d74e87e7166315b39090d3c0d680c6b0ab416138189dc913ccd8dc23316fba372a2dd85d4c516a321988834ea66123528e2f96e8901aab3be5b3224f4ff3a9e7c5b19fa05de4a61089f0999a7566ec80c17bd74ab7299fb5b40e8f051998e810d057a2ed77406ce3a154db06498ca658429c923a3ec06d426cab09105c54dbcc91f10995d2ced0443ebad6da4989c4ec892437afe145cc0999a2e6ac02a8ab6c3a116adfbf4e3efec010aad259a14fa236827968d3f7dac94ab810f5df8217919b94912ecf45c5352b0d896a30a74c89b5df94c83831d49a8976c23bfd23d2debd37dc904745c5663b20adedfb45971ff42358d4a55b4e665b9ff771869e19f1645bd27bfe421c908f9c3f5a3ff442688db8a934ec33f3b6dd75b1651af9ef9569cac62f6ce21a552215d88779ff92d5b9281dacd9becc7396728a18715c3888c6ef8de45600315faa83360454342fbf27d6bafee1bfba63cf50777be4dcafb75d34c0884cc8a97ebe3ee838e71c6bac688e893a1c188436ce169f6e7f1c4b3b3427566afd563f1a67705f8ef1add88f0a261a8384171e35dd7e65f54bf55e6b8592e1edecc42d443d18abafe046f328cf7f738cf03cce74c2ed9af79ff2596fa951adb29d1f560e6d784e9791582b29825c30b1786cc350a41a316d175941c8ac0e11233bca8a163205c6191b0c25b6299511db0c869f56804322d754f2ba4a2c690562195cb1dc65dee67328bc516a19f6230c034b582bebcadf6d5122d049c1f2a335d0a12b7747d1324aabf915085160f3e636198ecf5465fca45372c6087f4ace70b8f51285e8803f14b8cf9929ca80de5a7d031758dd24287eee7ddc80e868484d1d4c0c2427a145d9c716e9a5343495920a2e78c256cbad5c66a3058adc0cca9e620043cd74ce70200bd60215c5bab75835dec71429186d0fb22cd784f4bf8b927d54509fbce757c643ff743fb90f697c58ccd8da795401d09ce8572a0f3ef5e8d619abc9d032727d418f81ee490e19270aa97a2672591ad63a9e989aed84a9b6f3bed06d5d35e7ea87b4e60fd3bb73cc8a650eaa89ac73681971b35f99fa50090bcf0fc900c77d6576d4214216b6ff5f0bbe7858d70356f60136499c64399ba2352317eba4e47356db4064d00af6a6f9ca302167630d3b75ce5854a67f6bc1aea832ceb2daf3ada5296128cf0413b8784da31273df0ee3a11f33e816b62fd85ae3bcb6f26a6c8408539552e412c86b5fe5ae58f817c0fdac8e8fcf26ba826ad2dc2032bfe868202efa6f97e8651119d38f37de88e9fa8eb9081efc3f4adf1cfb6fc14e68c1c654af483694e5fd73993aad7056ab491aa3f9d1acac97dfe147aaae02f2e77ac8227ca3de6398a525ddd4b06c7f24a0fcf8572f9925598b78bac9e4bec94abb06f11791606d808686a8bba1ce607a435309a5f5b3cf004be1", "1a", "-1871f5bfe36aa23633933ba8a781fa6550edd166be4c56664b5e5a5b28f2e8cd9048df93c09ed796bfe034eb56ca9268812c6cb772151438646e28aecf51392542552315c390242d6624a09cd28d9e37ddc62807f2ef39ecc15cf57d55c82fdde9f6599c3e360d4c5c85836c04e0497464609ba3263ab4180eaa48e3a92ec52d456763884e246a620a680c7a5ab08deddccbd807ca763fda6a1a69f477788e342fe6bb079353781c4954a450be5a38f5ee8044270ecd0e875a7a3454a49cd49961c5d1c8f7b5e7349691b79538061154578d64f15f6dd8c412ceb4b151c17a6cd56c23ffc3103f946e3d4568a879c6e3a9b0d58fed8eb21407bfcacab5037e3b9d7da1d8426a46a86693339ddab05238bf76fcb0eab48f6363176b63ac20d5f541c1508355c10a582f0f39ec8dc6282affcf554b186f995c8a76fbf49e32f770071538e1297289a3285aa3578ed7c28d0a4309823d34163f13d450fe4e84c04910bd221e2f643f11fbfddc5cf86c3e389bf01f647ed50f1f96da8ee07ae032e67d460eaa325af944ec84b7a3a775b39c11d65013d43a9d07c0fe4ba6a354681c35f92cf16aba3906e0c2ac001d349f5fe3c6936436acfe3a9140212fa9023a5ddc63f8c2931d6a615a3c0360f2c009b098fdfafe2b319deb753035d3a1f9c598c56ce42434f035a031ac2ad0584e06277244f3363708cc5bee8dca8b761753145a8c866220d3a99848d4a38be5ba2406aacef96cc893d3fcea79f16c67e817792984227c26669d59bb20305ef5d2adca67ed6d03a3c146663a043415e8bb5dd01b38e85536c19263299610a7248e8fb01b509b2ac244171536f3247c426574b3b4110faeb5b69262713b22490debf85173026668b9ab00aa2adb0e845ab7efd38fbfb0042ab4966853e88da09e5a34fdf6b252ae043d77e085e466e5244bb3d1714d4ac3625a8c29d3226d77e5320e0c7526a25db08eff48f4b7af4df72411d171598ec82b7b7ed165c7fd08d6352956d39996e7fddc61a7867c5916f49eff90872423e70fd68ffd109a236e2a4d3b0cfcedb75d6c5946be7be55a72b18bdb38869548857621de7fe4b56e4a076b366fb31ce59ca2861c570e2231bbe37915800c57eaa0cd81150d0befc9f5aebfb86fee98f3d41ddef9372bedd74d302213322a5faf8fba0e39c71aeb1a23a24e8706210db385a7db9fc712cecd09d59abf558fc699dc17e3bc6b7623c28986a0e105c78d775f997d52fd579ae164b87b7b310b510f462aebf811bcca33dfdce33c0f339d30bb66bde7fc965bea546b6ca747d5839b5e13a5e4560aca60970c2c5e1b30d429068c5b45d650722b038448cef2a2858c81718646c3096d8a654476c321a7d5a010c8b5d53cae928b1a415886572c771977b99cca2f145a867d88c300d2d60afaf2b7db5448b412707ca8cd74284addd1f44c92aafe454214583cf98d8663b3d5197f2914dcb1821fd2b39c2e3d44a17a200fc52e33e64a72a037969f40c5d637490a1fbb9f77203a1a12134753030909e8517671c5ba694d0d2564828b9e3095b2eb5719a8c162b70332a7988010f35d339c0802f58085716eadd60d77b1c50a461b43ec8b35e13d2fe2e49f551427ef39d5f190ffdd0fee43da5f163336369e550074273a15ca83cfbd7a35866af2740c9c9f5063e07b92438649c2aa5e899c9646b58ea7a626bb612a6dbcefb41b574d79faa1ed3983f4eedcf3229943aaa26b1cda065c6cd7e67e940242f3c3f24031df595db5085085adbfd7c2ef9e1635c0d5bd804d9267190e66e88d48c5fae9391cd5b6d0193402bda9be728c0859d8c34edd739615299fdaf06baa0cb3acb6bceb694a584a33c104ee1e1368c49cf7c3b8e847ccfa05ad8bf616b8ef2dbc9a9b210214e554b904b21ad7f96b963e05f03f6b23a3f3c9aea09ab4b7080caffa1a080bbe9be5fa19444674e3cdf7a23a7ea3ae4207bf0fd2b7c73edbf0539a3071952bd20da5397f5ce64eab5c15aad246a8fe746b2b25f7f851eaab80bcb9deb2089f28f798e6294977752c1b1fc9283f3e15cbe6495662de2eb2792fb252aec1bc45e4581b6021a1aa2ee873981e90d4c2697d6cf3c012f84000000", .None}, + {.Shr_Signed, "-b8242e74162acd7b99d9b29fc88700f6bac8a192fc811c2ff7d3e4891203dd62c4f9210aa0b927c9a974d49a6ab7e861a03129c9288d83e05dcc47ed500ea1c3d02420d123607dae716410c223bf20cc1aa00d37d21f01db1c2212d91d64dbc4d5c719a1d9e5bfa4bb17762207714b79258d61b0a348ebd602b750eaf731579fed1b4c22732995cae0b93ec0e640445942914ee246564a0895db90f2de930a7220fb372bbc7f6ab11af37aa493960ac0bbaaac16894c4754a4255e91f9256ea409c828c5126573d4b41de1e64f318d6917faca96afd611ffb290fad319ebb16a05ec2159a6745bc9210c14afd6d03828807cf821d0edd1ac68ae789bee2e0a8463210447065e2b2785d762ca09b0284c9e219eec5ee3ec4cf0221e2a8790619641531b95178cf04dc249c067bd0fa9fa372cb1dcd860c274795d0074e38f8c40104b2ca0019b114e60f4f1cb34642d03e539b7cb087e7f11e8618e6e8dc255c34c8f651e9ec7de3fafea5496e0eaa8e4cb252ebed1b1721040f052add4fa95286b16df43494dfaea2628b5159594942a217f5244c0e184274e9300acc4e683a52de01b27311644f1a769555f1179ecca795f0b21a2eae6418bb7c01630a90bf6fffbc99e197a0cf15fa8d03946ebb3e98a7463ce9a31aa4fb914c4d3aa41bb6c96cb2aca09a6cfbaa2226fb375855c0f1c4647dce25ace855555bafde1f749795a651e9f92d130502089823f6ea4f39185e21db419190df342fdae9d2fc38b826cf4a55fb759057708a2a4d49887b4626111a4cac69f4a40823feffafd39df1fe5978a7d013e5c10179714f473584af464ce914aeeb8687ffafedb14cf499bfabbef470657074b3dbc26224c0296b93d1a6be30d5bd0a1f0339c6ded283a6149519050d79fcfb963b35152fcdc1a77e27c7597120d3d81eb1ab2f0f955a181ddb9ffa263a422340bfaa38109405d6c59794070ab7455e01afe9bc2e2c7505ae35e5550e3c2aa074d2e78d046ef7054c3e9bcb500b1862cb9091c9aed61baefebf05737879f91e93b87a6149bd840fe9ee9c70a679820261f25d4d7b121b33b459095fc8a4b6f13d07df00d639adebd6e1af97d92e843e04cd1256fe60b224a9cd970dcdc6899bc71b531d858364bf899def4943e90c651ddec7862ae4fd6862b5925ea185c05d3e625bcaeee44f0a5e9389e1b2794fca8e05c94af0735f5c5beac1f374af759aca228ed35d53928a746727f82c8cc08d01d9b4c4da65eeff732421684eb3c4d5fefb6cd73db99b432ac99ef069e0515e0ccdb3c3d24b94bb38ed1ce289cb3d709040410ffea86c1c59256d80025120299b4ee1460ee6ccdf2adc3d853a3fe92b850a5cbe5c3665e07af8203de016c334ceafaf2ee0b88a67c7369179d7f4e5a313ed9a8528c33e0980e5f3692dbde14ad27258ea9ee462156e9e09c99dbac1a93192777b906c21c485cc288a97a73297c0298894f0147bf2b1c0b94cb0707d311eaa0077052f252e6d711cf213409fb06a1f9ed9940b7fb719b5e14ed9906d3acb613402d26891fce2bd9a58994b489d984f0902f538f38d84557949ceacabab199bdfd8340ca49e6853a5838bb5a7304ea3c75fdcd582eaabcb10561dba2bd6cde8be01ae996bc128fe7a19f3f938ece8f6c1c6f02fe2d0cea0f81f446937c97fb69435990bed2bffab1e094414143ab15a85742d449f2e81d4a8fb29c9526acaed2b64c59948106278dfda37a10c4bc896f686804087a1020f33c5e647d0f7051dfc9cca073481ec040fee8d7857ac9825fe06b7f1de173f7bc72d4cb6d2c6a441080a219d5ffa3644f92812729e93b40f6f6abcbc40e4ffe13b0b2958d4072b277ce2ecacbe86bec44f46ca365465df148cce346f773b06ecf896f272efe10b8d107b0ed3e3be664a05f2ddb94e9b604a02709dc131d573b3b25e66abeae2d4402133fbe84e76caa253b319feae6b68a800fbaeef02aae56f2ebfd646d13663e1e0417a4d243db862a3059db2d318a014156d77869034697a981b7a40522f124fe743b4d64e2fec1c79b1c1e00287c427a9292e5583ff337935d6313daf36e7cc68462b02324f27108cc043b679c70cf438d1cf6", "6e", "-2e090b9d058ab35ee6766ca7f221c03daeb22864bf20470bfdf4f9224480f758b13e4842a82e49f26a5d35269aadfa18680c4a724a2360f8177311fb5403a870f409083448d81f6b9c59043088efc83306a8034df487c076c70884b6475936f13571c66876796fe92ec5dd8881dc52de4963586c28d23af580add43abdcc55e7fb46d3089cca6572b82e4fb03990111650a453b8919592822576e43cb7a4c29c883ecdcaef1fdaac46bcdea924e582b02eeaab05a25311d5290957a47e495ba902720a3144995cf52d07787993cc635a45feb2a5abf5847feca43eb4c67aec5a817b0856699d16f24843052bf5b40e0a201f3e08743b746b1a2b9e26fb8b82a118c84111c1978ac9e175d8b2826c0a13278867bb17b8fb133c08878aa1e418659054c6e545e33c1370927019ef43ea7e8dcb2c773618309d1e57401d38e3e3100412cb280066c453983d3c72cd190b40f94e6df2c21f9fc47a18639ba3709570d323d947a7b1f78febfa9525b83aaa3932c94bafb46c5c84103c14ab753ea54a1ac5b7d0d2537eba898a2d456565250a885fd49130386109d3a4c02b3139a0e94b7806c9cc45913c69da5557c45e7b329e57c2c868bab99062edf0058c2a42fdbffef267865e833c57ea340e51baecfa629d18f3a68c6a93ee453134ea906edb25b2cab28269b3eea8889becdd615703c71191f73896b3a155556ebf787dd25e569947a7e4b44c140822608fdba93ce46178876d0646437cd0bf6ba74bf0e2e09b3d2957edd6415dc228a9352621ed1898446932b1a7d290208ffbfebf4e77c7f965e29f404f970405e5c53d1cd612bd1933a452bbae1a1ffebfb6c533d266feaefbd1c195c1d2cf6f09889300a5ae4f469af8c356f4287c0ce71b7b4a0e985254641435e7f3ee58ecd454bf37069df89f1d65c4834f607ac6acbc3e556860776e7fe898e9088d02fea8e04250175b165e501c2add157806bfa6f0b8b1d416b8d7955438f0aa81d34b9e3411bbdc1530fa6f2d402c618b2e424726bb586ebbfafc15cde1e7e47a4ee1e98526f6103fa7ba71c299e6080987c97535ec486cced164257f2292dbc4f41f7c0358e6b7af5b86be5f64ba10f81334495bf982c892a7365c37371a266f1c6d4c76160d92fe2677bd250fa43194777b1e18ab93f5a18ad6497a86170174f9896f2bbb913c297a4e2786c9e53f2a3817252bc1cd7d716fab07cdd2bdd66b288a3b4d754e4a29d19c9fe0b23302340766d3136997bbfdcc9085a13acf1357fbedb35cf6e66d0cab267bc1a78145783336cf0f492e52ece3b4738a272cf5c24101043ffaa1b0716495b600094480a66d3b85183b9b337cab70f614e8ffa4ae142972f970d99781ebe080f7805b0cd33abebcbb82e2299f1cda45e75fd3968c4fb66a14a30cf8260397cda4b6f7852b49c963aa7b918855ba78272676eb06a4c649ddee41b087121730a22a5e9cca5f00a62253c051efcac702e532c1c1f4c47aa801dc14bc94b9b5c473c84d027ec1a87e7b66502dfedc66d7853b6641b4eb2d84d00b49a247f38af66962652d2276613c240bd4e3ce361155e5273ab2aeac666f7f60d0329279a14e960e2ed69cc13a8f1d7f73560baaaf2c415876e8af5b37a2f806ba65af04a3f9e867cfe4e3b3a3db071bc0bf8b433a83e07d11a4df25feda50d6642fb4affeac7825105050eac56a15d0b5127cba0752a3eca72549ab2bb4ad931665204189e37f68de84312f225bda1a01021e84083ccf17991f43dc1477f273281cd207b0103fba35e15eb26097f81adfc7785cfdef1cb532db4b1a9104202886757fe8d913e4a049ca7a4ed03dbdaaf2f10393ff84ec2ca563501cac9df38bb2b2fa1afb113d1b28d951977c523338d1bddcec1bb3e25bc9cbbf842e3441ec3b4f8ef9992817cb76e53a6d812809c27704c755cecec9799aafab8b510084cfefa139db2a894ecc67fab9ada2a003eebbbc0aab95bcbaff591b44d98f878105e93490f6e18a8c1676cb4c62805055b5de1a40d1a5ea606de90148bc493f9d0ed35938bfb071e6c707800a1f109ea4a4b9560ffccde4d758c4f6bcdb9f31a118ac08c94", .None}, + {.Shr_Signed, "-f2399f2999778aa99656b173687c8e522ea6bb26f1e3fa2315b5c8fd147262a080338f03c5b4fcefbf6309f53810f0e268e5ff74e3320eedfb68bfb714a3cfdac17c04e043b4257f9b500e579920290ad71f6fe4cf9c6fed4b4351dbf61326f37f222401ca30bd78297b036c1b71a6b95552299792a290b8bd9172365890fad645274fb30eed9219df7e10a66b63571fa31428280355d51bdd553d9fe148879fc932b894f617dc6d31a393eb47d3b98c0600f55dc93d75d81ed765e67e90abfbcf85894cd31ebfe4f8d1ad7e094a7d363b5123cc10c2ed19d487dfa459ecc32a05219eed1c4ac83ff30b432c9dbd1ecde9f4b2eaa26d8c866d7be76e33a4e3e7268b179f91add9bf07dec59c28d692507a273ad798a19355e78024148ae75e043d92660715bc36c15e3ed74b39e0058722b36167f96e9b6b82112b6f3e737eedd7d29ab51cc4b738b2fefac26049e7f65b1935621d3d4428de81d6d7156d2a10207c3967e0209b229a6359cba9767f6c62337067fd4872e8ecb99ca57e3119a8630ebcdf45526d587bfa474368be45c10dba4428ddead09769405b83e802db209575fd61b4d0ba0c69657e38a1c23de23d64c95b680008db9379a02f99b2b33118ee16e1b0b1a7cad8b4839d2c8bdf3033cef4484ff2d0c4d26bdd01fafc10753d07b4dc233f916f8ad6ad1fbd0693fce047fe85c6638dd1cbc6701dfec8557ebe08f2e346c3a4a97c68af38670535705fdd8ef6b2bb577b48b9e60dd96dd28bd2a43fe1327a879d87513bd289ce5cf3b079637503836647ad18ace00758bd2e0e444b53530180f59a583bea1a938b29acfc3b9a824eee56f1d4e9745acd4246a32a8f7b16bd6a070cbcab65c4f8cb6f89a67be4d793a3d615d849e01e98f9484e77eed54dd1d7ae574ab5713d569faf052a8c21b08b83314990819e538317b9dbb1f05e6e112de71dadda51691637d3486453ae85b061254419cbb858e004ead5ed8b5e90a29c59a5ccee0644417092d4cc7bb2a1a8bb05b13d56a7faa09c2599d33b43b2daedc3ebef25db9e696d4e5294c9db3dbcc093b1b4f8b6a487e8257e7b9ba190d114b08e7b318c9db23395da13f05a715ef92f51cb43f74eb1e0baa241bb156b09b999f28c385a27ac5a86f0e868825ac207f4851f0b4dd99a075a7e715de5ed58e85b621744fa591dd586ade2d9b1716e231cf4c904b53c9a7009020a0833e3ce529dc464e15288d0c02ed40925a99f687406f65f9fb033f3fe74a9b3429ed396949dc756bba8201c7475bf7eb48d9749d4913130dd695bd6453363d0ddc64f20342a116ace9621f95b19ad6b2fc27d580ceea45205b06a0deac739e2db58d1ce6a0f4afb940de70514e816b01e14a537af20df1649de339842f1cb64a2adbfcf28326d58cc110ff718ff53f5c5eaa3237a8fe67083d57c8788958783b801b70c6db2a4490f3aade47be966cf5f4eef4dcd4f75147faada6900731a3519a521e605484fe6ee243a7c0d151704e2029bdf26c0fb58fc76f10e8ee9ece65786b6430c867cbac403bc48cecda1c51630b9d3b73b0cf1255a651174fc44abd462fb908d6c2e9faccffe7144f365f8bc757216155ae848d1dd2a2f0d72a6070b6c6a1ae5ed12d60b3ca88036463f26300e4406498f0de8d9498926d2289b0113ae3faa169ef05de241571dcad379f4c6748ccc38a6a68fb43a12620cf8f532c3e679a468c402fefba0e9e90231c21c0cbb7d9c13f7b5599a68267e75e734c2d33673add6dcd6fba96c072634b763528334fc9b8d2b85c1da387d11076c82b1913db4e16bbc1fbb626fb6cdd3a5fea7b60c520483764e0c8d4dcacefa9d92ffafb618b434d548a220f6af05877a2ee9900814a752fc720aeb33fe7866a75a61403b7f8f48ed4d55ea35de73e45a97ca88f582d0b5a07fe065ff9c70b9c470eeb1ffbd3eb286f9221ddd880520b114810cc88f79b7fd2d2c95bc89a11da66df61136cfa953b72e2c9521dad07740a78f71d99a540ec6f463cec7451f433d646e9ced27186a674eddd830c9afbf22569444d6e1cfe8494cf13520d9a2eb8e2ec41f2091ceba9259bde08a8ccfe2196294489bd217278b18fd6c49", "0", "-f2399f2999778aa99656b173687c8e522ea6bb26f1e3fa2315b5c8fd147262a080338f03c5b4fcefbf6309f53810f0e268e5ff74e3320eedfb68bfb714a3cfdac17c04e043b4257f9b500e579920290ad71f6fe4cf9c6fed4b4351dbf61326f37f222401ca30bd78297b036c1b71a6b95552299792a290b8bd9172365890fad645274fb30eed9219df7e10a66b63571fa31428280355d51bdd553d9fe148879fc932b894f617dc6d31a393eb47d3b98c0600f55dc93d75d81ed765e67e90abfbcf85894cd31ebfe4f8d1ad7e094a7d363b5123cc10c2ed19d487dfa459ecc32a05219eed1c4ac83ff30b432c9dbd1ecde9f4b2eaa26d8c866d7be76e33a4e3e7268b179f91add9bf07dec59c28d692507a273ad798a19355e78024148ae75e043d92660715bc36c15e3ed74b39e0058722b36167f96e9b6b82112b6f3e737eedd7d29ab51cc4b738b2fefac26049e7f65b1935621d3d4428de81d6d7156d2a10207c3967e0209b229a6359cba9767f6c62337067fd4872e8ecb99ca57e3119a8630ebcdf45526d587bfa474368be45c10dba4428ddead09769405b83e802db209575fd61b4d0ba0c69657e38a1c23de23d64c95b680008db9379a02f99b2b33118ee16e1b0b1a7cad8b4839d2c8bdf3033cef4484ff2d0c4d26bdd01fafc10753d07b4dc233f916f8ad6ad1fbd0693fce047fe85c6638dd1cbc6701dfec8557ebe08f2e346c3a4a97c68af38670535705fdd8ef6b2bb577b48b9e60dd96dd28bd2a43fe1327a879d87513bd289ce5cf3b079637503836647ad18ace00758bd2e0e444b53530180f59a583bea1a938b29acfc3b9a824eee56f1d4e9745acd4246a32a8f7b16bd6a070cbcab65c4f8cb6f89a67be4d793a3d615d849e01e98f9484e77eed54dd1d7ae574ab5713d569faf052a8c21b08b83314990819e538317b9dbb1f05e6e112de71dadda51691637d3486453ae85b061254419cbb858e004ead5ed8b5e90a29c59a5ccee0644417092d4cc7bb2a1a8bb05b13d56a7faa09c2599d33b43b2daedc3ebef25db9e696d4e5294c9db3dbcc093b1b4f8b6a487e8257e7b9ba190d114b08e7b318c9db23395da13f05a715ef92f51cb43f74eb1e0baa241bb156b09b999f28c385a27ac5a86f0e868825ac207f4851f0b4dd99a075a7e715de5ed58e85b621744fa591dd586ade2d9b1716e231cf4c904b53c9a7009020a0833e3ce529dc464e15288d0c02ed40925a99f687406f65f9fb033f3fe74a9b3429ed396949dc756bba8201c7475bf7eb48d9749d4913130dd695bd6453363d0ddc64f20342a116ace9621f95b19ad6b2fc27d580ceea45205b06a0deac739e2db58d1ce6a0f4afb940de70514e816b01e14a537af20df1649de339842f1cb64a2adbfcf28326d58cc110ff718ff53f5c5eaa3237a8fe67083d57c8788958783b801b70c6db2a4490f3aade47be966cf5f4eef4dcd4f75147faada6900731a3519a521e605484fe6ee243a7c0d151704e2029bdf26c0fb58fc76f10e8ee9ece65786b6430c867cbac403bc48cecda1c51630b9d3b73b0cf1255a651174fc44abd462fb908d6c2e9faccffe7144f365f8bc757216155ae848d1dd2a2f0d72a6070b6c6a1ae5ed12d60b3ca88036463f26300e4406498f0de8d9498926d2289b0113ae3faa169ef05de241571dcad379f4c6748ccc38a6a68fb43a12620cf8f532c3e679a468c402fefba0e9e90231c21c0cbb7d9c13f7b5599a68267e75e734c2d33673add6dcd6fba96c072634b763528334fc9b8d2b85c1da387d11076c82b1913db4e16bbc1fbb626fb6cdd3a5fea7b60c520483764e0c8d4dcacefa9d92ffafb618b434d548a220f6af05877a2ee9900814a752fc720aeb33fe7866a75a61403b7f8f48ed4d55ea35de73e45a97ca88f582d0b5a07fe065ff9c70b9c470eeb1ffbd3eb286f9221ddd880520b114810cc88f79b7fd2d2c95bc89a11da66df61136cfa953b72e2c9521dad07740a78f71d99a540ec6f463cec7451f433d646e9ced27186a674eddd830c9afbf22569444d6e1cfe8494cf13520d9a2eb8e2ec41f2091ceba9259bde08a8ccfe2196294489bd217278b18fd6c49", .None}, + {.Shr_Signed, "-ecbc46227ec9d2a17921ef02ec6530b43d203988fbcea9cec512dc6a007ce10c4a63114a62518e8ad7f050bf10b99168be68a587f67bd88d89ad860e1737ba2b8440b9d7e58c0556bca0f0d85c18fda8d83d1960dbc6e014db640d1e42214d7e9c0e802f94b484c1161dcd9cb1f3556eac82af5f38ab86429131e6f96b3cc86b264f51efa06eb2a29819748c4c2b3512088bfc0063b8e342276d2fbb34bda16250353f9da628978a1fce5cb714c11792843f38d16fc1a76c9cb95692c5f1515c0338c8006aca7b18c0c25f57d1cd1784c56ef491c38a68017d4eb65dded5ab71d18affd2df5d075af68b1195db35b0b239e9cdf1608f7f9acb0313847e0ebbfa7e3020ce78b87de7077f12131080ac37fe0c05abbeb453d273712a98f65b46668cc08c53c41bb563f0bf7f722e08515dcc94187ded634d1eff0bc880863347a95a5da83e7fdba236ae774bf457b826a984ac7b853ea975094b0c62cf197cedbdc177ff217d8a955e97bf1920f069db81895ef2299a87bd0afa576d0df731e71f664c9eaeb62b2e3ee59be142ce08d6483a42344a89804c5cb59640b789f13f09365b10cb1c677984596680b87ef933522092378c789dea3cea5ce08f209a6675c4c8d580ceff2f236bca6454d595627dbcf27f2ed61a0ed72fb37068ac37845867bfd1554fb47501e023de588570a954930d39c04e6244523b539f58036dab644039ceaa4f872d766f1bf392fe1e8b3911f41edd7e365240ad958970053cbe24fe6156ec9d27c33ef02b01272efc57556bb952ead454d98b3eee76749bdc92ddad3a77e32b4229949e3aa5f084b8072c0165f43862f8d0ea3c9d335cbe92642ee62bc33c1b8bcb2e92e64dc5ca5e34cc3696b2501b18a8012a5dfe96b95f09c2ae8c0574b492308d7eaf485893a627d8e763d948c8a0844b00e4eef5f6be0b915ed0826a0481b5edf98a5fcf004ce1762769458a6e7fb40002e6457f33ded4293ca0e302b3ce299c2e806ef1aa1f2b840fa7155045158de7033ca7a59d5f6b985e536a605a1e1ae3b483d1e2171448027a8f06bda90d6e9aff6d926d5a11f845eec34dc17c6f24dd8806fafa91da6188abf30468091212b73e670ef06e01f24fedf1b5cf1b6d8fb47fcf65e3dfbde4b2a7f8fb4ff4ac9a03eb7cb2173ec00cfcd714ad7b4b61b44288036f89c138540e03ac898da7c66eb8b7adb7adef6d7a31d2ccb894f0f7598f5a5bc6409a57d1abe726cd013722e7b608b7bd3e1d769a39ce1ece45340a70497c36eff22194ab907bcf89c0916e24308b796758dc9f3971cdbb34d83c0acd7595a14c1408f901831820d7464a7a30bedc11f1a6aad402cd7dfeda39e564d8d843191e0f6abe26cd901917e96ac6f832c431a88cb22444014f6cb66f34cacd182268deacddf5dad66744d23b7e0af8ce2f8a76285d3a65f23a06e25e41b84322567bc41d0de37aed944c085e5278df8f095bc987b8587003903edc0023bb0fda716abc3efd8ef3692924285970935089757fd82093f389065c24899649bea5043528440b6dd237ced522f1b4c1cb288832cc579b72a2d06bd6eacda5bec1df9219971572965f3741d9f5d54fde6f3b65247ad9de681d06b1a8ff71f4c81e2461309aec4c0eaecbe1d1dbbbfc2882756958e2c570e5370d93fbea38f63629af772ac0925e0df0933e7e966ebac490e720ba01e4d3c27cb03f65af2b6b3b7694a49604f0a6b86b98ef2b669a7f9af19cd0307dc6926581ba768d2c20fd840a142ac5f0f86f77155b2b646e4680ef8fc16cb640e91375e03c27f234133b066cfd0e7d9d3dfa84a558982ef3ea22c41d9a9fa676f0849d27eaa84d4f1d87e7ce1ad8b6dab277c3f025b9eaae8a8245de582ec64e32e02dcedd730558c71a5110ac0357828ecc2fe958411a7df50aa8e69b9da8eced776ce5ee69534c6f31dffc71e00be484e79cbfc4557e1e0ac221aa50f81767959e7d3129369da9b5d2f0c2ef0f12177ee45314cbc7ab760053bab91ee1a4a189da0de491ca131b8a5fa5ab75b2af549bd004ab61312b327d7d3e42f3e6d2b6984b168b7b9a09fb64adb954e5d9e703ab40824f5b58b7fb49c3f74921754e8a3eeb", "15", "-765e23113f64e950bc90f7817632985a1e901cc47de754e762896e35003e7086253188a53128c7456bf8285f885cc8b45f3452c3fb3dec46c4d6c3070b9bdd15c2205cebf2c602ab5e50786c2e0c7ed46c1e8cb06de3700a6db2068f2110a6bf4e074017ca5a42608b0ee6ce58f9aab7564157af9c55c3214898f37cb59e64359327a8f7d03759514c0cba4626159a890445fe0031dc71a113b697dd9a5ed0b1281a9fced3144bc50fe72e5b8a608bc9421f9c68b7e0d3b64e5cab4962f8a8ae019c640035653d8c60612fabe8e68bc262b77a48e1c53400bea75b2eef6ad5b8e8c57fe96fae83ad7b4588caed9ad8591cf4e6f8b047bfcd658189c23f075dfd3f1810673c5c3ef383bf89098840561bff0602d5df5a29e939b8954c7b2da33346604629e20ddab1f85fbfb9170428aee64a0c3ef6b1a68f7f85e4404319a3d4ad2ed41f3fedd11b573ba5fa2bdc1354c2563dc29f54ba84a58631678cbe76dee0bbff90bec54aaf4bdf8c907834edc0c4af7914cd43de857d2bb686fb98f38fb3264f575b15971f72cdf0a167046b241d211a2544c0262e5acb205bc4f89f849b2d88658e33bcc22cb3405c3f7c99a910491bc63c4ef51e752e7047904d333ae2646ac0677f9791b5e5322a6acab13ede793f976b0d076b97d9b834561bc22c33dfe8aaa7da3a80f011ef2c42b854aa49869ce0273122291da9cfac01b6d5b2201ce75527c396bb378df9c97f0f459c88fa0f6ebf1b292056cac4b8029e5f127f30ab764e93e19f78158093977e2baab5dca9756a2a6cc59f773b3a4dee496ed69d3bf195a114ca4f1d52f8425c039600b2fa1c317c68751e4e99ae5f4932177315e19e0dc5e597497326e2e52f1a661b4b59280d8c5400952eff4b5caf84e1574602ba5a491846bf57a42c49d313ec73b1eca4645042258072777afb5f05c8af6841350240daf6fcc52fe7802670bb13b4a2c5373fda00017322bf99ef6a149e50718159e714ce17403778d50f95c207d38aa8228ac6f3819e53d2ceafb5cc2f29b5302d0f0d71da41e8f10b8a24013d47835ed486b74d7fb6c936ad08fc22f761a6e0be37926ec4037d7d48ed30c455f982340489095b9f3387783700f927f6f8dae78db6c7da3fe7b2f1efdef25953fc7da7fa564d01f5be590b9f60067e6b8a56bda5b0da214401b7c4e09c2a0701d644c6d3e3375c5bd6dbd6f7b6bd18e9665c4a787bacc7ad2de3204d2be8d5f39366809b9173db045bde9f0ebb4d1ce70f67229a053824be1b77f910ca55c83de7c4e048b7121845bcb3ac6e4f9cb8e6dd9a6c1e0566bacad0a60a047c80c18c106ba3253d185f6e08f8d3556a0166beff6d1cf2b26c6c218c8f07b55f1366c80c8bf4b5637c196218d44659122200a7b65b379a65668c11346f566efaed6b33a2691dbf057c6717c53b142e9d32f91d03712f20dc21912b3de20e86f1bd76ca26042f293c6fc784ade4c3dc2c3801c81f6e0011dd87ed38b55e1f7ec779b49492142cb849a844babfec1049f9c4832e1244cb24df52821a942205b6e91be76a9178da60e5944419662bcdb9516835eb7566d2df60efc90ccb8ab94b2f9ba0ecfaeaa7ef379db2923d6cef340e8358d47fb8fa640f1230984d7626075765f0e8edddfe14413ab4ac7162b8729b86c9fdf51c7b1b14d7bb9560492f06f8499f3f4b375d624873905d00f269e13e581fb2d795b59dbb4a524b0278535c35cc7795b34d3fcd78ce68183ee34932c0dd3b4696107ec2050a1562f87c37bb8aad95b237234077c7e0b65b207489baf01e13f91a099d83367e873ece9efd4252ac4c1779f511620ecd4fd33b78424e93f55426a78ec3f3e70d6c5b6d593be1f812dcf557454122ef2c176327197016e76eb982ac638d28885601abc1476617f4ac208d3efa8554734dced47676bbb672f734a9a63798effe38f005f24273ce5fe22abf0f056110d5287c0bb3cacf3e98949b4ed4dae978617787890bbf72298a65e3d5bb0029dd5c8f70d250c4ed06f248e5098dc52fd2d5bad957aa4de80255b09895993ebe9f2179f3695b4c258b45bdcd04fdb256dcaa72ecf381d5a04127adac5bfda4e1fba490baa75", .None}, + {.Shr_Signed, "3694d83615a1e5d33f3fb871033b5362e49e5183ba8a352c7260f31639427c8f5ab424befe4fea2b22b3bbe09c9baa3773c45eae13dbc59cbb77377b27bd517f3bea4bfc95a51f59c12d92c0a9d3439d6322ba7cd8f7fea5dde1d1440917a1f6bf2681135a4e867dcb1050efeb8958702f08e48eccd34a5681f0da112702063f47064b77055e8921f9e324170a7ad2e82ce7fbe351ad6347316dad04fff82f3f47b15a96b6869c2281577d17a3ac1c5ea1a9be0736a7989ba3cdb88fa6d133df6d8596e2ff2ed7c1d117f1d237a43a96e0c9091b37a1767d9cbab46c3f263727ded6bebd6b89529c9b39be3a83244fc8cb55c900123718a8112d9d153164c633fec05466f14bf776f51f2d240036ed3c2fb1e05be2ce15672580464f4e0ff4f651db71d90150ca876c4f140cb5309516d290d27b39da68b14aba51b5c3ff79803a893082e2911992afcc8d27b87bff1dfe382f28066a8013f2f2b2c487ce4e26020465bc7ea111fc5d7545dbf90f6cf88321ab8a906ad8443ac4da9a14aa77c65bb1d6bb24bfa7e4a5202d7d93ffa97a484b4ad236a4c5b892f93c97bf5a01424f6264db1cb86e5071d52cea829574839882895cf4b61455aedb8a035994f0e5f358d164d641abb8823b771005bedc431c8109c6dd79fa911beca65ebc4f46eb6acb3aab432f2766bff92acd8128c761012e73ad394ce13b014b369cc07861b8bd6e1ca080857c3c5fd2bb12ab67373e707134ce75e7ebf74f0cf6dc06fed95bd5ca0374f1dbfea1f9f2abef1203e8c6a0164d476bd7e6409b5a29e90b664cd5a1d9c4825ce334944f672b2847aea1b9195f88cf11d96831c8cdf700bb5fdbb57b3750b7fcb8b47ca5c8cfd8e85f0cd61963f1acf17df843e83bd998fba50536ad61dbcff78fc9b8374ddec57e243e2d0033688b21dd3ab55516714ebf4738a6bfee448f4c3288efd00209003b300ed6542eb229a6c48c8c94657dfccfa7ed83e33c1ce3e4f1cf93ac7db08cc821494191471542f570454f8fe4907142a350a8368535f37501a84b6ab922ff4984b923a39436f7745c7c37756f9de0471bd2dae5eaeb8b60c7131b41bd4172a01ecbde96196ca22064f0cb85d347af5c084b58bd23b4257372d9efc76b4e98e36d2174b8e35cccec0e5bc5c0bfc7fcd6f36d321f26a379922d7ba12564bb66be153897140486e01ac2c2b6e39b96319a4913c02828a5a4329f85b0c70d351cba0c89021ec9aeb2e6e0991888a425970da8bfd925949be9177bcfbcae4e65f2633780a1fde3740812c60862cc61e59bb688994624dfd066a60fec511631ca9938d4cb6427f561fcc3da3fefd47b9a81d4e5685c801e9466e4acbefba93977d8802aebd4d2ccc5fb1dd81713d98712be5500d646cafc18b1c859a8f14f221dc207543e93e65d9875ac590d45281c1e067bb4eb122eaa419190ca77e3c895e08fe065c2780bc7ff07ea814ecfb714d0121b8c1d54a1cb036d376f6ab698105f5e5fb617423a3ec569f3056a7e5b880d4660b90856e37812299501e77069716f29fe0e59d7b35abcbaa4fb9084afe2f99723339f3a2b26398fbb4a5bca46732bd73f171e8b8d831029f0c047d50ae1c443d59e510fb8963226a727df965eaf15b78985f2de641f0b0ba1e690f2fdc1e7a68005af10daa9fdb685ec7713cea42d1ba5571f8977947f320559e4c4ad67528323b8e3b211bd0c574d3eadf62a9e4e501339bfcb07376d8e7aba2b93c8c7b1baba679ee585c4160f3bb71b5b951684883332632ebd462f14516b10c33a836a46d9b7ef82ffb8c8bf996840bf3b75fd402c6c56286b1205bd7a2e6d3cbc36cd8d15ce1ccb749cbf6b66fd23508fc6738a2681ce581a75fb249a03b82f6d31baca27ae4ffcaf6cf12eb6da169d2ddefbb5bb6e3ac9f53d2aa26b629b40568b48ce2981023ef300108beee2e6d0749d04ef3d98910ff1e42c7b81066f166d066f12809980777c6365bf356939007b498cc6d0090e784d9186579657e3fc8d225ce6bd419aee262e06dafbe31087897ce92c35f7e46c1e59e44174ef48888a09e04b297e1835cd3a6191a816a5745e67fa95d871d19aa57399ca00d4502effa789a8", "6a", "da5360d85687974cfcfee1c40ced4d8b9279460eea28d4b1c983cc58e509f23d6ad092fbf93fa8ac8aceef82726ea8ddcf117ab84f6f1672eddcddec9ef545fcefa92ff256947d6704b64b02a74d0e758c8ae9f363dffa9777874510245e87dafc9a044d693a19f72c4143bfae2561c0bc23923b334d295a07c368449c0818fd1c192ddc157a2487e78c905c29eb4ba0b39fef8d46b58d1cc5b6b413ffe0bcfd1ec56a5ada1a708a055df45e8eb0717a86a6f81cda9e626e8f36e23e9b44cf7db6165b8bfcbb5f07445fc748de90ea5b8324246cde85d9f672ead1b0fc98dc9f7b5afaf5ae254a726ce6f8ea0c913f232d57240048dc62a044b67454c59318cffb01519bc52fdddbd47cb49000dbb4f0bec7816f8b38559c9601193d383fd3d9476dc76405432a1db13c5032d4c2545b4a4349ece769a2c52ae946d70ffde600ea24c20b8a44664abf32349ee1effc77f8e0bca019aa004fcbcacb121f393898081196f1fa8447f175d5176fe43db3e20c86ae2a41ab6110eb136a6852a9df196ec75aec92fe9f929480b5f64ffea5e9212d2b48da9316e24be4f25efd6805093d89936c72e1b941c754b3aa0a55d20e620a2573d2d85156bb6e280d6653c397cd6345935906aee208eddc4016fb710c7204271b75e7ea446fb2997af13d1badab2ceaad0cbc9d9affe4ab3604a31d8404b9ceb4e53384ec052cda7301e186e2f5b872820215f0f17f4aec4aad9cdcf9c1c4d339d79fafdd3c33db701bfb656f57280dd3c76ffa87e7caafbc480fa31a8059351daf5f99026d68a7a42d99335687671209738cd2513d9caca11eba86e4657e233c4765a0c72337dc02ed7f6ed5ecdd42dff2e2d1f297233f63a17c3358658fc6b3c5f7e10fa0ef6663ee9414dab5876f3fde3f26e0dd377b15f890f8b400cda22c8774ead55459c53afd1ce29affb9123d30ca23bf40082400ecc03b5950bac8a69b1232325195f7f33e9fb60f8cf0738f93c73e4eb1f6c23320852506451c550bd5c1153e3f9241c50a8d42a0da14d7cdd406a12daae48bfd2612e48e8e50dbddd171f0ddd5be77811c6f4b6b97abae2d831c4c6d06f505ca807b2f7a5865b2888193c32e174d1ebd70212d62f48ed095cdcb67bf1dad3a638db485d2e38d7333b0396f1702ff1ff35bcdb4c87c9a8de648b5ee849592ed9af854e25c50121b806b0b0adb8e6e58c669244f00a0a29690ca7e16c31c34d472e83224087b26bacb9b8264622290965c36a2ff6496526fa45def3ef2b93997c98cde0287f78dd0204b18218b3187966eda226518937f419a983fb14458c72a64e3532d909fd587f30f68ffbf51ee6a075395a172007a519b92b2fbeea4e5df6200abaf534b3317ec77605c4f661c4af95403591b2bf062c72166a3c53c8877081d50fa4f997661d6b1643514a0707819eed3ac48baa906464329df8f2257823f819709e02f1ffc1faa053b3edc5340486e307552872c0db4ddbdaada60417d797ed85d08e8fb15a7cc15a9f96e20351982e4215b8de048a654079dc1a5c5bca7f839675ecd6af2ea93ee4212bf8be65c8cce7ce8ac98e63eed296f2919ccaf5cfc5c7a2e360c40a7c3011f542b87110f5679443ee258c89a9c9f7e597abc56de2617cb79907c2c2e879a43cbf7079e9a0016bc436aa7f6da17b1dc4f3a90b46e955c7e25de51fcc815679312b59d4a0c8ee38ec846f4315d34fab7d8aa7939404ce6ff2c1cddb639eae8ae4f231ec6eae99e7b961710583ceedc6d6e545a1220ccc98cbaf518bc5145ac430cea0da91b66dfbe0bfee322fe65a102fcedd7f500b1b158a1ac4816f5e8b9b4f2f0db36345738732dd272fdad9bf48d423f19ce289a07396069d7ec92680ee0bdb4c6eb289eb93ff2bdb3c4badb685a74b77beed6edb8eb27d4f4aa89ad8a6d015a2d2338a60408fbcc00422fbb8b9b41d27413bcf662443fc790b1ee0419bc59b419bc4a026601ddf18d96fcd5a4e401ed26331b402439e13646195e595f8ff23489739af5066bb898b81b6bef8c421e25f3a4b0d7df91b079679105d3bd22222827812ca5f860d734e98646a05a95d1799fea5761c74", .None}, + {.Shr_Signed, "82804cbf3b788db760fa58b0ad6493e32d797f96511ebd9abfe5a0c79e3fe1235b112e49a0d7766555d392aae3fea814053badb9144a81c333aa5689098d8b0a1e4bcfb05fdc0961e3cdfa64d70908d0f60540fd8f58630808728a1c2b295ddd5fa2e9212d2f12465a83c55cd9f207b1622783519f8db565d86ba6e0d8a9029fab35c64c6302e0e3bad5041e1093826feb2a88f8a00e03f6450910f81c30aec912e2f7c5c04536c0eb552aab07b44e2c43191baea89f91026ad42575bbab257336350bc5d4a8dd430f6b9003339c67d5e737147aaa1262a0ef07e8172db21f96d5cb2fe592112f753640a40e57b23606a753eabe5bb414b9812dd649cf918476489cb077d86b386a36e9339cde118aff0d496614394e4423d6b7752a7a04facda6060f589dedfe34ffb288dfd75f561be429fcb74870707721d913c6bf1ae958197d2bb97afd734185092856e49560662ecc3a86292160e7a07b7151f1e6fbd81da4987e8d70671d6b0c355a1982d2161bcf153ad19558e0a1f73b714e2f293ec7878c1a9a47307ec9491e6dc51b4193d68a1afad17a9d9600fd7f9adad6d9162d8c95a42c506eab1b53a23a50ec96a0ae90e189b0b3308b68b4ddc5374a3afa52531d86e05a0831055a1cdee2f0d277aa09c0c6b7144d11a7c312fe447188a3154c60b9a32125113c964ea379a53c420d9175acca4e68aa8c4ddc58abda4ce1b14a734093a9488783b30c165c23498cd40113b2a3e024efb9787a34d9a601bc855a4f2d14dbd4ede991d061169a7f1d976083edea5ec8078df8f467e6b633281929253ceaedb66ea8bdd363323ee0e4d1df1806a106dc29396e8a4e51e249f8a828860ad43704cb62bfb987034884fd6b02ae4c98612b79ece04f902a0181e24167634486faa51860de031a948bddddceeb6383b8cf00634caee1e298004a1589ddf69de710839c15ba0afc91b8fdcbc7ba3d2ec987171b4acf9715c1f2d7c752ec4af0897bf9ce34b794ab3c5180f1af0b35b52b4436b3342940f66bcaaf765a28141f36ba69ab46f56aabb2630da19d43f01f1ae6c69960ffb66718330a5a7b7e85b9f3cf060f05444c9df1bcff95d1543bb2db089ba60737b322f0fd4a605c076dbae3c21cb71934dab5061b145ea59d6ccf19bab28b54037c9952fc9bef4a922f4fdddee818243f97c6c2b543fa47293561a6ea84081f86d426c9b0b40b5a4e8cc885f4493165a1e7804d97ea60b3aa53a606927741be9bbe1695b7f535969e58d2601b9164007b7ef358469a8ca10366f283ce9b4ad79db48725162d5d774f3dae2264ee576bb2225c9e126f0edb8d716dfc199e42e4fe9eea401673dca57371c67e7ccc47d9da4453e370bdebcce5042e7d3041109a19b0934d7a98172580ab09197c20442ead13a66babb794c9219fe40be81fc2744f8e8db1fea274953a3d44181fd1483db0d975da253d9fe7712147a6b7b4a758b5192a59280e68b7ce3e617c95589b29f79cd02e665f4493102878d711c66026a22d66a83788f3a5558369313157536805492e42c2100b191842f89986e3a98746eaa27d94dbcd4e1d4d0cdcb2ae5e4032452a157795f100aaaa696398ce1f5b7d62ff10c504e5c6abb766e45ed92e8166d46af961c17755264edfc6f1435e3ae58382dbac3158b980e6490b6bdec334aa18cf1471b131ab765a416ab935d7398a3d9b99ffc7581549584d22ecbfcb2a14d4e4c73e4bb28751cc561811df86a6b38151f84fe77571e6f0bf0528800519e761551d3d1ef8bae6c255cf43529d5bf6c3b4b287ac35e9500ad6758a00e1b083c90c6b8fb63a2c106c63e41b5ce576ffe7a048492a99d568dbdeeff517bd4de4c25de729aca062b357d50002c3406cf06869059ee132d8557aabadc0da3335ffc7628f5e67b5ee865afd4347558450dd707b5686363884e62c92899f535e5507dd21af3b10b3c3603b0696788292be2714c4017390c635631fbb262cdd92acdfbff59944df0468f86d8f2fe7acba8d0416f73803292098c3b0d217625997a118450c6879ada7de347682fc61597e4e01a659499d59b00c82daac58d705fd335d2bf6446c1332a460c757a3c34b7a0ff9817b", "6c", "82804cbf3b788db760fa58b0ad6493e32d797f96511ebd9abfe5a0c79e3fe1235b112e49a0d7766555d392aae3fea814053badb9144a81c333aa5689098d8b0a1e4bcfb05fdc0961e3cdfa64d70908d0f60540fd8f58630808728a1c2b295ddd5fa2e9212d2f12465a83c55cd9f207b1622783519f8db565d86ba6e0d8a9029fab35c64c6302e0e3bad5041e1093826feb2a88f8a00e03f6450910f81c30aec912e2f7c5c04536c0eb552aab07b44e2c43191baea89f91026ad42575bbab257336350bc5d4a8dd430f6b9003339c67d5e737147aaa1262a0ef07e8172db21f96d5cb2fe592112f753640a40e57b23606a753eabe5bb414b9812dd649cf918476489cb077d86b386a36e9339cde118aff0d496614394e4423d6b7752a7a04facda6060f589dedfe34ffb288dfd75f561be429fcb74870707721d913c6bf1ae958197d2bb97afd734185092856e49560662ecc3a86292160e7a07b7151f1e6fbd81da4987e8d70671d6b0c355a1982d2161bcf153ad19558e0a1f73b714e2f293ec7878c1a9a47307ec9491e6dc51b4193d68a1afad17a9d9600fd7f9adad6d9162d8c95a42c506eab1b53a23a50ec96a0ae90e189b0b3308b68b4ddc5374a3afa52531d86e05a0831055a1cdee2f0d277aa09c0c6b7144d11a7c312fe447188a3154c60b9a32125113c964ea379a53c420d9175acca4e68aa8c4ddc58abda4ce1b14a734093a9488783b30c165c23498cd40113b2a3e024efb9787a34d9a601bc855a4f2d14dbd4ede991d061169a7f1d976083edea5ec8078df8f467e6b633281929253ceaedb66ea8bdd363323ee0e4d1df1806a106dc29396e8a4e51e249f8a828860ad43704cb62bfb987034884fd6b02ae4c98612b79ece04f902a0181e24167634486faa51860de031a948bddddceeb6383b8cf00634caee1e298004a1589ddf69de710839c15ba0afc91b8fdcbc7ba3d2ec987171b4acf9715c1f2d7c752ec4af0897bf9ce34b794ab3c5180f1af0b35b52b4436b3342940f66bcaaf765a28141f36ba69ab46f56aabb2630da19d43f01f1ae6c69960ffb66718330a5a7b7e85b9f3cf060f05444c9df1bcff95d1543bb2db089ba60737b322f0fd4a605c076dbae3c21cb71934dab5061b145ea59d6ccf19bab28b54037c9952fc9bef4a922f4fdddee818243f97c6c2b543fa47293561a6ea84081f86d426c9b0b40b5a4e8cc885f4493165a1e7804d97ea60b3aa53a606927741be9bbe1695b7f535969e58d2601b9164007b7ef358469a8ca10366f283ce9b4ad79db48725162d5d774f3dae2264ee576bb2225c9e126f0edb8d716dfc199e42e4fe9eea401673dca57371c67e7ccc47d9da4453e370bdebcce5042e7d3041109a19b0934d7a98172580ab09197c20442ead13a66babb794c9219fe40be81fc2744f8e8db1fea274953a3d44181fd1483db0d975da253d9fe7712147a6b7b4a758b5192a59280e68b7ce3e617c95589b29f79cd02e665f4493102878d711c66026a22d66a83788f3a5558369313157536805492e42c2100b191842f89986e3a98746eaa27d94dbcd4e1d4d0cdcb2ae5e4032452a157795f100aaaa696398ce1f5b7d62ff10c504e5c6abb766e45ed92e8166d46af961c17755264edfc6f1435e3ae58382dbac3158b980e6490b6bdec334aa18cf1471b131ab765a416ab935d7398a3d9b99ffc7581549584d22ecbfcb2a14d4e4c73e4bb28751cc561811df86a6b38151f84fe77571e6f0bf0528800519e761551d3d1ef8bae6c255cf43529d5bf6c3b4b287ac35e9500ad6758a00e1b083c90c6b8fb63a2c106c63e41b5ce576ffe7a048492a99d568dbdeeff517bd4de4c25de729aca062b357d50002c3406cf06869059ee132d8557aabadc0da3335ffc7628f5e67b5ee865afd4347558450dd707b5686363884e62c92899f535e5507dd21af3b10b3c3603b0696788292be2714c4017390c635631fbb262cdd92acdfbff59944df0468f86d8f2fe7acba8d0416f73803292098c3b0d217625997a118450c6879ada7de347682fc61597e4e01a659499d59b00c82daac58d705fd335d2bf6446c1", .None}, + {.Shr_Signed, "-ad9f5fa0460cbd66d6eecc3653feeba6da1ad1f35be98ff0645e427931e2c9f57cd5d9088f554ee5ad08426152ced448553a7a46fc54c24c91a31724adf3c0401b2bc226ea9288632a803eade08640876adcd16119f2a31d3dc4c30b2053994b6cd5c3331389888bba413ba28c37d552dcafdc5cc8b5a8cd1582de02e5f3f786782caefc09d89e0771c30d4905c3b43a85fa5ad292fa2385ffccd96e07fcd435bcbdee096a4157cdf87a64a8d046b62ca9ba454382d77c19ee5c95caa9481e7aab2ed4f9964bae38f860cae4b00d928dd16942490cd41dcb4ac23e143f77a853dab488bde47fcd4bb43ffb0f79f0c85bb5941318d9cbda55210017e7c5eb9535e164bd6f79a789eccb2f12b253eb44f9b231619909b7243a8989690611cdc78622b5be390c09f7bb3284035d55fb5b81b99b11ea4aa9605f5dca7d1fc5ca87f4153649377f5f7e01bb6a8ff93172e7240a9dcfce338b6d62e3adc80159ba50fafdf18fbdab3539b01a3ba23a2ca978b02edd14809ecfc117fb342b6d2de19e07d0cf6683bc43a7d0ee1538fca6b4dee49e8f1e73c77de130cb64c6accacd259c839477659d893da1bb293c073a770a48c14fa762253705809853ee777c7bf5a35bcd2fff8009868e63cd011781fae1aa82306bd189be07d0fe67526f45ee6d77516d5fafe20fb40c13ecb5d7b38f7d2ae6910c1727f2698e4a86ac9947b986dbaee7814cb23700605986278e229160e213c6aea91db068f2c1a9f6a1f9f34ceb6679c68571a9ba5984c5b0f1034355533e12a79fa30fb2ea7ac127759b84f9c859d7e7e0e626419a04c3d4741d574668509332cb19096c816785e75f7ccee0653e0e5814820fd4be32717d2ee0e1db7bcd609515b42151dce1332182ba68a497c5ca7257aa44aef681b36ca40d9089768a62d2ed27578f61ec96e15c2d7807c7c0fcd4031cc97aab3e79b1248265b366ce85049d854a10fd1de08b0a7ca6842d18bfcccf15e19c00e39540dfb2b4206a14c5af7ae3aa812aef11eaafa224c306959b9b0d538db843ee69eaad9c55e083db70d5cfb4472cd8c098107b164fcec54d12eaa25592c8398f8006602491acd56c15cf22f59b2921832a5ff379d99401a16c54edc41c639690dd17c5fd87f184849308f28aa35e2dd120bc9a550f9a6a94c5d7eba113be46f3d07464f0db78dd09b144eaefbf6d7169e03febdd00c76feb4b59f05ab77c5a9785a3bc362a87afb82dc5f7aeeecd35b1651fcb5d50da59c3cc66eac3998d977129415a4a71298c19471a9ec1582046ec977c11bad874a622ad223b9c1d193d15130aac3d95ab8cfdcad239a45433c98002b7b64331e5c8c0e8968a21a93396580259d263a88570aaa459412ae90a3463e8ec24bde3569f5ea1b4b816b7c793f82073f0febbd6d61438e182ddf573b97232fea6bc82822af45109d87f0c2311ec786ca2a3558977c32830ab80732107dc8cab7d77a6da0f0e7544ff31e341ff1be45c966292242b48510d493cb121608130ee97c27540c4d6e0acf93b652b01d3321a305394bffb2ea2f244b2140e2365ef187a2b761e2106af354f9ec0b4b9bb41080c416ba540a9cd15858a4d1cbe50d9e517c3abbea8e6ec3addbe755fd62fd1ce204785c93a6aedfd903ed9428c379888283d1abe41fc1cf2e70ad6f76aaac74400b9bdbd2c37187ef2cde61d5d4328968ef774e1e08484aeae654bdda234c65d6c1e8ce5ed4fc34182f32e0cc160f331d6b3596e295efbe8530c1c754aa6410af70b7dfc850cb98dd545d4f9350e3bf54b21f6d5fd7cec4216a43c001cec51115a7e663e7fa14130f69e5ec484f6fa482d7771d64fb3524620a7a40e8dbe92d2cd8b7b7e79693938fe109bfb6b8c1b48ef3731dc587a6b893998303bf142b04a02cf4cf415529e40da43b69e9c2af60a4df270eb36e432f2cd09bf35e48b6f0aa98a19083a0527c4a5e06b0cbcd2a943eeb0ff575cb313d2465118cb1eebd28b499c5f904f0d5798fffde775bcc29ff6e562504ec3644d661ff4674b46bf53ead8ef901a32de8653ae69611ba9d91dd0034eb5a9efafddac5a92141fc10e0dc5ddc7587b112e6ebe1acc3f3d8628b60487", "47", "-15b3ebf408c197acdaddd986ca7fdd74db435a3e6b7d31fe0c8bc84f263c593eaf9abb2111eaa9dcb5a1084c2a59da890aa74f48df8a9849923462e495be780803657844dd52510c655007d5bc10c810ed5b9a2c233e5463a7b89861640a73296d9ab86662713111774827745186faaa5b95fb8b9916b519a2b05bc05cbe7ef0cf0595df813b13c0ee3861a920b8768750bf4b5a525f4470bff99b2dc0ff9a86b797bdc12d482af9bf0f4c951a08d6c5953748a8705aef833dcb92b9552903cf5565da9f32c975c71f0c195c9601b251ba2d2849219a83b9695847c287eef50a7b569117bc8ff9a97687ff61ef3e190b76b282631b397b4aa42002fcf8bd72a6bc2c97adef34f13d9965e2564a7d689f36462c332136e48751312d20c239b8f0c456b7c721813ef76650806baabf6b703733623d49552c0bebb94fa3f8b950fe82a6c926efebefc0376d51ff262e5ce48153b9f9c6716dac5c75b9002b374a1f5fbe31f7b566a7360347744745952f1605dba29013d9f822ff66856da5bc33c0fa19ecd0778874fa1dc2a71f94d69bdc93d1e3ce78efbc26196c98d59959a4b390728eecb3b127b437652780e74ee1491829f4ec44a6e0b0130a7dceef8f7eb46b79a5fff00130d1cc79a022f03f5c3550460d7a3137c0fa1fccea4de8bdcdaeea2dabf5fc41f681827d96baf671efa55cd22182e4fe4d31c950d59328f730db75dcf0299646e00c0b30c4f1c4522c1c4278d5d523b60d1e58353ed43f3e699d6ccf38d0ae35374b3098b61e20686aaa67c254f3f461f65d4f5824eeb3709f390b3afcfc1cc4c83340987a8e83aae8cd0a12665963212d902cf0bcebef99dc0ca7c1cb029041fa97c64e2fa5dc1c3b6f79ac12a2b6842a3b9c266430574d1492f8b94e4af54895ded0366d9481b2112ed14c5a5da4eaf1ec3d92dc2b85af00f8f81f9a8063992f5567cf3624904cb66cd9d0a093b0a9421fa3bc11614f94d085a317f999e2bc33801c72a81bf656840d4298b5ef5c7550255de23d55f4449860d2b37361aa71b7087dcd3d55b38abc107b6e1ab9f688e59b1813020f62c9f9d8a9a25d544ab2590731f000cc0492359aad82b9e45eb3652430654bfe6f3b3280342d8a9db8838c72d21ba2f8bfb0fe309092611e51546bc5ba2417934aa1f34d5298bafd742277c8de7a0e8c9e1b6f1ba136289d5df7edae2d3c07fd7ba018edfd696b3e0b56ef8b52f0b47786c550f5f705b8bef5ddd9a6b62ca3f96baa1b4b38798cdd587331b2ee25282b494e25318328e353d82b0408dd92ef82375b0e94c455a4477383a327a2a2615587b2b5719fb95a47348a8679300056f6c8663cb9181d12d144352672cb004b3a4c7510ae15548b28255d21468c7d1d8497bc6ad3ebd4369702d6f8f27f040e7e1fd77adac2871c305bbeae772e465fd4d79050455e8a213b0fe184623d8f0d94546ab12ef8650615700e6420fb91956faef4db41e1cea89fe63c683fe37c8b92cc524485690a21a92796242c10261dd2f84ea8189adc159f276ca5603a6643460a7297ff65d45e48964281c46cbde30f456ec3c420d5e6a9f3d8169737682101882d74a81539a2b0b149a397ca1b3ca2f87577d51cdd875bb7ceabfac5fa39c408f0b9274d5dbfb207db285186f3110507a357c83f839e5ce15adeed5558e8801737b7a586e30fde59bcc3aba86512d1deee9c3c109095d5cca97bb44698cbad83d19cbda9f868305e65c1982c1e663ad66b2dc52bdf7d0a61838ea954c8215ee16fbf90a19731baa8ba9f26a1c77ea9643edabfaf9d8842d48780039d8a222b4fccc7cff428261ed3cbd8909edf4905aeee3ac9f66a48c414f481d1b7d25a59b16f6fcf2d27271fc2137f6d7183691de6e63b8b0f4d71273306077e2856094059e99e82aa53c81b4876d3d3855ec149be4e1d66dc865e59a137e6bc916de1553143210740a4f894bc0d61979a55287dd61feaeb96627a48ca231963dd7a5169338bf209e1aaf31fffbceeb79853fedcac4a09d86c89acc3fe8ce968d7ea7d5b1df203465bd0ca75cd2c23753b23ba0069d6b53df5fbb58b524283f821c1b8bbb8eb0f6225cdd7d", .None}, + {.Shr_Signed, "-bc1f522327896aaf5113bd9d08349c6a563d8ea6afc05be52ea59a77cddbdb390f34923ca3d92235a5aadbafcd75db160d36be0403b17f5c4bf83235f2f3124fddeb1308403dee0cb7b942f2b561fc281391e751e5abb4309d0ece019fd8c6ba8930bd4ad2d459f987c3cb8606ce41ac00a3f518fded1d113486ccdd5b1eb4b7aa50bbb26bc8a2969127fc38e4e3d6716c5dfd3919efeda9236656cb878c3fa2161510023e33f7ffb13cf7b06ea0ed74e9b9444f317c927673c0bf7ec5ebd736beff7924027ee2207454071ffd2a894e49f5659b7b92c9a2dea3042c471ddd08bb5984eb3d2bd5b77c07a74c5c698b78b8d5134a85a16d8b464e2622704ef3e212f4b11282260a25dcac66bf1c6e539c601a3b3fd3a37d95e68296a47b4729cbe5d9a7c783ef627f68cf2136c41ead8bdc6c59e87d04a60846468e192eb38913c93fbbf6fdd8db95271f67867547c2d7be5060d52603cbe901e82a1295e4a1f55f10591c11447e0ed71b70aebf5fb9588bbe825fbdcb3e80cc561de73a75cf04807409dad73fb0e759488a8586ca747df792cc95c1cfd9aed28cb6dee4099089abfa15d46c9400b525d15e2d9947ed8d5974d3ca97bcabf072adc5f174ab825017d2f10a65c8cf1471aca4b603efeca43b1957e8e0375a39dd5c0b5a5a5f7abb574362f78338e1c4d0313a44c994adcc786ab2546b8fe349d326eaf0c8879002b8626a6edbadc26ac68d8e9441a2845da03acf781d4f40531e24a636dade26b45658c3e1563088e2ea063e54954d77235b25b291076f4e01e8cb0ad24bb725ebae7fe1acccd1a951462b8b01f65a3d1838aa6c6e49925d67feba3a47fdd4cddbe09449dc461f5a5f41d071a532c257880f9ff846809591949bf50aeb5184d90015ed0e7641b32ba497271a1abc3ceaae3e73cb2460bee235950dd3c238ebf9e20f2b4d7243b71d37fefc063f2eaddb3950c62c46ae02fe55cac619f9d1d34dd428cc57b1bede777a8f8d485766c5a7a19b55ade0b1d1933f5ffe8d35c466b4da2047f4b46684791c7d5b16406536b8a0f4c917a6cc587d6d22535172244f147d50eea6c76209ea15fc65d3263c113c06e2d43e60168be5c711a56bbf5b0d5a76f0e8077349729a285aeda1db7b2f2c1bdf4b418c3a0043a3abbde74e2f840d20509c81622d380c04e0f1654efb37ef132b348bbe1acfc3881ec198cf2ed0485a18af203b743768071fa3757cffb15ec159e1071a446c97d5a1a78d1b67b6af7693c6b56520363f81f7e2dc92fe76afdb2ac722109e3e1457949714d22f88b2a07468cfa0534b4c1229d0ace629b57243f2bef8c6102a84093b67130e180dd59b3ddcf4f74f78dccd990a5655d807d79797f79e8f3037b3065e2b34b801b0520d08d97b2d947e22893491b72ca939f21af28f7192a82f0beaa21324287f872d091bd56404d22ea6ebd77995d4111dc045710b3c269a4bd7d31dd8b7d0a29b020f14c1ae982590b702d4d83895d0d2eed089916d3e9c91f8aae12fc19d7aaa4119963f948beafbf511eda71f0248ced06d6fae85881834b098a5be00b54f272ce6e7a2085d5b5764038173e5bc7976eecada06aace885916902cf891dfb042f1ff34410a00e49371e49c9b4001d72250395a0d209a8c2149e013c35245034c07a8e5059e5165cf122a3519a94b8f353bc6d81483a2bf78470af9ef386ecfd087ea2a9cfbc47e00c20436f7e185b6b543ec30fb1e915a44f95f72a6d83b2c3d86e381da239e9e017d9142518f4ca2b73bc916ff647f371e9d82582b02c67b5c2d733dd1e89ef4778498e4d092717389c69a32467e173d0096c55b0c5bad5ac98f0e3d55c4b340ed8018179fdc5cb79918668dc11ebc50ebf6a23b06f97555936e83496f2213e5bfc9cfff16731b377965c738b26c87757f17e94df874e8d5e832647ac46610cb3ffeabce676a06d258e3891a11d4953a7951e407310a9c8929eb3c1b88504f28ec2d4a0b8f64063709fa9c6786eea0439a00150ca691d0ab66aacf86dc2b6ca1da0ff8c16bda372e5a535166216c1a83c1c8784a64922cf90b2bf57a898053f5d12259b1eedbddf8157ea9572d3f561a49d8f315969bcc", "55", "-5e0fa91193c4b557a889dece841a4e352b1ec75357e02df29752cd3be6eded9c879a491e51ec911ad2d56dd7e6baed8b069b5f0201d8bfae25fc191af9798927eef58984201ef7065bdca1795ab0fe1409c8f3a8f2d5da184e876700cfec635d44985ea5696a2cfcc3e1e5c3036720d60051fa8c7ef68e889a43666ead8f5a5bd5285dd935e4514b4893fe1c7271eb38b62efe9c8cf7f6d491b32b65c3c61fd10b0a88011f19fbffd89e7bd8375076ba74dca22798be493b39e05fbf62f5eb9b5f7fbc92013f71103a2a038ffe9544a724fab2cdbdc964d16f518216238eee845dacc2759e95eadbbe03d3a62e34c5bc5c6a89a542d0b6c5a3271311382779f1097a588941130512ee56335f8e3729ce300d1d9fe9d1becaf3414b523da394e5f2ecd3e3c1f7b13fb467909b620f56c5ee362cf43e8253042323470c9759c489e49fddfb7eec6dca938fb3c33aa3e16bdf28306a9301e5f480f415094af250faaf882c8e08a23f076b8db8575fafdcac45df412fdee59f40662b0ef39d3ae782403a04ed6b9fd873aca44542c3653a3efbc9664ae0e7ecd769465b6f7204c844d5fd0aea364a005a92e8af16cca3f6c6acba69e54bde55f83956e2f8ba55c1280be9788532e4678a38d6525b01f7f6521d8cabf4701bad1ceeae05ad2d2fbd5daba1b17bc19c70e268189d2264ca56e63c35592a35c7f1a4e99375786443c8015c3135376dd6e1356346c74a20d1422ed01d67bc0ea7a0298f12531b6d6f135a2b2c61f0ab18447175031f2a4aa6bb91ad92d94883b7a700f465856925db92f5d73ff0d66668d4a8a315c580fb2d1e8c1c55363724c92eb3ff5d1d23feea66edf04a24ee230fad2fa0e838d299612bc407cffc23404ac8ca4dfa8575a8c26c800af6873b20d995d24b938d0d5e1e75571f39e592305f711aca86e9e11c75fcf10795a6b921db8e9bff7e031f9756ed9ca863162357017f2ae5630cfce8e9a6ea14662bd8df6f3bbd47c6a42bb362d3d0cdaad6f058e8c99fafff469ae2335a6d1023fa5a33423c8e3ead8b20329b5c507a648bd3662c3eb69129a8b912278a3ea8775363b104f50afe32e9931e089e03716a1f300b45f2e388d2b5dfad86ad3b787403b9a4b94d142d76d0edbd97960defa5a0c61d0021d1d5def3a717c20690284e40b1169c06027078b2a77d9bf789959a45df0d67e1c40f60cc679768242d0c57901dba1bb4038fd1babe7fd8af60acf0838d22364bead0d3c68db3db57bb49e35ab2901b1fc0fbf16e497f3b57ed956391084f1f0a2bca4b8a6917c459503a3467d029a5a60914e8567314dab921f95f7c63081542049db389870c06eacd9eee7a7ba7bc6e66cc852b2aec03ebcbcbfbcf47981bd9832f159a5c00d82906846cbd96ca3f11449a48db96549cf90d7947b8c9541785f5510992143fc396848deab20269175375ebbccaea088ee022b8859e134d25ebe98eec5be8514d81078a60d74c12c85b816a6c1c4ae869776844c8b69f4e48fc557097e0cebd55208ccb1fca45f57dfa88f6d38f8124676836b7d742c40c1a584c52df005aa793967373d1042eadabb201c0b9f2de3cbb77656d035567442c8b48167c48efd82178ff9a2085007249b8f24e4da000eb91281cad06904d4610a4f009e1a92281a603d47282cf28b2e789151a8cd4a5c79a9de36c0a41d15fbc23857cf79c3767e843f5154e7de23f0061021b7bf0c2db5aa1f6187d8f48ad227cafb9536c1d961ec371c0ed11cf4f00bec8a128c7a6515b9de48b7fb23f9b8f4ec12c1581633dae16b99ee8f44f7a3bc24c72684938b9c4e34d19233f0b9e804b62ad862dd6ad64c7871eaae259a076c00c0bcfee2e5bcc8c3346e08f5e2875fb511d837cbaaac9b741a4b79109f2dfe4e7ff8b398d9bbcb2e39c593643babf8bf4a6fc3a746af419323d623308659fff55e733b503692c71c48d08ea4a9d3ca8f20398854e4494f59e0dc42827947616a505c7b2031b84fd4e33c3775021cd000a865348e855b35567c36e15b650ed07fc60b5ed1b972d29a8b310b60d41e0e43c253249167c8595fabd44c029fae8912cd8f76deefc0abf54aba", .None}, + {.Shr_Signed, "fc761e4c23edb580999f2ed9a1171f7c40cfc826958767078bba476f0cadfdffc17fd087789f32a54c9cc9fa4b9607d7af2e5354c116d58f52da93d59332a2b723211e3c4e9938d49b475bccd6bc980708b111d413289ebe72f75ef16055880a07a5388f53500c035a5f4d39cb59aa18229bb3e0bac13a60d5193bdea7199f786f59501c401234cb53288a97e8e85d2fa1e373b7575e8b8ae9b7b918dfdb8ad1764048c03843596338605d34cef962c85ac3d757d13e9856903fb1334e94d3e7ab4ff52942a39b519e640b78125eafb85d88b1c209ba80cbc86d471fe50fee35d0bdae869edc682c3df0552d5310bbb84a5d8e24a4ee9a0694e39cbb2d20948fe47e69a11de00ba2f7128f89bfed028457503c1d661afe2977ccecb1ca3c9589d648bf02a0515978cbbb864a7d791d2ee756adf8fdfef2b9ebe7a1e26ca973e23a6a26df9db00b21c91a10a6b1f9fa046b1f13d6b20e35037281f8d54e2ab1089d8799386091fd65f5a93acd7453e2feb7ed0f6d8775a421b3081a3fc22f24e3e3d824ff53b1365caed7923101416e79ecf2e06cd4d3067505c40b3f67df88b73500b4665bb36f2ae88ea29fea98f52d0f617ba52c7967ade6ae9477d460fbded2424b0178627ce6631bb7b425d3b4dae20803ecdd4cb22ffc856b9c2b9e42c287dc817557fed4a8489839d31034a52a40e9bb4c2af3a6ad0af32f9d1ef28fc0dde2696aa780c7eecce1980d7091bce4cee7ba9cb2ca15ff4d29d07eef9b83e2e20d29fdc1451a847a52ca74fde22ec8e4bf504e640f6be35621058488cea52fd0321c58e6919fa0faa9489f85d8229b4c8b26c52c0d78bf7ccf61fcf8aeb41f67ab2c6280c3566125983dbd2a578fe11c5fe2c854badafe45418f8bde08adf62d541b4a5fb2e78dab8cde5d4f71a2fb9babb43ceb80d3029a144a55ffc2fe34d583c025526004dbb4315ab57e71c423ed98641ba94af8b174ab96083afa3b16b46ebdb07f59a60656e4893f4a145cfa9a6ba13f0ec6409b2a1d149642c7844b44b53ead35c7c4773bc8f4283d2e6be79ac078e75408da940218ebabb9ed6ac0e0e168a7c8508a9cd2033b22ad891b0eb4392c7020c5a49b00f30977a13995c2b58fb699f2af318fa4ab52f4f1de4725777b8a740771a084c12f4131337a73e71574d473cbab36873a087c45fd247d0e22fff4823d96d24a9f95b85cee646f8594c62ac4b1ee5ca9239e8921eda85d4503c0e1f3f6c27386aa45db0417eaf951f389b1e70e4f79c51fb3a4b0d742f8f39fc06e888eaed6a1b82bed0a5f157d78f5cb3390b46eec9d02109c4777eec74d00851c402b286dd57b2e8bbdfe26b0364c7abaffbb62d5d0113c03039ecf3f09feaaa6bfd2c528c626d131757e2b2a85d80947ee625c74a759b288a184ce432eeebdf8efd7f130c65d0ab23e8851ffd1b11976ade455a148e59958fda8f6f8bcce1442cead0770ba9f121ddf854555ee32b1f1833de580fb0a2aea775605de4a6cf6f83746401a2a0cab3764caf5a72a8bfa5e82e0d3d4b6da865bd5f773d079a5d905891caceb14220768b27126833f117a3c867094d02ee3e403bf7429786541def3e1ec1df6954df74171d8c82838905ab7c766c6d27e6a4edc71eb27265e72e95baf249c72ebb165f93ebfccb48b26df505755bb4182fff00b7fe70f0e0ed2d97f3ebed127bda7ec086647856a63376dcf072201e66e9014d563ade611621f460b2e3ee5e390a1108386be4d6df442d2dedfb163b068513c43090e88063be7efe5b9390e39d9e6d0b5bcf4089ef2db6cbd17a47a934c6574f7b2339d6a50f87dc0e12dce44ebd44c099454f83ecf93fc91ee485f4ece85dd43da656da5ae80b41ed04e2f7ed627496f336b85187f684743e87be09959ca397a99c65a3388c0a84008407075ec5774e2a434a1ed89d8ab96c60a36ce63a0460a77a09eec28f008639684888283bc96acbe0223dcc69d6f25b2a5b47bc148c99d448ded31907d7c701c81211d2756c044415b1c9d7f6d2cafad97617542e380654af16a36e676e9230bb8a618bb3905b3689e92350c0021a654ff9d0dfbf0cbd31bdaad884efaf0bead260b0e3b781a465b", "28", "fc761e4c23edb580999f2ed9a1171f7c40cfc826958767078bba476f0cadfdffc17fd087789f32a54c9cc9fa4b9607d7af2e5354c116d58f52da93d59332a2b723211e3c4e9938d49b475bccd6bc980708b111d413289ebe72f75ef16055880a07a5388f53500c035a5f4d39cb59aa18229bb3e0bac13a60d5193bdea7199f786f59501c401234cb53288a97e8e85d2fa1e373b7575e8b8ae9b7b918dfdb8ad1764048c03843596338605d34cef962c85ac3d757d13e9856903fb1334e94d3e7ab4ff52942a39b519e640b78125eafb85d88b1c209ba80cbc86d471fe50fee35d0bdae869edc682c3df0552d5310bbb84a5d8e24a4ee9a0694e39cbb2d20948fe47e69a11de00ba2f7128f89bfed028457503c1d661afe2977ccecb1ca3c9589d648bf02a0515978cbbb864a7d791d2ee756adf8fdfef2b9ebe7a1e26ca973e23a6a26df9db00b21c91a10a6b1f9fa046b1f13d6b20e35037281f8d54e2ab1089d8799386091fd65f5a93acd7453e2feb7ed0f6d8775a421b3081a3fc22f24e3e3d824ff53b1365caed7923101416e79ecf2e06cd4d3067505c40b3f67df88b73500b4665bb36f2ae88ea29fea98f52d0f617ba52c7967ade6ae9477d460fbded2424b0178627ce6631bb7b425d3b4dae20803ecdd4cb22ffc856b9c2b9e42c287dc817557fed4a8489839d31034a52a40e9bb4c2af3a6ad0af32f9d1ef28fc0dde2696aa780c7eecce1980d7091bce4cee7ba9cb2ca15ff4d29d07eef9b83e2e20d29fdc1451a847a52ca74fde22ec8e4bf504e640f6be35621058488cea52fd0321c58e6919fa0faa9489f85d8229b4c8b26c52c0d78bf7ccf61fcf8aeb41f67ab2c6280c3566125983dbd2a578fe11c5fe2c854badafe45418f8bde08adf62d541b4a5fb2e78dab8cde5d4f71a2fb9babb43ceb80d3029a144a55ffc2fe34d583c025526004dbb4315ab57e71c423ed98641ba94af8b174ab96083afa3b16b46ebdb07f59a60656e4893f4a145cfa9a6ba13f0ec6409b2a1d149642c7844b44b53ead35c7c4773bc8f4283d2e6be79ac078e75408da940218ebabb9ed6ac0e0e168a7c8508a9cd2033b22ad891b0eb4392c7020c5a49b00f30977a13995c2b58fb699f2af318fa4ab52f4f1de4725777b8a740771a084c12f4131337a73e71574d473cbab36873a087c45fd247d0e22fff4823d96d24a9f95b85cee646f8594c62ac4b1ee5ca9239e8921eda85d4503c0e1f3f6c27386aa45db0417eaf951f389b1e70e4f79c51fb3a4b0d742f8f39fc06e888eaed6a1b82bed0a5f157d78f5cb3390b46eec9d02109c4777eec74d00851c402b286dd57b2e8bbdfe26b0364c7abaffbb62d5d0113c03039ecf3f09feaaa6bfd2c528c626d131757e2b2a85d80947ee625c74a759b288a184ce432eeebdf8efd7f130c65d0ab23e8851ffd1b11976ade455a148e59958fda8f6f8bcce1442cead0770ba9f121ddf854555ee32b1f1833de580fb0a2aea775605de4a6cf6f83746401a2a0cab3764caf5a72a8bfa5e82e0d3d4b6da865bd5f773d079a5d905891caceb14220768b27126833f117a3c867094d02ee3e403bf7429786541def3e1ec1df6954df74171d8c82838905ab7c766c6d27e6a4edc71eb27265e72e95baf249c72ebb165f93ebfccb48b26df505755bb4182fff00b7fe70f0e0ed2d97f3ebed127bda7ec086647856a63376dcf072201e66e9014d563ade611621f460b2e3ee5e390a1108386be4d6df442d2dedfb163b068513c43090e88063be7efe5b9390e39d9e6d0b5bcf4089ef2db6cbd17a47a934c6574f7b2339d6a50f87dc0e12dce44ebd44c099454f83ecf93fc91ee485f4ece85dd43da656da5ae80b41ed04e2f7ed627496f336b85187f684743e87be09959ca397a99c65a3388c0a84008407075ec5774e2a434a1ed89d8ab96c60a36ce63a0460a77a09eec28f008639684888283bc96acbe0223dcc69d6f25b2a5b47bc148c99d448ded31907d7c701c81211d2756c044415b1c9d7f6d2cafad97617542e380654af16a36e676e9230bb8a618bb3905b3689e92350c0021a654ff9d0dfbf0cbd31bdaad884efaf0bead260b0e", .None}, + {.Shr_Signed, "b3fb192740fa419457155a6e8d6dab2f547226c4a72a0fad2928c950224121026437064c262fdf8136f1a0e7737124c218db08baacd9ec98f02f045e74711461120a520f630231a3646d911cf1f19b57a00f3e011355ab1f708d7acb368c35324c4fa3cad7e6733c7b97817be5538de9b71280364da323abb74006d74461d9f572eddfde8017bfdecf105a28b9d6437eae3fbdbffffbdc3e6c97d87ace8cb89536e7bc83355ea8a3035fb70e6e6c3a19d5dda2edb6138fdd4794788bef54ff8f4e6bf43e77c191a8616a496a5ce581ccc902e182e16fb28098e5738f2d7efd6b8163e8416e0d6e6e65cef310fd5a77b5a494232bd19c5c36ec9f17bf4cb5046df9f00db2b37f1238c4c6fd49e688629d242419ef91fb023a376841f3dea4e30e5542aa1108b0225929df439876eea6902c6d13990396c5a76389c1dfd2ce50bfe4703894b9872b8d7a349b003d170537b1b6d6e02147dfb999eaeefc835ccaf0218ab3148ae453613f42e6c65685ae7e3e9491914062b1d216b5c99fa7b8bc4d795f188983e201f5a377d01ca3266943f053fd227b86d45f2c8995f73886abba3f9398420acf0aa28be064641c0cebc7c455255d2a64518384aa1c65b25845982c5b64acf725aaa3a60a88c82e654c7546d97dec68447cf931863550317ee85789549902d18e42ddc63226bdfbec93ef535f81834d833357bb050d51068b443200dbed9237301f071450775aabc1ee3f3d7ac9c260f0b559d0b525870976f24d8eb88ee5ec81184462fe4e8b7bb590a01849de6b5e1ff2cc507227559587438ece85a2961238b29e21f4854d2e0f28fc924c3fc8ec31ec323d64927552007e99f815d2c89c9721163ea9994bc084114ec2bf04d55f014a3ffb477053a8f4cc916a3ed578df3b0210dc34e02b098cdce022d318a5b6562d568bd9719f510f2d09f170d9e248cff6809b2071a8df9f6eddbaab3f821df3df6b05b040c5c3d76554d6613e478d8eb7e7d256bbf7d6aec2bf6f944fde2ff126225555c525869f0f2b70abb3ac607af796eccb201f7e0ef4005c1ecc2ffd7d219df9983f2d614b830ccfdbce340c13386812cbd42f71b114ad639bd8932b2c9bd57def3fa36d9ff5a0845e1b27f1f617413f13de3a0b9a12b74f0acd3b3d483151d6fe6388e4f559edf4a27e96343a820c5dcf4bd8c1164f4424f44671ff8c50729232d2d75d1219d05d1aa0351d79dd73faa81be27562e10e3d520e092061daf0a290679405d99ee170f15bd03cfe05c81b32216662a827040966316d01731cb321ca73b1d1cb23f1d3713a9acfc24b6fa4fd699c43df7f01dc57a7e72133b63506f0bd67548b3cca3aec8b73b23a7edc41009548c7aa2697627dad2ad459762d86d7635dc00e39ba570ab868d7849e48bf0f3bd7c55415b71892b09b6b75a3707afd9121cd46520c9fc17d5f3a04695790149f76d761f6a2945ffc2f8b8f1110e5a3ad9ca0b2d89838cc1efbb0b69ffcdeadb39d2d3c2800a72428f0ab74df1f261b98d132a92fa41ec460bf29ae5c29890f5fd8023b32ffa2505a3afe36a5f95f0ea11910533a06fdee042fd0f3fafa5ce685a4b74a19574974cfdd81c3989286373f584feaadb59f23b9379bd79e4550b18a0fe92dfd32377e8b9ad1c8ffe61d5ff12d39bc22bd55677db667cda51c5efbd3bfff28a9370eff1cd08e051e8c01d1fed9af825636aabbfc69a36c8d4c1927080288d25ecb69080d77c3a24907ff3acfe299388646cf9c6dcf77a4cc41a40dfdda391d707b746f449623f31e096300890778f7e3cac558ed6365f2ddd0ed10a06bf1f0fee32163d5541d13aff919a0d3e74101ffc3a6f1562b0e6839d4de00ce33d0f494c69dfa672b2e317d299c2e04e018919b334d81e58f497df139016c986740f9311c8cc9174c378c30b5303e82698e01e3c17213b189f667a7f1356a803e0dbbb4fbd18bafe8b0cb6a595d920776a7177924b9e02809c3bf9bf6386b8dd46f9369bba1e0e375211f1c0b4dcac27dca316581ecb33f0ae34af5a0c3c8329b8da2f462d9183ecf21a521c2d2a50d23b3509fbb0427ac13e24abcd49f41762fa7c0686569a469b20627ecd95907dbbf", "1", "59fd8c93a07d20ca2b8aad3746b6d597aa391362539507d6949464a811209081321b83261317efc09b78d073b9b892610c6d845d566cf64c7817822f3a388a3089052907b18118d1b236c88e78f8cdabd0079f0089aad58fb846bd659b461a992627d1e56bf3399e3dcbc0bdf2a9c6f4db89401b26d191d5dba0036ba230ecfab976efef400bdfef67882d145ceb21bf571fdedffffdee1f364bec3d67465c4a9b73de419aaf545181afdb8737361d0ceaeed176db09c7eea3ca3c45f7aa7fc7a735fa1f3be0c8d430b524b52e72c0e6648170c170b7d9404c72b9c796bf7eb5c0b1f420b706b73732e779887ead3bdad24a1195e8ce2e1b764f8bdfa65a8236fcf806d959bf891c62637ea4f344314e92120cf7c8fd811d1bb420f9ef5271872aa155088458112c94efa1cc3b775348163689cc81cb62d3b1c4e0efe967285ff2381c4a5cc395c6bd1a4d801e8b829bd8db6b7010a3efdcccf5777e41ae657810c5598a457229b09fa173632b42d73f1f4a48c8a03158e90b5ae4cfd3dc5e26bcaf8c44c1f100fad1bbe80e519334a1f829fe913dc36a2f9644cafb9c4355dd1fc9cc210567855145f032320e0675e3e22a92ae953228c1c2550e32d92c22cc162db2567b92d551d30544641732a63aa36cbef634223e7c98c31aa818bf742bc4aa4c8168c7216ee319135efdf649f7a9afc0c1a6c199abdd8286a88345a219006df6c91b980f838a283bad55e0f71f9ebd64e130785aace85a92c384bb7926c75c4772f6408c22317f2745bddac8500c24ef35af0ff966283913aacac3a1c76742d14b091c594f10fa42a69707947e49261fe47618f6191eb2493aa9003f4cfc0ae9644e4b908b1f54cca5e04208a7615f826aaf80a51ffda3b829d47a6648b51f6abc6f9d81086e1a701584c66e7011698c52db2b16ab45ecb8cfa8879684f8b86cf12467fb404d9038d46fcfb76edd559fc10ef9efb582d82062e1ebb2aa6b309f23c6c75bf3e92b5dfbeb57615fb7ca27ef17f893112aaae292c34f8795b855d9d6303d7bcb7665900fbf077a002e0f6617febe90cefccc1f96b0a5c18667ede71a06099c340965ea17b8d88a56b1cdec4995964deabef79fd1b6cffad0422f0d93f8fb0ba09f89ef1d05cd095ba785669d9ea418a8eb7f31c4727aacf6fa513f4b1a1d41062ee7a5ec608b27a2127a2338ffc628394919696bae890ce82e8d501a8ebceeb9fd540df13ab170871ea907049030ed78514833ca02eccf70b878ade81e7f02e40d9910b33154138204b318b680b98e5990e539d8e8e591f8e9b89d4d67e125b7d27eb4ce21efbf80ee2bd3f39099db1a83785eb3aa459e651d7645b9d91d3f6e20804aa463d5134bb13ed6956a2cbb16c36bb1aee0071cdd2b855c346bc24f245f879debe2aa0adb8c49584db5bad1b83d7ec890e6a329064fe0beaf9d0234abc80a4fbb6bb0fb514a2ffe17c5c7888872d1d6ce50596c4c1c660f7dd85b4ffe6f56d9ce969e14005392147855ba6f8f930dcc68995497d20f62305f94d72e14c487afec011d997fd1282d1d7f1b52fcaf87508c88299d037ef70217e879fd7d2e7342d25ba50caba4ba67eec0e1cc49431b9fac27f556dacf91dc9bcdebcf22a858c507f496fe991bbf45cd68e47ff30eaff8969cde115eaab3bedb33e6d28e2f7de9dfff94549b877f8e6847028f4600e8ff6cd7c12b1b555dfe34d1b646a60c93840144692f65b48406bbe1d12483ff9d67f14c9c432367ce36e7bbd26620d206feed1c8eb83dba37a24b11f98f04b1804483bc7bf1e562ac76b1b2f96ee876885035f8f87f7190b1eaaa0e89d7fc8cd069f3a080ffe1d378ab1587341cea6f006719e87a4a634efd33959718be94ce1702700c48cd99a6c0f2c7a4bef89c80b64c33a07c988e46648ba61bc6185a981f4134c700f1e0b909d8c4fb33d3f89ab5401f06ddda7de8c5d7f45865b52caec903bb538bbc925cf01404e1dfcdfb1c35c6ea37c9b4ddd0f071ba908f8e05a6e5613ee518b2c0f6599f8571a57ad061e4194dc6d17a316c8c1f6790d290e169528691d9a84fdd8213d609f1255e6a4fa0bb17d3e03432b4d234d90313f66cac83eddf", .None}, + {.Shr_Signed, "69a539bf20a729ecfe22ae13cef7808657e03e987036e77332c33f422b69b9d72a7b4bcd2ee168384bd3ae222ba09d61e4267ff2c2fec936ace5343a6276f831eed31186816828b716a2ef8e267a7d34076379bf335331c128523f6cca4325e731bdcb0aa80a39acaf2a7a94f629e4a722b09d74fdaa40a0b33de5ad7a78d4a2707c82a41a8bb4dc0d9065ed6c17aecc0870512bda4622b3fd0219b687979a37d1dafc197b276748c7731ab585b73d1e706bce2eb55c9bb3324f4bb978602f5a1d74d75cdeb62aaeecddeaec05510149e8170ffade1fe9da432340680fb2012782294e7eddb71121098483b763df5bfe5225938ee5084d530c806661b8abd7f57a094a6154fb06ef3fc878464d85a28076f88196f3aa253d954fca4b76f8834833f8d9aaa4e887a45acdbf6017309ee9e48a5f69952c13e6ffbbb12d33a4e23045ed33c246052088d2192e043f027c46db9958c481e718999e510fdf8a069995cd9fbc41953fc835a55eafd6f77089b3dd129ffc27aaf4f3e1687a798212e6e30c4df2e0e772d471b5d49c9c09205a06763a7524147ca708fbd0afe56190933a5a10146551b6c458fce4e916779cbdc87a63954f7f0cd80a0527389a4ebd2663998ea54ae2f11e05b775ff9e1dae7c62036fa23ebde96bb8159c74f3d138862ce5358f288cb5d5ee05fe01c2bf3221c8b8aa3552724fc46e50247e9974d7d19fe00926720aee981cddf2bde6f82a8f74735024a7da50e1a4b0030482dec5bfc2b03c16af0776d8ea8c8fbfdcc46f333c2b1ce2cc923c2672eadba588d4b216d58c9e1b408ec27713744ca8fd3eb49c921e74474dc29b3af09faa35345003ef93562c4ae55428a66be824e452cc059dc0164ba5ddb5811b15ebbcaa2535fdb1ca310054278d353aae7d7c11b4b4a18204ea647d99bce2d207566012080be3dc0e95a5d05847a749f89614d97d9256d6ea9a87b34218072e2a49f7b9cb728086dc077b0d0ace375ecc97ba97e6ef0fff382a0a83039fec92f095e59268a69ed40e0aa99350b73ba524335aaf4123adc24c0e70815895bac1451432c0e3068b5a2c2f347c5225c1f6f106d7d44b78b44fccbdc703e2cbdd2f0407b7150a4ef050cfc2da589f63acee1834ca994e857e066cf1772a0f23dc47963564caa70b1965c96e4212d1941d8e6e77f7b63be569d79162d10dd6a616ba3223bac7288be9cbae139b09c93a2550b719c6ae5c8e0b2202b30200e0851e34202a1a594bed67bf81b7c3bdbe6dc4a18cb58595895c68fa359a8a7fb97f48094bf86694773c96b60de716e5c005ebbe2ea1f052f64e10cfc3922d5795e33e46a0d6cd803e831cf60dea77aa5373317e942e25a0a9506727bf986fe9074dbaf1b7402dfeb7cf28b30c2d8b068fa69ceb15ecacfd4c1bbd7506130554111ae88daa45d6a33bb4cc1bf4d30d8ce21c0ebd30ad30ba91faea1b348fac37a1fecc0e6aa4c846ce7097ce9e8226dc4189e92863eff0a0b29ad25c87659c47f3adf2581240e6083bf965dc8f87b32516e3c995858692d1352cfd26612ef215528efae82879b7c97732e8d971c4bd182fb10bd39e264e7aca0c6316c8ac28b3bc456838ce87bc9de6b688b50c082a13a36e63413ccac92f5fd714e62391101115ba304a052d0bebdf501362e219fe924790932a37f54a3327c9da807fdaae998268f3b99cddb2ccc46297d79fd9a3c533b150fce3737b634bf522ad191d6ae69dd0ec4438e792a3f9072d6bd1768e5b1044d369b7ae976c705cab0387f579138482a9c46ec93fddb9b0425f07890eb3354d10ef9992b86589771371e13bb31e6c8137c2c9d33a7e27e3ae8918f43f3f5601ffb0ede41d76a094052ef39e722148d66c291b75b993b8e99ee315599d4bae9ee0105b8d619d984f0ad7c05e3f32ab68631fbe9984db9be36bdde9181664a84e1526ad4ccc94933a328994ac7695f71cf635b6e125cb96e0489bb9ed6fda903f2b530744e21b62dee2543efe6d803a5dcef3c4ee6060748b6d305968cdb21f81c02cf3f1306cc0b49520f0cc43672851752445d0b9b022263d9e17ca084928024b4a4ef927da5250bca613d6d0484285841c5604919709", "3b", "d34a737e414e53d9fc455c279def010cafc07d30e06dcee665867e8456d373ae54f6979a5dc2d07097a75c4457413ac3c84cffe585fd926d59ca6874c4edf063dda6230d02d0516e2d45df1c4cf4fa680ec6f37e66a6638250a47ed994864bce637b9615501473595e54f529ec53c94e45613ae9fb548141667bcb5af4f1a944e0f90548351769b81b20cbdad82f5d9810e0a257b48c4567fa04336d0f2f346fa3b5f832f64ece918ee6356b0b6e7a3ce0d79c5d6ab93766649e9772f0c05eb43ae9aeb9bd6c555dd9bbd5d80aa20293d02e1ff5bc3fd3b4864680d01f64024f04529cfdbb6e22421309076ec7beb7fca44b271dca109aa61900ccc37157afeaf41294c2a9f60dde7f90f08c9b0b4500edf1032de7544a7b2a9f9496edf1069067f1b35549d10f48b59b7ec02e613dd3c914bed32a5827cdff77625a6749c4608bda67848c0a4111a4325c087e04f88db732b18903ce31333ca21fbf140d332b9b3f78832a7f906b4abd5fadeee11367ba253ff84f55e9e7c2d0f4f30425cdc6189be5c1cee5a8e36ba939381240b40cec74ea4828f94e11f7a15fcac3212674b42028caa36d88b1f9c9d22cef397b90f4c72a9efe19b0140a4e71349d7a4cc7331d4a95c5e23c0b6eebff3c3b5cf8c406df447d7bd2d7702b38e9e7a2710c59ca6b1e51196babdc0bfc03857e64439171546aa4e49f88dca048fd32e9afa33fc0124ce415dd3039bbe57bcdf0551ee8e6a0494fb4a1c34960060905bd8b7f8560782d5e0eedb1d5191f7fb988de66785639c59924784ce5d5b74b11a9642dab193c36811d84ee26e89951fa7d6939243ce88e9b853675e13f546a68a007df26ac5895caa8514cd7d049c8a5980b3b802c974bbb6b02362bd779544a6bfb63946200a84f1a6a755cfaf8236969430409d4c8fb3379c5a40eacc0241017c7b81d2b4ba0b08f4e93f12c29b2fb24adadd5350f6684300e5c5493ef7396e5010db80ef61a159c6ebd992f752fcdde1ffe70541506073fd925e12bcb24d14d3da81c155326a16e774a4866b55e82475b84981ce102b12b75828a286581c60d16b4585e68f8a44b83ede20dafa896f1689f997b8e07c597ba5e080f6e2a149de0a19f85b4b13ec759dc306995329d0afc0cd9e2ee541e47b88f2c6ac9954e1632cb92dc8425a3283b1cdcefef6c77cad3af22c5a21bad4c2d746447758e5117d3975c27361392744aa16e338d5cb91c164405660401c10a3c68405434b297dacf7f036f877b7cdb8943196b0b2b12b8d1f46b3514ff72fe901297f0cd28ee792d6c1bce2dcb800bd77c5d43e0a5ec9c219f87245aaf2bc67c8d41ad9b007d0639ec1bd4ef54a6e662fd285c4b4152a0ce4f7f30dfd20e9b75e36e805bfd6f9e5166185b160d1f4d39d62bd959fa98377aea0c260aa82235d11b548bad4677699837e9a61b19c4381d7a615a617523f5d436691f586f43fd981cd549908d9ce12f9d3d044db88313d250c7dfe1416535a4b90ecb388fe75be4b02481cc1077f2cbb91f0f664a2dc7932b0b0d25a26a59fa4cc25de42aa51df5d050f36f92ee65d1b2e3897a305f6217a73c4c9cf59418c62d91585167788ad0719d0f793bcd6d116a1810542746dcc6827995925ebfae29cc472220222b7460940a5a17d7bea026c5c433fd248f2126546fea94664f93b500ffb55d3304d1e77339bb659988c52faf3fb3478a6762a1f9c6e6f6c697ea455a323ad5cd3ba1d88871cf2547f20e5ad7a2ed1cb62089a6d36f5d2ed8e0b956070feaf22709055388dd927fbb736084be0f121d666a9a21df332570cb12ee26e3c277663cd9026f8593a674fc4fc75d1231e87e7eac03ff61dbc83aed41280a5de73ce44291acd85236eb732771d33dc62ab33a975d3dc020b71ac33b309e15af80bc7e6556d0c63f7d3309b737c6d7bbd2302cc9509c2a4d5a999929267465132958ed2bee39ec6b6dc24b972dc0913773dadfb5207e56a60e89c436c5bdc4a87dfcdb0074bb9de789dcc0c0e916da60b2d19b643f038059e7e260d981692a41e19886ce50a2ea488ba17360444c7b3c2f941092500496949df24fb4a4a1794c27ada090850", .None}, + {.Gcd, "9a1a6ae6c3ea0e168a5b36ed8e599d6ece1e7d43d6e87832689ee0680a2664ac7c5353456136a0e55c059b0c804577ef8f060abaf830ddfcf226db5432e400ff7c1fd9ba4b3341223172e85809f2b40e5aa90304c1851c6565b26a16101a10184b5678020bb6f5565410994a34f79091aedb9fb391ec55cd589e8f8126f398d3f3c6abb7f55a37aabceb0e6617a8bf59b5d76749fb6c92e84fdc97420b83412ceb857bd90504f417b4d5e32f0c8c8f078abd18426ef1c019461610657f0c270191777d4839fb9d87cd8f52639d79fd2e4345724cd07899a55951436296a10f06691f67fdd2c0f0ad39f5e3d452af38ba82392af2b60540d2d32c0c22d5ed9fd3049076155ecbfb13868c47ec03d1356c7a5516c8f1e241012ed9a92d8fc8abbe415876c4f30565a64925899ab519ae7260f1e3852b91d3f8608682858476fcf508660c7968edcfd878e01de08f36906af170da26b1a88f45442a1e553dc97387f59790a52690858d5ba80613a323da3eabedf0fa717d8de157aef112568873960a5aa4e2d0b0016aa9b1f79b731ca8a5af6282f26de85516422b4c4ef06367128f14177a9044f3ec18e797d00b55a541a18f29adb3df90d579ab36aa27b5f27a751506797b63ca67b0abab157faa08b462d5c5946ee625f844376aed8054713ea5324a0a3b89bc4c07e1a42de447e9ac229c534a297b2d20f5d6bd54b47aa312bc20a0367eaf2151d695311d6ce59a02c2878abda123afa6d9e0fae5528a99f2adb8f0c5100d5722dffec78cb4f028d2ebf52b4ff2adaf7ce0599febc1b8b3e0621e2fe9add988eb43ea34f42b4d68765c043e16b397534b13b4110501570fce50581c0bbbad89d12e29fe93351f78d0e1ae30e1bb4d409062dbf678b3f2b8faf5fe4fcde5bce2b2e0f9f2160db9f4a5b6a359a6b7600d6001332e1f1e1763ae73ab3abe683c890a4408a04b9feba05c623491cc7e4cdd90b6bf36dc5507aa46def931963a2b1dec467934e4cc4286fcc11029ca47ecf265cc71781ec75e1493a012bbdfd10c387a4638af4c462d49989892f4702766d33ddeb897ab100ebcb4f9398d76b018b43b22bb95e9f4818d547410030d381554a272809009ecbf7173b6fd66b9eb83e52a01a8f2faf3089a23a34054bcabf7f07e63f1c975262798425b02cdc87f81669513a8a9b3f04a78a055b4f2b96df4e3c1f27b5dee557891d745fcb51538634801bc2e6dfcca9c15aa40cb7c373c69319656fab45d9950237910bff2d6f6911a3fcd7d946bce0c894f43dda968fea385c84729d8bad6bfacdf2e95a188281fbb6821b9dce8e6a68d7b367f12346c2b7a873406a54217aa0d3f79b56d3cee79eebb593fe0561ac8f437d851c19b17bfc59c8230c0c41a5d2dc250b4d54576243fe2190fc81809c1fd583bfc3d2253e001650674349a71b18eec964bfb67eb39f11dda93afe358e86f504bd91018be219d4d0ddd5e4ea6500263859998e4574075901a213d5d281935731eb3a8e5d874c3edf3d7acbbf1a62131cf63d382babeea1b62066520b6a5c34d030952a6a42c1f6c214e1dd0559e893338fec937c71800548749da1bf97d75382dc97b2d3b687ed339bbee8b6450d2d17c62ff854f10dd2b8f43bd6e60236919b0439e5f289638b6f893e5c64f2f786ad87f61ea16cb0a67231919a71a52401735db4153b33f563d9b912a0e160b141705b2640cca6f006e26733142aaf4d5117e298c1fbf9c072c33e17d7c5a8c0cac0039a13f39a2bede54fa4fa2651c79bf2b64bc0a1631ad4837e8081933de7c943cdb1b65ab6dc03ac39df6fbb376cadf4900bab5c8afaf4593058917813dba7ecfcbf6505216ce988b4ae7a0a55ef9ae6f3b5b151a0ac425d3bbd71795dc9047e5fb51993db128ef754aa705a0a731351f30d8e551f73ab60458f9408f364487623c9a880d95ddde86a15dcb4bfc76f7c4d22570de5805598c7043e7fb5f9cac9cb6ea9f65e547fc455da58824c639d6930ffe2daba51f73091742dccc528505f8a40c9a01128169e3f940d8d62d0b597c80f4c7a2070c9b5ba8c2c4715433459075bc4edab6aeed9d55985f7ca1124e026bfa516d45a6c6e7da4665", "8d1e4ac11c2406acaabe16552305bc95c28f90b4a5f12bdefa05bd3e07e30438eb1b1a8ff8019dacec2e355ca722b1ebdfbc67d1f13232db8a4937b11fcf2be0fc763add572b00998defc9f0d626e3dbb44c2a1a26aa8666cad4dcf9de8b053b2bb954de55b70f61f65a23130c997c92f22fbecfda498a736de5d0f90065b4c5f5d7a7d8d55460851abefbc689fb1a69a197d0ea12d23150e59efef17134a8a9774e7bb87fc03f5de0b34747a3bc286e32cf20f1f23197a2c30f597667104f4ed098b864521e21075589183a8b8459682114154776adf815396dd7aaa5efa51d1756e9bb0535fbc38baa01cd00de6a771d167dbcb6df122287977b2edaa5b4c87fe319e37a4d95a6cf65e45aec4e4fa7aaff7fee29ea82d8b8668188108b536fa9ac762b575791b0bd7648ad0ebe6214daf9e99b15ed89d7813c8050d4b55936bf84f04767905d49816a6c64c978a908964436eb4a03ad0def411a24ecec2080683920aa0a57e5c0480010851551155fdb30899aa34d10739442353a2b25f1cea27341a65626069a0fd9a6643f6923d8f5c874670a844c922d8782707a4aac3aa2a836104f6d6add681c29ee698af5b5289c3a337e1e373c0969e1b5ede589f445899bc13fa8f97869ab5825f0b5281511a4219ea70a750d8edf6c728e600da153f2559acc7268dbb918f1e5a3df9feec61e441544ef8abe2b13763bf44094f694046b82e89346bf2bceb72a673a3df15cf0d7709e4676f66d63d1504b51123198c3905b5b3cdb683d20fa2f2fa3973cf426f6daa565462410b80263464d4738a5571c9fc5ca019c740dafb937745a8496119c153f72f256ddd4ec57b1bafee2937c5ca79c38eca48da7ab71bb3d0677c4676adae2d3f9b671486d58712ffc160e4974fda19fd17d0678b0546523bcf18f48a064d48794ee5139c2836f59dd29c4554f543ded05d0110ef4b82f4301ded7c60fad3b0c55ae0daf4d75097285cd8e92968146d0467b3955054f6179d41b90d67b1b405256ab5a576a4c99cd293d7457ac0b1d0fa43d1a6a223c917523d58c875352885641db18832ab4d186fe1e10649dda47123f75ab7146eb350df12f46f90328fa0d3c0e6eaf94bfa02c9de1487f4902aeddece2f73f55b9e54125da59e42d1c5561a373d7f6e32ad5edb5f9ccbeed2b1a1ce7fda268a78e3a8b98e20bebb99a3c5e3e7cec68af27a4f39dda18d0fb093a8b6f768aa34b31c98367262f9cc54afeb5108288982df0f4270ccbc053e2ba04c685d253bfc96db4a757899fa9c21cc4f353f2f2c8939be5d486598a57c0ca48efb010a447c1d64c633c4e319a522dd2adf7ca6b2dcfc7b7b73897cf3cd51c809faf43a51f6c22707e0193dd0374d01bdb68d12639aa1887f55a70bc2d7e53aab5219fc5cf8587044b10fb90a1e60de480d9090a88294387e73844792aeb82c2ec29f993c2656de76cf015a62aca55336b7dfaa346d4c3616b288bfb39c37ace4ae615ee115a2f3bc8a333e6c912eca0d68b37ca23d2581a6f2d756abb155989098973028082e3e3eeceb028f91868c18abe7fe16b52207a0218e0dedb1571d65084827d76efaf0f61b2531498ce41aec30ec14e1e72d1604bb8a3ed0a8db937ee6330297727e0b019303dd6167177299f85b1a2fd13d5042ee395fb0d3dbf6a16a0d900a6e0bdd8f5e10eb3b9a9787e376522f81cb5ff4ca06780d7956213db9d5aec1f8add0702fa597fcdc3381d379362e1c5b59b31dda2dac7cc9e7504552c828805260666d85f690d2a2573573302c223ec93bf684e3491c57c1fe9bdec6279dbc79829cb279f7e0d639d88997e731ddd81aaf837bc49ade772358ed3d4fdc9dfd65348c2272b6e876f73dd8aea9b3d08e8e103a429fb3152624a10ac2564a6a86f15b88fdab287d98ea7ef7c56359f091ca0bbc0ebdf603e37f558c1d3d7dde1edaf011663e7a764aaeb2900790e6a1efecf645ce67fe843dbcc0aeae2f142baa0e52b974bb1e700c293a746b2176263ffc3ad32e55dcf2ef7e27afdcaa26b2d2ef547bf78c66741d004be879021a53b40926bb6ce692e36833027ccf63be37219cb7677206e2a727958c0a602e2b73c19e3f76a", "5", .None}, + {.Gcd, "da4981dbb23a520ec3c0905697b8838336a9ff5f10e98c6f1dc142812b1cec9ce7dc2e589e7d3836313320690ca5082f862737c34eb97cfe0ad624ff26e166d5b3fba47349b6df5b9fcb7e20b6587396f4a8ccc36eee9d7eaf93a6563c57f028a13a9fafcdf54ec139aee3105a6769f04789f8fb06cc051d1ae2c60595a172109579011441efbff509eef7550c7c58a99d0c69a8c16f1b3c68e1243033c1ac575ceaa92602ed25460e3f3f485ec88f20df174997732825ca966e31d02fa8f7e06dac5067da92a9cc8e4048543244838f6eb6aa793df5bfb029b165df3328f6497dd16965c0e0d85a9bf151d6c248e3b5df071180ec6d3baaa911eabdb798e5b3e35c026f8194d6c5a302d26d307b8ada29a70f0c124bc35c12bfe626c86da3824243836bafcf6e54f0abb4942b9b871937a061d3373e39772901a4c07cb28f51c088e142049b32f75ac6887e92f11c59c5f14b410d26914e46ac7ec2cb9ed6aeab4ef1ae0e9434931a8255a8b3b2d2a021965ccfb8e796ecd73633f333632b60de03115e96213603c06d8039fa6adcedfceeabe3c4c9dbf728defcc5297df3c4a228046b2139ea4bf6e49eb4500833cd5f14e2562d474b7f232004a39f86f0fcb94ed50bece862d71452f32703e637feec1f2207c1e0bb3dbd807e23491a46b0fbe20d42855ff19772972a006487d473c4f5d14d020571c28114a0d690e62d52e8561f0f416e431baa2c666e5f817b0f5cb6e3a9b249814a1f13a1385087f65f66360760afcfc413944b7259c82f5d039f67bea4a5471a89e40b2e8e0ec433985dd6ef0da99929b5a30bf220bca297f9323c6b60140d5032ed553c2548c8e838ddc7a21f70bb1d1e9bd3163816138e768b59e9a0a3d11d1699aa4f7faa81fb2f9b588478822c8f0adfd8ab53364cb9674b9e6a301582796c6b57129690d1aed594817da525d888e7189c168c5fda78992a4875f5295cb783a0af598e1f78a34e9b2abffe3182011cfd4178444100d53d4a47e0e64a6927a706f485189a3454e8ff4b6ed1017611ff9eae6aaed154ce70995db9cc158a041df35ad0244ccf5cdfc7783201bd8d22a76edb8153c4cb27fa29c85e2ca7451588ac71e23de2812691b520c18d5f3369581aba58863d518ff7b3949b581e35ba85951857cdc03dc18b2735d6599c9b7ab3ede7d264988c4e60a8221005cfc203dd79d47f6f75a52a6190d0dec65e5d1eb4251eb0e065cd747c31a1ca3b7c641570a35c8f5a54e1ef690a1c0c9c041d62fef7cca87bfbc90d477f65fcaec922c019b46a78e325766131745e5b912605cd66cc28bd42204a312b95053d04e38af909608062b40bc79b7737d4207e7cd4f733d82389124f4289eba35335a531287112ea8784d2f5882171677d89e55206673c12ef3f99b3f8dac7a65421f4a39bf7bc52346dc569ec3809ae7d5f37e96f7fada7c2e2ce003e3f0f54f0ca4ac7ccb4768927fed0791148a4eaf1cb587781033b5c606a2ed2413433b05cae2f9948999aa26f380840c7ceb7e9a52ad589513bb864f6ba8620c80d039e9cec9b20f4f550e92202d6bfc612f0ab75d467e90be589e80b6235462ef026f7e43e671d58898413faff10ef166dab89133977de7f2cf9d34f4ec58d4e516a2ccc9efb28adf5beb7dcfb2d5f5da6ec29b7da2e2ff5f4e2c951117493ca251cbbf0a0e683cc73cb46e5d27702b3885c0c4617a485f9ac3a0ccd80a17d9ce057be04d60c9175da5102f9227b75909b84f9b7accf108367ed6d3bb8aef4175a9bef418b5dd06ce2e7030cbf1b8bb6758fe3c34e62e410b91e8557a35c28f5525769bf388cb95ba49b9de2ba16c99510a1ab8a9b29490a5f58d3fd0beafc8ca6eaddf4e8064b0462f90154ecd19cddc9c28d9c95cf704ca87978b0a2856f1c779876e751846c6cb5dd03539974f7c3e3be2289605df3b54ca29db3f030f336542274bead9bb591c093fbb58aca097a82a09ab7de3760e6a7550de954a89b4189d2c849284c6b2096d5059c73f31084de79f74cf5e818587959b08b6ada07c6c5479961fc56e2723f4b7f5d715885030041acbc5ef4ecf8ec403945adc6862ee025de3c22a73a25765d5ebb3d3c", "d91492814cf4eea44f5f7b199ce00c25e978034115e64421a1c328552d2168ee0439da24ceef6e4a7275d340fb694d5f06fffdebb780a3e3d3088d273f8e05c38559f6c1c342bedcb293db754a1637cc80df8a85eae40c25ea62389b0d6655e39250ce453ea983d15c19294e8b45455d015089def5aeb0c01740fa2994d686f5f2df4d0aa955adbdd71a38ad36b044b3d909fdc22d714dd9981b2560ad1fa6c0ad65631ece02f75caf7792607e649aaed49ded89e6c5b73e105a66246120582c8d1b3927ca361881d4189796be3ed87ea5196c039f665e2b46193f28514980983a3a114ba5bc6b84d733c855f08dfaaec51c703a2b07965e2ae5211f2262e63951d60428ab9e500bd80841408b93c14e1091828fbe6b1602997c5537b04c84ae83ca62d64d3fb3108d73cdb5e428f8b34502ae5d3442b34c1dcc062b05329318c2d58b50fc28a07e8fda2d9fbc3e689fc6596c78a2db068ac33bf902feac6be77cbcb030d864493504cdfc922b60e417e21e015fdd36be736b642a7bd2129705511b5c9451d1154641ebae651c481d1d46f3499e79d96a93aefb5ad8fefa71c643de6d0351e698edb4f9636722b67996c98595d873bed218e5978aed1bdc317f4e80f2f3b75063994e9bb2d0336328e0bf2f8498ee65b722835a4b9b047f26f8a05a3be108e923be179268193fae8a200d77da2bdd49eb191eed76477ca3deebc096e3d5655bd114840680609fe316897bf6494d314a25bd48002c7238bd63da11d6b70d6941db4049453e9ea924e07cbf04fc10daf4acce566f958b23b7e52091735d29d2f11aa48bdd50307e3c7d6bb0154508a83ac9abd3f4804f3d6d9e6c9fa901924c2d80460c3221eb986d6d7154aba7afc1246f8000e0c38f9cee0e9012d54e5fb5e2de44f46fa394467f207d23d6f99055ba6b113e42ff6f5c20d9800cd00a14cc48ce4b5d3f12a9b3db9ea3cb517b3054d33c52756cd1aeee4aab53717fdf6c46476c4f845385a0b7d9e4899dcf98c738bccf2f10a059f45814a8780aba1ee55b54e418779f6fb0fad414b8e6ed2ebe03fa214eaa36610c8d3c910544236ee9272e361e200a2e89bf13aeebd01d8d216b19db114ae5665c0aa3755f1a5b6c7f5316bf37b146160a51df19ff4acbe6107cb531002bec11dfd31c027e1a74168e2849e43fccc15967944759ac46d9bd9a9aed58dd931cefdc248a326a874d33b72aa9f66fe9a9b2f5a74a66bf7de56244850be9e1b44aced0dd655ba223f4880ec35448ce8263b87735b4814a28760683d674d48d4f21debc962f214094429dbdb8d71b8a2b35bdca9fdbdb38e047a9bd1a2b1d717d4e119b3a4244c49ba16c5a7a345788cd6e59925beaea72616167730945ca48b704e3ee85e3bd5211e58aafc370b20014cec733b5a0ec39e0b2e815d69fd44e04902f1afcc1c089f964b497d879cb051d7814a5f72dd0e3390627eac77c87a8d5661dbda9126618bb21f42632a1662685ad66243a68ee853b0eabd6e2888274ba734ad68947a5575263b61ca37ccf5777df8236cf7a20b634229689fe9ba9d0d30769dc72fa57c2026f49ec713dc1874f408122bfcece5e5c1103fbb178326cf6b1d1cccd8918c151dae1c4678f348991fc9cc90556e764706e293961bfe84ea09b4a118c0ff66a24bb27cbe7a9205cc11eb15d99a919c8d81be2ec2728cc414f697dcadffcb004ab6bd0a40dfc5e98bba2f4805a7dc63b23d1287546edaea297cc4a8401390434016dc431e11df88b107625c5275861ced3b82f6db865a8f136f8fff15ac3d397d9fec5d97e1f2a9cd680b792d4922b143c18ff0d6a2f6833efc5fbb4dc98aae2240176b7d5f59302f3071c1793ac4aaf52d24996ef7c1698ca4ba25c79eee919d5b70956aacdaa962c028e9fdb67499a3e5bb9ff84053019221721b0d1ba2b51344f79db655ee1ab24af2402485c67c80079e0ec8eeeb919b5b85e7a08d49e88c7c067b95f9495715a4765dacfb1e6d68c260bd047c36c42813adefdec77425c22827a957191d643f8d662a84c4e42716efdbb36261e8078f5bf457b80c259b324c711780b1c0761bbf1dda6a25a45eb87c86b70a4d3593040bea991", "f", .None}, + {.Gcd, "-b27e4be7fb5a38cbb48d0835bc96d8cabd437d403af534f6a5ab18a86ad4eb3c043a0dd7c87bd1c9a6b5fe889e3b5c301f4b0867772acd56be5789d8c4ea643407a6ee6d5e2d45bdb511ad929e3eabe4db048772333abd7e7ccaa09ea7d3dee9644486cda7212e20c2d63ad1b1e91d380986275ed21a9b041132afa44c36e8700eaf0d68ec3363c8bd1dd2c57200799afcb533bfb8382924921349f418dc5c331526218320f7c3d1569cd95872de4c05849e257dacef3646a8ad772707738c22704bbe6b9e820cb0b53665f1afaa954105bcef2b38ff84b2b48c5d8405528916725be3c42b4e662f4556862dd0faee370bbcdefbb4fb87db9b8dceed60b2078466b4f7109e806776f496dcc65c966430b0876f31c82502e62bcf20c3e62131d9b8ee45803bb44717abe7a6d2dbbc14f462aa631a3e961f930b885be114bcb629563a586c1da961cb0fe322b2f58184c838e80d130e2c995a4fd64ae198ae8cc0bb0be470f7ed14d38e85c55451ecc144d68eb594f416008d05876dd4928d726b41d05e83c52679767c9bf6db43c76a5bcdff93652e217b2ef44da4222d5e909e59baaa612d8b36f1c71ecfa1122d0e61c6083620f261f972ea18b3be8e42a956d1befa51ec1f3691323ea489d4b8bace204e54db1623b041ae81d6424b7d26d712b81e77dd4e315d84e2dc7d5624e4f87ab2e7a88a9594c8b7d5167d9862ac9699fa25a8be1b46daaa180f5931c65aadfd8a336ea1623bd3ac6eb3873745b7814592ae3f1103da794abc078b94246ad1a45ec0b5eeb314a52764a3380b2d2ccd720d812aedcd608886003159bf2586ee141bdc22e26d3c3d6240f854bcf9c8df4e3472e9be8ba74e312139326086a54bab03ebfdbac6851d7509c92798de62a727b3fbddbf2c997f1c43659fe569960ae692c8ddbebce1783068afae05fa6e87742881571ec2bd09e674e0b27a59f5accf78b659d00df2589065453e7b3e3ec3d2467f1984c068384905a76557b42b8091aebe3de08790a4bd44cbe8ccbc0d9aa21cb7450e2e78697af6d97c6186313f11d9508540eb3a8ef5899a42f03372f727a92a21f31c7c8928a061f516773b5a310bef902c1c84930ff28453f27ff2fd9405c0dc6a532e75098baf05e19dc4e5222d3ab1dc99fb3045cb8b974e1de7c0014e22d17a902d20308e9cf8e0f8bdb31c65bd1c54b7e77b03d64323a524d069be7701be7808bff30ea279ded2f1b81349174776b5e6772c910fc11feb609eb0df724ac3b522bafd33f230222a1fbf8a47a4899c52ce2ba9f78502cc22d6be03e3a125c455329f1ad77879630e4b791bf77956de4761f133798bf2ba7f828a2f7dada7f4ae1af92062ba6cd2f659e5bbce66c8ce1872750579aa7f86171137ac32ffbf2aa957c6185538d59e92e04a8a1d712d14939f622dac6123431bc0ad57eba9e8a371a4533f211bc8c1dca188f2b07db1e8d7891e4d7954864bc78a13941c9a9f040c03b67e03a77f3e1052c92baefc3bfc3d9d2b1a4d9f2b5b2e4fcb089fe3fde33cbf9e2cab51750a695999857ad3b64e0b1fbcf5e84c8e389366e417578c9099caf74a376f7f2e0d9584732c05f7492260c917d6ea581ff57fd5407750b3b03fc5accfe7f35434f332bd0cdf0b901444a3bf952e20dd9b30f9851be6adb2769b875e884616b6c5b3baf6df1b35423447036029943a367da79368b14c0d9bbd1575749f397a5508722098fb4be7661086b87f93cf9a238a97144d57006001a8d3cfa6ece7219039b8dd9c9302c3cc3b5f30bb61b8024666f7ec4ff496e6ce46b5d37c132598d0fc395e956b622f649977d1cedc3656a415e492290e1105fc7b0dd32570a59300749343921e316d64173c546c5a9c6fd7a9ecba8b631b0eb708ff4a47b1948f288585640773c93be84106c91a1214f89ac2db43e9bc9545af09741263790805a8b2a088824ec73a3f20aa00ff78f6fe1b1fb74118d93cfdb3fad69cabbcfe434772e508bf2b4e5ca1bf9805a82fab0ae8b0ae3ecab40a9562c1da7f3cb99902909bdda204f94077938b7bdeeabcb6cfa78f9a012cb30b31de2572cf32c94c0053ba674bdf2a897f8c70c82552911f39defffb", "fc8c175f113c1f5f48aebccd99f8a4eb3355001021fbb1add20022eb5bdf1e003d9ba5c3dd732dedfab025db77e1ca83628aac79f773f8e10e96cfbefcefc7fac6bc7e5a3d968fb7e35c86ae91635f2e43a74df03c846ac040acf07ae6934a90b874b1208f6f57e3a666ba374f87fcf3cb5e7d4d92f9e9948d9f6ee766182f0ad4dd1d84dcd39a1b2de8e403eb88e466db1f80a98e4fc9977b77ffcf67c9a6b354f01d959934f31eaba23d3778e3ecd22a5e0ecc5c41b3c0d6d72ceb5855535ca1c1d67b5f78307418d1c938f6d1d7273afdb6942e4fc1ae6cccf641854220e923fed72a17f37a50aca40c84343c39c1eb15cd0fcacbd2436f42dc3ef7b0d28240e5c8f4575d0c3fd3f90d27dfaf0fb628b5d0aa31898c1a4a7ef61e83a66c8775d97e1724ad015587bb66faa60a431ee426f30c1dc3eb6581d9e2804dd2baf51ebdfa9deb8b655551313b4e1649928a1f3bdfdd0258ddf4fcd0e699ea993bfc723b60bef2f9f42abcfd148d693dbd4d27addee673bf7d5fca46c11c180d2a4c3bdd341fe1da09c2fafe276c26ca623e45b1abcaf444db6d0213171ff7285bb1135afea212a0ab9fd988ad47c43fe71021950bdd4d4ef26d24913eb683917ed75f3895af43609ec4399e25b8e1ec6e55aaab32d4a3f5ed2a3ebd143610e93a41372302f5e29dc33e8e0b15974aa5753063cf3dbb16f16e2af766c7ce068979d6fef69e5233e86b9923fba293c2c1ddeb1b250c7053bb3da15a6b1b66f9b7eca0badc2b3ddc738a7f638dbf0974c7045bf9af73dc623976bb9316781e25a737677629ef1d961a5953243adc03499efcec5a8f341c648bdcd1cceb4c1d10018d47f7e18ef65207ae936152ebc8db9d21e865023192e7d243e54e640a986639d5f6e2220991f33450eee784b7969e5569ce60a46c901d95997f9bdb4829a3a00f940c66196a5a507b86f6e00c0becf81eec3709822b1c0116ad675248d68dcfff53c7fd3fbae074c2caa1cffbcf36c6cc1b7da58684ae6a2edfd81ced3414d4b1fa838be9beecbc343aeaf739bbbf79390e903fba32ff31c51f81be4feedafabb59c1b713cd17afda82a9c32cbe811f5141114d90305de881ef3bd202ff7588a0f996433adf62acd682e63a100b19380600cf47ba8f40b191321e6b97bd1d4f506342bae8ef68068ed02a1751957e46e99c78e0d33adc354cf5df3f6141996eb5c686f587b2ba445a2b19cb13ffb129bde4819e057e4f61fcafd0a89ce03dc3a18b92064c0a9a02b80b8ae8148c3cd2ad1caed1899222c06f56ca2afb25011726e2dc2757023f4e58c2a3e5b7ad20a6d9a9dc015ddcbf168fe9cee4fc79a7306bfa194556a14cf9d804689ceb657767836548bc1bf634032936436cedcd5bb695f10f410ae800d8b559232d53859a879b566aea9eb16b3cbd8e7fce62f098fd3c2a448ab86f5c23604db7f8036fd97021559e3dcd94ab66b2d3f5b4ab0732cad1136f2dfbadcaeecd651d7d07c20da2e18e4269e65ac2c48c47cda0758777575a7593e54fc358022efb8e3ab0eddb6dc835b2a392c1bafca21c40fd2c3bf26c85c3222237f3483afdd60bce4197172d01f341038df3cb32da52fc548dd1c72bbbba09f54083cb62d47f88e5369018adb135713e443919fed4934ba906c5935d36e0f7f3c02eabe331a9d0a6663d5222ef2d8f6208f9b5f6f2c6a030973fa23b41194501fa628938dcce054e94f7b636380e91db56283a174d727c891eafcc6752bc7184819776029d94611e45d51114af5387dd11f4aeb060f9122785d9aec5ca9d57da14bc69c74e73a38b713d51cd291b68ba7cbdfba45c0a2758c1b952fd54f79daf748e3e4d47e00a5dfaccef87e5d0bee5fecb2786bbbaf5ea9496cc1670b8d9875c946f06e1115f023db445770a38d7eff75f01284224b7fbe572e76fbee3881eaba78866a61fb9102cf6973c29f25169a9520fd73be21072e5d7d320734476cafcfa351b2bb2786b4dd975580728b004c4decd1b8a2c371a02df6767041ef5c95935e8047a1867d5c3590de9de74fa8771ee4f2af00baafb5106d8859e80c8e3a3de1749f447a8edc31a8dca5ae27b9241bad8a972f5f50cc623", "3", .None}, + {.Gcd, "63c6461cb0a776ad2b5209f30c66224c18b2f1b43082995513068774438b5c98681aea5e4f8099a7ffb5f86a7fd95e1c15ec19790aa04f49e8d8ea9fe7ca2238f6a3503325fd48a6f14d3bbd15e58e9507fecf1be2df47633a751c87aedfd5272a044ec6b4c5754454839e89308ad41f4af8f16c3082e6f5942e4d6761cb459515ff5027b7550f90911cac4aff438300ad884b83d521d2ab0ee7a94d3d6e6e48c5dd60023a068976bb59d891b43bd221ec66ca325a6cd3a92a69ac8fe58db46cb451b492e0b8697929c7afb245acd9ca2ff469edaca36157839390db2d960e25a8b86686b62d57f6faec830525a7ac229194bb2690428151986f889f28e57a3f3e82606bf6cf31f8a29d8a0dc2f5d48642a91c7c3689109e4a622f09844d371dd347a4a35f0dd8b6b8a90c01831f557477ed02d0f492fe5097712aaa58c3c17047289ea4acd65f84ba95e138dc8f288ac07749641b9a7c8cbaf444c5879101ef467f5a7c119ae906705aeba396905a2f0885e4ab1b682c27e1c38659a9f66a7eb3b4a115392e5d7e85d80156e75588cfd6f42e4c3d34c1035b999f3f0adbdce3821e6c2098cd154550ec891b5daeec3fe9c2af539c33ca3510401c0d8f2b4583ef5d459c96b044416e4b937b487c78bb29ff2856f06f3326b44908bd8ae7cf3177ae3e94ae337a6a5a2678fb46434811a81ea4fe6ca599f1a5a2c2ab703e5d6729ba58f61e573510eb32282028015d76ceca2e29db4cf273b95ac427c021dff73d626706187df9044ef1c3a7629903b2f3fde42d3ad9a09ddba027e9070ce0e03e2880557b506c32dc7c2076c37b2adcaf8ea17b28dec2d81d4b7861016e0c97ac1270aa482745edc6c10b81f5cd4b76b0298b9368f2aa77808c5ccf59f511d58fcced3fddf834e6eea48ae6339db75c6a4800a2ce349790ab86619545fdccc5dc4da244d61f8fed5ffb5809d7769b3c70e1dbb7b8c9da71ac299098807a950f6680ce00fb6317caa396906b9b5a45a165e1e20264b29df7a53da3b31eb71d48699a4470fb4d0b1cb17727b6c29964681c95e7b7d1c2e1b506012a0304525af24838980de7585b66ea10ead98d56548631415a74c2ea336edd0cf47858e34b043ffed041c56e80e49abe016132cb2489dc26ccbe8e634de22a50fdbd958bdff14efcc3fa92d0f6eab7ac32c5b213b7eec12ddeba043e5f1376166837d0053b5d81943c81bde749bc572e56142a507e6ed57e0e49d608834f84111405bd50c7ea6dbb6825c9c70d4e501b53a6b887c167be1cca512ba4e2b97039b27d50f6efd316975b632d87a4b102cdb43ec89cd26f68bd0bffba1aa1f87b8049b2b62d6af54d9f814d60ce9d021aa4a47fae532fbae8db1d7d097bbaf26100684a5becaa9a818becb96762196eeea08b6100a900e15e74d4a8eecf7297299063b3f3a3d4516eedf8bd672d7a8485c975f951abe8f82f8700340ac0956bee2b1643ab8e84f63231fb560e3408a4adc80963677c56ed142e1bf88212554668b4335b8fad8e47a526680712b13010276b6595f94fa577f8baa8fece8f966032cb82c51fab6274f284026995412473f26a20762848baa83e2ffe86cd69f40bbb65b168180f097e41682a40c34003744c31da612117981ec7a676b89f2b36ff66f91cb1e57770383c209b86ca6a9880c08f606d7e0c8768274aa72ba66957c755cdf144084a9af76d726b744804ca891683bb1670b0eb101682f055bbd7324d1433fa46d51f2c548f915912891dc73b7f84526dc74a193fcc719bbb6493b0b9cd0dbe16a3f14d60cdab4d712037d737e5013bbb3e9d8ce371495d406e151a72564da22942e6ef252a79a5768ec33fecef62a0416df2cdc91a6cfbc805e4b1125eb217cae29cfe4a09c69fe764f0605835ea29061610a3bb55083bcf0967f53d6628e396f74c0d9784e8d38ca33b761da6020dc360e6cb7486747fe8f1a29f39bfc905f459c038cbdb90e7d2f6520dd66e38ea6b334648b65989f8907b3590e09c851ea4f8acb2f34ac541334e6171c01ae60ffa9a62d77de5accf2be7ee68f83096674ae7697675d850d692c5bcafb0d3a1970690c547ce0ca6de3ce3fc8e361d74ab6a", "34aab0d2bc1b48f2b8c57f272c8f5e3f0ad307cf6791ebba0b61d144fae1f51b97909066e430de464dc35bf201d09cff3c51dc8b292797901c40672a6ac4b3c9001796e1d04d459ec643431174a41d4e8548f5042846087157c43f58e168bfa032891649483c56b2443a3e9798e41ab6b3d53db1bb7bbd6e48195b72fb8835ae4324d1baa8501ebd1cc9a8e0bfd8db9a47259a9479d9d10eb64eb15e8ded66f3283401e361b891d1d5fb8623cac1f0e9a046676fc331fb18fbc83ccc55e5c5d5b7640ceebafab9283c08e6f89f618df7dc633ebd0e8135229d180837e60806f1f3179c7762fed23f866ce0e84b881052d7418e57950e63f517dd82a9f65f6960b5b9e7bf6f83eb0ff1f77783c408ffbac9cf2c428fcab06e2cb8e4112eff0612199c6fb20d0c62507e86b81eb5d694421e124f738abed414f30f0dd61e4069584f35ba76ea09a8d47f2fc5c3c16d7a1990b892ebd136428b67f9519a53d681acf4e04d1b1a26fe831815ff8ffa180162019a91b76077a04102ff38e724fd0c75fa5364a4bcd0ca8e2a77919d9732bcda293fd2aa46fbee110ff7a8f3b2b4a41c98a6c68e24972a3b5b22f571bcc69a2581da9d6520a6cf59a9779658c32d2ff3690018afaee5b1bd44091ec0f0302de0e8550700e8b86dbf04102e72000b2847db44090084953ccae9efa226147e9c08bbcd446e13a6b987811210486aa97e58b97cee31ef55951d997a4b9bab5000a1ba862d713610229c873a83f5a85a1f9c0751584c6305f36d103c0eac0959606c6cccc53c18415e8f57023be72c9d81b0cc9342f5479824d6ec55e7c69e319ec827d91ec2adb54829d4e690cb589ca2dbd156f18d9ce1e6f88680d58a92fa5b0caa00cecc286bed61fb580041bdea2abe8c48b26c79a6605a160f8f036f156af05ec265056d612607833992d228df7d6b88e3c4a57816442f142d02e7936d8f2341433f51e9f6f7dc4a4a6329bba95dcb59d3f5a5592e728f243734ae9de15769c1058fc48efd805d1c8b3a25dc4d903d00b0259c9ac018625d211f16d553850e9b640932664f4085175c955003bac02afc7eaea1553207275368c992af96c193f04de68653e41a5d357762a16eadd39b5eefda4e27735e1fb167e690c1fee2a0b9a2a102c58c10514f52f9ec1a0558fc5aaf335239dde05fc23c5120f3a5be4934f94c1a9f5acc3145df71c322f7132ad1643e403add6d1d4a30491adc1c148ebe762acdd1025528ae1e266dd194c94eed0bc3002d6a8010d573b1aed432828810c6789aa7bddc012e3ebecf72ce1fcbd18d94284071a6c55dfdf8644bd05bb5c9fb3301d3206eac9c884ebfbf5016d1cd67b62c3470fcb4d26f0011fe25825d5f4debdb12a4f1c24136722a75468bf41c6843d6ed695fc7142aff94f13b8af2f53356b70edb1f79b635d3c3e4789d927e0fd38b127e7aa1dd3903815e25e22d5dcea5ca3d79caf22c24a423f51da80c922a0d369e41b4542045388ca130b43939acbd2834d9cb895b6eaa22659094ae34576613c32d2e7b04836e9643b214439726edd67054067e1bf75fe28e5982954ce19eaf7dab5ffc10eb34e054b3039c1f3ee6cae8ecf5444f21e98def256f66066fe99750fb4011f1c9cc3fdb1d81407042b75772f03e98dd751948a8483841a7446dbbc270143a2b781c7c213f722fd89b7ee14c9933aab1400b58d0e40b001e18748beb9b3f3f103a8b7d61ddb39ddfbbc32d0e0825d848378f95cdf9c4de476badcfe2928778d695b2fc25ead040cb3462c2ac11d08116bf58abb789e2c36cceeea653561a30c782c0d0bad17b4534cf7a74ba54f989bd5827e413b9d8bf503e39ffeaac9ea056de61b2d1ccdf6790581184b9131428a0f5ca97832ea9c44670d1bbf5ee9d59787c12e25db5e0c695ee1b2ee2ac8bccee21bc49c489ad9b9874cb01f7cbbf0555b45758db6d25290743f2f4e3a7e1366a8d4ac01573d8556dfdaed2878e714ef5063174a6f9abf588a95e486e998c6831929e13f7b46ea4a2bf95cc96b8647e15851cd28e20b54999e1865c73fbfd5939a510fe6f7ba119e7cf64e76f57cdab76c2f82c55cede958f3255275f8f3328f944d91", "1", .None}, + {.Gcd, "-ac97dbc30d204462982784f6654c73db4bda7511b77e14b1007cf8074d5369f6f4c070391f312dd0fbd45fba7c85a8e7aa81e0fca5c322331b7b04a9b8402d61b4f80eda13aad0a56194ced4c64755e89e4fb7b74154e1803408fd46af69fbf41453a177d49dd675fe1e6a7db35b6526548b4690668e1dd4bd7ab5dc186a71fb3f7521f65609f9d94ba684ac62ea355c1cbd552ed85d70efa86c4a2dae7a44365037a5c7d7fdce85b5a7412431916601fd9e9c1c3f4db3835c4288c61bfd31e1a99db359c320b426fb5043bac043a08bd10c9bead397f655cee911ed19c53a3617a5c00f21df68fe466d852ef44ef32182d7c0b46327b52c817daf981787176867a420d728573f5b34652d6d799ee0d3bb1fc2bb02ef78ddbd48679d2e0f2abc320e5e566e882e63b3f03ce7f073dd3de178773950ffa97155230696c92310ec2f2cc6ead71aec65a17e73355421cb9b654d9ed8376e7d0fc775820129b94d788bea7f63c109f5abfbddb5ddb6ae06f01892b73b85d2f7ed7e426ed10fc9ce0262b3b59f22d9c4da3d9032bf9d3d886f3fc166e3b304960378148f2035ca389c346aa1a4a27087590c04a5ac0b5e31b97083ab02510d042eba02c466b41c652652ed80568e8573bc097e42b6e404a5323dd0e5193af60aefd970581e997d12c842bcf0fd9599988dcf2c0b05b32cd4dcae881baca1ed040cac3f3215f9bf0022a484b6061dd737005bf57bddb49bb3511bab11885c8eea9c97e760dd46e35d1707a8b3f5316316b78c11880979928211cb7b8bd01b392b7e2388097dcd54602f538171254fac335bda893d0ca113734fe1d8f60fdb8d0530e7c26e233154d78b52688d8c76f7732a3ea6209de763da6f3fc44ddef94cc4a1dee9ca86a2ddb47acd71b89a24cd3ae60c6f4db675ca34be1bbc6b14b1ddff7c46e223b823fb9ac4f042a3729d53e7b7379e48fd488dc0b3800e4ce44740aba88e6cea14bc53046d552a69ca07ae736034e810e7b1ed77aeb506e5c840fcbf5906377c3310e365c8024db8c0f7005996b6ab090e461614c4dfc2e97997922bcada6c40cc95d01a6a788957f5167f4914a90425bd99fd7dfede8283ddb07c100d120651c6abac5bccec78935d1448d32207a0f3a3cdc88ab6eda0bf5a3ac18eca4bd784ad966a7f7f7c647a22e6d2b68df7a321c30559290120363dd94d8bb87605b1cd007ea78af3185cb9f1cad374289db0d8018a086275a98652c434e7150139c56529857da949909bc082f7dc00b3f2888b73c25a8912fe21bf80d305b8a1f9456d909d3465f597ea59d40806b8de50144f3b003216d26e9a20235f7b859c18c32a1ed5f66af9e8e3500c443de6dbd8bd236d8300c21ee916b25b68718e3ced4a2fa515c1ead2c481a72928d01b12cd4c7b006c56e5267b4ff4f5d348fa2fb3fd8abad3f296bfaa382148271cd2517fa16360742c35563523d5dc5b66e50b928d2ccdf8d2d51e805316bfc37915a4887bc8a9098bc8148df552c55a98627cd07be80afffc68a667d5dcd1353b4be6276423b59eae2abba507d01d3dc8f1021ddf853c1354d4dfe5add8405bd3f7d287b711a4dd3109d3a43c1845d16460da3693d430afc737bb8bb20b6ddecfaff04461a730a3a053dac0d82bd96d4e3bc6bc1b7f0752dc86d3e0f9a4f2bf4ee003f0131627368d6549efe146e0ed888e2d6323123e943a70ff08f07f8e83ca20669f7974b7698448aa73d7334d03218bd08dfcec7a4abbf1484d0e5d32cf61ae835c0fb178f36cdfac6d7483f3dcd02d7c724bcd87fabd325f6202522392f79a82081c5ebb49119a571438097ab47d54d3bac04f1366e95a33dd59226c466faf3e7a771cf0241abb895dc2a44836a3b9a9e09fd63219a3247c91bf3159b64817f2ac3f5e8059805e8299d25ed72dc11ffda57eb0d27c584e977a45304b537fcf71f9788b65ecd3d3c456fdf1d9ff7fefb435dec7ca11f9a6bd2c2c499d53b05cc274ca47b3bba5b0dbbcbd1f7522f5522b9753f16b397ecc9c28874475d0c289c686b3ce96b789b5202244009b1b22eeb67a5961ee1fd29b579ec7f6dd177c7bee18ee768009aa5324c1603296e43f1f2d642b0d96", "ef423fd06828986a65090ec8c7bd8a8993b6f0a60f047ac46df82f39e527055d50d1b1c5c49c3570eaa68f34ad83d222a203df55521baf1de313916b6840ca2383f4b992210d881f243250f315129608501dee6297927586ef9fcaca07d7b20fc2834e319e195448da46d3a9d049f8dbe6d4d36794b45d14279e79c4c8db84951894bd944e801d4e7756b1bff54ca6035d38f24d39a7c16305e2a1721ffe058efb2820fda051020a6d9cadbf8f0cf93b9c4be9b1e2e851fa3d723477236c966ae58d49d5573715ad54fd23201c67ef86594bae933e7abe4a06cf41bcfd50fa924d632d43c91866ecf70e179901227d9d693039553a3c5fdc1dcfea4919ca1d1740912cadad4b0d0b817b98721cadd145cf28862badd144af9ea1052f8f143b567a4fbf24c9395e556fd921a98606a9f4b78cf8e22d74fa05b3f8b6fcca714394d7617e13f39d747a9c1e3731893d4c6f312acc6a4b85726fe26ca4a8bdb0583f2b43d555adf2370b1cb549f87a7edd01a00accd48cee30e7650db8c47458119e6e92b9defe541e5cdd901ea3d1e5013f6cb9e54da460dac15fb5c5c01d3c22cd5024a055ffee398623fe572f0919c2f084e6c74d9c61a17bcf665649be04024154054f4eab70e42f99dad3ae5c5563308750d92b0b46f4f1057338814439acb6eaa51c4560a4ff5feccb22fda0e72ed9eb5d0672a0b2e0c13335d4da79684c072698b3ff56783804e19386a1b17797dbd6dcc9aa3ad5b3dc004b5280fe7bf1c290fe7dafad5254796c1f4d3ba7dff0d55d042ad91d3d0f06ae193abd02537d13099980012aed9905206233504cefe099bf6f9717dded7fe7e1da0aed7d4be023ca88df26a446a7ad11c7e08cdca2893f96a7f1d3343cf6d277305caece637a30832831892d6c41d2353f1283253f50488095ba6eaec617058c4f8be271e8b46835b8dddc3ceed800051055c34f5146974ab2df013e38e8fdf6038097331f41ccdfcd3065768cb885be73b41ff0098ad60f2cabcf597138c4016c0e1f5d60f798026226a4445bd36aa15049df4f140de2b61f7527aafa51fba80a32400e31ce68ea3c4591ef99b9825469a1899586792c63aff31eaad4879460d3adbcdb38e2b8e6988c1c62a522dd0bce3a32e986e4c0cfc69c1cc9273b48c518d28a46d25e61dc7511803df1fff62db92ca61821965c6eb69c30eafcb22ca865c9b2f168d2a36ad3d05e98eee931ab8013727a4ca4408390768abea532592e3e6a9530bc592044616945e48f2f02d535472f24507b56372b13ed43df8f4d6f4f5b02e7f385a87e3e8933aa003e24c4d4a4336ee95e1d577c54fd5291b2a98b1bbae951a1277a803d24831200901babb390e43583e00926aad64572e0fd50041476f2f417861474768160c7adc657340da7a2bd94cb1eba191089dd97cfc953a2bfe9fa28bc207f056b205c5b5bb5591f6df084847b46282f762cb77cee9f9529aa406670e29267427ebb3f3a0cf3ed2304be796b422de381f4103fd71ff109cb248fc1cc642afa9e0a716288c1880186a0217eeefa9c29d4162ca97c0f9e39987c39acfda7c560941e8a3aec509fa3ccab4897b2c0639dcb83b2b6a67aca215184de3b8a1d5c4584b4d65f0a9159ff5842d1143a9d30381a1b4ec7f09386fcee4676049f57a2235ea30f392abf9f843b0d55cf6a2de1679ce83b01c187253ce86b32336f2de972b7dc59153c1d2ea36d529d1d5745b6025c4cda3dfca1cf6df272317cc60d157e145044c708b9db82915b76e5a3577a5f642635eb882545a62017d42be61314e869ea2f350dd3e2dbb7b82374c586d88dae890f7b39090eb02acf88b12ba271563f676055381ab5cd0eb154ff37c08d55b6b95b1458bda6b7ac220ad45b0d86d8ba93131cd48fd7eec2ea573867551bf082821d3ffee14617fb7f7709fb8482eb4dddec6e34af6665f9a284da6a4c7f10309bc1adc865cc5c2b7877c6d3a9e1d322a79ad68cb04e605ad0b6e97022a6c801efd68d275563481823209faee631794df3c2b9ed229dece01240de4ab469991359b80ad2e921892c62b3f1dc9dfd42e465686e445a31295900df3293443a8f4d17aba85206e2f7e4819a", "2", .None}, + {.Gcd, "-1fd59beab54243960332a8b1b43c2c3b2d3afd3136f4e9b6b27bf3ee6cd443e42a8a4bea5c53628562eace44f1817d85d2431669f18ae9e36f09c0bc0e11fa4c8a57c0f290560582b6d9e51472cd1c6eda17d8bec667a0da48679081861d127f9a05fa42223948932ceb00248e425d9f8d42c3e56cd9bc36bb8d7f66184ea3f8d99cbe56b8d6343e2e3ac87519849c98a10a10433501d702aab684c124432a88c8421b235b7a14e133af393bbd6efb0bb6f445258bd3ff74d66bdd23e819c6afbb7f45030c973701ce088341e58a8719270992606b1870fb782cec3082476991d6307543162e57f731b68ed39ae6530a43d1e4a4f064bd2703ade2a87b81147d6e0588e122e260201d5781b7aa9d265f1b7021f9cfc7d1202d2ed0d62670ebdf4f5494f49e3db010b329cf43a23a7157a256cb48c37728855bef00535927c1f3200bea83c40d758cf30054e518fe7ae4d35e2bc534471627d6148707d81adda7b97d44a0d677743420b3ced4790bd326b3d3c05069ca3e81cd2d48a16398a02ce8cd21267f0f93f8ea76cc79171cb2a5b4939ef94fb6fe14d9e3fdb99660af99d6d76f534e133b40ec78261c65205b6a42de832adaee53e32ad3e2df48ca3b0a966a9aa840f7e673f3d680a7212c3ba49f1afde7773c4180d9d65a5eca39e72fc8d7f39ebe88b178fb7717675721c15796982c5f82d9c82ad30123b77373bf9bab3062e97956e52210197421cd0015c49cba7ebf84fb0bddb663d3b7957625720bf0dd3feb8bc4845cdf36bd1a9714e9027746ca8235071bd8e891a50f35ea64debe0a35c48785eee306932ca53bfaf6dd9ab36453050348a85a17a5d29e08e1c7096c250e90bea66cec02a2ecc0f242dc508468729b6cb308a193763c9d17eeac231c9f61afea9db763585f5d21549daecbc8d45fdc173079f257a65b54bac841e8f2141e5cd1a8d6edd69253fa1066a5a5a58835428de41d147c2d51b1b40582204465005cf9f302cfac6bed09782bca8f96911010df2f22cdd7e15654c201e55eba1b85988557f8a57017cd03f7c6a06f388077835251c54e2dacfbe3b10a3f1534b5f190f65fe6e19d24f452a000c38516339f9af4a84d8b9cfa14cdf15b0a649145d6aaa07f94cffed1002d13f446874d6ecd8bf8e63ce0dcda8a26958db9c8dbf83460447573b7076982fad04a6c5c13d933721e28e87043d8a30f9574b448ab7c67c43bf5015b3f649bdf81e8720eaef19acf7a6975fc825a7b2c044e8464d6583d3a0d63c5c63c5dcd60168faa51e2653676e6770ca70a44590b7b89a7ab7326913b2e6868b7773c7c59e2c226e9de1b5d3d6f200f66676e0c42351a7b565c87251836d11870ad98d71ceba700376aeff0464d24b3a3ce4e91fa8cf7bea964913e92d177bfca477d74efdf94f614873a554aef100f293de5dbd4cd131bba4ecbb684ebcd6d506719fe23980d9efd3723f157d9bc54b95783830a2bc43d74377ff6ba15fa0a2e129f9ee5bf9c00fd1d1bcdee4126d1166a1f0291fceafe5eb8b3de6847d70d7a67583c89cefc8231e00da010956da34134466afd7789844c938902f9446fadb485200edc4a285c674d56753aab80cf03ead0281592ad80d6632429d24626d364aeebfb7078e7cf45f9a0faedd8150abbc73f88e063ddc44cb23415164d820bf83fdab704ff562e2c594e9522f498d6329ab2b13e5a267f9c9ec4a0d41034556d06e97a6017c429ebee42dd65d108811bed1fa0e84dc168ec8fdf6bb90d7d41797106e6793e60af0880fc9a1449c54c2c3a15493a13eb9b3c7062494412a774d718fb63a5fd82a0cc3a578d2c971abb21ed9e0e1d9468833a06d827f71daa4efa5341d29e42624f6626343f3709793a10d5bfc28f468ad7a9cbd9309857d8828f58884be66cef844f65d519ccd09b6352638765640b0cd912a8f56328446b3e1c1313da61c7765051312f3f7d6eb541af41f00d368b7b6fe4a010b848c7d7a26c3864d36d9e4c5c915cb1aa38abdbdd20fea1f660758f56c17a9eed23c30f6ac7e575a0153fc163d2b8ac6143e304b46fa39d43247458064066a232ecb7ab96737baf21141c47019f761ce9ce5be057d53b3a", "816d2718a868930cfeea3b2b12d22453a4347b128f19ad2f8b4182b1d6986be78c8d4f2533c8c30229449a97327254fc7444fc8280ad970b0654ac0f192cab46ca2904c1be8e03f9982c9219ceeb55d1ee47c1a1c5933bd656c15c75983ad4c374bbf67d2626d583a8e36517b982e10c375440b2894f48772097fed75c73065d8b5aeb63ab9a074315041bc7317fe700510e1b30927d256771ee855f04019bd24193a64567378b6fc9db72ed05c2bb2c1ce45aeef09f967133f479c21ff0344b87853bc312d9fe789d429091065bcc06eb07c109bfa39bfe68449d2485d3ddfb520e80f7f95f33503c02a52a1594296557f34924240729cd69b6fc42a7316acaed5166575a33457fee132898328beaf9a143c39964419fcd9aa33778194272cd94369235b732aadce236f6453837ef78e2eeef7980a37ee3ce389c3ab078bbab3b3de4d423b908ea817f42612b31626978f6d83c2c2438c41a8e2b8780e544b0a06400503b9a5eafaeddd81b0e5d6cd76f6cb6a22edd3f7000901259b0c76bf1af0a23b7821b7e01da1fd4035dbebcb5c4e9e20f0902b0158e23551c73e8e8560a0f3d24fabbec9b91c8c61920796ef0682e871b2eb2089e44eedf847b631cd3936b9cab0344c5214cff33cc719d262c4903fd32dc7468a51d9e20c4155016aa1898554e0d9a237aea1621883a4a2f7199579f29069f3d8003cb2f027ff3487dd9eb143f276e11154c054d3c25b9cb9a4b19ed3d8321290351d70e290257b38f6ceef143ad6362ecbbee07f7cd076a31fbc56d0ad1bb101377bdcf14acca5725e3b25ad02967f5cbdb6a92431ee50017d71d4050ed12c288c10e6ba3bb7d4a0b391378bea3740944e99cc914976f0a530e22616becf0573803ccdee23b151d12458f91a2d887a08fb77c0a237f081a59a986f298177e8fb0c46d9aa086ccfe93b93f8a8d187ff7e839ca2b8b931758afbf5163b4ec0704b17b14db4bc40602d2b0c5a962a475be71393c1d90eb37a1c95f704b65d981b093ef2ad162959f3636416f7f856a440021626fc8f9ce72e8ebc9778a628926e69f1d4f7074a98bf53c1d4e87e62bdea445b949655effa3e0b0111b9f475908cc3859b9b9d7e0213862518dd0a85bdd79dee05b2641bb9f6e57e2cb7f53179bc270f584ab0d1c2ae05655a70a49c13b843926be936391ece5373d8d52b8b3da1cbb820fb40172834d378185b1cd7789cd3c2d134f79a6184669d273cdb9c1540bdb70931d1d8cb2e54283e0e31d91aa60ae8c155a32292a50f36742df4f346071800c1967f448bfaf240e71c958591c35de9138585504f341ec8d11e3593735441e3f5ae7d057d13f00fdec9eaa1ad9ddeec6738304c60669876fb8841134771cf588f0c9bf9aa44f7a964c122d01f8586e99dc1e5f3aadba2331bd178c226aa6113116a18c509259775d3cc73f2f9a24b29913284f3ae72b4307d9352930c5eedbcb55e7bddab1e33af74204ad6f9869bc63bdf7da21aa4ce34109cd89cc22cd27d1bda48a07e42485a4aae354191042bf3bd3429e5d6f1dccbb03f6f1db582af82b5c868b64baeb277f21a388f227cd3b6ce43a03c3fbdb2e82d282e19c1cd35bf66542e97a62a1cad265491359ab7697a74c132696b3ff5c4248a942fdda236412f62136e5278eeb46b6a0778ee95b5dd6595be5ba52eb8d8b8e63eccf1e02032e40cde764f76ab93ee2e33007b4b2e11fdadd245bc03a55d98bbdd2e242d20cc469708527e0d1d8199959a8fd8f773c039743e0046a0baaf04bd1a8b6958e2defde15822966e9b16aad7477c75130c3a88dc94fd24d44416a61370cc8f5765e2c9b262a21495fa453f008568bd6f09b2583d11c21216172bb34578018ba6cd9f7e10a2ab75920dad50ed7ee8d7df6bdfd8c1123ec2bf86971019ad176fbf0f3c577b4d04c9e9c4255811c27ff015b7aa6171625b43ff19b9f6f94428f9cfebd7d43fb5d892eaae06e8fe6380f3d08ade3140b5c20c0cda64e1f8c86cfd83796f59a760610bf19d856aaa248430111c1145535bd30bbaec4bd4213df6380a66ecf1b68a2a55ec17f3ab39b116285828d288fc33684e4b622cd262163655d0c14d2ca7a48", "2", .None}, + {.Gcd, "fd7ff60fd14fe85ed0356c0128875c384cc23ceecb90fbb9bb0ccf962d52af4a383c15be7a8a64de59a7ea4a427abddf61d6e8b748639f9925fb644cd2ac8697c437058a624da6a00469c73ea03e7dbdbfb69698b9a2023318420978d3a6c2eea86164c97560827dfe4b050bf7dce076860d04dcce8a1fe90d83777aa6734173d0027edc20b7a6b727dc78058571e99a09af835371fcb2ea10fea8acec704afe664f87a761395360f9f9fb11ed8b5594b375814796cbcf3be62174ff97a73aad0294852aa719484b154e6d4bf6a87adc1b19feb902901538d572e079a99c3ba6ecf084973b059cf4a8ac76d9f75f1b3d3ce425511b6c51fb6807479976c0e4481e982e64308ba6953cd176501b3edce34fdf750f32e8f394e5e83259ccedf2dd01f831e8d62735f4363a8fc4245e67797a6282862c6132d7bc7226b202bb017882bed89bdd43a859204cdee2943f6d587cfccaca3a9c579665205d9240b6cfc057271e4f9dd5fed8eedd10d154e3ee89ed8b383716f5954df7b2a217b4049c6e1c96f29f3dce6ee7af24f1b582650c5a0ebfc780d6680ab463b5d2aa8accf3c9b57de9739c2f46fd0a9fa275869a7ab2700b80082e516a52185fdc4949e9c81be83611132871c494cafdf98fd186569aae11a449eb28512dd0ac1e75482bdb4fa33d77e8f6d281d0223988817073d36385f19f5ad7c9bd2082c89b2d3a77a02e5c0ffd20a66936645bfad7f468ebfc2ab06db9906eab88881788e7a328402be6a3c6e069e555a64dd68f4f3cbdcc45b09944bf3fde504ba7b35dc59aa2ec89d9c7bd63ac6a942fd4200f312e717fa51d258cd163b347fd9fd7c49db149f45ae0738eb8afd568f30da04bffc4313ee6dd6a3d42b286ed663132bb97f2fa34ea82385a92bf2b37dea08c76a64e2e5deaa216f6346e81abec648bd5199f4819870057d140cff4c02cdfcd8b9496fa94fd0b9652b1e23aa826d17416d9bdb641dd926fd0beb3c0abac330fad795fe5c6e20382f4831f3376262fa172aff814c280cb3a8adc0653e6af282d74cf51ecf40591c33c5adf5ddec0e4f80d9cda4414f7967199f6632ae26f2b059b7c71893ec65ba18a4b9fc35fc9eb21b8db6686d6e654b8c3fe920f33fed3ae2281f1b9ce68ef79e412457aac0e916b835a83d26fb2f3d27d190cce1d469b15d292080098abde1d95d6a6f41b8afbe5183bc86ead2f4d1a74ff1ef386bc19b4d402d1d295518e17a41a7a8313d1e1a2b7d8c7d2521d3ad766752957b7f90a542d442aad22146104e9747ed247c6ca8fa0abc4f873bcd1e2b9e6a54097c580012f944c5c903a30097f79025f696bff9e6f381c30860daec41499ee451ba52cc34eb85d7012b16f4052ab580f54a997efabd368e808da310a8869cd43ced142274d77ca49835380eb6f8bb0b5c4776831365acf166b1d85c9dd7a59763f45e50d3b398288e9af01648c23cfbb46a803e8293fbf7dc0e68df3d0f3696e9c682ee2e3c82a3a0d48dffb5396e0695b94ed16fc0f6f0d79efd216e7419eb53bd6192c31f5e3a3111aa9deaf558809f1fedc6b084b7d7b073c0cc6d7de9734a1ef2dd795853efe9c71b6636994db17e09da34f7d728fa05fee824bb720443f7be85e1867b6bd668f503d8b3a85c929bfdb42509004e0fc68a61a46bf0e8c223dd2150515dcc0bcf75593ea5f9a9c35278450f0a13ebc60df14001e84739da8917651ec54abeaa6749dcec8789d3753aab3ba4f82d15d2f2a168bf1f50706763eaef7ba361c151e65d6376c0ec1b6a62fe7e312122e6ff30ba4b41bd1227d75b73c3bb2e8c753522d5275ba8c823d22cd544841a267348b57ce1e863f995d6a6398218e868eacebfe0bd19703400b4126b0360d719e61c71d6682ebf8845b687aba91cf57843ee6e1bbe9d5445196e64fc5fb9a063be364effddbf9007d74796d8169b8b62cf8f8582d0cf49cb9164696680dbcb39bb62100c04575698760f4b4eb883071e29ae7f0bd4e5d8ffbfcf4a1e52929ad3f3a8572682d166b4f3ef699d59affd0f672d580e29843d7ed270efab79066370aad89e78f2765b1841f582b6cd7740f5b65a4184c83f44776cc0419efcff20ddb48", "ef09279c4045fe8689856bd6beff6b25fcf519e7cb87664183a08a1fca5a0e0f10505bb26fb25e7980625330b9ec8733166dd92587e0ed38bc344d35547e01134c17dda90eb897a1b9bb56b509fed488b110353ad4ac61cbcd19cde51d2b50df11352c7293da0a57f8e7680c23411b749ceb1676af0eb26971e401f72ca3115baae0ddcf45d963a41182a37d07e339e996f6d470315f3fa5415749aec6e4b4edfe818379dd3dfbfb4b20dd65d2c762190c3691e9db72a33e10b5450860dcb1f7ae96e7234140cf87d3703c38e368662f9c761739c8d7b42da7eb6a3b49baa88fb75de2a1ab3b950d12ccf21d61926668aa72194c4013489db954de75bda4147aec48da30da5e6ec7353e6ab2b2eb4048d42e33b601169866b9e4e687fe6fd7d39485d63973a7b82e4eb7a695c01925e77d1eddcc2d4ee963c69509149b6f35ab4aad09210ed31f3a9e5f9aa10e960e635fb9bc3380264a1c615624c8a53ac0321f5f0be210df457ce38a37a42fbcf21e38a9b7eed910040116a72becaf47337ed830f333f9585555557a4bcee22eccdf7bc5d4b846afd0a1eb280f2e00e9e466a612873c309d6e1d9419588b2503ef38ddd077dd9b6e42e62c4ef57eb3b4674712fb7ee07457a6117d7999ba5f7d9c6b358d60418009d69e732c2c160fe1430fd87d068683f4a87e9ee01e0148b651bfca6aac4bba3d837eb118af3d5d1c1e4dc35275268bf75b28ad3dbdb70bc28e718ed9a9ef0812b72d73a936140c1c3d5364355d11d623c05b1e97ba3691464f7d5d4810ee8106aa6586878cd619f1987322a131dfb9cefa1b125b2495655527dd44d1e77d2bbd009837904e36067bebb12e0562d2084565d879c5b7cb0ec7b72d49cc20dd916883a7cdbc9a734b15c151f577b8ac177612a043bc323bf854f08dbbfde5342daf90e8f4ebcd73a57cee0f788a4bf10cc858b4523be68771e78c0935e02f7998f4e211f02f7135bbf4aaeb99c71612b90853ca48795910ede786ce79677c436987b07e63d945c53e3ede746845e47d11af4f284efc91b0d651b7c2d309beaa800b04a737e0b8fc474e942cfa78cef951d79f9db409a6d789ab424cc245cf59f9885ed21c801b1cf73b406363365bb8efae57a3ebe5ea08c1c164bda264c85197b7be59eaa8986c48036050b27fa3605c70184eeaacf50fbeeff7027bce9cef598b297bbae7a9728515e44ad35dce319a4d6e84dad808132f81d4ff55f1736fb6cb0b1ca1cbdeccc2a9f9f693d5a1a412bc8f4af25a6c85f8c0bfb9016d07e73f6514d0920a218781b64ec831d2783548e85702d4702aa3a788ef59e0525f0c297d540c46fc0914657a78b97fc74b8f0ca144b8e705621a040ed0da42276151d294a12b634f8f9bb7234de358716bbafdbb77f0ad4f2f87415a89e66631c10c4662ccf3de315884bf7f5dd4ef1dc274d1b1a47db5864b45fc3e370464e20c41febdabfa1d0843f10f241f4f0c8b90711e2343f3c3b0b3494da882127617cd4ceb8110e1bda49dc71a8608a4af665ab7ac181b1e81208095ac7c09be2b760b33e4ec4634c95ac1ebf81c52d29602ecd771302043930d299a49f439fba375d43c644bb3b08cc571bd812b1cd81a62704de490db1862fb7fdf505bc455141a9d57ae903d2d0d95a6da5903bd450e82bf756e3637d8e692704bca8c702dd20852557932cefdae346b3c061d19a6416cbe9f43ced3c4d39cd64805e4c7cc7453da294878ba245b3267ef72e0ff1f27038806d1f257729216e26a9123184736cc546d639ea18e5f2712be47618e7abf2edede0eb3d21879658f97fab6d097e652bd119217d1d45a18f82b0933d5c61bef2a93e90d12a1692f2286c79bdaf86b03db14ab80c5d9d2836759fcf1ddf20cbc58f2fe45ab4d13e30bd4811892746d746a3647069ca0d2d6e496b0eab8c4b10b91bc0e10c009852aeeb9134921187b2718a17e8cd6610b12e4ad56c8814d60e8455e3756b50abfdaad1dc6db905bb0bd8e023b6c55b37b0c855ddf3877bce3c962e6e8251302120f73aff01ef79a71809e688ce0d6346776a465c967a49f665d6a59530daf260bf6f58187dbb10334c8eba55cd81c720250f5a4", "4", .None}, + {.Gcd, "468b1a43fb65e3cbea5fc330b4f7b4879a789e68a301a7fa69354f1c3139bb69dbf2f9ed2a938f072f4d73d2492d452d1a17a419d366883d9e22defdbfdb98597eeb494ebd32fb330fe9f0efea17f9a16559cd9ebebdb3445a6c83f46e59b8417c627cddbdd265411fc837736aacd65a8e22f6989827481bb7536e6a00141bf7e7e6c5c785dc9184bdfad5dc610301c82f1d4256e012e89d27b696d23c293699e4883d7267552693371ed705f0d04b2a429892b2bbd56a55291eb72b099a7b79b2d709d851b6bb4de707425922122b5dce6d25b4bf0228e7c3a9246e6d695e99cfbee2cc63af7d5b94a2cd32efa3469905cfe54ed935d4a91aef50bea230e697832dc3ee469d5a5babb8c13224d7ab94428c122433e2adf10b9888623b767b2312373d340c26490536b246677c1f380bf29ae2c1e51b99f911b20c49364922091eb80a5d541cc58822a917162e736cdc77e3d2352976b846590d732c7276c94e68e288b762e20f9b4cba4c5ead31e916242cf05de0c253de2e8bcd8c3c5632a95c01dc848b194136e3c159f41135e24f629a90fece2c66c750314cc47460626af4e646fe0e23c3c215341e8b0c1e304f34dedb768fa9a697666af4aa535c396646870444cf384f2b8fe475f2ca1b1ca35ca90ba2d739d071f6ff7889816ade9ed06da4d6a8ee4d6f079ec2dedf9cbcb6bbf001e8cf7140aeb7e135ca42c4aab0f334aa8043f875ea42ceca9ea5f7ab0cba5b7e0514b95a8c4162d33803018e7e29f4bbbe70433dcd757bf2edf5dfe70287be2a0b40cfceca86e0809f5e5d5c08b801e26440deaf31fe4712420547634f7accc1e5fc308c29ecf0523fa3353e9ce92d0df40a8a7d66c9cb5fafea9a64dc5c012029964f404ca178803ef4078804cd5eccb4710a0a8f8947551065598dcad3a693c058f7133c32d5324eb95a54c24716ca90300451c63715f3a5994cc72390a244dd7a7f9d839d85dfbc6c5a717a3c324967db0a417f1fa0ac0f565c8e2b0808915362b1fe4f52bad90faf43c1ceeae9d66ac92f22d808236656d7c52f33acd350a8a69e6d2494b252d530540cdd80add82ef487f4c66796ff9f1aa1e43dc5771a197a41eddeca63023029a29816ff8d10fd71068bed66da5c2c456460903cda740148b53ac6cf7ade4d1d770209988c40ceae4ff69e48c9b7e62df65338e4e8505c5ca97578d856b2e3956458340c9d7aa2f6b6198f51482cba3261a9a780d5d5a7c06c574e2bba1da3a5df7af9584af717e7d4da80ec1a6ae1f527ae95f76017d6f0d68aab7e54978a88f65bc29598e1d18fde4228afdf1c1afda30c80adf37566c281aa22566b90e2530937f7945e487b77405d8e0398a461c021a4894511399390d2eb6c4ffc58e14492d7a2a86295ba0a4e462b57d638f2bb5840a81f0bdf03a2acdad98650b186fe7edc19212fe421475bf59156be98760f88a3b3fc47e3ca79b95add0c9a4aae44beed2badbe2db2a73b96a1e70181dbe0ca46450d52591bc4721176092af48f0895ba38817baf903d606ad7b42e4540d93d040dedcb4a6b80f78e189e7407d872ed8af90583041cee9b987a338bc1cb76db3499eaa1fc3440b0656d7f2aed5a3aa0d6f58da5a2e3eb72498d5f301db5003123c65a5c148b0c1b7766d71102fac93cd8a5c67296dbacbb09145273575632c0fb0881a44b558ea355dd83f14ff0bd234470b75ab4730c41fa143374e707f7186a0f24ed85c3fde7bf594fc320592c9af90c2e82474414d6aa7aeb6f1ef40c5420e6665415472787959fa273d2d2cd4cd14672911b55dc7bd8d4619d16898d55468871cbaf24a916c411499657de7059889b8d9ecee5c8d6b259cacc2d05085c292d50ad2ebc37cf647e172b35375c008f0bf7ac354428030e7fe971c3e5f7cbf65b27f856983f97f434cd99a37fd94480e9b3c8921e11f593102cc6e0d7fae20cc36f7e08e4281245af8ba79adaa702f0297308d2fd73aab3537c3e3842f2e0dd14c66a0dbfdde351bb76f9152bb918009ed27b6d30f58cdc6a3453577785749ffbe76548b9702a481ad2a1f8c6bbb7b7debe1a1d70cc9cb26ddee4a4e30d6ace67f4145bd7663b2efe8a7bf1b5", "e73682f95be877ae54936b63f76e74fe54968920fd061cb9b274709aff0a20742744b6a6967d18e04710da979c143126f39c6ecfb1a9a3e28e5f5517295a5ac5badf1e81be424cf2136dfb4bc9512234e7e4c99e6053bed7eb74d1aeb29baf2c58bc222c95ac3a96bc30bab1e0311bc9cf3b97af08f4f3977fd08e8d4f887da89ffa029d18ad15d447e48c3e2d922b198864e69055152fcbf25ff0376ff1d7283ae411a4407d8c728574651a4c39e71e0bfcb58e459a50771c0bc1fb21b6219fe29a8c2b220ccfe61c339382f142b9b49844c986d89540ea423dd687b87c8de3fd033e4fadea538822d453038974a7711149e72f77e1e95bc75c3a490733ffb3918632cff93e8b4787493ccfa59a854a316a48c2fe7f10245f9ba63d27fd7cb609faa45eab3164ac2d450f3a352403325c94dcbf60bea9fd2294f3804dac0253a98a1f066f19d7bd60d3b8f3096fc33efff8a31dc08671f5a155fc62d2055f91fdbeddf9a797dba537c4ed7ff839ba36f8019e055966fda362de97074ad89d368d824bf7d01b744d0a393292a81a265241d4564f5af6588dec38cd4ba5ae614421c9466cb9f73acffa551f2bf0fecab3c54523fa1741b19ca787f7f4941b20215080a225c07b302a43959b810c02d98b93af467d226bcfd71948fa17c9641b5955409c30e0cf1cbf21eb0d338465a8117366daa4596eb3c360779f13b3eb71f359c6add1ccb2e51c8efaedc5420eb0c2dd99d4bfe2c8a9ffb39b51af8974a7ddb1ca008d53eec38d9ae0c3977527caa612cc593748113b5fbaa8f4817bcaf338dfff4d8dafb152b5d1b58074bf62cdeb97cba3ed10dae9a4c15b286a317fa25f74555d3211a7ffe5368c455c493ae61f78f68f8f71cffa412bb128eadb208f8eecb0b6b2496e8249a5f5314ee862e25bfbd494047fdb8df718c1558e55bb0cd93e224c3cec762c86f7bc4a32abf0d859d39a01fa16b1c1df86bc424754123222f817fc5d60093b6c4357e487f9cac637810ab4938005c7d855c4dbe4bc66f84567fcab1c79b88ec37810240dcb857b3515290562f00f725a0c5477b349237f9920bec5f885548e6b2cdcb9f75f641f869f73cdde22d6c8f5994ab6fc6a1c5bfa4704a69f5d4eb297dbe8506bf904658926f0b672024c582ca7ccab781d38b7b384926fa99389df5d1034e45fe031671661ea3e0e4b01f6d866bbd3b9b237e579ce1cfffe092e1547e3b77fe3009fac513f1af36d97faaca8d497369401ecac7f8ced006a12c82f4f5a8d48493c80f910e9b470a35042a93b3f245a47fd95e4649aa61edc06882b0bfb38ff0ceebd69f4629996d4c96fa1eeed1a890a9d661293077afec264b284f442d133f038113d4f777d99c72f444500b9de57b90f55734297c67c200b1805a2f8af3ef2fb5b79d2ff4de1938275ea3d77a4bab0ff6bacbbfb524fdb614ad4763e72c116140ed5f1d3e1c3f9abaedee7d2891d06b133e6465d2c21dcef6bfdc48046f2adc4d5b4b97633fbbda1251646291118cb85baec7f47092e3af64601fe5736fc9bd2735f0319f4ed91543f1a26a0b2a2a3d0a5f17e8364e745822577d4d03d21d33ac0fd78a8fb163f601984df4efca8a6863790c4f9802a783a6c27abd9db71fd6c130feadeaa196debe0bec25b18d47140bc61232b48b917a24f937c9836d771bf9e504f7becc0e99bb7310de21c24c478bd551cd4371892c3f4997e771240c936ec52659414a503dd65797e2aa9eec8b7c9fa182a26fc884a616c1a8555497b6231bca933e0b863318c9c1b873e1153a78fada577b624e96700a6603482d14ea3d2e6ce81e51e414f1075f375251d27a18a6e33dc6f366026351d03e9bc5d6f2b1231fa3207c5626dc67d241cbdd4ca1433505752051d7ef8fd7b13ea73778822f2bba2aa19ec4f44fea9762f0dd2d7c8e16cd34f72e7ff2a3a52d6c6107c5b5dd90cb949284a04203c976080d2c314c6d2572c88a6267ae758c7b980f8b18f95dc59b02e77f33476212d6b87db682f984553442f866eabcce1b2f58ec8d7eb78cda4f75c53f8f4551e5b91a117095a813f2cde54bf26b4f733d854bd80ddac0313f749a6dc0e76d809ecc4a5543337", "1", .None}, + {.Gcd, "2da8e3fa7e0cbf3b6650dee7fb7d3da57ab42bb3b8ec0cded4558f33faf7ed901f3c83b4dbd9449a616ab659aafa98248b75419312d406c2fe7e473259dbb261545f98170f401851e1d1f43e91ba5fe36b53caacd23e1afd566bab02c7007f1273049524817f49bb77576b416a8177fb505198948f29932334730252ce6e3952dff3f0b7a04eec1447554dd2b69b65a587964d3791868b623c94fbbad65f7ab784c5e643bd1bee2d14ab0e80e48c690cac5cb1e7c243469318beb0b3c7160be2ef87f6682bf6bea60e47ca9b989de226db0cd5bf8d12a2ed297eb636fb15cfa6188cc425adbc2cf123e7e851cc0b2a669313bab0f5d716fdc4fd8856133e20f1f6b1b41ebef2246d909be4d95ad3f3348a8552e376520a1991ade87272519de3b70e17c0a04fb87ca1615a5d3b20c5d8d0fae72bdcbaedf6cdfa634b9ca377ffe5ddfedc52a058d529b6c4c0485972821e2e538a75f08338afede137b4fbe5e5d0f3df23db752864732e381fb0e0def0e6683ee0161045f2f5a981edc1b74e4999515fc6901049a753865be8eedbec01f69e2a13f9fa5cb3e4fba4b2e385baa2482124364c847f1c7fed703274578feaf487354889d0ac1816e46fbdac615844357d56826f0f21b791c5fbc88630d1e4fbf8419b41defeca0dad94783afbc5fb4ea3d2966991a991c68c3e90422440de1994eec650dc837d585a3cd6483ab6b0bfa8d1912597800a72e2549f318fe57e42aa171935a82995bc8d049a58622f9cd0e1fc6129636689f9625d6bbc09d1204f04c166c703ba0a17d0e2b259b771267902ea335d60004fe6f1840ee602de7420f7ff91bc8423f29ee80817d0c793dd68a6c30df80bc347937dc54a18fd98d475f6f22b7444b32106fad741c27fb2bba9e0c804cf25c04bb00fcaefdc8f050e9b5b0af81523e23777c2185544c6fd8e665274b34de407b3294ee8e273d7bd79cbb3f0e0d0ed85ea482b4135e8b1a97844165568d15aa0d25938334149d08dcc57fa3d8bcb8846f18768f75d3b564cb559d2a4aa86087d15d78f61ed6be43460b2c1e535a8c08ba2595251706e1f5079dee68299f12b6c8080adfec428659e1964ded56b39ed6a3c95a632da1c5bfd0af79ace4fcde8ec773e3203fdb06f7c899df0b2477ea7c4906d63c01128acdd14fd55e1218ad524307ce41cf280142872ff0d5ffdb8e86be648d36befd446a2c908ea319c7c5e64eb3baca05535642ec4b2bd0607923378b8186dc7ea0d6c08b3cdacbe57631980d7cbfeb79bf8f2a8e6268e5680fbed8821a3f0c7130ab934fe10c04d9427bf4b96d1a2717c10e96f8655c138e5876b4f2871695731732b63f15280bd728d84b2965dab900ae50caebe56497ee1251d9c8c46b4dc53ad99a3331e6109dc6f05322482ff4bdc2bd927efbc6607a11bbee674f17c8f6f4d4fd4962b1e4a8facbb108594b5a451adc2c37cccce2e5ec1b3b5b2d39ffeab74513339cbf1e8717b6f861bf37870c058ec76aa6ce1f8e4913a1258f949da4ba2d8dc19c961352891e3223f1f2a76dbe1e5628e97537f04e5bc287c85423b0385ecc9a85fd3962c307aed456595e66c4299c06c767c588a8d6c476779d1733c193340fc0b42b3f9ea8d16164329147907629e68cdbc68717c7e7598291850fcd6895f355afdb60b1cdda09bb522b17d6281502bf933f7dec2eb9efeca92a256878d7d5d8e8ef827caeb4c9b8dba2237e5c7a93510bdb3405d4beebbb9428a17fef8b1931e13e76f4afd9dc9d214849b46fffac2c6253cfb61baf0205ee6861cb413efb2bccd7a9b5bb06e653549b07c5d10baf525b368cff9145b764d82cda4e877f360d25c97dc7414d7eddf62079eda9731ce37e99bfad632f221c1456804d86ebc87cae06e2c5e9204a916ca5ef436e8f49932f651756b2950e59b7a337c8852bc83ee4fc8056dce4994b5f29ec788c614d947725a331292d703d4311c27bc31ca2a1a8c4a281984c6c02d64e252f4117067ccd41ec3ac5371b60a1eb5ad4c6e0e74c6ab29137b0c689a935d0e1054e8774c9bb6ac31f08d5c97aed4937e377ba9561a4cc3777a088ceb3579041f3d19dba7eb88661d409d19e7e6b8a6c5", "45875814a3200230177dc28d197c3b565fdcaef2bc22541f34e864efc24902f67d3eb8fa4399e1d67502ca8e02d1adc5cd88003a387dd959125cb7801493b93ba671179700e6dfddc59b8cc257581a78aeeb2a2edcef8222b13006c1bd15043fb87e1e6992e422430e2d425775c64a1a58146ec8aaa2b56affd476f7d0cc1261fb6328257b6929e7365485d5150e17db4e004af5f7461b229c1b327b9503d290a8ed406fdab011193fd39a7a67a1a7c270c1eb75ddbdae602094986f45661f5cf2ad69c0b9a9c20d39e26369f6fe90760afe41cc938d82d134a8c1d00a18e0b924564a49816678dd518753cfc5e3a09807e16529ea9e7c78d1b68b5fa9e3d75218c51c7a7561ef512d2666a8636e6424c61c6a5f6f24558600ff27bc044d6f3baf558b1ed1b83fdd811de046cc9ac567e5381859e48dbd96850fc3814345afda4052c1ca8647718fcc0190ba1d24fe6f3c25aba473d3c96594803aabcaa60045f39f59065501632cedc7853bc896f1ec572241d69571203030846bed0dedc55193ab81a40289526596ba6c226aa8e85715b700e2d1a66b0bbac79116a98a201293d0e279c907d3eac5967a82a11afe57aaa0635926616109217b7242e19d1432297c75dc07014fd506e41632b46c15f1f2fb02f24a8ef581e51ce4e8e48219972eaf9ba44775e8e63a56ddd67e0e840966555274da2ba92e748266225974cce29be671cd2f7b440e5a96d5cbdad08f3994c27424e0c7a0346168ae12f8187cb10107a0550ad5fa3e130a5e36e56afec3d5d822894dc1afdcbeb51c03ad3d0cd14c6f789d21d06e05066ab30428fe927289f026fdf93fc032f8ab1825914a596801a991f1c36b4acc286490ec91ab3d8c136c028a39fbdd693a0a02865aa712f8cff4faa8ece7f1424ac3707f6830fa28deedf24834bf6ef8be9b80eb4654de2a045aa5b0b95cee28971bce6ee143ec325bc545b9d65437989059c338b0ffb19e17e74ecd0b4502ca010e30bda4c5faef3a157995a067d26f01ae25eb8b9423af8e19a7f98977e974de3f7aade06d0567a111394f67f932275dfb17ad46f3c2e4a2433138c783f36158003de203d0d6bf6ce0b0fa5bafb39c4cefaba8c49b6dadea03f0d2f88673a14a6acad456cf8d2a1d00ca5b3b9d30af3d26d183a59a23780ab1bfe891a2f62644053c71d1b096f31d49d814f2c54fae7c5a7769739eb81611c3904e2f5a6388ffd378fee4901040ce6624bdd8f45888e175745bfdaa088aa50c08b507c607ae999b50b30389423e77107078e7869a1c041a5dd26a4cfc1d45a40518770daa9faca65500b413bb7b699e03b3b3b2457197f8ef255781920ace6f869204514e3567df1870ba2f1a14b5f5e4cdf137ac579715fec018e8b313984f47f9947379aeca90b54a2e011e1655bc0eb4923f1bbfb58656d143af773835b3d893c4665fedf0304b43b11a61500612111cc9aee81fb713b8371ceb58625cbb0ffe069e13ed5ca0ce50fb8773eb1b27ce4ddac26dba8024935213c6ad7c5816b644839b0c66c730dfe43b50cc092723ef30581c84c39b2876a94a70fe82af8d60a4a75d5fa5d82a0f563d6f99f894341d6adf48d45c7c37e6834fc7f7ca6c23373aa5cb2f0695715af1538ef8ce89fdd9dc5af7335b27b485d0a320f573b7380f4715492908fa821728a08b905bc48add7ce53ca486fd53cef0a6c24f7198e16e791b0294cba6a65cc9474ad3ca68351850aa4565f9a89efe8d8c0bcf8f801531600c1e6efb14907969f8eabc1a3a808d908df8e221a104d2beba291fe748662e486a09d29e43ca794872661104a167dacc55b3acf947d05155b5f3aba37c613fcdbfc47e816bfe731f905e52ed0af5eb72573e12676d5b3187b15d2315ba205024ea7f762eabbdbb96fa1e087546b96edbb6b44097566ba0931c0923bcb2698309a7de6a88906e7a454be09ac8cba351bc805a41e06a99aeba40dfc78f778562ccbb6ef90779c64d297c1d8ee435e50a004852e581a8778b4e52414d503b52cef0ff55ed1fd24d223e311a67e40252c1cb1bf25a6a85b382b645283b71cfd4fbc60e05d4df9264569e30bed897dbf63ae27d67cb2e1e01e1bb", "1", .None}, + {.Gcd, "3a080aaac24a34c5bc224f88cdfda380e554c7de6653dfd34c9e8acd992d2baff7158b0317f77e85963a58cffd7862a3a9ca41b78fe392b63f9915df68b992a408c289fba602251b31a84aa0dd9457e34ec2882fef503b9ca11b9edc8c5ff31144a46a42a54b74be512511c1556c766e70445d6430bc35d8fdab3b11df4fb00dc4162a0300cd99afdd976d2e978ad9f1bf403974de15ec68430cf497293c19344e9a3df2f957459bd2c9d6166de430b1585c59534d9eff8fe51716ad0ddc8ec13f542445e872ab13526e8e828ade3e74db146a9d6abab037f2d4bd22ddd06b6cce3c8598648ac6ef45eae47452661022e555362f67bd99597cc1c2e29486cddd0c4852939516b68df16314c1e8d1a87771b1b07013352740300f4d2d7df0165e1728bba687f9414fd96c55f342bff8ba98212eb8fba0b6dab624c05ade977a70571d94a7fefc4af451ff847a8db0dd520dc256453ac2a220b1a5d3c74f7e0224ba3108dbe950d98c5ccf5a10bbdeaffee2542c519bccb94f84fcb93c6090bea9aec66c4ddd9fc4ede7a092655d4788c986994a82e92ed50f1ef2f4ac02cc83c5d3d1823f465656da4878eff2a9f5ad35c78cd8d98c1a62f78398f9414cef2664c4d54923294d1ad55ab55f12b7699ee0f8e32166cbbd02908d4fbba61e054f3aca37e0a414e8cac85d863b5b0ee2185b900e5a4df4c2e3b093919753f46eefab025b8e062f9872763c3f365cb877bbd19472d4a2e4a7cbba1805b7e16416722677d2252c99fa5c37dec5bbb7fe17c28f1d5b1d47580cfa4981484fd9c304b254b1ef998c965ea426357146e77d5227506fbb5f5b070477001f4122f3e779651a4ec696273dd49f04f1f3bedb0c46f7eb18700239c2b469336ea41f9dc359a0669d99f802334430ed785103458822385ed30f3db1cdb0f26f405f7fb9942c56ba7f34d4e5ebe6811506b34a125d4d5294bdf1268165d1187fdb85c3624e88295178ede760a2570e8f0c3e90a07e55e6db04afc0aed1f7e50d0043be0a94351df2b2b0ab6e9e25a24a38fdac6b60f9ea32823e036c70c9989cefb82e9ed3e0c7a522b3b4aed1811c2f7333679160220f97bd8b7a46262c58d3d0f4825e1326d446e637db2bc9d07cd9a8e3ee6d70c41d187c53dd87ff4686316e3caee647e4e0fe8da444470ba60cd52af3b5e77f2f5f0f623feb1c3ae244353a3ee2a37fad36b159aae3b699c284ab07979aca3073c426d8122885bf93f3cb6c5c610d337b799dcc63e29cbdde879f5e9fd5a2d7612e3cf4763a053ee89601de559b950d035d12bba5e72fa6e09c5ece4c6fcd550f5139faf354db273ab78e5af4f7f385fd5ff9dcbe2ab147dd634edf79e5ec7808fb52f825a7d2f0a7762244a7a232cbac613fbdbcee5b63a0ca38a3f01a7870b191f7cabe78eac04fea6b8dbc355880f9233543b6d0691f2f74a85760f0e178786501b16b480d40a97560d59c575cf355d0cfc4d8825f85dc8f7034ded7800cd1fd636dd5c50ab59cae196c2f2884f3da8f8f5e0a62b868d8c390851c971c3b7bc04279246c846202d966521907ece0b1dd0fa5a709c310f869b051b02f071f485ff0c4061e25eca76eea656c00aef60576a9c4f75fa16763f539f9d860631eca17b76238921508fb47e8421b3166400c805a67d2bd45afa0d431a146a206c235371a91b04d721817355cd483490bffd62859e657c891dc4eb18a3901e74fe04ba94d082caa6619e025566085346d54aa17c63821b64fa6538e0cdd5768e47a94f4c6ea2dea1665deb083aece86ca3194400c78960f32bec4e458cac6de0294fa60e9abcbefb2e07e43bd8794b2671e442c5c94721819f27505e57a90f8e5ef115090f9e8ef3d517969bd45e969da45b5d4d9a4d3724647829ea060dfcae367d4af3c3cb39c7be838dc01897b54330458d0f0cf070150bb88ad4b00bf2d63cf29a3b987bb9c176c0cc2aada85748e9347a1b4b71b5102b63f2dfd21d64c21279b782de056abd360c483ae0756b636d2fec0a85a9e03236d5143ca1925205dfc59595edad57cc99152efbd309ce3b248c5392a13b082bb2d75b2aaa5b948a0d02c9e13b6ae344caecc950b10935f8b", "213b898b66e158957eb3941b182be5f4a913d0a14dfd29c2f012c0a39912a9ddcf924f5c4c4f3b5017fc9076228a03eb87d8348e16317668ab3e6bbef40757d9c643ce081062721218cea563969b5fb7f428cf314101ad8669f21dab7c5c34d09aed5202b3a68391c8279fe6e42a991e01af417035e531d34dc9f3fcbd20a2ac0880d1848fa27e17db601388403121b7b209686c04ca0c0ddb4f0dc6cf372cc8d67481e26fa289a1a34279f98a21fde20829aef384ce81a09869deb75e301d2a1191286035a211c0211fd41657b0cfb6c68980d3294089c0fdb9fd3c8f7448d2c52850892cc8fc3ba0f133086f53efae74b3400ffe33b7f6ae52fea2f7f6ec5137b239eacadd42c4617152aae360c5f7db8a8328e26d9ef59641bdc381edf8033a8acff7ec8e6ba4ccc3767eb8174ffc7067d29c72a7ff2807343a28fcb914f85cd68153453902423d8574ea30568a3d16337a306c0435a7e9e9bc89e0bc6d5e00959734372497d9dc424355bab19b23345fca0c9528fbe61ba89aebad37ca35c6f9be31eb373a0c35afb015d1007d888f9200e16dd7d4aa4e8c4b73f0cf57c27b0c15e1b4aed6a427397f15f61bdcb8022b47c016dc51b5afe6f11f303e6d52f7b4515a70dfdf62119645f4b322c9ba6a4e05ee1404e21a43eecd4133d29b50210693dfe367d12a79074f4dc7eb69b24fe279246c35b61e75e1e583ace5f1cbeabe946bd66e508b776056b40d11c199ec63e64d43c73b0aba8c42fcb74e8f39dd820f7dd9974f58c526e880a252d2ccec370d0aa308bf388b880f3a9931c0d916e655f78376cc9ce0ce305071e8124a0df515773736436ef0d4b4d0114dfbd250c3ebc0c4ed6bf8c31b917aa6ccafe1c5d51f0595bc58d19049c24ed9d2d1364423d066c6571d6a523dcfe1f0b243212af6beb112e0e5b37c3d8ec7bc9edaf7835d44401adfe3318151e192beb7b9f8c1bd7494ded2b211d2d730868da2f8b1e311e04b93bdcf4040615e0d15b00f83ad0744e3b5d123289744909d879620b42ab1b5e34fd0f51b26fba216ffe1804da04ce2224f80e9713be6dc93bf64e383b2fba7eacece6445059850c5018fba27ce6bc5e4c11d3e1637262f12560874f506f692f70ec26f4b8cb3340697ac70ea445d64695210443e2d6c9d49f90178d0f4a3a8c9940546bd1a5b9bb359da4fde1f63c1eaa6bf09d172768c86b9822f082fe2c85dc9bc613f65b423ced4274c18ee7d2e38479105995ab9f559e4cd2f2e41b5176e914b9f184f2002758d16d3fdbc9ce648c623aa6e5f203dd39530e3cc8da0b8e8043ecfd4d7e4df4078eb98efcb1cc41aed4e3b3b6f66cf0a43fd83b9b7ca5a0774db01d8d14b1e57cc6eced0d8eb55ff0b80e136ced9f71253606ebf788cd7f3f37cb0193406f107d248f51ae43e136b3ef9f8c68901ce579d3e96d60607c1d302e7c0cc34be1141fbae8b38bd4985bb5fd45f393909c77ae74f43913a021945b645a3d34d2b07b51c0545a641498dad46fde45eaa62e7a644b2ffe62ad29f07dd2a21468107951d0ec2eb7fc3bd985c34bb25d00305e994341d0dc33ca3809435aa0b3ebb7597efe6cf5e0fba456a01da8b97946c1c8abc0ab93f6fea672b183478bb2b30dd22949a27b723bc00267123d34dee1ef8c3bb932893768f9b75b06ccfd3df427ec4ba162f19438921318074e7778cb7a77504bf280a7b503d89209b4d230c6c4048983d6d9c56c74098594b26ccd207cdc2657d925a14934bbbd4e4311dba3b40d01fb1733aa1b51bba805a71bace9f1e75fabe2ca52f3293e555fc4d35865b73b8df8b12925fdb1ca0fee2149607dc3b7e4199b1b79b6390650cd16872d9fbd0a2af74856514c4d40fd0cd2d95c6a00a2ea3d3b2709fb51ebb8cccb8f2356775421be172435e2ad9c52af890b7ad9b7889273def8c629edd10cf7de27e37ed997caff6c9298458a95253a6a487f17401000d0f51573ad4a6d1ec9d6967691b14fa56c5d3a7664de300c25da73063cc50a970393909a72164c49115153356e330c48cff64b78be325e130a6d3082e706948ae26fbe918c72a59824544a300c0c0b9ff58b6f23b53e6761bbe184a00d9956241", "1", .None}, + {.Lcm, "7b43c3977fe5a7feac35979c9060d22b81c36ac37272d039d67e9e0f65e1cb9b6f6f1d96125e143d8e25c4dea67292c5749df07126433439bcd3025715fd3562ead6031d2a7c215ddb2040fbaba410736db0b6dfc51079570303540710c74093b35933ebbdfb0144c308f4dc2ded7abd3b8a69d3d835e74c6a39a86c9d980c8a6ef47d489b0422ced552001c3ee7ee55878b4c25849f3636fcfb7f1f5e4c79f1034b72d3eeb6cc7b050fae4384add7291eaf945b90ea0d899a44407ea840daa86d20a5cbbaffc6fca85e6f09275dc29a03ea30e206ce2bbbe6b2c642e2473fbc8f0e8e602bf7580c6a622956b862d8e017f7b0fd74a620bc32b41aba1ebf41c24a1c8d0ce8cf52d5a645bceced7962f4d61e6f7f19809740b73287c015829f1e5255c52fa39a587d32efb5f4a4ec3e3ea7bd8127186d834291ae8b9a350aede69ef0475f2e193468d8f537acd7d96e93e425976a2fa17c82f3404249eb50e21a4d9489763b92c6ee0f7c8c88d32c00eed92ffea826c7b41bdfb12bdb428b56cf55cf4f863aa06d06201a8ec63d313597aa337736e5cb1e95e2437b739ceb03e281a1569e59384cd7c9c12f464e58d7ea79c451ca98c29f9659cf10f372aa7772e0c655f6647b9c7035ddc6f3fed5cf48fed48ed1f3dac3990b7c1d3b11e10307be5af7e60a7b19d59659267ea17019e75cc2af4d8b22c9daf34b6dc57e63fb82e72b50f930a41d44969ac887cfeaf01f4d046f8fc7f6efff6c4bf8d9e4aa756323e2b586400d336f6e4d7719e65b66be8c1f204bc62ec41e0900ad30ed0510dc50c09208d9688a281a2ee1ad21d167a0f49e3698713b53976f6d0bdf72d458d5f81f330fadb44de595633e4ea1d3cebad70562966b71ef42d73d7c58dce35bb99b526498bbf675cb338d70e61351aa6639df45f2a3fd1430eca21a379f7d10851a89d72786e9becf205af69de16af09c77a6fa2c954b06e99b828e568db4f286b1266592ae7f920065e729a1174deeecdb47d97acb328dac2009beaf358b5f0867b5a72060a5f0d55a992d046086220ab973b2527d573ee3c2779d0304fc2d3c05bb0755b7921f8cee898cb5d29f236e1b47082ae8d7bbec5a4d0dfd6b0d54f4653d3def2728e77d2c134e98bfc766c7b57547f97389018958076838ad2f3ae9ee6c6bc6cb2f0837e932db4a4a7d5aa0e73d1d9af1a605fbecacc492701bf7564a7018edce30f3ed74ddd2649a66c87423de4fbbe65152eb9bbf3642712db7d4a916169f324a75fed5046ce8c4256002a6c1e0728ba56c04cafd3a5fbfb4654281584d29234cfdb7900cff7a0759f462310b110fddc7613b3c998924ade6fa9bf098d192e37940406828897a70407b309eef03a72664a4ffb09a9a8fd246b3ec93cc2fb8a82e0a09248a9cbe19492ad48de53801b062e410d1814bb56245e991bb010e5c0ecc6c85f17cadd4bbbec96b6c3ac69158341864a583d7368ac3c1cfc52cabadb52081b6223a33dc36ba50062ea0f6b5026357c7f5b6e48efc941b2f942dd34c1ac96944d486c7ea6cde9cbf8dfc8c69e453261989fbba9d4585f94916347a802171555126e8ee601450558df455372a45aa37fa7b3a7c563e94e582c755de9dab951a7c75a93676bfcad7ca8ef9701a142df1b9673845455ababbb0a86613ce6dff719436eb0198dce2e264fe87973d2abbe393bbd47d7c568e8fa5d73e97ba0d9030db961a503561e150146abeef4086bba5846efbc01640911862036d8d6e45752d3f24a8b85bd17b17ce1cd141750bb0846028979548a393a571c9f24475394906240c6e7dcb41a9991a17bf08f40bda243286e1bf5f758b71db392e35382ddbe99b5e6ae177ccc7ee078a7be8ce922f94694f24c47211e973bf7bd234bb4bbef2660fed875f18b4e8bd61a003495e0a84cd9e2f76fac96a4c243fe413d45eef59730db6126fd4dc072618825e188fdabf1471ddd7398bb3aafb5c2068d51297784527074c84a7e0bfdb5ab89661c2eb144dfbe3a04fd84b13ea6873f565c3924331abe7c46aa7724267ed620a68202f1529373a8d2bb7c85b5a425966f6d8a68ce23d81ad4ca96d2d0ffc50cde3e750303e628da796", "370a11f171bb05b1525cbd111065ebebad8af54190c4469b644bfed0c5fc44f4350fe2e985214e7d3db3185a9ebd6689019feb25990c140627024a9c89f0460f5292a6c75446915fc77c974411ef0c13d0b9e7dfe3442e3f7a5151b1ba8998cce82cb99695a6ff3cbfa20fbcbfb12120d23db1cfe1ac1fa5c0520e5655aab46ce9d9b5a999c5d748b5e64e11d574c3cd2374e338208f2e937730b73e17b46cf90b90e151bc3a74f298e0129cf6ba30f678bd0bb3dbd5a987348be1018c145f8e56d337aa3e9d4eb00af0661b183c63008bd7c43ed46820c28557d756787da48f4286c92fdf6674ecdcded5bcdf84f6620aba5ae1854ddb50125a8974e64ae9d4c4b150de3fa53318182b1814aa6b19339828349340cd2bda1be5a925d293a5ab7673bfd24ea07ccb25e58919c4a10abe2b68bd7853be0fcb1719523580c205dd99d00fd941cc918d3aed782b5d7906812da3b2d7b10811d970d5e1fa5c80727977201430a1b93c296cf6483390818ee0409fa140bcd1ecc9a13919e3505fb3573fafbbcc4212744bef8e1be35b763323a9fe1537a300a4893f183494e4f457faa8cabb6c03a63f623dcb2f251a8de8af99de176c222d1792742f44aa825e58b63f89e8ff470adf4deb4a242214e10357a0402a0cd28c72aa8f21339ed573519eee39db148d5eabfbb9e57aeeefa6306e07916501711089969b0bf94c02a82f70f7b791b94752a80aa463eb1f9f0d75f0a80176a3739b510f5aa0f2863ff65f80cea071e866d3799e8093f20d88c7041d83d1ac87aa9e5a3e99ff523726e31d80f79018b6981c93fe307494eec262b28a0c491fceef83b88fa8afabcbf9c928d9378e123dc79efdaeb6d92fa7084eea77c42bc4a2721ea509ad004cbef4ff565ae8595747de1994bccfd5e7cda454d4fefd41ce904772d6516bb7597505d58b5e9650e7592d6c24f691cc0f95fa24304ab7adb4f69747912dac77dd1b926839155d813e420bbc18ce9d470fee91749b73a2fa50e8f927a35fe9b16cb648fac08e4878a0b70b527f4fa35bd6f14ff684dd528bade01a87b3135596c1c43ee0098a64583b9070857bbc61621bf369285ade0c1b0243555a0d305723fbe8172a6dcb824875733ddf5dfde01448f7ad656923630d358ac624b71243798ff7633d5cc0f59901a66a909469ab4aa272181013b81eaa553ef7cdfb2ac10f8ceff84182006e72d7fa1d70d964e508e88dfe967093680b5d1acc138df1bade94edfbda0ea5acb8dfff0c24e3d3d6427dc4da9a6eba3d869c89d74e38bebd95e7a5eb268677576dffc6b67587bc111fc8cab7fbc3dc3f8aa58f6286ff60e4246ae4ca1dfd1e1789cffdf5cf11add669aeeedecccde6b9aa109bb0d150b5208c4785e5977180e3a80954c4c9cea68c36e843b5c6d3bc418ba2c4d45ce96162ad832da5b28a40224bfb397fe4cc513c03a642363f84e134a1eb702f283051cd2ed4973e68f2aedd8fd550badbd5ffbb298b7b7ce8a9b8d5058cdaaa5b3a3e4da2e66147b1d717f624a8e731b1e160990c2f9c093b8d966c97449aece566297accf1adc186dba66be9ddfb366b3872260cdf776fbe17e70c4a4eaa2815d02bec6fcc05c5ad4dc9d7f1e4ea9ce0280f42bd276ac35ec06e099639e6cf08be7cc116ba59f02d57e6683bc51814c59ddd47f366f3feee13ecf51418bc5b885e26e91bea63f01d676f0241f7b3c47d86ec8f68fdc0d2924ebbe7d15d3e5a44691c4b7047d5bd9a70f3af52c13949b05e7ae90f14f002930af405f43a34eed3f19c819babfc8706f9a5f67af814cf4b88000b1c6865f113ddee243fc7cb8dacef1ffffe8e498a4e3e0a691c293d2c524241272bcebb9122f387d0d5031005df3690b8d3f0252060bd7a81a4008ab343fdd07dd95a38c68d6f3266462b86c7ca83b78299ccdac1e31e2084ccaf46b1c68ef1702d955c0cf8088f9e3982ae853c816ee2429bb70907fe139e2b12548f7004dab86a5b209e82577d368e88009e2ff66a5be0e8e4206641073beb28b30624cb15aeb9f40238231786c4f911175b41c0d6fa6fb2026adf9a9132998630f4651341873640282779fefff5d13fc4e6e1f629e89e9215", "1a80684ef1f07dc161c0a70c57f9d0d02fd53ef708db17fc612f063fa1a583961d1af87b6fe3aa1515300fa8717831a01cc07e6a9955ce3329d04187dd751b1a9933ed10abaa1645008cc162e9ba49aa55553b16f9eca57ede162506bf36e00d08b1cdb80ae90673d4ef5234d4f6bd8dacc2d063ff90c153a5f3c2f3ade974309e4f00ec6581bfb630176987e549981285d80109deb67058284015fbc7c0abfdbed89184d5e880eb80fecda55059469e88aeeb55ccbe116e1cb19cd064914d8af9ed5c91420c925bacffe185f22364e4d3f19520007f77031c3ee906e100e80c73be1a3e5e129c8282e32e70a661ad9ffe625a2dd819c0329d3a5d476560b05704bb447d515b232ed213904bf03b164c5d987377138e4fa6a277a919cd79f26dc117be45113338c6eb70f9bc173ae672afa63f82d6284a0ce6da64b552a67c712248f70b93305b164cabf6bf1acfa997372464f063b1567044da7ac57d4130a427ee437a205a419eb38d005752767606f0e7630ff396b52ebd70b87bb24f245cf20802080cc530ff7fed091cc9ebb842cc40ee1f3d592f60d07b417ed11e96909abd7d04b19406ebfeb2162e02cbefdb7441084e353b80dafe0c9641e839e93e02825fc220af51cc308121ee1e33c99920a27c31f409efde7f8ef927683b6687d7948ebdb91db41be467821d443661190afd1c053f0a07f8dd6edcf9e749af8ce9474c0918d707fb738af8078a184d26f8714b3788cfbb6a8828cd717c63126f8bc0488965494033fc02c0c0386d6c8175a33aa3eb2e538530099ff4eea73dcbdfdbde4a37a5cbc9872b12482856ca6a636a1dfe32107ff9a49747685db3484c041c7d4e9710db9faba9ad82909b2ead166e9d57ba1d9866bc819aca6ccf7ddc277e59f4711b62fe3499a9553b58a33f6a90364d454085f6bf62e7d78b85c453465f6f91f88e6da0c56cd3a6c0058a038e965c0f7e3af238cb1d884b1416bb88e630351d516d9ebf02f1f7ab067c42d1ff6a68988b88781bca78c84ff151f02ce2ad2271a1d6b456c179575a8e0a39fa7a5a7b4e4f62252f83440b044e3ce12a6f3faa231cbbcf98e383e70e180e68286cccfd60c254e7ef44756f2ce7ae14b1a5c412d7a3e1e12a82ba142b958a294fc306080a5f34110ecdfb50a6d593c47b95f30e5497c81295d266e25a0ca176ca2f1dc79cd634fb0311d78602f9ad8a6264f3cf9a6f9f080b7415c9cbde6236c3f5367526c7259b47c0c8d30dbd11d48c97d66f6221ed308c3c70243e26132eb5f80da55d0b3208e694e17551e3eb17bd4d40c5edf8c105c1027cb32e45b03c307e546efe917cb9f0aa1a23d20d3515b9f1946baecd6bfffb71ddc240041536981b7d5fd1bc43160d5c56a18503af7df1877670176abc483a586a5ea7f12e582c1298d83f1e6acb18309936b20ca447beec71a492af3425fcce936e8dfb7e3ae8861944ad32bbbd4fe8ddcae2c3c59dca72fb2991e0dbd802c9b284eca5d9c8b207656b1d8054d622437ae943bcc0fe84b483ab16198bbf0651e418f77438be0bd4fb22667c89bb53680a8a7275f4177fc2632434696bf456b6728e3ff2b4789b6b95b0cc372e4c21fc26bd6f8ed4415e646cf0c484633b68a9c3b130db13aec5faabaf062a47ebd659cca953aac1b743c7c26886159b12cb6e317ed251ee64948d879bbec2ec9f5300e3b0bc6afde22f25670cf1cedebbed4db18e4ef335969973c5fefd1e2ee15df62c8141a03a4928015b3418d607ae4cc332be6d601d20af7eaeb64e0434a9fb1bd4aaefb29c8f18b10761472eacf480350b9ace65352debad38d573e6a733b0ca12335b0bc83f5cc1870cba105b338b718a572459e7d291c65215f48219b969f1650e177f2a0e7f1fe1f4f76422baaffa33dd5392491f36ac28dbcddc99e9539fdf10f1761dff24588338d15bc6259603b3b8e51269debfbb9b5b2d22eef93d9b6d66224ba9a79eb07513a321b5a53f105023e126ea506c193ab8e31318154ea390e868c0bc9e3cd7e3da82422d19fb681326fc1721c86517d997d12904aef2343e3250d03f069243b28b964a9ab1b72a1981d8fad426a7234f9fbabbeac47d3bda027d8d934e61612c19161149aa876bc245107c108634062e26b002b7936c4091b5c96b01a60fc1a5540187eb03bc4ba8f432b8cb998668ca8b01c10d010ccdc8880cccce3ca9601aafe2795c77a160b074c94336f66cbafccfd2f28301309c343af7a95b68e35548992b4687ba674a25ae888c0dea11527415b10205c09ca4c04820a9e31d1f42a5cb5125b0506dcd55e0f8f9ef5bcaeb2304ab7fd2dc0404b329c86e14cfd007f8ea53fa35a52481946f4903ea740401568edd0951a7d17a3fe5fe628b23a85c2ec6157321b0a000707f2c004503e704e472c32bcfec2d6992befce27dd8e7889ce2893cc7f5ca2a1a63f5f88062f310ca51abc27f16ff533752cec7b2ce91276f7c1f741aab0f37d704ffe1f7a5e63234d967ffcc134cbb5ea72e47ce2a027bb6382b55a9d2905ebd9e3fd4907b96b0e54aa0a63a5e42da12a496e5bcb5a446d5301d4551cee18ecb12dbcc8fcf3f03ae63282d5683a7c84b2e853f2ef4ca516791318d809f1914d1dbb64c97088afabc60590916c9f0a85deac60f33a9bb0db49b7ca52df045cd9dd371ceb8f1e54243f6d0abe28d5cebeedd6cf56e14b18917002e8a23b722d0653ceb27506819031a152ce1bac3518fcd6611de050ff20551ab996ce36796ffd71b964f3cc6a513a2cc5358d938f5cad25dd026d4af5a57904ac7eee0c511948357e50489e61a24763e74b6abe4e8aa0b1a2dc4db3147eee441ad10ca0003f2828e220f4d64192e47a26a05cf06c0aa4147df1d7543452b6773929afa7a30a48fc6a6e9215459bd843ed1addba2b67e7c9777970d55e1d8992b76e40d01e1943906ad782cc39b76e4e73cba02f129c3e2da61a5d51b3dfc688ab6858da6770933d708796d38aaf4027b1fd66d999a4b77b931f67e56032c7bafa47c4ad10aaec1d296218e6b94adf04063e4cef55d4c17d7d3cd77a07ab195002e0566c739f6836f5c4803f2e7572ba86afd55862b28c3f6d8cd63026dd8bfa0ff4bb9d113167f09188bcdb6454f899286cebaaab4572dd9ff9d636fb9962636c284fe3013dab6313ec78cc1f815a49e0cd4e09acd5d999bc7dbeab15015abd65404e2a51c4981513d726acb0f6efb43ed57b27f0fc4fdd61db715585551b0568e1ef468b5000e96a1c192c7bc0611b16aac36684a8c7ef0d058535ec14dfc1eda2cc55b014a1685c830500033f74767c24b2d2df62776d9f9446482df7c1c2971c92059bba9ba309ff3997ad7d25667655008200140926753e82a33c3d084ef819491e1b03ece5008e6dd3edce5bc35df0b064abb0d799ce451f3a317dd00d180ab027f7a8593210b8c4bf073faa6b713e794c08cf6158a4649542a59dd7a7648d4dbd0f957d0dac5b39f5392a2980200691fcbfb78cd78668c44eeb780877dd05a6ea487f26761f066b73bc604aab337161740cb93bfc1fa633656a0f420ca12b3863b3f440557ae79067d8622c1113370e2254af028896b9fe944b8ba4e8faea110adfff3920ddddeca01417d20d22a5a558fd17cac8dec0c8f4b5204b2e3e1bf603874284f5d4d9b974386bcc99794111d4d6b6312919014791256bcc578d0b683f10c1787d673c75bf0a182199ab2962cb1023e3d12972d3e571ffa7e6946d379c9ea29240d6322a59ff0c99d81aebe3acd3ddc74bd0e1d35cdcd73d7e6564ffc4bd8ced2c229ebc10f813f31d1ce2cbe19f283b427ecfec4ae7cdfddf63c844969c559d2ccb2dee4fd777a65d34727566141cb85258483bdc49723f584d509c7c0771d29ec1218c19198f5e2d96f5729fb9c8da4fd7df98ca340b8271d1f0fdf2a0fd0d665e9430b84cefb9009bf45acf7a7b64af299a361853692d2f2d2abceaee6b182aa04086cabbb3a07b67e7b921a62cf485062f6cce771997cc7aac4db7384717be4ea5d3e20770af3574965e2aa497b6e21bd6f4c29d9cf4a05efa26bf4ef9c67ee18791bcfa1da7f6045ed59a9960e8c7ccdc601c98e79a5d28a00148690ee267d94967e56fef0507542b50068a55451021af726ef48066f48e9061e292e4184f0fe77889c25b6586e5d11d68318f39e1ee7af9804737d844f1841bd7e0cefe42abba212156efb78b7a63dc64b4e", .None}, + {.Lcm, "-712b25240960198bb0d76f717d2499782ebba76bcaf694b4f28fd1dda8f60e0b1bcc7d6ee5f7d8c4613164020ee37b843ff11249e041677d3f8eb4c90c04470cade354c94e92d4e7e8688f423266de6b26aa3e60e2e35d5ee1842208618d03fbccfab6dde6e32000bf234708bcf82e17a4c81577e17bd76bb27de35ef3ebec7e9d765824a442fdbfa421d8662276de1dd6bb014f02e707f1a471e8f5c7ca95410a146705da5492a743779590ebb7ec15fa32b2bf1ebcddd863087778b9bdb645bf5a8f8834e3d69cacc1240031710451fa6cc79ed8371423a24b4d2353aa8cf78e5c8fceca514532c7909a57951c32c8d4a1ff841e433284264571b1b43a4d1c1c4bd370cb9c39bb29340461d42318d956c818670ace54431d4e07e44ee4d6c914fee9620e7b4f1644e863e228c8be16afa9e6e080e968dc3e04cf38236afa2d2d371dc0ec4648cff474a648a81f38e3decb289e61f2d3ed93f77f74cb25af4a4c903d27cd6034a20274fac12624c3577edf9476227f9d35494afbaaab4d8d5981777bf6f81b07f0f687f04bdfe20dc8c1064351538b11c8e3c0ecc02ac37a2f0542bc9a15099bc07805efc5160d7bdf0949e4f87deb5631c89e9f8fe719ccb50a1fd606608460d6b1ccee3304112f3472cee4ce06d451a1145c45f4a23500dadf877f727496b63c9d7df9bf938db2d2252cb61fd7118a7e163e19679e9d296e33820eb46bab2802173f943ec2835a5bd2f25927037e6868745cd3422a2e2a0228d3b20855c497b8bae44f6b29813591d27952329b7cc95c4b11a12e238981e094d439a62e72b7f9e715dc3660fe1c5e611bed027d810143e9971eda7d697d6934cbfc0d2d3fc40b68c8546cf0f1171c414d53efe7355d14301e4c46ff222d49471a1237e8bdb89a92255e39ca3cbc1cb68cd6616dda3313eddfc0df821f6cad2ca2e7b3a93b45688002ac41e50104efda3eabc562a83dd1ae01465420412d6cbfffcb1778ea52feebba8bdea8f9040f1f554d6ecb33bc46e084d697674e88d16f47c7b765faa3057768905e948f02f2fa44208b7987b05694e0047984435eba991717f781b37e226feb7d86c10d08ce93ab2c987a5a3e62f6f6735fff5f50bec67febd053a00c62c55c102ebfcdf80b41d09683f00756e2a4842f42e21b3203385430c02055f94fb07b5e1c78d6644481ef037cb3069de3a9c47286ae9cdbee549b29b24432e5c703d07ba4b0bc4e3e3a02db2db1ce78098cbdf616115124ea511df32917fba7fb0a736ef10106777ccb8f414b46e1f2eadad8ff04abcc6758038ec8cc760cd567caa765241ac9d16c9887df0ef5532546851158ac7a85527cec222c1bf6e261be1b61ce91956e894dbc99dbffe3dc853ff53eb7100532a81e14cf1b140cdf541a3718b60a6b1c50a98c67c51c6c5860e1628c7b45ebb682ce9d707b859d56dfc2258f336f4d675e2f1acd2376f7fd4f51defb03cab62f9a590c25d70c2a6554e5b824bb64684914d432e03e5bb265d1966e07726b6a455c009d185c6463beff1d686ea96e66e92ca31759e78d95bc551d4c9f3b15f25c1fd50d00d7cc2ced20363145812e52e7acfb77d24aafeed00356ecf97ec1d56b947bebcd172840cdeaf6662b071e5af3881ac8718683ac0e49195933cd5f82366388ba9e3c36d2398c947b3736a9e0ed752b6fdcf704881d529a962ced8f264dd948a93f2fb5a2903e7fc1146cc1bf150c136ac76363e4b6e7456b268c8e896577c4c6bac018828c89f8d4bcbfd6efc80bf097aff56915cef79ee7aa8efd95f588d2fd98d48da3b4fdde5811d9ece8935ff8ca648843104966cb4e9958d6556fd72076d9510480f46e9ddbf2eb7ace92b63dbbeb8f98fa7af57c576beccc823f6571b31748a02619ae3fc79e7424abd8847953600d207fa17ecc04046f7fc7994f4d6c3ea65c6b38e279f77b2a43633692522a8fbd6095661b727eb90ab3c506e7a7ae8d07c92ceaba8adaf39bfd77b4926914101312e8bf55e2249a4548cef7d2ba93d8782e818972723302e7127b49aa114d26a8d5604911b431150453755c4ff378ffef5dddb3b6d4dbc4550d743d8de1c99a0f8aff60d37c919e12fc", "783bdd390021642cf9b87003df83d23506abf02c18f7afb242bebc5223726358935f748a2abcfda20b218346a3afef5ac7372e2f2de113dd93550b93c2414187fdf0ea233b4aa42b375cabfc763ae6c98fb1aee8ce9fb58dceb67d1b7e822232bfc5c4d62fbd54a3694619a8ac55cf1677090ca38cace3941ac65286d139d3fffca90f8573f84208009750f2e904aa119892f6715932e9cf961acc747725a3c279587ef0a4ec221532a8120dcf12e86e2d9c2f588fb8353de8ba16eb2ac58f22dd164dd3bb2d88fa9a0a4c9ba18fd99e9cdfcc39cd4cabe160fd6b3fb9db79acc2fb74220c85589d5d4428bbfd48000dd17faca122c6441fde431fb34913b085784eff6ab0e0a334aab3c52ed03a79b727b6235044b9ed0b51d2999a4fbfb6e88a9c32d0b24dfaaf4a220706aefb278931a242a6f070711b32b2853b03c2b4c92aa6470c53d43532232b327ca795adb85d24c07e67b275eac53ab2a5011ce03df8ca40e8af7ccf1d114954c5ee138aa22a82463fca643dda13734f9d0a181d811670095320416e100aa267d871499ab3bf38ebc23fe575f9df9b7ec81549e3ef4279051e3f03e1c74cf8663d2815d07af0d025b64ef4bd33f750b3e69b5739353081ca04ba99d2797742c6b4b5bc5e0248dabc8e58321450644a063b5bede837eed0e35138b5d8522f81e22132d94a07edb2dc915a151a6f4deac636758507e46c932abd1ae4562058b536667fc3c6711ac5fe06d70205e1557bc257c6fd5c4f2d4138df44f1bc764a2e8edb1f2c85ac90e07ad3ef67006d77d80ef62292a13adad121857c0161fdaa12247117b53777a3bbb8471ba163b2b6df43dcb6f39c0fa26f75314f61bdaaf11a5ec11b0c73d78e5dc28b27d0040f5836a51426fe02df82ff97228032ecba03150d87a6b7c65bf50f05b3a1aac893d6cc1e42a2f337f5635f63dc520f478a30c1954c2cc181a79e3bcf445e49d594a9e0c94713503f2d40a00fd02cd81cbf10b76ade991639862982f43eea4903e530192e459ade693590c2e971a1f3f09c3b90c4eb91b8695d761dddf87b799b5fb83557d84cdb5ef30e20fe484486f1f859e0153f2b9cf22c76071a6dc4af55a8d42c23a314720f98def4881731bc49647787ea2149a6f8a91f1052a0aa8cbeb10e4287670dacf9034d1b33f0320198d34777b95f5709909d49972d3fdcf22b38a2eaa7b08ab663c560ed5acd8ee47dc9769ff3ab00a3ae351b26bef7f25bf5ab4cadeb99a6fdf2907c8aba90f14e67b0d1af9a17a5030a5ea0da0ac1df868e1336ccf1c9123929bf51bd5aeb4335e9420f1ac0312cae1aee3eeaf7d2db85fbad80a49b9e8f8bf272fbe905fd701296dcc5fe27526974806b563e94346ba93bb67e5e3726cca9e8cd6fc87c6944a820dbacb3ef82e194944a2224c2d4c31adc466f07ee71fdb9e58ac0bc0034879c642045f78e550a80932e4e3ee63fd1b5707cf496f60a25db20cb09c797d618472b12466bb0ae6985f75e32bcf0e54405d6cd2d684ff37d713db0de821efce0b1142d756224cb55cbcf26331692b5053753d926d0957b8a6f1e542e24cccb281ef14098b9f4f673ce44c21aa1436993b831e01d39021ac5cfade65f0c730489ed9d6c0b3e3aed348ee3d4033f7a988c5bd9b0992dd2cef455ef2972e1c85c75eb10a22ed070f829fdb056d09c2f2e10d3f7e3ee299d009a094fa22853cefe17e5c942a7d784740825a71847995af8c93ce7a9c5e05a664b31f63e36e8098dbd8251fa438e7cdbaf776a789939a9febb99d4a4e0fcce7173f533ac71ad83d4d46ab280610acdfa43814bbab27055bc4e2ee760551ebd2825236dcb5dbad306b4bdb3d4f147d522957c822c554895e034c979a0c899aeb9fdc9357b8269b5d658f39ea86986da367ccb7d1cd51c33f4e3427bf50923450549799647c5e63ea2895a302cbd6fb01cc58fdc9d9f7db1918883873da9ce157575b2eb660eb35df9d11e5e599fb0e327e5ba6ea9fd52c4fbc6e6332b8766f43ee32f2076d5e95b6b545c85cf94ff511a69a4aa8720e00a3e796b1d5f20b3509128fc92cf9160f6ff7b7a7db6519a40d372c57f2efcb54f297934a4001fe8b38e", "1a935812f2b6ac8af84018470209e72ad90c8ed0054566af431a5ed8080d8ad3900adf62a340de578bd15d81c88259fd7cc1bf0835fbe66c4ba150438125927e9dafdb01ab54aacddbbbd39e8d7f45429b5d9e1d00f48488dccacf70e455635980d766fad7d4773fab53ebabc0f3735e76b48b2210cc3e6595b675749f4079254573da1d123a2958e365d8bea3f637e466740544df6e6bfb6eb034510359d01290fdc4dab3f461e8884226ac1db2c69602c5d54d0c6e6a9c8b544109d814d117256033efad595f2ee48460893ae9346e2c81c057d3306b99ef945b38fa0610f73c6e110c34f3646620cb2bf19157c56c2cb167a71de3db18c5d7a8f6f15620060b37a1444e710abf942dc7dd061e04a1d56dfb45def5c2115c970a3208fb49012a87c12c3d2e0329fc02ec73b008912d98fe79777078b2f671e48d124afeec6e7d6a4c538ad0262df38f80fb992fa8e97a8e23bd473e278f954bcf1cfd03ed67dd8e582d8674b0b9c0600d7b2984bdcc2e65ef894cd32bba65701cf96d9de25b6e04b364cf32ccbbad765ddc8e611e806cef05847ad619925e38d3129bff1054f0420dd388f0307abef186ef8b5ce3bdb36d3b6d71a21b0e78a589971ca6032af31c5eb304e14fad50962092eb7d5dc86496b5a2dbb691be4e8be4d46c842c226f4b4b1e475ebe1fa4fa9566a746cfbd6c760a72585eded35d9d0232ae96a90a498c9d31bb5b7171cd97719df09b157948615fef92c13f297ce64a047cc071de0dace53e1b13401568e9fcc4a7010e81af42a4bd156f80be19b650638e80c199d3922222a62af4f454fc2793bf14263a14a9bc01dc996a0da0b0361f3b810218c6fd94fc87a1994be1b4dcb1cba3d2a61f0cd2a2cb74516ce4da104cbbb851fdb49e9190b00cf8de324eda69bee8634297180560f8bff750f8bca1e735faba7cf8a19c059a42443e486122786e5f3505c8690edbd3403bd83732f9f9d32bd32f3dcc8f25b60bec568f0e3f502d350fdfc3a4468debc36b6585f404720a685b2fd48f9a4a7245d7b425ffbeb82ee1e4152f14c25dfe020d4caba515a283510862e0106b76a13edc79e4c26112e10d2c825d42ae9160314c9ad5db8eb1b582c1bddaf5fcc14ec4498a18db4979ddca3568abe52a3872d6f32d05f90f93c05d2ffacc039d94a2653be334646e5701a8cb623d8d0d843590ad773ba9239281ee611a262d15405c2f2e2321212e9f16750f2827298d0d24911eb3e17c15b067ea15a68c81d4f33e7d2f21ff789dae63148991ba9268f535658e1ef96cb0f678af724551ef95646bb851babc36a877931f6571f9bd797039620390c111744c236d8ffe696c7d4e99462a59c6be5056f6e4547f2b8b5a8d8f873365fdcc87cb20a875e16bc292238fbd6ca5fb634ba2fd6f7d5dabe30e350e195828fbfa6a784571ce972b1e41006b1fbbb7e68bc566382912c017b257b838939cd44a2f4547e224bbc3442b6b64c9a26566b60fdab79e6ee225d11227973da6405d622211b5e0012c0adbfd32a9351e41e9f59409def06cc8fef6e50c87abf974f8718ea8af3b8588e22db93ef80729fb3c32a0fe8a0b32b3bf145370a6bfe926f516225981b521947a3d2853283e386ec34bf199211e9916863e04014a8858c19ba4ac6a0d9a695191af1eea5e6eb49fd27089c2f9fe582611e09d83fc4640c0a0472ed7c15a9595034f72d552616935cd7e818d8cae5c325e69e5915f4153f11293fc1f71df0da482fa57f0419b8c0196789c8ae4ce18428031b0d96d15323c0990e0e6277810b3e1872bdc2b105641d75ca9bd238ab21fa96cff110849fe837e42a6c2b6ce36036cec557753f4e5f0e64ab9c956e5ce7ffb0ba46a783cd2f3f9b3c845f78b8275046d33d1b3b4efbbb2af102bab82c13208224467a5e49c4e60db442b17817f1ecdf3feba4c6fafb1a4c9d46325d53994a0717bca822e779880852040818c8403b9c04bf627717d80259210fb81653a35b71debc244aa33b03a4d5974b6833e7664b351908567a49de5043973f3a4d1ecb5d1865ad69870ed02bb76b2af637c33f1e3ce72619ee80cabaaa309fc3b8df7b93550fe2f7f0d5c694b8c7e9dc2396490ad6b2dafde03334f88d220094451d77a635f29fbd492f8f3e7ab038b286b37e4b5a64de62adedb62b610ad219dbb3decc88786e3be291157ca15b24c85eef39efc231b270b57773a14144444515f64165cbd537a8aaee471672869859af9932c3b36160f7afc33f1f77b628ab0a51f022b29c3e668010ad7e4bd2af2032b7c61fe70776674ad63a270e767705c68776a8cb40229bb28bfc8b9dae4bcd0d1cc9029a8230c3deb140a47ac033a39209d76274a3cb6f9decc4be81b3c8a9978dd19fef6295d43d9b3d4c4e10337e2fa4a1a7baccc602f5748a6e6d7669e5a4ea44bfa909ed3a7f03507d42e524e36f5b8aa643b67963f9a81ad251aa29fcd1a4e2ad16679bf2bab56254eda07aab30acaa5b59aab0c757d75276108fb881b5d23d23a0e173b92c88d513314417c1b69fee97a2c7165026eff351c5b26155eec1e7408c64c5f34e2ab08d765ab6335a43a2a5960b7fbf4041ab892836134f8932c2cbeb4d4d08654a06ca067ff7272f9633b557ae90f6c38ad6f30fc0d64dc48ac9be460e5e0f525dc1d5806f66962c32ae308ff4e437241676ef12d9524084cbe2a003325311c2678e1e872504335159f7f28cdaed58e9bbfaed7ffed6898e11c77be677cdca95fc8d3996ed9e21f44446bd5ce2477fd257578027d61e0857cb472b860075b1e7f8ac5e87dca42055ea7ab58ba7d2971d337973936600d411300ecc6c4470e394026a4009c9afb81d6a566aca813fb419be3f069c717fce6e81fb2906768303411760db94f61e10d82060b5c3301db3e8ffcd1c29e694415654afb76bc6079b946784353c223f5a3a1e2846f3fb37573baa21a0ab9e38d8387176bea26cc39264dcbe7cbca14a78991a941ec61ca32fe441392b49ada28cb048811edb5354cfcf759c79bc393b3885fbb27ebc36f0b263302f7d2c2d7e9c1c8f89a24386fa1b2d34161114801187dfe3e2219e9a2383e0b0e71feb5e9506f82b83b25138b51eb82633ff86e4c5e0f1c7712009165dbcf2a6bb1e7f4d4bdf7ae2ff17d228d277c4a2e27cb146518fedcc6830e0d966b8de66aa3f76345723e3222dd30568237e8c3db63aa6ab7d37a9b3fd7595db4443a66195b0caecfa4269104f01ce41beb0c63c8b9184de38f69c46ba93e316c057a7522fa1987f6d364fbd723bf864577cada2f3614b81a097b0977f550078fd511a1f7e136e85422c4b3c271aacd9a05d9376689cb007de80a59c15a26f041569a69efae5e66f946c96f2db93f736220040c833c824a49488d71765b687062da6db6852e9029d0f916f21bd293c78b191693860bcae1547179f1763b8136a42149d9f78bacccb2b1290a43c291d3c73e1960690614ee7fbf0b572724ed1efc335bec7c2d71b94437ff7fa6b5eb8ee8b5d94b66c27355d431256d0f6ec21f61d78c41401da0ced439cdf12ed02531f97df12655147b9983476a54330f9d5ba95c8f5ffa045cd9788eccefe9e1e803f7083181d95bf297253eee22f2e7642987aab7f6f7150db8464dd1f78c47d3676421b2f1ef185467dc28ddcee0c2dbd7468b6692d11cb20b9e9c0e7ef8f2148b9afff145abcd795ba489657296cd487cd565ee05fcb11f8db77ce392a2f9595ef8fc1bea7a96c271de3ce8397a50a937d369e553373709df797b4fa7866008e828daa9c6fd4188473529bd8bdef44a3dc40ebb99db94b7b98f5ecdc4a6979298e6058a0d1660358f14c6a7739e2abb9cd2edcc97315cef8158683feabf4262367f3d22bd4a0c1152dfc8a6efed533d175cbc3406bf2c55ec069b1981896bce7d96db37207ed79e675bf6be3a4175ac9daf0f55670575df6d650ecf408beea55ee75c0e00c2706d5c6bb0fa63235fa4c63b935ddf483a7d0e6acea0d692b847f6f2587e85c0119174289fe59fb7fd165c8d5cebf76d0b41e83cbc80e41cb57c11134301cc473b8fa0e5a3bfbeae714a10077ed8af44b008396bcc047cb1986a828ecebac3af483d50308baa0280b7f5f8c063e97f5af31c99fdd844609cd67fa118234a641a9bb2002b6f0a04b7915a4b86ad5f0c0d804d56f4646b800cf7b0390d23abbbf950aa9af546f5966fe02aba7a3c02aa5de4", .None}, + {.Lcm, "-7fb1ea93f84a2364b1c7a5b42dcf6b85039315e087f648f3c6e1cef4fed26b12b8df2b020196ed416c5f530aa0016550ccbbd228353513b0831bc8fbb66a983dc7087722bfe66f4b908cc49ed25e8c7fe4c120df442b554a8399e28abacba2b7af1c96bc9955c8a8c2d45838ed9817de206e72c1005cfd3ae82ea8c62c33c724f526c12169edaa115c8fb854ca64ad078f951724703eb5627f9b613394e4068f81b8ea6ef7e2486fb5b53139e94dce4675c09a3011c5060ec43b92ced644d0b99a2142c6de6243bca7ced52c2ec0ff99064c872bdbd134bc0ef7776b7390b63e78f647ecc424271fc7bfd6febafe7ea9b0a6d1a98a09e63a43b2aa3078375eff36312d0029bedc8035a8caeb5f92a546c9d855525bad6520b72f731c615c42ccf8a65b21cc856d73c3f20876a7871c12174317a52cfb661ae7df2f728c8081f7b529eb4fc0f99a9108636c77bf375319f7c994b2ab27ee5897231f60070f26e15f6e8b586658046129bde28a607f4148ff04882736207d1a30114d7efe721b3980fd1d9de2d88aadaef96fb9ada39efeaa364ddac552936c41dc97634e39d3ccd2f09dadf0b4821773a17ce71f6b685ea32263e9c80b773740f9229c4f5d2dd3e5d38092f501ae2d5a77f71cce8a14f2be72f97025ceb26950109917bf80b1202c88ecdf003f729aeffa9f298638061bd386ec407beb7e362e1363095a3d4b0264c92908fb3f222492085cd7765636374d8e0a6715a8dcd44a6b2205a8ffac248e50026264963dbab57dcb22410123c34e755b9e11bbfaba44930dff6c47a5684326bc70f928f99bc5864f5ceef95938aad225aeeac3da593bda43b8b0e0fd225d3a2ef7fb5ab5d14b46689d63e85299f6de5fe432780b797c91f8fa4755ca170e23edc7ba100a3a6d2a33e11808f0910043136c9bc59b8dcbef6c7c51245f95a4c7313ccbad742bb269f086732ce3864aa53711d589e592a9676ed49312d87ab4ea8791155b5e574c1cb05de64c6f4c3a4ecfa8b6919d0a4258c575992cf228cf5d233b1d3466878230c7c931ddf7264729b594e6e14a6c2d9510918cec628e6b53fe9d2d98ba0633b51822806dfba1b8cc42ee417b9eb82a9c05e854706720b943ffcc41f1b2951f9b0f4bca63b8aa18c4e9b37a3641409478db83cedc1c6654a518ffc84006d7294414a296df50dd502acb08cdc4b38adedc6778b5e092cbcdce34759588c883cef3c3db6e4642cfbbac7bdd6eeb99b424279cbd9a110ba16f51a80e34674972d118699f9c4848f56b1492b6280fd82f62f941a9eeacb8e4cca164247902cba3c1aa9837baf949d709d27f99fd44c1d387e84ec7fa37dbbbf603fd49c9a3c83d1523fbc8b4d4a62c09dc4ecaafce6b001634cb3c3bd42bad43ccd10f18ddd31ff0d6838a9de588361563f9375dc006a7312fc8e2afe1c535e8bd338785c399a3884c5cac74f36a6d91050022a52d463240115352e2fa7d26b565e2fc270606a323fb819cf7184383c7f6f2bda5d00f38c84810907b00060d97758a580c824a61a1d16d97a4b1beaed2bf588c7350b5db4e90784a0de3d89b2887458d0ef0e402f62a7d0281463cce04f5f3a5edfbca3452bc9425bc52208d8e371e39e072aeed69dd2bd0b7413df1ceb7b3967960dcb1cc285f938af26d54355cda57f65b3998cc21a20efd3d7c29fa3eaa50dcd9fc966c6855c1e88b07975c64e964731569c9ce24afe1af57ae301a4bc760842c122c9dd46e7a0d554709935e6cfb896a0dc04801fb30a68125174ac6b1ae4ca20eb222567c53c757bcbd8108884f3bd3caa47745e26a6277dc939ad2362f9502afdd21881c638f7c0cf6175ec398225f9ae7359296892695894e7e0d85e24ed97e378cefe81488d05dd11b10da744c2f4160605f7881f202555743c762e8c506e46dacd116eccf6e37d51303fd4ce35659ad47506bb35bd1ed342f1ee48a84a246679a169349509a7fb5f1aae89db17bc271a200f2bb8a20ed50e2b88f0647c5e8c9c239423e1387a6f7717fdb97473786f8fdf4f56cefe88f0bacd191dca7f04e0a86238f65599d91ebdbedbc21f2d08ff7f32e75c3d0f51d9640c911c0cceb904cb96453b1", "56e24e844adb939b5773560d416a2276631159187206dc841701c6b95d739ee0af1f64d55c2ce21493a91a9171df5fa74f49f0b7105d532446cab6b6e5b02da2298ccab44dbed1c004a002d7a6e41bfc5c99999f3976ed84681e3c991667ac365ad6d59f55d394accee1e59016ad70a9f3c5759b7b522ece3bdf80e32d84204b1ce566db89fd9222074fa1b7ecc55e4d01328d4f1eceff9bfaf282a35dbbb3ee6c511afc640e7dd1ece49e3a28b3f4fb58030ef87c430affa5193e006b68b0814217c922255f79cddb6c49b07fc3d93ec2abb87d52d5ba12c3109a44c4bf2dfa6dbe3aacd5ba7561a111d1724cb64cf163b6386848e6ba96a45726a41dc98c1afa59ceb64243a278ed7f97fee2ac1d67b122189c67fe452545ad569104add6fcb15a169a0038c4a98ccf38d07359cd245534918fceb0c036e4e48179f64c13a9263d751bd735a2a3ddfe1736a6b603a1a77c0462d1737756440a5cabb44f463dc88756e2f37a431ce44da52d1d42a417589267e8b552316d455ab05dd3af86b0c62385c9bb8bb5ec54475e5c9fa7323b1d02a0f50d4367c00c691967523c2b56aa728aa23b17703d835a20a5253a7e130fe795c561c5ff8544e97ae749230f6e8847f8c4f79512330a30768f971ccf7b93e4605f77c34b234fb1a0e7aa1bafe34b097befcfcf7ccb10fdeb474f1159d286063409b1b098c04032a056afe0f0ac3e9ea9db9856e57fb441f6e7a9f443fc9535584fc2f7f16526fbc63dc9d4cb54247808d75fd028f492298bd44a4eb51a65bda71bfdd793629ddbbc90b09e27c755c814f3404b36f0df3c185f59e26d4484ecac8d26a27203e038b364a6d961e48169ba4406b04ffc1aa33ff8345106a33577a40eda552b418ece15aaec6fa424cde9beadaad529d2cc0b08b8d645898f965ebea5f2ec8783862a2e94c2dd5291bafeb7e26233e613a3546d0b9bd41931869e1914516cdc42fd9a358885f295cbbe5c1569b07c41f28faee37d8506958fdb1992ab3b78a43861d5ba82d1f3f911d3f2c7d4d3417a9f80beec78f6c56f8846a3093170db0cddcf12f28153db8d4fef0f0f676b40852ecf0be9a8110632cfbb3688b0c76cf3084f35b4f6d9852a14e53ebd4feb0fbd41d7861aa46b4052b02094f6d3937d6ffa8fd9c73e9b12245da9d50c3a448a779d4067abfd93950354e2d80d3e6001e8c93ee2fd0be3702a7af157a798122233c7bba50d514a7c3aaa49ada47ad30fe44a913ae4ef59a1a6f6c77a70fea446d46317d58fce423b8e1c7f5286e160e33a93b165bc317569183e1901d8db2cb8b780134edd01451808143ab4b8232276e294e54a9306e3fea8b9030cd064ce4c6899d1b4e33228cd99e54016defd78e2c459b9514a4b92ff890e5a79bd9425bbb4afa4dc3b74ae42af152cc875b77368628461fcf99a0a87fd8bac0543121a8d709d043eac54e14c00b214deeacd079b2e2582a776f465d69815a309d8cf7d0c764d78db481684cc6bdc4297a3dd088c6c2ac044ed65dc1540ffcd89e75587168971f8381cbee16ee06660d093acd9e47845deba22126a77b5ef23aecaea724b960fcde34269af95734443697659af98fb09075f84fe3d12c55cf78f03ccb1e64049f4cd831d0b1934dccaecf05c3634ba9c6b8510f6a70d06da6338ab415f386cefff2743c6c77333f88ea858e33db4222f8457a7b15addb538612e384483e5b4dd026e5a31c7f22fddb841d489839fb22fd1d3644c9afb0df7b7a133d2b9c84ca2d8bf31d8488fe8297fee7eff3224e0ba5bc0fb5889eb67b560eb84a18c79efcb2e45b6531103f8d3bc04b3a0a1cf857296b263537afc79fe51981bdc8961b35a7f7c2fe8ff11fd7dd73b1535a673526a3fece2ccc42842f023459d809ec5364f0b512be5acc8d42e7368d576149f25738a718e21b3de143db235e90c11ad03de90b57482452d98a463be2380f60277c9696fe59720b4a1585dc884c4bdbabe720aa360fe8537eb57b9107f5d35b7e6ec8be56e4f7e330eeecb4ae3a8a51a699db14df2501f6b401e292f7e7427d05931fa47d4df939dc60fa35bcb6696ed3a0ace91ce9731ac3b1c4c29c0fdf570f18ab67d9072", "2b56a708fe9717ecc806c563a4f1f9838ef1ac76cc85c25188a8d76519dc1f6915aae50ad423cd90a1d95b6cd8969aa6dc75050481ae6a3ae74901a07b4f78591b7003e830246c5aa8874579f4fb127bd18a6e5c812c44ba29e0f9bed2d2478c38475a14e9b18ea96be701ee885866c1344fc4c987b2d469f889ad9869c5101adfbf30a92fc35ad283d69d1883993380d522b2975c7921f51d376cfd72d056dd36b7be7960df0631b594daa9da43e9a828eb9b122ab0ccbdf1964866acd8c9540fc74ea7d79bf9ae2e5b0ea511f42ee4e1aeb836a3c7ccbba716fe519dcd645921215b71cf6bc0d2ed104f77230fc24b8eb9ebe55aa1b26cfcd0cbb18f412d58a14cde57263455340f0192e26972db24dac67c6350c50462d7ed072425ccc20f15212078c15777eadae6b4f7f8c6a50b64914ea63d6187dec22031fcad74130480d44898bcb62e74c88f5e30d86f5eeaaa55289f4d8087f3c3d7c6574a3ee848edc61216933ecdecbbbc0d0abec94441a2fa83f498b3c616ed88dc6152f98e3030f033bbb332cd77c465f78eea3b07ab5ec4cb85dfcf4f84901fd667ce33b22e5b2087d872ef7c95cb222969c445cc2846390282b340469edff7b997247f5e8929ff051556cd860fc54d070eeff5890c2222de0e6e321f91f3493f9a7ef414449aa6102ae55c23b15b82ec7a85f9867b1c7d6d852eba54cc7454c03dbade7f253c575140443d7b1f417130d814c49916c1019057a1e7d70b6585f822460df4887df4af7f732ec1bd06425bbb9776c5d43caeb91240562ec0b1b4ca866120c7ec4d2b7468ab600011e2ee33b50e96308fa4580f4aff68644856d2caee7cb0f3d1dfb6b0af354248e0e606e23a9815a32039acb66a93c716e4bc304a79368c004498eb2d7c94a4b5b7b0d72d54190f06ad442564077b08edde159cc23a79d32ffe48ac97bcf9c124b57d1ac0d0832d32d0bf80f2c1b67c65e295230d6fe8ae96330a12dc75108c3065f15d7a8d26fff5c48286c0bd663a9caad88436c985cf7f8b789f153643aca6d1c122b01b60e5b74d5f9bbc2c1f85c8c9fb3f06df596d06e04ccd1121cb9f1e7628d9df64a0a911da6edc4729f18b478acd2dfb70cd98c3d224de2003cf5f34e184df99b8d7a846dba1bd6ec0cbaa721cf8655462ee59450c204deca91ce2a3a0050661b87ef4d77172cb639268a0ee96c73d56b024ad51d8c8776c2a989bb593068a328e37761019fc232eff8e3243331cb739259393d29b83e3b65ed3833fb7b76aa2eb01aec82b73c9ab6f0a0d33fe1757edc532b1c72b698dc990f00b1274d3a82baaac4c4e6cb0d36c6bf512a50a5ee99346b9f16b7160572dd888b4605ad6e7eb8fce25876bee8a9a318fa674fcbbeabc7b6a3fe05e2c27ead66b8c465429d2a885703e243b71a0e0900466bfc2b574e1638f56122c28731519b6d98737e45463bc48f9197754d34d977050aa89ec483d894cf78771a228f29713ff92535ef909a8c02041f92b14ae6622c154097ca8edf790eeba2df4c185ebf447dd2d6168e8bfc243957d2d08684ea591a765192ff5b86bf674736539ae53ecd80dd0066f46bbc71ac38bba6aae3b252b463eb249d831fd6d0364fd8ab9c4f36d17daa1b1fda868320177769e77ae780b035686559490b70fa85ae0c34056b148f6ce7833b1abfb76ba3526b04c827f22cffde2efa4927fa606a02b4512b05913614740c9ed8784b60ba2772b05f2c34d9c0a65ab82820c24bd81f1516389444781b3dab3a8770c779bb31637c85b20793ad61b4f73b6312ca028e97d513ba9b2f0e279ce745b979df3ff22672b42c8dc659197be78553adcbe23b002a5ff9ede2414d8a36829d04593802c430659149203f86ffac951bc2f38edde01e028a455a1e4c3f2e5c607af3c17f2dfc619992c70f3a8f1c8a904ae4c9e5c1540075c1464e0f153a36908adac1816f33b4c263cd01a4f618e45a87856e540e4fa8861fc098e5b949d34860421999e41dc6bd6d7718e62883e37b738dd68fca9714720fb8571dfce9fc55138e418bab6b92bb31eaa9020fa325ed9890a9491eb65651b3f5c88c044c34d7141b069aaecfe7bb1fc4cb00cf7b3304b1613c6f48890a54fbaf38ca6dcf8a53559bf49e6d86a64ee51ad1141d78b4df150ca580f828cbbf48557610aa8c704ad4c25af3491ae625cbbf99a2833f37fc535aabbf34b49a4a9d1acfeb9e6c22c0ddd52fade65f8f24f59b75bf3acbfafb2ba8f63b1e12fcdfa0b074b270e72ab277eb6d837c7a5c6892e9cc64c700e1425df0f9bdc88c9e08204031c65e147eb902b0647b1452792ac5cb3bd5bb50e49c7e61d420dc34f8cf6612e3b4cac3f056d186fd9c48e760775e082c41fc92d318f08b7a82fada1decad6c8222dc7fc841ebc1254027c8fd9e20359df356b9d7ab9e97418f2cb1ec48e95418660f1fef82947b04aae7d159216a1fd351e8241e18661f04ffcfed1e4c17c0b7587ff94ceafdbc77cbb60846a431e044db35748ef5a776b24e979d2750d53a84d9439b700e305938f9e7afa881ac46e112f8ad2445b06fb237bd18e624115db68a3e6ac1ab15e18916a5d2cdad306050c3b90ea435fa071d80f4c90b5c0deb3cf2e59970173c82d2ae777d0b36e08f6a5d5dba48b0176672615292e532e06cd6ffb51b38707045ed5fe507d55a63ac7a32449d4f583e6a065a766bbe56f80126963a1f7b442a241862b30686bc25dc28da26188e5410f0a75d46aabb705db14a75fd8034d74c4fcf8641d4a5202a94af00dfad799f0e1107249e0aa2b5c3829c1a516584d767b8dcdbe5ce13934d047e8d241eaf0c5514e1d065b147605fc58c16d043396c7cbac58ecfea2a4b6bc4ebbc189ffae619b2eeaf9b1689442a3cb0cc6b2efa7aefe2bab82b93014f4686900d43e9e7b3401bcb376f2e5fe424922335f1cc4a3aaf265ce33a304074f6e60e86a4d416f41c3ef2ff8e0a947a19cb7759e83471fb7f5fbdd7ae4b509f0d650606c1139f630eec59bd84766c6bb0111650a9dc15e23bbd44bf75f8002e6e98e22746ac298d9210738073c06fc3d662853f7255459f0cf2976f8d6b6008f9f3fca0f889d389d88529b96de59842710db9facc2e0b5a7f50a8fff6c5e274839bed22b45df5e5670970ba4819fb2affe18cd3baa57b0f4a9e57d438ad5d009ef33ca0ec14be01aaf1b6610cea9cf0c98a8e6b8cdf03f5ba2b0483ce0a5080980e86484e1a6304f029883f9aff918183b185209c0a9bc2ad1843b1bb147691fd766990a2ae1a859ad779cd1ce2e9778ee7960cd4c9be824b28f906f3af1322e3833eb3b26912a3b2fd2da5b2ad19c540b9014214fd886c34097c801f4abc05e433eddc3e753c12f58961ae87e20655aaa3030035dd11cf6a4ae344ecba7bb0bd2d84543b229e623e607c2aee3eb88a015387afb5a1548010817796fc187ae83fea57d1926bcb5dd109b3a8ae199fb52f0e960e1fa99267b40ecd42bcfa6b9568344026492b809a0dc42d5fe1ec7885f76ae3fa5868ec6dfdd08754a51be825e2c4d062c8121a8b41e92ce32f04381c481ec10c320964af0ca04dc6c962bf054006894d75e1fbd95755db3d1e7d41e519862df1f3493ee3da91a18c2b3e9e2930c1ffcd8aea041dafbcdbf394c73e90e01c0c3e098edb3df1fba9cb7d63104438fe70c9cb6ab99339df24271de17094cd529767a37cda79bf8a5d774efdf19243d6e4dafb0c31a7ad97bfcfce730600f094fd6b65ff25a0f7eeaecd39dc06de627865d92979fcde10540dd2e514001cb11d3cede4648f12dd3595c846185902eb062a2c9a484709d861ee4093146fbec1832e788f01af3dea25a55722b4c67bb9042731008f8ad18a5c81e91b3b342dc48c3a5d7bccd86d1c7e44f16885db99894b0a73cd0e200177c16497496722466428c8c8e419522366714ea40bb2cb1da1d4960e5f817870740d057bf01f196d2cbeb384ae5779251b6fa73337dee7428ec08008647e4c4657692576ea07ec78339fdc230c4b867fb6056f350a50bd413a9ac0eb33dd1a89baf0a62e885780d4448491733b6282f9c72f661d43b8e4e00ea9209791e8019b0df0102378a3577ff2a522030b18e69481edf222c1340d76b04e3720537bc358d219618c216daffb0c990be2632994b870dca3d6b1b688ea2d9712841de71ab55795540c76449b87165f9254753044be3707c8928a40259b12dd4d2", .None}, + {.Lcm, "7719f48a33b599495be91a3f5f08a421355d8a12361ac559ccd6d0e6943df265ef88f13898217d76e89f093ef30d88cbb2f63e12fe873fc17e16667bd831aa342961eefa966dd66e72279066c605edc1e29ed991dfeccda187f08cc8ffdc2c20f2b84c2cebd527b40ab4d85c0135ada89ad1c5ad9cdd175aeb8debe98bdf4fb306bfa908cd22891a7340b4d7b119824cf0520fe4b693634305322cc401a975943adefa72ab28af254ee3e704103cd50fd625bab2f0dd966c89268027435dbdfa175fc39dd902874ad17e983bdb9a81ef76464a3d762d5f6f1c428aff2c91d654a39ded5a70c27f0fcf196cffd1ce0250de61295074c48237c3591d59b28fbbd9a7485180310c4fc63b2e4e9413abc6b11e956b179c011604416c8ad1aa4d824cd72494544706d6c75f7558d0fe4f40f6cd32f146bfbd1f73366747860f84dd1d90baf55eb53879a4c3752abe73eeb8f703b107d62dcd33117c31ec1b420fe26ebc7812fb5b144f18397143e1b3e3bbaab40ec3de4343b32d2202e6282eb3a16078707b40de63ae3ae7f11ab2d7f90a31311e50d0517724b7fb8facdb19dbb8b0fa77265cf5b4f6d5e19c1793c73cffd7d5233cf4a7f82f57fafb419db5ff6aae3b1d06ab4c25d1bee6afe09360f8cab4624694a3eec6362a467932fe11d2a1b47a4cf4f173424fc5590ade5c7e3cb4cd4e9c2ebbfc976fa4e2eabfa85cc1cc6479c24c5510705560116d536f1d7fa716e4beea515ba3119e80d2542058e6c805a04d0f96ea5d7a89e5f1a10e67241a1184d4fa3fd077b58873d34fa4294007fb587a3e8d0faa73b7a7a8db99d40adf92c3554967f504c647aa65bb611ca9e103f4e6aa4d40e6ccca60c6823a891ff8f67e36437f7e0048258908de9177894f2ca0e9f7613b2d5404cf42870e4d01f209316fe210e0c561e5ba12ac9a3409329d24aa0a40cbb5ca7c24cf5f13983873881d7ae4d3af034cefb008ce2c4c884cdfb3fada2b5f9f0f67eb750bd0b2f1c318fa43702e30d37b5ea068b0ee65fd1940bcd0ec2e38bd7d4e04a6f48efe03ca8ecb709e30ab774309b25d6baeb07c5cdd2e75d10c8b33fb31f8a2ff9a9e04f6c7ffd93d6379fa569e316af2792b03f03f3c0438056255c4ac4c12e99a30c2667414c7a5af02eb0af1c19d6fb08423c7ad6c3f2b14a04925f8a7e669385c7fd3649584c0ed8a75ff5e5f79dc9f3fc6611942ef6e4b8b69825774f12414c67b99b675876cea74c015de87af9244fd0529364b6df1ee5c51b4500949913ff2b69015da4377f1da520bcee391b60796bb5a70babeed6d862e4dd17c36d36063a51761833aa56168cc7e74bbe8c8f4312c5a00fe1c4fa2af27e33ce1e52496c5f9765c1bfdc3038416aece582136c14e0b44798872683c767f88a417be7ab650e88b7330264afe0f92ad675e15719dc63def016d43e296c035f34e978292f9783e85332eba74e14c47765352a8f2a5af51e74222066d5927bfe3679942ac450e181f5daf1d9bb9db3e057977b5dc30fb548e345ce14a20f889333729f3f981a416806009cadb05318147e30e1d3d5910b8689cbce1fdc5986872ed0369ae97c7294ebfeb499670b6feafd7e41f28df6d9e65c7c40bf5e3245c7a670267569278875cb879ded11eb0b38e2ca1256ccb7b538cc62cf9d0c57a84236b04d66e07942a7d400edef0631638946257e136c517e718d945314fa8245f6690234c0ea846f0057ca429fd8e4ffc874725f235647000e4a07f3afe6cffccb9444e3ad8e14f29130e8dba352ab2edcb68835a8dd1c3a3e8505c8d85707e60a22f58fc92f51460fde60a9e84ca4ed90045c6bb7fd531f7d80e4b25f0073ed81b591e1861ce576304669612e66ba9edcc9cbb93c858dfba1da8deb9c50a5094b843761a62fc883bd2af7fb1d11ced3f2eb605d467d5955dfbf381d3dad836979625b9221fccc0f4a0e052539bae72306601d66fedcb83e1bfe8fda2d1693946a52d5dab71ed187797d8b5ada9d5e597092e5e45d1aa120e7716987199d86142928f701e8275a7d6959f47056745c8db70d7e51be50c8b3b988a472e82f6adaffc7154ba6abb4580d5e4061982c8b443241358cdc533", "39618a44202224c40ed9653ed386bc261a7c5c8bd73d4f826f688308cee42b5c8fd20e697b2e3c3b55c63c9dc427e3bfba4fc384de41aef0f0f2561a379a8d43bf625752c69bf566c48773b2b25cc5184ab0686c43d18407bc90429b4e05fd1f8afaa522abc54a786d4657c3ce828a1e059932ca2c96bbbd74b174cb882d094a1d297d05610a6090748a5172f269521c3845f0182ff63cbb6cdb0b6024ddd23bed52feeffc964e5a120cdcb3b7caffe64cc30b200859c3e040ba922c3fae4c7916474fba721bd500aa8422824749dda6928890b3d859fa557fab1c46c76c77372312045fc681ad5d916ba9fffd97a1307c6cc93fa785a73a412c5c456d756413cec1ce83a09eee8fb829c9022ac8d9c0982f88dd5655955bf08e0956001b72b19349caedf7ebe674c12b097da5b3b01429453669ff0189fb618764912d8416b181b428f0280acb936c9642dc6591519aedb76ee09a9d9dc04d672f0ee9c237fdbcff5e3f30527b0e3cd471faba314bd4fb3f55d1a3a1e272429e1d2350dd981a4927042955ad59fd4f13edb5ca9811695de52d2ce566f3d187116bc9883b9a77500b4b947ea247a5d97414b8b6382eb5b1e0322173db598ea5aa7708a17849d5df8b2faaddec90198a1649a7620b15a14e0fd1722e42e1a86ad3484ce8f2387d89ac3fbf3259d37abc3d0e32cca93ad9781111ff58c15cb35d82def52af1346e3cc3c5533dc2282fd35f7551b755d4d85407d9e8399afa1c813638c989df9275246c8a966c3d490517c6ded0c53ac7e9acb550a99575c4aeed40817f6d44ca6b5d47f198e5f9f8d2e3f8922f51c614ca25b5f6727bfb0c7e22228ce6d60330215b546ae73be4cdcd331eb12e5e71b2d4a61ed722673d3d6f15df8f9faa99fad8e810145b29d6e4526bdc93241134bfb31998e05485f793cb3a54033a4abac7305158a46ef3580e7a2ec5e441293159906a4f7b82293d5c021324a335da7a19ae6c18af90f9a527978f7b98d9bb5b6f8fe91f876d3b766d2984d409e158b905d8ef313abf8f7785b4a2ce2f87a0706a18efb50e49df3347878ee8d0855ec36d18b51f63922495ac08d1c11f26d1b8f141026e544790b19f3171dff80ef7bca40400cdaa9c9acead2cf1afcf1e91f61b0177181854578d35cb63c4504e22cbae2ee2713eb6795e6d4536da7f055c89b821a42c937def27029ba730fc6cc1308028a6c4be56e027220de3e66b9b6d6c932656388fb8b83fc5237cf05849500b14aaebeae49f50102046bc8a55ac7391e0d750b8c03b5c3bc374f9c800ac62346a5889499227e300152e666abf1f61aa0d1585359f3c1ab5b55df767649c85c5344ac88247bd98e2c26a526f9bdde78599bb026ef814649506148266e3521b2b6f3e78b18d6be05895c7340216375e87bcff52f8045a9b4105e1a39084a4c8896ec731dce15242a071e227e588002c8f0dd9bd334c052bb556acb793ecfb526f95ab9b984a344a24368d76b4b20fef88e08786bc746b52eed3910b49cdfd5ff7e8fafd59aab9717d93912b445438d29cc85911293e9be76378723cccb6a52e36a847687f7d782ecc4c00e22decc192dc7f8f38c8d82645dc6ad69ed6864c669541e1570a4af53f1b41d8c1cd4fa91c83392bcb5da949ad23af59bf7d7355e87df9cf5a221248ab6d27987d19f7e12eb21d184f059b42fb660cac3305decb0e74dab96f5a1b63260cbe53e51158a1202d900d41eb0ff5e9ba895b7e1e4ddb60db54c1f804676fdb072a027fde86f36a0d22152f09616ed4b2d9b18566735b3aeaf9ae5497ab727b89789feab73dd81d415d8797374055ec5b59968c78044f96eccd50a3ade3845cc87d539349c44ee7e9c30fcb9f112bf3f6135048db0257772d0d302ad3c4d56d488f0ae65e3e27866c858efe5723b78339ebde264c86871260493d8eba295a0e0a42224ef2869451670d0906a074da2a6f1d66e6974187352fa686140c0a32559edb6933ee4f3415dbe8b4d4ad19aaf20c3ff2f965f50fff306aa0ddaa4e75fc1e93e2b2c2d19b02c3a488c54d89dd489bf3dd8a7adfc7531a4746516801bab1ef5cb16ad00cd4f42d6955963efbdff4732245494d01e7", "8e60d895f2e898c385f4258b2bce45b9e5c009325e730dc25024dabf19cd4e0cbd539c2b480b413fd4be5b060ebfa3b4d7efda875292489a04277197ff864879c05eba15a6d0910eceec61d7c756a3c30cdbb4f98a51aad754d737855dd1cdff14652d545ebdf42ce4d64b4035c5ded6bcd40e1c7d7d98277c371ede23bb3f823945a339fc143de6ba67d0e553d5ed59c10dda0525f4d6373aabfc1badd36e4b236f9e110f7d07190e65ccb2630b7d006019d74e4f40bcda30882421b5ab9b71775245367b275aaca02e3725be137db07f11ead0b38772aad211a63e16cf6cce99874f1b23b521f29db211aeec8c48be55d55e23dfc520dbe94f274d1defcc98a4d98301671003f17f80860430b20ea9f6105e2da2a09207c9652377f5e0869811c26e22809255da45fe826c7f14fdebfcc8d70c902b53aac1b5e9e3310b927a8b25427302d358eb7204ef09dd16db76b616080e0b09ea9f42592f8ee4bd8de3514114ce8aee120de90cb24bc96af256f8bd79efe818ff534a80d39c67df99c8ad1c819ed6bed299ca67e5b7025c7331b10c9a35e3d8a54d586e4dec6b0702a926b1c200967ec9d13d399d28f5f36b78f8e5f055e7000077935d46b73ee503613e75804bcc436205ab845104663fc66901a218266cc47fcce81ce5618e85f5339e55184951bccd273bd50cad9da22caf31016a8777436336fb2d9a0a7701e0b94d47f61fa39350f1c04c57c9a9332080fbf0e307773306a2e6ae7f6f437173bafdfb6e850b8375a6b9c28ca93dea7e112eeb3fc6a2088d948c4ad0a29f868f5b14de513cd6bab1a49ebc9cc95704fd4b7ec609949c7e988029834db53e0ceb04f423556a0943382ceb23fe569fa1418b6046f1ac70d740814f2ab749fe57a6fe56212d83f84548cbc98e521155a79123358656e6e2d2a960e15fc227bf74c5290b388bbf609bdb60c5621695612e4cf1e42d23390a63920e1f423ac05199c3716da39daadaf520ee0dab5979c1f6bf04c065197452286129b3135fda72f042fc88553ee57a7bfd825e8cf293110349cd1e35a80b5cf0cc67905dc1b65884135c632dd2db3d38ef5b61ce93e5f581b045c023c02e57884471750ec1f549172e88a7589029b4775dbf0cdc2f816b50a0295ad59e517f435d16e20fa098b29e16066daa4b354a68b90de5580032fe8779e678cd50a1c053c3c45c1562de7cafbb80926986bf6320d20f45695ef57b9560fbb7e1558c500d6fc69db2c5618f4ddd016555bfc8ccbac80cda29f9895451a8c2b8d8ec1f22cea3f37a3502d0040f072be935bf497c3319a5e20edf8f4fd67d4e2bcc32c75dee27cacaa84f01d5e7785767d6ebee1b1d31ba514885b775038e3f9f81bcef68d795475c8c3236f68bcd76729d235052ef03bde2b41af562440012fe1ab707bef7c47ace0024f6b31c88566070f8b64cfd95e401db0362c2d87ebf33e3d65aaaf6ec96eb2d1f3fb62b2651d1a6d58919866686ab46d6175c4451168ce3b6f9e2181f9d6ceeda4037c89a8ff441623593a7aba4438dfeb1d263c96472cedf6cd0af6bb10eafd3cc31f16ca02856f4694525d3f2c845bb356b2761fb34050dfc5fa8d6b73441b4647fbccd760d3f475ec7840b95c5483b2a7a0baac6938655afa565fc371d7d7c6737dc866fc660336a737eec31916b8be083f8df92faf7b0a6cc69c663773e358b98afbb408b3660aa470832b6e7e041163ca8a27b4598bcbe808fe244e859f5f5559d7a7211aa7ae213586a80a978de24879a13ee83c490b56c344c84a9decfcee204892acd35ba08353482e2345b0aa608d963166386353250cf3dfc4f0277c1617fa91959dc45acccbb9afc3e9e5e52e4790086a6be53a6799d763c3782c7db5dd6e87709961000425096e585abcba9bbffe67af1e4f0687f189259e6a39a0930b6668729188748bcbe8c37cd1885bba5976a559d66f47e5a98619884a4f841cc33066abf14f2f1f18c5d6356634b9d7f4725591162462bde6bc110e754dff2bdb56ef07ddd620938c6fe29597cff892051c683078d5bbad93556ea006008da48219177ef3a1f31ba56a29b33b47ff3d5acc711bc750ff2cb30273babd252432bc8e5e999a65e5f17604e67677b81aa14f39506945eae72bdf077bf4e7bdd2ef59d236a2e49a828dfac6ccf740916d57669078b61ea834921a1ce9d42ef06518bc97eb40d42425dd6aed7d712ca6ff4836b1f247f66da6dc47efd6435b9048f86fd678e4061f99747de36e1011094fc544caa678df025462ec4fdff153018817d128092b141b883bacceeb44657b235333622da9d70ebf5da120b6d28c2840a4b56d8df8f2411f89dbabee56f162e70cbd56737e147b23f9f9b422963eb311bf405eceafc3597db34aa746bec0ed47cb698521a75ec491f8ce9de6c5fd81214b45dab8c5b053a970f3e7b96eced8b418bd0de38760744a308c4cd8a010e652902af519de51a1fa669a704d24c2d2d72f07a9ffe18a046695dac3e088c886b914548813d8e28eb9ab6dad4711a2c848e0d20cd57f138363870291d6691fbca017974a5e18e24284645c64c865d992789ad7d8c02fc7c4c57a99961b72071036912bc1c6e80b8f24369a05c20e8802edacf19ba6b19a3c6656b7b9562db87923a46632fd1e18e6eca358b0f2aead23ef2deabdec092ccd64c7a6036eab0cc3a826f9b285eaa16a6c1faa71aaea2bd49563ff5df9d6a0e9dd2fb58c862f7c921d5851a2a61f9fee6f50b0afd27a2e80239928f11ac206368af3fd16afcdecc344a76481b4bba3f7f0bfc1085479c148641e3631f21e3d393bd215dea7de8654d916d64479ad13f62882cad180a8d7f11f5a746377ce42e2777e2c460bac4f41a18f9defe3719813ca19916617f71413adb979c7df5aac54a355be1d8ec03a908a65683d61090cdda55d6386beeb5ed7fe3c0dc1eee2b3d9179a112c1b6fa5f26a940250c3fc691cb3c54fa5516993507bbc89ee816f719cb4d9b779ce468623472cf3a70656a2479fc82249598a00700fc9922c0946ea64228f0a37f990b8a24acc9dbe8878147acfa49617a5cd105cad873194069a7fc9f3d1516ba2a481eaff0fa23884b47d60de2dc8b9f554a17c484e12344f813bcdcdb37c2aeac5c5b18a3f7d3edc2e4146718faac5896073e9fe9f3c82c132b72337d754d6c493516ef196e7cbab4f3463ef6d546f033e195f5f408124b9ec500aa41acc9d59d3604a252fb3149b097d4457ae2bbafabfea327675044863c32ece0af01869906458caec7a4ae854cb48f30ec7ec23722761949f3cdd79eb69c81ff31cc518f1aba69bab32ce4a13e18d83f53cfe8d1d4f6f41db9e22c43e0da7f4db2477e16c0f4c221542eae8e52bb0e9ab3c59ce322ed3a60e6aa279f27f2bc69e2ecef399e2c0787b3e05ba3befd665abec5b5874970fda610f9a8400056deb28eee49c3bdbbd212ad63cb1eb850b6d33067a107ffda560ea307f8fac5b5c2ff942b8ea56a389253b935def001c39475593be05b7839190f3c9641b4e1b787c8bd398a2338cd4c64b65cd47a31c4d5a6d8ca40db0c5d7f6303fcf0671f3b2446cff1a419b6b91cbaf23dd5d811f2e0e2f8a6e5f14695d15ab92ab9fc6391e84cd792d93dd38aa0bd7d912cd1b391a444d3523194ab4727c858682328a67f945dfbf6c02a734f8ac6d79efad44a1551c415ac1e274d20f73a625c6e51c766c0728cc40ca7e9e553fc35993662bd10e70ca09e5bef05aec46b9ca6f9bfa0b2a6d6cf3fe26f98b8806663ea0318a8be67eea60a525e0fbd12f8298b167995909825eeca531000272ca50ce5d7a5c4ea5a93ca6624971890db831b792bb6d0a7d5db3d7ca38fc6fb1d07d84a4a74b91899db1b51516046159710291496d6227b5c38df3d7bcc335326a3a3fac7146a2583698b9576cc457b1bb9bac0c9653a2246538959bb90572621738519fb18f22f292e8411afa904962cd909f521bae9dc373c9281d0067c285881912004deb453bfa811d66be6b4cbfd404dc3c678b92cf5feaddd7815a248a4a6a4e45ec771c9ab164f775f7583f27431d3620c2f3849852502d53a230654c271414acc7886b2cd667e7210551f48feff223b1a6b69b781792b4c18e551d82407fa52d6b74c3674d3e48acc096adc1cf8a36ce0d181eb3955e45597fdee6d2f2eeecb8412f66c4b1ac1559e8853f203f85b0d26b09ea79fae443986157", .None}, + {.Lcm, "-e61330300105b8a6e26b348f073356fe9ab936461d61689afdf0343087df04f8fe8cc5f8de4ea8418f204d38067787719e8200593b14ce9e649fd941af18fa4004d02d1649d0844fb683c0cbefb27909899db10666981a3c18c5391f71145a2bf9595b238fdee67286731078cecd5f4d200f8f42ebea8bea0ec9f7cf936ce7dff41491c276b8ed2339aa3c88231bcd386ae40d6c1746b690a6cee022af255e8e8fecab14b758ea52f43e4e60199bddb423e66fe98c248c8188c533b2afb14a2658cb5ef3aa5450d3c6c64914ec04e680f673442aa6a692762600ec410855b8ddc54af0e3ee019b0a3b9c975262d208196cb1095602f9f11d6c3df66889e2ab0f8b48b5e10cea492def993bc39448bec230d5c83e3ec914437ac492a8cfb7c12e3a68bf24010aafa3be904b309cf7fdf36349ad9f94657b28d433e37b873e47e53e107267cb32d15cae880371cb97ba225e0c6dc6dd241d6aaf3f9b65ba9e75393a29e0d169f74b26a462f6cee3dd8f073c77983b159b796d4d78211d6280fb6572c2b5fef82ea7ef67ac5a45cc532691ae97e231aef769d7a5c9b3229863e22d932e8e28b94bb64668447dc95709141d31e6f20242009a04e950b466207c6a5cb994cd55b7e2a55761a4f93f0af9056c0e305ec9b0de14ab64da418379159e2f342bbeb7af8481f62c0348ad5dec30e912439a03ce4a7f63d2674b6f952f8b025b875b8355f317897fff14827e43de16a13531ea681ee3d2593e604950a4cc7507e5343378656fcc67c2a75a6551bdb3725f9953d0f6b2aa20e6ff086faf935e4eae33c204f39d61b69001ee9f603a168be4d22c22ac82d0dbbcadc0bf6b389707e8cc408fd9f7eb6b532f0e6ffd5d7839733c91530bf63896f5b4376b3d2d62bed528b840ff98ba9db762d04d2de6a247737a6a40318d4a03669082bd2f0174d617bbd841e24860074f325443aa8f7553a8feac7a3286a1bc08bf0bc69fbf3296f3dab954fc39656db7e215b79a1352daadff6977ea9f9b49f02a927bc9ff43e9966256a817a5078ad12afdfab56816ff05add13fff4c82a435b1d02d19cfa4e1513cc144f0f42fc4f13e6bcc59dc26eb693c9c1998c68de65d34723abd139b1f13ff731c5756b8e16d32d6af3cbce4fe6a400ea45ca0220c1c90ac3e590969849008b040bee83ab9c4fe4377a5a8ed0b62a04c4582ddd77fd1df28689159ea64a2bb80b5d23c06c3367f2c9ff9a5d8a35492589710fc191d1d3589ec8d79bd7351924835d6c0174be31a7a379c4ce659fcdff9bbfb56b796847c3ebc1fab36ca63c4390aa4dfa78660f697d4f5b55c4a53d360c2f8796579bc9dba88b29aaeb4ceef033ff255d4bc9bae54ef1bb78bef56c86ac69d0134167779ea4d381419f82150b3f6d71bf2e41062b6eb76fe2c3b2581e6cfbc30b9941bfb5fd209bf3d5259bacacde2bfde332664b1dd169619e81305a6e71ce23ba3c1976e8424fdd61c6c1f779e5cffb7622745ee1786c9218f5828afff51503fdd688c45e5206e707487d426735e386de5df62af446b27c718b11291d67caf287fcce1fdb58a2443b5e9ca70e828084f06603044f96622e32fa6db3d3b1566bd77c539b8f448661014e8bfb1831faeb3a2d0fd27d643ab122ea228a849957601c71c53d9da3f7a1fb0c3de59e3f464208758eaa202b8858a3c0b9c90e1d7fd54d2880e47aa94dc244deb4c1da63add0e9f6b3617452e6630f04a558c62797a1d4612a4576f1a1818faac64f9cc7480a5d76aca4f5ef434f30876871d5ae0b041d8474da31432aaad7b16389a41d4d0752e0a2b410d3c99cd0f6f2a6fbc1991050adf7bc2ae827a5365b49853ecb4634d094c46e5e2c5a4f220980e41b1a144b6acbf93f5209df508af90e0e09f417cbc16b31186be193400f6768c6afda442bb299f9d59a2f4ba7ac37a47edfaf70fa9e22626ea01fcfacd4add7b5001c28b560740d80164022a6b4a58d0fdb5eb8759be49070fc032b51fb39cb4d450328daecb49e113219f36a6345a678716a9f3461b85f6b73d70b6f03e18d3f34c93b8bc0c1ff46ee6e3444d633926e6bfafc948e4f0f78b9cac93f27759bd1879dc7b2f24acdd6a", "3ce4e0cb423e7ea7e2eee296692c1401f88e84687ce9382ff0e29c71f1c9abf2322ef9f1f49c5df2d3a8e6d835626350d8bc46d0004c604e6c0da20d4fefb0a46682a387e0512bc56b4ffee1b745fce66c22cbf24bed4dfa01bfa4a45e4eade3a262c5e42038e144ce87f53c936586a74db6beb612ecadc3ba1388acbf9ca3665b0578711a9c05737dd195c44bb8897567136b59cab9e0913cba4e51432a44ad293e06a0adb689da1576b6e4a8bde85e765dca4a6eef3acbc137586dbece77e8414ba33d1e252a1c1d8238bfc79ff8b784ed0225166a7b8c6d9743d8703cfa9512e1bcd6f10b2a1c0a0a5661b10ce743892c9826a8cf40e9a530880f000c461f9d178e073e819683470c798bf068fac142d6bf65ec83f3476d7e74b093c9f43b65fe2e058ce6375b29a5adb15f38989fd9d55cd537d6ff68e5782b6fc8bab863f02b473b7b56c76d439a29f42c32ada0e6d0a0fcbd34d83ee0e8b210187e0aad68034ea08094dbe4493c84e867d73030339d74379637c1b3cd3c366f35a0e0aff82c66c079574c73de5c0df85849c1b523e57bc2f70697136a6865819d622bc83adfe576cc412039130f410894bceef2c5d489102240de4809f56b99fed8a67bc6a5eb16d228039be0dd0f95eaa28479738b2980be48bf3da6d9f0b952e1764491785b2c8adb2b3aa2a663530e0173f79ce5621df06956963b38ce7e64bb44459d793cc1d2a3d37221c05b1e375b839c4d2fbab9643e2243656df7781201ed87d0704f992cb5b889e8b402747b260b5b010266095516f5691be37a95f1c254ea6bc2aebd832ea2aab770ded54612d736a24afb58c4a0e05a3258c8e7f5615e9c83d37b642e5df8d509c0e0394414c14d5addd980b227a6dc6c1f06fecc106be59d57ecdccdc4924e35178dc7ad45fdf9094185cb462b0f2dc450fb6a2282a6d43962f3724d0e5dbadfb97ed44227ab7ad432215358a1b6f6de6c0a7a367c8ab4d849883a120263eb4aef9c263e24f67969004c5cc8b077e6d41fb5d373c7da99b9bbd703ac3411692e0585aeb7a1bef8442ba3f9f5bc1f0b9909a3186465c0aefb5d63d55756f5aa31edcb4e954f8f00880f048ef968a10bfeb7c2653d2dffe71c89e87cafa99e0c0f19657f2e9c6013586922c3069c9427ff04f9e9e6236b1ab9636b3d1618c49e1e866363b84c723f295ac31cd45d296b561e8951061c72853447e1c2947fb040ddb869e3dc1fb99e2ff725f5afb9c304eaa731fe78bccd0191ff17042ef5db52ffa57592acb027068142aa144cdc00e00192630429acb2884537560386d1d49bd28c9251c39238465ee1e4044240a0d9ff309b5f48b402f7452538e19a29f5305a61a16a6d523f13f2e27f6fcb4b8f31ffefec258039e3f64ae572e90958b26f0aa63672d172277c7b60ac8c710891d53c1feb07e0ccf6c61a7c98d3521af1511eb9d74e5b5cb032543afad8a48557bdde466679bd9ee7aaa3df006d90c204d3a3ecc7df35ea740578c6657382b8fb7cf2f7bc97c39890fd07f83eaac5ace68e02a825f7aff1ab92ee6e4d8210b8ae19cca91d53559e15515b2a400696e48e173d63f80af8cfa2277af9e16569036b31be933cf753a954267c7e9c77cfda8a7f801aa81d3be04629db1b93cbac9ef8d48fae454e0f28e7f267c7dc140207d6a58c6e6f843fa79ed4b71ac56ce4f27527b58c48d9898313f79587fc4f32afa631d71abc0e1caeed5a897e9c0f9db672ca00873afa37214cb9a9950858820b4a92759724787a5b14a07a69552beac638ab038b231e208afb9706a48a4f133f76a5da415dc6f611118e9e5e773b64574ce884abcef7bed7c117db484bddbe558826a86e40b2f9d2d6421d4775a0c48425053ca4af2c827f2b343bd97d408a4d185ff033e688ea28488444ed9601665c5d83bab0c9322390a7fdf5546ee68483f37a478b5b9052e9c7f597d7f3dc151cd2348c8d21a410f2c9fd6796b5101b7b79c10f8df0e921413d6a133007ccfe69cfa730c16af1f79e1d9811a34d4a4e55aa9db836844718cf1bb66e25ccc415baf72c6318cec7a370314323e37f18775d87c146084d178b4ce2b16588fdc4599deccdb299f18f", "36ba3269a1e8943bc2e1a5143450710ebe726eb54e9cbb1254d826dab17638b280f165092f4f084a1978b2323421f623ff270c96ea419c212be980ac424e3886bf31937a6351d2c8a668b96c76d9936b81d65f6ffd6a6b3034fb790c64475253d448738049245d9baec1cc5a1ca706749fe5e72687d03d800b3883fea2a11dddd6044f3facfb46b661e242284326f93195ae23d352f12c1bd7f3921ff6655e56dd7c4aa697ae642df5ec7fb95a9e7e3ad9665dec2d556dec519b938ed497ad7178924688b0bf221c1024f61b82c22b2c88e72a7c0b2ed09cd43edae81e09974289f85eb762cc4be07272bb6a39fa74744f963a3e6bd63a9e46e7865d79c57c51dc1d1144f6105a40d6918be0b33cae88200151e0bdeadefc1979335f074d4d650bf1974719d28882ffadb419e796006258ab2ad0ee942a4e42a1872f0cc44db1c78af51d0d1a6fee14360657b11e7feb7596897a7937595992d30622a8e280c70e2eec4fe74937c9912ca06d6df6c28ab14abf797565a2584d1a713104f16ceec1c4e1361f5a267ec5bf0c7449f2ea71ab73719c6d11d5b5bbab54e840a92bf82675baf50128b6ef21efabb94043b99e49a846d7548ca26af3dc5b1c05b3c00346281cfa0806a69f67bafa7ac3b3979bb3712bd84bc9d69e2aa6c39aa928d881a3979ebca6893d3714a8687d2d0487cba21dcb84d78fd76bc03f02d241a46395bee61cdcb1101033c5bcb11b9aae54952d95f8a8571b89505c959619726763e0688f26d1d26e98129a6c74a87f504f0d8eceb92b8a301f5794245d9989b80d8b05b16eb5880c0028ede37bdbdf8bb39a84ce395adbf26f6f0b7534acb1d1e7248b09e2993fc6c8859741f33c8512891b4f7a6f27b61e2e949a9d0bf4997ac48b4a80afe8c46ccd93c6a5dbe853bf5954e7851e6e50895e1d6834658f25992da4b967c0abfbfa9d2c5490e15ed8b3178cebc598fe3cc63135dd7425e333481cd9b46f2df386b0410078c96a4066ae9ca41d8a0261952866866554ee5bfc4bfa7f82e19070347102020b7e112e4bd1955b2c4c10f6e306a5ee1e525877a1fa865b279c233c63e263ea0f8ded0bcb82ae766cc7e530ba53a595791d4d0201cd2a4011ad3cff5e66588a475e72682414c303ec4a72881a1e399ad5a30c2b2409ef874f53013ec361986b405f0373cb88ad6b6be5280ebacd0bcad15032e6fbec75dc391942dce53ad5127a1a4705e5b51962f71ecfa6c10728e7831bf1f35c8368882870c3e2d9d5c79ef89efcc95387cf0c6c41a56d9001b80f66395fb48439fe8d0117ee323260db164182be59e18a713a024117421444e05208102b350f972faef83910d154b165d40f434b705cba1d346d2c4d191838a021f45be4aa6a77c8b961e3c58e5e24e69534e2b1716d81aa5ced3b6da3860be7fc9ca5bbac3558ae14af23cb6ed13e3014e2ed9a2214b2c54f90cc26502971c2be0531fb6089cea262e39aee806b0b9a56c8d4e34fecd16231ceee689c1e297e2a124f8ababba64e252f51d6bdf6d8caef897353df12e803a4e6885b56373649e0077af5ec76e2a2460af4a0c787a8fde770e22efbd9d19c334648f9a16a68237ba50147f213671c68c39340060e55fbd6ae3857c1734d4bf421415bed19ac5eba61b0da3d5711e0a55190abd954153c8b63d3396453653e1f69d96546f8b6d4505c1e4076a08685cb1a4a8bfe81faea473f71b8f788c775632e2831ea39e48f2d5e4b2709f5549c75317d5b9750f0d4c3d7b77fcbc01c08d54d6e4166ecc0c27c67390db7ad86d996ed9255f28d4e20ec216ef2ab72730bbae283a105419a188c9fbdf3d54ed59ac3f6fa1951fcfcd2679b488ac66674606d98b3a8a7fec3f5a1c4c83bffa2a7fc4caccc6cfc60dd8e059c607b0e5de985e897dc227cd6d686c0b9a152f48369a29042fc748f720ab56c94db23fe3e9942a8f23a74a6441430ad36d637020b2208fa9463d779855972a5935bf1fe1f6d879686ddefa7cf759269ee850eff8f60c8a3f4a92c4435c4b809a11d5fe1a8b9c34b64fb252119b8f5b831844a1597ea4bfac1d8927dd794d672a685477a79c0bb44eb59c50dbd39f9aaa8ffcfe8793cbc78e2cb4477028a6bf44864036959c21859d1844123c4ab629d4760fda78ee5b9540b69e9d5dc897135a449270ed3f14d1a4b834fd3a03718efc3a6cc98fdad4d8c90cae7cca366cba93ed92863804f5792cddff5172f2b3588c7a4d0c11786fd948a571eebf7cd270ae6d3d304dc811ce8307226cadd7e739a48f884b5a5d82c233b23d73a85b6a487ef58aa4fc0e8a752c2017ccac950c96aff3f11bcc2eb522cae560581a68f6bc3e92b9907a901bb5b0ed2969bacd8200747a1fe43724be5d2e31b0271b05a48abee288b8d143f1661b1d2e0a3aeecaec13fd11fe463d5b780f0b2973d23086f31d7513c4a434d3c7f5c841630504c377750a6ed1b7817f82e6fd2908ff52926d0db9c5619ca5e27eee289f6d75c79222b636d122ebeddbf43c29f333a27f9acc91fe057b6b0cd2a964f1bda170bfc73d1dd99cd8c5e0471c7f516c0e422ef3a94886c03547c74473eef4469da1f23dbb5a12d2d582931ea1ca1617e459901b9dfd6e14045f96fe473a6905662a4741dfb445ac718412c42edd7ed2f6d57b5db2f5889e347648b887c5ee248297d4a902c71755bc328ca22c39e879095c530f45814fad7506ebf938a409c7e1fdf00f6f7e6d2d62487d95e0be6c14aa56ccb64bc117a846df92541e92bc5519d04407cf78917e87037f56e0b78ea1bb4d7cd9a2a2032f11911f3642abbb552999c4944a1f637dbdf5ca216d0e5b95bcf94a8e6ee418abce7bf6b2ad164da7978d25844c802446bd46bd69f03ca07367e48ee278cf7f6e091b9ae88af451a5874eae424280005305cae5edf05052ba25e4691105d378b52e4563ea2736ef9917e1be4a1f373c16b4b7f9db7b46280ba771062baafb269aefaa0457c04d8a9a1e04aeca773777e771cae0447d9a01a7b5fcbb008c17e02833ea1c3dc2628761074ddf580efc2c554fc87fcc7e09937ba208ed8c434555b4e74f76fcb090c36b2e1e9f3ed8956cf837effdc5d3c64b9dd01821947ecd8f5763e10f61c1f2dd92af32b5fb77c8bcf9630ecb5fc98ae6decc47d4c216afe1fd802dc924344bd2cf1fb094fa6939d2fecec6ef9687dc78a1e374016a7553c8c6c6af616e31d62b30798d99080210d528c2a1f2af67ba12adcb207c11c84a5f1c8b751e13ec85b99b4f14b83bcc5a0a5fd1cb0330bfd83aed35b0b938a2f8879c35ef1bf810acf88f1220d1ab9fd88b74f8fe8d1b7207cdf60ce2feef84f81ba89fcbd8c00bf97b305e9e0a46ba6304caf373885995329750fe1124d9a0fd33925b97758f66a3a11b5a61e952fbd931c552bb666422785e648bdbc0942ce0e1ce59cabdc619bdd8fe9a537a50be72e3a907d5b56767a7666395d186943e5833977b09400267b8f4c11aaaa341db28172d5b704ee556fb49a4810c4dde162d786d5a388d6e6803857580eaa3695d9cae6ccd760c794a74477620a0268cbea007f10b66eb32d7559a1b9918fe9bd72495f56efa1f9935ed7c124b31a487ada46acf0fbcd7160fd2776f677c11390dc16204acc7858e494db0bc25a6d9b85fd167cb8304c204d258dc7b4b783071bf21fcadd30936db9ecfe9d62f13f903d308b0ff749b09ca5ef4ca9f3b7aec255236012e0adeb9731c1ad2297d4132cbf3a9b105d4515c65305305353e3fa9d04bd3c200d57816a69e3d1030f1ce2ec11f5ddd2f4753bd97b3660bfe5edbc513c2219c7ac4aef6e636fde707d179bffe3beb80f8068d49935673bf64ebc128d743e0856f773f825eb6703638e0dce559dfa0dea5b529c6880444dfcd9dc650a093139c93b72529a676d9d4a0c257a210d3c433a3994cd49e682b4574a0285a545e0037b494f3bd129c0b82651d583a8641be4e8ce5b51bf96c859f8e315f94680108941b61b813715a4c58dffbd669f04b4f68e52fe55f90f5e13062af798ccb3a0686c559ceedf04a94b97094834ef58ce56ab2825176ad37b7ef9e29ff95706a61b89579f90473bfa0b732754a5abb6843d43eaa70a15b1f7416e844027929cef9c64e48a1f561b55893ad91b3b9827cd0a6a7956192e81147cf924ba179eb43813381972ab9dd5b3d44de2b9c701bc6543a741b652c3c686675a5402415a7836", .None}, + {.Lcm, "-2233409c6057a9b7affd611229c4356575d9eb1fdf0d0f2c003ee4d7fdba81e91c6722cb6b4c3043d8937f3aef02ea735191d26f22d2ff3e3f9967a87ebc98e82df487b8e16c62e62b255712e20302a691d4cb75efa5436031f30c7bcc7743cc5f3abd64da28a772bfc10b7d715183f850c5f4c69494b5c2c233557134944e83464782ff97f9572b6cf0fddfa19fab4cfa34776a62ed31a8d88b19d969e873810c28c92088300a9dcb036166ecda649cc6c52cb94b5a0c85b87da8c0c5105aca85f1c0720d96d2569364e43d1d7f5d3fa79412da4b5a7908604c543eba7e942026f76832847458369de7b172d1a9e4f27592a57dbce0311a8871d6cd1e6576581f7c8777e3156e13324a9eda9d2355f05c60d75c7fbbeb3c78c57e0caf9c421b1b8853b5f57d64b45130919e432eb7d74976c30eb65b0674d1fc4077dadb19e78af27f80496800aec6463e92894fdf60a6431cab07e57a8660b3194b716a46bc2fe69a603ae2d22a1c6f602ec1a5ba72f67cda694e086f222776d26216387ee9e38e5e67e5af9f1badf8f35bf4ec6db256f8d5fd9199e2230a5fe046afdbac08109efd9daad62c326c34ceda07511f53f10de88fd9c9936668b7418612265c736034265cec2b1b5f736ffb6eeb142803edbe95a03bc5af9b32f4fcbfbd9b4f0ce1b2241cb43b0d57f87a427b85bd80046a36d8076463989bdb36555fe2f424f8181ee4243811e2ac4077130edb88a1093f69efb24ade69d93613449dd34992ab06423e1467a8c846b74964f0cfac20b7fa6a2215f0c1125cb16b62673ed74c82e02df98c85731084b04f39bde8d91d29f77d5d5cf2162d33e151b054fa669cf7b474e3ad78b20826ab3f11998598bfc8d826db4b209f34de150e287c60168f6b5d81a284b12439ecfb268268b5f04c84e5fec508821d2d45faecae97c77eb6722d846e3c6e719fc3be7676022d8e54620265ff6284f96f61c2fd3e2d31b2d01886e5790460f3b966735b3be0e0408fc34e7078873682ab45b4b080ad725ad690f2497a2769d65d0f37ffdf9da00e05ed6d3be06e7f0e9a4d0c41ef898c46b031384988550988ffbe77182bbe3616065cc2c6d05ff046ff3f25a9b70ac3f69748018a16f08267d0750adfe975078a7dc53a5199f00eff8a9f491d9befd7e83c37193cbaa24c3c77c4a92ae9e8f64319a6dca1570fbef509d542029b175f838fc78f876e51641e7d47bee3bcaaa606ca994d13ddce1cf7305ce18801b456ec45c53d0e21471de32fdce8ba668f53883f0952d1337d63dc0987c5a699d7a667abe00f65a50e780761c771f9c39bce14f8720c48419da74097a9326f52fb21d30643ac2cec66f4b2977aa6e58b49ac0cfd89d26ef58978c86396a9c7410e5ad41b8faa34312df00ea5f8077dab72f3b64e089d74e47073b1886b00d2940ce1cbe1690943fc995f9ec04dd93500393202d420ae7e00d3a53b9ca829dd413e1ae117f865e7f2b73e9a9d37dd33168be50a6445559665bc4fed28919bb5437d9fbef4eedfe6266b4174f24b3013f9f178f2fef466ff7f8d887d16c6336258df4ddf25bb2cff5e3af4da3c522be50fdf60df9d8a5cf6205f2c96ab5d727b7646afc9aa4d96f49ce2f0fc79a1cd6613190a69b9521122c6f1e90571a053d566d8ca9afd2158cf42c671119ef9ffa7f929b50a494cbca18953562156b55ebb30b2ca4bd629224f7bf900b36dfecf75d60413557813f2056f05962912dfdb401fd33758027f10ba61b000e1dbac6d05f5016cb75710d71f4b4b02d3a30324c642d5ba3d7ea5e6a79c03c3c70e754e5417d2d17ce18d87d33f27a25192a1085d6f146de9d981f1664bc5d9920ccf5e09a9262cf8ff65054886a006a0b8c3fc113c5220d678bea76b4a8733df02cc093d4badc1cf5782d0017b75362cee7f1b06367137d17bd9b12158f472078ab0a394cc0ae95245d03625fb23bba32599956a4ae98fc1bea83ae1f45e611baf7a06419b7911e0a9b3aa8020f610d4d916999a5bd0772a6cbd4f95aa67cbae1617912874f9af8b7402fb5444b91eaa68b530d73a4307ca78e4e6e220d05d407cd2baf468e485dfa8be127991294ef572c00e422c6f", "-8b54293296dbf229cbbbb46db61962aed91075892c1e27cac54e00b14d75638f432585a0a557db7b0a9f900df4f7f12170ff5b18c0d7b511ffd9afdbaa8d6b36f3a3a7292c30046e834ffc3643cc2842c7f14a9d3d4952edb4aef0e86a684bc093026a53906c273ac64c1ea2d8ad5c9f7d5eb0dce0265b6c84ad49e6ef3fbe60162abd34db27884613a73700aa6104cdb71d6c46bb7690e074a353bcc9432d7acb52a26378a520f967d75c30af296d18f2e2abb2336fd77495ded3579cd8cbde036ebe244c2cbed1aacfaea09ea5754b1f0b4eabb49ea42fb9cf2d6a872b533ef2bc912c8e745ff57fed95dc2916f56306c90a8e8232861e2643fc2a31df61d5ac19efadcb9e1c482b4b3462f99530c6e277ec0793bae15a35069e4f40fd7a5c8a782207dda3f750cc3e49f202f194bf816f6032ea3c8285e1f1e76eea214ef23d0108269bf29aa955475233c62f461d4d7b98624714bffa3bb3bf3fb45df427009e2f8f52a336c6620ca4d7f82bab2ca2c89722490b9bdee4b210dce44bc41f9c08ad8f3f20b6894fd7c2c1e602b487475ac5ded6805b5d3df18b4c3d08f66c4f7b102c37635262e0101e3318f11bf1c1c318a434d8e42f157266922353afcb4376353cf0dfa2862147efa38a448f9e92f67be76e42e111d6e282379229184bd72973d1f9b3679449d59935cbb0896a3ab29d2d34045eda359a067ad29635b4bf9e49171d8e7959c9dbf2c80240a4ab94ffc9b393a45b8017763bd6f8862c388847076e86e4409e56e5e994c6d4262f615ff0102e7706596c75e6ea06ca0f26955dc0262b171a889d12e0b7999e8848f93b70131d8b420933eeeca9118acbc29a35fac7d5d2cce30774c381480f3559dcea5d06d0217a252cb4725daf8d9e75af9308600759075f30d45c1ccf0417c08cd665832ff3f846457cf54895ee6409432a3f2d4d48d73163c008871a86312dbceeff9d7ee1193218000070821106842e14bc28de32f71ea59338ea179a79f149945198aa10776a2f604856b2232244105f90d5854365d38e9bc62d4a9c2d993c6e877ac4af1a1737fc859a4c6010af2c77ee8dc784f592b8522257c78857f6ca82107c9c841fc7534c326ce3fe1cea0b6cdaf7014fe784b9eb45b22d04a8dc175c48224f004ea88631c6086d9cee345d12f127680dacc6fadda6a4bf232ed1a400b8689a3393871ac8694f9452bfc4a82b48676010a546f4113f72222a819378258d9ecda2f48e26e0324085e70f27f7128670daf7f205f90125cc11a070dbb52baa4c32357a333e7ca9e8e3a26e5e425501c7ec0ff42b22ffde71ed69c67e35bc252cbfdf5e085db86801eaac0c95a2b3dc6727d2daaae92e4e3a389cad46174f6ed64856b6b19b6cea00c66f30f051ee50a1a6ca040d74d97aa4953a821d5cb34d0d51c4afcbe4e1c17f1277de3b64c225cc7af8185f3697b68032a42b38ee017b842904801a749d186119b0287398823b2c249c3ec6d8974863c7bccc473eeff804a91c1d846055bee72f8bd10c38ba8dd4b321c7587be3570f3db77791c5b9cb8e81925d2010b165ae5887598653fd920a9f9d0820072b90f9340abe1c81cc5d2eda8a4ba540ffa9b5a54f4d8ca45ea747b305d791d96acfb9114fba2552698d7ae6736fe62362015b877b4b537346726ae0e5d72c147ad38f87e6b4bc686f80769f2103773a5a9c3fd4455e58a6e33f5297a1eaa0380a4c3968ee00e09d3cf09ddd2385bfb0e098b55ab3e634693cbe401e41a77fa6c011e2f24acbbf2243db59d07ac3975607699f8dd4935d9ed4419aa4e6ec338a3b0bdbc8311f9e50dada298d2ff527b349ff2bb01f46cdb99d734fcb667a58ce9384daf265908e43176b8cbbe0ab181103f9f0aba1315052980d14c535b4d244a1d025b469ad80af973c5c6e6233144074acc2ec4186f39023cff667a8c96365c84308f9c3342974982523225036955e168e265107262da5321d8cb03ddfa4890fa92dbbd4ac258fa46ee5c9b52e40aeceaa3b88128dc2e4319435fd5d51287f1b2abec86c768b7902b9693c1d8f8e7f6ad329e531ef3aa50debb814408212bd6b9523383b2785649de02982e8cc91ecd2c790", "129d1267132249f136dc903dac9c2117563b21769df5ae8bb4d7887c946b1c453f141318c55f1e5e7034ec7e976099d8d1e2ca737235b4ce0bd53b2317479c55c10101524e0796ffa6e9f1abeeb18d0a8236b28a3d2edb309d364f74ea02311cc863fccda19f44e86f34388bae58b53b5cb817d66efd1f247fe0ef9bda82b4ccac67e55e253911b8d966792c76f7616dba13b4d826c8a7679bf6dbd4983232f7e6f1866a7933ee12e33e8b1fa3cdde2b47e6948c4fe1011dbc3f048936f2c1cf94ba05be4c01e46d6ba8577a60c257f760c16c00c2b817abe4f017553682144909669d4a9e4ffd0fe08cc0a9f6c4530c5e38168337b6e079ca833cafa67c47b1c8dd6749150047a74b99dcda8a77e8422a863c595c5c8314ae187d7f769d4dd9f0e5f9c414e13c8aee31403368e36eaecbb7a4dbd90aaf148fed640abc294ac9a465112c36afab3b78861952ba4c5b29677f131d44e096cf245707c1551dca8d7d47d53dcd1f37c10997b80eae88409c89aaa1d5b42251d1ecf9511fba0ca28005777fff5c12f6eb8532ac1052e808650a68c82205c6f7a7811bb76ff4585686684d24216cf2862cc2c55f26e61828e207f36775779b533edfb85ffd3dd058e9ff6eea2eb00b810e4c47436ec835e3206a7d8db1b8f241d28257234d843152ce5b349688e28b040da0b170405589a3d53a844ab454d6431c5d6c13b5877e1cc687b8629491035abe8d28b3ce081ebb086cd695da8b6a289102d09293c148c4ea48acdf0d3279424df8cf39a541b41d9fd3bb34c57d547478ec476da66a117989850848e15e1f78f280dfc16a24fe5915d7018a64341b6b22967a765d5018e0918eb99db202ef14803df81ed4e03b44dd3abdf5ef60816c928282ad7c769d1925bea525afbbb042dd19ebb3561bf23561df1176fd9e707d8930ccb7a8020652cbcc71aeef866230e90f22628bfffea4721828b8172d6e33132e4444b419f9765e2236db6483b435e43eb48b454550c629a0dab00ea80fbd3f12d9adafb4a8a98545d149bc96c6cd60f0ef113deb4913c84478859af5387a52bfa7e71ba02d7cd86eddaa595295d5f6d96fefbba1f28eac127139878ed9dcbe4cabe70a439a7ca15791702227938020f4b57d1861be66efc4d5a895368c47c2bace7c4577825786903f89c7bb88bd050e79def5dd3a1a7158325afd2d499e9da903e9404eea72c19a648c13d40597779106a9a3899cdd7442d910938b331729a07b82d06e70056095bf7cd1f0f941dc9085f7d3c02df59c7be4907b0e5fdb5e766292bef8d9cd0e8b69944229a64393410b114bb2d2e2332e44de4b3f9916de02d9f260b0c3fe6725a206dda3876732a9d1bee70922358fbe9bb284bd5c551d6a414beff76f4e303d0270d8cb6a755a39495c11e025bea40d37e9aea55e15aa5665510ff6e7bb0f3e55cc801d8e4979209adf2c52ace2a5f85b25527ad4d2e639724b8a36c3a24928b743fae7e2a16b0ddae480d47d6369b89237b61eb541624d5f625cef2a0110aa59dfee80efdec20c27f983db186abda6dc2da7d254ed08a7fb97c427512dc514b563a99f3c516c54ae34d15396295dd0a1bbf30899bbe0f071e52e328034ebf8e7f3843c5e285cba92092eca11dfb62698c4f849788bb4b271bb4ba86cee7534c42b997da9c6fcf054b68d9ce6d1df78f578c70cf7355cdd764744e85919ff5f598f5f80ce21a6bb865144eb2325f5a35c03fb170564872655cfd25acb6a938899bf4f01f2e5aa066916ce6b8affceeeb679e31fb2c24a8880d862fbb77a4aa0045c134f260fd6739a95e9ecbae2eb9fba31c407d11ff1171a8f844509ffdf63b8282126bac4f1970d5fc913e1b4dc7f49f71dd0b91d0db5aa18fb6911772a835501331e5bc82b12f9b59bfa10a3eb5faa6029112cfdfe2e3151aef618ff048754251818120de2a5cf1b614f2dfbdf1a136b4121e1276110bfc5d4f9bb020ba824668cd61698c4c6fe63bf35fd78b41e95ad9c0acad9797c373ea2a7b7fc626b4e728fbd99bb911e46c388d03e3f8290bf737dbcb4362b1c0ac50c99a6293b06c89d4f30d22fae3fcb98fc27eb22eefa55dfad0c5ec736c65ef18a722293895cd534d0c640818cb7d209a1ce5e4cdcb2ef770b312c4f3980e48ec5c3534367ef3f8d95d0c352c07ae26c10d9ed3402f7fd338ef32c49887e910560274cc221a41149e2f03ebe5bff982a6552925b38a05f2e97c4ada07e546d0625b531ff7179282ab53cc85220c348cdcfd1fa42397b449ee39d8e52256b67b8f8554d0e81d21f78f90729032dfa76d4bdc52759fdf1683510b873ede3f6922685c61b1329eb7b4c890d96eb30b60fa5d206882182471dee1f3e733e8815d210a8c6a19b19ef21dcd4b743efe2b5d5cf23f89f71843efc327a1969248353920d8e89a5e9712e946fa7cf2f36e8da195e388f5065bb4c6bf38af135f95e759ebe681cc90c3185e0d610a2004df425ce8ffb62553d08ae814ff263877e6ad860ef5c6b9b0bb88b24a963b2deae39883bfbd90d1ee9186232bf225f80414a1d819c5757c07f7e97f658754900edffb7171b88c59d3f8f1dfac5fe5fce51b3a7aa5353ce973246fab5a28e9bcefbf64fc6be311736a5a436a3883d53ef773780f679e3550d82d6ed48ec0c9edc43ef9b2c12f9065e4741becfe92e75d5097d76a0be5fc7242d64f6e6af764d8ded4862dd100a9142bc495c3198e57fdd8fe0bf10a4e4dab2f5cd3c3179c974704d3d97922c12b43e3d9598f8d0a5f6781b89ce82d27e13cb62ea0087a729afe88ed07b4a6e466f2f9bf104c3b8d213b33d72107f0ecc8530f01ffdada129e9069f2f642c347968b18025635a731cbbecdecb9cf75b79879992056e548c786491c88396d25bedda01d92a6c8229ff6ace61a42a20e66e9fe18e375f6760a868649d0c1433181af4647d19d4caf8204eaf08f89c7c4cefdbf7c93b1e1934d65bd5d0c03bf9e74f8167087acb23590ac67104dc87c3653b5b0bdb8c280790f35375d1c5517d7e238894e40dfa75c3d05ba56d319f7e74acda8b7f405053a754b9c8e4fd81840fe3189a2f621fa16e4cc98eb97c3b1d66d5c154e9640ebb2a6eb2eb7dda216f578a2a09d0d973cb4b5b71c9c89acc5ecbc60fe228952cfc28e53521a418ac5ea24231dae5a414fea8d6ccef01f6242286d872b23d06e7a4ce51604d66de72c36310c505a3bab769d84180d5ee7c577a963b1a0cce7a876112f6683a475d7f5b67da36cad35934e8136b8527c99b0c3c65734bd8b549a2f137a813240139411f41b8e04be16e56d80b4870e39cd16bfb6b2f2071f935d7e09d942de597c1eefb8f91047b7e76ac4e28b9e3bc68908008bf96767b4eccda64ddc7ed14657ce7a0b28eb3c19d5b01630a27b4916f34aa3acfdc31eb3dafb333e95f5122d6322395ceb90267f405d46c0961cfa0fbeaf9d9c45246088d7aae6858fe5015a01fbc3e5e8d9f017e1ca27a6d621b8992c9ddaee9dd5e1be9c99954ce783fdcc5f967ad27860ea1fae70f376ff6af0432112ed17c3f5d68e4e24f5d187542bc0ee3845d999b2d5681d652c285b7ea6d8eecbeba72d6dd4eb37c33634646c0cf22300751d9832d31adf1b8251e0bfc369e40e2154f704459077189d59276e54779e9a28d5a70676880f6158297f30bb53a4547db992d3dfd3e4573b7227032f80c0d2841d637977c8a8e6a6f61102cc0c2fb16c2741c76a896e60cd4cde4bfd341baba288da9af5b7f929a666b3d927cb0d827f9142e13b4ea8581c2f7e91da66f3f94ce2ff8037a2aefe0e2d9d7d2b56cd4c95fb6c2273fd6822beed7e377f1555ad3342c87dd76dd81af749975fa546cbb9cdf617789d9b43f222ed352e3b0ea167990f065b6390c9bbf0ab12d383bce2c2e09bbfe8bb6d87b2655e5e8492451dcec8213dd010a94e6aef08d755e5ea09c88064a940a50109de4b057c5d8a711ee28c905f473e90905203c6a85b7b354aeed829ee6be5e9458da58191a35472769ca4ac0f8c38c8beb9c2a218aa763c249be72c31337c941e9a7a1ea43dd814738c30325c179f76ebdcd1c834c44d2b1665710910ba7ba61936ad36612828edeb8b1dd8a7bfce4fde172da29a2685a4ff66f9c67e57c4f2395611aa393cfdfe120e325028f875c929b39a363eac59a8d5a9bac653d9cef815f490da566b7062d0f7ecb3eb0ae349d32d670293b3cd14770", .None}, + {.Lcm, "-ad00195f994bdf4a5e5af19f4daeb881bb7b02d405361a922bc5ae3b3a15d616bc76e937767a2409f359c0ecae45c3c13d70a8f42b2528dc17c414705f83709c4200f74ac46644d49f405db211946cf3d06ed3c5fc0b145207d3208e835bee56de50847802afdfcb3058e7070966abb00044dbcbbed8068cf691d744b4397a3d358906da4d4092f011d2b696387a87cf271a48991d4ac46ba0d5e24c335a47c43e726d4370f4dd1f9fcdcbf51704162636ddb5d5342f1c6b3d27d8fe95b9814239108a9c7eca9d044b67db4ff977c82bb5054c14c23f99dd668b38bd6efef6f59e969c2c75fc25ba8c915d53a693621cba739b54f232e7c90dc2dd049166c22fd2c12c7e1100f5de78c505fd1eb35de2e11cc2bcd3941dc033164e4126747b6b2ad321f7ce50bd685ca6b75df1078892f8d7bba34ff070ecbee9ef3ff88c09d8ff26263a5b0cb07311755a0d24e4fef77413dc8ef27e987abec22a320ca9d065d21977f9207a19c93e88f84ff6878cdbdc2faa849e976b44bef1572086113cbb82d8552dbd36f547e863bb0a6210ec82e890b5cb5751981f02b6d3415fba0d32673b591e8b1f11ade65bc0966cfe6793a3477d2b9fbc45412eb5d9041a379ca93587f76172567942bd1f8bca8efb5844747143afad2308a5b22f2f41baabdad9a89e62b1578017af60a385b63b1e54e0d11dfd89cfa2483240d4a5f1d192a1bc0f054bbccf05c7c4d3a1608579809b80e64f6a9df5b9ddc08d55ac9ed539e219cb2b65582587ec2087de7103d3b4f38682df4f81f385980fb6d49588ce31a3718e6a2a4911a634a5e0a40fe09428b35450a6d1868808829597bb0dee8c95c05cae6aa4245858c15bc8ce82f42c5ed233706ee600195ad2d4f49e467bdb6b963620cbc73a398e1893a8f3e1a3e36c1beb26e79e6e0348116ffe5dd7870549bca99162d8c4d77b9d26cafeb4f1e298d187f6452413c0dc8bb81c1c26aa43b3c25ec0bdf9e8cce075cec898c1e39e8c906c03a30f0b6b9216aa3e6d9099260529badb1a9375a272695b31a7cee203c17f50495f00b38e30d42b3efb6ad3415aadd9c4314d9bb2bb1e22d91cb3fb2db0e117b505194db815efff9417a911f8cda2d8b96646d8a2d633e00a1d1bfb2cbb9db3e354dd74c7e4b57250b971f4687415dae10679ec4846ff1bb0f9fb3b6c2f0872672a60b3acb3795da8fb016b1d2102f4bf41bb3dfed63a90fec658d3294a44edf63c1c7fcba1c054e95f6df5babc4a4aa2bf315f07e61ad769f4cd8127632b272553476963431bb1bbf6c0d8e124fa5348b08034da31e0a365cc820c7249f9115334848b01cdd7dbb016697bfde88db7f33efcfcf77138305dff66af196755586278b0e601bd7a3b28917dcdc2dae7c85fe3d3ca28863fefd20f05103afa5131efa72ae9bce61c4ddfe0e2f79077436fb2a3e3f20f93133ca842d06f777a96e270cf0228b15fb7f10bef345296cee9851c3c139bd1e23b55eea61e9b54df62cb6cbd870072383c353f2df9a2b6ca01d84d201259f69c8f8c82dbb8cfa36716f3a7f68236a0def3d72db11d730d1441929b5d17184aeb534bc306e2c6bbee3b952b5efe7b575425fd571de252720df38667d57cf0017b4dcc715eb5b4bfbf3436685a80c1ea3154903bad8f115ed293b6a13a41d11ad25713041977238dd2c2cb48f4a0aae04f452bfdd975abb84952de7757b1911daa6a889949b60aa9bdfc4ebb47c939bf258fa3b24304936ba0f32af3ab248dc876f523e3f98040443788a290c7947a83946139dcedfa8385428cba336b675207cfd6bfde67bea19a7d3ae48496bfff576306fcbab0678285d4d36469d027d670d6f359128d5034ba3c616e520c9664302d01c0b41a33faaaf6185503f0a6d0518586b805c7eadea9bf3dbc1203db9edf28e41e4ca338f2b5139f22700f27987ea16aee8e823e2fd9d13d7f058088870f6a76688a621db340132b08adf94648ccb681044b98064a3a66d4fc7aef18f853e8a629ce60ed1543e2d4f376e2d384e7a8fc70c639f98cbc8b5a4a1ecfc79d51b633a881966385ef713e95502187194d3f46b2de31c15d8898dc3f83cc9538928af21dba6fd0b9", "7050d98b6aa96dd6b11c739d1e68cb024a77beaa946a6039fa33b235ae2e94fe1d7aa601fc64607b852840cebab20152f0f2284390b33fac2238ec57f6cf18a66fe4f165e17f88b39f856d89d91aac95d1cd6ba4d0699e324fd595119883be78fd170f641a21447403d0acd28956e4e324fc3af6be7bc8d7d726c75f1c89d985c38ac2a74d456e8c96445ac89fa8ec1c506a5f8cc6dfca86d2552841af8a40704ccd9421af2ec2b32a8cf9e4422be5f7b3481f2d0ac7d45db650fbf01078946818ad3d1da9bdb62284052dc2bafaaa053426b9606be4e5a53de1d782c9561f57f3f01c4d50f9e7facd67346218b372d6f333120ab7db7329ba84212c02b29aeb51d5146c524ea33816912142d0d39b0929b224e9a1a1a9124fe6cee473aeeedcc2722cde8280eca0491348f3dfb27fd73e0b9059bc7aa98bdc1ce1a8ab7ed3cb4cf3ac80f1590b912fca97d9168c4623b5ca27f6cb3c47addc2c7a6d514fd34651ab1f7cb7f5ccce57df9bab9fb22fdd2c90adc61f69c16c0d0ae78b0459035c82a8a6614e1d54facb02d85ad485637fff3af3bf69e5bdaba9d360f2ea60a9ec6103958035a75ef9af640def867883b2da9a77cbb20ed0b4fce2276f475a6c9eaac1c3ed3313bedaf4c20e895a702020559f89d5dae629f07febb2a0da16de85a28f88dc115c4c13296c267fd2073d20f5c7cd639dcfe49c7eedf49e75b9d84c639d9f09bdb2f9414d42cb3ec9c9b2adeb4a71d056c36ef6f697c2b4a3e53a8d05202905bb59bc53f7a06c233b11bd66c0e7cf08cd1e6218a54b0955b9dba91b067ce37561c1e9da0c3024fc1f30ad261aa3afefcb18b5a616a3cc86ed8b70f9babcfca6822ee38bd770fe8d3ba636d89037a6e9927ed29b3daa57b84f7b450a331c849aca6c96d46885ed315aa61fa79c49fc8ed90afe822772cf2e62a0c7831e5c304f7c61badd1627337da5c744c6b276110ded5f0d58fa4d4bcda9af32a31187ddff2f69c060156f3bd796b16290eb31fe3a5235d15b5798284e89ddfc97a13a34f103be8b6c9f2fb74d57b6df8515875579252bfa2c04021cb28eb0efa4744b96ff9093aa56446b1b0d4c38764a52e39bbc9e557e2166dff66a36854e92638ff4e7d76bdb8f6f322dcecc75bb69acbb3e5ef336adfe02c444127313addd5cbb870d325d305918009beb17946244320abe799e2ef87039cbc9cd689bd4f6f27bdb5d5d732d0c12b8fcb898b58950a99b92fb1a76787a7f24e46288aa010b1575aaf6078924db78b16c07a260aae3b39e96a747df6d89a5328b820aaf4c9c864ca3d987381d6e91d54a5d9426a9b55dd36cc509b1a096f3a9e824c1d2a59070156544c3f9406c6be37b49f83b32f82520be220d08e6acbea4c383571a04b25e659e2c1438d5f5bbb5c8ddceb1d93d45f7b23fdc16465ef9105c736622e63365d74a0b30280ea5979c74e2dbfdf4fbfbba4d2048f8535d5e42fa450b440d1e35efdf0ccdf384463dd40eedbd2ff41c513bba99a6d5bc9393d09821eaff18381457240b0831809890dae3fdaa2660f7b66b3098a6882bb59ce8d14b50c02f51d17ec5a82a2ac6069973a188d11ab5e36396cec5913ea5c8171e269904bdc234ce9a419d6719e922f83655b83ee3b4a74ad499525439a22fa0fdaeb52d4c183671fdba9a191882ff5e443e22c8e975f7a00554154ee06691917eae6158515d6ca5cc68e60cd17754f180020bd40cdf03ec6cbc70f859a4a9e1556a9c37b6b41f503672a40cf5b6f6a47fe1b3b074809ad6cb0014493dc9034db5a91a83aee7cf82d937846ab50cb18394f7e9250df16e5ba7e2ec65044eede09133370758c953b3ddda49d85c749adc1d7b33468578709b75c032930ac89476ee3bcb8bb91fb4e628859c32649348a44bc6451deefbab0419a032ec3487211fde5bb44d467c16ad2c0703509d62a910c8197fc43cde80fb61b56eb36ec80b5408ffa2478be08c0777f6378d9f954500e07bcf8dfae344366eec0f73828486d2ea317d635fdaaab8f63ab88d832a4ce34f4f1039fc805e6408350418b784c6fac65c5ba63ed7b11e9347ab24a40aebd5aa9c0b33acaba689a101a19011619f3869b1a7", "4be6ae250d95730c532660e74513c578d784a98c6aee6a77c7a5b352ea4603c761f6f1d7704c04c9ddfe57dcec7e19124fda4102081fe4ec94c7727c50efb4dd2cff8c0838907bc2d037d52168a5dd3573e9e2783eb84d09383d93d51a86961a090dc822b88ef9957432ad92311a44ae7ec707c7cad3ebad43a40f2a1640665b32fd46f588d43f67a215694a4b67f0648867f3ca011d249676cf65831cd979b7b50f6ec2d40ca3be2610c0be1ba5b966141108d720a5a96cf502bb085661a2b6ecdc0b999efe3690bd9d6ebe9fd229a43590a3e3f3ba88ee3c43cb84fd61d677a656800ae3080e7451dea65d35eecec66b70fbe3b81364c6cc84a270c9635628d29cddcf8230ef8e5bacef8a3bb8ab113d2dad13d841fa8efbbb7a8e051c8387157e8aa1634904f2dc2f56acd87e38b0704835e2613f40d97b3b4e9413842dc8181c9068ca7dbf1afc85a8be76dae20e2ef129e4a6446561cd91017c2eefc9a265b9299c32e2a79817f25d4dada7a1d6d4c0e2c9af789182c245a3618fd4ee6d0c5f8ba8779c09b9d2786fd118f157167df94d53d319c284acfb38ac320231326d96b465d22663e3bb13f31539731c17431a338edd05f96a09bc9de6940701dac1e1eaee3c4f91d64fdca55bc16a3ab87e7875240d6d3bd515c6f6e64977481f48a3a4ee6faf5a4f1d2f58c127c1bd8c3ed957f19d35d773235e5a7f663a0cdc66d4c72936898585152088fd480b3e2cb2f5f0f76f8a190f41715f0f074852242d05e2537403e97682db50e9f88f1c611bd1e662f4626f4a2f6e13d15609d482e74075e396172f2e9c7d1a36b33ba9dfc62cdfad1328383d5f0c14ea3707af78980c8154c363abc88d9ff13b7f788383551216b9973e69a00600aa02abf0994996dfcac5311c332b3af6359d8e7848874dd90fc6b2519012f0b1b051b89d18e2d323c4937954da4e3a3cb6100e83fe67e37ca1ead20a45407b63f9b6a86d3828c3686890d911842a82c6cbfb9a9e561382c49be75c451f9e07b795fec2c409cdeb4bbcdc6eb5561a3f44caf8a1ff56992f145f86ac98587134365e16dc21ba1e8ad2697d548675bf67408294069057e5551a190cf010ba09cf580114aaafcb39fa9e6b13c7cada1f2d90ee2b2a8924e3fff639632062f3d89490920fec4bd922606fde36c7b00c26f16f59b6ef19c1c35ad0f07e789085ebe9aa1cb7cd7d1c554a19d6280edd5c1181f59b4cdad8c99acea8ade5c1b25e21cea1e58e1b03f0ffaaf867ff55f80395f1afae8ac47443d1bb38e538e6aa86fe0890ba4908292b0d58899384a2887a346bddb0a39e493f7e487891145ec8820d2b5e279c89bfabfe42bc17fd4d3b852c1cf33732a4238a668220d64b655c2ab1ee7846ef36721332e647d503101ab9cbf57b05773e4738a0e4c4d600c62a369ed150bc0e195dfe3682a5583295223b207662f3c930df59bbc17c79cda56a9ed8023bb492465e2d2c1996c7abbeae7c7f63e428e55543849158acf8672b59d7a6b8be86f3146a20a922418f8c9a13a1379b1ea199b7725e56d9345050ff7f738dc58adceb4ee6659f1030c231c9f5f61078f79463b9d6fe162f186ebc3ef34544c7ea5d5019f7e1b208a3e9d4544aca1b38adc49a80aaf72a675c2cc29a29cfed711ef4edb787c8439ade7604e2dce357de5edf5ee15f9838e99185348d590c330ad2389040455568e97f9a65a390887ed39b10527179a2880eafc93e11ceea30dcbe9d5d3179436933bc52d6fce51529a8b96311e5d35d4c7f20dcbe58aba2a632a42ce7bd361f4842e3fc2efd22a2bb9aadc32f28e2239962fc33fc117aed749b23e2ebbe51bde96b92736c398a3e0ba7258214de6b29b5d71651e9cee9836dac48739af0316357315fb441c9a613d99aa8b7a4071bd6edeaa4d8adbb56afc036b2a4e5eb237e22103701ee5a29133bcd86d45da55ebdff839a824ed820ef1826f4f2097ef8e13a07e433e1e6bd7453e4b2256a24cdd56171bdc258b5ef5f2626f1c7b8f8263eda5fc06cd41d8cebbfa3bd642e9f6492fd5829dd7918491ed2715e56d44536d311d0eab36c8059e10c7b7410f20e0f9d7ebdf63bf7163ba366651a026bd88bb422c64fdd59b0b7b026e6a9325965de11de15a7da09b64bbd4a48a53540cb48e469acac472127b19ce3545c7c7916978ac47d61ab7dfacf08e0a67f8d384c0980355698899b79b2b97609da84f31c46c0d764a90b34a6a128456d22d7f151659fac06ff69780384b523903de481ac811d4757ba14eadb0f3520d8099a6795bebf3c826a41c04ebe58461f6b96dcaab1d50f037f8af30325280655bff88c281d0d32f7a369fcb997277ed4872a6cda8fc1ddc24eb9e95088630acda71915a718b833ab74242c8c62ddeef42f979d666e0ff8679599671c429bea77007adaaf685406efa951ddba932cf240ef6f596a3fefc5f2c0b5093383be1060a730adabf9a4f81d8e0ddc7f11e898676e1c060b5a423c367422372d3afafd6554107d4158e9e04bb03bb317eaf6a90f0c92bde0dac6dd97bf6e3e754837fcbfe75b68507cba873cd48950d429b2a89cd247115328179ef2aa4cb56f2e0a28caebc36b44059110f79c17d386b733e73fdb59b45450c82e33b5d8f4b8df82d8835975f55a895dc9dc12f3a6fc56948b2647e0e7f6d58f7f0770ce7511f86be84ae762802f4c76d158dfe3d624c2c7c027a1368577ec1a3cc6b564e22c32079711a778ee5d9dd5425af63943ad5503e3fdd46b1d0dee259c8a6ef3c55464fbcc1ed37de9bdae57ff045d2b562bf5a78473a6b2218df679d0c65f38ad0d10deb1c86a1d8fba5265d0f03b0fa4ec995fb709fce9fb802a979958e194ea6a08087ed61479d140349bc64f9708b2f8ec967a066226ea2c455da52c0d18dce74832dcc5b1ad030afa89328933ade9b4faf77effacd9a88e7a746558acd2dcc129536af69be820277f3fe2720c5cb9e3a1e7492951582aaa931a4347850a5158c669e56f9be83496d319887f37752995733e0e5baa5d77132c656cce6d426898f6ec0bf5052519d4d1ebe640cafff9bf1cf5c2b909f32a5c2b715927b71ef013e9d803fb7197ad2419b5df1700f4216bcb94a90d79c97428f1a579aea9be7cc639db67163b3c99e3bdc2ddd36849a3368d3e420011c51b1524cb59aea83327d2e1cbb121833de40b25695a87c3ada7cb26fb390537c8a06162abbc345c1e209909feea57d06282e963d6c28e9922d6a6def69b7dcd7abeceadd360a66bca6e054801dec6f07980f306b479659dd7135243df26e3f02a9f262f9e1569d2f1db6e6daa95f366ca1951a08adcca91953ea3c377e3f60e9d34c2d3f19ce3c7c7638a9f1afdc42d2efdc99f6597e77485bad0a150a870836c4b57573b62b1ce403b1236f23f86b9429bbe10680064098e6883e4810d9ea50549cdb5c0c0a0e8899936691eec2e71839080e56f4098f6e81aa0b6cc0008012823b4058f4556f4c3e3565ab9aba8841ff4b8bf522b76413e1b4d7afb39fbad0f1c493b097fba7af299c8b6955ea6c72a1e1d8331387368c46e8ecf49741a2654fc53e5f2cca7bcb3dabd2afb86c8bf5cff60b446e984384520697017137613df010d3daa9baaa645e9e84c400159e88f73f000cd77d35fe1ed7cec73d26cd6da04478d761001d7327c40f29532a539d9e44946512ef01ae7ed25b3aff92d4345e3dd440f93ce68fed245ab39ed823010ace56b2e611124f9c161600c9a4d39350fe05ee022d27a894e0ec4b0208cb7cafad5e3ab07da5fc54603cbbae7e76c3d49ab66e9d2152cbdba97a0b8778fe1d47e6b18a12f66116ac8f74e7a02c931971ddbbe3a090ea4cca3f015b927949532e7b8c00d3e924ba888c58cc6c1c88575a725e379962dc4055ba8c1dbd3eb6ffa8dc00b1e0231c3653228faf7177f158d50abc5cbcee667e9111482e64b37ab347ea94cb1ec8cdba73cda08f34d9d0c750698dbd2f32c14d9da2e519aadceaf686acb4c5477d3e7ed5549b1ba9cd59c0f71ce330aa3009c42e8c39ba02ecbec1d66e4f804519af0d660d642fc3ee3fda609d2f90d4bbeaa06670ac2cdeff6b4aaea14f415f3822a2caac6c9da4298f929345520726c80a888c9e7bcf7677d79c093a13dddb5f084968fbd9fc7ac2f39f77ddd3cfe8bd4947aaafcc0ba014a666e9560f0ed07f40a69ac262da5d1b0b1cc996e41dd768ed628b8022211af", .None}, + {.Lcm, "c35897797e047920ea7779f2141b3b4efe6a6c84ed4616bf19e822afe94ee4f248eb38f8031c9703455ef14025989ffecc819c5b2a0e6218a76330fc9cd6c35eac65189cc990c12b7b8b1d23757274f7a06de187091f3106df53e704d112dd5f86e4bc08d98b4fb27b2f73379b5d2c903b862ff9f19fe3898378948c3c4ae12c71b7ec096d4767cff8d6e3a7605e1cea0d57ba95ed749c167e270cc108f64fe45a065ec675723e9e9a242674eaffd48393c5ed2f57ca796bc4a75b2b97d45c1295d64fa10aba9d11e2376a943da5d66028d7fca4e4050c64c10bac47169ac8d13bcd60b5707fab454fab5d1ee859512aebb5e87d4552e020845b917972b0f98f4d3b4030141dc6f8669ecbfd1691bae60679ed5307ba350b8999554cd66aadb94f86118bcce6ca7e15933b6f8414792284cbb326ec3eedb16a4526073e685a51caac86f7fad0a4290a66b93b00b616b2a38761b2639c37147c9ff347db561312ee5f61783f9cdc6dcee60beeb3a4339dde27fe5da5319e99ebf548f7f971faf2081cf2560e09be698d91a524e63290725851cc03c881663a6c0a71cce9b592943c4f32d7d9ea7196b9665819ca8fee4ac48982a44673472d275a32c626a2c3aeaf4b4fc3e919a66eff80f838b2919894068cb47158c4f81a067208e6310ce06269bae1526f175651de89063513f3b770edb2dbeff436500f6a804094a159f6c5f34b9910bb43f372817d6e0887fc245c35c57ac12de4f6bdd4af959f9bb7848d74de246c4e3e26987a578aec4df8d61db80318b0d8b0a20c184f54db947f5df189a39771f642c71cd8ed354953766507911a9404afcaf07603930e585b03353e8652658124859ac05ae083170f1fee5cb757b97784f44253e60965607bcc11a02a34de9de19860a7fe1276aea7e5a9a08f8af8152fbcfc3e87724482224fb1401da440bd052931651248947d8506be13a22457ed1d94e2474d782c22f960b4cf505a7e2ec3bf85f9a13b8373353b83ca3bb90567b3a2e925ced07811cf2902e51ff312bc21809b52717e6f460838d8fae385ebbdb899963b3d0912580b4b9df6e7e2172a09b773e331b2e698ee89856df8469173338359adec3c3ccad9f7889de0b11ee5acda1d34436981c69d6be189d40a1cb6302d9be6ad7df225edfc7e92f80b9df53b27f2f66119eccc7a60812d8198fda16e36bc9575ff0b6df0966ab68ee36388b65edd1871d8bc4c451f46058554e403a1c2854a33a80e814e17c62a530141ebc28aca81acb81fa5fd76a7e43dbe32bc1a29524b1304397d56778b5c93847afa8246cd5e4df0a10babe348e0093f1b0d8dffec55d9757695853704aa31394f0aac6ea66f38f73c847ab63c26a0a62d3305fee0fe2ce64126346286a8815cce88044bf8c0431b716014db9fa820ac3b64a7ee1eff6886d56a9fbee9fc5c1a939dd117bbe4a5f4d5c609cfe52fafe22b57a509d80abc8b311f3c6ecfa7ea07df0c2e2d8844670e69bc0b6dff26a64b6161e42d72de9772884d96a217cd70897b8d1eb1b7e323aef45fa452b7d231e03bee75e4508b49d4091f5169284bb02579e9dd9695c46f6afd0c49794ce80fee211524038e383aea892253691d8d023c11f78b0cba52735867fc32fd3f1d029c264fdabba9f27c6d5a8e6fac9843e8dd503b3177542df6b8927a7d215477d3e7fb122418dc5322b7c7dc22d124cc42566ab8589688db9f5943bce106684285007ee4a07dcdd1393e1ef504338533a95ca1dcd985dd732840262c296368338766bdac90b8c9eb28c03335e3ff81d9a7294344a10904560098fd5eb4e6c8ba764ea194319e34ab58c28dd20a2588361cc28d54a6d8edd56d5bfd6574a5518117f5edb936bdb12499322bfa1b58b9bbe1c95763ec6b50a12d57fc02be5bae0b60e44e2ef87cfb9e1e14cb2f15a6e54e8b37eef544534f1ecd88f1e29265ba6013c83c28545aa95e3629bbd0ae2b7983cb6ea82402eb59b7db5580e92d5e104c553170db62ef8a23e33fb0a9579004593839ebf691002738dc842d6ee7b4d71aaf2d16551adb195a1bfaafdf4b01e3a48f74629c2b375698f2b710091d2e1ad26ec63acae4ead92dffb3c590", "-1d95657764e53e137fa13a5a8bdbd055446cb2895f41a8760b3680a9294aa0c822e1df0df2792817abe77d30185e8d5dfe9826af70b0ed329936e4737bad66c3419dad67feb85496d5818d870fde4112d67826375de584938909b04fcd336aab8216c81d4fe125094f37c282b170dc4dc3bd44673ac9dfa081a4aaaaf144c1d473ac276e382fb845dc1d05c3005dea5c1b73b682b24c1821fbb29126eb276587b076adf322611286dc07b3446649a8bbb28aa3423ecd6459e57c3c7292a035dbabb1f126d5d5debe1ef7f22ab0eda8958a6e0a4530c12e023868e7ac8ba8da3d85b3f755e91061c6b526b21cc3e49a70a30545631983b2ecb576934808ae07842b507a9471909a9a55cda2bcca920cfd54e9cd32b0f776caf4f5df29807d0616fa64ede292f2e47d65d3ef7c4d4a9c5c869f49ee56da8a68570b7c9df7c77c9824ed7ccf570277e5c07daa433ed80c96ce712ebf37e023248263709496ef96a111201eebd98a92dd99b7f15a107362e0460fc303feaf1db5971dc0167cbf9673710d46f9464743ab3eb59a63f7cc0444b61ca4ad595bb13f39ddb2550fe62f4ecb4bef3189a9968c22c084cb87a4a02d75b2766276579ed70cbdcf8c079f8f019cc80f11f662031c023f1bcad8b97e69e72c96afe7f50a343f32e68e395bf6c18bf27c8f06504de9262a2c0fc606de00e917377c2e3b4fbccf1eeabf1bc94dcf0c4a0f41ab6481a4dfe5420debf86b29e2ecf42798cb09ee47fe2f9fafef9925eb96a3ad65b6c8ce5a77d9d5df0cd97b139b8e588cbba01523e8613fedbdce462da8500e648a86730d75ce2d96e1600f94245913f9d916f1936b4d795f965fca14391c913f9d85b38bad8f709741557332f3cb28c555b0b478e299700157939b9ece14d48ef4c3140793b432a124d6c01e00ef3f78155b73fa373396fd12ff6a8e746cccf722a733a572515fad78e59045413f45dee582f1a2c2bd99c56b3be2bf518b1efefe575f344d15fab57c505dba101286196238d66823ef3802cc58b5c45bcecc037d422bf88f1bf9f52a8a8e0420978d30df12ad73b15f85a1b56bc4db48fa1a32bd965a9c02751bd29646831e2ef4c8ae84addb9cda809583ce3c08bd8f51be1469f16c7691154be489a5708519ed59681b8e1c8aa379950b915280491cdb3147b1c2d39540d1b004330930bfbe27d7ce729697b6b4af05db6ea684e551ebfd7989c3901955d533f533f408c1a4475a318df8f68771f55eadcaaf7b754b525be5db32a9a571dc96ff60aad23a70ccf5771369e19e6d0d5ef7e605163bb9c09ef2e3f1101d8ee38c43484259ce6064c0effb48717532e13d33fcb5ab869d6bccf4c48fa9709c65315b90f611b6323c1380f2cda6547eeeaa3084f8c31d9671629031df6c2384cc4efd1be4ec6cfe0162c21d3d0200aac6792dccb5525e4c0cd8b6e6b2b99490b98d44a4909711eb7076575cd6ee28f1a681013fe64e9001d463871414648c444b239d75c8347326e4e23674fbf708d56fd63e8426d86e4acfc9b25822ee74989b1ac152f361fcdecae27acd1905685984f6d55cc3db15b9c0a2c68566815d8759e78b3271b5ed2a07581f9e197655c8e2ada4b3555aadcf44b4cd4ea19c82e78ce55df78a8365728cb72a74f3d467ab75474c5abc1883a631cded84dfc5e94aef3dc3bbecbe6fa259423e49758646b6f318bd5458adfa2e14d8252e93ce0b8e800f708809a7d25006b3d47d37286faead71bd24a8dd5451941e97ebf6f46cf56f764381820bf8413d8d1b56230e68e8ed5c2ebd58cd283cc4b023aeee78ee2e6d732f52a1b76c6001263c8fa4b13f212781ac8dec29ffa5fba6fcce1c4324bcbb6027b96c1e855635991fadd55c0e4b8639ae2ae6a73abcee327f0a29390f088797c274cf04e057cebd7af53b70b934d15cc713f1289f1d82f5a0d5ad042e126be0487ae0db9ff4b1c9ecef96bca6625b05b10231be6f7b8f6e036be4c2c71b7d8eafc61c2dff3fd3260ac653fd7d57849f8c0daab1b16ed82b3cd6185b564e37eff40793326711395e9b44b6d446047d35e18e8851ed960a2c803a05ac566610af13b853016078a7d644926b51d6b13781", "16930925fbebbb4ddd246966dfa26ff0f5bfa8315253c4dc0e57e4fe5753e569395db75c90aabbe0e4946a0925a173a96d9cb691a0cfee3bae0ef016d23eb0e898a531a6fdccf5c5e8a6d0da48df918d80cb585983e68eec98f7009fbf127fe3452f188af4ccbe11ad2515a087a29bd33a71cf9a1935fbd8c4fc7e30eb263cc3d004652e706116587f5c0615a5bfc5f697c0303635f86aa90f84dadeac1e78ae752d37b2c3cf2471b431149d4979a51d7d7681c72a64c3cb66c052c567b3bf8e1087e1b26cb765ca0a2adb728392f36f258d4f2ff0fa2139df186c91f85a7b3c328e6f5af021f22d797060677f9a29a25bcf7e11068af8de79189fc7e8f8e6819d8d4ad8531e796658477d84760fef35393752060aa9e2454a271697d34cad5552119f662b2cf9e53e0b1ee0642d340f069d5989b8ec5df522180b3a6304fc37fa8c5bd9694f0152d9c9209db2dc8a662e19dcead856f360f1f4c45af7c40c86e9b6d6f200c1e4cdc90455fb49b181161e483679b8cc50403430aa3f8aa03e5d479757c82d0142d605ce4bd1122669386770474767b90c5949977de4df4a6eeb5fd4a1aee0cc113e9d14be66dca83892285cb1f52af5df172b9b350f28a771ffa6794d86b63b87b2a7f3e74a6671e3a2babb28b400a13ecca35593f87b852613700eb7fe68b2a80121055b163f557374dc094947614d4bf3dd2f6be07870fbe5e40a51d356d5f2bb057a9f6b224cfa3d949712a2c634c134327c16cebb305777e8f342bb94ee13c3e71db6515eb66cca0322ca84f10f4b6adcf6d00cb14765e79b2148bc9b221c3aa5d0be250ed0ea85c31c6c04075a666be9594578037aa03a8939262ee6b507fba505e5b42db14a7ba2a0bfda70339eb949a70f4768e092b9355639cd8bc4d745525f182978e22782159d8cc004fc26890480ce73c42c69e9d99e3bfb070a788f3dc0ab5cd98f115f84ffd6cc06484eabf9782def52a972cc36090f4635ed065e1bbb78c45f91ec507c62092fc7148a0d8b9bbf473f290c2dbc1df74424dc66ad715a5a5ae7638bf7891a040303cdd3577ccc7191fdcad430a3a2a3299cbd04fdecd52e6bca3b4c429fc732866d5e7f2657624fd150bf9b2214c116eb427a478522aac585a9701a4b7541488a8690e118152a12303502f314396107d58acc9a057f091f41b9a0ba2d5917ec4b9dfa50467496e130ea136cae0cb22c876b68f3686d43b8c5d562cca4d6c163f4fb7562bc461c86aae921176a958f59fa75b0ca13c5eeeb17470af2affedda6fbca2a25328c4c4731f11efd766de9c76318f715da0abbc7e18c808f67eda02d9ac41f5ef3400fe182d07cb298f087307d7226579ad61f409ac520706caafd60f4477d0ca75abc39f7a200c564f642c29ffffeeccf541c507eb84046f6809d310b6f8a0799d8bae9afbc5326a9b40b504a11a457d18e1fe4cbf453298fb967e2b5537fa452249d0b89dc542e6fff0b74a6581dd1acd6093961cec43dfd51a66b650d766420ca9a8dd62f717a27dbabd7604476317e7d526ad8ee346ab58ed5911f8295061cbc600bbb1af7eeee1b587caae740e7541eaeee720f401821cb86de3fb5ad98cf17690b4337e4439b5ed583cf00dabfd58da1f5be42151dd30ad407120fb3a5b7e7163664032232b63866956aaabdec0c20754721553eb572cb3c86da80cb7482db78c9286b5e37f8acf451c0e40aebb7479eaac46f6a3a207c243da98785642130b418b0531513de6b1e5c0e8a7e0044e95162a5f8bab68ec33762b10f5da5e292a56136f05ea6c4e82a85e2aaa3871615cf8258693c4fe3718fd0b24f7b53410af5edd8884deaaf48fdb48d391d470c70b0877eaabe34c50793ce62e2c87e827b9c8508ee2a7bc588a28037d4ecda042edcbb18495a9933e9e5f1a13328d6f9a1367c74c79244e952a665af68fd93a56df775a7ddfafb5f9c3b037a64e60604f26dcb19f8b3bda3ce56afdaedeac7427580eb3666773d5662b3f05c6ebd72d26b7427449cd2799df4de66fb3e5aaa83ca08c9f301527f976009f221571a3204d3b0d327c4c89bcf82a7f03ed2112a9ed570cc83225e1714533ee25e5ae7a93783a1e679608fdc2ebc0d5f53721e078698d66766a0515a7ec283d6e31419c5a044422ed33b56e672621a3ac41a1ae44b7c5961ba6e030def17eeaf765f252ee3acfe06c25994cd0e91c708f629128f5dc669a9f5bfb9e14545888e438c6735e8e64ba66b6ab32dd1ec2ec08bc493df804ad84bfcd7726f292b087b982825548327f19039e6174b921151c91937d0f29be92ab4b5168dc6bb12c482fec23c12bff5c7d269bcace2deb685dd7072b6646361f88321b4dfb869bb8944d95cded0cf79d4b675d676fd0e2e508451e184d0c9f771532f2b44deef12ca221127ce2f89603100b0837e5ac84ae2eab0a8320e36de02ef50561029409ee936d4467d86e46adf9124042722bcf06917e53ed7d8a797ee864f7ba861f6b596b396843858a9de865c08cd1b2f03af7b50c8f5b447e5da835b7a38369c5cd4e3f49a6556c959f77d9fc98cfa26b70713cec8cd50a51974e7767cc8f5faf83796a1fb19b308094ced765489dc66622ae0e29cf8a9aa9cb1e4a04c4f85ba1e4f71bcc529024caf54409ef8430a2f66514870eca5ad843cf710c6f1e29c2d1fc2507606c60d045d483f16ed753c77b64e8c58d7a2ef6e05fa1bcf784ccd9e43c37db33545be10c7c926e47c89f37abd6007a377a07b88db3d6177c974bbc479219a9374994446f701b3ef7f13d0879ec675013e6839a64279367c91a78f65d3da75953760433ab97cbf493e3decf48f23a01bfc06b9a1362e4e8f21026af534192b433152a21aed06474187f318ddfb50a1f5afc5e511331bd787ab3ec1ca49c25c008ea8dd653e17149a5c4574aa6d77fe22c20960e8a02adc397a2baa045deefc95839caf6091d029d365139e3ab69a38ac68b6979f0212c18280a0957af697f50390baac4ae841489376b180331f221bc85105cedfb49cc6de42c3914c057322514926c180d237c04f7657dfd48d1d3a3695b119c1e4b22e0756ef60e68e06e7950078f9c2c9411c3f38c77c0eed47fc86e3a598b790ba0acf996a5fa3736b9042c83daa04e052706230897db29da069677e0ea788143c009db9baebc5defeb3d3683f0f591bb245968d5abfac265fc7be4b541f06912ae3902431ac039c17f1fcd741c61268af2970d7129f771f15c395e9c53cd98330895bef1f7d9f148e2094f7035cb455769b05331c719acbc8fbba5512df890af794f2e8005ecfe7828d8fe06eb4c121779b0d18b0679e5f6e0cc81dfb945414cb2af72c77e85084da0aaa15df8de871ffee4bef2287bb61b6f39480e9e8ead9e6c22e9d860901c31caeea3aff1e5065c36ef42afc1604d170ef099ba4e94507c3597825a7fbf1b57f1d8f602424f8387e2a8eab227001f2081484aa7fa5a8c5923f0c2be11d415899226c9951c1b6b460af0ca2573048e5c447e679042443355f5446e28d751c18583a029be705d41c33b93f336a9a56591ec6f31b0199b0c50a99b9d4dd7db2e73692f28206ea6db82e864d5c665aa3eb2f792a543cbfb61558eba24ffd3a54045746ec4370fca45ec2c058714f6936d675bb651c966fa850327d1167bccd3a96a84794603dfa4b77e612969b8a6b3734bba4a966780cac8790914a10127cbbbc282b3748b53b14571a6f8139c9cb569e05de45ad03c179abae3bd27d5df7e228a22b7390f487d4058e028dd3e269f419d002c6b636db8a39bf58b1798574528fc1f2ebfc27d73f010a21ad0f86fc57763ced388bcce3ee4a0f0f65766a721b5039928edb3f9419baeb788d5e0fd697ba4309ee51c5468bb13360efdab04aaab7ce99ebcab6dd971d502985bd186a5ce15d82b8e0b06bbb576d2a4411d0609cad0a2a8ca1d7da7bfec174291cc496f29f616610d13a1cc267d8e446e2a298040bf963f7ebd019052a02b3216f46f1e8f93d27cfd5643a5e69cf103e5c5e75fc9edd8e8904bedf8223d762fd50ca78d8d7f8ec32d61d19112dd1be0598d363a4638bebdcf5dc74afd3d507f2dd93046f2a9f08b55e062c9fdbe965d8366035204faae15a84679bdd4bf6b46945b2cc05eb2ecab65c5047986ac06a27129315805b729e2de68e5aa160c77bb81b619bedbb773134ee449dd892f99aa7b7f70e6c276323171f71987d90", .None}, + {.Lcm, "3ffb5a94d5fb2585cc7b8e5cd00fda7327e7ce33e25d92c69bf6175613be15084ebe399561c60a9aa0e30dbe96150e7e7df0c6cf43585a34f65c4df44db823dc1de217ef2bd16f19c447a5e27ca2692b1adf3b32ac7fee33f13eb3c55b147e12e6c941a182c0e57fce02954bcb4e48c07d81b0664d954c3f897b354036ebb37b2b0062b4fa8bf96d55c7406f8121efcc5738205ab1e12d189d9033cedd0eb6840cd23f448586e518fde693f8607be4b817e94cacaad6e00a7f2ad6eaf7762dec382366322dd43c12f0bce647d5cfa1cfc2c14eed2b8347876316520f10a9c9ce15a978c997d0d4f3700929b6732c4a02300a915ba87fea56afd669667fc9a815e87fd5f5c38a5edcf0fc3ec7a13c5f4843258646b563a3ae79b2b1beb98bc54789c9b13d397123496e7fbd8ac231481999116a67ac45b063d4796c537659ebe78a67f82fe65445a2098d5e2697c56a0bf257d9165191ded1ff392c00a762375e226627fa113d9808a625bd5bf34816b8384eba9deb6ecfedc5df2479ac9c4eb850a5a0635c2ccd1e2e412679bf3e5df82c718ef9c6a5ad48bb63bf8e2a5e3c1ce49bb2de24783962e8962f4d517b04709aed44c42d5f23374d6cedab7486de8b2c3508890807bfb1052d3134e0e4e18f48a6fef6d3084ba229fa4b01c34766b809796d707ab0ebe7441d3038c920898f827188813f4fb532d7c35dd96521e7768be3550ae9307a59d81e53b490fc4e4e88e5e7587d33d353b3f9b0e752aa8b0c28defc9d86b8213acf1bdf6c7be1a1b868ac40d2cf6d01d25b6de3e221e6ffe8a53044ab109c4273d7600df45c972241d43873d7c9713b7a3054d7ffb9e28b681d6d698c0d22b9cd1ab016f224bc3fb1ce8f421b1de880c6172c109d6e8fc537e6a3552a75cc06fbebab8ccda1224a6d07d6014c7f8839bd6f611895e909d8816d090e2b7f9d8cefaf4d0b95e3a691111197e93f8b52a79247bb9296e9039f5aa78ad05cb55607d1c43ac71fb174dae29ce4e95800b0d419893543eb1f08afba74ef0c883794acbb0fc3106730c11bec408549e3902aae9233d61e91807077eaa65f35dbd55e1672a22a3d4a680611da0dcd07d408e01e6c3f955106aab7e74f41ee11096406297126af543d4af8555e355eb542de3f43350f023474ab6b9446621ef9438c7547b016ba44c09194f07ff44c26e1a634f80b88f540c292355dedc0dbc517b0a365593416234b0705609db02beab5200daaae3668c51594c5efe614c01ec6ee6010eb63f12afd02ce76b9f5cd2336ec0064b0c72794d375f7e2872740466ea4370976e0b2c00dcda5255c287ef211ae880d3fd741d92858b5bde073c689271ae3f8e2df9c0095b15a503a2683da3e7f5f0a99a5ae03d70b651db5a02ceebb33bc8e85851170a08b66119af28aa72b9035c85c3a40b875c215d48c1c3634f4ccbbf2727ce6e8a71544db51c58eab76ed848b2f2d72fdd1ed7021603470e5367b68972423316f7f2b5bc14c055984fd26d0de0483d0f6a6cb0fef17d35b89b67a048aa7f07e79959dae56d5084166102b4215a097e3b1b6ad52c4125be070e82e567964a545535b30cf41af38e12416575bf814714b3f904e4b8a50dd4ad20d73344c1f8bcb2aa32e005380bf906b9f9ddde0af8e339c23156468f62b057b379bf2e727e14f0a49dd6dc429495b6d76c0228e3b9099f115719a153f04cbf9fffc4637c6dcdd5249237bebf70ecffde500bc5e96ce588feebdbc3215a1e992b802bfb720c1bdb1c91e560edfe7960df8ea30616e9b1ce7af348b3b104d0780d18ed563eca19cfc3d9873a9b38336e0921a45373e5c7e60f5ca3ae313b19546362e5bcc8ddacf0499746a810438276b35a16e2285b14ffe530e7776bba898e2406ead3c54d781ece03242bd74374a0526e1b852be5def1dddd05e1599850e3fc601efb910894ceedaa30f2ca8b66f6b2ab0328e13ae0665093a4a237b69daea90847ba68f1ff564b87bed57025efb8d8fccbf294e5631a71c1b142e41d6b207492330ff5356b721fd6eb3a82a7a27c2558a43e9ac7e94e0f89213d1679d8fb91591d66763e4112a7b22581749e18b2166f2f18f2bab3ff04a", "-5c98aad052c4d55d70c1b253d8449b1aff0c0b220de925cb6114665566e540bea55f7a00a7779b74a399c24fb24b3e188f445cf3ca0768b5195c1d47957a12b20e3c9906c2c128503c7df35e8c36f97b594e21252e6755ac22f29190745391c60173cd07c26f36e228ab86b36fe1cdade17e33995bb2281c555fe7d224951c1e8a0fe741e679ecab681f690690f1190a0b77cadcd2a774078aef76d2683fc66363d0b6f4ccdd1fe118141a6723dc6b9ead5863fb773ae0d4aa1a792e8834be64ac6163d2628a2daa732ba489bf7fed52aa85cbf5239f80decb1e63a5e94c87c4cdfaab11d328582c8a000c23270d53a78d0610eb4d955e19f50f34d4c8a32307180841d6f0638cfa43518f2e5f96d0f6ace48a80ab3adcb51ab1a5dcdf8231467a5e622711de58ebb8495426bd9ad3ef1fcfd5722477cb536795dc6294b3ee06b311688dfae03695e91520dded9671579862f06abc26da39916d28a27e6cb5612c57f7893961b1befcaf5d64d238efcfc62ed685dcf30d71eed1b540eeac33cd9b1a944ce674f427f66938aea83c8766ef07bf345f6bc5b854545f7b11fdcf79737eb9783814b0a38dc5e2be8d80d04ddcb67cdc188605302514dfab5afaa841a94a36878a199fb79b27bb9e63af20c2da996e50d251deef653cee678ed844746ca4476e9151a036703e8370e4ba6c3764d5daa52029b713f7aeaa4fbd753accce3ae4b0ff6f656807e775280f0323eafbb10762a05b8d159765485fe3c5b6508b04e3873c69bd9ecd9b191461ae92387e66ab33cf15a7c930975ccbecf232c04f604c9b84cd763a31441742c156678dee4f98efadcdc11f257b76ba91c1a7023a7452eb9a347bec94e423087dcb3d790bee2a02b18accfa928852502470189dd90c1bf833e9ad70098b91567d35eebca2711631f0c8677a362282ff455f7d510874961a29142597fb7fd365af9c261774c66fe0c56850557878933cb0aa1a5f3bb83540eebe8d2d58588e14ab5629794d27c9af51fa4767d605b256eda7df3773013d5eb87a6c51e11a5649aaa06daf79832cf08939bfa6f8b9ef78feeec99fcc2ea6c61693f91582a69ef606950b13d3648eb7657f2b28abd0438653ebf12f599a9266e6068896f2685a7c124d6f6e4baef792f5311e2effc78f97c3f039f1e7d2a9aa19c18dd517ea57b06d75801fa79b34d875a1ef08df95a397c1b75468c0fffe1eecc394afd18b0a3f1f17b07c4f03acf87a705ba853c9bde070a1aa3e2c6d51533d92e9badc528f43cce88b1fb3814ffddd8463c1dd21dff3ae4f41ac177e937270b3ba52cd8f4de6c1a1d4d617ec200209a275a4d9421e132d41d26624479e7aa47f69099a2829f3d49341fae5b912ce1c5adba67444a0bed5e20fdebbb81f2fc05bc8a6575e1ab075b30b4fbee3747412bae393ea13c2a41ac776209d66203ae4e204177856d03c0d7ed1ed120ebeb9358d0d84047beaf16387636ad0fdc16d8bfb8c1ec9190522022e60a4751472283ad8c1be75fdc6b17d5ca19dca599cf3c92c93d6426b6017eb482d0e789c086111a9c8f2fef34663b319ebace1b3aa7dc760896f7faf2f3fa1e4f945b976300e311936455956e0332c17a0d98728127d46ae1da6f318b47bcd44eb48e5a34f40605ee7e88dd5ac619a0e3896d16a26ddb9fba9800c8aa3a9141cbb847b0886269347d47ae749879b983303f15c6358a70132f01df4fa7214aa4bfff69806b86036e124c71c3ae084760a4317b599f6ae9baf243db63756a5f6f5ab34d80fb37a2b3428c5fe81d61535d07d10460f250b00aa68c30bb8292efd76a3563633f940105baa72cfba0516a847b29f13885ea2b0c4c0454f997aaa85bd58c658b2eebcbc343dd33dceea521dee1aaea90872f4a35ef00d89470508007c41af3c992f07ba6335f7fd4ab54c1f74b31526742d76b58f8e8652932f6d01517200eea2de1a9c2a3091a410e64c42647c12445ce9705bc74eb10e63233a64b3734d60a52fb4b04178fc50d42c5ceb385837336fce72890fe43bbc45a98106deba068382dcf9a32f712a4ad9f840301cb2ba9f47394d5fcb880bff18d0192753b601c850603ea23de459aef2b402", "3db6a14b563931195e0420594c2515d7af5304328af6bfb59c6cd911d125ddf71709f7c8e9603bbae2a64922265997d3696364d3f66a83eaa63d2b9dc9802a387379e0b5c8b61974605cf06e069630c2b6d1d6c872f1400a9547f2c114d8c5ed9d140ca1a977bde1ece0338c8efb9d3f26352e70a9bb63c960bb687380f96c21e5aa91ff8f298b6778e6f75254495408fdb7ac4f51033332a0269b5c33fee03ca4bff61a03f289d17793b8059ecc5557d40baa976ea85eef0daa8f720938e04694f5b8a22eec504570c089be3e202126f9a472f1012ff8d2bdb2da453e453a86dcf57d9d627e11ca4b989f194584aa9f2aafd365f2073e2fbf30927de5507f0c0ef4a016c588745b5f2c7c928ad8be6dbbea7fca8ca99ce41674f845cedf207266640349e85d0444dd138a99b54775b6a9b07c5abee7db888d5c811f30f5d4d9bfd00b9fe97962d9efde8c551b171f91e53057885f06ef76393577a5cb4dd1f3d919d8b77206dcb2b44a77c5abf889fdd78bc502e0688b33003804751b01f00a070145262317dd20d0206840ad46da558823b95e8f421355514f26b4ee5eb8b2fbe9fa932ad686e19caecf2d6c3a31c10a3b7db33f714aab60b64f2eb488ea17dca18ce65a75b35ee73672535ce08c528352571a29678b354619d6821a734b9e448283a1cc0a00274b056d0026257ced79c23a1ed88ef437f4aaa0da462dd06ff996d8853bec5a28b2cb871dc51347b72fc99eb52dac5c508130ea57d04482727cea17c11f1a615f70976f3be85bbab7d152cc1bec9ce2c0cf7a91b50b6cfaa653f363ace726ca60f991bd4276ceb7bc52573eadd69dff7ac48ffa283cb593aa472a9d62f8ad1dcc9466a14ba6850707233631734166998fcf9ceb2dad435f60254acdc7b352b19c30c813cef301cd5b305bc00057c19b276532365dc2b833887cf0e6b15fcb08f3ce14beaab02b3e6405a87d6a555184e6df36faa507a4385f0cab91b7a0314199a9944de55708eb8248721ded84f31a92cb6d8b30aa5c7e8535d186afb2ac50845a313eba4a6c4a497096d09618ec4f09af71116157fc1adbb178055ab6b36c1b5ebdc84f2acf0e0db4214bbb2d1968ccc9004c7d57668d61b2afc48b741646b4d62c77e977f3fdc0a49e4f753e1f7a66bf09ecd08009b82203d7ef936b3440f99811fc27f7abee5f8c8032145e7f95cd5ee666e4ce8eb0dbb4448604d204f39d34d57dc4a0d6c5e36ce6e28c6dd0eef85b4e1ab1b42585e9eaa6fef1fb6bd07b66c77f389c723dc0d0dffa6512d03ae66daa3a531b8326f415037202696617075228ad4b31508da05abe4363849f7dd4a498e1d5de279965b687750940906efbd5fa8ba27ab343fb6b94fa12546daedb155ea38498d00619cd22fad7de78ce661a9cb4fb28fe635b6739f7ea6fa31986d27a8c6dc8e799d9fe221a537d423606c9a4bba44f73495a48541e4dbb0040ebf5235cd05c20c05a24dc858e1be50d266460313c66004ef91f121ad749ef2f37535f382dfd7b8267879a5a1557136e62f9c658eb0881023c4f8d46b5bc474b015552ef15a7f927aefc08dcc8c19e96e3af52c78016f911b425004329f2a45667bbfb6c7d1009e386888e3e32611cc196109d55b650a0950fbbf46bf5090602dd9b6beaf4e46f3ede312085b92a65a4541486d8792d0012f858c1668714ace49da1d51beab502495555bec25596e3e2105d58e497efe35e8b795cbd6e04fc8d820d121ccd5582d3011162e98ddc72a00885af545133ff11ec19be731ade0c881bf4e6add4d318042339622b5eaf652366d48a593a2fe9021912305ae38f247d125406458bb827cf5e4ee60d4179a524387716b714549a40ad1f94229238ffcbd1bc5e80dd527316c9eadb724f014a659cd4570243a347c668948ac2fd0a199c78f283afe3ae22a95da1def937ecb85a8776b45139827d51ec90424c334cbbee798c13fb6a96ab3b94534c96bb8a843f347c7a2b2681486b588a1745ab1bdc97f36eaf5e58de9a12f63ceddcae836ed7fbe2cf4834e4246c879a4598f10bfc7067b4ba1d1ee742fcaa935dab77d382b4d808858d04fb897ac89e304477e0d675c0e69fa01fbdbd1f7180bc9cb76ea89fbebbd655f4a7ba75ee36f89ff2e789fe4c07a9448f3f6a144b3aaafc28d1590c262acfb4e8a9c10f6c6bf4eb155c82952ca989d5112339a7b4a98bbb03bc3d0a618865dc9d88d30a18bcd09443679e8cc97faa65ecbcdaaac0f10080d8eaa96afc793588212e94f91995381258a4b4155020321657ac5a14dccf3747337e04a499c855cc8957431304908eb496012eca49af1b7ba240c488996f0c36a6f86a206a5a5649c0797a7556c4023b160f4deef58580a8247c59eb4575a7390d068279781aba6dd7c2ec19258baabf2e9e66bd89c0d486096927ebc71fba7a1afdd953bddb7d21920781051eee425c680cddd6a90e8bd98c9b791836c20127f082fcb0569fe04bffc08126cdc7c789b010f4bc490c8a698a360fd526465ad8f4a3ec4a25df15681c4c462085dbb1f6c434b6ffce5dc561afa7d5ec5096123d7bcbd1ad222c9b194b8679de83a81c6d842eccfcb02e310450baa00f330df054d0fd15cf5ae0ecfa7a77c371c164c7122afbca6b90b7427a6f6de873b3d89f01ffec1419376dbf78cfb521e771804acc81eb2460bebc730851e861860ab9c4bbbf4d7d29d98cd96f0943364e19b3887202823a8c156683c15592a1759dd4189612164ed695d510da13d319c91c293813f26f2fdee83ad77488a1c8b0584de7304b42cf3063665cb2c8b87f8752c4777c505ebde76a6f7ad5717c27d4341000fae5d69341c68420d79d7242fe2505d28d628efdae86a9977166061866a0187b10f5b9e2b2a92ad9ecb100d3f5809aead157a53a84d43a1398ff308670b8ecef5a6e7a57ca95a131c0db159a66be87fe39ceea2da496704d614b628ba2152923b7f3d40db960bfa7477893fd8c4ee23dce90d575c7298ff3e65c6a85a849fd7a8e2722f22e56ba66de366e21bda5981e8f889abce42dd1447e610b22280994f493f19deca051c7b85f289aac9411f15f28bd472bb96fb242ded98cc43b848d48563f78803809ce9d52022469101604c4e97f76072f700c77530dd14f3aea9c24e2da8587b6dbaafff9425f5048add5439a0f758d1d4cc66b5f3909907168487cbae487d8f20aa82784db19a1f2d5c1b1073770f62a8d375c2bfd6ad8c0ca9e30e7eb1f0887c8baf93fef248f243bd38ae1c424eed894cb55279db1ac9e8e1df8674eea53eec55841424c039921ca0382ae5bcbbbb2a66fb263c3cb8e54cef5ff538b6907abea5520e89ceca15d97977bd9ab86055cce7e8f41e1ba0014f941797e534e2d98de353bfa989c873fd24a892f813afdbfeb9740f7e34dee475b2ea9eee7d1e72ebeded9a711242c20bcaef148ed3a1b7bbfa1913bbd7841d4d3c9f9a0a103c84d32e25e4323c9b5640a06720b995f0927818a5f7e77d999b18704dd8e88f2093a5f8ee2a5340e06b8d3c35d1b6e2146f138e95bff7415ff8876941a155111fa953a3a30cf19ddc23e998093da1b36cc068d50424f1ed3c0bf5709be3dd86456fca6c235e141654561b6ce4df8877d0d0e16797be1fab633bc97576e9baf0a55ab6d615d26c6bee71a8183e31c53b0b74ddf810fe964f3b74bfdd79ff2191754427e9da298ce448f1dffbe0b1d07c3f187cb72aed34976c24f9be8944b65587441fd8e831703b0da6e35a4c067ce979ab3e8c01d31ec77b723a79e67051000aed32dc1d363fe2a6340fa85543be657acbdbaf5d6259add4dde95c83a55b96e034fdd97bc10827d6b1ce5b43ae95a5e2a78b2dbb13bb04843558b380d8dda7e70fc5e5ecbabe947ed03c901e3d903df8de9f9910a9f883fddb0bea70379434382b6d23f93117eae52beebfe90ec604939f8406f1aa310561e93d21d2829cc0962383b1dbbef688256bd7fd55ddb4776603836eb894c0bd1f60829270328898cf1ffdde4b7fad9ee79a76f1041b907f2fd76abe4f14a4c955728c0112199aac7f39c4bf7ddc3a2ec4a63033314220069dcc8bb68e5ed78d38d0a128b11809e9107aa7042edfef8946e77a0a4bd6ea6575675a93ca2b55005e9b3f5ecb4a7b65164e7ec6f3716e0845b233f907a4f9f9b7cbafbc12d6909ee5886781bbd2191f2bf451e8b700eaa3d565088e2eef5f9f91516e", .None}, + {.Lcm, "ca17fcc22163d5068d94c0f74dd9cb017c9c552a22709a8fb0cec74455492371bd9d16f458222e146c33ec7ec2a9bbae4c7fad1e0957bc3360844a160d3a63c0f0be4d30a28704c19dffb70beb9af4ea5c2bf73b8ea1f849a43ddc03cf17f862f9bf279b4fb1fdcca0c3c43d2bedc9b5732f37d1d3e459356a54adca5dbfb48a0f770515a3a8b773f7d5a775cdb2ffe2806729a91632050320b7dc8c7b75119795c94367c439820eff695a729213094d5fbc3c46259b671d34e88c948586881d2f1fae65d77d2945586f66ef0d27a18108f9c29c0578bb71a02bdd743dc1746feba2449fb164cbcbf9df068a52ba555cc6d88f07f5e0be3545c86a60e0bbe8062d654a01b8e840a22c3dd496e922550b72b5655b7aba2a55030fd2225f913f82b9907eea41c2a363ce47a3febc6a0738be127b24ce895ded42038c7fa6d9fc8a0aca69e9c5f7d2310cd69bcc24452c8604c9c97ce0124a579c7ca84a1fcc6d11b727d57b90d79909dccfa6e493d232126be324ccbf754b8705be097b41c0b2f8f9c9d91a6e6cad8e3cc90c8df3b46514c7205663e6a14059d76077fb0fd83b5347f4d7fd8bf7d0549b7ab7ca94ac217f851cf57db8aa23711646476e5f75f2f9416c4f3303e36cdd9247f9a3917ab0f83fac2f51a64b3a587cf9e50218153f78d399821611a63348ae25d061405ee7a8d79f7725c2d7bea7e7122d9b8dce1f9e862e788dbde698d1b5d3d03c8fad4e42328711f183cf3de92beb8fa3e62b5b1aacf033a7c15956f495804b5700485b7449992f15c3b47172f7819a37baa93b1f05b6d40a68ff13fc8c8c8455f388307feb2b2c9a42db1923a8b2552514e1ac5aab02ef620ee399d82caf6d39c0029e94f05ec352043e7a29f5d7bd3e1cdd767ed1398d131059240f4777cb58342dda7dc34943ed67d41f0e7a945f4e8ece2d1d802412d8d8e0819b0594b65b9b993110653d384fd3970747c2c065a2cee8c67ed26911f93ca418e91b3e0d258a691fbb15ceed9fd61a4f1df494d64227914beaac0efcb8d9d8eab7113bd93b239fb556032b6207c47292ff5f15bec09a5315764a3c15445762be93181ae2c7b0e0e69e7f566e1db165f3552e7325edc70d07b9a5a214558c3832dcb278573580c1b379e34ab55889313333455371f29fd1405f02bf526e10d4fc6d1ee88c66a0303a67f9637cd8982a449d14ca360c2a58f7d892da3d736f1b706172ee496ccdd62a8d5bf1ecba3f321885b02cd9a923af8b0cba30003b31bfb295bced2e4c800c59d4791fa0975a1fd15588bde81d1bf31982c2284dd8c013fdf9cdcc5c400f74eed766005efe0b71455c88dfe7fc0d87929904141f57cbf3197691e43a2125dd58dbd3bb3dc0a31d15db542ef5163d1f1d92c7d11d0bddbc4a9330d30059144e054c937fe2394d3bf4a3581b988bd0d60a744c12876c6b0e3b6a4abb76e261bab3fdd8d5da3e66ae0d45904a62039f555a5354e7d5b1787d37c45c562224286fc360902ad9939ff9a58ed9080f4075c18cc757ae5138cb061ed8e63fcb25adc3957701ff7d0a55a79ecdcc777ae79627c7d2bcb58eab28736e24023fc4f78ab9996a84e549982b4cad8d694aac7201c44f39b14a66683e59cde345e0385bf60996561e5355208077794c77f2bbd4e6a188a14f4b3b539803e6a7ad73949a3d76340faf3e5b6e51c36fe0ec08f6adcaded99e1774dc1b4b86c297d60eaec9dd471cb1e692b7dc8fd05fde68c331a99ec4e5feace445495e6514db4bd7417995de7bc2e077d0e130d18635b3fff10c3d3a3bc192988a0882cddcb07d592a565697d0b7bb4837de601727bbaea22006cc196f81e8701af1821b2335de3cd2499643c924870fb7769233bd6b8657eaa40fb639f922b5fa60061e6b91116b164e465a391342d7eadd6dbe39df3789c8866df9a28fc1148c1218edda710eeec22679ee3220e5fac1c64526a23ed445a5f06c1700139477cb4f109c0d91770e75704750900bfa247663cd424b12c53456fd6b048474047730b6b1310606c9cc0e6304bbcbbc76c9796a0f0216df7a51cbdfcaf21265133ae1a778f6e4000628cafb33fcc24dbac705e5e80461f2e1ce6ea9", "45c4ebb9334df2af8be4141c1159b9e1ecf978498744f4457b08d16c5109804edce0428b32fe84bfb64cc6e48bac90f885e53dd3864e5b3cb5e6a0dcf9f224e27d635e025669adef04a01587127a8a62f72ca1f54c87a330dde0361ee664021925a25a11c2ef2727470b187d29464e9566848ee974130cc4413642e835f584af9a74cd7b3bcbe606f7b3e972eb1ed8503fd4f8e32739bcb02ca2639a2d94a1ed40ed9e641f9373c88c3643048973722a1cfe4b62555f528d1bb573b78e026baac875b40a153595eb44e60316b1f07c572fa66d204a89fbdb74452ee9b1790ec0e6c5556e954784cd451bc15eb30e48432b439667edf0c4fa0fd8f480da32b3c3a610721efc3d41bbd78018b22b6ec9d46a2327e816e985beccf3a2d5c34d2d09b7fb5aed204aab275f81cb1d66cc837b2a1f33f3f0fa11e26fc89d9aac021c0d20173aa170f945b8a61642fb1067fe9f52926ad69608e1048848c2d2c6c05c22ccdda649a458d07f9739068c22c776729340aaa19f50fe692e27075c20eb4fcdf4ef77567434d0f53b71bcb59692b643dd42fc33f5faf4717a5822a4ff6c3e5246c13d5f66a1006885d88ab889ea711cb3c68f23f25412c30f69a6a1a8258f8d4bbcf026e1c9d775e0b7cc7a65f252b19ce3d305be680031640e706567cccdc0bf9df4107f5c2ef86a40f18766d11a723c02c44d0c04f7b8475bf3ee6d6afb999b8f8ce52abd5b4984b5056ce611d6a6c89eb39f94f374446a38298d46fa6adfa9a4f8b79e956abc1b74ab44919f770d604297e6302696185a8f898929da68f312dcd39e9aafeca38b83963313f9824f85623e76c0ce811748121fd084de792cdbbc8b7bd0327670021341d9fe20f586f93ec013a70f840ea9f7a67fefd71078823239f90dec05a8569923f6c8b5f651b062763738acd3913465ce80165414dbb005b2ce5b7ceca962ad0412c5e76d374f97378020b939046ec14f75f678e33e1b350aa46e2c89bd2116ba9e9011651adf683ed4e3c0e3af8ef33ac1acb5838e0a836d962c49f96e2d04274d8d89188215e9a045f8ca62dadf36fd3d127b5d0df5ce261edd7e40d8316898de36b30f2de60d780bfcaa87091219fecd11e746737f6bea9c4c89a8d3dc1e7221e0ff599a1a15c29d78f7e49300303ec999454c62b135bd4952dafa550eb6316d5ad164d08b546fc20224b41f7430b5900a5eb158e8584b8d430fc651c2cd6c9abfbb9f95172eb976d67db960646b77a7e8472910f6221c926afdaaa38fa2debcb494cf2ef9148c26b660f168666fe7d24de94c39e03229c81db62a37eb8034632873a74e58f441d8f4eaafaa3cc0553431729505583a59a734867915153835b0699929c6a4d24e35cfc2b9e65b90b8e94de48f4affc672ed2c32030dfc58da9c9aaf1c5e8c053c02ad80ecf5800a82a3741bad3463328489b5e7be1cb7c1987daf480da133b77c85ede59291e08a170f282478ee45521149d14a6510956b8bea3efe69e5a32cbfe43e53eef51074229aedcb4037d249c48c35579986c42ae90d3dcf9dd6e79d6a2e5bb3c9008a918477b7d6cfd1282f1cbd26ed7fe616d8689b8df59a83432913c40448e27410a88b5d58d0417a0d19e4e68bee5658a64b2817c4723c338556dc847e7b77f011706171159f703e8e1de84a27e1afd90d3484bb39b7510d625606462bf36a702e1b96c96a46c1e40572cf293bf1123b86871c05ba85b453c4c7505e0b76f081345974817ce54221d81e66de187aa01cd2882ee623b7e2137ff85d8b014a66de3d76e38f61a017d0b0ab19cf9ca78bd7883de015539601e4a6034f13b282bc33e1a8d6868973fb39ef59b22c2b0cf37692b151a3573de35f48cdeae7e852d2293ebf74e12de2a7e4b11447c5016ee576212c6cf3216c26ac90cb415bdce62f04082ba59bd9920811c816962469ef806ac7fe4651094e5c0b22fea287431160767a1f4741c20ed5ebb13f9f643e406d76e83345c6b02fda5746fe1f01ac1c13540259def69ac4a06b7e469918abc557f595432746fe82a525eda01e414f0e2daedad727f4666107cec821b4bbf86fd73682fbd79083f72046a570a9dc576324196edae98b", "3713eb94107da5f197aec1d163d9fd6ee94182a6e8b37ea8a9ba62b4f6299c114624f7b2eb8ae012f59281aef83cf795071c46c91f9681bbc6e698467d5283388f13f1bc8fc14d4d5dea1b35512fe389fd25ee45a6aedfedfdc8424db35f81b274802102248983c4895a14652977432a3a40fc22900a43f2d25c1542fea002f48ed8003a678eadd1d3c3579b7e9b2e19d0609b71639ab0636c1acb88fef1c416e3c66c6eeaf982776d4174d907d1702276c7e9b74a42f86f43eac6e050131a06c5a5ceb81e98078d4a49ae0916d218540c330181ea987f4922f22a11deadbd0814eb782bcf8d933036311adfb288540c20efad829d5a5bc781c9d2cf1c145e51167f3587e2d437731d114a70d914ba861a21bd72d60ba9870697955f024c4fdab2115a17d717dd9c376f796a7d788ca878c373817cdda898ae2430723abf590326ec40fd2098dec7d7ebd8700e4bde09d4f63eacc0e2ea91887c30f4c7f198645108fab035ad4fe6dafc5bbf1e8c8bc3770a2f8582853097e5254a0d5fdc34a22897945a517c76f6c11a8d7e337115148ff49b2c8a9cdf00cac0438d24d40b40c894061db1c35993171c5c44e8d1c6da275771771df4cf4040700167495bc2a30e07ebe7b2f4761b5bb6f1764df02cddc4dbf6906e7778638d5c4d34d648019a155511a6dfadf114253ef295589c7150c287572a375c0b83480c2e135cddae72b32f654171e29a812ff74a8620acfbdfa001cbf51960548ea93d561c6960e072fee8a6dd22c46a2ef8dae87c1db4348cc02a17aedaa3c3685a812dd8eea55c1aa695b5696b73e9cad7ba285ee3b43299f9f2ae1223e2f5247567e5d9ffa492f780abe0efd721b0c400b12c13a3e97e3df8e711018a92e438e269f803bc0ea1413a0da30db10ed90ac753d82adee198a0161408451f4dde770d2d6516d446a47d34de97f787b608ae8667b9cd57b2e7732eff79b083a48031a047b02cb2ec120dc34968eb99114f229df5857f00c5a4cf636edfebe7b22c4a2e4f6ed0ddf992eddc4251f35c9cfa1ee0618db36a1911bca750417ef0efb99eba58f851e92a3c5047ed8e3f28323c5aaf90870efa763ff4298fb9ca7a10aef78c9a754dbb6e1a777de6bd209066d8fbe8484c61aa55753f44f6a66f5ab88116aa018fe966c3678c9e86f5a4b0cf1a673d0677aae94d3abb343ebb1ba5545ed93884182ca10b0acbbd6a3780a08db9e75f972fa29bb8547a22679a07f9a7f904867fa93c3f1abf8158166f63bb889220480547993a50dbe0a9ff5f50f2723c2fb87fd56ec6ab811ffedb3f4719e0eadd67782668f29f76c515f7bb6b26a7125ec170139f49d6a248a3c1d2fa0458ea2e1196d24082f6b43fff52e45be000920c43d7008ea55cba0833f018205bcc81b66115bea63b3a477f5748b6df442d410ed71e10e7e1b5ae62d8b03045ce02c8f0e2fcf25e0f7b858c7c93bfa26759b11e35a0bf1d30e77c0995fe93bc4f7c1f410f2b25007370feeae17e35504bf29682b0a89ad800c522dd923cdd61e37a22572ba284788ec8987f3a6960b4c9d1dd6ae8e1f27c5db17671d01f8d1af6d745b643fc4911ba2255a9d7219fadb9befccd6368a8f3ac82a401b28d6cfa2e04f287de28c9a17ab8b35f93c8343a513bc7766807709e7ec3d68e9346911e2bb4b8eb4444eb0d1a413f85a9cb3999a53638de7196a9dfc1396dfd931da1c5aeb1834a9b5570c1ef2d659ff9214271367e99ce181796421693527037fc806cf5ea0da27c28d8beb3de5fcf7eda179e399267ae73358b05a9d0eef8a44a7b9a5e6ebbd82c8577720a911467a76f33c49e1f7f84ac6fe8e93ae2d6b18d2540dfd6b17f1a0a0013e49d36d18165950f1d788671c2d33458675215a632ab0ef6780d2cc7cc3ca77ba538e042949815ca921de5696210b0cd4a34254bd89dc1231f3634a8ecd4e579c6bc1fc52d1a774c40853b64880e52db237ed373ae6482ced137b51c5e7b5fff945c192ff25df7d8e4ae3455a13c669a0c2a39070178856e7d9bd6d8538fd6743a7f2af0a79bf7cff331525b04bda573af18b55c41ff2da0f8878e88779bf62e879fd722147b7c8b45a2babdcd260196a86057b6cb557523d978649f8416739998ae7723e7e2a13a9b243c893123ebd81e17e82de51067025b6f6992f94cf8061f7b5e807daabbfd68a1da56a632be00d6893db5f8d20cae7da2e0a4c105fce7707182306bebd10aae0106fcaf36d40e295b3da91e15dfc55d894cac2ab10ada071e187a6337feb359eccabdbfcf07b1bad5a3b27de3a4372e1b79350efce6d5632985885927eeed8911eee168d02343bc12b313dba0035da01a3350592122e8f2483a34e209b7161f0639ce40c52c4294eed67c0af27ff1274ecba6c9cdf84a4b5cea16bb51df9c4df635b56340c61088df0f11919f6ad70683886ecefaa02b45d1fb8b3e401222b0ca689179f876fc557dee04cb0465759d8d2fe80084d085db7ab48d15251d0f6e0b9bf165710a30f9c36fae3878254ccadcd004c7a09562e0b8b54f3856009af58ae0fbbd03ec25e84aa29fad438227ffc21a3145dcc04fd4827e39925eaa27c5f03cc74cb419752b9c85e670279898ce18d33513b6ad07c614a0f68a6118d09943512da67cf38b9077a1619064e7465b75f55ef653618c7851ee6364fb976534ed59755c0a2a4e5828610b52e1f80f46adcfa954b8f1af8b6e7ede89341cbd6d84f42cd17448a2769d32a1e9b76c2ff04e7d420303178d91f6e0876dad9831977b79d73c80a8ff000ac705414516d6a7bac80f72841b76e8c3aadc94be11d5b735a5170f385bc459c76c36a2ae56c7322fd16f689353809f5ed881f21a17b062351d80e29fd5589d4ed46790d8b7e908f53d9020d516a83312abb4e8283d9ccbb04df3f1ae5a36d5c81ade0b1b896fee39f6991409029b6571b8f38c074b31615e33be58f145e6cbd891a620c9c3248bb704a11c06daa41e95bb2579d5b5ca600b62cb7a891582cbde20be75a9f7af53f9a32b3680a744bcb86d34537be7dc0ce18698f36dfe7e2ce111331e47449e74356820ca2ab84427b313ad7ca90d6afdbbd94414b02ae4896a86da4d15f3ec9771caaaf0ed3d019fa62dbf97b063d7997b37b60450afc5dc724eb74b4a91de2afefdabc93cb9bccbfce6c15435d3f14a7be8a63ca94a89991a4ce8237eba6a034c5ad4675144ff6f42bc5c2ac0aceabed6a6d2597390c2bde0cdb3e63ef9d87cf284f225aefaa74cfe8057fca1c105dc3568188777ff77adf76b4c2a7a5ef688c1f3cb7f5af277b7391dbcb5daa0a3adbfdfaed316eeda04945774cf813edb87b858f8d4b8f182cb4347cf222d042269babf91c220c9c1d5a032ecb646a655419b9bdc576224914fa44762f277f7631bb40863d9611cb1c3c54b10ae02044814c747f165c100194cf5a74dacb078168bf07c0c81bedcbecff10a0e445e5f19334f8466c7fa164f101ae63b9e840a23c6d1ab981ac87eea04c04c0f6a0ae3efb5098962752cf58e817619ee897e610e8f118de62e3d6206b7d0d29bede21d58b3493eaa437253ad0dc591433fdcd209f1b4a29ba630222d77db0b77bc7d0a68f50b7bd317ce041a1073ce63c05d9e3ac25757cfffede369b86d8c7d5612ffb3fe522c0a200f23858f2cece9fc9428391c55fc7a42015b3e91fcdc4f2e4e13f6ac98f0497c08cbb48cfcbcaa9fcacb7bc221eda94fb99aeb1cd01f40968c9664aad38b24d2d80d9e33d9f6a81afc873809c204c43b67b7a86d55a9c67dbcd210bc26ab7fa0686ee28e0a7e842b7cc781e8d1795ac3f92cfe71e953aeb3751a833e576598ade653b9226f58fc28cf53c8010a88dc70d430f526b35c921d7625db1a11f00ff6c68625e52d5e8cdf165bc39be0fb462097f140ffc2a3e96404dcceb9a5b39183ee181c29b92bfb0d7d9848610b337be8db3d208c204e66f73a0f5e5d82317e402e0956633aa028a7b724e73e1f4ee739b4b07f02bb004797a2dde016ac16330d8395ee569b31ce46f64661cd4d462aef106e6169210fb8705a7ab91b1645445bd7783a20c05dfc94dc25e77bb9b87c11e77724d19e4a8a0f7898ba8cc98e03b9d835cb4cb4aee37aec4694f487a30fb52915ccd58b35bfcb872b508ac9974d8fa9a2081d67d8eede21e09c400805aef1b5d0992a5f6eb1c6f5740fe596d57f90421fadebbb2ac6f80c75ce3d57b7e6c3", .None}, + {.Is_Square, "c461177d9a0adebc26fcaaf800877617b9b955d76140203f873d4fbc9d74115f833423d942a5b23e4ab239e84a5504f14fafd4a1f2cbd3785487d6cb6e21e8000a56009bdb6f5175d5725f49dcf62fd1d9246d1ae6939a081e7a4a679f4e0fd201897087311fc74811824ab595d526ba23c12c5f7cb4548e5a7927dd0f73501668dd6d86a18344c986e45d979fd6350bfd59b2023b7b3252b3c75e7c2293ac4bd777bde1a74d8892144a2965e6ee1916e3452fa316946d3026ae63459c20d92a0ca93f613882c017978d11fe994a2e6948153afc74c5903a29cbb2b399780fabc00012a907cfb245009f6ee4d04c302e76bdd1d6c493dd1158c9943ef33f290edf6f83d7c8dad22667781e0abb519592e3e4aef9d4e4e700b65a88edba849dd0f166515213afd31936d0e712eba96aae93e1d52d8de2576d213aaa28c8af3a2657435fd98f125ea0430ccd720de5a11ba8274b97d3bf950b9247deeddcfe98590ccf8484c73b34aefbb4039e74290e9e3db18cf8b187bd21ae36c6b4a8869aab6067d2ce5ea0169fefd362450d1bb61c1b62211497683f79c0569c8da52d31a28c14e89c1d47887d175b5412ba169c63b329884e1e04f02142ec8bd658002ece525001c64d529285b2d1cf040929ce0983b89c005b70a38f0112039fe407ec1d206ea096f4f2fab2b651e3985cbef30334bd676d2fc4b7fc4c0c53e28406af4d61e629f972bc3acdb9b51e41e0a329711862a16ad10f201a865cb2b9fe987b854874c686af4a3ea835a89a832bd8bd70b46011e44b6a37f6a307a4569ea634cffbf6ce69f3202338fd8591e8ba81199c2e92f2e98f9744555e18d6e61f142c84523b565d508fddd0a13222b63aaaa49188c34f637d5b861c44306dd8b4dfe6306d3d03c07e4c7aa8a652faa110807e99563a80f9ba20001bb442c8c10ec63074c20b9824b2648ec07a4e319580bdc83e5997eb94afd5ef2c41afe5081b0be8d6007db0be460eca4e93d5dc5d396809a8b466c0c6a34c1a36fab565038326f30f9eb4d941e26087706f1db895c5f93c99cb115a73a8b4d39fbb2339a7a17135225182a4e96ab78f667cede2c11505aec275a22f3e46627a9babe906fa9ba05ea04775e4ca2485c233757f976b7eea9dd97fc248e425bd5b98b7317f89e655e5a42c40bdec0e734645e4d510871f123c72df0c3c52d045955198d07be02f020d0c657f10fdb0ac1fffe7b8b600dbdb1f540dab27adee1951c46960db8323fa319af804a225d356578f950559f0e68fb04743848f8bacbb1e33704b26fbd2efea8a3024357a047c9a7113ce6cac1bec242be8fdbc56909a85cfa6a102f1f3eb0bdccb52b573b7b108a16b76c872318d111539bdf1f5e27a6e7330e0a2edfb663c6cf4fe96e5df0fc8777b1130d69e6b2bb011834a91e5c427f411a3334c83b8f781803c7dadef7556fb09669170cb9b86c997e05e7ae1ef89e5ea9bc654437e3d47ad2fbb7cbf64902ecc3369b0fa64b94a6f505d94f2f2caa92eaf419dd827b482243e8f852962173ca1127efa1e608a53f4f962a9af8984c09d8ff62a2d69b1da4700c4fb9d9fca624d9ffb4b8eb8df4b137e3f559835ee0e69207c99c95c5714a2641b2a5c654c4f5eea34a5e1a30b8c19e4a90522a8f1999b900bca43fbc982d346a51679b160decaf5a74582c5c0e26869c7ebb76d04db40ebd8535f2b73cfb8370152f1efd9eb9f74fe54bb72802c9c11b83474d28ea54f4126c1b1328e9a2cf3621a19dd8e273f3f6ab5b6934c72a25666eb9f950ee71831e449ad02faae689d482b5da4e97f9544863baf7072d357c86adc659152792fb15a1ceec3353e69e2bd29f9475a133748d57389964ba24dcf80ba5785fd6a5181b9afe05d1c68eea81f49be4cf9b9ad43a3d60627cd3f997408b218be71dc637365c57bc3555f678bac982809bf9fc7131f17f0fc581ad518d025119b5c041e9e047a1ab045718ad52d31cd85bd98b0b2d3c675bb0d61bd53bfa742b75f353da81ba667eb563a2580c97c2983ddc050ac164fe90c66991e315780ea5cd30cd6144a9fbd64b17f6defb1f846d886e60ed2e8eb317ecc6e87014a33de056aa786396f6f", "0", "0", .None}, + {.Is_Square, "fb74f78b2108de631eff54becf9460c5819a49f98bbe9fd001ef3f484fb306c982c7514799de039d9026c76ba9e769166ef2e1ffa4ef8279b4257f9729adf10a8bec22b02893cded97cb3cb080c3209e859449c584b376be06dfdc3e2cac13d0178e928cceca85e90467b8536b51a007dc054af1ec579d208c4a4a3be3672758c5ef90fb9882fd1141501811b1ced6746d1f9db64d27cbec141016078a9b95e4d07f8ca2218ba1183c16dea9d49b75138dd8c63690eb1f449596b2f50c3ec499ad15555f2a43a00086e3448b0adec8dc5e9e3b2b8f3d24b2d3c515962a7037d9220d6fb4433ccc73081e53e233ecde0906d918f219367584f95698bd68072f218d557708c3797ca9746478080d3466a9193afb712bbc55c25b1ba496937ba73470a7f5543a668a2dcd062a6038f10f382a450442752c7667de716a178855ef2bd03217ec02b58340201af4582fff74076e55887d3eb4eb91df36d0cda89edbb8212d41f3e8ff61b58edcd46b863a080d5a79b7d0f9c2b275243a1184e4470d27175cf8c5420dd10e3d0b8badbcd73c538d7842c71d1e0cdca6992e015afd3dc82a9420eb6fe7be8fd20f7c7904b8a1301926b9fff64957edeb03589de1316660f16fe6c7540176b841e2f88a638ff3f96e980766b67a3256831c19d0e711ef70be91c526cb13302aa1df92fcc7894b6907461158e107240eb16af44bf5cf6028fc969fc1aba74cdd6e9cfb71193716bb6d3a10d67fc29ff41c4c9b9098f5c29e80725f316d3de4e364477eb08d7a21f218a1a8f1e95cff80995da26749f591591f988d2a7935a992235f4106bfceff497553efd5707882dc6f964cbabdc896ff784021f1b06a291a420f6667adb3a96df8d1a91e7b41d9dbc50cfc3955665d450c5b90b93ebf5181321e7694d8890f82eaf11588f8647b21e3ab2c21e4e23b710cb8270aca000938aeda1da3f9967c1bb9faa4ab8b2e382a6828d47d54aab4c2cfb47c15792a712efc43a755676c8643edb6d2dedc781ec685041b19a20936e471d736a31405e10cd9ad6121e9e5f3c7666e9a042e4e76c22f2ca65afc59be0ef444c2bcd23994d9868666d7d72a0bffe5b6489dcce2f602b2f279c821765a101ceaa19769e16de7a7d3ce3ffff47a4994307bc52652943e3ca7345cf37aa9a3d40542b0714149faf5d14e885fbae1b19afd3c800510c2aa588c0f552947e2ff76976ccfa9de2e2f2f92ac7d08c4f3df3f949bc0761de6a404f79e1b83954fc543e711dbf5e7e15700ce5616f254826eeb8563d5301dd229fe306fa3db5c14d70c5e47c51fab6e1e2f0d3df1760d219ba63f7cd61e8867bee6b19d757604b9856ffc9d73dac7340532b88950579cebea7faaf931153d4f9cde26fb4be2c57ea21cc313002c8cbbf35a4d13340c839351330db785a209bccfd79e4dcee9660246bbb128c98529f1d8ae9da2368d480f2ea3e5c0ba2850e99658680582bd81dcf94826f2a2d87ba9bf2146adc3b2ce035b9db1dc156935f56d730f3879cdfb510c2ff57878338cc911508464c1e86874969ecf15a06547a8758c4c0ff12cd73f90213ecd7ecfa3cfd138cbd55204704ce6198fee3d75112783b202767c4f782b4f2b696afa06fe41b72db4d2c42b3740b400b8ef54b8f332d640f7f47995e599987232e00ee96de5759dc3349c92bb6f6400b660d5697debde42ed639d664dffb24db31a2f8a8ec2838d62514beea519201872fa735326e7978b34b48084d0989e2527ee0c3abfd3f2f3c68718e8e7d52a6c8be50a2f3f9e61bea9a6903d07d0ef49ad769fcd7df2f7c459dd64ba2cc32902e55cb49e2de444dda93aa0bcca74e2c006056424d10262ac8aca8a788918c4bdcb7dcd7afdfd342b49e03803b16703075384b5af38ac0bf7f06e5dd65876c5edeb6aae9414eca61871e40aae7748fb5dbefe20e1e8058caad45e5adacab08ffa2ecbe23c01c575edeeb3ffc22bc79633c13d86797facfb726415ca019c74a13e6ebad699e9e5cccc6854af61e2be724e26fb75c5f627b04dd3b204f66531b76bad3c23a7d5a175636ffffbf7d40832a09843c96bfc56c28c85ddb8aed5b02db007081a317f6cda6e4c56eb", "0", "0", .None}, + {.Is_Square, "ea68eb64a026d5b5d71f86241a7cbbd20882739878bf867594248ef2795cc74bee498f7255b4cd87700a2cbf0ec14c28f897ca008d6313a0e41378753d01b5f2cb7a7fc41ceaf74ec32c996f9dfcc1a2a6dd493f7c7665eb5be3bfcff01d4c147e72f9e0d974fd7ebfab2fed99dcee513f251b3bc9e28badf2f0119d547c86582c626a8ace62b3fabe5b86b25b600cfb4a15c3c0a8e293b1cca70d641590445503ee9237611add949f6024871e3b302bd1ebe0aa21fb1909e5a2864a1ac1c4f30f6f9ad7324de9e3c9832dd7ff48fdb762aba634e12ae7b27f626ebb337f72fe5e572d1832441188c4474482699a237dafaea2156f8475dc34212e05cb78bc67471b468fdd389148eb99789c401e661c803eeaf99c3e44442534c37b51b4407e1359c98c9018aa9c05e2c582d916f1c9bb50c1c0f68fcd87ded3db3d47ae6785bfd6781c91a25c6f8a36591d99ed347a74a88d00527ac7eb01023f7be09d2aa0651464e6f0411aab60e82d5299cfee2940fbc87b8cc1a6ef765ffa0045eeea16f4cec9215f33b861ad98a4d516f689903850b620be3547f471e9eaf7a60a5ac104e420dc8abc42e231131b29cf2ac3f283df8259a3618e8d0b13fb05ecbdce998bd9590df0752f62f239291536fc126e3a13a54498f223cd1e06a5082e541b0b72b6c966b5d6c4805350cee7741c25eaf6f26b68af5de1429d72b34d43b4ea9f7251d66e206ab0dc323407c90f0c593a39539d0eb070d70629e2f8b69d987f50855875970eacdd4f6abe71d8425d6d090b53f6c9635edabfe7dda4e2441b8cb4612d96d2189e8764e863abcb5f92079f65e4bb24d11ddcbf4db9ff51b9ba678e21ec661701d3f2bcbe17793bf546996cba51c9e85c65af85b0e8ab05baa46027b44f0d052f85003689687a8d40ca13957b10dd700a3f5ee021cb56e6577a0cabd80f8df5b09fe2af09c53553d039f1fd869ab20686b5c7f6d6bae8a095cfe98a036194b662d362b209fb48452af7f64de68a301fd2019fdcd71a731812d39b6bab8f5a587e281f2450250e8f4647068cadea4a22d6e1c89db629d607591a5837437032246a809e8bbe2717619b99bd91800eb98b0bf38f34278ecc9b4fe186227c1c9067b19be384318f18739e987be9dec417470488599df1e11418e6c27b25861430388789b4136d96692163f99729438355414b8835bd19d5ad58b2a7ef7a911e18c7d60c000cd98cec23ebd0f143823ef87edeedbc40f321feca8bc492587f2d6df752dbf69b59c55e8aceea9d9ecb6427f5849aa022be6764570eb3992f83be40546217fed6393d002579bb484531a00678e4c5ec00fa50138f6dc8490089ebc5fc3b468d95ee74283112fd886ae2cdd41955061ab37e9d4dda6ab1ae8f2230c7ac12af154448aaa3bb2bb8ce1f170a543969ce5f299b8cdb377fb423167588759c134893959d6f8c3422366e306602db684927bb778d3d1d6f53726caa9740bd84f0ed1d76b826d6b71e9ae55f7afc596a238eaa77f15609fd1b802dd0b8756da3c2c5f325b8f4d626c1f2179998f62d5a50a85325082d94db4889c95b088bc1b44b22860801d6b5d14cdcce36528ab58a0802b865c7b52f8dee977b12f2e7bbf73da8dac128a3bbb2d68d92c80c2bc04d4072c46bf5b9976dddbe11c367c1dd08f099995e5a92e0cf6a8e3da350304a8e0f6841ba6958aa55548892e283ce8c8b3b9cfbd40cdbbefe2d11104b56716d8bc70eaf7a3e874db0de5693487372634d723ffc418d59cc25b4716278aa24bca4a359e92302f10c9c40ed742cad49dce52af1401f6c31ba9ab88fab0ff47f9448aa5adb6eb9c5814d29c82a55d9705e8b3da3dfdbaf2f022efe78b0c35fdc7ffd844f288472f660e2c38a4d3e6c400f8409e69235ae3c026808f170cefe7e40fde1b6956ce49fb6ab0c23f5a9e49d286604bc8a45a0fa6128d894c7612262c0b811781cf8b8c0d2e491c31e27c8f5e3618d65acc2112913623dcfbd27069302d9da78e8100c772a339c24aa7a9360301e54bb4a53780854922f2d45bd1ce069c6aa1a50f9a3455d5a0459a5352ade30455df6f1524b6540769f4962d9fc6b916e2c1cece79e6de06d", "0", "0", .None}, + {.Is_Square, "585e3fe9e90a22d7ca600c8d202c30caa28dc63e095c3f4c8766905081c4a2019dbddd5acd9aae8d4650b8f783dfd630a6d60718ca6a22ed2cc82a80f8532fe9ecfde3051c2400597ba57f523b7daef5f38b71151c016ef1a2bed6a15626c7008f695dcd0193034fd85163aa4b46c9d983d675388974ecfb5af0ece85d4b656571444bb803fe2819dd287c084de08e0f3cd1f3b18f4faa7b3e0b1f5664e90c2c2c715db4712933bbf512e27ff08bcc88240eebcaead8f896c2dbf5a1cbbf27f860f566d7479ede4557fadf8e6f80f9592af3a1062d2020e4fc5bb314615df485229ca5d9581acaa724b144670947568bfac107430bd48c6e1ffe60952863ba837d62e31031b27592ad87fc5a7823c80990849e2fb7738e2a50f8569f7558b1e6582d3bbecd1d08aab6f8dbd596070e144c85c74f8a3bf481a2629f75bb2b8d6e75b88ef18328ed4cbddc8faf3ef5677a436fc724c6f01ff40228dcf7a5bd39e2e07e6c440cdc7cf2699ba9dd250a8001a76e5bcb39dc40fb9669b42edb89005fc07618f8010ccc07040eedd5f433fc0d14089f35b3b8f79f91b50ce23cef58b4400aaf1812b334f15799a82130c013d74bf480fb8af6d37c6f020e66a7b78c14ea0157251689d6efccdfe8f77f7bf0765064362ece9568e1ce0e5c7c9110368fd21e46d82a1d37cc9e0df685d2a5292bae03dfacceeee8590b25e22c1fb45b56a74811e3454b0a2caebf40f186cfd95f0cfaac0849169f2521bc7f3c1d62135b20bd2870fcd472ef2d153409c07c7bdd7f3f650c65895b0a564d57c0eca90cf46dfd4c71edb86334695ee497ce25991478c80b7d05134928d3add4bad97e11694955946f7b0fbaafea341c470f3eaa2a557dc9b8adcaf95de516e382ade83bf8579067f518603a4d588fed9c2091a3110b7b13b1ea27e71a62b418a6516efcbd74f746d29681c0f3b579e6a1db80b5542a0e1b18f92d3a262521e4d3f6b1da5262baaaea6487e426cd7e7d9ad97ab795f2c9ef7d17a69299c02b05bf041fb19e82bee4c61f1bbd7e732c80537cf872576b789e1102203fd7427c8567bebf936ac0d706cb504d2b4132ced629b26509c43d5b03fc7e08cd3e4dedcbd6f7f762ad320f4e80f6bd5fad9b587db22cc15d8d24f425064ba14ab37bd53bb4b74c016e381a2753d8deba96a3f79e0932c067ae2a8a95a32ded6f46c113677bbd6d7d5c3493eca61939f2bf11edfdf37cec897cd5371715b3f76bebeed4c8dab20a0733aad8568e2e6317d39a75b9fa01cabf126e584186062622308e752eaffbaad2aaaeea098355d1be918441422b95ed667fdcd6f26012a717e31c43511b880ac115ca9564d3506fb5889f5ecfe8a1fe3ff21373be43e2f3b64e46da5934fabeb8dadb994a401d5f2c9d056b2d2f74ac225ba65666df21846507b97bc46c4851a11a590c8c15d5ec065248306878f37541946785f9b0809396f92fe31cba1e891d20b4ed7a48509e7008bcf4388805fd55e0285e891e12625a6b9c1c96e1bab21ec13c2ed034f28bb49722b928899be7dc10667102fcb9b8cf6b38c3bb248b8b5a204256ee4dd67bc6dbfa8fdce6191f4b6751db230b4e534f06cb2652c9fb2cd720facc64973abd9309fbb66ae37916479f3daa59ba1ab0d81e8868f021d9260e53b6eee7c4e7a9bcb0ae06cc10a4efadad8c64f63a7ca218e641aa1122b24302b8b8a689aac2f6b7aa2456459af1bf12d0367d239b022081412d8c9fd839909d5340a825bc3a85eb174265d48422ee7e9c1f98472a4d01a8c31f968819e5bd4b8ba4e38e57fa587692a1cffd8bc01ff35095a679d42a005ee3a903a111aae365965ee0cb77532d94c7abb1d36103a141b74f70b5a37b374dd646a1810e9150326855f9790930b0814b7a7eca8e977452dd39ea42afd7d0e60b2be26cb8cbdb8535566708e8743ca14c624b1f461ff61ac3de5b60a51d778a9b3843fd68ca6d8fb1e106a27cfcde040e6004c3ea1962a8cd3d8c79d68cf30fc27c70cfa85331c3e858b5a2695ff102640a4389cf3499d74a8919ca76fcd7c3130c0302bad97dc2e3a10369823cd7390f631d466e900288744e699df2b61a828241a9f532", "0", "0", .None}, + {.Is_Square, "1cde42c5d948096dfdbe4b34e4fefb200179a24d4fe5f772a643f39319668dd2e9468067cffe337f8f15080ae7ef7ecf7fb7335aeff41f75bb79fd8b0666bd7929d63a729d2065d3ec6fcd5e1ba228ec3ce5552abd2f7a1c395150e2372ded85180f92ddbac98b0463f85f7eeee9dae6f2b87ba2475172d2c4c6b8bdaf741ad086e0f6fafb07f245f8c6873c4171252296bc307265b8ca4cb99692028e57cbc8a82e3dbbfd2e485ba338b97096edf9e8acc8d8aa569ccd12c9d6479b843d1530ec99726d0ba438510b117c6af01b2a00da521d81cd2bd2e665879c142522631cd8da1c76d3bd1551367803e080e9be910e625999a96387ab4116aada82f1d659c4b70bf4a5bc07e7fb5160227402e0c9eb1cfcad44bf249e328d73ea02a405f8b8cace37c1c19c93d8d8cadf35ed9ea5c45a90bfb065c90a0c040683275e8b6d2eaeb85c72a629ef12b749fce86dfcd2c5a866f336e81251fa20fe8f9af0567b58653856b79c4811e087a5ebb45c9416c8398bb163ebb521769e7fe13bfe883ee1160db09fdf65cf5c79396ad021225f53ab7ae7f43e7b8a2dae02576a211f99d031a0d32f7ad2a76226570c0dfdb43852faa581e5aefeb61cd38c4911bb2ccb79673634c6f9655dcd1c1546d471032c2233816d7acb4a0c766d2f38a67f6b6776550d3a125cc3c4b4b69ab0c1f74c7e5e4d7c630799a25e9944562b59ef296811a8144cc7fc376490aa3937aeeb01bdf29e80b9a7e1a63dfc9d1ecc5b4e1f5a05c05e74afae63841e7c21a655d2cf8609110d990f7a0ab693a4f166fb7f07a8e68976fe6bf6e8be31fb43a52064d01cd275dc11bf676282e3b716ca4d98574b8511b46f9467b2ed9a4d324238aaa84fc2ad628b32b03aa573a30aab9a45cbe98a5b17965ca4b895088e7c908c220f6616e0d38b6bf8261a6c5d336d1b1c9b9d6455002c8ade10fae25f20cb9e0543396eb3197fdfa08b6835716d3f434d130d8bf8f75948282f848e8dc851a2fd018f4a06e285b20dc77d33d4f95304bec440fd9dcfe0e17f442a8d8ad1746f3e3a8ddedd4ee5f770660b9a66a239a0516aa8c10c956fd6d676e4609dd625e28fa5ffa7aee59d024db9932d81f8030025a78f98a8ff46b70b0d10e2330f0cfc5d95036788812784bd6da3cf7034b4998a2aabac2139452d5b3e1ef0d2a7b8c829e9a3ec07972048796bee2ad13e1d3d4c7464afa9308078c02023c6c56b5387395cc55c67a5562ba286fa259fdf2a318869d05431d6010b4cce91a02acf55f59260066f22194b714740d536846f0b0f96dae9da2563757d1a3ebd6656642f2ccfe6705aaa6fb180a537e69414121ffbb4795e9af1b9d8e1d430b1c15e19e3885ea70d20937cea03697fe2fc80501ac1eba9d5c11f6cc3de3f20458addbd548210cdbac026026c20c688b027ec9423942e8465fefb8ca39a084953f483cabceb299819f1043d25173d465cd7ef0ed016e0e22b09b727f009dffb8f441e46ff3aa62f7152b02be115b6ab27b3da281b949aed232d8d834938c829d2f2151d7b0977317539ce33744c77c818390685cf0dbc59a023c78168a540436ed41ca6e1eb6be957620d82f6aa1adf7feac2bf0f41d1b6550c03ea92159b01f5f05f8d1c51fad0098e2ca877327237f2d75e2811e2ae1a5d5cc99af80d2a2e57b88b8ae7b783ce2736aa5c307b2c66f264caacbba441369df449088f32654fbd9f8121e79326423e2b2c2cac945c1dd9ca3baff61eff6743877585d473614c71e18e823edf0758817df59aaca73a90cd662833fc0a74b06fbd0fcf6758c4e41f88e92f7c11c8d8543c9b4055110dffa3e25de548f30dc11513c0aed54572889f14c2087aca0ab9d7f3cad5fdd381bd80cb487d4f8249ca3a8f374521e44847818fbd910f6f23cb2aeb1b8ee68eb8e0ed647203f4bd1783bc8d0accc08e7bec8286ff0f8b52916c2441173da6bfef9a02e96d0c2645c8d27fd1459898582729b4717af5dad5625c6721aa5d38b42358be38bd102797548b3405f0f5ca8030f4f543f4cfb7a1c33fa5b50dde8094c16a66030722d96796fcc84382a10bd82bc8c61e9a81688ca8be4ad690f59b278b6750f567ea6c", "0", "0", .None}, + {.Is_Square, "8c574be4a98637730a1885cea65edf97f148d3749dd39fd80bbeafcbb9b7f49cdd12f86271da4b604cadcb8faf8f82eb63c6e793abf8fe36e64ded098e44c0284ab13d822e471a6964440a3bf2c768d3aed96d78f293a7b6bd3f970229917a3165f53913d89faec9eae7e655c8a33d668ad9df85d174e090ae151e59befa72fea7b74c1bdc6f0be69927e507a966c87bfb546740b420775c56d00593c6ce05a40e5cd8fa8d2a4c9f2b07da9979cf9f8151a723a9b53456284b7f4c8908fe170c3c576c1a8a0e4fe2efe179b31537b1a5e84080a49198b8c39a123b4dfc811bbd70fe429b26fa02909a547d0a0be6b6d569d98dfb580699eb92a7750eda21d67a5c062dc07152bc5a6cd2341f9e2757387e4d1e7e2e65a41a6f16bef4ffac016323a50b478d3fbdb5dab20c1013d4fb5b9afc49f0ec3e0e22c13ac881fefaeb24d3831fb36b5d776433e8831175724f93064d1767bc66372234a5dff4140065a360f375b6f9a74b72952829f8e0b59a16336cbb61d4433cf0afcbacd2fdc385e3cd07a78b34dc6100361ed25c91a32538bfa4d03150172892e22b355d52517498aa56edde10cde275c98c114ed062275ae07e5048805892798585e8d67eb57fcb872429f2451c7b70683449362a612d33ac8a8354f59a3a28994a98541d8289daa4f930ed338f4aab1dd6fa1d822f8dbace17302e0c0a7a167df7fcf81b085705a2072560b16b85a9f0cb808064b7d6fee80ddf042f6aa0daf1acaed6002e46b0b863e7e9d230cf7467e7a3e301e709e21a737ebc9281568dcfdf37d6e13059c77a12e80a0a5f97a2f66eda2ad5c8fd9deff1ec155748aea090208d53e6dfc5dd5c65b72bb1cbd1be5ff45eb51e51bda4a25bb5c544f2d636ad377d7fb7e1f8fac486929c2c8cdb860d0b746bf05b291c7da67191b10a91f470f0e4aa63d47a76a2eab7896eeba60b5fbb4a84e4bc20311c983834c1d0446ccb96b20de4833d2d27a71e55f5ba538d7950209c4f3b31c32efe36c5c045ec6a25d2f21ae56c82fafcf5806c1e88c731108d6379f25bd3a5cc355a0ebed1849208bf2d280d328117f13ed41afc9e2f8ce5b7c95d4d158d8e34ec4caac48ff918f6a302082970731a1dde939ff5c23b80597186585a7da2289001c49606bd49845abbb8f93733082d023a4486c8ba5d4ab68393f88074c08e51b53cee43fbd20f0702d24db91a876a2699c72f1670bd47da40b56448630e995485246d339200e5c3ecf84acb685dafbfb985cda2a868fd41bb749ad0e0b75cafe67b101ade2b03fa3ffe1e57d165b5a742766cc9ff6e18db96264761ccb8b3e5b476665a6705f9db1f8235da3d49b9f3f815693a7d5f07cd86cdb23d0c978ffeba9c4cbf6201ecead28082c1544fb9fb4c952254e0fe6eac2560d42c60fe95cea2192156df187392500f1362d13f736c47009b7d2102e5c8e20c9b66c097e0fa8d3ec9b12a7449481dd70b2182d26682316ea4d39cffb3bb116408637b8db6db6db42d6773d468e593ecc5b7a71017495842d0a85cb39b1c6837c0abd36ac28e12893e8431e4522a00754086c0a23edb1f8f207e42b7846fb6f9eca77c1411c25b2ade3a20b3f08596f6184429731b956186b43beeb4fb5345621f110801b73e6cef7b4b13bae9611c655e5c4c71c4db979719eb39142d0a55ccc5c09f880320ff4ef26a9c2f68f67c115cae7b61339539c81157c6efaf19e3ad984ae22c3ebf1fa48a30fa38d5e00ed00256741ad701da7d106235dfb1b787066b4bcf010485e1c2dc654b5f85c380db0d32a291c5c507a52dfd4577ecf84577e9e59c34ec27f1b2f6e2bf64d7f53b0ff2142419777993868fcf818e71e78dd0791eef5c7a90dc2a6129f4c15ecb70ff601164734bb1691b035296ba21a6be428d1f6902daa9b59bd4a567b42ac82105e58965566497e9a38c0de28c278a177733f6c455be8ab87dfe4ca3eb9c74c49933409579b1c50a37ac2fcab49dea1f207b5697ea1548131aae4b264ad6d92f8c0055bfb83a77aa384e49a394d7a04e0ac86783c9ea92f8163198179c630ad84bc4684b49cf9ed65c1dd6350cafe2cfc7577419f09028a8240fc90ec82bf5168c27", "0", "0", .None}, + {.Is_Square, "29f2dd00ad447f8ea38c262a495ea99a95937f485dc6b8b64ecbbdc8ca02a7356a4cb507560bfbf8e5e37b6e58ae2fa6258167ae52c1b367542f4e9b237421ce6f9006e4142d497667e6b424be7a3d195353ddff6b5809f0f1a78820d452e58974dd969ad837c209fb872a054e43d9205cadad858781af6d6158c712c8516d7489f1be779a3ec6ef71b4a654d627b29de819f3c81ca5da0f3944982aa05f6d1c960e72e22b7db15094945ab6c75bff829b3534782c011bdfb855ead4c7ea098a9e48313469ac097204e6719fb7973d3c1a1e71f3a1d2fe04d906024b85803a997a429b6188361081215c98fb09b6ea8fa616c2cf2ff0b57f22f2fef8e6a195ceec51802e24f772400e4e3b04d5e4c0090d9433313a3535a8c9ae036f341922496bfc7119f8683d178956be13b70b02328902cadfa290d2919898ef3bde636d93b4cdca832b8ee6fae4340b325655dee4469db55a0ad1ce3a4af895a77cda9f1779714875642361d33f81e9da904114db242bf9f3b2fa21619f0e02aff70f0cee8d4973ba1e9426cd7a7519c9cc57c2c97e80e947c4a0066c81358fdcdb006742e4d54ed4475895d23436aeed48c127da356cca06746061829d24f9e52d8d1639c59fa9668cab20d26460c96d184905a6d3221b5e9073cb11322832b61d69ac57531597b0bd936f63f40df2e916ff3b50eedb6ea3e9792b78b3f72196bf12977ff43645b452f5d65f0353622be1ee461165233950940f8c452ace7e72979e8853b5672457d013acfebd9ab204fc07483735d5ddb1a909c4b9ee33bc9d152bc53748315e117896e783351bcbb0665867b7a4037f55ee9a009e2662e1232b39f26b35813adeb3fa284e5d68951001880fbb127ed764f40664783c3eabbc67115fe17844fb3ef8392e926ce98a291983a30940e0ff182dcc7a4288652dd869d82ec7f4672a9b6f1f21744e1fc221e97f25c4c71b188581a27d6c707e5afdb264debd0face6e61add4ac11671acddc758ef2ca13f13b2b5fafaf5380bac1efd89ce200fafbd231732525b95ed7a21232ebe8dd97a58e0b36c7cb7da35381b63e2884561bf335ed8f968c892b8a660ffc614b1edd01b8e77e075ee81f3e3b37d148c1a73e82aab050b165e986daf7fd0ecafaabf13346aa94fbafbfe84318ae182faf92cea20735d6110c69fab80265821c35311d12118008289b8838d3b5897299316baea7dc8ffcae0586a0af627ffe7e27f2827a63e37be142d72870834305a98ec810c2ce62b7f18c41bec3ac9d42bbfe05a2bf460ab42eb42773c0e34cff7b161f8a482f3b1071f79e6b47e7b71e930b1e8e5ede2f37dbdfb1dceabb47023b6aea04a95404ace90f23477efac0a3ad10355a9cd86949621dba572372906034713055781046b79cf7cac0232f1abdaaaf2b5c5ef1ea9da563d402f8e97d14c18b7613e9852bdbb0add6f9ccfa580985c56b6095bf5cfb592d1e4bad172ef7b1fd08ec759db1488a1e35dc34b534aedb699b505c78c10a6bb5d70b6427700897fed223299e37461f049761c24c5fd8a75d68a9479ee651181fef9bdac8f80af943df571e55dd99389a3335909880c6c8dafb5becf081070d696d65fc9f4546d0e14cad0878a9e78e2ec322baf7c0eaf2b25862de260f91927f096208cb32818d61aecc88810942079f1cd6a7fd637c74844467e8c4363c328caea84158b3c6f3cc13cb685ea56eac016f8ab531075ac1922ec7344e9f0ee358d665d5272b9078f94d7337ac14d244465bf6d501d74bda1aa690032e241e91ce59f17d36249994175257136028dcac0551672b8501753f25290a014819fdb5f92e75b63fa068d410c8014be8089b94fbbb6569acfb5b8889a348c52670a0757c21c38ec34e12eb13546a1337ad92428e81161f319171c64e28163541f63390869630860163da074866331c9562f790b71ce75a9225bd0979d63b56a465c4444f10f5a868336204b01b3339451822e7c4b05a0ba53ba84bd32b36cfe764739b6b40c2b6479525eb7bd9e53da76874aedb4aadec811da0ba10a395bc0bf1d4ae06734c074685330a09a892cc11465150c0ed7763dfcd11aa16c161a7b5b6375520e3026519c", "0", "0", .None}, + {.Is_Square, "10513754ef160ce827ed9de35934c6b95774d9ff13bc75a8885c52c6c6f4c3c9893a4a540b32ce7c6a50b1848779187b7e0e68898c17c2268d741f9b96339b5e333ab72b6bc68b0b973712bc082d4c4fb8474e2ca02993b53086d31ca086b6a625f0aebe74b39993cd90da17482bfccd486e9dfb69096af38062d8fa5e8527fbc2c4f7abf9c6baa9f699439bc034be775224775b4113e21257a8b0b3cf90874cad7379379b2aa3e761f123c7aeaad2142c22588286a5e4c8dd29608f09611455c7739fd35580f1b673a6b4884d0a7760ca68ac5ccceeb38efb6972b24d58b2cfc262066faed415f9f4ae8ff176415855beccf81ca3a04abfc0aa8090781f3076ef491dba1094910621dcd12998bebbb4e356ed2ab4ecc9542328d35218c935650b402711fb30e1bdabf0a699a5c7061b6b581d638957ac69fcb73aba9fb158a6bc148e5bb1b554987dce42268af0fc60bad2ee8c3c209c05062e73c275929895aac514e6966ae106b5720ea4138008bf1a3eba1aea19c63d97318a2e59e7ef4d681f1d8816668b57674c88198ba3e9d9e6c2dfe34404c11ad31ed6534027b791796620ab99deff4652017fbd20d14ce413a58ffc01e2d322aa6216a2691761d6e82116001e40db39b4cc0064225250fecea76fc33c10538dd1cc5ea40af3eee43b207a64b5444964ff3a24f7b1896a21535c8adb67903c1d80dc9a24cf811b5a2ddbf2fe8535fc918ce9aa962caaaa9e2c241e11646b47f8391a37a742e4991924016aa5e3bb66c8bb1fad5e67593e1b3e161e14512c727853e79ea4079490e0a61393767f707312690bc1ee38c4fb2b53f7a8cff09a41c820a6e84ebefeeb709209102b2ae0ce48942a6dcb4e28bf25a1f1b12002eade18fd6d4f914bd057224ec754249a1ab571214029fb849c858d04d004b99fefe90299f7ba7e9ef04b447395d2f1d33f5b4dcb2437949c2fb1311c2f94ca1f15f478cbbc572fa4490acdc3e21093341d5a76d84841910df57b2ce8bb61faa845cce367fad6bafe4dd196b4aded916402897555a4bccfb61a2e669f029e4f9e5b22e717235225385e02fcac6e73650cea861ca0d966001aed75c878c87c4950533b5fd26c2a3a827fbde7e1daf9d427d3c2419e8fccfae53f26a683b314b9ebba8129f885e21bedf16590b3b8a53891dfab6b4d9eef9695bca3e1a3f3cfcf2b9077885c6f26ad3c062b0729d3643a2d4824ebdc04ce4ef9a810c1319c34ae3e59f5e127765fd086dbc7165fcd754159e5339232b217ac811dbab5899faa1f80b4465c35a3e545f25ef5a6cc39c4210fa098afa930115111700c3e770bd87aa566d2ec6ac9aeb48e3f38821f0cdb191ff1a70b2e6c023541e06cbb6a28dc6a9a4ec43ffea48deffe1ecab098227c6c65ff87ed6a7dfe58dc133b613b9cd35624e03b0fb58252dfdc972dc2bad56b3a7af8b8d613908f7634a91f2d13df55655bf2b37f8e233e4cf7d5552404cb96c7450bd6e4f18bb818e67c98a48c73d78fe84d44d5438b5d1f23033487da6bc62c10bbdec7d06f514c770eb4cd89e96eb6bec9476d799b7a6c1f7ecbf77283adc8b4a607f00b9eb5906b8bd56848ea27e023899208c204044466cd36ba4ba23be214ebbf52f3fd86f15f99c4faf5cf2acebc8216739c834244e7da9432c6b0638a758545def37964eb133a22d80f0650edd206e19fc66b4b3bb405eb9917bfccf49867c9ead6cfbbcc2252eb29c5eaea40064eee018a524ff516639af64d90deda26389a64beda125e5e4cade333f5bb20777e3868fdb77d8a7ae69ea8ae9ae7053689b63f670dcf272ce5cfc6412234c5e08336032ff8e8d46d8852fba749c107ec38c45caa70bfc6651fbd286a933357938b48bb8b6965b2f196a3cdc28e1b8142e76f41cd15a88651692aa62b69f6ebca1fb5eac131e2e4f80b27df8a3a071becee68e949a4e12847062f060c689aef5ec14ac1c353ebd4c38c52745fedd9aac36dc2d9972fb2241f3523ef2937123571b3c53f776fb494d62da6c202c486b303100bebc787e32cbba1a6f3f4b325a211b8ea20e683425d3affcc9b813a75ef83e437dc03c5979a774396f4ea4c0c3c103ade3c9f3daaea", "0", "0", .None}, + {.Is_Square, "bc8f414f55ea121636823c6b1d4ccbca253b66160fe8cfab7dbed7301eab783a94473e16e5b6fc83cc184810b8e4b4c07bec99cc893be33512670099cf6b96bfdbc20181c147d1648e2230fb50df229fdebde4d4d06e6cca7851f981b81a3d50ca2510caf3405c010f724b0b750dfbffe8438d69d40ce013900db6a13e072e1cf56d6aaebb5da04251801d14bd224d817b95cfeb224182b0a17b90d26a2d9524fc0fe81971074355b3eea74daa15019d92ef390cade061e224cc4b96e39db61f14adf590a6d00e4ee1f472d89a99f5d387c442a41acb8678ab3dacd172be4973ea75bddd20c8c8f5084924111cdd1bb4450cfde486181ebfc2be8ddb8df7896f2bf5cde7987aa99d357414ae8c4efafc0ecf17e77c60d01fbc83bc2d723aa3f7e48fe9074499e65dc98f578361654bf8e941c242a03116fd08564d1e887939ccc5d9dd910665e2d2d7690c579567e0f4ed61f9052d5e838b648c68b0c7513d30ed09ed27c86a5dfd4c1feb7935be9d9906798b842e13d4f64543cd6a16ef43336d045ad4f2ae58bfc13e6a3ea24ec00482629ed431a2333bb0a1f9743087aebe051f1d1854bd15ba67359dd2d4b606e09b412eba4198c9ce2bfcbedb5e5d36ebd3306acd57aacbdc76cf5cefaa3072aa92ade05351a96249d84f89269214368314e85c69d54312a341cea3fcc79e3c5559507b620bccca1c46f2ce4c968749c4e182e86644feb3353dcd2ca97fc5953a1dd9e5fa4aee74428d61bcbbbfc14acc6c0c863dd934e4d92725763ba330a30596d8ca1527ae33aaf2265f9d639c0e704d6b398b5e95dbb6ca5f5b2fa20d747ef3d6b814b134014204b88659ae5a286d89e405a1bf3effc1452b74277e1f9f8e94fff082ce875937592ff8129ec6fd9f715294a4e308af94f3630577dcb8fa4369f4017ae50a303088c7c2e5e8bee9520e002e921824d7059e174f66da75acef3a18c827e5fe40e684f85c04a69fd490515ca04a9e14d9610f064f3e710461bca7447f7aadc04bc8afff3e6838a2c3549d1fa8299ddde7bbd4a4fffae2a48eea7365e35248717c1f0f52cf55a31df46f516bde99c70ce29266a3127e5f43cf96237da37de6c5e104014af018408cfe32f01716072f59f58b6412dbf467bb832484ef79665235a360a5488aa440fc637c22f220a2991d5e021f6e3bf2d0401488c84a72e83cc4321840077f96a327f823cd3f58da007a10cd233ac2082ec62ca6e968ebe26db4c953c82b1d2438ef8b5ae920f8bba02a03bc8c59a554b8a5d5ad950936807675489d60a40c97c7ef88eb59f1d1163fb6d96a9e73cda291dd8db45f16010906b2e3ecd80845eec9aa74bd912c9e5b38430808f832b857aa325c2898b66b2eb3060ae726226392cf60039277dd64a2d01df3605d8839c19a70ea668ecedd37222f84ddcebead0e9e5bc49ccb07898af2496de2e8504e8c6e81eee991684428215ac276e73178a3d1e130df28aac365ab8f27be76407afd7fb1be675aed80506423739b85301ea42d47fc13c55bb34b741a315d7661fe081269698f7f783e1a81bdec2c7bf80e4b8ee2548c6bb9cd186b30dc84d03c762556c4be9c7f8dc93264bcaffa8c807877fb5c7b1bfa00bf3fbde1e0b456424e3db40389c18f28934d552f4c71ae02cca764dbc0d8349e63e7dbb4e85d3633c04405067681c3b9e36a0939068d7f6ea5a8c0a81b2aa4ce67cca1be48928a7f76d8bbaae11850e8780b5b3f615f6f9baaf943815076d18158caf673205b6c99b28883952185748a88430c4a4da852839f15f92500399c2e1aefc56bc2cde684e05b455aab5e6aa381e289e5f30cf6cc6cbc112dee55723dbfa2c61a8d3c3357c84a8f0e1e92626de7108fcf1ef0b84363ffd18b4b6a14f905a3120efd39a9d12fa63c6d70cf92de97684eb3303d7096843ffca1676354451301825112e40cfe606df3842010186ba427d51b1bc78844f58a67b6b7cc553cfe29e8e9e8085a7177a7a69676be9eee528c1ed19003629ee63430d3ecdfc0dcb302ef391a6392b8fedeac58f289ef039b3e38701fd24cb9cae993f5340ad2693bf9364380a67683193353b6b14d3bdadd722c7278647eca8174", "0", "0", .None}, + {.Is_Square, "77d880ee9018bbedc73e8e51016c1f29aa10dbef2228c6f2e5626f547074639705adaf44a111d423104947d4b7788eade32a899b01abcc5a9be57db11cca02857feed737f378ea9a259e464cbe1c5ae0fab488016f95133d4caf21851bd9e3a9fd544e4287438ed22497a8bb5dcd118bbf745205a3fd01249903328b030e38b6ef78b34d87a948094a2fa1a689c77b838793340cd88c1b70a7aff33ff34f73c91e7478978fa8bf1f4ba6482ffc4ab0b9ed8edc5dc90124e84b644dcb568f27e599e04f637cd107815bc99485d83dc5c91c582bf408f3d4b93cdb17d941e7ca73f3440ce5c0d535c1413e1d3d955f24fbdf3d6df86ea07a35b7ba9d47402e09b69d8d54e9fe04758aae1fa3ec6e31c608f45fcdec97f7293a6409fcbaea452eeffda5a486d2d1bf9df01cccf4ccef60a8530dfda75e96ea2c57bc0cd3ee23dd3575ef45afb5e62e8a5d77fff6ae0ecf735980896702384bec6bea53fd5b61399d9151692f1a15dbd02f9bd09bf6ecfb409232bded0049d90755f3c21401d5487e0d5ce1b954e002158e9ba3393fd6b2075f940ab7edffe6dcd35f3db6887b695b332a4999470dacbb6470b5904b60d765433a570ec885cc252add9a002a4f948a83b6681ad7fd0a96150f6d40e139802aa22425fefadb4be8bf2b5ae7f909cf1c4ef0cf4fe6bc1f3afb7944462987cef8ee4387f6f1009705f9a8856229ffa0f0a73ed41929c74f72077661a15a382a6e81ef3bd273e1ec0f284ff5f21207bec4a5ac5be7e65c01b95301fb3ccaf60e7231833c92460b9962ef9f2501a814136ed80d5a8c82c96e464aafc4480b3e66f808cf44babdf4b0e0ab37ccac1192fa2dfb5f677ab9b41d00d905214492c1cdc637e249305e503db46c0d1fd009400c8d6bf92e74c3900c2f8d1e11e94966b7785fb9be24219d8bc4bfa517f29b68cbb8e002b867b12a547687fb4ebaddc203a1ad5f464f5cb63586e5d23071b31ce04db79de1e1651f1350f3badb806645a0da1b1627707a159fb3e2986ba4a7648e74f25367f6af9e483e6537441eacec61edd29581937577a4dbfb2d73e4fd6cd1fca396f34403b0d82c66383fcbee120eb1f976546d8718756eb4db055b66584bfcc6809d78fa6d0c3f01063082b4224e400ebbb59ed3b56f787104a15a96146ad925427feddefab5ba545d61aee4818e14cac93a9ba90a570d1d2972b2468dac2418266125182541717fee812223bcb4bc9924bc2045770b44c7c05358048f54ffe4be0a3abc992db87f1e1409ddbd2de50c3a484113a03dabc3472c9442ab26def690ba0044b38710eef5bc2a740a8ac2eb35d4bf27f64076a6429f0195be8f00b9c59d07dbb67a1d753ff5e1ae01708ad8ac23f522d73be0e9e7e5f85b620aaa9ca0fc02e1c5c52555fe988939ab082f27fc842ac828b9f5b5c32b7940b2615edf2fa176035834517b666d30ffd714d2ddaf10d5e051c63905dada812764f46e2b8ad975e43f861b45022b758a6bac595fe9210d54898b1ac9af1c6a762b68bbfbfe62e84ed3b86a870fc13ea53fd246e6b321c3626246c0e014e3b5aca5877948f2efb006fee124322112c7666c2f70ff60381d42b5ae152d582fa735c60d9f90ce1ebabe5dd46a90a6aca003f07704089ac4f12816117ceb833ccd3ac3664398d2991d2344ea185f0a5468a75e6fb4cce310c7fd74bd37588af7c261e1d6425e42a9116e95a6279d21ffece380de27790f0c64f52dd7e5c44c4a3958a2d622dd3b72f8340c456eaf95f8a9f132c7c3bece6253f3325ea48a5dd102c36a5bcbdde217919e43a0b478422fe49875a594b8e8d6d76cb7392ff81c90b7bd5bf6d9531f4016ee1de70f44103a28f0fd420f27bd761f754b67c0a5a7bb4b73637d3384b041bffff2665586f03f9933c2c81c0a688267e888f8724e148ed2d2191696ceb8b735b6342947d8767f90b5f446b159115bc4f06892f6849586a2c10b3bbe0b465de9bde037ab19af8cc0d0468b5903f8bcb86354bf1744ef66fcf6f4227fa11fd8b8a70e94e095f8221d1b86465de0ecd20fd1de092b792cc557f52bc29cc853b17a122af2865abb93c17b5ba9e7182d62adc14136026cb383e0", "0", "0", .None}, + {.Div, "-41ac471edfa03c8aefcff0aeb2e567d01eae431433127cb410d82e29c9429b5a63a87bb062fa23803e755f3fab331cee08162fa78a191c0b66c14bf15ecc4ff7572fc56998b89ab5164d9125ef62ed4e24ced5e2eac6807dd2581e09e1b41fbb02bb7353bdce52b0ae5e686418b67291d7e31f37802b9402f2b41931b6cd797abb54ef7bdf3f2bc383de499962102dbd76633b6cc99dd47f161a63f38d87679076d027276f0817b6d9187d5ee76a973e22b69211a58319779ce847b56c97e43613c1b862ed8228304d04c76318a9fe3713ebd07594da11b8fee1de6b92bde2a987a6bdf089ce577914dc2ac15055a856d2913076dc9900114aa63fbebe0e57b1bc6c156c075bc12ca8055cc6c9ab3144f74d984a732d97a73633ef5c01ebf6cbdee3a9eab1d3d6389b0c39e4ac13b061273f1606927c5db080fe48e86352e0f99d9b4b2caf60262e6c5490356f24a64451fa07f7018e7b56b4a63cfa4ff8da10ac4769a9059b29d127b81cd56dfa54335eaafe1d64ae2b262cb658f2b02037d9d489bd0a37fabfcb1af3d766641b046301578bf2c983c6ed2fb1c6f16cbae8b0391a2e5a2151b0530afa9407752eaa216f61df6d432e8c91518689a099f96e1345704256676aca34b033facf0e610d442408836bb706f16f076555fae2946f7de183b23ebec44f7360b50196f5f2957699768078489e4926d9fbc8d5a9d9e065d1ee5e197ccfe75f496024fac3bfe581a5c3053775ac6724b84775958d20272fa4ceafec7ef44e6f7f4ef6dac2034b72e5af1b2a3bf39f742e45788c86b285b64f353b2f5f30a0802c503da97525bd2e25e84e8d30487e78e519386ff5bb9036a45331570eef6a7e63dd942bfff418b45ac09bcf14bee94842e047cb8b9cc53894acf8c86932cc0d274c9bdb7b80434be5274ea8a5997e390c1064cf30e936c2604b989a5b39734768728aa5adb4414f8ac66b23dccb598a1e3f042465bf5ea5af72388e006786a7cfea8c0070a51243f9762c0264f4a1f419ffbdac3a862292445a51bab0a2b9fbf609065a440b5d98fa000d96782430ad9edbac7f32c71a5a02213f9ed5a49e481657c152a79e2b2e8070ee9ebcea89ee48ebc662956be0b5aa50a05ff545fb9029bf48be570d7e4155b247fd065a01c0ba0d6eb778531b761c62ad73f263f5b94eb3833a2d8384f219e2de2a25dbcdefbccb0c3c2f06d9ec4d437a0f1d89223b6d576e9e99dcd6db6f43c49019a60be67e219c7a7ef8a293f5c93e9cd0ede7d4a167d744f3db793a1b15fdfbfb1a5e31885a874d32752f09cce350e2341cea6ec2333ac2f1253b2a19e8fb5a0d2f9d2358a794f637b10954a4a43cb2e455684b61f67002fac2dd096ba08a783462d66dc27cd653ea3931feffc8d6cc86a51d638bf1b26a3bb57e817c61bc59d17702889dacbee938deb93c7fa11e174b130c74a0c17d2191bff2a0fb52e85726eac110f153b78ab9a2de60a09b49d52c569e3ca390b76422c20bd4eacd2bc3b329c76c802c1fa2506ac95a2d134df8277518aee050b8181f5613fe27cef83e76217dc7e8535e15c98cfd1d69d1378c60ac7504a4e7328677286a4e696d30515dc486c69bc65fe027006fb1195844fbb973df9cf77a30f941cd4a8171b4c6856f007071e450829c1f904b332e7f0b4a1832cde8814fbf216c4701c2a61d0eb6181346f8f287c23eb19a67625c1b0b1f7b65e78f854aa227b3e5edb44953a18a1a5843f259b8223ce59a99f77276a450ef72668fd8cb3e4d5c9968e24dbf0f516cf36a934506ad1718cab4f394009f7a44ce37c47f5d3f6d7589004241e2e4c0a70e1fb57d9b678554110f0c40212245e9014c6217b964732320d02a876cfa401d6c894b16a4aa1f70e0d729d3b9e7174174aefdb4e05a3feee7c29b73382a9f4d4ef3c1f8cd4b9e13f956800d47a7e5d80d298e97aa8ff57cd11f015b9b3b5a30196fbb4fc1d5c4586707e4f776284699809a2b85131631111703ad7370e3dcec2f7a38baec3b9559af9461cb46cbeec36c476ba059c67d982bcc6bbbbd069c8b2767702172bc2d54e21d7c7ab32c69139899ee5afb49ec5d607c2c2f5d19ed1988d3adceb0538d", "-3d595f2713a035f52203948eb747cb8de2817b4c9ee37c6ecb5b834ebc98b22c93ade181ae8ed763d02d280dab60ceec778fb7c9345bac287767770bf1f23407ccda113c4a85d5d2681cd463c50a4c8577b53a7fecb02b181af6b394aa7e5e323d429af145f976c6a86165d43b6e205a502e616012a52ba6a52d7aaf98537245a9ff313f3bf48083e2fca294e628802ccf620d5ba30fd621acb67bc23eb4c96cdfb9e2500a24a75146fb60333eb2252db2f9d3106846e8eaf611492a9989a409a44da00d9022e6e71ad14d4426af1c5db5d86cc0481df9f44d85e74f385c76045534b2917a19b788cefc8867bc0e6326cb913b23f85e8027550fa754261c80682060d9f91d822bde82387db2e29ccd7095ef90962fff6342eb59c5db43228d93cfdfd6b97cbbf5b54792e805ad9a78781e5d830d0e2150689fd73c14e5ba7b991d979bce343a2b86f6e9a129df1718de10977ad6c9639e1dcce2b60346fa8f81c260e3b0b8d79f39983f5a97a7a00a55aec1f53567ac669a07bf9ba100e1b0aa60213087efd544896fd89916b797bdc4f95e0f09fa35682830c1eff676316174e752b62e6852c5a25d69d227b81bdd3bceb700f2acbb410272e011f59165ad95bcf977ffd10424d1e3253e0ea48592929e2c19d318454b803176bfeb938b8f271bcc520e62a4eaeb1573444c97c24f655b17b861c25fb7a4a60d13269b59518a8906fbf97ff4be372934c87e6f4790721a479def5dbaf805b13f59ac539a26a8d00e763eb38b24b2d496f165f552bb09e9497e73161c5d21d9cb73e1d80918153127e7ba9749d74f99ae7f85cbe578ac3182a6770ad0c88e3a88f3d8902e721d050df075410711cf0848f94970356ba06aaa45c383c340946c8306c1aa217880e0fbcbe143c3bc23550d57ab45e9d7239803b0bc907eb6587d0b1c26b24cd53c3b395922e2f01a14ca7bfa0451cfa0f582368f3be1e97377fbd797c102947b70f1e8e72043d0f5429fad7dda3f56b9a83932e937c7d9d62b66bbb52b049e975332fad649686a633de6073ed77584ec0cc0ea613397bf228f829fa962c1dac2c57965f0e825ccc7643b3c38042a7c6e6a3b4255802492eba3bd147a08dcf1ccceb4c6689b35b18f8c5bae6163872e2d503a7d23abdb0cbca69a7ad76deda48c591d2d3b7a6fe354054faf1856e8a19fbbd67c7f6bc9d8e8edc86308f37c042d9d9a82b997f6cf1096fdf396a1cb507bf3509c8f19e6bd23725c5d312be2bbd72bb8126820", "1120af12234c5dc2e2d5b0162ddfb2a8cf54897f607cca439e24419aaeea6d52425d0f8dc5e3058894a4dc26e44b8b1966f4b1307c9f94d8caebf5c84bcf269496fcd071eb3cc798d17a2427fba8fc99ea87395b6a26876a1a5c08dd494fed66d2a1ce47101850adc6d6c95765098572f5e38919d9623dbd82a8d61e071950bd526c34f3529efcbdeb643c61b430ebd4cb4f96fc6a1a926bacf92d2efdfa7e8a7c09fbbd986ea0b185f6ccf3add4f442788c42944410b0a72e47075c937bd8087009542c85acdb35f7b04547c3cdc9188ca6598e1a114017e3ba02257f224a822e1628380a76e2054fbf44a2633550a6999b9b3bfc4a92500d133357cc9ebbd08d634935c2d1906628c0ebd7ae51e371b514d57a39d48614f2d646019b8f98212e8b0e528863d6f6d32d0aca9b45add9a9393c16297af6cf9af851f18c01018c1aaba2450113a59597fdce85343d91f36cef7ed7ea1912d152cdbf540a055d2356c4e5bae1b6e3c1a3191fed09233836dbbd413dfdbcaacf4ce354ef882d05213084dd0caab7dd6a718e0df8fde0237661af3e7b227686e239cf54195da484147ddb2670ac52dd90ca537ef5f43a2354e477e74949ab37088142d972d27f47a179f83e8e37cbaec41a2ff0c379e79af13c8aa4f82f6a885e519e1153b58e6e8180edb586b2ee3cf1e5ac4bcb8d8f74438a463224b58df67e095f035149a3c06dc3f169cbcd2a79a4854028265899edcc8027cdeab816ce19faa0b5dcf4a449aa70170c7245f68bebdd16ef88b41b92567e1101a3ce6d00b97348c07277c31dc276bd54ad7ca211fd26540650bfe03f10626e398c8cce9e1fa", .None}, + {.Div, "-d4dd79f906a73fa6687322587d535eb369670fcc83d544bfd2fc5f42e02ca7e31612ab4be3a6c96892e4503e1545deca21d2beb0ca1056b6659d2e2c68d0c49cce61825b8a1ed3c9c176ecf28474706c8725e37460c5e5dd30a13eb413b32233725831f2a6571935879749e74bd2a1eb378c4114a979ade684f80b70d31aa586452d05f71246f121e38da0537bb27f8e82e4dd16f87ae9548915bb40b37080aa53ecf229ed8e6379764e0153aa3bc5dbb49a071b924903383de0b634a3473a948cae54a3052c5100ce82faac7967e2c1e8e6e5700ea49011f8d79672e0d08bce4d79c2bcc5faf11d4d779b18f0b194226774f253c0994923bcc1128f715150edb0c17ea07ad0b34afdae45f78551bad1d9c575f6995542763896be1a6f563373682169840539f9045bf4d42f9c563c0cca02328e8e4860e7bdd4ef74c066de24a2194552d9d0ebac0f9275b74d3313d57dab2d4a0366e1a4db3f7de02e9b0a954cb843ec360be71b443a1aa8b445ffa25956afd9e0ae3a98d194539d3a2d8ab8d41aaeff6c9ccc93b26e3a3136d834c0403823cd8dfdb34714a0cc0506c6f9776ad1a143c890cc7c02da77667d3cb96dc2f05e13cbee98ae84e046a0e1c6833ad611af70d55a396f8e91e3e1cbdcb4c8b0bcb188bfa5843fc27fe5a74b34b48f0d1903ebbafcea1529f2e66162caae7dce0acefefe6cc0668d191e96c742be635e31e16d53154042fba8431036afe26010dbaaf176db0d0c5567f5f586cc4da5184ab7c9206e1e4ef21a29e6da9d852d6a407ce6bea17398453e33642df09461b62d07b137324d937b9938a0dba5e89cd1b553c9b32fc4b7dd9765856bad5ae62407a3e7ab88d9966470e90bcbc8cd71ff5a6c3a476ade33195f57d851ddbd5701486e8ae27f3a45bc54261997af12e488ead29a7944064064847fe4eef36bbc8de7ed63ad50776bf51df95a25e0f97f3c5ca2940d772781a1829ae0128f9a177f0ecb9a1fe806aef3a59da3e214fb5d5ed7d9eb10d6b4e359ac563bc647ae1a868b965a42a6c668f33636c133220db868caac09644fbb4ce2f023a091480e6598b24bcc8f23052ac7e8dda699706ee401ebc66b49a6fbb6d03a2b7c6ca86352a3f4600c80c7c1368b8206526f442dc3f70937083c1cc8e440811794cba3122dcf541b7dc800e5408b5f7ba62ca187df43189cec8a8fdcb844c5dff269e791c597879c4db94e79721dcb93c502a2c69c92f5a2117b51ece80bec58b1c86f3833b22efd0f8aa463d0151a5ffab7ee17c56307782c1b970495869402ec3d7fe1452b5e90a897628a56bf44c920f5ab948ae72df0c35bb57b6f0aea09aea6b04e1f017990c0a80a50413371517639e739209371bec2a6e84ed391365b243eb050addcf568a37b73adb0f5098a1f5187b5724237599ab6195a8975b844ac91967f746a5d32279dae27d809ae45f67202459ffe2ea19e171188235b444775c5f262c0664362d761f1199587a041b8d21b967d39bd3d2c63a5e8edce5e5cf5d3c69b46a4f5d41ab0cb42a28d0be5d2424d9c9fa47561e843c89ccd11bbd59cda6fda58a930c5d7bed461af797e00f522710f987f5c3df5521dfbc20da001d1bd5f232704847fb8ae2997f963fb93e940fc8f4ec44d2347a877983bd8e25e3ddbcdabea608c9f02b81429bfec43a4b8798e96419e3f1e548d2335ee0fa10d5030c6498963260f9527d6a9bb369f00b78d85e01ce8cb0336f00ea6556f7612bb7541967b67acfb2fb3c931a5358049cb169dc8231f859bf2d45b6011be51ad4b23f4997f09c04f0f32bc0f9e9b35ac6e9da668675e24cbd128b66f4d9bd469ec862d76dc1cd48a39a3857dd347057b5013f4d49db30a57fb0b5f96f91ab05dd08979978d58d307fb27ce338ba7a11e50125b826c704568bd05265a7b64b0586688029514e146885be1d7ec7d7ef4f6e036e4cd2a0bd5524bc11d666be6595cd23c7ece06867c76b3f0f553560af432fdeabf692d1b12e25fac99cba8cfe96286750b37e64f938c82f9f78a0b4eea8294341b5e77bb944c38225beb1329c57eff8609628e9e3b9fb606973c35045a943514e72850bcb2357844e231e4f3fb00f6", "d55c7f8d695f17ea6a9cc95d062fc49830d3e6f0599501d1aed3ba5392d912af728e6be4e5faeb56f4892bd782fc1a676d3fa007cc2a70c64e84984a48c3ace03d4e8c2b3ce6986c75a9dfc1f26c3074fc6dbc5919f7526d30f7b524451ec07d25283cc4fc21833a9c6c5952b20f88207e2230dbe66738bff16bc843cd1bac6a4130a62c2037f3ccdf89369b2ed8cbf865728397aa049aef04c684793126fa932232c3fcbb3b21eb79c66b813231de3d27a63211b024ddc35ffbe4d3fc2a75c5c6fc0c41a83b621232bcb63efa1e466f9d1009be94769109612a88db24dfe752f9d3fc3456a392714bbc49edb9825de25519fd226bd93c020e30a311ceff703a77b46b9ff1b1d006e984b53d6d39866be4c08a0e3512620d64e05e25f7ba69dc60b98ccf88139ceff4c342d09d5ac608a718ec19521f5c658f741ece7b9cd9e94514d35695606217bb96459c4d2112a27431c787a93c323117500a4b9607c71de0be6b2c7e67dfdb49e859c03e399db7dea4c24dc152d2ad8d6339241af11ad634bfc7702efdc0cc13d0f3d5c532659f90d2db235cdb0fa119e46cb8f2765f4c0ac4dac980fd9c6afd31e2b315bf220c0fd1ef9cdc90a7fedc7bbe0cf50e70d5a83d665b96c7395db6ebc1499ea2cdf4465ee0ce7f43da38ffd6e5e733ba888b0827647d03ed9020d3bd3c24ee55f4434804d09361922736ca561e528fb2fd4e0ba0e38b73ed427658d0a50675829682eef76ab35d0f97da08d2a31bf88a47a8f3987a0e75f8e4103b4a2083269a127f4fbfec71a71b6ba361075c0c697b09db1035d1f68f0552933430cec89a811d5c9e6a7e2420a599cec77e62814ba993d0f2b67da06c6fbdaeeb6d95dacaaa3d5f92c9b3073abd772231ae7e3275c9fda673785c3575662d5372bf87a822efb5157855ef94d877914b56644155380a4cda1bbe7eaba67c4e547cfbf976e36f14304a1dcf390d1b69e2b8c9659612f6e4b157390b908967ae537e71a49fb632d107769a205b67dbc974ab1d5a0bb91c9dbe72338c3f763d6dd42b97ba7f1911e75bd7ab4fb338ad47525c7f298eb2a462ee15f8c8fa7c1423019b73cae4025e337b7ce52e89fc0c67ca831cbf502c0354c44f157067611de5fafc917663d768541707bd09252b852564691aec59efd0cfa211aa32343b0da9bcee12f3ea4cea4d8a777c44a6e79a5cbe25546f09fd844317d9eb9efe9e79ff16cd36bc12ded1160eca7d947370fb26e5ef75a1d67eec459e12676aff", "-ff679805e913c8b6c4dba5fc535d4647e1f006362e4ddbe86aa7bae9cfd81f0094da9f164c24aa1838f4bc496979992e2115c2afbf9c72514ca919bb4e6deffb88d99146817f2d7002a295795667e593d96a23dd2f6a3706e53dd4bd7fefe0f120566af4e1c20a2fd8a23a3d0b4540f0b6375738c784b67a07a3f607077dae64fa9d9ccb344364d0c834129cf115da33aef502ed67691f55d92716ddddc4dee6de976f54ef0ecce7db066f275032aa0db838f10a0dd8dfcacafba1302af852633d9b06c177accd5a852f79f36e0deb1e3927c8a69d6ba625ce689f9fc5bdd0f170de9d4d842b3bf293fd57ee61a736107fbb84fd5c515303d87ae48c0372ee31d49a9ea458674aff785297b486ac369145a4dc8b7f6b1ef9d0b66887799f7c32d30561a5adb6144f132cb1b180b7e2e0a2adaaaf2715ebc83c58b24bab921166d2af19fd9203261f2d4d51168a7af4aae583a38423898245306fb07c15fec2df2eafd3cc544d16b786f3a3cbc7b25b67b1c286e4ceca04b46ffc9e54f98cb184542f7cb65da987dae3576810786f379e4778693442a7cb01afe1a2a2ec2167f844724d4809ad77a212b8f3291c8d7d3575ba4e4f5a311488880e9dcd83871c46b310975b3398f266c5af6a3033cd600a0756f0c3dfc4b996e9aba8a7e501ba7e850048c58ff3596bed3ff3ce140449bf073a0ce4fb36c7ce7b19257f06b8592ca6e3c88d7645e463394357ff00f0ad021b3a5e40a54ebfec500fbee66e91f46bbef3d9a004e12641441960d2f794f0df7bedac87e22d42222a97275530f201772f2f39356c6f4142c8d4639b2f6884f5b7ac7a685de37f3b", .None}, + {.Div, "c5c0262b8f002df809f45e03ceaf7319be3a7031b0ea8228dc25f0e83f7d963a4e383d58931b85ee93253fe16c4c33c5fd637868143fd1c3658ec03735c0388ebbfbac687bb3cbee401c240a93ddcc29f3a523080d6eaeff7fd5d216cedebe794627a22ea63afd20e68d1be76ac7d2e9c4c330f4671b2b8da81358588c163b6654d18168fec5dd5e503fa103b3b771a9efbd0eae1087ac9c25a88f5565e5daaafe87e4fb9b1cb2ff0a188360f8f0e8b0651f56661f0fff3befad4cadf6299c0d8061fac4119ddd93446e45fa5bfe0c57266b3e2fc063a4cdadd777d2402f1172a6b7c30dddc5389a8d0d97d35ba6b9c1062867b9e5090fb4829e607b074bb6ca0a382ccbf271d04f3803bd101c640f146bbf5ae2e3274c38f2da3a8b59a76b9cfb22e3adf56f58e9b8fc2bebca80e064259fdfcd0fbe4ea41a7b439f11ec50a0538e0a8905a11f9cd6c2113e3267f7c6d3b22f56e48f41900300098ca791a14c557c47c039a4b91af37d7d30a98134910b1752f95d76b71e38aec1b814bcc62aaba8e13b4bc1afc6ada806e4589253b9d8e5a8a978d36cd236b4a0054181cfb62e9af9fb5f4faf168d165746e8b70dbc386bb4ebe9761c4936e28c7d071b2c1ead16bbb15ae8babf0b5f42dbd2ed49681e9c74c6874cfc3e6d2fee9cddea1bbaceff59ec763c238a12c9c27239a62504a56a932b3e6029107a5216b7e411bcae5f9ca68ae75211f2125b7d69f821462122c4e25d1f2f8694c22a75158d8d896141cf23aee3486cbd8c40924ce9e7a79a4ee807d145d63b79d9f5e994c44d8688f3501323b0c48354f2d6b02fdff671b679c7379eaa88f675db3d54be3dcec57aa8b865a8d57976552c0fe051746efd3c8a5cc6be959e6f7a45fa99308f7482a3243d88d223fc718016f27d96a341da141a5601893863aafc94dad91d09843c51977bf4ca4eab9ec6cece12bca78871c6b7885b96eb7bcd00b09dbd945a223dc6e733953d05567ce75d23015f1a419819e2c8472b97db3c1265b10af5cae47475af83fdb2e85ec0b18b073c9c82a5a2c88c226473cdd72d65af6bf837b89edf36193a0b0dcc599311c6c76cad0ddd9705735d544363ebeb3ec747a79880ca72990db0bbb874383a33832435848266eeac3a247514ebe8f4f8ec08ca88241a2da358563bd1834f6b083b0c08b51a39f048524d2cca0446c9e3bf414cb1290e03231450c8314093abbaae5543606580014ca94acbdc84a8786742f6a7fa445469702d6f67b2c5ab1ec44297af8492c1d6a774bccb823cd1cfdd04fb2c84c630b251dbe4633c2d473a6bd8ddfe950f0ea7e0e907d1bc1bbc9619d55c34779f368e583bd6728765450615ec42bc6c564b8928d929b0e1a094765629ad152bb3583c3befa4072e14730e571d0806fe807899522265ba30e4c8edc5d867260c1f8e624b24cd5878303c447376c6749a5921f5700830aeac16fd8d1318d1f2fd4777e0a2b2a87368e8e270f7d8cd03d554853d9ecd0d948dbbd119dd5f15953080f5401cf1421e8d9b2dbe05f8113879367af639daa47a4ec208ec4bd8a5bfc3ff6e6899c6ae24c1c506fc6a136d65edc2254a27474ba23c6b38627d6df73684ec5056b6269beb263120bf442b3c9ac649bf8f8acc1e4fd6ecf18fa96c48edab3770f92eb6df3374518a4947f4ee44a0a562ecb1ce34c11c1c3a4ae87263c13b0b298bfdaddb0751cacc108f6b35bf684f25600d809ae96291e55a7e128b2e890e15a6df0bb395a17912fb512330e9ee815d5d0b80f1d0292eb0676e1cb5b9ccfe87528c0bf43492a4495ba59b7a0a3542bd48ea57d24f761f9346f3de97a648c3bc3f7057eb61915e4bdc3820e890270c778f868291d1109669af7b56be55a16b30f14ec10df6dc1b061ac4d917e554316ab8705e1f3f5547b73d96a243070e0b33df02c3ed69a9ede2f648b1db56347d47dcf56cd415182ed8388f1d766f02399bbd00a0950fc5336801b3da9364d351c12e402e05e703855b93379bb49ef02ea0b244a85aba6267426fdcccbadd5653bf987e1159cf13c79a34e78f862838323fe4c16c7469fc6ede41f1e2da475128381bd8ae504c041510b734a47a86c0", "-f30dfbf826de4c335d3296e48dad8646414d51d6cab9f3a84b54f6df328179cf98ba50d36dd23b9bfc3204f4ecc17a25075f8f5f9bf23c55cb59471834ae4a6860c6326ba063bec0ca0c61dc36e2ff2b5f8396f987b62e6e7b3d8aac87aa1815db80dcdddaedd9b4d4fbbdd888f77c1b88cafd39a1c5efa8433a728947dc5848c7cd70ee1f7c1189818af1433f9f70219e057567ca305f70a146460f3b15be7bca34be5f6d145f249f8ba217cc11312bb95a34a2c96055ad90f5d8c3bb739be2ebbb4e054e42a305c00c8d8f605b39dbf93263f538eafa4626132ef9ea1fc01e260228a3c219ddce0748279b5d030fd06f8790ca09046900888c47287f9b18dd73c1d3c036fc887af2942893f7b341f65d2b8adeb6fdf076c0dfa154dd4e8c6c0b6b1ca5fa7c95d643a045e3f885149f57533b8a4e79a709cee7c02dc57b7e35ae931ea3a3fd10fd87782d83b2c7740cc228c98f79539269cb0543335bff78ee9d706455aa7a3db5cfb121d7ac4362725211dbd08f46f714d8a9ad221c978895067964b57e52ab212f67714d22175482054a32dce266b42ea7b30771e8bc702f4fe8380e0d87c44343af70a78027541a3c7baee71abf24ba2bfe1eabadaba32e18e3a541fae70726946408dc7b592032ff6d8007d65f471f5cb38b719048f6dbd4487faefa89c3b4418074b400f95f6d5ff5f0b512e5faf439de7d7e2558fc494095021a8203686b7847c1703ba48c88fa84016526e13bdedf7c9b86d022e589186b73b41445d1dd025a709e08dc01862675baa61ab6cf4b5b6a8d5251cd858096c2e046eca2ff8a362abeb53c4202dd7de8e6452deea3dcf63a08baf6344b4de6bab370acca778ddf1b87b0030fd49141c849c28a96f20ac5974bf234124a476b039364507d2477926d4d23b6130f1fb2d7206fed16b0f1255dff582745886c64c45219b9c3a3fb285c44ae47aeb6cdbcd0220de65f46e8997dfe0aea17ba5594636a0f1ee778f98904207c37ffa2101e0ff06c9c6c3d08bda2428091b791df645e97ef3a70193fbf6d8c8bbb6159dadd4ed045de6b0a436f240a1ff25363938d505334e1780f758abd5986d95c14bff2ca65f6b3a8459e80688601667e2a2842860fa564805dce4141063abe5b6cda01a39a7dde57c7f947ab221dcf37f756532f6fa65fe9b50df7605bc4f48c0a040483c58eed7dd843cc09e35b3b9862f7359a116f778b5025e32e5001ef5145605455c2914b0588c50cefc37b56bc8380f324c305", "-d04873583fdc3cd2691b7986a39202237a50492c143fb11fce0304b2b6952f1157a5ef7f149d6ce4ae0cd557226374626aa038e26676edb431c52a34739b99c22c54c813a18b29677ebb72d777a7e57ac688e8b72ac3ab88e5b85f515c4d0767b99099160ec6f11ce82ee3b3a85b3d00cbeab7d555e37126ea908b042f958c95e1a4661f9d53094d90b132060fa54c31ce361735e067a0f52a3ffd85f24cafc17092af090d332ae308da5d6bb257b6781a7d390ae393edbfa936ca8080a7111f0c09240ff596958953a1137efcd232e098e625b6ed42ae78f500a65735670e0ad4d33e3cf7f2e01bd1a573b895c03957b51e18e28ef18db682e26c188d64c5cb3e3fbae72729f03444e3e1cfe1837fb4ac135d73ce70f04f915a0cd950a5cc6da3ce296bd1eb4aa897352fa792d28f6e8a50c9a21c25419401b5dbaad3fe90b055f710c130d6162264a15dc8eb2a4584b76067debbeb78c7bcc58d0848bf508f1296adf4c28d613648b9eb2e8be7538eecf9dc7c4d1f996637c5cd732c8661a64b3b8706d2612913ea7baa88fc97ec19782959bcd3cb02cc2a6f1709348d87485918b5e746aa42d46e952575c1410a7b7894b7ae29eda61a3e38a4e79ec310f64502533e87a38a850cd9af5f1a0d35d9f46d25ff5c192d2450f49566a91445e754742a8115dde641f326c2e9c24dd5fd7347b86bae3efc83bd27f6eae3236a0f1d36833814c687736ccad4abf909c36a2688b2742bd8993b26087a1eb1087037d7035febc899cbbf002f030bc63ea3caec8157b03b8826f4f8eb8b886cd9e7f80360cc116d9529846bbcaf2deba3db949ac024ad4b2e1d2f", .None}, + {.Div, "b6044dd806f645ce97fb8f1d75815179feee71021ef1663216e1d4b4c494a15d9417b7736bb44d1cd6616544ce72d14ea5bedef39cf76c23757e792019e9b500bd283fbd6fbbdf7bfef0691716d0eff9e806f97855d2c91e49be0e4d79b148d29d6c4baa413bbaaba9d57bbeb33be2fc99b7dcf34542dfa43fafff942b3405cbd8ef3d9c1600f08634437e16a2019f06ada6fd8bf8f7f48c91f6d7f25f19a3c990797cb96331ddd668e425fc469d90f6d622b86df0a61cd92cbae2a88c3e61bea02cefb5795779cc65aba028a5dac889a2bdc0ebeb7974bf6550607af44e388e9a250261cb667aba396c6c44a6c1d0f0e81d42b115dcc6a6f679a74fcd694bd8a6516c127d72c5324eb7098452e81f7d1a60053e7223c3495be94a7e970e2d8ba4fe44607b027705048bb3d0fb87e264055aa552a1e5d1a597ebf2fd17e733f0877afe575e6a190266455fbdc24b72258072c28e9bb79a4724c1b0e4ecc5430e5506d169aeb4c82c7eedd87a8da5d3b9a3be68ae0dd1e7cb37f2824daa884960be7ffade887637ca193f700eb62c8d53fe597ce9e6cf0d5a9e0c8dfffa4666a843f37f797ffadb4bdd81c635259752689c4b02b4273d64a73f06fcc8cea486b81b938c50ccd145b7cdb0b2d42d9e8f5cd70cd21680ae2b89bc972b4f17f8fe5b62f7a2c7a3d6759554dc24820d6b9c823376b812c902444c0d730f8e99d5e08377d0a67628d02a6b653ed17a40f68a5d510ade97798f078be82c237d9f462092e6de299f84364f031957508273abc25cb9786f2e8a0bff49dd2a0c8d1fffd04e6b12cd107bae2e66e19f3fe191f8a82b901e809ebe535f7fa6094f291d0ca2d5febdbdf1240c662c448c7a7cc75a8538717db9a129e2ec4f33ee1f31c1d0fc40e18802ec17a32113599690589604be635795c5c3f141ca6cba2880520b8c9d37c730d4b84f32cb5214cc20111c9f31b3cc92b93a47397596de4b1797928188f98afac7b325635c9ec60b70dc7955850e0ed0c5bf5e4138383de76092dff8575c1e2a210273feb4907d1ca668ac01a477fca9900f33bcf7efb420aec605628a05801e46594c04c89b733e40543646703ab9cdfe82746485eae18ead250dbdf5eb848e32f64770b1c029ae295b6d4431979427b3ea5c19172be2f83bf7a31b72b4753dd8e8b70f159f6757981f5b2c1cdf8a621bf94e6e96c352a92875f573d6ea1bb06df3a92cce576b059d1127f893904a79d7e41008f90ebe431f00c3717b0e041f8fa1d96e0f213c1bc7de563be2f46dfc607de6cf70262e535bd3b2c5a74ac46f52fc479cc540ce4af1464aba247c45183b0f0c1effcecc741a5b9166d70a59732e8d520785e89dd4bb087dac2d369f747c4b04d9171f227420100791ca676bdaaf63d2b4da610bcaf37023bc6cc33fd9bbccfbe6b57b9f57ac038bafb6401d721a9476042400e5be0084d0a0fd34110784063332f58f469a966d943267ba27c8a0fbada9f1bfa47ff60edf4dc446f5ec5f5598616b24224b51be1c2fe0a7a5356a14401d9895949911df4c0609a580829aafaea6250319267c0a75ac7642a386dc1f68c0c9ddc17627f9e3c2092cd0b0dc2dacd893fe0d005d841c5fde16b122984672a689d5a9b8da5ea726830d4c0befcdbe69469d9f9a6dae5296fc634585f0ec0723e2797e636073d3283ec5830ca29b2ad6cfff5d3405da5e2c4ce23affdbd1f1b8f32031437e07f2cd2ff093499de6a7c55313d06c7e3219983c7b2210b3403a9be4779f6dd06d8414d215c03a16df7c66493c3d0ed06d94dc9966e1751d72981de4702b6a06e426d3aa6146470f8ee6950773b57f0b9f9a603c3d5da5c913432f1dd4f8c057344e52aba9d0064f8bd84750a20ff195cbe44ae2fe935557807ec18e5bbe81986d985ba44bcd28ca90d38432411fe3927f5e45e500311cc8caba8fda655a9ae6ca53ed68d5664d8d25a74fa279289a0b3e8f55747653e2b7e65c1259b6b1c0aec4965fd5064d2ece7e600e13f819ed548f6fecd0f665d62d11601519d63aaab51ab7dab32511f002a43a5945f30a1f96f1b15c8fbe4841f2e01aef759f059a0b80d8870c54caa5a63c235939b14ea8e014", "-f3a68fe22a997dac7f50edb71b74287039f43a88b29d89e58c621052adb6010c6fc53aeb6783cfee25a40682d32f85de2f668629489d60788bf943be84d5e4da93d4eb93a838fa0394718c28fe9332e9ede41702a3c3086463f27431b91dd8136058906e36f9333ac0eca9332ab27c02a4217f18d5ab7a44a1f97b640ca1678b0e2db94362a3960feed55e5fc2529c533e82fc1d5235c7bd6cfcea343d5ad8496b130969cc49b5c0c353d6a567b4be538058a25b67e55bc098c79854d73952fdd8cd01658bb7bf6b99b042ad76fd38bce883dc83a3767340bec2fa71925014545d0b839f4a56c90f12d5ebf0cef8cdff41525a1af46250b5a0ee1ec6b6a2be13685225ad97b6470b8854073525be247374c3178115bd27717abbb745e6eb18e324f758cb399bcddfa9ba165954d901d52785c4054518a0edb9f6de5438dde20d088d0cdf4e6eb84c282613437ba856186827d0dcf0bbc981ae0b2d3c51b4ab03637fbe329b8722838667a5dde68979512404366a0662c4e2fcdcbab99f6a2de8249fd050f1919f7037cafb23b9718cd409c40300ecf4ba4eb08a8f32a464b9bdd1cada879b26d91efb2e0dbedf4f9cd9d94c57fb31e493e48b5544aeb897c8d1591ae919c695294387c840552e940f28e4c62cca7152d635d01f6dc0ccfaaeada4517fb9c0d477de8993177f42274adf5dd640a41be1efaac97387657e57e2b71770d9233413502afff734a5aef6169ef6b097f61e22db6bbccd193e2a0199e6487fbd381348688564dc4d1eab80c533aa2ce8aa2def9ad1e428c7dd152fe315ef856e36bc98b0c2532a2c35f1f81b3f150450f7699304cfa0d66730c2161fc2a61a27def481cfa4fb5953bbb8e47af0e7002b64fad85c0ccc2374c029cd6bf0e2206b8f46a25e6e2eb79efade04c524b6894885d21eeea88a27d7a7485c8c1e24a0e0fd5b1caac65c814e2934d3bfcb0263ece2a749fb3574c49712bc255fce02f62b9ab73f885617b4edf16a7775b65e83b17895247e58d2b940348a50d6222e2ae6bf5a6409f938301c128e109afcae13f3a41d9b20ac6146fb604b6621ae9f72b1ca9c37e5c5484be34da6f57dd11180b5c12b9c8c2c30c419faae94ffa24f137f4de11503fd4dd893e69c1626cb73739fb40581bc84b4b960f86142b6f6204e3592920dd39cbedbb6e1c3a68e73e59c466f1da12d19cfbe98ea76944d8f4f200d4ba91520a55f12c26dee9a9a9b1949098b18c1da833663759ec5c4eff0640af9d0", "-bf3e06774a2f64694809f7b424dfd7908c242a8f67a8f56f0dcc753a8f2058cc1c23280b0d20a8feb77a173642337ddce5fdeb89dbebe3c668928879a8a9db954378c66ea0ee60b953b81e3d9ce7e39d1d456fc79279793597c28311b6ea9c2eac23bf6638e359bf648b5c9cbb3da6b4e9eceda69b61fe0123622e6eb2f7d5acf4c62610f89e23cc027e88305504e4eac850f568d7eb7d061b45900b495cd96b9b991abdc4beb80e9501923ac852e940622df1498fd3a50ba5bd20ed2bcc9c07c2d5d52805b82c3e0cf1d62c104a6eb4c125d44083caefa27e67e40ef4201fded5eaba25d67bac2342019baca3929be32842b3166930731625c99a9734245d6d37716108495ee658f22be6e2d1297c3933f1d2cdfea896d6f378ec462b64e65ec50db012791c6ed99a18c3b6cee47ce5020f51d1fb63e7854479dcdad184c7460083364e80b4fee5a110cb7e80a069fa5619e80d48db49b6623601a87bb7edb2bc013e2a6568feba52f3df1ead01291c880d98647de6e68c847df240fbfdf01de18302d8c94e40ae1f5e25857a1c5525edf5be2a1cb12c724bf9a75a9d9952cd8c6cc96ae799e6dcbbc6f46d3457ed1e4bb6b4cfba58d8b70a717e573309a4281b8a1b4ba81a575789620d62127f36cd1aa5f1c184c42d7811238a4d7b6a68efb50ade8f9d9d0eb0027e74558c3cfb6e00a0970567184ab62fb321a488abb7ecbfaa7c9cc8bd400ad58de591137b1aa269a9714ee69d396046119fc40e176c25532df0da5c53bd7cfd771af9190fb3ff28cf121086de537cb38d8e25511d7d1a1163c6e64550d04f06f0704956a3cccdeb2740017e457987", .None}, + {.Div, "60a12e7ad7c1d85778a9205c8c3089be9543befab23080f5e969ad52ee92a458145b1b3fc77addd8b1a47adcc9a77449fe526c4b9cc1ff24985d27e29918166b2fd2d4e1be54df04db6976db73d6562baa3c03b66c9a6ea49d79183683bd848b614b5c7277f875f60dda4d32b790b72cbc3080465242a86ea9bddc3412b10dd2c14d3855b547f50c4bfcedb1df3431d6ed88470a0e75ca6306ffcf30220077135c99c8e1c2d8de2455f55d122a1448e0eb771da7b65307087f285b468f492523cdb00e26a1b130dc016c54710b80d6420f4075c377fc4b841ca50f726ab08f1115859db774b8de99050ecf63aab96d4574a761d4df0de1637decf026aec34702e2fe99728baca4f0c77a2fe14da7fd299161d4963d8d61693dc9cee0d082351b02c17dfe8879e3b03f2db658ff1f68a7bb473df452f87ba34292845f86154989292ba4e92d49288a68e580d0eee41b5de46aab1efa0f2ceb5ff2d4a7904bc88714f0c06bafdb6f3ebfbcc803c94a3fe1062a69da181d590c638aab88a3154e18c450d330eba8376c7e67ebbe649fce6f1118d78e0b09641239a0c3c2412d633d8e10c1e1c7bd0df40027356a784bd4d553783f891d0abae67c2a664ad641af9196e61a45edd70c1b17512d1f05dce6079c98625f89c5496d71c2a6b0c2813a2f95cd14a777426160ee796239fb5af1da3d5c7ca743b3d43b288ec50644af04e6ccf03d7e7aa3b1923ea78a105f840fdc7eec128d7bb310285737bc77bdea46f8c9fee724548798895ad7d38d130d1f2ff71d897a6c0a665126ac513d503bb5e1f4d368cbd8e484b291d9f5c5e3435c62a15d841287178863586fbc38dcbc3bdeec74a0e1cac4b4a84bc73f3ef51c3b856bb7482aa04363725c7ad00d4d66ebb3ba6d79595ed5accac34d78e0a16e3e85ed757f4040365a6c8899d91e77db50f7dad1d8ea08b436ed4e36453c4eadc0e9189ece831955b7fd4e43553158eda929e7ed85a5c1157d9521f670df405ff3036c842bd18f661f2ea6dfe6fc55c8872d673244feaa00859bf059844754bc7730b4648cc55042c8fd4a01ae574beea44e3ddc2071c8413f12540e810fcfe4b9b2da7627e4a35c220e264e3132dacac5d1489534f2d1e79487b131f21f87000b54b1124d02d7480af52923e2c0e0c0b01cf59f85a83d913ff8457b2dcf29ebd8fabdc4764352346e9645dcfd6ec4188b56e160e6129eba27782283657b11588e549dcc9dadc9257e4f0f63ee1734a11fba5e275339dd339c8570d8ad8addcaf46cd1280d82bfa5d6f15e3c5083721cfd1dd19dcffd546317192c48d3512531fd9553fe8df7bf56df0288d7871aeeff3530683bf844d4713f7e2a8e348aeb639a488c65cac12e108e2928eab597bc9c18fdc789cdcedeca84ac9110d42b6a32902d3340cd416d2dde88e7caaf38edb24c1a3715d17feb6cd2ca46f416f12e62eac4e6bcd54b8210e1edf87529a516fa417377ba1d5a8505f6ed5c591f877aabb14426a6324a103db89f9f135fc0f777d6b439f8a272c7a43427bd609ad44579ab4e15d4af9049615ab07c6b754f481c77686bd2ab2b5caee370a561f76a5b7eb21a5c0ad8d182c7702059b469dd2bc2acf03aba6d06d865829f7b992cf4394ba84e6c04589c1e46fb4ffe2f249b1756e691d5894457a6af7e985ba604c2d2b60af48b16bce8da2e11f57c11ba4d356a5379ddf22c60fad860d5ac0835c62677955a0424bbe97f8b6c8e5c62b0ff4b27058d5b960e7cdb8f8a53ea8dcd09eb7ecb076b13721a55be807bf6066dec02ed011be780bf717beda17241c6a2223c8173335ca85c8ec3d0e5c0b65f10fed2464dd8af2c22beb256dc1160996c16e445b3a0fbc0cb8fc7c0680219bc753c85ad891686802383262d1546d4b5ee412aa41b42cd8ee486bea306d3ba15c13e9a654d34709413ea2fa8151be73efbe65147dc6e8288d50722014834f833b2327db4f08fe553e32d924922340f2ba4db509b99b8786efbc049ef1dd36c24acadd926ab15845f992f7cd878d66965694ed27c79f79eab2172032ec7b00c11dace85e654c88b56a90ce0007189c03732496a3dce448e0212a16c243f51942e281e", "1d6a33d87e58a4e68d6e4bda6aa8e9442523a3df5c5b2f5c817105c1aabe0be4b207c203078c569f096e73b42498527110884a8b7981a310e5147e3cd47b19555706bfd1f8342e0036d8cf9e032f94701be5a318f7dca32ddea350315c88e9fc63109e78fc9cd87e07573a1abac70c03bf177a820b18e553778dd6189d5595f756625754bdff90a912b2687596b22bcfe56f25a5ee4ed6d8ce4f320d1fc96ffa2cdb8ffdd1b73205a352ee91f79c00024a0eb6130045b63e9f5ad8506d41e67335657aef02780e8b3bede7eb27ab6ea69cdb1c294caf264bdf31bdae75f2ad4276b6c65d7a94ee65a4503b60c9b878329eeaf069bc2b25c308a1b84c0b612cf7ed35e52449523c6fe2d4188f2eb2fdec32f7c6dd029da9214a22a978b265b636ee429b71c3ffc50219d1e255e1756ff43fc3220bd9ea4f86f0c801fca5347446f594fa571ca9372a9906c1aa015ccf04d7d44dc021163c7b81cbfcfde20c90ccabb7739d672755f1ceecaf66e273baa676b4b6a9574fb55a5462d9bae64db0d292ecd4734965ab2e30dd3e41856cc35e53bcc0338233e1f7870f4a73365527f4d8f63515442e610c9a8787987663d9f7d2bc197f51dfaa4cc4624423a77922bd75a545652ca1cffd891847f69e23c2be441dc83c813821bad34332fa761198ba8ad2db1f48c28526e9aaa39865f1e5e79d2a883e8b859bdf7035bc24578dae413560af1d54f2446ff1f647cc70e6dd45f8da32f909e030dffceeb7738014900aaa863c445ae065c9000a50977231808c7a5efabf4d8fe9846b659a844c44ef6abc8421dff7778aa902d2ebb35623448aefbb607fbace3cf4d94d1c16aafd1b4fcc7bda38fa1cc2f31b85e60e626050d2ebc8f1f47694de24373e86b9484e183e0a24a91334831eb89076fb86779f96170e13562895af880cc978ef60bd5f45503f69e497e308701db475b8147961d395897dda668c11b766f303cb229f8bd851dc5db281e75f9d190b3ae841aeb365ae949b8f6d704cc44678a63c15ce9f11b03c02327b88a2c1ec7c047fed34e911b65f09b60d84e2263241ab047f3f2dd47f30d089a3db87cd63cc7f73cd9420a07e62c15b5adca90a6897ed9aaaff22ee4ab31800cfe55a564931d7e39e28fde17c21f4d77926c772b8bd132228f3f1e4e4d567a1f7c2b116a9c96b4e32bb3261022b4884f4ac61df3c44b673242a2e4ea47f48375d8a1053f77c2b0d35177f7dbb19be3e4bc33fb35471173ac971fa989395c369f9", "348f9d16b67820e0a1952304e2ffec2aa0c21a946e6469c075cbfed0d532caaac5fedd384b508889c9dfc9ecdc7a77082658aa60a6d7a2adabbe25cf8c5fccc4f849064a6ad124ed32903f25e47e0c05fbc6445bbe00be02c4256140caba96c435416b461869f61063d7b8e1fd1fbd668839ef97102e1639a1451212da9d8312ebef7ad33232198358e7e6a1bdf25910ad008fd790904c3c9ed9baa9a37ccd1e7f3f75cf90703db31efc04136eecdbdb7bb81ac8a918196b42752b8787c600065bb4027d3bac78575a6c51fae55245c6bf37cb840108f23d9a08b613a282c2104ba7ca7212bdb9bce8c5d290d3bd6d78819b532e52eb0e31a19bbcc1c8faea7e61edd7da85c42b7c143d1777197fa6cc5421ab937fcd17a821e24794e042e819f04ba38fe75779044528e0f63734d05eb7791b9a5f020d551f86035fa80fdd58c048f338b9476164e6a2e7ae07bfebcd8f91d575b45043aede7b88d35cf8fefd2ffeae4e11e9a98f1f11e17b3be8b283e8b755f2d2e095eec23321c840e7f1c636f5ae2f89817aeff3ae565cbc91f342229b5922b7293af38893016af780e88be88934d6a4b3e339551e475e68633c6375e9aa1156d09a1924e210dd485b3882e92fa70ef0336e19b516aa9204e46daf9a149a5396261332979f643a2ff0d45072a34ad6cf1eabf37cd92aebd00c3e22526cb42c668e3028b3168aa8b76f7d78088b65738d9a9f671750db413509ec6b514766eafbed67bf9349ec46fe2aedd6d674e9e12a2cb6c567331c2cd83cb469008439ce9e331fb7b65c8f34823b55346bd34db674cc3f9f1ede0222771dbdfd9a343ce14c914bfe9", .None}, + {.Div, "-40b6db39bc7912e4e4143a8353b87fc01f3e5a40fe9d5611273f39558ade95e24bdab915acab23b5539f5cfadfe3e747336844777c6ad5747eedbee306033132d7f18cf1a0afd512aeb923cca0c6368463684eeeaed780dfaac857578415ec025cd8e930b77a874d751d66a97edded822042fb94a9931d27a92f8eee7513a9431b0375a3bb707e4307629903adbce48ba9157e9177a43f6ba11927fc80b17137344c01a4d6b68b33ccd744e76cfe5900a416a44d1a24fa6e03222e538af4b8821ecd725a5742243773b47327586d6dbe559ce9a9ea4b44f958f6433f937d055c9f75db3a649841b2b391234dd80883d5edf941f31f088bba7f8aab09f410c3b673228b7872a5d90f41ac79d7a4c9dc7b8a2eea749d47de34a5c99f30d3ad7585fc6c40770b1360d0b91330e8a452e5fb8494968d0ce40440fa6665e27cb526b5fa63d1c29aaa7ef01be87aa9c67f66aaca0ccb09a01aa9d649e4a56b765c482b2a0622ce2b8092a5a56c636d9ea1a4ade3e2595c1e3784f66097e4b393bfa6cf02ac8999b868f1d94a8376c5cefbfe694e06da9a5c223703d6ebd36ff9c7405d012d794839facb8c9e62bf4340db1316214d458eb19bda2733d37850bcd4383c136dd7eada6b860e081563fc321e03bc5aab5a82bebfb7b5755849062c27663bdada76456952268e2982892506b6190543a8f42768f945c19feaff91753e31ee66cb70e2bdc485053bb9227023f517d00af04ad4dd0571d29bbe29d32551d6da396bd65119208ac32644b3b3ba30191872ccedde0e7cf49f1eaf98510ea16753c17072b7ddd82eabf81fdcb92b34c72001cee2217464cfa7d47dc4cec6b9aff7f7eecab57fd0b7cf6c3d43a4c89c54fdde1cdb288482fc272c5fb0d14b65e258f1597156e829093ec30c307858a6710592558a73d34f386cc6b1f0922ea30faf47f99e4d395621719437f14934af6ae3bc76d515895689397ce37be1e918376e5e2e49432d1cd16e60486230475af3a66c578a05c930971ea3a3f13b0fffbacdf1d2c97c52770ac6e2adbca6a615894e7072510e92c9faeff5ab7f1e4dc87b01cd93862fb069a4668e1023879956aa9abeb68d239b9023fac79aab76f8f7859e87a3dae452144e6249d99fd4d7acc676dcc3797a964abf3b067bb3c9ecfab57391331d7935611666b8845ddd0fd4d587079222fd210910497a255ca921a3558415ba1f7ff6071d6efa0432bb02473a36884732796f0d33561246f81c20eab7355a20e5b302ee509f8ecd6c1b1a7b7ac5d3f2f390e044a615ce4681fc035291fd745d97f7c5a2355dfbd77850ba61981d60ec2806336e586ae1db7fa39306af529167d5c793434715c208902cc6982c56cf1e394d979d7f6cfe0aa63686880358821906309b7d184318b4ef9812b927a2f763a2708fbf12f79bdb0c790b2d2d5e802728d66b8fd7ee249866ffce221ea9c5083e5a23df67d786cd317ce1957ae431ad285674b48546e671e301400d24589399ff0fe21da49c0be8264870da96742274a60c57d953c7ef3de06900bca5eec18f0fbddff4278e43b94b4e3b6169edec2cd6bc27cc860491fe214129ee99e8f3a216657a468ecbaa94ca0a14e8bf54c4c79c4062e6879e6c1d2f1985df29f36e933368483edd8c95bddf0664960b983c14923c0dcd292ae744456c4f30c3692f4eb28c631626f99f3aa3158cb5bd43dcee85d0d0914487ce6d4b1303a99dce6c2b703ccd1760c027e25a640fe2bb6849c9d2b7643cbc1a067d9f9936848ed54f8cd3d39f36eaa198d09ef4bd57272eff045124683751dbeef4331bf962cfd4c9169ff59cd55312b7cd54221b911208fa58a7171d150c40b6bb4faa73ef974b5bb859d2529090fcefd584696fa66aae2aadcde4909f05f0c3a9d55205dae103d42cd32ce9cdd8ee35024af99c3da13891fe27780fabb002cdf8974db0748e0dc82f600e639cdbcc1e33e7bb7a2bff375f0536e7ec007d139f1cb1c9697d10cf2b82e99502e6c9f8d337635e5653d2986cc4cc4247921957e688a1120cb0d7dd9776b6edaa0dc57e875223790d639757c64e7bf89f8892fcdedd99b4c7bcc956cab997c76867f8934caa7a48", "f004376605706643bc3e5f9b72224d7f9707e5dfb4ac7d4d63912924b9ea6761ea3d27e1dc28fa3bb89f3f67b7bcff3dc18214576334c890847bae9e43f83df1be74be6c779034725a8cc760a93d196ae0a3223de65857915bf6bb57f2c80f743b8750b3acc8c61cc9311ec267c831e85e589a149f1cc14461089f48044e110601d5d4e63fcfd85618f2174b42c63867ae923598f64aaa2e5a1ff2bffce065b90f83d235bdc35761a3d80f41ee4a942b622bff160dd4ba37c13a464d936f0c8c9cf2ebdfaa8d17dad898c8ef034be3cf20d325c1dba18e43f7220b711ef486b835d2ee7da9b38f76bca87f395b2891bfd6a28ac7a4570503f8a72598b17e15fdfee50552818ba80a1c599a2bb793b5b05e09274e75c5993d3b92c0578d88001110f4b6bcf58e58970a40cdf85b08dc353617a49a1670c49a0a354357d6ac586619f40d52206fa5951aaf59ca0dcd5efeed9ef7bba9d3230d8a1f5724bc108e49700e6e83f6c4406144150d31ce54e1c6033cef8775cf7d1720732a96a00426de3e528ce1a69f7462cc67fc64a84bc0ed7efe83a3665e31c29e4d9651068e8cf4af993061baa8267e25b3eb27e664d4d68de9fabeb3fc8030b9902624166398ce9903e21ea29cdaa99259dc252f7c94f2a717e32f11590318308b0106bed5d1563a5ebf4e3e858d56600b389568999c943cca5baa8f36b97a0e33d888737ba9e3c52f3d3c5c1f531107ec77811ef282737522452876cdfa64b1d00d69009143440ad5c07fcb1804d3eed26e38d3650126f568922ca8715049624c238b2a4fe729a3a13dc686bd3fc70ffb06240e5ba6260ddfa580e02ecfb662aec129ef18b9a8dd1f983ba04b6ed063750d3d97ff66e93799c07892f2a462320c4b89498da8f01d2b4fa65e7c6211bd6794b0acdd287ddee913f265c143f3ecbcc656df8266cb21b7e2457913ffe17448d5f700fc236b867075aa4270b9237e76eaa3dcd6f6a50ce5f53a41090f6eb00afd45a2ffa966df22679a642ec8b3204607b363cdd1d571d941a42bfa463e842c9d6556861fca46e915f047eb0f35f3f8f0d91227ff6205fb07015f5da23b75ef0b7f85cc54c8bf6bc3cace19b7e78ed4cce04f3377cf68e3b0f2c0a28cdfce86c00a3c860f5f17e979bec127349c74ac837c1691d88b49160dede6dcadee59e5b2e94459e59d155617780e6848cc2f984d8308504558a7196462a6447a3571aff055f1dbce6652658699f2c3adb712430c207b4e3929bdb59921", "-450619ce6a75b69b0089973a20f4a3b1f58612f29cd417e6fd4e8194f6a39fd7449e85e54afbd029a668dfa9922fd46f1c99b972c915e5d17fb247f6cd2ab5dfb2e0c131891de8a1881e145382ee58a539e7a6e6f24b54b66bb1e6bf84051670d737099492aab842c24b5051a0b9f877c080edb838871df90975b5390ef1d7ce2f6770b9761416e14c87b27d37240de0caf047bb4b027bcfa034b00e33f0fbe025308b05d6300bd260ecb63dcafb201b2c354b62d5b07a20d346a8ac68ca1bf7e06acdcc02331c855b9adb89ab17717cbf6426c4e42df695f93f0f6f87d000ce75afd6869a2e3c8b77cdc3e8fd5ebd68b580ddca88e39014792cc0434fb7e42e0fc105db1a05c04ecc86f108ecec9ce12dda4480fd400c49d01cb7383de363a0698a70f2728bceca3fe49e8cab3515f8153e8ff3d75f52d30f2fbac8ab4d9ffbba9eae7b97da82d970f7f9ac2bfdfbc41e98dac5d1259bcba665dfc929cec076d3c9b15cd456ecac34a2a140b7f586bb026976b5e9b7e2ae981a40e02271e28394873cd5e38047d9e4de33ba8fa8c8ca0e3b3c258b7b894be261b9b07402582bbb1ad324c28384fccc38ff7a8dac600406639bf06fd1c7fcaf6c79e793fce04f951ffd0d8d5f41dfeaa6f89efc4690da5f304254cce4e3b19ffe08e1d2625b482f763e3f6db657307f2d0b61e7f6a750f84839c2a0447efb7b7ff061bf7e39c0468dfeb5b12b3f76657df9ae0b3e206291711f623683f48f2308bd8b6d49eceaf3bab75fea8aaef5a3ee004939a69411643da28a400b16a4a1dee0f43c906694afb6a4e0ef2a105726c11d0b8561e06d506fe4ec76b831f4", .None}, + {.Div, "d1037e01cfd01ec62019f9208a6985bd7ba7f1dcd66a8fd638dd574a4b95bd797f4de3da4a0b046866f1cba0f246f9c8f6a0ba11a2922fc89df7f62a390d466fe7f8dbb2ae58b4f283feff8be96c50f57c6a260f7bcd4f2a2575f747934427a803829795312a364938c788daa5901b6c1634aa9529d05a326cbed508b3f554f2a9336243baac5784625b092bc5ad0fd7bba9a56ac7c19451e996b664e2d530ea70bee1c9d4c3b9109be313b313bb84f39c443d315e80963a931699ff31ada7046a9298e7ab5edab6a7a8413bd57d48e8f7c2823c2e0f075eb659d2309bcebef38a9c766238dcb60341c0a73e5902e37b88548a2c228cc340f827e6e471fe91780ada82b636a159800ab747cf1fd54b8695586cd9228ff6aa0541680ec1a20859f234e944c4c3550102e463f2f6609c39b4fefd4f21ef6f1000c9d2fd23dfad613258977cc8f953441e97128dc4d42aa6aa11bad9e53b84e967e9694b028360337add6694ff2b24582ca8d6869ee3357a9dcb7d0944903636b6031e7f232020473e8345772d99fbfa5587bd46eb9826c0826a2c2edd8308cac04e466e1a9ca6aff567407a636d589603b6f7482fb45533a2d42ec678a252d384374990468a59a23efd79d880d896fcfcf0b5996df2cbc7c3ce42a494759462ae6912674da9dcf9c5df63279185f868450f81ea8d5eb0f19d7abedcdcdb5ea8863bef6508955ed2a8018399cf735a54fc5d630836cb106d3e618f5031615182a9e13b4225ccd56041f21ec8427ea0a0d5223312c432684fb7b02bed53ca24d717e5cf5768360e8ddaf3260191978a14c47af37a27fa87fd0dcd2b38375c98c90735ed6a734745dc0dfa69ffe67a7517d42005d2916bcc4cc9f6479469fceeeace637a969412cdcce38e87d560c02364f0abc47e55e4d12bd4125139818051cc942810f334e20b7241481d0e60ba93fc9040fa7a7573fba6b4b12bb5114f6c8840bcf163b948a884f2f1b7f7493f4ba7d325930d577ecf46214c1ac0cd8d17629548d38ff69ca76d2cd03b47e0eae66f55cbe139e16a0693565dabb9ce43262ada96826b5c82151922c57a703cdeff7d93ee8a0695b2591626256eb9874a5db8404413469cfc18bcb6999e0881856b8a1be0b8686641b44a754ebf9112dbda43a4bfe6033bf45bb982b4f049ad0caca12489137cc7b4a6b755470b0799c8e2a17509a06f5075069aa69058988281951ac10928b6e1071f231a7f63c672b6ae0956631e0657edb70b2b557a385465aae2c2bde99d7cad68c1ab7e4f3398cfcb3fef835c2a786ec5fcc9de08b6393bb80686a2298e12538374502e3929019c468dc6250562f263aa4b7a334f9638b72a915c4bda8f570c5aca1c6450d9c96c2cd3640810c3624726b1fab210373f2400d0967815f010458191fcf5f3a1ab52b5410477f95d36cf9386c581a8c5c936869512fb0233c6fdaf49bba867709cfc4956bba3503b45c46f989557d4bef9d8240a71dab35f1a2792956cb216c482908fee85df8fcd9b5634ec86deb24c4211f75ae3b2469fde765e86fd591f2efde0064cc054228773e749ab3a8554431d3eb866ab9bbc8fbf18011cec075aaae548125ce3488aad68df4b6629f6a47fb9660e9606c0e4ebdd218d18fbe01745601eba77221eacd425d838e114723c806a5d47694b7aa2e3232fea41b58a92424d5d2e9db8b197cecd8fc48674c8358f8426849fb8c8510a750012a53c45a0c7268356863e904774b427d02b53c716ce7786603e59c96be693cfb6c68e2d24b83f4f9dcab58708cf04491e8af8abd915336fcded49d86a14c834215cd42397d694874d172746903f83218c6c305195173f7495cb7b4526d369838bb3e17a6e7e4b60616a39f0211df10dda929e1776530d9543500e97573372bee68005a727d5e1cbc6820ff63bb062528ab6f82299a3446d176ba4ff62ad8f51ddc313c8b5b6e71f74b577cf6b659302317717091eef97c79b381f2215010397f11d259dadb7dc4b2f9a0c0f51a7481e8aa3fafc9c732360894213e657924a85b957464febfa1246646fe09b5b3221e3d98091c4a5eb4b972540e076f00a4cd7f800da97f0c6c59211e2c907ab00", "-bab74ca5463f992a7d75e30633cf30c95636d6b315cc481287e69810ce5c665cd8c8f8bea8662f67c20cb3772dee75cb886d7ee8aeb48c93eb0169ebc490b0b6315e2de209a723353176b5943e03b5016a7f91ec99350b15a12a15c81646062b0a53697c23792fc3aceb912bcf385c0c117b345b18e1df4b0b10f7660fa0894e404d8debe3431b00762c721e23772f79f0e77c3d80e2c8e3f3af017c6d36d88bcc8c913f1e296b701545b01c48ab92273940e968db3c1b5342b0075f2d0c1e800e2f5267be6abae8bb49f4c2e0fd964916ccdc5a2e506ee282fe472ce69e19ae4efaec84657d9b48b765ecdeb75ee34f848ffaf63dbfa5d6ed00c94369f7de188b871c88561b4d61ed1b42bc2d1cae1dae2523cffe80152cc1974b167dcc34d7327f186e61cefc4dc02841e31d36d882577600a23720f2e122ec1d158d79673b2f7fecafc44b3c78d7b5d3a9a7f134814c83dd5ee566f58fc177e28e2191b7b23dcd131ae6778f79c22a4e34573c471bfd176931b0e90e7f124a4644d3d6d2c1bd2c74a3ebbb08624670c50d54bcc2abb5fd62c1574e18883e07c3ea0fb0ba37de67903ce0f182b500b0f68597547f053977456f2f6d35aa925d017522331f3c87b8a359ecc79cbfa666a70d5787e34f9a3358fb93ee564b8fbd77bcac2ea47fb607ef5cb3af8800a09d6104f60723c406a4e6cec6f6d0a89af7af64ba90c3f406b0777f535a33af42a87192ce4170076627b0d7ae28ce1496527a07cee4d574a2a7f8a350abeb74b42737765b7a88d58196c0aa95545e19d6ab8e4342535e23966ccefd83703df0de297a6cc22f1d6a96b136cef68564accc2526cee1ffb0372683e8d885e54584af30739d64550628bd6e34aed336e60d36cb75a7b556dd86753f063f28aa01faf2b825679bcd7e84f61347bc2012bb5bfba5d0a58f9472dcec1499e768c778478ad66fe889dd86fb3e7aa680b0259015a36a574d539e6dd5791729593d000991239ce3ac7e80567f722d7742f0272afb9278951bf96e80c4e3ed90851e708fefec92004ed2d0936395aad0c3854cb31e5fc8e94512fa7f10b384d0948730defdbda9790dcaf6202fd1446929314e8b272d9cd6571d36c426af8d7d7d855c423f8e5ecefd4379915308eba48d7942e77e8d77430bb519e164d14152f1f0b643ecb2e1d7965999b9c75350cc9ea1bb4929bc0ee3805fcee47713ae8fd15bd935eb6f46ee3c98d66fe0bf89a2d1246772dd38565b5f497feff8b38efa65", "-11e924f4e00c9110c3bcc3fca3441a95bf876cbb6627fc02c04646c1ab735e9460366083168179f214a0853f464ccce86c1436d9c90ba98299b4ddd0fef3f3704a4e8850e6c748213abbd22812847a4368dcb6fece65efa85734327c53fad155c3755ea8dcea0fcec6b57e02da8051ccf82c9087ed3696c13475b2e4ea8876c4fbc08aa400300108a2706a70d86f7ff97e6f88adff96b6ee4564119c36a2858aedb64b28ac311dc29fc3476b3e57d8ed19f0955f49cb9cbb3038c4521ea92a029c39bb765bbf848b37d11863ce74f16edec20b0db52f52180758603c696b00c49993c55fe28ee6e43731b767dd29db898c85420592b9acc6eddefa3bc47538514bed516f4db38e1a6d7a9cd4c85b454620f697fd696e2016a3616501cdb7fe5b8d8680cbcc3ce9d67de2d8598f0f4ba99206d33e64855857e29ce39a527b07070ad02a86b963eea11d1afdeb8b1573ff93e956cb0af416b4409dfb6edcbbdf343a57bacad2ea92e7a15ec5a5479b897081b99af5cd710a9e20506cf1c30e5c4ba4b69afaa075a47880c8579d558bd29fbc47e5beb1e7dcbef8682c78774c1f0c1058a2801a4b8e59cfb4e5cf310f4c1d07b1f901e09b8c578526ac6f805690044b3c12838a28d92445cdd51f8390cd5b29805e8172c77ed9feaac96cd2af9acf6060752dfefd7218f1547a37b2d035b3dd351820df6106aba8fa603084e499741d753601fe6e7126a51c58d3207271cecc81610dfd0a839c732e74cdf54ea107543f54c25f6aad02c0056c5ccbf2305c253772de437e81c82e902e6bcc6132654c7ac1c69410192ac0d3a86e482be4b1adec22fd23c3249ad", .None}, + {.Div, "6ca946b91ea2f61a05bcad34a6f88c60a99a32c5b6b16448b26c5168d7d6a252394ac95b15a2f2f4abffcf01a5cf0cbe3528fbde90927687806ac2d45e2d72ab8b988aca4d708fe4e0605dc95e6cad347a266d75311d6f9ecd07bf97c20613de2a383861f2b93b7095d600bf8b827ab4ebcfa11a833605ddd5bb822dc52ad3ecbca02b78df9a71010684906e02c071b37f7727eb0ee9ce685fc89cb9bc5bcabf27448edc2fff5a963dd7ffaf8ca837db6e33065cdd03ce8829b6094cec6614238bed1f2ee8c5f4acdcd86473aceda38b6819ffdff2c7d9d85ab0b3f799b832ec5f8a6f54c6bb2f7a86c80175d8b45b23aca878d489cd25ce71a308f9dc4321601bada32b51b08d1ed840005368c247ceab8ae65c02ca93013f03801a413cac8e6277536d026b997bd216051ed8f51049c7200bc59d14f44fcbf76f3c0c4c4bea67e7774b38c13bcbc9a03874145f14a05de769623fd59a10b17bbe6d2875d0ba9e8d61506d33a002b01f0b3d03b669cb075b1bba8249417b8d5347d71fc8ff1e7f5a49fa00ad2802ddf21c6fd478f9514454ca0d8710a1d39fd5dbb0ae4b3ac7f950dee9cbbf21d8905003ed10dca21dd830a5714c2b6ca2d987c7ce8e78d6ed80ea3207f3166a0742fc8cc51f0a71b40dd96cdf2756de6f1cce7e32bb15d15517b09f8f5ecd61f2466889cc86154da073eab5eaa983e7918da5aa0c1e7a5532d71623c1b0e6387ae8d47354439e61c16550e4bb3cc9653f9e92b85a49e25ec8595332510146b9ea3270806e17f740ac50beb58c049ee11a61d55ef09b1528395cd0438d911ef1156bce8fad91fa085c04853ed0e1edaad5f0f2f598e271abc04776ff5baf9f1a984c2ffbcd1a34f6e27145404f3c91a8136f93598d8b107702fd0de77c57824d97a82d4a9250970a629fd82c2ec55b6eb4ea599bf9d75a11250306ff82246ada09dab3d8cfe73682dd98ccd364c57b4a3e824337c3ac4ddaf405cff2dedb1a136517529072bdeba6746675cc3f790a6d7b7b05081a6837bddb0f098bf6ff4527921b4de9bf2a9518801e087f3fbb83382727a18a13768fd03010454ab53ab80e92a23e3027589d72bcca93ca0d0495c303b1297f054badeb1aa62df7c3b99596d39d117d57ab9cf69a40cc5f764d45e530585e6d8bfa5dffd842d3a7e836bb4a94995550bc58e738182c193a01c053ec935ac495fab83377d1596b49d9a13ee05110257b9ed45178abebb8116a53de6d9391c32f77dd9b79d6799f5885d33e92e0300a5d93b8a5bd9e2a30b21d7d9ac7d3aa212172dd2b726f68c3cbcf102d4138fa5f274f847ce7bbfe3dcb7b6249142baf5ead2dcf3475183c8661677006ead409d35a11dedcb0d26e5f831b223b043a2d72e90004994b8a1c026f19f394df7b2b28c6fc82533c84922ebfe0a626e97942a624e1135c1212009b405e57e536138a8c88e863e96bedef639140b5f8d576de9e122d45430f805b514db5ac33e0df158cda0703ee92c1c75a65b339390e3b40a8a043184ecc64522ba43e9042078221d4cce02e0f4651d33b2633da9a199ca8baba5d78b5eb84c0e853000488c02958863d5517485e0db7285e44ec2c83d929e5de38f261bf2144545f59f8d38c3b1bb9ca1f8c9f462392383677a0bb91701baf3f73b2cab6ba7b53f7567a0a779bd4e6e97384d679ab7162440ca2db5046e7ee186fd8b4a810e5ebbef981aa82f79da5db1e8e80f6a35b08077b81a06af3e81ea0d7b9f178fb79c324db70f9ab4a4b2b660ba0b4a9a8b1644c673182958b688031d6a2188c5bd7d783921448bfad99d1b8595b83a2f619f4ace1f4b041b392b078ea421c6de0e6fb367947797288cfb9393b7fed498a04802f3a698d35c2165d7576fd402c5f8e6715de21c79fd471aa42e00786f1a55052e43172248514385cc7830910a743cc507ac402cde3a3712d6e83589f79e33c9d1a8554aa55058efb860861e4ac83716a725bf3c7c4783396e23dc093410625f2f88277fb40301c8bc07774cd81bacfc36fede332ac8bb952e882ba6ac649cf4576a0772e4f729ac28ea289fa97d66620431b8843a0ee799bffa735787003a1f117eda19893a1121d4a13", "-3362860bb290e68526f8608badaddf777a6492a5ef1b8c91d9b2424f5d90fa5cf47cbab33f2183098e7d149e5d23a2b6282ae34270b57289c1347eef3558a416eeea46ccac81843a815ebdcc142e5b8b0e54031fcfd149d27c14639484ddcc178a972768df46a7eeb7b3e1329886a5988f0d0d6870215c20f1efdb7fe176a04ee341da727ce954bb7ec3f8549ed2a2dba6a213ad62f4cac102ffbcbc6a984e5a8a30f3ae10b2692d2bd784951b6255e4a246dd32353cf2b44b086396237e735d9067fc40e2ff3dc61a8e410187a5d09b910b61043dd84985d62ee7f31db666213a2966ba1945a64a37d2c3685b845d12a3444a3742b4607b5f1ba2a923aa33533bd9ca07f9656a7421b5e51e2e67dacb7c174f60c719301f622c08b9f382978be48e92b1f0c527b47a22cbe4de0274bb4ea72e2b6ed54b17ee8ef0fc49264bca21e8460d56d11bf077adb3f2a22c5c4f4267178d4f914080b6c563d76a2ac3ade3d893ad3fc5da5ae26b132e0a3d524abcc2130ddc7e40fd1b1e04a6742645616927dae322dffe516a23509244a697bfe7457e674ec1e6de234579ed61c2bd31890eeeb0694d3473feb5805b621c6b8b0fb8317f0fa9c5026801aa622a4f12873324fd16df5352b648313ace174fd40459c9bc47f61180b2c738d49dfd82ce29b243b0704983acb6bc01681e818c955ea4d8f6d132a2994cf9bd38c9eb4a9861a980f2816fa0017c0ffa322a6b4c7e6459a54d15c63ffbab5dbe1ee573fcb61886e88d8448529febed38cdca0e6aa414d45880f2c328634be1c612d0cf3424888a48880d6a9339792ffd6f257f433c6d2c8a91a4651ba6a26f309753548bf48e5ceec82c0fa9c660ba20004dec3a98fe50e4106b1bd8d5bc2b41ffc3a49db09c55d88ae019f0460072a0b5b6a5c3c3f0278a38c9d040c505d37af32c5b0e950bafcf93b5e298e19ccb4aea01e9c978e9a9938bd9a014cf7babf71272a5d71dfd64ceb79a0fa1c3434f6976aff1d8a203bb5ac8e34a8aa1f7d9322c3eef84e6f087770d3fd27c8f699a8c77fdd7ead577f3af80920713455999c9f2e099261202f3332b7d4d73f04c398a13e1735d133a8d555a013388236af66742830af0e66d8f3add964307a63507877b35a156207e2b78f6e30439b3286a9d6f43e916268aeae6279fb80d678859c79cda96d6e6d15252ca674bfb8ae9853f916ac1d92727baa7857af790d0c6417f1d033a763cdd9033d4cf515f40c2f1462dc42b373b6a69980caf", "-21d5a0408a45c11c9f7088fe4f113194094c7a70d08c4bdd1fdac1c5d6d8750ef39ac9cbe632e475a2add944b225dc9c1b23c1eef761e80fb6c6c60a389e5f63555600479cc625aa2ac2def144c5b317d62cf1e5d478c467999d4678a685394d2df243b6fe494a95544d0b2cf14cf79c2be1fc308ec19156541e938fe2baf1af7049bb5f2c215fe6e0216e3e12de661024d5c834d12fa6758e29e15e37890d3c7306bff41f4001309936c52f7decc7fb1191b268a9f59cdf534a27a41a910fee1e426c87977dfca9ef68ff47ddb7b6503790b64ba200e6051570816a69bfbe733f91990e07c0d535ea9539dffc2f7af73cba46236b8d9d191a60db0058e15fadd67db6e07571dfeb068959a9f385c83bd2139d5fcf53978d1c938b9a44ac74159b10106ab1f8357511fea5b4885b8210bee9d104ea11919c58ac0a66ddd2007b1fd1c37af94caf201d63acd4f4442b10294b17f7ab979b082696525dd62818bee1dbc46fa830246e257b7584aef75d4242494bc4a42887b2756a6d5c12b9658c8466fe7ac503f96033959c122d5aae4d0225d51bd9fbd951330bb1631df8a038bdef2a728746d343d29e4a1ced70fca835afa0bcf7114f7a287bb3858502e7b89d7c2cf367d8233cdb6f887b20c29669b3b71854a1371ae6f4ef08fab16351b3b9840f7967e1495d281617842aab7e69d6b10a9dd9dc06350b1de89179261b9cb32198564c73ef5128b05316799f76679f353d7733b44ba9dae4ad9d8c79ca73e86dd3784d432120136aadc533a9645bda897868fc94728c2a6f87aebfa8dbdc94c82a29a8241e3494f179758f4821378c2879293404be908", .None}, + {.Div, "4eaf4dcd7e1c9edd6f53227d6d44aa051e9e083e68b9640e975c8b2242be52bf124fcd6a1feb99beca3fb045a48a40c3db73c90bc1ae0b28b1de4273cd38c432543bd0688dc3972cd08f41b9ff5d65526e0d030a3151f2280a15bb82341d2128b7abdb481ee70002c359240a16ca0c1066bfd3942814f52637279c032310c1efb838df30eb92a42850126fbeefd8ef721f07d4271bdee9ee8030f704051806bdad2ddc1fa4f3065e367560808b951356ed7233c8827bf5d3db08217c5b0ca3669ca2752c01c25f7d812eb057e70e0940cbd0ae99dee8ebcb8b2dc5f8309ffc4f6605e348eb1016c06e1f3a4cf14baed493f384e0c475c3eba2d907232095595171e3f1f2035046bde96043728c4c90641bb5ef8627adc032e95a633b3f070c34ded7070305718a1a4b9a6770cf0e908540177450550803db7e005c84b81966bdf462d787bf2cbdbf1e8d73589fed89b94230ed9f823ff50d65d1c5a0874c19c7a8d187f0c0e12a2e79605a46c4ee4e03c59d723ea38880e5b5b9aa2f5ab55c8ededd9c442e30288af0c2fa9dc0d99cf79f7b99821d823aaae09be643f8bbdea1133b0631591aea2b377c309876e1a1e86329f4123dbee2a4ad8ee3693c0a487b42a869b9578b9f8e2b0c99c70c476deb0a3662e30a5119a4a3e5b3342b190ac375b4bebc4ce103df9367a72749dcf41419e98221ffebac59f1eb7193500763822574f9dea075c888cef58c90110b2c05dedb0d1f42cafedce4ae5037d6e945691897df6c78d6beafd0138da246783f26eb30f3d227ee0182f92b9b3978ce7f9f7119dc44c639a564e27729c9e206a3615f62fd6da1998176b4d301550155a5a004a15eec816bf03a85bca4f0e171669c66867b0474b5c84af337b94e34d0c439b2129e440c0bf20403e07e93fcd5524a5cd80d3f7ae431fe76ef8bb47c5427bb9f07fcba2cdb0acc1d7482fead4c4ba290eccccb51a930945b39b20ae28f9d0b1d3673f4496bf95de7b8328491a40fa4cd37be2b9b79da030abda5a11ffce792ddc1a647468e98387ec31dba5a5923d2c79539aaff77fe4d5a841db822f133d5c05e2c53e1c78ec2367447d4335e87b288e66dd5ef671f2f7a73ae97d7d50f4b8fc525b710174294702043c12bbd410a8ada8cfaf1c60a233d962c04170738049ad100214622f04efcd20d3ab8d89ae7f943fe61c48f50a94566e747d84689ee2677c5484f15519f88e2ac26250a3f0f86723bbd2f7e54339bcf0a8b6bd73e677006ea58ec2ab65fd0ac43094e1f8d17246823e5418721956115e7bc7e3609899ed7530f9cf072e8459033bdd5b4a6cf91f466dc1448fadb97866bd6ecaa05560ad059acc37d7ea47181b90fa0baa1f6c05997c8e46b12e61c4da7f39ff8720427465320e68ea2ec83f1ae90a1b3b267237681eb687598b91a39170bab42a4af433184ac8c74ac7261de9f7dd2e430fc22a213d2f340832f18dfdcb67e3f34fa41e13cfccd0982539184b9eb437a0e8a9ac6ff5bab3f4d4531db8a1b9010d85c71bf0cd89b9bada899840938bf4af9939ce7c6568e1e97afd19b5b4208e48ca3e6ba5ff02b948ef6d83e301c0df97995f23af7126c5e772d11d06f35c76613ff0220a189a07fc7fa208fd3deeb182dcfb28caa4231d60ccbfc62816ef32d5f6ea03f4bc1432f6e0016da58ce2b8573144547c831ab994cd48fb39b1d4429ab645fcdf2542458367b92398c469fe42bc48da9163c20002705dcf1269346f81dace1fe30948b077c8c65d7bc663d11dab8478bb81c038438079e361aad4cbb0956f4336e8cba52e6fccef82d9714ea1bdd02e93e3695cad6c2ffaed386aa5db63965aeb0661cb41ff80d4bb8e9e56c5ac378bb184bc632185922854b19de3aaacdf26524dc863f195c48b92b8944aded1dcdc15a76e15e9d80069b82a116e9af42921ccfd69c664903111363291bb2e7bbec292c22136b3d8502287250ce250a41f51d2331bd5b15aa247168b8fed7b51189e33fa792b19b67b1db82929b80bd935d52c9c2c0e54cf304b98e6341cd639227e5152f666afd3646b62a60108e427c4d38c09f38387e2abcae412eb9c977b8caf1740eeef45e941c7edfb9", "234bb6addbe6ad685e91f7ca1892bdf91e176a36e8135d6495d9d6f08dd4c9f6e418cea1435e38d5614a200326180751237baa133381ca47b2580bde1cf994562cf9f4f58c5820089e9493a18fb067c1ecdc031adab0c0f44d89ea8fc42ca6fa1bd8c57a6eb2d94b4a3816df5e565359823793844f38c03256131f0065b4f6f10a656564aa72a5f57a40a3496d1047568d5835ab9a3b076903bc45996c58e617be6ffe60b638c26819868784ad56507a9471765871211dba05b4193020ad41f95f4ebce9fa482d930fcd7d4c923a450c5cfe9f9ae7943a12eec52fbbd426e0456acbd0103ad3981daf22c311afdf179a68f633d10a932a980f771feda4e77ad92886209532285b1d0ec04f7eed9d992542cfbda4db654d0be767b624716c0b636c64973a6921afb6cbaf9a609f09a5c8f01b4f598efcd71935a989e09dc0a66c487bce49b0dd081305e627e3eb2a7936e6b02f8c39af55e5efba28249ad0ab2ae59d2a1ef74e9ca17f0b0952c8f0575db3184d79621c1dbe4a7ee6e64a6d4d96c102607074e7560176e5445adbf3abb033398ea504e740e31cbc098f0f1b9f0fd47a9cc701f48a7f5a1816fe5e5b850474a6e0abcbfc40131a3c64fa68e8bd8fee7c15a1de1f538b714db967750ea2117fe07f655fcf690172d2e5b8c0a13115e18b03d3489e30d1f6240944f7a467ba6b31355944ae00bffc94ee1eb2202ecd6f646813f43ab37af646549743146e74f6cabd881cabfc6cfc42eadda96af24b33c0bd3b90d09bd975bebecd97ad5b471520ae7575d07263eebfbb4ece42c62fc3dc05c5b0b4d11dd53985a6bba364ac05ede092cb7e24f608b7f5f4dc0af4037506a145243f46fc43198968ce4e4bec1f2c22145dbde32973bf93d46417d360590f0dd161259fc17ef11143119fa3bff0059ef44cf19623db7b6f902c4bea95213c3273323ea3bb7a635c7e0bb5e95387e965175d89469a1e3c26ffafacaf30cc354055333256dbca56048ec409072706e33c69b7285ccbc1ace99ba0d31d3986fcfe45d8a3fecab43a1549598863da23732e592ec6232b1ed20688028ca725bab9a60e27c1a324dfc007c98a727e1edeb64405fa734181d32b29b2d732aa76a08b6e2baf8ad3c7a8240d0be58c6f6c0f7277c8e56237886e312ff5cd6bc147fbea4c566d22ea7e1cfb354d9fcf5ab3a63cbeccb09171fa6b0aad9d13a44a336a30222ba0c96495c1fd66692aa560ab155f95ff1e4a5c460c02b0a17000596947a467a5", "23ab3509f812db10078b5ff49f467d0773940e9d280127fe248efded9d6fef4decc7f711d810a4b11cc6990590b6fe0153e9273010d3f04c8b4a81c09765ce84c75a1e4ec424da06515e840062b74207d69ea0f313c81547671221439722e43cbf7dd9099d7e2478a833b663c40eb3a4e41f1849f9e8429c899571a31486dc1997fb41a6e0fbdc16fe617e6d088d9c7a9e8b970fef06edb7770562ba5c46533b241cc4bb007c0d6ef478525407268683838c972e291f66fcce8fbe179a8cecd3a46108b73328fa3ec930433228eff7ee7e05cfff8d0241c4886c5ab49b18a27ccd8e7c7a117a4fbcecebaf541a53024d53703e3d12cfe17b98d4748a02de43d66f2c7a7bf42e454a24297ecb1944d93c25204aa124fc4d2a19bc947f18ae7943164289ddf0b9418cce5a5ec7a08f0feadb09cc16ff09fcd11e4656a6c141993e412f144f0a39150883fea746070039db887d07ce8cae9292ce995270fd72ecc81f997f81f13c1d8fb0e46e1f741711941a86d9cfce66829a5c1f0645f7b28a2d88cccb61a8ed1a14ff986f13b380ce5f1a762b54cabd976e42d701a23929c90eee7cf03d839cb65a2e538f5ba5568c247ad0d5bbaaae27eab98ad4a9991dd46e0566c887c38f0e495d235ed2978aa0fd21777d043f40706f6269a58042fd620a859175fd5f922eddc18899f8f52060afc7dc05ac33e500ceeab0c96ee0e9fc16d72b0c0358d410b5d32a064772413645076706da6884b59aa9283f0ea148298bbcbdfba96731d82f231c213a60d3a53c04f66224b721ee70263aa5426be03097395bcddd71db94e84a0b6b92afed813317063e5d6052661ca", .None}, + {.Div, "94fabcfddedc4b0082eec991798a4656b09a7c9173edd68d2ec58b3c6bd4aee484d22d6df51272e0b5198784ed28baf3b195831ad861a52f5ee374141336378115c661662bf599d859e9c9bade7b28bf45c5cec918f7921b4df855ee7b06bff8c6ba9e8a9a4cc498556ae8f3fbd70102e8a9fa94e133933aebe2c9b59193b446418d4874faeaa65a9297c81a274943d9c09a4227ed52a730bc4866edb3b0cc84c1bf63769553809bcab4e6644c4c6887c69fa146b4928874ac2a66fd3698556f0676167dbe5eb20057cc0d0eeb99090a684654c477f699700b40b5ec4680bcfc0d97f8fe565b2fc0a54ff16f25db127bbcc5de6b6ef2fea00fdd6435a41aabc8e802a0413d9acfb29b9cc0a376f0bf5b976208be05fbd82f0811e27a7880ae3e737f4174105fb5d9070d81b67da8f70a20a5b13d6962e02af8c1de24c2548310d80975bd8a369e344b0bc8eea1437654eb4706ce9e83912e5b310b66f00dcd14f53b74c2ccd77e689677b96a924b786b88a4bb39f66cc84a105c7c4f621970ff64b1be6477bdfa299120b2d6fa4d2802f6b53f9500924a86b86b74b60a9b90e0d26fa0805c510a569506ed542fab82553c38ce0701fb41d212a0ac4863dc8b5cd85fa3ab1bfd8b46d33bdc9525eddd44022898b8229ce1c875babd99ba1aa4bd9b07d2673d2ea542a695bed49715a49fbd8f3f4635f27aa2e88a473134567140ddc5804de83fa929f62fe9cf96b8fbe798907920fd99d73894aff81c22cc0670620b2827c892bed871b9b787f5cf17c7a9efb0776a08c3d05e5ec0712ee4a16ad0b59ceb699e97ccea3c4c890d56b24591134a402966510ef4e56f4593ca2cad143435248c192b78d5c659cac03c447e12c2efa051279f1ca24f6688e1d05997eb4c3e2682dc2191b1782d27e6aab685de5518eddb2ebcdbb03284c45faf3316856952fc6e66b1f822d4407dbe23c15b6f6fa789c3603d846d87fd0cdd29e192cf5a63db96f897148e18b565ad7451f9c789487a4ccff10db413d1f4a5d22f89d68c13e7d3a122466300c374f703712d8d14aa88f57df52b4ab4b06ea05db384240a11480b5c51bdc489ee23c42f574c14ec419ef937e29c401765e6b688f3c731c52171dbfcbd713b4d89763fd9b45ae4405c7c41bcfc5cf1f7123189e0942ac5f6a75ead91d9d308e305eefd78eb29b0473d3c47e3b5f49b60b290afdd16f0738d33ce39dd78aa076a30b15e066a9427dd2b51883dc0a71c195701a918f9f836c91ad86db903d6bcd2f268da4bf361444f61444b2d46ec4312160ea9d7364f621051a21ad15d76ef73b8ae6b618698180d370393feef4626135e84dda07790ee2c56375a83f559537b3a45bfbfdf69e4a0092daff702fe6afba92de86424b7eb781b05cef43b9fa26e643a0d35b25d56666dc791de1d5292759fa25d0bde081a2ebf0702f9edb8028e4eded7db1e39c39df726af95ec037c22ff05b8b924dd144fdf1b14bf35e6f3fb9e3830f6d4b3f7dcf20befdd2784661f68879fb9078a41c7553998510419c6815509dcc63c696954c862665fc934853acc53f4ca96cecf6d5370b6869edc454e4195a1f713c55d826aa0a9d377d37865be6c45e64767f56b134bc21febbf6df8b009e76b4f93b251a28d2fed7841a0caf4b32250c4ced26feb87288fb772cab70230973187613fdcdf6938a8290d919a1230f562b9029d36447c4d16542ddbfef099a7bc29c99cbe6cea6c16f100d79556b39edd1c8fe0db80567292de5529e459adad5a4532988255bb7cbf69dbcfa44333fd7988704e32a87ae4cd888223e3d6b7517d5d58663850afe00d6681e232df8ed198edc4e4126cec1a6507f2cae5abbc0492c1b4eca44b8f794de7f0545688604d5b4f519f0ed19d295dc1c8d7a3837ffabc4354c976cdd8190473f9468255e69510c732a8b5c2ac6f7ae854b1c7a4337b365bee65f1af66181760e799db134293dcedde4d760ce869043a669e9ae563e1f3c2413e2e2f3875ff828c77fc5f596648379bba37e569e90059adaa389a4653c2695707c292afdc175e8239dae57e4a27709afb2a5bf4febb192ff1ea0e5a10fc80127a4f5b04293206ceb135e2a", "22fc9629450e95695b8a8e23a1d11170b40616fff30fd965134de3c46dc9b91b710e02d3461b0b5c0d2c36b79a2b16ff066491e737b089d2c12451d052467623aa41ea34eca2a5e1d6ffb5aa4200dc23b42836dca9d61af078cb614660f680ee687dd2ea18de32b6b6e4112f4fb71cf7041fb52e4cb58614a9bf7d74cd174369a0403f3df8a3d415d235e2a6dff17c2fff618718c03000df4a4c3cee1e4945100c1b9f4dbb4c5de1b157af1c5de68b05e96300c5ce35c3f3d165962e5dcd988f26f83a58f531d9249f73a59258aa90df99ca7e1f52430e823e4364349398ebfb8d59a12c5be35773be8f78d10fd4ec290d575fc8b56a71aea06a12a6482f38646e9a4e9493f93ac3660b8b9772280fcb3cbb082b2fd47bd61c963e3202ebf4167eb1f571297f2c8ee1df1453a5729e9f84709d654dad47735b7701293acfd6ad83ecd0cb25fba21428ed711f56b232467cc85c629a48f76302aad800c4cbe6667ca622a086ea454b0b394c847dfc97b256acd439ea0330a994d0ea26cb7c06f601bfc883e8261431ee3190fadd4216a4881fccc250c3386d3aea82cd65472a4e267331f3b35fabf283c8a91bde85930c603bc02549a12147ab49d9cf5c5ea120dee35b755bc885f018deeea723b38fc3dfde9955837a190edb989e4df1e7f2213aa22e81c9a57b3f7b2ff9cb9502a86c9f81951449ed24023eb058a3110246648d90dacc3dbafbf546f926d00a38b5995e36a8dcebbb5ba6267f02e0943f6f6175da7fbc89345d0c66fcdee20c7f2a187ee75d7ef3878baa6bcb6e46e0eade67f292d7c41e693ab4254b7d6798ac807652d50c09933289473beb14e3f594f7719bdc1c5638a065a95d546d64551388980fadc21d1b280399967faaf38d38893d0123a43184a4ddc4d4793011aaa9e0a2711cd2df22b4089b6e2a687eb443ea8e11eefb414c539f7d9c2ff071702c9df5fe54363cfc054d5f7dda6aebe0454e8f71d7855ac0968c7542672dbacae47af311659d309e0d82e990086b381bf3168ed6842ca69c6e33d38aeddc8c06e735a42c1f78ee6f1675ed5657c026ec6199c89fe15e54430e5b134a41c21d6289fedd1fcddbed5af5411ff7d04485d71b9a03fd5cb8fe09d2dabba8b19d4dee1b03230491968a175393df432d92b3ee697116c7b91ec8aa76f80d7eba33c1d97f78651208d32c5606046e0ec3d72cba2bbe33669502f81e3a5bb3a632b3c229d17056e043b6bf55ed4193481ae39c929272c86603007c", "44217f1066541a239cacb5773c4f6a36007524bb5068f7c15b98cce1cd5cc1f28df6144128806863a6f15042a10c0c56b01e338530d14ea7c1e08b876a6781047ff107e8f6f90f5efbc5e97a075c6623f912de71d1d037421a683c2e507b378a232e60d8f605d4a1f9752fb72a62c4266d6d6dad48b09d782de7f9a00cd98e0c769bf67f168887ac8af7e9e645bb87b50666c9b6f1e30e494972e63126ce61afb991f59791d7720ee1210a19949a6ad33a7e784ad3d39c83343124d7a67589b6cdbf0992565d1f6f69079c2af0315ee7b3ccca911b468989d0ccbb7edb40b6afd5782b8082a227eabd0d5c300c2fdd6507c4d69c75a5b0f25da1c6a9becdd3f61fa5c85f8116c8673f3c03c314c3ac5553dd9204e165aacfd60229a3178322da5d3fbf6c1f22e6e6407aec97d23e32232f8e18301a4489a7dd164a5dde95a34315d669bd970a2a6d7eb71dc6964030c323db8f1739abbee1bc1a969ec61280936bafba45dd426e745e8c6f785c3ab0cd08337bd07ad73af2428551e05ccc1de3dee6f895db9cf889496d0f39427a9ff2b89288c3c6806bfaffc30560af130b8c63caf5ba7cf070286af8c7285704a5c7c1f2cc1a7b007016ec99eaf8423d954d4e02a69cf6f99f5b23ff1ad2e43430e3d32941e95624a774636f34de7343e0d1196b4973bed1eabfbd5ac4d7c8744f5787ede762e7bbf67dd960845690447b97dfa0be8d2d352c0b776ca1acef31c827339d74cdfaa50ba1678de5ca49615e26a5256a6f3b1c0a2c98ed187e86bba50cf009deff2f817f4d72cd9f7ef35fa39e92ef1368383dab252a14aba707a8fffe7ae845c823a80596", .None}, +} \ No newline at end of file diff --git a/tests/core/math/bits/test_core_math_bits.odin b/tests/core/math/bits/test_core_math_bits.odin new file mode 100644 index 000000000..fd9ee24c9 --- /dev/null +++ b/tests/core/math/bits/test_core_math_bits.odin @@ -0,0 +1,171 @@ +package test_core_math_bits + +import "core:math/bits" +import "core:math/rand" +import "core:testing" + +@test +test_log2 :: proc(t: ^testing.T) { + dumb_log2 :: proc(x: $T) -> (res: T) { + N :: T(size_of(T) * 8) + + if x == 0 { + return max(T) + } + + for k := N - 1; k > 0; k -= 1 { + bit_pos := T(k) + if (x >> bit_pos) & 1 == 1 { + return bit_pos + } + } + return + } + + testing.expect_value(t, bits.log2( u8(0)), max(u8)) + testing.expect_value(t, bits.log2( u16(0)), max(u16)) + testing.expect_value(t, bits.log2( u32(0)), max(u32)) + testing.expect_value(t, bits.log2( u64(0)), max(u64)) + testing.expect_value(t, bits.log2(uint(0)), max(uint)) + + for x in u8(0).. f64 { + n := 0 + for c in counts { + n += c + } + if n == 0 { + return 0 + } + k := len(counts) + exp := f64(n) / f64(k) + stat := f64(0) + for c in counts { + d := f64(c) - exp + stat += (d * d) / exp + } + return stat +} + +// Helper: check bit balance on u64 across many samples +@(private = "file") +expect_u64_bit_balance :: proc(t: ^testing.T, rng: Generator, samples: int, sigma_k: f64 = 6) { + rand.reset(t.seed, rng.gen) + + ones: [64]int + for i := 0; i < samples; i += 1 { + v := rand.uint64(rng.gen) + for b := 0; b < 64; b += 1 { + ones[b] += int((v >> u64(b)) & 1) + } + } + mu := f64(samples) * 0.5 + sigma := math.sqrt(f64(samples) * 0.25) + limit := sigma_k * sigma + for b := 0; b < 64; b += 1 { + diff := math.abs(f64(ones[b]) - mu) + if diff > limit { + testing.expectf(t, false, "rng '%s': u64 bit %d imbalance: ones=%d samples=%d diff=%.1f limit=%.1f", rng.name, b, ones[b], samples, diff, limit) + return + } + } +} + +// Helper: Uniformity sanity via 4D sign orthant chi-square with modest sample size. +@(private = "file") +expect_quaternion_sign_uniformity :: proc(t: ^testing.T, rng: Generator, iterations: int) { + counts: [16]int + for _ in 0..= 0 { idx |= 1 } + if y >= 0 { idx |= 2 } + if z >= 0 { idx |= 4 } + if w >= 0 { idx |= 8 } + counts[idx] += 1 + } + // df = 15. For a modest sample size, use a generous cutoff to reduce flakiness. + // Chi-square critical values (df=15): p=0.001 -> ~37.7, p=0.0001 -> ~43.8 + // We accept < 55 as a conservative stability bound across platforms. + chi := chi_square_equal(counts[:]) + testing.expectf(t, chi < 55.0, "rng '%s': 4D sign chi-square too high: %.3f (counts=%v)", rng.name, chi, counts) +} diff --git a/tests/core/math/test_core_math.odin b/tests/core/math/test_core_math.odin index 5797cb4ea..009e3fedd 100644 --- a/tests/core/math/test_core_math.odin +++ b/tests/core/math/test_core_math.odin @@ -1238,7 +1238,7 @@ test_count_digits :: proc(t: ^testing.T) { buf: [64]u8 for n in 0.. bool { + context.allocator = allocator + + { + a := make([dynamic]u8) + for i in 0..= out_band_size, "Sanity check failed, your test call is flawed! Make sure that num_bytes >= out_band_size!") + + arena: mem.Dynamic_Arena + mem.dynamic_arena_init(&arena, block_size = block_size, out_band_size = out_band_size) + arena_allocator := mem.dynamic_arena_allocator(&arena) + + element, err := mem.alloc(num_bytes, allocator = arena_allocator) + testing.expect(t, err == .None) + testing.expect(t, element != nil) + testing.expectf(t, arena.out_band_allocations != nil, + "Allocated data with size %v bytes, which is >= out_of_band_size and it should be in arena.out_band_allocations, but isn't!", + ) + + mem.dynamic_arena_destroy(&arena) + testing.expect(t, arena.out_band_allocations == nil) +} + +@(test) +test_dynamic_arena_alloc_aligned :: proc(t: ^testing.T) { + expect_arena_allocation(t, expected_used_bytes = 16, num_bytes = 16, alignment=8) +} + +@(test) +test_dynamic_arena_alloc_unaligned :: proc(t: ^testing.T) { + expect_arena_allocation(t, expected_used_bytes = 8, num_bytes = 1, alignment = 8) + expect_arena_allocation(t, expected_used_bytes = 16, num_bytes = 9, alignment = 8) +} + +@(test) +test_dynamic_arena_alloc_out_of_band :: proc(t: ^testing.T) { + expect_arena_allocation_out_of_band(t, num_bytes = 128, block_size = 512, out_band_size = 128) + expect_arena_allocation_out_of_band(t, num_bytes = 129, block_size = 512, out_band_size = 128) + expect_arena_allocation_out_of_band(t, num_bytes = 513, block_size = 512, out_band_size = 128) +} + +@(test) +test_intentional_leaks :: proc(t: ^testing.T) { + testing.expect_leaks(t, intentionally_leaky_test, leak_verifier) +} + +// Not tagged with @(test) because it's run through `test_intentional_leaks` +intentionally_leaky_test :: proc(t: ^testing.T) { + a: [dynamic]int + // Intentional leak + append(&a, 42) + + // Intentional bad free + b := uintptr(&a[0]) + 42 + free(rawptr(b)) +} + +leak_verifier :: proc(t: ^testing.T, ta: ^mem.Tracking_Allocator) { + testing.expect_value(t, len(ta.allocation_map), 1) + testing.expect_value(t, len(ta.bad_free_array), 1) +} diff --git a/tests/core/mem/test_mem_dynamic_pool.odin b/tests/core/mem/test_mem_dynamic_pool.odin deleted file mode 100644 index fa204d3b1..000000000 --- a/tests/core/mem/test_mem_dynamic_pool.odin +++ /dev/null @@ -1,101 +0,0 @@ -package test_core_mem - -import "core:testing" -import "core:mem" - - -expect_pool_allocation :: proc(t: ^testing.T, expected_used_bytes, num_bytes, alignment: int) { - pool: mem.Dynamic_Pool - mem.dynamic_pool_init(&pool, alignment = alignment) - pool_allocator := mem.dynamic_pool_allocator(&pool) - - element, err := mem.alloc(num_bytes, alignment, pool_allocator) - testing.expect(t, err == .None) - testing.expect(t, element != nil) - - expected_bytes_left := pool.block_size - expected_used_bytes - testing.expectf(t, pool.bytes_left == expected_bytes_left, - ` - Allocated data with size %v bytes, expected %v bytes left, got %v bytes left, off by %v bytes. - Pool: - block_size = %v - out_band_size = %v - alignment = %v - unused_blocks = %v - used_blocks = %v - out_band_allocations = %v - current_block = %v - current_pos = %v - bytes_left = %v - `, - num_bytes, expected_bytes_left, pool.bytes_left, expected_bytes_left - pool.bytes_left, - pool.block_size, - pool.out_band_size, - pool.alignment, - pool.unused_blocks, - pool.used_blocks, - pool.out_band_allocations, - pool.current_block, - pool.current_pos, - pool.bytes_left, - ) - - mem.dynamic_pool_destroy(&pool) - testing.expect(t, pool.used_blocks == nil) -} - -expect_pool_allocation_out_of_band :: proc(t: ^testing.T, num_bytes, out_band_size: int) { - testing.expect(t, num_bytes >= out_band_size, "Sanity check failed, your test call is flawed! Make sure that num_bytes >= out_band_size!") - - pool: mem.Dynamic_Pool - mem.dynamic_pool_init(&pool, out_band_size = out_band_size) - pool_allocator := mem.dynamic_pool_allocator(&pool) - - element, err := mem.alloc(num_bytes, allocator = pool_allocator) - testing.expect(t, err == .None) - testing.expect(t, element != nil) - testing.expectf(t, pool.out_band_allocations != nil, - "Allocated data with size %v bytes, which is >= out_of_band_size and it should be in pool.out_band_allocations, but isn't!", - ) - - mem.dynamic_pool_destroy(&pool) - testing.expect(t, pool.out_band_allocations == nil) -} - -@(test) -test_dynamic_pool_alloc_aligned :: proc(t: ^testing.T) { - expect_pool_allocation(t, expected_used_bytes = 16, num_bytes = 16, alignment=8) -} - -@(test) -test_dynamic_pool_alloc_unaligned :: proc(t: ^testing.T) { - expect_pool_allocation(t, expected_used_bytes = 8, num_bytes=1, alignment=8) - expect_pool_allocation(t, expected_used_bytes = 16, num_bytes=9, alignment=8) -} - -@(test) -test_dynamic_pool_alloc_out_of_band :: proc(t: ^testing.T) { - expect_pool_allocation_out_of_band(t, num_bytes = 128, out_band_size = 128) - expect_pool_allocation_out_of_band(t, num_bytes = 129, out_band_size = 128) -} - -@(test) -test_intentional_leaks :: proc(t: ^testing.T) { - testing.expect_leaks(t, intentionally_leaky_test, leak_verifier) -} - -// Not tagged with @(test) because it's run through `test_intentional_leaks` -intentionally_leaky_test :: proc(t: ^testing.T) { - a: [dynamic]int - // Intentional leak - append(&a, 42) - - // Intentional bad free - b := uintptr(&a[0]) + 42 - free(rawptr(b)) -} - -leak_verifier :: proc(t: ^testing.T, ta: ^mem.Tracking_Allocator) { - testing.expect_value(t, len(ta.allocation_map), 1) - testing.expect_value(t, len(ta.bad_free_array), 1) -} \ No newline at end of file diff --git a/tests/core/nbio/fs.odin b/tests/core/nbio/fs.odin new file mode 100644 index 000000000..1b10c03c9 --- /dev/null +++ b/tests/core/nbio/fs.odin @@ -0,0 +1,100 @@ +package tests_nbio + +import "core:nbio" +import "core:testing" +import "core:time" +import "core:os" + +@(test) +close_invalid_handle :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + nbio.close(max(nbio.Handle)) + + ev(t, nbio.run(), nil) + } +} + +@(test) +write_read_close :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + @static content := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + @static result: [20]byte + + FILENAME :: "test_write_read_close" + + nbio.open_poly(FILENAME, t, on_open, mode={.Read, .Write, .Create, .Trunc}) + + on_open :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.open.err, nil) + + nbio.write_poly(op.open.handle, 0, content[:], t, on_write) + } + + on_write :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.write.err, nil) + ev(t, op.write.written, len(content)) + + nbio.read_poly(op.write.handle, 0, result[:], t, on_read, all=true) + } + + on_read :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.read.err, nil) + ev(t, op.read.read, len(result)) + ev(t, result, content) + + nbio.close_poly(op.read.handle, t, on_close) + } + + on_close :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.close.err, nil) + os.remove(FILENAME) + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +read_empty_file :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + FILENAME :: "test_read_empty_file" + + handle, err := nbio.open_sync(FILENAME, mode={.Read, .Write, .Create, .Trunc}) + ev(t, err, nil) + + buf: [128]byte + nbio.read_poly(handle, 0, buf[:], t, proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.read.err, nbio.FS_Error.EOF) + ev(t, op.read.read, 0) + + nbio.close_poly(op.read.handle, t, proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.close.err, nil) + os.remove(FILENAME) + }) + }) + + ev(t, nbio.run(), nil) + } +} + +@(test) +read_entire_file :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + nbio.read_entire_file(#file, t, on_read) + + on_read :: proc(t: rawptr, data: []byte, err: nbio.Read_Entire_File_Error) { + t := (^testing.T)(t) + ev(t, err.value, nil) + ev(t, string(data), #load(#file, string)) + delete(data) + } + } +} diff --git a/tests/core/nbio/nbio.odin b/tests/core/nbio/nbio.odin new file mode 100644 index 000000000..6121d1ac7 --- /dev/null +++ b/tests/core/nbio/nbio.odin @@ -0,0 +1,305 @@ +package tests_nbio + +import "core:log" +import "core:nbio" +import "core:testing" +import "core:thread" +import "core:time" +import "core:os" + +ev :: testing.expect_value +e :: testing.expect + +@(deferred_in=event_loop_guard_exit) +event_loop_guard :: proc(t: ^testing.T) -> bool { + err := nbio.acquire_thread_event_loop() + if err == .Unsupported || !nbio.FULLY_SUPPORTED { + log.warn("nbio unsupported, skipping") + return false + } + + ev(t, err, nil) + return true +} + +event_loop_guard_exit :: proc(t: ^testing.T) { + ev(t, nbio.run(), nil) // Could have some things to clean up from a `defer` in the test. + nbio.release_thread_event_loop() +} + +// Tests that all poly variants are correctly passing through arguments, and that +// all procs eventually get their callback called. +// +// This is important because the poly procs are only checked when they are called, +// So this will also catch any typos in their implementations. +@(test) +all_poly_work :: proc(tt: ^testing.T) { + if event_loop_guard(tt) { + testing.set_fail_timeout(tt, time.Minute) + + @static t: ^testing.T + t = tt + + @static n: int + n = 0 + NUM_TESTS :: 39 + + UDP_SOCKET :: max(nbio.UDP_Socket) + TCP_SOCKET :: max(nbio.TCP_Socket) + + tmp, terr := os.create_temp_file("", "tests_nbio_poly*", {.Non_Blocking}) + ev(t, terr, nil) + defer os.close(tmp) + + HANDLE, aerr := nbio.associate_handle(os.fd(tmp)) + ev(t, aerr, nil) + + _buf: [1]byte + buf := _buf[:] + + one :: proc(op: ^nbio.Operation, one: int) { + n += 1 + ev(t, one, 1) + } + + two :: proc(op: ^nbio.Operation, one: int, two: int) { + n += 1 + ev(t, one, 1) + ev(t, two, 2) + } + + three :: proc(op: ^nbio.Operation, one: int, two: int, three: int) { + n += 1 + ev(t, one, 1) + ev(t, two, 2) + ev(t, three, 3) + } + + nbio.accept_poly(TCP_SOCKET, 1, one) + nbio.accept_poly2(TCP_SOCKET, 1, 2, two) + nbio.accept_poly3(TCP_SOCKET, 1, 2, 3, three) + + nbio.close_poly(max(nbio.Handle), 1, one) + nbio.close_poly2(max(nbio.Handle), 1, 2, two) + nbio.close_poly3(max(nbio.Handle), 1, 2, 3, three) + + nbio.dial_poly({nbio.IP4_Address{127, 0, 0, 1}, 0}, 1, one) + nbio.dial_poly2({nbio.IP4_Address{127, 0, 0, 1}, 0}, 1, 2, two) + nbio.dial_poly3({nbio.IP4_Address{127, 0, 0, 1}, 0}, 1, 2, 3, three) + + nbio.recv_poly(TCP_SOCKET, {buf}, 1, one) + nbio.recv_poly2(TCP_SOCKET, {buf}, 1, 2, two) + nbio.recv_poly3(TCP_SOCKET, {buf}, 1, 2, 3, three) + + nbio.send_poly(TCP_SOCKET, {buf}, 1, one) + nbio.send_poly2(TCP_SOCKET, {buf}, 1, 2, two) + nbio.send_poly3(TCP_SOCKET, {buf}, 1, 2, 3, three) + + nbio.sendfile_poly(TCP_SOCKET, HANDLE, 1, one) + nbio.sendfile_poly2(TCP_SOCKET, HANDLE, 1, 2, two) + nbio.sendfile_poly3(TCP_SOCKET, HANDLE, 1, 2, 3, three) + + nbio.read_poly(HANDLE, 0, buf, 1, one) + nbio.read_poly2(HANDLE, 0, buf, 1, 2, two) + nbio.read_poly3(HANDLE, 0, buf, 1, 2, 3, three) + + nbio.write_poly(HANDLE, 0, buf, 1, one) + nbio.write_poly2(HANDLE, 0, buf, 1, 2, two) + nbio.write_poly3(HANDLE, 0, buf, 1, 2, 3, three) + + nbio.next_tick_poly(1, one) + nbio.next_tick_poly2(1, 2, two) + nbio.next_tick_poly3(1, 2, 3, three) + + nbio.timeout_poly(1, 1, one) + nbio.timeout_poly2(1, 1, 2, two) + nbio.timeout_poly3(1, 1, 2, 3, three) + + nbio.poll_poly(TCP_SOCKET, .Receive, 1, one) + nbio.poll_poly2(TCP_SOCKET, .Receive, 1, 2, two) + nbio.poll_poly3(TCP_SOCKET, .Receive, 1, 2, 3, three) + + nbio.open_poly("", 1, one) + nbio.open_poly2("", 1, 2, two) + nbio.open_poly3("", 1, 2, 3, three) + + nbio.stat_poly(HANDLE, 1, one) + nbio.stat_poly2(HANDLE, 1, 2, two) + nbio.stat_poly3(HANDLE, 1, 2, 3, three) + + ev(t, n, 0) // Test that no callbacks are ran before the loop is ticked. + ev(t, nbio.run(), nil) + ev(t, n, NUM_TESTS) // Test that all callbacks have ran. + } +} + +@(test) +two_ops_at_the_same_time :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + server, err := nbio.create_udp_socket(.IP4) + ev(t, err, nil) + defer nbio.close(server) + + berr := nbio.bind(server, {nbio.IP4_Loopback, 0}) + ev(t, berr, nil) + ep, eperr := nbio.bound_endpoint(server) + ev(t, eperr, nil) + + // Server. + { + nbio.poll_poly(server, .Receive, t, on_poll) + + on_poll :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.poll.result, nbio.Poll_Result.Ready) + } + + buf: [128]byte + nbio.recv_poly(server, {buf[:]}, t, on_recv) + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.recv.err, nil) + } + } + + // Client. + { + sock, cerr := nbio.create_udp_socket(.IP4) + ev(t, cerr, nil) + + // Make sure the server would block. + nbio.timeout_poly3(time.Millisecond*10, t, sock, ep.port, on_timeout) + + on_timeout :: proc(op: ^nbio.Operation, t: ^testing.T, sock: nbio.UDP_Socket, port: int) { + nbio.send_poly(sock, {transmute([]byte)string("Hiya")}, t, on_send, {nbio.IP4_Loopback, port}) + } + + on_send :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.send.err, nil) + ev(t, op.send.sent, 4) + + // Do another send after a bit, some backends don't trigger both ops when one was enough to + // use up the socket. + nbio.timeout_poly3(time.Millisecond*10, t, op.send.socket.(nbio.UDP_Socket), op.send.endpoint.port, on_timeout2) + } + + on_timeout2 :: proc(op: ^nbio.Operation, t: ^testing.T, sock: nbio.UDP_Socket, port: int) { + nbio.send_poly(sock, {transmute([]byte)string("Hiya")}, t, on_send2, {nbio.IP4_Loopback, port}) + } + + on_send2 :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.send.err, nil) + ev(t, op.send.sent, 4) + + nbio.close(op.send.socket.(nbio.UDP_Socket)) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +timeout :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + start := time.now() + + nbio.timeout_poly2(time.Millisecond*20, t, start, on_timeout) + + on_timeout :: proc(op: ^nbio.Operation, t: ^testing.T, start: time.Time) { + since := time.since(start) + log.infof("timeout ran after: %v", since) + testing.expect(t, since >= time.Millisecond*19) // A ms grace, for some reason it is sometimes ran after 19.8ms. + if since < 20 { + log.warnf("timeout ran after: %v", since) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +wake_up :: proc(t: ^testing.T) { + testing.set_fail_timeout(t, time.Minute) + if event_loop_guard(t) { + for _ in 0..<2 { + sock, _ := open_next_available_local_port(t) + + // Add an accept, with nobody dialling this should block the event loop forever. + accept := nbio.accept(sock, proc(op: ^nbio.Operation) { + log.error("shouldn't be called") + }) + + // Make sure the accept is in progress. + ev(t, nbio.tick(timeout=0), nil) + + hit: bool + thr := thread.create_and_start_with_poly_data2(nbio.current_thread_event_loop(), &hit, proc(l: ^nbio.Event_Loop, hit: ^bool) { + hit^ = true + nbio.wake_up(l) + }, context) + defer thread.destroy(thr) + + // Should block forever until the thread calling wake_up will make it return. + ev(t, nbio.tick(), nil) + e(t, hit) + + nbio.remove(accept) + nbio.close(sock) + + ev(t, nbio.run(), nil) + ev(t, nbio.tick(timeout=0), nil) + } + } +} + +// Tests that if multiple accepts are queued, and a dial comes in which completes one of them, +// the rest are queued again properly. +@(test) +still_pending :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + defer nbio.close(sock) + + N :: 3 + + State :: struct { + accepted: int, + } + state: State + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T, state: ^State) { + ev(t, op.accept.err, nil) + state.accepted += 1 + nbio.close(op.accept.client) + } + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + nbio.close(op.dial.socket) + } + + for _ in 0.. (sock: net.TCP_Socket, ep: net.Endpoint) { + err: net.Network_Error + sock, err = nbio.listen_tcp({addr, 0}) + if err != nil { + log.errorf("listen_tcp: %v", err, location=loc) + return + } + + ep, err = net.bound_endpoint(sock) + if err != nil { + log.errorf("bound_endpoint: %v", err, location=loc) + } + + return +} + +@(test) +client_and_server_send_recv :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + server, ep := open_next_available_local_port(t) + + CONTENT :: [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} + + State :: struct { + server: net.TCP_Socket, + server_client: net.TCP_Socket, + client: net.TCP_Socket, + recv_buf: [20]byte, + send_buf: [20]byte, + } + + state := State{ + server = server, + send_buf = CONTENT, + } + + close_ok :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.close.err, nil) + } + + // Server + { + nbio.accept_poly2(server, t, &state, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T, state: ^State) { + ev(t, op.accept.err, nil) + + state.server_client = op.accept.client + + log.debugf("accepted connection from: %v", op.accept.client_endpoint) + + nbio.recv_poly2(state.server_client, {state.recv_buf[:]}, t, state, on_recv) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T, state: ^State) { + ev(t, op.recv.err, nil) + ev(t, op.recv.received, 20) + ev(t, state.recv_buf, CONTENT) + + nbio.close_poly(state.server_client, t, close_ok) + nbio.close_poly(state.server, t, close_ok) + } + + ev(t, nbio.tick(0), nil) + } + + // Client + { + nbio.dial_poly2(ep, t, &state, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T, state: ^State) { + ev(t, op.dial.err, nil) + + state.client = op.dial.socket + + nbio.send_poly2(state.client, {state.send_buf[:]}, t, state, on_send) + } + + on_send :: proc(op: ^nbio.Operation, t: ^testing.T, state: ^State) { + ev(t, op.send.err, nil) + ev(t, op.send.sent, 20) + + nbio.close_poly(state.client, t, close_ok) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +close_and_remove_accept :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + server, _ := open_next_available_local_port(t) + + accept := nbio.accept_poly(server, t, proc(_: ^nbio.Operation, t: ^testing.T) { + testing.fail_now(t) + }) + + ev(t, nbio.tick(0), nil) + + nbio.close_poly(server, t, proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.close.err, nil) + }) + + nbio.remove(accept) + ev(t, nbio.run(), nil) + } +} + +// Tests that when a client calls `close` on it's socket, `recv` returns with `0, nil` (connection closed). +@(test) +close_errors_recv :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + server, ep := open_next_available_local_port(t) + + // Server + { + nbio.accept_poly(server, t, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.accept.err, nil) + + bytes := make([]byte, 128, context.temp_allocator) + nbio.recv_poly(op.accept.client, {bytes}, t, on_recv) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.recv.received, 0) + ev(t, op.recv.err, nil) + } + + ev(t, nbio.tick(0), nil) + } + + // Client + { + nbio.dial_poly(ep, t, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + nbio.close_poly(op.dial.socket, t, on_close) + } + + on_close :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.close.err, nil) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +ipv6 :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + server, ep := open_next_available_local_port(t, net.IP6_Loopback) + + nbio.accept_poly(server, t, on_accept) + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.accept.err, nil) + addr, is_ipv6 := op.accept.client_endpoint.address.(net.IP6_Address) + e(t, is_ipv6) + ev(t, addr, net.IP6_Loopback) + e(t, op.accept.client_endpoint.port != 0) + nbio.close(op.accept.client) + nbio.close(op.accept.socket) + } + + nbio.dial_poly(ep, t, on_dial) + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + nbio.close(op.dial.socket) + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +accept_timeout :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, _ := open_next_available_local_port(t) + + hit: bool + nbio.accept_poly2(sock, t, &hit, on_accept, timeout=time.Millisecond) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T, hit: ^bool) { + hit^ = true + ev(t, op.accept.err, net.Accept_Error.Timeout) + nbio.close(op.accept.socket) + } + + ev(t, nbio.run(), nil) + + e(t, hit) + } +} + +@(test) +poll_timeout :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, err := nbio.create_udp_socket(.IP4) + ev(t, err, nil) + berr := nbio.bind(sock, {nbio.IP4_Loopback, 0}) + ev(t, berr, nil) + + nbio.poll_poly(sock, .Receive, t, on_poll, time.Millisecond) + on_poll :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.poll.result, nbio.Poll_Result.Timeout) + } + + ev(t, nbio.run(), nil) + } +} + +/* +This test walks through the scenario where a user wants to `poll` in order to check if some other package (in this case `core:net`), +would be able to do an operation without blocking. + +It also tests whether a poll can be issues when it is already in a ready state. +And it tests big send/recv buffers being handled properly. +*/ +@(test) +poll :: proc(t: ^testing.T) { + if event_loop_guard(t) { +// testing.set_fail_timeout(t, time.Minute) + + can_recv: bool + + sock, ep := open_next_available_local_port(t) + + // Server + { + nbio.accept_poly2(sock, t, &can_recv, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T, can_recv: ^bool) { + ev(t, op.accept.err, nil) + + check_recv :: proc(op: ^nbio.Operation, t: ^testing.T, can_recv: ^bool, client: net.TCP_Socket) { + // Not ready to unblock the client yet, requeue for after 10ms. + if !can_recv^ { + nbio.timeout_poly3(time.Millisecond * 10, t, can_recv, client, check_recv) + return + } + + free_all(context.temp_allocator) + + // Connection was closed by client, close server. + if op.type == .Recv && op.recv.received == 0 && op.recv.err == nil { + nbio.close(client) + return + } + + if op.type == .Recv { + log.debugf("received %M this time", op.recv.received) + } + + // Receive some data to unblock the client, which should complete the poll it does, allowing it to send data again. + buf, mem_err := make([]byte, mem.Gigabyte, context.temp_allocator) + ev(t, mem_err, nil) + nbio.recv_poly3(client, {buf}, t, can_recv, client, check_recv) + } + nbio.timeout_poly3(time.Millisecond * 10, t, can_recv, op.accept.client, check_recv) + } + + ev(t, nbio.tick(0), nil) + } + + // Client + { + nbio.dial_poly2(ep, t, &can_recv, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T, can_recv: ^bool) { + ev(t, op.dial.err, nil) + + // Do a poll even though we know it's ready, so we can test that all implementations can handle that. + nbio.poll_poly2(op.dial.socket, .Send, t, can_recv, on_poll1) + } + + on_poll1 :: proc(op: ^nbio.Operation, t: ^testing.T, can_recv: ^bool) { + ev(t, op.poll.result, nil) + + // Send 4 GB of data, which in my experience causes a Would_Block error because we filled up the internal buffer. + buf, mem_err := make([]byte, mem.Gigabyte*4, context.temp_allocator) + ev(t, mem_err, nil) + + // Use `core:net` as example external code that doesn't care about the event loop. + net.set_blocking(op.poll.socket, false) + n, send_err := net.send(op.poll.socket, buf) + ev(t, send_err, net.TCP_Send_Error.Would_Block) + + log.debugf("blocking after %M", n) + + // Tell the server it can start issueing recv calls, so it unblocks us. + can_recv^ = true + + // Now poll again, when the server reads enough data it should complete, telling us we can send without blocking again. + nbio.poll_poly(op.poll.socket, .Send, t, on_poll2) + } + + on_poll2 :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.poll.result, nil) + + buf: [128]byte + bytes_written, send_err := net.send(op.poll.socket, buf[:]) + ev(t, bytes_written, 128) + ev(t, send_err, nil) + + nbio.close(op.poll.socket.(net.TCP_Socket)) + } + } + + ev(t, nbio.run(), nil) + nbio.close(sock) + ev(t, nbio.run(), nil) + } +} + +@(test) +sendfile :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + CONTENT :: #load(#file) + + sock, ep := open_next_available_local_port(t) + + // Server + { + nbio.accept_poly(sock, t, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.accept.err, nil) + e(t, op.accept.client != 0) + + log.debugf("connection from: %v", op.accept.client_endpoint) + nbio.open_poly3(#file, t, op.accept.socket, op.accept.client, on_open) + } + + on_open :: proc(op: ^nbio.Operation, t: ^testing.T, server, client: net.TCP_Socket) { + ev(t, op.open.err, nil) + + nbio.sendfile_poly2(client, op.open.handle, t, server, on_sendfile) + } + + on_sendfile :: proc(op: ^nbio.Operation, t: ^testing.T, server: net.TCP_Socket) { + ev(t, op.sendfile.err, nil) + ev(t, op.sendfile.sent, len(CONTENT)) + + nbio.close(op.sendfile.file) + nbio.close(op.sendfile.socket) + nbio.close(server) + } + } + + // Client + { + nbio.dial_poly(ep, t, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + + buf := make([]byte, len(CONTENT), context.temp_allocator) + nbio.recv_poly(op.dial.socket, {buf}, t, on_recv, all=true) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.recv.err, nil) + ev(t, op.recv.received, len(CONTENT)) + ev(t, string(op.recv.bufs[0]), string(CONTENT)) + + nbio.close(op.recv.socket.(net.TCP_Socket)) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +vectored :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + + to_send := [?][]byte{ + {'H', 'e', 'l', 'l'}, + {'o', 'p', 'e'}, + {'!'}, + } + + to_recv := [?][]byte{ + {0, 0, 0, 0}, + {0, 0, 0}, + {0}, + } + + // Server + { + nbio.accept_poly2(sock, t, &to_send, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T, to_send: ^[3][]byte) { + ev(t, op.accept.err, nil) + e(t, op.accept.client != 0) + to_send_copy := to_send^[:] + nbio.send_poly3(op.accept.client, to_send_copy, t, op.accept.socket, to_send, on_send) + } + + on_send :: proc(op: ^nbio.Operation, t: ^testing.T, server: net.TCP_Socket, to_send: ^[3][]byte) { + ev(t, op.send.err, nil) + ev(t, op.send.sent, 8) + + expected := to_send^ + for buf, i in expected { + ev(t, string(op.send.bufs[i]), string(buf)) + } + + nbio.close(op.send.socket.(net.TCP_Socket)) + nbio.close(server) + } + } + + // Client + { + nbio.dial_poly3(ep, t, &to_recv, &to_send, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T, to_recv: ^[3][]byte, expected: ^[3][]byte) { + ev(t, op.dial.err, nil) + + to_recv_copy := to_recv^[:] + nbio.recv_poly2(op.dial.socket, to_recv_copy, t, expected, on_recv, all=true) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T, expected: ^[3][]byte) { + ev(t, op.recv.err, nil) + ev(t, op.recv.received, 8) + + expected := expected^[:] + for buf, i in expected { + ev(t, string(op.recv.bufs[i]), string(buf)) + } + + nbio.close(op.recv.socket.(net.TCP_Socket)) + } + } + + ev(t, nbio.run(), nil) + } +} diff --git a/tests/core/nbio/remove.odin b/tests/core/nbio/remove.odin new file mode 100644 index 000000000..063c2cf58 --- /dev/null +++ b/tests/core/nbio/remove.odin @@ -0,0 +1,247 @@ +package tests_nbio + +import "core:nbio" +import "core:net" +import "core:testing" +import "core:time" +import "core:log" + +// Removals are pretty complex. + +@(test) +immediate_remove_of_sendfile :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + + // Server + { + nbio.accept_poly(sock, t, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.accept.err, nil) + e(t, op.accept.client != 0) + + log.debugf("connection from: %v", op.accept.client_endpoint) + nbio.open_poly3(#file, t, op.accept.socket, op.accept.client, on_open) + } + + on_open :: proc(op: ^nbio.Operation, t: ^testing.T, server, client: net.TCP_Socket) { + ev(t, op.open.err, nil) + e(t, op.open.handle != 0) + + sendfile_op := nbio.sendfile_poly2(client, op.open.handle, t, server, on_sendfile) + + // oh no changed my mind. + nbio.remove(sendfile_op) + + nbio.close(op.open.handle) + nbio.close(client) + nbio.close(server) + } + + on_sendfile :: proc(op: ^nbio.Operation, t: ^testing.T, server: net.TCP_Socket) { + log.error("on_sendfile shouldn't be called") + } + } + + // Client + { + nbio.dial_poly(ep, t, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + + buf := make([]byte, 128, context.temp_allocator) + nbio.recv_poly(op.dial.socket, {buf}, t, on_recv) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.recv.err, nil) + + nbio.close(op.recv.socket.(net.TCP_Socket)) + } + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +immediate_remove_of_sendfile_without_stat :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + + // Server + { + nbio.accept_poly(sock, t, on_accept) + + on_accept :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.accept.err, nil) + e(t, op.accept.client != 0) + + log.debugf("connection from: %v", op.accept.client_endpoint) + nbio.open_poly3(#file, t, op.accept.socket, op.accept.client, on_open) + } + + on_open :: proc(op: ^nbio.Operation, t: ^testing.T, server, client: net.TCP_Socket) { + ev(t, op.open.err, nil) + e(t, op.open.handle != 0) + + nbio.stat_poly3(op.open.handle, t, server, client, on_stat) + } + + on_stat :: proc(op: ^nbio.Operation, t: ^testing.T, server, client: net.TCP_Socket) { + ev(t, op.stat.err, nil) + + sendfile_op := nbio.sendfile_poly2(client, op.stat.handle, t, server, on_sendfile, nbytes=int(op.stat.size)) + + // oh no changed my mind. + nbio.remove(sendfile_op) + + nbio.timeout_poly3(time.Millisecond * 10, op.stat.handle, client, server, proc(op: ^nbio.Operation, p1: nbio.Handle, p2, p3: net.TCP_Socket){ + nbio.close(p1) + nbio.close(p2) + nbio.close(p3) + }) + } + + on_sendfile :: proc(op: ^nbio.Operation, t: ^testing.T, server: net.TCP_Socket) { + log.error("on_sendfile shouldn't be called") + } + } + + // Client + { + nbio.dial_poly(ep, t, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + + buf := make([]byte, 128, context.temp_allocator) + nbio.recv_poly(op.dial.socket, {buf}, t, on_recv) + } + + on_recv :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.recv.err, nil) + + nbio.close(op.recv.socket.(net.TCP_Socket)) + } + } + + ev(t, nbio.run(), nil) + } +} + +// Open should free the temporary memory allocated for the path when removed. +// Can't really test that though, so should be checked manually that the internal callback is called but not the external. +@(test) +remove_open :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + open := nbio.open(#file, on_open) + nbio.remove(open) + + on_open :: proc(op: ^nbio.Operation) { + log.error("on_open shouldn't be called") + } + + ev(t, nbio.run(), nil) + } +} + +// Dial should close the socket when removed. +// Can't really test that though, so should be checked manually that the internal callback is called but not the external. +@(test) +remove_dial :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + defer nbio.close(sock) + + dial := nbio.dial(ep, on_dial) + nbio.remove(dial) + + on_dial :: proc(op: ^nbio.Operation) { + log.error("on_dial shouldn't be called") + } + + ev(t, nbio.run(), nil) + } +} + +@(test) +remove_next_tick :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + nt := nbio.next_tick_poly(t, proc(op: ^nbio.Operation, t: ^testing.T) { + log.error("shouldn't be called") + }) + nbio.remove(nt) + + ev(t, nbio.run(), nil) + } +} + +@(test) +remove_timeout :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + hit: bool + timeout := nbio.timeout_poly(time.Second, &hit, proc(_: ^nbio.Operation, hit: ^bool) { + hit^ = true + }) + + nbio.remove(timeout) + + ev(t, nbio.run(), nil) + + e(t, !hit) + } +} + +@(test) +remove_multiple_poll :: proc(t: ^testing.T) { + if event_loop_guard(t) { + testing.set_fail_timeout(t, time.Minute) + + sock, ep := open_next_available_local_port(t) + defer nbio.close(sock) + + hit: bool + + first := nbio.poll(sock, .Receive, on_poll) + nbio.poll_poly2(sock, .Receive, t, &hit, on_poll2) + + on_poll :: proc(op: ^nbio.Operation) { + log.error("shouldn't be called") + } + + on_poll2 :: proc(op: ^nbio.Operation, t: ^testing.T, hit: ^bool) { + ev(t, op.poll.result, nbio.Poll_Result.Ready) + hit^ = true + } + + ev(t, nbio.tick(0), nil) + + nbio.remove(first) + + ev(t, nbio.tick(0), nil) + + nbio.dial_poly(ep, t, on_dial) + + on_dial :: proc(op: ^nbio.Operation, t: ^testing.T) { + ev(t, op.dial.err, nil) + } + + ev(t, nbio.run(), nil) + e(t, hit) + } +} diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin index 0d57bd94a..0b079f5b0 100644 --- a/tests/core/net/test_core_net.odin +++ b/tests/core/net/test_core_net.odin @@ -1,7 +1,7 @@ /* Copyright 2021 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. @@ -10,8 +10,6 @@ A test suite for `core:net` */ -#+build !netbsd -#+build !openbsd #+feature dynamic-literals package test_core_net @@ -593,7 +591,8 @@ test_dns_resolve :: proc(t: ^testing.T) { } ip6, ip6_ok := ep6.address.(net.IP6_Address) - if !testing.expect(t, ip6_ok, "Unable to resolve IP6") { + if !ip6_ok { + log.info("Unable to resolve IP6") return } @@ -624,6 +623,41 @@ test_nonblocking_option :: proc(t: ^testing.T) { } } +// Test that when the server closes it's connection, the client's next receive is `0, nil` to indicate a correct close. +@(test) +test_connection_close :: proc(t: ^testing.T) { + server, listen_err := net.listen_tcp({address=net.IP4_Address{127, 0, 0, 1}, port=0}) + testing.expect_value(t, listen_err, nil) + defer net.close(server) + + server_ep, bound_endpoint_err := net.bound_endpoint(server) + testing.expect_value(t, bound_endpoint_err, nil) + + client, dial_err := net.dial_tcp(server_ep) + testing.expect_value(t, dial_err, nil) + defer net.close(client) + + server_client, _, accept_err := net.accept_tcp(server) + testing.expect_value(t, accept_err, nil) + + send_buf: [512]byte = 1 + sent, send_err := net.send(server_client, send_buf[:]) + testing.expect_value(t, sent, 512) + testing.expect_value(t, send_err, nil) + net.close(server_client) + + recv_buf: [512]byte = --- + received, recv_err := net.recv(client, recv_buf[:]) + testing.expect_value(t, received, 512) + testing.expect_value(t, recv_err, nil) + + testing.expect_value(t, recv_buf, send_buf) + + received, recv_err = net.recv(client, recv_buf[:]) + testing.expect_value(t, received, 0) + testing.expect_value(t, recv_err, nil) +} + @(private) address_to_binstr :: proc(address: net.Address) -> (binstr: string) { switch t in address { diff --git a/tests/core/net/test_core_net_freebsd.odin b/tests/core/net/test_core_net_freebsd.odin index 590db7de0..46feadc3f 100644 --- a/tests/core/net/test_core_net_freebsd.odin +++ b/tests/core/net/test_core_net_freebsd.odin @@ -1,7 +1,7 @@ /* Copyright 2021 Jeroen van Rijn . Copyright 2024 Feoramund . - Made available under Odin's BSD-3 license. + Made available under Odin's license. List of contributors: Jeroen van Rijn: Initial implementation. diff --git a/tests/core/normal.odin b/tests/core/normal.odin index 5bc73bd24..4708ed700 100644 --- a/tests/core/normal.odin +++ b/tests/core/normal.odin @@ -3,9 +3,9 @@ package tests_core import rlibc "core:c/libc" @(init) -download_assets :: proc() { +download_assets :: proc "contextless" () { if rlibc.system("python3 " + ODIN_ROOT + "tests/core/download_assets.py " + ODIN_ROOT + "tests/core/assets") != 0 { - panic("downloading test assets failed!") + panic_contextless("downloading test assets failed!") } } @@ -13,10 +13,12 @@ download_assets :: proc() { @(require) import "c/libc" @(require) import "compress" @(require) import "container" +@(require) import "encoding/base32" @(require) import "encoding/base64" @(require) import "encoding/cbor" @(require) import "encoding/hex" @(require) import "encoding/hxa" +@(require) import "encoding/ini" @(require) import "encoding/json" @(require) import "encoding/uuid" @(require) import "encoding/varint" @@ -26,15 +28,16 @@ download_assets :: proc() { @(require) import "io" @(require) import "math" @(require) import "math/big" +@(require) import "math/bits" @(require) import "math/linalg/glsl" @(require) import "math/noise" @(require) import "math/rand" @(require) import "mem" +@(require) import "nbio" @(require) import "net" @(require) import "odin" @(require) import "os" -@(require) import "os/os2" -@(require) import "path/filepath" +@(require) import "os/old" @(require) import "reflect" @(require) import "runtime" @(require) import "slice" @@ -43,10 +46,11 @@ download_assets :: proc() { @(require) import "sync" @(require) import "sync/chan" @(require) import "sys/posix" +@(require) import "sys/kqueue" @(require) import "sys/windows" @(require) import "text/i18n" @(require) import "text/match" @(require) import "text/regex" @(require) import "thread" @(require) import "time" -@(require) import "unicode" +@(require) import "unicode" \ No newline at end of file diff --git a/tests/core/odin/test_file_tags.odin b/tests/core/odin/test_file_tags.odin index 99a995be5..8c70a4827 100644 --- a/tests/core/odin/test_file_tags.odin +++ b/tests/core/odin/test_file_tags.odin @@ -34,7 +34,7 @@ package main }, }, {// [2] src = ` -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd #+build arm32, arm64 package main `, @@ -45,7 +45,6 @@ package main {os = {.FreeBSD}, arch = runtime.ALL_ODIN_ARCH_TYPES}, {os = {.OpenBSD}, arch = runtime.ALL_ODIN_ARCH_TYPES}, {os = {.NetBSD}, arch = runtime.ALL_ODIN_ARCH_TYPES}, - {os = {.Haiku}, arch = runtime.ALL_ODIN_ARCH_TYPES}, parser.BUILD_KIND_NEWLINE_MARKER, {os = runtime.ALL_ODIN_OS_TYPES, arch = {.arm32}}, {os = runtime.ALL_ODIN_OS_TYPES, arch = {.arm64}}, diff --git a/tests/core/odin/test_parser.odin b/tests/core/odin/test_parser.odin index b4310104f..3fb15d893 100644 --- a/tests/core/odin/test_parser.odin +++ b/tests/core/odin/test_parser.odin @@ -66,3 +66,68 @@ Foo :: bit_field uint { ok := parser.parse_file(&p, &file) testing.expect(t, ok, "bad parse") } + +@test +test_parse_parser :: proc(t: ^testing.T) { + context.allocator = context.temp_allocator + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + pkg, ok := parser.parse_package_from_path(ODIN_ROOT + "core/odin/parser") + + testing.expect(t, ok, "parser.parse_package_from_path failed") + + for key, value in pkg.files { + testing.expectf(t, value.syntax_error_count == 0, "%v should contain zero errors", key) + } +} + +@test +test_parse_stb_image :: proc(t: ^testing.T) { + context.allocator = context.temp_allocator + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + pkg, ok := parser.parse_package_from_path(ODIN_ROOT + "vendor/stb/image") + + testing.expect(t, ok, "parser.parse_package_from_path failed") + + for key, value in pkg.files { + testing.expectf(t, value.syntax_error_count == 0, "%v should contain zero errors", key) + } +} + +@test +test_parse_multiline_ternary :: proc(t: ^testing.T) { + context.allocator = context.temp_allocator + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + file := ast.File{ + fullpath = "test.odin", + src = ` +package main + +my_func :: proc (cond: bool, a: string, b: string) -> string { + out := ( + cond + ? a + : b + ) + return out +} + `, + } + + p := parser.default_parser() + + p.err = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.errorf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + p.warn = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.warnf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + ok := parser.parse_file(&p, &file) + testing.expect(t, ok, "bad parse") + testing.expect(t, file.syntax_error_count == 0, "should contain zero errors") +} diff --git a/tests/core/os/os2/dir.odin b/tests/core/os/dir.odin similarity index 82% rename from tests/core/os/os2/dir.odin rename to tests/core/os/dir.odin index 8ef333219..464abed98 100644 --- a/tests/core/os/os2/dir.odin +++ b/tests/core/os/dir.odin @@ -1,14 +1,14 @@ -package tests_core_os_os2 +package tests_core_os -import os "core:os/os2" -import "core:log" -import "core:slice" -import "core:testing" -import "core:strings" +import "core:os" +import "core:log" +import "core:slice" +import "core:testing" +import "core:strings" @(test) test_read_dir :: proc(t: ^testing.T) { - path, err_join := os.join_path({#directory, "../dir"}, context.allocator) + path, err_join := os.join_path({#directory, "dir"}, context.allocator) defer delete(path) fis, err_read := os.read_all_directory_by_path(path, context.allocator) @@ -17,7 +17,7 @@ test_read_dir :: proc(t: ^testing.T) { slice.sort_by_key(fis, proc(fi: os.File_Info) -> string { return fi.name }) if err_read == .Unsupported { - log.warn("os2 directory functionality is unsupported, skipping test") + log.warn("core:os directory functionality is unsupported, skipping test") return } @@ -34,7 +34,7 @@ test_read_dir :: proc(t: ^testing.T) { @(test) test_walker :: proc(t: ^testing.T) { - path, err := os.join_path({#directory, "../dir"}, context.allocator) + path, err := os.join_path({#directory, "dir"}, context.allocator) defer delete(path) testing.expect_value(t, err, nil) @@ -46,7 +46,7 @@ test_walker :: proc(t: ^testing.T) { @(test) test_walker_file :: proc(t: ^testing.T) { - path, err_join := os.join_path({#directory, "../dir"}, context.allocator) + path, err_join := os.join_path({#directory, "dir"}, context.allocator) defer delete(path) testing.expect_value(t, err_join, nil) @@ -95,7 +95,7 @@ test_walker_internal :: proc(t: ^testing.T, w: ^os.Walker) { } if _, err := os.walker_error(w); err == .Unsupported { - log.warn("os2 directory functionality is unsupported, skipping test") + log.warn("core:os directory functionality is unsupported, skipping test") return } diff --git a/tests/core/os/os2/file.odin b/tests/core/os/file.odin similarity index 70% rename from tests/core/os/os2/file.odin rename to tests/core/os/file.odin index 0152a2008..99ae5b928 100644 --- a/tests/core/os/os2/file.odin +++ b/tests/core/os/file.odin @@ -1,14 +1,13 @@ -package tests_core_os_os2 +package tests_core_os -import os "core:os/os2" -import "core:testing" +import "core:os" +import "core:testing" @(test) test_clone :: proc(t: ^testing.T) { - joined, err := os.join_path({#directory, "file.odin"}, context.temp_allocator) - testing.expect_value(t, err, nil) - f: ^os.File - f, err = os.open(joined) + joined, j_err := os.join_path({#directory, "file.odin"}, context.temp_allocator) + testing.expect_value(t, j_err, nil) + f, err := os.open(joined) testing.expect_value(t, err, nil) testing.expect(t, f != nil) diff --git a/tests/core/os/os.odin b/tests/core/os/old/os.odin similarity index 97% rename from tests/core/os/os.odin rename to tests/core/os/old/os.odin index 1510bad31..9925cf708 100644 --- a/tests/core/os/os.odin +++ b/tests/core/os/old/os.odin @@ -1,8 +1,8 @@ -package test_core_os +package test_core_os_old import "core:c/libc" import win32 "core:sys/windows" -import "core:os" +import os "core:os/old" import "core:slice" import "core:testing" import "core:log" diff --git a/tests/core/os/os2/path.odin b/tests/core/os/path.odin similarity index 55% rename from tests/core/os/os2/path.odin rename to tests/core/os/path.odin index 2cf1f1f1c..3a7611757 100644 --- a/tests/core/os/os2/path.odin +++ b/tests/core/os/path.odin @@ -1,9 +1,11 @@ -package tests_core_os_os2 +package tests_core_os -import os "core:os/os2" -import "core:log" -import "core:testing" -import "core:strings" +import "core:fmt" +import "core:os" +import "core:log" +import "core:testing" +import "core:slice" +import "core:strings" @(test) test_executable :: proc(t: ^testing.T) { @@ -36,47 +38,58 @@ posix_to_dos_path :: proc(path: string) -> string { @(test) test_clean_path :: proc(t: ^testing.T) { Test_Case :: struct{ - path: string, + path: string, expected: string, } - test_cases := [?]Test_Case { - {`../../foo/../../`, `../../..`}, - {`../../foo/..`, `../..`}, - {`../../foo`, `../../foo`}, - {`../..`, `../..`}, - {`.././foo`, `../foo`}, - {`..`, `..`}, - {`.`, `.`}, - {`.foo`, `.foo`}, - {`/../../foo/../../`, `/`}, - {`/../`, `/`}, - {`/..`, `/`}, - {`/`, `/`}, - {`//home/foo/bar/../../`, `/home`}, - {`/a/../..`, `/`}, - {`/a/../`, `/`}, - {`/a/あ`, `/a/あ`}, - {`/a/あ/..`, `/a`}, - {`/あ/a/..`, `/あ`}, - {`/あ/a/../あ`, `/あ/あ`}, - {`/home/../`, `/`}, - {`/home/..`, `/`}, - {`/home/foo/../../usr`, `/usr`}, - {`/home/foo/../..`, `/`}, - {`/home/foo/../`, `/home`}, - {``, `.`}, - {`a/..`, `.`}, - {`a`, `a`}, - {`abc//.//../foo`, `foo`}, - {`foo`, `foo`}, - {`home/foo/bar/../../`, `home`}, - } - when ODIN_OS == .Windows { - for &tc in test_cases { - tc.path = posix_to_dos_path(tc.path) - tc.expected = posix_to_dos_path(tc.expected) + test_cases := [?]Test_Case { + {`W:/odin\examples\demo/demo.odin`, `W:\odin\examples\demo\demo.odin`}, + {`\\server\share\path\file.ext`, `\\server\share\path\file.ext`}, + {`//server\share/path\file.ext`, `\\server\share\path\file.ext`}, + {`/\192.168.0.10\share/path\file.ext`, `\\192.168.0.10\share\path\file.ext`}, + {`\\?\C:/Users/Foo/path\file.ext`, `\\?\C:\Users\Foo\path\file.ext`}, + {`\\?\\localhost\share\file.ext`, `\\?\\localhost\share\file.ext`}, + {`//?\/192.168.0.10\share\file.ext`, `\\?\\192.168.0.10\share\file.ext`}, + {`\\.\PhysicalDrive3`, `\\.\PhysicalDrive3`}, + {`/\./PhysicalDrive3`, `\\.\PhysicalDrive3`}, + {`C:\a\..\..`, `C:\`}, + {`C:\a\..`, `C:\`}, + {`C:\あ/a/..`, `C:\あ`}, + {`C:\あ/a/../あ`, `C:\あ\あ`}, + } + } else { + test_cases := [?]Test_Case { + {`../../foo/../../`, `../../..`}, + {`../../foo/..`, `../..`}, + {`../../foo`, `../../foo`}, + {`../..`, `../..`}, + {`.././foo`, `../foo`}, + {`..`, `..`}, + {`.`, `.`}, + {`.foo`, `.foo`}, + {`/../../foo/../../`, `/`}, + {`/../`, `/`}, + {`/..`, `/`}, + {`/`, `/`}, + {`//home/foo/bar/../../`, `/home`}, + {`/a/../..`, `/`}, + {`/a/../`, `/`}, + {`/a/あ`, `/a/あ`}, + {`/a/あ/..`, `/a`}, + {`/あ/a/..`, `/あ`}, + {`/あ/a/../あ`, `/あ/あ`}, + {`/home/../`, `/`}, + {`/home/..`, `/`}, + {`/home/foo/../../usr`, `/usr`}, + {`/home/foo/../..`, `/`}, + {`/home/foo/../`, `/home`}, + {``, `.`}, + {`a/..`, `.`}, + {`a`, `a`}, + {`abc//.//../foo`, `foo`}, + {`foo`, `foo`}, + {`home/foo/bar/../../`, `home`}, } } @@ -86,6 +99,26 @@ test_clean_path :: proc(t: ^testing.T) { } } +@(test) +replace_path_separators :: proc(t: ^testing.T) { + { + P :: "W:/Odin/core/os/path.odin" + + p1, _ := os.replace_path_separators(P, '😀', context.temp_allocator) + testing.expect_value(t, p1, "W:😀Odin😀core😀os😀path.odin") + + p2, _ := os.replace_path_separators(P, '|', context.temp_allocator) + testing.expect_value(t, p2, "W:|Odin|core|os|path.odin") + } + + { + P :: "W:/恥知らずなフクロウ/path.odin" + + p1, _ := os.replace_path_separators(P, '😀', context.temp_allocator) + testing.expect_value(t, p1, "W:😀恥知らずなフクロウ😀path.odin") + } +} + @(test) test_is_absolute_path :: proc(t: ^testing.T) { when ODIN_OS == .Windows { @@ -323,6 +356,77 @@ test_join_filename :: proc(t: ^testing.T) { } } +Glob_Test :: struct { + pattern: string, + matches: []string, + err: os.Error, +} + +glob_tests := []Glob_Test{ + { + pattern = ODIN_ROOT + "tests/core/os/*/*.txt", + matches = { + ODIN_ROOT + "tests/core/os/dir/b.txt", + }, + err = {}, + }, + { + pattern = ODIN_ROOT + "tests/core/os/*.odin", + matches = { + ODIN_ROOT + "tests/core/os/dir.odin", + ODIN_ROOT + "tests/core/os/file.odin", + ODIN_ROOT + "tests/core/os/path.odin", + ODIN_ROOT + "tests/core/os/process.odin", + }, + err = {}, + }, +} + +@(test) +test_glob :: proc(t: ^testing.T) { + compare_matches :: proc(t: ^testing.T, pattern: string, globbed, expected: []string) { + glob_fold := make([]string, len(globbed), context.temp_allocator) + expect_fold := make([]string, len(globbed), context.temp_allocator) + + for glob, i in globbed { + // If `glob` returned a path in response to a pattern, + // then `match` should consider that path a match, too, + // irrespective of `/` versus `\` presence. + no_match_msg := fmt.tprintf("Expected os.match(%q, %q) to be `true`, got `false`", pattern, glob) + match, _ := os.match(pattern, glob) + + f, _ := strings.replace_all(glob, `\`, `/`, context.temp_allocator) + glob_fold[i] = f + testing.expect(t, match, no_match_msg) + } + + for exp, i in expected { + f, _ := strings.replace_all(exp, `\`, `/`, context.temp_allocator) + expect_fold[i] = f + } + + slice.sort(glob_fold) + slice.sort(expect_fold) + + not_equal_msg := fmt.tprintf("Expected os.glob(%q) to return %v, got %v", pattern, glob_fold, expect_fold) + testing.expect(t, slice.equal(glob_fold, expect_fold), not_equal_msg) + } + + for glob in glob_tests { + globbed, err := os.glob(glob.pattern, context.allocator) + defer { + for file in globbed { + delete(file) + } + delete(globbed) + } + testing.expect_value(t, err, glob.err) + compare_matches(t, glob.pattern, globbed, glob.matches) + } +} + + +// TODO: merge this and `test_split_list` @(test) test_split_path_list :: proc(t: ^testing.T) { Test_Case :: struct { @@ -364,3 +468,115 @@ test_split_path_list :: proc(t: ^testing.T) { } } } + +@(test) +test_split_list :: proc(t: ^testing.T) { + when ODIN_OS == .Windows { + test_split_list_windows(t) + } else { + test_split_list_unix(t) + } +} + +test_split_list_windows :: proc(t: ^testing.T) { + Datum :: struct { + i: int, + v: string, + e: [3]string, + } + @static data := []Datum{ + { 0, "C:\\Odin;C:\\Visual Studio;\"C:\\Some Other\"", + [3]string{"C:\\Odin", "C:\\Visual Studio", "C:\\Some Other"} }, // Issue #1537 + { 1, "a;;b", [3]string{"a", "", "b"} }, + { 2, "a;b;", [3]string{"a", "b", ""} }, + { 3, ";a;b", [3]string{"", "a", "b"} }, + { 4, ";;", [3]string{"", "", ""} }, + { 5, "\"a;b\"c;d;\"f\"", [3]string{"a;bc", "d", "f"} }, + { 6, "\"a;b;c\";d\";e\";f", [3]string{"a;b;c", "d;e", "f"} }, + } + + for d, i in data { + assert(i == d.i, fmt.tprintf("wrong data index: i %d != d.i %d\n", i, d.i)) + r, err := os.split_path_list(d.v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + defer delete_split(r) + testing.expect(t, len(r) == len(d.e), fmt.tprintf("i:%d %s(%s) len(r) %d != len(d.e) %d", i, #procedure, d.v, len(r), len(d.e))) + if len(r) == len(d.e) { + for _, j in r { + testing.expect(t, r[j] == d.e[j], fmt.tprintf("i:%d %s(%v) -> %v[%d] != %v", i, #procedure, d.v, r[j], j, d.e[j])) + } + } + } + + { + v := "" + r, err := os.split_path_list(v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + defer delete_split(r) + testing.expect(t, r == nil, fmt.tprintf("%s(%s) -> %v != nil", #procedure, v, r)) + } + { + v := "a" + r, err := os.split_path_list(v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + defer delete_split(r) + testing.expect(t, len(r) == 1, fmt.tprintf("%s(%s) len(r) %d != 1", #procedure, v, len(r))) + if len(r) == 1 { + testing.expect(t, r[0] == "a", fmt.tprintf("%s(%v) -> %v[0] != a", #procedure, v, r[0])) + } + } +} + +test_split_list_unix :: proc(t: ^testing.T) { + Datum :: struct { + v: string, + e: [3]string, + } + @static data := []Datum{ + { "/opt/butler:/home/fancykillerpanda/Projects/Odin/Odin:/usr/local/sbin", + [3]string{"/opt/butler", "/home/fancykillerpanda/Projects/Odin/Odin", "/usr/local/sbin"} }, // Issue #1537 + { "a::b", [3]string{"a", "", "b"} }, + { "a:b:", [3]string{"a", "b", ""} }, + { ":a:b", [3]string{"", "a", "b"} }, + { "::", [3]string{"", "", ""} }, + { "\"a:b\"c:d:\"f\"", [3]string{"a:bc", "d", "f"} }, + { "\"a:b:c\":d\":e\":f", [3]string{"a:b:c", "d:e", "f"} }, + } + + for d in data { + r, err := os.split_path_list(d.v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + defer delete_split(r) + testing.expectf(t, len(r) == len(d.e), "%s len(r) %d != len(d.e) %d", d.v, len(r), len(d.e)) + if len(r) == len(d.e) { + for _, j in r { + testing.expectf(t, r[j] == d.e[j], "%v -> %v[%d] != %v", d.v, r[j], j, d.e[j]) + } + } + } + + { + v := "" + r, err := os.split_path_list(v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + testing.expectf(t, r == nil, "'%s' -> '%v' != nil", v, r) + } + { + v := "a" + r, err := os.split_path_list(v, context.allocator) + testing.expectf(t, err == nil, "Expected err to be nil, got %v", err) + defer delete_split(r) + testing.expectf(t, len(r) == 1, "'%s' len(r) %d != 1", v, len(r)) + if len(r) == 1 { + testing.expectf(t, r[0] == "a", "'%v' -> %v[0] != a", v, r[0]) + } + } +} + +@(private) +delete_split :: proc(s: []string) { + for part in s { + delete(part) + } + delete(s) +} \ No newline at end of file diff --git a/tests/core/os/os2/process.odin b/tests/core/os/process.odin similarity index 84% rename from tests/core/os/os2/process.odin rename to tests/core/os/process.odin index d7700d201..adb65e95f 100644 --- a/tests/core/os/os2/process.odin +++ b/tests/core/os/process.odin @@ -1,8 +1,9 @@ -package tests_core_os_os2 +#+build !windows +package tests_core_os -import os "core:os/os2" -import "core:log" -import "core:testing" +import "core:os" +import "core:log" +import "core:testing" @(test) test_process_exec :: proc(t: ^testing.T) { diff --git a/tests/core/path/filepath/test_core_filepath.odin b/tests/core/path/filepath/test_core_filepath.odin index f0137f69b..61f87ad02 100644 --- a/tests/core/path/filepath/test_core_filepath.odin +++ b/tests/core/path/filepath/test_core_filepath.odin @@ -33,7 +33,7 @@ test_split_list_windows :: proc(t: ^testing.T) { for d, i in data { assert(i == d.i, fmt.tprintf("wrong data index: i %d != d.i %d\n", i, d.i)) - r := filepath.split_list(d.v) + r, _ := filepath.split_list(d.v, context.allocator) defer delete_split(r) testing.expect(t, len(r) == len(d.e), fmt.tprintf("i:%d %s(%s) len(r) %d != len(d.e) %d", i, #procedure, d.v, len(r), len(d.e))) if len(r) == len(d.e) { @@ -45,13 +45,13 @@ test_split_list_windows :: proc(t: ^testing.T) { { v := "" - r := filepath.split_list(v) + r, _ := filepath.split_list(v, context.allocator) defer delete_split(r) testing.expect(t, r == nil, fmt.tprintf("%s(%s) -> %v != nil", #procedure, v, r)) } { v := "a" - r := filepath.split_list(v) + r, _ := filepath.split_list(v, context.allocator) defer delete_split(r) testing.expect(t, len(r) == 1, fmt.tprintf("%s(%s) len(r) %d != 1", #procedure, v, len(r))) if len(r) == 1 { @@ -77,7 +77,7 @@ test_split_list_unix :: proc(t: ^testing.T) { } for d in data { - r := filepath.split_list(d.v) + r, _ := filepath.split_list(d.v, context.allocator) defer delete_split(r) testing.expectf(t, len(r) == len(d.e), "%s len(r) %d != len(d.e) %d", d.v, len(r), len(d.e)) if len(r) == len(d.e) { @@ -89,12 +89,12 @@ test_split_list_unix :: proc(t: ^testing.T) { { v := "" - r := filepath.split_list(v) + r, _ := filepath.split_list(v, context.allocator) testing.expectf(t, r == nil, "'%s' -> '%v' != nil", v, r) } { v := "a" - r := filepath.split_list(v) + r, _ := filepath.split_list(v, context.allocator) defer delete_split(r) testing.expectf(t, len(r) == 1, "'%s' len(r) %d != 1", v, len(r)) if len(r) == 1 { @@ -109,4 +109,46 @@ delete_split :: proc(s: []string) { delete(part) } delete(s) +} + +@(test) +test_stem :: proc(t: ^testing.T) { + @static stem := [][2]string{ + {"builder.tar.gz", "builder.tar"}, + {"./builder.tar.gz", "builder.tar"}, + {"./builder/", ""}, + } + + @static short_stem := [][2]string{ + {"builder.tar", "builder"}, + {"./builder.tar", "builder"}, + {"./builder/", ""}, + } + + for d in stem { + testing.expect_value(t, filepath.stem(d[0]), d[1]) + } + + for d in short_stem { + testing.expect_value(t, filepath.short_stem(d[0]), d[1]) + } +} + +@(test) +test_dir :: proc(t: ^testing.T) { + when ODIN_OS == .Windows { + @static dirs := [][2]string{ + {"../bin/css", "..\\bin"}, + {"W:/Odin/odin", "W:\\Odin"}, + } + } else { + @static dirs := [][2]string{ + {"../bin/css", "../bin"}, + {"/bin/usr/", "/bin/usr"}, + } + } + + for d in dirs { + testing.expect_value(t, filepath.dir(d[0], context.temp_allocator), d[1]) + } } \ No newline at end of file diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin index 472a5527d..f3559954d 100644 --- a/tests/core/runtime/test_core_runtime.odin +++ b/tests/core/runtime/test_core_runtime.odin @@ -4,6 +4,7 @@ package test_core_runtime import "base:intrinsics" import "core:mem" import "base:runtime" +import "core:slice" import "core:testing" // Tests that having space for the allocation, but not for the allocation and alignment @@ -59,26 +60,26 @@ test_temp_allocator_returns_correct_size :: proc(t: ^testing.T) { @(test) test_init_cap_map_dynarray :: proc(t: ^testing.T) { - m1 := make(map[int]string) - defer delete(m1) - testing.expect(t, cap(m1) == 0) - testing.expect(t, m1.allocator.procedure == context.allocator.procedure) + m1 := make(map[int]string) + defer delete(m1) + testing.expect(t, cap(m1) == 0) + testing.expect(t, m1.allocator.procedure == context.allocator.procedure) - ally := context.temp_allocator - m2 := make(map[int]string, ally) - defer delete(m2) - testing.expect(t, cap(m2) == 0) - testing.expect(t, m2.allocator.procedure == ally.procedure) + ally := context.temp_allocator + m2 := make(map[int]string, ally) + defer delete(m2) + testing.expect(t, cap(m2) == 0) + testing.expect(t, m2.allocator.procedure == ally.procedure) - d1 := make([dynamic]string) - defer delete(d1) - testing.expect(t, cap(d1) == 0) - testing.expect(t, d1.allocator.procedure == context.allocator.procedure) + d1 := make([dynamic]string) + defer delete(d1) + testing.expect(t, cap(d1) == 0) + testing.expect(t, d1.allocator.procedure == context.allocator.procedure) - d2 := make([dynamic]string, ally) - defer delete(d2) - testing.expect(t, cap(d2) == 0) - testing.expect(t, d2.allocator.procedure == ally.procedure) + d2 := make([dynamic]string, ally) + defer delete(d2) + testing.expect(t, cap(d2) == 0) + testing.expect(t, d2.allocator.procedure == ally.procedure) } @(test) @@ -177,3 +178,250 @@ test_map_get :: proc(t: ^testing.T) { check(t, m) } } + +@(test) +test_soa_array_resize :: proc(t: ^testing.T) { + + V :: struct {x: int, y: u8} + + array := make(#soa[dynamic]V, 0, 2) + defer delete(array) + + append(&array, V{1, 2}, V{3, 4}) + + testing.expect_value(t, len(array), 2) + testing.expect_value(t, array[0], V{1, 2}) + testing.expect_value(t, array[1], V{3, 4}) + + resize(&array, 1) + + testing.expect_value(t, len(array), 1) + testing.expect_value(t, array[0], V{1, 2}) + + resize(&array, 2) + + testing.expect_value(t, len(array), 2) + testing.expect_value(t, array[0], V{1, 2}) + testing.expect_value(t, array[1], V{0, 0}) + + resize(&array, 0) + resize(&array, 3) + + testing.expect_value(t, len(array), 3) + testing.expect_value(t, array[0], V{0, 0}) + testing.expect_value(t, array[1], V{0, 0}) + testing.expect_value(t, array[2], V{0, 0}) +} + +@(test) +test_soa_make_len :: proc(t: ^testing.T) { + + array, err := make(#soa[dynamic][2]int, 2) + defer delete(array) + array[0] = [2]int{1, 2} + array[1] = [2]int{3, 4} + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 2) + + testing.expect_value(t, array[0], [2]int{1, 2}) + testing.expect_value(t, array[1], [2]int{3, 4}) +} + +@(test) +test_soa_array_allocator_resize :: proc(t: ^testing.T) { + + arena: runtime.Arena + context.allocator = runtime.arena_allocator(&arena) + defer runtime.arena_destroy(&arena) + + // |1 3 _ 2 4 _| + // |1 3 _ _ 2 4 _ _| + + array, err := make(#soa[dynamic][2]int, 2, 3) + defer delete(array) + array[0] = [2]int{1, 2} + array[1] = [2]int{3, 4} + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 3) + + err = resize(&array, 4) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) + + testing.expect_value(t, array[0], [2]int{1, 2}) + testing.expect_value(t, array[1], [2]int{3, 4}) + testing.expect_value(t, array[2], [2]int{0, 0}) + testing.expect_value(t, array[3], [2]int{0, 0}) +} + + +@(test) +test_soa_array_allocator_resize_overlapping :: proc(t: ^testing.T) { + + arena: runtime.Arena + context.allocator = runtime.arena_allocator(&arena) + defer runtime.arena_destroy(&arena) + + // |1 4 2 5 3 6| + // |1 4 _ _ 2 5 _ _ 3 6 _ _| + + array, err := make(#soa[dynamic][3]int, 2, 2) + defer delete(array) + array[0] = [3]int{1, 2, 3} + array[1] = [3]int{4, 5, 6} + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 2) + + err = resize(&array, 4) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) + + testing.expect_value(t, array[0], [3]int{1, 2, 3}) + testing.expect_value(t, array[1], [3]int{4, 5, 6}) + testing.expect_value(t, array[2], [3]int{0, 0, 0}) + testing.expect_value(t, array[3], [3]int{0, 0, 0}) +} + +@(test) +test_soa_array_inject_at_elem :: proc(t: ^testing.T) { + + V :: struct {a: u8, b: f32} + + array := make(#soa[dynamic]V, 0, 2) + defer delete(array) + + append(&array, V{1, 1.5}, V{2, 2.5}, V{3, 3.5}) + + expect_inject(t, &array, 0, {0, 0.5}, {{0, 0.5}, {1, 1.5}, {2, 2.5}, {3, 3.5}}) + expect_inject(t, &array, 2, {5, 5.5}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {2, 2.5}, {3, 3.5}}) + expect_inject(t, &array, 5, {9, 9.5}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}}) + + expect_inject :: proc(t: ^testing.T, arr: ^#soa[dynamic]V, index: int, arg: V, expected_slice: []V) { + ok, err := inject_at_soa(arr, index, arg) + testing.expectf(t, ok == true, "Injection of %v at index %d failed", arg, index) + testing.expectf(t, err == nil, "Injection allocation of %v at index %d failed: %v", arg, index, err) + equals := len(arr) == len(expected_slice) + for e, i in expected_slice { + if arr[i] != e { + equals = false + break + } + } + testing.expectf(t, equals, "After injection of %v at index %d, expected array to be\n&%v, got\n%v", arg, index, expected_slice, arr) + } +} + +@(test) +test_soa_array_inject_at_elems :: proc(t: ^testing.T) { + + V :: struct {a: u8, b: f32} + + array := make(#soa[dynamic]V, 0, 2) + defer delete(array) + + append(&array, V{1, 1.5}, V{2, 2.5}, V{3, 3.5}) + + expect_inject(t, &array, 0, {{0, 0.5}}, {{0, 0.5}, {1, 1.5}, {2, 2.5}, {3, 3.5}}) + expect_inject(t, &array, 2, {{5, 5.5}, {6, 6.5}}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}}) + expect_inject(t, &array, 6, {{9, 9.5}, {10, 10.5}}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}, {10, 10.5}}) + expect_inject(t, &array, 6, {}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}, {10, 10.5}}) + + expect_inject :: proc(t: ^testing.T, arr: ^#soa[dynamic]V, index: int, args: []V, expected_slice: []V) { + ok, err := inject_at_soa(arr, index, ..args) + testing.expectf(t, ok == true, "Injection of %v at index %d failed", args, index) + testing.expectf(t, err == nil, "Injection allocation of %v at index %d failed: %v", args, index, err) + equals := len(arr) == len(expected_slice) + for e, i in expected_slice { + if arr[i] != e { + equals = false + break + } + } + testing.expectf(t, equals, "After injection of %v at index %d, expected array to be\n&%v, got\n%v", args, index, expected_slice, arr) + } +} + +@(test) +test_memory_equal :: proc(t: ^testing.T) { + data: [256]u8 + cmp: [256]u8 + + slice.fill(data[:], 0xAA) + slice.fill(cmp[:], 0xAA) + + for offset in 0.. (n: int) { + _len := min(len(a), len(b)) + + // Scan for matches including partial codepoints. + #no_bounds_check for n < _len && a[n] == b[n] { + n += 1 + } + + // Now scan to ignore partial codepoints. + if n > 0 { + s := a[:n] + n = 0 + for { + r0, w := utf8.decode_rune(s[n:]) + if r0 != utf8.RUNE_ERROR { + n += w + } else { + break + } + } + } + return + } + + cases := [][2]string{ + {"Hellope, there!", "Hellope, world!"}, + {"Hellope, there!", "Foozle"}, + {"Hellope, there!", "Hell"}, + {"Hellope! 🦉", "Hellope! 🦉"}, + } + + for v in cases { + p_scalar := prefix_length(v[0], v[1]) + p_simd := strings.prefix_length(v[0], v[1]) + testing.expect_value(t, p_simd, p_scalar) + + s := v[0] + for len(s) > 0 { + p_scalar = prefix_length(v[0], s) + p_simd = strings.prefix_length(v[0], s) + testing.expect_value(t, p_simd, p_scalar) + s = s[:len(s) - 1] + } + } +} \ No newline at end of file diff --git a/tests/core/sync/chan/test_core_sync_chan.odin b/tests/core/sync/chan/test_core_sync_chan.odin index 9b8d9b354..8ede19c7d 100644 --- a/tests/core/sync/chan/test_core_sync_chan.odin +++ b/tests/core/sync/chan/test_core_sync_chan.odin @@ -4,6 +4,7 @@ import "base:runtime" import "base:intrinsics" import "core:log" import "core:math/rand" +import "core:sync" import "core:sync/chan" import "core:testing" import "core:thread" @@ -33,18 +34,16 @@ Comm :: struct { BUFFER_SIZE :: 8 MAX_RAND :: 32 FAIL_TIME :: 1 * time.Second -SLEEP_TIME :: 1 * time.Millisecond + +// Synchronizes try_select tests that require access to global state. +test_lock: sync.Mutex +__global_context_for_test: rawptr comm_client :: proc(th: ^thread.Thread) { data := cast(^Comm)th.data - manual_buffering := data.manual_buffering n: i64 - for manual_buffering && !chan.can_recv(data.host) { - thread.yield() - } - recv_loop: for msg in chan.recv(data.host) { #partial switch msg.type { case .Add: n += msg.i @@ -56,14 +55,6 @@ comm_client :: proc(th: ^thread.Thread) { case: panic("Unknown message type for client.") } - - for manual_buffering && !chan.can_recv(data.host) { - thread.yield() - } - } - - for manual_buffering && !chan.can_send(data.host) { - thread.yield() } chan.send(data.client, Message{.Result, n}) @@ -72,9 +63,6 @@ comm_client :: proc(th: ^thread.Thread) { send_messages :: proc(t: ^testing.T, host: chan.Chan(Message), manual_buffering: bool = false) -> (expected: i64) { expected = 1 - for manual_buffering && !chan.can_send(host) { - thread.yield() - } chan.send(host, Message{.Add, 1}) log.debug(Message{.Add, 1}) @@ -96,9 +84,6 @@ send_messages :: proc(t: ^testing.T, host: chan.Chan(Message), manual_buffering: expected /= msg.i } - for manual_buffering && !chan.can_send(host) { - thread.yield() - } if manual_buffering { testing.expect(t, chan.len(host) == 0) } @@ -107,9 +92,6 @@ send_messages :: proc(t: ^testing.T, host: chan.Chan(Message), manual_buffering: log.debug(msg) } - for manual_buffering && !chan.can_send(host) { - thread.yield() - } chan.send(host, Message{.End, 0}) log.debug(Message{.End, 0}) chan.close(host) @@ -148,18 +130,15 @@ test_chan_buffered :: proc(t: ^testing.T) { expected := send_messages(t, comm.host, manual_buffering = false) - // Sleep so we can give the other thread enough time to buffer its message. - time.sleep(SLEEP_TIME) - - testing.expect_value(t, chan.len(comm.client), 1) - result, ok := chan.try_recv(comm.client) - - // One more sleep to ensure it has enough time to close. - time.sleep(SLEEP_TIME) - - testing.expect_value(t, chan.is_closed(comm.client), true) + result, ok := chan.recv(comm.client) testing.expect_value(t, ok, true) testing.expect_value(t, result.i, expected) + + // Wait for channel to close. + _, ok = chan.recv(comm.client) + testing.expect(t, !ok, "channel should have been closed") + + testing.expect_value(t, chan.is_closed(comm.client), true) log.debug(result, expected) // Make sure sending to closed channels fails. @@ -171,6 +150,8 @@ test_chan_buffered :: proc(t: ^testing.T) { _, ok = chan.recv(comm.client); testing.expect_value(t, ok, false) _, ok = chan.try_recv(comm.host); testing.expect_value(t, ok, false) _, ok = chan.try_recv(comm.client); testing.expect_value(t, ok, false) + + thread.join(reckoner) } @test @@ -193,6 +174,10 @@ test_chan_unbuffered :: proc(t: ^testing.T) { testing.expect(t, !chan.is_buffered(comm.client)) testing.expect(t, chan.is_unbuffered(comm.host)) testing.expect(t, chan.is_unbuffered(comm.client)) + testing.expect(t, !chan.can_send(comm.host)) + testing.expect(t, !chan.can_send(comm.client)) + testing.expect(t, !chan.can_recv(comm.host)) + testing.expect(t, !chan.can_recv(comm.client)) testing.expect_value(t, chan.len(comm.host), 0) testing.expect_value(t, chan.len(comm.client), 0) testing.expect_value(t, chan.cap(comm.host), 0) @@ -203,25 +188,16 @@ test_chan_unbuffered :: proc(t: ^testing.T) { reckoner.data = &comm thread.start(reckoner) - for !chan.can_send(comm.client) { - thread.yield() - } - expected := send_messages(t, comm.host) testing.expect_value(t, chan.is_closed(comm.host), true) - for !chan.can_recv(comm.client) { - thread.yield() - } - - result, ok := chan.try_recv(comm.client) + result, ok := chan.recv(comm.client) testing.expect_value(t, ok, true) testing.expect_value(t, result.i, expected) log.debug(result, expected) - // Sleep so we can give the other thread enough time to close its side - // after we've received its message. - time.sleep(SLEEP_TIME) + _, ok2 := chan.recv(comm.client) + testing.expect(t, !ok2, "read of closed channel should return false") testing.expect_value(t, chan.is_closed(comm.client), true) @@ -234,6 +210,8 @@ test_chan_unbuffered :: proc(t: ^testing.T) { _, ok = chan.recv(comm.client); testing.expect_value(t, ok, false) _, ok = chan.try_recv(comm.host); testing.expect_value(t, ok, false) _, ok = chan.try_recv(comm.client); testing.expect_value(t, ok, false) + + thread.join(reckoner) } @test @@ -250,6 +228,198 @@ test_full_buffered_closed_chan_deadlock :: proc(t: ^testing.T) { testing.expect(t, !chan.send(ch, 32)) } +// Ensures that if a thread is doing a blocking send and the channel +// is closed, it will report false to indicate a failure to complete. +@test +test_fail_blocking_send_on_close :: proc(t: ^testing.T) { + ch, ch_alloc_err := chan.create(chan.Chan(int), context.allocator) + assert(ch_alloc_err == nil, "allocation failed") + defer chan.destroy(ch) + + sender := thread.create_and_start_with_poly_data(ch, proc(ch: chan.Chan(int)) { + assert(!chan.send(ch, 42)) + }) + + for !chan.can_recv(ch) { + thread.yield() + } + + testing.expect(t, chan.close(ch)) + thread.join(sender) + thread.destroy(sender) +} + +// Ensures that if a thread is doing a blocking read and the channel +// is closed, it will report false to indicate a failure to complete. +@test +test_fail_blocking_recv_on_close :: proc(t: ^testing.T) { + ch, ch_alloc_err := chan.create(chan.Chan(int), context.allocator) + assert(ch_alloc_err == nil, "allocation failed") + defer chan.destroy(ch) + + reader := thread.create_and_start_with_poly_data(ch, proc(ch: chan.Chan(int)) { + v, ok := chan.recv(ch) + assert(!ok) + assert(v == 0) + }) + + for !chan.can_send(ch) { + thread.yield() + } + + testing.expect(t, chan.close(ch)) + thread.join(reader) + thread.destroy(reader) +} + +// Ensures that try_send for unbuffered channels works as expected. +// If 1 reader of a channel, and 3 try_senders, only one of the senders +// will succeed and none of them will block. +@test +test_unbuffered_try_send_chan_contention :: proc(t: ^testing.T) { + testing.set_fail_timeout(t, FAIL_TIME) + + start, start_alloc_err := chan.create(chan.Chan(any), context.allocator) + assert(start_alloc_err == nil, "allocation failed") + defer chan.destroy(start) + + trigger, trigger_alloc_err := chan.create(chan.Chan(any), context.allocator) + assert(trigger_alloc_err == nil, "allocation failed") + defer chan.destroy(trigger) + + results, results_alloc_err := chan.create(chan.Chan(int), 3, context.allocator) + assert(results_alloc_err == nil, "allocation failed") + defer chan.destroy(results) + + ch, ch_alloc_err := chan.create(chan.Chan(int), context.allocator) + assert(ch_alloc_err == nil, "allocation failed") + defer chan.destroy(ch) + + // There are no readers or writers, so calling recv or send would block! + testing.expect_value(t, chan.can_send(ch), false) + testing.expect_value(t, chan.can_recv(ch), false) + + // Non-blocking operations should not block, and should return false. + testing.expect_value(t, chan.try_send(ch, -1), false) + if v, ok := chan.try_recv(ch); ok { + testing.expect_value(t, ok, false) + testing.expect_value(t, v, 0) + } + + // Spinup several threads contending to send on an unbuffered channel. + contenders: [3]^thread.Thread + wait: sync.Wait_Group + + for ii in 0.. +#include +#include + +int main(int argc, char *argv[]) +{ + printf("kevent %zu %zu\n", sizeof(struct kevent), _Alignof(struct kevent)); + printf("kevent.ident %zu\n", offsetof(struct kevent, ident)); + printf("kevent.filter %zu\n", offsetof(struct kevent, filter)); + printf("kevent.flags %zu\n", offsetof(struct kevent, flags)); + printf("kevent.fflags %zu\n", offsetof(struct kevent, fflags)); + printf("kevent.data %zu\n", offsetof(struct kevent, data)); + printf("kevent.udata %zu\n", offsetof(struct kevent, udata)); + + printf("EV_ADD %d\n", EV_ADD); + printf("EV_DELETE %d\n", EV_DELETE); + printf("EV_ENABLE %d\n", EV_ENABLE); + printf("EV_DISABLE %d\n", EV_DISABLE); + printf("EV_ONESHOT %d\n", EV_ONESHOT); + printf("EV_CLEAR %d\n", EV_CLEAR); + printf("EV_RECEIPT %d\n", EV_RECEIPT); + printf("EV_DISPATCH %d\n", EV_DISPATCH); + printf("EV_ERROR %d\n", EV_ERROR); + printf("EV_EOF %d\n", EV_EOF); + + printf("EVFILT_READ %d\n", EVFILT_READ); + printf("EVFILT_WRITE %d\n", EVFILT_WRITE); + printf("EVFILT_AIO %d\n", EVFILT_AIO); + printf("EVFILT_VNODE %d\n", EVFILT_VNODE); + printf("EVFILT_PROC %d\n", EVFILT_PROC); + printf("EVFILT_SIGNAL %d\n", EVFILT_SIGNAL); + printf("EVFILT_TIMER %d\n", EVFILT_TIMER); + printf("EVFILT_USER %d\n", EVFILT_USER); + + printf("NOTE_SECONDS %u\n", NOTE_SECONDS); + printf("NOTE_USECONDS %u\n", NOTE_USECONDS); + printf("NOTE_NSECONDS %u\n", NOTE_NSECONDS); +#if defined(NOTE_ABSOLUTE) + printf("NOTE_ABSOLUTE %u\n", NOTE_ABSOLUTE); +#else + printf("NOTE_ABSOLUTE %u\n", NOTE_ABSTIME); +#endif + + printf("NOTE_LOWAT %u\n", NOTE_LOWAT); + + printf("NOTE_DELETE %u\n", NOTE_DELETE); + printf("NOTE_WRITE %u\n", NOTE_WRITE); + printf("NOTE_EXTEND %u\n", NOTE_EXTEND); + printf("NOTE_ATTRIB %u\n", NOTE_ATTRIB); + printf("NOTE_LINK %u\n", NOTE_LINK); + printf("NOTE_RENAME %u\n", NOTE_RENAME); + printf("NOTE_REVOKE %u\n", NOTE_REVOKE); + + printf("NOTE_EXIT %u\n", NOTE_EXIT); + printf("NOTE_FORK %u\n", NOTE_FORK); + printf("NOTE_EXEC %u\n", NOTE_EXEC); + + printf("NOTE_TRIGGER %u\n", NOTE_TRIGGER); + printf("NOTE_FFAND %u\n", NOTE_FFAND); + printf("NOTE_FFOR %u\n", NOTE_FFOR); + printf("NOTE_FFCOPY %u\n", NOTE_FFCOPY); + return 0; +} diff --git a/tests/core/sys/kqueue/structs/structs.odin b/tests/core/sys/kqueue/structs/structs.odin new file mode 100644 index 000000000..4886f63e4 --- /dev/null +++ b/tests/core/sys/kqueue/structs/structs.odin @@ -0,0 +1,58 @@ +package main + +import "core:fmt" +import "core:sys/kqueue" + +main :: proc() { + fmt.println("kevent", size_of(kqueue.KEvent), align_of(kqueue.KEvent)) + fmt.println("kevent.ident", offset_of(kqueue.KEvent, ident)) + fmt.println("kevent.filter", offset_of(kqueue.KEvent, filter)) + fmt.println("kevent.flags", offset_of(kqueue.KEvent, flags)) + fmt.println("kevent.fflags", offset_of(kqueue.KEvent, fflags)) + fmt.println("kevent.data", offset_of(kqueue.KEvent, data)) + fmt.println("kevent.udata", offset_of(kqueue.KEvent, udata)) + + fmt.println("EV_ADD", transmute(kqueue._Flags_Backing)kqueue.Flags{.Add}) + fmt.println("EV_DELETE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Delete}) + fmt.println("EV_ENABLE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Enable}) + fmt.println("EV_DISABLE", transmute(kqueue._Flags_Backing)kqueue.Flags{.Disable}) + fmt.println("EV_ONESHOT", transmute(kqueue._Flags_Backing)kqueue.Flags{.One_Shot}) + fmt.println("EV_CLEAR", transmute(kqueue._Flags_Backing)kqueue.Flags{.Clear}) + fmt.println("EV_RECEIPT", transmute(kqueue._Flags_Backing)kqueue.Flags{.Receipt}) + fmt.println("EV_DISPATCH", transmute(kqueue._Flags_Backing)kqueue.Flags{.Dispatch}) + fmt.println("EV_ERROR", transmute(kqueue._Flags_Backing)kqueue.Flags{.Error}) + fmt.println("EV_EOF", transmute(kqueue._Flags_Backing)kqueue.Flags{.EOF}) + + fmt.println("EVFILT_READ", int(kqueue.Filter.Read)) + fmt.println("EVFILT_WRITE", int(kqueue.Filter.Write)) + fmt.println("EVFILT_AIO", int(kqueue.Filter.AIO)) + fmt.println("EVFILT_VNODE", int(kqueue.Filter.VNode)) + fmt.println("EVFILT_PROC", int(kqueue.Filter.Proc)) + fmt.println("EVFILT_SIGNAL", int(kqueue.Filter.Signal)) + fmt.println("EVFILT_TIMER", int(kqueue.Filter.Timer)) + fmt.println("EVFILT_USER", int(kqueue.Filter.User)) + + fmt.println("NOTE_SECONDS", transmute(u32)kqueue.Timer_Flags{.Seconds}) + fmt.println("NOTE_USECONDS", transmute(u32)kqueue.Timer_Flags{.USeconds}) + fmt.println("NOTE_NSECONDS", transmute(u32)kqueue.TIMER_FLAGS_NSECONDS) + fmt.println("NOTE_ABSOLUTE", transmute(u32)kqueue.Timer_Flags{.Absolute}) + + fmt.println("NOTE_LOWAT", transmute(u32)kqueue.RW_Flags{.Low_Water_Mark}) + + fmt.println("NOTE_DELETE", transmute(u32)kqueue.VNode_Flags{.Delete}) + fmt.println("NOTE_WRITE", transmute(u32)kqueue.VNode_Flags{.Write}) + fmt.println("NOTE_EXTEND", transmute(u32)kqueue.VNode_Flags{.Extend}) + fmt.println("NOTE_ATTRIB", transmute(u32)kqueue.VNode_Flags{.Attrib}) + fmt.println("NOTE_LINK", transmute(u32)kqueue.VNode_Flags{.Link}) + fmt.println("NOTE_RENAME", transmute(u32)kqueue.VNode_Flags{.Rename}) + fmt.println("NOTE_REVOKE", transmute(u32)kqueue.VNode_Flags{.Revoke}) + + fmt.println("NOTE_EXIT", transmute(u32)kqueue.Proc_Flags{.Exit}) + fmt.println("NOTE_FORK", transmute(u32)kqueue.Proc_Flags{.Fork}) + fmt.println("NOTE_EXEC", transmute(u32)kqueue.Proc_Flags{.Exec}) + + fmt.println("NOTE_TRIGGER", transmute(u32)kqueue.User_Flags{.Trigger}) + fmt.println("NOTE_FFAND", transmute(u32)kqueue.User_Flags{.FFAnd}) + fmt.println("NOTE_FFOR", transmute(u32)kqueue.User_Flags{.FFOr}) + fmt.println("NOTE_FFCOPY", transmute(u32)kqueue.USER_FLAGS_COPY) +} diff --git a/tests/core/sys/posix/posix.odin b/tests/core/sys/posix/posix.odin index 772190a3a..9b864af39 100644 --- a/tests/core/sys/posix/posix.odin +++ b/tests/core/sys/posix/posix.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd package tests_core_posix import "core:log" @@ -21,7 +21,7 @@ test_arpa_inet :: proc(t: ^testing.T) { dst: [posix.INET6_ADDRSTRLEN]byte } - res := posix.inet_pton(af, src, &addr, size_of(addr)) + res := posix.inet_pton(af, src, &addr) testing.expect_value(t, res, expect, loc) if expect == .SUCCESS { @@ -65,21 +65,12 @@ test_dirent :: proc(t: ^testing.T) { for entry in entries { defer posix.free(entry) - when ODIN_OS == .Haiku { - stat: posix.stat_t - posix.stat(cstring(raw_data(entry.d_name[:])), &stat) - - if !posix.S_ISREG(stat.st_mode) { - continue - } - } else { - if entry.d_type != .REG { - continue - } + if entry.d_type != .REG { + continue } name := string(cstring(raw_data(entry.d_name[:]))) - testing.expectf(t, name in test_map, "%v in %v", name, test_map) + testing.expectf(t, name in test_map, "scandir: %v in %v", name, test_map) } } @@ -95,21 +86,12 @@ test_dirent :: proc(t: ^testing.T) { break } - when ODIN_OS == .Haiku { - stat: posix.stat_t - posix.stat(cstring(raw_data(entry.d_name[:])), &stat) - - if !posix.S_ISREG(stat.st_mode) { - continue - } - } else { - if entry.d_type != .REG { - continue - } + if entry.d_type != .REG { + continue } name := string(cstring(raw_data(entry.d_name[:]))) - testing.expectf(t, name in test_map, "%v in %v", name, test_map) + testing.expectf(t, name in test_map, "readdir: %v in %v", name, test_map) } } } @@ -165,8 +147,8 @@ test_libgen :: proc(t: ^testing.T) { { "///", "/", "/" }, { "/usr/", "/", "usr" }, { "/usr/lib", "/usr", "lib" }, - { "//usr//lib//", "//usr" + ("/" when ODIN_OS == .Haiku else ""), "lib" }, - { "/home//dwc//test", "/home//dwc" + ("/" when ODIN_OS == .Haiku else ""), "test" }, + { "//usr//lib//", "//usr", "lib" }, + { "/home//dwc//test", "/home//dwc", "test" }, } for test in tests { @@ -214,15 +196,13 @@ test_stat :: proc(t: ^testing.T) { stat: posix.stat_t testing.expect_value(t, posix.stat(#file, &stat), posix.result.OK) testing.expect(t, posix.S_ISREG(stat.st_mode)) - testing.expect_value(t, stat.st_mode, posix.mode_t{.IROTH, .IRGRP, .IRUSR, .IWUSR, .IFREG}) - CONTENT := #load(#file) testing.expect_value(t, stat.st_size, posix.off_t(len(CONTENT))) } @(test) test_pthreads :: proc(t: ^testing.T) { - testing.set_fail_timeout(t, time.Second) + testing.set_fail_timeout(t, 3 * time.Second) NTHREADS :: 3 thread_ids: [NTHREADS]posix.pthread_t @@ -261,7 +241,4 @@ open_permissions :: proc(t: ^testing.T) { stat: posix.stat_t res := posix.fstat(fd, &stat) testing.expectf(t, res == .OK, "failed to stat: %v", posix.strerror()) - - stat.st_mode -= posix.S_IFMT - testing.expect_value(t, stat.st_mode, in_mode) } diff --git a/tests/core/sys/posix/structs.odin b/tests/core/sys/posix/structs.odin index 66b7cb0e1..a0e8fea99 100644 --- a/tests/core/sys/posix/structs.odin +++ b/tests/core/sys/posix/structs.odin @@ -1,4 +1,4 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd package tests_core_posix import "core:log" diff --git a/tests/core/sys/posix/structs/structs.c b/tests/core/sys/posix/structs/structs.c index 995c1a8c0..fc8e1eb44 100644 --- a/tests/core/sys/posix/structs/structs.c +++ b/tests/core/sys/posix/structs/structs.c @@ -12,9 +12,7 @@ #include #include -#ifndef __HAIKU__ #include -#endif #include #include @@ -31,9 +29,7 @@ #include #include -#ifndef __HAIKU__ #include -#endif #include @@ -74,12 +70,11 @@ int main(int argc, char *argv[]) printf("ai_canonname %zu\n", offsetof(struct addrinfo, ai_canonname)); printf("pollfd %zu %zu\n", sizeof(struct pollfd), _Alignof(struct pollfd)); + printf("nfds_t %zu %zu\n", sizeof(nfds_t), _Alignof(nfds_t)); printf("passwd %zu %zu\n", sizeof(struct passwd), _Alignof(struct passwd)); -#ifndef __HAIKU__ printf("shmid_ds %zu %zu\n", sizeof(struct shmid_ds), _Alignof(struct shmid_ds)); -#endif printf("ipc_perm %zu %zu\n", sizeof(struct ipc_perm), _Alignof(struct ipc_perm)); printf("msqid_ds %zu %zu\n", sizeof(struct msqid_ds), _Alignof(struct msqid_ds)); @@ -102,15 +97,18 @@ int main(int argc, char *argv[]) printf("iovec %zu %zu\n", sizeof(struct iovec), _Alignof(struct iovec)); printf("semid_ds %zu %zu\n", sizeof(struct semid_ds), _Alignof(struct semid_ds)); + printf("semid_ds.sem_perm %zu\n", offsetof(struct semid_ds, sem_perm)); + printf("semid_ds.sem_otime %zu\n", offsetof(struct semid_ds, sem_otime)); + printf("semid_ds.sem_ctime %zu\n", offsetof(struct semid_ds, sem_ctime)); + printf("semid_ds.sem_nsems %zu\n", offsetof(struct semid_ds, sem_nsems)); + printf("sembuf %zu %zu\n", sizeof(struct sembuf), _Alignof(struct sembuf)); printf("itimerval %zu %zu\n", sizeof(struct itimerval), _Alignof(struct itimerval)); printf("utimbuf %zu %zu\n", sizeof(struct utimbuf), _Alignof(struct utimbuf)); -#ifndef __HAIKU__ printf("wordexp_t %zu %zu\n", sizeof(wordexp_t), _Alignof(wordexp_t)); -#endif printf("time_t %zu %zu\n", sizeof(time_t), _Alignof(time_t)); printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec)); diff --git a/tests/core/sys/posix/structs/structs.odin b/tests/core/sys/posix/structs/structs.odin index f2bead5ba..43afc0048 100644 --- a/tests/core/sys/posix/structs/structs.odin +++ b/tests/core/sys/posix/structs/structs.odin @@ -41,11 +41,11 @@ main :: proc() { fmt.println("ai_canonname", offset_of(posix.addrinfo, ai_canonname)) fmt.println("pollfd", size_of(posix.pollfd), align_of(posix.pollfd)) + fmt.println("nfds_t", size_of(posix.nfds_t), align_of(posix.nfds_t)) + fmt.println("passwd", size_of(posix.passwd), align_of(posix.passwd)) - when ODIN_OS != .Haiku { - fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds)) - } + fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds)) fmt.println("ipc_perm", size_of(posix.ipc_perm), align_of(posix.ipc_perm)) fmt.println("msqid_ds", size_of(posix.msqid_ds), align_of(posix.msqid_ds)) @@ -68,15 +68,18 @@ main :: proc() { fmt.println("iovec", size_of(posix.iovec), align_of(posix.iovec)) fmt.println("semid_ds", size_of(posix.semid_ds), align_of(posix.semid_ds)) + fmt.println("semid_ds.sem_perm", offset_of(posix.semid_ds, sem_perm)) + fmt.println("semid_ds.sem_otime", offset_of(posix.semid_ds, sem_otime)) + fmt.println("semid_ds.sem_ctime", offset_of(posix.semid_ds, sem_ctime)) + fmt.println("semid_ds.sem_nsems", offset_of(posix.semid_ds, sem_nsems)) + fmt.println("sembuf", size_of(posix.sembuf), align_of(posix.sembuf)) fmt.println("itimerval", size_of(posix.itimerval), align_of(posix.itimerval)) fmt.println("utimbuf", size_of(posix.utimbuf), align_of(posix.utimbuf)) - when ODIN_OS != .Haiku { - fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t)) - } + fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t)) fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t)) fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec)) diff --git a/tests/core/sys/windows/test_kernel32.odin b/tests/core/sys/windows/test_kernel32.odin index f6a88c769..15f3b5173 100644 --- a/tests/core/sys/windows/test_kernel32.odin +++ b/tests/core/sys/windows/test_kernel32.odin @@ -12,12 +12,12 @@ lcid_to_local :: proc(t: ^testing.T) { cc := win32.LCIDToLocaleName(lcid, &wname[0], len(wname) - 1, 0) testing.expectf(t, cc == 6, "%#x (should be: %#x)", u32(cc), 6) if cc == 0 {return} - str, err := win32.wstring_to_utf8(win32.wstring(&wname), int(cc)) + str, err := win32.wstring_to_utf8(win32.wstring(&wname[0]), int(cc)) testing.expectf(t, err == .None, "%v (should be: %x)", err, 0) exp :: "en-US" testing.expectf(t, str == exp, "%v (should be: %v)", str, exp) - cc2 := win32.LocaleNameToLCID(L(exp), 0) + cc2 := win32.LocaleNameToLCID(exp, 0) testing.expectf(t, cc2 == 0x0409, "%#x (should be: %#x)", u32(cc2), 0x0409) //fmt.printfln("%0X", lcid) diff --git a/tests/core/sys/windows/test_ole32.odin b/tests/core/sys/windows/test_ole32.odin index 8be231e1f..a0a2590b8 100644 --- a/tests/core/sys/windows/test_ole32.odin +++ b/tests/core/sys/windows/test_ole32.odin @@ -9,7 +9,7 @@ import "core:testing" string_from_clsid :: proc(t: ^testing.T) { p: win32.LPOLESTR hr := win32.StringFromCLSID(win32.CLSID_FileOpenDialog, &p) - defer if p != nil {win32.CoTaskMemFree(p)} + defer if p != nil {win32.CoTaskMemFree(rawptr(p))} testing.expectf(t, win32.SUCCEEDED(hr), "%x (should be: %x)", u32(hr), 0) testing.expectf(t, p != nil, "%v is nil", p) @@ -33,7 +33,7 @@ clsid_from_string :: proc(t: ^testing.T) { string_from_iid :: proc(t: ^testing.T) { p: win32.LPOLESTR hr := win32.StringFromIID(win32.IID_IFileDialog, &p) - defer if p != nil {win32.CoTaskMemFree(p)} + defer if p != nil {win32.CoTaskMemFree(rawptr(p))} testing.expectf(t, win32.SUCCEEDED(hr), "%x (should be: %x)", u32(hr), 0) testing.expectf(t, p != nil, "%v is nil", p) diff --git a/tests/core/sys/windows/test_windows_generated.odin b/tests/core/sys/windows/test_windows_generated.odin index 3d8184a8b..f859a8bed 100644 --- a/tests/core/sys/windows/test_windows_generated.odin +++ b/tests/core/sys/windows/test_windows_generated.odin @@ -527,8 +527,10 @@ verify_winmm :: proc(t: ^testing.T) { // mmsyscom.h expect_size(t, win32.MMVERSION, 4) expect_size(t, win32.MMTIME, 12) + // mmreg.h + expect_size(t, win32.WAVEFORMATEX, 18) + expect_size(t, win32.WAVEFORMATEXTENSIBLE, 40) // mmeapi.h - expect_size(t, win32.WAVEFORMATEX, 20) expect_size(t, win32.WAVEHDR, 48) expect_size(t, win32.WAVEINCAPSW, 80) expect_size(t, win32.WAVEOUTCAPSW, 84) @@ -678,17 +680,17 @@ verify_error_codes :: proc(t: ^testing.T) { @(test) verify_error_helpers :: proc(t: ^testing.T) { // winerror.h - expect_value(t, win32.SUCCEEDED(-1), 0x00000000) - expect_value(t, win32.SUCCEEDED(0), 0x00000001) - expect_value(t, win32.SUCCEEDED(1), 0x00000001) + expect_value(t, uint(win32.SUCCEEDED(-1)), 0x00000000) + expect_value(t, uint(win32.SUCCEEDED(0)), 0x00000001) + expect_value(t, uint(win32.SUCCEEDED(1)), 0x00000001) - expect_value(t, win32.FAILED(-1), 0x00000001) - expect_value(t, win32.FAILED(0), 0x00000000) - expect_value(t, win32.FAILED(1), 0x00000000) + expect_value(t, uint(win32.FAILED(-1)), 0x00000001) + expect_value(t, uint(win32.FAILED(0)), 0x00000000) + expect_value(t, uint(win32.FAILED(1)), 0x00000000) - expect_value(t, win32.IS_ERROR(-1), 0x00000001) - expect_value(t, win32.IS_ERROR(0), 0x00000000) - expect_value(t, win32.IS_ERROR(1), 0x00000000) + expect_value(t, uint(win32.IS_ERROR(-1)), 0x00000001) + expect_value(t, uint(win32.IS_ERROR(0)), 0x00000000) + expect_value(t, uint(win32.IS_ERROR(1)), 0x00000000) expect_value(t, win32.HRESULT_CODE(0xFFFFCCCC), 0x0000CCCC) expect_value(t, win32.HRESULT_FACILITY(0xFFFFCCCC), 0x00001FFF) diff --git a/tests/core/sys/windows/util.odin b/tests/core/sys/windows/util.odin new file mode 100644 index 000000000..777f85776 --- /dev/null +++ b/tests/core/sys/windows/util.odin @@ -0,0 +1,254 @@ +#+build windows +package test_core_sys_windows + +import "base:intrinsics" +import "core:testing" +import win32 "core:sys/windows" +import runtime "base:runtime" + +UTF16_Vector :: struct { + wstr: win32.wstring, + ustr: string, +} + +utf16_vectors := []UTF16_Vector{ + { + "Hellope, World!", + "Hellope, World!", + }, + { + "Hellope\x00, World!", + "Hellope", + }, +} + +@(test) +utf16_to_utf8_buf_test :: proc(t: ^testing.T) { + for test in utf16_vectors { + buf := make([]u8, len(test.ustr)) + defer delete(buf) + + wstr := string16(test.wstr) + res := win32.utf16_to_utf8_buf(buf[:], transmute([]u16)wstr) + testing.expect_value(t, res, test.ustr) + } +} + +@(test) +utf8_to_utf16_buf_test :: proc(t: ^testing.T) { + buf : [100]u16 = --- + // Test everything with a dirty buffer! + reset_buffer :: proc(buf : []u16) { + for i in 0 ..< len(buf) { + buf[i] = cast(u16)(i + 1) + } + } + + result : []u16 + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:], "Hello\x00, World!") + testing.expect_value(t, len(result), 14) + testing.expect_value(t, result[4], 'o') + testing.expect_value(t, result[5], 0) + testing.expect_value(t, result[6], ',') + testing.expect_value(t, result[13], '!') + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:], "H\x00\x00") + testing.expect_value(t, len(result), 3) + testing.expect_value(t, result[1], 0) + testing.expect_value(t, result[2], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:], "你好,世界!") + testing.expect_value(t, len(result), 6) + testing.expect_value(t, result[0], 0x4F60) + testing.expect_value(t, result[1], 0x597D) + testing.expect_value(t, result[2], 0xFF0C) + testing.expect_value(t, result[3], 0x4E16) + testing.expect_value(t, result[4], 0x754C) + testing.expect_value(t, result[5], 0xFF01) + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:4], "Hello") + // Buffer too short. + testing.expect(t, result == nil) + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:], "") + // Valid, but indistinguishable from an error. + testing.expect_value(t, len(result), 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_utf16_buf(buf[:0], "Hello") + // Buffer too short. + testing.expect(t, result == nil) +} + +@(test) +utf8_to_wstring_buf_test :: proc(t : ^testing.T) { + buf : [100]u16 = --- + // Test everything with a dirty buffer! + reset_buffer :: proc(buf : []u16) { + for i in 0 ..< len(buf) { + buf[i] = cast(u16)(i + 1) + } + } + + result : win32.wstring + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:], "Hello\x00, World!") + testing.expect(t, result != nil) + testing.expect_value(t, buf[13], '!') + testing.expect_value(t, buf[14], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:], "H\x00\x00") + testing.expect(t, result != nil) + testing.expect_value(t, buf[1], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:], "你好,世界!") + testing.expect(t, result != nil) + testing.expect_value(t, buf[0], 0x4F60) + testing.expect_value(t, buf[1], 0x597D) + testing.expect_value(t, buf[2], 0xFF0C) + testing.expect_value(t, buf[3], 0x4E16) + testing.expect_value(t, buf[4], 0x754C) + testing.expect_value(t, buf[5], 0xFF01) + testing.expect_value(t, buf[6], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:5], "Hello") + // Buffer too short. + testing.expect_value(t, result, nil) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:6], "Hello") + // Buffer *just* long enough. + testing.expect(t, result != nil) + testing.expect_value(t, buf[4], 'o') + testing.expect_value(t, buf[5], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:], "") + // Valid, and distinguishable from an error. + testing.expect(t, result != nil) + testing.expect_value(t, buf[0], 0) + + reset_buffer(buf[:]) + result = win32.utf8_to_wstring_buf(buf[:0], "Hello") + // Buffer too short. + testing.expect(t, result == nil) +} + +// Custom allocator proc that always returns dirty (non-zeroed) memory. +dirty_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, + location: runtime.Source_Code_Location = #caller_location) -> ([]byte, runtime.Allocator_Error) { + real_allocator := cast(^runtime.Allocator)allocator_data + bytes, error := real_allocator.procedure(real_allocator.data, mode, + size, alignment, + old_memory, old_size, + location) + if error == .None { + for i in 0 ..< len(bytes) { + // This will yield a 0 byte on overflow, but that does not matter in this test suite. + bytes[i] = cast(byte)(i + 1) + } + } + return bytes, error +} + +@(test) +utf8_to_utf16_alloc_test :: proc(t : ^testing.T) { + // We want to ensure that everything works with dirty + // (non-zeroed) memory returned from the allocator. + real_allocator := context.temp_allocator + allocator := runtime.Allocator { + procedure = dirty_allocator_proc, + data = cast(rawptr)&real_allocator, + } + + // Test the dirty allocator. + allocator_test_slice := make([]u8, 100, allocator) + testing.expect_value(t, len(allocator_test_slice), 100) + for i in 0 ..< len(allocator_test_slice) { + testing.expect_value(t, allocator_test_slice[i], cast(u8)(i + 1)) + } + + result : []u16 + + result = win32.utf8_to_utf16_alloc("Hello\x00, World!", allocator) + testing.expect_value(t, len(result), 14) + testing.expect_value(t, result[4], 'o') + testing.expect_value(t, result[5], 0) + testing.expect_value(t, result[6], ',') + testing.expect_value(t, result[13], '!') + + result = win32.utf8_to_utf16_alloc("H\x00\x00", allocator) + testing.expect_value(t, len(result), 3) + testing.expect_value(t, result[1], 0) + testing.expect_value(t, result[2], 0) + + result = win32.utf8_to_utf16_alloc("你好,世界!", allocator) + testing.expect_value(t, len(result), 6) + testing.expect_value(t, result[0], 0x4F60) + testing.expect_value(t, result[1], 0x597D) + testing.expect_value(t, result[2], 0xFF0C) + testing.expect_value(t, result[3], 0x4E16) + testing.expect_value(t, result[4], 0x754C) + testing.expect_value(t, result[5], 0xFF01) + + result = win32.utf8_to_utf16_alloc("", allocator) + // Valid, but indistinguishable from an error. + testing.expect_value(t, len(result), 0) +} + +@(test) +utf8_to_wstring_alloc_test :: proc(t : ^testing.T) { + // We want to ensure that everything works with dirty + // (non-zeroed) memory returned from the allocator. + backing_allocator := context.temp_allocator + allocator := runtime.Allocator { + procedure = dirty_allocator_proc, + data = cast(rawptr)&backing_allocator, + } + + result : win32.wstring + buf : [^]u16 + + result = win32.utf8_to_wstring_alloc("Hello\x00, World!", allocator) + buf = transmute([^]u16)result + testing.expect(t, result != nil) + testing.expect_value(t, buf[4], 'o') + testing.expect_value(t, buf[5], 0) + testing.expect_value(t, buf[6], ',') + testing.expect_value(t, buf[13], '!') + testing.expect_value(t, buf[14], 0) + + result = win32.utf8_to_wstring_alloc("H\x00\x00", allocator) + buf = transmute([^]u16)result + testing.expect(t, result != nil) + testing.expect_value(t, buf[1], 0) + + result = win32.utf8_to_wstring_alloc("你好,世界!", allocator) + buf = transmute([^]u16)result + testing.expect(t, result != nil) + testing.expect_value(t, buf[0], 0x4F60) + testing.expect_value(t, buf[1], 0x597D) + testing.expect_value(t, buf[2], 0xFF0C) + testing.expect_value(t, buf[3], 0x4E16) + testing.expect_value(t, buf[4], 0x754C) + testing.expect_value(t, buf[5], 0xFF01) + testing.expect_value(t, buf[6], 0) + + result = win32.utf8_to_wstring_alloc("", allocator) + buf = transmute([^]u16)result + // Valid, and distinguishable from an error. + testing.expect(t, result != nil) + testing.expect_value(t, buf[0], 0) +} diff --git a/tests/core/sys/windows/win32gen/win32gen.cpp b/tests/core/sys/windows/win32gen/win32gen.cpp index 57a094cd5..a2ff66d09 100644 --- a/tests/core/sys/windows/win32gen/win32gen.cpp +++ b/tests/core/sys/windows/win32gen/win32gen.cpp @@ -1,6 +1,7 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include +#include #include #include #include @@ -54,6 +55,10 @@ static std::string ConvertLPCWSTRToString(const LPCWSTR lpcwszStr) << '\t' << "expect_value(t, win32." << #s << ", " \ << "0x" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << s << ")" << endl +#define expect_value_bool(s) out \ + << '\t' << "expect_value(t, uint(win32." << #s << "), " \ + << "0x" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << s << ")" << endl + #define expect_value_32(s) out \ << '\t' << "expect_value(t, u32(win32." << #s << "), " \ << "0x" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << (ULONG)(ULONG_PTR)(s) << ")" << endl @@ -702,8 +707,10 @@ static void verify_winmm(ofstream& out) { test_proc_comment("mmsyscom.h"); expect_size(MMVERSION); expect_size(MMTIME); - test_proc_comment("mmeapi.h"); + test_proc_comment("mmreg.h"); expect_size(WAVEFORMATEX); + expect_size(WAVEFORMATEXTENSIBLE); + test_proc_comment("mmeapi.h"); expect_size(WAVEHDR); expect_size(WAVEINCAPSW); expect_size(WAVEOUTCAPSW); @@ -879,17 +886,17 @@ static void verify_error_helpers(ofstream& out) { test_proc_begin(); test_proc_comment("winerror.h"); - expect_value(SUCCEEDED(-1)); - expect_value(SUCCEEDED(0)); - expect_value(SUCCEEDED(1)); + expect_value_bool(SUCCEEDED(-1)); + expect_value_bool(SUCCEEDED(0)); + expect_value_bool(SUCCEEDED(1)); out << endl; - expect_value(FAILED(-1)); - expect_value(FAILED(0)); - expect_value(FAILED(1)); + expect_value_bool(FAILED(-1)); + expect_value_bool(FAILED(0)); + expect_value_bool(FAILED(1)); out << endl; - expect_value(IS_ERROR(-1)); - expect_value(IS_ERROR(0)); - expect_value(IS_ERROR(1)); + expect_value_bool(IS_ERROR(-1)); + expect_value_bool(IS_ERROR(0)); + expect_value_bool(IS_ERROR(1)); out << endl; expect_value(HRESULT_CODE(0xFFFFCCCC)); expect_value(HRESULT_FACILITY(0xFFFFCCCC)); diff --git a/tests/core/testing/test_core_testing.odin b/tests/core/testing/test_core_testing.odin new file mode 100644 index 000000000..ed3a29173 --- /dev/null +++ b/tests/core/testing/test_core_testing.odin @@ -0,0 +1,58 @@ +package test_core_testing + +import "core:c/libc" +import "core:math/rand" +import "core:testing" + +@test +test_expected_assert :: proc(t: ^testing.T) { + target := #location(); target.line += 2; target.column = 2 + testing.expect_assert_from(t, target) + assert(false) +} + +@test +test_expected_two_assert :: proc(t: ^testing.T) { + target1 := #location(); target1.line += 5; target1.column = 3 + target2 := #location(); target2.line += 6; target2.column = 3 + testing.expect_assert_from(t, target1) + testing.expect_assert_from(t, target2) + if rand.uint32() & 1 == 0 { + assert(false) + } else { + assert(false) + } +} + +some_proc :: proc() { + assert(false) +} + +@test +test_expected_assert_in_proc :: proc(t: ^testing.T) { + target := #location(some_proc) + target.line += 1 + target.column = 2 + assert(target.procedure == "", "The bug's been fixed; this line and the next can be deleted.") + target.procedure = "some_proc" // TODO: Is this supposed to be blank on #location(...)? + testing.expect_assert(t, target) + some_proc() +} + +@test +test_expected_assert_message :: proc(t: ^testing.T) { + testing.expect_assert(t, "failure") + assert(false, "failure") +} + +@test +test_expected_signal :: proc(t: ^testing.T) { + testing.expect_signal(t, libc.SIGILL) + libc.raise(libc.SIGILL) +} + +@test +test_array_bounds_trap_signal :: proc(t: ^testing.T) { + testing.expect_signal(t, libc.SIGILL) + _ = make([]u8, -1) +} diff --git a/tests/core/text/regex/test_core_text_regex.odin b/tests/core/text/regex/test_core_text_regex.odin index 913e716e5..732a3d321 100644 --- a/tests/core/text/regex/test_core_text_regex.odin +++ b/tests/core/text/regex/test_core_text_regex.odin @@ -51,13 +51,13 @@ check_expression_with_flags :: proc(t: ^testing.T, pattern: string, flags: regex } check_expression :: proc(t: ^testing.T, pattern, haystack: string, needles: ..string, extra_flags := regex.Flags{}, loc := #caller_location) { - check_expression_with_flags(t, pattern, { .Global } + extra_flags, + check_expression_with_flags(t, pattern, extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .No_Optimization } + extra_flags, + check_expression_with_flags(t, pattern, { .No_Optimization } + extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .Unicode } + extra_flags, + check_expression_with_flags(t, pattern, { .Unicode } + extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .Unicode, .No_Optimization } + extra_flags, + check_expression_with_flags(t, pattern, { .Unicode, .No_Optimization } + extra_flags, haystack, ..needles, loc = loc) } @@ -72,17 +72,18 @@ expect_error :: proc(t: ^testing.T, pattern: string, expected_error: typeid, fla testing.expect_value(t, variant_ti, expected_ti, loc = loc) } -check_capture :: proc(t: ^testing.T, got, expected: regex.Capture, loc := #caller_location) { - testing.expect_value(t, len(got.pos), len(got.groups), loc = loc) - testing.expect_value(t, len(got.pos), len(expected.pos), loc = loc) - testing.expect_value(t, len(got.groups), len(expected.groups), loc = loc) +check_capture :: proc(t: ^testing.T, got, expected: regex.Capture, loc := #caller_location) -> (ok: bool) { + testing.expect_value(t, len(got.pos), len(got.groups), loc = loc) or_return + testing.expect_value(t, len(got.pos), len(expected.pos), loc = loc) or_return + testing.expect_value(t, len(got.groups), len(expected.groups), loc = loc) or_return if len(got.pos) == len(expected.pos) { for i in 0..= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) + continue vector + } + if !check_capture(t, capture, test.expected[idx]) { + log.errorf("capture check failed on string %q against pattern %q", test.haystack, test.pattern) + } + } + testing.expectf(t, it.idx == len(test.expected), "expected idx to be %i, got %i on string %q against pattern %q", len(test.expected), it.idx, test.haystack, test.pattern) + } +} + +@test +test_iterator_reset :: proc(t: ^testing.T) { + test := Iterator_Test{ + `aaa`, `a`, {}, + { + {pos = {{0, 1}}, groups = {"a"}}, + {pos = {{1, 2}}, groups = {"a"}}, + {pos = {{2, 3}}, groups = {"a"}}, + }, + } + + out: { + it, err := regex.create_iterator(`aaa`, `a`) + defer regex.destroy(it) + + testing.expect_value(t, err, nil) + (err == nil) or_break out + + for capture, idx in regex.match(&it) { + if idx >= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) break } check_capture(t, capture, test.expected[idx]) } testing.expect_value(t, it.idx, len(test.expected)) + + // Do it again. + iterations := 0 + regex.reset(&it) + + // Mind that this loop can do nothing if it wasn't reset but leave us + // with the expected `idx` state. + // + // That's why we count iterations this time around. + for capture, idx in regex.match(&it) { + iterations += 1 + if idx >= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) + break + } + check_capture(t, capture, test.expected[idx]) + } + testing.expect_value(t, it.idx, len(test.expected)) + testing.expect_value(t, iterations, len(test.expected)) } -} \ No newline at end of file +} diff --git a/tests/core/time/test_core_time.odin b/tests/core/time/test_core_time.odin index cd2b19fb8..d1f83c0dc 100644 --- a/tests/core/time/test_core_time.odin +++ b/tests/core/time/test_core_time.odin @@ -2,6 +2,7 @@ package test_core_time import "core:testing" import "core:time" +@(require) import "core:log" import dt "core:time/datetime" import tz "core:time/timezone" @@ -15,8 +16,8 @@ test_time_and_date_formatting :: proc(t: ^testing.T) { d := time.Duration(now._nsec) testing.expect_value(t, time.to_string_hms (now, buf[:]), "00:12:44") - testing.expect_value(t, time.to_string_hms_12 (now, buf[:]), "00:12:44 am") - testing.expect_value(t, time.to_string_hms_12 (now, buf[:], {"㏂", "㏘"}), "00:12:44㏂") + testing.expect_value(t, time.to_string_hms_12 (now, buf[:]), "12:12:44 am") + testing.expect_value(t, time.to_string_hms_12 (now, buf[:], {"㏂", "㏘"}), "12:12:44㏂") testing.expect_value(t, time.to_string_hms (d, buf[:]), "00:12:44") testing.expect_value(t, time.to_string_yyyy_mm_dd(now, buf[:]), "1677-09-21") @@ -364,9 +365,10 @@ test_convert_timezone_roundtrip :: proc(t: ^testing.T) { std_dt, _ := dt.components_to_datetime(2024, 11, 4, 23, 47, 0) local_tz, local_load_ok := tz.region_load("local") - testing.expectf(t, local_load_ok, "Failed to load local timezone") defer tz.region_destroy(local_tz) + testing.expectf(t, local_load_ok, "Failed to load local timezone") + edm_tz, edm_load_ok := tz.region_load("America/Edmonton") testing.expectf(t, edm_load_ok, "Failed to load America/Edmonton timezone") defer tz.region_destroy(edm_tz) diff --git a/tests/documentation/documentation_tester.odin b/tests/documentation/documentation_tester.odin index 7b125d4e4..be59d9b4d 100644 --- a/tests/documentation/documentation_tester.odin +++ b/tests/documentation/documentation_tester.odin @@ -1,12 +1,11 @@ package documentation_tester -import "core:os" -import "core:io" -import "core:fmt" -import "core:strings" -import "core:odin/ast" -import "core:odin/parser" -import "core:c/libc" +import "core:os" +import "core:fmt" +import "core:strings" +import "core:odin/ast" +import "core:odin/parser" +import "core:c/libc" import doc "core:odin/doc-format" Example_Test :: struct { @@ -63,10 +62,11 @@ main :: proc() { errorf("expected path to odin executable") } g_path_to_odin = os.args[1] - data, ok := os.read_entire_file("all.odin-doc") - if !ok { + data, data_err := os.read_entire_file("all.odin-doc", context.allocator) + if data_err != nil { errorf("unable to read file: all.odin-doc") } + defer delete(data) err: doc.Reader_Error g_header, err = doc.read_from_bytes(data) switch err { @@ -257,8 +257,8 @@ find_and_add_examples :: proc(docs: string, package_name: string, entity_name: s write_test_suite :: proc(example_tests: []Example_Test) { TEST_SUITE_DIRECTORY :: "verify" - os.remove_directory(TEST_SUITE_DIRECTORY) - os.make_directory(TEST_SUITE_DIRECTORY) + os.remove_all(TEST_SUITE_DIRECTORY) + os.mkdir(TEST_SUITE_DIRECTORY) example_build := strings.builder_make() test_runner := strings.builder_make() @@ -276,9 +276,11 @@ import "core:sync" import "base:intrinsics" @(private="file") -_read_pipe: os.Handle +_read_pipe: ^os.File @(private="file") -_write_pipe: os.Handle +_write_pipe: ^os.File +@(private="file") +_old_stdout: ^os.File @(private="file") _pipe_reader_semaphore: sync.Sema @(private="file") @@ -286,20 +288,20 @@ _out_data: string @(private="file") _out_buffer: [mem.Megabyte]byte @(private="file") -_bad_test_found: bool +_bad_count: int +@(private="file") +_good_count: int @(private="file") _spawn_pipe_reader :: proc() { thread.run(proc() { - stream := os.stream_from_handle(_read_pipe) - reader := io.to_reader(stream) sync.post(&_pipe_reader_semaphore) // notify thread is ready for { n_read := 0 read_to_null_byte := 0 finished_reading := false for ! finished_reading { - just_read, err := io.read(reader, _out_buffer[n_read:], &n_read); if err != .None { + just_read, err := io.read(os.to_stream(_read_pipe), _out_buffer[n_read:], &n_read); if err != .None { panic("We got an IO error!") } for b in _out_buffer[n_read - just_read: n_read] { @@ -328,11 +330,14 @@ _check :: proc(test_name: string, expected: string) { if expected != output { fmt.eprintf("Test %q got unexpected output:\n%q\n", test_name, output) fmt.eprintf("Expected:\n%q\n", expected) - _bad_test_found = true + _bad_count += 1 + } else { + _good_count += 1 } } main :: proc() { + _old_stdout = os.stdout _read_pipe, _write_pipe, _ = os.pipe() os.stdout = _write_pipe _spawn_pipe_reader() @@ -445,24 +450,19 @@ main :: proc() { continue } defer os.close(test_file_handle) - stream := os.stream_from_handle(test_file_handle) - writer, ok := io.to_writer(stream); if ! ok { - fmt.eprintf("We could not make the writer for the path %q\n", save_path) - g_bad_doc = true - continue - } - fmt.wprintf(writer, "%v%v_%v", code_string[:index_of_proc_name], test.package_name, code_string[index_of_proc_name:]) + fmt.wprintf(os.to_stream(test_file_handle), "%v%v_%v", code_string[:index_of_proc_name], test.package_name, code_string[index_of_proc_name:]) fmt.println("Done") } strings.write_string(&test_runner, ` - if _bad_test_found { + fmt.wprintfln(os.to_stream(_old_stdout), "Passes: %v. Fails: %v", _good_count, _bad_count) + if _bad_count > 0 { fmt.eprintln("One or more tests failed") os.exit(1) } }`) - os.write_entire_file("verify/main.odin", transmute([]byte)strings.to_string(test_runner)) + _ = os.write_entire_file("verify/main.odin", transmute([]byte)strings.to_string(test_runner)) } run_test_suite :: proc() -> bool { diff --git a/tests/heap_allocator/libc/heap_allocator_other.odin b/tests/heap_allocator/libc/heap_allocator_other.odin index 5118aa612..3b18b063c 100644 --- a/tests/heap_allocator/libc/heap_allocator_other.odin +++ b/tests/heap_allocator/libc/heap_allocator_other.odin @@ -1,4 +1,4 @@ -#+build js, wasi, freestanding, essence +#+build js, wasi, freestanding #+private package tests_heap_allocator_libc diff --git a/tests/heap_allocator/libc/heap_allocator_unix.odin b/tests/heap_allocator/libc/heap_allocator_unix.odin index 49fb820bd..7e3ee0961 100644 --- a/tests/heap_allocator/libc/heap_allocator_unix.odin +++ b/tests/heap_allocator/libc/heap_allocator_unix.odin @@ -1,9 +1,9 @@ -#+build linux, darwin, freebsd, openbsd, netbsd, haiku +#+build linux, darwin, freebsd, openbsd, netbsd #+private package tests_heap_allocator_libc when ODIN_OS == .Darwin { - foreign import libc "system:System.framework" + foreign import libc "system:System" } else { foreign import libc "system:c" } diff --git a/tests/internal/test_anonymous_globals.odin b/tests/internal/test_anonymous_globals.odin new file mode 100644 index 000000000..fc214ebde --- /dev/null +++ b/tests/internal/test_anonymous_globals.odin @@ -0,0 +1,67 @@ +package test_internal + +import "core:testing" + + + +// https://github.com/odin-lang/Odin/pull/5908 +@(test) +test_address_of_anonymous_global :: proc(t: ^testing.T) { + // This loop exists so that we do more computation with stack memory + // This increases the likelihood of catching a bug where anonymous globals are incorrectly allocated on the stack + // instead of the data segment + for _ in 0..<10 { + testing.expect(t, global_variable.inner.field == 0xDEADBEEF) + } +} + +global_variable := Outer_Struct{ + inner = &Inner_Struct{ + field = 0xDEADBEEF, + }, +} +Outer_Struct :: struct{ + inner: ^Inner_Struct, + + // Must have a second field to prevent the compiler from simplifying the `Outer_Struct` type to `^Inner_Struct` + // ...I think? In any case, don't remove this field + _: int, +} +Inner_Struct :: struct{ + field: int, +} + + + +// https://github.com/odin-lang/Odin/pull/5908 +// +// Regression test for commit f1e3977cf94dfc0457f05d499cc280d8e1329086 where a larger anonymous global is needed to trigger +// the bug +@(test) +test_address_of_large_anonymous_global :: proc(t: ^testing.T) { + // This loop exists so that we do more computation with stack memory + // This increases the likelihood of catching a bug where anonymous globals are incorrectly allocated on the stack + // instead of the data segment + for _ in 0..<10 { + for i in 0..<8 { + testing.expect(t, global_variable_64.inner.field[i] == i) + } + } +} + +#assert(size_of(Inner_Struct_64) == 64) +global_variable_64 := Outer_Struct_64{ + inner = &Inner_Struct_64{ + field = [8]int{0, 1, 2, 3, 4, 5, 6, 7}, + }, +} +Outer_Struct_64 :: struct{ + inner: ^Inner_Struct_64, + + // Must have a second field to prevent the compiler from simplifying the `Outer_Struct` type to `^Inner_Struct` + // ...I think? In any case, don't remove this field + _: int, +} +Inner_Struct_64 :: struct{ + field: [8]int, +} diff --git a/tests/internal/test_chacha8rand.odin b/tests/internal/test_chacha8rand.odin new file mode 100644 index 000000000..378b398f0 --- /dev/null +++ b/tests/internal/test_chacha8rand.odin @@ -0,0 +1,151 @@ +package test_internal + +import "base:runtime" +import "core:bytes" +import "core:encoding/endian" +import "core:math/rand" +import "core:testing" + +@(private = "file") +ITERS :: 10000000 +@(private = "file") +ITERS_BULK :: 1000 + +@(private = "file") +SAMPLE_SEED : string : "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456" +@(private = "file") +SAMPLE_OUTPUT := []u64{ + 0xb773b6063d4616a5, 0x1160af22a66abc3c, 0x8c2599d9418d287c, 0x7ee07e037edc5cd6, + 0xcfaa9ee02d1c16ad, 0x0e090eef8febea79, 0x3c82d271128b5b3e, 0x9c5addc11252a34f, + 0xdf79bb617d6ceea6, 0x36d553591f9d736a, 0xeef0d14e181ee01f, 0x089bfc760ae58436, + 0xd9e52b59cc2ad268, 0xeb2fb4444b1b8aba, 0x4f95c8a692c46661, 0xc3c6323217cae62c, + 0x91ebb4367f4e2e7e, 0x784cf2c6a0ec9bc6, 0x5c34ec5c34eabe20, 0x4f0a8f515570daa8, + 0xfc35dcb4113d6bf2, 0x5b0da44c645554bc, 0x6d963da3db21d9e1, 0xeeaefc3150e500f3, + 0x2d37923dda3750a5, 0x380d7a626d4bc8b0, 0xeeaf68ede3d7ee49, 0xf4356695883b717c, + 0x846a9021392495a4, 0x8e8510549630a61b, 0x18dc02545dbae493, 0x0f8f9ff0a65a3d43, + 0xccf065f7190ff080, 0xfd76d1aa39673330, 0x95d232936cba6433, 0x6c7456d1070cbd17, + 0x462acfdaff8c6562, 0x5bafab866d34fc6a, 0x0c862f78030a2988, 0xd39a83e407c3163d, + 0xc00a2b7b45f22ebf, 0x564307c62466b1a9, 0x257e0424b0c072d4, 0x6fb55e99496c28fe, + 0xae9873a88f5cd4e0, 0x4657362ac60d3773, 0x1c83f91ecdf23e8e, 0x6fdc0792c15387c0, + 0x36dad2a30dfd2b5c, 0xa4b593290595bdb7, 0x4de18934e4cc02c5, 0xcdc0d604f015e3a7, + 0xfba0dbf69ad80321, 0x60e8bea3d139de87, 0xd18a4d851ef48756, 0x6366447c2215f34a, + 0x05682e97d3d007ee, 0x4c0e8978c6d54ab2, 0xcf1e9f6a6712edc2, 0x061439414c80cfd3, + 0xd1a8b6e2745c0ead, 0x31a7918d45c410e8, 0xabcc61ad90216eec, 0x4040d92d2032a71a, + 0x3cd2f66ffb40cd68, 0xdcd051c07295857a, 0xeab55cbcd9ab527e, 0x18471dce781bdaac, + 0xf7f08cd144dc7252, 0x5804e0b13d7f40d1, 0x5cb1a446e4b2d35b, 0xe6d4a728d2138a06, + 0x05223e40ca60dad8, 0x2d61ec3206ac6a68, 0xab692356874c17b8, 0xc30954417676de1c, + 0x4f1ace3732225624, 0xfba9510813988338, 0x997f200f52752e11, 0x1116aaafe86221fa, + 0x07ce3b5cb2a13519, 0x2956bc72bc458314, 0x4188b7926140eb78, 0x56ca6dbfd4adea4d, + 0x7fe3c22349340ce5, 0x35c08f9c37675f8a, 0x11e1c7fbef5ed521, 0x98adc8464ec1bc75, + 0xd163b2c73d1203f8, 0x8c761ee043a2f3f3, 0x24b99d6accecd7b7, 0x793e31aa112f0370, + 0x8e87dc2a19285139, 0x4247ae04f7096e25, 0x514f3122926fe20f, 0xdc6fb3f045d2a7e9, + 0x15cb30cecdd18eba, 0xcbc7fdecf6900274, 0x3fb5c696dc8ba021, 0xd1664417c8d274e6, + 0x05f7e445ea457278, 0xf920bbca1b9db657, 0x0c1950b4da22cb99, 0xf875baf1af09e292, + 0xbed3d7b84250f838, 0xf198e8080fd74160, 0xc9eda51d9b7ea703, 0xf709ef55439bf8f6, + 0xd20c74feebf116fc, 0x305668eb146d7546, 0x829af3ec10d89787, 0x15b8f9697b551dbc, + 0xfc823c6c8e64b8c9, 0x345585e8183b40bc, 0x674b4171d6581368, 0x1234d81cd670e9f7, + 0x0e505210d8a55e19, 0xe8258d69eeeca0dc, 0x05d4c452e8baf67e, 0xe8dbe30116a45599, + 0x1cf08ce1b1176f00, 0xccf7d0a4b81ecb49, 0x303fea136b2c430e, 0x861d6c139c06c871, + 0x5f41df72e05e0487, 0x25bd7e1e1ae26b1d, 0xbe9f4004d662a41d, 0x65bf58d483188546, + 0xd1b27cff69db13cc, 0x01a6663372c1bb36, 0x578dd7577b727f4d, 0x19c78f066c083cf6, + 0xdbe014d4f9c391bb, 0x97fbb2dd1d13ffb3, 0x31c91e0af9ef8d4f, 0x094dfc98402a43ba, + 0x069bd61bea37b752, 0x5b72d762e8d986ca, 0x72ee31865904bc85, 0xd1f5fdc5cd36c33e, + 0xba9b4980a8947cad, 0xece8f05eac49ab43, 0x65fe1184abae38e7, 0x2d7cb9dea5d31452, + 0xcc71489476e467e3, 0x4c03a258a578c68c, 0x00efdf9ecb0fd8fc, 0x9924cad471e2666d, + 0x87f8668318f765e9, 0xcb4dc57c1b55f5d8, 0xd373835a86604859, 0xe526568b5540e482, + 0x1f39040f08586fec, 0xb764f3f00293f8e6, 0x049443a2f6bd50a8, 0x76fec88697d3941a, + 0x3efb70d039bae7a2, 0xe2f4611368eca8a8, 0x7c007a96e01d2425, 0xbbcce5768e69c5bf, + 0x784fb4985c42aac3, 0xf72b5091aa223874, 0x3630333fb1e62e07, 0x8e7319ebdebbb8de, + 0x2a3982bca959fa00, 0xb2b98b9f964ba9b3, 0xf7e31014adb71951, 0xebd0fca3703acc82, + 0xec654e2a2fe6419a, 0xb326132d55a52e2c, 0x2248c57f44502978, 0x32710c2f342daf16, + 0x0517b47b5acb2bec, 0x4c7a718fca270937, 0xd69142bed0bcc541, 0xe40ebcb8ff52ce88, + 0x3e44a2dbc9f828d4, 0xc74c2f4f8f873f58, 0x3dbf648eb799e45b, 0x33f22475ee0e86f8, + 0x1eb4f9ee16d47f65, 0x40f8d2b8712744e3, 0xb886b4da3cb14572, 0x2086326fbdd6f64d, + 0xcc3de5907dd882b9, 0xa2e8b49a5ee909df, 0xdbfb8e7823964c10, 0x70dd6089ef0df8d5, + 0x30141663cdd9c99f, 0x04b805325c240365, 0x7483d80314ac12d6, 0x2b271cb91aa7f5f9, + 0x97e2245362abddf0, 0x5a84f614232a9fab, 0xf71125fcda4b7fa2, 0x1ca5a61d74b27267, + 0x38cc6a9b3adbcb45, 0xdde1bb85dc653e39, 0xe9d0c8fa64f89fd4, 0x02c5fb1ecd2b4188, + 0xf2bd137bca5756e5, 0xadefe25d121be155, 0x56cd1c3c5d893a8e, 0x4c50d337beb65bb9, + 0x918c5151675cf567, 0xaba649ffcfb56a1e, 0x20c74ab26a2247cd, 0x71166bac853c08da, + 0xb07befe2e584fc5d, 0xda45ff2a588dbf32, 0xdb98b03c4d75095e, 0x60285ae1aaa65a4c, + 0xf93b686a263140b8, 0xde469752ee1c180e, 0xcec232dc04129aae, 0xeb916baa1835ea04, + 0xd49c21c8b64388ff, 0x72a82d9658864888, 0x003348ef7eac66a8, 0x7f6f67e655b209eb, + 0x532ffb0b7a941b25, 0xd940ade6128deede, 0xdf24f2a1af89fe23, 0x95aa3b4988195ae0, + 0x3da649404f94be4a, 0x692dad132c3f7e27, 0x40aee76ecaaa9eb8, 0x1294a01e09655024, + 0x6df797abdba4e4f5, 0xea2fb6024c1d7032, 0x5f4e0492295489fc, 0x57972914ea22e06a, + 0x9a8137d133aad473, 0xa2e6dd6ae7cdf2f3, 0x9f42644f18086647, 0x16d03301c170bd3e, + 0x908c416fa546656d, 0xe081503be22e123e, 0x077cf09116c4cc72, 0xcbd25cd264b7f229, + 0x3db2f468ec594031, 0x46c00e734c9badd5, 0xd0ec0ac72075d861, 0x3037cb3cf80b7630, + 0x574c3d7b3a2721c6, 0xae99906a0076824b, 0xb175a5418b532e70, 0xd8b3e251ee231ddd, + 0xb433eec25dca1966, 0x530f30dc5cff9a93, 0x9ff03d98b53cd335, 0xafc4225076558cdf, + 0xef81d3a28284402a, 0x110bdbf51c110a28, 0x9ae1b255d027e8f6, 0x7de3e0aa24688332, + 0xe483c3ecd2067ee2, 0xf829328b276137e6, 0xa413ccad57562cad, 0xe6118e8b496acb1f, + 0x8288dca6da5ec01f, 0xa53777dc88c17255, 0x8a00f1e0d5716eda, 0x618e6f47b7a720a8, + 0x9e3907b0c692a841, 0x978b42ca963f34f3, 0x75e4b0cd98a7d7ef, 0xde4dbd6e0b5f4752, + 0x0252e4153f34493f, 0x50f0e7d803734ef9, 0x237766a38ed167ee, 0x4124414001ee39a0, + 0xd08df643e535bb21, 0x34f575b5a9a80b74, 0x2c343af87297f755, 0xcd8b6d99d821f7cb, + 0xe376fd7256fc48ae, 0xe1b06e7334352885, 0xfa87b26f86c169eb, 0x36c1604665a971de, + 0xdba147c2239c8e80, 0x6b208e69fc7f0e24, 0x8795395b6f2b60c3, 0x05dabee9194907f4, + 0xb98175142f5ed902, 0x5e1701e2021ddc81, 0x0875aba2755eed08, 0x778d83289251de95, + 0x3bfbe46a039ecb31, 0xb24704fce4cbd7f9, 0x6985ffe9a7c91e3d, 0xc8efb13df249dabb, + 0xb1037e64b0f4c9f6, 0x55f69fd197d6b7c3, 0x672589d71d68a90c, 0xbebdb8224f50a77e, + 0x3f589f80007374a7, 0xd307f4635954182a, 0xcff5850c10d4fd90, 0xc6da02dfb6408e15, + 0x93daeef1e2b1a485, 0x65d833208aeea625, 0xe2b13fa13ed3b5fa, 0x67053538130fb68e, + 0xc1042f6598218fa9, 0xee5badca749b8a2e, 0x6d22a3f947dae37d, 0xb62c6d1657f4dbaf, + 0x6e007de69704c20b, 0x1af2b913fc3841d8, 0xdc0e47348e2e8e22, 0x9b1ddef1cf958b22, + 0x632ed6b0233066b8, 0xddd02d3311bed8f2, 0xf147cfe1834656e9, 0x399aaa49d511597a, + 0x6b14886979ec0309, 0x64fc4ac36b5afb97, 0xb82f78e07f7cf081, 0x10925c9a323d0e1b, + 0xf451c79ee13c63f6, 0x7c2fc180317876c7, 0x35a12bd9eecb7d22, 0x335654a539621f90, + 0xcc32a3f35db581f0, 0xc60748a80b2369cb, 0x7c4dd3b08591156b, 0xac1ced4b6de22291, + 0xa32cfa2df134def5, 0x627108918dea2a53, 0x0555b1608fcb4ff4, 0x143ee7ac43aaa33c, + 0xdae90ce7cf4fc218, 0x4d68fc2582bcf4b5, 0x37094e1849135d71, 0xf7857e09f3d49fd8, + 0x007538c503768be7, 0xedf648ba2f6be601, 0xaa347664dd72513e, 0xbe63893c6ef23b86, + 0x130b85710605af97, 0xdd765c6b1ef6ab56, 0xf3249a629a97dc6b, 0x2a114f9020fab8e5, + 0x5a69e027cfc6ad08, 0x3c4ccb36f1a5e050, 0x2e9e7d596834f0a5, 0x2430be6858fce789, + 0xe90b862f2466e597, 0x895e2884f159a9ec, 0x26ab8fa4902fcb57, 0xa6efff5c54e1fa50, + 0x333ac4e5811a8255, 0xa58d515f02498611, 0xfe5a09dcb25c6ef4, 0x03898988ab5f5818, + 0x289ff6242af6c617, 0x3d9dd59fd381ea23, 0x52d7d93d8a8aae51, 0xc76a123d511f786f, + 0xf68901edaf00c46c, 0x8c630871b590de80, 0x05209c308991e091, 0x1f809f99b4788177, + 0x11170c2eb6c19fd8, 0x44433c779062ba58, 0xc0acb51af1874c45, 0x9f2e134284809fa1, + 0xedb523bd15c619fa, 0x02d97fd53ecc23c0, 0xacaf05a34462374c, 0xddd9c6d34bffa11f, +} + +@(test) +chacha8rand_u64s :: proc(t: ^testing.T) { + st: runtime.Default_Random_State + context.random_generator = runtime.default_random_generator(&st) + rand.reset_bytes(transmute([]byte)(SAMPLE_SEED)) + + for expected, i in SAMPLE_OUTPUT { + actual := rand.uint64() + testing.expectf(t, expected == actual, "[%d]: got %x (expected %x)", i, actual, expected) + } +} + +@(test) +chacha8rand_bytes :: proc(t: ^testing.T) { + st: runtime.Default_Random_State + context.random_generator = runtime.default_random_generator(&st) + rand.reset_bytes(transmute([]byte)(SAMPLE_SEED)) + + // Test a massive bulk read. + buf := make([]byte, len(SAMPLE_OUTPUT) * size_of(u64), context.temp_allocator) + n := rand.read(buf) + testing.expectf(t, n == len(buf), "insufficient output: got %d (expected %d)", n, len(buf)) + + for expected, i in SAMPLE_OUTPUT { + actual, _ := endian.get_u64(buf[i*8:], .Little) + testing.expectf(t, expected == actual, "[%d]: got %x (expected %x)", i, actual, expected) + } + + // Test that the internal state always advances by a multiple of + // 8-bytes. + rand.reset_bytes(transmute([]byte)(SAMPLE_SEED)) + tmp: [8]byte + off: int + for i := 1; i < 8; i += 1 { + _ = rand.read(tmp[:i]) + testing.expect(t, bytes.equal(tmp[:i], buf[off:off+i])) + off += 8 + } +} diff --git a/tests/internal/test_fixed_capacity_dynamic_array.odin b/tests/internal/test_fixed_capacity_dynamic_array.odin new file mode 100644 index 000000000..49cf3a8f9 --- /dev/null +++ b/tests/internal/test_fixed_capacity_dynamic_array.odin @@ -0,0 +1,93 @@ +package test_internal + +import "core:testing" + +@(private="file") +slice_equal :: proc(a, b: []int) -> bool { + if len(a) != len(b) { + return false + } + + for a, i in a { + if b[i] != a { + return false + } + } + return true +} + + +@(test) +test_fixed_capacity_dynamic_array_removes :: proc(t: ^testing.T) { + array: [dynamic; 10]int + append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + + ordered_remove(&array, 0) + testing.expect(t, slice_equal(array[:], []int { 1, 2, 3, 4, 5, 6, 7, 8, 9 })) + ordered_remove(&array, 5) + testing.expect(t, slice_equal(array[:], []int { 1, 2, 3, 4, 5, 7, 8, 9 })) + ordered_remove(&array, 6) + testing.expect(t, slice_equal(array[:], []int { 1, 2, 3, 4, 5, 7, 9 })) + unordered_remove(&array, 0) + testing.expect(t, slice_equal(array[:], []int { 9, 2, 3, 4, 5, 7 })) + unordered_remove(&array, 2) + testing.expect(t, slice_equal(array[:], []int { 9, 2, 7, 4, 5 })) + unordered_remove(&array, 4) + testing.expect(t, slice_equal(array[:], []int { 9, 2, 7, 4 })) +} + +@(test) +test_fixed_capacity_dynamic_array_inject_at :: proc(t: ^testing.T) { + array: [dynamic; 13]int + append(&array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + + testing.expect(t, inject_at(&array, 0, 0), "Expected to be able to inject into fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })) + testing.expect(t, inject_at(&array, 0, 5), "Expected to be able to inject into fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 5, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 })) + testing.expect(t, inject_at(&array, len(array), 0), "Expected to be able to inject into fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 5, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 })) +} + +@(test) +test_fixed_capacity_dynamic_array_push_back_elems :: proc(t: ^testing.T) { + array: [dynamic; 2]int + testing.expect(t, slice_equal(array[:], []int { })) + testing.expect(t, append(&array, 0) == 1, "Expected to be able to append to empty fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 0 })) + testing.expect(t, append(&array, 1) == 1, "Expected to be able to append to fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 0, 1 })) + testing.expect(t, append(&array, 1, 2) == 0, "Expected to fail appending multiple elements beyond capacity of fixed capacity dynamic array") + clear(&array) + testing.expect(t, append(&array, 1) == 1, "Expected to be able to append to fixed capacity dynamic array") + testing.expect(t, append(&array, 2) == 1, "Expected to be able to append to fixed capacity dynamic array") + testing.expect(t, append(&array, 1) != 1, "Expected to fail appending to full fixed capacity dynamic array") + testing.expect(t, append(&array, 1, 2) != 2, "Expected to fail appending multiple elements to full fixed capacity dynamic array") + clear(&array) + testing.expect(t, slice_equal(array[:], []int { })) + testing.expect(t, append(&array, 1, 2, 3) != 3, "Expected to fail appending multiple elements to empty fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 1, 2 })) + clear(&array) + testing.expect(t, append(&array, 1, 2) == 2, "Expected to be able to append multiple elements to empty fixed capacity dynamic array") + testing.expect(t, slice_equal(array[:], []int { 1, 2 })) +} + +@(test) +test_fixed_capacity_dynamic_array_resize :: proc(t: ^testing.T) { + array: [dynamic; 4]int + + for i in 0..<4 { + append(&array, i+1) + } + testing.expect(t, slice_equal(array[:], []int{1, 2, 3, 4}), "Expected to initialize the array with 1, 2, 3, 4") + + clear(&array) + testing.expect(t, slice_equal(array[:], []int{}), "Expected to clear the array") + + non_zero_resize(&array, 4) + testing.expect(t, slice_equal(array[:], []int{1, 2, 3, 4}), "Expected non_zero_resize to set length 4 with previous values") + + clear(&array) + resize(&array, 4) + testing.expect(t, slice_equal(array[:], []int{0, 0, 0, 0}), "Expected resize to set length 4 with zeroed values") +} diff --git a/tests/internal/test_global_any.odin b/tests/internal/test_global_any.odin new file mode 100644 index 000000000..850884912 --- /dev/null +++ b/tests/internal/test_global_any.odin @@ -0,0 +1,40 @@ +package test_internal + +@(private="file") +global_any_from_proc: any = from_proc() + +from_proc :: proc "contextless" () -> f32 { + return 1.1 +} + +@(private="file") +global_any: any = 1 + +import "core:testing" + +@(test) +test_global_any :: proc(t: ^testing.T) { + as_f32, is_f32 := global_any_from_proc.(f32) + testing.expect(t, is_f32 == true) + testing.expect(t, as_f32 == 1.1) + + as_int, is_int := global_any.(int) + testing.expect(t, is_int == true) + testing.expect(t, as_int == 1) +} + +@(test) +test_static_any :: proc(t: ^testing.T) { + @(static) + var: any = 3 + + as_int, is_int := var.(int) + testing.expect(t, is_int == true) + testing.expect(t, as_int == 3) + + var = f32(1.1) + + as_f32, is_f32 := var.(f32) + testing.expect(t, is_f32 == true) + testing.expect(t, as_f32 == 1.1) +} diff --git a/tests/internal/test_imported_proc_groups.odin b/tests/internal/test_imported_proc_groups.odin new file mode 100644 index 000000000..e91af4bf5 --- /dev/null +++ b/tests/internal/test_imported_proc_groups.odin @@ -0,0 +1,11 @@ +package test_internal + +import "core:testing" +import "test_imported_proc_groups" + +// https://github.com/odin-lang/Odin/pull/6119 +@test +test_use_imported_proc_group_as_argument :: proc(t: ^testing.T) { + use_proc :: proc(proc()) { } + use_proc(test_imported_proc_groups.proc_group) +} diff --git a/tests/internal/test_imported_proc_groups/proc_group.odin b/tests/internal/test_imported_proc_groups/proc_group.odin new file mode 100644 index 000000000..59519ab9c --- /dev/null +++ b/tests/internal/test_imported_proc_groups/proc_group.odin @@ -0,0 +1,4 @@ +package test_imported_proc_groups + +proc_group :: proc{empty_proc} +empty_proc :: proc() { } diff --git a/tests/internal/test_intrinsics_enum_contiguous.odin b/tests/internal/test_intrinsics_enum_contiguous.odin new file mode 100644 index 000000000..7a6901b82 --- /dev/null +++ b/tests/internal/test_intrinsics_enum_contiguous.odin @@ -0,0 +1,24 @@ +package test_internal + +import "base:intrinsics" +import "core:testing" + +@(test) +test_intrinsics_enum_is_contiguous :: proc(t: ^testing.T) { + contiguous :: intrinsics.type_enum_is_contiguous + testing.expect(t, contiguous(enum { A=0, B=0, C=0 })) + testing.expect(t, contiguous(enum { A=0, B=1, C=2 })) + testing.expect(t, contiguous(enum { A=1, B=2, C=2 })) + testing.expect(t, contiguous(enum { A=-2, B=-1, C=0 })) + testing.expect(t, contiguous(enum { A=-8, B=-6, C=-7, D=-8 })) + testing.expect(t, contiguous(enum { C=4, A=3 })) + testing.expect(t, contiguous(enum { })) + testing.expect(t, contiguous(enum { A })) + testing.expect(t, contiguous(enum { Delta=-4 })) + testing.expect(t, contiguous(enum { X = 2 * len([?]u8{ 0 }) })) + testing.expect(t, contiguous(enum { Alpha=-2, Beta=-1, Gamma=0, Delta=-3 })) + + testing.expect(t, !contiguous(enum { A=1, B=3 })) + testing.expect(t, !contiguous(enum { B=-5, Beta=-3 })) + testing.expect(t, !contiguous(enum { A=0, B=-2 })) +} diff --git a/tests/internal/test_intrinsics_integer_to.odin b/tests/internal/test_intrinsics_integer_to.odin new file mode 100644 index 000000000..108318c9a --- /dev/null +++ b/tests/internal/test_intrinsics_integer_to.odin @@ -0,0 +1,34 @@ +package test_internal + +import "base:intrinsics" +import "core:testing" + +/* +example_usage :: proc(#any_int x: int) -> intrinsics.type_integer_to_unsigned(type_of(x)) { + T :: intrinsics.type_integer_to_unsigned(type_of(x)) + return 1< int { return 0 } + proc_1 :: proc(Bit_Set) -> int { return 1 } + proc_2 :: proc(int, Bit_Set) -> int { return 2 } + proc_3 :: proc(f32, Bit_Set) -> int { return 3 } + proc_4 :: proc(int, int, Bit_Set) -> int { return 4 } + proc_5 :: proc(Bit_Set, int, int, int) -> int { return 5 } + + testing.expect_value(t, group({.A}), 1) + testing.expect_value(t, group(9, {.A}), 2) + testing.expect_value(t, group(3.14, {.A}), 3) + testing.expect_value(t, group(9, 9, {.A}), 4) + testing.expect_value(t, group({.A}, 9, 9, 9), 5) +} + +@test +test_type_inference_on_literals_with_default_args :: proc(t: ^testing.T) { + { + Bit_Set :: bit_set[enum{A, B, C}] + proc_nil :: proc() { } + proc_default_arg :: proc(a: Bit_Set={.A}) -> Bit_Set { return a } + group :: proc{proc_nil, proc_default_arg} + + testing.expect_value(t, group(Bit_Set{.A}), Bit_Set{.A}) + testing.expect_value(t, group({.A}), Bit_Set{.A}) + } + { + Bit_Set :: bit_set[enum{A, B, C}] + proc_1 :: proc(a: Bit_Set={.A}) -> int { return 1 } + proc_2 :: proc(a: Bit_Set={.B}, b: Bit_Set={.C}) -> int { return 2 } + group :: proc{proc_1, proc_2} + + testing.expect_value(t, group(), 2) + testing.expect_value(t, group(Bit_Set{.A}), 2) + testing.expect_value(t, group({.A}), 2) + testing.expect_value(t, group({.B}, {.C}), 2) + } +} + +@test +test_type_inference_on_literals_for_various_types :: proc(t: ^testing.T) { + proc_nil :: proc() { } + + proc_array :: proc(a: [3]f32) -> [3]f32 { return a } + group_array :: proc{proc_nil, proc_array} + testing.expect_value(t, group_array([3]f32{1.1, 2.2, 3.3}), [3]f32{1.1, 2.2, 3.3}) + testing.expect_value(t, group_array({1.1, 2.2, 3.3}), [3]f32{1.1, 2.2, 3.3}) + testing.expect_value(t, group_array({0=1.1, 1=2.2, 2=3.3}), [3]f32{1.1, 2.2, 3.3}) + testing.expect_value(t, group_array({}), [3]f32{}) + + proc_slice_u8 :: proc(a: []u8) -> []u8 { return a } + group_slice_u8 :: proc{proc_nil, proc_slice_u8} + testing.expect_value(t, len(group_slice_u8([]u8{1, 2, 3})), 3) + testing.expect_value(t, len(group_slice_u8({1, 2, 3})), 3) + testing.expect_value(t, len(group_slice_u8({0=1, 1=2, 2=3})), 3) + testing.expect_value(t, len(group_slice_u8({})), 0) + testing.expect_value(t, group_slice_u8(nil) == nil, true) + + proc_dynamic_array :: proc(t: ^testing.T, array: [dynamic]u8, expected_len: int) { + if expected_len < 0 { + testing.expect_value(t, array == nil, true) + } else { + testing.expect_value(t, len(array), expected_len) + } + delete(array) + } + group_dynamic_array :: proc{proc_nil, proc_dynamic_array} + group_dynamic_array(t, [dynamic]u8{1, 2, 3}, 3) + group_dynamic_array(t, {1, 2, 3}, 3) + group_dynamic_array(t, {0=1, 1=2, 2=3}, 3) + group_dynamic_array(t, {}, 0) + group_dynamic_array(t, nil, -1) + + Enum :: enum{A, B, C} + proc_enum :: proc(a: Enum) -> Enum { return a } + group_enum :: proc{proc_nil, proc_enum} + testing.expect_value(t, group_enum(Enum.A), Enum.A) + testing.expect_value(t, group_enum(.A), Enum.A) + + proc_enumerated_array :: proc(a: [Enum]u8) -> [Enum]u8 { return a } + group_enumerated_array :: proc{proc_nil, proc_enumerated_array} + testing.expect_value(t, group_enumerated_array([Enum]u8{.A=1, .B=2, .C=3}), [Enum]u8{.A=1, .B=2, .C=3}) + testing.expect_value(t, group_enumerated_array({.A=1, .B=2, .C=3}), [Enum]u8{.A=1, .B=2, .C=3}) + + Bit_Set :: bit_set[enum{A, B, C}] + proc_bit_set :: proc(a: Bit_Set) -> Bit_Set { return a } + group_bit_set :: proc{proc_nil, proc_bit_set} + testing.expect_value(t, group_bit_set(Bit_Set{.A}), Bit_Set{.A}) + testing.expect_value(t, group_bit_set({.A}), Bit_Set{.A}) + testing.expect_value(t, group_bit_set({}), Bit_Set{}) + + Struct :: struct{a: int, b: int, c: int} + proc_struct :: proc(a: Struct) -> Struct { return a } + group_struct :: proc{proc_nil, proc_struct} + testing.expect_value(t, group_struct(Struct{a = 9}), Struct{a = 9}) + testing.expect_value(t, group_struct({a = 9}), Struct{a = 9}) + testing.expect_value(t, group_struct({}), Struct{}) + + Raw_Union :: struct #raw_union{int_: int, f32_: f32} + proc_raw_union :: proc(a: Raw_Union) -> Raw_Union { return a } + group_raw_union :: proc{proc_nil, proc_raw_union} + testing.expect_value(t, group_raw_union(Raw_Union{int_ = 9}).int_, 9) + testing.expect_value(t, group_raw_union({int_ = 9}).int_, 9) + testing.expect_value(t, group_raw_union({}).int_, 0) + + Union :: union{int, f32} + proc_union :: proc(a: Union) -> Union { return a } + group_union :: proc{proc_nil, proc_union} + testing.expect_value(t, group_union(int(9)).(int), 9) + testing.expect_value(t, group_union({}), nil) + + proc_map :: proc(t: ^testing.T, map_: map[u8]u8, expected_len: int) { + if expected_len < 0 { + testing.expect_value(t, map_ == nil, true) + } else { + testing.expect_value(t, len(map_), expected_len) + } + delete(map_) + } + group_map :: proc{proc_nil, proc_map} + group_map(t, map[u8]u8{1=1, 2=2}, 2) + group_map(t, {1=1, 2=2}, 2) + group_map(t, {}, 0) + group_map(t, nil, -1) + + Bit_Field :: bit_field u16 {a: u8|4, b: u8|4, c: u8|4} + proc_bit_field :: proc(a: Bit_Field) -> Bit_Field { return a } + group_bit_field :: proc{proc_nil, proc_bit_field} + testing.expect_value(t, group_bit_field(Bit_Field{a = 1}), Bit_Field{a = 1}) + testing.expect_value(t, group_bit_field({a = 1}), Bit_Field{a = 1}) + testing.expect_value(t, group_bit_field({}), Bit_Field{}) + + SOA_Array :: #soa[2]struct{int, int} + proc_soa_array :: proc(a: SOA_Array) -> SOA_Array { return a } + group_soa_array :: proc{proc_nil, proc_soa_array} + testing.expect_value(t, len(group_soa_array(SOA_Array{{}, {}})), 2) + testing.expect_value(t, len(group_soa_array({struct{int, int}{1, 2}, struct{int, int}{1, 2}})), 2) + testing.expect_value(t, len(group_soa_array({})), 2) + testing.expect_value(t, len(soa_zip(a=[]int{1, 2}, b=[]int{3, 4})), 2) + + proc_matrix :: proc(a: matrix[2,2]f32) -> matrix[2,2]f32 { return a } + group_matrix :: proc{proc_nil, proc_matrix} + testing.expect_value(t, group_matrix(matrix[2,2]f32{1, 2, 3, 4}), matrix[2,2]f32{1, 2, 3, 4}) + testing.expect_value(t, group_matrix(1), (matrix[2,2]f32)(1)) + testing.expect_value(t, group_matrix({1, 2, 3, 4}), matrix[2,2]f32{1, 2, 3, 4}) + testing.expect_value(t, group_matrix({}), matrix[2,2]f32{}) +} diff --git a/tests/internal/test_signedness_comparisons.odin b/tests/internal/test_signedness_comparisons.odin new file mode 100644 index 000000000..5e7431c7a --- /dev/null +++ b/tests/internal/test_signedness_comparisons.odin @@ -0,0 +1,34 @@ +package test_internal + +import "core:testing" + +@test +test_comparisons_5408 :: proc(t: ^testing.T) { + // See: https://github.com/odin-lang/Odin/pull/5408 + test_proc :: proc(lhs: $T, rhs: T) -> bool { + return lhs > rhs + } + + Test_Enum :: enum u32 { + SMALL_VALUE = 0xFF, + BIG_VALUE = 0xFF00_0000, // negative if interpreted as i32 + } + + testing.expect_value(t, test_proc(Test_Enum.SMALL_VALUE, Test_Enum.BIG_VALUE), false) + testing.expect_value(t, test_proc(Test_Enum(0xF), Test_Enum.BIG_VALUE), false) + testing.expect_value(t, test_proc(Test_Enum(0xF), Test_Enum(0xF000_0000)), false) + testing.expect_value(t, test_proc(Test_Enum.SMALL_VALUE, max(Test_Enum)), false) + testing.expect_value(t, test_proc(Test_Enum(0xF), max(Test_Enum)), false) +} + +test_signedness :: proc(t: ^testing.T) { + { + a, b := i16(32767), i16(0) + testing.expect_value(t, a > b, true) + } + + { + a, b := u16(65535), u16(0) + testing.expect_value(t, a > b, true) + } +} \ No newline at end of file diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 267a2e030..43a7136b7 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -3,22 +3,40 @@ if not exist "build\" mkdir build pushd build -set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style +set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused-defineables @echo on ..\..\..\odin test ..\test_issue_829.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_1592.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_1730.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_2056.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_2113.odin %COMMON% -debug || exit /b ..\..\..\odin test ..\test_issue_2466.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_2615.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_2694.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_3435.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_4210.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_4364.odin %COMMON% || exit /b ..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_2395.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "2" || exit /b ..\..\..\odin build ..\test_issue_5043.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_5097.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_5097-2.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_5265.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_5699.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_6068.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_6101.odin %COMMON% || exit /b +..\..\..\odin test ..\test_issue_6165.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_6240.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "3" || exit /b +..\..\..\odin build ..\test_issue_6401.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "3" || exit /b +..\..\..\odin test ..\test_pr_6470.odin %COMMON% || exit /b +..\..\..\odin test ..\test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b +..\..\..\odin test ..\test_pr_6476.odin %COMMON% || exit /b +..\..\..\odin check ..\test_issue_6484.odin -no-entry-point %COMMON% || exit /b +..\..\..\odin check ..\test_issue_6874.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b @echo off diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 5102ee307..3633a7606 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -4,19 +4,23 @@ set -eu mkdir -p build pushd build ODIN=../../../odin -COMMON="-define:ODIN_TEST_FANCY=false -file -vet -strict-style" +COMMON="-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused-defineables" set -x $ODIN test ../test_issue_829.odin $COMMON $ODIN test ../test_issue_1592.odin $COMMON +$ODIN test ../test_issue_1730.odin $COMMON $ODIN test ../test_issue_2056.odin $COMMON $ODIN build ../test_issue_2113.odin $COMMON -debug $ODIN test ../test_issue_2466.odin $COMMON $ODIN test ../test_issue_2615.odin $COMMON $ODIN test ../test_issue_2637.odin $COMMON $ODIN test ../test_issue_2666.odin $COMMON +$ODIN test ../test_issue_2694.odin $COMMON +$ODIN test ../test_issue_3435.odin $COMMON $ODIN test ../test_issue_4210.odin $COMMON +$ODIN test ../test_issue_4364.odin $COMMON $ODIN test ../test_issue_4584.odin $COMMON if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then echo "SUCCESSFUL 1/1" @@ -26,6 +30,55 @@ else fi $ODIN build ../test_issue_5043.odin $COMMON $ODIN build ../test_issue_5097.odin $COMMON +$ODIN build ../test_issue_5097-2.odin $COMMON +$ODIN build ../test_issue_5265.odin $COMMON +$ODIN test ../test_issue_5699.odin $COMMON +$ODIN test ../test_issue_6068.odin $COMMON +$ODIN test ../test_issue_6101.odin $COMMON +$ODIN test ../test_issue_6165.odin $COMMON +$ODIN test ../test_issue_6344.odin $COMMON +$ODIN test ../test_issue_6344.odin $COMMON -o:speed +$ODIN test ../test_issue_6396.odin $COMMON +$ODIN test ../test_pr_6476.odin $COMMON + +if [[ $($ODIN build ../test_issue_6240.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi +if [[ $($ODIN build ../test_issue_6401.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi +if [[ $($ODIN build ../test_issue_6594.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi +if [[ $($ODIN build ../test_issue_6621.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi +$ODIN test ../test_pr_6470.odin $COMMON +if [[ $($ODIN test ../test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi +$ODIN check ../test_issue_6484.odin -no-entry-point $COMMON +if [[ $($ODIN check ../test_issue_6874.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]] ; then + echo "SUCCESSFUL 1/1" +else + echo "SUCCESSFUL 0/1" + exit 1 +fi set +x diff --git a/tests/issues/test_issue_1730.odin b/tests/issues/test_issue_1730.odin new file mode 100644 index 000000000..c1c5c4cae --- /dev/null +++ b/tests/issues/test_issue_1730.odin @@ -0,0 +1,21 @@ +package test_issues + +import "core:testing" + +// Tests issue #1730 https://github.com/odin-lang/Odin/issues/1730 +@(test) +test_issue_1730 :: proc(t: ^testing.T) { + ll := [4]int{1, 2, 3, 4} + for l, i in ll.yz { + testing.expect(t, i <= 1) + if i == 0 { + testing.expect_value(t, l, 2) + } else if i == 1 { + testing.expect_value(t, l, 3) + } + } + + out: [4]int + out.yz = ll.yz + testing.expect_value(t, out, [4]int{0, 2, 3, 0}) +} diff --git a/tests/issues/test_issue_2694.odin b/tests/issues/test_issue_2694.odin new file mode 100644 index 000000000..01860d603 --- /dev/null +++ b/tests/issues/test_issue_2694.odin @@ -0,0 +1,42 @@ +package test_issues + +import "core:fmt" +import "core:encoding/json" +import "core:log" +import "core:mem" +import "core:testing" + +// This is a minimal reproduction of the code in #2694. +// It exemplifies the original problem as briefly as possible. + +SAMPLE_JSON :: ` +{ + "foo": 0, + "things": [ + { "a": "ZZZZ"}, + ] +} +` + +@test +test_issue_2694 :: proc(t: ^testing.T) { + into: struct { + foo: int, + things: []json.Object, + } + + scratch := new(mem.Scratch_Allocator) + defer free(scratch) + if mem.scratch_allocator_init(scratch, 4 * mem.Megabyte) != .None { + log.error("unable to initialize scratch allocator") + return + } + defer mem.scratch_allocator_destroy(scratch) + + err := json.unmarshal_string(SAMPLE_JSON, &into, allocator = mem.scratch_allocator(scratch)) + testing.expect(t, err == nil) + + output := fmt.tprintf("%v", into) + expected := `{foo = 0, things = [map[a="ZZZZ"]]}` + testing.expectf(t, output == expected, "\n\texpected: %q\n\tgot: %q", expected, output) +} diff --git a/tests/issues/test_issue_3435.odin b/tests/issues/test_issue_3435.odin new file mode 100644 index 000000000..3830869ed --- /dev/null +++ b/tests/issues/test_issue_3435.odin @@ -0,0 +1,38 @@ +package main + +import "base:runtime" +import "core:mem" +import "core:testing" +import "core:time" + +@test +test_issue_3435 :: proc(t: ^testing.T) { + testing.set_fail_timeout(t, time.Second) + allocator: mem.Buddy_Allocator + data := runtime.make_aligned([]byte, 64, 32) + defer delete(data) + + // mem.buddy_allocator_init(&allocator, data, 32) + + // Bypass the assertion that would normally keep this from happening by + // manually putting the allocator together. + allocator.head = cast(^mem.Buddy_Block)raw_data(data) + allocator.head.size = len(data) + allocator.head.is_free = true + allocator.tail = mem.buddy_block_next(allocator.head) + allocator.alignment = 32 + + context.allocator = mem.buddy_allocator(&allocator) + + // Three allocations in the space above is all that's needed to reproduce + // the bug seen in #3435; this is the most minimal reproduction possible. + a := make([]u8, 1) + testing.expect(t, len(a) == 1) + b := make([]u8, 1) + testing.expect(t, len(b) == 0) + c := make([]u8, 1) + testing.expect(t, len(c) == 0) + + // With the bugfix in place, the allocator should be sensible enough to not + // fall into an infinite loop anymore, even if the assertion is disabled. +} diff --git a/tests/issues/test_issue_4364.odin b/tests/issues/test_issue_4364.odin new file mode 100644 index 000000000..817a1a26b --- /dev/null +++ b/tests/issues/test_issue_4364.odin @@ -0,0 +1,18 @@ +// Tests issue #4364 https://github.com/odin-lang/Odin/issues/4364 +package test_issues + +import "core:testing" + +@test +test_const_array_fill_assignment :: proc(t: ^testing.T) { + MAGIC :: 12345 + Struct :: struct {x: int} + CONST_ARR : [4]Struct : Struct{MAGIC} + arr := CONST_ARR + + testing.expect_value(t, len(arr), 4) + testing.expect_value(t, arr[0], Struct{MAGIC}) + testing.expect_value(t, arr[1], Struct{MAGIC}) + testing.expect_value(t, arr[2], Struct{MAGIC}) + testing.expect_value(t, arr[3], Struct{MAGIC}) +} diff --git a/tests/issues/test_issue_5097-2.odin b/tests/issues/test_issue_5097-2.odin new file mode 100644 index 000000000..1e4ad59c9 --- /dev/null +++ b/tests/issues/test_issue_5097-2.odin @@ -0,0 +1,24 @@ +// Tests another variation of, this should compile #5097 https://github.com/odin-lang/Odin/issues/5097 +package test_issues + +Face :: ^FaceRec +GlyphSlot :: ^GlyphSlotRec +Size :: ^SizeRec + +SizeRec :: struct { + face: Face, +} + +GlyphSlotRec :: struct { + face: Face, +} + +FaceRec :: struct { + glyph: GlyphSlot, + size: Size, +} + +main :: proc() { + face: Face + _ = face +} diff --git a/tests/issues/test_issue_5265.odin b/tests/issues/test_issue_5265.odin new file mode 100644 index 000000000..f61f05b0a --- /dev/null +++ b/tests/issues/test_issue_5265.odin @@ -0,0 +1,8 @@ +// Tests issue #5265 https://github.com/odin-lang/Odin/issues/5265 +package test_issues + +main :: proc() { + a: i128 = 1 + assert(1 / a == 1) + assert(a / 1 == 1) +} \ No newline at end of file diff --git a/tests/issues/test_issue_5699.odin b/tests/issues/test_issue_5699.odin new file mode 100644 index 000000000..cc91799e1 --- /dev/null +++ b/tests/issues/test_issue_5699.odin @@ -0,0 +1,36 @@ +// Tests issue #5699 https://github.com/odin-lang/Odin/issues/5699 +package test_issues + +import "core:testing" + +Issue5699_Value :: struct { + value: i32, +} + +Issue5699_Result :: union { + Issue5699_Value, +} + +test_issue_5699_increment_union :: proc(counter: ^i32) -> Issue5699_Result { + counter^ += 1 + return Issue5699_Value{0} +} + +@test +test_issue_5699_union :: proc(t: ^testing.T) { + counter: i32 = 0 + _ = test_issue_5699_increment_union(&counter).(Issue5699_Value).value + testing.expectf(t, counter == 1, "\n\texpected: 1\n\tgot: %d", counter) +} + +test_issue_5699_increment_any :: proc(counter: ^i32) -> any { + counter^ += 1 + return Issue5699_Value{0} +} + +@test +test_issue_5699_any :: proc(t: ^testing.T) { + counter: i32 = 0 + _ = test_issue_5699_increment_any(&counter).(Issue5699_Value).value + testing.expectf(t, counter == 1, "\n\texpected: 1\n\tgot: %d", counter) +} diff --git a/tests/issues/test_issue_6068.odin b/tests/issues/test_issue_6068.odin new file mode 100644 index 000000000..88a21ee27 --- /dev/null +++ b/tests/issues/test_issue_6068.odin @@ -0,0 +1,92 @@ +// Tests issue #6068 https://github.com/odin-lang/Odin/issues/6068 +package test_issues + +import "core:testing" + +@test +test_issue_6068 :: proc(t: ^testing.T) { + { + check_be : i128be = -1 + check_le : i128le = -1 + value := -1 + reverse := i128be(value) + + // test variable + testing.expect(t, i128be(value) == check_be) + testing.expect(t, i128be(-1) == check_be) + testing.expect(t, cast(i128be)value == check_be) + testing.expect(t, cast(i128be)-1 == check_be) + testing.expect(t, i128be(int(-1)) == check_be) + testing.expect(t, cast(i128be)int(-1) == check_be) + testing.expect(t, i128le(value) == check_le) + testing.expect(t, i128le(-1) == check_le) + testing.expect(t, cast(i128le)value == check_le) + testing.expect(t, cast(i128le)-1 == check_le) + testing.expect(t, i128le(int(-1)) == check_le) + testing.expect(t, cast(i128le)int(-1) == check_le) + testing.expect(t, i128le(reverse) == check_le) + testing.expect(t, cast(i128le)reverse == check_le) + + // test literal + testing.expect(t, i128be(value) == -1) + testing.expect(t, i128be(-1) == -1) + testing.expect(t, cast(i128be)value == -1) + testing.expect(t, cast(i128be)-1 == -1) + testing.expect(t, i128be(int(-1)) == -1) + testing.expect(t, cast(i128be)int(-1) == -1) + testing.expect(t, i128le(value) == -1) + testing.expect(t, i128le(-1) == -1) + testing.expect(t, cast(i128le)value == -1) + testing.expect(t, cast(i128le)-1 == -1) + testing.expect(t, i128le(int(-1)) == -1) + testing.expect(t, cast(i128le)int(-1) == -1) + testing.expect(t, i128le(reverse) == -1) + testing.expect(t, cast(i128le)reverse == -1) + } + + // NOTE(ske): [llvm_backend_const.cpp:lb_big_int_to_llvm] + // floats behaved wonky when I tested because I forgot to sign extend whole + // rop so I added more tests here to be safe + { + check_be : f64be = -1.234 + check_le : f64le = -1.234 + value : f64 = -1.234 + reverse := f64be(value) + + // test variable + testing.expect(t, f64be(value) == check_be) + testing.expect(t, f64be(-1.234) == check_be) + testing.expect(t, cast(f64be)value == check_be) + testing.expect(t, cast(f64be)-1.234 == check_be) + testing.expect(t, f64be(f64(-1.234)) == check_be) + testing.expect(t, cast(f64be)f64(-1.234) == check_be) + testing.expect(t, f64le(value) == check_le) + testing.expect(t, f64le(-1.234) == check_le) + testing.expect(t, cast(f64le)value == check_le) + testing.expect(t, cast(f64le)-1.234 == check_le) + testing.expect(t, f64le(f64(-1.234)) == check_le) + testing.expect(t, cast(f64le)f64(-1.234) == check_le) + testing.expect(t, f64le(reverse) == check_le) + testing.expect(t, cast(f64le)reverse == check_le) + + // test literal + testing.expect(t, f64be(value) == -1.234) + testing.expect(t, f64be(-1.234) == -1.234) + testing.expect(t, cast(f64be)value == -1.234) + testing.expect(t, cast(f64be)-1.234 == -1.234) + testing.expect(t, f64be(f64(-1.234)) == -1.234) + testing.expect(t, cast(f64be)f64(-1.234) == -1.234) + testing.expect(t, f64le(value) == -1.234) + testing.expect(t, f64le(-1.234) == -1.234) + testing.expect(t, cast(f64le)value == -1.234) + testing.expect(t, cast(f64le)-1.234 == -1.234) + testing.expect(t, f64le(f64(-1.234)) == -1.234) + testing.expect(t, cast(f64le)f64(-1.234) == -1.234) + testing.expect(t, f64le(reverse) == -1.234) + testing.expect(t, cast(f64le)reverse == -1.234) + } + + testing.expect(t, i64be(-1) + i64be(1) == 0) + testing.expect(t, i64le(-1) + i64le(i64be(1)) == 0) + testing.expect(t, i64be(-7) * i64be(7) == -49) +} diff --git a/tests/issues/test_issue_6101.odin b/tests/issues/test_issue_6101.odin new file mode 100644 index 000000000..9f24ade52 --- /dev/null +++ b/tests/issues/test_issue_6101.odin @@ -0,0 +1,23 @@ +// Tests issue #6101 https://github.com/odin-lang/Odin/issues/6101 +package test_issues + +import "core:testing" + +@(test) +test_issue_6101_bmp :: proc(t: ^testing.T) { + s := string16("\u732b") + testing.expect_value(t, len(s), 1) + + u := transmute([]u16)s + testing.expect_value(t, u[0], 0x732b) +} + +@(test) +test_issue_6101_non_bmp :: proc(t: ^testing.T) { + s := string16("\U0001F63A") + testing.expect_value(t, len(s), 2) + + u := transmute([]u16)s + testing.expect_value(t, u[0], 0xD83D) + testing.expect_value(t, u[1], 0xDE3A) +} diff --git a/tests/issues/test_issue_6165.odin b/tests/issues/test_issue_6165.odin new file mode 100644 index 000000000..b16995f0e --- /dev/null +++ b/tests/issues/test_issue_6165.odin @@ -0,0 +1,13 @@ +// Tests issue #6165 https://github.com/odin-lang/Odin/issues/6165 +package test_issues + +import "core:testing" + +@(test) +test_issue_6165 :: proc(t: ^testing.T) { + TXT :: #load(ODIN_ROOT + "LICENSE") + + // We don't really care about the length. The test is whether this compiles, or + // if the compiler says it can't find the file we know to exist. + assert(len(TXT) > 0) +} \ No newline at end of file diff --git a/tests/issues/test_issue_6240.odin b/tests/issues/test_issue_6240.odin new file mode 100644 index 000000000..a56f44f33 --- /dev/null +++ b/tests/issues/test_issue_6240.odin @@ -0,0 +1,14 @@ +// Tests issue #6240 https://github.com/odin-lang/Odin/issues/6240 +package test_issues + +// should error - N=10 does not match bit_set range 0..<5 +foo :: proc($N: int, b: $B/bit_set[0 ..< N]) {} + +// should error without segfaulting - undefined identifier in bit_set range +bar :: proc(b: $B/bit_set[0 ..< asdf]) {} + +main :: proc() { + b: bit_set[0 ..< 5] + foo(10, b) + bar(bit_set[0 ..< 1]{}) +} diff --git a/tests/issues/test_issue_6344.odin b/tests/issues/test_issue_6344.odin new file mode 100644 index 000000000..834ca25db --- /dev/null +++ b/tests/issues/test_issue_6344.odin @@ -0,0 +1,72 @@ +// Tests issue #6344 https://github.com/odin-lang/Odin/issues/6344 +package test_issues + +import "core:testing" + +@(test) +test_soa_dynamic_field_write :: proc(t: ^testing.T) { + V :: struct { + x: f32, + y: f32, + } + + array := make(#soa[dynamic]V, 4, 8) + defer delete(array) + + for i in 0 ..< 4 { + array[i] = V{f32(i), f32(i) * 2} + } + + // Simple write through field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + array.x[i] = f32(i) * 10 + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 10) + testing.expect_value(t, array[2].x, 20) + testing.expect_value(t, array[3].x, 30) + + // Compound write through field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + array.x[i] += array.y[i] + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 12) + testing.expect_value(t, array[2].x, 24) + testing.expect_value(t, array[3].x, 36) +} + +@(test) +test_soa_slice_field_write :: proc(t: ^testing.T) { + V :: struct { + x: f32, + y: f32, + } + + array := make(#soa[dynamic]V, 4, 8) + defer delete(array) + + for i in 0 ..< 4 { + array[i] = V{f32(i), f32(i) * 2} + } + + slice := array[:] + + // Write through slice field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + slice.x[i] = f32(i) * 10 + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 10) + testing.expect_value(t, array[2].x, 20) + testing.expect_value(t, array[3].x, 30) + + // Compound write through slice field-first indexing + for i in 0 ..< 4 { + slice.x[i] += slice.y[i] + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 12) + testing.expect_value(t, array[2].x, 24) + testing.expect_value(t, array[3].x, 36) +} diff --git a/tests/issues/test_issue_6396.odin b/tests/issues/test_issue_6396.odin new file mode 100644 index 000000000..5a0e7527c --- /dev/null +++ b/tests/issues/test_issue_6396.odin @@ -0,0 +1,23 @@ +// Tests issue #6396 https://github.com/odin-lang/Odin/issues/6396 +package test_issues + +import "core:testing" + +Issue6396_Full_Width_Field :: bit_field u32 { + a: u32 | 32, +} + +@test +test_issue_6396_full_width_bit_field_literal :: proc(t: ^testing.T) { + f0: Issue6396_Full_Width_Field = {a = 7} + testing.expect_value(t, f0.a, u32(7)) + + f0 = {a = 3} + testing.expect_value(t, f0.a, u32(3)) + + f0 = Issue6396_Full_Width_Field{a = 11} + testing.expect_value(t, f0.a, u32(11)) + + f0.a = 12 + testing.expect_value(t, f0.a, u32(12)) +} diff --git a/tests/issues/test_issue_6401.odin b/tests/issues/test_issue_6401.odin new file mode 100644 index 000000000..0f7cd58b6 --- /dev/null +++ b/tests/issues/test_issue_6401.odin @@ -0,0 +1,16 @@ +// Tests issue #6401 https://github.com/odin-lang/Odin/issues/6401 +package test_issues + +Wrapper :: struct(T: typeid) { + value: T, +} + +A :: struct { + value: Wrapper(B), +} + +B :: struct { + value: A, +} + +main :: proc() {} diff --git a/tests/issues/test_issue_6484.odin b/tests/issues/test_issue_6484.odin new file mode 100644 index 000000000..d115a12ef --- /dev/null +++ b/tests/issues/test_issue_6484.odin @@ -0,0 +1,17 @@ +// Tests issue #6484 https://github.com/odin-lang/Odin/pull/6484 +package test_issues + +foreign import lib "this_library_does_not_exist" + +foreign lib { + foo :: proc(int) --- + when true {} + when true {} + bar :: proc() --- +} + +foo_bar :: proc { + foo, + bar, +} + diff --git a/tests/issues/test_issue_6594.odin b/tests/issues/test_issue_6594.odin new file mode 100644 index 000000000..d332c72da --- /dev/null +++ b/tests/issues/test_issue_6594.odin @@ -0,0 +1,9 @@ +// Test issue #6594 https://github.com/odin-lang/Odin/issues/6594 +package test_issues + +a := a + +main :: proc() { + _ = a + 1 +} + diff --git a/tests/issues/test_issue_6621.odin b/tests/issues/test_issue_6621.odin new file mode 100644 index 000000000..ca76b23d5 --- /dev/null +++ b/tests/issues/test_issue_6621.odin @@ -0,0 +1,10 @@ +// Tests issue #6621 https://github.com/odin-lang/Odin/issues/6621 +package test_issues + +t: struct { + next: ^type_of(t), +} + +main :: proc() { + _ = t +} diff --git a/tests/issues/test_issue_6853.odin b/tests/issues/test_issue_6853.odin new file mode 100644 index 000000000..fec4951a5 --- /dev/null +++ b/tests/issues/test_issue_6853.odin @@ -0,0 +1,30 @@ +package test_issues + +import "core:testing" + +@(test) +test_issue_6853 :: proc(t: ^testing.T) { + + test_s :: struct { + a, b, c, d, e: u64, + } + + expected := test_s{1, 2, 3, 4, 5} + + case0 :: proc() -> (u64, u64) {return 1, 2} + test0 := test_s{case0(), 3, 4, 5} + testing.expect_value(t, test0, expected) + + case1 :: proc() -> (u64, u64, u64) {return 1, 2, 3} + test1 := test_s{case1(), 4, 5} + testing.expect_value(t, test1, expected) + + case2 :: proc() -> (u64, u64) {return 2, 3} + test2 := test_s{1, case2(), 4, 5} + testing.expect_value(t, test2, expected) + + case3_1 :: proc() -> (u64, u64) {return 1, 2} + case3_2 :: proc() -> (u64, u64) {return 3, 4} + test3 := test_s{case3_1(), case3_2(), 5} + testing.expect_value(t, test3, expected) +} diff --git a/tests/issues/test_issue_6874.odin b/tests/issues/test_issue_6874.odin new file mode 100644 index 000000000..946fef39d --- /dev/null +++ b/tests/issues/test_issue_6874.odin @@ -0,0 +1,35 @@ +// Test for issue #6874 https://github.com/odin-lang/Odin/issues/6874 + +package test_issues + +import "core:fmt" + +PersonData :: struct { + health: int, + age: int, +} + +MyUnion :: union { + f32, + int, + PersonData, +} + +change_union_data :: proc(data: MyUnion) { + switch &v in data { + case int: + v = 10 + case f32: + fmt.println("f32") + case PersonData: + fmt.println("PersonData") + fmt.println(v) + } +} + +main :: proc() { + val: MyUnion = int(12) + fmt.printfln("Before the call: %v", val) + change_union_data(val) + fmt.printfln("After the call: %v", val) +} diff --git a/tests/issues/test_pr_6470.odin b/tests/issues/test_pr_6470.odin new file mode 100644 index 000000000..d2427b335 --- /dev/null +++ b/tests/issues/test_pr_6470.odin @@ -0,0 +1,79 @@ +// Tests PR #6470 https://github.com/odin-lang/Odin/pull/6470 +package test_issues + +TEST_EXPECT_FAILURE :: #config(TEST_EXPECT_FAILURE, false) + +// Interfaces +IFoo :: struct { + foo: proc(self: ^IFoo) -> string, +} + +IBar :: struct { + bar: proc(self: ^IBar) -> string, +} + + +// Virtual table holders +Foo :: struct { + using vt: IFoo, +} + +// This is OK, but be careful! +Foo_Bar :: struct #raw_union { + using vt_foo: IFoo, + using vt_bar: IBar, +} + +// Implementation via Foo +Foo_Impl :: IFoo { + foo = proc(self: ^Foo) -> string { + return "Foo" + }, +} + +// Implementations via Foo_Bar +Foo_Bar_Foo_Impl :: IFoo { + foo = proc(self: ^Foo_Bar) -> string { + return "Foo_Bar: Foo" + }, +} + +Foo_Bar_Bar_Impl :: IBar { + bar = proc(self: ^Foo_Bar) -> string { + return "Foo_Bar: Bar" + }, +} + +when TEST_EXPECT_FAILURE { + // Will not be allowed in to be used in an implementation: + // The interface and implementation do not share the same address. + Invalid_Foo :: struct { + x: int, + using vt: IFoo, + } + + Invalid_Foo_Impl :: IFoo { + // Will not compile: + foo = proc(self: ^Invalid_Foo) -> string { + return "" + }, + } +} + +import "core:testing" + +@test +test_const_array_fill_assignment :: proc(t: ^testing.T) { + foo := Foo { + vt = Foo_Impl, + } + testing.expect_value(t, foo->foo(), "Foo") + + foo_bar := Foo_Bar { + vt_foo = Foo_Bar_Foo_Impl, + } + testing.expect_value(t, foo_bar->foo(), "Foo_Bar: Foo") + + foo_bar.vt_bar = Foo_Bar_Bar_Impl + testing.expect_value(t, foo_bar->bar(), "Foo_Bar: Bar") +} diff --git a/tests/issues/test_pr_6476.odin b/tests/issues/test_pr_6476.odin new file mode 100644 index 000000000..b63aec674 --- /dev/null +++ b/tests/issues/test_pr_6476.odin @@ -0,0 +1,35 @@ +package test_issues + +import "core:testing" +import "core:mem" + +// Test for a problem encountered with the scratch allocator. +// Say you have a scratch allocator with an arena size of N. +// If you make an allocation whose size is <= N but greater than +// the amount of free space left in the arena, the allocator +// will return a slice of memory from the start of the arena, +// overlapping previous allocations. (the expected +// behavior is it satisfies the request with the backup allocator) + +@test +test_scratch_smash :: proc(t: ^testing.T) { + // setup + frAlloc: mem.Scratch + err := mem.scratch_init(&frAlloc, 1 * mem.Kilobyte) + testing.expect(t, err == nil) + + talloc := mem.scratch_allocator(&frAlloc) + defer mem.scratch_destroy(&frAlloc) + + // First allocation fits in arena. + a1 := make([]byte, 512, talloc) + + // Second allocation does not fit in the free space, but is + // <= the arena size. + a2 := make([]byte, 1024, talloc) + + // Should be true, but bug in scratch allocator returns space + // overlapping a1 when allocating a2. + testing.expect(t, &a1[0] != &a2[0]) +} + diff --git a/tests/vendor/all.odin b/tests/vendor/all.odin index ba5628252..f26217c8f 100644 --- a/tests/vendor/all.odin +++ b/tests/vendor/all.odin @@ -2,3 +2,4 @@ package tests_vendor @(require) import "glfw" @(require) import _ "lua/5.4" +@(require) import _ "curl" diff --git a/tests/vendor/curl/test_vendor_curl.odin b/tests/vendor/curl/test_vendor_curl.odin new file mode 100644 index 000000000..ce54d0ab1 --- /dev/null +++ b/tests/vendor/curl/test_vendor_curl.odin @@ -0,0 +1,42 @@ +#+build windows, linux, darwin +package test_vendor_curl + +import "base:runtime" +import "core:testing" +import "vendor:curl" + +@(test) +test_curl :: proc(t: ^testing.T) { + data_callback :: proc "c" (contents: [^]byte, size: int, nmemb: int, userp: rawptr) -> int { + context = runtime.default_context() + + real_size := size * nmemb + memory := (^[dynamic]byte)(userp) + + n := len(memory^) + resize(memory, n + real_size) + copy(memory[n:], contents[:real_size]) + + return real_size + } + + + curl.global_init(curl.GLOBAL_ALL) + + c := curl.easy_init() + testing.expect(t, c != nil, "curl.easy_init failed") + + defer curl.easy_cleanup(c) + + memory, memory_err := make([dynamic]byte) + testing.expectf(t, memory_err == nil, "make failed: %v", memory_err) + defer delete(memory) + + curl.easy_setopt(c, .URL, cstring("https://odin-lang.org")) + curl.easy_setopt(c, .WRITEFUNCTION, data_callback) + curl.easy_setopt(c, .WRITEDATA, &memory) + curl.easy_setopt(c, .USERAGENT, cstring("libcurl-agent/1.0")) + + res := curl.easy_perform(c) + testing.expectf(t, res == nil, "curl.easy_perform failed: %v", res) +} diff --git a/vendor/ENet/enet.odin b/vendor/ENet/enet.odin index b4ef3fe70..235cc5684 100644 --- a/vendor/ENet/enet.odin +++ b/vendor/ENet/enet.odin @@ -1,3 +1,4 @@ +// Bindings for [[ ENet ; https://github.com/lsalzman/enet ]]. package ENet when ODIN_OS == .Windows { diff --git a/vendor/OpenEXRCore/exr_base.odin b/vendor/OpenEXRCore/exr_base.odin index cf059ffcf..4dffe86e3 100644 --- a/vendor/OpenEXRCore/exr_base.odin +++ b/vendor/OpenEXRCore/exr_base.odin @@ -1,3 +1,4 @@ +// Bindings for [[ OpenEXRCore ; https://github.com/AcademySoftwareFoundation/openexr/tree/main/src/lib/OpenEXRCore ]]. package vendor_openexr OPENEXRCORE_SHARED :: #config(OPENEXRCORE_SHARED, false) diff --git a/vendor/OpenGL/helpers.odin b/vendor/OpenGL/helpers.odin index 0bd8e451b..9c9c74d09 100644 --- a/vendor/OpenGL/helpers.odin +++ b/vendor/OpenGL/helpers.odin @@ -1,11 +1,13 @@ +// OpenGL function pointer loader implemented in Odin. Supports the `core` profile up to version 4.6. package vendor_gl // Helper for loading shaders into a program -import "core:os" -import "core:fmt" -import "core:strings" -import "base:runtime" +import "core:os" +import "core:fmt" +import "core:strings" +@(require) import "core:time" +import "base:runtime" _ :: fmt _ :: runtime @@ -149,7 +151,10 @@ create_and_link_program :: proc(shader_ids: []u32, binary_retrievable := false) } load_compute_file :: proc(filename: string, binary_retrievable := false) -> (program_id: u32, ok: bool) { - cs_data := os.read_entire_file(filename) or_return + cs_data, cs_data_err := os.read_entire_file(filename, context.allocator) + if cs_data_err != nil { + return 0, false + } defer delete(cs_data) // Create the shaders @@ -164,10 +169,16 @@ load_compute_source :: proc(cs_data: string, binary_retrievable := false) -> (pr } load_shaders_file :: proc(vs_filename, fs_filename: string, binary_retrievable := false) -> (program_id: u32, ok: bool) { - vs_data := os.read_entire_file(vs_filename) or_return + vs_data, vs_data_err := os.read_entire_file(vs_filename, context.allocator) + if vs_data_err != nil { + return 0, false + } defer delete(vs_data) - fs_data := os.read_entire_file(fs_filename) or_return + fs_data, fs_data_err := os.read_entire_file(fs_filename, context.allocator) + if fs_data_err != nil { + return 0, false + } defer delete(fs_data) return load_shaders_source(string(vs_data), string(fs_data), binary_retrievable) @@ -191,14 +202,14 @@ when ODIN_OS == .Windows { update_shader_if_changed :: proc( vertex_name, fragment_name: string, program: u32, - last_vertex_time, last_fragment_time: os.File_Time, + last_vertex_time, last_fragment_time: time.Time, ) -> ( old_program: u32, - current_vertex_time, current_fragment_time: os.File_Time, + current_vertex_time, current_fragment_time: time.Time, updated: bool, ) { - current_vertex_time, _ = os.last_write_time_by_name(vertex_name) - current_fragment_time, _ = os.last_write_time_by_name(fragment_name) + current_vertex_time, _ = os.modification_time_by_path(vertex_name) + current_fragment_time, _ = os.modification_time_by_path(fragment_name) old_program = program if current_vertex_time != last_vertex_time || current_fragment_time != last_fragment_time { @@ -219,13 +230,13 @@ when ODIN_OS == .Windows { update_shader_if_changed_compute :: proc( compute_name: string, program: u32, - last_compute_time: os.File_Time, + last_compute_time: time.Time, ) -> ( old_program: u32, - current_compute_time: os.File_Time, + current_compute_time: time.Time, updated: bool, ) { - current_compute_time, _ = os.last_write_time_by_name(compute_name) + current_compute_time, _ = os.modification_time_by_path(compute_name) old_program = program if current_compute_time != last_compute_time { diff --git a/vendor/OpenGL/wrappers.odin b/vendor/OpenGL/wrappers.odin index 1eb8fc72f..d68efee6c 100644 --- a/vendor/OpenGL/wrappers.odin +++ b/vendor/OpenGL/wrappers.odin @@ -880,7 +880,7 @@ when !GL_DEBUG { // VERSION_1_2 DrawRangeElements :: proc "c" (mode, start, end: u32, count: i32, type: u32, indices: rawptr, loc := #caller_location) { impl_DrawRangeElements(mode, start, end, count, type, indices); debug_helper(loc, 0, mode, start, end, count, type, indices) } - TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, pixels: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, pixels) } + TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, data: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, data); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, data) } TexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: u32, pixels: rawptr, loc := #caller_location) { impl_TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) } CopyTexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, x, y, width, height: i32, loc := #caller_location) { impl_CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, x, y, width, height) } diff --git a/vendor/README.md b/vendor/README.md index 186e6422a..53ff46179 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -6,60 +6,112 @@ Its use is similar to that of `core:` packages, which would be available in any Presently, the `vendor:` collection comprises the following packages: +## cgltf + +[cgltf](https://github.com/jkuhlmann/cgltf) is a [glTF2.0](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) loader and writer. + +Used in: [bgfx](https://github.com/bkaradzic/bgfx), [Filament](https://github.com/google/filament), [gltfpack](https://github.com/zeux/meshoptimizer/tree/master/gltf), [raylib](https://github.com/raysan5/raylib), [Unigine](https://developer.unigine.com/en/docs/2.14.1/third_party?rlang=cpp#cgltf), and more! + +See also LICENCE in `cgltf` directory itself. + +## CommonMark + +[CMark](https://github.com/commonmark/cmark) CommonMark parsing library. + +See also LICENSE in the `commonmark` directory itself. +Includes full bindings and Windows `.lib` and `.dll`. + +## curl + +[curl](https://curl.haxx.se) http(s) library. + +See also LICENSE in the `curl` directory itself. +Includes full bindings and Windows `.lib`. + +## ENet + +[ENet](http://enet.bespin.org/) Reliable UDP networking library. + +`enet.lib` and `enet64.lib` are available under ENet's [MIT](http://enet.bespin.org/License.html) license. + +See also LICENSE in the `ENet` directory itself. + +## fontstash (Port) + +[Font stash](https://github.com/memononen/fontstash) is a light-weight online font texture atlas builder. It uses stb_truetype to render fonts on demand to a texture atlas. + +## GGPO + +[GGPO](https://www.ggpo.net/) GGPO Rollback Networking SDK. + +Zero-input latency networking library for peer-to-peer games. + +See also LICENSE in the `GGPO` directory itself. + +## GLFW + +Bindings for the multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input API [GLFW](https://github.com/glfw/glfw). + +`GLFW.dll` and `GLFW.lib` are available under GLFW's [zlib/libpng](https://www.glfw.org/license.html) license. + +See also LICENSE.txt in the `glfw` directory itself. + +## kb + +[kb](https://github.com/JimmyLefevre/kb) provides ICU-like text segmentation (i.e. breaking Unicode text by direction, line, word and grapheme). It also provides Harfbuzz-like text shaping for OpenType fonts, which means it is capable of handling complex script layout and ligatures, among other things. + +It does not handle rasterization. It will only help you know which glyphs to display where! + +See also LICENSE in the `kb/src` directory. + +## lua + +[lua](https://www.lua.org) provides bindings and Windows and Linux libraries for Lua versions 5.1 through 5.4. + +See also LICENSE in the `lua` directory itself. + ## microui (Port) A tiny, portable, immediate-mode UI library written in Odin. [rxi/microui](https://github.com/rxi/microui) This package is available under the MIT license. See `LICENSE` for more details. +## miniaudio + +[miniaudio](https://miniaud.io) is a cross-platform An audio playback and capture library. + +Miniaudio is open source with a permissive license of your choice of public domain or [MIT No Attribution](https://github.com/aws/mit-0). + +## nanovg (Port) + +[NanoVG](https://github.com/memononen/nanovg) is a small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations. + +## OpenEXRCore + +[OpenEXRCore](https://github.com/AcademySoftwareFoundation/openexr) provides the specification and reference implementation of the EXR file format, the professional-grade image storage format of the motion picture industry. + +See also LICENSE.md in the `OpenEXRCore` directory itself. + ## OpenGL Bindings for the OpenGL graphics API and helpers in idiomatic Odin to, for example, reload shaders when they're changed on disk. This package is available under the MIT license. See `LICENSE` and `LICENSE_glad` for more details. +## PortMidi + +[PortMidi](https://sourceforge.net/projects/portmedia/) Portable Real-Time MIDI Library. + +`portmidi_s.lib` is available under PortMidi's [MIT](https://sourceforge.net/projects/portmedia/) license. + +See also LICENSE.txt in the `portmidi` directory itself. + ## raylib Bindings for the raylib, a simple and easy-to-use library to enjoy videogames programming, in idiomatic Odin. This package is available under the Zlib license. See `LICENSE` for more details. -## STB - -Bindings/ports for many of the [STB libraries](https://github.com/nothings/stb), single-file public domain (or MIT licensed) libraries for C/C++. - -### vendor:stb/easy_font - -quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc - -Source port of `stb_easy_font.h` - -### vendor:stb/image -Image _loader_, _writer_, and _resizer_. - -image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC - -image writing to disk: PNG, TGA, BMP - -resize images larger/smaller with good quality - -Bindings of `stb_image.h`, `stb_image_rewrite.h`, `stb_image_resize.h` - -### vendor:stb/rect_pack -simple 2D rectangle packer with decent quality - -Bindings of `stb_rect_pack.h` - -### vendor:stb/truetype -parse, decode, and rasterize characters from truetype fonts - -Bindings of `stb_truetype.h` - -### vendor:stb/vorbis -decode ogg vorbis files from file/memory to float/16-bit signed output - -Bindings of `stb_vorbis.c` - ## SDL2 Bindings for the cross platform multimedia API [SDL2](https://github.com/libsdl-org/SDL) and its sub-projects. @@ -90,71 +142,69 @@ Bindings for SDL's font rendering library, subject to SDL's [zlib](https://githu SDL2 TTF relies on 3rd party libraries `zlib`, available under the ZLIB license, and `FreeType`, available under its own license. Both can be found in the `ttf` directory. +## SDL3 + +Bindings for the cross platform multimedia API [SDL3](https://github.com/libsdl-org/SDL) and its sub-projects. + +`SDL3.dll` and `SDL3.lib` are available under SDL's [zlib](https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt) license. + +See also LICENSE.txt in the `sdl3` directory itself. + +### SDL3 Image + +Bindings for SDL's image decoding library, subject to SDL's [zlib](https://github.com/libsdl-org/SDL_image/blob/main/LICENSE.txt) license. + +SDL2 Image relies on 3rd party libraries to support various image formats. You can find the licenses for these in the `image` directory, alongside SDL\_image's own license. + +### SDL3 TTF + +Bindings for SDL's font rendering library, subject to SDL's [zlib](https://github.com/libsdl-org/SDL_ttf/blob/main/LICENSE.txt) license. + +SDL3 TTF relies on 3rd party libraries to support various font formats. You can find the licenses for these in the `ttf` directory, alongside SDL\_ttf's own license. + +## STB + +Bindings/ports for many of the [STB libraries](https://github.com/nothings/stb), single-file public domain (or MIT licensed) libraries for C/C++. + +### vendor:stb/easy_font + +quick-and-dirty easy-to-deploy bitmap font for printing frame rate, etc + +Source port of `stb_easy_font.h` + +### vendor:stb/image +Image _loader_, _writer_, and _resizer_. + +image loading/decoding from file/memory: JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC + +image writing to disk: PNG, TGA, BMP + +resize images larger/smaller with good quality + +Bindings of `stb_image.h`, `stb_image_rewrite.h`, `stb_image_resize.h` + +### vendor:stb/rect_pack +simple 2D rectangle packer with decent quality + +Bindings of `stb_rect_pack.h` + +### vendor:stb/truetype +parse, decode, and rasterize characters from truetype fonts + +Bindings of `stb_truetype.h` + +### vendor:stb/vorbis +decode ogg vorbis files from file/memory to float/16-bit signed output + +Bindings of `stb_vorbis.c` + ## Vulkan The Vulkan 3D graphics API are automatically generated from headers provided by Khronos, and are made available under the [Apache License, Version 2.0](https://github.com/KhronosGroup/Vulkan-Headers/blob/master/LICENSE.txt). -## GLFW - -Bindings for the multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input API [GLFW](https://github.com/glfw/glfw). - -`GLFW.dll` and `GLFW.lib` are available under GLFW's [zlib/libpng](https://www.glfw.org/license.html) license. - -See also LICENSE.txt in the `glfw` directory itself. - -## PortMidi - -[PortMidi](https://sourceforge.net/projects/portmedia/) Portable Real-Time MIDI Library. - -`portmidi_s.lib` is available under PortMidi's [MIT](https://sourceforge.net/projects/portmedia/) license. - -See also LICENSE.txt in the `portmidi` directory itself. - - -## ENet - -[ENet](http://enet.bespin.org/) Reliable UDP networking library. - -`enet.lib` and `enet64.lib` are available under ENet's [MIT](http://enet.bespin.org/License.html) license. - -See also LICENSE in the `ENet` directory itself. - -## GGPO - -[GGPO](https://www.ggpo.net/) GGPO Rollback Networking SDK. - -Zero-input latency networking library for peer-to-peer games. - -See also LICENSE in the `GGPO` directory itself. - -## CommonMark - -[CMark](https://github.com/commonmark/cmark) CommonMark parsing library. - -See also LICENSE in the `commonmark` directory itself. -Includes full bindings and Windows `.lib` and `.dll`. - ## zlib [zlib](https://github.com/madler/zlib) data compression library See also LICENSE in the `zlib` directory itself. Includes full bindings. - - -## cgltf - - -[cgltf](https://github.com/jkuhlmann/cgltf) is a [glTF2.0](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) loader and writer. - -Used in: [bgfx](https://github.com/bkaradzic/bgfx), [Filament](https://github.com/google/filament), [gltfpack](https://github.com/zeux/meshoptimizer/tree/master/gltf), [raylib](https://github.com/raysan5/raylib), [Unigine](https://developer.unigine.com/en/docs/2.14.1/third_party?rlang=cpp#cgltf), and more! - -Se also LICENCE in `cgltf` directory itself. - -## nanovg (Port) - -[NanoVG](https://github.com/memononen/nanovg) is a small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations. - -## fontstash (Port) - -[Font stash](https://github.com/memononen/fontstash) is a light-weight online font texture atlas builder. It uses stb_truetype to render fonts on demand to a texture atlas. diff --git a/vendor/box2d/box2d.odin b/vendor/box2d/box2d.odin index 640f430b8..2cdfea191 100644 --- a/vendor/box2d/box2d.odin +++ b/vendor/box2d/box2d.odin @@ -1,8 +1,11 @@ +// Bindings for [[ Box2D ; https://box2d.org ]]. package vendor_box2d import "base:intrinsics" import "core:c" +_ :: intrinsics + when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { @(private) VECTOR_EXT :: "_simd" when #config(VENDOR_BOX2D_ENABLE_SIMD128, intrinsics.has_target_feature("simd128")) else "" } else { @@ -330,7 +333,7 @@ MakeOffsetProxy :: proc "c" (points: []Vec2, radius: f32, position: Vec2, rotati @(link_prefix="b2", default_calling_convention="c", require_results) foreign lib { // Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. - // You may optionally supply an array to hold debug data. + // Initially touching shapes are treated as a miss. ShapeCast :: proc(#by_ptr input: ShapeCastPairInput) -> CastOutput --- // Evaluate the transform sweep at a specific time. @@ -480,12 +483,12 @@ foreign lib { */ @(require_results) -SolvePlanes :: proc(position: Vec2, planes: []CollisionPlane) -> PlaneSolverResult { +SolvePlanes :: proc(targetDelta: Vec2, planes: []CollisionPlane) -> PlaneSolverResult { foreign lib { - b2SolvePlanes :: proc "c" (position: Vec2, planes: [^]CollisionPlane, count: i32) -> PlaneSolverResult --- + b2SolvePlanes :: proc "c" (targetDelta: Vec2, planes: [^]CollisionPlane, count: i32) -> PlaneSolverResult --- } - return b2SolvePlanes(position, raw_data(planes), i32(len(planes))) + return b2SolvePlanes(targetDelta, raw_data(planes), i32(len(planes))) } @(require_results) @@ -549,7 +552,6 @@ foreign lib { // Cast a ray into the world to collect shapes in the path of the ray. // Your callback function controls whether you get the closest point, any point, or n-points. - // The ray-cast ignores shapes that contain the starting point. // @note The callback function may receive shapes in any order // @param worldId The world to cast the ray against // @param origin The start point of the ray @@ -560,7 +562,7 @@ foreign lib { // @return traversal performance counters World_CastRay :: proc(worldId: WorldId, origin: Vec2, translation: Vec2, filter: QueryFilter, fcn: CastResultFcn, ctx: rawptr) -> TreeStats --- - // Cast a ray into the world to collect the closest hit. This is a convenience function. + // Cast a ray into the world to collect the closest hit. This is a convenience function. Ignores initial overlap. // This is less general than b2World_CastRay() and does not allow for custom filtering. World_CastRayClosest :: proc(worldId: WorldId, origin: Vec2, translation: Vec2, filter: QueryFilter) -> RayResult --- @@ -636,13 +638,6 @@ foreign lib { // @note Advanced feature World_SetContactTuning :: proc(worldId: WorldId, hertz: f32, dampingRatio: f32, pushSpeed: f32) --- - // Adjust joint tuning parameters - // @param worldId The world id - // @param hertz The contact stiffness (cycles per second) - // @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) - // @note Advanced feature - World_SetJointTuning :: proc(worldId: WorldId, hertz: f32, dampingRatio: f32) --- - // Set the maximum linear speed. Usually in m/s. World_SetMaximumLinearSpeed :: proc(worldId: WorldId, maximumLinearSpeed: f32) --- @@ -770,6 +765,7 @@ foreign lib { // Set the velocity to reach the given transform after a given time step. // The result will be close but maybe not exact. This is meant for kinematic bodies. + // The target is not applied if the velocity would be below the sleep threshold. // This will automatically wake the body if asleep. Body_SetTargetTransform :: proc(bodyId: BodyId, target: Transform, timeStep: f32) --- @@ -777,7 +773,7 @@ foreign lib { Body_GetLocalPointVelocity :: proc(bodyId: BodyId, localPoint: Vec2) -> Vec2 --- // Get the linear velocity of a world point attached to a body. Usually in meters per second. - GetWorldPointVelocity :: proc(bodyId: BodyId, worldPoint: Vec2) -> Vec2 --- + Body_GetWorldPointVelocity :: proc(bodyId: BodyId, worldPoint: Vec2) -> Vec2 --- // Apply a force at a world point. If the force is not applied at the center of mass, // it will generate a torque and affect the angular velocity. This optionally wakes up the body. @@ -1067,6 +1063,12 @@ foreign lib { // Get the shape material identifier Shape_GetMaterial :: proc(shapeId: ShapeId) -> c.int --- + // Set the shape surface material + Shape_SetSurfaceMaterial :: proc(shapeId: ShapeId, surfaceMaterial: SurfaceMaterial) --- + + // Get the shape surface material + Shape_GetSurfaceMaterial :: proc(shapeId: ShapeId) -> SurfaceMaterial --- + // Get the shape filter Shape_GetFilter :: proc(shapeId: ShapeId) -> Filter --- @@ -1257,12 +1259,30 @@ foreign lib { // Get the world that owns this joint Joint_GetWorld :: proc(jointId: JointId) -> WorldId --- + // Set the local anchor on bodyA + Joint_SetLocalAnchorA :: proc(jointId: JointId, localAnchor: Vec2) --- + // Get the local anchor on bodyA Joint_GetLocalAnchorA :: proc(jointId: JointId) -> Vec2 --- + // Set the local anchor on bodyB + Joint_SetLocalAnchorB :: proc(jointId: JointId, localAnchor: Vec2) --- + // Get the local anchor on bodyB Joint_GetLocalAnchorB :: proc(jointId: JointId) -> Vec2 --- + // Get the joint reference angle in radians (revolute, prismatic, and weld) + Joint_GetReferenceAngle :: proc(jointId: JointId) -> f32 --- + + // Set the joint reference angle in radians, must be in [-pi,pi]. (revolute, prismatic, and weld) + Joint_SetReferenceAngle :: proc(jointId: JointId, angleInRadians: f32) --- + + // Set the local axis on bodyA (prismatic and wheel) + Joint_SetLocalAxisA :: proc(jointId: JointId, localAxis: Vec2) --- + + // Get the local axis on bodyA (prismatic and wheel) + Joint_GetLocalAxisA :: proc(jointId: JointId) -> Vec2 --- + // Toggle collision between connected bodies Joint_SetCollideConnected :: proc(jointId: JointId, shouldCollide: bool) --- @@ -1284,6 +1304,21 @@ foreign lib { // Get the current constraint torque for this joint. Usually in Newton * meters. Joint_GetConstraintTorque :: proc(jointId: JointId) -> f32 --- + // Get the current linear separation error for this joint. Does not consider admissible movement. Usually in meters. + Joint_GetLinearSeparation :: proc(jointId: JointId) -> f32 --- + + // Get the current angular separation error for this joint. Does not consider admissible movement. Usually in meters. + Joint_GetAngularSeparation :: proc(jointId: JointId) -> f32 --- + + // Get the joint constraint tuning. Advanced feature. + Joint_GetConstraintTuning :: proc(jointId: JointId, hertz: ^f32, dampingRatio: ^f32) --- + + // Set the joint constraint tuning. Advanced feature. + // @param jointId the joint + // @param hertz the stiffness in Hertz (cycles per second) + // @param dampingRatio the non-dimensional damping ratio (one for critical damping) + Joint_SetConstraintTuning :: proc(jointId: JointId, hertz: f32, dampingRatio: f32) --- + /** * @defgroup distance_joint Distance Joint * @brief Functions for the distance joint. @@ -1370,7 +1405,7 @@ foreign lib { // Create a motor joint // @see b2MotorJointDef for details - CreateMotorJoint :: proc(worldId: WorldId, def: MotorJointDef) -> JointId --- + CreateMotorJoint :: proc(worldId: WorldId, #by_ptr def: MotorJointDef) -> JointId --- // Set the motor joint linear offset target MotorJoint_SetLinearOffset :: proc(jointId: JointId, linearOffset: Vec2) --- @@ -1378,7 +1413,8 @@ foreign lib { // Get the motor joint linear offset target MotorJoint_GetLinearOffset :: proc(jointId: JointId) -> Vec2 --- - // Set the motor joint angular offset target in radians + // Set the motor joint angular offset target in radians. This angle will be unwound + // so the motor will drive along the shortest arc. MotorJoint_SetAngularOffset :: proc(jointId: JointId, angularOffset: f32) --- // Get the motor joint angular offset target in radians @@ -1414,31 +1450,37 @@ foreign lib { // Create a mouse joint // @see b2MouseJointDef for details - CreateMouseJoint :: proc(worldId: WorldId, #by_ptr def: MouseJointDef) -> JointId --- + CreateMouseJoint :: proc(worldId: WorldId, #by_ptr def: MouseJointDef) -> JointId --- // Set the mouse joint target - MouseJoint_SetTarget :: proc(jointId: JointId, target: Vec2) --- + MouseJoint_SetTarget :: proc(jointId: JointId, target: Vec2) --- // Get the mouse joint target - MouseJoint_GetTarget :: proc(jointId: JointId) -> Vec2 --- + MouseJoint_GetTarget :: proc(jointId: JointId) -> Vec2 --- // Set the mouse joint spring stiffness in Hertz - MouseJoint_SetSpringHertz :: proc(jointId: JointId, hertz: f32) --- + MouseJoint_SetSpringHertz :: proc(jointId: JointId, hertz: f32) --- // Get the mouse joint spring stiffness in Hertz - MouseJoint_GetSpringHertz :: proc(jointId: JointId) -> f32 --- + MouseJoint_GetSpringHertz :: proc(jointId: JointId) -> f32 --- // Set the mouse joint spring damping ratio, non-dimensional - MouseJoint_SetSpringDampingRatio :: proc(jointId: JointId, dampingRatio: f32) --- + MouseJoint_SetSpringDampingRatio :: proc(jointId: JointId, dampingRatio: f32) --- // Get the mouse joint damping ratio, non-dimensional - MouseJoint_GetSpringDampingRatio :: proc(jointId: JointId) -> f32 --- + MouseJoint_GetSpringDampingRatio :: proc(jointId: JointId) -> f32 --- + + // Set the prismatic joint sprint target angle, usually in meters + PrismaticJoint_SetTargetTranslation :: proc(jointId: JointId, translation: f32) --- + + // Get the prismatic joint sprint target translation, usually in meters + PrismaticJoint_GetTargetTranslation :: proc(jointId: JointId) -> f32 --- // Set the mouse joint maximum force, usually in newtons - MouseJoint_SetMaxForce :: proc(jointId: JointId, maxForce: f32) --- + MouseJoint_SetMaxForce :: proc(jointId: JointId, maxForce: f32) --- // Get the mouse joint maximum force, usually in newtons - MouseJoint_GetMaxForce :: proc(jointId: JointId) -> f32 --- + MouseJoint_GetMaxForce :: proc(jointId: JointId) -> f32 --- /**@}*/ @@ -1561,6 +1603,12 @@ foreign lib { // Get the revolute joint spring damping ratio, non-dimensional RevoluteJoint_GetSpringDampingRatio :: proc(jointId: JointId) -> f32 --- + // Set the revolute joint spring target angle, radians + RevoluteJoint_SetTargetAngle :: proc(jointId: JointId, angle: f32) --- + + // Get the revolute joint spring target angle, radians + RevoluteJoint_GetTargetAngle :: proc(jointId: JointId) -> f32 --- + // Get the revolute joint current angle in radians relative to the reference angle // @see b2RevoluteJointDef::referenceAngle RevoluteJoint_GetAngle :: proc(jointId: JointId) -> f32 --- @@ -1578,7 +1626,7 @@ foreign lib { RevoluteJoint_GetUpperLimit :: proc(jointId: JointId) -> f32 --- // Set the revolute joint limits in radians. It is expected that lower <= upper - // and that -0.95 * B2_PI <= lower && upper <= -0.95 * B2_PI. + // and that -0.99 * B2_PI <= lower && upper <= -0.99 * B2_PI. RevoluteJoint_SetLimits :: proc(jointId: JointId, lower, upper: f32) --- // Enable/disable a revolute joint motor @@ -1618,12 +1666,6 @@ foreign lib { // @see b2WeldJointDef for details CreateWeldJoint :: proc(worldId: WorldId, #by_ptr def: WeldJointDef) -> JointId --- - // Get the weld joint reference angle in radians - WeldJoint_GetReferenceAngle :: proc(jointId: JointId) -> f32 --- - - // Set the weld joint reference angle in radians, must be in [-pi,pi]. - WeldJoint_SetReferenceAngle :: proc(jointId: JointId, angleInRadians: f32) --- - // Set the weld joint linear stiffness in Hertz. 0 is rigid. WeldJoint_SetLinearHertz :: proc(jointId: JointId, hertz: f32) --- diff --git a/vendor/box2d/box2d_wasm.odin b/vendor/box2d/box2d_wasm.odin index 0fcaf753f..1bbe9b8bc 100644 --- a/vendor/box2d/box2d_wasm.odin +++ b/vendor/box2d/box2d_wasm.odin @@ -1,4 +1,4 @@ #+build wasm32, wasm64p32 package vendor_box2d -@(require) import _ "vendor:libc" +@(require) import _ "vendor:libc-shim" diff --git a/vendor/box2d/build_box2d.sh b/vendor/box2d/build_box2d.sh index d6fb3888d..9c79ce009 100755 --- a/vendor/box2d/build_box2d.sh +++ b/vendor/box2d/build_box2d.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eu -VERSION="3.1.0" +VERSION="3.1.1" RELEASE="https://github.com/erincatto/box2d/archive/refs/tags/v$VERSION.tar.gz" cd "$(dirname "$0")" diff --git a/vendor/box2d/collision.odin b/vendor/box2d/collision.odin index b29e2f946..9930e0549 100644 --- a/vendor/box2d/collision.odin +++ b/vendor/box2d/collision.odin @@ -49,7 +49,7 @@ ShapeCastInput :: struct { canEncroach: bool, } -// Low level ray cast or shape-cast output data +// Low level ray cast or shape-cast output data. Returns a zero fraction and normal in the case of initial overlap. CastOutput :: struct { // The surface normal at the hit point normal: Vec2, @@ -227,7 +227,7 @@ DistanceInput :: struct { DistanceOutput :: struct { pointA: Vec2, // Closest point on shapeA pointB: Vec2, // Closest point on shapeB - normal: Vec2, // Normal vector that points from A to B + normal: Vec2, // Normal vector that points from A to B. Invalid if distance is zero. distance: f32, // The final distance, zero if overlapped iterations: i32, // Number of GJK iterations used simplexCount: i32, // The number of simplexes stored in the simplex array @@ -459,6 +459,9 @@ PlaneResult :: struct { // The collision plane between the mover and convex shape plane: Plane, + // The collision point on the shape. + point: Vec2, + // Did the collision register a hit? If not this plane should be ignored. hit: bool, } @@ -482,8 +485,8 @@ CollisionPlane :: struct { // Result returned by b2SolvePlanes PlaneSolverResult :: struct { - // The final position of the mover - position: Vec2, + // The translation of the mover + translation: Vec2, // The number of iterations used by the plane solver. For diagnostics. iterationCount: i32, diff --git a/vendor/box2d/id.odin b/vendor/box2d/id.odin index cb530527a..d2465f7d7 100644 --- a/vendor/box2d/id.odin +++ b/vendor/box2d/id.odin @@ -86,3 +86,16 @@ ID_EQUALS :: #force_inline proc "c" (id1, id2: $T) -> bool intrinsics.type_has_field(T, "generation") { return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation } + +// Store a world id into a u32. +StoreWorldId :: #force_inline proc "c" (id: WorldId) -> u32 { + return (u32(id.index1) << 16) | u32(id.generation) +} + +// Load a u32 into a world id. +LoadWorldId :: #force_inline proc "c" (x: u32) -> WorldId { + return { + u16(x >> 16), + u16(x), + } +} diff --git a/vendor/box2d/lib/box2d_darwin_amd64_avx2.a b/vendor/box2d/lib/box2d_darwin_amd64_avx2.a index f98e919a4..43a231303 100644 Binary files a/vendor/box2d/lib/box2d_darwin_amd64_avx2.a and b/vendor/box2d/lib/box2d_darwin_amd64_avx2.a differ diff --git a/vendor/box2d/lib/box2d_darwin_amd64_sse2.a b/vendor/box2d/lib/box2d_darwin_amd64_sse2.a index 3df91e852..c9afbb673 100644 Binary files a/vendor/box2d/lib/box2d_darwin_amd64_sse2.a and b/vendor/box2d/lib/box2d_darwin_amd64_sse2.a differ diff --git a/vendor/box2d/lib/box2d_darwin_arm64.a b/vendor/box2d/lib/box2d_darwin_arm64.a index c5d04fc73..0552cf8e6 100644 Binary files a/vendor/box2d/lib/box2d_darwin_arm64.a and b/vendor/box2d/lib/box2d_darwin_arm64.a differ diff --git a/vendor/box2d/lib/box2d_wasm.o b/vendor/box2d/lib/box2d_wasm.o index fc3ed1cbd..493df4a1c 100755 Binary files a/vendor/box2d/lib/box2d_wasm.o and b/vendor/box2d/lib/box2d_wasm.o differ diff --git a/vendor/box2d/lib/box2d_wasm_simd.o b/vendor/box2d/lib/box2d_wasm_simd.o index 8b70dcedd..d7150082e 100755 Binary files a/vendor/box2d/lib/box2d_wasm_simd.o and b/vendor/box2d/lib/box2d_wasm_simd.o differ diff --git a/vendor/box2d/lib/box2d_windows_amd64_avx2.lib b/vendor/box2d/lib/box2d_windows_amd64_avx2.lib index 7b8626b80..05e5b90a3 100644 Binary files a/vendor/box2d/lib/box2d_windows_amd64_avx2.lib and b/vendor/box2d/lib/box2d_windows_amd64_avx2.lib differ diff --git a/vendor/box2d/lib/box2d_windows_amd64_sse2.lib b/vendor/box2d/lib/box2d_windows_amd64_sse2.lib index f1442615f..21c9a4e2b 100644 Binary files a/vendor/box2d/lib/box2d_windows_amd64_sse2.lib and b/vendor/box2d/lib/box2d_windows_amd64_sse2.lib differ diff --git a/vendor/box2d/math_functions.odin b/vendor/box2d/math_functions.odin index 4394feb39..31c6d4090 100644 --- a/vendor/box2d/math_functions.odin +++ b/vendor/box2d/math_functions.odin @@ -3,7 +3,7 @@ package vendor_box2d import "core:c" import "core:math" -EPSILON :: 1e-23 +EPSILON :: math.F32_EPSILON Vec2 :: [2]f32 @@ -247,7 +247,7 @@ Normalize :: proc "c" (v: Vec2) -> Vec2 { @(require_results) IsNormalized :: proc "c" (v: Vec2) -> bool { aa := Dot(v, v) - return abs(1. - aa) < 10. * EPSILON + return abs(1. - aa) < 100. * EPSILON } @(require_results) @@ -415,31 +415,10 @@ RelativeAngle :: proc "c" (b, a: Rot) -> f32 { return Atan2(s, c) } -// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi] +// Convert any angle into the range [-pi, pi] @(require_results) UnwindAngle :: proc "c" (radians: f32) -> f32 { - if radians < -PI { - return radians + 2.0 * PI - } else if radians > PI { - return radians - 2.0 * PI - } - return radians -} - -// Convert any into the range [-pi, pi] (slow) -@(require_results) -UnwindLargeAngle :: proc "c" (radians: f32) -> f32 { - radians := radians - - for radians > PI { - radians -= 2. * PI - } - - for radians < -PI { - radians += 2. * PI - } - - return radians + return math.remainder(radians, 2. * PI) } // Rotate a vector @@ -563,6 +542,17 @@ AABB_Union :: proc "c" (a, b: AABB) -> (c: AABB) { return } +// Do a and b overlap +@(require_results) +AABB_Overlaps :: proc "c" (a, b: AABB) -> bool { + return !( + b.lowerBound.x > a.upperBound.x || + b.lowerBound.y > a.upperBound.y || + a.lowerBound.x > b.upperBound.x || + a.lowerBound.y > b.upperBound.y \ + ) +} + // Compute the bounding box of an array of circles @(require_results) MakeAABB :: proc "c" (points: []Vec2, radius: f32) -> AABB { @@ -625,3 +615,15 @@ IsValidPlane :: proc "c" (plane: Plane) -> bool { IsNormalized(plane.normal) or_return return true } + +// One-dimensional mass-spring-damper simulation. Returns the new velocity given the position and time step. +// You can then compute the new position using: +// position += timeStep * newVelocity +// This drives towards a zero position. By using implicit integration we get a stable solution +// that doesn't require transcendental functions. +@(require_results) +b2SpringDamper :: proc "c" (hertz, dampingRatio, position, velocity, timeStep: f32) -> f32 { + omega := 2. * PI * hertz + omegaH := omega * timeStep + return (velocity - omega * omegaH * position) / (1. + 2. * dampingRatio * omegaH + omegaH * omegaH) +} diff --git a/vendor/box2d/types.odin b/vendor/box2d/types.odin index c4ef0cd0c..9e12aa1a1 100644 --- a/vendor/box2d/types.odin +++ b/vendor/box2d/types.odin @@ -41,15 +41,16 @@ FinishTaskCallback :: #type proc "c" (userTask: rawptr, userContext: rawptr) // from a worker thread. // @warning This function should not attempt to modify Box2D state or user application state. // @ingroup world -FrictionCallback :: #type proc "c" (frictionA: f32, userMaterialIdA: i32, frictionB: f32, userMaterialIdB: i32) +FrictionCallback :: #type proc "c" (frictionA: f32, userMaterialIdA: i32, frictionB: f32, userMaterialIdB: i32) -> f32 // Optional restitution mixing callback. This intentionally provides no context objects because this is called // from a worker thread. // @warning This function should not attempt to modify Box2D state or user application state. // @ingroup world -RestitutionCallback :: #type proc "c" (restitutionA: f32, userMaterialIdA: i32, restitutuionB: f32, userMaterialIdB: i32) +RestitutionCallback :: #type proc "c" (restitutionA: f32, userMaterialIdA: i32, restitutionB: f32, userMaterialIdB: i32) -> f32 // Result from b2World_RayCastClosest +// If there is initial overlap the fraction and normal will be zero while the point is an arbitrary point in the overlap region. // @ingroup world RayResult :: struct { shapeId: ShapeId, @@ -87,12 +88,6 @@ WorldDef :: struct { // decreasing the damping ratio. maxContactPushSpeed: f32, - // Joint stiffness. Cycles per second. - jointHertz: f32, - - // Joint bounciness. Non-dimensional. - jointDampingRatio: f32, - // Maximum linear speed. Usually meters per second. maximumLinearSpeed: f32, @@ -660,6 +655,10 @@ PrismaticJointDef :: struct { // The constrained angle between the bodies: bodyB_angle - bodyA_angle referenceAngle: f32, + // The target translation for the joint in meters. The spring-damper will drive + // to this translation. + targetTranslation: f32, + // Enable a linear spring along the prismatic joint axis enableSpring: bool, @@ -727,6 +726,10 @@ RevoluteJointDef :: struct { // This defines the zero angle for the joint limit. referenceAngle: f32, + // The target angle for the joint in radians. The spring-damper will drive + // to this angle. + targetAngle: f32, + // Enable a rotational spring on the revolute hinge axis enableSpring: bool, @@ -739,10 +742,10 @@ RevoluteJointDef :: struct { // A flag to enable joint limits enableLimit: bool, - // The lower angle for the joint limit in radians. Minimum of -0.95*pi radians. + // The lower angle for the joint limit in radians. Minimum of -0.99*pi radians. lowerAngle: f32, - // The upper angle for the joint limit in radians. Maximum of 0.95*pi radians. + // The upper angle for the joint limit in radians. Maximum of 0.99*pi radians. upperAngle: f32, // A flag to enable the joint motor @@ -984,6 +987,7 @@ ContactEndTouchEvent :: struct { } // A hit touch event is generated when two shapes collide with a speed faster than the hit speed threshold. +// This may be reported for speculative contacts that have a confirmed impulse. ContactHitEvent :: struct { // Id of the first shape shapeIdA: ShapeId, @@ -991,7 +995,9 @@ ContactHitEvent :: struct { // Id of the second shape shapeIdB: ShapeId, - // Point where the shapes hit + // Point where the shapes hit at the beginning of the time step. + // This is a mid-point between the two surfaces. It could be at speculative + // point where the two shapes were not touching at the beginning of the time step. point: Vec2, // Normal vector pointing from shape A to shape B @@ -1099,17 +1105,18 @@ PreSolveFcn :: #type proc "c" (shapeIdA, shapeIdB: ShapeId, manifold: ^Manifold, // @ingroup world OverlapResultFcn :: #type proc "c" (shapeId: ShapeId, ctx: rawptr) -> bool -// Prototype callback for ray casts. +// Prototype callback for ray and shape casts. // Called for each shape found in the query. You control how the ray cast // proceeds by returning a f32: // return -1: ignore this shape and continue // return 0: terminate the ray cast // return fraction: clip the ray to this point // return 1: don't clip the ray and continue +// A cast with initial overlap will return a zero fraction and a zero normal. // @param shapeId the shape hit by the ray // @param point the point of initial intersection -// @param normal the normal vector at the point of intersection -// @param fraction the fraction along the ray at the point of intersection +// @param normal the normal vector at the point of intersection, zero for a shape cast with initial overlap +// @param fraction the fraction along the ray at the point of intersection, zero for a shape cast with initial overlap // @param context the user context // @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue // @see b2World_CastRay diff --git a/vendor/box2d/wasm.Makefile b/vendor/box2d/wasm.Makefile index 74f4e4eff..5cce30ad1 100644 --- a/vendor/box2d/wasm.Makefile +++ b/vendor/box2d/wasm.Makefile @@ -7,11 +7,11 @@ # CC = $(shell brew --prefix llvm)/bin/clang # LD = $(shell brew --prefix llvm)/bin/wasm-ld -VERSION = 3.1.0 +VERSION = 3.1.1 SRCS = $(wildcard box2d-$(VERSION)/src/*.c) OBJS_SIMD = $(SRCS:.c=_simd.o) OBJS = $(SRCS:.c=.o) -SYSROOT = $(shell odin root)/vendor/libc +SYSROOT = $(shell odin root)/vendor/libc-shim CFLAGS = -Ibox2d-$(VERSION)/include --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT) all: lib/box2d_wasm.o lib/box2d_wasm_simd.o diff --git a/vendor/cgltf/cgltf.odin b/vendor/cgltf/cgltf.odin index e9dc7ef84..c30d2c4b6 100644 --- a/vendor/cgltf/cgltf.odin +++ b/vendor/cgltf/cgltf.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Cgtlf ; https://github.com/jkuhlmann/cgltf ]]. package cgltf @(private) @@ -12,7 +13,7 @@ LIB :: ( when LIB != "" { when !#exists(LIB) { // Windows library is shipped with the compiler, so a Windows specific message should not be needed. - #panic("Could not find the compiled cgltf library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/cgltf/src\"`") + // #panic("Could not find the compiled cgltf library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/cgltf/src\"`") } } @@ -262,12 +263,28 @@ image :: struct { extensions: [^]extension `fmt:"v,extensions_count"`, } +filter_type :: enum c.int { + undefined = 0, + nearest = 9728, + linear = 9729, + nearest_mipmap_nearest = 9984, + linear_mipmap_nearest = 9985, + nearest_mipmap_linear = 9986, + linear_mipmap_linear = 9987, +} + +wrap_mode :: enum c.int { + clamp_to_edge = 33071, + mirrored_repeat = 33648, + repeat = 10497, +} + sampler :: struct { name: cstring, - mag_filter: c.int, - min_filter: c.int, - wrap_s: c.int, - wrap_t: c.int, + mag_filter: filter_type, + min_filter: filter_type, + wrap_s: wrap_mode, + wrap_t: wrap_mode, extras: extras_t, extensions_count: uint, extensions: [^]extension `fmt:"v,extensions_count"`, @@ -494,8 +511,8 @@ camera :: struct { name: cstring, type: camera_type, data: struct #raw_union { - perspective: camera_perspective, - orthographic: camera_orthographic, + perspective: camera_perspective `raw_union_tag:"type=.perspective"`, + orthographic: camera_orthographic `raw_union_tag:"type=.orthographic"`, }, extras: extras_t, extensions_count: uint, diff --git a/vendor/cgltf/cgltf_wasm.odin b/vendor/cgltf/cgltf_wasm.odin index fb612b2ac..1404fc592 100644 --- a/vendor/cgltf/cgltf_wasm.odin +++ b/vendor/cgltf/cgltf_wasm.odin @@ -1,4 +1,4 @@ #+build wasm32, wasm64p32 package cgltf -@(require) import _ "vendor:libc" +@(require) import _ "vendor:libc-shim" diff --git a/vendor/cgltf/src/Makefile b/vendor/cgltf/src/Makefile index 0dd450ce0..f4dc8c12c 100644 --- a/vendor/cgltf/src/Makefile +++ b/vendor/cgltf/src/Makefile @@ -8,7 +8,7 @@ endif wasm: mkdir -p ../lib - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc cgltf.c -o ../lib/cgltf_wasm.o + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim cgltf.c -o ../lib/cgltf_wasm.o unix: mkdir -p ../lib diff --git a/vendor/commonmark/cmark.odin b/vendor/commonmark/cmark.odin index 6b07f157f..574b977e0 100644 --- a/vendor/commonmark/cmark.odin +++ b/vendor/commonmark/cmark.odin @@ -1,9 +1,3 @@ -/* - Bindings against CMark (https://github.com/commonmark/cmark) - - Original authors: John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. - See LICENSE for license details. -*/ package vendor_commonmark import "core:c" @@ -160,12 +154,12 @@ Node :: struct { flags: Node_Flags, as: struct #raw_union { - list: List, - code: Code, - heading: Heading, - link: Link, - custom: Custom, - html_block_type: c.int, + list: List `raw_union_tag:"type=.List"`, + code: Code `raw_union_tag:"type=.Code"`, + heading: Heading `raw_union_tag:"type=.Heading"`, + link: Link `raw_union_tag:"type=.Link"`, + custom: Custom `raw_union_tag:"type=.Custom"`, + html_block_type: c.int `raw_union_tag:"type=.HTML_Block"`, }, } diff --git a/vendor/commonmark/doc.odin b/vendor/commonmark/doc.odin index ef788fb8f..648226234 100644 --- a/vendor/commonmark/doc.odin +++ b/vendor/commonmark/doc.odin @@ -1,18 +1,13 @@ -#+build ignore /* - Bindings against CMark (https://github.com/commonmark/cmark) +Bindings for [[ CMark; https://github.com/commonmark/cmark ]]. - Original authors: John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. - See LICENSE for license details. -*/ -package vendor_commonmark +Original authors: John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. +See LICENSE for license details. -/* - Parsing - Simple interface: - - ```odin +Example: import cm "vendor:commonmark" + // Parsing - Simple interface hellope_world :: proc() { fmt.printf("CMark version: %v\n", cm.version_string()) @@ -25,13 +20,8 @@ package vendor_commonmark fmt.println(html) } - ``` - - Parsing - Streaming interface: - - ```odin - import cm "vendor:commonmark" + // Parsing - Streaming interface streaming :: proc() { using cm @@ -67,26 +57,23 @@ package vendor_commonmark fmt.println(html) } - ``` +An iterator will walk through a tree of nodes, starting from a root +node, returning one node at a time, together with information about +whether the node is being entered or exited. - An iterator will walk through a tree of nodes, starting from a root - node, returning one node at a time, together with information about - whether the node is being entered or exited. +The iterator will first descend to a child node, if there is one. +When there is no child, the iterator will go to the next sibling. +When there is no next sibling, the iterator will return to the parent +(but with an `Event_Type.Exit`). - The iterator will first descend to a child node, if there is one. - When there is no child, the iterator will go to the next sibling. - When there is no next sibling, the iterator will return to the parent - (but with an `Event_Type.Exit`). +The iterator will return `.Done` when it reaches the root node again. - The iterator will return `.Done` when it reaches the root node again. +One natural application is an HTML renderer, where an `.Enter` event +outputs an open tag and an `.Exit` event outputs a close tag. - One natural application is an HTML renderer, where an `.Enter` event - outputs an open tag and an `.Exit` event outputs a close tag. +An iterator might also be used to transform an AST in some systematic +way, for example, turning all level-3 headings into regular paragraphs. - An iterator might also be used to transform an AST in some systematic - way, for example, turning all level-3 headings into regular paragraphs. - - ```odin usage_example(root: ^Node) { ev_type: Event_Type iter := iter_new(root) @@ -98,20 +85,20 @@ package vendor_commonmark // Do something with `cur` and `ev_type` } } - ``` - Iterators will never return `.Exit` events for leaf nodes, - which are nodes of type: +Iterators will never return `.Exit` events for leaf nodes, +which are nodes of type: - * HTML_Block - * Thematic_Break - * Code_Block - * Text - * Soft_Break - * Line_Break - * Code - * HTML_Inline +* HTML_Block +* Thematic_Break +* Code_Block +* Text +* Soft_Break +* Line_Break +* Code +* HTML_Inline - Nodes must only be modified after an `.Exit` event, or an `.Enter` event for - leaf nodes. -*/ \ No newline at end of file +Nodes must only be modified after an `.Exit` event, or an `.Enter` event for +leaf nodes. +*/ +package vendor_commonmark \ No newline at end of file diff --git a/vendor/compress/lz4/lz4.odin b/vendor/compress/lz4/lz4.odin index 310248d56..f3b0fcb0d 100644 --- a/vendor/compress/lz4/lz4.odin +++ b/vendor/compress/lz4/lz4.odin @@ -1,8 +1,11 @@ +// Bindings for [[LZ4 ; https://github.com/lz4/lz4]]. package vendor_compress_lz4 when ODIN_OS == .Windows { @(extra_linker_flags="/NODEFAULTLIB:libcmt") - foreign import lib "lib/liblz4_static.lib" + foreign import lib { "lib/liblz4_static.lib", "system:ucrt.lib" } +} else { + foreign import lib "system:lz4" } import "core:c" diff --git a/vendor/curl/LICENSE b/vendor/curl/LICENSE new file mode 100644 index 000000000..acd4a6b34 --- /dev/null +++ b/vendor/curl/LICENSE @@ -0,0 +1,11 @@ +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1996 - 2025, Daniel Stenberg, daniel@haxx.se, and many contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. \ No newline at end of file diff --git a/vendor/curl/c/curl.h b/vendor/curl/c/curl.h new file mode 100644 index 000000000..9e07527dc --- /dev/null +++ b/vendor/curl/c/curl.h @@ -0,0 +1,3346 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.se/libcurl/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER /* not used since 8.11.0 */ +#endif + +/* Compile-time deprecation macros. */ +#if (defined(__GNUC__) && \ + ((__GNUC__ > 12) || ((__GNUC__ == 12) && (__GNUC_MINOR__ >= 1))) || \ + (defined(__clang__) && __clang_major__ >= 3) || \ + defined(__IAR_SYSTEMS_ICC__)) && \ + !defined(__INTEL_COMPILER) && \ + !defined(CURL_DISABLE_DEPRECATION) && !defined(BUILDING_LIBCURL) +#define CURL_DEPRECATED(version, message) \ + __attribute__((deprecated("since " # version ". " message))) +#ifdef __IAR_SYSTEMS_ICC__ +#define CURL_IGNORE_DEPRECATION(statements) \ + _Pragma("diag_suppress=Pe1444") \ + statements \ + _Pragma("diag_default=Pe1444") +#else +#define CURL_IGNORE_DEPRECATION(statements) \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ + statements \ + _Pragma("GCC diagnostic pop") +#endif +#else +#define CURL_DEPRECATED(version, message) +#define CURL_IGNORE_DEPRECATION(statements) statements +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things runtime */ + +#include +#include + +#if defined(__FreeBSD__) || defined(__MidnightBSD__) +/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2.h inclusion if winsock.h already was + included, since they cannot co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \ + (defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \ + defined(__sun__) || defined(__serenity__) || defined(__vxworks__) +#include +#endif + +#ifndef _WIN32 +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURL; +typedef void CURLSH; + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef __has_declspec_attribute +#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x) +#else +#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) 0 +#endif + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(_WIN32) || \ + (CURL_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ + CURL_HAS_DECLSPEC_ATTRIBUTE(dllimport)) +# ifdef BUILDING_LIBCURL +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS CURL_DEPRECATED(8.3.0, "") = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT CURL_DEPRECATED(8.3.0, "") = 5, + CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT CURL_DEPRECATED(8.15.0, "") = 9, + CURLSSLBACKEND_AXTLS CURL_DEPRECATED(7.61.0, "") = 10, + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK CURL_DEPRECATED(7.82.0, "") = 12, + CURLSSLBACKEND_BEARSSL CURL_DEPRECATED(8.15.0, "") = 13, + CURLSSLBACKEND_RUSTLS = 14 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_AWSLC CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +/* bits for the CURLOPT_FOLLOWLOCATION option */ +#define CURLFOLLOW_ALL 1L /* generic follow redirects */ + +/* Do not use the custom method in the follow-up request if the HTTP code + instructs so (301, 302, 303). */ +#define CURLFOLLOW_OBEYCODE 2L + +/* Only use the custom method in the first request, always reset in the next */ +#define CURLFOLLOW_FIRSTONLY 3L + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a filename */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a filename */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The filename to show. If not set, the + actual filename will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE (10*1024*1024) +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a bad buffer size for uploads on Windows, + while 16K for some odd reason performed a lot better. We do the ifndef + check to allow this value to easier be changed at build time for those + who feel adventurous. The practical minimum is about 400 bytes since + libcurl uses a buffer of this size as a scratch area (unrelated to + network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +/* This is a magic return code for the write callback that, when returned, + will signal an error from the callback. */ +#define CURL_WRITEFUNC_ERROR 0xFFFFFFFF + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* These are libcurl private struct fields. Previously used by libcurl, so + they must never be interfered with. */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we do not need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern does not match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking cannot be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors */ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback */ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* This is the CURLOPT_PREREQFUNCTION callback prototype. */ +typedef int (*curl_prereq_callback)(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port); + +/* Return code for when the pre-request callback has terminated without + any errors */ +#define CURL_PREREQFUNC_OK 0 +/* Return code for when the pre-request callback wants to abort the + request */ +#define CURL_PREREQFUNC_ABORT 1 + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - could not open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" did not work */ + CURLE_OBSOLETE34, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - could not resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_OBSOLETE41, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - could not use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + was not verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_OBSOLETE62, /* 62 - NOT IN USE since 7.82.0 */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_OBSOLETE75, /* 75 - NOT IN USE since 7.82.0 */ + CURLE_OBSOLETE76, /* 76 - NOT IN USE since 7.82.0 */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it is ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURLE_PROXY, /* 97 - proxy handshake error */ + CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */ + CURLE_TOO_LARGE, /* 100 - a value/data met its maximum */ + CURLE_ECH_REQUIRED, /* 101 - ECH tried but failed */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* removed in 7.53.0 */ +#define CURLE_FUNCTION_NOT_FOUND CURLE_OBSOLETE41 + +/* removed in 7.56.0 */ +#define CURLE_HTTP_POST_ERROR CURLE_OBSOLETE34 + +/* Previously obsolete error code reused in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes reused in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* Added for 7.78.0 */ +#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME +#define CURLE_LDAP_INVALID_URL CURLE_OBSOLETE62 +#define CURLE_CONV_REQD CURLE_OBSOLETE76 +#define CURLE_CONV_FAILED CURLE_OBSOLETE75 + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 +#define CURLOPT_OBSOLETE72 9999 +#define CURLOPT_OBSOLETE40 9999 + +#endif /* !CURL_NO_OLDIES */ + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +typedef enum { + CURLPX_OK, + CURLPX_BAD_ADDRESS_TYPE, + CURLPX_BAD_VERSION, + CURLPX_CLOSED, + CURLPX_GSSAPI, + CURLPX_GSSAPI_PERMSG, + CURLPX_GSSAPI_PROTECTION, + CURLPX_IDENTD, + CURLPX_IDENTD_DIFFER, + CURLPX_LONG_HOSTNAME, + CURLPX_LONG_PASSWD, + CURLPX_LONG_USER, + CURLPX_NO_AUTH, + CURLPX_RECV_ADDRESS, + CURLPX_RECV_AUTH, + CURLPX_RECV_CONNECT, + CURLPX_RECV_REQACK, + CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + CURLPX_REPLY_COMMAND_NOT_SUPPORTED, + CURLPX_REPLY_CONNECTION_REFUSED, + CURLPX_REPLY_GENERAL_SERVER_FAILURE, + CURLPX_REPLY_HOST_UNREACHABLE, + CURLPX_REPLY_NETWORK_UNREACHABLE, + CURLPX_REPLY_NOT_ALLOWED, + CURLPX_REPLY_TTL_EXPIRED, + CURLPX_REPLY_UNASSIGNED, + CURLPX_REQUEST_FAILED, + CURLPX_RESOLVE_HOST, + CURLPX_SEND_AUTH, + CURLPX_SEND_CONNECT, + CURLPX_SEND_REQUEST, + CURLPX_UNKNOWN_FAIL, + CURLPX_UNKNOWN_MODE, + CURLPX_USER_REJECTED, + CURLPX_LAST /* never use */ +} CURLproxycode; + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or wolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +#define CURLPROXY_HTTP 0L /* added in 7.10, new in 7.19.4 default is + to use CONNECT HTTP/1.1 */ +#define CURLPROXY_HTTP_1_0 1L /* force to use CONNECT HTTP/1.0 + added in 7.19.4 */ +#define CURLPROXY_HTTPS 2L /* HTTPS but stick to HTTP/1 + added in 7.52.0 */ +#define CURLPROXY_HTTPS2 3L /* HTTPS and attempt HTTP/2 + added in 8.2.0 */ +#define CURLPROXY_SOCKS4 4L /* support added in 7.15.2, enum existed + already in 7.10 */ +#define CURLPROXY_SOCKS5 5L /* added in 7.10 */ +#define CURLPROXY_SOCKS4A 6L /* added in 7.18.0 */ +#define CURLPROXY_SOCKS5_HOSTNAME 7L /* Use the SOCKS5 protocol but pass along + the hostname rather than the IP + address. added in 7.18.0 */ + +typedef enum { + CURLPROXY_LAST = 8 /* never use */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#ifndef CURL_NO_OLDIES + /* functionality removed since 8.8.0 */ +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#endif +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0L /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0L /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1L<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1L<<1) /* password */ +#define CURLSSH_AUTH_HOST (1L<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1L<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1L<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1L<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0L /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1L<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1L<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we cannot answer right now. + Causes a CURLE_PEER_FAILED_VERIFICATION error but the + connection will be left intact etc */ + CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed with */ + /* CURLOPT_SSH_KEYDATA */ + +typedef int + (*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed */ + /* with CURLOPT_SSH_HOSTKEYDATA */ + int keytype, /* CURLKHTYPE */ + const char *key, /* hostkey to check */ + size_t keylen); /* length of the key */ + /* return CURLE_OK to accept */ + /* or something else to refuse */ + + +/* parameter for the CURLOPT_USE_SSL option */ +#define CURLUSESSL_NONE 0L /* do not attempt to use SSL */ +#define CURLUSESSL_TRY 1L /* try using SSL, proceed anyway otherwise */ +#define CURLUSESSL_CONTROL 2L /* SSL for the control connection or fail */ +#define CURLUSESSL_ALL 3L /* SSL for all communication or fail */ + +typedef enum { + CURLUSESSL_LAST = 4 /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1L<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1L<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1L<<2) + +/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. */ +#define CURLSSLOPT_REVOKE_BEST_EFFORT (1L<<3) + +/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. */ +#define CURLSSLOPT_NATIVE_CA (1L<<4) + +/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) */ +#define CURLSSLOPT_AUTO_CLIENT_CERT (1L<<5) + +/* If possible, send data using TLS 1.3 early data */ +#define CURLSSLOPT_EARLYDATA (1L<<6) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /* !CURL_NO_OLDIES */ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +#define CURLFTPSSL_CCC_NONE 0L /* do not send CCC */ +#define CURLFTPSSL_CCC_PASSIVE 1L /* Let the server initiate the shutdown */ +#define CURLFTPSSL_CCC_ACTIVE 2L /* Initiate the shutdown */ + +typedef enum { + CURLFTPSSL_CCC_LAST = 3 /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +#define CURLFTPAUTH_DEFAULT 0L /* let libcurl decide */ +#define CURLFTPAUTH_SSL 1L /* use "AUTH SSL" */ +#define CURLFTPAUTH_TLS 2L /* use "AUTH TLS" */ + +typedef enum { + CURLFTPAUTH_LAST = 3 /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +#define CURLFTP_CREATE_DIR_NONE 0L /* do NOT create missing dirs! */ +#define CURLFTP_CREATE_DIR 1L /* (FTP/SFTP) if CWD fails, try MKD and + then CWD again if MKD succeeded, for + SFTP this does similar magic */ +#define CURLFTP_CREATE_DIR_RETRY 2L /* (FTP only) if CWD fails, try MKD and + then CWD again even if MKD failed! */ + +typedef enum { + CURLFTP_CREATE_DIR_LAST = 3 /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +#define CURLFTPMETHOD_DEFAULT 0L /* let libcurl pick */ +#define CURLFTPMETHOD_MULTICWD 1L /* single CWD operation for each path + part */ +#define CURLFTPMETHOD_NOCWD 2L /* no CWD at all */ +#define CURLFTPMETHOD_SINGLECWD 3L /* one CWD to full dir, then work on file */ + +typedef enum { + CURLFTPMETHOD_LAST = 4 /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0L +#define CURLHEADER_SEPARATE (1L<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_READONLYFILE (1L<<2) +#define CURLALTSVC_H1 (1L<<3) +#define CURLALTSVC_H2 (1L<<4) +#define CURLALTSVC_H3 (1L<<5) + +/* bitmask values for CURLOPT_UPLOAD_FLAGS */ +#define CURLULFLAG_ANSWERED (1L<<0) +#define CURLULFLAG_DELETED (1L<<1) +#define CURLULFLAG_DRAFT (1L<<2) +#define CURLULFLAG_FLAGGED (1L<<3) +#define CURLULFLAG_SEEN (1L<<4) + +struct curl_hstsentry { + char *name; + size_t namelen; + unsigned int includeSubDomains:1; + char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */ +}; + +struct curl_index { + size_t index; /* the provided entry's "index" or count */ + size_t total; /* total number of entries to save */ +}; + +typedef enum { + CURLSTS_OK, + CURLSTS_DONE, + CURLSTS_FAIL +} CURLSTScode; + +typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy, + struct curl_hstsentry *e, + void *userp); +typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, + struct curl_hstsentry *e, + struct curl_index *i, + void *userp); + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +#define CURLHSTS_ENABLE (1L<<0) +#define CURLHSTS_READONLYFILE (1L<<1) + +/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS + options. Do not use. */ +#define CURLPROTO_HTTP (1L<<0) +#define CURLPROTO_HTTPS (1L<<1) +#define CURLPROTO_FTP (1L<<2) +#define CURLPROTO_FTPS (1L<<3) +#define CURLPROTO_SCP (1L<<4) +#define CURLPROTO_SFTP (1L<<5) +#define CURLPROTO_TELNET (1L<<6) +#define CURLPROTO_LDAP (1L<<7) +#define CURLPROTO_LDAPS (1L<<8) +#define CURLPROTO_DICT (1L<<9) +#define CURLPROTO_FILE (1L<<10) +#define CURLPROTO_TFTP (1L<<11) +#define CURLPROTO_IMAP (1L<<12) +#define CURLPROTO_IMAPS (1L<<13) +#define CURLPROTO_POP3 (1L<<14) +#define CURLPROTO_POP3S (1L<<15) +#define CURLPROTO_SMTP (1L<<16) +#define CURLPROTO_SMTPS (1L<<17) +#define CURLPROTO_RTSP (1L<<18) +#define CURLPROTO_RTMP (1L<<19) +#define CURLPROTO_RTMPT (1L<<20) +#define CURLPROTO_RTMPE (1L<<21) +#define CURLPROTO_RTMPTE (1L<<22) +#define CURLPROTO_RTMPS (1L<<23) +#define CURLPROTO_RTMPTS (1L<<24) +#define CURLPROTO_GOPHER (1L<<25) +#define CURLPROTO_SMB (1L<<26) +#define CURLPROTO_SMBS (1L<<27) +#define CURLPROTO_MQTT (1L<<28) +#define CURLPROTO_GOPHERS (1L<<29) +#define CURLPROTO_ALL (~0L) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 +#define CURLOPTTYPE_BLOB 40000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu +#define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu + +/* CURLOPT aliases that make no runtime difference */ + +/* 'char *' argument to a string with a trailing zero */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If CURLOPT_READDATA is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPTDEPRECATED(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24, + 7.56.0, "Use CURLOPT_MIMEPOST"), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* 40 is not used */ + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPTDEPRECATED(CURLOPT_PUT, CURLOPTTYPE_LONG, 54, + 7.12.1, "Use CURLOPT_UPLOAD"), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPTDEPRECATED(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56, + 7.32.0, "Use CURLOPT_XFERINFOFUNCTION"), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57), +#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through an HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but does not match one of these, 'private' will be used. */ + CURLOPTDEPRECATED(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63, + 8.17.0, "removed"), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* 72 = OBSOLETE */ + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you are absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be reused + when done. Do not use this unless you are absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a filename that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPTDEPRECATED(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76, + 7.84.0, "Serves no purpose anymore"), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPTDEPRECATED(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77, + 7.84.0, "Serves no purpose anymore"), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which filename to write all known cookies in after completed + operation. Set filename to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPTDEPRECATED(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91, + 7.11.1, "Use CURLOPT_SHARE"), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + wolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111), + + /* Option that changes the timeout, in seconds, associated with getting a + response. This is different from transfer timeout time and essentially + places a demand on the server to acknowledge commands in a timely + manner. For FTP, SMTP, IMAP and POP3. */ + CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the filename of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129), + + CURLOPTDEPRECATED(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130, + 7.18.0, "Use CURLOPT_SEEKFUNCTION"), + CURLOPTDEPRECATED(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131, + 7.18.0, "Use CURLOPT_SEEKDATA"), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPTDEPRECATED(CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 142, + 7.82.0, "Serves no purpose anymore"), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPTDEPRECATED(CURLOPT_CONV_TO_NETWORK_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 143, + 7.82.0, "Serves no purpose anymore"), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPTDEPRECATED(CURLOPT_CONV_FROM_UTF8_FUNCTION, + CURLOPTTYPE_FUNCTIONPOINT, 144, + 7.82.0, "Serves no purpose anymore"), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149), + + /* set to 0 to disable session ID reuse for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPTDEPRECATED(CURLOPT_SOCKS5_GSSAPI_SERVICE, + CURLOPTTYPE_STRINGPOINT, 179, + 7.49.0, "Use CURLOPT_PROXY_SERVICE_NAME"), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPTDEPRECATED(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181, + 7.85.0, "Use CURLOPT_PROTOCOLS_STR"), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPTDEPRECATED(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182, + 7.85.0, "Use CURLOPT_REDIR_PROTOCOLS_STR"), + + /* set the SSH knownhost filename to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + is not any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210), + + /* Set the name servers to use for DNS resolution. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPTDEPRECATED(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225, + 7.86.0, "Has no function"), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to an HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), + + /* The public key used to validate the peer public key */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPTDEPRECATED(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233, + 8.15.0, "Has no function"), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/do not wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another curl handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another curl handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache filename to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age (idle time) of a connection to consider it for reuse + * (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorization identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOPTTYPE_LONG, 290), + + /* the private SSL-certificate as a "blob" */ + CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291), + CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292), + CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293), + CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294), + CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295), + + /* Issuer certificate for proxy */ + CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296), + CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297), + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://docs.openssl.org/master/man3/SSL_CTX_set1_curves/ + */ + CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298), + + /* HSTS bitmask */ + CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299), + /* HSTS filename */ + CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300), + + /* HSTS read callback */ + CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301), + CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302), + + /* HSTS write callback */ + CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303), + CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304), + + /* Parameters for V4 signature */ + CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305), + + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306), + + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307), + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ + CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308), + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPTTYPE_STRINGPOINT, 311), + + /* Function that will be called immediately before the initial request + is made on a connection (after any protocol negotiation step). */ + CURLOPT(CURLOPT_PREREQFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 312), + + /* Data passed to the CURLOPT_PREREQFUNCTION callback */ + CURLOPT(CURLOPT_PREREQDATA, CURLOPTTYPE_CBPOINT, 313), + + /* maximum age (since creation) of a connection to consider it for reuse + * (in seconds) */ + CURLOPT(CURLOPT_MAXLIFETIME_CONN, CURLOPTTYPE_LONG, 314), + + /* Set MIME option flags. */ + CURLOPT(CURLOPT_MIME_OPTIONS, CURLOPTTYPE_LONG, 315), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_HOSTKEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 316), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_HOSTKEYDATA, CURLOPTTYPE_CBPOINT, 317), + + /* specify which protocols that are allowed to be used for the transfer, + which thus helps the app which takes URLs from users or other external + inputs and want to restrict what protocol(s) to deal with. Defaults to + all built-in protocols. */ + CURLOPT(CURLOPT_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 318), + + /* specify which protocols that libcurl is allowed to follow directs to */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319), + + /* WebSockets options */ + CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320), + + /* CA cache timeout */ + CURLOPT(CURLOPT_CA_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 321), + + /* Can leak things, gonna exit() soon */ + CURLOPT(CURLOPT_QUICK_EXIT, CURLOPTTYPE_LONG, 322), + + /* set a specific client IP for HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323), + + /* millisecond version */ + CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), + + /* set ECH configuration */ + CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325), + + /* maximum number of keepalive probes (Linux, *BSD, macOS, etc.) */ + CURLOPT(CURLOPT_TCP_KEEPCNT, CURLOPTTYPE_LONG, 326), + + CURLOPT(CURLOPT_UPLOAD_FLAGS, CURLOPTTYPE_LONG, 327), + + /* set TLS supported signature algorithms */ + CURLOPT(CURLOPT_SSL_SIGNATURE_ALGORITHMS, CURLOPTTYPE_STRINGPOINT, 328), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +/* */ +#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT + +/* Added in 8.2.0 */ +#define CURLOPT_MAIL_RCPT_ALLLOWFAILS CURLOPT_MAIL_RCPT_ALLOWFAILS + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0L /* default, uses addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1L /* uses only IPv4 addresses/connections */ +#define CURL_IPRESOLVE_V6 2L /* uses only IPv6 addresses/connections */ + + /* Convenient "aliases" */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + +/* These constants are for use with the CURLOPT_HTTP_VERSION option. */ +#define CURL_HTTP_VERSION_NONE 0L /* setting this means we do not care, and + that we would like the library to choose + the best possible for us! */ +#define CURL_HTTP_VERSION_1_0 1L /* please use HTTP 1.0 in the request */ +#define CURL_HTTP_VERSION_1_1 2L /* please use HTTP 1.1 in the request */ +#define CURL_HTTP_VERSION_2_0 3L /* please use HTTP 2 in the request */ +#define CURL_HTTP_VERSION_2TLS 4L /* use version 2 for HTTPS, version 1.1 for + HTTP */ +#define CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE 5L /* please use HTTP 2 without + HTTP/1.1 Upgrade */ +#define CURL_HTTP_VERSION_3 30L /* Use HTTP/3, fallback to HTTP/2 or + HTTP/1 if needed. For HTTPS only. For + HTTP, this option makes libcurl + return error. */ +#define CURL_HTTP_VERSION_3ONLY 31L /* Use HTTP/3 without fallback. For + HTTPS only. For HTTP, this makes + libcurl return error. */ +#define CURL_HTTP_VERSION_LAST 32L /* *ILLEGAL* http version */ + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ + +#define CURL_RTSPREQ_NONE 0L +#define CURL_RTSPREQ_OPTIONS 1L +#define CURL_RTSPREQ_DESCRIBE 2L +#define CURL_RTSPREQ_ANNOUNCE 3L +#define CURL_RTSPREQ_SETUP 4L +#define CURL_RTSPREQ_PLAY 5L +#define CURL_RTSPREQ_PAUSE 6L +#define CURL_RTSPREQ_TEARDOWN 7L +#define CURL_RTSPREQ_GET_PARAMETER 8L +#define CURL_RTSPREQ_SET_PARAMETER 9L +#define CURL_RTSPREQ_RECORD 10L +#define CURL_RTSPREQ_RECEIVE 11L +#define CURL_RTSPREQ_LAST 12L /* not used */ + + /* These enums are for use with the CURLOPT_NETRC option. */ +#define CURL_NETRC_IGNORED 0L /* The .netrc will never be read. + This is the default. */ +#define CURL_NETRC_OPTIONAL 1L /* A user:password in the URL will be preferred + to one in the .netrc. */ +#define CURL_NETRC_REQUIRED 2L /* A user:password in the URL will be ignored. + Unless one is set programmatically, the + .netrc will be queried. */ +enum CURL_NETRC_OPTION { + /* we set a single member here, just to make sure we still provide the enum, + but the values to use are defined above with L suffixes */ + CURL_NETRC_LAST = 3 +}; + +#define CURL_SSLVERSION_DEFAULT 0L +#define CURL_SSLVERSION_TLSv1 1L /* TLS 1.x */ +#define CURL_SSLVERSION_SSLv2 2L +#define CURL_SSLVERSION_SSLv3 3L +#define CURL_SSLVERSION_TLSv1_0 4L +#define CURL_SSLVERSION_TLSv1_1 5L +#define CURL_SSLVERSION_TLSv1_2 6L +#define CURL_SSLVERSION_TLSv1_3 7L + +#define CURL_SSLVERSION_LAST 8L /* never use, keep last */ + +#define CURL_SSLVERSION_MAX_NONE 0L +#define CURL_SSLVERSION_MAX_DEFAULT (CURL_SSLVERSION_TLSv1 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_0 (CURL_SSLVERSION_TLSv1_0 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_1 (CURL_SSLVERSION_TLSv1_1 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_2 (CURL_SSLVERSION_TLSv1_2 << 16) +#define CURL_SSLVERSION_MAX_TLSv1_3 (CURL_SSLVERSION_TLSv1_3 << 16) + + /* never use, keep last */ +#define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16) + +#define CURL_TLSAUTH_NONE 0L +#define CURL_TLSAUTH_SRP 1L + +enum CURL_TLSAUTH { + /* we set a single member here, just to make sure we still provide the enum, + but the values to use are defined above with L suffixes */ + CURL_TLSAUTH_LAST = 2 +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0L +#define CURL_REDIR_POST_301 1L +#define CURL_REDIR_POST_302 2L +#define CURL_REDIR_POST_303 4L +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +#define CURL_TIMECOND_NONE 0L +#define CURL_TIMECOND_IFMODSINCE 1L +#define CURL_TIMECOND_IFUNMODSINCE 2L +#define CURL_TIMECOND_LASTMOD 3L + +typedef enum { + /* we set a single member here, just to make sure we still provide + the enum typedef, but the values to use are defined above with L + suffixes */ + CURL_TIMECOND_LAST = 4 +} curl_TimeCond; + +/* Special size_t value signaling a null-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime curl_mime; /* Mime context. */ +typedef struct curl_mimepart curl_mimepart; /* Mime part context. */ + +/* CURLMIMEOPT_ defines are for the CURLOPT_MIME_OPTIONS option. */ +#define CURLMIMEOPT_FORMESCAPE (1L<<0) /* Use backslash-escaping for forms. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote filename. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + /********* the first one is unused ************/ + CURLFORM_NOTHING CURL_DEPRECATED(7.56.0, ""), + CURLFORM_COPYNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"), + CURLFORM_PTRNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"), + CURLFORM_NAMELENGTH CURL_DEPRECATED(7.56.0, ""), + CURLFORM_COPYCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_PTRCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_CONTENTSLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_FILECONTENT CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"), + CURLFORM_ARRAY CURL_DEPRECATED(7.56.0, ""), + CURLFORM_OBSOLETE, + CURLFORM_FILE CURL_DEPRECATED(7.56.0, "Use curl_mime_filedata()"), + + CURLFORM_BUFFER CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"), + CURLFORM_BUFFERPTR CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + CURLFORM_BUFFERLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + + CURLFORM_CONTENTTYPE CURL_DEPRECATED(7.56.0, "Use curl_mime_type()"), + CURLFORM_CONTENTHEADER CURL_DEPRECATED(7.56.0, "Use curl_mime_headers()"), + CURLFORM_FILENAME CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"), + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"), + CURLFORM_CONTENTLEN /* added in 7.46.0, provide a curl_off_t length */ + CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"), + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK CURL_DEPRECATED(7.56.0, ""), /* 1st, no error */ + + CURL_FORMADD_MEMORY CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_OPTION_TWICE CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_NULL CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_UNKNOWN_OPTION CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_INCOMPLETE CURL_DEPRECATED(7.56.0, ""), + CURL_FORMADD_ILLEGAL_ARRAY CURL_DEPRECATED(7.56.0, ""), + /* libcurl was built with form api disabled */ + CURL_FORMADD_DISABLED CURL_DEPRECATED(7.56.0, ""), + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode CURL_DEPRECATED(7.56.0, "Use curl_mime_init()") +curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int CURL_DEPRECATED(7.56.0, "") +curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void CURL_DEPRECATED(7.56.0, "Use curl_mime_free()") +curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ASCII string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for misuse of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* + * NAME curl_global_trace() + * + * DESCRIPTION + * + * curl_global_trace() can be invoked at application start to + * configure which components in curl should participate in tracing. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ +CURL_EXTERN CURLcode curl_global_trace(const char *config); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). If + * both id and name are specified, the name will be ignored. If neither id nor + * name are specified, the function will fail with CURLSSLSET_UNKNOWN_BACKEND + * and set the "avail" pointer to the NULL-terminated list of available + * backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a + * NULL-terminated list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +struct curl_ssl_backend { + curl_sslbackend id; + const char *name; +}; +typedef struct curl_ssl_backend curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *list, + const char *data); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *list); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, for SSL backends that support it. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there is a + linked list with textual information for a + certificate in the format "name:content". + eg "Subject:foo", "Issuer:bar", etc. */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_UPLOAD_T") + = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_DOWNLOAD_T") + = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_DOWNLOAD_T") + = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD + CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_UPLOAD_T") + = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD + CURL_DEPRECATED(7.55.0, + "Use CURLINFO_CONTENT_LENGTH_DOWNLOAD_T") + = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD + CURL_DEPRECATED(7.55.0, + "Use CURLINFO_CONTENT_LENGTH_UPLOAD_T") + = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET CURL_DEPRECATED(7.45.0, "Use CURLINFO_ACTIVESOCKET") + = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION CURL_DEPRECATED(7.48.0, "Use CURLINFO_TLS_SSL_PTR") + = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL CURL_DEPRECATED(7.85.0, "Use CURLINFO_SCHEME") + = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, + CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59, + CURLINFO_REFERER = CURLINFO_STRING + 60, + CURLINFO_CAINFO = CURLINFO_STRING + 61, + CURLINFO_CAPATH = CURLINFO_STRING + 62, + CURLINFO_XFER_ID = CURLINFO_OFF_T + 63, + CURLINFO_CONN_ID = CURLINFO_OFF_T + 64, + CURLINFO_QUEUE_TIME_T = CURLINFO_OFF_T + 65, + CURLINFO_USED_PROXY = CURLINFO_LONG + 66, + CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67, + CURLINFO_EARLYDATA_SENT_T = CURLINFO_OFF_T + 68, + CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69, + CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70, + CURLINFO_LASTONE = 70 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_HSTS, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* do not use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, + ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *share); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, /* 7.10 */ + CURLVERSION_SECOND, /* 7.11.1 */ + CURLVERSION_THIRD, /* 7.12.0 */ + CURLVERSION_FOURTH, /* 7.16.1 */ + CURLVERSION_FIFTH, /* 7.57.0 */ + CURLVERSION_SIXTH, /* 7.66.0 */ + CURLVERSION_SEVENTH, /* 7.70.0 */ + CURLVERSION_EIGHTH, /* 7.72.0 */ + CURLVERSION_NINTH, /* 7.75.0 */ + CURLVERSION_TENTH, /* 7.77.0 */ + CURLVERSION_ELEVENTH, /* 7.87.0 */ + CURLVERSION_TWELFTH, /* 8.8.0 */ + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_TWELFTH + +struct curl_version_info_data { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + const char *cainfo; /* the built-in default CURLOPT_CAINFO, might + be NULL */ + const char *capath; /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + const char *hyper_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + const char *gsasl_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_ELEVENTH */ + /* feature_names is terminated by an entry with a NULL feature name */ + const char * const *feature_names; + + /* These fields were added in CURLVERSION_TWELFTH */ + const char *rtmp_version; /* human readable string. */ +}; +typedef struct curl_version_info_data curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ +#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */ +#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */ +#define CURL_VERSION_THREADSAFE (1<<30) /* libcurl API is thread-safe */ + +/* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +/* + * NAME curl_easy_ssls_import() + * + * DESCRIPTION + * + * The curl_easy_ssls_import function adds a previously exported SSL session + * to the SSL session cache of the easy handle (or the underlying share). + */ +CURL_EXTERN CURLcode curl_easy_ssls_import(CURL *handle, + const char *session_key, + const unsigned char *shmac, + size_t shmac_len, + const unsigned char *sdata, + size_t sdata_len); + +/* This is the curl_ssls_export_cb callback prototype. It + * is passed to curl_easy_ssls_export() to extract SSL sessions/tickets. */ +typedef CURLcode curl_ssls_export_cb(CURL *handle, + void *userptr, + const char *session_key, + const unsigned char *shmac, + size_t shmac_len, + const unsigned char *sdata, + size_t sdata_len, + curl_off_t valid_until, + int ietf_tls_id, + const char *alpn, + size_t earlydata_max); + +/* + * NAME curl_easy_ssls_export() + * + * DESCRIPTION + * + * The curl_easy_ssls_export function iterates over all SSL sessions stored + * in the easy handle (or underlying share) and invokes the passed + * callback. + * + */ +CURL_EXTERN CURLcode curl_easy_ssls_export(CURL *handle, + curl_ssls_export_cb *export_fn, + void *userptr); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" +#include "options.h" +#include "header.h" +#include "websockets.h" +#include "mprintf.h" + +/* the typechecker does not work in C++ (yet) */ +#if ((defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ + (defined(__clang__) && __clang_major__ >= 14)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus && !CURL_DISABLE_TYPECHECK */ + +#endif /* CURLINC_CURL_H */ diff --git a/vendor/curl/c/curlver.h b/vendor/curl/c/curlver.h new file mode 100644 index 000000000..19b2bf875 --- /dev/null +++ b/vendor/curl/c/curlver.h @@ -0,0 +1,78 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "8.17.0-DEV" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 8 +#define LIBCURL_VERSION_MINOR 17 +#define LIBCURL_VERSION_PATCH 0 +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x081100 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "[unreleased]" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/vendor/curl/c/easy.h b/vendor/curl/c/easy.h new file mode 100644 index 000000000..fa1356493 --- /dev/null +++ b/vendor/curl/c/easy.h @@ -0,0 +1,125 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* Flag bits in the curl_blob struct: */ +#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */ +#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */ + +struct curl_blob { + void *data; + size_t len; + unsigned int flags; /* bit 0 is defined, the rest are reserved and should be + left zeroes */ +}; + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. + * The third argument MUST be pointing to the specific type of the used option + * which is documented in each manpage of the option. The data pointed to + * will be filled in accordingly and can be relied upon only if the function + * returns CURLE_OK. This function is intended to get used *AFTER* a performed + * transfer, all results from this function are undefined until the transfer + * is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a curl handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/vendor/curl/c/header.h b/vendor/curl/c/header.h new file mode 100644 index 000000000..7465274b9 --- /dev/null +++ b/vendor/curl/c/header.h @@ -0,0 +1,74 @@ +#ifndef CURLINC_HEADER_H +#define CURLINC_HEADER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +struct curl_header { + char *name; /* this might not use the same case */ + char *value; + size_t amount; /* number of headers using this name */ + size_t index; /* ... of this instance, 0 or higher */ + unsigned int origin; /* see bits below */ + void *anchor; /* handle privately used by libcurl */ +}; + +/* 'origin' bits */ +#define CURLH_HEADER (1<<0) /* plain server header */ +#define CURLH_TRAILER (1<<1) /* trailers */ +#define CURLH_CONNECT (1<<2) /* CONNECT headers */ +#define CURLH_1XX (1<<3) /* 1xx headers */ +#define CURLH_PSEUDO (1<<4) /* pseudo headers */ + +typedef enum { + CURLHE_OK, + CURLHE_BADINDEX, /* header exists but not with this index */ + CURLHE_MISSING, /* no such header exists */ + CURLHE_NOHEADERS, /* no headers at all exist (yet) */ + CURLHE_NOREQUEST, /* no request with this number was used */ + CURLHE_OUT_OF_MEMORY, /* out of memory while processing */ + CURLHE_BAD_ARGUMENT, /* a function argument was not okay */ + CURLHE_NOT_BUILT_IN /* if API was disabled in the build */ +} CURLHcode; + +CURL_EXTERN CURLHcode curl_easy_header(CURL *easy, + const char *name, + size_t index, + unsigned int origin, + int request, + struct curl_header **hout); + +CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy, + unsigned int origin, + int request, + struct curl_header *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_HEADER_H */ diff --git a/vendor/curl/c/mprintf.h b/vendor/curl/c/mprintf.h new file mode 100644 index 000000000..9272e7489 --- /dev/null +++ b/vendor/curl/c/mprintf.h @@ -0,0 +1,85 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CURL_TEMP_PRINTF +#if (defined(__GNUC__) || defined(__clang__) || \ + defined(__IAR_SYSTEMS_ICC__)) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(CURL_NO_FMT_CHECKS) +#if defined(__MINGW32__) && !defined(__clang__) +#ifdef __MINGW_PRINTF_FORMAT /* mingw-w64 3.0.0+. Needs stdio.h. */ +#define CURL_TEMP_PRINTF(fmt, arg) \ + __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg))) +#else +#define CURL_TEMP_PRINTF(fmt, arg) +#endif +#else +#define CURL_TEMP_PRINTF(fmt, arg) \ + __attribute__((format(printf, fmt, arg))) +#endif +#else +#define CURL_TEMP_PRINTF(fmt, arg) +#endif +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...) + CURL_TEMP_PRINTF(1, 2); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...) + CURL_TEMP_PRINTF(2, 3); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...) + CURL_TEMP_PRINTF(2, 3); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...) + CURL_TEMP_PRINTF(3, 4); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args) + CURL_TEMP_PRINTF(1, 0); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args) + CURL_TEMP_PRINTF(2, 0); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args) + CURL_TEMP_PRINTF(2, 0); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args) + CURL_TEMP_PRINTF(3, 0); +CURL_EXTERN char *curl_maprintf(const char *format, ...) + CURL_TEMP_PRINTF(1, 2); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args) + CURL_TEMP_PRINTF(1, 0); + +#undef CURL_TEMP_PRINTF + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/vendor/curl/c/multi.h b/vendor/curl/c/multi.h new file mode 100644 index 000000000..4e30637ef --- /dev/null +++ b/vendor/curl/c/multi.h @@ -0,0 +1,553 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +/* + This is an "external" header file. Do not give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void CURLM; + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + CURLM_ABORTED_BY_CALLBACK, + CURLM_UNRECOVERABLE_POLL, + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We do not use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; +}; + +/* + * Name: curl_multi_init() + * + * Desc: initialize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there is data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there is any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be simple and only contain basic + * information. If more involved information is wanted, we will + * provide the particular "transfer handle" in that struct and that + * should/could/would be used in subsequent curl_easy_getinfo() calls + * (or similar). The point being that we must never expose complex + * structs to applications, as then we will undoubtably get backwards + * compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a null-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See manpage for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()") +curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()") +curl_multi_socket_all(CURLM *multi_handle, int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +typedef enum { + /* This is the socket callback function pointer */ + CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), + + /* This is the timer callback function pointer */ + CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7), + + /* maximum number of requests in a pipeline */ + CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10), + + /* a list of site names(+port) that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11), + + /* a list of server types that are blocked from pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13), + + /* This is the server push callback function pointer */ + CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16), + + /* network has changed, adjust caches/connection reuse */ + CURLOPT(CURLMOPT_NETWORK_CHANGED, CURLOPTTYPE_LONG, 17), + + /* This is the notify callback function pointer */ + CURLOPT(CURLMOPT_NOTIFYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 18), + + /* This is the argument passed to the notify callback */ + CURLOPT(CURLMOPT_NOTIFYDATA, CURLOPTTYPE_OBJECTPOINT, 19), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + +/* Definition of bits for the CURLMOPT_NETWORK_CHANGED argument: */ + +/* - CURLMNWC_CLEAR_CONNS tells libcurl to prevent further reuse of existing + connections. Connections that are idle will be closed. Ongoing transfers + will continue with the connection they have. */ +#define CURLMNWC_CLEAR_CONNS (1L<<0) + +/* - CURLMNWC_CLEAR_DNS tells libcurl to prevent further reuse of existing + connections. Connections that are idle will be closed. Ongoing transfers + will continue with the connection they have. */ +#define CURLMNWC_CLEAR_DNS (1L<<0) + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + +/* + * Name: curl_multi_get_handles() + * + * Desc: Returns an allocated array holding all handles currently added to + * the multi handle. Marks the final entry with a NULL pointer. If + * there is no easy handle added to the multi handle, this function + * returns an array with the first entry as a NULL pointer. + * + * Returns: NULL on failure, otherwise a CURL **array pointer + */ +CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle); + + +typedef enum { + CURLMINFO_NONE, /* first, never use this */ + /* The number of easy handles currently managed by the multi handle, + * e.g. have been added but not yet removed. */ + CURLMINFO_XFERS_CURRENT = 1, + /* The number of easy handles running, e.g. not done and not queueing. */ + CURLMINFO_XFERS_RUNNING = 2, + /* The number of easy handles waiting to start, e.g. for a connection + * to become available due to limits on parallelism, max connections + * or other factors. */ + CURLMINFO_XFERS_PENDING = 3, + /* The number of easy handles finished, waiting for their results to + * be read via `curl_multi_info_read()`. */ + CURLMINFO_XFERS_DONE = 4, + /* The total number of easy handles added to the multi handle, ever. */ + CURLMINFO_XFERS_ADDED = 5, + + CURLMINFO_LASTENTRY /* the last unused */ +} CURLMinfo_offt; + +/* + * Name: curl_multi_get_offt() + * + * Desc: Retrieves a numeric value for the `CURLMINFO_*` enums. + * + * Returns: CULRM_OK or error when value could not be obtained. + */ +CURL_EXTERN CURLMcode curl_multi_get_offt(CURLM *multi_handle, + CURLMinfo_offt info, + curl_off_t *pvalue); + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. + * + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 +#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */ + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +/* + * Name: curl_multi_waitfds() + * + * Desc: Ask curl for fds for polling. The app can use these to poll on. + * We want curl_multi_perform() called as soon as one of them are + * ready. Passing zero size allows to get just a number of fds. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi, + struct curl_waitfd *ufds, + unsigned int size, + unsigned int *fd_count); + +/* + * Notifications dispatched by a multi handle, when enabled. + */ +#define CURLMNOTIFY_INFO_READ 0 +#define CURLMNOTIFY_EASY_DONE 1 + +/* + * Callback to install via CURLMOPT_NOTIFYFUNCTION. + */ +typedef void (*curl_notify_callback)(CURLM *multi, + unsigned int notification, + CURL *easy, + void *user_data); + +CURL_EXTERN CURLMcode curl_multi_notify_disable(CURLM *multi, + unsigned int notification); + +CURL_EXTERN CURLMcode curl_multi_notify_enable(CURLM *multi, + unsigned int notification); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/vendor/curl/c/options.h b/vendor/curl/c/options.h new file mode 100644 index 000000000..77cab7768 --- /dev/null +++ b/vendor/curl/c/options.h @@ -0,0 +1,70 @@ +#ifndef CURLINC_OPTIONS_H +#define CURLINC_OPTIONS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + CURLOT_LONG, /* long (a range of values) */ + CURLOT_VALUES, /* (a defined set or bitmask) */ + CURLOT_OFF_T, /* curl_off_t (a range of values) */ + CURLOT_OBJECT, /* pointer (void *) */ + CURLOT_STRING, /* (char * to null-terminated buffer) */ + CURLOT_SLIST, /* (struct curl_slist *) */ + CURLOT_CBPTR, /* (void * passed as-is to a callback) */ + CURLOT_BLOB, /* blob (struct curl_blob *) */ + CURLOT_FUNCTION /* function pointer */ +} curl_easytype; + +/* Flag bits */ + +/* "alias" means it is provided for old programs to remain functional, + we prefer another name */ +#define CURLOT_FLAG_ALIAS (1<<0) + +/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size + to use for curl_easy_setopt() for the given id */ +struct curl_easyoption { + const char *name; + CURLoption id; + curl_easytype type; + unsigned int flags; +}; + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_name(const char *name); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_by_id(CURLoption id); + +CURL_EXTERN const struct curl_easyoption * +curl_easy_option_next(const struct curl_easyoption *prev); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif +#endif /* CURLINC_OPTIONS_H */ diff --git a/vendor/curl/c/stdcheaders.h b/vendor/curl/c/stdcheaders.h new file mode 100644 index 000000000..7451aa305 --- /dev/null +++ b/vendor/curl/c/stdcheaders.h @@ -0,0 +1,35 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/vendor/curl/c/system.h b/vendor/curl/c/system.h new file mode 100644 index 000000000..62ed2b0f4 --- /dev/null +++ b/vendor/curl/c/system.h @@ -0,0 +1,408 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built-in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t MUST be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#ifdef __DJGPP__ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# ifdef _MSC_VER +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# ifdef __MCST__ /* MCST eLbrus Compiler Collection */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(macintosh) +# include +# if TYPE_LONGLONG +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__TANDEM) +# ifndef __LP64 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int +# endif + +#elif defined(UNDER_CE) +# ifdef __MINGW32CE__ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__MINGW32__) +# include +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# define CURL_PULL_SYS_TYPES_H 1 + +#elif defined(__VMS) +# ifdef __VAX +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__MVS__) +# ifdef _LONG_LONG +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else /* _LP64 and default */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# ifdef _LONG_LONG +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else /* _LP64 and default */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# ifndef _LP64 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__hpux) /* HP aCC compiler */ +# ifndef _LP64 +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 1800) +# include +# define CURL_FORMAT_CURL_OFF_T PRId64 +# define CURL_FORMAT_CURL_OFF_TU PRIu64 +# else +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# endif +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# if (__GNUC__ >= 4) || \ + ((__GNUC__ == 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 4)) +# define CURL_POPCOUNT64(x) __builtin_popcountll(x) +# define CURL_CTZ64(x) __builtin_ctzll(x) +# endif +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# if (__GNUC__ >= 4) || \ + ((__GNUC__ == 3) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 4)) +# define CURL_POPCOUNT64(x) __builtin_popcountl(x) +# define CURL_CTZ64(x) __builtin_ctzl(x) +# endif +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32-bit style */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/vendor/curl/c/typecheck-gcc.h b/vendor/curl/c/typecheck-gcc.h new file mode 100644 index 000000000..063cea57e --- /dev/null +++ b/vendor/curl/c/typecheck-gcc.h @@ -0,0 +1,958 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * Wcurl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * Wcurl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you will + * just need to extend the appropriate _curl_*_option macro + */ + +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + if(__builtin_constant_p(option)) { \ + CURL_IGNORE_DEPRECATION( \ + if(curlcheck_long_option(option)) \ + if(!curlcheck_long(value)) \ + Wcurl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(option)) \ + if(!curlcheck_off_t(value)) \ + Wcurl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(option)) \ + if(!curlcheck_string(value)) \ + Wcurl_easy_setopt_err_string(); \ + if((option) == CURLOPT_PRIVATE) { } \ + if(curlcheck_write_cb_option(option)) \ + if(!curlcheck_write_cb(value)) \ + Wcurl_easy_setopt_err_write_callback(); \ + if(curlcheck_curl_option(option)) \ + if(!curlcheck_curl(value)) \ + Wcurl_easy_setopt_err_curl(); \ + if((option) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + Wcurl_easy_setopt_err_resolver_start_callback(); \ + if((option) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + Wcurl_easy_setopt_err_read_cb(); \ + if((option) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + Wcurl_easy_setopt_err_ioctl_cb(); \ + if((option) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + Wcurl_easy_setopt_err_sockopt_cb(); \ + if((option) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + Wcurl_easy_setopt_err_opensocket_cb(); \ + if((option) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + Wcurl_easy_setopt_err_progress_cb(); \ + if((option) == CURLOPT_XFERINFOFUNCTION) \ + if(!curlcheck_xferinfo_cb(value)) \ + Wcurl_easy_setopt_err_xferinfo_cb(); \ + if((option) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + Wcurl_easy_setopt_err_debug_cb(); \ + if((option) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + Wcurl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(option)) \ + if(!curlcheck_conv_cb(value)) \ + Wcurl_easy_setopt_err_conv_cb(); \ + if((option) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + Wcurl_easy_setopt_err_seek_cb(); \ + if((option) == CURLOPT_CHUNK_BGN_FUNCTION) \ + if(!curlcheck_chunk_bgn_cb(value)) \ + Wcurl_easy_setopt_err_chunk_bgn_cb(); \ + if((option) == CURLOPT_CHUNK_END_FUNCTION) \ + if(!curlcheck_chunk_end_cb(value)) \ + Wcurl_easy_setopt_err_chunk_end_cb(); \ + if((option) == CURLOPT_CLOSESOCKETFUNCTION) \ + if(!curlcheck_close_socket_cb(value)) \ + Wcurl_easy_setopt_err_close_socket_cb(); \ + if((option) == CURLOPT_FNMATCH_FUNCTION) \ + if(!curlcheck_fnmatch_cb(value)) \ + Wcurl_easy_setopt_err_fnmatch_cb(); \ + if((option) == CURLOPT_HSTSREADFUNCTION) \ + if(!curlcheck_hstsread_cb(value)) \ + Wcurl_easy_setopt_err_hstsread_cb(); \ + if((option) == CURLOPT_HSTSWRITEFUNCTION) \ + if(!curlcheck_hstswrite_cb(value)) \ + Wcurl_easy_setopt_err_hstswrite_cb(); \ + if((option) == CURLOPT_SSH_HOSTKEYFUNCTION) \ + if(!curlcheck_ssh_hostkey_cb(value)) \ + Wcurl_easy_setopt_err_ssh_hostkey_cb(); \ + if((option) == CURLOPT_SSH_KEYFUNCTION) \ + if(!curlcheck_ssh_key_cb(value)) \ + Wcurl_easy_setopt_err_ssh_key_cb(); \ + if((option) == CURLOPT_INTERLEAVEFUNCTION) \ + if(!curlcheck_interleave_cb(value)) \ + Wcurl_easy_setopt_err_interleave_cb(); \ + if((option) == CURLOPT_PREREQFUNCTION) \ + if(!curlcheck_prereq_cb(value)) \ + Wcurl_easy_setopt_err_prereq_cb(); \ + if((option) == CURLOPT_TRAILERFUNCTION) \ + if(!curlcheck_trailer_cb(value)) \ + Wcurl_easy_setopt_err_trailer_cb(); \ + if(curlcheck_cb_data_option(option)) \ + if(!curlcheck_cb_data(value)) \ + Wcurl_easy_setopt_err_cb_data(); \ + if((option) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + Wcurl_easy_setopt_err_error_buffer(); \ + if((option) == CURLOPT_CURLU) \ + if(!curlcheck_ptr((value), CURLU)) \ + Wcurl_easy_setopt_err_curlu(); \ + if((option) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + Wcurl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(option)) \ + if(!curlcheck_postfields(value)) \ + Wcurl_easy_setopt_err_postfields(); \ + if((option) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + Wcurl_easy_setopt_err_curl_httpost(); \ + if((option) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + Wcurl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(option)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + Wcurl_easy_setopt_err_curl_slist(); \ + if((option) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + Wcurl_easy_setopt_err_CURLSH(); \ + ) \ + } \ + curl_easy_setopt(handle, option, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + if(__builtin_constant_p(info)) { \ + CURL_IGNORE_DEPRECATION( \ + if(curlcheck_string_info(info)) \ + if(!curlcheck_arr((arg), char *)) \ + Wcurl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(info)) \ + if(!curlcheck_arr((arg), long)) \ + Wcurl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(info)) \ + if(!curlcheck_arr((arg), double)) \ + Wcurl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + Wcurl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + Wcurl_easy_getinfo_err_curl_tlssessioninfo(); \ + if(curlcheck_certinfo_info(info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + Wcurl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + Wcurl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + Wcurl_easy_getinfo_err_curl_off_t(); \ + ) \ + } \ + curl_easy_getinfo(handle, info, arg); \ + }) + +#define curl_multi_setopt(handle, option, value) \ + __extension__({ \ + if(__builtin_constant_p(option)) { \ + if(curlcheck_long_option(option)) \ + if(!curlcheck_long(value)) \ + Wcurl_multi_setopt_err_long(); \ + if(curlcheck_off_t_option(option)) \ + if(!curlcheck_off_t(value)) \ + Wcurl_multi_setopt_err_curl_off_t(); \ + if(curlcheck_multicb_data_option(option)) \ + if(!curlcheck_cb_data(value)) \ + Wcurl_multi_setopt_err_cb_data(); \ + if(curlcheck_charpp_option(option)) \ + if(!curlcheck_ptrptr(value, char)) \ + Wcurl_multi_setopt_err_charpp(); \ + if((option) == CURLMOPT_NOTIFYFUNCTION) \ + if(!curlcheck_multinotify_cb(value)) \ + Wcurl_multi_setopt_err_notifycb(); \ + if((option) == CURLMOPT_PUSHFUNCTION) \ + if(!curlcheck_multipush_cb(value)) \ + Wcurl_multi_setopt_err_pushcb(); \ + if((option) == CURLMOPT_SOCKETFUNCTION) \ + if(!curlcheck_multisocket_cb(value)) \ + Wcurl_multi_setopt_err_socketcb(); \ + if((option) == CURLMOPT_TIMERFUNCTION) \ + if(!curlcheck_multitimer_cb(value)) \ + Wcurl_multi_setopt_err_timercb(); \ + } \ + curl_multi_setopt(handle, option, value); \ + }) + +/* evaluates to true if the option takes a data argument to pass to a + callback */ +#define curlcheck_multicb_data_option(option) \ + ((option) == CURLMOPT_NOTIFYDATA || \ + (option) == CURLMOPT_PUSHDATA || \ + (option) == CURLMOPT_SOCKETDATA || \ + (option) == CURLMOPT_TIMERDATA || \ + 0) + +/* evaluates to true if the option takes a char ** argument */ +#define curlcheck_charpp_option(option) \ + ((option) == CURLMOPT_PIPELINING_SERVER_BL || \ + (option) == CURLMOPT_PIPELINING_SITE_BL || \ + 0) + +/* evaluates to true if expr is of type curl_multi_timer_callback */ +#define curlcheck_multitimer_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_multi_timer_callback)) + +/* evaluates to true if expr is of type curl_socket_callback */ +#define curlcheck_multisocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_socket_callback)) + +/* evaluates to true if expr is of type curl_push_callback */ +#define curlcheck_multipush_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_push_callback)) + +/* evaluates to true if expr is of type curl_push_callback */ +#define curlcheck_multinotify_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_notify_callback)) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) + + +/* the actual warnings, triggered by calling the Wcurl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(Wcurl_multi_setopt_err_long, + "curl_multi_setopt expects a long argument") +CURLWARNING(Wcurl_multi_setopt_err_curl_off_t, + "curl_multi_setopt expects a curl_off_t argument") +CURLWARNING(Wcurl_multi_setopt_err_cb_data, + "curl_multi_setopt expects a 'void *' argument") +CURLWARNING(Wcurl_multi_setopt_err_charpp, + "curl_multi_setopt expects a 'char **' argument") +CURLWARNING(Wcurl_multi_setopt_err_pushcb, + "curl_multi_setopt expects a curl_push_callback argument") +CURLWARNING(Wcurl_multi_setopt_err_notifycb, + "curl_multi_setopt expects a curl_notify_callback argument") +CURLWARNING(Wcurl_multi_setopt_err_socketcb, + "curl_multi_setopt expects a curl_socket_callback argument") +CURLWARNING(Wcurl_multi_setopt_err_timercb, + "curl_multi_setopt expects a curl_multi_timer_callback argument") + +CURLWARNING(Wcurl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument") +CURLWARNING(Wcurl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument") +CURLWARNING(Wcurl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument") +CURLWARNING(Wcurl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_xferinfo_cb, + "curl_easy_setopt expects a curl_xferinfo_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument") +CURLWARNING(Wcurl_easy_setopt_err_chunk_bgn_cb, + "curl_easy_setopt expects a curl_chunk_bgn_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_chunk_end_cb, + "curl_easy_setopt expects a curl_chunk_end_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_close_socket_cb, + "curl_easy_setopt expects a curl_closesocket_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_fnmatch_cb, + "curl_easy_setopt expects a curl_fnmatch_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_hstsread_cb, + "curl_easy_setopt expects a curl_hstsread_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_hstswrite_cb, + "curl_easy_setopt expects a curl_hstswrite_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_ssh_key_cb, + "curl_easy_setopt expects a curl_sshkeycallback argument") +CURLWARNING(Wcurl_easy_setopt_err_ssh_hostkey_cb, + "curl_easy_setopt expects a curl_sshhostkeycallback argument") +CURLWARNING(Wcurl_easy_setopt_err_interleave_cb, + "curl_easy_setopt expects a curl_interleave_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_prereq_cb, + "curl_easy_setopt expects a curl_prereq_callback argument") +CURLWARNING(Wcurl_easy_setopt_err_trailer_cb, + "curl_easy_setopt expects a curl_trailerfunc_ok argument") +CURLWARNING(Wcurl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument") +CURLWARNING(Wcurl_easy_setopt_err_curlu, + "curl_easy_setopt expects a 'CURLU *' argument") +CURLWARNING(Wcurl_easy_setopt_err_curl, + "curl_easy_setopt expects a 'CURL *' argument") +CURLWARNING(Wcurl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument") +CURLWARNING(Wcurl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument") +CURLWARNING(Wcurl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument") +CURLWARNING(Wcurl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument") +CURLWARNING(Wcurl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument") +CURLWARNING(Wcurl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument") +CURLWARNING(Wcurl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *'") +CURLWARNING(Wcurl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long") +CURLWARNING(Wcurl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double") +CURLWARNING(Wcurl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *'") +CURLWARNING(Wcurl_easy_getinfo_err_curl_tlssessioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *'") +CURLWARNING(Wcurl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *'") +CURLWARNING(Wcurl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t") +CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB)) + +/* option takes a CURL * argument */ +#define curlcheck_curl_option(option) \ + ((option) == CURLOPT_STREAM_DEPENDS || \ + (option) == CURLOPT_STREAM_DEPENDS_E || \ + 0) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_ECH || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_HAPROXY_CLIENT_IP || \ + (option) == CURLOPT_HSTS || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROTOCOLS_STR || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_ISSUERCERT || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REDIR_PROTOCOLS_STR || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_SSL_EC_CURVES || \ + (option) == CURLOPT_SSL_SIGNATURE_ALGORITHMS || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_AWS_SIGV4 || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_HSTSREADDATA || \ + (option) == CURLOPT_HSTSWRITEDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PREREQDATA || \ + (option) == CURLOPT_XFERINFODATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + (option) == CURLOPT_SSH_HOSTKEYDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \ + (info) != CURLINFO_PRIVATE) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type */ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is type**, const type** or NULL */ +#define curlcheck_ptrptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type **) || \ + __builtin_types_compatible_p(__typeof__(expr), type *[]) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *[]) || \ + __builtin_types_compatible_p(__typeof__(expr), const type **)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a CURL * */ +#define curlcheck_curl(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), CURL *)) + + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + ( \ + ((sizeof(long) != sizeof(int)) && \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long))) \ + || \ + ((sizeof(long) == sizeof(int)) && \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char))) \ + ) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback4) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback5) || \ + curlcheck_cb_compatible((expr), Wcurl_read_callback6)) +typedef size_t (*Wcurl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*Wcurl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*Wcurl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*Wcurl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*Wcurl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*Wcurl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback4) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback5) || \ + curlcheck_cb_compatible((expr), Wcurl_write_callback6)) +typedef size_t (*Wcurl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*Wcurl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*Wcurl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*Wcurl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*Wcurl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*Wcurl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_ioctl_callback4)) +typedef curlioerr (*Wcurl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*Wcurl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*Wcurl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*Wcurl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_sockopt_callback2)) +typedef int (*Wcurl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*Wcurl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_opensocket_callback4)) +typedef curl_socket_t (*Wcurl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*Wcurl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*Wcurl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*Wcurl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_progress_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_progress_callback2)) +typedef int (*Wcurl_progress_callback1)(void *, + double, double, double, double); +typedef int (*Wcurl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_xferinfo_callback */ +#define curlcheck_xferinfo_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_xferinfo_callback)) + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback4) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback5) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback6) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback7) || \ + curlcheck_cb_compatible((expr), Wcurl_debug_callback8)) +typedef int (*Wcurl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*Wcurl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*Wcurl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*Wcurl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*Wcurl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*Wcurl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*Wcurl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*Wcurl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), Wcurl_ssl_ctx_callback8)) +typedef CURLcode (*Wcurl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we are included before OpenSSL headers... + */ +typedef CURLcode (*Wcurl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *); +typedef CURLcode (*Wcurl_ssl_ctx_callback8)(CURL *, const SSL_CTX *, + const void *); +#else +typedef Wcurl_ssl_ctx_callback1 Wcurl_ssl_ctx_callback5; +typedef Wcurl_ssl_ctx_callback1 Wcurl_ssl_ctx_callback6; +typedef Wcurl_ssl_ctx_callback1 Wcurl_ssl_ctx_callback7; +typedef Wcurl_ssl_ctx_callback1 Wcurl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_conv_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_conv_callback2) || \ + curlcheck_cb_compatible((expr), Wcurl_conv_callback3) || \ + curlcheck_cb_compatible((expr), Wcurl_conv_callback4)) +typedef CURLcode (*Wcurl_conv_callback1)(char *, size_t length); +typedef CURLcode (*Wcurl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*Wcurl_conv_callback3)(void *, size_t length); +typedef CURLcode (*Wcurl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_seek_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_seek_callback2)) +typedef CURLcode (*Wcurl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*Wcurl_seek_callback2)(const void *, curl_off_t, int); + +/* evaluates to true if expr is of type curl_chunk_bgn_callback */ +#define curlcheck_chunk_bgn_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_chunk_bgn_callback) || \ + curlcheck_cb_compatible((expr), Wcurl_chunk_bgn_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_chunk_bgn_callback2)) +typedef long (*Wcurl_chunk_bgn_callback1)(struct curl_fileinfo *, + void *, int); +typedef long (*Wcurl_chunk_bgn_callback2)(void *, void *, int); + +/* evaluates to true if expr is of type curl_chunk_end_callback */ +#define curlcheck_chunk_end_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_chunk_end_callback)) + +/* evaluates to true if expr is of type curl_closesocket_callback */ +#define curlcheck_close_socket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_closesocket_callback)) + +/* evaluates to true if expr is of type curl_fnmatch_callback */ +#define curlcheck_fnmatch_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_fnmatch_callback)) + +/* evaluates to true if expr is of type curl_hstsread_callback */ +#define curlcheck_hstsread_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_hstsread_callback)) + +/* evaluates to true if expr is of type curl_hstswrite_callback */ +#define curlcheck_hstswrite_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_hstswrite_callback)) + +/* evaluates to true if expr is of type curl_sshhostkeycallback */ +#define curlcheck_ssh_hostkey_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sshhostkeycallback)) + +/* evaluates to true if expr is of type curl_sshkeycallback */ +#define curlcheck_ssh_key_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sshkeycallback)) + +/* evaluates to true if expr is of type curl_interleave_callback */ +#define curlcheck_interleave_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), Wcurl_interleave_callback1) || \ + curlcheck_cb_compatible((expr), Wcurl_interleave_callback2)) +typedef size_t (*Wcurl_interleave_callback1)(void *p, size_t s, + size_t n, void *u); +typedef size_t (*Wcurl_interleave_callback2)(char *p, size_t s, + size_t n, void *u); + +/* evaluates to true if expr is of type curl_prereq_callback */ +#define curlcheck_prereq_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_prereq_callback)) + +/* evaluates to true if expr is of type curl_trailer_callback */ +#define curlcheck_trailer_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_trailer_callback)) + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/vendor/curl/c/urlapi.h b/vendor/curl/c/urlapi.h new file mode 100644 index 000000000..34c11a6bb --- /dev/null +++ b/vendor/curl/c/urlapi.h @@ -0,0 +1,155 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT, /* 17 */ + CURLUE_NO_ZONEID, /* 18 */ + CURLUE_BAD_FILE_URL, /* 19 */ + CURLUE_BAD_FRAGMENT, /* 20 */ + CURLUE_BAD_HOSTNAME, /* 21 */ + CURLUE_BAD_IPV6, /* 22 */ + CURLUE_BAD_LOGIN, /* 23 */ + CURLUE_BAD_PASSWORD, /* 24 */ + CURLUE_BAD_PATH, /* 25 */ + CURLUE_BAD_QUERY, /* 26 */ + CURLUE_BAD_SCHEME, /* 27 */ + CURLUE_BAD_SLASHES, /* 28 */ + CURLUE_BAD_USER, /* 29 */ + CURLUE_LACKS_IDN, /* 30 */ + CURLUE_TOO_LARGE, /* 31 */ + CURLUE_LAST +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ +#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */ +#define CURLU_PUNYCODE (1<<12) /* get the hostname in punycode */ +#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */ +#define CURLU_GET_EMPTY (1<<14) /* allow empty queries and fragments + when extracting the URL or the + components */ +#define CURLU_NO_GUESS_SCHEME (1<<15) /* for get, do not accept a guess */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(const CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(const CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + +/* + * curl_url_strerror() turns a CURLUcode value into the equivalent human + * readable error string. This is useful for printing meaningful error + * messages. + */ +CURL_EXTERN const char *curl_url_strerror(CURLUcode); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/vendor/curl/c/websockets.h b/vendor/curl/c/websockets.h new file mode 100644 index 000000000..df8590f39 --- /dev/null +++ b/vendor/curl/c/websockets.h @@ -0,0 +1,98 @@ +#ifndef CURLINC_WEBSOCKETS_H +#define CURLINC_WEBSOCKETS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +struct curl_ws_frame { + int age; /* zero */ + int flags; /* See the CURLWS_* defines */ + curl_off_t offset; /* the offset of this data into the frame */ + curl_off_t bytesleft; /* number of pending bytes left of the payload */ + size_t len; /* size of the current data chunk */ +}; + +/* flag bits */ +#define CURLWS_TEXT (1<<0) +#define CURLWS_BINARY (1<<1) +#define CURLWS_CONT (1<<2) +#define CURLWS_CLOSE (1<<3) +#define CURLWS_PING (1<<4) +#define CURLWS_OFFSET (1<<5) + +/* + * NAME curl_ws_recv() + * + * DESCRIPTION + * + * Receives data from the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen, + size_t *recv, + const struct curl_ws_frame **metap); + +/* flags for curl_ws_send() */ +#define CURLWS_PONG (1<<6) + +/* + * NAME curl_ws_send() + * + * DESCRIPTION + * + * Sends data over the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer, + size_t buflen, size_t *sent, + curl_off_t fragsize, + unsigned int flags); + +/* + * NAME curl_ws_start_frame() + * + * DESCRIPTION + * + * Buffers a websocket frame header with the given flags and length. + * Errors when a previous frame is not complete, e.g. not all its + * payload has been added. + */ +CURL_EXTERN CURLcode curl_ws_start_frame(CURL *curl, + unsigned int flags, + curl_off_t frame_len); + +/* bits for the CURLOPT_WS_OPTIONS bitmask: */ +#define CURLWS_RAW_MODE (1L<<0) +#define CURLWS_NOAUTOPONG (1L<<1) + +CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_WEBSOCKETS_H */ diff --git a/vendor/curl/curl.odin b/vendor/curl/curl.odin new file mode 100644 index 000000000..6ecc8030f --- /dev/null +++ b/vendor/curl/curl.odin @@ -0,0 +1,2933 @@ +package vendor_curl + +import c "core:c/libc" + +when ODIN_OS == .Windows { + @(export, extra_linker_flags="/NODEFAULTLIB:msvcrt") + foreign import lib { + "lib/libcurl.lib", + "system:Advapi32.lib", + "system:Crypt32.lib", + "system:Normaliz.lib", + "system:Secur32.lib", + "system:Wldap32.lib", + "system:Ws2_32.lib", + "system:iphlpapi.lib", + } +} else when ODIN_OS == .Darwin { + @(export) + foreign import lib { + "system:curl", + "system:z", + "system:SystemConfiguration.framework", + } +} else { + @(export) + foreign import lib { + "system:curl", + "system:mbedtls", + "system:mbedx509", + "system:mbedcrypto", + "system:z", + } +} + +off_t :: i64 +socklen_t :: c.int + +/* This is the global package copyright */ +COPYRIGHT :: "Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header file origins: */ +VERSION :: "8.17.0" + +/* The numeric version number is also available "in parts" by using these defines: */ +VERSION_MAJOR :: 8 +VERSION_MINOR :: 17 +VERSION_PATCH :: 0 + +/* + This is the numeric version of the libcurl version number, meant for easier + parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +VERSION_NUM :: 0x081100 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +TIMESTAMP :: "2025-11-05" + + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +slist :: struct { + data: [^]byte, + next: ^slist, +} + + +CURL :: struct {} +CURLSH :: struct {} + +socket_t :: distinct c.int +SOCKET_BAD :: socket_t(-1) + +sslbackend :: enum c.int { + NONE = 0, + OPENSSL = 1, + GNUTLS = 2, + NSS = 3, /* CURL_DEPRECATED(8.3.0, "") */ + OBSOLETE4 = 4, /* Was QSOSSL. */ + GSKIT = 5, /* CURL_DEPRECATED(8.3.0, "") */ + POLARSSL = 6, /* CURL_DEPRECATED(7.69.0, "") */ + WOLFSSL = 7, + SCHANNEL = 8, + SECURETRANSPORT = 9, /* CURL_DEPRECATED(8.15.0, "") */ + AXTLS = 10, /* CURL_DEPRECATED(7.61.0, "") */ + MBEDTLS = 11, + MESALINK = 12, /* CURL_DEPRECATED(7.82.0, "") */ + BEARSSL = 13, /* CURL_DEPRECATED(8.15.0, "") */ + RUSTLS = 14, + + + AWSLC = OPENSSL, + BORINGSSL = OPENSSL, + LIBRESSL = OPENSSL, +} + +/* bits for the CURLOPT_FOLLOWLOCATION option */ +FOLLOW_ALL :: 1 /* generic follow redirects */ + +/* + Do not use the custom method in the follow-up request if the HTTP code + instructs so (301, 302, 303). +*/ +FOLLOW_OBEYCODE :: 2 + +/* Only use the custom method in the first request, always reset in the next */ +FOLLOW_FIRSTONLY :: 3 + +httppost_flags :: distinct bit_set[httppost_flag; c.long] +httppost_flag :: enum c.long { + /* specified content is a filename */ + FILENAME = 0, + /* specified content is a filename */ + READFILE = 1, + /* name is only stored pointer do not free in formfree */ + PTRNAME = 2, + /* contents is only stored pointer do not free in formfree */ + PTRCONTENTS = 3, + /* upload file from buffer */ + BUFFER = 4, + /* upload file from pointer contents */ + PTRBUFFER = 5, + /* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ + CALLBACK = 6, + /* use size in 'contentlen', added in 7.46.0 */ + LARGE = 7, +} + +HTTPPOST_FILENAME :: httppost_flags{.FILENAME} +HTTPPOST_READFILE :: httppost_flags{.READFILE} +HTTPPOST_PTRNAME :: httppost_flags{.PTRNAME} +HTTPPOST_PTRCONTENTS :: httppost_flags{.PTRCONTENTS} +HTTPPOST_BUFFER :: httppost_flags{.BUFFER} +HTTPPOST_PTRBUFFER :: httppost_flags{.PTRBUFFER} +HTTPPOST_CALLBACK :: httppost_flags{.CALLBACK} +HTTPPOST_LARGE :: httppost_flags{.LARGE} + +httppost :: struct { + next: ^httppost, /* next entry in the list */ + name: cstring `fmt:"v,name"`, /* pointer to allocated name */ + namelength: c.long, /* length of name length */ + contents: cstring, /* pointer to allocated data contents */ + contentslength: c.long, /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + buffer: [^]byte, /* pointer to allocated buffer contents */ + bufferlength: c.long, /* length of buffer field */ + contenttype: cstring, /* Content-Type */ + contentheader: ^slist, /* list of extra headers for this form */ + more: ^httppost, /* if one field name has more than one + file, this link should link to following + files */ + flags: httppost_flags, /* as defined below */ + + + + showfilename: cstring, /* The filename to show. If not set, the + actual filename will be used (if this + is a file part) */ + userp: rawptr, /* custom pointer used for + HTTPPOST_CALLBACK posts */ + contentlen: off_t, /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +} + +/* + This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function +*/ +PROGRESSFUNC_CONTINUE :: 0x10000001 + +/* + This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 +*/ +progress_callback :: #type proc "c" (clientp: rawptr, + dltotal: f64, + dlnow: f64, + ultotal: f64, + ulnow: f64) -> c.int + +/* + This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. +*/ +xferinfo_callback :: #type proc "c" (clientp: rawptr, + dltotal: off_t, + dlnow: off_t, + ultotal: off_t, + ulnow: off_t) -> c.int + + +/* The maximum receive buffer size. */ +MAX_READ_SIZE :: 10*1024*1024 + +/* + Tests have proven that 20K is a bad buffer size for uploads on Windows, + while 16K for some odd reason performed a lot better. We do the ifndef + check to allow this value to easier be changed at build time for those + who feel adventurous. The practical minimum is about 400 bytes since + libcurl uses a buffer of this size as a scratch area (unrelated to + network send operations). +*/ +MAX_WRITE_SIZE :: 16384 + +/* + The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely +*/ +MAX_HTTP_HEADER :: 100*1024 + +/* + This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. +*/ +WRITEFUNC_PAUSE :: 0x10000001 + +/* + This is a magic return code for the write callback that, when returned, + will signal an error from the callback. +*/ +WRITEFUNC_ERROR :: 0xFFFFFFFF + +write_callback :: #type proc "c" (buffer: [^]byte, + size: c.size_t, + nitems: c.size_t, + outstream: rawptr) -> c.size_t + +/* This callback will be called when a new resolver request is made */ +resolver_start_callback :: #type proc "c" (resolver_state: rawptr, + reserved: rawptr, userdata: rawptr) -> c.int + + +/* enumeration of file types */ +filetype :: enum c.int { + FILE = 0, + DIRECTORY, + SYMLINK, + DEVICE_BLOCK, + DEVICE_CHAR, + NAMEDPIPE, + SOCKET, + DOOR, /* is possible only on Sun Solaris now */ + + UNKNOWN, /* should never occur */ +} + +finfoflags :: distinct bit_set[finfoflag; c.uint] +finfoflag :: enum c.uint { + KNOWN_FILENAME = 0, + KNOWN_FILETYPE = 1, + KNOWN_TIME = 2, + KNOWN_PERM = 3, + KNOWN_UID = 4, + KNOWN_GID = 5, + KNOWN_SIZE = 6, + KNOWN_HLINKCOUNT = 7, +} + +FINFOFLAG_KNOWN_FILENAME :: finfoflags{.KNOWN_FILENAME} +FINFOFLAG_KNOWN_FILETYPE :: finfoflags{.KNOWN_FILETYPE} +FINFOFLAG_KNOWN_TIME :: finfoflags{.KNOWN_TIME} +FINFOFLAG_KNOWN_PERM :: finfoflags{.KNOWN_PERM} +FINFOFLAG_KNOWN_UID :: finfoflags{.KNOWN_UID} +FINFOFLAG_KNOWN_GID :: finfoflags{.KNOWN_GID} +FINFOFLAG_KNOWN_SIZE :: finfoflags{.KNOWN_SIZE} +FINFOFLAG_KNOWN_HLINKCOUNT :: finfoflags{.KNOWN_HLINKCOUNT} + +/* Information about a single file, used when doing FTP wildcard matching */ +fileinfo :: struct { + filename: cstring, + filetype: filetype, + time: c.time_t, /* always zero! */ + perm: c.uint, + uid: c.int, + gid: c.int, + size: off_t, + hardlinks: c.long, + + strings: struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + time: cstring, + perm: cstring, + user: cstring, + group: cstring, + target: cstring, /* pointer to the target filename of a symlink */ + }, + + flags: finfoflags, + + /* These are libcurl private struct fields. Previously used by libcurl, so + they must never be interfered with. */ + b_data: [^]byte, + b_size: c.size_t, + b_used: c.size_t, +} + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +CHUNK_BGN_FUNC_OK :: 0 +CHUNK_BGN_FUNC_FAIL :: 1 /* tell the lib to end the task */ +CHUNK_BGN_FUNC_SKIP :: 2 /* skip this chunk over */ + +/* + if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used +*/ +chunk_bgn_callback :: #type proc "c" (transfer_info: rawptr, + ptr: rawptr, + remains: c.int) -> c.long + + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +CHUNK_END_FUNC_OK :: 0 +CHUNK_END_FUNC_FAIL :: 1 /* tell the lib to end the task */ + + + +/* + If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we do not need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. +*/ +chunk_end_callback :: #type proc "c" (ptr: rawptr) -> c.long + +/* return codes for FNMATCHFUNCTION */ +FNMATCHFUNC_MATCH :: 0 /* string corresponds to the pattern */ +FNMATCHFUNC_NOMATCH :: 1 /* pattern does not match the string */ +FNMATCHFUNC_FAIL :: 2 /* an error occurred */ + +/* + callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. +*/ +fnmatch_callback :: #type proc "c" (ptr: rawptr, + pattern: cstring, + string: cstring) -> c.int + +/* These are the return codes for the seek callbacks */ +SEEKFUNC_OK :: 0 +SEEKFUNC_FAIL :: 1 /* fail the entire transfer */ +SEEKFUNC_CANTSEEK :: 2 /* tell libcurl seeking cannot be done, so + libcurl might try other means instead */ + +seek_callback :: #type proc "c" (instream: rawptr, + offset: off_t, + origin: c.int) -> c.int /* 'whence' */ + +/* + This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. +*/ +READFUNC_ABORT :: 0x10000000 +/* + This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. +*/ +READFUNC_PAUSE :: 0x10000001 + +/* Return code for when the trailing headers' callback has terminated without any errors */ +TRAILERFUNC_OK :: 0 +/* + Return code for when was an error in the trailing header's list and we + want to abort the request +*/ +TRAILERFUNC_ABORT :: 1 + +read_callback :: #type proc "c" (buffer: [^]byte, + size: c.size_t, + nitems: c.size_t, + instream: rawptr) -> c.size_t + +trailer_callback :: #type proc "c" (list: ^^slist, + userdata: rawptr) -> c.int + +socktype :: enum c.int { + IPCXN, /* socket created for a specific IP connection */ + ACCEPT, /* socket created by accept() call */ + LAST, /* never use */ +} + +/* + The return code from the sockopt_callback can signal information back + to libcurl: +*/ +SOCKOPT_OK :: 0 +SOCKOPT_ERROR :: 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +SOCKOPT_ALREADY_CONNECTED :: 2 + +sockopt_callback :: #type proc "c" (clientp: rawptr, + curlfd: socket_t, + purpose: socktype) -> c.int + +sockaddr :: struct { + family: c.int, + socktype: c.int, + protocol: c.int, + addrlen: c.uint, /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + addr: platform_sockaddr, +} + + +opensocket_callback :: #type proc "c" (clientp: rawptr, + purpose: socktype, + address: ^sockaddr) -> socket_t + +closesocket_callback :: #type proc "c" (clientp: rawptr, item: socket_t) -> c.int + +ioerr :: enum c.int { + E_OK, /* I/O operation successful */ + E_UNKNOWNCMD, /* command was unknown to callback */ + E_FAILRESTART, /* failed to restart the read */ +} + +iocmd :: enum c.int { + NOP, /* no operation */ + RESTARTREAD, /* restart the read stream from start */ +} + +ioctl_callback :: #type proc "c" (handle: ^CURL, + cmd: c.int, + clientp: rawptr) -> ioerr + +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +malloc_callback :: #type proc "c" (size: c.size_t) -> rawptr +free_callback :: #type proc "c" (ptr: rawptr) +realloc_callback :: #type proc "c" (ptr: rawptr, size: c.size_t) -> rawptr +strdup_callback :: #type proc "c" (str: cstring) -> cstring +calloc_callback :: #type proc "c" (nmemb, size: c.size_t) -> rawptr + +/* the kind of data that is passed to information_callback */ +infotype :: enum c.int { + TEXT = 0, + HEADER_IN, /* 1 */ + HEADER_OUT, /* 2 */ + DATA_IN, /* 3 */ + DATA_OUT, /* 4 */ + SSL_DATA_IN, /* 5 */ + SSL_DATA_OUT, /* 6 */ + END, +} + +debug_callback :: #type proc "c"( + handle: ^CURL, /* the handle/transfer this concerns */ + type: infotype, /* what kind of data */ + data: [^]byte, /* points to the data */ + size: c.size_t, /* size of the data pointed to */ + userptr: rawptr, /* whatever the user please */ +) -> c.int + +/* This is the CURLOPT_PREREQFUNCTION callback prototype. */ +prereq_callback :: #type proc "c" (clientp: rawptr, + conn_primary_ip: cstring, + conn_local_ip: cstring, + conn_primary_port: c.int, + conn_local_port: c.int) -> c.int + +/* Return code for when the pre-request callback has terminated without any errors */ +PREREQFUNC_OK :: 0 +/* Return code for when the pre-request callback wants to abort the request */ +PREREQFUNC_ABORT :: 1 + +/* + All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ +code :: enum c.int { + E_OK = 0, + E_UNSUPPORTED_PROTOCOL, /* 1 */ + E_FAILED_INIT, /* 2 */ + E_URL_MALFORMAT, /* 3 */ + E_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + E_COULDNT_RESOLVE_PROXY, /* 5 */ + E_COULDNT_RESOLVE_HOST, /* 6 */ + E_COULDNT_CONNECT, /* 7 */ + E_WEIRD_SERVER_REPLY, /* 8 */ + E_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + E_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + E_FTP_WEIRD_PASS_REPLY, /* 11 */ + E_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + E_FTP_WEIRD_PASV_REPLY, /* 13 */ + E_FTP_WEIRD_227_FORMAT, /* 14 */ + E_FTP_CANT_GET_HOST, /* 15 */ + E_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + E_FTP_COULDNT_SET_TYPE, /* 17 */ + E_PARTIAL_FILE, /* 18 */ + E_FTP_COULDNT_RETR_FILE, /* 19 */ + E_OBSOLETE20, /* 20 - NOT USED */ + E_QUOTE_ERROR, /* 21 - quote command failure */ + E_HTTP_RETURNED_ERROR, /* 22 */ + E_WRITE_ERROR, /* 23 */ + E_OBSOLETE24, /* 24 - NOT USED */ + E_UPLOAD_FAILED, /* 25 - failed upload "command" */ + E_READ_ERROR, /* 26 - could not open/read from file */ + E_OUT_OF_MEMORY, /* 27 */ + E_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + E_OBSOLETE29, /* 29 - NOT USED */ + E_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + E_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + E_OBSOLETE32, /* 32 - NOT USED */ + E_RANGE_ERROR, /* 33 - RANGE "command" did not work */ + E_OBSOLETE34, /* 34 */ + E_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + E_BAD_DOWNLOAD_RESUME, /* 36 - could not resume download */ + E_FILE_COULDNT_READ_FILE, /* 37 */ + E_LDAP_CANNOT_BIND, /* 38 */ + E_LDAP_SEARCH_FAILED, /* 39 */ + E_OBSOLETE40, /* 40 - NOT USED */ + E_OBSOLETE41, /* 41 - NOT USED starting with 7.53.0 */ + E_ABORTED_BY_CALLBACK, /* 42 */ + E_BAD_FUNCTION_ARGUMENT, /* 43 */ + E_OBSOLETE44, /* 44 - NOT USED */ + E_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + E_OBSOLETE46, /* 46 - NOT USED */ + E_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + E_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + E_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */ + E_OBSOLETE50, /* 50 - NOT USED */ + E_OBSOLETE51, /* 51 - NOT USED */ + E_GOT_NOTHING, /* 52 - when this is a specific error */ + E_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + E_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + E_SEND_ERROR, /* 55 - failed sending network data */ + E_RECV_ERROR, /* 56 - failure in receiving network data */ + E_OBSOLETE57, /* 57 - NOT IN USE */ + E_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + E_SSL_CIPHER, /* 59 - could not use specified cipher */ + E_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + was not verified fine */ + E_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + E_OBSOLETE62, /* 62 - NOT IN USE since 7.82.0 */ + E_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + E_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + E_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + E_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + E_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + E_TFTP_NOTFOUND, /* 68 - file not found on server */ + E_TFTP_PERM, /* 69 - permission problem on server */ + E_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + E_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + E_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + E_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + E_TFTP_NOSUCHUSER, /* 74 - No such user */ + E_OBSOLETE75, /* 75 - NOT IN USE since 7.82.0 */ + E_OBSOLETE76, /* 76 - NOT IN USE since 7.82.0 */ + E_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + E_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + E_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + E_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + E_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it is ready and try again (Added + in 7.18.2) */ + E_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + E_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + E_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + E_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + E_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + E_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + E_CHUNK_FAILED, /* 88 - chunk callback reported error */ + E_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + E_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + E_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + E_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + E_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + E_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + E_HTTP3, /* 95 - An HTTP/3 layer problem */ + E_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + E_PROXY, /* 97 - proxy handshake error */ + E_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + E_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */ + E_TOO_LARGE, /* 100 - a value/data met its maximum */ + E_ECH_REQUIRED, /* 101 - ECH tried but failed */ +} + +/* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was + * return for the transfers. + */ +proxycode :: enum c.int { + OK, + BAD_ADDRESS_TYPE, + BAD_VERSION, + CLOSED, + GSSAPI, + GSSAPI_PERMSG, + GSSAPI_PROTECTION, + IDENTD, + IDENTD_DIFFER, + LONG_HOSTNAME, + LONG_PASSWD, + LONG_USER, + NO_AUTH, + RECV_ADDRESS, + RECV_AUTH, + RECV_CONNECT, + RECV_REQACK, + REPLY_ADDRESS_TYPE_NOT_SUPPORTED, + REPLY_COMMAND_NOT_SUPPORTED, + REPLY_CONNECTION_REFUSED, + REPLY_GENERAL_SERVER_FAILURE, + REPLY_HOST_UNREACHABLE, + REPLY_NETWORK_UNREACHABLE, + REPLY_NOT_ALLOWED, + REPLY_TTL_EXPIRED, + REPLY_UNASSIGNED, + REQUEST_FAILED, + RESOLVE_HOST, + SEND_AUTH, + SEND_CONNECT, + SEND_REQUEST, + UNKNOWN_FAIL, + UNKNOWN_MODE, + USER_REJECTED, +} + +/* This prototype applies to all conversion callbacks */ +conv_callback :: #type proc "c"(buffer: [^]byte, length: c.size_t) -> code + +ssl_ctx_callback :: #type proc "c" (curl: ^CURL, /* easy handle */ + ssl_ctx: rawptr, /* actually an OpenSSL + or wolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + userptr: rawptr) -> code + +proxytype :: enum c.int { + HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + HTTPS = 2, /* HTTPS but stick to HTTP/1 added in 7.52.0 */ + HTTPS2 = 3, /* HTTPS and attempt HTTP/2 added in 8.2.0 */ + SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + SOCKS5 = 5, /* added in 7.10 */ + SOCKS4A = 6, /* added in 7.18.0 */ + SOCKS5_HOSTNAME = 7, /* Use the SOCKS5 protocol but pass along the + hostname rather than the IP address. added + in 7.18.0 */ +} /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +AUTH_NONE :: (c.ulong)(0) +AUTH_BASIC :: ((c.ulong)(1))<<0 +AUTH_DIGEST :: ((c.ulong)(1))<<1 +AUTH_NEGOTIATE :: ((c.ulong)(1))<<2 +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +AUTH_GSSNEGOTIATE :: AUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +AUTH_GSSAPI :: AUTH_NEGOTIATE +AUTH_NTLM :: ((c.ulong)(1))<<3 +AUTH_DIGEST_IE :: ((c.ulong)(1))<<4 + +AUTH_BEARER :: ((c.ulong)(1))<<6 +AUTH_AWS_SIGV4 :: ((c.ulong)(1))<<7 +AUTH_ONLY :: ((c.ulong)(1))<<31 +AUTH_ANY :: ~AUTH_DIGEST_IE +AUTH_ANYSAFE :: ~(AUTH_BASIC|AUTH_DIGEST_IE) + +SSH_AUTH_ANY :: ~c.int(0) /* all types supported by the server */ +SSH_AUTH_NONE :: 0 /* none allowed, silly but complete */ +SSH_AUTH_PUBLICKEY :: (1<<0) /* public/private key files */ +SSH_AUTH_PASSWORD :: (1<<1) /* password */ +SSH_AUTH_HOST :: (1<<2) /* host key files */ +SSH_AUTH_KEYBOARD :: (1<<3) /* keyboard interactive */ +SSH_AUTH_AGENT :: (1<<4) /* agent (ssh-agent, pageant...) */ +SSH_AUTH_GSSAPI :: (1<<5) /* gssapi (kerberos, ...) */ +SSH_AUTH_DEFAULT :: SSH_AUTH_ANY + +GSSAPI_DELEGATION_NONE :: 0 /* no delegation (default) */ +GSSAPI_DELEGATION_POLICY_FLAG :: (1<<0) /* if permitted by policy */ +GSSAPI_DELEGATION_FLAG :: (1<<1) /* delegate always */ + +ERROR_SIZE :: 256 + +khtype :: enum c.int { + UNKNOWN, + RSA1, + RSA, + DSS, + ECDSA, + ED25519, +} + +khkey :: struct { + key: cstring, /* points to a null-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + len: c.size_t, + keytype: khtype, +} + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +khstat :: enum c.int { + FINE_ADD_TO_FILE, + FINE, + REJECT, /* reject the connection, return an error */ + DEFER, /* do not accept it, but we cannot answer right now. + Causes a CURLE_PEER_FAILED_VERIFICATION error but the + connection will be left intact etc */ + FINE_REPLACE, /* accept and replace the wrong key */ +} + +/* this is the set of status codes pass in to the callback */ +khmatch :: enum c.int { + OK, /* match */ + MISMATCH, /* host found, key mismatch! */ + MISSING, /* no matching host/key found */ +} + +sshkeycallback :: #type proc "c" (easy: ^CURL, /* easy handle */ + knownkey: ^khkey, /* known */ + foundkey: ^khkey, /* found */ + _: khmatch, /* libcurl's view on the keys */ + clientp: rawptr) -> c.int /* custom pointer passed with */ + /* CURLOPT_SSH_KEYDATA */ + +sshhostkeycallback :: #type proc "c" (clientp: rawptr, /* custom pointer passed */ + /* with CURLOPT_SSH_HOSTKEYDATA */ + keytype: c.int, /* CURLKHTYPE */ + key: cstring, /* hostkey to check */ + keylen: c.size_t, /* length of the key */ + ) -> code /* return CURLE_OK to accept */ + /* or something else to refuse */ + + +/* parameter for the CURLOPT_USE_SSL option */ +USESSL_NONE :: 0 /* do not attempt to use SSL */ +USESSL_TRY :: 1 /* try using SSL, proceed anyway otherwise */ +USESSL_CONTROL :: 2 /* SSL for the control connection or fail */ +USESSL_ALL :: 3 /* SSL for all communication or fail */ + +usessl :: enum c.int { +} + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* + - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. +*/ +SSLOPT_ALLOW_BEAST :: 1<<0 + +/* + - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. +*/ +SSLOPT_NO_REVOKE :: 1<<1 + +/* + - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. +*/ +SSLOPT_NO_PARTIALCHAIN :: 1<<2 + +/* + - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline + checks and ignore missing revocation list for those SSL backends where such + behavior is present. +*/ +SSLOPT_REVOKE_BEST_EFFORT :: 1<<3 + +/* + - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of + operating system. Currently implemented under MS-Windows. +*/ +SSLOPT_NATIVE_CA :: 1<<4 + +/* + - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use + a client certificate for authentication. (Schannel) +*/ +SSLOPT_AUTO_CLIENT_CERT :: 1<<5 + +/* If possible, send data using TLS 1.3 early data */ +SSLOPT_EARLYDATA :: 1<<6 + +/* + The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. +*/ +HET_DEFAULT :: 200 + +/* The default connection upkeep interval in milliseconds. */ +UPKEEP_INTERVAL_DEFAULT :: 60000 + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +ftpccc :: enum c.int { + NONE, /* do not send CCC */ + PASSIVE, /* Let the server initiate the shutdown */ + ACTIVE, /* Initiate the shutdown */ +} + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +ftpauth :: enum c.int { + DEFAULT, /* let libcurl decide */ + SSL, /* use "AUTH SSL" */ + TLS, /* use "AUTH TLS" */ +} + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +ftpcreatedir :: enum c.int { + DIR_NONE, /* do NOT create missing dirs! */ + DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + _RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ +} + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +ftpmethod :: enum c.int { + DEFAULT, /* let libcurl pick */ + MULTICWD, /* single CWD operation for each path part */ + NOCWD, /* no CWD at all */ + SINGLECWD, /* one CWD to full dir, then work on file */ +} + +/* bitmask defines for CURLOPT_HEADEROPT */ +HEADER_UNIFIED :: 0 +HEADER_SEPARATE :: 1<<0 + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +ALTSVC_READONLYFILE :: 1<<2 +ALTSVC_H1 :: 1<<3 +ALTSVC_H2 :: 1<<4 +ALTSVC_H3 :: 1<<5 + +/* bitmask values for CURLOPT_UPLOAD_FLAGS */ +ULFLAG_ANSWERED :: 1<<0 +ULFLAG_DELETED :: 1<<1 +ULFLAG_DRAFT :: 1<<2 +ULFLAG_FLAGGED :: 1<<3 +ULFLAG_SEEN :: 1<<4 + +hstsentry :: struct { + name: cstring, + namelen: c.size_t, + using _: bit_field c.uint { + includeSubDomains: bool | 1, + }, + expire: [18]byte, /* YYYYMMDD HH:MM:SS [null-terminated] */ +} + +index :: struct { + index: c.size_t, /* the provided entry's "index" or count */ + total: c.size_t, /* total number of entries to save */ +} + +STScode :: enum c.int { + OK, + DONE, + FAIL, +} + +hstsread_callback :: #type proc "c" (easy: ^CURL, + e: ^hstsentry, + userp: rawptr) -> STScode +hstswrite_callback :: #type proc "c" (easy: ^CURL, + e: ^hstsentry, + i: ^index, + userp: rawptr) -> STScode + +/* CURLHSTS_* are bits for the CURLOPT_HSTS option */ +HSTS_ENABLE :: (c.long)(1<<0) +HSTS_READONLYFILE :: (c.long)(1<<1) + +/* The CURLPROTO_ defines below are for the **deprecated** CURLOPT_*PROTOCOLS options. Do not use. */ + +PROTO_HTTP :: (1<<0) +PROTO_HTTPS :: (1<<1) +PROTO_FTP :: (1<<2) +PROTO_FTPS :: (1<<3) +PROTO_SCP :: (1<<4) +PROTO_SFTP :: (1<<5) +PROTO_TELNET :: (1<<6) +PROTO_LDAP :: (1<<7) +PROTO_LDAPS :: (1<<8) +PROTO_DICT :: (1<<9) +PROTO_FILE :: (1<<10) +PROTO_TFTP :: (1<<11) +PROTO_IMAP :: (1<<12) +PROTO_IMAPS :: (1<<13) +PROTO_POP3 :: (1<<14) +PROTO_POP3S :: (1<<15) +PROTO_SMTP :: (1<<16) +PROTO_SMTPS :: (1<<17) +PROTO_RTSP :: (1<<18) +PROTO_RTMP :: (1<<19) +PROTO_RTMPT :: (1<<20) +PROTO_RTMPE :: (1<<21) +PROTO_RTMPTE :: (1<<22) +PROTO_RTMPS :: (1<<23) +PROTO_RTMPTS :: (1<<24) +PROTO_GOPHER :: (1<<25) +PROTO_SMB :: (1<<26) +PROTO_SMBS :: (1<<27) +PROTO_MQTT :: (1<<28) +PROTO_GOPHERS :: (1<<29) +PROTO_ALL :: (~c.int(0)) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else but 32 */ +OPTTYPE_LONG :: 0 +OPTTYPE_OBJECTPOINT :: 10000 +OPTTYPE_FUNCTIONPOINT :: 20000 +OPTTYPE_OFF_T :: 30000 +OPTTYPE_BLOB :: 40000 + +/* *OPTTYPE_STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the string options from the header file */ + + +/* CURLOPT aliases that make no runtime difference */ + +/* 'char *' argument to a string with a trailing zero */ +OPTTYPE_STRINGPOINT :: OPTTYPE_OBJECTPOINT + +/* 'struct curl_slist *' argument */ +OPTTYPE_SLISTPOINT :: OPTTYPE_OBJECTPOINT + +/* 'void *' argument passed untouched to callback */ +OPTTYPE_CBPOINT :: OPTTYPE_OBJECTPOINT + +/* 'long' argument with a set of values/bitmask */ +OPTTYPE_VALUES :: OPTTYPE_LONG + +/* + * All CURLOPT_* values. + */ +option :: enum c.int { + /* This is the FILE * or void * the regular output should be written to. */ + WRITEDATA = OPTTYPE_CBPOINT + 1, + + /* The full URL to get/put */ + URL = OPTTYPE_STRINGPOINT + 2, + + /* Port number to connect to, if other than default. */ + PORT = OPTTYPE_LONG + 3, + + /* Name of proxy to use. */ + PROXY = OPTTYPE_STRINGPOINT + 4, + + /* "user:password;options" to use when fetching. */ + USERPWD = OPTTYPE_STRINGPOINT + 5, + + /* "user:password" to use with proxy. */ + PROXYUSERPWD = OPTTYPE_STRINGPOINT + 6, + + /* Range to get, specified as an ASCII string. */ + RANGE = OPTTYPE_STRINGPOINT + 7, + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + READDATA = OPTTYPE_CBPOINT + 9, + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + ERRORBUFFER = OPTTYPE_OBJECTPOINT + 10, + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + WRITEFUNCTION = OPTTYPE_FUNCTIONPOINT + 11, + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + READFUNCTION = OPTTYPE_FUNCTIONPOINT + 12, + + /* Time-out the read operation after this amount of seconds */ + TIMEOUT = OPTTYPE_LONG + 13, + + /* If CURLOPT_READDATA is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + INFILESIZE = OPTTYPE_LONG + 14, + + /* POST static input fields. */ + POSTFIELDS = OPTTYPE_OBJECTPOINT + 15, + + /* Set the referrer page (needed by some CGIs) */ + REFERER = OPTTYPE_STRINGPOINT + 16, + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + FTPPORT = OPTTYPE_STRINGPOINT + 17, + + /* Set the User-Agent string (examined by some CGIs) */ + USERAGENT = OPTTYPE_STRINGPOINT + 18, + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + LOW_SPEED_LIMIT = OPTTYPE_LONG + 19, + + /* Set the "low speed time" */ + LOW_SPEED_TIME = OPTTYPE_LONG + 20, + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + RESUME_FROM = OPTTYPE_LONG + 21, + + /* Set cookie in request: */ + COOKIE = OPTTYPE_STRINGPOINT + 22, + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + HTTPHEADER = OPTTYPE_SLISTPOINT + 23, + + /* name of the file keeping your private SSL-certificate */ + SSLCERT = OPTTYPE_STRINGPOINT + 25, + + /* password for the SSL or SSH private key */ + KEYPASSWD = OPTTYPE_STRINGPOINT + 26, + + /* send TYPE parameter? */ + CRLF = OPTTYPE_LONG + 27, + + /* send linked-list of QUOTE commands */ + QUOTE = OPTTYPE_SLISTPOINT + 28, + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + HEADERDATA = OPTTYPE_CBPOINT + 29, + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + COOKIEFILE = OPTTYPE_STRINGPOINT + 31, + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + SSLVERSION = OPTTYPE_VALUES + 32, + + /* What kind of HTTP time condition to use, see defines */ + TIMECONDITION = OPTTYPE_VALUES + 33, + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + TIMEVALUE = OPTTYPE_LONG + 34, + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CUSTOMREQUEST = OPTTYPE_STRINGPOINT + 36, + + /* FILE handle to use instead of stderr */ + STDERR = OPTTYPE_OBJECTPOINT + 37, + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + POSTQUOTE = OPTTYPE_SLISTPOINT + 39, + + /* 40 is not used */ + + /* talk a lot */ + VERBOSE = OPTTYPE_LONG + 41, + + /* throw the header out too */ + HEADER = OPTTYPE_LONG + 42, + + /* shut off the progress meter */ + NOPROGRESS = OPTTYPE_LONG + 43, + + /* use HEAD to get http document */ + NOBODY = OPTTYPE_LONG + 44, + + /* no output on http error codes >= 400 */ + FAILONERROR = OPTTYPE_LONG + 45, + + /* this is an upload */ + UPLOAD = OPTTYPE_LONG + 46, + + /* HTTP POST method */ + POST = OPTTYPE_LONG + 47, + + /* bare names when listing directories */ + DIRLISTONLY = OPTTYPE_LONG + 48, + + /* Append instead of overwrite on upload! */ + APPEND = OPTTYPE_LONG + 50, + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + NETRC = OPTTYPE_VALUES + 51, + + /* use Location: Luke! */ + FOLLOWLOCATION = OPTTYPE_LONG + 52, + + /* transfer data in text/ASCII format */ + TRANSFERTEXT = OPTTYPE_LONG + 53, + + /* 55 = OBSOLETE */ + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + XFERINFODATA = OPTTYPE_CBPOINT + 57, + PROGRESSDATA = XFERINFODATA, + + /* We want the referrer field set automatically when following locations */ + AUTOREFERER = OPTTYPE_LONG + 58, + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + PROXYPORT = OPTTYPE_LONG + 59, + + /* size of the POST input data, if strlen() is not good to use */ + POSTFIELDSIZE = OPTTYPE_LONG + 60, + + /* tunnel non-http operations through an HTTP proxy */ + HTTPPROXYTUNNEL = OPTTYPE_LONG + 61, + + /* Set the interface string to use as outgoing network interface */ + INTERFACE = OPTTYPE_STRINGPOINT + 62, + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but does not match one of these, 'private' will be used. */ + KRBLEVEL = OPTTYPE_STRINGPOINT + 63, + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + SSL_VERIFYPEER = OPTTYPE_LONG + 64, + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CAINFO = OPTTYPE_STRINGPOINT + 65, + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + MAXREDIRS = OPTTYPE_LONG + 68, + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + FILETIME = OPTTYPE_LONG + 69, + + /* This points to a linked list of telnet options */ + TELNETOPTIONS = OPTTYPE_SLISTPOINT + 70, + + /* Max amount of cached alive connections */ + MAXCONNECTS = OPTTYPE_LONG + 71, + + /* 72 = OBSOLETE */ + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you are absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + FRESH_CONNECT = OPTTYPE_LONG + 74, + + /* Set to explicitly forbid the upcoming transfer's connection to be reused + when done. Do not use this unless you are absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + FORBID_REUSE = OPTTYPE_LONG + 75, + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CONNECTTIMEOUT = OPTTYPE_LONG + 78, + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + HEADERFUNCTION = OPTTYPE_FUNCTIONPOINT + 79, + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + HTTPGET = OPTTYPE_LONG + 80, + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + SSL_VERIFYHOST = OPTTYPE_LONG + 81, + + /* Specify which filename to write all known cookies in after completed + operation. Set filename to "-" (dash) to make it go to stdout. */ + COOKIEJAR = OPTTYPE_STRINGPOINT + 82, + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use */ + SSL_CIPHER_LIST = OPTTYPE_STRINGPOINT + 83, + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + HTTP_VERSION = OPTTYPE_VALUES + 84, + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + FTP_USE_EPSV = OPTTYPE_LONG + 85, + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + SSLCERTTYPE = OPTTYPE_STRINGPOINT + 86, + + /* name of the file keeping your private SSL-key */ + SSLKEY = OPTTYPE_STRINGPOINT + 87, + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + SSLKEYTYPE = OPTTYPE_STRINGPOINT + 88, + + /* crypto engine for the SSL-sub system */ + SSLENGINE = OPTTYPE_STRINGPOINT + 89, + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + SSLENGINE_DEFAULT = OPTTYPE_LONG + 90, + + /* DNS cache timeout */ + DNS_CACHE_TIMEOUT = OPTTYPE_LONG + 92, + + /* send linked-list of pre-transfer QUOTE commands */ + PREQUOTE = OPTTYPE_SLISTPOINT + 93, + + /* set the debug function */ + DEBUGFUNCTION = OPTTYPE_FUNCTIONPOINT + 94, + + /* set the data for the debug function */ + DEBUGDATA = OPTTYPE_CBPOINT + 95, + + /* mark this as start of a cookie session */ + COOKIESESSION = OPTTYPE_LONG + 96, + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CAPATH = OPTTYPE_STRINGPOINT + 97, + + /* Instruct libcurl to use a smaller receive buffer */ + BUFFERSIZE = OPTTYPE_LONG + 98, + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + NOSIGNAL = OPTTYPE_LONG + 99, + + /* Provide a CURLShare for mutexing non-ts data */ + SHARE = OPTTYPE_OBJECTPOINT + 100, + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + PROXYTYPE = OPTTYPE_VALUES + 101, + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + ACCEPT_ENCODING = OPTTYPE_STRINGPOINT + 102, + + /* Set pointer to private data */ + PRIVATE = OPTTYPE_OBJECTPOINT + 103, + + /* Set aliases for HTTP 200 in the HTTP Response header */ + HTTP200ALIASES = OPTTYPE_SLISTPOINT + 104, + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + UNRESTRICTED_AUTH = OPTTYPE_LONG + 105, + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + FTP_USE_EPRT = OPTTYPE_LONG + 106, + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + HTTPAUTH = OPTTYPE_VALUES + 107, + + /* Set the ssl context callback function, currently only for OpenSSL or + wolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + SSL_CTX_FUNCTION = OPTTYPE_FUNCTIONPOINT + 108, + + /* Set the userdata for the ssl context callback function's third + argument */ + SSL_CTX_DATA = OPTTYPE_CBPOINT + 109, + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + FTP_CREATE_MISSING_DIRS = OPTTYPE_LONG + 110, + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + PROXYAUTH = OPTTYPE_VALUES + 111, + + /* Option that changes the timeout, in seconds, associated with getting a + response. This is different from transfer timeout time and essentially + places a demand on the server to acknowledge commands in a timely + manner. For FTP, SMTP, IMAP and POP3. */ + SERVER_RESPONSE_TIMEOUT = OPTTYPE_LONG + 112, + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to use those IP versions only. This only has effect on + systems with support for more than one, i.e IPv4 _and_ IPv6. */ + IPRESOLVE = OPTTYPE_VALUES + 113, + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + MAXFILESIZE = OPTTYPE_LONG + 114, + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + INFILESIZE_LARGE = OPTTYPE_OFF_T + 115, + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + RESUME_FROM_LARGE = OPTTYPE_OFF_T + 116, + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + MAXFILESIZE_LARGE = OPTTYPE_OFF_T + 117, + + /* Set this option to the filename of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + NETRC_FILE = OPTTYPE_STRINGPOINT + 118, + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + USE_SSL = OPTTYPE_VALUES + 119, + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + POSTFIELDSIZE_LARGE = OPTTYPE_OFF_T + 120, + + /* Enable/disable the TCP Nagle algorithm */ + TCP_NODELAY = OPTTYPE_LONG + 121, + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + FTPSSLAUTH = OPTTYPE_VALUES + 129, + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* null-terminated string for pass on to the FTP server when asked for + "account" info */ + FTP_ACCOUNT = OPTTYPE_STRINGPOINT + 134, + + /* feed cookie into cookie engine */ + COOKIELIST = OPTTYPE_STRINGPOINT + 135, + + /* ignore Content-Length */ + IGNORE_CONTENT_LENGTH = OPTTYPE_LONG + 136, + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + FTP_SKIP_PASV_IP = OPTTYPE_LONG + 137, + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + FTP_FILEMETHOD = OPTTYPE_VALUES + 138, + + /* Local port number to bind the socket to */ + LOCALPORT = OPTTYPE_LONG + 139, + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + LOCALPORTRANGE = OPTTYPE_LONG + 140, + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CONNECT_ONLY = OPTTYPE_LONG + 141, + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + MAX_SEND_SPEED_LARGE = OPTTYPE_OFF_T + 145, + MAX_RECV_SPEED_LARGE = OPTTYPE_OFF_T + 146, + + /* Pointer to command string to send if USER/PASS fails. */ + FTP_ALTERNATIVE_TO_USER = OPTTYPE_STRINGPOINT + 147, + + /* callback function for setting socket options */ + SOCKOPTFUNCTION = OPTTYPE_FUNCTIONPOINT + 148, + SOCKOPTDATA = OPTTYPE_CBPOINT + 149, + + /* set to 0 to disable session ID reuse for this transfer, default is + enabled (== 1) */ + SSL_SESSIONID_CACHE = OPTTYPE_LONG + 150, + + /* allowed SSH authentication methods */ + SSH_AUTH_TYPES = OPTTYPE_VALUES + 151, + + /* Used by scp/sftp to do public/private key authentication */ + SSH_PUBLIC_KEYFILE = OPTTYPE_STRINGPOINT + 152, + SSH_PRIVATE_KEYFILE = OPTTYPE_STRINGPOINT + 153, + + /* Send CCC (Clear Command Channel) after authentication */ + FTP_SSL_CCC = OPTTYPE_LONG + 154, + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + TIMEOUT_MS = OPTTYPE_LONG + 155, + CONNECTTIMEOUT_MS = OPTTYPE_LONG + 156, + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + HTTP_TRANSFER_DECODING = OPTTYPE_LONG + 157, + HTTP_CONTENT_DECODING = OPTTYPE_LONG + 158, + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + NEW_FILE_PERMS = OPTTYPE_LONG + 159, + NEW_DIRECTORY_PERMS = OPTTYPE_LONG + 160, + + /* Set the behavior of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + POSTREDIR = OPTTYPE_VALUES + 161, + + /* used by scp/sftp to verify the host's public key */ + SSH_HOST_PUBLIC_KEY_MD5 = OPTTYPE_STRINGPOINT + 162, + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + OPENSOCKETFUNCTION = OPTTYPE_FUNCTIONPOINT + 163, + OPENSOCKETDATA = OPTTYPE_CBPOINT + 164, + + /* POST volatile input fields. */ + COPYPOSTFIELDS = OPTTYPE_OBJECTPOINT + 165, + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + PROXY_TRANSFER_MODE = OPTTYPE_LONG + 166, + + /* Callback function for seeking in the input stream */ + SEEKFUNCTION = OPTTYPE_FUNCTIONPOINT + 167, + SEEKDATA = OPTTYPE_CBPOINT + 168, + + /* CRL file */ + CRLFILE = OPTTYPE_STRINGPOINT + 169, + + /* Issuer certificate */ + ISSUERCERT = OPTTYPE_STRINGPOINT + 170, + + /* (IPv6) Address scope */ + ADDRESS_SCOPE = OPTTYPE_LONG + 171, + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CERTINFO = OPTTYPE_LONG + 172, + + /* "name" and "pwd" to use when fetching. */ + USERNAME = OPTTYPE_STRINGPOINT + 173, + PASSWORD = OPTTYPE_STRINGPOINT + 174, + + /* "name" and "pwd" to use with Proxy when fetching. */ + PROXYUSERNAME = OPTTYPE_STRINGPOINT + 175, + PROXYPASSWORD = OPTTYPE_STRINGPOINT + 176, + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + NOPROXY = OPTTYPE_STRINGPOINT + 177, + + /* block size for TFTP transfers */ + TFTP_BLKSIZE = OPTTYPE_LONG + 178, + + /* Socks Service */ + SOCKS5_GSSAPI_NEC = OPTTYPE_LONG + 180, + + /* set the SSH knownhost filename to use */ + SSH_KNOWNHOSTS = OPTTYPE_STRINGPOINT + 183, + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + SSH_KEYFUNCTION = OPTTYPE_FUNCTIONPOINT + 184, + + /* set the SSH host key callback custom pointer */ + SSH_KEYDATA = OPTTYPE_CBPOINT + 185, + + /* set the SMTP mail originator */ + MAIL_FROM = OPTTYPE_STRINGPOINT + 186, + + /* set the list of SMTP mail receiver(s) */ + MAIL_RCPT = OPTTYPE_SLISTPOINT + 187, + + /* FTP: send PRET before PASV */ + FTP_USE_PRET = OPTTYPE_LONG + 188, + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + RTSP_REQUEST = OPTTYPE_VALUES + 189, + + /* The RTSP session identifier */ + RTSP_SESSION_ID = OPTTYPE_STRINGPOINT + 190, + + /* The RTSP stream URI */ + RTSP_STREAM_URI = OPTTYPE_STRINGPOINT + 191, + + /* The Transport: header to use in RTSP requests */ + RTSP_TRANSPORT = OPTTYPE_STRINGPOINT + 192, + + /* Manually initialize the client RTSP CSeq for this handle */ + RTSP_CLIENT_CSEQ = OPTTYPE_LONG + 193, + + /* Manually initialize the server RTSP CSeq for this handle */ + RTSP_SERVER_CSEQ = OPTTYPE_LONG + 194, + + /* The stream to pass to INTERLEAVEFUNCTION. */ + INTERLEAVEDATA = OPTTYPE_CBPOINT + 195, + + /* Let the application define a custom write method for RTP data */ + INTERLEAVEFUNCTION = OPTTYPE_FUNCTIONPOINT + 196, + + /* Turn on wildcard matching */ + WILDCARDMATCH = OPTTYPE_LONG + 197, + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CHUNK_BGN_FUNCTION = OPTTYPE_FUNCTIONPOINT + 198, + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CHUNK_END_FUNCTION = OPTTYPE_FUNCTIONPOINT + 199, + + /* Change match (fnmatch-like) callback for wildcard matching */ + FNMATCH_FUNCTION = OPTTYPE_FUNCTIONPOINT + 200, + + /* Let the application define custom chunk data pointer */ + CHUNK_DATA = OPTTYPE_CBPOINT + 201, + + /* FNMATCH_FUNCTION user pointer */ + FNMATCH_DATA = OPTTYPE_CBPOINT + 202, + + /* send linked-list of name:port:address sets */ + RESOLVE = OPTTYPE_SLISTPOINT + 203, + + /* Set a username for authenticated TLS */ + TLSAUTH_USERNAME = OPTTYPE_STRINGPOINT + 204, + + /* Set a password for authenticated TLS */ + TLSAUTH_PASSWORD = OPTTYPE_STRINGPOINT + 205, + + /* Set authentication type for authenticated TLS */ + TLSAUTH_TYPE = OPTTYPE_STRINGPOINT + 206, + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + is not any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + TRANSFER_ENCODING = OPTTYPE_LONG + 207, + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CLOSESOCKETFUNCTION = OPTTYPE_FUNCTIONPOINT + 208, + CLOSESOCKETDATA = OPTTYPE_CBPOINT + 209, + + /* allow GSSAPI credential delegation */ + GSSAPI_DELEGATION = OPTTYPE_VALUES + 210, + + /* Set the name servers to use for DNS resolution. + * Only supported by the c-ares DNS backend */ + DNS_SERVERS = OPTTYPE_STRINGPOINT + 211, + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + ACCEPTTIMEOUT_MS = OPTTYPE_LONG + 212, + + /* Set TCP keepalive */ + TCP_KEEPALIVE = OPTTYPE_LONG + 213, + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + TCP_KEEPIDLE = OPTTYPE_LONG + 214, + TCP_KEEPINTVL = OPTTYPE_LONG + 215, + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + SSL_OPTIONS = OPTTYPE_VALUES + 216, + + /* Set the SMTP auth originator */ + MAIL_AUTH = OPTTYPE_STRINGPOINT + 217, + + /* Enable/disable SASL initial response */ + SASL_IR = OPTTYPE_LONG + 218, + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + XFERINFOFUNCTION = OPTTYPE_FUNCTIONPOINT + 219, + + /* The XOAUTH2 bearer token */ + XOAUTH2_BEARER = OPTTYPE_STRINGPOINT + 220, + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + DNS_INTERFACE = OPTTYPE_STRINGPOINT + 221, + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + DNS_LOCAL_IP4 = OPTTYPE_STRINGPOINT + 222, + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + DNS_LOCAL_IP6 = OPTTYPE_STRINGPOINT + 223, + + /* Set authentication options directly */ + LOGIN_OPTIONS = OPTTYPE_STRINGPOINT + 224, + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + SSL_ENABLE_ALPN = OPTTYPE_LONG + 226, + + /* Time to wait for a response to an HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + EXPECT_100_TIMEOUT_MS = OPTTYPE_LONG + 227, + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + PROXYHEADER = OPTTYPE_SLISTPOINT + 228, + + /* Pass in a bitmask of "header options" */ + HEADEROPT = OPTTYPE_VALUES + 229, + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + PINNEDPUBLICKEY = OPTTYPE_STRINGPOINT + 230, + + /* Path to Unix domain socket */ + UNIX_SOCKET_PATH = OPTTYPE_STRINGPOINT + 231, + + /* Set if we should verify the certificate status. */ + SSL_VERIFYSTATUS = OPTTYPE_LONG + 232, + + /* Do not squash dot-dot sequences */ + PATH_AS_IS = OPTTYPE_LONG + 234, + + /* Proxy Service Name */ + PROXY_SERVICE_NAME = OPTTYPE_STRINGPOINT + 235, + + /* Service Name */ + SERVICE_NAME = OPTTYPE_STRINGPOINT + 236, + + /* Wait/do not wait for pipe/mutex to clarify */ + PIPEWAIT = OPTTYPE_LONG + 237, + + /* Set the protocol used when curl is given a URL without a protocol */ + DEFAULT_PROTOCOL = OPTTYPE_STRINGPOINT + 238, + + /* Set stream weight, 1 - 256 (default is 16) */ + STREAM_WEIGHT = OPTTYPE_LONG + 239, + + /* Set stream dependency on another curl handle */ + STREAM_DEPENDS = OPTTYPE_OBJECTPOINT + 240, + + /* Set E-xclusive stream dependency on another curl handle */ + STREAM_DEPENDS_E = OPTTYPE_OBJECTPOINT + 241, + + /* Do not send any tftp option requests to the server */ + TFTP_NO_OPTIONS = OPTTYPE_LONG + 242, + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CONNECT_TO = OPTTYPE_SLISTPOINT + 243, + + /* Set TCP Fast Open */ + TCP_FASTOPEN = OPTTYPE_LONG + 244, + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + KEEP_SENDING_ON_ERROR = OPTTYPE_LONG + 245, + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + PROXY_CAINFO = OPTTYPE_STRINGPOINT + 246, + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + PROXY_CAPATH = OPTTYPE_STRINGPOINT + 247, + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + PROXY_SSL_VERIFYPEER = OPTTYPE_LONG + 248, + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + PROXY_SSL_VERIFYHOST = OPTTYPE_LONG + 249, + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + PROXY_SSLVERSION = OPTTYPE_VALUES + 250, + + /* Set a username for authenticated TLS for proxy */ + PROXY_TLSAUTH_USERNAME = OPTTYPE_STRINGPOINT + 251, + + /* Set a password for authenticated TLS for proxy */ + PROXY_TLSAUTH_PASSWORD = OPTTYPE_STRINGPOINT + 252, + + /* Set authentication type for authenticated TLS for proxy */ + PROXY_TLSAUTH_TYPE = OPTTYPE_STRINGPOINT + 253, + + /* name of the file keeping your private SSL-certificate for proxy */ + PROXY_SSLCERT = OPTTYPE_STRINGPOINT + 254, + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + PROXY_SSLCERTTYPE = OPTTYPE_STRINGPOINT + 255, + + /* name of the file keeping your private SSL-key for proxy */ + PROXY_SSLKEY = OPTTYPE_STRINGPOINT + 256, + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + PROXY_SSLKEYTYPE = OPTTYPE_STRINGPOINT + 257, + + /* password for the SSL private key for proxy */ + PROXY_KEYPASSWD = OPTTYPE_STRINGPOINT + 258, + + /* Specify which TLS 1.2 (1.1, 1.0) ciphers to use for proxy */ + PROXY_SSL_CIPHER_LIST = OPTTYPE_STRINGPOINT + 259, + + /* CRL file for proxy */ + PROXY_CRLFILE = OPTTYPE_STRINGPOINT + 260, + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + PROXY_SSL_OPTIONS = OPTTYPE_LONG + 261, + + /* Name of pre proxy to use. */ + PRE_PROXY = OPTTYPE_STRINGPOINT + 262, + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + PROXY_PINNEDPUBLICKEY = OPTTYPE_STRINGPOINT + 263, + + /* Path to an abstract Unix domain socket */ + ABSTRACT_UNIX_SOCKET = OPTTYPE_STRINGPOINT + 264, + + /* Suppress proxy CONNECT response headers from user callbacks */ + SUPPRESS_CONNECT_HEADERS = OPTTYPE_LONG + 265, + + /* The request target, instead of extracted from the URL */ + REQUEST_TARGET = OPTTYPE_STRINGPOINT + 266, + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + SOCKS5_AUTH = OPTTYPE_LONG + 267, + + /* Enable/disable SSH compression */ + SSH_COMPRESSION = OPTTYPE_LONG + 268, + + /* Post MIME data. */ + MIMEPOST = OPTTYPE_OBJECTPOINT + 269, + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + TIMEVALUE_LARGE = OPTTYPE_OFF_T + 270, + + /* Head start in milliseconds to give happy eyeballs. */ + HAPPY_EYEBALLS_TIMEOUT_MS = OPTTYPE_LONG + 271, + + /* Function that will be called before a resolver request is made */ + RESOLVER_START_FUNCTION = OPTTYPE_FUNCTIONPOINT + 272, + + /* User data to pass to the resolver start callback. */ + RESOLVER_START_DATA = OPTTYPE_CBPOINT + 273, + + /* send HAProxy PROXY protocol header? */ + HAPROXYPROTOCOL = OPTTYPE_LONG + 274, + + /* shuffle addresses before use when DNS returns multiple */ + DNS_SHUFFLE_ADDRESSES = OPTTYPE_LONG + 275, + + /* Specify which TLS 1.3 ciphers suites to use */ + TLS13_CIPHERS = OPTTYPE_STRINGPOINT + 276, + PROXY_TLS13_CIPHERS = OPTTYPE_STRINGPOINT + 277, + + /* Disallow specifying username/login in URL. */ + DISALLOW_USERNAME_IN_URL = OPTTYPE_LONG + 278, + + /* DNS-over-HTTPS URL */ + DOH_URL = OPTTYPE_STRINGPOINT + 279, + + /* Preferred buffer size to use for uploads */ + UPLOAD_BUFFERSIZE = OPTTYPE_LONG + 280, + + /* Time in ms between connection upkeep calls for long-lived connections. */ + UPKEEP_INTERVAL_MS = OPTTYPE_LONG + 281, + + /* Specify URL using CURL URL API. */ + CURLU = OPTTYPE_OBJECTPOINT + 282, + + /* add trailing data just after no more data is available */ + TRAILERFUNCTION = OPTTYPE_FUNCTIONPOINT + 283, + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + TRAILERDATA = OPTTYPE_CBPOINT + 284, + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + HTTP09_ALLOWED = OPTTYPE_LONG + 285, + + /* alt-svc control bitmask */ + ALTSVC_CTRL = OPTTYPE_LONG + 286, + + /* alt-svc cache filename to possibly read from/write to */ + ALTSVC = OPTTYPE_STRINGPOINT + 287, + + /* maximum age (idle time) of a connection to consider it for reuse + * (in seconds) */ + MAXAGE_CONN = OPTTYPE_LONG + 288, + + /* SASL authorization identity */ + SASL_AUTHZID = OPTTYPE_STRINGPOINT + 289, + + /* allow RCPT TO command to fail for some recipients */ + MAIL_RCPT_ALLOWFAILS = OPTTYPE_LONG + 290, + + /* the private SSL-certificate as a "blob" */ + SSLCERT_BLOB = OPTTYPE_BLOB + 291, + SSLKEY_BLOB = OPTTYPE_BLOB + 292, + PROXY_SSLCERT_BLOB = OPTTYPE_BLOB + 293, + PROXY_SSLKEY_BLOB = OPTTYPE_BLOB + 294, + ISSUERCERT_BLOB = OPTTYPE_BLOB + 295, + + /* Issuer certificate for proxy */ + PROXY_ISSUERCERT = OPTTYPE_STRINGPOINT + 296, + PROXY_ISSUERCERT_BLOB = OPTTYPE_BLOB + 297, + + /* the EC curves requested by the TLS client (RFC 8422, 5.1); + * OpenSSL support via 'set_groups'/'set_curves': + * https://docs.openssl.org/master/man3/SSL_CTX_set1_curves/ + */ + SSL_EC_CURVES = OPTTYPE_STRINGPOINT + 298, + + /* HSTS bitmask */ + HSTS_CTRL = OPTTYPE_LONG + 299, + /* HSTS filename */ + HSTS = OPTTYPE_STRINGPOINT + 300, + + /* HSTS read callback */ + HSTSREADFUNCTION = OPTTYPE_FUNCTIONPOINT + 301, + HSTSREADDATA = OPTTYPE_CBPOINT + 302, + + /* HSTS write callback */ + HSTSWRITEFUNCTION = OPTTYPE_FUNCTIONPOINT + 303, + HSTSWRITEDATA = OPTTYPE_CBPOINT + 304, + + /* Parameters for V4 signature */ + AWS_SIGV4 = OPTTYPE_STRINGPOINT + 305, + + /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */ + DOH_SSL_VERIFYPEER = OPTTYPE_LONG + 306, + + /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */ + DOH_SSL_VERIFYHOST = OPTTYPE_LONG + 307, + + /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */ + DOH_SSL_VERIFYSTATUS = OPTTYPE_LONG + 308, + + /* The CA certificates as "blob" used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CAINFO_BLOB = OPTTYPE_BLOB + 309, + + /* The CA certificates as "blob" used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + PROXY_CAINFO_BLOB = OPTTYPE_BLOB + 310, + + /* used by scp/sftp to verify the host's public key */ + SSH_HOST_PUBLIC_KEY_SHA256 = OPTTYPE_STRINGPOINT + 311, + + /* Function that will be called immediately before the initial request + is made on a connection (after any protocol negotiation step). */ + PREREQFUNCTION = OPTTYPE_FUNCTIONPOINT + 312, + + /* Data passed to the CURLOPT_PREREQFUNCTION callback */ + PREREQDATA = OPTTYPE_CBPOINT + 313, + + /* maximum age (since creation) of a connection to consider it for reuse + * (in seconds) */ + MAXLIFETIME_CONN = OPTTYPE_LONG + 314, + + /* Set MIME option flags. */ + MIME_OPTIONS = OPTTYPE_LONG + 315, + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + SSH_HOSTKEYFUNCTION = OPTTYPE_FUNCTIONPOINT + 316, + + /* set the SSH host key callback custom pointer */ + SSH_HOSTKEYDATA = OPTTYPE_CBPOINT + 317, + + /* specify which protocols that are allowed to be used for the transfer, + which thus helps the app which takes URLs from users or other external + inputs and want to restrict what protocol(s) to deal with. Defaults to + all built-in protocols. */ + PROTOCOLS_STR = OPTTYPE_STRINGPOINT + 318, + + /* specify which protocols that libcurl is allowed to follow directs to */ + REDIR_PROTOCOLS_STR = OPTTYPE_STRINGPOINT + 319, + + /* WebSockets options */ + WS_OPTIONS = OPTTYPE_LONG + 320, + + /* CA cache timeout */ + CA_CACHE_TIMEOUT = OPTTYPE_LONG + 321, + + /* Can leak things, gonna exit() soon */ + QUICK_EXIT = OPTTYPE_LONG + 322, + + /* set a specific client IP for HAProxy PROXY protocol header? */ + HAPROXY_CLIENT_IP = OPTTYPE_STRINGPOINT + 323, + + /* millisecond version */ + SERVER_RESPONSE_TIMEOUT_MS = OPTTYPE_LONG + 324, + + /* set ECH configuration */ + ECH = OPTTYPE_STRINGPOINT + 325, + + /* maximum number of keepalive probes (Linux, *BSD, macOS, etc.) */ + TCP_KEEPCNT = OPTTYPE_LONG + 326, + + UPLOAD_FLAGS = OPTTYPE_LONG + 327, + + /* set TLS supported signature algorithms */ + SSL_SIGNATURE_ALGORITHMS = OPTTYPE_STRINGPOINT + 328, +} + + + + /* + Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. + */ +IPRESOLVE_WHATEVER :: 0 /* default, uses addresses to all IP + versions that your system allows */ +IPRESOLVE_V4 :: 1 /* uses only IPv4 addresses/connections */ +IPRESOLVE_V6 :: 2 /* uses only IPv6 addresses/connections */ + +/* Convenient "aliases" */ +PT_RTSPHEADER :: option.HTTPHEADER + +/* These constants are for use with the CURLOPT_HTTP_VERSION option. */ +HTTP_VERSION_NONE :: 0 /* setting this means we do not care, and + that we would like the library to choose + the best possible for us! */ +HTTP_VERSION_1_0 :: 1 /* please use HTTP 1.0 in the request */ +HTTP_VERSION_1_1 :: 2 /* please use HTTP 1.1 in the request */ +HTTP_VERSION_2_0 :: 3 /* please use HTTP 2 in the request */ +HTTP_VERSION_2TLS :: 4 /* use version 2 for HTTPS, version 1.1 for + HTTP */ +HTTP_VERSION_2_PRIOR_KNOWLEDGE :: 5 /* please use HTTP 2 without + HTTP/1.1 Upgrade */ +HTTP_VERSION_3 :: 30 /* Use HTTP/3, fallback to HTTP/2 or + HTTP/1 if needed. For HTTPS only. For + HTTP, this option makes libcurl + return error. */ +HTTP_VERSION_3ONLY :: 31 /* Use HTTP/3 without fallback. For + HTTPS only. For HTTP, this makes + libcurl return error. */ +HTTP_VERSION_LAST :: 32 /* *ILLEGAL* http version */ + +/* + Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +HTTP_VERSION_2 :: HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ + +RTSPREQ_NONE :: 0 +RTSPREQ_OPTIONS :: 1 +RTSPREQ_DESCRIBE :: 2 +RTSPREQ_ANNOUNCE :: 3 +RTSPREQ_SETUP :: 4 +RTSPREQ_PLAY :: 5 +RTSPREQ_PAUSE :: 6 +RTSPREQ_TEARDOWN :: 7 +RTSPREQ_GET_PARAMETER :: 8 +RTSPREQ_SET_PARAMETER :: 9 +RTSPREQ_RECORD :: 10 +RTSPREQ_RECEIVE :: 11 +RTSPREQ_LAST :: 12 /* not used */ + + /* These enums are for use with the CURLOPT_NETRC option. */ +NETRC_IGNORED :: 0 /* The .netrc will never be read. + This is the default. */ +NETRC_OPTIONAL :: 1 /* A user:password in the URL will be preferred + to one in the .netrc. */ +NETRC_REQUIRED :: 2 /* A user:password in the URL will be ignored. + Unless one is set programmatically, the + .netrc will be queried. */ +NETRC_OPTION :: enum c.int { + /* we set a single member here, just to make sure we still provide the enum, + but the values to use are defined above with L suffixes */ + LAST = 3, +} + +SSLVERSION_DEFAULT :: 0 +SSLVERSION_TLSv1 :: 1 /* TLS 1.x */ +SSLVERSION_SSLv2 :: 2 +SSLVERSION_SSLv3 :: 3 +SSLVERSION_TLSv1_0 :: 4 +SSLVERSION_TLSv1_1 :: 5 +SSLVERSION_TLSv1_2 :: 6 +SSLVERSION_TLSv1_3 :: 7 + +SSLVERSION_LAST :: 8 /* never use, keep last */ + +SSLVERSION_MAX_NONE :: 0 +SSLVERSION_MAX_DEFAULT :: SSLVERSION_TLSv1 << 16 +SSLVERSION_MAX_TLSv1_0 :: SSLVERSION_TLSv1_0 << 16 +SSLVERSION_MAX_TLSv1_1 :: SSLVERSION_TLSv1_1 << 16 +SSLVERSION_MAX_TLSv1_2 :: SSLVERSION_TLSv1_2 << 16 +SSLVERSION_MAX_TLSv1_3 :: SSLVERSION_TLSv1_3 << 16 + + /* never use, keep last */ +SSLVERSION_MAX_LAST :: SSLVERSION_LAST << 16 + +TLSAUTH_NONE :: 0 +TLSAUTH_SRP :: 1 + +TLSAUTH :: enum c.int { + /* + we set a single member here, just to make sure we still provide the enum, + but the values to use are defined above with L suffixes + */ + LAST = 2, +} + +/* + symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL +*/ + +REDIR_GET_ALL :: 0 +REDIR_POST_301 :: 1 +REDIR_POST_302 :: 2 +REDIR_POST_303 :: 4 +REDIR_POST_ALL :: REDIR_POST_301|REDIR_POST_302|REDIR_POST_303 + +TIMECOND_NONE :: 0 +TIMECOND_IFMODSINCE :: 1 +TIMECOND_IFUNMODSINCE :: 2 +TIMECOND_LASTMOD :: 3 + +TimeCond :: enum c.int { + /* + we set a single member here, just to make sure we still provide + the enum typedef, but the values to use are defined above with L + suffixes + */ + LAST = 4, +} + +/* Special size_t value signaling a null-terminated string. */ +ZERO_TERMINATED :: ~c.size_t(0) + + +/* Mime/form handling support. */ +mime :: struct {} /* Mime context. */ +mimepart :: struct {} /* Mime part context. */ + + +/* CURLMIMEOPT_ defines are for the CURLOPT_MIME_OPTIONS option. */ +MIMEOPT_FORMESCAPE :: 1<<0 /* Use backslash-escaping for forms. */ + + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* curl_strequal() and curl_strnequal() are subject for removal in a future release */ + strequal :: proc(s1, s2: cstring) -> c.int --- + strnequal :: proc(s1, s2: cstring, n: c.size_t) -> c.int --- + + + /* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ + mime_init :: proc(easy: ^CURL) -> ^mime --- + + /* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ + mime_free :: proc(mime: ^mime) --- + + /* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ + mime_addpart :: proc(mime: ^mime) -> ^mimepart --- + + /* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ + mime_name :: proc(part: ^mimepart, name: cstring) -> code --- + + /* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote filename. + */ + mime_filename :: proc(part: ^mimepart, filename: cstring) -> code --- + + /* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ + mime_type :: proc(part: ^mimepart, mimetype: cstring) -> code --- + + /* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ + mime_encoder :: proc(part: ^mimepart, encoding: cstring) -> code --- + + /* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ + mime_data :: proc(part: ^mimepart, data: [^]byte, datasize: c.size_t) -> code --- + + /* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ + mime_filedata :: proc(part: ^mimepart, filename: rawptr) -> code --- + + /* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ + mime_data_cb :: proc(part: ^mimepart, datasize: off_t, + readfunc: read_callback, + seekfunc: seek_callback, + freefunc: free_callback, + arg: rawptr) -> code --- + + /* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ + mime_subparts :: proc(part: ^mimepart, subparts: ^mime) -> code --- + /* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ + mime_headers :: proc(part: ^mimepart, headers: ^slist, take_ownership: c.int) -> code --- +} + + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +formget_callback :: #type proc "c" (arg: rawptr, buf: [^]byte, len: c.size_t) -> c.size_t + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ + getenv :: proc(variable: cstring) -> cstring --- + + /* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ASCII string of the libcurl version. + */ + version :: proc() -> cstring --- + + /* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ + easy_escape :: proc(handle: ^CURL, string: cstring, length: c.int) -> cstring --- + + /* the previous version: */ + escape :: proc(string: cstring, length: c.int) -> cstring --- + + + /* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ + easy_unescape :: proc(handle: ^CURL, + string: cstring, + length: c.int, + outlength: ^c.int) -> cstring --- + + /* the previous version */ + unescape :: proc(string: cstring, length: c.int) -> cstring --- + + /* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ + free :: proc(p: rawptr) --- + + /* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ + global_init :: proc(flags: c.long) -> code --- + + /* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines will be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ + global_init_mem :: proc(flags: c.long, + m: malloc_callback, + f: free_callback, + r: realloc_callback, + s: strdup_callback, + c: calloc_callback) -> code --- + + /* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ + global_cleanup :: proc() --- + + /* + * NAME curl_global_trace() + * + * DESCRIPTION + * + * curl_global_trace() can be invoked at application start to + * configure which components in curl should participate in tracing. + + * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the + * curl_version_info_data.features flag (fetch by curl_version_info()). + + */ + global_trace :: proc(config: cstring) -> code --- +} + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). If + * both id and name are specified, the name will be ignored. If neither id nor + * name are specified, the function will fail with CURLSSLSET_UNKNOWN_BACKEND + * and set the "avail" pointer to the NULL-terminated list of available + * backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a + * NULL-terminated list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ +ssl_backend :: struct { + id: sslbackend, + name: cstring, +} + +sslset :: enum c.int { + OK = 0, + UNKNOWN_BACKEND, + TOO_LATE, + NO_BACKENDS, /* libcurl was built without any SSL support */ +} + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + global_sslset :: proc(id: sslbackend, name: cstring, avail: ^^^ssl_backend) -> sslset --- + + /* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ + slist_append :: proc(list: ^slist, data: cstring) -> ^slist --- + + /* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ + slist_free_all :: proc(list: ^slist) --- + + /* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ + getdate :: proc(p: cstring, unused: ^c.time_t) -> c.time_t --- +} + +/* + info about the certificate chain, for SSL backends that support it. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO +*/ +certinfo :: struct { + num_of_certs: c.int, /* number of certificates with information */ + certinfo: ^^slist, /* for each index in this array, there is a + linked list with textual information for a + certificate in the format "name:content". + eg "Subject:foo", "Issuer:bar", etc. */ +} + +/* + Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. +*/ +tlssessioninfo :: struct { + backend: sslbackend, + internals: rawptr, +} + + +INFO_STRING :: 0x100000 +INFO_LONG :: 0x200000 +INFO_DOUBLE :: 0x300000 +INFO_SLIST :: 0x400000 +INFO_PTR :: 0x400000 /* same as SLIST */ +INFO_SOCKET :: 0x500000 +INFO_OFF_T :: 0x600000 +INFO_MASK :: 0x0fffff +INFO_TYPEMASK :: 0xf00000 + +INFO :: enum c.int { + NONE, /* first, never use this */ + EFFECTIVE_URL = INFO_STRING + 1, + RESPONSE_CODE = INFO_LONG + 2, + TOTAL_TIME = INFO_DOUBLE + 3, + NAMELOOKUP_TIME = INFO_DOUBLE + 4, + CONNECT_TIME = INFO_DOUBLE + 5, + PRETRANSFER_TIME = INFO_DOUBLE + 6, + SIZE_UPLOAD_T = INFO_OFF_T + 7, + SIZE_DOWNLOAD_T = INFO_OFF_T + 8, + SPEED_DOWNLOAD_T = INFO_OFF_T + 9, + SPEED_UPLOAD_T = INFO_OFF_T + 10, + HEADER_SIZE = INFO_LONG + 11, + REQUEST_SIZE = INFO_LONG + 12, + SSL_VERIFYRESULT = INFO_LONG + 13, + FILETIME = INFO_LONG + 14, + FILETIME_T = INFO_OFF_T + 14, + CONTENT_LENGTH_DOWNLOAD_T = INFO_OFF_T + 15, + CONTENT_LENGTH_UPLOAD_T = INFO_OFF_T + 16, + STARTTRANSFER_TIME = INFO_DOUBLE + 17, + CONTENT_TYPE = INFO_STRING + 18, + REDIRECT_TIME = INFO_DOUBLE + 19, + REDIRECT_COUNT = INFO_LONG + 20, + PRIVATE = INFO_STRING + 21, + HTTP_CONNECTCODE = INFO_LONG + 22, + HTTPAUTH_AVAIL = INFO_LONG + 23, + PROXYAUTH_AVAIL = INFO_LONG + 24, + OS_ERRNO = INFO_LONG + 25, + NUM_CONNECTS = INFO_LONG + 26, + SSL_ENGINES = INFO_SLIST + 27, + COOKIELIST = INFO_SLIST + 28, + FTP_ENTRY_PATH = INFO_STRING + 30, + REDIRECT_URL = INFO_STRING + 31, + PRIMARY_IP = INFO_STRING + 32, + APPCONNECT_TIME = INFO_DOUBLE + 33, + CERTINFO = INFO_PTR + 34, + CONDITION_UNMET = INFO_LONG + 35, + RTSP_SESSION_ID = INFO_STRING + 36, + RTSP_CLIENT_CSEQ = INFO_LONG + 37, + RTSP_SERVER_CSEQ = INFO_LONG + 38, + RTSP_CSEQ_RECV = INFO_LONG + 39, + PRIMARY_PORT = INFO_LONG + 40, + LOCAL_IP = INFO_STRING + 41, + LOCAL_PORT = INFO_LONG + 42, + ACTIVESOCKET = INFO_SOCKET + 44, + TLS_SSL_PTR = INFO_PTR + 45, + HTTP_VERSION = INFO_LONG + 46, + PROXY_SSL_VERIFYRESULT = INFO_LONG + 47, + SCHEME = INFO_STRING + 49, + TOTAL_TIME_T = INFO_OFF_T + 50, + NAMELOOKUP_TIME_T = INFO_OFF_T + 51, + CONNECT_TIME_T = INFO_OFF_T + 52, + PRETRANSFER_TIME_T = INFO_OFF_T + 53, + STARTTRANSFER_TIME_T = INFO_OFF_T + 54, + REDIRECT_TIME_T = INFO_OFF_T + 55, + APPCONNECT_TIME_T = INFO_OFF_T + 56, + RETRY_AFTER = INFO_OFF_T + 57, + EFFECTIVE_METHOD = INFO_STRING + 58, + PROXY_ERROR = INFO_LONG + 59, + REFERER = INFO_STRING + 60, + CAINFO = INFO_STRING + 61, + CAPATH = INFO_STRING + 62, + XFER_ID = INFO_OFF_T + 63, + CONN_ID = INFO_OFF_T + 64, + QUEUE_TIME_T = INFO_OFF_T + 65, + USED_PROXY = INFO_LONG + 66, + POSTTRANSFER_TIME_T = INFO_OFF_T + 67, + EARLYDATA_SENT_T = INFO_OFF_T + 68, + HTTPAUTH_USED = INFO_LONG + 69, + PROXYAUTH_USED = INFO_LONG + 70, + + /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ + HTTP_CODE = RESPONSE_CODE, +} + + + +closepolicy :: enum c.int { + NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, +} + +GLOBAL_SSL :: 1<<0 /* no purpose since 7.57.0 */ +GLOBAL_WIN32 :: 1<<1 +GLOBAL_ALL :: (GLOBAL_SSL|GLOBAL_WIN32) +GLOBAL_NOTHING :: 0 +GLOBAL_DEFAULT :: GLOBAL_ALL +GLOBAL_ACK_EINTR :: 1<<2 + + + +/* Different data locks for a single share */ +lock_data :: enum c.int { + NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + SHARE, + COOKIE, + DNS, + SSL_SESSION, + CONNECT, + PSL, + HSTS, +} + +/* Different lock access types */ +lock_access :: enum c.int { + NONE = 0, /* unspecified action */ + SHARED = 1, /* for read perhaps */ + SINGLE = 2, /* for write perhaps */ +} + +lock_function :: #type proc "c" (handle: ^CURL, + data: lock_data, + locktype: lock_access, + userptr: rawptr) +unlock_function :: #type proc "c" (handle: ^CURL, + data: lock_data, + userptr: rawptr) + + +SHcode :: enum c.int { + OK, /* all is fine */ + BAD_OPTION, /* 1 */ + IN_USE, /* 2 */ + INVALID, /* 3 */ + NOMEM, /* 4 out of memory */ + NOT_BUILT_IN, /* 5 feature not present in lib */ +} + +SHoption :: enum c.int { + NONE, /* do not use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ +} + + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + share_init :: proc() -> ^CURLSH --- + share_setopt :: proc(share: ^CURLSH, option: SHoption, #c_vararg args: ..any) -> SHcode --- + share_cleanup :: proc(share: ^CURLSH) -> SHcode --- +} + + +version_enum :: enum c.int { + FIRST, /* 7.10 */ + SECOND, /* 7.11.1 */ + THIRD, /* 7.12.0 */ + FOURTH, /* 7.16.1 */ + FIFTH, /* 7.57.0 */ + SIXTH, /* 7.66.0 */ + SEVENTH, /* 7.70.0 */ + EIGHTH, /* 7.72.0 */ + NINTH, /* 7.75.0 */ + TENTH, /* 7.77.0 */ + ELEVENTH, /* 7.87.0 */ + TWELFTH, /* 8.8.0 */ +} + +/* + The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. +*/ +VERSION_NOW :: version_enum.TWELFTH + +version_info_data :: struct { + age: version_enum, /* age of the returned struct */ + version: cstring, /* LIBCURL_VERSION */ + version_num: c.uint, /* LIBCURL_VERSION_NUM */ + host: cstring, /* OS/host/cpu/machine when configured */ + features: c.int, /* bitmask, see defines below */ + ssl_version: cstring, /* human readable string */ + ssl_version_num: c.long, /* not used anymore, always 0 */ + libz_version: cstring, /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + protocols: [^]cstring, + + /* The fields below this were added in CURLVERSION_SECOND */ + ares: cstring, + ares_num: c.int, + + /* This field was added in CURLVERSION_THIRD */ + libidn: cstring, + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + iconv_ver_num: c.int, + + libssh_version: cstring, /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + brotli_ver_num: c.uint, /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + brotli_version: cstring, /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + nghttp2_ver_num: c.uint, /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + nghttp2_version: cstring, /* human readable string. */ + quic_version: cstring, /* human readable quic (+ HTTP/3) library + + version or NULL */ + + /* These fields were added in CURLVERSION_SEVENTH */ + cainfo: cstring, /* the built-in default CURLOPT_CAINFO, might + be NULL */ + capath: cstring, /* the built-in default CURLOPT_CAPATH, might + be NULL */ + + /* These fields were added in CURLVERSION_EIGHTH */ + zstd_ver_num: c.uint, /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + zstd_version: cstring, /* human readable string. */ + + /* These fields were added in CURLVERSION_NINTH */ + hyper_version: cstring, /* human readable string. */ + + /* These fields were added in CURLVERSION_TENTH */ + gsasl_version: cstring, /* human readable string. */ + + /* These fields were added in CURLVERSION_ELEVENTH */ + /* feature_names is terminated by an entry with a NULL feature name */ + feature_names: [^]cstring, + + /* These fields were added in CURLVERSION_TWELFTH */ + rtmp_version: cstring, /* human readable string. */ +} + +VERSION_IPV6 :: 1<<0 /* IPv6-enabled */ +VERSION_KERBEROS4 :: 1<<1 /* Kerberos V4 auth is supported (deprecated) */ +VERSION_SSL :: 1<<2 /* SSL options are present */ +VERSION_LIBZ :: 1<<3 /* libz features are present */ +VERSION_NTLM :: 1<<4 /* NTLM auth is supported */ +VERSION_GSSNEGOTIATE :: 1<<5 /* Negotiate auth is supported (deprecated) */ +VERSION_DEBUG :: 1<<6 /* Built with debug capabilities */ +VERSION_ASYNCHDNS :: 1<<7 /* Asynchronous DNS resolves */ +VERSION_SPNEGO :: 1<<8 /* SPNEGO auth is supported */ +VERSION_LARGEFILE :: 1<<9 /* Supports files larger than 2GB */ +VERSION_IDN :: 1<<10 /* Internationized Domain Names are supported */ +VERSION_SSPI :: 1<<11 /* Built against Windows SSPI */ +VERSION_CONV :: 1<<12 /* Character conversions supported */ +VERSION_CURLDEBUG :: 1<<13 /* Debug memory tracking supported */ +VERSION_TLSAUTH_SRP :: 1<<14 /* TLS-SRP auth is supported */ +VERSION_NTLM_WB :: 1<<15 /* NTLM delegation to winbind helper is supported */ +VERSION_HTTP2 :: 1<<16 /* HTTP2 support built-in */ +VERSION_GSSAPI :: 1<<17 /* Built against a GSS-API library */ +VERSION_KERBEROS5 :: 1<<18 /* Kerberos V5 auth is supported */ +VERSION_UNIX_SOCKETS :: 1<<19 /* Unix domain sockets support */ +VERSION_PSL :: 1<<20 /* Mozilla's Public Suffix List, used for cookie domain verification */ +VERSION_HTTPS_PROXY :: 1<<21 /* HTTPS-proxy support built-in */ +VERSION_MULTI_SSL :: 1<<22 /* Multiple SSL backends available */ +VERSION_BROTLI :: 1<<23 /* Brotli features are present. */ +VERSION_ALTSVC :: 1<<24 /* Alt-Svc handling built-in */ +VERSION_HTTP3 :: 1<<25 /* HTTP3 support built-in */ +VERSION_ZSTD :: 1<<26 /* zstd features are present */ +VERSION_UNICODE :: 1<<27 /* Unicode support on Windows */ +VERSION_HSTS :: 1<<28 /* HSTS is supported */ +VERSION_GSASL :: 1<<29 /* libgsasl is supported */ +VERSION_THREADSAFE :: 1<<30 /* libcurl API is thread-safe */ + + +PAUSE_RECV :: 1<<0 +PAUSE_RECV_CONT :: 0 + +PAUSE_SEND :: 1<<2 +PAUSE_SEND_CONT :: 0 + +PAUSE_ALL :: PAUSE_RECV|PAUSE_SEND +PAUSE_CONT :: PAUSE_RECV_CONT|PAUSE_SEND_CONT + +/* This is the curl_ssls_export_cb callback prototype. It is passed to curl_easy_ssls_export() to extract SSL sessions/tickets. */ +ssls_export_cb :: #type proc "c" (handle: ^CURL, + userptr: rawptr, + session_key: cstring, + shmac: [^]u8, + shmac_len: c.size_t, + sdata: [^]u8, + sdata_len: c.size_t, + valid_until: off_t, + ietf_tls_id: c.int, + alpn: cstring, + earlydata_max: c.size_t) -> code + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ + version_info :: proc(version_enum) -> ^version_info_data --- + + /* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ + easy_strerror :: proc(code) -> cstring --- + + /* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ + share_strerror :: proc(SHcode) -> cstring --- + + /* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ + easy_pause :: proc(handle: ^CURL, bitmask: c.uint) -> code --- + + /* + * NAME curl_easy_ssls_import() + * + * DESCRIPTION + * + * The curl_easy_ssls_import function adds a previously exported SSL session + * to the SSL session cache of the easy handle (or the underlying share). + */ + easy_ssls_import :: proc(handle: ^CURL, + session_key: cstring, + shmac: [^]u8, + shmac_len: c.size_t, + sdata: [^]u8, + sdata_len: c.size_t) -> code --- + + /* + * NAME curl_easy_ssls_export() + * + * DESCRIPTION + * + * The curl_easy_ssls_export function iterates over all SSL sessions stored + * in the easy handle (or underlying share) and invokes the passed + * callback. + * + */ + easy_ssls_export :: proc(handle: ^CURL, + export_fn: ssls_export_cb, + userptr: rawptr) -> code --- + + +} diff --git a/vendor/curl/curl_easy.odin b/vendor/curl/curl_easy.odin new file mode 100644 index 000000000..bad8fdc28 --- /dev/null +++ b/vendor/curl/curl_easy.odin @@ -0,0 +1,101 @@ +package vendor_curl + +import c "core:c/libc" + +/* Flag bits in the curl_blob struct: */ +BLOB_COPY :: blob_flags{.COPY} /* tell libcurl to copy the data */ +BLOB_NOCOPY :: blob_flags{} /* tell libcurl to NOT copy the data */ + +blob_flags :: distinct bit_set[blob_flag; c.uint] +blob_flag :: enum c.uint { + COPY = 0, +} + +blob :: struct { + data: rawptr, + len: c.size_t, + flags: blob_flags, /* bit 0 is defined, the rest are reserved and should be + left zeroes */ +} + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + easy_init :: proc() -> ^CURL --- + easy_setopt :: proc(curl: ^CURL, option: option, #c_vararg args: ..any) -> code --- + easy_perform :: proc(curl: ^CURL) -> code --- + easy_cleanup :: proc(curl: ^CURL) --- + + + /* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. + * The third argument MUST be pointing to the specific type of the used option + * which is documented in each manpage of the option. The data pointed to + * will be filled in accordingly and can be relied upon only if the function + * returns CURLE_OK. This function is intended to get used *AFTER* a performed + * transfer, all results from this function are undefined until the transfer + * is completed. + */ + easy_getinfo :: proc(curl: ^CURL, info: INFO, #c_vararg args: ..any) -> code --- + + + /* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ + easy_duphandle :: proc(curl: ^CURL) -> ^CURL --- + + /* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a curl handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ + easy_reset :: proc(curl: ^CURL) --- + + /* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ + easy_recv :: proc(curl: ^CURL, buffer: rawptr, buflen: c.size_t, n: ^c.size_t) -> code --- + + /* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ + easy_send :: proc(curl: ^CURL, buffer: rawptr, buflen: c.size_t, n: ^c.size_t) -> code --- + + + /* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ + easy_upkeep :: proc(curl: ^CURL) -> code --- +} \ No newline at end of file diff --git a/vendor/curl/curl_header.odin b/vendor/curl/curl_header.odin new file mode 100644 index 000000000..c90f9b30b --- /dev/null +++ b/vendor/curl/curl_header.odin @@ -0,0 +1,55 @@ +package vendor_curl + +import c "core:c/libc" + + +header :: struct { + name: cstring, /* this might not use the same case */ + value: cstring, + amount: c.size_t, /* number of headers using this name */ + index: c.size_t, /* ... of this instance, 0 or higher */ + origin: header_origin_bits, /* see bits below */ + anchor: rawptr, /* handle privately used by libcurl */ +} + +header_origin_bits :: distinct bit_set[header_origin_bit; c.uint] +/* 'origin' bits */ +header_origin_bit :: enum c.uint { + H_HEADER = 0, /* plain server header */ + H_TRAILER = 1, /* trailers */ + H_CONNECT = 2, /* CONNECT headers */ + H_1XX = 3, /* 1xx headers */ + H_PSEUDO = 4, /* pseudo headers */ +} + +H_HEADER :: header_origin_bits{.H_HEADER} /* plain server header */ +H_TRAILER :: header_origin_bits{.H_TRAILER} /* trailers */ +H_CONNECT :: header_origin_bits{.H_CONNECT} /* CONNECT headers */ +H_1XX :: header_origin_bits{.H_1XX} /* 1xx headers */ +H_PSEUDO :: header_origin_bits{.H_PSEUDO} /* pseudo headers */ + +Hcode :: enum c.int { + E_OK, + E_BADINDEX, /* header exists but not with this index */ + E_MISSING, /* no such header exists */ + E_NOHEADERS, /* no headers at all exist (yet) */ + E_NOREQUEST, /* no request with this number was used */ + E_OUT_OF_MEMORY, /* out of memory while processing */ + E_BAD_ARGUMENT, /* a function argument was not okay */ + E_NOT_BUILT_IN, /* if API was disabled in the build */ +} + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + easy_header :: proc(easy: ^CURL, + name: cstring, + index: c.size_t, + origin: c.uint, + request: c.int, + hout: ^^header) -> Hcode --- + + easy_nextheader :: proc(easy: ^CURL, + origin: c.uint, + request: c.int, + prev: ^header) -> ^header --- +} \ No newline at end of file diff --git a/vendor/curl/curl_multi.odin b/vendor/curl/curl_multi.odin new file mode 100644 index 000000000..624078684 --- /dev/null +++ b/vendor/curl/curl_multi.odin @@ -0,0 +1,485 @@ +package vendor_curl + +import c "core:c/libc" + +CURLM :: struct {} + +Mcode :: enum c.int { + CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + OK, + BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */ + INTERNAL_ERROR, /* this is a libcurl bug */ + BAD_SOCKET, /* the passed in socket argument did not match */ + UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + ABORTED_BY_CALLBACK, + UNRECOVERABLE_POLL, + + CALL_MULTI_SOCKET = CALL_MULTI_PERFORM, +} + + +/* bitmask bits for CURLMOPT_PIPELINING */ +PIPE_NOTHING :: 0 +PIPE_HTTP1 :: 1 +PIPE_MULTIPLEX :: 2 + + +MSG :: enum c.int { + NONE, /* first, not used */ + DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ +} + +Msg :: struct { + msg: MSG, /* what this message means */ + easy_handle: ^CURL, /* the handle it concerns */ + data: struct #raw_union { + whatever: rawptr, /* message-specific data */ + result: code, /* return code for transfer */ + }, +} + +/* Based on poll(2) structure and values. + * We do not use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +WAIT_POLLIN :: 0x0001 +WAIT_POLLPRI :: 0x0002 +WAIT_POLLOUT :: 0x0004 + +waitfd :: struct { + fd: socket_t, + events: c.short, + revents: c.short, +} + + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * Name: curl_multi_init() + * + * Desc: initialize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ + multi_init :: proc() -> ^CURLM --- + + /* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ + multi_add_handle :: proc(multi_handle: ^CURLM, curl_handle: ^CURL) -> Mcode --- + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ + multi_remove_handle :: proc(multi_handle: ^CURLM, curl_handle: ^CURL) -> Mcode --- + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_fdset :: proc(multi_handle: ^CURLM, + read_fd_set: ^platform_fd_set, + write_fd_set: ^platform_fd_set, + exc_fd_set: ^platform_fd_set, + max_fd: ^c.int) -> Mcode --- + + /* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_wait :: proc(multi_handle: ^CURLM, + extra_fds: [^]waitfd, + extra_nfds: c.uint, + timeout_ms: c.int, + ret: ^c.int) -> Mcode --- + + /* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_poll :: proc(multi_handle: ^CURLM, + extra_fds: [^]waitfd, + extra_nfds: c.uint, + timeout_ms: c.int, + ret: ^c.int) -> Mcode --- + + /* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_wakeup :: proc(multi_handle: ^CURLM) -> Mcode --- + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there is data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ + multi_perform :: proc(multi_handle: ^CURLM, running_handles: ^c.int) -> Mcode --- + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_cleanup :: proc(multi_handle: ^CURLM) -> Mcode --- + + /* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there is any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be simple and only contain basic + * information. If more involved information is wanted, we will + * provide the particular "transfer handle" in that struct and that + * should/could/would be used in subsequent curl_easy_getinfo() calls + * (or similar). The point being that we must never expose complex + * structs to applications, as then we will undoubtably get backwards + * compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ + multi_info_read :: proc(multi_handle: ^CURLM, msgs_in_queue: ^c.int) -> ^Msg --- + + /* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a null-terminated error message. + */ + multi_strerror :: proc(Mcode) -> cstring --- + +} + + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See manpage for details. + */ +POLL_NONE :: 0 +POLL_IN :: 1 +POLL_OUT :: 2 +POLL_INOUT :: 3 +POLL_REMOVE :: 4 + +SOCKET_TIMEOUT :: SOCKET_BAD + +CSELECT_IN :: 0x01 +CSELECT_OUT :: 0x02 +CSELECT_ERR :: 0x04 + +socket_callback :: #type proc "c" ( + easy: ^CURL, /* easy handle */ + s: socket_t, /* socket */ + what: c.int, /* see above */ + userp: rawptr, /* private callback pointer */ + socketp: rawptr, +) -> c.int /* private socket pointer */ + +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +multi_timer_callback :: #type proc "c" (multi: ^CURLM, /* multi handle */ + timeout_ms: c.long, /* see above */ + userp: rawptr) -> c.int /* private callback pointer */ + + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + multi_socket_action :: proc(multi_handle: ^CURLM, + s: socket_t, + ev_bitmask: c.int, + running_handles: ^c.int) -> Mcode --- + + + /* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ + multi_timeout :: proc(multi_handle: ^CURLM, milliseconds: ^c.long) -> Mcode --- +} + + +Moption :: enum c.int { + /* This is the socket callback function pointer */ + SOCKETFUNCTION = OPTTYPE_FUNCTIONPOINT + 1, + + /* This is the argument passed to the socket callback */ + SOCKETDATA = OPTTYPE_OBJECTPOINT + 2, + + /* set to 1 to enable pipelining for this multi handle */ + PIPELINING = OPTTYPE_LONG + 3, + + /* This is the timer callback function pointer */ + TIMERFUNCTION = OPTTYPE_FUNCTIONPOINT + 4, + + /* This is the argument passed to the timer callback */ + TIMERDATA = OPTTYPE_OBJECTPOINT + 5, + + /* maximum number of entries in the connection cache */ + MAXCONNECTS = OPTTYPE_LONG + 6, + + /* maximum number of (pipelining) connections to one host */ + MAX_HOST_CONNECTIONS = OPTTYPE_LONG + 7, + + /* maximum number of requests in a pipeline */ + MAX_PIPELINE_LENGTH = OPTTYPE_LONG + 8, + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CONTENT_LENGTH_PENALTY_SIZE = OPTTYPE_OFF_T + 9, + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CHUNK_LENGTH_PENALTY_SIZE = OPTTYPE_OFF_T + 10, + + /* a list of site names(+port) that are blocked from pipelining */ + PIPELINING_SITE_BL = OPTTYPE_OBJECTPOINT + 11, + + /* a list of server types that are blocked from pipelining */ + PIPELINING_SERVER_BL = OPTTYPE_OBJECTPOINT + 12, + + /* maximum number of open connections in total */ + MAX_TOTAL_CONNECTIONS = OPTTYPE_LONG + 13, + + /* This is the server push callback function pointer */ + PUSHFUNCTION = OPTTYPE_FUNCTIONPOINT + 14, + + /* This is the argument passed to the server push callback */ + PUSHDATA = OPTTYPE_OBJECTPOINT + 15, + + /* maximum number of concurrent streams to support on a connection */ + MAX_CONCURRENT_STREAMS = OPTTYPE_LONG + 16, + + /* network has changed, adjust caches/connection reuse */ + NETWORK_CHANGED = OPTTYPE_LONG + 17, + + /* This is the notify callback function pointer */ + NOTIFYFUNCTION = OPTTYPE_FUNCTIONPOINT + 18, + + /* This is the argument passed to the notify callback */ + NOTIFYDATA = OPTTYPE_OBJECTPOINT + 19, +} + +/* Definition of bits for the CURLMOPT_NETWORK_CHANGED argument: */ + +/* - CURLMNWC_CLEAR_CONNS tells libcurl to prevent further reuse of existing + connections. Connections that are idle will be closed. Ongoing transfers + will continue with the connection they have. */ +MNWC_CLEAR_CONNS :: 1 << 0 + +/* - CURLMNWC_CLEAR_DNS tells libcurl to prevent further reuse of existing + connections. Connections that are idle will be closed. Ongoing transfers + will continue with the connection they have. */ +MNWC_CLEAR_DNS :: 1 << 0 + +Minfo :: enum c.int { + /* first, never use this */ + NONE = 0, + /* The number of easy handles currently managed by the multi handle, + * e.g. have been added but not yet removed. */ + XFERS_CURRENT = 1, + /* The number of easy handles running, e.g. not done and not queueing. */ + XFERS_RUNNING = 2, + /* The number of easy handles waiting to start, e.g. for a connection + * to become available due to limits on parallelism, max connections + * or other factors. */ + INFO_XFERS_PENDING = 3, + /* The number of easy handles finished, waiting for their results to + * be read via `curl_multi_info_read()`. */ + XFERS_DONE = 4, + /* The total number of easy handles added to the multi handle, ever. */ + XFERS_ADDED = 5, + + /* the last unused */ + LASTENTRY, +} + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ + multi_setopt :: proc(multi_handle: ^CURLM, option: Moption, #c_vararg args: ..any) -> Mcode --- + + + /* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ + multi_assign :: proc(multi_handle: ^CURLM, sockfd: socket_t, sockp: rawptr) -> Mcode --- + + /* + * Name: curl_multi_get_handles() + * + * Desc: Returns an allocated array holding all handles currently added to + * the multi handle. Marks the final entry with a NULL pointer. If + * there is no easy handle added to the multi handle, this function + * returns an array with the first entry as a NULL pointer. + * + * Returns: NULL on failure, otherwise a CURL **array pointer + */ + multi_get_handles :: proc(multi_handle: ^CURLM) -> [^]^CURL --- + + /* + * Name: curl_multi_get_offt() + * + * Desc: Retrieves a numeric value for the `CURLMINFO_*` enums. + * + * Returns: CULRM_OK or error when value could not be obtained. + */ + multi_get_offt :: proc(multi_handle: ^CURLM, info: Minfo, value: ^off_t) -> Mcode --- +} + + +/* + * Notifications dispatched by a multi handle, when enabled. + */ +MULTI_NOTIFY :: enum c.uint { + INFO_READ = 0, + EASY_DONE = 1, +} + +/* + * Callback to install via CURLMOPT_NOTIFYFUNCTION. + */ +curl_notify_function :: #type proc "c" (multi_handle: ^CURLM, notification: MULTI_NOTIFY, easy: ^CURL, user_data: rawptr) + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + multi_notify_disable :: proc(multi: ^CURLM, notification: MULTI_NOTIFY) -> Mcode --- + multi_notify_enable :: proc(multi: ^CURLM, notification: MULTI_NOTIFY) -> Mcode --- +} + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. + * + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT + */ +PUSH_OK :: 0 +PUSH_DENY :: 1 +PUSH_ERROROUT :: 2 /* added in 7.72.0 */ + + +pushheaders :: struct {} + +push_callback :: #type proc "c"(parent: ^CURL, + easy: ^CURL, + num_headers: c.size_t, + headers: [^]pushheaders, + userp: rawptr) -> c.int + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + pushheader_bynum :: proc(h: ^pushheaders, num: c.size_t) -> cstring --- + pushheader_byname :: proc(h: ^pushheaders, name: cstring) -> cstring --- + + /* + * Name: curl_multi_waitfds() + * + * Desc: Ask curl for fds for polling. The app can use these to poll on. + * We want curl_multi_perform() called as soon as one of them are + * ready. Passing zero size allows to get just a number of fds. + * + * Returns: CURLMcode type, general multi error code. + */ + multi_waitfds :: proc(multi: ^CURLM, + ufds: [^]waitfd, + size: c.uint, + fd_count: ^c.uint) -> Mcode --- +} diff --git a/vendor/curl/curl_options.odin b/vendor/curl/curl_options.odin new file mode 100644 index 000000000..4d231bae5 --- /dev/null +++ b/vendor/curl/curl_options.odin @@ -0,0 +1,41 @@ +package vendor_curl + +import c "core:c/libc" + +easytype :: enum c.int { + OT_LONG, /* long (a range of values) */ + OT_VALUES, /* (a defined set or bitmask) */ + OT_OFF_T, /* curl_off_t (a range of values) */ + OT_OBJECT, /* pointer (void *) */ + OT_STRING, /* (char * to null-terminated buffer) */ + OT_SLIST, /* (struct curl_slist *) */ + OT_CBPTR, /* (void * passed as-is to a callback) */ + OT_BLOB, /* blob (struct curl_blob *) */ + OT_FUNCTION, /* function pointer */ +} + + +easyoptionflags :: distinct bit_set[easyoptionflag; c.uint] +easyoptionflag :: enum c.uint { + /* "alias" means it is provided for old programs to remain functional, we prefer another name */ + ALIAS = 0, +} + +/* + The CURLOPTTYPE_* id ranges can still be used to figure out what type/size + to use for curl_easy_setopt() for the given id + */ +easyoption :: struct { + name: cstring, + id: option, + type: easytype, + flags: easyoptionflags, +} + + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + easy_option_by_name :: proc(name: cstring) -> ^easyoption --- + easy_option_by_id :: proc(id: option) -> ^easyoption --- + easy_option_next :: proc(prev: ^easyoption) -> ^easyoption --- +} \ No newline at end of file diff --git a/vendor/curl/curl_posix.odin b/vendor/curl/curl_posix.odin new file mode 100644 index 000000000..d53118a7d --- /dev/null +++ b/vendor/curl/curl_posix.odin @@ -0,0 +1,7 @@ +#+build !windows +package vendor_curl + +import "core:sys/posix" + +platform_sockaddr :: posix.sockaddr +platform_fd_set :: posix.fd_set \ No newline at end of file diff --git a/vendor/curl/curl_urlapi.odin b/vendor/curl/curl_urlapi.odin new file mode 100644 index 000000000..0b8171e34 --- /dev/null +++ b/vendor/curl/curl_urlapi.odin @@ -0,0 +1,141 @@ +package vendor_curl + +import c "core:c/libc" + +CURLU :: struct {} + +/* the error codes for the URL API */ +Ucode :: enum c.int { + E_OK, + E_BAD_HANDLE, /* 1 */ + E_BAD_PARTPOINTER, /* 2 */ + E_MALFORMED_INPUT, /* 3 */ + E_BAD_PORT_NUMBER, /* 4 */ + E_UNSUPPORTED_SCHEME, /* 5 */ + E_URLDECODE, /* 6 */ + E_OUT_OF_MEMORY, /* 7 */ + E_USER_NOT_ALLOWED, /* 8 */ + E_UNKNOWN_PART, /* 9 */ + E_NO_SCHEME, /* 10 */ + E_NO_USER, /* 11 */ + E_NO_PASSWORD, /* 12 */ + E_NO_OPTIONS, /* 13 */ + E_NO_HOST, /* 14 */ + E_NO_PORT, /* 15 */ + E_NO_QUERY, /* 16 */ + E_NO_FRAGMENT, /* 17 */ + E_NO_ZONEID, /* 18 */ + E_BAD_FILE_URL, /* 19 */ + E_BAD_FRAGMENT, /* 20 */ + E_BAD_HOSTNAME, /* 21 */ + E_BAD_IPV6, /* 22 */ + E_BAD_LOGIN, /* 23 */ + E_BAD_PASSWORD, /* 24 */ + E_BAD_PATH, /* 25 */ + E_BAD_QUERY, /* 26 */ + E_BAD_SCHEME, /* 27 */ + E_BAD_SLASHES, /* 28 */ + E_BAD_USER, /* 29 */ + E_LACKS_IDN, /* 30 */ + E_TOO_LARGE, /* 31 */ +} + +UPart :: enum c.int { + URL, + SCHEME, + USER, + PASSWORD, + OPTIONS, + HOST, + PORT, + PATH, + QUERY, + FRAGMENT, + ZONEID, /* added in 7.65.0 */ +} + +UFlags :: distinct bit_set[UFlag; c.uint] +UFlag :: enum c.uint { + DEFAULT_PORT = 0, /* return default port number */ + NO_DEFAULT_PORT = 1, /* act as if no port number was set, + if the port number matches the + default for the scheme */ + DEFAULT_SCHEME = 2, /* return default scheme if + missing */ + NON_SUPPORT_SCHEME = 3, /* allow non-supported scheme */ + PATH_AS_IS = 4, /* leave dot sequences */ + DISALLOW_USER = 5, /* no user+password allowed */ + URLDECODE = 6, /* URL decode on get */ + URLENCODE = 7, /* URL encode on set */ + APPENDQUERY = 8, /* append a form style part */ + GUESS_SCHEME = 9, /* legacy curl-style guessing */ + NO_AUTHORITY = 10, /* Allow empty authority when the + scheme is unknown. */ + ALLOW_SPACE = 11, /* Allow spaces in the URL */ + PUNYCODE = 12, /* get the hostname in punycode */ + PUNY2IDN = 13, /* punycode => IDN conversion */ + GET_EMPTY = 14, /* allow empty queries and fragments + when extracting the URL or the + components */ + NO_GUESS_SCHEME = 15, /* for get, do not accept a guess */ +} + +U_DEFAULT_PORT :: UFlags{.DEFAULT_PORT} +U_NO_DEFAULT_PORT :: UFlags{.NO_DEFAULT_PORT} +U_DEFAULT_SCHEME :: UFlags{.DEFAULT_SCHEME} +U_NON_SUPPORT_SCHEME :: UFlags{.NON_SUPPORT_SCHEME} +U_PATH_AS_IS :: UFlags{.PATH_AS_IS} +U_DISALLOW_USER :: UFlags{.DISALLOW_USER} +U_URLDECODE :: UFlags{.URLDECODE} +U_URLENCODE :: UFlags{.URLENCODE} +U_APPENDQUERY :: UFlags{.APPENDQUERY} +U_GUESS_SCHEME :: UFlags{.GUESS_SCHEME} +U_NO_AUTHORITY :: UFlags{.NO_AUTHORITY} +U_ALLOW_SPACE :: UFlags{.ALLOW_SPACE} +U_PUNYCODE :: UFlags{.PUNYCODE} +U_PUNY2IDN :: UFlags{.PUNY2IDN} +U_GET_EMPTY :: UFlags{.GET_EMPTY} +U_NO_GUESS_SCHEME :: UFlags{.NO_GUESS_SCHEME} + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ + url :: proc() -> ^CURLU --- + + /* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ + url_cleanup :: proc(handle: ^CURLU) --- + + /* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ + url_dup :: proc(input: ^CURLU) -> ^CURLU --- + + /* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ + url_get :: proc(handle: ^CURLU, what: UPart, part: ^[^]byte, flags: UFlags) -> ^Ucode --- + + /* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ + url_set :: proc(handle: ^CURLU, what: UPart, part: cstring, flags: UFlags) -> Ucode --- + + /* + * curl_url_strerror() turns a CURLUcode value into the equivalent human + * readable error string. This is useful for printing meaningful error + * messages. + */ + url_strerror :: proc(Ucode) -> cstring --- +} diff --git a/vendor/curl/curl_websockets.odin b/vendor/curl/curl_websockets.odin new file mode 100644 index 000000000..7533198d2 --- /dev/null +++ b/vendor/curl/curl_websockets.odin @@ -0,0 +1,82 @@ +package vendor_curl + +import c "core:c/libc" + + +ws_frame :: struct { + age: c.int, /* zero */ + flags: ws_flags, /* See the CURLWS_* defines */ + offset: off_t, /* the offset of this data into the frame */ + bytesleft: off_t, /* number of pending bytes left of the payload */ + len: c.size_t, /* size of the current data chunk */ +} + +ws_flags :: distinct bit_set[ws_flag; c.uint] +ws_flag :: enum c.uint { + /* flag bits */ + TEXT = 0, + BINARY = 1, + CONT = 2, + CLOSE = 3, + PING = 4, + OFFSET = 5, + + /* flags for curl_ws_send() */ + PONG = 6, +} + +WS_TEXT :: ws_flags{.TEXT} +WS_BINARY :: ws_flags{.BINARY} +WS_CONT :: ws_flags{.CONT} +WS_CLOSE :: ws_flags{.CLOSE} +WS_PING :: ws_flags{.PING} +WS_OFFSET :: ws_flags{.OFFSET} +WS_PONG :: ws_flags{.PONG} + +/* bits for the CURLOPT_WS_OPTIONS bitmask: */ +WS_RAW_MODE :: 1<<0 +WS_NOAUTOPONG :: 1<<1 + +@(default_calling_convention="c", link_prefix="curl_") +foreign lib { + /* + * NAME curl_ws_recv() + * + * DESCRIPTION + * + * Receives data from the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ + ws_recv :: proc(curl: ^CURL, buffer: rawptr, buflen: c.size_t, recv: ^c.size_t, metap: ^^ws_frame) -> code --- + + + + /* + * NAME curl_ws_send() + * + * DESCRIPTION + * + * Sends data over the websocket connection. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ + ws_send :: proc(curl: ^CURL, buffer: rawptr, + buflen: c.size_t, sent: ^c.size_t, + fragsize: off_t, + flags: ws_flags) -> code --- + + + /* + * NAME curl_ws_start_frame() + * + * DESCRIPTION + * + * Buffers a websocket frame header with the given flags and length. + * Errors when a previous frame is not complete, e.g. not all its + * payload has been added. + */ + ws_start_frame :: proc(curl: ^CURL, + flags: c.uint, + frame_len: off_t) -> code --- + + ws_meta :: proc(curl: ^CURL) -> ^ws_frame --- +} \ No newline at end of file diff --git a/vendor/curl/curl_windows.odin b/vendor/curl/curl_windows.odin new file mode 100644 index 000000000..c6df20411 --- /dev/null +++ b/vendor/curl/curl_windows.odin @@ -0,0 +1,7 @@ +#+build windows +package vendor_curl + +import win32 "core:sys/windows" + +platform_sockaddr :: win32.sockaddr +platform_fd_set :: win32.fd_set \ No newline at end of file diff --git a/vendor/curl/lib/libcurl.lib b/vendor/curl/lib/libcurl.lib new file mode 100644 index 000000000..65ee6438d Binary files /dev/null and b/vendor/curl/lib/libcurl.lib differ diff --git a/vendor/darwin/CoreVideo/CVDisplayLink.odin b/vendor/darwin/CoreVideo/CVDisplayLink.odin index fae988e0a..73d11d739 100644 --- a/vendor/darwin/CoreVideo/CVDisplayLink.odin +++ b/vendor/darwin/CoreVideo/CVDisplayLink.odin @@ -1,3 +1,4 @@ +// Bindings for [[ CoreVideo ; https://developer.apple.com/documentation/corevideo ]]. package CoreVideo DisplayLinkRef :: distinct rawptr diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index 2d681b0ee..c01c6311a 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Metal ; https://developer.apple.com/documentation/metal ]]. package objc_Metal import NS "core:sys/darwin/Foundation" @@ -2767,6 +2768,14 @@ RenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^Rende RenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { return msgSend(^Function, self, "fragmentFunction") } +@(objc_type=RenderPipelineDescriptor, objc_name="vertexLinkedFunctions") +RenderPipelineDescriptor_vertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "vertexLinkedFunctions") +} +@(objc_type=RenderPipelineDescriptor, objc_name="fragmentLinkedFunctions") +RenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions") +} @(objc_type=RenderPipelineDescriptor, objc_name="inputPrimitiveTopology") RenderPipelineDescriptor_inputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> PrimitiveTopologyClass { return msgSend(PrimitiveTopologyClass, self, "inputPrimitiveTopology") @@ -2831,6 +2840,14 @@ RenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" RenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentFunction: ^Function) { msgSend(nil, self, "setFragmentFunction:", fragmentFunction) } +@(objc_type=RenderPipelineDescriptor, objc_name="setVertexLinkedFunctions") +RenderPipelineDescriptor_setVertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, vertexLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setVertexLinkedFunctions:", vertexLinkedFunctions) +} +@(objc_type=RenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions") +RenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions) +} @(objc_type=RenderPipelineDescriptor, objc_name="setInputPrimitiveTopology") RenderPipelineDescriptor_setInputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, inputPrimitiveTopology: PrimitiveTopologyClass) { msgSend(nil, self, "setInputPrimitiveTopology:", inputPrimitiveTopology) @@ -2940,86 +2957,6 @@ RenderPipelineDescriptor_vertexFunction :: #force_inline proc "c" (self: ^Render return msgSend(^Function, self, "vertexFunction") } -@(objc_type=RenderPipelineDescriptor, objc_name="objectFunction") -RenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { - return msgSend(^Function, self, "objectFunction") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setObjectFunction") -RenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectFunction: ^Function) { - msgSend(nil, self, "setObjectFunction:", objectFunction) -} -@(objc_type=RenderPipelineDescriptor, objc_name="meshFunction") -RenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { - return msgSend(^Function, self, "meshFunction") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMeshFunction") -RenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshFunction: ^Function) { - msgSend(nil, self, "setMeshFunction:", meshFunction) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup") -RenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup") -RenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup) -} -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup") -RenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadsPerMeshThreadgroup") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup") -RenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadsPerMeshThreadgroup:", maxTotalThreadsPerMeshThreadgroup) -} -@(objc_type=RenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: NS.UInteger) { - msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL { - return msgSend(BOOL, self, "meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { - msgSend(nil, self, "setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:", meshThreadgroupSizeIsMultipleOfThreadExecutionWidth) -} - - -@(objc_type=RenderPipelineDescriptor, objc_name="payloadMemoryLength") -RenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "payloadMemoryLength") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setPayloadMemoryLength") -RenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) { - msgSend(nil, self, "setPayloadMemoryLength:", payloadMemoryLength) -} -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid") -RenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid") -RenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="objectBuffers") -RenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { - return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers") -} -@(objc_type=RenderPipelineDescriptor, objc_name="meshBuffers") -RenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { - return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers") -} - - - @(objc_type=RenderPipelineDescriptor, objc_name="alphaToCoverageEnabled") RenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL { return msgSend(BOOL, self, "alphaToCoverageEnabled") @@ -3034,6 +2971,272 @@ RenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^ return msgSend(BOOL, self, "rasterizationEnabled") } +@(objc_type=RenderPipelineDescriptor, objc_name="shaderValidation") +RenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ShaderValidation { + return msgSend(ShaderValidation, self, "shaderValidation") +} +@(objc_type=RenderPipelineDescriptor, objc_name="setShaderValidation") +RenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, shaderValidation: ShaderValidation) { + msgSend(nil, self, "setShaderValidation:", shaderValidation) +} + + +//////////////////////////////////////////////////////////////////////////////// + + +@(objc_class="MTLMeshRenderPipelineDescriptor") +MeshRenderPipelineDescriptor :: struct{ using _: NS.Copying(MeshRenderPipelineDescriptor) } + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alloc", objc_is_class_method=true) +MeshRenderPipelineDescriptor_alloc :: #force_inline proc "c" () -> ^MeshRenderPipelineDescriptor { + return msgSend(^MeshRenderPipelineDescriptor, MeshRenderPipelineDescriptor, "alloc") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="init") +MeshRenderPipelineDescriptor_init :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^MeshRenderPipelineDescriptor { + return msgSend(^MeshRenderPipelineDescriptor, self, "init") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="binaryArchives") +MeshRenderPipelineDescriptor_binaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.Array { + return msgSend(^NS.Array, self, "binaryArchives") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setBinaryArchives") +MeshRenderPipelineDescriptor_setBinaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, binaryArchives: ^NS.Array) { + msgSend(nil, self, "setBinaryArchives:", binaryArchives) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="colorAttachments") +MeshRenderPipelineDescriptor_colorAttachments :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^RenderPipelineColorAttachmentDescriptorArray { + return msgSend(^RenderPipelineColorAttachmentDescriptorArray, self, "colorAttachments") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="depthAttachmentPixelFormat") +MeshRenderPipelineDescriptor_depthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat { + return msgSend(PixelFormat, self, "depthAttachmentPixelFormat") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setDepthAttachmentPixelFormat") +MeshRenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, depthAttachmentPixelFormat: PixelFormat) { + msgSend(nil, self, "setDepthAttachmentPixelFormat:", depthAttachmentPixelFormat) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentBuffers") +MeshRenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "fragmentBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentFunction") +MeshRenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "fragmentFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentFunction") +MeshRenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentFunction: ^Function) { + msgSend(nil, self, "setFragmentFunction:", fragmentFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentLinkedFunctions") +MeshRenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions") +MeshRenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToCoverageEnabled") +MeshRenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "alphaToCoverageEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToCoverageEnabled") +MeshRenderPipelineDescriptor_isAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isAlphaToCoverageEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToCoverageEnabled") +MeshRenderPipelineDescriptor_setAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToCoverageEnabled: BOOL) { + msgSend(nil, self, "setAlphaToCoverageEnabled:", alphaToCoverageEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToOneEnabled") +MeshRenderPipelineDescriptor_alphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "alphaToOneEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToOneEnabled") +MeshRenderPipelineDescriptor_isAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isAlphaToOneEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToOneEnabled") +MeshRenderPipelineDescriptor_setAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToOneEnabled: BOOL) { + msgSend(nil, self, "setAlphaToOneEnabled:", alphaToOneEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterizationEnabled") +MeshRenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "rasterizationEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isRasterizationEnabled") +MeshRenderPipelineDescriptor_isRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isRasterizationEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterizationEnabled") +MeshRenderPipelineDescriptor_setRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterizationEnabled: BOOL) { + msgSend(nil, self, "setRasterizationEnabled:", rasterizationEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="label") +MeshRenderPipelineDescriptor_label :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.String { + return msgSend(^NS.String, self, "label") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid") +MeshRenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid") +MeshRenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup") +MeshRenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadsPerMeshThreadgroup") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup") +MeshRenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadsPerMeshThreadgroup:", maxTotalThreadsPerMeshThreadgroup) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup") +MeshRenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup") +MeshRenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxVertexAmplificationCount") +MeshRenderPipelineDescriptor_maxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxVertexAmplificationCount") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxVertexAmplificationCount") +MeshRenderPipelineDescriptor_setMaxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxVertexAmplificationCount: NS.UInteger) { + msgSend(nil, self, "setMaxVertexAmplificationCount:", maxVertexAmplificationCount) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshBuffers") +MeshRenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshFunction") +MeshRenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "meshFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshFunction") +MeshRenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshFunction: ^Function) { + msgSend(nil, self, "setMeshFunction:", meshFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshLinkedFunctions") +MeshRenderPipelineDescriptor_meshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "meshLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshLinkedFunctions") +MeshRenderPipelineDescriptor_setMeshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setMeshLinkedFunctions:", meshLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { + msgSend(nil, self, "setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:", meshThreadgroupSizeIsMultipleOfThreadExecutionWidth) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectBuffers") +MeshRenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectFunction") +MeshRenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "objectFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectFunction") +MeshRenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectFunction: ^Function) { + msgSend(nil, self, "setObjectFunction:", objectFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectLinkedFunctions") +MeshRenderPipelineDescriptor_objectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "objectLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectLinkedFunctions") +MeshRenderPipelineDescriptor_setObjectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setObjectLinkedFunctions:", objectLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { + msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="payloadMemoryLength") +MeshRenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "payloadMemoryLength") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setPayloadMemoryLength") +MeshRenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) { + msgSend(nil, self, "setPayloadMemoryLength:", payloadMemoryLength) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterSampleCount") +MeshRenderPipelineDescriptor_rasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "rasterSampleCount") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterSampleCount") +MeshRenderPipelineDescriptor_setRasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterSampleCount: NS.UInteger) { + msgSend(nil, self, "setRasterSampleCount:", rasterSampleCount) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="shaderValidation") +MeshRenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ShaderValidation { + return msgSend(ShaderValidation, self, "shaderValidation") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setShaderValidation") +MeshRenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, shaderValidation: ShaderValidation) { + msgSend(nil, self, "setShaderValidation:", shaderValidation) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="stencilAttachmentPixelFormat") +MeshRenderPipelineDescriptor_stencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat { + return msgSend(PixelFormat, self, "stencilAttachmentPixelFormat") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setStencilAttachmentPixelFormat") +MeshRenderPipelineDescriptor_setStencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, stencilAttachmentPixelFormat: PixelFormat) { + msgSend(nil, self, "setStencilAttachmentPixelFormat:", stencilAttachmentPixelFormat) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="supportIndirectCommandBuffers") +MeshRenderPipelineDescriptor_supportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "supportIndirectCommandBuffers") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setSupportIndirectCommandBuffers") +MeshRenderPipelineDescriptor_setSupportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, supportIndirectCommandBuffers: BOOL) { + msgSend(nil, self, "setSupportIndirectCommandBuffers:", supportIndirectCommandBuffers) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="reset") +MeshRenderPipelineDescriptor_reset :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) { + msgSend(nil, self, "reset") +} + //////////////////////////////////////////////////////////////////////////////// @@ -4105,9 +4308,9 @@ AccelerationStructure_size :: #force_inline proc "c" (self: ^AccelerationStructu return msgSend(NS.UInteger, self, "size") } -@(objc_type=AccelerationStructure, objc_name="getResourceID") -AccelerationStructure_getResourceID :: #force_inline proc "c" (self: ^AccelerationStructure) -> ResourceID { - return msgSend(ResourceID, self, "getResourceID") +@(objc_type=AccelerationStructure, objc_name="gpuResourceID") +AccelerationStructure_gpuResourceID :: #force_inline proc "c" (self: ^AccelerationStructure) -> ResourceID { + return msgSend(ResourceID, self, "gpuResourceID") } //////////////////////////////////////////////////////////////////////////////// @@ -5379,7 +5582,7 @@ Device_newBufferWithSlice :: #force_inline proc "c" (self: ^Device, slice: $S/[] } @(objc_type=Device, objc_name="newBufferWithSliceNoCopy") Device_newBufferWithSliceNoCopy :: #force_inline proc "c" (self: ^Device, slice: $S/[]$E, options: ResourceOptions, deallocator: rawptr) -> ^Buffer { - return Device_newBufferWithBytesNotCopy(self, mem.slice_to_bytes(slice), options, deallocator) + return Device_newBufferWithBytesNoCopy(self, mem.slice_to_bytes(slice), options, deallocator) } @(objc_type=Device, objc_name="newBufferWithLength") Device_newBufferWithLength :: #force_inline proc "c" (self: ^Device, length: NS.UInteger, options: ResourceOptions) -> ^Buffer { @@ -5702,14 +5905,13 @@ Device_supportsVertexAmplificationCount :: #force_inline proc "c" (self: ^Device @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptor") -Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "contextless" (self: ^Device, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) { - state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", options, reflection, &error) +Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) { + state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", descriptor, options, reflection, &error) return } @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptorAndCompletionHandler") -Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, options: PipelineOption, completionHandler: ^NewRenderPipelineStateWithReflectionCompletionHandler) -> (state: ^RenderPipelineState) { - state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", options, completionHandler) - return +Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) { + msgSend(nil, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", descriptor, options, completionHandler) } @(objc_type=Device, objc_name="newIOHandle") diff --git a/vendor/darwin/Metal/MetalEnums.odin b/vendor/darwin/Metal/MetalEnums.odin index 5cef5f18d..7d4e86d65 100644 --- a/vendor/darwin/Metal/MetalEnums.odin +++ b/vendor/darwin/Metal/MetalEnums.odin @@ -1050,3 +1050,9 @@ VertexStepFunction :: enum NS.UInteger { PerPatch = 3, PerPatchControlPoint = 4, } + +ShaderValidation :: enum NS.UInteger { + Default = 0, + Enabled = 1, + Disabled = 2, +} diff --git a/vendor/darwin/MetalKit/MetalKit.odin b/vendor/darwin/MetalKit/MetalKit.odin index 34a87cf42..3a4491a21 100644 --- a/vendor/darwin/MetalKit/MetalKit.odin +++ b/vendor/darwin/MetalKit/MetalKit.odin @@ -1,3 +1,4 @@ +// Bindings for [[ MetalKit ; https://developer.apple.com/documentation/metalkit ]]. package objc_MetalKit import NS "core:sys/darwin/Foundation" diff --git a/vendor/darwin/QuartzCore/QuartzCore.odin b/vendor/darwin/QuartzCore/QuartzCore.odin index b19a5fec5..64e8e66d3 100644 --- a/vendor/darwin/QuartzCore/QuartzCore.odin +++ b/vendor/darwin/QuartzCore/QuartzCore.odin @@ -1,3 +1,4 @@ +// Bindings for [[ QuartzCore ; https://developer.apple.com/documentation/quartzcore ]]. package objc_QuartzCore import NS "core:sys/darwin/Foundation" @@ -46,6 +47,10 @@ MetalLayer_pixelFormat :: proc "c" (self: ^MetalLayer) -> MTL.PixelFormat { MetalLayer_setPixelFormat :: proc "c" (self: ^MetalLayer, pixelFormat: MTL.PixelFormat) { msgSend(nil, self, "setPixelFormat:", pixelFormat) } +@(objc_type=MetalLayer, objc_name="setColorSpace") +MetalLayer_setColorSpace :: proc "c" (self: ^MetalLayer, colorspace: NS.id) { + msgSend(nil, self, "setColorspace:", colorspace) +} @(objc_type=MetalLayer, objc_name="framebufferOnly") MetalLayer_framebufferOnly :: proc "c" (self: ^MetalLayer) -> NS.BOOL { @@ -125,3 +130,21 @@ MetalDrawable_addPresentedHandler :: proc "c" (self: ^MetalDrawable, block: Draw msgSend(nil, self, "addPresentedHandler:", block) } +@(objc_class="CATransaction") +Transaction :: struct { using _: NS.Object } + +@(objc_type=Transaction, objc_name="begin", objc_is_class_method=true) +transaction_begin :: proc() { + msgSend(nil, Transaction, "begin") +} + +@(objc_type=Transaction, objc_name="commit", objc_is_class_method=true) +transaction_commit :: proc() { + msgSend(nil, Transaction, "commit") +} + +@(objc_type=Transaction, objc_name="flush", objc_is_class_method=true) +transaction_flush :: proc() { + msgSend(nil, Transaction, "flush") +} + diff --git a/vendor/directx/d3d11/d3d11.odin b/vendor/directx/d3d11/d3d11.odin index bb91e87ce..51e27ba21 100644 --- a/vendor/directx/d3d11/d3d11.odin +++ b/vendor/directx/d3d11/d3d11.odin @@ -1,9 +1,10 @@ +// Bindings for [[ Direct3D 11 ; https://learn.microsoft.com/en-us/windows/win32/direct3d11/atoc-dx-graphics-direct3d-11 ]]. package directx_d3d11 foreign import "system:d3d11.lib" import "../dxgi" -import "../d3d_compiler" +import "../d3d_common" import "core:sys/windows" IUnknown :: dxgi.IUnknown @@ -19,14 +20,13 @@ BOOL :: dxgi.BOOL UINT :: dxgi.UINT INT :: dxgi.INT -LPCWSTR :: [^]u16 +LPCSTR :: windows.LPCSTR +LPCWSTR :: windows.LPCWSTR RECT :: dxgi.RECT SIZE :: dxgi.SIZE -IModuleInstance :: d3d_compiler.ID3D11ModuleInstance -IBlob :: d3d_compiler.ID3DBlob -IModule :: d3d_compiler.ID3D11Module +IBlob :: d3d_common.ID3DBlob @(default_calling_convention="system", link_prefix="D3D11") foreign d3d11 { @@ -949,7 +949,7 @@ INPUT_CLASSIFICATION :: enum i32 { } INPUT_ELEMENT_DESC :: struct { - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, Format: dxgi.FORMAT, InputSlot: u32, @@ -971,7 +971,7 @@ CULL_MODE :: enum i32 { SO_DECLARATION_ENTRY :: struct { Stream: u32, - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, StartComponent: u8, ComponentCount: u8, @@ -2171,8 +2171,8 @@ IClassLinkage :: struct #raw_union { } IClassLinkage_VTable :: struct { using id3d11devicechild_vtable: IDeviceChild_VTable, - GetClassInstance: proc "system" (this: ^IClassLinkage, pClassInstanceName: cstring, InstanceIndex: u32, ppInstance: ^^IClassInstance) -> HRESULT, - CreateClassInstance: proc "system" (this: ^IClassLinkage, pClassTypeName: cstring, ConstantBufferOffset: u32, ConstantVectorOffset: u32, TextureOffset: u32, SamplerOffset: u32, ppInstance: ^^IClassInstance) -> HRESULT, + GetClassInstance: proc "system" (this: ^IClassLinkage, pClassInstanceName: LPCSTR, InstanceIndex: u32, ppInstance: ^^IClassInstance) -> HRESULT, + CreateClassInstance: proc "system" (this: ^IClassLinkage, pClassTypeName: LPCSTR, ConstantBufferOffset: u32, ConstantVectorOffset: u32, TextureOffset: u32, SamplerOffset: u32, ppInstance: ^^IClassInstance) -> HRESULT, } @@ -3406,7 +3406,7 @@ SHADER_VERSION_TYPE :: enum i32 { } SIGNATURE_PARAMETER_DESC :: struct { - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, Register: u32, SystemValueType: NAME, @@ -3420,7 +3420,7 @@ SIGNATURE_PARAMETER_DESC :: struct { } SHADER_BUFFER_DESC :: struct { - Name: cstring, + Name: LPCSTR, Type: CBUFFER_TYPE, Variables: u32, Size: u32, @@ -3428,7 +3428,7 @@ SHADER_BUFFER_DESC :: struct { } SHADER_VARIABLE_DESC :: struct { - Name: cstring, + Name: LPCSTR, StartOffset: u32, Size: u32, uFlags: SHADER_VARIABLE_FLAGS, @@ -3447,12 +3447,12 @@ SHADER_TYPE_DESC :: struct { Elements: u32, Members: u32, Offset: u32, - Name: cstring, + Name: LPCSTR, } SHADER_DESC :: struct { Version: u32, - Creator: cstring, + Creator: LPCSTR, Flags: u32, ConstantBuffers: u32, @@ -3495,7 +3495,7 @@ SHADER_DESC :: struct { } SHADER_INPUT_BIND_DESC :: struct { - Name: cstring, + Name: LPCSTR, Type: SHADER_INPUT_TYPE, BindPoint: u32, BindCount: u32, @@ -3507,14 +3507,14 @@ SHADER_INPUT_BIND_DESC :: struct { } LIBRARY_DESC :: struct { - Creator: cstring, + Creator: LPCSTR, Flags: u32, FunctionCount: u32, } FUNCTION_DESC :: struct { Version: u32, - Creator: cstring, + Creator: LPCSTR, Flags: u32, ConstantBuffers: u32, @@ -3544,7 +3544,7 @@ FUNCTION_DESC :: struct { MinFeatureLevel: FEATURE_LEVEL, RequiredFeatureFlags: SHADER_REQUIRES_FLAGS, - Name: cstring, + Name: LPCSTR, FunctionParameterCount: i32, HasReturn: BOOL, Has10Level9VertexShader: BOOL, @@ -3552,8 +3552,8 @@ FUNCTION_DESC :: struct { } PARAMETER_DESC :: struct { - Name: cstring, - SemanticName: cstring, + Name: LPCSTR, + SemanticName: LPCSTR, Type: SHADER_VARIABLE_TYPE, Class: SHADER_VARIABLE_CLASS, Rows: u32, @@ -3567,6 +3567,34 @@ PARAMETER_DESC :: struct { FirstOutComponent: u32, } +IModule :: struct #raw_union { + #subtype iunknown: IUnknown, + using id3d11module_vtable: ^IModule_VTable, +} +IModule_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + CreateInstance: proc "system" (this: ^IModule, pNamespace: LPCSTR, ppModuleInstance: ^^IModuleInstance) -> HRESULT, +} + +IModuleInstance :: struct #raw_union { + #subtype iunknown: IUnknown, + using id3d11moduleinstance_vtable: ^IModuleInstance_VTable, +} +IModuleInstance_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + BindConstantBuffer: proc "system" (this: ^IModuleInstance, uSrcSlot: u32, uDstSlot: u32, cbDstOffset: u32) -> HRESULT, + BindConstantBufferByName: proc "system" (this: ^IModuleInstance, pName: LPCSTR, uDstSlot: u32, cbDstOffset: u32) -> HRESULT, + BindResource: proc "system" (this: ^IModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, + BindResourceByName: proc "system" (this: ^IModuleInstance, pName: LPCSTR, uDstSlot: u32, uCount: u32) -> HRESULT, + BindSampler: proc "system" (this: ^IModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, + BindSamplerByName: proc "system" (this: ^IModuleInstance, pName: LPCSTR, uDstSlot: u32, uCount: u32) -> HRESULT, + BindUnorderedAccessView: proc "system" (this: ^IModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, + BindUnorderedAccessViewByName: proc "system" (this: ^IModuleInstance, pName: LPCSTR, uDstSlot: u32, uCount: u32) -> HRESULT, + BindResourceAsUnorderedAccessView: proc "system" (this: ^IModuleInstance, uSrcSrvSlot: u32, uDstUavSlot: u32, uCount: u32) -> HRESULT, + BindResourceAsUnorderedAccessViewByName: proc "system" (this: ^IModuleInstance, pSrvName: LPCSTR, uDstUavSlot: u32, uCount: u32) -> HRESULT, +} + + ID3D11ShaderReflectionType_UUID_STRING :: "6E6FFA6A-9BAE-4613-A51E-91652D508C21" ID3D11ShaderReflectionType_UUID := &IID{0x6E6FFA6A, 0x9BAE, 0x4613, {0xA5, 0x1E, 0x91, 0x65, 0x2D, 0x50, 0x8C, 0x21}} IShaderReflectionType :: struct { @@ -3575,8 +3603,8 @@ IShaderReflectionType :: struct { IShaderReflectionType_VTable :: struct { GetDesc: proc "system" (this: ^IShaderReflectionType, pDesc: ^SHADER_TYPE_DESC) -> HRESULT, GetMemberTypeByIndex: proc "system" (this: ^IShaderReflectionType, Index: u32) -> ^IShaderReflectionType, - GetMemberTypeByName: proc "system" (this: ^IShaderReflectionType, Name: cstring) -> ^IShaderReflectionType, - GetMemberTypeName: proc "system" (this: ^IShaderReflectionType, Index: u32) -> cstring, + GetMemberTypeByName: proc "system" (this: ^IShaderReflectionType, Name: LPCSTR) -> ^IShaderReflectionType, + GetMemberTypeName: proc "system" (this: ^IShaderReflectionType, Index: u32) -> LPCSTR, IsEqual: proc "system" (this: ^IShaderReflectionType, pType: ^IShaderReflectionType) -> HRESULT, GetSubType: proc "system" (this: ^IShaderReflectionType) -> ^IShaderReflectionType, GetBaseClass: proc "system" (this: ^IShaderReflectionType) -> ^IShaderReflectionType, @@ -3606,7 +3634,7 @@ IShaderReflectionConstantBuffer :: struct { IShaderReflectionConstantBuffer_VTable :: struct { GetDesc: proc "system" (this: ^IShaderReflectionConstantBuffer, pDesc: ^SHADER_BUFFER_DESC) -> HRESULT, GetVariableByIndex: proc "system" (this: ^IShaderReflectionConstantBuffer, Index: u32) -> ^IShaderReflectionVariable, - GetVariableByName: proc "system" (this: ^IShaderReflectionConstantBuffer, Name: cstring) -> ^IShaderReflectionVariable, + GetVariableByName: proc "system" (this: ^IShaderReflectionConstantBuffer, Name: LPCSTR) -> ^IShaderReflectionVariable, } @@ -3620,13 +3648,13 @@ IShaderReflection_VTable :: struct { using iunknown_vtable: IUnknown_VTable, GetDesc: proc "system" (this: ^IShaderReflection, pDesc: ^SHADER_DESC) -> HRESULT, GetConstantBufferByIndex: proc "system" (this: ^IShaderReflection, Index: u32) -> ^IShaderReflectionConstantBuffer, - GetConstantBufferByName: proc "system" (this: ^IShaderReflection, Name: cstring) -> ^IShaderReflectionConstantBuffer, + GetConstantBufferByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR) -> ^IShaderReflectionConstantBuffer, GetResourceBindingDesc: proc "system" (this: ^IShaderReflection, ResourceIndex: u32, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetInputParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, GetOutputParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, GetPatchConstantParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, - GetVariableByName: proc "system" (this: ^IShaderReflection, Name: cstring) -> ^IShaderReflectionVariable, - GetResourceBindingDescByName: proc "system" (this: ^IShaderReflection, Name: cstring, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, + GetVariableByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR) -> ^IShaderReflectionVariable, + GetResourceBindingDescByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetMovInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, GetMovcInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, GetConversionInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, @@ -3660,10 +3688,10 @@ IFunctionReflection :: struct { IFunctionReflection_VTable :: struct { GetDesc: proc "system" (this: ^IFunctionReflection, pDesc: ^FUNCTION_DESC) -> HRESULT, GetConstantBufferByIndex: proc "system" (this: ^IFunctionReflection, BufferIndex: u32) -> ^IShaderReflectionConstantBuffer, - GetConstantBufferByName: proc "system" (this: ^IFunctionReflection, Name: cstring) -> ^IShaderReflectionConstantBuffer, + GetConstantBufferByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR) -> ^IShaderReflectionConstantBuffer, GetResourceBindingDesc: proc "system" (this: ^IFunctionReflection, ResourceIndex: u32, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, - GetVariableByName: proc "system" (this: ^IFunctionReflection, Name: cstring) -> ^IShaderReflectionVariable, - GetResourceBindingDescByName: proc "system" (this: ^IFunctionReflection, Name: cstring, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, + GetVariableByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR) -> ^IShaderReflectionVariable, + GetResourceBindingDescByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetFunctionParameter: proc "system" (this: ^IFunctionReflection, ParameterIndex: i32) -> ^IFunctionParameterReflection, } @@ -3690,7 +3718,7 @@ IFunctionLinkingGraph_VTable :: struct { CreateModuleInstance: proc "system" (this: ^IFunctionLinkingGraph, ppModuleInstance: ^^IModuleInstance, ppErrorBuffer: ^^IBlob) -> HRESULT, SetInputSignature: proc "system" (this: ^IFunctionLinkingGraph, pInputParameters: [^]PARAMETER_DESC, cInputParameters: u32, ppInputNode: ^^ILinkingNode) -> HRESULT, SetOutputSignature: proc "system" (this: ^IFunctionLinkingGraph, pOutputParameters: [^]PARAMETER_DESC, cOutputParameters: u32, ppOutputNode: ^^ILinkingNode) -> HRESULT, - CallFunction: proc "system" (this: ^IFunctionLinkingGraph, pModuleInstanceNamespace: cstring, pModuleWithFunctionPrototype: ^IModule, pFunctionName: cstring, ppCallNode: ^^ILinkingNode) -> HRESULT, + CallFunction: proc "system" (this: ^IFunctionLinkingGraph, pModuleInstanceNamespace: LPCSTR, pModuleWithFunctionPrototype: ^IModule, pFunctionName: LPCSTR, ppCallNode: ^^ILinkingNode) -> HRESULT, PassValue: proc "system" (this: ^IFunctionLinkingGraph, pSrcNode: ^ILinkingNode, SrcParameterIndex: i32, pDstNode: ^ILinkingNode, DstParameterIndex: i32) -> HRESULT, PassValueWithSwizzle: proc "system" (this: ^IFunctionLinkingGraph, pSrcNode: ^ILinkingNode, SrcParameterIndex: i32, pSrcSwizzle: ^u8, pDstNode: ^ILinkingNode, DstParameterIndex: i32, pDstSwizzle: ^u8) -> HRESULT, GetLastError: proc "system" (this: ^IFunctionLinkingGraph, ppErrorBuffer: ^^IBlob) -> HRESULT, @@ -3813,8 +3841,8 @@ IInfoQueue_VTable :: struct { PushRetrievalFilter: proc "system" (this: ^IInfoQueue, pFilter: ^INFO_QUEUE_FILTER) -> HRESULT, PopRetrievalFilter: proc "system" (this: ^IInfoQueue), GetRetrievalFilterStackSize: proc "system" (this: ^IInfoQueue) -> u64, - AddMessage: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: cstring) -> HRESULT, - AddApplicationMessage: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, pDescription: cstring) -> HRESULT, + AddMessage: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: LPCSTR) -> HRESULT, + AddApplicationMessage: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, pDescription: LPCSTR) -> HRESULT, SetBreakOnCategory: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, bEnable: BOOL) -> HRESULT, SetBreakOnSeverity: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, bEnable: BOOL) -> HRESULT, SetBreakOnID: proc "system" (this: ^IInfoQueue, ID: MESSAGE_ID, bEnable: BOOL) -> HRESULT, diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index a533ab7ae..43c23d129 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -1,9 +1,10 @@ +// Bindings for [[ Direct3D 12 ; https://learn.microsoft.com/en-us/windows/win32/direct3d12/direct3d-12-graphics ]]. package directx_d3d12 foreign import "system:d3d12.lib" import "../dxgi" -import "../d3d_compiler" +import "../d3d_common" import win32 "core:sys/windows" IUnknown :: dxgi.IUnknown @@ -22,9 +23,10 @@ BOOL :: dxgi.BOOL RECT :: dxgi.RECT -IModuleInstance :: d3d_compiler.ID3D11ModuleInstance -IBlob :: d3d_compiler.ID3DBlob -IModule :: d3d_compiler.ID3D11Module +LPCSTR :: win32.LPCSTR +LPCWSTR :: win32.LPCWSTR + +IBlob :: d3d_common.ID3DBlob @(default_calling_convention="system", link_prefix="D3D12") foreign d3d12 { @@ -172,19 +174,20 @@ PRIMITIVE :: enum i32 { } SRV_DIMENSION :: enum i32 { - UNKNOWN = 0, - BUFFER = 1, - TEXTURE1D = 2, - TEXTURE1DARRAY = 3, - TEXTURE2D = 4, - TEXTURE2DARRAY = 5, - TEXTURE2DMS = 6, - TEXTURE2DMSARRAY = 7, - TEXTURE3D = 8, - TEXTURECUBE = 9, - TEXTURECUBEARRAY = 10, - BUFFEREX = 11, + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE1DARRAY = 3, + TEXTURE2D = 4, + TEXTURE2DARRAY = 5, + TEXTURE2DMS = 6, + TEXTURE2DMSARRAY = 7, + TEXTURE3D = 8, + TEXTURECUBE = 9, + TEXTURECUBEARRAY = 10, + BUFFEREX = 11, RAYTRACING_ACCELERATION_STRUCTURE = 11, + BUFFER_BYTE_OFFSET = 12, } PFN_DESTRUCTION_CALLBACK :: #type proc "c" (a0: rawptr) @@ -464,7 +467,7 @@ INPUT_CLASSIFICATION :: enum i32 { } INPUT_ELEMENT_DESC :: struct { - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, Format: dxgi.FORMAT, InputSlot: u32, @@ -486,7 +489,7 @@ CULL_MODE :: enum i32 { SO_DECLARATION_ENTRY :: struct { Stream: u32, - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, StartComponent: u8, ComponentCount: u8, @@ -680,7 +683,7 @@ IObject_VTable :: struct { GetPrivateData: proc "system" (this: ^IObject, guid: ^GUID, pDataSize: ^u32, pData: rawptr) -> HRESULT, SetPrivateData: proc "system" (this: ^IObject, guid: ^GUID, DataSize: u32, pData: rawptr) -> HRESULT, SetPrivateDataInterface: proc "system" (this: ^IObject, guid: ^GUID, pData: ^IUnknown) -> HRESULT, - SetName: proc "system" (this: ^IObject, Name: [^]u16) -> HRESULT, + SetName: proc "system" (this: ^IObject, Name: LPCWSTR) -> HRESULT, } @@ -716,7 +719,7 @@ STREAM_OUTPUT_DESC :: struct { } INPUT_LAYOUT_DESC :: struct { - pInputElementDescs: [^]INPUT_ELEMENT_DESC, + pInputElementDescs: [^]INPUT_ELEMENT_DESC `fmt:"v,NumElements"`, NumElements: u32, } @@ -837,12 +840,33 @@ FEATURE :: enum i32 { OPTIONS8 = 36, OPTIONS9 = 37, WAVE_MMA = 38, + OPTIONS10 = 39, + OPTIONS11 = 40, + OPTIONS12 = 41, + OPTIONS13 = 42, + OPTIONS14 = 43, + OPTIONS15 = 44, + OPTIONS16 = 45, + OPTIONS17 = 46, + OPTIONS18 = 47, + OPTIONS19 = 48, + OPTIONS20 = 49, + PREDICATION = 50, + PLACED_RESOURCE_SUPPORT_INFO = 51, + HARDWARE_COPY = 52, + OPTIONS21 = 53, + TIGHT_ALIGNMENT = 54, + APPLICATION_SPECIFIC_DRIVER_STATE = 56, + BYTECODE_BYPASS_HASH_SUPPORTED = 57, + SHADER_CACHE_ABI_SUPPORT = 61, + BARRIER_LAYOUT = 64, + OPTIONS22 = 65, } -SHADER_MIN_PRECISION_SUPPORT :: enum i32 { - NONE = 0, - _10_BIT = 1, - _16_BIT = 2, +SHADER_MIN_PRECISION_SUPPORT :: distinct bit_set[SHADER_MIN_PRECISION_SUPPORT_FLAG; u32] +SHADER_MIN_PRECISION_SUPPORT_FLAG :: enum i32 { + _10_BIT, + _16_BIT, } TILED_RESOURCES_TIER :: enum i32 { @@ -949,6 +973,11 @@ VIEW_INSTANCING_TIER :: enum i32 { _3 = 3, } +WORK_GRAPHS_TIER :: enum i32 { + NOT_SUPPORTED = 0, + _1_0 = 10, +} + FEATURE_DATA_OPTIONS :: struct { DoublePrecisionFloatShaderOps: BOOL, OutputMergerLogicOp: BOOL, @@ -1195,6 +1224,128 @@ FEATURE_DATA_OPTIONS9 :: struct { WaveMMATier: WAVE_MMA_TIER, } +FEATURE_DATA_OPTIONS10 :: struct { + VariableRateShadingSumCombinerSupported: BOOL, + MeshShaderPerPrimitiveShadingRateSupported: BOOL, +} + +FEATURE_DATA_OPTIONS11 :: struct { + AtomicInt64OnDescriptorHeapResourceSupported: BOOL, +} + +TRI_STATE :: enum i32 { + UNKNOWN = -1, + FALSE = 0, + TRUE = 1, +} + +FEATURE_DATA_OPTIONS12 :: struct { + MSPrimitivesPipelineStatisticIncludesCulledPrimitives: TRI_STATE, + EnhancedBarriersSupported: BOOL, + RelaxedFormatCastingSupported: BOOL, +} + +FEATURE_DATA_OPTIONS13 :: struct { + UnrestrictedBufferTextureCopyPitchSupported: BOOL, + UnrestrictedVertexElementAlignmentSupported: BOOL, + InvertedViewportHeightFlipsYSupported: BOOL, + InvertedViewportDepthFlipsZSupported: BOOL, + TextureCopyBetweenDimensionsSupported: BOOL, + AlphaBlendFactorSupported: BOOL, +} + +FEATURE_DATA_OPTIONS14 :: struct { + AdvancedTextureOpsSupported: BOOL, + WriteableMSAATexturesSupported: BOOL, + IndependentFrontAndBackStencilRefMaskSupported: BOOL, +} + +FEATURE_DATA_OPTIONS15 :: struct { + TriangleFanSupported: BOOL, + DynamicIndexBufferStripCutSupported: BOOL, +} + +FEATURE_DATA_OPTIONS16 :: struct { + DynamicDepthBiasSupported: BOOL, + GPUUploadHeapSupported: BOOL, +} + +FEATURE_DATA_OPTIONS17 :: struct { + NonNormalizedCoordinateSamplersSupported: BOOL, + ManualWriteTrackingResourceSupported: BOOL, +} + +FEATURE_DATA_OPTIONS18 :: struct { + RenderPassesValid: BOOL, +} + +FEATURE_DATA_OPTIONS19 :: struct { + MismatchingOutputDimensionsSupported: BOOL, + SupportedSampleCountsWithNoOutputs: u32, + PointSamplingAddressesNeverRoundUp: BOOL, + RasterizerDesc2Supported: BOOL, + NarrowQuadrilateralLinesSupported: BOOL, + AnisoFilterWithPointMipSupported: BOOL, + MaxSamplerDescriptorHeapSize: u32, + MaxSamplerDescriptorHeapSizeWithStaticSamplers: u32, + MaxViewDescriptorHeapSize: u32, + ComputeOnlyCustomHeapSupported: BOOL, +} + +RECREATE_AT_TIER :: enum i32 { + NOT_SUPPORTED = 0, + _1 = 1, +} + +FEATURE_DATA_OPTIONS20 :: struct { + ComputeOnlyWriteWatchSupported: BOOL, + RecreateAtTier: RECREATE_AT_TIER, +} + +EXECUTE_INDIRECT_TIER :: enum i32 { + _1_0 = 10, + _1_1 = 11, +} + +FEATURE_DATA_OPTIONS21 :: struct { + WorkGraphsTier: WORK_GRAPHS_TIER, + ExecuteIndirectTier: EXECUTE_INDIRECT_TIER, + SampleCmpGradientAndBiasSupported: BOOL, + ExtendedCommandInfoSupported: BOOL, +} + +FEATURE_DATA_OPTIONS22 :: struct { + ShaderExecutionReorderingActuallyReorders: BOOL, + CreateByteOffsetViewsSupported: BOOL, + Max1DDispatchSize: u32, + Max1DDispatchMeshSize: u32, +} + +TIGHT_ALIGNMENT_TIER :: enum i32 { + NOT_SUPPORTED = 0, + _1 = NOT_SUPPORTED + 1, +} + +FEATURE_DATA_TIGHT_ALIGNMENT :: struct { + SupportTier: TIGHT_ALIGNMENT_TIER, +} + +FEATURE_DATA_PREDICATION :: struct { + Supported: BOOL, +} + +FEATURE_DATA_HARDWARE_COPY :: struct { + Supported: BOOL, +} + +FEATURE_DATA_APPLICATION_SPECIFIC_DRIVER_STATE :: struct { + Supported: BOOL, +} + +FEATURE_DATA_BYTECODE_BYPASS_HASH_SUPPORTED :: struct { + Supported: BOOL, +} + WAVE_MMA_INPUT_DATATYPE :: enum i32 { INVALID = 0, BYTE = 1, @@ -1238,10 +1389,11 @@ RESOURCE_ALLOCATION_INFO1 :: struct { } HEAP_TYPE :: enum i32 { - DEFAULT = 1, - UPLOAD = 2, - READBACK = 3, - CUSTOM = 4, + DEFAULT = 1, + UPLOAD = 2, + READBACK = 3, + CUSTOM = 4, + GPU_UPLOAD = 5, } CPU_PAGE_PROPERTY :: enum i32 { @@ -1309,14 +1461,16 @@ TEXTURE_LAYOUT :: enum i32 { RESOURCE_FLAGS :: distinct bit_set[RESOURCE_FLAG; u32] RESOURCE_FLAG :: enum u32 { - ALLOW_RENDER_TARGET = 0, - ALLOW_DEPTH_STENCIL = 1, - ALLOW_UNORDERED_ACCESS = 2, - DENY_SHADER_RESOURCE = 3, - ALLOW_CROSS_ADAPTER = 4, - ALLOW_SIMULTANEOUS_ACCESS = 5, - VIDEO_DECODE_REFERENCE_ONLY = 6, - VIDEO_ENCODE_REFERENCE_ONLY = 7, + ALLOW_RENDER_TARGET = 0, + ALLOW_DEPTH_STENCIL = 1, + ALLOW_UNORDERED_ACCESS = 2, + DENY_SHADER_RESOURCE = 3, + ALLOW_CROSS_ADAPTER = 4, + ALLOW_SIMULTANEOUS_ACCESS = 5, + VIDEO_DECODE_REFERENCE_ONLY = 6, + VIDEO_ENCODE_REFERENCE_ONLY = 7, + RAYTRACING_ACCELERATION_STRUCTURE = 8, + USE_TIGHT_ALIGNMENT = 10, } MIP_REGION :: struct { @@ -1473,7 +1627,7 @@ RESOURCE_STATE_GENERIC_READ :: RESOURCE_STATES{ .VERTEX_AND_CONSTANT_BUFFER, .INDEX_BUFFER, .NON_PIXEL_SHADER_RESOURCE, .PIXEL_SHADER_RESOURCE, .INDIRECT_ARGUMENT, .COPY_SOURCE, } RESOURCE_STATE_ALL_SHADER_RESOURCE :: RESOURCE_STATES{ - .SHADING_RATE_SOURCE, .INDEX_BUFFER, + .NON_PIXEL_SHADER_RESOURCE, .PIXEL_SHADER_RESOURCE, } RESOURCE_BARRIER_TYPE :: enum i32 { @@ -1567,7 +1721,7 @@ VIEW_INSTANCING_FLAG :: enum u32 { VIEW_INSTANCING_DESC :: struct { ViewInstanceCount: u32, - pViewInstanceLocations: [^]VIEW_INSTANCE_LOCATION, + pViewInstanceLocations: [^]VIEW_INSTANCE_LOCATION `fmt:"v,ViewInstanceCount"`, Flags: VIEW_INSTANCING_FLAGS, } @@ -1665,6 +1819,13 @@ RAYTRACING_ACCELERATION_STRUCTURE_SRV :: struct { Location: GPU_VIRTUAL_ADDRESS, } +BUFFER_SRV_BYTE_OFFSET :: struct { + Offset: u64, + Size: u64, + StructureByteStride: u32, + Flags: BUFFER_SRV_FLAGS, +} + SHADER_RESOURCE_VIEW_DESC :: struct { Format: dxgi.FORMAT, ViewDimension: SRV_DIMENSION, @@ -1681,6 +1842,7 @@ SHADER_RESOURCE_VIEW_DESC :: struct { TextureCube: TEXCUBE_SRV, TextureCubeArray: TEXCUBE_ARRAY_SRV, RaytracingAccelerationStructure: RAYTRACING_ACCELERATION_STRUCTURE_SRV, + BufferByteOffset: BUFFER_SRV_BYTE_OFFSET, }, } @@ -1802,26 +1964,36 @@ TEX3D_UAV :: struct { WSize: u32, } +BUFFER_UAV_BYTE_OFFSET :: struct { + Offset: u64, + Size: u32, + StructureByteStride: u32, + CounterOffsetInBytes: u64, + Flags: BUFFER_UAV_FLAGS, +} + UAV_DIMENSION :: enum i32 { - UNKNOWN = 0, - BUFFER = 1, - TEXTURE1D = 2, - TEXTURE1DARRAY = 3, - TEXTURE2D = 4, - TEXTURE2DARRAY = 5, - TEXTURE3D = 8, + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE1DARRAY = 3, + TEXTURE2D = 4, + TEXTURE2DARRAY = 5, + TEXTURE3D = 8, + BUFFER_BYTE_OFFSET = 9, } UNORDERED_ACCESS_VIEW_DESC :: struct { Format: dxgi.FORMAT, ViewDimension: UAV_DIMENSION, using _: struct #raw_union { - Buffer: BUFFER_UAV, - Texture1D: TEX1D_UAV, - Texture1DArray: TEX1D_ARRAY_UAV, - Texture2D: TEX2D_UAV, - Texture2DArray: TEX2D_ARRAY_UAV, - Texture3D: TEX3D_UAV, + Buffer: BUFFER_UAV, + Texture1D: TEX1D_UAV, + Texture1DArray: TEX1D_ARRAY_UAV, + Texture2D: TEX2D_UAV, + Texture2DArray: TEX2D_ARRAY_UAV, + Texture3D: TEX3D_UAV, + BufferByteOffset: BUFFER_UAV_BYTE_OFFSET, }, } @@ -2451,7 +2623,7 @@ IDescriptorHeap_VTable :: struct { GetDesc: proc "system" (this: ^IDescriptorHeap, desc: ^DESCRIPTOR_HEAP_DESC), GetCPUDescriptorHandleForHeapStart: proc "system" (this: ^IDescriptorHeap, handle: ^CPU_DESCRIPTOR_HANDLE), GetGPUDescriptorHandleForHeapStart: proc "system" (this: ^IDescriptorHeap, handle: ^GPU_DESCRIPTOR_HANDLE), -} +} IQueryHeap_UUID_STRING :: "0d9658ae-ed45-469e-a61d-970ec583cab4" IQueryHeap_UUID := &IID{0x0d9658ae, 0xed45, 0x469e, {0xa6, 0x1d, 0x97, 0x0e, 0xc5, 0x83, 0xca, 0xb4}} @@ -2635,9 +2807,9 @@ IDevice_VTable :: struct { CreateHeap: proc "system" (this: ^IDevice, pDesc: ^HEAP_DESC, riid: ^IID, ppvHeap: ^rawptr) -> HRESULT, CreatePlacedResource: proc "system" (this: ^IDevice, pHeap: ^IHeap, HeapOffset: u64, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT, CreateReservedResource: proc "system" (this: ^IDevice, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT, - CreateSharedHandle: proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: [^]u16, pHandle: ^HANDLE) -> HRESULT, + CreateSharedHandle: proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: LPCWSTR, pHandle: ^HANDLE) -> HRESULT, OpenSharedHandle: proc "system" (this: ^IDevice, NTHandle: HANDLE, riid: ^IID, ppvObj: ^rawptr) -> HRESULT, - OpenSharedHandleByName: proc "system" (this: ^IDevice, Name: [^]u16, Access: u32, pNTHandle: ^HANDLE) -> HRESULT, + OpenSharedHandleByName: proc "system" (this: ^IDevice, Name: LPCWSTR, Access: u32, pNTHandle: ^HANDLE) -> HRESULT, MakeResident: proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT, Evict: proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT, CreateFence: proc "system" (this: ^IDevice, InitialValue: u64, Flags: FENCE_FLAGS, riid: ^IID, ppFence: ^rawptr) -> HRESULT, @@ -2659,9 +2831,9 @@ IPipelineLibrary :: struct #raw_union { } IPipelineLibrary_VTable :: struct { using id3d12devicechild_vtable: IDeviceChild_VTable, - StorePipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pPipeline: ^IPipelineState) -> HRESULT, - LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, - LoadComputePipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + StorePipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pPipeline: ^IPipelineState) -> HRESULT, + LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + LoadComputePipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, GetSerializedSize: proc "system" (this: ^IPipelineLibrary) -> SIZE_T, Serialize: proc "system" (this: ^IPipelineLibrary, pData: rawptr, DataSizeInBytes: SIZE_T) -> HRESULT, } @@ -2675,7 +2847,7 @@ IPipelineLibrary1 :: struct #raw_union { } IPipelineLibrary1_VTable :: struct { using id3d12pipelinelibrary_vtable: IPipelineLibrary_VTable, - LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: [^]u16, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: LPCWSTR, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, } MULTIPLE_FENCE_WAIT_FLAGS :: distinct bit_set[MULTIPLE_FENCE_WAIT_FLAG; u32] @@ -2882,7 +3054,7 @@ META_COMMAND_PARAMETER_STAGE :: enum i32 { } META_COMMAND_PARAMETER_DESC :: struct { - Name: [^]u16, + Name: LPCWSTR, Type: META_COMMAND_PARAMETER_TYPE, Flags: META_COMMAND_PARAMETER_FLAGS, RequiredResourceState: RESOURCE_STATES, @@ -2912,7 +3084,7 @@ GRAPHICS_STATES :: enum i32 { META_COMMAND_DESC :: struct { Id: GUID, - Name: [^]u16, + Name: LPCWSTR, InitializationDirtyState: GRAPHICS_STATES, ExecutionDirtyState: GRAPHICS_STATES, } @@ -2933,8 +3105,8 @@ IStateObjectProperties :: struct #raw_union { } IStateObjectProperties_VTable :: struct { using iunknown_vtable: IUnknown_VTable, - GetShaderIdentifier: proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> rawptr, - GetShaderStackSize: proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> u64, + GetShaderIdentifier: proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> rawptr, + GetShaderStackSize: proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> u64, GetPipelineStackSize: proc "system" (this: ^IStateObjectProperties) -> u64, SetPipelineStackSize: proc "system" (this: ^IStateObjectProperties, PipelineStackSizeInBytes: u64), } @@ -2988,8 +3160,8 @@ EXPORT_FLAG :: enum u32 { } EXPORT_DESC :: struct { - Name: [^]u16, - ExportToRename: [^]u16, + Name: LPCWSTR, + ExportToRename: LPCWSTR, Flags: EXPORT_FLAGS, } @@ -3008,13 +3180,13 @@ EXISTING_COLLECTION_DESC :: struct { SUBOBJECT_TO_EXPORTS_ASSOCIATION :: struct { pSubobjectToAssociate: ^STATE_SUBOBJECT, NumExports: u32, - pExports: [^]^i16, + pExports: [^]LPCWSTR `fmt:"v,NumExports"`, } DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION :: struct { - SubobjectToAssociate: ^i16, + SubobjectToAssociate: LPCWSTR, NumExports: u32, - pExports: [^]^i16, + pExports: [^]LPCWSTR `fmt:"v,NumExports"`, } HIT_GROUP_TYPE :: enum i32 { @@ -3023,11 +3195,11 @@ HIT_GROUP_TYPE :: enum i32 { } HIT_GROUP_DESC :: struct { - HitGroupExport: ^i16, + HitGroupExport: LPCWSTR, Type: HIT_GROUP_TYPE, - AnyHitShaderImport: ^i16, - ClosestHitShaderImport: ^i16, - IntersectionShaderImport: ^i16, + AnyHitShaderImport: LPCWSTR, + ClosestHitShaderImport: LPCWSTR, + IntersectionShaderImport: LPCWSTR, } RAYTRACING_SHADER_CONFIG :: struct { @@ -3184,7 +3356,8 @@ SERIALIZED_DATA_DRIVER_MATCHING_IDENTIFIER :: struct { } SERIALIZED_DATA_TYPE :: enum i32 { - SERIALIZED_DATA_RAYTRACING_ACCELERATION_STRUCTURE = 0, + RAYTRACING_ACCELERATION_STRUCTURE = 0, + APPLICATION_SPECIFIC_DRIVER_STATE = 1, } DRIVER_MATCHING_IDENTIFIER_STATUS :: enum i32 { @@ -3335,9 +3508,9 @@ AUTO_BREADCRUMB_OP :: enum i32 { AUTO_BREADCRUMB_NODE :: struct { pCommandListDebugNameA: cstring, - pCommandListDebugNameW: [^]u16, + pCommandListDebugNameW: LPCWSTR, pCommandQueueDebugNameA: cstring, - pCommandQueueDebugNameW: [^]u16, + pCommandQueueDebugNameW: LPCWSTR, pCommandList: ^IGraphicsCommandList, pCommandQueue: ^ICommandQueue, BreadcrumbCount: u32, @@ -3348,14 +3521,14 @@ AUTO_BREADCRUMB_NODE :: struct { DRED_BREADCRUMB_CONTEXT :: struct { BreadcrumbIndex: u32, - pContextString: [^]u16, + pContextString: LPCWSTR, } AUTO_BREADCRUMB_NODE1 :: struct { pCommandListDebugNameA: cstring, - pCommandListDebugNameW: [^]u16, + pCommandListDebugNameW: LPCWSTR, pCommandQueueDebugNameA: cstring, - pCommandQueueDebugNameW: [^]u16, + pCommandQueueDebugNameW: LPCWSTR, pCommandList: ^IGraphicsCommandList, pCommandQueue: ^ICommandQueue, BreadcrumbCount: u32, @@ -3424,14 +3597,14 @@ DRED_ALLOCATION_TYPE :: enum i32 { DRED_ALLOCATION_NODE :: struct { ObjectNameA: cstring, - ObjectNameW: ^i16, + ObjectNameW: cstring16, AllocationType: DRED_ALLOCATION_TYPE, pNext: ^DRED_ALLOCATION_NODE, } DRED_ALLOCATION_NODE1 :: struct { ObjectNameA: cstring, - ObjectNameW: ^i16, + ObjectNameW: cstring16, AllocationType: DRED_ALLOCATION_TYPE, pNext: ^DRED_ALLOCATION_NODE1, pObject: ^IUnknown, @@ -3457,7 +3630,7 @@ DRED_PAGE_FAULT_OUTPUT1 :: struct { pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1, } -DRED_PAGE_FAULT_FLAGS :: bit_set[DRED_PAGE_FAULT_FLAG;u32] +DRED_PAGE_FAULT_FLAGS :: distinct bit_set[DRED_PAGE_FAULT_FLAG; u32] DRED_PAGE_FAULT_FLAG :: enum u32 { } @@ -3737,7 +3910,7 @@ RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS :: struct { pSrcResource: ^IResource, pDstResource: ^IResource, SubresourceCount: u32, - pSubresourceParameters: [^]RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS, + pSubresourceParameters: [^]RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS `fmt:"v,SubresourceCount"`, Format: dxgi.FORMAT, ResolveMode: RESOLVE_MODE, PreserveResolveSource: BOOL, @@ -3819,7 +3992,7 @@ SHADER_CACHE_MODE :: enum i32 { DISK = 1, } -SHADER_CACHE_FLAGS :: bit_set[SHADER_CACHE_FLAG;u32] +SHADER_CACHE_FLAGS :: distinct bit_set[SHADER_CACHE_FLAG; u32] SHADER_CACHE_FLAG :: enum u32 { DRIVER_VERSIONED = 0, USE_WORKING_DIR = 1, @@ -3850,7 +4023,7 @@ IShaderCacheSession_VTable :: struct { } -SHADER_CACHE_KIND_FLAGS :: bit_set[SHADER_CACHE_KIND_FLAG;u32] +SHADER_CACHE_KIND_FLAGS :: distinct bit_set[SHADER_CACHE_KIND_FLAG; u32] SHADER_CACHE_KIND_FLAG :: enum u32 { IMPLICIT_D3D_CACHE_FOR_DRIVER = 0, IMPLICIT_D3D_CONVERSIONS = 1, @@ -3858,7 +4031,7 @@ SHADER_CACHE_KIND_FLAG :: enum u32 { APPLICATION_MANAGED = 3, } -SHADER_CACHE_CONTROL_FLAGS :: bit_set[SHADER_CACHE_CONTROL_FLAG;u32] +SHADER_CACHE_CONTROL_FLAGS :: distinct bit_set[SHADER_CACHE_CONTROL_FLAG; u32] SHADER_CACHE_CONTROL_FLAG :: enum u32 { DISABLE = 0, ENABLE = 1, @@ -3878,6 +4051,19 @@ IDevice9_VTable :: struct { CreateCommandQueue1: proc "system" (this: ^IDevice9, pDesc: ^COMMAND_QUEUE_DESC, CreatorID: ^IID, riid: ^IID, ppCommandQueue: ^rawptr) -> HRESULT, } +IDevice10_UUID_STRING :: "517F8718-AA66-49F9-B02B-A7AB89C06031" +IDevice10_UUID := &IID{0x517F8718, 0xAA66, 0x49F9, {0xB0, 0x2B, 0xA7, 0xAB, 0x89, 0xC0, 0x60, 0x31}} +IDevice10 :: struct #raw_union { + #subtype id3d12device9: IDevice9, + using id3d12device10_vtable: ^IDevice10_VTable, +} +IDevice10_VTable :: struct { + using id3d12device9_vtable: IDevice9_VTable, + CreateCommittedResource3: proc "system" (this: ^IDevice10, pHeapProperties: ^HEAP_PROPERTIES, HeapFlags: HEAP_FLAGS, pDesc: ^RESOURCE_DESC1, InitialLayout: BARRIER_LAYOUT, pOptimizedClearValue: ^CLEAR_VALUE, pProtectedSession: ^IProtectedResourceSession, NumCastableFormats: u32, pCastableFormats: [^]dxgi.FORMAT, riidResource: ^IID, ppvResource: ^rawptr) -> HRESULT, + CreatePlacedResource2: proc "system" (this: ^IDevice10, pHeap: ^IHeap, HeapOffset: u64, pDesc: ^RESOURCE_DESC1, InitialLayout: BARRIER_LAYOUT, pOptimizedClearValue: ^CLEAR_VALUE, NumCastableFormats: u32, pCastableFormats: [^]dxgi.FORMAT, riid: ^IID, ppvResource: ^rawptr) -> HRESULT, + CreateReservedResource2: proc "system" (this: ^IDevice10, pDesc: ^RESOURCE_DESC, InitialLayout: BARRIER_LAYOUT, pOptimizedClearValue: ^CLEAR_VALUE, pProtectedSession: ^IProtectedResourceSession, NumCastableFormats: u32, pCastableFormats: [^]dxgi.FORMAT , riid: ^IID, ppvResource: ^rawptr) -> HRESULT, +} + ITools_UUID_STRING :: "7071e1f0-e84b-4b33-974f-12fa49de65c5" ITools_UUID := &IID{0x7071e1f0, 0xe84b, 0x4b33, {0x97, 0x4f, 0x12, 0xfa, 0x49, 0xde, 0x65, 0xc5}} @@ -5076,8 +5262,8 @@ IInfoQueue_VTable :: struct { PushRetrievalFilter: proc "system" (this: ^IInfoQueue, pFilter: ^INFO_QUEUE_FILTER) -> HRESULT, PopRetrievalFilter: proc "system" (this: ^IInfoQueue), GetRetrievalFilterStackSize: proc "system" (this: ^IInfoQueue) -> u32, - AddMessage: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: cstring) -> HRESULT, - AddApplicationMessage: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, pDescription: cstring) -> HRESULT, + AddMessage: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: LPCSTR) -> HRESULT, + AddApplicationMessage: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, pDescription: LPCSTR) -> HRESULT, SetBreakOnCategory: proc "system" (this: ^IInfoQueue, Category: MESSAGE_CATEGORY, bEnable: BOOL) -> HRESULT, SetBreakOnSeverity: proc "system" (this: ^IInfoQueue, Severity: MESSAGE_SEVERITY, bEnable: BOOL) -> HRESULT, SetBreakOnID: proc "system" (this: ^IInfoQueue, ID: MESSAGE_ID, bEnable: BOOL) -> HRESULT, @@ -5093,7 +5279,7 @@ MESSAGE_CALLBACK_FLAG :: enum { IGNORE_FILTERS = 0, } -PFN_MESSAGE_CALLBACK :: #type proc "c" (Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: cstring, pContext: rawptr) +PFN_MESSAGE_CALLBACK :: #type proc "c" (Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: LPCSTR, pContext: rawptr) IInfoQueue1_UUID_STRING :: "2852dd88-b484-4c0c-b6b1-67168500e600" IInfoQueue1_UUID := &IID{0x2852dd88, 0xb484, 0x4c0c, {0xb6, 0xb1, 0x67, 0x16, 0x85, 0x00, 0xe6, 0x00}} @@ -5116,7 +5302,7 @@ ISDKConfiguration :: struct #raw_union { } ISDKConfiguration_VTable :: struct { using iunknown_vtable: IUnknown_VTable, - SetSDKVersion: proc "system" (this: ^ISDKConfiguration, SDKVersion: u32, SDKPath: cstring) -> HRESULT, + SetSDKVersion: proc "system" (this: ^ISDKConfiguration, SDKVersion: u32, SDKPath: LPCSTR) -> HRESULT, } @@ -5178,10 +5364,177 @@ IGraphicsCommandList6_VTable :: struct { DispatchMesh: proc "system" (this: ^IGraphicsCommandList6, ThreadGroupCountX: u32, ThreadGroupCountY: u32, ThreadGroupCountZ: u32), } + +BARRIER_LAYOUT :: enum u32 { + UNDEFINED = 0xffffffff, + COMMON = 0, + PRESENT = 0, + GENERIC_READ = 1, + RENDER_TARGET = 2, + UNORDERED_ACCESS = 3, + DEPTH_STENCIL_WRITE = 4, + DEPTH_STENCIL_READ = 5, + SHADER_RESOURCE = 6, + COPY_SOURCE = 7, + COPY_DEST = 8, + RESOLVE_SOURCE = 9, + RESOLVE_DEST = 10, + SHADING_RATE_SOURCE = 11, + VIDEO_DECODE_READ = 12, + VIDEO_DECODE_WRITE = 13, + VIDEO_PROCESS_READ = 14, + VIDEO_PROCESS_WRITE = 15, + VIDEO_ENCODE_READ = 16, + VIDEO_ENCODE_WRITE = 17, + DIRECT_QUEUE_COMMON = 18, + DIRECT_QUEUE_GENERIC_READ = 19, + DIRECT_QUEUE_UNORDERED_ACCESS = 20, + DIRECT_QUEUE_SHADER_RESOURCE = 21, + DIRECT_QUEUE_COPY_SOURCE = 22, + DIRECT_QUEUE_COPY_DEST = 23, + COMPUTE_QUEUE_COMMON = 24, + COMPUTE_QUEUE_GENERIC_READ = 25, + COMPUTE_QUEUE_UNORDERED_ACCESS = 26, + COMPUTE_QUEUE_SHADER_RESOURCE = 27, + COMPUTE_QUEUE_COPY_SOURCE = 28, + COMPUTE_QUEUE_COPY_DEST = 29, + DIRECT_QUEUE_GENERIC_READ_COMPUTE_QUEUE_ACCESSIBLE = 31, +} + +BARRIER_SYNC_FLAG :: enum u32 { + ALL = 0, // 0x1 + DRAW = 1, // 0x2 + INDEX_INPUT = 2, // 0x4 + VERTEX_SHADING = 3, // 0x8 + PIXEL_SHADING = 4, // 0x10 + DEPTH_STENCIL = 5, // 0x20 + RENDER_TARGET = 6, // 0x40 + COMPUTE_SHADING = 7, // 0x80 + RAYTRACING = 8, // 0x100 + COPY = 9, // 0x200 + RESOLVE = 10, // 0x400 + EXECUTE_INDIRECT = 11, // 0x800 + PREDICATION = 11, // 0x800 + ALL_SHADING = 12, // 0x1000 + NON_PIXEL_SHADING = 13, // 0x2000 + EMIT_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO = 14, // 0x4000 + CLEAR_UNORDERED_ACCESS_VIEW = 15, // 0x8000 + VIDEO_DECODE = 20, // 0x100000 + VIDEO_PROCESS = 21, // 0x200000 + VIDEO_ENCODE = 22, // 0x400000 + BUILD_RAYTRACING_ACCELERATION_STRUCTURE = 23, // 0x800000 + COPY_RAYTRACING_ACCELERATION_STRUCTURE = 24, // 0x1000000 + SPLIT = 31, // 0x80000000 +} + +BARRIER_SYNC_FLAGS :: bit_set[BARRIER_SYNC_FLAG; u32] + +BARRIER_ACCESS_FLAG :: enum u32 { + VERTEX_BUFFER = 0, // 0x1 + CONSTANT_BUFFER = 1, // 0x2 + INDEX_BUFFER = 2, // 0x4 + RENDER_TARGET = 3, // 0x8 + UNORDERED_ACCESS = 4, // 0x10 + DEPTH_STENCIL_WRITE = 5, // 0x20 + DEPTH_STENCIL_READ = 6, // 0x40 + SHADER_RESOURCE = 7, // 0x80 + STREAM_OUTPUT = 8, // 0x100 + INDIRECT_ARGUMENT = 9, // 0x200 + PREDICATION = 9, // 0x200 + COPY_DEST = 10, // 0x400 + COPY_SOURCE = 11, // 0x800 + RESOLVE_DEST = 12, // 0x1000 + RESOLVE_SOURCE = 13, // 0x2000 + RAYTRACING_ACCELERATION_STRUCTURE_READ = 14, // 0x4000 + RAYTRACING_ACCELERATION_STRUCTURE_WRITE = 15, // 0x8000 + SHADING_RATE_SOURCE = 16, // 0x10000 + VIDEO_DECODE_READ = 17, // 0x20000 + VIDEO_DECODE_WRITE = 18, // 0x40000 + VIDEO_PROCESS_READ = 19, // 0x80000 + VIDEO_PROCESS_WRITE = 20, // 0x100000 + VIDEO_ENCODE_READ = 21, // 0x200000 + VIDEO_ENCODE_WRITE = 22, // 0x400000 + NO_ACCESS = 31, // 0x80000000 +} + +BARRIER_ACCESS_FLAGS :: bit_set[BARRIER_ACCESS_FLAG; u32] + +BARRIER_TYPE :: enum i32 { + GLOBAL, + TEXTURE, + BUFFER, +} + +TEXTURE_BARRIER_FLAGS :: enum i32 { + NONE = 0x0, + DISCARD = 0x1, +} + +BARRIER_SUBRESOURCE_RANGE :: struct { + IndexOrFirstMipLevel: u32, + NumMipLevels: u32, + FirstArraySlice: u32, + NumArraySlices: u32, + FirstPlane: u32, + NumPlanes: u32, +} + +GLOBAL_BARRIER :: struct { + SyncBefore: BARRIER_SYNC_FLAGS, + SyncAfter: BARRIER_SYNC_FLAGS, + AccessBefore: BARRIER_ACCESS_FLAGS, + AccessAfter: BARRIER_ACCESS_FLAGS, +} + +TEXTURE_BARRIER :: struct { + SyncBefore: BARRIER_SYNC_FLAGS, + SyncAfter: BARRIER_SYNC_FLAGS, + AccessBefore: BARRIER_ACCESS_FLAGS, + AccessAfter: BARRIER_ACCESS_FLAGS, + LayoutBefore: BARRIER_LAYOUT, + LayoutAfter: BARRIER_LAYOUT, + pResource: ^IResource, + Subresources: BARRIER_SUBRESOURCE_RANGE, + Flags: TEXTURE_BARRIER_FLAGS, +} + +BUFFER_BARRIER :: struct { + SyncBefore: BARRIER_SYNC_FLAGS, + SyncAfter: BARRIER_SYNC_FLAGS, + AccessBefore: BARRIER_ACCESS_FLAGS, + AccessAfter: BARRIER_ACCESS_FLAGS, + pRessource: ^IResource, + Offset: u64, + Size: u64, +} + +BARRIER_GROUP :: struct { + Type: BARRIER_TYPE, + NumBarriers: u32, + using _: struct #raw_union { + pGlobalBarriers: [^]GLOBAL_BARRIER `raw_union_tag:"Type=GLOBAL"`, + pTextureBarriers: [^]TEXTURE_BARRIER `raw_union_tag:"Type=TEXTURE"`, + pBufferBarriers: [^]BUFFER_BARRIER `raw_union_tag:"Type=BARRIER"`, + }, +} + + +IGraphicsCommandList7_UUID_STRING :: "dd171223-8b61-4769-90e3-160ccde4e2c1" +IGraphicsCommandList7_UUID := &IID{0xdd171223, 0x8b61, 0x4769, {0x90, 0xe3, 0x16, 0x0c, 0xcd, 0xe4, 0xe2, 0xc1}} +IGraphicsCommandList7 :: struct #raw_union { + #subtype id3d12graphicscommandlist6: IGraphicsCommandList6, + using id3d12graphicscommandlist7_vtable: ^IGraphicsCommandList7_VTable, +} +IGraphicsCommandList7_VTable :: struct { + using id3d12graphicscommandlist6_vtable: IGraphicsCommandList6_VTable, + Barrier: proc "system" (this: ^IGraphicsCommandList7, NumBarrierGroups: u32, pBarrierGroups: [^]BARRIER_GROUP), +} + + SHADER_VERSION_TYPE :: enum u32 { PIXEL_SHADER = 0, VERTEX_SHADER = 1, - GEOMETRY_SHADER = 2, + GEOMETRY_SHADER = 2, HULL_SHADER = 3, DOMAIN_SHADER = 4, @@ -5215,7 +5568,7 @@ shver_get_minor :: proc "contextless" (version: u32) -> u8 { } SIGNATURE_PARAMETER_DESC :: struct { - SemanticName: cstring, + SemanticName: LPCSTR, SemanticIndex: u32, Register: u32, SystemValueType: NAME, @@ -5229,7 +5582,7 @@ SIGNATURE_PARAMETER_DESC :: struct { } SHADER_BUFFER_DESC :: struct { - Name: cstring, + Name: LPCSTR, Type: CBUFFER_TYPE, Variables: u32, Size: u32, @@ -5237,7 +5590,7 @@ SHADER_BUFFER_DESC :: struct { } SHADER_VARIABLE_DESC :: struct { - Name: cstring, + Name: LPCSTR, StartOffset: u32, Size: u32, uFlags: u32, @@ -5256,12 +5609,12 @@ SHADER_TYPE_DESC :: struct { Elements: u32, Members: u32, Offset: u32, - Name: cstring, + Name: LPCSTR, } SHADER_DESC :: struct { Version: u32, - Creator: cstring, + Creator: LPCSTR, Flags: u32, ConstantBuffers: u32, @@ -5304,7 +5657,7 @@ SHADER_DESC :: struct { } SHADER_INPUT_BIND_DESC :: struct { - Name: cstring, + Name: LPCSTR, Type: SHADER_INPUT_TYPE, BindPoint: u32, BindCount: u32, @@ -5351,14 +5704,14 @@ SHADER_REQUIRES :: enum u64 { } LIBRARY_DESC :: struct { - Creator: cstring, + Creator: LPCSTR, Flags: u32, FunctionCount: u32, } FUNCTION_DESC :: struct { Version: u32, - Creator: cstring, + Creator: LPCSTR, Flags: u32, ConstantBuffers: u32, @@ -5388,7 +5741,7 @@ FUNCTION_DESC :: struct { MinFeatureLevel: FEATURE_LEVEL, RequiredFeatureFlags: u64, - Name: cstring, + Name: LPCSTR, FunctionParameterCount: i32, HasReturn: BOOL, Has10Level9VertexShader: BOOL, @@ -5396,8 +5749,8 @@ FUNCTION_DESC :: struct { } PARAMETER_DESC :: struct { - Name: cstring, - SemanticName: cstring, + Name: LPCSTR, + SemanticName: LPCSTR, Type: SHADER_VARIABLE_TYPE, Class: SHADER_VARIABLE_CLASS, Rows: u32, @@ -5419,8 +5772,8 @@ IShaderReflectionType :: struct { IShaderReflectionType_VTable :: struct { GetDesc: proc "system" (this: ^IShaderReflectionType, pDesc: ^SHADER_TYPE_DESC) -> HRESULT, GetMemberTypeByIndex: proc "system" (this: ^IShaderReflectionType, Index: u32) -> ^IShaderReflectionType, - GetMemberTypeByName: proc "system" (this: ^IShaderReflectionType, Name: cstring) -> ^IShaderReflectionType, - GetMemberTypeName: proc "system" (this: ^IShaderReflectionType, Index: u32) -> cstring, + GetMemberTypeByName: proc "system" (this: ^IShaderReflectionType, Name: LPCSTR) -> ^IShaderReflectionType, + GetMemberTypeName: proc "system" (this: ^IShaderReflectionType, Index: u32) -> LPCSTR, IsEqual: proc "system" (this: ^IShaderReflectionType, pType: ^IShaderReflectionType) -> HRESULT, GetSubType: proc "system" (this: ^IShaderReflectionType) -> ^IShaderReflectionType, GetBaseClass: proc "system" (this: ^IShaderReflectionType) -> ^IShaderReflectionType, @@ -5450,7 +5803,7 @@ IShaderReflectionConstantBuffer :: struct { IShaderReflectionConstantBuffer_VTable :: struct { GetDesc: proc "system" (this: ^IShaderReflectionConstantBuffer, pDesc: ^SHADER_BUFFER_DESC) -> HRESULT, GetVariableByIndex: proc "system" (this: ^IShaderReflectionConstantBuffer, Index: u32) -> ^IShaderReflectionVariable, - GetVariableByName: proc "system" (this: ^IShaderReflectionConstantBuffer, Name: cstring) -> ^IShaderReflectionVariable, + GetVariableByName: proc "system" (this: ^IShaderReflectionConstantBuffer, Name: LPCSTR) -> ^IShaderReflectionVariable, } IShaderReflection_UUID_STRING :: "5A58797D-A72C-478D-8BA2-EFC6B0EFE88E" @@ -5463,13 +5816,13 @@ IShaderReflection_VTable :: struct { using iunknown_vtable: IUnknown_VTable, GetDesc: proc "system" (this: ^IShaderReflection, pDesc: ^SHADER_DESC) -> HRESULT, GetConstantBufferByIndex: proc "system" (this: ^IShaderReflection, Index: u32) -> ^IShaderReflectionConstantBuffer, - GetConstantBufferByName: proc "system" (this: ^IShaderReflection, Name: cstring) -> ^IShaderReflectionConstantBuffer, + GetConstantBufferByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR) -> ^IShaderReflectionConstantBuffer, GetResourceBindingDesc: proc "system" (this: ^IShaderReflection, ResourceIndex: u32, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetInputParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, GetOutputParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, GetPatchConstantParameterDesc: proc "system" (this: ^IShaderReflection, ParameterIndex: u32, pDesc: ^SIGNATURE_PARAMETER_DESC) -> HRESULT, - GetVariableByName: proc "system" (this: ^IShaderReflection, Name: cstring) -> ^IShaderReflectionVariable, - GetResourceBindingDescByName: proc "system" (this: ^IShaderReflection, Name: cstring, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, + GetVariableByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR) -> ^IShaderReflectionVariable, + GetResourceBindingDescByName: proc "system" (this: ^IShaderReflection, Name: LPCSTR, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetMovInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, GetMovcInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, GetConversionInstructionCount: proc "system" (this: ^IShaderReflection) -> u32, @@ -5502,10 +5855,10 @@ IFunctionReflection :: struct { IFunctionReflection_VTable :: struct { GetDesc: proc "system" (this: ^IFunctionReflection, pDesc: ^FUNCTION_DESC) -> HRESULT, GetConstantBufferByIndex: proc "system" (this: ^IFunctionReflection, BufferIndex: u32) -> ^IShaderReflectionConstantBuffer, - GetConstantBufferByName: proc "system" (this: ^IFunctionReflection, Name: cstring) -> ^IShaderReflectionConstantBuffer, + GetConstantBufferByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR) -> ^IShaderReflectionConstantBuffer, GetResourceBindingDesc: proc "system" (this: ^IFunctionReflection, ResourceIndex: u32, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, - GetVariableByName: proc "system" (this: ^IFunctionReflection, Name: cstring) -> ^IShaderReflectionVariable, - GetResourceBindingDescByName: proc "system" (this: ^IFunctionReflection, Name: cstring, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, + GetVariableByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR) -> ^IShaderReflectionVariable, + GetResourceBindingDescByName: proc "system" (this: ^IFunctionReflection, Name: LPCSTR, pDesc: ^SHADER_INPUT_BIND_DESC) -> HRESULT, GetFunctionParameter: proc "system" (this: ^IFunctionReflection, ParameterIndex: i32) -> ^IFunctionParameterReflection, } diff --git a/vendor/directx/d3d12/d3d12_constants.odin b/vendor/directx/d3d12/d3d12_constants.odin index 62725656a..6e78381d8 100644 --- a/vendor/directx/d3d12/d3d12_constants.odin +++ b/vendor/directx/d3d12/d3d12_constants.odin @@ -461,6 +461,9 @@ TEXEL_ADDRESS_RANGE_BIT_COUNT :: 16 TEXTURE_DATA_PITCH_ALIGNMENT :: 256 TEXTURE_DATA_PLACEMENT_ALIGNMENT :: 512 +TIGHT_ALIGNMENT_MIN_COMMITTED_RESOURCE_ALIGNMENT :: 4096 +TIGHT_ALIGNMENT_MIN_PLACED_RESOURCE_ALIGNMENT :: 8 + TILED_RESOURCE_TILE_SIZE_IN_BYTES :: 65536 TRACKED_WORKLOAD_MAX_INSTANCES :: 32 diff --git a/vendor/directx/d3d_common/d3d_common.odin b/vendor/directx/d3d_common/d3d_common.odin new file mode 100644 index 000000000..af3d09ec9 --- /dev/null +++ b/vendor/directx/d3d_common/d3d_common.odin @@ -0,0 +1,25 @@ +// Declarations shared between D3D versions. +// Based on d3dcommon.h +package d3d_common + +import "core:sys/windows" + +IID :: windows.IID +SIZE_T :: windows.SIZE_T +IUnknown :: windows.IUnknown +IUnknown_VTable :: windows.IUnknown_VTable + +ID3D10Blob_UUID_STRING :: "8BA5FB08-5195-40E2-AC58-0D989C3A0102" +ID3D10Blob_UUID := &IID{0x8BA5FB08, 0x5195, 0x40E2, {0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02}} +ID3D10Blob :: struct #raw_union { + #subtype iunknown: IUnknown, + using id3d10blob_vtable: ^ID3D10Blob_VTable, +} +ID3D10Blob_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + GetBufferPointer: proc "system" (this: ^ID3D10Blob) -> rawptr, + GetBufferSize: proc "system" (this: ^ID3D10Blob) -> SIZE_T, +} + +ID3DBlob :: ID3D10Blob +ID3DBlob_VTable :: ID3D10Blob_VTable diff --git a/vendor/directx/d3d_compiler/d3d_compiler.odin b/vendor/directx/d3d_compiler/d3d_compiler.odin index 5a7178aff..85c5cb46c 100644 --- a/vendor/directx/d3d_compiler/d3d_compiler.odin +++ b/vendor/directx/d3d_compiler/d3d_compiler.odin @@ -1,12 +1,15 @@ +// Bindings for [[ Direct3D Shader Compiler ; https://learn.microsoft.com/en-us/windows/win32/api/d3dcompiler/ ]]. package directx_d3d_compiler foreign import d3dcompiler "d3dcompiler_47.lib" +import win32 "core:sys/windows" D3DCOMPILER_DLL_A :: "d3dcompiler_47.dll" COMPILER_VERSION :: 47 - import "../dxgi" +import "../d3d11" +import "../d3d_common" BOOL :: dxgi.BOOL IID :: dxgi.IID @@ -15,21 +18,26 @@ HRESULT :: dxgi.HRESULT IUnknown :: dxgi.IUnknown IUnknown_VTable :: dxgi.IUnknown_VTable +ID3DBlob :: d3d_common.ID3DBlob + +LPCSTR :: win32.LPCSTR +LPCWSTR :: win32.LPCWSTR + @(default_calling_convention="system", link_prefix="D3D") foreign d3dcompiler { - ReadFileToBlob :: proc(pFileName: [^]u16, ppContents: ^^ID3DBlob) -> HRESULT --- - WriteBlobToFile :: proc(pBlob: ^ID3DBlob, pFileName: [^]u16, bOverwrite: BOOL) -> HRESULT --- - Compile :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: cstring, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: cstring, pTarget: cstring, Flags1: u32, Flags2: u32, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- - Compile2 :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: cstring, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: cstring, pTarget: cstring, Flags1: u32, Flags2: u32, SecondaryDataFlags: u32, pSecondaryData: rawptr, SecondaryDataSize: SIZE_T, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- - CompileFromFile :: proc(pFileName: [^]u16, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: cstring, pTarget: cstring, Flags1: u32, Flags2: u32, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- - Preprocess :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: cstring, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, ppCodeText: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- + ReadFileToBlob :: proc(pFileName: LPCWSTR, ppContents: ^^ID3DBlob) -> HRESULT --- + WriteBlobToFile :: proc(pBlob: ^ID3DBlob, pFileName: LPCWSTR, bOverwrite: BOOL) -> HRESULT --- + Compile :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: LPCSTR, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: LPCSTR, pTarget: LPCSTR, Flags1: u32, Flags2: u32, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- + Compile2 :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: LPCSTR, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: LPCSTR, pTarget: LPCSTR, Flags1: u32, Flags2: u32, SecondaryDataFlags: u32, pSecondaryData: rawptr, SecondaryDataSize: SIZE_T, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- + CompileFromFile :: proc(pFileName: LPCWSTR, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, pEntrypoint: LPCSTR, pTarget: LPCSTR, Flags1: u32, Flags2: u32, ppCode: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- + Preprocess :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pSourceName: LPCSTR, pDefines: ^SHADER_MACRO, pInclude: ^ID3DInclude, ppCodeText: ^^ID3DBlob, ppErrorMsgs: ^^ID3DBlob) -> HRESULT --- GetDebugInfo :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, ppDebugInfo: ^^ID3DBlob) -> HRESULT --- Reflect :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, pInterface: ^IID, ppReflector: ^rawptr) -> HRESULT --- ReflectLibrary :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, riid: ^IID, ppReflector: ^rawptr) -> HRESULT --- - Disassemble :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, Flags: u32, szComments: cstring, ppDisassembly: ^^ID3DBlob) -> HRESULT --- - DisassembleRegion :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, Flags: u32, szComments: cstring, StartByteOffset: SIZE_T, NumInsts: SIZE_T, pFinishByteOffset: ^SIZE_T, ppDisassembly: ^^ID3DBlob) -> HRESULT --- + Disassemble :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, Flags: u32, szComments: LPCSTR, ppDisassembly: ^^ID3DBlob) -> HRESULT --- + DisassembleRegion :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, Flags: u32, szComments: LPCSTR, StartByteOffset: SIZE_T, NumInsts: SIZE_T, pFinishByteOffset: ^SIZE_T, ppDisassembly: ^^ID3DBlob) -> HRESULT --- CreateLinker :: proc(ppLinker: ^^ID3D11Linker) -> HRESULT --- - LoadModule :: proc(pSrcData: rawptr, cbSrcDataSize: SIZE_T, ppModule: ^^ID3D11Module) -> HRESULT --- + LoadModule :: proc(pSrcData: rawptr, cbSrcDataSize: SIZE_T, ppModule: ^^d3d11.IModule) -> HRESULT --- GetTraceInstructionOffsets :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, Flags: u32, StartInstIndex: SIZE_T, NumInsts: SIZE_T, pOffsets: ^SIZE_T, pTotalInsts: ^SIZE_T) -> HRESULT --- GetInputSignatureBlob :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, ppSignatureBlob: ^^ID3DBlob) -> HRESULT --- GetOutputSignatureBlob :: proc(pSrcData: rawptr, SrcDataSize: SIZE_T, ppSignatureBlob: ^^ID3DBlob) -> HRESULT --- @@ -112,40 +120,22 @@ GET_INST_OFFSETS_INCLUDE_NON_EXECUTABLE :: 0x00000001 COMPRESS_SHADER_KEEP_ALL_PARTS :: 0x00000001 SHADER_MACRO :: struct { - Name: cstring, - Definition: cstring, + Name: LPCSTR, + Definition: LPCSTR, } -ID3D10Blob_UUID_STRING :: "8BA5FB08-5195-40E2-AC58-0D989C3A0102" -ID3D10Blob_UUID := &IID{0x8BA5FB08, 0x5195, 0x40E2, {0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02}} -ID3D10Blob :: struct #raw_union { - #subtype iunknown: IUnknown, - using id3d10blob_vtable: ^ID3D10Blob_VTable, -} -ID3D10Blob_VTable :: struct { - using iunknown_vtable: IUnknown_VTable, - GetBufferPointer: proc "system" (this: ^ID3D10Blob) -> rawptr, - GetBufferSize: proc "system" (this: ^ID3D10Blob) -> SIZE_T, -} - - -ID3DBlob :: ID3D10Blob -ID3DBlob_VTable :: ID3D10Blob_VTable - - INCLUDE_TYPE :: enum i32 { INCLUDE_LOCAL = 0, INCLUDE_SYSTEM = 1, _10_INCLUDE_LOCAL = 0, _10_INCLUDE_SYSTEM = 1, - INCLUDE_FORCE_DWORD = 2147483647, } ID3DInclude :: struct { vtable: ^ID3DInclude_VTable, } ID3DInclude_VTable :: struct { - Open: proc "system" (this: ^ID3DInclude, IncludeType: INCLUDE_TYPE, pFileName: cstring, pParentData: rawptr, ppData: ^rawptr, pBytes: ^u32) -> HRESULT, + Open: proc "system" (this: ^ID3DInclude, IncludeType: INCLUDE_TYPE, pFileName: LPCSTR, pParentData: rawptr, ppData: ^rawptr, pBytes: ^u32) -> HRESULT, Close: proc "system" (this: ^ID3DInclude, pData: rawptr) -> HRESULT, } @@ -153,50 +143,21 @@ ID3DInclude_VTable :: struct { D3DCOMPILE_STANDARD_FILE_INCLUDE :: (^ID3DInclude)(uintptr(1)) -ID3D11Module :: struct #raw_union { - #subtype iunknown: IUnknown, - using id3d11module_vtable: ^ID3D11Module_VTable, -} -ID3D11Module_VTable :: struct { - using iunknown_vtable: IUnknown_VTable, - CreateInstance: proc "system" (this: ^ID3D11Module, pNamespace: cstring, ppModuleInstance: ^^ID3D11ModuleInstance) -> HRESULT, -} - - -ID3D11ModuleInstance :: struct #raw_union { - #subtype iunknown: IUnknown, - using id3d11moduleinstance_vtable: ^ID3D11ModuleInstance_VTable, -} -ID3D11ModuleInstance_VTable :: struct { - using iunknown_vtable: IUnknown_VTable, - BindConstantBuffer: proc "system" (this: ^ID3D11ModuleInstance, uSrcSlot: u32, uDstSlot: u32, cbDstOffset: u32) -> HRESULT, - BindConstantBufferByName: proc "system" (this: ^ID3D11ModuleInstance, pName: cstring, uDstSlot: u32, cbDstOffset: u32) -> HRESULT, - BindResource: proc "system" (this: ^ID3D11ModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, - BindResourceByName: proc "system" (this: ^ID3D11ModuleInstance, pName: cstring, uDstSlot: u32, uCount: u32) -> HRESULT, - BindSampler: proc "system" (this: ^ID3D11ModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, - BindSamplerByName: proc "system" (this: ^ID3D11ModuleInstance, pName: cstring, uDstSlot: u32, uCount: u32) -> HRESULT, - BindUnorderedAccessView: proc "system" (this: ^ID3D11ModuleInstance, uSrcSlot: u32, uDstSlot: u32, uCount: u32) -> HRESULT, - BindUnorderedAccessViewByName: proc "system" (this: ^ID3D11ModuleInstance, pName: cstring, uDstSlot: u32, uCount: u32) -> HRESULT, - BindResourceAsUnorderedAccessView: proc "system" (this: ^ID3D11ModuleInstance, uSrcSrvSlot: u32, uDstUavSlot: u32, uCount: u32) -> HRESULT, - BindResourceAsUnorderedAccessViewByName: proc "system" (this: ^ID3D11ModuleInstance, pSrvName: cstring, uDstUavSlot: u32, uCount: u32) -> HRESULT, -} - - ID3D11Linker :: struct #raw_union { #subtype iunknown: IUnknown, using id3d11linker_vtable: ^ID3D11Linker_VTable, } ID3D11Linker_VTable :: struct { using iunknown_vtable: IUnknown_VTable, - Link: proc "system" (this: ^ID3D11Linker, pEntry: ^ID3D11ModuleInstance, pEntryName: cstring, pTargetName: cstring, uFlags: u32, ppShaderBlob: ^^ID3DBlob, ppErrorBuffer: ^^ID3DBlob) -> HRESULT, - UseLibrary: proc "system" (this: ^ID3D11Linker, pLibraryMI: ^ID3D11ModuleInstance) -> HRESULT, + Link: proc "system" (this: ^ID3D11Linker, pEntry: ^d3d11.IModuleInstance, pEntryName: LPCSTR, pTargetName: LPCSTR, uFlags: u32, ppShaderBlob: ^^ID3DBlob, ppErrorBuffer: ^^ID3DBlob) -> HRESULT, + UseLibrary: proc "system" (this: ^ID3D11Linker, pLibraryMI: ^d3d11.IModuleInstance) -> HRESULT, AddClipPlaneFromCBuffer: proc "system" (this: ^ID3D11Linker, uCBufferSlot: u32, uCBufferEntry: u32) -> HRESULT, } -pD3DCompile :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: cstring, a3: ^SHADER_MACRO, a4: ^ID3DInclude, a5: cstring, a6: cstring, a7: u32, a8: u32, a9: ^^ID3DBlob, a10: ^^ID3DBlob) -> HRESULT -pD3DPreprocess :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: cstring, a3: ^SHADER_MACRO, a4: ^ID3DInclude, a5: ^^ID3DBlob, a6: ^^ID3DBlob) -> HRESULT -pD3DDisassemble :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: u32, a3: cstring, a4: ^^ID3DBlob) -> HRESULT +pD3DCompile :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: LPCSTR, a3: ^SHADER_MACRO, a4: ^ID3DInclude, a5: LPCSTR, a6: LPCSTR, a7: u32, a8: u32, a9: ^^ID3DBlob, a10: ^^ID3DBlob) -> HRESULT +pD3DPreprocess :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: LPCSTR, a3: ^SHADER_MACRO, a4: ^ID3DInclude, a5: ^^ID3DBlob, a6: ^^ID3DBlob) -> HRESULT +pD3DDisassemble :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: u32, a3: LPCSTR, a4: ^^ID3DBlob) -> HRESULT D3DCOMPILER_STRIP_FLAGS :: distinct bit_set[D3DCOMPILER_STRIP_FLAG; u32] D3DCOMPILER_STRIP_FLAG :: enum u32 { diff --git a/vendor/directx/dxc/dxcapi.odin b/vendor/directx/dxc/dxcapi.odin index 23dbc8f30..0eb20dbfe 100644 --- a/vendor/directx/dxc/dxcapi.odin +++ b/vendor/directx/dxc/dxcapi.odin @@ -1,3 +1,4 @@ +// Bindings for [[ DXC ; https://learn.microsoft.com/en-us/windows/win32/api/dxcapi/ ]]. package directx_dxc when ODIN_OS == .Windows { @@ -193,27 +194,27 @@ ICompiler :: struct #raw_union { ICompiler_VTable :: struct { using iunknown_vtable: IUnknown_VTable, Compile: proc "system" ( - this: ^ICompiler, - pSource: ^Buffer, - pSourceName: wstring, - pEntryPoint: wstring, - pTargetProfile: wstring, - pArguments: [^]wstring, - argCount: u32, - pDefines: [^]Define, - defineCount: u32, + this: ^ICompiler, + pSource: ^IBlob, + pSourceName: wstring, + pEntryPoint: wstring, + pTargetProfile: wstring, + pArguments: [^]wstring, + argCount: u32, + pDefines: [^]Define, + defineCount: u32, pIncludeHandler: ^IIncludeHandler, - ppResult: ^^IOperationResult) -> HRESULT, + ppResult: ^^IOperationResult) -> HRESULT, Preprocess: proc "system" ( - this: ^ICompiler, - pSource: ^Buffer, - pSourceName: wstring, - pArguments: [^]wstring, - argCount: u32, - pDefines: [^]Define, - defineCount: u32, + this: ^ICompiler, + pSource: ^IBlob, + pSourceName: wstring, + pArguments: [^]wstring, + argCount: u32, + pDefines: [^]Define, + defineCount: u32, pIncludeHandler: ^IIncludeHandler, - ppResult: ^^IOperationResult) -> HRESULT, + ppResult: ^^IOperationResult) -> HRESULT, Disassemble: proc "system" (this: ^ICompiler, pSource: ^Buffer, ppDisassembly: ^IBlobEncoding) -> HRESULT, } @@ -227,7 +228,7 @@ ICompiler2_VTable :: struct { using idxccompiler_vtable: ^ICompiler_VTable, CompileWithDebug: proc "system" ( this: ^ICompiler2, - pSource: ^Buffer, + pSource: ^IBlob, pSourceName: wstring, pEntryPoint: wstring, pTargetProfile: wstring, @@ -286,7 +287,7 @@ IUtils_VTable :: struct { GetBlobAsUtf16: proc "system" (this: ^IUtils, pBlob: ^IBlob, pBlobEncoding: ^^IBlobUtf16) -> HRESULT, GetDxilContainerPart: proc "system" (this: ^IUtils, pShader: ^Buffer, Part: u32, ppPartData: rawptr, pPartSizeInBytes: ^u32) -> HRESULT, CreateReflection: proc "system" (this: ^IUtils, pData: ^Buffer, iid: ^IID, ppvReflection: rawptr) -> HRESULT, - BuildArguments: proc "system" (this: ^IUtils, pSourceName: wstring, pEntryPoint: wstring, pTargetProfile: wstring, pArguments: [^]wstring, argCount: u32, pDefines: [^]Define, defineCount: u32, ppArgs: ^[^]ICompilerArgs) -> HRESULT, + BuildArguments: proc "system" (this: ^IUtils, pSourceName: wstring, pEntryPoint: wstring, pTargetProfile: wstring, pArguments: [^]wstring, argCount: u32, pDefines: [^]Define, defineCount: u32, ppArgs: [^]^ICompilerArgs) -> HRESULT, GetPDBContents: proc "system" (this: ^IUtils, pPDBBlob: ^IBlob, ppHash: ^^IBlob, ppContainer: ^^IBlob) -> HRESULT, } @@ -302,7 +303,6 @@ DXC_OUT_KIND :: enum u32 { REFLECTION = 8, ROOT_SIGNATURE = 9, EXTRA_OUTPUTS = 10, - FORCE_DWORD = 0xFFFFFFFF, } IResult_UUID_STRING :: "58346CDA-DDE7-4497-9461-6F87AF5E0659" diff --git a/vendor/directx/dxgi/dxgi.odin b/vendor/directx/dxgi/dxgi.odin index 0056b6a66..b3ece2984 100644 --- a/vendor/directx/dxgi/dxgi.odin +++ b/vendor/directx/dxgi/dxgi.odin @@ -1,3 +1,4 @@ +// Bindings for [[ DXGI ; https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ ]]. package directx_dxgi foreign import dxgi { @@ -29,19 +30,24 @@ SIZE :: win32.SIZE WCHAR :: win32.WCHAR DWORD :: win32.DWORD -IUnknown :: win32.IUnknown +IUnknown :: win32.IUnknown IUnknown_VTable :: win32.IUnknown_VTable -LPUNKNOWN :: win32.LPUNKNOWN +LPUNKNOWN :: win32.LPUNKNOWN @(default_calling_convention="system") foreign dxgi { CreateDXGIFactory :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- CreateDXGIFactory1 :: proc(riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- CreateDXGIFactory2 :: proc(Flags: CREATE_FACTORY, riid: ^IID, ppFactory: ^rawptr) -> HRESULT --- - DXGIGetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT --- +} + +@(default_calling_convention="system", link_prefix="DXGI") +foreign dxgi { + GetDebugInterface1 :: proc(Flags: u32, riid: ^IID, pDebug: ^rawptr) -> HRESULT --- DeclareAdapterRemovalSupport :: proc() -> HRESULT --- } + STANDARD_MULTISAMPLE_QUALITY_PATTERN :: 0xffffffff CENTER_MULTISAMPLE_QUALITY_PATTERN :: 0xfffffffe FORMAT_DEFINED :: 1 @@ -580,7 +586,7 @@ ISwapChain_VTable :: struct { SetFullscreenState: proc "system" (this: ^ISwapChain, Fullscreen: BOOL, pTarget: ^IOutput) -> HRESULT, GetFullscreenState: proc "system" (this: ^ISwapChain, pFullscreen: ^BOOL, ppTarget: ^^IOutput) -> HRESULT, GetDesc: proc "system" (this: ^ISwapChain, pDesc: ^SWAP_CHAIN_DESC) -> HRESULT, - ResizeBuffers: proc "system" (this: ^ISwapChain, BufferCount: u32, Width: u32, Height: u32, NewFormat: FORMAT, SwapChainFlags: SWAP_CHAIN) -> HRESULT, + ResizeBuffers: proc "system" (this: ^ISwapChain, BufferCount: u32, Width, Height: u32, NewFormat: FORMAT, SwapChainFlags: SWAP_CHAIN) -> HRESULT, ResizeTarget: proc "system" (this: ^ISwapChain, pNewTargetParameters: ^MODE_DESC) -> HRESULT, GetContainingOutput: proc "system" (this: ^ISwapChain, ppOutput: ^^IOutput) -> HRESULT, GetFrameStatistics: proc "system" (this: ^ISwapChain, pStats: ^FRAME_STATISTICS) -> HRESULT, @@ -738,10 +744,10 @@ IOutputDuplication :: struct #raw_union { IOutputDuplication_VTable :: struct { using idxgiobject_vtable: IObject_VTable, GetDesc: proc "system" (this: ^IOutputDuplication, pDesc: ^OUTDUPL_DESC), - AcquireNextFrame: proc "system" (this: ^IOutputDuplication, TimeoutInMilliseconds: u32, pFrameInfo: ^OUTDUPL_FRAME_INFO, ppDesktopResource: ^^IResource) -> HRESULT, - GetFrameDirtyRects: proc "system" (this: ^IOutputDuplication, DirtyRectsBufferSize: u32, pDirtyRectsBuffer: ^RECT, pDirtyRectsBufferSizeRequired: ^u32) -> HRESULT, - GetFrameMoveRects: proc "system" (this: ^IOutputDuplication, MoveRectsBufferSize: u32, pMoveRectBuffer: ^OUTDUPL_MOVE_RECT, pMoveRectsBufferSizeRequired: ^u32) -> HRESULT, - GetFramePointerShape: proc "system" (this: ^IOutputDuplication, PointerShapeBufferSize: u32, pPointerShapeBuffer: rawptr, pPointerShapeBufferSizeRequired: ^u32, pPointerShapeInfo: ^OUTDUPL_POINTER_SHAPE_INFO) -> HRESULT, + AcquireNextFrame: proc "system" (this: ^IOutputDuplication, TimeoutInMilliseconds: u32, pFrameInfo: ^OUTDUPL_FRAME_INFO, ppDesktopResource: ^^IResource) -> HRESULT, + GetFrameDirtyRects: proc "system" (this: ^IOutputDuplication, DirtyRectsBufferSize: u32, pDirtyRectsBuffer: ^RECT, pDirtyRectsBufferSizeRequired: ^u32) -> HRESULT, + GetFrameMoveRects: proc "system" (this: ^IOutputDuplication, MoveRectsBufferSize: u32, pMoveRectBuffer: ^OUTDUPL_MOVE_RECT, pMoveRectsBufferSizeRequired: ^u32) -> HRESULT, + GetFramePointerShape: proc "system" (this: ^IOutputDuplication, PointerShapeBufferSize: u32, pPointerShapeBuffer: rawptr, pPointerShapeBufferSizeRequired: ^u32, pPointerShapeInfo: ^OUTDUPL_POINTER_SHAPE_INFO) -> HRESULT, MapDesktopSurface: proc "system" (this: ^IOutputDuplication, pLockedRect: ^MAPPED_RECT) -> HRESULT, UnMapDesktopSurface: proc "system" (this: ^IOutputDuplication) -> HRESULT, ReleaseFrame: proc "system" (this: ^IOutputDuplication) -> HRESULT, @@ -751,7 +757,6 @@ ALPHA_MODE :: enum i32 { PREMULTIPLIED = 1, STRAIGHT = 2, IGNORE = 3, - FORCE_DWORD = -1, } @@ -836,7 +841,7 @@ SWAP_CHAIN_FULLSCREEN_DESC :: struct { PRESENT_PARAMETERS :: struct { DirtyRectsCount: u32, - pDirtyRects: [^]RECT, + pDirtyRects: [^]RECT `fmt:"v,DirtyRectsCount"`, pScrollRect: ^RECT, pScrollOffset: ^POINT, } @@ -967,8 +972,8 @@ ISwapChain2 :: struct #raw_union { } ISwapChain2_VTable :: struct { using idxgiswapchain1_vtable: ISwapChain1_VTable, - SetSourceSize: proc "system" (this: ^ISwapChain2, Width: u32, Height: u32) -> HRESULT, - GetSourceSize: proc "system" (this: ^ISwapChain2, pWidth: ^u32, pHeight: ^u32) -> HRESULT, + SetSourceSize: proc "system" (this: ^ISwapChain2, Width, Height: u32) -> HRESULT, + GetSourceSize: proc "system" (this: ^ISwapChain2, pWidth, pHeight: ^u32) -> HRESULT, SetMaximumFrameLatency: proc "system" (this: ^ISwapChain2, MaxLatency: u32) -> HRESULT, GetMaximumFrameLatency: proc "system" (this: ^ISwapChain2, pMaxLatency: ^u32) -> HRESULT, GetFrameLatencyWaitableObject: proc "system" (this: ^ISwapChain2) -> HANDLE, @@ -1020,7 +1025,7 @@ IDecodeSwapChain_VTable :: struct { PresentBuffer: proc "system" (this: ^IDecodeSwapChain, BufferToPresent: u32, SyncInterval: u32, Flags: PRESENT) -> HRESULT, SetSourceRect: proc "system" (this: ^IDecodeSwapChain, pRect: ^RECT) -> HRESULT, SetTargetRect: proc "system" (this: ^IDecodeSwapChain, pRect: ^RECT) -> HRESULT, - SetDestSize: proc "system" (this: ^IDecodeSwapChain, Width: u32, Height: u32) -> HRESULT, + SetDestSize: proc "system" (this: ^IDecodeSwapChain, Width, Height: u32) -> HRESULT, GetSourceRect: proc "system" (this: ^IDecodeSwapChain, pRect: ^RECT) -> HRESULT, GetTargetRect: proc "system" (this: ^IDecodeSwapChain, pRect: ^RECT) -> HRESULT, GetDestSize: proc "system" (this: ^IDecodeSwapChain, pWidth: ^u32, pHeight: ^u32) -> HRESULT, @@ -1104,7 +1109,7 @@ ISwapChain3_VTable :: struct { GetCurrentBackBufferIndex: proc "system" (this: ^ISwapChain3) -> u32, CheckColorSpaceSupport: proc "system" (this: ^ISwapChain3, ColorSpace: COLOR_SPACE_TYPE, pColorSpaceSupport: ^SWAP_CHAIN_COLOR_SPACE_SUPPORT) -> HRESULT, SetColorSpace1: proc "system" (this: ^ISwapChain3, ColorSpace: COLOR_SPACE_TYPE) -> HRESULT, - ResizeBuffers1: proc "system" (this: ^ISwapChain3, BufferCount: u32, Width: u32, Height: u32, Format: FORMAT, SwapChainFlags: SWAP_CHAIN, pCreationNodeMask: ^u32, ppPresentQueue: ^^IUnknown) -> HRESULT, + ResizeBuffers1: proc "system" (this: ^ISwapChain3, BufferCount: u32, Width, Height: u32, Format: FORMAT, SwapChainFlags: SWAP_CHAIN, pCreationNodeMask: ^u32, ppPresentQueue: ^^IUnknown) -> HRESULT, } OVERLAY_COLOR_SPACE_SUPPORT :: distinct bit_set[OVERLAY_COLOR_SPACE_SUPPORT_FLAG; u32] OVERLAY_COLOR_SPACE_SUPPORT_FLAG :: enum u32 { @@ -1164,8 +1169,9 @@ IAdapter3_VTable :: struct { } OUTDUPL_FLAG :: enum i32 { - COMPOSITED_UI_CAPTURE_ONLY = 1, + COMPOSITED_UI_CAPTURE_ONLY = 0, } +OUTDUPL_FLAGS :: distinct bit_set[OUTDUPL_FLAG; i32] IOutput5_UUID_STRING :: "80A07424-AB52-42EB-833C-0C42FD282D98" @@ -1176,7 +1182,7 @@ IOutput5 :: struct #raw_union { } IOutput5_VTable :: struct { using idxgioutput4_vtable: IOutput4_VTable, - DuplicateOutput1: proc "system" (this: ^IOutput5, pDevice: ^IUnknown, Flags: u32, SupportedFormatsCount: u32, pSupportedFormats: ^FORMAT, ppOutputDuplication: ^^IOutputDuplication) -> HRESULT, + DuplicateOutput1: proc "system" (this: ^IOutput5, pDevice: ^IUnknown, Flags: OUTDUPL_FLAGS, SupportedFormatsCount: u32, pSupportedFormats: [^]FORMAT, ppOutputDuplication: ^^IOutputDuplication) -> HRESULT, } HDR_METADATA_TYPE :: enum i32 { diff --git a/vendor/directx/dxgi/dxgidebug.odin b/vendor/directx/dxgi/dxgidebug.odin index 98a92d953..46cb588fb 100644 --- a/vendor/directx/dxgi/dxgidebug.odin +++ b/vendor/directx/dxgi/dxgidebug.odin @@ -27,7 +27,7 @@ INFO_QUEUE_MESSAGE_CATEGORY :: enum u32 { MISCELLANEOUS = UNKNOWN + 1, INITIALIZATION = MISCELLANEOUS + 1, CLEANUP = INITIALIZATION + 1, - COMPILATION = CLEANUP + 1, + COMPILATION = CLEANUP + 1, STATE_CREATION = COMPILATION + 1, STATE_SETTING = STATE_CREATION + 1, STATE_GETTING = STATE_SETTING + 1, @@ -49,17 +49,17 @@ INFO_QUEUE_MESSAGE :: struct { Category: INFO_QUEUE_MESSAGE_CATEGORY, Severity: INFO_QUEUE_MESSAGE_SEVERITY, ID: INFO_QUEUE_MESSAGE_ID, - pDescription: [^]c.char, + pDescription: [^]c.char `fmt:"q,DescriptionByteLength"`, DescriptionByteLength: SIZE_T, } INFO_QUEUE_FILTER_DESC :: struct { NumCategories: UINT, - pCategoryList: [^]INFO_QUEUE_MESSAGE_CATEGORY, + pCategoryList: [^]INFO_QUEUE_MESSAGE_CATEGORY `fmt:"v,NumCategories"`, NumSeverities: UINT, - pSeverityList: [^]INFO_QUEUE_MESSAGE_SEVERITY, + pSeverityList: [^]INFO_QUEUE_MESSAGE_SEVERITY `fmt:"v,NumSeverities"`, NumIDs: UINT, - pIDList: [^]INFO_QUEUE_MESSAGE_ID, + pIDList: [^]INFO_QUEUE_MESSAGE_ID `fmt:"v,NumIDs"`, } INFO_QUEUE_FILTER :: struct { diff --git a/vendor/egl/egl.odin b/vendor/egl/egl.odin index 985d58457..744dd2a5d 100644 --- a/vendor/egl/egl.odin +++ b/vendor/egl/egl.odin @@ -1,3 +1,4 @@ +// Bindings for [[ EGL ; https://registry.khronos.org/EGL/sdk/docs/man/html/eglIntro.xhtml ]]. #+build linux package egl @@ -25,6 +26,7 @@ OPENGL_BIT :: 0x0008 OPENGL_ES2_BIT :: 0x0004 OPENGL_ES3_BIT :: 0x00000040 +BUFFER_SIZE :: 0x3020 ALPHA_SIZE :: 0x3021 BLUE_SIZE :: 0x3022 GREEN_SIZE :: 0x3023 @@ -38,6 +40,8 @@ NONE :: 0x3038 COLOR_BUFFER_TYPE :: 0x303F RENDERABLE_TYPE :: 0x3040 CONFORMANT :: 0x3042 +VENDOR :: 0x3053 +VERSION :: 0x3054 HEIGHT :: 0x3056 WIDTH :: 0x3057 @@ -55,17 +59,38 @@ CONTEXT_OPENGL_PROFILE_MASK :: 0x30FD OPENGL_API :: 0x30A2 +CONTEXT_OPENGL_DEBUG :: 0x31B0 + +Platform :: enum u32 { + ANDROID_KHR = 0x3141, + GBM_KHR = 0x31D7, + WAYLAND_KHR = 0x31D8, + X11_KHR = 0x31D5, + X11_SCREEN_KHR = 0x31D6, + DEVICE_EXT = 0x313F, + WAYLAND_EXT = 0x31D8, + X11_EXT = 0x31D5, + X11_SCREEN_EXT = 0x31D6, + XCB_EXT = 0x31DC, + XCB_SCREEN_EXT = 0x31DE, + GBM_MESA = 0x31D7, + SURFACELESS_MESA = 0x31DD, +} + foreign import egl "system:EGL" @(default_calling_convention="c", link_prefix="egl") foreign egl { GetDisplay :: proc(display: NativeDisplayType) -> Display --- + GetPlatformDisplay :: proc(platform: Platform, native_display: rawptr, attrib_list: ^int) -> Display --- Initialize :: proc(display: Display, major: ^i32, minor: ^i32) -> Boolean --- BindAPI :: proc(api: u32) -> Boolean --- - ChooseConfig :: proc(display: Display, attrib_list: ^i32, configs: ^Config, config_size: i32, num_config: ^i32) -> Boolean --- + ChooseConfig :: proc(display: Display, attrib_list: ^i32, configs: [^]Config, config_size: i32, num_config: ^i32) -> Boolean --- CreateWindowSurface :: proc(display: Display, config: Config, native_window: NativeWindowType, attrib_list: ^i32) -> Surface --- + CreatePlatformWindowSurface :: proc(display: Display, config: Config, native_window: rawptr, attrib_list: ^int) -> Surface --- CreateContext :: proc(display: Display, config: Config, share_context: Context, attrib_list: ^i32) -> Context --- MakeCurrent :: proc(display: Display, draw: Surface, read: Surface, ctx: Context) -> Boolean --- QuerySurface :: proc(display: Display, surface: Surface, attribute: i32, value: ^i32) -> Boolean --- + QueryString :: proc(display: Display, name: i32) -> cstring --- SwapInterval :: proc(display: Display, interval: i32) -> Boolean --- SwapBuffers :: proc(display: Display, surface: Surface) -> Boolean --- GetProcAddress :: proc(name: cstring) -> rawptr --- diff --git a/vendor/fontstash/fontstash.odin b/vendor/fontstash/fontstash.odin index 8563277b1..33e7b68de 100644 --- a/vendor/fontstash/fontstash.odin +++ b/vendor/fontstash/fontstash.odin @@ -1,4 +1,5 @@ -#+vet !using-param +// An Odin-native source port of [[ Fontstash ; https://github.com/memononen/fontstash ]]. +#+feature using-stmt package fontstash import "base:runtime" @@ -323,11 +324,15 @@ __AtlasAddWhiteRect :: proc(ctx: ^FontContext, w, h: int) -> bool { // push a font to the font stack // optionally init with ascii characters at a wanted size +// +// 'fontIndex' controls which font you want to load within a multi-font format such +// as TTC. Leave it as zero if you are loading a single-font format such as TTF. AddFontMem :: proc( ctx: ^FontContext, name: string, data: []u8, freeLoadedData: bool, + fontIndex: int = 0, ) -> int { append(&ctx.fonts, Font{}) res := &ctx.fonts[len(ctx.fonts) - 1] @@ -335,7 +340,10 @@ AddFontMem :: proc( res.freeLoadedData = freeLoadedData res.name = strings.clone(name) - stbtt.InitFont(&res.info, &res.loadedData[0], 0) + num_fonts := stbtt.GetNumberOfFonts(raw_data(data)) + font_index_clamped := num_fonts > 0 ? clamp(i32(fontIndex), 0, num_fonts-1) : 0 + font_offset := stbtt.GetFontOffsetForIndex(raw_data(data), font_index_clamped) + stbtt.InitFont(&res.info, raw_data(data), font_offset) ascent, descent, line_gap: i32 stbtt.GetFontVMetrics(&res.info, &ascent, &descent, &line_gap) diff --git a/vendor/fontstash/fontstash_os.odin b/vendor/fontstash/fontstash_os.odin index ed453926f..d04df044c 100644 --- a/vendor/fontstash/fontstash_os.odin +++ b/vendor/fontstash/fontstash_os.odin @@ -4,17 +4,19 @@ package fontstash import "core:log" import "core:os" +// 'fontIndex' controls which font you want to load within a multi-font format such +// as TTC. Leave it as zero if you are loading a single-font format such as TTF. AddFontPath :: proc( ctx: ^FontContext, name: string, path: string, + fontIndex: int = 0, ) -> int { - data, ok := os.read_entire_file(path) + data, data_err := os.read_entire_file(path, context.allocator) - if !ok { + if data_err != nil { log.panicf("FONT: failed to read font at %s", path) } - return AddFontMem(ctx, name, data, true) -} - + return AddFontMem(ctx, name, data, true, fontIndex) +} \ No newline at end of file diff --git a/vendor/fontstash/fontstash_other.odin b/vendor/fontstash/fontstash_other.odin index edb76d9db..b0a0e2ab9 100644 --- a/vendor/fontstash/fontstash_other.odin +++ b/vendor/fontstash/fontstash_other.odin @@ -5,6 +5,7 @@ AddFontPath :: proc( ctx: ^FontContext, name: string, path: string, + fontIndex: int = 0, ) -> int { panic("fontstash.AddFontPath is unsupported on the JS target") } diff --git a/vendor/ggpo/ggpo.odin b/vendor/ggpo/ggpo.odin index 59321326a..01e03b6cb 100644 --- a/vendor/ggpo/ggpo.odin +++ b/vendor/ggpo/ggpo.odin @@ -1,4 +1,6 @@ /* +Bindings for [[ GGPO ; https://www.ggpo.net ]] rollback networking. + Created in 2009, the GGPO networking SDK pioneered the use of rollback networking in peer-to-peer games. It's designed specifically to hide network latency in fast paced, twitch style games which require very precise inputs and frame perfect execution. @@ -57,11 +59,11 @@ Player :: struct { type: PlayerType, player_num: c.int, using u: struct #raw_union { - local: struct {}, + local: struct {} `raw_union_tag:"type=.LOCAL"`, remote: struct { ip_address: [32]byte, port: u16, - }, + } `raw_union_tag:"type=.REMOTE"`, }, } @@ -130,28 +132,28 @@ Event :: struct { using u: struct #raw_union { connected: struct { player: PlayerHandle, - }, + } `raw_union_tag:"code=.CONNECTED_TO_PEER"`, synchronizing: struct { player: PlayerHandle, count: c.int, total: c.int, - }, + } `raw_union_tag:"code=.SYNCHRONIZING_WITH_PEER"`, synchronized: struct { player: PlayerHandle, - }, + } `raw_union_tag:"code=.SYNCHRONIZED_WITH_PEER"`, disconnected: struct { player: PlayerHandle, - }, + } `raw_union_tag:"code=.DISCONNECTED_FROM_PEER"`, timesync: struct { frames_ahead: c.int, - }, + } `raw_union_tag:"code=.TIMESYNC"`, connection_interrupted: struct { player: PlayerHandle, disconnect_timeout: c.int, - }, + } `raw_union_tag:"code=.connection_interrupted"`, connection_resumed: struct { player: PlayerHandle, - }, + } `raw_union_tag:"code=.connection_resumed"`, }, } diff --git a/vendor/glfw/bindings/bindings.odin b/vendor/glfw/bindings/bindings.odin index 75cdab4cd..3f2f08237 100644 --- a/vendor/glfw/bindings/bindings.odin +++ b/vendor/glfw/bindings/bindings.odin @@ -163,9 +163,9 @@ foreign glfw { SetJoystickUserPointer :: proc(jid: c.int, pointer: rawptr) --- GetJoystickUserPointer :: proc(jid: c.int) -> rawptr --- JoystickIsGamepad :: proc(jid: c.int) -> b32 --- - UpdateGamepadMappings :: proc(str: cstring) -> c.int --- + UpdateGamepadMappings :: proc(str: cstring) -> b32 --- GetGamepadName :: proc(jid: c.int) -> cstring --- - GetGamepadState :: proc(jid: c.int, state: ^GamepadState) -> c.int --- + GetGamepadState :: proc(jid: c.int, state: ^GamepadState) -> b32 --- SetClipboardString :: proc(window: WindowHandle, str: cstring) --- @@ -177,12 +177,12 @@ foreign glfw { MakeContextCurrent :: proc(window: WindowHandle) --- GetCurrentContext :: proc() -> WindowHandle --- GetProcAddress :: proc(name: cstring) -> rawptr --- - ExtensionSupported :: proc(extension: cstring) -> c.int --- + ExtensionSupported :: proc(extension: cstring) -> b32 --- VulkanSupported :: proc() -> b32 --- GetRequiredInstanceExtensions :: proc(count: ^u32) -> [^]cstring --- GetInstanceProcAddress :: proc(instance: vk.Instance, procname: cstring) -> rawptr --- - GetPhysicalDevicePresentationSupport :: proc(instance: vk.Instance, device: vk.PhysicalDevice, queuefamily: u32) -> c.int --- + GetPhysicalDevicePresentationSupport :: proc(instance: vk.Instance, device: vk.PhysicalDevice, queuefamily: u32) -> b32 --- CreateWindowSurface :: proc(instance: vk.Instance, window: WindowHandle, allocator: ^vk.AllocationCallbacks, surface: ^vk.SurfaceKHR) -> vk.Result --- SetWindowIconifyCallback :: proc(window: WindowHandle, cbfun: WindowIconifyProc) -> WindowIconifyProc --- @@ -212,9 +212,9 @@ foreign glfw { // Functions added in 3.4, Linux links against system glfw so we define these as weak to be able // to check at runtime if they are available. - @(linkage="weak") + @(linkage="strong" when ODIN_OS == .Windows else "weak") GetPlatform :: proc() -> c.int --- - @(linkage="weak") + @(linkage="strong" when ODIN_OS == .Windows else "weak") PlatformSupported :: proc(platform: c.int) -> b32 --- } diff --git a/vendor/glfw/types.odin b/vendor/glfw/types.odin index cfe810fe5..a89e0d1ba 100644 --- a/vendor/glfw/types.odin +++ b/vendor/glfw/types.odin @@ -1,3 +1,4 @@ +// Bindings for [[ GLFW ; https://www.glfw.org ]] package glfw import glfw "bindings" diff --git a/vendor/kb_text_shape/doc.odin b/vendor/kb_text_shape/doc.odin new file mode 100644 index 000000000..685b0d5a0 --- /dev/null +++ b/vendor/kb_text_shape/doc.odin @@ -0,0 +1,57 @@ +/* + Bindings for [[ Jimmy Lefevre's Text Shape ; https://github.com/JimmyLefevre/kb ]] Unicode text segmentation and OpenType shaping. + + Example: + // Basic + OdinAllocator := context.allocator + + FontData, _ := os.read_entire_file("myfonts.ttf", OdinAllocator) + + Context := kbts.CreateShapeContext(kbts.AllocatorFromOdinAllocator(&OdinAllocator)) + kbts.ShapePushFontFromMemory(Context, FontData, 0) + + kbts.ShapeBegin(Context, .DONT_KNOW, .DONT_KNOW) + kbts.ShapeUtf8(Context, "Let's shape something!", .CODEPOINT_INDEX) + kbts.ShapeEnd(Context) + + CursorX, CursorY: c.int = 0, 0 + for Run in kbts.ShapeRun(Context) { + Run := Run + for Glyph in kbts.GlyphIteratorNext(&Run.Glyphs) { + GlyphX := CursorX + Glyph.OffsetX + GlyphY := CursorY + Glyph.OffsetY + + DisplayGlyph(Glyph.Id, GlyphX, GlyphY) + + CursorX += Glyph.AdvanceX + CursorY += Glyph.AdvanceY + } + } + + Example: + // Font collections + OdinAllocator := context.allocator + + FontData, _ := os.read_entire_file("myfonts.ttf", OdinAllocator) + Font := kbts.FontFromMemory(FontData, 0, kbts.AllocatorFromOdinAllocator(&OdinAllocator)) + + _ = kbts.ShapePushFont(Context, &Font) + + FontCount := kbts.FontCount(FontData) + for FontIndex in 1.. c.int --- + PlaceShapeContext :: proc(Allocator: allocator_function, AllocatorData: rawptr, Memory: rawptr) -> ^shape_context --- + CreateShapeContext :: proc(Allocator: allocator_function, AllocatorData: rawptr) -> ^shape_context --- + DestroyShapeContext :: proc(Context: ^shape_context) --- + ShapePushFont :: proc(Context: ^shape_context, Font: ^font) -> ^font --- + ShapePopFont :: proc(Context: ^shape_context) -> ^font --- + ShapeBegin :: proc(Context: ^shape_context, ParagraphDirection: direction, Language: language) --- + ShapeEnd :: proc(Context: ^shape_context) --- + ShapePushFeature :: proc(Context: ^shape_context, FeatureTag: feature_tag, Value: c.int) --- + ShapePopFeature :: proc(Context: ^shape_context, FeatureTag: feature_tag) -> b32 --- + ShapeCodepoint :: proc(Context: ^shape_context, Codepoint: rune) --- + ShapeCodepointWithUserId :: proc(Context: ^shape_context, Codepoint: rune, UserId: c.int) --- + ShapeError :: proc(Context: ^shape_context) -> shape_error --- + ShapeBeginManualRuns :: proc(Context: ^shape_context) --- + ShapeNextManualRun :: proc(Context: ^shape_context, Direction: direction, Script: script) --- + ShapeEndManualRuns :: proc(Context: ^shape_context) --- + ShapeManualBreak :: proc(Context: ^shape_context) --- +} + +@(require_results) +PlaceShapeContextFixedMemory :: proc "c" (Memory: []byte) -> ^shape_context { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_PlaceShapeContextFixedMemory :: proc(Memory: rawptr, Size: c.int) -> ^shape_context --- + } + return kbts_PlaceShapeContextFixedMemory(raw_data(Memory), c.int(len(Memory))) +} + +ShapePushFontFromMemory :: proc "c" (Context: ^shape_context, Memory: []byte, FontIndex: c.int) -> ^font { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapePushFontFromMemory :: proc(Context: ^shape_context, Memory: rawptr, Size: c.int, FontIndex: c.int) -> ^font --- + } + return kbts_ShapePushFontFromMemory(Context, raw_data(Memory), c.int(len(Memory)), FontIndex) +} + +@(require_results) +ShapeRun :: proc "contextless" (Context: ^shape_context) -> (Run: run, Ok: b32) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeRun :: proc(Context: ^shape_context, Run: ^run) -> b32 --- + } + Ok = kbts_ShapeRun(Context, &Run) + return +} + +ShapeUtf32 :: proc "c" (Context: ^shape_context, Utf32: []rune) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeUtf32 :: proc(Context: ^shape_context, Utf32: [^]rune, Length: c.int) --- + } + kbts_ShapeUtf32(Context, raw_data(Utf32), c.int(len(Utf32))) +} +ShapeUtf32WithUserId :: proc "c" (Context: ^shape_context, Utf32: []rune, UserId: c.int, UserIdIncrement: c.int) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeUtf32WithUserId :: proc(Context: ^shape_context, Utf32: [^]rune, Length: c.int, UserId: c.int, UserIdIncrement: c.int) --- + } + kbts_ShapeUtf32WithUserId(Context, raw_data(Utf32), c.int(len(Utf32)), UserId, UserIdIncrement) +} + +ShapeUtf8 :: proc(Context: ^shape_context, Utf8: string, UserIdGenerationMode: user_id_generation_mode) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeUtf8 :: proc(Context: ^shape_context, Utf8: [^]byte, Length: c.int, UserIdGenerationMode: user_id_generation_mode) --- + } + kbts_ShapeUtf8(Context, raw_data(Utf8), c.int(len(Utf8)), UserIdGenerationMode) +} +ShapeUtf8WithUserId :: proc(Context: ^shape_context, Utf8: string, UserId: c.int, UserIdGenerationMode: user_id_generation_mode) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeUtf8WithUserId :: proc(Context: ^shape_context, Utf8: [^]byte, Length: c.int, UserId: c.int, UserIdGenerationMode: user_id_generation_mode) --- + } + kbts_ShapeUtf8WithUserId(Context, raw_data(Utf8), c.int(len(Utf8)), UserId, UserIdGenerationMode) +} + + +@(default_calling_convention="c", link_prefix="kbts_", require_results) +foreign lib { + ShapeCurrentCodepointsIterator :: proc(Context: ^shape_context) -> shape_codepoint_iterator --- + ShapeCodepointIteratorIsValid :: proc(It: ^shape_codepoint_iterator) -> b32 --- + ShapeGetShapeCodepoint :: proc(Context: ^shape_context, CodepointIndex: c.int, Codepoint: ^shape_codepoint) -> b32 --- +} + +@(require_results) +ShapeCodepointIteratorNext :: proc "contextless" (It: ^shape_codepoint_iterator) -> (Codepoint: shape_codepoint, CodepointIndex: c.int, Ok: b32) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeCodepointIteratorNext :: proc(It: ^shape_codepoint_iterator, Codepoint: ^shape_codepoint, CodepointIndex: ^c.int) -> b32 --- + } + Ok = kbts_ShapeCodepointIteratorNext(It, &Codepoint, &CodepointIndex) + return +} + + + +// +// Direct API +// +@(default_calling_convention="c", link_prefix="kbts_", require_results) +foreign lib { + FreeFont :: proc(Font: ^font) --- + FontIsValid :: proc(Font: ^font) -> b32 --- + PlaceBlob :: proc(Font: ^font, State: ^load_font_state, ScratchMemory: rawptr, OutputMemory: rawptr) -> load_font_error --- + GetFontInfo :: proc(Font: ^font, Info: ^font_info) --- + + // A shape_config is a bag of pre-computed data for a specific shaping setup. + SizeOfShapeConfig :: proc(Font: ^font, Script: script, Language: language) -> b32 --- + PlaceShapeConfig :: proc(Font: ^font, Script: script, Language: language, Memory: rawptr) -> ^shape_config --- + CreateShapeConfig :: proc(Font: ^font, Script: script, Language: language, Allocator: allocator_function, AllocatorData: rawptr) -> ^shape_config --- + DestroyShapeConfig :: proc(Config: ^shape_config) --- + + // A glyph_storage holds and recycles glyph data. + InitializeGlyphStorage :: proc(Storage: ^glyph_storage, Allocator: allocator_function, AllocatorData: rawptr) -> b32 --- + InitializeGlyphStorageFixedMemory :: proc(Storage: ^glyph_storage, Memory: rawptr, MemorySize: c.int) -> b32 --- + PushGlyph :: proc(Storage: ^glyph_storage, Font: ^font, Codepoint: rune, Config: ^glyph_config, UserId: c.int) -> ^glyph --- + ClearActiveGlyphs :: proc(Storage: ^glyph_storage) --- + FreeAllGlyphs :: proc(Storage: ^glyph_storage) --- + CodepointToGlyph :: proc(Font: ^font, Codepoint: rune, Config: ^glyph_config, UserId: c.int) -> glyph --- + CodepointToGlyphId :: proc(Font: ^font, Codepoint: rune) -> c.int --- + ActiveGlyphIterator :: proc(Storage: ^glyph_storage) -> glyph_iterator --- + + // A glyph_config specifies glyph-specific shaping parameters. + // A single glyph_config can be shared by multiple glyphs. + + DestroyGlyphConfig :: proc(Config: ^glyph_config) --- +} + +@(require_results) +LoadFont :: proc "contextless" (Font: ^font, State: ^load_font_state, FontData: []byte, FontIndex: c.int) -> (ScratchSize, OutputSize: c.int, Err: load_font_error) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_LoadFont :: proc(Font: ^font, State: ^load_font_state, FontData: rawptr, FontDataSize: c.int, FontIndex: c.int, ScratchSize_: ^c.int, OutputSize_: ^c.int) -> load_font_error --- + } + Err = kbts_LoadFont(Font, State, raw_data(FontData), c.int(len(FontData)), FontIndex, &ScratchSize, &OutputSize) + return +} + +@(require_results) +FontCount :: proc "c" (FileData: []byte) -> c.int { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_FontCount :: proc(FileData: rawptr, FileSize: c.int) -> c.int --- + } + return kbts_FontCount(raw_data(FileData), c.int(len(FileData))) +} + +@(require_results) +FontFromMemory :: proc "c" (FileData: []byte, FontIndex: c.int, Allocator: allocator_function, AllocatorData: rawptr) -> font { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_FontFromMemory :: proc(FileData: rawptr, FileSize: c.int, FontIndex: c.int, Allocator: allocator_function, AllocatorData: rawptr) -> font --- + } + return kbts_FontFromMemory(raw_data(FileData), c.int(len(FileData)), FontIndex, Allocator, AllocatorData) +} + + +@(require_results) +ShapeDirect :: proc "contextless" (Config: ^shape_config, Storage: ^glyph_storage, RunDirection: direction, Allocator: allocator_function, AllocatorData: rawptr) -> (Output: glyph_iterator, Err: shape_error) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeDirect :: proc(Config: ^shape_config, Storage: ^glyph_storage, RunDirection: direction, Allocator: allocator_function, AllocatorData: rawptr, Output: ^glyph_iterator) -> shape_error --- + } + Err = kbts_ShapeDirect(Config, Storage, RunDirection, Allocator, AllocatorData, &Output) + return +} + +@(require_results) +ShapeDirectFixedMemory :: proc "contextless" (Config: ^shape_config, Storage: ^glyph_storage, RunDirection: direction, Memory: rawptr, MemorySize: c.int) -> (Output: glyph_iterator, Err: shape_error) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_ShapeDirectFixedMemory :: proc(Config: ^shape_config, Storage: ^glyph_storage, RunDirection: direction, Memory: rawptr, MemorySize: c.int, Output: ^glyph_iterator) -> shape_error --- + } + Err = kbts_ShapeDirectFixedMemory(Config, Storage, RunDirection, Memory, MemorySize, &Output) + return +} + + +@(require_results) +SizeOfGlyphConfig :: proc "c" (Overrides: []feature_override) -> c.int { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_SizeOfGlyphConfig :: proc(Overrides: [^]feature_override, OverrideCount: c.int) -> c.int --- + } + return kbts_SizeOfGlyphConfig(raw_data(Overrides), c.int(len(Overrides))) +} + +@(require_results) +PlaceGlyphConfig :: proc "c" (Overrides: []feature_override, Memory: rawptr) -> ^glyph_config { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_PlaceGlyphConfig :: proc(Overrides: [^]feature_override, OverrideCount: c.int, Memory: rawptr) -> ^glyph_config --- + } + return kbts_PlaceGlyphConfig(raw_data(Overrides), c.int(len(Overrides)), Memory) +} + +@(require_results) +CreateGlyphConfig :: proc(Overrides: []feature_override, Allocator: allocator_function, AllocatorData: rawptr) -> ^glyph_config { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_CreateGlyphConfig :: proc(Overrides: [^]feature_override, OverrideCount: c.int, Allocator: allocator_function, AllocatorData: rawptr) -> ^glyph_config --- + } + return kbts_CreateGlyphConfig(raw_data(Overrides), c.int(len(Overrides)), Allocator, AllocatorData) +} + +@(default_calling_convention="c", link_prefix="kbts_", require_results) +foreign lib { + GlyphIteratorIsValid :: proc(It: ^glyph_iterator) -> b32 --- +} + +@(require_results) +GlyphIteratorNext :: proc "contextless" (It: ^glyph_iterator) -> (Glyph: ^glyph, Ok: b32) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_GlyphIteratorNext :: proc(It: ^glyph_iterator, Glyph: ^^glyph) -> b32 --- + } + Ok = kbts_GlyphIteratorNext(It, &Glyph) + return +} + + +// +// Segmentation +// +@(default_calling_convention="c", link_prefix="kbts_", require_results) +foreign lib { + BreakBegin :: proc(State: ^break_state, ParagraphDirection: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags) --- + BreakAddCodepoint :: proc(State: ^break_state, Codepoint: rune, PositionIncrement: c.int, EndOfText: b32) --- + BreakEnd :: proc(State: ^break_state) --- +} + +@(require_results) +Break :: proc "contextless" (State: ^break_state) -> (Break: break_type, Ok: b32) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_Break :: proc(State: ^break_state, Break: ^break_type) -> b32 --- + } + Ok = kbts_Break(State, &Break) + return +} + + +BreakEntireString :: proc "c" (Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Input: []byte, InputFormat: text_format, + Breaks: []break_type, BreakCount: ^c.int, + BreakFlags: []break_flags, BreakFlagCount: ^c.int) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_BreakEntireString :: proc(Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Input: rawptr, InputSizeInBytes: c.int, InputFormat: text_format, + Breaks: [^]break_type, BreakCapacity: c.int, BreakCount: ^c.int, + BreakFlags: [^]break_flags, BreakFlagCapacity: c.int, BreakFlagCount: ^c.int) --- + } + kbts_BreakEntireString(Direction, JapaneseLineBreakStyle, ConfigFlags, raw_data(Input), c.int(len(Input)), InputFormat, raw_data(Breaks), c.int(len(Breaks)), BreakCount, raw_data(BreakFlags), c.int(len(BreakFlags)), BreakFlagCount) +} + +BreakEntireStringUtf32 :: proc "c" (Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Utf32: []rune, + Breaks: []break_type, BreakCount: ^c.int, + BreakFlags: []break_flags, BreakFlagCount: ^c.int) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_BreakEntireStringUtf32 :: proc(Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Utf32: [^]rune, Utf32Count: c.int, + Breaks: [^]break_type, BreakCapacity: c.int, BreakCount: ^c.int, + BreakFlags: [^]break_flags, BreakFlagCapacity: c.int, BreakFlagCount: ^c.int) --- + } + kbts_BreakEntireStringUtf32(Direction, JapaneseLineBreakStyle, ConfigFlags, raw_data(Utf32), c.int(len(Utf32)), raw_data(Breaks), c.int(len(Breaks)), BreakCount, raw_data(BreakFlags), c.int(len(BreakFlags)), BreakFlagCount) +} + +BreakEntireStringUtf8 :: proc "c" (Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Utf8: string, + Breaks: []break_type, BreakCount: ^c.int, + BreakFlags: []break_flags, BreakFlagCount: ^c.int) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_BreakEntireStringUtf8 :: proc(Direction: direction, JapaneseLineBreakStyle: japanese_line_break_style, ConfigFlags: break_config_flags, + Utf8: [^]byte, Utf8Length: c.int, + Breaks: [^]break_type, BreakCapacity: c.int, BreakCount: ^c.int, + BreakFlags: [^]break_flags, BreakFlagCapacity: c.int, BreakFlagCount: ^c.int) --- + } + kbts_BreakEntireStringUtf8(Direction, JapaneseLineBreakStyle, ConfigFlags, raw_data(Utf8), c.int(len(Utf8)), raw_data(Breaks), c.int(len(Breaks)), BreakCount, raw_data(BreakFlags), c.int(len(BreakFlags)), BreakFlagCount) +} + + + +@(default_calling_convention="c", link_prefix="kbts_", require_results) +foreign lib { + // Quick test for font support of a sequence of codepoints. + FontCoverageTestBegin :: proc(Test: ^font_coverage_test, Font: ^font) --- + FontCoverageTestCodepoint :: proc(Test: ^font_coverage_test, Codepoint: rune) --- + FontCoverageTestEnd :: proc(Test: ^font_coverage_test) -> b32 --- + + ScriptDirection :: proc(Script: script) -> direction --- + ScriptIsComplex :: proc(Script: script) -> b32 --- + ScriptTagToScript :: proc(Tag: script_tag) -> script --- +} + +@(require_results) +EncodeUtf8 :: proc "c" (Codepoint: rune) -> (Encoded: [4]u8, EncodedLength: c.int, Valid: b32) { + return expand_values(kbts_EncodeUtf8(Codepoint)) +} + +@(default_calling_convention="c", require_results) +foreign lib { + kbts_EncodeUtf8 :: proc(Codepoint: rune) -> encode_utf8 --- +} + +@(require_results) +DecodeUtf8 :: proc "c" (Utf8: string) -> decode { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_DecodeUtf8 :: proc(Utf8: [^]byte, Length: un) -> decode --- + } + return kbts_DecodeUtf8(raw_data(Utf8), un(len(Utf8))) +} + +// This is a quick guess that stops at the first glyph that has a strong script/direction associated to it. +// It is convenient, but only works if you are sure your input text is mono-script and mono-direction. +@(require_results) +GuessTextProperties :: proc "contextless" (Text: []byte, Format: text_format) -> (Direction: direction, Script: script) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_GuessTextProperties :: proc(Text: rawptr, TextSizeInBytes: c.int, Format: text_format, Direction: ^direction, Script: ^script) --- + } + kbts_GuessTextProperties(raw_data(Text), c.int(len(Text)), Format, &Direction, &Script) + return +} + +// This is a quick guess that stops at the first glyph that has a strong script/direction associated to it. +// It is convenient, but only works if you are sure your input text is mono-script and mono-direction. +@(require_results) +GuessTextPropertiesUtf32 :: proc "contextless" (Utf32: []rune) -> (Direction: direction, Script: script) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_GuessTextPropertiesUtf32 :: proc(Utf32: [^]rune, Utf32Count: c.int, Direction: ^direction, Script: ^script) --- + } + kbts_GuessTextPropertiesUtf32(raw_data(Utf32), c.int(len(Utf32)), &Direction, &Script) + return +} + +// This is a quick guess that stops at the first glyph that has a strong script/direction associated to it. +// It is convenient, but only works if you are sure your input text is mono-script and mono-direction._results) +@(require_results) +GuessTextPropertiesUtf8 :: proc "contextless" (Utf8: string) -> (Direction: direction, Script: script) { + @(default_calling_convention="c", require_results) + foreign lib { + kbts_GuessTextPropertiesUtf8 :: proc(Utf8: cstring, Utf8Length: c.int, Direction: ^direction, Script: ^script) --- + } + kbts_GuessTextPropertiesUtf8(cstring(raw_data(Utf8)), c.int(len(Utf8)), &Direction, &Script) + return +} + + + + +@(require_results) +AllocatorFromOdinAllocator :: proc "contextless" (allocator: ^runtime.Allocator) -> (Allocator: allocator_function, AllocatorData: rawptr) { + allocator_function :: proc "c" (Data: rawptr, Op: ^allocator_op) { + if Data == nil { + return + } + context = runtime.default_context() + context.allocator = (^runtime.Allocator)(Data)^ + + switch Op.Kind { + case .NONE: + return + case .ALLOCATE: + res, _ := runtime.mem_alloc(int(Op.Allocate.Size), runtime.DEFAULT_ALIGNMENT) + Op.Allocate.Pointer = raw_data(res) + Op.Allocate.Size = u32(len(res)) + case .FREE: + _ = runtime.mem_free(Op.Free.Pointer) + } + } + + return allocator_function, rawptr(allocator) +} diff --git a/vendor/kb_text_shape/kb_text_shape_types.odin b/vendor/kb_text_shape/kb_text_shape_types.odin new file mode 100644 index 000000000..fa3c47f85 --- /dev/null +++ b/vendor/kb_text_shape/kb_text_shape_types.odin @@ -0,0 +1,2147 @@ +package vendor_kb_text_shape + +import "core:c" + +#assert(size_of(b8) == size_of(bool)) +#assert(size_of(b32) == size_of(u32)) +#assert(size_of(b32) == size_of(c.int)) + +un :: distinct ( + uint when (size_of(uintptr) == size_of(uint)) else + u32 when size_of(uintptr) == 4 else + u64 +) +// sn :: distinct ( +// int when (size_of(uintptr) == size_of(int)) else +// i32 when size_of(uintptr) == 4 else +// i64 +// ) + + +language :: enum u32 { + DONT_KNOW = 0, + + A_HMAO = 'H' | 'M'<<8 | 'D'<<16 | ' '<<24, + AARI = 'A' | 'R'<<8 | 'I'<<16 | ' '<<24, + ABAZA = 'A' | 'B'<<8 | 'A'<<16 | ' '<<24, + ABKHAZIAN = 'A' | 'B'<<8 | 'K'<<16 | ' '<<24, + ACHI = 'A' | 'C'<<8 | 'R'<<16 | ' '<<24, + ACHOLI = 'A' | 'C'<<8 | 'H'<<16 | ' '<<24, + ADYGHE = 'A' | 'D'<<8 | 'Y'<<16 | ' '<<24, + AFAR = 'A' | 'F'<<8 | 'R'<<16 | ' '<<24, + AFRIKAANS = 'A' | 'F'<<8 | 'K'<<16 | ' '<<24, + AGAW = 'A' | 'G'<<8 | 'W'<<16 | ' '<<24, + AITON = 'A' | 'I'<<8 | 'O'<<16 | ' '<<24, + AKAN = 'A' | 'K'<<8 | 'A'<<16 | ' '<<24, + ALBANIAN = 'S' | 'Q'<<8 | 'I'<<16 | ' '<<24, + ALSATIAN = 'A' | 'L'<<8 | 'S'<<16 | ' '<<24, + ALTAI = 'A' | 'L'<<8 | 'T'<<16 | ' '<<24, + ALUO = 'Y' | 'N'<<8 | 'A'<<16 | ' '<<24, + AMERICAN_PHONETIC = 'A' | 'P'<<8 | 'P'<<16 | 'H'<<24, + AMHARIC = 'A' | 'M'<<8 | 'H'<<16 | ' '<<24, + ANGLO_SAXON = 'A' | 'N'<<8 | 'G'<<16 | ' '<<24, + ARABIC = 'A' | 'R'<<8 | 'A'<<16 | ' '<<24, + ARAGONESE = 'A' | 'R'<<8 | 'G'<<16 | ' '<<24, + ARAKANESE = 'A' | 'R'<<8 | 'K'<<16 | ' '<<24, + ARAKWAL = 'R' | 'K'<<8 | 'W'<<16 | ' '<<24, + ARMENIAN = 'H' | 'Y'<<8 | 'E'<<16 | ' '<<24, + ARMENIAN_EAST = 'H' | 'Y'<<8 | 'E'<<16 | '0'<<24, + AROMANIAN = 'R' | 'U'<<8 | 'P'<<16 | ' '<<24, + ARPITAN = 'F' | 'R'<<8 | 'P'<<16 | ' '<<24, + ASSAMESE = 'A' | 'S'<<8 | 'M'<<16 | ' '<<24, + ASTURIAN = 'A' | 'S'<<8 | 'T'<<16 | ' '<<24, + ATHAPASKAN = 'A' | 'T'<<8 | 'H'<<16 | ' '<<24, + ATSINA = 'A' | 'T'<<8 | 'S'<<16 | ' '<<24, + AVAR = 'A' | 'V'<<8 | 'R'<<16 | ' '<<24, + AVATIME = 'A' | 'V'<<8 | 'N'<<16 | ' '<<24, + AWADHI = 'A' | 'W'<<8 | 'A'<<16 | ' '<<24, + AYMARA = 'A' | 'Y'<<8 | 'M'<<16 | ' '<<24, + AZERBAIDJANI = 'A' | 'Z'<<8 | 'E'<<16 | ' '<<24, + BADAGA = 'B' | 'A'<<8 | 'D'<<16 | ' '<<24, + BAGHELKHANDI = 'B' | 'A'<<8 | 'G'<<16 | ' '<<24, + BAGRI = 'B' | 'G'<<8 | 'Q'<<16 | ' '<<24, + BALANTE = 'B' | 'L'<<8 | 'N'<<16 | ' '<<24, + BALINESE = 'B' | 'A'<<8 | 'N'<<16 | ' '<<24, + BALKAR = 'B' | 'A'<<8 | 'L'<<16 | ' '<<24, + BALTI = 'B' | 'L'<<8 | 'T'<<16 | ' '<<24, + BALUCHI = 'B' | 'L'<<8 | 'I'<<16 | ' '<<24, + BAMBARA = 'B' | 'M'<<8 | 'B'<<16 | ' '<<24, + BAMILEKE = 'B' | 'M'<<8 | 'L'<<16 | ' '<<24, + BANDA = 'B' | 'A'<<8 | 'D'<<16 | '0'<<24, + BANDJALANG = 'B' | 'D'<<8 | 'Y'<<16 | ' '<<24, + BANGLA = 'B' | 'E'<<8 | 'N'<<16 | ' '<<24, + BASHKIR = 'B' | 'S'<<8 | 'H'<<16 | ' '<<24, + BASQUE = 'E' | 'U'<<8 | 'Q'<<16 | ' '<<24, + BATAK = 'B' | 'T'<<8 | 'K'<<16 | ' '<<24, + BATAK_ALAS_KLUET = 'B' | 'T'<<8 | 'Z'<<16 | ' '<<24, + BATAK_ANGKOLA = 'A' | 'K'<<8 | 'B'<<16 | ' '<<24, + BATAK_DAIRI = 'B' | 'T'<<8 | 'D'<<16 | ' '<<24, + BATAK_KARO = 'B' | 'T'<<8 | 'X'<<16 | ' '<<24, + BATAK_MANDAILING = 'B' | 'T'<<8 | 'M'<<16 | ' '<<24, + BATAK_SIMALUNGUN = 'B' | 'T'<<8 | 'S'<<16 | ' '<<24, + BATAK_TOBA = 'B' | 'B'<<8 | 'C'<<16 | ' '<<24, + BAULE = 'B' | 'A'<<8 | 'U'<<16 | ' '<<24, + BAVARIAN = 'B' | 'A'<<8 | 'R'<<16 | ' '<<24, + BELARUSIAN = 'B' | 'E'<<8 | 'L'<<16 | ' '<<24, + BEMBA = 'B' | 'E'<<8 | 'M'<<16 | ' '<<24, + BENCH = 'B' | 'C'<<8 | 'H'<<16 | ' '<<24, + BERBER = 'B' | 'B'<<8 | 'R'<<16 | ' '<<24, + BETI = 'B' | 'T'<<8 | 'I'<<16 | ' '<<24, + BETTE_KURUMA = 'X' | 'U'<<8 | 'B'<<16 | ' '<<24, + BHILI = 'B' | 'H'<<8 | 'I'<<16 | ' '<<24, + BHOJPURI = 'B' | 'H'<<8 | 'O'<<16 | ' '<<24, + BHUTANESE = 'D' | 'Z'<<8 | 'N'<<16 | ' '<<24, + BIBLE_CREE = 'B' | 'C'<<8 | 'R'<<16 | ' '<<24, + BIKOL = 'B' | 'I'<<8 | 'K'<<16 | ' '<<24, + BILEN = 'B' | 'I'<<8 | 'L'<<16 | ' '<<24, + BISHNUPRIYA_MANIPURI = 'B' | 'P'<<8 | 'Y'<<16 | ' '<<24, + BISLAMA = 'B' | 'I'<<8 | 'S'<<16 | ' '<<24, + BLACKFOOT = 'B' | 'K'<<8 | 'F'<<16 | ' '<<24, + BODO = 'B' | 'R'<<8 | 'X'<<16 | ' '<<24, + BOSNIAN = 'B' | 'O'<<8 | 'S'<<16 | ' '<<24, + BOUYEI = 'P' | 'C'<<8 | 'C'<<16 | ' '<<24, + BRAHUI = 'B' | 'R'<<8 | 'H'<<16 | ' '<<24, + BRAJ_BHASHA = 'B' | 'R'<<8 | 'I'<<16 | ' '<<24, + BRETON = 'B' | 'R'<<8 | 'E'<<16 | ' '<<24, + BUGIS = 'B' | 'U'<<8 | 'G'<<16 | ' '<<24, + BULGARIAN = 'B' | 'G'<<8 | 'R'<<16 | ' '<<24, + BUMTHANGKHA = 'K' | 'J'<<8 | 'Z'<<16 | ' '<<24, + BURMESE = 'B' | 'R'<<8 | 'M'<<16 | ' '<<24, + BURUSHASKI = 'B' | 'S'<<8 | 'K'<<16 | ' '<<24, + CAJUN_FRENCH = 'F' | 'R'<<8 | 'C'<<16 | ' '<<24, + CARRIER = 'C' | 'R'<<8 | 'R'<<16 | ' '<<24, + CATALAN = 'C' | 'A'<<8 | 'T'<<16 | ' '<<24, + CAYUGA = 'C' | 'A'<<8 | 'Y'<<16 | ' '<<24, + CEBUANO = 'C' | 'E'<<8 | 'B'<<16 | ' '<<24, + CENTRAL_YUPIK = 'E' | 'S'<<8 | 'U'<<16 | ' '<<24, + CHAHA_GURAGE = 'C' | 'H'<<8 | 'G'<<16 | ' '<<24, + CHAMORRO = 'C' | 'H'<<8 | 'A'<<16 | ' '<<24, + CHATTISGARHI = 'C' | 'H'<<8 | 'H'<<16 | ' '<<24, + CHECHEN = 'C' | 'H'<<8 | 'E'<<16 | ' '<<24, + CHEROKEE = 'C' | 'H'<<8 | 'R'<<16 | ' '<<24, + CHEYENNE = 'C' | 'H'<<8 | 'Y'<<16 | ' '<<24, + CHICHEWA = 'C' | 'H'<<8 | 'I'<<16 | ' '<<24, + CHIGA = 'C' | 'G'<<8 | 'G'<<16 | ' '<<24, + CHIMILA = 'C' | 'B'<<8 | 'G'<<16 | ' '<<24, + CHIN = 'Q' | 'I'<<8 | 'N'<<16 | ' '<<24, + CHINANTEC = 'C' | 'C'<<8 | 'H'<<16 | 'N'<<24, + CHINESE_PHONETIC = 'Z' | 'H'<<8 | 'P'<<16 | ' '<<24, + CHINESE_SIMPLIFIED = 'Z' | 'H'<<8 | 'S'<<16 | ' '<<24, + CHINESE_TRADITIONAL = 'Z' | 'H'<<8 | 'T'<<16 | ' '<<24, + CHINESE_TRADITIONAL_HONG_KONG = 'Z' | 'H'<<8 | 'H'<<16 | ' '<<24, + CHINESE_TRADITIONAL_MACAO = 'Z' | 'H'<<8 | 'T'<<16 | 'M'<<24, + CHIPEWYAN = 'C' | 'H'<<8 | 'P'<<16 | ' '<<24, + CHITTAGONIAN = 'C' | 'T'<<8 | 'G'<<16 | ' '<<24, + CHOCTAW = 'C' | 'H'<<8 | 'O'<<16 | ' '<<24, + CHUKCHI = 'C' | 'H'<<8 | 'K'<<16 | ' '<<24, + CHURCH_SLAVONIC = 'C' | 'S'<<8 | 'L'<<16 | ' '<<24, + CHUUKESE = 'C' | 'H'<<8 | 'K'<<16 | '0'<<24, + CHUVASH = 'C' | 'H'<<8 | 'U'<<16 | ' '<<24, + COMORIAN = 'C' | 'M'<<8 | 'R'<<16 | ' '<<24, + COMOX = 'C' | 'O'<<8 | 'O'<<16 | ' '<<24, + COPTIC = 'C' | 'O'<<8 | 'P'<<16 | ' '<<24, + CORNISH = 'C' | 'O'<<8 | 'R'<<16 | ' '<<24, + CORSICAN = 'C' | 'O'<<8 | 'S'<<16 | ' '<<24, + CREE = 'C' | 'R'<<8 | 'E'<<16 | ' '<<24, + CREOLES = 'C' | 'P'<<8 | 'P'<<16 | ' '<<24, + CRIMEAN_TATAR = 'C' | 'R'<<8 | 'T'<<16 | ' '<<24, + CRIOULO = 'K' | 'E'<<8 | 'A'<<16 | ' '<<24, + CROATIAN = 'H' | 'R'<<8 | 'V'<<16 | ' '<<24, + CYPRIOT_ARABIC = 'A' | 'C'<<8 | 'Y'<<16 | ' '<<24, + CZECH = 'C' | 'S'<<8 | 'Y'<<16 | ' '<<24, + DAGBANI = 'D' | 'A'<<8 | 'G'<<16 | ' '<<24, + DAN = 'D' | 'N'<<8 | 'J'<<16 | ' '<<24, + DANGME = 'D' | 'N'<<8 | 'G'<<16 | ' '<<24, + DANISH = 'D' | 'A'<<8 | 'N'<<16 | ' '<<24, + DARGWA = 'D' | 'A'<<8 | 'R'<<16 | ' '<<24, + DARI = 'D' | 'R'<<8 | 'I'<<16 | ' '<<24, + DAYI = 'D' | 'A'<<8 | 'X'<<16 | ' '<<24, + DEFAULT = 'd' | 'f'<<8 | 'l'<<16 | 't'<<24, // Can be DFLT too. + DEHONG_DAI = 'T' | 'D'<<8 | 'D'<<16 | ' '<<24, + DHANGU = 'D' | 'H'<<8 | 'G'<<16 | ' '<<24, + DHIVEHI = 'D' | 'I'<<8 | 'V'<<16 | ' '<<24, + DHUWAL = 'D' | 'U'<<8 | 'J'<<16 | ' '<<24, + DIMLI = 'D' | 'I'<<8 | 'Q'<<16 | ' '<<24, + DINKA = 'D' | 'N'<<8 | 'K'<<16 | ' '<<24, + DIVEHI = 'D' | 'I'<<8 | 'V'<<16 | ' '<<24, + DJAMBARRPUYNGU = 'D' | 'J'<<8 | 'R'<<16 | '0'<<24, + DOGRI = 'D' | 'G'<<8 | 'O'<<16 | ' '<<24, + DOGRI_MACROLANGUAGE = 'D' | 'G'<<8 | 'R'<<16 | ' '<<24, + DUNGAN = 'D' | 'U'<<8 | 'N'<<16 | ' '<<24, + DUTCH = 'N' | 'L'<<8 | 'D'<<16 | ' '<<24, + DZONGKHA = 'D' | 'Z'<<8 | 'N'<<16 | ' '<<24, + EASTERN_ABENAKI = 'A' | 'A'<<8 | 'Q'<<16 | ' '<<24, + EASTERN_CHAM = 'C' | 'J'<<8 | 'M'<<16 | ' '<<24, + EASTERN_CREE = 'E' | 'C'<<8 | 'R'<<16 | ' '<<24, + EASTERN_MANINKAKAN = 'E' | 'M'<<8 | 'K'<<16 | ' '<<24, + EASTERN_PWO_KAREN = 'K' | 'J'<<8 | 'P'<<16 | ' '<<24, + EBIRA = 'E' | 'B'<<8 | 'I'<<16 | ' '<<24, + EDO = 'E' | 'D'<<8 | 'O'<<16 | ' '<<24, + EFIK = 'E' | 'F'<<8 | 'I'<<16 | ' '<<24, + EMBERA_BAUDO = 'B' | 'D'<<8 | 'C'<<16 | ' '<<24, + EMBERA_CATIO = 'C' | 'T'<<8 | 'O'<<16 | ' '<<24, + EMBERA_CHAMI = 'C' | 'M'<<8 | 'I'<<16 | ' '<<24, + EMBERA_TADO = 'T' | 'D'<<8 | 'C'<<16 | ' '<<24, + ENGLISH = 'E' | 'N'<<8 | 'G'<<16 | ' '<<24, + EPENA = 'S' | 'J'<<8 | 'A'<<16 | ' '<<24, + ERZYA = 'E' | 'R'<<8 | 'Z'<<16 | ' '<<24, + KB_TEXT_SHAPEANTO = 'N' | 'T'<<8 | 'O'<<16 | ' '<<24, + ESTONIAN = 'E' | 'T'<<8 | 'I'<<16 | ' '<<24, + EVEN = 'E' | 'V'<<8 | 'N'<<16 | ' '<<24, + EVENKI = 'E' | 'V'<<8 | 'K'<<16 | ' '<<24, + EWE = 'E' | 'W'<<8 | 'E'<<16 | ' '<<24, + FALAM_CHIN = 'H' | 'A'<<8 | 'L'<<16 | ' '<<24, + FANG = 'F' | 'A'<<8 | 'N'<<16 | '0'<<24, + FANTI = 'F' | 'A'<<8 | 'T'<<16 | ' '<<24, + FAROESE = 'F' | 'O'<<8 | 'S'<<16 | ' '<<24, + FEFE = 'F' | 'M'<<8 | 'P'<<16 | ' '<<24, + FIJIAN = 'F' | 'J'<<8 | 'I'<<16 | ' '<<24, + FILIPINO = 'P' | 'I'<<8 | 'L'<<16 | ' '<<24, + FINNISH = 'F' | 'I'<<8 | 'N'<<16 | ' '<<24, + FLEMISH = 'F' | 'L'<<8 | 'E'<<16 | ' '<<24, + FON = 'F' | 'O'<<8 | 'N'<<16 | ' '<<24, + FOREST_ENETS = 'F' | 'N'<<8 | 'E'<<16 | ' '<<24, + FRENCH = 'F' | 'R'<<8 | 'A'<<16 | ' '<<24, + FRENCH_ANTILLEAN = 'F' | 'A'<<8 | 'N'<<16 | ' '<<24, + FRISIAN = 'F' | 'R'<<8 | 'I'<<16 | ' '<<24, + FRIULIAN = 'F' | 'R'<<8 | 'L'<<16 | ' '<<24, + FULAH = 'F' | 'U'<<8 | 'L'<<16 | ' '<<24, + FUTA = 'F' | 'T'<<8 | 'A'<<16 | ' '<<24, + GA = 'G' | 'A'<<8 | 'D'<<16 | ' '<<24, + GAGAUZ = 'G' | 'A'<<8 | 'G'<<16 | ' '<<24, + GALICIAN = 'G' | 'A'<<8 | 'L'<<16 | ' '<<24, + GANDA = 'L' | 'U'<<8 | 'G'<<16 | ' '<<24, + GARHWALI = 'G' | 'A'<<8 | 'W'<<16 | ' '<<24, + GARO = 'G' | 'R'<<8 | 'O'<<16 | ' '<<24, + GARSHUNI = 'G' | 'A'<<8 | 'R'<<16 | ' '<<24, + GEBA_KAREN = 'K' | 'V'<<8 | 'Q'<<16 | ' '<<24, + GEEZ = 'G' | 'E'<<8 | 'Z'<<16 | ' '<<24, + GEORGIAN = 'K' | 'A'<<8 | 'T'<<16 | ' '<<24, + GEPO = 'Y' | 'G'<<8 | 'P'<<16 | ' '<<24, + GERMAN = 'D' | 'E'<<8 | 'U'<<16 | ' '<<24, + GIKUYU = 'K' | 'I'<<8 | 'K'<<16 | ' '<<24, + GILAKI = 'G' | 'L'<<8 | 'K'<<16 | ' '<<24, + GILBERTESE = 'G' | 'I'<<8 | 'L'<<16 | '0'<<24, + GILYAK = 'G' | 'I'<<8 | 'L'<<16 | ' '<<24, + GITHABUL = 'G' | 'I'<<8 | 'H'<<16 | ' '<<24, + GOGO = 'G' | 'O'<<8 | 'G'<<16 | ' '<<24, + GONDI = 'G' | 'O'<<8 | 'N'<<16 | ' '<<24, + GREEK = 'E' | 'L'<<8 | 'L'<<16 | ' '<<24, + GREENLANDIC = 'G' | 'R'<<8 | 'N'<<16 | ' '<<24, + GUARANI = 'G' | 'U'<<8 | 'A'<<16 | ' '<<24, + GUINEA = 'G' | 'K'<<8 | 'P'<<16 | ' '<<24, + GUJARATI = 'G' | 'U'<<8 | 'J'<<16 | ' '<<24, + GUMATJ = 'G' | 'N'<<8 | 'N'<<16 | ' '<<24, + GUMUZ = 'G' | 'M'<<8 | 'Z'<<16 | ' '<<24, + GUPAPUYNGU = 'G' | 'U'<<8 | 'F'<<16 | ' '<<24, + GUSII = 'G' | 'U'<<8 | 'Z'<<16 | ' '<<24, + HAIDA = 'H' | 'A'<<8 | 'I'<<16 | '0'<<24, + HAITIAN_CREOLE = 'H' | 'A'<<8 | 'I'<<16 | ' '<<24, + HALKOMELEM = 'H' | 'U'<<8 | 'R'<<16 | ' '<<24, + HAMMER_BANNA = 'H' | 'B'<<8 | 'N'<<16 | ' '<<24, + HARARI = 'H' | 'R'<<8 | 'I'<<16 | ' '<<24, + HARAUTI = 'H' | 'A'<<8 | 'R'<<16 | ' '<<24, + HARYANVI = 'B' | 'G'<<8 | 'C'<<16 | ' '<<24, + HAUSA = 'H' | 'A'<<8 | 'U'<<16 | ' '<<24, + HAVASUPAI_WALAPAI_YAVAPAI = 'Y' | 'U'<<8 | 'F'<<16 | ' '<<24, + HAWAIIAN = 'H' | 'A'<<8 | 'W'<<16 | ' '<<24, + HAYA = 'H' | 'A'<<8 | 'Y'<<16 | ' '<<24, + HAZARAGI = 'H' | 'A'<<8 | 'Z'<<16 | ' '<<24, + HEBREW = 'I' | 'W'<<8 | 'R'<<16 | ' '<<24, + HEILTSUK = 'H' | 'E'<<8 | 'I'<<16 | ' '<<24, + HERERO = 'H' | 'E'<<8 | 'R'<<16 | ' '<<24, + HIGH_MARI = 'H' | 'M'<<8 | 'A'<<16 | ' '<<24, + HILIGAYNON = 'H' | 'I'<<8 | 'L'<<16 | ' '<<24, + HINDI = 'H' | 'I'<<8 | 'N'<<16 | ' '<<24, + HINDKO = 'H' | 'N'<<8 | 'D'<<16 | ' '<<24, + HIRI_MOTU = 'H' | 'M'<<8 | 'O'<<16 | ' '<<24, + HMONG = 'H' | 'M'<<8 | 'N'<<16 | ' '<<24, + HMONG_DAW = 'M' | 'W'<<8 | 'W'<<16 | ' '<<24, + HMONG_SHUAT = 'H' | 'M'<<8 | 'Z'<<16 | ' '<<24, + HO = 'H' | 'O'<<8 | ' '<<16 | ' '<<24, + HUNGARIAN = 'H' | 'U'<<8 | 'N'<<16 | ' '<<24, + IBAN = 'I' | 'B'<<8 | 'A'<<16 | ' '<<24, + IBIBIO = 'I' | 'B'<<8 | 'B'<<16 | ' '<<24, + ICELANDIC = 'I' | 'S'<<8 | 'L'<<16 | ' '<<24, + IDO = 'I' | 'D'<<8 | 'O'<<16 | ' '<<24, + IGBO = 'I' | 'B'<<8 | 'O'<<16 | ' '<<24, + IJO = 'I' | 'J'<<8 | 'O'<<16 | ' '<<24, + ILOKANO = 'I' | 'L'<<8 | 'O'<<16 | ' '<<24, + INARI_SAMI = 'I' | 'S'<<8 | 'M'<<16 | ' '<<24, + INDONESIAN = 'I' | 'N'<<8 | 'D'<<16 | ' '<<24, + INGUSH = 'I' | 'N'<<8 | 'G'<<16 | ' '<<24, + INTERLINGUA = 'I' | 'N'<<8 | 'A'<<16 | ' '<<24, + INTERLINGUE = 'I' | 'L'<<8 | 'E'<<16 | ' '<<24, + INUKTITUT = 'I' | 'N'<<8 | 'U'<<16 | ' '<<24, + INUPIAT = 'I' | 'P'<<8 | 'K'<<16 | ' '<<24, + IPA_PHONETIC = 'I' | 'P'<<8 | 'P'<<16 | ' '<<24, + IRISH = 'I' | 'R'<<8 | 'I'<<16 | ' '<<24, + IRISH_TRADITIONAL = 'I' | 'R'<<8 | 'T'<<16 | ' '<<24, + IRULA = 'I' | 'R'<<8 | 'U'<<16 | ' '<<24, + ITALIAN = 'I' | 'T'<<8 | 'A'<<16 | ' '<<24, + JAMAICAN_CREOLE = 'J' | 'A'<<8 | 'M'<<16 | ' '<<24, + JAPANESE = 'J' | 'A'<<8 | 'N'<<16 | ' '<<24, + JAVANESE = 'J' | 'A'<<8 | 'V'<<16 | ' '<<24, + JENNU_KURUMA = 'X' | 'U'<<8 | 'J'<<16 | ' '<<24, + JUDEO_TAT = 'J' | 'D'<<8 | 'T'<<16 | ' '<<24, + JULA = 'J' | 'U'<<8 | 'L'<<16 | ' '<<24, + KABARDIAN = 'K' | 'A'<<8 | 'B'<<16 | ' '<<24, + KABYLE = 'K' | 'A'<<8 | 'B'<<16 | '0'<<24, + KACHCHI = 'K' | 'A'<<8 | 'C'<<16 | ' '<<24, + KADIWEU = 'K' | 'B'<<8 | 'C'<<16 | ' '<<24, + KALENJIN = 'K' | 'A'<<8 | 'L'<<16 | ' '<<24, + KALMYK = 'K' | 'L'<<8 | 'M'<<16 | ' '<<24, + KAMBA = 'K' | 'M'<<8 | 'B'<<16 | ' '<<24, + KANAUJI = 'B' | 'J'<<8 | 'J'<<16 | ' '<<24, + KANNADA = 'K' | 'A'<<8 | 'N'<<16 | ' '<<24, + KANURI = 'K' | 'N'<<8 | 'R'<<16 | ' '<<24, + KAQCHIKEL = 'C' | 'A'<<8 | 'K'<<16 | ' '<<24, + KARACHAY = 'K' | 'A'<<8 | 'R'<<16 | ' '<<24, + KARAIM = 'K' | 'R'<<8 | 'M'<<16 | ' '<<24, + KARAKALPAK = 'K' | 'R'<<8 | 'K'<<16 | ' '<<24, + KARELIAN = 'K' | 'R'<<8 | 'L'<<16 | ' '<<24, + KAREN = 'K' | 'R'<<8 | 'N'<<16 | ' '<<24, + KASHMIRI = 'K' | 'S'<<8 | 'H'<<16 | ' '<<24, + KASHUBIAN = 'C' | 'S'<<8 | 'B'<<16 | ' '<<24, + KATE = 'K' | 'M'<<8 | 'G'<<16 | ' '<<24, + KAZAKH = 'K' | 'A'<<8 | 'Z'<<16 | ' '<<24, + KEBENA = 'K' | 'E'<<8 | 'B'<<16 | ' '<<24, + KEKCHI = 'K' | 'E'<<8 | 'K'<<16 | ' '<<24, + KHAKASS = 'K' | 'H'<<8 | 'A'<<16 | ' '<<24, + KHAMTI_SHAN = 'K' | 'H'<<8 | 'T'<<16 | ' '<<24, + KHAMYANG = 'K' | 'S'<<8 | 'U'<<16 | ' '<<24, + KHANTY_KAZIM = 'K' | 'H'<<8 | 'K'<<16 | ' '<<24, + KHANTY_SHURISHKAR = 'K' | 'H'<<8 | 'S'<<16 | ' '<<24, + KHANTY_VAKHI = 'K' | 'H'<<8 | 'V'<<16 | ' '<<24, + KHASI = 'K' | 'S'<<8 | 'I'<<16 | ' '<<24, + KHENGKHA = 'X' | 'K'<<8 | 'F'<<16 | ' '<<24, + KHINALUG = 'K' | 'J'<<8 | 'J'<<16 | ' '<<24, + KHMER = 'K' | 'H'<<8 | 'M'<<16 | ' '<<24, + KHORASANI_TURKIC = 'K' | 'M'<<8 | 'Z'<<16 | ' '<<24, + KHOWAR = 'K' | 'H'<<8 | 'W'<<16 | ' '<<24, + KHUTSURI_GEORGIAN = 'K' | 'G'<<8 | 'E'<<16 | ' '<<24, + KICHE = 'Q' | 'U'<<8 | 'C'<<16 | ' '<<24, + KIKONGO = 'K' | 'O'<<8 | 'N'<<16 | ' '<<24, + KILDIN_SAMI = 'K' | 'S'<<8 | 'M'<<16 | ' '<<24, + KINYARWANDA = 'R' | 'U'<<8 | 'A'<<16 | ' '<<24, + KIRMANJKI = 'K' | 'I'<<8 | 'U'<<16 | ' '<<24, + KISII = 'K' | 'I'<<8 | 'S'<<16 | ' '<<24, + KITUBA = 'M' | 'K'<<8 | 'W'<<16 | ' '<<24, + KODAGU = 'K' | 'O'<<8 | 'D'<<16 | ' '<<24, + KOKNI = 'K' | 'K'<<8 | 'N'<<16 | ' '<<24, + KOMI = 'K' | 'O'<<8 | 'M'<<16 | ' '<<24, + KOMI_PERMYAK = 'K' | 'O'<<8 | 'P'<<16 | ' '<<24, + KOMI_ZYRIAN = 'K' | 'O'<<8 | 'Z'<<16 | ' '<<24, + KOMO = 'K' | 'M'<<8 | 'O'<<16 | ' '<<24, + KOMSO = 'K' | 'M'<<8 | 'S'<<16 | ' '<<24, + KONGO = 'K' | 'O'<<8 | 'N'<<16 | '0'<<24, + KONKANI = 'K' | 'O'<<8 | 'K'<<16 | ' '<<24, + KOORETE = 'K' | 'R'<<8 | 'T'<<16 | ' '<<24, + KOREAN = 'K' | 'O'<<8 | 'R'<<16 | ' '<<24, + KOREAO_OLD_HANGUL = 'K' | 'O'<<8 | 'H'<<16 | ' '<<24, + KORYAK = 'K' | 'Y'<<8 | 'K'<<16 | ' '<<24, + KOSRAEAN = 'K' | 'O'<<8 | 'S'<<16 | ' '<<24, + KPELLE = 'K' | 'P'<<8 | 'L'<<16 | ' '<<24, + KPELLE_LIBERIA = 'X' | 'P'<<8 | 'E'<<16 | ' '<<24, + KRIO = 'K' | 'R'<<8 | 'I'<<16 | ' '<<24, + KRYMCHAK = 'J' | 'C'<<8 | 'T'<<16 | ' '<<24, + KUANYAMA = 'K' | 'U'<<8 | 'A'<<16 | ' '<<24, + KUBE = 'K' | 'G'<<8 | 'F'<<16 | ' '<<24, + KUI = 'K' | 'U'<<8 | 'I'<<16 | ' '<<24, + KULVI = 'K' | 'U'<<8 | 'K'<<16 | ' '<<24, + KUMAONI = 'K' | 'M'<<8 | 'N'<<16 | ' '<<24, + KUMYK = 'K' | 'U'<<8 | 'M'<<16 | ' '<<24, + KURDISH = 'K' | 'U'<<8 | 'R'<<16 | ' '<<24, + KURUKH = 'K' | 'U'<<8 | 'U'<<16 | ' '<<24, + KUY = 'K' | 'U'<<8 | 'Y'<<16 | ' '<<24, + KWAKWALA = 'K' | 'W'<<8 | 'K'<<16 | ' '<<24, + KYRGYZ = 'K' | 'I'<<8 | 'R'<<16 | ' '<<24, + L_CREE = 'L' | 'C'<<8 | 'R'<<16 | ' '<<24, + LADAKHI = 'L' | 'D'<<8 | 'K'<<16 | ' '<<24, + LADIN = 'L' | 'A'<<8 | 'D'<<16 | ' '<<24, + LADINO = 'J' | 'U'<<8 | 'D'<<16 | ' '<<24, + LAHULI = 'L' | 'A'<<8 | 'H'<<16 | ' '<<24, + LAK = 'L' | 'A'<<8 | 'K'<<16 | ' '<<24, + LAKI = 'L' | 'K'<<8 | 'I'<<16 | ' '<<24, + LAMBANI = 'L' | 'A'<<8 | 'M'<<16 | ' '<<24, + LAMPUNG = 'L' | 'J'<<8 | 'P'<<16 | ' '<<24, + LAO = 'L' | 'A'<<8 | 'O'<<16 | ' '<<24, + LATIN = 'L' | 'A'<<8 | 'T'<<16 | ' '<<24, + LATVIAN = 'L' | 'V'<<8 | 'I'<<16 | ' '<<24, + LAZ = 'L' | 'A'<<8 | 'Z'<<16 | ' '<<24, + LELEMI = 'L' | 'E'<<8 | 'F'<<16 | ' '<<24, + LEZGI = 'L' | 'E'<<8 | 'Z'<<16 | ' '<<24, + LIGURIAN = 'L' | 'I'<<8 | 'J'<<16 | ' '<<24, + LIMBU = 'L' | 'M'<<8 | 'B'<<16 | ' '<<24, + LIMBURGISH = 'L' | 'I'<<8 | 'M'<<16 | ' '<<24, + LINGALA = 'L' | 'I'<<8 | 'N'<<16 | ' '<<24, + LIPO = 'L' | 'P'<<8 | 'O'<<16 | ' '<<24, + LISU = 'L' | 'I'<<8 | 'S'<<16 | ' '<<24, + LITHUANIAN = 'L' | 'T'<<8 | 'H'<<16 | ' '<<24, + LIV = 'L' | 'I'<<8 | 'V'<<16 | ' '<<24, + LOJBAN = 'J' | 'B'<<8 | 'O'<<16 | ' '<<24, + LOMA = 'L' | 'O'<<8 | 'M'<<16 | ' '<<24, + LOMBARD = 'L' | 'M'<<8 | 'O'<<16 | ' '<<24, + LOMWE = 'L' | 'M'<<8 | 'W'<<16 | ' '<<24, + LOW_MARI = 'L' | 'M'<<8 | 'A'<<16 | ' '<<24, + LOW_SAXON = 'N' | 'D'<<8 | 'S'<<16 | ' '<<24, + LOWER_SORBIAN = 'L' | 'S'<<8 | 'B'<<16 | ' '<<24, + LU = 'X' | 'B'<<8 | 'D'<<16 | ' '<<24, + LUBA_KATANGA = 'L' | 'U'<<8 | 'B'<<16 | ' '<<24, + LUBA_LULUA = 'L' | 'U'<<8 | 'A'<<16 | ' '<<24, + LULE_SAMI = 'L' | 'S'<<8 | 'M'<<16 | ' '<<24, + LUO = 'L' | 'U'<<8 | 'O'<<16 | ' '<<24, + LURI = 'L' | 'R'<<8 | 'C'<<16 | ' '<<24, + LUSHOOTSEED = 'L' | 'U'<<8 | 'T'<<16 | ' '<<24, + LUXEMBOURGISH = 'L' | 'T'<<8 | 'Z'<<16 | ' '<<24, + LUYIA = 'L' | 'U'<<8 | 'H'<<16 | ' '<<24, + MACEDONIAN = 'M' | 'K'<<8 | 'D'<<16 | ' '<<24, + MADURA = 'M' | 'A'<<8 | 'D'<<16 | ' '<<24, + MAGAHI = 'M' | 'A'<<8 | 'G'<<16 | ' '<<24, + MAITHILI = 'M' | 'T'<<8 | 'H'<<16 | ' '<<24, + MAJANG = 'M' | 'A'<<8 | 'J'<<16 | ' '<<24, + MAKASAR = 'M' | 'K'<<8 | 'R'<<16 | ' '<<24, + MAKHUWA = 'M' | 'A'<<8 | 'K'<<16 | ' '<<24, + MAKONDE = 'K' | 'D'<<8 | 'E'<<16 | ' '<<24, + MALAGASY = 'M' | 'L'<<8 | 'G'<<16 | ' '<<24, + MALAY = 'M' | 'L'<<8 | 'Y'<<16 | ' '<<24, + MALAYALAM = 'M' | 'A'<<8 | 'L'<<16 | ' '<<24, + MALAYALAM_REFORMED = 'M' | 'L'<<8 | 'R'<<16 | ' '<<24, + MALE = 'M' | 'L'<<8 | 'E'<<16 | ' '<<24, + MALINKE = 'M' | 'L'<<8 | 'N'<<16 | ' '<<24, + MALTESE = 'M' | 'T'<<8 | 'S'<<16 | ' '<<24, + MAM = 'M' | 'A'<<8 | 'M'<<16 | ' '<<24, + MANCHU = 'M' | 'C'<<8 | 'H'<<16 | ' '<<24, + MANDAR = 'M' | 'D'<<8 | 'R'<<16 | ' '<<24, + MANDINKA = 'M' | 'N'<<8 | 'D'<<16 | ' '<<24, + MANINKA = 'M' | 'N'<<8 | 'K'<<16 | ' '<<24, + MANIPURI = 'M' | 'N'<<8 | 'I'<<16 | ' '<<24, + MANO = 'M' | 'E'<<8 | 'V'<<16 | ' '<<24, + MANSI = 'M' | 'A'<<8 | 'N'<<16 | ' '<<24, + MANX = 'M' | 'N'<<8 | 'X'<<16 | ' '<<24, + MAORI = 'M' | 'R'<<8 | 'I'<<16 | ' '<<24, + MAPUDUNGUN = 'M' | 'A'<<8 | 'P'<<16 | ' '<<24, + MARATHI = 'M' | 'A'<<8 | 'R'<<16 | ' '<<24, + MARSHALLESE = 'M' | 'A'<<8 | 'H'<<16 | ' '<<24, + MARWARI = 'M' | 'A'<<8 | 'W'<<16 | ' '<<24, + MAYAN = 'M' | 'Y'<<8 | 'N'<<16 | ' '<<24, + MAZANDERANI = 'M' | 'Z'<<8 | 'N'<<16 | ' '<<24, + MBEMBE_TIGON = 'N' | 'Z'<<8 | 'A'<<16 | ' '<<24, + MBO = 'M' | 'B'<<8 | 'O'<<16 | ' '<<24, + MBUNDU = 'M' | 'B'<<8 | 'N'<<16 | ' '<<24, + MEDUMBA = 'B' | 'Y'<<8 | 'V'<<16 | ' '<<24, + MEEN = 'M' | 'E'<<8 | 'N'<<16 | ' '<<24, + MENDE = 'M' | 'D'<<8 | 'E'<<16 | ' '<<24, + MERU = 'M' | 'E'<<8 | 'R'<<16 | ' '<<24, + MEWATI = 'W' | 'T'<<8 | 'M'<<16 | ' '<<24, + MINANGKABAU = 'M' | 'I'<<8 | 'N'<<16 | ' '<<24, + MINJANGBAL = 'X' | 'J'<<8 | 'B'<<16 | ' '<<24, + MIRANDESE = 'M' | 'W'<<8 | 'L'<<16 | ' '<<24, + MIZO = 'M' | 'I'<<8 | 'Z'<<16 | ' '<<24, + MOHAWK = 'M' | 'O'<<8 | 'H'<<16 | ' '<<24, + MOKSHA = 'M' | 'O'<<8 | 'K'<<16 | ' '<<24, + MOLDAVIAN = 'M' | 'O'<<8 | 'L'<<16 | ' '<<24, + MON = 'M' | 'O'<<8 | 'N'<<16 | ' '<<24, + MONGOLIAN = 'M' | 'N'<<8 | 'G'<<16 | ' '<<24, + MOOSE_CREE = 'M' | 'C'<<8 | 'R'<<16 | ' '<<24, + MORISYEN = 'M' | 'F'<<8 | 'E'<<16 | ' '<<24, + MOROCCAN = 'M' | 'O'<<8 | 'R'<<16 | ' '<<24, + MOSSI = 'M' | 'P'<<8 | 'S'<<16 | ' '<<24, + MUNDARI = 'M' | 'U'<<8 | 'N'<<16 | ' '<<24, + MUSCOGEE = 'M' | 'U'<<8 | 'S'<<16 | ' '<<24, + N_CREE = 'N' | 'C'<<8 | 'R'<<16 | ' '<<24, + NAGA_ASSAMESE = 'N' | 'A'<<8 | 'G'<<16 | ' '<<24, + NAGARI = 'N' | 'G'<<8 | 'R'<<16 | ' '<<24, + NAHUATL = 'N' | 'A'<<8 | 'H'<<16 | ' '<<24, + NANAI = 'N' | 'A'<<8 | 'N'<<16 | ' '<<24, + NASKAPI = 'N' | 'A'<<8 | 'S'<<16 | ' '<<24, + NAURUAN = 'N' | 'A'<<8 | 'U'<<16 | ' '<<24, + NAVAJO = 'N' | 'A'<<8 | 'V'<<16 | ' '<<24, + NDAU = 'N' | 'D'<<8 | 'C'<<16 | ' '<<24, + NDEBELE = 'N' | 'D'<<8 | 'B'<<16 | ' '<<24, + NDONGA = 'N' | 'D'<<8 | 'G'<<16 | ' '<<24, + NEAPOLITAN = 'N' | 'A'<<8 | 'P'<<16 | ' '<<24, + NEPALI = 'N' | 'E'<<8 | 'P'<<16 | ' '<<24, + NEWARI = 'N' | 'E'<<8 | 'W'<<16 | ' '<<24, + NGBAKA = 'N' | 'G'<<8 | 'A'<<16 | ' '<<24, + NIGERIAN_FULFULDE = 'F' | 'U'<<8 | 'V'<<16 | ' '<<24, + NIMADI = 'N' | 'O'<<8 | 'E'<<16 | ' '<<24, + NISI = 'N' | 'I'<<8 | 'S'<<16 | ' '<<24, + NIUEAN = 'N' | 'I'<<8 | 'U'<<16 | ' '<<24, + NKO = 'N' | 'K'<<8 | 'O'<<16 | ' '<<24, + NOGAI = 'N' | 'O'<<8 | 'G'<<16 | ' '<<24, + NORFOLK = 'P' | 'I'<<8 | 'H'<<16 | ' '<<24, + NORTH_SLAVEY = 'S' | 'C'<<8 | 'S'<<16 | ' '<<24, + NORTHERN_EMBERA = 'E' | 'M'<<8 | 'P'<<16 | ' '<<24, + NORTHERN_SAMI = 'N' | 'S'<<8 | 'M'<<16 | ' '<<24, + NORTHERN_SOTHO = 'N' | 'S'<<8 | 'O'<<16 | ' '<<24, + NORTHERN_TAI = 'N' | 'T'<<8 | 'A'<<16 | ' '<<24, + NORWAY_HOUSE_CREE = 'N' | 'H'<<8 | 'C'<<16 | ' '<<24, + NORWEGIAN = 'N' | 'O'<<8 | 'R'<<16 | ' '<<24, + NORWEGIAN_NYNORSK = 'N' | 'Y'<<8 | 'N'<<16 | ' '<<24, + NOVIAL = 'N' | 'O'<<8 | 'V'<<16 | ' '<<24, + NUMANGGANG = 'N' | 'O'<<8 | 'P'<<16 | ' '<<24, + NUNAVIK_INUKTITUT = 'I' | 'N'<<8 | 'U'<<16 | ' '<<24, + NUU_CHAH_NULTH = 'N' | 'U'<<8 | 'K'<<16 | ' '<<24, + NYAMWEZI = 'N' | 'Y'<<8 | 'M'<<16 | ' '<<24, + NYANKOLE = 'N' | 'K'<<8 | 'L'<<16 | ' '<<24, + OCCITAN = 'O' | 'C'<<8 | 'I'<<16 | ' '<<24, + ODIA = 'O' | 'R'<<8 | 'I'<<16 | ' '<<24, + OJI_CREE = 'O' | 'C'<<8 | 'R'<<16 | ' '<<24, + OJIBWAY = 'O' | 'J'<<8 | 'B'<<16 | ' '<<24, + OLD_IRISH = 'S' | 'G'<<8 | 'A'<<16 | ' '<<24, + OLD_JAVANESE = 'K' | 'A'<<8 | 'W'<<16 | ' '<<24, + ONEIDA = 'O' | 'N'<<8 | 'E'<<16 | ' '<<24, + ONONDAGA = 'O' | 'N'<<8 | 'O'<<16 | ' '<<24, + OROMO = 'O' | 'R'<<8 | 'O'<<16 | ' '<<24, + OSSETIAN = 'O' | 'S'<<8 | 'S'<<16 | ' '<<24, + PA_O_KAREN = 'B' | 'L'<<8 | 'K'<<16 | ' '<<24, + PALAUAN = 'P' | 'A'<<8 | 'U'<<16 | ' '<<24, + PALAUNG = 'P' | 'L'<<8 | 'G'<<16 | ' '<<24, + PALESTINIAN_ARAMAIC = 'P' | 'A'<<8 | 'A'<<16 | ' '<<24, + PALI = 'P' | 'A'<<8 | 'L'<<16 | ' '<<24, + PALPA = 'P' | 'A'<<8 | 'P'<<16 | ' '<<24, + PAMPANGAN = 'P' | 'A'<<8 | 'M'<<16 | ' '<<24, + PANGASINAN = 'P' | 'A'<<8 | 'G'<<16 | ' '<<24, + PAPIAMENTU = 'P' | 'A'<<8 | 'P'<<16 | '0'<<24, + PASHTO = 'P' | 'A'<<8 | 'S'<<16 | ' '<<24, + PATTANI_MALAY = 'M' | 'F'<<8 | 'A'<<16 | ' '<<24, + PENNSYLVANIA_GERMAN = 'P' | 'D'<<8 | 'C'<<16 | ' '<<24, + PERSIAN = 'F' | 'A'<<8 | 'R'<<16 | ' '<<24, + PHAKE = 'P' | 'J'<<8 | 'K'<<16 | ' '<<24, + PICARD = 'P' | 'C'<<8 | 'D'<<16 | ' '<<24, + PIEMONTESE = 'P' | 'M'<<8 | 'S'<<16 | ' '<<24, + PILAGA = 'P' | 'L'<<8 | 'G'<<16 | ' '<<24, + PITE_SAMI = 'S' | 'J'<<8 | 'E'<<16 | ' '<<24, + POCOMCHI = 'P' | 'O'<<8 | 'H'<<16 | ' '<<24, + POHNPEIAN = 'P' | 'O'<<8 | 'N'<<16 | ' '<<24, + POLISH = 'P' | 'L'<<8 | 'K'<<16 | ' '<<24, + POLYTONIC_GREEK = 'P' | 'G'<<8 | 'R'<<16 | ' '<<24, + PORTUGUESE = 'P' | 'T'<<8 | 'G'<<16 | ' '<<24, + PROVENCAL = 'P' | 'R'<<8 | 'O'<<16 | ' '<<24, + PUNJABI = 'P' | 'A'<<8 | 'N'<<16 | ' '<<24, + QUECHUA = 'Q' | 'U'<<8 | 'Z'<<16 | ' '<<24, + QUECHUA_BOLIVIA = 'Q' | 'U'<<8 | 'H'<<16 | ' '<<24, + QUECHUA_ECUADOR = 'Q' | 'V'<<8 | 'I'<<16 | ' '<<24, + QUECHUA_PERU = 'Q' | 'W'<<8 | 'H'<<16 | ' '<<24, + R_CREE = 'R' | 'C'<<8 | 'R'<<16 | ' '<<24, + RAJASTHANI = 'R' | 'A'<<8 | 'J'<<16 | ' '<<24, + RAKHINE = 'A' | 'R'<<8 | 'K'<<16 | ' '<<24, + RAROTONGAN = 'R' | 'A'<<8 | 'R'<<16 | ' '<<24, + REJANG = 'R' | 'E'<<8 | 'J'<<16 | ' '<<24, + RIANG = 'R' | 'I'<<8 | 'A'<<16 | ' '<<24, + RIPUARIAN = 'K' | 'S'<<8 | 'H'<<16 | ' '<<24, + RITARUNGO = 'R' | 'I'<<8 | 'T'<<16 | ' '<<24, + ROHINGYA = 'R' | 'H'<<8 | 'G'<<16 | ' '<<24, + ROMANIAN = 'R' | 'O'<<8 | 'M'<<16 | ' '<<24, + ROMANSH = 'R' | 'M'<<8 | 'S'<<16 | ' '<<24, + ROMANY = 'R' | 'O'<<8 | 'Y'<<16 | ' '<<24, + ROTUMAN = 'R' | 'T'<<8 | 'M'<<16 | ' '<<24, + RUNDI = 'R' | 'U'<<8 | 'N'<<16 | ' '<<24, + RUSSIAN = 'R' | 'U'<<8 | 'S'<<16 | ' '<<24, + RUSSIAN_BURIAT = 'R' | 'B'<<8 | 'U'<<16 | ' '<<24, + RUSYN = 'R' | 'S'<<8 | 'Y'<<16 | ' '<<24, + SADRI = 'S' | 'A'<<8 | 'D'<<16 | ' '<<24, + SAKHA = 'Y' | 'A'<<8 | 'K'<<16 | ' '<<24, + SAMOAN = 'S' | 'M'<<8 | 'O'<<16 | ' '<<24, + SAMOGITIAN = 'S' | 'G'<<8 | 'S'<<16 | ' '<<24, + SAN_BLAS_KUNA = 'C' | 'U'<<8 | 'K'<<16 | ' '<<24, + SANGO = 'S' | 'G'<<8 | 'O'<<16 | ' '<<24, + SANSKRIT = 'S' | 'A'<<8 | 'N'<<16 | ' '<<24, + SANTALI = 'S' | 'A'<<8 | 'T'<<16 | ' '<<24, + SARAIKI = 'S' | 'R'<<8 | 'K'<<16 | ' '<<24, + SARDINIAN = 'S' | 'R'<<8 | 'D'<<16 | ' '<<24, + SASAK = 'S' | 'A'<<8 | 'S'<<16 | ' '<<24, + SATERLAND_FRISIAN = 'S' | 'T'<<8 | 'Q'<<16 | ' '<<24, + SAYISI = 'S' | 'A'<<8 | 'Y'<<16 | ' '<<24, + SCOTS = 'S' | 'C'<<8 | 'I'<<16 | ' '<<24, + SCOTTISH_GAELIC = 'G' | 'A'<<8 | 'E'<<16 | ' '<<24, + SEKOTA = 'S' | 'E'<<8 | 'J'<<16 | ' '<<24, + SELKUP = 'S' | 'E'<<8 | 'L'<<16 | ' '<<24, + SENA = 'S' | 'N'<<8 | 'A'<<16 | ' '<<24, + SENECA = 'S' | 'E'<<8 | 'E'<<16 | ' '<<24, + SERBIAN = 'S' | 'R'<<8 | 'B'<<16 | ' '<<24, + SERER = 'S' | 'R'<<8 | 'R'<<16 | ' '<<24, + SGAW_KAREN = 'K' | 'S'<<8 | 'W'<<16 | ' '<<24, + SHAN = 'S' | 'H'<<8 | 'N'<<16 | ' '<<24, + SHONA = 'S' | 'N'<<8 | 'A'<<16 | ' '<<24, + SIBE = 'S' | 'I'<<8 | 'B'<<16 | ' '<<24, + SICILIAN = 'S' | 'C'<<8 | 'N'<<16 | ' '<<24, + SIDAMO = 'S' | 'I'<<8 | 'D'<<16 | ' '<<24, + SILESIAN = 'S' | 'Z'<<8 | 'L'<<16 | ' '<<24, + SILTE_GURAGE = 'S' | 'I'<<8 | 'G'<<16 | ' '<<24, + SINDHI = 'S' | 'N'<<8 | 'D'<<16 | ' '<<24, + SINHALA = 'S' | 'N'<<8 | 'H'<<16 | ' '<<24, + SKOLT_SAMI = 'S' | 'K'<<8 | 'S'<<16 | ' '<<24, + SLAVEY = 'S' | 'L'<<8 | 'A'<<16 | ' '<<24, + SLOVAK = 'S' | 'K'<<8 | 'Y'<<16 | ' '<<24, + SLOVENIAN = 'S' | 'L'<<8 | 'V'<<16 | ' '<<24, + SMALL_FLOWERY_MIAO = 'S' | 'F'<<8 | 'M'<<16 | ' '<<24, + SODO_GURAGE = 'S' | 'O'<<8 | 'G'<<16 | ' '<<24, + SOGA = 'X' | 'O'<<8 | 'G'<<16 | ' '<<24, + SOMALI = 'S' | 'M'<<8 | 'L'<<16 | ' '<<24, + SONGE = 'S' | 'O'<<8 | 'P'<<16 | ' '<<24, + SONINKE = 'S' | 'N'<<8 | 'K'<<16 | ' '<<24, + SOUTH_SLAVEY = 'S' | 'S'<<8 | 'L'<<16 | ' '<<24, + SOUTHERN_KIWAI = 'K' | 'J'<<8 | 'D'<<16 | ' '<<24, + SOUTHERN_SAMI = 'S' | 'S'<<8 | 'M'<<16 | ' '<<24, + SOUTHERN_SOTHO = 'S' | 'O'<<8 | 'T'<<16 | ' '<<24, + SPANISH = 'E' | 'S'<<8 | 'P'<<16 | ' '<<24, + STANDARD_MOROCCAN_TAMAZIGHT = 'Z' | 'G'<<8 | 'H'<<16 | ' '<<24, + STRAITS_SALISH = 'S' | 'T'<<8 | 'R'<<16 | ' '<<24, + SUKUMA = 'S' | 'U'<<8 | 'K'<<16 | ' '<<24, + SUNDANESE = 'S' | 'U'<<8 | 'N'<<16 | ' '<<24, + SURI = 'S' | 'U'<<8 | 'R'<<16 | ' '<<24, + SUTU = 'S' | 'X'<<8 | 'T'<<16 | ' '<<24, + SVAN = 'S' | 'V'<<8 | 'A'<<16 | ' '<<24, + SWADAYA_ARAMAIC = 'S' | 'W'<<8 | 'A'<<16 | ' '<<24, + SWAHILI = 'S' | 'W'<<8 | 'K'<<16 | ' '<<24, + SWATI = 'S' | 'W'<<8 | 'Z'<<16 | ' '<<24, + SWEDISH = 'S' | 'V'<<8 | 'E'<<16 | ' '<<24, + SYLHETI = 'S' | 'Y'<<8 | 'L'<<16 | ' '<<24, + SYRIAC = 'S' | 'Y'<<8 | 'R'<<16 | ' '<<24, + SYRIAC_EASTERN = 'S' | 'Y'<<8 | 'R'<<16 | 'N'<<24, + SYRIAC_ESTRANGELA = 'S' | 'Y'<<8 | 'R'<<16 | 'E'<<24, + SYRIAC_WESTERN = 'S' | 'Y'<<8 | 'R'<<16 | 'J'<<24, + TABASARAN = 'T' | 'A'<<8 | 'B'<<16 | ' '<<24, + TACHELHIT = 'S' | 'H'<<8 | 'I'<<16 | ' '<<24, + TAGALOG = 'T' | 'G'<<8 | 'L'<<16 | ' '<<24, + TAHAGGART_TAMAHAQ = 'T' | 'H'<<8 | 'V'<<16 | ' '<<24, + TAHITIAN = 'T' | 'H'<<8 | 'T'<<16 | ' '<<24, + TAI_LAING = 'T' | 'J'<<8 | 'L'<<16 | ' '<<24, + TAJIKI = 'T' | 'A'<<8 | 'J'<<16 | ' '<<24, + TALYSH = 'T' | 'L'<<8 | 'Y'<<16 | ' '<<24, + TAMASHEK = 'T' | 'M'<<8 | 'H'<<16 | ' '<<24, + TAMASHEQ = 'T' | 'A'<<8 | 'Q'<<16 | ' '<<24, + TAMAZIGHT = 'T' | 'Z'<<8 | 'M'<<16 | ' '<<24, + TAMIL = 'T' | 'A'<<8 | 'M'<<16 | ' '<<24, + TARIFIT = 'R' | 'I'<<8 | 'F'<<16 | ' '<<24, + TATAR = 'T' | 'A'<<8 | 'T'<<16 | ' '<<24, + TAWALLAMMAT_TAMAJAQ = 'T' | 'T'<<8 | 'Q'<<16 | ' '<<24, + TAY = 'T' | 'Y'<<8 | 'Z'<<16 | ' '<<24, + TAYART_TAMAJEQ = 'T' | 'H'<<8 | 'Z'<<16 | ' '<<24, + TELUGU = 'T' | 'E'<<8 | 'L'<<16 | ' '<<24, + TEMNE = 'T' | 'M'<<8 | 'N'<<16 | ' '<<24, + TETUM = 'T' | 'E'<<8 | 'T'<<16 | ' '<<24, + TH_CREE = 'T' | 'C'<<8 | 'R'<<16 | ' '<<24, + THAI = 'T' | 'H'<<8 | 'A'<<16 | ' '<<24, + THAILAND_MON = 'M' | 'O'<<8 | 'N'<<16 | 'T'<<24, + THOMPSON = 'T' | 'H'<<8 | 'P'<<16 | ' '<<24, + TIBETAN = 'T' | 'I'<<8 | 'B'<<16 | ' '<<24, + TIGRE = 'T' | 'G'<<8 | 'R'<<16 | ' '<<24, + TIGRINYA = 'T' | 'G'<<8 | 'Y'<<16 | ' '<<24, + TIV = 'T' | 'I'<<8 | 'V'<<16 | ' '<<24, + TLINGIT = 'T' | 'L'<<8 | 'I'<<16 | ' '<<24, + TOBO = 'T' | 'B'<<8 | 'V'<<16 | ' '<<24, + TODO = 'T' | 'O'<<8 | 'D'<<16 | ' '<<24, + TOK_PISIN = 'T' | 'P'<<8 | 'I'<<16 | ' '<<24, + TOMA = 'T' | 'O'<<8 | 'D'<<16 | '0'<<24, + TONGA = 'T' | 'N'<<8 | 'G'<<16 | ' '<<24, + TONGAN = 'T' | 'G'<<8 | 'N'<<16 | ' '<<24, + TORKI = 'A' | 'Z'<<8 | 'B'<<16 | ' '<<24, + TSHANGLA = 'T' | 'S'<<8 | 'J'<<16 | ' '<<24, + TSONGA = 'T' | 'S'<<8 | 'G'<<16 | ' '<<24, + TSWANA = 'T' | 'N'<<8 | 'A'<<16 | ' '<<24, + TULU = 'T' | 'U'<<8 | 'L'<<16 | ' '<<24, + TUMBUKA = 'T' | 'U'<<8 | 'M'<<16 | ' '<<24, + TUNDRA_ENETS = 'T' | 'N'<<8 | 'E'<<16 | ' '<<24, + TURKISH = 'T' | 'R'<<8 | 'K'<<16 | ' '<<24, + TURKMEN = 'T' | 'K'<<8 | 'M'<<16 | ' '<<24, + TUROYO_ARAMAIC = 'T' | 'U'<<8 | 'A'<<16 | ' '<<24, + TUSCARORA = 'T' | 'U'<<8 | 'S'<<16 | ' '<<24, + TUVALU = 'T' | 'V'<<8 | 'L'<<16 | ' '<<24, + TUVIN = 'T' | 'U'<<8 | 'V'<<16 | ' '<<24, + TWI = 'T' | 'W'<<8 | 'I'<<16 | ' '<<24, + TZOTZIL = 'T' | 'Z'<<8 | 'O'<<16 | ' '<<24, + UDI = 'U' | 'D'<<8 | 'I'<<16 | ' '<<24, + UDMURT = 'U' | 'D'<<8 | 'M'<<16 | ' '<<24, + UKRAINIAN = 'U' | 'K'<<8 | 'R'<<16 | ' '<<24, + UMBUNDU = 'U' | 'M'<<8 | 'B'<<16 | ' '<<24, + UME_SAMI = 'S' | 'J'<<8 | 'U'<<16 | ' '<<24, + UPPER_SAXON = 'S' | 'X'<<8 | 'U'<<16 | ' '<<24, + UPPER_SORBIAN = 'U' | 'S'<<8 | 'B'<<16 | ' '<<24, + URALIC_PHONETIC = 'U' | 'P'<<8 | 'P'<<16 | ' '<<24, + URDU = 'U' | 'R'<<8 | 'D'<<16 | ' '<<24, + UYGHUR = 'U' | 'Y'<<8 | 'G'<<16 | ' '<<24, + UZBEK = 'U' | 'Z'<<8 | 'B'<<16 | ' '<<24, + VENDA = 'V' | 'E'<<8 | 'N'<<16 | ' '<<24, + VENETIAN = 'V' | 'E'<<8 | 'C'<<16 | ' '<<24, + VIETNAMESE = 'V' | 'I'<<8 | 'T'<<16 | ' '<<24, + VLAX_ROMANI = 'R' | 'M'<<8 | 'Y'<<16 | ' '<<24, + VOLAPUK = 'V' | 'O'<<8 | 'L'<<16 | ' '<<24, + VORO = 'V' | 'R'<<8 | 'O'<<16 | ' '<<24, + WA = 'W' | 'A'<<8 | ' '<<16 | ' '<<24, + WACI_GBE = 'W' | 'C'<<8 | 'I'<<16 | ' '<<24, + WAGDI = 'W' | 'A'<<8 | 'G'<<16 | ' '<<24, + WAKHI = 'W' | 'B'<<8 | 'L'<<16 | ' '<<24, + WALLOON = 'W' | 'L'<<8 | 'N'<<16 | ' '<<24, + WARAY_WARAY = 'W' | 'A'<<8 | 'R'<<16 | ' '<<24, + WAYANAD_CHETTI = 'C' | 'T'<<8 | 'T'<<16 | ' '<<24, + WAYUU = 'G' | 'U'<<8 | 'C'<<16 | ' '<<24, + WELSH = 'W' | 'E'<<8 | 'L'<<16 | ' '<<24, + WENDAT = 'W' | 'D'<<8 | 'T'<<16 | ' '<<24, + WEST_CREE = 'W' | 'C'<<8 | 'R'<<16 | ' '<<24, + WESTERN_CHAM = 'C' | 'J'<<8 | 'A'<<16 | ' '<<24, + WESTERN_KAYAH = 'K' | 'Y'<<8 | 'U'<<16 | ' '<<24, + WESTERN_PANJABI = 'P' | 'N'<<8 | 'B'<<16 | ' '<<24, + WESTERN_PWO_KAREN = 'P' | 'W'<<8 | 'O'<<16 | ' '<<24, + WOLOF = 'W' | 'L'<<8 | 'F'<<16 | ' '<<24, + WOODS_CREE = 'D' | 'C'<<8 | 'R'<<16 | ' '<<24, + WUDING_LUQUAN_YI = 'Y' | 'W'<<8 | 'Q'<<16 | ' '<<24, + WYANDOT = 'W' | 'Y'<<8 | 'N'<<16 | ' '<<24, + XHOSA = 'X' | 'H'<<8 | 'S'<<16 | ' '<<24, + Y_CREE = 'Y' | 'C'<<8 | 'R'<<16 | ' '<<24, + YAO = 'Y' | 'A'<<8 | 'O'<<16 | ' '<<24, + YAPESE = 'Y' | 'A'<<8 | 'P'<<16 | ' '<<24, + YI_CLASSIC = 'Y' | 'I'<<8 | 'C'<<16 | ' '<<24, + YI_MODERN = 'Y' | 'I'<<8 | 'M'<<16 | ' '<<24, + YIDDISH = 'J' | 'I'<<8 | 'I'<<16 | ' '<<24, + YORUBA = 'Y' | 'B'<<8 | 'A'<<16 | ' '<<24, + ZAMBOANGA_CHAVACANO = 'C' | 'B'<<8 | 'K'<<16 | ' '<<24, + ZANDE = 'Z' | 'N'<<8 | 'D'<<16 | ' '<<24, + ZARMA = 'D' | 'J'<<8 | 'R'<<16 | ' '<<24, + ZAZAKI = 'Z' | 'Z'<<8 | 'A'<<16 | ' '<<24, + ZEALANDIC = 'Z' | 'E'<<8 | 'A'<<16 | ' '<<24, + ZHUANG = 'Z' | 'H'<<8 | 'A'<<16 | ' '<<24, + ZULU = 'Z' | 'U'<<8 | 'L'<<16 | ' '<<24, +} + +break_flags :: distinct bit_set[break_flag; u32] +break_flag :: enum u32 { + // Direction changes from left-to-right to right-to-left, or vice versa. + DIRECTION = 0, + // Script changes. + // Note that some characters, such as digits, are used in multiple + // scripts and, as such, will not produce script breaks. + SCRIPT = 1, + // Graphemes are "visual units". They may be composed of more than one codepoint. + // They are used as interaction boundaries in graphical interfaces, e.g. moving the + // caret. + GRAPHEME = 2, + // In most scripts, words are broken up by whitespace, but Unicode word breaking has + // better script coverage and also handles some special cases that a simple stateless + // loop cannot handle. + WORD = 3, + // By default, you are not allowed to break a line. + // Soft line breaks allow for line breaking, but do not require it. + // This is useful for when you are doing line wrapping. + LINE_SOFT = 4, + // Hard line breaks are required. They signal the end of a paragraph. + // (In Unicode, there is no meaningful distinction between a line and a paragraph. + // a paragraph is pretty much just a line of text that can wrap.) + LINE_HARD = 5, + // Used for manual segmentation in the context. + MANUAL = 6, + + PARAGRAPH_DIRECTION = 7, +} + +BREAK_FLAG_DIRECTION :: break_flags{.DIRECTION} +BREAK_FLAG_SCRIPT :: break_flags{.SCRIPT} +BREAK_FLAG_GRAPHEME :: break_flags{.GRAPHEME} +BREAK_FLAG_WORD :: break_flags{.WORD} +BREAK_FLAG_LINE_SOFT :: break_flags{.LINE_SOFT} +BREAK_FLAG_LINE_HARD :: break_flags{.LINE_HARD} +BREAK_FLAG_MANUAL :: break_flags{.MANUAL} +BREAK_FLAG_PARAGRAPH_DIRECTION :: break_flags{.PARAGRAPH_DIRECTION} + +BREAK_FLAG_LINE :: break_flags{.LINE_SOFT, .LINE_HARD} +BREAK_FLAG_ANY :: break_flags{.DIRECTION, .SCRIPT, .GRAPHEME, .WORD, .LINE_SOFT, .LINE_HARD} + + +// Japanese text contains "kinsoku" characters, around which breaking a line is forbidden. +// Exactly which characters are "kinsoku" or not depends on the context: +// - Strict style has the largest amount of kinsoku characters, which leads to longer lines. +// - Loose style has the smallest amount of kinsoku characters, which leads to smaller lines. +// - Normal style is somewhere in the middle. +// Note that, while the Unicode standard mentions all three of these styles, it does not mention +// any differences between the normal and loose styles. +// As such, normal and loose styles currently behave the same. +japanese_line_break_style :: enum u8 { + // The Unicode standard does not define what strict style is used for. + // Supposedly, it is used for anything that does not fall into the other two categories of text. + STRICT, + + // Normal style is used for books and documents. + NORMAL, + + // Loose style is used for newspapers, and (I assume) any other narrow column format. + LOOSE, +} + +break_state_flags :: distinct bit_set[break_state_flag; u32] +break_state_flag :: enum u32 { + STARTED = 0, + END = 1, + + _ = 2, + + // Bidirectional flags + SAW_R_AFTER_L = 3, + SAW_AL_AFTER_LR = 4, + LAST_WAS_BRACKET = 5, +} + + + +text_format :: enum u32 { + NONE, + + UTF32, + UTF8, +} + +direction :: enum u32 { + DONT_KNOW, + KBTS_DIRECTION_LTR, + KBTS_DIRECTION_RTL, +} + +orientation :: enum u32 { + HORIZONTAL, + VERTICAL, +} + +shaping_table :: enum u8 { + GSUB, + GPOS, +} + +shape_error :: enum u32 { + NONE, + INVALID_FONT, + GAVE_TEXT_BEFORE_CALLING_BEGIN, + OUT_OF_MEMORY, +} + +allocator_op_kind :: enum u32 { + NONE, + ALLOCATE, + FREE, +} + +blob_table_id :: enum u32 { + NONE, + HEAD, + CMAP, + GDEF, + GSUB, + GPOS, + HHEA, + VHEA, + HMTX, + VMTX, + MAXP, + OS2, + NAME, +} + +load_font_error :: enum u32 { + NONE, + NEED_TO_CREATE_BLOB, + INVALID_FONT, + OUT_OF_MEMORY, + COULD_NOT_OPEN_FILE, + READ_ERROR, +} + +version :: enum u32 { + _1_X, + _2_0, + + CURRENT = _2_0, +} + +blob_version :: enum u32 { + INVALID, + INITIAL, + + CURRENT = INITIAL, +} + +font_style_flags :: distinct bit_set[font_style_flag; u32] +font_style_flag :: enum u32 { + REGULAR = 0, + ITALIC = 1, + BOLD = 2, +} + +font_weight :: enum u32 { + UNKNOWN, + + THIN, + EXTRA_LIGHT, + LIGHT, + NORMAL, + MEDIUM, + SEMI_BOLD, + BOLD, + EXTRA_BOLD, + BLACK, +} + +font_width :: enum u32 { + UNKNOWN, + + ULTRA_CONDENSED, + EXTRA_CONDENSED, + CONDENSED, + SEMI_CONDENSED, + NORMAL, + SEMI_EXPANDED, + EXPANDED, + EXTRA_EXPANDED, + ULTRA_EXPANDED, +} + +glyph_flags :: distinct bit_set[glyph_flag; u32] +glyph_flag :: enum u32 { + // These feature flags must coincide with kbts_joining_feature _and_ KBTS_FEATURE_FLAG! + ISOL = 0, + FINA = 1, + FIN2 = 2, + FIN3 = 3, + MEDI = 4, + MED2 = 5, + INIT = 6, + + // These feature flags must coincide with FEATURE_FLAG! + LJMO = 7, + VJMO = 8, + TJMO = 9, + RPHF = 10, + BLWF = 11, + HALF = 12, + PSTF = 13, + ABVF = 14, + PREF = 15, + NUMR = 16, + FRAC = 17, + DNOM = 18, + CFAR = 19, + + // These can be anything. + DO_NOT_DECOMPOSE = 21, + FIRST_IN_MULTIPLE_SUBSTITUTION = 22, + NO_BREAK = 23, + CURSIVE = 24, + GENERATED_BY_GSUB = 25, + USED_IN_GPOS = 26, + + STCH_ENDPOINT = 27, + STCH_EXTENSION = 28, + + LIGATURE = 29, + MULTIPLE_SUBSTITUTION = 30, +} + +joining_feature :: enum u8 { + NONE, + + // These must correspond with glyph_flags and FEATURE_IDs. + ISOL, + FINA, + FIN2, + FIN3, + MEDI, + MED2, + INIT, +} + +user_id_generation_mode :: enum u32 { + CODEPOINT_INDEX, + SOURCE_INDEX, +} + +break_config_flags :: distinct bit_set[break_config_flag; u32] +break_config_flag :: enum u32 { + END_OF_TEXT_GENERATES_HARD_LINE_BREAK = 0, +} + +font_info_string_id :: enum u32 { + NONE, + COPYRIGHT, + FAMILY, + SUBFAMILY, + UID, + FULL_NAME, + VERSION, + POSTSCRIPT_NAME, + TRADEMARK, + MANUFACTURER, + DESIGNER, + TYPOGRAPHIC_FAMILY, + TYPOGRAPHIC_SUBFAMILY, +} + + +unicode_joining_type :: enum u8 { + NONE, + LEFT, + DUAL, + FORCE, + RIGHT, + TRANSPARENT, +} + +unicode_flags :: distinct bit_set[unicode_flag; u8] +unicode_flag :: enum u8 { + MODIFIER_COMBINING_MARK = 0, + DEFAULT_IGNORABLE = 1, + OPEN_BRACKET = 2, + CLOSE_BRACKET = 3, + PART_OF_WORD = 4, + DECIMAL_DIGIT = 5, + NON_SPACING_MARK = 6, +} + +UNICODE_FLAG_MODIFIER_COMBINING_MARK :: unicode_flags{.MODIFIER_COMBINING_MARK} +UNICODE_FLAG_DEFAULT_IGNORABLE :: unicode_flags{.DEFAULT_IGNORABLE} +UNICODE_FLAG_OPEN_BRACKET :: unicode_flags{.OPEN_BRACKET} +UNICODE_FLAG_CLOSE_BRACKET :: unicode_flags{.CLOSE_BRACKET} +UNICODE_FLAG_PART_OF_WORD :: unicode_flags{.PART_OF_WORD} +UNICODE_FLAG_DECIMAL_DIGIT :: unicode_flags{.DECIMAL_DIGIT} +UNICODE_FLAG_NON_SPACING_MARK :: unicode_flags{.NON_SPACING_MARK} +UNICODE_FLAG_MIRRORED :: unicode_flags{.OPEN_BRACKET, .CLOSE_BRACKET} + +unicode_bidirectional_class :: enum u8 { + NI, + BN, // Formatting characters need to be ignored. + L, + R, + NSM, + AL, + AN, + EN, + ES, + ET, + CS, +} + +line_break_class :: enum u8 { + /* 0 */ Onea, + /* 1 */ Oea, + /* 2 */ Ope, + /* 3 */ BK, + /* 4 */ CR, + /* 5 */ LF, + /* 6 */ NL, + /* 7 */ SP, + /* 8 */ ZW, + /* 9 */ WJ, + /* 10 */ GLnea, + /* 11 */ GLea, + /* 12 */ CLnea, + /* 13 */ CLea, + /* 14 */ CPnea, + /* 15 */ CPea, + /* 16 */ EXnea, + /* 17 */ EXea, + /* 18 */ SY, + /* 19 */ BAnea, + /* 20 */ BAea, + /* 21 */ OPnea, + /* 22 */ OPea, + /* 23 */ QU, + /* 24 */ QUPi, + /* 25 */ QUPf, + /* 26 */ IS, + /* 27 */ NSnea, + /* 28 */ NSea, + /* 29 */ B2, + /* 30 */ CB, + /* 31 */ HY, + /* 32 */ HYPHEN, + /* 33 */ INnea, + /* 34 */ INea, + /* 35 */ BB, + /* 36 */ HL, + /* 37 */ ALnea, + /* 38 */ ALea, + /* 39 */ NU, + /* 40 */ PRnea, + /* 41 */ PRea, + /* 42 */ IDnea, + /* 43 */ IDea, + /* 44 */ IDpe, + /* 45 */ EBnea, + /* 46 */ EBea, + /* 47 */ EM, + /* 48 */ POnea, + /* 49 */ POea, + /* 50 */ JL, + /* 51 */ JV, + /* 52 */ JT, + /* 53 */ H2, + /* 54 */ H3, + /* 55 */ AP, + /* 56 */ AK, + /* 57 */ DOTTED_CIRCLE, + /* 58 */ AS, + /* 59 */ VF, + /* 60 */ VI, + /* 61 */ RI, + + /* 62 */ COUNT, + + /* 63 */ CM, + /* 64 */ ZWJ, + + // CJ resolves to either NS or ID depending on the (Japanese) line break style. + // NS is strict line breaking, used for long lines. + // ID is normal line breaking, used for normal body text. + /* 65 */ CJ, + + /* 66 */ SOT, + /* 67 */ EOT, +} + +// @Cleanup: Merge EX and FO. +word_break_class :: enum u8 { + Onep, + Oep, + CR, + LF, + NL, + EX, + ZWJ, + RI, + FO, + KA, + HL, + ALnep, + ALep, + SQ, + DQ, + MNL, + ML, + MN, + NM, + ENL, + WSS, + + SOT, +} + +// Unicode defines scripts and languages. +// A language belongs to a single script, and a script belongs to a single writing system. +// On top of these, OpenType defines shapers, which are basically just designations for +// specific code paths that are taken depending on which script is being shapen. +// +// Some scripts, like Latin and Cyrillic, need relatively few operations, while complex +// scripts like Arabic and Indic scripts have specific processing steps that need to happen +// in order to obtain a correct result. +// +// These sequences of operations are _not_ described in the font file itself. The shaping +// code needs to know which script it is shaping, and implement all of those passes itself. +// That is why you, as a user, have to care about this. +// +// When creating shape_config, you can either pass in a known script, or you can specify +// SCRIPT_DONT_KNOW and let the library figure it out. +// While SCRIPT_DONT_KNOW may look appealing, it is worth noting that we can only infer +// the _script_, and not the language, of the text you pass in. +// This means that you might miss out on language-specific features when you use it. +shaper :: enum u32 { + DEFAULT, + ARABIC, + HANGUL, + HEBREW, + INDIC, + KHMER, + MYANMAR, + TIBETAN, + USE, +} + +MAXIMUM_RECOMPOSITION_PARENTS :: 19 +MAXIMUM_CODEPOINT_SCRIPTS :: 23 + +script_tag :: enum u32 { + DONT_KNOW = ' ' | ' '<<8 | ' '<<16 | ' '<<24, + ADLAM = 'a' | 'd'<<8 | 'l'<<16 | 'm'<<24, + AHOM = 'a' | 'h'<<8 | 'o'<<16 | 'm'<<24, + ANATOLIAN_HIEROGLYPHS = 'h' | 'l'<<8 | 'u'<<16 | 'w'<<24, + ARABIC = 'a' | 'r'<<8 | 'a'<<16 | 'b'<<24, + ARMENIAN = 'a' | 'r'<<8 | 'm'<<16 | 'n'<<24, + AVESTAN = 'a' | 'v'<<8 | 's'<<16 | 't'<<24, + BALINESE = 'b' | 'a'<<8 | 'l'<<16 | 'i'<<24, + BAMUM = 'b' | 'a'<<8 | 'm'<<16 | 'u'<<24, + BASSA_VAH = 'b' | 'a'<<8 | 's'<<16 | 's'<<24, + BATAK = 'b' | 'a'<<8 | 't'<<16 | 'k'<<24, + BENGALI = 'b' | 'n'<<8 | 'g'<<16 | '2'<<24, + BHAIKSUKI = 'b' | 'h'<<8 | 'k'<<16 | 's'<<24, + BOPOMOFO = 'b' | 'o'<<8 | 'p'<<16 | 'o'<<24, + BRAHMI = 'b' | 'r'<<8 | 'a'<<16 | 'h'<<24, + BUGINESE = 'b' | 'u'<<8 | 'g'<<16 | 'i'<<24, + BUHID = 'b' | 'u'<<8 | 'h'<<16 | 'd'<<24, + CANADIAN_SYLLABICS = 'c' | 'a'<<8 | 'n'<<16 | 's'<<24, + CARIAN = 'c' | 'a'<<8 | 'r'<<16 | 'i'<<24, + CAUCASIAN_ALBANIAN = 'a' | 'g'<<8 | 'h'<<16 | 'b'<<24, + CHAKMA = 'c' | 'a'<<8 | 'k'<<16 | 'm'<<24, + CHAM = 'c' | 'h'<<8 | 'a'<<16 | 'm'<<24, + CHEROKEE = 'c' | 'h'<<8 | 'e'<<16 | 'r'<<24, + CHORASMIAN = 'c' | 'h'<<8 | 'r'<<16 | 's'<<24, + CJK_IDEOGRAPHIC = 'h' | 'a'<<8 | 'n'<<16 | 'i'<<24, + COPTIC = 'c' | 'o'<<8 | 'p'<<16 | 't'<<24, + CYPRIOT_SYLLABARY = 'c' | 'p'<<8 | 'r'<<16 | 't'<<24, + CYPRO_MINOAN = 'c' | 'p'<<8 | 'm'<<16 | 'n'<<24, + CYRILLIC = 'c' | 'y'<<8 | 'r'<<16 | 'l'<<24, + DEFAULT = 'D' | 'F'<<8 | 'L'<<16 | 'T'<<24, + DEFAULT2 = 'D' | 'F'<<8 | 'L'<<16 | 'T'<<24, + DESERET = 'd' | 's'<<8 | 'r'<<16 | 't'<<24, + DEVANAGARI = 'd' | 'e'<<8 | 'v'<<16 | '2'<<24, + DIVES_AKURU = 'd' | 'i'<<8 | 'a'<<16 | 'k'<<24, + DOGRA = 'd' | 'o'<<8 | 'g'<<16 | 'r'<<24, + DUPLOYAN = 'd' | 'u'<<8 | 'p'<<16 | 'l'<<24, + EGYPTIAN_HIEROGLYPHS = 'e' | 'g'<<8 | 'y'<<16 | 'p'<<24, + ELBASAN = 'e' | 'l'<<8 | 'b'<<16 | 'a'<<24, + ELYMAIC = 'e' | 'l'<<8 | 'y'<<16 | 'm'<<24, + ETHIOPIC = 'e' | 't'<<8 | 'h'<<16 | 'i'<<24, + GARAY = 'g' | 'a'<<8 | 'r'<<16 | 'a'<<24, + GEORGIAN = 'g' | 'e'<<8 | 'o'<<16 | 'r'<<24, + GLAGOLITIC = 'g' | 'l'<<8 | 'a'<<16 | 'g'<<24, + GOTHIC = 'g' | 'o'<<8 | 't'<<16 | 'h'<<24, + GRANTHA = 'g' | 'r'<<8 | 'a'<<16 | 'n'<<24, + GREEK = 'g' | 'r'<<8 | 'e'<<16 | 'k'<<24, + GUJARATI = 'g' | 'j'<<8 | 'r'<<16 | '2'<<24, + GUNJALA_GONDI = 'g' | 'o'<<8 | 'n'<<16 | 'g'<<24, + GURMUKHI = 'g' | 'u'<<8 | 'r'<<16 | '2'<<24, + GURUNG_KHEMA = 'g' | 'u'<<8 | 'k'<<16 | 'h'<<24, + HANGUL = 'h' | 'a'<<8 | 'n'<<16 | 'g'<<24, + HANIFI_ROHINGYA = 'r' | 'o'<<8 | 'h'<<16 | 'g'<<24, + HANUNOO = 'h' | 'a'<<8 | 'n'<<16 | 'o'<<24, + HATRAN = 'h' | 'a'<<8 | 't'<<16 | 'r'<<24, + HEBREW = 'h' | 'e'<<8 | 'b'<<16 | 'r'<<24, + HIRAGANA = 'k' | 'a'<<8 | 'n'<<16 | 'a'<<24, + IMPERIAL_ARAMAIC = 'a' | 'r'<<8 | 'm'<<16 | 'i'<<24, + INSCRIPTIONAL_PAHLAVI = 'p' | 'h'<<8 | 'l'<<16 | 'i'<<24, + INSCRIPTIONAL_PARTHIAN = 'p' | 'r'<<8 | 't'<<16 | 'i'<<24, + JAVANESE = 'j' | 'a'<<8 | 'v'<<16 | 'a'<<24, + KAITHI = 'k' | 't'<<8 | 'h'<<16 | 'i'<<24, + KANNADA = 'k' | 'n'<<8 | 'd'<<16 | '2'<<24, + KATAKANA = 'k' | 'a'<<8 | 'n'<<16 | 'a'<<24, + KAWI = 'k' | 'a'<<8 | 'w'<<16 | 'i'<<24, + KAYAH_LI = 'k' | 'a'<<8 | 'l'<<16 | 'i'<<24, + KHAROSHTHI = 'k' | 'h'<<8 | 'a'<<16 | 'r'<<24, + KHITAN_SMALL_SCRIPT = 'k' | 'i'<<8 | 't'<<16 | 's'<<24, + KHMER = 'k' | 'h'<<8 | 'm'<<16 | 'r'<<24, + KHOJKI = 'k' | 'h'<<8 | 'o'<<16 | 'j'<<24, + KHUDAWADI = 's' | 'i'<<8 | 'n'<<16 | 'd'<<24, + KIRAT_RAI = 'k' | 'r'<<8 | 'a'<<16 | 'i'<<24, + LAO = 'l' | 'a'<<8 | 'o'<<16 | ' '<<24, + LATIN = 'l' | 'a'<<8 | 't'<<16 | 'n'<<24, + LEPCHA = 'l' | 'e'<<8 | 'p'<<16 | 'c'<<24, + LIMBU = 'l' | 'i'<<8 | 'm'<<16 | 'b'<<24, + LINEAR_A = 'l' | 'i'<<8 | 'n'<<16 | 'a'<<24, + LINEAR_B = 'l' | 'i'<<8 | 'n'<<16 | 'b'<<24, + LISU = 'l' | 'i'<<8 | 's'<<16 | 'u'<<24, + LYCIAN = 'l' | 'y'<<8 | 'c'<<16 | 'i'<<24, + LYDIAN = 'l' | 'y'<<8 | 'd'<<16 | 'i'<<24, + MAHAJANI = 'm' | 'a'<<8 | 'h'<<16 | 'j'<<24, + MAKASAR = 'm' | 'a'<<8 | 'k'<<16 | 'a'<<24, + MALAYALAM = 'm' | 'l'<<8 | 'm'<<16 | '2'<<24, + MANDAIC = 'm' | 'a'<<8 | 'n'<<16 | 'd'<<24, + MANICHAEAN = 'm' | 'a'<<8 | 'n'<<16 | 'i'<<24, + MARCHEN = 'm' | 'a'<<8 | 'r'<<16 | 'c'<<24, + MASARAM_GONDI = 'g' | 'o'<<8 | 'n'<<16 | 'm'<<24, + MEDEFAIDRIN = 'm' | 'e'<<8 | 'd'<<16 | 'f'<<24, + MEETEI_MAYEK = 'm' | 't'<<8 | 'e'<<16 | 'i'<<24, + MENDE_KIKAKUI = 'm' | 'e'<<8 | 'n'<<16 | 'd'<<24, + MEROITIC_CURSIVE = 'm' | 'e'<<8 | 'r'<<16 | 'c'<<24, + MEROITIC_HIEROGLYPHS = 'm' | 'e'<<8 | 'r'<<16 | 'o'<<24, + MIAO = 'p' | 'l'<<8 | 'r'<<16 | 'd'<<24, + MODI = 'm' | 'o'<<8 | 'd'<<16 | 'i'<<24, + MONGOLIAN = 'm' | 'o'<<8 | 'n'<<16 | 'g'<<24, + MRO = 'm' | 'r'<<8 | 'o'<<16 | 'o'<<24, + MULTANI = 'm' | 'u'<<8 | 'l'<<16 | 't'<<24, + MYANMAR = 'm' | 'y'<<8 | 'm'<<16 | '2'<<24, + NABATAEAN = 'n' | 'b'<<8 | 'a'<<16 | 't'<<24, + NAG_MUNDARI = 'n' | 'a'<<8 | 'g'<<16 | 'm'<<24, + NANDINAGARI = 'n' | 'a'<<8 | 'n'<<16 | 'd'<<24, + NEWA = 'n' | 'e'<<8 | 'w'<<16 | 'a'<<24, + NEW_TAI_LUE = 't' | 'a'<<8 | 'l'<<16 | 'u'<<24, + NKO = 'n' | 'k'<<8 | 'o'<<16 | ' '<<24, + NUSHU = 'n' | 's'<<8 | 'h'<<16 | 'u'<<24, + NYIAKENG_PUACHUE_HMONG = 'h' | 'm'<<8 | 'n'<<16 | 'p'<<24, + OGHAM = 'o' | 'g'<<8 | 'a'<<16 | 'm'<<24, + OL_CHIKI = 'o' | 'l'<<8 | 'c'<<16 | 'k'<<24, + OL_ONAL = 'o' | 'n'<<8 | 'a'<<16 | 'o'<<24, + OLD_ITALIC = 'i' | 't'<<8 | 'a'<<16 | 'l'<<24, + OLD_HUNGARIAN = 'h' | 'u'<<8 | 'n'<<16 | 'g'<<24, + OLD_NORTH_ARABIAN = 'n' | 'a'<<8 | 'r'<<16 | 'b'<<24, + OLD_PERMIC = 'p' | 'e'<<8 | 'r'<<16 | 'm'<<24, + OLD_PERSIAN_CUNEIFORM = 'x' | 'p'<<8 | 'e'<<16 | 'o'<<24, + OLD_SOGDIAN = 's' | 'o'<<8 | 'g'<<16 | 'o'<<24, + OLD_SOUTH_ARABIAN = 's' | 'a'<<8 | 'r'<<16 | 'b'<<24, + OLD_TURKIC = 'o' | 'r'<<8 | 'k'<<16 | 'h'<<24, + OLD_UYGHUR = 'o' | 'u'<<8 | 'g'<<16 | 'r'<<24, + ODIA = 'o' | 'r'<<8 | 'y'<<16 | '2'<<24, + OSAGE = 'o' | 's'<<8 | 'g'<<16 | 'e'<<24, + OSMANYA = 'o' | 's'<<8 | 'm'<<16 | 'a'<<24, + PAHAWH_HMONG = 'h' | 'm'<<8 | 'n'<<16 | 'g'<<24, + PALMYRENE = 'p' | 'a'<<8 | 'l'<<16 | 'm'<<24, + PAU_CIN_HAU = 'p' | 'a'<<8 | 'u'<<16 | 'c'<<24, + PHAGS_PA = 'p' | 'h'<<8 | 'a'<<16 | 'g'<<24, + PHOENICIAN = 'p' | 'h'<<8 | 'n'<<16 | 'x'<<24, + PSALTER_PAHLAVI = 'p' | 'h'<<8 | 'l'<<16 | 'p'<<24, + REJANG = 'r' | 'j'<<8 | 'n'<<16 | 'g'<<24, + RUNIC = 'r' | 'u'<<8 | 'n'<<16 | 'r'<<24, + SAMARITAN = 's' | 'a'<<8 | 'm'<<16 | 'r'<<24, + SAURASHTRA = 's' | 'a'<<8 | 'u'<<16 | 'r'<<24, + SHARADA = 's' | 'h'<<8 | 'r'<<16 | 'd'<<24, + SHAVIAN = 's' | 'h'<<8 | 'a'<<16 | 'w'<<24, + SIDDHAM = 's' | 'i'<<8 | 'd'<<16 | 'd'<<24, + SIGN_WRITING = 's' | 'g'<<8 | 'n'<<16 | 'w'<<24, + SOGDIAN = 's' | 'o'<<8 | 'g'<<16 | 'd'<<24, + SINHALA = 's' | 'i'<<8 | 'n'<<16 | 'h'<<24, + SORA_SOMPENG = 's' | 'o'<<8 | 'r'<<16 | 'a'<<24, + SOYOMBO = 's' | 'o'<<8 | 'y'<<16 | 'o'<<24, + SUMERO_AKKADIAN_CUNEIFORM = 'x' | 's'<<8 | 'u'<<16 | 'x'<<24, + SUNDANESE = 's' | 'u'<<8 | 'n'<<16 | 'd'<<24, + SUNUWAR = 's' | 'u'<<8 | 'n'<<16 | 'u'<<24, + SYLOTI_NAGRI = 's' | 'y'<<8 | 'l'<<16 | 'o'<<24, + SYRIAC = 's' | 'y'<<8 | 'r'<<16 | 'c'<<24, + TAGALOG = 't' | 'g'<<8 | 'l'<<16 | 'g'<<24, + TAGBANWA = 't' | 'a'<<8 | 'g'<<16 | 'b'<<24, + TAI_LE = 't' | 'a'<<8 | 'l'<<16 | 'e'<<24, + TAI_THAM = 'l' | 'a'<<8 | 'n'<<16 | 'a'<<24, + TAI_VIET = 't' | 'a'<<8 | 'v'<<16 | 't'<<24, + TAKRI = 't' | 'a'<<8 | 'k'<<16 | 'r'<<24, + TAMIL = 't' | 'm'<<8 | 'l'<<16 | '2'<<24, + TANGSA = 't' | 'n'<<8 | 's'<<16 | 'a'<<24, + TANGUT = 't' | 'a'<<8 | 'n'<<16 | 'g'<<24, + TELUGU = 't' | 'e'<<8 | 'l'<<16 | '2'<<24, + THAANA = 't' | 'h'<<8 | 'a'<<16 | 'a'<<24, + THAI = 't' | 'h'<<8 | 'a'<<16 | 'i'<<24, + TIBETAN = 't' | 'i'<<8 | 'b'<<16 | 't'<<24, + TIFINAGH = 't' | 'f'<<8 | 'n'<<16 | 'g'<<24, + TIRHUTA = 't' | 'i'<<8 | 'r'<<16 | 'h'<<24, + TODHRI = 't' | 'o'<<8 | 'd'<<16 | 'r'<<24, + TOTO = 't' | 'o'<<8 | 't'<<16 | 'o'<<24, + TULU_TIGALARI = 't' | 'u'<<8 | 't'<<16 | 'g'<<24, + UGARITIC_CUNEIFORM = 'u' | 'g'<<8 | 'a'<<16 | 'r'<<24, + VAI = 'v' | 'a'<<8 | 'i'<<16 | ' '<<24, + VITHKUQI = 'v' | 'i'<<8 | 't'<<16 | 'h'<<24, + WANCHO = 'w' | 'c'<<8 | 'h'<<16 | 'o'<<24, + WARANG_CITI = 'w' | 'a'<<8 | 'r'<<16 | 'a'<<24, + YEZIDI = 'y' | 'e'<<8 | 'z'<<16 | 'i'<<24, + YI = 'y' | 'i'<<8 | ' '<<16 | ' '<<24, + ZANABAZAR_SQUARE = 'z' | 'a'<<8 | 'n'<<16 | 'b'<<24, +} + +script :: enum u32 { + DONT_KNOW, + ADLAM, + AHOM, + ANATOLIAN_HIEROGLYPHS, + ARABIC, + ARMENIAN, + AVESTAN, + BALINESE, + BAMUM, + BASSA_VAH, + BATAK, + BENGALI, + BHAIKSUKI, + BOPOMOFO, + BRAHMI, + BUGINESE, + BUHID, + CANADIAN_SYLLABICS, + CARIAN, + CAUCASIAN_ALBANIAN, + CHAKMA, + CHAM, + CHEROKEE, + CHORASMIAN, + CJK_IDEOGRAPHIC, + COPTIC, + CYPRIOT_SYLLABARY, + CYPRO_MINOAN, + CYRILLIC, + DEFAULT, + DEFAULT2, + DESERET, + DEVANAGARI, + DIVES_AKURU, + DOGRA, + DUPLOYAN, + EGYPTIAN_HIEROGLYPHS, + ELBASAN, + ELYMAIC, + ETHIOPIC, + GARAY, + GEORGIAN, + GLAGOLITIC, + GOTHIC, + GRANTHA, + GREEK, + GUJARATI, + GUNJALA_GONDI, + GURMUKHI, + GURUNG_KHEMA, + HANGUL, + HANIFI_ROHINGYA, + HANUNOO, + HATRAN, + HEBREW, + HIRAGANA, + IMPERIAL_ARAMAIC, + INSCRIPTIONAL_PAHLAVI, + INSCRIPTIONAL_PARTHIAN, + JAVANESE, + KAITHI, + KANNADA, + KATAKANA, + KAWI, + KAYAH_LI, + KHAROSHTHI, + KHITAN_SMALL_SCRIPT, + KHMER, + KHOJKI, + KHUDAWADI, + KIRAT_RAI, + LAO, + LATIN, + LEPCHA, + LIMBU, + LINEAR_A, + LINEAR_B, + LISU, + LYCIAN, + LYDIAN, + MAHAJANI, + MAKASAR, + MALAYALAM, + MANDAIC, + MANICHAEAN, + MARCHEN, + MASARAM_GONDI, + MEDEFAIDRIN, + MEETEI_MAYEK, + MENDE_KIKAKUI, + MEROITIC_CURSIVE, + MEROITIC_HIEROGLYPHS, + MIAO, + MODI, + MONGOLIAN, + MRO, + MULTANI, + MYANMAR, + NABATAEAN, + NAG_MUNDARI, + NANDINAGARI, + NEWA, + NEW_TAI_LUE, + NKO, + NUSHU, + NYIAKENG_PUACHUE_HMONG, + OGHAM, + OL_CHIKI, + OL_ONAL, + OLD_ITALIC, + OLD_HUNGARIAN, + OLD_NORTH_ARABIAN, + OLD_PERMIC, + OLD_PERSIAN_CUNEIFORM, + OLD_SOGDIAN, + OLD_SOUTH_ARABIAN, + OLD_TURKIC, + OLD_UYGHUR, + ODIA, + OSAGE, + OSMANYA, + PAHAWH_HMONG, + PALMYRENE, + PAU_CIN_HAU, + PHAGS_PA, + PHOENICIAN, + PSALTER_PAHLAVI, + REJANG, + RUNIC, + SAMARITAN, + SAURASHTRA, + SHARADA, + SHAVIAN, + SIDDHAM, + SIGN_WRITING, + SOGDIAN, + SINHALA, + SORA_SOMPENG, + SOYOMBO, + SUMERO_AKKADIAN_CUNEIFORM, + SUNDANESE, + SUNUWAR, + SYLOTI_NAGRI, + SYRIAC, + TAGALOG, + TAGBANWA, + TAI_LE, + TAI_THAM, + TAI_VIET, + TAKRI, + TAMIL, + TANGSA, + TANGUT, + TELUGU, + THAANA, + THAI, + TIBETAN, + TIFINAGH, + TIRHUTA, + TODHRI, + TOTO, + TULU_TIGALARI, + UGARITIC_CUNEIFORM, + VAI, + VITHKUQI, + WANCHO, + WARANG_CITI, + YEZIDI, + YI, + ZANABAZAR_SQUARE, +} + +feature_tag :: enum u32 { + UNREGISTERED = 0, // Features that aren't pre-defined in the OpenType spec + isol = 'i' | 's'<<8 | 'o'<<16 | 'l'<<24, // Isolated Forms + fina = 'f' | 'i'<<8 | 'n'<<16 | 'a'<<24, // Terminal Forms + fin2 = 'f' | 'i'<<8 | 'n'<<16 | '2'<<24, // Terminal Forms #2 + fin3 = 'f' | 'i'<<8 | 'n'<<16 | '3'<<24, // Terminal Forms #3 + medi = 'm' | 'e'<<8 | 'd'<<16 | 'i'<<24, // Medial Forms + med2 = 'm' | 'e'<<8 | 'd'<<16 | '2'<<24, // Medial Forms #2 + init = 'i' | 'n'<<8 | 'i'<<16 | 't'<<24, // Initial Forms + ljmo = 'l' | 'j'<<8 | 'm'<<16 | 'o'<<24, // Leading Jamo Forms + vjmo = 'v' | 'j'<<8 | 'm'<<16 | 'o'<<24, // Vowel Jamo Forms + tjmo = 't' | 'j'<<8 | 'm'<<16 | 'o'<<24, // Trailing Jamo Forms + rphf = 'r' | 'p'<<8 | 'h'<<16 | 'f'<<24, // Reph Form + blwf = 'b' | 'l'<<8 | 'w'<<16 | 'f'<<24, // Below-base Forms + half = 'h' | 'a'<<8 | 'l'<<16 | 'f'<<24, // Half Forms + pstf = 'p' | 's'<<8 | 't'<<16 | 'f'<<24, // Post-base Forms + abvf = 'a' | 'b'<<8 | 'v'<<16 | 'f'<<24, // Above-base Forms + pref = 'p' | 'r'<<8 | 'e'<<16 | 'f'<<24, // Pre-base Forms + numr = 'n' | 'u'<<8 | 'm'<<16 | 'r'<<24, // Numerators + frac = 'f' | 'r'<<8 | 'a'<<16 | 'c'<<24, // Fractions + dnom = 'd' | 'n'<<8 | 'o'<<16 | 'm'<<24, // Denominators + cfar = 'c' | 'f'<<8 | 'a'<<16 | 'r'<<24, // Conjunct Form After Ro + aalt = 'a' | 'a'<<8 | 'l'<<16 | 't'<<24, // Access All Alternates + abvm = 'a' | 'b'<<8 | 'v'<<16 | 'm'<<24, // Above-base Mark Positioning + abvs = 'a' | 'b'<<8 | 'v'<<16 | 's'<<24, // Above-base Substitutions + afrc = 'a' | 'f'<<8 | 'r'<<16 | 'c'<<24, // Alternative Fractions + akhn = 'a' | 'k'<<8 | 'h'<<16 | 'n'<<24, // Akhand + apkn = 'a' | 'p'<<8 | 'k'<<16 | 'n'<<24, // Kerning for Alternate Proportional Widths + blwm = 'b' | 'l'<<8 | 'w'<<16 | 'm'<<24, // Below-base Mark Positioning + blws = 'b' | 'l'<<8 | 'w'<<16 | 's'<<24, // Below-base Substitutions + calt = 'c' | 'a'<<8 | 'l'<<16 | 't'<<24, // Contextual Alternates + Case = 'c' | 'a'<<8 | 's'<<16 | 'e'<<24, // Case-sensitive Forms + ccmp = 'c' | 'c'<<8 | 'm'<<16 | 'p'<<24, // Glyph Composition / Decomposition + chws = 'c' | 'h'<<8 | 'w'<<16 | 's'<<24, // Contextual Half-width Spacing + cjct = 'c' | 'j'<<8 | 'c'<<16 | 't'<<24, // Conjunct Forms + clig = 'c' | 'l'<<8 | 'i'<<16 | 'g'<<24, // Contextual Ligatures + cpct = 'c' | 'p'<<8 | 'c'<<16 | 't'<<24, // Centered CJK Punctuation + cpsp = 'c' | 'p'<<8 | 's'<<16 | 'p'<<24, // Capital Spacing + cswh = 'c' | 's'<<8 | 'w'<<16 | 'h'<<24, // Contextual Swash + curs = 'c' | 'u'<<8 | 'r'<<16 | 's'<<24, // Cursive Positioning + cv01 = 'c' | 'v'<<8 | '0'<<16 | '1'<<24, // Character Variant 1 + cv02 = 'c' | 'v'<<8 | '0'<<16 | '2'<<24, // Character Variant 2 + cv03 = 'c' | 'v'<<8 | '0'<<16 | '3'<<24, // Character Variant 3 + cv04 = 'c' | 'v'<<8 | '0'<<16 | '4'<<24, // Character Variant 4 + cv05 = 'c' | 'v'<<8 | '0'<<16 | '5'<<24, // Character Variant 5 + cv06 = 'c' | 'v'<<8 | '0'<<16 | '6'<<24, // Character Variant 6 + cv07 = 'c' | 'v'<<8 | '0'<<16 | '7'<<24, // Character Variant 7 + cv08 = 'c' | 'v'<<8 | '0'<<16 | '8'<<24, // Character Variant 8 + cv09 = 'c' | 'v'<<8 | '0'<<16 | '9'<<24, // Character Variant 9 + cv10 = 'c' | 'v'<<8 | '1'<<16 | '0'<<24, // Character Variant 10 + cv11 = 'c' | 'v'<<8 | '1'<<16 | '1'<<24, // Character Variant 11 + cv12 = 'c' | 'v'<<8 | '1'<<16 | '2'<<24, // Character Variant 12 + cv13 = 'c' | 'v'<<8 | '1'<<16 | '3'<<24, // Character Variant 13 + cv14 = 'c' | 'v'<<8 | '1'<<16 | '4'<<24, // Character Variant 14 + cv15 = 'c' | 'v'<<8 | '1'<<16 | '5'<<24, // Character Variant 15 + cv16 = 'c' | 'v'<<8 | '1'<<16 | '6'<<24, // Character Variant 16 + cv17 = 'c' | 'v'<<8 | '1'<<16 | '7'<<24, // Character Variant 17 + cv18 = 'c' | 'v'<<8 | '1'<<16 | '8'<<24, // Character Variant 18 + cv19 = 'c' | 'v'<<8 | '1'<<16 | '9'<<24, // Character Variant 19 + cv20 = 'c' | 'v'<<8 | '2'<<16 | '0'<<24, // Character Variant 20 + cv21 = 'c' | 'v'<<8 | '2'<<16 | '1'<<24, // Character Variant 21 + cv22 = 'c' | 'v'<<8 | '2'<<16 | '2'<<24, // Character Variant 22 + cv23 = 'c' | 'v'<<8 | '2'<<16 | '3'<<24, // Character Variant 23 + cv24 = 'c' | 'v'<<8 | '2'<<16 | '4'<<24, // Character Variant 24 + cv25 = 'c' | 'v'<<8 | '2'<<16 | '5'<<24, // Character Variant 25 + cv26 = 'c' | 'v'<<8 | '2'<<16 | '6'<<24, // Character Variant 26 + cv27 = 'c' | 'v'<<8 | '2'<<16 | '7'<<24, // Character Variant 27 + cv28 = 'c' | 'v'<<8 | '2'<<16 | '8'<<24, // Character Variant 28 + cv29 = 'c' | 'v'<<8 | '2'<<16 | '9'<<24, // Character Variant 29 + cv30 = 'c' | 'v'<<8 | '3'<<16 | '0'<<24, // Character Variant 30 + cv31 = 'c' | 'v'<<8 | '3'<<16 | '1'<<24, // Character Variant 31 + cv32 = 'c' | 'v'<<8 | '3'<<16 | '2'<<24, // Character Variant 32 + cv33 = 'c' | 'v'<<8 | '3'<<16 | '3'<<24, // Character Variant 33 + cv34 = 'c' | 'v'<<8 | '3'<<16 | '4'<<24, // Character Variant 34 + cv35 = 'c' | 'v'<<8 | '3'<<16 | '5'<<24, // Character Variant 35 + cv36 = 'c' | 'v'<<8 | '3'<<16 | '6'<<24, // Character Variant 36 + cv37 = 'c' | 'v'<<8 | '3'<<16 | '7'<<24, // Character Variant 37 + cv38 = 'c' | 'v'<<8 | '3'<<16 | '8'<<24, // Character Variant 38 + cv39 = 'c' | 'v'<<8 | '3'<<16 | '9'<<24, // Character Variant 39 + cv40 = 'c' | 'v'<<8 | '4'<<16 | '0'<<24, // Character Variant 40 + cv41 = 'c' | 'v'<<8 | '4'<<16 | '1'<<24, // Character Variant 41 + cv42 = 'c' | 'v'<<8 | '4'<<16 | '2'<<24, // Character Variant 42 + cv43 = 'c' | 'v'<<8 | '4'<<16 | '3'<<24, // Character Variant 43 + cv44 = 'c' | 'v'<<8 | '4'<<16 | '4'<<24, // Character Variant 44 + cv45 = 'c' | 'v'<<8 | '4'<<16 | '5'<<24, // Character Variant 45 + cv46 = 'c' | 'v'<<8 | '4'<<16 | '6'<<24, // Character Variant 46 + cv47 = 'c' | 'v'<<8 | '4'<<16 | '7'<<24, // Character Variant 47 + cv48 = 'c' | 'v'<<8 | '4'<<16 | '8'<<24, // Character Variant 48 + cv49 = 'c' | 'v'<<8 | '4'<<16 | '9'<<24, // Character Variant 49 + cv50 = 'c' | 'v'<<8 | '5'<<16 | '0'<<24, // Character Variant 50 + cv51 = 'c' | 'v'<<8 | '5'<<16 | '1'<<24, // Character Variant 51 + cv52 = 'c' | 'v'<<8 | '5'<<16 | '2'<<24, // Character Variant 52 + cv53 = 'c' | 'v'<<8 | '5'<<16 | '3'<<24, // Character Variant 53 + cv54 = 'c' | 'v'<<8 | '5'<<16 | '4'<<24, // Character Variant 54 + cv55 = 'c' | 'v'<<8 | '5'<<16 | '5'<<24, // Character Variant 55 + cv56 = 'c' | 'v'<<8 | '5'<<16 | '6'<<24, // Character Variant 56 + cv57 = 'c' | 'v'<<8 | '5'<<16 | '7'<<24, // Character Variant 57 + cv58 = 'c' | 'v'<<8 | '5'<<16 | '8'<<24, // Character Variant 58 + cv59 = 'c' | 'v'<<8 | '5'<<16 | '9'<<24, // Character Variant 59 + cv60 = 'c' | 'v'<<8 | '6'<<16 | '0'<<24, // Character Variant 60 + cv61 = 'c' | 'v'<<8 | '6'<<16 | '1'<<24, // Character Variant 61 + cv62 = 'c' | 'v'<<8 | '6'<<16 | '2'<<24, // Character Variant 62 + cv63 = 'c' | 'v'<<8 | '6'<<16 | '3'<<24, // Character Variant 63 + cv64 = 'c' | 'v'<<8 | '6'<<16 | '4'<<24, // Character Variant 64 + cv65 = 'c' | 'v'<<8 | '6'<<16 | '5'<<24, // Character Variant 65 + cv66 = 'c' | 'v'<<8 | '6'<<16 | '6'<<24, // Character Variant 66 + cv67 = 'c' | 'v'<<8 | '6'<<16 | '7'<<24, // Character Variant 67 + cv68 = 'c' | 'v'<<8 | '6'<<16 | '8'<<24, // Character Variant 68 + cv69 = 'c' | 'v'<<8 | '6'<<16 | '9'<<24, // Character Variant 69 + cv70 = 'c' | 'v'<<8 | '7'<<16 | '0'<<24, // Character Variant 70 + cv71 = 'c' | 'v'<<8 | '7'<<16 | '1'<<24, // Character Variant 71 + cv72 = 'c' | 'v'<<8 | '7'<<16 | '2'<<24, // Character Variant 72 + cv73 = 'c' | 'v'<<8 | '7'<<16 | '3'<<24, // Character Variant 73 + cv74 = 'c' | 'v'<<8 | '7'<<16 | '4'<<24, // Character Variant 74 + cv75 = 'c' | 'v'<<8 | '7'<<16 | '5'<<24, // Character Variant 75 + cv76 = 'c' | 'v'<<8 | '7'<<16 | '6'<<24, // Character Variant 76 + cv77 = 'c' | 'v'<<8 | '7'<<16 | '7'<<24, // Character Variant 77 + cv78 = 'c' | 'v'<<8 | '7'<<16 | '8'<<24, // Character Variant 78 + cv79 = 'c' | 'v'<<8 | '7'<<16 | '9'<<24, // Character Variant 79 + cv80 = 'c' | 'v'<<8 | '8'<<16 | '0'<<24, // Character Variant 80 + cv81 = 'c' | 'v'<<8 | '8'<<16 | '1'<<24, // Character Variant 81 + cv82 = 'c' | 'v'<<8 | '8'<<16 | '2'<<24, // Character Variant 82 + cv83 = 'c' | 'v'<<8 | '8'<<16 | '3'<<24, // Character Variant 83 + cv84 = 'c' | 'v'<<8 | '8'<<16 | '4'<<24, // Character Variant 84 + cv85 = 'c' | 'v'<<8 | '8'<<16 | '5'<<24, // Character Variant 85 + cv86 = 'c' | 'v'<<8 | '8'<<16 | '6'<<24, // Character Variant 86 + cv87 = 'c' | 'v'<<8 | '8'<<16 | '7'<<24, // Character Variant 87 + cv88 = 'c' | 'v'<<8 | '8'<<16 | '8'<<24, // Character Variant 88 + cv89 = 'c' | 'v'<<8 | '8'<<16 | '9'<<24, // Character Variant 89 + cv90 = 'c' | 'v'<<8 | '9'<<16 | '0'<<24, // Character Variant 90 + cv91 = 'c' | 'v'<<8 | '9'<<16 | '1'<<24, // Character Variant 91 + cv92 = 'c' | 'v'<<8 | '9'<<16 | '2'<<24, // Character Variant 92 + cv93 = 'c' | 'v'<<8 | '9'<<16 | '3'<<24, // Character Variant 93 + cv94 = 'c' | 'v'<<8 | '9'<<16 | '4'<<24, // Character Variant 94 + cv95 = 'c' | 'v'<<8 | '9'<<16 | '5'<<24, // Character Variant 95 + cv96 = 'c' | 'v'<<8 | '9'<<16 | '6'<<24, // Character Variant 96 + cv97 = 'c' | 'v'<<8 | '9'<<16 | '7'<<24, // Character Variant 97 + cv98 = 'c' | 'v'<<8 | '9'<<16 | '8'<<24, // Character Variant 98 + cv99 = 'c' | 'v'<<8 | '9'<<16 | '9'<<24, // Character Variant 99 + c2pc = 'c' | '2'<<8 | 'p'<<16 | 'c'<<24, // Petite Capitals From Capitals + c2sc = 'c' | '2'<<8 | 's'<<16 | 'c'<<24, // Small Capitals From Capitals + dist = 'd' | 'i'<<8 | 's'<<16 | 't'<<24, // Distances + dlig = 'd' | 'l'<<8 | 'i'<<16 | 'g'<<24, // Discretionary Ligatures + dtls = 'd' | 't'<<8 | 'l'<<16 | 's'<<24, // Dotless Forms + expt = 'e' | 'x'<<8 | 'p'<<16 | 't'<<24, // Expert Forms + falt = 'f' | 'a'<<8 | 'l'<<16 | 't'<<24, // Final Glyph on Line Alternates + flac = 'f' | 'l'<<8 | 'a'<<16 | 'c'<<24, // Flattened Accent Forms + fwid = 'f' | 'w'<<8 | 'i'<<16 | 'd'<<24, // Full Widths + haln = 'h' | 'a'<<8 | 'l'<<16 | 'n'<<24, // Halant Forms + halt = 'h' | 'a'<<8 | 'l'<<16 | 't'<<24, // Alternate Half Widths + hist = 'h' | 'i'<<8 | 's'<<16 | 't'<<24, // Historical Forms + hkna = 'h' | 'k'<<8 | 'n'<<16 | 'a'<<24, // Horizontal Kana Alternates + hlig = 'h' | 'l'<<8 | 'i'<<16 | 'g'<<24, // Historical Ligatures + hngl = 'h' | 'n'<<8 | 'g'<<16 | 'l'<<24, // Hangul + hojo = 'h' | 'o'<<8 | 'j'<<16 | 'o'<<24, // Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms) + hwid = 'h' | 'w'<<8 | 'i'<<16 | 'd'<<24, // Half Widths + ital = 'i' | 't'<<8 | 'a'<<16 | 'l'<<24, // Italics + jalt = 'j' | 'a'<<8 | 'l'<<16 | 't'<<24, // Justification Alternates + jp78 = 'j' | 'p'<<8 | '7'<<16 | '8'<<24, // JIS78 Forms + jp83 = 'j' | 'p'<<8 | '8'<<16 | '3'<<24, // JIS83 Forms + jp90 = 'j' | 'p'<<8 | '9'<<16 | '0'<<24, // JIS90 Forms + jp04 = 'j' | 'p'<<8 | '0'<<16 | '4'<<24, // JIS2004 Forms + kern = 'k' | 'e'<<8 | 'r'<<16 | 'n'<<24, // Kerning + lfbd = 'l' | 'f'<<8 | 'b'<<16 | 'd'<<24, // Left Bounds + liga = 'l' | 'i'<<8 | 'g'<<16 | 'a'<<24, // Standard Ligatures + lnum = 'l' | 'n'<<8 | 'u'<<16 | 'm'<<24, // Lining Figures + locl = 'l' | 'o'<<8 | 'c'<<16 | 'l'<<24, // Localized Forms + ltra = 'l' | 't'<<8 | 'r'<<16 | 'a'<<24, // Left-to-right Alternates + ltrm = 'l' | 't'<<8 | 'r'<<16 | 'm'<<24, // Left-to-right Mirrored Forms + mark = 'm' | 'a'<<8 | 'r'<<16 | 'k'<<24, // Mark Positioning + mgrk = 'm' | 'g'<<8 | 'r'<<16 | 'k'<<24, // Mathematical Greek + mkmk = 'm' | 'k'<<8 | 'm'<<16 | 'k'<<24, // Mark to Mark Positioning + mset = 'm' | 's'<<8 | 'e'<<16 | 't'<<24, // Mark Positioning via Substitution + nalt = 'n' | 'a'<<8 | 'l'<<16 | 't'<<24, // Alternate Annotation Forms + nlck = 'n' | 'l'<<8 | 'c'<<16 | 'k'<<24, // NLC Kanji Forms + nukt = 'n' | 'u'<<8 | 'k'<<16 | 't'<<24, // Nukta Forms + onum = 'o' | 'n'<<8 | 'u'<<16 | 'm'<<24, // Oldstyle Figures + opbd = 'o' | 'p'<<8 | 'b'<<16 | 'd'<<24, // Optical Bounds + ordn = 'o' | 'r'<<8 | 'd'<<16 | 'n'<<24, // Ordinals + ornm = 'o' | 'r'<<8 | 'n'<<16 | 'm'<<24, // Ornaments + palt = 'p' | 'a'<<8 | 'l'<<16 | 't'<<24, // Proportional Alternate Widths + pcap = 'p' | 'c'<<8 | 'a'<<16 | 'p'<<24, // Petite Capitals + pkna = 'p' | 'k'<<8 | 'n'<<16 | 'a'<<24, // Proportional Kana + pnum = 'p' | 'n'<<8 | 'u'<<16 | 'm'<<24, // Proportional Figures + pres = 'p' | 'r'<<8 | 'e'<<16 | 's'<<24, // Pre-base Substitutions + psts = 'p' | 's'<<8 | 't'<<16 | 's'<<24, // Post-base Substitutions + pwid = 'p' | 'w'<<8 | 'i'<<16 | 'd'<<24, // Proportional Widths + qwid = 'q' | 'w'<<8 | 'i'<<16 | 'd'<<24, // Quarter Widths + rand = 'r' | 'a'<<8 | 'n'<<16 | 'd'<<24, // Randomize + rclt = 'r' | 'c'<<8 | 'l'<<16 | 't'<<24, // Required Contextual Alternates + rkrf = 'r' | 'k'<<8 | 'r'<<16 | 'f'<<24, // Rakar Forms + rlig = 'r' | 'l'<<8 | 'i'<<16 | 'g'<<24, // Required Ligatures + rtbd = 'r' | 't'<<8 | 'b'<<16 | 'd'<<24, // Right Bounds + rtla = 'r' | 't'<<8 | 'l'<<16 | 'a'<<24, // Right-to-left Alternates + rtlm = 'r' | 't'<<8 | 'l'<<16 | 'm'<<24, // Right-to-left Mirrored Forms + ruby = 'r' | 'u'<<8 | 'b'<<16 | 'y'<<24, // Ruby Notation Forms + rvrn = 'r' | 'v'<<8 | 'r'<<16 | 'n'<<24, // Required Variation Alternates + salt = 's' | 'a'<<8 | 'l'<<16 | 't'<<24, // Stylistic Alternates + sinf = 's' | 'i'<<8 | 'n'<<16 | 'f'<<24, // Scientific Inferiors + size = 's' | 'i'<<8 | 'z'<<16 | 'e'<<24, // Optical size + smcp = 's' | 'm'<<8 | 'c'<<16 | 'p'<<24, // Small Capitals + smpl = 's' | 'm'<<8 | 'p'<<16 | 'l'<<24, // Simplified Forms + ss01 = 's' | 's'<<8 | '0'<<16 | '1'<<24, // Stylistic Set 1 + ss02 = 's' | 's'<<8 | '0'<<16 | '2'<<24, // Stylistic Set 2 + ss03 = 's' | 's'<<8 | '0'<<16 | '3'<<24, // Stylistic Set 3 + ss04 = 's' | 's'<<8 | '0'<<16 | '4'<<24, // Stylistic Set 4 + ss05 = 's' | 's'<<8 | '0'<<16 | '5'<<24, // Stylistic Set 5 + ss06 = 's' | 's'<<8 | '0'<<16 | '6'<<24, // Stylistic Set 6 + ss07 = 's' | 's'<<8 | '0'<<16 | '7'<<24, // Stylistic Set 7 + ss08 = 's' | 's'<<8 | '0'<<16 | '8'<<24, // Stylistic Set 8 + ss09 = 's' | 's'<<8 | '0'<<16 | '9'<<24, // Stylistic Set 9 + ss10 = 's' | 's'<<8 | '1'<<16 | '0'<<24, // Stylistic Set 10 + ss11 = 's' | 's'<<8 | '1'<<16 | '1'<<24, // Stylistic Set 11 + ss12 = 's' | 's'<<8 | '1'<<16 | '2'<<24, // Stylistic Set 12 + ss13 = 's' | 's'<<8 | '1'<<16 | '3'<<24, // Stylistic Set 13 + ss14 = 's' | 's'<<8 | '1'<<16 | '4'<<24, // Stylistic Set 14 + ss15 = 's' | 's'<<8 | '1'<<16 | '5'<<24, // Stylistic Set 15 + ss16 = 's' | 's'<<8 | '1'<<16 | '6'<<24, // Stylistic Set 16 + ss17 = 's' | 's'<<8 | '1'<<16 | '7'<<24, // Stylistic Set 17 + ss18 = 's' | 's'<<8 | '1'<<16 | '8'<<24, // Stylistic Set 18 + ss19 = 's' | 's'<<8 | '1'<<16 | '9'<<24, // Stylistic Set 19 + ss20 = 's' | 's'<<8 | '2'<<16 | '0'<<24, // Stylistic Set 20 + ssty = 's' | 's'<<8 | 't'<<16 | 'y'<<24, // Math Script-style Alternates + stch = 's' | 't'<<8 | 'c'<<16 | 'h'<<24, // Stretching Glyph Decomposition + subs = 's' | 'u'<<8 | 'b'<<16 | 's'<<24, // Subscript + sups = 's' | 'u'<<8 | 'p'<<16 | 's'<<24, // Superscript + swsh = 's' | 'w'<<8 | 's'<<16 | 'h'<<24, // Swash + test = 't' | 'e'<<8 | 's'<<16 | 't'<<24, // Test features, only for development + titl = 't' | 'i'<<8 | 't'<<16 | 'l'<<24, // Titling + tnam = 't' | 'n'<<8 | 'a'<<16 | 'm'<<24, // Traditional Name Forms + tnum = 't' | 'n'<<8 | 'u'<<16 | 'm'<<24, // Tabular Figures + trad = 't' | 'r'<<8 | 'a'<<16 | 'd'<<24, // Traditional Forms + twid = 't' | 'w'<<8 | 'i'<<16 | 'd'<<24, // Third Widths + unic = 'u' | 'n'<<8 | 'i'<<16 | 'c'<<24, // Unicase + valt = 'v' | 'a'<<8 | 'l'<<16 | 't'<<24, // Alternate Vertical Metrics + vapk = 'v' | 'a'<<8 | 'p'<<16 | 'k'<<24, // Kerning for Alternate Proportional Vertical Metrics + vatu = 'v' | 'a'<<8 | 't'<<16 | 'u'<<24, // Vattu Variants + vchw = 'v' | 'c'<<8 | 'h'<<16 | 'w'<<24, // Vertical Contextual Half-width Spacing + vert = 'v' | 'e'<<8 | 'r'<<16 | 't'<<24, // Vertical Alternates + vhal = 'v' | 'h'<<8 | 'a'<<16 | 'l'<<24, // Alternate Vertical Half Metrics + vkna = 'v' | 'k'<<8 | 'n'<<16 | 'a'<<24, // Vertical Kana Alternates + vkrn = 'v' | 'k'<<8 | 'r'<<16 | 'n'<<24, // Vertical Kerning + vpal = 'v' | 'p'<<8 | 'a'<<16 | 'l'<<24, // Proportional Alternate Vertical Metrics + vrt2 = 'v' | 'r'<<8 | 't'<<16 | '2'<<24, // Vertical Alternates and Rotation + vrtr = 'v' | 'r'<<8 | 't'<<16 | 'r'<<24, // Vertical Alternates for Rotation + zero = 'z' | 'e'<<8 | 'r'<<16 | 'o'<<24, // Slashed Zero +} + +_gdef :: struct {} +_cmap_14 :: struct {} +_gsub_gpos :: struct {} +_maxp :: struct {} +_hea :: struct {} +shaper_properties :: struct {} +_feature :: struct {} +_head :: struct {} +_langsys :: struct {} +shape_config :: struct {} +glyph_config :: struct {} +shape_context :: struct {} + +allocator_op_allocate :: struct { + Pointer: rawptr, + Size: u32, +} + +allocator_op_free :: struct { + Pointer: rawptr, +} + +allocator_op :: struct { + Kind: allocator_op_kind, + + using op: struct #raw_union { + Allocate: allocator_op_allocate `raw_union_tag:"Kind=.ALLOCATE"`, + Free: allocator_op_free `raw_union_tag:"Kind=.FREE"`, + }, +} + +allocator_function :: #type proc "c" (Data: rawptr, Op: ^allocator_op) + +lookup_subtable_info :: struct { + MinimumBacktrackPlusOne: u16, + MinimumFollowupPlusOne: u16, +} + +blob_table :: struct { + OffsetFromStartOfFile: u32, + Length: u32, +} + +load_font_state :: struct { + FontData: rawptr, + FontDataSize: u32, + + Tables: [blob_table_id]blob_table, + LookupCount: u32, + LookupSubtableCount: u32, + GlyphCount: u32, + ScratchSize: u32, + + GlyphLookupMatrixSizeInBytes: u32, + GlyphLookupSubtableMatrixSizeInBytes: u32, + TotalSize: u32, +} + +blob_header :: struct { + Magic: u32, + Version: u32, + + LookupCount: u32, + LookupSubtableCount: u32, + GlyphCount: u32, + + GposLookupIndexOffset: u32, + + GlyphLookupMatrixOffsetFromStartOfFile: u32, + GlyphLookupSubtableMatrixOffsetFromStartOfFile: u32, + LookupSubtableIndexOffsetsOffsetFromStartOfFile: u32, + SubtableInfosOffsetFromStartOfFile: u32, + + Tables: [blob_table_id]blob_table, +} + +font :: struct { + Allocator: allocator_function, + AllocatorData: rawptr, + + Blob: ^blob_header, + Cmap: ^u16, + Cmap14: ^_cmap_14, + + ShapingTables: [shaping_table]^_gsub_gpos, + + UserData: rawptr, + + Error: load_font_error, +} + +font_info :: struct { + Strings: [font_info_string_id]cstring, + StringLengths: [font_info_string_id]u16, + + StyleFlags: font_style_flags, + Weight: font_weight, + Width: font_width, +} + +feature_override :: struct { + Tag: feature_tag, + Value: c.int, +} + +break_type :: struct { + // The break code mostly works in relative positions, but we convert to absolute positions for the user. + // That way, breaks can be trivially stored and compared and such and it just works. + Position: c.int, + Flags: break_flags, + Direction: direction, // Only valid if (DIRECTION in Flags). + ParagraphDirection: direction, // Only valid if (PARAGRAPH_DIRECTION in Flags). + Script: script, // Only valid if (SCRIPT in Flags). +} + +bracket :: struct { + Codepoint: rune, + Position: u32, + using DirectionBitField: bit_field u8 { + Direction: direction | 8, + }, + using ScriptBitField: bit_field u8 { + Script: script | 8, + }, +} + +// In the worst case, a single call to BreakAddCodepoint would generate 4 breaks. +// We buffer breaks to reorder them before returning them to the user. +// This potentially requires infinite memory, which we don't have, so you may want to tweak this constant, +// although, really, if the defaults don't work, then you have likely found very strange/adversarial text. +break_state :: struct { + Breaks: [8]break_type `fmt:"v,BreakCount"`, + BreakCount: u32, + + ParagraphDirection: direction, + UserParagraphDirection: direction, + + CurrentPosition: u32, + ParagraphStartPosition: u32, + + LastScriptBreakPosition: u32, + LastDirectionBreakPosition: u32, + LastScriptBreakScript: u8, + LastDirectionBreakDirection: u8, + + ScriptPositionOffset: i16, + ScriptCount: u32, + ScriptSet: [MAXIMUM_CODEPOINT_SCRIPTS]u8 `fmt:"v,ScriptCount"`, + + Brackets: [64]bracket `fmt:"v,BracketCount"`, + BracketCount: u32, + Flags: break_state_flags, + + FlagState: bit_field u32 { + _0: u32 | 8, // break_flags + _1: u32 | 8, // break_flags + _2: u32 | 8, // break_flags + _3: u32 | 8, // break_flags + }, + PositionOffset2: i16, + PositionOffset3: i16, + + WordBreakHistory: bit_field u32 { + _0: u32 | 8, + _1: u32 | 8, + _2: u32 | 8, + _3: u32 | 8, + }, + WordBreaks, + WordUnbreaks: bit_field u16 { + _0: u16 | 4, + _1: u16 | 4, + _2: u16 | 4, + _3: u16 | 4, + }, + WordBreak2PositionOffset: i16, + + LineBreaks: bit_field u64 { + _0: u64 | 16, + _1: u64 | 16, + _2: u64 | 16, + _3: u64 | 16, + }, + // Instead of staying synchronized with LineBreaks/LineUnbreaks, + // this advances every character always. + // (This is only needed because ZWJ can create an unbreak while simultaneously being ignored.) + LineUnbreaksAsync: bit_field u64 { + _0: u64 | 16, + _1: u64 | 16, + _2: u64 | 16, + _3: u64 | 16, + }, + LineUnbreaks: bit_field u64 { + _0: u64 | 16, + _1: u64 | 16, + _2: u64 | 16, + _3: u64 | 16, + }, + LineBreakHistory: bit_field u32 { + _0: u32 | 8, + _1: u32 | 8, + _2: u32 | 8, + _3: u32 | 8, + }, + LineBreak2PositionOffset: i16, + LineBreak3PositionOffset: i16, + + using LastDirectionBitField: bit_field u8 { + LastDirection: direction | 8, + }, + BidirectionalClass2: u8, + BidirectionalClass1: u8, + Bidirectional1PositionOffset: i16, + Bidirectional2PositionOffset: i16, + + JapaneseLineBreakStyle: japanese_line_break_style, + ConfigFlags: break_config_flags, + GraphemeBreakState: u8, + LastLineBreakClass: u8, + LastWordBreakClass: u8, + LastWordBreakClassIncludingIgnored: u8, +} + +decode :: struct { + Codepoint: rune, + + SourceCharactersConsumed: c.int, + Valid: b32, +} + +encode_utf8 :: struct { + Encoded: [4]u8 `fmt:"q,EncodedLength"`, + EncodedLength: c.int, + Valid: b32, +} + +glyph_classes :: struct { + Class: u16, + MarkAttachmentClass: u16, +} + +glyph :: struct { + Prev: ^glyph, + Next: ^glyph, + + Codepoint: rune, + Id: u16, // Glyph index. This is what you want to use to query outline data. + Uid: u16, + + // This field is kept and returned as-is throughout the shaping process. + // When you are using the context API, it contains a codepoint index always! + // To get the original user ID with the context API, you need to get the corresponding shape_codepoint + // with ShapeGetShapeCodepoint(Context, Glyph^.UserIdOrCodepointIndex, ...); + UserIdOrCodepointIndex: c.int, + + // Used by GPOS + OffsetX: i32, + OffsetY: i32, + AdvanceX: i32, + AdvanceY: i32, + + // Earlier on, we used to assume that, if a glyph had no advance, or had the MARK glyph class, then + // it could be handled as a mark in layout operations. This is inaccurate. + // Unicode makes a distinction between attached marks and standalone marks. For our purposes, attached + // marks are marks that have found a valid base character to attach to. In practice, this means that the + // font contains a valid display position/configuration for it in the current context. + // In contrast, standalone marks are marks that aren't attached to anything. Fonts may still have glyphs + // for them, in which case we want to display those just like regular glyphs that take up horizontal space + // on the line. When fonts don't have glyphs for them, they simply stay around as zero-width glyphs. + // Standalone marks have notably different behavior compared to attached marks, and so, once we start + // applying positioning features, it becomes worthwhile to track exactly which glyph has attached to which. + AttachGlyph: ^glyph, // Set by GPOS attachments. + + Config: ^glyph_config, + + Decomposition: u64, + + Classes: glyph_classes, + + Flags: glyph_flags, + + ParentInfo: u32, + + // This is set by GSUB and used by GPOS. + // A 0-index means that we should attach to the last component in the ligature. + // + // From the Microsoft docs: + // To correctly access the subtables, the client must keep track of the component associated with the mark. + // + // For a given mark assigned to a particular class, the appropriate base attachment point is determined by which + // ligature component the mark is associated with. This is dependent on the original character string and subsequent + // character- or glyph-sequence processing, not the font data alone. While a text-layout client is performing any + // character-based preprocessing or any glyph-substitution operations using the GSUB table, the text-layout client + // must keep track of associations of marks to particular ligature-glyph components. + LigatureUid: u16, + LigatureComponentIndexPlusOne: u16, + LigatureComponentCount: u16, + + // Set in GSUB and used in GPOS, for STCH. + JoiningFeature: joining_feature, + + // Unicode properties filled in by CodepointToGlyph. + JoiningType: unicode_joining_type, + UnicodeFlags: unicode_flags, + SyllabicClass: u8, + SyllabicPosition: u8, + UseClass: u8, + CombiningClass: u8, + + MarkOrdering: u8, // Only used temporarily in NORMALIZE for Arabic mark reordering. +} + +shape_codepoint :: struct { + Font: ^font, // Only set when (.GRAPHEME in BreakFlags) + Config: ^glyph_config, + + Codepoint: rune, + UserId: c.int, + + BreakFlags: break_flags, + Script: script, // Only set when (BreakFlags & KBTS_BREAK_FLAG_SCRIPT) != 0. + Direction: direction, // Only set when (BreakFlags & KBTS_BREAK_FLAG_DIRECTION) != 0. + ParagraphDirection: direction, // Only set when (BreakFlags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) != 0. +} + +shape_codepoint_iterator :: struct { + Codepoint: ^shape_codepoint, + Context: ^shape_context, + + EndBlockIndex: u32, + OnePastLastCodepointIndex: u32, + BlockIndex: u32, + CodepointIndex: u32, + CurrentBlockCodepointCount: u32, + FlatCodepointIndex: u32, +} + +glyph_iterator :: struct { + GlyphStorage: ^glyph_storage, + CurrentGlyph: ^glyph, + + LastAdvanceX: c.int, + X: c.int, + Y: c.int, +} + +arena_block_header :: struct { + Prev: ^arena_block_header, + Next: ^arena_block_header, +} + +arena :: struct { + Allocator: allocator_function, + AllocatorData: rawptr, + + BlockSentinel: arena_block_header, + FreeBlockSentinel: arena_block_header, + + Error: b32, +} + +glyph_storage :: struct { + Arena: arena, + + GlyphSentinel: glyph, + FreeGlyphSentinel: glyph, + + Error: b32, +} + +glyph_parent :: struct { + Decomposition: u64, + Codepoint: rune, +} + +font_coverage_test :: struct { + Font: ^font, + BaseCodepoint: rune, + + CurrentBaseError: b32, + Error: b32, + + BaseParents: [MAXIMUM_RECOMPOSITION_PARENTS]glyph_parent `fmt:"v,BaseParentCount"`, + BaseParentCount: u32, +} + +run :: struct { + Font: ^font, + Script: script, + ParagraphDirection: direction, + Direction: direction, + Flags: break_flags, + + Glyphs: glyph_iterator, +} \ No newline at end of file diff --git a/vendor/kb_text_shape/lib/kb_text_shape.lib b/vendor/kb_text_shape/lib/kb_text_shape.lib new file mode 100644 index 000000000..6a48e9f87 Binary files /dev/null and b/vendor/kb_text_shape/lib/kb_text_shape.lib differ diff --git a/vendor/kb_text_shape/src/LICENSE b/vendor/kb_text_shape/src/LICENSE new file mode 100644 index 000000000..cad70fa11 --- /dev/null +++ b/vendor/kb_text_shape/src/LICENSE @@ -0,0 +1,19 @@ +zlib License + +(C) Copyright 2024-2025 Jimmy Lefevre + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/vendor/kb_text_shape/src/build.bat b/vendor/kb_text_shape/src/build.bat new file mode 100644 index 000000000..b37b219e7 --- /dev/null +++ b/vendor/kb_text_shape/src/build.bat @@ -0,0 +1,8 @@ +@echo off + +if not exist "..\lib" mkdir ..\lib + +cl -nologo -MT -TC -O2 -c kb_text_shape.c +lib -nologo kb_text_shape.obj -out:..\lib\kb_text_shape.lib + +del *.obj diff --git a/vendor/kb_text_shape/src/build_unix.sh b/vendor/kb_text_shape/src/build_unix.sh new file mode 100755 index 000000000..159aecb52 --- /dev/null +++ b/vendor/kb_text_shape/src/build_unix.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e + +mkdir -p "../lib" +cc -O2 -c kb_text_shape.c +ar -rcs ../lib/kb_text_shape.a kb_text_shape.o +rm *.o diff --git a/vendor/kb_text_shape/src/kb_text_shape.c b/vendor/kb_text_shape/src/kb_text_shape.c new file mode 100644 index 000000000..613669eca --- /dev/null +++ b/vendor/kb_text_shape/src/kb_text_shape.c @@ -0,0 +1,8 @@ +#include +#ifndef _MSC_VER + #include +#endif + +#define KB_TEXT_SHAPE_NO_CRT +#define KB_TEXT_SHAPE_IMPLEMENTATION +#include "kb_text_shape.h" \ No newline at end of file diff --git a/vendor/kb_text_shape/src/kb_text_shape.h b/vendor/kb_text_shape/src/kb_text_shape.h new file mode 100644 index 000000000..986bf3be6 --- /dev/null +++ b/vendor/kb_text_shape/src/kb_text_shape.h @@ -0,0 +1,29691 @@ +/* kb_text_shape - v2.05 - text segmentation and shaping + by Jimmy Lefevre + + SECURITY + This library provides NO SECURITY GUARANTEE whatsoever. + DO NOT use it on untrusted font files. + + WHAT DOES THIS LIBRARY DO? + Before computers had monitors, the main way of inspecting the output of a command + was to print it out on real paper. When monitors appeared, most computer graphics + were text-based, meaning the display was arranged in a hardcoded grid in which each + cell could hold one of several hardcoded characters. As simple as it is, this kind + of text handling is sufficient for displaying almost any document written in the + Latin alphabet and a few other writing systems that happen to fit particularly well + on a grid, like Chinese and Japanese. + Handwritten Latin characters do not all have the same width, however. As computers + became more powerful, glyphs started having different widths to fit better together. + After that came kerning, which allows for packing glyphs closer together in pairs. + This is, of course, N-squared in the number of glyphs you want to handle, but this + is fine for the Latin alphabet, because there really aren't that many glyphs. + This is where TrueType stops: it is a good and simple, format for displaying text + using the Latin alphabet or writing systems that happen to work similarly to it. + All is well and good. + + What about the rest of the writing systems? + + Arabic is a cursive writing system. Much like when we write cursive ourselves, the + letters need to join together visually. Furthermore, a given letter in Arabic has + a different appearance depending on whether it is the first letter of a word, the + last letter of a word, or in the middle, and Unicode does not differenciate between + any of these. Also, Arabic features a beautiful set of marks that attach to letters, + much like accents in the Latin alphabet. You would usually want to align these marks + in some way depending on which other marks are present in the immediate vicinity. + + Indic scripts, like Devanagari, have even less in common with Latin than Arabic does. + + To try to support the plethora of writing systems out there, OpenType was introduced. + OpenType fonts contain rules that allow modifying a sequence of glyphs through pattern + matching. These rules can modify both the content of the sequence (ligatures replace + multiple glyphs with a single one, for instance) and its visual appearance by e.g. + attaching marks to letters. This is the meat of text shaping. + + OpenType rules have limitations, though. They don't work with mixed direction text, + because, when going from one text direction to the other, there is a visual jump that + breaks pattern matching. + + To illustrate, the logical string "0123456789" might have a display order like this: + + 01234 765 89 + ^LTR ^RTL ^LTR continued + + As you can see, there is a visual jump from 4 all the way to 5, and similarly from + 7 to 8. + This kind of discontinuity cannot work with OpenType rules, which want to work with + "neighboring" glyphs in the visual sense. + + OpenType rules don't work with mixed script text, either. They are designed to work with + a single writing system, and ideally a single language. A typographic rule that is correct + in writing system A might not be in writing system B, and vice versa. + + So, for all of these reasons, we need to split our text before sending it to the shaper. + This is what the text processing pipeline looks like: + + Your text A Text runs with B Sequence of glyphs C + (Probably ------------> uniform direction ------------> ready to rasterize ------------> Pixels + UTF-8) and script + + We call arrow A text segmentation, arrow B text shaping, and arrow C rasterization. + This library does A and B. + + FEATURE OVERVIEW + This library provides: + - Unicode segmentation + LTR/RTL breaking + Script breaking + Line breaking + Word breaking + Grapheme breaking + - OpenType text shaping + Open and parse TTF and OTF fonts + Apply OpenType features such as ligatures and contextual typographic rules + All OpenType shapers are supported, which means most languages in the world are supported + (see LANGUAGE_SUPPORT for known non-supported cases) + + COMPILING & LINKING + This library uses declare-anywhere, so it will not compile as C89/VC6 C. + + In one C/C++ file that #includes this file, do this: + #define KB_TEXT_SHAPE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + If you also do this: + #define KB_TEXT_SHAPE_STATIC + then all functions will be declared as static. + + If you do this: + #define KB_TEXT_SHAPE_NO_CRT + then we do not use the C runtime library. + In that case, these functions are compiled out: + kbts_ShapePushFontFromFile() + kbts_FontFromFile() + Additionally, there are some functions that you will want to #define yourself: + KBTS_MEMSET + defaults to memset otherwise. + KBTS_MEMCPY + defaults to memcpy otherwise. + You can redefine the default allocator by redefining these: + KBTS_MALLOC(AllocatorData, Size) + defaults to 0 if KB_TEXT_SHAPE_NO_CRT is defined, + defaults to malloc(Size) otherwise. + KBTS_FREE(AllocatorData, Pointer) + defaults to a no-op if KB_TEXT_SHAPE_NO_CRT is defined, + defaults to free(Pointer) otherwise. + In other words, + if you do not redefine the default allocator, and you #define KB_TEXT_SHAPE_NO_CRT, + then the default allocator always returns 0. + + EXAMPLES + Basic + kbts_shape_context *Context = kbts_CreateShapeContext(0, 0); + kbts_ShapePushFontFromFile(Context, "myfont.ttf", 0); + + kbts_ShapeBegin(Context, KBTS_DIRECTION_DONT_KNOW, KBTS_LANGUAGE_DONT_KNOW); + kbts_ShapeUtf8(Context, "Let's shape something!", sizeof("Let's shape something!") - 1, KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX); + kbts_ShapeEnd(Context); + + // Layout runs naively left to right. + kbts_run Run; + int CursorX = 0, CursorY = 0; + while(kbts_ShapeRun(Context, &Run)) + { + kbts_glyph *Glyph; + while(kbts_GlyphIteratorNext(&Run.Glyphs, &Glyph)) + { + int GlyphX = CursorX + Glyph->OffsetX; + int GlyphY = CursorY + Glyph->OffsetY; + + DisplayGlyph(Glyph->Id, GlyphX, GlyphY); + + CursorX += Glyph->AdvanceX; + CursorY += Glyph->AdvanceY; + } + } + + Font collections + void *FontData; + int FontSize; + kbts_font Font = kbts_FontFromFile("myfonts.ttc", 0, 0, 0, &FontData, &FontSize); + + kbts_ShapePushFont(Context, &Font); + + int FontCount = kbts_FontCount(FontData, FontSize); + for(int FontIndex = 1; FontIndex < FontCount; ++FontIndex) + { + kbts_ShapePushFontFromMemory(Context, FontData, FontSize, FontIndex); + } + + Feature control + kbts_ShapeBegin(Context, KBTS_DIRECTION_DONT_KNOW, KBTS_LANGUAGE_DONT_KNOW); + + kbts_ShapePushFeature(Context, KBTS_FEATURE_TAG_kern, 0); + kbts_ShapeUtf8(Context, "Without kerning", sizeof("Without kerning") - 1, KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX); + kbts_ShapePopFeature(Context, KBTS_FEATURE_TAG_kern); + + kbts_ShapeUtf8(Context, "With kerning", sizeof("With kerning") - 1, KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX); + + kbts_ShapeEnd(Context); + + @Todo: Write more examples + + API + The shaping API is broken down into two parts: the context API and the direct API. + + The context API is the higher-level API of the two and is meant to be the default + API. + It exposes an immediate-mode, procedural interface somewhat inspired by Dear Imgui + and covers most of the functionality present in the library. It notably includes + automatic segmentation into paragraphs and runs, shaping, and font fallback. + + The direct API, in contrast, is all of the tools you can use to directly manage and + manipulate shaping data. With it, you can interact directly with the lower-level + parts of the library, giving you very granular control. It is also very explicit + about memory. As a result, it is also a lot more verbose than the context API. + + The library also contains several miscellaneous utility functions that are not + obviously part of any of the two aforementioned APIs. + + + In the documentation below, all functions (as well as some structs/enums) are + marked with "search tags". + As an example, this hypothetical function: + + int kbts_Foo(int X); + + Will be presented like this: + + :kbts_Foo + :Foo + int kbts_Foo(int X); + + Allowing you to easily search for its documentation by searching for either ":Foo" + or ":kbts_Foo". + + MEMORY MANAGEMENT + kb_text_shape takes manual memory management seriously, and tries to give the user as much + control over memory as possible. + + Whenever it is possible for you to pass your own buffer into a function, we allow it. + Whenever it is not possible, we allow specifying a custom allocator. + An allocator is simply a function that manages memory: + + :kbts_allocator_function + :allocator_function + typedef void kbts_allocator_function(void *Data, kbts_allocator_op *Op); + [Data] the custom data pointer you passed in along with your allocator. + [Op] the memory request. It is of this type: + + :kbts_allocator_op + :allocator_op + typedef struct kbts_allocator_op + { + kbts_allocator_op_kind Kind; + + union + { + kbts_allocator_op_allocate Allocate; + kbts_allocator_op_free Free; + }; + } kbts_allocator_op; + + And the possible op kinds are: + KBTS_ALLOCATOR_OP_KIND_ALLOCATE + KBTS_ALLOCATOR_OP_KIND_FREE + + ALLOCATE expects you to fill in Op->Allocate.Pointer. + The allocation does not need to be aligned. + FREE expects you to free Op->Free.Pointer. + + THE CONTEXT API + CONTEXT:CREATION + :kbts_SizeOfShapeContext + :SizeOfShapeContext + int kbts_SizeOfShapeContext() + Tells you how big of a buffer you need to provide to kbts_PlaceShapeContext. + + :kbts_PlaceShapeContext + :PlaceShapeContext + kbts_shape_context *kbts_PlaceShapeContext(kbts_allocator_function *Allocator, void *AllocatorData, void *Memory) + Places a context at Memory and initializes it. + [Allocator] will be used for subsequent allocations. + + :kbts_PlaceShapeContextFixedMemory + :PlaceShapeContextFixedMemory + kbts_shape_context *kbts_PlaceShapeContextFixedMemory(void *Memory, int Size) + Places a context at Memory and initializes it. + This context will only use the [Size] bytes located at [Memory] for its allocations. + + :kbts_CreateShapeContext + :CreateShapeContext + kbts_shape_context *kbts_CreateShapeContext(kbts_allocator_function *Allocator, void *AllocatorData) + Allocates a context using [Allocator] and initializes it. + + :kbts_DestroyShapeContext + :DestroyShapeContext + void kbts_DestroyShapeContext(kbts_shape_context *Context) + Frees all context memory. + If the Context was allocated by kbts_CreateShapeContext, then it is also freed. + + CONTEXT:FONT HANDLING + The context is capable of managing multiple fonts through a font stack. + The font stack will hold references to all fonts in use by the context. Whenever + you try to shape some text, the context will check to see if it is supported by + the font at the top of the stack. If it is not, it will try the next font down, + and so on, until all fonts have been tried. As such, you should push your fallback + fonts first, and your preferred fonts last. + + :kbts_ShapePushFontFromFile + :ShapePushFontFromFile + kbts_font *kbts_ShapePushFontFromFile(kbts_shape_context *Context, const char *FileName, int FontIndex) + (This function is not available if KB_TEXT_SHAPE_NO_CRT is defined.) + + Opens the file corresponding to [FileName], parses the [FontIndex]th font + within it, and, if successful, pushes the result onto the stack. + + A [return value] of 0 could mean that the stack is out of space (see + KBTS_CONTEXT_MAX_FONT_COUNT), that the file could not be found or opened, + or that the parse has failed. + + :kbts_ShapePushFontFromMemory + :ShapePushFontFromMemory + kbts_font *kbts_ShapePushFontFromMemory(kbts_shape_context *Context, void *Memory, int Size, int FontIndex) + Parses the [FontIndex]th font in [Memory] and pushes the result to the font + stack. + + A [return value] of 0 could mean that the stack is out of space (see + KBTS_CONTEXT_MAX_FONT_COUNT) or that the font could not be parsed. + + :kbts_ShapePushFont + :ShapePushFont + kbts_font *kbts_ShapePushFont(kbts_shape_context *Context, kbts_font *Font) + Pushes the pre-parsed [Font] onto the stack. + + A [return value] of 0 means that the stack has run out of space (see + KBTS_CONTEXT_MAX_FONT_COUNT). + + :kbts_ShapePopFont + :ShapePopFont + kbts_font *kbts_ShapePopFont(kbts_shape_context *Context) + Removes the topmost font from the stack. + + A [return value] of 0 means that there is no font to remove. + A non-null [return value] is the original font pointer that was pushed. + + If the context allocated the font itself, using kbts_ShapePushFontFromFile or + kbts_ShapePushFontFromMemory, then the pointer is still returned, but it points to + freed memory. + + CONTEXT:SHAPING + :kbts_ShapeBegin + :ShapeBegin + void kbts_ShapeBegin(kbts_shape_context *Context, kbts_direction ParagraphDirection, kbts_language Language) + Begins a shaping pass. + + [ParagraphDirection] is sometimes called the "document direction". It can significantly + affect segmentation. Bidirectionality in text works like a stack: the default direction + is at the bottom of the stack, and, sometimes, text can _temporarily_ take a different + direction. In the end, though, it will always go back to the document direction. + + To illustrate, a period followed by a space ". " typically ends up resetting the current + direction to the paragraph direction. This means that, if my paragraph direction is + left-to-right, and I am shaping Arabic text, then each Arabic sentence will be + right-to-left, but the sentences themselves will be sequenced left-to-right. If + [ParagraphDirection] is KBTS_DIRECTION_DONT_KNOW, then the context takes the first + directional hint in the text as the paragraph direction. + + [Language] is used to select which font rules are used. Knowing this allows access to + language-specific typographical features. If [Language] is KBTS_LANGUAGE_DONT_KNOW, then + the default, language-agnostic font rules are used. + + :kbts_ShapeEnd + :ShapeEnd + void kbts_ShapeEnd(kbts_shape_context *Context) + Ends a shaping pass. + + This means you are done providing input to the context, and, in turn, that + you can start getting results from it with kbts_ShapeRun(). + + :kbts_ShapeRun + :ShapeRun + int kbts_ShapeRun(kbts_shape_context *Context, kbts_run *Run) + Once you've called kbts_ShapeEnd, you can get the resulting runs by calling this + function repeatedly. + + !!! CAREFUL !!! Memory is reused from one run to the next, so you cannot + trivially store [Run] and reuse it later. Instead, you should traverse the + glyphs using the iterator provided in Run.Glyphs and extract whatever data + you need before calling kbts_ShapeRun again. + + The [return value] is non-zero if a run was shaped. + When there is no text left to shape, the [return value] is 0. + + kbts_ShapeEnd(Context); + kbts_run Run; + while(kbts_ShapeRun(Context, &Run)) + { + // Handle Run + } + + :kbts_ShapePushFeature + :ShapePushFeature + void kbts_ShapePushFeature(kbts_shape_context *Context, kbts_u32 FeatureTag, int Value) + The context has a feature stack that allows you to manipulate font features hierarchically. + When you give text to the context, it will apply all feature overrides that are on the + stack at the time. + If two feature overrides use the same tag, then only the latest one, i.e. the one higher + in the stack, is applied. + + :kbts_ShapePopFeature + :ShapePopFeature + int kbts_ShapePopFeature(kbts_shape_context *Context, kbts_u32 FeatureTag) + Removes the latest feature override with tag [FeatureTag]. + The [return value] is non-zero if an override was found and removed, 0 if not. + + :kbts_ShapeCodepointWithUserId + :ShapeCodepointWithUserId + void kbts_ShapeCodepointWithUserId(kbts_shape_context *Context, int Codepoint, int UserId) + Inputs a codepoint to shape. + [Codepoint] is a Unicode codepoint. + [UserId] is an arbitrary identifier that you will get back when reading the results. + This is often some kind of index into the input text so that you can perform hit-testing. + If an automatic codepoint index is fine for you, consider using kbts_ShapeCodepoint. + + :kbts_ShapeCodepoint + :ShapeCodepoint + void kbts_ShapeCodepoint(kbts_shape_context *Context, int Codepoint) + Inputs a codepoint to shape. + + The codepoint's user ID will be an implicit codepoint index assigned by the + context. + + :kbts_ShapeUtf32WithUserId + :ShapeUtf32WithUserId + void kbts_ShapeUtf32WithUserId(kbts_shape_context *Context, + int *Utf32, int Length, + int UserId, int UserIdIncrement); + Inputs a block of UTF-32 text to shape. + + User IDs for each codepoint start at [UserId] and increment by [UserIdIncrement] + for every codepoint. + + :kbts_ShapeUtf32 + :ShapeUtf32 + void kbts_ShapeUtf32(kbts_shape_context *Context, int *Utf32, int Length) + Same as kbts_ShapeUtf8WithUserId, but using the context's implicit user ID counter. + + :kbts_ShapeUtf8WithUserId + :ShapeUtf8WithUserId + void kbts_ShapeUtf8WithUserId(kbts_shape_context *Context, + const char *Utf8, int Length, + int UserId, kbts_user_id_generation_mode UserIdGenerationMode); + Inputs a block of UTF-8 text to shape. + + User IDs for the corresponding codepoints start at [UserId]. + If [UserIdGenerationMode] is KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX, + each codepoint will increment the user ID by 1. + If [UserIdGenerationMode] is KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX, + each codepoint will increment the user ID by the length of its encoding in + UTF-8. + + :kbts_ShapeUtf8 + :ShapeUtf8 + void kbts_ShapeUtf8(kbts_shape_context *Context, + const char *Utf8, int Length, + kbts_user_id_generation_mode UserIdGenerationMode) + Same as kbts_ShapeUtf8WithUserId, but using the context's implicit user ID + counter. + + User IDs for the corresponding codepoints start at the context's implicit + user ID counter. + If [UserIdGenerationMode] is KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX, + each codepoint will increment the user ID by 1. + If [UserIdGenerationMode] is KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX, + each codepoint will increment the user ID by the length of its encoding in + bytes in UTF-8. + + :kbts_ShapeCurrentCodepointsIterator + :ShapeCurrentCodepointsIterator + kbts_shape_codepoint_iterator kbts_ShapeCurrentCodepointsIterator(kbts_shape_context *Context) + The [return value] is an iterator that goes over all of the codepoints fed to + [Context] so far. + + These codepoints are tagged with user IDs, segmentation info and more. See + the definition of kbts_shape_codepoint for details. + + !!! WARNING !!! + Remember that segmentation is buffered, so, until you call kbts_ShapeEnd, + some codepoints might not be completely filled in yet! + + Call kbts_ShapeCodepointIteratorNext repeatedly to loop through the + corresponding codepoints. + + :kbts_ShapeCodepointIteratorIsValid + :ShapeCodepointIteratorIsValid + int kbts_ShapeCodepointIteratorIsValid(kbts_shape_codepoint_iterator *It) + The [return value] is non-zero if there is still a codepoint to iterate, + zero if not. + + :kbts_ShapeCodepointIteratorNext + :ShapeCodepointIteratorNext + int kbts_ShapeCodepointIteratorNext(kbts_shape_codepoint_iterator *It, kbts_shape_codepoint *Codepoint, int *CodepointIndex) + Gets the next codepoint from the context [It] was initialized from and writes + it to [Codepoint]. + + If [CodepointIndex] is non-zero, then it is filled with [Codepoint]'s index. + + The [return value] is non-zero if a codepoint was found, 0 if not. + + :kbts_ShapeGetShapeCodepoint + :ShapeGetShapeCodepoint + int kbts_ShapeGetShapeCodepoint(kbts_shape_context *Context, int CodepointIndex, kbts_shape_codepoint *Codepoint) + Gets the [CodepointIndex]th codepoint from [Context] and writes it to + [Codepoint]. + + If you are reading glyphs back from the context, then you can use the + UserIdOrCodepointIndex field of kbts_glyph here. + + !!! WARNING !!! + When using the context API, UserIdOrCodepointIndex will _always_ be a + codepoint index. To get your original user ID, you need to do: + + kbts_shape_codepoint ShapeCodepoint; + kbts_ShapeGetShapeCodepoint(Context, Glyph->UserIdOrCodepointIndex, &ShapeCodepoint); + int MyUserId = ShapeCodepoint.UserId; + + The [return value] is non-zero if [CodepointIndex] is in-bounds, 0 if not. + + CONTEXT:MISCELLANEOUS + :kbts_ShapeError + :ShapeError + kbts_shape_error kbts_ShapeError(kbts_shape_context *Context); + Get the first error that occurred on [Context]. + + Once a context is tagged with an error, most operations on it will do nothing. + Obviously, you can always destroy it. + + :kbts_ShapeManualBreak + :ShapeManualBreak + void kbts_ShapeManualBreak(kbts_shape_context *Context); + Forces a run break at the current position in the Context. + + This will flush the current segmentation state just like an end-of-text would, + and restart it as if it was at a start-of-text. + + This will also generate a KBTS_BREAK_FLAG_MANUAL at the current position. + + You do not need to be in manual break mode for this function to work. + + :kbts_ShapeBeginManualRuns + :ShapeBeginManualRuns + void kbts_ShapeBeginManualRuns(kbts_shape_context *Context); + Disables the context's automatic segmentation, and enters a manual break mode. + + :kbts_ShapeNextManualRun + :ShapeNextManualRun + void kbts_ShapeNextManualRun(kbts_shape_context *Context, kbts_direction Direction, kbts_script Script); + Add a run break at the current place in the input stream. + + Since the context's segmentation is disabled, it cannot know which direction + and script to use, so you need to provide them with [Direction] and [Script]. + + Outside of manual break mode, this function is a no-op. + + :kbts_ShapeEndManualRuns + :ShapeEndManualRuns + void kbts_ShapeEndManualRuns(kbts_shape_context *Context); + Ends manual break mode and re-enables the context's automatic segmentation. + + Note that this will force natural break barriers too, just like an end-of-text + would. + + Outside of manual break mode, this function is a no-op. + + DIRECT SHAPING API + When trying to shape things yourself, there are four main pieces of state you will need: + - Font data (kbts_font) + - A shaping configuration (kbts_shape_config) + A shaping configuration holds a bunch of precomputed data for a given combination of + font, script and language. + You can think of it as a pipeline state in a modern graphics API. + In practice, you are only ever shaping text with a single active configuration. + - Glyph storage (kbts_glyph_storage) + Glyph storage fills two roles: it allocates and holds glyph data, and it also manages + a set of active glyphs. + The active glyph set part is used by the library. As a user, you only need to care + about the memory allocation part. + - Scratch memory + Unfortunately, shaping can have a very unpredictable memory footprint, so all shaping + operations require some amount of scratch space that we cannot compute beforehand. + + The central function to call is this: + + :kbts_ShapeDirect + :ShapeDirect + kbts_shape_error kbts_ShapeDirect(kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_direction RunDirection, + kbts_allocator_function *Allocator, void *AllocatorData, + kbts_glyph_iterator *Output) + [RunDirection] is the direction of the specific run being shaped. + If the [return value] is KBTS_SHAPE_ERROR_NONE, then the shaping operation + completed successfully. + + Shaping output is returned in [Output]. You can go through the resulting glyphs + with kbts_GlyphIteratorNext. + + Note that kbts_ShapeDirect does not care about the paragraph direction. + Glyphs are always returned in left-to-right order. In other words, RTL runs + are flipped so that visual order is consistent. + + + :kbts_ShapeDirectFixedMemory + :ShapeDirectFixedMemory + kbts_shape_error kbts_ShapeDirectFixedMemory(kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_direction RunDirection, + void *Memory, int Size, + kbts_glyph_iterator *Output) + Same as kbts_ShapeDirect, but only uses the [Size] bytes at [Memory] for allocations. + + The rest of the direct API is more or less about preparing the data you need to call + kbts_ShapeDirect. + + DIRECT:FONT HANDLING + :kbts_FontCount + :FontCount + int kbts_FontCount(void *Data, int Size) + Parses the beginning of the file and returns the number of fonts contained + within the file data. + + While most font files contain single fonts, font collections contain + several. This function will return 0 if [Data] is invalid, 1 if it represents + a single font, and possibly more if it represents a collection. + + For all functions that require a font index, passing 0 is always safe no + matter the kind of file. + + :kbts_FontFromFile + :FontFromFile + kbts_font kbts_FontFromFile(const char *FileName, int FontIndex, + kbts_allocator_function *Allocator, void *AllocatorData, + void **FileData, int *FileSize) + (This function is not available if KB_TEXT_SHAPE_NO_CRT is defined.) + Opens the file at [FileName], parses it and returns the [FontIndex]th font. + You can call kbts_FontIsValid to check if the [return value] is usable. + + If [FileData] is non-zero, it is filled with a pointer to the file's contents. + This pointer is allocated using [Allocator]. If [FileData] is 0, it is freed + before the function returns. + If [FileSize] is non-zero, it is filled with the size of the file's contents. + + If [FontIndex] is out of range, the [return value] is invalid. + + :kbts_FontFromMemory + :FontFromMemory + kbts_font kbts_FontFromMemory(void *FileData, int FileSize, int FontIndex, + kbts_allocator_function *Allocator, void *AllocatorData) + Parses the [FontIndex]th font in [FileData]. + You can call kbts_FontIsValid to check if the [return value] is usable. + + :kbts_FontIsValid + :FontIsValid + int kbts_FontIsValid(kbts_font *Font) + Returns whether a font is usable. + + :kbts_LoadFont + :LoadFont + kbts_load_font_error kbts_LoadFont(kbts_font *Font, kbts_load_font_state *State, + void *FontData, int FontDataSize, int FontIndex, + int *ScratchSize, int *OutputSize) + Parses the [FontIndex]th font in [FontData] and puts the result into [Font] and [State]. + + [State] needs to be zeroed before calling this function. + + If the data represents a TrueType/OpenType font, we need to extract the data + we need and create some additional data structures. In this case, the [return + value] is KBTS_LOAD_FONT_ERROR_NEED_TO_CREATE_BLOB, and [ScratchSize] and + [OutputSize] are filled with the amount of memory we need to create our + blob. You can then initialize this blob with kbts_PlaceBlob. + + If the data represents a kbts blob, then nothing needs to be done, and [Font] is + immediately usable. + + Any value of [FontIndex] less than kbts_FontCount(FontData, FontDataSize) is + acceptable. + + If we could not find any useful font data, the [return value] is + KBTS_LOAD_FONT_ERROR_INVALID_FONT. + + :kbts_PlaceBlob + :PlaceBlob + kbts_load_font_error kbts_PlaceBlob(kbts_font *Font, kbts_load_font_state *State, + void *ScratchMemory, void *OutputMemory) + Creates a kbts blob from font data, and places it in [OutputMemory]. + [Font] is the resulting font. + [State] is the state you passed into kbts_LoadFont. + [ScratchMemory] needs to be as big as the [ScratchSize] returned by kbts_LoadFont. + You can free this buffer once this function returns. + [OutputMemory] needs to be as big as the [OutputSize] returned by kbts_LoadFont. + This buffer will be used by [Font] until it is freed by kbts_FreeFont. + + :kbts_FreeFont + :FreeFont + void kbts_FreeFont(kbts_font *Font) + If [Font] used allocators to allocate its data (for instance, if [Font] was + returned by kbts_FontFromFile), frees all of [Font]'s buffers. + Otherwise, does nothing. + + :kbts_GetFontInfo + :GetFontInfo + void kbts_GetFontInfo(kbts_font *Font, kbts_font_info *Info) + Writes a bunch of useful metadata about [Font] into [Info]. + You can use this function to extract styling, name and licensing information + from a font. + + We use a simplified representation for font weight and width that is fine for + classic font selection, e.g. "I need a bold font". OpenType fonts may feature + finer-grained metrics, and we currently do not expose/support those. + + :kbts_font_style_flags + :font_style_flags + [Info]->StyleFlags can be: + KBTS_FONT_STYLE_FLAG_NONE (no useful style flags have been found) + KBTS_FONT_STYLE_FLAG_REGULAR + KBTS_FONT_STYLE_FLAG_BOLD + KBTS_FONT_STYLE_FLAG_ITALIC + A given font can be bold and italic at the same time, but probably not regular + and bold and probably not regular and italic. + + If [Font] is not a valid font, then [Info] will be zeroed. + + DIRECT:SHAPE CONFIG + :kbts_SizeOfShapeConfig + :SizeOfShapeConfig + int kbts_SizeOfShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language) + Returns how large the buffer you pass into kbts_PlaceShapeConfig needs to be. + + :kbts_PlaceShapeConfig + :PlaceShapeConfig + kbts_shape_config *kbts_PlaceShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, + void *Memory) + Writes a shape config into [Memory] and returns a pointer to it. + [Memory] needs to be at least kbts_SizeOfShapeConfig([Font], [Script], [Language]) bytes. + + :kbts_CreateShapeConfig + :CreateShapeConfig + kbts_shape_config *kbts_CreateShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, + kbts_allocator_function *Allocator, void *AllocatorData) + Allocates and initializes a shape config. + + :kbts_DestroyShapeConfig + :DestroyShapeConfig + void kbts_DestroyShapeConfig(kbts_shape_config *Config) + If [Config] was allocated in kbts_CreateShapeConfig, frees all of [Config]'s data. + Otherwise, nothing is done. + + DIRECT:GLYPH STORAGE + kbts_glyph_storage is a public struct: + + :kbts_glyph_storage + :glyph_storage + typedef struct kbts_glyph_storage + { + kbts_arena Arena; + + kbts_glyph GlyphSentinel; + kbts_glyph FreeGlyphSentinel; + } kbts_glyph_storage; + + A zeroed kbts_glyph_storage will auto-initialize itself when you try to use it. + + Arena requires an allocator. By default, it will be initialized to KBTS_MALLOC + and KBTS_FREE. + You can specify your own allocator by writing to Arena.Allocator and + Arena.AllocatorData before trying to use a kbts_glyph_storage. + Alternatively, you can use kbts_InitializeGlyphStorage() to accomplish the + same thing. + + :kbts_InitializeGlyphStorage + :InitializeGlyphStorage + int kbts_InitializeGlyphStorage(kbts_glyph_storage *Storage, kbts_allocator_function *Allocator, void *AllocatorData) + Initializes [Storage] to use [Allocator] and [AllocatorData]. + + This is equivalent to setting [Storage]->Arena.Allocator and + [Storage]->Arena.AllocatorData, and setting all other members to 0. + + The [return value] is non-zero if [Storage] is non-null. + + :kbts_InitializeGlyphStorageFixedMemory + :InitializeGlyphStorageFixedMemory + int kbts_InitializeGlyphStorageFixedMemory(kbts_glyph_storage *Storage, void *Memory, int MemorySize) + Initializes [Storage] to use a fixed-size buffer of size [MemorySize] located at [Memory]. + If [Storage] needs more memory than [MemorySize], allocations will fail. + + The [return value] is non-zero if [Storage] is non-null and [MemorySize] is + large enough to initialize [Storage]'s arena. (Currently, this is 5 pointers' + worth of bytes.) + + :kbts_PushGlyph + :PushGlyph + kbts_glyph *kbts_PushGlyph(kbts_glyph_storage *Storage, + kbts_font *Font, int Codepoint, kbts_glyph_config *Config, int UserId) + Adds a glyph to [Storage]'s active glyph set and returns a pointer to it. + + [Font] is used to initialize the glyph's glyph ID. It is assumed that [Font] is + the same as the kbts_shape_config's Font field passed into kbts_ShapeDirect. + + [Config] is the glyph's configuration and needs to stay live until kbts_ShapeDirect + completes. See DIRECT:GLYPH CONFIG for more details. + + [UserId] is a user-provided unique identifier that you can get back once shaping + is done. + + The [return value] might be zero if [Storage]'s allocator fails. + + :kbts_ClearActiveGlyphs + :ClearActiveGlyphs + void kbts_ClearActiveGlyphs(kbts_glyph_storage *Storage) + Clears [Storage]'s active glyph set. + This does not free any memory; rather, it puts the active glyphs in a free list. + + :kbts_FreeAllGlyphs + :FreeAllGlyphs + void kbts_FreeAllGlyphs(kbts_glyph_storage *Storage) + Frees all memory allocated by [Storage]. + + :kbts_CodepointToGlyph + :CodepointToGlyph + kbts_glyph kbts_CodepointToGlyph(kbts_font *Font, int Codepoint, kbts_glyph_config *Config, int UserId) + You can create glyphs without a glyph storage at all with this function. + + :kbts_CodepointToGlyphId + :CodepointToGlyphId + int kbts_CodepointToGlyphId(kbts_font *Font, int Codepoint) + Gets the glyph ID corresponding to [Codepoint] from [Font]. + A glyph ID of 0 means that the codepoint is not present in the font. + Note that this is not thorough enough to be a good font coverage test! + See OTHER:FONT COVERAGE TEST for this. + + :kbts_ActiveGlyphIterator + :ActiveGlyphIterator + kbts_glyph_iterator kbts_ActiveGlyphIterator(kbts_glyph_storage *Storage) + Returns an iterator to traverse [Storage]'s active glyph set. + + See OTHER:GLYPH ITERATION for more details on glyph iterators. + + DIRECT:GLYPH CONFIG + The shaper figures out most of the work it needs to do based on the writing system + it is shaping. + + However, some fonts support optional, toggleable features, like "make this text + smallcaps". For things like this, you will want to create a kbts_glyph_config. + You can then pass it to glyph creation functions or write it to the Config field + of a kbts_glyph. + + A kbts_glyph_config can hold any number of feature overrides. A feature override + is a feature tag and a value. Most of the time, you only care whether the value + is 0 or 1, but a few features actually care about the exact value. (You can think + of a feature that is like "when I am enabled, change this letter to one of these + alternatives". In that case, the value you provide in the feature override is used + as an index into the array of alternatives.) + + :kbts_SizeOfGlyphConfig + :SizeOfGlyphConfig + int kbts_SizeOfGlyphConfig(kbts_feature_override *Overrides, int OverrideCount) + Returns the buffer size needed to hold a kbts_glyph_config that describes [Overrides]. + This size can vary a lot depending on the kind of feature overrides you specify. + Built-in OpenType features with values of 0 or 1 are "free"; they are packed in a + fixed-size representation which does not change the config's memory footprint. + On the other hand, if you need non-binary values, or non-standard features, then + we need to store a description of the override itself, which requires memory. + + :kbts_PlaceGlyphConfig + :PlaceGlyphConfig + kbts_glyph_config *kbts_PlaceGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, void *Memory) + Writes a kbts_glyph_config that describes [Overrides] into [Memory], and returns a + pointer to it. + The kbts_glyph_config uses its own representation for overrides, so you can modify + [Overrides] once this function returns. + + :kbts_CreateGlyphConfig + :CreateGlyphConfig + kbts_glyph_config *kbts_CreateGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, kbts_allocator_function *Allocator, void *AllocatorData) + Allocates a kbts_glyph_config that describes [Overrides] and returns a pointer to + it. + The kbts_glyph_config uses its own representation for overrides, so you can modify + [Overrides] once this function returns. + + :kbts_DestroyGlyphConfig + :DestroyGlyphConfig + void kbts_DestroyGlyphConfig(kbts_glyph_config *Config) + If [Config] was allocated in kbts_CreateGlyphConfig, frees all of its data. + Otherwise, does nothing. + + DIRECT:SEGMENTATION + kbts_break_state is the central struct used for segmentation. It contains all of the state + needed to perform fixed-memory segmentation of text. + + :kbts_BreakBegin + :BreakBegin + void kbts_BreakBegin(kbts_break_state *State, + kbts_direction ParagraphDirection, + kbts_japanese_line_break_style JapaneseLineBreakStyle, + kbts_break_config_flags ConfigFlags) + Initializes [State] for segmentation. + + [ParagraphDirection] is the top-level flow direction of your document or layout. + If [ParagraphDirection] is KBTS_DIRECTION_DONT_KNOW, then [State]'s + ParagraphDirection will be initialized to the first direction we find + while segmenting. + + :kbts_japanese_line_break_style + :japanese_line_break_style + [JapaneseLineBreakStyle] can be one of the following: + + KBTS_JAPANESE_LINE_BREAK_STYLE_STRICT + KBTS_JAPANESE_LINE_BREAK_STYLE_NORMAL + KBTS_JAPANESE_LINE_BREAK_STYLE_LOOSE + + Japanese text contains "kinsoku" characters, around which breaking a line is + forbidden. Exactly which characters are "kinsoku" or not depends on the context: + + - Strict style has the largest amount of kinsoku characters, which leads to + longer lines. + The Unicode standard does not define what strict style is used for. + Supposedly, it is used for anything that does not fall into the other + two categories of text. + + - Loose style has the smallest amount of kinsoku characters, which leads + to smaller lines. + According to the Unicode standard, loose style is used for newspapers. + I assume it is also used for any other narrow column format. + + - Normal style is somewhere in the middle. + According to the Unicode standard, normal style is used for books and + documents. + + Note that, while the Unicode standard mentions all three of these styles, it + does not mention any differences between the normal and loose styles. As such, + normal and loose styles currently behave the same. + + :kbts_kbts_break_config_flags + :kbts_break_config_flags + [ConfigFlags] can be a combination of the following: + + KBTS_BREAK_CONFIG_FLAG_END_OF_TEXT_GENERATES_HARD_LINE_BREAK + The Unicode standard specifies that the end of a text should generate a + hard line break. However, this is an awkward rule to uphold in practical + contexts, because it makes the case where the text ends in a newline + ambiguous. So, by default, we disable it. + + Without this flag (default behavior): + \n generates a hard line break at position 1 + A generates no hard line break + + With this flag (Unicode behavior): + \n generates a hard line break at position 1 + A generates a hard line break at position 1 + + :kbts_BreakAddCodepoint + :BreakAddCodepoint + void kbts_BreakAddCodepoint(kbts_break_state *State, int Codepoint, int PositionIncrement, int EndOfText) + Feeds [Codepoint] to [State]. + + [PositionIncrement] is used to update an internal cursor and fill out + kbts_break's Position field. If you only care about codepoint indices, pass + 1. Maybe you want to pass in the number of bytes it took to decode the + codepoint, though, to be able to directly index UTF-8 text. + + If [EndOfText] is non-zero, kbts_BreakEnd is called after adding [Codepoint]. + + Every time you call kbts_BreakAddCodepoint, you need to empty the break + buffer by calling kbts_Break repeatedly. + + :kbts_BreakEnd + :BreakEnd + void kbts_BreakEnd(kbts_break_state *State) + Flushes all pending breaks and finishes segmentation. + + You then obtain breaks by repeatedly calling kbts_Break, just as you would + after kbts_BreakAddCodepoint. + + :kbts_Break + :Break + int kbts_Break(kbts_break_state *State, kbts_break *Break) + If any breaks have been found, writes one to [Break] and returns a non-zero + value. If not, returns 0. + + kbts_break looks like this: + + typedef struct kbts_break + { + int Position; + kbts_break_flags Flags; + kbts_direction Direction; // Only valid if (Flags & KBTS_BREAK_FLAG_DIRECTION). + kbts_script Script; // Only valid if (Flags & KBTS_BREAK_FLAG_SCRIPT). + } kbts_break; + + Position is the position of the break, informed by the PositionIncrement + you passed to kbts_BreakAddCodepoint. + + Flags can be any combination of: + KBTS_BREAK_FLAG_DIRECTION + Indicates a change of direction. + + KBTS_BREAK_FLAG_SCRIPT + Indicates a change of script. + + KBTS_BREAK_FLAG_GRAPHEME + Indicates the start of a grapheme. + Unicode describes a grapheme as a visual unit. In practice, you care about + graphemes for font coverage testing and caret positioning. + + The way you do grapheme-aware font coverage testing is you split your text + into graphemes, then, for each grapheme, check if it is supported by your + font. Grapheme boundaries are nice because they group codepoints that may + want to combine together, but it separates codepoints that probably won't + recombine, so they work as an synchronization point for font coverage. + + Caret positioning typically works in graphemes, too. When the user presses + the right arrow, you would go to the next grapheme boundary instead of + naively going to the next codepoint. + + KBTS_BREAK_FLAG_WORD + Indicates the start of a word. + + KBTS_BREAK_FLAG_LINE_SOFT + A soft line break tells you where you are able to break lines. + In Unicode land, you cannot break a line without one of these! + + KBTS_BREAK_FLAG_LINE_HARD + A hard line break should always be respected. + + KBTS_BREAK_FLAG_MANUAL + This is used internally by the kbts_shape_context for manual segmentation. + (See kbts_ShapeBeginManualRuns for more details.) + + !CAREFUL! For a given break type, breaks are guaranteed to be returned in order. + However, there is no such ordering guarantee between different types + of breaks. Each type of break is processed separately, and the + corresponding Unicode algorithms all require some kind of buffering + scheme to work in fixed memory, so, while any given buffer is consistent + with itself, we cannot order multiple buffers together. + + :kbts_BreakEntireString + :BreakEntireString + void kbts_BreakEntireString(kbts_direction ParagraphDirection, + kbts_japanese_line_break_style JapaneseLineBreakStyle, + kbts_break_config_flags ConfigFlags, + void *Input, int InputSizeInBytes, kbts_text_format InputFormat, + kbts_break *Breaks, int BreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount) + Goes through the entire buffer at [Input] and finds all breaks. + [Input] is of type [InputFormat], which can be one of: + KBTS_TEXT_FORMAT_UTF32 + KBTS_TEXT_FORMAT_UTF8 + + Breaks will be written to [Breaks], up to [BreakCapacity]. Regardless of + whether [BreakCapacity] is large enough or not, the amount of breaks found + will be written to [BreakCount]. Unlike kbts_Break, here, [Breaks] are + guaranteed to be ordered. + + [BreakFlags] is a parallel array to the input sequence. If a break is found + at position X, then BreakFlags[X] will be filled with the appropriate flags, + up to [BreakFlagCapacity]. Regardless of whether [BreakFlagCapacity] is large + enough or not, the required capacity is written to [BreakFlagCount]. + + :kbts_BreakEntireStringUtf32 + :BreakEntireStringUtf32 + void kbts_BreakEntireStringUtf32(kbts_direction ParagraphDirection, + kbts_japanese_line_break_style JapaneseLineBreakStyle, + kbts_break_config_flags ConfigFlags, + int *Utf32, int Utf32Count, + kbts_break *Breaks, int BreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount) + Convenience wrapper for kbts_BreakEntireString for UTF-32 text. + + :kbts_BreakEntireStringUtf8 + :BreakEntireStringUtf8 + void kbts_BreakEntireStringUtf8(kbts_direction ParagraphDirection, + kbts_japanese_line_break_style JapaneseLineBreakStyle, + kbts_break_config_flags ConfigFlags, + const char *Utf8, int Utf8Length, + kbts_break *Breaks, int BreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount) + Convenience wrapper for kbts_BreakEntireString for UTF-8 text. + + This wrapper passes the amount of bytes used to decode each codepoint into + kbts_BreakAddCodepoint's PositionIncrement argument. This means that break + positions written to [Breaks] point into the UTF-8 stream. + + :kbts_GuessTextProperties + :GuessTextProperties + void kbts_GuessTextProperties(void *Text, int TextSizeInBytes, kbts_text_format Format, + kbts_direction *Direction, kbts_script *Script) + Goes through the input sequence at [Text], finds the first direction and + script, and writes them to [Direction] and [Script] respectively. + + This is a quick-and-dirty way of finding out simple facts about your text. + However, the results only really make sense when you know [Input] is + mono-script and mono-direction. + + :kbts_GuessTextPropertiesUtf32 + :GuessTextPropertiesUtf32 + void kbts_GuessTextPropertiesUtf32(const int *Utf32, int Utf32Count, + kbts_direction *Direction, kbts_script *Script) + Convenience wrapper for kbts_GuessTextProperties for UTF-32 text. + + :kbts_GuessTextPropertiesUtf8 + :GuessTextPropertiesUtf8 + void kbts_GuessTextPropertiesUtf8(const char *Utf8, int Utf8Length, + kbts_direction *Direction, kbts_script *Script) + Convenience wrapper for kbts_GuessTextProperties for UTF-8 text. + + OTHER APIS + OTHER:GLYPH ITERATION + :kbts_GlyphIteratorNext + :GlyphIteratorNext + int kbts_GlyphIteratorNext(kbts_glyph_iterator *It, kbts_glyph **Glyph) + Writes the next glyph to iterate over in [Glyph]. + + Once shaping is done, the interesting members of a glyph are: + - Id: the glyph index/id in the font. + - UserId: the user ID you passed in when creating the glyph. + This is typically some kind of codepoint index you can use to trace back + the glyph to your source text. + - AdvanceX/Y and OffsetX/Y: positioning data. + Here is how you might use them: + + kbts_glyph *Glyph; + int CursorX = 0, CursorY = 0; + while(kbts_GlyphIteratorNext(&It, &Glyph)) + { + int GlyphX = CursorX + Glyph->OffsetX; + int GlyphY = CursorY + Glyph->OffsetY; + + CursorX += Glyph->AdvanceX; + CursorY += Glyph->AdvanceY; + } + + You cannot assume that [Glyph] will stay valid if you free its glyph storage, + begin another shaping operation using the same glyph storage, or do any kind + of manipulation involving the glyph storage that holds this glyph. Likewise, + you should probably not assume that [Glyph] will stay valid after the next + call to kbts_GlyphIteratorNext. + + The [return value] is 1 if we found a glyph to return, and 0 if we did not. + Once kbts_GlyphIteratorNext has returned 0, you can keep calling it and + it will keep returning 0. + + :kbts_GlyphIteratorIsValid + :GlyphIteratorIsValid + int kbts_GlyphIteratorIsValid(kbts_glyph_iterator *It) + Returns whether there are still glyphs left to iterate over. + + If this returns a non-zero value, then the next call to + kbts_GlyphIteratorNext will also return a non-zero value and write a valid + glyph. + + OTHER:FONT COVERAGE TEST + To implement font fallback, you need to be able to know if a given span of text + is supported by a given font. However, this process is not as simple as it sounds. + Some Unicode codepoints have "canonical decompositions" and "canonical + recompositions" that are meant to describe different ways to represent the same + text, but with different codepoints. At the beginning of the shaping process, + shapers try all combinations until one is found that is fully supported by the + font. A font coverage test does this within a fixed memory footprint. + + :kbts_FontCoverageTestBegin + :FontCoverageTestBegin + void kbts_FontCoverageTestBegin(kbts_font_coverage_test *Test, kbts_font *Font) + Initializes [Test] to test coverage with [Font]. + + :kbts_FontCoverageTestCodepoint + :FontCoverageTestCodepoint + void kbts_FontCoverageTestCodepoint(kbts_font_coverage_test *Test, int Codepoint) + Feeds [Codepoint] into [Test] and updates coverage information. + + :kbts_FontCoverageTestEnd + :FontCoverageTestEnd + int kbts_FontCoverageTestEnd(kbts_font_coverage_test *Test) + Flushes the pending combinations not yet tested by [Test] and ends the coverage + test. + The [return value] is non-zero if the text is fully supported by the font, + whereas it is 0 if any glyph was not supported. + You can also check Test->Error to see if any glyph was unsupported. + + OTHER:OTHER OTHER:MISC + :kbts_DecodeUtf8 + :DecodeUtf8 + kbts_decode kbts_DecodeUtf8(const char *Utf8, kbts_un Length) + Tries to decode a single codepoint from [Utf8]. + kbts_decode looks like this: + + typedef struct kbts_decode + { + int Codepoint; + + int SourceCharactersConsumed; + int Valid; + } kbts_decode; + + Codepoint is the decoded codepoint. + SourceCharactersConsumed is the amount of bytes that were read from [Utf8]. + If decoding was successful, Valid is non-zero. Otherwise, it is zero. + Valid is zero if we run out of characters, or if the characters in [Utf8] + are invalid. + + :kbts_EncodeUtf8 + :EncodeUtf8 + kbts_encode_utf8 kbts_EncodeUtf8(int Codepoint) + Tries to encode a single codepoint into a UTF-8 sequence of bytes. + kbts_encode looks like this: + + typedef struct kbts_encode_utf8 + { + char Encoded[4]; + int EncodedLength; + int Valid; + } kbts_encode_utf8; + + Encoded is the encoded sequence. + EncodedLength is the number of bytes needed to encode [Codepoint]. + Valid is whether or not [Codepoint] is a valid codepoint to encode. + (All codepoints up to 0x10FFFF inclusive can be encoded.) + When Valid is 0, EncodedLength is also 0. + + :kbts_ScriptDirection + :ScriptDirection + kbts_direction kbts_ScriptDirection(kbts_script Script) + Returns the default direction for a given script. + + :kbts_ScriptIsComplex + :ScriptIsComplex + int kbts_ScriptIsComplex(kbts_script Script) + Returns whether a script is complex, i.e. if it requires complex shaper + support. + + :kbts_ScriptTagToScript + :ScriptTagToScript + kbts_script kbts_ScriptTagToScript(kbts_script_tag Tag) + Returns a given script from a four-character tag. + A kbts_script_tag can be obtained either through the KBTS_SCRIPT_TAG_* + constants, or through the KBTS_FOURCC() macro, which creates a tag from + four characters. + + LANGUAGE SUPPORT + Shaping is NOT supported for the following scripts: + Zawgyi: some fonts exist, but no standardized OpenType feature set seems to exist as of writing. + Syriac: Syriac Abbreviation Mark (0x070F) is not supported. + Egyptian Hieroglyphs, I think, although example text is hard to come by. + Word breaking is NOT supported for languages that require word dictionaries, like CJK. + + FONT SUPPORT + Indic fonts using the Indic1 shaping model are not supported. + e.g., 'bng2' will work, but 'beng' will not. + The Indic v2 shaping model was released with OpenType 1.5 in May 2008. + Traditional Arabic Windows 3.1 fonts are not supported. + https://github.com/harfbuzz/harfbuzz/issues/681 + Thai/Lao PUA fonts are not supported. + These are old fonts that use OS-specific codepages (PUA stands for [Unicode] "Private Use Area") and + pre-OpenType shaping. + https://linux.thai.net/~thep/th-otf/shaping.html + More generally, we try to be compatible with most well-formed fonts, but we try less hard than Harfbuzz + to be compatible with every font under the sun. + + OTHER LIMITATIONS + Explicit direction control characters are not supported. This includes: + 0x202A Left-to-right embedding + 0x202B Right-to-left embedding + 0x202D Left-to-right override + 0x202E Right-to-left override + 0x202C Pop directional formatting + 0x2066 Left-to-right isolate + 0x2067 Right-to-left isolate + 0x2068 First strong isolate + 0x2069 Pop directional isolate + See https://unicode.org/reports/tr9 for more information. + + VERSION HISTORY + 2.05 - Fix custom allocator initialization for kbts_shape_context.PermanentArena. + 2.04 - Fix Indic syllable logic for small/single-character syllables. + Fix wrong indirection in pointer code in Indic syllable logic. + 2.03 - Fix loading blobs directly, fix a parsing edge case in GPOS format 2 subtables. + 2.02 - Improve globbing of cursive attachments. + 2.01 - Add kbts_InitializeGlyphStorage and kbts_ScriptDirection. + Rename some private functions for better namespacing. + Delete some deprecated functions. + Bounds check in kbts_ScriptIsComplex. + Fix a couple pointer iteration bugs. + Fix some pedantic MSVC warnings. + Extend mirroring logic from brackets to any codepoint that has a Unicode mirror. + 2.0 - Completely new API and implementation. + 1.03 - New functions: kbts_FeatureTagToId(), kbts_FeatureOverrideFromTag(), kbts_EmptyGlyphConfig(), kbts_GlyphConfigOverrideFeature(), kbts_GlyphConfigOverrideFeatureFromTag(), kbts_ScriptTagToScript() + Unregistered features can now be overriden using their tags. + This is slower than overriding registered features, i.e. those that have a kbts_feature_id. + Compiler warning cleanup + 1.02b - Feature control for GPOS features + Bounds checking in ReadFontHeader + 1.02a - Positioning fix for format 2 GPOS pair adjustments + 1.02 - Added per-glyph manual feature control through kbts_FeatureOverride(), kbts_GlyphConfig() + Added enum definitions for features cv01-cv99 and ss01-ss20 + 1.01 - Header cleanup and glyph output documentation + 1.0 - Initial release + + TODO + Word dictionaries for word breaking: CJK, etc. + 'stch' feature. + + LICENSE + zlib License + + (C) Copyright 2024-2025 Jimmy Lefevre + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef KB_TEXT_SHAPE_INCLUDED +# define KB_TEXT_SHAPE_INCLUDED + +# ifndef kbts_s64 +# if defined(_MSC_VER) || defined(__BORLANDC__) +# define kbts_s64 __int64 +# else +# define kbts_s64 long long +# endif +# endif +# ifndef kbts_u64 +# if defined(_MSC_VER) || defined(__BORLANDC__) +# define kbts_u64 unsigned __int64 +# else +# define kbts_u64 unsigned long long +# endif +# endif +# ifndef kbts_u32 +# define kbts_u32 unsigned +# endif +# ifndef kbts_u16 +# define kbts_u16 unsigned short +# endif +# ifndef kbts_s32 +# define kbts_s32 int +# endif +# ifndef kbts_s16 +# define kbts_s16 short +# endif +# ifndef kbts_u8 +# define kbts_u8 unsigned char +# endif +# ifndef kbts_s8 +# define kbts_s8 signed char +# endif + +# ifndef KB_TEXT_SHAPE_POINTER_SIZE +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || defined(_M_ARM) || defined(__arm__) || defined(__x86) || (defined(__APPLE__) && defined(__ppc)) || \ + (defined(__TOS_AIX__) && !defined(__64BIT)) +# define KB_TEXT_SHAPE_POINTER_SIZE 4 +# else +# define KB_TEXT_SHAPE_POINTER_SIZE 8 +# endif +# endif + +# if KB_TEXT_SHAPE_POINTER_SIZE == 4 +# define kbts_un kbts_u32 +# define kbts_sn kbts_s32 +# else +# define kbts_un kbts_u64 +# define kbts_sn kbts_s64 +# endif + +# ifdef __has_attribute +# if __has_attribute(fallthrough) +# define KBTS_FALLTHROUGH __attribute__((fallthrough)) +# endif +# endif +# ifndef KBTS_FALLTHROUGH +# define KBTS_FALLTHROUGH +# endif + +# ifndef KBTS_EXPORT +# ifdef KB_TEXT_SHAPE_STATIC +# define KBTS_EXPORT static +# else +# ifdef __cplusplus +# define KBTS_EXPORT extern "C" +# else +# define KBTS_EXPORT extern +# endif +# endif +# endif + +# ifdef _MSC_VER +# define KBTS_INLINE static __forceinline +# define KBTS_NOINLINE static __declspec(noinline) +# define KBTS_ALIGNOF __alignof +# else +# ifdef __has_attribute +# if __has_attribute(always_inline) +# define KBTS_INLINE static inline __attribute__((always_inline)) +# endif +# if __has_attribute(noinline) +# define KBTS_NOINLINE static __attribute__((noinline)) +# endif +# endif +# define KBTS_ALIGNOF __alignof__ +# endif +# ifndef KBTS_INLINE +# define KBTS_INLINE static inline +# endif + +# define KBTS_FOURCC(A, B, C, D) ((A) | ((B) << 8) | ((C) << 16) | ((D) << 24)) + +typedef kbts_u32 kbts_language; +enum kbts_language_enum +{ + KBTS_LANGUAGE_DONT_KNOW = 0, + + KBTS_LANGUAGE_A_HMAO = KBTS_FOURCC('H', 'M', 'D', ' '), + KBTS_LANGUAGE_AARI = KBTS_FOURCC('A', 'R', 'I', ' '), + KBTS_LANGUAGE_ABAZA = KBTS_FOURCC('A', 'B', 'A', ' '), + KBTS_LANGUAGE_ABKHAZIAN = KBTS_FOURCC('A', 'B', 'K', ' '), + KBTS_LANGUAGE_ACHI = KBTS_FOURCC('A', 'C', 'R', ' '), + KBTS_LANGUAGE_ACHOLI = KBTS_FOURCC('A', 'C', 'H', ' '), + KBTS_LANGUAGE_ADYGHE = KBTS_FOURCC('A', 'D', 'Y', ' '), + KBTS_LANGUAGE_AFAR = KBTS_FOURCC('A', 'F', 'R', ' '), + KBTS_LANGUAGE_AFRIKAANS = KBTS_FOURCC('A', 'F', 'K', ' '), + KBTS_LANGUAGE_AGAW = KBTS_FOURCC('A', 'G', 'W', ' '), + KBTS_LANGUAGE_AITON = KBTS_FOURCC('A', 'I', 'O', ' '), + KBTS_LANGUAGE_AKAN = KBTS_FOURCC('A', 'K', 'A', ' '), + KBTS_LANGUAGE_ALBANIAN = KBTS_FOURCC('S', 'Q', 'I', ' '), + KBTS_LANGUAGE_ALSATIAN = KBTS_FOURCC('A', 'L', 'S', ' '), + KBTS_LANGUAGE_ALTAI = KBTS_FOURCC('A', 'L', 'T', ' '), + KBTS_LANGUAGE_ALUO = KBTS_FOURCC('Y', 'N', 'A', ' '), + KBTS_LANGUAGE_AMERICAN_PHONETIC = KBTS_FOURCC('A', 'P', 'P', 'H'), + KBTS_LANGUAGE_AMHARIC = KBTS_FOURCC('A', 'M', 'H', ' '), + KBTS_LANGUAGE_ANGLO_SAXON = KBTS_FOURCC('A', 'N', 'G', ' '), + KBTS_LANGUAGE_ARABIC = KBTS_FOURCC('A', 'R', 'A', ' '), + KBTS_LANGUAGE_ARAGONESE = KBTS_FOURCC('A', 'R', 'G', ' '), + KBTS_LANGUAGE_ARAKANESE = KBTS_FOURCC('A', 'R', 'K', ' '), + KBTS_LANGUAGE_ARAKWAL = KBTS_FOURCC('R', 'K', 'W', ' '), + KBTS_LANGUAGE_ARMENIAN = KBTS_FOURCC('H', 'Y', 'E', ' '), + KBTS_LANGUAGE_ARMENIAN_EAST = KBTS_FOURCC('H', 'Y', 'E', '0'), + KBTS_LANGUAGE_AROMANIAN = KBTS_FOURCC('R', 'U', 'P', ' '), + KBTS_LANGUAGE_ARPITAN = KBTS_FOURCC('F', 'R', 'P', ' '), + KBTS_LANGUAGE_ASSAMESE = KBTS_FOURCC('A', 'S', 'M', ' '), + KBTS_LANGUAGE_ASTURIAN = KBTS_FOURCC('A', 'S', 'T', ' '), + KBTS_LANGUAGE_ATHAPASKAN = KBTS_FOURCC('A', 'T', 'H', ' '), + KBTS_LANGUAGE_ATSINA = KBTS_FOURCC('A', 'T', 'S', ' '), + KBTS_LANGUAGE_AVAR = KBTS_FOURCC('A', 'V', 'R', ' '), + KBTS_LANGUAGE_AVATIME = KBTS_FOURCC('A', 'V', 'N', ' '), + KBTS_LANGUAGE_AWADHI = KBTS_FOURCC('A', 'W', 'A', ' '), + KBTS_LANGUAGE_AYMARA = KBTS_FOURCC('A', 'Y', 'M', ' '), + KBTS_LANGUAGE_AZERBAIDJANI = KBTS_FOURCC('A', 'Z', 'E', ' '), + KBTS_LANGUAGE_BADAGA = KBTS_FOURCC('B', 'A', 'D', ' '), + KBTS_LANGUAGE_BAGHELKHANDI = KBTS_FOURCC('B', 'A', 'G', ' '), + KBTS_LANGUAGE_BAGRI = KBTS_FOURCC('B', 'G', 'Q', ' '), + KBTS_LANGUAGE_BALANTE = KBTS_FOURCC('B', 'L', 'N', ' '), + KBTS_LANGUAGE_BALINESE = KBTS_FOURCC('B', 'A', 'N', ' '), + KBTS_LANGUAGE_BALKAR = KBTS_FOURCC('B', 'A', 'L', ' '), + KBTS_LANGUAGE_BALTI = KBTS_FOURCC('B', 'L', 'T', ' '), + KBTS_LANGUAGE_BALUCHI = KBTS_FOURCC('B', 'L', 'I', ' '), + KBTS_LANGUAGE_BAMBARA = KBTS_FOURCC('B', 'M', 'B', ' '), + KBTS_LANGUAGE_BAMILEKE = KBTS_FOURCC('B', 'M', 'L', ' '), + KBTS_LANGUAGE_BANDA = KBTS_FOURCC('B', 'A', 'D', '0'), + KBTS_LANGUAGE_BANDJALANG = KBTS_FOURCC('B', 'D', 'Y', ' '), + KBTS_LANGUAGE_BANGLA = KBTS_FOURCC('B', 'E', 'N', ' '), + KBTS_LANGUAGE_BASHKIR = KBTS_FOURCC('B', 'S', 'H', ' '), + KBTS_LANGUAGE_BASQUE = KBTS_FOURCC('E', 'U', 'Q', ' '), + KBTS_LANGUAGE_BATAK = KBTS_FOURCC('B', 'T', 'K', ' '), + KBTS_LANGUAGE_BATAK_ALAS_KLUET = KBTS_FOURCC('B', 'T', 'Z', ' '), + KBTS_LANGUAGE_BATAK_ANGKOLA = KBTS_FOURCC('A', 'K', 'B', ' '), + KBTS_LANGUAGE_BATAK_DAIRI = KBTS_FOURCC('B', 'T', 'D', ' '), + KBTS_LANGUAGE_BATAK_KARO = KBTS_FOURCC('B', 'T', 'X', ' '), + KBTS_LANGUAGE_BATAK_MANDAILING = KBTS_FOURCC('B', 'T', 'M', ' '), + KBTS_LANGUAGE_BATAK_SIMALUNGUN = KBTS_FOURCC('B', 'T', 'S', ' '), + KBTS_LANGUAGE_BATAK_TOBA = KBTS_FOURCC('B', 'B', 'C', ' '), + KBTS_LANGUAGE_BAULE = KBTS_FOURCC('B', 'A', 'U', ' '), + KBTS_LANGUAGE_BAVARIAN = KBTS_FOURCC('B', 'A', 'R', ' '), + KBTS_LANGUAGE_BELARUSIAN = KBTS_FOURCC('B', 'E', 'L', ' '), + KBTS_LANGUAGE_BEMBA = KBTS_FOURCC('B', 'E', 'M', ' '), + KBTS_LANGUAGE_BENCH = KBTS_FOURCC('B', 'C', 'H', ' '), + KBTS_LANGUAGE_BERBER = KBTS_FOURCC('B', 'B', 'R', ' '), + KBTS_LANGUAGE_BETI = KBTS_FOURCC('B', 'T', 'I', ' '), + KBTS_LANGUAGE_BETTE_KURUMA = KBTS_FOURCC('X', 'U', 'B', ' '), + KBTS_LANGUAGE_BHILI = KBTS_FOURCC('B', 'H', 'I', ' '), + KBTS_LANGUAGE_BHOJPURI = KBTS_FOURCC('B', 'H', 'O', ' '), + KBTS_LANGUAGE_BHUTANESE = KBTS_FOURCC('D', 'Z', 'N', ' '), + KBTS_LANGUAGE_BIBLE_CREE = KBTS_FOURCC('B', 'C', 'R', ' '), + KBTS_LANGUAGE_BIKOL = KBTS_FOURCC('B', 'I', 'K', ' '), + KBTS_LANGUAGE_BILEN = KBTS_FOURCC('B', 'I', 'L', ' '), + KBTS_LANGUAGE_BISHNUPRIYA_MANIPURI = KBTS_FOURCC('B', 'P', 'Y', ' '), + KBTS_LANGUAGE_BISLAMA = KBTS_FOURCC('B', 'I', 'S', ' '), + KBTS_LANGUAGE_BLACKFOOT = KBTS_FOURCC('B', 'K', 'F', ' '), + KBTS_LANGUAGE_BODO = KBTS_FOURCC('B', 'R', 'X', ' '), + KBTS_LANGUAGE_BOSNIAN = KBTS_FOURCC('B', 'O', 'S', ' '), + KBTS_LANGUAGE_BOUYEI = KBTS_FOURCC('P', 'C', 'C', ' '), + KBTS_LANGUAGE_BRAHUI = KBTS_FOURCC('B', 'R', 'H', ' '), + KBTS_LANGUAGE_BRAJ_BHASHA = KBTS_FOURCC('B', 'R', 'I', ' '), + KBTS_LANGUAGE_BRETON = KBTS_FOURCC('B', 'R', 'E', ' '), + KBTS_LANGUAGE_BUGIS = KBTS_FOURCC('B', 'U', 'G', ' '), + KBTS_LANGUAGE_BULGARIAN = KBTS_FOURCC('B', 'G', 'R', ' '), + KBTS_LANGUAGE_BUMTHANGKHA = KBTS_FOURCC('K', 'J', 'Z', ' '), + KBTS_LANGUAGE_BURMESE = KBTS_FOURCC('B', 'R', 'M', ' '), + KBTS_LANGUAGE_BURUSHASKI = KBTS_FOURCC('B', 'S', 'K', ' '), + KBTS_LANGUAGE_CAJUN_FRENCH = KBTS_FOURCC('F', 'R', 'C', ' '), + KBTS_LANGUAGE_CARRIER = KBTS_FOURCC('C', 'R', 'R', ' '), + KBTS_LANGUAGE_CATALAN = KBTS_FOURCC('C', 'A', 'T', ' '), + KBTS_LANGUAGE_CAYUGA = KBTS_FOURCC('C', 'A', 'Y', ' '), + KBTS_LANGUAGE_CEBUANO = KBTS_FOURCC('C', 'E', 'B', ' '), + KBTS_LANGUAGE_CENTRAL_YUPIK = KBTS_FOURCC('E', 'S', 'U', ' '), + KBTS_LANGUAGE_CHAHA_GURAGE = KBTS_FOURCC('C', 'H', 'G', ' '), + KBTS_LANGUAGE_CHAMORRO = KBTS_FOURCC('C', 'H', 'A', ' '), + KBTS_LANGUAGE_CHATTISGARHI = KBTS_FOURCC('C', 'H', 'H', ' '), + KBTS_LANGUAGE_CHECHEN = KBTS_FOURCC('C', 'H', 'E', ' '), + KBTS_LANGUAGE_CHEROKEE = KBTS_FOURCC('C', 'H', 'R', ' '), + KBTS_LANGUAGE_CHEYENNE = KBTS_FOURCC('C', 'H', 'Y', ' '), + KBTS_LANGUAGE_CHICHEWA = KBTS_FOURCC('C', 'H', 'I', ' '), + KBTS_LANGUAGE_CHIGA = KBTS_FOURCC('C', 'G', 'G', ' '), + KBTS_LANGUAGE_CHIMILA = KBTS_FOURCC('C', 'B', 'G', ' '), + KBTS_LANGUAGE_CHIN = KBTS_FOURCC('Q', 'I', 'N', ' '), + KBTS_LANGUAGE_CHINANTEC = KBTS_FOURCC('C', 'C', 'H', 'N'), + KBTS_LANGUAGE_CHINESE_PHONETIC = KBTS_FOURCC('Z', 'H', 'P', ' '), + KBTS_LANGUAGE_CHINESE_SIMPLIFIED = KBTS_FOURCC('Z', 'H', 'S', ' '), + KBTS_LANGUAGE_CHINESE_TRADITIONAL = KBTS_FOURCC('Z', 'H', 'T', ' '), + KBTS_LANGUAGE_CHINESE_TRADITIONAL_HONG_KONG = KBTS_FOURCC('Z', 'H', 'H', ' '), + KBTS_LANGUAGE_CHINESE_TRADITIONAL_MACAO = KBTS_FOURCC('Z', 'H', 'T', 'M'), + KBTS_LANGUAGE_CHIPEWYAN = KBTS_FOURCC('C', 'H', 'P', ' '), + KBTS_LANGUAGE_CHITTAGONIAN = KBTS_FOURCC('C', 'T', 'G', ' '), + KBTS_LANGUAGE_CHOCTAW = KBTS_FOURCC('C', 'H', 'O', ' '), + KBTS_LANGUAGE_CHUKCHI = KBTS_FOURCC('C', 'H', 'K', ' '), + KBTS_LANGUAGE_CHURCH_SLAVONIC = KBTS_FOURCC('C', 'S', 'L', ' '), + KBTS_LANGUAGE_CHUUKESE = KBTS_FOURCC('C', 'H', 'K', '0'), + KBTS_LANGUAGE_CHUVASH = KBTS_FOURCC('C', 'H', 'U', ' '), + KBTS_LANGUAGE_COMORIAN = KBTS_FOURCC('C', 'M', 'R', ' '), + KBTS_LANGUAGE_COMOX = KBTS_FOURCC('C', 'O', 'O', ' '), + KBTS_LANGUAGE_COPTIC = KBTS_FOURCC('C', 'O', 'P', ' '), + KBTS_LANGUAGE_CORNISH = KBTS_FOURCC('C', 'O', 'R', ' '), + KBTS_LANGUAGE_CORSICAN = KBTS_FOURCC('C', 'O', 'S', ' '), + KBTS_LANGUAGE_CREE = KBTS_FOURCC('C', 'R', 'E', ' '), + KBTS_LANGUAGE_CREOLES = KBTS_FOURCC('C', 'P', 'P', ' '), + KBTS_LANGUAGE_CRIMEAN_TATAR = KBTS_FOURCC('C', 'R', 'T', ' '), + KBTS_LANGUAGE_CRIOULO = KBTS_FOURCC('K', 'E', 'A', ' '), + KBTS_LANGUAGE_CROATIAN = KBTS_FOURCC('H', 'R', 'V', ' '), + KBTS_LANGUAGE_CYPRIOT_ARABIC = KBTS_FOURCC('A', 'C', 'Y', ' '), + KBTS_LANGUAGE_CZECH = KBTS_FOURCC('C', 'S', 'Y', ' '), + KBTS_LANGUAGE_DAGBANI = KBTS_FOURCC('D', 'A', 'G', ' '), + KBTS_LANGUAGE_DAN = KBTS_FOURCC('D', 'N', 'J', ' '), + KBTS_LANGUAGE_DANGME = KBTS_FOURCC('D', 'N', 'G', ' '), + KBTS_LANGUAGE_DANISH = KBTS_FOURCC('D', 'A', 'N', ' '), + KBTS_LANGUAGE_DARGWA = KBTS_FOURCC('D', 'A', 'R', ' '), + KBTS_LANGUAGE_DARI = KBTS_FOURCC('D', 'R', 'I', ' '), + KBTS_LANGUAGE_DAYI = KBTS_FOURCC('D', 'A', 'X', ' '), + KBTS_LANGUAGE_DEFAULT = KBTS_FOURCC('d', 'f', 'l', 't'), // Can be DFLT too... + KBTS_LANGUAGE_DEHONG_DAI = KBTS_FOURCC('T', 'D', 'D', ' '), + KBTS_LANGUAGE_DHANGU = KBTS_FOURCC('D', 'H', 'G', ' '), + KBTS_LANGUAGE_DHIVEHI = KBTS_FOURCC('D', 'I', 'V', ' '), + KBTS_LANGUAGE_DHUWAL = KBTS_FOURCC('D', 'U', 'J', ' '), + KBTS_LANGUAGE_DIMLI = KBTS_FOURCC('D', 'I', 'Q', ' '), + KBTS_LANGUAGE_DINKA = KBTS_FOURCC('D', 'N', 'K', ' '), + KBTS_LANGUAGE_DIVEHI = KBTS_FOURCC('D', 'I', 'V', ' '), + KBTS_LANGUAGE_DJAMBARRPUYNGU = KBTS_FOURCC('D', 'J', 'R', '0'), + KBTS_LANGUAGE_DOGRI = KBTS_FOURCC('D', 'G', 'O', ' '), + KBTS_LANGUAGE_DOGRI_MACROLANGUAGE = KBTS_FOURCC('D', 'G', 'R', ' '), + KBTS_LANGUAGE_DUNGAN = KBTS_FOURCC('D', 'U', 'N', ' '), + KBTS_LANGUAGE_DUTCH = KBTS_FOURCC('N', 'L', 'D', ' '), + KBTS_LANGUAGE_DZONGKHA = KBTS_FOURCC('D', 'Z', 'N', ' '), + KBTS_LANGUAGE_EASTERN_ABENAKI = KBTS_FOURCC('A', 'A', 'Q', ' '), + KBTS_LANGUAGE_EASTERN_CHAM = KBTS_FOURCC('C', 'J', 'M', ' '), + KBTS_LANGUAGE_EASTERN_CREE = KBTS_FOURCC('E', 'C', 'R', ' '), + KBTS_LANGUAGE_EASTERN_MANINKAKAN = KBTS_FOURCC('E', 'M', 'K', ' '), + KBTS_LANGUAGE_EASTERN_PWO_KAREN = KBTS_FOURCC('K', 'J', 'P', ' '), + KBTS_LANGUAGE_EBIRA = KBTS_FOURCC('E', 'B', 'I', ' '), + KBTS_LANGUAGE_EDO = KBTS_FOURCC('E', 'D', 'O', ' '), + KBTS_LANGUAGE_EFIK = KBTS_FOURCC('E', 'F', 'I', ' '), + KBTS_LANGUAGE_EMBERA_BAUDO = KBTS_FOURCC('B', 'D', 'C', ' '), + KBTS_LANGUAGE_EMBERA_CATIO = KBTS_FOURCC('C', 'T', 'O', ' '), + KBTS_LANGUAGE_EMBERA_CHAMI = KBTS_FOURCC('C', 'M', 'I', ' '), + KBTS_LANGUAGE_EMBERA_TADO = KBTS_FOURCC('T', 'D', 'C', ' '), + KBTS_LANGUAGE_ENGLISH = KBTS_FOURCC('E', 'N', 'G', ' '), + KBTS_LANGUAGE_EPENA = KBTS_FOURCC('S', 'J', 'A', ' '), + KBTS_LANGUAGE_ERZYA = KBTS_FOURCC('E', 'R', 'Z', ' '), + KBTS_LANGUAGE_KB_TEXT_SHAPEANTO = KBTS_FOURCC('N', 'T', 'O', ' '), + KBTS_LANGUAGE_ESTONIAN = KBTS_FOURCC('E', 'T', 'I', ' '), + KBTS_LANGUAGE_EVEN = KBTS_FOURCC('E', 'V', 'N', ' '), + KBTS_LANGUAGE_EVENKI = KBTS_FOURCC('E', 'V', 'K', ' '), + KBTS_LANGUAGE_EWE = KBTS_FOURCC('E', 'W', 'E', ' '), + KBTS_LANGUAGE_FALAM_CHIN = KBTS_FOURCC('H', 'A', 'L', ' '), + KBTS_LANGUAGE_FANG = KBTS_FOURCC('F', 'A', 'N', '0'), + KBTS_LANGUAGE_FANTI = KBTS_FOURCC('F', 'A', 'T', ' '), + KBTS_LANGUAGE_FAROESE = KBTS_FOURCC('F', 'O', 'S', ' '), + KBTS_LANGUAGE_FEFE = KBTS_FOURCC('F', 'M', 'P', ' '), + KBTS_LANGUAGE_FIJIAN = KBTS_FOURCC('F', 'J', 'I', ' '), + KBTS_LANGUAGE_FILIPINO = KBTS_FOURCC('P', 'I', 'L', ' '), + KBTS_LANGUAGE_FINNISH = KBTS_FOURCC('F', 'I', 'N', ' '), + KBTS_LANGUAGE_FLEMISH = KBTS_FOURCC('F', 'L', 'E', ' '), + KBTS_LANGUAGE_FON = KBTS_FOURCC('F', 'O', 'N', ' '), + KBTS_LANGUAGE_FOREST_ENETS = KBTS_FOURCC('F', 'N', 'E', ' '), + KBTS_LANGUAGE_FRENCH = KBTS_FOURCC('F', 'R', 'A', ' '), + KBTS_LANGUAGE_FRENCH_ANTILLEAN = KBTS_FOURCC('F', 'A', 'N', ' '), + KBTS_LANGUAGE_FRISIAN = KBTS_FOURCC('F', 'R', 'I', ' '), + KBTS_LANGUAGE_FRIULIAN = KBTS_FOURCC('F', 'R', 'L', ' '), + KBTS_LANGUAGE_FULAH = KBTS_FOURCC('F', 'U', 'L', ' '), + KBTS_LANGUAGE_FUTA = KBTS_FOURCC('F', 'T', 'A', ' '), + KBTS_LANGUAGE_GA = KBTS_FOURCC('G', 'A', 'D', ' '), + KBTS_LANGUAGE_GAGAUZ = KBTS_FOURCC('G', 'A', 'G', ' '), + KBTS_LANGUAGE_GALICIAN = KBTS_FOURCC('G', 'A', 'L', ' '), + KBTS_LANGUAGE_GANDA = KBTS_FOURCC('L', 'U', 'G', ' '), + KBTS_LANGUAGE_GARHWALI = KBTS_FOURCC('G', 'A', 'W', ' '), + KBTS_LANGUAGE_GARO = KBTS_FOURCC('G', 'R', 'O', ' '), + KBTS_LANGUAGE_GARSHUNI = KBTS_FOURCC('G', 'A', 'R', ' '), + KBTS_LANGUAGE_GEBA_KAREN = KBTS_FOURCC('K', 'V', 'Q', ' '), + KBTS_LANGUAGE_GEEZ = KBTS_FOURCC('G', 'E', 'Z', ' '), + KBTS_LANGUAGE_GEORGIAN = KBTS_FOURCC('K', 'A', 'T', ' '), + KBTS_LANGUAGE_GEPO = KBTS_FOURCC('Y', 'G', 'P', ' '), + KBTS_LANGUAGE_GERMAN = KBTS_FOURCC('D', 'E', 'U', ' '), + KBTS_LANGUAGE_GIKUYU = KBTS_FOURCC('K', 'I', 'K', ' '), + KBTS_LANGUAGE_GILAKI = KBTS_FOURCC('G', 'L', 'K', ' '), + KBTS_LANGUAGE_GILBERTESE = KBTS_FOURCC('G', 'I', 'L', '0'), + KBTS_LANGUAGE_GILYAK = KBTS_FOURCC('G', 'I', 'L', ' '), + KBTS_LANGUAGE_GITHABUL = KBTS_FOURCC('G', 'I', 'H', ' '), + KBTS_LANGUAGE_GOGO = KBTS_FOURCC('G', 'O', 'G', ' '), + KBTS_LANGUAGE_GONDI = KBTS_FOURCC('G', 'O', 'N', ' '), + KBTS_LANGUAGE_GREEK = KBTS_FOURCC('E', 'L', 'L', ' '), + KBTS_LANGUAGE_GREENLANDIC = KBTS_FOURCC('G', 'R', 'N', ' '), + KBTS_LANGUAGE_GUARANI = KBTS_FOURCC('G', 'U', 'A', ' '), + KBTS_LANGUAGE_GUINEA = KBTS_FOURCC('G', 'K', 'P', ' '), + KBTS_LANGUAGE_GUJARATI = KBTS_FOURCC('G', 'U', 'J', ' '), + KBTS_LANGUAGE_GUMATJ = KBTS_FOURCC('G', 'N', 'N', ' '), + KBTS_LANGUAGE_GUMUZ = KBTS_FOURCC('G', 'M', 'Z', ' '), + KBTS_LANGUAGE_GUPAPUYNGU = KBTS_FOURCC('G', 'U', 'F', ' '), + KBTS_LANGUAGE_GUSII = KBTS_FOURCC('G', 'U', 'Z', ' '), + KBTS_LANGUAGE_HAIDA = KBTS_FOURCC('H', 'A', 'I', '0'), + KBTS_LANGUAGE_HAITIAN_CREOLE = KBTS_FOURCC('H', 'A', 'I', ' '), + KBTS_LANGUAGE_HALKOMELEM = KBTS_FOURCC('H', 'U', 'R', ' '), + KBTS_LANGUAGE_HAMMER_BANNA = KBTS_FOURCC('H', 'B', 'N', ' '), + KBTS_LANGUAGE_HARARI = KBTS_FOURCC('H', 'R', 'I', ' '), + KBTS_LANGUAGE_HARAUTI = KBTS_FOURCC('H', 'A', 'R', ' '), + KBTS_LANGUAGE_HARYANVI = KBTS_FOURCC('B', 'G', 'C', ' '), + KBTS_LANGUAGE_HAUSA = KBTS_FOURCC('H', 'A', 'U', ' '), + KBTS_LANGUAGE_HAVASUPAI_WALAPAI_YAVAPAI = KBTS_FOURCC('Y', 'U', 'F', ' '), + KBTS_LANGUAGE_HAWAIIAN = KBTS_FOURCC('H', 'A', 'W', ' '), + KBTS_LANGUAGE_HAYA = KBTS_FOURCC('H', 'A', 'Y', ' '), + KBTS_LANGUAGE_HAZARAGI = KBTS_FOURCC('H', 'A', 'Z', ' '), + KBTS_LANGUAGE_HEBREW = KBTS_FOURCC('I', 'W', 'R', ' '), + KBTS_LANGUAGE_HEILTSUK = KBTS_FOURCC('H', 'E', 'I', ' '), + KBTS_LANGUAGE_HERERO = KBTS_FOURCC('H', 'E', 'R', ' '), + KBTS_LANGUAGE_HIGH_MARI = KBTS_FOURCC('H', 'M', 'A', ' '), + KBTS_LANGUAGE_HILIGAYNON = KBTS_FOURCC('H', 'I', 'L', ' '), + KBTS_LANGUAGE_HINDI = KBTS_FOURCC('H', 'I', 'N', ' '), + KBTS_LANGUAGE_HINDKO = KBTS_FOURCC('H', 'N', 'D', ' '), + KBTS_LANGUAGE_HIRI_MOTU = KBTS_FOURCC('H', 'M', 'O', ' '), + KBTS_LANGUAGE_HMONG = KBTS_FOURCC('H', 'M', 'N', ' '), + KBTS_LANGUAGE_HMONG_DAW = KBTS_FOURCC('M', 'W', 'W', ' '), + KBTS_LANGUAGE_HMONG_SHUAT = KBTS_FOURCC('H', 'M', 'Z', ' '), + KBTS_LANGUAGE_HO = KBTS_FOURCC('H', 'O', ' ', ' '), + KBTS_LANGUAGE_HUNGARIAN = KBTS_FOURCC('H', 'U', 'N', ' '), + KBTS_LANGUAGE_IBAN = KBTS_FOURCC('I', 'B', 'A', ' '), + KBTS_LANGUAGE_IBIBIO = KBTS_FOURCC('I', 'B', 'B', ' '), + KBTS_LANGUAGE_ICELANDIC = KBTS_FOURCC('I', 'S', 'L', ' '), + KBTS_LANGUAGE_IDO = KBTS_FOURCC('I', 'D', 'O', ' '), + KBTS_LANGUAGE_IGBO = KBTS_FOURCC('I', 'B', 'O', ' '), + KBTS_LANGUAGE_IJO = KBTS_FOURCC('I', 'J', 'O', ' '), + KBTS_LANGUAGE_ILOKANO = KBTS_FOURCC('I', 'L', 'O', ' '), + KBTS_LANGUAGE_INARI_SAMI = KBTS_FOURCC('I', 'S', 'M', ' '), + KBTS_LANGUAGE_INDONESIAN = KBTS_FOURCC('I', 'N', 'D', ' '), + KBTS_LANGUAGE_INGUSH = KBTS_FOURCC('I', 'N', 'G', ' '), + KBTS_LANGUAGE_INTERLINGUA = KBTS_FOURCC('I', 'N', 'A', ' '), + KBTS_LANGUAGE_INTERLINGUE = KBTS_FOURCC('I', 'L', 'E', ' '), + KBTS_LANGUAGE_INUKTITUT = KBTS_FOURCC('I', 'N', 'U', ' '), + KBTS_LANGUAGE_INUPIAT = KBTS_FOURCC('I', 'P', 'K', ' '), + KBTS_LANGUAGE_IPA_PHONETIC = KBTS_FOURCC('I', 'P', 'P', ' '), + KBTS_LANGUAGE_IRISH = KBTS_FOURCC('I', 'R', 'I', ' '), + KBTS_LANGUAGE_IRISH_TRADITIONAL = KBTS_FOURCC('I', 'R', 'T', ' '), + KBTS_LANGUAGE_IRULA = KBTS_FOURCC('I', 'R', 'U', ' '), + KBTS_LANGUAGE_ITALIAN = KBTS_FOURCC('I', 'T', 'A', ' '), + KBTS_LANGUAGE_JAMAICAN_CREOLE = KBTS_FOURCC('J', 'A', 'M', ' '), + KBTS_LANGUAGE_JAPANESE = KBTS_FOURCC('J', 'A', 'N', ' '), + KBTS_LANGUAGE_JAVANESE = KBTS_FOURCC('J', 'A', 'V', ' '), + KBTS_LANGUAGE_JENNU_KURUMA = KBTS_FOURCC('X', 'U', 'J', ' '), + KBTS_LANGUAGE_JUDEO_TAT = KBTS_FOURCC('J', 'D', 'T', ' '), + KBTS_LANGUAGE_JULA = KBTS_FOURCC('J', 'U', 'L', ' '), + KBTS_LANGUAGE_KABARDIAN = KBTS_FOURCC('K', 'A', 'B', ' '), + KBTS_LANGUAGE_KABYLE = KBTS_FOURCC('K', 'A', 'B', '0'), + KBTS_LANGUAGE_KACHCHI = KBTS_FOURCC('K', 'A', 'C', ' '), + KBTS_LANGUAGE_KADIWEU = KBTS_FOURCC('K', 'B', 'C', ' '), + KBTS_LANGUAGE_KALENJIN = KBTS_FOURCC('K', 'A', 'L', ' '), + KBTS_LANGUAGE_KALMYK = KBTS_FOURCC('K', 'L', 'M', ' '), + KBTS_LANGUAGE_KAMBA = KBTS_FOURCC('K', 'M', 'B', ' '), + KBTS_LANGUAGE_KANAUJI = KBTS_FOURCC('B', 'J', 'J', ' '), + KBTS_LANGUAGE_KANNADA = KBTS_FOURCC('K', 'A', 'N', ' '), + KBTS_LANGUAGE_KANURI = KBTS_FOURCC('K', 'N', 'R', ' '), + KBTS_LANGUAGE_KAQCHIKEL = KBTS_FOURCC('C', 'A', 'K', ' '), + KBTS_LANGUAGE_KARACHAY = KBTS_FOURCC('K', 'A', 'R', ' '), + KBTS_LANGUAGE_KARAIM = KBTS_FOURCC('K', 'R', 'M', ' '), + KBTS_LANGUAGE_KARAKALPAK = KBTS_FOURCC('K', 'R', 'K', ' '), + KBTS_LANGUAGE_KARELIAN = KBTS_FOURCC('K', 'R', 'L', ' '), + KBTS_LANGUAGE_KAREN = KBTS_FOURCC('K', 'R', 'N', ' '), + KBTS_LANGUAGE_KASHMIRI = KBTS_FOURCC('K', 'S', 'H', ' '), + KBTS_LANGUAGE_KASHUBIAN = KBTS_FOURCC('C', 'S', 'B', ' '), + KBTS_LANGUAGE_KATE = KBTS_FOURCC('K', 'M', 'G', ' '), + KBTS_LANGUAGE_KAZAKH = KBTS_FOURCC('K', 'A', 'Z', ' '), + KBTS_LANGUAGE_KEBENA = KBTS_FOURCC('K', 'E', 'B', ' '), + KBTS_LANGUAGE_KEKCHI = KBTS_FOURCC('K', 'E', 'K', ' '), + KBTS_LANGUAGE_KHAKASS = KBTS_FOURCC('K', 'H', 'A', ' '), + KBTS_LANGUAGE_KHAMTI_SHAN = KBTS_FOURCC('K', 'H', 'T', ' '), + KBTS_LANGUAGE_KHAMYANG = KBTS_FOURCC('K', 'S', 'U', ' '), + KBTS_LANGUAGE_KHANTY_KAZIM = KBTS_FOURCC('K', 'H', 'K', ' '), + KBTS_LANGUAGE_KHANTY_SHURISHKAR = KBTS_FOURCC('K', 'H', 'S', ' '), + KBTS_LANGUAGE_KHANTY_VAKHI = KBTS_FOURCC('K', 'H', 'V', ' '), + KBTS_LANGUAGE_KHASI = KBTS_FOURCC('K', 'S', 'I', ' '), + KBTS_LANGUAGE_KHENGKHA = KBTS_FOURCC('X', 'K', 'F', ' '), + KBTS_LANGUAGE_KHINALUG = KBTS_FOURCC('K', 'J', 'J', ' '), + KBTS_LANGUAGE_KHMER = KBTS_FOURCC('K', 'H', 'M', ' '), + KBTS_LANGUAGE_KHORASANI_TURKIC = KBTS_FOURCC('K', 'M', 'Z', ' '), + KBTS_LANGUAGE_KHOWAR = KBTS_FOURCC('K', 'H', 'W', ' '), + KBTS_LANGUAGE_KHUTSURI_GEORGIAN = KBTS_FOURCC('K', 'G', 'E', ' '), + KBTS_LANGUAGE_KICHE = KBTS_FOURCC('Q', 'U', 'C', ' '), + KBTS_LANGUAGE_KIKONGO = KBTS_FOURCC('K', 'O', 'N', ' '), + KBTS_LANGUAGE_KILDIN_SAMI = KBTS_FOURCC('K', 'S', 'M', ' '), + KBTS_LANGUAGE_KINYARWANDA = KBTS_FOURCC('R', 'U', 'A', ' '), + KBTS_LANGUAGE_KIRMANJKI = KBTS_FOURCC('K', 'I', 'U', ' '), + KBTS_LANGUAGE_KISII = KBTS_FOURCC('K', 'I', 'S', ' '), + KBTS_LANGUAGE_KITUBA = KBTS_FOURCC('M', 'K', 'W', ' '), + KBTS_LANGUAGE_KODAGU = KBTS_FOURCC('K', 'O', 'D', ' '), + KBTS_LANGUAGE_KOKNI = KBTS_FOURCC('K', 'K', 'N', ' '), + KBTS_LANGUAGE_KOMI = KBTS_FOURCC('K', 'O', 'M', ' '), + KBTS_LANGUAGE_KOMI_PERMYAK = KBTS_FOURCC('K', 'O', 'P', ' '), + KBTS_LANGUAGE_KOMI_ZYRIAN = KBTS_FOURCC('K', 'O', 'Z', ' '), + KBTS_LANGUAGE_KOMO = KBTS_FOURCC('K', 'M', 'O', ' '), + KBTS_LANGUAGE_KOMSO = KBTS_FOURCC('K', 'M', 'S', ' '), + KBTS_LANGUAGE_KONGO = KBTS_FOURCC('K', 'O', 'N', '0'), + KBTS_LANGUAGE_KONKANI = KBTS_FOURCC('K', 'O', 'K', ' '), + KBTS_LANGUAGE_KOORETE = KBTS_FOURCC('K', 'R', 'T', ' '), + KBTS_LANGUAGE_KOREAN = KBTS_FOURCC('K', 'O', 'R', ' '), + KBTS_LANGUAGE_KOREAO_OLD_HANGUL = KBTS_FOURCC('K', 'O', 'H', ' '), + KBTS_LANGUAGE_KORYAK = KBTS_FOURCC('K', 'Y', 'K', ' '), + KBTS_LANGUAGE_KOSRAEAN = KBTS_FOURCC('K', 'O', 'S', ' '), + KBTS_LANGUAGE_KPELLE = KBTS_FOURCC('K', 'P', 'L', ' '), + KBTS_LANGUAGE_KPELLE_LIBERIA = KBTS_FOURCC('X', 'P', 'E', ' '), + KBTS_LANGUAGE_KRIO = KBTS_FOURCC('K', 'R', 'I', ' '), + KBTS_LANGUAGE_KRYMCHAK = KBTS_FOURCC('J', 'C', 'T', ' '), + KBTS_LANGUAGE_KUANYAMA = KBTS_FOURCC('K', 'U', 'A', ' '), + KBTS_LANGUAGE_KUBE = KBTS_FOURCC('K', 'G', 'F', ' '), + KBTS_LANGUAGE_KUI = KBTS_FOURCC('K', 'U', 'I', ' '), + KBTS_LANGUAGE_KULVI = KBTS_FOURCC('K', 'U', 'K', ' '), + KBTS_LANGUAGE_KUMAONI = KBTS_FOURCC('K', 'M', 'N', ' '), + KBTS_LANGUAGE_KUMYK = KBTS_FOURCC('K', 'U', 'M', ' '), + KBTS_LANGUAGE_KURDISH = KBTS_FOURCC('K', 'U', 'R', ' '), + KBTS_LANGUAGE_KURUKH = KBTS_FOURCC('K', 'U', 'U', ' '), + KBTS_LANGUAGE_KUY = KBTS_FOURCC('K', 'U', 'Y', ' '), + KBTS_LANGUAGE_KWAKWALA = KBTS_FOURCC('K', 'W', 'K', ' '), + KBTS_LANGUAGE_KYRGYZ = KBTS_FOURCC('K', 'I', 'R', ' '), + KBTS_LANGUAGE_L_CREE = KBTS_FOURCC('L', 'C', 'R', ' '), + KBTS_LANGUAGE_LADAKHI = KBTS_FOURCC('L', 'D', 'K', ' '), + KBTS_LANGUAGE_LADIN = KBTS_FOURCC('L', 'A', 'D', ' '), + KBTS_LANGUAGE_LADINO = KBTS_FOURCC('J', 'U', 'D', ' '), + KBTS_LANGUAGE_LAHULI = KBTS_FOURCC('L', 'A', 'H', ' '), + KBTS_LANGUAGE_LAK = KBTS_FOURCC('L', 'A', 'K', ' '), + KBTS_LANGUAGE_LAKI = KBTS_FOURCC('L', 'K', 'I', ' '), + KBTS_LANGUAGE_LAMBANI = KBTS_FOURCC('L', 'A', 'M', ' '), + KBTS_LANGUAGE_LAMPUNG = KBTS_FOURCC('L', 'J', 'P', ' '), + KBTS_LANGUAGE_LAO = KBTS_FOURCC('L', 'A', 'O', ' '), + KBTS_LANGUAGE_LATIN = KBTS_FOURCC('L', 'A', 'T', ' '), + KBTS_LANGUAGE_LATVIAN = KBTS_FOURCC('L', 'V', 'I', ' '), + KBTS_LANGUAGE_LAZ = KBTS_FOURCC('L', 'A', 'Z', ' '), + KBTS_LANGUAGE_LELEMI = KBTS_FOURCC('L', 'E', 'F', ' '), + KBTS_LANGUAGE_LEZGI = KBTS_FOURCC('L', 'E', 'Z', ' '), + KBTS_LANGUAGE_LIGURIAN = KBTS_FOURCC('L', 'I', 'J', ' '), + KBTS_LANGUAGE_LIMBU = KBTS_FOURCC('L', 'M', 'B', ' '), + KBTS_LANGUAGE_LIMBURGISH = KBTS_FOURCC('L', 'I', 'M', ' '), + KBTS_LANGUAGE_LINGALA = KBTS_FOURCC('L', 'I', 'N', ' '), + KBTS_LANGUAGE_LIPO = KBTS_FOURCC('L', 'P', 'O', ' '), + KBTS_LANGUAGE_LISU = KBTS_FOURCC('L', 'I', 'S', ' '), + KBTS_LANGUAGE_LITHUANIAN = KBTS_FOURCC('L', 'T', 'H', ' '), + KBTS_LANGUAGE_LIV = KBTS_FOURCC('L', 'I', 'V', ' '), + KBTS_LANGUAGE_LOJBAN = KBTS_FOURCC('J', 'B', 'O', ' '), + KBTS_LANGUAGE_LOMA = KBTS_FOURCC('L', 'O', 'M', ' '), + KBTS_LANGUAGE_LOMBARD = KBTS_FOURCC('L', 'M', 'O', ' '), + KBTS_LANGUAGE_LOMWE = KBTS_FOURCC('L', 'M', 'W', ' '), + KBTS_LANGUAGE_LOW_MARI = KBTS_FOURCC('L', 'M', 'A', ' '), + KBTS_LANGUAGE_LOW_SAXON = KBTS_FOURCC('N', 'D', 'S', ' '), + KBTS_LANGUAGE_LOWER_SORBIAN = KBTS_FOURCC('L', 'S', 'B', ' '), + KBTS_LANGUAGE_LU = KBTS_FOURCC('X', 'B', 'D', ' '), + KBTS_LANGUAGE_LUBA_KATANGA = KBTS_FOURCC('L', 'U', 'B', ' '), + KBTS_LANGUAGE_LUBA_LULUA = KBTS_FOURCC('L', 'U', 'A', ' '), + KBTS_LANGUAGE_LULE_SAMI = KBTS_FOURCC('L', 'S', 'M', ' '), + KBTS_LANGUAGE_LUO = KBTS_FOURCC('L', 'U', 'O', ' '), + KBTS_LANGUAGE_LURI = KBTS_FOURCC('L', 'R', 'C', ' '), + KBTS_LANGUAGE_LUSHOOTSEED = KBTS_FOURCC('L', 'U', 'T', ' '), + KBTS_LANGUAGE_LUXEMBOURGISH = KBTS_FOURCC('L', 'T', 'Z', ' '), + KBTS_LANGUAGE_LUYIA = KBTS_FOURCC('L', 'U', 'H', ' '), + KBTS_LANGUAGE_MACEDONIAN = KBTS_FOURCC('M', 'K', 'D', ' '), + KBTS_LANGUAGE_MADURA = KBTS_FOURCC('M', 'A', 'D', ' '), + KBTS_LANGUAGE_MAGAHI = KBTS_FOURCC('M', 'A', 'G', ' '), + KBTS_LANGUAGE_MAITHILI = KBTS_FOURCC('M', 'T', 'H', ' '), + KBTS_LANGUAGE_MAJANG = KBTS_FOURCC('M', 'A', 'J', ' '), + KBTS_LANGUAGE_MAKASAR = KBTS_FOURCC('M', 'K', 'R', ' '), + KBTS_LANGUAGE_MAKHUWA = KBTS_FOURCC('M', 'A', 'K', ' '), + KBTS_LANGUAGE_MAKONDE = KBTS_FOURCC('K', 'D', 'E', ' '), + KBTS_LANGUAGE_MALAGASY = KBTS_FOURCC('M', 'L', 'G', ' '), + KBTS_LANGUAGE_MALAY = KBTS_FOURCC('M', 'L', 'Y', ' '), + KBTS_LANGUAGE_MALAYALAM = KBTS_FOURCC('M', 'A', 'L', ' '), + KBTS_LANGUAGE_MALAYALAM_REFORMED = KBTS_FOURCC('M', 'L', 'R', ' '), + KBTS_LANGUAGE_MALE = KBTS_FOURCC('M', 'L', 'E', ' '), + KBTS_LANGUAGE_MALINKE = KBTS_FOURCC('M', 'L', 'N', ' '), + KBTS_LANGUAGE_MALTESE = KBTS_FOURCC('M', 'T', 'S', ' '), + KBTS_LANGUAGE_MAM = KBTS_FOURCC('M', 'A', 'M', ' '), + KBTS_LANGUAGE_MANCHU = KBTS_FOURCC('M', 'C', 'H', ' '), + KBTS_LANGUAGE_MANDAR = KBTS_FOURCC('M', 'D', 'R', ' '), + KBTS_LANGUAGE_MANDINKA = KBTS_FOURCC('M', 'N', 'D', ' '), + KBTS_LANGUAGE_MANINKA = KBTS_FOURCC('M', 'N', 'K', ' '), + KBTS_LANGUAGE_MANIPURI = KBTS_FOURCC('M', 'N', 'I', ' '), + KBTS_LANGUAGE_MANO = KBTS_FOURCC('M', 'E', 'V', ' '), + KBTS_LANGUAGE_MANSI = KBTS_FOURCC('M', 'A', 'N', ' '), + KBTS_LANGUAGE_MANX = KBTS_FOURCC('M', 'N', 'X', ' '), + KBTS_LANGUAGE_MAORI = KBTS_FOURCC('M', 'R', 'I', ' '), + KBTS_LANGUAGE_MAPUDUNGUN = KBTS_FOURCC('M', 'A', 'P', ' '), + KBTS_LANGUAGE_MARATHI = KBTS_FOURCC('M', 'A', 'R', ' '), + KBTS_LANGUAGE_MARSHALLESE = KBTS_FOURCC('M', 'A', 'H', ' '), + KBTS_LANGUAGE_MARWARI = KBTS_FOURCC('M', 'A', 'W', ' '), + KBTS_LANGUAGE_MAYAN = KBTS_FOURCC('M', 'Y', 'N', ' '), + KBTS_LANGUAGE_MAZANDERANI = KBTS_FOURCC('M', 'Z', 'N', ' '), + KBTS_LANGUAGE_MBEMBE_TIGON = KBTS_FOURCC('N', 'Z', 'A', ' '), + KBTS_LANGUAGE_MBO = KBTS_FOURCC('M', 'B', 'O', ' '), + KBTS_LANGUAGE_MBUNDU = KBTS_FOURCC('M', 'B', 'N', ' '), + KBTS_LANGUAGE_MEDUMBA = KBTS_FOURCC('B', 'Y', 'V', ' '), + KBTS_LANGUAGE_MEEN = KBTS_FOURCC('M', 'E', 'N', ' '), + KBTS_LANGUAGE_MENDE = KBTS_FOURCC('M', 'D', 'E', ' '), + KBTS_LANGUAGE_MERU = KBTS_FOURCC('M', 'E', 'R', ' '), + KBTS_LANGUAGE_MEWATI = KBTS_FOURCC('W', 'T', 'M', ' '), + KBTS_LANGUAGE_MINANGKABAU = KBTS_FOURCC('M', 'I', 'N', ' '), + KBTS_LANGUAGE_MINJANGBAL = KBTS_FOURCC('X', 'J', 'B', ' '), + KBTS_LANGUAGE_MIRANDESE = KBTS_FOURCC('M', 'W', 'L', ' '), + KBTS_LANGUAGE_MIZO = KBTS_FOURCC('M', 'I', 'Z', ' '), + KBTS_LANGUAGE_MOHAWK = KBTS_FOURCC('M', 'O', 'H', ' '), + KBTS_LANGUAGE_MOKSHA = KBTS_FOURCC('M', 'O', 'K', ' '), + KBTS_LANGUAGE_MOLDAVIAN = KBTS_FOURCC('M', 'O', 'L', ' '), + KBTS_LANGUAGE_MON = KBTS_FOURCC('M', 'O', 'N', ' '), + KBTS_LANGUAGE_MONGOLIAN = KBTS_FOURCC('M', 'N', 'G', ' '), + KBTS_LANGUAGE_MOOSE_CREE = KBTS_FOURCC('M', 'C', 'R', ' '), + KBTS_LANGUAGE_MORISYEN = KBTS_FOURCC('M', 'F', 'E', ' '), + KBTS_LANGUAGE_MOROCCAN = KBTS_FOURCC('M', 'O', 'R', ' '), + KBTS_LANGUAGE_MOSSI = KBTS_FOURCC('M', 'P', 'S', ' '), + KBTS_LANGUAGE_MUNDARI = KBTS_FOURCC('M', 'U', 'N', ' '), + KBTS_LANGUAGE_MUSCOGEE = KBTS_FOURCC('M', 'U', 'S', ' '), + KBTS_LANGUAGE_N_CREE = KBTS_FOURCC('N', 'C', 'R', ' '), + KBTS_LANGUAGE_NAGA_ASSAMESE = KBTS_FOURCC('N', 'A', 'G', ' '), + KBTS_LANGUAGE_NAGARI = KBTS_FOURCC('N', 'G', 'R', ' '), + KBTS_LANGUAGE_NAHUATL = KBTS_FOURCC('N', 'A', 'H', ' '), + KBTS_LANGUAGE_NANAI = KBTS_FOURCC('N', 'A', 'N', ' '), + KBTS_LANGUAGE_NASKAPI = KBTS_FOURCC('N', 'A', 'S', ' '), + KBTS_LANGUAGE_NAURUAN = KBTS_FOURCC('N', 'A', 'U', ' '), + KBTS_LANGUAGE_NAVAJO = KBTS_FOURCC('N', 'A', 'V', ' '), + KBTS_LANGUAGE_NDAU = KBTS_FOURCC('N', 'D', 'C', ' '), + KBTS_LANGUAGE_NDEBELE = KBTS_FOURCC('N', 'D', 'B', ' '), + KBTS_LANGUAGE_NDONGA = KBTS_FOURCC('N', 'D', 'G', ' '), + KBTS_LANGUAGE_NEAPOLITAN = KBTS_FOURCC('N', 'A', 'P', ' '), + KBTS_LANGUAGE_NEPALI = KBTS_FOURCC('N', 'E', 'P', ' '), + KBTS_LANGUAGE_NEWARI = KBTS_FOURCC('N', 'E', 'W', ' '), + KBTS_LANGUAGE_NGBAKA = KBTS_FOURCC('N', 'G', 'A', ' '), + KBTS_LANGUAGE_NIGERIAN_FULFULDE = KBTS_FOURCC('F', 'U', 'V', ' '), + KBTS_LANGUAGE_NIMADI = KBTS_FOURCC('N', 'O', 'E', ' '), + KBTS_LANGUAGE_NISI = KBTS_FOURCC('N', 'I', 'S', ' '), + KBTS_LANGUAGE_NIUEAN = KBTS_FOURCC('N', 'I', 'U', ' '), + KBTS_LANGUAGE_NKO = KBTS_FOURCC('N', 'K', 'O', ' '), + KBTS_LANGUAGE_NOGAI = KBTS_FOURCC('N', 'O', 'G', ' '), + KBTS_LANGUAGE_NORFOLK = KBTS_FOURCC('P', 'I', 'H', ' '), + KBTS_LANGUAGE_NORTH_SLAVEY = KBTS_FOURCC('S', 'C', 'S', ' '), + KBTS_LANGUAGE_NORTHERN_EMBERA = KBTS_FOURCC('E', 'M', 'P', ' '), + KBTS_LANGUAGE_NORTHERN_SAMI = KBTS_FOURCC('N', 'S', 'M', ' '), + KBTS_LANGUAGE_NORTHERN_SOTHO = KBTS_FOURCC('N', 'S', 'O', ' '), + KBTS_LANGUAGE_NORTHERN_TAI = KBTS_FOURCC('N', 'T', 'A', ' '), + KBTS_LANGUAGE_NORWAY_HOUSE_CREE = KBTS_FOURCC('N', 'H', 'C', ' '), + KBTS_LANGUAGE_NORWEGIAN = KBTS_FOURCC('N', 'O', 'R', ' '), + KBTS_LANGUAGE_NORWEGIAN_NYNORSK = KBTS_FOURCC('N', 'Y', 'N', ' '), + KBTS_LANGUAGE_NOVIAL = KBTS_FOURCC('N', 'O', 'V', ' '), + KBTS_LANGUAGE_NUMANGGANG = KBTS_FOURCC('N', 'O', 'P', ' '), + KBTS_LANGUAGE_NUNAVIK_INUKTITUT = KBTS_FOURCC('I', 'N', 'U', ' '), + KBTS_LANGUAGE_NUU_CHAH_NULTH = KBTS_FOURCC('N', 'U', 'K', ' '), + KBTS_LANGUAGE_NYAMWEZI = KBTS_FOURCC('N', 'Y', 'M', ' '), + KBTS_LANGUAGE_NYANKOLE = KBTS_FOURCC('N', 'K', 'L', ' '), + KBTS_LANGUAGE_OCCITAN = KBTS_FOURCC('O', 'C', 'I', ' '), + KBTS_LANGUAGE_ODIA = KBTS_FOURCC('O', 'R', 'I', ' '), + KBTS_LANGUAGE_OJI_CREE = KBTS_FOURCC('O', 'C', 'R', ' '), + KBTS_LANGUAGE_OJIBWAY = KBTS_FOURCC('O', 'J', 'B', ' '), + KBTS_LANGUAGE_OLD_IRISH = KBTS_FOURCC('S', 'G', 'A', ' '), + KBTS_LANGUAGE_OLD_JAVANESE = KBTS_FOURCC('K', 'A', 'W', ' '), + KBTS_LANGUAGE_ONEIDA = KBTS_FOURCC('O', 'N', 'E', ' '), + KBTS_LANGUAGE_ONONDAGA = KBTS_FOURCC('O', 'N', 'O', ' '), + KBTS_LANGUAGE_OROMO = KBTS_FOURCC('O', 'R', 'O', ' '), + KBTS_LANGUAGE_OSSETIAN = KBTS_FOURCC('O', 'S', 'S', ' '), + KBTS_LANGUAGE_PA_O_KAREN = KBTS_FOURCC('B', 'L', 'K', ' '), + KBTS_LANGUAGE_PALAUAN = KBTS_FOURCC('P', 'A', 'U', ' '), + KBTS_LANGUAGE_PALAUNG = KBTS_FOURCC('P', 'L', 'G', ' '), + KBTS_LANGUAGE_PALESTINIAN_ARAMAIC = KBTS_FOURCC('P', 'A', 'A', ' '), + KBTS_LANGUAGE_PALI = KBTS_FOURCC('P', 'A', 'L', ' '), + KBTS_LANGUAGE_PALPA = KBTS_FOURCC('P', 'A', 'P', ' '), + KBTS_LANGUAGE_PAMPANGAN = KBTS_FOURCC('P', 'A', 'M', ' '), + KBTS_LANGUAGE_PANGASINAN = KBTS_FOURCC('P', 'A', 'G', ' '), + KBTS_LANGUAGE_PAPIAMENTU = KBTS_FOURCC('P', 'A', 'P', '0'), + KBTS_LANGUAGE_PASHTO = KBTS_FOURCC('P', 'A', 'S', ' '), + KBTS_LANGUAGE_PATTANI_MALAY = KBTS_FOURCC('M', 'F', 'A', ' '), + KBTS_LANGUAGE_PENNSYLVANIA_GERMAN = KBTS_FOURCC('P', 'D', 'C', ' '), + KBTS_LANGUAGE_PERSIAN = KBTS_FOURCC('F', 'A', 'R', ' '), + KBTS_LANGUAGE_PHAKE = KBTS_FOURCC('P', 'J', 'K', ' '), + KBTS_LANGUAGE_PICARD = KBTS_FOURCC('P', 'C', 'D', ' '), + KBTS_LANGUAGE_PIEMONTESE = KBTS_FOURCC('P', 'M', 'S', ' '), + KBTS_LANGUAGE_PILAGA = KBTS_FOURCC('P', 'L', 'G', ' '), + KBTS_LANGUAGE_PITE_SAMI = KBTS_FOURCC('S', 'J', 'E', ' '), + KBTS_LANGUAGE_POCOMCHI = KBTS_FOURCC('P', 'O', 'H', ' '), + KBTS_LANGUAGE_POHNPEIAN = KBTS_FOURCC('P', 'O', 'N', ' '), + KBTS_LANGUAGE_POLISH = KBTS_FOURCC('P', 'L', 'K', ' '), + KBTS_LANGUAGE_POLYTONIC_GREEK = KBTS_FOURCC('P', 'G', 'R', ' '), + KBTS_LANGUAGE_PORTUGUESE = KBTS_FOURCC('P', 'T', 'G', ' '), + KBTS_LANGUAGE_PROVENCAL = KBTS_FOURCC('P', 'R', 'O', ' '), + KBTS_LANGUAGE_PUNJABI = KBTS_FOURCC('P', 'A', 'N', ' '), + KBTS_LANGUAGE_QUECHUA = KBTS_FOURCC('Q', 'U', 'Z', ' '), + KBTS_LANGUAGE_QUECHUA_BOLIVIA = KBTS_FOURCC('Q', 'U', 'H', ' '), + KBTS_LANGUAGE_QUECHUA_ECUADOR = KBTS_FOURCC('Q', 'V', 'I', ' '), + KBTS_LANGUAGE_QUECHUA_PERU = KBTS_FOURCC('Q', 'W', 'H', ' '), + KBTS_LANGUAGE_R_CREE = KBTS_FOURCC('R', 'C', 'R', ' '), + KBTS_LANGUAGE_RAJASTHANI = KBTS_FOURCC('R', 'A', 'J', ' '), + KBTS_LANGUAGE_RAKHINE = KBTS_FOURCC('A', 'R', 'K', ' '), + KBTS_LANGUAGE_RAROTONGAN = KBTS_FOURCC('R', 'A', 'R', ' '), + KBTS_LANGUAGE_REJANG = KBTS_FOURCC('R', 'E', 'J', ' '), + KBTS_LANGUAGE_RIANG = KBTS_FOURCC('R', 'I', 'A', ' '), + KBTS_LANGUAGE_RIPUARIAN = KBTS_FOURCC('K', 'S', 'H', ' '), + KBTS_LANGUAGE_RITARUNGO = KBTS_FOURCC('R', 'I', 'T', ' '), + KBTS_LANGUAGE_ROHINGYA = KBTS_FOURCC('R', 'H', 'G', ' '), + KBTS_LANGUAGE_ROMANIAN = KBTS_FOURCC('R', 'O', 'M', ' '), + KBTS_LANGUAGE_ROMANSH = KBTS_FOURCC('R', 'M', 'S', ' '), + KBTS_LANGUAGE_ROMANY = KBTS_FOURCC('R', 'O', 'Y', ' '), + KBTS_LANGUAGE_ROTUMAN = KBTS_FOURCC('R', 'T', 'M', ' '), + KBTS_LANGUAGE_RUNDI = KBTS_FOURCC('R', 'U', 'N', ' '), + KBTS_LANGUAGE_RUSSIAN = KBTS_FOURCC('R', 'U', 'S', ' '), + KBTS_LANGUAGE_RUSSIAN_BURIAT = KBTS_FOURCC('R', 'B', 'U', ' '), + KBTS_LANGUAGE_RUSYN = KBTS_FOURCC('R', 'S', 'Y', ' '), + KBTS_LANGUAGE_SADRI = KBTS_FOURCC('S', 'A', 'D', ' '), + KBTS_LANGUAGE_SAKHA = KBTS_FOURCC('Y', 'A', 'K', ' '), + KBTS_LANGUAGE_SAMOAN = KBTS_FOURCC('S', 'M', 'O', ' '), + KBTS_LANGUAGE_SAMOGITIAN = KBTS_FOURCC('S', 'G', 'S', ' '), + KBTS_LANGUAGE_SAN_BLAS_KUNA = KBTS_FOURCC('C', 'U', 'K', ' '), + KBTS_LANGUAGE_SANGO = KBTS_FOURCC('S', 'G', 'O', ' '), + KBTS_LANGUAGE_SANSKRIT = KBTS_FOURCC('S', 'A', 'N', ' '), + KBTS_LANGUAGE_SANTALI = KBTS_FOURCC('S', 'A', 'T', ' '), + KBTS_LANGUAGE_SARAIKI = KBTS_FOURCC('S', 'R', 'K', ' '), + KBTS_LANGUAGE_SARDINIAN = KBTS_FOURCC('S', 'R', 'D', ' '), + KBTS_LANGUAGE_SASAK = KBTS_FOURCC('S', 'A', 'S', ' '), + KBTS_LANGUAGE_SATERLAND_FRISIAN = KBTS_FOURCC('S', 'T', 'Q', ' '), + KBTS_LANGUAGE_SAYISI = KBTS_FOURCC('S', 'A', 'Y', ' '), + KBTS_LANGUAGE_SCOTS = KBTS_FOURCC('S', 'C', 'I', ' '), + KBTS_LANGUAGE_SCOTTISH_GAELIC = KBTS_FOURCC('G', 'A', 'E', ' '), + KBTS_LANGUAGE_SEKOTA = KBTS_FOURCC('S', 'E', 'J', ' '), + KBTS_LANGUAGE_SELKUP = KBTS_FOURCC('S', 'E', 'L', ' '), + KBTS_LANGUAGE_SENA = KBTS_FOURCC('S', 'N', 'A', ' '), + KBTS_LANGUAGE_SENECA = KBTS_FOURCC('S', 'E', 'E', ' '), + KBTS_LANGUAGE_SERBIAN = KBTS_FOURCC('S', 'R', 'B', ' '), + KBTS_LANGUAGE_SERER = KBTS_FOURCC('S', 'R', 'R', ' '), + KBTS_LANGUAGE_SGAW_KAREN = KBTS_FOURCC('K', 'S', 'W', ' '), + KBTS_LANGUAGE_SHAN = KBTS_FOURCC('S', 'H', 'N', ' '), + KBTS_LANGUAGE_SHONA = KBTS_FOURCC('S', 'N', 'A', ' '), + KBTS_LANGUAGE_SIBE = KBTS_FOURCC('S', 'I', 'B', ' '), + KBTS_LANGUAGE_SICILIAN = KBTS_FOURCC('S', 'C', 'N', ' '), + KBTS_LANGUAGE_SIDAMO = KBTS_FOURCC('S', 'I', 'D', ' '), + KBTS_LANGUAGE_SILESIAN = KBTS_FOURCC('S', 'Z', 'L', ' '), + KBTS_LANGUAGE_SILTE_GURAGE = KBTS_FOURCC('S', 'I', 'G', ' '), + KBTS_LANGUAGE_SINDHI = KBTS_FOURCC('S', 'N', 'D', ' '), + KBTS_LANGUAGE_SINHALA = KBTS_FOURCC('S', 'N', 'H', ' '), + KBTS_LANGUAGE_SKOLT_SAMI = KBTS_FOURCC('S', 'K', 'S', ' '), + KBTS_LANGUAGE_SLAVEY = KBTS_FOURCC('S', 'L', 'A', ' '), + KBTS_LANGUAGE_SLOVAK = KBTS_FOURCC('S', 'K', 'Y', ' '), + KBTS_LANGUAGE_SLOVENIAN = KBTS_FOURCC('S', 'L', 'V', ' '), + KBTS_LANGUAGE_SMALL_FLOWERY_MIAO = KBTS_FOURCC('S', 'F', 'M', ' '), + KBTS_LANGUAGE_SODO_GURAGE = KBTS_FOURCC('S', 'O', 'G', ' '), + KBTS_LANGUAGE_SOGA = KBTS_FOURCC('X', 'O', 'G', ' '), + KBTS_LANGUAGE_SOMALI = KBTS_FOURCC('S', 'M', 'L', ' '), + KBTS_LANGUAGE_SONGE = KBTS_FOURCC('S', 'O', 'P', ' '), + KBTS_LANGUAGE_SONINKE = KBTS_FOURCC('S', 'N', 'K', ' '), + KBTS_LANGUAGE_SOUTH_SLAVEY = KBTS_FOURCC('S', 'S', 'L', ' '), + KBTS_LANGUAGE_SOUTHERN_KIWAI = KBTS_FOURCC('K', 'J', 'D', ' '), + KBTS_LANGUAGE_SOUTHERN_SAMI = KBTS_FOURCC('S', 'S', 'M', ' '), + KBTS_LANGUAGE_SOUTHERN_SOTHO = KBTS_FOURCC('S', 'O', 'T', ' '), + KBTS_LANGUAGE_SPANISH = KBTS_FOURCC('E', 'S', 'P', ' '), + KBTS_LANGUAGE_STANDARD_MOROCCAN_TAMAZIGHT = KBTS_FOURCC('Z', 'G', 'H', ' '), + KBTS_LANGUAGE_STRAITS_SALISH = KBTS_FOURCC('S', 'T', 'R', ' '), + KBTS_LANGUAGE_SUKUMA = KBTS_FOURCC('S', 'U', 'K', ' '), + KBTS_LANGUAGE_SUNDANESE = KBTS_FOURCC('S', 'U', 'N', ' '), + KBTS_LANGUAGE_SURI = KBTS_FOURCC('S', 'U', 'R', ' '), + KBTS_LANGUAGE_SUTU = KBTS_FOURCC('S', 'X', 'T', ' '), + KBTS_LANGUAGE_SVAN = KBTS_FOURCC('S', 'V', 'A', ' '), + KBTS_LANGUAGE_SWADAYA_ARAMAIC = KBTS_FOURCC('S', 'W', 'A', ' '), + KBTS_LANGUAGE_SWAHILI = KBTS_FOURCC('S', 'W', 'K', ' '), + KBTS_LANGUAGE_SWATI = KBTS_FOURCC('S', 'W', 'Z', ' '), + KBTS_LANGUAGE_SWEDISH = KBTS_FOURCC('S', 'V', 'E', ' '), + KBTS_LANGUAGE_SYLHETI = KBTS_FOURCC('S', 'Y', 'L', ' '), + KBTS_LANGUAGE_SYRIAC = KBTS_FOURCC('S', 'Y', 'R', ' '), + KBTS_LANGUAGE_SYRIAC_EASTERN = KBTS_FOURCC('S', 'Y', 'R', 'N'), + KBTS_LANGUAGE_SYRIAC_ESTRANGELA = KBTS_FOURCC('S', 'Y', 'R', 'E'), + KBTS_LANGUAGE_SYRIAC_WESTERN = KBTS_FOURCC('S', 'Y', 'R', 'J'), + KBTS_LANGUAGE_TABASARAN = KBTS_FOURCC('T', 'A', 'B', ' '), + KBTS_LANGUAGE_TACHELHIT = KBTS_FOURCC('S', 'H', 'I', ' '), + KBTS_LANGUAGE_TAGALOG = KBTS_FOURCC('T', 'G', 'L', ' '), + KBTS_LANGUAGE_TAHAGGART_TAMAHAQ = KBTS_FOURCC('T', 'H', 'V', ' '), + KBTS_LANGUAGE_TAHITIAN = KBTS_FOURCC('T', 'H', 'T', ' '), + KBTS_LANGUAGE_TAI_LAING = KBTS_FOURCC('T', 'J', 'L', ' '), + KBTS_LANGUAGE_TAJIKI = KBTS_FOURCC('T', 'A', 'J', ' '), + KBTS_LANGUAGE_TALYSH = KBTS_FOURCC('T', 'L', 'Y', ' '), + KBTS_LANGUAGE_TAMASHEK = KBTS_FOURCC('T', 'M', 'H', ' '), + KBTS_LANGUAGE_TAMASHEQ = KBTS_FOURCC('T', 'A', 'Q', ' '), + KBTS_LANGUAGE_TAMAZIGHT = KBTS_FOURCC('T', 'Z', 'M', ' '), + KBTS_LANGUAGE_TAMIL = KBTS_FOURCC('T', 'A', 'M', ' '), + KBTS_LANGUAGE_TARIFIT = KBTS_FOURCC('R', 'I', 'F', ' '), + KBTS_LANGUAGE_TATAR = KBTS_FOURCC('T', 'A', 'T', ' '), + KBTS_LANGUAGE_TAWALLAMMAT_TAMAJAQ = KBTS_FOURCC('T', 'T', 'Q', ' '), + KBTS_LANGUAGE_TAY = KBTS_FOURCC('T', 'Y', 'Z', ' '), + KBTS_LANGUAGE_TAYART_TAMAJEQ = KBTS_FOURCC('T', 'H', 'Z', ' '), + KBTS_LANGUAGE_TELUGU = KBTS_FOURCC('T', 'E', 'L', ' '), + KBTS_LANGUAGE_TEMNE = KBTS_FOURCC('T', 'M', 'N', ' '), + KBTS_LANGUAGE_TETUM = KBTS_FOURCC('T', 'E', 'T', ' '), + KBTS_LANGUAGE_TH_CREE = KBTS_FOURCC('T', 'C', 'R', ' '), + KBTS_LANGUAGE_THAI = KBTS_FOURCC('T', 'H', 'A', ' '), + KBTS_LANGUAGE_THAILAND_MON = KBTS_FOURCC('M', 'O', 'N', 'T'), + KBTS_LANGUAGE_THOMPSON = KBTS_FOURCC('T', 'H', 'P', ' '), + KBTS_LANGUAGE_TIBETAN = KBTS_FOURCC('T', 'I', 'B', ' '), + KBTS_LANGUAGE_TIGRE = KBTS_FOURCC('T', 'G', 'R', ' '), + KBTS_LANGUAGE_TIGRINYA = KBTS_FOURCC('T', 'G', 'Y', ' '), + KBTS_LANGUAGE_TIV = KBTS_FOURCC('T', 'I', 'V', ' '), + KBTS_LANGUAGE_TLINGIT = KBTS_FOURCC('T', 'L', 'I', ' '), + KBTS_LANGUAGE_TOBO = KBTS_FOURCC('T', 'B', 'V', ' '), + KBTS_LANGUAGE_TODO = KBTS_FOURCC('T', 'O', 'D', ' '), + KBTS_LANGUAGE_TOK_PISIN = KBTS_FOURCC('T', 'P', 'I', ' '), + KBTS_LANGUAGE_TOMA = KBTS_FOURCC('T', 'O', 'D', '0'), + KBTS_LANGUAGE_TONGA = KBTS_FOURCC('T', 'N', 'G', ' '), + KBTS_LANGUAGE_TONGAN = KBTS_FOURCC('T', 'G', 'N', ' '), + KBTS_LANGUAGE_TORKI = KBTS_FOURCC('A', 'Z', 'B', ' '), + KBTS_LANGUAGE_TSHANGLA = KBTS_FOURCC('T', 'S', 'J', ' '), + KBTS_LANGUAGE_TSONGA = KBTS_FOURCC('T', 'S', 'G', ' '), + KBTS_LANGUAGE_TSWANA = KBTS_FOURCC('T', 'N', 'A', ' '), + KBTS_LANGUAGE_TULU = KBTS_FOURCC('T', 'U', 'L', ' '), + KBTS_LANGUAGE_TUMBUKA = KBTS_FOURCC('T', 'U', 'M', ' '), + KBTS_LANGUAGE_TUNDRA_ENETS = KBTS_FOURCC('T', 'N', 'E', ' '), + KBTS_LANGUAGE_TURKISH = KBTS_FOURCC('T', 'R', 'K', ' '), + KBTS_LANGUAGE_TURKMEN = KBTS_FOURCC('T', 'K', 'M', ' '), + KBTS_LANGUAGE_TUROYO_ARAMAIC = KBTS_FOURCC('T', 'U', 'A', ' '), + KBTS_LANGUAGE_TUSCARORA = KBTS_FOURCC('T', 'U', 'S', ' '), + KBTS_LANGUAGE_TUVALU = KBTS_FOURCC('T', 'V', 'L', ' '), + KBTS_LANGUAGE_TUVIN = KBTS_FOURCC('T', 'U', 'V', ' '), + KBTS_LANGUAGE_TWI = KBTS_FOURCC('T', 'W', 'I', ' '), + KBTS_LANGUAGE_TZOTZIL = KBTS_FOURCC('T', 'Z', 'O', ' '), + KBTS_LANGUAGE_UDI = KBTS_FOURCC('U', 'D', 'I', ' '), + KBTS_LANGUAGE_UDMURT = KBTS_FOURCC('U', 'D', 'M', ' '), + KBTS_LANGUAGE_UKRAINIAN = KBTS_FOURCC('U', 'K', 'R', ' '), + KBTS_LANGUAGE_UMBUNDU = KBTS_FOURCC('U', 'M', 'B', ' '), + KBTS_LANGUAGE_UME_SAMI = KBTS_FOURCC('S', 'J', 'U', ' '), + KBTS_LANGUAGE_UPPER_SAXON = KBTS_FOURCC('S', 'X', 'U', ' '), + KBTS_LANGUAGE_UPPER_SORBIAN = KBTS_FOURCC('U', 'S', 'B', ' '), + KBTS_LANGUAGE_URALIC_PHONETIC = KBTS_FOURCC('U', 'P', 'P', ' '), + KBTS_LANGUAGE_URDU = KBTS_FOURCC('U', 'R', 'D', ' '), + KBTS_LANGUAGE_UYGHUR = KBTS_FOURCC('U', 'Y', 'G', ' '), + KBTS_LANGUAGE_UZBEK = KBTS_FOURCC('U', 'Z', 'B', ' '), + KBTS_LANGUAGE_VENDA = KBTS_FOURCC('V', 'E', 'N', ' '), + KBTS_LANGUAGE_VENETIAN = KBTS_FOURCC('V', 'E', 'C', ' '), + KBTS_LANGUAGE_VIETNAMESE = KBTS_FOURCC('V', 'I', 'T', ' '), + KBTS_LANGUAGE_VLAX_ROMANI = KBTS_FOURCC('R', 'M', 'Y', ' '), + KBTS_LANGUAGE_VOLAPUK = KBTS_FOURCC('V', 'O', 'L', ' '), + KBTS_LANGUAGE_VORO = KBTS_FOURCC('V', 'R', 'O', ' '), + KBTS_LANGUAGE_WA = KBTS_FOURCC('W', 'A', ' ', ' '), + KBTS_LANGUAGE_WACI_GBE = KBTS_FOURCC('W', 'C', 'I', ' '), + KBTS_LANGUAGE_WAGDI = KBTS_FOURCC('W', 'A', 'G', ' '), + KBTS_LANGUAGE_WAKHI = KBTS_FOURCC('W', 'B', 'L', ' '), + KBTS_LANGUAGE_WALLOON = KBTS_FOURCC('W', 'L', 'N', ' '), + KBTS_LANGUAGE_WARAY_WARAY = KBTS_FOURCC('W', 'A', 'R', ' '), + KBTS_LANGUAGE_WAYANAD_CHETTI = KBTS_FOURCC('C', 'T', 'T', ' '), + KBTS_LANGUAGE_WAYUU = KBTS_FOURCC('G', 'U', 'C', ' '), + KBTS_LANGUAGE_WELSH = KBTS_FOURCC('W', 'E', 'L', ' '), + KBTS_LANGUAGE_WENDAT = KBTS_FOURCC('W', 'D', 'T', ' '), + KBTS_LANGUAGE_WEST_CREE = KBTS_FOURCC('W', 'C', 'R', ' '), + KBTS_LANGUAGE_WESTERN_CHAM = KBTS_FOURCC('C', 'J', 'A', ' '), + KBTS_LANGUAGE_WESTERN_KAYAH = KBTS_FOURCC('K', 'Y', 'U', ' '), + KBTS_LANGUAGE_WESTERN_PANJABI = KBTS_FOURCC('P', 'N', 'B', ' '), + KBTS_LANGUAGE_WESTERN_PWO_KAREN = KBTS_FOURCC('P', 'W', 'O', ' '), + KBTS_LANGUAGE_WOLOF = KBTS_FOURCC('W', 'L', 'F', ' '), + KBTS_LANGUAGE_WOODS_CREE = KBTS_FOURCC('D', 'C', 'R', ' '), + KBTS_LANGUAGE_WUDING_LUQUAN_YI = KBTS_FOURCC('Y', 'W', 'Q', ' '), + KBTS_LANGUAGE_WYANDOT = KBTS_FOURCC('W', 'Y', 'N', ' '), + KBTS_LANGUAGE_XHOSA = KBTS_FOURCC('X', 'H', 'S', ' '), + KBTS_LANGUAGE_Y_CREE = KBTS_FOURCC('Y', 'C', 'R', ' '), + KBTS_LANGUAGE_YAO = KBTS_FOURCC('Y', 'A', 'O', ' '), + KBTS_LANGUAGE_YAPESE = KBTS_FOURCC('Y', 'A', 'P', ' '), + KBTS_LANGUAGE_YI_CLASSIC = KBTS_FOURCC('Y', 'I', 'C', ' '), + KBTS_LANGUAGE_YI_MODERN = KBTS_FOURCC('Y', 'I', 'M', ' '), + KBTS_LANGUAGE_YIDDISH = KBTS_FOURCC('J', 'I', 'I', ' '), + KBTS_LANGUAGE_YORUBA = KBTS_FOURCC('Y', 'B', 'A', ' '), + KBTS_LANGUAGE_ZAMBOANGA_CHAVACANO = KBTS_FOURCC('C', 'B', 'K', ' '), + KBTS_LANGUAGE_ZANDE = KBTS_FOURCC('Z', 'N', 'D', ' '), + KBTS_LANGUAGE_ZARMA = KBTS_FOURCC('D', 'J', 'R', ' '), + KBTS_LANGUAGE_ZAZAKI = KBTS_FOURCC('Z', 'Z', 'A', ' '), + KBTS_LANGUAGE_ZEALANDIC = KBTS_FOURCC('Z', 'E', 'A', ' '), + KBTS_LANGUAGE_ZHUANG = KBTS_FOURCC('Z', 'H', 'A', ' '), + KBTS_LANGUAGE_ZULU = KBTS_FOURCC('Z', 'U', 'L', ' '), +}; + +typedef kbts_u32 kbts_break_flags; +enum kbts_break_flags_enum +{ + // Direction changes from left-to-right to right-to-left, or vice versa. + KBTS_BREAK_FLAG_DIRECTION = 1 << 0, + // Script changes. + // Note that some characters, such as digits, are used in multiple + // scripts and, as such, will not produce script breaks. + KBTS_BREAK_FLAG_SCRIPT = 1 << 1, + // Graphemes are "visual units". They may be composed of more than one codepoint. + // They are used as interaction boundaries in graphical interfaces, e.g. moving the + // caret. + KBTS_BREAK_FLAG_GRAPHEME = 1 << 2, + // In most scripts, words are broken up by whitespace, but Unicode word breaking has + // better script coverage and also handles some special cases that a simple stateless + // loop cannot handle. + KBTS_BREAK_FLAG_WORD = 1 << 3, + // By default, you are not allowed to break a line. + // Soft line breaks allow for line breaking, but do not require it. + // This is useful for when you are doing line wrapping. + KBTS_BREAK_FLAG_LINE_SOFT = 1 << 4, + // Hard line breaks are required. They signal the end of a paragraph. + // (In Unicode, there is no meaningful distinction between a line and a paragraph. + // a paragraph is pretty much just a line of text that can wrap.) + KBTS_BREAK_FLAG_LINE_HARD = 1 << 5, + // Used for manual segmentation in the context. + KBTS_BREAK_FLAG_MANUAL = 1 << 6, + + KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION = 1 << 7, + + KBTS_BREAK_FLAG_LINE = KBTS_BREAK_FLAG_LINE_SOFT | KBTS_BREAK_FLAG_LINE_HARD, + KBTS_BREAK_FLAG_ANY = KBTS_BREAK_FLAG_DIRECTION | KBTS_BREAK_FLAG_SCRIPT | KBTS_BREAK_FLAG_GRAPHEME | KBTS_BREAK_FLAG_WORD | KBTS_BREAK_FLAG_LINE_SOFT | KBTS_BREAK_FLAG_LINE_HARD, +}; + +// Japanese text contains "kinsoku" characters, around which breaking a line is forbidden. +// Exactly which characters are "kinsoku" or not depends on the context: +// - Strict style has the largest amount of kinsoku characters, which leads to longer lines. +// - Loose style has the smallest amount of kinsoku characters, which leads to smaller lines. +// - Normal style is somewhere in the middle. +// Note that, while the Unicode standard mentions all three of these styles, it does not mention +// any differences between the normal and loose styles. +// As such, normal and loose styles currently behave the same. +typedef kbts_u8 kbts_japanese_line_break_style; +enum kbts_japanese_line_break_style_enum +{ + // The Unicode standard does not define what strict style is used for. + // Supposedly, it is used for anything that does not fall into the other two categories of text. + KBTS_JAPANESE_LINE_BREAK_STYLE_STRICT, + + // Normal style is used for books and documents. + KBTS_JAPANESE_LINE_BREAK_STYLE_NORMAL, + + // Loose style is used for newspapers, and (I assume) any other narrow column format. + KBTS_JAPANESE_LINE_BREAK_STYLE_LOOSE, + + KBTS_JAPANESE_LINE_BREAK_STYLE_COUNT, +}; + +typedef kbts_u32 kbts_break_state_flags; +enum kbts_break_state_flags_enum +{ + KBTS_BREAK_STATE_FLAG_STARTED = 1, + KBTS_BREAK_STATE_FLAG_END = 2, + + // Bidirectional flags + KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L = 8, + KBTS_BREAK_STATE_FLAG_SAW_AL_AFTER_LR = 0x10, + KBTS_BREAK_STATE_FLAG_LAST_WAS_BRACKET = 0x20, +}; + +typedef kbts_u32 kbts_text_format; +enum kbts_text_format_enum +{ + KBTS_TEXT_FORMAT_NONE, + + KBTS_TEXT_FORMAT_UTF32, + KBTS_TEXT_FORMAT_UTF8, + + KBTS_TEXT_FORMAT_COUNT, +}; + +typedef kbts_u32 kbts_direction; +enum kbts_direction_enum +{ + KBTS_DIRECTION_DONT_KNOW, + KBTS_DIRECTION_LTR, + KBTS_DIRECTION_RTL, + + KBTS_DIRECTION_COUNT, +}; + +typedef kbts_u32 kbts_orientation; +enum kbts_orientation_enum +{ + KBTS_ORIENTATION_HORIZONTAL, + KBTS_ORIENTATION_VERTICAL, + + KBTS_ORIENTATION_COUNT, +}; + +typedef kbts_u8 kbts_shaping_table; +enum kbts_shaping_table_enum +{ + KBTS_SHAPING_TABLE_GSUB, + KBTS_SHAPING_TABLE_GPOS, + KBTS_SHAPING_TABLE_COUNT, +}; + +typedef kbts_u32 kbts_shape_error; +enum kbts_shape_error_enum +{ + KBTS_SHAPE_ERROR_NONE, + KBTS_SHAPE_ERROR_INVALID_FONT, + KBTS_SHAPE_ERROR_GAVE_TEXT_BEFORE_CALLING_BEGIN, + KBTS_SHAPE_ERROR_OUT_OF_MEMORY, + + KBTS_SHAPE_ERROR_COUNT, +}; + +typedef kbts_u32 kbts_allocator_op_kind; +enum kbts_allocator_op_kind_enum +{ + KBTS_ALLOCATOR_OP_KIND_NONE, + KBTS_ALLOCATOR_OP_KIND_ALLOCATE, + KBTS_ALLOCATOR_OP_KIND_FREE, + + KBTS_ALLOCATOR_OP_KIND_COUNT, +}; + +typedef kbts_u32 kbts_blob_table_id; +enum kbts_blob_table_id_enum +{ + KBTS_BLOB_TABLE_ID_NONE, + KBTS_BLOB_TABLE_ID_HEAD, + KBTS_BLOB_TABLE_ID_CMAP, + KBTS_BLOB_TABLE_ID_GDEF, + KBTS_BLOB_TABLE_ID_GSUB, + KBTS_BLOB_TABLE_ID_GPOS, + KBTS_BLOB_TABLE_ID_HHEA, + KBTS_BLOB_TABLE_ID_VHEA, + KBTS_BLOB_TABLE_ID_HMTX, + KBTS_BLOB_TABLE_ID_VMTX, + KBTS_BLOB_TABLE_ID_MAXP, + KBTS_BLOB_TABLE_ID_OS2, + KBTS_BLOB_TABLE_ID_NAME, + + KBTS_BLOB_TABLE_ID_COUNT, +}; + +typedef kbts_u32 kbts_load_font_error; +enum kbts_load_font_error_enum +{ + KBTS_LOAD_FONT_ERROR_NONE, + KBTS_LOAD_FONT_ERROR_NEED_TO_CREATE_BLOB, + KBTS_LOAD_FONT_ERROR_INVALID_FONT, + KBTS_LOAD_FONT_ERROR_OUT_OF_MEMORY, + KBTS_LOAD_FONT_ERROR_COULD_NOT_OPEN_FILE, + KBTS_LOAD_FONT_ERROR_READ_ERROR, + + KBTS_LOAD_FONT_ERROR_COUNT, +}; + +typedef kbts_u32 kbts_version; +enum kbts_version_enum +{ + KBTS_VERSION_1_X, + KBTS_VERSION_2_0, + + KBTS_VERSION_CURRENT = KBTS_VERSION_2_0, +}; + +typedef kbts_u32 kbts_blob_version; +enum kbts_blob_version_enum +{ + KBTS_BLOB_VERSION_INVALID, + KBTS_BLOB_VERSION_INITIAL, + + KBTS_BLOB_VERSION_CURRENT = KBTS_BLOB_VERSION_INITIAL, +}; + +typedef kbts_u32 kbts_font_style_flags; +enum kbts_font_style_flags_enum +{ + KBTS_FONT_STYLE_FLAG_NONE, + + KBTS_FONT_STYLE_FLAG_REGULAR = (1 << 0), + KBTS_FONT_STYLE_FLAG_ITALIC = (1 << 1), + KBTS_FONT_STYLE_FLAG_BOLD = (1 << 2), +}; + +typedef kbts_u32 kbts_font_weight; +enum kbts_font_weight_enum +{ + KBTS_FONT_WEIGHT_UNKNOWN, + + KBTS_FONT_WEIGHT_THIN, + KBTS_FONT_WEIGHT_EXTRA_LIGHT, + KBTS_FONT_WEIGHT_LIGHT, + KBTS_FONT_WEIGHT_NORMAL, + KBTS_FONT_WEIGHT_MEDIUM, + KBTS_FONT_WEIGHT_SEMI_BOLD, + KBTS_FONT_WEIGHT_BOLD, + KBTS_FONT_WEIGHT_EXTRA_BOLD, + KBTS_FONT_WEIGHT_BLACK, + + KBTS_FONT_WEIGHT_COUNT, +}; + +typedef kbts_u32 kbts_font_width; +enum kbts_font_width_enum +{ + KBTS_FONT_WIDTH_UNKNOWN, + + KBTS_FONT_WIDTH_ULTRA_CONDENSED, + KBTS_FONT_WIDTH_EXTRA_CONDENSED, + KBTS_FONT_WIDTH_CONDENSED, + KBTS_FONT_WIDTH_SEMI_CONDENSED, + KBTS_FONT_WIDTH_NORMAL, + KBTS_FONT_WIDTH_SEMI_EXPANDED, + KBTS_FONT_WIDTH_EXPANDED, + KBTS_FONT_WIDTH_EXTRA_EXPANDED, + KBTS_FONT_WIDTH_ULTRA_EXPANDED, + + KBTS_FONT_WIDTH_COUNT, +}; + +typedef kbts_u32 kbts_glyph_flags; +enum kbts_glyph_flags_enum +{ + // These feature flags must coincide with kbts_joining_feature _and_ KBTS_FEATURE_FLAG! + KBTS_GLYPH_FLAG_ISOL = (1 << 0), + KBTS_GLYPH_FLAG_FINA = (1 << 1), + KBTS_GLYPH_FLAG_FIN2 = (1 << 2), + KBTS_GLYPH_FLAG_FIN3 = (1 << 3), + KBTS_GLYPH_FLAG_MEDI = (1 << 4), + KBTS_GLYPH_FLAG_MED2 = (1 << 5), + KBTS_GLYPH_FLAG_INIT = (1 << 6), + + // These feature flags must coincide with FEATURE_FLAG! + KBTS_GLYPH_FLAG_LJMO = (1 << 7), + KBTS_GLYPH_FLAG_VJMO = (1 << 8), + KBTS_GLYPH_FLAG_TJMO = (1 << 9), + KBTS_GLYPH_FLAG_RPHF = (1 << 10), + KBTS_GLYPH_FLAG_BLWF = (1 << 11), + KBTS_GLYPH_FLAG_HALF = (1 << 12), + KBTS_GLYPH_FLAG_PSTF = (1 << 13), + KBTS_GLYPH_FLAG_ABVF = (1 << 14), + KBTS_GLYPH_FLAG_PREF = (1 << 15), + KBTS_GLYPH_FLAG_NUMR = (1 << 16), + KBTS_GLYPH_FLAG_FRAC = (1 << 17), + KBTS_GLYPH_FLAG_DNOM = (1 << 18), + KBTS_GLYPH_FLAG_CFAR = (1 << 19), + + // These can be anything. + KBTS_GLYPH_FLAG_DO_NOT_DECOMPOSE = (1 << 21), + KBTS_GLYPH_FLAG_FIRST_IN_MULTIPLE_SUBSTITUTION = (1 << 22), + KBTS_GLYPH_FLAG_NO_BREAK = (1 << 23), + KBTS_GLYPH_FLAG_CURSIVE = (1 << 24), + KBTS_GLYPH_FLAG_GENERATED_BY_GSUB = (1 << 25), + KBTS_GLYPH_FLAG_USED_IN_GPOS = (1 << 26), + + KBTS_GLYPH_FLAG_STCH_ENDPOINT = (1 << 27), + KBTS_GLYPH_FLAG_STCH_EXTENSION = (1 << 28), + + KBTS_GLYPH_FLAG_LIGATURE = (1 << 29), + KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION = (1 << 30), +}; + +typedef kbts_u8 kbts_joining_feature; +enum kbts_joining_feature_enum +{ + KBTS_JOINING_FEATURE_NONE, + + // These must correspond with glyph_flags and FEATURE_IDs. + KBTS_JOINING_FEATURE_ISOL, + KBTS_JOINING_FEATURE_FINA, + KBTS_JOINING_FEATURE_FIN2, + KBTS_JOINING_FEATURE_FIN3, + KBTS_JOINING_FEATURE_MEDI, + KBTS_JOINING_FEATURE_MED2, + KBTS_JOINING_FEATURE_INIT, + + KBTS_JOINING_FEATURE_COUNT, +}; + +typedef kbts_u32 kbts_user_id_generation_mode; +enum kbts_user_id_generation_mode_enum +{ + KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX, + KBTS_USER_ID_GENERATION_MODE_SOURCE_INDEX, + + KBTS_USER_ID_GENERATION_MODE_COUNT, +}; + +typedef kbts_u32 kbts_break_config_flags; +enum kbts_break_config_flags_enum +{ + KBTS_BREAK_CONFIG_FLAG_NONE, + + KBTS_BREAK_CONFIG_FLAG_END_OF_TEXT_GENERATES_HARD_LINE_BREAK = 1, +}; + +typedef kbts_u32 kbts_font_info_string_id; +enum kbts_font_info_string_id_enum +{ + KBTS_FONT_INFO_STRING_ID_NONE, + KBTS_FONT_INFO_STRING_ID_COPYRIGHT, + KBTS_FONT_INFO_STRING_ID_FAMILY, + KBTS_FONT_INFO_STRING_ID_SUBFAMILY, + KBTS_FONT_INFO_STRING_ID_UID, + KBTS_FONT_INFO_STRING_ID_FULL_NAME, + KBTS_FONT_INFO_STRING_ID_VERSION, + KBTS_FONT_INFO_STRING_ID_POSTSCRIPT_NAME, + KBTS_FONT_INFO_STRING_ID_TRADEMARK, + KBTS_FONT_INFO_STRING_ID_MANUFACTURER, + KBTS_FONT_INFO_STRING_ID_DESIGNER, + KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_FAMILY, + KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_SUBFAMILY, + + KBTS_FONT_INFO_STRING_ID_COUNT, +}; + + +typedef kbts_u8 kbts_unicode_joining_type; +enum kbts_unicode_joining_type_enum +{ + KBTS_UNICODE_JOINING_TYPE_NONE, + KBTS_UNICODE_JOINING_TYPE_LEFT, + KBTS_UNICODE_JOINING_TYPE_DUAL, + KBTS_UNICODE_JOINING_TYPE_FORCE, + KBTS_UNICODE_JOINING_TYPE_RIGHT, + KBTS_UNICODE_JOINING_TYPE_TRANSPARENT, + KBTS_UNICODE_JOINING_TYPE_COUNT, +}; + +typedef kbts_u8 kbts_unicode_flags; +enum kbts_unicode_flag_enum +{ + KBTS_UNICODE_FLAG_MODIFIER_COMBINING_MARK = (1 << 0), + KBTS_UNICODE_FLAG_DEFAULT_IGNORABLE = (1 << 1), + KBTS_UNICODE_FLAG_OPEN_BRACKET = (1 << 2), + KBTS_UNICODE_FLAG_CLOSE_BRACKET = (1 << 3), + KBTS_UNICODE_FLAG_PART_OF_WORD = (1 << 4), + KBTS_UNICODE_FLAG_DECIMAL_DIGIT = (1 << 5), + KBTS_UNICODE_FLAG_NON_SPACING_MARK = (1 << 6), + + KBTS_UNICODE_FLAG_MIRRORED = KBTS_UNICODE_FLAG_OPEN_BRACKET | KBTS_UNICODE_FLAG_CLOSE_BRACKET, +}; + +typedef kbts_u8 kbts_unicode_bidirectional_class; +enum kbts_unicode_bidirectional_class_enum +{ + KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_BN, // Formatting characters need to be ignored. + KBTS_UNICODE_BIDIRECTIONAL_CLASS_L, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_R, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_NSM, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_AL, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_ES, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_ET, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_CS, + KBTS_UNICODE_BIDIRECTIONAL_CLASS_COUNT, +}; + +typedef kbts_u8 kbts_line_break_class; +enum kbts_line_break_class_enum +{ + /* 0 */ KBTS_LINE_BREAK_CLASS_Onea, + /* 1 */ KBTS_LINE_BREAK_CLASS_Oea, + /* 2 */ KBTS_LINE_BREAK_CLASS_Ope, + /* 3 */ KBTS_LINE_BREAK_CLASS_BK, + /* 4 */ KBTS_LINE_BREAK_CLASS_CR, + /* 5 */ KBTS_LINE_BREAK_CLASS_LF, + /* 6 */ KBTS_LINE_BREAK_CLASS_NL, + /* 7 */ KBTS_LINE_BREAK_CLASS_SP, + /* 8 */ KBTS_LINE_BREAK_CLASS_ZW, + /* 9 */ KBTS_LINE_BREAK_CLASS_WJ, + /* 10 */ KBTS_LINE_BREAK_CLASS_GLnea, + /* 11 */ KBTS_LINE_BREAK_CLASS_GLea, + /* 12 */ KBTS_LINE_BREAK_CLASS_CLnea, + /* 13 */ KBTS_LINE_BREAK_CLASS_CLea, + /* 14 */ KBTS_LINE_BREAK_CLASS_CPnea, + /* 15 */ KBTS_LINE_BREAK_CLASS_CPea, + /* 16 */ KBTS_LINE_BREAK_CLASS_EXnea, + /* 17 */ KBTS_LINE_BREAK_CLASS_EXea, + /* 18 */ KBTS_LINE_BREAK_CLASS_SY, + /* 19 */ KBTS_LINE_BREAK_CLASS_BAnea, + /* 20 */ KBTS_LINE_BREAK_CLASS_BAea, + /* 21 */ KBTS_LINE_BREAK_CLASS_OPnea, + /* 22 */ KBTS_LINE_BREAK_CLASS_OPea, + /* 23 */ KBTS_LINE_BREAK_CLASS_QU, + /* 24 */ KBTS_LINE_BREAK_CLASS_QUPi, + /* 25 */ KBTS_LINE_BREAK_CLASS_QUPf, + /* 26 */ KBTS_LINE_BREAK_CLASS_IS, + /* 27 */ KBTS_LINE_BREAK_CLASS_NSnea, + /* 28 */ KBTS_LINE_BREAK_CLASS_NSea, + /* 29 */ KBTS_LINE_BREAK_CLASS_B2, + /* 30 */ KBTS_LINE_BREAK_CLASS_CB, + /* 31 */ KBTS_LINE_BREAK_CLASS_HY, + /* 32 */ KBTS_LINE_BREAK_CLASS_HYPHEN, + /* 33 */ KBTS_LINE_BREAK_CLASS_INnea, + /* 34 */ KBTS_LINE_BREAK_CLASS_INea, + /* 35 */ KBTS_LINE_BREAK_CLASS_BB, + /* 36 */ KBTS_LINE_BREAK_CLASS_HL, + /* 37 */ KBTS_LINE_BREAK_CLASS_ALnea, + /* 38 */ KBTS_LINE_BREAK_CLASS_ALea, + /* 39 */ KBTS_LINE_BREAK_CLASS_NU, + /* 40 */ KBTS_LINE_BREAK_CLASS_PRnea, + /* 41 */ KBTS_LINE_BREAK_CLASS_PRea, + /* 42 */ KBTS_LINE_BREAK_CLASS_IDnea, + /* 43 */ KBTS_LINE_BREAK_CLASS_IDea, + /* 44 */ KBTS_LINE_BREAK_CLASS_IDpe, + /* 45 */ KBTS_LINE_BREAK_CLASS_EBnea, + /* 46 */ KBTS_LINE_BREAK_CLASS_EBea, + /* 47 */ KBTS_LINE_BREAK_CLASS_EM, + /* 48 */ KBTS_LINE_BREAK_CLASS_POnea, + /* 49 */ KBTS_LINE_BREAK_CLASS_POea, + /* 50 */ KBTS_LINE_BREAK_CLASS_JL, + /* 51 */ KBTS_LINE_BREAK_CLASS_JV, + /* 52 */ KBTS_LINE_BREAK_CLASS_JT, + /* 53 */ KBTS_LINE_BREAK_CLASS_H2, + /* 54 */ KBTS_LINE_BREAK_CLASS_H3, + /* 55 */ KBTS_LINE_BREAK_CLASS_AP, + /* 56 */ KBTS_LINE_BREAK_CLASS_AK, + /* 57 */ KBTS_LINE_BREAK_CLASS_DOTTED_CIRCLE, + /* 58 */ KBTS_LINE_BREAK_CLASS_AS, + /* 59 */ KBTS_LINE_BREAK_CLASS_VF, + /* 60 */ KBTS_LINE_BREAK_CLASS_VI, + /* 61 */ KBTS_LINE_BREAK_CLASS_RI, + + /* 62 */ KBTS_LINE_BREAK_CLASS_COUNT, + + /* 63 */ KBTS_LINE_BREAK_CLASS_CM, + /* 64 */ KBTS_LINE_BREAK_CLASS_ZWJ, + + // CJ resolves to either NS or ID depending on the (Japanese) line break style. + // NS is strict line breaking, used for long lines. + // ID is normal line breaking, used for normal body text. + /* 65 */ KBTS_LINE_BREAK_CLASS_CJ, + + /* 66 */ KBTS_LINE_BREAK_CLASS_SOT, + /* 67 */ KBTS_LINE_BREAK_CLASS_EOT, +}; + +// @Cleanup: Merge EX and FO. +typedef kbts_u8 kbts_word_break_class; +enum kbts_word_break_class_enum +{ + KBTS_WORD_BREAK_CLASS_Onep, + KBTS_WORD_BREAK_CLASS_Oep, + KBTS_WORD_BREAK_CLASS_CR, + KBTS_WORD_BREAK_CLASS_LF, + KBTS_WORD_BREAK_CLASS_NL, + KBTS_WORD_BREAK_CLASS_EX, + KBTS_WORD_BREAK_CLASS_ZWJ, + KBTS_WORD_BREAK_CLASS_RI, + KBTS_WORD_BREAK_CLASS_FO, + KBTS_WORD_BREAK_CLASS_KA, + KBTS_WORD_BREAK_CLASS_HL, + KBTS_WORD_BREAK_CLASS_ALnep, + KBTS_WORD_BREAK_CLASS_ALep, + KBTS_WORD_BREAK_CLASS_SQ, + KBTS_WORD_BREAK_CLASS_DQ, + KBTS_WORD_BREAK_CLASS_MNL, + KBTS_WORD_BREAK_CLASS_ML, + KBTS_WORD_BREAK_CLASS_MN, + KBTS_WORD_BREAK_CLASS_NM, + KBTS_WORD_BREAK_CLASS_ENL, + KBTS_WORD_BREAK_CLASS_WSS, + + KBTS_WORD_BREAK_CLASS_SOT, +}; + +// Unicode defines scripts and languages. +// A language belongs to a single script, and a script belongs to a single writing system. +// On top of these, OpenType defines shapers, which are basically just designations for +// specific code paths that are taken depending on which script is being shapen. +// +// Some scripts, like Latin and Cyrillic, need relatively few operations, while complex +// scripts like Arabic and Indic scripts have specific processing steps that need to happen +// in order to obtain a correct result. +// +// These sequences of operations are _not_ described in the font file itself. The shaping +// code needs to know which script it is shaping, and implement all of those passes itself. +// That is why you, as a user, have to care about this. +// +// When creating shape_config, you can either pass in a known script, or you can specify +// SCRIPT_DONT_KNOW and let the library figure it out. +// While SCRIPT_DONT_KNOW may look appealing, it is worth noting that we can only infer +// the _script_, and not the language, of the text you pass in. +// This means that you might miss out on language-specific features when you use it. +typedef kbts_u32 kbts_shaper; +enum kbts_shaper_enum +{ + KBTS_SHAPER_DEFAULT, + KBTS_SHAPER_ARABIC, + KBTS_SHAPER_HANGUL, + KBTS_SHAPER_HEBREW, + KBTS_SHAPER_INDIC, + KBTS_SHAPER_KHMER, + KBTS_SHAPER_MYANMAR, + KBTS_SHAPER_TIBETAN, + KBTS_SHAPER_USE, + + KBTS_SHAPER_COUNT, +}; +#define KBTS_MAXIMUM_RECOMPOSITION_PARENTS 19 +#define KBTS_MAXIMUM_CODEPOINT_SCRIPTS 23 +typedef kbts_u32 kbts_script_tag; +enum kbts_script_tag_enum +{ + KBTS_SCRIPT_TAG_DONT_KNOW = KBTS_FOURCC(' ', ' ', ' ', ' '), + KBTS_SCRIPT_TAG_ADLAM = KBTS_FOURCC('a', 'd', 'l', 'm'), + KBTS_SCRIPT_TAG_AHOM = KBTS_FOURCC('a', 'h', 'o', 'm'), + KBTS_SCRIPT_TAG_ANATOLIAN_HIEROGLYPHS = KBTS_FOURCC('h', 'l', 'u', 'w'), + KBTS_SCRIPT_TAG_ARABIC = KBTS_FOURCC('a', 'r', 'a', 'b'), + KBTS_SCRIPT_TAG_ARMENIAN = KBTS_FOURCC('a', 'r', 'm', 'n'), + KBTS_SCRIPT_TAG_AVESTAN = KBTS_FOURCC('a', 'v', 's', 't'), + KBTS_SCRIPT_TAG_BALINESE = KBTS_FOURCC('b', 'a', 'l', 'i'), + KBTS_SCRIPT_TAG_BAMUM = KBTS_FOURCC('b', 'a', 'm', 'u'), + KBTS_SCRIPT_TAG_BASSA_VAH = KBTS_FOURCC('b', 'a', 's', 's'), + KBTS_SCRIPT_TAG_BATAK = KBTS_FOURCC('b', 'a', 't', 'k'), + KBTS_SCRIPT_TAG_BENGALI = KBTS_FOURCC('b', 'n', 'g', '2'), + KBTS_SCRIPT_TAG_BHAIKSUKI = KBTS_FOURCC('b', 'h', 'k', 's'), + KBTS_SCRIPT_TAG_BOPOMOFO = KBTS_FOURCC('b', 'o', 'p', 'o'), + KBTS_SCRIPT_TAG_BRAHMI = KBTS_FOURCC('b', 'r', 'a', 'h'), + KBTS_SCRIPT_TAG_BUGINESE = KBTS_FOURCC('b', 'u', 'g', 'i'), + KBTS_SCRIPT_TAG_BUHID = KBTS_FOURCC('b', 'u', 'h', 'd'), + KBTS_SCRIPT_TAG_CANADIAN_SYLLABICS = KBTS_FOURCC('c', 'a', 'n', 's'), + KBTS_SCRIPT_TAG_CARIAN = KBTS_FOURCC('c', 'a', 'r', 'i'), + KBTS_SCRIPT_TAG_CAUCASIAN_ALBANIAN = KBTS_FOURCC('a', 'g', 'h', 'b'), + KBTS_SCRIPT_TAG_CHAKMA = KBTS_FOURCC('c', 'a', 'k', 'm'), + KBTS_SCRIPT_TAG_CHAM = KBTS_FOURCC('c', 'h', 'a', 'm'), + KBTS_SCRIPT_TAG_CHEROKEE = KBTS_FOURCC('c', 'h', 'e', 'r'), + KBTS_SCRIPT_TAG_CHORASMIAN = KBTS_FOURCC('c', 'h', 'r', 's'), + KBTS_SCRIPT_TAG_CJK_IDEOGRAPHIC = KBTS_FOURCC('h', 'a', 'n', 'i'), + KBTS_SCRIPT_TAG_COPTIC = KBTS_FOURCC('c', 'o', 'p', 't'), + KBTS_SCRIPT_TAG_CYPRIOT_SYLLABARY = KBTS_FOURCC('c', 'p', 'r', 't'), + KBTS_SCRIPT_TAG_CYPRO_MINOAN = KBTS_FOURCC('c', 'p', 'm', 'n'), + KBTS_SCRIPT_TAG_CYRILLIC = KBTS_FOURCC('c', 'y', 'r', 'l'), + KBTS_SCRIPT_TAG_DEFAULT = KBTS_FOURCC('D', 'F', 'L', 'T'), + KBTS_SCRIPT_TAG_DEFAULT2 = KBTS_FOURCC('D', 'F', 'L', 'T'), + KBTS_SCRIPT_TAG_DESERET = KBTS_FOURCC('d', 's', 'r', 't'), + KBTS_SCRIPT_TAG_DEVANAGARI = KBTS_FOURCC('d', 'e', 'v', '2'), + KBTS_SCRIPT_TAG_DIVES_AKURU = KBTS_FOURCC('d', 'i', 'a', 'k'), + KBTS_SCRIPT_TAG_DOGRA = KBTS_FOURCC('d', 'o', 'g', 'r'), + KBTS_SCRIPT_TAG_DUPLOYAN = KBTS_FOURCC('d', 'u', 'p', 'l'), + KBTS_SCRIPT_TAG_EGYPTIAN_HIEROGLYPHS = KBTS_FOURCC('e', 'g', 'y', 'p'), + KBTS_SCRIPT_TAG_ELBASAN = KBTS_FOURCC('e', 'l', 'b', 'a'), + KBTS_SCRIPT_TAG_ELYMAIC = KBTS_FOURCC('e', 'l', 'y', 'm'), + KBTS_SCRIPT_TAG_ETHIOPIC = KBTS_FOURCC('e', 't', 'h', 'i'), + KBTS_SCRIPT_TAG_GARAY = KBTS_FOURCC('g', 'a', 'r', 'a'), + KBTS_SCRIPT_TAG_GEORGIAN = KBTS_FOURCC('g', 'e', 'o', 'r'), + KBTS_SCRIPT_TAG_GLAGOLITIC = KBTS_FOURCC('g', 'l', 'a', 'g'), + KBTS_SCRIPT_TAG_GOTHIC = KBTS_FOURCC('g', 'o', 't', 'h'), + KBTS_SCRIPT_TAG_GRANTHA = KBTS_FOURCC('g', 'r', 'a', 'n'), + KBTS_SCRIPT_TAG_GREEK = KBTS_FOURCC('g', 'r', 'e', 'k'), + KBTS_SCRIPT_TAG_GUJARATI = KBTS_FOURCC('g', 'j', 'r', '2'), + KBTS_SCRIPT_TAG_GUNJALA_GONDI = KBTS_FOURCC('g', 'o', 'n', 'g'), + KBTS_SCRIPT_TAG_GURMUKHI = KBTS_FOURCC('g', 'u', 'r', '2'), + KBTS_SCRIPT_TAG_GURUNG_KHEMA = KBTS_FOURCC('g', 'u', 'k', 'h'), + KBTS_SCRIPT_TAG_HANGUL = KBTS_FOURCC('h', 'a', 'n', 'g'), + KBTS_SCRIPT_TAG_HANIFI_ROHINGYA = KBTS_FOURCC('r', 'o', 'h', 'g'), + KBTS_SCRIPT_TAG_HANUNOO = KBTS_FOURCC('h', 'a', 'n', 'o'), + KBTS_SCRIPT_TAG_HATRAN = KBTS_FOURCC('h', 'a', 't', 'r'), + KBTS_SCRIPT_TAG_HEBREW = KBTS_FOURCC('h', 'e', 'b', 'r'), + KBTS_SCRIPT_TAG_HIRAGANA = KBTS_FOURCC('k', 'a', 'n', 'a'), + KBTS_SCRIPT_TAG_IMPERIAL_ARAMAIC = KBTS_FOURCC('a', 'r', 'm', 'i'), + KBTS_SCRIPT_TAG_INSCRIPTIONAL_PAHLAVI = KBTS_FOURCC('p', 'h', 'l', 'i'), + KBTS_SCRIPT_TAG_INSCRIPTIONAL_PARTHIAN = KBTS_FOURCC('p', 'r', 't', 'i'), + KBTS_SCRIPT_TAG_JAVANESE = KBTS_FOURCC('j', 'a', 'v', 'a'), + KBTS_SCRIPT_TAG_KAITHI = KBTS_FOURCC('k', 't', 'h', 'i'), + KBTS_SCRIPT_TAG_KANNADA = KBTS_FOURCC('k', 'n', 'd', '2'), + KBTS_SCRIPT_TAG_KATAKANA = KBTS_FOURCC('k', 'a', 'n', 'a'), + KBTS_SCRIPT_TAG_KAWI = KBTS_FOURCC('k', 'a', 'w', 'i'), + KBTS_SCRIPT_TAG_KAYAH_LI = KBTS_FOURCC('k', 'a', 'l', 'i'), + KBTS_SCRIPT_TAG_KHAROSHTHI = KBTS_FOURCC('k', 'h', 'a', 'r'), + KBTS_SCRIPT_TAG_KHITAN_SMALL_SCRIPT = KBTS_FOURCC('k', 'i', 't', 's'), + KBTS_SCRIPT_TAG_KHMER = KBTS_FOURCC('k', 'h', 'm', 'r'), + KBTS_SCRIPT_TAG_KHOJKI = KBTS_FOURCC('k', 'h', 'o', 'j'), + KBTS_SCRIPT_TAG_KHUDAWADI = KBTS_FOURCC('s', 'i', 'n', 'd'), + KBTS_SCRIPT_TAG_KIRAT_RAI = KBTS_FOURCC('k', 'r', 'a', 'i'), + KBTS_SCRIPT_TAG_LAO = KBTS_FOURCC('l', 'a', 'o', ' '), + KBTS_SCRIPT_TAG_LATIN = KBTS_FOURCC('l', 'a', 't', 'n'), + KBTS_SCRIPT_TAG_LEPCHA = KBTS_FOURCC('l', 'e', 'p', 'c'), + KBTS_SCRIPT_TAG_LIMBU = KBTS_FOURCC('l', 'i', 'm', 'b'), + KBTS_SCRIPT_TAG_LINEAR_A = KBTS_FOURCC('l', 'i', 'n', 'a'), + KBTS_SCRIPT_TAG_LINEAR_B = KBTS_FOURCC('l', 'i', 'n', 'b'), + KBTS_SCRIPT_TAG_LISU = KBTS_FOURCC('l', 'i', 's', 'u'), + KBTS_SCRIPT_TAG_LYCIAN = KBTS_FOURCC('l', 'y', 'c', 'i'), + KBTS_SCRIPT_TAG_LYDIAN = KBTS_FOURCC('l', 'y', 'd', 'i'), + KBTS_SCRIPT_TAG_MAHAJANI = KBTS_FOURCC('m', 'a', 'h', 'j'), + KBTS_SCRIPT_TAG_MAKASAR = KBTS_FOURCC('m', 'a', 'k', 'a'), + KBTS_SCRIPT_TAG_MALAYALAM = KBTS_FOURCC('m', 'l', 'm', '2'), + KBTS_SCRIPT_TAG_MANDAIC = KBTS_FOURCC('m', 'a', 'n', 'd'), + KBTS_SCRIPT_TAG_MANICHAEAN = KBTS_FOURCC('m', 'a', 'n', 'i'), + KBTS_SCRIPT_TAG_MARCHEN = KBTS_FOURCC('m', 'a', 'r', 'c'), + KBTS_SCRIPT_TAG_MASARAM_GONDI = KBTS_FOURCC('g', 'o', 'n', 'm'), + KBTS_SCRIPT_TAG_MEDEFAIDRIN = KBTS_FOURCC('m', 'e', 'd', 'f'), + KBTS_SCRIPT_TAG_MEETEI_MAYEK = KBTS_FOURCC('m', 't', 'e', 'i'), + KBTS_SCRIPT_TAG_MENDE_KIKAKUI = KBTS_FOURCC('m', 'e', 'n', 'd'), + KBTS_SCRIPT_TAG_MEROITIC_CURSIVE = KBTS_FOURCC('m', 'e', 'r', 'c'), + KBTS_SCRIPT_TAG_MEROITIC_HIEROGLYPHS = KBTS_FOURCC('m', 'e', 'r', 'o'), + KBTS_SCRIPT_TAG_MIAO = KBTS_FOURCC('p', 'l', 'r', 'd'), + KBTS_SCRIPT_TAG_MODI = KBTS_FOURCC('m', 'o', 'd', 'i'), + KBTS_SCRIPT_TAG_MONGOLIAN = KBTS_FOURCC('m', 'o', 'n', 'g'), + KBTS_SCRIPT_TAG_MRO = KBTS_FOURCC('m', 'r', 'o', 'o'), + KBTS_SCRIPT_TAG_MULTANI = KBTS_FOURCC('m', 'u', 'l', 't'), + KBTS_SCRIPT_TAG_MYANMAR = KBTS_FOURCC('m', 'y', 'm', '2'), + KBTS_SCRIPT_TAG_NABATAEAN = KBTS_FOURCC('n', 'b', 'a', 't'), + KBTS_SCRIPT_TAG_NAG_MUNDARI = KBTS_FOURCC('n', 'a', 'g', 'm'), + KBTS_SCRIPT_TAG_NANDINAGARI = KBTS_FOURCC('n', 'a', 'n', 'd'), + KBTS_SCRIPT_TAG_NEWA = KBTS_FOURCC('n', 'e', 'w', 'a'), + KBTS_SCRIPT_TAG_NEW_TAI_LUE = KBTS_FOURCC('t', 'a', 'l', 'u'), + KBTS_SCRIPT_TAG_NKO = KBTS_FOURCC('n', 'k', 'o', ' '), + KBTS_SCRIPT_TAG_NUSHU = KBTS_FOURCC('n', 's', 'h', 'u'), + KBTS_SCRIPT_TAG_NYIAKENG_PUACHUE_HMONG = KBTS_FOURCC('h', 'm', 'n', 'p'), + KBTS_SCRIPT_TAG_OGHAM = KBTS_FOURCC('o', 'g', 'a', 'm'), + KBTS_SCRIPT_TAG_OL_CHIKI = KBTS_FOURCC('o', 'l', 'c', 'k'), + KBTS_SCRIPT_TAG_OL_ONAL = KBTS_FOURCC('o', 'n', 'a', 'o'), + KBTS_SCRIPT_TAG_OLD_ITALIC = KBTS_FOURCC('i', 't', 'a', 'l'), + KBTS_SCRIPT_TAG_OLD_HUNGARIAN = KBTS_FOURCC('h', 'u', 'n', 'g'), + KBTS_SCRIPT_TAG_OLD_NORTH_ARABIAN = KBTS_FOURCC('n', 'a', 'r', 'b'), + KBTS_SCRIPT_TAG_OLD_PERMIC = KBTS_FOURCC('p', 'e', 'r', 'm'), + KBTS_SCRIPT_TAG_OLD_PERSIAN_CUNEIFORM = KBTS_FOURCC('x', 'p', 'e', 'o'), + KBTS_SCRIPT_TAG_OLD_SOGDIAN = KBTS_FOURCC('s', 'o', 'g', 'o'), + KBTS_SCRIPT_TAG_OLD_SOUTH_ARABIAN = KBTS_FOURCC('s', 'a', 'r', 'b'), + KBTS_SCRIPT_TAG_OLD_TURKIC = KBTS_FOURCC('o', 'r', 'k', 'h'), + KBTS_SCRIPT_TAG_OLD_UYGHUR = KBTS_FOURCC('o', 'u', 'g', 'r'), + KBTS_SCRIPT_TAG_ODIA = KBTS_FOURCC('o', 'r', 'y', '2'), + KBTS_SCRIPT_TAG_OSAGE = KBTS_FOURCC('o', 's', 'g', 'e'), + KBTS_SCRIPT_TAG_OSMANYA = KBTS_FOURCC('o', 's', 'm', 'a'), + KBTS_SCRIPT_TAG_PAHAWH_HMONG = KBTS_FOURCC('h', 'm', 'n', 'g'), + KBTS_SCRIPT_TAG_PALMYRENE = KBTS_FOURCC('p', 'a', 'l', 'm'), + KBTS_SCRIPT_TAG_PAU_CIN_HAU = KBTS_FOURCC('p', 'a', 'u', 'c'), + KBTS_SCRIPT_TAG_PHAGS_PA = KBTS_FOURCC('p', 'h', 'a', 'g'), + KBTS_SCRIPT_TAG_PHOENICIAN = KBTS_FOURCC('p', 'h', 'n', 'x'), + KBTS_SCRIPT_TAG_PSALTER_PAHLAVI = KBTS_FOURCC('p', 'h', 'l', 'p'), + KBTS_SCRIPT_TAG_REJANG = KBTS_FOURCC('r', 'j', 'n', 'g'), + KBTS_SCRIPT_TAG_RUNIC = KBTS_FOURCC('r', 'u', 'n', 'r'), + KBTS_SCRIPT_TAG_SAMARITAN = KBTS_FOURCC('s', 'a', 'm', 'r'), + KBTS_SCRIPT_TAG_SAURASHTRA = KBTS_FOURCC('s', 'a', 'u', 'r'), + KBTS_SCRIPT_TAG_SHARADA = KBTS_FOURCC('s', 'h', 'r', 'd'), + KBTS_SCRIPT_TAG_SHAVIAN = KBTS_FOURCC('s', 'h', 'a', 'w'), + KBTS_SCRIPT_TAG_SIDDHAM = KBTS_FOURCC('s', 'i', 'd', 'd'), + KBTS_SCRIPT_TAG_SIGN_WRITING = KBTS_FOURCC('s', 'g', 'n', 'w'), + KBTS_SCRIPT_TAG_SOGDIAN = KBTS_FOURCC('s', 'o', 'g', 'd'), + KBTS_SCRIPT_TAG_SINHALA = KBTS_FOURCC('s', 'i', 'n', 'h'), + KBTS_SCRIPT_TAG_SORA_SOMPENG = KBTS_FOURCC('s', 'o', 'r', 'a'), + KBTS_SCRIPT_TAG_SOYOMBO = KBTS_FOURCC('s', 'o', 'y', 'o'), + KBTS_SCRIPT_TAG_SUMERO_AKKADIAN_CUNEIFORM = KBTS_FOURCC('x', 's', 'u', 'x'), + KBTS_SCRIPT_TAG_SUNDANESE = KBTS_FOURCC('s', 'u', 'n', 'd'), + KBTS_SCRIPT_TAG_SUNUWAR = KBTS_FOURCC('s', 'u', 'n', 'u'), + KBTS_SCRIPT_TAG_SYLOTI_NAGRI = KBTS_FOURCC('s', 'y', 'l', 'o'), + KBTS_SCRIPT_TAG_SYRIAC = KBTS_FOURCC('s', 'y', 'r', 'c'), + KBTS_SCRIPT_TAG_TAGALOG = KBTS_FOURCC('t', 'g', 'l', 'g'), + KBTS_SCRIPT_TAG_TAGBANWA = KBTS_FOURCC('t', 'a', 'g', 'b'), + KBTS_SCRIPT_TAG_TAI_LE = KBTS_FOURCC('t', 'a', 'l', 'e'), + KBTS_SCRIPT_TAG_TAI_THAM = KBTS_FOURCC('l', 'a', 'n', 'a'), + KBTS_SCRIPT_TAG_TAI_VIET = KBTS_FOURCC('t', 'a', 'v', 't'), + KBTS_SCRIPT_TAG_TAKRI = KBTS_FOURCC('t', 'a', 'k', 'r'), + KBTS_SCRIPT_TAG_TAMIL = KBTS_FOURCC('t', 'm', 'l', '2'), + KBTS_SCRIPT_TAG_TANGSA = KBTS_FOURCC('t', 'n', 's', 'a'), + KBTS_SCRIPT_TAG_TANGUT = KBTS_FOURCC('t', 'a', 'n', 'g'), + KBTS_SCRIPT_TAG_TELUGU = KBTS_FOURCC('t', 'e', 'l', '2'), + KBTS_SCRIPT_TAG_THAANA = KBTS_FOURCC('t', 'h', 'a', 'a'), + KBTS_SCRIPT_TAG_THAI = KBTS_FOURCC('t', 'h', 'a', 'i'), + KBTS_SCRIPT_TAG_TIBETAN = KBTS_FOURCC('t', 'i', 'b', 't'), + KBTS_SCRIPT_TAG_TIFINAGH = KBTS_FOURCC('t', 'f', 'n', 'g'), + KBTS_SCRIPT_TAG_TIRHUTA = KBTS_FOURCC('t', 'i', 'r', 'h'), + KBTS_SCRIPT_TAG_TODHRI = KBTS_FOURCC('t', 'o', 'd', 'r'), + KBTS_SCRIPT_TAG_TOTO = KBTS_FOURCC('t', 'o', 't', 'o'), + KBTS_SCRIPT_TAG_TULU_TIGALARI = KBTS_FOURCC('t', 'u', 't', 'g'), + KBTS_SCRIPT_TAG_UGARITIC_CUNEIFORM = KBTS_FOURCC('u', 'g', 'a', 'r'), + KBTS_SCRIPT_TAG_VAI = KBTS_FOURCC('v', 'a', 'i', ' '), + KBTS_SCRIPT_TAG_VITHKUQI = KBTS_FOURCC('v', 'i', 't', 'h'), + KBTS_SCRIPT_TAG_WANCHO = KBTS_FOURCC('w', 'c', 'h', 'o'), + KBTS_SCRIPT_TAG_WARANG_CITI = KBTS_FOURCC('w', 'a', 'r', 'a'), + KBTS_SCRIPT_TAG_YEZIDI = KBTS_FOURCC('y', 'e', 'z', 'i'), + KBTS_SCRIPT_TAG_YI = KBTS_FOURCC('y', 'i', ' ', ' '), + KBTS_SCRIPT_TAG_ZANABAZAR_SQUARE = KBTS_FOURCC('z', 'a', 'n', 'b'), +}; + +typedef kbts_u32 kbts_script; +enum kbts_script_enum +{ + KBTS_SCRIPT_DONT_KNOW, + KBTS_SCRIPT_ADLAM, + KBTS_SCRIPT_AHOM, + KBTS_SCRIPT_ANATOLIAN_HIEROGLYPHS, + KBTS_SCRIPT_ARABIC, + KBTS_SCRIPT_ARMENIAN, + KBTS_SCRIPT_AVESTAN, + KBTS_SCRIPT_BALINESE, + KBTS_SCRIPT_BAMUM, + KBTS_SCRIPT_BASSA_VAH, + KBTS_SCRIPT_BATAK, + KBTS_SCRIPT_BENGALI, + KBTS_SCRIPT_BHAIKSUKI, + KBTS_SCRIPT_BOPOMOFO, + KBTS_SCRIPT_BRAHMI, + KBTS_SCRIPT_BUGINESE, + KBTS_SCRIPT_BUHID, + KBTS_SCRIPT_CANADIAN_SYLLABICS, + KBTS_SCRIPT_CARIAN, + KBTS_SCRIPT_CAUCASIAN_ALBANIAN, + KBTS_SCRIPT_CHAKMA, + KBTS_SCRIPT_CHAM, + KBTS_SCRIPT_CHEROKEE, + KBTS_SCRIPT_CHORASMIAN, + KBTS_SCRIPT_CJK_IDEOGRAPHIC, + KBTS_SCRIPT_COPTIC, + KBTS_SCRIPT_CYPRIOT_SYLLABARY, + KBTS_SCRIPT_CYPRO_MINOAN, + KBTS_SCRIPT_CYRILLIC, + KBTS_SCRIPT_DEFAULT, + KBTS_SCRIPT_DEFAULT2, + KBTS_SCRIPT_DESERET, + KBTS_SCRIPT_DEVANAGARI, + KBTS_SCRIPT_DIVES_AKURU, + KBTS_SCRIPT_DOGRA, + KBTS_SCRIPT_DUPLOYAN, + KBTS_SCRIPT_EGYPTIAN_HIEROGLYPHS, + KBTS_SCRIPT_ELBASAN, + KBTS_SCRIPT_ELYMAIC, + KBTS_SCRIPT_ETHIOPIC, + KBTS_SCRIPT_GARAY, + KBTS_SCRIPT_GEORGIAN, + KBTS_SCRIPT_GLAGOLITIC, + KBTS_SCRIPT_GOTHIC, + KBTS_SCRIPT_GRANTHA, + KBTS_SCRIPT_GREEK, + KBTS_SCRIPT_GUJARATI, + KBTS_SCRIPT_GUNJALA_GONDI, + KBTS_SCRIPT_GURMUKHI, + KBTS_SCRIPT_GURUNG_KHEMA, + KBTS_SCRIPT_HANGUL, + KBTS_SCRIPT_HANIFI_ROHINGYA, + KBTS_SCRIPT_HANUNOO, + KBTS_SCRIPT_HATRAN, + KBTS_SCRIPT_HEBREW, + KBTS_SCRIPT_HIRAGANA, + KBTS_SCRIPT_IMPERIAL_ARAMAIC, + KBTS_SCRIPT_INSCRIPTIONAL_PAHLAVI, + KBTS_SCRIPT_INSCRIPTIONAL_PARTHIAN, + KBTS_SCRIPT_JAVANESE, + KBTS_SCRIPT_KAITHI, + KBTS_SCRIPT_KANNADA, + KBTS_SCRIPT_KATAKANA, + KBTS_SCRIPT_KAWI, + KBTS_SCRIPT_KAYAH_LI, + KBTS_SCRIPT_KHAROSHTHI, + KBTS_SCRIPT_KHITAN_SMALL_SCRIPT, + KBTS_SCRIPT_KHMER, + KBTS_SCRIPT_KHOJKI, + KBTS_SCRIPT_KHUDAWADI, + KBTS_SCRIPT_KIRAT_RAI, + KBTS_SCRIPT_LAO, + KBTS_SCRIPT_LATIN, + KBTS_SCRIPT_LEPCHA, + KBTS_SCRIPT_LIMBU, + KBTS_SCRIPT_LINEAR_A, + KBTS_SCRIPT_LINEAR_B, + KBTS_SCRIPT_LISU, + KBTS_SCRIPT_LYCIAN, + KBTS_SCRIPT_LYDIAN, + KBTS_SCRIPT_MAHAJANI, + KBTS_SCRIPT_MAKASAR, + KBTS_SCRIPT_MALAYALAM, + KBTS_SCRIPT_MANDAIC, + KBTS_SCRIPT_MANICHAEAN, + KBTS_SCRIPT_MARCHEN, + KBTS_SCRIPT_MASARAM_GONDI, + KBTS_SCRIPT_MEDEFAIDRIN, + KBTS_SCRIPT_MEETEI_MAYEK, + KBTS_SCRIPT_MENDE_KIKAKUI, + KBTS_SCRIPT_MEROITIC_CURSIVE, + KBTS_SCRIPT_MEROITIC_HIEROGLYPHS, + KBTS_SCRIPT_MIAO, + KBTS_SCRIPT_MODI, + KBTS_SCRIPT_MONGOLIAN, + KBTS_SCRIPT_MRO, + KBTS_SCRIPT_MULTANI, + KBTS_SCRIPT_MYANMAR, + KBTS_SCRIPT_NABATAEAN, + KBTS_SCRIPT_NAG_MUNDARI, + KBTS_SCRIPT_NANDINAGARI, + KBTS_SCRIPT_NEWA, + KBTS_SCRIPT_NEW_TAI_LUE, + KBTS_SCRIPT_NKO, + KBTS_SCRIPT_NUSHU, + KBTS_SCRIPT_NYIAKENG_PUACHUE_HMONG, + KBTS_SCRIPT_OGHAM, + KBTS_SCRIPT_OL_CHIKI, + KBTS_SCRIPT_OL_ONAL, + KBTS_SCRIPT_OLD_ITALIC, + KBTS_SCRIPT_OLD_HUNGARIAN, + KBTS_SCRIPT_OLD_NORTH_ARABIAN, + KBTS_SCRIPT_OLD_PERMIC, + KBTS_SCRIPT_OLD_PERSIAN_CUNEIFORM, + KBTS_SCRIPT_OLD_SOGDIAN, + KBTS_SCRIPT_OLD_SOUTH_ARABIAN, + KBTS_SCRIPT_OLD_TURKIC, + KBTS_SCRIPT_OLD_UYGHUR, + KBTS_SCRIPT_ODIA, + KBTS_SCRIPT_OSAGE, + KBTS_SCRIPT_OSMANYA, + KBTS_SCRIPT_PAHAWH_HMONG, + KBTS_SCRIPT_PALMYRENE, + KBTS_SCRIPT_PAU_CIN_HAU, + KBTS_SCRIPT_PHAGS_PA, + KBTS_SCRIPT_PHOENICIAN, + KBTS_SCRIPT_PSALTER_PAHLAVI, + KBTS_SCRIPT_REJANG, + KBTS_SCRIPT_RUNIC, + KBTS_SCRIPT_SAMARITAN, + KBTS_SCRIPT_SAURASHTRA, + KBTS_SCRIPT_SHARADA, + KBTS_SCRIPT_SHAVIAN, + KBTS_SCRIPT_SIDDHAM, + KBTS_SCRIPT_SIGN_WRITING, + KBTS_SCRIPT_SOGDIAN, + KBTS_SCRIPT_SINHALA, + KBTS_SCRIPT_SORA_SOMPENG, + KBTS_SCRIPT_SOYOMBO, + KBTS_SCRIPT_SUMERO_AKKADIAN_CUNEIFORM, + KBTS_SCRIPT_SUNDANESE, + KBTS_SCRIPT_SUNUWAR, + KBTS_SCRIPT_SYLOTI_NAGRI, + KBTS_SCRIPT_SYRIAC, + KBTS_SCRIPT_TAGALOG, + KBTS_SCRIPT_TAGBANWA, + KBTS_SCRIPT_TAI_LE, + KBTS_SCRIPT_TAI_THAM, + KBTS_SCRIPT_TAI_VIET, + KBTS_SCRIPT_TAKRI, + KBTS_SCRIPT_TAMIL, + KBTS_SCRIPT_TANGSA, + KBTS_SCRIPT_TANGUT, + KBTS_SCRIPT_TELUGU, + KBTS_SCRIPT_THAANA, + KBTS_SCRIPT_THAI, + KBTS_SCRIPT_TIBETAN, + KBTS_SCRIPT_TIFINAGH, + KBTS_SCRIPT_TIRHUTA, + KBTS_SCRIPT_TODHRI, + KBTS_SCRIPT_TOTO, + KBTS_SCRIPT_TULU_TIGALARI, + KBTS_SCRIPT_UGARITIC_CUNEIFORM, + KBTS_SCRIPT_VAI, + KBTS_SCRIPT_VITHKUQI, + KBTS_SCRIPT_WANCHO, + KBTS_SCRIPT_WARANG_CITI, + KBTS_SCRIPT_YEZIDI, + KBTS_SCRIPT_YI, + KBTS_SCRIPT_ZANABAZAR_SQUARE, + KBTS_SCRIPT_COUNT, +}; + +typedef kbts_u32 kbts_feature_tag; +enum kbts_feature_tag_enum +{ + KBTS_FEATURE_TAG_UNREGISTERED = KBTS_FOURCC(0, 0, 0, 0), // Features that aren't pre-defined in the OpenType spec + KBTS_FEATURE_TAG_isol = KBTS_FOURCC('i', 's', 'o', 'l'), // Isolated Forms + KBTS_FEATURE_TAG_fina = KBTS_FOURCC('f', 'i', 'n', 'a'), // Terminal Forms + KBTS_FEATURE_TAG_fin2 = KBTS_FOURCC('f', 'i', 'n', '2'), // Terminal Forms #2 + KBTS_FEATURE_TAG_fin3 = KBTS_FOURCC('f', 'i', 'n', '3'), // Terminal Forms #3 + KBTS_FEATURE_TAG_medi = KBTS_FOURCC('m', 'e', 'd', 'i'), // Medial Forms + KBTS_FEATURE_TAG_med2 = KBTS_FOURCC('m', 'e', 'd', '2'), // Medial Forms #2 + KBTS_FEATURE_TAG_init = KBTS_FOURCC('i', 'n', 'i', 't'), // Initial Forms + KBTS_FEATURE_TAG_ljmo = KBTS_FOURCC('l', 'j', 'm', 'o'), // Leading Jamo Forms + KBTS_FEATURE_TAG_vjmo = KBTS_FOURCC('v', 'j', 'm', 'o'), // Vowel Jamo Forms + KBTS_FEATURE_TAG_tjmo = KBTS_FOURCC('t', 'j', 'm', 'o'), // Trailing Jamo Forms + KBTS_FEATURE_TAG_rphf = KBTS_FOURCC('r', 'p', 'h', 'f'), // Reph Form + KBTS_FEATURE_TAG_blwf = KBTS_FOURCC('b', 'l', 'w', 'f'), // Below-base Forms + KBTS_FEATURE_TAG_half = KBTS_FOURCC('h', 'a', 'l', 'f'), // Half Forms + KBTS_FEATURE_TAG_pstf = KBTS_FOURCC('p', 's', 't', 'f'), // Post-base Forms + KBTS_FEATURE_TAG_abvf = KBTS_FOURCC('a', 'b', 'v', 'f'), // Above-base Forms + KBTS_FEATURE_TAG_pref = KBTS_FOURCC('p', 'r', 'e', 'f'), // Pre-base Forms + KBTS_FEATURE_TAG_numr = KBTS_FOURCC('n', 'u', 'm', 'r'), // Numerators + KBTS_FEATURE_TAG_frac = KBTS_FOURCC('f', 'r', 'a', 'c'), // Fractions + KBTS_FEATURE_TAG_dnom = KBTS_FOURCC('d', 'n', 'o', 'm'), // Denominators + KBTS_FEATURE_TAG_cfar = KBTS_FOURCC('c', 'f', 'a', 'r'), // Conjunct Form After Ro + KBTS_FEATURE_TAG_aalt = KBTS_FOURCC('a', 'a', 'l', 't'), // Access All Alternates + KBTS_FEATURE_TAG_abvm = KBTS_FOURCC('a', 'b', 'v', 'm'), // Above-base Mark Positioning + KBTS_FEATURE_TAG_abvs = KBTS_FOURCC('a', 'b', 'v', 's'), // Above-base Substitutions + KBTS_FEATURE_TAG_afrc = KBTS_FOURCC('a', 'f', 'r', 'c'), // Alternative Fractions + KBTS_FEATURE_TAG_akhn = KBTS_FOURCC('a', 'k', 'h', 'n'), // Akhand + KBTS_FEATURE_TAG_apkn = KBTS_FOURCC('a', 'p', 'k', 'n'), // Kerning for Alternate Proportional Widths + KBTS_FEATURE_TAG_blwm = KBTS_FOURCC('b', 'l', 'w', 'm'), // Below-base Mark Positioning + KBTS_FEATURE_TAG_blws = KBTS_FOURCC('b', 'l', 'w', 's'), // Below-base Substitutions + KBTS_FEATURE_TAG_calt = KBTS_FOURCC('c', 'a', 'l', 't'), // Contextual Alternates + KBTS_FEATURE_TAG_case = KBTS_FOURCC('c', 'a', 's', 'e'), // Case-sensitive Forms + KBTS_FEATURE_TAG_ccmp = KBTS_FOURCC('c', 'c', 'm', 'p'), // Glyph Composition / Decomposition + KBTS_FEATURE_TAG_chws = KBTS_FOURCC('c', 'h', 'w', 's'), // Contextual Half-width Spacing + KBTS_FEATURE_TAG_cjct = KBTS_FOURCC('c', 'j', 'c', 't'), // Conjunct Forms + KBTS_FEATURE_TAG_clig = KBTS_FOURCC('c', 'l', 'i', 'g'), // Contextual Ligatures + KBTS_FEATURE_TAG_cpct = KBTS_FOURCC('c', 'p', 'c', 't'), // Centered CJK Punctuation + KBTS_FEATURE_TAG_cpsp = KBTS_FOURCC('c', 'p', 's', 'p'), // Capital Spacing + KBTS_FEATURE_TAG_cswh = KBTS_FOURCC('c', 's', 'w', 'h'), // Contextual Swash + KBTS_FEATURE_TAG_curs = KBTS_FOURCC('c', 'u', 'r', 's'), // Cursive Positioning + KBTS_FEATURE_TAG_cv01 = KBTS_FOURCC('c', 'v', '0', '1'), // Character Variant 1 + KBTS_FEATURE_TAG_cv02 = KBTS_FOURCC('c', 'v', '0', '2'), // Character Variant 2 + KBTS_FEATURE_TAG_cv03 = KBTS_FOURCC('c', 'v', '0', '3'), // Character Variant 3 + KBTS_FEATURE_TAG_cv04 = KBTS_FOURCC('c', 'v', '0', '4'), // Character Variant 4 + KBTS_FEATURE_TAG_cv05 = KBTS_FOURCC('c', 'v', '0', '5'), // Character Variant 5 + KBTS_FEATURE_TAG_cv06 = KBTS_FOURCC('c', 'v', '0', '6'), // Character Variant 6 + KBTS_FEATURE_TAG_cv07 = KBTS_FOURCC('c', 'v', '0', '7'), // Character Variant 7 + KBTS_FEATURE_TAG_cv08 = KBTS_FOURCC('c', 'v', '0', '8'), // Character Variant 8 + KBTS_FEATURE_TAG_cv09 = KBTS_FOURCC('c', 'v', '0', '9'), // Character Variant 9 + KBTS_FEATURE_TAG_cv10 = KBTS_FOURCC('c', 'v', '1', '0'), // Character Variant 10 + KBTS_FEATURE_TAG_cv11 = KBTS_FOURCC('c', 'v', '1', '1'), // Character Variant 11 + KBTS_FEATURE_TAG_cv12 = KBTS_FOURCC('c', 'v', '1', '2'), // Character Variant 12 + KBTS_FEATURE_TAG_cv13 = KBTS_FOURCC('c', 'v', '1', '3'), // Character Variant 13 + KBTS_FEATURE_TAG_cv14 = KBTS_FOURCC('c', 'v', '1', '4'), // Character Variant 14 + KBTS_FEATURE_TAG_cv15 = KBTS_FOURCC('c', 'v', '1', '5'), // Character Variant 15 + KBTS_FEATURE_TAG_cv16 = KBTS_FOURCC('c', 'v', '1', '6'), // Character Variant 16 + KBTS_FEATURE_TAG_cv17 = KBTS_FOURCC('c', 'v', '1', '7'), // Character Variant 17 + KBTS_FEATURE_TAG_cv18 = KBTS_FOURCC('c', 'v', '1', '8'), // Character Variant 18 + KBTS_FEATURE_TAG_cv19 = KBTS_FOURCC('c', 'v', '1', '9'), // Character Variant 19 + KBTS_FEATURE_TAG_cv20 = KBTS_FOURCC('c', 'v', '2', '0'), // Character Variant 20 + KBTS_FEATURE_TAG_cv21 = KBTS_FOURCC('c', 'v', '2', '1'), // Character Variant 21 + KBTS_FEATURE_TAG_cv22 = KBTS_FOURCC('c', 'v', '2', '2'), // Character Variant 22 + KBTS_FEATURE_TAG_cv23 = KBTS_FOURCC('c', 'v', '2', '3'), // Character Variant 23 + KBTS_FEATURE_TAG_cv24 = KBTS_FOURCC('c', 'v', '2', '4'), // Character Variant 24 + KBTS_FEATURE_TAG_cv25 = KBTS_FOURCC('c', 'v', '2', '5'), // Character Variant 25 + KBTS_FEATURE_TAG_cv26 = KBTS_FOURCC('c', 'v', '2', '6'), // Character Variant 26 + KBTS_FEATURE_TAG_cv27 = KBTS_FOURCC('c', 'v', '2', '7'), // Character Variant 27 + KBTS_FEATURE_TAG_cv28 = KBTS_FOURCC('c', 'v', '2', '8'), // Character Variant 28 + KBTS_FEATURE_TAG_cv29 = KBTS_FOURCC('c', 'v', '2', '9'), // Character Variant 29 + KBTS_FEATURE_TAG_cv30 = KBTS_FOURCC('c', 'v', '3', '0'), // Character Variant 30 + KBTS_FEATURE_TAG_cv31 = KBTS_FOURCC('c', 'v', '3', '1'), // Character Variant 31 + KBTS_FEATURE_TAG_cv32 = KBTS_FOURCC('c', 'v', '3', '2'), // Character Variant 32 + KBTS_FEATURE_TAG_cv33 = KBTS_FOURCC('c', 'v', '3', '3'), // Character Variant 33 + KBTS_FEATURE_TAG_cv34 = KBTS_FOURCC('c', 'v', '3', '4'), // Character Variant 34 + KBTS_FEATURE_TAG_cv35 = KBTS_FOURCC('c', 'v', '3', '5'), // Character Variant 35 + KBTS_FEATURE_TAG_cv36 = KBTS_FOURCC('c', 'v', '3', '6'), // Character Variant 36 + KBTS_FEATURE_TAG_cv37 = KBTS_FOURCC('c', 'v', '3', '7'), // Character Variant 37 + KBTS_FEATURE_TAG_cv38 = KBTS_FOURCC('c', 'v', '3', '8'), // Character Variant 38 + KBTS_FEATURE_TAG_cv39 = KBTS_FOURCC('c', 'v', '3', '9'), // Character Variant 39 + KBTS_FEATURE_TAG_cv40 = KBTS_FOURCC('c', 'v', '4', '0'), // Character Variant 40 + KBTS_FEATURE_TAG_cv41 = KBTS_FOURCC('c', 'v', '4', '1'), // Character Variant 41 + KBTS_FEATURE_TAG_cv42 = KBTS_FOURCC('c', 'v', '4', '2'), // Character Variant 42 + KBTS_FEATURE_TAG_cv43 = KBTS_FOURCC('c', 'v', '4', '3'), // Character Variant 43 + KBTS_FEATURE_TAG_cv44 = KBTS_FOURCC('c', 'v', '4', '4'), // Character Variant 44 + KBTS_FEATURE_TAG_cv45 = KBTS_FOURCC('c', 'v', '4', '5'), // Character Variant 45 + KBTS_FEATURE_TAG_cv46 = KBTS_FOURCC('c', 'v', '4', '6'), // Character Variant 46 + KBTS_FEATURE_TAG_cv47 = KBTS_FOURCC('c', 'v', '4', '7'), // Character Variant 47 + KBTS_FEATURE_TAG_cv48 = KBTS_FOURCC('c', 'v', '4', '8'), // Character Variant 48 + KBTS_FEATURE_TAG_cv49 = KBTS_FOURCC('c', 'v', '4', '9'), // Character Variant 49 + KBTS_FEATURE_TAG_cv50 = KBTS_FOURCC('c', 'v', '5', '0'), // Character Variant 50 + KBTS_FEATURE_TAG_cv51 = KBTS_FOURCC('c', 'v', '5', '1'), // Character Variant 51 + KBTS_FEATURE_TAG_cv52 = KBTS_FOURCC('c', 'v', '5', '2'), // Character Variant 52 + KBTS_FEATURE_TAG_cv53 = KBTS_FOURCC('c', 'v', '5', '3'), // Character Variant 53 + KBTS_FEATURE_TAG_cv54 = KBTS_FOURCC('c', 'v', '5', '4'), // Character Variant 54 + KBTS_FEATURE_TAG_cv55 = KBTS_FOURCC('c', 'v', '5', '5'), // Character Variant 55 + KBTS_FEATURE_TAG_cv56 = KBTS_FOURCC('c', 'v', '5', '6'), // Character Variant 56 + KBTS_FEATURE_TAG_cv57 = KBTS_FOURCC('c', 'v', '5', '7'), // Character Variant 57 + KBTS_FEATURE_TAG_cv58 = KBTS_FOURCC('c', 'v', '5', '8'), // Character Variant 58 + KBTS_FEATURE_TAG_cv59 = KBTS_FOURCC('c', 'v', '5', '9'), // Character Variant 59 + KBTS_FEATURE_TAG_cv60 = KBTS_FOURCC('c', 'v', '6', '0'), // Character Variant 60 + KBTS_FEATURE_TAG_cv61 = KBTS_FOURCC('c', 'v', '6', '1'), // Character Variant 61 + KBTS_FEATURE_TAG_cv62 = KBTS_FOURCC('c', 'v', '6', '2'), // Character Variant 62 + KBTS_FEATURE_TAG_cv63 = KBTS_FOURCC('c', 'v', '6', '3'), // Character Variant 63 + KBTS_FEATURE_TAG_cv64 = KBTS_FOURCC('c', 'v', '6', '4'), // Character Variant 64 + KBTS_FEATURE_TAG_cv65 = KBTS_FOURCC('c', 'v', '6', '5'), // Character Variant 65 + KBTS_FEATURE_TAG_cv66 = KBTS_FOURCC('c', 'v', '6', '6'), // Character Variant 66 + KBTS_FEATURE_TAG_cv67 = KBTS_FOURCC('c', 'v', '6', '7'), // Character Variant 67 + KBTS_FEATURE_TAG_cv68 = KBTS_FOURCC('c', 'v', '6', '8'), // Character Variant 68 + KBTS_FEATURE_TAG_cv69 = KBTS_FOURCC('c', 'v', '6', '9'), // Character Variant 69 + KBTS_FEATURE_TAG_cv70 = KBTS_FOURCC('c', 'v', '7', '0'), // Character Variant 70 + KBTS_FEATURE_TAG_cv71 = KBTS_FOURCC('c', 'v', '7', '1'), // Character Variant 71 + KBTS_FEATURE_TAG_cv72 = KBTS_FOURCC('c', 'v', '7', '2'), // Character Variant 72 + KBTS_FEATURE_TAG_cv73 = KBTS_FOURCC('c', 'v', '7', '3'), // Character Variant 73 + KBTS_FEATURE_TAG_cv74 = KBTS_FOURCC('c', 'v', '7', '4'), // Character Variant 74 + KBTS_FEATURE_TAG_cv75 = KBTS_FOURCC('c', 'v', '7', '5'), // Character Variant 75 + KBTS_FEATURE_TAG_cv76 = KBTS_FOURCC('c', 'v', '7', '6'), // Character Variant 76 + KBTS_FEATURE_TAG_cv77 = KBTS_FOURCC('c', 'v', '7', '7'), // Character Variant 77 + KBTS_FEATURE_TAG_cv78 = KBTS_FOURCC('c', 'v', '7', '8'), // Character Variant 78 + KBTS_FEATURE_TAG_cv79 = KBTS_FOURCC('c', 'v', '7', '9'), // Character Variant 79 + KBTS_FEATURE_TAG_cv80 = KBTS_FOURCC('c', 'v', '8', '0'), // Character Variant 80 + KBTS_FEATURE_TAG_cv81 = KBTS_FOURCC('c', 'v', '8', '1'), // Character Variant 81 + KBTS_FEATURE_TAG_cv82 = KBTS_FOURCC('c', 'v', '8', '2'), // Character Variant 82 + KBTS_FEATURE_TAG_cv83 = KBTS_FOURCC('c', 'v', '8', '3'), // Character Variant 83 + KBTS_FEATURE_TAG_cv84 = KBTS_FOURCC('c', 'v', '8', '4'), // Character Variant 84 + KBTS_FEATURE_TAG_cv85 = KBTS_FOURCC('c', 'v', '8', '5'), // Character Variant 85 + KBTS_FEATURE_TAG_cv86 = KBTS_FOURCC('c', 'v', '8', '6'), // Character Variant 86 + KBTS_FEATURE_TAG_cv87 = KBTS_FOURCC('c', 'v', '8', '7'), // Character Variant 87 + KBTS_FEATURE_TAG_cv88 = KBTS_FOURCC('c', 'v', '8', '8'), // Character Variant 88 + KBTS_FEATURE_TAG_cv89 = KBTS_FOURCC('c', 'v', '8', '9'), // Character Variant 89 + KBTS_FEATURE_TAG_cv90 = KBTS_FOURCC('c', 'v', '9', '0'), // Character Variant 90 + KBTS_FEATURE_TAG_cv91 = KBTS_FOURCC('c', 'v', '9', '1'), // Character Variant 91 + KBTS_FEATURE_TAG_cv92 = KBTS_FOURCC('c', 'v', '9', '2'), // Character Variant 92 + KBTS_FEATURE_TAG_cv93 = KBTS_FOURCC('c', 'v', '9', '3'), // Character Variant 93 + KBTS_FEATURE_TAG_cv94 = KBTS_FOURCC('c', 'v', '9', '4'), // Character Variant 94 + KBTS_FEATURE_TAG_cv95 = KBTS_FOURCC('c', 'v', '9', '5'), // Character Variant 95 + KBTS_FEATURE_TAG_cv96 = KBTS_FOURCC('c', 'v', '9', '6'), // Character Variant 96 + KBTS_FEATURE_TAG_cv97 = KBTS_FOURCC('c', 'v', '9', '7'), // Character Variant 97 + KBTS_FEATURE_TAG_cv98 = KBTS_FOURCC('c', 'v', '9', '8'), // Character Variant 98 + KBTS_FEATURE_TAG_cv99 = KBTS_FOURCC('c', 'v', '9', '9'), // Character Variant 99 + KBTS_FEATURE_TAG_c2pc = KBTS_FOURCC('c', '2', 'p', 'c'), // Petite Capitals From Capitals + KBTS_FEATURE_TAG_c2sc = KBTS_FOURCC('c', '2', 's', 'c'), // Small Capitals From Capitals + KBTS_FEATURE_TAG_dist = KBTS_FOURCC('d', 'i', 's', 't'), // Distances + KBTS_FEATURE_TAG_dlig = KBTS_FOURCC('d', 'l', 'i', 'g'), // Discretionary Ligatures + KBTS_FEATURE_TAG_dtls = KBTS_FOURCC('d', 't', 'l', 's'), // Dotless Forms + KBTS_FEATURE_TAG_expt = KBTS_FOURCC('e', 'x', 'p', 't'), // Expert Forms + KBTS_FEATURE_TAG_falt = KBTS_FOURCC('f', 'a', 'l', 't'), // Final Glyph on Line Alternates + KBTS_FEATURE_TAG_flac = KBTS_FOURCC('f', 'l', 'a', 'c'), // Flattened Accent Forms + KBTS_FEATURE_TAG_fwid = KBTS_FOURCC('f', 'w', 'i', 'd'), // Full Widths + KBTS_FEATURE_TAG_haln = KBTS_FOURCC('h', 'a', 'l', 'n'), // Halant Forms + KBTS_FEATURE_TAG_halt = KBTS_FOURCC('h', 'a', 'l', 't'), // Alternate Half Widths + KBTS_FEATURE_TAG_hist = KBTS_FOURCC('h', 'i', 's', 't'), // Historical Forms + KBTS_FEATURE_TAG_hkna = KBTS_FOURCC('h', 'k', 'n', 'a'), // Horizontal Kana Alternates + KBTS_FEATURE_TAG_hlig = KBTS_FOURCC('h', 'l', 'i', 'g'), // Historical Ligatures + KBTS_FEATURE_TAG_hngl = KBTS_FOURCC('h', 'n', 'g', 'l'), // Hangul + KBTS_FEATURE_TAG_hojo = KBTS_FOURCC('h', 'o', 'j', 'o'), // Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms) + KBTS_FEATURE_TAG_hwid = KBTS_FOURCC('h', 'w', 'i', 'd'), // Half Widths + KBTS_FEATURE_TAG_ital = KBTS_FOURCC('i', 't', 'a', 'l'), // Italics + KBTS_FEATURE_TAG_jalt = KBTS_FOURCC('j', 'a', 'l', 't'), // Justification Alternates + KBTS_FEATURE_TAG_jp78 = KBTS_FOURCC('j', 'p', '7', '8'), // JIS78 Forms + KBTS_FEATURE_TAG_jp83 = KBTS_FOURCC('j', 'p', '8', '3'), // JIS83 Forms + KBTS_FEATURE_TAG_jp90 = KBTS_FOURCC('j', 'p', '9', '0'), // JIS90 Forms + KBTS_FEATURE_TAG_jp04 = KBTS_FOURCC('j', 'p', '0', '4'), // JIS2004 Forms + KBTS_FEATURE_TAG_kern = KBTS_FOURCC('k', 'e', 'r', 'n'), // Kerning + KBTS_FEATURE_TAG_lfbd = KBTS_FOURCC('l', 'f', 'b', 'd'), // Left Bounds + KBTS_FEATURE_TAG_liga = KBTS_FOURCC('l', 'i', 'g', 'a'), // Standard Ligatures + KBTS_FEATURE_TAG_lnum = KBTS_FOURCC('l', 'n', 'u', 'm'), // Lining Figures + KBTS_FEATURE_TAG_locl = KBTS_FOURCC('l', 'o', 'c', 'l'), // Localized Forms + KBTS_FEATURE_TAG_ltra = KBTS_FOURCC('l', 't', 'r', 'a'), // Left-to-right Alternates + KBTS_FEATURE_TAG_ltrm = KBTS_FOURCC('l', 't', 'r', 'm'), // Left-to-right Mirrored Forms + KBTS_FEATURE_TAG_mark = KBTS_FOURCC('m', 'a', 'r', 'k'), // Mark Positioning + KBTS_FEATURE_TAG_mgrk = KBTS_FOURCC('m', 'g', 'r', 'k'), // Mathematical Greek + KBTS_FEATURE_TAG_mkmk = KBTS_FOURCC('m', 'k', 'm', 'k'), // Mark to Mark Positioning + KBTS_FEATURE_TAG_mset = KBTS_FOURCC('m', 's', 'e', 't'), // Mark Positioning via Substitution + KBTS_FEATURE_TAG_nalt = KBTS_FOURCC('n', 'a', 'l', 't'), // Alternate Annotation Forms + KBTS_FEATURE_TAG_nlck = KBTS_FOURCC('n', 'l', 'c', 'k'), // NLC Kanji Forms + KBTS_FEATURE_TAG_nukt = KBTS_FOURCC('n', 'u', 'k', 't'), // Nukta Forms + KBTS_FEATURE_TAG_onum = KBTS_FOURCC('o', 'n', 'u', 'm'), // Oldstyle Figures + KBTS_FEATURE_TAG_opbd = KBTS_FOURCC('o', 'p', 'b', 'd'), // Optical Bounds + KBTS_FEATURE_TAG_ordn = KBTS_FOURCC('o', 'r', 'd', 'n'), // Ordinals + KBTS_FEATURE_TAG_ornm = KBTS_FOURCC('o', 'r', 'n', 'm'), // Ornaments + KBTS_FEATURE_TAG_palt = KBTS_FOURCC('p', 'a', 'l', 't'), // Proportional Alternate Widths + KBTS_FEATURE_TAG_pcap = KBTS_FOURCC('p', 'c', 'a', 'p'), // Petite Capitals + KBTS_FEATURE_TAG_pkna = KBTS_FOURCC('p', 'k', 'n', 'a'), // Proportional Kana + KBTS_FEATURE_TAG_pnum = KBTS_FOURCC('p', 'n', 'u', 'm'), // Proportional Figures + KBTS_FEATURE_TAG_pres = KBTS_FOURCC('p', 'r', 'e', 's'), // Pre-base Substitutions + KBTS_FEATURE_TAG_psts = KBTS_FOURCC('p', 's', 't', 's'), // Post-base Substitutions + KBTS_FEATURE_TAG_pwid = KBTS_FOURCC('p', 'w', 'i', 'd'), // Proportional Widths + KBTS_FEATURE_TAG_qwid = KBTS_FOURCC('q', 'w', 'i', 'd'), // Quarter Widths + KBTS_FEATURE_TAG_rand = KBTS_FOURCC('r', 'a', 'n', 'd'), // Randomize + KBTS_FEATURE_TAG_rclt = KBTS_FOURCC('r', 'c', 'l', 't'), // Required Contextual Alternates + KBTS_FEATURE_TAG_rkrf = KBTS_FOURCC('r', 'k', 'r', 'f'), // Rakar Forms + KBTS_FEATURE_TAG_rlig = KBTS_FOURCC('r', 'l', 'i', 'g'), // Required Ligatures + KBTS_FEATURE_TAG_rtbd = KBTS_FOURCC('r', 't', 'b', 'd'), // Right Bounds + KBTS_FEATURE_TAG_rtla = KBTS_FOURCC('r', 't', 'l', 'a'), // Right-to-left Alternates + KBTS_FEATURE_TAG_rtlm = KBTS_FOURCC('r', 't', 'l', 'm'), // Right-to-left Mirrored Forms + KBTS_FEATURE_TAG_ruby = KBTS_FOURCC('r', 'u', 'b', 'y'), // Ruby Notation Forms + KBTS_FEATURE_TAG_rvrn = KBTS_FOURCC('r', 'v', 'r', 'n'), // Required Variation Alternates + KBTS_FEATURE_TAG_salt = KBTS_FOURCC('s', 'a', 'l', 't'), // Stylistic Alternates + KBTS_FEATURE_TAG_sinf = KBTS_FOURCC('s', 'i', 'n', 'f'), // Scientific Inferiors + KBTS_FEATURE_TAG_size = KBTS_FOURCC('s', 'i', 'z', 'e'), // Optical size + KBTS_FEATURE_TAG_smcp = KBTS_FOURCC('s', 'm', 'c', 'p'), // Small Capitals + KBTS_FEATURE_TAG_smpl = KBTS_FOURCC('s', 'm', 'p', 'l'), // Simplified Forms + KBTS_FEATURE_TAG_ss01 = KBTS_FOURCC('s', 's', '0', '1'), // Stylistic Set 1 + KBTS_FEATURE_TAG_ss02 = KBTS_FOURCC('s', 's', '0', '2'), // Stylistic Set 2 + KBTS_FEATURE_TAG_ss03 = KBTS_FOURCC('s', 's', '0', '3'), // Stylistic Set 3 + KBTS_FEATURE_TAG_ss04 = KBTS_FOURCC('s', 's', '0', '4'), // Stylistic Set 4 + KBTS_FEATURE_TAG_ss05 = KBTS_FOURCC('s', 's', '0', '5'), // Stylistic Set 5 + KBTS_FEATURE_TAG_ss06 = KBTS_FOURCC('s', 's', '0', '6'), // Stylistic Set 6 + KBTS_FEATURE_TAG_ss07 = KBTS_FOURCC('s', 's', '0', '7'), // Stylistic Set 7 + KBTS_FEATURE_TAG_ss08 = KBTS_FOURCC('s', 's', '0', '8'), // Stylistic Set 8 + KBTS_FEATURE_TAG_ss09 = KBTS_FOURCC('s', 's', '0', '9'), // Stylistic Set 9 + KBTS_FEATURE_TAG_ss10 = KBTS_FOURCC('s', 's', '1', '0'), // Stylistic Set 10 + KBTS_FEATURE_TAG_ss11 = KBTS_FOURCC('s', 's', '1', '1'), // Stylistic Set 11 + KBTS_FEATURE_TAG_ss12 = KBTS_FOURCC('s', 's', '1', '2'), // Stylistic Set 12 + KBTS_FEATURE_TAG_ss13 = KBTS_FOURCC('s', 's', '1', '3'), // Stylistic Set 13 + KBTS_FEATURE_TAG_ss14 = KBTS_FOURCC('s', 's', '1', '4'), // Stylistic Set 14 + KBTS_FEATURE_TAG_ss15 = KBTS_FOURCC('s', 's', '1', '5'), // Stylistic Set 15 + KBTS_FEATURE_TAG_ss16 = KBTS_FOURCC('s', 's', '1', '6'), // Stylistic Set 16 + KBTS_FEATURE_TAG_ss17 = KBTS_FOURCC('s', 's', '1', '7'), // Stylistic Set 17 + KBTS_FEATURE_TAG_ss18 = KBTS_FOURCC('s', 's', '1', '8'), // Stylistic Set 18 + KBTS_FEATURE_TAG_ss19 = KBTS_FOURCC('s', 's', '1', '9'), // Stylistic Set 19 + KBTS_FEATURE_TAG_ss20 = KBTS_FOURCC('s', 's', '2', '0'), // Stylistic Set 20 + KBTS_FEATURE_TAG_ssty = KBTS_FOURCC('s', 's', 't', 'y'), // Math Script-style Alternates + KBTS_FEATURE_TAG_stch = KBTS_FOURCC('s', 't', 'c', 'h'), // Stretching Glyph Decomposition + KBTS_FEATURE_TAG_subs = KBTS_FOURCC('s', 'u', 'b', 's'), // Subscript + KBTS_FEATURE_TAG_sups = KBTS_FOURCC('s', 'u', 'p', 's'), // Superscript + KBTS_FEATURE_TAG_swsh = KBTS_FOURCC('s', 'w', 's', 'h'), // Swash + KBTS_FEATURE_TAG_test = KBTS_FOURCC('t', 'e', 's', 't'), // Test features, only for development + KBTS_FEATURE_TAG_titl = KBTS_FOURCC('t', 'i', 't', 'l'), // Titling + KBTS_FEATURE_TAG_tnam = KBTS_FOURCC('t', 'n', 'a', 'm'), // Traditional Name Forms + KBTS_FEATURE_TAG_tnum = KBTS_FOURCC('t', 'n', 'u', 'm'), // Tabular Figures + KBTS_FEATURE_TAG_trad = KBTS_FOURCC('t', 'r', 'a', 'd'), // Traditional Forms + KBTS_FEATURE_TAG_twid = KBTS_FOURCC('t', 'w', 'i', 'd'), // Third Widths + KBTS_FEATURE_TAG_unic = KBTS_FOURCC('u', 'n', 'i', 'c'), // Unicase + KBTS_FEATURE_TAG_valt = KBTS_FOURCC('v', 'a', 'l', 't'), // Alternate Vertical Metrics + KBTS_FEATURE_TAG_vapk = KBTS_FOURCC('v', 'a', 'p', 'k'), // Kerning for Alternate Proportional Vertical Metrics + KBTS_FEATURE_TAG_vatu = KBTS_FOURCC('v', 'a', 't', 'u'), // Vattu Variants + KBTS_FEATURE_TAG_vchw = KBTS_FOURCC('v', 'c', 'h', 'w'), // Vertical Contextual Half-width Spacing + KBTS_FEATURE_TAG_vert = KBTS_FOURCC('v', 'e', 'r', 't'), // Vertical Alternates + KBTS_FEATURE_TAG_vhal = KBTS_FOURCC('v', 'h', 'a', 'l'), // Alternate Vertical Half Metrics + KBTS_FEATURE_TAG_vkna = KBTS_FOURCC('v', 'k', 'n', 'a'), // Vertical Kana Alternates + KBTS_FEATURE_TAG_vkrn = KBTS_FOURCC('v', 'k', 'r', 'n'), // Vertical Kerning + KBTS_FEATURE_TAG_vpal = KBTS_FOURCC('v', 'p', 'a', 'l'), // Proportional Alternate Vertical Metrics + KBTS_FEATURE_TAG_vrt2 = KBTS_FOURCC('v', 'r', 't', '2'), // Vertical Alternates and Rotation + KBTS_FEATURE_TAG_vrtr = KBTS_FOURCC('v', 'r', 't', 'r'), // Vertical Alternates for Rotation + KBTS_FEATURE_TAG_zero = KBTS_FOURCC('z', 'e', 'r', 'o'), // Slashed Zero +}; + +typedef struct kbts__gdef kbts__gdef; +typedef struct kbts__cmap_14 kbts__cmap_14; +typedef struct kbts__gsub_gpos kbts__gsub_gpos; +typedef struct kbts__maxp kbts__maxp; +typedef struct kbts__hea kbts__hea; +typedef struct kbts_shaper_properties kbts_shaper_properties; +typedef struct kbts__feature kbts__feature; +typedef struct kbts__head kbts__head; +typedef struct kbts__langsys kbts__langsys; +typedef struct kbts_shape_config kbts_shape_config; +typedef struct kbts_glyph kbts_glyph; +typedef struct kbts_glyph_config kbts_glyph_config; +typedef struct kbts_shape_context kbts_shape_context; +typedef struct kbts_glyph_storage kbts_glyph_storage; + +typedef struct kbts_allocator_op_allocate +{ + void *Pointer; + kbts_u32 Size; +} kbts_allocator_op_allocate; + +typedef struct kbts_allocator_op_free +{ + void *Pointer; +} kbts_allocator_op_free; + +typedef struct kbts_allocator_op +{ + kbts_allocator_op_kind Kind; + + union + { + kbts_allocator_op_allocate Allocate; + kbts_allocator_op_free Free; + }; +} kbts_allocator_op; + +typedef void kbts_allocator_function(void *Data, kbts_allocator_op *Op); + +typedef struct kbts_lookup_subtable_info +{ + kbts_u16 MinimumBacktrackPlusOne; + kbts_u16 MinimumFollowupPlusOne; +} kbts_lookup_subtable_info; + +typedef struct kbts_blob_table +{ + kbts_u32 OffsetFromStartOfFile; + kbts_u32 Length; +} kbts_blob_table; + +typedef struct kbts_load_font_state +{ + void *FontData; + kbts_u32 FontDataSize; + + kbts_blob_table Tables[KBTS_BLOB_TABLE_ID_COUNT]; + kbts_u32 LookupCount; + kbts_u32 LookupSubtableCount; + kbts_u32 GlyphCount; + kbts_u32 ScratchSize; + + kbts_u32 GlyphLookupMatrixSizeInBytes; + kbts_u32 GlyphLookupSubtableMatrixSizeInBytes; + kbts_u32 TotalSize; +} kbts_load_font_state; + +typedef struct kbts_blob_header +{ + kbts_u32 Magic; + kbts_u32 Version; + + kbts_u32 LookupCount; + kbts_u32 LookupSubtableCount; + kbts_u32 GlyphCount; + + kbts_u32 GposLookupIndexOffset; + + kbts_u32 GlyphLookupMatrixOffsetFromStartOfFile; + kbts_u32 GlyphLookupSubtableMatrixOffsetFromStartOfFile; + kbts_u32 LookupSubtableIndexOffsetsOffsetFromStartOfFile; + kbts_u32 SubtableInfosOffsetFromStartOfFile; + + kbts_blob_table Tables[KBTS_BLOB_TABLE_ID_COUNT]; +} kbts_blob_header; + +typedef struct kbts_font +{ + kbts_allocator_function *Allocator; + void *AllocatorData; + + kbts_blob_header *Blob; + kbts_u16 *Cmap; + kbts__cmap_14 *Cmap14; + + kbts__gsub_gpos *ShapingTables[KBTS_SHAPING_TABLE_COUNT]; + + void *UserData; + + kbts_load_font_error Error; +} kbts_font; + +typedef struct kbts_font_info +{ + char *Strings[KBTS_FONT_INFO_STRING_ID_COUNT]; + kbts_u16 StringLengths[KBTS_FONT_INFO_STRING_ID_COUNT]; + + kbts_font_style_flags StyleFlags; + kbts_font_weight Weight; + kbts_font_width Width; +} kbts_font_info; + +typedef struct kbts_feature_override +{ + kbts_feature_tag Tag; + int Value; +} kbts_feature_override; + +typedef struct kbts_break +{ + // The break code mostly works in relative positions, but we convert to absolute positions for the user. + // That way, breaks can be trivially stored and compared and such and it just works. + int Position; + kbts_break_flags Flags; + kbts_direction Direction; // Only valid if (Flags & KBTS_BREAK_FLAG_DIRECTION). + kbts_direction ParagraphDirection; // Only valid if (Flags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION). + kbts_script Script; // Only valid if (Flags & KBTS_BREAK_FLAG_SCRIPT). +} kbts_break; + +typedef struct kbts_bracket +{ + kbts_u32 Codepoint; + kbts_u32 Position; + kbts_u8 Direction; + kbts_u8 Script; +} kbts_bracket; + +// In the worst case, a single call to BreakAddCodepoint would generate 4 breaks. +// We buffer breaks to reorder them before returning them to the user. +// This potentially requires infinite memory, which we don't have, so you may want to tweak this constant, +// although, really, if the defaults don't work, then you have likely found very strange/adversarial text. +typedef struct kbts_break_state +{ + kbts_break Breaks[8]; + kbts_u32 BreakCount; + + kbts_direction ParagraphDirection; + kbts_direction UserParagraphDirection; + + kbts_u32 CurrentPosition; + kbts_u32 ParagraphStartPosition; + + kbts_u32 LastScriptBreakPosition; + kbts_u32 LastDirectionBreakPosition; + kbts_u8 LastScriptBreakScript; + kbts_u8 LastDirectionBreakDirection; + + kbts_s16 ScriptPositionOffset; + kbts_u32 ScriptCount; + kbts_u8 ScriptSet[KBTS_MAXIMUM_CODEPOINT_SCRIPTS]; + + kbts_bracket Brackets[64]; + kbts_u32 BracketCount; + kbts_break_state_flags Flags; + + kbts_u32 FlagState; // u8(kbts_break_flags)x4 + kbts_s16 PositionOffset2; + kbts_s16 PositionOffset3; + + kbts_u32 WordBreakHistory; // u8x4 + kbts_u16 WordBreaks; // u4x4 + kbts_u16 WordUnbreaks; // u4x4 + kbts_s16 WordBreak2PositionOffset; + + kbts_u64 LineBreaks; // u16x4 + // Instead of staying synchronized with LineBreaks/LineUnbreaks, + // this advances every character always. + // (This is only needed because ZWJ can create an unbreak while simultaneously being ignored.) + kbts_u64 LineUnbreaksAsync; // u16x4 + kbts_u64 LineUnbreaks; // u16x4 + kbts_u32 LineBreakHistory; // u8(line_break_class)x4 + kbts_s16 LineBreak2PositionOffset; + kbts_s16 LineBreak3PositionOffset; + + kbts_u8 LastDirection; + kbts_u8 BidirectionalClass2; + kbts_u8 BidirectionalClass1; + kbts_s16 Bidirectional1PositionOffset; + kbts_s16 Bidirectional2PositionOffset; + + kbts_japanese_line_break_style JapaneseLineBreakStyle; + kbts_break_config_flags ConfigFlags; + kbts_u8 GraphemeBreakState; + kbts_u8 LastLineBreakClass; + kbts_u8 LastWordBreakClass; + kbts_u8 LastWordBreakClassIncludingIgnored; +} kbts_break_state; + +typedef struct kbts_decode +{ + int Codepoint; + + int SourceCharactersConsumed; + int Valid; +} kbts_decode; + +typedef struct kbts_encode_utf8 +{ + char Encoded[4]; + int EncodedLength; + int Valid; +} kbts_encode_utf8; + +typedef struct kbts_glyph_classes +{ + kbts_u16 Class; + kbts_u16 MarkAttachmentClass; +} kbts_glyph_classes; + +typedef struct kbts_glyph +{ + kbts_glyph *Prev; + kbts_glyph *Next; + + kbts_u32 Codepoint; + kbts_u16 Id; // Glyph index. This is what you want to use to query outline data. + kbts_u16 Uid; + + // This field is kept and returned as-is throughout the shaping process. + // When you are using the context API, it contains a codepoint index always! + // To get the original user ID with the context API, you need to get the corresponding kbts_shape_codepoint + // with kbts_ShapeGetShapeCodepoint(Context, Glyph->UserIdOrCodepointIndex, ...); + int UserIdOrCodepointIndex; + + // Used by GPOS + kbts_s32 OffsetX; + kbts_s32 OffsetY; + kbts_s32 AdvanceX; + kbts_s32 AdvanceY; + + // Earlier on, we used to assume that, if a glyph had no advance, or had the MARK glyph class, then + // it could be handled as a mark in layout operations. This is inaccurate. + // Unicode makes a distinction between attached marks and standalone marks. For our purposes, attached + // marks are marks that have found a valid base character to attach to. In practice, this means that the + // font contains a valid display position/configuration for it in the current context. + // In contrast, standalone marks are marks that aren't attached to anything. Fonts may still have glyphs + // for them, in which case we want to display those just like regular glyphs that take up horizontal space + // on the line. When fonts don't have glyphs for them, they simply stay around as zero-width glyphs. + // Standalone marks have notably different behavior compared to attached marks, and so, once we start + // applying positioning features, it becomes worthwhile to track exactly which glyph has attached to which. + struct kbts_glyph *AttachGlyph; // Set by GPOS attachments. + + kbts_glyph_config *Config; + + kbts_u64 Decomposition; + + kbts_glyph_classes Classes; + + kbts_glyph_flags Flags; + + kbts_u32 ParentInfo; + + // This is set by GSUB and used by GPOS. + // A 0-index means that we should attach to the last component in the ligature. + // + // From the Microsoft docs: + // To correctly access the subtables, the client must keep track of the component associated with the mark. + // + // For a given mark assigned to a particular class, the appropriate base attachment point is determined by which + // ligature component the mark is associated with. This is dependent on the original character string and subsequent + // character- or glyph-sequence processing, not the font data alone. While a text-layout client is performing any + // character-based preprocessing or any glyph-substitution operations using the GSUB table, the text-layout client + // must keep track of associations of marks to particular ligature-glyph components. + kbts_u16 LigatureUid; + kbts_u16 LigatureComponentIndexPlusOne; + kbts_u16 LigatureComponentCount; + + // Set in GSUB and used in GPOS, for STCH. + kbts_joining_feature JoiningFeature; + + // Unicode properties filled in by CodepointToGlyph. + kbts_unicode_joining_type JoiningType; + kbts_u8 UnicodeFlags; + kbts_u8 SyllabicClass; + kbts_u8 SyllabicPosition; + kbts_u8 UseClass; + kbts_u8 CombiningClass; + + kbts_u8 MarkOrdering; // Only used temporarily in NORMALIZE for Arabic mark reordering. +} kbts_glyph; + +typedef struct kbts_shape_codepoint +{ + kbts_font *Font; // Only set when (BreakFlags & KBTS_BREAK_FLAG_GRAPHEME) != 0. + kbts_glyph_config *Config; + + int Codepoint; + int UserId; + + kbts_break_flags BreakFlags; + kbts_script Script; // Only set when (BreakFlags & KBTS_BREAK_FLAG_SCRIPT) != 0. + kbts_direction Direction; // Only set when (BreakFlags & KBTS_BREAK_FLAG_DIRECTION) != 0. + kbts_direction ParagraphDirection; // Only set when (BreakFlags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) != 0. +} kbts_shape_codepoint; + +typedef struct kbts_shape_codepoint_iterator +{ + kbts_shape_codepoint *Codepoint; + kbts_shape_context *Context; + + kbts_u32 EndBlockIndex; + kbts_u32 OnePastLastCodepointIndex; + kbts_u32 BlockIndex; + kbts_u32 CodepointIndex; + kbts_u32 CurrentBlockCodepointCount; + kbts_u32 FlatCodepointIndex; +} kbts_shape_codepoint_iterator; + +typedef struct kbts_glyph_iterator +{ + kbts_glyph_storage *GlyphStorage; + kbts_glyph *CurrentGlyph; + + int LastAdvanceX; + int X; + int Y; +} kbts_glyph_iterator; + +typedef struct kbts_arena_block_header +{ + struct kbts_arena_block_header *Prev; + struct kbts_arena_block_header *Next; +} kbts_arena_block_header; + +typedef struct kbts_arena +{ + kbts_allocator_function *Allocator; + void *AllocatorData; + + kbts_arena_block_header BlockSentinel; + kbts_arena_block_header FreeBlockSentinel; + + int Error; +} kbts_arena; + +typedef struct kbts_glyph_storage +{ + kbts_arena Arena; + + kbts_glyph GlyphSentinel; + kbts_glyph FreeGlyphSentinel; + + int Error; +} kbts_glyph_storage; + +typedef struct kbts_glyph_parent +{ + kbts_u64 Decomposition; + kbts_u32 Codepoint; +} kbts_glyph_parent; + +typedef struct kbts_font_coverage_test +{ + kbts_font *Font; + kbts_u32 BaseCodepoint; + + int CurrentBaseError; + int Error; + + kbts_glyph_parent BaseParents[KBTS_MAXIMUM_RECOMPOSITION_PARENTS]; + kbts_u32 BaseParentCount; +} kbts_font_coverage_test; + +typedef struct kbts_run +{ + kbts_font *Font; + kbts_script Script; + kbts_direction ParagraphDirection; + kbts_direction Direction; + kbts_break_flags Flags; + + kbts_glyph_iterator Glyphs; +} kbts_run; + +// +// Context API +// The context can do everything for you. It is pretty convenient! +// + +KBTS_EXPORT int kbts_SizeOfShapeContext(void); +KBTS_EXPORT kbts_shape_context *kbts_PlaceShapeContext(kbts_allocator_function *Allocator, void *AllocatorData, void *Memory); +KBTS_EXPORT kbts_shape_context *kbts_PlaceShapeContextFixedMemory(void *Memory, int Size); +KBTS_EXPORT kbts_shape_context *kbts_CreateShapeContext(kbts_allocator_function *Allocator, void *AllocatorData); +KBTS_EXPORT void kbts_DestroyShapeContext(kbts_shape_context *Context); +#ifndef KB_TEXT_SHAPE_NO_CRT +KBTS_EXPORT kbts_font *kbts_ShapePushFontFromFile(kbts_shape_context *Context, const char *FileName, int FontIndex); +#endif +KBTS_EXPORT kbts_font *kbts_ShapePushFontFromMemory(kbts_shape_context *Context, void *Memory, int Size, int FontIndex); +KBTS_EXPORT kbts_font *kbts_ShapePushFont(kbts_shape_context *Context, kbts_font *Font); +KBTS_EXPORT kbts_font *kbts_ShapePopFont(kbts_shape_context *Context); +KBTS_EXPORT void kbts_ShapeBegin(kbts_shape_context *Context, kbts_direction ParagraphDirection, kbts_language Language); +KBTS_EXPORT void kbts_ShapeEnd(kbts_shape_context *Context); +KBTS_EXPORT int kbts_ShapeRun(kbts_shape_context *Context, kbts_run *Run); +KBTS_EXPORT void kbts_ShapePushFeature(kbts_shape_context *Context, kbts_u32 FeatureTag, int Value); +KBTS_EXPORT int kbts_ShapePopFeature(kbts_shape_context *Context, kbts_u32 FeatureTag); +KBTS_EXPORT void kbts_ShapeCodepoint(kbts_shape_context *Context, int Codepoint); +KBTS_EXPORT void kbts_ShapeCodepointWithUserId(kbts_shape_context *Context, int Codepoint, int UserId); +KBTS_EXPORT void kbts_ShapeUtf32(kbts_shape_context *Context, int *Utf32, int Length); +KBTS_EXPORT void kbts_ShapeUtf32WithUserId(kbts_shape_context *Context, int *Utf32, int Length, int UserId, int UserIdIncrement); +KBTS_EXPORT void kbts_ShapeUtf8(kbts_shape_context *Context, const char *Utf8, int Length, kbts_user_id_generation_mode UserIdGenerationMode); +KBTS_EXPORT void kbts_ShapeUtf8WithUserId(kbts_shape_context *Context, const char *Utf8, int Length, int UserId, kbts_user_id_generation_mode UserIdGenerationMode); +KBTS_EXPORT kbts_shape_error kbts_ShapeError(kbts_shape_context *Context); +KBTS_EXPORT void kbts_ShapeBeginManualRuns(kbts_shape_context *Context); +KBTS_EXPORT void kbts_ShapeNextManualRun(kbts_shape_context *Context, kbts_direction Direction, kbts_script Script); +KBTS_EXPORT void kbts_ShapeEndManualRuns(kbts_shape_context *Context); +KBTS_EXPORT void kbts_ShapeManualBreak(kbts_shape_context *Context); +KBTS_EXPORT kbts_shape_codepoint_iterator kbts_ShapeCurrentCodepointsIterator(kbts_shape_context *Context); +KBTS_EXPORT int kbts_ShapeCodepointIteratorIsValid(kbts_shape_codepoint_iterator *It); +KBTS_EXPORT int kbts_ShapeCodepointIteratorNext(kbts_shape_codepoint_iterator *It, kbts_shape_codepoint *Codepoint, int *CodepointIndex); +KBTS_EXPORT int kbts_ShapeGetShapeCodepoint(kbts_shape_context *Context, int CodepointIndex, kbts_shape_codepoint *Codepoint); + +// +// Direct API +// + +KBTS_EXPORT kbts_shape_error kbts_ShapeDirect(kbts_shape_config *Config, kbts_glyph_storage *Storage, kbts_direction RunDirection, kbts_allocator_function *Allocator, void *AllocatorData, kbts_glyph_iterator *Output); +KBTS_EXPORT kbts_shape_error kbts_ShapeDirectFixedMemory(kbts_shape_config *Config, kbts_glyph_storage *Storage, kbts_direction RunDirection, void *Memory, int MemorySize, kbts_glyph_iterator *Output); + +// A font holds all data that corresponds to a given font file. +#ifndef KB_TEXT_SHAPE_NO_CRT +KBTS_EXPORT kbts_font kbts_FontFromFile(const char *FileName, int FontIndex, kbts_allocator_function *Allocator, void *AllocatorData, void **FileData, int *FileSize); +#endif +KBTS_EXPORT int kbts_FontCount(void *FileData, int FileSize); +KBTS_EXPORT kbts_font kbts_FontFromMemory(void *FileData, int FileSize, int FontIndex, kbts_allocator_function *Allocator, void *AllocatorData); +KBTS_EXPORT void kbts_FreeFont(kbts_font *Font); +KBTS_EXPORT int kbts_FontIsValid(kbts_font *Font); +KBTS_EXPORT kbts_load_font_error kbts_LoadFont(kbts_font *Font, kbts_load_font_state *State, void *FontData, int FontDataSize, int FontIndex, int *ScratchSize_, int *OutputSize_); +KBTS_EXPORT kbts_load_font_error kbts_PlaceBlob(kbts_font *Font, kbts_load_font_state *State, void *ScratchMemory, void *OutputMemory); +KBTS_EXPORT void kbts_GetFontInfo(kbts_font *Font, kbts_font_info *Info); + +// A shape_config is a bag of pre-computed data for a specific shaping setup. +KBTS_EXPORT int kbts_SizeOfShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language); +KBTS_EXPORT kbts_shape_config *kbts_PlaceShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, void *Memory); +KBTS_EXPORT kbts_shape_config *kbts_CreateShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, kbts_allocator_function *Allocator, void *AllocatorData); +KBTS_EXPORT void kbts_DestroyShapeConfig(kbts_shape_config *Config); + +// A glyph_storage holds and recycles glyph data. +KBTS_EXPORT int kbts_InitializeGlyphStorage(kbts_glyph_storage *Storage, kbts_allocator_function *Allocator, void *AllocatorData); +KBTS_EXPORT int kbts_InitializeGlyphStorageFixedMemory(kbts_glyph_storage *Storage, void *Memory, int MemorySize); +KBTS_EXPORT kbts_glyph *kbts_PushGlyph(kbts_glyph_storage *Storage, kbts_font *Font, int Codepoint, kbts_glyph_config *Config, int UserId); +KBTS_EXPORT void kbts_ClearActiveGlyphs(kbts_glyph_storage *Storage); +KBTS_EXPORT void kbts_FreeAllGlyphs(kbts_glyph_storage *Storage); +KBTS_EXPORT kbts_glyph kbts_CodepointToGlyph(kbts_font *Font, int Codepoint, kbts_glyph_config *Config, int UserId); +KBTS_EXPORT int kbts_CodepointToGlyphId(kbts_font *Font, int Codepoint); +KBTS_EXPORT kbts_glyph_iterator kbts_ActiveGlyphIterator(kbts_glyph_storage *Storage); + +// A glyph_config specifies glyph-specific shaping parameters. +// A single glyph_config can be shared by multiple glyphs. +KBTS_EXPORT int kbts_SizeOfGlyphConfig(kbts_feature_override *Overrides, int OverrideCount); +KBTS_EXPORT kbts_glyph_config *kbts_PlaceGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, void *Memory); +KBTS_EXPORT kbts_glyph_config *kbts_CreateGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, kbts_allocator_function *Allocator, void *AllocatorData); +KBTS_EXPORT void kbts_DestroyGlyphConfig(kbts_glyph_config *Config); + +// +// Glyph iterator +// + +KBTS_EXPORT int kbts_GlyphIteratorNext(kbts_glyph_iterator *It, kbts_glyph **Glyph); +KBTS_EXPORT int kbts_GlyphIteratorIsValid(kbts_glyph_iterator *It); + +// +// Segmentation +// + +// This is a quick guess that stops at the first glyph that has a strong script/direction associated to it. +// It is convenient, but only works if you are sure your input text is mono-script and mono-direction. +KBTS_EXPORT void kbts_GuessTextProperties(void *Text, int TextSizeInBytes, kbts_text_format Format, kbts_direction *Direction, kbts_script *Script); +KBTS_EXPORT void kbts_GuessTextPropertiesUtf32(const int *Utf32, int Utf32Count, kbts_direction *Direction, kbts_script *Script); +KBTS_EXPORT void kbts_GuessTextPropertiesUtf8(const char *Utf8, int Utf8Length, kbts_direction *Direction, kbts_script *Script); + +KBTS_EXPORT void kbts_BreakBegin(kbts_break_state *State, kbts_direction ParagraphDirection, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags); +KBTS_EXPORT void kbts_BreakAddCodepoint(kbts_break_state *State, int Codepoint, int PositionIncrement, int EndOfText); +KBTS_EXPORT void kbts_BreakEnd(kbts_break_state *State); +KBTS_EXPORT int kbts_Break(kbts_break_state *State, kbts_break *Break); +KBTS_EXPORT void kbts_BreakEntireString(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, const void *Input, int InputSizeInBytes, kbts_text_format InputFormat, kbts_break *Breaks, int BreakCapacity, int *BreakCount, kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount); +KBTS_EXPORT void kbts_BreakEntireStringUtf32(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, const int *Utf32, int Utf32Count, kbts_break *Breaks, int BreakCapacity, int *BreakCount, kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount); +KBTS_EXPORT void kbts_BreakEntireStringUtf8(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, const char *Utf8, int Utf8Length, kbts_break *Breaks, int BreakCapacity, int *BreakCount, kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount); + +// +// Other stuff +// + +// Quick test for font support of a sequence of codepoints. +KBTS_EXPORT void kbts_FontCoverageTestBegin(kbts_font_coverage_test *Test, kbts_font *Font); +KBTS_EXPORT void kbts_FontCoverageTestCodepoint(kbts_font_coverage_test *Test, int Codepoint); +KBTS_EXPORT int kbts_FontCoverageTestEnd(kbts_font_coverage_test *Test); + +KBTS_EXPORT kbts_decode kbts_DecodeUtf8(const char *Utf8, kbts_un Length); +KBTS_EXPORT kbts_encode_utf8 kbts_EncodeUtf8(int Codepoint); +KBTS_EXPORT kbts_direction kbts_ScriptDirection(kbts_script Script); +KBTS_EXPORT int kbts_ScriptIsComplex(kbts_script Script); +KBTS_EXPORT kbts_script kbts_ScriptTagToScript(kbts_script_tag Tag); + +#endif + +#ifdef KB_TEXT_SHAPE_IMPLEMENTATION +#ifdef _MSC_VER +#define KBTS__UNUSED(X) (void)sizeof((X)) +#else +#define KBTS__UNUSED(X) (void)(X) +#endif +# define KBTS__FOR(I, Start, End) for(kbts_un I = (Start); I < (End); ++I) +# ifdef __cplusplus +# define KBTS__ZERO {} +# define KBTS__ZERO_TYPE(T) T{} +# else +# define KBTS__ZERO {0} +# define KBTS__ZERO_TYPE(T) (T){0} +# endif +# define KBTS__MAX(A, B) (((A) < (B)) ? (B) : (A)) +# define KBTS__MIN(A, B) (((A) < (B)) ? (A) : (B)) +# define KBTS__ARRAY_LENGTH(A) (sizeof(A)/sizeof(*(A))) +# define KBTS__POINTER_AFTER(Type, X) ((Type *)((X) + 1)) +# define KBTS__POINTER_OFFSET(Type, Base, Offset) ((Type *)((char *)(Base) + (Offset))) +# define KBTS__POINTER_DIFF32(Pointer, Base) ((kbts_u32)((char *)(Pointer) - (char *)(Base))) +# define KBTS__POINTER_DIFF(Pointer, Base) ((kbts_un)((char *)(Pointer) - (char *)(Base))) +# define KBTS__ALIGN_POINTER(Type, Pointer, Align) (Type *)(((kbts_un)(Pointer) + ((Align) - 1)) & ~((Align) - 1)) +# define KBTS__PASTE_1(A, B) A##B +# define KBTS__PASTE_0(A, B) KBTS__PASTE_1(A, B) +# define KBTS__PASTE(A, B) KBTS__PASTE_0(A, B) +# define KBTS__IN_SET(X, Set) ((1u << (X)) & (Set)) +# define KBTS__SET32_0(Arg) | (1u << (Arg)) KBTS__SET32_1 +# define KBTS__SET32_1(Arg) | (1u << (Arg)) KBTS__SET32_0 +# define KBTS__SET32_0End +# define KBTS__SET32_1End +# define KBTS__SET32(Args) (0u KBTS__PASTE(KBTS__SET32_0 Args, End)) +# define KBTS__IN_SET64(X, Set) ((1ull << (X)) & (Set)) +# define KBTS__SET64_0(Arg) | (1ull << (Arg)) KBTS__SET64_1 +# define KBTS__SET64_1(Arg) | (1ull << (Arg)) KBTS__SET64_0 +# define KBTS__SET64_0End +# define KBTS__SET64_1End +# define KBTS__SET64(Args) (0u KBTS__PASTE(KBTS__SET64_0 Args, End)) +#define KBTS__U32BE(X) kbts__ByteSwap32((X)) +#define KBTS__U32LE(X) (X) + +#define KBTS_LOOKUP_STACK_SIZE 64 + +# ifndef KBTS_ASSERT +#ifndef KB_TEXT_SHAPE_NO_CRT +# include +# define KBTS_ASSERT(Cond) assert(Cond) +#else +#define KBTS_ASSERT(Cond) +#endif +# endif + +#ifndef KB_TEXT_SHAPE_NO_CRT +#include +#endif + +#ifndef KBTS_MEMSET +#include +#define KBTS_MEMSET memset +#endif + +#ifndef KBTS_MEMCPY +#include +#define KBTS_MEMCPY memcpy +#endif + +#ifndef KB_TEXT_SHAPE_NO_CRT +#ifndef KBTS_MALLOC +#include +#define KBTS_MALLOC(Data, Size) malloc((Size)) +#define KBTS_FREE(Data, Pointer) free((Pointer)) +#endif +#else +#ifndef KBTS_MALLOC +// Nerf the default allocator to a null allocator. +#define KBTS_MALLOC(Data, Size) 0 +#define KBTS_FREE(Data, Pointer) +#endif +#endif + +#ifndef kbts__ByteSwap16 +# if defined(_MSC_VER) && !defined(__clang__) +#include +KBTS_INLINE kbts_u16 kbts__ByteSwap16(kbts_u16 X) +{ + kbts_u16 Result = (kbts_u16)((X >> 8) | (X << 8)); + return Result; +} +KBTS_INLINE kbts_u32 kbts__ByteSwap32(kbts_u32 X) +{ + kbts_u32 Result = (X >> 24) | + ((X & 0xFF0000) >> 8) | + ((X & 0xFF00) << 8) | + ((X & 0xFF) << 24); + return Result; +} +# define kbts__PopCount32(X) (kbts_un)__popcnt(X) +# elif defined(__clang__) || defined(__GNUC__) +# define kbts__ByteSwap16(X) __builtin_bswap16(X) +# define kbts__ByteSwap32(X) __builtin_bswap32(X) +# define kbts__PopCount32(X) (kbts_un)__builtin_popcount(X) +# else +# error Unsupported compiler! +# endif +#endif + +#ifndef kbts__MsbPositionOrZero32 +# if defined(_MSC_VER) && !defined(__clang__) +#include +KBTS_INLINE kbts_u32 kbts__MsbPositionOrZero32(kbts_u32 X) +{ + unsigned long Result; + if(!_BitScanReverse(&Result, X)) + { + Result = 0; + } + return (kbts_u32)Result; +} +# elif defined(__clang__) || defined(__GNUC__) +KBTS_INLINE kbts_u32 kbts__MsbPositionOrZero32(kbts_u32 X) +{ + kbts_u32 Result = 0; + if(X) + { + Result = 31 - __builtin_clz(X); + } + return Result; +} +# else +# error Unsupported compiler! +# endif +#endif + +#define KBTS__FEATURE_FLAG0(Feature) (1ull << KBTS__FEATURE_ID_##Feature) +#define KBTS__FEATURE_FLAG1(Feature) (1ull << (KBTS__FEATURE_ID_##Feature - 64)) +#define KBTS__FEATURE_FLAG2(Feature) (1ull << (KBTS__FEATURE_ID_##Feature - 128)) +#define KBTS__FEATURE_FLAG3(Feature) (1ull << (KBTS__FEATURE_ID_##Feature - 192)) + +// #define KBTS_SANITY_CHECK +// #define KBTS_DUMP + +# ifdef KBTS_DUMP +# define KBTS_DUMPF(...) printf(__VA_ARGS__), fflush(stdout) +# else +# define KBTS_DUMPF(...) +# endif + +#ifndef KBTS_INSTRUMENT_BLOCK_BEGIN +#define KBTS_INSTRUMENT_BLOCK_BEGIN(Name) +#define KBTS_INSTRUMENT_BLOCK_END(Name) +#define KBTS_INSTRUMENT_FUNCTION_BEGIN +#define KBTS_INSTRUMENT_FUNCTION_END +#endif + +#define KBTS__GLYPH_FEATURE_MASK ((KBTS_GLYPH_FLAG_CFAR << 1) - 1) +// In USE, glyphs are mostly not pre-flagged for feature application. +// However, we do want to flag rphf/pref results for reordering, so we want to +// keep all of the flags as usual, and only use these feature flags for filtering. +#define KBTS__USE_GLYPH_FEATURE_MASK (KBTS_GLYPH_FLAG_ISOL | KBTS_GLYPH_FLAG_FINA | KBTS_GLYPH_FLAG_FIN2 | KBTS_GLYPH_FLAG_FIN3 | \ + KBTS_GLYPH_FLAG_MEDI | KBTS_GLYPH_FLAG_MED2 | KBTS_GLYPH_FLAG_INIT | KBTS_GLYPH_FLAG_NUMR | \ + KBTS_GLYPH_FLAG_DNOM | KBTS_GLYPH_FLAG_FRAC) +#define KBTS__JOINING_FEATURE_MASK (KBTS_GLYPH_FLAG_ISOL | KBTS_GLYPH_FLAG_FINA | KBTS_GLYPH_FLAG_FIN2 | KBTS_GLYPH_FLAG_FIN3 | \ + KBTS_GLYPH_FLAG_MEDI | KBTS_GLYPH_FLAG_MED2 | KBTS_GLYPH_FLAG_INIT) +#define KBTS__JOINING_FEATURE_TO_GLYPH_FLAG(Feature) (1 << ((Feature) - 1)) + +typedef kbts_u8 kbts__reph_position; +enum kbts__reph_position_enum +{ + KBTS__REPH_POSITION_AFTER_POST, + KBTS__REPH_POSITION_BEFORE_POST, + KBTS__REPH_POSITION_BEFORE_SUBJOINED, + KBTS__REPH_POSITION_AFTER_SUBJOINED, + KBTS__REPH_POSITION_AFTER_MAIN, + + KBTS__REPH_POSITION_COUNT, +}; + +typedef kbts_u8 kbts__reph_encoding; +enum kbts__reph_encoding_enum +{ + KBTS__REPH_ENCODING_IMPLICIT, + KBTS__REPH_ENCODING_EXPLICIT, + KBTS__REPH_ENCODING_LOGICAL_REPHA, + KBTS__REPH_ENCODING_VISUAL_REPHA, + + KBTS__REPH_ENCODING_COUNT, +}; + +typedef kbts_u8 kbts__syllabic_position; +enum kbts__syllabic_position_enum +{ + KBTS__SYLLABIC_POSITION_NONE, + + KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH, + + KBTS__SYLLABIC_POSITION_PREBASE_MATRA, + KBTS__SYLLABIC_POSITION_PREBASE_CONSONANT, + + KBTS__SYLLABIC_POSITION_SYLLABLE_BASE, + KBTS__SYLLABIC_POSITION_AFTER_MAIN, + + KBTS__SYLLABIC_POSITION_ABOVEBASE_CONSONANT, + + KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED, + KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT, + KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED, + + KBTS__SYLLABIC_POSITION_BEFORE_POST, + KBTS__SYLLABIC_POSITION_POSTBASE_CONSONANT, + KBTS__SYLLABIC_POSITION_AFTER_POST, + + KBTS__SYLLABIC_POSITION_FINAL_CONSONANT, + KBTS__SYLLABIC_POSITION_SMVD, + + KBTS__SYLLABIC_POSITION_COUNT, +}; + + +typedef kbts_u32 kbts__feature_id; +enum kbts__feature_id_enum +{ + KBTS__FEATURE_ID_UNREGISTERED, // Features that aren't pre-defined in the OpenType spec + KBTS__FEATURE_ID_isol, // Isolated Forms + KBTS__FEATURE_ID_fina, // Terminal Forms + KBTS__FEATURE_ID_fin2, // Terminal Forms #2 + KBTS__FEATURE_ID_fin3, // Terminal Forms #3 + KBTS__FEATURE_ID_medi, // Medial Forms + KBTS__FEATURE_ID_med2, // Medial Forms #2 + KBTS__FEATURE_ID_init, // Initial Forms + KBTS__FEATURE_ID_ljmo, // Leading Jamo Forms + KBTS__FEATURE_ID_vjmo, // Vowel Jamo Forms + KBTS__FEATURE_ID_tjmo, // Trailing Jamo Forms + KBTS__FEATURE_ID_rphf, // Reph Form + KBTS__FEATURE_ID_blwf, // Below-base Forms + KBTS__FEATURE_ID_half, // Half Forms + KBTS__FEATURE_ID_pstf, // Post-base Forms + KBTS__FEATURE_ID_abvf, // Above-base Forms + KBTS__FEATURE_ID_pref, // Pre-base Forms + KBTS__FEATURE_ID_numr, // Numerators + KBTS__FEATURE_ID_frac, // Fractions + KBTS__FEATURE_ID_dnom, // Denominators + KBTS__FEATURE_ID_cfar, // Conjunct Form After Ro + KBTS__FEATURE_ID_aalt, // Access All Alternates + KBTS__FEATURE_ID_abvm, // Above-base Mark Positioning + KBTS__FEATURE_ID_abvs, // Above-base Substitutions + KBTS__FEATURE_ID_afrc, // Alternative Fractions + KBTS__FEATURE_ID_akhn, // Akhand + KBTS__FEATURE_ID_apkn, // Kerning for Alternate Proportional Widths + KBTS__FEATURE_ID_blwm, // Below-base Mark Positioning + KBTS__FEATURE_ID_blws, // Below-base Substitutions + KBTS__FEATURE_ID_calt, // Contextual Alternates + KBTS__FEATURE_ID_case, // Case-sensitive Forms + KBTS__FEATURE_ID_ccmp, // Glyph Composition / Decomposition + KBTS__FEATURE_ID_chws, // Contextual Half-width Spacing + KBTS__FEATURE_ID_cjct, // Conjunct Forms + KBTS__FEATURE_ID_clig, // Contextual Ligatures + KBTS__FEATURE_ID_cpct, // Centered CJK Punctuation + KBTS__FEATURE_ID_cpsp, // Capital Spacing + KBTS__FEATURE_ID_cswh, // Contextual Swash + KBTS__FEATURE_ID_curs, // Cursive Positioning + KBTS__FEATURE_ID_cv01, // Character Variant 1 + KBTS__FEATURE_ID_cv02, // Character Variant 2 + KBTS__FEATURE_ID_cv03, // Character Variant 3 + KBTS__FEATURE_ID_cv04, // Character Variant 4 + KBTS__FEATURE_ID_cv05, // Character Variant 5 + KBTS__FEATURE_ID_cv06, // Character Variant 6 + KBTS__FEATURE_ID_cv07, // Character Variant 7 + KBTS__FEATURE_ID_cv08, // Character Variant 8 + KBTS__FEATURE_ID_cv09, // Character Variant 9 + KBTS__FEATURE_ID_cv10, // Character Variant 10 + KBTS__FEATURE_ID_cv11, // Character Variant 11 + KBTS__FEATURE_ID_cv12, // Character Variant 12 + KBTS__FEATURE_ID_cv13, // Character Variant 13 + KBTS__FEATURE_ID_cv14, // Character Variant 14 + KBTS__FEATURE_ID_cv15, // Character Variant 15 + KBTS__FEATURE_ID_cv16, // Character Variant 16 + KBTS__FEATURE_ID_cv17, // Character Variant 17 + KBTS__FEATURE_ID_cv18, // Character Variant 18 + KBTS__FEATURE_ID_cv19, // Character Variant 19 + KBTS__FEATURE_ID_cv20, // Character Variant 20 + KBTS__FEATURE_ID_cv21, // Character Variant 21 + KBTS__FEATURE_ID_cv22, // Character Variant 22 + KBTS__FEATURE_ID_cv23, // Character Variant 23 + KBTS__FEATURE_ID_cv24, // Character Variant 24 + KBTS__FEATURE_ID_cv25, // Character Variant 25 + KBTS__FEATURE_ID_cv26, // Character Variant 26 + KBTS__FEATURE_ID_cv27, // Character Variant 27 + KBTS__FEATURE_ID_cv28, // Character Variant 28 + KBTS__FEATURE_ID_cv29, // Character Variant 29 + KBTS__FEATURE_ID_cv30, // Character Variant 30 + KBTS__FEATURE_ID_cv31, // Character Variant 31 + KBTS__FEATURE_ID_cv32, // Character Variant 32 + KBTS__FEATURE_ID_cv33, // Character Variant 33 + KBTS__FEATURE_ID_cv34, // Character Variant 34 + KBTS__FEATURE_ID_cv35, // Character Variant 35 + KBTS__FEATURE_ID_cv36, // Character Variant 36 + KBTS__FEATURE_ID_cv37, // Character Variant 37 + KBTS__FEATURE_ID_cv38, // Character Variant 38 + KBTS__FEATURE_ID_cv39, // Character Variant 39 + KBTS__FEATURE_ID_cv40, // Character Variant 40 + KBTS__FEATURE_ID_cv41, // Character Variant 41 + KBTS__FEATURE_ID_cv42, // Character Variant 42 + KBTS__FEATURE_ID_cv43, // Character Variant 43 + KBTS__FEATURE_ID_cv44, // Character Variant 44 + KBTS__FEATURE_ID_cv45, // Character Variant 45 + KBTS__FEATURE_ID_cv46, // Character Variant 46 + KBTS__FEATURE_ID_cv47, // Character Variant 47 + KBTS__FEATURE_ID_cv48, // Character Variant 48 + KBTS__FEATURE_ID_cv49, // Character Variant 49 + KBTS__FEATURE_ID_cv50, // Character Variant 50 + KBTS__FEATURE_ID_cv51, // Character Variant 51 + KBTS__FEATURE_ID_cv52, // Character Variant 52 + KBTS__FEATURE_ID_cv53, // Character Variant 53 + KBTS__FEATURE_ID_cv54, // Character Variant 54 + KBTS__FEATURE_ID_cv55, // Character Variant 55 + KBTS__FEATURE_ID_cv56, // Character Variant 56 + KBTS__FEATURE_ID_cv57, // Character Variant 57 + KBTS__FEATURE_ID_cv58, // Character Variant 58 + KBTS__FEATURE_ID_cv59, // Character Variant 59 + KBTS__FEATURE_ID_cv60, // Character Variant 60 + KBTS__FEATURE_ID_cv61, // Character Variant 61 + KBTS__FEATURE_ID_cv62, // Character Variant 62 + KBTS__FEATURE_ID_cv63, // Character Variant 63 + KBTS__FEATURE_ID_cv64, // Character Variant 64 + KBTS__FEATURE_ID_cv65, // Character Variant 65 + KBTS__FEATURE_ID_cv66, // Character Variant 66 + KBTS__FEATURE_ID_cv67, // Character Variant 67 + KBTS__FEATURE_ID_cv68, // Character Variant 68 + KBTS__FEATURE_ID_cv69, // Character Variant 69 + KBTS__FEATURE_ID_cv70, // Character Variant 70 + KBTS__FEATURE_ID_cv71, // Character Variant 71 + KBTS__FEATURE_ID_cv72, // Character Variant 72 + KBTS__FEATURE_ID_cv73, // Character Variant 73 + KBTS__FEATURE_ID_cv74, // Character Variant 74 + KBTS__FEATURE_ID_cv75, // Character Variant 75 + KBTS__FEATURE_ID_cv76, // Character Variant 76 + KBTS__FEATURE_ID_cv77, // Character Variant 77 + KBTS__FEATURE_ID_cv78, // Character Variant 78 + KBTS__FEATURE_ID_cv79, // Character Variant 79 + KBTS__FEATURE_ID_cv80, // Character Variant 80 + KBTS__FEATURE_ID_cv81, // Character Variant 81 + KBTS__FEATURE_ID_cv82, // Character Variant 82 + KBTS__FEATURE_ID_cv83, // Character Variant 83 + KBTS__FEATURE_ID_cv84, // Character Variant 84 + KBTS__FEATURE_ID_cv85, // Character Variant 85 + KBTS__FEATURE_ID_cv86, // Character Variant 86 + KBTS__FEATURE_ID_cv87, // Character Variant 87 + KBTS__FEATURE_ID_cv88, // Character Variant 88 + KBTS__FEATURE_ID_cv89, // Character Variant 89 + KBTS__FEATURE_ID_cv90, // Character Variant 90 + KBTS__FEATURE_ID_cv91, // Character Variant 91 + KBTS__FEATURE_ID_cv92, // Character Variant 92 + KBTS__FEATURE_ID_cv93, // Character Variant 93 + KBTS__FEATURE_ID_cv94, // Character Variant 94 + KBTS__FEATURE_ID_cv95, // Character Variant 95 + KBTS__FEATURE_ID_cv96, // Character Variant 96 + KBTS__FEATURE_ID_cv97, // Character Variant 97 + KBTS__FEATURE_ID_cv98, // Character Variant 98 + KBTS__FEATURE_ID_cv99, // Character Variant 99 + KBTS__FEATURE_ID_c2pc, // Petite Capitals From Capitals + KBTS__FEATURE_ID_c2sc, // Small Capitals From Capitals + KBTS__FEATURE_ID_dist, // Distances + KBTS__FEATURE_ID_dlig, // Discretionary Ligatures + KBTS__FEATURE_ID_dtls, // Dotless Forms + KBTS__FEATURE_ID_expt, // Expert Forms + KBTS__FEATURE_ID_falt, // Final Glyph on Line Alternates + KBTS__FEATURE_ID_flac, // Flattened Accent Forms + KBTS__FEATURE_ID_fwid, // Full Widths + KBTS__FEATURE_ID_haln, // Halant Forms + KBTS__FEATURE_ID_halt, // Alternate Half Widths + KBTS__FEATURE_ID_hist, // Historical Forms + KBTS__FEATURE_ID_hkna, // Horizontal Kana Alternates + KBTS__FEATURE_ID_hlig, // Historical Ligatures + KBTS__FEATURE_ID_hngl, // Hangul + KBTS__FEATURE_ID_hojo, // Hojo Kanji Forms (JIS X 0212-1990 Kanji Forms) + KBTS__FEATURE_ID_hwid, // Half Widths + KBTS__FEATURE_ID_ital, // Italics + KBTS__FEATURE_ID_jalt, // Justification Alternates + KBTS__FEATURE_ID_jp78, // JIS78 Forms + KBTS__FEATURE_ID_jp83, // JIS83 Forms + KBTS__FEATURE_ID_jp90, // JIS90 Forms + KBTS__FEATURE_ID_jp04, // JIS2004 Forms + KBTS__FEATURE_ID_kern, // Kerning + KBTS__FEATURE_ID_lfbd, // Left Bounds + KBTS__FEATURE_ID_liga, // Standard Ligatures + KBTS__FEATURE_ID_lnum, // Lining Figures + KBTS__FEATURE_ID_locl, // Localized Forms + KBTS__FEATURE_ID_ltra, // Left-to-right Alternates + KBTS__FEATURE_ID_ltrm, // Left-to-right Mirrored Forms + KBTS__FEATURE_ID_mark, // Mark Positioning + KBTS__FEATURE_ID_mgrk, // Mathematical Greek + KBTS__FEATURE_ID_mkmk, // Mark to Mark Positioning + KBTS__FEATURE_ID_mset, // Mark Positioning via Substitution + KBTS__FEATURE_ID_nalt, // Alternate Annotation Forms + KBTS__FEATURE_ID_nlck, // NLC Kanji Forms + KBTS__FEATURE_ID_nukt, // Nukta Forms + KBTS__FEATURE_ID_onum, // Oldstyle Figures + KBTS__FEATURE_ID_opbd, // Optical Bounds + KBTS__FEATURE_ID_ordn, // Ordinals + KBTS__FEATURE_ID_ornm, // Ornaments + KBTS__FEATURE_ID_palt, // Proportional Alternate Widths + KBTS__FEATURE_ID_pcap, // Petite Capitals + KBTS__FEATURE_ID_pkna, // Proportional Kana + KBTS__FEATURE_ID_pnum, // Proportional Figures + KBTS__FEATURE_ID_pres, // Pre-base Substitutions + KBTS__FEATURE_ID_psts, // Post-base Substitutions + KBTS__FEATURE_ID_pwid, // Proportional Widths + KBTS__FEATURE_ID_qwid, // Quarter Widths + KBTS__FEATURE_ID_rand, // Randomize + KBTS__FEATURE_ID_rclt, // Required Contextual Alternates + KBTS__FEATURE_ID_rkrf, // Rakar Forms + KBTS__FEATURE_ID_rlig, // Required Ligatures + KBTS__FEATURE_ID_rtbd, // Right Bounds + KBTS__FEATURE_ID_rtla, // Right-to-left Alternates + KBTS__FEATURE_ID_rtlm, // Right-to-left Mirrored Forms + KBTS__FEATURE_ID_ruby, // Ruby Notation Forms + KBTS__FEATURE_ID_rvrn, // Required Variation Alternates + KBTS__FEATURE_ID_salt, // Stylistic Alternates + KBTS__FEATURE_ID_sinf, // Scientific Inferiors + KBTS__FEATURE_ID_size, // Optical size + KBTS__FEATURE_ID_smcp, // Small Capitals + KBTS__FEATURE_ID_smpl, // Simplified Forms + KBTS__FEATURE_ID_ss01, // Stylistic Set 1 + KBTS__FEATURE_ID_ss02, // Stylistic Set 2 + KBTS__FEATURE_ID_ss03, // Stylistic Set 3 + KBTS__FEATURE_ID_ss04, // Stylistic Set 4 + KBTS__FEATURE_ID_ss05, // Stylistic Set 5 + KBTS__FEATURE_ID_ss06, // Stylistic Set 6 + KBTS__FEATURE_ID_ss07, // Stylistic Set 7 + KBTS__FEATURE_ID_ss08, // Stylistic Set 8 + KBTS__FEATURE_ID_ss09, // Stylistic Set 9 + KBTS__FEATURE_ID_ss10, // Stylistic Set 10 + KBTS__FEATURE_ID_ss11, // Stylistic Set 11 + KBTS__FEATURE_ID_ss12, // Stylistic Set 12 + KBTS__FEATURE_ID_ss13, // Stylistic Set 13 + KBTS__FEATURE_ID_ss14, // Stylistic Set 14 + KBTS__FEATURE_ID_ss15, // Stylistic Set 15 + KBTS__FEATURE_ID_ss16, // Stylistic Set 16 + KBTS__FEATURE_ID_ss17, // Stylistic Set 17 + KBTS__FEATURE_ID_ss18, // Stylistic Set 18 + KBTS__FEATURE_ID_ss19, // Stylistic Set 19 + KBTS__FEATURE_ID_ss20, // Stylistic Set 20 + KBTS__FEATURE_ID_ssty, // Math Script-style Alternates + KBTS__FEATURE_ID_stch, // Stretching Glyph Decomposition + KBTS__FEATURE_ID_subs, // Subscript + KBTS__FEATURE_ID_sups, // Superscript + KBTS__FEATURE_ID_swsh, // Swash + KBTS__FEATURE_ID_test, // Test features, only for development + KBTS__FEATURE_ID_titl, // Titling + KBTS__FEATURE_ID_tnam, // Traditional Name Forms + KBTS__FEATURE_ID_tnum, // Tabular Figures + KBTS__FEATURE_ID_trad, // Traditional Forms + KBTS__FEATURE_ID_twid, // Third Widths + KBTS__FEATURE_ID_unic, // Unicase + KBTS__FEATURE_ID_valt, // Alternate Vertical Metrics + KBTS__FEATURE_ID_vapk, // Kerning for Alternate Proportional Vertical Metrics + KBTS__FEATURE_ID_vatu, // Vattu Variants + KBTS__FEATURE_ID_vchw, // Vertical Contextual Half-width Spacing + KBTS__FEATURE_ID_vert, // Vertical Alternates + KBTS__FEATURE_ID_vhal, // Alternate Vertical Half Metrics + KBTS__FEATURE_ID_vkna, // Vertical Kana Alternates + KBTS__FEATURE_ID_vkrn, // Vertical Kerning + KBTS__FEATURE_ID_vpal, // Proportional Alternate Vertical Metrics + KBTS__FEATURE_ID_vrt2, // Vertical Alternates and Rotation + KBTS__FEATURE_ID_vrtr, // Vertical Alternates for Rotation + KBTS__FEATURE_ID_zero, // Slashed Zero + KBTS__FEATURE_ID_COUNT, +}; + +typedef struct kbts__feature_set +{ + kbts_u64 Flags[(KBTS__FEATURE_ID_COUNT + 63) / 64]; +} kbts__feature_set; +typedef kbts_u8 kbts__op_kind; +enum kbts__op_kind_enum +{ + KBTS__OP_KIND_END, + KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES, + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_NORMALIZE_HANGUL, + KBTS__OP_KIND_FLAG_JOINING_LETTERS, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, + KBTS__OP_KIND_STCH_POSTPASS, + KBTS__OP_KIND_BEGIN_CLUSTER, + KBTS__OP_KIND_END_CLUSTER, + KBTS__OP_KIND_END_SYLLABLE, + KBTS__OP_KIND_COUNT, +}; +typedef struct kbts__feature_stage +{ + kbts_u32 FeatureCount; + kbts__feature_set Features; +} kbts__feature_stage; +typedef struct kbts__op_list +{ + kbts_u32 TotalFeatureCount; + kbts_u32 FeatureStageCount; + kbts__feature_stage *FeatureStages; + kbts_u32 OpCount; + kbts__op_kind *Ops; +} kbts__op_list; +static kbts__op_kind kbts__Ops_Default[] = { + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Default[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {12, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom) | KBTS__FEATURE_FLAG0(ccmp) | KBTS__FEATURE_FLAG0(clig) | KBTS__FEATURE_FLAG0(calt), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm) | KBTS__FEATURE_FLAG2(locl) | KBTS__FEATURE_FLAG2(rlig) | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(rclt), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk) | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Default = {20, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Default), kbts__FeatureStages_Default, KBTS__ARRAY_LENGTH(kbts__Ops_Default), kbts__Ops_Default}; +static kbts__op_kind kbts__Ops_Hangul[] = { + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_NORMALIZE_HANGUL, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Hangul[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {14, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom) | KBTS__FEATURE_FLAG0(ljmo) | KBTS__FEATURE_FLAG0(vjmo) | KBTS__FEATURE_FLAG0(tjmo) | KBTS__FEATURE_FLAG0(ccmp) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm) | KBTS__FEATURE_FLAG2(rlig) | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(locl) | KBTS__FEATURE_FLAG2(rclt), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(mkmk) | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Hangul = {22, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Hangul), kbts__FeatureStages_Hangul, KBTS__ARRAY_LENGTH(kbts__Ops_Hangul), kbts__Ops_Hangul}; +static kbts__op_kind kbts__Ops_ArabicRclt[] = { + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_FLAG_JOINING_LETTERS, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_STCH_POSTPASS, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_ArabicRclt[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rtla) | KBTS__FEATURE_FLAG3(rtlm)}}}, + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(stch)}}}, + {2, {{0ull | KBTS__FEATURE_FLAG0(ccmp), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(isol), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fina), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fin2), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fin3), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(medi), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(med2), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(init), 0ull, 0ull, 0ull}}}, + {1, {{0ull, 0ull, 0ull | KBTS__FEATURE_FLAG2(rlig), 0ull}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(calt) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(mset) | KBTS__FEATURE_FLAG2(rclt), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk) | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern), 0ull}}}, +}; +static kbts__op_list kbts__OpList_ArabicRclt = {29, KBTS__ARRAY_LENGTH(kbts__FeatureStages_ArabicRclt), kbts__FeatureStages_ArabicRclt, KBTS__ARRAY_LENGTH(kbts__Ops_ArabicRclt), kbts__Ops_ArabicRclt}; +static kbts__op_kind kbts__Ops_ArabicNoRclt[] = { + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_FLAG_JOINING_LETTERS, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_STCH_POSTPASS, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_ArabicNoRclt[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rtla) | KBTS__FEATURE_FLAG3(rtlm)}}}, + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(stch)}}}, + {2, {{0ull | KBTS__FEATURE_FLAG0(ccmp), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(isol), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fina), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fin2), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(fin3), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(medi), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(med2), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(init), 0ull, 0ull, 0ull}}}, + {1, {{0ull, 0ull, 0ull | KBTS__FEATURE_FLAG2(rlig), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(calt), 0ull, 0ull, 0ull}}}, + {3, {{0ull | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(mset), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk) | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern), 0ull}}}, +}; +static kbts__op_list kbts__OpList_ArabicNoRclt = {28, KBTS__ARRAY_LENGTH(kbts__FeatureStages_ArabicNoRclt), kbts__FeatureStages_ArabicNoRclt, KBTS__ARRAY_LENGTH(kbts__Ops_ArabicNoRclt), kbts__Ops_ArabicNoRclt}; +static kbts__op_kind kbts__Ops_Indic[] = { + KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES, + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_BEGIN_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_SYLLABLE, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Indic[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm), 0ull}}}, + {1, {{0ull, 0ull, 0ull | KBTS__FEATURE_FLAG2(nukt), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(akhn), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(rphf), 0ull, 0ull, 0ull}}}, + {1, {{0ull, 0ull, 0ull | KBTS__FEATURE_FLAG2(rkrf), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(pref), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(blwf), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(abvf), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(half), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(pstf), 0ull, 0ull, 0ull}}}, + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(vatu)}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(cjct), 0ull, 0ull, 0ull}}}, + {6, {{0ull | KBTS__FEATURE_FLAG0(abvs) | KBTS__FEATURE_FLAG0(blws) | KBTS__FEATURE_FLAG0(init), 0ull, 0ull | KBTS__FEATURE_FLAG2(haln) | KBTS__FEATURE_FLAG2(pres) | KBTS__FEATURE_FLAG2(psts), 0ull}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(calt) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl) | KBTS__FEATURE_FLAG2(rlig) | KBTS__FEATURE_FLAG2(rclt), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk) | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Indic = {35, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Indic), kbts__FeatureStages_Indic, KBTS__ARRAY_LENGTH(kbts__Ops_Indic), kbts__Ops_Indic}; +static kbts__op_kind kbts__Ops_Khmer[] = { + KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES, + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_BEGIN_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_CLUSTER, + KBTS__OP_KIND_END_SYLLABLE, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Khmer[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(ccmp) | KBTS__FEATURE_FLAG0(pref) | KBTS__FEATURE_FLAG0(blwf) | KBTS__FEATURE_FLAG0(abvf) | KBTS__FEATURE_FLAG0(pstf) | KBTS__FEATURE_FLAG0(cfar), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl), 0ull}}}, + {8, {{0ull | KBTS__FEATURE_FLAG0(abvs) | KBTS__FEATURE_FLAG0(blws) | KBTS__FEATURE_FLAG0(calt) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(pres) | KBTS__FEATURE_FLAG2(psts) | KBTS__FEATURE_FLAG2(rclt) | KBTS__FEATURE_FLAG2(rlig), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern) | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Khmer = {28, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Khmer), kbts__FeatureStages_Khmer, KBTS__ARRAY_LENGTH(kbts__Ops_Khmer), kbts__Ops_Khmer}; +static kbts__op_kind kbts__Ops_Myanmar[] = { + KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES, + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_BEGIN_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_SYLLABLE, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Myanmar[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm), 0ull}}}, + {2, {{0ull | KBTS__FEATURE_FLAG0(ccmp), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(rphf), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(pref), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(blwf), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(pstf), 0ull, 0ull, 0ull}}}, + {9, {{0ull | KBTS__FEATURE_FLAG0(abvs) | KBTS__FEATURE_FLAG0(blws) | KBTS__FEATURE_FLAG0(calt) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(pres) | KBTS__FEATURE_FLAG2(psts) | KBTS__FEATURE_FLAG2(rlig) | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(rclt), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern) | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Myanmar = {28, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Myanmar), kbts__FeatureStages_Myanmar, KBTS__ARRAY_LENGTH(kbts__Ops_Myanmar), kbts__Ops_Myanmar}; +static kbts__op_kind kbts__Ops_Tibetan[] = { + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Tibetan[] = { + {1, {{0ull, 0ull, 0ull | KBTS__FEATURE_FLAG2(locl), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(ccmp), 0ull, 0ull, 0ull}}}, + {4, {{0ull | KBTS__FEATURE_FLAG0(abvs) | KBTS__FEATURE_FLAG0(blws) | KBTS__FEATURE_FLAG0(calt), 0ull, 0ull | KBTS__FEATURE_FLAG2(liga), 0ull}}}, + {4, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm), 0ull, 0ull | KBTS__FEATURE_FLAG2(kern) | KBTS__FEATURE_FLAG2(mkmk), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Tibetan = {10, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Tibetan), kbts__FeatureStages_Tibetan, KBTS__ARRAY_LENGTH(kbts__Ops_Tibetan), kbts__Ops_Tibetan}; +static kbts__op_kind kbts__Ops_Use[] = { + KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES, + KBTS__OP_KIND_NORMALIZE, + KBTS__OP_KIND_FLAG_JOINING_LETTERS, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_BEGIN_CLUSTER, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_END_CLUSTER, + KBTS__OP_KIND_END_SYLLABLE, + KBTS__OP_KIND_GSUB_FEATURES, + KBTS__OP_KIND_GSUB_FEATURES_WITH_USER, + KBTS__OP_KIND_GPOS_METRICS, + KBTS__OP_KIND_GPOS_FEATURES, + KBTS__OP_KIND_POST_GPOS_FIXUP, +}; +static kbts__feature_stage kbts__FeatureStages_Use[] = { + {1, {{0ull, 0ull, 0ull, 0ull | KBTS__FEATURE_FLAG3(rvrn)}}}, + {5, {{0ull | KBTS__FEATURE_FLAG0(frac) | KBTS__FEATURE_FLAG0(numr) | KBTS__FEATURE_FLAG0(dnom), 0ull, 0ull | KBTS__FEATURE_FLAG2(ltra) | KBTS__FEATURE_FLAG2(ltrm), 0ull}}}, + {4, {{0ull | KBTS__FEATURE_FLAG0(ccmp) | KBTS__FEATURE_FLAG0(akhn), 0ull, 0ull | KBTS__FEATURE_FLAG2(locl) | KBTS__FEATURE_FLAG2(nukt), 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(rphf), 0ull, 0ull, 0ull}}}, + {1, {{0ull | KBTS__FEATURE_FLAG0(pref), 0ull, 0ull, 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvf) | KBTS__FEATURE_FLAG0(blwf) | KBTS__FEATURE_FLAG0(cjct) | KBTS__FEATURE_FLAG0(half) | KBTS__FEATURE_FLAG0(pstf), 0ull, 0ull | KBTS__FEATURE_FLAG2(rkrf), 0ull | KBTS__FEATURE_FLAG3(vatu)}}}, + {4, {{0ull | KBTS__FEATURE_FLAG0(fina) | KBTS__FEATURE_FLAG0(init) | KBTS__FEATURE_FLAG0(isol) | KBTS__FEATURE_FLAG0(medi), 0ull, 0ull, 0ull}}}, + {10, {{0ull | KBTS__FEATURE_FLAG0(abvs) | KBTS__FEATURE_FLAG0(blws) | KBTS__FEATURE_FLAG0(calt) | KBTS__FEATURE_FLAG0(clig), 0ull, 0ull | KBTS__FEATURE_FLAG2(haln) | KBTS__FEATURE_FLAG2(pres) | KBTS__FEATURE_FLAG2(psts) | KBTS__FEATURE_FLAG2(liga) | KBTS__FEATURE_FLAG2(rclt) | KBTS__FEATURE_FLAG2(rlig), 0ull}}}, + {7, {{0ull | KBTS__FEATURE_FLAG0(abvm) | KBTS__FEATURE_FLAG0(blwm) | KBTS__FEATURE_FLAG0(curs), 0ull, 0ull | KBTS__FEATURE_FLAG2(dist) | KBTS__FEATURE_FLAG2(kern) | KBTS__FEATURE_FLAG2(mark) | KBTS__FEATURE_FLAG2(mkmk), 0ull}}}, +}; +static kbts__op_list kbts__OpList_Use = {40, KBTS__ARRAY_LENGTH(kbts__FeatureStages_Use), kbts__FeatureStages_Use, KBTS__ARRAY_LENGTH(kbts__Ops_Use), kbts__Ops_Use}; +#define KBTS__MAXIMUM_DECOMPOSITION_CODEPOINTS 6 +typedef struct kbts__script_properties { + kbts_u32 Tag; + kbts_shaper Shaper; +} kbts__script_properties; + +static kbts__script_properties kbts__ScriptProperties[KBTS_SCRIPT_COUNT] = { + {KBTS_FOURCC(' ', ' ', ' ', ' '), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('a', 'd', 'l', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('a', 'h', 'o', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'l', 'u', 'w'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('a', 'r', 'a', 'b'), KBTS_SHAPER_ARABIC}, + {KBTS_FOURCC('a', 'r', 'm', 'n'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('a', 'v', 's', 't'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'a', 'l', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'a', 'm', 'u'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('b', 'a', 's', 's'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'a', 't', 'k'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'n', 'g', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('b', 'h', 'k', 's'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'o', 'p', 'o'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('b', 'r', 'a', 'h'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'u', 'g', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('b', 'u', 'h', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('c', 'a', 'n', 's'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('c', 'a', 'r', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('a', 'g', 'h', 'b'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('c', 'a', 'k', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('c', 'h', 'a', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('c', 'h', 'e', 'r'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('c', 'h', 'r', 's'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'a', 'n', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('c', 'o', 'p', 't'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('c', 'p', 'r', 't'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('c', 'p', 'm', 'n'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('c', 'y', 'r', 'l'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('D', 'F', 'L', 'T'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('D', 'F', 'L', 'T'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('d', 's', 'r', 't'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('d', 'e', 'v', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('d', 'i', 'a', 'k'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('d', 'o', 'g', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('d', 'u', 'p', 'l'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('e', 'g', 'y', 'p'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('e', 'l', 'b', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('e', 'l', 'y', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('e', 't', 'h', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('g', 'a', 'r', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('g', 'e', 'o', 'r'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('g', 'l', 'a', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('g', 'o', 't', 'h'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('g', 'r', 'a', 'n'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('g', 'r', 'e', 'k'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('g', 'j', 'r', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('g', 'o', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('g', 'u', 'r', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('g', 'u', 'k', 'h'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'a', 'n', 'g'), KBTS_SHAPER_HANGUL}, + {KBTS_FOURCC('r', 'o', 'h', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'a', 'n', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'a', 't', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('h', 'e', 'b', 'r'), KBTS_SHAPER_HEBREW}, + {KBTS_FOURCC('k', 'a', 'n', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('a', 'r', 'm', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('p', 'h', 'l', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('p', 'r', 't', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('j', 'a', 'v', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 't', 'h', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'n', 'd', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('k', 'a', 'n', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('k', 'a', 'w', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'a', 'l', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'h', 'a', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'i', 't', 's'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'h', 'm', 'r'), KBTS_SHAPER_KHMER}, + {KBTS_FOURCC('k', 'h', 'o', 'j'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'i', 'n', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('k', 'r', 'a', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'a', 'o', ' '), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('l', 'a', 't', 'n'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('l', 'e', 'p', 'c'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'i', 'm', 'b'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'i', 'n', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('l', 'i', 'n', 'b'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('l', 'i', 's', 'u'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'y', 'c', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'y', 'd', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('m', 'a', 'h', 'j'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'a', 'k', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'l', 'm', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('m', 'a', 'n', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'a', 'n', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'a', 'r', 'c'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('g', 'o', 'n', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'e', 'd', 'f'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 't', 'e', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'e', 'n', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'e', 'r', 'c'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'e', 'r', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('p', 'l', 'r', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'o', 'd', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'o', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'r', 'o', 'o'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('m', 'u', 'l', 't'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('m', 'y', 'm', '2'), KBTS_SHAPER_MYANMAR}, + {KBTS_FOURCC('n', 'b', 'a', 't'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('n', 'a', 'g', 'm'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('n', 'a', 'n', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('n', 'e', 'w', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'l', 'u'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('n', 'k', 'o', ' '), KBTS_SHAPER_USE}, + {KBTS_FOURCC('n', 's', 'h', 'u'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('h', 'm', 'n', 'p'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('o', 'g', 'a', 'm'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('o', 'l', 'c', 'k'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('o', 'n', 'a', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('i', 't', 'a', 'l'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('h', 'u', 'n', 'g'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('n', 'a', 'r', 'b'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('p', 'e', 'r', 'm'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('x', 'p', 'e', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'o', 'g', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'a', 'r', 'b'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('o', 'r', 'k', 'h'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('o', 'u', 'g', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('o', 'r', 'y', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('o', 's', 'g', 'e'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('o', 's', 'm', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('h', 'm', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('p', 'a', 'l', 'm'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('p', 'a', 'u', 'c'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('p', 'h', 'a', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('p', 'h', 'n', 'x'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('p', 'h', 'l', 'p'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('r', 'j', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('r', 'u', 'n', 'r'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('s', 'a', 'm', 'r'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('s', 'a', 'u', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'h', 'r', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'h', 'a', 'w'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('s', 'i', 'd', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'g', 'n', 'w'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'o', 'g', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'i', 'n', 'h'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'o', 'r', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'o', 'y', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('x', 's', 'u', 'x'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'u', 'n', 'd'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'u', 'n', 'u'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'y', 'l', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('s', 'y', 'r', 'c'), KBTS_SHAPER_ARABIC}, + {KBTS_FOURCC('t', 'g', 'l', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'g', 'b'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'l', 'e'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('l', 'a', 'n', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'v', 't'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'k', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'm', 'l', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('t', 'n', 's', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'a', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'e', 'l', '2'), KBTS_SHAPER_INDIC}, + {KBTS_FOURCC('t', 'h', 'a', 'a'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('t', 'h', 'a', 'i'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('t', 'i', 'b', 't'), KBTS_SHAPER_TIBETAN}, + {KBTS_FOURCC('t', 'f', 'n', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'i', 'r', 'h'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'o', 'd', 'r'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'o', 't', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('t', 'u', 't', 'g'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('u', 'g', 'a', 'r'), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('v', 'a', 'i', ' '), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('v', 'i', 't', 'h'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('w', 'c', 'h', 'o'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('w', 'a', 'r', 'a'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('y', 'e', 'z', 'i'), KBTS_SHAPER_USE}, + {KBTS_FOURCC('y', 'i', ' ', ' '), KBTS_SHAPER_DEFAULT}, + {KBTS_FOURCC('z', 'a', 'n', 'b'), KBTS_SHAPER_USE}, +}; + +KBTS_EXPORT kbts_script kbts_ScriptTagToScript(kbts_script_tag Tag) +{ + kbts_script Result = 0; + switch(Tag) + { + case KBTS_SCRIPT_TAG_DONT_KNOW: Result = KBTS_SCRIPT_DONT_KNOW; break; + case KBTS_SCRIPT_TAG_ADLAM: Result = KBTS_SCRIPT_ADLAM; break; + case KBTS_SCRIPT_TAG_AHOM: Result = KBTS_SCRIPT_AHOM; break; + case KBTS_SCRIPT_TAG_ANATOLIAN_HIEROGLYPHS: Result = KBTS_SCRIPT_ANATOLIAN_HIEROGLYPHS; break; + case KBTS_SCRIPT_TAG_ARABIC: Result = KBTS_SCRIPT_ARABIC; break; + case KBTS_SCRIPT_TAG_ARMENIAN: Result = KBTS_SCRIPT_ARMENIAN; break; + case KBTS_SCRIPT_TAG_AVESTAN: Result = KBTS_SCRIPT_AVESTAN; break; + case KBTS_SCRIPT_TAG_BALINESE: Result = KBTS_SCRIPT_BALINESE; break; + case KBTS_SCRIPT_TAG_BAMUM: Result = KBTS_SCRIPT_BAMUM; break; + case KBTS_SCRIPT_TAG_BASSA_VAH: Result = KBTS_SCRIPT_BASSA_VAH; break; + case KBTS_SCRIPT_TAG_BATAK: Result = KBTS_SCRIPT_BATAK; break; + case KBTS_SCRIPT_TAG_BENGALI: Result = KBTS_SCRIPT_BENGALI; break; + case KBTS_SCRIPT_TAG_BHAIKSUKI: Result = KBTS_SCRIPT_BHAIKSUKI; break; + case KBTS_SCRIPT_TAG_BOPOMOFO: Result = KBTS_SCRIPT_BOPOMOFO; break; + case KBTS_SCRIPT_TAG_BRAHMI: Result = KBTS_SCRIPT_BRAHMI; break; + case KBTS_SCRIPT_TAG_BUGINESE: Result = KBTS_SCRIPT_BUGINESE; break; + case KBTS_SCRIPT_TAG_BUHID: Result = KBTS_SCRIPT_BUHID; break; + case KBTS_SCRIPT_TAG_CANADIAN_SYLLABICS: Result = KBTS_SCRIPT_CANADIAN_SYLLABICS; break; + case KBTS_SCRIPT_TAG_CARIAN: Result = KBTS_SCRIPT_CARIAN; break; + case KBTS_SCRIPT_TAG_CAUCASIAN_ALBANIAN: Result = KBTS_SCRIPT_CAUCASIAN_ALBANIAN; break; + case KBTS_SCRIPT_TAG_CHAKMA: Result = KBTS_SCRIPT_CHAKMA; break; + case KBTS_SCRIPT_TAG_CHAM: Result = KBTS_SCRIPT_CHAM; break; + case KBTS_SCRIPT_TAG_CHEROKEE: Result = KBTS_SCRIPT_CHEROKEE; break; + case KBTS_SCRIPT_TAG_CHORASMIAN: Result = KBTS_SCRIPT_CHORASMIAN; break; + case KBTS_SCRIPT_TAG_CJK_IDEOGRAPHIC: Result = KBTS_SCRIPT_CJK_IDEOGRAPHIC; break; + case KBTS_SCRIPT_TAG_COPTIC: Result = KBTS_SCRIPT_COPTIC; break; + case KBTS_SCRIPT_TAG_CYPRIOT_SYLLABARY: Result = KBTS_SCRIPT_CYPRIOT_SYLLABARY; break; + case KBTS_SCRIPT_TAG_CYPRO_MINOAN: Result = KBTS_SCRIPT_CYPRO_MINOAN; break; + case KBTS_SCRIPT_TAG_CYRILLIC: Result = KBTS_SCRIPT_CYRILLIC; break; + case KBTS_SCRIPT_TAG_DEFAULT: Result = KBTS_SCRIPT_DEFAULT; break; + case KBTS_SCRIPT_TAG_DESERET: Result = KBTS_SCRIPT_DESERET; break; + case KBTS_SCRIPT_TAG_DEVANAGARI: Result = KBTS_SCRIPT_DEVANAGARI; break; + case KBTS_SCRIPT_TAG_DIVES_AKURU: Result = KBTS_SCRIPT_DIVES_AKURU; break; + case KBTS_SCRIPT_TAG_DOGRA: Result = KBTS_SCRIPT_DOGRA; break; + case KBTS_SCRIPT_TAG_DUPLOYAN: Result = KBTS_SCRIPT_DUPLOYAN; break; + case KBTS_SCRIPT_TAG_EGYPTIAN_HIEROGLYPHS: Result = KBTS_SCRIPT_EGYPTIAN_HIEROGLYPHS; break; + case KBTS_SCRIPT_TAG_ELBASAN: Result = KBTS_SCRIPT_ELBASAN; break; + case KBTS_SCRIPT_TAG_ELYMAIC: Result = KBTS_SCRIPT_ELYMAIC; break; + case KBTS_SCRIPT_TAG_ETHIOPIC: Result = KBTS_SCRIPT_ETHIOPIC; break; + case KBTS_SCRIPT_TAG_GARAY: Result = KBTS_SCRIPT_GARAY; break; + case KBTS_SCRIPT_TAG_GEORGIAN: Result = KBTS_SCRIPT_GEORGIAN; break; + case KBTS_SCRIPT_TAG_GLAGOLITIC: Result = KBTS_SCRIPT_GLAGOLITIC; break; + case KBTS_SCRIPT_TAG_GOTHIC: Result = KBTS_SCRIPT_GOTHIC; break; + case KBTS_SCRIPT_TAG_GRANTHA: Result = KBTS_SCRIPT_GRANTHA; break; + case KBTS_SCRIPT_TAG_GREEK: Result = KBTS_SCRIPT_GREEK; break; + case KBTS_SCRIPT_TAG_GUJARATI: Result = KBTS_SCRIPT_GUJARATI; break; + case KBTS_SCRIPT_TAG_GUNJALA_GONDI: Result = KBTS_SCRIPT_GUNJALA_GONDI; break; + case KBTS_SCRIPT_TAG_GURMUKHI: Result = KBTS_SCRIPT_GURMUKHI; break; + case KBTS_SCRIPT_TAG_GURUNG_KHEMA: Result = KBTS_SCRIPT_GURUNG_KHEMA; break; + case KBTS_SCRIPT_TAG_HANGUL: Result = KBTS_SCRIPT_HANGUL; break; + case KBTS_SCRIPT_TAG_HANIFI_ROHINGYA: Result = KBTS_SCRIPT_HANIFI_ROHINGYA; break; + case KBTS_SCRIPT_TAG_HANUNOO: Result = KBTS_SCRIPT_HANUNOO; break; + case KBTS_SCRIPT_TAG_HATRAN: Result = KBTS_SCRIPT_HATRAN; break; + case KBTS_SCRIPT_TAG_HEBREW: Result = KBTS_SCRIPT_HEBREW; break; + case KBTS_SCRIPT_TAG_HIRAGANA: Result = KBTS_SCRIPT_HIRAGANA; break; + case KBTS_SCRIPT_TAG_IMPERIAL_ARAMAIC: Result = KBTS_SCRIPT_IMPERIAL_ARAMAIC; break; + case KBTS_SCRIPT_TAG_INSCRIPTIONAL_PAHLAVI: Result = KBTS_SCRIPT_INSCRIPTIONAL_PAHLAVI; break; + case KBTS_SCRIPT_TAG_INSCRIPTIONAL_PARTHIAN: Result = KBTS_SCRIPT_INSCRIPTIONAL_PARTHIAN; break; + case KBTS_SCRIPT_TAG_JAVANESE: Result = KBTS_SCRIPT_JAVANESE; break; + case KBTS_SCRIPT_TAG_KAITHI: Result = KBTS_SCRIPT_KAITHI; break; + case KBTS_SCRIPT_TAG_KANNADA: Result = KBTS_SCRIPT_KANNADA; break; + case KBTS_SCRIPT_TAG_KAWI: Result = KBTS_SCRIPT_KAWI; break; + case KBTS_SCRIPT_TAG_KAYAH_LI: Result = KBTS_SCRIPT_KAYAH_LI; break; + case KBTS_SCRIPT_TAG_KHAROSHTHI: Result = KBTS_SCRIPT_KHAROSHTHI; break; + case KBTS_SCRIPT_TAG_KHITAN_SMALL_SCRIPT: Result = KBTS_SCRIPT_KHITAN_SMALL_SCRIPT; break; + case KBTS_SCRIPT_TAG_KHMER: Result = KBTS_SCRIPT_KHMER; break; + case KBTS_SCRIPT_TAG_KHOJKI: Result = KBTS_SCRIPT_KHOJKI; break; + case KBTS_SCRIPT_TAG_KHUDAWADI: Result = KBTS_SCRIPT_KHUDAWADI; break; + case KBTS_SCRIPT_TAG_KIRAT_RAI: Result = KBTS_SCRIPT_KIRAT_RAI; break; + case KBTS_SCRIPT_TAG_LAO: Result = KBTS_SCRIPT_LAO; break; + case KBTS_SCRIPT_TAG_LATIN: Result = KBTS_SCRIPT_LATIN; break; + case KBTS_SCRIPT_TAG_LEPCHA: Result = KBTS_SCRIPT_LEPCHA; break; + case KBTS_SCRIPT_TAG_LIMBU: Result = KBTS_SCRIPT_LIMBU; break; + case KBTS_SCRIPT_TAG_LINEAR_A: Result = KBTS_SCRIPT_LINEAR_A; break; + case KBTS_SCRIPT_TAG_LINEAR_B: Result = KBTS_SCRIPT_LINEAR_B; break; + case KBTS_SCRIPT_TAG_LISU: Result = KBTS_SCRIPT_LISU; break; + case KBTS_SCRIPT_TAG_LYCIAN: Result = KBTS_SCRIPT_LYCIAN; break; + case KBTS_SCRIPT_TAG_LYDIAN: Result = KBTS_SCRIPT_LYDIAN; break; + case KBTS_SCRIPT_TAG_MAHAJANI: Result = KBTS_SCRIPT_MAHAJANI; break; + case KBTS_SCRIPT_TAG_MAKASAR: Result = KBTS_SCRIPT_MAKASAR; break; + case KBTS_SCRIPT_TAG_MALAYALAM: Result = KBTS_SCRIPT_MALAYALAM; break; + case KBTS_SCRIPT_TAG_MANDAIC: Result = KBTS_SCRIPT_MANDAIC; break; + case KBTS_SCRIPT_TAG_MANICHAEAN: Result = KBTS_SCRIPT_MANICHAEAN; break; + case KBTS_SCRIPT_TAG_MARCHEN: Result = KBTS_SCRIPT_MARCHEN; break; + case KBTS_SCRIPT_TAG_MASARAM_GONDI: Result = KBTS_SCRIPT_MASARAM_GONDI; break; + case KBTS_SCRIPT_TAG_MEDEFAIDRIN: Result = KBTS_SCRIPT_MEDEFAIDRIN; break; + case KBTS_SCRIPT_TAG_MEETEI_MAYEK: Result = KBTS_SCRIPT_MEETEI_MAYEK; break; + case KBTS_SCRIPT_TAG_MENDE_KIKAKUI: Result = KBTS_SCRIPT_MENDE_KIKAKUI; break; + case KBTS_SCRIPT_TAG_MEROITIC_CURSIVE: Result = KBTS_SCRIPT_MEROITIC_CURSIVE; break; + case KBTS_SCRIPT_TAG_MEROITIC_HIEROGLYPHS: Result = KBTS_SCRIPT_MEROITIC_HIEROGLYPHS; break; + case KBTS_SCRIPT_TAG_MIAO: Result = KBTS_SCRIPT_MIAO; break; + case KBTS_SCRIPT_TAG_MODI: Result = KBTS_SCRIPT_MODI; break; + case KBTS_SCRIPT_TAG_MONGOLIAN: Result = KBTS_SCRIPT_MONGOLIAN; break; + case KBTS_SCRIPT_TAG_MRO: Result = KBTS_SCRIPT_MRO; break; + case KBTS_SCRIPT_TAG_MULTANI: Result = KBTS_SCRIPT_MULTANI; break; + case KBTS_SCRIPT_TAG_MYANMAR: Result = KBTS_SCRIPT_MYANMAR; break; + case KBTS_SCRIPT_TAG_NABATAEAN: Result = KBTS_SCRIPT_NABATAEAN; break; + case KBTS_SCRIPT_TAG_NAG_MUNDARI: Result = KBTS_SCRIPT_NAG_MUNDARI; break; + case KBTS_SCRIPT_TAG_NANDINAGARI: Result = KBTS_SCRIPT_NANDINAGARI; break; + case KBTS_SCRIPT_TAG_NEWA: Result = KBTS_SCRIPT_NEWA; break; + case KBTS_SCRIPT_TAG_NEW_TAI_LUE: Result = KBTS_SCRIPT_NEW_TAI_LUE; break; + case KBTS_SCRIPT_TAG_NKO: Result = KBTS_SCRIPT_NKO; break; + case KBTS_SCRIPT_TAG_NUSHU: Result = KBTS_SCRIPT_NUSHU; break; + case KBTS_SCRIPT_TAG_NYIAKENG_PUACHUE_HMONG: Result = KBTS_SCRIPT_NYIAKENG_PUACHUE_HMONG; break; + case KBTS_SCRIPT_TAG_OGHAM: Result = KBTS_SCRIPT_OGHAM; break; + case KBTS_SCRIPT_TAG_OL_CHIKI: Result = KBTS_SCRIPT_OL_CHIKI; break; + case KBTS_SCRIPT_TAG_OL_ONAL: Result = KBTS_SCRIPT_OL_ONAL; break; + case KBTS_SCRIPT_TAG_OLD_ITALIC: Result = KBTS_SCRIPT_OLD_ITALIC; break; + case KBTS_SCRIPT_TAG_OLD_HUNGARIAN: Result = KBTS_SCRIPT_OLD_HUNGARIAN; break; + case KBTS_SCRIPT_TAG_OLD_NORTH_ARABIAN: Result = KBTS_SCRIPT_OLD_NORTH_ARABIAN; break; + case KBTS_SCRIPT_TAG_OLD_PERMIC: Result = KBTS_SCRIPT_OLD_PERMIC; break; + case KBTS_SCRIPT_TAG_OLD_PERSIAN_CUNEIFORM: Result = KBTS_SCRIPT_OLD_PERSIAN_CUNEIFORM; break; + case KBTS_SCRIPT_TAG_OLD_SOGDIAN: Result = KBTS_SCRIPT_OLD_SOGDIAN; break; + case KBTS_SCRIPT_TAG_OLD_SOUTH_ARABIAN: Result = KBTS_SCRIPT_OLD_SOUTH_ARABIAN; break; + case KBTS_SCRIPT_TAG_OLD_TURKIC: Result = KBTS_SCRIPT_OLD_TURKIC; break; + case KBTS_SCRIPT_TAG_OLD_UYGHUR: Result = KBTS_SCRIPT_OLD_UYGHUR; break; + case KBTS_SCRIPT_TAG_ODIA: Result = KBTS_SCRIPT_ODIA; break; + case KBTS_SCRIPT_TAG_OSAGE: Result = KBTS_SCRIPT_OSAGE; break; + case KBTS_SCRIPT_TAG_OSMANYA: Result = KBTS_SCRIPT_OSMANYA; break; + case KBTS_SCRIPT_TAG_PAHAWH_HMONG: Result = KBTS_SCRIPT_PAHAWH_HMONG; break; + case KBTS_SCRIPT_TAG_PALMYRENE: Result = KBTS_SCRIPT_PALMYRENE; break; + case KBTS_SCRIPT_TAG_PAU_CIN_HAU: Result = KBTS_SCRIPT_PAU_CIN_HAU; break; + case KBTS_SCRIPT_TAG_PHAGS_PA: Result = KBTS_SCRIPT_PHAGS_PA; break; + case KBTS_SCRIPT_TAG_PHOENICIAN: Result = KBTS_SCRIPT_PHOENICIAN; break; + case KBTS_SCRIPT_TAG_PSALTER_PAHLAVI: Result = KBTS_SCRIPT_PSALTER_PAHLAVI; break; + case KBTS_SCRIPT_TAG_REJANG: Result = KBTS_SCRIPT_REJANG; break; + case KBTS_SCRIPT_TAG_RUNIC: Result = KBTS_SCRIPT_RUNIC; break; + case KBTS_SCRIPT_TAG_SAMARITAN: Result = KBTS_SCRIPT_SAMARITAN; break; + case KBTS_SCRIPT_TAG_SAURASHTRA: Result = KBTS_SCRIPT_SAURASHTRA; break; + case KBTS_SCRIPT_TAG_SHARADA: Result = KBTS_SCRIPT_SHARADA; break; + case KBTS_SCRIPT_TAG_SHAVIAN: Result = KBTS_SCRIPT_SHAVIAN; break; + case KBTS_SCRIPT_TAG_SIDDHAM: Result = KBTS_SCRIPT_SIDDHAM; break; + case KBTS_SCRIPT_TAG_SIGN_WRITING: Result = KBTS_SCRIPT_SIGN_WRITING; break; + case KBTS_SCRIPT_TAG_SOGDIAN: Result = KBTS_SCRIPT_SOGDIAN; break; + case KBTS_SCRIPT_TAG_SINHALA: Result = KBTS_SCRIPT_SINHALA; break; + case KBTS_SCRIPT_TAG_SORA_SOMPENG: Result = KBTS_SCRIPT_SORA_SOMPENG; break; + case KBTS_SCRIPT_TAG_SOYOMBO: Result = KBTS_SCRIPT_SOYOMBO; break; + case KBTS_SCRIPT_TAG_SUMERO_AKKADIAN_CUNEIFORM: Result = KBTS_SCRIPT_SUMERO_AKKADIAN_CUNEIFORM; break; + case KBTS_SCRIPT_TAG_SUNDANESE: Result = KBTS_SCRIPT_SUNDANESE; break; + case KBTS_SCRIPT_TAG_SUNUWAR: Result = KBTS_SCRIPT_SUNUWAR; break; + case KBTS_SCRIPT_TAG_SYLOTI_NAGRI: Result = KBTS_SCRIPT_SYLOTI_NAGRI; break; + case KBTS_SCRIPT_TAG_SYRIAC: Result = KBTS_SCRIPT_SYRIAC; break; + case KBTS_SCRIPT_TAG_TAGALOG: Result = KBTS_SCRIPT_TAGALOG; break; + case KBTS_SCRIPT_TAG_TAGBANWA: Result = KBTS_SCRIPT_TAGBANWA; break; + case KBTS_SCRIPT_TAG_TAI_LE: Result = KBTS_SCRIPT_TAI_LE; break; + case KBTS_SCRIPT_TAG_TAI_THAM: Result = KBTS_SCRIPT_TAI_THAM; break; + case KBTS_SCRIPT_TAG_TAI_VIET: Result = KBTS_SCRIPT_TAI_VIET; break; + case KBTS_SCRIPT_TAG_TAKRI: Result = KBTS_SCRIPT_TAKRI; break; + case KBTS_SCRIPT_TAG_TAMIL: Result = KBTS_SCRIPT_TAMIL; break; + case KBTS_SCRIPT_TAG_TANGSA: Result = KBTS_SCRIPT_TANGSA; break; + case KBTS_SCRIPT_TAG_TANGUT: Result = KBTS_SCRIPT_TANGUT; break; + case KBTS_SCRIPT_TAG_TELUGU: Result = KBTS_SCRIPT_TELUGU; break; + case KBTS_SCRIPT_TAG_THAANA: Result = KBTS_SCRIPT_THAANA; break; + case KBTS_SCRIPT_TAG_THAI: Result = KBTS_SCRIPT_THAI; break; + case KBTS_SCRIPT_TAG_TIBETAN: Result = KBTS_SCRIPT_TIBETAN; break; + case KBTS_SCRIPT_TAG_TIFINAGH: Result = KBTS_SCRIPT_TIFINAGH; break; + case KBTS_SCRIPT_TAG_TIRHUTA: Result = KBTS_SCRIPT_TIRHUTA; break; + case KBTS_SCRIPT_TAG_TODHRI: Result = KBTS_SCRIPT_TODHRI; break; + case KBTS_SCRIPT_TAG_TOTO: Result = KBTS_SCRIPT_TOTO; break; + case KBTS_SCRIPT_TAG_TULU_TIGALARI: Result = KBTS_SCRIPT_TULU_TIGALARI; break; + case KBTS_SCRIPT_TAG_UGARITIC_CUNEIFORM: Result = KBTS_SCRIPT_UGARITIC_CUNEIFORM; break; + case KBTS_SCRIPT_TAG_VAI: Result = KBTS_SCRIPT_VAI; break; + case KBTS_SCRIPT_TAG_VITHKUQI: Result = KBTS_SCRIPT_VITHKUQI; break; + case KBTS_SCRIPT_TAG_WANCHO: Result = KBTS_SCRIPT_WANCHO; break; + case KBTS_SCRIPT_TAG_WARANG_CITI: Result = KBTS_SCRIPT_WARANG_CITI; break; + case KBTS_SCRIPT_TAG_YEZIDI: Result = KBTS_SCRIPT_YEZIDI; break; + case KBTS_SCRIPT_TAG_YI: Result = KBTS_SCRIPT_YI; break; + case KBTS_SCRIPT_TAG_ZANABAZAR_SQUARE: Result = KBTS_SCRIPT_ZANABAZAR_SQUARE; break; + default: break; + } + return Result; +} + +static kbts__feature_id kbts__FeatureTagToId(kbts_feature_tag Tag) +{ + kbts__feature_id Result = 0; + switch(Tag) + { + case KBTS_FEATURE_TAG_isol: Result = KBTS__FEATURE_ID_isol; break; + case KBTS_FEATURE_TAG_fina: Result = KBTS__FEATURE_ID_fina; break; + case KBTS_FEATURE_TAG_fin2: Result = KBTS__FEATURE_ID_fin2; break; + case KBTS_FEATURE_TAG_fin3: Result = KBTS__FEATURE_ID_fin3; break; + case KBTS_FEATURE_TAG_medi: Result = KBTS__FEATURE_ID_medi; break; + case KBTS_FEATURE_TAG_med2: Result = KBTS__FEATURE_ID_med2; break; + case KBTS_FEATURE_TAG_init: Result = KBTS__FEATURE_ID_init; break; + case KBTS_FEATURE_TAG_ljmo: Result = KBTS__FEATURE_ID_ljmo; break; + case KBTS_FEATURE_TAG_vjmo: Result = KBTS__FEATURE_ID_vjmo; break; + case KBTS_FEATURE_TAG_tjmo: Result = KBTS__FEATURE_ID_tjmo; break; + case KBTS_FEATURE_TAG_rphf: Result = KBTS__FEATURE_ID_rphf; break; + case KBTS_FEATURE_TAG_blwf: Result = KBTS__FEATURE_ID_blwf; break; + case KBTS_FEATURE_TAG_half: Result = KBTS__FEATURE_ID_half; break; + case KBTS_FEATURE_TAG_pstf: Result = KBTS__FEATURE_ID_pstf; break; + case KBTS_FEATURE_TAG_abvf: Result = KBTS__FEATURE_ID_abvf; break; + case KBTS_FEATURE_TAG_pref: Result = KBTS__FEATURE_ID_pref; break; + case KBTS_FEATURE_TAG_numr: Result = KBTS__FEATURE_ID_numr; break; + case KBTS_FEATURE_TAG_frac: Result = KBTS__FEATURE_ID_frac; break; + case KBTS_FEATURE_TAG_dnom: Result = KBTS__FEATURE_ID_dnom; break; + case KBTS_FEATURE_TAG_cfar: Result = KBTS__FEATURE_ID_cfar; break; + case KBTS_FEATURE_TAG_aalt: Result = KBTS__FEATURE_ID_aalt; break; + case KBTS_FEATURE_TAG_abvm: Result = KBTS__FEATURE_ID_abvm; break; + case KBTS_FEATURE_TAG_abvs: Result = KBTS__FEATURE_ID_abvs; break; + case KBTS_FEATURE_TAG_afrc: Result = KBTS__FEATURE_ID_afrc; break; + case KBTS_FEATURE_TAG_akhn: Result = KBTS__FEATURE_ID_akhn; break; + case KBTS_FEATURE_TAG_apkn: Result = KBTS__FEATURE_ID_apkn; break; + case KBTS_FEATURE_TAG_blwm: Result = KBTS__FEATURE_ID_blwm; break; + case KBTS_FEATURE_TAG_blws: Result = KBTS__FEATURE_ID_blws; break; + case KBTS_FEATURE_TAG_calt: Result = KBTS__FEATURE_ID_calt; break; + case KBTS_FEATURE_TAG_case: Result = KBTS__FEATURE_ID_case; break; + case KBTS_FEATURE_TAG_ccmp: Result = KBTS__FEATURE_ID_ccmp; break; + case KBTS_FEATURE_TAG_chws: Result = KBTS__FEATURE_ID_chws; break; + case KBTS_FEATURE_TAG_cjct: Result = KBTS__FEATURE_ID_cjct; break; + case KBTS_FEATURE_TAG_clig: Result = KBTS__FEATURE_ID_clig; break; + case KBTS_FEATURE_TAG_cpct: Result = KBTS__FEATURE_ID_cpct; break; + case KBTS_FEATURE_TAG_cpsp: Result = KBTS__FEATURE_ID_cpsp; break; + case KBTS_FEATURE_TAG_cswh: Result = KBTS__FEATURE_ID_cswh; break; + case KBTS_FEATURE_TAG_curs: Result = KBTS__FEATURE_ID_curs; break; + case KBTS_FEATURE_TAG_cv01: Result = KBTS__FEATURE_ID_cv01; break; + case KBTS_FEATURE_TAG_cv02: Result = KBTS__FEATURE_ID_cv02; break; + case KBTS_FEATURE_TAG_cv03: Result = KBTS__FEATURE_ID_cv03; break; + case KBTS_FEATURE_TAG_cv04: Result = KBTS__FEATURE_ID_cv04; break; + case KBTS_FEATURE_TAG_cv05: Result = KBTS__FEATURE_ID_cv05; break; + case KBTS_FEATURE_TAG_cv06: Result = KBTS__FEATURE_ID_cv06; break; + case KBTS_FEATURE_TAG_cv07: Result = KBTS__FEATURE_ID_cv07; break; + case KBTS_FEATURE_TAG_cv08: Result = KBTS__FEATURE_ID_cv08; break; + case KBTS_FEATURE_TAG_cv09: Result = KBTS__FEATURE_ID_cv09; break; + case KBTS_FEATURE_TAG_cv10: Result = KBTS__FEATURE_ID_cv10; break; + case KBTS_FEATURE_TAG_cv11: Result = KBTS__FEATURE_ID_cv11; break; + case KBTS_FEATURE_TAG_cv12: Result = KBTS__FEATURE_ID_cv12; break; + case KBTS_FEATURE_TAG_cv13: Result = KBTS__FEATURE_ID_cv13; break; + case KBTS_FEATURE_TAG_cv14: Result = KBTS__FEATURE_ID_cv14; break; + case KBTS_FEATURE_TAG_cv15: Result = KBTS__FEATURE_ID_cv15; break; + case KBTS_FEATURE_TAG_cv16: Result = KBTS__FEATURE_ID_cv16; break; + case KBTS_FEATURE_TAG_cv17: Result = KBTS__FEATURE_ID_cv17; break; + case KBTS_FEATURE_TAG_cv18: Result = KBTS__FEATURE_ID_cv18; break; + case KBTS_FEATURE_TAG_cv19: Result = KBTS__FEATURE_ID_cv19; break; + case KBTS_FEATURE_TAG_cv20: Result = KBTS__FEATURE_ID_cv20; break; + case KBTS_FEATURE_TAG_cv21: Result = KBTS__FEATURE_ID_cv21; break; + case KBTS_FEATURE_TAG_cv22: Result = KBTS__FEATURE_ID_cv22; break; + case KBTS_FEATURE_TAG_cv23: Result = KBTS__FEATURE_ID_cv23; break; + case KBTS_FEATURE_TAG_cv24: Result = KBTS__FEATURE_ID_cv24; break; + case KBTS_FEATURE_TAG_cv25: Result = KBTS__FEATURE_ID_cv25; break; + case KBTS_FEATURE_TAG_cv26: Result = KBTS__FEATURE_ID_cv26; break; + case KBTS_FEATURE_TAG_cv27: Result = KBTS__FEATURE_ID_cv27; break; + case KBTS_FEATURE_TAG_cv28: Result = KBTS__FEATURE_ID_cv28; break; + case KBTS_FEATURE_TAG_cv29: Result = KBTS__FEATURE_ID_cv29; break; + case KBTS_FEATURE_TAG_cv30: Result = KBTS__FEATURE_ID_cv30; break; + case KBTS_FEATURE_TAG_cv31: Result = KBTS__FEATURE_ID_cv31; break; + case KBTS_FEATURE_TAG_cv32: Result = KBTS__FEATURE_ID_cv32; break; + case KBTS_FEATURE_TAG_cv33: Result = KBTS__FEATURE_ID_cv33; break; + case KBTS_FEATURE_TAG_cv34: Result = KBTS__FEATURE_ID_cv34; break; + case KBTS_FEATURE_TAG_cv35: Result = KBTS__FEATURE_ID_cv35; break; + case KBTS_FEATURE_TAG_cv36: Result = KBTS__FEATURE_ID_cv36; break; + case KBTS_FEATURE_TAG_cv37: Result = KBTS__FEATURE_ID_cv37; break; + case KBTS_FEATURE_TAG_cv38: Result = KBTS__FEATURE_ID_cv38; break; + case KBTS_FEATURE_TAG_cv39: Result = KBTS__FEATURE_ID_cv39; break; + case KBTS_FEATURE_TAG_cv40: Result = KBTS__FEATURE_ID_cv40; break; + case KBTS_FEATURE_TAG_cv41: Result = KBTS__FEATURE_ID_cv41; break; + case KBTS_FEATURE_TAG_cv42: Result = KBTS__FEATURE_ID_cv42; break; + case KBTS_FEATURE_TAG_cv43: Result = KBTS__FEATURE_ID_cv43; break; + case KBTS_FEATURE_TAG_cv44: Result = KBTS__FEATURE_ID_cv44; break; + case KBTS_FEATURE_TAG_cv45: Result = KBTS__FEATURE_ID_cv45; break; + case KBTS_FEATURE_TAG_cv46: Result = KBTS__FEATURE_ID_cv46; break; + case KBTS_FEATURE_TAG_cv47: Result = KBTS__FEATURE_ID_cv47; break; + case KBTS_FEATURE_TAG_cv48: Result = KBTS__FEATURE_ID_cv48; break; + case KBTS_FEATURE_TAG_cv49: Result = KBTS__FEATURE_ID_cv49; break; + case KBTS_FEATURE_TAG_cv50: Result = KBTS__FEATURE_ID_cv50; break; + case KBTS_FEATURE_TAG_cv51: Result = KBTS__FEATURE_ID_cv51; break; + case KBTS_FEATURE_TAG_cv52: Result = KBTS__FEATURE_ID_cv52; break; + case KBTS_FEATURE_TAG_cv53: Result = KBTS__FEATURE_ID_cv53; break; + case KBTS_FEATURE_TAG_cv54: Result = KBTS__FEATURE_ID_cv54; break; + case KBTS_FEATURE_TAG_cv55: Result = KBTS__FEATURE_ID_cv55; break; + case KBTS_FEATURE_TAG_cv56: Result = KBTS__FEATURE_ID_cv56; break; + case KBTS_FEATURE_TAG_cv57: Result = KBTS__FEATURE_ID_cv57; break; + case KBTS_FEATURE_TAG_cv58: Result = KBTS__FEATURE_ID_cv58; break; + case KBTS_FEATURE_TAG_cv59: Result = KBTS__FEATURE_ID_cv59; break; + case KBTS_FEATURE_TAG_cv60: Result = KBTS__FEATURE_ID_cv60; break; + case KBTS_FEATURE_TAG_cv61: Result = KBTS__FEATURE_ID_cv61; break; + case KBTS_FEATURE_TAG_cv62: Result = KBTS__FEATURE_ID_cv62; break; + case KBTS_FEATURE_TAG_cv63: Result = KBTS__FEATURE_ID_cv63; break; + case KBTS_FEATURE_TAG_cv64: Result = KBTS__FEATURE_ID_cv64; break; + case KBTS_FEATURE_TAG_cv65: Result = KBTS__FEATURE_ID_cv65; break; + case KBTS_FEATURE_TAG_cv66: Result = KBTS__FEATURE_ID_cv66; break; + case KBTS_FEATURE_TAG_cv67: Result = KBTS__FEATURE_ID_cv67; break; + case KBTS_FEATURE_TAG_cv68: Result = KBTS__FEATURE_ID_cv68; break; + case KBTS_FEATURE_TAG_cv69: Result = KBTS__FEATURE_ID_cv69; break; + case KBTS_FEATURE_TAG_cv70: Result = KBTS__FEATURE_ID_cv70; break; + case KBTS_FEATURE_TAG_cv71: Result = KBTS__FEATURE_ID_cv71; break; + case KBTS_FEATURE_TAG_cv72: Result = KBTS__FEATURE_ID_cv72; break; + case KBTS_FEATURE_TAG_cv73: Result = KBTS__FEATURE_ID_cv73; break; + case KBTS_FEATURE_TAG_cv74: Result = KBTS__FEATURE_ID_cv74; break; + case KBTS_FEATURE_TAG_cv75: Result = KBTS__FEATURE_ID_cv75; break; + case KBTS_FEATURE_TAG_cv76: Result = KBTS__FEATURE_ID_cv76; break; + case KBTS_FEATURE_TAG_cv77: Result = KBTS__FEATURE_ID_cv77; break; + case KBTS_FEATURE_TAG_cv78: Result = KBTS__FEATURE_ID_cv78; break; + case KBTS_FEATURE_TAG_cv79: Result = KBTS__FEATURE_ID_cv79; break; + case KBTS_FEATURE_TAG_cv80: Result = KBTS__FEATURE_ID_cv80; break; + case KBTS_FEATURE_TAG_cv81: Result = KBTS__FEATURE_ID_cv81; break; + case KBTS_FEATURE_TAG_cv82: Result = KBTS__FEATURE_ID_cv82; break; + case KBTS_FEATURE_TAG_cv83: Result = KBTS__FEATURE_ID_cv83; break; + case KBTS_FEATURE_TAG_cv84: Result = KBTS__FEATURE_ID_cv84; break; + case KBTS_FEATURE_TAG_cv85: Result = KBTS__FEATURE_ID_cv85; break; + case KBTS_FEATURE_TAG_cv86: Result = KBTS__FEATURE_ID_cv86; break; + case KBTS_FEATURE_TAG_cv87: Result = KBTS__FEATURE_ID_cv87; break; + case KBTS_FEATURE_TAG_cv88: Result = KBTS__FEATURE_ID_cv88; break; + case KBTS_FEATURE_TAG_cv89: Result = KBTS__FEATURE_ID_cv89; break; + case KBTS_FEATURE_TAG_cv90: Result = KBTS__FEATURE_ID_cv90; break; + case KBTS_FEATURE_TAG_cv91: Result = KBTS__FEATURE_ID_cv91; break; + case KBTS_FEATURE_TAG_cv92: Result = KBTS__FEATURE_ID_cv92; break; + case KBTS_FEATURE_TAG_cv93: Result = KBTS__FEATURE_ID_cv93; break; + case KBTS_FEATURE_TAG_cv94: Result = KBTS__FEATURE_ID_cv94; break; + case KBTS_FEATURE_TAG_cv95: Result = KBTS__FEATURE_ID_cv95; break; + case KBTS_FEATURE_TAG_cv96: Result = KBTS__FEATURE_ID_cv96; break; + case KBTS_FEATURE_TAG_cv97: Result = KBTS__FEATURE_ID_cv97; break; + case KBTS_FEATURE_TAG_cv98: Result = KBTS__FEATURE_ID_cv98; break; + case KBTS_FEATURE_TAG_cv99: Result = KBTS__FEATURE_ID_cv99; break; + case KBTS_FEATURE_TAG_c2pc: Result = KBTS__FEATURE_ID_c2pc; break; + case KBTS_FEATURE_TAG_c2sc: Result = KBTS__FEATURE_ID_c2sc; break; + case KBTS_FEATURE_TAG_dist: Result = KBTS__FEATURE_ID_dist; break; + case KBTS_FEATURE_TAG_dlig: Result = KBTS__FEATURE_ID_dlig; break; + case KBTS_FEATURE_TAG_dtls: Result = KBTS__FEATURE_ID_dtls; break; + case KBTS_FEATURE_TAG_expt: Result = KBTS__FEATURE_ID_expt; break; + case KBTS_FEATURE_TAG_falt: Result = KBTS__FEATURE_ID_falt; break; + case KBTS_FEATURE_TAG_flac: Result = KBTS__FEATURE_ID_flac; break; + case KBTS_FEATURE_TAG_fwid: Result = KBTS__FEATURE_ID_fwid; break; + case KBTS_FEATURE_TAG_haln: Result = KBTS__FEATURE_ID_haln; break; + case KBTS_FEATURE_TAG_halt: Result = KBTS__FEATURE_ID_halt; break; + case KBTS_FEATURE_TAG_hist: Result = KBTS__FEATURE_ID_hist; break; + case KBTS_FEATURE_TAG_hkna: Result = KBTS__FEATURE_ID_hkna; break; + case KBTS_FEATURE_TAG_hlig: Result = KBTS__FEATURE_ID_hlig; break; + case KBTS_FEATURE_TAG_hngl: Result = KBTS__FEATURE_ID_hngl; break; + case KBTS_FEATURE_TAG_hojo: Result = KBTS__FEATURE_ID_hojo; break; + case KBTS_FEATURE_TAG_hwid: Result = KBTS__FEATURE_ID_hwid; break; + case KBTS_FEATURE_TAG_ital: Result = KBTS__FEATURE_ID_ital; break; + case KBTS_FEATURE_TAG_jalt: Result = KBTS__FEATURE_ID_jalt; break; + case KBTS_FEATURE_TAG_jp78: Result = KBTS__FEATURE_ID_jp78; break; + case KBTS_FEATURE_TAG_jp83: Result = KBTS__FEATURE_ID_jp83; break; + case KBTS_FEATURE_TAG_jp90: Result = KBTS__FEATURE_ID_jp90; break; + case KBTS_FEATURE_TAG_jp04: Result = KBTS__FEATURE_ID_jp04; break; + case KBTS_FEATURE_TAG_kern: Result = KBTS__FEATURE_ID_kern; break; + case KBTS_FEATURE_TAG_lfbd: Result = KBTS__FEATURE_ID_lfbd; break; + case KBTS_FEATURE_TAG_liga: Result = KBTS__FEATURE_ID_liga; break; + case KBTS_FEATURE_TAG_lnum: Result = KBTS__FEATURE_ID_lnum; break; + case KBTS_FEATURE_TAG_locl: Result = KBTS__FEATURE_ID_locl; break; + case KBTS_FEATURE_TAG_ltra: Result = KBTS__FEATURE_ID_ltra; break; + case KBTS_FEATURE_TAG_ltrm: Result = KBTS__FEATURE_ID_ltrm; break; + case KBTS_FEATURE_TAG_mark: Result = KBTS__FEATURE_ID_mark; break; + case KBTS_FEATURE_TAG_mgrk: Result = KBTS__FEATURE_ID_mgrk; break; + case KBTS_FEATURE_TAG_mkmk: Result = KBTS__FEATURE_ID_mkmk; break; + case KBTS_FEATURE_TAG_mset: Result = KBTS__FEATURE_ID_mset; break; + case KBTS_FEATURE_TAG_nalt: Result = KBTS__FEATURE_ID_nalt; break; + case KBTS_FEATURE_TAG_nlck: Result = KBTS__FEATURE_ID_nlck; break; + case KBTS_FEATURE_TAG_nukt: Result = KBTS__FEATURE_ID_nukt; break; + case KBTS_FEATURE_TAG_onum: Result = KBTS__FEATURE_ID_onum; break; + case KBTS_FEATURE_TAG_opbd: Result = KBTS__FEATURE_ID_opbd; break; + case KBTS_FEATURE_TAG_ordn: Result = KBTS__FEATURE_ID_ordn; break; + case KBTS_FEATURE_TAG_ornm: Result = KBTS__FEATURE_ID_ornm; break; + case KBTS_FEATURE_TAG_palt: Result = KBTS__FEATURE_ID_palt; break; + case KBTS_FEATURE_TAG_pcap: Result = KBTS__FEATURE_ID_pcap; break; + case KBTS_FEATURE_TAG_pkna: Result = KBTS__FEATURE_ID_pkna; break; + case KBTS_FEATURE_TAG_pnum: Result = KBTS__FEATURE_ID_pnum; break; + case KBTS_FEATURE_TAG_pres: Result = KBTS__FEATURE_ID_pres; break; + case KBTS_FEATURE_TAG_psts: Result = KBTS__FEATURE_ID_psts; break; + case KBTS_FEATURE_TAG_pwid: Result = KBTS__FEATURE_ID_pwid; break; + case KBTS_FEATURE_TAG_qwid: Result = KBTS__FEATURE_ID_qwid; break; + case KBTS_FEATURE_TAG_rand: Result = KBTS__FEATURE_ID_rand; break; + case KBTS_FEATURE_TAG_rclt: Result = KBTS__FEATURE_ID_rclt; break; + case KBTS_FEATURE_TAG_rkrf: Result = KBTS__FEATURE_ID_rkrf; break; + case KBTS_FEATURE_TAG_rlig: Result = KBTS__FEATURE_ID_rlig; break; + case KBTS_FEATURE_TAG_rtbd: Result = KBTS__FEATURE_ID_rtbd; break; + case KBTS_FEATURE_TAG_rtla: Result = KBTS__FEATURE_ID_rtla; break; + case KBTS_FEATURE_TAG_rtlm: Result = KBTS__FEATURE_ID_rtlm; break; + case KBTS_FEATURE_TAG_ruby: Result = KBTS__FEATURE_ID_ruby; break; + case KBTS_FEATURE_TAG_rvrn: Result = KBTS__FEATURE_ID_rvrn; break; + case KBTS_FEATURE_TAG_salt: Result = KBTS__FEATURE_ID_salt; break; + case KBTS_FEATURE_TAG_sinf: Result = KBTS__FEATURE_ID_sinf; break; + case KBTS_FEATURE_TAG_size: Result = KBTS__FEATURE_ID_size; break; + case KBTS_FEATURE_TAG_smcp: Result = KBTS__FEATURE_ID_smcp; break; + case KBTS_FEATURE_TAG_smpl: Result = KBTS__FEATURE_ID_smpl; break; + case KBTS_FEATURE_TAG_ss01: Result = KBTS__FEATURE_ID_ss01; break; + case KBTS_FEATURE_TAG_ss02: Result = KBTS__FEATURE_ID_ss02; break; + case KBTS_FEATURE_TAG_ss03: Result = KBTS__FEATURE_ID_ss03; break; + case KBTS_FEATURE_TAG_ss04: Result = KBTS__FEATURE_ID_ss04; break; + case KBTS_FEATURE_TAG_ss05: Result = KBTS__FEATURE_ID_ss05; break; + case KBTS_FEATURE_TAG_ss06: Result = KBTS__FEATURE_ID_ss06; break; + case KBTS_FEATURE_TAG_ss07: Result = KBTS__FEATURE_ID_ss07; break; + case KBTS_FEATURE_TAG_ss08: Result = KBTS__FEATURE_ID_ss08; break; + case KBTS_FEATURE_TAG_ss09: Result = KBTS__FEATURE_ID_ss09; break; + case KBTS_FEATURE_TAG_ss10: Result = KBTS__FEATURE_ID_ss10; break; + case KBTS_FEATURE_TAG_ss11: Result = KBTS__FEATURE_ID_ss11; break; + case KBTS_FEATURE_TAG_ss12: Result = KBTS__FEATURE_ID_ss12; break; + case KBTS_FEATURE_TAG_ss13: Result = KBTS__FEATURE_ID_ss13; break; + case KBTS_FEATURE_TAG_ss14: Result = KBTS__FEATURE_ID_ss14; break; + case KBTS_FEATURE_TAG_ss15: Result = KBTS__FEATURE_ID_ss15; break; + case KBTS_FEATURE_TAG_ss16: Result = KBTS__FEATURE_ID_ss16; break; + case KBTS_FEATURE_TAG_ss17: Result = KBTS__FEATURE_ID_ss17; break; + case KBTS_FEATURE_TAG_ss18: Result = KBTS__FEATURE_ID_ss18; break; + case KBTS_FEATURE_TAG_ss19: Result = KBTS__FEATURE_ID_ss19; break; + case KBTS_FEATURE_TAG_ss20: Result = KBTS__FEATURE_ID_ss20; break; + case KBTS_FEATURE_TAG_ssty: Result = KBTS__FEATURE_ID_ssty; break; + case KBTS_FEATURE_TAG_stch: Result = KBTS__FEATURE_ID_stch; break; + case KBTS_FEATURE_TAG_subs: Result = KBTS__FEATURE_ID_subs; break; + case KBTS_FEATURE_TAG_sups: Result = KBTS__FEATURE_ID_sups; break; + case KBTS_FEATURE_TAG_swsh: Result = KBTS__FEATURE_ID_swsh; break; + case KBTS_FEATURE_TAG_test: Result = KBTS__FEATURE_ID_test; break; + case KBTS_FEATURE_TAG_titl: Result = KBTS__FEATURE_ID_titl; break; + case KBTS_FEATURE_TAG_tnam: Result = KBTS__FEATURE_ID_tnam; break; + case KBTS_FEATURE_TAG_tnum: Result = KBTS__FEATURE_ID_tnum; break; + case KBTS_FEATURE_TAG_trad: Result = KBTS__FEATURE_ID_trad; break; + case KBTS_FEATURE_TAG_twid: Result = KBTS__FEATURE_ID_twid; break; + case KBTS_FEATURE_TAG_unic: Result = KBTS__FEATURE_ID_unic; break; + case KBTS_FEATURE_TAG_valt: Result = KBTS__FEATURE_ID_valt; break; + case KBTS_FEATURE_TAG_vapk: Result = KBTS__FEATURE_ID_vapk; break; + case KBTS_FEATURE_TAG_vatu: Result = KBTS__FEATURE_ID_vatu; break; + case KBTS_FEATURE_TAG_vchw: Result = KBTS__FEATURE_ID_vchw; break; + case KBTS_FEATURE_TAG_vert: Result = KBTS__FEATURE_ID_vert; break; + case KBTS_FEATURE_TAG_vhal: Result = KBTS__FEATURE_ID_vhal; break; + case KBTS_FEATURE_TAG_vkna: Result = KBTS__FEATURE_ID_vkna; break; + case KBTS_FEATURE_TAG_vkrn: Result = KBTS__FEATURE_ID_vkrn; break; + case KBTS_FEATURE_TAG_vpal: Result = KBTS__FEATURE_ID_vpal; break; + case KBTS_FEATURE_TAG_vrt2: Result = KBTS__FEATURE_ID_vrt2; break; + case KBTS_FEATURE_TAG_vrtr: Result = KBTS__FEATURE_ID_vrtr; break; + case KBTS_FEATURE_TAG_zero: Result = KBTS__FEATURE_ID_zero; break; + default: break; + } + return Result; +} + +static kbts_s32 kbts__UnicodeParentDeltas[1679] = { + 132,133,134,135,244,246,248,250,252,254,315,351,416,418,7678,7680,7682,7792,7794,132,133,134,135,275,277,279,281,283,285,346,382,447, + 449,7709,7711,7713,7823,7825,131,132,133,134,174,176,178,180,182,416,418,452,7604,7606,7764,7766,7768,131,132,133,134,205,207,209,211,213, + 447,449,483,7635,7637,7795,7797,7799,127,128,129,130,131,132,160,162,164,365,416,418,454,7584,7744,7746,127,128,129,130,131,132,191,193, + 195,396,447,449,485,7615,7775,7777,131,132,133,134,135,222,224,226,306,355,380,414,416,448,7774,7776,131,132,133,134,135,253,255,257, + 337,386,411,445,447,479,7805,7807,131,132,133,134,223,225,227,229,231,390,447,449,7651,7807,7809,131,132,133,134,192,194,196,198,359, + 416,418,7620,7776,7778,132,134,254,442,7702,7712,7802,7804,7806,7808,-10,17,7031,7032,7101,7173,7191,7192,7197,131,214,216,218,395,7639,7641,7643, + 7645,131,245,247,249,426,7670,7672,7674,7676,132,285,287,473,7733,7833,7835,7837,7839,227,229,231,415,417,7655,7657,7661,6,8,7051,7052,7093, + 7195,7196,7201,189,439,7611,7613,7615,7617,7619,7726,239,241,423,7671,7673,7675,7677,7715,-5,6991,6992,7103,7167,7168,7170,7173,258,260,262,446,448, + 7686,7688,7692,182,184,186,188,384,398,7610,213,215,217,219,415,429,7641,232,234,236,238,422,7662,7664,263,265,267,269,453,7693,7695,-15, + 17,7071,7072,7231,7232,7233,220,470,7642,7644,7646,7648,7650,-11,7031,7032,7207,7208,7209,7211,254,7690,7692,7694,7696,7698,7713,270,272,454,7702,7704, + 7706,7708,206,208,210,7627,7631,7633,-23,6,7092,7235,7236,7237,-26,7103,7104,7249,7251,7549,235,413,7653,7655,7657,8415,237,239,241,7658,7662,7664, + -9,7017,7018,7101,7180,7183,5,7063,7064,7091,7210,7213,256,258,260,7703,7705,7707,171,7591,7593,7595,7597,7599,287,289,291,7734,7736,7738,202,7622, + 7624,7626,7628,7630,285,7721,7723,7725,7727,7729,-3,-2,-1,3,4,1,2,3,4,5,132,164,166,168,170,-14,7057,7058,7219,7221,132,195, + 197,199,201,7481,7483,7485,7487,7489,7482,7484,7486,7488,7490,204,382,7622,7624,7626,2,4,6,64,3,4,5,7,-21,203,205,207,2,4, + 6,112,-11,1,202,204,2,4,6,128,1,37,171,173,-8,7003,7004,7101,-19,7081,7082,7257,27,172,174,176,-13,7043,7044,7219,218,220, + 222,224,249,251,253,255,13,7041,7042,7097,7596,7598,7600,7602,7619,7621,7623,7625,7637,7639,7641,7643,7645,7647,7649,7651,7650,7652,7654,7656,7668,7670, + 7672,7674,7676,7678,7680,7682,-33,-32,-31,-58,7176,7181,-27,7191,7196,-5,-4,-2,1,2,4,1,3,5,2,3,5,1,4,5,-21,-20, + 193,2,4,16,3,5,6,14,15,16,27,28,162,312,7512,7514,343,7543,7545,7585,7587,7589,733,7961,8005,7616,7618,7620,7634,7636,7638,7665, + 7667,7669,22891,22892,23346,31318,31405,162165,31650,31843,31932,35977,36182,166849,36278,36572,167227,36626,36698,36797,62785,62786,62816,25280,156147,156148,37394,37755,168385,38990,39065,169662, + 62814,62815,62816,39089,39163,169757,40312,40387,171144,173234,173235,173236,-29,-28,12,22,161,163,140,167,171,198,253,279,203,390,284,310,7109,7176,7111,7190, + 7087,7206,7203,7204,7426,7428,7428,7430,7684,7686,309,8294,7687,7689,7699,7701,7718,7720,7730,7732,25135,25233,25194,25291,25286,25458,25477,25572,27117,27183,27997,28089, + 28255,28607,28357,28407,28458,28550,28458,28610,28513,28603,28875,28962,30692,30693,24507,155384,32406,32493,27530,158375,28470,159303,33613,33756,28625,159459,29500,160322,34266,34388,34540,34678, + 29402,160600,30216,161096,35034,35118,30351,161459,32788,163609,32908,163783,35621,35704,37790,37917,32943,164035,33018,163837,40630,40631,41398,41506,42137,42203,33247,163972,54624,54625,33631,164350, + 33716,164428,33778,164808,34352,165055,34921,165612,35453,166134,35790,166464,62788,62816,62816,62826,36046,166794,62816,62834,62816,62838,37311,168029,37752,168382,37810,168510,62816,62843,161426,161674, + 38130,168825,38679,169659,39225,169818,39337,169999,39518,170436,40398,171018,42033,172614,42209,172718,164391,164392,169819,169821,42724,173276,42572,173332,42877,173358,42832,173379,170354,170355,42858,173405, + 42927,173406,43001,173641,43196,173670,43237,173761,171308,171309,43338,173859,172737,172738,43650,174167,47771,178448,178804,178805,48949,179530,-99324,-90618,-87924,-84098,-80132,-77179,-77172,-3295,-163,-70, + -60,-59,-36,-16,-6,9,10,26,32,34,41,48,51,55,56,59,60,63,66,67,78,81,100,118,169,187,200,278,282,294,340,720, + 835,7085,7086,7110,7112,7156,7234,7243,7261,7273,7276,7277,7434,7440,7452,7458,7519,7609,7640,8009,8079,8739,8753,8754,21533,21757,22403,22533,22797,22850,23095,23227, + 23233,23281,23298,23360,23371,23380,23445,23673,23963,24010,24281,24349,24361,24836,24879,24891,24946,24988,25094,25170,25195,25276,25316,25326,25344,25350,25352,25422,25430,25435,25464,25496, + 25532,25561,25674,25675,25959,26097,26171,26173,26193,26425,26493,26543,26589,26627,26653,26703,26718,26756,26801,26921,26923,26951,26960,26999,27073,27179,27192,27217,27250,27309,27312,27340, + 27464,27707,27770,27782,27832,28049,28122,28147,28267,28324,28331,28608,28656,28666,28698,28799,28894,28935,28936,28952,28977,29008,29015,29045,29116,29367,29393,29426,29487,29526,29684,29686, + 29710,29867,29894,29915,29989,30055,30069,30405,30408,30477,30542,30561,30734,30805,30831,30919,30920,31016,31027,31082,31114,31253,31329,31341,31401,31464,31513,31603,31641,31645,31768,31776, + 31816,31823,31892,31935,31972,32043,32045,32084,32095,32103,32104,32307,32472,32556,32570,32701,32715,32724,32763,32776,32859,32870,32873,32893,32949,32955,32965,32988,33012,33023,33028,33030, + 33038,33053,33123,33210,33356,33388,33445,33526,33630,33642,33663,33740,33795,33809,33908,33926,33927,34059,34105,34117,34135,34152,34204,34243,34270,34273,34299,34344,34351,34354,34532,34563, + 34594,34618,34800,34802,34846,34877,34890,35031,35039,35127,35170,35206,35327,35379,35391,35439,35457,35631,35634,35699,35773,35776,35820,35834,35882,35884,35898,35996,36049,36071,36074,36094, + 36206,36343,36373,36377,36443,36446,36636,36665,37113,37178,37315,37331,37334,37344,37389,37453,37469,37523,37573,37693,37694,37714,37822,37837,37846,37873,37925,37977,37984,37996,38049,38135, + 38202,38357,38441,38457,38461,38492,38514,38517,38540,38556,38590,38601,38700,38703,38730,38800,38820,38911,39000,39061,39126,39128,39210,39246,39296,39312,39342,39357,39397,39414,39487,39501, + 39574,39640,39641,39706,39707,39736,39771,39850,39856,39889,39921,40124,40165,40169,40314,40318,40374,40407,40575,40793,40888,40900,40928,40974,40990,41059,41074,41230,41259,41274,41362,41418, + 41465,41616,41648,41658,41772,41860,41936,42061,42273,42276,42288,42302,42407,42408,42447,42448,42577,42624,42634,42668,42735,42746,42814,42871,42872,42885,42889,42928,42932,42949,43023,43025, + 43050,43063,43086,43088,43108,43212,43233,43253,43257,43274,43311,43396,43418,43430,43431,43433,43562,43673,43716,43721,43731,43763,43813,43828,43837,43866,44106,44197,44287,45331,45553,45851, + 46452,46778,47491,47538,47676,47803,48104,48191,48639,48746,49225,49737,50294,50458,50655,50670,50678,50721,51392,52429,52652,53712,55046,55194,55959,56301,56665,56996,57719,57784,58229,60629, + 60936,61695,61907,61909,62155,62198,62454,62765,63201,154337,154373,154379,154388,154394,154398,154458,154792,154895,155083,155657,155716,155742,155867,155936,156119,156186,156370,156464,156729,156771,157143,157170, + 157457,157550,157615,157899,157907,157938,158030,158191,158474,158700,158735,158751,158816,158907,158996,159017,159101,159535,159951,159977,159983,160097,160099,160192,160223,160312,160338,160404,160427,160472,160526,160560, + 160589,160590,160611,160840,160916,160950,160951,161207,161223,161238,161239,161248,161262,161335,161357,161401,161404,161456,161496,161505,161506,161524,161534,161541,161672,161833,161863,161920,162000,162063,162077,162175, + 162275,162300,162603,162669,162727,162825,162922,162944,162950,162964,163226,163228,163441,163596,163600,163692,164096,164287,164650,164856,164880,164968,165036,165075,165095,165254,165278,165294,165520,165540,165586,165624, + 165762,165829,165847,165997,166043,166050,166093,166106,166138,166220,166305,166469,166555,166617,166677,166784,166796,166810,166850,166867,166889,166960,166973,167063,167084,167253,167297,167325,167374,167442,167491,167680, + 167750,167846,167890,168022,168079,168134,168165,168283,168317,168329,168377,168404,168505,168580,168680,168797,169000,169030,169039,169050,169117,169177,169211,169240,169273,169299,169319,169340,169406,169442,169476,169559, + 169624,169634,169681,169722,169727,169737,169776,169822,169950,170015,170150,170183,170192,170242,170273,170287,170295,170386,170455,170457,170459,170526,170569,170589,170631,170656,170756,170768,170772,170809,170937,170989, + 171031,171074,171091,171117,171123,171133,171158,171178,171361,171520,171581,171592,171638,171661,171729,171773,171836,171843,171862,171875,171876,171880,171948,172068,172070,172103,172127,172164,172234,172341,172342,172507, + 172541,172680,172694,172701,172769,172784,172850,172875,172958,173015,173046,173061,173109,173129,173134,173144,173164,173244,173268,173283,173348,173484,173488,173531,173541,173595,173608,173678,173684,173696,173704,173722, + 173740,173741,173755,173791,173884,173886,173888,173936,173966,174085,174155,174244,174413,174529,174531,174537,175296,175385,175393,175423,175674,175824,175946,176003,176010,176140,176218,176903,176911,177043,177097,177128, + 177223,177230,177233,177276,177406,177443,177529,177580,177691,177725,177772,177863,177981,178014,178217,178286,178358,178437,178487,178498,178712,178814,179072,179159,179364,179414,179605,179637,179656,179693,179803,179860, + 180071,180102,180152,180175,180238,180262,180308,180469,180588,180601,181007,181056,181082,181102,181519, +}; + +static kbts_u8 kbts__ScriptExtensions[447] = { + 6,18,24,25,35,37,41,42,43,45,47,72,79,80,112,132,11,28,32,72,77,155,160,13,72,72,155,22,25,28,45,72, + 112,141,146,22,28,45,72,119,141,146,159,22,28,72,157,42,72,141,143,155,19,22,25,28,43,45,72,119,143,157,159,25, + 37,42,43,62,72,25,35,54,72,112,143,146,157,159,5,28,35,43,45,54,72,112,143,146,35,72,143,22,28,72,119,22, + 72,146,39,72,28,72,159,45,72,112,159,22,35,62,72,143,22,35,72,143,22,72,143,19,22,43,72,141,155,19,72,159, + 25,45,28,112,28,42,5,41,42,4,40,51,103,143,154,167,4,143,154,1,4,40,51,103,143,154,167,1,4,51,83,84, + 117,126,135,143,4,154,167,11,32,44,46,48,61,72,82,118,131,150,153,158,11,32,44,46,48,61,72,82,118,150,153,158, + 11,32,34,44,46,47,48,61,69,80,82,86,100,108,118,136,142,149,150,153,158,11,32,34,44,46,47,48,49,61,69,74, + 80,82,86,100,108,118,136,142,149,150,153,158,32,34,60,80,11,20,142,48,96,46,68,44,150,61,100,161,20,97,146,41, + 42,72,16,52,144,145,94,124,11,32,44,61,32,131,32,61,82,118,150,153,32,100,11,32,44,61,82,100,118,136,153,158, + 161,32,44,61,161,28,72,143,72,94,124,18,41,42,78,110,116,18,45,91,110,32,44,72,25,72,6,116,6,18,41,60, + 79,110,129,1,4,110,24,152,13,24,50,55,62,94,168,13,24,50,55,62,94,124,168,13,24,50,55,62,94,156,168,13, + 24,50,55,62,77,94,156,168,13,24,50,55,62,168,24,55,62,24,72,32,34,46,48,60,61,68,69,80,82,93,100,131, + 149,158,161,32,34,46,48,60,61,68,69,80,93,100,131,149,158,161,32,34,46,48,60,68,69,80,93,149,158,32,34,46, + 48,60,68,69,80,93,131,149,158,11,32,161,32,150,64,72,97,15,59,4,103,26,27,76,26,76,26,75,76,4,25, +}; + +static kbts_u8 kbts__UnicodeDecomposition_PageIndices[17407] = { + 0,1,1,2,3,4,5,6,7,1,1,1,1,8,9,10,11,12,1,13,1,1,1,1,14,1,1,15,1,1,1,1, + 1,1,1,1,16,17,1,18,19,20,1,1,1,21,1,22,1,23,1,24,1,25,1,26,1,1,1,1,1,27,28,1, + 29,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,30,31, + 1,1,1,1,1,1,1,1,1,1,1,1,32,33,1,1,1,1,1,1,1,1,1,1,34,35,36,37,38,39,40,41, + 42,1,1,1,43,1,44,45,46,47,48,49,50,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,52,53,54,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,55,56,57,58,59,60,61,62,63,64,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,65,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,66,1,67,1,1,1,1,1,1,1,1,68,69,70,1,1,71,1,1,1,72,1,1,1,1,1,1,1,1,1, + 1,1,1,1,73,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,74,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,75,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,76,77,78,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 79,80,81,82,83,84,85,86,87,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +static kbts_u64 kbts__UnicodeDecomposition_Data[5632] = { + 52776558133248ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6442451206ull,6450839814ull,6459228422ull,6467617030ull,6509560070ull,6526337286ull,0ull,6769606926ull,6442451222ull,6450839830ull,6459228438ull,6509560086ull,6442451238ull,6450839846ull,6459228454ull,6509560102ull,0ull,6467617082ull,6442451262ull,6450839870ull,6459228478ull,6467617086ull,6509560126ull,0ull,0ull,6442451286ull,6450839894ull,6459228502ull,6509560150ull,6450839910ull,0ull,0ull, + 6442451334ull,6450839942ull,6459228550ull,6467617158ull,6509560198ull,6526337414ull,0ull,6769607054ull,6442451350ull,6450839958ull,6459228566ull,6509560214ull,6442451366ull,6450839974ull,6459228582ull,6509560230ull,0ull,6467617210ull,6442451390ull,6450839998ull,6459228606ull,6467617214ull,6509560254ull,0ull,0ull,6442451414ull,6450840022ull,6459228630ull,6509560278ull,6450840038ull,0ull,6509560294ull, + 6476005638ull,6476005766ull,6492782854ull,6492782982ull,6777995526ull,6777995654ull,6450839822ull,6450839950ull,6459228430ull,6459228558ull,6501171470ull,6501171598ull,6543114510ull,6543114638ull,6543114514ull,6543114642ull,0ull,0ull,6476005654ull,6476005782ull,6492782870ull,6492782998ull,6501171478ull,6501171606ull,6777995542ull,6777995670ull,6543114518ull,6543114646ull,6459228446ull,6459228574ull,6492782878ull,6492783006ull, + 6501171486ull,6501171614ull,6769606942ull,6769607070ull,6459228450ull,6459228578ull,0ull,0ull,6467617062ull,6467617190ull,6476005670ull,6476005798ull,6492782886ull,6492783014ull,6777995558ull,6777995686ull,6501171494ull,0ull,0ull,0ull,6459228458ull,6459228586ull,6769606958ull,6769607086ull,0ull,6450839858ull,6450839986ull,6769606962ull,6769607090ull,6543114546ull,6543114674ull,0ull, + 0ull,0ull,0ull,6450839866ull,6450839994ull,6769606970ull,6769607098ull,6543114554ull,6543114682ull,0ull,0ull,0ull,6476005694ull,6476005822ull,6492782910ull,6492783038ull,6534725950ull,6534726078ull,0ull,0ull,6450839882ull,6450840010ull,6769606986ull,6769607114ull,6543114570ull,6543114698ull,6450839886ull,6450840014ull,6459228494ull,6459228622ull,6769606990ull,6769607118ull, + 6543114574ull,6543114702ull,6769606994ull,6769607122ull,6543114578ull,6543114706ull,0ull,0ull,6467617110ull,6467617238ull,6476005718ull,6476005846ull,6492782934ull,6492783062ull,6526337366ull,6526337494ull,6534725974ull,6534726102ull,6777995606ull,6777995734ull,6459228510ull,6459228638ull,6459228518ull,6459228646ull,6509560166ull,6450839914ull,6450840042ull,6501171562ull,6501171690ull,6543114602ull,6543114730ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6668943678ull,6668943806ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6668943702ull,6668943830ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6543114502ull,6543114630ull,6543114534ull,6543114662ull,6543114558ull,6543114686ull,6543114582ull,6543114710ull,6476006258ull,6476006386ull,6450840434ull,6450840562ull,6543115122ull,6543115250ull,6442451826ull,6442451954ull,0ull,6476006162ull,6476006290ull, + 6476007578ull,6476007582ull,6476006170ull,6476006298ull,0ull,0ull,6543114526ull,6543114654ull,6543114542ull,6543114670ull,6777995582ull,6777995710ull,6476007338ull,6476007342ull,6543115998ull,6543116874ull,6543114666ull,0ull,0ull,0ull,6450839838ull,6450839966ull,0ull,0ull,6442451258ull,6442451386ull,6450840342ull,6450840470ull,6450840346ull,6450840474ull,6450840418ull,6450840546ull, + 6568280326ull,6568280454ull,6585057542ull,6585057670ull,6568280342ull,6568280470ull,6585057558ull,6585057686ull,6568280358ull,6568280486ull,6585057574ull,6585057702ull,6568280382ull,6568280510ull,6585057598ull,6585057726ull,6568280394ull,6568280522ull,6585057610ull,6585057738ull,6568280406ull,6568280534ull,6585057622ull,6585057750ull,6761218382ull,6761218510ull,6761218386ull,6761218514ull,0ull,0ull,6543114530ull,6543114658ull, + 0ull,0ull,0ull,0ull,0ull,0ull,6501171462ull,6501171590ull,6769606934ull,6769607062ull,6476006234ull,6476006362ull,6476006230ull,6476006358ull,6501171518ull,6501171646ull,6476007610ull,6476007614ull,6476005734ull,6476005862ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 3073ull,3077ull,0ull,3149ull,6450842658ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,2789ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,237ull,0ull, + 0ull,0ull,0ull,0ull,0ull,6450840226ull,6450843206ull,733ull,6450843222ull,6450843230ull,6450843238ull,0ull,6450843262ull,0ull,6450843286ull,6450843302ull,6450843434ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6509563494ull,6509563542ull,6450843334ull,6450843350ull,6450843358ull,6450843366ull,6450843438ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6509563622ull,6509563670ull,6450843390ull,6450843414ull,6450843430ull,0ull,0ull,0ull,0ull,6450843466ull,6509563722ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6442455126ull,6509563990ull,0ull,6450843726ull,0ull,0ull,0ull,6509563930ull,0ull,0ull,0ull,0ull,6450843754ull,6442455138ull,6492786830ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6492786786ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6492786914ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6442455254ull,6509564118ull,0ull,6450843854ull,0ull,0ull,0ull,6509564250ull,0ull,0ull,0ull,0ull,6450843882ull,6442455266ull,6492786958ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6568284626ull,6568284630ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,6492786778ull,6492786906ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6492786754ull,6492786882ull,6509563970ull,6509564098ull,0ull,0ull,6492786774ull,6492786902ull,0ull,0ull,6509564770ull,6509564774ull,6509563994ull,6509564122ull,6509563998ull,6509564126ull, + 0ull,0ull,6476009570ull,6476009698ull,6509564002ull,6509564130ull,6509564026ull,6509564154ull,0ull,0ull,6509564834ull,6509564838ull,6509564086ull,6509564214ull,6476009614ull,6476009742ull,6509564046ull,6509564174ull,6534729870ull,6534729998ull,6509564062ull,6509564190ull,0ull,0ull,6509564078ull,6509564206ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,13581162654ull,13589551262ull,13589551394ull,13597939870ull,13589551402ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 13589551958ull,0ull,13589551878ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,13589551946ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,19830678690ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,19830678734ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,19830678614ull,19830678618ull,19830678622ull,19830678642ull,19830678662ull,19830678666ull,19830678702ull,19830678718ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,20921198366ull,21130913566ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,20904421054ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,21978163402ull,0ull,0ull,21978163426ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,21978163290ull,21978163294ull,21978163314ull,0ull,0ull,21978163374ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,24343751966ull,0ull,0ull,24142425374ull,24352140574ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,24125648006ull,24125648010ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,25216167706ull,25216167710ull,25425882906ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,26491236634ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 27556590334ull,0ull,0ull,0ull,0ull,0ull,0ull,27556590362ull,27564978970ull,0ull,27397206810ull,27556590378ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,28437394714ull,28437394718ull,28647109914ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,29611800422ull,0ull,29653743462ull,29611800434ull,29787961190ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,33747385610ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33747385650ull,0ull,0ull,0ull,0ull,33747385670ull,0ull,0ull,0ull,0ull,33747385690ull,0ull,0ull,0ull,0ull,33747385710ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33730608386ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33168571846ull,0ull,33185349062ull,33286012618ull,0ull,33286012622ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,33286012358ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33747385930ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33747385970ull,0ull,0ull, + 0ull,0ull,33747385990ull,0ull,0ull,0ull,0ull,33747386010ull,0ull,0ull,0ull,0ull,33747386030ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,33730608706ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,34745630870ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,35235358072582ull,35235366461190ull, + 35235374849798ull,0ull,0ull,0ull,35235408404230ull,35235416792838ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,58426682390ull,0ull,58426682398ull,0ull,58426682406ull,0ull,58426682414ull,0ull,58426682422ull,0ull,0ull,0ull,58426682438ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,58426682602ull,0ull,58426682610ull,0ull,0ull, + 58426682618ull,58426682622ull,0ull,58426682634ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6752829702ull,6752829830ull,6501171466ull,6501171594ull,6736052490ull,6736052618ull,6853493002ull,6853493130ull,6450840350ull,6450840478ull,6501171474ull,6501171602ull,6736052498ull,6736052626ull,6853493010ull,6853493138ull,6769606930ull,6769607058ull,6819938578ull,6819938706ull,6442452042ull,6442452046ull,6450840650ull,6450840654ull,6819938582ull,6819938710ull,6845104406ull,6845104534ull,6492784802ull,6492784806ull,6501171482ull,6501171610ull, + 6476005662ull,6476005790ull,6501171490ull,6501171618ull,6736052514ull,6736052642ull,6509560098ull,6509560226ull,6769606946ull,6769607074ull,6828327202ull,6828327330ull,6845104422ull,6845104550ull,6450840382ull,6450840510ull,6450839854ull,6450839982ull,6736052526ull,6736052654ull,6853493038ull,6853493166ull,6736052530ull,6736052658ull,6476036314ull,6476036318ull,6853493042ull,6853493170ull,6819938610ull,6819938738ull,6450839862ull,6450839990ull, + 6501171510ull,6501171638ull,6736052534ull,6736052662ull,6501171514ull,6501171642ull,6736052538ull,6736052666ull,6853493050ull,6853493178ull,6819938618ull,6819938746ull,6450840406ull,6450840534ull,6509560662ull,6509560790ull,6442452274ull,6442452278ull,6450840882ull,6450840886ull,6450839874ull,6450840002ull,6501171522ull,6501171650ull,6501171530ull,6501171658ull,6736052554ull,6736052682ull,6476036458ull,6476036462ull,6853493066ull,6853493194ull, + 6501171534ull,6501171662ull,6736052558ull,6736052686ull,6501172586ull,6501172590ull,6501172610ull,6501172614ull,6501202314ull,6501202318ull,6501171538ull,6501171666ull,6736052562ull,6736052690ull,6853493074ull,6853493202ull,6819938642ull,6819938770ull,6744441174ull,6744441302ull,6845104470ull,6845104598ull,6819938646ull,6819938774ull,6450840994ull,6450840998ull,6509561258ull,6509561262ull,6467617114ull,6467617242ull,6736052570ull,6736052698ull, + 6442451294ull,6442451422ull,6450839902ull,6450840030ull,6509560158ull,6509560286ull,6501171550ull,6501171678ull,6736052574ull,6736052702ull,6501171554ull,6501171682ull,6509560162ull,6509560290ull,6501171558ull,6501171686ull,6459228522ull,6459228650ull,6736052586ull,6736052714ull,6853493098ull,6853493226ull,6853493154ull,6509560274ull,6526337502ull,6526337510ull,0ull,6501172734ull,0ull,0ull,0ull,0ull, + 6736052486ull,6736052614ull,6517948678ull,6517948806ull,6450840330ull,6450840458ull,6442451722ull,6442451850ull,6517949194ull,6517949322ull,6467617546ull,6467617674ull,6459259522ull,6459259526ull,6450840586ull,6450840590ull,6442451978ull,6442451982ull,6517949450ull,6517949454ull,6467617802ull,6467617806ull,6492813954ull,6492813958ull,6736052502ull,6736052630ull,6517948694ull,6517948822ull,6467617046ull,6467617174ull,6450840362ull,6450840490ull, + 6442451754ull,6442451882ull,6517949226ull,6517949354ull,6467617578ull,6467617706ull,6459259618ull,6459259622ull,6517948710ull,6517948838ull,6736052518ull,6736052646ull,6736052542ull,6736052670ull,6517948734ull,6517948862ull,6450840402ull,6450840530ull,6442451794ull,6442451922ull,6517949266ull,6517949394ull,6467617618ull,6467617746ull,6459259698ull,6459259702ull,6450841218ull,6450841222ull,6442452610ull,6442452614ull,6517950082ull,6517950086ull, + 6467618434ull,6467618438ull,6736053890ull,6736053894ull,6736052566ull,6736052694ull,6517948758ull,6517948886ull,6450841278ull,6450841282ull,6442452670ull,6442452674ull,6517950142ull,6517950146ull,6467618494ull,6467618498ull,6736053950ull,6736053954ull,6442451302ull,6442451430ull,6736052582ull,6736052710ull,6517948774ull,6517948902ull,6467617126ull,6467617254ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6601838278ull,6610226886ull,6442482690ull,6442482694ull,6450871298ull,6450871302ull,6996130818ull,6996130822ull,6601838150ull,6610226758ull,6442482722ull,6442482726ull,6450871330ull,6450871334ull,6996130850ull,6996130854ull,6601838294ull,6610226902ull,6442482754ull,6442482758ull,6450871362ull,6450871366ull,0ull,0ull,6601838166ull,6610226774ull,6442482786ull,6442482790ull,6450871394ull,6450871398ull,0ull,0ull, + 6601838302ull,6610226910ull,6442482818ull,6442482822ull,6450871426ull,6450871430ull,6996130946ull,6996130950ull,6601838174ull,6610226782ull,6442482850ull,6442482854ull,6450871458ull,6450871462ull,6996130978ull,6996130982ull,6601838310ull,6610226918ull,6442482882ull,6442482886ull,6450871490ull,6450871494ull,6996131010ull,6996131014ull,6601838182ull,6610226790ull,6442482914ull,6442482918ull,6450871522ull,6450871526ull,6996131042ull,6996131046ull, + 6601838334ull,6610226942ull,6442482946ull,6442482950ull,6450871554ull,6450871558ull,0ull,0ull,6601838206ull,6610226814ull,6442482978ull,6442482982ull,6450871586ull,6450871590ull,0ull,0ull,6601838358ull,6610226966ull,6442483010ull,6442483014ull,6450871618ull,6450871622ull,6996131138ull,6996131142ull,0ull,6610226838ull,0ull,6442483046ull,0ull,6450871654ull,0ull,6996131174ull, + 6601838374ull,6610226982ull,6442483074ull,6442483078ull,6450871682ull,6450871686ull,6996131202ull,6996131206ull,6601838246ull,6610226854ull,6442483106ull,6442483110ull,6450871714ull,6450871718ull,6996131234ull,6996131238ull,6442454726ull,3761ull,6442454742ull,3765ull,6442454750ull,3769ull,6442454758ull,3773ull,6442454782ull,3889ull,6442454806ull,3893ull,6442454822ull,3897ull,0ull,0ull, + 7021296642ull,7021296646ull,7021296650ull,7021296654ull,7021296658ull,7021296662ull,7021296666ull,7021296670ull,7021296674ull,7021296678ull,7021296682ull,7021296686ull,7021296690ull,7021296694ull,7021296698ull,7021296702ull,7021296770ull,7021296774ull,7021296778ull,7021296782ull,7021296786ull,7021296790ull,7021296794ull,7021296798ull,7021296802ull,7021296806ull,7021296810ull,7021296814ull,7021296818ull,7021296822ull,7021296826ull,7021296830ull, + 7021297026ull,7021297030ull,7021297034ull,7021297038ull,7021297042ull,7021297046ull,7021297050ull,7021297054ull,7021297058ull,7021297062ull,7021297066ull,7021297070ull,7021297074ull,7021297078ull,7021297082ull,7021297086ull,6492786374ull,6476009158ull,7021297090ull,7021268678ull,7021268658ull,0ull,6996102854ull,7021297370ull,6492786246ull,6476009030ull,6442454598ull,3609ull,7021268550ull,0ull,3813ull,0ull, + 0ull,6996099746ull,7021297106ull,7021268702ull,7021268666ull,0ull,6996102878ull,7021297434ull,6442454614ull,3617ull,6442454622ull,3621ull,7021268574ull,6442483454ull,6450872062ull,6996131582ull,6492786406ull,6476009190ull,6442454826ull,3649ull,0ull,0ull,6996102886ull,6996102954ull,6492786278ull,6476009062ull,6442454630ull,3625ull,0ull,6442483706ull,6450872314ull,6996131834ull, + 6492786454ull,6476009238ull,6442454830ull,3777ull,6601838342ull,6610226950ull,6996102934ull,6996102958ull,6492786326ull,6476009110ull,6442454678ull,3641ull,6610226822ull,6442451618ull,3605ull,385ull,0ull,0ull,7021297138ull,7021268774ull,7021268794ull,0ull,6996102950ull,7021297626ull,6442454654ull,3633ull,6442454694ull,3645ull,7021268646ull,721ull,0ull,0ull, + 32777ull,32781ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,32833ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,3749ull,0ull,0ull,0ull,301ull,789ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912247362ull,6912247370ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912247378ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912247618ull,6912247634ull,6912247626ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,6912247822ull,0ull,0ull,0ull,0ull,6912247842ull,0ull,0ull,6912247854ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,6912247950ull,0ull,6912247958ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,6912248050ull,0ull,0ull,6912248078ull,0ull,0ull,6912248086ull,0ull,6912248098ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6912213238ull,0ull,6912248198ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912248118ull,6912213234ull,6912213242ull,6912248210ull,6912248214ull,0ull,0ull,6912248266ull,6912248270ull,0ull,0ull,6912248282ull,6912248286ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6912248298ull,6912248302ull,0ull,0ull,6912248330ull,6912248334ull,0ull,0ull,6912248346ull,6912248350ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912248458ull,6912248482ull,6912248486ull,6912248494ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 6912248306ull,6912248310ull,6912248390ull,6912248394ull,0ull,0ull,0ull,0ull,0ull,0ull,6912248522ull,6912248526ull,6912248530ull,6912248534ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,49185ull,49189ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6912256886ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721582ull,0ull,104362721590ull,0ull,104362721598ull,0ull,104362721606ull,0ull,104362721614ull,0ull,104362721622ull,0ull,104362721630ull,0ull,104362721638ull,0ull,104362721646ull,0ull,104362721654ull,0ull, + 104362721662ull,0ull,104362721670ull,0ull,0ull,104362721682ull,0ull,104362721690ull,0ull,104362721698ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721726ull,104371110334ull,0ull,104362721738ull,104371110346ull,0ull,104362721750ull,104371110358ull,0ull,104362721762ull,104371110370ull,0ull,104362721774ull,104371110382ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721562ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721910ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721966ull,0ull,104362721974ull,0ull,104362721982ull,0ull,104362721990ull,0ull,104362721998ull,0ull,104362722006ull,0ull,104362722014ull,0ull,104362722022ull,0ull,104362722030ull,0ull,104362722038ull,0ull, + 104362722046ull,0ull,104362722054ull,0ull,0ull,104362722066ull,0ull,104362722074ull,0ull,104362722082ull,0ull,0ull,0ull,0ull,0ull,0ull,104362722110ull,104371110718ull,0ull,104362722122ull,104371110730ull,0ull,104362722134ull,104371110742ull,0ull,104362722146ull,104371110754ull,0ull,104362722158ull,104371110766ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,104362721946ull,0ull,0ull,104362722238ull,104362722242ull,104362722246ull,104362722250ull,0ull,0ull,0ull,104362722294ull,0ull, + 143649ull,105425ull,146217ull,144161ull,113477ull,80073ull,85909ull,163441ull,163441ull,91461ull,149317ull,87581ull,91425ull,100313ull,121253ull,130581ull,137469ull,138985ull,140257ull,148029ull,108553ull,111725ull,115557ull,118649ull,135413ull,148905ull,157637ull,80393ull,85461ull,109585ull,116845ull,137397ull, + 161913ull,95553ull,114605ull,137013ull,140689ull,101157ull,132961ull,139389ull,97065ull,105565ull,112041ull,117745ull,148281ull,81433ull,83677ull,84857ull,103185ull,109389ull,116801ull,121757ull,131077ull,137241ull,137585ull,145341ull,154825ull,159165ull,161769ull,123441ull,124413ull,128641ull,134949ull,150545ull, + 162301ull,142169ull,91005ull,97297ull,127361ull,131577ull,117129ull,123689ull,144137ull,154589ull,90977ull,94601ull,108621ull,112489ull,113725ull,128189ull,129245ull,153901ull,84809ull,131629ull,83825ull,83761ull,125041ull,128761ull,135109ull,154069ull,142849ull,101181ull,108553ull,142329ull,80101ull,94109ull, + 98377ull,118301ull,120257ull,85085ull,123885ull,81661ull,97957ull,79925ull,111409ull,103905ull,128137ull,85773ull,90489ull,121861ull,135461ull,141993ull,110313ull,147137ull,111137ull,101369ull,134037ull,102017ull,120213ull,80569ull,83365ull,83749ull,107013ull,127901ull,133565ull,142153ull,149309ull,84949ull, + 86281ull,91597ull,97201ull,104213ull,114681ull,124073ull,153269ull,158121ull,162397ull,162617ull,84589ull,105241ull,110045ull,146825ull,96721ull,99905ull,100353ull,103017ull,113805ull,116005ull,119333ull,124713ull,128977ull,131517ull,146585ull,136121ull,147597ull,150825ull,84061ull,84621ull,86773ull,115489ull, + 140041ull,141993ull,97061ull,98261ull,101869ull,110265ull,127225ull,118229ull,80785ull,89061ull,94109ull,95977ull,98417ull,118473ull,119205ull,130665ull,131353ull,149713ull,154585ull,154913ull,155745ull,81453ull,124601ull,149201ull,154337ull,99205ull,80409ull,82793ull,94137ull,94461ull,104037ull,108553ull, + 116537ull,121097ull,136177ull,147953ull,163381ull,104993ull,153785ull,84517ull,105965ull,106445ull,111877ull,113265ull,118821ull,120165ull,123309ull,128065ull,156025ull,83381ull,100537ull,154081ull,82093ull,95333ull,112553ull,146601ull,97837ull,99601ull,106589ull,118301ull,154137ull,84133ull,86077ull,94613ull, + 104525ull,105785ull,107169ull,111509ull,118809ull,120713ull,130533ull,140093ull,140165ull,149297ull,154505ull,85245ull,113385ull,86133ull,116545ull,119393ull,137193ull,154253ull,160093ull,162429ull,106077ull,112429ull,133025ull,125741ull,126081ull,127561ull,117505ull,115301ull,142689ull,80641ull,134361ull,84201ull, + 83997ull,96921ull,101197ull,127833ull,93717ull,111737ull,105169ull,146669ull,139569ull,153909ull,140845ull,97101ull,83201ull,87809ull,0ull,0ull,90473ull,0ull,104913ull,0ull,0ull,83833ull,117929ull,121641ull,124145ull,124281ull,124309ull,124477ull,154969ull,127737ull,130805ull,0ull, + 137289ull,0ull,142305ull,0ull,0ull,147681ull,148469ull,0ull,0ull,0ull,156605ull,156657ull,156833ull,161489ull,148345ull,154333ull,81593ull,82845ull,83253ull,84773ull,84881ull,85317ull,87669ull,88089ull,88481ull,90369ull,90785ull,94609ull,94649ull,98897ull,99745ull,99897ull, + 100297ull,103741ull,104329ull,105029ull,107029ull,112093ull,112745ull,113801ull,116153ull,116909ull,118921ull,123461ull,124153ull,124197ull,124193ull,124225ull,124249ull,124277ull,124469ull,124473ull,125185ull,125445ull,126721ull,128977ull,129061ull,129285ull,130505ull,131093ull,133045ull,133605ull,133605ull,135517ull, + 140353ull,140889ull,142341ull,142565ull,144205ull,144417ull,147161ull,147681ull,154509ull,155645ull,155885ull,98773ull,592825ull,133217ull,0ull,0ull,80025ull,83669ull,83361ull,81409ull,83221ull,83457ull,84765ull,84969ull,87669ull,87381ull,87653ull,87945ull,90473ull,90829ull,91409ull,91473ull, + 92553ull,93345ull,97097ull,97125ull,97701ull,97973ull,99169ull,99641ull,99361ull,99897ull,99713ull,100297ull,100561ull,102161ull,102513ull,102729ull,103769ull,104913ull,105565ull,105581ull,105817ull,110053ull,110313ull,111877ull,113517ull,113453ull,113801ull,114809ull,116153ull,122525ull,116949ull,117437ull, + 117929ull,119237ull,119833ull,120045ull,120949ull,120957ull,121641ull,121709ull,121809ull,122153ull,122113ull,123697ull,125637ull,126721ull,127469ull,128365ull,128977ull,130297ull,131093ull,134473ull,135101ull,138725ull,140549ull,140825ull,140889ull,142077ull,142305ull,142125ull,142341ull,142329ull,142261ull,142565ull, + 142889ull,144417ull,146657ull,147913ull,149093ull,149977ull,154097ull,154509ull,154969ull,155501ull,155645ull,155693ull,155885ull,158793ull,163441ull,565545ull,565521ull,577365ull,61045ull,65633ull,65765ull,608549ull,619329ull,654157ull,163085ull,163385ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,12247373670ull,0ull,12272539594ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,12356425638ull,12364814246ull,12356676902ull,12365065510ull,12272539458ull,12280928066ull,12314482498ull,12314482502ull,12314482506ull,12314482510ull,12314482514ull,12314482518ull,12314482522ull,0ull,12314482530ull,12314482534ull,12314482538ull,12314482542ull,12314482546ull,0ull,12314482554ull,0ull, + 12314482562ull,12314482566ull,0ull,12314482574ull,12314482578ull,0ull,12314482586ull,12314482590ull,12314482594ull,12314482598ull,12314482602ull,12289316694ull,12339648326ull,12339648366ull,12339648402ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,6501439306ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,6501439338ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,585676112486ull,0ull,585676112494ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,585676112534ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,586590471366ull,586590471370ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,591078378782ull,591288093982ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,592244395530ull,0ull,592126955026ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,592185675310ull,0ull,0ull,592244395586ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,592185675530ull,0ull,592101789450ull,592244395786ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,594266051302ull,594182165222ull,0ull,594291217126ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,596321261282ull,596321261286ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,603845846230ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,758313747578ull,758406022266ull,758322136186ull,758322136230ull,758330524794ull,758322136198ull,758322136202ull,758330524806ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,784695932318ull,784695932302ull,784695932326ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,999427622238ull,999427622242ull, + 999503119742ull,999511508350ull,999519896958ull,999528285566ull,999536674174ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,999427622630ull,999427622634ull,999503120110ull,999503120114ull,999511508718ull, + 999511508722ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, + 80117ull,80097ull,80133ull,525449ull,81281ull,81593ull,81645ull,81929ull,82409ull,82533ull,82845ull,82749ull,53881ull,530665ull,83253ull,83281ull,83345ull,83421ull,529521ull,53989ull,83357ull,83509ull,529709ull,83549ull,83601ull,80689ull,83633ull,83669ull,673661ull,83925ull,83981ull,54141ull, + 84205ull,84249ull,84425ull,84445ull,54357ull,84765ull,84773ull,84881ull,84969ull,85013ull,85017ull,85085ull,85285ull,85317ull,85353ull,85453ull,85493ull,85501ull,85501ull,85501ull,534705ull,115137ull,85801ull,85885ull,535949ull,85933ull,85957ull,86041ull,86649ull,86241ull,86305ull,86433ull, + 86665ull,87001ull,87105ull,87373ull,87437ull,87569ull,87569ull,87653ull,87725ull,87757ull,87817ull,89177ull,88089ull,89181ull,88389ull,88529ull,83997ull,91065ull,89913ull,90065ull,90165ull,89645ull,90313ull,90309ull,90801ull,545681ull,91081ull,91101ull,91161ull,91241ull,91273ull,91529ull, + 547489ull,547753ull,92081ull,92269ull,92317ull,92001ull,92569ull,56249ull,56305ull,93217ull,93433ull,93433ull,550689ull,93965ull,94049ull,94109ull,94157ull,552033ull,94205ull,94233ull,97613ull,94345ull,56837ull,94593ull,94649ull,94977ull,94773ull,554897ull,95501ull,554905ull,95673ull,95661ull, + 95729ull,96133ull,96137ull,57533ull,96245ull,96417ull,96501ull,96677ull,57737ull,558605ull,57841ull,96961ull,96973ull,96985ull,97065ull,691785ull,97273ull,560325ull,560325ull,133125ull,97417ull,97417ull,58141ull,576225ull,624489ull,97673ull,97709ull,58253ull,97897ull,98101ull,98141ull,98277ull, + 98821ull,58601ull,58481ull,98897ull,564049ull,99101ull,99617ull,99633ull,99641ull,99633ull,99817ull,99897ull,100041ull,99985ull,100029ull,100217ull,100297ull,100313ull,100417ull,100461ull,100725ull,101061ull,101201ull,101697ull,568369ull,101621ull,101361ull,101793ull,101901ull,102289ull,569285ull,102537ull, + 102165ull,102053ull,59577ull,102821ull,102905ull,103029ull,102877ull,59825ull,103741ull,103857ull,573481ull,104333ull,105441ull,104741ull,60517ull,105029ull,60449ull,60305ull,83529ull,83541ull,105473ull,105073ull,131765ull,69477ull,105565ull,105581ull,105605ull,105849ull,105805ull,577293ull,60709ull,106473ull, + 106005ull,106825ull,107029ull,577973ull,107065ull,106621ull,107601ull,61045ull,107785ull,108173ull,108457ull,109217ull,580237ull,109421ull,61537ull,109701ull,582301ull,109905ull,61753ull,110025ull,110205ull,110313ull,110317ull,584245ull,554029ull,584681ull,110905ull,586481ull,111357ull,111413ull,111005ull,111705ull, + 111865ull,112093ull,111877ull,112037ull,112097ull,112149ull,586873ull,111825ull,112829ull,113081ull,62669ull,113453ull,113437ull,588613ull,112613ull,114105ull,589177ull,589369ull,114457ull,114917ull,114809ull,114797ull,63065ull,114985ull,115189ull,115165ull,115381ull,529557ull,115989ull,592269ull,116337ull,593581ull, + 116897ull,116949ull,117057ull,596001ull,117249ull,117333ull,597205ull,598097ull,118249ull,118317ull,64177ull,118421ull,64225ull,64225ull,119069ull,119153ull,119237ull,119317ull,119593ull,64621ull,119953ull,602329ull,120057ull,602697ull,120257ull,558717ull,120897ull,605829ull,605921ull,606481ull,65521ull,65569ull, + 121809ull,607181ull,607177ull,607333ull,607437ull,121977ull,121981ull,121981ull,122153ull,65765ull,122413ull,65817ull,66137ull,610421ull,123193ull,123441ull,123697ull,66445ull,612505ull,124249ull,612969ull,613141ull,124477ull,124845ull,66749ull,125185ull,125225ull,125245ull,615921ull,617117ull,617117ull,125881ull, + 67593ull,618157ull,126745ull,126757ull,67741ull,619009ull,127817ull,68225ull,127905ull,127885ull,128001ull,622105ull,128397ull,68613ull,128797ull,129033ull,129301ull,68817ull,624801ull,624925ull,68965ull,625509ull,130537ull,625913ull,130645ull,131049ull,131093ull,627561ull,627853ull,131457ull,628385ull,131521ull, + 576893ull,69461ull,131785ull,132109ull,69677ull,132345ull,92885ull,630429ull,630485ull,577101ull,577137ull,133125ull,133137ull,147065ull,70061ull,133701ull,133677ull,133749ull,84685ull,133829ull,133837ull,133877ull,134041ull,634097ull,134037ull,134261ull,134541ull,134837ull,134285ull,134901ull,135069ull,135517ull, + 134477ull,134953ull,134961ull,135025ull,635097ull,636333ull,635733ull,70829ull,136133ull,136141ull,136281ull,642857ull,136593ull,638129ull,71029ull,71045ull,638661ull,639817ull,71085ull,137537ull,137585ull,137629ull,137637ull,137893ull,137761ull,138297ull,138121ull,138725ull,138401ull,138669ull,138777ull,71517ull, + 139141ull,139269ull,71653ull,139649ull,139661ull,645533ull,140125ull,140153ull,71893ull,140265ull,53997ull,647865ull,648601ull,72441ull,72477ull,141953ull,142261ull,142889ull,143701ull,651937ull,144045ull,144133ull,144493ull,144861ull,654525ull,532497ull,145197ull,145137ull,145345ull,533369ull,146257ull,146657ull, + 661321ull,661429ull,148049ull,148421ull,148549ull,662713ull,148589ull,149729ull,150365ull,150369ull,150001ull,151525ull,151637ull,667625ull,153133ull,75349ull,153309ull,669149ull,75673ull,154381ull,95945ull,154765ull,673045ull,673897ull,76217ull,76249ull,155521ull,675881ull,76489ull,676441ull,155693ull,155693ull, + 155813ull,677593ull,156553ull,77005ull,156837ull,157341ull,157449ull,157689ull,77625ull,683201ull,158793ull,160001ull,160757ull,78649ull,78773ull,161181ull,688953ull,78817ull,689173ull,690233ull,690757ull,162541ull,79193ull,162789ull,162809ull,162837ull,162877ull,162905ull,163053ull,694273ull,0ull,0ull, + 0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull,0ull, +}; + +KBTS_INLINE kbts_u64 kbts__GetUnicodeDecomposition(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeDecomposition_Data[((kbts_un)kbts__UnicodeDecomposition_PageIndices[Codepoint/64] * 64) | (Codepoint & 63)] : 0; +} + +static kbts_u8 kbts__UnicodeWordBreakClass_PageIndices[8703] = { + 0,1,2,2,2,3,4,5,2,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28, + 29,30,2,2,31,32,33,34,35,2,2,2,36,37,38,39,40,41,42,43,44,45,46,47,48,49,2,50,2,2,51,52, + 53,54,55,56,57,57,58,59,57,60,57,61,62,63,64,65,57,57,66,57,57,57,67,57,2,68,69,70,71,57,57,57, + 72,73,74,75,57,76,77,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 2,2,2,2,2,2,2,2,2,78,2,2,79,80,81,82,83,84,85,86,87,88,89,90,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,91,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,92,93,2,2,94,95,96,97,98,99, + 100,101,102,103,57,104,105,106,2,107,108,109,2,2,110,111,112,113,114,115,116,117,118,119,120,121,122,123,57,124,125,126, + 127,128,129,130,131,132,133,134,135,136,57,137,138,139,140,57,141,142,143,144,145,146,57,147,148,149,150,151,57,152,153,154, + 2,2,2,2,2,2,2,155,156,2,157,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,158, + 2,2,2,2,2,2,2,2,159,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,101,2,2,2,2,160,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,161,57,57,57,57,57,57,57,57,57,57,57,57,57,2,2,2,2,162,163,164,165,57,57,166,57,167,57,168,169, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,170, + 171,57,172,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,173,174,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,175,57,57,57,57,176,57, + 57,57,177,178,179,57,57,57,180,181,182,2,2,183,184,185,57,57,57,57,186,187,57,57,57,57,57,57,57,57,188,57, + 189,190,191,57,57,192,57,57,57,193,57,194,57,57,57,195,2,196,197,57,57,57,57,57,57,57,57,57,198,199,57,57, + 200,200,201,202,203,200,200,204,200,200,205,200,206,200,207,208,209,210,211,200,200,200,57,175,200,200,200,200,200,200,200,212, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 213,57,214,215,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +}; + +static kbts_u8 kbts__UnicodeWordBreakClass_Data[27648] = { + 0,0,0,0,0,0,0,0,0,0,3,4,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,14,0,0,0,0,13,0,0,0,0,17,0,15,0,18,18,18,18,18,18,18,18,18,18,16,17,0,0,0,0, + 0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,19,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,0,0,8,1,0,0,0,0,0,0,11,0,16,0,0,11,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,11,11,11,11,11,0,11,11,0,0,11,11,11,11,17,11, + 0,0,0,0,0,0,11,16,11,11,11,0,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11, + 11,11,0,5,5,5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,0,11,16,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,17,11,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5, + 0,5,5,0,5,5,0,5,0,0,0,0,0,0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,10,10,10,10,11,16,0,0,0,0,0,0,0,0,0,0,0, + 18,18,18,18,18,18,0,0,0,0,0,0,17,17,0,0,5,5,5,5,5,5,5,5,5,5,5,0,8,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,18,18,18,18,18,18,18,18,18,18,0,18,17,0,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,5,5,5,5,5,5,5,18,0,5,5,5,5,5,5,11,11,5,5,0,5,5,5,5,11,11,18,18,18,18,18,18,18,18,18,18,11,11,11,0,0,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 18,18,18,18,18,18,18,18,18,18,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,11,11,0,0,17,0,11,0,0,5,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,11,5,5,5,5,5,5,5,5,5,11,5,5,5,11,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,0,18,18,0,0,0,0,0,5,5,5,5,5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,18,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,11,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,11,5,5,5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,5,5,5,0,11,11,11,11,11,11,11,11,0,0,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,0,0,0,11,11,11,11,0,0,5,11,5,5, + 5,5,5,5,5,0,0,5,5,0,0,5,5,5,11,0,0,0,0,0,0,0,0,5,0,0,0,0,11,11,0,11,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,11,11,0,0,0,0,0,0,0,0,0,0,11,0,5,0, + 0,5,5,5,0,11,11,11,11,11,11,0,0,0,0,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,11,11,0,11,11,0,0,5,0,5,5, + 5,5,5,0,0,0,0,5,5,0,0,5,5,5,0,0,0,5,0,0,0,0,0,0,0,11,11,11,11,0,11,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,5,5,11,11,11,5,0,0,0,0,0,0,0,0,0,0, + 0,5,5,5,0,11,11,11,11,11,11,11,11,11,0,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,0,0,5,11,5,5, + 5,5,5,5,5,5,0,5,5,5,0,5,5,5,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,11,5,5,5,5,5,5, + 0,5,5,5,0,11,11,11,11,11,11,11,11,0,0,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,0,0,5,11,5,5, + 5,5,5,5,5,0,0,5,5,0,0,5,5,5,0,0,0,0,0,0,0,5,5,5,0,0,0,0,11,11,0,11,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,11,0,11,11,11,11,11,11,0,0,0,11,11,11,0,11,11,11,11,0,0,0,11,11,0,11,0,11,11,0,0,0,11,11,0,0,0,11,11,11,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,5,5, + 5,5,5,0,0,0,5,5,5,0,5,5,5,5,0,0,11,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,11,11,11,11,11,11,11,11,0,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,5,11,5,5, + 5,5,5,5,5,0,5,5,5,0,5,5,5,5,0,0,0,0,0,0,0,5,5,0,11,11,11,0,0,11,0,0,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,5,5,5,0,11,11,11,11,11,11,11,11,0,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,0,0,5,11,5,5, + 5,5,5,5,5,0,5,5,5,0,5,5,5,5,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,11,11,0,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,11,11,5,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,11,11,11,11,11,11,11,11,11,0,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,11,5,5, + 5,5,5,5,5,0,5,5,5,0,5,5,5,5,11,0,0,0,0,0,11,11,11,5,0,0,0,0,0,0,0,11,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11, + 0,5,5,5,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,0,11,0,0, + 11,11,11,11,11,11,11,0,0,0,5,0,0,0,0,5,5,5,5,5,5,0,5,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,5,5,5,5,5,0,0,0,0,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,5,0,0,0,0,5,5, + 11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0,5,5,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,5,5,5,0,5,5,5,0,0,5,5,5,5,5,5,5,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,5,18,18,18,18,18,18,18,18,18,18,5,5,5,5,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,0,11,0,0,0,0,0,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,0,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,0, + 11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0, + 0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 20,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,5,5,5,8,5,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0, + 11,11,11,11,11,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, + 0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5, + 18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,11,11,11,11,11,11,11,11,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,11,11,18,18,18,18,18,18,18,18,18,18,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0, + 18,18,18,18,18,18,18,18,18,18,0,0,0,11,11,11,18,18,18,18,18,18,18,18,18,18,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0, + 11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,11,11,11,11,5,11,11,11,11,11,11,5,11,11,5,5,5,11,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,0,11,0,11,0,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,0, + 0,0,11,11,11,0,11,11,11,11,11,11,11,0,0,0,11,11,11,11,0,0,11,11,11,11,11,11,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,0,11,11,11,11,11,11,11,0,0,0, + 20,20,20,20,20,20,20,0,20,20,20,0,5,6,8,8,0,0,0,0,0,0,0,0,15,15,0,0,0,0,0,0,0,0,0,0,15,0,0,16,4,4,8,8,8,8,8,19,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,19, + 19,0,0,0,17,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,20,8,8,8,8,8,0,8,8,8,8,8,8,8,8,8,8,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,11,0,0,0,0,11,0,0,11,11,11,11,11,11,11,11,11,11,0,11,0,0,0,11,11,11,11,11,0,0,0,0,1,0,11,0,11,0,11,0,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,12,0,0,11,11,11,11, + 0,0,0,0,0,11,11,11,11,11,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11, + 11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0, + 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11,11,11,5,5,5,11,11,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,0,0,0,0,0,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0, + 11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 20,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,1,9,9,9,9,9,0,0,0,0,0,11,11,1,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,9,9,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,9,9,9, + 0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,18,18,18,18,18,18,18,18,18,18,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,0,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,0,11,0,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,5,11,11,11,5,11,11,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,11,11,11,11,11,11,0,0,0,11,0,11,11,5, + 18,18,18,18,18,18,18,18,18,18,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0, + 5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, + 11,11,11,5,11,11,11,11,11,11,11,11,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5,5,0,0,5,5,0,0,0,0,0,5,5, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,0,0,11,11,11,5,5,0,0,0,0,0,0,0,0,0, + 0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,0,5,5,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0, + 11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,0,0,0,0,0,10,5,10,10,10,10,10,10,10,10,10,10,0,10,10,10,10,10,10,10,10,10,10,10,10,10,0,10,10,10,10,10,0,10,0, + 10,10,0,10,10,0,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,19,19,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,19,19,19,17,0,15,0,17,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,8, + 0,0,0,0,0,0,0,15,0,0,0,0,17,0,15,0,18,18,18,18,18,18,18,18,18,18,16,17,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,19, + 0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0, + 0,0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,11,11,11,11,11,11,0,0,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8,8,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,0,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,0,0,0,0,11,11,11,11,11,11,11,11,0,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,0,0,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,0,0,0,11,0,0,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,5,5,5,0,5,5,0,0,0,0,0,5,5,5,5,11,11,11,11,0,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,5,5,5,0,0,0,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 18,18,18,18,18,18,18,18,18,18,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,5,5,5,5,5,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,5,5,0,0,0,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0, + 5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,5,11,11,5,5,11,0,0,0,0,0,0,0,0,0,5, + 5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,0,0,18,0,0, + 0,0,5,0,0,0,0,0,0,0,0,0,0,18,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,18,18,18,18,18,18,18,18,18,18, + 0,0,0,0,11,5,5,11,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,0,0,11,0,0,0,0,0,0,0,0,0, + 5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,11,11,11,11,0,0,0,0,5,5,5,5,0,5,5,18,18,18,18,18,18,18,18,18,18,11,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,5,11, + 11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,0,11,0,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 5,5,5,5,0,11,11,11,11,11,11,11,11,0,0,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,0,5,5,11,5,5, + 5,5,5,5,5,0,0,5,5,0,0,5,5,5,0,0,11,0,0,0,0,0,0,5,0,0,0,0,0,11,11,11,11,11,5,5,0,0,5,5,5,5,5,5,5,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,0,11,0,0,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,5,5,5,5,5,5,5,5, + 5,0,5,0,0,5,0,5,5,5,5,0,5,5,5,5,5,11,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,11,11,11,11,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,5,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,11,11,0,11,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,11,0,0,0,0,0,0,0, + 18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, + 11,11,11,11,11,11,11,0,0,11,0,0,11,11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,0,5,5,0,0,5,5,5,5,11, + 5,11,5,5,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,11,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,5,5,5,5,5,5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,11,5,5,5,5,0, + 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,11,5,5,5,5,5,5,5,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5, + 11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,0,0,0,5,0,5,5,0,5, + 5,5,5,5,5,5,11,5,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,11,11,11,11,11,11,0,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,0,5,5,0,5,5,5,5,5,11,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,0,0,0,0,0,0,0,0,0, + 5,5,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,0,0,0,5,5, + 5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 5,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0, + 18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, + 11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,5,11,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,0,11,5,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,0,9,9,9,9,9,9,9,0,9,9,0, + 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0, + 11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,0,0,0,5,5,0,8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,5,5,5,5,5,5,8,8,8,8,8,8,8,8,5,5,5,5,5, + 5,5,5,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,0,0,11,0,0,11,11,0,0,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,0,11,0,11,11,11, + 11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,0,11,11,11,11,0,0,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,0, + 11,11,11,11,11,0,11,0,0,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,0,11,11,11,11,11,11,11,11,0,0,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,5,5,5,5,5,5,5,11,11,11,11,11,11,11,0,0, + 18,18,18,18,18,18,18,18,18,18,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,5,5,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,5,11,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,0,11,11,11,11,0,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,5,5,5,5,5,5,5,11,0,0,0,0,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,0,11,0,0,11,0,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,11,0,11,0,0,0,0, + 0,0,11,0,0,0,0,11,0,11,0,11,0,11,11,11,0,11,11,0,11,0,0,11,0,11,0,11,0,11,0,11,0,11,11,0,11,0,0,11,11,11,11,0,11,11,11,11,11,11,11,0,11,11,11,11,0,11,11,11,11,0,11,0, + 11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,11,11,11,0,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,1,1,1,1,12,12,11,11,11,11,11,11,11,11,11,11,11,11,12,12, + 11,11,11,11,11,11,11,11,11,11,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1, + 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, + 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0, + 0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeWordBreakClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeWordBreakClass_Data[((kbts_un)kbts__UnicodeWordBreakClass_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeLineBreakClass_PageIndices[8703] = { + 0,1,2,2,2,3,4,2,2,5,2,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26, + 27,28,29,30,2,2,31,2,32,2,2,2,2,33,34,35,36,37,38,39,40,41,42,43,44,45,2,46,2,2,2,47, + 48,49,50,2,51,52,53,54,2,2,2,55,56,57,58,59,2,2,2,60,2,2,61,2,2,62,63,64,65,66,67,68, + 69,70,71,72,73,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,74,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 75,67,67,67,67,67,67,67,67,76,2,2,77,78,2,2,79,80,81,82,83,84,2,85,86,87,88,89,90,91,92,86, + 87,88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,89,90, + 91,92,86,87,88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,89,90,91,92,86,87, + 88,89,90,91,92,86,87,88,89,90,91,92,86,87,88,93,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,67,67,67,67,95,2,2,2,96,97,98,99,100,101, + 2,2,102,103,2,104,105,106,2,107,2,2,2,2,2,2,108,2,109,2,110,111,112,2,2,2,113,2,2,114,115,116, + 117,118,119,120,121,122,123,124,125,126,2,127,128,129,130,2,131,132,133,134,135,136,137,138,139,140,141,142,2,143,144,145, + 2,2,2,2,2,2,2,2,146,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,147,148,149,2,150,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,151,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,152,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,153,154,155,2,2,2,156,2,2,157,158,159, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,160,67,67,67,67,67,67,161,161,161,162,163,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,164, + 67,67,165,67,67,166,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,167,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,138,2,2,2,2,168,2, + 2,2,169,170,171,2,172,2,2,2,2,2,2,2,2,173,2,2,2,2,174,175,2,2,2,2,2,2,2,2,2,2, + 176,177,178,2,2,179,2,2,2,180,2,181,2,2,2,2,2,182,183,2,2,2,2,2,2,184,2,2,2,2,2,2, + 185,186,2,187,188,189,190,191,192,193,194,195,196,197,198,199,2,2,200,201,202,203,2,138,189,189,189,189,189,189,189,204, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,205, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67, + 67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,205, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 206,2,207,208,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; + +static kbts_u8 kbts__UnicodeLineBreakClass_Data[26752] = { + 63,63,63,63,63,63,63,63,63,19,5,3,3,4,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,7,16,23,37,40,48,37,23,21,14,37,40,26,31,26,18,39,39,39,39,39,39,39,39,39,39,26,26,37,37,37,16, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,40,14,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,19,12,37,63, + 63,63,63,63,63,6,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,10,21,48,40,40,40,37,37,37,37,37,24,37,19,37,37,48,40,37,37,35,37,37,37,37,37,37,25,37,37,37,21, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,35,37,37,37,35,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,35,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,10,63,63,63,63,63,63,63,63,63,63,63,63,10,10,10,10,10,10,10,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,26,37, + 37,37,37,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,26,19,37,37,37,37,40,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,19,63, + 37,63,63,37,63,63,16,63,37,37,37,37,37,37,37,37,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,37,37,37,37,36,36,36,36,37,37,37,37,37,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,37,37,37,48,48,48,26,26,37,37,63,63,63,63,63,63,63,63,63,63,63,16,63,16,16,16,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,39,39,39,39,39,39,39,39,39,39,48,39,39,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,16,37,63,63,63,63,63,63,63,39,37,63,63,63,63,63,63,37,37,63,63,37,63,63,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,37,37,37,37,26,16,37,37,37,63,40,40, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,37,63,63,63,63,63,63,63,63,63,37,63,63,63,37,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,37,37,37,37,37,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,39,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,63,63,19,19,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,63,63,37,37,63,63,37,37,63,63,63,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,48,48,37,37,37,37,37,48,37,40,37,37,63,37, + 37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,37,37,37,37,63,63,37,37,63,63,63,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,63,63,37,37,37,63,37,37,37,37,37,37,37,37,37,37, + 37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,63,63,63,37,63,63,63,37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,40,37,37,37,37,37,37,37,37,63,63,63,63,63,63, + 37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,63,63,37,37,63,63,37,37,63,63,63,37,37,37,37,37,37,37,63,63,63,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63, + 63,63,63,37,37,37,63,63,63,37,63,63,63,63,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,40,37,37,37,37,37,37, + 63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,63,63,37,63,63,63,37,63,63,63,63,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,35,37,37,37,37,37,37,37,37, + 37,63,63,63,35,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63, + 63,63,63,63,63,37,63,63,63,37,63,63,63,63,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,63,63, + 63,63,63,63,63,37,63,63,63,37,63,63,63,63,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,48,37,37,37,37,37,37, + 37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,63,63,63,63,63,63,37,63,37,63,63,63,63,63,63,63,63,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,40, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,35,35,35,35,37,35,35,10,35,35,19,10,16,16,16,16,16,10,37,16,37,37,37,63,63,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,19,63,37,63,37,63,21,12,21,12,63,63, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,19, + 63,63,63,63,63,19,63,63,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,19,19, + 37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,35,35,19,35,37,37,37,37,37,10,10,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50, + 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, + 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,19,19,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,27,37,19,37,19,40,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,16,16,19,19,35,37,16,16,37,63,63,63,10,63,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37, + 37,37,37,37,16,16,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,63,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,60,56,56,56,56,56,56,56,56,37,19,19,58,58,58,58,58,58,58,58,58,58,19,19,42,19,19,19,19,42,42,42,42,42,42,42,42,42,42,63,63,63,63,63,63,63,63,63,42,42,42,42,42,42,42,42,42,19,19,19, + 63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,63,63,63,63,63,63,63,63,63,63,63,63,59,59,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,19,19,19,19,19, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,63,37,37,37,37,37,37,63,37,37,63,63,63,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,63,63,63,63,63,63,63,63,63,10,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,10,63,63,63, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,35,37,37, + 19,19,19,19,19,19,19,10,19,19,19,8,63,64,63,63,32,10,19,19,29,37,37,37,24,25,21,24,24,25,21,24,37,37,37,37,33,33,33,19,3,3,63,63,63,63,63,10,48,48,48,48,48,48,48,48,37,24,25,37,27,27,37,37, + 37,37,37,37,26,21,12,27,27,27,37,37,37,37,37,37,37,37,37,37,37,37,19,48,19,19,19,19,37,19,19,19,9,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,40,40,40,40,40,40,40,48,40,41,40,40,40,40,40,40,40,40,40,40,40,40,48,40,40,40,40,48,40,40,48,40, + 48,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,48,37,37,37,37,37,48,37,37,37,37,37,37,37,37,37,37,37,37,40,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,40,40,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,33,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,21,12,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,43,43,37,37,37,37,37,37,37,37,37,37,37,37,37,22,13,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,38,38,37,37,37,43,42,42,43,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,57,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,37, + 42,42,42,42,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,43,43,37,37,42,37,42,42,42,45,42,42,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,38,38,38,38,38,38,37,42,42,42,37,37,37,37, + 37,37,37,37,37,37,37,37,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,42,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,43, + 37,37,37,37,37,37,37,37,37,37,38,38,38,38,38,38,37,37,37,38,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,43,43,42, + 42,42,42,42,43,43,42,42,42,37,37,37,37,42,38,42,42,42,37,42,43,37,37,37,42,42,37,37,42,37,37,42,42,42,37,37,37,37,37,37,37,37,43,37,37,37,37,37,37,42,43,43,42,43,37,42,42,45,43,37,37,43,42,42, + 42,42,42,42,42,38,37,37,42,42,46,46,45,45,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,38,37,38,37,37,37,37,38,38,38,37,38,37,37,37,23,23,23,23,23,23,37,16,16,42,37,37,37,21,12,21,12,21,12,21,12,21,12,21,12,21,12,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38, + 37,37,37,37,37,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,21,12,21,12,21,12,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,21,12,21,12,21,12,21,12,21,12,21,12,21,12,21,12,21,12,21,12,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,37,37,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,37,37,37,37,37,37,16,19,19,19,37,16,19, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 23,23,24,25,24,25,23,23,23,24,25,23,24,25,19,19,19,19,19,19,19,19,37,19,21,19,37,37,24,25,37,37,24,25,21,12,21,12,21,12,21,12,19,19,19,19,16,37,19,19,37,19,19,37,37,37,37,37,29,29,19,19,19,37, + 19,19,21,19,19,19,19,19,19,19,19,37,19,37,19,19,37,37,37,16,16,21,14,21,14,21,14,21,14,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,37,37,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 20,13,13,43,43,28,43,43,22,13,22,13,22,13,22,13,22,13,43,43,22,13,22,13,22,13,22,13,28,22,13,13,43,43,43,43,43,43,43,43,43,43,63,63,63,63,63,63,43,43,43,43,43,63,43,43,43,43,43,28,28,43,43,42, + 37,65,43,65,43,65,43,65,43,65,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,65,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,65,43,65,43,65,43,43,43,43,43,43,65,43,43,43,43,43,43,65,65,37,37,63,63,28,28,28,28,43,28,65,43,65,43,65,43,65,43,65,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,65,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,65,43,65,43,65,43,43,43,43,43,43,65,43,43,43,43,43,43,65,65,43,43,43,43,28,65,28,28,43, + 37,37,37,37,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,43,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,28,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19, + 37,37,37,37,37,37,37,37,37,37,37,37,37,19,16,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,19,19,19,19,19,37,37,37,37,37,37,37,37, + 37,37,63,37,37,37,63,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,48,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,35,35,16,16,37,37,37,37,37,37,37,37, + 63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,37,37,37,37,37,37,37,37,19,19,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,35,37,37,63, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,37,37,37, + 63,63,63,63,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,63,63,63,63,63,63,63,63,63,63,63,63,63, + 60,42,42,42,42,42,42,19,19,19,42,42,42,42,37,19,58,58,58,58,58,58,58,58,58,58,37,37,37,37,42,42,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37, + 19,19,19,63,19,19,19,19,19,19,19,19,63,63,37,37,58,58,58,58,58,58,58,58,58,58,37,37,42,19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,19,19,37,37,37,63,63,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,19,63,63,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54, + 54,54,54,54,54,54,54,54,53,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,37,37,37,37,37,37,37,37,37,37,37,37,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51, + 51,51,51,51,51,51,51,37,37,37,37,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,37,37,37,37, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,36,63,36,36,36,36,36,36,36,36,36,36,37,36,36,36,36,36,36,36,36,36,36,36,36,36,37,36,36,36,36,36,37,36,37, + 36,36,37,36,36,37,36,36,36,36,36,36,36,36,36,36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,12,21, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,48,37,37,37, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,13,13,13,28,28,17,17,22,13,34,37,37,37,37,37,37,10,63,10,63,10,63,10,10,63,10,63,10,63,10,10,63,43,43,43,43,43,22,13,22,13,22,13,22,13,22,13,22, + 13,22,13,22,13,43,43,22,13,43,43,43,43,43,43,43,13,43,13,37,28,28,17,17,43,22,13,22,13,22,13,43,43,43,43,43,43,43,43,37,43,41,49,43,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,9, + 37,17,43,43,41,49,43,43,22,13,43,43,13,43,13,43,43,43,43,43,43,43,43,43,43,43,28,28,43,43,43,17,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,22,43,13,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,22,43,13,43,22,13,13,22,13,13,28,43,65,65,65,65,65,65,65,65,65,65,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,28,28,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37, + 37,37,43,43,43,43,43,43,37,37,43,43,43,43,43,43,37,37,43,43,43,43,43,43,37,37,43,43,43,37,37,37,49,41,43,43,43,41,41,37,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,63,63,63,30,37,37,37, + 19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,63,63,63,37,63,63,37,37,37,37,37,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,37,37,37,37,63, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,19,19,19,19,19,19,33,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,19,19, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,55,55,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,60,19,19,42,42,42,42,42,37,37,37,37,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,58,58,58,58,58,58,58,58,58,58,63,56,56,63,63,56,37,37,37,37,37,37,37,37,37,10, + 63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,37,37,39,19,19, + 19,19,63,37,37,37,37,37,37,37,37,37,37,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,39,39,39,39,39,39,39,39,39,39, + 19,19,19,19,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,35,37,37,37,37,37,37,37,37,37,37, + 63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,37,37,37,37,19,19,37,19,63,63,63,63,37,63,63,39,39,39,39,39,39,39,39,39,39,37,35,37,19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,19,19,37,19,19,37,63,37, + 37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 63,63,63,63,37,56,56,56,56,56,56,56,56,37,37,56,56,37,37,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,37,56,56,56,56,56,56,56,37,56,56,37,56,56,56,56,56,37,63,63,19,63,63, + 63,63,63,63,63,37,37,63,63,37,37,63,63,60,37,37,58,37,37,37,37,37,37,63,37,37,37,37,37,19,58,58,56,56,63,63,37,37,63,63,63,63,63,63,63,37,37,37,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37, + 58,58,58,58,58,58,58,58,58,58,37,58,37,37,58,37,58,58,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,37,42,63,63,63,63,63,63,63,63, + 63,37,63,37,37,63,37,63,63,63,63,37,63,63,63,63,60,55,63,42,42,42,37,42,42,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,37,37,37,37,19,19,19,19,37,39,39,39,39,39,39,39,39,39,39,19,19,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,37,37,63,63,63,63,63,63,63,63, + 63,35,19,19,16,16,37,37,37,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,35,35,35,35,35,35,35,35,35,35,35,35,35,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,19,19,19,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 56,56,56,56,56,56,56,37,37,56,37,37,56,56,56,56,56,56,56,56,37,56,56,37,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,63,63,63,63,63,63,37,63,63,37,37,63,63,63,60,55, + 63,55,63,63,19,19,19,37,37,37,37,37,37,37,37,37,58,58,58,58,58,58,58,58,58,58,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,37,37,63,63,63,63,63,63,63,37,35,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,37,63,63,63,63,35, + 37,19,19,19,19,35,37,63,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,19,19,19,37,35,35,35,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 35,35,35,35,35,35,35,35,35,35,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,63, + 37,19,19,19,19,19,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,35,16,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,37,37,37,63,37,63,63,37,63, + 63,63,63,63,63,63,37,63,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,63,63,37,63,63,63,63,63,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,19,63,63,63,63,19,19,37,37,37,37,37,37,37, + 63,63,55,63,56,56,56,56,56,56,56,56,56,56,56,56,56,37,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,63,63,63,63,63,63,63,37,37,37,63,63, + 63,63,60,19,19,42,42,42,42,42,42,42,42,42,42,42,58,58,58,58,58,58,58,58,58,58,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,48,48,48,48,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,12,12,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,12,37,37,37,21,12,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,12,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,10,10,10,10,10,10,10,21,12,10,10,10,21,12,21,12, + 63,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,12,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,58,58,58,58,58,58,58,58,58,58,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,19,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,19,19,19,37,37,37,37,37,37, + 37,37,37,37,19,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,28,28,28,28,11,37,37,37,37,37,37,37,37,37,37,37,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38, + 43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,38,38,37,38,38,38,38,38,38,38,37,38,38,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,65,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,65,65,65,37,37,65,37,37,37,37,37,37,37,37,37,37,37,37,37,37,65,65,65,65,37,37,37,37,37,37,37,37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,19,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,37,37,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, + 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,63,37,37,19,19,19,19,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,63,63,63,63,63,63,63,37,63,63,37,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37, + 39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,40, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,63,63,63,63,63,63,63,37,37,37,37,37,39,39,39,39,39,39,39,39,39,39,37,37,37,37,21,21,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,48,37,37,37,48,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 42,42,42,42,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,44,44,44,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, + 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, + 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,44,44,44,44,44,44,44,44,44,44,44,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,44,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, + 44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,44,44,44,44,44,44,44,44,44,44, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 43,43,43,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44, + 43,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,43,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,42,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,43,43, + 43,43,43,43,43,46,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,37,37,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,38,38,43,43,43,43,43,38,43,43,43, + 43,43,46,46,46,43,43,46,43,43,46,45,45,42,42,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,43,42,42,42,43,43,43,47,47,47,47,47, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42, + 43,42,46,46,43,43,46,46,46,46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,43,43,43,46,43,43,43, + 43,46,46,46,43,46,46,46,43,43,43,43,43,43,43,46,43,46,43,43,43,43,43,43,43,43,43,43,43,43,43,43,38,43,38,43,38,43,43,43,43,43,46,43,43,43,43,38,43,38,38,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,43, + 38,38,38,38,38,38,38,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,38,38,38,38,38,38,38,38,38,38,38,38,38,38,43,43,43,43,43,43,43,43,43,43,43,43,43,38,38,38,38,38,38,38,38,38,38,38,38,37,37, + 37,37,37,37,37,37,37,37,37,37,42,43,43,43,43,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,45,45,42,42,42,42,46,42,42,42,42,42, + 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,45,42,42,42,42,46,46,42,42,42,42,42,42,42,42,42,42,42,42,42,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42, + 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,37,37,37,37,37,37,37,37,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,37,37,37,37,37,37,42,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,46,46,46,43,43,43,46,46,46,46,46,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,27,27,27,37,37,37,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,46,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,46,46,46,43,43,43,43,43,43,43,43,43, + 46,43,43,43,43,43,42,42,42,42,42,42,46,42,42,42,43,43,43,42,42,43,43,43,44,44,44,44,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,43,43,44,44,44,42,42,42,42,43,43,43,43,43,43,43,43,43,44,44,44, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,42,42,42,44,44,44,44,42,42,42,42,42, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,42,42,42,42,42,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 37,37,37,37,37,37,37,37,37,37,37,37,46,43,43,46,43,43,43,43,43,43,43,43,46,46,46,46,46,46,46,46,43,43,43,43,43,43,46,43,43,43,43,43,43,43,43,43,46,46,46,46,46,46,46,46,46,46,43,42,46,46,46,43, + 43,43,43,43,43,43,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,46,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,46,46,43,46,46,43,46,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,46,46,46,43,46,46,46,46,46,46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,44,44,44,44,44,44,44,44,44,44,44,44,42,42,42,42,42,42,42,42,42,42,42,42,42,42,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44, + 43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,46,46,46,43,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,44,46,46,46,46,46,46,46,46,46,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,37,37, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,37,37, + 37,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63, + 63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeLineBreakClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeLineBreakClass_Data[((kbts_un)kbts__UnicodeLineBreakClass_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeGraphemeBreakClass_PageIndices[8703] = { + 0,1,2,2,2,2,3,2,2,4,2,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, + 26,27,28,29,2,2,30,2,2,2,2,2,2,2,31,32,33,34,35,2,36,37,38,39,40,41,2,42,2,2,2,2, + 43,44,45,46,2,2,47,48,2,49,2,50,51,52,53,54,2,2,55,2,2,2,56,2,2,57,58,59,2,2,2,2, + 60,61,2,2,2,62,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,63,64,2,2,65,66,67,68,69,70,2,71,72,73,74,75,76,77,78,79, + 73,74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,75,76, + 77,78,79,73,74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,75,76,77,78,79,73, + 74,75,76,77,78,79,73,74,75,76,77,78,79,73,74,80,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,81,2,2,2,2,2,82,83,2,84, + 2,2,2,85,2,86,87,2,2,2,2,2,2,2,2,2,2,2,2,2,88,89,2,2,2,2,90,2,2,91,92,93, + 94,95,96,97,98,99,100,101,102,103,2,104,105,106,107,2,108,2,109,110,111,112,2,2,113,114,115,116,2,117,118,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,119,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,120,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,121,122,2,2,2,123,2,2,2,124,125, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,126,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,127,2, + 2,2,128,129,130,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,131,132,2,2,2,2,2,2,2,2,2,2, + 133,134,122,2,2,135,2,2,2,136,2,137,2,2,2,2,2,138,139,2,2,2,2,2,2,2,2,2,2,2,2,2, + 140,140,141,142,143,140,140,144,140,140,145,140,146,140,147,148,149,150,151,140,140,140,2,2,140,140,140,140,140,140,140,152, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 153,154,155,156,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; + +static kbts_u8 kbts__UnicodeGraphemeBreakClass_Data[20096] = { + 3,3,3,3,3,3,3,3,3,3,2,0,3,1,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,16,0,0,0,3,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,14, + 0,14,14,0,14,14,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 12,12,12,12,12,12,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,12,0,14,14,14,14,14,14,0,0,14,14,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,14,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,14,14,14,14,14,14,14,14,14,0,14,14,14,0,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,12,0,0,0,0,0,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,12,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,6,14,0,6,6, + 6,14,14,14,14,14,14,14,14,6,6,6,6,15,6,6,0,14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13, + 0,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,13,13,13,13,13,13,13,0,13,0,0,0,13,13,13,13,0,0,14,0,14,6, + 6,14,14,14,14,0,0,6,6,0,0,6,6,15,0,0,0,0,0,0,0,0,0,14,0,0,0,0,13,13,0,13,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,13,13,0,0,0,0,0,0,0,0,0,0,0,0,14,0, + 0,14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,6,6, + 6,14,14,0,0,0,0,14,14,0,0,14,14,14,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,14,0,0,0,0,0,0,0,0,0,0, + 0,14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,13,13,13,13,13,13,13,0,13,13,0,13,13,13,13,13,0,0,14,0,6,6, + 6,14,14,14,14,14,0,14,14,6,0,6,6,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,14,14,14,14,14,14, + 0,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,13,13,13,13,13,13,13,0,13,13,0,13,13,13,13,13,0,0,14,0,14,14, + 6,14,14,14,14,0,0,6,6,0,0,6,6,15,0,0,0,0,0,0,0,14,14,14,0,0,0,0,13,13,0,13,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6, + 14,6,6,0,0,0,6,6,6,0,6,6,6,14,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,6,6,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,0,0,14,0,14,14, + 14,6,6,6,6,0,14,14,14,0,14,14,14,15,0,0,0,0,0,0,0,14,14,0,13,13,13,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,6,14, + 14,6,14,6,6,0,14,14,14,0,14,14,14,14,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,0,14,6, + 6,14,14,14,14,0,6,6,6,0,6,6,6,15,12,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,14,6,6,14,14,14,0,14,0,6,6,6,6,6,6,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,6,14,14,14,14,14,14,14,0,0,0,0,0, + 0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,6,14,14,14,14,14,14,14,14,14,0,0,0, + 0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,14,0,14,0,0,0,0,6,6, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,6, + 14,14,14,14,14,0,14,14,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0, + 0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,6,14,14,14,14,14,14,0,14,14,6,6,14,14,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,14,14,0,0,0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0, + 0,0,14,0,6,14,14,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,6,14,14,14,14,14,14,14,6,6, + 6,6,6,6,6,6,14,6,6,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,14,14,14,3,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,6,6,6,6,14,14,6,6,6,0,0,0,0,6,6,14,6,6,6,6,6,6,14,14,14,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,6,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,14,6,14,14,14,14,14,14,14,0,14,0,14,0,0,14,14,14,14,14,14,14,14,6,6,6,6,6,6,14,14,14,14,14,14,14,14,14,14,0,0,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,6,6, + 6,6,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,14,14,14,14,6,6,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,14,14,6,6,6,14,6,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,14,14,14,14,14,14,14,14,6,6,14,14,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,14,14,14,14,14,14,14,14,14,14,14,14,14,6,14,14,14,14,14,14,14,0,0,0,0,14,0,0,0,0,0,0,14,0,0,6,14,14,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 0,0,0,0,0,0,0,0,0,0,0,3,4,5,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0, + 0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,0, + 16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,0,16,0,16,0,0,0,0,0,0,16,0,0,0,16,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,16,0,0,16,0,0,0,0,16,0,16,0,0,0,0,16,16,16,0,16,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,16,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,14,14,14,14,14,14,14,14,14,14,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,14,0,0,0,14,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,14,14,6,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,6,14,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0, + 14,14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,14,14,14,14,6,6,14,14,6,6, + 14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,6,6,14,14,6,6,14,14,0,0,0,0,0,0,0,0,0, + 0,0,0,14,0,0,0,0,0,0,0,0,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,14,14,14,0,0,14,14,0,0,0,0,0,14,14, + 0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,14,14,6,6,0,0,0,0,0,6,14,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,14,6,6,14,6,6,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,9,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,0,0,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,0,3,3,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,0,0,0,0,0, + 0,14,14,14,0,14,14,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,0,0,0,0,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 6,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,14,14,0,0,0,0,0,0,0,0,0,0,14, + 14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,6,6,14,14,0,0,12,0,0, + 0,0,14,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,6,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,14,14,14,14,14,6, + 14,0,12,12,0,0,0,0,0,14,14,14,14,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,6,6,14,14,14,14,0,0,0,0,0,0,14,0, + 0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,6,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,14,6, + 14,6,6,6,6,0,0,6,6,0,0,6,6,14,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,6,6,0,0,14,14,14,14,14,14,14,0,0,0,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,14,14,14,14,14, + 14,0,14,0,0,14,0,14,14,14,6,0,6,6,14,14,14,12,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,14,14,14,14, + 6,6,14,14,14,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,14,14,14,14,14,14,6,14,6,6,14,6,14, + 14,6,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,14,14,14,14,0,0,6,6,6,6,14,14,6,14, + 14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,14,14,14,14,6,6,14,6,14, + 14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,14,6,6,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,14,0,0,14,14,14,14,6,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,14,14,14,14,14,6,14,14,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,6,6,6,6,6,0,6,6,0,0,14,14,14,14,12, + 6,12,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,14,14,14,14,0,0,14,14,6,6,6,6,14,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,6,12,14,14,14,14,0, + 0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,6,6,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,12,12,12,12,12,12,14,14,14,14,14,14,14,14,14,14,14,14,14,6,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,14,14,14,14,14,14,14,0,14,14,14,14,14,14,6,14, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,6,14,14,14,14,14,14,14,6,14,14,6,14,14,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,0,0,0,14,0,14,14,0,14, + 14,14,14,14,14,14,12,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,0,14,14,0,6,6,14,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,6,6,0,0,0,0,0,0,0,0,0, + 14,14,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,14,14,14,14,14,0,0,0,6,6, + 14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 14,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,14,14,14,14,14,6,6,6,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,0,0,0,14,14,14,14,14,14,3,3,3,3,3,3,3,3,14,14,14,14,14, + 14,14,14,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 14,14,14,14,14,14,14,0,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,0,0,14,14,14,14,14,14,14,0,14,14,0,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,14,14,14,14,14,14,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,16,16,16,16,16,16,16,16,16,0,16,16,16,16, + 0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,14,14,14,14,14, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16, + 16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 3,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeGraphemeBreakClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeGraphemeBreakClass_Data[((kbts_un)kbts__UnicodeGraphemeBreakClass_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeSyllabicInfo_PageIndices[8703] = { + 0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,3,4,2,5,6,7,8,9,10,11,12,13,14,15,16,17,18, + 19,20,2,2,2,2,2,2,2,2,2,2,2,2,21,22,23,24,25,26,27,28,29,30,31,32,2,33,2,2,2,2, + 34,35,2,2,2,2,2,2,2,2,2,36,2,2,2,2,2,2,2,2,2,2,2,2,2,2,37,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,38,39,40,41,42,43,2,44,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,45,2,2,2, + 2,2,2,2,2,2,2,2,2,2,46,47,2,2,2,2,2,2,2,2,48,49,2,2,2,2,50,51,2,52,53,54, + 55,56,57,58,59,60,61,62,63,64,2,65,66,67,68,2,69,2,70,71,72,73,2,2,74,75,76,77,2,78,79,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,80,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,81,82,2,2,2,83,2,2,2,84,85, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,86,86,86,87,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,88,89,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,90,2,2,91,2,2,2,92,2,93,2,2,2,2,2,2,94,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; + +static kbts_u16 kbts__UnicodeSyllabicInfo_Data[12160] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1034,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3592,3592,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,3,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,3,3,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,1025,1025,1025,1025,1025,1025,2311,2311,2307,3601,2311,519, + 2311,2311,2311,2311,2311,2311,2311,2311,2311,2311,2311,2311,2311,2308,519,2311,0,3593,3593,3592,3592,2311,2311,2311,1025,1025,1025,1025,1025,1025,1025,1025, + 1026,1026,2311,2311,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025, + 1034,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,0,0,1026,1026,0,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,0,1025,0,0,0,1025,1025,1025,1025,0,0,2307,3601,3079,519, + 3079,2311,2311,2311,2311,0,0,519,519,0,0,3079,3079,2308,1025,0,0,0,0,0,0,0,0,3079,0,0,0,0,1025,1025,0,1025, + 1026,1026,2311,2311,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1025,1025,0,0,0,0,0,0,0,0,0,0,1034,0,3592,0, + 0,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,0,0,0,0,1026,1026,0,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,0,1025,1025,0,1025,1025,0,1025,1025,0,0,3075,0,3079,519, + 3085,3079,3079,0,0,0,0,3079,3079,0,0,3079,3079,3076,0,0,0,2055,0,0,0,0,0,0,0,1025,1025,1025,1025,0,1025,0, + 0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,3592,3592,1025,1025,0,1040,0,0,0,0,0,0,0,0,0,0, + 0,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,1026,1026,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,0,1025,1025,0,1025,1025,1025,1025,1025,0,0,3075,3601,3079,519, + 3079,3079,3079,3079,3079,2311,0,2311,2311,3079,0,3079,3079,3076,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,3079,3079,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,1025,3593,2307,3593,2307,2307,2307, + 0,1800,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,0,0,1026,1026,0,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,0,1025,1025,0,1025,1025,1025,1025,1025,0,0,2307,3601,3079,1287, + 3079,2311,2311,2311,2311,0,0,519,1287,0,0,3079,3079,2308,0,0,0,0,0,0,0,1283,1287,3079,0,0,0,0,1025,1025,0,1025, + 1026,1026,2311,2311,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,3592,0,0,1026,1026,1026,1026,1026,1026,0,0,0,1026,1026,1026,0,1026,1026,1026,1025,0,0,0,1025,1025,0,1025,0,1025,1025, + 0,0,0,1025,1025,0,0,0,1025,1025,1025,0,0,0,1025,1025,1039,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,3079,3079, + 2311,3079,3079,0,0,0,519,519,519,0,3079,3079,3079,2308,0,0,0,0,0,0,0,0,0,3079,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,3592,3592,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,1026,1026,0,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,1795,3601,1799,1799, + 1799,1799,1799,2311,2311,0,1799,1799,1799,0,1799,1799,1799,1796,0,0,0,0,0,0,0,1799,1799,0,1025,1025,1025,0,0,1025,0,0, + 1026,1026,1799,1799,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1034,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,1026,1026,0,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,0,1025,1025,1025,1025,1025,0,0,1795,3601,1799,1799, + 1799,1799,1799,2311,2311,0,1799,2311,2311,0,2311,2311,1799,1796,0,0,0,0,0,0,0,2311,2311,0,0,0,0,0,0,1025,1025,0, + 1026,1026,1799,1799,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,1042,1042,3592,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,3592,1034,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,1026,1026,0,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,3601,3079,3079, + 3079,3079,3079,3079,3079,0,519,519,519,0,3079,3079,3079,4,14,0,0,0,0,0,1025,1025,1025,3079,0,0,0,0,0,0,0,1026, + 1026,1026,3079,3079,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025, + 0,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,0,0,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,0,0, + 1025,1025,1025,1025,1025,1025,1025,0,0,0,2308,0,0,0,0,2311,2311,2311,2311,2311,2311,0,2311,0,2311,519,2311,519,2311,2311,2311,2311, + 0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,2311,2311,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, + 519,519,519,519,519,7,0,7,3,3,3,3,7,3592,7,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1025,1025,0,1025,0,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,0,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,0,7,7,7,7,7,7,7,7,7,7,7,7,1040,1040,0,0, + 519,519,519,519,519,0,0,0,3,3,3,3,0,3592,3592,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,1025,1025,1025,1025, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,0,0,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,3592,0,3592,0,3,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,3,7,7,7,7,7,7,7,7,7,7,7,7,3592,1025, + 7,7,3592,3592,7,3601,3,3,1025,1025,1025,1025,1025,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,0,1040,1040,1040,1040,1040,1040,1040, + 1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,0,0,0, + 0,0,0,0,0,0,3592,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1039,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,1025, + 1025,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,23,23,20,20,21,21,22,3593,20,20,20,3593,3,1034,4,27,33,31,32,30,1025, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,1025,0,1025,1025,1026,1026,1026,1026,23,23,21,21,1039,1025,1025,1025,33,33, + 36,1025,23,34,34,1025,1025,23,23,34,34,34,34,34,1025,1025,1025,20,20,20,20,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,32,23,22,20,20,1034,1034,1034,1034,1034,1034,1034,1025,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,20,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,0,0,0,0,0,0,0,0,0,1025, + 1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,0,7,7,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1039,1025,1025,1025,1025,1025, + 1025,1025,1025,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,0,23,20,20,20,20,21,21,21,20,23, + 23,22,22,22,23,23,25,25,25,24,24,25,24,25,25,25,25,25,4,25,0,0,0,0,0,1034,0,0,3601,25,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,0,0,0,0,0,0,1025,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1034,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0, + 7,7,7,7,7,7,7,7,7,1040,1040,1040,0,0,0,0,1040,1040,3592,1040,1040,1040,1040,1040,1040,1040,3592,3592,0,0,0,0, + 0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,7,7,7,7,7,519,519,519,7,7,519,7,7,7,7,7, + 7,1025,1025,1025,1025,1025,1025,1025,3,3,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1026,1026,1026,1026,1026,1026,1025,1025,1040,1040,1040,1040,1040,1025,1040,1040,1040,1040,0, + 4,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,3592,3,3,3,3,3,7,3,3,0,0,3, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,1040,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,4,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,1040,3592,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1040,1040,1040,7,7,7,7,7,7,7,4,1040,1040,1025,1025,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,3601,1025,1025,1025,1040,1040, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1026,1026,3,7,7,7,7,7,7,7,7,7,1040,1040,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1040,1040,7,7,7,7,7,7,7,1040,1040,1040,1040,1040,1040,1040,3592,3592,0,3,0,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3593,3593,3593,0,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593, + 3593,3593,3593,3593,3593,3593,3593,3593,3593,3601,3601,3601,3601,3593,3601,3601,3601,3601,1025,1025,3593,1025,1025,3593,3593,3593,1034,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3592,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,5,6,0,0,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0, + 0,0,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3592,0,0,0,0,0,0,0,0,0,0,0, + 0,0,3592,3592,3592,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3593,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1035,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, + 1026,1026,7,1026,1026,1026,4,1025,1025,1025,1025,3592,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,7,7,7,7,7,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1026,1026, + 1026,1026,1025,1025,1025,1025,1026,1040,1040,1025,1025,1025,1025,1025,1025,1025,1025,1040,1025,3592,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1040,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,4,3592,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3593,3601,3601,3601,3601,3601,3601,0,0,0,0,0,0,1026,2311, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1026,1026,1026,1026,1026,1026,1026,1026,1026,3,3,3,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,1040,1040,1040,1040,7,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,1040,3592,1026,1026,1026,1026,1026,1025,1025,1025,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,7,7,7,7,7,7,7,7,7,1040,1040,1040, + 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,20,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1025,1025,1025,1025,1025,0, + 1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,3592,7,7,7,7,7,7,7,7,7,1040,1040,1040,1040,0,0,0,0,0,0,0,0,0, + 1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1034,1034,1034,0,0,0,1025,34,3,3,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,1026,7,7,7,519,519,7,7,519,1026,519,519,1026,7,3, + 0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,0,0,0,0,0,3592,4,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1026,1026,1025,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1040,1040,1040,1040,1040, + 1040,1040,1040,7,7,7,7,7,7,7,7,0,3,7,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1287,7,7,0,7,1287,0,0,0,0,0,7,3592,3592,3592,1025,1025,1025,1025,0,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,3,3,3,0,0,0,0,4, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,3,3,3,3592,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,0,0,0,7,7,7,7,7,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,7,7,0,0,0,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,3,3,3,3,3,3,3,3,3,3,3,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,1042,1042,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,4,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,7,1026,1026,7,7,1025,0,0,0,0,0,0,0,0,0,1034, + 3592,3592,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,4,3,0,0,0,0,0, + 0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7,7,4,3592,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034, + 0,0,0,0,1025,7,7,1025,0,0,0,0,0,0,0,0,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7,7,7, + 4,3601,0,0,0,0,0,0,0,3592,3,7,7,0,7,3592,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1025,0,0,0,0,0, + 0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,3592,4,3,3592,0,0,0,0,0,0,3593,1025, + 1026,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1025,1025,1025,0,1025,0,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3592, + 7,7,7,7,7,7,7,7,7,3,7,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 3592,3592,3592,3592,0,1026,1026,1026,1026,1026,1026,1026,1026,0,0,1026,1026,0,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,0,1025,1025,1025,1025,1025,0,3,3,3601,7,7, + 7,7,7,7,7,0,0,7,7,0,0,7,7,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,3592,3592, + 1026,1026,7,7,0,0,3593,3593,3593,3593,3593,3593,3593,0,0,0,3593,3593,3593,3593,3593,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,0,0,1026,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,3601,7,7,7,7,7,7,7,7, + 7,0,7,0,0,7,0,7,7,7,3592,0,3592,3592,3592,3,4,14,3592,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,3593,3593,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7, + 7,7,4,3592,3592,3592,3,3601,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,3592,3592, + 1042,1042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,3592, + 3592,3592,4,3,3601,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,0,0,7,7,7,7,3592,3592,3592,4, + 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1026,1026,1026,1026,7,7,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7,7,7,3592,3592,4, + 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3592,3592,7,7,7,7,7,7,7,7,7,4,3,1025,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034, + 1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,1040,1040,1040, + 7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,7,7,7,3592,3592,4,3,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,0,0,1026,0,0,1025,1025,1025,1025,1025,1025,1025,1025,0,1025,1025,0,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,0,7,7,0,0,3592,3592,7,4,0, + 1040,14,1040,3,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,0,0,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,0,0,7,7,7,7,3592,3592, + 4,3601,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,7,7,7,7,7,7,7,7,7,7,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3592,7,3592,3592,3592,3592,3592,1042,1040,1040,1040,1040,1034, + 0,0,0,0,0,1034,0,4,0,0,0,0,0,0,0,0,1026,7,7,7,7,7,7,7,7,7,7,7,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,0,0,0,0,0,0,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,3592,3592,3592,4,0,0,0,3601,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,1026,1026,0,1026,1026,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,7,0,7,7,7,7,3592,3592,3592,4, + 3601,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040, + 1040,1040,1040,1040,1040,1040,1040,1040,0,1040,1040,1040,1040,1040,1040,1040,7,7,7,7,7,3592,3592,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,1026,0,1026,1026,0,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,0,0,0,7,0,7,7,0,7, + 3592,3592,3,7,7,4,14,1040,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 1026,1026,1026,1026,1026,1026,0,1026,1026,0,1026,1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,0,7,7,0,7,7,3592,3592,4,0,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1034,7,7,7,7,0,0,0,0,0,0,0,0,0, + 3592,3592,14,3592,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,7,7,7,0,0,0,7,7, + 7,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,3,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1026,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7, + 7,7,7,7,7,7,7,7,7,7,1040,1040,1040,3592,1040,7,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3592,3592,3592,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,7,7,7,7,7,7,7,7,7,7,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,3,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,1283,1283,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,3,3,3,3,3,3,3,1025,1025,1025,1025,1025,1025,1025,0,0, + 1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,3,3,3,3,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,7,7,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,7,7,1025,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,3,3,3,3,3,3,3,1025,0,0,0,0,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u16 kbts__GetUnicodeSyllabicInfo(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeSyllabicInfo_Data[((kbts_un)kbts__UnicodeSyllabicInfo_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeFlags_PageIndices[8703] = { + 0,1,2,3,2,4,5,6,2,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, + 30,31,32,33,34,35,36,37,38,33,33,33,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,2,2,2,55, + 56,57,58,59,60,61,62,33,63,33,33,33,33,33,64,65,33,33,33,66,67,68,69,70,71,72,73,74,75,76,33,77, + 78,79,80,81,82,33,33,33,83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,84,83,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,85, + 33,33,33,33,33,33,33,33,33,86,33,33,87,88,89,90,91,92,93,94,95,96,97,98,83,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,99,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,85,33,33,100,101,102,103,33,33,104,105,106,107,108,109, + 110,111,112,113,2,114,115,116,117,118,119,120,33,33,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138, + 139,140,141,142,143,144,145,146,147,148,2,149,150,151,152,2,153,154,155,156,157,158,2,159,160,161,162,163,2,164,165,166, + 33,33,33,33,33,33,33,37,167,33,168,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,169, + 33,33,33,33,33,33,33,33,170,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, + 33,33,33,33,33,33,33,111,33,33,33,33,171,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,172,2,2,2,2,2,2,2,2,2,2,2,2,2,33,33,33,33,173,174,175,176,2,2,177,2,2,178,179,180, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,181,33,33,33,33,33,33,33,33,33,182,183,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,184, + 33,33,185,33,33,186,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,187,188,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,189,33,33,33,190,191,168, + 33,192,193,194,195,196,197,2,2,2,2,2,2,198,199,200,33,33,33,33,201,202,2,2,2,2,2,2,2,2,203,2, + 204,205,206,2,2,207,2,2,2,208,2,209,2,2,2,210,33,211,212,2,2,2,2,2,213,214,215,2,216,217,2,2, + 218,219,33,220,221,2,33,33,33,33,33,33,33,222,223,224,225,226,33,33,227,228,33,229,2,2,2,2,2,2,2,2, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,230,83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,231,2,232,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,233,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,234,2,2,2,2,235,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,33,33,33,236,2,2,2,2,2,2,2,2,2,2,2, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,237,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,238,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 239,239,240,241,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,242, + 83,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; + +static kbts_u8 kbts__UnicodeFlags_Data[31104] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,4,8,0,16,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,28,16,28,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,8,16,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,16,8,16,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,0,16,16,16,12,16,2,16,16,16,16,16,16,16,0,0,0,16,16,16,12,16,16,16,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0, + 16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,82,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,16,16,0,0,0,0,16,0,0,0,0,0, + 0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0, + 0,0,16,80,80,80,80,80,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,80, + 0,80,80,0,80,80,0,80,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,16,16,16,0,0,16,0,0,16,16,80,80,80,80,80,80,80,80,80,80,80,0,2,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,81,81,80,80,81,80,80,80,80,80,80,80,48,48,48,48,48,48,48,48,48,48,0,0,0,0,16,16,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,80,80,80,80,80,80,81,0,16,80,80,80,80,81,80,16,16,81,81,16,80,80,80,80,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, + 80,80,80,80,80,80,80,80,80,80,80,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,16,16,16,0,0,0,16,0,0,80,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,80,80,80,80,80,80,80,80,80,16,80,80,80,16,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,81,81,80,81,81,81,80,80,80,81,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,81,80,80,80,80,80,80,80,80,80,80,80,80, + 80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,16,16,16, + 16,80,80,80,80,80,80,80,80,16,16,16,16,80,16,16,16,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,80,16,16,0,16,16,16,16,16,16,16,16,0,0,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,0,0,0,16,16,16,16,0,0,80,16,16,16, + 16,80,80,80,80,0,0,16,16,0,0,16,16,80,16,0,0,0,0,0,0,0,0,16,0,0,0,0,16,16,0,16,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,0,80,0, + 0,80,80,16,0,16,16,16,16,16,16,0,0,0,0,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,0,16,16,0,16,16,0,0,80,0,16,16, + 16,80,80,0,0,0,0,80,80,0,0,80,80,80,0,0,0,80,0,0,0,0,0,0,0,16,16,16,16,0,16,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,80,80,16,16,16,80,0,0,0,0,0,0,0,0,0,0, + 0,80,80,16,0,16,16,16,16,16,16,16,16,16,0,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,0,0,80,16,16,16, + 16,80,80,80,80,80,0,80,80,16,0,16,16,80,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,0,16,0,0,0,0,0,0,0,16,80,80,80,80,80,80, + 0,80,16,16,0,16,16,16,16,16,16,16,16,0,0,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,0,0,80,16,16,80, + 16,80,80,80,80,0,0,16,16,0,0,16,16,80,0,0,0,0,0,0,0,80,80,16,0,0,0,0,16,16,0,16,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0, + 0,0,80,16,0,16,16,16,16,16,16,0,0,0,16,16,16,0,16,16,16,16,0,0,0,16,16,0,16,0,16,16,0,0,0,16,16,0,0,0,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16, + 80,16,16,0,0,0,16,16,16,0,16,16,16,80,0,0,16,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0, + 80,16,16,16,80,16,16,16,16,16,16,16,16,0,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,16,80,80, + 80,16,16,16,16,0,80,80,80,0,80,80,80,80,0,0,0,0,0,0,0,80,80,0,16,16,16,0,0,16,0,0,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16, + 16,80,16,16,0,16,16,16,16,16,16,16,16,0,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,0,0,80,16,16,80, + 16,16,16,16,16,0,80,16,16,0,16,16,80,80,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,16,16,0,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 80,80,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,16,16, + 16,80,80,80,80,0,16,16,16,0,16,16,16,80,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,80,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,0,16,0,0, + 16,16,16,16,16,16,16,0,0,0,80,0,0,0,0,16,16,16,80,80,80,0,80,0,16,16,16,16,16,16,16,16,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,16,80,80,80,80,80,80,80,0,0,0,0,16, + 16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,16,16,0,16,0,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,0,16,16,16,16,16,16,16,16,16,16,80,16,16,80,80,80,80,80,80,80,80,80,16,0,0, + 16,16,16,16,16,0,16,0,80,80,80,80,80,80,80,0,48,48,48,48,48,48,48,48,48,48,0,0,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,16,16,16,80,80,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,80,16,80,16,80,4,8,4,8,16,16, + 16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,16, + 80,80,80,80,80,0,80,80,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,16,16, + 16,16,16,16,16,16,80,16,16,16,16,16,16,0,16,16,0,0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,80,80,80,80,80,80,16,80,80,16,16,80,80,16, + 48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,80,80,16,16,16,16,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16, + 16,16,80,16,16,80,80,16,16,16,16,16,16,80,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,80,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,18,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,0,16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,0, + 16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,80,80,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,4,8,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,0,80,80,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,82,82,16,80,80,80,80,80,80,80,16,16, + 16,16,16,16,16,16,80,16,16,80,80,80,80,80,80,80,80,80,80,80,0,0,0,16,0,0,0,16,16,80,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,82,82,82,2,82,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 16,16,16,16,16,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,80,80,80,16,16,16,16,80,80,16,16,16,0,0,0,0,16,16,80,16,16,16,16,16,16,80,80,80,0,0,0,0, + 16,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,16,80,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,80,80,80,80,80,80,0,80,16,80,16,16,80,80,80,80,80,80,80,80,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,0,0,80, + 48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,16,80, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,80,80,80,80,16,80,16,16,16, + 16,16,80,16,16,16,16,16,16,16,16,16,16,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,16,0,0,0, + 80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,16,80,80,16,80,80,80,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,80,16,16,16,80,16,80,80,80,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,16,16,80,80,0,0,0,0,0,0,0,0, + 48,48,48,48,48,48,48,48,48,48,0,0,0,16,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,0,80,80,80,80,80,80,80,80,80,80,80,80,80,16,80,80,80,80,80,80,80,16,16,16,16,80,16,16,16,16,16,16,80,16,16,16,80,80,16,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,16, + 16,16,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0, + 0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,12,12,0,0,0,0,0, + 0,0,0,0,16,4,8,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,16,16,0,0,16,16,16,16,16,16,16,16,16,4,8,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,4,8,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,16,16,16,16,80,16,16,16,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,0,16,16,16,16,0,16,16,0,0,0,0,0,0,0,0,0,0,16,0,16,16,16,0,0,0,0,0,16,16,16,16,16,16,0,16,0,16,0,16,0,0,0,0,16,0,0,0,0,0,0,16,16,16,16,0,16,16,0,0,0,0, + 16,16,16,16,16,0,0,0,0,0,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,0,0,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,28,28,28,28,28,28,16,16,16,16,16,16,16,28,16,16,16,16,16,16,16,16,16,28,28,28,28,16,28,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,28,16,16, + 16,16,16,28,16,28,16,16,16,16,16,16,28,16,16,16,16,16,28,28,28,28,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,28,28,28,28,28,28,28,16,16,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,28,28,28,28,16,16,16,28,28,28,28,16,16,16,16,16,28,16,16,16,16,16,16,16,16,16,28,28,16,16,28,16,28,28,16,28,16,16,16,16,28,28,28,28,28,28,28,28,28,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,28,28,28,28,28,16,16,28,28,16,16,16,16,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,16,16,28,28,28,28,28,16,28,28,16,16,28,28,28,28,28,16, + 16,16,16,16,16,16,16,16,4,8,4,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,4,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,4,8,4,8,4,8,4,8,4,8,4,8,4,8,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,28,28,4,8,16,28,28,16,28,16,28,16,16,16,16,16,16,16,28,28,16,16,16,16,16,28,28,28,16,16,16,28,28,28,28,4,8,4,8,4,8,4,8,4,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,4,8,4,8,4,8,4,8,4,8,4,8,4,8,4,8,4,8,4,8,4,8,16,16,28,16,16,16,16,28,16,16,28,28,28,16,16,28,28,28,28,28,28,28,28,16,16,16,16,16,16,16,16,28,16,16,16,16,16,16,16, + 28,28,16,16,28,28,16,16,16,16,16,16,16,16,16,28,28,28,28,16,28,28,16,16,4,8,4,8,16,16,16,16,16,16,16,16,16,16,16,16,28,28,16,16,16,16,16,16,16,16,16,16,16,28,16,16,28,28,16,16,4,8,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,28,28,28,16,16,16,16,16,28,28,16,16,16,16,16,16,28,28,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,28,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,16,16,16,28,28,28,28,28,28,28,28,16,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,16,16,16,16,16,16,16,28,16,16,16,16,28,28,28,16,16,16,16,16,16,28,28,28,16,16,16,16,16,16,16,16,28,28,28,28,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,28,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,0,0,0,0,80,80,80,0,0,0,0,0,0,0,0,0,0,0,16,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0, + 16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, + 0,0,12,12,12,12,0,0,0,12,12,0,12,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,12,0,0,12,12,4,8,4,8,4,8,4,8,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,4,8,4,8,4,8,4,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,16,16,16,16,4,8,4,8,4,8,4,8,4,8,16,16,4,8,4,8,4,8,4,8,0,0,0,0,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,80,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16, + 0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,80,16,16,16,0,80,80,80,80,80,80,80,80,80,80,0,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,16,16,16,0,16,16,16,16,16, + 16,16,80,16,16,16,80,16,16,16,16,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,16,16,16,16,80,0,0,0,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,80,80,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,16,16,16,16,16,16,0,0,0,16,0,16,16,80, + 48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0, + 80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,16,80,80,80,80,16,16,80,80,16,16, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,80,16,16,16,16,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,16,16,80,80,16,16,80,80,0,0,0,0,0,0,0,0,0, + 16,16,16,80,16,16,16,16,16,16,16,16,80,16,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,80,80,16,16,80,80,16,16,16,16,16,80,80, + 16,80,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,16,0,0,16,16,16,16,80,0,0,0,0,0,0,0,0,0, + 0,16,16,16,16,16,16,0,0,16,16,16,16,16,16,0,0,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,16,80,16,16,0,16,80,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,0,16,0, + 16,16,0,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,4,8,4,8,0,0,0,16,0,28,28,16,0,0,16,0,0,0,0,0,0,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,2, + 0,0,0,0,16,0,0,0,4,8,0,16,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,28,16,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,8,16,0, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,16,8,16,4,8,0,4,8,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0, + 0,0,16,16,16,16,16,16,0,0,16,16,16,16,16,16,0,0,16,16,16,16,16,16,0,0,16,16,16,0,0,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,2,2,2,2,2,2,2,2,2,0,0,0,16,16,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,0,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0, + 0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,0,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,0,0,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,0,0,0,16,0,0,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,0,0,0,0,0,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,80,80,80,0,80,80,0,0,0,0,0,80,80,80,80,16,16,16,16,0,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,80,80,0,0,0,0,80, + 16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,0,0,0,0,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,80,80,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0, + 16,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80, + 80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,80,16,16,80,80,16,0,0,0,0,0,0,0,0,0,80, + 80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,16,80,80,0,0,0,0,0, + 0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,16,80,80,80,80,80,80,80,80,0,48,48,48,48,48,48,48,48,48,48, + 0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,0,0,16,0,0,0,0,0,0,0,0,0, + 80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,16, + 16,16,16,16,16,0,0,0,0,80,80,80,80,0,16,80,48,48,48,48,48,48,48,48,48,48,16,0,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,16,16,80,16,80,80,0,0,0,0,0,0,80,16, + 16,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,0,16,0,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,16,16,80,80,80,80,80,80,80,80,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 80,80,16,16,0,16,16,16,16,16,16,16,16,0,0,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,0,80,80,16,16,16, + 80,16,16,16,16,0,0,16,16,0,0,16,16,16,0,0,16,0,0,0,0,0,0,16,0,0,0,0,0,16,16,16,16,16,16,16,0,0,80,80,80,80,80,80,80,0,0,0,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,0,16,0,0,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,80,80,80,80,80, + 80,0,16,0,0,16,0,16,16,16,16,0,16,16,80,16,80,16,80,16,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80, + 16,16,80,80,80,16,80,16,16,16,16,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,80,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,16,80,16,16,16,16,80, + 80,16,80,80,16,16,0,16,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,0,0,16,16,16,16,80,80,16,80, + 80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,16,16,80,16,80, + 80,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,16,80,16,16,80,80,80,80,80,80,16,80,16,0,0,0,0,0,0,0, + 48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,16,80,16,16,80,80,80,80,16,80,80,80,80,80,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,16,0,0,0,16, + 16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,16,80,80,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16, + 16,16,16,16,16,16,16,0,0,16,0,0,16,16,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,0,0,80,80,16,80,16, + 16,16,16,80,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,0,0,80,80,16,16,16,16,80,16,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,80,80,80,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,16,16,80,80,80,80,0, + 0,0,0,0,0,0,0,80,0,0,0,0,0,0,0,0,16,80,80,80,80,80,80,16,16,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,80,80,16,80,80,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,0,80,80,80,80,80,80,16,80, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,16,80,80,80,80,80,80,80,16,80,80,16,80,80,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,0,0,0,80,0,80,80,0,80, + 80,80,80,80,80,80,16,80,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,0,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,80,80,0,16,16,80,16,80,16,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,16,0,0,0,0,0,0,0,0,0, + 80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,0,0,0,16,16, + 80,16,80,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 80,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,80,80,80,80,80,16,16,16,80,80,80,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0, + 48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,0,0,0,0,0,16,16,16,16, + 16,16,16,16,0,16,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,16,80,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16, + 16,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0, + 16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,0,0,16,80,80,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80, + 80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,16,16,16,16,16,16,16,16,16,2,2,2,2,2,2,2,2,80,80,80,80,80, + 80,80,80,16,16,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,80,80,80,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,16,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,16,16,16,16,80,80,80,80,80, + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,16,16,16,16,16,16,16,16,80,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,80,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 80,80,80,80,80,80,80,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,0,0,80,80,80,80,80,80,80,0,80,80,0,80,80,80,80,80,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,80,80,80,80,80,80,80,16,16,16,16,16,16,16,0,0, + 48,48,48,48,48,48,48,48,48,48,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,16, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,80,80,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,80,80,16,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,0,16,16,16,16,0,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,80,80,80,80,80,80,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,80,80,80,80,80,80,80,16,0,0,0,0,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,0,16,0,0,16,0,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,0,16,0,16,0,0,0,0, + 0,0,16,0,0,0,0,16,0,16,0,16,0,16,16,16,0,16,16,0,16,0,0,16,0,16,0,16,0,16,0,16,0,16,16,0,16,0,0,16,16,16,16,0,16,16,16,16,16,16,16,0,16,16,16,16,0,16,16,16,16,0,16,0, + 16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,0,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0, + 16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0, + 16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0, + 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, + 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, + 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82, + 82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeFlags(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeFlags_Data[((kbts_un)kbts__UnicodeFlags_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeBidirectionalClass_PageIndices[8703] = { + 0,1,2,2,2,3,4,5,2,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28, + 29,30,2,2,31,32,33,34,35,2,2,2,2,36,37,38,39,40,41,42,43,44,45,46,47,48,2,49,2,2,50,51, + 52,53,54,55,56,57,58,59,57,60,57,57,57,61,57,57,2,2,57,57,57,57,57,57,2,62,63,64,57,57,57,57, + 65,66,67,68,69,70,71,72,73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,74,73,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,75, + 2,2,2,2,2,2,2,2,2,76,2,2,77,78,79,80,81,82,83,84,85,86,87,88,73,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,89,73,57,57,57,57,57,75,90,73,57,57,57,57,57,57,75, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,75,2,2,91,92,93,94,95,95,96,97,98,99,100,101, + 102,103,104,105,57,106,107,108,2,109,110,111,2,2,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129, + 130,131,132,133,134,135,136,137,138,139,57,140,141,142,143,57,144,145,146,147,148,149,150,151,152,153,154,155,57,156,157,158, + 2,2,2,2,2,2,2,159,160,2,161,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,162, + 2,2,2,2,2,2,2,2,163,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,103,2,2,2,2,164,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,165,57,57,57,57,57,57,57,57,57,57,57,57,57,2,2,2,2,166,167,168,169,57,57,170,57,171,172,173,174, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,175,2,2,2,2,2,2,2,2,2,176,177,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,178, + 2,2,179,2,2,180,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,181,182,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,183,57,57,57,57,184,161, + 2,185,186,187,188,189,190,57,191,192,193,2,2,194,195,196,2,2,2,2,197,198,57,57,57,57,57,57,57,57,199,57, + 200,201,202,57,57,203,57,57,57,204,57,205,57,57,57,206,207,208,209,57,57,57,57,57,210,211,212,57,213,214,57,57, + 57,57,215,216,217,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,218,57,57,57,57,57,57,57,57, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,219,73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,220,57,221,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,222,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,223,57,57,57,57,224,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,2,2,2,2,225,57,57,57,57,57,57,57,57,57,57,57, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,226,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,227,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 228,57,229,230,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,231, + 73,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, + 57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57, +}; + +static kbts_u8 kbts__UnicodeBidirectionalClass_Data[29696] = { + 1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,9,9,9,0,0,0,0,0,8,10,8,10,10,7,7,7,7,7,7,7,7,7,7,10,0,0,0,0,0, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,1, + 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,10,0,9,9,9,9,0,0,0,0,2,0,0,1,0,0,9,9,7,7,0,2,0,0,0,7,2,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2, + 2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,0,0,2,2,0,0,2,2,2,2,0,2, + 0,0,0,0,0,0,2,0,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2, + 2,2,2,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,9,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,4, + 3,4,4,3,4,4,3,4,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0, + 6,6,6,6,6,6,0,0,5,9,9,5,10,5,0,0,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,6,6,6,6,9,6,6,5,5,5,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,6,0,4,4,4,4,4,4,5,5,4,4,0,4,4,4,4,5,5,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,3,3,0,0,0,0,3,0,0,4,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,3,4,4,4,4,4,4,4,4,4,3,4,4,4,3,4,4,4,4,4,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,0,0,3,0,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,6,6,0,0,0,0,0,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,2,2,2, + 2,4,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,4,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0,0,0,2,2,2,2,0,0,4,2,2,2, + 2,4,4,4,4,0,0,2,2,0,0,2,2,4,2,0,0,0,0,0,0,0,0,2,0,0,0,0,2,2,0,2,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,2,2,9,9,2,2,2,2,2,2,2,9,2,2,4,0, + 0,4,4,2,0,2,2,2,2,2,2,0,0,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,0,2,2,0,0,4,0,2,2, + 2,4,4,0,0,0,0,4,4,0,0,4,4,4,0,0,0,4,0,0,0,0,0,0,0,2,2,2,2,0,2,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,4,2,0,0,0,0,0,0,0,0,0, + 0,4,4,2,0,2,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,4,2,2,2, + 2,4,4,4,4,4,0,4,4,2,0,2,2,4,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,2,9,0,0,0,0,0,0,0,2,4,4,4,4,4,4, + 0,4,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,0,4,2,2,4, + 2,4,4,4,4,0,0,2,2,0,0,2,2,4,0,0,0,0,0,0,0,4,4,2,0,0,0,0,2,2,0,2,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0, + 0,0,4,2,0,2,2,2,2,2,2,0,0,0,2,2,2,0,2,2,2,2,0,0,0,2,2,0,2,0,2,2,0,0,0,2,2,0,0,0,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2, + 4,2,2,0,0,0,2,2,2,0,2,2,2,4,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,9,0,0,0,0,0,0, + 4,2,2,2,4,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,2,4,4, + 4,2,2,2,2,0,4,4,4,0,4,4,4,4,0,0,0,0,0,0,0,4,4,0,2,2,2,0,0,2,0,0,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2, + 2,4,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,4,2,2,2, + 2,2,2,2,2,0,2,2,2,0,2,2,4,4,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 4,4,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2, + 2,4,4,4,4,0,2,2,2,0,2,2,2,4,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,4,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,0,0, + 2,2,2,2,2,2,2,0,0,0,4,0,0,0,0,2,2,2,4,4,4,0,4,0,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,4,4,4,4,4,4,4,0,0,0,0,9, + 2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,2,0,2,0,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2,2,2,2,2,2,2,2,4,2,2,4,4,4,4,4,4,4,4,4,2,0,0, + 2,2,2,2,2,0,2,0,4,4,4,4,4,4,4,0,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,2,4,0,0,0,0,2,2, + 2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2, + 4,4,4,4,4,2,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2, + 2,2,2,2,2,2,4,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,4,4,4,4,4,4,2,4,4,2,2,4,4,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2, + 2,2,4,2,2,4,4,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,0, + 2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,4,4,4,4,4,4,4,2,2, + 2,2,2,2,2,2,4,2,2,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,9,2,4,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,4,4,4,1,4,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,4,4,4,2,2,2,2,4,4,2,2,2,0,0,0,0,2,2,4,2,2,2,2,2,2,4,4,4,0,0,0,0, + 0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,4,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,4,4,4,0,4,2,4,2,2,4,4,4,4,4,4,4,4,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,0,0,4, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,4,4,2,4,2,2,2, + 2,2,4,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2, + 4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,4,2,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,2,2,2,4,2,4,4,4,2,2,0,0,0,0,0,0,0,0,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,2,2,4,4,0,0,0,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2, + 2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,4,4,2,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,2,0,2,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,0, + 0,0,2,2,2,0,2,2,2,2,2,2,2,0,0,0,2,2,2,2,0,0,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,0,2,2,2,2,2,2,2,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,7,2,0,0,7,7,7,7,7,7,8,8,0,0,0,2, + 7,7,7,7,7,7,7,7,7,7,8,8,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2,2,2,0,2,0,0,0,2,2,2,2,2,0,0,0,0,0,0,2,0,2,0,2,0,2,2,2,2,9,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2, + 0,0,0,0,0,2,2,2,2,2,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,4,4,4,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0, + 2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,0,2,2,2,2,2,0,0,2,2,2,2,2,0,0,0, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,4,0,0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2, + 0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,0,2,0,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,4,2,2,2,4,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,0,0,0,0,4,0,0,0,2,2,2,2,2,2,2,2,9,9,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,4,4,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,4, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0, + 4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,4,4,4,4,2,2,4,4,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,2,2,4,4,2,2,4,4,0,0,0,0,0,0,0,0,0, + 2,2,2,4,2,2,2,2,2,2,2,2,4,2,0,0,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,2,2,4,4,2,2,2,2,2,4,4, + 2,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0, + 0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,4,2,2,2,2,4,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,3,4,3,3,3,3,3,3,3,3,3,3,8,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,0,3,0, + 3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,10,0,0,10,0,0,0,0,0,0,0,0,0,9,0,0,8,8,0,0,0,0,0,9,9,0,0,0,0,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,1, + 0,0,0,9,9,9,0,0,0,0,0,8,10,8,10,10,7,7,7,7,7,7,7,7,7,7,10,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0, + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, + 0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,2,2,2,0,0,2,2,2,0,0,0,9,9,0,0,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0, + 2,0,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,0,0,3,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0,0,0,3,0,0,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0,0,0,0,0,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,4,4,4,0,4,4,0,0,0,0,0,4,4,4,4,3,3,3,3,0,3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,4,4,4,0,0,0,0,4, + 3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,3,3,3,3,3,3, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,6,0,0,0,0,0,0, + 6,6,6,6,6,6,6,6,6,6,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,4,4,4,4,4,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,4,4,3,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,4,4,4,4,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0, + 2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,4,2,2,4,4,2,0,0,0,0,0,0,0,0,0,4, + 4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,4,2,2,2,2,2, + 2,2,4,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,2,4,4,4,4,4,4,4,4,0,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,0,0,0,0,0,0,0,0,0, + 4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,2, + 2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,2,4,2,4,4,2,2,2,2,2,2,4,2, + 2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,0,2,0,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,4,4,4,4,4,4,4,4,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 4,4,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,0,4,4,2,2,2, + 4,2,2,2,2,0,0,2,2,0,0,2,2,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,2,2,2,2,2,2,2,0,0,4,4,4,4,4,4,4,0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,0,2,0,0,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,4,4,4,4,4, + 4,0,2,0,0,2,0,2,2,2,2,0,2,2,4,2,4,2,4,2,2,2,0,2,2,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4, + 2,2,4,4,4,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,2,4,2,2,2,2,4, + 4,2,4,4,2,2,2,2,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,0,0,2,2,2,2,4,4,2,4, + 4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,2,2,4,2,4, + 4,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,4,2,2,4,4,4,4,4,4,2,4,2,2,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,2,4,2,2,4,4,4,4,2,4,4,4,4,4,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,2,4,4,2,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2, + 2,2,2,2,2,2,2,0,0,2,0,0,2,2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,4,4,2,4,2, + 2,2,2,4,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,0,0,4,4,2,2,2,2,4,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,4,4,4,4,4,4,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,2,2,4,4,4,4,2, + 2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,2,4,4,4,4,4,4,2,2,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,0,4,4,4,4,4,4,2,2, + 2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,4,4,4,4,4,4,4,2,4,4,2,4,4,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,0,0,0,4,0,4,4,0,4, + 4,4,4,4,4,4,2,4,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,4,4,0,2,2,4,2,4,2,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,0,0,0,0,0,0,0, + 4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,0,0,0,2,2, + 4,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 4,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,4,4,4,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,4,4,4,4,4,2,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,2,4,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, + 2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0, + 2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,0,2,4,4,2,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,4,4,4,4,4, + 4,4,4,2,2,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,2,0,0,2,2,0,0,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,0,2,0,2,2,2, + 2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,0, + 2,2,2,2,2,0,2,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,2,2,2,2,2,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,4,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 4,4,4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,4,4,4,0,4,4,0,4,4,4,4,4,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,4,4,4,4,4,4,4,2,2,2,2,2,2,2,0,0, + 2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,0,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,4,4,4,4,4,4,4,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,0,5,0,0,5,0,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,0,5,0,5,0,0,0,0, + 0,0,5,0,0,0,0,5,0,5,0,5,0,5,5,5,0,5,5,0,5,0,0,5,0,5,0,5,0,5,0,5,0,5,5,0,5,0,0,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5,5,5,0,5,5,5,5,0,5,0, + 5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,5,5,5,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0, + 2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, + 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeBidirectionalClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeBidirectionalClass_Data[((kbts_un)kbts__UnicodeBidirectionalClass_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeJoiningType_PageIndices[8703] = { + 0,1,0,0,0,0,2,0,0,3,0,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,0,0,0,0,27,0,0,0,0,0,0,0,28,29,30,31,32,0,33,34,35,36,37,38,0,39,0,0,0,0, + 40,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,43,44,0,0,0,0, + 45,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,47,48,0,0,49,50,51,52,53,54,0,55,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,57,43,0,58, + 0,0,0,59,0,60,61,0,0,0,0,0,0,0,0,0,0,0,0,0,62,63,0,64,0,0,65,0,0,66,67,68, + 69,70,71,72,73,74,75,76,77,78,0,79,80,81,82,0,83,0,84,85,86,87,0,0,88,89,90,91,0,92,93,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,94,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,97,0,0,0,0,0,0,0,98,99, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,0, + 0,0,102,103,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,105,106,0,0,0,0,0,0,0,0,0,0, + 107,108,97,0,0,109,0,0,0,110,0,111,0,0,0,0,0,112,113,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 114,0,115,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static kbts_u8 kbts__UnicodeJoiningType_Data[14848] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5, + 0,5,5,0,5,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,5,0,0,0,2,0,4,4,4,4,2,4,2,4,2,2,2,2,2,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,2,2,2,2,2,2,2,4,2,2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,5,4,4,4,0,4,4,4,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 4,2,2,4,4,4,4,4,4,4,4,4,2,4,2,4,2,2,4,4,0,4,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,0,0,5,5,0,5,5,5,5,4,4,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,4,5,2,2,2,4,4,4,4,4,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,4,2,4,2,2,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0,0,4,2,2,2,2,2,2,2,2,2,2,2,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,2,2,2,2,4,2,4,4,2,2,2,4,4,2,2,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,3,0,0,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,5,5,5,5,5,0,5,5,5,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 4,2,2,2,2,2,4,4,2,4,2,2,2,2,2,2,2,2,2,2,4,2,4,4,4,5,5,5,0,0,0,0,2,0,2,2,2,2,0,4,2,4,4,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,3,3,3,2,0,0,2,2,2,2,2,4,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,2,2,2,2,2,2,2,2,2,2,4,4,4,0,4,2,2,4,4,2,2,2,2,2,2,4,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0, + 0,5,5,5,5,5,5,5,5,0,0,0,0,5,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0, + 0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 0,5,5,0,0,0,0,5,5,0,0,5,5,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0, + 0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 0,5,5,5,5,5,0,5,5,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5, + 0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5, + 5,0,0,0,0,0,5,5,5,0,5,5,5,5,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5, + 0,0,0,0,0,0,5,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0, + 0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,5,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,5,5,5,5,5,0,0,0,0,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,5,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,5,5,5,5,0,5,5,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,5,5,0,5,5,0,0,5,5,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,0,0,5,5,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,5,0,0,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,3,5,5,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 0,0,0,0,0,5,5,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,5,5,5,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5,5,5,5,5,5,0,5,0,5,0,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5,5,5,5,0,5,0,0,0, + 0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,5,5,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5,0,0,0,5,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0,0,5,5,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,0,0,0,0,5,0,0,0,0,0,0,5,0,0,0,5,5,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,5,0,3,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,0,0,0,5,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,5,5,0,0,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,5,5,0,0,5,5,0,0,0,0,0,0,0,0,0, + 0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,5,5,0,0,5,5,0,0,0,0,0,5,5, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0, + 0,5,5,5,0,5,5,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,4,0,4,0,4,4,0,0,1,4,4,4,4,4,2,2,2,2,1,2,2,2,2,2,4,2,2,2,4,0,0,4,5,5,0,0,0,0,2,2,2,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,4,2,4,4,4,2,2,2,4,2,2,4,2,4,4,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,4,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,0,5,5,5,5,5,5,5,5,5,5,5,2,2,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,4,4,2,2,2,2,2,2,2,2,2,2, + 2,2,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,2,4,4,4,0,2,4,4,2,2,4,2,2, + 0,2,4,4,2,0,0,0,0,4,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,5,5,0,0,0,0,0,0,0,0,0,0,5, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,5,5,0,0,0,0,0, + 0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0, + 0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,5,0,5,5,0,0,0,0,0,0,5,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 0,0,5,5,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,5,0,0,0,0,5, + 5,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,5,5,0,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0,0,5,0,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,5,5,5,5,5,5,0,5,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,5,5,5,5,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,5,5,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,5,0, + 0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,5,5,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,5,5,5,5,0, + 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,5,5,5,5,5,5,0,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,0,5,5,0,5,5,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,0,5,0,5,5,0,5, + 5,5,5,5,5,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0, + 5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0, + 5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,5,5,5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeJoiningType(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeJoiningType_Data[((kbts_un)kbts__UnicodeJoiningType_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeCombiningClass_PageIndices[8703] = { + 0,0,0,0,0,0,1,0,0,2,0,3,4,5,6,7,8,9,10,11,12,12,12,13,14,12,15,16,17,18,19,20, + 21,22,0,0,0,0,23,0,0,0,0,0,0,0,24,25,0,26,27,0,28,29,30,31,32,33,0,34,0,0,0,0, + 0,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,37,38,0,0,0,0, + 39,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,41,42,0,0,43,44,45,46,0,47,0,48,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,0,0,0,0,0,50,0,0,0, + 0,0,0,51,0,52,53,0,0,0,0,0,0,0,0,0,0,0,0,0,54,55,0,0,0,0,56,0,0,57,58,59, + 60,61,62,63,64,65,66,67,68,69,0,70,71,72,73,0,61,0,74,75,76,77,0,0,71,0,78,79,0,0,80,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,83,0,0,0,0,0,0,0,0,84, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,86,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 89,90,83,0,0,91,0,0,0,92,0,93,0,0,0,0,0,94,95,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static kbts_u8 kbts__UnicodeCombiningClass_Data[12288] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,220,220,220,220,220,220,220,220,1,1,1,1,1,220,220,220,220,230,230,230, + 230,230,230,230,230,240,230,220,220,220,230,230,230,220,220,0,230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,234,234,233,230,230,230,230,230,230,230,230,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,230,230,230,230,220,230,230,230,222,220,230,230,230,230,230,230,220,220,220,220,220,220,230,230,220,230,230,222,228,230,22,15,16,17,23,18,19,20,21,14,14,24,12,25,0,13, + 0,10,11,0,230,220,0,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,230,31,32,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,28,29,30,31,32,33,27,34,230,230,220,220,230,230,230,230,230,220,230,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,0,0,230,230,230,230,220,230,0,0,230,230,0,220,230,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,220,230,230,220,230,230,220,220,220,230,220,220,230,220,230, + 230,230,220,230,220,230,220,230,220,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,220,230,0,0,0,0,0,0,0,0,0,220,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,0,230,230,230,230,230,230,230,230,230,0,230,230,230,0,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,220,220,220,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,220,220,220,220,220,230,230,230,230,230,230,230,230,230,230,230,230,230,230,0,220,230,230,220,230,230,220,230,230,230,220,220,220,28,29,30,230,230,230,220,230,230,220,220,230,230,230,230,230, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,230,220,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,9,0,0,0,0,0, + 0,0,0,0,0,0,0,0,107,107,107,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,118,9,0,0,0,0,0, + 0,0,0,0,0,0,0,0,122,122,122,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,220,0,127,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,132,0,131,0,0,0,0,0,132,132,132,132,0,0, + 132,0,230,230,9,0,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,9,9,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,222,230,220,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,230,0,0,220, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,220,220,220,220,220,220,230,230,220,0,220, + 220,230,230,220,220,230,230,230,230,230,220,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,220,230,230,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,0,1,220,220,220,220,220,230,230,220,220,220,220,230,0,1,1,1,1,1,1,1,0,0,0,0,220,0,0,0,0,0,0,230,0,0,0,230,230,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 230,230,220,230,230,230,230,230,230,230,220,230,230,234,214,220,202,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,232,228,228,220,218,230,233,220,230,220, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,1,1,230,230,230,230,1,1,1,230,230,0,0,0,0,230,0,0,0,1,1,230,220,230,1,1,220,220,220,220,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,218,228,232,222,224,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,0,230,230,230,230,230,230,230,230,230,230,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0, + 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,230,230,220,0,0,230,230,0,0,0,0,0,230,230, + 0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,220,220,220,220,220,220,220,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,1,220,0,0,0,0,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,220,220, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,220,220,230,230,230,220,230,220,220,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,230,220,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 9,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,0,0,0,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,9,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, + 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9,0, + 0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,7,0,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,230,230,230,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,216,216,1,1,1,0,0,0,226,216,216,216,216,216,0,0,0,0,0,0,0,0,220,220,220,220,220, + 220,220,220,0,0,230,230,230,230,230,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 230,230,230,230,230,230,230,0,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,0,0,230,230,230,230,230,230,230,0,230,230,0,230,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,230,230,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,232,232,220,230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,220,220,220,220,220,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,230,230,230,230,230,230,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeCombiningClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeCombiningClass_Data[((kbts_un)kbts__UnicodeCombiningClass_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u16 kbts__UnicodeParentInfo_PageIndices[34815] = { + 0,1,2,3,0,4,5,6,7,0,8,9,0,10,0,11,0,12,0,0,13,14,0,0,15,0,0,0,16,17,18,0, + 19,20,21,22,0,0,23,24,0,0,0,0,0,0,25,26,0,27,28,0,0,0,29,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,30,31,0,0,0,32,33,0,34,35,0,0,0,0,0,0,0,36,37,0,0,0,38,0, + 0,0,39,0,0,40,41,0,0,0,38,0,0,0,42,0,0,0,0,0,0,0,0,0,0,0,43,44,45,46,0,0, + 0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50,51,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,52,53,54,0,55,56,0,57,58,59,60,0,61,62,63, + 64,0,0,0,0,0,0,0,0,0,0,0,65,0,66,0,67,68,69,70,71,72,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 74,0,75,76,77,75,76,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,79,80,81,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,0,0,0,0,84,0,0,0, + 0,85,0,86,0,0,87,88,89,90,0,0,0,0,0,0,0,91,0,92,0,0,0,93,94,0,95,0,96,0,0,0, + 97,0,98,0,0,0,0,0,0,99,0,0,100,0,0,0,0,0,0,0,0,101,0,0,102,0,0,0,0,0,0,103, + 104,105,106,0,107,0,0,108,0,109,0,0,0,0,0,0,110,111,0,0,0,112,0,0,113,114,115,0,0,0,116,0, + 117,0,0,118,0,0,0,0,0,119,120,121,0,0,122,123,0,124,0,0,0,125,126,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,128,0,0,0,129,0,130,0,0,0,131,0,0,0,0,132,0, + 0,0,0,0,0,0,133,134,0,0,135,0,0,0,0,0,136,137,138,0,139,140,141,142,0,0,0,143,144,145,0,0, + 146,147,0,148,149,0,150,151,0,0,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,0,0,170,171, + 172,173,174,175,176,177,0,178,179,0,180,181,182,183,184,185,186,0,187,188,0,0,0,189,190,0,0,0,191,0,192,193, + 194,195,196,0,0,197,198,199,200,201,202,203,0,0,204,205,206,207,0,208,0,209,0,0,210,211,0,0,212,0,213,214, + 215,216,0,217,218,0,219,0,220,0,221,222,0,223,0,224,0,225,0,226,0,227,228,229,230,231,232,233,234,235,236,237, + 238,0,0,239,240,0,241,242,243,0,244,245,246,247,248,249,250,251,252,0,0,253,254,255,0,256,257,258,259,260,261,262, + 263,264,265,266,267,0,268,0,0,0,269,270,271,0,272,273,274,0,275,276,277,278,279,280,281,282,283,284,285,0,0,286, + 287,0,288,0,289,290,0,0,291,0,292,0,0,293,0,294,295,0,0,0,0,296,297,0,298,299,300,301,302,303,0,0, + 0,0,304,305,306,307,308,309,310,311,312,313,314,0,315,316,317,318,0,319,320,321,322,0,323,324,0,325,0,0,326,327, + 328,329,330,331,332,333,334,0,0,0,335,336,337,0,338,0,339,340,341,342,343,344,345,346,0,347,0,348,349,350,351,0, + 352,353,354,355,356,0,357,0,358,359,360,361,0,0,0,362,363,0,364,365,0,0,366,367,368,0,369,0,370,371,0,0, + 0,0,372,373,374,0,375,376,0,377,378,379,380,381,382,383,384,0,385,0,386,387,388,389,0,390,0,0,0,0,391,0, + 0,392,0,393,394,395,396,397,398,399,400,401,0,402,403,404,405,406,407,0,0,0,0,0,0,408,0,409,410,411,0,412, + 413,0,414,415,416,417,0,0,418,419,0,0,0,0,420,421,422,0,0,423,424,425,0,426,427,428,429,430,0,431,432,433, + 0,434,435,0,0,0,0,436,437,0,0,438,0,0,439,440,441,442,443,444,445,446,0,447,448,449,0,450,451,452,0,453, + 454,0,455,456,0,0,457,458,459,0,460,461,462,0,0,0,0,0,0,0,0,463,464,465,466,467,468,0,469,0,0,0, + 0,0,470,0,0,471,472,0,473,0,0,474,0,475,476,477,0,0,0,0,0,0,478,0,0,479,0,480,481,482,0,0, + 0,483,0,484,485,0,486,487,488,0,0,489,490,491,492,0,0,493,0,494,0,0,495,0,496,0,497,0,0,0,0,498, + 499,0,0,0,0,0,0,0,0,0,0,0,500,501,0,0,0,502,503,504,505,506,507,508,0,509,510,0,0,0,511,512, + 513,514,515,0,0,0,0,516,0,517,0,0,0,518,519,520,0,0,0,521,0,0,0,0,522,0,0,523,0,0,0,0, + 0,0,524,0,0,0,0,525,0,0,0,526,0,527,0,528,529,0,0,530,531,532,533,534,535,536,537,0,538,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,539,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,540,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,541,542,0,0,0,543,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,0,544,0,545,0, + 0,0,0,0,0,546,0,0,0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,548,549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,551,0,0,552,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,553,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,554,555,556,0,0,0,0,0,0,557,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 558,0,0,0,0,0,559,0,0,0,0,0,0,0,0,0,0,560,0,0,0,0,0,0,0,0,0,561,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,562,0,0,0,0,0,0,0,0,0,0,0,0,0,563,0,564,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,565,0,0,0,0,0,0,0,0,0,566,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,567,0,0,0,0,0,0,568,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,569,0,0,0,0,0,0,0,0,0,0,0,0,570,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,571,0,0,0,0,0,0,0,0,0, + 0,0,572,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,573,0,0,0,0,0,0,574, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 575,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,576,0,0,0,0,577,0,578,0,579,0, + 0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,581,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,582,0,0,0,0,0,0,0,0,0,0,0,0,0,0,583,0,0,584,0,0,0,0,0,0,0,0, + 0,0,0,0,0,585,0,0,586,0,0,0,0,0,0,0,0,0,0,0,0,0,587,0,0,0,588,0,589,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,590,0,0,0,591,0,0,0,0,0,592,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,593,0,0,0,0,0,0,0,0,594,0,0,0,0,0,0, + 595,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,596,0,0,597,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,598,0,0, + 0,0,599,0,0,0,0,600,601,602,0,0,0,0,0,0,0,0,603,0,0,0,0,0,0,0,0,0,0,0,0,0, + 604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,605,0,0,606,0,607,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,608,0,0,0,0,0,0,0,0,0,609,0,0,0,0,0,0,0,610,0,0, + 0,0,0,0,611,0,612,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,613,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,614,0,0,615,616,0,0,0,617,0,0,618,0,0,0,0,0,0, + 0,0,0,0,0,0,619,0,0,620,0,0,0,621,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,622,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,623,0,0,0,0,0,0, + 0,624,0,0,0,0,625,0,0,0,0,626,0,0,0,0,0,0,0,0,0,0,0,0,0,627,0,0,0,628,0,0, + 0,0,0,0,0,0,629,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,630,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,632,0,0,0,0,0,633,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,634,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,635,0,0,636,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,637,638,0,0,0,0,0,0,0,0,0,639,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,640, + 0,0,0,0,0,0,0,0,0,0,0,641,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,642,0,0,0,643,0,644,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 645,0,0,0,646,0,0,0,0,0,0,0,0,647,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,648,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,649,0,650,0,0,0,0,0,0,0,651,0,0,0,652,0,0,0,0,0,0,0,653,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,654,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static kbts_u32 kbts__UnicodeParentInfo_Data[20960] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66400,66423,66421,66422,0, + 0,1048664,197177,328094,393598,1114167,66418,459018,459046,983176,65810,393556,393562,197183,590017,1048696,131720,0,524539,459032,459067,1245203,131728,393604,131730,590026,393592,0,0,0,0,0, + 66420,1048648,197171,328084,393586,1114150,66417,459011,524515,917655,131704,328109,393538,197180,590008,1048680,131414,0,524499,459025,524523,1245184,131724,459060,131726,655525,393580,0,0,0,0,0, + 0,0,0,0,0,0,0,0,197174,0,0,0,0,0,0,0,0,0,0,0,66419,0,0,66399,0,0,0,0,0,0,0,0, + 0,0,262650,0,66396,131722,131706,65959,0,0,262654,0,0,0,0,66416,0,0,0,0,262658,197168,66398,0,66397,0,0,0,262626,0,0,0, + 0,0,262638,0,66019,66395,131702,66415,0,0,262642,0,0,0,0,65963,0,0,0,0,262646,197165,66186,0,65816,0,0,0,262622,0,0,0, + 0,0,262634,262634,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131716,131716,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,131718,131718,0,0,0,0,0,0,0,0,0,0,0,0,66412,66412,0,0,0,0, + 66183,66183,0,0,0,0,0,0,66413,66413,66413,66413,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66414, + 328104,328104,0,0,0,0,0,0,0,0,0,0,0,0,0,328099,328099,0,0,0,0,0,0,66381,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66367,66367,66405,66405,0,0,0,0,65936,65936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66366,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66393,0,0,0,0,0,0, + 65973,65973,0,0,0,0,0,0,66384,0,0,0,0,0,0,0,0,0,0,66379,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66409,65949,0,65829,66406,65873,0,66411,0,66408,66410,65867,459053,0,0,0,262618,0,328089,0,459039,0,0,0,0,0,262610, + 0,66407,0,0,0,393544,0,0,0,393550,0,0,131708,66403,131710,66404,65948,524531,0,0,0,262606,0,393568,0,589999,0,0,0,0,0,262630, + 0,131714,0,0,0,524507,0,0,0,393574,197129,197132,66401,66402,131712,0,0,0,131471,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,65935,0,0,0,0,0,0,0,0,0,131227,0,0,66371,0,197150,131700,65953,262594,0,65945,0,0,0,66394,0, + 0,0,0,262586,0,0,0,65595,0,0,0,65595,0,65630,0,0,131696,0,0,66376,0,197162,131698,65943,262602,0,66377,0,0,0,66392,0, + 0,0,0,262614,0,0,0,65578,0,0,0,65578,0,65614,0,0,0,0,0,0,0,0,65935,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,65936,65936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197216,131836,66134,66134,66134,131828,66134,0,66134,131820,66134,131826,66134,0,66134,0, + 66134,66134,0,66134,131822,0,66134,66134,66134,197204,66134,0,0,0,0,0,0,0,66855,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,197135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66370,0,66370,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,0,65978,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66387,66387,66387,0,0,0,0,66385,0,0,0, + 0,66383,66383,0,0,0,0,0,65935,0,0,66380,0,0,0,66379,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66379,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,131474,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66387,66387,0,0,0,0,66385,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66380,0,0,0,0,0,0,65935,0,0,0,0,0,65931,0,0,0,0,0,0,0, + 0,66383,66383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,197147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,131507,65934,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,65936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935, + 0,0,0,0,0,0,197138,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197141,0,0,65935,0,0,0, + 66378,0,65935,0,0,0,0,0,0,0,0,0,65935,0,0,0,0,65935,0,0,0,0,65935,0,0,0,0,65935,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197153,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66378,0,65935,0,0,0,0,0,0,0,0,0,65935,0,0,0, + 0,65935,0,0,0,0,65935,0,0,0,0,65935,0,0,0,0,0,0,66368,66369,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,328074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,65935,0,65935,0,65935,0,65935,0,65935,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,65935,0,65936,65936, + 0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,0,0, + 0,0,65755,65755,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 131694,131694,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66087,66087,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66158,66158,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 262598,262598,65609,65609,65609,65609,65609,65609,262598,262598,65609,65609,65609,65609,65609,65609,131506,131506,0,0,0,0,0,0,131506,131506,0,0,0,0,0,0, + 262590,262590,65985,65985,65985,65985,65985,65985,262590,262590,65985,65985,65985,65985,65985,65985,197042,197042,0,0,0,0,0,0,197042,197042,0,0,0,0,0,0, + 131506,131506,0,0,0,0,0,0,131506,131506,0,0,0,0,0,0,197042,197042,0,0,0,0,0,0,0,197042,0,0,0,0,0,0, + 262578,262578,65973,65973,65973,65973,65973,65973,262578,262578,65973,65973,65973,65973,65973,65973,66386,0,0,0,66388,0,0,0,0,0,0,0,66391,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,0,0,0,0,0,0,0,197159, + 0,0,0,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,0,0,0,0,0,0,197126,0, + 0,0,65931,65931,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66374,0,66373,0,66375,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65930,0,65930,0,66372,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,65935,0,0,0,0,65935,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,65935,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65894,0,0,0, + 0,0,0,65935,0,65936,0,0,65935,0,0,0,0,66376,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,65935,0,0,66158,66158,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,0,0,65936,65936,0,0,65755,65755,66390,66390,0,0, + 0,0,65936,65936,0,0,65936,65936,0,0,0,0,0,0,0,0,0,66389,66389,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66374,0,0,0,0,0,65894,65894,0,65934,0,0,0,0,0,0,66382,66382,66382,66382,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65932,0,0, + 0,0,0,0,0,0,0,0,66365,66365,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66388,0,0,0,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935,0,65935, + 0,65935,0,0,65935,0,65935,0,65935,0,0,0,0,0,0,131471,0,0,131471,0,0,131471,0,0,131471,0,0,131471,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65756,65756,65756,65756,0,0,0,0,0,0,0,0,0,0,65935,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67213,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67212,0,67214,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67211, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67210,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67209,0,0,0,0,0,0,0,0,0,0,0,0,0,67208,0,0,0, + 0,67207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67206,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67204,0,0,0, + 0,0,0,0,0,0,0,67203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,67202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67201,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67200,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67199,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,67198,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,67197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,67196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67195,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,67194,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131892,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67193,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67191,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67190,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,67189,0,0,0,0,0,0,0,0,0,0,0,131890,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67188,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67187,0,0,0, + 0,0,0,0,0,0,0,0,67186,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66821,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131888,0,0,0,0,0,0, + 0,0,0,0,0,0,67185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67184,0,0,0,0,0,0,0,0,0, + 0,0,0,67183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67182,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67181,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,67180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 67179,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,67178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67177,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67176,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67175,0,0,0,67172,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67173,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67170,0,0, + 0,67169,0,0,0,0,0,0,0,0,0,67168,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67167,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67166,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67165,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67164,0, + 0,0,0,0,0,0,0,67163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67162,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,67161,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67160,0,0,0,0,0,0,0,67159,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67158,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67157,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,67154,0,0,0,0,0,0,0,0,0,0,67153,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67152,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66809,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66810,0,0,0,0,0,0,0,0,0,0,0,66804,0,0,0,0,0,67151,66806,0,0,0,67150,0,0, + 0,67149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66801,0,0,0,66807,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66803,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66808,0,0,0,0,0,0,0,0,0,0,0,67148,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 67147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66805,0,0,0,0,0,66798,0,0,0,0,66800,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,131886,0,0,0,0,0,0,0,0,0,0,0,0,67146,0,0,0,66797, + 0,0,67145,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66799,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67144,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67143,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67140,0,0,0,0,0,0,0,0,0,0,66790,0,0,0,0,0, + 0,0,0,0,0,0,0,131882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66789,0,0,0,0,66794,0,0,0,0,0,0,0,131878,0,0,0,0,0,0,67138,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,67136,0,0,67137,66793,66782,0,0,0,66788,0,0,0,0,0,0,0,0,0,67135,0,0,0,0,0,0,0,0, + 66791,0,0,0,0,0,0,0,0,0,0,0,0,67134,0,0,0,0,67142,0,0,67141,0,67133,0,0,0,0,0,0,0,0, + 0,0,0,0,67132,0,0,0,0,0,0,0,67131,0,0,0,0,0,0,0,0,131876,0,66775,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66779,0,0,66778,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66776,0,66785,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67130,0,0,0,0,0,0,0,0,0,0, + 0,0,0,67129,0,0,0,131874,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66777,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66781,67128,0,0,0,0, + 0,0,0,0,0,0,67127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67126,0,0,0,0,67125,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66774,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66772,0,0,0,0, + 0,0,0,66773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67139,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,131872,0,131870,0,0,0,0,0,0,0,0,66769,0,0,0,0,0,0,0,0,0,0,0,66768,0, + 0,0,0,0,131866,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66770,0,0,0,0,131864,0,0,0,0,0, + 0,0,0,0,0,67124,67124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131862,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66771, + 0,0,0,0,0,0,0,0,0,67123,0,0,0,0,0,0,0,131860,0,0,0,0,0,0,0,0,67122,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67121,0,66764,0,0,0,0,0,0,0,66154,0,197225, + 0,0,0,66765,0,0,0,0,0,0,67120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67119, + 0,0,0,0,0,66760,0,0,0,0,0,67118,0,0,0,0,0,67117,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,67116,0,0,0,0,0,0,0,0,66766,0,0,0,0,0,0,0,0,0,0,0,0,0,66767,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67115,0,0,0,0,0,0,0, + 0,0,66763,0,0,0,0,0,67114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,67113,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67112,0, + 0,0,67112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66318,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67111,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67109,0,66761,0,0,0,0,0,0,0,0,0,0, + 0,0,0,67108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,131884,0,0,66757,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131854,0,0,0,131800,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67107,0,0,0,0,0,0,0,67106,0,0,0,0,0,0,0,0,0,0,0,0, + 66759,0,67105,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66264,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,131852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67104,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66758,0,0,0,0,0,0,0,0,0,0,0,67103,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66754,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67101,67102,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67099,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67098,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,67097,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67096,67095,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66752,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131798,0,0,0,66747,0, + 0,0,0,0,0,0,0,0,66750,0,0,0,67094,0,0,0,0,0,0,66751,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66746,0,0,0,0,0,0,66745, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67091,0,0,0,67093,0,0,0,0,67092,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,67090,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67089,0,0,0,0,0, + 0,0,67088,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66749,0,0,0,66741,0,0,0,0,0,0,0,0,66740,0,0,66748,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67087,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66743,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67085,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,67084,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67083,0,0,0,0, + 0,0,0,0,0,0,0,67082,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66744,0,0,0,67081,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67086,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,67080,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131880,0, + 0,0,0,0,0,66738,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,67079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67078,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,197222,0,0,0,0,0,0,66314,0,0,0,0,67077,0,0,0,0,0,0,0,0,0,0,0,67076, + 0,0,0,0,0,0,67075,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66735, + 67072,0,66733,0,66737,66734,0,0,0,0,0,0,0,0,131850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,67071,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 67070,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66731,0,0,0,0,0,0, + 0,0,0,67069,0,0,0,0,0,0,0,0,0,0,0,0,66729,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,67068,0,0,67067,0,0,0,0,0,0,0,0,0,0,0,0,0,67066,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67073,0,0,0,0,0,0,0,66730,0,0,0,0,0, + 0,67065,67065,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67064,0,0, + 0,0,0,0,0,0,0,0,67063,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67062,0,0, + 0,0,0,0,0,0,0,0,0,67061,0,0,0,0,0,0,0,0,0,0,66723,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66726,0,0,0,0,0,0,0,0,0,67060,0,0,67059,0,0,67058,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66722,131848,0,0,0,0,0,0,0,66728,66725,0,0,0,0,0,66727,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66720,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67057,0, + 0,0,0,0,66718,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,131868,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67054,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67056,0,0,0,0,0,0,66724,0,67055,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66719,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67053,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66715,0,0,0,66721,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,67052,0,0,0,0,0,0,0,0,0,67051,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66714,0,0,0,67050,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66711,0,0,0,0,0,0,0,0,0,66713,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66717,0,0,0,0,0,0,0,0,0,0, + 0,67049,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131846,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,67048,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66714,0,0,0,0,0,0,0, + 0,66709,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66712,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66707,0,0,0,67047,0,0,0,131858,0,131844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66710,0,0,0,0,0,0,0,66708,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67046,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,197219,0,66705,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,67045,0,0,0,0,0,0,0,0,0,0,67044,0,0,67043,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67042,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197213,0,0,0,131842,0,0,0,0,0,0,0,0,0, + 66703,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67041,0,0,0,0,0,0,0,0,0,0,67040,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66704,0,0,0,0,0,66706,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67039,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67038,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66693,0,0,0,0,0,66696,0,0,0,66701,67037,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67036,0,66695,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67035,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67034,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,67033,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66690,0,0,0,0, + 0,0,0,67032,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66689,0,0,0,0,0,0,0,0,67031,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66699,67030,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,67029,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66694,0,0,0, + 0,0,67028,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66692,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,67027,0,0,0,0,0,0,0,0,0,0,0,0,0,67026,0,0,0,0,0,0,67025,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66687,0,0,67024,0,0, + 0,0,0,0,66685,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131840,0,0,0,0,0,0,66688,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,67023,0,0,0,0,0,0,0,0,0,0,0,66681,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66682,0,0,0,0,0,0, + 0,0,0,0,0,66678,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66684,67022,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66679,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,67021,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131790,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66675,0,0,0,0,0,0,0,0,131834,0,0,0,0,0,0,0,0,0,0,67020,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66677,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66674,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66670,0,0,0,67019,0,0,0,0,0,0,0, + 67019,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197210,0,0,0,131832,0,0,0,0, + 0,67018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66673,0,0,0,0,67017,0,0,66676,0,0,0,0,0,0,0,67016,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66671,0,0,0,0, + 0,0,0,0,0,67015,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66672,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66668,0,0,0,0,0,0,67014,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66666,0,0,0,0,0,0,0,67013, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67012,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66664,0,0,0,131830,0,0,0,0,0,0,0,0,67011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67010,0,0,0,0,0,0,0,0,0,0,0, + 0,0,67009,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,67008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,67007,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,197201,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66663,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,67006,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66661,0,0,0,0,0,0,0,67005,0,0,0,0, + 0,0,0,0,66659,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,67004,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67003,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67002,0,0,0,0,66658,0,66662,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67001, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66657,0,0,0,0,0,0,0,0,0,0,0,197198,66128,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,67000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66999,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66654,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66998, + 0,0,0,0,0,0,0,0,0,0,0,0,66651,66997,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66655,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66996,0,0,0,0,66647,0,0,66653,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66995,0,0,0,0,0,0,0,0,0,66994,0, + 0,197195,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66993,66645,0,0,0,0,0,0,0,0,0,0,0,0,131824,66992,0,0,0,0,0,0,0, + 0,0,0,0,0,66991,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66648,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66643,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66646,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66990,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66649,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66989,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66988,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66641,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66642,0,0,0,0,0, + 0,0,0,0,0,0,0,66987,0,0,0,131818,0,0,0,0,0,66637,0,0,0,0,0,0,0,0,0,66644,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66638,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,131788,66639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66986,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66985,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66633,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66635,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66984,0,0,131816,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66983,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66982,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66977,0,0,0,0,0,0,66981,0,0,0,0,0,66980,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66634,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66979,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66631,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66629,0,0,0,0,0,0, + 0,0,0,0,0,66978,0,0,0,66630,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,131780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66976,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66627,0,66628,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66624,0,0,0,0,0,0,0,0,0,0,66623,0,0,0,0, + 0,0,0,0,0,0,0,0,66975,0,0,66628,0,0,0,0,0,0,0,0,0,131814,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66974,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66622,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66973,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66972,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66626,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66625,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66620,0,0,0, + 0,0,0,0,0,0,0,0,0,0,131774,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66621,0,0,0,0,66971,0,0,0,0,0, + 0,0,0,0,0,0,0,131772,0,0,0,66970,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66969,0,0,0,0,0,0,0,0,0,0,0,0,66618,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66610,0, + 0,0,0,0,0,0,66616,0,0,66615,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66967,0,0,0, + 0,0,0,0,0,0,0,0,0,66611,0,0,0,0,0,0,0,131812,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66966,0,0,0,66609,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66612,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66965,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66614,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66964,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66613,0,0,66963,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66606,0,0,0,0,0,0, + 0,0,0,0,0,66605,0,0,0,0,0,0,0,0,0,0,131810,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66962,0,0,0,0,0,0,0,0,0,0,0,0,66608,0,66607, + 0,0,66602,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66598,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,131766,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66603,0,0,0,0, + 0,0,0,0,0,0,0,66596,0,0,0,0,0,0,0,0,0,0,0,0,131808,0,0,0,0,0,0,0,0,0,0,0, + 0,66597,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66320,131856, + 66601,0,0,0,0,0,0,0,0,0,131806,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66961,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66960,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66594,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,131792,0,0,0,0,66595,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66583,0,131802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66582,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66587,0,66592,0, + 0,0,0,0,0,0,0,0,66591,66590,0,0,0,0,0,0,66589,0,0,0,0,0,131794,0,0,0,0,0,0,66588,66585,0, + 0,0,0,0,0,66584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66575, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66586,66586,131786,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66579,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66576,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66959,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66574,0,0,0, + 131784,0,0,0,0,0,0,0,0,0,66958,0,0,0,0,66957,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66577,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66578,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66573,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66956,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66572,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 131760,0,0,0,0,0,66955,0,0,66954,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66570,0, + 66564,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66571,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66569,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66568,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66953,0,0,0,66566,0,0,0,0,0,0,0,0,0, + 0,0,0,66952,0,0,0,66562,66951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66563,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66560,0,0,0,0,0,0,0,0,0,0,0,0,66559,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66567,0,0,0,0, + 0,0,0,66949,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66557,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66556,0, + 0,0,0,0,0,0,0,66948,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197192,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66947,0,0,0,0,0,0,66561,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66554,0,0,0,0,0,0,0,0, + 0,66558,0,0,0,66946,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66555,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66553,0,0,0,0,0,0,66551,66945,0,0,0,0,0, + 0,0,0,0,0,66548,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66944,0,0,0,0,66549,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66550,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66943,0,0,0,0,0, + 0,66546,0,0,0,197189,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66942,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66545,66941,0,0,0,0,0,0,0,0,0,0,0,0,0,66543,0, + 0,0,0,0,0,0,0,0,0,0,0,66544,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66937,0,0,0,0,66940,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66939,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66938,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66538,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66540,0,0,0,0,66542,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,131838,0,0,66936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66541,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66537,0,0,0,0,0,0,0,0,0,131756,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66935,0,0,0,0,0,66934,0,0,0,0,0,0,0,0,0,0,0,66933,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66932,0,66931,0,0,0,0,0,0,0,0,0,66930,0,0, + 0,0,0,0,0,131782,66929,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66928,0,0, + 0,0,0,66927,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66536,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66539,66926,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66925,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66924,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66923,0,0, + 0,0,0,0,0,0,0,0,0,66534,66922,0,66921,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66920,0,0,0, + 0,0,0,0,0,0,0,66919,0,0,0,0,0,0,0,66535,0,66533,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66531,0,0, + 0,0,0,0,0,0,0,0,0,66532,0,0,0,0,0,0,0,0,0,0,0,0,0,131778,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66529,0,0,66918,0,66917,0,0,0,0,0,0,0,0,66530,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66916,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66915,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66527,0,0,0,0,0, + 0,0,0,0,0,0,66524,0,0,0,0,0,0,0,0,0,0,0,66528,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66523,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66522, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66914,0,0,0,0,0,0,0,0,0,0,0,131776,0,0,0, + 0,0,0,0,0,0,0,66913,0,66912,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66911,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66909,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66908,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66907,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66906,0,0,0,0,0,0,0,0,0,0,0,0,0,131770,0,0,0,0,0,0, + 0,0,0,0,0,0,66905,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66518,0,0,0,0,0, + 0,66904,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66903,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66514, + 0,0,0,0,0,0,0,0,0,0,0,0,66520,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66902,0,0,66901,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66512,0,0,0,0,0,0,0,0,0,0,0,0,66515,0,0,0,0,0,0,0,66900,0,0,0,0,0,0,66899,0, + 0,66513,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66510,0,66898,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66517,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66519,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66507,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66516,0,0,0,0,66511,0,0,0,0,0,0,0,0,0,0,131754,0,0,0,0,0,0,0,0,0, + 66897,0,0,0,0,0,0,0,0,0,131746,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66509, + 0,0,0,0,0,0,0,0,0,0,0,66508,0,0,0,0,0,0,66506,0,0,0,66504,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,131768,0,0,0,0,0,0,0,0,0,0,131750,0,0,0,0,0,131744,0, + 0,131752,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131748,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66505,0,0,0,0,0,0,0, + 66502,0,0,0,0,0,0,0,0,0,131764,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66500,0,0,0,0,0,0,0,0,0,0,0,0,66896,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66895,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66894,66499,0,0,0,0,0,66497,0,0,0,0,0,0,0,0,0,0,66501,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,131742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66893,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66892,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66891,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66890,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66496,66889,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66490,0,0,0,0,0,0,0,0,0,66888,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66492,0,0,0,66493,0,0,0,0,0,0,0,0,0,0,0,0,0,131762,0,0,66495,0,0,0,0, + 0,0,66489,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66887,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66488,0,0,0,0,0,66494,0,0,0,0,0,0,0,0,0, + 0,0,0,66487,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131740,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66491,0,0,0,0,0,0,0,0,0,66485,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66481,0,0,0,0,66886,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66486,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66885,0,0,0,0,0,0,0,0,0,0,0,66483,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66884,0,0,0,0,0,0,0,0,0,66883,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66475,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66484,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66477,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66478,0,0,66475,0,66473,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66474,0,0,0,66882,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66479,0,0,0,0,0,66881,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66880,66880,0,0,0,0,0,0,0, + 0,0,0,0,66470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66879,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66878,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66877,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66465,0,0,0,0,0,0,0,0,0,66876,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66463,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66457,0,66464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66454,0,0,66461,0,0,0,66466,0,0,0, + 0,0,0,0,0,0,66460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66459,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66462,66456,0,0,0,0,0,0,0, + 0,0,0,66875,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66458,131738,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66453,66451,0,0,0,0,0,0,0,0, + 0,0,0,66874,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66450,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66452,0,0,0,0,0,0,0,0,0,0,0,0,0,131736,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66455,0,0,0,0, + 66873,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131734, + 0,0,0,0,0,0,0,0,0,0,0,197207,0,0,0,0,0,0,0,0,0,0,0,0,66449,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66872,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131732,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66448,0, + 0,0,66871,0,0,0,0,0,0,0,0,0,0,0,0,66447,0,0,0,0,0,0,0,0,0,0,0,0,66446,0,0,0, + 0,0,0,0,0,0,0,0,66445,66870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66869,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,66868,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66444,0,0,0,0,0,0,0,0,0,0,0,0,66867,0, + 0,0,0,0,0,0,0,0,0,0,66443,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131758,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66441,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66866,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66440,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66865,0,0, + 0,0,0,0,0,0,0,66864,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66439,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66435,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66434,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66432, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66433,0,0,0,0,0,0,0,66437, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66863,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66431,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66862,0,0,0,0,66861,0, + 0,0,0,0,0,66860,0,0,0,0,0,0,0,0,0,66859,0,0,0,0,0,0,66858,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66857,0,0,0,0, + 0,0,0,66438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66430,66436,0,0,0,0,0,0,0,0,0,0,0,0,0,197186,0,0,0, + 0,0,0,0,0,0,0,0,0,131692,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65888,0,0,0,0,0,0,0,66374,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65935,0,65935,0,0,0,0, + 0,0,0,0,0,65755,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65930,65930,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,65935,0,65935,0,0,0,0,0,0,65933,0,0,0,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,197156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197144,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65933,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,262582,0, + 0,131512,65894,0,0,0,0,0,0,65779,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,65755,0,0,0,65935,0,65935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65977,65977,0,0,0,0,0,0,328079, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65936,65936,131506,131506,0,0,0, + 0,0,66856,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66853,0,0,0, + 0,0,0,0,0,66854,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66850,0,0,0,0,0, + 0,0,0,0,66851,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66849,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66848,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66846,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66845,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66842,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66840,0,66840,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66838,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66839, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,131804,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66837,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,66364,0,0,0,0,0,66363,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66836,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66835,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66834,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66830,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66833, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66832,0,0,0,0,0,0,0,0,66831,0,0,0, + 0,0,0,66829,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66362,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66828,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66827,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66826,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66825,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66824,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66823,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66822,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66820,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66819,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66818,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,66817,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66361,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66815,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66814,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66813,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66812,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66811,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,66796,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66795,0,0,0,0,0,0,0, + 0,0,0,0,66792,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66787,66786,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66784,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66783,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,66360,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66762,0,0, + 0,0,0,0,0,0,66756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66755,0,0,0,0,0, + 0,0,0,0,0,66753,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66742,0,0,0, + 0,0,0,0,0,0,0,131796,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66736,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66732,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66359,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66716,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66698,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66702,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66700,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66697,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66691,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66686,0,0,0,0,0, + 0,0,0,66683,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66669,0,0,0,0,0,0,0,0,0,0,0,0,0,66667,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66660,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66656,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66652,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,66650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,66640,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66636,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66632,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66617,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,66600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66593,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,66581,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,66565,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66358,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66552,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66528,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,66526,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66521,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66503,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66498,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66482,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66471, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66476,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,66469,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66468,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66467,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66442,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66429,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,66428,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,66427,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66426,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66425,0,0,0,0,0,0,0,0,0,0,0,0,0, + 66424,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u32 kbts__GetUnicodeParentInfo(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeParentInfo_Data[((kbts_un)kbts__UnicodeParentInfo_PageIndices[Codepoint/32] * 32) | (Codepoint & 31)] : 0; +} + +static kbts_u8 kbts__UnicodeUseClass_PageIndices[4351] = { + 0,1,1,1,1,1,2,3,4,5,6,7,8,9,10,11,12,1,1,1,1,1,1,13,14,15,16,17,18,19,1,1, + 20,1,1,1,1,21,1,22,1,1,1,1,1,23,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,25,26,27,28,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,29,1,1,1,1,30,31,1,32,33,34,35,36,37,38,39,40,41,42,43,44,45,1,46,47,48,49, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,50,50,50,50,51,50,50,50,50,50,50,50,50,50,50,50, + 50,50,50,52,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,53,1,1,1,1,1,1,1,1,54,55,1,56,1,57,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,58,59,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,60,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,61,62,1,63,64,1,1,1,65,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +static kbts_u8 kbts__UnicodeUseClass_Data[16896] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,21,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,29,29,29,29,29,29,29,29,0,0,0,0,0,0,1,0,0,29,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,0,0,0,0,1,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,29,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,36,9,1,36,33, + 36,35,35,35,35,34,34,34,34,36,36,36,36,3,33,36,0,29,30,0,0,34,35,35,1,1,1,1,1,1,1,1,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,29,31,31,0,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,1,0,0,9,1,36,33, + 36,35,35,35,35,0,0,33,33,0,0,33,33,3,0,0,0,0,0,0,0,0,0,36,0,0,0,0,1,1,0,1,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,6,0, + 0,29,29,31,0,1,1,1,1,1,1,0,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,0,0,9,0,36,33, + 36,35,35,0,0,0,0,34,34,0,0,34,34,3,0,0,0,30,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,29,8,2,2,0,12,0,0,0,0,0,0,0,0,0,0, + 0,29,29,31,0,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,0,9,1,36,33, + 36,35,35,35,35,34,0,34,34,34,0,36,36,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,29,8,29,8,8,8, + 0,29,31,31,0,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,0,9,1,36,34, + 36,35,35,35,35,0,0,33,33,0,0,33,33,3,0,0,0,0,0,0,0,34,34,34,0,0,0,0,1,1,0,1,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,29,0,0,1,1,1,1,1,1,0,0,0,1,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,36,36, + 34,36,36,0,0,0,33,33,33,0,33,33,33,3,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,31,31,31,29,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,9,1,34,34, + 34,36,36,36,36,0,34,34,34,0,34,34,34,3,0,0,0,0,0,0,0,34,35,0,1,1,1,0,0,0,0,0,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,29,31,31,0,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,9,1,36,34, + 34,36,36,36,36,0,34,34,34,0,34,34,34,3,0,0,0,0,0,0,0,36,36,0,0,0,0,0,0,0,1,0,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,37,37,31,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,31,31,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,1,36,36, + 36,35,35,35,35,0,33,33,33,0,33,33,33,3,38,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,1,1,1,35,35,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,29,31,31,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,0,0, + 1,1,1,1,1,1,1,0,0,0,4,0,0,0,0,36,36,36,34,34,35,0,35,0,36,33,33,33,33,33,33,36,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,36,36,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,34,1,1,34,34,34,34,35,35,35,0,0,0,0,0, + 1,1,1,1,1,1,0,34,29,29,29,29,8,29,34,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,0,1,34,1,1,34,34,34,34,35,35,35,34,12,1,0,0, + 1,1,1,1,1,0,0,0,29,29,29,29,0,29,6,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,6,0,6,0,8,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,9,35,34,34,35,34,34,34,34,35,35,35,35,29,0, + 35,34,29,29,35,0,29,29,1,1,1,1,1,7,7,7,7,7,7,7,7,7,7,7,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0, + 0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,34,34,35,35,33,34,34,34,34,29,30,31,6,34,13,10,12,12,1, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,36,36,35,35,1,1,1,1,12,12,12,1,36,31,31,1,1,36,36,31,31,31,31,31,1,1,1,34,34,34,34,1,1,1,1,1,1,1,1,1,1,1, + 1,1,12,36,33,34,34,31,31,31,31,31,31,30,1,31,1,1,1,1,1,1,1,1,1,1,31,31,36,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,35,35,36,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,35,36,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,35,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,34,35,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,36,34,34,34,34,35,35,35,33,33, + 33,33,33,33,33,33,29,31,36,29,29,6,14,8,6,29,6,34,6,6,0,0,0,0,0,0,0,0,1,6,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, + 2,2,2,2,2,8,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,34,34,35,36,36,34,34,34,34,7,7,7,0,0,0,0,16,16,30,16,16,16,16,16,16,15,29,6,0,0,0,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,31,31,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,33,36,34,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,10,12,7,14,14,11,7,7,7,7,0,5,36,34,36,36,34,34,34,34,35,35,34,35,36,33,33,33,33,33,34,29,29,29,29,29,29,34,29,29,0,0,30, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,29,14,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,36,34,34,35,35,35,35,34,34,33,33, + 33,33,34,34,3,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,14,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,7,7,34,35,33,36,34,34,36,6,7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,36,34,34,36,36,36,34,36,34,14,14,17,17,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,7,36,33,33,33,36,36,35,14,14,14,14,14,14,14,32,32,0,9,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,29,29,0,30,30,30,30,30,30,29,29,30,30,30,30,29,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,37,37,31,29,29,2,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,39,1,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0, + 0,0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,21,19,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,21,19,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,34,1,1,1,3,1,1,1,1,29,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,35,34,36,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + 31,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,13,36,36,36,36,36,36,36,36,36,36,36, + 36,36,36,36,3,29,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,1,1,0,0,0,0,0,0,0,0,0,0,1,34, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,34,34,34,30,30,30,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,35,35,35,34,35,35,35,35,14,14,14,16,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,14,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,36,36,34,34,35,35,33,33,34,12,13,12, + 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,34,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,34,34,34,35,34,33,33,34,35,13,10,11,12,0,0,0,0,0,0,0,0,0, + 1,1,1,14,1,1,1,1,1,1,1,1,14,16,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,2,2,2,0,0,0,1,31,29,31,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,35,1,35,35,34,1,1,35,35,1,1,1,1,1,35,29, + 1,29,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,33,35,34,33,36,0,0,0,0,0,31,6,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,34,36,36,35,36,36,0,31,35,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,35,35,35,0,34,35,0,0,0,0,0,36,30,30,29,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,9,9,9,0,0,0,0,6, + 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,29,29,8,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,34,34,34,34,34,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,34,34,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,30,30,30,30,30,30,30,30,30,30,30,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1, + 0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 31,29,31,37,37,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,34,34,35,35,35,35, + 35,35,34,34,34,34,3,0,0,0,0,0,0,0,0,0,0,0,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,1,1,1,1,1,1,1,1,1,1,34,1,1,34,34,1,0,0,0,0,0,0,0,0,0,40, + 29,29,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,34,34,36,36,3,9,0,0,0,0,0, + 0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,29,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,35,35,35,34,34,33,35,34,34,35,34,34,6,8,0,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,1,36,36,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,0,0,0,0,0,0,0,0,0,0,0,0, + 29,29,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,35,35,34,34,34,34, + 3,1,38,38,0,0,0,0,0,6,9,34,35,0,33,29,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,36,35,34,34,34,34,29,3,8,8,0,0,0,0,0,0,29,1, + 1,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,36,33,36,35,35,34,34,34,34,9,35,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 29,29,31,31,0,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,9,9,1,36,36, + 34,36,36,36,36,0,0,33,33,0,0,33,33,3,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,1,1,1,1,36,36,0,0,29,29,29,29,29,29,29,0,0,0,29,29,29,29,29,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,36,34,34,35,35,35,35,35, + 35,0,33,0,0,33,0,33,33,36,31,0,31,31,29,9,6,38,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,35,35,34,34, + 36,36,3,29,29,31,9,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,6,1,37,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,35,35,33,34,33,33,36,33,29, + 29,31,3,9,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,0,0,33,33,33,33,29,29,31,3, + 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,35,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,36,35,35,35,35,35,35,34,34,36,36,29,31,3, + 34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,31,34,33,36,35,35,34,34,34,34,3,9,1,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,12,3,11,36,36,34,34,35,35,33,34,35,34,34,34,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, + 1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,34,34,34,34,29,31,3,9,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,0,0,1,0,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,36,36,36,33,0,33,33,0,0,29,29,36,6,38, + 13,38,13,9,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,33,36,35,35,35,35,0,0,34,34,36,36,31,31,3,1,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,34,35,35,34,34,34,34,34,34,35,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,35,29,29,29,29,31,37,7,7,7,7,0, + 0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,1,34,35,35,34,34,34,36,36,35,35,35,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,38,38,38,38,38,38,15,15,15,15,15,15,15,15,15,15,15,15,29,31,8,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,34,34,35,35,35,35,35,0,34,34,34,34,29,29,31,3, + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,7,7,7,7,7,7,7,35,33,35,34,36,29,29,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,34,34,34,35,0,0,0,34,0,34,34,0,34, + 29,29,9,34,35,6,38,12,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,36,36,36,36,36,0,34,34,0,36,36,29,31,6,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,34,35,33,36,0,0,0,0,0,0,0,0,0, + 29,29,38,31,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,34,34,35,35,35,0,0,0,33,33, + 34,36,6,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,22,22,22,22,22,22,22,19,21,22,22,22,18,18,18,18, + 23,18,18,18,18,18,18,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0,0,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,34,34,34,34,34,34,34,34,34,34,10,10,13,29,12,35,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,29,29,29,29,29,29,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 31,31,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,36,36,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,9,0,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35, + 35,35,35,35,35,35,35,35,0,0,0,0,0,0,0,30,30,30,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0, + 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,29,29,29,29,29,29,29,1,1,1,1,1,1,1,0,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,29,29,29,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,34,34,34,34,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,35,35,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,8,8,8,8,8,8,8,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u8 kbts__GetUnicodeUseClass(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeUseClass_Data[((kbts_un)kbts__UnicodeUseClass_PageIndices[Codepoint/256] * 256) | (Codepoint & 255)] : 0; +} + +static kbts_u8 kbts__UnicodeScriptExtension_PageIndices[8703] = { + 0,1,2,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, + 30,31,32,32,33,34,35,36,37,37,37,37,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,2,2,53,54, + 55,56,57,58,59,59,59,59,60,59,59,59,59,59,59,59,61,61,59,59,59,59,62,63,64,65,66,67,68,61,61,69, + 70,71,72,73,74,75,76,77,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,78,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 79,79,79,79,79,79,79,79,79,80,81,81,82,83,84,85,86,87,88,89,90,91,92,93,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,94,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,95,96,97,97,98,99,100,101,102,103, + 104,105,106,107,61,108,109,110,111,112,113,114,115,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, + 134,135,136,137,138,139,140,141,142,143,61,144,145,146,147,61,148,149,150,151,152,153,154,155,156,157,158,159,61,160,161,162, + 163,163,163,163,163,163,163,164,165,163,166,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,167, + 168,168,168,168,168,168,168,168,169,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, + 168,168,168,168,168,168,168,170,171,171,171,171,172,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,173,61,61,61,61,61,61,61,61,61,61,61,61,61,174,174,174,174,175,176,177,178,61,61,179,61,180,181,182,183, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184, + 184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,185,184,184,184,184,184,184,186,186,186,187,188,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,189, + 190,191,192,193,193,194,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,195,196,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,59,197,59,59,59,198,199,200, + 59,201,202,203,204,205,206,61,207,208,209,59,59,210,59,211,212,212,212,212,212,213,61,61,61,61,61,61,61,61,214,61, + 215,216,217,61,61,218,61,61,61,219,61,220,61,61,61,221,222,223,224,61,61,61,61,61,225,226,227,61,228,229,61,61, + 230,231,59,232,233,61,59,59,59,59,59,59,59,234,235,236,237,238,59,59,239,240,59,241,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 242,61,243,244,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, +}; + +static kbts_u16 kbts__UnicodeScriptExtension_Data[31360] = { + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,929,929, + 929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,2305,929,929,929,929,929,929,929,929,929,929,929,929,16,929,929,2305,929,929,929,929,929, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,519,929,929,929, + 929,929,929,929,929,929,929,738,929,738,738,738,929,610,929,929,929,929,929,929,929,929,929,802,929,738,929,929,929,929,929,929, + 2305,2305,2305,2305,2305,929,929,929,929,929,417,417,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 872,1128,1380,1509,1675,2022,932,2217,2506,1442,2819,2916,3043,1538,3138,961,1538,3203,961,3300,961,961,961,961,961,961,961,961,961,961,961,961, + 2850,961,961,3429,3588,2850,961,961,961,961,961,961,961,1539,2850,961,3715,3814,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,1441,961,961,1441,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,1218,961,961,961,961,961,4003,961, + 961,961,961,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1441,1441,1441,1441,4098,4098,1441,1441,1,1,1441,1441,1441,1441,929,1441, + 1,1,1,1,1441,929,1441,929,1441,1441,1441,1,1441,1,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,801,801,801,801,801,801,801,801,801,801,801,801,801,801,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,4162,4226,1410,1410,4226,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,1,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, + 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,1,1,161,161,161,161,161,161,161, + 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161, + 161,161,161,161,161,161,161,161,161,4291,161,1,1,161,161,161,1,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729, + 1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729, + 1729,1729,1729,1729,1729,1729,1729,1729,1,1,1,1,1,1,1,1,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729, + 1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1,1,1,1,1729,1729,1729,1729,1729,1729,1,1,1,1,1,1,1,1,1,1,1, + 129,129,129,129,129,929,129,129,129,129,129,129,4391,129,129,129,129,129,129,129,129,129,129,129,129,129,129,4391,4611,129,129,4712, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 4969,129,129,129,129,129,129,129,129,129,129,4610,4610,4610,4610,4610,4610,4610,4610,4610,4610,4610,129,129,129,129,129,129,129,129,129,129, + 5251,5251,5251,5251,5251,5251,5251,5251,5251,5251,129,129,129,129,129,129,4610,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,4994,129,129,129,129,129,129,129,129,929,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,1,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577, + 4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577, + 4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,1,1,4577,4577,4577,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929, + 4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,4929,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297, + 3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,3297,1,1,3297,3297,3297, + 4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129, + 4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,1,1,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,4129,1, + 2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,2657,1,1,2657,1, + 4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,4577,1,1,1,1,1,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,129,129,1,1,1,1,1,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,929,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,5357,5772,961,961,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 1025,1025,1025,1025,6165,6839,7556,7556,7556,7556,7556,7556,7556,7556,7556,7556,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 353,353,353,353,1,353,353,353,353,353,353,353,353,1,1,353,353,1,1,353,353,353,353,353,353,353,353,353,353,353,353,353, + 353,353,353,353,353,353,353,353,353,1,353,353,353,353,353,353,353,1,353,1,1,1,353,353,353,353,1,1,353,353,353,353, + 353,353,353,353,353,1,1,353,353,1,1,353,353,353,353,1,1,1,1,1,1,1,1,353,1,1,1,1,353,353,1,353, + 353,353,353,353,1,1,7683,7683,7683,7683,7683,7683,7683,7683,7683,7683,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,1, + 1,1537,1537,1537,1,1537,1537,1537,1537,1537,1537,1,1,1,1,1537,1537,1,1,1537,1537,1537,1537,1537,1537,1537,1537,1537,1537,1537,1537,1537, + 1537,1537,1537,1537,1537,1537,1537,1537,1537,1,1537,1537,1537,1537,1537,1537,1537,1,1537,1537,1,1537,1537,1,1537,1537,1,1,1537,1,1537,1537, + 1537,1537,1537,1,1,1,1,1537,1537,1,1,1537,1537,1537,1,1,1,1537,1,1,1,1,1,1,1,1537,1537,1537,1537,1,1537,1, + 1,1,1,1,1,1,7778,7778,7778,7778,7778,7778,7778,7778,7778,7778,1537,1537,1537,1537,1537,1537,1537,1,1,1,1,1,1,1,1,1, + 1,1473,1473,1473,1,1473,1473,1473,1473,1473,1473,1473,1473,1473,1,1473,1473,1473,1,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473,1473, + 1473,1473,1473,1473,1473,1473,1473,1473,1473,1,1473,1473,1473,1473,1473,1473,1473,1,1473,1473,1,1473,1473,1473,1473,1473,1,1,1473,1473,1473,1473, + 1473,1473,1473,1473,1473,1473,1,1473,1473,1473,1,1473,1473,1473,1,1,1473,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1473,1473,1473,1473,1,1,7842,7842,7842,7842,7842,7842,7842,7842,7842,7842,1473,1473,1,1,1,1,1,1,1,1473,1473,1473,1473,1473,1473,1473, + 1,3777,3777,3777,1,3777,3777,3777,3777,3777,3777,3777,3777,1,1,3777,3777,1,1,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777, + 3777,3777,3777,3777,3777,3777,3777,3777,3777,1,3777,3777,3777,3777,3777,3777,3777,1,3777,3777,1,3777,3777,3777,3777,3777,1,1,3777,3777,3777,3777, + 3777,3777,3777,3777,3777,1,1,3777,3777,1,1,3777,3777,3777,1,1,1,1,1,1,1,3777,3777,3777,1,1,1,1,3777,3777,1,3777, + 3777,3777,3777,3777,1,1,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,3777,1,1,1,1,1,1,1,1, + 1,1,4801,4801,1,4801,4801,4801,4801,4801,4801,1,1,1,4801,4801,4801,1,4801,4801,4801,4801,1,1,1,4801,4801,1,4801,1,4801,4801, + 1,1,1,4801,4801,1,1,1,4801,4801,4801,1,1,1,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,1,1,1,1,4801,4801, + 4801,4801,4801,1,1,1,4801,4801,4801,1,4801,4801,4801,4801,1,1,4801,1,1,1,1,1,1,4801,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,7906,7906,7906,7906,7906,7906,7906,7906,7906,7906,7906,7906,7906,7906,4801,4801,4801,4801,4801,4801,4801,1,1,1,1,1, + 4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,1,4897,4897,4897,1,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897, + 4897,4897,4897,4897,4897,4897,4897,4897,4897,1,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,1,1,4897,4897,4897,4897, + 4897,4897,4897,4897,4897,1,4897,4897,4897,1,4897,4897,4897,4897,1,1,1,1,1,1,1,4897,4897,1,4897,4897,4897,1,1,4897,1,1, + 4897,4897,4897,4897,1,1,4897,4897,4897,4897,4897,4897,4897,4897,4897,4897,1,1,1,1,1,1,1,4897,4897,4897,4897,4897,4897,4897,4897,4897, + 1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1,1953,1953,1953,1,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953, + 1953,1953,1953,1953,1953,1953,1953,1953,1953,1,1953,1953,1953,1953,1953,1953,1953,1953,1953,1953,1,1953,1953,1953,1953,1953,1,1,1953,1953,1953,1953, + 1953,1953,1953,1953,1953,1,1953,1953,1953,1,1953,1953,1953,1953,1,1,1,1,1,1,1,1953,1953,1,1,1,1,1,1,1953,1953,1, + 1953,1953,1953,1953,1,1,7971,7971,7971,7971,7971,7971,7971,7971,7971,7971,1,1953,1953,1953,1,1,1,1,1,1,1,1,1,1,1,1, + 2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,1,2625,2625,2625,1,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625, + 2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625, + 2625,2625,2625,2625,2625,1,2625,2625,2625,1,2625,2625,2625,2625,2625,2625,1,1,1,1,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625, + 2625,2625,2625,2625,1,1,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625,2625, + 1,4353,4353,4353,1,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,1,1,1,4353,4353,4353,4353,4353,4353, + 4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,1,4353,4353,4353,4353,4353,4353,4353,4353,4353,1,4353,1,1, + 4353,4353,4353,4353,4353,4353,4353,1,1,1,4353,1,1,1,1,4353,4353,4353,4353,4353,4353,1,4353,1,4353,4353,4353,4353,4353,4353,4353,4353, + 1,1,1,1,1,1,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,1,1,4353,4353,4353,1,1,1,1,1,1,1,1,1,1,1, + 1,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961, + 4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,1,1,1,1,929, + 4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,4961,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2273,2273,1,2273,1,2273,2273,2273,2273,2273,1,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273, + 2273,2273,2273,2273,1,2273,1,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,1,1, + 2273,2273,2273,2273,2273,1,2273,1,2273,2273,2273,2273,2273,2273,2273,1,2273,2273,2273,2273,2273,2273,2273,2273,2273,2273,1,1,2273,2273,2273,2273, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,1,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,1,1,1,1,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,1,4993,4993,4993,4993,4993,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,1,4993,4993, + 4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,4993,1,4993,4993,4993,4993,4993,4993,4993,929,929,929,929,4993,4993,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 8067,8067,8067,8067,8067,8067,8067,8067,8067,8067,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, + 1313,1313,1313,1313,1313,1313,1,1313,1,1,1,1,1,1313,1,1,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, + 1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,8163,1313,1313,1313,1313, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1249,1,1249,1,1249,1249,1249,1249,1,1, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1249,1, + 1249,1,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1,1249,1249,1249, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1,1, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1,1,1,1,1, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,1,1,705,705,705,705,705,705,1,1, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,3393,1,1,1, + 4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097, + 4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097, + 4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,4097,1,1,1,1,1,1,1, + 4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,4609,1,1,1,1,1,1,1,1,1,4609, + 1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,1665,8260,8260,1,1,1,1,1,1,1,1,1, + 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,1,1,1,1,1,1,1,1,1,1,1,1, + 4641,4641,4641,4641,4641,4641,4641,4641,4641,4641,4641,4641,4641,1,4641,4641,4641,1,4641,4641,1,1,1,1,1,1,1,1,1,1,1,1, + 2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145, + 2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145, + 2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,1,1, + 2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,1,1,1,1,1,1,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,1,1,1,1,1,1, + 3009,3009,8386,8386,3009,8386,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,1,1,1,1,1,1, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,1,1,1,1,1,1,1, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,1,1,1,1,1,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,1,1,1,1,1,1,1,1,1,1, + 2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,1, + 2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,1,1,1,1,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,1,1,1,1, + 2369,1,1,1,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,2369,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673, + 4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,4673,1,1,4673,4673,4673,4673,4673,1,1,1,1,1,1,1,1,1,1,1, + 3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265, + 3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,1,1,1,1,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265, + 3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,1,1,1,1,1,1,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,3265,1,1,1,3265,3265, + 2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145,2145, + 481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,1,1,481,481, + 4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705, + 4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,1, + 4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,1,1,4705, + 4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,1,1,1,1,1,1,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,1,1,1,1,1,1, + 4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,4705,1,1,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, + 225,225,225,225,225,225,225,225,225,225,225,225,225,1,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, + 4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481, + 4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481,4481, + 321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321, + 321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,1,1,1,1,1,1,1,1,321,321,321,321, + 2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337, + 2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,1,1,1,2337,2337,2337,2337,2337, + 2337,2337,2337,2337,2337,2337,2337,2337,2337,2337,1,1,1,2337,2337,2337,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425, + 3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425,3425, + 897,897,897,897,897,897,897,897,897,897,897,1,1,1,1,1,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, + 1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1,1,1313,1313,1313, + 4481,4481,4481,4481,4481,4481,4481,4481,1,1,1,1,1,1,1,1,8452,1025,8452,8483,1025,5346,5346,8578,5346,8578,8646,1025,8578,8578,1025,1025, + 8578,5346,1025,1025,1025,1025,1025,1025,1025,8834,5346,1025,1025,5346,1025,1025,1025,1025,8907,5378,9252,5346,5346,353,5378,5378,3201,1,1,1,1,1, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,1441,1441,1441,1441,1441,897,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1441,1441,1441, + 1441,1441,2305,2305,2305,2305,1441,1441,1441,1441,1441,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,897,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1441, + 1441,1441,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,9379,961,4577,961,961,961,961,961, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,1,1441,1441,1441,1441,1441,1441,1,1, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1,1,1441,1441,1441,1441,1441,1441,1,1,1441,1441,1441,1441,1441,1441,1441,1441,1,1441,1,1441,1,1441,1,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,1, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,1,1441,1441,1441,1441,1441,1441,1,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,1,1441,1441,1441,1,1441,1441,1441,1441,1441,1441,1441,1441,1441,1, + 929,929,929,929,929,929,929,929,929,929,929,929,961,961,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,9475,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,4706,929,929,929,929,929,929,929,929,929,929,9574,929,929,9764,929,929, + 929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,2305,1,1,929,929,929,929,929,929,929,929,929,929,929,2305, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,9891,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,1441,929,929,929,2305,2305,929,929,929,929,929,929,2305,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,2305,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345, + 1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345, + 1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801, + 801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801, + 801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801, + 801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,1,1,1,1,1,801,801,801,801,801,801,801, + 1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,1313, + 1313,1313,1313,1313,1313,1313,1,1313,1,1,1,1,1,1313,1,1,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025, + 5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025,5025, + 5025,5025,5025,5025,5025,5025,5025,5025,1,1,1,1,1,1,1,5025,5025,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5025, + 1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1,1,1,1,1,1,1,1,1, + 1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1, + 1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,9986,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,10050,10119,929,929,929,929,929,929,929,929,929,929,1121,929,929,929, + 929,10339,929,4226,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434,10434, + 929,10503,10728,10501,929,1,769,1,10984,10984,11241,11241,11526,11526,11526,11526,11526,11526,929,10501,11526,11526,11526,11526,11526,11526,11526,11526,10501,10501,10501,10501, + 929,1,1,1,1,1,1,1,1,1,10498,10498,10498,10498,1601,1601,10501,10594,10594,10594,10594,10594,929,10501,1,1,1,1,11715,11715,769,769, + 1,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1,1,10594,10594,10594,10594,1761,1761,1761, + 10594,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,11526,10594,1985,1985,1985, + 1,1,1,1,1,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, + 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,1,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769, + 417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769, + 769,769,769,769,769,769,1,1,1,1,1,1,1,1,1,10434,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769, + 769,769,769,769,769,769,769,769,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,929, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 769,769,769,769,769,769,769,769,769,769,769,769,929,929,929,929,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,769, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,769,769,769,769,769,769,769,769, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,929,929,929,929,929,929,929,929,929,929,769,769,769,769,769, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,929, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,1,1,1,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377,5377, + 5377,5377,5377,5377,5377,5377,5377,1,1,1,1,1,1,1,1,1,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465, + 2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465,2465, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217, + 5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,5217,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,4226,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,1,1,1,1,1,1,1,1, + 11810,11810,11810,11810,11810,11810,11810,11810,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1,1,2305,2305,1,2305,1,2305,2305,2305,2305,2305,2305,2305,2305,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545, + 4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,4545,1,1,1,11888,11888,11888,12399,12399,12399,12875,12875,13228,12875,1,1,1,1,1,1, + 3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969, + 3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,3969,1,1,1,1,1,1,1,1, + 4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161, + 4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161, + 4161,4161,4161,4161,4161,4161,1,1,1,1,1,1,1,1,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,4161,1,1,1,1,1,1, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,13603,1025,13698,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025, + 2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049, + 2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,2049,13763,2049,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065, + 4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,4065,1,1,1,1,1,1,1,1,1,1,1,4065, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1,1,1, + 1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889, + 1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889, + 1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1,13858,1889,1889,1889,1889,1889,1889,1889,1889,1889,1889,1,1,1,1,1889,1889, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,1, + 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + 673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,1,1,1,1,1,1,1,1,1, + 673,673,673,673,673,673,673,673,673,673,673,673,673,673,1,1,673,673,673,673,673,673,673,673,673,673,1,1,673,673,673,673, + 3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737, + 4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737,4737, + 4737,4737,4737,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4737,4737,4737,4737,4737, + 2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,1,1,1,1,1,1,1,1,1, + 1,1249,1249,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1,1,1249,1249,1249,1249,1249,1249,1,1,1,1,1,1,1,1,1, + 1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,1441,2305,2305,2305,2305,929,929,1,1,1,1,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, + 2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817, + 2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,1,1,2817,2817,2817,2817,2817,2817,2817,2817,2817,2817,1,1,1,1,1,1, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1,1,1,1,1,1,1,1,1,1,1,1,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1,1,1,1,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1,1,1,1, + 2305,2305,2305,2305,2305,2305,2305,1,1,1,1,1,1,1,1,1,1,1,1,161,161,161,161,161,1,1,1,1,1,1729,1729,1729, + 1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,1,1729,1729,1729,1729,1729,1,1729,1, + 1729,1729,1,1729,1729,1,1729,1729,1729,1729,1729,1729,1729,1729,1729,1729,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,13922,13922, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,1,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,1,1,1,1,1,1,1,129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,129,129,5250,129,129,129,129,129,129,129,129,129,129,5250,129,129, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,897,897,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,10501,10501,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,1,929,929,929,929,1,1,1,1,129,129,129,129,129,1,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,1,929, + 1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,929,929, + 929,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,929,929,929,929,929, + 929,11526,11526,11526,11526,11526,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,10594,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985, + 1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,1985,10594,10594, + 1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1601,1, + 1,1,1601,1601,1601,1601,1601,1601,1,1,1601,1601,1601,1601,1601,1601,1,1,1601,1601,1601,1601,1601,1601,1,1,1601,1601,1601,1,1,1, + 929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,929,929,929,929,929,1,1, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,1,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433, + 2433,2433,2433,2433,2433,2433,2433,1,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,1,2433,2433,1,2433, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,1,1,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433, + 2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,2433,1,1,1,1,1, + 13987,13987,14082,1,1,1,1,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147, + 14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,14147,1,1,1,14082,14082,14082,14082,14082,14082,14082,14082,14082, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1, + 1441,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,961,1,1, + 2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,2497,1,1,1, + 577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, + 577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,14242,1,1,1,1, + 3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489,3489, + 3489,3489,3489,3489,1,1,1,1,1,1,1,1,1,3489,3489,3489,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377, + 1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1377,1,1,1,1,1,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585, + 3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,3585,1,1,1,1,1, + 5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,5185,1,5185, + 3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617, + 3617,3617,3617,3617,1,1,1,1,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,3617,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, + 993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993, + 993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225, + 4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225,4225, + 3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,1,1, + 3841,3841,3841,3841,3841,3841,3841,3841,3841,3841,1,1,1,1,1,1,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809, + 3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,1,1,1,1,3809,3809,3809,3809,3809,3809,3809,3809, + 3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,3809,1,1,1,1, + 1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185,1185, + 1185,1185,1185,1185,1185,1185,1185,1185,1,1,1,1,1,1,1,1,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609, + 609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609, + 609,609,609,609,1,1,1,1,1,1,1,1,1,1,1,609,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,1,5249,5249,5249,5249, + 5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,1,5249,5249,5249,5249,5249,5249,5249,1,5249,5249,1,5249,5249,5249,5249,5249,5249,5249,5249,5249, + 5249,5249,1,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,5249,1,5249,5249,5249,5249,5249,5249,5249,1,5249,5249,1,1,1, + 5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089, + 5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,5089,1,1,1,1,1,1,1,1,1,1,1,1, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,1,1,1,1,1,1,1,1,1, + 2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,2401,1,1,1,1,1,1,1,1,1,1, + 2401,2401,2401,2401,2401,2401,2401,2401,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2305,2305,2305,2305,2305,2305,1,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1,2305,2305,2305,2305,2305,2305,2305,2305,2305,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 833,833,833,833,833,833,1,1,833,1,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833, + 833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,1,833,833,1,1,1,833,1,1,833, + 1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1793,1,1793,1793,1793,1793,1793,1793,1793,1793,1793, + 3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905,3905, + 3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,3137,1, + 1,1,1,1,1,1,1,3137,3137,3137,3137,3137,3137,3137,3137,3137,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1697,1,1697,1697,1,1,1,1,1,1697,1697,1697,1697,1697, + 4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,4001,1,1,1,4001, + 2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,2529,1,1,1,1,1,2529, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913,2913, + 2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,1,1,1,1,2881,2881,2881,2881, + 2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,1,1,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881, + 2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881,2881, + 2081,2081,2081,2081,1,2081,2081,1,1,1,1,1,2081,2081,2081,2081,2081,2081,2081,2081,1,2081,2081,2081,1,2081,2081,2081,2081,2081,2081,2081, + 2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,2081,1,1,2081,2081,2081,1,1,1,1,2081, + 2081,2081,2081,2081,2081,2081,2081,2081,2081,1,1,1,1,1,1,1,2081,2081,2081,2081,2081,2081,2081,2081,2081,1,1,1,1,1,1,1, + 3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681,3681, + 3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553,3553, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689,2689, + 2689,2689,2689,2689,2689,2689,2689,1,1,1,1,2689,2689,2689,2689,2689,2689,2689,5090,2689,2689,2689,2689,1,1,1,1,1,1,1,1,1, + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,1,1,1,193,193,193,193,193,193,193, + 1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1857,1,1,1857,1857,1857,1857,1857,1857,1857,1857, + 1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1825,1,1,1,1,1,1825,1825,1825,1825,1825,1825,1825,1825, + 4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,4033,1,1,1,1,1,1,1,4033,4033,4033,4033,1,1,1, + 1,1,1,1,1,1,1,1,1,4033,4033,4033,4033,4033,4033,4033,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713, + 3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713,3713, + 3713,3713,3713,3713,3713,3713,3713,3713,3713,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521, + 3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521, + 3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,3521,1,1,1,1,1,1,1,3521,3521,3521,3521,3521,3521, + 1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633, + 1633,1633,1633,1633,1633,1633,1633,1633,1,1,1,1,1,1,1,1,1633,1633,1633,1633,1633,1633,1633,1633,1633,1633,1,1,1,1,1,1, + 1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281, + 1281,1281,1281,1281,1281,1281,1,1,1,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281, + 1281,1281,1281,1281,1281,1281,1,1,1,1,1,1,1,1,1281,1281,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1, + 5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,5345, + 5345,5345,5345,5345,5345,5345,5345,5345,5345,5345,1,5345,5345,5345,1,1,5345,5345,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,129,129,129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,129,129,129,129, + 3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649,3649, + 3649,3649,3649,3649,3649,3649,3649,3649,1,1,1,1,1,1,1,1,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321, + 4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,4321,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,3745, + 3745,3745,3745,3745,3745,3745,3745,3745,3745,3745,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, + 737,737,737,737,737,737,737,737,737,737,737,737,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1217,1,1,1,1,1,1,1,1,1, + 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, + 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, + 449,449,449,449,449,449,449,449,449,449,449,449,449,449,1,1,1,1,449,449,449,449,449,449,449,449,449,449,449,449,449,449, + 449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,1,1,1,1,1,1,1,1,1,449, + 1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921, + 1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921,1921, + 1921,1921,1921,1,1,1,1,1,1,1,1,1,1,1921,1,1,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385, + 4385,4385,4385,4385,4385,4385,4385,4385,4385,1,1,1,1,1,1,1,4385,4385,4385,4385,4385,4385,4385,4385,4385,4385,1,1,1,1,1,1, + 641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, + 641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,1,641,641,641,641,641,641,641,641,641,641, + 641,641,641,641,641,641,641,641,1,1,1,1,1,1,1,1,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561, + 2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,2561,1,1,1,1,1,1,1,1,1, + 4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193, + 4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193, + 4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193,4193, + 1,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,4353,1,1,1,1,1,1,1,1,1,1,1, + 2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,1,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177, + 2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177,2177, + 2177,2177,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3073,3073,3073,3073,3073,3073,3073,1,3073,1,3073,3073,3073,3073,1,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,1,3073, + 3073,3073,3073,3073,3073,3073,3073,3073,3073,3073,1,1,1,1,1,1,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209, + 2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209, + 2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,1,1,1,1,1,2209,2209,2209,2209,2209,2209,2209,2209,2209,2209,1,1,1,1,1,1, + 1409,7906,1409,7906,1,1409,1409,1409,1409,1409,1409,1409,1409,1,1,1409,1409,1,1,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409,1409, + 1409,1409,1409,1409,1409,1409,1409,1409,1409,1,1409,1409,1409,1409,1409,1409,1409,1,1409,1409,1,1409,1409,1409,1409,1409,1,7906,7906,1409,1409,1409, + 1409,1409,1409,1409,1409,1,1,1409,1409,1,1,1409,1409,1409,1,1,1409,1,1,1,1,1,1,1409,1,1,1,1,1,1409,1409,1409, + 1409,1409,1409,1409,1,1,1409,1409,1409,1409,1409,1409,1409,1,1,1,1409,1409,1409,1409,1409,1,1,1,1,1,1,1,1,1,1,1, + 5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,1,5153,1,1,5153,1,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153, + 5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,1,5153,5153,5153,5153,5153,5153,5153,5153,5153, + 5153,1,5153,1,1,5153,1,5153,5153,5153,5153,1,5153,5153,5153,5153,5153,5153,5153,5153,5153,5153,1,5153,5153,1,1,1,1,1,1,1, + 1,5153,5153,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233, + 3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233, + 3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,3233,1,3233,3233,3233, + 3233,3233,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057, + 5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057, + 5057,5057,5057,5057,5057,5057,5057,5057,1,1,1,1,1,1,1,1,5057,5057,5057,5057,5057,5057,5057,5057,5057,5057,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257, + 4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,1,1,4257,4257,4257,4257,4257,4257,4257,4257, + 4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,4257,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977, + 2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977, + 2977,2977,2977,2977,2977,1,1,1,1,1,1,1,1,1,1,1,2977,2977,2977,2977,2977,2977,2977,2977,2977,2977,1,1,1,1,1,1, + 3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,3009,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769, + 4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,1,1,1,1,1,1, + 4769,4769,4769,4769,4769,4769,4769,4769,4769,4769,1,1,1,1,1,1,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105,3105, + 3105,3105,3105,3105,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,1,1,65,65,65, + 65,65,65,65,65,65,65,65,65,65,65,65,1,1,1,1,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65, + 65,65,65,65,65,65,65,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089, + 1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313, + 5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313, + 5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,5313,1,1,1,1,1,1,1,1,1,1,1,1,5313, + 1057,1057,1057,1057,1057,1057,1057,1,1,1057,1,1,1057,1057,1057,1057,1057,1057,1057,1057,1,1057,1057,1,1057,1057,1057,1057,1057,1057,1057,1057, + 1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1,1057,1057,1,1,1057,1057,1057,1057,1057, + 1057,1057,1057,1057,1057,1057,1057,1,1,1,1,1,1,1,1,1,1057,1057,1057,1057,1057,1057,1057,1057,1057,1057,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3201,3201,3201,3201,3201,3201,3201,3201,1,1,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201, + 3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,3201,1,1,3201,3201,3201,3201,3201,3201, + 3201,3201,3201,3201,3201,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409, + 5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409,5409, + 5409,5409,5409,5409,5409,5409,5409,5409,1,1,1,1,1,1,1,1,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417, + 4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417, + 4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417,4417, + 4417,4417,4417,1,1,1,1,1,1,1,1,1,1,1,1,1,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545, + 3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937, + 3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,3937,1,1,1,1,1,1,1, + 1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513, + 4513,4513,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4513,4513,4513,4513,4513,4513,4513,4513,4513,4513,1,1,1,1,1,1, + 385,385,385,385,385,385,385,385,385,1,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385, + 385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,1,385,385,385,385,385,385,385,385, + 385,385,385,385,385,385,1,1,1,1,1,1,1,1,1,1,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385, + 385,385,385,385,385,385,385,385,385,385,385,385,385,1,1,1,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721, + 2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,1,1,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721, + 2721,2721,2721,2721,2721,2721,2721,2721,1,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,2721,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2753,2753,2753,2753,2753,2753,2753,1,2753,2753,1,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753, + 2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,1,1,1,2753,1,2753,2753,1,2753, + 2753,2753,2753,2753,2753,2753,2753,2753,1,1,1,1,1,1,1,1,2753,2753,2753,2753,2753,2753,2753,2753,2753,2753,1,1,1,1,1,1, + 1505,1505,1505,1505,1505,1505,1,1505,1505,1,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505, + 1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1,1505,1505,1,1505,1505,1505,1505,1505,1505,1,1,1,1,1,1,1, + 1505,1505,1505,1505,1505,1505,1505,1505,1505,1505,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,2593,1,1,1,1,1,1,1, + 2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,1,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017, + 2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,1,1,1,2017,2017, + 2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2465,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,7906,7906,4801,7906,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801, + 4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,4801,1,1,1,1,1,1,1,1,1,1,1,1,1,4801, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,1,4449,4449,4449,4449,4449,1,1,1,1,1,1,1,1,1,1,1, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449,4449, + 4449,4449,4449,4449,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865, + 865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865, + 865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865, + 865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,865,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1,1,1,1,1,1,1,1,1,1, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153, + 1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1153,1,1,1,1,1, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97, + 97,97,97,97,97,97,97,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569, + 1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1569,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257, + 257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,1,1,1,1,1,1,1, + 3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,1, + 3041,3041,3041,3041,3041,3041,3041,3041,3041,3041,1,1,1,1,3041,3041,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833, + 4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833, + 4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,1, + 4833,4833,4833,4833,4833,4833,4833,4833,4833,4833,1,1,1,1,1,1,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289, + 289,289,289,289,289,289,289,289,289,289,289,289,289,289,1,1,289,289,289,289,289,289,1,1,1,1,1,1,1,1,1,1, + 3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873, + 3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873, + 3873,3873,3873,3873,3873,3873,1,1,1,1,1,1,1,1,1,1,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,1,3873,3873,3873,3873,3873, + 3873,3873,1,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,1,1,1,1,1,3873,3873,3873, + 3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,3873,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241, + 2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,2241,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785, + 2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785, + 2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,2785,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945, + 2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945, + 2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,1,1,1,1,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945, + 2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945, + 2945,2945,2945,2945,2945,2945,2945,2945,1,1,1,1,1,1,1,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945,2945, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4865,3329,1,1,2113,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,4865,1,1,1,1,1,1,1,1, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113, + 2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,2113,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2113, + 4865,4865,4865,4865,4865,4865,4865,4865,4865,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1985,1985,1985,1985,1,1985,1985,1985,1985,1985,1985,1985,1,1985,1985,1, + 1985,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761,1761, + 1985,1985,1985,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1761,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1761,1761,1761,1,1,1985,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1985,1985,1985,1985,1,1,1,1,1,1,1,1,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329, + 3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,3329,1,1,1,1, + 1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121, + 1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121, + 1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121, + 1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1,1,1,1,1,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1,1,1, + 1121,1121,1121,1121,1121,1121,1121,1121,1121,1,1,1,1,1,1,1,1121,1121,1121,1121,1121,1121,1121,1121,1121,1121,1,1,1121,1121,1121,1121, + 1121,1121,1121,1121,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,1,1,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,1,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,961,961,961,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,961,961,961,961,961, + 961,961,961,929,929,961,961,961,961,961,961,961,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,961,961,961,961,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441,1441, + 1441,1441,1441,1441,1441,1441,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1, + 769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,929,929,929,929,929,929,929,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929, + 1,1,929,1,1,929,929,1,1,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929,1,929,1,929,929,929, + 929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,1,929,929,929,929,1,1,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,1,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,1, + 929,929,929,929,929,1,929,1,1,1,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289, + 4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289, + 4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289, + 4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289, + 4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4289,4289,4289,4289,4289, + 1,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,4289,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,2305,1, + 1,1,1,1,1,2305,2305,2305,2305,2305,2305,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1345,1345,1345,1345,1345,1345,1345,1,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1345,1,1,1345,1345,1345,1345,1345, + 1345,1345,1,1345,1345,1,1345,1345,1345,1345,1345,1,1,1,1,1,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897, + 897,897,897,897,897,897,897,897,897,897,897,897,897,897,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,897,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361, + 3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,1,1,1,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,1,1, + 3361,3361,3361,3361,3361,3361,3361,3361,3361,3361,1,1,1,1,3361,3361,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121, + 5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,5121,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281, + 5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,5281,1,1,1,1,1,5281, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169, + 3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,3169,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457, + 3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,3457,1,1,1,1,3457, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1249,1249,1249,1249,1249,1249,1249,1,1249,1249,1249,1249,1,1249,1249,1,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1249,1, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849, + 2849,2849,2849,2849,2849,1,1,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,2849,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, + 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33, + 33,33,33,33,33,33,33,33,33,33,33,33,1,1,1,1,33,33,33,33,33,33,33,33,33,33,1,1,1,1,33,33, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 129,129,129,129,1,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129, + 1,129,129,1,129,1,1,129,1,129,129,129,129,129,129,129,129,129,129,1,129,129,129,129,1,129,1,129,1,1,1,1, + 1,1,129,1,1,1,1,129,1,129,1,129,1,129,129,129,1,129,129,1,129,1,1,129,1,129,1,129,1,129,1,129, + 1,129,129,1,129,1,1,129,129,129,129,1,129,129,129,129,129,129,129,1,129,129,129,129,1,129,129,129,129,1,129,1, + 129,129,129,129,129,129,129,129,129,129,1,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,1,1,1, + 1,129,129,129,1,129,129,129,129,129,1,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,129,129,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 1761,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1, + 929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,769,769,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1, + 929,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1, + 929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,1,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,929, + 929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,1,1,1,1,1,1, + 1,929,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, + 961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +KBTS_INLINE kbts_u16 kbts__GetUnicodeScriptExtension(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeScriptExtension_Data[((kbts_un)kbts__UnicodeScriptExtension_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +static kbts_u8 kbts__UnicodeMirrorCodepoint_PageIndices[8703] = { + 0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 5,6,2,2,7,8,9,2,2,2,2,2,2,2,10,11,2,2,2,12,13,14,2,15,2,2,2,2,16,2,2,2, + 17,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,18,2,19,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +}; + +static kbts_u32 kbts__UnicodeMirrorCodepoint_Data[2560] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,41,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,0,60,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,91,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,123,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,187,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,171,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3899,3898,3901,3900,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5788,5787,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8250,8249,0,0,0,0,0, + 0,0,0,0,0,8262,8261,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8318,8317,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,8334,8333,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,8715,8716,8717,8712,8713,8714,0,0,0,0,0,0,0,10741,0,0,0,0,0,0,0,0,0,11262, + 10659,10651,10656,0,10990,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8765,8764,0,0, + 0,0,0,8909,0,8780,0,0,0,0,0,0,8773,0,0,0,0,0,8787,8786,8789,8788,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,8805,8804,8807,8806,8809,8808,8811,8810,0,0,8815,8814,8817,8816,8819,8818,8821,8820,8823,8822,8825,8824,8827,8826,8829,8828,8831,8830, + 8833,8832,8835,8834,8837,8836,8839,8838,8841,8840,8843,8842,0,0,0,8848,8847,8850,8849,0,0,0,0,0,10680,0,0,0,0,0,0,0, + 0,0,8867,8866,0,0,10974,0,10980,10979,0,10981,0,0,0,0,8881,8880,8883,8882,8885,8884,8887,8886,10204,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,8906,8905,8908,8907,8771,0,0,8913,8912,0,0,0,0,8919,8918,8921,8920,8923,8922,8925,8924,8927,8926, + 8929,8928,8931,8930,8933,8932,8935,8934,8937,8936,8939,8938,8941,8940,0,0,8945,8944,8954,8955,8956,0,8957,8958,0,0,8946,8947,8948,8950,8951,0, + 0,0,0,0,0,0,0,0,8969,8968,8971,8970,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,9002,9001,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,10089,10088,10091,10090,10093,10092,10095,10094,10097,10096,10099,10098,10101,10100,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,10180,10179,10182,10181,0,10185,10184,0,10189,0,10187,0,0,0,0,0,0,0,10198,10197,0,0,0,0,0,8888,10206,10205,0, + 0,0,10211,10210,10213,10212,10215,10214,10217,10216,10219,10218,10221,10220,10223,10222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,10628,10627,10630,10629,10632,10631,10634,10633,10636,10635,10640,10639,10638,10637,10642,10641,10644,10643,10646,10645,10648,10647,0,0,8737,0,0,0,0, + 8738,0,0,8736,10661,10660,0,0,10665,10664,10667,10666,10669,10668,10671,10670,0,0,0,0,0,0,0,0,8856,0,0,0,0,0,0,0, + 10689,10688,0,0,10693,10692,0,0,0,0,0,0,0,0,0,10704,10703,10706,10705,0,10709,10708,0,0,10713,10712,10715,10714,0,0,0,0, + 0,0,0,0,0,0,0,0,10729,10728,0,0,0,0,0,0,0,0,0,0,0,8725,0,0,10745,10744,0,0,10749,10748,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,10796,10795,10798,10797,0,0,0,0,0,10805,10804,0,0,0,0,0,0,10813,10812,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,10853,10852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10874,10873,10876,10875,10878,10877,10880, + 10879,10882,10881,10884,10883,10886,10885,10888,10887,10890,10889,10892,10891,10894,10893,10896,10895,10898,10897,10900,10899,10902,10901,10904,10903,10906,10905,10908,10907,10910,10909,10912, + 10911,10914,10913,0,0,0,10919,10918,10921,10920,10923,10922,10925,10924,0,10928,10927,10930,10929,10932,10931,10934,10933,10936,10935,10938,10937,10940,10939,10942,10941,10944, + 10943,10946,10945,10948,10947,10950,10949,10952,10951,10954,10953,10956,10955,10958,10957,10960,10959,10962,10961,10964,10963,10966,10965,0,0,0,0,0,0,0,8870,0, + 0,0,0,8873,8872,8875,0,0,0,0,0,0,10989,10988,8740,0,0,0,0,0,0,0,0,11000,10999,11002,11001,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8735,0, + 0,0,11779,11778,11781,11780,0,0,0,11786,11785,0,11789,11788,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11805,11804,0,0, + 11809,11808,11811,11810,11813,11812,11815,11814,11817,11816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11862,11861,11864,11863,11866,11865,11868,11867,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,12297,12296,12299,12298,12301,12300,12303,12302,12305,12304,0,0,12309,12308,12311,12310,12313,12312,12315,12314,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65114,65113,65116,65115,65118,65117,0, + 0,0,0,0,65125,65124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,65289,65288,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65310,0,65308,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65341,0,65339,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65373,0,65371,0,65376, + 65375,0,65379,65378,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +KBTS_INLINE kbts_u32 kbts__GetUnicodeMirrorCodepoint(kbts_u32 Codepoint) +{ + return (Codepoint < 1114110) ? kbts__UnicodeMirrorCodepoint_Data[((kbts_un)kbts__UnicodeMirrorCodepoint_PageIndices[Codepoint/128] * 128) | (Codepoint & 127)] : 0; +} + +KBTS_INLINE kbts_u32 kbts__GetDecompositionSize(kbts_u64 Decomposition) +{ + return Decomposition & 3; +} + +KBTS_INLINE kbts_u32 kbts__GetDecompositionCodepoint(kbts_u64 Decomposition, kbts_un Index){ + return (Decomposition >> (Index ? 23 : 2)) & 0x1FFFFF; +} + +#define KBTS_UNICODE_DECOMPOSITION_DO_NOT_RECURSE0 (1ull << 44) +#define KBTS_UNICODE_DECOMPOSITION_DO_NOT_RECURSE1 (1ull << 45) + +KBTS_INLINE kbts_u8 kbts__GetSyllabicClass(kbts_u16 SyllabicInfo) +{ + return SyllabicInfo & 0xFF; +} + +KBTS_INLINE kbts_u8 kbts__GetSyllabicPosition(kbts_u16 SyllabicInfo) +{ + return SyllabicInfo >> 8; +} + +KBTS_INLINE kbts_s32 *kbts__GetParentInfoDeltas(kbts_u32 ParentInfo) +{ + return kbts__UnicodeParentDeltas + (ParentInfo & 0xFFFF); +} + +KBTS_INLINE kbts_un kbts__GetParentInfoCount(kbts_u32 ParentInfo) +{ + return ParentInfo >> 16; +} + +KBTS_INLINE kbts_un kbts__ScriptExtensionCount(kbts_u16 ScriptExtension) +{ + return (ScriptExtension & 0x1f); +} + +KBTS_INLINE kbts_un kbts__ScriptExtensionOffset(kbts_u16 ScriptExtension) +{ + return (ScriptExtension >> 5); +} + +typedef kbts_u8 kbts_grapheme_break_class; +enum kbts_grapheme_break_class_enum { + /* 0 */ KBTS_GRAPHEME_BREAK_CLASS_DEFAULT, + /* 1 */ KBTS_GRAPHEME_BREAK_CLASS_CR, + /* 2 */ KBTS_GRAPHEME_BREAK_CLASS_LF, + /* 3 */ KBTS_GRAPHEME_BREAK_CLASS_Control, + /* 4 */ KBTS_GRAPHEME_BREAK_CLASS_Extend, + /* 5 */ KBTS_GRAPHEME_BREAK_CLASS_ZWJ, + /* 6 */ KBTS_GRAPHEME_BREAK_CLASS_SpacingMark, + /* 7 */ KBTS_GRAPHEME_BREAK_CLASS_L, + /* 8 */ KBTS_GRAPHEME_BREAK_CLASS_V, + /* 9 */ KBTS_GRAPHEME_BREAK_CLASS_LV, + /* 10 */ KBTS_GRAPHEME_BREAK_CLASS_LVT, + /* 11 */ KBTS_GRAPHEME_BREAK_CLASS_T, + /* 12 */ KBTS_GRAPHEME_BREAK_CLASS_Prepend, + /* 13 */ KBTS_GRAPHEME_BREAK_CLASS_IndicConsonant, + /* 14 */ KBTS_GRAPHEME_BREAK_CLASS_IndicExtend, + /* 15 */ KBTS_GRAPHEME_BREAK_CLASS_IndicLinker, + /* 16 */ KBTS_GRAPHEME_BREAK_CLASS_ExtendedPictographic, + /* 17 */ KBTS_GRAPHEME_BREAK_CLASS_RI, + + KBTS_GRAPHEME_BREAK_CLASS_COUNT, +}; + +typedef kbts_u8 kbts_grapheme_break_state; +enum kbts_grapheme_break_state_enum { + /* 0 */ KBTS_GRAPHEME_BREAK_STATE_START, + /* 1 */ KBTS_GRAPHEME_BREAK_STATE_CR, + /* 2 */ KBTS_GRAPHEME_BREAK_STATE_L, + /* 3 */ KBTS_GRAPHEME_BREAK_STATE_LVxV, + /* 4 */ KBTS_GRAPHEME_BREAK_STATE_LVTxT, + /* 5 */ KBTS_GRAPHEME_BREAK_STATE_IndicConsonantxIndicLinker, + /* 6 */ KBTS_GRAPHEME_BREAK_STATE_IndicExtendr, + /* 7 */ KBTS_GRAPHEME_BREAK_STATE_IndicExtendLinkerr, + /* 8 */ KBTS_GRAPHEME_BREAK_STATE_ExtendedPictographic, + /* 9 */ KBTS_GRAPHEME_BREAK_STATE_ExtendR, + /* 10 */ KBTS_GRAPHEME_BREAK_STATE_ExtendR_ZWJ, + /* 11 */ KBTS_GRAPHEME_BREAK_STATE_RI, + /* 12 */ KBTS_GRAPHEME_BREAK_STATE_SKIP, + + /* 13 */ KBTS_GRAPHEME_BREAK_STATE_COUNT, + + /* 14 */ KBTS_GRAPHEME_BREAK_STATE_b0, + /* 15 */ KBTS_GRAPHEME_BREAK_STATE_b01, + // The values below have to be in the same order as their corresponding states. + /* 16 */ KBTS_GRAPHEME_BREAK_STATE_b1, + /* 17 */ KBTS_GRAPHEME_BREAK_STATE_b1toCR, + /* 18 */ KBTS_GRAPHEME_BREAK_STATE_b1toL, + /* 19 */ KBTS_GRAPHEME_BREAK_STATE_b1toLVxV, + /* 20 */ KBTS_GRAPHEME_BREAK_STATE_b1toLVTxT, + /* 21 */ KBTS_GRAPHEME_BREAK_STATE_b1toIndicConsonantxIndicLinker, + /* 22 */ KBTS_GRAPHEME_BREAK_STATE_PADDING0, + /* 23 */ KBTS_GRAPHEME_BREAK_STATE_PADDING1, + /* 24 */ KBTS_GRAPHEME_BREAK_STATE_b1toExtendedPictographic, + /* 25 */ KBTS_GRAPHEME_BREAK_STATE_PADDING2, + /* 26 */ KBTS_GRAPHEME_BREAK_STATE_PADDING3, + /* 27 */ KBTS_GRAPHEME_BREAK_STATE_b1toRI, + /* 28 */ KBTS_GRAPHEME_BREAK_STATE_b1toSKIP, +}; + +// In the SKIP column, CR, LF and Control all still break before the cursor +// because their rules have a higher priority. +// In Indic-related states, ZWJ should behave like an Indic Extend. +static kbts_grapheme_break_state kbts_GraphemeBreakTransition[KBTS_GRAPHEME_BREAK_CLASS_COUNT][KBTS_GRAPHEME_BREAK_STATE_COUNT] = { + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* 0 */ {16,16,16,16,16,16,16,16,16,16,16,16, 0}, + /* 1 */ {17,17,17,17,17,17,17,17,17,17,17,17,17}, + /* 2 */ {15,14,15,15,15,15,15,15,15,15,15,15,15}, + /* 3 */ {15,15,15,15,15,15,15,15,15,15,15,15,15}, + /* 4 */ { 0,16, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0}, + /* 5 */ { 0,16, 0, 0, 0, 6, 6, 7,10,10, 0, 0, 0}, + /* 6 */ { 0,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 7 */ {18,18, 2,18,18,18,18,16,18,18,18,18, 2}, + /* 8 */ {19,19, 3, 3,19,19,19,16,19,19,19,19, 3}, + /* 9 */ {19,19, 3,19,19,19,19,16,19,19,19,19, 3}, + /* 10 */ {20,20, 4,20,20,20,20,16,20,20,20,20, 4}, + /* 11 */ {20,20,20, 4, 4,20,20,16,20,20,20,20, 4}, + /* 12 */ {28,28,28,28,28,28,28,28,28,28,28,28,12}, + /* 13 */ {21,21,21,21,21,21,21, 5,21,21,21,21, 5}, + /* 14 */ { 0,16, 0, 0, 0, 6, 6, 7, 9, 9, 0, 0, 0}, + /* 15 */ { 5,21, 5, 5, 5, 7, 7, 7, 5, 5, 5, 5, 5}, + /* 16 */ {24,24,24,24,24,24,24,16,24,24, 0,24, 8}, + /* 17 */ {27,27,27,27,27,27,27,27,27,27,27, 0,11}, +}; + +// These classes are for Indic, Myanmar and Khmer. +typedef kbts_u8 kbts_indic_syllabic_class; +enum kbts_indic_syllabic_class_enum { + /* 0 A */ KBTS_INDIC_SYLLABIC_CLASS_OTHER, + /* 1 B */ KBTS_INDIC_SYLLABIC_CLASS_CONSONANT, + /* 2 C */ KBTS_INDIC_SYLLABIC_CLASS_VOWEL, + /* 3 D */ KBTS_INDIC_SYLLABIC_CLASS_NUKTA, + /* 4 E */ KBTS_INDIC_SYLLABIC_CLASS_HALANT, + /* 5 F */ KBTS_INDIC_SYLLABIC_CLASS_ZWNJ, + /* 6 G */ KBTS_INDIC_SYLLABIC_CLASS_ZWJ, + /* 7 H */ KBTS_INDIC_SYLLABIC_CLASS_MATRA, + /* 8 I */ KBTS_INDIC_SYLLABIC_CLASS_SYLLABLE_MODIFIER, + /* 9 J */ KBTS_INDIC_SYLLABIC_CLASS_VEDIC_SIGN, + /* 10 K */ KBTS_INDIC_SYLLABIC_CLASS_PLACEHOLDER, + /* 11 L */ KBTS_INDIC_SYLLABIC_CLASS_DOTTED_CIRCLE, + /* 12 M */ KBTS_INDIC_SYLLABIC_CLASS_REGISTER_SHIFTER, + /* 13 N */ KBTS_INDIC_SYLLABIC_CLASS_MATRA_POST, + /* 14 O */ KBTS_INDIC_SYLLABIC_CLASS_REPHA, + /* 15 P */ KBTS_INDIC_SYLLABIC_CLASS_RA, + /* 16 Q */ KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL, + /* 17 R */ KBTS_INDIC_SYLLABIC_CLASS_SYMBOL, + /* 18 S */ KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_WITH_STACKER, + /* 19 T */ KBTS_INDIC_SYLLABIC_CLASS_SYLLABLE_MODIFIER_POST, + /* 20 U */ KBTS_INDIC_SYLLABIC_CLASS_VOWEL_ABOVE, + /* 21 V */ KBTS_INDIC_SYLLABIC_CLASS_VOWEL_BELOW, + /* 22 W */ KBTS_INDIC_SYLLABIC_CLASS_VOWEL_PRE, + /* 23 X */ KBTS_INDIC_SYLLABIC_CLASS_VOWEL_POST, + /* 24 Y */ KBTS_INDIC_SYLLABIC_CLASS_ROBATIC, + /* 25 Z */ KBTS_INDIC_SYLLABIC_CLASS_X_GROUP, + /* 26 a */ KBTS_INDIC_SYLLABIC_CLASS_Y_GROUP, + /* 27 b */ KBTS_INDIC_SYLLABIC_CLASS_ASAT, + /* 28 c */ KBTS_INDIC_SYLLABIC_CLASS_DOT_BELOW, + /* 29 d */ KBTS_INDIC_SYLLABIC_CLASS_SYLLABLE_MOD, + /* 30 e */ KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_HA, + /* 31 f */ KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_RA, + /* 32 g */ KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_WA, + /* 33 h */ KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_YA, + /* 34 i */ KBTS_INDIC_SYLLABIC_CLASS_PWO, + /* 35 j */ KBTS_INDIC_SYLLABIC_CLASS_VARIATION_SELECTOR, + /* 36 k */ KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_MON_LA, + + KBTS_MYANMAR_SYLLABIC_CLASS_COUNT, + KBTS_INDIC_SYLLABIC_CLASS_COUNT = KBTS_INDIC_SYLLABIC_CLASS_SYLLABLE_MODIFIER_POST + 1, + KBTS_KHMER_SYLLABIC_CLASS_COUNT = KBTS_INDIC_SYLLABIC_CLASS_Y_GROUP + 1, +}; + +#define KBTS_INDIC_SYLLABIC_STATE_COUNT 41 +#define KBTS_MYANMAR_SYLLABIC_STATE_COUNT 31 +#define KBTS_KHMER_SYLLABIC_STATE_COUNT 23 + +// @Incomplete: Decrement every state by 1. +static kbts_u8 kbts_IndicSyllabicTransition[KBTS_INDIC_SYLLABIC_CLASS_COUNT][KBTS_INDIC_SYLLABIC_STATE_COUNT] = { + /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 */ + /* A */ {43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,}, + /* B */ {14,43,43,43,43,43,43,14,43,43,43,43,43,43,43,14,43,14,43,43,43,43,43,43,43,14,43,43,43,43,43,43,14,43,43,14,43,43,14,43,14,}, + /* C */ {30,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,30,43,43,43,43,43,43,43,43,43,43,43,43,30,43,43,}, + /* D */ {24,43,24,20,43,43,31,43,43,43, 7,43,43,24,43,33,43,43,43,43,43,43,43,12,43,24,43,43,43, 7,43,24,43,43,43,33,15,43,24,24,43,}, + /* E */ { 8,43, 8,21,27,43, 8,43,18,18, 8, 8,18, 8,43,43,43,43,43,21,43,43,43, 8,18, 8,43,38,43, 8, 8, 8,43,43,18,18,43,43, 8,26,43,}, + /* F */ {25,43,13,22,28, 2,13,15,19,19,13,13,19,25,29,29, 2,29,19,22,22,19, 2,13,19,35,15,19,43, 9,13,25,29,43,22,22,29,29,25,25,43,}, + /* G */ {13,43,13,22,28,43,10,16,19,19,10,13,19,32,29,29,43,16,19,22,22,19,43,13,19,36,37,19,43,10,10,13,29,43,22,22,29,37,13,32,43,}, + /* H */ { 4,43, 4, 4, 4,43, 4,43, 4, 4, 4, 4, 4, 4,43,43,43,43, 4, 4, 4, 4,43, 4, 4, 4,43, 4,43, 4, 4, 4,43,43, 4, 4,43,43, 4, 4,43,}, + /* I */ { 6,43, 6, 6, 6,23, 6,17, 6, 6, 6, 6, 6, 6,17,17,23,17,34, 6, 6, 6,43, 6, 6, 6,17, 6,17, 6, 6, 6,17,43, 6, 6,17,17, 6, 6,43,}, + /* J */ { 2, 2, 2, 2, 2, 2, 2, 2,43,43, 2, 2,43, 2, 2, 2, 2, 2,43, 2, 2,43, 2, 2,43, 2, 2,43,43, 2, 2, 2, 2,43, 2, 2, 2, 2, 2, 2,43,}, + /* K */ {32,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,32,43,32,}, + /* L */ {32,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,32,43,43,43,43,43,43,43,43,43,43,43,43,32,43,43,}, + /* M */ { 3,43,43,43,43,43,43,43,11,43,43,43,43, 3,43,43,43,43,43,43,43,43,43,43, 3, 3,43,43,43,11,43, 3,43,43, 3,43,43,43, 3, 3,43,}, + /* N */ { 4,43, 4, 4, 4, 4, 4,43, 4, 4, 4, 4, 4, 4,43,43,43,43, 4, 4, 4, 4,43, 4, 4, 4,43, 4,43, 4, 4, 4,43, 4, 4, 4,43,43, 4, 4,43,}, + /* O */ {39,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,}, + /* P */ {40,43,43,43,43,43,43,14,43,43,43,43,43,43,43,14,43,14,43,43,43,43,43,43,43,14,43,43,43,43,43,43,14,43,43,14,43,43,14,43,14,}, + /* Q */ { 5,43, 5,43,43,43, 5,43,43,43, 5, 5,43, 5,43,43,43,43,43,43,43,43,43, 5,43, 5,43,43,43, 5, 5, 5,43,43,43,43,43,43, 5, 5,43,}, + /* R */ {37,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,}, + /* S */ {41,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,}, + /* T */ { 6,43, 6, 6, 6,23, 6,17, 6, 6, 6, 6, 6, 6,17,17,23,17,34, 6, 6, 6,43, 6, 6, 6,17, 6,17, 6, 6, 6,17,43, 6, 6,17,17, 6, 6,43,}, +}; + +// @Incomplete: Decrement every state by 1. +static kbts_u8 kbts_MyanmarSyllabicTransition[KBTS_MYANMAR_SYLLABIC_CLASS_COUNT][KBTS_MYANMAR_SYLLABIC_STATE_COUNT] = { + /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 */ + /* A */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* B */ {18,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,18,33,33,33,33,33,33,33,33,18,18,33,18,}, + /* C */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* D */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* E */ {19,33,33,33,33,33,33,33,33,33,33,33,33,33,33,28,33,28,19,29,33,33,33,33,33,33,33,18,19,28,18,}, + /* F */ { 2,33, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,33, 2, 2,33,}, + /* G */ { 2,33, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,33, 2, 2,33,}, + /* H */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* I */ { 3,33, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,33, 3, 3,33,}, + /* J */ { 4,33,33, 4, 4, 4, 4, 4, 4,33, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4, 4, 4, 4,33, 4,33,33, 4, 4, 4,}, + /* K */ {18,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,18,33,18,}, + /* L */ {18,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,18,33,18,}, + /* M */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* N */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* O */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* P */ {30,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,18,33,33,33,33,33,33,33,33,18,18,33,18,}, + /* Q */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* R */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* S */ {31,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* T */ { 3,33, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,33, 3, 3,33,}, + /* U */ { 5,33,33,33, 5,33, 5,22, 5,33, 5, 5, 5, 5,33, 5, 5, 5, 5, 5, 5,22,22,22,33, 5,33,33, 5, 5,33,}, + /* V */ { 6,33,33,33, 6, 6, 6,33, 6,33, 6, 6, 6, 6,33, 6, 6, 6, 6, 6, 6,33,33,33,33, 6,33,33, 6, 6,33,}, + /* W */ { 7,33,33,33,33,33, 7,33, 7,33, 7, 7, 7, 7,33, 7, 7, 7, 7, 7, 7,33,33,33,33, 7,33,33, 7, 7,33,}, + /* X */ { 8,33,33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,33,33, 8, 8,33,}, + /* Y */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* Z */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* a */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* b */ { 9,33,33,33,33,33,33,23, 9,25,21,33,21,26, 3, 9,21, 9, 9, 9,33,33,23,23,33,33, 3,33, 9,20,33,}, + /* c */ {10,33,33,10,10,10,10,10,10,33,10,10,10,10,27,10,10,10,10,10,10,10,10,10,33,10,33,33,10,10,33,}, + /* d */ {33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,}, + /* e */ {11,33,33,33,33,33,33,24,11,33,33,11,11,11,33,11,33,11,11,11,33,33,33,33,33,11,33,33,11,11,33,}, + /* f */ {12,33,33,33,33,33,33,33,12,33,33,33,33,12,33,12,33,12,12,12,33,33,33,33,33,12,33,33,12,12,33,}, + /* g */ {13,33,33,33,33,33,33,33,13,33,33,13,33,13,33,13,33,13,13,13,33,33,33,33,33,13,33,33,13,13,33,}, + /* h */ {14,33,33,33,33,33,33,33,14,33,33,33,33,33,33,14,33,14,14,14,33,33,33,33,33,33,33,33,14,14,33,}, + /* i */ {15,33,15,15,15,15,15,15,15,15,15,15,15,15,33,15,15,15,15,15,15,15,15,15,15,15,15,33,15,15,33,}, + /* j */ {16,33,33,33,33,33,21,33,33,33,33,33,33,33,33,33,33,16,16,33,33,33,33,33,33,33,33,33,16,16,33,}, + /* k */ {17,33,33,33,33,33,33,23,17,33,17,17,17,17,33,17,33,17,17,17,33,33,33,23,33,17,33,33,17,17,33,}, +}; + +// @Incomplete: Decrement every state by 1. +static kbts_u8 kbts_KhmerSyllabicTransition[KBTS_KHMER_SYLLABIC_CLASS_COUNT][KBTS_KHMER_SYLLABIC_STATE_COUNT] = { + /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 */ + /* A */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* B */ {15,25,25,25,25,18,25,25,25,25,25,25,25,25,25,25,25,25,25,25, 2,25,25,}, + /* C */ {15,25,25,25,25,18,25,25,25,25,25,25,25,25,25,25,25,25,25,25, 2,25,25,}, + /* D */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* E */ {21,21,25,25,21,25,25, 6,25, 6,25, 6,25, 6,21,21,25,25,25,25,25, 6,25,}, + /* F */ { 4,17, 3, 3, 4,25, 7, 7,19, 9,20,11,13,13,23, 4, 3,25,19,20,25, 4, 3,}, + /* G */ { 4,17, 3, 3, 4,25, 7, 7,19, 9,20,11,13,13,23, 4, 3,25,19,20,25, 4, 3,}, + /* H */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* I */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* J */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* K */ {16,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* L */ {16,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* M */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* N */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* O */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* P */ {15,25,25,25,25,18,25,25,25,25,25,25,25,25,25,25,25,25,25,25, 2,25,25,}, + /* Q */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* R */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* S */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* T */ {25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,}, + /* U */ { 8, 8,25, 8, 8,25,25,25, 8, 8, 8, 8,25,25, 8, 8, 8,25,25,25,25, 8, 8,}, + /* V */ {10,10,25,25,10,25,25,25,25,25,25,10,25,25,10,10,25,25,25,25,25,10,25,}, + /* W */ {12,12,25,25,12,25,25,25,25,25,25,25,25,25,12,12,25,25,25,25,25,12,25,}, + /* X */ {14,14,25,25,14,25,25,14,25,14,25,14,25,25,14,14,25,25,25,25,25,14,25,}, + /* Y */ { 5, 5,25,25,25,25,25,25,25,25,25,25,25,25,16, 5, 5,25,25,25,25,25,16,}, + /* Z */ {22,22,22,22,22,25, 8, 8,10,10,12,12,14,14,22,22,22,25,10,12,25,22,22,}, + /* a */ {18,18,25,25,18,25,25,18,25,18,25,18,25,18,18,18,25,18,25,25,25,18,25,}, +}; + +typedef kbts_u8 kbts_use_syllabic_class; +enum kbts_use_syllabic_class_enum { + /* 0 */ KBTS_USE_SYLLABIC_CLASS_OTHER, + /* 1 */ KBTS_USE_SYLLABIC_CLASS_BASE, + /* 2 */ KBTS_USE_SYLLABIC_CLASS_BASE_OTHER, + /* 3 */ KBTS_USE_SYLLABIC_CLASS_HALANT, + /* 4 */ KBTS_USE_SYLLABIC_CLASS_HALANT_OR_VOWEL_MODIFIER, + /* 5 */ KBTS_USE_SYLLABIC_CLASS_SAKOT, + /* 6 */ KBTS_USE_SYLLABIC_CLASS_INVISIBLE_STACKER, + /* 7 */ KBTS_USE_SYLLABIC_CLASS_CONS_SUB, + /* 8 */ KBTS_USE_SYLLABIC_CLASS_CONS_MOD_ABOVE, + /* 9 */ KBTS_USE_SYLLABIC_CLASS_CONS_MOD_BELOW, + /* 10 */ KBTS_USE_SYLLABIC_CLASS_CONS_MED_PRE, + /* 11 */ KBTS_USE_SYLLABIC_CLASS_CONS_MED_ABOVE, + /* 12 */ KBTS_USE_SYLLABIC_CLASS_CONS_MED_BELOW, + /* 13 */ KBTS_USE_SYLLABIC_CLASS_CONS_MED_POST, + /* 14 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_ABOVE, + /* 15 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_BELOW, + /* 16 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_POST, + /* 17 */ KBTS_USE_SYLLABIC_CLASS_REORDERING_KILLER, + /* 18 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH, + /* 19 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH_SEGMENT_BEGIN, + /* 20 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH_MOD, + /* 21 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH_SEGMENT_END, + /* 22 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH_JOINER, + /* 23 */ KBTS_USE_SYLLABIC_CLASS_HIEROGLYPH_MIRROR, + /* 24 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_ABOVE, + /* 25 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_BELOW, + /* 26 */ KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_POST, + /* 27 */ KBTS_USE_SYLLABIC_CLASS_SYMBOL_MOD_ABOVE, + /* 28 */ KBTS_USE_SYLLABIC_CLASS_SYMBOL_MOD_BELOW, + /* 29 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_ABOVE, + /* 30 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_BELOW, + /* 31 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_POST, + /* 32 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_PRE, + /* 33 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_PRE, + /* 34 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_ABOVE, + /* 35 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_BELOW, + /* 36 */ KBTS_USE_SYLLABIC_CLASS_VOWEL_POST, + /* 37 */ KBTS_USE_SYLLABIC_CLASS_CONSONANT_WITH_STACKER, + /* 38 */ KBTS_USE_SYLLABIC_CLASS_REPHA, + /* 39 */ KBTS_USE_SYLLABIC_CLASS_ZWNJ, + /* 40 */ KBTS_USE_SYLLABIC_CLASS_HALANT_NUM, + /* 41 */ KBTS_USE_SYLLABIC_CLASS_BASE_NUM, + + KBTS_USE_SYLLABIC_CLASS_COUNT, +}; + +enum +{ + KBTS_USE_STATE_s0 = 42, +}; + +// @Incomplete: Decrement every state by 1. +static kbts_u8 kbts_UseTransition[KBTS_USE_SYLLABIC_CLASS_COUNT][KBTS_USE_STATE_s0] = { + /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 */ + /* A */ {24,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* B */ {15,44,44,44,44,44,44,44,44,15,15,44,44,15,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,37,44,37,44,44,44,44,44,44,44,44,44,44,}, + /* C */ {24,44,44,44,44,44,44,44,44,15,15,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* D */ {14,44,44,44,44,44,44,44,44,44,14,44,44,44,14,14,31,31,31,31,44,44,44,14,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,14,}, + /* E */ {14,44,44,44,44, 5, 5, 5, 5,44,14,44,44, 5,14,14,31,31,31,31,44,44,44,14,44,44,44,44,44,44, 5, 5,44,44,44,44,44,44,44,44,44,14,}, + /* F */ {14,30,30,30,30,30,30,30,30,44,14,44,44,30,14,14,32,32,32,32,44,44,44,14,44,44,44,44,44,44,30,30,44,44,44,44,30,44,44,44,44,14,}, + /* G */ {14,44,44,44,44,44,44,44,44,44,14,44,44,44,14,14,31,31,31,31,44,44,44,14,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,14,}, + /* H */ {15,44,44,44,44,44,44,44,44,44,15,44,44,44,15,15,44,44,44,44,44,44,44,15,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,15,}, + /* I */ {15,44,44,44,44,44,44,44,44,44,15,44,44,44,15,44,44,44,44,44,44,44,44,15,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,15,}, + /* J */ {16,44,44,44,44,44,44,44,44,44,16,44,44,44,16,16,44,44,44,44,44,44,44,16,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,16,}, + /* K */ {17,44,44,44,44,44,44,44,44,44,17,44,44,44,17,17,44,44,44,44,44,44,44,17,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,17,}, + /* L */ {18,44,44,44,44,44,44,44,44,44,18,44,44,44,18,18,18,44,44,44,44,44,44,18,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,18,}, + /* M */ {19,44,44,44,44,44,44,44,44,44,19,44,44,44,19,19,19,19,44,44,44,44,44,19,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,19,}, + /* N */ {20,44,44,44,44,44,44,44,44,44,20,44,44,44,20,20,20,20,20,44,44,44,44,20,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,20,}, + /* O */ {21,21,21,21,21,21,21,21,21,44,21,44,44,21,21,21,21,21,21,21,21,44,44,21,44,44,44,44,44,44,21,21,44,44,44,44,21,44,44,44,44,21,}, + /* P */ {22,22,22,22,22,22,22,22,22,44,22,44,44,22,22,22,22,22,22,22,22,22,44,22,44,44,44,44,44,44,22,22,44,44,44,44,22,44,44,44,44,22,}, + /* Q */ {23,23,23,23,23,23,23,23,23,44,23,44,44,23,23,23,23,23,23,23,23,23,23,23,44,44,44,44,44,44,23,23,44,44,44,44,23,44,44,44,44,23,}, + /* R */ {25,44,44,44,44,44,44,44,44,44,25,44,44,44,25,25,44,44,44,44,44,44,44,25,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,25,}, + /* S */ {41,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,38,44,41,44,44,44,44,44,41,}, + /* T */ {42,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,34,44,36,44,39,39,39,44,36,}, + /* U */ {44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,33,44,44,39,44,39,33,44,}, + /* V */ {44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,33,44,33,44,44,44,44,44,33,44,}, + /* W */ {44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,34,34,34,44,44,34,34,34,34,44,}, + /* X */ {44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,40,44,44,35,44,}, + /* Y */ {26,26,26,26,26,26,26,26,26,44,26,44,44,26,26,26,26,26,26,26,26,26,26,26,44,26,44,44,44,44,26,26,44,44,44,44,26,44,44,44,44,26,}, + /* Z */ {27,27,27,27,27,27,27,27,27,44,27,44,44,27,27,27,27,27,27,27,27,27,27,27,44,27,27,44,44,44,27,27,44,44,44,44,27,44,44,44,44,27,}, + /* a */ {25,25,25,25,25,25,25,25,25,44,25,44,44,25,25,25,25,25,25,25,25,25,25,25,44,44,44,44,44,44,25,25,44,44,44,44,25,44,44,44,44,25,}, + /* b */ {28,44,44,44,44,44,44,44,44,44,11,44,44,44,44,44,44,44,44,44,44,44,44,28,44,44,44,28,44,44,44,44,44,44,44,44,44,44,44,44,44,28,}, + /* c */ {29,44,44,44,44,44,44,44,44,44,29,44,44,44,44,44,44,44,44,44,44,44,44,29,44,44,44,29,29,44,44,44,44,44,44,44,44,44,44,44,44,29,}, + /* d */ { 2, 2,44,44, 2, 2, 2, 2, 2,44, 2,44,44, 2, 2, 2, 2, 2, 2, 2,44,44,44, 2,44,44,44,44,44,44, 2, 2,44,44,44,44,44,44,44,44,44, 2,}, + /* e */ { 3, 3, 3,44, 3, 3, 3, 3, 3,44, 3,44,44, 3, 3, 3, 3, 3, 3, 3,44,44,44, 3,44,44,44,44,44,44, 3, 3,44,44,44,44,44,44,44,44,44, 3,}, + /* f */ { 4, 4, 4,44, 4, 4, 4, 4, 4,44, 4,44,44, 4, 4, 4, 4, 4, 4, 4,44,44,44, 4,44,44,44,44,44,44, 4, 4,44,44,44,44,44,44,44,44,44, 4,}, + /* g */ { 5,44,44,44, 5, 5, 5, 5, 5,44, 5,44,44, 5, 5, 5, 5, 5, 5, 5,44,44,44, 5,44,44,44,44,44,44, 5, 5,44,44,44,44,44,44,44,44,44, 5,}, + /* h */ { 6,44,44,44,44, 6,44,44,44,44, 6,44,44,44, 6, 6, 6, 6, 6, 6,44,44,44, 6,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, 6,}, + /* i */ { 7,44,44,44,44, 7, 7,44,44,44, 7,44,44,44, 7, 7, 7, 7, 7, 7,44,44,44, 7,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, 7,}, + /* j */ { 8,44,44,44,44, 8, 8, 8,44,44, 8,44,44,44, 8, 8, 8, 8, 8, 8,44,44,44, 8,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, 8,}, + /* k */ { 9,44,44,44,44, 9, 9, 9, 9,44, 9,44,44,44, 9, 9, 9, 9, 9, 9,44,44,44, 9,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44, 9,}, + /* l */ {10,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* m */ {11,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* n */ {44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* o */ {12,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, + /* p */ {13,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,}, +}; + +KBTS_EXPORT void kbts_FontCoverageTestBegin(kbts_font_coverage_test *Test, kbts_font *Font) +{ + Test->Font = Font; + Test->BaseParentCount = 0; + Test->BaseCodepoint = 0; + Test->CurrentBaseError = 0; + Test->Error = 0; +} + +KBTS_EXPORT void kbts_FontCoverageTestCodepoint(kbts_font_coverage_test *Test, int Codepoint) +{ + if(!Test->Error) + { + kbts_u32 UCodepoint = (kbts_u32)Codepoint; + int RecomposeBase = 0; + + if(!kbts__GetUnicodeCombiningClass(UCodepoint)) + { + Test->Error |= Test->CurrentBaseError; + Test->CurrentBaseError = 0; + Test->BaseCodepoint = UCodepoint; + + RecomposeBase = 1; + } + else + { + kbts_u16 Id = (kbts_u16)kbts_CodepointToGlyphId(Test->Font, Codepoint); + + if(!Id) + { + KBTS__FOR(ParentIndex, 0, Test->BaseParentCount) + { + kbts_glyph_parent *Parent = &Test->BaseParents[ParentIndex]; + + if(kbts__GetDecompositionCodepoint(Parent->Decomposition, 1) == UCodepoint) + { + Test->BaseCodepoint = Parent->Codepoint; + RecomposeBase = 1; + + break; + } + } + + if(!RecomposeBase) + { + Test->Error = 1; + } + } + } + + if(RecomposeBase) + { + kbts_u32 BaseCodepoint = Test->BaseCodepoint; + kbts_u16 BaseId = (kbts_u16)kbts_CodepointToGlyphId(Test->Font, (int)Test->BaseCodepoint); + kbts_un BaseParentCount = 0; + + int Done = 0; + while(!Done) + { + kbts_u32 ParentInfo = kbts__GetUnicodeParentInfo(BaseCodepoint); + kbts_s32 *ParentDeltas = kbts__GetParentInfoDeltas(ParentInfo); + + BaseParentCount = 0; + + Done = 1; + + KBTS__FOR(ParentIndex, 0, BaseParentCount) + { + kbts_glyph_parent Parent = KBTS__ZERO; + Parent.Codepoint = BaseCodepoint + (kbts_u32)ParentDeltas[ParentIndex]; + Parent.Decomposition = kbts__GetUnicodeDecomposition(Parent.Codepoint); + kbts_u16 RecompositionId = (kbts_u16)kbts_CodepointToGlyphId(Test->Font, (int)Parent.Codepoint); + + if(RecompositionId) + { + if(kbts__GetDecompositionSize(Parent.Decomposition) == 1) + { + BaseCodepoint = Parent.Codepoint; + BaseId = RecompositionId; + + Done = 0; + + break; + } + else + { + Test->BaseParents[BaseParentCount++] = Parent; + } + } + } + } + + Test->BaseCodepoint = BaseCodepoint; + Test->BaseParentCount = (kbts_u32)BaseParentCount; + + if(!BaseId) + { + Test->CurrentBaseError = 1; + } + } + } +} + +KBTS_EXPORT int kbts_FontCoverageTestEnd(kbts_font_coverage_test *Test) +{ + int Result = Test->CurrentBaseError | Test->Error; + Test->Error = Result; + return !Result; +} + +typedef struct kbts__feature_override_header +{ + struct kbts__feature_override_header *Prev; + struct kbts__feature_override_header *Next; +} kbts__feature_override_header; + +typedef struct kbts__feature_override +{ + kbts__feature_override_header Header; + + kbts_u32 Tag; + int Value; +} kbts__feature_override; + +typedef struct kbts_glyph_config +{ + kbts__feature_set EnabledFeatures; + kbts__feature_set DisabledFeatures; + + kbts_u32 ExtraOverrideCount; + + kbts_allocator_function *Allocator; + void *AllocatorData; + + kbts__feature_override_header FeatureOverrideSentinel; +} kbts_glyph_config; + +typedef struct kbts__arena_block +{ + kbts_arena_block_header Header; + void *BaseAllocation; // For freeing + + kbts_un Size; + kbts_un Used; + + // char Memory[Size]; // if Memory is NULL +} kbts__arena_block; + +typedef struct kbts__arena_lifetime +{ + kbts_arena *Arena; + kbts_arena_block_header *BlockHeader; + kbts_un Used; +} kbts__arena_lifetime; + +typedef struct kbts__glyph_list +{ + kbts_glyph *SentinelPrev; + kbts_glyph *SentinelNext; + kbts_glyph *OneBeforeFirst; + kbts_glyph *OnePastLast; +} kbts__glyph_list; + +typedef struct kbts__baked_feature +{ + kbts_u16 *Indices; + kbts_u32 Count; + kbts_u32 FeatureTag; + kbts_u32 FeatureId; + kbts_u32 SkipFlags; + kbts_u32 GlyphFilter; +} kbts__baked_feature; + +typedef struct kbts__baked_feature_stage +{ + kbts_u16 FeatureCount; + kbts_u16 FeatureIndexCount; + kbts__baked_feature *Features; // [FeatureCount] + kbts_u16 *FeatureIndices; // [FeatureIndexCount] +} kbts__baked_feature_stage; + +#define KBTS_MAX_SIMULTANEOUS_FEATURES 32 +typedef struct kbts__shape_scratchpad +{ + kbts_arena *Arena; + + kbts__feature_set LookupFeatures; + kbts__feature_set UserFeatures; + kbts__feature_set ScratchFeatures; + + kbts__glyph_list Cluster; + int RealCluster; + int ClusterAtStartOfWord; + + kbts_glyph *LookupOnePastLastGlyph; + kbts_u32 LookupOnePastLastGlyphIndex; + + kbts_u32 NextGlyphUid; + + kbts_u32 Ip; + kbts__op_kind OpKind; + kbts__feature_set *OpFeatures; + + kbts_direction RunDirection; + + kbts_u32 FeatureIndexIndex; + kbts_u32 FeatureStagesRead; + kbts_u16 BakedLookupSubtablesRead[KBTS_MAX_SIMULTANEOUS_FEATURES]; + + kbts_u32 UnregisteredFeatureCount; + kbts_feature_tag UnregisteredFeatureTags[KBTS_MAX_SIMULTANEOUS_FEATURES]; + + kbts_shape_error Error; +} kbts__shape_scratchpad; + +#define KBTS_CONTEXT_MAX_FONT_COUNT 32 + +typedef struct kbts__config_params +{ + kbts_u32 FontIndex; + kbts_script Script; + kbts_language Language; +} kbts__config_params; + +#define KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB 6 +#define KBTS__INPUT_CODEPOINT_ONE_PAST_LAST_BLOCK_MSB 27 + +typedef struct kbts__existing_shape_config +{ + kbts_shape_config *Config; + + kbts_font *Font; + kbts_script Script; +} kbts__existing_shape_config; + +typedef kbts_u32 kbts__context_flags; +enum kbts__context_flags_enum +{ + KBTS__CONTEXT_FLAG_NONE, + + KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION = 1, + KBTS__CONTEXT_FLAG_START_OF_MANUAL_RUN = 2, + KBTS__CONTEXT_FLAG_USE_MANUAL_BREAK_INFO = 4, +}; + +typedef struct kbts__context_font +{ + kbts_font *Font; + kbts__arena_lifetime Lifetime; +} kbts__context_font; + +typedef struct kbts_shape_context +{ + kbts_arena PermanentArena; + kbts_arena FontArena; + kbts_arena ConfigArena; + kbts_arena ScratchArena; + + kbts_allocator_function *SelfAllocator; + void *SelfAllocatorData; + + kbts_shape_codepoint *LastGraphemeBreak; + kbts_u32 LastGraphemeBreakIndex; + kbts_u32 LastLineBreakIndex; + kbts_u32 BreakStartIndex; + + kbts_u32 FontCount; + kbts__context_font Fonts[KBTS_CONTEXT_MAX_FONT_COUNT]; + + kbts__config_params *ConfigTableKeys; + kbts_shape_config **ConfigTable; + + kbts__feature_override_header FeatureOverrideSentinel; + kbts__feature_override_header FreeFeatureOverrideSentinel; + + kbts_un InputCodepointCount; + int NextUserId; + kbts_shape_codepoint *InputBlocks[KBTS__INPUT_CODEPOINT_ONE_PAST_LAST_BLOCK_MSB - KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB]; + + kbts_glyph_storage GlyphStorage; + + kbts__context_flags Flags; + kbts_direction ManualRunDirection; + kbts_script ManualRunScript; + + kbts_u32 BeginClusterIp; + kbts_u32 BeginClusterFeatureStagesRead; + kbts_glyph *TopLevelGlyph; + + kbts__feature_set *OpFeatures; + kbts__feature_set ScratchFeatures; + kbts__feature_set UserFeatures; + kbts__feature_set UserFeaturesEnabled; + + kbts_glyph_config *CurrentGlyphConfig; + int NeedNewGlyphConfig; + + kbts_direction ParagraphDirection; + kbts_language Language; + + kbts_font *RunFont; + kbts_script RunScript; + // This may be different from ParagraphDirection if ParagraphDirection == KBTS_DIRECTION_DONT_KNOW. + kbts_direction RunParagraphDirection; + kbts_direction RunDirection; + kbts_shape_codepoint_iterator RunCodepointIterator; + int DoneShapingRuns; + + kbts_u32 ExistingShapeConfigCount; + kbts__existing_shape_config ExistingShapeConfigs[32]; + + kbts_break_state BreakState; + + kbts_u32 FrameCount; + + kbts_shape_error Error; +} kbts_shape_context; + +typedef struct kbts__indic_script_properties +{ + kbts_u32 ViramaCodepoint; + kbts_u8 BlwfPostOnly; + kbts__reph_position RephPosition; + kbts__reph_encoding RephEncoding; + kbts__syllabic_position RightSideMatraPosition; + kbts__syllabic_position AboveBaseMatraPosition; + kbts__syllabic_position BelowBaseMatraPosition; +} kbts__indic_script_properties; + +typedef struct kbts_shape_config +{ + kbts_allocator_function *Allocator; + void *AllocatorData; + + kbts_font *Font; + kbts_script Script; + kbts_language Language; + kbts__langsys *Langsys[KBTS_SHAPING_TABLE_COUNT]; + kbts__op_list OpList; + + kbts__feature_set Features; + + kbts_shaper Shaper; + kbts_shaper_properties *ShaperProperties; + + kbts__indic_script_properties IndicScriptProperties; + kbts__feature *Blwf; + kbts__feature *Pref; + kbts__feature *Pstf; + kbts__feature *Locl; + kbts__feature *Rphf; + kbts__feature *Half; + kbts__feature *Vatu; + + // Indic + kbts_glyph Virama; + + kbts_glyph DottedCircle; + kbts_glyph Whitespace; + + // Thai + kbts_glyph Nikhahit; + kbts_glyph SaraAa; + + kbts__baked_feature_stage *FeatureStages; // [OpList.FeatureStageCount] +} kbts_shape_config; + +static const kbts_u8 kbts__CmapFormatPrecedence[14] = {1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 3, 0, 4, 5}; + +static int kbts__ShaperClearsMarkAdvancesInPostGposFixup(kbts_u32 Shaper) +{ + int Result = (1 << Shaper) & ((1 << KBTS_SHAPER_ARABIC) | (1 << KBTS_SHAPER_DEFAULT) | (1 << KBTS_SHAPER_HEBREW)); + return Result; +} + +static kbts__indic_script_properties kbts__IndicScriptProperties(kbts_u32 Script) +{ + kbts__indic_script_properties Result = KBTS__ZERO; + + switch(Script) + { + case KBTS_SCRIPT_DEVANAGARI: + { + Result.ViramaCodepoint = 0x94D; + Result.RephPosition = KBTS__REPH_POSITION_BEFORE_POST; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + } + break; + + case KBTS_SCRIPT_BENGALI: + { + Result.ViramaCodepoint = 0x9CD; + Result.RephPosition = KBTS__REPH_POSITION_AFTER_SUBJOINED; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + } + break; + + case KBTS_SCRIPT_GUJARATI: + { + Result.ViramaCodepoint = 0xACD; + Result.RephPosition = KBTS__REPH_POSITION_BEFORE_POST; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + } + break; + + case KBTS_SCRIPT_GURMUKHI: + { + Result.ViramaCodepoint = 0xA4D; + Result.RephPosition = KBTS__REPH_POSITION_BEFORE_SUBJOINED; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + } + break; + + case KBTS_SCRIPT_KANNADA: + { + Result.ViramaCodepoint = 0xCCD; + Result.BlwfPostOnly = 1; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED; + } + break; + + case KBTS_SCRIPT_MALAYALAM: + { + Result.ViramaCodepoint = 0xD4D; + Result.RephPosition = KBTS__REPH_POSITION_AFTER_MAIN; + Result.RephEncoding = KBTS__REPH_ENCODING_LOGICAL_REPHA; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + } + break; + + case KBTS_SCRIPT_ODIA: + { + Result.ViramaCodepoint = 0xB4D; + Result.RephPosition = KBTS__REPH_POSITION_AFTER_MAIN; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_MAIN; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + } + break; + + case KBTS_SCRIPT_TAMIL: + { + Result.ViramaCodepoint = 0xBCD; + Result.RightSideMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_AFTER_POST; + } + break; + + case KBTS_SCRIPT_TELUGU: + { + Result.ViramaCodepoint = 0xC4D; + Result.RephEncoding = KBTS__REPH_ENCODING_EXPLICIT; + Result.BlwfPostOnly = 1; + Result.AboveBaseMatraPosition = KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED; + Result.BelowBaseMatraPosition = KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED; + } + break; + } + + return Result; +} + +static void kbts__ByteSwapArray16Unchecked(kbts_u16 *Array, kbts_un Count) +{ + KBTS__FOR(It, 0, Count) + { + Array[It] = kbts__ByteSwap16(Array[It]); + } +} + +static int kbts__ByteSwapArray16(kbts_u16 *Array, kbts_un Count, char *End) +{ + int Result = 0; + if((char *)(Array + Count) <= End) + { + kbts__ByteSwapArray16Unchecked(Array, Count); + Result = 1; + } + + return Result; +} + +static void kbts__ByteSwapArray32Unchecked(kbts_u32 *Array, kbts_un Count) +{ + KBTS__FOR(It, 0, Count) + { + Array[It] = kbts__ByteSwap32(Array[It]); + } +} + +static int kbts__ByteSwapArray32(kbts_u32 *Array, kbts_un Count, char *End) +{ + int Result = 0; + if((char *)(Array + Count) <= End) + { + kbts__ByteSwapArray32Unchecked(Array, Count); + Result = 1; + } + return Result; +} + +static kbts_u64 kbts__ContainsFeature(kbts__feature_set *Set, kbts__feature_id Id) +{ + kbts_un WordIndex = Id / 64; + kbts_un BitIndex = Id % 64; + + kbts_u64 Result = Set->Flags[WordIndex] & (1ull << BitIndex); + return Result; +} + +static void kbts__AddFeature(kbts__feature_set *Set, kbts__feature_id Id) +{ + kbts_un WordIndex = Id / 64; + kbts_un BitIndex = Id % 64; + + Set->Flags[WordIndex] |= 1ull << BitIndex; +} + +// +// TTF struct definitions. +// + +enum +{ + KBTS__GLYPH_CLASS_BASE = 1, + KBTS__GLYPH_CLASS_LIGATURE = 2, + KBTS__GLYPH_CLASS_MARK = 3, + KBTS__GLYPH_CLASS_COMPONENT = 4, +}; + +enum +{ + KBTS__LOOKUP_FLAG_RIGHT_TO_LEFT = 1 << 0, + KBTS__LOOKUP_FLAG_IGNORE_BASE_GLYPHS = 1 << 1, + KBTS__LOOKUP_FLAG_IGNORE_LIGATURES = 1 << 2, + KBTS__LOOKUP_FLAG_IGNORE_MARKS = 1 << 3, + KBTS__LOOKUP_FLAG_USE_MARK_FILTERING_SET = 1 << 4, + + KBTS__LOOKUP_FLAG_MARK_ATTACHMENT_CLASS_FILTER = 0xFF00, +}; + +enum +{ + KBTS__OS2_WIDTH_ULTRA_CONDENSED = 1, + KBTS__OS2_WIDTH_EXTRA_CONDENSED = 2, + KBTS__OS2_WIDTH_CONDENSED = 3, + KBTS__OS2_WIDTH_SEMI_CONDENSED = 4, + KBTS__OS2_WIDTH_MEDIUM = 5, + KBTS__OS2_WIDTH_SEMI_EXPANDED = 6, + KBTS__OS2_WIDTH_EXPANDED = 7, + KBTS__OS2_WIDTH_EXTRA_EXPANDED = 8, + KBTS__OS2_WIDTH_ULTRA_EXPANDED = 9, +}; + +enum +{ + KBTS__VALUE_FORMAT_X_PLACEMENT = 1 << 0, + KBTS__VALUE_FORMAT_Y_PLACEMENT = 1 << 1, + KBTS__VALUE_FORMAT_X_ADVANCE = 1 << 2, + KBTS__VALUE_FORMAT_Y_ADVANCE = 1 << 3, + KBTS__VALUE_FORMAT_X_PLACEMENT_DEVICE = 1 << 4, + KBTS__VALUE_FORMAT_Y_PLACEMENT_DEVICE = 1 << 5, + KBTS__VALUE_FORMAT_X_ADVANCE_DEVICE = 1 << 6, + KBTS__VALUE_FORMAT_Y_ADVANCE_DEVICE = 1 << 7, +}; + +enum +{ + KBTS__OS2_SELECTION_FLAG_NONE, + + KBTS__OS2_SELECTION_FLAG_ITALIC = (1 << 0), + KBTS__OS2_SELECTION_FLAG_UNDERSCORE = (1 << 1), + KBTS__OS2_SELECTION_FLAG_NEGATIVE = (1 << 2), + KBTS__OS2_SELECTION_FLAG_OUTLINED = (1 << 3), + KBTS__OS2_SELECTION_FLAG_STRIKEOUT = (1 << 4), + KBTS__OS2_SELECTION_FLAG_BOLD = (1 << 5), + KBTS__OS2_SELECTION_FLAG_REGULAR = (1 << 6), + KBTS__OS2_SELECTION_FLAG_USE_TYPO_METRICS = (1 << 7), + KBTS__OS2_SELECTION_FLAG_WWS = (1 << 8), + KBTS__OS2_SELECTION_FLAG_OBLIQUE = (1 << 9), +}; + +# pragma pack(push, 1) + +typedef struct kbts__script_record +{ + kbts_u32 Tag; + kbts_u16 Offset; +} kbts__script_record; + +typedef struct kbts__script_list +{ + kbts_u16 Count; + // kbts__script_record Records[Count]; +} kbts__script_list; + +typedef struct kbts__ot_script +{ + kbts_u16 DefaultLangsysOffset; + kbts_u16 Count; + // kbts__langsys_record Records[Count]; +} kbts__ot_script; + +typedef struct kbts__langsys_record +{ + kbts_u32 Tag; + kbts_u16 Offset; +} kbts__langsys_record; + +typedef struct kbts__langsys +{ + kbts_u16 LookupOrderOffset; // reserved + kbts_u16 RequiredFeatureIndex; + kbts_u16 FeatureIndexCount; + // kbts_u16 FeatureIndices[FeatureIndexCount]; +} kbts__langsys; + +typedef struct kbts__feature_list +{ + kbts_u16 Count; + // kbts__feature_record Records[Count]; +} kbts__feature_list; + +typedef struct kbts__feature_record +{ + kbts_u32 Tag; + kbts_u16 Offset; +} kbts__feature_record; + +typedef struct kbts__feature +{ + kbts_u16 FeatureParamsOffset; + kbts_u16 LookupIndexCount; + // kbts_u16 LookupIndices[LookupIndexCount]; +} kbts__feature; + +typedef struct kbts_lookup_list +{ + kbts_u16 Count; + // kbts_u16 Offsets[Count]; +} kbts_lookup_list; + +// Lookups are used both in GSUB and GPOS. +// Type means either GSUB Lookup Type, or GPOS Lookup Type, depending on the table we are parsing. +typedef struct kbts__lookup +{ + kbts_u16 Type; + kbts_u16 Flag; + kbts_u16 SubtableCount; + // kbts_u16 SubtableOffsets[SubtableCount]; + // If USE_MARK_FILTERING_SET: + // kbts_u16 MarkFilteringSet; +} kbts__lookup; + +typedef struct kbts__coverage +{ + kbts_u16 Format; + kbts_u16 Count; + // If Format == 1: + // kbts_u16 GlyphArray[Count]; + // If Format == 2: + // kbts__range_record Ranges[Count]; +} kbts__coverage; + +typedef struct kbts__range_record +{ + kbts_u16 StartGlyphId; + kbts_u16 EndGlyphId; + kbts_u16 StartCoverageIndex; +} kbts__range_record; + +typedef struct kbts__class_definition_1 +{ + kbts_u16 Format; + kbts_u16 StartGlyphId; + kbts_u16 GlyphCount; + // kbts_u16 ClassValues[GlyphCount]; +} kbts__class_definition_1; + +typedef struct kbts__class_definition_2 +{ + kbts_u16 Format; + kbts_u16 Count; + // kbts__class_range_record Ranges[Count]; +} kbts__class_definition_2; + +typedef struct kbts__class_range_record +{ + kbts_u16 StartGlyphId; + kbts_u16 EndGlyphId; + kbts_u16 Class; +} kbts__class_range_record; + +typedef struct kbts__sequence_lookup_record +{ + kbts_u16 SequenceIndex; + kbts_u16 LookupListIndex; +} kbts__sequence_lookup_record; + +typedef struct kbts__sequence_rule +{ + kbts_u16 GlyphCount; + kbts_u16 SequenceLookupCount; + // kbts_u16 InputSequence[GlyphCount - 1]; + // kbts__sequence_lookup_record SequenceLookupRecords[SequenceLookupCount]; +} kbts__sequence_rule; + +typedef struct kbts__sequence_rule_set +{ + kbts_u16 Count; + // kbts_u16 Offsets[Count]; +} kbts__sequence_rule_set; + +typedef struct kbts__sequence_context_1 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 SeqRuleSetCount; + // kbts_u16 SeqRuleSetOffsets[]; +} kbts__sequence_context_1; + +typedef struct kbts__sequence_context_2 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ClassDefOffset; + kbts_u16 ClassSequenceRuleSetCount; + // kbts_u16 ClassSequenceRuleSetOffsets[ClassSequenceRuleSetCount]; May be NULL! +} kbts__sequence_context_2; + +typedef struct kbts__class_sequence_rule_set +{ + kbts_u16 Count; + // kbts_u16 ClassSequenceRuleOffsets[Count]; +} kbts__class_sequence_rule_set; + +typedef struct kbts__class_sequence_rule +{ + kbts_u16 GlyphCount; + kbts_u16 SequenceLookupCount; + // kbts_u16 InputSequence[GlyphCount-1]; + // kbts__sequence_lookup_record SequenceLookupRecords[SequenceLookupCount]; +} kbts__class_sequence_rule; + +typedef struct kbts__sequence_context_3 +{ + kbts_u16 Format; + kbts_u16 GlyphCount; + kbts_u16 SequenceLookupCount; + // kbts_u16 CoverageOffsets[GlyphCount]; + // kbts__sequence_lookup_record SequenceLookupRecords[SequenceLookupCount]; +} kbts__sequence_context_3; + +typedef struct kbts__chained_sequence_context_1 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ChainedSequenceRuleSetCount; + // kbts_u16 ChainedSequenceRuleSetOffsets[ChainedSequenceRuleSetCount]; +} kbts__chained_sequence_context_1; + +typedef struct kbts__chained_sequence_rule_set +{ + kbts_u16 Count; + // kbts_u16 Offsets[Count]; +} kbts__chained_sequence_rule_set; + +typedef struct kbts__chained_sequence_rule +{ + kbts_u16 BacktrackGlyphCount; + // kbts_u16 BacktrackSequence[BacktrackCount]; + // kbts_u16 InputGlyphCount; + // kbts_u16 InputSequence[InputGlyphCount - 1]; + // kbts_u16 LookaheadGlyphCount; + // kbts_u16 LookaheadSequence[LookaheadGlyphCount]; + // kbts_u16 SequenceLookupCount; + // kbts__sequence_lookup_record SequenceLookupRecords[SequenceLookupCount]; +} kbts__chained_sequence_rule; + +typedef struct kbts__chained_sequence_context_2 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 BacktrackClassDefOffset; + kbts_u16 InputClassDefOffset; + kbts_u16 LookaheadClassDefOffset; + kbts_u16 ChainedClassSequenceRuleSetCount; + // kbts_u16 ChainedClassSequenceRuleSetOffsets[ChainedClassSequenceRuleSetCount]; +} kbts__chained_sequence_context_2; + +typedef struct kbts__chained_sequence_context_3 +{ + kbts_u16 Format; + kbts_u16 BacktrackGlyphCount; + // kbts_u16 BacktrackCoverageOffsets[BacktrackGlyphCount]; + // kbts_u16 InputGlyphCount; + // kbts_u16 InputCoverageOffsets[InputGlyphCount]; + // kbts_u16 LookaheadGlyphCount; + // kbts_u16 LookaheadCoverageOffsets[LookaheadGlyphCount]; + // kbts_u16 SequenceLookupCount; + // kbts__sequence_lookup_record SequenceLookupRecords[SequenceLookupCount]; +} kbts__chained_sequence_context_3; + +typedef struct kbts__device +{ + union + { + struct + { + kbts_u16 StartSize; + kbts_u16 EndSize; + } Device; + + struct + { + kbts_u16 DeltaSetOuterIndex; + kbts_u16 DeltaSetInnerIndex; + } VariationIndex; + } U; + kbts_u16 DeltaFormat; + // kbts_u16 DeltaValue[]; +} kbts__device; + +typedef struct kbts__feature_variations +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u32 RecordCount; + // kbts__feature_variation_record Records[RecordCount]; +} kbts__feature_variations; + +typedef struct kbts__feature_variation_record +{ + kbts_u32 ConditionSetOffset; + kbts_u32 FeatureTableSubstitutionOffset; +} kbts__feature_variation_record; + +typedef struct kbts__condition_set +{ + kbts_u16 Count; + // kbts_u32 Offsets[Count]; +} kbts__condition_set; + +typedef struct kbts__condition_1 +{ + kbts_u16 Format; + kbts_u16 AxisIndex; + kbts_u16 FilterRangeMinValue; + kbts_u16 FilterRangeMaxValue; +} kbts__condition_1; + +typedef struct kbts__feature_table_substitution +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u16 Count; + // kbts__feature_table_substitution_record Records[Count]; +} kbts__feature_table_substitution; + +typedef struct kbts__feature_table_substitution_record +{ + kbts_u16 FeatureIndex; + kbts_u32 AlternateFeatureOffset; +} kbts__feature_table_substitution_record; + +typedef struct kbts__ttc_header +{ + kbts_u32 Magic; // ttcf + kbts_u16 Major; + kbts_u16 Minor; + kbts_u32 FontCount; + // kbts_u32 TableDirectoryOffsets[FontCount]; + + // If Major == 2: + // kbts_u32 DsigTag; + // kbts_u32 DsigLength; + // kbts_u32 DsigOffset; +} kbts__ttc_header; + +typedef struct kbts__table_directory +{ + kbts_u32 Version; + kbts_u16 TableCount; + kbts_u16 SearchRange; + kbts_u16 EntrySelector; + kbts_u16 RangeShift; + // kbts__table_record Records[TableCount]; +} kbts__table_directory; + +typedef struct kbts__table_record +{ + kbts_u32 Tag; + kbts_u32 Checksum; + kbts_u32 Offset; + kbts_u32 Length; +} kbts__table_record; + +typedef struct kbts__cmap +{ + kbts_u16 Version; + kbts_u16 TableCount; + // kbts__encoding_record Records[TableCount]; +} kbts__cmap; + +typedef struct kbts__encoding_record +{ + kbts_u16 PlatformId; + kbts_u16 EncodingId; + kbts_u32 SubtableOffset; +} kbts__encoding_record; + +/* Precedence rules for cmap tables: + - Tables are mutually exclusive, except for format 14 which completes the others. + - 8, 10, 12 > 0, 2, 4, 6 + - Formats 4, 12, 13, 14 are used today. + - Formats 4 and 12 are basic cmap tables. + - Format 13 is for fallback fonts that want to map lots of codepoints to a few fallback glyphs. + - Format 14 is for Unicode Variation Sequences. + - There can be Unicode and Windows tables with the same formats. In that case, we prefer the Windows tables. +*/ + +typedef struct kbts__cmap_0 +{ + kbts_u16 Format; + kbts_u16 Length; + kbts_u16 Language; + kbts_u8 GlyphIdArray[256]; +} kbts__cmap_0; + +typedef struct kbts__cmap_2 +{ + kbts_u16 Format; + kbts_u16 Length; + kbts_u16 Language; + kbts_u16 SubHeaderKeys[256]; + // kbts__sub_header SubHeaders[]; + // kbts_u16 GlyphIdArray[]; +} kbts__cmap_2; + +typedef struct kbts__sub_header +{ + kbts_u16 FirstCode; + kbts_u16 EntryCount; + kbts_s16 IdDelta; + kbts_u16 IdRangeOffset; +} kbts__sub_header; + +typedef struct kbts__cmap_4 +{ + kbts_u16 Format; + kbts_u16 Length; + kbts_u16 Language; + kbts_u16 SegmentCountTimesTwo; + kbts_u16 SearchRange; + kbts_u16 EntrySelector; + kbts_u16 RangeShift; + // kbts_u16 EndCode[SegmentCount]; + // kbts_u16 Reserved; + // kbts_u16 StartCode[SegmentCount]; + // kbts_s16 IdDelta[SegmentCount]; + // kbts_u16 IdRangeOffsets[SegmentCount]; + // kbts_u16 GlyphIdArray[]; +} kbts__cmap_4; + +typedef struct kbts__cmap_6 +{ + kbts_u16 Format; + kbts_u16 Length; + kbts_u16 Language; + kbts_u16 FirstCode; + kbts_u16 EntryCount; + // kbts_u16 GlyphIdArray[EntryCount]; +} kbts__cmap_6; + +typedef struct kbts__cmap_12_13 +{ + kbts_u16 Format; + kbts_u16 Reserved; + kbts_u32 Length; + kbts_u32 Language; + kbts_u32 GroupCount; + // kbts__sequential_map_group Groups[GroupCount]; +} kbts__cmap_12_13; + +typedef struct kbts__sequential_map_group +{ + kbts_u32 StartCharacterCode; + kbts_u32 EndCharacterCode; + kbts_u32 StartGlyphId; +} kbts__sequential_map_group; + +typedef struct kbts__cmap_14 +{ + kbts_u16 Format; + kbts_u32 Length; + kbts_u32 SelectorCount; + // kbts__variation_selector Selectors[SelectorCount]; +} kbts__cmap_14; + +typedef struct kbts__variation_selector +{ + kbts_u8 Selector[3]; + kbts_u32 DefaultUvsOffset; + kbts_u32 NonDefaultUvsOffset; +} kbts__variation_selector; + +typedef struct kbts__default_uvs +{ + kbts_u32 RangeCount; + // kbts__unicode_range Ranges[RangeCount]; +} kbts__default_uvs; + +typedef struct kbts__unicode_range +{ + kbts_u8 Start[3]; + kbts_u8 Count; +} kbts__unicode_range; + +typedef struct kbts__non_default_uvs +{ + kbts_u32 MappingCount; + // kbts__uvs_mapping Mappings[MappingCount]; +} kbts__non_default_uvs; + +typedef struct kbts__uvs_mapping +{ + kbts_u8 UnicodeValue[3]; + kbts_u16 GlyphId; +} kbts__uvs_mapping; + +typedef struct kbts__gsub_gpos +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u16 ScriptListOffset; + kbts_u16 FeatureListOffset; + kbts_u16 LookupListOffset; + kbts_u32 FeatureVariationsOffset; // Only present in v1.1 +} kbts__gsub_gpos; + +typedef struct kbts__single_substitution +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + union + { + kbts_s16 DeltaGlyphId; // Format == 1 + kbts_u16 GlyphCount; // Format == 2 + } DeltaOrCount; + // If Format == 2: + // kbts_u16 SubstituteGlyphIds[GlyphCount]; +} kbts__single_substitution; + +typedef struct kbts__multiple_substitution +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 SequenceCount; + // kbts_u16 SequenceOffsets[SequenceCount]; +} kbts__multiple_substitution; + +typedef struct kbts__sequence +{ + kbts_u16 GlyphCount; + // kbts_u16 SubstituteGlyphIds[GlyphCount]; +} kbts__sequence; + +typedef struct kbts__alternate_substitution +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 AlternateSetCount; + // kbts_u16 AlternateSetOffsets[AlternateSetCount]; +} kbts__alternate_substitution; + +typedef struct kbts__alternate_set +{ + kbts_u16 GlyphCount; + // kbts_u16 AlternateGlyphIds[GlyphCount]; +} kbts__alternate_set; + +typedef struct kbts__ligature_substitution +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 LigatureSetCount; + // kbts_u16 LigatureSetOffsets[LigatureSetCount]; +} kbts__ligature_substitution; + +typedef struct kbts__ligature_set +{ + kbts_u16 Count; + // kbts_u16 Offsets[Count]; +} kbts__ligature_set; + +typedef struct kbts__ligature +{ + kbts_u16 Glyph; + kbts_u16 ComponentCount; + // kbts_u16 ComponentGlyphIds[ComponentCount - 1]; +} kbts__ligature; + +typedef struct kbts__extension +{ + kbts_u16 Format; + kbts_u16 LookupType; + kbts_u32 Offset; +} kbts__extension; + +typedef struct kbts__reverse_chain_substitution +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 BacktrackGlyphCount; + // kbts_u16 BacktrackCoverageOffsets[BacktrackGlyphCount]; + // kbts_u16 LookaheadGlyphCount; + // kbts_u16 LookaheadCoverageOffsets[LookaheadGlyphCount]; + // kbts_u16 GlyphCount; + // kbts_u16 SubstituteGlyphIds[GlyphCount]; +} kbts__reverse_chain_substitution; + +typedef struct kbts__mark_glyph_sets +{ + kbts_u16 Format; + kbts_u16 MarkGlyphSetCount; + // kbts_u32 CoverageOffsets[MarkGlyphSetCount]; +} kbts__mark_glyph_sets; + +typedef struct kbts__gdef +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u16 ClassDefinitionOffset; // May be 0 + kbts_u16 AttachListOffset; // May be 0 + kbts_u16 LigatureCaretListOffset; // May be 0 + kbts_u16 MarkAttachmentClassDefinitionOffset; // May be 0 + kbts_u16 MarkGlyphSetsDefinitionOffset; // v1.2 and up; may be 0 + kbts_u32 ItemVariationStoreOffset; // v1.3 and up; may be 0 +} kbts__gdef; + +typedef struct kbts__anchor +{ + kbts_u16 Format; + kbts_s16 X; + kbts_s16 Y; + union + { + kbts_u16 AnchorPoint; // If Format == 2 + kbts_u16 XDeviceOffset; // If Format == 3 + } U; + kbts_u16 YDeviceOffset; // If Format == 3 +} kbts__anchor; + +typedef struct kbts__mark_record +{ + kbts_u16 Class; + kbts_u16 AnchorOffset; +} kbts__mark_record; + +typedef struct kbts__mark_array +{ + kbts_u16 Count; + // kbts__mark_record Records[Count]; +} kbts__mark_array; + +typedef struct kbts__single_adjustment_1 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ValueFormat; + // ValueRecord; +} kbts__single_adjustment_1; + +typedef struct kbts__single_adjustment_2 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ValueFormat; + kbts_u16 RecordCount; + // ValueRecord Records[RecordCount]; +} kbts__single_adjustment_2; + +typedef struct kbts__pair_value_record +{ + kbts_u16 SecondGlyph; + // ValueRecord Record1; + // ValueRecord Record2; +} kbts__pair_value_record; + +typedef struct kbts__pair_set +{ + kbts_u16 Count; + // kbts__pair_value_record PairValueRecords[Count]; +} kbts__pair_set; + +typedef struct kbts__pair_adjustment_1 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ValueFormat1; // May be 0 + kbts_u16 ValueFormat2; // May be 0 + kbts_u16 SetCount; + // kbts_u16 SetOffsets[PairSetCount]; +} kbts__pair_adjustment_1; + +typedef struct kbts__pair_adjustment_2 +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 ValueFormat1; // May be 0 + kbts_u16 ValueFormat2; // May be 0 + kbts_u16 ClassDefinition1Offset; + kbts_u16 ClassDefinition2Offset; + kbts_u16 Class1Count; + kbts_u16 Class2Count; + // ValueRecord ValueRecords[Class1Count][Class2Count][2]; +} kbts__pair_adjustment_2; + +typedef struct kbts__entry_exit +{ + kbts_u16 EntryAnchorOffset; + kbts_u16 ExitAnchorOffset; +} kbts__entry_exit; + +typedef struct kbts__cursive_attachment +{ + kbts_u16 Format; + kbts_u16 CoverageOffset; + kbts_u16 EntryExitCount; + // kbts__entry_exit Records[EntryExitCount]; +} kbts__cursive_attachment; + +typedef struct kbts__base_array +{ + kbts_u16 BaseCount; + // kbts_u16 BaseAnchorOffsets[BaseCount][MarkClassCount]; // May be NULL +} kbts__base_array; + +typedef struct kbts__mark_to_base_attachment +{ + kbts_u16 Format; + kbts_u16 MarkCoverageOffset; + kbts_u16 BaseCoverageOffset; + kbts_u16 MarkClassCount; + kbts_u16 MarkArrayOffset; + kbts_u16 BaseArrayOffset; +} kbts__mark_to_base_attachment; + +typedef struct kbts__ligature_attach +{ + kbts_u16 Count; + // kbts_u16 LigatureAnchorOffsets[Count][MarkClassCount]; // May be NULL +} kbts__ligature_attach; + +typedef struct kbts__ligature_array +{ + kbts_u16 Count; + // kbts_u16 LigatureAttachOffsets[Count]; +} kbts__ligature_array; + +typedef struct kbts__mark_to_ligature_attachment +{ + kbts_u16 Format; + kbts_u16 MarkCoverageOffset; + kbts_u16 LigatureCoverageOffset; + kbts_u16 MarkClassCount; + kbts_u16 MarkArrayOffset; + kbts_u16 LigatureArrayOffset; +} kbts__mark_to_ligature_attachment; + +typedef struct kbts__long_mtx +{ + kbts_u16 Advance; + kbts_s16 PreviousSideBearing; +} kbts__long_mtx; + +struct kbts__head +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u32 Revision; + kbts_u32 ChecksumAdjustment; + kbts_u32 MagicNumber; + kbts_u16 Flags; + kbts_u16 UnitsPerEm; + kbts_s64 CreatedTime; + kbts_s64 LastModifiedTime; + kbts_s16 XMin; + kbts_s16 YMin; + kbts_s16 XMax; + kbts_s16 YMax; + kbts_u16 MacStyle; // OS/2 style takes priority on Windows. + kbts_u16 LowestRecommendedPpem; + kbts_s16 DirectionHint; // Deprecated. Should ~always be 2. + kbts_s16 IndexToLocFormat; + kbts_s16 GlyphDataFormat; // Only 0 is defined. +}; + +typedef struct kbts__hea +{ + kbts_u16 Major; + kbts_u16 Minor; + + // According to Microsoft, these metrics are deprecated. + // The OS/2 table is the preferred way to get these, now. + kbts_s16 Ascent; + kbts_s16 Descent; + kbts_s16 LineGap; + + kbts_u16 MaxAdvance; + kbts_s16 MinPreviousSideBearing; + kbts_s16 MinNextSideBearing; + kbts_s16 MaxExtent; + + kbts_s16 CaretSlopeRise; + kbts_s16 CaretSlopeRun; + kbts_s16 CaretOffset; + + kbts_u16 Reserved[4]; + + kbts_s16 MetricDataFormat; + kbts_u16 MetricCount; +} kbts__hea; + +typedef struct kbts__os2 +{ + kbts_u16 Version; + kbts_s16 AverageCharacterWidth; + kbts_u16 WeightClass; + kbts_u16 WidthClass; + kbts_u16 Type; + kbts_s16 SubscriptXSize; + kbts_s16 SubscriptYSize; + kbts_s16 SubscriptXOffset; + kbts_s16 SubscriptYOffset; + kbts_s16 SuperscriptXSize; + kbts_s16 SuperscriptYSize; + kbts_s16 SuperscriptXOffset; + kbts_s16 SuperscriptYOffset; + kbts_s16 StrikeoutSize; + kbts_s16 StrikeoutPosition; + kbts_s16 FamilyClass; + kbts_u8 Panose[10]; + kbts_u32 UnicodeRange[4]; + kbts_u32 VendorId; + kbts_u16 Selection; + kbts_u16 FirstCharacterIndex; + kbts_u16 LastCharacterIndex; + + // Some version 0 fonts support this, others do not. + kbts_s16 TypoAscender; + kbts_s16 TypoDescender; + kbts_s16 TypoLineGap; + kbts_u16 WinAscent; + kbts_u16 WinDescent; + + // If Version >= 1: + kbts_u32 CodePageRange[2]; + + // If Version >= 2: + kbts_s16 Height; + kbts_s16 CapHeight; + kbts_u16 DefaultChar; + kbts_u16 BreakChar; + kbts_u16 MaxContext; + + // If Version >= 5: + kbts_u16 LowerOpticalPointSize; + kbts_u16 UpperOpticalPointSize; +} kbts__os2; + +typedef struct kbts__lang_tag_record +{ + kbts_u16 Length; + kbts_u16 LangTagOffset; +} kbts__lang_tag_record; + +typedef struct kbts__name_record +{ + kbts_u16 PlatformId; + kbts_u16 EncodingId; + kbts_u16 LanguageId; + kbts_u16 NameId; + kbts_u16 Length; + kbts_u16 StringOffset; +} kbts__name_record; + +typedef struct kbts__name +{ + kbts_u16 Version; + kbts_u16 Count; + kbts_u16 StringStorageOffset; + // kbts__name_record Records[Count]; + + // If Version == 1: + // kbts_u16 LangTagCount; + // kbts__lang_tag_record LangTags[LangTagCount]; +} kbts__name; + +typedef struct kbts__maxp +{ + kbts_u16 Major; + kbts_u16 Minor; + kbts_u16 GlyphCount; + + // If Major == 1: + kbts_u16 MaxPointCount; + kbts_u16 MaxContourCount; + kbts_u16 MaxCompositePointCount; + kbts_u16 MaxCompositeContourCount; + kbts_u16 MaxZoneCount; + kbts_u16 MaxTwilightPointCount; + kbts_u16 StorageAreaCount; + kbts_u16 FunctionDefinitionCount; + kbts_u16 InstructionDefinitionCount; + kbts_u16 MaximumStackDepth; + kbts_u16 MaximumInstructionSize; + kbts_u16 MaximumTopLevelComponentCount; + kbts_u16 MaximumComponentDepth; +} kbts__maxp; + +# pragma pack(pop) + +// +// Unpack functions for TTF structs. +// + +typedef struct kbts__script_pointer +{ + kbts_u32 Tag; + kbts__ot_script *Script; +} kbts__script_pointer; + +typedef struct kbts__langsys_pointer +{ + kbts_u32 Tag; + kbts__langsys *Langsys; +} kbts__langsys_pointer; + +typedef struct kbts__feature_pointer +{ + kbts_u32 Tag; + kbts__feature *Feature; +} kbts__feature_pointer; + +typedef struct kbts__feature_variation_pointer +{ + kbts__condition_set *ConditionSet; + kbts__feature_table_substitution *FeatureTableSubstitution; +} kbts__feature_variation_pointer; + +typedef struct kbts__feature_substitution_pointer +{ + kbts_u16 SubstitutedFeatureIndex; + kbts__feature *AlternateFeature; +} kbts__feature_substitution_pointer; + +typedef struct kbts__cmap_subtable_pointer +{ + kbts_u16 PlatformId; + kbts_u16 EncodingId; + kbts_u16 *Subtable; +} kbts__cmap_subtable_pointer; + +typedef struct kbts__unpacked_chained_sequence_rule +{ + kbts_u16 *Input; + kbts_u16 *Backtrack; + kbts_u16 *Lookahead; + kbts__sequence_lookup_record *Records; + + kbts_u16 BacktrackCount; + kbts_u16 InputCount; + kbts_u16 LookaheadCount; + kbts_u16 RecordCount; +} kbts__unpacked_chained_sequence_rule; + +typedef struct kbts__unpacked_chained_sequence_context_3 +{ + kbts_u16 *BacktrackCoverageOffsets; + kbts_u16 *InputCoverageOffsets; + kbts_u16 *LookaheadCoverageOffsets; + kbts__sequence_lookup_record *Records; + + kbts_u16 BacktrackCount; + kbts_u16 InputCount; + kbts_u16 LookaheadCount; + kbts_u16 RecordCount; +} kbts__unpacked_chained_sequence_context_3; + +typedef struct kbts__unpacked_reverse_chain_substitution +{ + kbts_u16 *BacktrackCoverageOffsets; + kbts_u16 *LookaheadCoverageOffsets; + kbts_u16 *SubstituteGlyphIds; + + kbts_u16 BacktrackCount; + kbts_u16 LookaheadCount; + kbts_u16 GlyphCount; +} kbts__unpacked_reverse_chain_substitution; + +typedef struct kbts__unpacked_value_record +{ + kbts_u16 Size; + + kbts_s16 PlacementX; + kbts_s16 PlacementY; + kbts_s16 AdvanceX; + kbts_s16 AdvanceY; + kbts__device *PlacementXDevice; + kbts__device *PlacementYDevice; + kbts__device *AdvanceXDevice; + kbts__device *AdvanceYDevice; +} kbts__unpacked_value_record; + +static kbts__unpacked_value_record kbts__UnpackValueRecord(void *Parent, kbts_u16 Format, kbts_u16 *Record) +{ + kbts__unpacked_value_record Result = KBTS__ZERO; + + kbts_u16 *At = Record; + + if(Format & KBTS__VALUE_FORMAT_X_PLACEMENT) + { + Result.PlacementX = (kbts_s16)*At++; + } + if(Format & KBTS__VALUE_FORMAT_Y_PLACEMENT) + { + Result.PlacementY = (kbts_s16)*At++; + } + if(Format & KBTS__VALUE_FORMAT_X_ADVANCE) + { + Result.AdvanceX = (kbts_s16)*At++; + } + if(Format & KBTS__VALUE_FORMAT_Y_ADVANCE) + { + Result.AdvanceY = (kbts_s16)*At++; + } + if(Format & KBTS__VALUE_FORMAT_X_PLACEMENT_DEVICE) + { + kbts_u16 Offset = *At++; + + if(Offset) + { + Result.PlacementXDevice = KBTS__POINTER_OFFSET(kbts__device, Parent, Offset); + } + } + if(Format & KBTS__VALUE_FORMAT_Y_PLACEMENT_DEVICE) + { + kbts_u16 Offset = *At++; + + if(Offset) + { + Result.PlacementYDevice = KBTS__POINTER_OFFSET(kbts__device, Parent, Offset); + } + } + if(Format & KBTS__VALUE_FORMAT_X_ADVANCE_DEVICE) + { + kbts_u16 Offset = *At++; + + if(Offset) + { + Result.AdvanceXDevice = KBTS__POINTER_OFFSET(kbts__device, Parent, Offset); + } + } + if(Format & KBTS__VALUE_FORMAT_Y_ADVANCE_DEVICE) + { + kbts_u16 Offset = *At++; + + if(Offset) + { + Result.AdvanceYDevice = KBTS__POINTER_OFFSET(kbts__device, Parent, Offset); + } + } + + Result.Size = (kbts_u16)(At - Record); + + return Result; +} + +static kbts__unpacked_reverse_chain_substitution kbts__UnpackReverseChainSubstitution(kbts__reverse_chain_substitution *Subst, int ByteSwap) +{ + kbts__unpacked_reverse_chain_substitution Result; + + Result.BacktrackCoverageOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + Result.BacktrackCount = Subst->BacktrackGlyphCount; + if(ByteSwap) + { + Result.BacktrackCount = kbts__ByteSwap16(Result.BacktrackCount); + } + + Result.LookaheadCoverageOffsets = Result.BacktrackCoverageOffsets + Result.BacktrackCount + 1; + Result.LookaheadCount = Result.BacktrackCoverageOffsets[Result.BacktrackCount]; + if(ByteSwap) + { + Result.LookaheadCount = kbts__ByteSwap16(Result.LookaheadCount); + } + + Result.SubstituteGlyphIds = Result.LookaheadCoverageOffsets + Result.LookaheadCount + 1; + Result.GlyphCount = Result.LookaheadCoverageOffsets[Result.LookaheadCount]; + if(ByteSwap) + { + Result.GlyphCount = kbts__ByteSwap16(Result.GlyphCount); + } + + return Result; +} + +static kbts__unpacked_chained_sequence_rule kbts__UnpackChainedSequenceRule(kbts__chained_sequence_rule *Rule, int ByteSwap) +{ + kbts__unpacked_chained_sequence_rule Result; + + Result.Backtrack = KBTS__POINTER_AFTER(kbts_u16, Rule); + Result.BacktrackCount = Rule->BacktrackGlyphCount; + if(ByteSwap) + { + Result.BacktrackCount = kbts__ByteSwap16(Result.BacktrackCount); + } + + Result.Input = Result.Backtrack + Result.BacktrackCount + 1; + Result.InputCount = Result.Backtrack[Result.BacktrackCount]; + if(ByteSwap) + { + Result.InputCount = kbts__ByteSwap16(Result.InputCount); + } + + Result.Lookahead = Result.Input + Result.InputCount; + Result.LookaheadCount = Result.Input[Result.InputCount - 1]; + if(ByteSwap) + { + Result.LookaheadCount = kbts__ByteSwap16(Result.LookaheadCount); + } + + Result.Records = (kbts__sequence_lookup_record *)(Result.Lookahead + Result.LookaheadCount + 1); + Result.RecordCount = Result.Lookahead[Result.LookaheadCount]; + if(ByteSwap) + { + Result.RecordCount = kbts__ByteSwap16(Result.RecordCount); + } + + return Result; +} + +static kbts__unpacked_chained_sequence_context_3 kbts__UnpackChainedSequenceContext3(kbts__chained_sequence_context_3 *Subst, int ByteSwap) +{ + kbts__unpacked_chained_sequence_context_3 Result; + + Result.BacktrackCoverageOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + Result.BacktrackCount = Subst->BacktrackGlyphCount; + if(ByteSwap) + { + Result.BacktrackCount = kbts__ByteSwap16(Result.BacktrackCount); + } + + Result.InputCoverageOffsets = Result.BacktrackCoverageOffsets + Result.BacktrackCount + 1; + Result.InputCount = Result.BacktrackCoverageOffsets[Result.BacktrackCount]; + if(ByteSwap) + { + Result.InputCount = kbts__ByteSwap16(Result.InputCount); + } + + Result.LookaheadCoverageOffsets = Result.InputCoverageOffsets + Result.InputCount + 1; + Result.LookaheadCount = Result.InputCoverageOffsets[Result.InputCount]; + if(ByteSwap) + { + Result.LookaheadCount = kbts__ByteSwap16(Result.LookaheadCount); + } + + Result.Records = (kbts__sequence_lookup_record *)(Result.LookaheadCoverageOffsets + Result.LookaheadCount + 1); + Result.RecordCount = Result.LookaheadCoverageOffsets[Result.LookaheadCount]; + if(ByteSwap) + { + Result.RecordCount = kbts__ByteSwap16(Result.RecordCount); + } + + return Result; +} + +typedef struct kbts__unpacked_lookup +{ + kbts_u16 *SubtableOffsets; + kbts__coverage *MarkFilteringSet; + kbts_u16 Type; + kbts_u16 Flags; + kbts_u16 SubtableCount; +} kbts__unpacked_lookup; + +static kbts__unpacked_lookup kbts__UnpackLookup(kbts__gdef *Gdef, kbts__lookup *Lookup) +{ + kbts__unpacked_lookup Result = KBTS__ZERO; + + Result.Type = Lookup->Type; + Result.Flags = Lookup->Flag; + Result.SubtableCount = Lookup->SubtableCount; + Result.SubtableOffsets = KBTS__POINTER_AFTER(kbts_u16, Lookup); + if(Result.Flags & KBTS__LOOKUP_FLAG_USE_MARK_FILTERING_SET) + { + kbts_u16 MarkFilteringSetIndex = Result.SubtableOffsets[Result.SubtableCount]; + if(Gdef && Gdef->MarkGlyphSetsDefinitionOffset) + { + kbts__mark_glyph_sets *MarkGlyphSets = KBTS__POINTER_OFFSET(kbts__mark_glyph_sets, Gdef, Gdef->MarkGlyphSetsDefinitionOffset); + if(MarkGlyphSets->MarkGlyphSetCount > MarkFilteringSetIndex) + { + kbts_u32 *CoverageOffsets = KBTS__POINTER_AFTER(kbts_u32, MarkGlyphSets); + Result.MarkFilteringSet = KBTS__POINTER_OFFSET(kbts__coverage, MarkGlyphSets, CoverageOffsets[MarkFilteringSetIndex]); + } + } + } + + return Result; +} + +static kbts__script_pointer kbts__GetScript(kbts__script_list *List, kbts_un Index) +{ + kbts__script_record *Records = (kbts__script_record *)(List + 1); + kbts__script_record *Record = &Records[Index]; + + kbts__script_pointer Result; + Result.Tag = Record->Tag; + Result.Script = (kbts__ot_script *)((char *)List + Record->Offset); + + return Result; +} + +static kbts__langsys *kbts__GetDefaultLangsys(kbts__ot_script *Script) +{ + kbts__langsys *Result = Script->DefaultLangsysOffset ? KBTS__POINTER_OFFSET(kbts__langsys, Script, Script->DefaultLangsysOffset) : 0; + return Result; +} + +static kbts__langsys_pointer kbts__GetLangsys(kbts__ot_script *Script, kbts_un Index) +{ + kbts__langsys_record *Records = (kbts__langsys_record *)(Script + 1); + kbts__langsys_record *Record = &Records[Index]; + + kbts__langsys_pointer Result; + Result.Tag = Record->Tag; + Result.Langsys = KBTS__POINTER_OFFSET(kbts__langsys, Script, Record->Offset); + return Result; +} + +static kbts__feature_pointer kbts__GetFeature(kbts__feature_list *List, kbts_un Index) +{ + kbts__feature_record *Records = (kbts__feature_record *)(List + 1); + kbts__feature_record *Record = &Records[Index]; + + kbts__feature_pointer Result; + Result.Tag = Record->Tag; + Result.Feature = KBTS__POINTER_OFFSET(kbts__feature, List, Record->Offset); + return Result; +} + +static kbts_lookup_list *kbts__GetLookupList(kbts__gsub_gpos *GsubGpos) +{ + kbts_lookup_list *Result = 0; + + if(GsubGpos) + { + Result = KBTS__POINTER_OFFSET(kbts_lookup_list, GsubGpos, GsubGpos->LookupListOffset); + } + + return Result; +} + +static kbts__lookup *kbts__GetLookup(kbts_lookup_list *List, kbts_un Index) +{ + KBTS_ASSERT(Index < List->Count); + kbts_u16 *Offsets = (kbts_u16 *)(List + 1); + kbts__lookup *Result = KBTS__POINTER_OFFSET(kbts__lookup, List, Offsets[Index]); + return Result; +} + +static kbts__sequence_rule_set *kbts__GetSequenceRuleSet(kbts__sequence_context_1 *Context, kbts_un Index) +{ + KBTS_ASSERT(Index < Context->SeqRuleSetCount); + kbts_u16 *Offsets = (kbts_u16 *)(Context + 1); + kbts_u16 Offset = Offsets[Index]; + + kbts__sequence_rule_set *Result = Offset ? KBTS__POINTER_OFFSET(kbts__sequence_rule_set, Context, Offsets[Index]) : 0; + return Result; +} + +static kbts__sequence_rule *kbts__GetSequenceRule(kbts__sequence_rule_set *Set, kbts_un Index) +{ + KBTS_ASSERT(Index < Set->Count); + kbts_u16 *Offsets = (kbts_u16 *)(Set + 1); + kbts__sequence_rule *Result = KBTS__POINTER_OFFSET(kbts__sequence_rule, Set, Offsets[Index]); + return Result; +} + +// A single class definition table can be used by multiple lookups, so it is possible +// (and valid) to get an out-of-bounds glyph class. +static kbts__class_sequence_rule_set *kbts__GetClassSequenceRuleSet(kbts__sequence_context_2 *Context, kbts_un Index) +{ + kbts__class_sequence_rule_set *Result = 0; + if(Index < Context->ClassSequenceRuleSetCount) + { + kbts_u16 *Offsets = (kbts_u16 *)(Context + 1); + Result = Offsets[Index] ? KBTS__POINTER_OFFSET(kbts__class_sequence_rule_set, Context, Offsets[Index]) : 0; + } + return Result; +} + +static kbts__class_sequence_rule *kbts__GetClassSequenceRule(kbts__class_sequence_rule_set *Set, kbts_un Index) +{ + KBTS_ASSERT(Index < Set->Count); + kbts_u16 *Offsets = (kbts_u16 *)(Set + 1); + kbts__class_sequence_rule *Result = KBTS__POINTER_OFFSET(kbts__class_sequence_rule, Set, Offsets[Index]); + return Result; +} + +static kbts__chained_sequence_rule_set *kbts__GetChainedSequenceRuleSet(kbts__chained_sequence_context_1 *Context, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Context + 1); + kbts__chained_sequence_rule_set *Result = Offsets[Index] ? KBTS__POINTER_OFFSET(kbts__chained_sequence_rule_set, Context, Offsets[Index]) : 0; + return Result; +} + +static kbts__chained_sequence_rule *kbts__GetChainedSequenceRule(kbts__chained_sequence_rule_set *Set, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Set + 1); + kbts__chained_sequence_rule *Result = KBTS__POINTER_OFFSET(kbts__chained_sequence_rule, Set, Offsets[Index]); + return Result; +} + +static kbts__chained_sequence_rule_set *kbts__GetChainedClassSequenceRuleSet(kbts__chained_sequence_context_2 *Context, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Context + 1); + kbts_u16 Offset = Offsets[Index]; + kbts__chained_sequence_rule_set *Result = Offset ? KBTS__POINTER_OFFSET(kbts__chained_sequence_rule_set, Context, Offset) : NULL; + return Result; +} + +static kbts__chained_sequence_rule *kbts__GetChainedClassSequenceRule(kbts__chained_sequence_rule_set *Set, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Set + 1); + kbts__chained_sequence_rule *Result = KBTS__POINTER_OFFSET(kbts__chained_sequence_rule, Set, Offsets[Index]); + return Result; +} + +#if 0 // @Incomplete +static kbts__feature_variation_pointer kbts__GetFeatureVariation(kbts__feature_variations *Variations, kbts_un Index) +{ + kbts__feature_variation_record *Records = (kbts__feature_variation_record *)(Variations + 1); + kbts__feature_variation_record *Record = &Records[Index]; + + kbts__feature_variation_pointer Result; + Result.ConditionSet = KBTS__POINTER_OFFSET(kbts__condition_set, Variations, Record->ConditionSetOffset); + Result.FeatureTableSubstitution = KBTS__POINTER_OFFSET(kbts__feature_table_substitution, Variations, Record->FeatureTableSubstitutionOffset); + return Result; +} + +static kbts__condition_1 *kbts__GetCondition(kbts__condition_set *Set, kbts_un Index) +{ + kbts_u32 *Offsets = (kbts_u32 *)(Set + 1); + kbts__condition_1 *Result = KBTS__POINTER_OFFSET(kbts__condition_1, Set, Offsets[Index]); + return Result; +} + +static kbts__feature_substitution_pointer kbts__GetFeatureSubstitution(kbts__feature_table_substitution *Table, kbts_un Index) +{ + kbts__feature_table_substitution_record *Records = (kbts__feature_table_substitution_record *)(Table + 1); + kbts__feature_table_substitution_record *Record = &Records[Index]; + + kbts__feature_substitution_pointer Result; + Result.SubstitutedFeatureIndex = Record->FeatureIndex; + Result.AlternateFeature = KBTS__POINTER_OFFSET(kbts__feature, Table, Record->AlternateFeatureOffset); + return Result; +} +#endif + +static kbts__cmap_subtable_pointer kbts__GetCmapSubtable(kbts__cmap *Cmap, kbts_un Index) +{ + kbts__encoding_record *Records = (kbts__encoding_record *)(Cmap + 1); + kbts__encoding_record *Record = &Records[Index]; + + kbts__cmap_subtable_pointer Result; + Result.PlatformId = Record->PlatformId; + Result.EncodingId = Record->EncodingId; + Result.Subtable = KBTS__POINTER_OFFSET(kbts_u16, Cmap, Record->SubtableOffset); + + return Result; +} + +static kbts__sequence *kbts__GetSequence(kbts__multiple_substitution *Subst, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Subst + 1); + kbts__sequence *Result = KBTS__POINTER_OFFSET(kbts__sequence, Subst, Offsets[Index]); + return Result; +} + +static kbts__alternate_set *kbts__GetAlternateSet(kbts__alternate_substitution *Subst, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Subst + 1); + kbts__alternate_set *Result = KBTS__POINTER_OFFSET(kbts__alternate_set, Subst, Offsets[Index]); + return Result; +} + +static kbts__ligature_set *kbts__GetLigatureSet(kbts__ligature_substitution *Subst, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Subst + 1); + kbts__ligature_set *Result = KBTS__POINTER_OFFSET(kbts__ligature_set, Subst, Offsets[Index]); + return Result; +} + +static kbts__ligature *kbts__GetLigature(kbts__ligature_set *Set, kbts_un Index) +{ + kbts_u16 *Offsets = (kbts_u16 *)(Set + 1); + kbts__ligature *Result = KBTS__POINTER_OFFSET(kbts__ligature, Set, Offsets[Index]); + return Result; +} + +static kbts__mark_record *kbts__GetMarkRecord(kbts__mark_array *Array, kbts_un Index) +{ + kbts__mark_record *Records = KBTS__POINTER_AFTER(kbts__mark_record, Array); + kbts__mark_record *Result = &Records[Index]; + return Result; +} + +static kbts__ligature_attach *kbts__GetLigatureAttach(kbts__ligature_array *Array, kbts_un Index) +{ + kbts_u16 *Offsets = KBTS__POINTER_AFTER(kbts_u16, Array); + kbts__ligature_attach *Result = KBTS__POINTER_OFFSET(kbts__ligature_attach, Array, Offsets[Index]); + return Result; +} + +static kbts__anchor *kbts__GetLigatureAttachAnchor(kbts__mark_to_ligature_attachment *Adjust, kbts__ligature_attach *Attach, kbts_u16 MarkClass, kbts_un ComponentIndex) +{ + kbts_u16 *Offsets = KBTS__POINTER_AFTER(kbts_u16, Attach); + kbts_u16 Offset = Offsets[ComponentIndex * Adjust->MarkClassCount + MarkClass]; + + kbts__anchor *Result = 0; + if(Offset) + { + Result = KBTS__POINTER_OFFSET(kbts__anchor, Attach, Offset); + } + + return Result; +} + +typedef struct kbts__mark_info +{ + kbts__mark_array *Array; + kbts__mark_record *Record; + kbts__anchor *Anchor; +} kbts__mark_info; + +static kbts__mark_info kbts__GetMarkInfo(void *Subtable, kbts_un SubtableOffsetToMarkArray, kbts_un CoverageIndex) +{ + kbts__mark_info Result = KBTS__ZERO; + + Result.Array = KBTS__POINTER_OFFSET(kbts__mark_array, Subtable, SubtableOffsetToMarkArray); + Result.Record = kbts__GetMarkRecord(Result.Array, CoverageIndex); + Result.Anchor = KBTS__POINTER_OFFSET(kbts__anchor, Result.Array, Result.Record->AnchorOffset); + + return Result; +} + +// +// +// + +typedef struct kbts__byteswap_context +{ + char *FileBase; + char *FileEnd; + kbts_u32 *Pointers; + kbts_un PointerCapacity; + kbts_un PointerCount; + + int Error; +} kbts__byteswap_context; + +static int kbts__ByteSwapArray16Context(kbts_u16 *Array, kbts_un Count, kbts__byteswap_context *Context) +{ + int Result = kbts__ByteSwapArray16(Array, Count, Context->FileEnd); + Context->Error |= !Result; + return Result; +} + +static int kbts__ByteSwapArray32Context(kbts_u32 *Array, kbts_un Count, kbts__byteswap_context *Context) +{ + int Result = kbts__ByteSwapArray32(Array, Count, Context->FileEnd); + Context->Error |= !Result; + return Result; +} + +typedef struct kbts__cover_glyph_result +{ + int Valid; + kbts_u32 Index; +} kbts__cover_glyph_result; + +static int kbts__LookupBeginsWithCoverage(kbts_shaping_table ShapingTable, kbts_u16 LookupType, kbts_u16 Format) +{ + int Result = 0; + if(ShapingTable == KBTS_SHAPING_TABLE_GSUB) + { + Result = (LookupType != 7) && (Format != 3); + } + else + { + Result = (LookupType != 9) && (Format != 3); + } + return Result; +} + +// Except for lookup tables 5.3, 6.3 and 7, all tables begin with (kbts_u16 Format, kbts_u16 CoverageOffset). +KBTS_INLINE int kbts__GsubLookupBeginsWithCoverage(kbts_u16 LookupType, kbts_u16 Format) +{ + int Result = kbts__LookupBeginsWithCoverage(KBTS_SHAPING_TABLE_GSUB, LookupType, Format); + return Result; +} + +KBTS_INLINE int kbts__GposLookupBeginsWithCoverage(kbts_u16 LookupType, kbts_u16 Format) +{ + int Result = kbts__LookupBeginsWithCoverage(KBTS_SHAPING_TABLE_GPOS, LookupType, Format); + return Result; +} + +static int kbts__AlreadyVisited(kbts__byteswap_context *Context, void *Pointer) +{ + int Result = !Pointer || Context->Error; + + if(!Result) + { + kbts_u32 *Pointers = Context->Pointers; + kbts_u32 Pointer32 = KBTS__POINTER_DIFF32(Pointer, Context->FileBase); + + kbts_un Index = 0; + if(Context->PointerCount) + { + kbts_un PointerCount = Context->PointerCount; + if(PointerCount) + { + while(PointerCount > 1) + { + kbts_un HalfCount = PointerCount / 2; + Index = (Pointers[Index + HalfCount - 1] < Pointer32) ? (Index + HalfCount) : Index; + PointerCount -= HalfCount; + } + Result = (Pointer32 == Pointers[Index]); + } + } + + if(!Result && (Context->PointerCount < Context->PointerCapacity)) + { + while((Index < Context->PointerCount) && (Pointers[Index] < Pointer32)) ++Index; + + for(kbts_un GrowIndex = Context->PointerCount; GrowIndex > Index; --GrowIndex) + { + Pointers[GrowIndex] = Pointers[GrowIndex - 1]; + } + Pointers[Index] = Pointer32; + Context->PointerCount += 1; + } + } + + return Result; +} + +static void kbts__ByteSwapFeature(kbts__byteswap_context *Context, kbts__feature *Feature) +{ + if(!kbts__AlreadyVisited(Context, Feature)) + { + kbts_u16 *LookupIndices = KBTS__POINTER_AFTER(kbts_u16, Feature); + Context->Error |= !kbts__ByteSwapArray16(&Feature->FeatureParamsOffset, 2, Context->FileEnd); + Context->Error |= !kbts__ByteSwapArray16(LookupIndices, Feature->LookupIndexCount, Context->FileEnd); + + // We require lookup indices to be sorted per feature for the lookup application order to match Harfbuzz. + // Lookup indices are _typically_ sorted per feature, but we can't assume it is always the case. + kbts_un LookupIndexCount = Feature->LookupIndexCount; + KBTS__FOR(Iter, 0, LookupIndexCount) + { + KBTS__FOR(IndexIndex, 1, LookupIndexCount) + { + kbts_u16 Left = LookupIndices[IndexIndex - 1]; + kbts_u16 Right = LookupIndices[IndexIndex]; + + if(Left > Right) + { + LookupIndices[IndexIndex - 1] = Right; + LookupIndices[IndexIndex] = Left; + } + } + } + } + +# ifdef KBTS_DUMP + kbts_u16 *LookupIndices = KBTS__POINTER_AFTER(kbts_u16, Feature); + KBTS__FOR(LookupIndexIndex, 0, Feature->LookupIndexCount) + { + KBTS_DUMPF(" Lookup index %u\n", LookupIndices[LookupIndexIndex]); + } +# endif +} + +static void kbts__ByteSwapGsubGposCommon(kbts__byteswap_context *Context, kbts__gsub_gpos *Header) +{ + kbts__ByteSwapArray16Context(&Header->Major, 5, Context); + + if(Header->Minor == 1) + { + Header->FeatureVariationsOffset = kbts__ByteSwap32(Header->FeatureVariationsOffset); + } + + kbts__script_list *ScriptList = KBTS__POINTER_OFFSET(kbts__script_list, Header, Header->ScriptListOffset); + if(!kbts__AlreadyVisited(Context, ScriptList)) + { + ScriptList->Count = kbts__ByteSwap16(ScriptList->Count); + + kbts__script_record *ScriptRecords = KBTS__POINTER_AFTER(kbts__script_record, ScriptList); + KBTS__FOR(It, 0, ScriptList->Count) + { + kbts__script_record *Record = &ScriptRecords[It]; + + Record->Offset = kbts__ByteSwap16(Record->Offset); + + KBTS_DUMPF("Script %.4s\n", (char *)&Record->Tag); + + kbts__ot_script *Script = KBTS__POINTER_OFFSET(kbts__ot_script, ScriptList, Record->Offset); + if(!kbts__AlreadyVisited(Context, Script)) + { + Script->DefaultLangsysOffset = kbts__ByteSwap16(Script->DefaultLangsysOffset); + Script->Count = kbts__ByteSwap16(Script->Count); + + kbts__langsys *DefaultLangsys = kbts__GetDefaultLangsys(Script); + + if(DefaultLangsys && !kbts__AlreadyVisited(Context, DefaultLangsys)) + { + kbts__ByteSwapArray16Context(&DefaultLangsys->LookupOrderOffset, 3, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, DefaultLangsys), DefaultLangsys->FeatureIndexCount, Context); + } + + kbts__langsys_record *LangsysRecords = KBTS__POINTER_AFTER(kbts__langsys_record, Script); + KBTS__FOR(LangsysIndex, 0, Script->Count) + { + kbts__langsys_record *LangsysRecord = &LangsysRecords[LangsysIndex]; + + LangsysRecord->Offset = kbts__ByteSwap16(LangsysRecord->Offset); + + kbts__langsys *Langsys = KBTS__POINTER_OFFSET(kbts__langsys, Script, LangsysRecord->Offset); + if(!kbts__AlreadyVisited(Context, Langsys)) + { + kbts__ByteSwapArray16Context(&Langsys->LookupOrderOffset, 3, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Langsys), Langsys->FeatureIndexCount, Context); + } + } + +# ifdef KBTS_DUMP + if(DefaultLangsys) + { + KBTS_DUMPF(" Default langsys @ %zu\n", (char *)DefaultLangsys - Context->FileBase); + KBTS_DUMPF(" Lookup order offset %u\n", DefaultLangsys->LookupOrderOffset); + KBTS_DUMPF(" Required feature %u\n", DefaultLangsys->RequiredFeatureIndex); + kbts_u16 *FeatureIndices = KBTS__POINTER_AFTER(kbts_u16, DefaultLangsys); + KBTS__FOR(FeatureIndexIndex, 0, DefaultLangsys->FeatureIndexCount) + { + KBTS_DUMPF(" Feature %u\n", FeatureIndices[FeatureIndexIndex]); + } + } + + KBTS__FOR(LangsysIndex, 0, Script->Count) + { + kbts__langsys_record *LangsysRecord = &LangsysRecords[LangsysIndex]; + kbts__langsys *Langsys = KBTS__POINTER_OFFSET(kbts__langsys, Script, LangsysRecord->Offset); + KBTS_DUMPF(" Langsys %.4s @ %zu\n", (char *)&LangsysRecord->Tag, (char *)Script + LangsysRecord->Offset - Context->FileBase); + KBTS_DUMPF(" Lookup order offset %u\n" + " Required feature %u\n", + Langsys->LookupOrderOffset, Langsys->RequiredFeatureIndex); + kbts_u16 *FeatureIndices = KBTS__POINTER_AFTER(kbts_u16, Langsys); + KBTS__FOR(FeatureIndexIndex, 0, Langsys->FeatureIndexCount) + { + KBTS_DUMPF(" Feature %u\n", FeatureIndices[FeatureIndexIndex]); + } + } +# endif + } + } + + // @Incomplete + if((Header->Minor == 1) && Header->FeatureVariationsOffset) + { + kbts__feature_variations *FeatureVariations = KBTS__POINTER_OFFSET(kbts__feature_variations, Header, Header->FeatureVariationsOffset); + + if(!kbts__AlreadyVisited(Context, FeatureVariations)) + { + kbts__ByteSwapArray16Context(&FeatureVariations->Major, 2, Context); + FeatureVariations->RecordCount = kbts__ByteSwap32(FeatureVariations->RecordCount); + + kbts__feature_variation_record *Records = KBTS__POINTER_AFTER(kbts__feature_variation_record, FeatureVariations); + KBTS__FOR(VariationIndex, 0, FeatureVariations->RecordCount) + { + kbts__feature_variation_record *Record = &Records[VariationIndex]; + + kbts__ByteSwapArray32Context(&Record->ConditionSetOffset, 2, Context); + + kbts__condition_set *Set = KBTS__POINTER_OFFSET(kbts__condition_set, FeatureVariations, Record->ConditionSetOffset); + + if(!kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + + kbts_u32 *ConditionOffsets = KBTS__POINTER_AFTER(kbts_u32, Set); + kbts__ByteSwapArray32Context(ConditionOffsets, Set->Count, Context); + + KBTS__FOR(ConditionIndex, 0, Set->Count) + { + kbts__condition_1 *Condition = KBTS__POINTER_OFFSET(kbts__condition_1, Set, ConditionOffsets[ConditionIndex]); + + if(!kbts__AlreadyVisited(Context, Condition)) + { + kbts__ByteSwapArray16Context(&Condition->Format, 4, Context); + } + } + + // @Incomplete + kbts__feature_table_substitution *FeatureSubst = KBTS__POINTER_OFFSET(kbts__feature_table_substitution, FeatureVariations, Record->FeatureTableSubstitutionOffset); + + if(!kbts__AlreadyVisited(Context, FeatureSubst)) + { + kbts__ByteSwapArray16Context(&FeatureSubst->Major, 3, Context); + + kbts__feature_table_substitution_record *SubstRecords = KBTS__POINTER_AFTER(kbts__feature_table_substitution_record, FeatureSubst); + KBTS__FOR(SubstRecordIndex, 0, FeatureSubst->Count) + { + kbts__feature_table_substitution_record *SubstRecord = &SubstRecords[SubstRecordIndex]; + SubstRecord->FeatureIndex = kbts__ByteSwap16(SubstRecord->FeatureIndex); + SubstRecord->AlternateFeatureOffset = kbts__ByteSwap32(SubstRecord->AlternateFeatureOffset); + + kbts__feature *Feature = KBTS__POINTER_OFFSET(kbts__feature, FeatureSubst, SubstRecord->AlternateFeatureOffset); + kbts__ByteSwapFeature(Context, Feature); + } + } + } + } + } + } + } + + kbts__feature_list *FeatureList = KBTS__POINTER_OFFSET(kbts__feature_list, Header, Header->FeatureListOffset); + if(!kbts__AlreadyVisited(Context, FeatureList)) + { + FeatureList->Count = kbts__ByteSwap16(FeatureList->Count); + kbts__feature_record *FeatureRecords = KBTS__POINTER_AFTER(kbts__feature_record, FeatureList); + KBTS__FOR(FeatureRecordIndex, 0, FeatureList->Count) + { + kbts__feature_record *FeatureRecord = &FeatureRecords[FeatureRecordIndex]; + + KBTS_DUMPF("Feature %llu %.4s\n", FeatureRecordIndex, (char *)&FeatureRecord->Tag); + + if(!kbts__AlreadyVisited(Context, FeatureRecord)) + { + FeatureRecord->Offset = kbts__ByteSwap16(FeatureRecord->Offset); + + kbts__feature *Feature = KBTS__POINTER_OFFSET(kbts__feature, FeatureList, FeatureRecord->Offset); + kbts__ByteSwapFeature(Context, Feature); + } + } + } +} + +static int kbts__ByteSwapLookup(kbts__byteswap_context *Context, kbts__lookup *Lookup) +{ + int Result = 0; + + if(!kbts__AlreadyVisited(Context, Lookup)) + { + Result = 1; + + kbts__ByteSwapArray16Context(&Lookup->Type, 3, Context); + kbts_u16 *SubtableOffsets = KBTS__POINTER_AFTER(kbts_u16, Lookup); + + kbts_un U16Count = Lookup->SubtableCount; + if(Lookup->Flag & KBTS__LOOKUP_FLAG_USE_MARK_FILTERING_SET) + { + U16Count += 1; + } + kbts__ByteSwapArray16Context(SubtableOffsets, U16Count, Context); + } + + return Result; +} + +static void kbts__ByteSwapCoverage(kbts__byteswap_context *Context, kbts__coverage *Coverage) +{ + if(!kbts__AlreadyVisited(Context, Coverage)) + { + kbts__ByteSwapArray16Context(&Coverage->Format, 2, Context); + + kbts_un U16Count = 0; + if(Coverage->Format == 1) + { + U16Count = Coverage->Count; + } + else if(Coverage->Format == 2) + { + U16Count = Coverage->Count * 3; + } + + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Coverage), U16Count, Context); + } +} + +static void kbts__ByteSwapAnchor(kbts__byteswap_context *Context, kbts__anchor *Anchor) +{ + if(!kbts__AlreadyVisited(Context, Anchor)) + { + Anchor->Format = kbts__ByteSwap16(Anchor->Format); + + kbts_un U16Count = 2; + if(Anchor->Format == 2) + { + U16Count = 3; + } + else if(Anchor->Format == 3) + { + U16Count = 4; + } + + kbts__ByteSwapArray16Context((kbts_u16 *)&Anchor->X, U16Count, Context); + } +} + +static void kbts__ByteSwapBaseArray(kbts__byteswap_context *Context, kbts_u16 MarkClassCount, kbts__base_array *Array) +{ + if(!kbts__AlreadyVisited(Context, Array)) + { + Array->BaseCount = kbts__ByteSwap16(Array->BaseCount); + + kbts_u16 *BaseAnchorOffsets = KBTS__POINTER_AFTER(kbts_u16, Array); + kbts__ByteSwapArray16Context(BaseAnchorOffsets, Array->BaseCount * MarkClassCount, Context); + + KBTS__FOR(OffsetIndex, 0, (kbts_un)Array->BaseCount * MarkClassCount) + { + kbts_u16 Offset = BaseAnchorOffsets[OffsetIndex]; + + if(Offset) + { + kbts__ByteSwapAnchor(Context, KBTS__POINTER_OFFSET(kbts__anchor, Array, Offset)); + } + } + } +} + +static void kbts__ByteSwapDevice(kbts__byteswap_context *Context, kbts__device *Device) +{ + if(!kbts__AlreadyVisited(Context, Device)) + { + kbts__ByteSwapArray16Context(&Device->U.Device.StartSize, 3, Context); + + if(Device->DeltaFormat <= 3) + { + // @Incomplete + } + } +} + +static kbts__unpacked_value_record kbts_ByteSwapValueRecord(kbts__byteswap_context *Context, void *Parent, kbts_u16 ValueFormat, kbts_u16 *Record) +{ + kbts__unpacked_value_record Result = KBTS__ZERO; + + if(ValueFormat) + { + kbts_un U16Count = kbts__PopCount32(ValueFormat); + + kbts__ByteSwapArray16Context(Record, U16Count, Context); + + Result = kbts__UnpackValueRecord(Parent, ValueFormat, Record); + + kbts__ByteSwapDevice(Context, Result.PlacementXDevice); + kbts__ByteSwapDevice(Context, Result.PlacementYDevice); + kbts__ByteSwapDevice(Context, Result.AdvanceXDevice); + kbts__ByteSwapDevice(Context, Result.AdvanceYDevice); + } + + return Result; +} + +static void kbts__ByteSwapMarkArray(kbts__byteswap_context *Context, kbts__mark_array *MarkArray) +{ + if(!kbts__AlreadyVisited(Context, MarkArray)) + { + MarkArray->Count = kbts__ByteSwap16(MarkArray->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, MarkArray), MarkArray->Count * 2, Context); + + kbts__mark_record *MarkRecords = KBTS__POINTER_AFTER(kbts__mark_record, MarkArray); + KBTS__FOR(MarkRecordIndex, 0, MarkArray->Count) + { + kbts__mark_record *MarkRecord = &MarkRecords[MarkRecordIndex]; + + kbts__ByteSwapAnchor(Context, KBTS__POINTER_OFFSET(kbts__anchor, MarkArray, MarkRecord->AnchorOffset)); + } + } +} + +static void kbts__ByteSwapChainedSequenceRuleSet(kbts__byteswap_context *Context, kbts__chained_sequence_rule_set *Set) +{ + if(Set && !kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Set), Set->Count, Context); + + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedSequenceRule(Set, RuleIndex); + + if(!kbts__AlreadyVisited(Context, Rule)) + { + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 1); + + kbts_un U16Count = Unpacked.BacktrackCount + Unpacked.InputCount + Unpacked.LookaheadCount + Unpacked.RecordCount * 2 + 3; + kbts__ByteSwapArray16Context(&Rule->BacktrackGlyphCount, U16Count, Context); + } + } + } +} + +#ifdef KBTS_DUMP +static void kbts__DumpClassDefinition(kbts_u16 *Base) +{ + if(*Base == 1) + { + kbts__class_definition_1 *ClassDef = (kbts__class_definition_1 *)Base; + kbts_u16 *ClassValues = KBTS__POINTER_AFTER(kbts_u16, ClassDef); + KBTS__FOR(GlyphIndex, 0, ClassDef->GlyphCount) + { + KBTS_DUMPF("%llx -> %u\n", ClassDef->StartGlyphId + GlyphIndex, ClassValues[GlyphIndex]); + } + } + else if(*Base == 2) + { + kbts__class_definition_2 *ClassDef = (kbts__class_definition_2 *)Base; + kbts__class_range_record *Ranges = KBTS__POINTER_AFTER(kbts__class_range_record, ClassDef); + KBTS__FOR(RangeIndex, 0, ClassDef->Count) + { + kbts__class_range_record *Range = &Ranges[RangeIndex]; + + KBTS_DUMPF("[%x..%x] -> %u\n", Range->StartGlyphId, Range->EndGlyphId, Range->Class); + } + } +} +#endif + +static void kbts__ByteSwapClassDefinition(kbts__byteswap_context *Context, kbts_u16 *Base) +{ + if(!kbts__AlreadyVisited(Context, Base)) + { + *Base = kbts__ByteSwap16(*Base); + + if(*Base == 1) + { + kbts__class_definition_1 *ClassDef = (kbts__class_definition_1 *)Base; + kbts__ByteSwapArray16Context(&ClassDef->StartGlyphId, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, ClassDef), ClassDef->GlyphCount, Context); + } + else if(*Base == 2) + { + kbts__class_definition_2 *ClassDef = (kbts__class_definition_2 *)Base; + ClassDef->Count = kbts__ByteSwap16(ClassDef->Count); + + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, ClassDef), ClassDef->Count * 3, Context); + } + } +} + +typedef struct kbts__glyph_class_from_table_result +{ + int Found; + kbts_u16 Class; +} kbts__glyph_class_from_table_result; + +static kbts__glyph_class_from_table_result kbts__GlyphClassFromTable(kbts_u16 *ClassDefinitionBase, kbts_un Id) +{ + kbts__glyph_class_from_table_result Result = KBTS__ZERO; + + // From the Microsoft docs: + // There is one offset to a ChainedClassSequenceRuleSet subtable for each class defined in the input sequence + // class definition table. The offsets are listed in class value order. + // This means that we do not actually care what the class _values_ are. We only care about the classes' relative + // values. + // Also from the Microsoft docs, about class definition tables: + // A class definition table (ClassDef) assigns glyphs into classes, beginning with Class 1, then Class 2, and so + // on. All glyphs not assigned to a class fall into Class 0. + // So, we should be able to pretty reliably just subtract 1 from the class to get. + + if(*ClassDefinitionBase == 1) + { + kbts__class_definition_1 *ClassDef = (kbts__class_definition_1 *)ClassDefinitionBase; + kbts_u16 *GlyphClasses = KBTS__POINTER_AFTER(kbts_u16, ClassDef); + + kbts_un Offset = Id - ClassDef->StartGlyphId; + if(Offset < ClassDef->GlyphCount) + { + Result.Class = GlyphClasses[Offset]; + Result.Found = 1; + } + } + else if(*ClassDefinitionBase == 2) + { + kbts__class_definition_2 *ClassDef = (kbts__class_definition_2 *)ClassDefinitionBase; + kbts__class_range_record *Ranges = KBTS__POINTER_AFTER(kbts__class_range_record, ClassDef); + + kbts_un RangeCount = ClassDef->Count; + if(RangeCount) + { + while(RangeCount > 1) + { + kbts_un HalfCount = RangeCount / 2; + Ranges = (Ranges[HalfCount - 1].EndGlyphId < Id) ? (Ranges + HalfCount) : Ranges; + RangeCount -= HalfCount; + } + if((Id >= Ranges->StartGlyphId) && (Id <= Ranges->EndGlyphId)) + { + Result.Class = Ranges->Class; + Result.Found = 1; + } + } + } + + return Result; +} + +static kbts__cover_glyph_result kbts__CoverGlyph(kbts__coverage *Coverage, kbts_u32 GlyphId) +{ + KBTS_INSTRUMENT_FUNCTION_BEGIN; + kbts__cover_glyph_result Result = KBTS__ZERO; + kbts_un Count = Coverage->Count; + + if(Count) + { + if(Coverage->Format == 1) + { + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Coverage); + + while(Count > 1) + { + kbts_un HalfCount = Count / 2; + GlyphIds = (GlyphIds[HalfCount - 1] < GlyphId) ? (GlyphIds + HalfCount) : GlyphIds; + Count -= HalfCount; + } + + if(GlyphId == *GlyphIds) + { + Result.Valid = 1; + Result.Index = (kbts_u32)(GlyphIds - KBTS__POINTER_AFTER(kbts_u16, Coverage)); + } + } + else if(Coverage->Format == 2) + { + kbts__range_record *Ranges = KBTS__POINTER_AFTER(kbts__range_record, Coverage); + + while(Count > 1) + { + kbts_un HalfCount = Count / 2; + Ranges = (Ranges[HalfCount - 1].EndGlyphId < GlyphId) ? (Ranges + HalfCount) : Ranges; + Count -= HalfCount; + } + if((GlyphId >= Ranges->StartGlyphId) && (GlyphId <= Ranges->EndGlyphId)) + { + Result.Valid = 1; + Result.Index = Ranges->StartCoverageIndex + GlyphId - Ranges->StartGlyphId; + } + } + } + + KBTS_INSTRUMENT_FUNCTION_END; + return Result; +} + +static void kbts__ByteSwapSequenceContextSubtable(kbts__byteswap_context *Context, kbts_u16 *Base) +{ + if(Base[0] == 1) + { + kbts__sequence_context_1 *Subst = (kbts__sequence_context_1 *)Base; + Subst->SeqRuleSetCount = kbts__ByteSwap16(Subst->SeqRuleSetCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->SeqRuleSetCount, Context); + + KBTS__FOR(SetIndex, 0, Subst->SeqRuleSetCount) + { + kbts__sequence_rule_set *Set = kbts__GetSequenceRuleSet(Subst, SetIndex); + + if(Set && !kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Set), Set->Count, Context); + + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__sequence_rule *Rule = kbts__GetSequenceRule(Set, RuleIndex); + + if(!kbts__AlreadyVisited(Context, Rule)) + { + kbts__ByteSwapArray16Context(&Rule->GlyphCount, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Rule), (kbts_un)Rule->GlyphCount - 1 + (kbts_un)Rule->SequenceLookupCount * 2, Context); + } + } + } + } + } + else if(Base[0] == 2) + { + kbts__sequence_context_2 *Subst = (kbts__sequence_context_2 *)Base; + kbts__ByteSwapArray16Context(&Subst->ClassDefOffset, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->ClassSequenceRuleSetCount, Context); + + kbts_u16 *ClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->ClassDefOffset); + kbts__ByteSwapClassDefinition(Context, ClassDefBase); + + KBTS__FOR(SetIndex, 0, Subst->ClassSequenceRuleSetCount) + { + kbts__class_sequence_rule_set *Set = kbts__GetClassSequenceRuleSet(Subst, SetIndex); + + if(Set && !kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Set), Set->Count, Context); + + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__class_sequence_rule *Rule = kbts__GetClassSequenceRule(Set, RuleIndex); + + if(!kbts__AlreadyVisited(Context, Rule)) + { + kbts__ByteSwapArray16Context(&Rule->GlyphCount, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Rule), Rule->GlyphCount - 1 + 2 * Rule->SequenceLookupCount, Context); + } + } + } + } + + #ifdef KBTS_DUMP + kbts__DumpClassDefinition(ClassDefBase); + KBTS__FOR(SetIndex, 0, Subst->ClassSequenceRuleSetCount) + { + kbts__class_sequence_rule_set *Set = kbts__GetClassSequenceRuleSet(Subst, SetIndex); + + if(Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__class_sequence_rule *Rule = kbts__GetClassSequenceRule(Set, RuleIndex); + kbts_u16 *InputSequence = KBTS__POINTER_AFTER(kbts_u16, Rule); + kbts__sequence_lookup_record *Records = (kbts__sequence_lookup_record *)(InputSequence + Rule->GlyphCount - 1); + KBTS_DUMPF("Input: ["); + KBTS__FOR(GlyphIndex, 1, Rule->GlyphCount) + { + KBTS_DUMPF(", %x", InputSequence[GlyphIndex - 1]); + } + KBTS_DUMPF("]\nRecords: ["); + KBTS__FOR(RecordIndex, 0, Rule->SequenceLookupCount) + { + kbts__sequence_lookup_record *Record = &Records[RecordIndex]; + if(RecordIndex) KBTS_DUMPF(", "); + KBTS_DUMPF("%u@%u", Record->LookupListIndex, Record->SequenceIndex); + } + KBTS_DUMPF("]\n"); + } + } + } + #endif + } + else if(Base[0] == 3) + { + kbts__sequence_context_3 *Subst = (kbts__sequence_context_3 *)Base; + kbts__ByteSwapArray16Context(&Subst->GlyphCount, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->GlyphCount + 2 * Subst->SequenceLookupCount, Context); + + kbts_u16 *CoverageOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + KBTS__FOR(CoverageIndex, 0, Subst->GlyphCount) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, CoverageOffsets[CoverageIndex]); + + kbts__ByteSwapCoverage(Context, Coverage); + } + } +} + +typedef kbts_u32 kbts__skip_flags; +enum kbts__skip_flags_enum +{ + KBTS__SKIP_FLAG_NONE, + KBTS__SKIP_FLAG_ZWNJ = (1 << 0), + KBTS__SKIP_FLAG_ZWJ = (1 << 1), +}; +// The Harfbuzz behavior is: +// - GPOS lookups always skip ZWNJ. +// - Sequence lookups always skip ZWJ. +// - GSUB sequence lookups skip ZWNJ when requested. +// - Regular lookups skip ZWJ when requested. +#define KBTS__SKIP_FLAGS_GSUB_REGULAR(RequestedFlags) ((RequestedFlags) & KBTS__SKIP_FLAG_ZWJ) +#define KBTS__SKIP_FLAGS_GSUB_SEQUENCE(RequestedFlags) (KBTS__SKIP_FLAG_ZWJ | ((RequestedFlags) & KBTS__SKIP_FLAG_ZWNJ)) +#define KBTS__SKIP_FLAGS_GPOS_REGULAR(RequestedFlags) (((RequestedFlags) & KBTS__SKIP_FLAG_ZWJ) | KBTS__SKIP_FLAG_ZWNJ) +#define KBTS__SKIP_FLAGS_GPOS_SEQUENCE(RequestedFlags) (KBTS__SKIP_FLAG_ZWJ | KBTS__SKIP_FLAG_ZWNJ) + +static kbts__skip_flags kbts__SkipFlags(kbts__feature_id FeatureId, kbts_shaper Shaper) +{ + kbts__skip_flags Result = 0; + switch(FeatureId) + { + case KBTS__FEATURE_ID_nukt: + case KBTS__FEATURE_ID_akhn: + case KBTS__FEATURE_ID_rphf: + case KBTS__FEATURE_ID_rkrf: + case KBTS__FEATURE_ID_pref: + case KBTS__FEATURE_ID_blwf: + case KBTS__FEATURE_ID_abvf: + case KBTS__FEATURE_ID_half: + case KBTS__FEATURE_ID_pstf: + case KBTS__FEATURE_ID_vatu: + case KBTS__FEATURE_ID_cjct: + case KBTS__FEATURE_ID_pres: + case KBTS__FEATURE_ID_abvs: + case KBTS__FEATURE_ID_blws: + case KBTS__FEATURE_ID_psts: + case KBTS__FEATURE_ID_haln: + case KBTS__FEATURE_ID_cfar: + if(Shaper == KBTS_SHAPER_USE) + { + Result = KBTS__SKIP_FLAG_ZWNJ; + } + else if((Shaper == KBTS_SHAPER_INDIC) || + (Shaper == KBTS_SHAPER_KHMER)) + { + Result = 0; + } + else + { + Result = KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ; + } + break; + + case KBTS__FEATURE_ID_init: + if (Shaper == KBTS_SHAPER_INDIC) {Result = 0;} + else if(Shaper == KBTS_SHAPER_ARABIC) {Result = KBTS__SKIP_FLAG_ZWNJ;} + else {Result = KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ;} + break; + + case KBTS__FEATURE_ID_ccmp: + case KBTS__FEATURE_ID_locl: + case KBTS__FEATURE_ID_isol: + case KBTS__FEATURE_ID_fina: + case KBTS__FEATURE_ID_fin2: + case KBTS__FEATURE_ID_fin3: + case KBTS__FEATURE_ID_medi: + case KBTS__FEATURE_ID_med2: + case KBTS__FEATURE_ID_calt: + case KBTS__FEATURE_ID_liga: + case KBTS__FEATURE_ID_clig: + case KBTS__FEATURE_ID_rlig: + case KBTS__FEATURE_ID_mset: + Result = (Shaper == KBTS_SHAPER_ARABIC) ? KBTS__SKIP_FLAG_ZWNJ : KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ; + break; + + case KBTS__FEATURE_ID_mark: + case KBTS__FEATURE_ID_mkmk: + Result = 0; + break; + + default: + Result = KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ; + break; + } + return Result; +} + +static kbts_u32 kbts__GlyphIncludedInLookup(kbts_font *Font, int Gpos, kbts_un LookupIndex, kbts_u32 Id) +{ + kbts_u32 Result = 1; + kbts_u32 GlyphCount = Font->Blob->GlyphCount; + if(Font->Blob->GlyphLookupMatrixOffsetFromStartOfFile && (Id < GlyphCount)) + { + kbts_u32 *GlyphLookupMatrix = KBTS__POINTER_OFFSET(kbts_u32, Font->Blob, Font->Blob->GlyphLookupMatrixOffsetFromStartOfFile); + + kbts_un FlatLookupIndex = (Gpos ? Font->Blob->GposLookupIndexOffset : 0) + LookupIndex; + kbts_un FlatIndex = FlatLookupIndex * Font->Blob->GlyphCount + Id; + kbts_un WordIndex = FlatIndex / 32; + kbts_un BitIndex = FlatIndex % 32; + + Result = GlyphLookupMatrix[WordIndex] & (1 << BitIndex); + } + return Result; +} + +static int kbts__GlyphPassesLookupFilter(kbts_glyph *Glyph, kbts__unpacked_lookup *Lookup) +{ + int Result = 1; + kbts_u16 Class = Glyph->Classes.Class; + + if(Class && (Lookup->Flags & (1 << Class))) + { + Result = 0; + } + + if(Result && (Class == KBTS__GLYPH_CLASS_MARK)) + { + if(Lookup->Flags & KBTS__LOOKUP_FLAG_MARK_ATTACHMENT_CLASS_FILTER) + { + kbts_u32 DesiredMarkAttachmentClass = Lookup->Flags >> 8; + + if(Glyph->Classes.MarkAttachmentClass != DesiredMarkAttachmentClass) + { + Result = 0; + } + } + + if(Result && Lookup->MarkFilteringSet) + { + // @Speed: We may want to save the result of the last mark filtering test on the glyph itself. + kbts__cover_glyph_result Cover = kbts__CoverGlyph(Lookup->MarkFilteringSet, Glyph->Id); + if(!Cover.Valid) + { + Result = 0; + } + } + } + + return Result; +} + +static int kbts__SkipGlyph(kbts_glyph *Glyph, kbts__unpacked_lookup *Lookup, kbts__skip_flags SkipFlags, kbts_u32 SkipUnicodeFlags) +{ + int Result = (Glyph->UnicodeFlags & SkipUnicodeFlags) || + ((SkipFlags & KBTS__SKIP_FLAG_ZWNJ) && (Glyph->Codepoint == 0x200C)) || + ((SkipFlags & KBTS__SKIP_FLAG_ZWJ) && (Glyph->Codepoint == 0x200D)) || + !kbts__GlyphPassesLookupFilter(Glyph, Lookup); + return Result; +} + +static int kbts__GlyphIsValid(kbts_glyph_storage *Storage, kbts_glyph *Glyph) +{ + int Result = Glyph != &Storage->GlyphSentinel; + return Result; +} + +typedef struct kbts__matrix_index +{ + kbts_un WordIndex; + kbts_un BitIndex; +} kbts__matrix_index; + +static kbts__matrix_index kbts__GlyphLookupMatrixIndex(kbts_un LookupIndex, kbts_un GlyphIndex, kbts_un GlyphCount) +{ + kbts_un FlatIndex = LookupIndex * GlyphCount + GlyphIndex; + + kbts__matrix_index Result = KBTS__ZERO; + Result.WordIndex = FlatIndex / 32; + Result.BitIndex = FlatIndex % 32; + + return Result; +} + +static kbts__matrix_index kbts__GlyphLookupSubtableMatrixIndex(kbts_un SubtableIndex, kbts_un SubtableCount, kbts_un GlyphIndex) +{ + // Since we try many subtables in a row against the same glyphs, the rows are glyph-wise and the columns subtable-wise. + kbts_un FlatIndex = GlyphIndex * SubtableCount + SubtableIndex; + + kbts__matrix_index Result = KBTS__ZERO; + Result.WordIndex = FlatIndex / 32; + Result.BitIndex = FlatIndex % 32; + return Result; +} + +static int kbts__GlyphsIncludedInLookupSubtable(kbts_glyph_storage *Storage, kbts_font *Font, int Gpos, kbts__unpacked_lookup *Lookup, kbts_un LookupIndex, kbts_un SubtableIndex, kbts_glyph *AtGlyph, kbts__skip_flags SkipFlags, kbts_unicode_flags SkipUnicodeFlags) +{ + if(Font->Blob->GlyphLookupSubtableMatrixOffsetFromStartOfFile) + { + kbts_u32 *GlyphLookupSubtableMatrix = KBTS__POINTER_OFFSET(kbts_u32, Font->Blob, Font->Blob->GlyphLookupSubtableMatrixOffsetFromStartOfFile); + kbts_u32 *LookupSubtableIndexOffsets = KBTS__POINTER_OFFSET(kbts_u32, Font->Blob, Font->Blob->LookupSubtableIndexOffsetsOffsetFromStartOfFile); + kbts_lookup_subtable_info *SubtableInfos = KBTS__POINTER_OFFSET(kbts_lookup_subtable_info, Font->Blob, Font->Blob->SubtableInfosOffsetFromStartOfFile); + kbts_un GlyphCount = Font->Blob->GlyphCount; + kbts_un SubtableCount = Font->Blob->LookupSubtableCount; + + kbts_un FlatLookupIndex = (Gpos ? Font->Blob->GposLookupIndexOffset : 0) + LookupIndex; + kbts_un FlatSubtableIndex = LookupSubtableIndexOffsets[FlatLookupIndex] + SubtableIndex; + kbts_lookup_subtable_info *Info = &SubtableInfos[FlatSubtableIndex]; + kbts_un MinimumBacktrack = (Info->MinimumBacktrackPlusOne) ? Info->MinimumBacktrackPlusOne - 1 : 0; + kbts_un MinimumFollowup = (Info->MinimumFollowupPlusOne) ? Info->MinimumFollowupPlusOne - 1 : 0; + + { // Check the current glyph. + kbts_un Id = AtGlyph->Id; + kbts__matrix_index MatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(FlatSubtableIndex, SubtableCount, Id); + if(Id >= GlyphCount) + { + return 1; + } + else if(!(GlyphLookupSubtableMatrix[MatrixIndex.WordIndex] & (1 << MatrixIndex.BitIndex))) + { + return 0; + } + } + + { + kbts_un BacktrackCounter = 0; + kbts_glyph *BacktrackGlyph = AtGlyph->Prev; + while(kbts__GlyphIsValid(Storage, BacktrackGlyph) && + (BacktrackCounter < MinimumBacktrack)) + { + kbts__matrix_index MatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(FlatSubtableIndex, SubtableCount, BacktrackGlyph->Id); + + if((BacktrackGlyph->Id >= GlyphCount) || + kbts__SkipGlyph(BacktrackGlyph, Lookup, SkipFlags, SkipUnicodeFlags) || + GlyphLookupSubtableMatrix[MatrixIndex.WordIndex] & (1 << MatrixIndex.BitIndex)) + { + BacktrackCounter += 1; + } + else + { + return 0; + } + + BacktrackGlyph = BacktrackGlyph->Prev; + } + + if(BacktrackCounter < MinimumBacktrack) + { + return 0; + } + } + + { + kbts_un LookaheadCounter = 0; + kbts_glyph *LookaheadGlyph = AtGlyph->Next; + while(kbts__GlyphIsValid(Storage, LookaheadGlyph) && (LookaheadCounter < MinimumFollowup)) + { + kbts__matrix_index MatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(FlatSubtableIndex, SubtableCount, LookaheadGlyph->Id); + + if((LookaheadGlyph->Id >= GlyphCount) || + kbts__SkipGlyph(LookaheadGlyph, Lookup, SkipFlags, SkipUnicodeFlags) || + GlyphLookupSubtableMatrix[MatrixIndex.WordIndex] & (1 << MatrixIndex.BitIndex)) + { + LookaheadCounter += 1; + } + else + { + return 0; + } + + LookaheadGlyph = LookaheadGlyph->Next; + } + + if(LookaheadCounter < MinimumFollowup) + { + return 0; + } + } + } + + return 1; +} + +# ifdef KBTS_DUMP +static void kbts__DumpCoverage(kbts__coverage *Coverage) +{ + KBTS_DUMPF("["); + if(Coverage->Format == 1) + { + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Coverage); + KBTS__FOR(GlyphIndex, 0, Coverage->Count) + { + KBTS_DUMPF("%x,", GlyphIds[GlyphIndex]); + } + } + else if(Coverage->Format == 2) + { + kbts__range_record *Ranges = KBTS__POINTER_AFTER(kbts__range_record, Coverage); + KBTS__FOR(RangeIndex, 0, Coverage->Count) + { + kbts__range_record *Range = &Ranges[RangeIndex]; + KBTS_DUMPF("%x..%x @ %u,", Range->StartGlyphId, Range->EndGlyphId, Range->StartCoverageIndex); + } + } + KBTS_DUMPF("]"); +} +# endif + +static void kbts__ByteSwapChainedSequenceContextSubtable(kbts__byteswap_context *Context, kbts_u16 *Base) +{ + if(Base[0] == 1) + { + kbts__chained_sequence_context_1 *Subst = (kbts__chained_sequence_context_1 *)Base; + Subst->ChainedSequenceRuleSetCount = kbts__ByteSwap16(Subst->ChainedSequenceRuleSetCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->ChainedSequenceRuleSetCount, Context); + + KBTS__FOR(SetIndex, 0, Subst->ChainedSequenceRuleSetCount) + { + kbts__ByteSwapChainedSequenceRuleSet(Context, kbts__GetChainedSequenceRuleSet(Subst, SetIndex)); + } + } + else if(Base[0] == 2) + { + kbts__chained_sequence_context_2 *Subst = (kbts__chained_sequence_context_2 *)Base; + kbts__ByteSwapArray16Context(&Subst->BacktrackClassDefOffset, 4, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->ChainedClassSequenceRuleSetCount, Context); + + kbts_u16 *BacktrackClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->BacktrackClassDefOffset); + kbts__ByteSwapClassDefinition(Context, BacktrackClassDefinition); + + kbts_u16 *InputClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->InputClassDefOffset); + kbts__ByteSwapClassDefinition(Context, InputClassDefinition); + + kbts_u16 *LookaheadClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->LookaheadClassDefOffset); + kbts__ByteSwapClassDefinition(Context, LookaheadClassDefinition); + + #ifdef KBTS_DUMP + KBTS_DUMPF("Backtrack classes:\n"); + // kbts__DumpClassDefinition(BacktrackClassDefinition); + KBTS_DUMPF("Input classes:\n"); + // kbts__DumpClassDefinition(InputClassDefinition); + KBTS_DUMPF("Lookahead classes:\n"); + // kbts__DumpClassDefinition(LookaheadClassDefinition); + #endif + + KBTS__FOR(SetIndex, 0, Subst->ChainedClassSequenceRuleSetCount) + { + kbts__chained_sequence_rule_set *Set = kbts__GetChainedClassSequenceRuleSet(Subst, SetIndex); + kbts__ByteSwapChainedSequenceRuleSet(Context, Set); + + #ifdef KBTS_DUMP + if(Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedClassSequenceRule(Set, RuleIndex); + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 0); + + KBTS_DUMPF("Backtrack: ["); + KBTS__FOR(BacktrackIndex, 0, Unpacked.BacktrackCount) + { + if(BacktrackIndex) KBTS_DUMPF(", "); + KBTS_DUMPF("%u", Unpacked.Backtrack[BacktrackIndex]); + } + KBTS_DUMPF("]\n" + "Input: ["); + KBTS__FOR(InputIndex, 1, Unpacked.InputCount) + { + if(InputIndex) KBTS_DUMPF(", "); + KBTS_DUMPF("%u", Unpacked.Input[InputIndex - 1]); + } + KBTS_DUMPF("]\n" + "Lookahead: ["); + KBTS__FOR(LookaheadIndex, 0, Unpacked.LookaheadCount) + { + if(LookaheadIndex) KBTS_DUMPF(", "); + KBTS_DUMPF("%u", Unpacked.Lookahead[LookaheadIndex]); + } + KBTS_DUMPF("]\n" + "Records: ["); + KBTS__FOR(RecordIndex, 0, Unpacked.RecordCount) + { + kbts__sequence_lookup_record *Record = &Unpacked.Records[RecordIndex]; + if(RecordIndex) KBTS_DUMPF(", "); + KBTS_DUMPF("%u@%u", Record->LookupListIndex, Record->SequenceIndex); + } + KBTS_DUMPF("]\n"); + } + } + #endif + } + } + else if(Base[0] == 3) + { + kbts__chained_sequence_context_3 *Subst = (kbts__chained_sequence_context_3 *)Base; + kbts__unpacked_chained_sequence_context_3 Unpacked = kbts__UnpackChainedSequenceContext3(Subst, 1); + + kbts_un U16Count = Unpacked.BacktrackCount + Unpacked.InputCount + Unpacked.LookaheadCount + Unpacked.RecordCount * 2 + 4; + kbts__ByteSwapArray16Context(&Subst->BacktrackGlyphCount, U16Count, Context); + + KBTS__FOR(BacktrackCoverageIndex, 0, Unpacked.BacktrackCount) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.BacktrackCoverageOffsets[BacktrackCoverageIndex]); + + kbts__ByteSwapCoverage(Context, Coverage); + } + + KBTS__FOR(InputCoverageIndex, 0, Unpacked.InputCount) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.InputCoverageOffsets[InputCoverageIndex]); + + kbts__ByteSwapCoverage(Context, Coverage); + } + + KBTS__FOR(LookaheadCoverageIndex, 0, Unpacked.LookaheadCount) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.LookaheadCoverageOffsets[LookaheadCoverageIndex]); + + kbts__ByteSwapCoverage(Context, Coverage); + } + +# ifdef KBTS_DUMP + KBTS_DUMPF(" Backtrack: "); + KBTS__FOR(BacktrackCoverageIndex, 0, Unpacked.BacktrackCount) + { + kbts__DumpCoverage(KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.BacktrackCoverageOffsets[BacktrackCoverageIndex])); + } + KBTS_DUMPF("\n Input: "); + KBTS__FOR(InputCoverageIndex, 0, Unpacked.InputCount) + { + kbts__DumpCoverage(KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.InputCoverageOffsets[InputCoverageIndex])); + } + KBTS_DUMPF("\n Lookahead: "); + KBTS__FOR(LookaheadCoverageIndex, 0, Unpacked.LookaheadCount) + { + kbts__DumpCoverage(KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.LookaheadCoverageOffsets[LookaheadCoverageIndex])); + } + KBTS_DUMPF("\n Lookups: ["); + KBTS__FOR(RecordIndex, 0, Unpacked.RecordCount) + { + kbts__sequence_lookup_record *Record = &Unpacked.Records[RecordIndex]; + + KBTS_DUMPF("%u@%u,", Record->LookupListIndex, Record->SequenceIndex); + } + KBTS_DUMPF("]\n"); +# endif + } +} + +static void kbts__ByteSwapGsubLookupSubtable(kbts__byteswap_context *Context, kbts_u16 LookupType, kbts_u16 *Base) +{ + int Swap = !kbts__AlreadyVisited(Context, Base); + while(Swap && (LookupType == 7)) + { + kbts__extension *Subst = (kbts__extension *)Base; + Subst->Format = kbts__ByteSwap16(Subst->Format); + Subst->LookupType = kbts__ByteSwap16(Subst->LookupType); + Subst->Offset = kbts__ByteSwap32(Subst->Offset); + + KBTS_DUMPF(" Type 7.1\n" + " Offset %zu\n" + " -> %zu\n", + (char *)Base - Context->FileBase, (char *)Subst + Subst->Offset - Context->FileBase); + + Base = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->Offset); + LookupType = Subst->LookupType; + + Swap = !kbts__AlreadyVisited(Context, Base); + } + + if(Swap) + { + *Base = kbts__ByteSwap16(*Base); + + KBTS_DUMPF(" Type %u.%u\n" + " Offset %zu\n", + LookupType, *Base, (char *)Base - Context->FileBase); + + if(kbts__GsubLookupBeginsWithCoverage(LookupType, Base[0])) + { + Base[1] = kbts__ByteSwap16(Base[1]); + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Base, Base[1]); + + kbts__ByteSwapCoverage(Context, Coverage); + +# ifdef KBTS_DUMP + KBTS_DUMPF(" Coverage %u\n", Coverage->Format); + if(Coverage->Format == 1) + { + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Coverage); + KBTS__FOR(GlyphIndex, 0, Coverage->Count) + { + KBTS_DUMPF(" %x\n", GlyphIds[GlyphIndex]); + } + } + else if(Coverage->Format == 2) + { + kbts__range_record *Ranges = KBTS__POINTER_AFTER(kbts__range_record, Coverage); + KBTS__FOR(RangeIndex, 0, Coverage->Count) + { + kbts__range_record Range = Ranges[RangeIndex]; + KBTS_DUMPF(" %x..%x@%u..%u\n", Range.StartGlyphId, Range.EndGlyphId, Range.StartCoverageIndex, Range.StartCoverageIndex + (Range.EndGlyphId - Range.StartGlyphId)); + } + } +# endif + } + + switch(LookupType) + { + case 1: + { + kbts__single_substitution *Subst = (kbts__single_substitution *)Base; + Subst->DeltaOrCount.GlyphCount = kbts__ByteSwap16(Subst->DeltaOrCount.GlyphCount); + +# ifdef KBTS_DUMP + if(Subst->Format == 1) + { + KBTS_DUMPF(" += %d\n", Subst->DeltaOrCount.DeltaGlyphId); + } +# endif + + if(Subst->Format == 2) + { + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Subst); + kbts__ByteSwapArray16Context(GlyphIds, Subst->DeltaOrCount.GlyphCount, Context); + + #ifdef KBTS_DUMP + KBTS_DUMPF(" ["); + KBTS__FOR(IdIndex, 0, Subst->DeltaOrCount.GlyphCount) + { + if(IdIndex) KBTS_DUMPF(" "); + KBTS_DUMPF("%x", GlyphIds[IdIndex]); + } + KBTS_DUMPF("]\n"); + #endif + } + } + break; + + case 2: + { + kbts__multiple_substitution *Subst = (kbts__multiple_substitution *)Base; + Subst->SequenceCount = kbts__ByteSwap16(Subst->SequenceCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->SequenceCount, Context); + + KBTS__FOR(SequenceIndex, 0, Subst->SequenceCount) + { + kbts__sequence *Sequence = kbts__GetSequence(Subst, SequenceIndex); + + if(!kbts__AlreadyVisited(Context, Sequence)) + { + Sequence->GlyphCount = kbts__ByteSwap16(Sequence->GlyphCount); + + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Sequence), Sequence->GlyphCount, Context); + } + + #ifdef KBTS_DUMP + KBTS_DUMPF(" ["); + kbts_u16 *SequenceGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Sequence); + KBTS__FOR(SequenceGlyphIndex, 0, Sequence->GlyphCount) + { + if(SequenceGlyphIndex) KBTS_DUMPF(" "); + KBTS_DUMPF("%x", SequenceGlyphIds[SequenceGlyphIndex]); + } + KBTS_DUMPF("]\n"); + #endif + } + } + break; + + case 3: + { + kbts__alternate_substitution *Subst = (kbts__alternate_substitution *)Base; + Subst->AlternateSetCount = kbts__ByteSwap16(Subst->AlternateSetCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->AlternateSetCount, Context); + + KBTS__FOR(SetIndex, 0, Subst->AlternateSetCount) + { + kbts__alternate_set *Set = kbts__GetAlternateSet(Subst, SetIndex); + + if(!kbts__AlreadyVisited(Context, Set)) + { + Set->GlyphCount = kbts__ByteSwap16(Set->GlyphCount); + + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Set), Set->GlyphCount, Context); + } + + #ifdef KBTS_DUMP + KBTS_DUMPF(" ["); + kbts_u16 *SetGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Set); + KBTS__FOR(SetGlyphIndex, 0, Set->GlyphCount) + { + if(SetGlyphIndex) KBTS_DUMPF(" "); + KBTS_DUMPF("%x", SetGlyphIds[SetGlyphIndex]); + } + KBTS_DUMPF("]\n"); + #endif + } + } + break; + + case 4: + { + kbts__ligature_substitution *Subst = (kbts__ligature_substitution *)Base; + Subst->LigatureSetCount = kbts__ByteSwap16(Subst->LigatureSetCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Subst), Subst->LigatureSetCount, Context); + + KBTS__FOR(SetIndex, 0, Subst->LigatureSetCount) + { + kbts__ligature_set *Set = kbts__GetLigatureSet(Subst, SetIndex); + + if(!kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Set), Set->Count, Context); + + KBTS__FOR(LigatureIndex, 0, Set->Count) + { + kbts__ligature *Ligature = kbts__GetLigature(Set, LigatureIndex); + + if(!kbts__AlreadyVisited(Context, Ligature)) + { + kbts__ByteSwapArray16Context(&Ligature->Glyph, 2, Context); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Ligature), Ligature->ComponentCount - 1, Context); + +# ifdef KBTS_DUMP + KBTS_DUMPF("ligature: ["); + kbts_u16 *ComponentIds = KBTS__POINTER_AFTER(kbts_u16, Ligature); + KBTS__FOR(ComponentIndex, 1, Ligature->ComponentCount) + { + KBTS_DUMPF("%x,", ComponentIds[ComponentIndex - 1]); + } + KBTS_DUMPF("] -> %x\n", Ligature->Glyph); +# endif + } + } + } + } + +# ifdef KBTS_DUMP + +# endif + } + break; + + case 5: + { + kbts__ByteSwapSequenceContextSubtable(Context, Base); + } + break; + + case 6: + { + kbts__ByteSwapChainedSequenceContextSubtable(Context, Base); + } + break; + + case 8: + { + kbts__reverse_chain_substitution *Subst = (kbts__reverse_chain_substitution *)Base; + kbts__unpacked_reverse_chain_substitution Unpacked = kbts__UnpackReverseChainSubstitution(Subst, 1); + + kbts_un U16Count = Unpacked.BacktrackCount + Unpacked.GlyphCount + Unpacked.LookaheadCount + 3; + kbts__ByteSwapArray16Context(&Subst->BacktrackGlyphCount, U16Count, Context); + + KBTS__FOR(BacktrackCoverageIndex, 0, Unpacked.BacktrackCount) + { + kbts__ByteSwapCoverage(Context, KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.BacktrackCoverageOffsets[BacktrackCoverageIndex])); + } + KBTS__FOR(LookaheadCoverageIndex, 0, Unpacked.LookaheadCount) + { + kbts__ByteSwapCoverage(Context, KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.LookaheadCoverageOffsets[LookaheadCoverageIndex])); + } + } + break; + } + } +} + +static void kbts__ByteSwapGposLookupSubtable(kbts__byteswap_context *Context, kbts_lookup_list *LookupList, kbts_u16 LookupType, kbts_u16 *Base) +{ + if(!kbts__AlreadyVisited(Context, Base)) + { + *Base = kbts__ByteSwap16(*Base); + + KBTS_DUMPF(" GPOS subtable %u.%u\n", LookupType, *Base); + + if(kbts__GposLookupBeginsWithCoverage(LookupType, *Base)) + { + kbts_u16 *CoverageOffset = &Base[1]; + *CoverageOffset = kbts__ByteSwap16(*CoverageOffset); + + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Base, *CoverageOffset); + kbts__ByteSwapCoverage(Context, Coverage); + } + + switch(LookupType) + { + case 1: + { + kbts__single_adjustment_1 *Adjust = (kbts__single_adjustment_1 *)Base; + Adjust->ValueFormat = kbts__ByteSwap16(Adjust->ValueFormat); + + if(Adjust->Format == 1) + { + kbts_ByteSwapValueRecord(Context, Adjust, Adjust->ValueFormat, KBTS__POINTER_AFTER(kbts_u16, Adjust)); + } + else if(Adjust->Format == 2) + { + kbts__single_adjustment_2 *Adjust2 = (kbts__single_adjustment_2 *)Base; + Adjust2->RecordCount = kbts__ByteSwap16(Adjust2->RecordCount); + + kbts_u16 *At = KBTS__POINTER_AFTER(kbts_u16, Adjust2); + KBTS__FOR(RecordIndex, 0, Adjust2->RecordCount) + { + kbts__unpacked_value_record Unpacked = kbts_ByteSwapValueRecord(Context, Adjust2, Adjust2->ValueFormat, At); + + At += Unpacked.Size; + } + } + } + break; + + case 2: + { + if(*Base == 1) + { + kbts__pair_adjustment_1 *Adjust = (kbts__pair_adjustment_1 *)Base; + kbts__ByteSwapArray16Context(&Adjust->ValueFormat1, 3, Context); + + kbts_u16 *SetOffsets = KBTS__POINTER_AFTER(kbts_u16, Adjust); + kbts__ByteSwapArray16Context(SetOffsets, Adjust->SetCount, Context); + + kbts_un Size1 = kbts__PopCount32(Adjust->ValueFormat1); + kbts_un Size2 = kbts__PopCount32(Adjust->ValueFormat2); + kbts_un PairRecordSize = Size1 + Size2 + 1; + + KBTS__FOR(SetIndex, 0, Adjust->SetCount) + { + kbts__pair_set *Set = KBTS__POINTER_OFFSET(kbts__pair_set, Adjust, SetOffsets[SetIndex]); + + if(!kbts__AlreadyVisited(Context, Set)) + { + Set->Count = kbts__ByteSwap16(Set->Count); + + kbts_u16 *At = KBTS__POINTER_AFTER(kbts_u16, Set); + + KBTS__FOR(RecordIndex, 0, Set->Count) + { + kbts__pair_value_record *PairRecord = (kbts__pair_value_record *)(At + RecordIndex * PairRecordSize); + + PairRecord->SecondGlyph = kbts__ByteSwap16(PairRecord->SecondGlyph); + kbts_u16 *Record = KBTS__POINTER_AFTER(kbts_u16, PairRecord); + + kbts__unpacked_value_record Unpacked1 = kbts_ByteSwapValueRecord(Context, Set, Adjust->ValueFormat1, Record); + Record += Unpacked1.Size; + kbts_ByteSwapValueRecord(Context, Set, Adjust->ValueFormat2, Record); + } + } + } + } + else if(*Base == 2) + { + kbts__pair_adjustment_2 *Adjust = (kbts__pair_adjustment_2 *)Base; + kbts__ByteSwapArray16Context(&Adjust->ValueFormat1, 6, Context); + + kbts__ByteSwapClassDefinition(Context, KBTS__POINTER_OFFSET(kbts_u16, Adjust, Adjust->ClassDefinition1Offset)); + kbts__ByteSwapClassDefinition(Context, KBTS__POINTER_OFFSET(kbts_u16, Adjust, Adjust->ClassDefinition2Offset)); + + kbts_u16 *Records = KBTS__POINTER_AFTER(kbts_u16, Adjust); + + kbts_un Size1 = kbts__PopCount32(Adjust->ValueFormat1); + kbts_un Size2 = kbts__PopCount32(Adjust->ValueFormat2); + + kbts_u16 *RecordPair = Records; + KBTS__FOR(RecordIndex, 0, (kbts_un)Adjust->Class1Count * (kbts_un)Adjust->Class2Count) + { + kbts_ByteSwapValueRecord(Context, Adjust, Adjust->ValueFormat1, RecordPair); + RecordPair += Size1; + + kbts_ByteSwapValueRecord(Context, Adjust, Adjust->ValueFormat2, RecordPair); + RecordPair += Size2; + } + } + } + break; + + case 3: + { + kbts__cursive_attachment *Adjust = (kbts__cursive_attachment *)Base; + Adjust->EntryExitCount = kbts__ByteSwap16(Adjust->EntryExitCount); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, Adjust), Adjust->EntryExitCount * 2, Context); + + kbts__entry_exit *EntryExits = KBTS__POINTER_AFTER(kbts__entry_exit, Adjust); + KBTS__FOR(EntryExitIndex, 0, Adjust->EntryExitCount) + { + kbts__entry_exit *EntryExit = &EntryExits[EntryExitIndex]; + + if(EntryExit->EntryAnchorOffset) + { + kbts__ByteSwapAnchor(Context, KBTS__POINTER_OFFSET(kbts__anchor, Adjust, EntryExit->EntryAnchorOffset)); + } + + if(EntryExit->ExitAnchorOffset) + { + kbts__ByteSwapAnchor(Context, KBTS__POINTER_OFFSET(kbts__anchor, Adjust, EntryExit->ExitAnchorOffset)); + } + } + } + break; + + case 4: + case 6: + { + kbts__mark_to_base_attachment *Adjust = (kbts__mark_to_base_attachment *)Base; + kbts__ByteSwapArray16Context(&Adjust->BaseCoverageOffset, 4, Context); + + kbts__ByteSwapCoverage(Context, KBTS__POINTER_OFFSET(kbts__coverage, Adjust, Adjust->BaseCoverageOffset)); + kbts__ByteSwapMarkArray(Context, KBTS__POINTER_OFFSET(kbts__mark_array, Adjust, Adjust->MarkArrayOffset)); + kbts__ByteSwapBaseArray(Context, Adjust->MarkClassCount, KBTS__POINTER_OFFSET(kbts__base_array, Adjust, Adjust->BaseArrayOffset)); + } + break; + + case 5: + { + kbts__mark_to_ligature_attachment *Adjust = (kbts__mark_to_ligature_attachment *)Base; + kbts__ByteSwapArray16Context(&Adjust->LigatureCoverageOffset, 4, Context); + + kbts__ByteSwapCoverage(Context, KBTS__POINTER_OFFSET(kbts__coverage, Adjust, Adjust->LigatureCoverageOffset)); + kbts__ByteSwapMarkArray(Context, KBTS__POINTER_OFFSET(kbts__mark_array, Adjust, Adjust->MarkArrayOffset)); + + kbts__ligature_array *LigatureArray = KBTS__POINTER_OFFSET(kbts__ligature_array, Adjust, Adjust->LigatureArrayOffset); + if(!kbts__AlreadyVisited(Context, LigatureArray)) + { + LigatureArray->Count = kbts__ByteSwap16(LigatureArray->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, LigatureArray), LigatureArray->Count, Context); + + KBTS__FOR(AttachIndex, 0, LigatureArray->Count) + { + kbts__ligature_attach *Attach = kbts__GetLigatureAttach(LigatureArray, AttachIndex); + + if(!kbts__AlreadyVisited(Context, Attach)) + { + Attach->Count = kbts__ByteSwap16(Attach->Count); + + kbts_u16 *AttachAnchorOffsets = KBTS__POINTER_AFTER(kbts_u16, Attach); + kbts__ByteSwapArray16Context(AttachAnchorOffsets, Attach->Count * Adjust->MarkClassCount, Context); + + KBTS__FOR(ComponentIndex, 0, Attach->Count) + { + KBTS__FOR(MarkClass, 0, Adjust->MarkClassCount) + { + kbts__anchor *Anchor = kbts__GetLigatureAttachAnchor(Adjust, Attach, (kbts_u16)MarkClass, ComponentIndex); + + kbts__ByteSwapAnchor(Context, Anchor); + } + } + } + } + } + } + break; + + case 7: + { + kbts__ByteSwapSequenceContextSubtable(Context, Base); + } + break; + + case 8: + { + kbts__ByteSwapChainedSequenceContextSubtable(Context, Base); + } + break; + + case 9: + { + // @Cleanup: Replace recursion with a loop at the start of this function! + kbts__extension *Adjust = (kbts__extension *)Base; + + Adjust->LookupType = kbts__ByteSwap16(Adjust->LookupType); + Adjust->Offset = kbts__ByteSwap32(Adjust->Offset); + + kbts__ByteSwapGposLookupSubtable(Context, LookupList, Adjust->LookupType, KBTS__POINTER_OFFSET(kbts_u16, Adjust, Adjust->Offset)); + } + break; + } + } +} + +static void *kbts__BlobTableData(kbts_blob_header *Header, kbts_blob_table_id TableId) +{ + void *Result = 0; + kbts_blob_table *Table = &Header->Tables[TableId]; + + if(Table->Length) + { + Result = KBTS__POINTER_OFFSET(void, Header, Table->OffsetFromStartOfFile); + } + + return Result; +} +#define kbts__BlobTableDataType(Header, TableId, Type) (Type *)kbts__BlobTableData((Header), (TableId)) + +static kbts_glyph_classes kbts__GlyphClasses(kbts_font *Font, kbts_u32 Id) +{ + kbts_glyph_classes Result = KBTS__ZERO; + + // Look up all glyph classes. + kbts__gdef *Gdef = kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GDEF, kbts__gdef); + if(Gdef) + { + if(Gdef->ClassDefinitionOffset) + { + kbts_u16 *ClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Gdef, Gdef->ClassDefinitionOffset); + Result.Class = kbts__GlyphClassFromTable(ClassDefBase, Id).Class; + } + + if(Gdef->MarkAttachmentClassDefinitionOffset && (Result.Class == KBTS__GLYPH_CLASS_MARK)) + { + kbts_u16 *MarkAttachmentClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Gdef, Gdef->MarkAttachmentClassDefinitionOffset); + Result.MarkAttachmentClass = kbts__GlyphClassFromTable(MarkAttachmentClassDefBase, Id).Class; + } + } + + return Result; +} + +static int kbts__ScriptIsWeak(kbts_script Script) +{ + int Result = (Script == KBTS_SCRIPT_DONT_KNOW) || (Script == KBTS_SCRIPT_DEFAULT) || (Script == KBTS_SCRIPT_DEFAULT2); + return Result; +} + +static int kbts__ShaperRtl(kbts_shaper Shaper) +{ + int Result = (Shaper == KBTS_SHAPER_ARABIC) || (Shaper == KBTS_SHAPER_HEBREW); + return Result; +} + +KBTS_EXPORT int kbts_CodepointToGlyphId(kbts_font *Font, int ICodepoint) +{ + int Result = 0; + kbts_u32 Codepoint = (kbts_u32)ICodepoint; + + kbts_u16 *CmapBase = Font->Cmap; + if(CmapBase) + { + switch(*CmapBase) + { + case 0: + { + kbts__cmap_0 *Cmap0 = (kbts__cmap_0 *)CmapBase; + + if((kbts_un)Codepoint < KBTS__ARRAY_LENGTH(Cmap0->GlyphIdArray)) + { + Result = Cmap0->GlyphIdArray[Codepoint]; + } + } break; + + case 2: + { + kbts__cmap_2 *Cmap2 = (kbts__cmap_2 *)CmapBase; + kbts__sub_header *SubHeaders = KBTS__POINTER_AFTER(kbts__sub_header, Cmap2); + + kbts_u32 High = (Codepoint >> 8) & 0xFF; + + if(!(Codepoint & 0xFF00)) + { + High = Codepoint & 0xFF; + } + + // The Microsoft documentation doesn't mention that the SubHeaderKeys are indices multiplied by 8, for some + // reason..! The Apple documentation does. + kbts_u16 SubHeaderIndex = Cmap2->SubHeaderKeys[High] / 8; + kbts__sub_header *SubHeader = &SubHeaders[SubHeaderIndex]; + + if(!SubHeaderIndex) + { + // With SubHeader 0, we only use the first byte. + Codepoint = High; + } + else + { + Codepoint = Codepoint & 0xFF; + } + + kbts_u32 Offset = Codepoint - SubHeader->FirstCode; + if(Offset < SubHeader->EntryCount) + { + kbts_u16 *GlyphIds = KBTS__POINTER_OFFSET(kbts_u16, &SubHeader->IdRangeOffset, SubHeader->IdRangeOffset); + kbts_u16 GlyphId = GlyphIds[Offset]; + if(GlyphId) + { + GlyphId += SubHeader->IdDelta; + } + + Result = GlyphId; + } + } break; + + case 4: + { + kbts__cmap_4 *Cmap4 = (kbts__cmap_4 *)CmapBase; + kbts_un SegmentCount = Cmap4->SegmentCountTimesTwo / 2; + kbts_u16 *EndCodes = KBTS__POINTER_AFTER(kbts_u16, Cmap4); + kbts_u16 *StartCodes = EndCodes + SegmentCount + 1; + kbts_s16 *IdDeltas = (kbts_s16 *)(StartCodes + SegmentCount); + kbts_u16 *IdRangeOffsets = (kbts_u16 *)(IdDeltas + SegmentCount); + kbts_un SegmentIndexOffset = 0; + + if(SegmentCount) + { + while(SegmentCount > 1) + { + kbts_un HalfCount = SegmentCount / 2; + SegmentIndexOffset = (EndCodes[SegmentIndexOffset + HalfCount - 1] < Codepoint) ? (SegmentIndexOffset + HalfCount) : SegmentIndexOffset; + SegmentCount -= HalfCount; + } + } + + kbts_u16 Start = StartCodes[SegmentIndexOffset]; + if((Codepoint >= Start) && (Codepoint <= EndCodes[SegmentIndexOffset])) + { + kbts_s16 Delta = IdDeltas[SegmentIndexOffset]; + kbts_u16 RangeOffset = IdRangeOffsets[SegmentIndexOffset]; + + kbts_u16 GlyphId = (kbts_u16)Delta; + if(RangeOffset) + { + GlyphId += *(&IdRangeOffsets[SegmentIndexOffset] + (Codepoint - Start) + RangeOffset / 2); + } + else + { + GlyphId += (kbts_u16)(Codepoint); + } + Result = GlyphId; + } + } break; + + case 6: + { + kbts__cmap_6 *Cmap6 = (kbts__cmap_6 *)CmapBase; + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Cmap6); + + kbts_un Offset = Codepoint - Cmap6->FirstCode; + if(Offset < Cmap6->EntryCount) + { + Result = GlyphIds[Offset]; + } + } break; + + case 12: + { + kbts__cmap_12_13 *Cmap12 = (kbts__cmap_12_13 *)CmapBase; + kbts__sequential_map_group *Groups = KBTS__POINTER_AFTER(kbts__sequential_map_group, Cmap12); + + kbts_un GlyphId = 0; + kbts_un GroupCount = Cmap12->GroupCount; + if(GroupCount) + { + while(GroupCount > 1) + { + kbts_un HalfCount = GroupCount / 2; + Groups = (Groups[HalfCount - 1].EndCharacterCode < Codepoint) ? (Groups + HalfCount) : Groups; + GroupCount -= HalfCount; + } + } + + if((Codepoint >= Groups->StartCharacterCode) && (Codepoint <= Groups->EndCharacterCode)) + { + kbts_un Offset = Codepoint - Groups->StartCharacterCode; + GlyphId = Groups->StartGlyphId + Offset; + } + + Result = (int)GlyphId; + } break; + } + } + + return Result; +} + +KBTS_EXPORT kbts_glyph kbts_CodepointToGlyph(kbts_font *Font, int ICodepoint, kbts_glyph_config *Config, int UserId) +{ + kbts_u32 Codepoint = (kbts_u32)ICodepoint; + + kbts_glyph Result = KBTS__ZERO; + Result.Codepoint = Codepoint; + Result.Config = Config; + Result.UserIdOrCodepointIndex = UserId; + + // Look up Unicode properties. + Result.Decomposition = kbts__GetUnicodeDecomposition(Codepoint); + Result.JoiningType = kbts__GetUnicodeJoiningType(Codepoint); + Result.UnicodeFlags = kbts__GetUnicodeFlags(Codepoint); + kbts_u16 SyllabicInfo = kbts__GetUnicodeSyllabicInfo(Codepoint); + Result.SyllabicClass = kbts__GetSyllabicClass(SyllabicInfo); + Result.SyllabicPosition = kbts__GetSyllabicPosition(SyllabicInfo); + Result.CombiningClass = kbts__GetUnicodeCombiningClass(Codepoint); + Result.UseClass = kbts__GetUnicodeUseClass(Codepoint); + Result.ParentInfo = kbts__GetUnicodeParentInfo(Codepoint); + + Result.Id = (kbts_u16)kbts_CodepointToGlyphId(Font, ICodepoint); + + if(Font->Blob->Tables[KBTS_BLOB_TABLE_ID_GDEF].Length) + { + Result.Classes = kbts__GlyphClasses(Font, Result.Id); + } + else + { + // @Cleanup: This is garbage compatibility-with-broken-fonts code. I would very much like to get rid of it. + if((Result.UnicodeFlags & KBTS_UNICODE_FLAG_DEFAULT_IGNORABLE) || !(Result.UnicodeFlags & KBTS_UNICODE_FLAG_NON_SPACING_MARK)) + { + Result.Classes.Class = KBTS__GLYPH_CLASS_BASE; + } + else + { + Result.Classes.Class = KBTS__GLYPH_CLASS_MARK; + } + } + + return Result; +} + +typedef struct kbts__iterate_features +{ + kbts__gsub_gpos *Header; + kbts__feature_list *FeatureList; + // @Incomplete + // kbts__feature_variations *FeatureVariations; + kbts__langsys *Langsys; + + kbts__feature_set EnabledFeatures; + + kbts_u32 CurrentFeatureTag; + kbts_u32 CurrentFeatureFlag; + + kbts_u32 FeatureIndex; + kbts__feature *Feature; +} kbts__iterate_features; + +static kbts__iterate_features kbts__IterateFeatures(kbts_shape_config *Config, kbts_shaping_table ShapingTable, kbts__feature_set EnabledFeatures) +{ + kbts__iterate_features Result = KBTS__ZERO; + + kbts_blob_table_id TableId = (ShapingTable == KBTS_SHAPING_TABLE_GSUB) ? KBTS_BLOB_TABLE_ID_GSUB : KBTS_BLOB_TABLE_ID_GPOS; + + kbts__gsub_gpos *Header = kbts__BlobTableDataType(Config->Font->Blob, TableId, kbts__gsub_gpos); + if(Header) + { + // @Incomplete + // if(Header->Minor == 1) + // { + // Result.FeatureVariations = KBTS__POINTER_OFFSET(kbts__feature_variations, Header, Header->FeatureVariationsOffset); + // } + + Result.FeatureList = KBTS__POINTER_OFFSET(kbts__feature_list, Header, Header->FeatureListOffset); + Result.Header = Header; + Result.Langsys = Config->Langsys[ShapingTable]; + Result.EnabledFeatures = EnabledFeatures; + } + + return Result; +} + +static int kbts__IsValidFeatureIteration(kbts__iterate_features *It) +{ + int Result = It->Langsys != 0; + return Result; +} + +static int kbts__NextFeature(kbts__iterate_features *It) +{ + int Result = 0; + It->Feature = 0; + + if(kbts__IsValidFeatureIteration(It)) + { + kbts_u16 *FeatureIndices = KBTS__POINTER_AFTER(kbts_u16, It->Langsys); + // @Incomplete + // kbts__feature_variations *FeatureVariations = It->FeatureVariations; + while(It->FeatureIndex < It->Langsys->FeatureIndexCount) + { + kbts__feature_pointer Feature = kbts__GetFeature(It->FeatureList, FeatureIndices[It->FeatureIndex]); + + // We might need to swap out this feature with another. + // Check for variations. + // @Incomplete + //if(FeatureVariations) + //{ + // KBTS__FOR(VariationIndex, 0, FeatureVariations->RecordCount) + // { + // kbts__feature_variation_pointer Variation = kbts__GetFeatureVariation(FeatureVariations, VariationIndex); + // KBTS__FOR(ConditionIndex, 0, Variation.ConditionSet->Count) + // { + // kbts__condition_1 *Condition = kbts__GetCondition(Variation.ConditionSet, ConditionIndex); + // KBTS_ASSERT(0); + // } + // } + //} + + It->FeatureIndex += 1; + + kbts_u32 FeatureId = kbts__FeatureTagToId(Feature.Tag); + if(kbts__ContainsFeature(&It->EnabledFeatures, FeatureId)) + { + It->Feature = Feature.Feature; + It->CurrentFeatureTag = Feature.Tag; + if(FeatureId && (FeatureId <= 32)) + { + It->CurrentFeatureFlag = (1 << (FeatureId - 1)) & KBTS__GLYPH_FEATURE_MASK; + } + Result = 1; + + break; + } + } + } + + return Result; +} + +typedef struct kbts__iterate_lookups +{ + kbts_lookup_list *LookupList; + kbts__feature *Feature; + + kbts__lookup *Lookup; + kbts_u16 LookupIndex; + + kbts_u32 LookupIndexIndex; +} kbts__iterate_lookups; + +static kbts__iterate_lookups kbts__IterateLookups(kbts_lookup_list *List, kbts__feature *Feature) +{ + kbts__iterate_lookups Result = KBTS__ZERO; + Result.LookupList = List; + Result.Feature = Feature; + + return Result; +} + +static int kbts__NextLookup(kbts__iterate_lookups *It) +{ + int Result = 0; + kbts__feature *Feature = It->Feature; + + if(It->LookupList && Feature && (It->LookupIndexIndex < Feature->LookupIndexCount)) + { + kbts_u16 *LookupIndices = KBTS__POINTER_AFTER(kbts_u16, Feature); + + It->LookupIndex = LookupIndices[It->LookupIndexIndex]; + It->Lookup = kbts__GetLookup(It->LookupList, It->LookupIndex); + + Result = 1; + It->LookupIndexIndex += 1; + } + + return Result; +} + +KBTS_INLINE void kbts__GsubMutate(kbts_font *Font, kbts_glyph *Glyph, kbts_u16 NewId, kbts_u32 Flags) +{ + Glyph->Id = NewId; + Glyph->Classes = kbts__GlyphClasses(Font, NewId); + Glyph->Flags = (Glyph->Flags & ~KBTS_GLYPH_FLAG_FIRST_IN_MULTIPLE_SUBSTITUTION) | Flags; +} + +static kbts__op_list *kbts__ShaperOpLists[KBTS_SHAPER_COUNT] = { + /* DEFAULT, */ &kbts__OpList_Default, + /* ARABIC, */ &kbts__OpList_ArabicRclt, + /* HANGUL, */ &kbts__OpList_Hangul, + /* HEBREW, */ &kbts__OpList_Default, + /* INDIC, */ &kbts__OpList_Indic, + /* KHMER, */ &kbts__OpList_Khmer, + /* MYANMAR, */ &kbts__OpList_Myanmar, + /* TIBETAN, */ &kbts__OpList_Tibetan, + /* USE, */ &kbts__OpList_Use, +}; + +typedef struct kbts__gsub_frame +{ + kbts_glyph *InputGlyph; + + // This isn't really an index into anything, per se. + // It is just an offset that allows reordering for ShapeState->LookupOnePastLastGlyph. + kbts_u32 StartIndex; + + kbts_u16 LookupIndex; + kbts_u16 SubtableIndex; + + // Defined for nested lookups. + kbts__sequence_lookup_record *Records; + kbts_u16 RecordCount; + kbts_u16 RecordIndex; +} kbts__gsub_frame; + +#define KBTS__DLLIST_REMOVE(Node) do {(Node)->Prev->Next = (Node)->Next; (Node)->Next->Prev = (Node)->Prev;} while(0) +#define KBTS__DLLIST_INSERT_BEFORE(A, B) do{(A)->Next = (B); (A)->Prev = (B)->Prev; (A)->Prev->Next = (A)->Next->Prev = (A);} while(0) +#define KBTS__DLLIST_INSERT_AFTER(A, B) do{(A)->Prev = (B); (A)->Next = (B)->Next; (A)->Prev->Next = (A)->Next->Prev = (A);} while(0) +#define KBTS__DLLIST_SENTINEL_INIT(Sentinel) do{(Sentinel)->Prev = (Sentinel)->Next = (Sentinel);} while(0) +#define KBTS__DLLIST_SORT(First, OnePastLast, Member) \ + do \ + { \ + kbts_glyph *DllistSort_OneBeforeFirst = (First)->Prev; \ + kbts_glyph *DllistSort_OnePastLast = (OnePastLast); \ + for(int DllistSort_Swapped = 1; \ + DllistSort_Swapped; \ + ) \ + { \ + DllistSort_Swapped = 0; \ + kbts_glyph *DllistSort_Glyph0 = DllistSort_OneBeforeFirst->Next; \ + kbts_glyph *DllistSort_Glyph1 = DllistSort_Glyph0->Next; \ + while(DllistSort_Glyph1 != DllistSort_OnePastLast) \ + { \ + kbts_glyph *DllistSort_Next = DllistSort_Glyph1->Next; \ + \ + if(DllistSort_Glyph0->Member > DllistSort_Glyph1->Member) \ + { \ + KBTS__DLLIST_SWAP(DllistSort_Glyph0, DllistSort_Glyph1); \ + DllistSort_Swapped = 1; \ + } \ + else \ + { \ + DllistSort_Glyph0 = DllistSort_Glyph1; \ + } \ + \ + DllistSort_Glyph1 = DllistSort_Next; \ + } \ + } \ + } while(0) + +#define KBTS__FOR_GLYPH(Storage, GlyphName) \ + for(kbts_glyph *GlyphName = (Storage)->GlyphSentinel.Next; \ + GlyphName != (kbts_glyph *)&(Storage)->GlyphSentinel; \ + GlyphName = GlyphName->Next) + +static void KBTS__DLLIST_SWAP(kbts_glyph *A, kbts_glyph *B) +{ + kbts_glyph *APrev = A->Prev; + kbts_glyph *ANext = A->Next; + kbts_glyph *BPrev = B->Prev; + kbts_glyph *BNext = B->Next; + + A->Prev = (BPrev == A) ? B : BPrev; + A->Next = (BNext == A) ? B : BNext; + B->Prev = (APrev == B) ? A : APrev; + B->Next = (ANext == B) ? A : ANext; + + A->Prev->Next = A->Next->Prev = A; + B->Prev->Next = B->Next->Prev = B; +} + +static void kbts__NullAllocator(void *Data, kbts_allocator_op *Op) +{ + KBTS__UNUSED(Data); + KBTS__UNUSED(Op); +} + +static void kbts__DefaultAllocator(void *Data, kbts_allocator_op *Op) +{ + KBTS__UNUSED(Data); + + switch(Op->Kind) + { + case KBTS_ALLOCATOR_OP_KIND_ALLOCATE: + { + Op->Allocate.Pointer = KBTS_MALLOC(Data, Op->Allocate.Size); + } break; + + case KBTS_ALLOCATOR_OP_KIND_FREE: + { + KBTS_FREE(Data, Op->Free.Pointer); + } break; + } +} + +static void *kbts__AllocatorAllocate(kbts_allocator_function *Allocator, void *AllocatorData, kbts_un Size) +{ + kbts_allocator_op AllocatorOp = KBTS__ZERO; + AllocatorOp.Kind = KBTS_ALLOCATOR_OP_KIND_ALLOCATE; + AllocatorOp.Allocate.Size = (kbts_u32)Size; + + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + Allocator(AllocatorData, &AllocatorOp); + + void *Result = AllocatorOp.Allocate.Pointer; + return Result; +} +#define kbts__AllocatorAllocateType(Allocator, AllocatorData, Type) (Type *)kbts_AllocatorAllocate((Allocator), (AllocatorData), sizeof(Type)) +#define kbts__AllocatorAllocateArray(Allocator, AllocatorData, Type, Count) (Type *)kbts_AllocatorAllocate((Allocator), (AllocatorData), sizeof(Type) * (Count)) + +static void kbts__AllocatorFree(kbts_allocator_function *Allocator, void *AllocatorData, void *Pointer) +{ + if(Pointer) + { + kbts_allocator_op AllocatorOp = KBTS__ZERO; + AllocatorOp.Kind = KBTS_ALLOCATOR_OP_KIND_FREE; + AllocatorOp.Free.Pointer = Pointer; + + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + Allocator(AllocatorData, &AllocatorOp); + } +} + +static void kbts__EnsureArenaInitialized(kbts_arena *Arena) +{ + if(!Arena->BlockSentinel.Next) + { + KBTS__DLLIST_SENTINEL_INIT(&Arena->BlockSentinel); + KBTS__DLLIST_SENTINEL_INIT(&Arena->FreeBlockSentinel); + + if(!Arena->Allocator) + { + Arena->Allocator = kbts__DefaultAllocator; + } + } +} + +#define KBTS_ARENA_MIN_BLOCK_SIZE 4096 +static kbts__arena_block *kbts__ArenaPushBlock(kbts_arena *Arena, kbts_un Size, kbts_un Align) +{ + kbts__arena_block *Result = (kbts__arena_block *)&Arena->BlockSentinel; + + if(!Arena->Error) + { + kbts_un BlockSize = sizeof(kbts__arena_block) + Size + KBTS_ALIGNOF(kbts__arena_block) + Align - 1; + if(BlockSize < KBTS_ARENA_MIN_BLOCK_SIZE) + { + BlockSize = KBTS_ARENA_MIN_BLOCK_SIZE; + } + + Result = (kbts__arena_block *)Arena->FreeBlockSentinel.Prev; + if((Result == (kbts__arena_block *)&Arena->FreeBlockSentinel) || + ((Result->Size + sizeof(kbts__arena_block)) < BlockSize)) + { + void *Base = kbts__AllocatorAllocate(Arena->Allocator, Arena->AllocatorData, BlockSize); + + if(Base) + { + Result = KBTS__ALIGN_POINTER(kbts__arena_block, Base, KBTS_ALIGNOF(kbts__arena_block)); + KBTS_MEMSET(Result, 0, sizeof(*Result)); + Result->BaseAllocation = Base; + Result->Size = (kbts_un)(KBTS__POINTER_OFFSET(char, Base, BlockSize) - KBTS__POINTER_AFTER(char, Result)); + } + else + { + Result = (kbts__arena_block *)&Arena->BlockSentinel; + Arena->Error = 1; + } + } + else + { + KBTS__DLLIST_REMOVE(&Result->Header); + } + + KBTS__DLLIST_INSERT_BEFORE(&Result->Header, &Arena->BlockSentinel); + + Result->Used = 0; + } + + return Result; +} + +static int kbts__ArenaBlockIsValid(kbts_arena *Arena, kbts__arena_block *Block) +{ + int Result = Block && (&Block->Header != &Arena->BlockSentinel); + return Result; +} + +static void kbts__ClearArena(kbts_arena *Arena) +{ + kbts__EnsureArenaInitialized(Arena); + + kbts_arena_block_header *First = Arena->BlockSentinel.Next; + kbts_arena_block_header *Last = Arena->BlockSentinel.Prev; + + if(kbts__ArenaBlockIsValid(Arena, (kbts__arena_block *)First)) + { + First->Prev = Arena->FreeBlockSentinel.Prev; + Last->Next = &Arena->FreeBlockSentinel; + + First->Prev->Next = First; + Last->Next->Prev = Last; + + KBTS__DLLIST_SENTINEL_INIT(&Arena->BlockSentinel); + } +} + +static void *kbts__PushSize(kbts_arena *Arena, kbts_un Size, kbts_un Align) +{ + kbts__EnsureArenaInitialized(Arena); + void *Result = 0; + + if(!Arena->Error) + { + kbts__arena_block *Block = (kbts__arena_block *)Arena->BlockSentinel.Prev; + char *BlockMemory = KBTS__POINTER_AFTER(char, Block); + + if(kbts__ArenaBlockIsValid(Arena, Block)) + { + char *Top = BlockMemory + Block->Used; + char *TopAligned = KBTS__ALIGN_POINTER(char, Top, Align); + + if((kbts_un)((TopAligned + Size) - BlockMemory) <= Block->Size) + { + Result = TopAligned; + } + } + + if(!Result) + { + Block = kbts__ArenaPushBlock(Arena, Size, Align); + + if(kbts__ArenaBlockIsValid(Arena, Block)) + { + BlockMemory = KBTS__POINTER_AFTER(char, Block); + char *Top = BlockMemory + Block->Used; + char *TopAligned = KBTS__ALIGN_POINTER(char, Top, Align); + + Result = TopAligned; + } + } + + if(Result) + { + Block->Used = (kbts_un)((char *)Result + Size - BlockMemory); + KBTS_ASSERT(Block->Used <= Block->Size); + } + } + + return Result; +} +#define kbts__PushType(Arena, Type) (Type *)kbts__PushSize((Arena), sizeof(Type), KBTS_ALIGNOF(Type)) +#define kbts__PushArray(Arena, Type, Count) (Type *)kbts__PushSize((Arena), sizeof(Type) * (Count), KBTS_ALIGNOF(Type)) + +static kbts__arena_lifetime kbts__BeginLifetime(kbts_arena *Arena) +{ + kbts__arena_block *Block = (kbts__arena_block *)Arena->BlockSentinel.Prev; + kbts_un Used = 0; + + if(!Block) + { + Block = (kbts__arena_block *)&Arena->BlockSentinel; + } + + if(kbts__ArenaBlockIsValid(Arena, Block)) + { + Used = Block->Used; + } + + kbts__arena_lifetime Result = KBTS__ZERO; + Result.Arena = Arena; + Result.BlockHeader = &Block->Header; + Result.Used = Used; + return Result; +} + +static void kbts__EndLifetime(kbts__arena_lifetime *Lifetime) +{ + kbts_arena *Arena = Lifetime->Arena; + if(Arena && !Arena->Error) + { + kbts__arena_block *Block = (kbts__arena_block *)Lifetime->BlockHeader; + + if(kbts__ArenaBlockIsValid(Lifetime->Arena, Block)) + { + Block->Used = Lifetime->Used; + } + + // This works even if Block is the sentinel. + for(kbts_arena_block_header *Header = Block->Header.Next; + kbts__ArenaBlockIsValid(Arena, (kbts__arena_block *)Header); + ) + { + kbts_arena_block_header *Next = Header->Next; + + KBTS__DLLIST_REMOVE(Header); + KBTS__DLLIST_INSERT_BEFORE(Header, &Arena->FreeBlockSentinel); + + Header = Next; + } + } +} + +static void kbts__MoveArena(kbts_arena *To, kbts_arena *From) +{ + *To = *From; + + if(To->BlockSentinel.Next != &From->BlockSentinel) + { + To->BlockSentinel.Next->Prev = To->BlockSentinel.Prev->Next = &To->BlockSentinel; + } + else + { + KBTS__DLLIST_SENTINEL_INIT(&To->BlockSentinel); + } + + if(To->FreeBlockSentinel.Next != &From->FreeBlockSentinel) + { + To->FreeBlockSentinel.Next->Prev = To->FreeBlockSentinel.Prev->Next = &To->FreeBlockSentinel; + } + else + { + KBTS__DLLIST_SENTINEL_INIT(&To->FreeBlockSentinel); + } +} + +static void kbts__FreeArena(kbts_arena *Arena) +{ + kbts__EnsureArenaInitialized(Arena); + + kbts_arena StackArena; + kbts__MoveArena(&StackArena, Arena); + + kbts_arena_block_header *Sentinels[2] = {&StackArena.BlockSentinel, &StackArena.FreeBlockSentinel}; + + KBTS__FOR(SentinelIndex, 0, KBTS__ARRAY_LENGTH(Sentinels)) + { + kbts_arena_block_header *Sentinel = Sentinels[SentinelIndex]; + + for(kbts_arena_block_header *Header = Sentinel->Next; + Header != Sentinel; + ) + { + kbts_arena_block_header *Next = Header->Next; + kbts__arena_block *Block = (kbts__arena_block *)Header; + + kbts__AllocatorFree(StackArena.Allocator, StackArena.AllocatorData, Block->BaseAllocation); + + Header = Next; + } + } +} + +static void kbts__ArenaAllocator(void *Data, kbts_allocator_op *Op) +{ + kbts_arena *Arena = (kbts_arena *)Data; + + if(Op->Kind == KBTS_ALLOCATOR_OP_KIND_ALLOCATE) + { + Op->Allocate.Pointer = kbts__PushSize(Arena, Op->Allocate.Size, 8); + } + // No free! +} + +static int kbts__InitializeFixedMemoryArena(kbts_arena *Arena, void *Memory, kbts_un MemorySize) +{ + int Result = 0; + KBTS_MEMSET(Arena, 0, sizeof(*Arena)); + Arena->Allocator = kbts__NullAllocator; + kbts__EnsureArenaInitialized(Arena); + + char *BaseAligned = KBTS__ALIGN_POINTER(char, Memory, KBTS_ALIGNOF(kbts__arena_block)); + char *End = (char *)Memory + MemorySize; + kbts_un TotalBlockSize = (kbts_un)(End - BaseAligned); + + if(TotalBlockSize >= sizeof(kbts__arena_block)) + { + kbts__arena_block *Block = (kbts__arena_block *)BaseAligned; + + Block->Header.Prev = Block->Header.Next = &Arena->BlockSentinel; + Block->Header.Prev->Next = Block->Header.Next->Prev = &Block->Header; + Block->BaseAllocation = 0; + Block->Size = TotalBlockSize - sizeof(kbts__arena_block); + Block->Used = 0; + + Result = 1; + } + + return Result; +} + +static kbts_glyph *kbts__InsertGlyph(kbts_glyph_storage *Storage, kbts_glyph *Anchor, int InsertBeforeAnchor, kbts_glyph *BaseGlyph) +{ + kbts_glyph *Result = Storage->FreeGlyphSentinel.Next; + + if(Result != &Storage->FreeGlyphSentinel) + { + KBTS__DLLIST_REMOVE(Result); + } + else + { + Result = kbts__PushType(&Storage->Arena, kbts_glyph); + } + + if(Result) + { + if(BaseGlyph) + { + *Result = *BaseGlyph; + } + + if(InsertBeforeAnchor) + { + Result->Next = Anchor; + Result->Prev = Anchor->Prev; + } + else + { + Result->Prev = Anchor; + Result->Next = Anchor->Next; + } + + Result->Prev->Next = Result->Next->Prev = Result; + } + else + { + Storage->Error = 1; + } + + return Result; +} +static kbts_glyph *kbts__InsertGlyphBefore(kbts_glyph_storage *Storage, kbts_glyph *Anchor, kbts_glyph *BaseGlyph) +{ + kbts_glyph *Result = kbts__InsertGlyph(Storage, Anchor, 1, BaseGlyph); + return Result; +} +static kbts_glyph *kbts__InsertGlyphAfter(kbts_glyph_storage *Storage, kbts_glyph *Anchor, kbts_glyph *BaseGlyph) +{ + kbts_glyph *Result = kbts__InsertGlyph(Storage, Anchor, 0, BaseGlyph); + return Result; +} + +static kbts_glyph *kbts__FreeGlyph(kbts__shape_scratchpad *Scratchpad, kbts_glyph_storage *Storage, kbts_glyph *Glyph) +{ + if(Glyph == Scratchpad->LookupOnePastLastGlyph) + { + Scratchpad->LookupOnePastLastGlyph = Glyph->Next; + } + if(Glyph == Scratchpad->Cluster.SentinelPrev) + { + Scratchpad->Cluster.SentinelPrev = Glyph->Prev; + } + if(Glyph == Scratchpad->Cluster.SentinelNext) + { + Scratchpad->Cluster.SentinelNext = Glyph->Next; + } + + KBTS__DLLIST_REMOVE(Glyph); + KBTS__DLLIST_INSERT_BEFORE(Glyph, (kbts_glyph *)&Storage->FreeGlyphSentinel); + + return Glyph; +} + +static kbts_glyph *kbts__SetGlyphPreserveLinksAndUserId(kbts_glyph *Dest, kbts_glyph *Source) +{ + kbts_glyph *Prev = Dest->Prev; + kbts_glyph *Next = Dest->Next; + int UserId = Dest->UserIdOrCodepointIndex; + + *Dest = *Source; + + Dest->Prev = Prev; + Dest->Next = Next; + Dest->UserIdOrCodepointIndex = UserId; + + return Dest; +} + +static int kbts__BeginFeatures(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_shaping_table ShapingTable) +{ + int Result = 0; + kbts_blob_table_id TableId = (ShapingTable == KBTS_SHAPING_TABLE_GSUB) ? KBTS_BLOB_TABLE_ID_GSUB : KBTS_BLOB_TABLE_ID_GPOS; + kbts__gsub_gpos *GsubGpos = kbts__BlobTableDataType(Config->Font->Blob, TableId, kbts__gsub_gpos); + kbts__langsys *Langsys = Config->Langsys[ShapingTable]; + kbts_un FeatureStageIndex = Scratchpad->FeatureStagesRead - 1; + + Scratchpad->FeatureIndexIndex = 0; + + if(GsubGpos && Langsys && (FeatureStageIndex < Config->OpList.FeatureStageCount)) + { + kbts__baked_feature_stage *BakedFeatureStage = &Config->FeatureStages[FeatureStageIndex]; + + // @Incomplete + // if(GsubGpos->Minor == 1) + // { + // kbts__feature_variations *FeatureVariations = KBTS__POINTER_OFFSET(kbts__feature_variations, GsubGpos, GsubGpos->FeatureVariationsOffset); + // } + + + KBTS__FOR(FeatureIndex, 0, BakedFeatureStage->FeatureCount) + { + Scratchpad->BakedLookupSubtablesRead[FeatureIndex] = 0; + } + + Result = 1; + } + + return Result; +} + +typedef struct kbts__sequence_lookup_result +{ + kbts__sequence_lookup_record *Records; + kbts_un RecordCount; + kbts_un InputSequenceCountIncludingSkippedGlyphs; + + kbts_glyph *OnePastLastGlyphMatched; + + // This is specified _nowhere_ in the docs, BUT some sequence lookups have 0 records, and exist just to prevent the + // next lookups from executing. + // So, checking if we got any records is not enough to figure out whether we need to "apply" this lookup. + // We need to have an explicit bool as well. + // Sigh. + int Matched; +} kbts__sequence_lookup_result; + +typedef struct kbts__sequence_match +{ + kbts_un MatchCount; + kbts_un MatchOrSkipCount; + kbts_glyph *OnePastMatchGlyph; +} kbts__sequence_match; + +static kbts__sequence_match kbts__MatchCoverageSequence(kbts_glyph_storage *Storage, kbts__unpacked_lookup *Lookup, kbts_u32 SkipFlags, kbts_u32 SkipUnicodeFlags, + void *Base, kbts_u16 *CoverageOffsets, kbts_un CoverageCount, + kbts_glyph *AtGlyph, int Backward) +{ + kbts_un CoverageIndex = 0; + kbts_un GlyphCounter = 0; + while(kbts__GlyphIsValid(Storage, AtGlyph) && (CoverageIndex < CoverageCount)) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Base, CoverageOffsets[CoverageIndex]); + + if(!kbts__SkipGlyph(AtGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + kbts__cover_glyph_result Cover = kbts__CoverGlyph(Coverage, AtGlyph->Id); + + if(Cover.Valid) + { + CoverageIndex += 1; + } + else + { + break; + } + } + + AtGlyph = Backward ? AtGlyph->Prev : AtGlyph->Next; + GlyphCounter += 1; + } + + kbts__sequence_match Result = KBTS__ZERO; + Result.MatchCount = CoverageIndex; + Result.MatchOrSkipCount = GlyphCounter; + Result.OnePastMatchGlyph = AtGlyph; + return Result; +} + +static int kbts__BranchlessCompareArray16(kbts_u16 *A, kbts_u16 *B, kbts_un Count) +{ + kbts_u16 DifferenceMask = 0; + KBTS__FOR(Index, 0, Count) + { + DifferenceMask |= A[Index] ^ B[Index]; + } + return (int)DifferenceMask; +} + +static kbts__sequence_lookup_result kbts__DoSequenceLookup(kbts_glyph_storage *Storage, kbts__unpacked_lookup *Lookup, kbts_u16 *Base, kbts__cover_glyph_result Cover, + kbts_glyph *AtGlyph, kbts__skip_flags SkipFlags, kbts_u32 SkipUnicodeFlags) +{ + KBTS_INSTRUMENT_FUNCTION_BEGIN; + kbts__sequence_lookup_result Result = KBTS__ZERO; + Result.OnePastLastGlyphMatched = AtGlyph->Next; + + kbts_glyph *CurrentGlyph = AtGlyph; + kbts_glyph *InputGlyph = AtGlyph->Next; + kbts_un InputGlyphsTraversed = 1; + kbts_glyph *BacktrackGlyph = AtGlyph->Prev; + + // Lookup types 7 and 8 are dispatch mechanisms. They do not substitute anything by themselves, they only point to + // other rules. + // Some formats have multiple rules; when that happens, we only ever match on the first one that fits. + + // We want to go to the right LookupType/SubtableFormat combination in a single jump, so we concatenate them here. + // GSUB format 5 == GPOS format 7. + // GSUB format 6 == GPOS format 8. + switch(((kbts_u32)Lookup->Type << 16) | (kbts_u32)Base[0]) + { + case 0x50001: + case 0x70001: + { + kbts__sequence_context_1 *Subst = (kbts__sequence_context_1 *)Base; + kbts__sequence_rule_set *Set = kbts__GetSequenceRuleSet(Subst, Cover.Index); + + if(Set) + { + kbts_u16 Ids[64]; // @Hardcoded + kbts_u16 InputGlyphOffsets[64]; + kbts_glyph *InputGlyphs[64]; + kbts_un IdCount = 0; + + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__sequence_rule *Rule = kbts__GetSequenceRule(Set, RuleIndex); + kbts_u16 *InputSequence = KBTS__POINTER_AFTER(kbts_u16, Rule); + + // @Hardcoded! + KBTS_ASSERT(Rule->GlyphCount <= 64); + + while(kbts__GlyphIsValid(Storage, InputGlyph) && ((IdCount + 1) < Rule->GlyphCount)) + { + if(!kbts__SkipGlyph(InputGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + InputGlyphOffsets[IdCount] = (kbts_u16)InputGlyphsTraversed; + InputGlyphs[IdCount] = InputGlyph; + Ids[IdCount++] = InputGlyph->Id; + } + + InputGlyph = InputGlyph->Next; + InputGlyphsTraversed += 1; + } + + if(((IdCount + 1) >= Rule->GlyphCount) && + !kbts__BranchlessCompareArray16(Ids, InputSequence, Rule->GlyphCount - 1)) + { + Result.Records = (kbts__sequence_lookup_record *)(InputSequence + Rule->GlyphCount - 1); + Result.RecordCount = Rule->SequenceLookupCount; + Result.InputSequenceCountIncludingSkippedGlyphs = 1; + if(Rule->GlyphCount > 1) + { + Result.InputSequenceCountIncludingSkippedGlyphs = InputGlyphOffsets[Rule->GlyphCount - 2] + 1; + Result.OnePastLastGlyphMatched = InputGlyphs[Rule->GlyphCount - 2]->Next; + } + Result.Matched = 1; + + break; + } + } + } + } + break; + + case 0x50002: + case 0x70002: + { + kbts__sequence_context_2 *Subst = (kbts__sequence_context_2 *)Base; + kbts_u16 *ClassDefinitionBase = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->ClassDefOffset); + + // @Hardcoded! + kbts_u16 InputClasses[64]; + kbts_u16 InputOffsets[64]; + kbts_glyph *InputGlyphs[64]; + kbts_un InputCount = 0; + + // For class-based contexts, the coverage index is not used. + // Instead, we know which set to use based on the current glyph's class. + // From the Microsoft docs: + // The class value is used as the index into an array of offsets to ClassSequenceRuleSet tables. + kbts__glyph_class_from_table_result CurrentGlyphClass = kbts__GlyphClassFromTable(ClassDefinitionBase, CurrentGlyph->Id); + kbts__class_sequence_rule_set *Set = kbts__GetClassSequenceRuleSet(Subst, CurrentGlyphClass.Class); + + if((CurrentGlyphClass.Class < Subst->ClassSequenceRuleSetCount) && Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__class_sequence_rule *Rule = kbts__GetClassSequenceRule(Set, RuleIndex); + kbts_u16 *InputSequence = KBTS__POINTER_AFTER(kbts_u16, Rule); + + while(kbts__GlyphIsValid(Storage, InputGlyph) && ((InputCount + 1) < Rule->GlyphCount)) + { + if(!kbts__SkipGlyph(InputGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + InputOffsets[InputCount] = (kbts_u16)InputGlyphsTraversed; + InputGlyphs[InputCount] = InputGlyph; + InputClasses[InputCount++] = kbts__GlyphClassFromTable(ClassDefinitionBase, InputGlyph->Id).Class; + } + + InputGlyph = InputGlyph->Next; + InputGlyphsTraversed += 1; + } + + if(((InputCount + 1) >= Rule->GlyphCount) && + !kbts__BranchlessCompareArray16(InputClasses, InputSequence, Rule->GlyphCount - 1)) + { + Result.Records = (kbts__sequence_lookup_record *)(InputSequence + Rule->GlyphCount - 1); + Result.RecordCount = Rule->SequenceLookupCount; + Result.InputSequenceCountIncludingSkippedGlyphs = 1; + if(Rule->GlyphCount > 1) + { + Result.InputSequenceCountIncludingSkippedGlyphs = InputOffsets[Rule->GlyphCount - 2] + 1; + Result.OnePastLastGlyphMatched = InputGlyphs[Rule->GlyphCount - 2]->Next; + } + Result.Matched = 1; + + break; + } + } + } + } + break; + + case 0x50003: + case 0x70003: + { + kbts__sequence_context_3 *Subst = (kbts__sequence_context_3 *)Base; + kbts_u16 *CoverageOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + + kbts__sequence_match InputMatch = kbts__MatchCoverageSequence(Storage, Lookup, SkipFlags, SkipUnicodeFlags, Subst, CoverageOffsets, Subst->GlyphCount, AtGlyph, 0); + + if(InputMatch.MatchCount == Subst->GlyphCount) + { + Result.Records = (kbts__sequence_lookup_record *)(CoverageOffsets + Subst->GlyphCount); + Result.RecordCount = Subst->SequenceLookupCount; + Result.InputSequenceCountIncludingSkippedGlyphs = InputMatch.MatchOrSkipCount; + Result.OnePastLastGlyphMatched = InputMatch.OnePastMatchGlyph; + Result.Matched = 1; + } + } + break; + + case 0x60001: + case 0x80001: + { + kbts__chained_sequence_context_1 *Subst = (kbts__chained_sequence_context_1 *)Base; + kbts__chained_sequence_rule_set *Set = kbts__GetChainedSequenceRuleSet(Subst, Cover.Index); + + if(Set) + { + // @Hardcoded! + kbts_u16 BacktrackIds[64]; + kbts_u16 InputIds[64]; + kbts_u16 InputOffsets[64]; + kbts_glyph *InputGlyphs[64]; + kbts_un BacktrackCount = 0; + kbts_un InputCount = 0; + + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedSequenceRule(Set, RuleIndex); + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 0); + + while(kbts__GlyphIsValid(Storage, BacktrackGlyph) && (BacktrackCount < Unpacked.BacktrackCount)) + { + if(!kbts__SkipGlyph(BacktrackGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + BacktrackIds[BacktrackCount++] = BacktrackGlyph->Id; + } + + BacktrackGlyph = BacktrackGlyph->Prev; + } + + kbts_un TotalInputGlyphsRequired = Unpacked.InputCount - 1 + Unpacked.LookaheadCount; + while(kbts__GlyphIsValid(Storage, InputGlyph) && (InputCount < TotalInputGlyphsRequired)) + { + if(!kbts__SkipGlyph(InputGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + InputGlyphs[InputCount] = InputGlyph; + InputOffsets[InputCount] = (kbts_u16)InputGlyphsTraversed; + InputIds[InputCount++] = InputGlyph->Id; + } + + InputGlyph = InputGlyph->Next; + InputGlyphsTraversed += 1; + } + + if((BacktrackCount >= Unpacked.BacktrackCount) && (InputCount >= TotalInputGlyphsRequired) && + !kbts__BranchlessCompareArray16(BacktrackIds, Unpacked.Backtrack, Unpacked.BacktrackCount) && + !kbts__BranchlessCompareArray16(InputIds, Unpacked.Input, Unpacked.InputCount - 1) && + !kbts__BranchlessCompareArray16(InputIds + Unpacked.InputCount - 1, Unpacked.Lookahead, Unpacked.LookaheadCount)) + { + Result.Records = Unpacked.Records; + Result.RecordCount = Unpacked.RecordCount; + Result.InputSequenceCountIncludingSkippedGlyphs = 1; + if(Unpacked.InputCount > 1) + { + Result.InputSequenceCountIncludingSkippedGlyphs = InputOffsets[Unpacked.InputCount - 2] + 1; + Result.OnePastLastGlyphMatched = InputGlyphs[Unpacked.InputCount - 2]->Next; + } + Result.Matched = 1; + + break; + } + } + } + } + break; + + case 0x60002: + case 0x80002: + { + kbts__chained_sequence_context_2 *Subst = (kbts__chained_sequence_context_2 *)Base; + kbts_u16 *BacktrackClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->BacktrackClassDefOffset); + kbts_u16 *InputClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->InputClassDefOffset); + kbts_u16 *LookaheadClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->LookaheadClassDefOffset); + + // @Incomplete: Do this with all sequence types! + + // @Hardcoded: Pre-alloc this using LookupInfo! + kbts_u16 BacktrackClasses[64]; + kbts_u16 InputClasses[64]; + kbts_u16 InputClassOffsets[64]; + kbts_glyph *InputGlyphs[64]; + kbts_u16 LookaheadClasses[64]; + kbts_un BacktrackClassCount = 0; + kbts_un InputClassCount = 0; + + // Just like lookup 5.2, we use the current glyph class to figure out which set to look up. + // From the Microsoft docs: + // If found, the client then searches in the class definition table to find the class value assigned to the + // current glyph. The class value is used as the index into an array of offsets to ChainedClassSequenceRuleSet + // tables. + // + kbts_u16 CurrentGlyphClass = kbts__GlyphClassFromTable(InputClassDefinition, CurrentGlyph->Id).Class; + kbts__chained_sequence_rule_set *Set = kbts__GetChainedClassSequenceRuleSet(Subst, CurrentGlyphClass); + // If the glyph was contained in the coverage table, then it should have a valid class. + // Nevertheless, one Harfbuzz test font did not remove out-of-bounds glyph classes from the class definition + // table here, so we double-check it here. + // (It is also possible for a font to want to reuse the same class definition table across multiple lookups, + // in which case ignoring these classes becomes a feature.) + if((CurrentGlyphClass < Subst->ChainedClassSequenceRuleSetCount) && Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedClassSequenceRule(Set, RuleIndex); + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 0); + + // @Hardcoded + KBTS_ASSERT(Unpacked.BacktrackCount <= 64); + KBTS_ASSERT(Unpacked.InputCount <= 64); + KBTS_ASSERT(Unpacked.LookaheadCount <= 64); + + while(kbts__GlyphIsValid(Storage, BacktrackGlyph) && (BacktrackClassCount < Unpacked.BacktrackCount)) + { + if(!kbts__SkipGlyph(BacktrackGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + // @Robustness: Do we want to break if we don't find a class? + kbts__glyph_class_from_table_result Class = kbts__GlyphClassFromTable(BacktrackClassDefinition, BacktrackGlyph->Id); + BacktrackClasses[BacktrackClassCount++] = Class.Class; + } + + BacktrackGlyph = BacktrackGlyph->Prev; + } + + kbts_un InputClassCountRequired = Unpacked.InputCount - 1 + Unpacked.LookaheadCount; + while(kbts__GlyphIsValid(Storage, InputGlyph) && (InputClassCount < InputClassCountRequired)) + { + if(!kbts__SkipGlyph(InputGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + kbts__glyph_class_from_table_result InputClass = kbts__GlyphClassFromTable(InputClassDefinition, InputGlyph->Id); + // In many cases, the font designer just wants to match "a set of glyphs" forward, + // and it doesn't matter whether those glyphs are in the input sequence or part of the lookahead. + // This happens often enough that we care to special-case it. + kbts__glyph_class_from_table_result LookaheadClass = InputClass; + if(LookaheadClassDefinition != InputClassDefinition) + { + LookaheadClass = kbts__GlyphClassFromTable(LookaheadClassDefinition, InputGlyph->Id); + } + + // @Robustness: Do we want to break if we don't find a class? + InputGlyphs[InputClassCount] = InputGlyph; + InputClassOffsets[InputClassCount] = (kbts_u16)InputGlyphsTraversed; + InputClasses[InputClassCount] = InputClass.Class; + LookaheadClasses[InputClassCount] = LookaheadClass.Class; + + InputClassCount += 1; + } + + InputGlyph = InputGlyph->Next; + InputGlyphsTraversed += 1; + } + + if((BacktrackClassCount >= Unpacked.BacktrackCount) && + (InputClassCount >= InputClassCountRequired) && + !kbts__BranchlessCompareArray16(BacktrackClasses, Unpacked.Backtrack, Unpacked.BacktrackCount) && + !kbts__BranchlessCompareArray16(InputClasses, Unpacked.Input, Unpacked.InputCount - 1) && + !kbts__BranchlessCompareArray16(LookaheadClasses + Unpacked.InputCount - 1, Unpacked.Lookahead, Unpacked.LookaheadCount)) + { + Result.Records = Unpacked.Records; + Result.RecordCount = Unpacked.RecordCount; + Result.InputSequenceCountIncludingSkippedGlyphs = 1; + if(Unpacked.InputCount > 1) + { + Result.InputSequenceCountIncludingSkippedGlyphs = InputClassOffsets[Unpacked.InputCount - 2] + 1; + Result.OnePastLastGlyphMatched = InputGlyphs[Unpacked.InputCount - 2]->Next; + } + Result.Matched = 1; + + break; + } + } + } + } + break; + + case 0x60003: + case 0x80003: + { + kbts__chained_sequence_context_3 *Subst = (kbts__chained_sequence_context_3 *)Base; + kbts__unpacked_chained_sequence_context_3 Unpacked = kbts__UnpackChainedSequenceContext3(Subst, 0); + + // Since chained sequence contexts roll the coverage for the first glyph into an array, you'd think that + // the matching logic for the first glyph would be the same as for any other glyph in that array. + // You'd be wrong! + // The first glyph does _not_ have to pass glyph filtering logic. It just has to pass the coverage test. + // Every other input glyph still does, though. + kbts__cover_glyph_result CurrentCover = KBTS__ZERO; + CurrentCover.Valid = !Unpacked.InputCount || kbts__GlyphPassesLookupFilter(CurrentGlyph, Lookup); + if(Unpacked.InputCount) + { + kbts__coverage *CurrentCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.InputCoverageOffsets[0]); + CurrentCover = kbts__CoverGlyph(CurrentCoverage, CurrentGlyph->Id); + } + + if(CurrentCover.Valid) + { + kbts__sequence_match BacktrackMatch = kbts__MatchCoverageSequence(Storage, Lookup, SkipFlags, SkipUnicodeFlags, Subst, Unpacked.BacktrackCoverageOffsets, Unpacked.BacktrackCount, BacktrackGlyph, 1); + kbts__sequence_match InputMatch = kbts__MatchCoverageSequence(Storage, Lookup, SkipFlags, SkipUnicodeFlags, Subst, Unpacked.InputCoverageOffsets + 1, Unpacked.InputCount - 1, InputGlyph, 0); + kbts_un MatchingInputGlyphCount = 1 + InputMatch.MatchCount; + kbts_un MatchedOrSkippedInputGlyphCount = 1 + InputMatch.MatchOrSkipCount; + kbts__sequence_match LookaheadMatch = kbts__MatchCoverageSequence(Storage, Lookup, SkipFlags, SkipUnicodeFlags, Subst, Unpacked.LookaheadCoverageOffsets, Unpacked.LookaheadCount, InputMatch.OnePastMatchGlyph, 0); + + if((BacktrackMatch.MatchCount == Unpacked.BacktrackCount) && ((MatchingInputGlyphCount) == Unpacked.InputCount) && (LookaheadMatch.MatchCount == Unpacked.LookaheadCount)) + { + Result.Records = Unpacked.Records; + Result.RecordCount = Unpacked.RecordCount; + Result.InputSequenceCountIncludingSkippedGlyphs = MatchedOrSkippedInputGlyphCount; + Result.OnePastLastGlyphMatched = InputMatch.OnePastMatchGlyph; + Result.Matched = 1; + + break; + } + } + } + break; + } + + KBTS_INSTRUMENT_FUNCTION_END; + return Result; +} + +static void kbts__ApplyValueRecord(kbts_glyph *Glyph, kbts__unpacked_value_record *Unpacked) +{ + Glyph->OffsetX += Unpacked->PlacementX; + Glyph->OffsetY += Unpacked->PlacementY; + + Glyph->AdvanceX += Unpacked->AdvanceX; + Glyph->AdvanceY += Unpacked->AdvanceY; +} + +static int kbts__NextGlyph(kbts_glyph_storage *Storage, kbts__unpacked_lookup *Lookup, kbts_glyph *AtGlyph, kbts__skip_flags SkipFlags, kbts_u32 SkipUnicodeFlags, kbts_glyph **Match, int Backward) +{ + kbts_glyph *MatchingGlyph = 0; + + while(kbts__GlyphIsValid(Storage, AtGlyph)) + { + if(!kbts__SkipGlyph(AtGlyph, Lookup, SkipFlags, SkipUnicodeFlags)) + { + MatchingGlyph = AtGlyph; + break; + } + else + { + AtGlyph = Backward ? AtGlyph->Prev : AtGlyph->Next; + } + } + + *Match = MatchingGlyph; + return MatchingGlyph != 0; +} + +static void kbts__AttachGlyph(kbts_glyph_storage *Storage, kbts_glyph *Parent, kbts_glyph *Child, kbts_s32 X, kbts_s32 Y) +{ + kbts_s32 DeltaOffsetX = X - Child->OffsetX; + kbts_s32 DeltaOffsetY = Y - Child->OffsetY; + + Child->OffsetX = X; + Child->OffsetY = Y; + Child->Flags |= KBTS_GLYPH_FLAG_USED_IN_GPOS; + Child->AttachGlyph = Parent; + + Parent->Flags |= KBTS_GLYPH_FLAG_USED_IN_GPOS; + + for(kbts_glyph *MiddleGlyph = Parent->Next; + MiddleGlyph != Child; + MiddleGlyph = MiddleGlyph->Next) + { + MiddleGlyph->Flags |= KBTS_GLYPH_FLAG_NO_BREAK; + } + + // @Speed: Fuck this. + // Attachments can happen in anti-topological order, so we have to fix them up here. + // We should store glyph parent/child indices instead of traversing all glyphs. + for(kbts_glyph *PostGlyph = Child->Next; + kbts__GlyphIsValid(Storage, PostGlyph); + PostGlyph = PostGlyph->Next) + { + if(PostGlyph->AttachGlyph == Child) + { + PostGlyph->OffsetX += DeltaOffsetX; + PostGlyph->OffsetY += DeltaOffsetY; + } + } +} + +static void kbts__SetLookupOnePastLastGlyph(kbts__shape_scratchpad *Scratchpad, kbts_un Index, kbts_glyph *Glyph) +{ + if(Index > Scratchpad->LookupOnePastLastGlyphIndex) + { + Scratchpad->LookupOnePastLastGlyphIndex = (kbts_u32)Index; + Scratchpad->LookupOnePastLastGlyph = Glyph; + } +} + +typedef kbts_u32 kbts__cursive_flags; +enum kbts__cursive_flags_enum +{ + KBTS__CURSIVE_FLAG_NONE, + KBTS__CURSIVE_FLAG_START = (1 << 0), + KBTS__CURSIVE_FLAG_END = (1 << 1), +}; + +KBTS_INLINE kbts__cursive_flags kbts__GetCursiveFlags(kbts_glyph *Glyph) +{ + kbts__cursive_flags Result = (kbts__cursive_flags)Glyph->MarkOrdering; + return Result; +} + +KBTS_INLINE void kbts__SetCursiveFlags(kbts_glyph *Glyph, kbts__cursive_flags CursiveFlags) +{ + Glyph->MarkOrdering = (kbts_u8)CursiveFlags; +} + +static int kbts__DoSingleAdjustment(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_lookup_list *LookupList, kbts_un LookupIndex, kbts_un SubtableIndex, kbts__unpacked_lookup *Lookup, kbts_u16 *Base, + kbts_glyph *CurrentGlyph, kbts_un StartIndex, kbts__skip_flags RequestedSkipFlags) +{ + KBTS_INSTRUMENT_FUNCTION_BEGIN; + kbts_unicode_flags SkipUnicodeFlags = KBTS_UNICODE_FLAG_DEFAULT_IGNORABLE; + kbts__skip_flags RegularSkipFlags = KBTS__SKIP_FLAGS_GPOS_REGULAR(RequestedSkipFlags); + kbts__skip_flags SequenceSkipFlags = KBTS__SKIP_FLAGS_GPOS_SEQUENCE(RequestedSkipFlags); + + int Result = 0; + + kbts_un OnePastLastGlyphIndex = StartIndex + 1; + kbts_glyph *OnePastLastGlyph = CurrentGlyph->Next; + + if(kbts__GlyphsIncludedInLookupSubtable(Storage, Config->Font, 1, Lookup, LookupIndex, SubtableIndex, CurrentGlyph, SequenceSkipFlags, SkipUnicodeFlags)) + { + // CAREFUL: We want kbts__unpacked_lookup to be a useful bag-of-arguments type, but, for extension + // lookups, each subtable may specify its own lookup type, so we save it here and restore it at + // the end of this function. + kbts_u16 OriginalLookupType = Lookup->Type; + + while(Lookup->Type == 9) + { + kbts__extension *Extension = (kbts__extension *)Base; + + Lookup->Type = Extension->LookupType; + Base = KBTS__POINTER_OFFSET(kbts_u16, Extension, Extension->Offset); + } + + kbts__cover_glyph_result Cover = KBTS__ZERO; + Cover.Valid = kbts__GlyphPassesLookupFilter(CurrentGlyph, Lookup); + kbts__coverage *Coverage = 0; + if(Cover.Valid && kbts__GposLookupBeginsWithCoverage(Lookup->Type, Base[0])) + { + kbts_u16 *CoverageOffset = Base + 1; + Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Base, *CoverageOffset); + Cover = kbts__CoverGlyph(Coverage, CurrentGlyph->Id); + } + + if(Cover.Valid) + { + kbts_un OnePastLastGlyphOffset = 0; + + switch(Lookup->Type) + { + case 1: + { + kbts__unpacked_value_record Unpacked = KBTS__ZERO; + + if(Base[0] == 1) + { + kbts__single_adjustment_1 *Adjust = (kbts__single_adjustment_1 *)Base; + + Unpacked = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat, KBTS__POINTER_AFTER(kbts_u16, Adjust)); + } + else if(Base[0] == 2) + { + kbts__single_adjustment_2 *Adjust = (kbts__single_adjustment_2 *)Base; + + kbts_un RecordSize = kbts__PopCount32(Adjust->ValueFormat); + kbts_u16 *Records = KBTS__POINTER_AFTER(kbts_u16, Adjust); + kbts_u16 *Record = Records + RecordSize * Cover.Index; + + Unpacked = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat, Record); + } + + kbts__ApplyValueRecord(CurrentGlyph, &Unpacked); + CurrentGlyph->Flags |= KBTS_GLYPH_FLAG_USED_IN_GPOS; + + Result = 1; + } + break; + + case 2: + { + kbts_glyph *NextGlyph; + if(kbts__NextGlyph(Storage, Lookup, CurrentGlyph->Next, RegularSkipFlags, SkipUnicodeFlags, &NextGlyph, 0)) + { + kbts_u32 NextGlyphId = NextGlyph->Id; + + kbts__unpacked_value_record Unpacked1 = KBTS__ZERO; + kbts__unpacked_value_record Unpacked2 = KBTS__ZERO; + int Valid = 0; + + if(Base[0] == 1) + { + kbts__pair_adjustment_1 *Adjust = (kbts__pair_adjustment_1 *)Base; + + kbts_un Size1 = kbts__PopCount32(Adjust->ValueFormat1); + kbts_un Size2 = kbts__PopCount32(Adjust->ValueFormat2); + + kbts_u16 *SetOffsets = KBTS__POINTER_AFTER(kbts_u16, Adjust); + kbts__pair_set *Set = KBTS__POINTER_OFFSET(kbts__pair_set, Adjust, SetOffsets[Cover.Index]); + + kbts_un PairRecordSize = Size1 + Size2 + 1; // + 1 because each pair stores the next glyph ID. + kbts__pair_value_record *PairRecords = KBTS__POINTER_AFTER(kbts__pair_value_record, Set); + KBTS__FOR(PairIndex, 0, Set->Count) + { + kbts__pair_value_record *PairRecord = PairRecords + PairRecordSize * PairIndex; + + if(PairRecord->SecondGlyph == NextGlyphId) + { + kbts_u16 *Records = KBTS__POINTER_AFTER(kbts_u16, PairRecord); + + Unpacked1 = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat1, Records); + Records += Unpacked1.Size; + Unpacked2 = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat2, Records); + Valid = 1; + } + } + } + else if(Base[0] == 2) + { + kbts__pair_adjustment_2 *Adjust = (kbts__pair_adjustment_2 *)Base; + kbts_u16 *ClassDef1 = KBTS__POINTER_OFFSET(kbts_u16, Adjust, Adjust->ClassDefinition1Offset); + kbts_u16 *ClassDef2 = KBTS__POINTER_OFFSET(kbts_u16, Adjust, Adjust->ClassDefinition2Offset); + + kbts_un Size1 = kbts__PopCount32(Adjust->ValueFormat1); + kbts_un Size2 = kbts__PopCount32(Adjust->ValueFormat2); + kbts_un PairRecordSize = Size1 + Size2; + kbts_u16 *PairRecords = KBTS__POINTER_AFTER(kbts_u16, Adjust); + + // From the Microsoft docs: + // PairPosFormat2 requires that each glyph in all pairs be assigned to a class, which is + // identified by an integer called a class value. + // This _seems_ like it would mean that, if either glyph is not specified in its respective + // class definition table, then we should skip the lookup. + // However, this seems wrong in practice. Undefined classes seem to just default to 0, and then + // the bounds check takes care of deciding whether the lookup is okay to apply or not. + kbts__glyph_class_from_table_result Class1 = kbts__GlyphClassFromTable(ClassDef1, CurrentGlyph->Id); + kbts__glyph_class_from_table_result Class2 = kbts__GlyphClassFromTable(ClassDef2, NextGlyphId); + if((Class1.Class < Adjust->Class1Count) && (Class2.Class < Adjust->Class2Count)) + { + kbts_u16 *PairRecord = PairRecords + Class1.Class * PairRecordSize * Adjust->Class2Count + Class2.Class * PairRecordSize; + + Unpacked1 = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat1, PairRecord); + PairRecord += Size1; + + Unpacked2 = kbts__UnpackValueRecord(Adjust, Adjust->ValueFormat2, PairRecord); + PairRecord += Size2; + Valid = 1; + } + } + + if(Valid) + { + kbts__ApplyValueRecord(CurrentGlyph, &Unpacked1); + CurrentGlyph->Flags |= KBTS_GLYPH_FLAG_USED_IN_GPOS; + + kbts__ApplyValueRecord(NextGlyph, &Unpacked2); + NextGlyph->Flags |= KBTS_GLYPH_FLAG_USED_IN_GPOS; + + Result = 1; + OnePastLastGlyph = Unpacked2.Size ? NextGlyph->Next : CurrentGlyph->Next; + } + } + } + break; + + // All three types of attachment (cursive, mark-to-base, mark-to-ligature) look backward instead of forward. + case 3: + { + kbts__cursive_attachment *Adjust = (kbts__cursive_attachment *)Base; + kbts__entry_exit *EntryExits = KBTS__POINTER_AFTER(kbts__entry_exit, Adjust); + + kbts_glyph *Prev; + if(kbts__NextGlyph(Storage, Lookup, CurrentGlyph->Prev, RegularSkipFlags, SkipUnicodeFlags, &Prev, 1)) + { + // For two cursive glyphs to be aligned, they both need to be defined by the same cursive attachment table. + kbts__cover_glyph_result PrevCover = kbts__CoverGlyph(Coverage, Prev->Id); + + if(PrevCover.Valid) + { + // Get anchor points for both glyphs. + kbts__entry_exit *PrevEntryExit = &EntryExits[PrevCover.Index]; + kbts__entry_exit *EntryExit = &EntryExits[Cover.Index]; + + if(PrevEntryExit->ExitAnchorOffset && EntryExit->EntryAnchorOffset) + { + kbts__anchor *PrevExitAnchor = KBTS__POINTER_OFFSET(kbts__anchor, Adjust, PrevEntryExit->ExitAnchorOffset); + kbts__anchor *EntryAnchor = KBTS__POINTER_OFFSET(kbts__anchor, Adjust, EntryExit->EntryAnchorOffset); + kbts_s32 Anchor0X = PrevExitAnchor->X; + kbts_s32 Anchor0Y = PrevExitAnchor->Y; + kbts_s32 Anchor1X = EntryAnchor->X; + kbts_s32 Anchor1Y = EntryAnchor->Y; + kbts_s32 Advance0X = Prev->AdvanceX; + kbts_s32 Advance1X = CurrentGlyph->AdvanceX; + kbts_s32 Offset0X = Prev->OffsetX; + kbts_s32 Offset0Y = Prev->OffsetY; + kbts_s32 Offset1X = CurrentGlyph->OffsetX; + kbts_s32 Offset1Y = CurrentGlyph->OffsetY; + + // Cursive positioning is made up of two parts. + // The first part is glyph-to-glyph alignment, which depends on the text direction. + // Here, we are only concerned with making the relative placements of the glyphs correct, + // insofar as they follow the specified anchor positions. + // + // The OpenType spec makes no attempt to describe how the two glyphs should be aligned, mathematically + // speaking. + // + // This is all we get: + // + // "To position glyphs using the CursivePosFormat1 subtable, a text-processing client aligns the exit + // anchor point of a glyph with the entry anchor point of the following glyph." + // + // In practice, we reproduce harfbuzz's behavior here, which is: + // - Glyph1.Offset.X is unaffected + // - Glyph1.Advance.X = Glyph1.Offset.X + Glyph1.Anchor.X, aka. the _actual position of its anchor_ + // - Glyph2.Offset.X = -Glyph2.Anchor.X + // - Glyph2.Offset.Y = Glyph1.Anchor.Y - Glyph2.Anchor.Y + // - Glyph2.Advance.X -= Glyph2.Anchor.X + // + // (...where "X" here just means "the main direction". In top-to-bottom or bottom-to-top contexts, that + // would be the Y coordinate, but we do not support those yet.) + // + // So, instead of aligning everything with offsets, we use Advance to align _the rest of the string_ + // horizontally with the first glyph, and not just the next glyph. + // + // It might seem dumb to modify both Glyph2.Offset _and_ Glyph2.Advance, because, when the glyphs are next + // to one another, this is equivalent to modifying Glyph1.Advance. However, due to lookup flag nonsense, + // there may be some glyphs between Glyph1 and Glyph2, and, _apparently_, it is fine to adjust them by the + // position of Glyph1's anchor point, and it is not fine to adjust them by the position of Glyph2's anchor + // point. + // + // This Advance tweak seems like it would be wrong, because any marks attached to Glyph1 will then have + // invalid positions. The hope is that this does not matter in practice, because 'mark' is applied after + // 'curs', and font designers are expected to know that and to know never to apply mark attachments + // before cursive positioning, I guess. + if(!kbts__ShaperRtl(Config->Shaper)) + { + Advance0X = Offset0X + Anchor0X; + kbts_s32 Dx = -Anchor1X - Offset1X; + Advance1X += Dx; + Offset1X += Dx; + } + else + { + kbts_s32 Dx = -Anchor0X - Offset0X; + Advance0X += Dx; + Offset0X += Dx; + Advance1X = Offset1X + Anchor1X; + } + + Prev->AdvanceX = Advance0X; + Prev->OffsetX = Offset0X; + Prev->Flags |= (KBTS_GLYPH_FLAG_CURSIVE | KBTS_GLYPH_FLAG_USED_IN_GPOS | KBTS_GLYPH_FLAG_NO_BREAK); + kbts__SetCursiveFlags(Prev, KBTS__CURSIVE_FLAG_START); + CurrentGlyph->AdvanceX = Advance1X; + CurrentGlyph->OffsetX = Offset1X; + CurrentGlyph->Flags |= KBTS_GLYPH_FLAG_CURSIVE | KBTS_GLYPH_FLAG_USED_IN_GPOS; + kbts__SetCursiveFlags(CurrentGlyph, KBTS__CURSIVE_FLAG_END); + + for(kbts_glyph *CursiveGlyph = Prev->Next; + CursiveGlyph != CurrentGlyph; + CursiveGlyph = CursiveGlyph->Next) + { + CursiveGlyph->Flags |= KBTS_GLYPH_FLAG_NO_BREAK; + kbts__SetCursiveFlags(CursiveGlyph, 0); + } + + // The second part is aligning the newly-formed cursive cluster to the "baseline". It is trickier than you'd expect. + // + // When applying cursive attachments, Glyph1 (RIGHT_TO_LEFT=0) or Glyph2 (RIGHT_TO_LEFT=1) is treated as being + // "on the baseline" and its Y coordinate is used as the reference Y coordinate for the entire cursive glyph + // cluster that has been formed so far. + // This means that, anytime we apply a cursive attachment, we have to offset _all_ of the cursive glyphs to the + // left (RIGHT_TO_LEFT=0) or to the right (RIGHT_TO_LEFT=1) of it. + // This is obviously O(n^2), and @Speed: it might be worthwhile to record cursive offsets as we go, and only resolve + // them when we actually need them, i.e. when applying a non-cursive lookup or, at the latest, when we are done with + // positioning. + // + // The glyph being attached is set at a hard relative offset from the reference glyph. Its previous Y coordinate only + // matters insofar as we need to align every other cursive glyph in its direction. + + kbts_s32 CursiveDy = 0; + kbts_glyph *CursiveGlyph = CurrentGlyph; + int Backward = 0; + kbts_u32 AdjustNearbyGlyphs = (CurrentGlyph->Flags & KBTS_GLYPH_FLAG_CURSIVE); + + if(!(Lookup->Flags & KBTS__LOOKUP_FLAG_RIGHT_TO_LEFT)) + { + kbts_s32 NewOffset1Y = Offset0Y + Anchor0Y - Anchor1Y; + CursiveDy = NewOffset1Y - Offset1Y; + } + else + { + kbts_s32 NewOffset0Y = Offset1Y + Anchor1Y - Anchor0Y; + CursiveDy = NewOffset0Y - Offset0Y; + Backward = 1; + CursiveGlyph = Prev; + AdjustNearbyGlyphs = 1; + } + + CursiveGlyph->OffsetY += CursiveDy; + + if(AdjustNearbyGlyphs) + { + kbts__SetCursiveFlags(CursiveGlyph, 0); + CursiveGlyph = Backward ? CursiveGlyph->Prev : CursiveGlyph->Next; + + kbts__cursive_flags StopFlag = Backward ? KBTS__CURSIVE_FLAG_END : KBTS__CURSIVE_FLAG_START; + + while(kbts__GlyphIsValid(Storage, CursiveGlyph)) + { + kbts__cursive_flags CursiveFlags = kbts__GetCursiveFlags(CursiveGlyph); + + if(CursiveFlags & StopFlag) + { + break; + } + else if(CursiveGlyph->Flags & KBTS_GLYPH_FLAG_CURSIVE) + { + CursiveGlyph->OffsetY += CursiveDy; + } + else if(!(CursiveGlyph->Classes.Class & KBTS__GLYPH_CLASS_MARK)) // Ignore marks. + { + break; + } + + CursiveGlyph = Backward ? CursiveGlyph->Prev : CursiveGlyph->Next; + } + } + + Result = 1; + } + } + } + } + break; + + case 4: + case 6: + { + kbts__mark_to_base_attachment *Adjust = (kbts__mark_to_base_attachment *)Base; + + // We want to know which glyph to attach to, and how far that glyph is from us. + // To do that, we add up all advances between it and us. + // There is a slight wrinkle here: most shapers end up zeroing mark advances at the _end_ + // of the shaping process, which would retroactively make a naive advance accumulation wrong. + // We have to take that into account here, and only accumulate mark advances for shapers that + // don't do that zeroing at the end (either because they do it at the beginning of GPOS, or + // because they don't do it at all). + int CountMarkAdvances = !kbts__ShaperClearsMarkAdvancesInPostGposFixup(Config->Shaper); + kbts__coverage *BaseCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Adjust, Adjust->BaseCoverageOffset); + kbts_s32 AdvanceSinceBaseX = 0; + kbts_s32 AdvanceSinceBaseY = 0; + kbts_u32 BaseClasses = Lookup->Type == 6 ? (1 << KBTS__GLYPH_CLASS_MARK) : (1 | (1 << KBTS__GLYPH_CLASS_BASE) | (1 << KBTS__GLYPH_CLASS_LIGATURE) | (1 << KBTS__GLYPH_CLASS_COMPONENT)); + kbts_glyph *BaseGlyph = 0; + for(kbts_glyph *PrevGlyph = CurrentGlyph->Prev; kbts__GlyphIsValid(Storage, PrevGlyph); PrevGlyph = PrevGlyph->Prev) + { + if(CountMarkAdvances || (PrevGlyph->Classes.Class != KBTS__GLYPH_CLASS_MARK)) + { + AdvanceSinceBaseX += PrevGlyph->AdvanceX; + AdvanceSinceBaseY += PrevGlyph->AdvanceY; + } + + if(!kbts__SkipGlyph(PrevGlyph, Lookup, RegularSkipFlags, SkipUnicodeFlags)) + { + if((1 << PrevGlyph->Classes.Class) & BaseClasses) + { + // :MultipleSubstSadness + // There is some sadness when we have to look for bases here... + // In multiple substitutions, we allow skipping covered glyphs if they are: + // - Not the first in the multiple substitution + // - Not preceded by a mark + // + // More details on the sadness can be found here: + // https://github.com/harfbuzz/harfbuzz/issues/740 + // https://github.com/harfbuzz/harfbuzz/issues/1020 + // https://github.com/harfbuzz/harfbuzz/issues/4124 + if((Lookup->Type == 4) && + ((PrevGlyph->Flags & (KBTS_GLYPH_FLAG_FIRST_IN_MULTIPLE_SUBSTITUTION | KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION)) == KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION) && // Stop if we see the first of a multiple substitution. + (PrevGlyph->Prev->Classes.Class != KBTS__GLYPH_CLASS_MARK)) // Stop if we see any mark. + { + // Otherwise, we allow skipping uncovered glyphs. + kbts__cover_glyph_result BaseCover = kbts__CoverGlyph(BaseCoverage, PrevGlyph->Id); + if(BaseCover.Valid) + { + BaseGlyph = PrevGlyph; + break; + } + } + else + { + BaseGlyph = PrevGlyph; + break; + } + } + else if(Lookup->Type == 6) + { + // Unskipped non-marks block mark attachments. + break; + } + } + } + + if(BaseGlyph) + { + int Ok = (Lookup->Type == 4) || // This is a mark-to-base attachment + ((BaseGlyph->LigatureUid == CurrentGlyph->LigatureUid) && (BaseGlyph->LigatureComponentIndexPlusOne == CurrentGlyph->LigatureComponentIndexPlusOne)) || // This is a mark-to-mark attachment, and both marks belong to the same ligature component + ((BaseGlyph->Flags | CurrentGlyph->Flags) & KBTS_GLYPH_FLAG_LIGATURE); // This is a mark-to-mark attachment, and either mark was created by a ligature substitution + if(Ok) + { + // @Speed: This is duplicating work in the :MultipleSubstSadness case. + kbts__cover_glyph_result BaseCover = kbts__CoverGlyph(BaseCoverage, BaseGlyph->Id); + + if(BaseCover.Valid) + { + kbts__base_array *BaseArray = KBTS__POINTER_OFFSET(kbts__base_array, Adjust, Adjust->BaseArrayOffset); + kbts_u16 *BaseAnchorOffsets = KBTS__POINTER_AFTER(kbts_u16, BaseArray) + BaseCover.Index * Adjust->MarkClassCount; + kbts__mark_info MarkInfo = kbts__GetMarkInfo(Adjust, Adjust->MarkArrayOffset, Cover.Index); + + kbts_u16 BaseAnchorOffset = BaseAnchorOffsets[MarkInfo.Record->Class]; + if(BaseAnchorOffset) + { + kbts__anchor *BaseAnchor = KBTS__POINTER_OFFSET(kbts__anchor, BaseArray, BaseAnchorOffset); + + /* From the Microsoft docs: + When a mark is combined with a given base, the mark placement is adjusted so that the mark anchor is + aligned with the base anchor for the applicable mark class. Placement of the base glyph and advances of + both glyphs are not affected. + */ + + kbts_s32 NewOffsetX = BaseGlyph->OffsetX - AdvanceSinceBaseX + (BaseAnchor->X - MarkInfo.Anchor->X); + kbts_s32 NewOffsetY = BaseGlyph->OffsetY - AdvanceSinceBaseY + (BaseAnchor->Y - MarkInfo.Anchor->Y); + + kbts__AttachGlyph(Storage, BaseGlyph, CurrentGlyph, NewOffsetX, NewOffsetY); + + Result = 1; + } + } + } + } + } + break; + + case 5: + { + kbts__mark_to_ligature_attachment *Adjust = (kbts__mark_to_ligature_attachment *)Base; + + kbts_s32 AdvanceSinceBaseX = 0; + kbts_s32 AdvanceSinceBaseY = 0; + kbts_u32 BaseClasses = (1 | (1 << KBTS__GLYPH_CLASS_BASE) | (1 << KBTS__GLYPH_CLASS_LIGATURE) | (1 << KBTS__GLYPH_CLASS_COMPONENT)); + kbts_glyph *LigatureGlyph = 0; + for(kbts_glyph *PrevGlyph = CurrentGlyph->Prev; + kbts__GlyphIsValid(Storage, PrevGlyph); + PrevGlyph = PrevGlyph->Prev) + { + AdvanceSinceBaseX += PrevGlyph->AdvanceX; + AdvanceSinceBaseY += PrevGlyph->AdvanceY; + if(!kbts__SkipGlyph(PrevGlyph, Lookup, RegularSkipFlags, SkipUnicodeFlags) && ((1 << PrevGlyph->Classes.Class) & BaseClasses)) + { + LigatureGlyph = PrevGlyph; + break; + } + } + + if(LigatureGlyph) + { + kbts__cover_glyph_result LigatureCover = kbts__CoverGlyph(KBTS__POINTER_OFFSET(kbts__coverage, Adjust, Adjust->LigatureCoverageOffset), + LigatureGlyph->Id); + if(LigatureCover.Valid) + { + kbts__ligature_array *LigatureArray = KBTS__POINTER_OFFSET(kbts__ligature_array, Adjust, Adjust->LigatureArrayOffset); + kbts__ligature_attach *LigatureAttach = kbts__GetLigatureAttach(LigatureArray, LigatureCover.Index); + kbts__mark_info MarkInfo = kbts__GetMarkInfo(Adjust, Adjust->MarkArrayOffset, Cover.Index); + kbts_un LigatureComponentIndexPlusOne = CurrentGlyph->LigatureComponentIndexPlusOne; + + if(CurrentGlyph->LigatureUid != LigatureGlyph->Uid) + { + // If the mark is not yet attached to the ligature, attach it now. + // Apparently, in this case, the mark should be considered part of the _last_ component of the ligature. + LigatureComponentIndexPlusOne = LigatureAttach->Count; + } + + if(LigatureComponentIndexPlusOne <= LigatureAttach->Count) + { + kbts_un AnchorIndex = LigatureComponentIndexPlusOne; + if(AnchorIndex) + { + AnchorIndex -= 1; + } + else + { + AnchorIndex = LigatureAttach->Count - 1; + } + + kbts__anchor *LigatureAnchor = kbts__GetLigatureAttachAnchor(Adjust, LigatureAttach, MarkInfo.Record->Class, AnchorIndex); + + kbts_s32 NewOffsetX = LigatureGlyph->OffsetX - AdvanceSinceBaseX + (LigatureAnchor->X - MarkInfo.Anchor->X); + kbts_s32 NewOffsetY = LigatureGlyph->OffsetY - AdvanceSinceBaseY + (LigatureAnchor->Y - MarkInfo.Anchor->Y); + + kbts__AttachGlyph(Storage, LigatureGlyph, CurrentGlyph, NewOffsetX, NewOffsetY); + + CurrentGlyph->LigatureComponentIndexPlusOne = (kbts_u16)LigatureComponentIndexPlusOne; + CurrentGlyph->LigatureUid = LigatureGlyph->Uid; + // I'm not sure why, but Harfbuzz only clears this in mark-to-ligature substitutions, and not in mark-to-base or + // mark-to-mark. + CurrentGlyph->AdvanceX = 0; + CurrentGlyph->AdvanceY = 0; + + for(kbts_glyph *MiddleGlyph = LigatureGlyph->Next; + MiddleGlyph != CurrentGlyph; + MiddleGlyph = MiddleGlyph->Next) + { + MiddleGlyph->Flags |= KBTS_GLYPH_FLAG_NO_BREAK; + } + + Result = 1; + } + } + } + } + break; + + case 7: + case 8: + { + kbts__sequence_lookup_result SequenceLookup = kbts__DoSequenceLookup(Storage, Lookup, Base, Cover, CurrentGlyph, SequenceSkipFlags, SkipUnicodeFlags); + if(SequenceLookup.RecordCount) + { + KBTS__FOR(RecordIndex, 0, SequenceLookup.RecordCount) + { + kbts__sequence_lookup_record *Record = &SequenceLookup.Records[RecordIndex]; + kbts__lookup *PackedRecordLookup = kbts__GetLookup(LookupList, Record->LookupListIndex); + kbts__unpacked_lookup RecordLookup = kbts__UnpackLookup(kbts__BlobTableDataType(Config->Font->Blob, KBTS_BLOB_TABLE_ID_GDEF, kbts__gdef), PackedRecordLookup); + + kbts_glyph *NestedCurrentGlyph = CurrentGlyph; + kbts_un NestedCurrentGlyphIndex = 0; + { // Figure out where in the input sequence we need to apply the lookup. + kbts_un SequenceIndex = 0; + for(kbts_glyph *Glyph = CurrentGlyph; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Next) + { + if(!kbts__SkipGlyph(Glyph, Lookup, SequenceSkipFlags, SkipUnicodeFlags)) + { + if(SequenceIndex == Record->SequenceIndex) + { + NestedCurrentGlyph = Glyph; + + break; + } + + SequenceIndex += 1; + } + + NestedCurrentGlyphIndex += 1; + } + } + + KBTS__FOR(NestedSubtableIndex, 0, RecordLookup.SubtableCount) + { + kbts_u16 *NestedBase = KBTS__POINTER_OFFSET(kbts_u16, PackedRecordLookup, RecordLookup.SubtableOffsets[NestedSubtableIndex]); + + kbts__DoSingleAdjustment(Scratchpad, Config, Storage, LookupList, + Record->LookupListIndex, NestedSubtableIndex, &RecordLookup, NestedBase, + NestedCurrentGlyph, StartIndex + NestedCurrentGlyphIndex, RequestedSkipFlags); + } + } + + OnePastLastGlyphIndex = StartIndex + SequenceLookup.InputSequenceCountIncludingSkippedGlyphs; + OnePastLastGlyph = SequenceLookup.OnePastLastGlyphMatched; + } + } + break; + } + + kbts__SetLookupOnePastLastGlyph(Scratchpad, OnePastLastGlyphIndex + OnePastLastGlyphOffset, OnePastLastGlyph); + } + + Lookup->Type = OriginalLookupType; + } + + KBTS_INSTRUMENT_FUNCTION_END; + return Result; +} + +typedef kbts_u32 kbts__mcm_sequence_state; +enum kbts__mcm_sequence_state_enum +{ + KBTS__MCM_SEQUENCE_STATE_NONE, + KBTS__MCM_SEQUENCE_STATE_OUT, + KBTS__MCM_SEQUENCE_STATE_IN, +}; + +typedef kbts_u32 kbts__hangul_syllable_type; +enum kbts__hangul_syllable_type_enum +{ + KBTS__HANGUL_SYLLABLE_TYPE_NONE, + + KBTS__HANGUL_SYLLABLE_TYPE_L, + KBTS__HANGUL_SYLLABLE_TYPE_V, + KBTS__HANGUL_SYLLABLE_TYPE_T, + KBTS__HANGUL_SYLLABLE_TYPE_LV, + KBTS__HANGUL_SYLLABLE_TYPE_LVT, + + KBTS__HANGUL_SYLLABLE_TYPE_COUNT, +}; + +typedef struct kbts__hangul_syllable_info +{ + kbts__hangul_syllable_type Type; + kbts_u32 Composable; +} kbts__hangul_syllable_info; + +static kbts__hangul_syllable_info kbts__HangulSyllableInfo(kbts_u32 Codepoint) +{ + kbts__hangul_syllable_info Result = KBTS__ZERO; + + if((Codepoint >= 0x1100) && (Codepoint <= 0x115F)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_L; + Result.Composable = (Codepoint < 0x1113); + } + else if((Codepoint >= 0x1160) && (Codepoint <= 0x11A7)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_V; + Result.Composable = ((Codepoint >= 0x1161) & (Codepoint <= 0x1175)); + } + else if((Codepoint >= 0x11A8) && (Codepoint <= 0x11FF)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_T; + Result.Composable = (Codepoint < 0x11C3); + } + else if((Codepoint >= 0xA960) && (Codepoint <= 0xA97C)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_L; + } + else if((Codepoint == 0xAC00) && (Codepoint <= 0xD7A3)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_LVT; + + if(!((Codepoint - 0xAC00) % 28)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_LV; + } + } + else if((Codepoint >= 0xD7B0) && (Codepoint <= 0xD7C6)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_V; + } + else if((Codepoint >= 0xD7CB) && (Codepoint <= 0xD7FB)) + { + Result.Type = KBTS__HANGUL_SYLLABLE_TYPE_T; + } + + return Result; +} + +KBTS_INLINE kbts_u32 kbts__SyllabicClassIsConsonant(kbts_indic_syllabic_class Class) +{ + kbts_u32 Result = + KBTS__IN_SET(Class, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_CONSONANT)(KBTS_INDIC_SYLLABIC_CLASS_RA)(KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_WITH_STACKER)(KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL))); + return Result; +} + +enum +{ + KBTS__FEATURE_MATCH_FLAG_KA_JA = (1 << 0), + KBTS__FEATURE_MATCH_FLAG_SSA_NYA = (1 << 1), + KBTS__FEATURE_MATCH_FLAG_RA_HA_VA = (1 << 2), + KBTS__FEATURE_MATCH_FLAG_YA = (1 << 3), + KBTS__FEATURE_MATCH_FLAG_CONSONANT = (1 << 4), + KBTS__FEATURE_MATCH_FLAG_NUKTA = (1 << 5), + KBTS__FEATURE_MATCH_FLAG_HALANT = (1 << 6), + KBTS__FEATURE_MATCH_FLAG_ZWJ = (1 << 7), + KBTS__FEATURE_MATCH_FLAG_ZWNJ = (1 << 8), + KBTS__FEATURE_MATCH_FLAG_INITIAL = (1 << 10), + KBTS__FEATURE_MATCH_FLAG_POST_BASE = (1 << 11), + + KBTS__FEATURE_MATCH_FLAG_RPHF = KBTS__FEATURE_FLAG0(rphf), +}; +# define KBTS__FEATURE_MATCH_MASK(W0, W1, W2, W3) (((kbts_u64)(W0) << 48) | ((kbts_u64)(W1) << 32) | ((kbts_u64)(W0) << 16) | (kbts_u64)(W0)) +# define KBTS__FEATURE_MATCH_MASK_AKHN KBTS__FEATURE_MATCH_MASK(0, KBTS__FEATURE_MATCH_FLAG_KA_JA, KBTS__FEATURE_MATCH_FLAG_HALANT, KBTS__FEATURE_MATCH_FLAG_SSA_NYA) +# define KBTS__FEATURE_MATCH_MASK_BLWF_PRE KBTS__FEATURE_MATCH_MASK(0, 0, KBTS__FEATURE_MATCH_FLAG_RA_HA_VA | KBTS__FEATURE_MATCH_FLAG_INITIAL, KBTS__FEATURE_MATCH_FLAG_HALANT) +# define KBTS__FEATURE_MATCH_MASK_BLWF_PRE_OK KBTS__FEATURE_MATCH_MASK(0, 0, KBTS__FEATURE_MATCH_FLAG_RA_HA_VA, KBTS__FEATURE_MATCH_FLAG_HALANT) +# define KBTS__FEATURE_MATCH_MASK_BLWF_POST KBTS__FEATURE_MATCH_MASK(0, 0, KBTS__FEATURE_MATCH_FLAG_HALANT, KBTS__FEATURE_MATCH_FLAG_RA_HA_VA) +# define KBTS__FEATURE_MATCH_MASK_CJCT KBTS__FEATURE_MATCH_MASK(0, KBTS__FEATURE_MATCH_FLAG_CONSONANT, KBTS__FEATURE_MATCH_FLAG_HALANT, KBTS__FEATURE_MATCH_FLAG_CONSONANT) +# define KBTS__FEATURE_MATCH_MASK_HALF KBTS__FEATURE_MATCH_MASK(KBTS__FEATURE_MATCH_FLAG_CONSONANT | KBTS__FEATURE_MATCH_FLAG_RPHF | KBTS__FEATURE_MATCH_FLAG_POST_BASE, KBTS__FEATURE_MATCH_FLAG_HALANT, KBTS__FEATURE_MATCH_FLAG_ZWNJ, KBTS__FEATURE_MATCH_FLAG_CONSONANT) +# define KBTS__FEATURE_MATCH_MASK_HALF_OK KBTS__FEATURE_MATCH_MASK(KBTS__FEATURE_MATCH_FLAG_CONSONANT, KBTS__FEATURE_MATCH_FLAG_HALANT, 0, 0) +# define KBTS__FEATURE_MATCH_MASK_NUKT KBTS__FEATURE_MATCH_MASK(0, 0, KBTS__FEATURE_MATCH_FLAG_CONSONANT, KBTS__FEATURE_MATCH_FLAG_HALANT) +# define KBTS__FEATURE_MATCH_MASK_PSTF KBTS__FEATURE_MATCH_MASK(0, 0, KBTS__FEATURE_MATCH_FLAG_HALANT | KBTS__FEATURE_MATCH_FLAG_INITIAL, KBTS__FEATURE_MATCH_FLAG_YA) +# define KBTS__FEATURE_MATCH_MASK_VATU KBTS__FEATURE_MATCH_MASK(0, KBTS__FEATURE_MATCH_FLAG_CONSONANT, KBTS__FEATURE_MATCH_FLAG_HALANT, KBTS__FEATURE_MATCH_FLAG_RA_HA_VA) + +typedef kbts_u32 kbts__substitution_result_flags; +enum kbts__substitution_result_flags_enum +{ + KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION = (1 << 0), + KBTS__SUBSTITUTION_RESULT_FLAG_TRIED_TO_INSERT_WHILE_CHECK_ONLY = (1 << 1), +}; + +static void kbts__BeginLookupApplication(kbts__shape_scratchpad *Scratchpad, kbts_glyph *Glyph) +{ + Scratchpad->LookupOnePastLastGlyph = Glyph->Next; + Scratchpad->LookupOnePastLastGlyphIndex = 0; +} + +static kbts_glyph *kbts__EndLookupApplication(kbts__shape_scratchpad *Scratchpad) +{ + kbts_glyph *Result = Scratchpad->LookupOnePastLastGlyph; + return Result; +} + +static kbts__substitution_result_flags kbts__DoSubstitution(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_lookup_list *LookupList, kbts__gsub_frame *Frames, kbts_un *FrameCount_, + int CheckOnly, kbts__skip_flags RequestedSkipFlags, kbts_u32 GeneratedGlyphFlags) +{ + kbts__substitution_result_flags Result = 0; + kbts_font *Font = Config->Font; + kbts_unicode_flags SkipUnicodeFlags = 0; // @Incomplete + kbts__skip_flags RegularSkipFlags = KBTS__SKIP_FLAGS_GSUB_REGULAR(RequestedSkipFlags); + kbts__skip_flags SequenceSkipFlags = KBTS__SKIP_FLAGS_GSUB_SEQUENCE(RequestedSkipFlags); + GeneratedGlyphFlags |= KBTS_GLYPH_FLAG_GENERATED_BY_GSUB; + + kbts_un FrameCount = *FrameCount_; + kbts__gsub_frame *Frame = &Frames[FrameCount - 1]; + + kbts__lookup *PackedLookup = kbts__GetLookup(LookupList, Frame->LookupIndex); + kbts__unpacked_lookup Lookup = kbts__UnpackLookup(kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GDEF, kbts__gdef), PackedLookup); + kbts_u16 BaseLookupType = Lookup.Type; + + while(Frame->SubtableIndex < Lookup.SubtableCount) + { + kbts_u16 *Subtable = KBTS__POINTER_OFFSET(kbts_u16, PackedLookup, Lookup.SubtableOffsets[Frame->SubtableIndex]); + // In a type-7 lookup, each subtable can specify a different lookup type. + // We still want to pass kbts__unpacked_lookup around as a useful bag of arguments, though. + // So, we restore the original lookup's type here before resolving each subtable. + Lookup.Type = BaseLookupType; + + while(Lookup.Type == 7) + { + kbts__extension *Extension = (kbts__extension *)Subtable; + Lookup.Type = Extension->LookupType; + Subtable = KBTS__POINTER_OFFSET(kbts_u16, Extension, Extension->Offset); + } + + kbts_glyph *CurrentGlyph = Frame->InputGlyph; + + kbts__skip_flags SkipFlags = (Lookup.Type >= 5) ? SequenceSkipFlags : RegularSkipFlags; + if(kbts__GlyphsIncludedInLookupSubtable(Storage, Font, 0, &Lookup, Frame->LookupIndex, Frame->SubtableIndex, CurrentGlyph, SkipFlags, SkipUnicodeFlags)) + { + kbts__cover_glyph_result Cover = KBTS__ZERO; + Cover.Valid = kbts__GlyphPassesLookupFilter(CurrentGlyph, &Lookup); + if(Cover.Valid && kbts__GsubLookupBeginsWithCoverage(Lookup.Type, Subtable[0])) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subtable, Subtable[1]); + Cover = kbts__CoverGlyph(Coverage, CurrentGlyph->Id); + } + + if(Cover.Valid) + { + kbts_un OnePastLastGlyphOffset = 1; + kbts_glyph *OnePastLastGlyph = CurrentGlyph->Next; + + if((Lookup.Type == 5) || (Lookup.Type == 6)) + { + kbts__sequence_lookup_result SequenceLookup = kbts__DoSequenceLookup(Storage, &Lookup, Subtable, Cover, CurrentGlyph, SequenceSkipFlags, SkipUnicodeFlags); + + if(SequenceLookup.Matched) + { + Frame->Records = SequenceLookup.Records; + Frame->RecordCount = (kbts_u16)SequenceLookup.RecordCount; + Frame->RecordIndex = 0; + + Frame->SubtableIndex = 0xFFFE; + + OnePastLastGlyphOffset = SequenceLookup.InputSequenceCountIncludingSkippedGlyphs; + OnePastLastGlyph = SequenceLookup.OnePastLastGlyphMatched; + } + } + else + { + // Do single substitution. + + switch(Lookup.Type) + { + case 1: + { + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION; + + if(!CheckOnly) + { + kbts__single_substitution *Subst = (kbts__single_substitution *)Subtable; + + kbts_u16 NewId = 0; + if(Subst->Format == 1) + { + // From the Microsoft docs: + // "Addition of deltaGlyphID is modulo 65536." + NewId = (CurrentGlyph->Id + (kbts_u32)Subst->DeltaOrCount.DeltaGlyphId) & 0xFFFF; + } + else if(Subst->Format == 2) + { + kbts_u16 *SubstituteGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Subst); + NewId = SubstituteGlyphIds[Cover.Index]; + } + + kbts__GsubMutate(Font, CurrentGlyph, NewId, GeneratedGlyphFlags); + } + } break; + + case 2: + { + kbts__multiple_substitution *Subst = (kbts__multiple_substitution *)Subtable; + kbts__sequence *Sequence = kbts__GetSequence(Subst, Cover.Index); + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION; + + if(!CheckOnly) + { + kbts_u16 *SubstGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Sequence); + + kbts_un GrowCount = Sequence->GlyphCount - 1; + + if(Sequence->GlyphCount) + { + kbts_glyph OriginalGlyph = *CurrentGlyph; + kbts_glyph *LastInsert = CurrentGlyph; + KBTS__FOR(SubstGlyphIndex, 0, Sequence->GlyphCount) + { + kbts_u32 NewGlyphFlags = GeneratedGlyphFlags | KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION; + + kbts_glyph *NewGlyph = CurrentGlyph; + if(SubstGlyphIndex) + { + NewGlyph = kbts__InsertGlyphAfter(Storage, LastInsert, &OriginalGlyph); + + if(!NewGlyph) + { + Scratchpad->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + return Result; + } + + NewGlyph->Uid = (kbts_u16)++Scratchpad->NextGlyphUid; + } + else + { + NewGlyphFlags |= KBTS_GLYPH_FLAG_FIRST_IN_MULTIPLE_SUBSTITUTION; + } + + kbts__GsubMutate(Font, NewGlyph, SubstGlyphIds[SubstGlyphIndex], GeneratedGlyphFlags | NewGlyphFlags); + LastInsert = NewGlyph; + } + + OnePastLastGlyph = LastInsert->Next; + } + else + { + kbts__FreeGlyph(Scratchpad, Storage, CurrentGlyph); + } + + OnePastLastGlyphOffset = 1 + GrowCount; + + // Shift other frames' input cursors. + KBTS__FOR(FrameIndex, 0, FrameCount - 1) + { + kbts__gsub_frame *OtherFrame = &Frames[FrameIndex]; + + if(OtherFrame->StartIndex > Frame->StartIndex) + { + OtherFrame->StartIndex = (kbts_u16)(OtherFrame->StartIndex + GrowCount); + } + } + } + else if(Sequence->GlyphCount > 1) + { + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_TRIED_TO_INSERT_WHILE_CHECK_ONLY; + } + } break; + + case 3: + { + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION; + + if(!CheckOnly) + { + kbts__alternate_substitution *Subst = (kbts__alternate_substitution *)Subtable; + kbts__alternate_set *Set = kbts__GetAlternateSet(Subst, Cover.Index); + kbts_u16 *AltGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Set); + + kbts_un AlternateIndex = 0; + + { + kbts__feature_set *ShaperFeatures = &Config->Features; + kbts_glyph_config *GlyphConfig = CurrentGlyph->Config; + if(GlyphConfig) + { + int HasOverride = 0; + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(GlyphConfig->EnabledFeatures.Flags)) + { + kbts_u64 Flags = GlyphConfig->EnabledFeatures.Flags[WordIndex] & ShaperFeatures->Flags[WordIndex]; + if(Flags) + { + HasOverride = 1; + break; + } + } + + if(HasOverride) + { + for(kbts__feature_override_header *OverrideHeader = GlyphConfig->FeatureOverrideSentinel.Next; + OverrideHeader != &GlyphConfig->FeatureOverrideSentinel; + OverrideHeader = OverrideHeader->Next) + { + kbts__feature_override *Override = (kbts__feature_override *)OverrideHeader; + int Value = Override->Value; + kbts__feature_id Id = kbts__FeatureTagToId(Override->Tag); + + if(Value && + kbts__ContainsFeature(&Scratchpad->LookupFeatures, Id)) + { + int Match = 1; + if(!Id) + { + // Slow path for unregistered features. + Match = 0; + KBTS__FOR(UnregisteredFeatureIndex, 0, Scratchpad->UnregisteredFeatureCount) + { + if(Override->Tag == Scratchpad->UnregisteredFeatureTags[UnregisteredFeatureIndex]) + { + Match = 1; + break; + } + } + } + + if(Match) + { + AlternateIndex = (kbts_un)(Value - 1); + + break; + } + } + } + } + } + } + + if(AlternateIndex >= Set->GlyphCount) + { + AlternateIndex = 0; + } + + kbts_u16 NewId = AltGlyphIds[AlternateIndex]; + kbts__GsubMutate(Font, CurrentGlyph, NewId, GeneratedGlyphFlags); + } + } break; + + case 4: + { + kbts__ligature_substitution *Subst = (kbts__ligature_substitution *)Subtable; + kbts__ligature_set *Set = kbts__GetLigatureSet(Subst, Cover.Index); + + KBTS__FOR(LigatureIndex, 0, Set->Count) + { + kbts__ligature *Ligature = kbts__GetLigature(Set, LigatureIndex); + kbts_u16 *ComponentIds = KBTS__POINTER_AFTER(kbts_u16, Ligature); + + kbts_un MatchingGlyphCount = 1; + + { + kbts_glyph *LigatureGlyphCursor = CurrentGlyph->Next; + while(kbts__GlyphIsValid(Storage, LigatureGlyphCursor) && (MatchingGlyphCount < Ligature->ComponentCount)) + { + // A ligature may contain an explicit ZWJ, which SkipGlyph() would probably skip. + // The expected behavior in that case is to assume the font designer knows what they are doing + // and match the ZWJ. + if(LigatureGlyphCursor->Id == ComponentIds[MatchingGlyphCount - 1]) + { + MatchingGlyphCount += 1; + } + else if(!kbts__SkipGlyph(LigatureGlyphCursor, &Lookup, RegularSkipFlags, SkipUnicodeFlags)) + { + break; + } + + LigatureGlyphCursor = LigatureGlyphCursor->Next; + } + } + + if(MatchingGlyphCount == Ligature->ComponentCount) + { + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION; + + if(!CheckOnly) + { + kbts_u32 LigatureUid = ++Scratchpad->NextGlyphUid; + kbts_un ComponentCount = Ligature->ComponentCount; + + { // For glyphs that aren't part of the ligature, store which component it is attached to. + // For glyphs that _are_, eat them. + kbts_un LigatureGlyphCount = 1; + kbts_un GrowCount = 0; + + // Consider this example: + // ABCD -> DB (A and C form a ligature) + // DB -> DEB (E is inserted in whatever way) + // DEB -> FB (D and E form a ligature) + // In that case, 'B' was supposed to be attached to D, but D does not exist anymore. + // To handle this case, we go through the ligature, counting the total flattened components + // and the ligature info of the last glyph that is part of the ligature. + // Then, all trailing marks get are re-attached to the new ligature, and their component indices + // are adjusted to take into account the new (flattened) component count. + // (I say 'flattened' here because a previous ligature glyph counts as multiple components.) + kbts_un PreviousLigatureUid = CurrentGlyph->LigatureUid; + kbts_un PreviousComponentCount = CurrentGlyph->LigatureComponentCount; + if(!PreviousComponentCount) + { + PreviousComponentCount = 1; + } + kbts_un RunningComponentCount = PreviousComponentCount; + + kbts_glyph *LigatureGlyphCursor = CurrentGlyph->Next; + while(kbts__GlyphIsValid(Storage, LigatureGlyphCursor) && (LigatureGlyphCount < ComponentCount)) + { + kbts_glyph *Next = LigatureGlyphCursor->Next; + + if(LigatureGlyphCursor->Id == ComponentIds[LigatureGlyphCount - 1]) + { + PreviousLigatureUid = LigatureGlyphCursor->LigatureUid; + PreviousComponentCount = LigatureGlyphCursor->LigatureComponentCount; + if(!PreviousComponentCount) + { + PreviousComponentCount = 1; + } + RunningComponentCount += PreviousComponentCount; + + LigatureGlyphCount += 1; + + // Eat! + kbts__FreeGlyph(Scratchpad, Storage, LigatureGlyphCursor); + GrowCount -= 1; + } + else if(kbts__SkipGlyph(LigatureGlyphCursor, &Lookup, RegularSkipFlags, SkipUnicodeFlags)) + { + LigatureGlyphCursor->LigatureComponentIndexPlusOne = (kbts_u16)LigatureGlyphCount; + LigatureGlyphCursor->LigatureUid = (kbts_u16)LigatureUid; + LigatureGlyphCursor->LigatureComponentCount = (kbts_u16)ComponentCount; + } + else + { + break; + } + + LigatureGlyphCursor = Next; + } + + OnePastLastGlyph = CurrentGlyph->Next; + + // Re-attach trailing marks that were part of a component ligature to the new ligature. + if(PreviousLigatureUid) + { + kbts_un DeltaComponentCount = RunningComponentCount - PreviousComponentCount; + + while(kbts__GlyphIsValid(Storage, LigatureGlyphCursor)) + { + kbts_un PreviousComponentIndexPlusOne = LigatureGlyphCursor->LigatureComponentIndexPlusOne; + + if((LigatureGlyphCursor->Classes.Class == KBTS__GLYPH_CLASS_MARK) && + (LigatureGlyphCursor->LigatureUid == PreviousLigatureUid) && + PreviousComponentIndexPlusOne) + { + if(PreviousComponentIndexPlusOne > PreviousComponentCount) + { + PreviousComponentIndexPlusOne = PreviousComponentCount; + } + + kbts_un NewComponentIndexPlusOne = PreviousComponentIndexPlusOne + DeltaComponentCount; + + LigatureGlyphCursor->LigatureUid = (kbts_u16)LigatureUid; + LigatureGlyphCursor->LigatureComponentIndexPlusOne = (kbts_u16)NewComponentIndexPlusOne; + } + else + { + break; + } + + LigatureGlyphCursor = LigatureGlyphCursor->Next; + } + } + + // Update frame input cursors. + KBTS__FOR(FrameIndex, 0, FrameCount - 1) + { + kbts__gsub_frame *OtherFrame = &Frames[FrameIndex]; + + if(OtherFrame->StartIndex >= Frame->StartIndex) + { + OtherFrame->StartIndex += (kbts_u16)GrowCount; + } + } + } + + // Currently, we only take the main glyph's config into account while making the ligature's config. + // Maybe we should merge all of the components' configs into one instead? + kbts__GsubMutate(Font, CurrentGlyph, Ligature->Glyph, GeneratedGlyphFlags | KBTS_GLYPH_FLAG_LIGATURE); + CurrentGlyph->Uid = (kbts_u16)LigatureUid; + CurrentGlyph->LigatureUid = (kbts_u16)LigatureUid; + CurrentGlyph->LigatureComponentCount = (kbts_u16)ComponentCount; + + // Harfbuzz does this, because Uniscribe does this, and so we do the same. Sigh. + CurrentGlyph->Flags &= ~KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION; + } + + break; + } + } + } break; + + case 8: + { + kbts__reverse_chain_substitution *Subst = (kbts__reverse_chain_substitution *)Subtable; + kbts__unpacked_reverse_chain_substitution Unpacked = kbts__UnpackReverseChainSubstitution(Subst, 0); + + // :BoundsChecking + if(Cover.Index < Unpacked.GlyphCount) + { + // Should we use regular or sequence skip flags here? + kbts__sequence_match BacktrackMatch = kbts__MatchCoverageSequence(Storage, &Lookup, RegularSkipFlags, SkipUnicodeFlags, Subst, Unpacked.BacktrackCoverageOffsets, Unpacked.BacktrackCount, + CurrentGlyph->Prev, 1); + kbts__sequence_match LookaheadMatch = kbts__MatchCoverageSequence(Storage, &Lookup, RegularSkipFlags, SkipUnicodeFlags, Subst, Unpacked.LookaheadCoverageOffsets, Unpacked.LookaheadCount, + CurrentGlyph->Next, 0); + if((BacktrackMatch.MatchCount == Unpacked.BacktrackCount) && (LookaheadMatch.MatchCount == Unpacked.LookaheadCount)) + { + Result |= KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION; + kbts__GsubMutate(Font, CurrentGlyph, Unpacked.SubstituteGlyphIds[Cover.Index], GeneratedGlyphFlags); + } + } + } break; + } + + if(Result & KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION) + { + Frame->SubtableIndex = 0xFFFE; + + // From the Microsoft docs: + // To move to the “next” glyph, the client skips all the glyphs that participated in the lookup operation: + // glyphs that were substituted/positioned as well as any other glyphs in the matched input sequence. + } + } + + kbts__SetLookupOnePastLastGlyph(Scratchpad, Frame->StartIndex + OnePastLastGlyphOffset, OnePastLastGlyph); + } + } + + Frame->SubtableIndex += 1; + } + + if(Frame->RecordIndex < Frame->RecordCount) + { + kbts__sequence_lookup_record *SequenceRecord = &Frame->Records[Frame->RecordIndex++]; + + if(FrameCount < KBTS_LOOKUP_STACK_SIZE) + { + kbts__gsub_frame NewFrame = KBTS__ZERO; + NewFrame.LookupIndex = SequenceRecord->LookupListIndex; + NewFrame.StartIndex = Frame->StartIndex; + NewFrame.InputGlyph = Frame->InputGlyph; + + if(SequenceRecord->SequenceIndex) + { + // @Speed: Re-scan the sequence to find where we are in the _filtered_ sequence. + kbts_un SequenceInputIndex = 0; + for(kbts_glyph *FilterGlyph = Frame->InputGlyph->Next; + kbts__GlyphIsValid(Storage, FilterGlyph); + FilterGlyph = FilterGlyph->Next) + { + // @Incomplete: SequenceSkipFlags? 0? + // What do we use here? + if(!kbts__SkipGlyph(FilterGlyph, &Lookup, 0, SkipUnicodeFlags)) + { + SequenceInputIndex += 1; + + if(SequenceInputIndex == SequenceRecord->SequenceIndex) + { + NewFrame.InputGlyph = FilterGlyph; + + break; + } + } + + NewFrame.StartIndex += 1; + } + } + + Frames[FrameCount++] = NewFrame; + } + } + + // Only actually pop the frame if we haven't pushed anything else in the meantime. + if(Frame == &Frames[FrameCount - 1]) + { + FrameCount -= 1; + } + + *FrameCount_ = FrameCount; + + return Result; +} + +static kbts__glyph_list kbts__PushGlyphList(kbts_glyph_storage *Storage, kbts_glyph *First, kbts_glyph *Last) +{ + kbts__glyph_list Result = KBTS__ZERO; + + Result.SentinelPrev = Storage->GlyphSentinel.Prev; + Result.SentinelNext = Storage->GlyphSentinel.Next; + Result.OneBeforeFirst = First->Prev; + Result.OnePastLast = Last->Next; + + First->Prev = Last->Next = (kbts_glyph *)&Storage->GlyphSentinel; + First->Prev->Next = First; + Last->Next->Prev = Last; + + return Result; +} + +static void kbts__PopGlyphList(kbts_glyph_storage *Storage, kbts__glyph_list *List) +{ + List->OneBeforeFirst->Next = Storage->GlyphSentinel.Next; + List->OnePastLast->Prev = Storage->GlyphSentinel.Prev; + + // Storage->GlyphSentinel.Prev->Next = Storage->GlyphSentinel.Next->Prev = &Storage->GlyphSentinel; + + if((kbts_glyph *)&Storage->GlyphSentinel != List->OneBeforeFirst) + { + Storage->GlyphSentinel.Next = List->SentinelNext; + } + if((kbts_glyph *)&Storage->GlyphSentinel != List->OnePastLast) + { + Storage->GlyphSentinel.Prev = List->SentinelPrev; + } + + Storage->GlyphSentinel.Prev->Next = Storage->GlyphSentinel.Next->Prev = (kbts_glyph *)&Storage->GlyphSentinel; + + *List = KBTS__ZERO_TYPE(kbts__glyph_list); +} + +static int kbts__WouldSubstitute(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_lookup_list *LookupList, + kbts__gsub_frame *Frames, kbts__feature *Feature, kbts__skip_flags SkipFlags, + kbts_glyph *Glyphs, kbts_un GlyphCount) +{ + int Result = 0; + + KBTS_ASSERT(GlyphCount <= 4); + kbts_glyph TempSentinel; + kbts_glyph Scratch[4]; + + KBTS__FOR(GlyphIndex, 0, GlyphCount) + { + kbts_glyph *ScratchGlyph = &Scratch[GlyphIndex]; + + // Glyphs is assumed to be in-order on the stack or something. + // This is one of the rare places where we manipulate arrays. + *ScratchGlyph = Glyphs[GlyphIndex]; + ScratchGlyph->Prev = ScratchGlyph - 1; + ScratchGlyph->Next = ScratchGlyph + 1; + } + Scratch[0].Prev = &TempSentinel; + Scratch[GlyphCount - 1].Next = &TempSentinel; + TempSentinel.Next = &Scratch[0]; + TempSentinel.Prev = &Scratch[GlyphCount - 1]; + + kbts__glyph_list OldList = kbts__PushGlyphList(Storage, &Scratch[0], &Scratch[GlyphCount - 1]); + + kbts__iterate_lookups IterateLookups = kbts__IterateLookups(LookupList, Feature); + while(kbts__NextLookup(&IterateLookups)) + { + kbts_glyph *CurrentGlyph = &Scratch[0]; + while(kbts__GlyphIsValid(Storage, CurrentGlyph)) + { + kbts__gsub_frame *Frame = &Frames[0]; + *Frame = KBTS__ZERO_TYPE(kbts__gsub_frame); + Frame->LookupIndex = IterateLookups.LookupIndex; + Frame->SubtableIndex = 0; + Frame->StartIndex = 0; + Frame->InputGlyph = CurrentGlyph; + kbts_un FrameCount = 1; + + kbts__BeginLookupApplication(Scratchpad, CurrentGlyph); + + while(FrameCount) + { + kbts__substitution_result_flags SubstitutionResult = kbts__DoSubstitution(Scratchpad, Config, Storage, LookupList, Frames, &FrameCount, 1, SkipFlags, 0); + + if(SubstitutionResult & KBTS__SUBSTITUTION_RESULT_FLAG_MATCHED_SUBSTITUTION) + { + Result = 1; + goto Done; + } + } + + CurrentGlyph = kbts__EndLookupApplication(Scratchpad); + } + } + +Done:; + kbts__PopGlyphList(Storage, &OldList); + + return Result; +} + +static int kbts__NextLookupIndex(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_un *LookupIndex_, kbts_u32 *SkipFlags_, kbts_u32 *GlyphFilter_, kbts__feature_set *FeatureSet_) +{ + int Result = 0; + + kbts_un FeatureStageIndex = Scratchpad->FeatureStagesRead - 1; + kbts_u32 SkipFlags = 0; + kbts_u32 GlyphFilter = 0; + Scratchpad->UnregisteredFeatureCount = 0; + kbts_un ResultLookupIndex = 0; + kbts__baked_feature_stage *FeatureStage = &Config->FeatureStages[FeatureStageIndex]; + + *FeatureSet_ = KBTS__ZERO_TYPE(kbts__feature_set); + + while(Scratchpad->FeatureIndexIndex < FeatureStage->FeatureIndexCount) + { + KBTS_ASSERT(Scratchpad->FeatureIndexIndex < FeatureStage->FeatureIndexCount); + + kbts_u16 FeatureIndex = FeatureStage->FeatureIndices[Scratchpad->FeatureIndexIndex]; + KBTS_ASSERT(FeatureIndex < FeatureStage->FeatureIndexCount); + + kbts__baked_feature *Feature = &FeatureStage->Features[FeatureIndex]; + kbts_un Offset = Scratchpad->BakedLookupSubtablesRead[FeatureIndex]; + + KBTS_ASSERT(Offset < Feature->Count); + kbts_un LookupIndex = Feature->Indices[Offset]; + + if(!Result) + { + ResultLookupIndex = LookupIndex; + Result = 1; + } + + if(LookupIndex == ResultLookupIndex) + { + kbts__AddFeature(FeatureSet_, Feature->FeatureId); + SkipFlags |= Feature->SkipFlags; + GlyphFilter |= Feature->GlyphFilter; + + if(!Feature->FeatureId && (Scratchpad->UnregisteredFeatureCount < KBTS_MAX_SIMULTANEOUS_FEATURES)) + { + Scratchpad->UnregisteredFeatureTags[Scratchpad->UnregisteredFeatureCount++] = Feature->FeatureTag; + } + + Scratchpad->FeatureIndexIndex += 1; + Scratchpad->BakedLookupSubtablesRead[FeatureIndex] += 1; + } + else + { + break; + } + } + + *LookupIndex_ = ResultLookupIndex; + *SkipFlags_ = SkipFlags; + *GlyphFilter_ = GlyphFilter; + + return Result; +} + +static int kbts__ConfigAllowsFeatures(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_config *GlyphConfig, kbts__feature_set *Features) +{ + kbts_glyph_config DummyGlyphConfig = KBTS__ZERO; + kbts_u64 UserEnabled = 0; // Whether the user enabled _any_ feature corresponding to this lookup. + kbts_u64 UserDisabled = 1; // Whether the user disabled _all_ features corresponding to this lookup. + kbts_u64 DefaultEnabled = 0; // Whether any feature is non-user. + + if(!GlyphConfig) + { + GlyphConfig = &DummyGlyphConfig; + } + + kbts_u64 Mask = 1; // Ignore unregistered features in the broad pass. + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(GlyphConfig->EnabledFeatures.Flags)) + { + kbts_u64 LookupFeatureFlags = Features->Flags[WordIndex] & ~Mask; + Mask = 0; + + UserEnabled |= GlyphConfig->EnabledFeatures.Flags[WordIndex] & LookupFeatureFlags; + UserDisabled &= (GlyphConfig->DisabledFeatures.Flags[WordIndex] & LookupFeatureFlags) == LookupFeatureFlags; + DefaultEnabled |= Features->Flags[WordIndex] & Config->Features.Flags[WordIndex]; + } + + if(Features->Flags[0] & (GlyphConfig->EnabledFeatures.Flags[0] | GlyphConfig->DisabledFeatures.Flags[0]) & KBTS__FEATURE_FLAG0(UNREGISTERED)) + { + // Slow path for unregistered features. + for(kbts__feature_override_header *Header = GlyphConfig->FeatureOverrideSentinel.Next; + Header != &GlyphConfig->FeatureOverrideSentinel; + Header = Header->Next) + { + kbts__feature_override *Override = (kbts__feature_override *)Header; + kbts__feature_id Id = kbts__FeatureTagToId(Override->Tag); + + if(Id == KBTS__FEATURE_ID_UNREGISTERED) + { + kbts_feature_tag OverrideTag = Override->Tag; + + KBTS__FOR(UnregisteredFeatureIndex, 0, Scratchpad->UnregisteredFeatureCount) + { + if(OverrideTag == Scratchpad->UnregisteredFeatureTags[UnregisteredFeatureIndex]) + { + UserEnabled |= (kbts_u32)Override->Value; + UserDisabled &= !Override->Value; + break; + } + } + } + } + } + + int Result = (!UserDisabled && (DefaultEnabled || UserEnabled)); + + return Result; +} + +static void kbts__DllistReverseSublist(kbts_glyph *First, kbts_glyph *OnePastLast) +{ + kbts_glyph *OneBeforeFirst = First->Prev; + kbts_glyph *Last = First; + + for(kbts_glyph *Glyph = First; + ; + ) + { + kbts_glyph *Next = Glyph->Next; + + Glyph->Next = Glyph->Prev; + Glyph->Prev = Next; + + Last = Glyph; + Glyph = Next; + if(Glyph == OnePastLast) + { + break; + } + } + + if(First != OnePastLast) + { + Last->Prev = OneBeforeFirst; + Last->Prev->Next = Last; + First->Next = OnePastLast; + First->Next->Prev = First; + } +} + +static void kbts__ExecuteOp(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage) +{ + KBTS_INSTRUMENT_FUNCTION_BEGIN; + + if(Config) + { + kbts_font *Font = Config->Font; + kbts__op_kind OpKind = Scratchpad->OpKind; + + switch(OpKind) + { + case KBTS__OP_KIND_PRE_NORMALIZE_DOTTED_CIRCLES: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(PRE_NORMALIZE_DOTTED_CIRCLES); + + // Before even trying to normalize anything, there are some _exceptions_ we have to take care of. + // The USE spec gives us a list of codepoint sequences which necessitate insertion of a dotted circle. + // These sequences are from IndicShapingInvalidClusters.txt. + kbts_u64 Codepoints; Codepoints = 0; // 0xABBBBBCCCCCDDDDD + KBTS__FOR_GLYPH(Storage, Glyph) + { + kbts_u32 NewCodepoint; NewCodepoint = Glyph->Codepoint & 0x1FFFFF; + Codepoints = (Codepoints << 21) | NewCodepoint; + + // This switch is faster than any table lookup I could come up with in my tests. + #define KBTS_C2(A, B) case (((kbts_u64)(A) << 21) | (kbts_u64)(B)): + switch(Codepoints & (((kbts_u64)1 << 42) - 1)) + { + default: + if((Codepoints & (((kbts_u64)1 << 63) - 1)) == (((kbts_u64)0x930 << 42) | ((kbts_u64)0x94D << 21) | ((kbts_u64)0x907))) + { + KBTS_C2(0x905, 0x93A) + KBTS_C2(0x905, 0x93B) + KBTS_C2(0x905, 0x93E) + KBTS_C2(0x905, 0x945) + KBTS_C2(0x905, 0x946) + KBTS_C2(0x905, 0x949) + KBTS_C2(0x905, 0x94A) + KBTS_C2(0x905, 0x94B) + KBTS_C2(0x905, 0x94C) + KBTS_C2(0x905, 0x94F) + KBTS_C2(0x905, 0x956) + KBTS_C2(0x905, 0x957) + KBTS_C2(0x906, 0x93A) + KBTS_C2(0x906, 0x945) + KBTS_C2(0x906, 0x946) + KBTS_C2(0x906, 0x947) + KBTS_C2(0x906, 0x948) + KBTS_C2(0x909, 0x941) + KBTS_C2(0x90F, 0x945) + KBTS_C2(0x90F, 0x946) + KBTS_C2(0x90F, 0x947) + KBTS_C2(0x985, 0x9BE) + KBTS_C2(0x98B, 0x9C3) + KBTS_C2(0x98C, 0x9E2) + KBTS_C2(0xA05, 0xA3E) + KBTS_C2(0xA05, 0xA48) + KBTS_C2(0xA05, 0xA4C) + KBTS_C2(0xA72, 0xA3F) + KBTS_C2(0xA72, 0xA40) + KBTS_C2(0xA72, 0xA47) + KBTS_C2(0xA73, 0xA41) + KBTS_C2(0xA73, 0xA42) + KBTS_C2(0xA73, 0xA4B) + KBTS_C2(0xA85, 0xABE) + KBTS_C2(0xA85, 0xAC5) + KBTS_C2(0xA85, 0xAC7) + KBTS_C2(0xA85, 0xAC8) + KBTS_C2(0xA85, 0xAC9) + KBTS_C2(0xA85, 0xACB) + KBTS_C2(0xA85, 0xACC) + KBTS_C2(0xAC5, 0xABE) + KBTS_C2(0xB05, 0xB3E) + KBTS_C2(0xB0F, 0xB57) + KBTS_C2(0xB13, 0xB57) + KBTS_C2(0xB85, 0xBC2) + KBTS_C2(0xC12, 0xC4C) + KBTS_C2(0xC12, 0xC55) + KBTS_C2(0xC3F, 0xC55) + KBTS_C2(0xC46, 0xC55) + KBTS_C2(0xC4A, 0xC55) + KBTS_C2(0xC89, 0xCBE) + KBTS_C2(0xC8B, 0xCBE) + KBTS_C2(0xC92, 0xCCC) + KBTS_C2(0xD07, 0xD57) + KBTS_C2(0xD09, 0xD57) + KBTS_C2(0xD0E, 0xD46) + KBTS_C2(0xD12, 0xD3E) + KBTS_C2(0xD12, 0xD57) + KBTS_C2(0xD85, 0xDCF) + KBTS_C2(0xD85, 0xDD0) + KBTS_C2(0xD85, 0xDD1) + KBTS_C2(0xD8B, 0xDDF) + KBTS_C2(0xD8D, 0xDD8) + KBTS_C2(0xD8F, 0xDDF) + KBTS_C2(0xD91, 0xDCA) + KBTS_C2(0xD91, 0xDD9) + KBTS_C2(0xD91, 0xDDA) + KBTS_C2(0xD91, 0xDDC) + KBTS_C2(0xD91, 0xDDD) + KBTS_C2(0xD91, 0xDDE) + KBTS_C2(0xD94, 0xDDF) + KBTS_C2(0x11005, 0x11038) + KBTS_C2(0x1100B, 0x1103E) + KBTS_C2(0x1100F, 0x11042) + KBTS_C2(0x11200, 0x1122C) + KBTS_C2(0x11200, 0x11231) + KBTS_C2(0x11200, 0x11233) + KBTS_C2(0x11206, 0x1122C) + KBTS_C2(0x1122C, 0x11230) + KBTS_C2(0x1122C, 0x11231) + KBTS_C2(0x11240, 0x1122E) + KBTS_C2(0x112B0, 0x112E0) + KBTS_C2(0x112B0, 0x112E5) + KBTS_C2(0x112B0, 0x112E6) + KBTS_C2(0x112B0, 0x112E7) + KBTS_C2(0x112B0, 0x112E8) + KBTS_C2(0x11481, 0x114B0) + KBTS_C2(0x1148B, 0x114BA) + KBTS_C2(0x1148D, 0x114BA) + KBTS_C2(0x114AA, 0x114B5) + KBTS_C2(0x114AA, 0x114B6) + KBTS_C2(0x11600, 0x11639) + KBTS_C2(0x11600, 0x1163A) + KBTS_C2(0x11601, 0x11639) + KBTS_C2(0x11601, 0x1163A) + KBTS_C2(0x11680, 0x116AD) + KBTS_C2(0x11680, 0x116B4) + KBTS_C2(0x11680, 0x116B5) + KBTS_C2(0x11686, 0x116B2) + { + kbts_glyph *NewGlyph = kbts__InsertGlyphBefore(Storage, Glyph, &Config->DottedCircle); + if(!NewGlyph) + { + goto OutOfMemory; + } + } break; + } + } + #undef KBTS_C2 + } + + KBTS_INSTRUMENT_BLOCK_END(PRE_NORMALIZE_DOTTED_CIRCLES); + } break; + + case KBTS__OP_KIND_NORMALIZE: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(NORMALIZE); + // @Incomplete: We need to honor this. + // HB_OT_SHAPE_NORMALIZATION_MODE_NONE, + // HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, + // HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */ + // + // hangul: HB_OT_SHAPE_NORMALIZATION_MODE_NONE, + // arabic: HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, + // default: HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, + // hebrew: HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, + // thai: HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, + // indic: HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + // khmer: HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + // myanmar: HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + // use: HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, + + KBTS_INSTRUMENT_BLOCK_BEGIN(Decompose); + { // Full NFD decomposition + kbts__arena_lifetime Lifetime = kbts__BeginLifetime(Scratchpad->Arena); + kbts_glyph *DecompositionGlyphs = kbts__PushArray(Scratchpad->Arena, kbts_glyph, KBTS__MAXIMUM_DECOMPOSITION_CODEPOINTS); + kbts_un CodepointsToDecomposeCount = 0; + + KBTS__FOR_GLYPH(Storage, Glyph) + { + if(kbts__GetDecompositionSize(Glyph->Decomposition)) + { + kbts_glyph *PrevAnchor = Glyph->Prev; + + DecompositionGlyphs[0] = *Glyph; + CodepointsToDecomposeCount = 1; + + kbts__FreeGlyph(Scratchpad, Storage, Glyph); + + while(CodepointsToDecomposeCount) + { + kbts_glyph GlyphToDecompose = DecompositionGlyphs[--CodepointsToDecomposeCount]; + kbts_u64 Decomposition = 0; + kbts_u32 DecompositionSize = 0; + int AnyUnsupported = 0; + kbts_glyph Decomposed[2]; + + if(!(GlyphToDecompose.Flags & KBTS_GLYPH_FLAG_DO_NOT_DECOMPOSE)) + { + Decomposition = GlyphToDecompose.Decomposition; + DecompositionSize = kbts__GetDecompositionSize(Decomposition); + + // Only decompose when the font supports the decomposed form. + KBTS__FOR(DecompositionIndex, 0, DecompositionSize) + { + kbts_glyph DecompositionGlyph = kbts_CodepointToGlyph(Font, (int)kbts__GetDecompositionCodepoint(Decomposition, DecompositionIndex), 0, 0); + DecompositionGlyph.Config = GlyphToDecompose.Config; + DecompositionGlyph.UserIdOrCodepointIndex = GlyphToDecompose.UserIdOrCodepointIndex; + + AnyUnsupported |= !DecompositionGlyph.Id; + Decomposed[DecompositionIndex] = DecompositionGlyph; + } + } + + if(AnyUnsupported | !DecompositionSize) + { + kbts_glyph *NewGlyph = kbts__InsertGlyphAfter(Storage, PrevAnchor, &GlyphToDecompose); + if(!NewGlyph) + { + goto OutOfMemory; + } + + PrevAnchor = NewGlyph; + } + else + { + KBTS_ASSERT((CodepointsToDecomposeCount + DecompositionSize) <= KBTS__MAXIMUM_DECOMPOSITION_CODEPOINTS); + + if(Decomposition & KBTS_UNICODE_DECOMPOSITION_DO_NOT_RECURSE0) + { + Decomposed[0].Flags |= KBTS_GLYPH_FLAG_DO_NOT_DECOMPOSE; + } + if(Decomposition & KBTS_UNICODE_DECOMPOSITION_DO_NOT_RECURSE1) + { + Decomposed[1].Flags |= KBTS_GLYPH_FLAG_DO_NOT_DECOMPOSE; + } + + KBTS__FOR(DecompositionIndex, 0, DecompositionSize) + { + // We reverse the glyphs here because we use a stack. + DecompositionGlyphs[CodepointsToDecomposeCount++] = Decomposed[DecompositionSize - 1 - DecompositionIndex]; + } + } + } + + Glyph = PrevAnchor; + } + } + + kbts__EndLifetime(&Lifetime); + } + KBTS_INSTRUMENT_BLOCK_END(Decompose); + + KBTS_INSTRUMENT_BLOCK_BEGIN(Recompose); + { // Selective recomposition. + // The OpenType shaping documents say that Hebrew Alphabetic Presentation Form compositions aren't canonical, + // but looking at UnicodeData.txt, it seems like they totally are, so they are handled here. + kbts__arena_lifetime Lifetime = kbts__BeginLifetime(Scratchpad->Arena); + kbts_glyph *LastBase = 0; + kbts_un LastBaseParentCount = 0; + kbts_un PreSlashDecimalDigitCount = 0; + kbts_glyph *PreSlashGlyph = 0; + kbts_glyph *DigitGlyph = 0; + kbts_un DecimalDigitCount = 0; + int InFraction = 0; + kbts_u32 LastBaseParentsLoaded = 0; + kbts_glyph_parent LastBaseParents[KBTS_MAXIMUM_RECOMPOSITION_PARENTS]; + kbts_glyph *Parents = kbts__PushArray(Scratchpad->Arena, kbts_glyph, KBTS_MAXIMUM_RECOMPOSITION_PARENTS); + + kbts_u32 BeforeFractionSlashGlyphFlags = KBTS_GLYPH_FLAG_NUMR | KBTS_GLYPH_FLAG_FRAC; + kbts_u32 AfterFractionSlashGlyphFlags = KBTS_GLYPH_FLAG_DNOM | KBTS_GLYPH_FLAG_FRAC; + if(kbts__ShaperRtl(Config->Shaper)) + { + // RTL needs to invert NUMR and DNOM. + kbts_u32 Swap = BeforeFractionSlashGlyphFlags; + BeforeFractionSlashGlyphFlags = AfterFractionSlashGlyphFlags; + AfterFractionSlashGlyphFlags = Swap; + } + + // We also collate user features here. + kbts__feature_set UserFeatures = KBTS__ZERO; + kbts__feature_set *DefaultFeatures = &Config->Features; + + int ShouldFlip = (Scratchpad->RunDirection == KBTS_DIRECTION_RTL); + + KBTS__FOR_GLYPH(Storage, Glyph) + { + Glyph->Uid = (kbts_u16)++Scratchpad->NextGlyphUid; + + if(Glyph->Config) + { + kbts_glyph_config *GlyphConfig = Glyph->Config; + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(UserFeatures.Flags)) + { + UserFeatures.Flags[WordIndex] |= GlyphConfig->EnabledFeatures.Flags[WordIndex] & ~DefaultFeatures->Flags[WordIndex]; + } + } + + // In RTL, mirror all glyphs when their mirror is covered. + if(ShouldFlip && + (Glyph->UnicodeFlags & KBTS_UNICODE_FLAG_MIRRORED)) + { + kbts_u32 MatchingBracketCodepoint = kbts__GetUnicodeMirrorCodepoint(Glyph->Codepoint); + kbts_glyph MatchingBracket = kbts_CodepointToGlyph(Font, (int)MatchingBracketCodepoint, 0, 0); + if(MatchingBracket.Id) + { + kbts__SetGlyphPreserveLinksAndUserId(Glyph, &MatchingBracket); + } + } + + kbts_u32 SingleRecompositionCodepoints[KBTS_MAXIMUM_RECOMPOSITION_PARENTS]; + kbts_un SingleRecompositionCodepointCount = 0; + kbts_un DoubleRecompositionCount = LastBaseParentCount; + + if(!Glyph->CombiningClass) + { + LastBase = Glyph; + // From the Microsoft docs: + // USE decomposes split vowel characters belonging to UISC = Vowel_Dependent according to character + // decomposition mappings defined in UnicodeData.txt + // Cluster validation, is done based on the decomposed state of a split vowel. + // + // (Note: our Matra corresponds to Vowel_Dependent + Pure_Killer.) + if((Config->Shaper != KBTS_SHAPER_USE) || (Glyph->SyllabicClass != KBTS_INDIC_SYLLABIC_CLASS_MATRA)) + { + kbts_s32 *LastBaseParentDeltas = kbts__GetParentInfoDeltas(Glyph->ParentInfo); + kbts_un ParentCount = kbts__GetParentInfoCount(Glyph->ParentInfo); + + kbts_un DoubleDecompositionCount = 0; + KBTS__FOR(ParentIndex, 0, ParentCount) + { + kbts_glyph_parent Parent = KBTS__ZERO; + Parent.Codepoint = Glyph->Codepoint + (kbts_u32)LastBaseParentDeltas[ParentIndex]; + Parent.Decomposition = kbts__GetUnicodeDecomposition(Parent.Codepoint); + + kbts_un DecompositionSize = kbts__GetDecompositionSize(Parent.Decomposition); + if(DecompositionSize == 1) + { + SingleRecompositionCodepoints[SingleRecompositionCodepointCount++] = Parent.Codepoint; + } + else + { + LastBaseParents[DoubleDecompositionCount++] = Parent; + } + } + + LastBaseParentCount = DoubleDecompositionCount; + LastBaseParentsLoaded = 0; + } + else + { + LastBaseParentCount = 0; + } + + DoubleRecompositionCount = 0; + } + + int Recomposed = 0; + + if(!Recomposed) + { + KBTS_INSTRUMENT_BLOCK_BEGIN(ParentNSquaredStupidity); + KBTS__FOR(ParentIndex, 0, DoubleRecompositionCount) + { + kbts_glyph_parent *Parent = &LastBaseParents[ParentIndex]; + kbts_u32 Codepoint1 = kbts__GetDecompositionCodepoint(Parent->Decomposition, 1); + + if(Glyph->Codepoint == Codepoint1) + { + kbts_glyph *ParentGlyph = &Parents[ParentIndex]; + if(!(LastBaseParentsLoaded & (1 << ParentIndex))) + { + *ParentGlyph = kbts_CodepointToGlyph(Font, (int)Parent->Codepoint, 0, 0); + ParentGlyph->Uid = LastBase->Uid; + ParentGlyph->UserIdOrCodepointIndex = LastBase->UserIdOrCodepointIndex; + ParentGlyph->Config = LastBase->Config; + } + + if(ParentGlyph->Id) + { + // Both match. Reclaim space. + kbts_glyph *Next = Glyph->Next; + KBTS__DLLIST_REMOVE(Glyph); + Glyph = Next; + + Recomposed = 1; + kbts__SetGlyphPreserveLinksAndUserId(LastBase, ParentGlyph); + + break; + } + else + { + // This glyph is never good. Forget it. + LastBaseParents[ParentIndex] = LastBaseParents[LastBaseParentCount - 1]; + Parents[ParentIndex] = Parents[LastBaseParentCount - 1]; + LastBaseParentsLoaded &= ~(1 << ParentIndex); + LastBaseParentsLoaded |= (LastBaseParentsLoaded & (1 << (LastBaseParentCount - 1))) >> (LastBaseParentCount - 1 - ParentIndex); + + LastBaseParentCount -= 1; + DoubleRecompositionCount -= 1; + ParentIndex -= 1; + } + } + } + KBTS_INSTRUMENT_BLOCK_END(ParentNSquaredStupidity); + } + + if(!Recomposed) + { + KBTS__FOR(SingleRecompositionIndex, 0, SingleRecompositionCodepointCount) + { + kbts_glyph ParentGlyph = kbts_CodepointToGlyph(Font, (int)SingleRecompositionCodepoints[SingleRecompositionIndex], 0, 0); + if(ParentGlyph.Id) + { + ParentGlyph.Config = Glyph->Config; + + kbts__SetGlyphPreserveLinksAndUserId(Glyph, &ParentGlyph); + Recomposed = 1; + break; + } + } + } + + // It is safe to look for fractions here, because decimal digits/the fraction slash are not marks or + // jamos, so they should not get reordered after this pass. + if(Glyph->UnicodeFlags & KBTS_UNICODE_FLAG_DECIMAL_DIGIT) + { + if(InFraction) + { + // We are in the post-slash part of the fraction. + Glyph->Flags |= AfterFractionSlashGlyphFlags; + // Only flag the pre-slash part of the fraction if there is a post-slash part. + KBTS__FOR(DecimalDigitIndex, 0, PreSlashDecimalDigitCount) + { + PreSlashGlyph->Flags |= BeforeFractionSlashGlyphFlags; + PreSlashGlyph = PreSlashGlyph->Next; + } + PreSlashDecimalDigitCount = 0; + } + if(!DecimalDigitCount) + { + DigitGlyph = Glyph; + } + DecimalDigitCount += 1; + } + else if((Glyph->Codepoint == 0x2044) && (!InFraction || DecimalDigitCount)) + { + // Fraction slash. + Glyph->Flags |= KBTS_GLYPH_FLAG_FRAC; + PreSlashDecimalDigitCount = DecimalDigitCount; + PreSlashGlyph = DigitGlyph; + InFraction = DecimalDigitCount != 0; + DecimalDigitCount = 0; + } + else + { + InFraction = 0; + } + + if(Recomposed) + { + // @Robustness: This doesn't work when LastBase != Glyph->Prev, does it? + Glyph = Glyph->Prev; // Handle recursive recomposition. + } + } + + // Ignore added features that are already part of the shaper. + kbts__feature_set *ShaperFeatures = &Config->Features; + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(UserFeatures.Flags)) + { + UserFeatures.Flags[WordIndex] &= ~ShaperFeatures->Flags[WordIndex]; + } + + Scratchpad->UserFeatures = UserFeatures; + kbts__EndLifetime(&Lifetime); + } + KBTS_INSTRUMENT_BLOCK_END(Recompose); + + KBTS_INSTRUMENT_BLOCK_BEGIN(MarkReordering); + { // Unicode mark reordering. + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts_u8 CombiningClass = Glyph->CombiningClass; + + if(CombiningClass) + { + Glyph->MarkOrdering = CombiningClass; + + kbts_glyph *SequenceGlyph = Glyph->Next; + for(; + kbts__GlyphIsValid(Storage, SequenceGlyph); + SequenceGlyph = SequenceGlyph->Next) + { + kbts_u8 SequenceGlyphCombiningClass = SequenceGlyph->CombiningClass; + if(SequenceGlyphCombiningClass) + { + SequenceGlyph->MarkOrdering = SequenceGlyphCombiningClass; + } + else + { + break; + } + } + + kbts_glyph *AfterSequence = SequenceGlyph; + if(kbts__GlyphIsValid(Storage, AfterSequence)) + { + AfterSequence = AfterSequence->Next; + } + + KBTS__DLLIST_SORT(Glyph, SequenceGlyph, MarkOrdering); + + #ifdef KBTS_SANITY_CHECK + { + kbts_glyph *Glyph0 = OneBeforeSequence->Next; + kbts_glyph *Glyph1 = Glyph0->Next; + KBTS__FOR(SequenceIndex, 1, MarkSequenceLength) + { + KBTS_ASSERT(Glyph0->MarkOrdering <= Glyph1->MarkOrdering); + + Glyph0 = Glyph0->Next; + Glyph1 = Glyph1->Next; + } + } + #endif + + Glyph = AfterSequence; + } + else + { + Glyph = Glyph->Next; + } + } + } + KBTS_INSTRUMENT_BLOCK_END(MarkReordering); + + if(Config->Script == KBTS_SCRIPT_ARABIC) + { + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts_glyph *Next = Glyph->Next; + + // Find a mark sequence. + kbts_u8 CombiningClass = Glyph->CombiningClass; + + if(CombiningClass) + { + // Arabic: Reorder sequences of mark glyphs. + // + // From the Unicode standard: + // - Move any shadda characters (ccc=33) to the beginning of S. + // - If a sequence of ccc=230 characters begins with any MCM characters, move the sequence of such MCM + // characters + // to the beginning of S (before any characters with ccc=33). + // - If a sequence of ccc=220 characters begins with any MCM characters, move the sequence of such MCM + // characters + // to the beginning of S (before any MCM with ccc=230 or ccc=33). + // + // Final ordering: 220 230 shadda other + + kbts__mcm_sequence_state Mcm220SequenceState = 0; + kbts__mcm_sequence_state Mcm230SequenceState = 0; + + # define KBTS_REMAPPED_CCC_33 27 + + kbts_glyph *SequenceGlyph = Glyph; + for(; + kbts__GlyphIsValid(Storage, SequenceGlyph); + SequenceGlyph = SequenceGlyph->Next) + { + kbts_u16 SequenceGlyphCombiningClass = SequenceGlyph->CombiningClass; + kbts_u16 SequenceGlyphFlags = SequenceGlyph->UnicodeFlags; + + kbts_u8 MarkOrdering = 3; + + if(SequenceGlyphCombiningClass == KBTS_REMAPPED_CCC_33) + { + MarkOrdering = 2; + } + else if(SequenceGlyphCombiningClass == 220) + { + if(SequenceGlyphFlags & KBTS_UNICODE_FLAG_MODIFIER_COMBINING_MARK) + { + if(Mcm220SequenceState != KBTS__MCM_SEQUENCE_STATE_OUT) + { + Mcm220SequenceState = KBTS__MCM_SEQUENCE_STATE_IN; + } + } + else + { + Mcm220SequenceState = KBTS__MCM_SEQUENCE_STATE_OUT; + } + + if(Mcm220SequenceState == KBTS__MCM_SEQUENCE_STATE_IN) + { + MarkOrdering = 0; + } + + Mcm230SequenceState = KBTS__MCM_SEQUENCE_STATE_NONE; + } + else if(SequenceGlyphCombiningClass == 230) + { + if(SequenceGlyphFlags & KBTS_UNICODE_FLAG_MODIFIER_COMBINING_MARK) + { + if(Mcm230SequenceState != KBTS__MCM_SEQUENCE_STATE_OUT) + { + Mcm230SequenceState = KBTS__MCM_SEQUENCE_STATE_IN; + } + } + else + { + Mcm230SequenceState = KBTS__MCM_SEQUENCE_STATE_OUT; + } + + if(Mcm230SequenceState == KBTS__MCM_SEQUENCE_STATE_IN) + { + MarkOrdering = 1; + } + } + else if(SequenceGlyphCombiningClass) + { + Mcm220SequenceState = KBTS__MCM_SEQUENCE_STATE_NONE; + Mcm230SequenceState = KBTS__MCM_SEQUENCE_STATE_NONE; + } + else + { + break; + } + + SequenceGlyph->MarkOrdering = MarkOrdering; + } + + KBTS__DLLIST_SORT(Glyph, SequenceGlyph, MarkOrdering); + + #ifdef KBTS_SANITY_CHECK + { + kbts_glyph *Glyph0 = OneBeforeGlyph->Next; + for(kbts_glyph *Glyph1 = Glyph0->Next; + Glyph1 != SequenceGlyph; + Glyph1 = Glyph1->Next) + { + KBTS_ASSERT(Glyph0->MarkOrdering <= Glyph1->MarkOrdering); + Glyph0 = Glyph1; + } + } + #endif + + Next = SequenceGlyph; + } + + Glyph = Next; + } + } + else if((Config->Script == KBTS_SCRIPT_THAI) || (Config->Script == KBTS_SCRIPT_LAO)) + { + // Decompose sara/sala ams. + kbts_glyph *AboveBaseGlyph; AboveBaseGlyph = 0; + + KBTS__FOR_GLYPH(Storage, Glyph) + { + kbts_u32 Codepoint = Glyph->Codepoint; + + switch(Codepoint) + { + // Sara am/sala am. + // We match both because storing the sara am codepoint that corresponds to the current script + // doesn't seem that worthwhile, given that this is already a pretty big switch case. + // If we choose to use a unicode flag or indic syllabic category to notate above-base marks, + // then this loops gets a lot tighter and it would probably become the right call to pre-determine + // the sara am codepoint. + case 0xE33: case 0xEB3: // Sara am + { + kbts_glyph *NewGlyph = kbts__InsertGlyphBefore(Storage, AboveBaseGlyph, &Config->Nikhahit); + if(!NewGlyph) + { + goto OutOfMemory; + } + + kbts__SetGlyphPreserveLinksAndUserId(Glyph, &Config->SaraAa); + } break; + + case 0xE31: case 0xE34: case 0xE35: case 0xE36: case 0xE37: case 0xE3B: + case 0xE47: case 0xE48: case 0xE49: case 0xE4A: case 0xE4B: case 0xE4C: case 0xE4D: case 0xE4E: + case 0xEB1: case 0xEB4: case 0xEB5: case 0xEB6: case 0xEB7: case 0xEBB: + case 0xEC7: case 0xEC8: case 0xEC9: case 0xECA: case 0xECB: case 0xECC: case 0xECD: case 0xECE: + if(!AboveBaseGlyph) + { + AboveBaseGlyph = Glyph; + } + break; + + default: + AboveBaseGlyph = 0; + break; + } + } + } + + KBTS_INSTRUMENT_BLOCK_END(NORMALIZE); + } break; + + case KBTS__OP_KIND_NORMALIZE_HANGUL: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(NORMALIZE_HANGUL); + + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts_glyph *Next = Glyph->Next; + + kbts_un L = 0; + kbts_un V = 0; + kbts_un T = 0; + kbts_un LvtGlyphCount = 0; + kbts_glyph LvtGlyphs[4]; + + kbts__hangul_syllable_info LInfo = kbts__HangulSyllableInfo(Glyph->Codepoint); + if(LInfo.Type >= KBTS__HANGUL_SYLLABLE_TYPE_LV) + { + kbts_un SIndex = (Glyph->Codepoint - 0xAC00); + + L = 0x1100 + SIndex / 588; + V = 0x1161 + (SIndex % 588) / 28; + + kbts_un TIndex = SIndex % 28; + if(TIndex) + { + T = 0x11A7 + TIndex; + } + } + else if(LInfo.Type == KBTS__HANGUL_SYLLABLE_TYPE_L) + { + L = Glyph->Codepoint; + } + + if(L) + { + kbts__hangul_syllable_info VInfo = KBTS__ZERO; + + if(!V && kbts__GlyphIsValid(Storage, Next)) + { + kbts_u32 VCodepoint = Next->Codepoint; + + VInfo = kbts__HangulSyllableInfo(VCodepoint); + + if(VInfo.Type == KBTS__HANGUL_SYLLABLE_TYPE_V) + { + V = VCodepoint; + + Next = Next->Next; + } + } + + if(V) + { + kbts__hangul_syllable_info TInfo = KBTS__ZERO; + + if(!T && kbts__GlyphIsValid(Storage, Next)) + { + kbts_u32 TCodepoint = Next->Codepoint; + + TInfo = kbts__HangulSyllableInfo(TCodepoint); + + if(TInfo.Type == KBTS__HANGUL_SYLLABLE_TYPE_T) + { + T = TCodepoint; + + Next = Next->Next; + } + } + + // Check for any tone marks that we need to swap to the front of the syllable. + // The OpenType shaping documents say that we need to do this after applying GSUB features, but + // harfbuzz does it before, so it's probably fine to do it here? + // It's also basically free to do here, which is nice. + if(kbts__GlyphIsValid(Storage, Next)) + { + kbts_u32 ToneMarkCodepoint = Next->Codepoint; + + if((ToneMarkCodepoint >= 0x302E) && (ToneMarkCodepoint <= 0x302F)) + { + LvtGlyphs[LvtGlyphCount++] = kbts_CodepointToGlyph(Font, (int)ToneMarkCodepoint, 0, 0); + + Next = Next->Next; + } + } + + if(LInfo.Composable & VInfo.Composable & TInfo.Composable) + { + // Try LVT. + kbts_un LvtCodepoint = 0xAC00 + (L - 0x1100) * 588 + (V - 0x1161) * 28 + (T - 0x11A7); + + kbts_glyph LvtGlyph = kbts_CodepointToGlyph(Font, (int)LvtCodepoint, 0, 0); + if(LvtGlyph.Id) + { + LvtGlyphs[LvtGlyphCount++] = LvtGlyph; + } + } + + if(!LvtGlyphCount) + { + kbts_glyph LvGlyph = KBTS__ZERO; + if(LInfo.Composable & VInfo.Composable) + { + // Try LV. + kbts_un LvCodepoint = 0xAC00 + (L - 0x1100) * 588 + (V - 0x1161) * 28; + + LvGlyph = kbts_CodepointToGlyph(Font, (int)LvCodepoint, 0, 0); + } + + if(LvGlyph.Id) + { + LvtGlyphs[LvtGlyphCount++] = LvGlyph; + } + else + { + // Do L-V. + kbts_glyph LGlyph = kbts_CodepointToGlyph(Font, (int)L, 0, 0); + LGlyph.Flags |= KBTS_GLYPH_FLAG_LJMO; + + kbts_glyph VGlyph = kbts_CodepointToGlyph(Font, (int)V, 0, 0); + VGlyph.Flags |= KBTS_GLYPH_FLAG_VJMO; + + LvtGlyphs[LvtGlyphCount++] = LGlyph; + LvtGlyphs[LvtGlyphCount++] = VGlyph; + } + + if(T) + { + kbts_glyph TGlyph = kbts_CodepointToGlyph(Font, (int)T, 0, 0); + TGlyph.Flags |= KBTS_GLYPH_FLAG_TJMO; + + LvtGlyphs[LvtGlyphCount++] = TGlyph; + } + } + } + } + + if(!LvtGlyphCount) + { + kbts_glyph NewGlyph = kbts_CodepointToGlyph(Font, (int)Glyph->Codepoint, 0, 0); + + LvtGlyphs[LvtGlyphCount++] = NewGlyph; + } + + { // Insert the LVT glyphs. + kbts_glyph *LastConsumed = Next->Prev; + + // Remove the sub-list from the main list. + Glyph->Prev->Next = LastConsumed->Next; + LastConsumed->Next->Prev = Glyph->Prev; + + // Send it to the free list. + Glyph->Prev = (kbts_glyph *)&Storage->FreeGlyphSentinel; + LastConsumed->Next = Storage->FreeGlyphSentinel.Next; + Glyph->Prev->Next = Glyph; + LastConsumed->Next->Prev = LastConsumed; + + for(kbts_un LvtGlyphIndex = 0; + LvtGlyphIndex < LvtGlyphCount; + ++LvtGlyphIndex) + { + kbts_glyph *LvtGlyph = &LvtGlyphs[LvtGlyphIndex]; + kbts_glyph *NewGlyph = kbts__InsertGlyphBefore(Storage, Next, LvtGlyph); + if(!NewGlyph) + { + goto OutOfMemory; + } + } + } + + Glyph = Next; + } + // KBTS_INSTRUMENT_BLOCK_END(NORMALIZE_HANGUL); + } + break; + + case KBTS__OP_KIND_GSUB_FEATURES: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(GSUB_FEATURES); + + kbts__gsub_gpos *FontGsub = kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GSUB, kbts__gsub_gpos); + kbts_lookup_list *LookupList; LookupList = kbts__GetLookupList(FontGsub); + kbts__arena_lifetime Lifetime = kbts__BeginLifetime(Scratchpad->Arena); + kbts__gsub_frame *Frames = kbts__PushArray(Scratchpad->Arena, kbts__gsub_frame, KBTS_LOOKUP_STACK_SIZE); + kbts_u32 GlyphFilter; + kbts__skip_flags SkipFlags; + kbts_un LookupIndex; + + if(kbts__BeginFeatures(Scratchpad, Config, KBTS_SHAPING_TABLE_GSUB)) + { + while(kbts__NextLookupIndex(Scratchpad, Config, &LookupIndex, &SkipFlags, &GlyphFilter, &Scratchpad->LookupFeatures)) + { + kbts__lookup *Lookup = kbts__GetLookup(LookupList, LookupIndex); + + // From the Microsoft docs: + // If a Lookup table has multiple subtables, the subtables are processed in order, testing the glyph sequence + // at the current glyph position for a match with the input sequence patterns specified by each subtable in + // turn. + // + // This means the subtable loop is _inside_ of the loop over our glyphs. + + // Reverse chaining substitutions are tricky. + // See the comment at :ReverseChaining. + for(kbts_glyph *Glyph = (Lookup->Type == 8) ? Storage->GlyphSentinel.Prev : Storage->GlyphSentinel.Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts__BeginLookupApplication(Scratchpad, Glyph); + kbts_un FrameCount = 0; + kbts_u32 FilterMask = Config->Shaper == KBTS_SHAPER_USE ? KBTS__USE_GLYPH_FEATURE_MASK : KBTS__GLYPH_FEATURE_MASK; + kbts_u32 EffectiveGlyphFilter = GlyphFilter & FilterMask; + + if(kbts__GlyphIncludedInLookup(Font, 0, LookupIndex, Glyph->Id) && + ((Glyph->Flags & EffectiveGlyphFilter) == EffectiveGlyphFilter) && + kbts__ConfigAllowsFeatures(Scratchpad, Config, Glyph->Config, &Scratchpad->LookupFeatures)) + { + kbts__gsub_frame FirstFrame = KBTS__ZERO; + FirstFrame.LookupIndex = (kbts_u16)LookupIndex; + FirstFrame.InputGlyph = Glyph; + + Frames[0] = FirstFrame; + FrameCount = 1; + + while(FrameCount) + { + // These flags are used by USE. + kbts_u32 GeneratedGlyphFlags = GlyphFilter & (KBTS_GLYPH_FLAG_RPHF | KBTS_GLYPH_FLAG_PREF); + kbts__DoSubstitution(Scratchpad, Config, Storage, LookupList, Frames, &FrameCount, 0, SkipFlags, GeneratedGlyphFlags); + } + } + + kbts_glyph *OnePastLast = kbts__EndLookupApplication(Scratchpad); + Glyph = (Lookup->Type == 8) ? Glyph->Prev : OnePastLast; + } + } + } + + kbts__EndLifetime(&Lifetime); + KBTS_INSTRUMENT_BLOCK_END(GSUB_FEATURES); + } + break; + + case KBTS__OP_KIND_FLAG_JOINING_LETTERS: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(FLAG_JOINING_LETTERS); + kbts_u64 JoiningTypesMatchLookup = + (((1ull << KBTS_UNICODE_JOINING_TYPE_RIGHT) | (1ull << KBTS_UNICODE_JOINING_TYPE_DUAL) | (1ull << KBTS_UNICODE_JOINING_TYPE_FORCE)) << (8 * KBTS_UNICODE_JOINING_TYPE_LEFT)) | + (((1ull << KBTS_UNICODE_JOINING_TYPE_RIGHT) | (1ull << KBTS_UNICODE_JOINING_TYPE_DUAL) | (1ull << KBTS_UNICODE_JOINING_TYPE_FORCE)) << (8 * KBTS_UNICODE_JOINING_TYPE_DUAL)) | + (((1ull << KBTS_UNICODE_JOINING_TYPE_RIGHT) | (1ull << KBTS_UNICODE_JOINING_TYPE_DUAL) | (1ull << KBTS_UNICODE_JOINING_TYPE_FORCE)) << (8 * KBTS_UNICODE_JOINING_TYPE_FORCE)); + + kbts_u64 JoiningFeatureTransition = ((kbts_u64)KBTS_JOINING_FEATURE_INIT << (8 * KBTS_JOINING_FEATURE_ISOL)) | ((kbts_u64)KBTS_JOINING_FEATURE_MEDI << (8 * KBTS_JOINING_FEATURE_FINA)) | + ((kbts_u64)KBTS_JOINING_FEATURE_MEDI << (8 * KBTS_JOINING_FEATURE_MEDI)) | ((kbts_u64)KBTS_JOINING_FEATURE_MED2 << (8 * KBTS_JOINING_FEATURE_MED2)); + + // Tag letters for joining features. + kbts_glyph PreviousGlyph_ = KBTS__ZERO; + kbts_glyph *PreviousGlyph = &PreviousGlyph_; + KBTS__FOR_GLYPH(Storage, Glyph) + { + if(Glyph->JoiningType != KBTS_UNICODE_JOINING_TYPE_TRANSPARENT) + { + Glyph->JoiningFeature = (kbts_joining_feature)(!PreviousGlyph->JoiningType ? KBTS_JOINING_FEATURE_INIT : KBTS_JOINING_FEATURE_FINA); + + if(JoiningTypesMatchLookup & (1ull << (Glyph->JoiningType + 8 * PreviousGlyph->JoiningType))) + { + PreviousGlyph->JoiningFeature = (JoiningFeatureTransition >> (8 * PreviousGlyph->JoiningFeature)) & 0xFF; + PreviousGlyph->Flags = (PreviousGlyph->Flags & ~KBTS__JOINING_FEATURE_MASK) | KBTS__JOINING_FEATURE_TO_GLYPH_FLAG(PreviousGlyph->JoiningFeature); + + Glyph->JoiningFeature = KBTS_JOINING_FEATURE_FINA; + } + else + { + Glyph->JoiningFeature = KBTS_JOINING_FEATURE_ISOL; + } + + if(Glyph->JoiningFeature) + { + // Be careful that this properly maps kbts_joining_feature to KBTS_GLYPH_FLAG! + Glyph->Flags = (Glyph->Flags & ~KBTS__JOINING_FEATURE_MASK) | KBTS__JOINING_FEATURE_TO_GLYPH_FLAG(Glyph->JoiningFeature); + } + + PreviousGlyph = Glyph; + } + } + + KBTS_INSTRUMENT_BLOCK_END(FLAG_JOINING_LETTERS); + } + break; + + case KBTS__OP_KIND_GPOS_METRICS: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(GPOS_METRICS); + // hmtx/vmtx pass. + int ClearMarkAdvances = (Config->Shaper == KBTS_SHAPER_MYANMAR) || (Config->Shaper == KBTS_SHAPER_USE); + + kbts_u32 Orientation = KBTS_ORIENTATION_HORIZONTAL; // @Hardcoded + kbts_blob_table_id HeaTableId = KBTS_BLOB_TABLE_ID_HHEA; + kbts_blob_table_id MtxTableId = KBTS_BLOB_TABLE_ID_HMTX; + if(Orientation == KBTS_ORIENTATION_VERTICAL) + { + HeaTableId = KBTS_BLOB_TABLE_ID_VHEA; + MtxTableId = KBTS_BLOB_TABLE_ID_VMTX; + } + + kbts__hea *Hea = kbts__BlobTableDataType(Font->Blob, HeaTableId, kbts__hea); + kbts_u16 *Mtx = kbts__BlobTableDataType(Font->Blob, MtxTableId, kbts_u16); + + kbts__long_mtx *LongMetrics = 0; + // :LeftSideBearing + // kbts_s16 *ShortMetrics = 0; + if(Hea && Mtx) + { + LongMetrics = (kbts__long_mtx *)Mtx; + // :LeftSideBearing + // ShortMetrics = (kbts_s16 *)(LongMetrics + Hea->MetricCount); + } + + kbts__long_mtx DefaultMetric = {1024, 0}; + kbts__head *Head = kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_HEAD, kbts__head); + if(Head) + { + DefaultMetric.Advance = Head->UnitsPerEm; + if(Orientation == KBTS_ORIENTATION_HORIZONTAL) + { + DefaultMetric.Advance /= 2; + } + } + + KBTS__FOR_GLYPH(Storage, Glyph) + { + kbts__SetCursiveFlags(Glyph, 0); + + kbts__long_mtx Metric = DefaultMetric; + if(LongMetrics) + { + kbts_u32 Id = Glyph->Id; + + // At the end of shaping, default ignorable glyphs that are not generated by GSUB are replaced with zero-width + // whitespace glyphs (or a zero-width empty glyph if no whitespace glyph is present). + // (By the way, we do this because Harfbuzz does it, and Harfbuzz does it probably because Uniscribe does it.) + // We handle this in two steps: + // - The first is here. We want cursive attachments, and mark-to-base attachments, and other relative placements + // to take the zero width into account, and zeroing the width right at the beginning of GPOS is the most + // straighforward way to accomplish this. + // (@Incomplete: It is likely that we also need to take the default ignorable case into account when accumulating + // cursive offsets.) + // - In POST_GPOS_FIXUP, we perform the glyph ID substitution. We have to wait until all GPOS features have been + // executed to do this because they might possibly match the original ID. + if(!(Glyph->Flags & KBTS_GLYPH_FLAG_GENERATED_BY_GSUB) && (Glyph->UnicodeFlags & KBTS_UNICODE_FLAG_DEFAULT_IGNORABLE)) + { + Metric.Advance = 0; + // :LeftSideBearing + // Metric.PreviousSideBearing = 0; + } + else if(Id < Hea->MetricCount) + { + Metric = LongMetrics[Id]; + } + else + { + Metric.Advance = LongMetrics[Hea->MetricCount - 1].Advance; + // :LeftSideBearing + // Metric.PreviousSideBearing = ShortMetrics[Id - Hea->MetricCount]; + } + } + + if(!ClearMarkAdvances | (Glyph->Classes.Class != KBTS__GLYPH_CLASS_MARK)) + { + if(Orientation == KBTS_ORIENTATION_HORIZONTAL) + { + // :LeftSideBearing + // Why does harfbuzz not take bearings into account in these tests? + // P.X += Metric.PreviousSideBearing; + Glyph->AdvanceX = Metric.Advance; + } + else + { + // :LeftSideBearing + // Why does harfbuzz not take bearings into account in these tests? + // P.Y += Metric.PreviousSideBearing; + Glyph->AdvanceY = Metric.Advance; + } + } + } + KBTS_INSTRUMENT_BLOCK_END(GPOS_METRICS); + } + break; + + case KBTS__OP_KIND_GPOS_FEATURES: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(GPOS_FEATURES); + kbts__gsub_gpos *Gpos = kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GPOS, kbts__gsub_gpos); + + if(kbts__BeginFeatures(Scratchpad, Config, KBTS_SHAPING_TABLE_GPOS)) + { + kbts_lookup_list *LookupList = kbts__GetLookupList(Gpos); + kbts_un LookupIndex; + kbts__skip_flags SkipFlags; + kbts_u32 GlyphFilter; + kbts__feature_set LookupFeatures; + while(kbts__NextLookupIndex(Scratchpad, Config, &LookupIndex, &SkipFlags, &GlyphFilter, &LookupFeatures)) + { + kbts__lookup *PackedLookup = kbts__GetLookup(LookupList, LookupIndex); + kbts__unpacked_lookup Lookup = kbts__UnpackLookup(kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GDEF, kbts__gdef), PackedLookup); + + kbts_glyph *Glyph = Storage->GlyphSentinel.Next; + while(kbts__GlyphIsValid(Storage, Glyph)) + { + kbts__BeginLookupApplication(Scratchpad, Glyph); + + if(kbts__GlyphIncludedInLookup(Config->Font, 1, LookupIndex, Glyph->Id) && + kbts__ConfigAllowsFeatures(Scratchpad, Config, Glyph->Config, &LookupFeatures)) + { + KBTS__FOR(SubtableIndex, 0, Lookup.SubtableCount) + { + kbts_u16 *Subtable = KBTS__POINTER_OFFSET(kbts_u16, PackedLookup, Lookup.SubtableOffsets[SubtableIndex]); + + if(kbts__DoSingleAdjustment(Scratchpad, Config, Storage, LookupList, + LookupIndex, SubtableIndex, &Lookup, Subtable, + Glyph, 0, SkipFlags)) + { + break; + } + } + } + + Glyph = kbts__EndLookupApplication(Scratchpad); + } + } + } + + KBTS_INSTRUMENT_BLOCK_END(GPOS_FEATURES); + } + break; + + case KBTS__OP_KIND_POST_GPOS_FIXUP: + { + KBTS_INSTRUMENT_BLOCK_BEGIN(POST_GPOS_FIXUP); + kbts_glyph WhitespaceGlyph = Config->Whitespace; + int ClearMarkAdvances = kbts__ShaperClearsMarkAdvancesInPostGposFixup(Config->Shaper); + + if(Scratchpad->RunDirection == KBTS_DIRECTION_RTL) + { + // Flip direction. + // This might seem like a totally superfluous thing to do, because we have to do a bunch + // of work to reverse glyph order while still preserving their relative positions. + // However, for mainly LTR documents, the anchor position will naturally be left-aligned, + // while, in RTL documents, it will naturally right-align. + // As such, going through the glyph sequence and reversing it is needed _anyway_ at some point, + // and we might as well do it here, because this is where we can take resolve attachments + // for relatively cheap, since they are always back-looking. (The next paragraph explains this + // in more detail.) + + // The unintuitive part about this pass is the glyph advances. + // Normally, when iterating over a sequence of glyphs, we see base glyphs before marks. Obviously. + // However, when flipping the sequence, we see the marks before seeing the bases, which means we + // won't have accumulated the base glyph's advance yet! So we have to go through the sequence here + // and compensate for missing advances by precomputing them and baking them into the marks. + // Another way to reach the same result would be to keep marks on the same side as their bases when + // flipping, but that is not what Harfbuzz does, and, the day we decide we want to diverge from Harfbuzz, + // we will very likely be better off not flipping the sequence at all and deleting all of this garbage code. + kbts_s32 MarkAttachAdvanceX = 0; + kbts_s32 MarkAttachAdvanceY = 0; + KBTS__FOR_GLYPH(Storage, Glyph) + { + kbts_glyph *Attach = Glyph->AttachGlyph; + if(Attach) + { + kbts_s32 AttachAdvanceX = MarkAttachAdvanceX; + kbts_s32 AttachAdvanceY = MarkAttachAdvanceY; + if(Attach->Classes.Class != KBTS__GLYPH_CLASS_MARK) + { + AttachAdvanceX = Attach->AdvanceX; + AttachAdvanceY = Attach->AdvanceY; + } + Glyph->OffsetX += AttachAdvanceX; + Glyph->OffsetY += AttachAdvanceY; + MarkAttachAdvanceX = AttachAdvanceX; + MarkAttachAdvanceY = AttachAdvanceY; + } + } + + // Swap. + // @Speed: We could just choose the correct links when traversing instead. + kbts__DllistReverseSublist((kbts_glyph *)&Storage->GlyphSentinel, (kbts_glyph *)&Storage->GlyphSentinel); + } + + // Make default ignorables that weren't explicitly created by the font invisible. + // + // It is tempting to put this loop inside of an if(WhitespaceGlyph.Id), just like we do + // for dotted circle insertion. However, Harfbuzz does not do this! + // When the font does not contain a dotted circle, nothing is inserted, but when the font + // does not contain a whitespace glyph, _we still insert an empty glyph_. + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts_glyph *Next = Glyph->Next; + int Keep = 0; + + // It might be tempting to keep glyphs that were used in GPOS, but Harfbuzz doesn't care. + if(!(Glyph->Flags & KBTS_GLYPH_FLAG_GENERATED_BY_GSUB) && (Glyph->UnicodeFlags & KBTS_UNICODE_FLAG_DEFAULT_IGNORABLE)) + { + // This glyph is default ignorable and should be ignored. + if(WhitespaceGlyph.Id) + { + Keep = 1; + kbts__SetGlyphPreserveLinksAndUserId(Glyph, &WhitespaceGlyph); + } + } + else + { + if(ClearMarkAdvances && (Glyph->Classes.Class == KBTS__GLYPH_CLASS_MARK)) + { + Glyph->AdvanceX = Glyph->AdvanceY = 0; + } + Keep = 1; + } + + if(!Keep) + { + kbts__FreeGlyph(Scratchpad, Storage, Glyph); + } + + Glyph = Next; + } + + KBTS_INSTRUMENT_BLOCK_END(POST_GPOS_FIXUP); + } + break; + + case KBTS__OP_KIND_STCH_POSTPASS: + { + #if 0 + KBTS__FOR_GLYPH(ShapeState, Glyph) + { + if(Glyph->Flags & (KBTS_GLYPH_FLAG_STCH_ENDPOINT | KBTS_GLYPH_FLAG_STCH_EXTENSION)) + { + kbts_glyph *Extension = 0; + + kbts_s32 EndpointWidth = 0; + kbts_s32 ExtensionWidth = 0; + + while(kbts__GlyphIsValid(ShapeState, Glyph)) + { + kbts_glyph *AtGlyph = &Glyphs[At]; + + if(AtGlyph->Flags & KBTS_GLYPH_FLAG_STCH_ENDPOINT) + { + EndpointWidth += AtGlyph->AdvanceX; + + At += 1; + } + else if(AtGlyph->Flags & KBTS_GLYPH_FLAG_STCH_EXTENSION) + { + ExtensionIndex = At; + ExtensionWidth += AtGlyph->AdvanceX; + SawExtension = 1; + + At += 1; + } + else + { + break; + } + } + + kbts_sn WordWidth = 0; + + while(At < GlyphArray->Count) + { + kbts_glyph *AtGlyph = &Glyphs[At]; + + int Ok = 0; + + if(!(AtGlyph->Flags & (KBTS_GLYPH_FLAG_STCH_ENDPOINT | KBTS_GLYPH_FLAG_STCH_EXTENSION)) && (AtGlyph->UnicodeFlags & KBTS_UNICODE_FLAG_PART_OF_WORD)) + { + Ok = 1; + } + + if(Ok) + { + WordWidth += AtGlyph->AdvanceX; + + At += 1; + } + else + { + break; + } + } + + if(WordWidth > EndpointWidth) + { + kbts_sn ExtensionCount = (WordWidth - EndpointWidth) / ExtensionWidth; + if((ExtensionWidth * ExtensionCount) < (WordWidth - EndpointWidth)) + { + ExtensionCount += 1; + } + + (void)ExtensionCount; + (void)ExtensionIndex; + (void)SawExtension; + /* @Incomplete + kbts_glyph_adjustment *ExtensionAdjustment = &Positions[ExtensionIndex]; + ExtensionAdjustment->LastRepeatIndex = ExtensionCount - 1; + ExtensionAdjustment->RepeatOffsetX = (WordWidth - EndpointWidth - ExtensionWidth) / ExtensionCount; + */ + } + + GlyphIndex = At; + } + } + #endif + } + break; + } + + if(0) + { + OutOfMemory:; + Scratchpad->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + } + } + + KBTS_INSTRUMENT_FUNCTION_END; +} + +static kbts_glyph kbts__Substitute1(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_lookup_list *LookupList, kbts__feature *Feature, kbts__skip_flags SkipFlags, kbts_glyph *Glyph) +{ + kbts_glyph Result = *Glyph; + kbts_glyph TempSentinel; + TempSentinel.Prev = TempSentinel.Next = &Result; + Result.Prev = Result.Next = &TempSentinel; + kbts__glyph_list List = kbts__PushGlyphList(Storage, &Result, &Result); + + kbts__iterate_lookups IterateLookups = kbts__IterateLookups(LookupList, Feature); + while(kbts__NextLookup(&IterateLookups)) + { + kbts__gsub_frame Frames[8]; + { + kbts__gsub_frame *Frame = &Frames[0]; + *Frame = KBTS__ZERO_TYPE(kbts__gsub_frame); + Frame->LookupIndex = IterateLookups.LookupIndex; + Frame->SubtableIndex = 0; + Frame->StartIndex = 0; + Frame->InputGlyph = &Result; + } + kbts_un FrameCount = 1; + + while(FrameCount) + { + kbts__substitution_result_flags SubstitutionResult = kbts__DoSubstitution(Scratchpad, Config, Storage, + LookupList, Frames, &FrameCount, 0, SkipFlags, 0); + if(SubstitutionResult & KBTS__SUBSTITUTION_RESULT_FLAG_TRIED_TO_INSERT_WHILE_CHECK_ONLY) + { + goto Done; + } + } + } + +Done:; + kbts__PopGlyphList(Storage, &List); + return Result; +} + +typedef struct kbts__attach_state +{ + kbts__syllabic_position CurrentPosition; + kbts__syllabic_position LastPositionThatWasNotPreBaseMatra; + kbts_indic_syllabic_class LastClass; + kbts_glyph *Start; + kbts_glyph *OnePastLast; + kbts_glyph *At; +} kbts__attach_state; + +static kbts_glyph *kbts__BeginCluster(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage, + kbts_glyph *Glyph) +{ + kbts_font *Font = Config->Font; + kbts_glyph *Result = Glyph->Next; + kbts__arena_lifetime Lifetime = kbts__BeginLifetime(Scratchpad->Arena); + + Scratchpad->RealCluster = 0; + + switch(Config->Shaper) + { + case KBTS_SHAPER_INDIC: + { + kbts_lookup_list *LookupList = kbts__GetLookupList(kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GSUB, kbts__gsub_gpos)); + + int NonCluster = 0; + while(kbts__GlyphIsValid(Storage, Glyph) && + ((Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_OTHER) || + (Glyph->SyllabicClass >= KBTS_INDIC_SYLLABIC_CLASS_COUNT))) + { + NonCluster = 1; + Glyph = Glyph->Next; + } + + Result = Glyph; + + if(!NonCluster) + { + kbts_un ScanGlyphIndex = 0; + kbts_un State = 0; + kbts_un Broken = 1; + kbts_un BrokenState = 0; + kbts_glyph *FirstGlyphs[3]; + + while(kbts__GlyphIsValid(Storage, Glyph) && + (State < KBTS_INDIC_SYLLABIC_STATE_COUNT)) + { + kbts_un Class = Glyph->SyllabicClass; + + if(KBTS__IN_SET(Class, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_RA) + (KBTS_INDIC_SYLLABIC_CLASS_CONSONANT) + (KBTS_INDIC_SYLLABIC_CLASS_VOWEL) + (KBTS_INDIC_SYLLABIC_CLASS_DOTTED_CIRCLE) + (KBTS_INDIC_SYLLABIC_CLASS_PLACEHOLDER) + (KBTS_INDIC_SYLLABIC_CLASS_SYMBOL)))) + { + Broken = 0; + } + BrokenState = (BrokenState << 1) | Broken; + + if(ScanGlyphIndex < KBTS__ARRAY_LENGTH(FirstGlyphs)) + { + FirstGlyphs[ScanGlyphIndex] = Glyph; + } + + State = kbts_IndicSyllabicTransition[Class][State]; + State -= 1; // @Incomplete @Cleanup: Decrement every state by 1 in the transition table. + Glyph = Glyph->Next; + ScanGlyphIndex += 1; + } + + if(State > KBTS_INDIC_SYLLABIC_STATE_COUNT) + { + ScanGlyphIndex -= State - KBTS_INDIC_SYLLABIC_STATE_COUNT; + BrokenState >>= State - KBTS_INDIC_SYLLABIC_STATE_COUNT; + + while(State > KBTS_INDIC_SYLLABIC_STATE_COUNT) + { + Glyph = Glyph->Prev; + State -= 1; + } + + if(!ScanGlyphIndex) + { + // If we backtrack all the way to the beginning, still eat a character. + ScanGlyphIndex = 1; + } + } + + // NOTE: Symbols, vedics, modifiers, matras have their syllabic positions tagged at build time. + // It is tempting to use Unicode's positional information for consonants, too, but OpenType + // _strongly_ recommends that shapers use the font's tables instead, ie. doing tentative lookups + // with specific features. + + kbts__gsub_frame *Frames = kbts__PushArray(Scratchpad->Arena, kbts__gsub_frame, KBTS_LOOKUP_STACK_SIZE); + kbts_glyph *OnePastLastSyllableGlyph = Glyph; + kbts_glyph *FirstGlyph = FirstGlyphs[0]; + kbts_glyph *OneBeforeSyllableGlyph = FirstGlyph->Prev; + + if((Config->Script == KBTS_SCRIPT_KANNADA) && (ScanGlyphIndex >= 3) && + (FirstGlyphs[0]->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_RA) && + (FirstGlyphs[1]->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT) && + (FirstGlyphs[2]->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ)) + { + // In older versions of Unicode (~4.x, pre-2004), Ra-Virama-Zwj was recommended in Kannada + // to communicate the intent of displaying (Ra + (next consonant as below-base form)). + // This was changed in Unicode 5. Now, the recommended sequence to display (Ra + + // (next consonant as below-base form)) is Ra-Zwj-Virama. + // Since Ra-Virama-Zwj is not a useful sequence that happens organically in Kannada, + // we are free to transform it into Ra-Zwj-Virama here without losing information. + KBTS__DLLIST_SWAP(FirstGlyphs[1], FirstGlyphs[2]); + + // Also swap this, because this is used below for OnePastReph. + kbts_glyph *Swap = FirstGlyphs[1]; + FirstGlyphs[1] = FirstGlyphs[2]; + FirstGlyphs[2] = Swap; + } + + kbts_glyph_flags RephFlags = KBTS_GLYPH_FLAG_RPHF; + kbts_glyph *OnePastReph = FirstGlyphs[0]; + kbts_un OnePastRephIndex = 0; + { // Reph tagging. + // This first pass only figures out where the reph ends. + // We delay updating glyph properties until we know whether the reph is the base or not. + kbts_glyph *Second = FirstGlyphs[1]; + kbts_glyph *Third = FirstGlyphs[2]; + kbts__feature *Rphf = Config->Rphf; + + switch(Config->IndicScriptProperties.RephEncoding) + { + case KBTS__REPH_ENCODING_LOGICAL_REPHA: + if(FirstGlyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_REPHA) + { + RephFlags = 0; + OnePastRephIndex = 1; + } + break; + + case KBTS__REPH_ENCODING_IMPLICIT: + if((ScanGlyphIndex >= 2) && + (Second->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT)) + { + kbts_glyph Scratch[2]; + Scratch[0] = *FirstGlyphs[0]; + Scratch[1] = *FirstGlyphs[1]; + + if(kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Rphf, 0, Scratch, 2)) + { + OnePastRephIndex = 2; + } + } + break; + + case KBTS__REPH_ENCODING_EXPLICIT: + if((ScanGlyphIndex >= 3) && + (Second->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT) && + (Third->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ)) + { + kbts_glyph Scratch[3]; + Scratch[0] = *FirstGlyphs[0]; + Scratch[1] = *FirstGlyphs[1]; + Scratch[2] = *FirstGlyphs[2]; + + if(kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Rphf, 0, Scratch, 3)) + { + OnePastRephIndex = 3; + } + } + break; + } + + // Extend the reph with suffixed joiners. + if(OnePastRephIndex) + { + OnePastReph = FirstGlyphs[OnePastRephIndex - 1]->Next; + while(kbts__GlyphIsValid(Storage, OnePastReph) && + KBTS__IN_SET(OnePastReph->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_ZWJ) + (KBTS_INDIC_SYLLABIC_CLASS_ZWNJ)))) + { + OnePastReph = OnePastReph->Next; + } + } + } + + kbts__feature *Pref = Config->Pref; + kbts_glyph *BaseGlyph = OnePastLastSyllableGlyph; + kbts_glyph *LastConsonant = 0; + kbts__syllabic_position LastConsonantPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + if(Config->DottedCircle.Id && (BrokenState & 1)) + { + BaseGlyph = kbts__InsertGlyphBefore(Storage, OnePastReph, &Config->DottedCircle); + if(!BaseGlyph) + { + goto OutOfMemory; + } + + BaseGlyph->UserIdOrCodepointIndex = OnePastReph->UserIdOrCodepointIndex; + } + else + { + // Going backwards, tag blwf and pstf consonants until we get to the base. + kbts_glyph Scratch[3]; + Scratch[0] = Config->Virama; + Scratch[2] = Config->Virama; + + kbts__feature *Locl = Config->Locl; + kbts__feature *Vatu = Config->Vatu; + + // pstf forms come last, then blwf. + kbts__feature *SectionFeature = Config->Pstf; + kbts__syllabic_position SectionPosition = KBTS__SYLLABIC_POSITION_POSTBASE_CONSONANT; + // If we see no consonant/matra, then surely we want to attach to the base. + kbts__syllabic_position SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + kbts_indic_syllabic_class LastClass = KBTS_INDIC_SYLLABIC_CLASS_COUNT; + + for(Glyph = OnePastLastSyllableGlyph->Prev; + ; + Glyph = Glyph->Prev) + { + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + + switch(Class) + { + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT: + case KBTS_INDIC_SYLLABIC_CLASS_RA: + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_WITH_STACKER: + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL: + // Apply locl first. + Scratch[1] = kbts__Substitute1(Scratchpad, Config, Storage, LookupList, Locl, KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ, Glyph); + + // Microsoft says to "move backwards until a consonant is found that does not have a below-base + // or post-base form". + // As with everything else the spec says, it is wrong. There are cases in which the only consonant + // in a syllable has a below-base or post-base form. In those cases, we still want them to be the + // syllable base. + // So, as we sweep backward, set the base index on consonants unconditionally. + // @Robustness: Do we want to update Base only if we do not match Pref/Vatu? + BaseGlyph = Glyph; + + if(kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Pref, 0, Scratch, 2) || + kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Pref, 0, Scratch + 1, 2) || + kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Vatu, 0, Scratch, 2) || + kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Vatu, 0, Scratch + 1, 2)) + { + SyllabicPosition = KBTS__SYLLABIC_POSITION_POSTBASE_CONSONANT; + } + else + { + for(;;) + { + if(kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, SectionFeature, 0, Scratch, 2) || + kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, SectionFeature, 0, Scratch + 1, 2)) + { + SyllabicPosition = SectionPosition; + break; + } + else if(SectionPosition == KBTS__SYLLABIC_POSITION_POSTBASE_CONSONANT) + { + SectionFeature = Config->Blwf; + SectionPosition = KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT; + // Retry with Blwf. + } + else + { + goto DoneScanningForBase; + } + } + } + + if(!LastConsonant) + { + LastConsonant = Glyph; + LastConsonantPosition = SyllabicPosition; + } + + Glyph->SyllabicPosition = SyllabicPosition; + break; + + case KBTS_INDIC_SYLLABIC_CLASS_VOWEL: + case KBTS_INDIC_SYLLABIC_CLASS_PLACEHOLDER: + case KBTS_INDIC_SYLLABIC_CLASS_DOTTED_CIRCLE: + BaseGlyph = Glyph; + goto DoneScanningForBase; + break; + + case KBTS_INDIC_SYLLABIC_CLASS_HALANT: + if(LastClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ) + { + // Explicit half form. + // Since half forms are always before the base, we can safely stop here. + goto DoneScanningForBase; + } + case KBTS_INDIC_SYLLABIC_CLASS_NUKTA: + case KBTS_INDIC_SYLLABIC_CLASS_ZWJ: + case KBTS_INDIC_SYLLABIC_CLASS_ZWNJ: + // @Incomplete: Register Shifter + Glyph->SyllabicPosition = SyllabicPosition; + break; + } + + LastClass = Class; + if(Glyph == OnePastReph) + { + break; + } + } + DoneScanningForBase:; + } + + // Fix reph position now. + if(OnePastReph != FirstGlyph) + { + kbts__syllabic_position RephPosition = KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH; + kbts_glyph_flags Flags = RephFlags; + kbts_un RephGlyphCount = OnePastRephIndex; + if(BaseGlyph == OnePastLastSyllableGlyph) + { + RephPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + Flags = 0; + + BaseGlyph = OnePastReph = FirstGlyph; + } + + KBTS__FOR(GlyphIndex, 0, RephGlyphCount) + { + kbts_glyph *RephGlyph = FirstGlyphs[GlyphIndex]; + RephGlyph->SyllabicPosition = RephPosition; + RephGlyph->Flags |= Flags; + } + } + + if(BaseGlyph != OnePastLastSyllableGlyph) + { + BaseGlyph->SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + + if(!LastConsonant) + { + LastConsonant = BaseGlyph; + // LastConsonantPosition is already set to SYLLABLE_BASE. + } + } + + { // Reorder marks. + // @Cleanup @Speed: Supposedly, NORMALIZE already does this... + kbts_glyph *ReorderGlyph = OnePastLastSyllableGlyph->Prev; + while(ReorderGlyph != OneBeforeSyllableGlyph) + { + if(ReorderGlyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_NUKTA) + { + kbts_glyph *Prev = ReorderGlyph->Prev; + + while((Prev != OneBeforeSyllableGlyph) && + KBTS__IN_SET(Prev->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_HALANT) + (KBTS_INDIC_SYLLABIC_CLASS_VEDIC_SIGN)))) + { + kbts_glyph *NextPrev = Prev->Prev; + + KBTS__DLLIST_SWAP(Prev, Prev->Next); + + Prev = NextPrev; + } + + ReorderGlyph = Prev; + } + else + { + ReorderGlyph = ReorderGlyph->Prev; + } + } + } + + { // @Temporary @Cleanup + // Left matras should be ordered backwards. + // We want to bake this ordering into our sort, so we increase our syllabic position bits + // and sub-order matras with the low nibble. (There should only be 4 matras tops, anyway.) + kbts_un LeftMatraCount = 0; + for(Glyph = OneBeforeSyllableGlyph->Next; + Glyph != OnePastLastSyllableGlyph; + Glyph = Glyph->Next) + { + Glyph->SyllabicPosition <<= 4; + + if(Glyph->SyllabicPosition == (KBTS__SYLLABIC_POSITION_PREBASE_MATRA << 4)) + { + Glyph->SyllabicPosition += (15 - LeftMatraCount++) & 0xF; + } + } + } + + { // Attach stuff to the right of consonants/matras. + // Pre-base consonants, the base consonant, and matras all have right attachments, + // while post-base consonants have left attachments. + // Since matras always come after all consonants, we try to separate the buffer into three parts: + // a pre-base+base part (right attachments), a post-base consonant part (left attachments), and + // a post-consonant part (right attachments again). + // This part handles right attachments. Left attachments were handled in the base syllable search. + kbts__attach_state States[2] = { + { + KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH << 4, + KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH << 4, + KBTS_INDIC_SYLLABIC_CLASS_COUNT, + OnePastReph, + BaseGlyph, + OnePastReph, + }, + { + (kbts_u8)(LastConsonantPosition << 4), + (kbts_u8)(LastConsonantPosition << 4), + KBTS_INDIC_SYLLABIC_CLASS_COUNT, + LastConsonant ? LastConsonant->Next : OnePastLastSyllableGlyph, + OnePastLastSyllableGlyph, + LastConsonant ? LastConsonant->Next : OnePastLastSyllableGlyph, + }, + }; + for(;;) + { + int Done = 1; + + KBTS__FOR(StateIndex, 0, KBTS__ARRAY_LENGTH(States)) + { + kbts__attach_state *Attach = &States[StateIndex]; + + if(Attach->At != Attach->OnePastLast) + { + Glyph = Attach->At; + + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + switch(Class) + { + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT: + case KBTS_INDIC_SYLLABIC_CLASS_RA: + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_WITH_STACKER: + case KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL: + // This only happens in the pre-base state. + Glyph->SyllabicPosition = (KBTS__SYLLABIC_POSITION_PREBASE_CONSONANT << 4); + Attach->CurrentPosition = (KBTS__SYLLABIC_POSITION_PREBASE_CONSONANT << 4); + break; + + case KBTS_INDIC_SYLLABIC_CLASS_MATRA_POST: + // This specific category (which is composed of a single character) may come after + // a syllable modifier in a sequence like Consonant-SyllableModifier-MatraPost. + // In this very particular case (!), the syllable modifier is attached _to the matra_, + // and not to the consonant. + if(Attach->LastClass == KBTS_INDIC_SYLLABIC_CLASS_SYLLABLE_MODIFIER) + { + Glyph->Prev->SyllabicPosition = Glyph->SyllabicPosition; + } + case KBTS_INDIC_SYLLABIC_CLASS_MATRA: + Attach->CurrentPosition = Glyph->SyllabicPosition; + if((Attach->CurrentPosition >> 4) != KBTS__SYLLABIC_POSITION_PREBASE_MATRA) + { + Attach->LastPositionThatWasNotPreBaseMatra = Attach->CurrentPosition; + } + break; + + case KBTS_INDIC_SYLLABIC_CLASS_HALANT: + if((Attach->CurrentPosition >> 4) == KBTS__SYLLABIC_POSITION_PREBASE_MATRA) + { + // Uniscribe does not reorder halants with pre-base matras. Not sure why. + Glyph->SyllabicPosition = Attach->LastPositionThatWasNotPreBaseMatra; + break; + } + case KBTS_INDIC_SYLLABIC_CLASS_NUKTA: + case KBTS_INDIC_SYLLABIC_CLASS_ZWJ: + case KBTS_INDIC_SYLLABIC_CLASS_ZWNJ: + // @Incomplete: Register Shifter + Glyph->SyllabicPosition = Attach->CurrentPosition; + break; + } + + Attach->LastClass = Class; + Attach->At = Glyph->Next; + Done = 0; + } + } + + if(Done) + { + break; + } + } + } + + { // Do the sort! + // NOTE: It is important that we sort _now_, because some characters will be reordered across the base from + // where they started, which can change which features will apply to them. + KBTS__DLLIST_SORT(OneBeforeSyllableGlyph->Next, OnePastLastSyllableGlyph, SyllabicPosition); + +#ifdef KBTS_SANITY_CHECK + { + kbts_glyph *Glyph0 = OneBeforeSyllableGlyph->Next; + if(Glyph0 != OnePastLastSyllableGlyph) + { + for(kbts_glyph *Glyph1 = Glyph0->Next; + kbts__GlyphIsValid(C, Glyph1); + Glyph1 = Glyph1->Next) + { + if(Glyph1 != OnePastLastSyllableGlyph) + { + KBTS_ASSERT(Glyph0->SyllabicPosition <= Glyph1->SyllabicPosition); + } + else + { + break; + } + } + } + } + #endif + } + + // @Temporary @Cleanup + // Revert our syllabic position shift for now. + for(Glyph = OneBeforeSyllableGlyph->Next; + Glyph != OnePastLastSyllableGlyph; + Glyph = Glyph->Next) + { + Glyph->SyllabicPosition >>= 4; + } + + // This is what Harfbuzz does: + + // - NUKT, AKHN, RKRF, VATU, CJCT are active for all characters, but they count ZWJ/ZWNJ in their sequence + // lookups. + // - Note that, by default, Harfbuzz skips ZWJ/ZWNJ in sequence lookups, and selectively disables it for CJCT. + // - Anyway, since these are active for all characters, we don't need flags for them. + + // (RPHF was already handled before sorting.) + + { // All pre-base glyphs get HALF, which is then selectively disabled in front of ZWNJs. + kbts_glyph_flags BaseFlags = 0; + if(!Config->IndicScriptProperties.BlwfPostOnly) + { + BaseFlags = KBTS_GLYPH_FLAG_BLWF; + } + + kbts_indic_syllabic_class LastClass = 0; + for(Glyph = BaseGlyph->Prev; + Glyph != OneBeforeSyllableGlyph; + Glyph = Glyph->Prev) + { + kbts_glyph_flags Flags = BaseFlags; + + if(LastClass != KBTS_INDIC_SYLLABIC_CLASS_ZWNJ) + { + Flags |= KBTS_GLYPH_FLAG_HALF; + } + + Glyph->Flags |= Flags; + LastClass = Glyph->SyllabicClass; + } + } + + // All post-base glyphs get BLWF, ABVF, PSTF. Some get PREF. + kbts_glyph Scratch[2]; Scratch[0] = Scratch[1] = KBTS__ZERO_TYPE(kbts_glyph); + kbts_glyph *LastGlyph; LastGlyph = 0; + for(Glyph = BaseGlyph->Next; + Glyph != OnePastLastSyllableGlyph; + Glyph = Glyph->Next) + { + // It is tempting to apply PREF to every glyph after the base. + // However, the PREF flag is also used to find the syllable base again in EndCluster, + // so we have to be precise with it. + Scratch[1] = *Glyph; + if(kbts__WouldSubstitute(Scratchpad, Config, Storage, LookupList, Frames, Pref, 0, Scratch, 2)) + { + LastGlyph->Flags |= KBTS_GLYPH_FLAG_PREF; + Glyph->Flags |= KBTS_GLYPH_FLAG_PREF; + } + + Glyph->Flags |= (KBTS_GLYPH_FLAG_BLWF | KBTS_GLYPH_FLAG_ABVF | KBTS_GLYPH_FLAG_PSTF); + Scratch[0] = Scratch[1]; + LastGlyph = Glyph; + } + + // The base only inherits stuff after it, up to whatever and not including what was grabbed by + // post-base consonants. + if(BaseGlyph != OnePastLastSyllableGlyph) + { + BaseGlyph->SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + + kbts_u64 Classes = (1ull << KBTS_INDIC_SYLLABIC_CLASS_HALANT) | + (1ull << KBTS_INDIC_SYLLABIC_CLASS_VEDIC_SIGN) | + (1ull << KBTS_INDIC_SYLLABIC_CLASS_NUKTA) | + (1ull << KBTS_INDIC_SYLLABIC_CLASS_ZWJ) | + (1ull << KBTS_INDIC_SYLLABIC_CLASS_ZWNJ); + + kbts_glyph *Next = BaseGlyph->Next; + while((Next != OnePastLastSyllableGlyph) && + (Next->SyllabicPosition < KBTS__SYLLABIC_POSITION_SYLLABLE_BASE) && + ((1ull << Next->SyllabicClass) & Classes)) + { + Next->SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + + Next = Next->Next; + } + } + + Result = OnePastLastSyllableGlyph; + Scratchpad->RealCluster = 1; + } + } break; + + case KBTS_SHAPER_USE: + { + int NonCluster = 0; + while(kbts__GlyphIsValid(Storage, Glyph) && + ((Glyph->UseClass == KBTS_USE_SYLLABIC_CLASS_OTHER) || + (Glyph->UseClass == KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_POST))) + { + NonCluster = 1; + + Glyph = Glyph->Next; + } + + if(!NonCluster) + { + // Parse a real cluster. + kbts_u8 State = 0; + + kbts_glyph *StartGlyph = Glyph; + while(kbts__GlyphIsValid(Storage, Glyph) && + (State < KBTS_USE_STATE_s0)) + { + State = kbts_UseTransition[Glyph->UseClass][State]; + // @Incomplete: Remove this!!! + State -= 1; + Glyph = Glyph->Next; + } + + if(State >= KBTS_USE_STATE_s0) + { + Glyph = Glyph->Prev; + } + if(kbts__GlyphIsValid(Storage, Glyph) && + (Glyph->UseClass == KBTS_USE_SYLLABIC_CLASS_ZWNJ)) + { + Glyph = Glyph->Next; + } + if(Glyph == StartGlyph) + { + Glyph = Glyph->Next; + } + + Scratchpad->RealCluster = 1; + } + + Result = Glyph; + } break; + + case KBTS_SHAPER_KHMER: + { + int NonCluster = 0; + while(kbts__GlyphIsValid(Storage, Glyph) && + ((Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_OTHER) || + (Glyph->SyllabicClass >= KBTS_KHMER_SYLLABIC_CLASS_COUNT))) + { + Glyph = Glyph->Next; + NonCluster = 1; + } + + Result = Glyph; + + if(!NonCluster) + { + kbts_u8 State = 0; + kbts_glyph *FirstGlyph = Glyph; + kbts_glyph *OneBeforeSyllableGlyph = Glyph->Prev; + + while(kbts__GlyphIsValid(Storage, Glyph) && + (State < KBTS_KHMER_SYLLABIC_STATE_COUNT)) + { + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + + State = kbts_KhmerSyllabicTransition[Class][State]; + // @Incomplete: Remove this! + State -= 1; + Glyph = Glyph->Next; + } + + if(State >= KBTS_KHMER_SYLLABIC_STATE_COUNT) + { + Glyph = Glyph->Prev; + } + if(Glyph == FirstGlyph) + { + Glyph = Glyph->Next; + } + + kbts_glyph *OnePastLastSyllableGlyph = Glyph; + + if(Config->DottedCircle.Id && + !KBTS__IN_SET64(FirstGlyph->SyllabicClass, KBTS__SET64((KBTS_INDIC_SYLLABIC_CLASS_CONSONANT) + (KBTS_INDIC_SYLLABIC_CLASS_RA) + (KBTS_INDIC_SYLLABIC_CLASS_VOWEL) + (KBTS_INDIC_SYLLABIC_CLASS_DOTTED_CIRCLE) + (KBTS_INDIC_SYLLABIC_CLASS_PLACEHOLDER)))) + { + // Broken cluster. + // Insert a dotted circle. + kbts_glyph *NewFirstGlyph = kbts__InsertGlyphBefore(Storage, FirstGlyph, &Config->DottedCircle); + if(!NewFirstGlyph) + { + goto OutOfMemory; + } + + NewFirstGlyph->UserIdOrCodepointIndex = FirstGlyph->UserIdOrCodepointIndex; + FirstGlyph = NewFirstGlyph; + } + + // In Khmer, the first glyph is always the base. + + kbts_glyph *PreBaseGlyphs[3]; + int SawHalantRa = 0; + kbts_un PreBaseGlyphCount = 0; + kbts_un Classes = 0; + + kbts_u32 AddFlags = KBTS_GLYPH_FLAG_ABVF | KBTS_GLYPH_FLAG_BLWF | KBTS_GLYPH_FLAG_PSTF; + + kbts_glyph *LastGlyph = OnePastLastSyllableGlyph; + for(Glyph = OnePastLastSyllableGlyph->Prev; + Glyph != OneBeforeSyllableGlyph; + Glyph = Glyph->Prev) + { + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + + if(Glyph == FirstGlyph) + { + AddFlags = 0; + } + + Glyph->Flags |= AddFlags; + + Classes = ((Classes << 8) | Class) & 0xFFFF; + + if(Class == KBTS_INDIC_SYLLABIC_CLASS_VOWEL_PRE) + { + PreBaseGlyphs[PreBaseGlyphCount++] = Glyph; + } + else if(!SawHalantRa && (Classes == (KBTS_INDIC_SYLLABIC_CLASS_HALANT | (KBTS_INDIC_SYLLABIC_CLASS_RA << 8)))) + { + Glyph->Flags |= KBTS_GLYPH_FLAG_PREF; + LastGlyph->Flags |= KBTS_GLYPH_FLAG_PREF; + + PreBaseGlyphs[PreBaseGlyphCount++] = Glyph; + PreBaseGlyphs[PreBaseGlyphCount++] = LastGlyph; + + // All of the glyphs written so far need to be flagged with cfar. + // @Speed: Detect the Halant-Ra sequence in the FSM loop. + for(kbts_glyph *PostRaGlyph = LastGlyph->Next; + PostRaGlyph != OnePastLastSyllableGlyph; + PostRaGlyph = PostRaGlyph->Next) + { + PostRaGlyph->Flags |= KBTS_GLYPH_FLAG_CFAR; + } + + SawHalantRa = 1; + } + + LastGlyph = Glyph; + } + + while(PreBaseGlyphCount) + { + kbts_glyph *PreBaseGlyph = PreBaseGlyphs[--PreBaseGlyphCount]; + KBTS__DLLIST_REMOVE(PreBaseGlyph); + PreBaseGlyph->Prev = OneBeforeSyllableGlyph; + PreBaseGlyph->Next = OneBeforeSyllableGlyph->Next; + PreBaseGlyph->Prev->Next = PreBaseGlyph->Next->Prev = PreBaseGlyph; + } + + Result = OnePastLastSyllableGlyph; + } + } break; + + case KBTS_SHAPER_MYANMAR: + { + int NonCluster = 0; + while(kbts__GlyphIsValid(Storage, Glyph) && + ((Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_OTHER) || + (Glyph->SyllabicClass >= KBTS_MYANMAR_SYLLABIC_CLASS_COUNT))) + { + NonCluster = 1; + } + + if(!NonCluster) + { + kbts_u8 State = 0; + kbts_glyph *FirstGlyph = Glyph; + while(kbts__GlyphIsValid(Storage, Glyph) && + (State < KBTS_MYANMAR_SYLLABIC_STATE_COUNT)) + { + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + + State = kbts_MyanmarSyllabicTransition[Class][State]; + // @Incomplete: Remove this! + State -= 1; + + Glyph = Glyph->Next; + } + + if(State >= KBTS_MYANMAR_SYLLABIC_STATE_COUNT) + { + Glyph = Glyph->Prev; + } + if(Glyph == FirstGlyph) + { + Glyph = Glyph->Next; + } + + Scratchpad->RealCluster = 1; + } + + Result = Glyph; + } break; + } + + if(0) + { + OutOfMemory:; + Scratchpad->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + } + + kbts__EndLifetime(&Lifetime); + return Result; +} + +static void kbts__EndCluster(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage) +{ + switch(Config->Shaper) + { + case KBTS_SHAPER_INDIC: + if(kbts__GlyphIsValid(Storage, Storage->GlyphSentinel.Next)) + { + // Final syllable reordering. + // We are just copying Harfbuzz here, because I've read all the documentation I can and, frankly, I have no idea. + kbts__feature *Pref = Config->Pref; + + kbts_u32 ViramaId = Config->Virama.Id; + KBTS__FOR_GLYPH(Storage, Glyph) + { + // Harfbuzz tests for (ligated | multiplied) here. + // I don't really get why, because, supposedly, all viramas should be + // classified as halants regardless. + if(ViramaId && (Glyph->Id == ViramaId)) + { + Glyph->SyllabicClass = KBTS_INDIC_SYLLABIC_CLASS_HALANT; + Glyph->Flags &= ~(KBTS_GLYPH_FLAG_LIGATURE | KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION); + } + else if(Glyph->Flags & KBTS_GLYPH_FLAG_LIGATURE) + { + // We can't know the syllabic classes of ligatures for sure. + Glyph->SyllabicClass = KBTS_INDIC_SYLLABIC_CLASS_COUNT; + } + } + + // Locate the syllable base. + kbts_glyph *BaseGlyph = (kbts_glyph *)&Storage->GlyphSentinel; + { + kbts_glyph *AfterPreBase = Storage->GlyphSentinel.Next; + while(kbts__GlyphIsValid(Storage, AfterPreBase) && + (AfterPreBase->SyllabicPosition < KBTS__SYLLABIC_POSITION_SYLLABLE_BASE)) + { + AfterPreBase = AfterPreBase->Next; + } + + if(kbts__GlyphIsValid(Storage, AfterPreBase)) + { + BaseGlyph = AfterPreBase; + + if(Pref && kbts__GlyphIsValid(Storage, AfterPreBase->Next)) + { + // If we find a pre-base-reordering ra, then the base is probably right after it! + kbts_glyph *AtGlyph = AfterPreBase->Next; + while(kbts__GlyphIsValid(Storage, AtGlyph) && + !(AtGlyph->Flags & KBTS_GLYPH_FLAG_PREF)) + { + AtGlyph = AtGlyph->Next; + } + + // If we are not a consonant, then we are attached to a consonant. + // If we are a pref-able consonant, but we did not form a pref, then we should be right after the base. + // Either way, we are very close to the base. + kbts_glyph *Prefable = AtGlyph; // Read like "pref-able". :) + if(kbts__GlyphIsValid(Storage, Prefable) && + (!(Prefable->Flags & KBTS_GLYPH_FLAG_GENERATED_BY_GSUB) || + !(Prefable->Flags & KBTS_GLYPH_FLAG_LIGATURE) || + (Prefable->Flags & KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION))) + { + while(kbts__GlyphIsValid(Storage, Prefable) && + (Prefable->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT)) + { + Prefable = Prefable->Next; + } + + if(kbts__GlyphIsValid(Storage, Prefable)) + { + Prefable->SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + BaseGlyph = Prefable; + // Fall through to the Malayalam test. + } + } + } + + if(Config->Script == KBTS_SCRIPT_MALAYALAM) + { + // In Malayalam, the base is after below-base forms. + // (We actually just give all below-base forms the base pos.) + // @Speed: This would be way simpler with a null sentinel at the end of Glyphs! + kbts_glyph *AtGlyph = BaseGlyph->Next; + while(kbts__GlyphIsValid(Storage, AtGlyph)) + { + while(kbts__GlyphIsValid(Storage, AtGlyph) && + KBTS__IN_SET(AtGlyph->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_ZWJ) + (KBTS_INDIC_SYLLABIC_CLASS_ZWNJ)))) + { + AtGlyph = AtGlyph->Next; + } + + if(kbts__GlyphIsValid(Storage, AtGlyph) && + (AtGlyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT)) + { + AtGlyph = AtGlyph->Next; + } + else + { + break; + } + + while(kbts__GlyphIsValid(Storage, AtGlyph) && + KBTS__IN_SET(AtGlyph->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_ZWJ) + (KBTS_INDIC_SYLLABIC_CLASS_ZWNJ)))) + { + AtGlyph = AtGlyph->Next; + } + + if(kbts__GlyphIsValid(Storage, AtGlyph)) + { + if(kbts__SyllabicClassIsConsonant(AtGlyph->SyllabicClass) && + (AtGlyph->SyllabicPosition == KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT)) + { + AtGlyph->SyllabicPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + BaseGlyph = AtGlyph; + // Do not break; keep matching below-base forms. + } + } + } + } + } + + if(kbts__GlyphIsValid(Storage, BaseGlyph) && + kbts__GlyphIsValid(Storage, BaseGlyph->Prev) && + (BaseGlyph->SyllabicPosition > KBTS__SYLLABIC_POSITION_SYLLABLE_BASE)) + { + BaseGlyph = BaseGlyph->Prev; + } + + if(!kbts__GlyphIsValid(Storage, BaseGlyph) && + (BaseGlyph->Prev->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ)) + { + BaseGlyph = BaseGlyph->Prev; + } + + if(kbts__GlyphIsValid(Storage, BaseGlyph)) + { + while(kbts__GlyphIsValid(Storage, BaseGlyph->Prev) && + KBTS__IN_SET(BaseGlyph->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_NUKTA) + (KBTS_INDIC_SYLLABIC_CLASS_HALANT)))) + { + BaseGlyph = BaseGlyph->Prev; + } + } + } + + // Reorder matras. + if(kbts__GlyphIsValid(Storage, BaseGlyph->Prev) && + (Storage->GlyphSentinel.Prev != Storage->GlyphSentinel.Next) /* GlyphCount > 1 */) + { + kbts_glyph *FirstGlyph = Storage->GlyphSentinel.Next; + kbts_glyph *To = BaseGlyph->Prev; + if(!kbts__GlyphIsValid(Storage, BaseGlyph)) + { + To = To->Prev; + } + + if((Config->Script != KBTS_SCRIPT_MALAYALAM) && (Config->Script != KBTS_SCRIPT_TAMIL)) + { + kbts_glyph *LastGlyph = To->Next; + + for(;;) + { + while((To != FirstGlyph) && + !KBTS__IN_SET(To->SyllabicClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_MATRA) + (KBTS_INDIC_SYLLABIC_CLASS_MATRA_POST) + (KBTS_INDIC_SYLLABIC_CLASS_HALANT)))) + { + LastGlyph = To; + To = To->Prev; + } + + if((To->SyllabicClass != KBTS_INDIC_SYLLABIC_CLASS_HALANT) || + (To->SyllabicPosition == KBTS__SYLLABIC_POSITION_PREBASE_MATRA)) + { + // We have nothing to move. + To = FirstGlyph; + + break; + } + else if((To != FirstGlyph) && + kbts__GlyphIsValid(Storage, LastGlyph) && + (LastGlyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ)) + { + // Zwj+Halant cancels matra movement when the Halant is not attached to the matra. + To = To->Prev; + } + else + { + break; + } + } + } + + if((To != FirstGlyph) && + (To->SyllabicPosition != KBTS__SYLLABIC_POSITION_PREBASE_MATRA)) + { + for(kbts_glyph *Matra = To->Prev; + kbts__GlyphIsValid(Storage, Matra); + ) + { + kbts_glyph *MatraPrev = Matra->Prev; + + if(Matra->SyllabicPosition == KBTS__SYLLABIC_POSITION_PREBASE_MATRA) + { + KBTS__DLLIST_REMOVE(Matra); + KBTS__DLLIST_INSERT_AFTER(Matra, To); + + To = Matra->Prev; + } + + Matra = MatraPrev; + } + } + } + + // Reorder reph. + // We should only reorder reph when it is a single Repha glyph, and not a Ra sequence. + kbts_glyph *First = Storage->GlyphSentinel.Next; + kbts_glyph *Second = First->Next; + if((First->SyllabicPosition == KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH) && + kbts__GlyphIsValid(Storage, Second) && + (Second->SyllabicPosition != KBTS__SYLLABIC_POSITION_RA_TO_BECOME_REPH)) + { + kbts__reph_position RephPosition = Config->IndicScriptProperties.RephPosition; + kbts_glyph *To = 0; + + for(kbts_glyph *Glyph = First; + Glyph != BaseGlyph; + ) + { + kbts_glyph *Next = Glyph->Next; + + if(Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT) + { + To = Glyph; + + if(Next != BaseGlyph) + { + kbts_u8 NextClass = Next->SyllabicClass; + + if((NextClass == KBTS_INDIC_SYLLABIC_CLASS_ZWJ) || + (NextClass == KBTS_INDIC_SYLLABIC_CLASS_ZWNJ)) + { + To = Next; + } + } + + break; + } + + Glyph = Next; + } + + if(!To) + { + // @Cleanup: We can merge these loops. + if(RephPosition == KBTS__REPH_POSITION_AFTER_SUBJOINED) + { + for(kbts_glyph *Glyph = BaseGlyph; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Next) + { + kbts_u8 SyllabicPosition = Glyph->SyllabicPosition; + + if(KBTS__IN_SET(SyllabicPosition, KBTS__SET32((KBTS__SYLLABIC_POSITION_POSTBASE_CONSONANT) + (KBTS__SYLLABIC_POSITION_AFTER_POST) + (KBTS__SYLLABIC_POSITION_SMVD)))) + { + To = Glyph->Prev; + + break; + } + } + } + else if(RephPosition == KBTS__REPH_POSITION_AFTER_MAIN) + { + for(kbts_glyph *Glyph = BaseGlyph; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Next) + { + if(Glyph->SyllabicPosition > KBTS__SYLLABIC_POSITION_AFTER_MAIN) + { + To = Glyph->Prev; + + break; + } + } + } + } + + if(!To) + { + // As a fallback, move reph to the end of the syllable. + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Prev; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Prev) + { + if(Glyph->SyllabicPosition != KBTS__SYLLABIC_POSITION_SMVD) + { + To = Glyph; + + break; + } + } + + // Matras will still come after reph. + kbts_glyph *Glyph = To; + if(Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT) + { + for(kbts_glyph *Matra = BaseGlyph->Next; + Matra != To; + Matra = Matra->Next) + { + kbts_u8 Class = Matra->SyllabicClass; + + if(KBTS__IN_SET(Class, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_MATRA) + (KBTS_INDIC_SYLLABIC_CLASS_MATRA_POST) + (KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL)))) + { + To = To->Prev; + } + } + } + } + + if(To) + { + // Do the reorder! + KBTS__DLLIST_REMOVE(First); + KBTS__DLLIST_INSERT_AFTER(First, To); + } + } + + // Reorder pre-base-reordering consonants. + if(Pref) + { + First = Storage->GlyphSentinel.Next; + kbts_glyph *PrefGlyph = 0; + + for(kbts_glyph *Glyph = BaseGlyph->Next; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Next) + { + if(Glyph->Flags & KBTS_GLYPH_FLAG_PREF) + { + PrefGlyph = Glyph; + + break; + } + } + + if(PrefGlyph) + { + // Harfbuzz says the ideal is to check that this glyph was generated by the pref feature specifically, + // but then just uses a generic flag like this. + // The ideal solution would not be very difficult to implement! + if(PrefGlyph->Flags & KBTS_GLYPH_FLAG_GENERATED_BY_GSUB) + { + kbts_glyph *To = First; + + kbts_glyph *Last = BaseGlyph; + for(kbts_glyph *Glyph = BaseGlyph->Prev; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Prev) + { + kbts_u8 Class = Glyph->SyllabicClass; + + if(KBTS__IN_SET(Class, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_MATRA) + (KBTS_INDIC_SYLLABIC_CLASS_MATRA_POST) + (KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_MEDIAL) + (KBTS_INDIC_SYLLABIC_CLASS_HALANT)))) + { + To = Last; + + break; + } + + Last = Glyph; + } + + if(To != First) + { + kbts_glyph *Prev = To->Prev; + kbts_u8 CurrentClass = To->SyllabicClass; + + if((Prev->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT) && + KBTS__IN_SET(CurrentClass, KBTS__SET32((KBTS_INDIC_SYLLABIC_CLASS_ZWJ) + (KBTS_INDIC_SYLLABIC_CLASS_ZWNJ)))) + { + To = To->Next; + } + } + + // Do the reorder! + KBTS__DLLIST_REMOVE(PrefGlyph); + KBTS__DLLIST_INSERT_BEFORE(PrefGlyph, To); + } + } + } + + { // Mark matras at the beginning of a word for init application. + // It is tempting to check for this at the same time as the reph reordering, but glyphs could have been + // reordered since then and the reordering procedure is clearly defined to happen in sequential steps. + First = Storage->GlyphSentinel.Next; // I don't think this needs to be reloaded, but you never know. + + if((First->SyllabicPosition == KBTS__SYLLABIC_POSITION_PREBASE_MATRA) && Scratchpad->ClusterAtStartOfWord) + { + First->Flags |= KBTS_GLYPH_FLAG_INIT; + } + } + } + break; + + case KBTS_SHAPER_USE: + { + kbts_u64 PostBaseSet = KBTS__SET64((KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_ABOVE) (KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_BELOW) + (KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_ABOVE) (KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_BELOW) + (KBTS_USE_SYLLABIC_CLASS_CONS_FINAL_MOD_POST) (KBTS_USE_SYLLABIC_CLASS_CONS_MED_ABOVE) + (KBTS_USE_SYLLABIC_CLASS_CONS_MED_BELOW) (KBTS_USE_SYLLABIC_CLASS_CONS_MED_POST) + (KBTS_USE_SYLLABIC_CLASS_CONS_MED_PRE) (KBTS_USE_SYLLABIC_CLASS_VOWEL_ABOVE) + (KBTS_USE_SYLLABIC_CLASS_VOWEL_BELOW) (KBTS_USE_SYLLABIC_CLASS_VOWEL_POST) + (KBTS_USE_SYLLABIC_CLASS_VOWEL_PRE) (KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_ABOVE) + (KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_BELOW) (KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_POST) + (KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_PRE)); + kbts_u64 HalantSet = KBTS__SET64((KBTS_USE_SYLLABIC_CLASS_HALANT) + (KBTS_USE_SYLLABIC_CLASS_HALANT_OR_VOWEL_MODIFIER) + (KBTS_USE_SYLLABIC_CLASS_INVISIBLE_STACKER)); + + // In the reorderings below, we check for halants because that's what Harfbuzz does. + // Nowhere does Microsoft mention that halants should block reorderings! + kbts_glyph *Repha = Storage->GlyphSentinel.Next; + if((Repha->UseClass == KBTS_USE_SYLLABIC_CLASS_REPHA) || + (Repha->Flags & KBTS_GLYPH_FLAG_RPHF)) + { + kbts_glyph *To = Repha->Next; + for(; + kbts__GlyphIsValid(Storage, To); + To = To->Next) + { + // Microsoft says that rephas are reordered "after a following full base", which is needlessly vague. + // Harfbuzz reorders them in front of the first post-base glyph. + if(KBTS__IN_SET64(To->UseClass, PostBaseSet) || + (!(To->Flags & KBTS_GLYPH_FLAG_LIGATURE) && + KBTS__IN_SET64(To->UseClass, HalantSet))) + { + break; + } + } + + KBTS__DLLIST_REMOVE(Repha); + KBTS__DLLIST_INSERT_BEFORE(Repha, To); + } + + { + // Microsoft says that pre-base vowels and vowel modifiers should be reordered "before the base glyph + // and, if present, before a pre-base glyph reordered via the 'pref' feature". + // In practice, we tag 'pref'-generated glyphs with the VOWEL_PRE class so that they get reordered here. + // Note that the final reordered glyphs end up backwards from their original order. + kbts_glyph *PreBaseVowels[16]; // @Robustness: How many vowels can there realistically be in a single cluster? + kbts_un PreBaseVowelCount = 0; + kbts_u64 SawBase = 0; + for(kbts_glyph *Glyph = Storage->GlyphSentinel.Prev; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Prev) + { + SawBase |= KBTS__IN_SET64(Glyph->UseClass, KBTS__SET64((KBTS_USE_SYLLABIC_CLASS_BASE) + (KBTS_USE_SYLLABIC_CLASS_BASE_OTHER) + (KBTS_USE_SYLLABIC_CLASS_BASE_NUM))); + + kbts_u32 Flags = Glyph->Flags; + // Only accept the first glyphs produced by multiple substitutions. + if(((Flags & KBTS_GLYPH_FLAG_FIRST_IN_MULTIPLE_SUBSTITUTION) || + !(Flags & KBTS_GLYPH_FLAG_MULTIPLE_SUBSTITUTION)) && + (KBTS__IN_SET64(Glyph->UseClass, KBTS__SET64((KBTS_USE_SYLLABIC_CLASS_VOWEL_PRE) + (KBTS_USE_SYLLABIC_CLASS_VOWEL_MOD_PRE))) || + (Flags & KBTS_GLYPH_FLAG_PREF))) + { + if(PreBaseVowelCount < KBTS__ARRAY_LENGTH(PreBaseVowels)) + { + PreBaseVowels[PreBaseVowelCount++] = Glyph; + } + } + else if(!(Glyph->Flags & KBTS_GLYPH_FLAG_LIGATURE) && + KBTS__IN_SET64(Glyph->UseClass, HalantSet)) + { + // Reordering stops at halants, apparently. + // We want to write the vowels in the reverse order they appear in the glyph sequence. + // Since we are iterating backwards, they already _are_ backwards in the PreBaseVowels array, + // so there's no need to do anything. + kbts_glyph *InsertAfter = Glyph; + KBTS__FOR(PreBaseVowelIndex, 0, PreBaseVowelCount) + { + kbts_glyph *PreBaseVowel = PreBaseVowels[PreBaseVowelIndex]; + + KBTS__DLLIST_REMOVE(PreBaseVowel); + KBTS__DLLIST_INSERT_AFTER(PreBaseVowel, InsertAfter); + InsertAfter = PreBaseVowel; + } + PreBaseVowelCount = 0; + + // Valid bases only show up before halants. + SawBase = 0; + } + } + + kbts_glyph *DottedCircleInsertBefore = Storage->GlyphSentinel.Next; + + { // Flush the rest of the vowels. + kbts_glyph *InsertAfter = (kbts_glyph *)&Storage->GlyphSentinel; + KBTS__FOR(PreBaseVowelIndex, 0, PreBaseVowelCount) + { + kbts_glyph *PreBaseVowel = PreBaseVowels[PreBaseVowelIndex]; + + KBTS__DLLIST_REMOVE(PreBaseVowel); + KBTS__DLLIST_INSERT_AFTER(PreBaseVowel, InsertAfter); + + InsertAfter = PreBaseVowel; + } + } + + if(Scratchpad->RealCluster && !SawBase && Config->DottedCircle.Id) + { + kbts_glyph *DottedCircle = kbts__InsertGlyphBefore(Storage, DottedCircleInsertBefore, &Config->DottedCircle); + if(!DottedCircle) + { + goto OutOfMemory; + } + + DottedCircle->UserIdOrCodepointIndex = DottedCircleInsertBefore->UserIdOrCodepointIndex; + } + } + } break; + + case KBTS_SHAPER_MYANMAR: + if(Scratchpad->RealCluster) + { + kbts_glyph *BaseGlyph = (kbts_glyph *)&Storage->GlyphSentinel; + kbts_glyph *First = BaseGlyph->Next; + kbts_glyph *Second = First->Next; + kbts_glyph *Third = Second->Next; + kbts_glyph *OnePastReph = First; + + kbts_un MinimumGlyphCount = 0; + + if(kbts__GlyphIsValid(Storage, First)) + { + MinimumGlyphCount += 1; + + if(kbts__GlyphIsValid(Storage, Second)) + { + MinimumGlyphCount += 1; + + if(kbts__GlyphIsValid(Storage, Third)) + { + MinimumGlyphCount += 1; + } + } + } + + if((MinimumGlyphCount == 3) && + (First->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_RA) && + (Second->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_ASAT) && + (Third->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_HALANT)) + { + First->SyllabicPosition = KBTS__SYLLABIC_POSITION_AFTER_MAIN; + Second->SyllabicPosition = KBTS__SYLLABIC_POSITION_AFTER_MAIN; + Third->SyllabicPosition = KBTS__SYLLABIC_POSITION_AFTER_MAIN; + + OnePastReph = Third->Next; + BaseGlyph = First; + } + + kbts_u64 BaseSet = KBTS__SET64((KBTS_INDIC_SYLLABIC_CLASS_CONSONANT) + (KBTS_INDIC_SYLLABIC_CLASS_CONSONANT_WITH_STACKER) + (KBTS_INDIC_SYLLABIC_CLASS_RA) + (KBTS_INDIC_SYLLABIC_CLASS_VOWEL) + (KBTS_INDIC_SYLLABIC_CLASS_PLACEHOLDER) + (KBTS_INDIC_SYLLABIC_CLASS_DOTTED_CIRCLE)); + + // Scan for a non-reph base glyph. + for(kbts_glyph *Glyph = OnePastReph; + kbts__GlyphIsValid(Storage, Glyph); + Glyph = Glyph->Next) + { + kbts_indic_syllabic_class Class = Glyph->SyllabicClass; + + if(!kbts__GlyphIsValid(Storage, BaseGlyph) && + KBTS__IN_SET64(Class, BaseSet)) + { + BaseGlyph = Glyph; + + break; + } + } + + // Otherwise, reph can be the base. + // @Cleanup: I'm pretty sure this is @Duplication with the reph check above. + if(!kbts__GlyphIsValid(Storage, BaseGlyph) && + (OnePastReph != First)) + { + BaseGlyph = First; + } + + if(kbts__GlyphIsValid(Storage, BaseGlyph)) + { + kbts__syllabic_position LastPosition = KBTS__SYLLABIC_POSITION_SYLLABLE_BASE; + kbts__syllabic_position SectionPosition = KBTS__SYLLABIC_POSITION_AFTER_MAIN; + kbts_glyph *LastPreBaseMatra = (kbts_glyph *)&Storage->GlyphSentinel; + for(kbts_glyph *Glyph = BaseGlyph->Next; + kbts__GlyphIsValid(Storage, Glyph); + ) + { + kbts_glyph *Next = Glyph->Next; // Make sure we preserve the link when reversing. + kbts__syllabic_position Position = SectionPosition; + + switch(Glyph->SyllabicClass) + { + case KBTS_INDIC_SYLLABIC_CLASS_MEDIAL_RA: + Position = KBTS__SYLLABIC_POSITION_PREBASE_CONSONANT; + break; + + case KBTS_INDIC_SYLLABIC_CLASS_VOWEL_PRE: + { + Position = KBTS__SYLLABIC_POSITION_PREBASE_MATRA; + + // According to Unicode 15.0: + // For combining characters placed to the left of a base character, the combining characters start from the base + // character and are arranged leftward. + // Since these guys will get reordered into being pre-base, we need to flip them. + if(kbts__GlyphIsValid(Storage, LastPreBaseMatra)) + { + kbts__DllistReverseSublist(LastPreBaseMatra, Glyph->Next); + } + else + { + // When we reverse, this will become the "last" pre-base matra again, so we only need to set it once. + LastPreBaseMatra = Glyph; + } + } break; + + case KBTS_INDIC_SYLLABIC_CLASS_VARIATION_SELECTOR: + Position = LastPosition; + break; + + case KBTS_INDIC_SYLLABIC_CLASS_VOWEL_BELOW: + if(Position == KBTS__SYLLABIC_POSITION_AFTER_MAIN) + { + Position = KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT; + } + else if(Position == KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT) + { + Position = SectionPosition; + } + break; + + case KBTS_INDIC_SYLLABIC_CLASS_VEDIC_SIGN: + if(Position == KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT) + { + Position = KBTS__SYLLABIC_POSITION_BEFORE_SUBJOINED; + } + break; + } + + if((SectionPosition == KBTS__SYLLABIC_POSITION_BELOWBASE_CONSONANT) && (Glyph->SyllabicClass == KBTS_INDIC_SYLLABIC_CLASS_VEDIC_SIGN)) + { + SectionPosition = KBTS__SYLLABIC_POSITION_AFTER_SUBJOINED; + Position = SectionPosition; + } + + Glyph->SyllabicPosition = Position; + LastPosition = Position; + Glyph = Next; + } + } + + if(MinimumGlyphCount > 1) + { + KBTS__DLLIST_SORT(Storage->GlyphSentinel.Next, (kbts_glyph *)&Storage->GlyphSentinel, SyllabicPosition); + + #ifdef KBTS_SANITY_CHECK + { + kbts_glyph *Left = C->GlyphSentinel.Next; + kbts_glyph *Right = Left->Next; + while(kbts__GlyphIsValid(C, Right)) + { + kbts_glyph *Next = Right->Next; + + KBTS_ASSERT(Left->SyllabicPosition <= Right->SyllabicPosition); + + Left = Right; + Right = Next; + } + } + #endif + } + } break; + } + + if(0) + { + OutOfMemory:; + Scratchpad->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + } +} + +static void *kbts__PointerPush(char **Pointer, kbts_un Size, kbts_un Align) +{ + char *At = *Pointer; + char *Aligned = KBTS__ALIGN_POINTER(char, At, Align); + *Pointer = Aligned + Size; + + void *Result = Aligned; + return Result; +} +#define kbts__PointerPushType(Pointer, Type) (Type *)kbts__PointerPush((Pointer), sizeof(Type), KBTS_ALIGNOF(Type)) +#define kbts__PointerPushArray(Pointer, Type, Count) (Type *)kbts__PointerPush((Pointer), sizeof(Type) * (Count), KBTS_ALIGNOF(Type)) + +static kbts_shape_config *kbts__PlaceShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, void *Memory, kbts_un *Size) +{ + kbts_shape_config *Result = 0; + kbts_shape_config DummyConfig; + char *MemoryAt = (char *)Memory; + + if(Font) + { + Result = kbts__PointerPushType(&MemoryAt, kbts_shape_config); + if(!Memory) + { + Result = &DummyConfig; + } + + KBTS_MEMSET(Result, 0, sizeof(*Result)); + + Result->Font = Font; + Result->Script = Script; + Result->Language = Language; + + kbts__gsub_gpos *ShapingTables[2] = { + kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GSUB, kbts__gsub_gpos), + kbts__BlobTableDataType(Font->Blob, KBTS_BLOB_TABLE_ID_GPOS, kbts__gsub_gpos), + }; + + kbts__gsub_gpos *Gsub = ShapingTables[0]; + + // Find the appropriate language system in GSUB/GPOS. + kbts__script_properties *ScriptProperties = &kbts__ScriptProperties[Script]; + int FoundScriptIsIndic3 = 0; + + KBTS__FOR(ShapingTableIndex, 0, KBTS_SHAPING_TABLE_COUNT) + { + kbts__gsub_gpos *ShapingTable = ShapingTables[ShapingTableIndex]; + if(ShapingTable) + { + kbts__script_list *ScriptList = KBTS__POINTER_OFFSET(kbts__script_list, ShapingTable, ShapingTable->ScriptListOffset); + + kbts__langsys *ChosenLangsys = 0; + kbts_u32 DesiredTag = ScriptProperties->Tag; + + KBTS__FOR(ScriptIndex, 0, ScriptList->Count) + { + kbts__script_pointer ThisScript = kbts__GetScript(ScriptList, ScriptIndex); + kbts_u32 Tag = ThisScript.Tag; + + // The OpenType spec does not define or even mention "Indic3" scripts at all. + // Nevertheless, Harfbuzz at least checks for '3' at the end of script tags, and, if one exists, they choose USE. + int Indic3 = (ThisScript.Tag >> 24) == '3'; + kbts_u32 MatchMask = Indic3 ? 0xFFFFFF : 0xFFFFFFFF; + int PerfectMatch = !((Tag ^ DesiredTag) & MatchMask); + if(!ScriptIndex || PerfectMatch || (Tag == KBTS_FOURCC('D', 'F', 'L', 'T'))) + { + kbts__langsys *Langsys = kbts__GetDefaultLangsys(ThisScript.Script); + KBTS__FOR(LangsysIndex, 0, ThisScript.Script->Count) + { + kbts__langsys_pointer LangsysPointer = kbts__GetLangsys(ThisScript.Script, LangsysIndex); + + if(LangsysPointer.Tag == Language) + { + Langsys = LangsysPointer.Langsys; + break; + } + } + + // It is tempting to try to look for another script if the one we want has no langsys. + // However, it is possible for a script to purposefully have no langsys at all. In that case, + // the shaper should not apply any GSUB features. + // In that case, the shaper should not apply any GSUB features. + // So, store the result _regardless_ of whether Langsys is null or not. + ChosenLangsys = Langsys; + if(ShapingTableIndex == KBTS_SHAPING_TABLE_GSUB) + { + // Apparently, it is allowed to have script-specific GSUB tables, and a huge DFLT GPOS table. + FoundScriptIsIndic3 = Indic3; + } + // And then get out if we found the appropriate script, even if the langsys is null! + if(PerfectMatch) + { + break; + } + } + } + + Result->Langsys[ShapingTableIndex] = ChosenLangsys; + } + } + + Result->IndicScriptProperties = kbts__IndicScriptProperties(Script); + Result->Shaper = FoundScriptIsIndic3 ? KBTS_SHAPER_USE : ScriptProperties->Shaper; + Result->OpList = *kbts__ShaperOpLists[Result->Shaper]; + + Result->Features = KBTS__ZERO_TYPE(kbts__feature_set); + KBTS__FOR(StageIndex, 0, Result->OpList.FeatureStageCount) + { + kbts__feature_stage *Stage = &Result->OpList.FeatureStages[StageIndex]; + + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(Result->Features.Flags)) + { + Result->Features.Flags[WordIndex] |= Stage->Features.Flags[WordIndex]; + } + } + + kbts__feature *Rclt = 0; + kbts__feature_set SyllableFeatureSet = {{KBTS__FEATURE_FLAG0(rphf) | KBTS__FEATURE_FLAG0(blwf) | KBTS__FEATURE_FLAG0(half) | KBTS__FEATURE_FLAG0(pstf) | KBTS__FEATURE_FLAG0(pref), + 0, KBTS__FEATURE_FLAG2(rclt) | KBTS__FEATURE_FLAG2(locl), KBTS__FEATURE_FLAG3(vatu)}}; + kbts__iterate_features IterateFeatures = kbts__IterateFeatures(Result, KBTS_SHAPING_TABLE_GSUB, SyllableFeatureSet); + while(kbts__NextFeature(&IterateFeatures)) + { + switch(IterateFeatures.CurrentFeatureTag) + { + case KBTS_FEATURE_TAG_blwf: Result->Blwf = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_pref: Result->Pref = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_pstf: Result->Pstf = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_locl: Result->Locl = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_rphf: Result->Rphf = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_half: Result->Half = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_vatu: Result->Vatu = IterateFeatures.Feature; break; + case KBTS_FEATURE_TAG_rclt: Rclt = IterateFeatures.Feature; break; + } + } + + if((Result->Shaper == KBTS_SHAPER_ARABIC) && !Rclt) + { + Result->OpList = kbts__OpList_ArabicNoRclt; + } + + if(Result->IndicScriptProperties.ViramaCodepoint) + { + kbts__shape_scratchpad DummyScratchpad = KBTS__ZERO; + kbts_glyph_storage DummyStorage = KBTS__ZERO; + KBTS__DLLIST_SENTINEL_INIT(&DummyStorage.GlyphSentinel); + KBTS__DLLIST_SENTINEL_INIT(&DummyStorage.FreeGlyphSentinel); + + // Bake the locl-ized virama. + kbts_glyph Virama = kbts_CodepointToGlyph(Font, (int)Result->IndicScriptProperties.ViramaCodepoint, 0, 0); + Result->Virama = kbts__Substitute1(&DummyScratchpad, Result, &DummyStorage, kbts__GetLookupList(Gsub), Result->Locl, KBTS__SKIP_FLAG_ZWNJ | KBTS__SKIP_FLAG_ZWJ, &Virama); + } + + if((Result->Script == KBTS_SCRIPT_THAI) || (Result->Script == KBTS_SCRIPT_LAO)) + { + kbts_u32 NikhahitCodepoint = (Result->Script == KBTS_SCRIPT_THAI) ? 0xE4D : 0xECD; + kbts_u32 SaraAaCodepoint = (Result->Script == KBTS_SCRIPT_THAI) ? 0xE32 : 0xEB2; + Result->Nikhahit = kbts_CodepointToGlyph(Font, (int)NikhahitCodepoint, 0, 0); + Result->SaraAa = kbts_CodepointToGlyph(Font, (int)SaraAaCodepoint, 0, 0); + } + + Result->DottedCircle = kbts_CodepointToGlyph(Font, 0x25CC, 0, 0); + Result->Whitespace = kbts_CodepointToGlyph(Font, ' ', 0, 0); + + if(ShapingTables[KBTS_SHAPING_TABLE_GSUB] || ShapingTables[KBTS_SHAPING_TABLE_GPOS]) + { // Initialize the per-feature lookup lists. + kbts__baked_feature_stage *BakedStages = kbts__PointerPushArray(&MemoryAt, kbts__baked_feature_stage, Result->OpList.FeatureStageCount); + + kbts_un FeatureStageIndex = 0; + KBTS__FOR(OpIndex, 0, Result->OpList.OpCount) + { + kbts__op_kind Op = Result->OpList.Ops[OpIndex]; + int UserFeaturesAllowed = KBTS__IN_SET(Op, KBTS__SET32((KBTS__OP_KIND_GSUB_FEATURES_WITH_USER) + (KBTS__OP_KIND_GPOS_FEATURES))); + + if(KBTS__IN_SET(Op, KBTS__SET32((KBTS__OP_KIND_GSUB_FEATURES) + (KBTS__OP_KIND_GSUB_FEATURES_WITH_USER) + (KBTS__OP_KIND_GPOS_FEATURES)))) + { + kbts__feature_stage *FeatureStage = &Result->OpList.FeatureStages[FeatureStageIndex]; + kbts_shaping_table ShapingTable = (kbts_shaping_table)((Op == KBTS__OP_KIND_GPOS_FEATURES) ? KBTS_SHAPING_TABLE_GPOS : KBTS_SHAPING_TABLE_GSUB); + kbts__gsub_gpos *GsubGpos = ShapingTables[ShapingTable]; + kbts__langsys *Langsys = Result->Langsys[ShapingTable]; + kbts_un BakedFeatureCount = 0; + kbts_un BakedFeatureLookupIndexCount = 0; + + kbts__baked_feature_stage *BakedStage = &BakedStages[FeatureStageIndex]; + + if(GsubGpos && Langsys) + { + kbts__feature_list *FeatureList = KBTS__POINTER_OFFSET(kbts__feature_list, GsubGpos, GsubGpos->FeatureListOffset); + kbts_u16 *FeatureIndices = KBTS__POINTER_AFTER(kbts_u16, Langsys); + kbts__baked_feature *BakedFeatures; + + // @Speed: Maybe we don't care about fragmentation and we just allocate Langsys->FeatureIndexCount in advance? + KBTS__FOR(FeatureIndexIndex, 0, Langsys->FeatureIndexCount) + { + kbts_un FeatureIndex = FeatureIndices[FeatureIndexIndex]; + kbts__feature_pointer Feature = kbts__GetFeature(FeatureList, FeatureIndex); + + kbts_u32 FeatureId = kbts__FeatureTagToId(Feature.Tag); + + if(Feature.Feature->LookupIndexCount && + ((UserFeaturesAllowed && + !kbts__ContainsFeature(&Result->Features, FeatureId)) || + kbts__ContainsFeature(&FeatureStage->Features, FeatureId))) + { + BakedFeatureCount += 1; + } + } + + kbts_un BakedFeatureCapacity = KBTS__MIN(BakedFeatureCount, KBTS_MAX_SIMULTANEOUS_FEATURES); + + BakedFeatures = kbts__PointerPushArray(&MemoryAt, kbts__baked_feature, BakedFeatureCapacity); + + BakedFeatureCount = 0; + + KBTS__FOR(FeatureIndexIndex, 0, Langsys->FeatureIndexCount) + { + kbts_un FeatureIndex = FeatureIndices[FeatureIndexIndex]; + kbts__feature_pointer Feature = kbts__GetFeature(FeatureList, FeatureIndex); + + kbts_u32 FeatureId = kbts__FeatureTagToId(Feature.Tag); + // We add all features indiscriminately for ops that might incorporate user features. + if(Feature.Feature->LookupIndexCount && + // We add "all" features to user feature stages, except for features that are a default part of the shaper. + // If a user asks for a default feature explicitly, it is unclear whether it should be applied now or in its + // default stage. + // Leaving the feature in its default stage seems like the better thing to do, because, supposedly, these features + // will have been designed to apply at a specific point in the pipeline, and moving them makes little sense. + ((UserFeaturesAllowed && + !kbts__ContainsFeature(&Result->Features, FeatureId)) || + kbts__ContainsFeature(&FeatureStage->Features, FeatureId))) + { + kbts__baked_feature BakedFeature = KBTS__ZERO; + BakedFeature.FeatureTag = Feature.Tag; + BakedFeature.FeatureId = FeatureId; + // CAREFUL: We use SkipFlags as a temporary index until the end of the stage. + BakedFeature.SkipFlags = kbts__SkipFlags(BakedFeature.FeatureId, Result->Shaper); + BakedFeature.Count = Feature.Feature->LookupIndexCount; + // These point directly into the file. + BakedFeature.Indices = KBTS__POINTER_AFTER(kbts_u16, Feature.Feature); + + // @Incomplete + //if(FeatureVariations) + //{ + // KBTS__FOR(VariationIndex, 0, FeatureVariations->RecordCount) + // { + // kbts__feature_variation_pointer Variation = kbts__GetFeatureVariation(FeatureVariations, VariationIndex); + // KBTS__FOR(ConditionIndex, 0, Variation.ConditionSet->Count) + // { + // kbts__condition_1 *Condition = kbts__GetCondition(Variation.ConditionSet, ConditionIndex); + // KBTS_ASSERT(0); + // } + // } + //} + + // For Myanmar, we could try and tag glyphs depending on their Indic properties in BeginCluster, just like we do for + // Indic scripts. + // However, Harfbuzz does _not_ do this, so it seems like a bunch of work that would, at best, make us diverge from + // Harfbuzz more often. + if((Result->Shaper != KBTS_SHAPER_MYANMAR) && (FeatureId >= 1) && (FeatureId <= 32)) + { + // These must properly map KBTS__FEATURE_ID to kbts_glyph_flags! + BakedFeature.GlyphFilter = (1 << (FeatureId - 1)) & KBTS__GLYPH_FEATURE_MASK; + } + + if(Memory) + { + BakedFeatures[BakedFeatureCount] = BakedFeature; + } + + BakedFeatureCount += 1; + BakedFeatureLookupIndexCount += BakedFeature.Count; + + if(BakedFeatureCount >= BakedFeatureCapacity) + { + break; + } + } + } + + kbts_u16 *OrderedFeatureIndices = kbts__PointerPushArray(&MemoryAt, kbts_u16, BakedFeatureLookupIndexCount); + kbts_u16 *BakedFeatureLookupIndicesRead = kbts__PointerPushArray(&MemoryAt, kbts_u16, BakedFeatureCount); + + if(Memory) + { + kbts_un OrderedFeatureIndicesWritten = 0; + + KBTS__FOR(BakedFeatureIndex, 0, BakedFeatureCount) + { + BakedFeatureLookupIndicesRead[BakedFeatureIndex] = 0; + } + + KBTS__FOR(OrderedLookupIndex, 0, BakedFeatureLookupIndexCount) + { + kbts_u16 LowestLookupIndex = 0xFFFF; + kbts_un BestBakedFeatureIndex = 0; + + KBTS__FOR(BakedFeatureIndex, 0, BakedFeatureCount) + { + kbts__baked_feature *BakedFeature = &BakedFeatures[BakedFeatureIndex]; + kbts_un LookupIndicesRead = BakedFeatureLookupIndicesRead[BakedFeatureIndex]; + + if(LookupIndicesRead < BakedFeature->Count) + { + kbts_u16 NextIndex = BakedFeature->Indices[LookupIndicesRead]; + + if(NextIndex < LowestLookupIndex) + { + LowestLookupIndex = NextIndex; + BestBakedFeatureIndex = BakedFeatureIndex; + } + } + } + + BakedFeatureLookupIndicesRead[BestBakedFeatureIndex] += 1; + OrderedFeatureIndices[OrderedFeatureIndicesWritten++] = (kbts_u16)BestBakedFeatureIndex; + } + + KBTS_ASSERT(OrderedFeatureIndicesWritten == BakedFeatureLookupIndexCount); + + BakedStage->FeatureCount = (kbts_u16)BakedFeatureCount; + BakedStage->FeatureIndexCount = (kbts_u16)BakedFeatureLookupIndexCount; + BakedStage->Features = BakedFeatures; + BakedStage->FeatureIndices = OrderedFeatureIndices; + } + } + + KBTS_ASSERT(FeatureStageIndex < Result->OpList.FeatureStageCount); + FeatureStageIndex += 1; + } + } + + Result->FeatureStages = BakedStages; + } + } + + if(!Memory) + { + *Size = (kbts_un)(MemoryAt - (char *)Memory) + KBTS_ALIGNOF(kbts_shape_config); + Result = 0; + } + + return Result; +} + +KBTS_EXPORT int kbts_SizeOfShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language) +{ + kbts_un Size; + kbts__PlaceShapeConfig(Font, Script, Language, 0, &Size); + + return (int)Size; +} + +KBTS_EXPORT kbts_shape_config *kbts_PlaceShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, void *Memory) +{ + kbts_un Size; + kbts_shape_config *Result = kbts__PlaceShapeConfig(Font, Script, Language, Memory, &Size); + return Result; +} + +KBTS_EXPORT kbts_shape_config *kbts_CreateShapeConfig(kbts_font *Font, kbts_script Script, kbts_language Language, kbts_allocator_function *Allocator, void *AllocatorData) +{ + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + kbts_un Size; + kbts__PlaceShapeConfig(Font, Script, Language, 0, &Size); + kbts_shape_config *Result = kbts__PlaceShapeConfig(Font, Script, Language, kbts__AllocatorAllocate(Allocator, AllocatorData, Size), &Size); + if(Result) + { + Result->Allocator = Allocator; + Result->AllocatorData = AllocatorData; + } + + return Result; +} + +KBTS_EXPORT void kbts_DestroyShapeConfig(kbts_shape_config *Config) +{ + if(Config->Allocator) + { + kbts__AllocatorFree(Config->Allocator, Config->AllocatorData, Config); + } +} + +static int kbts__ReadOp(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts__op_kind End) +{ + KBTS_INSTRUMENT_FUNCTION_BEGIN; + int Result = 0; + + if(Config) + { + kbts__op_list *OpList = &Config->OpList; + + if(Scratchpad->Ip < OpList->OpCount) + { + kbts__op_kind Kind = OpList->Ops[Scratchpad->Ip++]; + + if((Kind == KBTS__OP_KIND_GSUB_FEATURES_WITH_USER) || + (Kind == KBTS__OP_KIND_GSUB_FEATURES) || + (Kind == KBTS__OP_KIND_GPOS_FEATURES)) + { + kbts__feature_stage *FeatureStage = &OpList->FeatureStages[Scratchpad->FeatureStagesRead++]; + Scratchpad->OpFeatures = &FeatureStage->Features; + + // We only have one GPOS_FEATURES op per op list, so it's fine to add user features like this. + if((Kind == KBTS__OP_KIND_GSUB_FEATURES_WITH_USER) || + (Kind == KBTS__OP_KIND_GPOS_FEATURES)) + { + if(Kind == KBTS__OP_KIND_GSUB_FEATURES_WITH_USER) + { + Kind = KBTS__OP_KIND_GSUB_FEATURES; + } + + KBTS__FOR(WordIndex, 0, KBTS__ARRAY_LENGTH(Scratchpad->ScratchFeatures.Flags)) + { + Scratchpad->ScratchFeatures.Flags[WordIndex] = Scratchpad->UserFeatures.Flags[WordIndex] | FeatureStage->Features.Flags[WordIndex]; + } + + Scratchpad->OpFeatures = &Scratchpad->ScratchFeatures; + } + } + + Scratchpad->OpKind = Kind; + Result = (Kind != End); + } + } + + KBTS_INSTRUMENT_FUNCTION_END; + return Result; +} + +KBTS_EXPORT int kbts_SizeOfShapeContext(void) +{ + int Result = sizeof(kbts_shape_context); + return Result; +} + +KBTS_EXPORT kbts_shape_context *kbts_PlaceShapeContext(kbts_allocator_function *Allocator, void *AllocatorData, void *Memory) +{ + kbts_shape_context *Result = (kbts_shape_context *)Memory; + + if(Memory) + { + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + KBTS_MEMSET(Result, 0, sizeof(*Result)); + + Result->PermanentArena.Allocator = Allocator; + Result->PermanentArena.AllocatorData = AllocatorData; + + Result->FontArena.Allocator = Allocator; + Result->FontArena.AllocatorData = AllocatorData; + + Result->ConfigArena.Allocator = Allocator; + Result->ConfigArena.AllocatorData = AllocatorData; + + Result->ScratchArena.Allocator = Allocator; + Result->ScratchArena.AllocatorData = AllocatorData; + + Result->GlyphStorage.Arena.Allocator = Allocator; + Result->GlyphStorage.Arena.AllocatorData = AllocatorData; + + KBTS__DLLIST_SENTINEL_INIT(&Result->FeatureOverrideSentinel); + KBTS__DLLIST_SENTINEL_INIT(&Result->FreeFeatureOverrideSentinel); + } + + return Result; +} + +KBTS_EXPORT kbts_shape_context *kbts_PlaceShapeContextFixedMemory(void *Memory, int Size) +{ + kbts_shape_context *Result = 0; + kbts_un SizeOfShapeContext = kbts_SizeOfShapeContext(); + kbts_un ContextAndArenaSize = sizeof(kbts_arena) + SizeOfShapeContext; + + if((Size >= 0) && ((kbts_un)Size >= ContextAndArenaSize)) + { + kbts_arena *Arena = (kbts_arena *)KBTS__POINTER_OFFSET(kbts_arena, Memory, SizeOfShapeContext); + kbts__InitializeFixedMemoryArena(Arena, KBTS__POINTER_AFTER(void, Arena), (kbts_un)Size - ContextAndArenaSize); + + Result = kbts_PlaceShapeContext(kbts__ArenaAllocator, Arena, Memory); + } + + return Result; +} + +KBTS_EXPORT kbts_shape_context *kbts_CreateShapeContext(kbts_allocator_function *Allocator, void *AllocatorData) +{ + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + kbts_shape_context *Result = kbts_PlaceShapeContext(Allocator, AllocatorData, kbts__AllocatorAllocate(Allocator, AllocatorData, (kbts_un)kbts_SizeOfShapeContext())); + Result->SelfAllocator = Allocator; + Result->SelfAllocatorData = AllocatorData; + return Result; +} + +KBTS_EXPORT void kbts_DestroyShapeContext(kbts_shape_context *Context) +{ + if(Context) + { + kbts__FreeArena(&Context->PermanentArena); + kbts__FreeArena(&Context->ConfigArena); + kbts__FreeArena(&Context->ScratchArena); + kbts__FreeArena(&Context->FontArena); + kbts__FreeArena(&Context->GlyphStorage.Arena); + + if(Context->SelfAllocator) + { + kbts__AllocatorFree(Context->SelfAllocator, Context->SelfAllocatorData, Context); + } + } +} + +KBTS_EXPORT kbts_direction kbts_ScriptDirection(kbts_script Script) +{ + kbts_direction Result = ((Script == KBTS_SCRIPT_ARABIC) || (Script == KBTS_SCRIPT_HEBREW)) ? KBTS_DIRECTION_RTL : KBTS_DIRECTION_LTR; + return Result; +} + +static kbts__context_font *kbts__ShapePushFont(kbts_shape_context *Context) +{ + kbts__context_font *Result = 0; + + if(!Context->Error && (Context->FontCount < KBTS_CONTEXT_MAX_FONT_COUNT)) + { + Result = &Context->Fonts[Context->FontCount++]; + Result->Font = 0; + Result->Lifetime = kbts__BeginLifetime(&Context->FontArena); + } + + return Result; +} + +KBTS_EXPORT kbts_font *kbts_ShapePushFont(kbts_shape_context *Context, kbts_font *Font) +{ + if(!Context->Error) + { + kbts__context_font *ContextFont = kbts__ShapePushFont(Context); + + if(ContextFont) + { + ContextFont->Font = Font; + } + } + + return Font; +} + +KBTS_EXPORT kbts_font *kbts_ShapePopFont(kbts_shape_context *Context) +{ + kbts_font *Result = 0; + + if(!Context->Error && Context->FontCount) + { + kbts__context_font *ContextFont = &Context->Fonts[Context->FontCount - 1]; + Result = ContextFont->Font; + + kbts__EndLifetime(&ContextFont->Lifetime); + + Context->FontCount -= 1; + } + + return Result; +} + +#ifndef KB_TEXT_SHAPE_NO_CRT +KBTS_EXPORT kbts_font *kbts_ShapePushFontFromFile(kbts_shape_context *Context, const char *FileName, int FontIndex) +{ + kbts__context_font *ContextFont = kbts__ShapePushFont(Context); + kbts_font *Result = 0; + + if(!Context->Error) + { + Result = kbts__PushType(&Context->FontArena, kbts_font); + if(Result) + { + *Result = kbts_FontFromFile(FileName, FontIndex, kbts__ArenaAllocator, &Context->FontArena, 0, 0); + + if(!Result->Error) + { + ContextFont->Font = Result; + } + else + { + kbts_ShapePopFont(Context); + Result = 0; + } + } + else + { + Context->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + } + } + + return Result; +} +#endif + +KBTS_EXPORT kbts_font *kbts_ShapePushFontFromMemory(kbts_shape_context *Context, void *Memory, int Length, int FontIndex) +{ + kbts_font *Result = 0; + + if(!Context->Error && (Length > 0)) + { + kbts__context_font *ContextFont = kbts__ShapePushFont(Context); + + Result = kbts__PushType(&Context->FontArena, kbts_font); + + if(Result) + { + int ScratchSize, OutputSize; + kbts_load_font_state State = KBTS__ZERO; + kbts_load_font_error Error = kbts_LoadFont(Result, &State, Memory, Length, FontIndex, &ScratchSize, &OutputSize); + if(Error == KBTS_LOAD_FONT_ERROR_NEED_TO_CREATE_BLOB) + { + void *Scratch = kbts__PushSize(&Context->ScratchArena, (kbts_un)ScratchSize, 8); + void *Output = kbts__PushSize(&Context->FontArena, (kbts_un)OutputSize, 8); + + Error = kbts_PlaceBlob(Result, &State, Scratch, Output); + } + + if(!Error) + { + ContextFont->Font = Result; + } + else + { + kbts_ShapePopFont(Context); + Result = 0; + } + } + } + + return Result; +} + +static void kbts__EnsureGlyphStorageInitialized(kbts_glyph_storage *Storage) +{ + if(!Storage->GlyphSentinel.Next) + { + KBTS__DLLIST_SENTINEL_INIT(&Storage->GlyphSentinel); + KBTS__DLLIST_SENTINEL_INIT(&Storage->FreeGlyphSentinel); + } +} + +KBTS_EXPORT int kbts_InitializeGlyphStorage(kbts_glyph_storage *Storage, kbts_allocator_function *Allocator, void *AllocatorData) +{ + int Result = 0; + + if(Storage) + { + Result = 1; + KBTS_MEMSET(Storage, 0, sizeof(*Storage)); + + Storage->Arena.Allocator = Allocator; + Storage->Arena.AllocatorData = AllocatorData; + } + + return Result; +} + +KBTS_EXPORT int kbts_InitializeGlyphStorageFixedMemory(kbts_glyph_storage *Storage, void *Memory, int MemorySize) +{ + int Result = 0; + + if(Storage && + (MemorySize > 0)) + { + KBTS_MEMSET(Storage, 0, sizeof(*Storage)); + + Result = kbts__InitializeFixedMemoryArena(&Storage->Arena, Memory, (kbts_un)MemorySize); + } + + return Result; +} + +KBTS_EXPORT kbts_glyph_iterator kbts_ActiveGlyphIterator(kbts_glyph_storage *Storage) +{ + kbts_glyph_iterator Result = KBTS__ZERO; + + if(Storage && !Storage->Error) + { + kbts__EnsureGlyphStorageInitialized(Storage); + + Result.GlyphStorage = Storage; + Result.CurrentGlyph = Storage->GlyphSentinel.Next; + } + + return Result; +} + +KBTS_EXPORT void kbts_ClearActiveGlyphs(kbts_glyph_storage *Storage) +{ + if(!Storage->Error) + { + kbts__EnsureGlyphStorageInitialized(Storage); + + kbts_glyph *First = Storage->GlyphSentinel.Next; + kbts_glyph *Last = Storage->GlyphSentinel.Prev; + + if(kbts__GlyphIsValid(Storage, First)) + { + // Free all previous glyphs. + First->Prev = Storage->FreeGlyphSentinel.Prev; + Last->Next = &Storage->FreeGlyphSentinel; + First->Prev->Next = First; + Last->Next->Prev = Last; + } + + KBTS__DLLIST_SENTINEL_INIT(&Storage->GlyphSentinel); + } +} + +KBTS_EXPORT void kbts_FreeAllGlyphs(kbts_glyph_storage *Storage) +{ + kbts__FreeArena(&Storage->Arena); + + KBTS__DLLIST_SENTINEL_INIT(&Storage->GlyphSentinel); + KBTS__DLLIST_SENTINEL_INIT(&Storage->FreeGlyphSentinel); +} + +KBTS_EXPORT kbts_glyph *kbts_PushGlyph(kbts_glyph_storage *Storage, kbts_font *Font, int Codepoint, kbts_glyph_config *Config, int UserId) +{ + kbts_glyph *Result = 0; + + if(!Storage->Error) + { + kbts__EnsureGlyphStorageInitialized(Storage); + + kbts_glyph Template = KBTS__ZERO; + if(Font) + { + Template = kbts_CodepointToGlyph(Font, Codepoint, Config, UserId); + } + else + { + Template.Codepoint = (kbts_u32)Codepoint; + Template.Config = Config; + // We do not want to use the template's UserId here, because it is just a bag of properties! + // We want to keep the original UserId. + } + + Result = kbts__InsertGlyphBefore(Storage, &Storage->GlyphSentinel, &Template); + } + + return Result; +} + +static int kbts__FeatureOverrideIsExtra(kbts_u32 Tag, int Value) +{ + int Result = 0; + kbts__feature_id Id = kbts__FeatureTagToId(Tag); + + if(!Id || (kbts_u32)(Value > 1)) + { + Result = 1; + } + + return Result; +} + +static void kbts__AddExtraFeatureOverride(kbts_glyph_config *Config, kbts__feature_override *Extra, kbts_u32 Tag, int Value) +{ + Extra->Tag = Tag; + Extra->Value = Value; + + KBTS__DLLIST_INSERT_BEFORE(&Extra->Header, &Config->FeatureOverrideSentinel); +} + +KBTS_EXPORT int kbts_SizeOfGlyphConfig(kbts_feature_override *Overrides, int OverrideCount) +{ + kbts_un StoredOverrideCount = 0; + + if(OverrideCount > 0) + { + KBTS__FOR(OverrideIndex, 0, (kbts_un)OverrideCount) + { + kbts_feature_override *Override = &Overrides[OverrideIndex]; + + if(kbts__FeatureOverrideIsExtra(Override->Tag, Override->Value)) + { + StoredOverrideCount += 1; + } + } + } + + kbts_un Result = sizeof(kbts_glyph_config) + StoredOverrideCount * sizeof(kbts__feature_override); + return (int)Result; +} + +KBTS_EXPORT kbts_glyph_config *kbts_PlaceGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, void *Memory) +{ + kbts_glyph_config *Result = (kbts_glyph_config *)Memory; + if(Memory) + { + KBTS_MEMSET(Result, 0, sizeof(*Result)); + KBTS__DLLIST_SENTINEL_INIT(&Result->FeatureOverrideSentinel); + + kbts__feature_override *ExtraOverrides = KBTS__POINTER_AFTER(kbts__feature_override, Result); + + if(OverrideCount > 0) + { + KBTS__FOR(OverrideIndex, 0, (kbts_un)OverrideCount) + { + kbts_feature_override *Override = &Overrides[OverrideIndex]; + kbts__feature_id Id = kbts__FeatureTagToId(Override->Tag); + + if(kbts__FeatureOverrideIsExtra(Override->Tag, Override->Value)) + { + kbts__feature_override *ExtraOverride = &ExtraOverrides[Result->ExtraOverrideCount++]; + + kbts__AddExtraFeatureOverride(Result, ExtraOverride, Override->Tag, Override->Value); + } + + kbts__AddFeature((Override->Value) ? &Result->EnabledFeatures : &Result->DisabledFeatures, Id); + } + + if(Result->ExtraOverrideCount) + { + kbts__feature_override *Last = &ExtraOverrides[Result->ExtraOverrideCount - 1]; + Last->Header.Next = &Result->FeatureOverrideSentinel; + Result->FeatureOverrideSentinel.Prev = &Last->Header; + } + } + } + + return Result; +} + +KBTS_EXPORT kbts_glyph_config *kbts_CreateGlyphConfig(kbts_feature_override *Overrides, int OverrideCount, kbts_allocator_function *Allocator, void *AllocatorData) +{ + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + kbts_glyph_config *Result = kbts_PlaceGlyphConfig(Overrides, OverrideCount, kbts__AllocatorAllocate(Allocator, AllocatorData, (kbts_un)kbts_SizeOfGlyphConfig(Overrides, OverrideCount))); + + if(Result) + { + Result->Allocator = Allocator; + Result->AllocatorData = AllocatorData; + } + + return Result; +} + +KBTS_EXPORT void kbts_DestroyGlyphConfig(kbts_glyph_config *Config) +{ + if(Config && Config->Allocator) + { + kbts__AllocatorFree(Config->Allocator, Config->AllocatorData, Config); + } +} + +KBTS_EXPORT kbts_shape_error kbts_ShapeError(kbts_shape_context *Context) +{ + kbts_shape_error Result = Context->Error; + return Result; +} + +KBTS_EXPORT void kbts_ShapeBegin(kbts_shape_context *Context, kbts_direction ParagraphDirection, kbts_language Language) +{ + if(!Context->Error) + { + kbts__ClearArena(&Context->ScratchArena); + kbts_ClearActiveGlyphs(&Context->GlyphStorage); + + Context->BreakStartIndex = 0; + Context->CurrentGlyphConfig = 0; + Context->NeedNewGlyphConfig = 1; + + Context->ParagraphDirection = ParagraphDirection; + Context->Language = Language; + Context->UserFeatures = KBTS__ZERO_TYPE(kbts__feature_set); + + Context->InputCodepointCount = 0; + Context->NextUserId = 0; + Context->LastGraphemeBreak = 0; + Context->LastLineBreakIndex = 0; + Context->RunFont = 0; + Context->RunScript = 0; + Context->RunDirection = 0; + Context->ExistingShapeConfigCount = 0; + + kbts_BreakBegin(&Context->BreakState, ParagraphDirection, KBTS_JAPANESE_LINE_BREAK_STYLE_NORMAL, 0); + } +} + +typedef struct kbts__input_codepoint_index +{ + kbts_u32 BlockIndex; + kbts_u32 CodepointIndex; + kbts_u32 BlockCodepointCount; +} kbts__input_codepoint_index; + +static kbts__input_codepoint_index kbts__InputCodepointIndex(kbts_un FlatCodepointIndex) +{ + kbts__input_codepoint_index Result = KBTS__ZERO; + + kbts_un MsbPosition = kbts__MsbPositionOrZero32((kbts_u32)FlatCodepointIndex); + if(MsbPosition <= KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB) + { + Result.BlockIndex = 0; + Result.CodepointIndex = (kbts_u32)FlatCodepointIndex; + Result.BlockCodepointCount = 1 << (KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB + 1); + } + else + { + Result.BlockIndex = (kbts_u32)(MsbPosition - KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB); + Result.CodepointIndex = (kbts_u32)(FlatCodepointIndex & ~(1 << MsbPosition)); + Result.BlockCodepointCount = (kbts_u32)(1 << MsbPosition); + } + + return Result; +} + +static kbts_shape_codepoint *kbts__InputCodepoint(kbts_shape_context *Context, kbts_un Index) +{ + kbts_shape_codepoint *Result = 0; + + if(!Context->Error) + { + kbts__input_codepoint_index InputIndex = kbts__InputCodepointIndex(Index); + + kbts_shape_codepoint *Block = Context->InputBlocks[InputIndex.BlockIndex]; + if(!Block) + { + Block = kbts__PushArray(&Context->PermanentArena, kbts_shape_codepoint, InputIndex.BlockCodepointCount); + if(!Block) + { + Context->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + return Result; + } + + Context->InputBlocks[InputIndex.BlockIndex] = Block; + } + + Result = &Context->InputBlocks[InputIndex.BlockIndex][InputIndex.CodepointIndex]; + } + + return Result; +} + +static kbts_shape_codepoint_iterator kbts__InputCodepointIterator(kbts_shape_context *Context, kbts_un StartCodepointIndex, kbts_un OnePastLastCodepointIndex) +{ + kbts_shape_codepoint_iterator Result = KBTS__ZERO; + + if(Context && + !Context->Error && + (OnePastLastCodepointIndex > StartCodepointIndex)) + { + kbts__input_codepoint_index StartInputIndex = kbts__InputCodepointIndex(StartCodepointIndex); + kbts__input_codepoint_index OnePastLastInputIndex = kbts__InputCodepointIndex(OnePastLastCodepointIndex); + + Result.Context = Context; + Result.BlockIndex = StartInputIndex.BlockIndex; + Result.CodepointIndex = StartInputIndex.CodepointIndex; + Result.EndBlockIndex = OnePastLastInputIndex.BlockIndex; + Result.OnePastLastCodepointIndex = OnePastLastInputIndex.CodepointIndex; + Result.CurrentBlockCodepointCount = (Result.BlockIndex == Result.EndBlockIndex) ? Result.OnePastLastCodepointIndex : StartInputIndex.BlockCodepointCount; + Result.FlatCodepointIndex = (kbts_u32)StartCodepointIndex; + } + + return Result; +} + +KBTS_EXPORT kbts_shape_codepoint_iterator kbts_ShapeCurrentCodepointsIterator(kbts_shape_context *Context) +{ + kbts_shape_codepoint_iterator Result = kbts__InputCodepointIterator(Context, 0, Context->InputCodepointCount); + + return Result; +} + +static int kbts__NextInputCodepoint(kbts_shape_codepoint_iterator *It, int *CodepointIndex) +{ + int Result = 0; + + if(It->CodepointIndex >= It->CurrentBlockCodepointCount) + { + It->BlockIndex += 1; + It->CodepointIndex = 0; + It->CurrentBlockCodepointCount = (It->BlockIndex == It->EndBlockIndex) ? It->OnePastLastCodepointIndex : (1 << (It->BlockIndex + KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB)); + } + + if(It->BlockIndex <= It->EndBlockIndex) + { + if(CodepointIndex) + { + *CodepointIndex = (int)It->FlatCodepointIndex; + } + + It->Codepoint = &It->Context->InputBlocks[It->BlockIndex][It->CodepointIndex++]; + It->FlatCodepointIndex += 1; + + Result = 1; + } + + return Result; +} + +KBTS_EXPORT int kbts_ShapeCodepointIteratorIsValid(kbts_shape_codepoint_iterator *It) +{ + int Result = It->Context && (It->BlockIndex <= It->EndBlockIndex); + return Result; +} + +KBTS_EXPORT int kbts_ShapeCodepointIteratorNext(kbts_shape_codepoint_iterator *It, kbts_shape_codepoint *Codepoint, int *CodepointIndex) +{ + int Result = kbts__NextInputCodepoint(It, CodepointIndex); + + if(Result) + { + *Codepoint = *It->Codepoint; + } + + return Result; +} + +KBTS_EXPORT int kbts_ShapeGetShapeCodepoint(kbts_shape_context *Context, int CodepointIndex, kbts_shape_codepoint *Codepoint) +{ + int Result = 0; + + if((CodepointIndex >= 0) && + ((kbts_un)CodepointIndex < Context->InputCodepointCount)) + { + kbts_shape_codepoint *Source = kbts__InputCodepoint(Context, (kbts_un)CodepointIndex); + *Codepoint = *Source; + + Result = 1; + } + + return Result; +} + +static void kbts__UpdateBreaks(kbts_shape_context *Context) +{ + if(!(Context->Flags & KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION)) + { + kbts_break Break; + while(kbts_Break(&Context->BreakState, &Break)) + { + // Strictly speaking, we do not need all of the flags, but we record them all anyway so we can expose them to the user. + kbts_un BreakPosition = (kbts_u32)Break.Position + Context->BreakStartIndex; + kbts_shape_codepoint *InputCodepoint = kbts__InputCodepoint(Context, BreakPosition); + + if(Break.Flags & KBTS_BREAK_FLAG_LINE_HARD) + { + Context->LastLineBreakIndex = (kbts_u32)BreakPosition; + } + + if(Break.Flags & KBTS_BREAK_FLAG_GRAPHEME) + { + // Try fonts, potentially break run. + kbts_font *MatchFont = 0; + + for(kbts_un FontIndex = Context->FontCount; + FontIndex; + --FontIndex) + { + kbts_font *Font = Context->Fonts[FontIndex - 1].Font; + kbts_font_coverage_test CoverageTest; + kbts_FontCoverageTestBegin(&CoverageTest, Font); + + kbts_shape_codepoint_iterator It = kbts__InputCodepointIterator(Context, Context->LastGraphemeBreakIndex, BreakPosition); + + while(kbts__NextInputCodepoint(&It, 0)) + { + kbts_shape_codepoint *GraphemeCodepoint = It.Codepoint; + + kbts_FontCoverageTestCodepoint(&CoverageTest, GraphemeCodepoint->Codepoint); + } + + kbts_FontCoverageTestEnd(&CoverageTest); + + if(!CoverageTest.Error) + { + MatchFont = Font; + + break; + } + } + + Context->LastGraphemeBreak->Font = MatchFont; + Context->LastGraphemeBreak = InputCodepoint; + Context->LastGraphemeBreakIndex = (kbts_u32)BreakPosition; + } + + InputCodepoint->BreakFlags |= Break.Flags; + if(Break.Flags & KBTS_BREAK_FLAG_SCRIPT) + { + InputCodepoint->Script = Break.Script; + } + if(Break.Flags & KBTS_BREAK_FLAG_DIRECTION) + { + InputCodepoint->Direction = Break.Direction; + } + if(Break.Flags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) + { + InputCodepoint->ParagraphDirection = Break.ParagraphDirection; + } + } + } +} + +KBTS_EXPORT void kbts_ShapeBeginManualRuns(kbts_shape_context *Context) +{ + if(!Context->Error) + { + if(Context->InputCodepointCount > 0) + { + kbts_BreakEnd(&Context->BreakState); + kbts__UpdateBreaks(Context); + } + + Context->Flags |= KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION; + } +} + +KBTS_EXPORT void kbts_ShapeNextManualRun(kbts_shape_context *Context, kbts_direction Direction, kbts_script Script) +{ + if(!Context->Error && + (Context->Flags & KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION)) + { + Context->Flags |= KBTS__CONTEXT_FLAG_START_OF_MANUAL_RUN | KBTS__CONTEXT_FLAG_USE_MANUAL_BREAK_INFO; + + Context->ManualRunDirection = Direction; + Context->ManualRunScript = Script; + } +} + +KBTS_EXPORT void kbts_ShapeEndManualRuns(kbts_shape_context *Context) +{ + if(!Context->Error && + (Context->Flags & KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION)) + { + Context->Flags &= ~KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION; + + if(Context->InputCodepointCount > 0) + { + kbts_BreakBegin(&Context->BreakState, Context->ParagraphDirection, KBTS_JAPANESE_LINE_BREAK_STYLE_NORMAL, 0); + Context->BreakStartIndex = (kbts_u32)Context->InputCodepointCount; + } + } +} + +KBTS_EXPORT void kbts_ShapeManualBreak(kbts_shape_context *Context) +{ + kbts_ShapeBeginManualRuns(Context); + Context->Flags |= KBTS__CONTEXT_FLAG_START_OF_MANUAL_RUN; + kbts_ShapeEndManualRuns(Context); +} + +KBTS_EXPORT void kbts_ShapeCodepointWithUserId(kbts_shape_context *Context, int Codepoint, int UserId) +{ + if(!Context->Error) + { + if(Context->NeedNewGlyphConfig) + { + kbts_glyph_config *Config = kbts__PushType(&Context->ScratchArena, kbts_glyph_config); + if(!Config) + { + Context->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + return; + } + + *Config = KBTS__ZERO_TYPE(kbts_glyph_config); + KBTS__DLLIST_SENTINEL_INIT(&Config->FeatureOverrideSentinel); + + kbts__feature_set Features = KBTS__ZERO; + for(kbts__feature_override_header *OverrideHeader = Context->FeatureOverrideSentinel.Prev; + OverrideHeader != &Context->FeatureOverrideSentinel; + OverrideHeader = OverrideHeader->Prev) + { + kbts__feature_override *Override = (kbts__feature_override *)OverrideHeader; + kbts__feature_id Id = kbts__FeatureTagToId(Override->Tag); + + if(!Id || !kbts__ContainsFeature(&Features, Id)) + { + if(kbts__FeatureOverrideIsExtra(Override->Tag, Override->Value)) + { + kbts__feature_override *Insert = kbts__PushType(&Context->ScratchArena, kbts__feature_override); + if(!Insert) + { + Context->Error = KBTS_SHAPE_ERROR_OUT_OF_MEMORY; + return; + } + + kbts__AddExtraFeatureOverride(Config, Insert, Override->Tag, Override->Value); + } + + kbts__AddFeature(&Features, Id); + kbts__AddFeature((Override->Value) ? &Config->EnabledFeatures : &Config->DisabledFeatures, Id); + } + } + + Context->CurrentGlyphConfig = Config; + Context->NeedNewGlyphConfig = 0; + } + + { // Add the codepoint. + kbts_un FlatCodepointIndex = Context->InputCodepointCount; + kbts_shape_codepoint InputCodepoint = KBTS__ZERO; + InputCodepoint.Codepoint = Codepoint; + InputCodepoint.UserId = UserId; + InputCodepoint.Config = Context->CurrentGlyphConfig; + + // @Robustness: There is probably a saner way of doing this. + // When we do a manual break, we may have line breaks go out-of-bounds, and we + // do not want to lose that information. + if(FlatCodepointIndex && + (FlatCodepointIndex == Context->LastLineBreakIndex)) + { + InputCodepoint.BreakFlags |= KBTS_BREAK_FLAG_LINE; + } + + if(Context->Flags & KBTS__CONTEXT_FLAG_START_OF_MANUAL_RUN) + { + InputCodepoint.BreakFlags |= KBTS_BREAK_FLAG_MANUAL; + + if(Context->Flags & KBTS__CONTEXT_FLAG_USE_MANUAL_BREAK_INFO) + { + InputCodepoint.Direction = Context->ManualRunDirection; + InputCodepoint.Script = Context->ManualRunScript; + } + + Context->Flags &= ~KBTS__CONTEXT_FLAG_START_OF_MANUAL_RUN; + } + + kbts_shape_codepoint *To = kbts__InputCodepoint(Context, FlatCodepointIndex); + if(To) + { + *To = InputCodepoint; + } + + if(!Context->LastGraphemeBreak) + { + Context->LastGraphemeBreak = To; + } + + Context->InputCodepointCount += 1; + } + + if(!(Context->Flags & KBTS__CONTEXT_FLAG_MANUAL_SEGMENTATION)) + { + // Check for breaks. + kbts_BreakAddCodepoint(&Context->BreakState, Codepoint, 1, 0); + + kbts__UpdateBreaks(Context); + } + } +} +static void kbts__ShapeCodepoint(kbts_shape_context *Context, int Codepoint, int UserIdIncrement) +{ + int UserId = Context->NextUserId; + Context->NextUserId += UserIdIncrement; + kbts_ShapeCodepointWithUserId(Context, Codepoint, UserId); +} +KBTS_EXPORT void kbts_ShapeCodepoint(kbts_shape_context *Context, int Codepoint) +{ + if(!Context->Error) + { + kbts__ShapeCodepoint(Context, Codepoint, 1); + } +} + +KBTS_EXPORT void kbts_ShapeUtf32WithUserId(kbts_shape_context *Context, int *Utf32, int Length, int BaseUserId, int UserIdIncrement) +{ + if(!Context->Error && (Length > 0)) + { + int UserId = BaseUserId; + + KBTS__FOR(Utf32Index, 0, (kbts_un)Length) + { + int Codepoint = Utf32[Utf32Index]; + kbts_ShapeCodepointWithUserId(Context, Codepoint, UserId); + + UserId += UserIdIncrement; + } + } +} +KBTS_EXPORT void kbts_ShapeUtf32(kbts_shape_context *Context, int *Utf32, int Length) +{ + if(!Context->Error && (Length > 0)) + { + KBTS__FOR(Utf32Index, 0, (kbts_un)Length) + { + int Codepoint = Utf32[Utf32Index]; + kbts_ShapeCodepoint(Context, Codepoint); + } + } +} + +KBTS_EXPORT void kbts_ShapeUtf8WithUserId(kbts_shape_context *Context, const char *Utf8, int Length, int BaseUserId, kbts_user_id_generation_mode UserIdGenerationMode) +{ + if(!Context->Error && (Length > 0)) + { + const char *At = Utf8; + const char *End = Utf8 + Length; + int UserId = BaseUserId; + + int CodepointIncrement = (UserIdGenerationMode == KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX) ? 1 : 0; + int SourceCharacterMask = (UserIdGenerationMode == KBTS_USER_ID_GENERATION_MODE_SOURCE_INDEX) ? ~0 : 0; + + while(At < End) + { + kbts_decode Decode = kbts_DecodeUtf8(At, (kbts_un)(End - At)); + + if(Decode.Valid) + { + kbts_ShapeCodepointWithUserId(Context, Decode.Codepoint, UserId); + + UserId += CodepointIncrement; + } + + At += Decode.SourceCharactersConsumed; + UserId += Decode.SourceCharactersConsumed & SourceCharacterMask; + } + } +} +KBTS_EXPORT void kbts_ShapeUtf8(kbts_shape_context *Context, const char *Utf8, int Length, kbts_user_id_generation_mode UserIdGenerationMode) +{ + if(!Context->Error && (Length > 0)) + { + const char *At = Utf8; + const char *End = Utf8 + Length; + while(At < End) + { + kbts_decode Decode = kbts_DecodeUtf8(At, (kbts_un)(End - At)); + + if(Decode.Valid) + { + int Increment = 0; + if(UserIdGenerationMode == KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX) + { + Increment = 1; + } + else if(UserIdGenerationMode == KBTS_USER_ID_GENERATION_MODE_SOURCE_INDEX) + { + Increment = Decode.SourceCharactersConsumed; + } + + kbts__ShapeCodepoint(Context, Decode.Codepoint, Increment); + } + + At += Decode.SourceCharactersConsumed; + } + } +} + +KBTS_EXPORT void kbts_ShapePushFeature(kbts_shape_context *Context, kbts_u32 Tag, int Value) +{ + if(!Context->Error) + { + kbts__feature_override *Override; + kbts__feature_override_header *Header = Context->FreeFeatureOverrideSentinel.Prev; + if(Header != &Context->FreeFeatureOverrideSentinel) + { + Override = (kbts__feature_override *)Header; + } + else + { + Override = kbts__PushType(&Context->PermanentArena, kbts__feature_override); + } + + KBTS__DLLIST_INSERT_BEFORE(&Override->Header, &Context->FeatureOverrideSentinel); + Override->Tag = Tag; + Override->Value = Value; + + kbts__feature_id Id = kbts__FeatureTagToId(Tag); + kbts__AddFeature(&Context->UserFeaturesEnabled, Id); + + Context->NeedNewGlyphConfig = 1; + } +} + +KBTS_EXPORT int kbts_ShapePopFeature(kbts_shape_context *Context, kbts_u32 Tag) +{ + int Result = 0; + + if(!Context->Error) + { + for(kbts__feature_override_header *Header = Context->FeatureOverrideSentinel.Prev; + Header != &Context->FeatureOverrideSentinel; + Header = Header->Prev) + { + kbts__feature_override *Override = (kbts__feature_override *)Header; + + if(Override->Tag == Tag) + { + Result = 1; + + KBTS__DLLIST_REMOVE(Header); + KBTS__DLLIST_INSERT_BEFORE(Header, &Context->FreeFeatureOverrideSentinel); + + break; + } + } + + if(Result) + { + Context->NeedNewGlyphConfig = 1; + } + } + + return Result; +} + +static void kbts__ShapeDirect(kbts__shape_scratchpad *Scratchpad, kbts_shape_config *Config, kbts_glyph_storage *Storage) +{ + KBTS_INSTRUMENT_BLOCK_BEGIN(ReadOpLoop0); + + // For simple shapers, all of the shaping happens in this single loop. + // For complex shapers, this loop is preparing the text for clustering logic, which happens below. + while(kbts__ReadOp(Scratchpad, Config, KBTS__OP_KIND_BEGIN_CLUSTER)) + { + kbts__ExecuteOp(Scratchpad, Config, Storage); + + if(Scratchpad->Error) + { + return; + } + } + + KBTS_INSTRUMENT_BLOCK_END(ReadOpLoop0); + + if(Scratchpad->OpKind == KBTS__OP_KIND_BEGIN_CLUSTER) + { + kbts_u32 BeginClusterIp = Scratchpad->Ip; + kbts_u32 BeginClusterFeatureStagesRead = Scratchpad->FeatureStagesRead; + kbts_glyph *TopLevelGlyph = Storage->GlyphSentinel.Next; + + Scratchpad->ClusterAtStartOfWord = 1; + + while(kbts__GlyphIsValid(Storage, TopLevelGlyph)) + { + int WordBreak = 0; + + Scratchpad->Ip = BeginClusterIp; + Scratchpad->FeatureStagesRead = BeginClusterFeatureStagesRead; + + { + // We need to store this in case TopLevelGlyph is reordered. + kbts_glyph *OneBeforeFirstClusterGlyph = TopLevelGlyph->Prev; + kbts_glyph *OnePastLastClusterGlyph = kbts__BeginCluster(Scratchpad, Config, Storage, TopLevelGlyph); + + if(Scratchpad->Error) + { + return; + } + + WordBreak = !(OnePastLastClusterGlyph->Prev->UnicodeFlags & KBTS_UNICODE_FLAG_PART_OF_WORD); + Scratchpad->Cluster = kbts__PushGlyphList(Storage, OneBeforeFirstClusterGlyph->Next, OnePastLastClusterGlyph->Prev); + } + + while(kbts__ReadOp(Scratchpad, Config, KBTS__OP_KIND_END_CLUSTER)) + { + kbts__ExecuteOp(Scratchpad, Config, Storage); + + if(Scratchpad->Error) + { + return; + } + } + + kbts__EndCluster(Scratchpad, Config, Storage); + + while(kbts__ReadOp(Scratchpad, Config, KBTS__OP_KIND_END_SYLLABLE)) + { + kbts__ExecuteOp(Scratchpad, Config, Storage); + + if(Scratchpad->Error) + { + return; + } + } + + // Reattach the cluster to the main list. + Storage->GlyphSentinel.Next->Prev = Scratchpad->Cluster.OneBeforeFirst; + Storage->GlyphSentinel.Prev->Next = Scratchpad->Cluster.OnePastLast; + TopLevelGlyph = Scratchpad->Cluster.OnePastLast; + + kbts__PopGlyphList(Storage, &Scratchpad->Cluster); + + Scratchpad->ClusterAtStartOfWord = WordBreak; + } + + // Post-clustering ops work across clusters. + // This is where Indic GPOS + post-passes happen. + while(kbts__ReadOp(Scratchpad, Config, 0)) + { + kbts__ExecuteOp(Scratchpad, Config, Storage); + + if(Scratchpad->Error) + { + return; + } + } + } + + KBTS_INSTRUMENT_FUNCTION_END; +} + +KBTS_EXPORT kbts_shape_error kbts_ShapeDirect(kbts_shape_config *Config, kbts_glyph_storage *Storage, kbts_direction RunDirection, kbts_allocator_function *Allocator, void *AllocatorData, kbts_glyph_iterator *Output) +{ + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + kbts_arena Arena = KBTS__ZERO; + Arena.Allocator = Allocator; + Arena.AllocatorData = AllocatorData; + + kbts__shape_scratchpad *Scratchpad = kbts__PushType(&Arena, kbts__shape_scratchpad); + KBTS_MEMSET(Scratchpad, 0, sizeof(*Scratchpad)); + Scratchpad->Arena = &Arena; + Scratchpad->RunDirection = RunDirection; + + kbts__ShapeDirect(Scratchpad, Config, Storage); + kbts_shape_error Result = Scratchpad->Error; + + if(!Result) + { + *Output = kbts_ActiveGlyphIterator(Storage); + } + else + { + *Output = KBTS__ZERO_TYPE(kbts_glyph_iterator); + } + + kbts__FreeArena(&Arena); + + return Result; +} + +KBTS_EXPORT kbts_shape_error kbts_ShapeDirectFixedMemory(kbts_shape_config *Config, kbts_glyph_storage *Storage, kbts_direction RunDirection, void *Memory, int MemorySize, kbts_glyph_iterator *Output) +{ + kbts_shape_error Result = 0; + + if(Config && Storage && !Storage->Error && Memory && (MemorySize > 0)) + { + kbts_arena Arena; + + if(kbts__InitializeFixedMemoryArena(&Arena, Memory, (kbts_un)MemorySize)) + { + Result = kbts_ShapeDirect(Config, Storage, RunDirection, kbts__ArenaAllocator, &Arena, Output); + } + } + + return Result; +} + +static void kbts__BeginParagraph(kbts_shape_context *Context) +{ + Context->RunFont = 0; + if(Context->FontCount) + { + Context->RunFont = Context->Fonts[Context->FontCount - 1].Font; + } + + Context->RunScript = 0; + Context->RunParagraphDirection = 0; + Context->RunDirection = 0; +} + +KBTS_EXPORT void kbts_ShapeEnd(kbts_shape_context *Context) +{ + if(!Context->Error) + { + // We check the break flags of the one-past-last codepoint, so reset it here. + kbts_shape_codepoint *OnePastLastCodepoint = kbts__InputCodepoint(Context, Context->InputCodepointCount); + *OnePastLastCodepoint = KBTS__ZERO_TYPE(kbts_shape_codepoint); + + kbts_BreakEnd(&Context->BreakState); + kbts__UpdateBreaks(Context); + + Context->RunCodepointIterator.Context = 0; + Context->DoneShapingRuns = 0; + + kbts__BeginParagraph(Context); + } +} + +KBTS_EXPORT int kbts_ShapeRun(kbts_shape_context *Context, kbts_run *Run) +{ + int Result = 0; + + if(!Context->Error && + !Context->DoneShapingRuns) + { + kbts_font *RunFont = Context->RunFont; + kbts_script RunScript = Context->RunScript; + kbts_direction RunParagraphDirection = Context->RunParagraphDirection; + kbts_direction RunDirection = Context->RunDirection; + kbts_language Language = Context->Language; + + Run->Flags = 0; + + kbts_ClearActiveGlyphs(&Context->GlyphStorage); + + int Initialized = 1; + + if(!Context->RunCodepointIterator.Context) + { + Context->RunCodepointIterator = kbts__InputCodepointIterator(Context, 0, Context->InputCodepointCount); + Initialized = 0; + } + + kbts_shape_codepoint_iterator *It = &Context->RunCodepointIterator; + + if(kbts_ShapeCodepointIteratorIsValid(It)) + { + int InputCodepointIndex = 0; + while(kbts__NextInputCodepoint(It, &InputCodepointIndex)) + { + kbts_shape_codepoint *InputCodepoint = It->Codepoint; + + // Resolve neutral directions. + if((InputCodepoint->BreakFlags & KBTS_BREAK_FLAG_DIRECTION) && + (InputCodepoint->Direction == KBTS_DIRECTION_DONT_KNOW)) + { + InputCodepoint->Direction = RunParagraphDirection; + } + + int First = !Result; + Result = 1; + + kbts_font *CodepointFont = InputCodepoint->Font; + kbts_script CodepointScript = InputCodepoint->Script; + kbts_direction CodepointDirection = InputCodepoint->Direction; + kbts_direction CodepointParagraphDirection = InputCodepoint->ParagraphDirection; + kbts_break_flags CodepointBreakFlags = InputCodepoint->BreakFlags; + + int NewLine = !First && (CodepointBreakFlags & (KBTS_BREAK_FLAG_LINE_HARD | KBTS_BREAK_FLAG_MANUAL)); + + if(First) + { + Run->Flags = CodepointBreakFlags; + + if(CodepointBreakFlags & KBTS_BREAK_FLAG_LINE_HARD) + { + kbts__BeginParagraph(Context); + RunFont = Context->RunFont; + RunScript = 0; + RunDirection = 0; + + // If we see a bunch of whitespace at the beginning of a paragraph, + // we want to merge with the first actual text that shows up. + Initialized = 0; + } + } + + if((CodepointFont && (CodepointFont != RunFont)) || + (CodepointScript && (CodepointScript != RunScript)) || + (CodepointDirection && (CodepointDirection != RunDirection)) || + (CodepointParagraphDirection && (CodepointParagraphDirection != RunParagraphDirection)) || + NewLine) + { + if(CodepointFont) + { + Context->RunFont = CodepointFont; + } + if(CodepointScript) + { + Context->RunScript = CodepointScript; + } + if(CodepointDirection) + { + Context->RunDirection = CodepointDirection; + } + if(CodepointParagraphDirection) + { + Context->RunParagraphDirection = CodepointParagraphDirection; + } + + if(Initialized || NewLine) + { + // Rewind the current codepoint. + // We could also try to peek the codepoint before advancing, but this seems fine. + if(!It->CodepointIndex) + { + It->BlockIndex -= 1; + It->CodepointIndex = (1 << (It->BlockIndex + KBTS__INPUT_CODEPOINT_FIRST_BLOCK_MSB)) - 1; + } + else + { + It->CodepointIndex -= 1; + } + + It->FlatCodepointIndex -= 1; + + goto FoundBreak; + } + else + { + // Initialize and keep matching. + RunFont = Context->RunFont; + RunScript = Context->RunScript; + RunDirection = Context->RunDirection; + RunParagraphDirection = Context->RunParagraphDirection; + + kbts_PushGlyph(&Context->GlyphStorage, RunFont, InputCodepoint->Codepoint, InputCodepoint->Config, InputCodepointIndex); + + Initialized = 1; + } + } + else + { + kbts_PushGlyph(&Context->GlyphStorage, RunFont, InputCodepoint->Codepoint, InputCodepoint->Config, InputCodepointIndex); + } + } + + FoundBreak:; + + if(Result) + { + kbts_shape_config *Config = 0; + KBTS__FOR(ExistingConfigIndex, 0, Context->ExistingShapeConfigCount) + { + kbts__existing_shape_config *Existing = &Context->ExistingShapeConfigs[ExistingConfigIndex]; + + if((Existing->Font == RunFont) && + (Existing->Script == RunScript)) + { + Config = Existing->Config; + + break; + } + } + + if(!Config) + { + Config = kbts_CreateShapeConfig(RunFont, RunScript, Language, kbts__ArenaAllocator, &Context->ScratchArena); + + if(Context->ExistingShapeConfigCount < KBTS__ARRAY_LENGTH(Context->ExistingShapeConfigs)) + { + kbts__existing_shape_config *NewExisting = &Context->ExistingShapeConfigs[Context->ExistingShapeConfigCount++]; + + NewExisting->Config = Config; + NewExisting->Font = RunFont; + NewExisting->Script = RunScript; + } + } + + if(!RunDirection) + { + RunDirection = KBTS_DIRECTION_LTR; + + if((Config->Shaper == KBTS_SHAPER_ARABIC) || + (Config->Shaper == KBTS_SHAPER_HEBREW)) + { + RunDirection = KBTS_DIRECTION_RTL; + } + } + + kbts__shape_scratchpad *Scratchpad = kbts__PushType(&Context->ScratchArena, kbts__shape_scratchpad); + KBTS_MEMSET(Scratchpad, 0, sizeof(*Scratchpad)); + Scratchpad->Arena = &Context->ScratchArena; + Scratchpad->RunDirection = RunDirection; + + kbts__ShapeDirect(Scratchpad, Config, &Context->GlyphStorage); + + if(Scratchpad->Error) + { + Context->Error = Scratchpad->Error; + } + } + } + else + { + kbts_shape_codepoint *OnePastLast = kbts__InputCodepoint(Context, Context->InputCodepointCount); + + if(OnePastLast->BreakFlags & KBTS_BREAK_FLAG_LINE_HARD) + { + // Signal the terminating line break with a 0-sized run. + Run->Flags = OnePastLast->BreakFlags; + + Result = 1; + } + + Context->DoneShapingRuns = 1; + } + + if(Result) + { + Run->Font = RunFont; + Run->Script = RunScript; + Run->ParagraphDirection = RunParagraphDirection; + Run->Direction = RunDirection; + Run->Glyphs = kbts_ActiveGlyphIterator(&Context->GlyphStorage); + } + } + + return Result; +} + +KBTS_EXPORT int kbts_GlyphIteratorIsValid(kbts_glyph_iterator *It) +{ + int Result = It->CurrentGlyph && kbts__GlyphIsValid(It->GlyphStorage, It->CurrentGlyph); + return Result; +} + +KBTS_EXPORT int kbts_GlyphIteratorNext(kbts_glyph_iterator *It, kbts_glyph **Glyph) +{ + int Result = 0; + kbts_glyph *CurrentGlyph = It->CurrentGlyph; + + if(kbts_GlyphIteratorIsValid(It)) + { + *Glyph = CurrentGlyph; + + Result = 1; + It->CurrentGlyph = CurrentGlyph->Next; + } + + return Result; +} + +KBTS_EXPORT int kbts_FontCount(void *Data, int Size) +{ + int Result = 0; + + if(Data && (Size >= 4)) + { + kbts_u32 Magic = *(kbts_u32 *)Data; + + if(Magic == KBTS_FOURCC('t', 't', 'c', 'f')) + { + kbts__ttc_header *Header = (kbts__ttc_header *)Data; + + if(Header->Magic == KBTS_FOURCC('t', 't', 'c', 'f')) + { + Result = (int)kbts__ByteSwap32(Header->FontCount); + } + } + else if((Magic == KBTS_FOURCC('O', 'T', 'T', 'O')) || + (Magic == KBTS__U32BE(0x10000)) || + (Magic == KBTS_FOURCC('k', 'b', 't', 's'))) + { + Result = 1; + } + } + + return Result; +} + +static kbts__cmap_subtable_pointer kbts__SelectCmapSubtable(kbts_blob_header *Header, kbts_blob_table *CmapTable, kbts__cmap_14 **Cmap14, kbts_u16 *ResultFormat) +{ + kbts__cmap_subtable_pointer Result = KBTS__ZERO; + + if(CmapTable->Length >= sizeof(kbts__cmap)) + { + char *TableEnd = KBTS__POINTER_OFFSET(char, Header, CmapTable->OffsetFromStartOfFile + CmapTable->Length); + kbts__cmap *Cmap = KBTS__POINTER_OFFSET(kbts__cmap, Header, CmapTable->OffsetFromStartOfFile); + + kbts_u16 PreferredFormat = 1; + KBTS__FOR(It, 0, Cmap->TableCount) + { + kbts__cmap_subtable_pointer Subtable = kbts__GetCmapSubtable(Cmap, It); + if((char *)(Subtable.Subtable + 1) <= TableEnd) + { + kbts_u16 Format = *Subtable.Subtable; + + // This is kind of iffy, but the statelessness is useful for selecting + // the cmap from an already-prepared blob without having to deal with + // the byteswap context. + if((Format > 0xFF) && + ((Format >> 8) <= 14)) + { + Format = kbts__ByteSwap16(Format); + *Subtable.Subtable = Format; + } + + if(Format == 14) + { + if((char *)(Subtable.Subtable + sizeof(kbts__cmap_14)) <= TableEnd) + { + if(Cmap14) + { + *Cmap14 = (kbts__cmap_14 *)Subtable.Subtable; + } + } + } + else if(!Result.Subtable) + { + Result = Subtable; + } + else if(Format < KBTS__ARRAY_LENGTH(kbts__CmapFormatPrecedence)) + { + kbts_u16 Precedence = kbts__CmapFormatPrecedence[Format]; + kbts_u16 PreferredPrecedence = kbts__CmapFormatPrecedence[PreferredFormat]; + + if((Precedence > PreferredPrecedence) || ((Precedence == PreferredPrecedence) && (Subtable.PlatformId == 3))) + { + Result = Subtable; + if(ResultFormat) + { + *ResultFormat = Format; + } + } + } + } + } + } + + return Result; +} + +KBTS_EXPORT kbts_load_font_error kbts_LoadFont(kbts_font *Font, kbts_load_font_state *State, void *FontData, int FontDataSize, int FontIndex, int *ScratchSize_, int *OutputSize_) +{ + kbts_load_font_error Result = 0; + kbts_un ScratchSize = 0; + kbts_un OutputSize = 0; + + if(FontDataSize >= 4) + { + char *FileEnd = (char *)FontData + FontDataSize; + kbts_u32 Magic = *(kbts_u32 *)FontData; + kbts_un DirectoryOffset = 0; + + if(Magic == KBTS_FOURCC('t', 't', 'c', 'f')) + { + Magic = 0; + + if(FontDataSize >= (int)sizeof(kbts__ttc_header)) + { + kbts__ttc_header *Header = (kbts__ttc_header *)FontData; + kbts_un FontCount = kbts__ByteSwap32(Header->FontCount); + + if(((kbts_u32)FontIndex < FontCount) && + ((kbts_un)FontDataSize >= (sizeof(kbts__ttc_header) + sizeof(kbts_u32) * FontCount))) + { + kbts_u32 *TableDirectoryOffsets = KBTS__POINTER_AFTER(kbts_u32, Header); + DirectoryOffset = kbts__ByteSwap32(TableDirectoryOffsets[FontIndex]); + + Magic = KBTS__U32BE(0x10000); + } + } + } + + if((Magic == KBTS_FOURCC('O', 'T', 'T', 'O')) || + (Magic == KBTS__U32BE(0x10000))) + { + Result = KBTS_LOAD_FONT_ERROR_NEED_TO_CREATE_BLOB; + + State->FontData = FontData; + State->FontDataSize = (kbts_u32)FontDataSize; + + kbts__table_directory *Directory = KBTS__POINTER_OFFSET(kbts__table_directory, FontData, DirectoryOffset); + kbts_un DirectoryTableCount = kbts__ByteSwap16(Directory->TableCount); + + kbts__table_record *Tables = KBTS__POINTER_AFTER(kbts__table_record, Directory); + + kbts_un DirectoryTableCapacity = (kbts_un)(FileEnd - (char *)Tables) / sizeof(kbts__table_record); + if(DirectoryTableCount <= DirectoryTableCapacity) + { + for(kbts_un TableIndex = 0; TableIndex < DirectoryTableCount; ++TableIndex) + { + kbts__table_record *Table = &Tables[TableIndex]; + kbts_u32 TableOffset = kbts__ByteSwap32(Table->Offset); + kbts_u32 TableLength = kbts__ByteSwap32(Table->Length); + + void *TableBase = KBTS__POINTER_OFFSET(void, FontData, TableOffset); + char *TableEnd = (char *)TableBase + TableLength; + if(((char *)TableBase >= (char *)(Tables + DirectoryTableCount)) && (TableEnd <= FileEnd)) + { + kbts_blob_table_id TableId = 0; + + switch(Table->Tag) + { + case KBTS_FOURCC('h', 'e', 'a', 'd'): TableId = KBTS_BLOB_TABLE_ID_HEAD; break; + case KBTS_FOURCC('c', 'm', 'a', 'p'): TableId = KBTS_BLOB_TABLE_ID_CMAP; break; + case KBTS_FOURCC('G', 'D', 'E', 'F'): TableId = KBTS_BLOB_TABLE_ID_GDEF; break; + case KBTS_FOURCC('G', 'S', 'U', 'B'): TableId = KBTS_BLOB_TABLE_ID_GSUB; break; + case KBTS_FOURCC('G', 'P', 'O', 'S'): TableId = KBTS_BLOB_TABLE_ID_GPOS; break; + case KBTS_FOURCC('h', 'h', 'e', 'a'): TableId = KBTS_BLOB_TABLE_ID_HHEA; break; + case KBTS_FOURCC('v', 'h', 'e', 'a'): TableId = KBTS_BLOB_TABLE_ID_VHEA; break; + case KBTS_FOURCC('h', 'm', 't', 'x'): TableId = KBTS_BLOB_TABLE_ID_HMTX; break; + case KBTS_FOURCC('v', 'm', 't', 'x'): TableId = KBTS_BLOB_TABLE_ID_VMTX; break; + case KBTS_FOURCC('m', 'a', 'x', 'p'): TableId = KBTS_BLOB_TABLE_ID_MAXP; break; + case KBTS_FOURCC('O', 'S', '/', '2'): TableId = KBTS_BLOB_TABLE_ID_OS2; break; + case KBTS_FOURCC('n', 'a', 'm', 'e'): TableId = KBTS_BLOB_TABLE_ID_NAME; break; + } + + if(TableId) + { + kbts_blob_table *ReadTable = &State->Tables[TableId]; + ReadTable->OffsetFromStartOfFile = TableOffset; + ReadTable->Length = TableLength; + } + } + } + } + + { + kbts_un TotalLookupCount = 0; + kbts_un TotalSubtableCount = 0; + + kbts_blob_table *GsubGposTables[] = {&State->Tables[KBTS_BLOB_TABLE_ID_GSUB], &State->Tables[KBTS_BLOB_TABLE_ID_GPOS]}; + KBTS__FOR(GsubGposTableIndex, 0, KBTS__ARRAY_LENGTH(GsubGposTables)) + { + kbts_blob_table *Table = GsubGposTables[GsubGposTableIndex]; + + if(Table->Length) + { + kbts__gsub_gpos *GsubGpos = KBTS__POINTER_OFFSET(kbts__gsub_gpos, FontData, Table->OffsetFromStartOfFile); + kbts_lookup_list *LookupList = KBTS__POINTER_OFFSET(kbts_lookup_list, GsubGpos, kbts__ByteSwap16(GsubGpos->LookupListOffset)); + kbts_u16 *LookupOffsets = KBTS__POINTER_AFTER(kbts_u16, LookupList); + kbts_un LookupCount = kbts__ByteSwap16(LookupList->Count); + + KBTS__FOR(LookupIndex, 0, LookupCount) + { + kbts__lookup *Lookup = KBTS__POINTER_OFFSET(kbts__lookup, LookupList, kbts__ByteSwap16(LookupOffsets[LookupIndex])); + + TotalSubtableCount += kbts__ByteSwap16(Lookup->SubtableCount); + } + + TotalLookupCount += LookupCount; + } + } + + State->LookupCount = (kbts_u32)TotalLookupCount; + State->LookupSubtableCount = (kbts_u32)TotalSubtableCount; + } + + { + kbts_un GlyphCount = 0; + + kbts_blob_table *MaxpTable = &State->Tables[KBTS_BLOB_TABLE_ID_MAXP]; + if(MaxpTable->Length) + { + kbts__maxp *Maxp = KBTS__POINTER_OFFSET(kbts__maxp, FontData, MaxpTable->OffsetFromStartOfFile); + + GlyphCount = kbts__ByteSwap16(Maxp->GlyphCount); + } + + State->GlyphCount = (kbts_u32)GlyphCount; + } + + ScratchSize = (State->Tables[KBTS_BLOB_TABLE_ID_GSUB].Length + + State->Tables[KBTS_BLOB_TABLE_ID_GPOS].Length + + State->Tables[KBTS_BLOB_TABLE_ID_GDEF].Length) * sizeof(kbts_u32) / 2; + + kbts_un GlyphLookupMatrixSizeInBytes = ((((State->LookupCount * State->GlyphCount) + 7) / 8) + 3) & ~3u; + kbts_un GlyphLookupSubtableMatrixSizeInBytes = ((((State->LookupSubtableCount * State->GlyphCount) + 7) / 8) + 3) & ~3u; + OutputSize = sizeof(kbts_blob_header) + + sizeof(kbts_blob_table) * KBTS_BLOB_TABLE_ID_COUNT + + GlyphLookupMatrixSizeInBytes + + GlyphLookupSubtableMatrixSizeInBytes + + sizeof(kbts_u32) * State->LookupCount + + sizeof(kbts_lookup_subtable_info) * State->LookupSubtableCount; + + KBTS__FOR(TableId, 0, KBTS_BLOB_TABLE_ID_COUNT) + { + OutputSize += State->Tables[TableId].Length; + } + + *ScratchSize_ = (int)ScratchSize; + *OutputSize_ = (int)OutputSize; + + State->ScratchSize = (kbts_u32)ScratchSize; + State->GlyphLookupMatrixSizeInBytes = (kbts_u32)GlyphLookupMatrixSizeInBytes; + State->GlyphLookupSubtableMatrixSizeInBytes = (kbts_u32)GlyphLookupSubtableMatrixSizeInBytes; + State->TotalSize = (kbts_u32)OutputSize; + } + else if(Magic == KBTS_FOURCC('k', 'b', 't', 's')) + { + kbts_blob_header *Header = (kbts_blob_header *)FontData; + + if(Header->Version != KBTS_BLOB_VERSION_CURRENT) + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + + // @Incomplete: Bounds check or something. + + Font->Blob = Header; + kbts__cmap_subtable_pointer PreferredSubtable = kbts__SelectCmapSubtable(Header, &Header->Tables[KBTS_BLOB_TABLE_ID_CMAP], &Font->Cmap14, 0); + Font->Cmap = PreferredSubtable.Subtable; + } + } + + return Result; +} + +KBTS_EXPORT int kbts_FontIsValid(kbts_font *Font) +{ + int Result = !Font->Error; + return Result; +} + +static void kbts__MarkMatrixCoverage(kbts_u32 *Matrix, kbts_un TableIndex, kbts_un TableCount, kbts_un GlyphCount, kbts__coverage *Coverage, int SubtableMatrix) +{ + if(Coverage) + { + if(Coverage->Format == 1) + { + kbts_u16 *GlyphIds = KBTS__POINTER_AFTER(kbts_u16, Coverage); + + KBTS__FOR(GlyphIndex, 0, Coverage->Count) + { + kbts_un GlyphId = GlyphIds[GlyphIndex]; + kbts__matrix_index MatrixIndex = SubtableMatrix ? + kbts__GlyphLookupSubtableMatrixIndex(TableIndex, TableCount, GlyphId) : + kbts__GlyphLookupMatrixIndex(TableIndex, GlyphId, GlyphCount); + + if(GlyphId < GlyphCount) + { + Matrix[MatrixIndex.WordIndex] |= 1 << MatrixIndex.BitIndex; + } + } + } + else if(Coverage->Format == 2) + { + kbts__range_record *Ranges = KBTS__POINTER_AFTER(kbts__range_record, Coverage); + + KBTS__FOR(RangeIndex, 0, Coverage->Count) + { + kbts__range_record *Range = &Ranges[RangeIndex]; + KBTS__FOR(GlyphId, Range->StartGlyphId, (kbts_un)Range->EndGlyphId + 1) + { + kbts__matrix_index MatrixIndex = SubtableMatrix ? + kbts__GlyphLookupSubtableMatrixIndex(TableIndex, TableCount, GlyphId) : + kbts__GlyphLookupMatrixIndex(TableIndex, GlyphId, GlyphCount); + + if(GlyphId < GlyphCount) + { + Matrix[MatrixIndex.WordIndex] |= 1 << MatrixIndex.BitIndex; + } + } + } + } + } +} + +static void kbts__MarkMatrixClassDef(kbts_u32 *Matrix, kbts_un SubtableIndex, kbts_un SubtableCount, kbts_un GlyphCount, kbts_u16 *ClassDefBase, kbts_u64 *ClassesIncluded, kbts_un ClassesIncludedLength) +{ + if(ClassDefBase) + { + if(*ClassDefBase == 1) + { + kbts__class_definition_1 *ClassDef = (kbts__class_definition_1 *)ClassDefBase; + kbts_u16 *GlyphClasses = KBTS__POINTER_AFTER(kbts_u16, ClassDef); + + KBTS__FOR(GlyphIndex, 0, ClassDef->GlyphCount) + { + kbts_un GlyphId = ClassDef->StartGlyphId + GlyphIndex; + kbts_un GlyphClass = GlyphClasses[GlyphIndex]; + + if((GlyphId >= (ClassesIncludedLength * 64)) || + (ClassesIncluded[GlyphClass / 64] & (1ull << (GlyphClass % 64)))) + { + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(SubtableIndex, SubtableCount, GlyphId); + Matrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + } + } + else if(*ClassDefBase == 2) + { + kbts__class_definition_2 *ClassDef = (kbts__class_definition_2 *)ClassDefBase; + kbts__class_range_record *Ranges = KBTS__POINTER_AFTER(kbts__class_range_record, ClassDef); + + KBTS__FOR(RangeIndex, 0, ClassDef->Count) + { + kbts__class_range_record *Range = &Ranges[RangeIndex]; + kbts_un RangeClass = Range->Class; + + if((RangeClass >= (ClassesIncludedLength * 64)) || + (ClassesIncluded[RangeClass / 64] & (1ull << (RangeClass % 64)))) + { + kbts_un OnePastLastGlyphId = Range->EndGlyphId + 1; + if(OnePastLastGlyphId > GlyphCount) + { + OnePastLastGlyphId = GlyphCount; + } + + KBTS__FOR(GlyphId, Range->StartGlyphId, OnePastLastGlyphId) + { + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(SubtableIndex, SubtableCount, GlyphId); + Matrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + } + } + } + } +} + +KBTS_EXPORT kbts_load_font_error kbts_PlaceBlob(kbts_font *Font, kbts_load_font_state *State, void *ScratchMemory, void *OutputMemory) +{ + kbts_load_font_error Result = 0; + + if(!Font) + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + + if(!ScratchMemory || !OutputMemory) + { + Result = KBTS_LOAD_FONT_ERROR_OUT_OF_MEMORY; + } + + if(Result == KBTS_LOAD_FONT_ERROR_NONE) + { + kbts_blob_header *Header = (kbts_blob_header *)OutputMemory; + *Header = KBTS__ZERO_TYPE(kbts_blob_header); + Header->Magic = KBTS_FOURCC('k', 'b', 't', 's'); + Header->Version = 1; + Header->LookupCount = State->LookupCount; + Header->LookupSubtableCount = State->LookupSubtableCount; + + // Stamp packed font data. + char *OutData = KBTS__POINTER_AFTER(char, Header); + KBTS__FOR(TableId, 0, KBTS_BLOB_TABLE_ID_COUNT) + { + kbts_blob_table InTable = State->Tables[TableId]; + kbts_blob_table *OutTable = &Header->Tables[TableId]; + + OutTable->OffsetFromStartOfFile = KBTS__POINTER_DIFF32(OutData, Header); + OutTable->Length = InTable.Length; + + void *InData = KBTS__POINTER_OFFSET(void, State->FontData, InTable.OffsetFromStartOfFile); + KBTS_MEMCPY(OutData, InData, InTable.Length); + + OutData += InTable.Length; + } + + // Byteswap it. + + { + kbts_blob_table *HeadTable = &Header->Tables[KBTS_BLOB_TABLE_ID_HEAD]; + + if(HeadTable->Length) + { + if(HeadTable->Length >= sizeof(kbts__head)) + { + kbts__head *Head = KBTS__POINTER_OFFSET(kbts__head, Header, HeadTable->OffsetFromStartOfFile); + + kbts__ByteSwapArray16Unchecked(&Head->Major, 2); + kbts__ByteSwapArray32Unchecked(&Head->Revision, 2); + // We do not swap the magic number. + kbts__ByteSwapArray16Unchecked(&Head->Flags, 2); + // We do not swap file times. + kbts__ByteSwapArray16Unchecked((kbts_u16 *)&Head->XMin, 9); + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + + Font->Blob = Header; + + { + kbts_blob_table *CmapTable = &Header->Tables[KBTS_BLOB_TABLE_ID_CMAP]; + + if(CmapTable->Length) + { + if(CmapTable->Length >= sizeof(kbts__cmap)) + { + int TableValid = 0; + char *TableEnd = KBTS__POINTER_OFFSET(char, Header, CmapTable->OffsetFromStartOfFile + CmapTable->Length); + kbts__cmap *Cmap = KBTS__POINTER_OFFSET(kbts__cmap, Header, CmapTable->OffsetFromStartOfFile); + Cmap->Version = kbts__ByteSwap16(Cmap->Version); + Cmap->TableCount = kbts__ByteSwap16(Cmap->TableCount); + + kbts__encoding_record *Records = KBTS__POINTER_AFTER(kbts__encoding_record, Cmap); + + if((char *)(Records + Cmap->TableCount) <= TableEnd) + { + KBTS__FOR(It, 0, Cmap->TableCount) + { + kbts__encoding_record *Record = &Records[It]; + Record->EncodingId = kbts__ByteSwap16(Record->EncodingId); + Record->PlatformId = kbts__ByteSwap16(Record->PlatformId); + Record->SubtableOffset = kbts__ByteSwap32(Record->SubtableOffset); + } + + kbts_u16 PreferredFormat = 1; + + kbts__cmap_subtable_pointer PreferredSubtable = kbts__SelectCmapSubtable(Header, CmapTable, &Font->Cmap14, &PreferredFormat); + if(PreferredSubtable.Subtable) + { + switch(*PreferredSubtable.Subtable) + { + case 0: + { + kbts__cmap_0 *Cmap0 = (kbts__cmap_0 *)PreferredSubtable.Subtable; + if((char *)(Cmap0 + 1) <= TableEnd) + { + Cmap0->Length = kbts__ByteSwap16(Cmap0->Length); + Cmap0->Language = kbts__ByteSwap16(Cmap0->Language); + TableValid = 1; + } + } + break; + + case 2: + { + kbts__cmap_2 *Cmap2 = (kbts__cmap_2 *)PreferredSubtable.Subtable; + if(kbts__ByteSwapArray16(&Cmap2->Length, 258, TableEnd)) + { + kbts_un SubHeaderCount = 0; + KBTS__FOR(It, 0, 256) + { + kbts_un SubHeaderIndex = Cmap2->SubHeaderKeys[It]; + SubHeaderCount = KBTS__MAX(SubHeaderCount, SubHeaderIndex + 1); + } + + kbts__sub_header *SubHeaders = KBTS__POINTER_AFTER(kbts__sub_header, Cmap2); + if(kbts__ByteSwapArray16(&SubHeaders->FirstCode, 4 * SubHeaderCount, TableEnd)) + { + kbts_u16 *GlyphIds = (kbts_u16 *)(SubHeaders + SubHeaderCount); + + kbts_sn GlyphIdCount = 0; + KBTS__FOR(It, 0, SubHeaderCount) + { + kbts__sub_header *SubHeader = &SubHeaders[It]; + + kbts_u16 *OnePastLastGlyphId = &SubHeader->IdRangeOffset + SubHeader->IdRangeOffset / 2 + SubHeader->EntryCount; + GlyphIdCount = KBTS__MAX(GlyphIdCount, OnePastLastGlyphId - GlyphIds); + } + + if(kbts__ByteSwapArray16(GlyphIds, (kbts_un)GlyphIdCount, TableEnd)) + { + TableValid = 1; + } + } + } + } + break; + + case 4: + { + kbts__cmap_4 *Cmap4 = (kbts__cmap_4 *)PreferredSubtable.Subtable; + if(kbts__ByteSwapArray16(&Cmap4->Length, 5, TableEnd) && + kbts__ByteSwapArray16(KBTS__POINTER_AFTER(kbts_u16, Cmap4), Cmap4->SegmentCountTimesTwo * 2 + 1, TableEnd)) + { + kbts_un SegmentCount = Cmap4->SegmentCountTimesTwo / 2; + kbts_u16 *EndCodes = KBTS__POINTER_AFTER(kbts_u16, Cmap4); + kbts_u16 *StartCodes = EndCodes + SegmentCount + 1; + kbts_s16 *IdDeltas = (kbts_s16 *)(StartCodes + SegmentCount); + kbts_u16 *IdRangeOffsets = (kbts_u16 *)(IdDeltas + SegmentCount); + kbts_u16 *GlyphIds = IdRangeOffsets + SegmentCount; + + kbts_sn GlyphIdCount = 0; + + KBTS__FOR(SegmentIndex, 0, SegmentCount) + { + kbts_u16 Offset = IdRangeOffsets[SegmentIndex]; + + if(Offset) + { + kbts_u16 *IdLookup = &IdRangeOffsets[SegmentIndex] + (EndCodes[SegmentIndex] - StartCodes[SegmentIndex] + 1) + Offset / 2; + + GlyphIdCount = KBTS__MAX(GlyphIdCount, (IdLookup - GlyphIds)); + } + } + + if(kbts__ByteSwapArray16(GlyphIds, (kbts_un)GlyphIdCount, TableEnd)) + { + TableValid = 1; + } + } + } + break; + + case 6: + { + kbts__cmap_6 *Cmap6 = (kbts__cmap_6 *)PreferredSubtable.Subtable; + if(kbts__ByteSwapArray16(&Cmap6->Length, 4, TableEnd) && + kbts__ByteSwapArray16(KBTS__POINTER_AFTER(kbts_u16, Cmap6), Cmap6->EntryCount, TableEnd)) + { + TableValid = 1; + } + } + break; + + case 12: + { + kbts__cmap_12_13 *Cmap12 = (kbts__cmap_12_13 *)PreferredSubtable.Subtable; + if(kbts__ByteSwapArray32(&Cmap12->Length, 3, TableEnd) && + kbts__ByteSwapArray32(KBTS__POINTER_AFTER(kbts_u32, Cmap12), Cmap12->GroupCount * 3, TableEnd)) + { + TableValid = 1; + } + } + break; + } + + Font->Cmap = PreferredSubtable.Subtable; + } + } + + if(!TableValid) + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + + { + kbts_blob_table *GdefTable = &Header->Tables[KBTS_BLOB_TABLE_ID_GDEF]; + + if(GdefTable->Length) + { + kbts__gdef *Gdef = KBTS__POINTER_OFFSET(kbts__gdef, Header, GdefTable->OffsetFromStartOfFile); + char *TableEnd = KBTS__POINTER_OFFSET(char, Header, GdefTable->OffsetFromStartOfFile + GdefTable->Length); + + if(kbts__ByteSwapArray16(&Gdef->Major, 6, TableEnd)) + { + if(Gdef->Minor >= 2) + { + if(GdefTable->Length >= 14) + { + Gdef->MarkGlyphSetsDefinitionOffset = kbts__ByteSwap16(Gdef->MarkGlyphSetsDefinitionOffset); + + if(Gdef->Minor == 3) + { + if(GdefTable->Length >= sizeof(kbts__gdef)) + { + // @Incomplete + Gdef->ItemVariationStoreOffset = kbts__ByteSwap32(Gdef->ItemVariationStoreOffset); + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + + { + kbts_blob_table_id HeaTableIds[2] = {KBTS_BLOB_TABLE_ID_HHEA, KBTS_BLOB_TABLE_ID_VHEA}; + KBTS__FOR(HeaTableIndex, 0, KBTS__ARRAY_LENGTH(HeaTableIds)) + { + kbts_blob_table *HeaTable = &Header->Tables[HeaTableIds[HeaTableIndex]]; + + if(HeaTable->Length) + { + kbts__hea *Hea = KBTS__POINTER_OFFSET(kbts__hea, Header, HeaTable->OffsetFromStartOfFile); + char *TableEnd = KBTS__POINTER_OFFSET(char, Header, HeaTable->OffsetFromStartOfFile + HeaTable->Length); + + if(!kbts__ByteSwapArray16((kbts_u16 *)Hea, sizeof(kbts__hea) / sizeof(kbts_u16), TableEnd)) + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + } + + { + kbts_blob_table_id MtxTableIds[2] = {KBTS_BLOB_TABLE_ID_HMTX, KBTS_BLOB_TABLE_ID_VMTX}; + + KBTS__FOR(MtxTableIndex, 0, KBTS__ARRAY_LENGTH(MtxTableIds)) + { + kbts_blob_table *MtxTable = &Header->Tables[MtxTableIds[MtxTableIndex]]; + + if(MtxTable->Length) + { + kbts_u16 *Mtx = KBTS__POINTER_OFFSET(kbts_u16, Header, MtxTable->OffsetFromStartOfFile); + kbts__ByteSwapArray16Unchecked(Mtx, MtxTable->Length / sizeof(kbts_u16)); + } + } + } + + { + kbts_blob_table *MaxpTable = &Header->Tables[KBTS_BLOB_TABLE_ID_MAXP]; + + if(MaxpTable->Length) + { + if(MaxpTable->Length >= 6) + { + kbts__maxp *Maxp = KBTS__POINTER_OFFSET(kbts__maxp, Header, MaxpTable->OffsetFromStartOfFile); + char *TableEnd = KBTS__POINTER_OFFSET(char, Header, MaxpTable->OffsetFromStartOfFile + MaxpTable->Length); + + Maxp->Major = kbts__ByteSwap16(Maxp->Major); + Maxp->Minor = kbts__ByteSwap16(Maxp->Minor); + + kbts_un U16Count = 0; + if(!Maxp->Major && (Maxp->Minor == 0x5000)) + { + U16Count = 1; + } + else if((Maxp->Major == 1) && !Maxp->Minor) + { + U16Count = 14; + } + + if(kbts__ByteSwapArray16(&Maxp->GlyphCount, U16Count, TableEnd)) + { + Header->GlyphCount = Maxp->GlyphCount; + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + + { + kbts_blob_table *Os2Table = &Header->Tables[KBTS_BLOB_TABLE_ID_OS2]; + + if(Os2Table->Length) + { + kbts__os2 *Os2 = KBTS__POINTER_OFFSET(kbts__os2, Header, Os2Table->OffsetFromStartOfFile); + kbts_un Length = Os2Table->Length; + + if(Length >= 68) + { + kbts__ByteSwapArray16Unchecked(&Os2->Version, 16); + kbts__ByteSwapArray32Unchecked(Os2->UnicodeRange, 4); + kbts__ByteSwapArray16Unchecked(&Os2->Selection, 3); + + kbts_un Version = Os2->Version; + + if(Length >= 78) + { + kbts__ByteSwapArray16Unchecked((kbts_u16 *)&Os2->TypoAscender, 5); + + if(Version >= 1) + { + if(Length >= 86) + { + kbts__ByteSwapArray32Unchecked(Os2->CodePageRange, 2); + + if(Version >= 2) + { + if(Length >= 96) + { + kbts__ByteSwapArray16Unchecked((kbts_u16 *)&Os2->Height, 5); + + if(Version >= 5) + { + if(Length >= 100) + { + kbts__ByteSwapArray16Unchecked(&Os2->LowerOpticalPointSize, 2); + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + } + } + else + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + // We should normally set Result to INVALID_FONT if there is no OS/2 table. + // However, one Harfbuzz test has a font with no OS/2 table. + } + + { + kbts_blob_table *NameTable = &Header->Tables[KBTS_BLOB_TABLE_ID_NAME]; + + if(NameTable->Length >= sizeof(kbts__name)) + { + kbts__name *Name = KBTS__POINTER_OFFSET(kbts__name, Header, NameTable->OffsetFromStartOfFile); + char *TableEnd = KBTS__POINTER_OFFSET(char, Name, NameTable->Length); + + kbts__ByteSwapArray16Unchecked(&Name->Version, 3); + + kbts__name_record *NameRecords = KBTS__POINTER_AFTER(kbts__name_record, Name); + + kbts_un U16Count = Name->Count * 6; + if(!kbts__ByteSwapArray16(&NameRecords->PlatformId, U16Count, TableEnd)) + { + Result = KBTS_LOAD_FONT_ERROR_INVALID_FONT; + } + } + // We should normally set Result to INVALID_FONT if there is no name table. + // However, one Harfbuzz test has a font with no name table. + } + + kbts__byteswap_context ByteSwapContext = KBTS__ZERO; + ByteSwapContext.FileBase = (char *)Header; + ByteSwapContext.FileEnd = (char *)Header + State->TotalSize; + ByteSwapContext.PointerCapacity = State->ScratchSize / sizeof(kbts_u32); + ByteSwapContext.Pointers = (kbts_u32 *)ScratchMemory; + + kbts_blob_table *GdefTable = &Header->Tables[KBTS_BLOB_TABLE_ID_GDEF]; + if(GdefTable->Length) + { + kbts__gdef *Gdef = KBTS__POINTER_OFFSET(kbts__gdef, Header, GdefTable->OffsetFromStartOfFile); + + if(Gdef->ClassDefinitionOffset) + { + kbts_u16 *ClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Gdef, Gdef->ClassDefinitionOffset); + kbts__ByteSwapClassDefinition(&ByteSwapContext, ClassDefBase); + } + + if(Gdef->MarkAttachmentClassDefinitionOffset) + { + kbts_u16 *ClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Gdef, Gdef->MarkAttachmentClassDefinitionOffset); + kbts__ByteSwapClassDefinition(&ByteSwapContext, ClassDefBase); + } + + if((Gdef->Minor >= 2) && Gdef->MarkGlyphSetsDefinitionOffset) + { + kbts__mark_glyph_sets *MarkGlyphSets = KBTS__POINTER_OFFSET(kbts__mark_glyph_sets, Gdef, Gdef->MarkGlyphSetsDefinitionOffset); + kbts__ByteSwapArray16Context(&MarkGlyphSets->Format, 2, &ByteSwapContext); + if(MarkGlyphSets->Format == 1) + { + kbts_u32 *CoverageOffsets = KBTS__POINTER_AFTER(kbts_u32, MarkGlyphSets); + kbts__ByteSwapArray32Context(CoverageOffsets, MarkGlyphSets->MarkGlyphSetCount, &ByteSwapContext); + + KBTS__FOR(MarkGlyphSetIndex, 0, MarkGlyphSets->MarkGlyphSetCount) + { + kbts__coverage *Coverage = KBTS__POINTER_OFFSET(kbts__coverage, MarkGlyphSets, CoverageOffsets[MarkGlyphSetIndex]); + kbts__ByteSwapCoverage(&ByteSwapContext, Coverage); + } + } + } + } + + kbts__gsub_gpos *Gsub = kbts__BlobTableDataType(Header, KBTS_BLOB_TABLE_ID_GSUB, kbts__gsub_gpos); + kbts__gsub_gpos *Gpos = kbts__BlobTableDataType(Header, KBTS_BLOB_TABLE_ID_GPOS, kbts__gsub_gpos); + kbts__gdef *Gdef = kbts__BlobTableDataType(Header, KBTS_BLOB_TABLE_ID_GDEF, kbts__gdef); + + if(Gsub) + { + kbts__ByteSwapGsubGposCommon(&ByteSwapContext, Gsub); + + kbts_lookup_list *LookupList = kbts__GetLookupList(Gsub); + LookupList->Count = kbts__ByteSwap16(LookupList->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, LookupList), LookupList->Count, &ByteSwapContext); + + KBTS__FOR(LookupIndex, 0, LookupList->Count) + { + kbts__lookup *PackedLookup = kbts__GetLookup(LookupList, LookupIndex); + + KBTS_DUMPF("GSUB Lookup %llu:\n", LookupIndex); + + if(kbts__ByteSwapLookup(&ByteSwapContext, PackedLookup)) + { + kbts__unpacked_lookup Lookup = kbts__UnpackLookup(Gdef, PackedLookup); + KBTS_DUMPF(" Flags %u\n", Lookup.Flags); + + KBTS__FOR(SubstitutionIndex, 0, Lookup.SubtableCount) + { + kbts_u16 *Base = KBTS__POINTER_OFFSET(kbts_u16, PackedLookup, Lookup.SubtableOffsets[SubstitutionIndex]); + + KBTS_DUMPF(" Subtable %llu:\n", SubstitutionIndex); + + kbts__ByteSwapGsubLookupSubtable(&ByteSwapContext, Lookup.Type, Base); + } + } + } + } + + if(Gpos) + { + kbts__ByteSwapGsubGposCommon(&ByteSwapContext, Gpos); + + kbts_lookup_list *LookupList = kbts__GetLookupList(Gpos); + LookupList->Count = kbts__ByteSwap16(LookupList->Count); + kbts__ByteSwapArray16Context(KBTS__POINTER_AFTER(kbts_u16, LookupList), LookupList->Count, &ByteSwapContext); + + KBTS__FOR(LookupIndex, 0, LookupList->Count) + { + kbts__lookup *PackedLookup = kbts__GetLookup(LookupList, LookupIndex); + + KBTS_DUMPF("GPOS Lookup %llu:\n", LookupIndex); + + if(kbts__ByteSwapLookup(&ByteSwapContext, PackedLookup)) + { + kbts__unpacked_lookup Lookup = kbts__UnpackLookup(Gdef, PackedLookup); + + KBTS_DUMPF(" Flags %x\n", Lookup.Flags); + + KBTS__FOR(SubstitutionIndex, 0, Lookup.SubtableCount) + { + kbts_u16 *Base = KBTS__POINTER_OFFSET(kbts_u16, PackedLookup, Lookup.SubtableOffsets[SubstitutionIndex]); + + KBTS_DUMPF(" Subtable %llu:\n", (kbts_un)SubstitutionIndex); + + kbts__ByteSwapGposLookupSubtable(&ByteSwapContext, LookupList, Lookup.Type, Base); + } + } + } + } + + // At this point, we are done byteswapping the file, so we can start reusing scratch memory. + + // Bake our own data. + + if(!Result && Header->Tables[KBTS_BLOB_TABLE_ID_MAXP].Length) + { + kbts_un GlyphCount = Header->GlyphCount; + kbts_un LookupCount = Header->LookupCount; + kbts_un SubtableCount = Header->LookupSubtableCount; + + kbts_u32 *GlyphLookupMatrix = (kbts_u32 *)OutData; + kbts_u32 *GlyphLookupSubtableMatrix = KBTS__POINTER_OFFSET(kbts_u32, GlyphLookupMatrix, State->GlyphLookupMatrixSizeInBytes); + kbts_u32 *LookupSubtableIndexOffsets = KBTS__POINTER_OFFSET(kbts_u32, GlyphLookupSubtableMatrix, State->GlyphLookupSubtableMatrixSizeInBytes); + kbts_lookup_subtable_info *SubtableInfos = KBTS__POINTER_OFFSET(kbts_lookup_subtable_info, LookupSubtableIndexOffsets, sizeof(kbts_u32) * Header->LookupCount); + + KBTS_MEMSET(GlyphLookupMatrix, 0, State->GlyphLookupMatrixSizeInBytes + + State->GlyphLookupSubtableMatrixSizeInBytes + + sizeof(kbts_u32) * Header->LookupCount + + sizeof(kbts_lookup_subtable_info) * Header->LookupSubtableCount); + + kbts_un GposLookupIndexOffset = 0; + kbts_un RunningLookupIndex = 0; + kbts_un RunningSubtableIndex = 0; + + kbts_blob_table_id TableIds[2] = {KBTS_BLOB_TABLE_ID_GSUB, KBTS_BLOB_TABLE_ID_GPOS}; + KBTS__FOR(TableIdIndex, 0, KBTS__ARRAY_LENGTH(TableIds)) + { + kbts_blob_table_id TableId = TableIds[TableIdIndex]; + kbts_blob_table *Table = &Header->Tables[TableId]; + + if(Table->Length) + { + kbts__gsub_gpos *ShapingTable = KBTS__POINTER_OFFSET(kbts__gsub_gpos, Header, Table->OffsetFromStartOfFile); + int InGpos = (TableId == KBTS_BLOB_TABLE_ID_GPOS); + kbts_shaping_table ShapingTableId = (kbts_shaping_table)(InGpos ? KBTS_SHAPING_TABLE_GPOS : KBTS_SHAPING_TABLE_GSUB); + + if(InGpos) + { + GposLookupIndexOffset = RunningLookupIndex; + } + + if(ShapingTable) + { + kbts_lookup_list *LookupList = kbts__GetLookupList(ShapingTable); + KBTS__FOR(LookupIndex, 0, LookupList->Count) + { + kbts__lookup *PackedLookup = kbts__GetLookup(LookupList, LookupIndex); + kbts__unpacked_lookup Lookup = kbts__UnpackLookup(Gdef, PackedLookup); + + LookupSubtableIndexOffsets[RunningLookupIndex] = (kbts_u32)RunningSubtableIndex; + + KBTS__FOR(SubtableIndex, 0, Lookup.SubtableCount) + { + kbts_lookup_subtable_info SubtableInfo = KBTS__ZERO; + kbts_u16 LookupType = Lookup.Type; + kbts_u16 *Base = KBTS__POINTER_OFFSET(kbts_u16, PackedLookup, Lookup.SubtableOffsets[SubtableIndex]); + + while((!InGpos && (LookupType == 7)) || + (InGpos && (LookupType == 9))) + { + kbts__extension *Extension = (kbts__extension *)Base; + + // CAREFUL: Here, we remap LookupType only. + // Do not use Lookup.Type beyond this point! + LookupType = Extension->LookupType; + Base = KBTS__POINTER_OFFSET(kbts_u16, Extension, Extension->Offset); + } + + kbts__coverage *Coverage = 0; + + if(kbts__LookupBeginsWithCoverage(ShapingTableId, LookupType, Base[0])) + { + Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Base, Base[1]); + } + + if(!InGpos && (LookupType == 4)) + { + kbts__ligature_substitution *Subst = (kbts__ligature_substitution *)Base; + KBTS__FOR(SetIndex, 0, Subst->LigatureSetCount) + { + kbts__ligature_set *Set = kbts__GetLigatureSet(Subst, SetIndex); + KBTS__FOR(LigatureIndex, 0, Set->Count) + { + kbts__ligature *Ligature = kbts__GetLigature(Set, LigatureIndex); + kbts_u16 *Ids = KBTS__POINTER_AFTER(kbts_u16, Ligature); + + KBTS__FOR(IdIndex, 1, Ligature->ComponentCount) + { + kbts_un GlyphId = Ids[IdIndex - 1]; + + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(RunningSubtableIndex, SubtableCount, GlyphId); + GlyphLookupSubtableMatrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Ligature->ComponentCount - 1) + 1; + } + } + } + else if((!InGpos && (LookupType == 5)) || + (InGpos && (LookupType == 7))) + { + switch(Base[0]) + { + case 1: + { + kbts__sequence_context_1 *Subst = (kbts__sequence_context_1 *)Base; + KBTS__FOR(SetIndex, 0, Subst->SeqRuleSetCount) + { + kbts__sequence_rule_set *Set = kbts__GetSequenceRuleSet(Subst, SetIndex); + + if(Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__sequence_rule *Rule = kbts__GetSequenceRule(Set, RuleIndex); + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Rule->GlyphCount - 1) + 1; + + kbts_u16 *SequenceGlyphIds = KBTS__POINTER_AFTER(kbts_u16, Rule); + KBTS__FOR(InputIndex, 1, Rule->GlyphCount) + { + kbts_un GlyphId = SequenceGlyphIds[InputIndex - 1]; + + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(RunningSubtableIndex, SubtableCount, GlyphId); + GlyphLookupSubtableMatrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + } + } + } + } break; + + case 2: + { + kbts__sequence_context_2 *Subst = (kbts__sequence_context_2 *)Base; + kbts_u16 *ClassDefBase = KBTS__POINTER_OFFSET(kbts_u16, Subst, Subst->ClassDefOffset); + + kbts_u64 ClassesIncluded[16] = KBTS__ZERO; + + KBTS__FOR(SetIndex, 0, Subst->ClassSequenceRuleSetCount) + { + kbts__class_sequence_rule_set *Set = kbts__GetClassSequenceRuleSet(Subst, SetIndex); + if(Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__class_sequence_rule *Rule = kbts__GetClassSequenceRule(Set, RuleIndex); + kbts_u16 *SequenceClasses = KBTS__POINTER_AFTER(kbts_u16, Rule); + + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Rule->GlyphCount - 1) + 1; + + KBTS__FOR(SequenceIndex, 1, Rule->GlyphCount) + { + kbts_un Class = SequenceClasses[SequenceIndex - 1]; + + if(Class < (KBTS__ARRAY_LENGTH(ClassesIncluded) * 64)) + { + ClassesIncluded[Class / 64] |= 1ull << (Class % 64); + } + } + } + } + } + + kbts__MarkMatrixClassDef(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, ClassDefBase, ClassesIncluded, KBTS__ARRAY_LENGTH(ClassesIncluded)); + } break; + + case 3: + { + kbts__sequence_context_3 *Subst = (kbts__sequence_context_3 *)Base; + kbts_u16 *CoverageOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Subst->GlyphCount - 1) + 1; + + KBTS__FOR(CoverageIndex, 1, Subst->GlyphCount) + { + kbts__coverage *SubstCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, CoverageOffsets[CoverageIndex]); + + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubstCoverage, 1); + } + + Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, CoverageOffsets[0]); + } break; + } + } + else if((!InGpos && (LookupType == 6)) || + (InGpos && (LookupType == 8))) + { + switch(Base[0]) + { + case 1: + { + kbts__chained_sequence_context_1 *Subst = (kbts__chained_sequence_context_1 *)Base; + kbts_u16 *ChainedSequenceRuleSetOffsets = KBTS__POINTER_AFTER(kbts_u16, Subst); + + KBTS__FOR(SetIndex, 0, Subst->ChainedSequenceRuleSetCount) + { + kbts__chained_sequence_rule_set *Set = KBTS__POINTER_OFFSET(kbts__chained_sequence_rule_set, Subst, ChainedSequenceRuleSetOffsets[SetIndex]); + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedClassSequenceRule(Set, RuleIndex); + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 0); + + SubtableInfo.MinimumBacktrackPlusOne = KBTS__MIN(SubtableInfo.MinimumBacktrackPlusOne - 1, Unpacked.BacktrackCount) + 1; + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Unpacked.InputCount - 1 + Unpacked.LookaheadCount) + 1; + + KBTS__FOR(BacktrackIndex, 0, Unpacked.BacktrackCount) + { + kbts_un GlyphId = Unpacked.Backtrack[BacktrackIndex]; + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(RunningSubtableIndex, SubtableCount, GlyphId); + GlyphLookupSubtableMatrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + + KBTS__FOR(InputIndex, 1, Unpacked.InputCount) + { + kbts_un GlyphId = Unpacked.Input[InputIndex - 1]; + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(RunningSubtableIndex, SubtableCount, GlyphId); + GlyphLookupSubtableMatrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + + KBTS__FOR(LookaheadIndex, 0, Unpacked.LookaheadCount) + { + kbts_un GlyphId = Unpacked.Lookahead[LookaheadIndex]; + kbts__matrix_index SubtableMatrixIndex = kbts__GlyphLookupSubtableMatrixIndex(RunningSubtableIndex, SubtableCount, GlyphId); + GlyphLookupSubtableMatrix[SubtableMatrixIndex.WordIndex] |= 1 << SubtableMatrixIndex.BitIndex; + } + } + } + } break; + + case 2: + { + kbts__chained_sequence_context_2 *Subst = (kbts__chained_sequence_context_2 *)Base; + kbts_un BacktrackClassDefOffset = Subst->BacktrackClassDefOffset; + kbts_un InputClassDefOffset = Subst->InputClassDefOffset; + kbts_un LookaheadClassDefOffset = Subst->LookaheadClassDefOffset; + kbts_u16 *BacktrackClassDefinition = 0; + if(BacktrackClassDefOffset) + { + BacktrackClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, BacktrackClassDefOffset); + } + kbts_u16 *InputClassDefinition = 0; + if(InputClassDefOffset) + { + InputClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, InputClassDefOffset); + } + kbts_u16 *LookaheadClassDefinition = 0; + if(LookaheadClassDefOffset) + { + LookaheadClassDefinition = KBTS__POINTER_OFFSET(kbts_u16, Subst, LookaheadClassDefOffset); + } + + kbts_u64 BacktrackClassesIncluded[16] = KBTS__ZERO; + kbts_u64 InputClassesIncluded[16] = KBTS__ZERO; + kbts_u64 LookaheadClassesIncluded[16] = KBTS__ZERO; + + KBTS__FOR(SetIndex, 0, Subst->ChainedClassSequenceRuleSetCount) + { + kbts__chained_sequence_rule_set *Set = kbts__GetChainedClassSequenceRuleSet(Subst, SetIndex); + if(Set) + { + KBTS__FOR(RuleIndex, 0, Set->Count) + { + kbts__chained_sequence_rule *Rule = kbts__GetChainedSequenceRule(Set, RuleIndex); + kbts__unpacked_chained_sequence_rule Unpacked = kbts__UnpackChainedSequenceRule(Rule, 0); + + SubtableInfo.MinimumBacktrackPlusOne = KBTS__MIN(SubtableInfo.MinimumBacktrackPlusOne - 1, Unpacked.BacktrackCount) + 1; + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Unpacked.InputCount - 1 + Unpacked.LookaheadCount) + 1; + + KBTS__FOR(BacktrackIndex, 0, Unpacked.BacktrackCount) + { + kbts_un Class = Unpacked.Backtrack[BacktrackIndex]; + if(Class < (KBTS__ARRAY_LENGTH(BacktrackClassesIncluded) * 64)) + { + BacktrackClassesIncluded[Class / 64] |= 1ull << (Class % 64); + } + } + + KBTS__FOR(InputIndex, 1, Unpacked.InputCount) + { + kbts_un Class = Unpacked.Input[InputIndex - 1]; + if(Class < (KBTS__ARRAY_LENGTH(InputClassesIncluded) * 64)) + { + InputClassesIncluded[Class / 64] |= 1ull << (Class % 64); + } + } + + KBTS__FOR(LookaheadIndex, 0, Unpacked.LookaheadCount) + { + kbts_un Class = Unpacked.Lookahead[LookaheadIndex]; + if(Class < (KBTS__ARRAY_LENGTH(LookaheadClassesIncluded) * 64)) + { + LookaheadClassesIncluded[Class / 64] |= 1ull << (Class % 64); + } + } + } + } + } + + kbts__MarkMatrixClassDef(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, BacktrackClassDefinition, BacktrackClassesIncluded, KBTS__ARRAY_LENGTH(BacktrackClassesIncluded)); + kbts__MarkMatrixClassDef(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, InputClassDefinition, InputClassesIncluded, KBTS__ARRAY_LENGTH(InputClassesIncluded)); + kbts__MarkMatrixClassDef(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, LookaheadClassDefinition, LookaheadClassesIncluded, KBTS__ARRAY_LENGTH(LookaheadClassesIncluded)); + } break; + + case 3: + { + kbts__chained_sequence_context_3 *Subst = (kbts__chained_sequence_context_3 *)Base; + kbts__unpacked_chained_sequence_context_3 Unpacked = kbts__UnpackChainedSequenceContext3(Subst, 0); + + Coverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.InputCoverageOffsets[0]); + + SubtableInfo.MinimumBacktrackPlusOne = KBTS__MIN(SubtableInfo.MinimumBacktrackPlusOne - 1, Unpacked.BacktrackCount) + 1; + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Unpacked.InputCount - 1 + Unpacked.LookaheadCount) + 1; + + KBTS__FOR(BacktrackCoverageIndex, 0, Unpacked.BacktrackCount) + { + kbts__coverage *SubCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.BacktrackCoverageOffsets[BacktrackCoverageIndex]); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubCoverage, 1); + } + + KBTS__FOR(InputCoverageIndex, 1, Unpacked.InputCount) + { + kbts__coverage *SubCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.InputCoverageOffsets[InputCoverageIndex]); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubCoverage, 1); + } + + + KBTS__FOR(LookaheadCoverageIndex, 0, Unpacked.LookaheadCount) + { + kbts__coverage *SubCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.LookaheadCoverageOffsets[LookaheadCoverageIndex]); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubCoverage, 1); + } + } break; + } + } + else if(!InGpos && (LookupType == 8)) + { + kbts__reverse_chain_substitution *Subst = (kbts__reverse_chain_substitution *)Base; + kbts__unpacked_reverse_chain_substitution Unpacked = kbts__UnpackReverseChainSubstitution(Subst, 0); + SubtableInfo.MinimumBacktrackPlusOne = KBTS__MIN(SubtableInfo.MinimumBacktrackPlusOne - 1, Unpacked.BacktrackCount) + 1; + SubtableInfo.MinimumFollowupPlusOne = KBTS__MIN(SubtableInfo.MinimumFollowupPlusOne - 1, Unpacked.LookaheadCount) + 1; + + KBTS__FOR(BacktrackIndex, 0, Unpacked.BacktrackCount) + { + kbts__coverage *SubCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.BacktrackCoverageOffsets[BacktrackIndex]); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubCoverage, 1); + } + + KBTS__FOR(LookaheadIndex, 0, Unpacked.LookaheadCount) + { + kbts__coverage *SubCoverage = KBTS__POINTER_OFFSET(kbts__coverage, Subst, Unpacked.LookaheadCoverageOffsets[LookaheadIndex]); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, SubCoverage, 1); + } + } + + kbts__MarkMatrixCoverage(GlyphLookupMatrix, RunningLookupIndex, LookupCount, GlyphCount, Coverage, 0); + kbts__MarkMatrixCoverage(GlyphLookupSubtableMatrix, RunningSubtableIndex, SubtableCount, GlyphCount, Coverage, 1); + + SubtableInfos[RunningSubtableIndex] = SubtableInfo; + RunningSubtableIndex += 1; + } + + RunningLookupIndex += 1; + } + } + } + } + + Header->GposLookupIndexOffset = (kbts_u32)GposLookupIndexOffset; + Header->GlyphLookupMatrixOffsetFromStartOfFile = KBTS__POINTER_DIFF32(GlyphLookupMatrix, Header); + Header->GlyphLookupSubtableMatrixOffsetFromStartOfFile = KBTS__POINTER_DIFF32(GlyphLookupSubtableMatrix, Header); + Header->LookupSubtableIndexOffsetsOffsetFromStartOfFile = KBTS__POINTER_DIFF32(LookupSubtableIndexOffsets, Header); + Header->SubtableInfosOffsetFromStartOfFile = KBTS__POINTER_DIFF32(SubtableInfos, Header); + } + } + + if(Result != KBTS_LOAD_FONT_ERROR_NONE) + { + Font->Blob = 0; + } + Font->Error = Result; + + return Result; +} + +KBTS_EXPORT void kbts_GetFontInfo(kbts_font *Font, kbts_font_info *Info) +{ + KBTS_MEMSET(Info, 0, sizeof(*Info)); + kbts_blob_header *Blob = Font->Blob; + + if(kbts_FontIsValid(Font) && Blob) + { + kbts_blob_table *NameTable = &Blob->Tables[KBTS_BLOB_TABLE_ID_NAME]; + + if(NameTable->Length) + { + kbts__name *Name = KBTS__POINTER_OFFSET(kbts__name, Blob, NameTable->OffsetFromStartOfFile); + kbts__name_record *Records = KBTS__POINTER_AFTER(kbts__name_record, Name); + char *StringBase = KBTS__POINTER_OFFSET(char, Name, Name->StringStorageOffset); + + KBTS__FOR(RecordIndex, 0, Name->Count) + { + kbts__name_record *Record = &Records[RecordIndex]; + + if(!Record->LanguageId) + { + kbts_font_info_string_id Id = KBTS_FONT_INFO_STRING_ID_NONE; + + switch(Record->NameId) + { + case 0: Id = KBTS_FONT_INFO_STRING_ID_COPYRIGHT; break; + case 1: Id = KBTS_FONT_INFO_STRING_ID_FAMILY; break; + case 2: Id = KBTS_FONT_INFO_STRING_ID_SUBFAMILY; break; + case 3: Id = KBTS_FONT_INFO_STRING_ID_UID; break; + case 4: Id = KBTS_FONT_INFO_STRING_ID_FULL_NAME; break; + case 5: Id = KBTS_FONT_INFO_STRING_ID_VERSION; break; + case 6: Id = KBTS_FONT_INFO_STRING_ID_POSTSCRIPT_NAME; break; + case 7: Id = KBTS_FONT_INFO_STRING_ID_TRADEMARK; break; + case 8: Id = KBTS_FONT_INFO_STRING_ID_MANUFACTURER; break; + case 9: Id = KBTS_FONT_INFO_STRING_ID_DESIGNER; break; + case 10: Id = KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_FAMILY; break; + case 11: Id = KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_SUBFAMILY; break; + } + + if(Id) + { + Info->Strings[Id] = KBTS__POINTER_OFFSET(char, StringBase, Record->StringOffset); + Info->StringLengths[Id] = Record->Length; + } + } + } + + if(!Info->Strings[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_FAMILY]) + { + Info->Strings[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_FAMILY] = Info->Strings[KBTS_FONT_INFO_STRING_ID_FAMILY]; + Info->StringLengths[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_FAMILY] = Info->StringLengths[KBTS_FONT_INFO_STRING_ID_FAMILY]; + } + + if(!Info->Strings[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_SUBFAMILY]) + { + Info->Strings[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_SUBFAMILY] = Info->Strings[KBTS_FONT_INFO_STRING_ID_SUBFAMILY]; + Info->StringLengths[KBTS_FONT_INFO_STRING_ID_TYPOGRAPHIC_SUBFAMILY] = Info->StringLengths[KBTS_FONT_INFO_STRING_ID_SUBFAMILY]; + } + } + + kbts_blob_table *Os2Table = &Blob->Tables[KBTS_BLOB_TABLE_ID_OS2]; + + if(Os2Table->Length) + { + kbts__os2 *Os2 = KBTS__POINTER_OFFSET(kbts__os2, Blob, Os2Table->OffsetFromStartOfFile); + kbts_font_weight Weight = KBTS_FONT_WEIGHT_UNKNOWN; + kbts_font_width Width = KBTS_FONT_WIDTH_UNKNOWN; + kbts_font_style_flags StyleFlags = KBTS_FONT_STYLE_FLAG_NONE; + + switch(Os2->WeightClass) + { + case 100: Weight = KBTS_FONT_WEIGHT_THIN; break; + case 200: Weight = KBTS_FONT_WEIGHT_EXTRA_LIGHT; break; + case 300: Weight = KBTS_FONT_WEIGHT_LIGHT; break; + case 400: Weight = KBTS_FONT_WEIGHT_NORMAL; break; + case 500: Weight = KBTS_FONT_WEIGHT_MEDIUM; break; + case 600: Weight = KBTS_FONT_WEIGHT_SEMI_BOLD; break; + case 700: Weight = KBTS_FONT_WEIGHT_BOLD; break; + case 800: Weight = KBTS_FONT_WEIGHT_EXTRA_BOLD; break; + case 900: Weight = KBTS_FONT_WEIGHT_BLACK; break; + } + + switch(Os2->WidthClass) + { + case 1: Width = KBTS_FONT_WIDTH_ULTRA_CONDENSED; break; + case 2: Width = KBTS_FONT_WIDTH_EXTRA_CONDENSED; break; + case 3: Width = KBTS_FONT_WIDTH_CONDENSED; break; + case 4: Width = KBTS_FONT_WIDTH_SEMI_CONDENSED; break; + case 5: Width = KBTS_FONT_WIDTH_NORMAL; break; + case 6: Width = KBTS_FONT_WIDTH_SEMI_EXPANDED; break; + case 7: Width = KBTS_FONT_WIDTH_EXPANDED; break; + case 8: Width = KBTS_FONT_WIDTH_EXTRA_EXPANDED; break; + case 9: Width = KBTS_FONT_WIDTH_ULTRA_EXPANDED; break; + } + + if(Os2->Selection & (KBTS__OS2_SELECTION_FLAG_ITALIC | KBTS__OS2_SELECTION_FLAG_OBLIQUE)) + { + StyleFlags |= KBTS_FONT_STYLE_FLAG_ITALIC; + } + if(Os2->Selection & KBTS__OS2_SELECTION_FLAG_BOLD) + { + StyleFlags |= KBTS_FONT_STYLE_FLAG_BOLD; + } + if(Os2->Selection & KBTS__OS2_SELECTION_FLAG_REGULAR) + { + StyleFlags |= KBTS_FONT_STYLE_FLAG_REGULAR; + } + + Info->Weight = Weight; + Info->Width = Width; + Info->StyleFlags = StyleFlags; + } + } +} + +KBTS_EXPORT kbts_font kbts_FontFromMemory(void *FileData, int FileSize, int FontIndex, kbts_allocator_function *Allocator, void *AllocatorData) +{ + kbts_font Result = KBTS__ZERO; + + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + if(FileData && (FileSize > 0)) + { + kbts_load_font_state LoadFontState = KBTS__ZERO; + int ScratchSize, OutputSize; + kbts_load_font_error Error = kbts_LoadFont(&Result, &LoadFontState, FileData, (int)FileSize, FontIndex, &ScratchSize, &OutputSize); + + if(Error == KBTS_LOAD_FONT_ERROR_NEED_TO_CREATE_BLOB) + { + void *ScratchMemory = kbts__AllocatorAllocate(Allocator, AllocatorData, (kbts_un)ScratchSize); + void *OutputMemory = kbts__AllocatorAllocate(Allocator, AllocatorData, (kbts_un)OutputSize); + + kbts_PlaceBlob(&Result, &LoadFontState, ScratchMemory, OutputMemory); + + kbts__AllocatorFree(Allocator, AllocatorData, ScratchMemory); + + Result.Allocator = Allocator; + Result.AllocatorData = AllocatorData; + } + } + + return Result; +} + +#ifndef KB_TEXT_SHAPE_NO_CRT + +KBTS_EXPORT kbts_font kbts_FontFromFile(const char *FileName, int FontIndex, kbts_allocator_function *Allocator, void *AllocatorData, void **FileData, int *FileSize_) +{ + kbts_font Result = KBTS__ZERO; + + if(!Allocator) + { + Allocator = kbts__DefaultAllocator; + } + + FILE *File; +# ifndef _MSC_VER + File = fopen(FileName, "rb"); +# else + fopen_s(&File, FileName, "rb"); +# endif + + if(File) + { + fseek(File, 0, SEEK_END); + long FileSize = ftell(File); + fseek(File, 0, SEEK_SET); + + if(FileSize > 0) + { + void *Data = kbts__AllocatorAllocate(Allocator, AllocatorData, (kbts_un)FileSize); + + if(Data) + { + kbts_un Ok = fread(Data, (kbts_un)FileSize, 1, File); + + if(Ok) + { + Result = kbts_FontFromMemory(Data, (int)FileSize, FontIndex, Allocator, AllocatorData); + + if(!Result.Error) + { + + if(FileData) + { + *FileData = Data; + } + else + { + kbts__AllocatorFree(Allocator, AllocatorData, Data); + } + + if(FileSize_) + { + *FileSize_ = (int)FileSize; + } + } + } + else + { + Result.Error = KBTS_LOAD_FONT_ERROR_READ_ERROR; + } + } + else + { + Result.Error = KBTS_LOAD_FONT_ERROR_OUT_OF_MEMORY; + } + } + + fclose(File); + } + else + { + Result.Error = KBTS_LOAD_FONT_ERROR_COULD_NOT_OPEN_FILE; + } + + return Result; +} + +#endif + +KBTS_EXPORT void kbts_FreeFont(kbts_font *Font) +{ + if(Font->Blob && Font->Allocator) + { + kbts__AllocatorFree(Font->Allocator, Font->AllocatorData, Font->Blob); + } +} + +static void kbts__DoBreak(kbts_break_state *State, kbts_s32 Position, kbts_u8 Flags, kbts_direction Direction, kbts_direction ParagraphDirection, kbts_script Script) +{ + kbts_u32 BreakPosition = State->CurrentPosition + (kbts_u32)Position; + if(Flags && + (BreakPosition <= State->CurrentPosition)) + { + kbts_break Break = KBTS__ZERO; + Break.Position = (int)BreakPosition; + Break.Flags = Flags; + Break.Direction = Direction; + Break.ParagraphDirection = ParagraphDirection; + Break.Script = Script; + + if((Flags & KBTS_BREAK_FLAG_SCRIPT) && + (State->LastScriptBreakScript)) + { + kbts_un LastScriptBreakPosition = State->LastScriptBreakPosition; + kbts_u8 LastScriptBreakScript = State->LastScriptBreakScript; + + // Resolve bracket scripts here. + // The only span we can fully resolve is the _previous_ script, but we don't + // know when it starts, so we might as well tag all of the brackets we have stored so far. + for(kbts_un BracketIndex = State->BracketCount; + BracketIndex; + --BracketIndex) + { + kbts_bracket *Bracket = &State->Brackets[BracketIndex - 1]; + + if(Bracket->Position >= BreakPosition) + { + Bracket->Script = (kbts_u8)Script; + } + else if(Bracket->Position >= LastScriptBreakPosition) + { + Bracket->Script = LastScriptBreakScript; + } + else + { + break; + } + } + + State->LastScriptBreakPosition = BreakPosition; + State->LastScriptBreakScript = (kbts_u8)Script; + } + + if((Flags & KBTS_BREAK_FLAG_DIRECTION) && + (State->LastDirectionBreakDirection)) + { + kbts_un LastDirectionBreakPosition = State->LastDirectionBreakPosition; + kbts_u8 LastDirectionBreakDirection = State->LastDirectionBreakDirection; + + for(kbts_un BracketIndex = State->BracketCount; + BracketIndex; + --BracketIndex) + { + kbts_bracket *Bracket = &State->Brackets[BracketIndex - 1]; + + if(Bracket->Position >= BreakPosition) + { + Bracket->Direction = (kbts_u8)Direction; + } + else if(Bracket->Position >= LastDirectionBreakPosition) + { + Bracket->Direction = LastDirectionBreakDirection; + } + else + { + break; + } + } + + State->LastDirectionBreakPosition = BreakPosition; + State->LastDirectionBreakDirection = (kbts_u8)Direction; + } + + int Matched = 0; + KBTS__FOR(BreakIndex, 0, State->BreakCount) + { + kbts_break *Existing = &State->Breaks[BreakIndex]; + + if(Existing->Position == Break.Position) + { + Existing->Flags |= Break.Flags; + + if(Break.Flags & KBTS_BREAK_FLAG_DIRECTION) + { + Existing->Direction = Break.Direction; + } + + if(Break.Flags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) + { + Existing->ParagraphDirection = Break.ParagraphDirection; + } + + if(Break.Flags & KBTS_BREAK_FLAG_SCRIPT) + { + Existing->Script = Break.Script; + } + + Matched = 1; + + break; + } + else if(Existing->Position < Break.Position) + { + // We order breaks in backwards order here, because we want to simply pop them off the top in Break(). + kbts_break Swap = *Existing; + *Existing = Break; + Break = Swap; + } + else if((Break.Flags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) && + (Existing->Flags & KBTS_BREAK_FLAG_DIRECTION) && + !Existing->Direction) + { + // Short-circuit coerce neutral blocks to the paragraph direction. + Existing->Direction = Break.ParagraphDirection; + } + } + + State->Breaks[State->BreakCount] = Break; + State->BreakCount += !Matched; + } +} + +// The line break state is a 4-character history. Each character is a bags of 12 bits (padded to 16 bits). +// Each character specifies allowed and required breaks on 6 levels of priority. +// A required break implies an allowed break. +// A priority N break implies priority 0..N-1 breaks. +enum { + KBTS__LINE_BREAK_ALLOWED0 = 1, + KBTS__LINE_BREAK_ALLOWED1 = 3, + KBTS__LINE_BREAK_ALLOWED2 = 7, + KBTS__LINE_BREAK_ALLOWED3 = 0xF, + KBTS__LINE_BREAK_ALLOWED4 = 0x1F, + KBTS__LINE_BREAK_ALLOWED5 = 0x3F, + KBTS__LINE_BREAK_REQUIRED0 = (1 << 6) | KBTS__LINE_BREAK_ALLOWED0, + KBTS__LINE_BREAK_REQUIRED1 = (3 << 6) | KBTS__LINE_BREAK_ALLOWED1, + KBTS__LINE_BREAK_REQUIRED2 = (7 << 6) | KBTS__LINE_BREAK_ALLOWED2, + KBTS__LINE_BREAK_REQUIRED3 = (0xF << 6) | KBTS__LINE_BREAK_ALLOWED3, + KBTS__LINE_BREAK_REQUIRED4 = (0x1F << 6) | KBTS__LINE_BREAK_ALLOWED4, + KBTS__LINE_BREAK_REQUIRED5 = (0x3F << 6) | KBTS__LINE_BREAK_ALLOWED5, + KBTS__LINE_BREAK_REQUIRED_MASK = 0x3F << 6, + KBTS__LINE_BREAK_ALLOWED_MASK = 0x3F, + KBTS__LINE_BREAK_MASK = KBTS__LINE_BREAK_REQUIRED_MASK | KBTS__LINE_BREAK_ALLOWED_MASK, +}; + +static void kbts__DoLineBreak(kbts_break_state *State, int Position, kbts_u64 EffectiveLineBreaks) +{ + if(EffectiveLineBreaks & KBTS__LINE_BREAK_MASK) + { + kbts_u8 Flags = 0; + + if(EffectiveLineBreaks & KBTS__LINE_BREAK_ALLOWED_MASK) + { + Flags |= KBTS_BREAK_FLAG_LINE_SOFT; + } + + if(EffectiveLineBreaks & KBTS__LINE_BREAK_REQUIRED_MASK) + { + Flags |= KBTS_BREAK_FLAG_LINE_HARD; + } + + kbts__DoBreak(State, Position, Flags, 0, 0, 0); + } +} + +static void kbts__BreakStateStartParagraph(kbts_break_state *State) +{ + kbts_direction ParagraphDirection = State->UserParagraphDirection; + // At the beginning of a paragraph, we want to pretend like start-of-text is an actual character + // with bidirectional data that depends on its direction. + kbts_u32 StartOfTextBidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI; + kbts_u32 Flags = 0; + + if(ParagraphDirection == KBTS_DIRECTION_LTR) + { + StartOfTextBidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_L; + } + else if(ParagraphDirection == KBTS_DIRECTION_RTL) + { + Flags = KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L; + StartOfTextBidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_R; + } + + State->ParagraphDirection = (kbts_u8)ParagraphDirection; + State->BidirectionalClass1 = (kbts_u8)StartOfTextBidirectionalClass; + State->Flags = Flags; +} + +typedef kbts_u32 kbts__break_flush_flags; +enum kbts__break_flush_flags_enum +{ + KBTS__BREAK_FLUSH_FLAG_NONE, + KBTS__BREAK_FLUSH_FLAG_SCRIPT = (1 << 0), + KBTS__BREAK_FLUSH_FLAG_DIRECTION_2 = (1 << 1), + KBTS__BREAK_FLUSH_FLAG_DIRECTION_1 = (1 << 2), + KBTS__BREAK_FLUSH_FLAG_DIRECTION_PARAGRAPH = (1 << 3), +}; + +static void kbts__FlushDirection(kbts_break_state *State, kbts_direction *LastDirection, kbts_unicode_bidirectional_class BidirectionalClass, kbts_s16 PositionOffset) +{ + // @Incomplete: ET+ EN -> EN+ EN + kbts_break_flags BreakFlags = 0; + kbts_direction Direction = KBTS_DIRECTION_DONT_KNOW; + + switch(BidirectionalClass) + { + // @Incomplete: Surely, there are other edge cases we could handle here. + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_L: + BreakFlags = KBTS_BREAK_FLAG_DIRECTION | KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION; + Direction = KBTS_DIRECTION_LTR; + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_R: + BreakFlags = KBTS_BREAK_FLAG_DIRECTION | KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION; + Direction = KBTS_DIRECTION_RTL; + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN: + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN: + // Digits are weak LTR, i.e. they do not influence the paragraph direction. + BreakFlags = KBTS_BREAK_FLAG_DIRECTION; + Direction = KBTS_DIRECTION_LTR; + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI: + // We've already checked the ParagraphDirection earlier, when coercing neutrals to L or R. + // If a neutral shows up here, it means that we did not find any way to resolve it to either direction. + // In this case, neutrals get the unresolved embedding direction. + BreakFlags = KBTS_BREAK_FLAG_DIRECTION; + break; + } + + if((BreakFlags & KBTS_BREAK_FLAG_DIRECTION) && + (Direction != *LastDirection)) + { + *LastDirection = Direction; + kbts__DoBreak(State, PositionOffset, KBTS_BREAK_FLAG_DIRECTION, Direction, 0, 0); + } + + if((BreakFlags & KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION) && + !State->ParagraphDirection) + { + kbts_s32 StartOfParagraphOffset = (kbts_s16)(State->ParagraphStartPosition - State->CurrentPosition); + kbts__DoBreak(State, StartOfParagraphOffset, KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION, 0, Direction, 0); + State->ParagraphDirection = (kbts_u8)Direction; + } +} + +static void kbts__BreakAddCodepoint(kbts_break_state *State, kbts_u32 Codepoint, kbts_u32 PositionIncrement, int MaybeEndOfText) +{ + // In these macros, and in FlagState, and in the way we buffer our state in general, + // index 0 means _after_ the codepoint currently being added, + // index 1 means _before_ the codepoint currently being added. +#define KBTS_BREAK(Flags, Position) do {FlagState |= ((Flags) << (8 * (Position)));} while(0) +#define KBTS_BREAK2(Flags, Position0, Position1) do {FlagState |= ((Flags) << (8 * (Position0))) | ((Flags) << (8 * (Position1)));} while(0) + + kbts_unicode_bidirectional_class BidirectionalClass = kbts__GetUnicodeBidirectionalClass(Codepoint); + kbts_u8 UnicodeFlags = kbts__GetUnicodeFlags(Codepoint); + kbts_u32 MatchingBracket = kbts__GetUnicodeMirrorCodepoint(Codepoint); + kbts_u8 GraphemeBreakClass = kbts__GetUnicodeGraphemeBreakClass(Codepoint); + kbts_u8 LineBreakClass = kbts__GetUnicodeLineBreakClass(Codepoint); + kbts_u8 WordBreakClass = kbts__GetUnicodeWordBreakClass(Codepoint); + kbts_u16 CodepointScriptExtension = kbts__GetUnicodeScriptExtension(Codepoint); + kbts_u32 CodepointScriptCount = (kbts_u32)kbts__ScriptExtensionCount(CodepointScriptExtension); + kbts_u32 CodepointScriptOffset = (kbts_u32)kbts__ScriptExtensionOffset(CodepointScriptExtension); + kbts_u8 *CodepointScripts = &kbts__ScriptExtensions[CodepointScriptOffset]; + kbts_u32 FlagState = State->FlagState << 8; + kbts_u8 LastLineBreakClass = State->LastLineBreakClass; + // Super secret cheat code for signaling end-of-text + int EndOfText = (Codepoint == 3) && MaybeEndOfText; + int StartOfText = !(State->Flags & KBTS_BREAK_STATE_FLAG_STARTED); + kbts_u32 LineBreakHistory = State->LineBreakHistory; + kbts_u32 WordBreakHistory = State->WordBreakHistory; + kbts_u8 LastWordBreakClass = State->LastWordBreakClass; + kbts_s16 WordBreak2PositionOffset = State->WordBreak2PositionOffset; + kbts_u8 LastWordBreakClassIncludingIgnored = State->LastWordBreakClassIncludingIgnored; + kbts_s16 PositionOffset2 = State->PositionOffset2; + kbts_s16 PositionOffset3 = State->PositionOffset3; + kbts_u32 Flags = State->Flags; + kbts_direction LastDirection = State->LastDirection; + kbts_u8 *ScriptSet = State->ScriptSet; + kbts_s16 ScriptPositionOffset = State->ScriptPositionOffset; + kbts_u32 ScriptCount = State->ScriptCount; + kbts_u32 ScriptCountAtBeginningOfUpdate = ScriptCount; + kbts_u8 BreakScript = ScriptSet[0]; + kbts__break_flush_flags FlushFlags = 0; + kbts_s16 Bidirectional1PositionOffset = State->Bidirectional1PositionOffset; + kbts_s16 Bidirectional2PositionOffset = State->Bidirectional2PositionOffset; + kbts_u8 Bidirectional2 = State->BidirectionalClass2; + kbts_u8 Bidirectional1 = State->BidirectionalClass1; + + if(StartOfText) + { + LineBreakHistory = LastLineBreakClass = KBTS_LINE_BREAK_CLASS_SOT; + WordBreakHistory = LastWordBreakClass = KBTS_WORD_BREAK_CLASS_SOT; + } + + // Bracket pairing overrides default directions/scripts. + if((UnicodeFlags & KBTS_UNICODE_FLAG_MIRRORED) == KBTS_UNICODE_FLAG_OPEN_BRACKET) + { + if(State->BracketCount < KBTS__ARRAY_LENGTH(State->Brackets)) + { + kbts_bracket *Bracket = &State->Brackets[State->BracketCount++]; + + // @Incomplete: Canonicalize the bracket. + Bracket->Codepoint = Codepoint; + Bracket->Position = State->CurrentPosition; + + // Unfortunately, because our script/direction breaks are arbitrary lookback now, + // we have to wait until DoBreak() to resolve these. + Bracket->Direction = KBTS_DIRECTION_DONT_KNOW; + Bracket->Script = KBTS_SCRIPT_DONT_KNOW; + + if(ScriptCount) + { + Bracket->Script = ScriptSet[0]; + } + + State->Flags |= KBTS_BREAK_STATE_FLAG_LAST_WAS_BRACKET; + } + } + else if((UnicodeFlags & KBTS_UNICODE_FLAG_MIRRORED) == KBTS_UNICODE_FLAG_CLOSE_BRACKET) + { + if(State->BracketCount) + { + kbts_un FoundBracketIndex = 0; + kbts_bracket *FoundBracket = 0; + + // @Incomplete: Canonicalize the bracket. + KBTS__FOR(BracketIndex, 0, State->BracketCount) + { + kbts_bracket *Bracket = &State->Brackets[State->BracketCount - 1 - BracketIndex]; + + if(Bracket->Codepoint == MatchingBracket) + { + FoundBracket = Bracket; + FoundBracketIndex = State->BracketCount - 1 - BracketIndex; + + break; + } + } + + if(FoundBracket) + { + // In case the bracket hasn't been resolved yet, take the current values. + kbts_u8 BracketScript = FoundBracket->Script; + kbts_u8 BracketDirection = FoundBracket->Direction; + + if(!BracketScript && ScriptCount) + { + BracketScript = ScriptSet[0]; + } + + if(!BracketDirection) + { + BracketDirection = (kbts_u8)LastDirection; + } + + if(BracketDirection == KBTS_DIRECTION_LTR) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_L; + } + else if(BracketDirection == KBTS_DIRECTION_RTL) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_R; + } + + BidirectionalClass = FoundBracket->Direction; + CodepointScriptCount = 1; + CodepointScriptOffset = BracketScript; + + State->BracketCount = (kbts_u32)FoundBracketIndex; + } + } + } + + // Script breaking. + if(EndOfText) + { + FlushFlags |= KBTS__BREAK_FLUSH_FLAG_SCRIPT; + } + + if(CodepointScriptCount < 2) + { + // We special case this entire path because, supposedly, this is the common case. + kbts_u8 CodepointScript = (kbts_u8)CodepointScriptOffset; + + if((CodepointScript == KBTS_SCRIPT_DONT_KNOW) || + (CodepointScript == KBTS_SCRIPT_DEFAULT) || + (CodepointScript == KBTS_SCRIPT_DEFAULT2)) + { + // Nothing to do. + } + else + { + kbts_u32 ScriptSetMatch = 0; + KBTS__FOR(ScriptIndex, 0, ScriptCount) + { + ScriptSetMatch |= (ScriptSet[ScriptIndex] == CodepointScript); + } + + if(!ScriptSetMatch) + { + FlushFlags |= KBTS__BREAK_FLUSH_FLAG_SCRIPT; + } + + ScriptCount = 1; + ScriptSet[0] = CodepointScript; + } + } + else + { + // Refine the script set. + kbts_un NewScriptCount = 0; + + { + kbts_un CodepointScriptIndex = 0; + kbts_un ScriptIndex = 0; + + while((ScriptIndex < ScriptCount) && + (CodepointScriptIndex < CodepointScriptCount)) + { + kbts_u8 CodepointScript = CodepointScripts[CodepointScriptIndex]; + kbts_u8 Script = ScriptSet[ScriptIndex]; + + if(CodepointScript < Script) + { + CodepointScriptIndex += 1; + } + else if(Script < CodepointScript) + { + ScriptIndex += 1; + } + else + { + ScriptSet[NewScriptCount++] = Script; + + CodepointScriptIndex += 1; + ScriptIndex += 1; + } + } + } + + if(!NewScriptCount) + { + FlushFlags |= KBTS__BREAK_FLUSH_FLAG_SCRIPT; + + KBTS__FOR(CodepointScriptIndex, 0, CodepointScriptCount) + { + ScriptSet[CodepointScriptIndex] = CodepointScripts[CodepointScriptIndex]; + } + ScriptCount = (kbts_u32)CodepointScriptCount; + } + else + { + ScriptCount = (kbts_u32)NewScriptCount; + } + } + + // Direction breaking. + if(EndOfText) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI; + } + + if(BidirectionalClass != KBTS_UNICODE_BIDIRECTIONAL_CLASS_BN) // Formatting characters should be ignored. + { + switch(BidirectionalClass) + { + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_NSM: BidirectionalClass = Bidirectional1; break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_L: + Flags &= ~(KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L | KBTS_BREAK_STATE_FLAG_SAW_AL_AFTER_LR); + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_R: + Flags |= KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L; + Flags &= ~KBTS_BREAK_STATE_FLAG_SAW_AL_AFTER_LR; + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_AL: + // Rule W3 occurs before W7, so we treat AL as R for the purposes of rule W7. + Flags |= (KBTS_BREAK_STATE_FLAG_SAW_AL_AFTER_LR | KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L); + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_R; + break; + + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN: + if(Flags & KBTS_BREAK_STATE_FLAG_SAW_AL_AFTER_LR) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN; + goto CaseAn; + } + if((Bidirectional2 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN) && + ((Bidirectional1 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_ES) || + (Bidirectional1 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_CS))) + { + Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN; + } + + // We test State->ParagraphDirection here because we do not want + // digits to coerce to L when the paragrpah direction is unknown. + // It might be cleaner to explicitly store the last strong direction seen, + // with DONT_KNOW as an option. + // @Cleanup + if(State->ParagraphDirection && + !(Flags & KBTS_BREAK_STATE_FLAG_SAW_R_AFTER_L)) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_L; + } + break; + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN: + CaseAn:; + if((Bidirectional2 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN) && + (Bidirectional1 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_CS)) + { + Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN; + } + break; + case KBTS_UNICODE_BIDIRECTIONAL_CLASS_ET: + if(Bidirectional1 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN) + { + BidirectionalClass = KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN; + } + break; + } + + // This rule has a lower priority than AN CS AN -> AN AN AN, so we have to wait until slot 1 to apply it. + if(KBTS__IN_SET(Bidirectional1, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_ET) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_ES) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_CS)))) + { + Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI; + } + + if(Bidirectional1 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI) + { + if(KBTS__IN_SET(BidirectionalClass, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_NI) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_ET) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_ES) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_CS)))) + { + // All of these input classes end up resolving to NI later on anyway if they are preceded by NI. + // We are in a situation where: + // - We have an NI in slot 1 + // - The direction in slot 0 will eventually resolve to NI due to the NI in slot 1 + // - Storing multiple NIs in our shift buffer is redundant, because no rule necessitates multiple NIs + // - NIs don't interact with anything, except that they resolve when surrounded by strong characters + // - NIs are resolved in groups. As per the Unicode specification: + // N1. A sequence of NIs takes the direction of the surrounding strong text if the text on both + // sides has the same direction. + // This means we can merge the current bidirectional class with the preceding NI, bump the offset, + // and it just works. + goto SkipDirectionBreak; + } + else if(((Bidirectional2 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_R) || + (BidirectionalClass == KBTS_UNICODE_BIDIRECTIONAL_CLASS_R)) && + KBTS__IN_SET(Bidirectional2, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_R) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN))) && + KBTS__IN_SET(BidirectionalClass, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_R) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN)))) + { + // Note that the way we resolve digits is different from the way the Unicode standard specifies it. + // This is because the standard assumes the paragraph direction is always known, whereas in our case it isn't. + // We want neutral surrounded by uncoerced digits to resolve to the paragraph direction, which may be DONT_KNOW. + Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_R; + } + else if(((Bidirectional2 == KBTS_UNICODE_BIDIRECTIONAL_CLASS_L) || + (BidirectionalClass == KBTS_UNICODE_BIDIRECTIONAL_CLASS_L)) && + KBTS__IN_SET(Bidirectional2, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_L) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN))) && + KBTS__IN_SET(BidirectionalClass, KBTS__SET32((KBTS_UNICODE_BIDIRECTIONAL_CLASS_L) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_AN) + (KBTS_UNICODE_BIDIRECTIONAL_CLASS_EN)))) + { + Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_L; + } + else + { + if (State->ParagraphDirection == KBTS_DIRECTION_LTR) Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_L; + else if(State->ParagraphDirection == KBTS_DIRECTION_RTL) Bidirectional1 = KBTS_UNICODE_BIDIRECTIONAL_CLASS_R; + } + } + + FlushFlags |= KBTS__BREAK_FLUSH_FLAG_DIRECTION_2; + if(EndOfText) + { + FlushFlags |= KBTS__BREAK_FLUSH_FLAG_DIRECTION_1; + } + } + else + { + SkipDirectionBreak:; + State->Bidirectional2PositionOffset -= (kbts_s16)PositionIncrement; + State->Bidirectional1PositionOffset -= (kbts_s16)PositionIncrement; + } + + { // Grapheme breaking. + if(EndOfText && !StartOfText) + { + KBTS_BREAK(KBTS_BREAK_FLAG_GRAPHEME, 1); + State->GraphemeBreakState = KBTS_GRAPHEME_BREAK_STATE_START; + } + else + { + kbts_u8 GraphemeBreakState = kbts_GraphemeBreakTransition[GraphemeBreakClass][State->GraphemeBreakState]; + switch(GraphemeBreakState) + { + case KBTS_GRAPHEME_BREAK_STATE_b01: KBTS_BREAK2(KBTS_BREAK_FLAG_GRAPHEME, 1, 0); GraphemeBreakState = KBTS_GRAPHEME_BREAK_STATE_START; break; + case KBTS_GRAPHEME_BREAK_STATE_b0: KBTS_BREAK(KBTS_BREAK_FLAG_GRAPHEME, 0); GraphemeBreakState = KBTS_GRAPHEME_BREAK_STATE_START; break; + + case KBTS_GRAPHEME_BREAK_STATE_b1: + case KBTS_GRAPHEME_BREAK_STATE_b1toCR: + case KBTS_GRAPHEME_BREAK_STATE_b1toL: + case KBTS_GRAPHEME_BREAK_STATE_b1toLVxV: + case KBTS_GRAPHEME_BREAK_STATE_b1toLVTxT: + case KBTS_GRAPHEME_BREAK_STATE_b1toIndicConsonantxIndicLinker: + case KBTS_GRAPHEME_BREAK_STATE_PADDING0: // Padding values are just here to help the compiler. + case KBTS_GRAPHEME_BREAK_STATE_PADDING1: + case KBTS_GRAPHEME_BREAK_STATE_b1toExtendedPictographic: + case KBTS_GRAPHEME_BREAK_STATE_PADDING2: + case KBTS_GRAPHEME_BREAK_STATE_PADDING3: + case KBTS_GRAPHEME_BREAK_STATE_b1toRI: + case KBTS_GRAPHEME_BREAK_STATE_b1toSKIP: + KBTS_BREAK(KBTS_BREAK_FLAG_GRAPHEME, 1); + GraphemeBreakState -= KBTS_GRAPHEME_BREAK_STATE_b1; + } + + State->GraphemeBreakState = GraphemeBreakState; + } + } + + // Word breaks. + // We buffer 3 characters for word breaks. + // Each character gets 3 bits (padded to 4) representing 3 levels of priority. + #define KBTS_WORD_BREAK_BITS(Priority, Position) (((1 << ((Priority) + 1)) - 1) << ((Position) * 4)) + #define KBTS_C2(A, B) case (KBTS_WORD_BREAK_CLASS_##A << 8) | (KBTS_WORD_BREAK_CLASS_##B) + #define KBTS_C3(A, B, C) case (KBTS_WORD_BREAK_CLASS_##A << 16) | (KBTS_WORD_BREAK_CLASS_##B << 8) | (KBTS_WORD_BREAK_CLASS_##C) + + // Ignore [EX FO ZWJ] after ^[_sot_ CR LF NL]. + // @Cleanup: This is the only time we explicitly use EX and FO. They can be merged. + if(KBTS__IN_SET(WordBreakClass, KBTS__SET32((KBTS_WORD_BREAK_CLASS_EX)(KBTS_WORD_BREAK_CLASS_FO)(KBTS_WORD_BREAK_CLASS_ZWJ))) && + !KBTS__IN_SET(LastWordBreakClass, KBTS__SET32((KBTS_WORD_BREAK_CLASS_SOT)(KBTS_WORD_BREAK_CLASS_CR)(KBTS_WORD_BREAK_CLASS_LF)(KBTS_WORD_BREAK_CLASS_NL)))) + { + WordBreak2PositionOffset -= (kbts_s16)PositionIncrement; + State->WordBreak2PositionOffset = WordBreak2PositionOffset; + } + else + { + kbts_u32 WordBreaks = State->WordBreaks << 4; + kbts_u32 WordUnbreaks = State->WordUnbreaks << 4; + WordBreakHistory = (WordBreakHistory << 8) | WordBreakClass; + + WordBreaks |= KBTS_WORD_BREAK_BITS(0, 1) | KBTS_WORD_BREAK_BITS(0, 0); + if(StartOfText) + { + WordBreaks |= KBTS_WORD_BREAK_BITS(2, 1); + } + + if(KBTS__IN_SET(WordBreakClass, KBTS__SET32((KBTS_WORD_BREAK_CLASS_CR)(KBTS_WORD_BREAK_CLASS_LF)(KBTS_WORD_BREAK_CLASS_NL)))) + { + WordBreaks |= KBTS_WORD_BREAK_BITS(1, 1) | KBTS_WORD_BREAK_BITS(1, 0); + } + else if(KBTS__IN_SET(WordBreakClass, KBTS__SET32((KBTS_WORD_BREAK_CLASS_Oep)(KBTS_WORD_BREAK_CLASS_ALep)))) + { + // ZWJ x {Extended_Pictographic} + if(LastWordBreakClassIncludingIgnored == KBTS_WORD_BREAK_CLASS_ZWJ) + { + WordUnbreaks |= KBTS_WORD_BREAK_BITS(0, 1); + } + } + + switch(WordBreakHistory & 0xFFFF) + { + KBTS_C2(CR, LF): WordUnbreaks |= KBTS_WORD_BREAK_BITS(1, 1); break; + + KBTS_C2(WSS, WSS): + // WSS x WSS is a special rule, because it is supposed to happen _before_ ignores. + if(WordBreak2PositionOffset >= 0) WordUnbreaks |= KBTS_WORD_BREAK_BITS(0, 1); + break; + + // (RI RI)* RI x RI + KBTS_C2(RI, RI): + WordBreakHistory = 0; + // fallthrough + KBTS_C2(HL, SQ): + KBTS_C2(ALnep, ALnep): KBTS_C2(ALnep, ALep): KBTS_C2(ALnep, HL): KBTS_C2(ALnep, NM): KBTS_C2(ALnep, ENL): + KBTS_C2(ALep, ALnep): KBTS_C2(ALep, ALep): KBTS_C2(ALep, HL): KBTS_C2(ALep, NM): KBTS_C2(ALep, ENL): + KBTS_C2(HL, ALnep): KBTS_C2(HL, ALep): KBTS_C2(HL, HL): KBTS_C2(HL, NM): KBTS_C2(HL, ENL): + KBTS_C2(NM, ALnep): KBTS_C2(NM, ALep): KBTS_C2(NM, HL): KBTS_C2(NM, NM): KBTS_C2(NM, ENL): + KBTS_C2(KA, KA): KBTS_C2(KA, ENL): + KBTS_C2(ENL, ALnep): KBTS_C2(ENL, ALep): KBTS_C2(ENL, HL): KBTS_C2(ENL, NM): KBTS_C2(ENL, KA): KBTS_C2(ENL, ENL): + WordUnbreaks |= KBTS_WORD_BREAK_BITS(0, 1); break; + } + + switch(WordBreakHistory & 0xFFFFFF) + { + KBTS_C3(ALnep, ML, ALnep): KBTS_C3(ALnep, ML, ALep): KBTS_C3(ALnep, ML, HL): + KBTS_C3(ALnep, MNL, ALnep): KBTS_C3(ALnep, MNL, ALep): KBTS_C3(ALnep, MNL, HL): + KBTS_C3(ALnep, SQ, ALnep): KBTS_C3(ALnep, SQ, ALep): KBTS_C3(ALnep, SQ, HL): + KBTS_C3(ALep, ML, ALnep): KBTS_C3(ALep, ML, ALep): KBTS_C3(ALep, ML, HL): + KBTS_C3(ALep, MNL, ALnep): KBTS_C3(ALep, MNL, ALep): KBTS_C3(ALep, MNL, HL): + KBTS_C3(ALep, SQ, ALnep): KBTS_C3(ALep, SQ, ALep): KBTS_C3(ALep, SQ, HL): + KBTS_C3(HL, ML, ALnep): KBTS_C3(HL, ML, ALep): KBTS_C3(HL, ML, HL): + KBTS_C3(HL, MNL, ALnep): KBTS_C3(HL, MNL, ALep): KBTS_C3(HL, MNL, HL): + KBTS_C3(HL, SQ, ALnep): KBTS_C3(HL, SQ, ALep): KBTS_C3(HL, SQ, HL): + KBTS_C3(HL, DQ, HL): + KBTS_C3(NM, MN, NM): KBTS_C3(NM, MNL, NM): KBTS_C3(NM, SQ, NM): + WordUnbreaks |= KBTS_WORD_BREAK_BITS(0, 1) | KBTS_WORD_BREAK_BITS(0, 2); break; + } + + kbts_u32 EffectiveWordBreaks = WordBreaks & ~WordUnbreaks; + if(EffectiveWordBreaks & KBTS_WORD_BREAK_BITS(2, 2)) + { + kbts__DoBreak(State, PositionOffset2 + WordBreak2PositionOffset, KBTS_BREAK_FLAG_WORD, 0, 0, 0); + } + if(EndOfText) + { + // Always break at the end of the text. + KBTS_BREAK(KBTS_BREAK_FLAG_WORD, 1); + // Do not break after the end of the text. + } + + State->WordBreaks = (kbts_u16)WordBreaks; + State->WordUnbreaks = (kbts_u16)WordUnbreaks; + State->LastWordBreakClass = WordBreakClass; + State->WordBreak2PositionOffset = 0; + State->WordBreakHistory = WordBreakHistory; + } + State->LastWordBreakClassIncludingIgnored = WordBreakClass; + #undef KBTS_WORD_BREAK_BITS + #undef KBTS_C2 + #undef KBTS_C3 + + kbts_s16 LineBreak3PositionOffset = State->LineBreak3PositionOffset; + kbts_s16 LineBreak2PositionOffset = State->LineBreak2PositionOffset; + int HardLineBreak = 0; + { // Line breaking. + kbts_u64 LineBreaks = State->LineBreaks << 16; + kbts_u64 LineUnbreaks = State->LineUnbreaks << 16; + kbts_u64 LineUnbreaksAsync = State->LineUnbreaksAsync << 16; + + #define KBTS_C1(A) case KBTS_LINE_BREAK_CLASS_##A + #define KBTS_C2(A, B) case (KBTS_LINE_BREAK_CLASS_##A << 8) | (KBTS_LINE_BREAK_CLASS_##B) + #define KBTS_C3(A, B, C) case (KBTS_LINE_BREAK_CLASS_##A << 16) | (KBTS_LINE_BREAK_CLASS_##B << 8) | KBTS_LINE_BREAK_CLASS_##C + #define KBTS_C4(A, B, C, D) case (KBTS_LINE_BREAK_CLASS_##A << 24) | (KBTS_LINE_BREAK_CLASS_##B << 16) | (KBTS_LINE_BREAK_CLASS_##C << 8) | KBTS_LINE_BREAK_CLASS_##D + #define KBTS_REQUIRED_LINE_BREAK(Priority, Position) do {LineBreaks |= (kbts_u64)KBTS__LINE_BREAK_REQUIRED##Priority << ((Position) * 16);} while(0) + #define KBTS_LINE_BREAK(Priority, Position) do {LineBreaks |= (kbts_u64)KBTS__LINE_BREAK_ALLOWED##Priority << ((Position) * 16);} while(0) + #define KBTS_LINE_UNBREAK(Priority, Position) do {LineUnbreaks |= (kbts_u64)KBTS__LINE_BREAK_REQUIRED##Priority << ((Position) * 16);} while(0) + #define KBTS_LINE_UNBREAK_ASYNC(Priority, Position) do {LineUnbreaksAsync |= (kbts_u64)KBTS__LINE_BREAK_REQUIRED##Priority << ((Position) * 16);} while(0) + + if(EndOfText) + { + // Depending on the current line break state, we might need very different breaks. + // For now, we copy the transitions from the first row of the transition table, but + // we might want to special-case these. + LineBreakClass = KBTS_LINE_BREAK_CLASS_Onea; + } + else if(LineBreakClass > KBTS_LINE_BREAK_CLASS_COUNT) + { + // These guys have special rules. + if((LineBreakClass == KBTS_LINE_BREAK_CLASS_CM) || (LineBreakClass == KBTS_LINE_BREAK_CLASS_ZWJ)) + { + if(LineBreakClass == KBTS_LINE_BREAK_CLASS_ZWJ) + { + KBTS_LINE_UNBREAK_ASYNC(3, 0); + } + + switch(LastLineBreakClass) + { + case KBTS_LINE_BREAK_CLASS_SOT: + case KBTS_LINE_BREAK_CLASS_BK: + case KBTS_LINE_BREAK_CLASS_CR: + case KBTS_LINE_BREAK_CLASS_LF: + case KBTS_LINE_BREAK_CLASS_NL: + case KBTS_LINE_BREAK_CLASS_SP: + case KBTS_LINE_BREAK_CLASS_ZW: + LineBreakClass = KBTS_LINE_BREAK_CLASS_ALnea; + break; + + default: + // The standard says to treat X [CM ZWJ]* as X. + // This means that we need to hoist [CM ZWJ] completely out of the line breaking logic. + // However, we give our results in index offsets relative to the current glyph, so we + // do have to acknowledge that we are skipping glyphs. + goto LineBreakAbsorbCharacter; + } + } + else if(LineBreakClass == KBTS_LINE_BREAK_CLASS_CJ) + { + LineBreakClass = (kbts_u8)((State->JapaneseLineBreakStyle == KBTS_JAPANESE_LINE_BREAK_STYLE_STRICT) ? KBTS_LINE_BREAK_CLASS_NSea : KBTS_LINE_BREAK_CLASS_IDea); + } + } + + if(LastLineBreakClass == LineBreakClass) + { + // @Incomplete: Handle repeats that aren't SP*. + if(LineBreakClass == KBTS_LINE_BREAK_CLASS_SP) + { + goto LineBreakAbsorbCharacter; + } + } + + LineBreakHistory = (LineBreakHistory << 8) | LineBreakClass; + + if(EndOfText && (State->ConfigFlags & KBTS_BREAK_CONFIG_FLAG_END_OF_TEXT_GENERATES_HARD_LINE_BREAK)) + { + // Always break at the end of text. + KBTS_REQUIRED_LINE_BREAK(5, 1); + + // x QUPf _eot_ + if((LineBreakHistory & 0xFF00) == (KBTS_LINE_BREAK_CLASS_QUPf << 8)) + { + KBTS_LINE_UNBREAK(3, 2); + } + } + + KBTS_LINE_BREAK(0, 0); + KBTS_LINE_BREAK(0, 1); + + switch(LineBreakClass) + { + KBTS_C1(BK): + KBTS_C1(CR): + KBTS_C1(LF): + KBTS_C1(NL): + { + KBTS_LINE_UNBREAK(4, 1); + + // This is the only place that's not the end of text where we generate hard line breaks. + // When we see a hard line break, we want to reset the direction/script state, so that + // we generate new direction/script breaks for the new paragraph. + FlushFlags |= (KBTS__BREAK_FLUSH_FLAG_SCRIPT | + KBTS__BREAK_FLUSH_FLAG_DIRECTION_2 | + KBTS__BREAK_FLUSH_FLAG_DIRECTION_1 | + KBTS__BREAK_FLUSH_FLAG_DIRECTION_PARAGRAPH); + ScriptCount = 0; + HardLineBreak = 1; + + KBTS_REQUIRED_LINE_BREAK(5, 0); + } break; + + KBTS_C1(ZW): KBTS_LINE_BREAK(4, 0); KBTS_LINE_UNBREAK(4, 1); break; + KBTS_C1(BB): KBTS_LINE_UNBREAK(0, 0); break; + + KBTS_C1(GLea): + KBTS_C1(GLnea): + KBTS_C1(OPea): + KBTS_C1(OPnea): KBTS_LINE_UNBREAK(3, 0); break; + + KBTS_C1(WJ): KBTS_LINE_UNBREAK(3, 0); KBTS_LINE_UNBREAK(3, 1); break; + + KBTS_C1(CLea): + KBTS_C1(CLnea): + KBTS_C1(CPea): + KBTS_C1(CPnea): + KBTS_C1(EXea): + KBTS_C1(EXnea): + KBTS_C1(SY): KBTS_LINE_UNBREAK(3, 1); break; + + KBTS_C1(IS): KBTS_LINE_UNBREAK(2, 1); break; + + KBTS_C1(SP): KBTS_LINE_UNBREAK(4, 1); KBTS_LINE_BREAK(2, 0); break; + + KBTS_C1(QU): KBTS_LINE_UNBREAK(1, 1); KBTS_LINE_UNBREAK(1, 0); break; + KBTS_C1(QUPi): KBTS_LINE_UNBREAK(1, 0); break; + KBTS_C1(QUPf): KBTS_LINE_UNBREAK(1, 1); break; + KBTS_C1(CB): KBTS_LINE_BREAK(1, 0); KBTS_LINE_BREAK(1, 1); break; + + KBTS_C1(BAnea): + KBTS_C1(BAea): + KBTS_C1(HYPHEN): + KBTS_C1(HY): + KBTS_C1(NSnea): + KBTS_C1(NSea): + KBTS_C1(INnea): + KBTS_C1(INea): + KBTS_LINE_UNBREAK(0, 1); break; + } + + switch(LineBreakHistory & 0xFFFF) + { + KBTS_C2(CR, LF): KBTS_LINE_UNBREAK(5, 1); break; + KBTS_C2(ZW, SP): KBTS_LINE_BREAK(4, 0); break; + + + KBTS_C2(OPea, QUPi): + KBTS_C2(GLea, QUPi): + KBTS_C2(OPea, SP): + KBTS_C2(OPnea,SP): + KBTS_LINE_UNBREAK(3, 0); + break; + + KBTS_C2(SOT, QUPi): + KBTS_C2(BK, QUPi): + KBTS_C2(CR, QUPi): + KBTS_C2(LF, QUPi): + KBTS_C2(NL, QUPi): + KBTS_C2(SP, QUPi): + KBTS_C2(ZW, QUPi): + KBTS_C2(GLnea, QUPi): + KBTS_C2(QU, QUPi): + KBTS_C2(OPnea, QUPi): + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + KBTS_LINE_UNBREAK(3, 0); + break; + + KBTS_C2(QUPi, QUPi): + KBTS_LINE_UNBREAK(3, 0); + KBTS_LINE_UNBREAK(1, 2); + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + break; + + KBTS_C2(QUPf, QUPi): + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + KBTS_LINE_UNBREAK(3, 0); + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(1, 1); + break; + + KBTS_C2(QUPf, GLnea): + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(3, 1); + KBTS_LINE_UNBREAK(1, 1); + break; + + KBTS_C2(QUPf, BK): + KBTS_C2(QUPf, CR): + KBTS_C2(QUPf, LF): + KBTS_C2(QUPf, NL): + KBTS_C2(QUPf, ZW): + KBTS_C2(QUPf, WJ): + KBTS_C2(QUPf, CLnea): + KBTS_C2(QUPf, CPnea): + KBTS_C2(QUPf, EXnea): + KBTS_C2(QUPf, SY): + KBTS_C2(QUPf, IS): + KBTS_C2(QUPf, SP): + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(1, 1); + break; + + KBTS_C2(QUPf, QUPf): + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + break; + + KBTS_C2(QUPf, QU): + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + break; + + KBTS_C2(QUPf, GLea): + KBTS_LINE_UNBREAK(3, 2); + KBTS_LINE_UNBREAK(3, 1); + break; + + KBTS_C2(QUPf, CPea): + KBTS_C2(QUPf, CLea): + KBTS_C2(QUPf, EXea): + KBTS_LINE_UNBREAK(3, 2); + break; + + KBTS_C2(QUPi, QU): + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + KBTS_LINE_UNBREAK(1, 2); + break; + + KBTS_C2(QUPi, QUPf): + KBTS_LINE_UNBREAK(1, 1); + KBTS_LINE_UNBREAK(1, 0); + KBTS_LINE_UNBREAK(1, 2); + break; + + KBTS_C2(QUPi, GLnea): + KBTS_LINE_UNBREAK(1, 2); + KBTS_LINE_UNBREAK(3, 1); + break; + + KBTS_C2(QUPi, Onea): KBTS_C2(QUPi, Ope): KBTS_C2(QUPi, BK): KBTS_C2(QUPi, CR): KBTS_C2(QUPi, LF): KBTS_C2(QUPi, NL): KBTS_C2(QUPi, SP): KBTS_C2(QUPi, ZW): + KBTS_C2(QUPi, WJ): KBTS_C2(QUPi, CLnea): KBTS_C2(QUPi, CPnea): KBTS_C2(QUPi, EXnea): KBTS_C2(QUPi, SY): KBTS_C2(QUPi, BAnea): + KBTS_C2(QUPi, OPnea): KBTS_C2(QUPi, IS): KBTS_C2(QUPi, NSnea): KBTS_C2(QUPi, B2): KBTS_C2(QUPi, CB): + KBTS_C2(QUPi, HY): KBTS_C2(QUPi, HYPHEN): KBTS_C2(QUPi, INnea): KBTS_C2(QUPi, BB): KBTS_C2(QUPi, HL): KBTS_C2(QUPi, ALnea): KBTS_C2(QUPi, NU): KBTS_C2(QUPi, PRnea): + KBTS_C2(QUPi, IDnea): KBTS_C2(QUPi, IDpe): KBTS_C2(QUPi, EBnea): KBTS_C2(QUPi, POnea): KBTS_C2(QUPi, JV): KBTS_C2(QUPi, JT): KBTS_C2(QUPi, AP): KBTS_C2(QUPi, AK): + KBTS_C2(QUPi, DOTTED_CIRCLE): KBTS_C2(QUPi, AS): KBTS_C2(QUPi, VF): KBTS_C2(QUPi, VI): KBTS_C2(QUPi, RI): + KBTS_LINE_UNBREAK(1, 2); break; + + + KBTS_C2(QUPf, Onea): KBTS_C2(QUPf, Ope): + KBTS_C2(QUPf, BAnea): + KBTS_C2(QUPf, OPnea): KBTS_C2(QUPf, NSnea): KBTS_C2(QUPf, B2): KBTS_C2(QUPf, CB): + KBTS_C2(QUPf, HY): KBTS_C2(QUPf, HYPHEN): KBTS_C2(QUPf, INnea): KBTS_C2(QUPf, BB): KBTS_C2(QUPf, HL): KBTS_C2(QUPf, ALnea): KBTS_C2(QUPf, NU): KBTS_C2(QUPf, PRnea): + KBTS_C2(QUPf, IDnea): KBTS_C2(QUPf, IDpe): KBTS_C2(QUPf, EBnea): KBTS_C2(QUPf, POnea): KBTS_C2(QUPf, JV): KBTS_C2(QUPf, JT): KBTS_C2(QUPf, AP): KBTS_C2(QUPf, AK): + KBTS_C2(QUPf, DOTTED_CIRCLE): KBTS_C2(QUPf, AS): KBTS_C2(QUPf, VF): KBTS_C2(QUPf, VI): KBTS_C2(QUPf, RI): + KBTS_LINE_UNBREAK(1, 1); break; + + KBTS_C2(SOT, QU): KBTS_C2(SOT, QUPf): + KBTS_C2(Onea, QU): KBTS_C2(Ope, QU): KBTS_C2(BK, QU): KBTS_C2(CR, QU): KBTS_C2(LF, QU): KBTS_C2(NL, QU): KBTS_C2(SP, QU): KBTS_C2(ZW, QU): + KBTS_C2(WJ, QU): KBTS_C2(GLnea, QU): KBTS_C2(CLnea, QU): KBTS_C2(CPnea, QU): KBTS_C2(EXnea, QU): KBTS_C2(SY, QU): KBTS_C2(BAnea, QU): + KBTS_C2(OPnea, QU): KBTS_C2(QU, QU): KBTS_C2(IS, QU): KBTS_C2(NSnea, QU): KBTS_C2(B2, QU): KBTS_C2(CB, QU): + KBTS_C2(HY, QU): KBTS_C2(HYPHEN, QU): KBTS_C2(INnea, QU): KBTS_C2(BB, QU): KBTS_C2(HL, QU): KBTS_C2(ALnea, QU): KBTS_C2(NU, QU): KBTS_C2(PRnea, QU): + KBTS_C2(IDnea, QU): KBTS_C2(IDpe, QU): KBTS_C2(EBnea, QU): KBTS_C2(POnea, QU): KBTS_C2(JV, QU): KBTS_C2(JT, QU): KBTS_C2(AP, QU): KBTS_C2(AK, QU): + KBTS_C2(DOTTED_CIRCLE, QU): KBTS_C2(AS, QU): KBTS_C2(VF, QU): KBTS_C2(VI, QU): KBTS_C2(RI, QU): + KBTS_C2(Onea, QUPi): KBTS_C2(Ope, QUPi): + KBTS_C2(WJ, QUPi): KBTS_C2(CLnea, QUPi): KBTS_C2(CPnea, QUPi): KBTS_C2(EXnea, QUPi): KBTS_C2(SY, QUPi): KBTS_C2(BAnea, QUPi): + KBTS_C2(IS, QUPi): + KBTS_C2(NSnea, QUPi): + KBTS_C2(B2, QUPi): + KBTS_C2(CB, QUPi): + KBTS_C2(HY, QUPi): KBTS_C2(HYPHEN, QUPi): KBTS_C2(INnea, QUPi): KBTS_C2(BB, QUPi): KBTS_C2(HL, QUPi): KBTS_C2(ALnea, QUPi): KBTS_C2(NU, QUPi): KBTS_C2(PRnea, QUPi): + KBTS_C2(IDnea, QUPi): KBTS_C2(IDpe, QUPi): KBTS_C2(EBnea, QUPi): KBTS_C2(POnea, QUPi): KBTS_C2(JV, QUPi): KBTS_C2(JT, QUPi): KBTS_C2(AP, QUPi): KBTS_C2(AK, QUPi): + KBTS_C2(DOTTED_CIRCLE, QUPi): KBTS_C2(AS, QUPi): KBTS_C2(VF, QUPi): KBTS_C2(VI, QUPi): KBTS_C2(RI, QUPi): + KBTS_C2(Onea, QUPf): KBTS_C2(Ope, QUPf): KBTS_C2(BK, QUPf): KBTS_C2(CR, QUPf): KBTS_C2(LF, QUPf): KBTS_C2(NL, QUPf): KBTS_C2(SP, QUPf): KBTS_C2(ZW, QUPf): + KBTS_C2(WJ, QUPf): KBTS_C2(GLnea, QUPf): KBTS_C2(CLnea, QUPf): KBTS_C2(CPnea, QUPf): KBTS_C2(EXnea, QUPf): KBTS_C2(SY, QUPf): KBTS_C2(BAnea, QUPf): + KBTS_C2(OPnea, QUPf): KBTS_C2(QU, QUPf): KBTS_C2(IS, QUPf): KBTS_C2(NSnea, QUPf): KBTS_C2(B2, QUPf): KBTS_C2(CB, QUPf): + KBTS_C2(HY, QUPf): KBTS_C2(HYPHEN, QUPf): KBTS_C2(INnea, QUPf): KBTS_C2(BB, QUPf): KBTS_C2(HL, QUPf): KBTS_C2(ALnea, QUPf): KBTS_C2(NU, QUPf): KBTS_C2(PRnea, QUPf): + KBTS_C2(IDnea, QUPf): KBTS_C2(IDpe, QUPf): KBTS_C2(EBnea, QUPf): KBTS_C2(POnea, QUPf): KBTS_C2(JV, QUPf): KBTS_C2(JT, QUPf): KBTS_C2(AP, QUPf): KBTS_C2(AK, QUPf): + KBTS_C2(DOTTED_CIRCLE, QUPf): KBTS_C2(AS, QUPf): KBTS_C2(VF, QUPf): KBTS_C2(VI, QUPf): KBTS_C2(RI, QUPf): + KBTS_LINE_UNBREAK(1, 1); KBTS_LINE_UNBREAK(1, 0); break; + + KBTS_C2(HL, NU): KBTS_C2(ALnea, NU): KBTS_C2(ALea, NU): KBTS_C2(DOTTED_CIRCLE, NU): + KBTS_C2(NU, ALnea): KBTS_C2(NU, ALea): KBTS_C2(NU, DOTTED_CIRCLE): KBTS_C2(NU, HL): + KBTS_C2(PRnea, IDnea): KBTS_C2(PRnea, IDea): KBTS_C2(PRnea, IDpe): KBTS_C2(PRnea, EBea): KBTS_C2(PRnea, EBnea): KBTS_C2(PRnea, EM): + KBTS_C2(PRea, IDnea): KBTS_C2(PRea, IDea): KBTS_C2(PRea, IDpe): KBTS_C2(PRea, EBea): KBTS_C2(PRea, EBnea): KBTS_C2(PRea, EM): + KBTS_C2(IDnea, POea): KBTS_C2(IDnea, POnea): KBTS_C2(IDea, POea): KBTS_C2(IDea, POnea): KBTS_C2(IDpe, POea): KBTS_C2(IDpe, POnea): + KBTS_C2(EBnea, POea): KBTS_C2(EBnea, POnea): KBTS_C2(EBea, POea): KBTS_C2(EBea, POnea): KBTS_C2(EM, POea): KBTS_C2(EM, POnea): + KBTS_C2(PRea, ALea): KBTS_C2(PRea, ALnea): KBTS_C2(PRea, DOTTED_CIRCLE): KBTS_C2(PRea, HL): + KBTS_C2(PRnea, ALea): KBTS_C2(PRnea, ALnea): KBTS_C2(PRnea, DOTTED_CIRCLE): KBTS_C2(PRnea, HL): + KBTS_C2(POea, ALea): KBTS_C2(POea, ALnea): KBTS_C2(POea, DOTTED_CIRCLE): KBTS_C2(POea, HL): + KBTS_C2(POnea, ALea): KBTS_C2(POnea, ALnea): KBTS_C2(POnea, DOTTED_CIRCLE): KBTS_C2(POnea, HL): + KBTS_C2(ALea, PRea): KBTS_C2(ALea, PRnea): KBTS_C2(ALea, POea): KBTS_C2(ALea, POnea): + KBTS_C2(ALnea, PRea): KBTS_C2(ALnea, PRnea): KBTS_C2(ALnea, POea): KBTS_C2(ALnea, POnea): + KBTS_C2(DOTTED_CIRCLE, PRea): KBTS_C2(DOTTED_CIRCLE, PRnea): KBTS_C2(DOTTED_CIRCLE, POea): KBTS_C2(DOTTED_CIRCLE, POnea): + KBTS_C2(HL, PRea): KBTS_C2(HL, PRnea): KBTS_C2(HL, POea): KBTS_C2(HL, POnea): + KBTS_C2(NU, POea): KBTS_C2(NU, POnea): KBTS_C2(NU, PRea): KBTS_C2(NU, PRnea): KBTS_C2(NU, NU): + KBTS_C2(POea, NU): KBTS_C2(POnea, NU): KBTS_C2(PRea, NU): KBTS_C2(PRnea, NU): + KBTS_C2(SY, HL): + KBTS_C2(JL, JL): KBTS_C2(JL, JV): KBTS_C2(JL, H2): KBTS_C2(JL, H3): + KBTS_C2(JV, JV): KBTS_C2(JV, JT): KBTS_C2(H2, JV): KBTS_C2(H2, JT): + KBTS_C2(JT, JT): KBTS_C2(H3, JT): + KBTS_C2(JL, POea): KBTS_C2(JL, POnea): KBTS_C2(JV, POea): KBTS_C2(JV, POnea): KBTS_C2(JT, POea): KBTS_C2(JT, POnea): + KBTS_C2(H2, POea): KBTS_C2(H2, POnea): KBTS_C2(H3, POea): KBTS_C2(H3, POnea): + KBTS_C2(PRea, JL): KBTS_C2(PRea, JV): KBTS_C2(PRea, JT): KBTS_C2(PRea, H2): KBTS_C2(PRea, H3): + KBTS_C2(PRnea, JL): KBTS_C2(PRnea, JV): KBTS_C2(PRnea, JT): KBTS_C2(PRnea, H2): KBTS_C2(PRnea, H3): + KBTS_C2(ALea, ALea): KBTS_C2(ALea, ALnea): KBTS_C2(ALea, DOTTED_CIRCLE): KBTS_C2(ALea, HL): + KBTS_C2(ALnea, ALea): KBTS_C2(ALnea, ALnea): KBTS_C2(ALnea, DOTTED_CIRCLE): KBTS_C2(ALnea, HL): + KBTS_C2(DOTTED_CIRCLE, ALea): KBTS_C2(DOTTED_CIRCLE, ALnea): KBTS_C2(DOTTED_CIRCLE, DOTTED_CIRCLE): KBTS_C2(DOTTED_CIRCLE, HL): + KBTS_C2(HL, ALea): KBTS_C2(HL, ALnea): KBTS_C2(HL, DOTTED_CIRCLE): KBTS_C2(HL, HL): + KBTS_C2(AP, AK): KBTS_C2(AP, DOTTED_CIRCLE): KBTS_C2(AP, AS): + KBTS_C2(AK, VF): KBTS_C2(AK, VI): KBTS_C2(DOTTED_CIRCLE, VF): KBTS_C2(DOTTED_CIRCLE, VI): KBTS_C2(AS, VF): KBTS_C2(AS, VI): + KBTS_C2(IS, ALea): KBTS_C2(IS, ALnea): KBTS_C2(IS, DOTTED_CIRCLE): KBTS_C2(IS, HL): + KBTS_C2(ALea, OPnea): KBTS_C2(ALnea, OPnea): KBTS_C2(DOTTED_CIRCLE, OPnea): KBTS_C2(HL, OPnea): KBTS_C2(NU, OPnea): + KBTS_C2(CPnea, ALea): KBTS_C2(CPnea, ALnea): KBTS_C2(CPnea, DOTTED_CIRCLE): KBTS_C2(CPnea, HL): KBTS_C2(CPnea, NU): + KBTS_C2(EBea, EM): KBTS_C2(EBnea, EM): KBTS_C2(Ope, EM): KBTS_C2(IDpe, EM): + KBTS_C2(HY, NU): KBTS_C2(IS, NU): + KBTS_LINE_UNBREAK(0, 1); break; + + KBTS_C2(Oea, GLea):KBTS_C2(Oea, GLnea): + KBTS_C2(Onea, GLea):KBTS_C2(Onea, GLnea): + KBTS_C2(Ope, GLea):KBTS_C2(Ope, GLnea): + KBTS_C2(BK, GLea):KBTS_C2(BK, GLnea): + KBTS_C2(CR, GLea):KBTS_C2(CR, GLnea): + KBTS_C2(LF, GLea):KBTS_C2(LF, GLnea): + KBTS_C2(NL, GLea):KBTS_C2(NL, GLnea): + KBTS_C2(ZW, GLea):KBTS_C2(ZW, GLnea): + KBTS_C2(WJ, GLea):KBTS_C2(WJ, GLnea): + KBTS_C2(GLea, GLea):KBTS_C2(GLea, GLnea): + KBTS_C2(GLnea, GLea):KBTS_C2(GLnea, GLnea): + KBTS_C2(CLea, GLea):KBTS_C2(CLea, GLnea): + KBTS_C2(CLnea, GLea):KBTS_C2(CLnea, GLnea): + KBTS_C2(CPea, GLea):KBTS_C2(CPea, GLnea): + KBTS_C2(CPnea, GLea):KBTS_C2(CPnea, GLnea): + KBTS_C2(EXea, GLea):KBTS_C2(EXea, GLnea): + KBTS_C2(EXnea, GLea):KBTS_C2(EXnea, GLnea): + KBTS_C2(SY, GLea):KBTS_C2(SY, GLnea): + KBTS_C2(OPea, GLea):KBTS_C2(OPea, GLnea): + KBTS_C2(OPnea, GLea):KBTS_C2(OPnea, GLnea): + KBTS_C2(QU, GLea):KBTS_C2(QU, GLnea): + KBTS_C2(QUPi, GLea): + KBTS_C2(IS, GLea):KBTS_C2(IS, GLnea): + KBTS_C2(NSea, GLea):KBTS_C2(NSea, GLnea): + KBTS_C2(NSnea, GLea):KBTS_C2(NSnea, GLnea): + KBTS_C2(B2, GLea):KBTS_C2(B2, GLnea): + KBTS_C2(CB, GLea):KBTS_C2(CB, GLnea): + KBTS_C2(INea, GLea):KBTS_C2(INea, GLnea): + KBTS_C2(INnea, GLea):KBTS_C2(INnea, GLnea): + KBTS_C2(BB, GLea):KBTS_C2(BB, GLnea): + KBTS_C2(HL, GLea):KBTS_C2(HL, GLnea): + KBTS_C2(ALea, GLea):KBTS_C2(ALea, GLnea): + KBTS_C2(ALnea, GLea):KBTS_C2(ALnea, GLnea): + KBTS_C2(NU, GLea):KBTS_C2(NU, GLnea): + KBTS_C2(PRea, GLea):KBTS_C2(PRea, GLnea): + KBTS_C2(PRnea, GLea):KBTS_C2(PRnea, GLnea): + KBTS_C2(IDea, GLea):KBTS_C2(IDea, GLnea): + KBTS_C2(IDnea, GLea):KBTS_C2(IDnea, GLnea): + KBTS_C2(IDpe, GLea):KBTS_C2(IDpe, GLnea): + KBTS_C2(EBea, GLea):KBTS_C2(EBea, GLnea): + KBTS_C2(EBnea, GLea):KBTS_C2(EBnea, GLnea): + KBTS_C2(EM, GLea):KBTS_C2(EM, GLnea): + KBTS_C2(POea, GLea):KBTS_C2(POea, GLnea): + KBTS_C2(POnea, GLea):KBTS_C2(POnea, GLnea): + KBTS_C2(JL, GLea):KBTS_C2(JL, GLnea): + KBTS_C2(JV, GLea):KBTS_C2(JV, GLnea): + KBTS_C2(JT, GLea):KBTS_C2(JT, GLnea): + KBTS_C2(H2, GLea):KBTS_C2(H2, GLnea): + KBTS_C2(H3, GLea):KBTS_C2(H3, GLnea): + KBTS_C2(AP, GLea):KBTS_C2(AP, GLnea): + KBTS_C2(AK, GLea):KBTS_C2(AK, GLnea): + KBTS_C2(DOTTED_CIRCLE, GLea):KBTS_C2(DOTTED_CIRCLE, GLnea): + KBTS_C2(AS, GLea):KBTS_C2(AS, GLnea): + KBTS_C2(VF, GLea):KBTS_C2(VF, GLnea): + KBTS_C2(VI, GLea):KBTS_C2(VI, GLnea): + KBTS_C2(RI, GLea):KBTS_C2(RI, GLnea): + KBTS_LINE_UNBREAK(3, 1); break; + + + KBTS_C2(CLea, NSnea): KBTS_C2(CLea, NSea): KBTS_C2(CLnea, NSnea): KBTS_C2(CLnea, NSea): + KBTS_C2(CPea, NSnea): KBTS_C2(CPea, NSea): KBTS_C2(CPnea, NSnea): KBTS_C2(CPnea, NSea): + KBTS_C2(B2, B2): + KBTS_LINE_UNBREAK(2, 1); break; + + KBTS_C2(RI, RI): // (RI RI)* RI x RI + KBTS_LINE_UNBREAK(0, 1); + LineBreakHistory = 0; + break; + } + + switch(LineBreakHistory & 0xFFFFFF) + { + KBTS_C3(SOT, QUPi, SP): KBTS_C3(BK, QUPi, SP): KBTS_C3(CR, QUPi, SP): KBTS_C3(LF, QUPi, SP): KBTS_C3(NL, QUPi, SP): KBTS_C3(OPea, QUPi, SP): KBTS_C3(OPnea, QUPi, SP): + KBTS_C3(SP, QUPi, SP): KBTS_C3(ZW, QUPi, SP): KBTS_C3(QU, QUPi, SP): KBTS_C3(QUPi, QUPi, SP): KBTS_C3(QUPf, QUPi, SP): KBTS_C3(GLea, QUPi, SP): KBTS_C3(GLnea, QUPi, SP): + KBTS_LINE_UNBREAK(3, 0); break; + + KBTS_C3(SP, IS, NU): + KBTS_LINE_BREAK(3, 2); break; + + KBTS_C3(CLea, SP, NSnea): KBTS_C3(CLea, SP, NSea): KBTS_C3(CLnea, SP, NSnea): KBTS_C3(CLnea, SP, NSea): + KBTS_C3(CPea, SP, NSnea): KBTS_C3(CPea, SP, NSea): KBTS_C3(CPnea, SP, NSnea): KBTS_C3(CPnea, SP, NSea): + KBTS_C3(B2, SP, B2): + KBTS_LINE_UNBREAK(2, 1); break; + + KBTS_C3(SOT, HY, ALnea): KBTS_C3(SOT, HY, ALea): KBTS_C3(SOT, HY, DOTTED_CIRCLE): KBTS_C3(SOT, HYPHEN, ALnea): KBTS_C3(SOT, HYPHEN, ALea): KBTS_C3(SOT, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(BK, HY, ALnea): KBTS_C3(BK, HY, ALea): KBTS_C3(BK, HY, DOTTED_CIRCLE): KBTS_C3(BK, HYPHEN, ALnea): KBTS_C3(BK, HYPHEN, ALea): KBTS_C3(BK, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(LF, HY, ALnea): KBTS_C3(LF, HY, ALea): KBTS_C3(LF, HY, DOTTED_CIRCLE): KBTS_C3(LF, HYPHEN, ALnea): KBTS_C3(LF, HYPHEN, ALea): KBTS_C3(LF, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(NL, HY, ALnea): KBTS_C3(NL, HY, ALea): KBTS_C3(NL, HY, DOTTED_CIRCLE): KBTS_C3(NL, HYPHEN, ALnea): KBTS_C3(NL, HYPHEN, ALea): KBTS_C3(NL, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(CR, HY, ALnea): KBTS_C3(CR, HY, ALea): KBTS_C3(CR, HY, DOTTED_CIRCLE): KBTS_C3(CR, HYPHEN, ALnea): KBTS_C3(CR, HYPHEN, ALea): KBTS_C3(CR, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(SP, HY, ALnea): KBTS_C3(SP, HY, ALea): KBTS_C3(SP, HY, DOTTED_CIRCLE): KBTS_C3(SP, HYPHEN, ALnea): KBTS_C3(SP, HYPHEN, ALea): KBTS_C3(SP, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(ZW, HY, ALnea): KBTS_C3(ZW, HY, ALea): KBTS_C3(ZW, HY, DOTTED_CIRCLE): KBTS_C3(ZW, HYPHEN, ALnea): KBTS_C3(ZW, HYPHEN, ALea): KBTS_C3(ZW, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(CB, HY, ALnea): KBTS_C3(CB, HY, ALea): KBTS_C3(CB, HY, DOTTED_CIRCLE): KBTS_C3(CB, HYPHEN, ALnea): KBTS_C3(CB, HYPHEN, ALea): KBTS_C3(CB, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(GLnea, HY, ALnea): KBTS_C3(GLnea, HY, ALea): KBTS_C3(GLnea, HY, DOTTED_CIRCLE): KBTS_C3(GLnea, HYPHEN, ALnea): KBTS_C3(GLnea, HYPHEN, ALea): KBTS_C3(GLnea, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(GLea, HY, ALnea): KBTS_C3(GLea, HY, ALea): KBTS_C3(GLea, HY, DOTTED_CIRCLE): KBTS_C3(GLea, HYPHEN, ALnea): KBTS_C3(GLea, HYPHEN, ALea): KBTS_C3(GLea, HYPHEN, DOTTED_CIRCLE): + KBTS_C3(NU, SY, POea): KBTS_C3(NU, SY, POnea): KBTS_C3(NU, SY, PRea): KBTS_C3(NU, SY, PRnea): KBTS_C3(NU, SY, NU): + KBTS_C3(NU, IS, POea): KBTS_C3(NU, IS, POnea): KBTS_C3(NU, IS, PRea): KBTS_C3(NU, IS, PRnea): KBTS_C3(NU, IS, NU): + KBTS_C3(NU, CLea, POea): KBTS_C3(NU, CLea, POnea): KBTS_C3(NU, CLea, PRea): KBTS_C3(NU, CLea, PRnea): + KBTS_C3(NU, CLnea, POea): KBTS_C3(NU, CLnea, POnea): KBTS_C3(NU, CLnea, PRea): KBTS_C3(NU, CLnea, PRnea): + KBTS_C3(NU, CPea, POea): KBTS_C3(NU, CPea, POnea): KBTS_C3(NU, CPea, PRea): KBTS_C3(NU, CPea, PRnea): + KBTS_C3(NU, CPnea, POea): KBTS_C3(NU, CPnea, POnea): KBTS_C3(NU, CPnea, PRea): KBTS_C3(NU, CPnea, PRnea): + KBTS_C3(AK, VI, AK): KBTS_C3(AK, VI, DOTTED_CIRCLE): KBTS_C3(DOTTED_CIRCLE, VI, AK): KBTS_C3(DOTTED_CIRCLE, VI, DOTTED_CIRCLE): KBTS_C3(AS, VI, AK): KBTS_C3(AS, VI, DOTTED_CIRCLE): + KBTS_LINE_UNBREAK(0, 1); break; + + KBTS_C3(POea, OPea, NU): KBTS_C3(POea, OPnea, NU): KBTS_C3(POnea, OPea, NU): KBTS_C3(POnea, OPnea, NU): + KBTS_C3(PRea, OPea, NU): KBTS_C3(PRea, OPnea, NU): KBTS_C3(PRnea, OPea, NU): KBTS_C3(PRnea, OPnea, NU): + KBTS_LINE_UNBREAK(0, 2); break; + + KBTS_C3(AK, AK, VF): KBTS_C3(AK, DOTTED_CIRCLE, VF): KBTS_C3(AK, AS, VF): + KBTS_C3(DOTTED_CIRCLE, AK, VF): KBTS_C3(DOTTED_CIRCLE, DOTTED_CIRCLE, VF): KBTS_C3(DOTTED_CIRCLE, AS, VF): + KBTS_C3(AS, AK, VF): KBTS_C3(AS, DOTTED_CIRCLE, VF): KBTS_C3(AS, AS, VF): + KBTS_LINE_UNBREAK(0, 2); break; + + KBTS_C3(HL, BAnea, Oea): KBTS_C3(HL, BAnea, Onea): KBTS_C3(HL, BAnea, Ope): KBTS_C3(HL, BAnea, BK): KBTS_C3(HL, BAnea, CR): KBTS_C3(HL, BAnea, LF): + KBTS_C3(HL, BAnea, NL): KBTS_C3(HL, BAnea, SP): KBTS_C3(HL, BAnea, ZW): KBTS_C3(HL, BAnea, WJ): KBTS_C3(HL, BAnea, GLea): KBTS_C3(HL, BAnea, GLnea): + KBTS_C3(HL, BAnea, CLea): KBTS_C3(HL, BAnea, CLnea): KBTS_C3(HL, BAnea, CPea): KBTS_C3(HL, BAnea, CPnea): KBTS_C3(HL, BAnea, EXea): KBTS_C3(HL, BAnea, EXnea): + KBTS_C3(HL, BAnea, SY): KBTS_C3(HL, BAnea, BAea): KBTS_C3(HL, BAnea, BAnea): KBTS_C3(HL, BAnea, OPea): KBTS_C3(HL, BAnea, OPnea): KBTS_C3(HL, BAnea, QU): + KBTS_C3(HL, BAnea, QUPi): KBTS_C3(HL, BAnea, QUPf): KBTS_C3(HL, BAnea, IS): KBTS_C3(HL, BAnea, NSea): KBTS_C3(HL, BAnea, NSnea): KBTS_C3(HL, BAnea, B2): + KBTS_C3(HL, BAnea, CB): KBTS_C3(HL, BAnea, HY): KBTS_C3(HL, BAnea, HYPHEN): KBTS_C3(HL, BAnea, INea): KBTS_C3(HL, BAnea, INnea): KBTS_C3(HL, BAnea, BB): + KBTS_C3(HL, BAnea, ALea): KBTS_C3(HL, BAnea, ALnea): KBTS_C3(HL, BAnea, NU): KBTS_C3(HL, BAnea, PRea): KBTS_C3(HL, BAnea, PRnea): KBTS_C3(HL, BAnea, IDea): + KBTS_C3(HL, BAnea, IDnea): KBTS_C3(HL, BAnea, IDpe): KBTS_C3(HL, BAnea, EBea): KBTS_C3(HL, BAnea, EBnea): KBTS_C3(HL, BAnea, EM): KBTS_C3(HL, BAnea, POea): + KBTS_C3(HL, BAnea, POnea): KBTS_C3(HL, BAnea, JL): KBTS_C3(HL, BAnea, JV): KBTS_C3(HL, BAnea, JT): KBTS_C3(HL, BAnea, H2): KBTS_C3(HL, BAnea, H3): + KBTS_C3(HL, BAnea, AP): KBTS_C3(HL, BAnea, AK): KBTS_C3(HL, BAnea, DOTTED_CIRCLE): KBTS_C3(HL, BAnea, AS): KBTS_C3(HL, BAnea, VF): KBTS_C3(HL, BAnea, VI): KBTS_C3(HL, BAnea, RI): + KBTS_C3(HL, HYPHEN, Oea): KBTS_C3(HL, HYPHEN, Onea): KBTS_C3(HL, HYPHEN, Ope): KBTS_C3(HL, HYPHEN, BK): KBTS_C3(HL, HYPHEN, CR): KBTS_C3(HL, HYPHEN, LF): + KBTS_C3(HL, HYPHEN, NL): KBTS_C3(HL, HYPHEN, SP): KBTS_C3(HL, HYPHEN, ZW): KBTS_C3(HL, HYPHEN, WJ): KBTS_C3(HL, HYPHEN, GLea): KBTS_C3(HL, HYPHEN, GLnea): + KBTS_C3(HL, HYPHEN, CLea): KBTS_C3(HL, HYPHEN, CLnea): KBTS_C3(HL, HYPHEN, CPea): KBTS_C3(HL, HYPHEN, CPnea): KBTS_C3(HL, HYPHEN, EXea): KBTS_C3(HL, HYPHEN, EXnea): + KBTS_C3(HL, HYPHEN, SY): KBTS_C3(HL, HYPHEN, BAea): KBTS_C3(HL, HYPHEN, BAnea): KBTS_C3(HL, HYPHEN, OPea): KBTS_C3(HL, HYPHEN, OPnea): KBTS_C3(HL, HYPHEN, QU): + KBTS_C3(HL, HYPHEN, QUPi): KBTS_C3(HL, HYPHEN, QUPf): KBTS_C3(HL, HYPHEN, IS): KBTS_C3(HL, HYPHEN, NSea): KBTS_C3(HL, HYPHEN, NSnea): KBTS_C3(HL, HYPHEN, B2): + KBTS_C3(HL, HYPHEN, CB): KBTS_C3(HL, HYPHEN, HY): KBTS_C3(HL, HYPHEN, HYPHEN): KBTS_C3(HL, HYPHEN, INea): KBTS_C3(HL, HYPHEN, INnea): KBTS_C3(HL, HYPHEN, BB): + KBTS_C3(HL, HYPHEN, ALea): KBTS_C3(HL, HYPHEN, ALnea): KBTS_C3(HL, HYPHEN, NU): KBTS_C3(HL, HYPHEN, PRea): KBTS_C3(HL, HYPHEN, PRnea): KBTS_C3(HL, HYPHEN, IDea): + KBTS_C3(HL, HYPHEN, IDnea): KBTS_C3(HL, HYPHEN, IDpe): KBTS_C3(HL, HYPHEN, EBea): KBTS_C3(HL, HYPHEN, EBnea): KBTS_C3(HL, HYPHEN, EM): KBTS_C3(HL, HYPHEN, POea): + KBTS_C3(HL, HYPHEN, POnea): KBTS_C3(HL, HYPHEN, JL): KBTS_C3(HL, HYPHEN, JV): KBTS_C3(HL, HYPHEN, JT): KBTS_C3(HL, HYPHEN, H2): KBTS_C3(HL, HYPHEN, H3): + KBTS_C3(HL, HYPHEN, AP): KBTS_C3(HL, HYPHEN, AK): KBTS_C3(HL, HYPHEN, DOTTED_CIRCLE): KBTS_C3(HL, HYPHEN, AS): KBTS_C3(HL, HYPHEN, VF): KBTS_C3(HL, HYPHEN, VI): KBTS_C3(HL, HYPHEN, RI): + KBTS_C3(HL, HY, Oea): KBTS_C3(HL, HY, Onea): KBTS_C3(HL, HY, Ope): KBTS_C3(HL, HY, BK): KBTS_C3(HL, HY, CR): KBTS_C3(HL, HY, LF): + KBTS_C3(HL, HY, NL): KBTS_C3(HL, HY, SP): KBTS_C3(HL, HY, ZW): KBTS_C3(HL, HY, WJ): KBTS_C3(HL, HY, GLea): KBTS_C3(HL, HY, GLnea): + KBTS_C3(HL, HY, CLea): KBTS_C3(HL, HY, CLnea): KBTS_C3(HL, HY, CPea): KBTS_C3(HL, HY, CPnea): KBTS_C3(HL, HY, EXea): KBTS_C3(HL, HY, EXnea): + KBTS_C3(HL, HY, SY): KBTS_C3(HL, HY, BAea): KBTS_C3(HL, HY, BAnea): KBTS_C3(HL, HY, OPea): KBTS_C3(HL, HY, OPnea): KBTS_C3(HL, HY, QU): + KBTS_C3(HL, HY, QUPi): KBTS_C3(HL, HY, QUPf): KBTS_C3(HL, HY, IS): KBTS_C3(HL, HY, NSea): KBTS_C3(HL, HY, NSnea): KBTS_C3(HL, HY, B2): + KBTS_C3(HL, HY, CB): KBTS_C3(HL, HY, HY): KBTS_C3(HL, HY, HYPHEN): KBTS_C3(HL, HY, INea): KBTS_C3(HL, HY, INnea): KBTS_C3(HL, HY, BB): + KBTS_C3(HL, HY, ALea): KBTS_C3(HL, HY, ALnea): KBTS_C3(HL, HY, NU): KBTS_C3(HL, HY, PRea): KBTS_C3(HL, HY, PRnea): KBTS_C3(HL, HY, IDea): + KBTS_C3(HL, HY, IDnea): KBTS_C3(HL, HY, IDpe): KBTS_C3(HL, HY, EBea): KBTS_C3(HL, HY, EBnea): KBTS_C3(HL, HY, EM): KBTS_C3(HL, HY, POea): + KBTS_C3(HL, HY, POnea): KBTS_C3(HL, HY, JL): KBTS_C3(HL, HY, JV): KBTS_C3(HL, HY, JT): KBTS_C3(HL, HY, H2): KBTS_C3(HL, HY, H3): + KBTS_C3(HL, HY, AP): KBTS_C3(HL, HY, AK): KBTS_C3(HL, HY, DOTTED_CIRCLE): KBTS_C3(HL, HY, AS): KBTS_C3(HL, HY, VF): KBTS_C3(HL, HY, VI): KBTS_C3(HL, HY, RI): + KBTS_LINE_UNBREAK(0, 1); break; + } + + switch(LineBreakHistory) + { + KBTS_C4(NU, SY, CLnea, POnea): KBTS_C4(NU, SY, CLnea, POea): KBTS_C4(NU, SY, CLnea, PRnea): KBTS_C4(NU, SY, CLnea, PRea): + KBTS_C4(NU, SY, CLea, POnea): KBTS_C4(NU, SY, CLea, POea): KBTS_C4(NU, SY, CLea, PRnea): KBTS_C4(NU, SY, CLea, PRea): + KBTS_C4(NU, SY, CPnea, POnea): KBTS_C4(NU, SY, CPnea, POea): KBTS_C4(NU, SY, CPnea, PRnea): KBTS_C4(NU, SY, CPnea, PRea): + KBTS_C4(NU, SY, CPea, POnea): KBTS_C4(NU, SY, CPea, POea): KBTS_C4(NU, SY, CPea, PRnea): KBTS_C4(NU, SY, CPea, PRea): + KBTS_C4(NU, IS, CLnea, POnea): KBTS_C4(NU, IS, CLnea, POea): KBTS_C4(NU, IS, CLnea, PRnea): KBTS_C4(NU, IS, CLnea, PRea): + KBTS_C4(NU, IS, CLea, POnea): KBTS_C4(NU, IS, CLea, POea): KBTS_C4(NU, IS, CLea, PRnea): KBTS_C4(NU, IS, CLea, PRea): + KBTS_C4(NU, IS, CPnea, POnea): KBTS_C4(NU, IS, CPnea, POea): KBTS_C4(NU, IS, CPnea, PRnea): KBTS_C4(NU, IS, CPnea, PRea): + KBTS_C4(NU, IS, CPea, POnea): KBTS_C4(NU, IS, CPea, POea): KBTS_C4(NU, IS, CPea, PRnea): KBTS_C4(NU, IS, CPea, PRea): + KBTS_LINE_UNBREAK(0, 1); break; + + KBTS_C4(POea, OPea, IS, NU): KBTS_C4(POea, OPnea, IS, NU): KBTS_C4(POnea, OPea, IS, NU): KBTS_C4(POnea, OPnea, IS, NU): + KBTS_C4(PRea, OPea, IS, NU): KBTS_C4(PRea, OPnea, IS, NU): KBTS_C4(PRnea, OPea, IS, NU): KBTS_C4(PRnea, OPnea, IS, NU): + KBTS_LINE_UNBREAK(0, 3); break; + } + + if(StartOfText) + { + // Never break lines. + KBTS_LINE_UNBREAK(5, 1); + // Always break graphemes. + KBTS_BREAK(KBTS_BREAK_FLAG_GRAPHEME, 1); + } + + #undef KBTS_C1 + #undef KBTS_C2 + #undef KBTS_C3 + #undef KBTS_C4 + #undef KBTS_REQUIRED_LINE_BREAK + #undef KBTS_LINE_BREAK + #undef KBTS_LINE_UNBREAK + + { + kbts_u64 EffectiveLineBreaks = LineBreaks & ~(LineUnbreaks | LineUnbreaksAsync); + + kbts__DoLineBreak(State, PositionOffset3 + LineBreak3PositionOffset, EffectiveLineBreaks >> 48); + if(EndOfText) + { + kbts__DoLineBreak(State, PositionOffset2 + LineBreak2PositionOffset, EffectiveLineBreaks >> 32); + { // @Cleanup: This is the same flag code as DoLineBreak, but we want to use FlagState buffering for this. + // The only places where we want to manually call DoBreak is for asynchronous/buffered guys. + kbts_u8 FlushedLineFlags = 0; + if((EffectiveLineBreaks >> 16) & KBTS__LINE_BREAK_ALLOWED_MASK) FlushedLineFlags |= KBTS_BREAK_FLAG_LINE_SOFT; + if((EffectiveLineBreaks >> 16) & KBTS__LINE_BREAK_REQUIRED_MASK) FlushedLineFlags |= KBTS_BREAK_FLAG_LINE_HARD; + + KBTS_BREAK(FlushedLineFlags, 1); + } + // Lines are never broken after the end of text. + } + } + + State->LineBreaks = LineBreaks; + State->LineUnbreaks = LineUnbreaks; + State->LineBreak2PositionOffset = 0; + State->LineBreak3PositionOffset = LineBreak2PositionOffset; + State->LastLineBreakClass = LineBreakClass; + State->LineBreakHistory = LineBreakHistory; + + if(0) + { + LineBreakAbsorbCharacter:; + State->LineBreak2PositionOffset -= (kbts_s16)PositionIncrement; + State->LineBreak3PositionOffset -= (kbts_s16)PositionIncrement; + } + + // This always gets updated. + State->LineUnbreaksAsync = LineUnbreaksAsync; + } + + // We flush scripts late because hard line breaks also want to flush scripts. + // + // If we have no active script at all, then either we are at the very beginning of the text, + // or we have only seen common/inherited scripts so far. + // Either way, we want everything before us to coerce to our type, so don't actually break, + // and do not update the script break position. + if((FlushFlags & KBTS__BREAK_FLUSH_FLAG_SCRIPT) && + ScriptCountAtBeginningOfUpdate) + { + kbts__DoBreak(State, ScriptPositionOffset, KBTS_BREAK_FLAG_SCRIPT, 0, 0, BreakScript); + ScriptPositionOffset = 0; + + if(HardLineBreak) + { + // Put the next script break after the newline. + ScriptPositionOffset = (kbts_s16)PositionIncrement; + } + } + + if(FlushFlags & KBTS__BREAK_FLUSH_FLAG_DIRECTION_2) + { + kbts__FlushDirection(State, &LastDirection, Bidirectional2, Bidirectional2PositionOffset); + } + if(FlushFlags & KBTS__BREAK_FLUSH_FLAG_DIRECTION_1) + { + kbts__FlushDirection(State, &LastDirection, Bidirectional1, Bidirectional1PositionOffset); + } + + if(FlushFlags & KBTS__BREAK_FLUSH_FLAG_DIRECTION_PARAGRAPH) + { + // Reset direction state for the new paragraph. + Bidirectional1 = 0; + + // Clear direction history. + // This is necessary to uphold the invariant that the first direction break is always + // on the first character of a paragraph. + LastDirection = 0; + + // CAUTION: This needs to be updated _after_ calling kbts__FlushDirection! + // Alternatively, we could load ParagraphStartPosition into a variable at the start of this function. + State->ParagraphStartPosition = State->CurrentPosition + 1; + + kbts__BreakStateStartParagraph(State); + + if(State->UserParagraphDirection == KBTS_DIRECTION_DONT_KNOW) + { + kbts__DoBreak(State, 1, KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION, 0, KBTS_DIRECTION_DONT_KNOW, 0); + } + } + + ScriptPositionOffset -= (kbts_s16)PositionIncrement; + + // This is where we flush the normal breaks that don't need any special position adjustment. + kbts__DoBreak(State, PositionOffset3, (FlagState >> 24) & 0xFF, 0, 0, 0); + if(EndOfText) + { + kbts__DoBreak(State, PositionOffset2, (FlagState >> 16) & 0xFF, 0, 0, 0); + kbts__DoBreak(State, 0, (FlagState >> 8) & 0xFF, 0, 0, 0); + kbts__DoBreak(State, (int)PositionIncrement, FlagState & 0xFF, 0, 0, 0); + } + + State->FlagState = FlagState; + Flags |= KBTS_BREAK_STATE_FLAG_STARTED; + if(EndOfText) Flags |= KBTS_BREAK_STATE_FLAG_END; + State->Flags = Flags; + State->PositionOffset2 = (kbts_s16)-(int)PositionIncrement; + State->PositionOffset3 = (kbts_s16)(PositionOffset2 - (int)PositionIncrement); + State->CurrentPosition += PositionIncrement; + + if(FlushFlags & KBTS__BREAK_FLUSH_FLAG_DIRECTION_2) + { + // Only update the buffer if we've actually flushed something. + State->BidirectionalClass2 = Bidirectional1; + State->BidirectionalClass1 = BidirectionalClass; + State->Bidirectional2PositionOffset = State->Bidirectional1PositionOffset - (kbts_s16)PositionIncrement; + State->Bidirectional1PositionOffset = (kbts_s16)-(int)PositionIncrement; + } + State->LastDirection = (kbts_u8)LastDirection; + + State->ScriptPositionOffset = ScriptPositionOffset; + State->ScriptCount = ScriptCount; +#undef KBTS_BREAK +#undef KBTS_BREAK2 +} + +KBTS_EXPORT void kbts_BreakEnd(kbts_break_state *State) +{ + // We pass 3, aka. ASCII end-of-text, at the end of text. + kbts__BreakAddCodepoint(State, 3, 0, 1); +} + +KBTS_EXPORT void kbts_BreakAddCodepoint(kbts_break_state *State, int Codepoint, int PositionIncrement, int EndOfText) +{ + kbts__BreakAddCodepoint(State, Codepoint, (kbts_u32)PositionIncrement, 0); + + if(EndOfText) + { + kbts_BreakEnd(State); + } +} + +KBTS_EXPORT int kbts_Break(kbts_break_state *State, kbts_break *Break) +{ + int Result = 0; + + if(State->BreakCount) + { + kbts_break *ToFlush = &State->Breaks[--State->BreakCount]; + + *Break = *ToFlush; + Result = 1; + } + + return Result; +} + +KBTS_EXPORT void kbts_GuessTextProperties(void *Text, int TextSizeInBytes, kbts_text_format Format, kbts_direction *Direction_, kbts_script *Script_) +{ + kbts_script Script = KBTS_SCRIPT_DONT_KNOW; + kbts_direction Direction = KBTS_DIRECTION_DONT_KNOW; + + if(Text && (TextSizeInBytes > 0) && Format) + { + const char *At = (const char *)Text; + const char *End = (const char *)Text + TextSizeInBytes; + + kbts_break_state BreakState; + kbts_BreakBegin(&BreakState, KBTS_DIRECTION_DONT_KNOW, KBTS_JAPANESE_LINE_BREAK_STYLE_NORMAL, 0); + + while(((Script == KBTS_SCRIPT_DONT_KNOW) || + (Direction == KBTS_DIRECTION_DONT_KNOW)) && + (At < End)) + { + kbts_u32 Codepoint = 0; + kbts_u32 PositionIncrement = 1; + + switch(Format) + { + case KBTS_TEXT_FORMAT_UTF32: + { + Codepoint = *(kbts_u32 *)At; + PositionIncrement = 4; + + } break; + + case KBTS_TEXT_FORMAT_UTF8: + { + kbts_decode Decode = kbts_DecodeUtf8(At, End - At); + + PositionIncrement = Decode.SourceCharactersConsumed; + + if(Decode.Valid) + { + Codepoint = Decode.Codepoint; + } + } break; + } + + kbts_BreakAddCodepoint(&BreakState, Codepoint, PositionIncrement, (At + PositionIncrement) == End); + kbts_break Break; + while(kbts_Break(&BreakState, &Break)) + { + if((Script == KBTS_SCRIPT_DONT_KNOW) && (Break.Flags & KBTS_BREAK_FLAG_SCRIPT)) + { + Script = Break.Script; + } + + if((Direction == KBTS_DIRECTION_DONT_KNOW) && (Break.Flags & KBTS_BREAK_FLAG_DIRECTION)) + { + Direction = Break.Direction; + } + } + + At += PositionIncrement; + } + } + + if(Script_) + { + *Script_ = Script; + } + + if(Direction_) + { + *Direction_ = Direction; + } +} + +KBTS_EXPORT void kbts_GuessTextPropertiesUtf32(const int *Utf32, int Utf32Count, kbts_direction *Direction, kbts_script *Script) +{ + kbts_GuessTextProperties((void *)Utf32, sizeof(int) * Utf32Count, KBTS_TEXT_FORMAT_UTF32, Direction, Script); +} + +KBTS_EXPORT void kbts_GuessTextPropertiesUtf8(const char *Utf8, int Utf8Length, kbts_direction *Direction, kbts_script *Script) +{ + kbts_GuessTextProperties((void *)Utf8, Utf8Length, KBTS_TEXT_FORMAT_UTF8, Direction, Script); +} + +KBTS_EXPORT void kbts_BreakBegin(kbts_break_state *State, kbts_direction ParagraphDirection, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags) +{ + if(State) + { + // @Speed: Clearing all the brackets isn't great. + KBTS_MEMSET(State, 0, sizeof(*State)); + State->UserParagraphDirection = (kbts_u8)ParagraphDirection; + State->ParagraphDirection = (kbts_u8)ParagraphDirection; + State->JapaneseLineBreakStyle = JapaneseLineBreakStyle; + State->ConfigFlags = ConfigFlags; + + // Force a direction break at the start of the text. + State->LastDirection = KBTS_DIRECTION_COUNT; + + // These should be out-of-bounds while the buffers haven't filled up. + State->PositionOffset2 = -100; + State->PositionOffset3 = -100; + State->WordBreak2PositionOffset = -100; + State->LineBreak2PositionOffset = -100; + State->LineBreak3PositionOffset = -100; + State->Bidirectional1PositionOffset = -100; + State->Bidirectional2PositionOffset = -100; + + kbts__BreakStateStartParagraph(State); + + if(ParagraphDirection) + { + kbts__DoBreak(State, 0, KBTS_BREAK_FLAG_PARAGRAPH_DIRECTION, 0, ParagraphDirection, 0); + } + } +} + +KBTS_EXPORT void kbts_BreakEntireString(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, + const void *Input, int InputSizeInBytes, kbts_text_format InputFormat, + kbts_break *Breaks, int IBreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int IBreakFlagCapacity, int *BreakFlagCount) +{ + kbts_break_state BreakState = KBTS__ZERO; + kbts_BreakBegin(&BreakState, Direction, JapaneseLineBreakStyle, ConfigFlags); + + char *InputElement = (char *)Input; + char *End = (char *)Input + InputSizeInBytes; + kbts_un BreaksWritten = 0; + kbts_un MaxBreakPosition = 0; + kbts_un BreakCapacity = (kbts_un)IBreakCapacity; + kbts_un BreakFlagCapacity = (kbts_un)IBreakFlagCapacity; + + if(BreakFlags && BreakFlagCapacity) + { + KBTS_MEMSET(BreakFlags, 0, sizeof(kbts_break_flags) * BreakFlagCapacity); + } + + while(InputElement < End) + { + kbts_u32 Codepoint = 0; + kbts_un InputElementSize = 1; + kbts_un SourceCharacterCount = 1; + + switch(InputFormat) + { + case KBTS_TEXT_FORMAT_UTF32: + { + Codepoint = *(kbts_u32 *)InputElement; + + InputElementSize = sizeof(kbts_u32); + } break; + + case KBTS_TEXT_FORMAT_UTF8: + { + kbts_decode Decode = kbts_DecodeUtf8(InputElement, End - InputElement); + + if(Decode.Valid) + { + Codepoint = Decode.Codepoint; + + InputElementSize = Decode.SourceCharactersConsumed; + SourceCharacterCount = Decode.SourceCharactersConsumed; + } + } break; + } + + InputElement += InputElementSize; + + kbts_BreakAddCodepoint(&BreakState, Codepoint, (kbts_u32)SourceCharacterCount, InputElement >= End); + kbts_break Break; + while(kbts_Break(&BreakState, &Break)) + { + if(Breaks && (BreaksWritten < BreakCapacity)) + { + int Found = 0; + kbts_un ExistingBreakCount = KBTS__MIN(BreaksWritten, BreakCapacity); + + // @Speed: Binary search! + for(kbts_un ExistingBreakIndex = ExistingBreakCount; + ExistingBreakIndex; + --ExistingBreakIndex) + { + kbts_break *Existing = &Breaks[ExistingBreakIndex - 1]; + + if(Existing->Position == Break.Position) + { + Existing->Flags |= Break.Flags; + + if(Break.Flags & KBTS_BREAK_FLAG_SCRIPT) + { + Existing->Script = Break.Script; + } + + if(Break.Flags & KBTS_BREAK_FLAG_DIRECTION) + { + Existing->Direction = Break.Direction; + } + + Found = 1; + + break; + } + } + + if(!Found) + { + Breaks[BreaksWritten] = Break; + } + } + + if(BreakFlags && ((kbts_u32)Break.Position < BreakFlagCapacity)) + { + BreakFlags[Break.Position] |= Break.Flags; + } + + MaxBreakPosition = KBTS__MAX(MaxBreakPosition, (kbts_u32)Break.Position); + + BreaksWritten += 1; + } + } + + if(!Breaks && BreakCount) + { + *BreakCount = (int)BreaksWritten; + } + if(!BreakFlags && BreakFlagCount) + { + *BreakFlagCount = (int)(MaxBreakPosition + 1); + } +} + +KBTS_EXPORT void kbts_BreakEntireStringUtf32(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, + const int *Utf32, int Utf32Count, + kbts_break *Breaks, int BreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount) +{ + kbts_BreakEntireString(Direction, JapaneseLineBreakStyle, ConfigFlags, Utf32, sizeof(int) * Utf32Count, KBTS_TEXT_FORMAT_UTF32, Breaks, BreakCapacity, BreakCount, BreakFlags, BreakFlagCapacity, BreakFlagCount); +} +KBTS_EXPORT void kbts_BreakEntireStringUtf8(kbts_direction Direction, kbts_japanese_line_break_style JapaneseLineBreakStyle, kbts_break_config_flags ConfigFlags, + const char *Utf8, int Utf8Length, + kbts_break *Breaks, int BreakCapacity, int *BreakCount, + kbts_break_flags *BreakFlags, int BreakFlagCapacity, int *BreakFlagCount) +{ + kbts_BreakEntireString(Direction, JapaneseLineBreakStyle, ConfigFlags, Utf8, Utf8Length, KBTS_TEXT_FORMAT_UTF8, Breaks, BreakCapacity, BreakCount, BreakFlags, BreakFlagCapacity, BreakFlagCount); +} + +KBTS_EXPORT kbts_decode kbts_DecodeUtf8(const char *Utf8, kbts_un Length) +{ + kbts_decode Result = KBTS__ZERO; + const char *Utf8Start = Utf8; + + if(Length) + { + kbts_u8 First = (kbts_u8)*Utf8++; + kbts_un FollowupCharacterCount = 0; + + switch((First & 0xF0) >> 4) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + { + Result.Codepoint = First & 0x7F; + Result.Valid = 1; + } + break; + + case 0xC: + case 0xD: + { + FollowupCharacterCount = 1; + Result.Codepoint = First & 0x1F; + Result.Valid = 1; + } + break; + + case 0xE: + { + FollowupCharacterCount = 2; + Result.Codepoint = First & 0xF; + Result.Valid = 1; + } + break; + + case 0xF: + { + FollowupCharacterCount = 3; + Result.Codepoint = First & 7; + Result.Valid = 1; + } + break; + } + + if(Length > FollowupCharacterCount) + { + KBTS__FOR(FollowupCharacterIndex, 0, FollowupCharacterCount) + { + kbts_u8 C = (kbts_u8)*Utf8++; + + if((C & 0xC0) == 0x80) + { + Result.Codepoint = (Result.Codepoint << 6) | (C & 0x3F); + } + else + { + Result.Valid = 0; + + break; + } + } + } + else + { + Result.Valid = 0; + } + } + + Result.SourceCharactersConsumed = (kbts_u32)(Utf8 - Utf8Start); + + return Result; +} + +KBTS_EXPORT kbts_encode_utf8 kbts_EncodeUtf8(int Codepoint) +{ + kbts_encode_utf8 Result = KBTS__ZERO; + + if(Codepoint <= 0x7F) + { + Result.Encoded[0] = (char)Codepoint; + Result.EncodedLength = 1; + } + else if(Codepoint <= 0x7FF) + { + Result.Encoded[1] = (Codepoint & 0x3F) | 0x80; + Result.Encoded[0] = ((Codepoint >> 6) & 0x1F) | 0xC0; + Result.EncodedLength = 2; + } + else if(Codepoint <= 0xFFFF) + { + Result.Encoded[2] = (Codepoint & 0x3F) | 0x80; + Result.Encoded[1] = ((Codepoint >> 6) & 0x3F) | 0x80; + Result.Encoded[0] = ((Codepoint >> 12) & 0xF) | 0xE0; + Result.EncodedLength = 3; + } + else if(Codepoint <= 0x10FFFF) + { + Result.Encoded[3] = (Codepoint & 0x3F) | 0x80; + Result.Encoded[2] = ((Codepoint >> 6) & 0x3F) | 0x80; + Result.Encoded[1] = ((Codepoint >> 12) & 0x3F) | 0x80; + Result.Encoded[0] = ((Codepoint >> 18) & 0x7) | 0xF0; + Result.EncodedLength = 4; + } + + Result.Valid = Result.EncodedLength > 0; + return Result; +} + +static int kbts__ShaperIsComplex(kbts_shaper Shaper) +{ + int Result = Shaper != KBTS_SHAPER_DEFAULT; // @Incomplete? + + return Result; +} + +KBTS_EXPORT int kbts_ScriptIsComplex(kbts_script Script) +{ + if(Script >= KBTS_SCRIPT_COUNT) + { + Script = KBTS_SCRIPT_DONT_KNOW; + } + + kbts__script_properties *Properties = &kbts__ScriptProperties[Script]; + int Result = kbts__ShaperIsComplex(Properties->Shaper); + return Result; +} + +#endif +#undef KBTS_X_FEATURES \ No newline at end of file diff --git a/vendor/libc/README.md b/vendor/libc-shim/README.md similarity index 79% rename from vendor/libc/README.md rename to vendor/libc-shim/README.md index 1dd50c5a9..9b44984f6 100644 --- a/vendor/libc/README.md +++ b/vendor/libc-shim/README.md @@ -1,11 +1,11 @@ -# vendor:libc +# vendor:libc-shim A (very small) subset of a libc implementation over Odin libraries. This is mainly intended for use in Odin WASM builds to allow using libraries like box2d, cgltf etc. without emscripten hacks. -You can use this with clang by doing `clang -c --target=wasm32 --sysroot=$(odin root)/vendor/libc` (+ all other flags and inputs). +You can use this with clang by doing `clang -c --target=wasm32 --sysroot=$(odin root)/vendor/libc-shim` (+ all other flags and inputs). This will (if all the libc usage of the library is implemented) spit out a `.o` file you can use with the foreign import system. -If you then also make sure this package is included in the Odin side of the project (`@(require) import "vendor:libc"`) you will be able +If you then also make sure this package is included in the Odin side of the project (`@(require) import "vendor:libc-shim"`) you will be able compile to WASM like Odin expects. This is currently used by `vendor:box2d`, `vendor:stb/image`, `vendor:stb/truetype`, `vendor:stb/rect_pack`, and `vendor:cgltf`. diff --git a/vendor/libc/assert.odin b/vendor/libc-shim/assert.odin similarity index 100% rename from vendor/libc/assert.odin rename to vendor/libc-shim/assert.odin diff --git a/vendor/libc/ctype.odin b/vendor/libc-shim/ctype.odin similarity index 100% rename from vendor/libc/ctype.odin rename to vendor/libc-shim/ctype.odin diff --git a/vendor/libc/include/alloca.h b/vendor/libc-shim/include/alloca.h similarity index 100% rename from vendor/libc/include/alloca.h rename to vendor/libc-shim/include/alloca.h diff --git a/vendor/libc/include/assert.h b/vendor/libc-shim/include/assert.h similarity index 100% rename from vendor/libc/include/assert.h rename to vendor/libc-shim/include/assert.h diff --git a/vendor/libc/include/ctype.h b/vendor/libc-shim/include/ctype.h similarity index 100% rename from vendor/libc/include/ctype.h rename to vendor/libc-shim/include/ctype.h diff --git a/vendor/libc/include/inttypes.h b/vendor/libc-shim/include/inttypes.h similarity index 100% rename from vendor/libc/include/inttypes.h rename to vendor/libc-shim/include/inttypes.h diff --git a/vendor/libc/include/math.h b/vendor/libc-shim/include/math.h similarity index 97% rename from vendor/libc/include/math.h rename to vendor/libc-shim/include/math.h index fba520e4a..dd9e8e9ba 100644 --- a/vendor/libc/include/math.h +++ b/vendor/libc-shim/include/math.h @@ -43,6 +43,8 @@ double tan(double); double atan2(double, double); double modf(double, double*); +float remainderf(float x, float y); + bool __isnanf(float); bool __isnand(double); #define isnan(x) \ diff --git a/vendor/libc/include/sched.h b/vendor/libc-shim/include/sched.h similarity index 100% rename from vendor/libc/include/sched.h rename to vendor/libc-shim/include/sched.h diff --git a/vendor/libc/include/stdio.h b/vendor/libc-shim/include/stdio.h similarity index 100% rename from vendor/libc/include/stdio.h rename to vendor/libc-shim/include/stdio.h diff --git a/vendor/libc/include/stdlib.h b/vendor/libc-shim/include/stdlib.h similarity index 100% rename from vendor/libc/include/stdlib.h rename to vendor/libc-shim/include/stdlib.h diff --git a/vendor/libc/include/string.h b/vendor/libc-shim/include/string.h similarity index 93% rename from vendor/libc/include/string.h rename to vendor/libc-shim/include/string.h index 7e5e2b252..6d947858f 100644 --- a/vendor/libc/include/string.h +++ b/vendor/libc-shim/include/string.h @@ -8,7 +8,7 @@ extern "C" { void *memcpy(void *, const void *, size_t); void *memset(void *, int, size_t); -void *memmove(void *, void *, size_t); +void *memmove(void *, const void *, size_t); int memcmp(const void *, const void *, size_t); void *memchr(const void *, int, size_t); diff --git a/vendor/libc/include/time.h b/vendor/libc-shim/include/time.h similarity index 100% rename from vendor/libc/include/time.h rename to vendor/libc-shim/include/time.h diff --git a/vendor/libc-shim/libc.odin b/vendor/libc-shim/libc.odin new file mode 100644 index 000000000..a5508e14f --- /dev/null +++ b/vendor/libc-shim/libc.odin @@ -0,0 +1,26 @@ +package odin_libc + +import "base:runtime" + +import "core:mem" + +@(private) +g_ctx: runtime.Context +@(private) +g_allocator: mem.Compat_Allocator + +@(init) +init_context :: proc "contextless" () { + g_ctx = runtime.default_context() + context = g_ctx + + // Wrapping the allocator with the mem.Compat_Allocator so we can + // mimic the realloc semantics. + mem.compat_allocator_init(&g_allocator, g_ctx.allocator) + g_ctx.allocator = mem.compat_allocator(&g_allocator) +} + +// NOTE: the allocator must respect an `old_size` of `-1` on resizes! +set_context :: proc(ctx := context) { + g_ctx = ctx +} diff --git a/vendor/libc/math.odin b/vendor/libc-shim/math.odin similarity index 97% rename from vendor/libc/math.odin rename to vendor/libc-shim/math.odin index 93df1fea6..26d8a917a 100644 --- a/vendor/libc/math.odin +++ b/vendor/libc-shim/math.odin @@ -204,3 +204,8 @@ modf :: proc "c" (num: f64, iptr: ^f64) -> f64 { iptr^ = integral return fractional } + +@(require, linkage="strong", link_name="remainderf") +remainderf :: proc "c" (x, y: f32) -> f32 { + return math.remainder(x, y) +} diff --git a/vendor/libc/sched.odin b/vendor/libc-shim/sched.odin similarity index 100% rename from vendor/libc/sched.odin rename to vendor/libc-shim/sched.odin diff --git a/vendor/libc/stdio.odin b/vendor/libc-shim/stdio.odin similarity index 88% rename from vendor/libc/stdio.odin rename to vendor/libc-shim/stdio.odin index d41f790ee..b47b3f166 100644 --- a/vendor/libc/stdio.odin +++ b/vendor/libc-shim/stdio.odin @@ -4,93 +4,60 @@ package odin_libc import "base:runtime" import "core:c" -import "core:io" -import "core:os" import "core:strconv" import stb "vendor:stb/sprintf" -FILE :: uintptr +FILE :: rawptr EOF :: -1 @(require, linkage="strong", link_name="fopen") fopen :: proc "c" (path: cstring, mode: cstring) -> FILE { context = g_ctx - unimplemented("vendor/libc: fopen") + return _fopen(path, mode) } @(require, linkage="strong", link_name="fseek") fseek :: proc "c" (file: FILE, offset: c.long, whence: i32) -> i32 { context = g_ctx - handle := os.Handle(file-1) - _, err := os.seek(handle, i64(offset), int(whence)) - if err != nil { - return -1 - } - return 0 + return _fseek(file, offset, whence) } @(require, linkage="strong", link_name="ftell") ftell :: proc "c" (file: FILE) -> c.long { context = g_ctx - handle := os.Handle(file-1) - off, err := os.seek(handle, 0, os.SEEK_CUR) - if err != nil { - return -1 - } - return c.long(off) + return _ftell(file) } @(require, linkage="strong", link_name="fclose") fclose :: proc "c" (file: FILE) -> i32 { context = g_ctx - handle := os.Handle(file-1) - if os.close(handle) != nil { - return -1 - } - return 0 + return _fclose(file) } @(require, linkage="strong", link_name="fread") fread :: proc "c" (buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint { context = g_ctx - handle := os.Handle(file-1) - n, _ := os.read(handle, buffer[:min(size, count)]) - return uint(max(0, n)) + return _fread(buffer, size, count, file) } @(require, linkage="strong", link_name="fwrite") fwrite :: proc "c" (buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint { context = g_ctx - handle := os.Handle(file-1) - n, _ := os.write(handle, buffer[:min(size, count)]) - return uint(max(0, n)) + return _fwrite(buffer, size, count, file) } @(require, linkage="strong", link_name="putchar") putchar :: proc "c" (char: c.int) -> c.int { context = g_ctx - - n, err := os.write_byte(os.stdout, byte(char)) - if n == 0 || err != nil { - return EOF - } - return char + return _putchar(char) } @(require, linkage="strong", link_name="getchar") getchar :: proc "c" () -> c.int { - when #defined(os.stdin) { - ret: [1]byte - n, err := os.read(os.stdin, ret[:]) - if n == 0 || err != nil { - return EOF - } - return c.int(ret[0]) - } else { - return EOF - } + context = g_ctx + return _getchar() } @(require, linkage="strong", link_name="vsnprintf") @@ -109,8 +76,6 @@ vsprintf :: proc "c" (buf: [^]byte, fmt: cstring, args: ^c.va_list) -> i32 { vfprintf :: proc "c" (file: FILE, fmt: cstring, args: ^c.va_list) -> i32 { context = g_ctx - handle := os.Handle(file-1) - MAX_STACK :: 4096 buf: []byte @@ -133,12 +98,15 @@ vfprintf :: proc "c" (file: FILE, fmt: cstring, args: ^c.va_list) -> i32 { delete(buf) } - _, err := io.write_full(os.stream_from_handle(handle), buf) - if err != nil { - return -1 + written: i32 + for len(buf) > 0 { + n := _fwrite(raw_data(buf), size_of(byte), len(buf), file) + if n == 0 { break } + buf = buf[n:] + written += i32(n) } - return i32(len(buf)) + return written } /* @@ -366,7 +334,7 @@ _sscanf :: proc "c" (str, fmt: [^]byte, orig_ptrs: [^]rawptr) -> i32 { i = 0 k = t == 'c' ? width + 1 : 31 if size == .l { - unimplemented("vendor/libc: sscanf wide character support") + unimplemented("vendor/libc-shim: sscanf wide character support") } else if alloc { s = make([^]byte, k) if s == nil { diff --git a/vendor/libc-shim/stdio_js.odin b/vendor/libc-shim/stdio_js.odin new file mode 100644 index 000000000..2382ed449 --- /dev/null +++ b/vendor/libc-shim/stdio_js.odin @@ -0,0 +1,60 @@ +#+private +package odin_libc + +import "core:c" + +foreign import "odin_env" + +_fopen :: proc(path, mode: cstring) -> FILE { + unimplemented("vendor/libc: fopen in JS") +} + +_fseek :: proc(file: FILE, offset: c.long, whence: i32) -> i32 { + unimplemented("vendor/libc: fseek in JS") +} + +_ftell :: proc(file: FILE) -> c.long { + unimplemented("vendor/libc: ftell in JS") +} + +_fclose :: proc(file: FILE) -> i32 { + unimplemented("vendor/libc: fclose in JS") +} + +_fread :: proc(buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint { + unimplemented("vendor/libc: fread in JS") +} + +_fwrite :: proc(buffer: [^]byte, size: uint, count: uint, file: FILE) -> uint { + fd, ok := __fd(file) + if !ok { + return 0 + } + + __write(fd, buffer[:size*count]) + return count +} + +_putchar :: proc(char: c.int) -> c.int { + __write(1, {byte(char)}) + return char +} + +_getchar :: proc() -> c.int { + return EOF +} + +@(private="file") +foreign odin_env { + @(link_name="write") + __write :: proc "contextless" (fd: u32, p: []byte) --- +} + +@(private="file") +__fd :: proc(file: FILE) -> (u32, bool) { + switch (uint(uintptr(file))) { + case 2: return 1, true // stdout + case 3: return 2, true // stderr + case: return 0, false + } +} diff --git a/vendor/libc-shim/stdio_os.odin b/vendor/libc-shim/stdio_os.odin new file mode 100644 index 000000000..f6d30a227 --- /dev/null +++ b/vendor/libc-shim/stdio_os.odin @@ -0,0 +1,104 @@ +#+build !freestanding +#+build !js +package odin_libc + +import "core:io" +import "core:c" +import "core:os" + +_fopen :: proc(path, _mode: cstring) -> FILE { + flags: os.File_Flags + + mode := string(_mode) + if len(mode) > 1 { + switch mode[0] { + case 'r': + flags += {.Read} + case 'w': + flags += {.Write, .Create, .Trunc} + case 'a': + flags += {.Write, .Create, .Append} + case: + return nil + } + + if len(mode) > 1 && mode[1] == '+' { + flags += {.Write, .Read} + } else if len(mode) > 2 && mode[1] == 'b' && mode[2] == '+' { + flags += {.Write, .Read} + } + } + + file, err := os.open(string(path), flags, os.Permissions_Read_Write_All) + if err != nil { + return nil + } + + return FILE(file) +} + +_fseek :: proc(_file: FILE, offset: c.long, whence: i32) -> i32 { + file := __file(_file) + if _, err := os.seek(file, i64(offset), io.Seek_From(whence)); err != nil { + return -1 + } + + return 0 +} + +_ftell :: proc(_file: FILE) -> c.long { + file := __file(_file) + pos, err := os.seek(file, 0, .Current) + if err != nil { + return -1 + } + + return c.long(pos) +} + +_fclose :: proc(_file: FILE) -> i32 { + file := __file(_file) + if err := os.close(file); err != nil { + return EOF + } + + return 0 +} + +_fread :: proc(buffer: [^]byte, size: uint, count: uint, _file: FILE) -> uint { + file := __file(_file) + n, _ := os.read(file, buffer[:size*count]) + return uint(max(0, n)) / size +} + +_fwrite :: proc(buffer: [^]byte, size: uint, count: uint, _file: FILE) -> uint { + file := __file(_file) + n, _ := os.write(file, buffer[:size*count]) + return uint(max(0, n)) / size +} + +_putchar :: proc(char: c.int) -> c.int { + n, err := os.write_byte(os.stdout, byte(char)) + if n == 0 || err != nil { + return EOF + } + return char +} + +_getchar :: proc() -> c.int { + ret: [1]byte + n, err := os.read(os.stdin, ret[:]) + if n == 0 || err != nil { + return EOF + } + return c.int(ret[0]) +} + +@(private="file") +__file :: proc(file: FILE) -> ^os.File { + switch (uint(uintptr(file))) { + case 2: return os.stdout + case 3: return os.stderr + case: return (^os.File)(file) + } +} diff --git a/vendor/libc/stdlib.odin b/vendor/libc-shim/stdlib.odin similarity index 96% rename from vendor/libc/stdlib.odin rename to vendor/libc-shim/stdlib.odin index 9f578a436..5dd4c53c1 100644 --- a/vendor/libc/stdlib.odin +++ b/vendor/libc-shim/stdlib.odin @@ -1,10 +1,10 @@ +// A (very small) subset of a libc implementation over Odin libraries for use with `vendor:*` packages. package odin_libc import "base:intrinsics" import "base:runtime" import "core:c" -import "core:os" import "core:slice" import "core:sort" import "core:strconv" @@ -165,11 +165,11 @@ atexit :: proc "c" (function: proc "c" ()) -> i32 { @(require, linkage="strong", link_name="exit") exit :: proc "c" (exit_code: c.int) -> ! { finish_atexit() - os.exit(int(exit_code)) + runtime.exit(int(exit_code)) } @(private, fini) -finish_atexit :: proc "c" () { +finish_atexit :: proc "contextless" () { n := intrinsics.atomic_exchange(&atexit_functions_count, 0) for function in atexit_functions[:n] { function() diff --git a/vendor/libc/string.odin b/vendor/libc-shim/string.odin similarity index 100% rename from vendor/libc/string.odin rename to vendor/libc-shim/string.odin diff --git a/vendor/libc/time.odin b/vendor/libc-shim/time.odin similarity index 100% rename from vendor/libc/time.odin rename to vendor/libc-shim/time.odin diff --git a/vendor/libc/libc.odin b/vendor/libc/libc.odin index 00d687109..7af35b090 100644 --- a/vendor/libc/libc.odin +++ b/vendor/libc/libc.odin @@ -1,25 +1,3 @@ package odin_libc -import "base:runtime" - -import "core:mem" - -@(private) -g_ctx: runtime.Context -@(private) -g_allocator: mem.Compat_Allocator - -@(init) -init_context :: proc() { - g_ctx = context - - // Wrapping the allocator with the mem.Compat_Allocator so we can - // mimic the realloc semantics. - mem.compat_allocator_init(&g_allocator, g_ctx.allocator) - g_ctx.allocator = mem.compat_allocator(&g_allocator) -} - -// NOTE: the allocator must respect an `old_size` of `-1` on resizes! -set_context :: proc(ctx := context) { - g_ctx = ctx -} +#panic("`vendor:libc` has been moved, use `vendor:libc-shim` instead.") diff --git a/vendor/lua/5.1/lua.odin b/vendor/lua/5.1/lua.odin index 5b7482931..f955e0dd3 100644 --- a/vendor/lua/5.1/lua.odin +++ b/vendor/lua/5.1/lua.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Lua 5.1 ; https://www.lua.org/manual/5.1/ ]]. package lua_5_1 import "base:intrinsics" @@ -13,7 +14,7 @@ when LUA_SHARED { when ODIN_OS == .Windows { // Does nothing special on windows foreign import lib "windows/lua5.1.dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua5.1.so" } else { foreign import lib "system:lua5.1" @@ -21,7 +22,7 @@ when LUA_SHARED { } else { when ODIN_OS == .Windows { foreign import lib "windows/lua5.1.dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua5.1.a" } else { foreign import lib "system:lua5.1" diff --git a/vendor/lua/5.2/lua.odin b/vendor/lua/5.2/lua.odin index bc47479e3..98d13cf69 100644 --- a/vendor/lua/5.2/lua.odin +++ b/vendor/lua/5.2/lua.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Lua 5.2 ; https://www.lua.org/manual/5.2/ ]]. package lua_5_2 import "base:intrinsics" @@ -13,7 +14,7 @@ when LUA_SHARED { when ODIN_OS == .Windows { // Does nothing special on windows foreign import lib "windows/lua52dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua52.so" } else { foreign import lib "system:lua5.2" @@ -21,7 +22,7 @@ when LUA_SHARED { } else { when ODIN_OS == .Windows { foreign import lib "windows/lua52dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua52.a" } else { foreign import lib "system:lua5.2" diff --git a/vendor/lua/5.3/lua.odin b/vendor/lua/5.3/lua.odin index 47215a327..2c0dc1fbf 100644 --- a/vendor/lua/5.3/lua.odin +++ b/vendor/lua/5.3/lua.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Lua 5.3 ; https://www.lua.org/manual/5.3/ ]]. package lua_5_3 import "base:intrinsics" @@ -13,7 +14,7 @@ when LUA_SHARED { when ODIN_OS == .Windows { // Does nothing special on windows foreign import lib "windows/lua53dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua53.so" } else { foreign import lib "system:lua5.3" @@ -21,7 +22,7 @@ when LUA_SHARED { } else { when ODIN_OS == .Windows { foreign import lib "windows/lua53dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua53.a" } else { foreign import lib "system:lua5.3" diff --git a/vendor/lua/5.4/include/luaconf.h b/vendor/lua/5.4/include/luaconf.h index 3ad294e4f..fbfa5781b 100644 --- a/vendor/lua/5.4/include/luaconf.h +++ b/vendor/lua/5.4/include/luaconf.h @@ -71,7 +71,7 @@ /* -@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. +@@ LUAI_IS32INT is true if and only if (⟺) 'int' has (at least) 32 bits. */ #define LUAI_IS32INT ((UINT_MAX >> 30) >= 3) diff --git a/vendor/lua/5.4/lua.odin b/vendor/lua/5.4/lua.odin index a45de4d49..3ffa68714 100644 --- a/vendor/lua/5.4/lua.odin +++ b/vendor/lua/5.4/lua.odin @@ -1,3 +1,4 @@ +// Bindings for [[ Lua 5.4 ; https://www.lua.org/manual/5.4/ ]]. package lua_5_4 import "base:intrinsics" @@ -13,7 +14,7 @@ when LUA_SHARED { when ODIN_OS == .Windows { // LUA_SHARED does nothing special on windows foreign import lib "windows/lua54dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua54.so" } else { foreign import lib "system:lua5.4" @@ -21,7 +22,7 @@ when LUA_SHARED { } else { when ODIN_OS == .Windows { foreign import lib "windows/lua54dll.lib" - } else when ODIN_OS == .Linux { + } else when ODIN_OS == .Linux && ODIN_ARCH == .amd64 { foreign import lib "linux/liblua54.a" } else { foreign import lib "system:lua5.4" diff --git a/vendor/microui/microui.odin b/vendor/microui/microui.odin index 08a96acf2..5f5646cc2 100644 --- a/vendor/microui/microui.odin +++ b/vendor/microui/microui.odin @@ -1,4 +1,6 @@ /* +An Odin-native source port of [[ rxi's microui ; https://github.com/rxi/microui ]] immediate mode UI. + ** Original work: Copyright (c) 2020 rxi ** Modified work: Copyright (c) 2020 oskarnp ** Modified work: Copyright (c) 2021 gingerBill @@ -21,7 +23,6 @@ ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ** IN THE SOFTWARE. */ - package microui import "core:fmt" diff --git a/vendor/miniaudio/common.odin b/vendor/miniaudio/common.odin index d72c3f251..1a3806734 100644 --- a/vendor/miniaudio/common.odin +++ b/vendor/miniaudio/common.odin @@ -20,12 +20,12 @@ foreign import lib { LIB } BINDINGS_VERSION_MAJOR :: 0 BINDINGS_VERSION_MINOR :: 11 -BINDINGS_VERSION_REVISION :: 21 +BINDINGS_VERSION_REVISION :: 24 BINDINGS_VERSION :: [3]u32{BINDINGS_VERSION_MAJOR, BINDINGS_VERSION_MINOR, BINDINGS_VERSION_REVISION} -BINDINGS_VERSION_STRING :: "0.11.21" +BINDINGS_VERSION_STRING :: "0.11.24" @(init) -version_check :: proc() { +version_check :: proc "contextless" () { v: [3]u32 version(&v.x, &v.y, &v.z) if v != BINDINGS_VERSION { @@ -43,7 +43,7 @@ version_check :: proc() { n += copy(buf[n:], "and executing `make`") } - panic(string(buf[:n])) + panic_contextless(string(buf[:n])) } } @@ -114,9 +114,9 @@ channel :: enum u8 { AUX_29 = 49, AUX_30 = 50, AUX_31 = 51, + POSITION_COUNT, LEFT = FRONT_LEFT, RIGHT = FRONT_RIGHT, - POSITION_COUNT = AUX_31 + 1, } result :: enum c.int { @@ -296,7 +296,7 @@ allocation_callbacks :: struct { } lcg :: struct { - state: i32, + state: u32, } diff --git a/vendor/miniaudio/data_conversion.odin b/vendor/miniaudio/data_conversion.odin index c33f54707..a6df39e3b 100644 --- a/vendor/miniaudio/data_conversion.odin +++ b/vendor/miniaudio/data_conversion.odin @@ -194,7 +194,7 @@ foreign lib { resampler_get_expected_output_frame_count :: proc(pResampler: ^resampler, inputFrameCount: u64, pOutputFrameCount: ^u64) -> result --- /* - Resets the resampler's timer and clears it's internal cache. + Resets the resampler's timer and clears its internal cache. */ resampler_reset :: proc(pResampler: ^resampler) -> result --- } @@ -421,7 +421,7 @@ foreign lib { /* Copies a channel map. - Both input and output channel map buffers must have a capacity of at at least `channels`. + Both input and output channel map buffers must have a capacity of at least `channels`. */ channel_map_copy :: proc(pOut: [^]channel, pIn: [^]channel, channels: u32) --- @@ -566,9 +566,9 @@ foreign lib { pcm_rb_uninit :: proc(pRB: ^pcm_rb) --- pcm_rb_reset :: proc(pRB: ^pcm_rb) --- pcm_rb_acquire_read :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result --- - pcm_rb_commit_read :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result --- + pcm_rb_commit_read :: proc(pRB: ^pcm_rb, sizeInFrames: u32) -> result --- pcm_rb_acquire_write :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result --- - pcm_rb_commit_write :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result --- + pcm_rb_commit_write :: proc(pRB: ^pcm_rb, sizeInFrames: u32) -> result --- pcm_rb_seek_read :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result --- pcm_rb_seek_write :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result --- pcm_rb_pointer_distance :: proc(pRB: ^pcm_rb) -> i32 --- /* Return value is in frames. */ diff --git a/vendor/miniaudio/decoding.odin b/vendor/miniaudio/decoding.odin index f1fa279ac..e2f33b8e7 100644 --- a/vendor/miniaudio/decoding.odin +++ b/vendor/miniaudio/decoding.odin @@ -71,7 +71,7 @@ decoder :: struct { pInputCache: rawptr, /* In input format. Can be null if it's not needed. */ inputCacheCap: u64, /* The capacity of the input cache. */ inputCacheConsumed: u64, /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */ - inputCacheRemaining: u64, /* The number of valid frames remaining in the cahce. */ + inputCacheRemaining: u64, /* The number of valid frames remaining in the cache. */ allocationCallbacks: allocation_callbacks, data: struct #raw_union { vfs: struct { @@ -111,7 +111,7 @@ foreign lib { decoder_read_pcm_frames :: proc(pDecoder: ^decoder, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result --- /* - Seeks to a PCM frame based on it's absolute index. + Seeks to a PCM frame based on its absolute index. This is not thread safe without your own synchronization. */ diff --git a/vendor/miniaudio/device_io_procs.odin b/vendor/miniaudio/device_io_procs.odin index 21ac1afd7..ced6e7403 100644 --- a/vendor/miniaudio/device_io_procs.odin +++ b/vendor/miniaudio/device_io_procs.odin @@ -12,6 +12,8 @@ foreign lib { device_job_thread_uninit :: proc(pJobThread: ^device_job_thread, pAllocationCallbacks: ^allocation_callbacks) --- device_job_thread_post :: proc(pJobThread: ^device_job_thread, pJob: ^job) -> result --- device_job_thread_next :: proc(pJobThread: ^device_job_thread, pJob: ^job) -> result --- + + device_id_equal :: proc(pA: ^device_id, pB: ^device_id) -> b32 --- /* Initializes a `ma_context_config` object. @@ -370,6 +372,9 @@ foreign lib { This function will allocate memory internally for the device lists and return a pointer to them through the `ppPlaybackDeviceInfos` and `ppCaptureDeviceInfos` parameters. If you do not want to incur the overhead of these allocations consider using `ma_context_enumerate_devices()` which will instead use a callback. + Note that this only retrieves the ID and name/description of the device. The reason for only retrieving basic information is that it would otherwise require + opening the backend device in order to probe it for more detailed information which can be inefficient. Consider using `ma_context_get_device_info()` for this, + but don't call it from within the enumeration callback. Parameters ---------- @@ -411,7 +416,7 @@ foreign lib { See Also -------- - ma_context_get_devices() + ma_context_enumerate_devices() */ context_get_devices :: proc(pContext: ^context_type, ppPlaybackDeviceInfos: ^[^]device_info, pPlaybackDeviceCount: ^u32, ppCaptureDeviceInfos: ^[^]device_info, pCaptureDeviceCount: ^u32) -> result --- @@ -550,7 +555,7 @@ foreign lib { playback, capture, full-duplex or loopback. (Note that loopback mode is only supported on select backends.) Sending and receiving audio data to and from the device is done via a callback which is fired by miniaudio at periodic time intervals. - The frequency at which data is delivered to and from a device depends on the size of it's period. The size of the period can be defined in terms of PCM frames + The frequency at which data is delivered to and from a device depends on the size of its period. The size of the period can be defined in terms of PCM frames or milliseconds, whichever is more convenient. Generally speaking, the smaller the period, the lower the latency at the expense of higher CPU usage and increased risk of glitching due to the more frequent and granular data deliver intervals. The size of a period will depend on your requirements, but miniaudio's defaults should work fine for most scenarios. If you're building a game you should leave this fairly small, whereas if you're building a simple @@ -624,7 +629,7 @@ foreign lib { performanceProfile A hint to miniaudio as to the performance requirements of your program. Can be either `ma_performance_profile_low_latency` (default) or - `ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at it's default value. + `ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at its default value. noPreSilencedOutputBuffer When set to true, the contents of the output buffer passed into the data callback will be left undefined. When set to false (default), the contents of @@ -664,7 +669,7 @@ foreign lib { A pointer that will passed to callbacks in pBackendVTable. resampling.linear.lpfOrder - The linear resampler applies a low-pass filter as part of it's processing for anti-aliasing. This setting controls the order of the filter. The higher + The linear resampler applies a low-pass filter as part of its processing for anti-aliasing. This setting controls the order of the filter. The higher the value, the better the quality, in general. Setting this to 0 will disable low-pass filtering altogether. The maximum value is `MA_MAX_FILTER_ORDER`. The default value is `min(4, MA_MAX_FILTER_ORDER)`. @@ -741,6 +746,9 @@ foreign lib { pulse.pStreamNameCapture PulseAudio only. Sets the stream name for capture. + pulse.channelMap + PulseAudio only. Sets the channel map that is requested from PulseAudio. See MA_PA_CHANNEL_MAP_* constants. Defaults to MA_PA_CHANNEL_MAP_AIFF. + coreaudio.allowNominalSampleRateChange Core Audio only. Desktop only. When enabled, allows the sample rate of the device to be changed at the operating system level. This is disabled by default in order to prevent intrusive changes to the user's system. This is useful if you want to use a sample rate @@ -914,7 +922,7 @@ foreign lib { Remarks ------- - You only need to use this function if you want to configure the context differently to it's defaults. You should never use this function if you want to manage + You only need to use this function if you want to configure the context differently to its defaults. You should never use this function if you want to manage your own context. See the documentation for `ma_context_init()` for information on the different context configuration options. @@ -1598,7 +1606,7 @@ foreign lib { ---------- pBackends (out, optional) A pointer to the buffer that will receive the enabled backends. Set to NULL to retrieve the backend count. Setting - the capacity of the buffer to `MA_BUFFER_COUNT` will guarantee it's large enough for all backends. + the capacity of the buffer to `MA_BACKEND_COUNT` will guarantee it's large enough for all backends. backendCap (in) The capacity of the `pBackends` buffer. diff --git a/vendor/miniaudio/device_io_types.odin b/vendor/miniaudio/device_io_types.odin index b52a3f423..924bcda59 100644 --- a/vendor/miniaudio/device_io_types.odin +++ b/vendor/miniaudio/device_io_types.odin @@ -93,16 +93,16 @@ device_notification :: struct { data: struct #raw_union { started: struct { _unused: c.int, - }, + } `raw_union_tag:"type=.started"`, stopped: struct { _unused: c.int, - }, + } `raw_union_tag:"type=.stopped"`, rerouted: struct { _unused: c.int, - }, + } `raw_union_tag:"type=.rerouted"`, interruption: struct { _unused: c.int, - }, + } `raw_union_tag:"type=.interruption_began,.interruption_ended,"`, }, } @@ -427,6 +427,7 @@ device_config :: struct { pulse: struct { pStreamNamePlayback: cstring, pStreamNameCapture: cstring, + channelMap: i32, }, coreaudio: struct { allowNominalSampleRateChange: b32, /* Desktop only. When enabled, allows changing of the sample rate at the operating system level. */ @@ -443,6 +444,7 @@ device_config :: struct { allowedCapturePolicy: aaudio_allowed_capture_policy, noAutoStartAfterReroute: b32, enableCompatibilityWorkarounds: b32, + allowSetBufferCapacity: b32, }, } @@ -514,7 +516,7 @@ and on output returns detailed information about the device in `ma_device_info`. case when the device ID is NULL, in which case information about the default device needs to be retrieved. Once the context has been created and the device ID retrieved (if using anything other than the default device), the device can be created. -This is a little bit more complicated than initialization of the context due to it's more complicated configuration. When initializing a +This is a little bit more complicated than initialization of the context due to its more complicated configuration. When initializing a device, a duplex device may be requested. This means a separate data format needs to be specified for both playback and capture. On input, the data format is set to what the application wants. On output it's set to the native format which should match as closely as possible to the requested format. The conversion between the format requested by the application and the device's native format will be handled @@ -535,10 +537,10 @@ asynchronous reading and writing, `onDeviceStart()` and `onDeviceStop()` should The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the `onDeviceRead()` and `onDeviceWrite()` callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the -backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within it's callback. +backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within its callback. This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback. -If the backend requires absolute flexibility with it's data delivery, it can optionally implement the `onDeviceDataLoop()` callback +If the backend requires absolute flexibility with its data delivery, it can optionally implement the `onDeviceDataLoop()` callback which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional. The audio thread should run data delivery logic in a loop while `ma_device_get_state() == ma_device_state_started` and no errors have been @@ -575,6 +577,9 @@ context_config :: struct { threadStackSize: c.size_t, pUserData: rawptr, allocationCallbacks: allocation_callbacks, + dsound: struct { + hWnd: handle, /* HWND. Optional window handle to pass into SetCooperativeLevel(). Will default to the foreground window, and if that fails, the desktop window. */ + }, alsa: struct { useVerboseDeviceEnumeration: b32, }, @@ -649,6 +654,7 @@ context_type :: struct { } when SUPPORT_WASAPI else struct {}), dsound: (struct { + hWnd: handle, /* Can be null. */ hDSoundDLL: handle, DirectSoundCreate: proc "system" (), DirectSoundEnumerateA: proc "system" (), @@ -692,6 +698,7 @@ context_type :: struct { snd_pcm_hw_params_set_rate_resample: proc "system" (), snd_pcm_hw_params_set_rate: proc "system" (), snd_pcm_hw_params_set_rate_near: proc "system" (), + snd_pcm_hw_params_set_rate_minmax: proc "system" (), snd_pcm_hw_params_set_buffer_size_near: proc "system" (), snd_pcm_hw_params_set_periods_near: proc "system" (), snd_pcm_hw_params_set_access: proc "system" (), @@ -1195,6 +1202,8 @@ device :: struct { aaudio: (struct { /*AAudioStream**/ pStreamPlayback: rawptr, /*AAudioStream**/ pStreamCapture: rawptr, + rerouteLock: mutex, + isTearingDown: b32, usage: aaudio_usage, contentType: aaudio_content_type, inputPreset: aaudio_input_preset, diff --git a/vendor/miniaudio/doc.odin b/vendor/miniaudio/doc.odin index 33c613ae4..32c83cb46 100644 --- a/vendor/miniaudio/doc.odin +++ b/vendor/miniaudio/doc.odin @@ -1,17 +1,15 @@ -package miniaudio - /* -Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.11.21 - 2023-11-15 +Bindings for [[ miniaudio ; https://miniaud.io/docs ]] audio playback and capture library. + +Choice of public domain or MIT-0. See license statements at the end of this file. +miniaudio - v0.11.24 - 2025-09-11 David Reid - mackron@gmail.com Website: https://miniaud.io Documentation: https://miniaud.io/docs GitHub: https://github.com/mackron/miniaudio -*/ -/* 1. Introduction =============== miniaudio is a single file library for audio playback and capture. To use it, do the following in @@ -295,14 +293,14 @@ avoids the same sound being loaded multiple times. The node graph is used for mixing and effect processing. The idea is that you connect a number of nodes into the graph by connecting each node's outputs to another node's inputs. Each node can -implement it's own effect. By chaining nodes together, advanced mixing and effect processing can +implement its own effect. By chaining nodes together, advanced mixing and effect processing can be achieved. The engine encapsulates both the resource manager and the node graph to create a simple, easy to use high level API. The resource manager and node graph APIs are covered in more later sections of this manual. -The code below shows how you can initialize an engine using it's default configuration. +The code below shows how you can initialize an engine using its default configuration. ```c ma_result result; @@ -390,7 +388,7 @@ Sounds are not started by default. Start a sound with `ma_sound_start()` and sto `ma_sound_stop()`. When a sound is stopped, it is not rewound to the start. Use `ma_sound_seek_to_pcm_frame(&sound, 0)` to seek back to the start of a sound. By default, starting and stopping sounds happens immediately, but sometimes it might be convenient to schedule the sound -the be started and/or stopped at a specific time. This can be done with the following functions: +to be started and/or stopped at a specific time. This can be done with the following functions: ```c ma_sound_set_start_time_in_pcm_frames() @@ -400,7 +398,7 @@ the be started and/or stopped at a specific time. This can be done with the foll ``` The start/stop time needs to be specified based on the absolute timer which is controlled by the -engine. The current global time time in PCM frames can be retrieved with +engine. The current global time in PCM frames can be retrieved with `ma_engine_get_time_in_pcm_frames()`. The engine's global time can be changed with `ma_engine_set_time_in_pcm_frames()` for synchronization purposes if required. Note that scheduling a start time still requires an explicit call to `ma_sound_start()` before anything will play: @@ -432,11 +430,11 @@ Sounds and sound groups are nodes in the engine's node graph and can be plugged API. This makes it possible to connect sounds and sound groups to effect nodes to produce complex effect chains. -A sound can have it's volume changed with `ma_sound_set_volume()`. If you prefer decibel volume +A sound can have its volume changed with `ma_sound_set_volume()`. If you prefer decibel volume control you can use `ma_volume_db_to_linear()` to convert from decibel representation to linear. Panning and pitching is supported with `ma_sound_set_pan()` and `ma_sound_set_pitch()`. If you know -a sound will never have it's pitch changed with `ma_sound_set_pitch()` or via the doppler effect, +a sound will never have its pitch changed with `ma_sound_set_pitch()` or via the doppler effect, you can specify the `MA_SOUND_FLAG_NO_PITCH` flag when initializing the sound for an optimization. By default, sounds and sound groups have spatialization enabled. If you don't ever want to @@ -462,6 +460,11 @@ is at the end, use `ma_sound_at_end()`. Looping of a sound can be controlled wit miniaudio should work cleanly out of the box without the need to download or install any dependencies. See below for platform-specific details. +This library has been designed to be added directly to your source tree which is the preferred way +of using it, but you can compile it as a normal library if that's your preference. Be careful if +compiling as a shared object because miniaudio is not ABI compatible between any release, including +bug fix releases. It's recommended you link statically + Note that GCC and Clang require `-msse2`, `-mavx2`, etc. for SIMD optimizations. If you get errors about undefined references to `__sync_val_compare_and_swap_8`, `__atomic_load_8`, @@ -485,21 +488,12 @@ link the relevant frameworks but should compile cleanly out of the box with Xcod through the command line requires linking to `-lpthread` and `-lm`. Due to the way miniaudio links to frameworks at runtime, your application may not pass Apple's -notarization process. To fix this there are two options. The first is to use the -`MA_NO_RUNTIME_LINKING` option, like so: - - ```c - #ifdef __APPLE__ - #define MA_NO_RUNTIME_LINKING - #endif - #define MINIAUDIO_IMPLEMENTATION - #include "miniaudio.h" - ``` - -This will require linking with `-framework CoreFoundation -framework CoreAudio -framework AudioToolbox`. -If you get errors about AudioToolbox, try with `-framework AudioUnit` instead. You may get this when -using older versions of iOS. Alternatively, if you would rather keep using runtime linking you can -add the following to your entitlements.xcent file: +notarization process. To fix this there are two options. The first is to compile with +`-DMA_NO_RUNTIME_LINKING` which in turn will require linking with +`-framework CoreFoundation -framework CoreAudio -framework AudioToolbox`. If you get errors about +AudioToolbox, try with `-framework AudioUnit` instead. You may get this when using older versions +of iOS. Alternatively, if you would rather keep using runtime linking you can add the following to +your entitlements.xcent file: ``` com.apple.security.cs.allow-dyld-environment-variables @@ -540,7 +534,7 @@ you'll need to disable run-time linking with `MA_NO_RUNTIME_LINKING` and link wi The Emscripten build emits Web Audio JavaScript directly and should compile cleanly out of the box. You cannot use `-std=c*` compiler flags, nor `-ansi`. -You can enable the use of AudioWorkets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling +You can enable the use of AudioWorklets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling with the following options: -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY @@ -557,7 +551,7 @@ To run locally, you'll need to use emrun: 2.7. Build Options ------------------ -`#define` these options before including miniaudio.h. +`#define` these options before including miniaudio.c, or pass them as compiler flags: +----------------------------------+--------------------------------------------------------------------+ | Option | Description | @@ -588,6 +582,8 @@ To run locally, you'll need to use emrun: +----------------------------------+--------------------------------------------------------------------+ | MA_NO_WEBAUDIO | Disables the Web Audio backend. | +----------------------------------+--------------------------------------------------------------------+ + | MA_NO_CUSTOM | Disables support for custom backends. | + +----------------------------------+--------------------------------------------------------------------+ | MA_NO_NULL | Disables the null backend. | +----------------------------------+--------------------------------------------------------------------+ | MA_ENABLE_ONLY_SPECIFIC_BACKENDS | Disables all backends by default and requires `MA_ENABLE_*` to | @@ -632,6 +628,9 @@ To run locally, you'll need to use emrun: | MA_ENABLE_WEBAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | | | enable the Web Audio backend. | +----------------------------------+--------------------------------------------------------------------+ + | MA_ENABLE_CUSTOM | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | + | | enable custom backends. | + +----------------------------------+--------------------------------------------------------------------+ | MA_ENABLE_NULL | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | | | enable the null backend. | +----------------------------------+--------------------------------------------------------------------+ @@ -695,11 +694,30 @@ To run locally, you'll need to use emrun: | | You may need to enable this if your target platform does not allow | | | runtime linking via `dlopen()`. | +----------------------------------+--------------------------------------------------------------------+ + | MA_USE_STDINT | (Pass this in a compiler flag. Do not #define this before | + | | miniaudio.c) Forces the use of stdint.h for sized types. | + +----------------------------------+--------------------------------------------------------------------+ | MA_DEBUG_OUTPUT | Enable `printf()` output of debug logs (`MA_LOG_LEVEL_DEBUG`). | +----------------------------------+--------------------------------------------------------------------+ | MA_COINIT_VALUE | Windows only. The value to pass to internal calls to | | | `CoInitializeEx()`. Defaults to `COINIT_MULTITHREADED`. | +----------------------------------+--------------------------------------------------------------------+ + | MA_FORCE_UWP | Windows only. Affects only the WASAPI backend. Will force the | + | | WASAPI backend to use the UWP code path instead of the regular | + | | desktop path. This is normally auto-detected and should rarely be | + | | needed to be used explicitly, but can be useful for debugging. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_ON_THREAD_ENTRY | Defines some code that will be executed as soon as an internal | + | | miniaudio-managed thread is created. This will be the first thing | + | | to be executed by the thread entry point. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_ON_THREAD_EXIT | Defines some code that will be executed from the entry point of an | + | | internal miniaudio-managed thread upon exit. This will be the last | + | | thing to be executed before the thread's entry point exits. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_THREAD_DEFAULT_STACK_SIZE | If set, specifies the default stack size used by miniaudio-managed | + | | threads. | + +----------------------------------+--------------------------------------------------------------------+ | MA_API | Controls how public APIs should be decorated. Default is `extern`. | +----------------------------------+--------------------------------------------------------------------+ @@ -865,7 +883,7 @@ read data within a certain range of the underlying data. To do this you can use This is useful if you have a sound bank where many sounds are stored in the same file and you want the data source to only play one of those sub-sounds. Note that once the range is set, everything -that takes a position, such as cursors and loop points, should always be relatvie to the start of +that takes a position, such as cursors and loop points, should always be relative to the start of the range. When the range is set, any previously defined loop point will be reset. Custom loop points can also be used with data sources. By default, data sources will loop after @@ -873,7 +891,7 @@ they reach the end of the data source, but if you need to loop at a specific loc the following: ```c - result = ma_data_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames); + result = ma_data_source_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames); if (result != MA_SUCCESS) { return result; // Failed to set the loop point. } @@ -1311,7 +1329,7 @@ only works for sounds that were initialized with `ma_sound_init_from_file()` and When you initialize a sound, if you specify a sound group the sound will be attached to that group automatically. If you set it to NULL, it will be automatically attached to the engine's endpoint. -If you would instead rather leave the sound unattached by default, you can can specify the +If you would instead rather leave the sound unattached by default, you can specify the `MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT` flag. This is useful if you want to set up a complex node graph. @@ -1688,6 +1706,7 @@ combination of the following flags: MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT + MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING ``` When no flags are specified (set to 0), the sound will be fully loaded into memory, but not @@ -1708,6 +1727,14 @@ can instead stream audio data which you can do by specifying the second pages. When a new page needs to be decoded, a job will be posted to the job queue and then subsequently processed in a job thread. +The `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING` flag can be used so that the sound will loop +when it reaches the end by default. It's recommended you use this flag when you want to have a +looping streaming sound. If you try loading a very short sound as a stream, you will get a glitch. +This is because the resource manager needs to pre-fill the initial buffer at initialization time, +and if you don't specify the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING` flag, the resource +manager will assume the sound is not looping and will stop filling the buffer when it reaches the +end, therefore resulting in a discontinuous buffer. + For in-memory sounds, reference counting is used to ensure the data is loaded only once. This means multiple calls to `ma_resource_manager_data_source_init()` with the same file path will result in the file data only being loaded once. Each call to `ma_resource_manager_data_source_init()` must be @@ -1722,7 +1749,7 @@ actual file paths. When `ma_resource_manager_data_source_init()` is called (with `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag), the resource manager will look for these explicitly registered data buffers and, if found, will use it as the backing data for the data source. Note that the resource manager does *not* make a copy of this data so it is up to the -caller to ensure the pointer stays valid for it's lifetime. Use +caller to ensure the pointer stays valid for its lifetime. Use `ma_resource_manager_unregister_data()` to unregister the self-managed data. You can also use `ma_resource_manager_register_file()` and `ma_resource_manager_unregister_file()` to register and unregister a file. It does not make sense to use the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` @@ -2033,7 +2060,7 @@ In the above graph, it starts with two data sources whose outputs are attached t splitter node. It's at this point that the two data sources are mixed. After mixing, the splitter performs it's processing routine and produces two outputs which is simply a duplication of the input stream. One output is attached to a low pass filter, whereas the other output is attached to -a echo/delay. The outputs of the the low pass filter and the echo are attached to the endpoint, and +a echo/delay. The outputs of the low pass filter and the echo are attached to the endpoint, and since they're both connected to the same input bus, they'll be mixed. Each input bus must be configured to accept the same number of channels, but the number of channels @@ -2074,7 +2101,7 @@ data from the graph: ``` When you read audio data, miniaudio starts at the node graph's endpoint node which then pulls in -data from it's input attachments, which in turn recursively pull in data from their inputs, and so +data from its input attachments, which in turn recursively pull in data from their inputs, and so on. At the start of the graph there will be some kind of data source node which will have zero inputs and will instead read directly from a data source. The base nodes don't literally need to read from a `ma_data_source` object, but they will always have some kind of underlying object that @@ -2320,7 +2347,7 @@ You can start and stop a node with the following: By default the node is in a started state, but since it won't be connected to anything won't actually be invoked by the node graph until it's connected. When you stop a node, data will not be -read from any of it's input connections. You can use this property to stop a group of sounds +read from any of its input connections. You can use this property to stop a group of sounds atomically. You can configure the initial state of a node in it's config: @@ -2413,29 +2440,29 @@ audio thread is finished so that control is not handed back to the caller thereb chance to free the node's memory. When the audio thread is processing a node, it does so by reading from each of the output buses of -the node. In order for a node to process data for one of it's output buses, it needs to read from -each of it's input buses, and so on an so forth. It follows that once all output buses of a node +the node. In order for a node to process data for one of its output buses, it needs to read from +each of its input buses, and so on an so forth. It follows that once all output buses of a node are detached, the node as a whole will be disconnected and no further processing will occur unless it's output buses are reattached, which won't be happening when the node is being uninitialized. By having `ma_node_detach_output_bus()` wait until the audio thread is finished with it, we can simplify a few things, at the expense of making `ma_node_detach_output_bus()` a bit slower. By doing this, the implementation of `ma_node_uninit()` becomes trivial - just detach all output -nodes, followed by each of the attachments to each of it's input nodes, and then do any final clean +nodes, followed by each of the attachments to each of its input nodes, and then do any final clean up. With the above design, the worst-case scenario is `ma_node_detach_output_bus()` taking as long as it takes to process the output bus being detached. This will happen if it's called at just the wrong moment where the audio thread has just iterated it and has just started processing. The caller of `ma_node_detach_output_bus()` will stall until the audio thread is finished, which -includes the cost of recursively processing it's inputs. This is the biggest compromise made with -the approach taken by miniaudio for it's lock-free processing system. The cost of detaching nodes +includes the cost of recursively processing its inputs. This is the biggest compromise made with +the approach taken by miniaudio for its lock-free processing system. The cost of detaching nodes earlier in the pipeline (data sources, for example) will be cheaper than the cost of detaching higher level nodes, such as some kind of final post-processing endpoint. If you need to do mass detachments, detach starting from the lowest level nodes and work your way towards the final endpoint node (but don't try detaching the node graph's endpoint). If the audio thread is not running, detachment will be fast and detachment in any order will be the same. The reason nodes need to wait for their input attachments to complete is due to the potential for desyncs between -data sources. If the node was to terminate processing mid way through processing it's inputs, +data sources. If the node was to terminate processing mid way through processing its inputs, there's a chance that some of the underlying data sources will have been read, but then others not. That will then result in a potential desynchronization when detaching and reattaching higher-level nodes. A possible solution to this is to have an option when detaching to terminate processing @@ -2806,7 +2833,7 @@ weights. Custom weights can be passed in as the last parameter of `ma_channel_converter_config_init()`. Predefined channel maps can be retrieved with `ma_channel_map_init_standard()`. This takes a -`ma_standard_channel_map` enum as it's first parameter, which can be one of the following: +`ma_standard_channel_map` enum as its first parameter, which can be one of the following: +-----------------------------------+-----------------------------------------------------------+ | Name | Description | @@ -2892,7 +2919,7 @@ like the following: ma_resample_algorithm_linear); ma_resampler resampler; - ma_result result = ma_resampler_init(&config, &resampler); + ma_result result = ma_resampler_init(&config, NULL, &resampler); if (result != MA_SUCCESS) { // An error occurred... } @@ -3134,7 +3161,7 @@ Biquad filtering is achieved with the `ma_biquad` API. Example: ```c ma_biquad_config config = ma_biquad_config_init(ma_format_f32, channels, b0, b1, b2, a0, a1, a2); - ma_result result = ma_biquad_init(&config, &biquad); + ma_result result = ma_biquad_init(&config, NULL, &biquad); if (result != MA_SUCCESS) { // Error. } @@ -3712,3 +3739,4 @@ See below for some tips on improving performance. - When compiling with VC6 and earlier, decoding is restricted to files less than 2GB in size. This is due to 64-bit file APIs not being available. */ +package miniaudio diff --git a/vendor/miniaudio/engine.odin b/vendor/miniaudio/engine.odin index a06e6c62c..0a3887d4b 100644 --- a/vendor/miniaudio/engine.odin +++ b/vendor/miniaudio/engine.odin @@ -18,7 +18,8 @@ sound_flag :: enum c.int { ASYNC = 2, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */ WAIT_INIT = 3, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */ UNKNOWN_LENGTH = 4, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH */ - + LOOPING = 5, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING */ + /* ma_sound specific flags. */ NO_DEFAULT_ATTACHMENT = 12, /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */ NO_PITCH = 13, /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */ @@ -47,17 +48,18 @@ engine_node_config :: struct { isPitchDisabled: b8, /* Pitching can be explicitly disable with MA_SOUND_FLAG_NO_PITCH to optimize processing. */ isSpatializationDisabled: b8, /* Spatialization can be explicitly disabled with MA_SOUND_FLAG_NO_SPATIALIZATION. */ pinnedListenerIndex: u8, /* The index of the listener this node should always use for spatialization. If set to MA_LISTENER_INDEX_CLOSEST the engine will use the closest listener. */ + resampling: resampler_config, } /* Base node object for both ma_sound and ma_sound_group. */ engine_node :: struct { - baseNode: node_base, /* Must be the first member for compatiblity with the ma_node API. */ + baseNode: node_base, /* Must be the first member for compatibility with the ma_node API. */ pEngine: ^engine, /* A pointer to the engine. Set based on the value from the config. */ sampleRate: u32, /* The sample rate of the input data. For sounds backed by a data source, this will be the data source's sample rate. Otherwise it'll be the engine's sample rate. */ volumeSmoothTimeInPCMFrames: u32, monoExpansionMode: mono_expansion_mode, fader: fader, - resampler: linear_resampler, /* For pitch shift. */ + resampler: resampler, /* For pitch shift. */ spatializer: spatializer, panner: panner, volumeGainer: gainer, /* This will only be used if volumeSmoothTimeInPCMFrames is > 0. */ @@ -113,14 +115,16 @@ sound_config :: struct { rangeEndInPCMFrames: u64, loopPointBegInPCMFrames: u64, loopPointEndInPCMFrames: u64, - isLooping: b32, endCallback: sound_end_proc, /* Fired when the sound reaches the end. Will be fired from the audio thread. Do not restart, uninitialize or otherwise change the state of the sound from here. Instead fire an event or set a variable to indicate to a different thread to change the start of the sound. Will not be fired in response to a scheduled stop with ma_sound_set_stop_time_*(). */ pEndCallbackUserData: rawptr, + pitchResampling: resampler_config, initNotifications: resource_manager_pipeline_notifications, pDoneFence: ^fence, /* Deprecated. Use initNotifications instead. Released when the resource manager has finished decoding the entire sound. Not used with streams. */ + + isLooping: b32, /* Deprecated. Use the MA_SOUND_FLAG_LOOPING in `flags` instead. */ } sound :: struct { @@ -132,6 +136,10 @@ sound :: struct { endCallback: sound_end_proc, pEndCallbackUserData: rawptr, + pProcessingCache: ^f32, + processingCacheFramesRemaining: u32, + processingCacheMap: u32, + ownsDataSource: b8, /* @@ -164,8 +172,12 @@ foreign lib { sound_get_data_source :: proc(pSound: ^sound) -> ^data_source --- sound_start :: proc(pSound: ^sound) -> result --- sound_stop :: proc(pSound: ^sound) -> result --- - sound_stop_with_fade_in_pcm_frames :: proc(pSound: ^sound, fadeLengthInFrames: u64) --- /* Will overwrite any scheduled stop and fade. */ - sound_stop_with_fade_in_milliseconds :: proc(pSound: ^sound, fadeLengthInFrames: u64) --- /* Will overwrite any scheduled stop and fade. */ + sound_stop_with_fade_in_pcm_frames :: proc(pSound: ^sound, fadeLengthInFrames: u64) --- /* Will overwrite any scheduled stop and fade. If you want to restart the sound, first reset it with `ma_sound_reset_stop_time_and_fade()`. There are plans to make this less awkward in the future. */ + sound_stop_with_fade_in_milliseconds :: proc(pSound: ^sound, fadeLengthInFrames: u64) --- /* Will overwrite any scheduled stop and fade. If you want to restart the sound, first reset it with `ma_sound_reset_stop_time_and_fade()`. There are plans to make this less awkward in the future. */ + sound_reset_start_time :: proc(pSound: ^sound) --- + sound_reset_stop_time :: proc(pSound: ^sound) --- + sound_reset_fade :: proc(pSound: ^sound) --- + sound_reset_stop_time_and_fade :: proc(pSound: ^sound) --- /* Resets fades and scheduled stop time. Does not seek back to the start. */ sound_set_volume :: proc(pSound: ^sound, volume: f32) --- sound_get_volume :: proc(pSound: ^sound) -> f32 --- sound_set_pan :: proc(pSound: ^sound, pan: f32) --- @@ -226,6 +238,7 @@ foreign lib { sound_is_looping :: proc(pSound: ^sound) -> b32 --- sound_at_end :: proc(pSound: ^sound) -> b32 --- sound_seek_to_pcm_frame :: proc(pSound: ^sound, frameIndex: u64) -> result --- /* Just a wrapper around ma_data_source_seek_to_pcm_frame(). */ + sound_seek_to_second :: proc(pSound: ^sound, seekPointInSeconds: f32) -> result --- /* Abstraction to ma_sound_seek_to_pcm_frame() */ sound_get_data_format :: proc(pSound: ^sound, pFormat: ^format, pChannels, pSampleRate: ^u32, pChannelMap: ^channel, channelMapCap: c.size_t) -> result --- sound_get_cursor_in_pcm_frames :: proc(pSound: ^sound, pCursor: ^u64) -> result --- sound_get_length_in_pcm_frames :: proc(pSound: ^sound, pLength: ^u64) -> result --- @@ -316,13 +329,14 @@ engine_config :: struct { pLog: ^log, /* When set to NULL, will use the context's log. */ listenerCount: u32, /* Must be between 1 and MA_ENGINE_MAX_LISTENERS. */ channels: u32, /* The number of channels to use when mixing and spatializing. When set to 0, will use the native channel count of the device. */ - sampleRate: u32, /* The sample rate. When set to 0 will use the native channel count of the device. */ + sampleRate: u32, /* The sample rate. When set to 0 will use the native sample rate of the device. */ periodSizeInFrames: u32, /* If set to something other than 0, updates will always be exactly this size. The underlying device may be a different size, but from the perspective of the mixer that won't matter.*/ periodSizeInMilliseconds: u32, /* Used if periodSizeInFrames is unset. */ gainSmoothTimeInFrames: u32, /* The number of frames to interpolate the gain of spatialized sounds across. If set to 0, will use gainSmoothTimeInMilliseconds. */ gainSmoothTimeInMilliseconds: u32, /* When set to 0, gainSmoothTimeInFrames will be used. If both are set to 0, a default value will be used. */ defaultVolumeSmoothTimeInPCMFrames: u32, /* Defaults to 0. Controls the default amount of smoothing to apply to volume changes to sounds. High values means more smoothing at the expense of high latency (will take longer to reach the new volume). */ + preMixStackSizeInBytes: u32, /* A stack is used for internal processing in the node graph. This allows you to configure the size of this stack. Smaller values will reduce the maximum depth of your node graph. You should rarely need to modify this. */ allocationCallbacks: allocation_callbacks, noAutoStart: b32, /* When set to true, requires an explicit call to ma_engine_start(). This is false by default, meaning the engine will be started automatically in ma_engine_init(). */ @@ -331,6 +345,8 @@ engine_config :: struct { pResourceManagerVFS: ^vfs, /* A pointer to a pre-allocated VFS object to use with the resource manager. This is ignored if pResourceManager is not NULL. */ onProcess: engine_process_proc, /* Fired at the end of each call to ma_engine_read_pcm_frames(). For engine's that manage their own internal device (the default configuration), this will be fired from the audio thread, and you do not need to call ma_engine_read_pcm_frames() manually in order to trigger this. */ pProcessUserData: rawptr, /* User data that's passed into onProcess. */ + resourceManagerResampling: resampler_config, /* The resampling config to use with the resource manager. */ + pitchResampling: resampler_config, /* The resampling config for the pitch and Doppler effects. You will typically want this to be a fast resampler. For high quality stuff, it's recommended that you pre-sample. */ } engine :: struct { @@ -344,7 +360,7 @@ engine :: struct { allocationCallbacks: allocation_callbacks, ownsResourceManager: b8, ownsDevice: b8, - inlinedSoundLock: spinlock, /* For synchronizing access so the inlined sound list. */ + inlinedSoundLock: spinlock, /* For synchronizing access to the inlined sound list. */ pInlinedSoundHead: ^sound_inlined, /* The first inlined sound. Inlined sounds are tracked in a linked list. */ inlinedSoundCount: u32, /*atomic*/ /* The total number of allocated inlined sound objects. Used for debugging. */ gainSmoothTimeInFrames: u32, /* The number of frames to interpolate the gain of spatialized sounds across. */ @@ -354,6 +370,8 @@ engine :: struct { monoExpansionMode: mono_expansion_mode, onProcess: engine_process_proc, pProcessUserData: rawptr, + + pitchResamplingConfig: resampler_config, } @(default_calling_convention="c", link_prefix="ma_") diff --git a/vendor/miniaudio/lib/miniaudio.lib b/vendor/miniaudio/lib/miniaudio.lib index d339c746e..f63ddf09d 100644 Binary files a/vendor/miniaudio/lib/miniaudio.lib and b/vendor/miniaudio/lib/miniaudio.lib differ diff --git a/vendor/miniaudio/logging.odin b/vendor/miniaudio/logging.odin index afddf8e68..135c6a9b1 100644 --- a/vendor/miniaudio/logging.odin +++ b/vendor/miniaudio/logging.odin @@ -1,6 +1,6 @@ package miniaudio -import "core:c/libc" +import "core:c" foreign import lib { LIB } @@ -48,12 +48,12 @@ log :: struct { @(default_calling_convention="c", link_prefix="ma_") foreign lib { log_callback_init :: proc(onLog: log_callback_proc, pUserData: rawptr) -> log_callback --- - + log_init :: proc(pAllocationCallbacks: ^allocation_callbacks, pLog: ^log) -> result --- log_uninit :: proc(pLog: ^log) --- log_register_callback :: proc(pLog: ^log, callback: log_callback) -> result --- log_unregister_callback :: proc(pLog: ^log, callback: log_callback) -> result --- log_post :: proc(pLog: ^log, level: u32, pMessage: cstring) -> result --- - log_postv :: proc(pLog: ^log, level: u32, pFormat: cstring, args: libc.va_list) -> result --- + log_postv :: proc(pLog: ^log, level: u32, pFormat: cstring, args: c.va_list) -> result --- log_postf :: proc(pLog: ^log, level: u32, pFormat: cstring, #c_vararg args: ..any) -> result --- } diff --git a/vendor/miniaudio/node_graph.odin b/vendor/miniaudio/node_graph.odin index 610ada7a8..96138eeed 100644 --- a/vendor/miniaudio/node_graph.odin +++ b/vendor/miniaudio/node_graph.odin @@ -19,6 +19,13 @@ MAX_NODE_LOCAL_BUS_COUNT :: 2 /* Use this when the bus count is determined by the node instance rather than the vtable. */ NODE_BUS_COUNT_UNKNOWN :: 255 +/* For some internal memory management of ma_node_graph. */ +stack :: struct { + offset: uint, + sizeInBytes: uint, + _data: [1]byte, +} + node :: struct {} /* Node flags. */ @@ -53,7 +60,7 @@ node_vtable :: struct { onProcess: proc "c" (pNode: ^node, ppFramesIn: ^[^]f32, pFrameCountIn: ^u32, ppFramesOut: ^[^]f32, pFrameCountOut: ^u32), /* - A callback for retrieving the number of a input frames that are required to output the + A callback for retrieving the number of input frames that are required to output the specified number of output frames. You would only want to implement this when the node performs resampling. This is optional, even for nodes that perform resampling, but it does offer a small reduction in latency as it allows miniaudio to calculate the exact number of input frames @@ -134,8 +141,12 @@ node_input_bus :: struct { node_base :: struct { /* These variables are set once at startup. */ - pNodeGraph: ^node_graph, /* The graph this node belongs to. */ + pNodeGraph: ^node_graph, /* The graph this node belongs to. */ vtable: ^node_vtable, + inputBusCount: u32, + outputBusCount: u32, + pInputBuses: [^]node_input_bus `fmt:"v,inputBusCount"`, + pOutputBuses: [^]node_output_bus `fmt:"v,outputBusCount"`, pCachedData: [^]f32, /* Allocated on the heap. Fixed size. Needs to be stored on the heap because reading from output buses is done in separate function calls. */ cachedDataCapInFramesPerBus: u16, /* The capacity of the input data cache in frames, per bus. */ @@ -148,10 +159,6 @@ node_base :: struct { state: node_state, /*atomic*/ /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */ stateTimes: [2]u64, /*atomic*/ /* Indexed by ma_node_state. Specifies the time based on the global clock that a node should be considered to be in the relevant state. */ localTime: u64, /*atomic*/ /* The node's local clock. This is just a running sum of the number of output frames that have been processed. Can be modified by any thread with `ma_node_set_time()`. */ - inputBusCount: u32, - outputBusCount: u32, - pInputBuses: [^]node_input_bus, - pOutputBuses: [^]node_output_bus, /* Memory management. */ _inputBuses: [MAX_NODE_LOCAL_BUS_COUNT]node_input_bus, @@ -189,31 +196,39 @@ foreign lib { } node_graph_config :: struct { - channels: u32, - nodeCacheCapInFrames: u16, + channels: u32, + processingSizeInFrames: u32, /* This is the preferred processing size for node processing callbacks unless overridden by a node itself. Can be 0 in which case it will be based on the frame count passed into ma_node_graph_read_pcm_frames(), but will not be well defined. */ + preMixStackSizeInBytes: uint, /* Defaults to 512KB per channel. Reducing this will save memory, but the depth of your node graph will be more restricted. */ } node_graph :: struct { /* Immutable. */ base: node_base, /* The node graph itself is a node so it can be connected as an input to different node graph. This has zero inputs and calls ma_node_graph_read_pcm_frames() to generate it's output. */ endpoint: node_base, /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */ - nodeCacheCapInFrames: u16, + + pProcessingCache: [^]f32, /* This will be allocated when processingSizeInFrames is non-zero. This is needed because ma_node_graph_read_pcm_frames() can be called with a variable number of frames, and we may need to do some buffering in situations where the caller requests a frame count that's not a multiple of processingSizeInFrames. */ + processingCacheFramesRemaining: u32, + processingSizeInFrames: u32, /* Read and written by multiple threads. */ isReading: b32, /*atomic*/ + + /* Modified only by the audio thread. */ + pPreMixStack: ^stack, } @(default_calling_convention="c", link_prefix="ma_") foreign lib { node_graph_config_init :: proc(channels: u32) -> node_graph_config --- - node_graph_init :: proc(pConfig: ^node_graph_config, pAllocationCallbacks: ^allocation_callbacks, pNodeGraph: ^node_graph) -> result --- - node_graph_uninit :: proc(pNodeGraph: ^node_graph, pAllocationCallbacks: ^allocation_callbacks) --- - node_graph_get_endpoint :: proc(pNodeGraph: ^node_graph) -> ^node --- - node_graph_read_pcm_frames :: proc(pNodeGraph: ^node_graph, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result --- - node_graph_get_channels :: proc(pNodeGraph: ^node_graph) -> u32 --- - node_graph_get_time :: proc(pNodeGraph: ^node_graph) -> u64 --- - node_graph_set_time :: proc(pNodeGraph: ^node_graph, globalTime: u64) -> result --- + node_graph_init :: proc(pConfig: ^node_graph_config, pAllocationCallbacks: ^allocation_callbacks, pNodeGraph: ^node_graph) -> result --- + node_graph_uninit :: proc(pNodeGraph: ^node_graph, pAllocationCallbacks: ^allocation_callbacks) --- + node_graph_get_endpoint :: proc(pNodeGraph: ^node_graph) -> ^node --- + node_graph_read_pcm_frames :: proc(pNodeGraph: ^node_graph, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result --- + node_graph_get_channels :: proc(pNodeGraph: ^node_graph) -> u32 --- + node_graph_get_time :: proc(pNodeGraph: ^node_graph) -> u64 --- + node_graph_set_time :: proc(pNodeGraph: ^node_graph, globalTime: u64) -> result --- + node_graph_get_processing_size_in_frames :: proc(pNodeGraph: ^node_graph) -> u32 --- } diff --git a/vendor/miniaudio/resource_manager.odin b/vendor/miniaudio/resource_manager.odin index 495a02c5d..1bc65227b 100644 --- a/vendor/miniaudio/resource_manager.odin +++ b/vendor/miniaudio/resource_manager.odin @@ -16,6 +16,7 @@ resource_manager_data_source_flag :: enum c.int { ASYNC = 2, /* When set, the resource manager will load the data source asynchronously. */ WAIT_INIT = 3, /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */ UNKNOWN_LENGTH = 4, /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */ + LOOPING = 5, /* When set, configures the data source to loop by default. */ } resource_manager_data_source_flags :: bit_set[resource_manager_data_source_flag; u32] @@ -79,8 +80,8 @@ resource_manager_data_source_config :: struct { rangeEndInPCMFrames: u64, loopPointBegInPCMFrames: u64, loopPointEndInPCMFrames: u64, - isLooping: b32, flags: u32, + isLooping: b32, /* Deprecated. Use the MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING flag in `flags` instead. */ } resource_manager_data_supply_type :: enum c.int { @@ -197,6 +198,7 @@ resource_manager_config :: struct { ppCustomDecodingBackendVTables: ^[^]decoding_backend_vtable, customDecodingBackendCount: u32, pCustomDecodingBackendUserData: rawptr, + resampling: resampler_config, } resource_manager :: struct { diff --git a/vendor/miniaudio/src/miniaudio.h b/vendor/miniaudio/src/miniaudio.h index 47332e11a..24e676bb2 100644 --- a/vendor/miniaudio/src/miniaudio.h +++ b/vendor/miniaudio/src/miniaudio.h @@ -1,6 +1,6 @@ /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.11.21 - 2023-11-15 +miniaudio - v0.11.24 - 2026-01-17 David Reid - mackron@gmail.com @@ -12,15 +12,10 @@ GitHub: https://github.com/mackron/miniaudio /* 1. Introduction =============== -miniaudio is a single file library for audio playback and capture. To use it, do the following in -one .c file: - - ```c - #define MINIAUDIO_IMPLEMENTATION - #include "miniaudio.h" - ``` - -You can do `#include "miniaudio.h"` in other parts of the program just like any other header. +To use miniaudio, just include "miniaudio.h" like any other header and add "miniaudio.c" to your +source tree. If you don't want to add it to your source tree you can compile and link to it like +any other library. Note that ABI compatibility is not guaranteed between versions, even with bug +fix releases, so take care if compiling as a shared object. miniaudio includes both low level and high level APIs. The low level API is good for those who want to do all of their mixing themselves and only require a light weight interface to the underlying @@ -293,14 +288,14 @@ avoids the same sound being loaded multiple times. The node graph is used for mixing and effect processing. The idea is that you connect a number of nodes into the graph by connecting each node's outputs to another node's inputs. Each node can -implement it's own effect. By chaining nodes together, advanced mixing and effect processing can +implement its own effect. By chaining nodes together, advanced mixing and effect processing can be achieved. The engine encapsulates both the resource manager and the node graph to create a simple, easy to use high level API. The resource manager and node graph APIs are covered in more later sections of this manual. -The code below shows how you can initialize an engine using it's default configuration. +The code below shows how you can initialize an engine using its default configuration. ```c ma_result result; @@ -388,7 +383,7 @@ Sounds are not started by default. Start a sound with `ma_sound_start()` and sto `ma_sound_stop()`. When a sound is stopped, it is not rewound to the start. Use `ma_sound_seek_to_pcm_frame(&sound, 0)` to seek back to the start of a sound. By default, starting and stopping sounds happens immediately, but sometimes it might be convenient to schedule the sound -the be started and/or stopped at a specific time. This can be done with the following functions: +to be started and/or stopped at a specific time. This can be done with the following functions: ```c ma_sound_set_start_time_in_pcm_frames() @@ -398,7 +393,7 @@ the be started and/or stopped at a specific time. This can be done with the foll ``` The start/stop time needs to be specified based on the absolute timer which is controlled by the -engine. The current global time time in PCM frames can be retrieved with +engine. The current global time in PCM frames can be retrieved with `ma_engine_get_time_in_pcm_frames()`. The engine's global time can be changed with `ma_engine_set_time_in_pcm_frames()` for synchronization purposes if required. Note that scheduling a start time still requires an explicit call to `ma_sound_start()` before anything will play: @@ -430,11 +425,11 @@ Sounds and sound groups are nodes in the engine's node graph and can be plugged API. This makes it possible to connect sounds and sound groups to effect nodes to produce complex effect chains. -A sound can have it's volume changed with `ma_sound_set_volume()`. If you prefer decibel volume +A sound can have its volume changed with `ma_sound_set_volume()`. If you prefer decibel volume control you can use `ma_volume_db_to_linear()` to convert from decibel representation to linear. Panning and pitching is supported with `ma_sound_set_pan()` and `ma_sound_set_pitch()`. If you know -a sound will never have it's pitch changed with `ma_sound_set_pitch()` or via the doppler effect, +a sound will never have its pitch changed with `ma_sound_set_pitch()` or via the doppler effect, you can specify the `MA_SOUND_FLAG_NO_PITCH` flag when initializing the sound for an optimization. By default, sounds and sound groups have spatialization enabled. If you don't ever want to @@ -460,6 +455,11 @@ is at the end, use `ma_sound_at_end()`. Looping of a sound can be controlled wit miniaudio should work cleanly out of the box without the need to download or install any dependencies. See below for platform-specific details. +This library has been designed to be added directly to your source tree which is the preferred way +of using it, but you can compile it as a normal library if that's your preference. Be careful if +compiling as a shared object because miniaudio is not ABI compatible between any release, including +bug fix releases. It's recommended you link statically. + Note that GCC and Clang require `-msse2`, `-mavx2`, etc. for SIMD optimizations. If you get errors about undefined references to `__sync_val_compare_and_swap_8`, `__atomic_load_8`, @@ -483,21 +483,12 @@ link the relevant frameworks but should compile cleanly out of the box with Xcod through the command line requires linking to `-lpthread` and `-lm`. Due to the way miniaudio links to frameworks at runtime, your application may not pass Apple's -notarization process. To fix this there are two options. The first is to use the -`MA_NO_RUNTIME_LINKING` option, like so: - - ```c - #ifdef __APPLE__ - #define MA_NO_RUNTIME_LINKING - #endif - #define MINIAUDIO_IMPLEMENTATION - #include "miniaudio.h" - ``` - -This will require linking with `-framework CoreFoundation -framework CoreAudio -framework AudioToolbox`. -If you get errors about AudioToolbox, try with `-framework AudioUnit` instead. You may get this when -using older versions of iOS. Alternatively, if you would rather keep using runtime linking you can -add the following to your entitlements.xcent file: +notarization process. To fix this there are two options. The first is to compile with +`-DMA_NO_RUNTIME_LINKING` which in turn will require linking with +`-framework CoreFoundation -framework CoreAudio -framework AudioToolbox`. If you get errors about +AudioToolbox, try with `-framework AudioUnit` instead. You may get this when using older versions +of iOS. Alternatively, if you would rather keep using runtime linking you can add the following to +your entitlements.xcent file: ``` com.apple.security.cs.allow-dyld-environment-variables @@ -538,7 +529,7 @@ you'll need to disable run-time linking with `MA_NO_RUNTIME_LINKING` and link wi The Emscripten build emits Web Audio JavaScript directly and should compile cleanly out of the box. You cannot use `-std=c*` compiler flags, nor `-ansi`. -You can enable the use of AudioWorkets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling +You can enable the use of AudioWorklets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling with the following options: -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY @@ -555,7 +546,7 @@ To run locally, you'll need to use emrun: 2.7. Build Options ------------------ -`#define` these options before including miniaudio.h. +`#define` these options before including miniaudio.c, or pass them as compiler flags: +----------------------------------+--------------------------------------------------------------------+ | Option | Description | @@ -586,6 +577,8 @@ To run locally, you'll need to use emrun: +----------------------------------+--------------------------------------------------------------------+ | MA_NO_WEBAUDIO | Disables the Web Audio backend. | +----------------------------------+--------------------------------------------------------------------+ + | MA_NO_CUSTOM | Disables support for custom backends. | + +----------------------------------+--------------------------------------------------------------------+ | MA_NO_NULL | Disables the null backend. | +----------------------------------+--------------------------------------------------------------------+ | MA_ENABLE_ONLY_SPECIFIC_BACKENDS | Disables all backends by default and requires `MA_ENABLE_*` to | @@ -630,6 +623,9 @@ To run locally, you'll need to use emrun: | MA_ENABLE_WEBAUDIO | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | | | enable the Web Audio backend. | +----------------------------------+--------------------------------------------------------------------+ + | MA_ENABLE_CUSTOM | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | + | | enable custom backends. | + +----------------------------------+--------------------------------------------------------------------+ | MA_ENABLE_NULL | Used in conjunction with MA_ENABLE_ONLY_SPECIFIC_BACKENDS to | | | enable the null backend. | +----------------------------------+--------------------------------------------------------------------+ @@ -693,11 +689,30 @@ To run locally, you'll need to use emrun: | | You may need to enable this if your target platform does not allow | | | runtime linking via `dlopen()`. | +----------------------------------+--------------------------------------------------------------------+ + | MA_USE_STDINT | (Pass this in as a compiler flag. Do not `#define` this before | + | | miniaudio.c) Forces the use of stdint.h for sized types. | + +----------------------------------+--------------------------------------------------------------------+ | MA_DEBUG_OUTPUT | Enable `printf()` output of debug logs (`MA_LOG_LEVEL_DEBUG`). | +----------------------------------+--------------------------------------------------------------------+ | MA_COINIT_VALUE | Windows only. The value to pass to internal calls to | | | `CoInitializeEx()`. Defaults to `COINIT_MULTITHREADED`. | +----------------------------------+--------------------------------------------------------------------+ + | MA_FORCE_UWP | Windows only. Affects only the WASAPI backend. Will force the | + | | WASAPI backend to use the UWP code path instead of the regular | + | | desktop path. This is normally auto-detected and should rarely be | + | | needed to be used explicitly, but can be useful for debugging. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_ON_THREAD_ENTRY | Defines some code that will be executed as soon as an internal | + | | miniaudio-managed thread is created. This will be the first thing | + | | to be executed by the thread entry point. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_ON_THREAD_EXIT | Defines some code that will be executed from the entry point of an | + | | internal miniaudio-managed thread upon exit. This will be the last | + | | thing to be executed before the thread's entry point exits. | + +----------------------------------+--------------------------------------------------------------------+ + | MA_THREAD_DEFAULT_STACK_SIZE | If set, specifies the default stack size used by miniaudio-managed | + | | threads. | + +----------------------------------+--------------------------------------------------------------------+ | MA_API | Controls how public APIs should be decorated. Default is `extern`. | +----------------------------------+--------------------------------------------------------------------+ @@ -863,7 +878,7 @@ read data within a certain range of the underlying data. To do this you can use This is useful if you have a sound bank where many sounds are stored in the same file and you want the data source to only play one of those sub-sounds. Note that once the range is set, everything -that takes a position, such as cursors and loop points, should always be relatvie to the start of +that takes a position, such as cursors and loop points, should always be relative to the start of the range. When the range is set, any previously defined loop point will be reset. Custom loop points can also be used with data sources. By default, data sources will loop after @@ -871,7 +886,7 @@ they reach the end of the data source, but if you need to loop at a specific loc the following: ```c - result = ma_data_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames); + result = ma_data_source_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames); if (result != MA_SUCCESS) { return result; // Failed to set the loop point. } @@ -1309,7 +1324,7 @@ only works for sounds that were initialized with `ma_sound_init_from_file()` and When you initialize a sound, if you specify a sound group the sound will be attached to that group automatically. If you set it to NULL, it will be automatically attached to the engine's endpoint. -If you would instead rather leave the sound unattached by default, you can can specify the +If you would instead rather leave the sound unattached by default, you can specify the `MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT` flag. This is useful if you want to set up a complex node graph. @@ -1686,6 +1701,7 @@ combination of the following flags: MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT + MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING ``` When no flags are specified (set to 0), the sound will be fully loaded into memory, but not @@ -1706,6 +1722,14 @@ can instead stream audio data which you can do by specifying the second pages. When a new page needs to be decoded, a job will be posted to the job queue and then subsequently processed in a job thread. +The `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING` flag can be used so that the sound will loop +when it reaches the end by default. It's recommended you use this flag when you want to have a +looping streaming sound. If you try loading a very short sound as a stream, you will get a glitch. +This is because the resource manager needs to pre-fill the initial buffer at initialization time, +and if you don't specify the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING` flag, the resource +manager will assume the sound is not looping and will stop filling the buffer when it reaches the +end, therefore resulting in a discontinuous buffer. + For in-memory sounds, reference counting is used to ensure the data is loaded only once. This means multiple calls to `ma_resource_manager_data_source_init()` with the same file path will result in the file data only being loaded once. Each call to `ma_resource_manager_data_source_init()` must be @@ -1720,7 +1744,7 @@ actual file paths. When `ma_resource_manager_data_source_init()` is called (with `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag), the resource manager will look for these explicitly registered data buffers and, if found, will use it as the backing data for the data source. Note that the resource manager does *not* make a copy of this data so it is up to the -caller to ensure the pointer stays valid for it's lifetime. Use +caller to ensure the pointer stays valid for its lifetime. Use `ma_resource_manager_unregister_data()` to unregister the self-managed data. You can also use `ma_resource_manager_register_file()` and `ma_resource_manager_unregister_file()` to register and unregister a file. It does not make sense to use the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` @@ -2031,7 +2055,7 @@ In the above graph, it starts with two data sources whose outputs are attached t splitter node. It's at this point that the two data sources are mixed. After mixing, the splitter performs it's processing routine and produces two outputs which is simply a duplication of the input stream. One output is attached to a low pass filter, whereas the other output is attached to -a echo/delay. The outputs of the the low pass filter and the echo are attached to the endpoint, and +a echo/delay. The outputs of the low pass filter and the echo are attached to the endpoint, and since they're both connected to the same input bus, they'll be mixed. Each input bus must be configured to accept the same number of channels, but the number of channels @@ -2072,7 +2096,7 @@ data from the graph: ``` When you read audio data, miniaudio starts at the node graph's endpoint node which then pulls in -data from it's input attachments, which in turn recursively pull in data from their inputs, and so +data from its input attachments, which in turn recursively pull in data from their inputs, and so on. At the start of the graph there will be some kind of data source node which will have zero inputs and will instead read directly from a data source. The base nodes don't literally need to read from a `ma_data_source` object, but they will always have some kind of underlying object that @@ -2318,7 +2342,7 @@ You can start and stop a node with the following: By default the node is in a started state, but since it won't be connected to anything won't actually be invoked by the node graph until it's connected. When you stop a node, data will not be -read from any of it's input connections. You can use this property to stop a group of sounds +read from any of its input connections. You can use this property to stop a group of sounds atomically. You can configure the initial state of a node in it's config: @@ -2411,29 +2435,29 @@ audio thread is finished so that control is not handed back to the caller thereb chance to free the node's memory. When the audio thread is processing a node, it does so by reading from each of the output buses of -the node. In order for a node to process data for one of it's output buses, it needs to read from -each of it's input buses, and so on an so forth. It follows that once all output buses of a node +the node. In order for a node to process data for one of its output buses, it needs to read from +each of its input buses, and so on an so forth. It follows that once all output buses of a node are detached, the node as a whole will be disconnected and no further processing will occur unless it's output buses are reattached, which won't be happening when the node is being uninitialized. By having `ma_node_detach_output_bus()` wait until the audio thread is finished with it, we can simplify a few things, at the expense of making `ma_node_detach_output_bus()` a bit slower. By doing this, the implementation of `ma_node_uninit()` becomes trivial - just detach all output -nodes, followed by each of the attachments to each of it's input nodes, and then do any final clean +nodes, followed by each of the attachments to each of its input nodes, and then do any final clean up. With the above design, the worst-case scenario is `ma_node_detach_output_bus()` taking as long as it takes to process the output bus being detached. This will happen if it's called at just the wrong moment where the audio thread has just iterated it and has just started processing. The caller of `ma_node_detach_output_bus()` will stall until the audio thread is finished, which -includes the cost of recursively processing it's inputs. This is the biggest compromise made with -the approach taken by miniaudio for it's lock-free processing system. The cost of detaching nodes +includes the cost of recursively processing its inputs. This is the biggest compromise made with +the approach taken by miniaudio for its lock-free processing system. The cost of detaching nodes earlier in the pipeline (data sources, for example) will be cheaper than the cost of detaching higher level nodes, such as some kind of final post-processing endpoint. If you need to do mass detachments, detach starting from the lowest level nodes and work your way towards the final endpoint node (but don't try detaching the node graph's endpoint). If the audio thread is not running, detachment will be fast and detachment in any order will be the same. The reason nodes need to wait for their input attachments to complete is due to the potential for desyncs between -data sources. If the node was to terminate processing mid way through processing it's inputs, +data sources. If the node was to terminate processing mid way through processing its inputs, there's a chance that some of the underlying data sources will have been read, but then others not. That will then result in a potential desynchronization when detaching and reattaching higher-level nodes. A possible solution to this is to have an option when detaching to terminate processing @@ -2804,7 +2828,7 @@ weights. Custom weights can be passed in as the last parameter of `ma_channel_converter_config_init()`. Predefined channel maps can be retrieved with `ma_channel_map_init_standard()`. This takes a -`ma_standard_channel_map` enum as it's first parameter, which can be one of the following: +`ma_standard_channel_map` enum as its first parameter, which can be one of the following: +-----------------------------------+-----------------------------------------------------------+ | Name | Description | @@ -2890,7 +2914,7 @@ like the following: ma_resample_algorithm_linear); ma_resampler resampler; - ma_result result = ma_resampler_init(&config, &resampler); + ma_result result = ma_resampler_init(&config, NULL, &resampler); if (result != MA_SUCCESS) { // An error occurred... } @@ -3132,7 +3156,7 @@ Biquad filtering is achieved with the `ma_biquad` API. Example: ```c ma_biquad_config config = ma_biquad_config_init(ma_format_f32, channels, b0, b1, b2, a0, a1, a2); - ma_result result = ma_biquad_init(&config, &biquad); + ma_result result = ma_biquad_init(&config, NULL, &biquad); if (result != MA_SUCCESS) { // Error. } @@ -3723,7 +3747,7 @@ extern "C" { #define MA_VERSION_MAJOR 0 #define MA_VERSION_MINOR 11 -#define MA_VERSION_REVISION 21 +#define MA_VERSION_REVISION 24 #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #if defined(_MSC_VER) && !defined(__clang__) @@ -3740,8 +3764,7 @@ extern "C" { #endif - -#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__) +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__) || defined(__ppc64__) #define MA_SIZEOF_PTR 8 #else #define MA_SIZEOF_PTR 4 @@ -3805,7 +3828,7 @@ typedef void* ma_handle; typedef void* ma_ptr; /* -ma_proc is annoying because when compiling with GCC we get pendantic warnings about converting +ma_proc is annoying because when compiling with GCC we get pedantic warnings about converting between `void*` and `void (*)()`. We can't use `void (*)()` with MSVC however, because we'll get warning C4191 about "type cast between incompatible function types". To work around this I'm going to use a different data type depending on the compiler. @@ -3831,37 +3854,65 @@ typedef ma_uint16 wchar_t; #define MA_SIZE_MAX 0xFFFFFFFF /* When SIZE_MAX is not defined by the standard library just default to the maximum 32-bit unsigned integer. */ #endif +#define MA_UINT64_MAX (((ma_uint64)0xFFFFFFFF << 32) | (ma_uint64)0xFFFFFFFF) /* Weird shifting syntax is for VC6 compatibility. */ + /* Platform/backend detection. */ -#if defined(_WIN32) || defined(__COSMOPOLITAN__) +#if defined(_WIN32) #define MA_WIN32 #if defined(MA_FORCE_UWP) || (defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PC_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) || (defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP))) #define MA_WIN32_UWP #elif defined(WINAPI_FAMILY) && (defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES) #define MA_WIN32_GDK + #elif defined(NXDK) + #define MA_WIN32_NXDK #else #define MA_WIN32_DESKTOP #endif + + /* The original Xbox. */ + #if defined(NXDK) /* <-- Add other Xbox compiler toolchains here, and then add a toolchain-specific define in case we need to discriminate between them later. */ + #define MA_XBOX + + #if defined(NXDK) + #define MA_XBOX_NXDK + #endif + #endif #endif -#if !defined(_WIN32) /* If it's not Win32, assume POSIX. */ +#if defined(__MSDOS__) || defined(MSDOS) || defined(_MSDOS) || defined(__DOS__) + #define MA_DOS + + /* No threading allowed on DOS. */ + #ifndef MA_NO_THREADING + #define MA_NO_THREADING + #endif + + /* No runtime linking allowed on DOS. */ + #ifndef MA_NO_RUNTIME_LINKING + #define MA_NO_RUNTIME_LINKING + #endif +#endif +#if !defined(MA_WIN32) && !defined(MA_DOS) /* If it's not Win32, assume POSIX. */ #define MA_POSIX - /* - Use the MA_NO_PTHREAD_IN_HEADER option at your own risk. This is intentionally undocumented. - You can use this to avoid including pthread.h in the header section. The downside is that it - results in some fixed sized structures being declared for the various types that are used in - miniaudio. The risk here is that these types might be too small for a given platform. This - risk is yours to take and no support will be offered if you enable this option. - */ - #ifndef MA_NO_PTHREAD_IN_HEADER - #include /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */ - typedef pthread_t ma_pthread_t; - typedef pthread_mutex_t ma_pthread_mutex_t; - typedef pthread_cond_t ma_pthread_cond_t; - #else - typedef ma_uintptr ma_pthread_t; - typedef union ma_pthread_mutex_t { char __data[40]; ma_uint64 __alignment; } ma_pthread_mutex_t; - typedef union ma_pthread_cond_t { char __data[48]; ma_uint64 __alignment; } ma_pthread_cond_t; + #if !defined(MA_NO_THREADING) + /* + Use the MA_NO_PTHREAD_IN_HEADER option at your own risk. This is intentionally undocumented. + You can use this to avoid including pthread.h in the header section. The downside is that it + results in some fixed sized structures being declared for the various types that are used in + miniaudio. The risk here is that these types might be too small for a given platform. This + risk is yours to take and no support will be offered if you enable this option. + */ + #ifndef MA_NO_PTHREAD_IN_HEADER + #include /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */ + typedef pthread_t ma_pthread_t; + typedef pthread_mutex_t ma_pthread_mutex_t; + typedef pthread_cond_t ma_pthread_cond_t; + #else + typedef ma_uintptr ma_pthread_t; + typedef union ma_pthread_mutex_t { char __data[40]; ma_uint64 __alignment; } ma_pthread_mutex_t; + typedef union ma_pthread_cond_t { char __data[48]; ma_uint64 __alignment; } ma_pthread_cond_t; + #endif #endif #if defined(__unix__) @@ -3888,8 +3939,11 @@ typedef ma_uint16 wchar_t; #if defined(__PROSPERO__) #define MA_PROSPERO #endif - #if defined(__NX__) - #define MA_NX + #if defined(__3DS__) + #define MA_3DS + #endif + #if defined(__SWITCH__) || defined(__NX__) + #define MA_SWITCH #endif #if defined(__BEOS__) || defined(__HAIKU__) #define MA_BEOS @@ -3899,12 +3953,13 @@ typedef ma_uint16 wchar_t; #endif #endif -#if defined(__has_c_attribute) - #if __has_c_attribute(fallthrough) - #define MA_FALLTHROUGH [[fallthrough]] - #endif +#if !defined(MA_FALLTHROUGH) && defined(__cplusplus) && __cplusplus >= 201703L + #define MA_FALLTHROUGH [[fallthrough]] #endif -#if !defined(MA_FALLTHROUGH) && defined(__has_attribute) && (defined(__clang__) || defined(__GNUC__)) +#if !defined(MA_FALLTHROUGH) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L + #define MA_FALLTHROUGH [[fallthrough]] +#endif +#if !defined(MA_FALLTHROUGH) && defined(__has_attribute) #if __has_attribute(fallthrough) #define MA_FALLTHROUGH __attribute__((fallthrough)) #endif @@ -3941,7 +3996,7 @@ typedef ma_uint16 wchar_t; #define MA_NO_INLINE __attribute__((noinline)) #else #define MA_INLINE MA_GNUC_INLINE_HINT - #define MA_NO_INLINE __attribute__((noinline)) + #define MA_NO_INLINE #endif #elif defined(__WATCOMC__) #define MA_INLINE __inline @@ -3999,7 +4054,7 @@ Special wchar_t type to ensure any structures in the public sections that refere consistent size across all platforms. On Windows, wchar_t is 2 bytes, whereas everywhere else it's 4 bytes. Since Windows likes to use -wchar_t for it's IDs, we need a special explicitly sized wchar type that is always 2 bytes on all +wchar_t for its IDs, we need a special explicitly sized wchar type that is always 2 bytes on all platforms. */ #if !defined(MA_POSIX) && defined(MA_WIN32) @@ -4025,7 +4080,7 @@ MA_LOG_LEVEL_INFO callback. MA_LOG_LEVEL_WARNING - Warnings. You should enable this in you development builds and action them when encounted. These + Warnings. You should enable this in you development builds and action them when encountered. These logs usually indicate a potential problem or misconfiguration, but still allow you to keep running. This will never be called from within the data callback. @@ -4127,9 +4182,13 @@ typedef enum MA_CHANNEL_AUX_29 = 49, MA_CHANNEL_AUX_30 = 50, MA_CHANNEL_AUX_31 = 51, + + /* Count. */ + MA_CHANNEL_POSITION_COUNT, + + /* Aliases. */ MA_CHANNEL_LEFT = MA_CHANNEL_FRONT_LEFT, MA_CHANNEL_RIGHT = MA_CHANNEL_FRONT_RIGHT, - MA_CHANNEL_POSITION_COUNT = (MA_CHANNEL_AUX_31 + 1) } _ma_channel_position; /* Do not use `_ma_channel_position` directly. Use `ma_channel` instead. */ typedef enum @@ -4324,7 +4383,7 @@ typedef struct typedef struct { - ma_int32 state; + ma_uint32 state; } ma_lcg; @@ -5457,7 +5516,7 @@ input frames. MA_API ma_result ma_resampler_get_expected_output_frame_count(const ma_resampler* pResampler, ma_uint64 inputFrameCount, ma_uint64* pOutputFrameCount); /* -Resets the resampler's timer and clears it's internal cache. +Resets the resampler's timer and clears its internal cache. */ MA_API ma_result ma_resampler_reset(ma_resampler* pResampler); @@ -5678,7 +5737,7 @@ MA_API void ma_channel_map_init_standard(ma_standard_channel_map standardChannel /* Copies a channel map. -Both input and output channel map buffers must have a capacity of at at least `channels`. +Both input and output channel map buffers must have a capacity of at least `channels`. */ MA_API void ma_channel_map_copy(ma_channel* pOut, const ma_channel* pIn, ma_uint32 channels); @@ -5817,6 +5876,8 @@ MA_API void ma_data_source_uninit(ma_data_source* pDataSource); MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */ MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead); */ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex); +MA_API ma_result ma_data_source_seek_seconds(ma_data_source* pDataSource, float secondCount, float* pSecondsSeeked); /* Can only seek forward. Abstraction to ma_data_source_seek_pcm_frames() */ +MA_API ma_result ma_data_source_seek_to_second(ma_data_source* pDataSource, float seekPointInSeconds); /* Abstraction to ma_data_source_seek_to_pcm_frame() */ MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap); MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor); MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength); /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */ @@ -6182,6 +6243,12 @@ MA_API ma_result ma_event_wait(ma_event* pEvent); Signals the specified auto-reset event. */ MA_API ma_result ma_event_signal(ma_event* pEvent); + + +MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore* pSemaphore); +MA_API void ma_semaphore_uninit(ma_semaphore* pSemaphore); +MA_API ma_result ma_semaphore_wait(ma_semaphore* pSemaphore); +MA_API ma_result ma_semaphore_release(ma_semaphore* pSemaphore); #endif /* MA_NO_THREADING */ @@ -6273,7 +6340,7 @@ Job Queue /* Slot Allocator -------------- -The idea of the slot allocator is for it to be used in conjunction with a fixed sized buffer. You use the slot allocator to allocator an index that can be used +The idea of the slot allocator is for it to be used in conjunction with a fixed sized buffer. You use the slot allocator to allocate an index that can be used as the insertion point for an object. Slots are reference counted to help mitigate the ABA problem in the lock-free queue we use for tracking jobs. @@ -6535,22 +6602,18 @@ This section contains the APIs for device playback and capture. Here is where yo ************************************************************************************************************************************************************/ #ifndef MA_NO_DEVICE_IO /* Some backends are only supported on certain platforms. */ -#if defined(MA_WIN32) +#if defined(MA_WIN32) && !defined(MA_XBOX) #define MA_SUPPORT_WASAPI #if defined(MA_WIN32_DESKTOP) /* DirectSound and WinMM backends are only supported on desktops. */ #define MA_SUPPORT_DSOUND #define MA_SUPPORT_WINMM - - /* Don't enable JACK here if compiling with Cosmopolitan. It'll be enabled in the Linux section below. */ - #if !defined(__COSMOPOLITAN__) - #define MA_SUPPORT_JACK /* JACK is technically supported on Windows, but I don't know how many people use it in practice... */ - #endif + #define MA_SUPPORT_JACK /* JACK is technically supported on Windows, but I don't know how many people use it in practice... */ #endif #endif #if defined(MA_UNIX) && !defined(MA_ORBIS) && !defined(MA_PROSPERO) #if defined(MA_LINUX) - #if !defined(MA_ANDROID) && !defined(__COSMOPOLITAN__) /* ALSA is not supported on Android. */ + #if !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN) /* ALSA is not supported on Android. */ #define MA_SUPPORT_ALSA #endif #endif @@ -7006,6 +7069,8 @@ typedef union int nullbackend; /* The null backend uses an integer for device IDs. */ } ma_device_id; +MA_API ma_bool32 ma_device_id_equal(const ma_device_id* pA, const ma_device_id* pB); + typedef struct ma_context_config ma_context_config; typedef struct ma_device_config ma_device_config; @@ -7093,6 +7158,7 @@ struct ma_device_config { const char* pStreamNamePlayback; const char* pStreamNameCapture; + int channelMap; } pulse; struct { @@ -7112,6 +7178,7 @@ struct ma_device_config ma_aaudio_allowed_capture_policy allowedCapturePolicy; ma_bool32 noAutoStartAfterReroute; ma_bool32 enableCompatibilityWorkarounds; + ma_bool32 allowSetBufferCapacity; } aaudio; }; @@ -7184,7 +7251,7 @@ and on output returns detailed information about the device in `ma_device_info`. case when the device ID is NULL, in which case information about the default device needs to be retrieved. Once the context has been created and the device ID retrieved (if using anything other than the default device), the device can be created. -This is a little bit more complicated than initialization of the context due to it's more complicated configuration. When initializing a +This is a little bit more complicated than initialization of the context due to its more complicated configuration. When initializing a device, a duplex device may be requested. This means a separate data format needs to be specified for both playback and capture. On input, the data format is set to what the application wants. On output it's set to the native format which should match as closely as possible to the requested format. The conversion between the format requested by the application and the device's native format will be handled @@ -7205,10 +7272,10 @@ asynchronous reading and writing, `onDeviceStart()` and `onDeviceStop()` should The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the `onDeviceRead()` and `onDeviceWrite()` callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the -backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within it's callback. +backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within its callback. This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback. -If the backend requires absolute flexibility with it's data delivery, it can optionally implement the `onDeviceDataLoop()` callback +If the backend requires absolute flexibility with its data delivery, it can optionally implement the `onDeviceDataLoop()` callback which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional. The audio thread should run data delivery logic in a loop while `ma_device_get_state() == ma_device_state_started` and no errors have been @@ -7248,6 +7315,10 @@ struct ma_context_config void* pUserData; ma_allocation_callbacks allocationCallbacks; struct + { + ma_handle hWnd; /* HWND. Optional window handle to pass into SetCooperativeLevel(). Will default to the foreground window, and if that fails, the desktop window. */ + } dsound; + struct { ma_bool32 useVerboseDeviceEnumeration; } alsa; @@ -7336,6 +7407,7 @@ struct ma_context #ifdef MA_SUPPORT_DSOUND struct { + ma_handle hWnd; /* Can be null. */ ma_handle hDSoundDLL; ma_proc DirectSoundCreate; ma_proc DirectSoundEnumerateA; @@ -7383,6 +7455,7 @@ struct ma_context ma_proc snd_pcm_hw_params_set_rate_resample; ma_proc snd_pcm_hw_params_set_rate; ma_proc snd_pcm_hw_params_set_rate_near; + ma_proc snd_pcm_hw_params_set_rate_minmax; ma_proc snd_pcm_hw_params_set_buffer_size_near; ma_proc snd_pcm_hw_params_set_periods_near; ma_proc snd_pcm_hw_params_set_access; @@ -7942,6 +8015,8 @@ struct ma_device { /*AAudioStream**/ ma_ptr pStreamPlayback; /*AAudioStream**/ ma_ptr pStreamCapture; + ma_mutex rerouteLock; + ma_atomic_bool32 isTearingDown; ma_aaudio_usage usage; ma_aaudio_content_type contentType; ma_aaudio_input_preset inputPreset; @@ -8365,6 +8440,10 @@ Retrieves basic information about every active playback and/or capture device. This function will allocate memory internally for the device lists and return a pointer to them through the `ppPlaybackDeviceInfos` and `ppCaptureDeviceInfos` parameters. If you do not want to incur the overhead of these allocations consider using `ma_context_enumerate_devices()` which will instead use a callback. +Note that this only retrieves the ID and name/description of the device. The reason for only retrieving basic information is that it would otherwise require +opening the backend device in order to probe it for more detailed information which can be inefficient. Consider using `ma_context_get_device_info()` for this, +but don't call it from within the enumeration callback. + Parameters ---------- @@ -8406,7 +8485,7 @@ The returned pointers will become invalid upon the next call this this function, See Also -------- -ma_context_get_devices() +ma_context_enumerate_devices() */ MA_API ma_result ma_context_get_devices(ma_context* pContext, ma_device_info** ppPlaybackDeviceInfos, ma_uint32* pPlaybackDeviceCount, ma_device_info** ppCaptureDeviceInfos, ma_uint32* pCaptureDeviceCount); @@ -8545,7 +8624,7 @@ from a microphone. Whether or not you should send or receive data from the devic playback, capture, full-duplex or loopback. (Note that loopback mode is only supported on select backends.) Sending and receiving audio data to and from the device is done via a callback which is fired by miniaudio at periodic time intervals. -The frequency at which data is delivered to and from a device depends on the size of it's period. The size of the period can be defined in terms of PCM frames +The frequency at which data is delivered to and from a device depends on the size of its period. The size of the period can be defined in terms of PCM frames or milliseconds, whichever is more convenient. Generally speaking, the smaller the period, the lower the latency at the expense of higher CPU usage and increased risk of glitching due to the more frequent and granular data deliver intervals. The size of a period will depend on your requirements, but miniaudio's defaults should work fine for most scenarios. If you're building a game you should leave this fairly small, whereas if you're building a simple @@ -8619,7 +8698,7 @@ then be set directly on the structure. Below are the members of the `ma_device_c performanceProfile A hint to miniaudio as to the performance requirements of your program. Can be either `ma_performance_profile_low_latency` (default) or - `ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at it's default value. + `ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at its default value. noPreSilencedOutputBuffer When set to true, the contents of the output buffer passed into the data callback will be left undefined. When set to false (default), the contents of @@ -8659,7 +8738,7 @@ then be set directly on the structure. Below are the members of the `ma_device_c A pointer that will passed to callbacks in pBackendVTable. resampling.linear.lpfOrder - The linear resampler applies a low-pass filter as part of it's processing for anti-aliasing. This setting controls the order of the filter. The higher + The linear resampler applies a low-pass filter as part of its processing for anti-aliasing. This setting controls the order of the filter. The higher the value, the better the quality, in general. Setting this to 0 will disable low-pass filtering altogether. The maximum value is `MA_MAX_FILTER_ORDER`. The default value is `min(4, MA_MAX_FILTER_ORDER)`. @@ -8736,6 +8815,9 @@ then be set directly on the structure. Below are the members of the `ma_device_c pulse.pStreamNameCapture PulseAudio only. Sets the stream name for capture. + pulse.channelMap + PulseAudio only. Sets the channel map that is requested from PulseAudio. See MA_PA_CHANNEL_MAP_* constants. Defaults to MA_PA_CHANNEL_MAP_AIFF. + coreaudio.allowNominalSampleRateChange Core Audio only. Desktop only. When enabled, allows the sample rate of the device to be changed at the operating system level. This is disabled by default in order to prevent intrusive changes to the user's system. This is useful if you want to use a sample rate @@ -8909,7 +8991,7 @@ Unsafe. It is not safe to call this inside any callback. Remarks ------- -You only need to use this function if you want to configure the context differently to it's defaults. You should never use this function if you want to manage +You only need to use this function if you want to configure the context differently to its defaults. You should never use this function if you want to manage your own context. See the documentation for `ma_context_init()` for information on the different context configuration options. @@ -9593,7 +9675,7 @@ Parameters ---------- pBackends (out, optional) A pointer to the buffer that will receive the enabled backends. Set to NULL to retrieve the backend count. Setting - the capacity of the buffer to `MA_BUFFER_COUNT` will guarantee it's large enough for all backends. + the capacity of the buffer to `MA_BACKEND_COUNT` will guarantee it's large enough for all backends. backendCap (in) The capacity of the `pBackends` buffer. @@ -9674,7 +9756,7 @@ Utilities ************************************************************************************************************************************************************/ /* -Calculates a buffer size in milliseconds from the specified number of frames and sample rate. +Calculates a buffer size in milliseconds (rounded up) from the specified number of frames and sample rate. */ MA_API ma_uint32 ma_calculate_buffer_size_in_milliseconds_from_frames(ma_uint32 bufferSizeInFrames, ma_uint32 sampleRate); @@ -9931,7 +10013,7 @@ struct ma_decoder void* pInputCache; /* In input format. Can be null if it's not needed. */ ma_uint64 inputCacheCap; /* The capacity of the input cache. */ ma_uint64 inputCacheConsumed; /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */ - ma_uint64 inputCacheRemaining; /* The number of valid frames remaining in the cahce. */ + ma_uint64 inputCacheRemaining; /* The number of valid frames remaining in the cache. */ ma_allocation_callbacks allocationCallbacks; union { @@ -9972,7 +10054,7 @@ This is not thread safe without your own synchronization. MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* -Seeks to a PCM frame based on it's absolute index. +Seeks to a PCM frame based on its absolute index. This is not thread safe without your own synchronization. */ @@ -10235,7 +10317,8 @@ typedef enum MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE = 0x00000002, /* Decode data before storing in memory. When set, decoding is done at the resource manager level rather than the mixing thread. Results in faster mixing, but higher memory usage. */ MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC = 0x00000004, /* When set, the resource manager will load the data source asynchronously. */ MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT = 0x00000008, /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */ - MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH = 0x00000010 /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */ + MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH = 0x00000010, /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */ + MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING = 0x00000020 /* When set, configures the data source to loop by default. */ } ma_resource_manager_data_source_flags; @@ -10303,8 +10386,8 @@ typedef struct ma_uint64 rangeEndInPCMFrames; ma_uint64 loopPointBegInPCMFrames; ma_uint64 loopPointEndInPCMFrames; - ma_bool32 isLooping; ma_uint32 flags; + ma_bool32 isLooping; /* Deprecated. Use the MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING flag in `flags` instead. */ } ma_resource_manager_data_source_config; MA_API ma_resource_manager_data_source_config ma_resource_manager_data_source_config_init(void); @@ -10437,6 +10520,7 @@ typedef struct ma_decoding_backend_vtable** ppCustomDecodingBackendVTables; ma_uint32 customDecodingBackendCount; void* pCustomDecodingBackendUserData; + ma_resampler_config resampling; } ma_resource_manager_config; MA_API ma_resource_manager_config ma_resource_manager_config_init(void); @@ -10547,6 +10631,16 @@ Node Graph /* Use this when the bus count is determined by the node instance rather than the vtable. */ #define MA_NODE_BUS_COUNT_UNKNOWN 255 + +/* For some internal memory management of ma_node_graph. */ +typedef struct +{ + size_t offset; + size_t sizeInBytes; + unsigned char _data[1]; +} ma_stack; + + typedef struct ma_node_graph ma_node_graph; typedef void ma_node; @@ -10586,7 +10680,7 @@ typedef struct void (* onProcess)(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut); /* - A callback for retrieving the number of a input frames that are required to output the + A callback for retrieving the number of input frames that are required to output the specified number of output frames. You would only want to implement this when the node performs resampling. This is optional, even for nodes that perform resampling, but it does offer a small reduction in latency as it allows miniaudio to calculate the exact number of input frames @@ -10671,10 +10765,14 @@ typedef struct ma_node_base ma_node_base; struct ma_node_base { /* These variables are set once at startup. */ - ma_node_graph* pNodeGraph; /* The graph this node belongs to. */ + ma_node_graph* pNodeGraph; /* The graph this node belongs to. */ const ma_node_vtable* vtable; - float* pCachedData; /* Allocated on the heap. Fixed size. Needs to be stored on the heap because reading from output buses is done in separate function calls. */ - ma_uint16 cachedDataCapInFramesPerBus; /* The capacity of the input data cache in frames, per bus. */ + ma_uint32 inputBusCount; + ma_uint32 outputBusCount; + ma_node_input_bus* pInputBuses; + ma_node_output_bus* pOutputBuses; + float* pCachedData; /* Allocated on the heap. Fixed size. Needs to be stored on the heap because reading from output buses is done in separate function calls. */ + ma_uint16 cachedDataCapInFramesPerBus; /* The capacity of the input data cache in frames, per bus. */ /* These variables are read and written only from the audio thread. */ ma_uint16 cachedFrameCountOut; @@ -10682,13 +10780,9 @@ struct ma_node_base ma_uint16 consumedFrameCountIn; /* These variables are read and written between different threads. */ - MA_ATOMIC(4, ma_node_state) state; /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */ - MA_ATOMIC(8, ma_uint64) stateTimes[2]; /* Indexed by ma_node_state. Specifies the time based on the global clock that a node should be considered to be in the relevant state. */ - MA_ATOMIC(8, ma_uint64) localTime; /* The node's local clock. This is just a running sum of the number of output frames that have been processed. Can be modified by any thread with `ma_node_set_time()`. */ - ma_uint32 inputBusCount; - ma_uint32 outputBusCount; - ma_node_input_bus* pInputBuses; - ma_node_output_bus* pOutputBuses; + MA_ATOMIC(4, ma_node_state) state; /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */ + MA_ATOMIC(8, ma_uint64) stateTimes[2]; /* Indexed by ma_node_state. Specifies the time based on the global clock that a node should be considered to be in the relevant state. */ + MA_ATOMIC(8, ma_uint64) localTime; /* The node's local clock. This is just a running sum of the number of output frames that have been processed. Can be modified by any thread with `ma_node_set_time()`. */ /* Memory management. */ ma_node_input_bus _inputBuses[MA_MAX_NODE_LOCAL_BUS_COUNT]; @@ -10724,7 +10818,8 @@ MA_API ma_result ma_node_set_time(ma_node* pNode, ma_uint64 localTime); typedef struct { ma_uint32 channels; - ma_uint16 nodeCacheCapInFrames; + ma_uint32 processingSizeInFrames; /* This is the preferred processing size for node processing callbacks unless overridden by a node itself. Can be 0 in which case it will be based on the frame count passed into ma_node_graph_read_pcm_frames(), but will not be well defined. */ + size_t preMixStackSizeInBytes; /* Defaults to 512KB per channel. Reducing this will save memory, but the depth of your node graph will be more restricted. */ } ma_node_graph_config; MA_API ma_node_graph_config ma_node_graph_config_init(ma_uint32 channels); @@ -10735,10 +10830,15 @@ struct ma_node_graph /* Immutable. */ ma_node_base base; /* The node graph itself is a node so it can be connected as an input to different node graph. This has zero inputs and calls ma_node_graph_read_pcm_frames() to generate it's output. */ ma_node_base endpoint; /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */ - ma_uint16 nodeCacheCapInFrames; + float* pProcessingCache; /* This will be allocated when processingSizeInFrames is non-zero. This is needed because ma_node_graph_read_pcm_frames() can be called with a variable number of frames, and we may need to do some buffering in situations where the caller requests a frame count that's not a multiple of processingSizeInFrames. */ + ma_uint32 processingCacheFramesRemaining; + ma_uint32 processingSizeInFrames; /* Read and written by multiple threads. */ MA_ATOMIC(4, ma_bool32) isReading; + + /* Modified only by the audio thread. */ + ma_stack* pPreMixStack; }; MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node_graph* pNodeGraph); @@ -10748,6 +10848,7 @@ MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void* MA_API ma_uint32 ma_node_graph_get_channels(const ma_node_graph* pNodeGraph); MA_API ma_uint64 ma_node_graph_get_time(const ma_node_graph* pNodeGraph); MA_API ma_result ma_node_graph_set_time(ma_node_graph* pNodeGraph, ma_uint64 globalTime); +MA_API ma_uint32 ma_node_graph_get_processing_size_in_frames(const ma_node_graph* pNodeGraph); @@ -11023,6 +11124,7 @@ typedef enum MA_SOUND_FLAG_ASYNC = 0x00000004, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */ MA_SOUND_FLAG_WAIT_INIT = 0x00000008, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */ MA_SOUND_FLAG_UNKNOWN_LENGTH = 0x00000010, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH */ + MA_SOUND_FLAG_LOOPING = 0x00000020, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING */ /* ma_sound specific flags. */ MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT = 0x00001000, /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */ @@ -11054,6 +11156,7 @@ typedef struct ma_bool8 isPitchDisabled; /* Pitching can be explicitly disabled with MA_SOUND_FLAG_NO_PITCH to optimize processing. */ ma_bool8 isSpatializationDisabled; /* Spatialization can be explicitly disabled with MA_SOUND_FLAG_NO_SPATIALIZATION. */ ma_uint8 pinnedListenerIndex; /* The index of the listener this node should always use for spatialization. If set to MA_LISTENER_INDEX_CLOSEST the engine will use the closest listener. */ + ma_resampler_config resampling; } ma_engine_node_config; MA_API ma_engine_node_config ma_engine_node_config_init(ma_engine* pEngine, ma_engine_node_type type, ma_uint32 flags); @@ -11062,13 +11165,13 @@ MA_API ma_engine_node_config ma_engine_node_config_init(ma_engine* pEngine, ma_e /* Base node object for both ma_sound and ma_sound_group. */ typedef struct { - ma_node_base baseNode; /* Must be the first member for compatiblity with the ma_node API. */ + ma_node_base baseNode; /* Must be the first member for compatibility with the ma_node API. */ ma_engine* pEngine; /* A pointer to the engine. Set based on the value from the config. */ ma_uint32 sampleRate; /* The sample rate of the input data. For sounds backed by a data source, this will be the data source's sample rate. Otherwise it'll be the engine's sample rate. */ ma_uint32 volumeSmoothTimeInPCMFrames; ma_mono_expansion_mode monoExpansionMode; ma_fader fader; - ma_linear_resampler resampler; /* For pitch shift. */ + ma_resampler resampler; /* For pitch shift. */ ma_spatializer spatializer; ma_panner panner; ma_gainer volumeGainer; /* This will only be used if volumeSmoothTimeInPCMFrames is > 0. */ @@ -11122,13 +11225,14 @@ typedef struct ma_uint64 rangeEndInPCMFrames; ma_uint64 loopPointBegInPCMFrames; ma_uint64 loopPointEndInPCMFrames; - ma_bool32 isLooping; ma_sound_end_proc endCallback; /* Fired when the sound reaches the end. Will be fired from the audio thread. Do not restart, uninitialize or otherwise change the state of the sound from here. Instead fire an event or set a variable to indicate to a different thread to change the start of the sound. Will not be fired in response to a scheduled stop with ma_sound_set_stop_time_*(). */ void* pEndCallbackUserData; + ma_resampler_config pitchResampling; #ifndef MA_NO_RESOURCE_MANAGER ma_resource_manager_pipeline_notifications initNotifications; #endif ma_fence* pDoneFence; /* Deprecated. Use initNotifications instead. Released when the resource manager has finished decoding the entire sound. Not used with streams. */ + ma_bool32 isLooping; /* Deprecated. Use the MA_SOUND_FLAG_LOOPING flag in `flags` instead. */ } ma_sound_config; MA_API ma_sound_config ma_sound_config_init(void); /* Deprecated. Will be removed in version 0.12. Use ma_sound_config_2() instead. */ @@ -11142,7 +11246,10 @@ struct ma_sound MA_ATOMIC(4, ma_bool32) atEnd; ma_sound_end_proc endCallback; void* pEndCallbackUserData; - ma_bool8 ownsDataSource; + float* pProcessingCache; /* Will be null if pDataSource is null. */ + ma_uint32 processingCacheFramesRemaining; + ma_uint32 processingCacheCap; + ma_bool8 ownsDataSource; /* We're declaring a resource manager data source object here to save us a malloc when loading a @@ -11186,12 +11293,13 @@ typedef struct ma_log* pLog; /* When set to NULL, will use the context's log. */ ma_uint32 listenerCount; /* Must be between 1 and MA_ENGINE_MAX_LISTENERS. */ ma_uint32 channels; /* The number of channels to use when mixing and spatializing. When set to 0, will use the native channel count of the device. */ - ma_uint32 sampleRate; /* The sample rate. When set to 0 will use the native channel count of the device. */ + ma_uint32 sampleRate; /* The sample rate. When set to 0 will use the native sample rate of the device. */ ma_uint32 periodSizeInFrames; /* If set to something other than 0, updates will always be exactly this size. The underlying device may be a different size, but from the perspective of the mixer that won't matter.*/ ma_uint32 periodSizeInMilliseconds; /* Used if periodSizeInFrames is unset. */ ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. If set to 0, will use gainSmoothTimeInMilliseconds. */ ma_uint32 gainSmoothTimeInMilliseconds; /* When set to 0, gainSmoothTimeInFrames will be used. If both are set to 0, a default value will be used. */ ma_uint32 defaultVolumeSmoothTimeInPCMFrames; /* Defaults to 0. Controls the default amount of smoothing to apply to volume changes to sounds. High values means more smoothing at the expense of high latency (will take longer to reach the new volume). */ + ma_uint32 preMixStackSizeInBytes; /* A stack is used for internal processing in the node graph. This allows you to configure the size of this stack. Smaller values will reduce the maximum depth of your node graph. You should rarely need to modify this. */ ma_allocation_callbacks allocationCallbacks; ma_bool32 noAutoStart; /* When set to true, requires an explicit call to ma_engine_start(). This is false by default, meaning the engine will be started automatically in ma_engine_init(). */ ma_bool32 noDevice; /* When set to true, don't create a default device. ma_engine_read_pcm_frames() can be called manually to read data. */ @@ -11199,6 +11307,8 @@ typedef struct ma_vfs* pResourceManagerVFS; /* A pointer to a pre-allocated VFS object to use with the resource manager. This is ignored if pResourceManager is not NULL. */ ma_engine_process_proc onProcess; /* Fired at the end of each call to ma_engine_read_pcm_frames(). For engine's that manage their own internal device (the default configuration), this will be fired from the audio thread, and you do not need to call ma_engine_read_pcm_frames() manually in order to trigger this. */ void* pProcessUserData; /* User data that's passed into onProcess. */ + ma_resampler_config resourceManagerResampling; /* The resampling config to use with the resource manager. */ + ma_resampler_config pitchResampling; /* The resampling config for the pitch and Doppler effects. You will typically want this to be a fast resampler. For high quality stuff, it's recommended that you pre-resample. */ } ma_engine_config; MA_API ma_engine_config ma_engine_config_init(void); @@ -11206,12 +11316,12 @@ MA_API ma_engine_config ma_engine_config_init(void); struct ma_engine { - ma_node_graph nodeGraph; /* An engine is a node graph. It should be able to be plugged into any ma_node_graph API (with a cast) which means this must be the first member of this struct. */ + ma_node_graph nodeGraph; /* An engine is a node graph. It should be able to be plugged into any ma_node_graph API (with a cast) which means this must be the first member of this struct. */ #if !defined(MA_NO_RESOURCE_MANAGER) ma_resource_manager* pResourceManager; #endif #if !defined(MA_NO_DEVICE_IO) - ma_device* pDevice; /* Optionally set via the config, otherwise allocated by the engine in ma_engine_init(). */ + ma_device* pDevice; /* Optionally set via the config, otherwise allocated by the engine in ma_engine_init(). */ #endif ma_log* pLog; ma_uint32 sampleRate; @@ -11220,14 +11330,15 @@ struct ma_engine ma_allocation_callbacks allocationCallbacks; ma_bool8 ownsResourceManager; ma_bool8 ownsDevice; - ma_spinlock inlinedSoundLock; /* For synchronizing access so the inlined sound list. */ - ma_sound_inlined* pInlinedSoundHead; /* The first inlined sound. Inlined sounds are tracked in a linked list. */ - MA_ATOMIC(4, ma_uint32) inlinedSoundCount; /* The total number of allocated inlined sound objects. Used for debugging. */ - ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. */ + ma_spinlock inlinedSoundLock; /* For synchronizing access to the inlined sound list. */ + ma_sound_inlined* pInlinedSoundHead; /* The first inlined sound. Inlined sounds are tracked in a linked list. */ + MA_ATOMIC(4, ma_uint32) inlinedSoundCount; /* The total number of allocated inlined sound objects. Used for debugging. */ + ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. */ ma_uint32 defaultVolumeSmoothTimeInPCMFrames; ma_mono_expansion_mode monoExpansionMode; ma_engine_process_proc onProcess; void* pProcessUserData; + ma_resampler_config pitchResamplingConfig; }; MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEngine); @@ -11288,8 +11399,12 @@ MA_API ma_engine* ma_sound_get_engine(const ma_sound* pSound); MA_API ma_data_source* ma_sound_get_data_source(const ma_sound* pSound); MA_API ma_result ma_sound_start(ma_sound* pSound); MA_API ma_result ma_sound_stop(ma_sound* pSound); -MA_API ma_result ma_sound_stop_with_fade_in_pcm_frames(ma_sound* pSound, ma_uint64 fadeLengthInFrames); /* Will overwrite any scheduled stop and fade. */ -MA_API ma_result ma_sound_stop_with_fade_in_milliseconds(ma_sound* pSound, ma_uint64 fadeLengthInFrames); /* Will overwrite any scheduled stop and fade. */ +MA_API ma_result ma_sound_stop_with_fade_in_pcm_frames(ma_sound* pSound, ma_uint64 fadeLengthInFrames); /* Will overwrite any scheduled stop and fade. If you want to restart the sound, first reset it with `ma_sound_reset_stop_time_and_fade()`. There are plans to make this less awkward in the future. */ +MA_API ma_result ma_sound_stop_with_fade_in_milliseconds(ma_sound* pSound, ma_uint64 fadeLengthInFrames); /* Will overwrite any scheduled stop and fade. If you want to restart the sound, first reset it with `ma_sound_reset_stop_time_and_fade()`. There are plans to make this less awkward in the future. */ +MA_API void ma_sound_reset_start_time(ma_sound* pSound); +MA_API void ma_sound_reset_stop_time(ma_sound* pSound); +MA_API void ma_sound_reset_fade(ma_sound* pSound); +MA_API void ma_sound_reset_stop_time_and_fade(ma_sound* pSound); /* Resets fades and scheduled stop time. Does not seek back to the start. */ MA_API void ma_sound_set_volume(ma_sound* pSound, float volume); MA_API float ma_sound_get_volume(const ma_sound* pSound); MA_API void ma_sound_set_pan(ma_sound* pSound, float pan); @@ -11348,11 +11463,12 @@ MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping); MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound); MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound); MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameIndex); /* Just a wrapper around ma_data_source_seek_to_pcm_frame(). */ -MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap); -MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor); -MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength); -MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor); -MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength); +MA_API ma_result ma_sound_seek_to_second(ma_sound* pSound, float seekPointInSeconds); /* Abstraction to ma_sound_seek_to_pcm_frame() */ +MA_API ma_result ma_sound_get_data_format(const ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap); +MA_API ma_result ma_sound_get_cursor_in_pcm_frames(const ma_sound* pSound, ma_uint64* pCursor); +MA_API ma_result ma_sound_get_length_in_pcm_frames(const ma_sound* pSound, ma_uint64* pLength); +MA_API ma_result ma_sound_get_cursor_in_seconds(const ma_sound* pSound, float* pCursor); +MA_API ma_result ma_sound_get_length_in_seconds(const ma_sound* pSound, float* pLength); MA_API ma_result ma_sound_set_end_callback(ma_sound* pSound, ma_sound_end_proc callback, void* pUserData); MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup); @@ -11473,17 +11589,23 @@ IMPLEMENTATION #endif #if !defined(MA_WIN32) -#include -#include /* select() (used for ma_sleep()). */ -#include + #if !defined(MA_NO_THREADING) + #include + #include /* For pthreads. */ + #endif + + #include /* select() (used for ma_sleep()). */ + #include /* For nanosleep() */ + #include #endif -#ifdef MA_NX -#include /* For nanosleep() */ +/* For fstat(), etc. */ +#if defined(MA_XBOX_NXDK) + #include /* Suggestion for NXDK: Add a sys/stat.h wrapper for compatibility. */ +#else + #include #endif -#include /* For fstat(), etc. */ - #ifdef MA_EMSCRIPTEN #include #endif @@ -11535,7 +11657,7 @@ IMPLEMENTATION #endif /* Intrinsics Support */ -#if (defined(MA_X64) || defined(MA_X86)) && !defined(__COSMOPOLITAN__) +#if defined(MA_X64) || defined(MA_X86) #if defined(_MSC_VER) && !defined(__clang__) /* MSVC. */ #if _MSC_VER >= 1400 && !defined(MA_NO_SSE2) /* 2005 */ @@ -11790,7 +11912,7 @@ static MA_INLINE ma_bool32 ma_has_neon(void) #endif #ifndef MA_RESTRICT - #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) + #if defined(__clang__) || defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))) #define MA_RESTRICT __restrict #else #define MA_RESTRICT @@ -11884,7 +12006,7 @@ static void ma_sleep__posix(ma_uint32 milliseconds) (void)milliseconds; MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */ #else - #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || defined(MA_NX) + #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || defined(MA_SWITCH) struct timespec ts; ts.tv_sec = milliseconds / 1000; ts.tv_nsec = milliseconds % 1000 * 1000000; @@ -11926,7 +12048,7 @@ static MA_INLINE void ma_yield(void) #endif #endif #else - __asm__ __volatile__ ("pause"); + __asm__ __volatile__ ("rep; nop"); #endif #elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) /* ARM */ @@ -11949,7 +12071,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void) { unsigned int prevState; - #if defined(_MSC_VER) + #if defined(_MSC_VER) && !defined(MA_XBOX_NXDK) { /* Older versions of Visual Studio don't support the "safe" versions of _controlfp_s(). I don't @@ -11972,7 +12094,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void) } #elif defined(MA_X86) || defined(MA_X64) { - #if defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */ + #if defined(MA_SUPPORT_SSE2) && defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */ { prevState = _mm_getcsr(); _mm_setcsr(prevState | MA_MM_DENORMALS_ZERO_MASK | MA_MM_FLUSH_ZERO_MASK); @@ -11996,7 +12118,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void) static MA_INLINE void ma_restore_denormals(unsigned int prevState) { - #if defined(_MSC_VER) + #if defined(_MSC_VER) && !defined(MA_XBOX_NXDK) { /* Older versions of Visual Studio do not support _controlfp_s(). See ma_disable_denormals(). */ #if _MSC_VER <= 1200 @@ -12012,7 +12134,7 @@ static MA_INLINE void ma_restore_denormals(unsigned int prevState) } #elif defined(MA_X86) || defined(MA_X64) { - #if defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */ + #if defined(MA_SUPPORT_SSE2) && defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */ { _mm_setcsr(prevState); } @@ -12648,6 +12770,29 @@ MA_API MA_NO_INLINE int ma_strcmp(const char* str1, const char* str2) return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0]; } +MA_API MA_NO_INLINE int ma_wcscmp(const wchar_t* str1, const wchar_t* str2) +{ + if (str1 == str2) return 0; + + /* These checks differ from the standard implementation. It's not important, but I prefer it just for sanity. */ + if (str1 == NULL) return -1; + if (str2 == NULL) return 1; + + for (;;) { + if (str1[0] == L'\0') { + break; + } + if (str1[0] != str2[0]) { + break; + } + + str1 += 1; + str2 += 1; + } + + return ((unsigned short*)str1)[0] - ((unsigned short*)str2)[0]; +} + MA_API MA_NO_INLINE int ma_strappend(char* dst, size_t dstSize, const char* srcA, const char* srcB) { int result; @@ -12665,6 +12810,22 @@ MA_API MA_NO_INLINE int ma_strappend(char* dst, size_t dstSize, const char* srcA return result; } +MA_API MA_NO_INLINE size_t ma_wcslen(const wchar_t* str) +{ + const wchar_t* end; + + if (str == NULL) { + return 0; + } + + end = str; + while (end[0] != '\0') { + end += 1; + } + + return end - str; +} + MA_API MA_NO_INLINE char* ma_copy_string(const char* src, const ma_allocation_callbacks* pAllocationCallbacks) { size_t sz; @@ -12687,7 +12848,7 @@ MA_API MA_NO_INLINE char* ma_copy_string(const char* src, const ma_allocation_ca MA_API MA_NO_INLINE wchar_t* ma_copy_string_w(const wchar_t* src, const ma_allocation_callbacks* pAllocationCallbacks) { - size_t sz = wcslen(src)+1; + size_t sz = ma_wcslen(src)+1; wchar_t* dst = (wchar_t*)ma_malloc(sz * sizeof(*dst), pAllocationCallbacks); if (dst == NULL) { return NULL; @@ -13118,7 +13279,7 @@ MA_API ma_result ma_fopen(FILE** ppFile, const char* pFilePath, const char* pOpe return MA_INVALID_ARGS; } -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if (defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(MA_XBOX_NXDK) err = fopen_s(ppFile, pFilePath, pOpenMode); if (err != 0) { return ma_result_from_errno(err); @@ -13160,7 +13321,7 @@ _wfopen() isn't always available in all compilation environments. This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs() fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support. */ -#if defined(_WIN32) +#if defined(_WIN32) && !defined(MA_XBOX_NXDK) #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS)) #define MA_HAS_WFOPEN #endif @@ -13176,29 +13337,34 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_ return MA_INVALID_ARGS; } -#if defined(MA_HAS_WFOPEN) + #if defined(MA_HAS_WFOPEN) { /* Use _wfopen() on Windows. */ - #if defined(_MSC_VER) && _MSC_VER >= 1400 - errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode); - if (err != 0) { - return ma_result_from_errno(err); + #if defined(_MSC_VER) && _MSC_VER >= 1400 + { + errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode); + if (err != 0) { + return ma_result_from_errno(err); + } } - #else - *ppFile = _wfopen(pFilePath, pOpenMode); - if (*ppFile == NULL) { - return ma_result_from_errno(errno); + #else + { + *ppFile = _wfopen(pFilePath, pOpenMode); + if (*ppFile == NULL) { + return ma_result_from_errno(errno); + } } - #endif + #endif + (void)pAllocationCallbacks; } -#else - /* - Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can - think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for - maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility. - */ + #elif !defined(MA_XBOX_NXDK) && !defined(MA_DOS) /* If your compiler does not support wcsrtombs(), add it here. */ { + /* + Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can + think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for + maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility. + */ mbstate_t mbs; size_t lenMB; const wchar_t* pFilePathTemp = pFilePath; @@ -13239,11 +13405,16 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_ ma_free(pFilePathMB, pAllocationCallbacks); } + #else + { + /* Getting here means there is no way to open the file with a wide character string. */ + *ppFile = NULL; + } + #endif if (*ppFile == NULL) { return MA_ERROR; } -#endif return MA_SUCCESS; } @@ -13252,7 +13423,7 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_ static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 sizeInBytes) { -#if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX +#if MA_SIZE_MAX > 0xFFFFFFFF MA_COPY_MEMORY(dst, src, (size_t)sizeInBytes); #else while (sizeInBytes > 0) { @@ -13272,7 +13443,7 @@ static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 si static MA_INLINE void ma_zero_memory_64(void* dst, ma_uint64 sizeInBytes) { -#if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX +#if MA_SIZE_MAX > 0xFFFFFFFF MA_ZERO_MEMORY(dst, (size_t)sizeInBytes); #else while (sizeInBytes > 0) { @@ -13401,6 +13572,18 @@ static ma_result ma_allocation_callbacks_init_copy(ma_allocation_callbacks* pDst Logging **************************************************************************************************************************************************************/ +#ifndef ma_va_copy + #if !defined(_MSC_VER) || _MSC_VER >= 1800 + #if (defined(__GNUC__) && __GNUC__ < 3) + #define ma_va_copy(dst, src) ((dst) = (src)) /* This is untested. Not sure if this is correct for old GCC. */ + #else + #define ma_va_copy(dst, src) va_copy((dst), (src)) + #endif + #else + #define ma_va_copy(dst, src) ((dst) = (src)) + #endif +#endif + MA_API const char* ma_log_level_to_string(ma_uint32 logLevel) { switch (logLevel) @@ -13641,9 +13824,15 @@ MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat int length; char pFormattedMessageStack[1024]; char* pFormattedMessageHeap = NULL; + va_list args2; /* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */ - length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args); + ma_va_copy(args2, args); + { + length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args2); + } + va_end(args2); + if (length < 0) { return MA_INVALID_OPERATION; /* An error occurred when trying to convert the buffer. */ } @@ -13684,17 +13873,10 @@ MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat char* pFormattedMessage = NULL; va_list args2; - #if _MSC_VER >= 1800 + ma_va_copy(args2, args); { - va_copy(args2, args); + formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2); } - #else - { - args2 = args; - } - #endif - - formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2); va_end(args2); if (formattedLen <= 0) { @@ -13861,7 +14043,7 @@ static ma_uint32 ma_ffs_32(ma_uint32 x) /* Just a naive implementation just to get things working for now. Will optimize this later. */ for (i = 0; i < 32; i += 1) { - if ((x & (1 << i)) != 0) { + if ((x & (1U << i)) != 0) { return i; } } @@ -13893,7 +14075,7 @@ miniaudio's purposes. #define MA_LCG_A 48271 #define MA_LCG_C 0 -static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_seed() to use an explicit seed. */ +static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_lcg_seed() to use an explicit seed. */ static MA_INLINE void ma_lcg_seed(ma_lcg* pLCG, ma_int32 seed) { @@ -13942,7 +14124,7 @@ static MA_INLINE ma_int32 ma_lcg_rand_range_s32(ma_lcg* pLCG, ma_int32 lo, ma_in } - +#if 0 /* Currently unused. */ static MA_INLINE void ma_seed(ma_int32 seed) { ma_lcg_seed(&g_maLCG, seed); @@ -13967,6 +14149,7 @@ static MA_INLINE float ma_rand_f32(void) { return ma_lcg_rand_f32(&g_maLCG); } +#endif static MA_INLINE float ma_rand_range_f32(float lo, float hi) { @@ -14024,8 +14207,9 @@ static MA_INLINE ma_int32 ma_dither_s32(ma_dither_mode ditherMode, ma_int32 dith Atomics **************************************************************************************************************************************************************/ -/* ma_atomic.h begin */ +/* c89atomic.h begin */ #ifndef ma_atomic_h +#define ma_atomic_h #if defined(__cplusplus) extern "C" { #endif @@ -14037,11 +14221,63 @@ extern "C" { #endif #endif typedef int ma_atomic_memory_order; -#define MA_ATOMIC_HAS_8 -#define MA_ATOMIC_HAS_16 -#define MA_ATOMIC_HAS_32 -#define MA_ATOMIC_HAS_64 -#if (defined(_MSC_VER) ) || defined(__WATCOMC__) || defined(__DMC__) +#if !defined(MA_ATOMIC_MODERN_MSVC) && \ + !defined(MA_ATOMIC_LEGACY_MSVC) && \ + !defined(MA_ATOMIC_LEGACY_MSVC_ASM) && \ + !defined(MA_ATOMIC_MODERN_GCC) && \ + !defined(MA_ATOMIC_LEGACY_GCC) && \ + !defined(MA_ATOMIC_LEGACY_GCC_ASM) + #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__) || defined(__BORLANDC__) + #if (defined(_MSC_VER) && _MSC_VER > 1600) + #define MA_ATOMIC_MODERN_MSVC + #else + #if defined(MA_X64) + #define MA_ATOMIC_LEGACY_MSVC + #else + #define MA_ATOMIC_LEGACY_MSVC_ASM + #endif + #endif + #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || defined(__clang__) + #define MA_ATOMIC_MODERN_GCC + #else + #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) + #define MA_ATOMIC_LEGACY_GCC + #else + #define MA_ATOMIC_LEGACY_GCC_ASM + #endif + #endif +#endif +#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC) + #include + #define ma_atomic_memory_order_relaxed 1 + #define ma_atomic_memory_order_consume 2 + #define ma_atomic_memory_order_acquire 3 + #define ma_atomic_memory_order_release 4 + #define ma_atomic_memory_order_acq_rel 5 + #define ma_atomic_memory_order_seq_cst 6 + #define MA_ATOMIC_MSVC_ARM_INTRINSIC_NORETURN(dst, src, order, intrin, ma_atomicType, msvcType) \ + switch (order) \ + { \ + case ma_atomic_memory_order_relaxed: \ + { \ + intrin##_nf((volatile msvcType*)dst, (msvcType)src); \ + } break; \ + case ma_atomic_memory_order_consume: \ + case ma_atomic_memory_order_acquire: \ + { \ + intrin##_acq((volatile msvcType*)dst, (msvcType)src); \ + } break; \ + case ma_atomic_memory_order_release: \ + { \ + intrin##_rel((volatile msvcType*)dst, (msvcType)src); \ + } break; \ + case ma_atomic_memory_order_acq_rel: \ + case ma_atomic_memory_order_seq_cst: \ + default: \ + { \ + intrin((volatile msvcType*)dst, (msvcType)src); \ + } break; \ + } #define MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, intrin, ma_atomicType, msvcType) \ ma_atomicType result; \ switch (order) \ @@ -14067,720 +14303,1501 @@ typedef int ma_atomic_memory_order; } break; \ } \ return result; - #define MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, expected, desired, order, intrin, ma_atomicType, msvcType) \ + typedef ma_uint32 ma_atomic_flag; + static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, 1, order, _InterlockedExchange, ma_atomic_flag, long); + } + #else + { + (void)order; + return (ma_atomic_flag)_InterlockedExchange((volatile long*)dst, (long)1); + } + #endif + } + static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC_NORETURN(dst, 0, order, _InterlockedExchange, ma_atomic_flag, long); + } + #else + { + (void)order; + _InterlockedExchange((volatile long*)dst, (long)0); + } + #endif + } + static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order) + { + (void)order; + return (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, 0, 0); + } +#endif +#if defined(MA_ATOMIC_LEGACY_MSVC_ASM) + #define ma_atomic_memory_order_relaxed 1 + #define ma_atomic_memory_order_consume 2 + #define ma_atomic_memory_order_acquire 3 + #define ma_atomic_memory_order_release 4 + #define ma_atomic_memory_order_acq_rel 5 + #define ma_atomic_memory_order_seq_cst 6 + typedef ma_uint32 ma_atomic_flag; + static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + ma_atomic_flag result = 0; + (void)order; + __asm { + mov ecx, dst + mov eax, 1 + xchg [ecx], eax + mov result, eax + } + return result; + } + static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov dword ptr [esi], 0 + } + } else { + __asm { + mov esi, dst + mov eax, 0 + xchg [esi], eax + } + } + } + static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order) + { + ma_atomic_flag result = 0; + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov eax, [esi] + mov result, eax + } + } else if (order <= ma_atomic_memory_order_release) { + __asm { + mov esi, dst + mov eax, [esi] + lock add dword ptr [esp], 0 + mov result, eax + } + } else { + __asm { + lock add dword ptr [esp], 0 + mov esi, dst + mov eax, [esi] + mov result, eax + lock add dword ptr [esp], 0 + } + } + return result; + } +#endif +#if defined(MA_ATOMIC_MODERN_GCC) + #define ma_atomic_memory_order_relaxed __ATOMIC_RELAXED + #define ma_atomic_memory_order_consume __ATOMIC_CONSUME + #define ma_atomic_memory_order_acquire __ATOMIC_ACQUIRE + #define ma_atomic_memory_order_release __ATOMIC_RELEASE + #define ma_atomic_memory_order_acq_rel __ATOMIC_ACQ_REL + #define ma_atomic_memory_order_seq_cst __ATOMIC_SEQ_CST + typedef ma_uint32 ma_atomic_flag; + #define ma_atomic_flag_test_and_set_explicit(dst, order) __atomic_exchange_n(dst, 1, order) + #define ma_atomic_flag_clear_explicit(dst, order) __atomic_store_n(dst, 0, order) + #define ma_atomic_flag_load_explicit(dst, order) __atomic_load_n(dst, order) +#endif +#if defined(MA_ATOMIC_LEGACY_GCC) + #define ma_atomic_memory_order_relaxed 1 + #define ma_atomic_memory_order_consume 2 + #define ma_atomic_memory_order_acquire 3 + #define ma_atomic_memory_order_release 4 + #define ma_atomic_memory_order_acq_rel 5 + #define ma_atomic_memory_order_seq_cst 6 + typedef ma_uint32 ma_atomic_flag; + static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + if (order > ma_atomic_memory_order_acquire) { + __sync_synchronize(); + } + return __sync_lock_test_and_set(dst, 1); + } + static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + if (order > ma_atomic_memory_order_release) { + __sync_synchronize(); + } + __sync_lock_release(dst); + } + static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order) + { + (void)order; + return __sync_val_compare_and_swap((ma_atomic_flag*)dst, 0, 0); + } +#endif +#if defined(MA_ATOMIC_LEGACY_GCC_ASM) + #define ma_atomic_memory_order_relaxed 1 + #define ma_atomic_memory_order_consume 2 + #define ma_atomic_memory_order_acquire 3 + #define ma_atomic_memory_order_release 4 + #define ma_atomic_memory_order_acq_rel 5 + #define ma_atomic_memory_order_seq_cst 6 + #if defined(MA_X86) + #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory") + #elif defined(MA_X64) + #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory") + #else + #error Unsupported architecture. + #endif + #define MA_ATOMIC_XCHG_GCC_X86(instructionSizeSuffix, result, dst, src) \ + __asm__ __volatile__( \ + "xchg"instructionSizeSuffix" %0, %1" \ + : "=r"(result), \ + "=m"(*dst) \ + : "0"(src), \ + "m"(*dst) \ + : "memory" \ + ) + #define MA_ATOMIC_LOAD_RELAXED_GCC_X86(instructionSizeSuffix, result, dst) \ + __asm__ __volatile__( \ + "mov"instructionSizeSuffix" %1, %0" \ + : "=r"(result) \ + : "m"(*dst) \ + ) + #define MA_ATOMIC_LOAD_RELEASE_GCC_X86(instructionSizeSuffix, result, dst) \ + ma_atomic_thread_fence(ma_atomic_memory_order_release); \ + __asm__ __volatile__( \ + "mov"instructionSizeSuffix" %1, %0" \ + : "=r"(result) \ + : "m"(*dst) \ + : "memory" \ + ) + #define MA_ATOMIC_LOAD_SEQ_CST_GCC_X86(instructionSizeSuffix, result, dst) \ + ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst); \ + __asm__ __volatile__( \ + "mov"instructionSizeSuffix" %1, %0" \ + : "=r"(result) \ + : "m"(*dst) \ + : "memory" \ + ); \ + ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst) + typedef ma_uint32 ma_atomic_flag; + static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + ma_atomic_flag result; + #if defined(MA_X86) || defined(MA_X64) + { + (void)order; + MA_ATOMIC_XCHG_GCC_X86("l", result, dst, 1); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order) + { + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm__ __volatile__( + "movl $0, %0" + : "=m"(*dst) + ); + } else if (order == ma_atomic_memory_order_release) { + __asm__ __volatile__( + "movl $0, %0" + : "=m"(*dst) + : + : "memory" + ); + } else { + ma_atomic_flag tmp = 0; + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(tmp), + "=m"(*dst) + : "0"(tmp), + "m"(*dst) + : "memory" + ); + } + } + #else + { + #error Unsupported architecture. + } + #endif + } + static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order) + { + #if defined(MA_X86) || defined(MA_X64) + { + ma_atomic_flag result; + if (order == ma_atomic_memory_order_relaxed) { + MA_ATOMIC_LOAD_RELAXED_GCC_X86("l", result, dst); + } else if (order <= ma_atomic_memory_order_release) { + MA_ATOMIC_LOAD_RELEASE_GCC_X86("l", result, dst); + } else { + MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("l", result, dst); + } + return result; + } + #else + { + #error Unsupported architecture. + } + #endif + } +#endif +#define ma_atomic_flag_test_and_set(dst) ma_atomic_flag_test_and_set_explicit(dst, ma_atomic_memory_order_acquire) +#define ma_atomic_flag_clear(dst) ma_atomic_flag_clear_explicit(dst, ma_atomic_memory_order_release) +typedef ma_atomic_flag ma_atomic_spinlock; +static MA_INLINE void ma_atomic_spinlock_lock(volatile ma_atomic_spinlock* pSpinlock) +{ + for (;;) { + if (ma_atomic_flag_test_and_set_explicit(pSpinlock, ma_atomic_memory_order_acquire) == 0) { + break; + } + while (ma_atomic_flag_load_explicit(pSpinlock, ma_atomic_memory_order_relaxed) == 1) { + } + } +} +static MA_INLINE void ma_atomic_spinlock_unlock(volatile ma_atomic_spinlock* pSpinlock) +{ + ma_atomic_flag_clear_explicit(pSpinlock, ma_atomic_memory_order_release); +} +ma_atomic_spinlock ma_atomic_global_lock; +#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC_ASM) || defined(MA_ATOMIC_LEGACY_GCC) || defined(MA_ATOMIC_LEGACY_GCC_ASM) + #if defined(MA_X64) || (defined(MA_X86) && ((defined(__GNUC__) && defined(__i486__)) || (defined(_M_IX86) && _M_IX86 >= 400))) + #if defined(MA_ATOMIC_LEGACY_MSVC) && defined(MA_X64) + #else + #define MA_ATOMIC_IS_LOCK_FREE_8 1 + #define MA_ATOMIC_IS_LOCK_FREE_16 1 + #endif + #define MA_ATOMIC_IS_LOCK_FREE_32 1 + #if defined(MA_X64) || (defined(MA_X86) && ((defined(__GNUC__) && defined(__i586__)) || (defined(_M_IX86) && _M_IX86 >= 500))) + #define MA_ATOMIC_IS_LOCK_FREE_64 1 + #else + #endif + #else + #endif + #if defined(MA_ARM32) || defined(MA_ARM64) + #define MA_ATOMIC_IS_LOCK_FREE_8 1 + #define MA_ATOMIC_IS_LOCK_FREE_16 1 + #define MA_ATOMIC_IS_LOCK_FREE_32 1 + #if defined(MA_ARM64) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) + #define MA_ATOMIC_IS_LOCK_FREE_64 1 + #endif + #endif + #if defined(MA_ATOMIC_PPC32) || defined(MA_ATOMIC_PPC64) + #if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7))) && !defined(__clang__) + #else + #define MA_ATOMIC_IS_LOCK_FREE_8 1 + #define MA_ATOMIC_IS_LOCK_FREE_16 1 + #endif + #define MA_ATOMIC_IS_LOCK_FREE_32 1 + #if defined(MA_ATOMIC_PPC64) + #define MA_ATOMIC_IS_LOCK_FREE_64 1 + #endif + #endif + static MA_INLINE ma_bool32 ma_atomic_is_lock_free_8(volatile void* ptr) + { + (void)ptr; + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + return 1; + #else + return 0; + #endif + } + static MA_INLINE ma_bool32 ma_atomic_is_lock_free_16(volatile void* ptr) + { + (void)ptr; + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + return 1; + #else + return 0; + #endif + } + static MA_INLINE ma_bool32 ma_atomic_is_lock_free_32(volatile void* ptr) + { + (void)ptr; + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + return 1; + #else + return 0; + #endif + } + static MA_INLINE ma_bool32 ma_atomic_is_lock_free_64(volatile void* ptr) + { + (void)ptr; + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + return 1; + #else + return 0; + #endif + } +#endif +#define MA_ATOMIC_COMPARE_AND_SWAP_LOCK(sizeInBits, dst, expected, replacement) \ + ma_uint##sizeInBits result; \ + ma_atomic_spinlock_lock(&ma_atomic_global_lock); \ + { \ + result = *dst; \ + if (result == expected) { \ + *dst = replacement; \ + } \ + } \ + ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \ + return result +#define MA_ATOMIC_LOAD_EXPLICIT_LOCK(sizeInBits, ptr, order) \ + ma_uint##sizeInBits result; \ + ma_atomic_spinlock_lock(&ma_atomic_global_lock); \ + { \ + result = *ptr; \ + (void)order; \ + } \ + ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \ + return result +#define MA_ATOMIC_STORE_EXPLICIT_LOCK(sizeInBits, dst, src, order) \ + ma_atomic_spinlock_lock(&ma_atomic_global_lock); \ + { \ + *dst = src; \ + (void)order; \ + } \ + ma_atomic_spinlock_unlock(&ma_atomic_global_lock) +#define MA_ATOMIC_STORE_EXPLICIT_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, src) != oldValue); \ + (void)order +#define MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits result; \ + ma_atomic_spinlock_lock(&ma_atomic_global_lock); \ + { \ + result = *dst; \ + *dst = src; \ + (void)order; \ + } \ + ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \ + return result +#define MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, src) != oldValue); \ + (void)order; \ + return oldValue +#define MA_ATOMIC_FETCH_ADD_LOCK(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits result; \ + ma_atomic_spinlock_lock(&ma_atomic_global_lock); \ + { \ + result = *dst; \ + *dst += src; \ + (void)order; \ + } \ + ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \ + return result +#define MA_ATOMIC_FETCH_ADD_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + ma_uint##sizeInBits newValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + newValue = oldValue + src; \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \ + (void)order; \ + return oldValue +#define MA_ATOMIC_FETCH_AND_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + ma_uint##sizeInBits newValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + newValue = (ma_uint##sizeInBits)(oldValue & src); \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \ + (void)order; \ + return oldValue +#define MA_ATOMIC_FETCH_OR_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + ma_uint##sizeInBits newValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + newValue = (ma_uint##sizeInBits)(oldValue | src); \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \ + (void)order; \ + return oldValue +#define MA_ATOMIC_FETCH_XOR_CAS(sizeInBits, dst, src, order) \ + ma_uint##sizeInBits oldValue; \ + ma_uint##sizeInBits newValue; \ + do { \ + oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \ + newValue = (ma_uint##sizeInBits)(oldValue ^ src); \ + } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \ + (void)order; \ + return oldValue +#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC) + #define MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, expected, replacement, order, intrin, ma_atomicType, msvcType) \ ma_atomicType result; \ switch (order) \ { \ case ma_atomic_memory_order_relaxed: \ { \ - result = (ma_atomicType)intrin##_nf((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \ + result = (ma_atomicType)intrin##_nf((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \ } break; \ case ma_atomic_memory_order_consume: \ case ma_atomic_memory_order_acquire: \ { \ - result = (ma_atomicType)intrin##_acq((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \ + result = (ma_atomicType)intrin##_acq((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \ } break; \ case ma_atomic_memory_order_release: \ { \ - result = (ma_atomicType)intrin##_rel((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \ + result = (ma_atomicType)intrin##_rel((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \ } break; \ case ma_atomic_memory_order_acq_rel: \ case ma_atomic_memory_order_seq_cst: \ default: \ { \ - result = (ma_atomicType)intrin((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \ + result = (ma_atomicType)intrin((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \ } break; \ } \ return result; - #define ma_atomic_memory_order_relaxed 0 - #define ma_atomic_memory_order_consume 1 - #define ma_atomic_memory_order_acquire 2 - #define ma_atomic_memory_order_release 3 - #define ma_atomic_memory_order_acq_rel 4 - #define ma_atomic_memory_order_seq_cst 5 - #if _MSC_VER < 1600 && defined(MA_X86) - #define MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY - #endif - #if _MSC_VER < 1600 - #undef MA_ATOMIC_HAS_8 - #undef MA_ATOMIC_HAS_16 - #endif - #if !defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY) - #include - #endif - #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY) - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired) - { - ma_uint8 result = 0; - __asm { - mov ecx, dst - mov al, expected - mov dl, desired - lock cmpxchg [ecx], dl - mov result, al - } - return result; - } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired) - { - ma_uint16 result = 0; - __asm { - mov ecx, dst - mov ax, expected - mov dx, desired - lock cmpxchg [ecx], dx - mov result, ax - } - return result; - } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired) - { - ma_uint32 result = 0; - __asm { - mov ecx, dst - mov eax, expected - mov edx, desired - lock cmpxchg [ecx], edx - mov result, eax - } - return result; - } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired) - { - ma_uint32 resultEAX = 0; - ma_uint32 resultEDX = 0; - __asm { - mov esi, dst - mov eax, dword ptr expected - mov edx, dword ptr expected + 4 - mov ebx, dword ptr desired - mov ecx, dword ptr desired + 4 - lock cmpxchg8b qword ptr [esi] - mov resultEAX, eax - mov resultEDX, edx - } - return ((ma_uint64)resultEDX << 32) | resultEAX; - } - #endif + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + #define ma_atomic_compare_and_swap_8( dst, expected, replacement) (ma_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)replacement, (char)expected) #else - #if defined(MA_ATOMIC_HAS_8) - #define ma_atomic_compare_and_swap_8( dst, expected, desired) (ma_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)desired, (char)expected) - #endif - #if defined(MA_ATOMIC_HAS_16) - #define ma_atomic_compare_and_swap_16(dst, expected, desired) (ma_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)desired, (short)expected) - #endif - #if defined(MA_ATOMIC_HAS_32) - #define ma_atomic_compare_and_swap_32(dst, expected, desired) (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)desired, (long)expected) - #endif - #if defined(MA_ATOMIC_HAS_64) - #define ma_atomic_compare_and_swap_64(dst, expected, desired) (ma_uint64)_InterlockedCompareExchange64((volatile ma_int64*)dst, (ma_int64)desired, (ma_int64)expected) - #endif + static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement); + } #endif - #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY) - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 result = 0; - (void)order; - __asm { - mov ecx, dst - mov al, src - lock xchg [ecx], al - mov result, al - } - return result; - } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 result = 0; - (void)order; - __asm { - mov ecx, dst - mov ax, src - lock xchg [ecx], ax - mov result, ax - } - return result; - } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 result = 0; - (void)order; - __asm { - mov ecx, dst - mov eax, src - lock xchg [ecx], eax - mov result, eax - } - return result; - } - #endif + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + #define ma_atomic_compare_and_swap_16(dst, expected, replacement) (ma_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)replacement, (short)expected) #else - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { + static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement); + } + #endif + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + #define ma_atomic_compare_and_swap_32(dst, expected, replacement) (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)replacement, (long)expected) + #else + static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement); + } + #endif + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + #define ma_atomic_compare_and_swap_64(dst, expected, replacement) (ma_uint64)_InterlockedCompareExchange64((volatile ma_int64*)dst, (ma_int64)replacement, (ma_int64)expected) + #else + static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement); + } + #endif + static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange8, ma_uint8, char); + { + MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange8, ma_uint8, char); + } #else + { + (void)order; + return ma_atomic_compare_and_swap_8((volatile ma_uint8*)ptr, 0, 0); + } + #endif + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, ptr, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange16, ma_uint16, short); + } + #else + { + (void)order; + return ma_atomic_compare_and_swap_16((volatile ma_uint16*)ptr, 0, 0); + } + #endif + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, ptr, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange, ma_uint32, long); + } + #else + { + (void)order; + return ma_atomic_compare_and_swap_32((volatile ma_uint32*)ptr, 0, 0); + } + #endif + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, ptr, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange64, ma_uint64, long long); + } + #else + { + (void)order; + return ma_atomic_compare_and_swap_64((volatile ma_uint64*)ptr, 0, 0); + } + #endif + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, ptr, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange8, ma_uint8, char); + } + #else + { (void)order; return (ma_uint8)_InterlockedExchange8((volatile char*)dst, (char)src); - #endif } + #endif + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order); + } #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { #if defined(MA_ARM) + { MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange16, ma_uint16, short); + } #else + { (void)order; return (ma_uint16)_InterlockedExchange16((volatile short*)dst, (short)src); - #endif } + #endif + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order); + } #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { #if defined(MA_ARM) + { MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange, ma_uint32, long); + } #else + { (void)order; return (ma_uint32)_InterlockedExchange((volatile long*)dst, (long)src); - #endif } - #endif - #if defined(MA_ATOMIC_HAS_64) && defined(MA_64BIT) - static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange64, ma_uint64, long long); - #else - (void)order; - return (ma_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src); #endif - } - #else - #endif - #endif - #if defined(MA_ATOMIC_HAS_64) && !defined(MA_64BIT) - static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - do { - oldValue = *dst; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, src) != oldValue); - (void)order; - return oldValue; } - #endif - #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY) - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 result = 0; - (void)order; - __asm { - mov ecx, dst - mov al, src - lock xadd [ecx], al - mov result, al - } - return result; - } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order); + } #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + #if defined(MA_32BIT) { - ma_uint16 result = 0; - (void)order; - __asm { - mov ecx, dst - mov ax, src - lock xadd [ecx], ax - mov result, ax - } - return result; + MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order); } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 result = 0; - (void)order; - __asm { - mov ecx, dst - mov eax, src - lock xadd [ecx], eax - mov result, eax - } - return result; - } - #endif - #else - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd8, ma_uint8, char); #else + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange64, ma_uint64, long long); + } + #else + { + (void)order; + return (ma_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src); + } + #endif + } + #endif + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd8, ma_uint8, char); + } + #else + { (void)order; return (ma_uint8)_InterlockedExchangeAdd8((volatile char*)dst, (char)src); - #endif } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order); + } #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { #if defined(MA_ARM) + { MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd16, ma_uint16, short); + } #else + { (void)order; return (ma_uint16)_InterlockedExchangeAdd16((volatile short*)dst, (short)src); - #endif } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order); + } #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { #if defined(MA_ARM) + { MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd, ma_uint32, long); + } #else + { (void)order; return (ma_uint32)_InterlockedExchangeAdd((volatile long*)dst, (long)src); - #endif } - #endif - #if defined(MA_ATOMIC_HAS_64) && defined(MA_64BIT) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd64, ma_uint64, long long); - #else - (void)order; - return (ma_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src); #endif - } + } #else - #endif - #endif - #if defined(MA_ATOMIC_HAS_64) && !defined(MA_64BIT) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue + src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + #if defined(MA_32BIT) + { + MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order); + } + #else + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd64, ma_uint64, long long); + } + #else + { + (void)order; + return (ma_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src); + } + #endif + } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_8(dst, (ma_uint8)(-(ma_int8)src), order); + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_16(dst, (ma_uint16)(-(ma_int16)src), order); + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_32(dst, (ma_uint32)(-(ma_int32)src), order); + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_64(dst, (ma_uint64)(-(ma_int64)src), order); + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd8, ma_uint8, char); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd16, ma_uint16, short); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd, ma_uint32, long); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd64, ma_uint64, long long); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr8, ma_uint8, char); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr16, ma_uint16, short); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr, ma_uint32, long); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr64, ma_uint64, long long); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor8, ma_uint8, char); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor16, ma_uint16, short); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor, ma_uint32, long); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ARM) + { + MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor64, ma_uint64, long long); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order); + } + #endif + } + #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order) + #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order) + #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order) + #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order) + #if defined(MA_X64) + #define ma_atomic_thread_fence(order) __faststorefence(), (void)order + #elif defined(MA_ARM64) + #define ma_atomic_thread_fence(order) __dmb(_ARM64_BARRIER_ISH), (void)order + #else + static MA_INLINE void ma_atomic_thread_fence(ma_atomic_memory_order order) + { + volatile ma_uint32 barrier = 0; + ma_atomic_fetch_add_explicit_32(&barrier, 0, order); } #endif - #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY) - static MA_INLINE void __stdcall ma_atomic_thread_fence(ma_atomic_memory_order order) + #define ma_atomic_signal_fence(order) _ReadWriteBarrier(), (void)order +#endif +#if defined(MA_ATOMIC_LEGACY_MSVC_ASM) + static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) { + ma_uint8 result = 0; + __asm { + mov ecx, dst + mov al, expected + mov dl, replacement + lock cmpxchg [ecx], dl + mov result, al + } + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + ma_uint16 result = 0; + __asm { + mov ecx, dst + mov ax, expected + mov dx, replacement + lock cmpxchg [ecx], dx + mov result, ax + } + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + ma_uint32 result = 0; + __asm { + mov ecx, dst + mov eax, expected + mov edx, replacement + lock cmpxchg [ecx], edx + mov result, eax + } + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + ma_uint32 resultEAX = 0; + ma_uint32 resultEDX = 0; + __asm { + mov esi, dst + mov eax, dword ptr expected + mov edx, dword ptr expected + 4 + mov ebx, dword ptr replacement + mov ecx, dword ptr replacement + 4 + lock cmpxchg8b qword ptr [esi] + mov resultEAX, eax + mov resultEDX, edx + } + return ((ma_uint64)resultEDX << 32) | resultEAX; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + ma_uint8 result = 0; + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov al, [esi] + mov result, al + } + } else if (order <= ma_atomic_memory_order_release) { + __asm { + mov esi, dst + mov al, [esi] + lock add dword ptr [esp], 0 + mov result, al + } + } else { + __asm { + lock add dword ptr [esp], 0 + mov esi, dst + mov al, [esi] + mov result, al + lock add dword ptr [esp], 0 + } + } + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, dst, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + ma_uint16 result = 0; + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov ax, [esi] + mov result, ax + } + } else if (order <= ma_atomic_memory_order_release) { + __asm { + mov esi, dst + mov ax, [esi] + lock add dword ptr [esp], 0 + mov result, ax + } + } else { + __asm { + lock add dword ptr [esp], 0 + mov esi, dst + mov ax, [esi] + mov result, ax + lock add dword ptr [esp], 0 + } + } + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, dst, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + ma_uint32 result = 0; + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov eax, [esi] + mov result, eax + } + } else if (order <= ma_atomic_memory_order_release) { + __asm { + mov esi, dst + mov eax, [esi] + lock add dword ptr [esp], 0 + mov result, eax + } + } else { + __asm { + lock add dword ptr [esp], 0 + mov esi, dst + mov eax, [esi] + mov result, eax + lock add dword ptr [esp], 0 + } + } + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, dst, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* dst, ma_atomic_memory_order order) + { + (void)order; + return ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, 0, 0); + } + static MA_INLINE void __stdcall ma_atomic_store_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov al, src + mov [esi], al + } + } else { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + __asm { + mov esi, dst + mov al, src + xchg [esi], al + } + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(8, dst, src, order); + } + #endif + } + } + static MA_INLINE void __stdcall ma_atomic_store_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov ax, src + mov [esi], ax + } + } else { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + __asm { + mov esi, dst + mov ax, src + xchg [esi], ax + } + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(16, dst, src, order); + } + #endif + } + } + static MA_INLINE void __stdcall ma_atomic_store_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm { + mov esi, dst + mov eax, src + mov [esi], eax + } + } else { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + __asm { + mov esi, dst + mov eax, src + xchg [esi], eax + } + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(32, dst, src, order); + } + #endif + } + } + static MA_INLINE void __stdcall ma_atomic_store_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + MA_ATOMIC_STORE_EXPLICIT_CAS(64, dst, src, order); + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + ma_uint8 result = 0; (void)order; __asm { - lock add [esp], 0 + mov ecx, dst + mov al, src + lock xchg [ecx], al + mov result, al } + return result; } - #else - #if defined(MA_X64) - #define ma_atomic_thread_fence(order) __faststorefence(), (void)order - #elif defined(MA_ARM64) - #define ma_atomic_thread_fence(order) __dmb(_ARM64_BARRIER_ISH), (void)order #else - static MA_INLINE void ma_atomic_thread_fence(ma_atomic_memory_order order) - { - volatile ma_uint32 barrier = 0; - ma_atomic_fetch_add_explicit_32(&barrier, 0, order); + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + ma_uint16 result = 0; + (void)order; + __asm { + mov ecx, dst + mov ax, src + lock xchg [ecx], ax + mov result, ax } - #endif - #endif - #define ma_atomic_compiler_fence() ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst) - #define ma_atomic_signal_fence(order) ma_atomic_thread_fence(order) - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order) - { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange8, ma_uint8, char); + return result; + } #else - (void)order; - return ma_atomic_compare_and_swap_8((volatile ma_uint8*)ptr, 0, 0); - #endif - } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange16, ma_uint16, short); + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + ma_uint32 result = 0; + (void)order; + __asm { + mov ecx, dst + mov eax, src + xchg [ecx], eax + mov result, eax + } + return result; + } #else - (void)order; - return ma_atomic_compare_and_swap_16((volatile ma_uint16*)ptr, 0, 0); - #endif - } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange, ma_uint32, long); + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order); + } #else - (void)order; - return ma_atomic_compare_and_swap_32((volatile ma_uint32*)ptr, 0, 0); - #endif - } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange64, ma_uint64, long long); + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + ma_uint8 result = 0; + (void)order; + __asm { + mov ecx, dst + mov al, src + lock xadd [ecx], al + mov result, al + } + return result; + } #else - (void)order; - return ma_atomic_compare_and_swap_64((volatile ma_uint64*)ptr, 0, 0); + { + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order); + } #endif - } - #endif - #if defined(MA_ATOMIC_HAS_8) - #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order) - #endif - #if defined(MA_ATOMIC_HAS_16) - #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order) - #endif - #if defined(MA_ATOMIC_HAS_32) - #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order) - #endif - #if defined(MA_ATOMIC_HAS_64) - #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order) - #endif - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) { - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue - src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); + ma_uint16 result = 0; (void)order; - return oldValue; + __asm { + mov ecx, dst + mov ax, src + lock xadd [ecx], ax + mov result, ax + } + return result; } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue - src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue - src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue - src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - #endif - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd8, ma_uint8, char); #else - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue & src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif - } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd16, ma_uint16, short); - #else - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue & src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order); } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd, ma_uint32, long); - #else - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue & src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); + ma_uint32 result = 0; (void)order; - return oldValue; - #endif + __asm { + mov ecx, dst + mov eax, src + lock xadd [ecx], eax + mov result, eax + } + return result; } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + #else { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd64, ma_uint64, long long); - #else - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue & src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order); } - #endif - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor8, ma_uint8, char); - #else - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue ^ src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order); } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + #else { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor16, ma_uint16, short); - #else - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue ^ src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order); } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + #endif + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor, ma_uint32, long); - #else - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue ^ src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); + ma_uint8 result = 0; (void)order; - return oldValue; - #endif + __asm { + mov ecx, dst + mov al, src + neg al + lock xadd [ecx], al + mov result, al + } + return result; } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + #else { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor64, ma_uint64, long long); - #else - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue ^ src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, (ma_uint8)(-(ma_int8)src), order); } - #endif - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + #endif + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr8, ma_uint8, char); - #else - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue | src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); + ma_uint16 result = 0; (void)order; - return oldValue; - #endif + __asm { + mov ecx, dst + mov ax, src + neg ax + lock xadd [ecx], ax + mov result, ax + } + return result; } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + #else { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr16, ma_uint16, short); - #else - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue | src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, (ma_uint16)(-(ma_int16)src), order); } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + #endif + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr, ma_uint32, long); - #else - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue | src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); + ma_uint32 result = 0; (void)order; - return oldValue; - #endif + __asm { + mov ecx, dst + mov eax, src + neg eax + lock xadd [ecx], eax + mov result, eax + } + return result; } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + #else { - #if defined(MA_ARM) - MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr64, ma_uint64, long long); - #else - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue | src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - #endif + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, (ma_uint32)(-(ma_int32)src), order); } - #endif - #if defined(MA_ATOMIC_HAS_8) - #define ma_atomic_test_and_set_explicit_8( dst, order) ma_atomic_exchange_explicit_8 (dst, 1, order) - #endif - #if defined(MA_ATOMIC_HAS_16) - #define ma_atomic_test_and_set_explicit_16(dst, order) ma_atomic_exchange_explicit_16(dst, 1, order) - #endif - #if defined(MA_ATOMIC_HAS_32) - #define ma_atomic_test_and_set_explicit_32(dst, order) ma_atomic_exchange_explicit_32(dst, 1, order) - #endif - #if defined(MA_ATOMIC_HAS_64) - #define ma_atomic_test_and_set_explicit_64(dst, order) ma_atomic_exchange_explicit_64(dst, 1, order) - #endif - #if defined(MA_ATOMIC_HAS_8) - #define ma_atomic_clear_explicit_8( dst, order) ma_atomic_store_explicit_8 (dst, 0, order) - #endif - #if defined(MA_ATOMIC_HAS_16) - #define ma_atomic_clear_explicit_16(dst, order) ma_atomic_store_explicit_16(dst, 0, order) - #endif - #if defined(MA_ATOMIC_HAS_32) - #define ma_atomic_clear_explicit_32(dst, order) ma_atomic_store_explicit_32(dst, 0, order) - #endif - #if defined(MA_ATOMIC_HAS_64) - #define ma_atomic_clear_explicit_64(dst, order) ma_atomic_store_explicit_64(dst, 0, order) - #endif - #if defined(MA_ATOMIC_HAS_8) - typedef ma_uint8 ma_atomic_flag; - #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_8(ptr, order) - #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_8(ptr, order) - #define c89atoimc_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order) - #else - typedef ma_uint32 ma_atomic_flag; - #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_32(ptr, order) - #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_32(ptr, order) - #define c89atoimc_flag_load_explicit(ptr, order) ma_atomic_load_explicit_32(ptr, order) - #endif -#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) + #endif + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_ADD_CAS(64, dst, (ma_uint64)(-(ma_int64)src), order); + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order); + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order); + } + static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order); + } + static MA_INLINE void __stdcall ma_atomic_thread_fence(ma_atomic_memory_order order) + { + (void)order; + __asm { + lock add dword ptr [esp], 0 + } + } + #define ma_atomic_signal_fence(order) __asm {}; (void)order +#endif +#if defined(MA_ATOMIC_MODERN_GCC) #define MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE - #define MA_ATOMIC_HAS_NATIVE_IS_LOCK_FREE - #define ma_atomic_memory_order_relaxed __ATOMIC_RELAXED - #define ma_atomic_memory_order_consume __ATOMIC_CONSUME - #define ma_atomic_memory_order_acquire __ATOMIC_ACQUIRE - #define ma_atomic_memory_order_release __ATOMIC_RELEASE - #define ma_atomic_memory_order_acq_rel __ATOMIC_ACQ_REL - #define ma_atomic_memory_order_seq_cst __ATOMIC_SEQ_CST - #define ma_atomic_compiler_fence() __asm__ __volatile__("":::"memory") #define ma_atomic_thread_fence(order) __atomic_thread_fence(order) #define ma_atomic_signal_fence(order) __atomic_signal_fence(order) #define ma_atomic_is_lock_free_8(ptr) __atomic_is_lock_free(1, ptr) #define ma_atomic_is_lock_free_16(ptr) __atomic_is_lock_free(2, ptr) #define ma_atomic_is_lock_free_32(ptr) __atomic_is_lock_free(4, ptr) #define ma_atomic_is_lock_free_64(ptr) __atomic_is_lock_free(8, ptr) - #define ma_atomic_test_and_set_explicit_8( dst, order) __atomic_exchange_n(dst, 1, order) - #define ma_atomic_test_and_set_explicit_16(dst, order) __atomic_exchange_n(dst, 1, order) - #define ma_atomic_test_and_set_explicit_32(dst, order) __atomic_exchange_n(dst, 1, order) - #define ma_atomic_test_and_set_explicit_64(dst, order) __atomic_exchange_n(dst, 1, order) - #define ma_atomic_clear_explicit_8( dst, order) __atomic_store_n(dst, 0, order) - #define ma_atomic_clear_explicit_16(dst, order) __atomic_store_n(dst, 0, order) - #define ma_atomic_clear_explicit_32(dst, order) __atomic_store_n(dst, 0, order) - #define ma_atomic_clear_explicit_64(dst, order) __atomic_store_n(dst, 0, order) #define ma_atomic_store_explicit_8( dst, src, order) __atomic_store_n(dst, src, order) #define ma_atomic_store_explicit_16(dst, src, order) __atomic_store_n(dst, src, order) #define ma_atomic_store_explicit_32(dst, src, order) __atomic_store_n(dst, src, order) @@ -14793,14 +15810,14 @@ typedef int ma_atomic_memory_order; #define ma_atomic_exchange_explicit_16(dst, src, order) __atomic_exchange_n(dst, src, order) #define ma_atomic_exchange_explicit_32(dst, src, order) __atomic_exchange_n(dst, src, order) #define ma_atomic_exchange_explicit_64(dst, src, order) __atomic_exchange_n(dst, src, order) - #define ma_atomic_compare_exchange_strong_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder) - #define ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder) - #define ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder) - #define ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder) + #define ma_atomic_compare_exchange_strong_explicit_8( dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder) + #define ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder) + #define ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder) + #define ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder) #define ma_atomic_fetch_add_explicit_8( dst, src, order) __atomic_fetch_add(dst, src, order) #define ma_atomic_fetch_add_explicit_16(dst, src, order) __atomic_fetch_add(dst, src, order) #define ma_atomic_fetch_add_explicit_32(dst, src, order) __atomic_fetch_add(dst, src, order) @@ -14821,648 +15838,1155 @@ typedef int ma_atomic_memory_order; #define ma_atomic_fetch_and_explicit_16(dst, src, order) __atomic_fetch_and(dst, src, order) #define ma_atomic_fetch_and_explicit_32(dst, src, order) __atomic_fetch_and(dst, src, order) #define ma_atomic_fetch_and_explicit_64(dst, src, order) __atomic_fetch_and(dst, src, order) - static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired) + static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) { - __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return expected; } - static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired) + static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) { - __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return expected; } - static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired) + static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) { - __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return expected; } - static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired) - { - __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); - return expected; - } - typedef ma_uint8 ma_atomic_flag; - #define ma_atomic_flag_test_and_set_explicit(dst, order) (ma_bool32)__atomic_test_and_set(dst, order) - #define ma_atomic_flag_clear_explicit(dst, order) __atomic_clear(dst, order) - #define c89atoimc_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order) -#else - #define ma_atomic_memory_order_relaxed 1 - #define ma_atomic_memory_order_consume 2 - #define ma_atomic_memory_order_acquire 3 - #define ma_atomic_memory_order_release 4 - #define ma_atomic_memory_order_acq_rel 5 - #define ma_atomic_memory_order_seq_cst 6 - #define ma_atomic_compiler_fence() __asm__ __volatile__("":::"memory") - #if defined(__GNUC__) - #define ma_atomic_thread_fence(order) __sync_synchronize(), (void)order - static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - if (order > ma_atomic_memory_order_acquire) { - __sync_synchronize(); - } - return __sync_lock_test_and_set(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - do { - oldValue = *dst; - } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - do { - oldValue = *dst; - } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - do { - oldValue = *dst; - } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_add(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_add(dst, src); - } - static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_add(dst, src); - } - static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_add(dst, src); - } - static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_sub(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_sub(dst, src); - } - static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_sub(dst, src); - } - static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_sub(dst, src); - } - static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_or(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_or(dst, src); - } - static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_or(dst, src); - } - static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_or(dst, src); - } - static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_xor(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_xor(dst, src); - } - static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_xor(dst, src); - } - static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_xor(dst, src); - } - static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_and(dst, src); - } - static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_and(dst, src); - } - static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_and(dst, src); - } - static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - (void)order; - return __sync_fetch_and_and(dst, src); - } - #define ma_atomic_compare_and_swap_8( dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired) - #define ma_atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired) - #define ma_atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired) - #define ma_atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired) - #else - #if defined(MA_X86) - #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory", "cc") - #elif defined(MA_X64) - #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory", "cc") - #else - #error Unsupported architecture. Please submit a feature request. + #if defined(__clang__) + #pragma clang diagnostic push + #if __clang_major__ >= 8 + #pragma clang diagnostic ignored "-Watomic-alignment" #endif - static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired) - { - ma_uint8 result; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired) - { - ma_uint16 result; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired) - { - ma_uint32 result; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired) - { - volatile ma_uint64 result; - #if defined(MA_X86) - ma_uint32 resultEAX; - ma_uint32 resultEDX; - __asm__ __volatile__("push %%ebx; xchg %5, %%ebx; lock; cmpxchg8b %0; pop %%ebx" : "+m"(*dst), "=a"(resultEAX), "=d"(resultEDX) : "a"(expected & 0xFFFFFFFF), "d"(expected >> 32), "r"(desired & 0xFFFFFFFF), "c"(desired >> 32) : "cc"); - result = ((ma_uint64)resultEDX << 32) | resultEAX; - #elif defined(MA_X64) - __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 result = 0; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src)); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 result = 0; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src)); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 result; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src)); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 result; - (void)order; - #if defined(MA_X86) - do { - result = *dst; - } while (ma_atomic_compare_and_swap_64(dst, result, src) != result); - #elif defined(MA_X64) - __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src)); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 result; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 result; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 result; - (void)order; - #if defined(MA_X86) || defined(MA_X64) - __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc"); - #else - #error Unsupported architecture. Please submit a feature request. - #endif - return result; - } - static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - #if defined(MA_X86) - ma_uint64 oldValue; - ma_uint64 newValue; - (void)order; - do { - oldValue = *dst; - newValue = oldValue + src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - return oldValue; - #elif defined(MA_X64) - ma_uint64 result; - (void)order; - __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc"); - return result; - #endif - } - static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue - src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue - src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue - src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue - src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue & src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue & src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue & src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue & src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue ^ src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue ^ src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue ^ src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue ^ src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) - { - ma_uint8 oldValue; - ma_uint8 newValue; - do { - oldValue = *dst; - newValue = (ma_uint8)(oldValue | src); - } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) - { - ma_uint16 oldValue; - ma_uint16 newValue; - do { - oldValue = *dst; - newValue = (ma_uint16)(oldValue | src); - } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) - { - ma_uint32 oldValue; - ma_uint32 newValue; - do { - oldValue = *dst; - newValue = oldValue | src; - } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } - static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) - { - ma_uint64 oldValue; - ma_uint64 newValue; - do { - oldValue = *dst; - newValue = oldValue | src; - } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue); - (void)order; - return oldValue; - } #endif - #define ma_atomic_signal_fence(order) ma_atomic_thread_fence(order) - static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order) + static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) { - (void)order; - return ma_atomic_compare_and_swap_8((ma_uint8*)ptr, 0, 0); + __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return expected; } - static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order) - { - (void)order; - return ma_atomic_compare_and_swap_16((ma_uint16*)ptr, 0, 0); - } - static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order) - { - (void)order; - return ma_atomic_compare_and_swap_32((ma_uint32*)ptr, 0, 0); - } - static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order) - { - (void)order; - return ma_atomic_compare_and_swap_64((ma_uint64*)ptr, 0, 0); - } - #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order) - #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order) - #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order) - #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order) - #define ma_atomic_test_and_set_explicit_8( dst, order) ma_atomic_exchange_explicit_8 (dst, 1, order) - #define ma_atomic_test_and_set_explicit_16(dst, order) ma_atomic_exchange_explicit_16(dst, 1, order) - #define ma_atomic_test_and_set_explicit_32(dst, order) ma_atomic_exchange_explicit_32(dst, 1, order) - #define ma_atomic_test_and_set_explicit_64(dst, order) ma_atomic_exchange_explicit_64(dst, 1, order) - #define ma_atomic_clear_explicit_8( dst, order) ma_atomic_store_explicit_8 (dst, 0, order) - #define ma_atomic_clear_explicit_16(dst, order) ma_atomic_store_explicit_16(dst, 0, order) - #define ma_atomic_clear_explicit_32(dst, order) ma_atomic_store_explicit_32(dst, 0, order) - #define ma_atomic_clear_explicit_64(dst, order) ma_atomic_store_explicit_64(dst, 0, order) - typedef ma_uint8 ma_atomic_flag; - #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_8(ptr, order) - #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_8(ptr, order) - #define c89atoimc_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order) + #if defined(__clang__) + #pragma clang diagnostic pop + #endif +#endif +#if defined(MA_ATOMIC_LEGACY_GCC) || defined(MA_ATOMIC_LEGACY_GCC_ASM) + #define ma_atomic_signal_fence(order) __asm__ __volatile__("":::"memory") + #if defined(MA_ATOMIC_LEGACY_GCC) + #define ma_atomic_thread_fence(order) __sync_synchronize(), (void)order + static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + return __sync_val_compare_and_swap(dst, expected, replacement); + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + return __sync_val_compare_and_swap(dst, expected, replacement); + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + return __sync_val_compare_and_swap(dst, expected, replacement); + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + return __sync_val_compare_and_swap(dst, expected, replacement); + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return ma_atomic_compare_and_swap_8((ma_uint8*)ptr, 0, 0); + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, ptr, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return ma_atomic_compare_and_swap_16((ma_uint16*)ptr, 0, 0); + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, ptr, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return ma_atomic_compare_and_swap_32((ma_uint32*)ptr, 0, 0); + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, ptr, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return ma_atomic_compare_and_swap_64((ma_uint64*)ptr, 0, 0); + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, ptr, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + if (order > ma_atomic_memory_order_acquire) { + __sync_synchronize(); + } + return __sync_lock_test_and_set(dst, src); + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + if (order > ma_atomic_memory_order_acquire) { + __sync_synchronize(); + } + return __sync_lock_test_and_set(dst, src); + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + if (order > ma_atomic_memory_order_acquire) { + __sync_synchronize(); + } + return __sync_lock_test_and_set(dst, src); + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + if (order > ma_atomic_memory_order_acquire) { + __sync_synchronize(); + } + return __sync_lock_test_and_set(dst, src); + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order) + #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order) + #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order) + #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order) + static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return __sync_fetch_and_add(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return __sync_fetch_and_add(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return __sync_fetch_and_add(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return __sync_fetch_and_add(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return __sync_fetch_and_sub(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, (ma_uint8)(-(ma_int8)src), order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return __sync_fetch_and_sub(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, (ma_uint16)(-(ma_int16)src), order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return __sync_fetch_and_sub(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, (ma_uint32)(-(ma_int32)src), order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return __sync_fetch_and_sub(dst, src); + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(64, dst, (ma_uint64)(-(ma_int64)src), order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return __sync_fetch_and_and(dst, src); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return __sync_fetch_and_and(dst, src); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return __sync_fetch_and_and(dst, src); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return __sync_fetch_and_and(dst, src); + } + #else + { + MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return __sync_fetch_and_or(dst, src); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return __sync_fetch_and_or(dst, src); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return __sync_fetch_and_or(dst, src); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return __sync_fetch_and_or(dst, src); + } + #else + { + MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) + { + (void)order; + return __sync_fetch_and_xor(dst, src); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) + { + (void)order; + return __sync_fetch_and_xor(dst, src); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) + { + (void)order; + return __sync_fetch_and_xor(dst, src); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) + { + (void)order; + return __sync_fetch_and_xor(dst, src); + } + #else + { + MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order); + } + #endif + } + #elif defined(MA_ATOMIC_LEGACY_GCC_ASM) + #define MA_ATOMIC_CMPXCHG_GCC_X86(instructionSizeSuffix, result, dst, expected, replacement) \ + __asm__ __volatile__( \ + "lock; cmpxchg"instructionSizeSuffix" %2, %1" \ + : "=a"(result), \ + "=m"(*dst) \ + : "r"(replacement), \ + "0"(expected), \ + "m"(*dst) \ + : "cc", "memory") + #define MA_ATOMIC_XADD_GCC_X86(instructionSizeSuffix, result, dst, src) \ + __asm__ __volatile__( \ + "lock; xadd"instructionSizeSuffix" %0, %1" \ + : "=a"(result), \ + "=m"(*dst) \ + : "0"(src), \ + "m"(*dst) \ + : "cc", "memory") + static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint8 result; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_CMPXCHG_GCC_X86("b", result, dst, expected, replacement); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint16 result; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_CMPXCHG_GCC_X86("w", result, dst, expected, replacement); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint32 result; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_CMPXCHG_GCC_X86("l", result, dst, expected, replacement); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint64 result; + #if defined(MA_X86) + { + ma_uint32 resultEAX; + ma_uint32 resultEDX; + __asm__ __volatile__( + "pushl %%ebx\n" + "movl %4, %%ebx\n" + "lock cmpxchg8b (%%edi)\n" + "popl %%ebx\n" + : "=a"(resultEAX), + "=d"(resultEDX) + : "a"((ma_uint32)(expected & 0xFFFFFFFF)), + "d"((ma_uint32)(expected >> 32)), + "r"((ma_uint32)(replacement & 0xFFFFFFFF)), + "c"((ma_uint32)(replacement >> 32)), + "D"(dst) + : "memory", "cc"); + result = ((ma_uint64)resultEDX << 32) | resultEAX; + } + #elif defined(MA_X64) + { + MA_ATOMIC_CMPXCHG_GCC_X86("q", result, dst, expected, replacement); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint8 result; + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + MA_ATOMIC_LOAD_RELAXED_GCC_X86("b", result, dst); + } else if (order <= ma_atomic_memory_order_release) { + MA_ATOMIC_LOAD_RELEASE_GCC_X86("b", result, dst); + } else { + MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("b", result, dst); + } + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, dst, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint16 result; + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + MA_ATOMIC_LOAD_RELAXED_GCC_X86("w", result, dst); + } else if (order <= ma_atomic_memory_order_release) { + MA_ATOMIC_LOAD_RELEASE_GCC_X86("w", result, dst); + } else { + MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("w", result, dst); + } + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, dst, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint32 result; + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + MA_ATOMIC_LOAD_RELAXED_GCC_X86("l", result, dst); + } else if (order <= ma_atomic_memory_order_release) { + MA_ATOMIC_LOAD_RELEASE_GCC_X86("l", result, dst); + } else { + MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("l", result, dst); + } + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, dst, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* dst, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint64 result; + #if defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + MA_ATOMIC_LOAD_RELAXED_GCC_X86("q", result, dst); + } else if (order <= ma_atomic_memory_order_release) { + MA_ATOMIC_LOAD_RELEASE_GCC_X86("q", result, dst); + } else { + MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("q", result, dst); + } + } + #elif defined(MA_X86) + { + (void)order; + return ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, 0, 0); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, dst, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint8 result; + (void)order; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_XCHG_GCC_X86("b", result, dst, src); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint16 result; + (void)order; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_XCHG_GCC_X86("w", result, dst, src); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint32 result; + (void)order; + #if defined(MA_X86) || defined(MA_X64) + { + MA_ATOMIC_XCHG_GCC_X86("l", result, dst, src); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64)) + { + ma_uint64 result; + (void)order; + #if defined(MA_X86) + { + MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order); + } + #elif defined(MA_X64) + { + MA_ATOMIC_XCHG_GCC_X86("q", result, dst, src); + } + #else + { + #error Unsupported architecture. + } + #endif + return result; + } + #else + { + MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE void ma_atomic_store_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm__ __volatile__ ( + "movb %1, %0" + : "=m"(*dst) + : "r"(src) + ); + } else { + __asm__ __volatile__ ( + "xchgb %1, %0" + : "=m"(*dst) + : "r"(src) + : "memory" + ); + } + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE void ma_atomic_store_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm__ __volatile__ ( + "movw %1, %0" + : "=m"(*dst) + : "r"(src) + ); + } else { + __asm__ __volatile__ ( + "xchgw %1, %0" + : "=m"(*dst) + : "r"(src) + : "memory" + ); + } + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE void ma_atomic_store_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm__ __volatile__ ( + "movl %1, %0" + : "=m"(*dst) + : "r"(src) + ); + } else { + __asm__ __volatile__ ( + "xchgl %1, %0" + : "=m"(*dst) + : "r"(src) + : "memory" + ); + } + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE void ma_atomic_store_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X64) + { + if (order == ma_atomic_memory_order_relaxed) { + __asm__ __volatile__ ( + "movq %1, %0" + : "=m"(*dst) + : "r"(src) + ); + } else { + __asm__ __volatile__ ( + "xchgq %1, %0" + : "=m"(*dst) + : "r"(src) + : "memory" + ); + } + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_CAS(64, dst, src, order); + } + #endif + } + #else + { + MA_ATOMIC_STORE_EXPLICIT_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + ma_uint8 result; + (void)order; + MA_ATOMIC_XADD_GCC_X86("b", result, dst, src); + return result; + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + ma_uint16 result; + (void)order; + MA_ATOMIC_XADD_GCC_X86("w", result, dst, src); + return result; + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) || defined(MA_X64) + { + ma_uint32 result; + (void)order; + MA_ATOMIC_XADD_GCC_X86("l", result, dst, src); + return result; + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64)) + { + #if defined(MA_X86) + { + MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order); + } + #elif defined(MA_X64) + { + ma_uint64 result; + MA_ATOMIC_XADD_GCC_X86("q", result, dst, src); + (void)order; + return result; + } + #else + { + #error Unsupported architecture. + } + #endif + } + #else + { + MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order); + } + #endif + } + static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_8(dst, (ma_uint8)(-(ma_int8)src), order); + } + static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_16(dst, (ma_uint16)(-(ma_int16)src), order); + } + static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_32(dst, (ma_uint32)(-(ma_int32)src), order); + } + static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + return ma_atomic_fetch_add_explicit_64(dst, (ma_uint64)(-(ma_int64)src), order); + } + static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order); + } + static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order); + } + static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order); + } + static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order); + } + static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order); + } + static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order) + { + MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order); + } + #else + #error Unsupported compiler. + #endif #endif #if !defined(MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE) - #if defined(MA_ATOMIC_HAS_8) - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) - { - ma_uint8 expectedValue; - ma_uint8 result; - (void)successOrder; - (void)failureOrder; - expectedValue = ma_atomic_load_explicit_8(expected, ma_atomic_memory_order_seq_cst); - result = ma_atomic_compare_and_swap_8(dst, expectedValue, desired); - if (result == expectedValue) { - return 1; - } else { - ma_atomic_store_explicit_8(expected, result, failureOrder); - return 0; - } - } - #endif - #if defined(MA_ATOMIC_HAS_16) - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_16(volatile ma_uint16* dst, ma_uint16* expected, ma_uint16 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) - { - ma_uint16 expectedValue; - ma_uint16 result; - (void)successOrder; - (void)failureOrder; - expectedValue = ma_atomic_load_explicit_16(expected, ma_atomic_memory_order_seq_cst); - result = ma_atomic_compare_and_swap_16(dst, expectedValue, desired); - if (result == expectedValue) { - return 1; - } else { - ma_atomic_store_explicit_16(expected, result, failureOrder); - return 0; - } - } - #endif - #if defined(MA_ATOMIC_HAS_32) - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_32(volatile ma_uint32* dst, ma_uint32* expected, ma_uint32 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) - { - ma_uint32 expectedValue; - ma_uint32 result; - (void)successOrder; - (void)failureOrder; - expectedValue = ma_atomic_load_explicit_32(expected, ma_atomic_memory_order_seq_cst); - result = ma_atomic_compare_and_swap_32(dst, expectedValue, desired); - if (result == expectedValue) { - return 1; - } else { - ma_atomic_store_explicit_32(expected, result, failureOrder); - return 0; - } - } - #endif - #if defined(MA_ATOMIC_HAS_64) - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_64(volatile ma_uint64* dst, volatile ma_uint64* expected, ma_uint64 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) - { - ma_uint64 expectedValue; - ma_uint64 result; - (void)successOrder; - (void)failureOrder; - expectedValue = ma_atomic_load_explicit_64(expected, ma_atomic_memory_order_seq_cst); - result = ma_atomic_compare_and_swap_64(dst, expectedValue, desired); - if (result == expectedValue) { - return 1; - } else { - ma_atomic_store_explicit_64(expected, result, failureOrder); - return 0; - } - } - #endif - #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8 (dst, expected, desired, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder) - #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder) -#endif -#if !defined(MA_ATOMIC_HAS_NATIVE_IS_LOCK_FREE) - static MA_INLINE ma_bool32 ma_atomic_is_lock_free_8(volatile void* ptr) + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { - (void)ptr; - return 1; - } - static MA_INLINE ma_bool32 ma_atomic_is_lock_free_16(volatile void* ptr) - { - (void)ptr; - return 1; - } - static MA_INLINE ma_bool32 ma_atomic_is_lock_free_32(volatile void* ptr) - { - (void)ptr; - return 1; - } - static MA_INLINE ma_bool32 ma_atomic_is_lock_free_64(volatile void* ptr) - { - (void)ptr; - #if defined(MA_64BIT) - return 1; - #else - #if defined(MA_X86) || defined(MA_X64) + ma_uint8 result; + (void)successOrder; + (void)failureOrder; + result = ma_atomic_compare_and_swap_8(dst, *expected, replacement); + if (result == *expected) { return 1; - #else + } else { + *expected = result; return 0; - #endif - #endif + } } + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_16(volatile ma_uint16* dst, ma_uint16* expected, ma_uint16 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + { + ma_uint16 result; + (void)successOrder; + (void)failureOrder; + result = ma_atomic_compare_and_swap_16(dst, *expected, replacement); + if (result == *expected) { + return 1; + } else { + *expected = result; + return 0; + } + } + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_32(volatile ma_uint32* dst, ma_uint32* expected, ma_uint32 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + { + ma_uint32 result; + (void)successOrder; + (void)failureOrder; + result = ma_atomic_compare_and_swap_32(dst, *expected, replacement); + if (result == *expected) { + return 1; + } else { + *expected = result; + return 0; + } + } + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_64(volatile ma_uint64* dst, volatile ma_uint64* expected, ma_uint64 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + { + ma_uint64 result; + (void)successOrder; + (void)failureOrder; + result = ma_atomic_compare_and_swap_64(dst, *expected, replacement); + if (result == *expected) { + return 1; + } else { + *expected = result; + return 0; + } + } + #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8 (dst, expected, replacement, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, successOrder, failureOrder) + #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, successOrder, failureOrder) #endif #if defined(MA_64BIT) static MA_INLINE ma_bool32 ma_atomic_is_lock_free_ptr(volatile void** ptr) @@ -15481,17 +17005,17 @@ typedef int ma_atomic_memory_order; { return (void*)ma_atomic_exchange_explicit_64((volatile ma_uint64*)dst, (ma_uint64)src, order); } - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { - return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder); + return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder); } - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { - return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder); + return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder); } - static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired) + static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* replacement) { - return (void*)ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, (ma_uint64)expected, (ma_uint64)desired); + return (void*)ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, (ma_uint64)expected, (ma_uint64)replacement); } #elif defined(MA_32BIT) static MA_INLINE ma_bool32 ma_atomic_is_lock_free_ptr(volatile void** ptr) @@ -15510,36 +17034,26 @@ typedef int ma_atomic_memory_order; { return (void*)ma_atomic_exchange_explicit_32((volatile ma_uint32*)dst, (ma_uint32)src, order); } - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { - return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder); + return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder); } - static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) + static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { - return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder); + return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder); } - static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired) + static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* replacement) { - return (void*)ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, (ma_uint32)expected, (ma_uint32)desired); + return (void*)ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, (ma_uint32)expected, (ma_uint32)replacement); } #else #error Unsupported architecture. #endif -#define ma_atomic_flag_test_and_set(ptr) ma_atomic_flag_test_and_set_explicit(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_flag_clear(ptr) ma_atomic_flag_clear_explicit(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_store_ptr(dst, src) ma_atomic_store_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_load_ptr(ptr) ma_atomic_load_explicit_ptr((volatile void**)ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_exchange_ptr(dst, src) ma_atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_ptr(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_ptr((volatile void**)dst, (void**)expected, (void*)desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_ptr(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_ptr((volatile void**)dst, (void**)expected, (void*)desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_8( ptr) ma_atomic_test_and_set_explicit_8( ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_16(ptr) ma_atomic_test_and_set_explicit_16(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_32(ptr) ma_atomic_test_and_set_explicit_32(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_64(ptr) ma_atomic_test_and_set_explicit_64(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_8( ptr) ma_atomic_clear_explicit_8( ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_16(ptr) ma_atomic_clear_explicit_16(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_32(ptr) ma_atomic_clear_explicit_32(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_64(ptr) ma_atomic_clear_explicit_64(ptr, ma_atomic_memory_order_seq_cst) +#define ma_atomic_store_ptr(dst, src) ma_atomic_store_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst) +#define ma_atomic_load_ptr(ptr) ma_atomic_load_explicit_ptr((volatile void**)ptr, ma_atomic_memory_order_seq_cst) +#define ma_atomic_exchange_ptr(dst, src) ma_atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_ptr(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_ptr((volatile void**)dst, (void**)expected, (void*)replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_ptr(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_ptr((volatile void**)dst, (void**)expected, (void*)replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_8( dst, src) ma_atomic_store_explicit_8( dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_16(dst, src) ma_atomic_store_explicit_16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_32(dst, src) ma_atomic_store_explicit_32(dst, src, ma_atomic_memory_order_seq_cst) @@ -15552,14 +17066,14 @@ typedef int ma_atomic_memory_order; #define ma_atomic_exchange_16(dst, src) ma_atomic_exchange_explicit_16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_32(dst, src) ma_atomic_exchange_explicit_32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_64(dst, src) ma_atomic_exchange_explicit_64(dst, src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_8( dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_16(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_8( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_16( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_32( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_64( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_8( dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_16(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_8( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_16( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_32( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_64( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_8( dst, src) ma_atomic_fetch_add_explicit_8( dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_16(dst, src) ma_atomic_fetch_add_explicit_16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_32(dst, src) ma_atomic_fetch_add_explicit_32(dst, src, ma_atomic_memory_order_seq_cst) @@ -15580,14 +17094,6 @@ typedef int ma_atomic_memory_order; #define ma_atomic_fetch_and_16(dst, src) ma_atomic_fetch_and_explicit_16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_and_32(dst, src) ma_atomic_fetch_and_explicit_32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_and_64(dst, src) ma_atomic_fetch_and_explicit_64(dst, src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_explicit_i8( ptr, order) (ma_int8 )ma_atomic_test_and_set_explicit_8( (ma_uint8* )ptr, order) -#define ma_atomic_test_and_set_explicit_i16(ptr, order) (ma_int16)ma_atomic_test_and_set_explicit_16((ma_uint16*)ptr, order) -#define ma_atomic_test_and_set_explicit_i32(ptr, order) (ma_int32)ma_atomic_test_and_set_explicit_32((ma_uint32*)ptr, order) -#define ma_atomic_test_and_set_explicit_i64(ptr, order) (ma_int64)ma_atomic_test_and_set_explicit_64((ma_uint64*)ptr, order) -#define ma_atomic_clear_explicit_i8( ptr, order) ma_atomic_clear_explicit_8( (ma_uint8* )ptr, order) -#define ma_atomic_clear_explicit_i16(ptr, order) ma_atomic_clear_explicit_16((ma_uint16*)ptr, order) -#define ma_atomic_clear_explicit_i32(ptr, order) ma_atomic_clear_explicit_32((ma_uint32*)ptr, order) -#define ma_atomic_clear_explicit_i64(ptr, order) ma_atomic_clear_explicit_64((ma_uint64*)ptr, order) #define ma_atomic_store_explicit_i8( dst, src, order) ma_atomic_store_explicit_8( (ma_uint8* )dst, (ma_uint8 )src, order) #define ma_atomic_store_explicit_i16(dst, src, order) ma_atomic_store_explicit_16((ma_uint16*)dst, (ma_uint16)src, order) #define ma_atomic_store_explicit_i32(dst, src, order) ma_atomic_store_explicit_32((ma_uint32*)dst, (ma_uint32)src, order) @@ -15600,14 +17106,14 @@ typedef int ma_atomic_memory_order; #define ma_atomic_exchange_explicit_i16(dst, src, order) (ma_int16)ma_atomic_exchange_explicit_16((ma_uint16*)dst, (ma_uint16)src, order) #define ma_atomic_exchange_explicit_i32(dst, src, order) (ma_int32)ma_atomic_exchange_explicit_32((ma_uint32*)dst, (ma_uint32)src, order) #define ma_atomic_exchange_explicit_i64(dst, src, order) (ma_int64)ma_atomic_exchange_explicit_64((ma_uint64*)dst, (ma_uint64)src, order) -#define ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder) -#define ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder) +#define ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder) +#define ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder) #define ma_atomic_fetch_add_explicit_i8( dst, src, order) (ma_int8 )ma_atomic_fetch_add_explicit_8( (ma_uint8* )dst, (ma_uint8 )src, order) #define ma_atomic_fetch_add_explicit_i16(dst, src, order) (ma_int16)ma_atomic_fetch_add_explicit_16((ma_uint16*)dst, (ma_uint16)src, order) #define ma_atomic_fetch_add_explicit_i32(dst, src, order) (ma_int32)ma_atomic_fetch_add_explicit_32((ma_uint32*)dst, (ma_uint32)src, order) @@ -15628,14 +17134,6 @@ typedef int ma_atomic_memory_order; #define ma_atomic_fetch_and_explicit_i16(dst, src, order) (ma_int16)ma_atomic_fetch_and_explicit_16((ma_uint16*)dst, (ma_uint16)src, order) #define ma_atomic_fetch_and_explicit_i32(dst, src, order) (ma_int32)ma_atomic_fetch_and_explicit_32((ma_uint32*)dst, (ma_uint32)src, order) #define ma_atomic_fetch_and_explicit_i64(dst, src, order) (ma_int64)ma_atomic_fetch_and_explicit_64((ma_uint64*)dst, (ma_uint64)src, order) -#define ma_atomic_test_and_set_i8( ptr) ma_atomic_test_and_set_explicit_i8( ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_i16(ptr) ma_atomic_test_and_set_explicit_i16(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_i32(ptr) ma_atomic_test_and_set_explicit_i32(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_test_and_set_i64(ptr) ma_atomic_test_and_set_explicit_i64(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_i8( ptr) ma_atomic_clear_explicit_i8( ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_i16(ptr) ma_atomic_clear_explicit_i16(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_i32(ptr) ma_atomic_clear_explicit_i32(ptr, ma_atomic_memory_order_seq_cst) -#define ma_atomic_clear_i64(ptr) ma_atomic_clear_explicit_i64(ptr, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_i8( dst, src) ma_atomic_store_explicit_i8( dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_i16(dst, src) ma_atomic_store_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_store_i32(dst, src) ma_atomic_store_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst) @@ -15648,14 +17146,14 @@ typedef int ma_atomic_memory_order; #define ma_atomic_exchange_i16(dst, src) ma_atomic_exchange_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_i32(dst, src) ma_atomic_exchange_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_i64(dst, src) ma_atomic_exchange_explicit_i64(dst, src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_i8( dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_i16(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_i32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_i64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_i8( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_i16(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_i32(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_i64(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_i8( dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_i16(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_i32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_i64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_i8( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_i16(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_i32(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_i64(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_i8( dst, src) ma_atomic_fetch_add_explicit_i8( dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_i16(dst, src) ma_atomic_fetch_add_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_i32(dst, src) ma_atomic_fetch_add_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst) @@ -15732,28 +17230,28 @@ static MA_INLINE double ma_atomic_exchange_explicit_f64(volatile double* dst, do r.i = ma_atomic_exchange_explicit_64((volatile ma_uint64*)dst, x.i, order); return r.f; } -static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f32(volatile float* dst, float* expected, float desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) +static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f32(volatile float* dst, float* expected, float replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { ma_atomic_if32 d; - d.f = desired; + d.f = replacement; return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, d.i, successOrder, failureOrder); } -static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f64(volatile double* dst, double* expected, double desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) +static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f64(volatile double* dst, double* expected, double replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { ma_atomic_if64 d; - d.f = desired; + d.f = replacement; return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, d.i, successOrder, failureOrder); } -static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f32(volatile float* dst, float* expected, float desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) +static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f32(volatile float* dst, float* expected, float replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { ma_atomic_if32 d; - d.f = desired; + d.f = replacement; return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, d.i, successOrder, failureOrder); } -static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f64(volatile double* dst, double* expected, double desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) +static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f64(volatile double* dst, double* expected, double replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder) { ma_atomic_if64 d; - d.f = desired; + d.f = replacement; return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, d.i, successOrder, failureOrder); } static MA_INLINE float ma_atomic_fetch_add_explicit_f32(volatile float* dst, float src, ma_atomic_memory_order order) @@ -15844,10 +17342,10 @@ static MA_INLINE double ma_atomic_fetch_and_explicit_f64(volatile double* dst, d #define ma_atomic_load_f64(ptr) (double)ma_atomic_load_explicit_f64(ptr, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_f32(dst, src) (float )ma_atomic_exchange_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_exchange_f64(dst, src) (double)ma_atomic_exchange_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_f32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_f32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_strong_f64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_f64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_f32(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_f32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) -#define ma_atomic_compare_exchange_weak_f64(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_f64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_f32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_f32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_strong_f64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_f64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_f32(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_f32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) +#define ma_atomic_compare_exchange_weak_f64(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_f64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_f32(dst, src) ma_atomic_fetch_add_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_add_f64(dst, src) ma_atomic_fetch_add_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_sub_f32(dst, src) ma_atomic_fetch_sub_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst) @@ -15858,39 +17356,24 @@ static MA_INLINE double ma_atomic_fetch_and_explicit_f64(volatile double* dst, d #define ma_atomic_fetch_xor_f64(dst, src) ma_atomic_fetch_xor_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_and_f32(dst, src) ma_atomic_fetch_and_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst) #define ma_atomic_fetch_and_f64(dst, src) ma_atomic_fetch_and_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst) -static MA_INLINE float ma_atomic_compare_and_swap_f32(volatile float* dst, float expected, float desired) +static MA_INLINE float ma_atomic_compare_and_swap_f32(volatile float* dst, float expected, float replacement) { ma_atomic_if32 r; ma_atomic_if32 e, d; e.f = expected; - d.f = desired; + d.f = replacement; r.i = ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, e.i, d.i); return r.f; } -static MA_INLINE double ma_atomic_compare_and_swap_f64(volatile double* dst, double expected, double desired) +static MA_INLINE double ma_atomic_compare_and_swap_f64(volatile double* dst, double expected, double replacement) { ma_atomic_if64 r; ma_atomic_if64 e, d; e.f = expected; - d.f = desired; + d.f = replacement; r.i = ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, e.i, d.i); return r.f; } -typedef ma_atomic_flag ma_atomic_spinlock; -static MA_INLINE void ma_atomic_spinlock_lock(volatile ma_atomic_spinlock* pSpinlock) -{ - for (;;) { - if (ma_atomic_flag_test_and_set_explicit(pSpinlock, ma_atomic_memory_order_acquire) == 0) { - break; - } - while (c89atoimc_flag_load_explicit(pSpinlock, ma_atomic_memory_order_relaxed) == 1) { - } - } -} -static MA_INLINE void ma_atomic_spinlock_unlock(volatile ma_atomic_spinlock* pSpinlock) -{ - ma_atomic_flag_clear_explicit(pSpinlock, ma_atomic_memory_order_release); -} #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) #pragma GCC diagnostic pop #endif @@ -15898,7 +17381,7 @@ static MA_INLINE void ma_atomic_spinlock_unlock(volatile ma_atomic_spinlock* pSp } #endif #endif -/* ma_atomic.h end */ +/* c89atomic.h end */ #define MA_ATOMIC_SAFE_TYPE_IMPL(c89TypeExtension, type) \ static MA_INLINE ma_##type ma_atomic_##type##_get(ma_atomic_##type* x) \ @@ -16096,7 +17579,7 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority int result; pthread_attr_t* pAttr = NULL; -#if !defined(__EMSCRIPTEN__) +#if !defined(MA_EMSCRIPTEN) && !defined(MA_3DS) && !defined(MA_SWITCH) /* Try setting the thread priority. It's not critical if anything fails here. */ pthread_attr_t attr; if (pthread_attr_init(&attr) == 0) { @@ -16128,9 +17611,18 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority } #endif - if (stackSize > 0) { - pthread_attr_setstacksize(&attr, stackSize); + #if defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE >= 0 + { + if (stackSize > 0) { + pthread_attr_setstacksize(&attr, stackSize); + } } + #else + { + (void)stackSize; /* Suppress unused parameter warning. */ + } + #endif + if (scheduler != -1) { int priorityMin = sched_get_priority_min(scheduler); @@ -16138,23 +17630,38 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority int priorityStep = (priorityMax - priorityMin) / 7; /* 7 = number of priorities supported by miniaudio. */ struct sched_param sched; - if (pthread_attr_getschedparam(&attr, &sched) == 0) { + if (priorityMin != -1 && priorityMax != -1 && pthread_attr_getschedparam(&attr, &sched) == 0) { if (priority == ma_thread_priority_idle) { sched.sched_priority = priorityMin; } else if (priority == ma_thread_priority_realtime) { - sched.sched_priority = priorityMax; - } else { - sched.sched_priority += ((int)priority + 5) * priorityStep; /* +5 because the lowest priority is -5. */ - if (sched.sched_priority < priorityMin) { - sched.sched_priority = priorityMin; + #if defined(MA_PTHREAD_REALTIME_THREAD_PRIORITY) + { + sched.sched_priority = MA_PTHREAD_REALTIME_THREAD_PRIORITY; } - if (sched.sched_priority > priorityMax) { + #else + { sched.sched_priority = priorityMax; } + #endif + } else { + sched.sched_priority += ((int)priority + 5) * priorityStep; /* +5 because the lowest priority is -5. */ } - /* I'm not treating a failure of setting the priority as a critical error so not checking the return value here. */ - pthread_attr_setschedparam(&attr, &sched); + if (sched.sched_priority < priorityMin) { + sched.sched_priority = priorityMin; + } + if (sched.sched_priority > priorityMax) { + sched.sched_priority = priorityMax; + } + + /* I'm not treating a failure of setting the priority as a critical error so not aborting on failure here. */ + if (pthread_attr_setschedparam(&attr, &sched) == 0) { + #if !defined(MA_ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) + { + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + } + #endif + } } } } @@ -16172,6 +17679,21 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority } if (result != 0) { + /* + There have been reports that attempting to create a realtime thread can sometimes fail. In this case, + fall back to a normal priority thread. + + I'm including a compile-time option here to disable this functionality for those who have a hard + requirement on realtime threads and would rather an explicit failure. + */ + #ifndef MA_NO_PTHREAD_REALTIME_PRIORITY_FALLBACK + { + if(result == EPERM && priority == ma_thread_priority_realtime) { + return ma_thread_create__posix(pThread, ma_thread_priority_normal, stackSize, entryProc, pData); + } + } + #endif + return ma_result_from_errno(result); } @@ -16187,7 +17709,7 @@ static void ma_thread_wait__posix(ma_thread* pThread) static ma_result ma_mutex_init__posix(ma_mutex* pMutex) { int result; - + if (pMutex == NULL) { return MA_INVALID_ARGS; } @@ -16443,7 +17965,7 @@ static ma_result ma_event_signal__win32(ma_event* pEvent) static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore) { - *pSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL); + *pSemaphore = CreateSemaphore(NULL, (LONG)initialValue, LONG_MAX, NULL); if (*pSemaphore == NULL) { return ma_result_from_GetLastError(GetLastError()); } @@ -17337,10 +18859,12 @@ static MA_INLINE ma_uint16 ma_job_extract_slot(ma_uint64 toc) return (ma_uint16)(toc & 0x0000FFFF); } +#if 0 /* Currently unused, but might make use of this later. */ static MA_INLINE ma_uint16 ma_job_extract_code(ma_uint64 toc) { return (ma_uint16)((toc & 0xFFFF0000) >> 16); } +#endif static MA_INLINE ma_uint64 ma_job_toc_to_allocation(ma_uint64 toc) { @@ -17406,7 +18930,7 @@ static ma_job_proc g_jobVTable[MA_JOB_TYPE_COUNT] = /* Device. */ #if !defined(MA_NO_DEVICE_IO) - ma_job_process__device__aaudio_reroute /*MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE*/ + ma_job_process__device__aaudio_reroute /* MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE */ #endif }; @@ -17751,7 +19275,7 @@ MA_API ma_result ma_job_queue_next(ma_job_queue* pQueue, ma_job* pJob) is stored. One thread can fall through to the freeing of this item while another is still using "head" for the retrieval of the "next" variable. - The slot allocator might need to make use of some reference counting to ensure it's only truely freed when + The slot allocator might need to make use of some reference counting to ensure it's only truly freed when there are no more references to the item. This must be fixed before removing these locks. */ @@ -17805,6 +19329,13 @@ MA_API ma_result ma_job_queue_next(ma_job_queue* pQueue, ma_job* pJob) Dynamic Linking *******************************************************************************/ +/* Disable run-time linking on certain backends and platforms. */ +#ifndef MA_NO_RUNTIME_LINKING + #if defined(MA_EMSCRIPTEN) || defined(MA_ORBIS) || defined(MA_PROSPERO) || defined(MA_SWITCH) || defined(MA_DOS) + #define MA_NO_RUNTIME_LINKING + #endif +#endif + #ifdef MA_POSIX /* No need for dlfcn.h if we're not using runtime linking. */ #ifndef MA_NO_RUNTIME_LINKING @@ -17814,95 +19345,124 @@ Dynamic Linking MA_API ma_handle ma_dlopen(ma_log* pLog, const char* filename) { -#ifndef MA_NO_RUNTIME_LINKING - ma_handle handle; + #ifndef MA_NO_RUNTIME_LINKING + { + ma_handle handle; - ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename); + ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename); - #ifdef MA_WIN32 - /* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/ - #if !defined(MA_WIN32_UWP) || !(defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP))) - handle = (ma_handle)LoadLibraryA(filename); + #ifdef MA_WIN32 + /* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/ + #if !defined(MA_WIN32_UWP) || !(defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP))) + handle = (ma_handle)LoadLibraryA(filename); + #else + /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */ + WCHAR filenameW[4096]; + if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) { + handle = NULL; + } else { + handle = (ma_handle)LoadPackagedLibrary(filenameW, 0); + } + #endif #else - /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */ - WCHAR filenameW[4096]; - if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) { - handle = NULL; - } else { - handle = (ma_handle)LoadPackagedLibrary(filenameW, 0); - } + handle = (ma_handle)dlopen(filename, RTLD_NOW); #endif - #else - handle = (ma_handle)dlopen(filename, RTLD_NOW); - #endif - /* - I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority - backend is a deliberate design choice. Instead I'm logging it as an informational message. - */ - if (handle == NULL) { - ma_log_postf(pLog, MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename); + /* + I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority + backend is a deliberate design choice. Instead I'm logging it as an informational message. + */ + if (handle == NULL) { + ma_log_postf(pLog, MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename); + } + + return handle; } - - return handle; -#else - /* Runtime linking is disabled. */ - (void)pLog; - (void)filename; - return NULL; -#endif + #else + { + /* Runtime linking is disabled. */ + (void)pLog; + (void)filename; + return NULL; + } + #endif } MA_API void ma_dlclose(ma_log* pLog, ma_handle handle) { -#ifndef MA_NO_RUNTIME_LINKING - #ifdef MA_WIN32 - FreeLibrary((HMODULE)handle); - #else - dlclose((void*)handle); - #endif + #ifndef MA_NO_RUNTIME_LINKING + { + #ifdef MA_WIN32 + { + FreeLibrary((HMODULE)handle); + } + #else + { + /* Hack for Android bug (see https://github.com/android/ndk/issues/360). Calling dlclose() pre-API 28 may segfault. */ + #if !defined(MA_ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) + { + dlclose((void*)handle); + } + #else + { + (void)handle; + } + #endif + } + #endif - (void)pLog; -#else - /* Runtime linking is disabled. */ - (void)pLog; - (void)handle; -#endif + (void)pLog; + } + #else + { + /* Runtime linking is disabled. */ + (void)pLog; + (void)handle; + } + #endif } MA_API ma_proc ma_dlsym(ma_log* pLog, ma_handle handle, const char* symbol) { -#ifndef MA_NO_RUNTIME_LINKING - ma_proc proc; + #ifndef MA_NO_RUNTIME_LINKING + { + ma_proc proc; - ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol); + ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol); -#ifdef _WIN32 - proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol); -#else -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wpedantic" -#endif - proc = (ma_proc)dlsym((void*)handle, symbol); -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) - #pragma GCC diagnostic pop -#endif -#endif + #ifdef _WIN32 + { + proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol); + } + #else + { + #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpedantic" + #endif + proc = (ma_proc)dlsym((void*)handle, symbol); + #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__) + #pragma GCC diagnostic pop + #endif + } + #endif - if (proc == NULL) { - ma_log_postf(pLog, MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol); + if (proc == NULL) { + ma_log_postf(pLog, MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol); + } + + (void)pLog; /* It's possible for pContext to be unused. */ + return proc; } - - (void)pLog; /* It's possible for pContext to be unused. */ - return proc; -#else - /* Runtime linking is disabled. */ - (void)pLog; - (void)handle; - (void)symbol; - return NULL; -#endif + #else + { + /* Runtime linking is disabled. */ + (void)pLog; + (void)handle; + (void)symbol; + return NULL; + } + #endif } @@ -17916,29 +19476,24 @@ DEVICE I/O ************************************************************************************************************************************************************* ************************************************************************************************************************************************************/ -/* Disable run-time linking on certain backends and platforms. */ -#ifndef MA_NO_RUNTIME_LINKING - #if defined(MA_EMSCRIPTEN) || defined(MA_ORBIS) || defined(MA_PROSPERO) - #define MA_NO_RUNTIME_LINKING - #endif +#ifdef MA_APPLE + #include #endif #ifndef MA_NO_DEVICE_IO -#if defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200) +#if defined(MA_APPLE) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101200) #include /* For mach_absolute_time() */ #endif #ifdef MA_POSIX #include - #include - - /* No need for dlfcn.h if we're not using runtime linking. */ - #ifndef MA_NO_RUNTIME_LINKING - #include - #endif #endif +/* This must be set to at least 26. */ +#ifndef MA_AAUDIO_MIN_ANDROID_SDK_VERSION +#define MA_AAUDIO_MIN_ANDROID_SDK_VERSION 27 +#endif MA_API void ma_device_info_add_native_data_format(ma_device_info* pDeviceInfo, ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 flags) @@ -18085,7 +19640,7 @@ MA_API ma_bool32 ma_is_backend_enabled(ma_backend backend) #if defined(MA_HAS_AAUDIO) #if defined(MA_ANDROID) { - return ma_android_sdk_version() >= 26; + return ma_android_sdk_version() >= MA_AAUDIO_MIN_ANDROID_SDK_VERSION; } #else return MA_FALSE; @@ -18187,7 +19742,7 @@ MA_API ma_bool32 ma_is_loopback_supported(ma_backend backend) -#if defined(MA_WIN32) +#if defined(MA_WIN32) && !defined(MA_XBOX) /* WASAPI error codes. */ #define MA_AUDCLNT_E_NOT_INITIALIZED ((HRESULT)0x88890001) #define MA_AUDCLNT_E_ALREADY_INITIALIZED ((HRESULT)0x88890002) @@ -18402,6 +19957,10 @@ typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey); typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, const char* lpValueName, DWORD* lpReserved, DWORD* lpType, BYTE* lpData, DWORD* lpcbData); #endif /* MA_WIN32_DESKTOP */ +static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/ +/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/ MA_API size_t ma_strlen_WCHAR(const WCHAR* str) { @@ -18466,7 +20025,7 @@ Timing *******************************************************************************/ #if defined(MA_WIN32) && !defined(MA_POSIX) static LARGE_INTEGER g_ma_TimerFrequency; /* <-- Initialized to zero since it's static. */ - static void ma_timer_init(ma_timer* pTimer) + static MA_INLINE void ma_timer_init(ma_timer* pTimer) { LARGE_INTEGER counter; @@ -18478,7 +20037,7 @@ Timing pTimer->counter = counter.QuadPart; } - static double ma_timer_get_time_in_seconds(ma_timer* pTimer) + static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer) { LARGE_INTEGER counter; if (!QueryPerformanceCounter(&counter)) { @@ -18487,9 +20046,9 @@ Timing return (double)(counter.QuadPart - pTimer->counter) / g_ma_TimerFrequency.QuadPart; } -#elif defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200) +#elif defined(MA_APPLE) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101200) static ma_uint64 g_ma_TimerFrequency = 0; - static void ma_timer_init(ma_timer* pTimer) + static MA_INLINE void ma_timer_init(ma_timer* pTimer) { mach_timebase_info_data_t baseTime; mach_timebase_info(&baseTime); @@ -18498,7 +20057,7 @@ Timing pTimer->counter = mach_absolute_time(); } - static double ma_timer_get_time_in_seconds(ma_timer* pTimer) + static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer) { ma_uint64 newTimeCounter = mach_absolute_time(); ma_uint64 oldTimeCounter = pTimer->counter; @@ -18523,15 +20082,15 @@ Timing #define MA_CLOCK_ID CLOCK_REALTIME #endif - static void ma_timer_init(ma_timer* pTimer) + static MA_INLINE void ma_timer_init(ma_timer* pTimer) { struct timespec newTime; clock_gettime(MA_CLOCK_ID, &newTime); - pTimer->counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec; + pTimer->counter = ((ma_int64)newTime.tv_sec * 1000000000) + newTime.tv_nsec; } - static double ma_timer_get_time_in_seconds(ma_timer* pTimer) + static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer) { ma_uint64 newTimeCounter; ma_uint64 oldTimeCounter; @@ -18539,21 +20098,21 @@ Timing struct timespec newTime; clock_gettime(MA_CLOCK_ID, &newTime); - newTimeCounter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec; + newTimeCounter = ((ma_uint64)newTime.tv_sec * 1000000000) + newTime.tv_nsec; oldTimeCounter = pTimer->counter; return (newTimeCounter - oldTimeCounter) / 1000000000.0; } #else - static void ma_timer_init(ma_timer* pTimer) + static MA_INLINE void ma_timer_init(ma_timer* pTimer) { struct timeval newTime; gettimeofday(&newTime, NULL); - pTimer->counter = (newTime.tv_sec * 1000000) + newTime.tv_usec; + pTimer->counter = ((ma_int64)newTime.tv_sec * 1000000) + newTime.tv_usec; } - static double ma_timer_get_time_in_seconds(ma_timer* pTimer) + static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer) { ma_uint64 newTimeCounter; ma_uint64 oldTimeCounter; @@ -18561,7 +20120,7 @@ Timing struct timeval newTime; gettimeofday(&newTime, NULL); - newTimeCounter = (newTime.tv_sec * 1000000) + newTime.tv_usec; + newTimeCounter = ((ma_uint64)newTime.tv_sec * 1000000) + newTime.tv_usec; oldTimeCounter = pTimer->counter; return (newTimeCounter - oldTimeCounter) / 1000000.0; @@ -18670,11 +20229,16 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice) #endif #if defined(MA_EMSCRIPTEN) -EMSCRIPTEN_KEEPALIVE -void ma_device__on_notification_unlocked(ma_device* pDevice) +#ifdef __cplusplus +extern "C" { +#endif +void EMSCRIPTEN_KEEPALIVE ma_device__on_notification_unlocked(ma_device* pDevice) { ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_unlocked)); } +#ifdef __cplusplus +} +#endif #endif @@ -18802,7 +20366,7 @@ static void ma_device__handle_data_callback(ma_device* pDevice, void* pFramesOut unsigned int prevDenormalState = ma_device_disable_denormals(pDevice); { /* Volume control of input makes things a bit awkward because the input buffer is read-only. We'll need to use a temp buffer and loop in this case. */ - if (pFramesIn != NULL && masterVolumeFactor < 1) { + if (pFramesIn != NULL && masterVolumeFactor != 1) { ma_uint8 tempFramesIn[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels); ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels); @@ -18825,7 +20389,7 @@ static void ma_device__handle_data_callback(ma_device* pDevice, void* pFramesOut /* Volume control and clipping for playback devices. */ if (pFramesOut != NULL) { - if (masterVolumeFactor < 1) { + if (masterVolumeFactor != 1) { if (pFramesIn == NULL) { /* <-- In full-duplex situations, the volume will have been applied to the input samples before the data callback. Applying it again post-callback will incorrectly compound it. */ ma_apply_volume_factor_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels, masterVolumeFactor); } @@ -18837,6 +20401,11 @@ static void ma_device__handle_data_callback(ma_device* pDevice, void* pFramesOut } } ma_device_restore_denormals(pDevice, prevDenormalState); + } else { + /* No data callback. Just silence the output. */ + if (pFramesOut != NULL) { + ma_silence_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels); + } } } @@ -18922,9 +20491,7 @@ static void ma_device__read_frames_from_client(ma_device* pDevice, ma_uint32 fra framesToReadThisIterationIn = requiredInputFrameCount; } - if (framesToReadThisIterationIn > 0) { - ma_device__handle_data_callback(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn); - } + ma_device__handle_data_callback(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn); /* At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any @@ -18965,7 +20532,7 @@ static void ma_device__send_frames_to_client(ma_device* pDevice, ma_uint32 frame ma_uint64 totalClientFramesProcessed = 0; const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat; - /* We just keep going until we've exhaused all of our input frames and cannot generate any more output frames. */ + /* We just keep going until we've exhausted all of our input frames and cannot generate any more output frames. */ for (;;) { ma_uint64 deviceFramesProcessedThisIteration; ma_uint64 clientFramesProcessedThisIteration; @@ -19129,14 +20696,6 @@ static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_device_state n } -#if defined(MA_WIN32) - static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - /*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/ - /*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/ -#endif - - MA_API ma_uint32 ma_get_format_priority_index(ma_format format) /* Lower = better. */ { @@ -19248,7 +20807,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice) } /* - If we weren't able to generate any output frames it must mean we've exhaused all of our input. The only time this would not be the case is if capturedClientData was too small + If we weren't able to generate any output frames it must mean we've exhausted all of our input. The only time this would not be the case is if capturedClientData was too small which should never be the case when it's of the size MA_DATA_CONVERTER_STACK_BUFFER_SIZE. */ if (capturedClientFramesToProcessThisIteration == 0) { @@ -19451,7 +21010,7 @@ static ma_result ma_device_do_operation__null(ma_device* pDevice, ma_uint32 oper /* The first thing to do is wait for an operation slot to become available. We only have a single slot for this, but we could extend this later - to support queing of operations. + to support queuing of operations. */ result = ma_semaphore_wait(&pDevice->null_device.operationSemaphore); if (result != MA_SUCCESS) { @@ -19848,7 +21407,7 @@ static ma_result ma_context_init__null(ma_context* pContext, const ma_context_co WIN32 COMMON *******************************************************************************/ -#if defined(MA_WIN32) +#if defined(MA_WIN32) && !defined(MA_XBOX) #if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((pContext->win32.CoInitializeEx) ? ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit) : ((MA_PFN_CoInitialize)pContext->win32.CoInitialize)(pvReserved)) #define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)() @@ -19863,7 +21422,7 @@ WIN32 COMMON #define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar) #endif -#if !defined(MAXULONG_PTR) && !defined(__WATCOMC__) +#if !defined(MAXULONG_PTR) && !defined(__WATCOMC__) && !defined(MA_XBOX_NXDK) typedef size_t DWORD_PTR; #endif @@ -20290,11 +21849,21 @@ typedef enum MA_AudioCategory_Other = 0 /* <-- miniaudio is only caring about Other. */ } MA_AUDIO_STREAM_CATEGORY; +typedef enum +{ + MA_AUDCLNT_STREAMOPTIONS_NONE, + MA_AUDCLNT_STREAMOPTIONS_RAW, + MA_AUDCLNT_STREAMOPTIONS_MATCH_FORMAT, + MA_AUDCLNT_STREAMOPTIONS_AMBISONICS, + MA_AUDCLNT_STREAMOPTIONS_POST_VOLUME_LOOPBACK +} MA_AUDCLNT_STREAMOPTIONS; + typedef struct { ma_uint32 cbSize; BOOL bIsOffload; MA_AUDIO_STREAM_CATEGORY eCategory; + MA_AUDCLNT_STREAMOPTIONS Options; } ma_AudioClientProperties; /* IUnknown */ @@ -21268,7 +22837,7 @@ static ma_result ma_context_get_device_info_from_IAudioClient__wasapi(ma_context } /* - Exlcusive Mode. We repeatedly call IsFormatSupported() here. This is not currently supported on + Exclusive Mode. We repeatedly call IsFormatSupported() here. This is not currently supported on UWP. Failure to retrieve the exclusive mode format is not considered an error, so from here on out, MA_SUCCESS is guaranteed to be returned. */ @@ -21469,12 +23038,33 @@ static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device { ma_IMMDeviceEnumerator* pDeviceEnumerator; HRESULT hr; + HRESULT CoInitializeResult; MA_ASSERT(pContext != NULL); MA_ASSERT(ppMMDevice != NULL); - hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator); - if (FAILED(hr)) { + /* + This weird COM init/uninit here is a hack to work around a crash when changing devices. What is happening is + WASAPI fires a callback from another thread when the device is changed. It's from that thread where this + function is getting called. What I'm suspecting is that the other thread is not initializing COM which in turn + results in CoCreateInstance() failing. + + The community has reported that this seems to fix the crash. There are future plans to move all WASAPI operation + over to a single thread to make everything safer, but in the meantime while we wait for that to come online I'm + happy enough to use this hack instead. + + CoUninitialize should only be called if we successfully initialized. S_OK and S_FALSE both mean that we need to + call CoUninitialize since the internal ref count was increased. RPC_E_CHANGED_MODE means that CoInitializeEx was + called with a different COINIT value, and we don't call CoUninitialize in that case. Other errors are possible, + so we check for S_OK and S_FALSE specifically. + */ + CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE); + { + hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator); + } + if (CoInitializeResult == S_OK || CoInitializeResult == S_FALSE) { ma_CoUninitialize(pContext); } + + if (FAILED(hr)) { /* <-- This is checking the call above to ma_CoCreateInstance(). */ ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n"); return ma_result_from_HRESULT(hr); } @@ -21506,7 +23096,7 @@ static ma_result ma_context_get_device_id_from_MMDevice__wasapi(ma_context* pCon size_t idlen = ma_strlen_WCHAR(pDeviceIDString); if (idlen+1 > ma_countof(pDeviceID->wasapi)) { ma_CoTaskMemFree(pContext, pDeviceIDString); - MA_ASSERT(MA_FALSE); /* NOTE: If this is triggered, please report it. It means the format of the ID must haved change and is too long to fit in our fixed sized buffer. */ + MA_ASSERT(MA_FALSE); /* NOTE: If this is triggered, please report it. It means the format of the ID must have changed and is too long to fit in our fixed sized buffer. */ return MA_ERROR; } @@ -21816,7 +23406,7 @@ static ma_result ma_context_get_IAudioClient__wasapi(ma_context* pContext, ma_de pActivationParams = &activationParams; /* When requesting a specific device ID we need to use a special device ID. */ - MA_COPY_MEMORY(virtualDeviceID.wasapi, MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, (wcslen(MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK) + 1) * sizeof(wchar_t)); /* +1 for the null terminator. */ + MA_COPY_MEMORY(virtualDeviceID.wasapi, MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, (ma_wcslen(MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK) + 1) * sizeof(wchar_t)); /* +1 for the null terminator. */ pDeviceID = &virtualDeviceID; } else { pActivationParams = NULL; /* No activation parameters required. */ @@ -21950,12 +23540,16 @@ static ma_result ma_device_uninit__wasapi(ma_device* pDevice) { MA_ASSERT(pDevice != NULL); -#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) - if (pDevice->wasapi.pDeviceEnumerator) { - ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient); - ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator); + #if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) + { + if (pDevice->wasapi.pDeviceEnumerator) { + ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient); + ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator); + } + + ma_mutex_uninit(&pDevice->wasapi.rerouteLock); } -#endif + #endif if (pDevice->wasapi.pRenderClient) { if (pDevice->wasapi.pMappedBufferPlayback != NULL) { @@ -22256,7 +23850,7 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device MA_REFERENCE_TIME bufferDuration = periodDurationInMicroseconds * pData->periodsOut * 10; /* - If the periodicy is too small, Initialize() will fail with AUDCLNT_E_INVALID_DEVICE_PERIOD. In this case we should just keep increasing + If the periodicity is too small, Initialize() will fail with AUDCLNT_E_INVALID_DEVICE_PERIOD. In this case we should just keep increasing it and trying it again. */ hr = E_FAIL; @@ -22266,7 +23860,7 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device if (bufferDuration > 500*10000) { break; } else { - if (bufferDuration == 0) { /* <-- Just a sanity check to prevent an infinit loop. Should never happen, but it makes me feel better. */ + if (bufferDuration == 0) { /* <-- Just a sanity check to prevent an infinite loop. Should never happen, but it makes me feel better. */ break; } @@ -23005,6 +24599,14 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) } if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) { + /* If we have a mapped buffer we need to release it. */ + if (pDevice->wasapi.pMappedBufferCapture != NULL) { + ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, pDevice->wasapi.mappedBufferCaptureCap); + pDevice->wasapi.pMappedBufferCapture = NULL; + pDevice->wasapi.mappedBufferCaptureCap = 0; + pDevice->wasapi.mappedBufferCaptureLen = 0; + } + hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture); if (FAILED(hr)) { ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal capture device."); @@ -23018,31 +24620,34 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) return ma_result_from_HRESULT(hr); } - /* If we have a mapped buffer we need to release it. */ - if (pDevice->wasapi.pMappedBufferCapture != NULL) { - ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, pDevice->wasapi.mappedBufferCaptureCap); - pDevice->wasapi.pMappedBufferCapture = NULL; - pDevice->wasapi.mappedBufferCaptureCap = 0; - pDevice->wasapi.mappedBufferCaptureLen = 0; - } - ma_atomic_bool32_set(&pDevice->wasapi.isStartedCapture, MA_FALSE); } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { + if (pDevice->wasapi.pMappedBufferPlayback != NULL) { + ma_silence_pcm_frames( + ma_offset_pcm_frames_ptr(pDevice->wasapi.pMappedBufferPlayback, pDevice->wasapi.mappedBufferPlaybackLen, pDevice->playback.internalFormat, pDevice->playback.internalChannels), + pDevice->wasapi.mappedBufferPlaybackCap - pDevice->wasapi.mappedBufferPlaybackLen, + pDevice->playback.internalFormat, pDevice->playback.internalChannels + ); + ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); + pDevice->wasapi.pMappedBufferPlayback = NULL; + pDevice->wasapi.mappedBufferPlaybackCap = 0; + pDevice->wasapi.mappedBufferPlaybackLen = 0; + } + /* The buffer needs to be drained before stopping the device. Not doing this will result in the last few frames not getting output to the speakers. This is a problem for very short sounds because it'll result in a significant portion of it not getting played. */ if (ma_atomic_bool32_get(&pDevice->wasapi.isStartedPlayback)) { /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */ - DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / pDevice->playback.internalSampleRate; + DWORD waitTime = (pDevice->wasapi.actualBufferSizeInFramesPlayback * 1000) / pDevice->playback.internalSampleRate; if (pDevice->playback.shareMode == ma_share_mode_exclusive) { WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); - } - else { - ma_uint32 prevFramesAvaialablePlayback = (ma_uint32)-1; + } else { + ma_uint32 prevFramesAvailablePlayback = (ma_uint32)-1; ma_uint32 framesAvailablePlayback; for (;;) { result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback); @@ -23058,13 +24663,13 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) Just a safety check to avoid an infinite loop. If this iteration results in a situation where the number of available frames has not changed, get out of the loop. I don't think this should ever happen, but I think it's nice to have just in case. */ - if (framesAvailablePlayback == prevFramesAvaialablePlayback) { + if (framesAvailablePlayback == prevFramesAvailablePlayback) { break; } - prevFramesAvaialablePlayback = framesAvailablePlayback; + prevFramesAvailablePlayback = framesAvailablePlayback; - WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime * 1000); ResetEvent((HANDLE)pDevice->wasapi.hEventPlayback); /* Manual reset. */ + WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); } } } @@ -23076,19 +24681,20 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) } /* The audio client needs to be reset otherwise restarting will fail. */ - hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback); + { + ma_int32 retries = 5; + + while ((hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback)) == MA_AUDCLNT_E_BUFFER_OPERATION_PENDING && retries > 0) { + ma_sleep(10); + retries -= 1; + } + } + if (FAILED(hr)) { ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to reset internal playback device."); return ma_result_from_HRESULT(hr); } - if (pDevice->wasapi.pMappedBufferPlayback != NULL) { - ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); - pDevice->wasapi.pMappedBufferPlayback = NULL; - pDevice->wasapi.mappedBufferPlaybackCap = 0; - pDevice->wasapi.mappedBufferPlaybackLen = 0; - } - ma_atomic_bool32_set(&pDevice->wasapi.isStartedPlayback, MA_FALSE); } @@ -23655,6 +25261,13 @@ DirectSound Backend #define MA_DSBPLAY_TERMINATEBY_DISTANCE 0x00000010 #define MA_DSBPLAY_TERMINATEBY_PRIORITY 0x00000020 +#define MA_DSBSTATUS_PLAYING 0x00000001 +#define MA_DSBSTATUS_BUFFERLOST 0x00000002 +#define MA_DSBSTATUS_LOOPING 0x00000004 +#define MA_DSBSTATUS_LOCHARDWARE 0x00000008 +#define MA_DSBSTATUS_LOCSOFTWARE 0x00000010 +#define MA_DSBSTATUS_TERMINATED 0x00000020 + #define MA_DSCBSTART_LOOPING 0x00000001 typedef struct @@ -24024,9 +25637,12 @@ static ma_result ma_context_create_IDirectSound__dsound(ma_context* pContext, ma } /* The cooperative level must be set before doing anything else. */ - hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)(); + hWnd = (HWND)pContext->dsound.hWnd; if (hWnd == 0) { - hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)(); + hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)(); + if (hWnd == 0) { + hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)(); + } } hr = ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode == ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY); @@ -24530,8 +26146,8 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf } /* - Unfortunately DirectSound uses different APIs and data structures for playback and catpure devices. We need to initialize - the capture device first because we'll want to match it's buffer size and period count on the playback side if we're using + Unfortunately DirectSound uses different APIs and data structures for playback and capture devices. We need to initialize + the capture device first because we'll want to match its buffer size and period count on the playback side if we're using full-duplex mode. */ if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) { @@ -24814,6 +26430,7 @@ static ma_result ma_device_data_loop__dsound(ma_device* pDevice) ma_bool32 isPlaybackDeviceStarted = MA_FALSE; ma_uint32 framesWrittenToPlaybackDevice = 0; /* For knowing whether or not the playback device needs to be started. */ ma_uint32 waitTimeInMilliseconds = 1; + DWORD playbackBufferStatus = 0; MA_ASSERT(pDevice != NULL); @@ -25142,6 +26759,20 @@ static ma_result ma_device_data_loop__dsound(ma_device* pDevice) break; } + hr = ma_IDirectSoundBuffer_GetStatus((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &playbackBufferStatus); + if (SUCCEEDED(hr) && (playbackBufferStatus & MA_DSBSTATUS_PLAYING) == 0 && isPlaybackDeviceStarted) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[DirectSound] Attempting to resume audio due to state: %d.", (int)playbackBufferStatus); + hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING); + if (FAILED(hr)) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed after attempting to resume from state %d.", (int)playbackBufferStatus); + return ma_result_from_HRESULT(hr); + } + + isPlaybackDeviceStarted = MA_TRUE; + ma_sleep(waitTimeInMilliseconds); + continue; + } + if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) { physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback; } @@ -25343,6 +26974,8 @@ static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_ return MA_API_NOT_FOUND; } + pContext->dsound.hWnd = pConfig->dsound.hWnd; + pCallbacks->onContextInit = ma_context_init__dsound; pCallbacks->onContextUninit = ma_context_uninit__dsound; pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound; @@ -25665,7 +27298,7 @@ static ma_result ma_context_get_device_info_from_WAVECAPS(ma_context* pContext, - If the name GUID is not present in the registry we'll also need to stick to the original 31 characters. - I like consistency, so I want the returned device names to be consistent with those returned by WASAPI and DirectSound. The problem, however is that WASAPI and DirectSound use " ()" format (such as "Speakers (High Definition Audio)"), - but WinMM does not specificy the component name. From my admittedly limited testing, I've notice the component name seems to + but WinMM does not specify the component name. From my admittedly limited testing, I've notice the component name seems to usually fit within the 31 characters of the fixed sized buffer, so what I'm going to do is parse that string for the component name, and then concatenate the name from the registry. */ @@ -25933,7 +27566,7 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_confi return MA_DEVICE_TYPE_NOT_SUPPORTED; } - /* No exlusive mode with WinMM. */ + /* No exclusive mode with WinMM. */ if (((pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) && pDescriptorPlayback->shareMode == ma_share_mode_exclusive) || ((pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) && pDescriptorCapture->shareMode == ma_share_mode_exclusive)) { return MA_SHARE_MODE_NOT_SUPPORTED; @@ -25955,7 +27588,7 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_confi /* We use an event to know when a new fragment needs to be enqueued. */ pDevice->winmm.hEventCapture = (ma_handle)CreateEventA(NULL, TRUE, TRUE, NULL); if (pDevice->winmm.hEventCapture == NULL) { - errorMsg = "[WinMM] Failed to create event for fragment enqueing for the capture device.", errorCode = ma_result_from_GetLastError(GetLastError()); + errorMsg = "[WinMM] Failed to create event for fragment enqueuing for the capture device.", errorCode = ma_result_from_GetLastError(GetLastError()); goto on_error; } @@ -25993,7 +27626,7 @@ static ma_result ma_device_init__winmm(ma_device* pDevice, const ma_device_confi /* We use an event to know when a new fragment needs to be enqueued. */ pDevice->winmm.hEventPlayback = (ma_handle)CreateEventA(NULL, TRUE, TRUE, NULL); if (pDevice->winmm.hEventPlayback == NULL) { - errorMsg = "[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode = ma_result_from_GetLastError(GetLastError()); + errorMsg = "[WinMM] Failed to create event for fragment enqueuing for the playback device.", errorCode = ma_result_from_GetLastError(GetLastError()); goto on_error; } @@ -26502,6 +28135,9 @@ typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t; typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t; typedef snd_pcm_state_t ma_snd_pcm_state_t; +/* snd_pcm_state_t */ +#define MA_SND_PCM_STATE_XRUN SND_PCM_STATE_XRUN + /* snd_pcm_stream_t */ #define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK #define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE @@ -26697,6 +28333,7 @@ typedef int (* ma_snd_pcm_hw_params_set_channels_minmax_proc) ( typedef int (* ma_snd_pcm_hw_params_set_rate_resample_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val); typedef int (* ma_snd_pcm_hw_params_set_rate_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val, int dir); typedef int (* ma_snd_pcm_hw_params_set_rate_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir); +typedef int (* ma_snd_pcm_hw_params_set_rate_minmax_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir); typedef int (* ma_snd_pcm_hw_params_set_buffer_size_near_proc)(ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_uframes_t *val); typedef int (* ma_snd_pcm_hw_params_set_periods_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir); typedef int (* ma_snd_pcm_hw_params_set_access_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_access_t _access); @@ -27115,7 +28752,7 @@ static ma_result ma_context_open_pcm__alsa(ma_context* pContext, ma_share_mode s /* We're trying to open a specific device. There's a few things to consider here: - miniaudio recongnizes a special format of device id that excludes the "hw", "dmix", etc. prefix. It looks like this: ":0,0", ":0,1", etc. When + miniaudio recognizes a special format of device id that excludes the "hw", "dmix", etc. prefix. It looks like this: ":0,0", ":0,1", etc. When an ID of this format is specified, it indicates to miniaudio that it can try different combinations of plugins ("hw", "dmix", etc.) until it finds an appropriate one that works. This comes in very handy when trying to open a device in shared mode ("dmix"), vs exclusive mode ("hw"). */ @@ -27214,7 +28851,7 @@ static ma_result ma_context_enumerate_devices__alsa(ma_context* pContext, ma_enu /* At this point, hwid looks like "hw:0,0". In simplified enumeration mode, we actually want to strip off the plugin name so it looks like ":0,0". The reason for this is that this special format is detected at device - initialization time and is used as an indicator to try and use the most appropriate plugin depending on the + initialization time and is used as an indicator to try to use the most appropriate plugin depending on the device type and sharing mode. */ char* dst = hwid; @@ -27393,7 +29030,7 @@ static void ma_context_iterate_rates_and_add_native_data_format__alsa(ma_context ((ma_snd_pcm_hw_params_get_rate_min_proc)pContext->alsa.snd_pcm_hw_params_get_rate_min)(pHWParams, &minSampleRate, &sampleRateDir); ((ma_snd_pcm_hw_params_get_rate_max_proc)pContext->alsa.snd_pcm_hw_params_get_rate_max)(pHWParams, &maxSampleRate, &sampleRateDir); - /* Make sure our sample rates are clamped to sane values. Stupid devices like "pulse" will reports rates like "1" which is ridiculus. */ + /* Make sure our sample rates are clamped to sane values. Stupid devices like "pulse" will reports rates like "1" which is ridiculous. */ minSampleRate = ma_clamp(minSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max); maxSampleRate = ma_clamp(maxSampleRate, (unsigned int)ma_standard_sample_rate_min, (unsigned int)ma_standard_sample_rate_max); @@ -27469,10 +29106,10 @@ static ma_result ma_context_get_device_info__alsa(ma_context* pContext, ma_devic /* Some ALSA devices can support many permutations of formats, channels and rates. We only support a fixed number of permutations which means we need to employ some strategies to ensure the best - combinations are returned. An example is the "pulse" device which can do it's own data conversion + combinations are returned. An example is the "pulse" device which can do its own data conversion in software and as a result can support any combination of format, channels and rate. - We want to ensure the the first data formats are the best. We have a list of favored sample + We want to ensure that the first data formats are the best. We have a list of favored sample formats and sample rates, so these will be the basis of our iteration. */ @@ -28050,7 +29687,21 @@ static ma_result ma_device_start__alsa(ma_device* pDevice) } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { - /* Don't need to do anything for playback because it'll be started automatically when enough data has been written. */ + /* + When data is written to the device we wait for the device to get ready to receive data with poll(). In my testing + I have observed that poll() can sometimes block forever unless the device is started explicitly with snd_pcm_start() + or some data is written with snd_pcm_writei(). + + To resolve this I've decided to do an explicit start with snd_pcm_start(). The problem with this is that the device + is started without any data in the internal buffer which will result in an immediate underrun. If instead we were + to call into snd_pcm_writei() in an attempt to prevent the underrun, we would run the risk of a weird deadlock + issue as documented inside ma_device_write__alsa(). + */ + resultALSA = ((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback); + if (resultALSA < 0) { + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start playback device."); + return ma_result_from_errno(-resultALSA); + } } return MA_SUCCESS; @@ -28063,6 +29714,7 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice) a small chance that our wakeupfd has not been cleared. We'll clear that out now if applicable. */ int resultPoll; + int resultRead; if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) { ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Dropping capture device...\n"); @@ -28077,12 +29729,15 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice) ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Preparing capture device successful.\n"); } - /* Clear the wakeupfd. */ - resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0); - if (resultPoll > 0) { - ma_uint64 t; - read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t)); - } + /* Clear the wakeupfd. */ + resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture, 1, 0); + if (resultPoll > 0) { + ma_uint64 t; + resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsCapture)[0].fd, &t, sizeof(t)); + if (resultRead != sizeof(t)) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from capture wakeupfd. read() = %d\n", resultRead); + } + } } if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { @@ -28099,12 +29754,14 @@ static ma_result ma_device_stop__alsa(ma_device* pDevice) } /* Clear the wakeupfd. */ - resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0); - if (resultPoll > 0) { - ma_uint64 t; - read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t)); - } - + resultPoll = poll((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback, 1, 0); + if (resultPoll > 0) { + ma_uint64 t; + resultRead = read(((struct pollfd*)pDevice->alsa.pPollDescriptorsPlayback)[0].fd, &t, sizeof(t)); + if (resultRead != sizeof(t)) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to read from playback wakeupfd. read() = %d\n", resultRead); + } + } } return MA_SUCCESS; @@ -28117,13 +29774,20 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st int resultALSA; int resultPoll = poll(pPollDescriptors, pollDescriptorCount, -1); if (resultPoll < 0) { - ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] poll() failed.\n"); - return ma_result_from_errno(errno); + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[ALSA] poll() failed.\n"); + + /* + There have been reports that poll() is returning an error randomly and that instead of + returning an error, simply trying again will work. I'm experimenting with adopting this + advice. + */ + continue; + /*return ma_result_from_errno(errno);*/ } /* Before checking the ALSA poll descriptor flag we need to check if the wakeup descriptor - has had it's POLLIN flag set. If so, we need to actually read the data and then exit + has had it's POLLIN flag set. If so, we need to actually read the data and then exit the function. The wakeup descriptor will be the first item in the descriptors buffer. */ if ((pPollDescriptors[0].revents & POLLIN) != 0) { @@ -28152,7 +29816,7 @@ static ma_result ma_device_wait__alsa(ma_device* pDevice, ma_snd_pcm_t* pPCM, st ma_snd_pcm_state_t state = ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM); if (state == MA_SND_PCM_STATE_XRUN) { /* The PCM is in a xrun state. This will be recovered from at a higher level. We can disregard this. */ - } else { + } else { ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[ALSA] POLLERR detected. status = %d\n", ((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)(pPCM)); } } @@ -28436,8 +30100,9 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask; ma_snd_pcm_hw_params_set_channels_proc _snd_pcm_hw_params_set_channels = snd_pcm_hw_params_set_channels; ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near; + ma_snd_pcm_hw_params_set_channels_minmax_proc _snd_pcm_hw_params_set_channels_minmax = snd_pcm_hw_params_set_channels_minmax; ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample; - ma_snd_pcm_hw_params_set_rate_near _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate; + ma_snd_pcm_hw_params_set_rate_proc _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate; ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near; ma_snd_pcm_hw_params_set_rate_minmax_proc _snd_pcm_hw_params_set_rate_minmax = snd_pcm_hw_params_set_rate_minmax; ma_snd_pcm_hw_params_set_buffer_size_near_proc _snd_pcm_hw_params_set_buffer_size_near = snd_pcm_hw_params_set_buffer_size_near; @@ -28489,9 +30154,9 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info; ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof; ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name; - ma_snd_pcm_poll_descriptors _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors; - ma_snd_pcm_poll_descriptors_count _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count; - ma_snd_pcm_poll_descriptors_revents _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents; + ma_snd_pcm_poll_descriptors_proc _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors; + ma_snd_pcm_poll_descriptors_count_proc _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count; + ma_snd_pcm_poll_descriptors_revents_proc _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents; ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global; pContext->alsa.snd_pcm_open = (ma_proc)_snd_pcm_open; @@ -28507,6 +30172,7 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)_snd_pcm_hw_params_set_rate_resample; pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)_snd_pcm_hw_params_set_rate; pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)_snd_pcm_hw_params_set_rate_near; + pContext->alsa.snd_pcm_hw_params_set_rate_minmax = (ma_proc)_snd_pcm_hw_params_set_rate_minmax; pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (ma_proc)_snd_pcm_hw_params_set_buffer_size_near; pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)_snd_pcm_hw_params_set_periods_near; pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)_snd_pcm_hw_params_set_access; @@ -28585,7 +30251,7 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co return MA_SUCCESS; } -#endif /* ALSA */ +#endif /* MA_HAS_ALSA */ @@ -28596,7 +30262,7 @@ PulseAudio Backend ******************************************************************************/ #ifdef MA_HAS_PULSEAUDIO /* -The PulseAudio API, along with Apple's Core Audio, is the worst of the maintream audio APIs. This is a brief description of what's going on +The PulseAudio API, along with Apple's Core Audio, is the worst of the mainstream audio APIs. This is a brief description of what's going on in the PulseAudio backend. I apologize if this gets a bit ranty for your liking - you might want to skip this discussion. PulseAudio has something they call the "Simple API", which unfortunately isn't suitable for miniaudio. I've not seen anywhere where it @@ -28611,7 +30277,7 @@ get fun, and I don't mean that in a good way... The problems start with the very name of the API - "asynchronous". Yes, this is an asynchronous oriented API which means your commands don't immediately take effect. You instead need to issue your commands, and then wait for them to complete. The waiting mechanism is -enabled through the use of a "main loop". In the asychronous API you cannot get away from the main loop, and the main loop is where almost +enabled through the use of a "main loop". In the asynchronous API you cannot get away from the main loop, and the main loop is where almost all of PulseAudio's problems stem from. When you first initialize PulseAudio you need an object referred to as "main loop". You can implement this yourself by defining your own @@ -28661,7 +30327,7 @@ because PulseAudio takes it literally, specifically the "can be". You would thin writing and reading data to and from the stream, and that would be right, except when it's not. When you initialize the stream, you can set a flag that tells PulseAudio to not start the stream automatically. This is required because miniaudio does not auto-start devices straight after initialization - you need to call `ma_device_start()` manually. The problem is that even when this flag is specified, -PulseAudio will immediately fire it's write or read callback. This is *technically* correct (based on the wording in the documentation) +PulseAudio will immediately fire its write or read callback. This is *technically* correct (based on the wording in the documentation) because indeed, data *can* be written at this point. The problem is that it's not *practical*. It makes sense that the write/read callback would be where a program will want to write or read data to or from the stream, but when it's called before the application has even requested that the stream be started, it's just not practical because the program probably isn't ready for any kind of data delivery at @@ -29232,7 +30898,7 @@ typedef void (* ma_pa_threaded_mainloop_unlock_proc) ( typedef void (* ma_pa_threaded_mainloop_wait_proc) (ma_pa_threaded_mainloop* m); typedef void (* ma_pa_threaded_mainloop_signal_proc) (ma_pa_threaded_mainloop* m, int wait_for_accept); typedef void (* ma_pa_threaded_mainloop_accept_proc) (ma_pa_threaded_mainloop* m); -typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (ma_pa_threaded_mainloop* m); +typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (const ma_pa_threaded_mainloop* m); typedef ma_pa_mainloop_api* (* ma_pa_threaded_mainloop_get_api_proc) (ma_pa_threaded_mainloop* m); typedef int (* ma_pa_threaded_mainloop_in_thread_proc) (ma_pa_threaded_mainloop* m); typedef void (* ma_pa_threaded_mainloop_set_name_proc) (ma_pa_threaded_mainloop* m, const char* name); @@ -29241,13 +30907,13 @@ typedef void (* ma_pa_context_unref_proc) ( typedef int (* ma_pa_context_connect_proc) (ma_pa_context* c, const char* server, ma_pa_context_flags_t flags, const ma_pa_spawn_api* api); typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c); typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb, void* userdata); -typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c); +typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (const ma_pa_context* c); typedef ma_pa_operation* (* ma_pa_context_get_sink_info_list_proc) (ma_pa_context* c, ma_pa_sink_info_cb_t cb, void* userdata); typedef ma_pa_operation* (* ma_pa_context_get_source_info_list_proc) (ma_pa_context* c, ma_pa_source_info_cb_t cb, void* userdata); typedef ma_pa_operation* (* ma_pa_context_get_sink_info_by_name_proc) (ma_pa_context* c, const char* name, ma_pa_sink_info_cb_t cb, void* userdata); typedef ma_pa_operation* (* ma_pa_context_get_source_info_by_name_proc)(ma_pa_context* c, const char* name, ma_pa_source_info_cb_t cb, void* userdata); typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o); -typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o); +typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (const ma_pa_operation* o); typedef ma_pa_channel_map* (* ma_pa_channel_map_init_extend_proc) (ma_pa_channel_map* m, unsigned channels, ma_pa_channel_map_def_t def); typedef int (* ma_pa_channel_map_valid_proc) (const ma_pa_channel_map* m); typedef int (* ma_pa_channel_map_compatible_proc) (const ma_pa_channel_map* m, const ma_pa_sample_spec* ss); @@ -29256,12 +30922,12 @@ typedef void (* ma_pa_stream_unref_proc) ( typedef int (* ma_pa_stream_connect_playback_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags, const ma_pa_cvolume* volume, ma_pa_stream* sync_stream); typedef int (* ma_pa_stream_connect_record_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags); typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream* s); -typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream* s); +typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (const ma_pa_stream* s); typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream* s); typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream* s); typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream* s); typedef ma_pa_operation* (* ma_pa_stream_set_buffer_attr_proc) (ma_pa_stream* s, const ma_pa_buffer_attr* attr, ma_pa_stream_success_cb_t cb, void* userdata); -typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream* s); +typedef const char* (* ma_pa_stream_get_device_name_proc) (const ma_pa_stream* s); typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata); typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata); typedef void (* ma_pa_stream_set_suspended_callback_proc) (ma_pa_stream* s, ma_pa_stream_notify_cb_t cb, void* userdata); @@ -29269,15 +30935,15 @@ typedef void (* ma_pa_stream_set_moved_callback_proc) ( typedef int (* ma_pa_stream_is_suspended_proc) (const ma_pa_stream* s); typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata); typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata); -typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream* s); +typedef int (* ma_pa_stream_is_corked_proc) (const ma_pa_stream* s); typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream* s, int b, ma_pa_stream_success_cb_t cb, void* userdata); typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata); typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream* s, void** data, size_t* nbytes); typedef int (* ma_pa_stream_write_proc) (ma_pa_stream* s, const void* data, size_t nbytes, ma_pa_free_cb_t free_cb, int64_t offset, ma_pa_seek_mode_t seek); typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream* s, const void** data, size_t* nbytes); typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream* s); -typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream* s); -typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream* s); +typedef size_t (* ma_pa_stream_writable_size_proc) (const ma_pa_stream* s); +typedef size_t (* ma_pa_stream_readable_size_proc) (const ma_pa_stream* s); typedef struct { @@ -29573,9 +31239,10 @@ static ma_result ma_init_pa_mainloop_and_pa_context__pulse(ma_context* pContext, } /* Now we need to connect to the context. Everything is asynchronous so we need to wait for it to connect before returning. */ - result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pPulseContext, pServerName, (tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN, NULL)); + result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pPulseContext, pServerName, (tryAutoSpawn) ? MA_PA_CONTEXT_NOFLAGS : MA_PA_CONTEXT_NOAUTOSPAWN, NULL)); if (result != MA_SUCCESS) { ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio context."); + ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)(pPulseContext)); ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop)); return result; } @@ -29584,6 +31251,7 @@ static ma_result ma_init_pa_mainloop_and_pa_context__pulse(ma_context* pContext, result = ma_wait_for_pa_context_to_connect__pulse(pContext, pMainLoop, pPulseContext); if (result != MA_SUCCESS) { ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Waiting for connection failed."); + ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)(pPulseContext)); ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop)); return result; } @@ -30039,16 +31707,18 @@ static ma_pa_buffer_attr ma_device__pa_buffer_attr_new(ma_uint32 periodSizeInFra static ma_pa_stream* ma_device__pa_stream_new__pulse(ma_device* pDevice, const char* pStreamName, const ma_pa_sample_spec* ss, const ma_pa_channel_map* cmap) { - static int g_StreamCounter = 0; + static ma_atomic_uint32 g_StreamCounter = { 0 }; char actualStreamName[256]; if (pStreamName != NULL) { ma_strncpy_s(actualStreamName, sizeof(actualStreamName), pStreamName, (size_t)-1); } else { - ma_strcpy_s(actualStreamName, sizeof(actualStreamName), "miniaudio:"); - ma_itoa_s(g_StreamCounter, actualStreamName + 8, sizeof(actualStreamName)-8, 10); /* 8 = strlen("miniaudio:") */ + const char* pBaseName = "miniaudio:"; + size_t baseNameLen = strlen(pBaseName); + ma_strcpy_s(actualStreamName, sizeof(actualStreamName), pBaseName); + ma_itoa_s((int)ma_atomic_uint32_get(&g_StreamCounter), actualStreamName + baseNameLen, sizeof(actualStreamName)-baseNameLen, 10); } - g_StreamCounter += 1; + ma_atomic_uint32_fetch_add(&g_StreamCounter, 1); return ((ma_pa_stream_new_proc)pDevice->pContext->pulse.pa_stream_new)((ma_pa_context*)pDevice->pulse.pPulseContext, actualStreamName, ss, cmap); } @@ -30302,8 +31972,9 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi ma_pa_buffer_attr attr; const ma_pa_sample_spec* pActualSS = NULL; const ma_pa_buffer_attr* pActualAttr = NULL; + const ma_pa_channel_map* pActualChannelMap = NULL; ma_uint32 iChannel; - ma_pa_stream_flags_t streamFlags; + int streamFlags; MA_ASSERT(pDevice != NULL); MA_ZERO_OBJECT(&pDevice->pulse); @@ -30361,8 +32032,13 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi ss.channels = pDescriptorCapture->channels; } + /* PulseAudio has a maximum channel count of 32. We'll get a crash if this is exceeded. */ + if (ss.channels > 32) { + ss.channels = 32; + } + /* Use a default channel map. */ - ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT); + ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, (ma_pa_channel_map_def_t)pConfig->pulse.channelMap); /* Use the requested sample rate if one was specified. */ if (pDescriptorCapture->sampleRate != 0) { @@ -30419,7 +32095,7 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi streamFlags |= MA_PA_STREAM_DONT_MOVE; } - error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags); + error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, (ma_pa_stream_flags_t)streamFlags); if (error != MA_PA_OK) { ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream."); result = ma_result_from_pulse(error); @@ -30451,7 +32127,12 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi goto on_error4; } + /* Internal channel map. */ + pActualChannelMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture); + if (pActualChannelMap == NULL) { + pActualChannelMap = &cmap; /* Fallback just in case. */ + } /* Bug in PipeWire. There have been reports that PipeWire is returning AUX channels when reporting @@ -30461,8 +32142,8 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi fixed sooner than later. I might remove this hack later. */ if (pDescriptorCapture->channels > 2) { - for (iChannel = 0; iChannel < pDescriptorCapture->channels; ++iChannel) { - pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]); + for (iChannel = 0; iChannel < pDescriptorCapture->channels; iChannel += 1) { + pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(pActualChannelMap->map[iChannel]); } } else { /* Hack for mono and stereo. */ @@ -30508,8 +32189,13 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi ss.channels = pDescriptorPlayback->channels; } + /* PulseAudio has a maximum channel count of 32. We'll get a crash if this is exceeded. */ + if (ss.channels > 32) { + ss.channels = 32; + } + /* Use a default channel map. */ - ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT); + ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, (ma_pa_channel_map_def_t)pConfig->pulse.channelMap); /* Use the requested sample rate if one was specified. */ @@ -30571,7 +32257,7 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi streamFlags |= MA_PA_STREAM_DONT_MOVE; } - error = ((ma_pa_stream_connect_playback_proc)pDevice->pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags, NULL, NULL); + error = ((ma_pa_stream_connect_playback_proc)pDevice->pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, (ma_pa_stream_flags_t)streamFlags, NULL, NULL); if (error != MA_PA_OK) { ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream."); result = ma_result_from_pulse(error); @@ -30603,7 +32289,12 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi goto on_error4; } + /* Internal channel map. */ + pActualChannelMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback); + if (pActualChannelMap == NULL) { + pActualChannelMap = &cmap; /* Fallback just in case. */ + } /* Bug in PipeWire. There have been reports that PipeWire is returning AUX channels when reporting @@ -30613,8 +32304,8 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi fixed sooner than later. I might remove this hack later. */ if (pDescriptorPlayback->channels > 2) { - for (iChannel = 0; iChannel < pDescriptorPlayback->channels; ++iChannel) { - pDescriptorPlayback->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]); + for (iChannel = 0; iChannel < pDescriptorPlayback->channels; iChannel += 1) { + pDescriptorPlayback->channelMap[iChannel] = ma_channel_position_from_pulse(pActualChannelMap->map[iChannel]); } } else { /* Hack for mono and stereo. */ @@ -31121,6 +32812,7 @@ typedef JackProcessCallback ma_JackProcessCallback; typedef JackBufferSizeCallback ma_JackBufferSizeCallback; typedef JackShutdownCallback ma_JackShutdownCallback; #define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE +#define ma_JackNullOption JackNullOption #define ma_JackNoStartServer JackNoStartServer #define ma_JackPortIsInput JackPortIsInput #define ma_JackPortIsOutput JackPortIsOutput @@ -31135,6 +32827,7 @@ typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes, void* arg) typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes, void* arg); typedef void (* ma_JackShutdownCallback) (void* arg); #define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" +#define ma_JackNullOption 0 #define ma_JackNoStartServer 1 #define ma_JackPortIsInput 1 #define ma_JackPortIsOutput 2 @@ -31175,7 +32868,7 @@ static ma_result ma_context_open_client__jack(ma_context* pContext, ma_jack_clie maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->jack.jack_client_name_size)(); /* Includes null terminator. */ ma_strncpy_s(clientName, ma_min(sizeof(clientName), maxClientNameSize), (pContext->jack.pClientName != NULL) ? pContext->jack.pClientName : "miniaudio", (size_t)-1); - pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status, NULL); + pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? ma_JackNullOption : ma_JackNoStartServer, &status, NULL); if (pClient == NULL) { return MA_FAILED_TO_OPEN_BACKEND_DEVICE; } @@ -31767,7 +33460,7 @@ static ma_result ma_context_init__jack(ma_context* pContext, const ma_context_co return MA_SUCCESS; } -#endif /* JACK */ +#endif /* MA_HAS_JACK */ @@ -31858,7 +33551,7 @@ that supports this level of detail. There was some public domain sample code I s and AudioUnit APIs, but I couldn't see anything that gave low-level control over device selection and capabilities (the distinction between playback and capture in particular). Therefore, miniaudio is using the AudioObject API. -Most (all?) functions in the AudioObject API take a AudioObjectID as it's input. This is the device identifier. When +Most (all?) functions in the AudioObject API take a AudioObjectID as its input. This is the device identifier. When retrieving global information, such as the device list, you use kAudioObjectSystemObject. When retrieving device-specific data, you pass in the ID for that device. In order to retrieve device-specific IDs you need to enumerate over each of the devices. This is done using the AudioObjectGetPropertyDataSize() and AudioObjectGetPropertyData() APIs which seem to be @@ -32193,6 +33886,12 @@ static ma_result ma_get_channel_map_from_AudioChannelLayout(AudioChannelLayout* #define AUDIO_OBJECT_PROPERTY_ELEMENT kAudioObjectPropertyElementMaster #endif +/* kAudioDevicePropertyScope* were renamed to kAudioObjectPropertyScope* in 10.8. */ +#if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8) +#define kAudioObjectPropertyScopeInput kAudioDevicePropertyScopeInput +#define kAudioObjectPropertyScopeOutput kAudioDevicePropertyScopeOutput +#endif + static ma_result ma_get_device_object_ids__coreaudio(ma_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs) /* NOTE: Free the returned buffer with ma_free(). */ { AudioObjectPropertyAddress propAddressDevices; @@ -32782,7 +34481,7 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec desiredSampleRate = sampleRate; if (desiredSampleRate == 0) { - desiredSampleRate = pOrigFormat->mSampleRate; + desiredSampleRate = (ma_uint32)pOrigFormat->mSampleRate; } desiredChannelCount = channels; @@ -33425,7 +35124,7 @@ static OSStatus ma_on_output__coreaudio(void* pUserData, AudioUnitRenderActionFl } } else { /* This is the deinterleaved case. We need to update each buffer in groups of internalChannels. This assumes each buffer is the same size. */ - MA_ASSERT(pDevice->playback.internalChannels <= MA_MAX_CHANNELS); /* This should heve been validated at initialization time. */ + MA_ASSERT(pDevice->playback.internalChannels <= MA_MAX_CHANNELS); /* This should have been validated at initialization time. */ /* For safety we'll check that the internal channels is a multiple of the buffer count. If it's not it means something @@ -33516,11 +35215,12 @@ static OSStatus ma_on_input__coreaudio(void* pUserData, AudioUnitRenderActionFla */ for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) { pRenderedBufferList->mBuffers[iBuffer].mDataByteSize = pDevice->coreaudio.audioBufferCapInFrames * ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pRenderedBufferList->mBuffers[iBuffer].mNumberChannels; + /*printf("DEBUG: nDataByteSize = %d\n", (int)pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);*/ } status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList); if (status != noErr) { - ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, " ERROR: AudioUnitRender() failed with %d.\n", (int)status); + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "ERROR: AudioUnitRender() failed with %d.\n", (int)status); return status; } @@ -33756,7 +35456,7 @@ static ma_result ma_context__init_device_tracking__coreaudio(ma_context* pContex ma_spinlock_lock(&g_DeviceTrackingInitLock_CoreAudio); { - /* Don't do anything if we've already initializd device tracking. */ + /* Don't do anything if we've already initialized device tracking. */ if (g_DeviceTrackingInitCounter_CoreAudio == 0) { AudioObjectPropertyAddress propAddress; propAddress.mScope = kAudioObjectPropertyScopeGlobal; @@ -34068,11 +35768,11 @@ typedef struct static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_init_internal_data__coreaudio* pData, void* pDevice_DoNotReference) /* <-- pDevice is typed as void* intentionally so as to avoid accidentally referencing it. */ { - ma_result result; + ma_result result = MA_SUCCESS; OSStatus status; UInt32 enableIOFlag; AudioStreamBasicDescription bestFormat; - UInt32 actualPeriodSizeInFrames; + ma_uint32 actualPeriodSizeInFrames; AURenderCallbackStruct callbackInfo; #if defined(MA_APPLE_DESKTOP) AudioObjectID deviceObjectID; @@ -34224,7 +35924,7 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev returning a result code of -10863. I have also tried changing the format directly on the input scope on the input bus, but this just results in `ca_require: IsStreamFormatWritable(inScope, inElement) NotWritable` when trying to set the format. - Something that does seem to work, however, has been setting the nominal sample rate on the deivce object. The problem with + Something that does seem to work, however, has been setting the nominal sample rate on the device object. The problem with this, however, is that it actually changes the sample rate at the operating system level and not just the application. This could be intrusive to the user, however, so I don't think it's wise to make this the default. Instead I'm making this a configuration option. When the `coreaudio.allowNominalSampleRateChange` config option is set to true, changing the sample @@ -34275,15 +35975,28 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev /* I've had a report that the channel count returned by AudioUnitGetProperty above is inconsistent with AVAudioSession outputNumberOfChannels. I'm going to try using the AVAudioSession values instead. + + UPDATE 20/02/2025: + When testing on the simulator with an iPhone 15 and iOS 17 I get an error when initializing the audio + unit if set the input channels to pAudioSession.inputNumberOfChannels. What is happening is the channel + count returned from AudioUnitGetProperty() above is set to 2, but pAudioSession is reporting a channel + count of 1. When this happens, the call to AudioUnitSetProprty() below just down below will succeed, but + AudioUnitInitialize() further down will fail. The only solution I have come up with is to not set the + channel count to pAudioSession.inputNumberOfChannels. */ if (deviceType == ma_device_type_playback) { bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.outputNumberOfChannels; } + + #if 0 if (deviceType == ma_device_type_capture) { + /*printf("DEBUG: bestFormat.mChannelsPerFrame = %d; pAudioSession.inputNumberOfChannels = %d\n", (int)bestFormat.mChannelsPerFrame, (int)pAudioSession.inputNumberOfChannels);*/ bestFormat.mChannelsPerFrame = (UInt32)pAudioSession.inputNumberOfChannels; } + #endif } + status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, sizeof(bestFormat)); if (status != noErr) { ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit); @@ -34303,7 +36016,7 @@ static ma_result ma_device_init_internal__coreaudio(ma_context* pContext, ma_dev } pData->channelsOut = bestFormat.mChannelsPerFrame; - pData->sampleRateOut = bestFormat.mSampleRate; + pData->sampleRateOut = (ma_uint32)bestFormat.mSampleRate; } /* Clamp the channel count for safety. */ @@ -34610,7 +36323,7 @@ static ma_result ma_device_init__coreaudio(ma_device* pDevice, const ma_device_c ma_get_AudioObject_uid(pDevice->pContext, pDevice->coreaudio.deviceObjectIDCapture, sizeof(pDevice->capture.id.coreaudio), pDevice->capture.id.coreaudio); /* - If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly + If we are using the default device we'll need to listen for changes to the system's default device so we can seamlessly switch the device in the background. */ if (pConfig->capture.pDeviceID == NULL) { @@ -34674,7 +36387,7 @@ static ma_result ma_device_init__coreaudio(ma_device* pDevice, const ma_device_c ma_get_AudioObject_uid(pDevice->pContext, pDevice->coreaudio.deviceObjectIDPlayback, sizeof(pDevice->playback.id.coreaudio), pDevice->playback.id.coreaudio); /* - If we are using the default device we'll need to listen for changes to the system's default device so we can seemlessly + If we are using the default device we'll need to listen for changes to the system's default device so we can seamlessly switch the device in the background. */ if (pDescriptorPlayback->pDeviceID == NULL && (pConfig->deviceType != ma_device_type_duplex || pDescriptorCapture->pDeviceID != NULL)) { @@ -34992,7 +36705,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte return MA_SUCCESS; } -#endif /* Core Audio */ +#endif /* MA_HAS_COREAUDIO */ @@ -35484,7 +37197,7 @@ static ma_result ma_device_uninit__sndio(ma_device* pDevice) ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handleCapture); } - if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) { + if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback); } @@ -35839,7 +37552,7 @@ static ma_result ma_context_init__sndio(ma_context* pContext, const ma_context_c (void)pConfig; return MA_SUCCESS; } -#endif /* sndio */ +#endif /* MA_HAS_SNDIO */ @@ -35857,6 +37570,10 @@ audio(4) Backend #include #include +#ifdef __NetBSD__ +#include +#endif + #if defined(__OpenBSD__) #include #if defined(OpenBSD) && OpenBSD >= 201709 @@ -36076,9 +37793,15 @@ static ma_result ma_context_get_device_info_from_fd__audio4(ma_context* pContext ma_uint32 channels; ma_uint32 sampleRate; +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) + if (ioctl(fd, AUDIO_GETFORMAT, &fdInfo) < 0) { + return MA_ERROR; + } +#else if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) { return MA_ERROR; } +#endif if (deviceType == ma_device_type_playback) { channels = fdInfo.play.channels; @@ -36356,7 +38079,11 @@ static ma_result ma_device_init_fd__audio4(ma_device* pDevice, const ma_device_c /* We're using a default device. Get the info from the /dev/audioctl file instead of /dev/audio. */ int fdctl = open(pDefaultDeviceCtlNames[iDefaultDevice], fdFlags, 0); if (fdctl != -1) { +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) + fdInfoResult = ioctl(fdctl, AUDIO_GETFORMAT, &fdInfo); +#else fdInfoResult = ioctl(fdctl, AUDIO_GETINFO, &fdInfo); +#endif close(fdctl); } } @@ -36723,7 +38450,7 @@ static ma_result ma_context_init__audio4(ma_context* pContext, const ma_context_ return MA_SUCCESS; } -#endif /* audio4 */ +#endif /* MA_HAS_AUDIO4 */ /****************************************************************************** @@ -36743,7 +38470,7 @@ OSS Backend #define MA_OSS_DEFAULT_DEVICE_NAME "/dev/dsp" -static int ma_open_temp_device__oss() +static int ma_open_temp_device__oss(void) { /* The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same. */ int fd = open("/dev/mixer", O_RDONLY, 0); @@ -37086,7 +38813,7 @@ static ma_result ma_device_init_fd__oss(ma_device* pDevice, const ma_device_conf } /* - The OSS documantation is very clear about the order we should be initializing the device's properties: + The OSS documentation is very clear about the order we should be initializing the device's properties: 1) Format 2) Channels 3) Sample rate. @@ -37354,7 +39081,7 @@ static ma_result ma_context_init__oss(ma_context* pContext, const ma_context_con return MA_SUCCESS; } -#endif /* OSS */ +#endif /* MA_HAS_OSS */ @@ -37367,7 +39094,9 @@ AAudio Backend ******************************************************************************/ #ifdef MA_HAS_AAUDIO -/*#include */ +#ifdef MA_NO_RUNTIME_LINKING + #include +#endif typedef int32_t ma_aaudio_result_t; typedef int32_t ma_aaudio_direction_t; @@ -37580,28 +39309,31 @@ static void ma_stream_error_callback__aaudio(ma_AAudioStream* pStream, void* pUs MA_ASSERT(pDevice != NULL); (void)error; - ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] ERROR CALLBACK: error=%d, AAudioStream_getState()=%d\n", error, ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream)); - + /* When we get an error, we'll assume that the stream is in an erroneous state and needs to be restarted. From the documentation, we cannot do this from the error callback. Therefore we are going to use an event thread for the AAudio backend to do this cleanly and safely. */ - job = ma_job_init(MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE); - job.data.device.aaudio.reroute.pDevice = pDevice; - - if (pStream == pDevice->aaudio.pStreamCapture) { - job.data.device.aaudio.reroute.deviceType = ma_device_type_capture; + if (ma_atomic_bool32_get(&pDevice->aaudio.isTearingDown)) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Tearing down device.\n"); } else { - job.data.device.aaudio.reroute.deviceType = ma_device_type_playback; - } - - result = ma_device_job_thread_post(&pDevice->pContext->aaudio.jobThread, &job); - if (result != MA_SUCCESS) { - ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Failed to post job for rerouting.\n"); - return; + job = ma_job_init(MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE); + job.data.device.aaudio.reroute.pDevice = pDevice; + + if (pStream == pDevice->aaudio.pStreamCapture) { + job.data.device.aaudio.reroute.deviceType = ma_device_type_capture; + } else { + job.data.device.aaudio.reroute.deviceType = ma_device_type_playback; + } + + result = ma_device_job_thread_post(&pDevice->pContext->aaudio.jobThread, &job); + if (result != MA_SUCCESS) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Failed to post job for rerouting.\n"); + return; + } } } @@ -37610,7 +39342,9 @@ static ma_aaudio_data_callback_result_t ma_stream_data_callback_capture__aaudio( ma_device* pDevice = (ma_device*)pUserData; MA_ASSERT(pDevice != NULL); - ma_device_handle_backend_data_callback(pDevice, NULL, pAudioData, frameCount); + if (frameCount > 0) { + ma_device_handle_backend_data_callback(pDevice, NULL, pAudioData, (ma_uint32)frameCount); + } (void)pStream; return MA_AAUDIO_CALLBACK_RESULT_CONTINUE; @@ -37621,7 +39355,14 @@ static ma_aaudio_data_callback_result_t ma_stream_data_callback_playback__aaudio ma_device* pDevice = (ma_device*)pUserData; MA_ASSERT(pDevice != NULL); - ma_device_handle_backend_data_callback(pDevice, pAudioData, NULL, frameCount); + /* + I've had a report that AAudio can sometimes post a frame count of 0. We need to check for that here + so we don't get any errors at a deeper level. I'm doing the same with the capture side for safety, + though I've not yet had any reports about that one. + */ + if (frameCount > 0) { + ma_device_handle_backend_data_callback(pDevice, pAudioData, NULL, (ma_uint32)frameCount); + } (void)pStream; return MA_AAUDIO_CALLBACK_RESULT_CONTINUE; @@ -37656,32 +39397,25 @@ static ma_result ma_create_and_configure_AAudioStreamBuilder__aaudio(ma_context* ((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pDescriptor->sampleRate); } - if (deviceType == ma_device_type_capture) { - if (pDescriptor->channels != 0) { - ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels); - } - if (pDescriptor->format != ma_format_unknown) { - ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT); - } - } else { - if (pDescriptor->channels != 0) { - ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels); - } - if (pDescriptor->format != ma_format_unknown) { - ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT); - } + if (pDescriptor->channels != 0) { + ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pDescriptor->channels); + } + + if (pDescriptor->format != ma_format_unknown) { + ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pDescriptor->format == ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT); } /* - There have been reports where setting the frames per data callback results in an error - later on from Android. To address this, I'm experimenting with simply not setting it on - anything from Android 11 and earlier. Suggestions welcome on how we might be able to make - this more targetted. + There have been reports where setting the frames per data callback results in an error. + In particular, re-routing may inadvertently switch from low-latency mode, resulting in a less stable + stream from the legacy path (AudioStreamLegacy). To address this, we simply don't set the value. It + can still be set if it's explicitly requested via the aaudio.allowSetBufferCapacity variable in the + device config. */ - if (!pConfig->aaudio.enableCompatibilityWorkarounds || ma_android_sdk_version() > 30) { + if ((!pConfig->aaudio.enableCompatibilityWorkarounds || ma_android_sdk_version() > 30) && pConfig->aaudio.allowSetBufferCapacity) { /* - AAudio is annoying when it comes to it's buffer calculation stuff because it doesn't let you + AAudio is annoying when it comes to its buffer calculation stuff because it doesn't let you retrieve the actual sample rate until after you've opened the stream. But you need to configure the buffer capacity before you open the stream... :/ @@ -37715,7 +39449,11 @@ static ma_result ma_create_and_configure_AAudioStreamBuilder__aaudio(ma_context* ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_playback__aaudio, (void*)pDevice); } - /* Not sure how this affects things, but since there's a mapping between miniaudio's performance profiles and AAudio's performance modes, let go ahead and set it. */ + /* + If we set AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, we allow for MMAP (non-legacy path). + Since there's a mapping between miniaudio's performance profiles and AAudio's performance modes, let's use it. + Beware though, with a conservative performance profile, AAudio will indeed take the legacy path. + */ ((MA_PFN_AAudioStreamBuilder_setPerformanceMode)pContext->aaudio.AAudioStreamBuilder_setPerformanceMode)(pBuilder, (pConfig->performanceProfile == ma_performance_profile_low_latency) ? MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY : MA_AAUDIO_PERFORMANCE_MODE_NONE); /* We need to set an error callback to detect device changes. */ @@ -37751,6 +39489,9 @@ static ma_result ma_open_stream_basic__aaudio(ma_context* pContext, const ma_dev return result; } + /* Let's give AAudio a hint to avoid the legacy path (AudioStreamLegacy). */ + ((MA_PFN_AAudioStreamBuilder_setPerformanceMode)pContext->aaudio.AAudioStreamBuilder_setPerformanceMode)(pBuilder, MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); + return ma_open_stream_and_close_builder__aaudio(pContext, pBuilder, ppStream); } @@ -37775,6 +39516,10 @@ static ma_result ma_open_stream__aaudio(ma_device* pDevice, const ma_device_conf static ma_result ma_close_stream__aaudio(ma_context* pContext, ma_AAudioStream* pStream) { + if (pStream == NULL) { + return MA_INVALID_ARGS; + } + return ma_result_from_aaudio(((MA_PFN_AAudioStream_close)pContext->aaudio.AAudioStream_close)(pStream)); } @@ -37901,20 +39646,42 @@ static ma_result ma_context_get_device_info__aaudio(ma_context* pContext, ma_dev return MA_SUCCESS; } +static ma_result ma_close_streams__aaudio(ma_device* pDevice) +{ + MA_ASSERT(pDevice != NULL); + + /* When rerouting, streams may have been closed and never re-opened. Hence the extra checks below. */ + if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) { + ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture); + pDevice->aaudio.pStreamCapture = NULL; + } + if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { + ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback); + pDevice->aaudio.pStreamPlayback = NULL; + } + + return MA_SUCCESS; +} static ma_result ma_device_uninit__aaudio(ma_device* pDevice) { MA_ASSERT(pDevice != NULL); - if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) { - ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture); - pDevice->aaudio.pStreamCapture = NULL; - } + /* + Note: Closing the streams may cause a timeout error, which would then trigger rerouting in our error callback. + We must not schedule a reroute when device is getting destroyed. + */ + ma_atomic_bool32_set(&pDevice->aaudio.isTearingDown, MA_TRUE); - if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { - ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback); - pDevice->aaudio.pStreamPlayback = NULL; + /* Wait for any rerouting to finish before attempting to close the streams. */ + ma_mutex_lock(&pDevice->aaudio.rerouteLock); + { + ma_close_streams__aaudio(pDevice); } + ma_mutex_unlock(&pDevice->aaudio.rerouteLock); + + /* Destroy rerouting lock. */ + ma_mutex_uninit(&pDevice->aaudio.rerouteLock); return MA_SUCCESS; } @@ -37966,7 +39733,7 @@ static ma_result ma_device_init_by_type__aaudio(ma_device* pDevice, const ma_dev return MA_SUCCESS; } -static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture) +static ma_result ma_device_init_streams__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture) { ma_result result; @@ -37999,6 +39766,25 @@ static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_conf return MA_SUCCESS; } +static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture) +{ + ma_result result; + + MA_ASSERT(pDevice != NULL); + + result = ma_device_init_streams__aaudio(pDevice, pConfig, pDescriptorPlayback, pDescriptorCapture); + if (result != MA_SUCCESS) { + return result; + } + + result = ma_mutex_init(&pDevice->aaudio.rerouteLock); + if (result != MA_SUCCESS) { + return result; + } + + return MA_SUCCESS; +} + static ma_result ma_device_start_stream__aaudio(ma_device* pDevice, ma_AAudioStream* pStream) { ma_aaudio_result_t resultAA; @@ -38006,12 +39792,16 @@ static ma_result ma_device_start_stream__aaudio(ma_device* pDevice, ma_AAudioStr MA_ASSERT(pDevice != NULL); + if (pStream == NULL) { + return MA_INVALID_ARGS; + } + resultAA = ((MA_PFN_AAudioStream_requestStart)pDevice->pContext->aaudio.AAudioStream_requestStart)(pStream); if (resultAA != MA_AAUDIO_OK) { return ma_result_from_aaudio(resultAA); } - /* Do we actually need to wait for the device to transition into it's started state? */ + /* Do we actually need to wait for the device to transition into its started state? */ /* The device should be in either a starting or started state. If it's not set to started we need to wait for it to transition. It should go from starting to started. */ currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream); @@ -38038,6 +39828,10 @@ static ma_result ma_device_stop_stream__aaudio(ma_device* pDevice, ma_AAudioStre MA_ASSERT(pDevice != NULL); + if (pStream == NULL) { + return MA_INVALID_ARGS; + } + /* From the AAudio documentation: @@ -38122,23 +39916,26 @@ static ma_result ma_device_stop__aaudio(ma_device* pDevice) static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type deviceType) { + const ma_int32 maxAttempts = 4; /* Reasonable retry limit. */ + ma_result result; + ma_int32 iAttempt; MA_ASSERT(pDevice != NULL); - /* The first thing to do is close the streams. */ - if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) { - ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture); - pDevice->aaudio.pStreamCapture = NULL; - } + /* We got disconnected! Retry a few times, until we find a connected device! */ + iAttempt = 0; + while (iAttempt++ < maxAttempts) { + /* Device tearing down? No need to reroute! */ + if (ma_atomic_bool32_get(&pDevice->aaudio.isTearingDown)) { + result = MA_SUCCESS; /* Caller should continue as normal. */ + break; + } - if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) { - ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback); - pDevice->aaudio.pStreamPlayback = NULL; - } + /* The first thing to do is close the streams. */ + ma_close_streams__aaudio(pDevice); - /* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */ - { + /* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */ ma_device_config deviceConfig; ma_device_descriptor descriptorPlayback; ma_device_descriptor descriptorCapture; @@ -38187,15 +39984,19 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev descriptorPlayback.periodCount = deviceConfig.periods; } - result = ma_device_init__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture); + result = ma_device_init_streams__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture); if (result != MA_SUCCESS) { - return result; + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change."); + /* Reroute failed! */ + break; } result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture); if (result != MA_SUCCESS) { - ma_device_uninit__aaudio(pDevice); - return result; + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change."); + ma_close_streams__aaudio(pDevice); + /* Reroute failed! */ + break; } /* We'll only ever do this in response to a reroute. */ @@ -38204,14 +40005,26 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev /* If the device is started, start the streams. Maybe make this configurable? */ if (ma_device_get_state(pDevice) == ma_device_state_started) { if (pDevice->aaudio.noAutoStartAfterReroute == MA_FALSE) { - ma_device_start__aaudio(pDevice); + result = ma_device_start__aaudio(pDevice); + if (result != MA_SUCCESS) { + if (iAttempt < maxAttempts) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change, retrying(%d)", iAttempt); + } else { + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change, giving up."); + } + } } else { - ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */ + ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */ } } - return MA_SUCCESS; + if (result == MA_SUCCESS) { + /* Reroute successful! */ + break; + } } + + return result; } static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo) @@ -38222,12 +40035,12 @@ static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type t MA_ASSERT(type != ma_device_type_duplex); MA_ASSERT(pDeviceInfo != NULL); - if (type == ma_device_type_playback) { + if (type == ma_device_type_capture) { pStream = (ma_AAudioStream*)pDevice->aaudio.pStreamCapture; pDeviceInfo->id.aaudio = pDevice->capture.id.aaudio; ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1); /* Only supporting default devices. */ } - if (type == ma_device_type_capture) { + if (type == ma_device_type_playback) { pStream = (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback; pDeviceInfo->id.aaudio = pDevice->playback.id.aaudio; ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1); /* Only supporting default devices. */ @@ -38260,6 +40073,7 @@ static ma_result ma_context_uninit__aaudio(ma_context* pContext) static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks) { +#if !defined(MA_NO_RUNTIME_LINKING) size_t i; const char* libNames[] = { "libaaudio.so" @@ -38305,7 +40119,39 @@ static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_ pContext->aaudio.AAudioStream_getFramesPerBurst = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->aaudio.hAAudio, "AAudioStream_getFramesPerBurst"); pContext->aaudio.AAudioStream_requestStart = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->aaudio.hAAudio, "AAudioStream_requestStart"); pContext->aaudio.AAudioStream_requestStop = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->aaudio.hAAudio, "AAudioStream_requestStop"); - +#else + pContext->aaudio.AAudio_createStreamBuilder = (ma_proc)AAudio_createStreamBuilder; + pContext->aaudio.AAudioStreamBuilder_delete = (ma_proc)AAudioStreamBuilder_delete; + pContext->aaudio.AAudioStreamBuilder_setDeviceId = (ma_proc)AAudioStreamBuilder_setDeviceId; + pContext->aaudio.AAudioStreamBuilder_setDirection = (ma_proc)AAudioStreamBuilder_setDirection; + pContext->aaudio.AAudioStreamBuilder_setSharingMode = (ma_proc)AAudioStreamBuilder_setSharingMode; + pContext->aaudio.AAudioStreamBuilder_setFormat = (ma_proc)AAudioStreamBuilder_setFormat; + pContext->aaudio.AAudioStreamBuilder_setChannelCount = (ma_proc)AAudioStreamBuilder_setChannelCount; + pContext->aaudio.AAudioStreamBuilder_setSampleRate = (ma_proc)AAudioStreamBuilder_setSampleRate; + pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (ma_proc)AAudioStreamBuilder_setBufferCapacityInFrames; + pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (ma_proc)AAudioStreamBuilder_setFramesPerDataCallback; + pContext->aaudio.AAudioStreamBuilder_setDataCallback = (ma_proc)AAudioStreamBuilder_setDataCallback; + pContext->aaudio.AAudioStreamBuilder_setErrorCallback = (ma_proc)AAudioStreamBuilder_setErrorCallback; + pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (ma_proc)AAudioStreamBuilder_setPerformanceMode; + pContext->aaudio.AAudioStreamBuilder_setUsage = (ma_proc)AAudioStreamBuilder_setUsage; + pContext->aaudio.AAudioStreamBuilder_setContentType = (ma_proc)AAudioStreamBuilder_setContentType; + pContext->aaudio.AAudioStreamBuilder_setInputPreset = (ma_proc)AAudioStreamBuilder_setInputPreset; + #if defined(__ANDROID_API__) && __ANDROID_API__ >= 29 + pContext->aaudio.AAudioStreamBuilder_setAllowedCapturePolicy = (ma_proc)AAudioStreamBuilder_setAllowedCapturePolicy; + #endif + pContext->aaudio.AAudioStreamBuilder_openStream = (ma_proc)AAudioStreamBuilder_openStream; + pContext->aaudio.AAudioStream_close = (ma_proc)AAudioStream_close; + pContext->aaudio.AAudioStream_getState = (ma_proc)AAudioStream_getState; + pContext->aaudio.AAudioStream_waitForStateChange = (ma_proc)AAudioStream_waitForStateChange; + pContext->aaudio.AAudioStream_getFormat = (ma_proc)AAudioStream_getFormat; + pContext->aaudio.AAudioStream_getChannelCount = (ma_proc)AAudioStream_getChannelCount; + pContext->aaudio.AAudioStream_getSampleRate = (ma_proc)AAudioStream_getSampleRate; + pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (ma_proc)AAudioStream_getBufferCapacityInFrames; + pContext->aaudio.AAudioStream_getFramesPerDataCallback = (ma_proc)AAudioStream_getFramesPerDataCallback; + pContext->aaudio.AAudioStream_getFramesPerBurst = (ma_proc)AAudioStream_getFramesPerBurst; + pContext->aaudio.AAudioStream_requestStart = (ma_proc)AAudioStream_requestStart; + pContext->aaudio.AAudioStream_requestStop = (ma_proc)AAudioStream_requestStop; +#endif pCallbacks->onContextInit = ma_context_init__aaudio; pCallbacks->onContextUninit = ma_context_uninit__aaudio; @@ -38343,6 +40189,7 @@ static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_ static ma_result ma_job_process__device__aaudio_reroute(ma_job* pJob) { + ma_result result = MA_SUCCESS; ma_device* pDevice; MA_ASSERT(pJob != NULL); @@ -38350,8 +40197,22 @@ static ma_result ma_job_process__device__aaudio_reroute(ma_job* pJob) pDevice = (ma_device*)pJob->data.device.aaudio.reroute.pDevice; MA_ASSERT(pDevice != NULL); - /* Here is where we need to reroute the device. To do this we need to uninitialize the stream and reinitialize it. */ - return ma_device_reinit__aaudio(pDevice, (ma_device_type)pJob->data.device.aaudio.reroute.deviceType); + ma_mutex_lock(&pDevice->aaudio.rerouteLock); + { + /* Here is where we need to reroute the device. To do this we need to uninitialize the stream and reinitialize it. */ + result = ma_device_reinit__aaudio(pDevice, (ma_device_type)pJob->data.device.aaudio.reroute.deviceType); + if (result != MA_SUCCESS) { + /* + Getting here means we failed to reroute the device. The best thing I can think of here is to + just stop the device. + */ + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[AAudio] Stopping device due to reroute failure."); + ma_device_stop(pDevice); + } + } + ma_mutex_unlock(&pDevice->aaudio.rerouteLock); + + return result; } #else /* Getting here means there is no AAudio backend so we need a no-op job implementation. */ @@ -39637,6 +41498,10 @@ Web Audio Backend #if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 32))) #include #define MA_SUPPORT_AUDIO_WORKLETS + + #if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 70))) + #define MA_SUPPORT_AUDIO_WORKLETS_VARIABLE_BUFFER_SIZE + #endif #endif /* @@ -39648,7 +41513,7 @@ TODO: Version 0.12: Swap this logic around so that AudioWorklets are used by def /* The thread stack size must be a multiple of 16. */ #ifndef MA_AUDIO_WORKLETS_THREAD_STACK_SIZE -#define MA_AUDIO_WORKLETS_THREAD_STACK_SIZE 16384 +#define MA_AUDIO_WORKLETS_THREAD_STACK_SIZE 131072 #endif #if defined(MA_USE_AUDIO_WORKLETS) @@ -39774,12 +41639,14 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) #if defined(MA_USE_AUDIO_WORKLETS) { EM_ASM({ - var device = miniaudio.get_device_by_index($0); + var device = window.miniaudio.get_device_by_index($0); if (device.streamNode !== undefined) { device.streamNode.disconnect(); device.streamNode = undefined; } + + device.pDevice = undefined; }, pDevice->webaudio.deviceIndex); emscripten_destroy_web_audio_node(pDevice->webaudio.audioWorklet); @@ -39789,7 +41656,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) #else { EM_ASM({ - var device = miniaudio.get_device_by_index($0); + var device = window.miniaudio.get_device_by_index($0); /* Make sure all nodes are disconnected and marked for collection. */ if (device.scriptNode !== undefined) { @@ -39816,7 +41683,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) /* Clean up the device on the JS side. */ EM_ASM({ - miniaudio.untrack_device_by_index($0); + window.miniaudio.untrack_device_by_index($0); }, pDevice->webaudio.deviceIndex); ma_free(pDevice->webaudio.pIntermediaryBuffer, &pDevice->pContext->allocationCallbacks); @@ -39882,10 +41749,6 @@ static EM_BOOL ma_audio_worklet_process_callback__webaudio(int inputCount, const (void)paramCount; (void)pParams; - if (ma_device_get_state(pDevice) != ma_device_state_started) { - return EM_TRUE; - } - /* The Emscripten documentation says that it'll always be 128 frames being passed in. Hard coding it like that feels like a very bad idea to me. Even if it's hard coded in the backend, the API and documentation should always refer @@ -39894,7 +41757,23 @@ static EM_BOOL ma_audio_worklet_process_callback__webaudio(int inputCount, const Unfortunately the audio data is not interleaved so we'll need to convert it before we give the data to miniaudio for further processing. */ - frameCount = 128; + if (pDevice->type == ma_device_type_playback) { + frameCount = pDevice->playback.internalPeriodSizeInFrames; + } else { + frameCount = pDevice->capture.internalPeriodSizeInFrames; + } + + /* + If this is called by the device has not yet been started we need to return early, making sure we output silence to + the output buffer. + */ + if (ma_device_get_state(pDevice) != ma_device_state_started) { + for (int i = 0; i < outputCount; i += 1) { + MA_ZERO_MEMORY(pOutputs[i].data, pOutputs[i].numberOfChannels * frameCount * sizeof(float)); + } + + return EM_TRUE; + } if (inputCount > 0) { /* Input data needs to be interleaved before we hand it to the client. */ @@ -39910,7 +41789,9 @@ static EM_BOOL ma_audio_worklet_process_callback__webaudio(int inputCount, const if (outputCount > 0) { /* If it's a capture-only device, we'll need to output silence. */ if (pDevice->type == ma_device_type_capture) { - MA_ZERO_MEMORY(pOutputs[0].data, frameCount * pDevice->playback.internalChannels * sizeof(float)); + for (int i = 0; i < outputCount; i += 1) { + MA_ZERO_MEMORY(pOutputs[i].data, pOutputs[i].numberOfChannels * frameCount * sizeof(float)); + } } else { ma_device_process_pcm_frames_playback__webaudio(pDevice, frameCount, pDevice->webaudio.pIntermediaryBuffer); @@ -39920,6 +41801,14 @@ static EM_BOOL ma_audio_worklet_process_callback__webaudio(int inputCount, const pOutputs[0].data[frameCount*iChannel + iFrame] = pDevice->webaudio.pIntermediaryBuffer[iFrame*pDevice->playback.internalChannels + iChannel]; } } + + /* + Just above we output data to the first output buffer. Here we just make sure we're putting silence into any + remaining output buffers. + */ + for (int i = 1; i < outputCount; i += 1) { /* <-- Note that the counter starts at 1 instead of 0. */ + MA_ZERO_MEMORY(pOutputs[i].data, pOutputs[i].numberOfChannels * frameCount * sizeof(float)); + } } } @@ -39949,7 +41838,7 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a count from MediaStreamAudioSourceNode (what we use for capture)? The only way to have control is to configure an output channel count on the capture side. This is slightly confusing for capture mode because intuitively you wouldn't actually connect an output to an input-only node, but this is what we'll have to do in order to have - proper control over the channel count. In the capture case, we'll have to output silence to it's output node. + proper control over the channel count. In the capture case, we'll have to output silence to its output node. */ if (pParameters->pConfig->deviceType == ma_device_type_capture) { channels = (int)((pParameters->pDescriptorCapture->channels > 0) ? pParameters->pDescriptorCapture->channels : MA_DEFAULT_CHANNELS); @@ -39972,7 +41861,15 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a Now that we know the channel count to use we can allocate the intermediary buffer. The intermediary buffer is used for interleaving and deinterleaving. */ - intermediaryBufferSizeInFrames = 128; + #if defined(MA_SUPPORT_AUDIO_WORKLETS_VARIABLE_BUFFER_SIZE) + { + intermediaryBufferSizeInFrames = (size_t)emscripten_audio_context_quantum_size(audioContext); + } + #else + { + intermediaryBufferSizeInFrames = 128; + } + #endif pParameters->pDevice->webaudio.pIntermediaryBuffer = (float*)ma_malloc(intermediaryBufferSizeInFrames * (ma_uint32)channels * sizeof(float), &pParameters->pDevice->pContext->allocationCallbacks); if (pParameters->pDevice->webaudio.pIntermediaryBuffer == NULL) { @@ -39981,7 +41878,6 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a return; } - pParameters->pDevice->webaudio.audioWorklet = emscripten_create_wasm_audio_worklet_node(audioContext, "miniaudio", &audioWorkletOptions, &ma_audio_worklet_process_callback__webaudio, pParameters->pDevice); /* With the audio worklet initialized we can now attach it to the graph. */ @@ -40121,7 +42017,6 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co /* It's not clear if this can return an error. None of the tests in the Emscripten repository check for this, so neither am I for now. */ pDevice->webaudio.audioContext = emscripten_create_audio_context(&audioContextAttributes); - /* With the context created we can now create the worklet. We can only have a single worklet per audio context which means we'll need to craft this appropriately to handle duplex devices correctly. @@ -40170,11 +42065,12 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co /* We need to add an entry to the miniaudio.devices list on the JS side so we can do some JS/C interop. */ pDevice->webaudio.deviceIndex = EM_ASM_INT({ - return miniaudio.track_device({ + return window.miniaudio.track_device({ webaudio: emscriptenGetAudioObject($0), - state: 1 /* 1 = ma_device_state_stopped */ + state: 1, /* 1 = ma_device_state_stopped */ + pDevice: $1 }); - }, pDevice->webaudio.audioContext); + }, pDevice->webaudio.audioContext, pDevice); return MA_SUCCESS; } @@ -40186,7 +42082,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co ma_uint32 sampleRate; ma_uint32 periodSizeInFrames; - /* The channel count will depend on the device type. If it's a capture, use it's, otherwise use the playback side. */ + /* The channel count will depend on the device type. If it's a capture, use its, otherwise use the playback side. */ if (pConfig->deviceType == ma_device_type_capture) { channels = (pDescriptorCapture->channels > 0) ? pDescriptorCapture->channels : MA_DEFAULT_CHANNELS; } else { @@ -40255,11 +42151,11 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co /* The node processing callback. */ device.scriptNode.onaudioprocess = function(e) { if (device.intermediaryBufferView == null || device.intermediaryBufferView.length == 0) { - device.intermediaryBufferView = new Float32Array(Module.HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels); + device.intermediaryBufferView = new Float32Array(HEAPF32.buffer, pIntermediaryBuffer, bufferSize * channels); } /* Do the capture side first. */ - if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) { + if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) { /* The data must be interleaved before being processed miniaudio. */ for (var iChannel = 0; iChannel < channels; iChannel += 1) { var inputBuffer = e.inputBuffer.getChannelData(iChannel); @@ -40273,7 +42169,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co _ma_device_process_pcm_frames_capture__webaudio(pDevice, bufferSize, pIntermediaryBuffer); } - if (deviceType == miniaudio.device_type.playback || deviceType == miniaudio.device_type.duplex) { + if (deviceType == window.miniaudio.device_type.playback || deviceType == window.miniaudio.device_type.duplex) { _ma_device_process_pcm_frames_playback__webaudio(pDevice, bufferSize, pIntermediaryBuffer); for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) { @@ -40293,7 +42189,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co }; /* Now we need to connect our node to the graph. */ - if (deviceType == miniaudio.device_type.capture || deviceType == miniaudio.device_type.duplex) { + if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) { navigator.mediaDevices.getUserMedia({audio:true, video:false}) .then(function(stream) { device.streamNode = device.webaudio.createMediaStreamSource(stream); @@ -40305,13 +42201,13 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co }); } - if (deviceType == miniaudio.device_type.playback) { + if (deviceType == window.miniaudio.device_type.playback) { device.scriptNode.connect(device.webaudio.destination); } device.pDevice = pDevice; - return miniaudio.track_device(device); + return window.miniaudio.track_device(device); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); if (deviceIndex < 0) { @@ -40321,7 +42217,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co pDevice->webaudio.deviceIndex = deviceIndex; /* Grab the sample rate from the audio context directly. */ - sampleRate = (ma_uint32)EM_ASM_INT({ return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex); + sampleRate = (ma_uint32)EM_ASM_INT({ return window.miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex); if (pDescriptorCapture != NULL) { pDescriptorCapture->format = ma_format_f32; @@ -40351,9 +42247,9 @@ static ma_result ma_device_start__webaudio(ma_device* pDevice) MA_ASSERT(pDevice != NULL); EM_ASM({ - var device = miniaudio.get_device_by_index($0); + var device = window.miniaudio.get_device_by_index($0); device.webaudio.resume(); - device.state = miniaudio.device_state.started; + device.state = window.miniaudio.device_state.started; }, pDevice->webaudio.deviceIndex); return MA_SUCCESS; @@ -40373,9 +42269,9 @@ static ma_result ma_device_stop__webaudio(ma_device* pDevice) do any kind of explicit draining. */ EM_ASM({ - var device = miniaudio.get_device_by_index($0); + var device = window.miniaudio.get_device_by_index($0); device.webaudio.suspend(); - device.state = miniaudio.device_state.stopped; + device.state = window.miniaudio.device_state.stopped; }, pDevice->webaudio.deviceIndex); ma_device__on_notification_stopped(pDevice); @@ -40393,6 +42289,10 @@ static ma_result ma_context_uninit__webaudio(ma_context* pContext) /* Remove the global miniaudio object from window if there are no more references to it. */ EM_ASM({ if (typeof(window.miniaudio) !== 'undefined') { + window.miniaudio.unlock_event_types.map(function(event_type) { + document.removeEventListener(event_type, window.miniaudio.unlock, true); + }); + window.miniaudio.referenceCount -= 1; if (window.miniaudio.referenceCount === 0) { delete window.miniaudio; @@ -40434,6 +42334,7 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex window.miniaudio.device_state.started = $4; /* Device cache for mapping devices to indexes for JavaScript/C interop. */ + let miniaudio = window.miniaudio; miniaudio.devices = []; miniaudio.track_device = function(device) { @@ -40485,13 +42386,13 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex var device = miniaudio.devices[i]; if (device != null && device.webaudio != null && - device.state === window.miniaudio.device_state.started) { + device.state === miniaudio.device_state.started) { device.webaudio.resume().then(() => { - Module._ma_device__on_notification_unlocked(device.pDevice); - }, - (error) => {console.error("Failed to resume audiocontext", error); - }); + _ma_device__on_notification_unlocked(device.pDevice); + }, + (error) => {console.error("Failed to resume audiocontext", error); + }); } } miniaudio.unlock_event_types.map(function(event_type) { @@ -40527,7 +42428,7 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex return MA_SUCCESS; } -#endif /* Web Audio */ +#endif /* MA_HAS_WEBAUDIO */ @@ -40806,7 +42707,7 @@ MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceTy ma_device_info deviceInfo; if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex || deviceType == ma_device_type_loopback) { - result = ma_device_get_info(pDevice, (deviceType == ma_device_type_loopback) ? ma_device_type_playback : ma_device_type_capture, &deviceInfo); + result = ma_device_get_info(pDevice, ma_device_type_capture, &deviceInfo); if (result == MA_SUCCESS) { ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), deviceInfo.name, (size_t)-1); } else { @@ -40842,18 +42743,18 @@ MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceTy static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData) { ma_device* pDevice = (ma_device*)pData; -#ifdef MA_WIN32 +#if defined(MA_WIN32) && !defined(MA_XBOX) HRESULT CoInitializeResult; #endif MA_ASSERT(pDevice != NULL); -#ifdef MA_WIN32 +#if defined(MA_WIN32) && !defined(MA_XBOX) CoInitializeResult = ma_CoInitializeEx(pDevice->pContext, NULL, MA_COINIT_VALUE); #endif /* - When the device is being initialized it's initial state is set to ma_device_state_uninitialized. Before returning from + When the device is being initialized its initial state is set to ma_device_state_uninitialized. Before returning from ma_device_init(), the state needs to be set to something valid. In miniaudio the device's default state immediately after initialization is stopped, so therefore we need to mark the device as such. miniaudio will wait on the worker thread to signal an event to know when the worker thread is ready for action. @@ -40939,8 +42840,8 @@ static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData) ma_event_signal(&pDevice->stopEvent); } -#ifdef MA_WIN32 - if (CoInitializeResult == S_OK) { +#if defined(MA_WIN32) && !defined(MA_XBOX) + if (CoInitializeResult == S_OK || CoInitializeResult == S_FALSE) { ma_CoUninitialize(pDevice->pContext); } #endif @@ -40964,67 +42865,92 @@ static ma_bool32 ma_device__is_initialized(ma_device* pDevice) static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext) { /* For some reason UWP complains when CoUninitialize() is called. I'm just not going to call it on UWP. */ -#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) - if (pContext->win32.CoInitializeResult == S_OK) { - ma_CoUninitialize(pContext); + #if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) + { + /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */ + #if !defined(MA_XBOX) + { + if (pContext->win32.CoInitializeResult == S_OK || pContext->win32.CoInitializeResult == S_FALSE) { + ma_CoUninitialize(pContext); /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */ + } + } + #endif + + #if defined(MA_WIN32_DESKTOP) + ma_dlclose(ma_context_get_log(pContext), pContext->win32.hUser32DLL); + ma_dlclose(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL); + #endif + + ma_dlclose(ma_context_get_log(pContext), pContext->win32.hOle32DLL); + } + #else + { + (void)pContext; } - - #if defined(MA_WIN32_DESKTOP) - ma_dlclose(ma_context_get_log(pContext), pContext->win32.hUser32DLL); - ma_dlclose(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL); #endif - ma_dlclose(ma_context_get_log(pContext), pContext->win32.hOle32DLL); -#else - (void)pContext; -#endif - return MA_SUCCESS; } static ma_result ma_context_init_backend_apis__win32(ma_context* pContext) { -#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK) - #if defined(MA_WIN32_DESKTOP) - /* User32.dll */ - pContext->win32.hUser32DLL = ma_dlopen(ma_context_get_log(pContext), "user32.dll"); - if (pContext->win32.hUser32DLL == NULL) { + /* + TODO: Reassess all of this stuff and move everything to the relevant backends. For example, I think + GetForegroundWindow() and GetDesktopWindow() are only used by the DirectSound backend. + */ + #if (defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)) && !defined(MA_XBOX) + { + #if defined(MA_WIN32_DESKTOP) + { + /* User32.dll */ + pContext->win32.hUser32DLL = ma_dlopen(ma_context_get_log(pContext), "user32.dll"); + if (pContext->win32.hUser32DLL == NULL) { + return MA_FAILED_TO_INIT_BACKEND; + } + + pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetForegroundWindow"); + pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetDesktopWindow"); + + + /* Advapi32.dll */ + pContext->win32.hAdvapi32DLL = ma_dlopen(ma_context_get_log(pContext), "advapi32.dll"); + if (pContext->win32.hAdvapi32DLL == NULL) { + return MA_FAILED_TO_INIT_BACKEND; + } + + pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegOpenKeyExA"); + pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegCloseKey"); + pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegQueryValueExA"); + } + #endif + + /* Ole32.dll */ + pContext->win32.hOle32DLL = ma_dlopen(ma_context_get_log(pContext), "ole32.dll"); + if (pContext->win32.hOle32DLL == NULL) { return MA_FAILED_TO_INIT_BACKEND; } - pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetForegroundWindow"); - pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetDesktopWindow"); - - - /* Advapi32.dll */ - pContext->win32.hAdvapi32DLL = ma_dlopen(ma_context_get_log(pContext), "advapi32.dll"); - if (pContext->win32.hAdvapi32DLL == NULL) { - return MA_FAILED_TO_INIT_BACKEND; - } - - pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegOpenKeyExA"); - pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegCloseKey"); - pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegQueryValueExA"); + pContext->win32.CoInitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitialize"); + pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitializeEx"); + pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoUninitialize"); + pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoCreateInstance"); + pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoTaskMemFree"); + pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "PropVariantClear"); + pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "StringFromGUID2"); + } + #else + { + (void)pContext; /* Unused. */ + } #endif - /* Ole32.dll */ - pContext->win32.hOle32DLL = ma_dlopen(ma_context_get_log(pContext), "ole32.dll"); - if (pContext->win32.hOle32DLL == NULL) { - return MA_FAILED_TO_INIT_BACKEND; + /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */ + #if !defined(MA_XBOX) + { + pContext->win32.CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE); } + #endif - pContext->win32.CoInitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitialize"); - pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitializeEx"); - pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoUninitialize"); - pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoCreateInstance"); - pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoTaskMemFree"); - pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "PropVariantClear"); - pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "StringFromGUID2"); -#else - (void)pContext; /* Unused. */ -#endif - - pContext->win32.CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE); return MA_SUCCESS; } #else @@ -41198,6 +43124,24 @@ MA_API ma_result ma_device_job_thread_next(ma_device_job_thread* pJobThread, ma_ } +MA_API ma_bool32 ma_device_id_equal(const ma_device_id* pA, const ma_device_id* pB) +{ + size_t i; + + if (pA == NULL || pB == NULL) { + return MA_FALSE; + } + + for (i = 0; i < sizeof(ma_device_id); i += 1) { + if (((const char*)pA)[i] != ((const char*)pB)[i]) { + return MA_FALSE; + } + } + + return MA_TRUE; +} + + MA_API ma_context_config ma_context_config_init(void) { @@ -41971,7 +43915,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC return result; } - /* Wait for the worker thread to put the device into it's stopped state for real. */ + /* Wait for the worker thread to put the device into its stopped state for real. */ ma_event_wait(&pDevice->stopEvent); MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped); } else { @@ -41997,7 +43941,7 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[%s]\n", ma_get_backend_name(pDevice->pContext->backend)); if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) { char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; - ma_device_get_name(pDevice, (pDevice->type == ma_device_type_loopback) ? ma_device_type_playback : ma_device_type_capture, name, sizeof(name), NULL); + ma_device_get_name(pDevice, ma_device_type_capture, name, sizeof(name), NULL); ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", name, "Capture"); ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Format: %s -> %s\n", ma_get_format_name(pDevice->capture.internalFormat), ma_get_format_name(pDevice->capture.format)); @@ -42250,6 +44194,17 @@ MA_API ma_result ma_device_get_info(ma_device* pDevice, ma_device_type type, ma_ if (type == ma_device_type_playback) { return ma_context_get_device_info(pDevice->pContext, type, pDevice->playback.pID, pDeviceInfo); } else { + /* + Here we're getting the capture side, which is the branch we'll be entering for a loopback + device, since loopback is capturing. However, if the device is using the default device ID, + it won't get the correct information because it'll think we're asking for the default + capture device, where in fact for loopback we want the default *playback* device. We'll do + a bit of a hack here to make sure we get the correct info. + */ + if (pDevice->type == ma_device_type_loopback && pDevice->capture.pID == NULL) { + type = ma_device_type_playback; + } + return ma_context_get_device_info(pDevice->pContext, type, pDevice->capture.pID, pDeviceInfo); } } @@ -42311,6 +44266,15 @@ MA_API ma_result ma_device_start(ma_device* pDevice) ma_mutex_lock(&pDevice->startStopLock); { + /* + We need to check again if the device is in a started state because it's possible for one thread to have started the device + while another was waiting on the mutex. + */ + if (ma_device_get_state(pDevice) == ma_device_state_started) { + ma_mutex_unlock(&pDevice->startStopLock); + return MA_SUCCESS; /* Already started. */ + } + /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */ MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped); @@ -42371,6 +44335,15 @@ MA_API ma_result ma_device_stop(ma_device* pDevice) ma_mutex_lock(&pDevice->startStopLock); { + /* + We need to check again if the device is in a stopped state because it's possible for one thread to have stopped the device + while another was waiting on the mutex. + */ + if (ma_device_get_state(pDevice) == ma_device_state_stopped) { + ma_mutex_unlock(&pDevice->startStopLock); + return MA_SUCCESS; /* Already stopped. */ + } + /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */ MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_started); @@ -42389,7 +44362,7 @@ MA_API ma_result ma_device_stop(ma_device* pDevice) } else { /* Synchronous backends. The stop callback is always called from the worker thread. Do not call the stop callback here. If - the backend is implementing it's own audio thread loop we'll need to wake it up if required. Note that we need to make + the backend is implementing its own audio thread loop we'll need to wake it up if required. Note that we need to make sure the state of the device is *not* playing right now, which it shouldn't be since we set it above. This is super important though, so I'm asserting it here as well for extra safety in case we accidentally change something later. */ @@ -42506,6 +44479,15 @@ MA_API ma_result ma_device_handle_backend_data_callback(ma_device* pDevice, void return MA_INVALID_ARGS; } + /* + There is an assert deeper in the code that checks that frameCount > 0. Since this is a public facing + API we'll need to check for that here. I've had reports that AAudio can sometimes post a frame count + of 0. + */ + if (frameCount == 0) { + return MA_INVALID_ARGS; + } + if (pDevice->type == ma_device_type_duplex) { if (pInput != NULL) { ma_device__handle_duplex_callback_capture(pDevice, frameCount, pInput, &pDevice->duplexRB.rb); @@ -42580,7 +44562,7 @@ MA_API ma_uint32 ma_calculate_buffer_size_in_milliseconds_from_frames(ma_uint32 return 0; } - return bufferSizeInFrames*1000 / sampleRate; + return (bufferSizeInFrames*1000 + (sampleRate - 1)) / sampleRate; } MA_API ma_uint32 ma_calculate_buffer_size_in_frames_from_milliseconds(ma_uint32 bufferSizeInMilliseconds, ma_uint32 sampleRate) @@ -43566,7 +45548,7 @@ static MA_INLINE void ma_pcm_s16_to_s32__reference(void* dst, const void* src, m ma_uint64 i; for (i = 0; i < count; i += 1) { - dst_s32[i] = src_s16[i] << 16; + dst_s32[i] = (ma_int32)src_s16[i] << 16; } (void)ditherMode; @@ -47408,7 +49390,7 @@ static ma_result ma_bpf_get_heap_layout(const ma_bpf_config* pConfig, ma_bpf_hea return MA_INVALID_ARGS; } - bpf2Count = pConfig->channels / 2; + bpf2Count = pConfig->order / 2; pHeapLayout->sizeInBytes = 0; @@ -48897,15 +50879,15 @@ static /*__attribute__((noinline))*/ ma_result ma_gainer_process_pcm_frames_inte a += d; } } + + pFramesOut = ma_offset_ptr(pFramesOut, interpolatedFrameCount * sizeof(float)); + pFramesIn = ma_offset_ptr(pFramesIn, interpolatedFrameCount * sizeof(float)); } + frameCount -= interpolatedFrameCount; + /* Make sure the timer is updated. */ pGainer->t = (ma_uint32)ma_min(pGainer->t + interpolatedFrameCount, pGainer->config.smoothTimeInFrames); - - /* Adjust our arguments so the next part can work normally. */ - frameCount -= interpolatedFrameCount; - pFramesOut = ma_offset_ptr(pFramesOut, interpolatedFrameCount * sizeof(float)); - pFramesIn = ma_offset_ptr(pFramesIn, interpolatedFrameCount * sizeof(float)); } /* All we need to do here is apply the new gains using an optimized path. */ @@ -49466,7 +51448,7 @@ MA_API float ma_fader_get_current_volume(const ma_fader* pFader) } else if ((ma_uint64)pFader->cursorInFrames >= pFader->lengthInFrames) { /* Safe case because the < 0 case was checked above. */ return pFader->volumeEnd; } else { - /* The cursor is somewhere inside the fading period. We can figure this out with a simple linear interpoluation between volumeBeg and volumeEnd based on our cursor position. */ + /* The cursor is somewhere inside the fading period. We can figure this out with a simple linear interpolation between volumeBeg and volumeEnd based on our cursor position. */ return ma_mix_f32_fast(pFader->volumeBeg, pFader->volumeEnd, (ma_uint32)pFader->cursorInFrames / (float)((ma_uint32)pFader->lengthInFrames)); /* Safe cast to uint32 because we clamp it in ma_fader_process_pcm_frames(). */ } } @@ -49689,9 +51671,9 @@ static float ma_attenuation_exponential(float distance, float minDistance, float /* -Dopper Effect calculation taken from the OpenAL spec, with two main differences: +Doppler Effect calculation taken from the OpenAL spec, with two main differences: - 1) The source to listener vector will have already been calcualted at an earlier step so we can + 1) The source to listener vector will have already been calculated at an earlier step so we can just use that directly. We need only the position of the source relative to the origin. 2) We don't scale by a frequency because we actually just want the ratio which we'll plug straight @@ -49730,7 +51712,7 @@ static void ma_get_default_channel_map_for_spatializer(ma_channel* pChannelMap, Special case for stereo. Want to default the left and right speakers to side left and side right so that they're facing directly down the X axis rather than slightly forward. Not doing this will result in sounds being quieter when behind the listener. This might - actually be good for some scenerios, but I don't think it's an appropriate default because + actually be good for some scenarios, but I don't think it's an appropriate default because it can be a bit unexpected. */ if (channelCount == 2) { @@ -50064,7 +52046,7 @@ MA_API ma_spatializer_config ma_spatializer_config_init(ma_uint32 channelsIn, ma config.maxDistance = MA_FLT_MAX; config.rolloff = 1; config.coneInnerAngleInRadians = 6.283185f; /* 360 degrees. */ - config.coneOuterAngleInRadians = 6.283185f; /* 360 degress. */ + config.coneOuterAngleInRadians = 6.283185f; /* 360 degrees. */ config.coneOuterGain = 0.0f; config.dopplerFactor = 1; config.directionalAttenuationFactor = 1; @@ -50298,7 +52280,7 @@ static float ma_calculate_angular_gain(ma_vec3f dirA, ma_vec3f dirB, float coneI To do cone attenuation, I'm just using the same math that we'd use to implement a basic spotlight in OpenGL. We just need to get the direction from the source to the listener and then do a dot product against that and the direction of the spotlight. Then we just compare that dot product against the cosine of the inner and outer - angles. If the dot product is greater than the the outer angle, we just use coneOuterGain. If it's less than + angles. If the dot product is greater than the outer angle, we just use coneOuterGain. If it's less than the inner angle, we just use a gain of 1. Otherwise we linearly interpolate between 1 and coneOuterGain. */ if (coneInnerAngleInRadians < 6.283185f) { @@ -50333,13 +52315,16 @@ static float ma_calculate_angular_gain(ma_vec3f dirA, ma_vec3f dirB, float coneI MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, ma_spatializer_listener* pListener, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount) { - ma_channel* pChannelMapIn = pSpatializer->pChannelMapIn; - ma_channel* pChannelMapOut = pListener->config.pChannelMapOut; + ma_channel* pChannelMapIn; + ma_channel* pChannelMapOut; - if (pSpatializer == NULL) { + if (pSpatializer == NULL || pListener == NULL) { return MA_INVALID_ARGS; } + pChannelMapIn = pSpatializer->pChannelMapIn; + pChannelMapOut = pListener->config.pChannelMapOut; + /* If we're not spatializing we need to run an optimized path. */ if (ma_atomic_load_i32(&pSpatializer->attenuationModel) == ma_attenuation_model_none) { if (ma_spatializer_listener_is_enabled(pListener)) { @@ -50368,7 +52353,7 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, ma_vec3f relativePosNormalized; ma_vec3f relativePos; /* The position relative to the listener. */ ma_vec3f relativeDir; /* The direction of the sound, relative to the listener. */ - ma_vec3f listenerVel; /* The volocity of the listener. For doppler pitch calculation. */ + ma_vec3f listenerVel; /* The velocity of the listener. For doppler pitch calculation. */ float speedOfSound; float distance = 0; float gain = 1; @@ -50384,23 +52369,17 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, We'll need the listener velocity for doppler pitch calculations. The speed of sound is defined by the listener, so we'll grab that here too. */ - if (pListener != NULL) { - listenerVel = ma_spatializer_listener_get_velocity(pListener); - speedOfSound = pListener->config.speedOfSound; - } else { - listenerVel = ma_vec3f_init_3f(0, 0, 0); - speedOfSound = MA_DEFAULT_SPEED_OF_SOUND; - } + listenerVel = ma_spatializer_listener_get_velocity(pListener); + speedOfSound = pListener->config.speedOfSound; - if (pListener == NULL || ma_spatializer_get_positioning(pSpatializer) == ma_positioning_relative) { - /* There's no listener or we're using relative positioning. */ + if (ma_spatializer_get_positioning(pSpatializer) == ma_positioning_relative) { relativePos = ma_spatializer_get_position(pSpatializer); relativeDir = ma_spatializer_get_direction(pSpatializer); } else { /* - We've found a listener and we're using absolute positioning. We need to transform the - sound's position and direction so that it's relative to listener. Later on we'll use - this for determining the factors to apply to each channel to apply the panning effect. + We're using absolute positioning. We need to transform the sound's position and + direction so that it's relative to listener. Later on we'll use this for determining + the factors to apply to each channel to apply the panning effect. */ ma_spatializer_get_relative_position_and_direction(pSpatializer, pListener, &relativePos, &relativeDir); } @@ -50449,11 +52428,11 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, To do cone attenuation, I'm just using the same math that we'd use to implement a basic spotlight in OpenGL. We just need to get the direction from the source to the listener and then do a dot product against that and the direction of the spotlight. Then we just compare that dot product against the cosine of the inner and outer - angles. If the dot product is greater than the the outer angle, we just use coneOuterGain. If it's less than + angles. If the dot product is greater than the outer angle, we just use coneOuterGain. If it's less than the inner angle, we just use a gain of 1. Otherwise we linearly interpolate between 1 and coneOuterGain. */ if (distance > 0) { - /* Source anglular gain. */ + /* Source angular gain. */ float spatializerConeInnerAngle; float spatializerConeOuterAngle; float spatializerConeOuterGain; @@ -50965,7 +52944,7 @@ MA_API void ma_spatializer_get_relative_position_and_direction(const ma_spatiali listenerDirection = ma_spatializer_listener_get_direction(pListener); /* - We need to calcualte the right vector from our forward and up vectors. This is done with + We need to calculate the right vector from our forward and up vectors. This is done with a cross product. */ axisZ = ma_vec3f_normalize(listenerDirection); /* Normalization required here because we can't trust the caller. */ @@ -51111,7 +53090,7 @@ static ma_result ma_linear_resampler_set_rate_internal(ma_linear_resampler* pRes lpfConfig = ma_lpf_config_init(pResampler->config.format, pResampler->config.channels, lpfSampleRate, lpfCutoffFrequency, pResampler->config.lpfOrder); /* - If the resampler is alreay initialized we don't want to do a fresh initialization of the low-pass filter because it will result in the cached frames + If the resampler is already initialized we don't want to do a fresh initialization of the low-pass filter because it will result in the cached frames getting cleared. Instead we re-initialize the filter which will maintain any cached frames. */ if (isResamplerAlreadyInitialized) { @@ -51806,7 +53785,7 @@ MA_API ma_result ma_linear_resampler_get_expected_output_frame_count(const ma_li preliminaryInputFrameCount = (pResampler->inTimeInt + outputFrameCount*pResampler->inAdvanceInt ) + preliminaryInputFrameCountFromFrac; /* - If the total number of *whole* input frames that would be required to generate our preliminary output frame count is greather than + If the total number of *whole* input frames that would be required to generate our preliminary output frame count is greater than the amount of whole input frames we have available as input we need to *not* add an extra output frame as there won't be enough data to actually process. Otherwise we need to add the extra output frame. */ @@ -51844,7 +53823,7 @@ MA_API ma_result ma_linear_resampler_reset(ma_linear_resampler* pResampler) } } - /* The low pass filter needs to have it's cache reset. */ + /* The low pass filter needs to have its cache reset. */ ma_lpf_clear_cache(&pResampler->lpf); return MA_SUCCESS; @@ -52361,19 +54340,19 @@ static float ma_calculate_channel_position_rectangular_weight(ma_channel channel of contribution to apply to the side/left and back/left speakers, however, is a bit more complicated. Imagine the front/left speaker as emitting audio from two planes - the front plane and the left plane. You can think of the front/left - speaker emitting half of it's total volume from the front, and the other half from the left. Since part of it's volume is being emitted + speaker emitting half of its total volume from the front, and the other half from the left. Since part of its volume is being emitted from the left side, and the side/left and back/left channels also emit audio from the left plane, one would expect that they would receive some amount of contribution from front/left speaker. The amount of contribution depends on how many planes are shared between the two speakers. Note that in the examples below I've added a top/front/left speaker as an example just to show how the math works across 3 spatial dimensions. The first thing to do is figure out how each speaker's volume is spread over each of plane: - - front/left: 2 planes (front and left) = 1/2 = half it's total volume on each plane + - front/left: 2 planes (front and left) = 1/2 = half its total volume on each plane - side/left: 1 plane (left only) = 1/1 = entire volume from left plane - - back/left: 2 planes (back and left) = 1/2 = half it's total volume on each plane - - top/front/left: 3 planes (top, front and left) = 1/3 = one third it's total volume on each plane + - back/left: 2 planes (back and left) = 1/2 = half its total volume on each plane + - top/front/left: 3 planes (top, front and left) = 1/3 = one third its total volume on each plane - The amount of volume each channel contributes to each of it's planes is what controls how much it is willing to given and take to other + The amount of volume each channel contributes to each of its planes is what controls how much it is willing to given and take to other channels on the same plane. The volume that is willing to the given by one channel is multiplied by the volume that is willing to be taken by the other to produce the final contribution. */ @@ -52435,7 +54414,7 @@ static ma_bool32 ma_is_spatial_channel_position(ma_channel channelPosition) return MA_FALSE; } - if (channelPosition >= MA_CHANNEL_AUX_0 && channelPosition <= MA_CHANNEL_AUX_31) { + if (channelPosition >= MA_CHANNEL_AUX_0) { return MA_FALSE; } @@ -52484,12 +54463,7 @@ static ma_channel_conversion_path ma_channel_map_get_conversion_path(const ma_ch ma_uint32 iChannelIn; ma_bool32 areAllChannelPositionsPresent = MA_TRUE; for (iChannelIn = 0; iChannelIn < channelsIn; ++iChannelIn) { - ma_bool32 isInputChannelPositionInOutput = MA_FALSE; - if (ma_channel_map_contains_channel_position(channelsOut, pChannelMapOut, ma_channel_map_get_channel(pChannelMapIn, channelsIn, iChannelIn))) { - isInputChannelPositionInOutput = MA_TRUE; - break; - } - + ma_bool32 isInputChannelPositionInOutput = ma_channel_map_contains_channel_position(channelsOut, pChannelMapOut, ma_channel_map_get_channel(pChannelMapIn, channelsIn, iChannelIn)); if (!isInputChannelPositionInOutput) { areAllChannelPositionsPresent = MA_FALSE; break; @@ -52516,8 +54490,8 @@ static ma_result ma_channel_map_build_shuffle_table(const ma_channel* pChannelMa } /* - When building the shuffle table we just do a 1:1 mapping based on the first occurance of a channel. If the - input channel has more than one occurance of a channel position, the second one will be ignored. + When building the shuffle table we just do a 1:1 mapping based on the first occurrence of a channel. If the + input channel has more than one occurrence of a channel position, the second one will be ignored. */ for (iChannelOut = 0; iChannelOut < channelCountOut; iChannelOut += 1) { ma_channel channelOut; @@ -54812,7 +56786,7 @@ static ma_result ma_data_converter_process_pcm_frames__channels_first(ma_data_co Before doing any processing we need to determine how many frames we should try processing this iteration, for both input and output. The resampler requires us to perform format and channel conversion before passing any data into it. If we get our input count wrong, we'll - end up peforming redundant pre-processing. This isn't the end of the world, but it does + end up performing redundant pre-processing. This isn't the end of the world, but it does result in some inefficiencies proportionate to how far our estimates are off. If the resampler has a means to calculate exactly how much we'll need, we'll use that. @@ -55963,8 +57937,12 @@ MA_API size_t ma_channel_map_to_string(const ma_channel* pChannelMap, ma_uint32 } /* Null terminate. Don't increment the length here. */ - if (pBufferOut != NULL && bufferCap > len + 1) { - pBufferOut[len] = '\0'; + if (pBufferOut != NULL) { + if (bufferCap > len) { + pBufferOut[len] = '\0'; + } else if (bufferCap > 0) { + pBufferOut[bufferCap - 1] = '\0'; + } } return len; @@ -55982,7 +57960,7 @@ MA_API const char* ma_channel_position_to_string(ma_channel channel) case MA_CHANNEL_LFE : return "CHANNEL_LFE"; case MA_CHANNEL_BACK_LEFT : return "CHANNEL_BACK_LEFT"; case MA_CHANNEL_BACK_RIGHT : return "CHANNEL_BACK_RIGHT"; - case MA_CHANNEL_FRONT_LEFT_CENTER : return "CHANNEL_FRONT_LEFT_CENTER "; + case MA_CHANNEL_FRONT_LEFT_CENTER : return "CHANNEL_FRONT_LEFT_CENTER"; case MA_CHANNEL_FRONT_RIGHT_CENTER: return "CHANNEL_FRONT_RIGHT_CENTER"; case MA_CHANNEL_BACK_CENTER : return "CHANNEL_BACK_CENTER"; case MA_CHANNEL_SIDE_LEFT : return "CHANNEL_SIDE_LEFT"; @@ -56175,7 +58153,7 @@ MA_API ma_result ma_rb_init_ex(size_t subbufferSizeInBytes, size_t subbufferCoun Here is where we allocate our own buffer. We always want to align this to MA_SIMD_ALIGNMENT for future SIMD optimization opportunity. To do this we need to make sure the stride is a multiple of MA_SIMD_ALIGNMENT. */ - pRB->subbufferStrideInBytes = (pRB->subbufferSizeInBytes + (MA_SIMD_ALIGNMENT-1)) & ~MA_SIMD_ALIGNMENT; + pRB->subbufferStrideInBytes = ma_align(pRB->subbufferSizeInBytes, MA_SIMD_ALIGNMENT); bufferSizeInBytes = (size_t)pRB->subbufferCount*pRB->subbufferStrideInBytes; pRB->pBuffer = ma_aligned_malloc(bufferSizeInBytes, MA_SIMD_ALIGNMENT, &pRB->allocationCallbacks); @@ -56287,13 +58265,9 @@ MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes) newReadOffsetLoopFlag ^= 0x80000000; } - ma_atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes)); + ma_atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag)); - if (ma_rb_pointer_distance(pRB) == 0) { - return MA_AT_END; - } else { - return MA_SUCCESS; - } + return MA_SUCCESS; } MA_API ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut) @@ -56373,13 +58347,9 @@ MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes) newWriteOffsetLoopFlag ^= 0x80000000; } - ma_atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes)); + ma_atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag)); - if (ma_rb_pointer_distance(pRB) == 0) { - return MA_AT_END; - } else { - return MA_SUCCESS; - } + return MA_SUCCESS; } MA_API ma_result ma_rb_seek_read(ma_rb* pRB, size_t offsetInBytes) @@ -56602,6 +58572,16 @@ static ma_result ma_pcm_rb_data_source__on_read(ma_data_source* pDataSource, voi totalFramesRead += mappedFrameCount; } + /* + There is no notion of an "end" in a ring buffer. If we didn't have enough data to fill the requested frame + count we'll need to pad with silence. If we don't do this, totalFramesRead might equal 0 which will result + in the data source layer at a higher level translating this to MA_AT_END which is incorrect for a ring buffer. + */ + if (totalFramesRead < frameCount) { + ma_silence_pcm_frames(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, pRB->format, pRB->channels), (frameCount - totalFramesRead), pRB->format, pRB->channels); + totalFramesRead = frameCount; + } + *pFramesRead = totalFramesRead; return MA_SUCCESS; } @@ -57150,6 +59130,10 @@ MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_da return MA_INVALID_ARGS; } + if (pConfig->vtable == NULL) { + return MA_INVALID_ARGS; + } + pDataSourceBase->vtable = pConfig->vtable; pDataSourceBase->rangeBegInFrames = MA_DATA_SOURCE_DEFAULT_RANGE_BEG; pDataSourceBase->rangeEndInFrames = MA_DATA_SOURCE_DEFAULT_RANGE_END; @@ -57200,6 +59184,58 @@ static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_ return MA_SUCCESS; } +static ma_result ma_data_source_read_pcm_frames_from_backend(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead) +{ + ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; + + MA_ASSERT(pDataSourceBase != NULL); + MA_ASSERT(pDataSourceBase->vtable != NULL); + MA_ASSERT(pDataSourceBase->vtable->onRead != NULL); + MA_ASSERT(pFramesRead != NULL); + + if (pFramesOut != NULL) { + return pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, pFramesRead); + } else { + /* + No output buffer. Probably seeking forward. Read and discard. Can probably optimize this in terms of + onSeek and onGetCursor, but need to keep in mind that the data source may not implement these functions. + */ + ma_result result; + ma_uint64 framesRead; + ma_format format; + ma_uint32 channels; + ma_uint64 discardBufferCapInFrames; + ma_uint8 pDiscardBuffer[4096]; + + result = ma_data_source_get_data_format(pDataSource, &format, &channels, NULL, NULL, 0); + if (result != MA_SUCCESS) { + return result; + } + + discardBufferCapInFrames = sizeof(pDiscardBuffer) / ma_get_bytes_per_frame(format, channels); + + framesRead = 0; + while (framesRead < frameCount) { + ma_uint64 framesReadThisIteration = 0; + ma_uint64 framesToRead = frameCount - framesRead; + if (framesToRead > discardBufferCapInFrames) { + framesToRead = discardBufferCapInFrames; + } + + result = pDataSourceBase->vtable->onRead(pDataSourceBase, pDiscardBuffer, framesToRead, &framesReadThisIteration); + if (result != MA_SUCCESS) { + return result; + } + + framesRead += framesReadThisIteration; + } + + *pFramesRead = framesRead; + + return MA_SUCCESS; + } +} + static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead) { ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; @@ -57215,9 +59251,11 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa return MA_INVALID_ARGS; } + MA_ASSERT(pDataSourceBase->vtable != NULL); + if ((pDataSourceBase->vtable->flags & MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT) != 0 || (pDataSourceBase->rangeEndInFrames == ~((ma_uint64)0) && (pDataSourceBase->loopEndInFrames == ~((ma_uint64)0) || loop == MA_FALSE))) { /* Either the data source is self-managing the range, or no range is set - just read like normal. The data source itself will tell us when the end is reached. */ - result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead); + result = ma_data_source_read_pcm_frames_from_backend(pDataSource, pFramesOut, frameCount, &framesRead); } else { /* Need to clamp to within the range. */ ma_uint64 relativeCursor; @@ -57226,7 +59264,7 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa result = ma_data_source_get_cursor_in_pcm_frames(pDataSourceBase, &relativeCursor); if (result != MA_SUCCESS) { /* Failed to retrieve the cursor. Cannot read within a range or loop points. Just read like normal - this may happen for things like noise data sources where it doesn't really matter. */ - result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead); + result = ma_data_source_read_pcm_frames_from_backend(pDataSource, pFramesOut, frameCount, &framesRead); } else { ma_uint64 rangeBeg; ma_uint64 rangeEnd; @@ -57254,7 +59292,7 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa MA_AT_END so the higher level function can know about it. */ if (frameCount > 0) { - result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead); + result = ma_data_source_read_pcm_frames_from_backend(pDataSource, pFramesOut, frameCount, &framesRead); } else { result = MA_AT_END; /* The cursor is sitting on the end of the range which means we're at the end. */ } @@ -57336,7 +59374,7 @@ MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, voi totalFramesProcessed += framesProcessed; /* - If we encounted an error from the read callback, make sure it's propagated to the caller. The caller may need to know whether or not MA_BUSY is returned which is + If we encountered an error from the read callback, make sure it's propagated to the caller. The caller may need to know whether or not MA_BUSY is returned which is not necessarily considered an error. */ if (result != MA_SUCCESS && result != MA_AT_END) { @@ -57427,7 +59465,7 @@ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, m ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; if (pDataSourceBase == NULL) { - return MA_SUCCESS; + return MA_INVALID_ARGS; } if (pDataSourceBase->vtable->onSeek == NULL) { @@ -57435,12 +59473,61 @@ MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, m } if (frameIndex > pDataSourceBase->rangeEndInFrames) { - return MA_INVALID_OPERATION; /* Trying to seek to far forward. */ + return MA_INVALID_OPERATION; /* Trying to seek too far forward. */ } + MA_ASSERT(pDataSourceBase->vtable != NULL); + return pDataSourceBase->vtable->onSeek(pDataSource, pDataSourceBase->rangeBegInFrames + frameIndex); } +MA_API ma_result ma_data_source_seek_seconds(ma_data_source* pDataSource, float secondCount, float* pSecondsSeeked) +{ + ma_uint64 frameCount; + ma_uint64 framesSeeked = 0; + ma_uint32 sampleRate; + ma_result result; + + if (pDataSource == NULL) { + return MA_INVALID_ARGS; + } + + result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0); + if (result != MA_SUCCESS) { + return result; + } + + /* We need PCM frames instead of seconds */ + frameCount = (ma_uint64)(secondCount * sampleRate); + + result = ma_data_source_seek_pcm_frames(pDataSource, frameCount, &framesSeeked); + + /* VC6 doesn't support division between unsigned 64-bit integer and floating point number. Signed integer needed. This shouldn't affect anything in practice */ + *pSecondsSeeked = (ma_int64)framesSeeked / (float)sampleRate; + return result; +} + +MA_API ma_result ma_data_source_seek_to_second(ma_data_source* pDataSource, float seekPointInSeconds) +{ + ma_uint64 frameIndex; + ma_uint32 sampleRate; + ma_result result; + + if (pDataSource == NULL) { + return MA_INVALID_ARGS; + } + + result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0); + if (result != MA_SUCCESS) { + return result; + } + + /* We need PCM frames instead of seconds */ + frameIndex = (ma_uint64)(seekPointInSeconds * sampleRate); + + return ma_data_source_seek_to_pcm_frame(pDataSource, frameIndex); +} + MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap) { ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource; @@ -57467,6 +59554,8 @@ MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_ return MA_INVALID_ARGS; } + MA_ASSERT(pDataSourceBase->vtable != NULL); + if (pDataSourceBase->vtable->onGetDataFormat == NULL) { return MA_NOT_IMPLEMENTED; } @@ -57507,6 +59596,8 @@ MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSo return MA_SUCCESS; } + MA_ASSERT(pDataSourceBase->vtable != NULL); + if (pDataSourceBase->vtable->onGetCursor == NULL) { return MA_NOT_IMPLEMENTED; } @@ -57540,6 +59631,8 @@ MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSo return MA_INVALID_ARGS; } + MA_ASSERT(pDataSourceBase->vtable != NULL); + /* If we have a range defined we'll use that to determine the length. This is one of rare times where we'll actually trust the caller. If they've set the range, I think it's mostly safe to @@ -57627,6 +59720,8 @@ MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool ma_atomic_exchange_32(&pDataSourceBase->isLooping, isLooping); + MA_ASSERT(pDataSourceBase->vtable != NULL); + /* If there's no callback for this just treat it as a successful no-op. */ if (pDataSourceBase->vtable->onSetLooping == NULL) { return MA_SUCCESS; @@ -57664,7 +59759,7 @@ MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSou /* We may need to adjust the position of the cursor to ensure it's clamped to the range. Grab it now - so we can calculate it's absolute position before we change the range. + so we can calculate its absolute position before we change the range. */ result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &relativeCursor); if (result == MA_SUCCESS) { @@ -57698,7 +59793,7 @@ MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSou /* Seek to within range. Note that our seek positions here are relative to the new range. We don't want - do do this if we failed to retrieve the cursor earlier on because it probably means the data source + to do this if we failed to retrieve the cursor earlier on because it probably means the data source has no notion of a cursor. In practice the seek would probably fail (which we silently ignore), but I'm just not even going to attempt it. */ @@ -57717,6 +59812,13 @@ MA_API void ma_data_source_get_range_in_pcm_frames(const ma_data_source* pDataSo { const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource; + if (pRangeBegInFrames != NULL) { + *pRangeBegInFrames = 0; + } + if (pRangeEndInFrames != NULL) { + *pRangeEndInFrames = 0; + } + if (pDataSource == NULL) { return; } @@ -57761,6 +59863,13 @@ MA_API void ma_data_source_get_loop_point_in_pcm_frames(const ma_data_source* pD { const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource; + if (pLoopBegInFrames != NULL) { + *pLoopBegInFrames = 0; + } + if (pLoopEndInFrames != NULL) { + *pLoopEndInFrames = 0; + } + if (pDataSource == NULL) { return; } @@ -58939,7 +61048,7 @@ MA_API ma_result ma_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo } -#if !defined(MA_USE_WIN32_FILEIO) && (defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO) && !defined(MA_POSIX)) +#if !defined(MA_USE_WIN32_FILEIO) && (defined(MA_WIN32) && (defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_NXDK)) && !defined(MA_NO_WIN32_FILEIO) && !defined(MA_POSIX)) #define MA_USE_WIN32_FILEIO #endif @@ -59016,25 +61125,34 @@ static ma_result ma_default_vfs_open__win32(ma_vfs* pVFS, const char* pFilePath, static ma_result ma_default_vfs_open_w__win32(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile) { - HANDLE hFile; - DWORD dwDesiredAccess; - DWORD dwShareMode; - DWORD dwCreationDisposition; + #if !defined(MA_XBOX_NXDK) + { + HANDLE hFile; + DWORD dwDesiredAccess; + DWORD dwShareMode; + DWORD dwCreationDisposition; - (void)pVFS; + (void)pVFS; - /* Load some Win32 symbols dynamically so we can dynamically check for the existence of SetFilePointerEx. */ - ma_win32_fileio_init(); + /* Load some Win32 symbols dynamically so we can dynamically check for the existence of SetFilePointerEx. */ + ma_win32_fileio_init(); - ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition); + ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition); - hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - return ma_result_from_GetLastError(GetLastError()); + hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return ma_result_from_GetLastError(GetLastError()); + } + + *pFile = hFile; + return MA_SUCCESS; } - - *pFile = hFile; - return MA_SUCCESS; + #else + { + /* No CreateFileW() available. */ + return MA_NOT_IMPLEMENTED; + } + #endif } static ma_result ma_default_vfs_close__win32(ma_vfs* pVFS, ma_vfs_file file) @@ -59155,7 +61273,7 @@ static ma_result ma_default_vfs_seek__win32(ma_vfs* pVFS, ma_vfs_file file, ma_i result = ma_SetFilePointerEx((HANDLE)file, liDistanceToMove, NULL, dwMoveMethod); } else if (ma_SetFilePointer != NULL) { /* No SetFilePointerEx() so restrict to 31 bits. */ - if (origin > 0x7FFFFFFF) { + if (offset > 0x7FFFFFFF) { return MA_OUT_OF_RANGE; } @@ -59205,19 +61323,28 @@ static ma_result ma_default_vfs_tell__win32(ma_vfs* pVFS, ma_vfs_file file, ma_i static ma_result ma_default_vfs_info__win32(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo) { - BY_HANDLE_FILE_INFORMATION fi; - BOOL result; - (void)pVFS; - result = GetFileInformationByHandle((HANDLE)file, &fi); - if (result == 0) { - return ma_result_from_GetLastError(GetLastError()); + #if !defined(MA_XBOX_NXDK) + { + BY_HANDLE_FILE_INFORMATION fi; + BOOL result; + + result = GetFileInformationByHandle((HANDLE)file, &fi); + if (result == 0) { + return ma_result_from_GetLastError(GetLastError()); + } + + pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow); + + return MA_SUCCESS; } - - pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow); - - return MA_SUCCESS; + #else + { + /* GetFileInformationByHandle() is unavailable. */ + return MA_NOT_IMPLEMENTED; + } + #endif } #else static ma_result ma_default_vfs_open__stdio(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile) @@ -59365,7 +61492,7 @@ static ma_result ma_default_vfs_seek__stdio(ma_vfs* pVFS, ma_vfs_file file, ma_i result = _fseeki64((FILE*)file, offset, whence); #else /* No _fseeki64() so restrict to 31 bits. */ - if (origin > 0x7FFFFFFF) { + if (offset > 0x7FFFFFFF) { return MA_OUT_OF_RANGE; } @@ -59555,6 +61682,8 @@ static ma_result ma_default_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* p static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo) { + ma_result result; + if (pInfo == NULL) { return MA_INVALID_ARGS; } @@ -59566,10 +61695,42 @@ static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_inf } #if defined(MA_USE_WIN32_FILEIO) - return ma_default_vfs_info__win32(pVFS, file, pInfo); + result = ma_default_vfs_info__win32(pVFS, file, pInfo); #else - return ma_default_vfs_info__stdio(pVFS, file, pInfo); + result = ma_default_vfs_info__stdio(pVFS, file, pInfo); #endif + + if (result == MA_NOT_IMPLEMENTED) { + /* Not implemented. Fall back to seek/tell/seek. */ + ma_int64 cursor; + ma_int64 sizeInBytes; + + result = ma_default_vfs_tell(pVFS, file, &cursor); + if (result != MA_SUCCESS) { + return result; + } + + result = ma_default_vfs_seek(pVFS, file, 0, ma_seek_origin_end); + if (result != MA_SUCCESS) { + return result; + } + + result = ma_default_vfs_tell(pVFS, file, &sizeInBytes); + if (result != MA_SUCCESS) { + return result; + } + + pInfo->sizeInBytes = sizeInBytes; + + result = ma_default_vfs_seek(pVFS, file, cursor, ma_seek_origin_start); + if (result != MA_SUCCESS) { + return result; + } + + MA_ASSERT(result == MA_SUCCESS); + } + + return result; } @@ -59748,6 +61909,8 @@ Decoding and Encoding Headers. These are auto-generated from a tool. **************************************************************************************************************************************************************/ #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING)) +#define MA_HAS_WAV + /* dr_wav_h begin */ #ifndef ma_dr_wav_h #define ma_dr_wav_h @@ -59757,8 +61920,8 @@ extern "C" { #define MA_DR_WAV_STRINGIFY(x) #x #define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x) #define MA_DR_WAV_VERSION_MAJOR 0 -#define MA_DR_WAV_VERSION_MINOR 13 -#define MA_DR_WAV_VERSION_REVISION 13 +#define MA_DR_WAV_VERSION_MINOR 14 +#define MA_DR_WAV_VERSION_REVISION 4 #define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION) #include #define MA_DR_WAVE_FORMAT_PCM 0x1 @@ -59774,8 +61937,9 @@ MA_API void ma_dr_wav_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* p MA_API const char* ma_dr_wav_version_string(void); typedef enum { - ma_dr_wav_seek_origin_start, - ma_dr_wav_seek_origin_current + MA_DR_WAV_SEEK_SET, + MA_DR_WAV_SEEK_CUR, + MA_DR_WAV_SEEK_END } ma_dr_wav_seek_origin; typedef enum { @@ -59812,6 +61976,7 @@ MA_API ma_uint16 ma_dr_wav_fmt_get_format(const ma_dr_wav_fmt* pFMT); typedef size_t (* ma_dr_wav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); typedef size_t (* ma_dr_wav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite); typedef ma_bool32 (* ma_dr_wav_seek_proc)(void* pUserData, int offset, ma_dr_wav_seek_origin origin); +typedef ma_bool32 (* ma_dr_wav_tell_proc)(void* pUserData, ma_int64* pCursor); typedef ma_uint64 (* ma_dr_wav_chunk_proc)(void* pChunkUserData, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pReadSeekUserData, const ma_dr_wav_chunk_header* pChunkHeader, ma_dr_wav_container container, const ma_dr_wav_fmt* pFMT); typedef struct { @@ -59856,6 +62021,11 @@ typedef enum ma_dr_wav_metadata_type_list_info_genre = 1 << 15, ma_dr_wav_metadata_type_list_info_album = 1 << 16, ma_dr_wav_metadata_type_list_info_tracknumber = 1 << 17, + ma_dr_wav_metadata_type_list_info_location = 1 << 18, + ma_dr_wav_metadata_type_list_info_organization = 1 << 19, + ma_dr_wav_metadata_type_list_info_keywords = 1 << 20, + ma_dr_wav_metadata_type_list_info_medium = 1 << 21, + ma_dr_wav_metadata_type_list_info_description = 1 << 22, ma_dr_wav_metadata_type_list_all_info_strings = ma_dr_wav_metadata_type_list_info_software | ma_dr_wav_metadata_type_list_info_copyright | ma_dr_wav_metadata_type_list_info_title @@ -59864,7 +62034,12 @@ typedef enum | ma_dr_wav_metadata_type_list_info_date | ma_dr_wav_metadata_type_list_info_genre | ma_dr_wav_metadata_type_list_info_album - | ma_dr_wav_metadata_type_list_info_tracknumber, + | ma_dr_wav_metadata_type_list_info_tracknumber + | ma_dr_wav_metadata_type_list_info_location + | ma_dr_wav_metadata_type_list_info_organization + | ma_dr_wav_metadata_type_list_info_keywords + | ma_dr_wav_metadata_type_list_info_medium + | ma_dr_wav_metadata_type_list_info_description, ma_dr_wav_metadata_type_list_all_adtl = ma_dr_wav_metadata_type_list_label | ma_dr_wav_metadata_type_list_note | ma_dr_wav_metadata_type_list_labelled_cue_region, @@ -59881,8 +62056,8 @@ typedef struct { ma_uint32 cuePointId; ma_uint32 type; - ma_uint32 firstSampleByteOffset; - ma_uint32 lastSampleByteOffset; + ma_uint32 firstSampleOffset; + ma_uint32 lastSampleOffset; ma_uint32 sampleFraction; ma_uint32 playCount; } ma_dr_wav_smpl_loop; @@ -59917,7 +62092,7 @@ typedef struct ma_uint8 dataChunkId[4]; ma_uint32 chunkStart; ma_uint32 blockStart; - ma_uint32 sampleByteOffset; + ma_uint32 sampleOffset; } ma_dr_wav_cue_point; typedef struct { @@ -60019,6 +62194,7 @@ typedef struct ma_dr_wav_read_proc onRead; ma_dr_wav_write_proc onWrite; ma_dr_wav_seek_proc onSeek; + ma_dr_wav_tell_proc onTell; void* pUserData; ma_allocation_callbacks allocationCallbacks; ma_dr_wav_container container; @@ -60061,9 +62237,9 @@ typedef struct ma_bool8 isUnsigned; } aiff; } ma_dr_wav; -MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, ma_dr_wav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_wav_init_write(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_dr_wav_write_proc onWrite, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_wav_init_write_sequential(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_uint64 totalSampleCount, ma_dr_wav_write_proc onWrite, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_wav_init_write_sequential_pcm_frames(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_uint64 totalPCMFrameCount, ma_dr_wav_write_proc onWrite, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); @@ -60135,9 +62311,9 @@ MA_API ma_bool32 ma_dr_wav_init_memory_write(ma_dr_wav* pWav, void** ppData, siz MA_API ma_bool32 ma_dr_wav_init_memory_write_sequential(ma_dr_wav* pWav, void** ppData, size_t* pDataSize, const ma_dr_wav_data_format* pFormat, ma_uint64 totalSampleCount, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_wav_init_memory_write_sequential_pcm_frames(ma_dr_wav* pWav, void** ppData, size_t* pDataSize, const ma_dr_wav_data_format* pFormat, ma_uint64 totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); #ifndef MA_DR_WAV_NO_CONVERSION_API -MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); #ifndef MA_DR_WAV_NO_STDIO MA_API ma_int16* ma_dr_wav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); MA_API float* ma_dr_wav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks); @@ -60168,6 +62344,8 @@ MA_API ma_bool32 ma_dr_wav_fourcc_equal(const ma_uint8* a, const char* b); #endif /* MA_NO_WAV */ #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING) +#define MA_HAS_FLAC + /* dr_flac_h begin */ #ifndef ma_dr_flac_h #define ma_dr_flac_h @@ -60177,8 +62355,8 @@ extern "C" { #define MA_DR_FLAC_STRINGIFY(x) #x #define MA_DR_FLAC_XSTRINGIFY(x) MA_DR_FLAC_STRINGIFY(x) #define MA_DR_FLAC_VERSION_MAJOR 0 -#define MA_DR_FLAC_VERSION_MINOR 12 -#define MA_DR_FLAC_VERSION_REVISION 42 +#define MA_DR_FLAC_VERSION_MINOR 13 +#define MA_DR_FLAC_VERSION_REVISION 3 #define MA_DR_FLAC_VERSION_STRING MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MAJOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MINOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_REVISION) #include #if defined(_MSC_VER) && _MSC_VER >= 1700 @@ -60241,8 +62419,9 @@ typedef enum } ma_dr_flac_container; typedef enum { - ma_dr_flac_seek_origin_start, - ma_dr_flac_seek_origin_current + MA_DR_FLAC_SEEK_SET, + MA_DR_FLAC_SEEK_CUR, + MA_DR_FLAC_SEEK_END } ma_dr_flac_seek_origin; typedef struct { @@ -60265,8 +62444,9 @@ typedef struct typedef struct { ma_uint32 type; - const void* pRawData; ma_uint32 rawDataSize; + ma_uint64 rawDataOffset; + const void* pRawData; union { ma_dr_flac_streaminfo streaminfo; @@ -60312,12 +62492,14 @@ typedef struct ma_uint32 colorDepth; ma_uint32 indexColorCount; ma_uint32 pictureDataSize; + ma_uint64 pictureDataOffset; const ma_uint8* pPictureData; } picture; } data; } ma_dr_flac_metadata; typedef size_t (* ma_dr_flac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); typedef ma_bool32 (* ma_dr_flac_seek_proc)(void* pUserData, int offset, ma_dr_flac_seek_origin origin); +typedef ma_bool32 (* ma_dr_flac_tell_proc)(void* pUserData, ma_int64* pCursor); typedef void (* ma_dr_flac_meta_proc)(void* pUserData, ma_dr_flac_metadata* pMetadata); typedef struct { @@ -60329,6 +62511,7 @@ typedef struct { ma_dr_flac_read_proc onRead; ma_dr_flac_seek_proc onSeek; + ma_dr_flac_tell_proc onTell; void* pUserData; size_t unalignedByteCount; ma_dr_flac_cache_t unalignedCache; @@ -60388,10 +62571,10 @@ typedef struct ma_dr_flac_bs bs; ma_uint8 pExtraData[1]; } ma_dr_flac; -MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); MA_API void ma_dr_flac_close(ma_dr_flac* pFlac); MA_API ma_uint64 ma_dr_flac_read_pcm_frames_s32(ma_dr_flac* pFlac, ma_uint64 framesToRead, ma_int32* pBufferOut); MA_API ma_uint64 ma_dr_flac_read_pcm_frames_s16(ma_dr_flac* pFlac, ma_uint64 framesToRead, ma_int16* pBufferOut); @@ -60405,9 +62588,9 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata_w(const wchar_t* pFileName #endif MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_t dataSize, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); #ifndef MA_DR_FLAC_NO_STDIO MA_API ma_int32* ma_dr_flac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_int16* ma_dr_flac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); @@ -60455,6 +62638,14 @@ MA_API ma_bool32 ma_dr_flac_next_cuesheet_track(ma_dr_flac_cuesheet_track_iterat #endif /* MA_NO_FLAC */ #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING) +#define MA_HAS_MP3 + +#ifndef MA_DR_MP3_NO_SIMD + #if (defined(MA_NO_NEON) && defined(MA_ARM)) || (defined(MA_NO_SSE2) && (defined(MA_X86) || defined(MA_X64))) + #define MA_DR_MP3_NO_SIMD + #endif +#endif + /* dr_mp3_h begin */ #ifndef ma_dr_mp3_h #define ma_dr_mp3_h @@ -60464,31 +62655,57 @@ extern "C" { #define MA_DR_MP3_STRINGIFY(x) #x #define MA_DR_MP3_XSTRINGIFY(x) MA_DR_MP3_STRINGIFY(x) #define MA_DR_MP3_VERSION_MAJOR 0 -#define MA_DR_MP3_VERSION_MINOR 6 -#define MA_DR_MP3_VERSION_REVISION 38 +#define MA_DR_MP3_VERSION_MINOR 7 +#define MA_DR_MP3_VERSION_REVISION 3 #define MA_DR_MP3_VERSION_STRING MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MAJOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MINOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_REVISION) #include #define MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152 #define MA_DR_MP3_MAX_SAMPLES_PER_FRAME (MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2) MA_API void ma_dr_mp3_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* pRevision); MA_API const char* ma_dr_mp3_version_string(void); +#define MA_DR_MP3_MAX_BITRESERVOIR_BYTES 511 +#define MA_DR_MP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 +#define MA_DR_MP3_MAX_L3_FRAME_PAYLOAD_BYTES MA_DR_MP3_MAX_FREE_FORMAT_FRAME_SIZE typedef struct { - int frame_bytes, channels, hz, layer, bitrate_kbps; + int frame_bytes, channels, sample_rate, layer, bitrate_kbps; } ma_dr_mp3dec_frame_info; typedef struct +{ + const ma_uint8 *buf; + int pos, limit; +} ma_dr_mp3_bs; +typedef struct +{ + const ma_uint8 *sfbtab; + ma_uint16 part_23_length, big_values, scalefac_compress; + ma_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb; + ma_uint8 table_select[3], region_count[3], subblock_gain[3]; + ma_uint8 preflag, scalefac_scale, count1_table, scfsi; +} ma_dr_mp3_L3_gr_info; +typedef struct +{ + ma_dr_mp3_bs bs; + ma_uint8 maindata[MA_DR_MP3_MAX_BITRESERVOIR_BYTES + MA_DR_MP3_MAX_L3_FRAME_PAYLOAD_BYTES]; + ma_dr_mp3_L3_gr_info gr_info[4]; + float grbuf[2][576], scf[40], syn[18 + 15][2*32]; + ma_uint8 ist_pos[2][39]; +} ma_dr_mp3dec_scratch; +typedef struct { float mdct_overlap[2][9*32], qmf_state[15*2*32]; int reserv, free_format_bytes; ma_uint8 header[4], reserv_buf[511]; + ma_dr_mp3dec_scratch scratch; } ma_dr_mp3dec; MA_API void ma_dr_mp3dec_init(ma_dr_mp3dec *dec); MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int mp3_bytes, void *pcm, ma_dr_mp3dec_frame_info *info); MA_API void ma_dr_mp3dec_f32_to_s16(const float *in, ma_int16 *out, size_t num_samples); typedef enum { - ma_dr_mp3_seek_origin_start, - ma_dr_mp3_seek_origin_current + MA_DR_MP3_SEEK_SET, + MA_DR_MP3_SEEK_CUR, + MA_DR_MP3_SEEK_END } ma_dr_mp3_seek_origin; typedef struct { @@ -60497,8 +62714,24 @@ typedef struct ma_uint16 mp3FramesToDiscard; ma_uint16 pcmFramesToDiscard; } ma_dr_mp3_seek_point; +typedef enum +{ + MA_DR_MP3_METADATA_TYPE_ID3V1, + MA_DR_MP3_METADATA_TYPE_ID3V2, + MA_DR_MP3_METADATA_TYPE_APE, + MA_DR_MP3_METADATA_TYPE_XING, + MA_DR_MP3_METADATA_TYPE_VBRI +} ma_dr_mp3_metadata_type; +typedef struct +{ + ma_dr_mp3_metadata_type type; + const void* pRawData; + size_t rawDataSize; +} ma_dr_mp3_metadata; typedef size_t (* ma_dr_mp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead); typedef ma_bool32 (* ma_dr_mp3_seek_proc)(void* pUserData, int offset, ma_dr_mp3_seek_origin origin); +typedef ma_bool32 (* ma_dr_mp3_tell_proc)(void* pUserData, ma_int64* pCursor); +typedef void (* ma_dr_mp3_meta_proc)(void* pUserData, const ma_dr_mp3_metadata* pMetadata); typedef struct { ma_uint32 channels; @@ -60511,7 +62744,9 @@ typedef struct ma_uint32 sampleRate; ma_dr_mp3_read_proc onRead; ma_dr_mp3_seek_proc onSeek; + ma_dr_mp3_meta_proc onMeta; void* pUserData; + void* pUserDataMeta; ma_allocation_callbacks allocationCallbacks; ma_uint32 mp3FrameChannels; ma_uint32 mp3FrameSampleRate; @@ -60520,13 +62755,20 @@ typedef struct ma_uint8 pcmFrames[sizeof(float)*MA_DR_MP3_MAX_SAMPLES_PER_FRAME]; ma_uint64 currentPCMFrame; ma_uint64 streamCursor; + ma_uint64 streamLength; + ma_uint64 streamStartOffset; ma_dr_mp3_seek_point* pSeekPoints; ma_uint32 seekPointCount; + ma_uint32 delayInPCMFrames; + ma_uint32 paddingInPCMFrames; + ma_uint64 totalPCMFrameCount; + ma_bool32 isVBR; + ma_bool32 isCBR; size_t dataSize; size_t dataCapacity; size_t dataConsumed; ma_uint8* pData; - ma_bool32 atEnd : 1; + ma_bool32 atEnd; struct { const ma_uint8* pData; @@ -60534,9 +62776,12 @@ typedef struct size_t currentReadPos; } memory; } ma_dr_mp3; -MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_mp3_init_memory_with_metadata(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks); #ifndef MA_DR_MP3_NO_STDIO +MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata(ma_dr_mp3* pMP3, const char* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks); #endif @@ -60549,8 +62794,8 @@ MA_API ma_uint64 ma_dr_mp3_get_mp3_frame_count(ma_dr_mp3* pMP3); MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint64* pMP3FrameCount, ma_uint64* pPCMFrameCount); MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSeekPointCount, ma_dr_mp3_seek_point* pSeekPoints); MA_API ma_bool32 ma_dr_mp3_bind_seek_table(ma_dr_mp3* pMP3, ma_uint32 seekPointCount, ma_dr_mp3_seek_point* pSeekPoints); -MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); -MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); +MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); MA_API float* ma_dr_mp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); MA_API ma_int16* ma_dr_mp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks); #ifndef MA_DR_MP3_NO_STDIO @@ -60627,7 +62872,7 @@ MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint3 return config; } -MA_API ma_decoder_config ma_decoder_config_init_default() +MA_API ma_decoder_config ma_decoder_config_init_default(void) { return ma_decoder_config_init(ma_format_unknown, 0, 0); } @@ -61015,7 +63260,6 @@ static ma_result ma_decoder_init_custom_from_memory__internal(const void* pData, /* WAV */ #ifdef ma_dr_wav_h -#define MA_HAS_WAV typedef struct { @@ -61103,8 +63347,10 @@ static ma_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, ma_dr_wav MA_ASSERT(pWav != NULL); maSeekOrigin = ma_seek_origin_start; - if (origin == ma_dr_wav_seek_origin_current) { - maSeekOrigin = ma_seek_origin_current; + if (origin == MA_DR_WAV_SEEK_CUR) { + maSeekOrigin = ma_seek_origin_current; + } else if (origin == MA_DR_WAV_SEEK_END) { + maSeekOrigin = ma_seek_origin_end; } result = pWav->onSeek(pWav->pReadSeekTellUserData, offset, maSeekOrigin); @@ -61114,6 +63360,26 @@ static ma_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, ma_dr_wav return MA_TRUE; } + +static ma_bool32 ma_wav_dr_callback__tell(void* pUserData, ma_int64* pCursor) +{ + ma_wav* pWav = (ma_wav*)pUserData; + ma_result result; + + MA_ASSERT(pWav != NULL); + MA_ASSERT(pCursor != NULL); + + if (pWav->onTell == NULL) { + return MA_FALSE; /* Not implemented. */ + } + + result = pWav->onTell(pWav->pReadSeekTellUserData, pCursor); + if (result != MA_SUCCESS) { + return MA_FALSE; /* Failed to tell. */ + } + + return MA_TRUE; +} #endif static ma_result ma_wav_init_internal(const ma_decoding_backend_config* pConfig, ma_wav* pWav) @@ -61208,7 +63474,7 @@ MA_API ma_result ma_wav_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_p { ma_bool32 wavResult; - wavResult = ma_dr_wav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, pWav, pAllocationCallbacks); + wavResult = ma_dr_wav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, ma_wav_dr_callback__tell, pWav, pAllocationCallbacks); if (wavResult != MA_TRUE) { return MA_INVALID_FILE; } @@ -61699,7 +63965,6 @@ static ma_result ma_decoder_init_wav_from_memory__internal(const void* pData, si /* FLAC */ #ifdef ma_dr_flac_h -#define MA_HAS_FLAC typedef struct { @@ -61787,8 +64052,10 @@ static ma_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, ma_dr_fl MA_ASSERT(pFlac != NULL); maSeekOrigin = ma_seek_origin_start; - if (origin == ma_dr_flac_seek_origin_current) { - maSeekOrigin = ma_seek_origin_current; + if (origin == MA_DR_FLAC_SEEK_CUR) { + maSeekOrigin = ma_seek_origin_current; + } else if (origin == MA_DR_FLAC_SEEK_END) { + maSeekOrigin = ma_seek_origin_end; } result = pFlac->onSeek(pFlac->pReadSeekTellUserData, offset, maSeekOrigin); @@ -61798,6 +64065,26 @@ static ma_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, ma_dr_fl return MA_TRUE; } + +static ma_bool32 ma_flac_dr_callback__tell(void* pUserData, ma_int64* pCursor) +{ + ma_flac* pFlac = (ma_flac*)pUserData; + ma_result result; + + MA_ASSERT(pFlac != NULL); + MA_ASSERT(pCursor != NULL); + + if (pFlac->onTell == NULL) { + return MA_FALSE; /* Not implemented. */ + } + + result = pFlac->onTell(pFlac->pReadSeekTellUserData, pCursor); + if (result != MA_SUCCESS) { + return MA_FALSE; /* Failed to tell. */ + } + + return MA_TRUE; +} #endif static ma_result ma_flac_init_internal(const ma_decoding_backend_config* pConfig, ma_flac* pFlac) @@ -61849,7 +64136,7 @@ MA_API ma_result ma_flac_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_ #if !defined(MA_NO_FLAC) { - pFlac->dr = ma_dr_flac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, pFlac, pAllocationCallbacks); + pFlac->dr = ma_dr_flac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, ma_flac_dr_callback__tell, pFlac, pAllocationCallbacks); if (pFlac->dr == NULL) { return MA_INVALID_FILE; } @@ -62321,7 +64608,6 @@ static ma_result ma_decoder_init_flac_from_memory__internal(const void* pData, s /* MP3 */ #ifdef ma_dr_mp3_h -#define MA_HAS_MP3 typedef struct { @@ -62410,9 +64696,12 @@ static ma_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, ma_dr_mp3 MA_ASSERT(pMP3 != NULL); - maSeekOrigin = ma_seek_origin_start; - if (origin == ma_dr_mp3_seek_origin_current) { - maSeekOrigin = ma_seek_origin_current; + if (origin == MA_DR_MP3_SEEK_SET) { + maSeekOrigin = ma_seek_origin_start; + } else if (origin == MA_DR_MP3_SEEK_END) { + maSeekOrigin = ma_seek_origin_end; + } else { + maSeekOrigin = ma_seek_origin_current; } result = pMP3->onSeek(pMP3->pReadSeekTellUserData, offset, maSeekOrigin); @@ -62422,6 +64711,21 @@ static ma_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, ma_dr_mp3 return MA_TRUE; } + +static ma_bool32 ma_mp3_dr_callback__tell(void* pUserData, ma_int64* pCursor) +{ + ma_mp3* pMP3 = (ma_mp3*)pUserData; + ma_result result; + + MA_ASSERT(pMP3 != NULL); + + result = pMP3->onTell(pMP3->pReadSeekTellUserData, pCursor); + if (result != MA_SUCCESS) { + return MA_FALSE; + } + + return MA_TRUE; +} #endif static ma_result ma_mp3_init_internal(const ma_decoding_backend_config* pConfig, ma_mp3* pMP3) @@ -62522,7 +64826,7 @@ MA_API ma_result ma_mp3_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_p { ma_bool32 mp3Result; - mp3Result = ma_dr_mp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, pMP3, pAllocationCallbacks); + mp3Result = ma_dr_mp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, ma_mp3_dr_callback__tell, NULL, pMP3, pAllocationCallbacks); if (mp3Result != MA_TRUE) { return MA_INVALID_FILE; } @@ -63220,7 +65524,7 @@ MA_API ma_result ma_stbvorbis_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_ #if !defined(MA_NO_VORBIS) { /* - stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the + stb_vorbis lacks a callback based API for its pulling API which means we're stuck with the pushing API. In order for us to be able to successfully initialize the decoder we need to supply it with enough data. We need to keep loading data until we have enough. */ @@ -63301,7 +65605,7 @@ MA_API ma_result ma_stbvorbis_init_memory(const void* pData, size_t dataSize, co { (void)pAllocationCallbacks; - /* stb_vorbis uses an int as it's size specifier, restricting it to 32-bit even on 64-bit systems. *sigh*. */ + /* stb_vorbis uses an int as its size specifier, restricting it to 32-bit even on 64-bit systems. *sigh*. */ if (dataSize > INT_MAX) { return MA_TOO_BIG; } @@ -63391,7 +65695,7 @@ MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFram /* The first thing to do is read from any already-cached frames. */ ma_uint32 framesToReadFromCache = (ma_uint32)ma_min(pVorbis->push.framesRemaining, (frameCount - totalFramesRead)); /* Safe cast because pVorbis->framesRemaining is 32-bit. */ - /* The output pointer can be null in which case we just treate it as a seek. */ + /* The output pointer can be null in which case we just treat it as a seek. */ if (pFramesOut != NULL) { ma_uint64 iFrame; for (iFrame = 0; iFrame < framesToReadFromCache; iFrame += 1) { @@ -63465,7 +65769,7 @@ MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFram } } - /* If we don't have a success code at this point it means we've encounted an error or the end of the file has been reached (probably the latter). */ + /* If we don't have a success code at this point it means we've encountered an error or the end of the file has been reached (probably the latter). */ if (result != MA_SUCCESS) { break; } @@ -63981,11 +66285,9 @@ static ma_result ma_decoder_init__internal(ma_decoder_read_proc onRead, ma_decod We use trial and error to open a decoder. We prioritize custom decoders so that if they implement the same encoding format they take priority over the built-in decoders. */ + result = ma_decoder_init_custom__internal(pConfig, pDecoder); if (result != MA_SUCCESS) { - result = ma_decoder_init_custom__internal(pConfig, pDecoder); - if (result != MA_SUCCESS) { - onSeek(pDecoder, 0, ma_seek_origin_start); - } + onSeek(pDecoder, 0, ma_seek_origin_start); } /* @@ -64249,14 +66551,6 @@ MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, cons /* Initialization was successful. Finish up. */ result = ma_decoder__postinit(&config, pDecoder); if (result != MA_SUCCESS) { - /* - The backend was initialized successfully, but for some reason post-initialization failed. This is most likely - due to an out of memory error. We're going to abort with an error here and not try to recover. - */ - if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onUninit != NULL) { - pDecoder->pBackendVTable->onUninit(pDecoder->pBackendUserData, &pDecoder->pBackend, &pDecoder->allocationCallbacks); - } - return result; } } else { @@ -64279,8 +66573,7 @@ MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, cons #if defined(MA_HAS_WAV) || \ defined(MA_HAS_MP3) || \ defined(MA_HAS_FLAC) || \ - defined(MA_HAS_VORBIS) || \ - defined(MA_HAS_OPUS) + defined(MA_HAS_VORBIS) #define MA_HAS_PATH_API #endif @@ -64422,14 +66715,16 @@ static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* e ext1 = extension; ext2 = ma_path_extension_w(path); -#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__) - return _wcsicmp(ext1, ext2) == 0; -#else - /* - I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This - isn't the most efficient way to do it, but it should work OK. - */ + #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)) && !defined(MA_XBOX_NXDK) { + return _wcsicmp(ext1, ext2) == 0; + } + #elif !defined(MA_XBOX_NXDK) && !defined(MA_DOS) + { + /* + I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This + isn't the most efficient way to do it, but it should work OK. + */ char ext1MB[4096]; char ext2MB[4096]; const wchar_t* pext1 = ext1; @@ -64449,7 +66744,13 @@ static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* e return strcasecmp(ext1MB, ext2MB) == 0; } -#endif + #else + { + /* Getting here means we don't have a way to do a case-sensitive comparison for wide strings. Fall back to a simple case-sensitive comparison. */ + /* TODO: Implement our own wchar_t-to-char conversion routine and then use the char* version for comparing. */ + return ma_wcscmp(ext1, ext2) == 0; + } + #endif } #endif /* MA_HAS_PATH_API */ @@ -64550,11 +66851,9 @@ MA_API ma_result ma_decoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const We use trial and error to open a decoder. We prioritize custom decoders so that if they implement the same encoding format they take priority over the built-in decoders. */ + result = ma_decoder_init_custom__internal(&config, pDecoder); if (result != MA_SUCCESS) { - result = ma_decoder_init_custom__internal(&config, pDecoder); - if (result != MA_SUCCESS) { - ma_decoder__on_seek_vfs(pDecoder, 0, ma_seek_origin_start); - } + ma_decoder__on_seek_vfs(pDecoder, 0, ma_seek_origin_start); } /* @@ -64683,11 +66982,9 @@ MA_API ma_result ma_decoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, c We use trial and error to open a decoder. We prioritize custom decoders so that if they implement the same encoding format they take priority over the built-in decoders. */ + result = ma_decoder_init_custom__internal(&config, pDecoder); if (result != MA_SUCCESS) { - result = ma_decoder_init_custom__internal(&config, pDecoder); - if (result != MA_SUCCESS) { - ma_decoder__on_seek_vfs(pDecoder, 0, ma_seek_origin_start); - } + ma_decoder__on_seek_vfs(pDecoder, 0, ma_seek_origin_start); } /* @@ -64869,14 +67166,6 @@ MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_co /* Initialization was successful. Finish up. */ result = ma_decoder__postinit(&config, pDecoder); if (result != MA_SUCCESS) { - /* - The backend was initialized successfully, but for some reason post-initialization failed. This is most likely - due to an out of memory error. We're going to abort with an error here and not try to recover. - */ - if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onUninit != NULL) { - pDecoder->pBackendVTable->onUninit(pDecoder->pBackendUserData, &pDecoder->pBackend, &pDecoder->allocationCallbacks); - } - return result; } } else { @@ -65019,14 +67308,6 @@ MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decod /* Initialization was successful. Finish up. */ result = ma_decoder__postinit(&config, pDecoder); if (result != MA_SUCCESS) { - /* - The backend was initialized successfully, but for some reason post-initialization failed. This is most likely - due to an out of memory error. We're going to abort with an error here and not try to recover. - */ - if (pDecoder->pBackendVTable != NULL && pDecoder->pBackendVTable->onUninit != NULL) { - pDecoder->pBackendVTable->onUninit(pDecoder->pBackendUserData, &pDecoder->pBackend, &pDecoder->allocationCallbacks); - } - return result; } } else { @@ -65095,7 +67376,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO } else { /* Getting here means we need to do data conversion. If we're seeking forward and are _not_ doing resampling we can run this in a fast path. If we're doing resampling we - need to run through each sample because we need to ensure it's internal cache is updated. + need to run through each sample because we need to ensure its internal cache is updated. */ if (pFramesOut == NULL && pDecoder->converter.hasResampler == MA_FALSE) { result = ma_data_source_read_pcm_frames(pDecoder->pBackend, NULL, frameCount, &totalFramesReadOut); @@ -65185,8 +67466,17 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO if (requiredInputFrameCount > 0) { result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn); + + /* + Note here that even if we've reached the end, we don't want to abort because there might be more output frames needing to be + generated from cached input data, which might happen if resampling is being performed. + */ + if (result != MA_SUCCESS && result != MA_AT_END) { + break; + } } else { framesReadThisIterationIn = 0; + pIntermediaryBuffer[0] = 0; /* <-- This is just to silence a static analysis warning. */ } /* @@ -65535,10 +67825,18 @@ static ma_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, m { ma_encoder* pEncoder = (ma_encoder*)pUserData; ma_result result; + ma_seek_origin maSeekOrigin; MA_ASSERT(pEncoder != NULL); - result = pEncoder->onSeek(pEncoder, offset, (origin == ma_dr_wav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current); + maSeekOrigin = ma_seek_origin_start; + if (origin == MA_DR_WAV_SEEK_CUR) { + maSeekOrigin = ma_seek_origin_current; + } else if (origin == MA_DR_WAV_SEEK_END) { + maSeekOrigin = ma_seek_origin_end; + } + + result = pEncoder->onSeek(pEncoder, offset, maSeekOrigin); if (result != MA_SUCCESS) { return MA_FALSE; } else { @@ -66667,7 +68965,7 @@ MA_API ma_result ma_noise_set_type(ma_noise* pNoise, ma_noise_type type) /* This function should never have been implemented in the first place. Changing the type dynamically is not - supported. Instead you need to uninitialize and reinitiailize a fresh `ma_noise` object. This function + supported. Instead you need to uninitialize and reinitialize a fresh `ma_noise` object. This function will be removed in version 0.12. */ MA_ASSERT(MA_FALSE); @@ -67060,7 +69358,7 @@ static MA_INLINE ma_uint32 ma_hash_getblock(const ma_uint32* blocks, int i) ma_uint32 block; /* Try silencing a sanitization warning about unaligned access by doing a memcpy() instead of assignment. */ - MA_COPY_MEMORY(&block, ma_offset_ptr(blocks, i * sizeof(block)), sizeof(block)); + MA_COPY_MEMORY(&block, ma_offset_ptr(blocks, i * (int) sizeof(block)), sizeof(block)); if (ma_is_little_endian()) { return block; @@ -67136,7 +69434,7 @@ static ma_uint32 ma_hash_string_32(const char* str) static ma_uint32 ma_hash_string_w_32(const wchar_t* str) { - return ma_hash_32(str, (int)wcslen(str) * sizeof(*str), MA_DEFAULT_HASH_SEED); + return ma_hash_32(str, (int)ma_wcslen(str) * sizeof(*str), MA_DEFAULT_HASH_SEED); } @@ -67296,6 +69594,7 @@ static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_ return ma_resource_manager_data_buffer_node_find_min(pDataBufferNode->pChildHi); } +#if 0 /* Currently unused, but might make use of this later. */ static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_buffer_node_find_inorder_predecessor(ma_resource_manager_data_buffer_node* pDataBufferNode) { MA_ASSERT(pDataBufferNode != NULL); @@ -67303,6 +69602,7 @@ static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_ return ma_resource_manager_data_buffer_node_find_max(pDataBufferNode->pChildLo); } +#endif static ma_result ma_resource_manager_data_buffer_node_remove(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode) { @@ -67653,6 +69953,7 @@ MA_API ma_resource_manager_config ma_resource_manager_config_init(void) config.decodedSampleRate = 0; config.jobThreadCount = 1; /* A single miniaudio-managed job thread by default. */ config.jobQueueCapacity = MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY; + config.resampling = ma_resampler_config_init(ma_format_unknown, 0, 0, 0, ma_resample_algorithm_linear); /* Format/channels/rate doesn't matter here. */ /* Flags. */ config.flags = 0; @@ -67713,7 +70014,7 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon pResourceManager->config.pVFS = &pResourceManager->defaultVFS; } - /* If threading has been disabled at compile time, enfore it at run time as well. */ + /* If threading has been disabled at compile time, enforce it at run time as well. */ #ifdef MA_NO_THREADING { pResourceManager->config.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING; @@ -67750,15 +70051,17 @@ MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pCon /* Custom decoding backends. */ if (pConfig->ppCustomDecodingBackendVTables != NULL && pConfig->customDecodingBackendCount > 0) { size_t sizeInBytes = sizeof(*pResourceManager->config.ppCustomDecodingBackendVTables) * pConfig->customDecodingBackendCount; + ma_decoding_backend_vtable** ppCustomDecodingBackendVTables; - pResourceManager->config.ppCustomDecodingBackendVTables = (ma_decoding_backend_vtable**)ma_malloc(sizeInBytes, &pResourceManager->config.allocationCallbacks); + ppCustomDecodingBackendVTables = (ma_decoding_backend_vtable**)ma_malloc(sizeInBytes, &pResourceManager->config.allocationCallbacks); if (pResourceManager->config.ppCustomDecodingBackendVTables == NULL) { ma_job_queue_uninit(&pResourceManager->jobQueue, &pResourceManager->config.allocationCallbacks); return MA_OUT_OF_MEMORY; } - MA_COPY_MEMORY(pResourceManager->config.ppCustomDecodingBackendVTables, pConfig->ppCustomDecodingBackendVTables, sizeInBytes); + MA_COPY_MEMORY(ppCustomDecodingBackendVTables, pConfig->ppCustomDecodingBackendVTables, sizeInBytes); + pResourceManager->config.ppCustomDecodingBackendVTables = ppCustomDecodingBackendVTables; pResourceManager->config.customDecodingBackendCount = pConfig->customDecodingBackendCount; pResourceManager->config.pCustomDecodingBackendUserData = pConfig->pCustomDecodingBackendUserData; } @@ -67809,7 +70112,7 @@ static void ma_resource_manager_delete_all_data_buffer_nodes(ma_resource_manager ma_resource_manager_data_buffer_node* pDataBufferNode = pResourceManager->pRootDataBufferNode; ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBufferNode); - /* The data buffer has been removed from the BST, so now we need to free it's data. */ + /* The data buffer has been removed from the BST, so now we need to free its data. */ ma_resource_manager_data_buffer_node_free(pResourceManager, pDataBufferNode); } } @@ -67822,7 +70125,7 @@ MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager) /* Job threads need to be killed first. To do this we need to post a quit message to the message queue and then wait for the thread. The quit message will never be removed from the - queue which means it will never not be returned after being encounted for the first time which means all threads will eventually receive it. + queue which means it will never not be returned after being encountered for the first time which means all threads will eventually receive it. */ ma_resource_manager_post_job_quit(pResourceManager); @@ -67862,7 +70165,7 @@ MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager) #endif } - ma_free(pResourceManager->config.ppCustomDecodingBackendVTables, &pResourceManager->config.allocationCallbacks); + ma_free((ma_decoding_backend_vtable**)pResourceManager->config.ppCustomDecodingBackendVTables, &pResourceManager->config.allocationCallbacks); /* <-- Naughty const-cast, but this is safe. */ if (pResourceManager->config.pLog == &pResourceManager->log) { ma_log_uninit(&pResourceManager->log); @@ -67904,6 +70207,7 @@ static ma_decoder_config ma_resource_manager__init_decoder_config(ma_resource_ma config.ppCustomBackendVTables = pResourceManager->config.ppCustomDecodingBackendVTables; config.customBackendCount = pResourceManager->config.customDecodingBackendCount; config.pCustomBackendUserData = pResourceManager->config.pCustomDecodingBackendUserData; + config.resampling = pResourceManager->config.resampling; return config; } @@ -68280,7 +70584,7 @@ static ma_result ma_resource_manager_data_buffer_node_decode_next_page(ma_resour } result = ma_decoder_read_pcm_frames(pDecoder, pPage->pAudioData, framesToTryReading, &framesRead); - if (framesRead > 0) { + if (result == MA_SUCCESS && framesRead > 0) { pPage->sizeInFrames = framesRead; result = ma_paged_audio_buffer_data_append_page(&pDataBufferNode->data.backend.decodedPaged.data, pPage); @@ -68423,17 +70727,20 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m /* Failed to post job. Probably ran out of memory. */ ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE job. %s.\n", ma_result_description(result)); - /* - Fences were acquired before posting the job, but since the job was not able to - be posted, we need to make sure we release them so nothing gets stuck waiting. - */ - if (pInitFence != NULL) { ma_fence_release(pInitFence); } - if (pDoneFence != NULL) { ma_fence_release(pDoneFence); } - if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) { ma_resource_manager_inline_notification_uninit(pInitNotification); } else { - /* These will have been freed by the job thread, but with WAIT_INIT they will already have happend sinced the job has already been handled. */ + /* + Fences were acquired before posting the job, but since the job was not able to + be posted, we need to make sure we release them so nothing gets stuck waiting. + + In the WAIT_INIT case, these will have already been released in ma_job_process() + so we should only release fences in this branch. + */ + if (pInitFence != NULL) { ma_fence_release(pInitFence); } + if (pDoneFence != NULL) { ma_fence_release(pDoneFence); } + + /* These will have been freed by the job thread, but with WAIT_INIT they will already have happened since the job has already been handled. */ ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks); ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks); } @@ -68798,6 +71105,10 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma flags &= ~MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC; } + if (pConfig->isLooping) { + flags |= MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING; + } + async = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) != 0; /* @@ -68810,7 +71121,7 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma These fences are always released at the "done" tag at the end of this function. They'll be acquired a second if loading asynchronously. This double acquisition system is just done to - simplify code maintanence. + simplify code maintenance. */ ma_resource_manager_pipeline_notifications_acquire_all_fences(¬ifications); { @@ -68855,7 +71166,7 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma /* The status of the data buffer needs to be set to MA_BUSY before posting the job so that the - worker thread is aware of it's busy state. If the LOAD_DATA_BUFFER job sees a status other + worker thread is aware of its busy state. If the LOAD_DATA_BUFFER job sees a status other than MA_BUSY, it'll assume an error and fall through to an early exit. */ ma_atomic_exchange_i32(&pDataBuffer->result, MA_BUSY); @@ -68874,7 +71185,7 @@ static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_ma job.data.resourceManager.loadDataBuffer.rangeEndInPCMFrames = pConfig->rangeEndInPCMFrames; job.data.resourceManager.loadDataBuffer.loopPointBegInPCMFrames = pConfig->loopPointBegInPCMFrames; job.data.resourceManager.loadDataBuffer.loopPointEndInPCMFrames = pConfig->loopPointEndInPCMFrames; - job.data.resourceManager.loadDataBuffer.isLooping = pConfig->isLooping; + job.data.resourceManager.loadDataBuffer.isLooping = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING) != 0; /* If we need to wait for initialization to complete we can just process the job in place. */ if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) { @@ -69095,22 +71406,29 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man isDecodedBufferBusy = (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY); if (ma_resource_manager_data_buffer_get_available_frames(pDataBuffer, &availableFrames) == MA_SUCCESS) { - /* Don't try reading more than the available frame count. */ - if (frameCount > availableFrames) { - frameCount = availableFrames; + /* Don't try reading more than the available frame count if the data buffer node is still loading. */ + if (isDecodedBufferBusy) { + if (frameCount > availableFrames) { + frameCount = availableFrames; - /* - If there's no frames available we want to set the status to MA_AT_END. The logic below - will check if the node is busy, and if so, change it to MA_BUSY. The reason we do this - is because we don't want to call `ma_data_source_read_pcm_frames()` if the frame count - is 0 because that'll result in a situation where it's possible MA_AT_END won't get - returned. - */ - if (frameCount == 0) { - result = MA_AT_END; + /* + If there's no frames available we want to set the status to MA_AT_END. The logic below + will check if the node is busy, and if so, change it to MA_BUSY. The reason we do this + is because we don't want to call `ma_data_source_read_pcm_frames()` if the frame count + is 0 because that'll result in a situation where it's possible MA_AT_END won't get + returned. + */ + if (frameCount == 0) { + result = MA_AT_END; + } + } else { + isDecodedBufferBusy = MA_FALSE; /* We have enough frames available in the buffer to avoid a MA_BUSY status. */ } } else { - isDecodedBufferBusy = MA_FALSE; /* We have enough frames available in the buffer to avoid a MA_BUSY status. */ + /* + Getting here means the buffer has been fully loaded. We can just pass the frame count straight + into ma_data_source_read_pcm_frames() below and let ma_data_source handle it. + */ } } } @@ -69215,13 +71533,13 @@ MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_man MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pCursor) { - /* We cannot be using the data source after it's been uninitialized. */ - MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE); - if (pDataBuffer == NULL || pCursor == NULL) { return MA_INVALID_ARGS; } + /* We cannot be using the data source after it's been uninitialized. */ + MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE); + *pCursor = 0; switch (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode)) @@ -69255,13 +71573,13 @@ MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_res MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength) { - /* We cannot be using the data source after it's been uninitialized. */ - MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE); - if (pDataBuffer == NULL || pLength == NULL) { return MA_INVALID_ARGS; } + /* We cannot be using the data source after it's been uninitialized. */ + MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE); + if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) { return MA_BUSY; /* Still loading. */ } @@ -69510,6 +71828,7 @@ MA_API ma_result ma_resource_manager_data_stream_init_ex(ma_resource_manager* pR ma_bool32 waitBeforeReturning = MA_FALSE; ma_resource_manager_inline_notification waitNotification; ma_resource_manager_pipeline_notifications notifications; + ma_uint32 flags; if (pDataStream == NULL) { if (pConfig != NULL && pConfig->pNotifications != NULL) { @@ -69540,13 +71859,18 @@ MA_API ma_result ma_resource_manager_data_stream_init_ex(ma_resource_manager* pR return result; } + flags = pConfig->flags; + if (pConfig->isLooping) { + flags |= MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING; + } + pDataStream->pResourceManager = pResourceManager; pDataStream->flags = pConfig->flags; pDataStream->result = MA_BUSY; ma_data_source_set_range_in_pcm_frames(pDataStream, pConfig->rangeBegInPCMFrames, pConfig->rangeEndInPCMFrames); ma_data_source_set_loop_point_in_pcm_frames(pDataStream, pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames); - ma_data_source_set_looping(pDataStream, pConfig->isLooping); + ma_data_source_set_looping(pDataStream, (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING) != 0); if (pResourceManager == NULL || (pConfig->pFilePath == NULL && pConfig->pFilePathW == NULL)) { ma_resource_manager_pipeline_notifications_signal_all_notifications(¬ifications); @@ -70168,6 +72492,9 @@ static ma_result ma_resource_manager_data_source_preinit(ma_resource_manager* pR } pDataSource->flags = pConfig->flags; + if (pConfig->isLooping) { + pDataSource->flags |= MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING; + } return MA_SUCCESS; } @@ -70607,8 +72934,6 @@ static ma_result ma_job_process__resource_manager__free_data_buffer_node(ma_job* return ma_resource_manager_post_job(pResourceManager, pJob); /* Out of order. */ } - ma_resource_manager_data_buffer_node_free(pResourceManager, pDataBufferNode); - /* The event needs to be signalled last. */ if (pJob->data.resourceManager.freeDataBufferNode.pDoneNotification != NULL) { ma_async_notification_signal(pJob->data.resourceManager.freeDataBufferNode.pDoneNotification); @@ -70619,6 +72944,9 @@ static ma_result ma_job_process__resource_manager__free_data_buffer_node(ma_job* } ma_atomic_fetch_add_32(&pDataBufferNode->executionPointer, 1); + + ma_resource_manager_data_buffer_node_free(pResourceManager, pDataBufferNode); + return MA_SUCCESS; } @@ -70726,9 +73054,10 @@ static ma_result ma_job_process__resource_manager__load_data_buffer(ma_job* pJob */ result = ma_resource_manager_data_buffer_result(pDataBuffer); if (result != MA_BUSY) { - goto done; /* <-- This will ensure the exucution pointer is incremented. */ + goto done; /* <-- This will ensure the execution pointer is incremented. */ } else { result = MA_SUCCESS; /* <-- Make sure this is reset. */ + (void)result; /* <-- This is to suppress a static analysis diagnostic about "result" not being used. But for safety when I do future maintenance I don't want to delete that assignment. */ } /* Try initializing the connector if we haven't already. */ @@ -71075,11 +73404,74 @@ static ma_result ma_job_process__resource_manager__seek_data_stream(ma_job* pJob #ifndef MA_NO_NODE_GRAPH + +static ma_stack* ma_stack_init(size_t sizeInBytes, const ma_allocation_callbacks* pAllocationCallbacks) +{ + ma_stack* pStack; + + if (sizeInBytes == 0) { + return NULL; + } + + pStack = (ma_stack*)ma_malloc(sizeof(*pStack) - sizeof(pStack->_data) + sizeInBytes, pAllocationCallbacks); + if (pStack == NULL) { + return NULL; + } + + pStack->offset = 0; + pStack->sizeInBytes = sizeInBytes; + + return pStack; +} + +static void ma_stack_uninit(ma_stack* pStack, const ma_allocation_callbacks* pAllocationCallbacks) +{ + if (pStack == NULL) { + return; + } + + ma_free(pStack, pAllocationCallbacks); +} + +static void* ma_stack_alloc(ma_stack* pStack, size_t sz) +{ + /* The size of the allocation is stored in the memory directly before the pointer. This needs to include padding to keep it aligned to ma_uintptr */ + void* p = (void*)((char*)pStack->_data + pStack->offset); + size_t* pSize = (size_t*)p; + + sz = (sz + (sizeof(ma_uintptr) - 1)) & ~(sizeof(ma_uintptr) - 1); /* Padding. */ + if (pStack->offset + sz + sizeof(size_t) > pStack->sizeInBytes) { + return NULL; /* Out of memory. */ + } + + pStack->offset += sz + sizeof(size_t); + + *pSize = sz; + return (void*)((char*)p + sizeof(size_t)); +} + +static void ma_stack_free(ma_stack* pStack, void* p) +{ + size_t* pSize; + + if (p == NULL) { + return; + } + + pSize = (size_t*)p - 1; + pStack->offset -= *pSize + sizeof(size_t); +} + + + /* 10ms @ 48K = 480. Must never exceed 65535. */ #ifndef MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS #define MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS 480 #endif +#ifndef MA_DEFAULT_PREMIX_STACK_SIZE_PER_CHANNEL +#define MA_DEFAULT_PREMIX_STACK_SIZE_PER_CHANNEL 524288 +#endif static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusIndex, float* pFramesOut, ma_uint32 frameCount, ma_uint32* pFramesRead, ma_uint64 globalTime); @@ -71119,8 +73511,8 @@ MA_API ma_node_graph_config ma_node_graph_config_init(ma_uint32 channels) ma_node_graph_config config; MA_ZERO_OBJECT(&config); - config.channels = channels; - config.nodeCacheCapInFrames = MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS; + config.channels = channels; + config.processingSizeInFrames = 0; return config; } @@ -71207,11 +73599,7 @@ MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const m } MA_ZERO_OBJECT(pNodeGraph); - pNodeGraph->nodeCacheCapInFrames = pConfig->nodeCacheCapInFrames; - if (pNodeGraph->nodeCacheCapInFrames == 0) { - pNodeGraph->nodeCacheCapInFrames = MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS; - } - + pNodeGraph->processingSizeInFrames = pConfig->processingSizeInFrames; /* Base node so we can use the node graph as a node into another graph. */ baseConfig = ma_node_config_init(); @@ -71236,6 +73624,40 @@ MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const m return result; } + + /* Processing cache. */ + if (pConfig->processingSizeInFrames > 0) { + pNodeGraph->pProcessingCache = (float*)ma_malloc(pConfig->processingSizeInFrames * pConfig->channels * sizeof(float), pAllocationCallbacks); + if (pNodeGraph->pProcessingCache == NULL) { + ma_node_uninit(&pNodeGraph->endpoint, pAllocationCallbacks); + ma_node_uninit(&pNodeGraph->base, pAllocationCallbacks); + return MA_OUT_OF_MEMORY; + } + } + + + /* + We need a pre-mix stack. The size of this stack is configurable via the config. The default value depends on the channel count. + */ + { + size_t preMixStackSizeInBytes = pConfig->preMixStackSizeInBytes; + if (preMixStackSizeInBytes == 0) { + preMixStackSizeInBytes = pConfig->channels * MA_DEFAULT_PREMIX_STACK_SIZE_PER_CHANNEL; + } + + pNodeGraph->pPreMixStack = ma_stack_init(preMixStackSizeInBytes, pAllocationCallbacks); + if (pNodeGraph->pPreMixStack == NULL) { + ma_node_uninit(&pNodeGraph->endpoint, pAllocationCallbacks); + ma_node_uninit(&pNodeGraph->base, pAllocationCallbacks); + if (pNodeGraph->pProcessingCache != NULL) { + ma_free(pNodeGraph->pProcessingCache, pAllocationCallbacks); + } + + return MA_OUT_OF_MEMORY; + } + } + + return MA_SUCCESS; } @@ -71246,6 +73668,17 @@ MA_API void ma_node_graph_uninit(ma_node_graph* pNodeGraph, const ma_allocation_ } ma_node_uninit(&pNodeGraph->endpoint, pAllocationCallbacks); + ma_node_uninit(&pNodeGraph->base, pAllocationCallbacks); + + if (pNodeGraph->pProcessingCache != NULL) { + ma_free(pNodeGraph->pProcessingCache, pAllocationCallbacks); + pNodeGraph->pProcessingCache = NULL; + } + + if (pNodeGraph->pPreMixStack != NULL) { + ma_stack_uninit(pNodeGraph->pPreMixStack, pAllocationCallbacks); + pNodeGraph->pPreMixStack = NULL; + } } MA_API ma_node* ma_node_graph_get_endpoint(ma_node_graph* pNodeGraph) @@ -71278,27 +73711,72 @@ MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void* totalFramesRead = 0; while (totalFramesRead < frameCount) { ma_uint32 framesJustRead; - ma_uint64 framesToRead = frameCount - totalFramesRead; + ma_uint64 framesToRead; + float* pRunningFramesOut; + framesToRead = frameCount - totalFramesRead; if (framesToRead > 0xFFFFFFFF) { framesToRead = 0xFFFFFFFF; } - ma_node_graph_set_is_reading(pNodeGraph, MA_TRUE); - { - result = ma_node_read_pcm_frames(&pNodeGraph->endpoint, 0, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), (ma_uint32)framesToRead, &framesJustRead, ma_node_get_time(&pNodeGraph->endpoint)); - } - ma_node_graph_set_is_reading(pNodeGraph, MA_FALSE); + pRunningFramesOut = (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels); - totalFramesRead += framesJustRead; + /* If there's anything in the cache, consume that first. */ + if (pNodeGraph->processingCacheFramesRemaining > 0) { + ma_uint32 framesToReadFromCache; - if (result != MA_SUCCESS) { - break; - } + framesToReadFromCache = (ma_uint32)framesToRead; + if (framesToReadFromCache > pNodeGraph->processingCacheFramesRemaining) { + framesToReadFromCache = pNodeGraph->processingCacheFramesRemaining; + } - /* Abort if we weren't able to read any frames or else we risk getting stuck in a loop. */ - if (framesJustRead == 0) { - break; + MA_COPY_MEMORY(pRunningFramesOut, pNodeGraph->pProcessingCache, framesToReadFromCache * channels * sizeof(float)); + MA_MOVE_MEMORY(pNodeGraph->pProcessingCache, pNodeGraph->pProcessingCache + (framesToReadFromCache * channels), (pNodeGraph->processingCacheFramesRemaining - framesToReadFromCache) * channels * sizeof(float)); + pNodeGraph->processingCacheFramesRemaining -= framesToReadFromCache; + + totalFramesRead += framesToReadFromCache; + continue; + } else { + /* + If processingSizeInFrames is non-zero, we need to make sure we always read in chunks of that size. If the frame count is less than + that, we need to read into the cache and then continue on. + */ + float* pReadDst = pRunningFramesOut; + + if (pNodeGraph->processingSizeInFrames > 0) { + if (framesToRead < pNodeGraph->processingSizeInFrames) { + pReadDst = pNodeGraph->pProcessingCache; /* We need to read into the cache because otherwise we'll overflow the output buffer. */ + } + + framesToRead = pNodeGraph->processingSizeInFrames; + } + + ma_node_graph_set_is_reading(pNodeGraph, MA_TRUE); + { + result = ma_node_read_pcm_frames(&pNodeGraph->endpoint, 0, pReadDst, (ma_uint32)framesToRead, &framesJustRead, ma_node_get_time(&pNodeGraph->endpoint)); + } + ma_node_graph_set_is_reading(pNodeGraph, MA_FALSE); + + /* + Do not increment the total frames read counter if we read into the cache. We use this to determine how many frames have + been written to the final output buffer. + */ + if (pReadDst == pNodeGraph->pProcessingCache) { + /* We read into the cache. */ + pNodeGraph->processingCacheFramesRemaining = framesJustRead; + } else { + /* We read straight into the output buffer. */ + totalFramesRead += framesJustRead; + } + + if (result != MA_SUCCESS) { + break; + } + + /* Abort if we weren't able to read any frames or else we risk getting stuck in a loop. */ + if (framesJustRead == 0) { + break; + } } } @@ -71341,6 +73819,15 @@ MA_API ma_result ma_node_graph_set_time(ma_node_graph* pNodeGraph, ma_uint64 glo return ma_node_set_time(&pNodeGraph->endpoint, globalTime); /* Global time is just the local time of the endpoint. */ } +MA_API ma_uint32 ma_node_graph_get_processing_size_in_frames(const ma_node_graph* pNodeGraph) +{ + if (pNodeGraph == NULL) { + return 0; + } + + return pNodeGraph->processingSizeInFrames; +} + #define MA_NODE_OUTPUT_BUS_FLAG_HAS_READ 0x01 /* Whether or not this bus ready to read more data. Only used on nodes with multiple output buses. */ @@ -71499,7 +73986,7 @@ static void ma_node_input_bus_detach__no_output_bus_lock(ma_node_input_bus* pInp *not* using a lock when iterating over the list in the audio thread. We therefore need to craft this in a way such that the iteration on the audio thread doesn't break. - The the first thing to do is swap out the "next" pointer of the previous output bus with the + The first thing to do is swap out the "next" pointer of the previous output bus with the new "next" output bus. This is the operation that matters for iteration on the audio thread. After that, the previous pointer on the new "next" pointer needs to be updated, after which point the linked list will be in a good state. @@ -71592,7 +74079,7 @@ static void ma_node_input_bus_attach(ma_node_input_bus* pInputBus, ma_node_outpu /* Now we need to attach the output bus to the linked list. This involves updating two pointers on two different output buses so I'm going to go ahead and keep this simple and just use a lock. - There are ways to do this without a lock, but it's just too hard to maintain for it's value. + There are ways to do this without a lock, but it's just too hard to maintain for its value. Although we're locking here, it's important to remember that we're *not* locking when iterating and reading audio data since that'll be running on the audio thread. As a result we need to be @@ -71685,11 +74172,9 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_ ma_uint32 inputChannels; ma_bool32 doesOutputBufferHaveContent = MA_FALSE; - (void)pInputNode; /* Not currently used. */ - /* This will be called from the audio thread which means we can't be doing any locking. Basically, - this function will not perfom any locking, whereas attaching and detaching will, but crafted in + this function will not perform any locking, whereas attaching and detaching will, but crafted in such a way that we don't need to perform any locking here. The important thing to remember is to always iterate in a forward direction. @@ -71735,19 +74220,12 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_ if (pFramesOut != NULL) { /* Read. */ - float temp[MA_DATA_CONVERTER_STACK_BUFFER_SIZE / sizeof(float)]; - ma_uint32 tempCapInFrames = ma_countof(temp) / inputChannels; - while (framesProcessed < frameCount) { float* pRunningFramesOut; ma_uint32 framesToRead; - ma_uint32 framesJustRead; + ma_uint32 framesJustRead = 0; framesToRead = frameCount - framesProcessed; - if (framesToRead > tempCapInFrames) { - framesToRead = tempCapInFrames; - } - pRunningFramesOut = ma_offset_pcm_frames_ptr_f32(pFramesOut, framesProcessed, inputChannels); if (doesOutputBufferHaveContent == MA_FALSE) { @@ -71755,11 +74233,32 @@ static ma_result ma_node_input_bus_read_pcm_frames(ma_node* pInputNode, ma_node_ result = ma_node_read_pcm_frames(pOutputBus->pNode, pOutputBus->outputBusIndex, pRunningFramesOut, framesToRead, &framesJustRead, globalTime + framesProcessed); } else { /* Slow path. Not the first attachment. Mixing required. */ - result = ma_node_read_pcm_frames(pOutputBus->pNode, pOutputBus->outputBusIndex, temp, framesToRead, &framesJustRead, globalTime + framesProcessed); - if (result == MA_SUCCESS || result == MA_AT_END) { - if (isSilentOutput == MA_FALSE) { /* Don't mix if the node outputs silence. */ - ma_mix_pcm_frames_f32(pRunningFramesOut, temp, framesJustRead, inputChannels, /*volume*/1); + ma_uint32 preMixBufferCapInFrames = ((ma_node_base*)pInputNode)->cachedDataCapInFramesPerBus; + float* pPreMixBuffer = (float*)ma_stack_alloc(((ma_node_base*)pInputNode)->pNodeGraph->pPreMixStack, preMixBufferCapInFrames * inputChannels * sizeof(float)); + + if (pPreMixBuffer == NULL) { + /* + If you're hitting this assert it means you've got an unusually deep chain of nodes, you've got an excessively large processing + size, or you have a combination of both, and as a result have run out of stack space. You can increase this using the + preMixStackSizeInBytes variable in ma_node_graph_config. If you're using ma_engine, you can do it via the preMixStackSizeInBytes + variable in ma_engine_config. It defaults to 512KB per output channel. + */ + MA_ASSERT(MA_FALSE); + } else { + if (framesToRead > preMixBufferCapInFrames) { + framesToRead = preMixBufferCapInFrames; } + + result = ma_node_read_pcm_frames(pOutputBus->pNode, pOutputBus->outputBusIndex, pPreMixBuffer, framesToRead, &framesJustRead, globalTime + framesProcessed); + if (result == MA_SUCCESS || result == MA_AT_END) { + if (isSilentOutput == MA_FALSE) { /* Don't mix if the node outputs silence. */ + ma_mix_pcm_frames_f32(pRunningFramesOut, pPreMixBuffer, framesJustRead, inputChannels, /*volume*/1); + } + } + + /* The pre-mix buffer is no longer required. */ + ma_stack_free(((ma_node_base*)pInputNode)->pNodeGraph->pPreMixStack, pPreMixBuffer); + pPreMixBuffer = NULL; } } @@ -71814,6 +74313,25 @@ MA_API ma_node_config ma_node_config_init(void) return config; } +static ma_uint16 ma_node_config_get_cache_size_in_frames(const ma_node_config* pConfig, const ma_node_graph* pNodeGraph) +{ + ma_uint32 cacheSizeInFrames; + + (void)pConfig; + + if (pNodeGraph->processingSizeInFrames > 0) { + cacheSizeInFrames = pNodeGraph->processingSizeInFrames; + } else { + cacheSizeInFrames = MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS; + } + + if (cacheSizeInFrames > 0xFFFF) { + cacheSizeInFrames = 0xFFFF; + } + + return (ma_uint16)cacheSizeInFrames; +} + static ma_result ma_node_detach_full(ma_node* pNode); @@ -71968,7 +74486,7 @@ static ma_result ma_node_get_heap_layout(ma_node_graph* pNodeGraph, const ma_nod /* Cached audio data. - We need to allocate memory for a caching both input and output data. We have an optimization + We need to allocate memory for caching both input and output data. We have an optimization where no caching is necessary for specific conditions: - The node has 0 inputs and 1 output. @@ -71987,14 +74505,18 @@ static ma_result ma_node_get_heap_layout(ma_node_graph* pNodeGraph, const ma_nod } else { /* Slow path. Cache needed. */ size_t cachedDataSizeInBytes = 0; + ma_uint32 cacheCapInFrames; ma_uint32 iBus; + /* The capacity of the cache is based on our callback processing size. */ + cacheCapInFrames = ma_node_config_get_cache_size_in_frames(pConfig, pNodeGraph); + for (iBus = 0; iBus < inputBusCount; iBus += 1) { - cachedDataSizeInBytes += pNodeGraph->nodeCacheCapInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->pInputChannels[iBus]); + cachedDataSizeInBytes += cacheCapInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->pInputChannels[iBus]); } for (iBus = 0; iBus < outputBusCount; iBus += 1) { - cachedDataSizeInBytes += pNodeGraph->nodeCacheCapInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->pOutputChannels[iBus]); + cachedDataSizeInBytes += cacheCapInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->pOutputChannels[iBus]); } pHeapLayout->cachedDataOffset = pHeapLayout->sizeInBytes; @@ -72080,13 +74602,12 @@ MA_API ma_result ma_node_init_preallocated(ma_node_graph* pNodeGraph, const ma_n if (heapLayout.cachedDataOffset != MA_SIZE_MAX) { pNodeBase->pCachedData = (float*)ma_offset_ptr(pHeap, heapLayout.cachedDataOffset); - pNodeBase->cachedDataCapInFramesPerBus = pNodeGraph->nodeCacheCapInFrames; + pNodeBase->cachedDataCapInFramesPerBus = ma_node_config_get_cache_size_in_frames(pConfig, pNodeGraph); } else { pNodeBase->pCachedData = NULL; } - /* We need to run an initialization step for each input and output bus. */ for (iInputBus = 0; iInputBus < ma_node_get_input_bus_count(pNodeBase); iInputBus += 1) { result = ma_node_input_bus_init(pConfig->pInputChannels[iInputBus], &pNodeBase->pInputBuses[iInputBus]); @@ -72260,7 +74781,7 @@ static ma_result ma_node_detach_full(ma_node* pNode) /* At this point all output buses will have been detached from the graph and we can be guaranteed - that none of it's input nodes will be getting processed by the graph. We can detach these + that none of its input nodes will be getting processed by the graph. We can detach these without needing to worry about the audio thread touching them. */ for (iInputBus = 0; iInputBus < ma_node_get_input_bus_count(pNode); iInputBus += 1) { @@ -72275,7 +74796,7 @@ static ma_result ma_node_detach_full(ma_node* pNode) linked list logic. We don't need to worry about the audio thread referencing these because the step above severed the connection to the graph. */ - for (pOutputBus = (ma_node_output_bus*)ma_atomic_load_ptr(&pInputBus->head.pNext); pOutputBus != NULL; pOutputBus = (ma_node_output_bus*)ma_atomic_load_ptr(&pOutputBus->pNext)) { + for (pOutputBus = (ma_node_output_bus*)ma_atomic_load_ptr(&pInputBus->head.pNext); pOutputBus != NULL; pOutputBus = (ma_node_output_bus*)ma_atomic_load_ptr(&pInputBus->head.pNext)) { ma_node_detach_output_bus(pOutputBus->pNode, pOutputBus->outputBusIndex); /* This won't do any waiting in practice and should be efficient. */ } } @@ -72297,7 +74818,7 @@ MA_API ma_result ma_node_detach_output_bus(ma_node* pNode, ma_uint32 outputBusIn return MA_INVALID_ARGS; /* Invalid output bus index. */ } - /* We need to lock the output bus because we need to inspect the input node and grab it's input bus. */ + /* We need to lock the output bus because we need to inspect the input node and grab its input bus. */ ma_node_output_bus_lock(&pNodeBase->pOutputBuses[outputBusIndex]); { pInputNodeBase = (ma_node_base*)pNodeBase->pOutputBuses[outputBusIndex].pInputNode; @@ -72463,18 +74984,18 @@ MA_API ma_node_state ma_node_get_state_by_time_range(const ma_node* pNode, ma_ui /* Getting here means the node is marked as started, but it may still not be truly started due to - it's start time not having been reached yet. Also, the stop time may have also been reached in + its start time not having been reached yet. Also, the stop time may have also been reached in which case it'll be considered stopped. */ - if (ma_node_get_state_time(pNode, ma_node_state_started) > globalTimeBeg) { - return ma_node_state_stopped; /* Start time has not yet been reached. */ + if (ma_node_get_state_time(pNode, ma_node_state_stopped) < globalTimeBeg) { + return ma_node_state_stopped; /* End time is before the start of the range. */ } - if (ma_node_get_state_time(pNode, ma_node_state_stopped) <= globalTimeEnd) { - return ma_node_state_stopped; /* Stop time has been reached. */ + if (ma_node_get_state_time(pNode, ma_node_state_started) > globalTimeEnd) { + return ma_node_state_stopped; /* Start time is after the end of the range. */ } - /* Getting here means the node is marked as started and is within it's start/stop times. */ + /* Getting here means the node is marked as started and is within its start/stop times. */ return ma_node_state_started; } @@ -72551,14 +75072,14 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde return MA_INVALID_ARGS; /* Invalid output bus index. */ } + globalTimeBeg = globalTime; + globalTimeEnd = globalTime + frameCount; + /* Don't do anything if we're in a stopped state. */ - if (ma_node_get_state_by_time_range(pNode, globalTime, globalTime + frameCount) != ma_node_state_started) { + if (ma_node_get_state_by_time_range(pNode, globalTimeBeg, globalTimeEnd) != ma_node_state_started) { return MA_SUCCESS; /* We're in a stopped state. This is not an error - we just need to not read anything. */ } - - globalTimeBeg = globalTime; - globalTimeEnd = globalTime + frameCount; startTime = ma_node_get_state_time(pNode, ma_node_state_started); stopTime = ma_node_get_state_time(pNode, ma_node_state_stopped); @@ -72571,11 +75092,16 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde therefore need to offset it by a number of frames to accommodate. The same thing applies for the stop time. */ - timeOffsetBeg = (globalTimeBeg < startTime) ? (ma_uint32)(globalTimeEnd - startTime) : 0; + timeOffsetBeg = (globalTimeBeg < startTime) ? (ma_uint32)(startTime - globalTimeBeg) : 0; timeOffsetEnd = (globalTimeEnd > stopTime) ? (ma_uint32)(globalTimeEnd - stopTime) : 0; /* Trim based on the start offset. We need to silence the start of the buffer. */ if (timeOffsetBeg > 0) { + MA_ASSERT(timeOffsetBeg <= frameCount); + if (timeOffsetBeg > frameCount) { + timeOffsetBeg = frameCount; + } + ma_silence_pcm_frames(pFramesOut, timeOffsetBeg, ma_format_f32, ma_node_get_output_channels(pNode, outputBusIndex)); pFramesOut += timeOffsetBeg * ma_node_get_output_channels(pNode, outputBusIndex); frameCount -= timeOffsetBeg; @@ -72583,6 +75109,11 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde /* Trim based on the end offset. We don't need to silence the tail section because we'll just have a reduced value written to pFramesRead. */ if (timeOffsetEnd > 0) { + MA_ASSERT(timeOffsetEnd <= frameCount); + if (timeOffsetEnd > frameCount) { + timeOffsetEnd = frameCount; + } + frameCount -= timeOffsetEnd; } @@ -72636,12 +75167,12 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde frameCountOut = totalFramesRead; if (totalFramesRead > 0) { - ma_node_process_pcm_frames_internal(pNode, (const float**)ppFramesIn, &frameCountIn, ppFramesOut, &frameCountOut); /* From GCC: expected 'const float **' but argument is of type 'float **'. Shouldn't this be implicit? Excplicit cast to silence the warning. */ + ma_node_process_pcm_frames_internal(pNode, (const float**)ppFramesIn, &frameCountIn, ppFramesOut, &frameCountOut); /* From GCC: expected 'const float **' but argument is of type 'float **'. Shouldn't this be implicit? Explicit cast to silence the warning. */ } /* A passthrough should never have modified the input and output frame counts. If you're - triggering these assers you need to fix your processing callback. + triggering these asserts you need to fix your processing callback. */ MA_ASSERT(frameCountIn == totalFramesRead); MA_ASSERT(frameCountOut == totalFramesRead); @@ -72819,7 +75350,7 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde frames available right now. */ if (frameCountIn > 0 || (pNodeBase->vtable->flags & MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES) != 0) { - ma_node_process_pcm_frames_internal(pNode, (const float**)ppFramesIn, &frameCountIn, ppFramesOut, &frameCountOut); /* From GCC: expected 'const float **' but argument is of type 'float **'. Shouldn't this be implicit? Excplicit cast to silence the warning. */ + ma_node_process_pcm_frames_internal(pNode, (const float**)ppFramesIn, &frameCountIn, ppFramesOut, &frameCountOut); /* From GCC: expected 'const float **' but argument is of type 'float **'. Shouldn't this be implicit? Explicit cast to silence the warning. */ } else { frameCountOut = 0; /* No data was processed. */ } @@ -73997,12 +76528,20 @@ static void ma_sound_set_at_end(ma_sound* pSound, ma_bool32 atEnd) MA_ASSERT(pSound != NULL); ma_atomic_exchange_32(&pSound->atEnd, atEnd); + /* + When this function is called the state of the sound will not yet be in a stopped state. This makes it confusing + because an end callback will intuitively expect ma_sound_is_playing() to return false from inside the callback. + I'm therefore no longer firing the callback here and will instead fire it manually in the *next* processing step + when the state should be set to stopped as expected. + */ + #if 0 /* Fire any callbacks or events. */ if (atEnd) { if (pSound->endCallback != NULL) { pSound->endCallback(pSound->pEndCallbackUserData, pSound); } } + #endif } static ma_bool32 ma_sound_get_at_end(const ma_sound* pSound) @@ -74022,6 +76561,7 @@ MA_API ma_engine_node_config ma_engine_node_config_init(ma_engine* pEngine, ma_e config.isPitchDisabled = (flags & MA_SOUND_FLAG_NO_PITCH) != 0; config.isSpatializationDisabled = (flags & MA_SOUND_FLAG_NO_SPATIALIZATION) != 0; config.monoExpansionMode = pEngine->monoExpansionMode; + config.resampling = pEngine->pitchResamplingConfig; return config; } @@ -74048,7 +76588,7 @@ static void ma_engine_node_update_pitch_if_required(ma_engine_node* pEngineNode) if (isUpdateRequired) { float basePitch = (float)pEngineNode->sampleRate / ma_engine_get_sample_rate(pEngineNode->pEngine); - ma_linear_resampler_set_rate_ratio(&pEngineNode->resampler, basePitch * pEngineNode->oldPitch * pEngineNode->oldDopplerPitch); + ma_resampler_set_rate_ratio(&pEngineNode->resampler, basePitch * pEngineNode->oldPitch * pEngineNode->oldDopplerPitch); } } @@ -74056,7 +76596,7 @@ static ma_bool32 ma_engine_node_is_pitching_enabled(const ma_engine_node* pEngin { MA_ASSERT(pEngineNode != NULL); - /* Don't try to be clever by skiping resampling in the pitch=1 case or else you'll glitch when moving away from 1. */ + /* Don't try to be clever by skipping resampling in the pitch=1 case or else you'll glitch when moving away from 1. */ return !ma_atomic_load_explicit_32(&pEngineNode->isPitchDisabled, ma_atomic_memory_order_acquire); } @@ -74067,22 +76607,6 @@ static ma_bool32 ma_engine_node_is_spatialization_enabled(const ma_engine_node* return !ma_atomic_load_explicit_32(&pEngineNode->isSpatializationDisabled, ma_atomic_memory_order_acquire); } -static ma_uint64 ma_engine_node_get_required_input_frame_count(const ma_engine_node* pEngineNode, ma_uint64 outputFrameCount) -{ - ma_uint64 inputFrameCount = 0; - - if (ma_engine_node_is_pitching_enabled(pEngineNode)) { - ma_result result = ma_linear_resampler_get_required_input_frame_count(&pEngineNode->resampler, outputFrameCount, &inputFrameCount); - if (result != MA_SUCCESS) { - inputFrameCount = 0; - } - } else { - inputFrameCount = outputFrameCount; /* No resampling, so 1:1. */ - } - - return inputFrameCount; -} - static ma_result ma_engine_node_set_volume(ma_engine_node* pEngineNode, float volume) { if (pEngineNode == NULL) { @@ -74093,7 +76617,7 @@ static ma_result ma_engine_node_set_volume(ma_engine_node* pEngineNode, float vo /* If we're not smoothing we should bypass the volume gainer entirely. */ if (pEngineNode->volumeSmoothTimeInPCMFrames == 0) { - /* We should always have an active spatializer because it can be enabled and disabled dynamically. We can just use that for hodling our volume. */ + /* We should always have an active spatializer because it can be enabled and disabled dynamically. We can just use that for holding our volume. */ ma_spatializer_set_master_volume(&pEngineNode->spatializer, volume); } else { /* We're using volume smoothing, so apply the master volume to the gainer. */ @@ -74224,7 +76748,7 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo ma_uint64 resampleFrameCountIn = framesAvailableIn; ma_uint64 resampleFrameCountOut = framesAvailableOut; - ma_linear_resampler_process_pcm_frames(&pEngineNode->resampler, pRunningFramesIn, &resampleFrameCountIn, pWorkingBuffer, &resampleFrameCountOut); + ma_resampler_process_pcm_frames(&pEngineNode->resampler, pRunningFramesIn, &resampleFrameCountIn, pWorkingBuffer, &resampleFrameCountOut); isWorkingBufferValid = MA_TRUE; framesJustProcessedIn = (ma_uint32)resampleFrameCountIn; @@ -74348,6 +76872,11 @@ static void ma_engine_node_process_pcm_frames__sound(ma_node* pNode, const float /* If we're marked at the end we need to stop the sound and do nothing. */ if (ma_sound_at_end(pSound)) { ma_sound_stop(pSound); + + if (pSound->endCallback != NULL) { + pSound->endCallback(pSound->pEndCallbackUserData, pSound); + } + *pFrameCountOut = 0; return; } @@ -74385,55 +76914,74 @@ static void ma_engine_node_process_pcm_frames__sound(ma_node* pNode, const float /* Keep reading until we've read as much as was requested or we reach the end of the data source. */ while (totalFramesRead < frameCount) { ma_uint32 framesRemaining = frameCount - totalFramesRead; - ma_uint32 framesToRead; ma_uint64 framesJustRead; ma_uint32 frameCountIn; ma_uint32 frameCountOut; const float* pRunningFramesIn; float* pRunningFramesOut; - /* - The first thing we need to do is read into the temporary buffer. We can calculate exactly - how many input frames we'll need after resampling. - */ - framesToRead = (ma_uint32)ma_engine_node_get_required_input_frame_count(&pSound->engineNode, framesRemaining); - if (framesToRead > tempCapInFrames) { - framesToRead = tempCapInFrames; - } + /* If there's any input frames sitting in the cache get those processed first. */ + if (pSound->processingCacheFramesRemaining > 0) { + pRunningFramesIn = pSound->pProcessingCache; + frameCountIn = pSound->processingCacheFramesRemaining; - result = ma_data_source_read_pcm_frames(pSound->pDataSource, temp, framesToRead, &framesJustRead); + pRunningFramesOut = ma_offset_pcm_frames_ptr_f32(ppFramesOut[0], totalFramesRead, ma_node_get_output_channels(pNode, 0)); + frameCountOut = framesRemaining; - /* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */ - if (result == MA_AT_END) { - ma_sound_set_at_end(pSound, MA_TRUE); /* This will be set to false in ma_sound_start(). */ - } - - pRunningFramesOut = ma_offset_pcm_frames_ptr_f32(ppFramesOut[0], totalFramesRead, ma_engine_get_channels(ma_sound_get_engine(pSound))); - - frameCountIn = (ma_uint32)framesJustRead; - frameCountOut = framesRemaining; - - /* Convert if necessary. */ - if (dataSourceFormat == ma_format_f32) { - /* Fast path. No data conversion necessary. */ - pRunningFramesIn = (float*)temp; ma_engine_node_process_pcm_frames__general(&pSound->engineNode, &pRunningFramesIn, &frameCountIn, &pRunningFramesOut, &frameCountOut); + + MA_ASSERT(frameCountIn <= pSound->processingCacheFramesRemaining); + pSound->processingCacheFramesRemaining -= frameCountIn; + + /* Move any remaining data in the cache down. */ + if (pSound->processingCacheFramesRemaining > 0) { + MA_MOVE_MEMORY(pSound->pProcessingCache, ma_offset_pcm_frames_ptr_f32(pSound->pProcessingCache, frameCountIn, dataSourceChannels), pSound->processingCacheFramesRemaining * ma_get_bytes_per_frame(ma_format_f32, dataSourceChannels)); + } + + totalFramesRead += (ma_uint32)frameCountOut; /* Safe cast. */ + + if (result != MA_SUCCESS || ma_sound_at_end(pSound)) { + break; /* Might have reached the end. */ + } } else { - /* Slow path. Need to do sample format conversion to f32. If we give the f32 buffer the same count as the first temp buffer, we're guaranteed it'll be large enough. */ - float tempf32[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; /* Do not do `MA_DATA_CONVERTER_STACK_BUFFER_SIZE/sizeof(float)` here like we've done in other places. */ - ma_convert_pcm_frames_format(tempf32, ma_format_f32, temp, dataSourceFormat, framesJustRead, dataSourceChannels, ma_dither_mode_none); + /* Getting here means there's nothing in the cache. Read more data from the data source. */ + if (dataSourceFormat == ma_format_f32) { + /* Fast path. No conversion to f32 necessary. */ + result = ma_data_source_read_pcm_frames(pSound->pDataSource, pSound->pProcessingCache, pSound->processingCacheCap, &framesJustRead); + } else { + /* Slow path. Need to convert to f32. */ + ma_uint64 totalFramesConverted = 0; - /* Now that we have our samples in f32 format we can process like normal. */ - pRunningFramesIn = tempf32; - ma_engine_node_process_pcm_frames__general(&pSound->engineNode, &pRunningFramesIn, &frameCountIn, &pRunningFramesOut, &frameCountOut); - } + while (totalFramesConverted < pSound->processingCacheCap) { + ma_uint64 framesConverted; + ma_uint32 framesToConvertThisIteration = pSound->processingCacheCap - (ma_uint32)totalFramesConverted; + if (framesToConvertThisIteration > tempCapInFrames) { + framesToConvertThisIteration = tempCapInFrames; + } - /* We should have processed all of our input frames since we calculated the required number of input frames at the top. */ - MA_ASSERT(frameCountIn == framesJustRead); - totalFramesRead += (ma_uint32)frameCountOut; /* Safe cast. */ + result = ma_data_source_read_pcm_frames(pSound->pDataSource, temp, framesToConvertThisIteration, &framesConverted); + if (result != MA_SUCCESS) { + break; + } - if (result != MA_SUCCESS || ma_sound_at_end(pSound)) { - break; /* Might have reached the end. */ + ma_convert_pcm_frames_format(ma_offset_pcm_frames_ptr_f32(pSound->pProcessingCache, totalFramesConverted, dataSourceChannels), ma_format_f32, temp, dataSourceFormat, framesConverted, dataSourceChannels, ma_dither_mode_none); + totalFramesConverted += framesConverted; + } + + framesJustRead = totalFramesConverted; + } + + MA_ASSERT(framesJustRead <= pSound->processingCacheCap); + pSound->processingCacheFramesRemaining = (ma_uint32)framesJustRead; + + /* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */ + if (result == MA_AT_END) { + ma_sound_set_at_end(pSound, MA_TRUE); /* This will be set to false in ma_sound_start(). */ + } + + if (result != MA_SUCCESS || ma_sound_at_end(pSound)) { + break; + } } } } @@ -74456,25 +77004,6 @@ static void ma_engine_node_process_pcm_frames__group(ma_node* pNode, const float ma_engine_node_process_pcm_frames__general((ma_engine_node*)pNode, ppFramesIn, pFrameCountIn, ppFramesOut, pFrameCountOut); } -static ma_result ma_engine_node_get_required_input_frame_count__group(ma_node* pNode, ma_uint32 outputFrameCount, ma_uint32* pInputFrameCount) -{ - ma_uint64 inputFrameCount; - - MA_ASSERT(pInputFrameCount != NULL); - - /* Our pitch will affect this calculation. We need to update it. */ - ma_engine_node_update_pitch_if_required((ma_engine_node*)pNode); - - inputFrameCount = ma_engine_node_get_required_input_frame_count((ma_engine_node*)pNode, outputFrameCount); - if (inputFrameCount > 0xFFFFFFFF) { - inputFrameCount = 0xFFFFFFFF; /* Will never happen because miniaudio will only ever process in relatively small chunks. */ - } - - *pInputFrameCount = (ma_uint32)inputFrameCount; - - return MA_SUCCESS; -} - static ma_node_vtable g_ma_engine_node_vtable__sound = { @@ -74488,7 +77017,7 @@ static ma_node_vtable g_ma_engine_node_vtable__sound = static ma_node_vtable g_ma_engine_node_vtable__group = { ma_engine_node_process_pcm_frames__group, - ma_engine_node_get_required_input_frame_count__group, + NULL, /* onGetRequiredInputFrameCount */ 1, /* Groups have one input bus. */ 1, /* Groups have one output bus. */ MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES /* The engine node does resampling so should let miniaudio know about it. */ @@ -74534,9 +77063,10 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo ma_result result; size_t tempHeapSize; ma_node_config baseNodeConfig; - ma_linear_resampler_config resamplerConfig; + ma_resampler_config resamplerConfig; ma_spatializer_config spatializerConfig; ma_gainer_config gainerConfig; + ma_uint32 sampleRate; ma_uint32 channelsIn; ma_uint32 channelsOut; ma_channel defaultStereoChannelMap[2] = {MA_CHANNEL_SIDE_LEFT, MA_CHANNEL_SIDE_RIGHT}; /* <-- Consistent with the default channel map of a stereo listener. Means channel conversion can run on a fast path. */ @@ -74555,6 +77085,7 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo pHeapLayout->sizeInBytes = 0; + sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pConfig->pEngine); channelsIn = (pConfig->channelsIn != 0) ? pConfig->channelsIn : ma_engine_get_channels(pConfig->pEngine); channelsOut = (pConfig->channelsOut != 0) ? pConfig->channelsOut : ma_engine_get_channels(pConfig->pEngine); @@ -74574,10 +77105,13 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo /* Resmapler. */ - resamplerConfig = ma_linear_resampler_config_init(ma_format_f32, channelsIn, 1, 1); /* Input and output sample rates don't affect the calculation of the heap size. */ - resamplerConfig.lpfOrder = 0; + resamplerConfig = pConfig->resampling; + resamplerConfig.format = ma_format_f32; + resamplerConfig.channels = channelsIn; + resamplerConfig.sampleRateIn = sampleRate; + resamplerConfig.sampleRateOut = ma_engine_get_sample_rate(pConfig->pEngine); - result = ma_linear_resampler_get_heap_size(&resamplerConfig, &tempHeapSize); + result = ma_resampler_get_heap_size(&resamplerConfig, &tempHeapSize); if (result != MA_SUCCESS) { return result; /* Failed to retrieve the size of the heap for the resampler. */ } @@ -74645,7 +77179,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p ma_result result; ma_engine_node_heap_layout heapLayout; ma_node_config baseNodeConfig; - ma_linear_resampler_config resamplerConfig; + ma_resampler_config resamplerConfig; ma_fader_config faderConfig; ma_spatializer_config spatializerConfig; ma_panner_config pannerConfig; @@ -74720,10 +77254,13 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p */ /* We'll always do resampling first. */ - resamplerConfig = ma_linear_resampler_config_init(ma_format_f32, baseNodeConfig.pInputChannels[0], pEngineNode->sampleRate, ma_engine_get_sample_rate(pEngineNode->pEngine)); - resamplerConfig.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */ + resamplerConfig = pConfig->resampling; + resamplerConfig.format = ma_format_f32; + resamplerConfig.channels = baseNodeConfig.pInputChannels[0]; + resamplerConfig.sampleRateIn = pEngineNode->sampleRate; + resamplerConfig.sampleRateOut = ma_engine_get_sample_rate(pEngineNode->pEngine); - result = ma_linear_resampler_init_preallocated(&resamplerConfig, ma_offset_ptr(pHeap, heapLayout.resamplerOffset), &pEngineNode->resampler); + result = ma_resampler_init_preallocated(&resamplerConfig, ma_offset_ptr(pHeap, heapLayout.resamplerOffset), &pEngineNode->resampler); if (result != MA_SUCCESS) { goto error1; } @@ -74739,7 +77276,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p /* - Spatialization comes next. We spatialize based ont he node's output channel count. It's up the caller to + Spatialization comes next. We spatialize based on the node's output channel count. It's up the caller to ensure channels counts link up correctly in the node graph. */ spatializerConfig = ma_engine_node_spatializer_config_init(&baseNodeConfig); @@ -74782,7 +77319,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p /* No need for allocation callbacks here because we use a preallocated heap. */ error3: ma_spatializer_uninit(&pEngineNode->spatializer, NULL); -error2: ma_linear_resampler_uninit(&pEngineNode->resampler, NULL); +error2: ma_resampler_uninit(&pEngineNode->resampler, NULL); error1: ma_node_uninit(&pEngineNode->baseNode, NULL); error0: return result; } @@ -74831,7 +77368,7 @@ MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocati } ma_spatializer_uninit(&pEngineNode->spatializer, pAllocationCallbacks); - ma_linear_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks); + ma_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks); /* Free the heap last. */ if (pEngineNode->_ownsHeap) { @@ -74853,8 +77390,12 @@ MA_API ma_sound_config ma_sound_config_init_2(ma_engine* pEngine) if (pEngine != NULL) { config.monoExpansionMode = pEngine->monoExpansionMode; + config.pitchResampling = pEngine->pitchResamplingConfig; } else { config.monoExpansionMode = ma_mono_expansion_mode_default; + + config.pitchResampling = ma_resampler_config_init(ma_format_f32, 0, 0, 0, ma_resample_algorithm_linear); + config.pitchResampling.linear.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */ } config.rangeEndInPCMFrames = ~((ma_uint64)0); @@ -74876,8 +77417,12 @@ MA_API ma_sound_group_config ma_sound_group_config_init_2(ma_engine* pEngine) if (pEngine != NULL) { config.monoExpansionMode = pEngine->monoExpansionMode; + config.pitchResampling = pEngine->pitchResamplingConfig; } else { config.monoExpansionMode = ma_mono_expansion_mode_default; + + config.pitchResampling = ma_resampler_config_init(ma_format_f32, 0, 0, 0, ma_resample_algorithm_linear); + config.pitchResampling.linear.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */ } return config; @@ -74889,8 +77434,12 @@ MA_API ma_engine_config ma_engine_config_init(void) ma_engine_config config; MA_ZERO_OBJECT(&config); - config.listenerCount = 1; /* Always want at least one listener. */ - config.monoExpansionMode = ma_mono_expansion_mode_default; + config.listenerCount = 1; /* Always want at least one listener. */ + config.monoExpansionMode = ma_mono_expansion_mode_default; + config.resourceManagerResampling = ma_resampler_config_init(ma_format_unknown, 0, 0, 0, ma_resample_algorithm_linear); + + config.pitchResampling = ma_resampler_config_init(ma_format_f32, 0, 0, 0, ma_resample_algorithm_linear); + config.pitchResampling.linear.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */ return config; } @@ -74929,6 +77478,21 @@ static void ma_engine_data_callback_internal(ma_device* pDevice, void* pFramesOu ma_engine_read_pcm_frames(pEngine, pFramesOut, frameCount, NULL); } + +static ma_uint32 ma_device__get_processing_size_in_frames(ma_device* pDevice) +{ + /* + The processing size is the period size. The device can have a fixed sized processing size, or + it can be decided by the backend in which case it can be variable. + */ + if (pDevice->playback.intermediaryBufferCap > 0) { + /* Using a fixed sized processing callback. */ + return pDevice->playback.intermediaryBufferCap; + } else { + /* Not using a fixed sized processing callback. Need to estimate the processing size based on the backend. */ + return pDevice->playback.internalPeriodSizeInFrames; + } +} #endif MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEngine) @@ -74956,6 +77520,7 @@ MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEng pEngine->defaultVolumeSmoothTimeInPCMFrames = engineConfig.defaultVolumeSmoothTimeInPCMFrames; pEngine->onProcess = engineConfig.onProcess; pEngine->pProcessUserData = engineConfig.pProcessUserData; + pEngine->pitchResamplingConfig = engineConfig.pitchResampling; ma_allocation_callbacks_init_copy(&pEngine->allocationCallbacks, &engineConfig.allocationCallbacks); #if !defined(MA_NO_RESOURCE_MANAGER) @@ -75022,6 +77587,14 @@ MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEng if (pEngine->pDevice != NULL) { engineConfig.channels = pEngine->pDevice->playback.channels; engineConfig.sampleRate = pEngine->pDevice->sampleRate; + + /* + The processing size used by the engine is determined by engineConfig.periodSizeInFrames. We want + to make this equal to what the device is using for it's period size. If we don't do that, it's + possible that the node graph will split it's processing into multiple passes which can introduce + glitching. + */ + engineConfig.periodSizeInFrames = ma_device__get_processing_size_in_frames(pEngine->pDevice); } } #endif @@ -75048,9 +77621,10 @@ MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEng } - /* The engine is a node graph. This needs to be initialized after we have the device so we can can determine the channel count. */ + /* The engine is a node graph. This needs to be initialized after we have the device so we can determine the channel count. */ nodeGraphConfig = ma_node_graph_config_init(engineConfig.channels); - nodeGraphConfig.nodeCacheCapInFrames = (engineConfig.periodSizeInFrames > 0xFFFF) ? 0xFFFF : (ma_uint16)engineConfig.periodSizeInFrames; + nodeGraphConfig.processingSizeInFrames = engineConfig.periodSizeInFrames; + nodeGraphConfig.preMixStackSizeInBytes = engineConfig.preMixStackSizeInBytes; result = ma_node_graph_init(&nodeGraphConfig, &pEngine->allocationCallbacks, &pEngine->nodeGraph); if (result != MA_SUCCESS) { @@ -75129,9 +77703,10 @@ MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEng resourceManagerConfig.decodedSampleRate = ma_engine_get_sample_rate(pEngine); ma_allocation_callbacks_init_copy(&resourceManagerConfig.allocationCallbacks, &pEngine->allocationCallbacks); resourceManagerConfig.pVFS = engineConfig.pResourceManagerVFS; + resourceManagerConfig.resampling = engineConfig.resourceManagerResampling; - /* The Emscripten build cannot use threads. */ - #if defined(MA_EMSCRIPTEN) + /* The Emscripten build cannot use threads unless it's targeting pthreads. */ + #if defined(MA_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) { resourceManagerConfig.jobThreadCount = 0; resourceManagerConfig.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING; @@ -75646,7 +78221,7 @@ MA_API ma_result ma_engine_play_sound_ex(ma_engine* pEngine, const char* pFilePa return MA_INVALID_ARGS; } - /* Attach to the endpoint node if nothing is specicied. */ + /* Attach to the endpoint node if nothing is specified. */ if (pNode == NULL) { pNode = ma_node_graph_get_endpoint(&pEngine->nodeGraph); nodeInputBusIndex = 0; @@ -75854,16 +78429,35 @@ static ma_result ma_sound_init_from_data_source_internal(ma_engine* pEngine, con } + /* + When pulling data from a data source we need a processing cache to hold onto unprocessed input data from the data source + after doing resampling. + */ + if (pSound->pDataSource != NULL) { + pSound->processingCacheFramesRemaining = 0; + pSound->processingCacheCap = ma_node_graph_get_processing_size_in_frames(&pEngine->nodeGraph); + if (pSound->processingCacheCap == 0) { + pSound->processingCacheCap = 512; + } + + pSound->pProcessingCache = (float*)ma_calloc(pSound->processingCacheCap * ma_get_bytes_per_frame(ma_format_f32, engineNodeConfig.channelsIn), &pEngine->allocationCallbacks); + if (pSound->pProcessingCache == NULL) { + ma_engine_node_uninit(&pSound->engineNode, &pEngine->allocationCallbacks); + return MA_OUT_OF_MEMORY; + } + } + + /* Apply initial range and looping state to the data source if applicable. */ if (pConfig->rangeBegInPCMFrames != 0 || pConfig->rangeEndInPCMFrames != ~((ma_uint64)0)) { ma_data_source_set_range_in_pcm_frames(ma_sound_get_data_source(pSound), pConfig->rangeBegInPCMFrames, pConfig->rangeEndInPCMFrames); } if (pConfig->loopPointBegInPCMFrames != 0 || pConfig->loopPointEndInPCMFrames != ~((ma_uint64)0)) { - ma_data_source_set_range_in_pcm_frames(ma_sound_get_data_source(pSound), pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames); + ma_data_source_set_loop_point_in_pcm_frames(ma_sound_get_data_source(pSound), pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames); } - ma_sound_set_looping(pSound, pConfig->isLooping); + ma_sound_set_looping(pSound, pConfig->isLooping || ((pConfig->flags & MA_SOUND_FLAG_LOOPING) != 0)); return MA_SUCCESS; } @@ -75887,6 +78481,9 @@ MA_API ma_result ma_sound_init_from_file_internal(ma_engine* pEngine, const ma_s it and can avoid accessing the sound from within the notification. */ flags = pConfig->flags | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT; + if (pConfig->isLooping) { + flags |= MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING; + } pSound->pResourceManagerDataSource = (ma_resource_manager_data_source*)ma_malloc(sizeof(*pSound->pResourceManagerDataSource), &pEngine->allocationCallbacks); if (pSound->pResourceManagerDataSource == NULL) { @@ -75915,10 +78512,11 @@ MA_API ma_result ma_sound_init_from_file_internal(ma_engine* pEngine, const ma_s resourceManagerDataSourceConfig.rangeEndInPCMFrames = pConfig->rangeEndInPCMFrames; resourceManagerDataSourceConfig.loopPointBegInPCMFrames = pConfig->loopPointBegInPCMFrames; resourceManagerDataSourceConfig.loopPointEndInPCMFrames = pConfig->loopPointEndInPCMFrames; - resourceManagerDataSourceConfig.isLooping = pConfig->isLooping; + resourceManagerDataSourceConfig.isLooping = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_LOOPING) != 0; result = ma_resource_manager_data_source_init_ex(pEngine->pResourceManager, &resourceManagerDataSourceConfig, pSound->pResourceManagerDataSource); if (result != MA_SUCCESS) { + ma_free(pSound->pResourceManagerDataSource, &pEngine->allocationCallbacks); goto done; } @@ -76067,7 +78665,7 @@ MA_API ma_result ma_sound_init_ex(ma_engine* pEngine, const ma_sound_config* pCo { /* Getting here means we're not loading from a file. We may be loading from an already-initialized - data source, or none at all. If we aren't specifying any data source, we'll be initializing the + data source, or none at all. If we aren't specifying any data source, we'll be initializing the equivalent to a group. ma_data_source_init_from_data_source_internal() will deal with this for us, so no special treatment required here. */ @@ -76087,6 +78685,11 @@ MA_API void ma_sound_uninit(ma_sound* pSound) */ ma_engine_node_uninit(&pSound->engineNode, &pSound->engineNode.pEngine->allocationCallbacks); + if (pSound->pProcessingCache != NULL) { + ma_free(pSound->pProcessingCache, &pSound->engineNode.pEngine->allocationCallbacks); + pSound->pProcessingCache = NULL; + } + /* Once the sound is detached from the group we can guarantee that it won't be referenced by the mixer thread which means it's safe for us to destroy the data source. */ #ifndef MA_NO_RESOURCE_MANAGER if (pSound->ownsDataSource) { @@ -76182,6 +78785,27 @@ MA_API ma_result ma_sound_stop_with_fade_in_milliseconds(ma_sound* pSound, ma_ui return ma_sound_stop_with_fade_in_pcm_frames(pSound, (fadeLengthInMilliseconds * sampleRate) / 1000); } +MA_API void ma_sound_reset_start_time(ma_sound* pSound) +{ + ma_sound_set_start_time_in_pcm_frames(pSound, 0); +} + +MA_API void ma_sound_reset_stop_time(ma_sound* pSound) +{ + ma_sound_set_stop_time_in_pcm_frames(pSound, ~(ma_uint64)0); +} + +MA_API void ma_sound_reset_fade(ma_sound* pSound) +{ + ma_sound_set_fade_in_pcm_frames(pSound, 0, 1, 0); +} + +MA_API void ma_sound_reset_stop_time_and_fade(ma_sound* pSound) +{ + ma_sound_reset_stop_time(pSound); + ma_sound_reset_fade(pSound); +} + MA_API void ma_sound_set_volume(ma_sound* pSound, float volume) { if (pSound == NULL) { @@ -76724,7 +79348,12 @@ MA_API ma_uint64 ma_sound_get_time_in_pcm_frames(const ma_sound* pSound) MA_API ma_uint64 ma_sound_get_time_in_milliseconds(const ma_sound* pSound) { - return ma_sound_get_time_in_pcm_frames(pSound) * 1000 / ma_engine_get_sample_rate(ma_sound_get_engine(pSound)); + ma_uint32 sampleRate = ma_engine_get_sample_rate(ma_sound_get_engine(pSound)); + if (sampleRate == 0) { + return 0; /* Prevent a division by zero. */ + } + + return ma_sound_get_time_in_pcm_frames(pSound) * 1000 / sampleRate; } MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping) @@ -76787,7 +79416,28 @@ MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameInd return MA_SUCCESS; } -MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap) +MA_API ma_result ma_sound_seek_to_second(ma_sound* pSound, float seekPointInSeconds) +{ + ma_uint64 frameIndex; + ma_uint32 sampleRate; + ma_result result; + + if (pSound == NULL) { + return MA_INVALID_ARGS; + } + + result = ma_sound_get_data_format(pSound, NULL, NULL, &sampleRate, NULL, 0); + if (result != MA_SUCCESS) { + return result; + } + + /* We need PCM frames. We need to convert first */ + frameIndex = (ma_uint64)(seekPointInSeconds * sampleRate); + + return ma_sound_seek_to_pcm_frame(pSound, frameIndex); +} + +MA_API ma_result ma_sound_get_data_format(const ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap) { if (pSound == NULL) { return MA_INVALID_ARGS; @@ -76807,7 +79457,7 @@ MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, } if (pSampleRate != NULL) { - *pSampleRate = pSound->engineNode.resampler.config.sampleRateIn; + *pSampleRate = pSound->engineNode.resampler.sampleRateIn; } if (pChannelMap != NULL) { @@ -76820,7 +79470,7 @@ MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, } } -MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor) +MA_API ma_result ma_sound_get_cursor_in_pcm_frames(const ma_sound* pSound, ma_uint64* pCursor) { ma_uint64 seekTarget; @@ -76842,7 +79492,7 @@ MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* } } -MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength) +MA_API ma_result ma_sound_get_length_in_pcm_frames(const ma_sound* pSound, ma_uint64* pLength) { if (pSound == NULL) { return MA_INVALID_ARGS; @@ -76856,7 +79506,7 @@ MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* return ma_data_source_get_length_in_pcm_frames(pSound->pDataSource, pLength); } -MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor) +MA_API ma_result ma_sound_get_cursor_in_seconds(const ma_sound* pSound, float* pCursor) { ma_result result; ma_uint64 cursorInPCMFrames; @@ -76882,7 +79532,7 @@ MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor return MA_SUCCESS; } -MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength) +MA_API ma_result ma_sound_get_length_in_seconds(const ma_sound* pSound, float* pLength) { if (pSound == NULL) { return MA_INVALID_ARGS; @@ -77233,7 +79883,7 @@ code below please report the bug to the respective repository for the relevant p *************************************************************************************************************************************************************** **************************************************************************************************************************************************************/ #if !defined(MA_NO_WAV) && (!defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING)) -#if !defined(MA_DR_WAV_IMPLEMENTATION) && !defined(MA_DR_WAV_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */ +#if !defined(MA_DR_WAV_IMPLEMENTATION) /* dr_wav_c begin */ #ifndef ma_dr_wav_c #define ma_dr_wav_c @@ -77701,12 +80351,12 @@ MA_PRIVATE ma_bool32 ma_dr_wav__seek_forward(ma_dr_wav_seek_proc onSeek, ma_uint ma_uint64 bytesRemainingToSeek = offset; while (bytesRemainingToSeek > 0) { if (bytesRemainingToSeek > 0x7FFFFFFF) { - if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_current)) { + if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_CUR)) { return MA_FALSE; } bytesRemainingToSeek -= 0x7FFFFFFF; } else { - if (!onSeek(pUserData, (int)bytesRemainingToSeek, ma_dr_wav_seek_origin_current)) { + if (!onSeek(pUserData, (int)bytesRemainingToSeek, MA_DR_WAV_SEEK_CUR)) { return MA_FALSE; } bytesRemainingToSeek = 0; @@ -77717,17 +80367,17 @@ MA_PRIVATE ma_bool32 ma_dr_wav__seek_forward(ma_dr_wav_seek_proc onSeek, ma_uint MA_PRIVATE ma_bool32 ma_dr_wav__seek_from_start(ma_dr_wav_seek_proc onSeek, ma_uint64 offset, void* pUserData) { if (offset <= 0x7FFFFFFF) { - return onSeek(pUserData, (int)offset, ma_dr_wav_seek_origin_start); + return onSeek(pUserData, (int)offset, MA_DR_WAV_SEEK_SET); } - if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_start)) { + if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_SET)) { return MA_FALSE; } offset -= 0x7FFFFFFF; for (;;) { if (offset <= 0x7FFFFFFF) { - return onSeek(pUserData, (int)offset, ma_dr_wav_seek_origin_current); + return onSeek(pUserData, (int)offset, MA_DR_WAV_SEEK_CUR); } - if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_current)) { + if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_CUR)) { return MA_FALSE; } offset -= 0x7FFFFFFF; @@ -77750,7 +80400,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav__on_seek(ma_dr_wav_seek_proc onSeek, void* pUserD if (!onSeek(pUserData, offset, origin)) { return MA_FALSE; } - if (origin == ma_dr_wav_seek_origin_start) { + if (origin == MA_DR_WAV_SEEK_SET) { *pCursor = offset; } else { *pCursor += offset; @@ -77869,12 +80519,12 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa ma_uint8 smplLoopData[MA_DR_WAV_SMPL_LOOP_BYTES]; bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead); if (bytesJustRead == sizeof(smplLoopData)) { - pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = ma_dr_wav_bytes_to_u32(smplLoopData + 0); - pMetadata->data.smpl.pLoops[iSampleLoop].type = ma_dr_wav_bytes_to_u32(smplLoopData + 4); - pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 8); - pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 12); - pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = ma_dr_wav_bytes_to_u32(smplLoopData + 16); - pMetadata->data.smpl.pLoops[iSampleLoop].playCount = ma_dr_wav_bytes_to_u32(smplLoopData + 20); + pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = ma_dr_wav_bytes_to_u32(smplLoopData + 0); + pMetadata->data.smpl.pLoops[iSampleLoop].type = ma_dr_wav_bytes_to_u32(smplLoopData + 4); + pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 8); + pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 12); + pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = ma_dr_wav_bytes_to_u32(smplLoopData + 16); + pMetadata->data.smpl.pLoops[iSampleLoop].playCount = ma_dr_wav_bytes_to_u32(smplLoopData + 20); } else { break; } @@ -77918,7 +80568,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_cue_to_metadata_obj(ma_dr_wav__metadata_par pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11]; pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = ma_dr_wav_bytes_to_u32(cuePointData + 12); pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = ma_dr_wav_bytes_to_u32(cuePointData + 16); - pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = ma_dr_wav_bytes_to_u32(cuePointData + 20); + pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset = ma_dr_wav_bytes_to_u32(cuePointData + 20); } else { break; } @@ -78258,7 +80908,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse if (pParser->stage == ma_dr_wav__metadata_parser_stage_count) { ma_uint8 buffer[4]; size_t bytesJustRead; - if (!pParser->onSeek(pParser->pReadSeekUserData, 28, ma_dr_wav_seek_origin_current)) { + if (!pParser->onSeek(pParser->pReadSeekUserData, 28, MA_DR_WAV_SEEK_CUR)) { return bytesRead; } bytesRead += 28; @@ -78353,7 +81003,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse return bytesRead; } allocSizeNeeded += ma_dr_wav__strlen(buffer) + 1; - allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - MA_DR_WAV_BEXT_BYTES; + allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - MA_DR_WAV_BEXT_BYTES + 1; ma_dr_wav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1); pParser->metadataCount += 1; } else { @@ -78436,6 +81086,16 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_album); } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_tracknumber, "ITRK")) { subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_tracknumber); + } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_location, "IARL")) { + subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_location); + } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_organization, "ICMS")) { + subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_organization); + } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_keywords, "IKEY")) { + subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_keywords); + } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_medium, "IMED")) { + subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_medium); + } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_description, "ISBJ")) { + subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_description); } else if ((allowedMetadataTypes & ma_dr_wav_metadata_type_unknown) != 0) { subchunkBytesRead = ma_dr_wav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType); } @@ -78443,13 +81103,13 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse MA_DR_WAV_ASSERT(subchunkBytesRead <= subchunkDataSize); if (subchunkBytesRead < subchunkDataSize) { ma_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead; - if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, ma_dr_wav_seek_origin_current)) { + if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, MA_DR_WAV_SEEK_CUR)) { break; } bytesRead += bytesToSeek; } if ((subchunkDataSize % 2) == 1) { - if (!pParser->onSeek(pParser->pReadSeekUserData, 1, ma_dr_wav_seek_origin_current)) { + if (!pParser->onSeek(pParser->pReadSeekUserData, 1, MA_DR_WAV_SEEK_CUR)) { break; } bytesRead += 1; @@ -78486,7 +81146,7 @@ MA_API ma_uint16 ma_dr_wav_fmt_get_format(const ma_dr_wav_fmt* pFMT) return ma_dr_wav_bytes_to_u16(pFMT->subFormat); } } -MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pReadSeekUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pReadSeekTellUserData, const ma_allocation_callbacks* pAllocationCallbacks) { if (pWav == NULL || onRead == NULL || onSeek == NULL) { return MA_FALSE; @@ -78494,7 +81154,8 @@ MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRe MA_DR_WAV_ZERO_MEMORY(pWav, sizeof(*pWav)); pWav->onRead = onRead; pWav->onSeek = onSeek; - pWav->pUserData = pReadSeekUserData; + pWav->onTell = onTell; + pWav->pUserData = pReadSeekTellUserData; pWav->allocationCallbacks = ma_dr_wav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks); if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) { return MA_FALSE; @@ -78555,7 +81216,6 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p } if (pWav->container == ma_dr_wav_container_riff || pWav->container == ma_dr_wav_container_rifx) { if (ma_dr_wav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) { - return MA_FALSE; } } else if (pWav->container == ma_dr_wav_container_rf64) { if (ma_dr_wav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) { @@ -78709,14 +81369,14 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p fmt.channelMask = ma_dr_wav_bytes_to_u32_ex(fmtext + 2, pWav->container); ma_dr_wav_bytes_to_guid(fmtext + 6, fmt.subFormat); } else { - if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, ma_dr_wav_seek_origin_current) == MA_FALSE) { + if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, MA_DR_WAV_SEEK_CUR) == MA_FALSE) { return MA_FALSE; } } cursor += fmt.extendedSize; bytesReadSoFar += fmt.extendedSize; } - if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), ma_dr_wav_seek_origin_current) == MA_FALSE) { + if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), MA_DR_WAV_SEEK_CUR) == MA_FALSE) { return MA_FALSE; } cursor += (header.sizeInBytes - bytesReadSoFar); @@ -78824,7 +81484,9 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p compressionFormat = MA_DR_WAVE_FORMAT_MULAW; } else if (ma_dr_wav_fourcc_equal(type, "ima4")) { compressionFormat = MA_DR_WAVE_FORMAT_DVI_ADPCM; - sampleSizeInBits = 4; + sampleSizeInBits = 4; + (void)compressionFormat; + (void)sampleSizeInBits; return MA_FALSE; } else { return MA_FALSE; @@ -78865,15 +81527,26 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p return MA_FALSE; } offset = ma_dr_wav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container); - if (ma_dr_wav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == MA_FALSE) { - return MA_FALSE; - } - cursor += offset; - pWav->dataChunkDataPos = cursor; + pWav->dataChunkDataPos = cursor + offset; dataChunkSize = chunkSize; - if (sequential || !isProcessingMetadata) { - break; + if (dataChunkSize > offset) { + dataChunkSize -= offset; } else { + dataChunkSize = 0; + } + if (sequential) { + if (foundChunk_fmt) { + if (ma_dr_wav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == MA_FALSE) { + return MA_FALSE; + } + cursor += offset; + break; + } else { + return MA_FALSE; + } + } else { + chunkSize += header.paddingSize; + chunkSize -= sizeof(offsetAndBlockSizeData); if (ma_dr_wav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == MA_FALSE) { break; } @@ -78882,9 +81555,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p } } if (isProcessingMetadata) { - ma_uint64 metadataBytesRead; - metadataBytesRead = ma_dr_wav__metadata_process_chunk(&metadataParser, &header, ma_dr_wav_metadata_type_all_including_unknown); - MA_DR_WAV_ASSERT(metadataBytesRead <= header.sizeInBytes); + ma_dr_wav__metadata_process_chunk(&metadataParser, &header, ma_dr_wav_metadata_type_all_including_unknown); if (ma_dr_wav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == MA_FALSE) { break; } @@ -78939,6 +81610,17 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p pWav->pMetadata = metadataParser.pMetadata; pWav->metadataCount = metadataParser.metadataCount; } + if (pWav->onTell != NULL && pWav->onSeek != NULL) { + if (pWav->onSeek(pWav->pUserData, 0, MA_DR_WAV_SEEK_END) == MA_TRUE) { + ma_int64 fileSize; + if (pWav->onTell(pWav->pUserData, &fileSize)) { + if (dataChunkSize + pWav->dataChunkDataPos > (ma_uint64)fileSize) { + dataChunkSize = (ma_uint64)fileSize - pWav->dataChunkDataPos; + } + } + } else { + } + } if (dataChunkSize == 0xFFFFFFFF && (pWav->container == ma_dr_wav_container_riff || pWav->container == ma_dr_wav_container_rifx) && pWav->isSequentialWrite == MA_FALSE) { dataChunkSize = 0; for (;;) { @@ -78958,8 +81640,14 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p pWav->sampleRate = fmt.sampleRate; pWav->channels = fmt.channels; pWav->bitsPerSample = fmt.bitsPerSample; - pWav->bytesRemaining = dataChunkSize; pWav->translatedFormatTag = translatedFormatTag; + if (!ma_dr_wav__is_compressed_format_tag(translatedFormatTag)) { + ma_uint32 bytesPerFrame = ma_dr_wav_get_bytes_per_pcm_frame(pWav); + if (bytesPerFrame > 0) { + dataChunkSize -= (dataChunkSize % bytesPerFrame); + } + } + pWav->bytesRemaining = dataChunkSize; pWav->dataChunkDataSize = dataChunkSize; if (sampleCountFromFactChunk != 0) { pWav->totalPCMFrameCount = sampleCountFromFactChunk; @@ -79014,20 +81702,20 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p #endif return MA_TRUE; } -MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_dr_wav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks); + return ma_dr_wav_init_ex(pWav, onRead, onSeek, onTell, NULL, pUserData, NULL, 0, pAllocationCallbacks); } -MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, ma_dr_wav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks) { - if (!ma_dr_wav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) { + if (!ma_dr_wav_preinit(pWav, onRead, onSeek, onTell, pReadSeekTellUserData, pAllocationCallbacks)) { return MA_FALSE; } return ma_dr_wav_init__internal(pWav, onChunk, pChunkUserData, flags); } -MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks) { - if (!ma_dr_wav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_wav_preinit(pWav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) { return MA_FALSE; } return ma_dr_wav_init__internal(pWav, NULL, NULL, flags | MA_DR_WAV_WITH_METADATA); @@ -79189,8 +81877,8 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_ for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) { bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId); bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type); - bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset); - bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset); + bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleOffset); + bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleOffset); bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction); bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount); } @@ -79224,7 +81912,7 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_ bytesWritten += ma_dr_wav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4); bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart); bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart); - bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset); + bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset); } } break; case ma_dr_wav_metadata_type_acid: @@ -79310,15 +81998,20 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_ if (pMetadata->type & ma_dr_wav_metadata_type_list_all_info_strings) { const char* pID = NULL; switch (pMetadata->type) { - case ma_dr_wav_metadata_type_list_info_software: pID = "ISFT"; break; - case ma_dr_wav_metadata_type_list_info_copyright: pID = "ICOP"; break; - case ma_dr_wav_metadata_type_list_info_title: pID = "INAM"; break; - case ma_dr_wav_metadata_type_list_info_artist: pID = "IART"; break; - case ma_dr_wav_metadata_type_list_info_comment: pID = "ICMT"; break; - case ma_dr_wav_metadata_type_list_info_date: pID = "ICRD"; break; - case ma_dr_wav_metadata_type_list_info_genre: pID = "IGNR"; break; - case ma_dr_wav_metadata_type_list_info_album: pID = "IPRD"; break; - case ma_dr_wav_metadata_type_list_info_tracknumber: pID = "ITRK"; break; + case ma_dr_wav_metadata_type_list_info_software: pID = "ISFT"; break; + case ma_dr_wav_metadata_type_list_info_copyright: pID = "ICOP"; break; + case ma_dr_wav_metadata_type_list_info_title: pID = "INAM"; break; + case ma_dr_wav_metadata_type_list_info_artist: pID = "IART"; break; + case ma_dr_wav_metadata_type_list_info_comment: pID = "ICMT"; break; + case ma_dr_wav_metadata_type_list_info_date: pID = "ICRD"; break; + case ma_dr_wav_metadata_type_list_info_genre: pID = "IGNR"; break; + case ma_dr_wav_metadata_type_list_info_album: pID = "IPRD"; break; + case ma_dr_wav_metadata_type_list_info_tracknumber: pID = "ITRK"; break; + case ma_dr_wav_metadata_type_list_info_location: pID = "IARL"; break; + case ma_dr_wav_metadata_type_list_info_organization: pID = "ICMS"; break; + case ma_dr_wav_metadata_type_list_info_keywords: pID = "IKEY"; break; + case ma_dr_wav_metadata_type_list_info_medium: pID = "IMED"; break; + case ma_dr_wav_metadata_type_list_info_description: pID = "ISBJ"; break; default: break; } MA_DR_WAV_ASSERT(pID != NULL); @@ -79533,7 +82226,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init_write__internal(ma_dr_wav* pWav, const ma_dr } pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize; if (pFormat->container == ma_dr_wav_container_riff) { - ma_uint32 chunkSizeRIFF = 28 + (ma_uint32)initialDataChunkSize; + ma_uint32 chunkSizeRIFF = 36 + (ma_uint32)initialDataChunkSize; runningPos += ma_dr_wav__write(pWav, "RIFF", 4); runningPos += ma_dr_wav__write_u32ne_to_le(pWav, chunkSizeRIFF); runningPos += ma_dr_wav__write(pWav, "WAVE", 4); @@ -79656,7 +82349,31 @@ MA_PRIVATE size_t ma_dr_wav__on_write_stdio(void* pUserData, const void* pData, } MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_stdio(void* pUserData, int offset, ma_dr_wav_seek_origin origin) { - return fseek((FILE*)pUserData, offset, (origin == ma_dr_wav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; + int whence = SEEK_SET; + if (origin == MA_DR_WAV_SEEK_CUR) { + whence = SEEK_CUR; + } else if (origin == MA_DR_WAV_SEEK_END) { + whence = SEEK_END; + } + return fseek((FILE*)pUserData, offset, whence) == 0; +} +MA_PRIVATE ma_bool32 ma_dr_wav__on_tell_stdio(void* pUserData, ma_int64* pCursor) +{ + FILE* pFileStdio = (FILE*)pUserData; + ma_int64 result; + MA_DR_WAV_ASSERT(pFileStdio != NULL); + MA_DR_WAV_ASSERT(pCursor != NULL); +#if defined(_WIN32) && !defined(NXDK) + #if defined(_MSC_VER) && _MSC_VER > 1200 + result = _ftelli64(pFileStdio); + #else + result = ftell(pFileStdio); + #endif +#else + result = ftell(pFileStdio); +#endif + *pCursor = result; + return MA_TRUE; } MA_API ma_bool32 ma_dr_wav_init_file(ma_dr_wav* pWav, const char* filename, const ma_allocation_callbacks* pAllocationCallbacks) { @@ -79665,7 +82382,7 @@ MA_API ma_bool32 ma_dr_wav_init_file(ma_dr_wav* pWav, const char* filename, cons MA_PRIVATE ma_bool32 ma_dr_wav_init_file__internal_FILE(ma_dr_wav* pWav, FILE* pFile, ma_dr_wav_chunk_proc onChunk, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks) { ma_bool32 result; - result = ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_stdio, ma_dr_wav__on_seek_stdio, (void*)pFile, pAllocationCallbacks); + result = ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_stdio, ma_dr_wav__on_seek_stdio, ma_dr_wav__on_tell_stdio, (void*)pFile, pAllocationCallbacks); if (result != MA_TRUE) { fclose(pFile); return result; @@ -79802,25 +82519,26 @@ MA_PRIVATE size_t ma_dr_wav__on_read_memory(void* pUserData, void* pBufferOut, s MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_memory(void* pUserData, int offset, ma_dr_wav_seek_origin origin) { ma_dr_wav* pWav = (ma_dr_wav*)pUserData; + ma_int64 newCursor; MA_DR_WAV_ASSERT(pWav != NULL); - if (origin == ma_dr_wav_seek_origin_current) { - if (offset > 0) { - if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) { - return MA_FALSE; - } - } else { - if (pWav->memoryStream.currentReadPos < (size_t)-offset) { - return MA_FALSE; - } - } - pWav->memoryStream.currentReadPos += offset; + if (origin == MA_DR_WAV_SEEK_SET) { + newCursor = 0; + } else if (origin == MA_DR_WAV_SEEK_CUR) { + newCursor = (ma_int64)pWav->memoryStream.currentReadPos; + } else if (origin == MA_DR_WAV_SEEK_END) { + newCursor = (ma_int64)pWav->memoryStream.dataSize; } else { - if ((ma_uint32)offset <= pWav->memoryStream.dataSize) { - pWav->memoryStream.currentReadPos = offset; - } else { - return MA_FALSE; - } + MA_DR_WAV_ASSERT(!"Invalid seek origin"); + return MA_FALSE; } + newCursor += offset; + if (newCursor < 0) { + return MA_FALSE; + } + if ((size_t)newCursor > pWav->memoryStream.dataSize) { + return MA_FALSE; + } + pWav->memoryStream.currentReadPos = (size_t)newCursor; return MA_TRUE; } MA_PRIVATE size_t ma_dr_wav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite) @@ -79854,25 +82572,34 @@ MA_PRIVATE size_t ma_dr_wav__on_write_memory(void* pUserData, const void* pDataI MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_memory_write(void* pUserData, int offset, ma_dr_wav_seek_origin origin) { ma_dr_wav* pWav = (ma_dr_wav*)pUserData; + ma_int64 newCursor; MA_DR_WAV_ASSERT(pWav != NULL); - if (origin == ma_dr_wav_seek_origin_current) { - if (offset > 0) { - if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) { - offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos); - } - } else { - if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) { - offset = -(int)pWav->memoryStreamWrite.currentWritePos; - } - } - pWav->memoryStreamWrite.currentWritePos += offset; + if (origin == MA_DR_WAV_SEEK_SET) { + newCursor = 0; + } else if (origin == MA_DR_WAV_SEEK_CUR) { + newCursor = (ma_int64)pWav->memoryStreamWrite.currentWritePos; + } else if (origin == MA_DR_WAV_SEEK_END) { + newCursor = (ma_int64)pWav->memoryStreamWrite.dataSize; } else { - if ((ma_uint32)offset <= pWav->memoryStreamWrite.dataSize) { - pWav->memoryStreamWrite.currentWritePos = offset; - } else { - pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize; - } + MA_DR_WAV_ASSERT(!"Invalid seek origin"); + return MA_FALSE; } + newCursor += offset; + if (newCursor < 0) { + return MA_FALSE; + } + if ((size_t)newCursor > pWav->memoryStreamWrite.dataSize) { + return MA_FALSE; + } + pWav->memoryStreamWrite.currentWritePos = (size_t)newCursor; + return MA_TRUE; +} +MA_PRIVATE ma_bool32 ma_dr_wav__on_tell_memory(void* pUserData, ma_int64* pCursor) +{ + ma_dr_wav* pWav = (ma_dr_wav*)pUserData; + MA_DR_WAV_ASSERT(pWav != NULL); + MA_DR_WAV_ASSERT(pCursor != NULL); + *pCursor = (ma_int64)pWav->memoryStream.currentReadPos; return MA_TRUE; } MA_API ma_bool32 ma_dr_wav_init_memory(ma_dr_wav* pWav, const void* data, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks) @@ -79884,7 +82611,7 @@ MA_API ma_bool32 ma_dr_wav_init_memory_ex(ma_dr_wav* pWav, const void* data, siz if (data == NULL || dataSize == 0) { return MA_FALSE; } - if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, pWav, pAllocationCallbacks)) { + if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, ma_dr_wav__on_tell_memory, pWav, pAllocationCallbacks)) { return MA_FALSE; } pWav->memoryStream.data = (const ma_uint8*)data; @@ -79897,7 +82624,7 @@ MA_API ma_bool32 ma_dr_wav_init_memory_with_metadata(ma_dr_wav* pWav, const void if (data == NULL || dataSize == 0) { return MA_FALSE; } - if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, pWav, pAllocationCallbacks)) { + if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, ma_dr_wav__on_tell_memory, pWav, pAllocationCallbacks)) { return MA_FALSE; } pWav->memoryStream.data = (const ma_uint8*)data; @@ -79956,30 +82683,30 @@ MA_API ma_result ma_dr_wav_uninit(ma_dr_wav* pWav) } if (pWav->onSeek && !pWav->isSequentialWrite) { if (pWav->container == ma_dr_wav_container_riff) { - if (pWav->onSeek(pWav->pUserData, 4, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, 4, MA_DR_WAV_SEEK_SET)) { ma_uint32 riffChunkSize = ma_dr_wav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount); ma_dr_wav__write_u32ne_to_le(pWav, riffChunkSize); } - if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, MA_DR_WAV_SEEK_SET)) { ma_uint32 dataChunkSize = ma_dr_wav__data_chunk_size_riff(pWav->dataChunkDataSize); ma_dr_wav__write_u32ne_to_le(pWav, dataChunkSize); } } else if (pWav->container == ma_dr_wav_container_w64) { - if (pWav->onSeek(pWav->pUserData, 16, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, 16, MA_DR_WAV_SEEK_SET)) { ma_uint64 riffChunkSize = ma_dr_wav__riff_chunk_size_w64(pWav->dataChunkDataSize); ma_dr_wav__write_u64ne_to_le(pWav, riffChunkSize); } - if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, MA_DR_WAV_SEEK_SET)) { ma_uint64 dataChunkSize = ma_dr_wav__data_chunk_size_w64(pWav->dataChunkDataSize); ma_dr_wav__write_u64ne_to_le(pWav, dataChunkSize); } } else if (pWav->container == ma_dr_wav_container_rf64) { int ds64BodyPos = 12 + 8; - if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, MA_DR_WAV_SEEK_SET)) { ma_uint64 riffChunkSize = ma_dr_wav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount); ma_dr_wav__write_u64ne_to_le(pWav, riffChunkSize); } - if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, ma_dr_wav_seek_origin_start)) { + if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, MA_DR_WAV_SEEK_SET)) { ma_uint64 dataChunkSize = ma_dr_wav__data_chunk_size_rf64(pWav->dataChunkDataSize); ma_dr_wav__write_u64ne_to_le(pWav, dataChunkSize); } @@ -80026,7 +82753,7 @@ MA_API size_t ma_dr_wav_read_raw(ma_dr_wav* pWav, size_t bytesToRead, void* pBuf if (bytesToSeek > 0x7FFFFFFF) { bytesToSeek = 0x7FFFFFFF; } - if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, ma_dr_wav_seek_origin_current) == MA_FALSE) { + if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, MA_DR_WAV_SEEK_CUR) == MA_FALSE) { break; } bytesRead += bytesToSeek; @@ -80125,7 +82852,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav_seek_to_first_pcm_frame(ma_dr_wav* pWav) if (pWav->onWrite != NULL) { return MA_FALSE; } - if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, ma_dr_wav_seek_origin_start)) { + if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, MA_DR_WAV_SEEK_SET)) { return MA_FALSE; } if (ma_dr_wav__is_compressed_format_tag(pWav->translatedFormatTag)) { @@ -80206,7 +82933,7 @@ MA_API ma_bool32 ma_dr_wav_seek_to_pcm_frame(ma_dr_wav* pWav, ma_uint64 targetFr } while (offset > 0) { int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset); - if (!pWav->onSeek(pWav->pUserData, offset32, ma_dr_wav_seek_origin_current)) { + if (!pWav->onSeek(pWav->pUserData, offset32, MA_DR_WAV_SEEK_CUR)) { return MA_FALSE; } pWav->readCursorInPCMFrames += offset32 / bytesPerFrame; @@ -80332,6 +83059,12 @@ MA_API ma_uint64 ma_dr_wav_write_pcm_frames(ma_dr_wav* pWav, ma_uint64 framesToW MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_uint64 framesToRead, ma_int16* pBufferOut) { ma_uint64 totalFramesRead = 0; + static const ma_int32 adaptationTable[] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 + }; + static const ma_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 }; + static const ma_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 }; MA_DR_WAV_ASSERT(pWav != NULL); MA_DR_WAV_ASSERT(framesToRead > 0); while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) { @@ -80350,6 +83083,9 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0]; pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.cachedFrameCount = 2; + if (pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff2Table)) { + return totalFramesRead; + } } else { ma_uint8 header[14]; if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) { @@ -80369,6 +83105,10 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1]; pWav->msadpcm.cachedFrameCount = 2; + if (pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff2Table) || + pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff2Table)) { + return totalFramesRead; + } } } while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) { @@ -80391,12 +83131,6 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ if (pWav->msadpcm.bytesRemainingInBlock == 0) { continue; } else { - static ma_int32 adaptationTable[] = { - 230, 230, 230, 230, 307, 409, 512, 614, - 768, 614, 512, 409, 307, 230, 230, 230 - }; - static ma_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 }; - static ma_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 }; ma_uint8 nibbles; ma_int32 nibble0; ma_int32 nibble1; @@ -80409,6 +83143,9 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ if (pWav->channels == 1) { ma_int32 newSample0; ma_int32 newSample1; + if (pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff2Table)) { + return totalFramesRead; + } newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767); @@ -80433,6 +83170,9 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ } else { ma_int32 newSample0; ma_int32 newSample1; + if (pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= ma_dr_wav_countof(coeff2Table)) { + return totalFramesRead; + } newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767); @@ -80442,6 +83182,9 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_ } pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][1] = newSample0; + if (pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff2Table)) { + return totalFramesRead; + } newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8; newSample1 += nibble1 * pWav->msadpcm.delta[1]; newSample1 = ma_dr_wav_clamp(newSample1, -32768, 32767); @@ -80464,11 +83207,11 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint { ma_uint64 totalFramesRead = 0; ma_uint32 iChannel; - static ma_int32 indexTable[16] = { + static const ma_int32 indexTable[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; - static ma_int32 stepTable[89] = { + static const ma_int32 stepTable[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, @@ -80491,7 +83234,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint } pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header); if (header[2] >= ma_dr_wav_countof(stepTable)) { - pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, ma_dr_wav_seek_origin_current); + pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, MA_DR_WAV_SEEK_CUR); pWav->ima.bytesRemainingInBlock = 0; return totalFramesRead; } @@ -80506,7 +83249,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint } pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header); if (header[2] >= ma_dr_wav_countof(stepTable) || header[6] >= ma_dr_wav_countof(stepTable)) { - pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, ma_dr_wav_seek_origin_current); + pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, MA_DR_WAV_SEEK_CUR); pWav->ima.bytesRemainingInBlock = 0; return totalFramesRead; } @@ -80581,7 +83324,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint return totalFramesRead; } #ifndef MA_DR_WAV_NO_CONVERSION_API -static unsigned short g_ma_dr_wavAlawTable[256] = { +static const unsigned short ma_dr_wav_gAlawTable[256] = { 0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580, 0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0, 0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600, @@ -80599,7 +83342,7 @@ static unsigned short g_ma_dr_wavAlawTable[256] = { 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0, 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350 }; -static unsigned short g_ma_dr_wavMulawTable[256] = { +static const unsigned short ma_dr_wav_gMulawTable[256] = { 0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84, 0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84, 0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004, @@ -80619,11 +83362,11 @@ static unsigned short g_ma_dr_wavMulawTable[256] = { }; static MA_INLINE ma_int16 ma_dr_wav__alaw_to_s16(ma_uint8 sampleIn) { - return (short)g_ma_dr_wavAlawTable[sampleIn]; + return (short)ma_dr_wav_gAlawTable[sampleIn]; } static MA_INLINE ma_int16 ma_dr_wav__mulaw_to_s16(ma_uint8 sampleIn) { - return (short)g_ma_dr_wavMulawTable[sampleIn]; + return (short)ma_dr_wav_gMulawTable[sampleIn]; } MA_PRIVATE void ma_dr_wav__pcm_to_s16(ma_int16* pOut, const ma_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample) { @@ -81647,7 +84390,7 @@ MA_API void ma_dr_wav_f32_to_s32(ma_int32* pOut, const float* pIn, size_t sample return; } for (i = 0; i < sampleCount; ++i) { - *pOut++ = (ma_int32)(2147483648.0 * pIn[i]); + *pOut++ = (ma_int32)(2147483648.0f * pIn[i]); } } MA_API void ma_dr_wav_f64_to_s32(ma_int32* pOut, const double* pIn, size_t sampleCount) @@ -81686,6 +84429,10 @@ MA_PRIVATE ma_int16* ma_dr_wav__read_pcm_frames_and_close_s16(ma_dr_wav* pWav, u ma_int16* pSampleData; ma_uint64 framesRead; MA_DR_WAV_ASSERT(pWav != NULL); + if (pWav->channels == 0 || pWav->totalPCMFrameCount > MA_SIZE_MAX / pWav->channels / sizeof(ma_int16)) { + ma_dr_wav_uninit(pWav); + return NULL; + } sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(ma_int16); if (sampleDataSize > MA_SIZE_MAX) { ma_dr_wav_uninit(pWav); @@ -81720,6 +84467,10 @@ MA_PRIVATE float* ma_dr_wav__read_pcm_frames_and_close_f32(ma_dr_wav* pWav, unsi float* pSampleData; ma_uint64 framesRead; MA_DR_WAV_ASSERT(pWav != NULL); + if (pWav->channels == 0 || pWav->totalPCMFrameCount > MA_SIZE_MAX / pWav->channels / sizeof(float)) { + ma_dr_wav_uninit(pWav); + return NULL; + } sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float); if (sampleDataSize > MA_SIZE_MAX) { ma_dr_wav_uninit(pWav); @@ -81754,6 +84505,10 @@ MA_PRIVATE ma_int32* ma_dr_wav__read_pcm_frames_and_close_s32(ma_dr_wav* pWav, u ma_int32* pSampleData; ma_uint64 framesRead; MA_DR_WAV_ASSERT(pWav != NULL); + if (pWav->channels == 0 || pWav->totalPCMFrameCount > MA_SIZE_MAX / pWav->channels / sizeof(ma_int32)) { + ma_dr_wav_uninit(pWav); + return NULL; + } sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(ma_int32); if (sampleDataSize > MA_SIZE_MAX) { ma_dr_wav_uninit(pWav); @@ -81782,7 +84537,7 @@ MA_PRIVATE ma_int32* ma_dr_wav__read_pcm_frames_and_close_s32(ma_dr_wav* pWav, u } return pSampleData; } -MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_wav wav; if (channelsOut) { @@ -81794,12 +84549,12 @@ MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRe if (totalFrameCountOut) { *totalFrameCountOut = 0; } - if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) { return NULL; } return ma_dr_wav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut); } -MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_wav wav; if (channelsOut) { @@ -81811,12 +84566,12 @@ MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, if (totalFrameCountOut) { *totalFrameCountOut = 0; } - if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) { return NULL; } return ma_dr_wav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut); } -MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_wav wav; if (channelsOut) { @@ -81828,7 +84583,7 @@ MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRe if (totalFrameCountOut) { *totalFrameCountOut = 0; } - if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) { return NULL; } return ma_dr_wav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut); @@ -82061,7 +84816,7 @@ MA_API ma_bool32 ma_dr_wav_fourcc_equal(const ma_uint8* a, const char* b) #endif /* MA_NO_WAV */ #if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING) -#if !defined(MA_DR_FLAC_IMPLEMENTATION) && !defined(MA_DR_FLAC_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */ +#if !defined(MA_DR_FLAC_IMPLEMENTATION) /* dr_flac_c begin */ #ifndef ma_dr_flac_c #define ma_dr_flac_c @@ -83136,7 +85891,7 @@ static MA_INLINE ma_uint32 ma_dr_flac__clz_lzcnt(ma_dr_flac_cache_t x) { ma_uint64 r; __asm__ __volatile__ ( - "lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + "rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" ); return (ma_uint32)r; } @@ -83144,11 +85899,11 @@ static MA_INLINE ma_uint32 ma_dr_flac__clz_lzcnt(ma_dr_flac_cache_t x) { ma_uint32 r; __asm__ __volatile__ ( - "lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" + "rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc" ); return r; } - #elif defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(MA_64BIT) + #elif defined(MA_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(MA_64BIT) { unsigned int r; __asm__ __volatile__ ( @@ -83263,23 +86018,23 @@ static ma_bool32 ma_dr_flac__seek_to_byte(ma_dr_flac_bs* bs, ma_uint64 offsetFro MA_DR_FLAC_ASSERT(offsetFromStart > 0); if (offsetFromStart > 0x7FFFFFFF) { ma_uint64 bytesRemaining = offsetFromStart; - if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_start)) { + if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } bytesRemaining -= 0x7FFFFFFF; while (bytesRemaining > 0x7FFFFFFF) { - if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_current)) { + if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } bytesRemaining -= 0x7FFFFFFF; } if (bytesRemaining > 0) { - if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, ma_dr_flac_seek_origin_current)) { + if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } } } else { - if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, ma_dr_flac_seek_origin_start)) { + if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } } @@ -85093,6 +87848,7 @@ static ma_bool32 ma_dr_flac__read_subframe_header(ma_dr_flac_bs* bs, ma_dr_flac_ if ((header & 0x80) != 0) { return MA_FALSE; } + pSubframe->lpcOrder = 0; type = (header & 0x7E) >> 1; if (type == 0) { pSubframe->subframeType = MA_DR_FLAC_SUBFRAME_CONSTANT; @@ -85150,6 +87906,9 @@ static ma_bool32 ma_dr_flac__decode_subframe(ma_dr_flac_bs* bs, ma_dr_flac_frame } subframeBitsPerSample -= pSubframe->wastedBitsPerSample; pSubframe->pSamplesS32 = pDecodedSamplesOut; + if (frame->header.blockSizeInPCMFrames < pSubframe->lpcOrder) { + return MA_FALSE; + } switch (pSubframe->subframeType) { case MA_DR_FLAC_SUBFRAME_CONSTANT: @@ -85753,6 +88512,7 @@ typedef struct { ma_dr_flac_read_proc onRead; ma_dr_flac_seek_proc onSeek; + ma_dr_flac_tell_proc onTell; ma_dr_flac_meta_proc onMeta; ma_dr_flac_container container; void* pUserData; @@ -85881,11 +88641,12 @@ static void ma_dr_flac__free_from_callbacks(void* p, const ma_allocation_callbac pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); } } -static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks) +static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks) { ma_uint64 runningFilePos = 42; ma_uint64 seektablePos = 0; ma_uint32 seektableSize = 0; + (void)onTell; for (;;) { ma_dr_flac_metadata metadata; ma_uint8 isLastBlock = 0; @@ -85896,8 +88657,9 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea } runningFilePos += 4; metadata.type = blockType; - metadata.pRawData = NULL; metadata.rawDataSize = 0; + metadata.rawDataOffset = runningFilePos; + metadata.pRawData = NULL; switch (blockType) { case MA_DR_FLAC_METADATA_BLOCK_TYPE_APPLICATION: @@ -86097,53 +88859,124 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea return MA_FALSE; } if (onMeta) { - void* pRawData; - const char* pRunningData; - const char* pRunningDataEnd; - pRawData = ma_dr_flac__malloc_from_callbacks(blockSize, pAllocationCallbacks); - if (pRawData == NULL) { + ma_bool32 result = MA_TRUE; + ma_uint32 blockSizeRemaining = blockSize; + char* pMime = NULL; + char* pDescription = NULL; + void* pPictureData = NULL; + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.type = ma_dr_flac__be2host_32(metadata.data.picture.type); + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.mimeLength = ma_dr_flac__be2host_32(metadata.data.picture.mimeLength); + pMime = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); + if (pMime == NULL) { + result = MA_FALSE; + goto done_flac; + } + if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= metadata.data.picture.mimeLength; + pMime[metadata.data.picture.mimeLength] = '\0'; + metadata.data.picture.mime = (const char*)pMime; + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.descriptionLength = ma_dr_flac__be2host_32(metadata.data.picture.descriptionLength); + pDescription = (char*)ma_dr_flac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); + if (pDescription == NULL) { + result = MA_FALSE; + goto done_flac; + } + if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= metadata.data.picture.descriptionLength; + pDescription[metadata.data.picture.descriptionLength] = '\0'; + metadata.data.picture.description = (const char*)pDescription; + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.width = ma_dr_flac__be2host_32(metadata.data.picture.width); + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.height = ma_dr_flac__be2host_32(metadata.data.picture.height); + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.colorDepth = ma_dr_flac__be2host_32(metadata.data.picture.colorDepth); + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.indexColorCount = ma_dr_flac__be2host_32(metadata.data.picture.indexColorCount); + if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) { + result = MA_FALSE; + goto done_flac; + } + blockSizeRemaining -= 4; + metadata.data.picture.pictureDataSize = ma_dr_flac__be2host_32(metadata.data.picture.pictureDataSize); + if (blockSizeRemaining < metadata.data.picture.pictureDataSize) { + result = MA_FALSE; + goto done_flac; + } + metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining); + #ifndef MA_DR_FLAC_NO_PICTURE_METADATA_MALLOC + pPictureData = ma_dr_flac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks); + if (pPictureData != NULL) { + if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) { + result = MA_FALSE; + goto done_flac; + } + } else + #endif + { + if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, MA_DR_FLAC_SEEK_CUR)) { + result = MA_FALSE; + goto done_flac; + } + } + blockSizeRemaining -= metadata.data.picture.pictureDataSize; + (void)blockSizeRemaining; + metadata.data.picture.pPictureData = (const ma_uint8*)pPictureData; + if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) { + onMeta(pUserDataMD, &metadata); + } else { + } + done_flac: + ma_dr_flac__free_from_callbacks(pMime, pAllocationCallbacks); + ma_dr_flac__free_from_callbacks(pDescription, pAllocationCallbacks); + ma_dr_flac__free_from_callbacks(pPictureData, pAllocationCallbacks); + if (result != MA_TRUE) { return MA_FALSE; } - if (onRead(pUserData, pRawData, blockSize) != blockSize) { - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); - return MA_FALSE; - } - metadata.pRawData = pRawData; - metadata.rawDataSize = blockSize; - pRunningData = (const char*)pRawData; - pRunningDataEnd = (const char*)pRawData + blockSize; - metadata.data.picture.type = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.mimeLength = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - if ((pRunningDataEnd - pRunningData) - 24 < (ma_int64)metadata.data.picture.mimeLength) { - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); - return MA_FALSE; - } - metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength; - metadata.data.picture.descriptionLength = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - if ((pRunningDataEnd - pRunningData) - 20 < (ma_int64)metadata.data.picture.descriptionLength) { - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); - return MA_FALSE; - } - metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength; - metadata.data.picture.width = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.height = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.colorDepth = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.indexColorCount = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.pictureDataSize = ma_dr_flac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4; - metadata.data.picture.pPictureData = (const ma_uint8*)pRunningData; - if (pRunningDataEnd - pRunningData < (ma_int64)metadata.data.picture.pictureDataSize) { - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); - return MA_FALSE; - } - onMeta(pUserDataMD, &metadata); - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); } } break; case MA_DR_FLAC_METADATA_BLOCK_TYPE_PADDING: { if (onMeta) { metadata.data.padding.unused = 0; - if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) { isLastBlock = MA_TRUE; } else { onMeta(pUserDataMD, &metadata); @@ -86153,7 +88986,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea case MA_DR_FLAC_METADATA_BLOCK_TYPE_INVALID: { if (onMeta) { - if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) { isLastBlock = MA_TRUE; } } @@ -86162,12 +88995,15 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea { if (onMeta) { void* pRawData = ma_dr_flac__malloc_from_callbacks(blockSize, pAllocationCallbacks); - if (pRawData == NULL) { - return MA_FALSE; - } - if (onRead(pUserData, pRawData, blockSize) != blockSize) { - ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); - return MA_FALSE; + if (pRawData != NULL) { + if (onRead(pUserData, pRawData, blockSize) != blockSize) { + ma_dr_flac__free_from_callbacks(pRawData, pAllocationCallbacks); + return MA_FALSE; + } + } else { + if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) { + return MA_FALSE; + } } metadata.pRawData = pRawData; metadata.rawDataSize = blockSize; @@ -86177,7 +89013,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea } break; } if (onMeta == NULL && blockSize > 0) { - if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) { isLastBlock = MA_TRUE; } } @@ -86441,6 +89277,7 @@ typedef struct { ma_dr_flac_read_proc onRead; ma_dr_flac_seek_proc onSeek; + ma_dr_flac_tell_proc onTell; void* pUserData; ma_uint64 currentBytePos; ma_uint64 firstBytePos; @@ -86459,29 +89296,29 @@ static size_t ma_dr_flac_oggbs__read_physical(ma_dr_flac_oggbs* oggbs, void* buf } static ma_bool32 ma_dr_flac_oggbs__seek_physical(ma_dr_flac_oggbs* oggbs, ma_uint64 offset, ma_dr_flac_seek_origin origin) { - if (origin == ma_dr_flac_seek_origin_start) { + if (origin == MA_DR_FLAC_SEEK_SET) { if (offset <= 0x7FFFFFFF) { - if (!oggbs->onSeek(oggbs->pUserData, (int)offset, ma_dr_flac_seek_origin_start)) { + if (!oggbs->onSeek(oggbs->pUserData, (int)offset, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } oggbs->currentBytePos = offset; return MA_TRUE; } else { - if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_start)) { + if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } oggbs->currentBytePos = offset; - return ma_dr_flac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, ma_dr_flac_seek_origin_current); + return ma_dr_flac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR); } } else { while (offset > 0x7FFFFFFF) { - if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_current)) { + if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } oggbs->currentBytePos += 0x7FFFFFFF; offset -= 0x7FFFFFFF; } - if (!oggbs->onSeek(oggbs->pUserData, (int)offset, ma_dr_flac_seek_origin_current)) { + if (!oggbs->onSeek(oggbs->pUserData, (int)offset, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } oggbs->currentBytePos += offset; @@ -86507,7 +89344,7 @@ static ma_bool32 ma_dr_flac_oggbs__goto_next_page(ma_dr_flac_oggbs* oggbs, ma_dr continue; } if (header.serialNumber != oggbs->serialNumber) { - if (pageBodySize > 0 && !ma_dr_flac_oggbs__seek_physical(oggbs, pageBodySize, ma_dr_flac_seek_origin_current)) { + if (pageBodySize > 0 && !ma_dr_flac_oggbs__seek_physical(oggbs, pageBodySize, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } continue; @@ -86569,7 +89406,7 @@ static ma_bool32 ma_dr_flac_oggbs__seek_to_next_packet(ma_dr_flac_oggbs* oggbs) } bytesToEndOfPacketOrPage += segmentSize; } - ma_dr_flac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, ma_dr_flac_seek_origin_current); + ma_dr_flac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, MA_DR_FLAC_SEEK_CUR); oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage; if (atEndOfPage) { if (!ma_dr_flac_oggbs__goto_next_page(oggbs)) { @@ -86622,36 +89459,44 @@ static ma_bool32 ma_dr_flac__on_seek_ogg(void* pUserData, int offset, ma_dr_flac int bytesSeeked = 0; MA_DR_FLAC_ASSERT(oggbs != NULL); MA_DR_FLAC_ASSERT(offset >= 0); - if (origin == ma_dr_flac_seek_origin_start) { - if (!ma_dr_flac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, ma_dr_flac_seek_origin_start)) { + if (origin == MA_DR_FLAC_SEEK_SET) { + if (!ma_dr_flac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) { return MA_FALSE; } - return ma_dr_flac__on_seek_ogg(pUserData, offset, ma_dr_flac_seek_origin_current); - } - MA_DR_FLAC_ASSERT(origin == ma_dr_flac_seek_origin_current); - while (bytesSeeked < offset) { - int bytesRemainingToSeek = offset - bytesSeeked; - MA_DR_FLAC_ASSERT(bytesRemainingToSeek >= 0); - if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) { - bytesSeeked += bytesRemainingToSeek; - (void)bytesSeeked; - oggbs->bytesRemainingInPage -= bytesRemainingToSeek; - break; - } - if (oggbs->bytesRemainingInPage > 0) { - bytesSeeked += (int)oggbs->bytesRemainingInPage; - oggbs->bytesRemainingInPage = 0; - } - MA_DR_FLAC_ASSERT(bytesRemainingToSeek > 0); - if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) { - return MA_FALSE; + return ma_dr_flac__on_seek_ogg(pUserData, offset, MA_DR_FLAC_SEEK_CUR); + } else if (origin == MA_DR_FLAC_SEEK_CUR) { + while (bytesSeeked < offset) { + int bytesRemainingToSeek = offset - bytesSeeked; + MA_DR_FLAC_ASSERT(bytesRemainingToSeek >= 0); + if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) { + bytesSeeked += bytesRemainingToSeek; + (void)bytesSeeked; + oggbs->bytesRemainingInPage -= bytesRemainingToSeek; + break; + } + if (oggbs->bytesRemainingInPage > 0) { + bytesSeeked += (int)oggbs->bytesRemainingInPage; + oggbs->bytesRemainingInPage = 0; + } + MA_DR_FLAC_ASSERT(bytesRemainingToSeek > 0); + if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) { + return MA_FALSE; + } } + } else if (origin == MA_DR_FLAC_SEEK_END) { + return MA_FALSE; } return MA_TRUE; } +static ma_bool32 ma_dr_flac__on_tell_ogg(void* pUserData, ma_int64* pCursor) +{ + (void)pUserData; + (void)pCursor; + return MA_FALSE; +} static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64 pcmFrameIndex) { ma_dr_flac_oggbs* oggbs = (ma_dr_flac_oggbs*)pFlac->_oggbs; @@ -86668,7 +89513,7 @@ static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64 runningGranulePosition = 0; for (;;) { if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_recover_on_crc_mismatch)) { - ma_dr_flac_oggbs__seek_physical(oggbs, originalBytePos, ma_dr_flac_seek_origin_start); + ma_dr_flac_oggbs__seek_physical(oggbs, originalBytePos, MA_DR_FLAC_SEEK_SET); return MA_FALSE; } runningFrameBytePos = oggbs->currentBytePos - ma_dr_flac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize; @@ -86687,7 +89532,7 @@ static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64 } } } - if (!ma_dr_flac_oggbs__seek_physical(oggbs, runningFrameBytePos, ma_dr_flac_seek_origin_start)) { + if (!ma_dr_flac_oggbs__seek_physical(oggbs, runningFrameBytePos, MA_DR_FLAC_SEEK_SET)) { return MA_FALSE; } if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_recover_on_crc_mismatch)) { @@ -86782,7 +89627,7 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d if (mappingVersion[0] != 1) { return MA_FALSE; } - if (!onSeek(pUserData, 2, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, 2, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } if (onRead(pUserData, sig, 4) != 4) { @@ -86827,17 +89672,17 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d return MA_FALSE; } } else { - if (!onSeek(pUserData, bytesRemainingInPage, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, bytesRemainingInPage, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } } } else { - if (!onSeek(pUserData, bytesRemainingInPage, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, bytesRemainingInPage, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } } } else { - if (!onSeek(pUserData, pageBodySize, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, pageBodySize, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } } @@ -86851,7 +89696,7 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d return MA_TRUE; } #endif -static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD) +static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD) { ma_bool32 relaxed; ma_uint8 id[4]; @@ -86861,12 +89706,14 @@ static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_fla MA_DR_FLAC_ZERO_MEMORY(pInit, sizeof(*pInit)); pInit->onRead = onRead; pInit->onSeek = onSeek; + pInit->onTell = onTell; pInit->onMeta = onMeta; pInit->container = container; pInit->pUserData = pUserData; pInit->pUserDataMD = pUserDataMD; pInit->bs.onRead = onRead; pInit->bs.onSeek = onSeek; + pInit->bs.onTell = onTell; pInit->bs.pUserData = pUserData; ma_dr_flac__reset_cache(&pInit->bs); relaxed = container != ma_dr_flac_container_unknown; @@ -86889,7 +89736,7 @@ static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_fla if (flags & 0x10) { headerSize += 10; } - if (!onSeek(pUserData, headerSize, ma_dr_flac_seek_origin_current)) { + if (!onSeek(pUserData, headerSize, MA_DR_FLAC_SEEK_CUR)) { return MA_FALSE; } pInit->runningFilePos += headerSize; @@ -86932,7 +89779,7 @@ static void ma_dr_flac__init_from_info(ma_dr_flac* pFlac, const ma_dr_flac_init_ pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount; pFlac->container = pInit->container; } -static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD, const ma_allocation_callbacks* pAllocationCallbacks) +static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_flac_init_info init; ma_uint32 allocationSize; @@ -86947,7 +89794,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on ma_allocation_callbacks allocationCallbacks; ma_dr_flac* pFlac; ma_dr_flac__init_cpu_caps(); - if (!ma_dr_flac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) { + if (!ma_dr_flac__init_private(&init, onRead, onSeek, onTell, onMeta, container, pUserData, pUserDataMD)) { return NULL; } if (pAllocationCallbacks != NULL) { @@ -86980,6 +89827,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on MA_DR_FLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs)); pOggbs->onRead = onRead; pOggbs->onSeek = onSeek; + pOggbs->onTell = onTell; pOggbs->pUserData = pUserData; pOggbs->currentBytePos = init.oggFirstBytePos; pOggbs->firstBytePos = init.oggFirstBytePos; @@ -86994,15 +89842,17 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on if (init.hasMetadataBlocks) { ma_dr_flac_read_proc onReadOverride = onRead; ma_dr_flac_seek_proc onSeekOverride = onSeek; + ma_dr_flac_tell_proc onTellOverride = onTell; void* pUserDataOverride = pUserData; #ifndef MA_DR_FLAC_NO_OGG if (init.container == ma_dr_flac_container_ogg) { onReadOverride = ma_dr_flac__on_read_ogg; onSeekOverride = ma_dr_flac__on_seek_ogg; + onTellOverride = ma_dr_flac__on_tell_ogg; pUserDataOverride = (void*)pOggbs; } #endif - if (!ma_dr_flac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) { + if (!ma_dr_flac__read_and_decode_metadata(onReadOverride, onSeekOverride, onTellOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) { #ifndef MA_DR_FLAC_NO_OGG ma_dr_flac__free_from_callbacks(pOggbs, &allocationCallbacks); #endif @@ -87028,6 +89878,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on pOggbs = NULL; pFlac->bs.onRead = ma_dr_flac__on_read_ogg; pFlac->bs.onSeek = ma_dr_flac__on_seek_ogg; + pFlac->bs.onTell = ma_dr_flac__on_tell_ogg; pFlac->bs.pUserData = (void*)pInternalOggbs; pFlac->_oggbs = (void*)pInternalOggbs; } @@ -87047,7 +89898,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on pFlac->pSeekpoints = (ma_dr_flac_seekpoint*)((ma_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize); MA_DR_FLAC_ASSERT(pFlac->bs.onSeek != NULL); MA_DR_FLAC_ASSERT(pFlac->bs.onRead != NULL); - if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, ma_dr_flac_seek_origin_start)) { + if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, MA_DR_FLAC_SEEK_SET)) { ma_uint32 iSeekpoint; for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) { if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, MA_DR_FLAC_SEEKPOINT_SIZE_IN_BYTES) == MA_DR_FLAC_SEEKPOINT_SIZE_IN_BYTES) { @@ -87060,7 +89911,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on break; } } - if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, ma_dr_flac_seek_origin_start)) { + if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, MA_DR_FLAC_SEEK_SET)) { ma_dr_flac__free_from_callbacks(pFlac, &allocationCallbacks); return NULL; } @@ -87103,8 +89954,31 @@ static size_t ma_dr_flac__on_read_stdio(void* pUserData, void* bufferOut, size_t } static ma_bool32 ma_dr_flac__on_seek_stdio(void* pUserData, int offset, ma_dr_flac_seek_origin origin) { - MA_DR_FLAC_ASSERT(offset >= 0); - return fseek((FILE*)pUserData, offset, (origin == ma_dr_flac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; + int whence = SEEK_SET; + if (origin == MA_DR_FLAC_SEEK_CUR) { + whence = SEEK_CUR; + } else if (origin == MA_DR_FLAC_SEEK_END) { + whence = SEEK_END; + } + return fseek((FILE*)pUserData, offset, whence) == 0; +} +static ma_bool32 ma_dr_flac__on_tell_stdio(void* pUserData, ma_int64* pCursor) +{ + FILE* pFileStdio = (FILE*)pUserData; + ma_int64 result; + MA_DR_FLAC_ASSERT(pFileStdio != NULL); + MA_DR_FLAC_ASSERT(pCursor != NULL); +#if defined(_WIN32) && !defined(NXDK) + #if defined(_MSC_VER) && _MSC_VER > 1200 + result = _ftelli64(pFileStdio); + #else + result = ftell(pFileStdio); + #endif +#else + result = ftell(pFileStdio); +#endif + *pCursor = result; + return MA_TRUE; } MA_API ma_dr_flac* ma_dr_flac_open_file(const char* pFileName, const ma_allocation_callbacks* pAllocationCallbacks) { @@ -87113,7 +89987,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file(const char* pFileName, const ma_allocati if (ma_fopen(&pFile, pFileName, "rb") != MA_SUCCESS) { return NULL; } - pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, (void*)pFile, pAllocationCallbacks); + pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, (void*)pFile, pAllocationCallbacks); if (pFlac == NULL) { fclose(pFile); return NULL; @@ -87128,7 +90002,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_w(const wchar_t* pFileName, const ma_all if (ma_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != MA_SUCCESS) { return NULL; } - pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, (void*)pFile, pAllocationCallbacks); + pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, (void*)pFile, pAllocationCallbacks); if (pFlac == NULL) { fclose(pFile); return NULL; @@ -87143,7 +90017,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata(const char* pFileName, ma_ if (ma_fopen(&pFile, pFileName, "rb") != MA_SUCCESS) { return NULL; } - pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks); if (pFlac == NULL) { fclose(pFile); return pFlac; @@ -87158,7 +90032,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata_w(const wchar_t* pFileName if (ma_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != MA_SUCCESS) { return NULL; } - pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks); if (pFlac == NULL) { fclose(pFile); return pFlac; @@ -87186,24 +90060,34 @@ static size_t ma_dr_flac__on_read_memory(void* pUserData, void* bufferOut, size_ static ma_bool32 ma_dr_flac__on_seek_memory(void* pUserData, int offset, ma_dr_flac_seek_origin origin) { ma_dr_flac__memory_stream* memoryStream = (ma_dr_flac__memory_stream*)pUserData; + ma_int64 newCursor; MA_DR_FLAC_ASSERT(memoryStream != NULL); - MA_DR_FLAC_ASSERT(offset >= 0); - if (offset > (ma_int64)memoryStream->dataSize) { + if (origin == MA_DR_FLAC_SEEK_SET) { + newCursor = 0; + } else if (origin == MA_DR_FLAC_SEEK_CUR) { + newCursor = (ma_int64)memoryStream->currentReadPos; + } else if (origin == MA_DR_FLAC_SEEK_END) { + newCursor = (ma_int64)memoryStream->dataSize; + } else { + MA_DR_FLAC_ASSERT(!"Invalid seek origin"); return MA_FALSE; } - if (origin == ma_dr_flac_seek_origin_current) { - if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) { - memoryStream->currentReadPos += offset; - } else { - return MA_FALSE; - } - } else { - if ((ma_uint32)offset <= memoryStream->dataSize) { - memoryStream->currentReadPos = offset; - } else { - return MA_FALSE; - } + newCursor += offset; + if (newCursor < 0) { + return MA_FALSE; } + if ((size_t)newCursor > memoryStream->dataSize) { + return MA_FALSE; + } + memoryStream->currentReadPos = (size_t)newCursor; + return MA_TRUE; +} +static ma_bool32 ma_dr_flac__on_tell_memory(void* pUserData, ma_int64* pCursor) +{ + ma_dr_flac__memory_stream* memoryStream = (ma_dr_flac__memory_stream*)pUserData; + MA_DR_FLAC_ASSERT(memoryStream != NULL); + MA_DR_FLAC_ASSERT(pCursor != NULL); + *pCursor = (ma_int64)memoryStream->currentReadPos; return MA_TRUE; } MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks) @@ -87213,7 +90097,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, co memoryStream.data = (const ma_uint8*)pData; memoryStream.dataSize = dataSize; memoryStream.currentReadPos = 0; - pFlac = ma_dr_flac_open(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, &memoryStream, pAllocationCallbacks); + pFlac = ma_dr_flac_open(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, ma_dr_flac__on_tell_memory, &memoryStream, pAllocationCallbacks); if (pFlac == NULL) { return NULL; } @@ -87238,7 +90122,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_ memoryStream.data = (const ma_uint8*)pData; memoryStream.dataSize = dataSize; memoryStream.currentReadPos = 0; - pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, onMeta, ma_dr_flac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, ma_dr_flac__on_tell_memory, onMeta, ma_dr_flac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks); if (pFlac == NULL) { return NULL; } @@ -87256,21 +90140,21 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_ } return pFlac; } -MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_dr_flac_open_with_metadata_private(onRead, onSeek, NULL, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks); + return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, NULL, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks); } -MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_dr_flac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks); + return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, NULL, container, pUserData, pUserData, pAllocationCallbacks); } -MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onMeta, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks); + return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks); } -MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks); + return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, container, pUserData, pUserData, pAllocationCallbacks); } MA_API void ma_dr_flac_close(ma_dr_flac* pFlac) { @@ -89498,56 +92382,41 @@ static type* ma_dr_flac__full_read_and_close_ ## extension (ma_dr_flac* pFlac, u { \ type* pSampleData = NULL; \ ma_uint64 totalPCMFrameCount; \ + type buffer[4096]; \ + ma_uint64 pcmFramesRead; \ + size_t sampleDataBufferSize = sizeof(buffer); \ \ MA_DR_FLAC_ASSERT(pFlac != NULL); \ \ - totalPCMFrameCount = pFlac->totalPCMFrameCount; \ + totalPCMFrameCount = 0; \ \ - if (totalPCMFrameCount == 0) { \ - type buffer[4096]; \ - ma_uint64 pcmFramesRead; \ - size_t sampleDataBufferSize = sizeof(buffer); \ + pSampleData = (type*)ma_dr_flac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \ + if (pSampleData == NULL) { \ + goto on_error; \ + } \ \ - pSampleData = (type*)ma_dr_flac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \ - if (pSampleData == NULL) { \ - goto on_error; \ - } \ + while ((pcmFramesRead = (ma_uint64)ma_dr_flac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \ + if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \ + type* pNewSampleData; \ + size_t newSampleDataBufferSize; \ \ - while ((pcmFramesRead = (ma_uint64)ma_dr_flac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \ - if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \ - type* pNewSampleData; \ - size_t newSampleDataBufferSize; \ - \ - newSampleDataBufferSize = sampleDataBufferSize * 2; \ - pNewSampleData = (type*)ma_dr_flac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \ - if (pNewSampleData == NULL) { \ - ma_dr_flac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \ - goto on_error; \ - } \ - \ - sampleDataBufferSize = newSampleDataBufferSize; \ - pSampleData = pNewSampleData; \ + newSampleDataBufferSize = sampleDataBufferSize * 2; \ + pNewSampleData = (type*)ma_dr_flac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \ + if (pNewSampleData == NULL) { \ + ma_dr_flac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \ + goto on_error; \ } \ \ - MA_DR_FLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \ - totalPCMFrameCount += pcmFramesRead; \ + sampleDataBufferSize = newSampleDataBufferSize; \ + pSampleData = pNewSampleData; \ } \ \ + MA_DR_FLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \ + totalPCMFrameCount += pcmFramesRead; \ + } \ + \ \ - MA_DR_FLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \ - } else { \ - ma_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \ - if (dataSize > (ma_uint64)MA_SIZE_MAX) { \ - goto on_error; \ - } \ - \ - pSampleData = (type*)ma_dr_flac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); \ - if (pSampleData == NULL) { \ - goto on_error; \ - } \ - \ - totalPCMFrameCount = ma_dr_flac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \ - } \ + MA_DR_FLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \ \ if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \ if (channelsOut) *channelsOut = pFlac->channels; \ @@ -89563,7 +92432,7 @@ on_error: MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(s32, ma_int32) MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(s16, ma_int16) MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float) -MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_flac* pFlac; if (channelsOut) { @@ -89575,13 +92444,13 @@ MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc on if (totalPCMFrameCountOut) { *totalPCMFrameCountOut = 0; } - pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks); if (pFlac == NULL) { return NULL; } return ma_dr_flac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut); } -MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_flac* pFlac; if (channelsOut) { @@ -89593,13 +92462,13 @@ MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc on if (totalPCMFrameCountOut) { *totalPCMFrameCountOut = 0; } - pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks); if (pFlac == NULL) { return NULL; } return ma_dr_flac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut); } -MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_flac* pFlac; if (channelsOut) { @@ -89611,7 +92480,7 @@ MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRea if (totalPCMFrameCountOut) { *totalPCMFrameCountOut = 0; } - pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks); + pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks); if (pFlac == NULL) { return NULL; } @@ -89806,7 +92675,7 @@ MA_API ma_bool32 ma_dr_flac_next_cuesheet_track(ma_dr_flac_cuesheet_track_iterat #endif /* MA_NO_FLAC */ #if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING) -#if !defined(MA_DR_MP3_IMPLEMENTATION) && !defined(MA_DR_MP3_IMPLEMENTATION) /* For backwards compatibility. Will be removed in version 0.11 for cleanliness. */ +#if !defined(MA_DR_MP3_IMPLEMENTATION) /* dr_mp3_c begin */ #ifndef ma_dr_mp3_c #define ma_dr_mp3_c @@ -89833,12 +92702,9 @@ MA_API const char* ma_dr_mp3_version_string(void) #define MA_DR_MP3_NO_SIMD #endif #define MA_DR_MP3_OFFSET_PTR(p, offset) ((void*)((ma_uint8*)(p) + (offset))) -#define MA_DR_MP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 #ifndef MA_DR_MP3_MAX_FRAME_SYNC_MATCHES #define MA_DR_MP3_MAX_FRAME_SYNC_MATCHES 10 #endif -#define MA_DR_MP3_MAX_L3_FRAME_PAYLOAD_BYTES MA_DR_MP3_MAX_FREE_FORMAT_FRAME_SIZE -#define MA_DR_MP3_MAX_BITRESERVOIR_BYTES 511 #define MA_DR_MP3_SHORT_BLOCK_TYPE 2 #define MA_DR_MP3_STOP_BLOCK_TYPE 3 #define MA_DR_MP3_MODE_MONO 3 @@ -89867,7 +92733,7 @@ MA_API const char* ma_dr_mp3_version_string(void) #define MA_DR_MP3_MIN(a, b) ((a) > (b) ? (b) : (a)) #define MA_DR_MP3_MAX(a, b) ((a) < (b) ? (b) : (a)) #if !defined(MA_DR_MP3_NO_SIMD) -#if !defined(MA_DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64)) +#if !defined(MA_DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) #define MA_DR_MP3_ONLY_SIMD #endif #if ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__))) @@ -89888,7 +92754,7 @@ MA_API const char* ma_dr_mp3_version_string(void) #define MA_DR_MP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s)) #define MA_DR_MP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3)) typedef __m128 ma_dr_mp3_f4; -#if defined(_MSC_VER) || defined(MA_DR_MP3_ONLY_SIMD) +#if (defined(_MSC_VER) || defined(MA_DR_MP3_ONLY_SIMD)) && !defined(__clang__) #define ma_dr_mp3_cpuid __cpuid #else static __inline__ __attribute__((always_inline)) void ma_dr_mp3_cpuid(int CPUInfo[], const int InfoType) @@ -89940,7 +92806,7 @@ end: return g_have_simd - 1; #endif } -#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) +#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) #include #define MA_DR_MP3_HAVE_SSE 0 #define MA_DR_MP3_HAVE_SIMD 1 @@ -89969,7 +92835,7 @@ static int ma_dr_mp3_have_simd(void) #else #define MA_DR_MP3_HAVE_SIMD 0 #endif -#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(__ARM_ARCH_6M__) +#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) && !defined(__ARM_ARCH_6M__) #define MA_DR_MP3_HAVE_ARMV6 1 static __inline__ __attribute__((always_inline)) ma_int32 ma_dr_mp3_clip_int16_arm(ma_int32 a) { @@ -90004,11 +92870,6 @@ static __inline__ __attribute__((always_inline)) ma_int32 ma_dr_mp3_clip_int16_a #define MA_DR_MP3_FREE(p) free((p)) #endif typedef struct -{ - const ma_uint8 *buf; - int pos, limit; -} ma_dr_mp3_bs; -typedef struct { float scf[3*64]; ma_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64]; @@ -90017,22 +92878,6 @@ typedef struct { ma_uint8 tab_offset, code_tab_width, band_count; } ma_dr_mp3_L12_subband_alloc; -typedef struct -{ - const ma_uint8 *sfbtab; - ma_uint16 part_23_length, big_values, scalefac_compress; - ma_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb; - ma_uint8 table_select[3], region_count[3], subblock_gain[3]; - ma_uint8 preflag, scalefac_scale, count1_table, scfsi; -} ma_dr_mp3_L3_gr_info; -typedef struct -{ - ma_dr_mp3_bs bs; - ma_uint8 maindata[MA_DR_MP3_MAX_BITRESERVOIR_BYTES + MA_DR_MP3_MAX_L3_FRAME_PAYLOAD_BYTES]; - ma_dr_mp3_L3_gr_info gr_info[4]; - float grbuf[2][576], scf[40], syn[18 + 15][2*32]; - ma_uint8 ist_pos[2][39]; -} ma_dr_mp3dec_scratch; static void ma_dr_mp3_bs_init(ma_dr_mp3_bs *bs, const ma_uint8 *data, int bytes) { bs->buf = data; @@ -90415,6 +93260,10 @@ static float ma_dr_mp3_L3_ldexp_q2(float y, int exp_q2) } while ((exp_q2 -= e) > 0); return y; } +#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif static void ma_dr_mp3_L3_decode_scalefactors(const ma_uint8 *hdr, ma_uint8 *ist_pos, ma_dr_mp3_bs *bs, const ma_dr_mp3_L3_gr_info *gr, float *scf, int ch) { static const ma_uint8 g_scf_partitions[3][28] = { @@ -90473,7 +93322,10 @@ static void ma_dr_mp3_L3_decode_scalefactors(const ma_uint8 *hdr, ma_uint8 *ist_ scf[i] = ma_dr_mp3_L3_ldexp_q2(gain, iscf[i] << scf_shift); } } -static const float g_ma_dr_mp3_pow43[129 + 16] = { +#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__) + #pragma GCC diagnostic pop +#endif +static const float ma_dr_mp3_g_pow43[129 + 16] = { 0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f, 0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f }; @@ -90483,7 +93335,7 @@ static float ma_dr_mp3_L3_pow_43(int x) int sign, mult = 256; if (x < 129) { - return g_ma_dr_mp3_pow43[16 + x]; + return ma_dr_mp3_g_pow43[16 + x]; } if (x < 1024) { @@ -90492,7 +93344,7 @@ static float ma_dr_mp3_L3_pow_43(int x) } sign = 2*x & 64; frac = (float)((x & 63) - sign) / ((x & ~63) + sign); - return g_ma_dr_mp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult; + return ma_dr_mp3_g_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult; } static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit) { @@ -90562,7 +93414,7 @@ static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L *dst = one*ma_dr_mp3_L3_pow_43(lsb)*((ma_int32)bs_cache < 0 ? -1: 1); } else { - *dst = g_ma_dr_mp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + *dst = ma_dr_mp3_g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; } MA_DR_MP3_FLUSH_BITS(lsb ? 1 : 0); } @@ -90590,7 +93442,7 @@ static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L for (j = 0; j < 2; j++, dst++, leaf >>= 4) { int lsb = leaf & 0x0F; - *dst = g_ma_dr_mp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + *dst = ma_dr_mp3_g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; MA_DR_MP3_FLUSH_BITS(lsb ? 1 : 0); } MA_DR_MP3_CHECK_BITS; @@ -91135,8 +93987,8 @@ static ma_int16 ma_dr_mp3d_scale_pcm(float sample) s32 -= (s32 < 0); s = (ma_int16)ma_dr_mp3_clip_int16_arm(s32); #else - if (sample >= 32766.5) return (ma_int16) 32767; - if (sample <= -32767.5) return (ma_int16)-32768; + if (sample >= 32766.5f) return (ma_int16) 32767; + if (sample <= -32767.5f) return (ma_int16)-32768; s = (ma_int16)(sample + .5f); s -= (s < 0); #endif @@ -91398,7 +94250,6 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int int i = 0, igr, frame_size = 0, success = 1; const ma_uint8 *hdr; ma_dr_mp3_bs bs_frame[1]; - ma_dr_mp3dec_scratch scratch; if (mp3_bytes > 4 && dec->header[0] == 0xff && ma_dr_mp3_hdr_compare(dec->header, mp3)) { frame_size = ma_dr_mp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + ma_dr_mp3_hdr_padding(mp3); @@ -91421,7 +94272,7 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int MA_DR_MP3_COPY_MEMORY(dec->header, hdr, MA_DR_MP3_HDR_SIZE); info->frame_bytes = i + frame_size; info->channels = MA_DR_MP3_HDR_IS_MONO(hdr) ? 1 : 2; - info->hz = ma_dr_mp3_hdr_sample_rate_hz(hdr); + info->sample_rate = ma_dr_mp3_hdr_sample_rate_hz(hdr); info->layer = 4 - MA_DR_MP3_HDR_GET_LAYER(hdr); info->bitrate_kbps = ma_dr_mp3_hdr_bitrate_kbps(hdr); ma_dr_mp3_bs_init(bs_frame, hdr + MA_DR_MP3_HDR_SIZE, frame_size - MA_DR_MP3_HDR_SIZE); @@ -91431,23 +94282,23 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int } if (info->layer == 3) { - int main_data_begin = ma_dr_mp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr); + int main_data_begin = ma_dr_mp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr); if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit) { ma_dr_mp3dec_init(dec); return 0; } - success = ma_dr_mp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin); + success = ma_dr_mp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin); if (success && pcm != NULL) { for (igr = 0; igr < (MA_DR_MP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = MA_DR_MP3_OFFSET_PTR(pcm, sizeof(ma_dr_mp3d_sample_t)*576*info->channels)) { - MA_DR_MP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); - ma_dr_mp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels); - ma_dr_mp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (ma_dr_mp3d_sample_t*)pcm, scratch.syn[0]); + MA_DR_MP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); + ma_dr_mp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels); + ma_dr_mp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (ma_dr_mp3d_sample_t*)pcm, dec->scratch.syn[0]); } } - ma_dr_mp3_L3_save_reservoir(dec, &scratch); + ma_dr_mp3_L3_save_reservoir(dec, &dec->scratch); } else { #ifdef MA_DR_MP3_ONLY_MP3 @@ -91458,15 +94309,15 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int return ma_dr_mp3_hdr_frame_samples(hdr); } ma_dr_mp3_L12_read_scale_info(hdr, bs_frame, sci); - MA_DR_MP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); + MA_DR_MP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); for (i = 0, igr = 0; igr < 3; igr++) { - if (12 == (i += ma_dr_mp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) + if (12 == (i += ma_dr_mp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1))) { i = 0; - ma_dr_mp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]); - ma_dr_mp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (ma_dr_mp3d_sample_t*)pcm, scratch.syn[0]); - MA_DR_MP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float)); + ma_dr_mp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]); + ma_dr_mp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (ma_dr_mp3d_sample_t*)pcm, dec->scratch.syn[0]); + MA_DR_MP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float)); pcm = MA_DR_MP3_OFFSET_PTR(pcm, sizeof(ma_dr_mp3d_sample_t)*384*info->channels); } if (bs_frame->pos > bs_frame->limit) @@ -91522,9 +94373,9 @@ MA_API void ma_dr_mp3dec_f32_to_s16(const float *in, ma_int16 *out, size_t num_s for(; i < num_samples; i++) { float sample = in[i] * 32768.0f; - if (sample >= 32766.5) + if (sample >= 32766.5f) out[i] = (ma_int16) 32767; - else if (sample <= -32767.5) + else if (sample <= -32767.5f) out[i] = (ma_int16)-32768; else { @@ -91644,19 +94495,41 @@ static ma_allocation_callbacks ma_dr_mp3_copy_allocation_callbacks_or_defaults(c } static size_t ma_dr_mp3__on_read(ma_dr_mp3* pMP3, void* pBufferOut, size_t bytesToRead) { - size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead); + size_t bytesRead; + MA_DR_MP3_ASSERT(pMP3 != NULL); + MA_DR_MP3_ASSERT(pMP3->onRead != NULL); + if (bytesToRead == 0) { + return 0; + } + bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead); pMP3->streamCursor += bytesRead; return bytesRead; } +static size_t ma_dr_mp3__on_read_clamped(ma_dr_mp3* pMP3, void* pBufferOut, size_t bytesToRead) +{ + MA_DR_MP3_ASSERT(pMP3 != NULL); + MA_DR_MP3_ASSERT(pMP3->onRead != NULL); + if (pMP3->streamLength == MA_UINT64_MAX) { + return ma_dr_mp3__on_read(pMP3, pBufferOut, bytesToRead); + } else { + ma_uint64 bytesRemaining; + bytesRemaining = (pMP3->streamLength - pMP3->streamCursor); + if (bytesToRead > bytesRemaining) { + bytesToRead = (size_t)bytesRemaining; + } + return ma_dr_mp3__on_read(pMP3, pBufferOut, bytesToRead); + } +} static ma_bool32 ma_dr_mp3__on_seek(ma_dr_mp3* pMP3, int offset, ma_dr_mp3_seek_origin origin) { MA_DR_MP3_ASSERT(offset >= 0); + MA_DR_MP3_ASSERT(origin == MA_DR_MP3_SEEK_SET || origin == MA_DR_MP3_SEEK_CUR); if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) { return MA_FALSE; } - if (origin == ma_dr_mp3_seek_origin_start) { + if (origin == MA_DR_MP3_SEEK_SET) { pMP3->streamCursor = (ma_uint64)offset; - } else { + } else{ pMP3->streamCursor += offset; } return MA_TRUE; @@ -91666,18 +94539,18 @@ static ma_bool32 ma_dr_mp3__on_seek_64(ma_dr_mp3* pMP3, ma_uint64 offset, ma_dr_ if (offset <= 0x7FFFFFFF) { return ma_dr_mp3__on_seek(pMP3, (int)offset, origin); } - if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, ma_dr_mp3_seek_origin_start)) { + if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, MA_DR_MP3_SEEK_SET)) { return MA_FALSE; } offset -= 0x7FFFFFFF; while (offset > 0) { if (offset <= 0x7FFFFFFF) { - if (!ma_dr_mp3__on_seek(pMP3, (int)offset, ma_dr_mp3_seek_origin_current)) { + if (!ma_dr_mp3__on_seek(pMP3, (int)offset, MA_DR_MP3_SEEK_CUR)) { return MA_FALSE; } offset = 0; } else { - if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, ma_dr_mp3_seek_origin_current)) { + if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, MA_DR_MP3_SEEK_CUR)) { return MA_FALSE; } offset -= 0x7FFFFFFF; @@ -91685,7 +94558,18 @@ static ma_bool32 ma_dr_mp3__on_seek_64(ma_dr_mp3* pMP3, ma_uint64 offset, ma_dr_ } return MA_TRUE; } -static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames) +static void ma_dr_mp3__on_meta(ma_dr_mp3* pMP3, ma_dr_mp3_metadata_type type, const void* pRawData, size_t rawDataSize) +{ + if (pMP3->onMeta) { + ma_dr_mp3_metadata metadata; + MA_DR_MP3_ZERO_OBJECT(&metadata); + metadata.type = type; + metadata.pRawData = pRawData; + metadata.rawDataSize = rawDataSize; + pMP3->onMeta(pMP3->pUserDataMeta, &metadata); + } +} +static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData) { ma_uint32 pcmFramesRead = 0; MA_DR_MP3_ASSERT(pMP3 != NULL); @@ -91712,7 +94596,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d pMP3->pData = pNewData; pMP3->dataCapacity = newDataCap; } - bytesRead = ma_dr_mp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + bytesRead = ma_dr_mp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); if (bytesRead == 0) { if (pMP3->dataSize == 0) { pMP3->atEnd = MA_TRUE; @@ -91731,16 +94615,20 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d return 0; } pcmFramesRead = ma_dr_mp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info); - if (info.frame_bytes > 0) { - pMP3->dataConsumed += (size_t)info.frame_bytes; - pMP3->dataSize -= (size_t)info.frame_bytes; - } + pMP3->dataConsumed += (size_t)info.frame_bytes; + pMP3->dataSize -= (size_t)info.frame_bytes; if (pcmFramesRead > 0) { pcmFramesRead = ma_dr_mp3_hdr_frame_samples(pMP3->decoder.header); pMP3->pcmFramesConsumedInMP3Frame = 0; pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead; pMP3->mp3FrameChannels = info.channels; - pMP3->mp3FrameSampleRate = info.hz; + pMP3->mp3FrameSampleRate = info.sample_rate; + if (pMP3FrameInfo != NULL) { + *pMP3FrameInfo = info; + } + if (ppMP3FrameData != NULL) { + *ppMP3FrameData = pMP3->pData + pMP3->dataConsumed - (size_t)info.frame_bytes; + } break; } else if (info.frame_bytes == 0) { size_t bytesRead; @@ -91757,7 +94645,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d pMP3->pData = pNewData; pMP3->dataCapacity = newDataCap; } - bytesRead = ma_dr_mp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); + bytesRead = ma_dr_mp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize)); if (bytesRead == 0) { pMP3->atEnd = MA_TRUE; return 0; @@ -91767,7 +94655,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d }; return pcmFramesRead; } -static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames) +static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData) { ma_uint32 pcmFramesRead = 0; ma_dr_mp3dec_frame_info info; @@ -91783,36 +94671,44 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_m pMP3->pcmFramesConsumedInMP3Frame = 0; pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead; pMP3->mp3FrameChannels = info.channels; - pMP3->mp3FrameSampleRate = info.hz; + pMP3->mp3FrameSampleRate = info.sample_rate; + if (pMP3FrameInfo != NULL) { + *pMP3FrameInfo = info; + } + if (ppMP3FrameData != NULL) { + *ppMP3FrameData = pMP3->memory.pData + pMP3->memory.currentReadPos; + } break; } else if (info.frame_bytes > 0) { pMP3->memory.currentReadPos += (size_t)info.frame_bytes; + pMP3->streamCursor += (size_t)info.frame_bytes; } else { break; } } pMP3->memory.currentReadPos += (size_t)info.frame_bytes; + pMP3->streamCursor += (size_t)info.frame_bytes; return pcmFramesRead; } -static ma_uint32 ma_dr_mp3_decode_next_frame_ex(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames) +static ma_uint32 ma_dr_mp3_decode_next_frame_ex(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData) { if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) { - return ma_dr_mp3_decode_next_frame_ex__memory(pMP3, pPCMFrames); + return ma_dr_mp3_decode_next_frame_ex__memory(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData); } else { - return ma_dr_mp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames); + return ma_dr_mp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData); } } static ma_uint32 ma_dr_mp3_decode_next_frame(ma_dr_mp3* pMP3) { MA_DR_MP3_ASSERT(pMP3 != NULL); - return ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames); + return ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames, NULL, NULL); } #if 0 static ma_uint32 ma_dr_mp3_seek_next_frame(ma_dr_mp3* pMP3) { ma_uint32 pcmFrameCount; MA_DR_MP3_ASSERT(pMP3 != NULL); - pcmFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL); + pcmFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL); if (pcmFrameCount == 0) { return 0; } @@ -91822,33 +94718,252 @@ static ma_uint32 ma_dr_mp3_seek_next_frame(ma_dr_mp3* pMP3) return pcmFrameCount; } #endif -static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks) { + ma_dr_mp3dec_frame_info firstFrameInfo; + const ma_uint8* pFirstFrameData; + ma_uint32 firstFramePCMFrameCount; + ma_uint32 detectedMP3FrameCount = 0xFFFFFFFF; MA_DR_MP3_ASSERT(pMP3 != NULL); MA_DR_MP3_ASSERT(onRead != NULL); ma_dr_mp3dec_init(&pMP3->decoder); pMP3->onRead = onRead; pMP3->onSeek = onSeek; + pMP3->onMeta = onMeta; pMP3->pUserData = pUserData; + pMP3->pUserDataMeta = pUserDataMeta; pMP3->allocationCallbacks = ma_dr_mp3_copy_allocation_callbacks_or_defaults(pAllocationCallbacks); if (pMP3->allocationCallbacks.onFree == NULL || (pMP3->allocationCallbacks.onMalloc == NULL && pMP3->allocationCallbacks.onRealloc == NULL)) { return MA_FALSE; } - if (ma_dr_mp3_decode_next_frame(pMP3) == 0) { + pMP3->streamCursor = 0; + pMP3->streamLength = MA_UINT64_MAX; + pMP3->streamStartOffset = 0; + pMP3->delayInPCMFrames = 0; + pMP3->paddingInPCMFrames = 0; + pMP3->totalPCMFrameCount = MA_UINT64_MAX; + #if 1 + if (onSeek != NULL && onTell != NULL) { + if (onSeek(pUserData, 0, MA_DR_MP3_SEEK_END)) { + ma_int64 streamLen; + int streamEndOffset = 0; + if (onTell(pUserData, &streamLen)) { + if (streamLen > 128) { + char id3[3]; + if (onSeek(pUserData, streamEndOffset - 128, MA_DR_MP3_SEEK_END)) { + if (onRead(pUserData, id3, 3) == 3 && id3[0] == 'T' && id3[1] == 'A' && id3[2] == 'G') { + streamEndOffset -= 128; + streamLen -= 128; + if (onMeta != NULL) { + ma_uint8 tag[128]; + tag[0] = 'T'; tag[1] = 'A'; tag[2] = 'G'; + if (onRead(pUserData, tag + 3, 125) == 125) { + ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_ID3V1, tag, 128); + } + } + } else { + } + } else { + } + } else { + } + if (streamLen > 32) { + char ape[32]; + if (onSeek(pUserData, streamEndOffset - 32, MA_DR_MP3_SEEK_END)) { + if (onRead(pUserData, ape, 32) == 32 && ape[0] == 'A' && ape[1] == 'P' && ape[2] == 'E' && ape[3] == 'T' && ape[4] == 'A' && ape[5] == 'G' && ape[6] == 'E' && ape[7] == 'X') { + ma_uint32 tagSize = + ((ma_uint32)ape[24] << 0) | + ((ma_uint32)ape[25] << 8) | + ((ma_uint32)ape[26] << 16) | + ((ma_uint32)ape[27] << 24); + if (32 + tagSize < streamLen) { + streamEndOffset -= 32 + tagSize; + streamLen -= 32 + tagSize; + if (onMeta != NULL) { + if (onSeek(pUserData, streamEndOffset, MA_DR_MP3_SEEK_END)) { + size_t apeTagSize = (size_t)tagSize + 32; + ma_uint8* pTagData = (ma_uint8*)ma_dr_mp3_malloc(apeTagSize, pAllocationCallbacks); + if (pTagData != NULL) { + if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) { + ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_APE, pTagData, apeTagSize); + } + ma_dr_mp3_free(pTagData, pAllocationCallbacks); + } + } + } + } else { + } + } + } + } else { + } + if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) { + return MA_FALSE; + } + pMP3->streamLength = (ma_uint64)streamLen; + if (pMP3->memory.pData != NULL) { + pMP3->memory.dataSize = (size_t)pMP3->streamLength; + } + } else { + if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) { + return MA_FALSE; + } + } + } else { + } + } else { + } + #endif + #if 1 + { + char header[10]; + if (onRead(pUserData, header, 10) == 10) { + if (header[0] == 'I' && header[1] == 'D' && header[2] == '3') { + ma_uint32 tagSize = + (((ma_uint32)header[6] & 0x7F) << 21) | + (((ma_uint32)header[7] & 0x7F) << 14) | + (((ma_uint32)header[8] & 0x7F) << 7) | + (((ma_uint32)header[9] & 0x7F) << 0); + if (header[5] & 0x10) { + tagSize += 10; + } + if (onMeta != NULL) { + size_t tagSizeWithHeader = 10 + tagSize; + ma_uint8* pTagData = (ma_uint8*)ma_dr_mp3_malloc(tagSizeWithHeader, pAllocationCallbacks); + if (pTagData != NULL) { + MA_DR_MP3_COPY_MEMORY(pTagData, header, 10); + if (onRead(pUserData, pTagData + 10, tagSize) == tagSize) { + ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_ID3V2, pTagData, tagSizeWithHeader); + } + ma_dr_mp3_free(pTagData, pAllocationCallbacks); + } + } else { + if (onSeek != NULL) { + if (!onSeek(pUserData, tagSize, MA_DR_MP3_SEEK_CUR)) { + return MA_FALSE; + } + } else { + char discard[1024]; + while (tagSize > 0) { + size_t bytesToRead = tagSize; + if (bytesToRead > sizeof(discard)) { + bytesToRead = sizeof(discard); + } + if (onRead(pUserData, discard, bytesToRead) != bytesToRead) { + return MA_FALSE; + } + tagSize -= (ma_uint32)bytesToRead; + } + } + } + pMP3->streamStartOffset += 10 + tagSize; + pMP3->streamCursor = pMP3->streamStartOffset; + } else { + if (onSeek != NULL) { + if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) { + return MA_FALSE; + } + } else { + } + } + } else { + return MA_FALSE; + } + } + #endif + firstFramePCMFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames, &firstFrameInfo, &pFirstFrameData); + if (firstFramePCMFrameCount > 0) { + MA_DR_MP3_ASSERT(pFirstFrameData != NULL); + #if 1 + MA_DR_MP3_ASSERT(firstFrameInfo.frame_bytes > 0); + { + ma_dr_mp3_bs bs; + ma_dr_mp3_L3_gr_info grInfo[4]; + ma_dr_mp3_bs_init(&bs, pFirstFrameData + MA_DR_MP3_HDR_SIZE, firstFrameInfo.frame_bytes - MA_DR_MP3_HDR_SIZE); + if (MA_DR_MP3_HDR_IS_CRC(pFirstFrameData)) { + ma_dr_mp3_bs_get_bits(&bs, 16); + } + if (ma_dr_mp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) { + ma_bool32 isXing = MA_FALSE; + ma_bool32 isInfo = MA_FALSE; + const ma_uint8* pTagData; + const ma_uint8* pTagDataBeg; + pTagDataBeg = pFirstFrameData + MA_DR_MP3_HDR_SIZE + (bs.pos/8); + pTagData = pTagDataBeg; + isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g'); + isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o'); + if (isXing || isInfo) { + ma_uint32 bytes = 0; + ma_uint32 flags = pTagData[7]; + pTagData += 8; + if (flags & 0x01) { + detectedMP3FrameCount = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3]; + pTagData += 4; + } + if (flags & 0x02) { + bytes = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3]; + (void)bytes; + pTagData += 4; + } + if (flags & 0x04) { + pTagData += 100; + } + if (flags & 0x08) { + pTagData += 4; + } + if (pTagData[0]) { + pTagData += 21; + if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) { + int delayInPCMFrames; + int paddingInPCMFrames; + delayInPCMFrames = (( (ma_uint32)pTagData[0] << 4) | ((ma_uint32)pTagData[1] >> 4)) + (528 + 1); + paddingInPCMFrames = ((((ma_uint32)pTagData[1] & 0xF) << 8) | ((ma_uint32)pTagData[2] )) - (528 + 1); + if (paddingInPCMFrames < 0) { + paddingInPCMFrames = 0; + } + pMP3->delayInPCMFrames = (ma_uint32)delayInPCMFrames; + pMP3->paddingInPCMFrames = (ma_uint32)paddingInPCMFrames; + } + } + if (isXing) { + pMP3->isVBR = MA_TRUE; + } else if (isInfo) { + pMP3->isCBR = MA_TRUE; + } + if (onMeta != NULL) { + ma_dr_mp3_metadata_type metadataType = isXing ? MA_DR_MP3_METADATA_TYPE_XING : MA_DR_MP3_METADATA_TYPE_VBRI; + size_t tagDataSize; + tagDataSize = (size_t)firstFrameInfo.frame_bytes; + tagDataSize -= (size_t)(pTagDataBeg - pFirstFrameData); + ma_dr_mp3__on_meta(pMP3, metadataType, pTagDataBeg, tagDataSize); + } + pMP3->pcmFramesRemainingInMP3Frame = 0; + pMP3->streamStartOffset += (ma_uint32)(firstFrameInfo.frame_bytes); + pMP3->streamCursor = pMP3->streamStartOffset; + ma_dr_mp3dec_init(&pMP3->decoder); + } + } else { + } + } + #endif + } else { ma_dr_mp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks); return MA_FALSE; } + if (detectedMP3FrameCount != 0xFFFFFFFF) { + pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount; + } pMP3->channels = pMP3->mp3FrameChannels; pMP3->sampleRate = pMP3->mp3FrameSampleRate; return MA_TRUE; } -MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks) { if (pMP3 == NULL || onRead == NULL) { return MA_FALSE; } MA_DR_MP3_ZERO_OBJECT(pMP3); - return ma_dr_mp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks); + return ma_dr_mp3_init_internal(pMP3, onRead, onSeek, onTell, onMeta, pUserData, pUserData, pAllocationCallbacks); } static size_t ma_dr_mp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead) { @@ -91869,29 +94984,39 @@ static size_t ma_dr_mp3__on_read_memory(void* pUserData, void* pBufferOut, size_ static ma_bool32 ma_dr_mp3__on_seek_memory(void* pUserData, int byteOffset, ma_dr_mp3_seek_origin origin) { ma_dr_mp3* pMP3 = (ma_dr_mp3*)pUserData; + ma_int64 newCursor; MA_DR_MP3_ASSERT(pMP3 != NULL); - if (origin == ma_dr_mp3_seek_origin_current) { - if (byteOffset > 0) { - if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) { - byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos); - } - } else { - if (pMP3->memory.currentReadPos < (size_t)-byteOffset) { - byteOffset = -(int)pMP3->memory.currentReadPos; - } - } - pMP3->memory.currentReadPos += byteOffset; + if (origin == MA_DR_MP3_SEEK_SET) { + newCursor = 0; + } else if (origin == MA_DR_MP3_SEEK_CUR) { + newCursor = (ma_int64)pMP3->memory.currentReadPos; + } else if (origin == MA_DR_MP3_SEEK_END) { + newCursor = (ma_int64)pMP3->memory.dataSize; } else { - if ((ma_uint32)byteOffset <= pMP3->memory.dataSize) { - pMP3->memory.currentReadPos = byteOffset; - } else { - pMP3->memory.currentReadPos = pMP3->memory.dataSize; - } + MA_DR_MP3_ASSERT(!"Invalid seek origin"); + return MA_FALSE; } + newCursor += byteOffset; + if (newCursor < 0) { + return MA_FALSE; + } + if ((size_t)newCursor > pMP3->memory.dataSize) { + return MA_FALSE; + } + pMP3->memory.currentReadPos = (size_t)newCursor; return MA_TRUE; } -MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks) +static ma_bool32 ma_dr_mp3__on_tell_memory(void* pUserData, ma_int64* pCursor) { + ma_dr_mp3* pMP3 = (ma_dr_mp3*)pUserData; + MA_DR_MP3_ASSERT(pMP3 != NULL); + MA_DR_MP3_ASSERT(pCursor != NULL); + *pCursor = (ma_int64)pMP3->memory.currentReadPos; + return MA_TRUE; +} +MA_API ma_bool32 ma_dr_mp3_init_memory_with_metadata(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks) +{ + ma_bool32 result; if (pMP3 == NULL) { return MA_FALSE; } @@ -91902,7 +95027,21 @@ MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_ pMP3->memory.pData = (const ma_uint8*)pData; pMP3->memory.dataSize = dataSize; pMP3->memory.currentReadPos = 0; - return ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_memory, ma_dr_mp3__on_seek_memory, pMP3, pAllocationCallbacks); + result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_memory, ma_dr_mp3__on_seek_memory, ma_dr_mp3__on_tell_memory, onMeta, pMP3, pUserDataMeta, pAllocationCallbacks); + if (result == MA_FALSE) { + return MA_FALSE; + } + if (pMP3->streamLength <= (ma_uint64)MA_SIZE_MAX) { + pMP3->memory.dataSize = (size_t)pMP3->streamLength; + } + if (pMP3->streamStartOffset > (ma_uint64)MA_SIZE_MAX) { + return MA_FALSE; + } + return MA_TRUE; +} +MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks) +{ + return ma_dr_mp3_init_memory_with_metadata(pMP3, pData, dataSize, NULL, NULL, pAllocationCallbacks); } #ifndef MA_DR_MP3_NO_STDIO #include @@ -91913,36 +95052,76 @@ static size_t ma_dr_mp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t } static ma_bool32 ma_dr_mp3__on_seek_stdio(void* pUserData, int offset, ma_dr_mp3_seek_origin origin) { - return fseek((FILE*)pUserData, offset, (origin == ma_dr_mp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0; + int whence = SEEK_SET; + if (origin == MA_DR_MP3_SEEK_CUR) { + whence = SEEK_CUR; + } else if (origin == MA_DR_MP3_SEEK_END) { + whence = SEEK_END; + } + return fseek((FILE*)pUserData, offset, whence) == 0; } -MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks) +static ma_bool32 ma_dr_mp3__on_tell_stdio(void* pUserData, ma_int64* pCursor) +{ + FILE* pFileStdio = (FILE*)pUserData; + ma_int64 result; + MA_DR_MP3_ASSERT(pFileStdio != NULL); + MA_DR_MP3_ASSERT(pCursor != NULL); +#if defined(_WIN32) && !defined(NXDK) + #if defined(_MSC_VER) && _MSC_VER > 1200 + result = _ftelli64(pFileStdio); + #else + result = ftell(pFileStdio); + #endif +#else + result = ftell(pFileStdio); +#endif + *pCursor = result; + return MA_TRUE; +} +MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata(ma_dr_mp3* pMP3, const char* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks) { ma_bool32 result; FILE* pFile; + if (pMP3 == NULL) { + return MA_FALSE; + } + MA_DR_MP3_ZERO_OBJECT(pMP3); if (ma_fopen(&pFile, pFilePath, "rb") != MA_SUCCESS) { return MA_FALSE; } - result = ma_dr_mp3_init(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks); + result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, ma_dr_mp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks); if (result != MA_TRUE) { fclose(pFile); return result; } return MA_TRUE; } -MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks) { ma_bool32 result; FILE* pFile; + if (pMP3 == NULL) { + return MA_FALSE; + } + MA_DR_MP3_ZERO_OBJECT(pMP3); if (ma_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != MA_SUCCESS) { return MA_FALSE; } - result = ma_dr_mp3_init(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks); + result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, ma_dr_mp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks); if (result != MA_TRUE) { fclose(pFile); return result; } return MA_TRUE; } +MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks) +{ + return ma_dr_mp3_init_file_with_metadata(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks); +} +MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks) +{ + return ma_dr_mp3_init_file_with_metadata_w(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks); +} #endif MA_API void ma_dr_mp3_uninit(ma_dr_mp3* pMP3) { @@ -92012,17 +95191,38 @@ static ma_uint64 ma_dr_mp3_read_pcm_frames_raw(ma_dr_mp3* pMP3, ma_uint64 frames MA_DR_MP3_ASSERT(pMP3 != NULL); MA_DR_MP3_ASSERT(pMP3->onRead != NULL); while (framesToRead > 0) { - ma_uint32 framesToConsume = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead); + ma_uint32 framesToConsume; + if (pMP3->currentPCMFrame < pMP3->delayInPCMFrames) { + ma_uint32 framesToSkip = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, pMP3->delayInPCMFrames - pMP3->currentPCMFrame); + pMP3->currentPCMFrame += framesToSkip; + pMP3->pcmFramesConsumedInMP3Frame += framesToSkip; + pMP3->pcmFramesRemainingInMP3Frame -= framesToSkip; + } + framesToConsume = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead); + if (pMP3->totalPCMFrameCount != MA_UINT64_MAX && pMP3->totalPCMFrameCount > pMP3->paddingInPCMFrames) { + if (pMP3->currentPCMFrame < (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames)) { + ma_uint64 framesRemainigToPadding = (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames) - pMP3->currentPCMFrame; + if (framesToConsume > framesRemainigToPadding) { + framesToConsume = (ma_uint32)framesRemainigToPadding; + } + } else { + break; + } + } if (pBufferOut != NULL) { - #if defined(MA_DR_MP3_FLOAT_OUTPUT) - float* pFramesOutF32 = (float*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels); - float* pFramesInF32 = (float*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels); - MA_DR_MP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels); - #else - ma_int16* pFramesOutS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(ma_int16) * totalFramesRead * pMP3->channels); - ma_int16* pFramesInS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(ma_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels); - MA_DR_MP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(ma_int16) * framesToConsume * pMP3->channels); - #endif + #if defined(MA_DR_MP3_FLOAT_OUTPUT) + { + float* pFramesOutF32 = (float*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels); + float* pFramesInF32 = (float*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels); + MA_DR_MP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels); + } + #else + { + ma_int16* pFramesOutS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(ma_int16) * totalFramesRead * pMP3->channels); + ma_int16* pFramesInS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(ma_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels); + MA_DR_MP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(ma_int16) * framesToConsume * pMP3->channels); + } + #endif } pMP3->currentPCMFrame += framesToConsume; pMP3->pcmFramesConsumedInMP3Frame += framesToConsume; @@ -92032,6 +95232,9 @@ static ma_uint64 ma_dr_mp3_read_pcm_frames_raw(ma_dr_mp3* pMP3, ma_uint64 frames if (framesToRead == 0) { break; } + if (pMP3->totalPCMFrameCount != MA_UINT64_MAX && pMP3->totalPCMFrameCount > pMP3->paddingInPCMFrames && pMP3->currentPCMFrame >= (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames)) { + break; + } MA_DR_MP3_ASSERT(pMP3->pcmFramesRemainingInMP3Frame == 0); if (ma_dr_mp3_decode_next_frame(pMP3) == 0) { break; @@ -92111,7 +95314,7 @@ static ma_bool32 ma_dr_mp3_seek_to_start_of_stream(ma_dr_mp3* pMP3) { MA_DR_MP3_ASSERT(pMP3 != NULL); MA_DR_MP3_ASSERT(pMP3->onSeek != NULL); - if (!ma_dr_mp3__on_seek(pMP3, 0, ma_dr_mp3_seek_origin_start)) { + if (!ma_dr_mp3__on_seek_64(pMP3, pMP3->streamStartOffset, MA_DR_MP3_SEEK_SET)) { return MA_FALSE; } ma_dr_mp3_reset(pMP3); @@ -92177,7 +95380,7 @@ static ma_bool32 ma_dr_mp3_seek_to_pcm_frame__seek_table(ma_dr_mp3* pMP3, ma_uin seekPoint.mp3FramesToDiscard = 0; seekPoint.pcmFramesToDiscard = 0; } - if (!ma_dr_mp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, ma_dr_mp3_seek_origin_start)) { + if (!ma_dr_mp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, MA_DR_MP3_SEEK_SET)) { return MA_FALSE; } ma_dr_mp3_reset(pMP3); @@ -92188,7 +95391,7 @@ static ma_bool32 ma_dr_mp3_seek_to_pcm_frame__seek_table(ma_dr_mp3* pMP3, ma_uin if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) { pPCMFrames = (ma_dr_mp3d_sample_t*)pMP3->pcmFrames; } - pcmFramesRead = ma_dr_mp3_decode_next_frame_ex(pMP3, pPCMFrames); + pcmFramesRead = ma_dr_mp3_decode_next_frame_ex(pMP3, pPCMFrames, NULL, NULL); if (pcmFramesRead == 0) { return MA_FALSE; } @@ -92230,7 +95433,7 @@ MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint6 totalMP3FrameCount = 0; for (;;) { ma_uint32 pcmFramesInCurrentMP3Frame; - pcmFramesInCurrentMP3Frame = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL); + pcmFramesInCurrentMP3Frame = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL); if (pcmFramesInCurrentMP3Frame == 0) { break; } @@ -92254,10 +95457,26 @@ MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint6 MA_API ma_uint64 ma_dr_mp3_get_pcm_frame_count(ma_dr_mp3* pMP3) { ma_uint64 totalPCMFrameCount; - if (!ma_dr_mp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) { + if (pMP3 == NULL) { return 0; } - return totalPCMFrameCount; + if (pMP3->totalPCMFrameCount != MA_UINT64_MAX) { + totalPCMFrameCount = pMP3->totalPCMFrameCount; + if (totalPCMFrameCount >= pMP3->delayInPCMFrames) { + totalPCMFrameCount -= pMP3->delayInPCMFrames; + } else { + } + if (totalPCMFrameCount >= pMP3->paddingInPCMFrames) { + totalPCMFrameCount -= pMP3->paddingInPCMFrames; + } else { + } + return totalPCMFrameCount; + } else { + if (!ma_dr_mp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) { + return 0; + } + return totalPCMFrameCount; + } } MA_API ma_uint64 ma_dr_mp3_get_mp3_frame_count(ma_dr_mp3* pMP3) { @@ -92327,7 +95546,7 @@ MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSe MA_DR_MP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize); mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize; mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount; - pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL); + pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL); if (pcmFramesInCurrentMP3FrameIn == 0) { return MA_FALSE; } @@ -92351,7 +95570,7 @@ MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSe } mp3FrameInfo[MA_DR_MP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize; mp3FrameInfo[MA_DR_MP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount; - pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL); + pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL); if (pcmFramesInCurrentMP3FrameIn == 0) { pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos; pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame; @@ -92417,6 +95636,8 @@ static float* ma_dr_mp3__full_read_and_close_f32(ma_dr_mp3* pMP3, ma_dr_mp3_conf pNewFrames = (float*)ma_dr_mp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks); if (pNewFrames == NULL) { ma_dr_mp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks); + pFrames = NULL; + totalFramesRead = 0; break; } pFrames = pNewFrames; @@ -92468,6 +95689,8 @@ static ma_int16* ma_dr_mp3__full_read_and_close_s16(ma_dr_mp3* pMP3, ma_dr_mp3_c pNewFrames = (ma_int16*)ma_dr_mp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks); if (pNewFrames == NULL) { ma_dr_mp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks); + pFrames = NULL; + totalFramesRead = 0; break; } pFrames = pNewFrames; @@ -92489,18 +95712,18 @@ static ma_int16* ma_dr_mp3__full_read_and_close_s16(ma_dr_mp3* pMP3, ma_dr_mp3_c } return pFrames; } -MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_mp3 mp3; - if (!ma_dr_mp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_mp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) { return NULL; } return ma_dr_mp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount); } -MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks) { ma_dr_mp3 mp3; - if (!ma_dr_mp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) { + if (!ma_dr_mp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) { return NULL; } return ma_dr_mp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount); @@ -92602,7 +95825,7 @@ For more information, please refer to =============================================================================== ALTERNATIVE 2 - MIT No Attribution =============================================================================== -Copyright 2023 David Reid +Copyright 2025 David Reid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/vendor/miniaudio/synchronization.odin b/vendor/miniaudio/synchronization.odin index 012f52c2c..08182c32b 100644 --- a/vendor/miniaudio/synchronization.odin +++ b/vendor/miniaudio/synchronization.odin @@ -62,6 +62,11 @@ when !NO_THREADING { Signals the specified auto-reset event. */ event_signal :: proc(pEvent: ^event) -> result --- + + semaphore_init :: proc(initialValue: i32, pSemaphore: ^semaphore) -> result --- + semaphore_uninit :: proc(pSemaphore: ^semaphore) --- + semaphore_wait :: proc(pSemaphore: ^semaphore) -> result --- + semaphore_release :: proc(pSemaphore: ^semaphore) -> result --- } /* NO_THREADING */ } diff --git a/vendor/miniaudio/utilities.odin b/vendor/miniaudio/utilities.odin index 9285874b6..d59bb75a4 100644 --- a/vendor/miniaudio/utilities.odin +++ b/vendor/miniaudio/utilities.odin @@ -7,7 +7,7 @@ foreign import lib { LIB } @(default_calling_convention="c", link_prefix="ma_") foreign lib { /* - Calculates a buffer size in milliseconds from the specified number of frames and sample rate. + Calculates a buffer size in milliseconds (rounded up) from the specified number of frames and sample rate. */ calculate_buffer_size_in_milliseconds_from_frames :: proc(bufferSizeInFrames: u32, sampleRate: u32) -> u32 --- @@ -163,6 +163,8 @@ foreign lib { data_source_read_pcm_frames :: proc(pDataSource: ^data_source, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result --- /* Must support pFramesOut = NULL in which case a forward seek should be performed. */ data_source_seek_pcm_frames :: proc(pDataSource: ^data_source, frameCount: u64, pFramesSeeked: ^u64) -> result --- /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount); */ data_source_seek_to_pcm_frame :: proc(pDataSource: ^data_source, frameIndex: u64) -> result --- + data_source_seek_seconds :: proc(pDataSource: ^data_source, secondCount: f32, pSecondsSeeked: ^f32) -> result --- /* Can only seek forward. Abstraction to ma_data_source_seek_pcm_frames() */ + data_source_seek_to_seconds :: proc(pDataSource: ^data_source, seekPointInSeconds: f32) -> result --- /* Abstraction to ma_data_source_seek_to_pcm_frame() */ data_source_get_data_format :: proc(pDataSource: ^data_source, pFormat: ^format, pChannels: ^u32, pSampleRate: ^u32, pChannelMap: [^]channel, channelMapCap: c.size_t) -> result --- data_source_get_cursor_in_pcm_frames :: proc(pDataSource: ^data_source, pCursor: ^u64) -> result --- data_source_get_length_in_pcm_frames :: proc(pDataSource: ^data_source, pLength: ^u64) -> result --- /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */ diff --git a/vendor/nanovg/gl/gl.odin b/vendor/nanovg/gl/gl.odin index 5af7ed4bc..e43f07354 100644 --- a/vendor/nanovg/gl/gl.odin +++ b/vendor/nanovg/gl/gl.odin @@ -1,3 +1,4 @@ +// An Odin-native source port of [[ nanovg ; https://github.com/memononen/nanovg ]]'s GL backend. #+build windows, linux, darwin package nanovg_gl diff --git a/vendor/nanovg/nanovg.odin b/vendor/nanovg/nanovg.odin index 540ca47cf..70ba90681 100644 --- a/vendor/nanovg/nanovg.odin +++ b/vendor/nanovg/nanovg.odin @@ -1,3 +1,4 @@ +// An Odin-native source port of [[ nanovg ; https://github.com/memononen/nanovg ]]. #+build windows, linux, darwin package nanovg diff --git a/vendor/portmidi/doc.odin b/vendor/portmidi/doc.odin index 6a3d5331a..3e6b0b3b2 100644 --- a/vendor/portmidi/doc.odin +++ b/vendor/portmidi/doc.odin @@ -1,3 +1,4 @@ +// Bindings for [[ PortMidi ; http://sourceforge.net/projects/portmedia ]] Portable Real-Time MIDI Library. package portmidi /* diff --git a/vendor/portmidi/portmidi.odin b/vendor/portmidi/portmidi.odin index 58d7c2ec2..1f2aca286 100644 --- a/vendor/portmidi/portmidi.odin +++ b/vendor/portmidi/portmidi.odin @@ -119,8 +119,8 @@ DeviceInfo :: struct { structVersion: c.int, /**< this internal structure version */ interf: cstring, /**< underlying MIDI API, e.g. MMSystem or DirectX */ name: cstring, /**< device name, e.g. USB MidiSport 1x1 */ - input: b32, /**< true iff input is available */ - output: b32, /**< true iff output is available */ + input: b32, /**< true if and only if (⟺) input is available */ + output: b32, /**< true if and only if (⟺) output is available */ opened: b32, /**< used by generic PortMidi code to do error checking on arguments */ } diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin index 02bb6deea..b051f1885 100644 --- a/vendor/raylib/raylib.odin +++ b/vendor/raylib/raylib.odin @@ -1,5 +1,5 @@ /* -Package vendor:raylib implements bindings for version 5.5 of the raylib library (https://www.raylib.com/) +Bindings for [[ raylib v5.5 ; https://www.raylib.com ]]. ********************************************************************************************* * @@ -91,11 +91,9 @@ import "core:c" import "core:fmt" import "core:mem" -import "core:math/linalg" -_ :: linalg - MAX_TEXTFORMAT_BUFFERS :: #config(RAYLIB_MAX_TEXTFORMAT_BUFFERS, 4) MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024) +MAX_MATERIAL_MAPS :: #config(RAYLIB_MAX_MATERIAL_MAPS, 12) #assert(size_of(rune) == size_of(c.int)) @@ -127,7 +125,7 @@ when ODIN_OS == .Windows { "system:Cocoa.framework", "system:OpenGL.framework", "system:IOKit.framework", - } + } } else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { foreign import lib { RAYLIB_WASM_LIB, @@ -141,7 +139,7 @@ VERSION_MINOR :: 5 VERSION_PATCH :: 0 VERSION :: "5.5" -PI :: 3.14159265358979323846 +PI :: 3.14159265358979323846 DEG2RAD :: PI/180.0 RAD2DEG :: 180.0/PI @@ -234,7 +232,7 @@ RenderTexture :: struct { id: c.uint, // OpenGL framebuffer object id texture: Texture, // Color buffer attachment texture depth: Texture, // Depth buffer attachment texture -} +} // RenderTexture2D type, same as RenderTexture RenderTexture2D :: RenderTexture @@ -256,7 +254,7 @@ GlyphInfo :: struct { offsetY: c.int, // Character offset Y when drawing advanceX: c.int, // Character advance position X image: Image, // Character image data -} +} // Font type, includes texture and charSet array data Font :: struct { @@ -274,7 +272,7 @@ Camera3D :: struct { target: Vector3, // Camera target it looks-at up: Vector3, // Camera up vector (rotation over its axis) fovy: f32, // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic - projection: CameraProjection, // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC + projection: CameraProjection, // Camera projection: `.PERSPECTIVE` or `.ORTHOGRAPHIC` } Camera :: Camera3D // Camera type fallback, defaults to Camera3D @@ -850,7 +848,7 @@ Gesture :: enum c.uint { } Gestures :: distinct bit_set[Gesture; c.uint] -// Camera speed values +// Camera speed values CAMERA_MOVE_SPEED :: 5.4 CAMERA_ROTATION_SPEED :: 0.03 CAMERA_PAN_SPEED :: 0.2 @@ -1028,7 +1026,7 @@ foreign lib { GetScreenToWorld2D :: proc(position: Vector2, camera: Camera2D) -> Vector2 --- // Get the world space position for a 2d camera screen space position GetCameraMatrix :: proc(camera: Camera) -> Matrix --- // Get camera transform matrix (view matrix) GetCameraMatrix2D :: proc(camera: Camera2D) -> Matrix --- // Get camera 2d transform matrix - + // Timing-related functions SetTargetFPS :: proc(fps: c.int) --- // Set target FPS (maximum) @@ -1109,7 +1107,7 @@ foreign lib { ComputeMD5 :: proc (data: rawptr, dataSize: c.int) -> [^]c.uint --- // Compute MD5 hash code, returns static int[4] (16 bytes) ComputeSHA1 :: proc(data: rawptr, dataSize: c.int) -> [^]c.uint --- // Compute SHA1 hash code, returns static int[5] (20 bytes) - + // Automation events functionality LoadAutomationEventList :: proc(fileName: cstring) -> AutomationEventList --- // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS @@ -1150,14 +1148,14 @@ foreign lib { SetGamepadMappings :: proc(mappings: cstring) -> c.int --- // Set internal gamepad mappings (SDL_GameControllerDB) SetGamepadVibration :: proc(gamepad: c.int, leftMotor: f32, rightMotor: f32, duration: f32) --- // Set gamepad vibration for both motors (duration in seconds) - + // Input-related functions: mouse IsMouseButtonPressed :: proc(button: MouseButton) -> bool --- // Detect if a mouse button has been pressed once IsMouseButtonDown :: proc(button: MouseButton) -> bool --- // Detect if a mouse button is being pressed IsMouseButtonReleased :: proc(button: MouseButton) -> bool --- // Detect if a mouse button has been released once IsMouseButtonUp :: proc(button: MouseButton) -> bool --- - + GetMouseX :: proc() -> c.int --- // Returns mouse position X GetMouseY :: proc() -> c.int --- // Returns mouse position Y GetMousePosition :: proc() -> Vector2 --- // Returns mouse position XY @@ -1225,7 +1223,7 @@ foreign lib { GetShapesTexture :: proc() -> Texture2D --- // Get texture that is used for shapes drawing GetShapesTextureRectangle :: proc() -> Rectangle --- // Get texture source rectangle that is used for shapes drawing - + // Basic shapes drawing functions DrawPixel :: proc(posX, posY: c.int, color: Color) --- // Draw a pixel using geometry [Can be slow, use with care] @@ -1421,7 +1419,7 @@ foreign lib { DrawTextureNPatch :: proc(texture: Texture2D, nPatchInfo: NPatchInfo, dest: Rectangle, origin: Vector2, rotation: f32, tint: Color) --- // Draws a texture (or part of it) that stretches or shrinks nicely // Color/pixel related functions - + @(deprecated="Prefer col1 == col2") ColorIsEqual :: proc(col1, col2: Color) --- // Check if two colors are equal Fade :: proc(color: Color, alpha: f32) -> Color --- // Get color with alpha applied, alpha goes from 0.0f to 1.0f @@ -1729,15 +1727,15 @@ IsGestureDetected :: proc "c" (gesture: Gesture) -> bool { TextFormat :: proc(text: cstring, args: ..any) -> cstring { @static buffers: [MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH]byte @static index: u32 - + buffer := buffers[index][:] mem.zero_slice(buffer) - + index = (index+1)%MAX_TEXTFORMAT_BUFFERS - + str := fmt.bprintf(buffer[:len(buffer)-1], string(text), ..args) buffer[len(str)] = 0 - + return cstring(raw_data(buffer)) } @@ -1784,7 +1782,7 @@ MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case .Free: MemFree(old_memory) return nil, nil - + case .Resize, .Resize_Non_Zeroed: ptr := MemRealloc(old_memory, c.uint(size)) if ptr == nil { @@ -1793,10 +1791,10 @@ MemAllocatorProc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, } data = mem.byte_slice(ptr, size) return - + case .Free_All, .Query_Features, .Query_Info: return nil, .Mode_Not_Implemented - } + } return nil, .Mode_Not_Implemented } diff --git a/vendor/raylib/rlgl/rlgl.odin b/vendor/raylib/rlgl/rlgl.odin index 6ac19695d..a08479680 100644 --- a/vendor/raylib/rlgl/rlgl.odin +++ b/vendor/raylib/rlgl/rlgl.odin @@ -375,17 +375,20 @@ foreign lib { //------------------------------------------------------------------------------------ // Functions Declaration - Matrix operations //------------------------------------------------------------------------------------ - MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed - PushMatrix :: proc() --- // Push the current matrix to stack - PopMatrix :: proc() --- // Pop lattest inserted matrix from stack - LoadIdentity :: proc() --- // Reset current matrix to identity matrix - Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix - Rotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix - Scalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix - MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix - Frustum :: proc(left, right, bottom, top, znear, zfar: f64) --- - Ortho :: proc(left, right, bottom, top, znear, zfar: f64) --- - Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area + MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed + PushMatrix :: proc() --- // Push the current matrix to stack + PopMatrix :: proc() --- // Pop lattest inserted matrix from stack + LoadIdentity :: proc() --- // Reset current matrix to identity matrix + Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix + Rotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix + Scalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix + MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix + Frustum :: proc(left, right, bottom, top, znear, zfar: f64) --- + Ortho :: proc(left, right, bottom, top, znear, zfar: f64) --- + Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area + SetClipPlanes :: proc(near, far: f64) --- // Set clip planes distances + GetCullDistanceNear :: proc() -> f64 --- // Get cull plane distance near + GetCullDistanceFar :: proc() -> f64 --- // Get cull plane distance far //------------------------------------------------------------------------------------ // Functions Declaration - Vertex level operations @@ -428,17 +431,19 @@ foreign lib { EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap DisableTextureCubemap :: proc() --- // Disable texture cubemap TextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap) - CubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap) + CubemapParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap) // Shader state EnableShader :: proc(id: c.uint) --- // Enable shader program DisableShader :: proc() --- // Disable shader program // Framebuffer state - EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo) - DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer - ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers - BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer + EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo) + DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer + GetActiveFramebuffer :: proc() -> c.uint --- // Get the currently active render texture (fbo), 0 for default framebuffer + ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers + BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight: c.int, dstX, dstY, dstWidth, dstHeight: c.int, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer + BindFramebuffer :: proc(target, framebuffer: c.uint) --- // Bind framebuffer (FBO) // General render state EnableColorBlend :: proc() --- // Enable color blending @@ -449,12 +454,13 @@ foreign lib { DisableDepthMask :: proc() --- // Disable depth write EnableBackfaceCulling :: proc() --- // Enable backface culling DisableBackfaceCulling :: proc() --- // Disable backface culling + ColorMask :: proc(r, g, b, a: bool) --- // Color mask control SetCullFace :: proc(mode: CullMode) --- // Set face culling mode EnableScissorTest :: proc() --- // Enable scissor test DisableScissorTest :: proc() --- // Disable scissor test Scissor :: proc(x, y, width, height: c.int) --- // Scissor test EnableWireMode :: proc() --- // Enable wire mode - EnablePointMode :: proc() --- // Enable point mode + EnablePointMode :: proc() --- // Enable point mode DisableWireMode :: proc() --- // Disable wire and point modes SetLineWidth :: proc(width: f32) --- // Set the line drawing width GetLineWidth :: proc() -> f32 --- // Get the line drawing width @@ -500,7 +506,7 @@ foreign lib { DrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset) SetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal) DrawRenderBatchActive :: proc() --- // Update and draw internal render batch - CheckRenderBatchLimit :: proc(vCount: c.int) -> c.int --- // Check internal buffer overflow for a given number of vertex + CheckRenderBatchLimit :: proc(vCount: c.int) -> bool --- // Check internal buffer overflow for a given number of vertex SetTexture :: proc(id: c.uint) --- // Set current texture for render batch and check buffers limits @@ -525,7 +531,7 @@ foreign lib { // Textures management LoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU LoadTextureDepth :: proc(width, height: c.int, useRenderBuffer: bool) -> c.uint --- // Load depth texture/renderbuffer (to be attached to fbo) - LoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int) -> c.uint --- // Load texture cubemap + LoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture cubemap UpdateTexture :: proc(id: c.uint, offsetX, offsetY: c.int, width, height: c.int, format: c.int, data: rawptr) --- // Update GPU texture with new data GetGlTextureFormats :: proc(format: c.int, glInternalFormat, glFormat, glType: ^c.uint) --- // Get OpenGL internal formats GetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format @@ -535,7 +541,7 @@ foreign lib { ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer) // Framebuffer management (fbo) - LoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer + LoadFramebuffer :: proc() -> c.uint --- // Load an empty framebuffer FramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU @@ -549,6 +555,7 @@ foreign lib { GetLocationAttrib :: proc(shaderId: c.uint, attribName: cstring) -> c.int --- // Get shader location attribute SetUniform :: proc(locIndex: c.int, value: rawptr, uniformType: c.int, count: c.int) --- // Set shader value uniform SetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix + SetUniformMatrices :: proc(locIndex: c.int, matrices: [^]Matrix, count: c.int) --- // Set shader value matrices SetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler SetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations) diff --git a/vendor/sdl2/image/sdl_image.odin b/vendor/sdl2/image/sdl_image.odin index 204ec9a0d..ade4c5aae 100644 --- a/vendor/sdl2/image/sdl_image.odin +++ b/vendor/sdl2/image/sdl_image.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL2 Image; https://wiki.libsdl.org/SDL2_image/FrontPage ]]. package sdl2_image import "core:c" diff --git a/vendor/sdl2/mixer/sdl_mixer.odin b/vendor/sdl2/mixer/sdl_mixer.odin index b0c16871d..a9978fc3b 100644 --- a/vendor/sdl2/mixer/sdl_mixer.odin +++ b/vendor/sdl2/mixer/sdl_mixer.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL2 Mixer ; https://wiki.libsdl.org/SDL2_mixer/FrontPage ]]. package sdl2_mixer import "core:c" diff --git a/vendor/sdl2/net/sdl_net.odin b/vendor/sdl2/net/sdl_net.odin index 579f245e5..9cd63d55a 100644 --- a/vendor/sdl2/net/sdl_net.odin +++ b/vendor/sdl2/net/sdl_net.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL2 Net ; https://wiki.libsdl.org/SDL2_net/FrontPage ]]. package sdl2_net import "core:c" diff --git a/vendor/sdl2/sdl2.odin b/vendor/sdl2/sdl2.odin index 5bc52b70e..ffe70c330 100644 --- a/vendor/sdl2/sdl2.odin +++ b/vendor/sdl2/sdl2.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL2 ; https://wiki.libsdl.org/SDL2/FrontPage ]]. package sdl2 /* diff --git a/vendor/sdl2/sdl_audio.odin b/vendor/sdl2/sdl_audio.odin index 6ff9e93f4..296a773c4 100644 --- a/vendor/sdl2/sdl_audio.odin +++ b/vendor/sdl2/sdl_audio.odin @@ -74,12 +74,14 @@ when ODIN_ENDIAN == .Little { AUDIO_F32SYS :: AUDIO_F32MSB } - -AUDIO_ALLOW_FREQUENCY_CHANGE :: 0x00000001 -AUDIO_ALLOW_FORMAT_CHANGE :: 0x00000002 -AUDIO_ALLOW_CHANNELS_CHANGE :: 0x00000004 -AUDIO_ALLOW_SAMPLES_CHANGE :: 0x00000008 -AUDIO_ALLOW_ANY_CHANGE :: AUDIO_ALLOW_FREQUENCY_CHANGE|AUDIO_ALLOW_FORMAT_CHANGE|AUDIO_ALLOW_CHANNELS_CHANGE|AUDIO_ALLOW_SAMPLES_CHANGE +AudioAllowChangeFlags :: distinct bit_set[AudioAllowChangeFlag; c.int] +AudioAllowChangeFlag :: enum c.int { + FREQUENCY = 0, + FORMAT = 1, + CHANNELS = 2, + SAMPLES = 3, +} +AUDIO_ALLOW_ANY_CHANGE :: AudioAllowChangeFlags{.FREQUENCY, .FORMAT, .CHANNELS, .SAMPLES} AudioCallback :: proc "c" (userdata: rawptr, stream: [^]u8, len: c.int) @@ -151,7 +153,7 @@ foreign lib { iscapture: bool, desired: ^AudioSpec, obtained: ^AudioSpec, - allowed_changes: bool) -> AudioDeviceID --- + allowed_changes: AudioAllowChangeFlags) -> AudioDeviceID --- } diff --git a/vendor/sdl2/sdl_messagebox.odin b/vendor/sdl2/sdl_messagebox.odin index edd8422e0..5211affd8 100644 --- a/vendor/sdl2/sdl_messagebox.odin +++ b/vendor/sdl2/sdl_messagebox.odin @@ -66,7 +66,7 @@ MessageBoxData :: struct { message: cstring, /**< UTF-8 message text */ numbuttons: c.int, - buttons: ^MessageBoxButtonData, + buttons: [^]MessageBoxButtonData, colorScheme: ^MessageBoxColorScheme, /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */ } diff --git a/vendor/sdl2/sdl_rwops.odin b/vendor/sdl2/sdl_rwops.odin index ca7fa0bea..d3986f4b3 100644 --- a/vendor/sdl2/sdl_rwops.odin +++ b/vendor/sdl2/sdl_rwops.odin @@ -87,7 +87,7 @@ foreign lib { RWseek :: proc(ctx: ^RWops, offset: i64, whence: c.int) -> i64 --- RWtell :: proc(ctx: ^RWops) -> i64 --- RWread :: proc(ctx: ^RWops, ptr: rawptr, size: c.size_t, maxnum: c.size_t) -> c.size_t --- - RWwrite :: proc(ctx: ^RWops, size: c.size_t, num: c.size_t) -> c.size_t --- + RWwrite :: proc(ctx: ^RWops, ptr: rawptr, size: c.size_t, num: c.size_t) -> c.size_t --- RWclose :: proc(ctx: ^RWops) -> c.int --- LoadFile_RW :: proc(src: ^RWops, datasize: ^c.size_t, freesrc: bool) -> rawptr --- diff --git a/vendor/sdl2/sdl_video.odin b/vendor/sdl2/sdl_video.odin index 809735414..8a98d79dc 100644 --- a/vendor/sdl2/sdl_video.odin +++ b/vendor/sdl2/sdl_video.odin @@ -237,7 +237,7 @@ foreign lib { CreateWindowFrom :: proc(data: rawptr) -> ^Window --- GetWindowID :: proc(window: ^Window) -> u32 --- GetWindowFromID :: proc(id: u32) -> ^Window --- - GetWindowFlags :: proc(window: ^Window) -> u32 --- + GetWindowFlags :: proc(window: ^Window) -> WindowFlags --- SetWindowTitle :: proc(window: ^Window, title: cstring) --- GetWindowTitle :: proc(window: ^Window) -> cstring --- SetWindowIcon :: proc(window: ^Window, icon: ^Surface) --- diff --git a/vendor/sdl2/ttf/sdl_ttf.odin b/vendor/sdl2/ttf/sdl_ttf.odin index ca9beded0..5c44d8784 100644 --- a/vendor/sdl2/ttf/sdl_ttf.odin +++ b/vendor/sdl2/ttf/sdl_ttf.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL2 TTF ; https://wiki.libsdl.org/SDL2_ttf/FrontPage ]]. package sdl2_ttf import "core:c" diff --git a/vendor/sdl3/LICENSE.txt b/vendor/sdl3/LICENSE.txt index 23abb73f2..e9adee448 100644 --- a/vendor/sdl3/LICENSE.txt +++ b/vendor/sdl3/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 1997-2025 Sam Lantinga +Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/SDL3.dll b/vendor/sdl3/SDL3.dll index 3bbfd4be8..080cd755d 100644 Binary files a/vendor/sdl3/SDL3.dll and b/vendor/sdl3/SDL3.dll differ diff --git a/vendor/sdl3/SDL3.lib b/vendor/sdl3/SDL3.lib index f736458fb..ef10d51b9 100644 Binary files a/vendor/sdl3/SDL3.lib and b/vendor/sdl3/SDL3.lib differ diff --git a/vendor/sdl3/gamecontrollerdb.txt b/vendor/sdl3/gamecontrollerdb.txt index c57935b14..56e8c75b7 100644 --- a/vendor/sdl3/gamecontrollerdb.txt +++ b/vendor/sdl3/gamecontrollerdb.txt @@ -20,7 +20,7 @@ 03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -05000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows, +03000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows, 03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, @@ -154,6 +154,7 @@ 03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, 030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, @@ -182,6 +183,9 @@ 030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, 03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, 03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000095090000010000000000000000,Elecom JC-U609,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, +0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, +03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows, 030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, 03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, 030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, @@ -193,6 +197,7 @@ 030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows, 03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000062000001801000000000000,EMS TrioLinker Plus II,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Windows, 03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, 03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, @@ -332,6 +337,7 @@ 03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, 03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows, 03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, 03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows, 03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, 03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -387,7 +393,7 @@ 03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, -03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008031000000000000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, 03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, @@ -414,7 +420,7 @@ 03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, 0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, +03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, 03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, 03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, 030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, @@ -446,7 +452,6 @@ 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, 03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, 03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, -030000006f0e00001311000000000000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Windows, 030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, @@ -464,8 +469,10 @@ 030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, 03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, 03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows, +030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows, 030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows, 030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows, 03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows, @@ -481,6 +488,7 @@ 030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, 03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, 03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -576,8 +584,10 @@ 030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, 030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, 030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, +030000009b2800003c00000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, 030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, 030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, +030000009b2800006400000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, 030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, 030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows, 030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, @@ -610,6 +620,7 @@ 03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000632500007805000000000000,Retro Fighters Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, 03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, 03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, @@ -627,6 +638,7 @@ 030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000830500007030000000000000,Rockfire Space Ranger,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b9,righttrigger:b8,start:b2,x:b3,y:b4,platform:Windows, 03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, 03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, 03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, @@ -637,6 +649,7 @@ 030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows, 030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001311000000000000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows, 03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000a306000023f6000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, @@ -665,7 +678,7 @@ 03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, 03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, -03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, 0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, 03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, @@ -682,6 +695,7 @@ 03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, 03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, 03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows, 030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, 03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -756,8 +770,8 @@ 03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows, -03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001a18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001b18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, 0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, @@ -967,6 +981,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, 03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X, 03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, @@ -987,18 +1002,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, 03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000853200008906000000010000,Nacon Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X, 030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X, 050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X, +030000007e0500007320000001010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Mac OS X, 030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X, 030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X, 03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, 030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X, -03000000790000001c18000000010000,PB Tails Choc,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X, 030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, @@ -1032,6 +1050,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X, 03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -1070,6 +1089,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X, 03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X, +03000000790000001c18000000010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, 03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X, @@ -1089,6 +1109,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, 050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, 030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -1244,9 +1265,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000300e000011010000,Brook Audio Fighting Board PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000310e000011010000,Brook Audio Fighting Board PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000d81d00000b00000010010000,Buffalo BSGP1601,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Linux, 03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux, 030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, @@ -1264,7 +1288,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1276,15 +1300,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000f0250000c283000010010000,Gioteck VX2 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux, 190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux, -190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,y:b3,platform:Linux, +190000004b4800000011000000010000,GO-Super Gamepad,a:b0,b:b1,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b3,y:b2,platform:Linux, 03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, @@ -1380,6 +1406,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000380700008031000011010000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008081000011010000,Mad Catz FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1419,6 +1447,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000dd02000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea0200000f050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1426,7 +1455,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000016050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000017050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b000001050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -1441,10 +1472,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux, -030000006f0e00001311000011010000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Linux, 030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000853200000503000000010000,Nacon MG-X Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1455,6 +1486,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, +030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux, 060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, 060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, @@ -1467,13 +1499,16 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux, 05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +050000005a1d00000218000003000000,Nokia GC 5000,a:b9,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux, -030000007e0500001920000011810000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, +030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux, +030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux, 050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux, -050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, -030000007e0500001720000011810000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux, +030000007e0500001e20000011810000,NSO Sega Genesis Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,platform:Linux, +030000007e0500001720000011810000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, 050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux, -050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +050000007e0500001720000001800000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, 03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, 05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, @@ -1489,7 +1524,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -1497,14 +1532,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, 03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d62000000540000001010000,PowerA Advantage Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000540000001010000,PowerA Advantage Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1519,8 +1554,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d62000000b20000001010000,PowerA Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, @@ -1577,7 +1613,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0300132d9b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux, +030000009b2800006400000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux, 030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, +030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, 03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -1611,6 +1650,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001311000011010000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Linux, 03000000a306000023f6000011010000,Saitek Cyborg PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux, 03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux, @@ -1711,6 +1751,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, 03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +03000000790000001a18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000790000001b18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, 05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, @@ -1738,6 +1780,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1752,6 +1795,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000011050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000014050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1761,13 +1806,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000017050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000120b000014050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000130b000017050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, -060000005e040000120b00000d050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, @@ -1789,7 +1833,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, 34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, -38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android, +38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android, 38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, @@ -1903,6 +1947,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, 38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39373064396565646338333134303131,Joy-Con (R),a:b1,b:b2,back:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,platform:Android, 4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, 39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, 63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, @@ -1910,7 +1955,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -39653365373864633935383236363438,Logitech G Butt,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, @@ -1936,6 +1981,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, 050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, +31316661666466633938376335383661,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,start:b6,x:b3,y:b2,platform:Android, 34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, 36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, @@ -1999,6 +2045,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, 526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64633735616665613536653363336132,Retroid Pocket,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b19,paddle2:b20,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, 38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b6,platform:Android, 37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, @@ -2059,8 +2106,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, 35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, -36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65316262316265373335666131623538,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -2081,17 +2129,22 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, 05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +05000000ac05000004000000a8986d04,8BitDo Micro gamepad,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,platform:iOS, +05000000ac05000004000000fd216d04,8BitDo Pro 2,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,platform:iOS, +05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,platform:iOS, +05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,platform:iOS, 050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, 4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, 050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, 050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS, -050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, 050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, -050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS, +050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, +050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, 050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, -050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,platform:iOS, 050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, @@ -2103,9 +2156,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, -050000005e040000050b0000df070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000050b0000ff070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, -050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, 050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, -050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, \ No newline at end of file +050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, \ No newline at end of file diff --git a/vendor/sdl3/image/LICENSE.libpng.txt b/vendor/sdl3/image/LICENSE.libpng.txt new file mode 100644 index 000000000..ea6df986c --- /dev/null +++ b/vendor/sdl3/image/LICENSE.libpng.txt @@ -0,0 +1,134 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= + +PNG Reference Library License version 2 +--------------------------------------- + + * Copyright (c) 1995-2025 The PNG Reference Library Authors. + * Copyright (c) 2018-2025 Cosmin Truta. + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * Copyright (c) 1996-1997 Andreas Dilger. + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +The software is supplied "as is", without warranty of any kind, +express or implied, including, without limitation, the warranties +of merchantability, fitness for a particular purpose, title, and +non-infringement. In no event shall the Copyright owners, or +anyone distributing the software, be liable for any damages or +other liability, whether in contract, tort or otherwise, arising +from, out of, or in connection with the software, or the use or +other dealings in the software, even if advised of the possibility +of such damage. + +Permission is hereby granted to use, copy, modify, and distribute +this software, or portions hereof, for any purpose, without fee, +subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you + use this software in a product, an acknowledgment in the product + documentation would be appreciated, but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + + +PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) +----------------------------------------------------------------------- + +libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are +derived from libpng-1.0.6, and are distributed according to the same +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of + the library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is + with the user. + +Some files in the "contrib" directory and some configure-generated +files that are distributed with libpng have other copyright owners, and +are released under other open source licenses. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +libpng-0.96, and are distributed according to the same disclaimer and +license as libpng-0.96, with the following individuals added to the +list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +Some files in the "scripts" directory have other copyright owners, +but are released under this license. + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing +Authors and Group 42, Inc. disclaim all warranties, expressed or +implied, including, without limitation, the warranties of +merchantability and of fitness for any purpose. The Contributing +Authors and Group 42, Inc. assume no liability for direct, indirect, +incidental, special, exemplary, or consequential damages, which may +result from the use of the PNG Reference Library, even if advised of +the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + + 1. The origin of this source code must not be misrepresented. + + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, +without fee, and encourage the use of this source code as a component +to supporting the PNG file format in commercial products. If you use +this source code in a product, acknowledgment is not required but would +be appreciated. diff --git a/vendor/sdl3/image/LICENSE.txt b/vendor/sdl3/image/LICENSE.txt index 52d0ed38b..acaf5b21b 100644 --- a/vendor/sdl3/image/LICENSE.txt +++ b/vendor/sdl3/image/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 1997-2025 Sam Lantinga +Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/image/SDL3_image.dll b/vendor/sdl3/image/SDL3_image.dll index a45e44530..ea48dab75 100644 Binary files a/vendor/sdl3/image/SDL3_image.dll and b/vendor/sdl3/image/SDL3_image.dll differ diff --git a/vendor/sdl3/image/SDL3_image.lib b/vendor/sdl3/image/SDL3_image.lib index 4e9913b4c..7db2f734a 100644 Binary files a/vendor/sdl3/image/SDL3_image.lib and b/vendor/sdl3/image/SDL3_image.lib differ diff --git a/vendor/sdl3/image/include/SDL_image.h b/vendor/sdl3/image/include/SDL_image.h index 9775ee616..19d9f2e02 100644 --- a/vendor/sdl3/image/include/SDL_image.h +++ b/vendor/sdl3/image/include/SDL_image.h @@ -1,6 +1,6 @@ /* SDL_image: An example image loading library for use with SDL - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -44,7 +44,7 @@ extern "C" { * Printable format: "%d.%d.%d", MAJOR, MINOR, MICRO */ #define SDL_IMAGE_MAJOR_VERSION 3 -#define SDL_IMAGE_MINOR_VERSION 2 +#define SDL_IMAGE_MINOR_VERSION 4 #define SDL_IMAGE_MICRO_VERSION 0 /** @@ -70,6 +70,103 @@ extern "C" { */ extern SDL_DECLSPEC int SDLCALL IMG_Version(void); +/** + * Load an image from a filesystem path into a software surface. + * + * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use + * this if you plan to hand the data to something else or manipulate it + * further in code. + * + * There are no guarantees about what format the new SDL_Surface data will be; + * in many cases, SDL_image will attempt to supply a surface that exactly + * matches the provided image, but in others it might have to convert (either + * because the image is in a format that SDL doesn't directly support or + * because it's compressed data that could reasonably uncompress to various + * formats and SDL_image had to pick one). You can inspect an SDL_Surface for + * its specifics, and use SDL_ConvertSurface to then migrate to any supported + * format. + * + * If the image format supports a transparent pixel, SDL will set the colorkey + * for the surface. You can enable RLE acceleration on the surface afterwards + * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, + * image->format->colorkey); + * + * There is a separate function to read files from an SDL_IOStream, if you + * need an i/o abstraction to provide data from anywhere instead of a simple + * filesystem read; that function is IMG_Load_IO(). + * + * If you are using SDL's 2D rendering API, there is an equivalent call to + * load images directly into an SDL_Texture for use by the GPU without using a + * software surface: call IMG_LoadTexture() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to + * [SDL_DestroySurface](https://wiki.libsdl.org/SDL3/SDL_DestroySurface) + * (). + * + * \param file a path on the filesystem to load an image from. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadTyped_IO + * \sa IMG_Load_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file); + +/** + * Load an image from an SDL data source into a software surface. + * + * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use + * this if you plan to hand the data to something else or manipulate it + * further in code. + * + * There are no guarantees about what format the new SDL_Surface data will be; + * in many cases, SDL_image will attempt to supply a surface that exactly + * matches the provided image, but in others it might have to convert (either + * because the image is in a format that SDL doesn't directly support or + * because it's compressed data that could reasonably uncompress to various + * formats and SDL_image had to pick one). You can inspect an SDL_Surface for + * its specifics, and use SDL_ConvertSurface to then migrate to any supported + * format. + * + * If the image format supports a transparent pixel, SDL will set the colorkey + * for the surface. You can enable RLE acceleration on the surface afterwards + * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, + * image->format->colorkey); + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_Load("filename.jpg")` will call this function and + * manage those details for you, determining the file type from the filename's + * extension. + * + * There is also IMG_LoadTyped_IO(), which is equivalent to this function + * except a file extension (like "BMP", "JPG", etc) can be specified, in case + * SDL_image cannot autodetect the file format. + * + * If you are using SDL's 2D rendering API, there is an equivalent call to + * load images directly into an SDL_Texture for use by the GPU without using a + * software surface: call IMG_LoadTexture_IO() instead. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns a new SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_Load + * \sa IMG_LoadTyped_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool closeio); + /** * Load an image from an SDL data source into a software surface. * @@ -128,111 +225,11 @@ extern SDL_DECLSPEC int SDLCALL IMG_Version(void); * * \sa IMG_Load * \sa IMG_Load_IO - * \sa SDL_DestroySurface */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type); /** - * Load an image from a filesystem path into a software surface. - * - * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use - * this if you plan to hand the data to something else or manipulate it - * further in code. - * - * There are no guarantees about what format the new SDL_Surface data will be; - * in many cases, SDL_image will attempt to supply a surface that exactly - * matches the provided image, but in others it might have to convert (either - * because the image is in a format that SDL doesn't directly support or - * because it's compressed data that could reasonably uncompress to various - * formats and SDL_image had to pick one). You can inspect an SDL_Surface for - * its specifics, and use SDL_ConvertSurface to then migrate to any supported - * format. - * - * If the image format supports a transparent pixel, SDL will set the colorkey - * for the surface. You can enable RLE acceleration on the surface afterwards - * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, - * image->format->colorkey); - * - * There is a separate function to read files from an SDL_IOStream, if you - * need an i/o abstraction to provide data from anywhere instead of a simple - * filesystem read; that function is IMG_Load_IO(). - * - * If you are using SDL's 2D rendering API, there is an equivalent call to - * load images directly into an SDL_Texture for use by the GPU without using a - * software surface: call IMG_LoadTexture() instead. - * - * When done with the returned surface, the app should dispose of it with a - * call to - * [SDL_DestroySurface](https://wiki.libsdl.org/SDL3/SDL_DestroySurface) - * (). - * - * \param file a path on the filesystem to load an image from. - * \returns a new SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadTyped_IO - * \sa IMG_Load_IO - * \sa SDL_DestroySurface - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file); - -/** - * Load an image from an SDL data source into a software surface. - * - * An SDL_Surface is a buffer of pixels in memory accessible by the CPU. Use - * this if you plan to hand the data to something else or manipulate it - * further in code. - * - * There are no guarantees about what format the new SDL_Surface data will be; - * in many cases, SDL_image will attempt to supply a surface that exactly - * matches the provided image, but in others it might have to convert (either - * because the image is in a format that SDL doesn't directly support or - * because it's compressed data that could reasonably uncompress to various - * formats and SDL_image had to pick one). You can inspect an SDL_Surface for - * its specifics, and use SDL_ConvertSurface to then migrate to any supported - * format. - * - * If the image format supports a transparent pixel, SDL will set the colorkey - * for the surface. You can enable RLE acceleration on the surface afterwards - * by calling: SDL_SetSurfaceColorKey(image, SDL_RLEACCEL, - * image->format->colorkey); - * - * If `closeio` is true, `src` will be closed before returning, whether this - * function succeeds or not. SDL_image reads everything it needs from `src` - * during this call in any case. - * - * There is a separate function to read files from disk without having to deal - * with SDL_IOStream: `IMG_Load("filename.jpg")` will call this function and - * manage those details for you, determining the file type from the filename's - * extension. - * - * There is also IMG_LoadTyped_IO(), which is equivalent to this function - * except a file extension (like "BMP", "JPG", etc) can be specified, in case - * SDL_image cannot autodetect the file format. - * - * If you are using SDL's 2D rendering API, there is an equivalent call to - * load images directly into an SDL_Texture for use by the GPU without using a - * software surface: call IMG_LoadTexture_IO() instead. - * - * When done with the returned surface, the app should dispose of it with a - * call to SDL_DestroySurface(). - * - * \param src an SDL_IOStream that data will be read from. - * \param closeio true to close/free the SDL_IOStream before returning, false - * to leave it open. - * \returns a new SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_Load - * \sa IMG_LoadTyped_IO - * \sa SDL_DestroySurface - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool closeio); - -/** - * Load an image from a filesystem path into a GPU texture. + * Load an image from a filesystem path into a texture. * * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render * API. This can be significantly more efficient than using a CPU-bound @@ -255,7 +252,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool cl * When done with the returned texture, the app should dispose of it with a * call to SDL_DestroyTexture(). * - * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param renderer the SDL_Renderer to use to create the texture. * \param file a path on the filesystem to load an image from. * \returns a new texture, or NULL on error. * @@ -267,7 +264,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool cl extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture(SDL_Renderer *renderer, const char *file); /** - * Load an image from an SDL data source into a GPU texture. + * Load an image from an SDL data source into a texture. * * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render * API. This can be significantly more efficient than using a CPU-bound @@ -299,7 +296,7 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture(SDL_Renderer *renderer * When done with the returned texture, the app should dispose of it with a * call to SDL_DestroyTexture(). * - * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param renderer the SDL_Renderer to use to create the texture. * \param src an SDL_IOStream that data will be read from. * \param closeio true to close/free the SDL_IOStream before returning, false * to leave it open. @@ -309,12 +306,11 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture(SDL_Renderer *renderer * * \sa IMG_LoadTexture * \sa IMG_LoadTextureTyped_IO - * \sa SDL_DestroyTexture */ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture_IO(SDL_Renderer *renderer, SDL_IOStream *src, bool closeio); /** - * Load an image from an SDL data source into a GPU texture. + * Load an image from an SDL data source into a texture. * * An SDL_Texture represents an image in GPU memory, usable by SDL's 2D Render * API. This can be significantly more efficient than using a CPU-bound @@ -352,7 +348,7 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture_IO(SDL_Renderer *rende * When done with the returned texture, the app should dispose of it with a * call to SDL_DestroyTexture(). * - * \param renderer the SDL_Renderer to use to create the GPU texture. + * \param renderer the SDL_Renderer to use to create the texture. * \param src an SDL_IOStream that data will be read from. * \param closeio true to close/free the SDL_IOStream before returning, false * to leave it open. @@ -364,10 +360,194 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture_IO(SDL_Renderer *rende * * \sa IMG_LoadTexture * \sa IMG_LoadTexture_IO - * \sa SDL_DestroyTexture */ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTextureTyped_IO(SDL_Renderer *renderer, SDL_IOStream *src, bool closeio, const char *type); +/** + * Load an image from a filesystem path into a GPU texture. + * + * An SDL_GPUTexture represents an image in GPU memory, usable by SDL's GPU + * API. Regardless of the source format of the image, this function will + * create a GPU texture with the format SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM + * with no mip levels. It can be bound as a sampled texture from a graphics or + * compute pipeline and as a a readonly storage texture in a compute pipeline. + * + * There is a separate function to read files from an SDL_IOStream, if you + * need an i/o abstraction to provide data from anywhere instead of a simple + * filesystem read; that function is IMG_LoadGPUTexture_IO(). + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_ReleaseGPUTexture(). + * + * \param device the SDL_GPUDevice to use to create the GPU texture. + * \param copy_pass the SDL_GPUCopyPass to use to upload the loaded image to + * the GPU texture. + * \param file a path on the filesystem to load an image from. + * \param width a pointer filled in with the width of the GPU texture. may be + * NULL. + * \param height a pointer filled in with the width of the GPU texture. may be + * NULL. + * \returns a new GPU texture, or NULL on error. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_LoadGPUTextureTyped_IO + * \sa IMG_LoadGPUTexture_IO + */ +extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL IMG_LoadGPUTexture(SDL_GPUDevice *device, SDL_GPUCopyPass *copy_pass, const char *file, int *width, int *height); + +/** + * Load an image from an SDL data source into a GPU texture. + * + * An SDL_GPUTexture represents an image in GPU memory, usable by SDL's GPU + * API. Regardless of the source format of the image, this function will + * create a GPU texture with the format SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM + * with no mip levels. It can be bound as a sampled texture from a graphics or + * compute pipeline and as a a readonly storage texture in a compute pipeline. + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_LoadGPUTexture(device, copy_pass, "filename.jpg", + * width, height) will call this function and manage those details for you, + * determining the file type from the filename's extension. + * + * There is also IMG_LoadGPUTextureTyped_IO(), which is equivalent to this + * function except a file extension (like "BMP", "JPG", etc) can be specified, + * in case SDL_image cannot autodetect the file format. + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_ReleaseGPUTexture(). + * + * \param device the SDL_GPUDevice to use to create the GPU texture. + * \param copy_pass the SDL_GPUCopyPass to use to upload the loaded image to + * the GPU texture. + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param width a pointer filled in with the width of the GPU texture. may be + * NULL. + * \param height a pointer filled in with the width of the GPU texture. may be + * NULL. + * \returns a new GPU texture, or NULL on error. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_LoadGPUTexture + * \sa IMG_LoadGPUTextureTyped_IO + */ +extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL IMG_LoadGPUTexture_IO(SDL_GPUDevice *device, SDL_GPUCopyPass *copy_pass, SDL_IOStream *src, bool closeio, int *width, int *height); + +/** + * Load an image from an SDL data source into a GPU texture. + * + * An SDL_GPUTexture represents an image in GPU memory, usable by SDL's GPU + * API. Regardless of the source format of the image, this function will + * create a GPU texture with the format SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM + * with no mip levels. It can be bound as a sampled texture from a graphics or + * compute pipeline and as a a readonly storage texture in a compute pipeline. + * + * If `closeio` is true, `src` will be closed before returning, whether this + * function succeeds or not. SDL_image reads everything it needs from `src` + * during this call in any case. + * + * Even though this function accepts a file type, SDL_image may still try + * other decoders that are capable of detecting file type from the contents of + * the image data, but may rely on the caller-provided type string for formats + * that it cannot autodetect. If `type` is NULL, SDL_image will rely solely on + * its ability to guess the format. + * + * There is a separate function to read files from disk without having to deal + * with SDL_IOStream: `IMG_LoadGPUTexture(device, copy_pass, "filename.jpg", + * width, height) will call this function and manage those details for you, + * determining the file type from the filename's extension. + * + * There is also IMG_LoadGPUTexture_IO(), which is equivalent to this function + * except that it will rely on SDL_image to determine what type of data it is + * loading, much like passing a NULL for type. + * + * When done with the returned texture, the app should dispose of it with a + * call to SDL_ReleaseGPUTexture(). + * + * \param device the SDL_GPUDevice to use to create the GPU texture. + * \param copy_pass the SDL_GPUCopyPass to use to upload the loaded image to + * the GPU texture. + * \param src an SDL_IOStream that data will be read from. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("BMP", "GIF", + * "PNG", etc). + * \param width a pointer filled in with the width of the GPU texture. may be + * NULL. + * \param height a pointer filled in with the width of the GPU texture. may be + * NULL. + * \returns a new GPU texture, or NULL on error. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_LoadGPUTexture + * \sa IMG_LoadGPUTexture_IO + */ +extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL IMG_LoadGPUTextureTyped_IO(SDL_GPUDevice *device, SDL_GPUCopyPass *copy_pass, SDL_IOStream *src, bool closeio, const char *type, int *width, int *height); + +/** + * Get the image currently in the clipboard. + * + * When done with the returned surface, the app should dispose of it with a + * call to SDL_DestroySurface(). + * + * \returns a new SDL surface, or NULL if no supported image is available. + * + * \since This function is available since SDL_image 3.4.0. + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_GetClipboardImage(void); + +/** + * Detect ANI animated cursor data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns true if this is ANI animated cursor data, false otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isAVIF + * \sa IMG_isBMP + * \sa IMG_isCUR + * \sa IMG_isGIF + * \sa IMG_isICO + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isQOI + * \sa IMG_isSVG + * \sa IMG_isTIF + * \sa IMG_isWEBP + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isANI(SDL_IOStream *src); + /** * Detect AVIF image data on a readable/seekable SDL_IOStream. * @@ -387,74 +567,31 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL IMG_LoadTextureTyped_IO(SDL_Renderer * * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is AVIF data, zero otherwise. + * \returns true if this is AVIF data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * - * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR + * \sa IMG_isANI * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isAVIF(SDL_IOStream *src); -/** - * Detect ICO image data on a readable/seekable SDL_IOStream. - * - * This function attempts to determine if a file is a given filetype, reading - * the least amount possible from the SDL_IOStream (usually a few bytes). - * - * There is no distinction made between "not the filetype in question" and - * basic i/o errors. - * - * This function will always attempt to seek `src` back to where it started - * when this function was called, but it will not report any errors in doing - * so, but assuming seeking works, this means you can immediately use this - * with a different IMG_isTYPE function, or load the image without further - * seeking. - * - * You do not need to call this function to load data; SDL_image can work to - * determine file type in many cases in its standard load functions. - * - * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is ICO data, zero otherwise. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_isAVIF - * \sa IMG_isCUR - * \sa IMG_isBMP - * \sa IMG_isGIF - * \sa IMG_isJPG - * \sa IMG_isJXL - * \sa IMG_isLBM - * \sa IMG_isPCX - * \sa IMG_isPNG - * \sa IMG_isPNM - * \sa IMG_isSVG - * \sa IMG_isQOI - * \sa IMG_isTIF - * \sa IMG_isXCF - * \sa IMG_isXPM - * \sa IMG_isXV - * \sa IMG_isWEBP - */ -extern SDL_DECLSPEC bool SDLCALL IMG_isICO(SDL_IOStream *src); - /** * Detect CUR image data on a readable/seekable SDL_IOStream. * @@ -474,27 +611,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isICO(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is CUR data, zero otherwise. + * \returns true if this is CUR data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO * \sa IMG_isBMP * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isCUR(SDL_IOStream *src); @@ -517,27 +655,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isCUR(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is BMP data, zero otherwise. + * \returns true if this is BMP data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isBMP(SDL_IOStream *src); @@ -560,30 +699,75 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isBMP(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is GIF data, zero otherwise. + * \returns true if this is GIF data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isGIF(SDL_IOStream *src); +/** + * Detect ICO image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns true if this is ICO data, false otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isANI + * \sa IMG_isAVIF + * \sa IMG_isBMP + * \sa IMG_isCUR + * \sa IMG_isGIF + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isQOI + * \sa IMG_isSVG + * \sa IMG_isTIF + * \sa IMG_isWEBP + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isICO(SDL_IOStream *src); + /** * Detect JPG image data on a readable/seekable SDL_IOStream. * @@ -603,27 +787,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isGIF(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is JPG data, zero otherwise. + * \returns true if this is JPG data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isJPG(SDL_IOStream *src); @@ -646,27 +831,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isJPG(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is JXL data, zero otherwise. + * \returns true if this is JXL data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isJXL(SDL_IOStream *src); @@ -689,27 +875,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isJXL(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is LBM data, zero otherwise. + * \returns true if this is LBM data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isLBM(SDL_IOStream *src); @@ -732,27 +919,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isLBM(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is PCX data, zero otherwise. + * \returns true if this is PCX data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isPCX(SDL_IOStream *src); @@ -775,27 +963,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isPCX(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is PNG data, zero otherwise. + * \returns true if this is PNG data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isPNG(SDL_IOStream *src); @@ -818,73 +1007,31 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isPNG(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is PNM data, zero otherwise. + * \returns true if this is PNM data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isPNM(SDL_IOStream *src); -/** - * Detect SVG image data on a readable/seekable SDL_IOStream. - * - * This function attempts to determine if a file is a given filetype, reading - * the least amount possible from the SDL_IOStream (usually a few bytes). - * - * There is no distinction made between "not the filetype in question" and - * basic i/o errors. - * - * This function will always attempt to seek `src` back to where it started - * when this function was called, but it will not report any errors in doing - * so, but assuming seeking works, this means you can immediately use this - * with a different IMG_isTYPE function, or load the image without further - * seeking. - * - * You do not need to call this function to load data; SDL_image can work to - * determine file type in many cases in its standard load functions. - * - * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is SVG data, zero otherwise. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR - * \sa IMG_isBMP - * \sa IMG_isGIF - * \sa IMG_isJPG - * \sa IMG_isJXL - * \sa IMG_isLBM - * \sa IMG_isPCX - * \sa IMG_isPNG - * \sa IMG_isPNM - * \sa IMG_isQOI - * \sa IMG_isTIF - * \sa IMG_isXCF - * \sa IMG_isXPM - * \sa IMG_isXV - * \sa IMG_isWEBP - */ -extern SDL_DECLSPEC bool SDLCALL IMG_isSVG(SDL_IOStream *src); - /** * Detect QOI image data on a readable/seekable SDL_IOStream. * @@ -904,15 +1051,16 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isSVG(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is QOI data, zero otherwise. + * \returns true if this is QOI data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM @@ -921,13 +1069,57 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isSVG(SDL_IOStream *src); * \sa IMG_isPNM * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isQOI(SDL_IOStream *src); +/** + * Detect SVG image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns true if this is SVG data, false otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isANI + * \sa IMG_isAVIF + * \sa IMG_isBMP + * \sa IMG_isCUR + * \sa IMG_isGIF + * \sa IMG_isICO + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isQOI + * \sa IMG_isTIF + * \sa IMG_isWEBP + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isSVG(SDL_IOStream *src); + /** * Detect TIFF image data on a readable/seekable SDL_IOStream. * @@ -947,30 +1139,75 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isQOI(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is TIFF data, zero otherwise. + * \returns true if this is TIFF data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isTIF(SDL_IOStream *src); +/** + * Detect WEBP image data on a readable/seekable SDL_IOStream. + * + * This function attempts to determine if a file is a given filetype, reading + * the least amount possible from the SDL_IOStream (usually a few bytes). + * + * There is no distinction made between "not the filetype in question" and + * basic i/o errors. + * + * This function will always attempt to seek `src` back to where it started + * when this function was called, but it will not report any errors in doing + * so, but assuming seeking works, this means you can immediately use this + * with a different IMG_isTYPE function, or load the image without further + * seeking. + * + * You do not need to call this function to load data; SDL_image can work to + * determine file type in many cases in its standard load functions. + * + * \param src a seekable/readable SDL_IOStream to provide image data. + * \returns true if this is WEBP data, false otherwise. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_isANI + * \sa IMG_isAVIF + * \sa IMG_isBMP + * \sa IMG_isCUR + * \sa IMG_isGIF + * \sa IMG_isICO + * \sa IMG_isJPG + * \sa IMG_isJXL + * \sa IMG_isLBM + * \sa IMG_isPCX + * \sa IMG_isPNG + * \sa IMG_isPNM + * \sa IMG_isQOI + * \sa IMG_isSVG + * \sa IMG_isTIF + * \sa IMG_isXCF + * \sa IMG_isXPM + * \sa IMG_isXV + */ +extern SDL_DECLSPEC bool SDLCALL IMG_isWEBP(SDL_IOStream *src); + /** * Detect XCF image data on a readable/seekable SDL_IOStream. * @@ -990,27 +1227,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isTIF(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is XCF data, zero otherwise. + * \returns true if this is XCF data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXPM * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isXCF(SDL_IOStream *src); @@ -1033,27 +1271,28 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isXCF(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is XPM data, zero otherwise. + * \returns true if this is XPM data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXV - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isXPM(SDL_IOStream *src); @@ -1076,73 +1315,31 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isXPM(SDL_IOStream *src); * determine file type in many cases in its standard load functions. * * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is XV data, zero otherwise. + * \returns true if this is XV data, false otherwise. * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isANI * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR * \sa IMG_isBMP + * \sa IMG_isCUR * \sa IMG_isGIF + * \sa IMG_isICO * \sa IMG_isJPG * \sa IMG_isJXL * \sa IMG_isLBM * \sa IMG_isPCX * \sa IMG_isPNG * \sa IMG_isPNM - * \sa IMG_isSVG * \sa IMG_isQOI + * \sa IMG_isSVG * \sa IMG_isTIF + * \sa IMG_isWEBP * \sa IMG_isXCF * \sa IMG_isXPM - * \sa IMG_isWEBP */ extern SDL_DECLSPEC bool SDLCALL IMG_isXV(SDL_IOStream *src); -/** - * Detect WEBP image data on a readable/seekable SDL_IOStream. - * - * This function attempts to determine if a file is a given filetype, reading - * the least amount possible from the SDL_IOStream (usually a few bytes). - * - * There is no distinction made between "not the filetype in question" and - * basic i/o errors. - * - * This function will always attempt to seek `src` back to where it started - * when this function was called, but it will not report any errors in doing - * so, but assuming seeking works, this means you can immediately use this - * with a different IMG_isTYPE function, or load the image without further - * seeking. - * - * You do not need to call this function to load data; SDL_image can work to - * determine file type in many cases in its standard load functions. - * - * \param src a seekable/readable SDL_IOStream to provide image data. - * \returns non-zero if this is WEBP data, zero otherwise. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_isAVIF - * \sa IMG_isICO - * \sa IMG_isCUR - * \sa IMG_isBMP - * \sa IMG_isGIF - * \sa IMG_isJPG - * \sa IMG_isJXL - * \sa IMG_isLBM - * \sa IMG_isPCX - * \sa IMG_isPNG - * \sa IMG_isPNM - * \sa IMG_isSVG - * \sa IMG_isQOI - * \sa IMG_isTIF - * \sa IMG_isXCF - * \sa IMG_isXPM - * \sa IMG_isXV - */ -extern SDL_DECLSPEC bool SDLCALL IMG_isWEBP(SDL_IOStream *src); - /** * Load a AVIF image directly. * @@ -1156,95 +1353,27 @@ extern SDL_DECLSPEC bool SDLCALL IMG_isWEBP(SDL_IOStream *src); * * \since This function is available since SDL_image 3.0.0. * - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadAVIF_IO(SDL_IOStream *src); -/** - * Load a ICO image directly. - * - * If you know you definitely have a ICO image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_IO(SDL_IOStream *src); - -/** - * Load a CUR image directly. - * - * If you know you definitely have a CUR image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_IO(SDL_IOStream *src); - /** * Load a BMP image directly. * @@ -1259,26 +1388,60 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_IO(SDL_IOStream *src); +/** + * Load a CUR image directly. + * + * If you know you definitely have a CUR image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_IO(SDL_IOStream *src); + /** * Load a GIF image directly. * @@ -1293,26 +1456,60 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_IO(SDL_IOStream *src); +/** + * Load a ICO image directly. + * + * If you know you definitely have a ICO image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_IO(SDL_IOStream *src); + /** * Load a JPG image directly. * @@ -1327,23 +1524,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_IO(SDL_IOStream *src); @@ -1361,23 +1558,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJXL_IO(SDL_IOStream *src); @@ -1395,23 +1592,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadJXL_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_IO(SDL_IOStream *src); @@ -1429,23 +1626,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_IO(SDL_IOStream *src); @@ -1463,23 +1660,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_IO(SDL_IOStream *src); @@ -1497,23 +1694,23 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO * \sa IMG_LoadPCX_IO * \sa IMG_LoadPNG_IO - * \sa IMG_LoadSVG_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_IO(SDL_IOStream *src); @@ -1531,10 +1728,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_IO(SDL_IOStream *src); * \since This function is available since SDL_image 3.0.0. * * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO * \sa IMG_LoadJPG_IO * \sa IMG_LoadJXL_IO * \sa IMG_LoadLBM_IO @@ -1542,253 +1739,16 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_IO(SDL_IOStream *src); * \sa IMG_LoadPNG_IO * \sa IMG_LoadPNM_IO * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSizedSVG_IO * \sa IMG_LoadTGA_IO * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO * \sa IMG_LoadXCF_IO * \sa IMG_LoadXPM_IO * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadSVG_IO(SDL_IOStream *src); -/** - * Load a QOI image directly. - * - * If you know you definitely have a QOI image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadQOI_IO(SDL_IOStream *src); - -/** - * Load a TGA image directly. - * - * If you know you definitely have a TGA image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_IO(SDL_IOStream *src); - -/** - * Load a TIFF image directly. - * - * If you know you definitely have a TIFF image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_IO(SDL_IOStream *src); - -/** - * Load a XCF image directly. - * - * If you know you definitely have a XCF image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_IO(SDL_IOStream *src); - -/** - * Load a XPM image directly. - * - * If you know you definitely have a XPM image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXV_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_IO(SDL_IOStream *src); - -/** - * Load a XV image directly. - * - * If you know you definitely have a XV image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadWEBP_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_IO(SDL_IOStream *src); - -/** - * Load a WEBP image directly. - * - * If you know you definitely have a WEBP image, you can call this function, - * which will skip SDL_image's file format detection routines. Generally it's - * better to use the abstract interfaces; also, there is only an SDL_IOStream - * interface available here. - * - * \param src an SDL_IOStream to load image data from. - * \returns SDL surface, or NULL on error. - * - * \since This function is available since SDL_image 3.0.0. - * - * \sa IMG_LoadAVIF_IO - * \sa IMG_LoadICO_IO - * \sa IMG_LoadCUR_IO - * \sa IMG_LoadBMP_IO - * \sa IMG_LoadGIF_IO - * \sa IMG_LoadJPG_IO - * \sa IMG_LoadJXL_IO - * \sa IMG_LoadLBM_IO - * \sa IMG_LoadPCX_IO - * \sa IMG_LoadPNG_IO - * \sa IMG_LoadPNM_IO - * \sa IMG_LoadSVG_IO - * \sa IMG_LoadQOI_IO - * \sa IMG_LoadTGA_IO - * \sa IMG_LoadTIF_IO - * \sa IMG_LoadXCF_IO - * \sa IMG_LoadXPM_IO - * \sa IMG_LoadXV_IO - */ -extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_IO(SDL_IOStream *src); - /** * Load an SVG image, scaled to a specific size. * @@ -1807,9 +1767,249 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_IO(SDL_IOStream *src); * \returns a new SDL surface, or NULL on error. * * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadSVG_IO */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadSizedSVG_IO(SDL_IOStream *src, int width, int height); +/** + * Load a QOI image directly. + * + * If you know you definitely have a QOI image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadQOI_IO(SDL_IOStream *src); + +/** + * Load a TGA image directly. + * + * If you know you definitely have a TGA image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_IO(SDL_IOStream *src); + +/** + * Load a TIFF image directly. + * + * If you know you definitely have a TIFF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_IO(SDL_IOStream *src); + +/** + * Load a WEBP image directly. + * + * If you know you definitely have a WEBP image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_IO(SDL_IOStream *src); + +/** + * Load a XCF image directly. + * + * If you know you definitely have a XCF image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXPM_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_IO(SDL_IOStream *src); + +/** + * Load a XPM image directly. + * + * If you know you definitely have a XPM image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXV_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_IO(SDL_IOStream *src); + +/** + * Load a XV image directly. + * + * If you know you definitely have a XV image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * \param src an SDL_IOStream to load image data from. + * \returns SDL surface, or NULL on error. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAVIF_IO + * \sa IMG_LoadBMP_IO + * \sa IMG_LoadCUR_IO + * \sa IMG_LoadGIF_IO + * \sa IMG_LoadICO_IO + * \sa IMG_LoadJPG_IO + * \sa IMG_LoadJXL_IO + * \sa IMG_LoadLBM_IO + * \sa IMG_LoadPCX_IO + * \sa IMG_LoadPNG_IO + * \sa IMG_LoadPNM_IO + * \sa IMG_LoadQOI_IO + * \sa IMG_LoadSVG_IO + * \sa IMG_LoadTGA_IO + * \sa IMG_LoadTIF_IO + * \sa IMG_LoadWEBP_IO + * \sa IMG_LoadXCF_IO + * \sa IMG_LoadXPM_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_IO(SDL_IOStream *src); + /** * Load an XPM image from a memory array. * @@ -1848,6 +2048,67 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm); */ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArrayToRGB888(char **xpm); +/** + * Save an SDL_Surface into an image file. + * + * If the file already exists, it will be overwritten. + * + * For formats that accept a quality, a default quality of 90 will be used. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveTyped_IO + * \sa IMG_SaveAVIF + * \sa IMG_SaveBMP + * \sa IMG_SaveCUR + * \sa IMG_SaveGIF + * \sa IMG_SaveICO + * \sa IMG_SaveJPG + * \sa IMG_SavePNG + * \sa IMG_SaveTGA + * \sa IMG_SaveWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_Save(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into formatted image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_Save() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * For formats that accept a quality, a default quality of 90 will be used. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("BMP", "GIF", + * "PNG", etc). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_Save + * \sa IMG_SaveAVIF_IO + * \sa IMG_SaveBMP_IO + * \sa IMG_SaveCUR_IO + * \sa IMG_SaveGIF_IO + * \sa IMG_SaveICO_IO + * \sa IMG_SaveJPG_IO + * \sa IMG_SavePNG_IO + * \sa IMG_SaveTGA_IO + * \sa IMG_SaveWEBP_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveTyped_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, const char *type); + /** * Save an SDL_Surface into a AVIF image file. * @@ -1890,7 +2151,7 @@ extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIF(SDL_Surface *surface, const char * extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIF_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, int quality); /** - * Save an SDL_Surface into a PNG image file. + * Save an SDL_Surface into a BMP image file. * * If the file already exists, it will be overwritten. * @@ -1899,16 +2160,16 @@ extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIF_IO(SDL_Surface *surface, SDL_IOStr * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \since This function is available since SDL_image 3.0.0. + * \since This function is available since SDL_image 3.4.0. * - * \sa IMG_SavePNG_IO + * \sa IMG_SaveBMP_IO */ -extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG(SDL_Surface *surface, const char *file); +extern SDL_DECLSPEC bool SDLCALL IMG_SaveBMP(SDL_Surface *surface, const char *file); /** - * Save an SDL_Surface into PNG image data, via an SDL_IOStream. + * Save an SDL_Surface into BMP image data, via an SDL_IOStream. * - * If you just want to save to a filename, you can use IMG_SavePNG() instead. + * If you just want to save to a filename, you can use IMG_SaveBMP() instead. * * If `closeio` is true, `dst` will be closed before returning, whether this * function succeeds or not. @@ -1920,11 +2181,122 @@ extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG(SDL_Surface *surface, const char *f * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \since This function is available since SDL_image 3.0.0. + * \since This function is available since SDL_image 3.4.0. * - * \sa IMG_SavePNG + * \sa IMG_SaveBMP */ -extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); +extern SDL_DECLSPEC bool SDLCALL IMG_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a CUR image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveCUR_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveCUR(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into CUR image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveCUR() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveCUR + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveCUR_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a GIF image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveGIF_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveGIF(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into GIF image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveGIF() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveGIF + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveGIF_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a ICO image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveICO_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveICO(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into ICO image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveICO() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveICO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveICO_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); /** * Save an SDL_Surface into a JPEG image file. @@ -1968,16 +2340,134 @@ extern SDL_DECLSPEC bool SDLCALL IMG_SaveJPG(SDL_Surface *surface, const char *f extern SDL_DECLSPEC bool SDLCALL IMG_SaveJPG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, int quality); /** - * Animated image support + * Save an SDL_Surface into a PNG image file. * - * Currently only animated GIFs and WEBP images are supported. + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SavePNG_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into PNG image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SavePNG() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_SavePNG + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a TGA image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write new file to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveTGA_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveTGA(SDL_Surface *surface, const char *file); + +/** + * Save an SDL_Surface into TGA image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveTGA() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveTGA + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveTGA_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save an SDL_Surface into a WEBP image file. + * + * If the file already exists, it will be overwritten. + * + * \param surface the SDL surface to save. + * \param file path on the filesystem to write the new file to. + * \param quality between 0 and 100. For lossy, 0 gives the smallest size and + * 100 the largest. For lossless, this parameter is the amount + * of effort put into the compression: 0 is the fastest but + * gives larger files compared to the slowest, but best, 100. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveWEBP_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveWEBP(SDL_Surface *surface, const char *file, float quality); + +/** + * Save an SDL_Surface into WEBP image data, via an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveWEBP() instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param surface the SDL surface to save. + * \param dst the SDL_IOStream to save the image data to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param quality between 0 and 100. For lossy, 0 gives the smallest size and + * 100 the largest. For lossless, this parameter is the amount + * of effort put into the compression: 0 is the fastest but + * gives larger files compared to the slowest, but best, 100. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveWEBP + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveWEBP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio, float quality); + +/** + * Animated image support */ typedef struct IMG_Animation { - int w, h; - int count; - SDL_Surface **frames; - int *delays; + int w; /**< The width of the frames */ + int h; /**< The height of the frames */ + int count; /**< The number of frames */ + SDL_Surface **frames; /**< An array of frames */ + int *delays; /**< An array of frame delays, in milliseconds */ } IMG_Animation; /** @@ -1991,6 +2481,14 @@ typedef struct IMG_Animation * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_CreateAnimatedCursor + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO * \sa IMG_FreeAnimation */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation(const char *file); @@ -2012,12 +2510,20 @@ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation(const char *file); * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_CreateAnimatedCursor + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO * \sa IMG_FreeAnimation */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation_IO(SDL_IOStream *src, bool closeio); /** - * Load an animation from an SDL datasource + * Load an animation from an SDL_IOStream. * * Even though this function accepts a file type, SDL_image may still try * other decoders that are capable of detecting file type from the contents of @@ -2040,26 +2546,101 @@ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimation_IO(SDL_IOStream *s * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_CreateAnimatedCursor * \sa IMG_LoadAnimation * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO * \sa IMG_FreeAnimation */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadAnimationTyped_IO(SDL_IOStream *src, bool closeio, const char *type); /** - * Dispose of an IMG_Animation and free its resources. + * Load an ANI animation directly from an SDL_IOStream. * - * The provided `anim` pointer is not valid once this call returns. + * If you know you definitely have an ANI image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally, it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. * - * \param anim IMG_Animation to dispose of. + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). * - * \since This function is available since SDL_image 3.0.0. + * \param src an SDL_IOStream from which data will be read. + * \returns a new IMG_Animation, or NULL on error. * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_isANI * \sa IMG_LoadAnimation * \sa IMG_LoadAnimation_IO * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO + * \sa IMG_FreeAnimation */ -extern SDL_DECLSPEC void SDLCALL IMG_FreeAnimation(IMG_Animation *anim); +extern SDL_DECLSPEC IMG_Animation *SDLCALL IMG_LoadANIAnimation_IO(SDL_IOStream *src); + +/** + * Load an APNG animation directly from an SDL_IOStream. + * + * If you know you definitely have an APNG image, you can call this function, + * which will skip SDL_image's file format detection routines. Generally, it's + * better to use the abstract interfaces; also, there is only an SDL_IOStream + * interface available here. + * + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). + * + * \param src an SDL_IOStream from which data will be read. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_isPNG + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation *SDLCALL IMG_LoadAPNGAnimation_IO(SDL_IOStream *src); + +/** + * Load an AVIF animation directly from an SDL_IOStream. + * + * If you know you definitely have an AVIF animation, you can call this + * function, which will skip SDL_image's file format detection routines. + * Generally it's better to use the abstract interfaces; also, there is only + * an SDL_IOStream interface available here. + * + * When done with the returned animation, the app should dispose of it with a + * call to IMG_FreeAnimation(). + * + * \param src an SDL_IOStream that data will be read from. + * \returns a new IMG_Animation, or NULL on error. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_isAVIF + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO + * \sa IMG_FreeAnimation + */ +extern SDL_DECLSPEC IMG_Animation *SDLCALL IMG_LoadAVIFAnimation_IO(SDL_IOStream *src); /** * Load a GIF animation directly. @@ -2074,9 +2655,14 @@ extern SDL_DECLSPEC void SDLCALL IMG_FreeAnimation(IMG_Animation *anim); * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isGIF * \sa IMG_LoadAnimation * \sa IMG_LoadAnimation_IO * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO * \sa IMG_FreeAnimation */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadGIFAnimation_IO(SDL_IOStream *src); @@ -2094,13 +2680,643 @@ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadGIFAnimation_IO(SDL_IOStream * * \since This function is available since SDL_image 3.0.0. * + * \sa IMG_isWEBP * \sa IMG_LoadAnimation * \sa IMG_LoadAnimation_IO * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO * \sa IMG_FreeAnimation */ extern SDL_DECLSPEC IMG_Animation * SDLCALL IMG_LoadWEBPAnimation_IO(SDL_IOStream *src); +/** + * Save an animation to a file. + * + * For formats that accept a quality, a default quality of 90 will be used. + * + * \param anim the animation to save. + * \param file path on the filesystem containing an animated image. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAnimation(IMG_Animation *anim, const char *file); + +/** + * Save an animation to an SDL_IOStream. + * + * If you just want to save to a filename, you can use IMG_SaveAnimation() + * instead. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * For formats that accept a quality, a default quality of 90 will be used. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream that data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param type a filename extension that represent this data ("GIF", etc). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAnimationTyped_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio, const char *type); + +/** + * Save an animation in ANI format to an SDL_IOStream. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream from which data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveANIAnimation_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio); + +/** + * Save an animation in APNG format to an SDL_IOStream. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream from which data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAPNGAnimation_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio); + +/** + * Save an animation in AVIF format to an SDL_IOStream. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream from which data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param quality the desired quality, ranging between 0 (lowest) and 100 + * (highest). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveAVIFAnimation_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio, int quality); + +/** + * Save an animation in GIF format to an SDL_IOStream. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream from which data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveWEBPAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveGIFAnimation_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio); + +/** + * Save an animation in WEBP format to an SDL_IOStream. + * + * If `closeio` is true, `dst` will be closed before returning, whether this + * function succeeds or not. + * + * \param anim the animation to save. + * \param dst an SDL_IOStream from which data will be written to. + * \param closeio true to close/free the SDL_IOStream before returning, false + * to leave it open. + * \param quality between 0 and 100. For lossy, 0 gives the smallest size and + * 100 the largest. For lossless, this parameter is the amount + * of effort put into the compression: 0 is the fastest but + * gives larger files compared to the slowest, but best, 100. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_SaveAnimation + * \sa IMG_SaveAnimationTyped_IO + * \sa IMG_SaveANIAnimation_IO + * \sa IMG_SaveAPNGAnimation_IO + * \sa IMG_SaveAVIFAnimation_IO + * \sa IMG_SaveGIFAnimation_IO + */ +extern SDL_DECLSPEC bool SDLCALL IMG_SaveWEBPAnimation_IO(IMG_Animation *anim, SDL_IOStream *dst, bool closeio, int quality); + +/** + * Create an animated cursor from an animation. + * + * \param anim an animation to use to create an animated cursor. + * \param hot_x the x position of the cursor hot spot. + * \param hot_y the y position of the cursor hot spot. + * \returns the new cursor on success or NULL on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + */ +extern SDL_DECLSPEC SDL_Cursor * SDLCALL IMG_CreateAnimatedCursor(IMG_Animation *anim, int hot_x, int hot_y); + +/** + * Dispose of an IMG_Animation and free its resources. + * + * The provided `anim` pointer is not valid once this call returns. + * + * \param anim IMG_Animation to dispose of. + * + * \since This function is available since SDL_image 3.0.0. + * + * \sa IMG_LoadAnimation + * \sa IMG_LoadAnimation_IO + * \sa IMG_LoadAnimationTyped_IO + * \sa IMG_LoadANIAnimation_IO + * \sa IMG_LoadAPNGAnimation_IO + * \sa IMG_LoadAVIFAnimation_IO + * \sa IMG_LoadGIFAnimation_IO + * \sa IMG_LoadWEBPAnimation_IO + */ +extern SDL_DECLSPEC void SDLCALL IMG_FreeAnimation(IMG_Animation *anim); + +/** + * An object representing the encoder context. + */ +typedef struct IMG_AnimationEncoder IMG_AnimationEncoder; + +/** + * Create an encoder to save a series of images to a file. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * The file type is determined from the file extension, e.g. "file.webp" will + * be encoded using WEBP. + * + * \param file the file where the animation will be saved. + * \returns a new IMG_AnimationEncoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationEncoder_IO + * \sa IMG_CreateAnimationEncoderWithProperties + * \sa IMG_AddAnimationEncoderFrame + * \sa IMG_CloseAnimationEncoder + */ +extern SDL_DECLSPEC IMG_AnimationEncoder * SDLCALL IMG_CreateAnimationEncoder(const char *file); + +/** + * Create an encoder to save a series of images to an IOStream. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * If `closeio` is true, `dst` will be closed before returning if this + * function fails, or when the animation encoder is closed if this function + * succeeds. + * + * \param dst an SDL_IOStream that will be used to save the stream. + * \param closeio true to close the SDL_IOStream when done, false to leave it + * open. + * \param type a filename extension that represent this data ("WEBP", etc). + * \returns a new IMG_AnimationEncoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationEncoder + * \sa IMG_CreateAnimationEncoderWithProperties + * \sa IMG_AddAnimationEncoderFrame + * \sa IMG_CloseAnimationEncoder + */ +extern SDL_DECLSPEC IMG_AnimationEncoder * SDLCALL IMG_CreateAnimationEncoder_IO(SDL_IOStream *dst, bool closeio, const char *type); + +/** + * Create an animation encoder with the specified properties. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * These are the supported properties: + * + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_FILENAME_STRING`: the file to save, if + * an SDL_IOStream isn't being used. This is required if + * `IMG_PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_POINTER` isn't set. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_POINTER`: an SDL_IOStream + * that will be used to save the stream. This should not be closed until the + * animation encoder is closed. This is required if + * `IMG_PROP_ANIMATION_ENCODER_CREATE_FILENAME_STRING` isn't set. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN`: true if + * closing the animation encoder should also close the associated + * SDL_IOStream. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_TYPE_STRING`: the output file type, + * e.g. "webp", defaults to the file extension if + * `IMG_PROP_ANIMATION_ENCODER_CREATE_FILENAME_STRING` is set. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_QUALITY_NUMBER`: the compression + * quality, in the range of 0 to 100. The higher the number, the higher the + * quality and file size. This defaults to a balanced value for compression + * and quality. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_NUMERATOR_NUMBER`: the + * numerator of the fraction used to multiply the pts to convert it to + * seconds. This defaults to 1. + * - `IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER`: the + * denominator of the fraction used to multiply the pts to convert it to + * seconds. This defaults to 1000. + * + * \param props the properties of the animation encoder. + * \returns a new IMG_AnimationEncoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationEncoder + * \sa IMG_CreateAnimationEncoder_IO + * \sa IMG_AddAnimationEncoderFrame + * \sa IMG_CloseAnimationEncoder + */ +extern SDL_DECLSPEC IMG_AnimationEncoder * SDLCALL IMG_CreateAnimationEncoderWithProperties(SDL_PropertiesID props); + +#define IMG_PROP_ANIMATION_ENCODER_CREATE_FILENAME_STRING "SDL_image.animation_encoder.create.filename" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_POINTER "SDL_image.animation_encoder.create.iostream" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN "SDL_image.animation_encoder.create.iostream.autoclose" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_TYPE_STRING "SDL_image.animation_encoder.create.type" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_QUALITY_NUMBER "SDL_image.animation_encoder.create.quality" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_NUMERATOR_NUMBER "SDL_image.animation_encoder.create.timebase.numerator" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER "SDL_image.animation_encoder.create.timebase.denominator" + +#define IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_MAX_THREADS_NUMBER "SDL_image.animation_encoder.create.avif.max_threads" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_KEYFRAME_INTERVAL_NUMBER "SDL_image.animation_encoder.create.avif.keyframe_interval" +#define IMG_PROP_ANIMATION_ENCODER_CREATE_GIF_USE_LUT_BOOLEAN "SDL_image.animation_encoder.create.gif.use_lut" + +/** + * Add a frame to an animation encoder. + * + * \param encoder the receiving images. + * \param surface the surface to add as the next frame in the animation. + * \param duration the duration of the frame, usually in milliseconds but can + * be other units if the + * `IMG_PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER` + * property is set when creating the encoder. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationEncoder + * \sa IMG_CreateAnimationEncoder_IO + * \sa IMG_CreateAnimationEncoderWithProperties + * \sa IMG_CloseAnimationEncoder + */ +extern SDL_DECLSPEC bool SDLCALL IMG_AddAnimationEncoderFrame(IMG_AnimationEncoder *encoder, SDL_Surface *surface, Uint64 duration); + +/** + * Close an animation encoder, finishing any encoding. + * + * Calling this function frees the animation encoder, and returns the final + * status of the encoding process. + * + * \param encoder the encoder to close. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationEncoder + * \sa IMG_CreateAnimationEncoder_IO + * \sa IMG_CreateAnimationEncoderWithProperties + */ +extern SDL_DECLSPEC bool SDLCALL IMG_CloseAnimationEncoder(IMG_AnimationEncoder *encoder); + +/** + * An enum representing the status of an animation decoder. + * + * \since This enum is available since SDL_image 3.4.0. + */ +typedef enum IMG_AnimationDecoderStatus +{ + IMG_DECODER_STATUS_INVALID = -1, /**< The decoder is invalid */ + IMG_DECODER_STATUS_OK, /**< The decoder is ready to decode the next frame */ + IMG_DECODER_STATUS_FAILED, /**< The decoder failed to decode a frame, call SDL_GetError() for more information. */ + IMG_DECODER_STATUS_COMPLETE /**< No more frames available */ +} IMG_AnimationDecoderStatus; + +/** + * An object representing animation decoder. + */ +typedef struct IMG_AnimationDecoder IMG_AnimationDecoder; + +/** + * Create a decoder to read a series of images from a file. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * The file type is determined from the file extension, e.g. "file.webp" will + * be decoded using WEBP. + * + * \param file the file containing a series of images. + * \returns a new IMG_AnimationDecoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_CreateAnimationDecoderWithProperties + * \sa IMG_GetAnimationDecoderFrame + * \sa IMG_ResetAnimationDecoder + * \sa IMG_CloseAnimationDecoder + */ +extern SDL_DECLSPEC IMG_AnimationDecoder * SDLCALL IMG_CreateAnimationDecoder(const char *file); + +/** + * Create a decoder to read a series of images from an IOStream. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * If `closeio` is true, `src` will be closed before returning if this + * function fails, or when the animation decoder is closed if this function + * succeeds. + * + * \param src an SDL_IOStream containing a series of images. + * \param closeio true to close the SDL_IOStream when done, false to leave it + * open. + * \param type a filename extension that represent this data ("WEBP", etc). + * \returns a new IMG_AnimationDecoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoderWithProperties + * \sa IMG_GetAnimationDecoderFrame + * \sa IMG_ResetAnimationDecoder + * \sa IMG_CloseAnimationDecoder + */ +extern SDL_DECLSPEC IMG_AnimationDecoder * SDLCALL IMG_CreateAnimationDecoder_IO(SDL_IOStream *src, bool closeio, const char *type); + +/** + * Create an animation decoder with the specified properties. + * + * These animation types are currently supported: + * + * - ANI + * - APNG + * - AVIFS + * - GIF + * - WEBP + * + * These are the supported properties: + * + * - `IMG_PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING`: the file to load, if + * an SDL_IOStream isn't being used. This is required if + * `IMG_PROP_ANIMATION_DECODER_CREATE_IOSTREAM_POINTER` isn't set. + * - `IMG_PROP_ANIMATION_DECODER_CREATE_IOSTREAM_POINTER`: an SDL_IOStream + * containing a series of images. This should not be closed until the + * animation decoder is closed. This is required if + * `IMG_PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING` isn't set. + * - `IMG_PROP_ANIMATION_DECODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN`: true if + * closing the animation decoder should also close the associated + * SDL_IOStream. + * - `IMG_PROP_ANIMATION_DECODER_CREATE_TYPE_STRING`: the input file type, + * e.g. "webp", defaults to the file extension if + * `IMG_PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING` is set. + * + * \param props the properties of the animation decoder. + * \returns a new IMG_AnimationDecoder, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_GetAnimationDecoderFrame + * \sa IMG_ResetAnimationDecoder + * \sa IMG_CloseAnimationDecoder + */ +extern SDL_DECLSPEC IMG_AnimationDecoder * SDLCALL IMG_CreateAnimationDecoderWithProperties(SDL_PropertiesID props); + +#define IMG_PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING "SDL_image.animation_decoder.create.filename" +#define IMG_PROP_ANIMATION_DECODER_CREATE_IOSTREAM_POINTER "SDL_image.animation_decoder.create.iostream" +#define IMG_PROP_ANIMATION_DECODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN "SDL_image.animation_decoder.create.iostream.autoclose" +#define IMG_PROP_ANIMATION_DECODER_CREATE_TYPE_STRING "SDL_image.animation_decoder.create.type" +#define IMG_PROP_ANIMATION_DECODER_CREATE_TIMEBASE_NUMERATOR_NUMBER "SDL_image.animation_decoder.create.timebase.numerator" +#define IMG_PROP_ANIMATION_DECODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER "SDL_image.animation_decoder.create.timebase.denominator" + +#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_MAX_THREADS_NUMBER "SDL_image.animation_decoder.create.avif.max_threads" +#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_INCREMENTAL_BOOLEAN "SDL_image.animation_decoder.create.avif.allow_incremental" +#define IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_PROGRESSIVE_BOOLEAN "SDL_image.animation_decoder.create.avif.allow_progressive" +#define IMG_PROP_ANIMATION_DECODER_CREATE_GIF_TRANSPARENT_COLOR_INDEX_NUMBER "SDL_image.animation_encoder.create.gif.transparent_color_index" +#define IMG_PROP_ANIMATION_DECODER_CREATE_GIF_NUM_COLORS_NUMBER "SDL_image.animation_encoder.create.gif.num_colors" + +/** + * Get the properties of an animation decoder. + * + * This function returns the properties of the animation decoder, which holds + * information about the underlying image such as description, copyright text + * and loop count. + * + * \param decoder the animation decoder. + * \returns the properties ID of the animation decoder, or 0 if there are no + * properties; call SDL_GetError() for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_CreateAnimationDecoderWithProperties + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL IMG_GetAnimationDecoderProperties(IMG_AnimationDecoder* decoder); + +#define IMG_PROP_METADATA_IGNORE_PROPS_BOOLEAN "SDL_image.metadata.ignore_props" +#define IMG_PROP_METADATA_DESCRIPTION_STRING "SDL_image.metadata.description" +#define IMG_PROP_METADATA_COPYRIGHT_STRING "SDL_image.metadata.copyright" +#define IMG_PROP_METADATA_TITLE_STRING "SDL_image.metadata.title" +#define IMG_PROP_METADATA_AUTHOR_STRING "SDL_image.metadata.author" +#define IMG_PROP_METADATA_CREATION_TIME_STRING "SDL_image.metadata.creation_time" +#define IMG_PROP_METADATA_FRAME_COUNT_NUMBER "SDL_image.metadata.frame_count" +#define IMG_PROP_METADATA_LOOP_COUNT_NUMBER "SDL_image.metadata.loop_count" + +/** + * Get the next frame in an animation decoder. + * + * This function decodes the next frame in the animation decoder, returning it + * as an SDL_Surface. The returned surface should be freed with + * SDL_FreeSurface() when no longer needed. + * + * If the animation decoder has no more frames or an error occurred while + * decoding the frame, this function returns false. In that case, please call + * SDL_GetError() for more information. If SDL_GetError() returns an empty + * string, that means there are no more available frames. If SDL_GetError() + * returns a valid string, that means the decoding failed. + * + * \param decoder the animation decoder. + * \param frame a pointer filled in with the SDL_Surface for the next frame in + * the animation. + * \param duration the duration of the frame, usually in milliseconds but can + * be other units if the + * `IMG_PROP_ANIMATION_DECODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER` + * property is set when creating the decoder. + * \returns true on success or false on failure and when no more frames are + * available; call IMG_GetAnimationDecoderStatus() or SDL_GetError() + * for more information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_CreateAnimationDecoderWithProperties + * \sa IMG_GetAnimationDecoderStatus + * \sa IMG_ResetAnimationDecoder + * \sa IMG_CloseAnimationDecoder + */ +extern SDL_DECLSPEC bool SDLCALL IMG_GetAnimationDecoderFrame(IMG_AnimationDecoder *decoder, SDL_Surface **frame, Uint64 *duration); + +/** + * Get the decoder status indicating the current state of the decoder. + * + * \param decoder the decoder to get the status of. + * \returns the status of the underlying decoder, or + * IMG_DECODER_STATUS_INVALID if the given decoder is invalid. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_GetAnimationDecoderFrame + */ +extern SDL_DECLSPEC IMG_AnimationDecoderStatus SDLCALL IMG_GetAnimationDecoderStatus(IMG_AnimationDecoder *decoder); + +/** + * Reset an animation decoder. + * + * Calling this function resets the animation decoder, allowing it to start + * from the beginning again. This is useful if you want to decode the frame + * sequence again without creating a new decoder. + * + * \param decoder the decoder to reset. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_CreateAnimationDecoderWithProperties + * \sa IMG_GetAnimationDecoderFrame + * \sa IMG_CloseAnimationDecoder + */ +extern SDL_DECLSPEC bool SDLCALL IMG_ResetAnimationDecoder(IMG_AnimationDecoder *decoder); + +/** + * Close an animation decoder, finishing any decoding. + * + * Calling this function frees the animation decoder, and returns the final + * status of the decoding process. + * + * \param decoder the decoder to close. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_image 3.4.0. + * + * \sa IMG_CreateAnimationDecoder + * \sa IMG_CreateAnimationDecoder_IO + * \sa IMG_CreateAnimationDecoderWithProperties + */ +extern SDL_DECLSPEC bool SDLCALL IMG_CloseAnimationDecoder(IMG_AnimationDecoder *decoder); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/vendor/sdl3/image/libavif-16.dll b/vendor/sdl3/image/libavif-16.dll index 7fef6232a..eb235450f 100644 Binary files a/vendor/sdl3/image/libavif-16.dll and b/vendor/sdl3/image/libavif-16.dll differ diff --git a/vendor/sdl3/image/libpng16-16.dll b/vendor/sdl3/image/libpng16-16.dll new file mode 100644 index 000000000..ea1e35e61 Binary files /dev/null and b/vendor/sdl3/image/libpng16-16.dll differ diff --git a/vendor/sdl3/image/libtiff-6.dll b/vendor/sdl3/image/libtiff-6.dll index 645e446b8..0dcf40a01 100644 Binary files a/vendor/sdl3/image/libtiff-6.dll and b/vendor/sdl3/image/libtiff-6.dll differ diff --git a/vendor/sdl3/image/libwebpmux-3.dll b/vendor/sdl3/image/libwebpmux-3.dll new file mode 100644 index 000000000..4294a2394 Binary files /dev/null and b/vendor/sdl3/image/libwebpmux-3.dll differ diff --git a/vendor/sdl3/image/sdl_image.odin b/vendor/sdl3/image/sdl_image.odin index 4712c7f3c..820a7c4da 100644 --- a/vendor/sdl3/image/sdl_image.odin +++ b/vendor/sdl3/image/sdl_image.odin @@ -1,3 +1,4 @@ +// Bindings for [[ SDL3 Image ; https://wiki.libsdl.org/SDL3_image/FrontPage ]]. package sdl3_image import "core:c" @@ -10,7 +11,7 @@ when ODIN_OS == .Windows { } MAJOR_VERSION :: 3 -MINOR_VERSION :: 2 +MINOR_VERSION :: 4 PATCHLEVEL :: 0 Animation :: struct { @@ -20,6 +21,51 @@ Animation :: struct { delays: [^]c.int, } +AnimationEncoder :: struct {} + +PROP_ANIMATION_ENCODER_CREATE_FILENAME_STRING :: "SDL_image.animation_encoder.create.filename" +PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_POINTER :: "SDL_image.animation_encoder.create.iostream" +PROP_ANIMATION_ENCODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN :: "SDL_image.animation_encoder.create.iostream.autoclose" +PROP_ANIMATION_ENCODER_CREATE_TYPE_STRING :: "SDL_image.animation_encoder.create.type" +PROP_ANIMATION_ENCODER_CREATE_QUALITY_NUMBER :: "SDL_image.animation_encoder.create.quality" +PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_NUMERATOR_NUMBER :: "SDL_image.animation_encoder.create.timebase.numerator" +PROP_ANIMATION_ENCODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER :: "SDL_image.animation_encoder.create.timebase.denominator" + +PROP_ANIMATION_ENCODER_CREATE_AVIF_MAX_THREADS_NUMBER :: "SDL_image.animation_encoder.create.avif.max_threads" +PROP_ANIMATION_ENCODER_CREATE_AVIF_KEYFRAME_INTERVAL_NUMBER :: "SDL_image.animation_encoder.create.avif.keyframe_interval" +PROP_ANIMATION_ENCODER_CREATE_GIF_USE_LUT_BOOLEAN :: "SDL_image.animation_encoder.create.gif.use_lut" + +AnimationDecoderStatus :: enum c.int { + INVALID = -1, + OK, + FAILED, + COMPLETE, +} + +AnimationDecoder :: struct {} + +PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING :: "SDL_image.animation_decoder.create.filename" +PROP_ANIMATION_DECODER_CREATE_IOSTREAM_POINTER :: "SDL_image.animation_decoder.create.iostream" +PROP_ANIMATION_DECODER_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN :: "SDL_image.animation_decoder.create.iostream.autoclose" +PROP_ANIMATION_DECODER_CREATE_TYPE_STRING :: "SDL_image.animation_decoder.create.type" +PROP_ANIMATION_DECODER_CREATE_TIMEBASE_NUMERATOR_NUMBER :: "SDL_image.animation_decoder.create.timebase.numerator" +PROP_ANIMATION_DECODER_CREATE_TIMEBASE_DENOMINATOR_NUMBER :: "SDL_image.animation_decoder.create.timebase.denominator" + +PROP_ANIMATION_DECODER_CREATE_AVIF_MAX_THREADS_NUMBER :: "SDL_image.animation_decoder.create.avif.max_threads" +PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_INCREMENTAL_BOOLEAN :: "SDL_image.animation_decoder.create.avif.allow_incremental" +PROP_ANIMATION_DECODER_CREATE_AVIF_ALLOW_PROGRESSIVE_BOOLEAN :: "SDL_image.animation_decoder.create.avif.allow_progressive" +PROP_ANIMATION_DECODER_CREATE_GIF_TRANSPARENT_COLOR_INDEX_NUMBER :: "SDL_image.animation_encoder.create.gif.transparent_color_index" +PROP_ANIMATION_DECODER_CREATE_GIF_NUM_COLORS_NUMBER :: "SDL_image.animation_encoder.create.gif.num_colors" + +PROP_METADATA_IGNORE_PROPS_BOOLEAN :: "SDL_image.metadata.ignore_props" +PROP_METADATA_DESCRIPTION_STRING :: "SDL_image.metadata.description" +PROP_METADATA_COPYRIGHT_STRING :: "SDL_image.metadata.copyright" +PROP_METADATA_TITLE_STRING :: "SDL_image.metadata.title" +PROP_METADATA_AUTHOR_STRING :: "SDL_image.metadata.author" +PROP_METADATA_CREATION_TIME_STRING :: "SDL_image.metadata.creation_time" +PROP_METADATA_FRAME_COUNT_NUMBER :: "SDL_image.metadata.frame_count" +PROP_METADATA_LOOP_COUNT_NUMBER :: "SDL_image.metadata.loop_count" + @(default_calling_convention="c", link_prefix="IMG_") foreign lib { Version :: proc() -> c.int --- @@ -42,7 +88,16 @@ foreign lib { LoadTexture_IO :: proc(renderer: ^SDL.Renderer, src: ^SDL.IOStream, closeio: bool) -> ^SDL.Texture --- LoadTextureTyped_IO :: proc(renderer: ^SDL.Renderer, src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^SDL.Texture --- + /* Load an image directly into a GPU texture. */ + LoadGPUTexture :: proc(device: ^SDL.GPUDevice, copy_pass: ^SDL.GPUCopyPass, file: cstring, width: ^c.int, height: ^c.int) -> ^SDL.GPUTexture --- + LoadGPUTexture_IO :: proc(device: ^SDL.GPUDevice, copy_pass: ^SDL.GPUCopyPass, src: ^SDL.IOStream, closeio: bool, width: ^c.int, height: ^c.int) -> ^SDL.GPUTexture --- + LoadGPUTextureTyped_IO :: proc(device: ^SDL.GPUDevice, copy_pass: ^SDL.GPUCopyPass, src: ^SDL.IOStream, closeio: bool, type: cstring, width: ^c.int, height: ^c.int) -> ^SDL.GPUTexture --- + + /* Get the image currently in the clipboard. */ + GetClipboardImage :: proc() -> ^SDL.Surface --- + /* Functions to detect a file type, given a seekable source */ + isANI :: proc(src: ^SDL.IOStream) -> bool --- isAVIF :: proc(src: ^SDL.IOStream) -> bool --- isICO :: proc(src: ^SDL.IOStream) -> bool --- isCUR :: proc(src: ^SDL.IOStream) -> bool --- @@ -89,19 +144,63 @@ foreign lib { ReadXPMFromArrayToRGB888 :: proc(xpm: [^]cstring) -> ^SDL.Surface --- /* Individual saving functions */ - SaveAVIF :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.int --- - SaveAVIF_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.int --- - SavePNG :: proc(surface: ^SDL.Surface, file: cstring) -> c.int --- - SavePNG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.int --- - SaveJPG :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.int --- - SaveJPG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.int --- + Save :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveTyped_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, type: cstring) -> c.bool --- + SaveAVIF :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.bool --- + SaveAVIF_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.bool --- + SaveBMP :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveBMP_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveCUR :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveCUR_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveGIF :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveGIF_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveICO :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveICO_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveJPG :: proc(surface: ^SDL.Surface, file: cstring, quality: c.int) -> c.bool --- + SaveJPG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.bool --- + SavePNG :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SavePNG_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveTGA :: proc(surface: ^SDL.Surface, file: cstring) -> c.bool --- + SaveTGA_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveWEBP :: proc(surface: ^SDL.Surface, file: cstring, quality: f32) -> c.bool --- + SaveWEBP_IO :: proc(surface: ^SDL.Surface, dst: ^SDL.IOStream, closeio: bool, quality: f32) -> c.bool --- LoadAnimation :: proc(file: cstring) -> ^Animation --- LoadAnimation_IO :: proc(src: ^SDL.IOStream, closeio: bool) -> ^Animation --- LoadAnimationTyped_IO :: proc(src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^Animation --- + SaveAnimation :: proc(anim: ^Animation, file: cstring) -> c.bool --- + SaveAnimationTyped_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool, type: cstring) -> c.bool --- + CreateAnimatedCursor :: proc(anim: ^Animation, hot_x: c.int, hot_y: c.int) -> ^SDL.Cursor --- FreeAnimation :: proc(anim: ^Animation) --- + /* Animation encoder functions */ + CreateAnimationEncoder :: proc(file: cstring) -> ^AnimationEncoder --- + CreateAnimationEncoder_IO :: proc(dst: ^SDL.IOStream, closeio: bool, type: cstring) -> ^AnimationEncoder --- + CreateAnimationEncoderWithProperties :: proc(props: SDL.PropertiesID) -> ^AnimationEncoder --- + AddAnimationEncoderFrame :: proc(encoder: ^AnimationEncoder, surface: ^SDL.Surface, duration: u64) -> c.bool --- + CloseAnimationEncoder :: proc(encoder: ^AnimationEncoder) -> c.bool --- + + /* Animation decoder functions */ + CreateAnimationDecoder :: proc(file: cstring) -> ^AnimationDecoder --- + CreateAnimationDecoder_IO :: proc(src: ^SDL.IOStream, closeio: bool, type: cstring) -> ^AnimationDecoder --- + CreateAnimationDecoderWithProperties :: proc(props: SDL.PropertiesID) -> ^AnimationDecoder --- + GetAnimationDecoderProperties :: proc(decoder: ^AnimationDecoder) -> SDL.PropertiesID --- + GetAnimationDecoderFrame :: proc(decoder: ^AnimationDecoder, frame: ^^SDL.Surface, duration: ^u64) -> c.bool --- + GetAnimationDecoderStatus :: proc(decoder: ^AnimationDecoder) -> AnimationDecoderStatus --- + ResetAnimationDecoder :: proc(decoder: ^AnimationDecoder) -> c.bool --- + CloseAnimationDecoder :: proc(decoder: ^AnimationDecoder) -> c.bool --- + /* Individual loading functions */ + LoadANIAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- + LoadAPNGAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- + LoadAVIFAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- LoadGIFAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- LoadWEBPAnimation_IO :: proc(src: ^SDL.IOStream) -> ^Animation --- + + /* Individual saving functions */ + SaveANIAnimation_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveAPNGAnimation_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveAVIFAnimation_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.bool --- + SaveGIFAnimation_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool) -> c.bool --- + SaveWEBPAnimation_IO :: proc(anim: ^Animation, dst: ^SDL.IOStream, closeio: bool, quality: c.int) -> c.bool --- } diff --git a/vendor/sdl3/include/SDL.h b/vendor/sdl3/include/SDL.h index 9d2168877..fd13b8340 100644 --- a/vendor/sdl3/include/SDL.h +++ b/vendor/sdl3/include/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -20,7 +20,7 @@ */ /** - * Main include header for the SDL library, version 3.2.10 + * Main include header for the SDL library, version 3.4.2 * * It is almost always best to include just this one header instead of * picking out individual headers included here. There are exceptions to @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/vendor/sdl3/include/SDL_assert.h b/vendor/sdl3/include/SDL_assert.h index 6c90acc02..fb6746235 100644 --- a/vendor/sdl3/include/SDL_assert.h +++ b/vendor/sdl3/include/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -126,20 +126,17 @@ extern "C" { */ #define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner -#elif defined(_MSC_VER) && _MSC_VER >= 1310 +#elif defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1310) /* Don't include intrin.h here because it contains C++ code */ extern void __cdecl __debugbreak(void); #define SDL_TriggerBreakpoint() __debugbreak() #elif defined(_MSC_VER) && defined(_M_IX86) #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } -#elif defined(ANDROID) - #include - #define SDL_TriggerBreakpoint() assert(0) #elif SDL_HAS_BUILTIN(__builtin_debugtrap) #define SDL_TriggerBreakpoint() __builtin_debugtrap() #elif SDL_HAS_BUILTIN(__builtin_trap) #define SDL_TriggerBreakpoint() __builtin_trap() -#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) +#elif (defined(__GNUC__) || defined(__clang__) || defined(__TINYC__) || defined(__slimcc__)) && (defined(__i386__) || defined(__x86_64__)) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" ) @@ -163,7 +160,7 @@ extern "C" { #ifdef SDL_WIKI_DOCUMENTATION_SECTION /** - * A macro that reports the current function being compiled. + * A constant that contains the current function being compiled. * * If SDL can't figure how the compiler reports this, it will use "???". * @@ -171,20 +168,58 @@ extern "C" { */ #define SDL_FUNCTION __FUNCTION__ -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ +#elif !defined(SDL_FUNCTION) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ # define SDL_FUNCTION __func__ #elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__)) # define SDL_FUNCTION __FUNCTION__ #else # define SDL_FUNCTION "???" #endif +#endif + +#ifdef SDL_WIKI_DOCUMENTATION_SECTION /** * A macro that reports the current file being compiled. * + * This macro is only defined if it isn't already defined, so to override it + * (perhaps with something that doesn't provide path information at all, so + * build machine information doesn't leak into public binaries), apps can + * define this macro before including SDL.h or SDL_assert.h. + * * \since This macro is available since SDL 3.2.0. */ +#define SDL_FILE __FILE_NAME__ + +#elif !defined(SDL_FILE) +#ifdef __FILE_NAME__ +#define SDL_FILE __FILE_NAME__ +#else #define SDL_FILE __FILE__ +#endif +#endif + +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + +/** + * A macro that reports the current file being compiled, for use in + * assertions. + * + * This macro is only defined if it isn't already defined, so to override it + * (perhaps with something that doesn't provide path information at all, so + * build machine information doesn't leak into public binaries), apps can + * define this macro before including SDL_assert.h. For example, defining this + * to `""` will make sure no source path information is included in asserts. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_ASSERT_FILE SDL_FILE + +#elif !defined(SDL_ASSERT_FILE) +#define SDL_ASSERT_FILE SDL_FILE +#endif + /** * A macro that reports the current line number of the file being compiled. @@ -362,8 +397,8 @@ extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData * #define SDL_enabled_assert(condition) \ do { \ while ( !(condition) ) { \ - static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \ - const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ + static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \ + const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_ASSERT_FILE, SDL_LINE); \ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ continue; /* go again. */ \ } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ diff --git a/vendor/sdl3/include/SDL_asyncio.h b/vendor/sdl3/include/SDL_asyncio.h index b36cb071b..3c894d696 100644 --- a/vendor/sdl3/include/SDL_asyncio.h +++ b/vendor/sdl3/include/SDL_asyncio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -213,6 +213,8 @@ typedef struct SDL_AsyncIOQueue SDL_AsyncIOQueue; * \returns a pointer to the SDL_AsyncIO structure that is created or NULL on * failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CloseAsyncIO @@ -531,6 +533,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SignalAsyncIOQueue(SDL_AsyncIOQueue *queue) * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LoadFile_IO diff --git a/vendor/sdl3/include/SDL_atomic.h b/vendor/sdl3/include/SDL_atomic.h index 78b5e0fa5..1ec0753da 100644 --- a/vendor/sdl3/include/SDL_atomic.h +++ b/vendor/sdl3/include/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -596,6 +596,24 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_SetAtomicU32(SDL_AtomicU32 *a, Uint32 v); */ extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetAtomicU32(SDL_AtomicU32 *a); +/** + * Add to an atomic variable. + * + * This function also acts as a full memory barrier. + * + * ***Note: If you don't know what this function is for, you shouldn't use + * it!*** + * + * \param a a pointer to an SDL_AtomicU32 variable to be modified. + * \param v the desired value to add or subtract. + * \returns the previous value of the atomic variable. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_AddAtomicU32(SDL_AtomicU32 *a, int v); + /** * Set a pointer to a new value if it is currently an old value. * diff --git a/vendor/sdl3/include/SDL_audio.h b/vendor/sdl3/include/SDL_audio.h index c6acf885f..da797c6a8 100644 --- a/vendor/sdl3/include/SDL_audio.h +++ b/vendor/sdl3/include/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -577,6 +577,15 @@ extern SDL_DECLSPEC SDL_AudioDeviceID * SDLCALL SDL_GetAudioRecordingDevices(int /** * Get the human-readable name of a specific audio device. * + * **WARNING**: this function will work with SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK + * and SDL_AUDIO_DEVICE_DEFAULT_RECORDING, returning the current default + * physical devices' names. However, as the default device may change at any + * time, it is likely better to show a generic name to the user, like "System + * default audio device" or perhaps "default [currently %s]". Do not store + * this name to disk to reidentify the device in a later run of the program, + * as the default might change in general, and the string will be the name of + * a specific device and not the abstract system default. + * * \param devid the instance ID of the device to query. * \returns the name of the audio device, or NULL on failure; call * SDL_GetError() for more information. @@ -942,7 +951,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid); * Binding a stream to a device will set its output format for playback * devices, and its input format for recording devices, so they match the * device's settings. The caller is welcome to change the other end of the - * stream's format at any time with SDL_SetAudioStreamFormat(). + * stream's format at any time with SDL_SetAudioStreamFormat(). If the other + * end of the stream's format has never been set (the audio stream was created + * with a NULL audio spec), this function will set it to match the device + * end's format. * * \param devid an audio device to bind a stream to. * \param streams an array of audio streams to bind. @@ -1021,7 +1033,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream); /** * Query an audio stream for its currently-bound device. * - * This reports the audio device that an audio stream is currently bound to. + * This reports the logical audio device that an audio stream is currently + * bound to. * * If not bound, or invalid, this returns zero, which is not a valid device * ID. @@ -1063,6 +1076,17 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au /** * Get the properties associated with an audio stream. * + * The application can hang any data it wants here, but the following + * properties are understood by SDL: + * + * - `SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN`: if true (the default), the + * stream be automatically cleaned up when the audio subsystem quits. If set + * to false, the streams will persist beyond that. This property is ignored + * for streams created through SDL_OpenAudioDeviceStream(), and will always + * be cleaned up. Streams that are not cleaned up will still be unbound from + * devices when the audio subsystem quits. This property was added in SDL + * 3.4.0. + * * \param stream the SDL_AudioStream to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -1073,6 +1097,9 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au */ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_AudioStream *stream); +#define SDL_PROP_AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN "SDL.audiostream.auto_cleanup" + + /** * Query the current format of an audio stream. * @@ -1149,14 +1176,14 @@ extern SDL_DECLSPEC float SDLCALL SDL_GetAudioStreamFrequencyRatio(SDL_AudioStre * * The frequency ratio is used to adjust the rate at which input data is * consumed. Changing this effectively modifies the speed and pitch of the - * audio. A value greater than 1.0 will play the audio faster, and at a higher - * pitch. A value less than 1.0 will play the audio slower, and at a lower - * pitch. + * audio. A value greater than 1.0f will play the audio faster, and at a + * higher pitch. A value less than 1.0f will play the audio slower, and at a + * lower pitch. 1.0f means play at normal speed. * * This is applied during SDL_GetAudioStreamData, and can be continuously * changed to create various effects. * - * \param stream the stream the frequency ratio is being changed. + * \param stream the stream on which the frequency ratio is being changed. * \param ratio the frequency ratio. 1.0 is normal speed. Must be between 0.01 * and 100. * \returns true on success or false on failure; call SDL_GetError() for more @@ -1318,7 +1345,7 @@ extern SDL_DECLSPEC int * SDLCALL SDL_GetAudioStreamOutputChannelMap(SDL_AudioSt * \threadsafety It is safe to call this function from any thread, as it holds * a stream-specific mutex while running. Don't change the * stream's format to have a different number of channels from a - * a different thread at the same time, though! + * different thread at the same time, though! * * \since This function is available since SDL 3.2.0. * @@ -1332,7 +1359,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamInputChannelMap(SDL_AudioStre * Channel maps are optional; most things do not need them, instead passing * data in the [order that SDL expects](CategoryAudio#channel-layouts). * - * The output channel map reorders data that leaving a stream via + * The output channel map reorders data that is leaving a stream via * SDL_GetAudioStreamData. * * Each item in the array represents an input channel, and its value is the @@ -1414,6 +1441,136 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamOutputChannelMap(SDL_AudioStr */ extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len); +/** + * A callback that fires for completed SDL_PutAudioStreamDataNoCopy() data. + * + * When using SDL_PutAudioStreamDataNoCopy() to provide data to an + * SDL_AudioStream, it's not safe to dispose of the data until the stream has + * completely consumed it. Often times it's difficult to know exactly when + * this has happened. + * + * This callback fires once when the stream no longer needs the buffer, + * allowing the app to easily free or reuse it. + * + * \param userdata an opaque pointer provided by the app for their personal + * use. + * \param buf the pointer provided to SDL_PutAudioStreamDataNoCopy(). + * \param buflen the size of buffer, in bytes, provided to + * SDL_PutAudioStreamDataNoCopy(). + * + * \threadsafety This callbacks may run from any thread, so if you need to + * protect shared data, you should use SDL_LockAudioStream to + * serialize access; this lock will be held before your callback + * is called, so your callback does not need to manage the lock + * explicitly. + * + * \since This datatype is available since SDL 3.4.0. + * + * \sa SDL_SetAudioStreamGetCallback + * \sa SDL_SetAudioStreamPutCallback + */ +typedef void (SDLCALL *SDL_AudioStreamDataCompleteCallback)(void *userdata, const void *buf, int buflen); + +/** + * Add external data to an audio stream without copying it. + * + * Unlike SDL_PutAudioStreamData(), this function does not make a copy of the + * provided data, instead storing the provided pointer. This means that the + * put operation does not need to allocate and copy the data, but the original + * data must remain available until the stream is done with it, either by + * being read from the stream in its entirety, or a call to + * SDL_ClearAudioStream() or SDL_DestroyAudioStream(). + * + * The data must match the format/channels/samplerate specified in the latest + * call to SDL_SetAudioStreamFormat, or the format specified when creating the + * stream if it hasn't been changed. + * + * An optional callback may be provided, which is called when the stream no + * longer needs the data. Once this callback fires, the stream will not access + * the data again. This callback will fire for any reason the data is no + * longer needed, including clearing or destroying the stream. + * + * Note that there is still an allocation to store tracking information, so + * this function is more efficient for larger blocks of data. If you're + * planning to put a few samples at a time, it will be more efficient to use + * SDL_PutAudioStreamData(), which allocates and buffers in blocks. + * + * \param stream the stream the audio data is being added to. + * \param buf a pointer to the audio data to add. + * \param len the number of bytes to add to the stream. + * \param callback the callback function to call when the data is no longer + * needed by the stream. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread, but if the + * stream has a callback set, the caller might need to manage + * extra locking. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_ClearAudioStream + * \sa SDL_FlushAudioStream + * \sa SDL_GetAudioStreamData + * \sa SDL_GetAudioStreamQueued + */ +extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamDataNoCopy(SDL_AudioStream *stream, const void *buf, int len, SDL_AudioStreamDataCompleteCallback callback, void *userdata); + +/** + * Add data to the stream with each channel in a separate array. + * + * This data must match the format/channels/samplerate specified in the latest + * call to SDL_SetAudioStreamFormat, or the format specified when creating the + * stream if it hasn't been changed. + * + * The data will be interleaved and queued. Note that SDL_AudioStream only + * operates on interleaved data, so this is simply a convenience function for + * easily queueing data from sources that provide separate arrays. There is no + * equivalent function to retrieve planar data. + * + * The arrays in `channel_buffers` are ordered as they are to be interleaved; + * the first array will be the first sample in the interleaved data. Any + * individual array may be NULL; in this case, silence will be interleaved for + * that channel. + * + * `num_channels` specifies how many arrays are in `channel_buffers`. This can + * be used as a safety to prevent overflow, in case the stream format has + * changed elsewhere. If more channels are specified than the current input + * spec, they are ignored. If less channels are specified, the missing arrays + * are treated as if they are NULL (silence is written to those channels). If + * the count is -1, SDL will assume the array count matches the current input + * spec. + * + * Note that `num_samples` is the number of _samples per array_. This can also + * be thought of as the number of _sample frames_ to be queued. A value of 1 + * with stereo arrays will queue two samples to the stream. This is different + * than SDL_PutAudioStreamData, which wants the size of a single array in + * bytes. + * + * \param stream the stream the audio data is being added to. + * \param channel_buffers a pointer to an array of arrays, one array per + * channel. + * \param num_channels the number of arrays in `channel_buffers` or -1. + * \param num_samples the number of _samples_ per array to write to the + * stream. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread, but if the + * stream has a callback set, the caller might need to manage + * extra locking. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_ClearAudioStream + * \sa SDL_FlushAudioStream + * \sa SDL_GetAudioStreamData + * \sa SDL_GetAudioStreamQueued + */ +extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_channels, int num_samples); + /** * Get converted/resampled data from the stream. * @@ -1583,8 +1740,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioStreamDevice(SDL_AudioStream *str * previously been paused. Once unpaused, any bound audio streams will begin * to progress again, and audio can be generated. * - * Remember, SDL_OpenAudioDeviceStream opens device in a paused state, so this - * function call is required for audio playback to begin on such device. + * SDL_OpenAudioDeviceStream opens audio devices in a paused state, so this + * function call is required for audio playback to begin on such devices. * * \param stream the audio stream associated with the audio device to resume. * \returns true on success or false on failure; call SDL_GetError() for more @@ -1841,7 +1998,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream) * Also unlike other functions, the audio device begins paused. This is to map * more closely to SDL2-style behavior, since there is no extra step here to * bind a stream to begin audio flowing. The audio device should be resumed - * with `SDL_ResumeAudioStreamDevice(stream);` + * with SDL_ResumeAudioStreamDevice(). * * This function works with both playback and recording devices. * diff --git a/vendor/sdl3/include/SDL_begin_code.h b/vendor/sdl3/include/SDL_begin_code.h index a6b47cf4b..94f79099b 100644 --- a/vendor/sdl3/include/SDL_begin_code.h +++ b/vendor/sdl3/include/SDL_begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -261,9 +261,9 @@ * * On compilers without restrict support, this is defined to nothing. * - * \since This macro is available since SDL 3.2.0. + * \since This macro is available since SDL 3.4.0. */ -#define SDL_RESTRICT __restrict__ +#define SDL_RESTRICT __restrict /** * Check if the compiler supports a given builtin functionality. @@ -281,9 +281,61 @@ */ #define SDL_HAS_BUILTIN(x) __has_builtin(x) +/** + * A macro to specify data alignment. + * + * This informs the compiler that a given datatype or variable must be aligned + * to a specific byte count. + * + * For example: + * + * ```c + * // make sure this is struct is aligned to 16 bytes for SIMD access. + * typedef struct { + * float x, y, z, w; + * } SDL_ALIGNED(16) MySIMDAlignedData; + * + * // make sure this one field in a struct is aligned to 16 bytes for SIMD access. + * typedef struct { + * SomeStuff stuff; + * float SDL_ALIGNED(16) position[4]; + * SomeOtherStuff other_stuff; + * } MyStruct; + * + * // make sure this variable is aligned to 32 bytes. + * int SDL_ALIGNED(32) myval = 0; + * ``` + * + * Alignment is only guaranteed for things the compiler places: local + * variables on the stack and global/static variables. To dynamically allocate + * something that respects this alignment, use SDL_aligned_alloc() or some + * other mechanism. + * + * On compilers without alignment support, this macro is defined to an invalid + * symbol, to make it clear that the current compiler is likely to generate + * incorrect code when it sees this macro. + * + * \param x the byte count to align to, so the data's address will be a + * multiple of this value. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_ALIGNED(x) __attribute__((aligned(x))) + /* end of wiki documentation section. */ #endif +/* `restrict` is from C99, but __restrict works with both Visual Studio and GCC. */ +#ifndef SDL_RESTRICT +# if defined(restrict) || ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))) +# define SDL_RESTRICT restrict +# elif defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__) +# define SDL_RESTRICT __restrict +# else +# define SDL_RESTRICT +# endif +#endif + #ifndef SDL_HAS_BUILTIN #ifdef __has_builtin #define SDL_HAS_BUILTIN(x) __has_builtin(x) @@ -379,7 +431,7 @@ #endif /* SDL_INLINE not defined */ #ifndef SDL_FORCE_INLINE -#ifdef _MSC_VER +#if defined(_MSC_VER) && (_MSC_VER >= 1200) #define SDL_FORCE_INLINE __forceinline #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) #define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ @@ -389,7 +441,7 @@ #endif /* SDL_FORCE_INLINE not defined */ #ifndef SDL_NORETURN -#ifdef __GNUC__ +#if defined(__GNUC__) #define SDL_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) #define SDL_NORETURN __declspec(noreturn) @@ -484,3 +536,18 @@ #define SDL_ALLOC_SIZE2(p1, p2) #endif #endif /* SDL_ALLOC_SIZE2 not defined */ + +#ifndef SDL_ALIGNED +#if defined(__clang__) || defined(__GNUC__) +#define SDL_ALIGNED(x) __attribute__((aligned(x))) +#elif defined(_MSC_VER) +#define SDL_ALIGNED(x) __declspec(align(x)) +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +#define SDL_ALIGNED(x) alignas(x) +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define SDL_ALIGNED(x) _Alignas(x) +#else +#define SDL_ALIGNED(x) PLEASE_DEFINE_SDL_ALIGNED +#endif +#endif /* SDL_ALIGNED not defined */ + diff --git a/vendor/sdl3/include/SDL_bits.h b/vendor/sdl3/include/SDL_bits.h index 7435ce6d9..ddb5cdbab 100644 --- a/vendor/sdl3/include/SDL_bits.h +++ b/vendor/sdl3/include/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_blendmode.h b/vendor/sdl3/include/SDL_blendmode.h index 8f00cbcaf..84cf622cb 100644 --- a/vendor/sdl3/include/SDL_blendmode.h +++ b/vendor/sdl3/include/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_camera.h b/vendor/sdl3/include/SDL_camera.h index 5f3911fdf..14ea647a7 100644 --- a/vendor/sdl3/include/SDL_camera.h +++ b/vendor/sdl3/include/SDL_camera.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -119,7 +119,7 @@ typedef struct SDL_CameraSpec int width; /**< Frame width */ int height; /**< Frame height */ int framerate_numerator; /**< Frame rate numerator ((num / denom) == FPS, (denom / num) == duration in seconds) */ - int framerate_denominator; /**< Frame rate demoninator ((num / denom) == FPS, (denom / num) == duration in seconds) */ + int framerate_denominator; /**< Frame rate denominator ((num / denom) == FPS, (denom / num) == duration in seconds) */ } SDL_CameraSpec; /** @@ -136,6 +136,20 @@ typedef enum SDL_CameraPosition SDL_CAMERA_POSITION_BACK_FACING } SDL_CameraPosition; +/** + * The current state of a request for camera access. + * + * \since This enum is available since SDL 3.4.0. + * + * \sa SDL_GetCameraPermissionState + */ +typedef enum SDL_CameraPermissionState +{ + SDL_CAMERA_PERMISSION_STATE_DENIED = -1, + SDL_CAMERA_PERMISSION_STATE_PENDING, + SDL_CAMERA_PERMISSION_STATE_APPROVED, +} SDL_CameraPermissionState; + /** * Use this function to get the number of built-in camera drivers. @@ -346,8 +360,9 @@ extern SDL_DECLSPEC SDL_Camera * SDLCALL SDL_OpenCamera(SDL_CameraID instance_id * on others the approval might be implicit and not alert the user at all. * * This function can be used to check the status of that approval. It will - * return 0 if still waiting for user response, 1 if the camera is approved - * for use, and -1 if the user denied access. + * return SDL_CAMERA_PERMISSION_STATE_PENDING if waiting for user response, + * SDL_CAMERA_PERMISSION_STATE_APPROVED if the camera is approved for use, and + * SDL_CAMERA_PERMISSION_STATE_DENIED if the user denied access. * * Instead of polling with this function, you can wait for a * SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event @@ -358,8 +373,9 @@ extern SDL_DECLSPEC SDL_Camera * SDLCALL SDL_OpenCamera(SDL_CameraID instance_id * SDL_CloseCamera() to dispose of it. * * \param camera the opened camera device to query. - * \returns -1 if user denied access to the camera, 1 if user approved access, - * 0 if no decision has been made yet. + * \returns an SDL_CameraPermissionState value indicating if access is + * granted, or `SDL_CAMERA_PERMISSION_STATE_PENDING` if the decision + * is still pending. * * \threadsafety It is safe to call this function from any thread. * @@ -368,7 +384,7 @@ extern SDL_DECLSPEC SDL_Camera * SDLCALL SDL_OpenCamera(SDL_CameraID instance_id * \sa SDL_OpenCamera * \sa SDL_CloseCamera */ -extern SDL_DECLSPEC int SDLCALL SDL_GetCameraPermissionState(SDL_Camera *camera); +extern SDL_DECLSPEC SDL_CameraPermissionState SDLCALL SDL_GetCameraPermissionState(SDL_Camera *camera); /** * Get the instance ID of an opened camera. diff --git a/vendor/sdl3/include/SDL_clipboard.h b/vendor/sdl3/include/SDL_clipboard.h index 0d3cbb499..696825376 100644 --- a/vendor/sdl3/include/SDL_clipboard.h +++ b/vendor/sdl3/include/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -106,7 +106,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text); /** * Get UTF-8 text from the clipboard. * - * This functions returns an empty string if there was not enough memory left + * This function returns an empty string if there is not enough memory left * for a copy of the clipboard's content. * * \returns the clipboard text on success or an empty string on failure; call @@ -155,7 +155,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text); /** * Get UTF-8 text from the primary selection. * - * This functions returns an empty string if there was not enough memory left + * This function returns an empty string if there is not enough memory left * for a copy of the primary selection's content. * * \returns the primary selection text on success or an empty string on @@ -194,15 +194,14 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void); * clipboard is cleared or new data is set. The clipboard is automatically * cleared in SDL_Quit(). * - * \param userdata a pointer to provided user data. + * \param userdata a pointer to the provided user data. * \param mime_type the requested mime-type. * \param size a pointer filled in with the length of the returned data. * \returns a pointer to the data for the provided mime-type. Returning NULL - * or setting length to 0 will cause no data to be sent to the - * "receiver". It is up to the receiver to handle this. Essentially - * returning no data is more or less undefined behavior and may cause - * breakage in receiving applications. The returned data will not be - * freed so it needs to be retained and dealt with internally. + * or setting the length to 0 will cause zero length data to be sent + * to the "receiver", which should be able to handle this. The + * returned data will not be freed, so it needs to be retained and + * dealt with internally. * * \since This function is available since SDL 3.2.0. * @@ -211,10 +210,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void); typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size); /** - * Callback function that will be called when the clipboard is cleared, or new - * data is set. + * Callback function that will be called when the clipboard is cleared, or + * when new data is set. * - * \param userdata a pointer to provided user data. + * \param userdata a pointer to the provided user data. * * \since This function is available since SDL 3.2.0. * @@ -231,7 +230,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata); * respond with the data for the requested mime-type. * * The size of text data does not include any terminator, and the text does - * not need to be null terminated (e.g. you can directly copy a portion of a + * not need to be null-terminated (e.g., you can directly copy a portion of a * document). * * \param callback a function pointer to the function that provides the @@ -239,7 +238,8 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata); * \param cleanup a function pointer to the function that cleans up the * clipboard data. * \param userdata an opaque pointer that will be forwarded to the callbacks. - * \param mime_types a list of mime-types that are being offered. + * \param mime_types a list of mime-types that are being offered. SDL copies + * the given list. * \param num_mime_types the number of mime-types in the mime_types list. * \returns true on success or false on failure; call SDL_GetError() for more * information. @@ -269,10 +269,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void); /** - * Get the data from clipboard for a given mime type. + * Get the data from the clipboard for a given mime type. * * The size of text data does not include the terminator, but the text is - * guaranteed to be null terminated. + * guaranteed to be null-terminated. * * \param mime_type the mime type to read from the clipboard. * \param size a pointer filled in with the length of the returned data. @@ -292,8 +292,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, s /** * Query whether there is data in the clipboard for the provided mime type. * - * \param mime_type the mime type to check for data for. - * \returns true if there exists data in clipboard for the provided mime type, + * \param mime_type the mime type to check for data. + * \returns true if data exists in the clipboard for the provided mime type, * false if it does not. * * \threadsafety This function should only be called on the main thread. @@ -310,7 +310,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type); * * \param num_mime_types a pointer filled with the number of mime types, may * be NULL. - * \returns a null terminated array of strings with mime types, or NULL on + * \returns a null-terminated array of strings with mime types, or NULL on * failure; call SDL_GetError() for more information. This should be * freed with SDL_free() when it is no longer needed. * diff --git a/vendor/sdl3/include/SDL_close_code.h b/vendor/sdl3/include/SDL_close_code.h index da1dea7fa..ad9daa6d4 100644 --- a/vendor/sdl3/include/SDL_close_code.h +++ b/vendor/sdl3/include/SDL_close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_copying.h b/vendor/sdl3/include/SDL_copying.h index 747bd3570..dd9dbc7ee 100644 --- a/vendor/sdl3/include/SDL_copying.h +++ b/vendor/sdl3/include/SDL_copying.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_cpuinfo.h b/vendor/sdl3/include/SDL_cpuinfo.h index 1745bd934..5669c2373 100644 --- a/vendor/sdl3/include/SDL_cpuinfo.h +++ b/vendor/sdl3/include/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -344,6 +344,27 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetSystemRAM(void); */ extern SDL_DECLSPEC size_t SDLCALL SDL_GetSIMDAlignment(void); +/** + * Report the size of a page of memory. + * + * Different platforms might have different memory page sizes. In current + * times, 4 kilobytes is not unusual, but newer systems are moving to larger + * page sizes, and esoteric platforms might have any unexpected size. + * + * Note that this function can return 0, which means SDL can't determine the + * page size on this platform. It will _not_ set an error string to be + * retrieved with SDL_GetError() in this case! In this case, defaulting to + * 4096 is often a reasonable option. + * + * \returns the size of a single page of memory, in bytes, or 0 if SDL can't + * determine this information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetSystemPageSize(void); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/vendor/sdl3/include/SDL_dialog.h b/vendor/sdl3/include/SDL_dialog.h index ddb9e24d5..1e01347bf 100644 --- a/vendor/sdl3/include/SDL_dialog.h +++ b/vendor/sdl3/include/SDL_dialog.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -139,10 +139,12 @@ typedef void (SDLCALL *SDL_DialogFileCallback)(void *userdata, const char * cons * it will be invoked. * \param window the window that the dialog should be modal for, may be NULL. * Not all platforms support this option. - * \param filters a list of filters, may be NULL. Not all platforms support - * this option, and platforms that do support it may allow the - * user to ignore the filters. If non-NULL, it must remain - * valid at least until the callback is invoked. + * \param filters a list of filters, may be NULL. See the + * [`SDL_DialogFileFilter`](SDL_DialogFileFilter#code-examples) + * documentation for examples]. Not all platforms support this + * option, and platforms that do support it may allow the user + * to ignore the filters. If non-NULL, it must remain valid at + * least until the callback is invoked. * \param nfilters the number of filters. Ignored if filters is NULL. * \param default_location the default folder or file to start the dialog at, * may be NULL. Not all platforms support this option. diff --git a/vendor/sdl3/include/SDL_dlopennote.h b/vendor/sdl3/include/SDL_dlopennote.h new file mode 100644 index 000000000..299435a5d --- /dev/null +++ b/vendor/sdl3/include/SDL_dlopennote.h @@ -0,0 +1,234 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2026 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* WIKI CATEGORY: DlopenNotes */ + +/** + * # CategoryDlopenNotes + * + * This header allows you to annotate your code so external tools know about + * dynamic shared library dependencies. + * + * If you determine that your toolchain doesn't support dlopen notes, you can + * disable this feature by defining `SDL_DISABLE_DLOPEN_NOTES`. You can use + * this CMake snippet to check for support: + * + * ```cmake + * include(CheckCSourceCompiles) + * find_package(SDL3 REQUIRED CONFIG COMPONENTS Headers) + * list(APPEND CMAKE_REQUIRED_LIBRARIES SDL3::Headers) + * check_c_source_compiles([==[ + * #include + * SDL_ELF_NOTE_DLOPEN("sdl-video", + * "Support for video through SDL", + * SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, + * "libSDL-1.2.so.0", "libSDL-2.0.so.0", "libSDL3.so.0" + * ) + * int main(int argc, char *argv[]) { + * return argc + argv[0][1]; + * } + * ]==] COMPILER_SUPPORTS_SDL_ELF_NOTE_DLOPEN) + * if(NOT COMPILER_SUPPORTS_SDL_ELF_NOTE_DLOPEN) + * add_compile_definitions(-DSDL_DISABLE_DLOPEN_NOTE) + * endif() + * ``` + */ + +#ifndef SDL_dlopennote_h +#define SDL_dlopennote_h + +/** + * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared + * library dependency is optional. + * + * Optional functionality uses the dependency, the binary will work and the + * dependency is only needed for full-featured installations. + * + * \since This macro is available since SDL 3.4.0. + * + * \sa SDL_ELF_NOTE_DLOPEN + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED + */ +#define SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED "suggested" + +/** + * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared + * library dependency is recommended. + * + * Important functionality needs the dependency, the binary will work but in + * most cases the dependency should be provided. + * + * \since This macro is available since SDL 3.4.0. + * + * \sa SDL_ELF_NOTE_DLOPEN + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED + */ +#define SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED "recommended" + +/** + * Use this macro with SDL_ELF_NOTE_DLOPEN() to note that a dynamic shared + * library dependency is required. + * + * Core functionality needs the dependency, the binary will not work if it + * cannot be found. + * + * \since This macro is available since SDL 3.4.0. + * + * \sa SDL_ELF_NOTE_DLOPEN + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED + */ +#define SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED "required" + + +#if !defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_ANDROID) +/* The dlopen note functionality isn't used on this platform */ +#ifndef SDL_DISABLE_DLOPEN_NOTES +#define SDL_DISABLE_DLOPEN_NOTES +#endif +#elif defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)) +/* gcc < 3.1 too old */ +#ifndef SDL_DISABLE_DLOPEN_NOTES +#define SDL_DISABLE_DLOPEN_NOTES +#endif +#endif /* SDL_PLATFORM_UNIX || SDL_PLATFORM_ANDROID */ + +#if defined(__ELF__) && !defined(SDL_DISABLE_DLOPEN_NOTES) + +#include + +#define SDL_ELF_NOTE_DLOPEN_VENDOR "FDO" +#define SDL_ELF_NOTE_DLOPEN_TYPE 0x407c0c0aU + +#define SDL_ELF_NOTE_INTERNAL2(json, variable_name) \ + __attribute__((aligned(4), used, section(".note.dlopen"))) \ + static const struct { \ + struct { \ + Uint32 n_namesz; \ + Uint32 n_descsz; \ + Uint32 n_type; \ + } nhdr; \ + char name[4]; \ + __attribute__((aligned(4))) char dlopen_json[sizeof(json)]; \ + } variable_name = { \ + { \ + sizeof(SDL_ELF_NOTE_DLOPEN_VENDOR), \ + sizeof(json), \ + SDL_ELF_NOTE_DLOPEN_TYPE \ + }, \ + SDL_ELF_NOTE_DLOPEN_VENDOR, \ + json \ + } + +#define SDL_ELF_NOTE_INTERNAL(json, variable_name) \ + SDL_ELF_NOTE_INTERNAL2(json, variable_name) + +#define SDL_DLNOTE_JSON_ARRAY1(N1) "[\"" N1 "\"]" +#define SDL_DLNOTE_JSON_ARRAY2(N1,N2) "[\"" N1 "\",\"" N2 "\"]" +#define SDL_DLNOTE_JSON_ARRAY3(N1,N2,N3) "[\"" N1 "\",\"" N2 "\",\"" N3 "\"]" +#define SDL_DLNOTE_JSON_ARRAY4(N1,N2,N3,N4) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\"]" +#define SDL_DLNOTE_JSON_ARRAY5(N1,N2,N3,N4,N5) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\"]" +#define SDL_DLNOTE_JSON_ARRAY6(N1,N2,N3,N4,N5,N6) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\"]" +#define SDL_DLNOTE_JSON_ARRAY7(N1,N2,N3,N4,N5,N6,N7) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\",\"" N7 "\"]" +#define SDL_DLNOTE_JSON_ARRAY8(N1,N2,N3,N4,N5,N6,N7,N8) "[\"" N1 "\",\"" N2 "\",\"" N3 "\",\"" N4 "\",\"" N5 "\",\"" N6 "\",\"" N7 "\",\"" N8 "\"]" +#define SDL_DLNOTE_JSON_ARRAY_GET(N1,N2,N3,N4,N5,N6,N7,N8,NAME,...) NAME +#define SDL_DLNOTE_JSON_ARRAY(...) \ + SDL_DLNOTE_JSON_ARRAY_GET( \ + __VA_ARGS__, \ + SDL_DLNOTE_JSON_ARRAY8, \ + SDL_DLNOTE_JSON_ARRAY7, \ + SDL_DLNOTE_JSON_ARRAY6, \ + SDL_DLNOTE_JSON_ARRAY5, \ + SDL_DLNOTE_JSON_ARRAY4, \ + SDL_DLNOTE_JSON_ARRAY3, \ + SDL_DLNOTE_JSON_ARRAY2, \ + SDL_DLNOTE_JSON_ARRAY1 \ + )(__VA_ARGS__) + +/* Create "unique" variable name using __LINE__, + * so creating multiple elf notes on the same line is not supported + */ +#define SDL_DLNOTE_JOIN2(A,B) A##B +#define SDL_DLNOTE_JOIN(A,B) SDL_DLNOTE_JOIN2(A,B) +#define SDL_DLNOTE_UNIQUE_NAME SDL_DLNOTE_JOIN(s_SDL_dlopen_note_, __LINE__) + +/** + * Add a note that your application has dynamic shared library dependencies. + * + * You can do this by adding the following to the global scope: + * + * ```c + * SDL_ELF_NOTE_DLOPEN( + * "png", + * "Support for loading PNG images using libpng (required for APNG)", + * SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED, + * "libpng12.so.0" + * ) + * ``` + * + * A trailing semicolon is not needed. + * + * Or if you support multiple versions of a library, you can list them: + * + * ```c + * // Our app supports SDL1, SDL2, and SDL3 by dynamically loading them + * SDL_ELF_NOTE_DLOPEN( + * "SDL", + * "Create windows through SDL video backend", + * SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED + * "libSDL-1.2.so.0", "libSDL2-2.0.so.0", "libSDL3.so.0" + * ) + * ``` + * + * This macro is not available for compilers that do not support variadic + * macro's. + * + * \since This macro is available since SDL 3.4.0. + * + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED + * \sa SDL_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED + */ +#define SDL_ELF_NOTE_DLOPEN(feature, description, priority, ...) \ + SDL_ELF_NOTE_INTERNAL( \ + "[{\"feature\":\"" feature \ + "\",\"description\":\"" description \ + "\",\"priority\":\"" priority \ + "\",\"soname\":" SDL_DLNOTE_JSON_ARRAY(__VA_ARGS__) "}]", \ + SDL_DLNOTE_UNIQUE_NAME); + +#elif defined(__GNUC__) && __GNUC__ < 3 + +#define SDL_ELF_NOTE_DLOPEN(args...) + +#elif defined(_MSC_VER) && _MSC_VER < 1400 + +/* Variadic macros are not supported */ + +#else + +#define SDL_ELF_NOTE_DLOPEN(...) + +#endif + +#endif /* SDL_dlopennote_h */ diff --git a/vendor/sdl3/include/SDL_egl.h b/vendor/sdl3/include/SDL_egl.h index 65d4e967a..1371c4d01 100644 --- a/vendor/sdl3/include/SDL_egl.h +++ b/vendor/sdl3/include/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_endian.h b/vendor/sdl3/include/SDL_endian.h index a34e9d4b0..957ea20c3 100644 --- a/vendor/sdl3/include/SDL_endian.h +++ b/vendor/sdl3/include/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -46,7 +46,7 @@ #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ -#ifdef __clang__ +#if defined(__clang__) && !SDL_HAS_BUILTIN(_m_prefetch) #ifndef __PRFCHWINTRIN_H #define __PRFCHWINTRIN_H static __inline__ void __attribute__((__always_inline__, __nodebug__)) @@ -128,7 +128,7 @@ _m_prefetch(void *__P) * \sa SDL_BIG_ENDIAN */ #define SDL_BYTEORDER SDL_LIL_ENDIAN___or_maybe___SDL_BIG_ENDIAN -#elif defined(SDL_PLATFORM_LINUX) +#elif defined(SDL_PLATFORM_LINUX) || defined(__GLIBC__) #include #define SDL_BYTEORDER __BYTE_ORDER #elif defined(SDL_PLATFORM_SOLARIS) @@ -252,7 +252,7 @@ SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) #elif defined(__x86_64__) SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) { - __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x)); + __asm__("xchgb %b0,%h0": "=abcd"(x):"0"(x)); return x; } #elif (defined(__powerpc__) || defined(__ppc__)) @@ -486,7 +486,7 @@ SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return x_but_byteswapped; } * * \since This function is available since SDL 3.2.0. */ -SDL_FORCE_INLINE Uint32 SDL_Swap64(Uint64 x) { return x_but_byteswapped; } +SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) { return x_but_byteswapped; } /** * Swap a 16-bit value from littleendian to native byte order. diff --git a/vendor/sdl3/include/SDL_error.h b/vendor/sdl3/include/SDL_error.h index 934967c1c..3453818cb 100644 --- a/vendor/sdl3/include/SDL_error.h +++ b/vendor/sdl3/include/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_events.h b/vendor/sdl3/include/SDL_events.h index 56a2194b3..d82a615f8 100644 --- a/vendor/sdl3/include/SDL_events.h +++ b/vendor/sdl3/include/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -30,7 +30,7 @@ * coming and going, the system changing in some way, etc. * * An app generally takes a moment, perhaps at the start of a new frame, to - * examine any events that have occured since the last time and process or + * examine any events that have occurred since the last time and process or * ignore them. This is generally done by calling SDL_PollEvent() in a loop * until it returns false (or, if using the main callbacks, events are * provided one at a time in calls to SDL_AppEvent() before the next call to @@ -127,15 +127,17 @@ typedef enum SDL_EventType SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, /**< Display has changed desktop mode */ SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, /**< Display has changed current mode */ SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */ + SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, /**< Display has changed usable bounds */ SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION, - SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, + SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, /* Window events */ /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */ /* 0x201 was SDL_SYSWMEVENT, reserve the number for sdl2-compat */ SDL_EVENT_WINDOW_SHOWN = 0x202, /**< Window has been shown */ SDL_EVENT_WINDOW_HIDDEN, /**< Window has been hidden */ - SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn, and can be redrawn directly from event watchers for this event */ + SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn, and can be redrawn directly from event watchers for this event. + data1 is 1 for live-resize expose events, 0 otherwise. */ SDL_EVENT_WINDOW_MOVED, /**< Window has been moved to data1, data2 */ SDL_EVENT_WINDOW_RESIZED, /**< Window has been resized to data1xdata2 */ SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED,/**< The pixel size of the window has changed to data1xdata2 */ @@ -174,6 +176,8 @@ typedef enum SDL_EventType SDL_EVENT_KEYBOARD_ADDED, /**< A new keyboard has been inserted into the system */ SDL_EVENT_KEYBOARD_REMOVED, /**< A keyboard has been removed */ SDL_EVENT_TEXT_EDITING_CANDIDATES, /**< Keyboard text editing candidates */ + SDL_EVENT_SCREEN_KEYBOARD_SHOWN, /**< The on-screen keyboard has been shown */ + SDL_EVENT_SCREEN_KEYBOARD_HIDDEN, /**< The on-screen keyboard has been hidden */ /* Mouse events */ SDL_EVENT_MOUSE_MOTION = 0x400, /**< Mouse moved */ @@ -214,10 +218,15 @@ typedef enum SDL_EventType SDL_EVENT_FINGER_MOTION, SDL_EVENT_FINGER_CANCELED, + /* Pinch events */ + SDL_EVENT_PINCH_BEGIN = 0x710, /**< Pinch gesture started */ + SDL_EVENT_PINCH_UPDATE, /**< Pinch gesture updated */ + SDL_EVENT_PINCH_END, /**< Pinch gesture ended */ + /* 0x800, 0x801, and 0x802 were the Gesture events from SDL2. Do not reuse these values! sdl2-compat needs them! */ /* Clipboard events */ - SDL_EVENT_CLIPBOARD_UPDATE = 0x900, /**< The clipboard or primary selection changed */ + SDL_EVENT_CLIPBOARD_UPDATE = 0x900, /**< The clipboard changed */ /* Drag and drop events */ SDL_EVENT_DROP_FILE = 0x1000, /**< The system requests a file open */ @@ -298,7 +307,7 @@ typedef struct SDL_CommonEvent */ typedef struct SDL_DisplayEvent { - SDL_EventType type; /**< SDL_DISPLAYEVENT_* */ + SDL_EventType type; /**< SDL_EVENT_DISPLAY_* */ Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_DisplayID displayID;/**< The associated display */ @@ -492,6 +501,8 @@ typedef struct SDL_MouseWheelEvent SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ float mouse_x; /**< X coordinate, relative to window */ float mouse_y; /**< Y coordinate, relative to window */ + Sint32 integer_x; /**< The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12) */ + Sint32 integer_y; /**< The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12) */ } SDL_MouseWheelEvent; /** @@ -702,6 +713,10 @@ typedef struct SDL_GamepadSensorEvent /** * Audio device event structure (event.adevice.*) * + * Note that SDL will send a SDL_EVENT_AUDIO_DEVICE_ADDED event for every + * device it discovers during initialization. After that, this event will only + * arrive when a device is hotplugged during the program's run. + * * \since This struct is available since SDL 3.2.0. */ typedef struct SDL_AudioDeviceEvent @@ -779,7 +794,19 @@ typedef struct SDL_TouchFingerEvent } SDL_TouchFingerEvent; /** - * Pressure-sensitive pen proximity event structure (event.pmotion.*) + * Pinch event structure (event.pinch.*) + */ +typedef struct SDL_PinchFingerEvent +{ + SDL_EventType type; /**< ::SDL_EVENT_PINCH_BEGIN or ::SDL_EVENT_PINCH_UPDATE or ::SDL_EVENT_PINCH_END */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + float scale; /**< The scale change since the last SDL_EVENT_PINCH_UPDATE. Scale < 1 is "zoom out". Scale > 1 is "zoom in". */ + SDL_WindowID windowID; /**< The window underneath the finger, if any */ +} SDL_PinchFingerEvent; + +/** + * Pressure-sensitive pen proximity event structure (event.pproximity.*) * * When a pen becomes visible to the system (it is close enough to a tablet, * etc), SDL will send an SDL_EVENT_PEN_PROXIMITY_IN event with the new pen's @@ -791,6 +818,9 @@ typedef struct SDL_TouchFingerEvent * is there." The pen touching and lifting off from the tablet while not * leaving the area are handled by SDL_EVENT_PEN_DOWN and SDL_EVENT_PEN_UP. * + * Not all platforms have a window associated with the pen during proximity + * events. Some wait until motion/button/etc events to offer this info. + * * \since This struct is available since SDL 3.2.0. */ typedef struct SDL_PenProximityEvent @@ -965,7 +995,7 @@ typedef struct SDL_QuitEvent */ typedef struct SDL_UserEvent { - Uint32 type; /**< SDL_EVENT_USER through SDL_EVENT_LAST-1, Uint32 because these are not in the SDL_EventType enumeration */ + Uint32 type; /**< SDL_EVENT_USER through SDL_EVENT_LAST, Uint32 because these are not in the SDL_EventType enumeration */ Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The associated window if any */ @@ -1015,6 +1045,7 @@ typedef union SDL_Event SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_PinchFingerEvent pinch; /**< Pinch event data */ SDL_PenProximityEvent pproximity; /**< Pen proximity event data */ SDL_PenTouchEvent ptouch; /**< Pen tip touching event data */ SDL_PenMotionEvent pmotion; /**< Pen motion event data */ @@ -1041,7 +1072,7 @@ typedef union SDL_Event } SDL_Event; /* Make sure we haven't broken binary compatibility */ -SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding)); +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof((SDL_static_cast(SDL_Event *, NULL))->padding)); /* Function prototypes */ @@ -1225,15 +1256,13 @@ extern SDL_DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType) * Poll for currently pending events. * * If `event` is not NULL, the next event is removed from the queue and stored - * in the SDL_Event structure pointed to by `event`. The 1 returned refers to - * this event, immediately stored in the SDL Event structure -- not an event - * to follow. + * in the SDL_Event structure pointed to by `event`. * - * If `event` is NULL, it simply returns 1 if there is an event in the queue, + * If `event` is NULL, it simply returns true if there is an event in the queue, * but will not remove it from the queue. * * As this function may implicitly call SDL_PumpEvents(), you can only call - * this function in the thread that set the video mode. + * this function in the thread that initialized the video subsystem. * * SDL_PollEvent() is the favored way of receiving system events since it can * be done from the main loop and does not suspend the main loop while waiting @@ -1253,6 +1282,13 @@ extern SDL_DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType) * } * ``` * + * Note that Windows (and possibly other platforms) has a quirk about how it + * handles events while dragging/resizing a window, which can cause this + * function to block for significant amounts of time. Technical explanations + * and solutions are discussed on the wiki: + * + * https://wiki.libsdl.org/SDL3/AppFreezeDuringDrag + * * \param event the SDL_Event structure to be filled with the next event from * the queue, or NULL. * \returns true if this got an event or false if there are none available. @@ -1389,7 +1425,10 @@ typedef bool (SDLCALL *SDL_EventFilter)(void *userdata, SDL_Event *event); * allows selective filtering of dynamically arriving events. * * **WARNING**: Be very careful of what you do in the event filter function, - * as it may run in a different thread! + * as it may run in a different thread! The exception is handling of + * SDL_EVENT_WINDOW_EXPOSED, which is guaranteed to be sent from the OS on the + * main thread and you are expected to redraw your window in response to this + * event. * * On platforms that support it, if the quit event is generated by an * interrupt signal (e.g. pressing Ctrl-C), it will be delivered to the @@ -1402,7 +1441,7 @@ typedef bool (SDLCALL *SDL_EventFilter)(void *userdata, SDL_Event *event); * the event filter, but events pushed onto the queue with SDL_PeepEvents() do * not. * - * \param filter an SDL_EventFilter function to call when an event happens. + * \param filter a function to call when an event happens. * \param userdata a pointer that is passed to `filter`. * * \threadsafety It is safe to call this function from any thread. @@ -1565,6 +1604,38 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); */ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromEvent(const SDL_Event *event); +/** + * Generate an English description of an event. + * + * This will fill `buf` with a null-terminated string that might look + * something like this: + * + * ``` + * SDL_EVENT_MOUSE_MOTION (timestamp=1140256324 windowid=2 which=0 state=0 x=492.99 y=139.09 xrel=52 yrel=6) + * ``` + * + * The exact format of the string is not guaranteed; it is intended for + * logging purposes, to be read by a human, and not parsed by a computer. + * + * The returned value follows the same rules as SDL_snprintf(): `buf` will + * always be NULL-terminated (unless `buflen` is zero), and will be truncated + * if `buflen` is too small. The return code is the number of bytes needed for + * the complete string, not counting the NULL-terminator, whether the string + * was truncated or not. Unlike SDL_snprintf(), though, this function never + * returns -1. + * + * \param event an event to describe. May be NULL. + * \param buf the buffer to fill with the description string. May be NULL. + * \param buflen the maximum bytes that can be written to `buf`. + * \returns number of bytes needed for the full string, not counting the + * null-terminator byte. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetEventDescription(const SDL_Event *event, char *buf, int buflen); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/vendor/sdl3/include/SDL_filesystem.h b/vendor/sdl3/include/SDL_filesystem.h index af3ca27e0..006293554 100644 --- a/vendor/sdl3/include/SDL_filesystem.h +++ b/vendor/sdl3/include/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -77,6 +77,9 @@ extern "C" { * - `parent`: the containing directory of the bundle. For example: * `/Applications/SDLApp/` * + * **Android Specific Functionality**: This function returns "./", which + * allows filesystem operations to use internal storage and the asset system. + * * **Nintendo 3DS Specific Functionality**: This function returns "romfs" * directory of the application as it is uncommon to store resources outside * the executable. As such it is not a writable directory. @@ -89,6 +92,8 @@ extern "C" { * doesn't implement this functionality, call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetPrefPath @@ -134,6 +139,12 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetBasePath(void); * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. * + * Due to historical mistakes, `org` is allowed to be NULL or "". In such + * cases, SDL will omit the org subdirectory, including on platforms where it + * shouldn't, and including on platforms where this would make your app fail + * certification for an app store. New apps should definitely specify a real + * string for `org`. + * * The returned path is guaranteed to end with a path separator ('\\' on * Windows, '/' on most other platforms). * @@ -144,6 +155,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetBasePath(void); * etc.). This should be freed with SDL_free() when it is no longer * needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetBasePath @@ -216,6 +229,8 @@ typedef enum SDL_Folder * \returns either a null-terminated C string containing the full path to the * folder, or NULL if an error happened. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC const char * SDLCALL SDL_GetUserFolder(SDL_Folder folder); @@ -227,8 +242,7 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetUserFolder(SDL_Folder folder); * Types of filesystem entries. * * Note that there may be other sorts of items on a filesystem: devices, - * symlinks, named pipes, etc. They are currently reported as - * SDL_PATHTYPE_OTHER. + * named pipes, etc. They are currently reported as SDL_PATHTYPE_OTHER. * * \since This enum is available since SDL 3.2.0. * @@ -283,6 +297,8 @@ typedef Uint32 SDL_GlobFlags; * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_CreateDirectory(const char *path); @@ -346,6 +362,8 @@ typedef SDL_EnumerationResult (SDLCALL *SDL_EnumerateDirectoryCallback)(void *us * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata); @@ -360,6 +378,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateDirectory(const char *path, SDL_En * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_RemovePath(const char *path); @@ -367,7 +387,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RemovePath(const char *path); /** * Rename a file or directory. * - * If the file at `newpath` already exists, it will replaced. + * If the file at `newpath` already exists, it will be replaced. * * Note that this will not copy files across filesystems/drives/volumes, as * that is a much more complicated (and possibly time-consuming) operation. @@ -383,6 +403,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RemovePath(const char *path); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_RenamePath(const char *oldpath, const char *newpath); @@ -423,6 +445,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenamePath(const char *oldpath, const char * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread, but this + * operation is not atomic, so the app might need to protect + * access to specific paths from other threads if appropriate. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_CopyFile(const char *oldpath, const char *newpath); @@ -430,12 +456,18 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CopyFile(const char *oldpath, const char *n /** * Get information about a filesystem path. * + * Symlinks, on filesystems that support them, are always followed, so you will + * always get information on what the symlink eventually points to, and not the + * symlink itself. + * * \param path the path to query. * \param info a pointer filled in with information about the path, or NULL to * check for the existence of a file. * \returns true on success or false if the file doesn't exist, or another * failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo *info); @@ -444,10 +476,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo * Enumerate a directory tree, filtered by pattern, and return a list. * * Files are filtered out if they don't match the string in `pattern`, which - * may contain wildcard characters '\*' (match everything) and '?' (match one + * may contain wildcard characters `*` (match everything) and `?` (match one * character). If pattern is NULL, no filtering is done and all results are * returned. Subdirectories are permitted, and are specified with a path - * separator of '/'. Wildcard characters '\*' and '?' never match a path + * separator of `/`. Wildcard characters `*` and `?` never match a path * separator. * * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching @@ -490,6 +522,8 @@ extern SDL_DECLSPEC char ** SDLCALL SDL_GlobDirectory(const char *path, const ch * platform-dependent notation. NULL if there's a problem. This * should be freed with SDL_free() when it is no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC char * SDLCALL SDL_GetCurrentDirectory(void); diff --git a/vendor/sdl3/include/SDL_gamepad.h b/vendor/sdl3/include/SDL_gamepad.h index 99f8b6593..113452535 100644 --- a/vendor/sdl3/include/SDL_gamepad.h +++ b/vendor/sdl3/include/SDL_gamepad.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -48,6 +48,9 @@ * SDL_INIT_GAMEPAD flag. This causes SDL to scan the system for gamepads, and * load appropriate drivers. * + * If you're using SDL gamepad support in a Steam game, you must call + * SteamAPI_InitEx() before calling SDL_Init(). + * * If you would like to receive gamepad updates while the application is in * the background, you should set the following hint before calling * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS @@ -118,6 +121,7 @@ typedef enum SDL_GamepadType SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT, SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT, SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR, + SDL_GAMEPAD_TYPE_GAMECUBE, SDL_GAMEPAD_TYPE_COUNT } SDL_GamepadType; @@ -127,8 +131,9 @@ typedef enum SDL_GamepadType * For controllers that use a diamond pattern for the face buttons, the * south/east/west/north buttons below correspond to the locations in the * diamond pattern. For Xbox controllers, this would be A/B/X/Y, for Nintendo - * Switch controllers, this would be B/A/Y/X, for PlayStation controllers this - * would be Cross/Circle/Square/Triangle. + * Switch controllers, this would be B/A/Y/X, for GameCube controllers this + * would be A/X/B/Y, for PlayStation controllers this would be + * Cross/Circle/Square/Triangle. * * For controllers that don't use a diamond pattern for the face buttons, the * south/east/west/north buttons indicate the buttons labeled A, B, C, D, or @@ -163,14 +168,14 @@ typedef enum SDL_GamepadButton SDL_GAMEPAD_BUTTON_DPAD_LEFT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, SDL_GAMEPAD_BUTTON_MISC1, /**< Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button, Google Stadia capture button) */ - SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /**< Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1) */ - SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /**< Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3) */ - SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /**< Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2) */ - SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /**< Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4) */ + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /**< Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1, DualSense Edge RB button, Right Joy-Con SR button) */ + SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /**< Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3, DualSense Edge LB button, Left Joy-Con SL button) */ + SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /**< Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2, DualSense Edge right Fn button, Right Joy-Con SL button) */ + SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /**< Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4, DualSense Edge left Fn button, Left Joy-Con SR button) */ SDL_GAMEPAD_BUTTON_TOUCHPAD, /**< PS4/PS5 touchpad button */ SDL_GAMEPAD_BUTTON_MISC2, /**< Additional button */ - SDL_GAMEPAD_BUTTON_MISC3, /**< Additional button */ - SDL_GAMEPAD_BUTTON_MISC4, /**< Additional button */ + SDL_GAMEPAD_BUTTON_MISC3, /**< Additional button (e.g. Nintendo GameCube left trigger click) */ + SDL_GAMEPAD_BUTTON_MISC4, /**< Additional button (e.g. Nintendo GameCube right trigger click) */ SDL_GAMEPAD_BUTTON_MISC5, /**< Additional button */ SDL_GAMEPAD_BUTTON_MISC6, /**< Additional button */ SDL_GAMEPAD_BUTTON_COUNT @@ -422,6 +427,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file) * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_ReloadGamepadMappings(void); @@ -436,6 +443,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReloadGamepadMappings(void); * single allocation that should be freed with SDL_free() when it is * no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC char ** SDLCALL SDL_GetGamepadMappings(int *count); @@ -448,6 +457,8 @@ extern SDL_DECLSPEC char ** SDLCALL SDL_GetGamepadMappings(int *count); * information. This should be freed with SDL_free() when it is no * longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickGUIDForID @@ -465,6 +476,8 @@ extern SDL_DECLSPEC char * SDLCALL SDL_GetGamepadMappingForGUID(SDL_GUID guid); * available; call SDL_GetError() for more information. This should * be freed with SDL_free() when it is no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AddGamepadMapping @@ -485,6 +498,8 @@ extern SDL_DECLSPEC char * SDLCALL SDL_GetGamepadMapping(SDL_Gamepad *gamepad); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AddGamepadMapping @@ -497,6 +512,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGamepadMapping(SDL_JoystickID instance_i * * \returns true if a gamepad is connected, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepads @@ -512,6 +529,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasGamepad(void); * call SDL_GetError() for more information. This should be freed * with SDL_free() when it is no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_HasGamepad @@ -526,6 +545,8 @@ extern SDL_DECLSPEC SDL_JoystickID * SDLCALL SDL_GetGamepads(int *count); * \returns true if the given joystick is supported by the gamepad interface, * false if it isn't or it's an invalid index. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoysticks @@ -542,6 +563,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsGamepad(SDL_JoystickID instance_id); * \returns the name of the selected gamepad. If no name can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadName @@ -558,6 +581,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadNameForID(SDL_JoystickID * \returns the path of the selected gamepad. If no path can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadPath @@ -573,6 +598,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadPathForID(SDL_JoystickID * \param instance_id the joystick instance ID. * \returns the player index of a gamepad, or -1 if it's not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadPlayerIndex @@ -589,6 +616,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetGamepadPlayerIndexForID(SDL_JoystickID in * \returns the GUID of the selected gamepad. If called on an invalid index, * this function returns a zero GUID. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GUIDToString @@ -606,6 +635,8 @@ extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetGamepadGUIDForID(SDL_JoystickID inst * \returns the USB vendor ID of the selected gamepad. If called on an invalid * index, this function returns zero. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadVendor @@ -623,6 +654,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadVendorForID(SDL_JoystickID inst * \returns the USB product ID of the selected gamepad. If called on an * invalid index, this function returns zero. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadProduct @@ -640,6 +673,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadProductForID(SDL_JoystickID ins * \returns the product version of the selected gamepad. If called on an * invalid index, this function returns zero. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadProductVersion @@ -655,6 +690,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadProductVersionForID(SDL_Joystic * \param instance_id the joystick instance ID. * \returns the gamepad type. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadType @@ -671,6 +708,8 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeForID(SDL_Joystick * \param instance_id the joystick instance ID. * \returns the gamepad type. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadTypeForID @@ -688,6 +727,8 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadTypeForID(SDL_Joys * \returns the mapping string. Returns NULL if no mapping is available. This * should be freed with SDL_free() when it is no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepads @@ -702,6 +743,8 @@ extern SDL_DECLSPEC char * SDLCALL SDL_GetGamepadMappingForID(SDL_JoystickID ins * \returns a gamepad identifier or NULL if an error occurred; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CloseGamepad @@ -717,6 +760,8 @@ extern SDL_DECLSPEC SDL_Gamepad * SDLCALL SDL_OpenGamepad(SDL_JoystickID instanc * \returns an SDL_Gamepad on success or NULL on failure or if it hasn't been * opened yet; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Gamepad * SDLCALL SDL_GetGamepadFromID(SDL_JoystickID instance_id); @@ -727,6 +772,8 @@ extern SDL_DECLSPEC SDL_Gamepad * SDLCALL SDL_GetGamepadFromID(SDL_JoystickID in * \param player_index the player index, which different from the instance ID. * \returns the SDL_Gamepad associated with a player index. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadPlayerIndex @@ -757,6 +804,8 @@ extern SDL_DECLSPEC SDL_Gamepad * SDLCALL SDL_GetGamepadFromPlayerIndex(int play * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGamepadProperties(SDL_Gamepad *gamepad); @@ -775,6 +824,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGamepadProperties(SDL_Gamepa * \returns the instance ID of the specified gamepad on success or 0 on * failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadID(SDL_Gamepad *gamepad); @@ -787,6 +838,8 @@ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadID(SDL_Gamepad *gamepad * \returns the implementation dependent name for the gamepad, or NULL if * there is no name or the identifier passed is invalid. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadNameForID @@ -801,6 +854,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad * \returns the implementation dependent path for the gamepad, or NULL if * there is no path or the identifier passed is invalid. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadPathForID @@ -814,6 +869,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadPath(SDL_Gamepad *gamepad * \returns the gamepad type, or SDL_GAMEPAD_TYPE_UNKNOWN if it's not * available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadTypeForID @@ -827,6 +884,8 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadType(SDL_Gamepad *game * \returns the gamepad type, or SDL_GAMEPAD_TYPE_UNKNOWN if it's not * available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetRealGamepadTypeForID @@ -841,6 +900,8 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadType(SDL_Gamepad * * \param gamepad the gamepad object to query. * \returns the player index for gamepad, or -1 if it's not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetGamepadPlayerIndex @@ -856,6 +917,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetGamepadPlayerIndex(SDL_Gamepad *gamepad); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadPlayerIndex @@ -870,6 +933,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGamepadPlayerIndex(SDL_Gamepad *gamepad, * \param gamepad the gamepad object to query. * \returns the USB vendor ID, or zero if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadVendorForID @@ -884,6 +949,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadVendor(SDL_Gamepad *gamepad); * \param gamepad the gamepad object to query. * \returns the USB product ID, or zero if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadProductForID @@ -898,6 +965,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadProduct(SDL_Gamepad *gamepad); * \param gamepad the gamepad object to query. * \returns the USB product version, or zero if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadProductVersionForID @@ -912,6 +981,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadProductVersion(SDL_Gamepad *gam * \param gamepad the gamepad object to query. * \returns the gamepad firmware version, or zero if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadFirmwareVersion(SDL_Gamepad *gamepad); @@ -924,6 +995,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadFirmwareVersion(SDL_Gamepad *ga * \param gamepad the gamepad object to query. * \returns the serial number, or NULL if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamepad); @@ -937,6 +1010,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadSerial(SDL_Gamepad *gamep * \param gamepad the gamepad object to query. * \returns the gamepad handle, or 0 if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad); @@ -949,6 +1024,8 @@ extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepa * `SDL_JOYSTICK_CONNECTION_INVALID` on failure; call SDL_GetError() * for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetGamepadConnectionState(SDL_Gamepad *gamepad); @@ -969,6 +1046,8 @@ extern SDL_DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetGamepadConnection * battery. * \returns the current battery state. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetGamepadPowerInfo(SDL_Gamepad *gamepad, int *percent); @@ -981,6 +1060,8 @@ extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetGamepadPowerInfo(SDL_Gamepad * * \returns true if the gamepad has been opened and is currently connected, or * false if not. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadConnected(SDL_Gamepad *gamepad); @@ -1001,6 +1082,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadConnected(SDL_Gamepad *gamepad); * \returns an SDL_Joystick object, or NULL on failure; call SDL_GetError() * for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetGamepadJoystick(SDL_Gamepad *gamepad); @@ -1013,6 +1096,8 @@ extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetGamepadJoystick(SDL_Gamepad *g * * \param enabled whether to process gamepad events or not. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GamepadEventsEnabled @@ -1028,6 +1113,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetGamepadEventsEnabled(bool enabled); * * \returns true if gamepad events are being processed, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetGamepadEventsEnabled @@ -1044,6 +1131,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadEventsEnabled(void); * single allocation that should be freed with SDL_free() when it is * no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_GamepadBinding ** SDLCALL SDL_GetGamepadBindings(SDL_Gamepad *gamepad, int *count); @@ -1055,6 +1144,8 @@ extern SDL_DECLSPEC SDL_GamepadBinding ** SDLCALL SDL_GetGamepadBindings(SDL_Gam * enabled. Under such circumstances, it will not be necessary to call this * function. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_UpdateGamepads(void); @@ -1071,6 +1162,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UpdateGamepads(void); * \returns the SDL_GamepadType enum corresponding to the input string, or * `SDL_GAMEPAD_TYPE_UNKNOWN` if no match was found. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadStringForType @@ -1085,6 +1178,8 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeFromString(const c * specified. The string returned is of the format used by * SDL_Gamepad mapping strings. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadTypeFromString @@ -1107,6 +1202,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadStringForType(SDL_Gamepad * \returns the SDL_GamepadAxis enum corresponding to the input string, or * `SDL_GAMEPAD_AXIS_INVALID` if no match was found. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadStringForAxis @@ -1121,6 +1218,8 @@ extern SDL_DECLSPEC SDL_GamepadAxis SDLCALL SDL_GetGamepadAxisFromString(const c * specified. The string returned is of the format used by * SDL_Gamepad mapping strings. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadAxisFromString @@ -1137,6 +1236,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadStringForAxis(SDL_Gamepad * \param axis an axis enum value (an SDL_GamepadAxis value). * \returns true if the gamepad has this axis, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GamepadHasButton @@ -1156,10 +1257,14 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_Ga * return a negative value. Note that this differs from the value reported by * the lower-level SDL_GetJoystickAxis(), which normally uses the full range. * + * Note that for invalid gamepads or axes, this will return 0. Zero is also a + * valid value in normal operation; usually it means a centered axis. + * * \param gamepad a gamepad. * \param axis an axis index (one of the SDL_GamepadAxis values). - * \returns axis state (including 0) on success or 0 (also) on failure; call - * SDL_GetError() for more information. + * \returns axis state. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * @@ -1176,10 +1281,12 @@ extern SDL_DECLSPEC Sint16 SDLCALL SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_ * You do not normally need to call this function unless you are parsing * SDL_Gamepad mappings in your own code. * - * \param str string representing a SDL_Gamepad axis. + * \param str string representing a SDL_Gamepad button. * \returns the SDL_GamepadButton enum corresponding to the input string, or * `SDL_GAMEPAD_BUTTON_INVALID` if no match was found. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadStringForButton @@ -1194,6 +1301,8 @@ extern SDL_DECLSPEC SDL_GamepadButton SDLCALL SDL_GetGamepadButtonFromString(con * specified. The string returned is of the format used by * SDL_Gamepad mapping strings. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadButtonFromString @@ -1210,6 +1319,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadStringForButton(SDL_Gamep * \param button a button enum value (an SDL_GamepadButton value). * \returns true if the gamepad has this button, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GamepadHasAxis @@ -1223,6 +1334,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_ * \param button a button index (one of the SDL_GamepadButton values). * \returns true if the button is pressed, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GamepadHasButton @@ -1237,6 +1350,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_ * \param button a button index (one of the SDL_GamepadButton values). * \returns the SDL_GamepadButtonLabel enum corresponding to the button label. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadButtonLabel @@ -1250,6 +1365,8 @@ extern SDL_DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabelForT * \param button a button index (one of the SDL_GamepadButton values). * \returns the SDL_GamepadButtonLabel enum corresponding to the button label. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadButtonLabelForType @@ -1262,6 +1379,8 @@ extern SDL_DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabel(SDL * \param gamepad a gamepad. * \returns number of touchpads. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumGamepadTouchpadFingers @@ -1276,6 +1395,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpads(SDL_Gamepad *gamepad) * \param touchpad a touchpad. * \returns number of supported simultaneous fingers. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadTouchpadFinger @@ -1299,6 +1420,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpadFingers(SDL_Gamepad *ga * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumGamepadTouchpadFingers @@ -1312,6 +1435,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGamepadTouchpadFinger(SDL_Gamepad *gamep * \param type the type of sensor to query. * \returns true if the sensor exists, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadSensorData @@ -1329,6 +1454,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadHasSensor(SDL_Gamepad *gamepad, SDL_ * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GamepadHasSensor @@ -1343,6 +1470,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGamepadSensorEnabled(SDL_Gamepad *gamepa * \param type the type of sensor to query. * \returns true if the sensor is enabled, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetGamepadSensorEnabled @@ -1356,6 +1485,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GamepadSensorEnabled(SDL_Gamepad *gamepad, * \param type the type of sensor to query. * \returns the data rate, or 0.0f if the data rate is not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC float SDLCALL SDL_GetGamepadSensorDataRate(SDL_Gamepad *gamepad, SDL_SensorType type); @@ -1364,7 +1495,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_GetGamepadSensorDataRate(SDL_Gamepad *game * Get the current state of a gamepad sensor. * * The number of values and interpretation of the data is sensor dependent. - * See SDL_sensor.h for the details for each type of sensor. + * See the remarks in SDL_SensorType for details for each type of sensor. * * \param gamepad the gamepad to query. * \param type the type of sensor to query. @@ -1373,6 +1504,8 @@ extern SDL_DECLSPEC float SDLCALL SDL_GetGamepadSensorDataRate(SDL_Gamepad *game * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, SDL_SensorType type, float *data, int num_values); @@ -1395,6 +1528,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); @@ -1421,6 +1556,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_RumbleGamepad @@ -1443,6 +1580,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleGamepadTriggers(SDL_Gamepad *gamepad, * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SetGamepadLED(SDL_Gamepad *gamepad, Uint8 red, Uint8 green, Uint8 blue); @@ -1456,6 +1595,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetGamepadLED(SDL_Gamepad *gamepad, Uint8 r * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SendGamepadEffect(SDL_Gamepad *gamepad, const void *data, int size); @@ -1466,6 +1607,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SendGamepadEffect(SDL_Gamepad *gamepad, con * \param gamepad a gamepad identifier previously returned by * SDL_OpenGamepad(). * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_OpenGamepad @@ -1480,6 +1623,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseGamepad(SDL_Gamepad *gamepad); * \param button a button on the gamepad. * \returns the sfSymbolsName or NULL if the name can't be found. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadAppleSFSymbolsNameForAxis @@ -1493,6 +1638,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadAppleSFSymbolsNameForButt * \param axis an axis on the gamepad. * \returns the sfSymbolsName or NULL if the name can't be found. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetGamepadAppleSFSymbolsNameForButton diff --git a/vendor/sdl3/include/SDL_gpu.h b/vendor/sdl3/include/SDL_gpu.h index 9f516d73f..b9e19ab54 100644 --- a/vendor/sdl3/include/SDL_gpu.h +++ b/vendor/sdl3/include/SDL_gpu.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -206,14 +206,20 @@ * underlying graphics API. While it's possible that we have done something * inefficiently, it's very unlikely especially if you are relatively * inexperienced with GPU rendering. Please see the performance tips above and - * make sure you are following them. Additionally, tools like RenderDoc can be - * very helpful for diagnosing incorrect behavior and performance issues. + * make sure you are following them. Additionally, tools like + * [RenderDoc](https://renderdoc.org/) + * can be very helpful for diagnosing incorrect behavior and performance + * issues. * * ## System Requirements * - * **Vulkan:** Supported on Windows, Linux, Nintendo Switch, and certain - * Android devices. Requires Vulkan 1.0 with the following extensions and - * device features: + * ### Vulkan + * + * SDL driver name: "vulkan" (for use in SDL_CreateGPUDevice() and + * SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING) + * + * Supported on Windows, Linux, Nintendo Switch, and certain Android devices. + * Requires Vulkan 1.0 with the following extensions and device features: * * - `VK_KHR_swapchain` * - `VK_KHR_maintenance1` @@ -222,13 +228,37 @@ * - `depthClamp` * - `shaderClipDistance` * - `drawIndirectFirstInstance` + * - `sampleRateShading` * - * **D3D12:** Supported on Windows 10 or newer, Xbox One (GDK), and Xbox - * Series X|S (GDK). Requires a GPU that supports DirectX 12 Feature Level - * 11_1. + * You can remove some of these requirements to increase compatibility with + * Android devices by using these properties when creating the GPU device with + * SDL_CreateGPUDeviceWithProperties(): * - * **Metal:** Supported on macOS 10.14+ and iOS/tvOS 13.0+. Hardware - * requirements vary by operating system: + * - SDL_PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN + * - SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN + * - SDL_PROP_GPU_DEVICE_CREATE_FEATURE_INDIRECT_DRAW_FIRST_INSTANCE_BOOLEAN + * - SDL_PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN + * + * ### D3D12 + * + * SDL driver name: "direct3d12" + * + * Supported on Windows 10 or newer, Xbox One (GDK), and Xbox Series X|S + * (GDK). Requires a GPU that supports DirectX 12 Feature Level 11_0 and + * Resource Binding Tier 2 or above. + * + * You can remove the Tier 2 resource binding requirement to support Intel + * Haswell and Broadwell GPUs by using this property when creating the GPU + * device with SDL_CreateGPUDeviceWithProperties(): + * + * - SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN + * + * ### Metal + * + * SDL driver name: "metal" + * + * Supported on macOS 10.14+ and iOS/tvOS 13.0+. Hardware requirements vary by + * operating system: * * - macOS requires an Apple Silicon or * [Intel Mac2 family](https://developer.apple.com/documentation/metal/mtlfeatureset/mtlfeatureset_macos_gpufamily2_v1?language=objc) @@ -236,6 +266,26 @@ * - iOS/tvOS requires an A9 GPU or newer * - iOS Simulator and tvOS Simulator are unsupported * + * ## Coordinate System + * + * The GPU API uses a left-handed coordinate system, following the convention + * of D3D12 and Metal. Specifically: + * + * - **Normalized Device Coordinates:** The lower-left corner has an x,y + * coordinate of `(-1.0, -1.0)`. The upper-right corner is `(1.0, 1.0)`. Z + * values range from `[0.0, 1.0]` where 0 is the near plane. + * - **Viewport Coordinates:** The top-left corner has an x,y coordinate of + * `(0, 0)` and extends to the bottom-right corner at `(viewportWidth, + * viewportHeight)`. +Y is down. + * - **Texture Coordinates:** The top-left corner has an x,y coordinate of + * `(0, 0)` and extends to the bottom-right corner at `(1.0, 1.0)`. +Y is + * down. + * + * If the backend driver differs from this convention (e.g. Vulkan, which has + * an NDC that assumes +Y is down), SDL will automatically convert the + * coordinate system behind the scenes, so you don't need to perform any + * coordinate flipping logic in your shaders. + * * ## Uniform Data * * Uniforms are for passing data to shaders. The uniform data will be constant @@ -301,6 +351,39 @@ * unreferenced data in a bound resource without cycling, but overwriting a * section of data that has already been referenced will produce unexpected * results. + * + * ## Debugging + * + * At some point of your GPU journey, you will probably encounter issues that + * are not traceable with regular debugger - for example, your code compiles + * but you get an empty screen, or your shader fails in runtime. + * + * For debugging such cases, there are tools that allow visually inspecting + * the whole GPU frame, every drawcall, every bound resource, memory buffers, + * etc. They are the following, per platform: + * + * * For Windows/Linux, use + * [RenderDoc](https://renderdoc.org/) + * * For MacOS (Metal), use Xcode built-in debugger (Open XCode, go to Debug > + * Debug Executable..., select your application, set "GPU Frame Capture" to + * "Metal" in scheme "Options" window, run your app, and click the small + * Metal icon on the bottom to capture a frame) + * + * Aside from that, you may want to enable additional debug layers to receive + * more detailed error messages, based on your GPU backend: + * + * * For D3D12, the debug layer is an optional feature that can be installed + * via "Windows Settings -> System -> Optional features" and adding the + * "Graphics Tools" optional feature. + * * For Vulkan, you will need to install Vulkan SDK on Windows, and on Linux, + * you usually have some sort of `vulkan-validation-layers` system package + * that should be installed. + * * For Metal, it should be enough just to run the application from XCode to + * receive detailed errors or warnings in the output. + * + * Don't hesitate to use tools as RenderDoc when encountering runtime issues + * or unexpected output on screen, quick GPU frame inspection can usually help + * you fix the majority of such problems. */ #ifndef SDL_gpu_h_ @@ -1091,7 +1174,7 @@ typedef enum SDL_GPUCompareOp SDL_GPU_COMPAREOP_LESS_OR_EQUAL, /**< The comparison evaluates reference <= test. */ SDL_GPU_COMPAREOP_GREATER, /**< The comparison evaluates reference > test. */ SDL_GPU_COMPAREOP_NOT_EQUAL, /**< The comparison evaluates reference != test. */ - SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, /**< The comparison evalutes reference >= test. */ + SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, /**< The comparison evaluates reference >= test. */ SDL_GPU_COMPAREOP_ALWAYS /**< The comparison always evaluates true. */ } SDL_GPUCompareOp; @@ -1310,6 +1393,18 @@ typedef struct SDL_GPUViewport * A structure specifying parameters related to transferring data to or from a * texture. * + * If either of `pixels_per_row` or `rows_per_layer` is zero, then width and + * height of passed SDL_GPUTextureRegion to SDL_UploadToGPUTexture or + * SDL_DownloadFromGPUTexture are used as default values respectively and data + * is considered to be tightly packed. + * + * **WARNING**: On some older/integrated hardware, Direct3D 12 requires texture + * data row pitch to be 256 byte aligned, and offsets to be aligned to 512 bytes. + * If they are not, SDL will make a temporary copy of the data that is properly + * aligned, but this adds overhead to the transfer process. Apps can avoid this + * by aligning their data appropriately, or using a different GPU backend than + * Direct3D 12. + * * \since This struct is available since SDL 3.2.0. * * \sa SDL_UploadToGPUTexture @@ -1391,7 +1486,7 @@ typedef struct SDL_GPUTextureRegion */ typedef struct SDL_GPUBlitRegion { - SDL_GPUTexture *texture; /**< The texture. */ + SDL_GPUTexture *texture; /**< The texture. */ Uint32 mip_level; /**< The mip level index of the region. */ Uint32 layer_or_depth_plane; /**< The layer index or depth plane of the region. This value is treated as a layer index on 2D array and cube textures, and as a depth plane on 3D textures. */ Uint32 x; /**< The left offset of the region. */ @@ -1520,8 +1615,8 @@ typedef struct SDL_GPUSamplerCreateInfo SDL_GPUCompareOp compare_op; /**< The comparison operator to apply to fetched data before filtering. */ float min_lod; /**< Clamps the minimum of the computed LOD value. */ float max_lod; /**< Clamps the maximum of the computed LOD value. */ - bool enable_anisotropy; /**< true to enable anisotropic filtering. */ - bool enable_compare; /**< true to enable comparison against a reference value during lookups. */ + bool enable_anisotropy; /**< true to enable anisotropic filtering. */ + bool enable_compare; /**< true to enable comparison against a reference value during lookups. */ Uint8 padding1; Uint8 padding2; @@ -1549,7 +1644,7 @@ typedef struct SDL_GPUSamplerCreateInfo typedef struct SDL_GPUVertexBufferDescription { Uint32 slot; /**< The binding slot of the vertex buffer. */ - Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */ + Uint32 pitch; /**< The size of a single element + the offset between elements. */ SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */ Uint32 instance_step_rate; /**< Reserved for future use. Must be set to 0. */ } SDL_GPUVertexBufferDescription; @@ -1613,6 +1708,9 @@ typedef struct SDL_GPUStencilOpState * \since This struct is available since SDL 3.2.0. * * \sa SDL_GPUColorTargetDescription + * \sa SDL_GPUBlendFactor + * \sa SDL_GPUBlendOp + * \sa SDL_GPUColorComponentFlags */ typedef struct SDL_GPUColorTargetBlendState { @@ -1623,8 +1721,8 @@ typedef struct SDL_GPUColorTargetBlendState SDL_GPUBlendFactor dst_alpha_blendfactor; /**< The value to be multiplied by the destination alpha. */ SDL_GPUBlendOp alpha_blend_op; /**< The blend operation for the alpha component. */ SDL_GPUColorComponentFlags color_write_mask; /**< A bitmask specifying which of the RGBA components are enabled for writing. Writes to all channels if enable_color_write_mask is false. */ - bool enable_blend; /**< Whether blending is enabled for the color target. */ - bool enable_color_write_mask; /**< Whether the color write mask is enabled. */ + bool enable_blend; /**< Whether blending is enabled for the color target. */ + bool enable_color_write_mask; /**< Whether the color write mask is enabled. */ Uint8 padding1; Uint8 padding2; } SDL_GPUColorTargetBlendState; @@ -1636,6 +1734,8 @@ typedef struct SDL_GPUColorTargetBlendState * \since This struct is available since SDL 3.2.0. * * \sa SDL_CreateGPUShader + * \sa SDL_GPUShaderFormat + * \sa SDL_GPUShaderStage */ typedef struct SDL_GPUShaderCreateInfo { @@ -1741,8 +1841,8 @@ typedef struct SDL_GPURasterizerState float depth_bias_constant_factor; /**< A scalar factor controlling the depth value added to each fragment. */ float depth_bias_clamp; /**< The maximum depth bias of a fragment. */ float depth_bias_slope_factor; /**< A scalar factor applied to a fragment's slope in depth calculations. */ - bool enable_depth_bias; /**< true to bias fragment depth values. */ - bool enable_depth_clip; /**< true to enable depth clip, false to enable depth clamp. */ + bool enable_depth_bias; /**< true to bias fragment depth values. */ + bool enable_depth_clip; /**< true to enable depth clip, false to enable depth clamp. */ Uint8 padding1; Uint8 padding2; } SDL_GPURasterizerState; @@ -1759,8 +1859,8 @@ typedef struct SDL_GPUMultisampleState { SDL_GPUSampleCount sample_count; /**< The number of samples to be used in rasterization. */ Uint32 sample_mask; /**< Reserved for future use. Must be set to 0. */ - bool enable_mask; /**< Reserved for future use. Must be set to false. */ - Uint8 padding1; + bool enable_mask; /**< Reserved for future use. Must be set to false. */ + bool enable_alpha_to_coverage; /**< true enables the alpha-to-coverage feature. */ Uint8 padding2; Uint8 padding3; } SDL_GPUMultisampleState; @@ -1780,9 +1880,9 @@ typedef struct SDL_GPUDepthStencilState SDL_GPUStencilOpState front_stencil_state; /**< The stencil op state for front-facing triangles. */ Uint8 compare_mask; /**< Selects the bits of the stencil values participating in the stencil test. */ Uint8 write_mask; /**< Selects the bits of the stencil values updated by the stencil test. */ - bool enable_depth_test; /**< true enables the depth test. */ - bool enable_depth_write; /**< true enables depth writes. Depth writes are always disabled when enable_depth_test is false. */ - bool enable_stencil_test; /**< true enables the stencil test. */ + bool enable_depth_test; /**< true enables the depth test. */ + bool enable_depth_write; /**< true enables depth writes. Depth writes are always disabled when enable_depth_test is false. */ + bool enable_stencil_test; /**< true enables the stencil test. */ Uint8 padding1; Uint8 padding2; Uint8 padding3; @@ -1817,7 +1917,7 @@ typedef struct SDL_GPUGraphicsPipelineTargetInfo const SDL_GPUColorTargetDescription *color_target_descriptions; /**< A pointer to an array of color target descriptions. */ Uint32 num_color_targets; /**< The number of color target descriptions in the above array. */ SDL_GPUTextureFormat depth_stencil_format; /**< The pixel format of the depth-stencil target. Ignored if has_depth_stencil_target is false. */ - bool has_depth_stencil_target; /**< true specifies that the pipeline uses a depth-stencil target. */ + bool has_depth_stencil_target; /**< true specifies that the pipeline uses a depth-stencil target. */ Uint8 padding1; Uint8 padding2; Uint8 padding3; @@ -1912,6 +2012,7 @@ typedef struct SDL_GPUComputePipelineCreateInfo * \since This struct is available since SDL 3.2.0. * * \sa SDL_BeginGPURenderPass + * \sa SDL_FColor */ typedef struct SDL_GPUColorTargetInfo { @@ -1924,8 +2025,8 @@ typedef struct SDL_GPUColorTargetInfo SDL_GPUTexture *resolve_texture; /**< The texture that will receive the results of a multisample resolve operation. Ignored if a RESOLVE* store_op is not used. */ Uint32 resolve_mip_level; /**< The mip level of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. */ Uint32 resolve_layer; /**< The layer index of the resolve texture to use for the resolve operation. Ignored if a RESOLVE* store_op is not used. */ - bool cycle; /**< true cycles the texture if the texture is bound and load_op is not LOAD */ - bool cycle_resolve_texture; /**< true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used. */ + bool cycle; /**< true cycles the texture if the texture is bound and load_op is not LOAD */ + bool cycle_resolve_texture; /**< true cycles the resolve texture if the resolve texture is bound. Ignored if a RESOLVE* store_op is not used. */ Uint8 padding1; Uint8 padding2; } SDL_GPUColorTargetInfo; @@ -1970,6 +2071,9 @@ typedef struct SDL_GPUColorTargetInfo * * Note that depth/stencil targets do not support multisample resolves. * + * Due to ABI limitations, depth textures with more than 255 layers are not + * supported. + * * \since This struct is available since SDL 3.2.0. * * \sa SDL_BeginGPURenderPass @@ -1982,10 +2086,10 @@ typedef struct SDL_GPUDepthStencilTargetInfo SDL_GPUStoreOp store_op; /**< What is done with the depth results of the render pass. */ SDL_GPULoadOp stencil_load_op; /**< What is done with the stencil contents at the beginning of the render pass. */ SDL_GPUStoreOp stencil_store_op; /**< What is done with the stencil results of the render pass. */ - bool cycle; /**< true cycles the texture if the texture is bound and any load ops are not LOAD */ + bool cycle; /**< true cycles the texture if the texture is bound and any load ops are not LOAD */ Uint8 clear_stencil; /**< The value to clear the stencil component to at the beginning of the render pass. Ignored if SDL_GPU_LOADOP_CLEAR is not used. */ - Uint8 padding1; - Uint8 padding2; + Uint8 mip_level; /**< The mip level to use as the depth stencil target. */ + Uint8 layer; /**< The layer index to use as the depth stencil target. */ } SDL_GPUDepthStencilTargetInfo; /** @@ -2002,7 +2106,7 @@ typedef struct SDL_GPUBlitInfo { SDL_FColor clear_color; /**< The color to clear the destination region to before the blit. Ignored if load_op is not SDL_GPU_LOADOP_CLEAR. */ SDL_FlipMode flip_mode; /**< The flip mode for the source region. */ SDL_GPUFilter filter; /**< The filter mode used when blitting. */ - bool cycle; /**< true cycles the destination texture if it is already bound. */ + bool cycle; /**< true cycles the destination texture if it is already bound. */ Uint8 padding1; Uint8 padding2; Uint8 padding3; @@ -2031,6 +2135,8 @@ typedef struct SDL_GPUBufferBinding * * \sa SDL_BindGPUVertexSamplers * \sa SDL_BindGPUFragmentSamplers + * \sa SDL_GPUTexture + * \sa SDL_GPUSampler */ typedef struct SDL_GPUTextureSamplerBinding { @@ -2111,6 +2217,13 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties( /** * Creates a GPU context. * + * The GPU driver name can be one of the following: + * + * - "vulkan": [Vulkan](CategoryGPU#vulkan) + * - "direct3d12": [D3D12](CategoryGPU#d3d12) + * - "metal": [Metal](CategoryGPU#metal) + * - NULL: let SDL pick the optimal driver + * * \param format_flags a bitflag indicating which shader formats the app is * able to provide. * \param debug_mode enable debug mode properties and validations. @@ -2121,6 +2234,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties( * * \since This function is available since SDL 3.2.0. * + * \sa SDL_CreateGPUDeviceWithProperties * \sa SDL_GetGPUShaderFormats * \sa SDL_GetGPUDeviceDriver * \sa SDL_DestroyGPUDevice @@ -2140,8 +2254,31 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( * properties and validations, defaults to true. * - `SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN`: enable to prefer * energy efficiency over maximum GPU performance, defaults to false. + * - `SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN`: enable to automatically log + * useful debug information on device creation, defaults to true. * - `SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING`: the name of the GPU driver to * use, if a specific one is desired. + * - `SDL_PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN`: Enable Vulkan + * device feature shaderClipDistance. If disabled, clip distances are not + * supported in shader code: gl_ClipDistance[] built-ins of GLSL, + * SV_ClipDistance0/1 semantics of HLSL and [[clip_distance]] attribute of + * Metal. Disabling optional features allows the application to run on some + * older Android devices. Defaults to true. + * - `SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN`: Enable + * Vulkan device feature depthClamp. If disabled, there is no depth clamp + * support and enable_depth_clip in SDL_GPURasterizerState must always be + * set to true. Disabling optional features allows the application to run on + * some older Android devices. Defaults to true. + * - `SDL_PROP_GPU_DEVICE_CREATE_FEATURE_INDIRECT_DRAW_FIRST_INSTANCE_BOOLEAN`: + * Enable Vulkan device feature drawIndirectFirstInstance. If disabled, the + * argument first_instance of SDL_GPUIndirectDrawCommand must be set to + * zero. Disabling optional features allows the application to run on some + * older Android devices. Defaults to true. + * - `SDL_PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN`: Enable Vulkan + * device feature samplerAnisotropy. If disabled, enable_anisotropy of + * SDL_GPUSamplerCreateInfo must be set to false. Disabling optional + * features allows the application to run on some older Android devices. + * Defaults to true. * * These are the current shader format properties: * @@ -2158,10 +2295,56 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( * - `SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN`: The app is able to * provide Metal shader libraries if applicable. * - * With the D3D12 renderer: + * With the D3D12 backend: * * - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING`: the prefix to * use for all vertex semantics, default is "TEXCOORD". + * - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN`: By + * default, Resourcing Binding Tier 2 is required for D3D12 support. + * However, an application can set this property to true to enable Tier 1 + * support, if (and only if) the application uses 8 or fewer storage + * resources across all shader stages. As of writing, this property is + * useful for targeting Intel Haswell and Broadwell GPUs; other hardware + * either supports Tier 2 Resource Binding or does not support D3D12 in any + * capacity. Defaults to false. + * - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_VERSION_NUMBER`: Certain + * feature checks are only possible on Windows 11 by default. By setting + * this alongside `SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_PATH_STRING` + * and vendoring D3D12Core.dll from the D3D12 Agility SDK, you can make + * those feature checks possible on older platforms. The version you provide + * must match the one given in the DLL. + * - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_PATH_STRING`: Certain + * feature checks are only possible on Windows 11 by default. By setting + * this alongside + * `SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_VERSION_NUMBER` and + * vendoring D3D12Core.dll from the D3D12 Agility SDK, you can make those + * feature checks possible on older platforms. The path you provide must be + * relative to the executable path of your app. Be sure not to put the DLL + * in the same directory as the exe; Microsoft strongly advises against + * this! + * + * With the Vulkan backend: + * + * - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN`: + * By default, Vulkan device enumeration includes drivers of all types, + * including software renderers (for example, the Lavapipe Mesa driver). + * This can be useful if your application _requires_ SDL_GPU, but if you can + * provide your own fallback renderer (for example, an OpenGL renderer) this + * property can be set to true. Defaults to false. + * - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER`: a pointer to an + * SDL_GPUVulkanOptions structure to be processed during device creation. + * This allows configuring a variety of Vulkan-specific options such as + * increasing the API version and opting into extensions aside from the + * minimal set SDL requires. + * + * With the Metal backend: - + * `SDL_PROP_GPU_DEVICE_CREATE_METAL_ALLOW_MACFAMILY1_BOOLEAN`: By default, + * macOS support requires what Apple calls "MTLGPUFamilyMac2" hardware or + * newer. However, an application can set this property to true to enable + * support for "MTLGPUFamilyMac1" hardware, if (and only if) the application + * does not write to sRGB textures. (For history's sake: MacFamily1 also does + * not support indirect command buffers, MSAA depth resolve, and stencil + * resolve/feedback, but these are not exposed features in SDL_GPU.) * * \param props the properties to use. * \returns a GPU context on success or NULL on failure; call SDL_GetError() @@ -2177,16 +2360,55 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties( SDL_PropertiesID props); -#define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode" -#define SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN "SDL.gpu.device.create.preferlowpower" -#define SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING "SDL.gpu.device.create.name" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN "SDL.gpu.device.create.shaders.private" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN "SDL.gpu.device.create.shaders.spirv" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN "SDL.gpu.device.create.shaders.dxbc" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN "SDL.gpu.device.create.shaders.dxil" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl" -#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib" -#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic" +#define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode" +#define SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN "SDL.gpu.device.create.preferlowpower" +#define SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN "SDL.gpu.device.create.verbose" +#define SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING "SDL.gpu.device.create.name" +#define SDL_PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN "SDL.gpu.device.create.feature.clip_distance" +#define SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN "SDL.gpu.device.create.feature.depth_clamping" +#define SDL_PROP_GPU_DEVICE_CREATE_FEATURE_INDIRECT_DRAW_FIRST_INSTANCE_BOOLEAN "SDL.gpu.device.create.feature.indirect_draw_first_instance" +#define SDL_PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN "SDL.gpu.device.create.feature.anisotropy" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN "SDL.gpu.device.create.shaders.private" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN "SDL.gpu.device.create.shaders.spirv" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN "SDL.gpu.device.create.shaders.dxbc" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN "SDL.gpu.device.create.shaders.dxil" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl" +#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib" +#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN "SDL.gpu.device.create.d3d12.allowtier1resourcebinding" +#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic" +#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_VERSION_NUMBER "SDL.gpu.device.create.d3d12.agility_sdk_version" +#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_PATH_STRING "SDL.gpu.device.create.d3d12.agility_sdk_path" +#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN "SDL.gpu.device.create.vulkan.requirehardwareacceleration" +#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER "SDL.gpu.device.create.vulkan.options" +#define SDL_PROP_GPU_DEVICE_CREATE_METAL_ALLOW_MACFAMILY1_BOOLEAN "SDL.gpu.device.create.metal.allowmacfamily1" + + +/** + * A structure specifying additional options when using Vulkan. + * + * When no such structure is provided, SDL will use Vulkan API version 1.0 and + * a minimal set of features. The requested API version influences how the + * feature_list is processed by SDL. When requesting API version 1.0, the + * feature_list is ignored. Only the vulkan_10_physical_device_features and + * the extension lists are used. When requesting API version 1.1, the + * feature_list is scanned for feature structures introduced in Vulkan 1.1. + * When requesting Vulkan 1.2 or higher, the feature_list is additionally + * scanned for compound feature structs such as + * VkPhysicalDeviceVulkan11Features. The device and instance extension lists, + * as well as vulkan_10_physical_device_features, are always processed. + * + * \since This struct is available since SDL 3.4.0. + */ +typedef struct SDL_GPUVulkanOptions +{ + Uint32 vulkan_api_version; /**< The Vulkan API version to request for the instance. Use Vulkan's VK_MAKE_VERSION or VK_MAKE_API_VERSION. */ + void *feature_list; /**< Pointer to the first element of a chain of Vulkan feature structs. (Requires API version 1.1 or higher.)*/ + void *vulkan_10_physical_device_features; /**< Pointer to a VkPhysicalDeviceFeatures struct to enable additional Vulkan 1.0 features. */ + Uint32 device_extension_count; /**< Number of additional device extensions to require. */ + const char **device_extension_names; /**< Pointer to a list of additional device extensions to require. */ + Uint32 instance_extension_count; /**< Number of additional instance extensions to require. */ + const char **instance_extension_names; /**< Pointer to a list of additional instance extensions to require. */ +} SDL_GPUVulkanOptions; /** * Destroys a GPU context previously returned by SDL_CreateGPUDevice. @@ -2250,6 +2472,116 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGPUDeviceDriver(SDL_GPUDevice *d */ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_GetGPUShaderFormats(SDL_GPUDevice *device); +/** + * Get the properties associated with a GPU device. + * + * All properties are optional and may differ between GPU backends and SDL + * versions. + * + * The following properties are provided by SDL: + * + * `SDL_PROP_GPU_DEVICE_NAME_STRING`: Contains the name of the underlying + * device as reported by the system driver. This string has no standardized + * format, is highly inconsistent between hardware devices and drivers, and is + * able to change at any time. Do not attempt to parse this string as it is + * bound to fail at some point in the future when system drivers are updated, + * new hardware devices are introduced, or when SDL adds new GPU backends or + * modifies existing ones. + * + * Strings that have been found in the wild include: + * + * - GTX 970 + * - GeForce GTX 970 + * - NVIDIA GeForce GTX 970 + * - Microsoft Direct3D12 (NVIDIA GeForce GTX 970) + * - NVIDIA Graphics Device + * - GeForce GPU + * - P106-100 + * - AMD 15D8:C9 + * - AMD Custom GPU 0405 + * - AMD Radeon (TM) Graphics + * - ASUS Radeon RX 470 Series + * - Intel(R) Arc(tm) A380 Graphics (DG2) + * - Virtio-GPU Venus (NVIDIA TITAN V) + * - SwiftShader Device (LLVM 16.0.0) + * - llvmpipe (LLVM 15.0.4, 256 bits) + * - Microsoft Basic Render Driver + * - unknown device + * + * The above list shows that the same device can have different formats, the + * vendor name may or may not appear in the string, the included vendor name + * may not be the vendor of the chipset on the device, some manufacturers + * include pseudo-legal marks while others don't, some devices may not use a + * marketing name in the string, the device string may be wrapped by the name + * of a translation interface, the device may be emulated in software, or the + * string may contain generic text that does not identify the device at all. + * + * `SDL_PROP_GPU_DEVICE_DRIVER_NAME_STRING`: Contains the self-reported name + * of the underlying system driver. + * + * Strings that have been found in the wild include: + * + * - Intel Corporation + * - Intel open-source Mesa driver + * - Qualcomm Technologies Inc. Adreno Vulkan Driver + * - MoltenVK + * - Mali-G715 + * - venus + * + * `SDL_PROP_GPU_DEVICE_DRIVER_VERSION_STRING`: Contains the self-reported + * version of the underlying system driver. This is a relatively short version + * string in an unspecified format. If SDL_PROP_GPU_DEVICE_DRIVER_INFO_STRING + * is available then that property should be preferred over this one as it may + * contain additional information that is useful for identifying the exact + * driver version used. + * + * Strings that have been found in the wild include: + * + * - 53.0.0 + * - 0.405.2463 + * - 32.0.15.6614 + * + * `SDL_PROP_GPU_DEVICE_DRIVER_INFO_STRING`: Contains the detailed version + * information of the underlying system driver as reported by the driver. This + * is an arbitrary string with no standardized format and it may contain + * newlines. This property should be preferred over + * SDL_PROP_GPU_DEVICE_DRIVER_VERSION_STRING if it is available as it usually + * contains the same information but in a format that is easier to read. + * + * Strings that have been found in the wild include: + * + * - 101.6559 + * - 1.2.11 + * - Mesa 21.2.2 (LLVM 12.0.1) + * - Mesa 22.2.0-devel (git-f226222 2022-04-14 impish-oibaf-ppa) + * - v1.r53p0-00eac0.824c4f31403fb1fbf8ee1042422c2129 + * + * This string has also been observed to be a multiline string (which has a + * trailing newline): + * + * ``` + * Driver Build: 85da404, I46ff5fc46f, 1606794520 + * Date: 11/30/20 + * Compiler Version: EV031.31.04.01 + * Driver Branch: promo490_3_Google + * ``` + * + * \param device a GPU context to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGPUDeviceProperties(SDL_GPUDevice *device); + +#define SDL_PROP_GPU_DEVICE_NAME_STRING "SDL.gpu.device.name" +#define SDL_PROP_GPU_DEVICE_DRIVER_NAME_STRING "SDL.gpu.device.driver_name" +#define SDL_PROP_GPU_DEVICE_DRIVER_VERSION_STRING "SDL.gpu.device.driver_version" +#define SDL_PROP_GPU_DEVICE_DRIVER_INFO_STRING "SDL.gpu.device.driver_info" + + /* State Creation */ /** @@ -2440,7 +2772,8 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader( * Creates a texture object to be used in graphics or compute workflows. * * The contents of this texture are undefined until data is written to the - * texture. + * texture, either via SDL_UploadToGPUTexture or by performing a render or + * compute pass with this texture as a target. * * Note that certain combinations of usage flags are invalid. For example, a * texture cannot have both the SAMPLER and GRAPHICS_STORAGE_READ flags. @@ -2467,9 +2800,9 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader( * - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT`: (Direct3D 12 only) * if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, clear * the texture to a depth of this value. Defaults to zero. - * - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8`: (Direct3D 12 + * - `SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER`: (Direct3D 12 * only) if the texture usage is SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET, - * clear the texture to a stencil of this value. Defaults to zero. + * clear the texture to a stencil of this Uint8 value. Defaults to zero. * - `SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING`: a name that can be displayed * in debugging tools. * @@ -2482,6 +2815,8 @@ extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader( * * \sa SDL_UploadToGPUTexture * \sa SDL_DownloadFromGPUTexture + * \sa SDL_BeginGPURenderPass + * \sa SDL_BeginGPUComputePass * \sa SDL_BindGPUVertexSamplers * \sa SDL_BindGPUVertexStorageTextures * \sa SDL_BindGPUFragmentSamplers @@ -2495,13 +2830,13 @@ extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL SDL_CreateGPUTexture( SDL_GPUDevice *device, const SDL_GPUTextureCreateInfo *createinfo); -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r" -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g" -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b" -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a" -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth" -#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 "SDL.gpu.texture.create.d3d12.clear.stencil" -#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT "SDL.gpu.texture.create.d3d12.clear.r" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT "SDL.gpu.texture.create.d3d12.clear.g" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT "SDL.gpu.texture.create.d3d12.clear.b" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT "SDL.gpu.texture.create.d3d12.clear.a" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT "SDL.gpu.texture.create.d3d12.clear.depth" +#define SDL_PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER "SDL.gpu.texture.create.d3d12.clear.stencil" +#define SDL_PROP_GPU_TEXTURE_CREATE_NAME_STRING "SDL.gpu.texture.create.name" /** * Creates a buffer object to be used in graphics or compute workflows. @@ -2638,6 +2973,12 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetGPUTextureName( * * Useful for debugging. * + * On Direct3D 12, using SDL_InsertGPUDebugLabel requires + * WinPixEventRuntime.dll to be in your PATH or in the same directory as your + * executable. See + * [here](https://devblogs.microsoft.com/pix/winpixeventruntime/) + * for instructions on how to obtain it. + * * \param command_buffer a command buffer. * \param text a UTF-8 string constant to insert as the label. * @@ -2648,7 +2989,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_InsertGPUDebugLabel( const char *text); /** - * Begins a debug group with an arbitary name. + * Begins a debug group with an arbitrary name. * * Used for denoting groups of calls when viewing the command buffer * callstream in a graphics debugging tool. @@ -2656,6 +2997,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_InsertGPUDebugLabel( * Each call to SDL_PushGPUDebugGroup must have a corresponding call to * SDL_PopGPUDebugGroup. * + * On Direct3D 12, using SDL_PushGPUDebugGroup requires WinPixEventRuntime.dll + * to be in your PATH or in the same directory as your executable. See + * [here](https://devblogs.microsoft.com/pix/winpixeventruntime/) + * for instructions on how to obtain it. + * * On some backends (e.g. Metal), pushing a debug group during a * render/blit/compute pass will create a group that is scoped to the native * pass rather than the command buffer. For best results, if you push a debug @@ -2675,6 +3021,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUDebugGroup( /** * Ends the most-recently pushed debug group. * + * On Direct3D 12, using SDL_PopGPUDebugGroup requires WinPixEventRuntime.dll + * to be in your PATH or in the same directory as your executable. See + * [here](https://devblogs.microsoft.com/pix/winpixeventruntime/) + * for instructions on how to obtain it. + * * \param command_buffer a command buffer. * * \since This function is available since SDL 3.2.0. @@ -2816,12 +3167,15 @@ extern SDL_DECLSPEC SDL_GPUCommandBuffer * SDLCALL SDL_AcquireGPUCommandBuffer( /** * Pushes data to a vertex uniform slot on the command buffer. * - * Subsequent draw calls will use this uniform data. + * Subsequent draw calls in this command buffer will use this uniform data. * * The data being pushed must respect std140 layout conventions. In practical * terms this means you must ensure that vec3 and vec4 fields are 16-byte * aligned. * + * For detailed information about accessing uniform data from a shader, please + * refer to SDL_CreateGPUShader. + * * \param command_buffer a command buffer. * \param slot_index the vertex uniform slot to push data to. * \param data client data to write. @@ -2838,7 +3192,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUVertexUniformData( /** * Pushes data to a fragment uniform slot on the command buffer. * - * Subsequent draw calls will use this uniform data. + * Subsequent draw calls in this command buffer will use this uniform data. * * The data being pushed must respect std140 layout conventions. In practical * terms this means you must ensure that vec3 and vec4 fields are 16-byte @@ -2860,7 +3214,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUFragmentUniformData( /** * Pushes data to a uniform slot on the command buffer. * - * Subsequent draw calls will use this uniform data. + * Subsequent draw calls in this command buffer will use this uniform data. * * The data being pushed must respect std140 layout conventions. In practical * terms this means you must ensure that vec3 and vec4 fields are 16-byte @@ -2892,6 +3246,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUComputeUniformData( * is called. You cannot begin another render pass, or begin a compute pass or * copy pass until you have ended the render pass. * + * Using SDL_GPU_LOADOP_LOAD before any contents have been written to the + * texture subresource will result in undefined behavior. SDL_GPU_LOADOP_CLEAR + * will set the contents of the texture subresource to a single value before + * any rendering is performed. It's fine to do an empty render pass using + * SDL_GPU_STOREOP_STORE to clear a texture, but in general it's better to + * think of clearing not as an independent operation but as something that's + * done as the beginning of a render pass. + * * \param command_buffer a command buffer. * \param color_target_infos an array of texture subresources with * corresponding clear values and load/store ops. @@ -3338,7 +3700,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputePipeline( * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * * Be sure your shader is set up according to the requirements documented in - * SDL_CreateGPUShader(). + * SDL_CreateGPUComputePipeline(). * * \param compute_pass a compute pass handle. * \param first_slot the compute sampler slot to begin binding from. @@ -3349,7 +3711,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputePipeline( * * \since This function is available since SDL 3.2.0. * - * \sa SDL_CreateGPUShader + * \sa SDL_CreateGPUComputePipeline */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( SDL_GPUComputePass *compute_pass, @@ -3364,7 +3726,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( * SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ. * * Be sure your shader is set up according to the requirements documented in - * SDL_CreateGPUShader(). + * SDL_CreateGPUComputePipeline(). * * \param compute_pass a compute pass handle. * \param first_slot the compute storage texture slot to begin binding from. @@ -3373,7 +3735,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( * * \since This function is available since SDL 3.2.0. * - * \sa SDL_CreateGPUShader + * \sa SDL_CreateGPUComputePipeline */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageTextures( SDL_GPUComputePass *compute_pass, @@ -3388,7 +3750,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageTextures( * SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ. * * Be sure your shader is set up according to the requirements documented in - * SDL_CreateGPUShader(). + * SDL_CreateGPUComputePipeline(). * * \param compute_pass a compute pass handle. * \param first_slot the compute storage buffer slot to begin binding from. @@ -3397,7 +3759,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageTextures( * * \since This function is available since SDL 3.2.0. * - * \sa SDL_CreateGPUShader + * \sa SDL_CreateGPUComputePipeline */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageBuffers( SDL_GPUComputePass *compute_pass, @@ -3514,6 +3876,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnmapGPUTransferBuffer( * \returns a copy pass handle. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_EndGPUCopyPass */ extern SDL_DECLSPEC SDL_GPUCopyPass * SDLCALL SDL_BeginGPUCopyPass( SDL_GPUCommandBuffer *command_buffer); @@ -3567,6 +3931,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_UploadToGPUBuffer( * This copy occurs on the GPU timeline. You may assume the copy has finished * in subsequent commands. * + * This function does not support copying between depth and color textures. + * For those, copy the texture to a buffer and then to the destination + * texture. + * * \param copy_pass a copy pass handle. * \param source a source texture region. * \param destination a destination texture region. @@ -3775,7 +4143,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseWindowFromGPUDevice( * supported via SDL_WindowSupportsGPUPresentMode / * SDL_WindowSupportsGPUSwapchainComposition prior to calling this function. * - * SDL_GPU_PRESENTMODE_VSYNC and SDL_GPU_SWAPCHAINCOMPOSITION_SDR are always + * SDL_GPU_PRESENTMODE_VSYNC with SDL_GPU_SWAPCHAINCOMPOSITION_SDR is always * supported. * * \param device a GPU context. @@ -3849,7 +4217,9 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUSwapchainTextureForma * buffer used to acquire it. * * This function will fill the swapchain texture handle with NULL if too many - * frames are in flight. This is not an error. + * frames are in flight. This is not an error. This NULL pointer should not be + * passed back into SDL. Instead, it should be considered as an indication to + * wait until the swapchain is available. * * If you use this function, it is possible to create a situation where many * command buffers are allocated while the rendering context waits for the GPU @@ -4171,6 +4541,29 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_CalculateGPUTextureFormatSize( Uint32 height, Uint32 depth_or_layer_count); +/** + * Get the SDL pixel format corresponding to a GPU texture format. + * + * \param format a texture format. + * \returns the corresponding pixel format, or SDL_PIXELFORMAT_UNKNOWN if + * there is no corresponding pixel format. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PixelFormat SDLCALL SDL_GetPixelFormatFromGPUTextureFormat(SDL_GPUTextureFormat format); + +/** + * Get the GPU texture format corresponding to an SDL pixel format. + * + * \param format a pixel format. + * \returns the corresponding GPU texture format, or + * SDL_GPU_TEXTUREFORMAT_INVALID if there is no corresponding GPU + * texture format. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUTextureFormatFromPixelFormat(SDL_PixelFormat format); + #ifdef SDL_PLATFORM_GDK /** diff --git a/vendor/sdl3/include/SDL_guid.h b/vendor/sdl3/include/SDL_guid.h index 312c42c03..cf9df31ce 100644 --- a/vendor/sdl3/include/SDL_guid.h +++ b/vendor/sdl3/include/SDL_guid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_haptic.h b/vendor/sdl3/include/SDL_haptic.h index a45335b28..1cd9ddc0d 100644 --- a/vendor/sdl3/include/SDL_haptic.h +++ b/vendor/sdl3/include/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -70,7 +70,7 @@ * { * SDL_Haptic *haptic; * SDL_HapticEffect effect; - * int effect_id; + * SDL_HapticEffectID effect_id; * * // Open the device * haptic = SDL_OpenHapticFromJoystick(joystick); @@ -149,6 +149,19 @@ extern "C" { */ typedef struct SDL_Haptic SDL_Haptic; +/* + * Misc defines. + */ + +/** + * Used to play a device an infinite number of times. + * + * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_RunHapticEffect + */ +#define SDL_HAPTIC_INFINITY 4294967295U + /** * \name Haptic features @@ -162,6 +175,11 @@ typedef struct SDL_Haptic SDL_Haptic; */ /* @{ */ +/** + * Type of haptic effect. + */ +typedef Uint16 SDL_HapticEffectType; + /** * Constant effect supported. * @@ -383,6 +401,11 @@ typedef struct SDL_Haptic SDL_Haptic; */ /* @{ */ +/** + * Type of coordinates used for haptic direction. + */ +typedef Uint8 SDL_HapticDirectionType; + /** * Uses polar coordinates for the direction. * @@ -426,18 +449,15 @@ typedef struct SDL_Haptic SDL_Haptic; /* @} *//* Haptic features */ -/* - * Misc defines. - */ /** - * Used to play a device an infinite number of times. + * ID for haptic effects. * - * \since This macro is available since SDL 3.2.0. + * This is -1 if the ID is invalid. * - * \sa SDL_RunHapticEffect + * \sa SDL_CreateHapticEffect */ -#define SDL_HAPTIC_INFINITY 4294967295U +typedef int SDL_HapticEffectID; /** @@ -545,8 +565,8 @@ typedef struct SDL_Haptic SDL_Haptic; */ typedef struct SDL_HapticDirection { - Uint8 type; /**< The type of encoding. */ - Sint32 dir[3]; /**< The encoded direction. */ + SDL_HapticDirectionType type; /**< The type of encoding. */ + Sint32 dir[3]; /**< The encoded direction. */ } SDL_HapticDirection; @@ -566,7 +586,7 @@ typedef struct SDL_HapticDirection typedef struct SDL_HapticConstant { /* Header */ - Uint16 type; /**< SDL_HAPTIC_CONSTANT */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_CONSTANT */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -652,9 +672,9 @@ typedef struct SDL_HapticConstant typedef struct SDL_HapticPeriodic { /* Header */ - Uint16 type; /**< SDL_HAPTIC_SINE, SDL_HAPTIC_SQUARE - SDL_HAPTIC_TRIANGLE, SDL_HAPTIC_SAWTOOTHUP or - SDL_HAPTIC_SAWTOOTHDOWN */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_SINE, SDL_HAPTIC_SQUARE + SDL_HAPTIC_TRIANGLE, SDL_HAPTIC_SAWTOOTHUP or + SDL_HAPTIC_SAWTOOTHDOWN */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -708,8 +728,8 @@ typedef struct SDL_HapticPeriodic typedef struct SDL_HapticCondition { /* Header */ - Uint16 type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER, - SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER, + SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -747,7 +767,7 @@ typedef struct SDL_HapticCondition typedef struct SDL_HapticRamp { /* Header */ - Uint16 type; /**< SDL_HAPTIC_RAMP */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_RAMP */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -786,7 +806,7 @@ typedef struct SDL_HapticRamp typedef struct SDL_HapticLeftRight { /* Header */ - Uint16 type; /**< SDL_HAPTIC_LEFTRIGHT */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_LEFTRIGHT */ /* Replay */ Uint32 length; /**< Duration of the effect in milliseconds. */ @@ -816,7 +836,7 @@ typedef struct SDL_HapticLeftRight typedef struct SDL_HapticCustom { /* Header */ - Uint16 type; /**< SDL_HAPTIC_CUSTOM */ + SDL_HapticEffectType type; /**< SDL_HAPTIC_CUSTOM */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -915,7 +935,7 @@ typedef struct SDL_HapticCustom typedef union SDL_HapticEffect { /* Common for all force feedback effects */ - Uint16 type; /**< Effect type. */ + SDL_HapticEffectType type; /**< Effect type. */ SDL_HapticConstant constant; /**< Constant effect. */ SDL_HapticPeriodic periodic; /**< Periodic effect. */ SDL_HapticCondition condition; /**< Condition effect. */ @@ -1193,7 +1213,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, c * \sa SDL_RunHapticEffect * \sa SDL_UpdateHapticEffect */ -extern SDL_DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect); +extern SDL_DECLSPEC SDL_HapticEffectID SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect); /** * Update the properties of an effect. @@ -1215,7 +1235,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const * \sa SDL_CreateHapticEffect * \sa SDL_RunHapticEffect */ -extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data); +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect, const SDL_HapticEffect *data); /** * Run the haptic effect on its associated haptic device. @@ -1239,7 +1259,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int * \sa SDL_StopHapticEffect * \sa SDL_StopHapticEffects */ -extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations); +extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect, Uint32 iterations); /** * Stop the haptic effect on its associated haptic device. @@ -1254,7 +1274,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int eff * \sa SDL_RunHapticEffect * \sa SDL_StopHapticEffects */ -extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect); /** * Destroy a haptic effect on the device. @@ -1269,7 +1289,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int ef * * \sa SDL_CreateHapticEffect */ -extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, SDL_HapticEffectID effect); /** * Get the status of the current effect on the specified haptic device. @@ -1285,7 +1305,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int * * \sa SDL_GetHapticFeatures */ -extern SDL_DECLSPEC bool SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, SDL_HapticEffectID effect); /** * Set the global gain of the specified haptic device. diff --git a/vendor/sdl3/include/SDL_hidapi.h b/vendor/sdl3/include/SDL_hidapi.h index 131b03723..90e574c41 100644 --- a/vendor/sdl3/include/SDL_hidapi.h +++ b/vendor/sdl3/include/SDL_hidapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -55,6 +55,7 @@ #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -283,6 +284,24 @@ extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_ */ extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path); +/** + * Get the properties associated with an SDL_hid_device. + * + * The following read-only properties are provided by SDL: + * + * - `SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER`: the libusb_device_handle + * associated with the device, if it was opened using libusb. + * + * \param dev a device handle returned from SDL_hid_open(). + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_hid_get_properties(SDL_hid_device *dev); + +#define SDL_PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER "SDL.hidapi.libusb.device.handle" + /** * Write an Output report to a HID device. * diff --git a/vendor/sdl3/include/SDL_hints.h b/vendor/sdl3/include/SDL_hints.h index 9c8ad3f82..857dfcec1 100644 --- a/vendor/sdl3/include/SDL_hints.h +++ b/vendor/sdl3/include/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -391,12 +391,46 @@ extern "C" { * concept, so it applies to a physical audio device in this case, and not an * SDL_AudioStream, nor an SDL logical audio device. * + * For Windows WASAPI audio, the following roles are supported, and map to + * `AUDIO_STREAM_CATEGORY`: + * + * - "Other" (default) + * - "Communications" - Real-time communications, such as VOIP or chat + * - "Game" - Game audio + * - "GameChat" - Game chat audio, similar to "Communications" except that + * this will not attenuate other audio streams + * - "Movie" - Music or sound with dialog + * - "Media" - Music or sound without dialog + * + * If your application applies its own echo cancellation, gain control, and + * noise reduction it should also set SDL_HINT_AUDIO_DEVICE_RAW_STREAM. + * * This hint should be set before an audio device is opened. * * \since This hint is available since SDL 3.2.0. */ #define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE" +/** + * Specify whether this audio device should do audio processing. + * + * Some operating systems perform echo cancellation, gain control, and noise + * reduction as needed. If your application already handles these, you can set + * this hint to prevent the OS from doing additional audio processing. + * + * This corresponds to the WASAPI audio option `AUDCLNT_STREAMOPTIONS_RAW`. + * + * The variable can be set to the following values: + * + * - "0": audio processing can be done by the OS. (default) + * - "1": audio processing is done by the application. + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_AUDIO_DEVICE_RAW_STREAM "SDL_AUDIO_DEVICE_RAW_STREAM" + /** * Specify the input file when recording audio using the disk audio driver. * @@ -595,7 +629,7 @@ extern "C" { * A variable that limits what CPU features are available. * * By default, SDL marks all features the current CPU supports as available. - * This hint allows to limit these to a subset. + * This hint allows the enabled features to be limited to a subset. * * When the hint is unset, or empty, SDL will enable all detected CPU * features. @@ -685,6 +719,21 @@ extern "C" { */ #define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS" +/** + * Set the level of checking for invalid parameters passed to SDL functions. + * + * The variable can be set to the following values: + * + * - "1": Enable fast parameter error checking, e.g. quick NULL checks, etc. + * - "2": Enable full parameter error checking, e.g. validating objects are + * the correct type, etc. (default) + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_INVALID_PARAM_CHECKS "SDL_INVALID_PARAM_CHECKS" + /** * Disable giving back control to the browser automatically when running with * asyncify. @@ -711,8 +760,6 @@ extern "C" { * * This hint only applies to the emscripten platform. * - * The default value is "#canvas" - * * This hint should be set before creating a window. * * \since This hint is available since SDL 3.2.0. @@ -726,7 +773,7 @@ extern "C" { * * The variable can be one of: * - * - "#window": the javascript window object (default) + * - "#window": the javascript window object * - "#document": the javascript document object * - "#screen": the javascript window.screen object * - "#canvas": the WebGL canvas element @@ -1037,6 +1084,21 @@ extern "C" { */ #define SDL_HINT_HIDAPI_LIBUSB "SDL_HIDAPI_LIBUSB" + +/** + * A variable to control whether HIDAPI uses libusb for GameCube adapters. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI will not use libusb for GameCube adapters. + * - "1": HIDAPI will use libusb for GameCube adapters if available. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_HIDAPI_LIBUSB_GAMECUBE "SDL_HIDAPI_LIBUSB_GAMECUBE" + /** * A variable to control whether HIDAPI uses libusb only for whitelisted * devices. @@ -1074,8 +1136,8 @@ extern "C" { * * By default, SDL will try all available GPU backends in a reasonable order * until it finds one that can work, but this hint allows the app or user to - * force a specific target, such as "direct3d11" if, say, your hardware - * supports D3D12 but want to try using D3D11 instead. + * force a specific target, such as "direct3d12" if, say, your hardware + * supports Vulkan but you want to try using D3D12 instead. * * This hint should be set before any GPU functions are called. * @@ -1143,8 +1205,8 @@ extern "C" { #define SDL_HINT_IME_IMPLEMENTED_UI "SDL_IME_IMPLEMENTED_UI" /** - * A variable controlling whether the home indicator bar on iPhone X should be - * hidden. + * A variable controlling whether the home indicator bar on iPhone X and later + * should be hidden. * * The variable can be set to the following values: * @@ -1716,13 +1778,106 @@ extern "C" { * A variable controlling whether the HIDAPI driver for HORI licensed Steam * controllers should be used. * - * This variable can be set to the following values: "0" - HIDAPI driver is - * not used "1" - HIDAPI driver is used + * The variable can be set to the following values: * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.2.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI "SDL_JOYSTICK_HIDAPI_STEAM_HORI" +/** + * A variable controlling whether the HIDAPI driver for some Logitech wheels + * should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_LG4FF "SDL_JOYSTICK_HIDAPI_LG4FF" + +/** + * A variable controlling whether the HIDAPI driver for 8BitDo controllers + * should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_8BITDO "SDL_JOYSTICK_HIDAPI_8BITDO" + +/** + * A variable controlling whether the HIDAPI driver for SInput controllers + * should be used. + * + * More info - https://github.com/HandHeldLegend/SInput-HID + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SINPUT "SDL_JOYSTICK_HIDAPI_SINPUT" + +/** + * A variable controlling whether the HIDAPI driver for ZUIKI controllers + * should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_ZUIKI "SDL_JOYSTICK_HIDAPI_ZUIKI" + +/** + * A variable controlling whether the HIDAPI driver for Flydigi controllers + * should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_FLYDIGI "SDL_JOYSTICK_HIDAPI_FLYDIGI" + /** * A variable controlling whether the HIDAPI driver for Nintendo Switch * controllers should be used. @@ -1774,6 +1929,23 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" +/** + * A variable controlling whether the HIDAPI driver for Nintendo Switch 2 + * controllers should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH2 "SDL_JOYSTICK_HIDAPI_SWITCH2" + /** * A variable controlling whether Nintendo Switch Joy-Con controllers will be * in vertical mode when using the HIDAPI driver. @@ -1926,6 +2098,41 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" +/** + * A variable controlling whether the new HIDAPI driver for wired Xbox One + * (GIP) controllers should be used. + * + * The variable can be set to the following values: + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_GIP "SDL_JOYSTICK_HIDAPI_GIP" + +/** + * A variable controlling whether the new HIDAPI driver for wired Xbox One + * (GIP) controllers should reset the controller if it can't get the metadata + * from the controller. + * + * The variable can be set to the following values: + * + * - "0": Assume this is a generic controller. + * - "1": Reset the controller to get metadata. + * + * By default the controller is not reset. + * + * This hint should be set before initializing joysticks and gamepads. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA "SDL_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA" + /** * A variable controlling whether IOKit should be used for controller * handling. @@ -2026,8 +2233,8 @@ extern "C" { * * The variable can be set to the following values: * - * - "0": RAWINPUT drivers are not used. - * - "1": RAWINPUT drivers are used. (default) + * - "0": RAWINPUT drivers are not used. (default) + * - "1": RAWINPUT drivers are used. * * This hint should be set before SDL is initialized. * @@ -2126,8 +2333,8 @@ extern "C" { * * The variable can be set to the following values: * - * - "0": WGI is not used. - * - "1": WGI is used. (default) + * - "0": WGI is not used. (default) + * - "1": WGI is used. * * This hint should be set before SDL is initialized. * @@ -2228,9 +2435,9 @@ extern "C" { * pressing the 1 key would yield the keycode SDLK_1, or '1', instead of * SDLK_AMPERSAND, or '&' * - "latin_letters": For keyboards using non-Latin letters, such as Russian - * or Thai, the letter keys generate keycodes as though it had an en_US - * layout. e.g. pressing the key associated with SDL_SCANCODE_A on a Russian - * keyboard would yield 'a' instead of a Cyrillic letter. + * or Thai, the letter keys generate keycodes as though it had an English + * QWERTY layout. e.g. pressing the key associated with SDL_SCANCODE_A on a + * Russian keyboard would yield 'a' instead of a Cyrillic letter. * * The default value for this hint is "french_numbers,latin_letters" * @@ -2289,6 +2496,27 @@ extern "C" { */ #define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" +/** + * A variable that controls whether KMSDRM will use "atomic" functionality. + * + * The KMSDRM backend can use atomic commits, if both DRM_CLIENT_CAP_ATOMIC + * and DRM_CLIENT_CAP_UNIVERSAL_PLANES is supported by the system. As of SDL + * 3.4.0, it will favor this functionality, but in case this doesn't work well + * on a given system or other surprises, this hint can be used to disable it. + * + * This hint can not enable the functionality if it isn't available. + * + * The variable can be set to the following values: + * + * - "0": SDL will not use the KMSDRM "atomic" functionality. + * - "1": SDL will allow usage of the KMSDRM "atomic" functionality. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_KMSDRM_ATOMIC "SDL_KMSDRM_ATOMIC" + /** * A variable controlling the default SDL log levels. * @@ -2309,6 +2537,11 @@ extern "C" { * * `app=info,assert=warn,test=verbose,*=error` * + * If the `DEBUG_INVOCATION` environment variable is set to "1", the default + * log levels are equivalent to: + * + * `assert=warn,test=verbose,*=debug` + * * This hint can be set anytime. * * \since This hint is available since SDL 3.2.0. @@ -2410,6 +2643,21 @@ extern "C" { */ #define SDL_HINT_MAC_SCROLL_MOMENTUM "SDL_MAC_SCROLL_MOMENTUM" +/** + * A variable controlling whether holding down a key will repeat the pressed + * key or open the accents menu on macOS. + * + * The variable can be set to the following values: + * + * - "0": Holding a key will repeat the pressed key. + * - "1": Holding a key will open the accents menu for that key. (default) + * + * This hint needs to be set before SDL_Init(). + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_MAC_PRESS_AND_HOLD "SDL_MAC_PRESS_AND_HOLD" + /** * Request SDL_AppIterate() be called at a specific rate. * @@ -2430,6 +2678,10 @@ extern "C" { * This defaults to 0, and specifying NULL for the hint's value will restore * the default. * + * This doesn't have to be an integer value. For example, "59.94" won't be + * rounded to an integer rate; the digits after the decimal are actually + * respected. + * * This hint can be set anytime. * * \since This hint is available since SDL 3.2.0. @@ -2485,6 +2737,24 @@ extern "C" { */ #define SDL_HINT_MOUSE_DEFAULT_SYSTEM_CURSOR "SDL_MOUSE_DEFAULT_SYSTEM_CURSOR" +/** + * A variable setting whether we should scale cursors by the current display + * scale. + * + * The variable can be set to the following values: + * + * - "0": Cursors will not change size based on the display content scale. + * (default) + * - "1": Cursors will automatically match the display content scale (e.g. a + * 2x sized cursor will be used when the window is on a monitor with 200% + * scale). This is currently implemented on Windows and Wayland. + * + * This hint needs to be set before creating cursors. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_MOUSE_DPI_SCALE_CURSORS "SDL_MOUSE_DPI_SCALE_CURSORS" + /** * A variable controlling whether warping a hidden mouse cursor will activate * relative mouse mode. @@ -2493,7 +2763,7 @@ extern "C" { * the window center occur within a short time period, SDL will emulate mouse * warps using relative mouse mode. This can provide smoother and more * reliable mouse motion for some older games, which continuously calculate - * the distance travelled by the mouse pointer and warp it back to the center + * the distance traveled by the mouse pointer and warp it back to the center * of the window, rather than using relative mouse motion. * * Note that relative mouse mode may have different mouse acceleration @@ -2736,6 +3006,46 @@ extern "C" { */ #define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" +/** + * A variable controlling whether to force an sRGB-capable OpenGL context. + * + * At OpenGL context creation time, some platforms can request an sRGB-capable + * context. However, sometimes any form of the request can cause surprising + * results on some drivers, platforms, and hardware. Usually the surprise is + * in the form of rendering that is either a little darker or a little + * brighter than intended. + * + * This hint allows the user to override the app's sRGB requests and either + * force a specific value, or avoid requesting anything at all, depending on + * what makes things work correctly for their system. + * + * This is meant as a fail-safe; apps should probably not explicitly set this, + * and most users should not, either. + * + * Note that some platforms cannot make this request at all, and on all + * platforms this request can be denied by the operating system. + * + * In addition to attempting to obtain the type of sRGB-capable OpenGL context + * requested by this hint, SDL will try to force the state of + * GL_FRAMEBUFFER_SRGB on the new context, if appropriate. + * + * The variable can be set to the following values: + * + * - "0": Force a request for an OpenGL context that is _not_ sRGB-capable. + * - "1": Force a request for an OpenGL context that _is_ sRGB-capable. + * - "skip": Don't make any request for an sRGB-capable context + * (don't specify the attribute at all during context creation time). + * - any other string is undefined behavior. + * + * If unset, or set to an empty string, SDL will make a request using the + * value the app specified with the SDL_GL_FRAMEBUFFER_SRGB_CAPABLE attribute. + * + * This hint should be set before an OpenGL context is created. + * + * \since This hint is available since SDL 3.4.2. + */ +#define SDL_HINT_OPENGL_FORCE_SRGB_FRAMEBUFFER "SDL_OPENGL_FORCE_SRGB_FRAMEBUFFER" + /** * Mechanism to specify openvr_api library location * @@ -2859,6 +3169,24 @@ extern "C" { */ #define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" +/** + * A variable controlling whether to use the Direct3D 11 WARP software + * rasterizer. + * + * For more information, see: + * https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp + * + * The variable can be set to the following values: + * + * - "0": Disable WARP rasterizer. (default) + * - "1": Enable WARP rasterizer. + * + * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_RENDER_DIRECT3D11_WARP "SDL_RENDER_DIRECT3D11_WARP" + /** * A variable controlling whether to enable Vulkan Validation Layers. * @@ -3041,6 +3369,49 @@ extern "C" { */ #define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" +/** + * A variable controlling the width of the PS2's framebuffer in pixels. + * + * By default, the variable is "640". + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_PS2_GS_WIDTH "SDL_PS2_GS_WIDTH" + +/** + * A variable controlling the height of the PS2's framebuffer in pixels. + * + * By default, the variable is "448". + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_PS2_GS_HEIGHT "SDL_PS2_GS_HEIGHT" + +/** + * A variable controlling whether the signal is interlaced or progressive. + * + * The variable can be set to the following values: + * + * - "0": Image is interlaced. (default) + * - "1": Image is progressive. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_PS2_GS_PROGRESSIVE "SDL_PS2_GS_PROGRESSIVE" + +/** + * A variable controlling the video mode of the console. + * + * The variable can be set to the following values: + * + * - "": Console-native. (default) + * - "NTSC": 60hz region. + * - "PAL": 50hz region. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_PS2_GS_MODE "SDL_PS2_GS_MODE" + /** * A variable controlling which Dispmanx layer to use on a Raspberry PI. * @@ -3267,10 +3638,12 @@ extern "C" { * prioritized in the list of displays, as exposed by calling * SDL_GetDisplays(), with the first listed becoming the primary display. The * naming convention can vary depending on the environment, but it is usually - * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-A-1',etc...). + * a connector name (e.g. 'DP-1', 'DP-2', 'HDMI-A-1', etc...). * - * On Wayland and X11 desktops, the connector names associated with displays - * can typically be found by using the `xrandr` utility. + * On Wayland desktops, the connector names associated with displays can be + * found in the `name` property of the info output from `wayland-info -i + * wl_output`. On X11 desktops, the `xrandr` utility can be used to retrieve + * the connector names associated with displays. * * This hint is currently supported on the following drivers: * @@ -3407,6 +3780,43 @@ extern "C" { */ #define SDL_HINT_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY "SDL_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY" +/** + * A variable indicating whether the metal layer drawable size should be + * updated for the SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event on macOS. + * + * The variable can be set to the following values: + * + * - "0": the metal layer drawable size will not be updated on the + * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. + * - "1": the metal layer drawable size will be updated on the + * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. (default) + * + * This hint should be set before SDL_Metal_CreateView called. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_VIDEO_METAL_AUTO_RESIZE_DRAWABLE "SDL_VIDEO_METAL_AUTO_RESIZE_DRAWABLE" + +/** + * A variable controlling whether SDL will attempt to automatically set the + * destination display to a mode most closely matching that of the previous + * display if an exclusive fullscreen window is moved onto it. + * + * The variable can be set to the following values: + * + * - "0": SDL will not attempt to automatically set a matching mode on the + * destination display. If an exclusive fullscreen window is moved to a new + * display, the window will become fullscreen desktop. + * - "1": SDL will attempt to automatically set a mode on the destination + * display that most closely matches the mode of the display that the + * exclusive fullscreen window was previously on. (default) + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_VIDEO_MATCH_EXCLUSIVE_MODE_ON_MOVE "SDL_VIDEO_MATCH_EXCLUSIVE_MODE_ON_MOVE" + /** * A variable controlling whether fullscreen windows are minimized when they * lose focus. @@ -3414,8 +3824,10 @@ extern "C" { * The variable can be set to the following values: * * - "0": Fullscreen windows will not be minimized when they lose focus. - * (default) * - "1": Fullscreen windows are minimized when they lose focus. + * - "auto": Fullscreen windows are minimized when they lose focus if they use + * exclusive fullscreen modes, so the desktop video mode is restored. + * (default) * * This hint can be set anytime. * @@ -4061,15 +4473,14 @@ extern "C" { * * The variable can be set to the following values: * - * - "0": GameInput is not used for raw keyboard and mouse events. + * - "0": GameInput is not used for raw keyboard and mouse events. (default) * - "1": GameInput is used for raw keyboard and mouse events, if available. - * (default) * * This hint should be set before SDL is initialized. * * \since This hint is available since SDL 3.2.0. */ -#define SDL_HINT_WINDOWS_GAMEINPUT "SDL_WINDOWS_GAMEINPUT" +#define SDL_HINT_WINDOWS_GAMEINPUT "SDL_WINDOWS_GAMEINPUT" /** * A variable controlling whether raw keyboard events are used on Windows. @@ -4085,6 +4496,28 @@ extern "C" { */ #define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD" +/** + * A variable controlling whether or not the RIDEV_NOHOTKEYS flag is set when + * enabling Windows raw keyboard events. + * + * This blocks any hotkeys that have been registered by applications from + * having any effect beyond generating raw WM_INPUT events. + * + * This flag does not affect system-hotkeys like ALT-TAB or CTRL-ALT-DEL, but + * does affect the Windows Logo key since it is a userland hotkey registered + * by explorer.exe. + * + * The variable can be set to the following values: + * + * - "0": Hotkeys are not excluded. (default) + * - "1": Hotkeys are excluded. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS "SDL_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS" + /** * A variable controlling whether SDL uses Kernel Semaphores on Windows. * @@ -4114,7 +4547,7 @@ extern "C" { * * \since This hint is available since SDL 3.2.0. */ -#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" +#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" /** * A variable to specify custom icon resource id from RC file on Windows @@ -4287,7 +4720,6 @@ extern "C" { */ #define SDL_HINT_PEN_TOUCH_EVENTS "SDL_PEN_TOUCH_EVENTS" - /** * An enumeration of hint priorities. * @@ -4386,19 +4818,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetHints(void); * \param name the hint to query. * \returns the string value of a hint or NULL if the hint isn't set. * - * \threadsafety It is safe to call this function from any thread, however the - * return value only remains valid until the hint is changed; if - * another thread might do so, the app should supply locks - * and/or make a copy of the string. Note that using a hint - * callback instead is always thread-safe, as SDL holds a lock - * on the thread subsystem during the callback. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetHint * \sa SDL_SetHintWithPriority */ -extern SDL_DECLSPEC const char * SDLCALL SDL_GetHint(const char *name); +extern SDL_DECLSPEC const char *SDLCALL SDL_GetHint(const char *name); /** * Get the boolean value of a hint variable. @@ -4474,8 +4901,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AddHintCallback(const char *name, SDL_HintC * \sa SDL_AddHintCallback */ extern SDL_DECLSPEC void SDLCALL SDL_RemoveHintCallback(const char *name, - SDL_HintCallback callback, - void *userdata); + SDL_HintCallback callback, + void *userdata); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/vendor/sdl3/include/SDL_init.h b/vendor/sdl3/include/SDL_init.h index adf0de8a2..d75ccc31d 100644 --- a/vendor/sdl3/include/SDL_init.h +++ b/vendor/sdl3/include/SDL_init.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -79,7 +79,7 @@ typedef Uint32 SDL_InitFlags; #define SDL_INIT_AUDIO 0x00000010u /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */ #define SDL_INIT_VIDEO 0x00000020u /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread */ -#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD */ +#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS` */ #define SDL_INIT_HAPTIC 0x00001000u #define SDL_INIT_GAMEPAD 0x00002000u /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ #define SDL_INIT_EVENTS 0x00004000u @@ -101,7 +101,7 @@ typedef Uint32 SDL_InitFlags; * to run. * * See - * [Main callbacks in SDL3](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3) + * [Main callbacks in SDL3](https://wiki.libsdl.org/SDL3/README-main-functions#main-callbacks-in-sdl3) * for complete details. * * \since This enum is available since SDL 3.2.0. @@ -224,6 +224,8 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate, SDL_AppResult result); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetAppMetadata @@ -244,6 +246,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_Init(SDL_InitFlags flags); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Init @@ -260,6 +264,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_InitSubSystem(SDL_InitFlags flags); * * \param flags any of the flags used by SDL_Init(); see SDL_Init for details. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_InitSubSystem @@ -274,6 +280,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_QuitSubSystem(SDL_InitFlags flags); * \returns a mask of all initialized subsystems if `flags` is 0, otherwise it * returns the initialization status of the specified subsystems. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Init @@ -292,6 +300,8 @@ extern SDL_DECLSPEC SDL_InitFlags SDLCALL SDL_WasInit(SDL_InitFlags flags); * application is shutdown, but it is not wise to do this from a library or * other dynamically loaded code. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Init diff --git a/vendor/sdl3/include/SDL_intrin.h b/vendor/sdl3/include/SDL_intrin.h index bac6d7ad4..59a3831e2 100644 --- a/vendor/sdl3/include/SDL_intrin.h +++ b/vendor/sdl3/include/SDL_intrin.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -268,6 +268,7 @@ _m_prefetch(void *__P) #endif /* compiler version */ #ifdef SDL_WIKI_DOCUMENTATION_SECTION + /** * A macro to decide if the compiler supports `__attribute__((target))`. * @@ -280,12 +281,14 @@ _m_prefetch(void *__P) * \sa SDL_TARGETING */ #define SDL_HAS_TARGET_ATTRIBS - +#elif defined(__loongarch64) && defined(__GNUC__) && (__GNUC__ >= 15) +/* LoongArch requires GCC 15+ for target attribute support */ +# define SDL_HAS_TARGET_ATTRIBS #elif defined(__clang__) && defined(__has_attribute) # if __has_attribute(target) # define SDL_HAS_TARGET_ATTRIBS # endif -#elif defined(__GNUC__) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */ +#elif defined(__GNUC__) && !defined(__loongarch64) && (__GNUC__ + (__GNUC_MINOR__ >= 9) > 4) /* gcc >= 4.9 */ # define SDL_HAS_TARGET_ATTRIBS #elif defined(__ICC) && __ICC >= 1600 # define SDL_HAS_TARGET_ATTRIBS diff --git a/vendor/sdl3/include/SDL_iostream.h b/vendor/sdl3/include/SDL_iostream.h index 4ca16093e..f369fde17 100644 --- a/vendor/sdl3/include/SDL_iostream.h +++ b/vendor/sdl3/include/SDL_iostream.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -111,7 +111,7 @@ typedef struct SDL_IOStreamInterface /** * Read up to `size` bytes from the data stream to the area pointed - * at by `ptr`. + * at by `ptr`. `size` will always be > 0. * * On an incomplete read, you should set `*status` to a value from the * SDL_IOStatus enum. You do not have to explicitly set this on @@ -123,7 +123,7 @@ typedef struct SDL_IOStreamInterface /** * Write exactly `size` bytes from the area pointed at by `ptr` - * to data stream. + * to data stream. `size` will always be > 0. * * On an incomplete write, you should set `*status` to a value from the * SDL_IOStatus enum. You do not have to explicitly set this on @@ -203,6 +203,8 @@ typedef struct SDL_IOStream SDL_IOStream; * - "w": Create an empty file for writing. If a file with the same name * already exists its content is erased and the file is treated as a new * empty file. + * - "wx": Create an empty file for writing. If a file with the same name + * already exists, the call fails. * - "a": Append to a file. Writing operations append data at the end of the * file. The file is created if it does not exist. * - "r+": Open a file for update both reading and writing. The file must @@ -210,6 +212,8 @@ typedef struct SDL_IOStream SDL_IOStream; * - "w+": Create an empty file for both reading and writing. If a file with * the same name already exists its content is erased and the file is * treated as a new empty file. + * - "w+x": Create an empty file for both reading and writing. If a file with + * the same name already exists, the call fails. * - "a+": Open a file for reading and appending. All writing operations are * performed at the end of the file, protecting the previous content to be * overwritten. You can reposition (fseek, rewind) the internal pointer to @@ -260,7 +264,7 @@ typedef struct SDL_IOStream SDL_IOStream; * \returns a pointer to the SDL_IOStream structure that is created or NULL on * failure; call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * @@ -286,8 +290,7 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromFile(const char *file, cons * certain size, for both read and write access. * * This memory buffer is not copied by the SDL_IOStream; the pointer you - * provide must remain valid until you close the stream. Closing the stream - * will not free the original buffer. + * provide must remain valid until you close the stream. * * If you need to make sure the SDL_IOStream never writes to the memory * buffer, you should use SDL_IOFromConstMem() with a read-only buffer of @@ -300,6 +303,13 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromFile(const char *file, cons * - `SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER`: this will be the `size` parameter * that was passed to this function. * + * Additionally, the following properties are recognized: + * + * - `SDL_PROP_IOSTREAM_MEMORY_FREE_FUNC_POINTER`: if this property is set to + * a non-NULL value it will be interpreted as a function of SDL_free_func + * type and called with the passed `mem` pointer when closing the stream. By + * default it is unset, i.e., the memory will not be freed. + * * \param mem a pointer to a buffer to feed an SDL_IOStream stream. * \param size the buffer size, in bytes. * \returns a pointer to a new SDL_IOStream structure or NULL on failure; call @@ -321,6 +331,7 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromMem(void *mem, size_t size) #define SDL_PROP_IOSTREAM_MEMORY_POINTER "SDL.iostream.memory.base" #define SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER "SDL.iostream.memory.size" +#define SDL_PROP_IOSTREAM_MEMORY_FREE_FUNC_POINTER "SDL.iostream.memory.free" /** * Use this function to prepare a read-only memory buffer for use with @@ -333,8 +344,7 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromMem(void *mem, size_t size) * without writing to the memory buffer. * * This memory buffer is not copied by the SDL_IOStream; the pointer you - * provide must remain valid until you close the stream. Closing the stream - * will not free the original buffer. + * provide must remain valid until you close the stream. * * If you need to write to a memory buffer, you should use SDL_IOFromMem() * with a writable buffer of memory instead. @@ -346,6 +356,13 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromMem(void *mem, size_t size) * - `SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER`: this will be the `size` parameter * that was passed to this function. * + * Additionally, the following properties are recognized: + * + * - `SDL_PROP_IOSTREAM_MEMORY_FREE_FUNC_POINTER`: if this property is set to + * a non-NULL value it will be interpreted as a function of SDL_free_func + * type and called with the passed `mem` pointer when closing the stream. By + * default it is unset, i.e., the memory will not be freed. + * * \param mem a pointer to a read-only buffer to feed an SDL_IOStream stream. * \param size the buffer size, in bytes. * \returns a pointer to a new SDL_IOStream structure or NULL on failure; call @@ -452,7 +469,7 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_OpenIO(const SDL_IOStreamInterfac * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -467,7 +484,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CloseIO(SDL_IOStream *context); * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -487,7 +504,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *c * \param context the SDL_IOStream to query. * \returns an SDL_IOStatus enum with the current state. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -501,7 +518,7 @@ extern SDL_DECLSPEC SDL_IOStatus SDLCALL SDL_GetIOStatus(SDL_IOStream *context); * negative error code on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -528,7 +545,7 @@ extern SDL_DECLSPEC Sint64 SDLCALL SDL_GetIOSize(SDL_IOStream *context); * \returns the final offset in the data stream after the seek or -1 on * failure; call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -548,7 +565,7 @@ extern SDL_DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offs * \returns the current offset in the stream, or -1 if the information can not * be determined. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -567,13 +584,17 @@ extern SDL_DECLSPEC Sint64 SDLCALL SDL_TellIO(SDL_IOStream *context); * the stream is not at EOF, SDL_GetIOStatus() will return a different error * value and SDL_GetError() will offer a human-readable message. * + * A request for zero bytes on a valid stream will return zero immediately + * without accessing the stream, so the stream status (EOF, err, etc) will not + * change. + * * \param context a pointer to an SDL_IOStream structure. * \param ptr a pointer to a buffer to read data into. * \param size the number of bytes to read from the data source. * \returns the number of bytes read, or 0 on end of file or other failure; * call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -596,13 +617,17 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_ReadIO(SDL_IOStream *context, void *ptr, * recoverable, such as a non-blocking write that can simply be retried later, * or a fatal error. * + * A request for zero bytes on a valid stream will return zero immediately + * without accessing the stream, so the stream status (EOF, err, etc) will not + * change. + * * \param context a pointer to an SDL_IOStream structure. * \param ptr a pointer to a buffer containing data to write. * \param size the number of bytes to write. * \returns the number of bytes written, which will be less than `size` on * failure; call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -626,7 +651,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void * \returns the number of bytes written or 0 on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -646,7 +671,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_IOprintf(SDL_IOStream *context, SDL_PRINT * \returns the number of bytes written or 0 on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -666,7 +691,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_IOvprintf(SDL_IOStream *context, SDL_PRIN * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -692,7 +717,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlushIO(SDL_IOStream *context); * \returns the data or NULL on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -715,7 +740,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *da * \returns the data or NULL on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * @@ -736,7 +761,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile(const char *file, size_t *datasi * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. * @@ -755,7 +780,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveFile_IO(SDL_IOStream *src, const void * * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * @@ -784,7 +809,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveFile(const char *file, const void *data * \returns true on success or false on failure or EOF; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -803,7 +828,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value); * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -823,10 +848,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS8(SDL_IOStream *src, Sint8 *value); * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -846,10 +871,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -869,10 +894,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -892,10 +917,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -915,10 +940,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -938,10 +963,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -961,10 +986,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -984,10 +1009,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1007,10 +1032,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1030,10 +1055,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1053,10 +1078,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1076,10 +1101,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value) * * \param src the stream from which to read data. * \param value a pointer filled in with the data read. - * \returns true on successful write or false on failure; call SDL_GetError() + * \returns true on successful read or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1101,7 +1126,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1115,7 +1140,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value); * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1134,7 +1159,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS8(SDL_IOStream *dst, Sint8 value); * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1153,7 +1178,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1171,7 +1196,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1189,7 +1214,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1208,7 +1233,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1227,7 +1252,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1245,7 +1270,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1263,7 +1288,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1282,7 +1307,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1301,7 +1326,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1319,7 +1344,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ @@ -1337,7 +1362,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value) * \returns true on successful write or false on failure; call SDL_GetError() * for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety Do not use the same SDL_IOStream from two threads at once. * * \since This function is available since SDL 3.2.0. */ diff --git a/vendor/sdl3/include/SDL_joystick.h b/vendor/sdl3/include/SDL_joystick.h index d15668b66..c93b35210 100644 --- a/vendor/sdl3/include/SDL_joystick.h +++ b/vendor/sdl3/include/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -29,8 +29,8 @@ * instead. * * The term "instance_id" is the current instantiation of a joystick device in - * the system, if the joystick is removed and then re-inserted then it will - * get a new instance_id, instance_id's are monotonically increasing + * the system. If the joystick is removed and then re-inserted then it will + * get a new instance_id. instance_id's are monotonically increasing * identifiers of a joystick plugged in. * * The term "player_index" is the number assigned to a player on a specific @@ -48,6 +48,14 @@ * If you would like to receive joystick updates while the application is in * the background, you should set the following hint before calling * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS + * + * SDL can provide virtual joysticks as well: the app defines an imaginary + * controller with SDL_AttachVirtualJoystick(), and then can provide inputs + * for it via SDL_SetJoystickVirtualAxis(), SDL_SetJoystickVirtualButton(), + * etc. As this data is supplied, it will look like a normal joystick to SDL, + * just not backed by a hardware driver. This has been used to make unusual + * devices, like VR headset controllers, look like normal joysticks, or + * provide recording/playback of game inputs, etc. */ #ifndef SDL_joystick_h_ @@ -107,6 +115,10 @@ typedef Uint32 SDL_JoystickID; * This is by no means a complete list of everything that can be plugged into * a computer. * + * You may refer to + * [XInput Controller Types](https://learn.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes) + * table for a general understanding of each joystick type. + * * \since This enum is available since SDL 3.2.0. */ typedef enum SDL_JoystickType @@ -170,6 +182,8 @@ typedef enum SDL_JoystickConnectionState * joysticks while processing to guarantee that the joystick list won't change * and joystick and gamepad events will not be delivered. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock); @@ -177,6 +191,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystic /** * Unlocking for atomic access to the joystick API. * + * \threadsafety This should be called from the same thread that called + * SDL_LockJoysticks(). + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock); @@ -186,6 +203,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joyst * * \returns true if a joystick is connected, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoysticks @@ -201,6 +220,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasJoystick(void); * call SDL_GetError() for more information. This should be freed * with SDL_free() when it is no longer needed. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_HasJoystick @@ -217,6 +238,8 @@ extern SDL_DECLSPEC SDL_JoystickID * SDLCALL SDL_GetJoysticks(int *count); * \returns the name of the selected joystick. If no name can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickName @@ -233,6 +256,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickNameForID(SDL_JoystickID * \returns the path of the selected joystick. If no path can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickPath @@ -248,6 +273,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickPathForID(SDL_JoystickID * \param instance_id the joystick instance ID. * \returns the player index of a joystick, or -1 if it's not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickPlayerIndex @@ -264,6 +291,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndexForID(SDL_JoystickID i * \returns the GUID of the selected joystick. If called with an invalid * instance_id, this function returns a zero GUID. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickGUID @@ -281,6 +310,8 @@ extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetJoystickGUIDForID(SDL_JoystickID ins * \returns the USB vendor ID of the selected joystick. If called with an * invalid instance_id, this function returns 0. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickVendor @@ -298,6 +329,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendorForID(SDL_JoystickID ins * \returns the USB product ID of the selected joystick. If called with an * invalid instance_id, this function returns 0. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickProduct @@ -315,6 +348,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductForID(SDL_JoystickID in * \returns the product version of the selected joystick. If called with an * invalid instance_id, this function returns 0. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickProductVersion @@ -332,6 +367,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersionForID(SDL_Joysti * invalid instance_id, this function returns * `SDL_JOYSTICK_TYPE_UNKNOWN`. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickType @@ -349,6 +386,8 @@ extern SDL_DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickTypeForID(SDL_Joysti * \returns a joystick identifier or NULL on failure; call SDL_GetError() for * more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CloseJoystick @@ -362,6 +401,8 @@ extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_OpenJoystick(SDL_JoystickID insta * \returns an SDL_Joystick on success or NULL on failure or if it hasn't been * opened yet; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetJoystickFromID(SDL_JoystickID instance_id); @@ -373,6 +414,8 @@ extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetJoystickFromID(SDL_JoystickID * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError() * for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickPlayerIndex @@ -465,13 +508,33 @@ SDL_COMPILE_TIME_ASSERT(SDL_VirtualJoystickDesc_SIZE, /** * Attach a new virtual joystick. * + * Apps can create virtual joysticks, that exist without hardware directly + * backing them, and have program-supplied inputs. Once attached, a virtual + * joystick looks like any other joystick that SDL can access. These can be + * used to make other things look like joysticks, or provide pre-recorded + * input, etc. + * + * Once attached, the app can send joystick inputs to the new virtual joystick + * using SDL_SetJoystickVirtualAxis(), etc. + * + * When no longer needed, the virtual joystick can be removed by calling + * SDL_DetachVirtualJoystick(). + * * \param desc joystick description, initialized using SDL_INIT_INTERFACE(). * \returns the joystick instance ID, or 0 on failure; call SDL_GetError() for * more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DetachVirtualJoystick + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualTouchpad + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(const SDL_VirtualJoystickDesc *desc); @@ -483,6 +546,8 @@ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(const SDL_V * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AttachVirtualJoystick @@ -495,6 +560,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_DetachVirtualJoystick(SDL_JoystickID instan * \param instance_id the joystick instance ID. * \returns true if the joystick is virtual, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_id); @@ -518,7 +585,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_i * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualTouchpad + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value); @@ -538,7 +613,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualAxis(SDL_Joystick *joysti * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualTouchpad + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualBall(SDL_Joystick *joystick, int ball, Sint16 xrel, Sint16 yrel); @@ -557,7 +640,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualBall(SDL_Joystick *joysti * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualTouchpad + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, bool down); @@ -576,7 +667,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joys * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualTouchpad + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value); @@ -602,7 +701,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystic * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualSensorData */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualTouchpad(SDL_Joystick *joystick, int touchpad, int finger, bool down, float x, float y, float pressure); @@ -624,7 +731,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualTouchpad(SDL_Joystick *jo * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_SetJoystickVirtualAxis + * \sa SDL_SetJoystickVirtualButton + * \sa SDL_SetJoystickVirtualBall + * \sa SDL_SetJoystickVirtualHat + * \sa SDL_SetJoystickVirtualTouchpad */ extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickVirtualSensorData(SDL_Joystick *joystick, SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values); @@ -648,6 +763,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickVirtualSensorData(SDL_Joystick * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick *joystick); @@ -665,6 +782,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joyst * \returns the name of the selected joystick. If no name can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickNameForID @@ -678,6 +797,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickName(SDL_Joystick *joyst * \returns the path of the selected joystick. If no path can be found, this * function returns NULL; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickPathForID @@ -693,6 +814,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickPath(SDL_Joystick *joyst * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the player index, or -1 if it's not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetJoystickPlayerIndex @@ -708,6 +831,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndex(SDL_Joystick *joystic * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickPlayerIndex @@ -724,6 +849,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickPlayerIndex(SDL_Joystick *joysti * this function returns a zero GUID; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickGUIDForID @@ -739,6 +866,8 @@ extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetJoystickGUID(SDL_Joystick *joystick) * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the USB vendor ID of the selected joystick, or 0 if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickVendorForID @@ -753,6 +882,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendor(SDL_Joystick *joystick) * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the USB product ID of the selected joystick, or 0 if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickProductForID @@ -767,6 +898,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProduct(SDL_Joystick *joystick * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the product version of the selected joystick, or 0 if unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickProductVersionForID @@ -782,6 +915,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersion(SDL_Joystick *j * \returns the firmware version of the selected joystick, or 0 if * unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickFirmwareVersion(SDL_Joystick *joystick); @@ -795,6 +930,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickFirmwareVersion(SDL_Joystick * * \returns the serial number of the selected joystick, or NULL if * unavailable. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickSerial(SDL_Joystick *joystick); @@ -805,6 +942,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickSerial(SDL_Joystick *joy * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the SDL_JoystickType of the selected joystick. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickTypeForID @@ -824,6 +963,8 @@ extern SDL_DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickType(SDL_Joystick *j * \param crc16 a pointer filled in with a CRC used to distinguish different * products with the same VID/PID, or 0 if not available. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickGUIDForID @@ -837,6 +978,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_GUID guid, Uint16 * * \returns true if the joystick has been opened, false if it has not; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); @@ -848,6 +991,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); * \returns the instance ID of the specified joystick on success or 0 on * failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickID(SDL_Joystick *joystick); @@ -863,6 +1008,8 @@ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickID(SDL_Joystick *joyst * \returns the number of axis controls/number of axes on success or -1 on * failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickAxis @@ -884,6 +1031,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); * \returns the number of trackballs on success or -1 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickBall @@ -900,6 +1049,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickBalls(SDL_Joystick *joystick); * \returns the number of POV hats on success or -1 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickHat @@ -916,6 +1067,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); * \returns the number of buttons on success or -1 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetJoystickButton @@ -934,6 +1087,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick * * \param enabled whether to process joystick events or not. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_JoystickEventsEnabled @@ -950,6 +1105,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetJoystickEventsEnabled(bool enabled); * * \returns true if joystick events are being processed, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetJoystickEventsEnabled @@ -962,6 +1119,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_JoystickEventsEnabled(void); * This is called automatically by the event loop if any joystick events are * enabled. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); @@ -984,6 +1143,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); * \returns a 16-bit signed integer representing the current position of the * axis or 0 on failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumJoystickAxes @@ -1002,6 +1163,8 @@ extern SDL_DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, i * \param state upon return, the initial value is supplied here. * \returns true if this axis has any initial value, or false if not. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state); @@ -1021,6 +1184,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *j * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumJoystickBalls @@ -1036,6 +1201,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickBall(SDL_Joystick *joystick, int * \param hat the hat index to get the state from; indices start at index 0. * \returns the current hat position. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumJoystickHats @@ -1060,6 +1227,8 @@ extern SDL_DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, int * index 0. * \returns true if the button is pressed, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetNumJoystickButtons @@ -1083,6 +1252,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, i * \param duration_ms the duration of the rumble effect, in milliseconds. * \returns true, or false if rumble isn't supported on this joystick. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); @@ -1110,6 +1281,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_RumbleJoystick @@ -1132,6 +1305,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joysti * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); @@ -1145,6 +1320,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickLED(SDL_Joystick *joystick, Uint * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickEffect(SDL_Joystick *joystick, const void *data, int size); @@ -1154,6 +1331,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickEffect(SDL_Joystick *joystick, * * \param joystick the joystick device to close. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_OpenJoystick @@ -1168,6 +1347,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseJoystick(SDL_Joystick *joystick); * `SDL_JOYSTICK_CONNECTION_INVALID` on failure; call SDL_GetError() * for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectionState(SDL_Joystick *joystick); @@ -1189,6 +1370,8 @@ extern SDL_DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectio * \returns the current battery state or `SDL_POWERSTATE_ERROR` on failure; * call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetJoystickPowerInfo(SDL_Joystick *joystick, int *percent); diff --git a/vendor/sdl3/include/SDL_keyboard.h b/vendor/sdl3/include/SDL_keyboard.h index afa77b6c2..d14ab6fb2 100644 --- a/vendor/sdl3/include/SDL_keyboard.h +++ b/vendor/sdl3/include/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -174,8 +174,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetKeyboard(void); /** * Get the current key modifier state for the keyboard. * - * \returns an OR'd combination of the modifier keys for the keyboard. See - * SDL_Keymod for details. + * \returns an OR'd combination of the modifier keys for the keyboard. * * \threadsafety It is safe to call this function from any thread. * diff --git a/vendor/sdl3/include/SDL_keycode.h b/vendor/sdl3/include/SDL_keycode.h index 61b68e794..1818ee3e4 100644 --- a/vendor/sdl3/include/SDL_keycode.h +++ b/vendor/sdl3/include/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -45,12 +45,16 @@ * `SDLK_*` constant for those keys that do not generate characters. * * A special exception is the number keys at the top of the keyboard which map - * to SDLK_0...SDLK_9 on AZERTY layouts. + * by default to SDLK_0...SDLK_9 on AZERTY layouts. * * Keys with the `SDLK_EXTENDED_MASK` bit set do not map to a scancode or - * unicode code point. + * Unicode code point. + * + * Many common keycodes are listed below, but this list is not exhaustive. * * \since This datatype is available since SDL 3.2.0. + * + * \sa SDL_HINT_KEYCODE_OPTIONS */ typedef Uint32 SDL_Keycode; diff --git a/vendor/sdl3/include/SDL_loadso.h b/vendor/sdl3/include/SDL_loadso.h index f8649d758..51d0d8811 100644 --- a/vendor/sdl3/include/SDL_loadso.h +++ b/vendor/sdl3/include/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_locale.h b/vendor/sdl3/include/SDL_locale.h index 902843e81..9f03aa90d 100644 --- a/vendor/sdl3/include/SDL_locale.h +++ b/vendor/sdl3/include/SDL_locale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -102,6 +102,8 @@ typedef struct SDL_Locale * allocation that should be freed with SDL_free() when it is no * longer needed. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Locale ** SDLCALL SDL_GetPreferredLocales(int *count); diff --git a/vendor/sdl3/include/SDL_log.h b/vendor/sdl3/include/SDL_log.h index 3fd7ec2ed..2ae0963c2 100644 --- a/vendor/sdl3/include/SDL_log.h +++ b/vendor/sdl3/include/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -206,6 +206,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetLogPriorities(void); * SDL_LOG_PRIORITY_WARN and higher have a prefix showing their priority, e.g. * "WARNING: ". * + * This function makes a copy of its string argument, **prefix**, so it is not + * necessary to keep the value of **prefix** alive after the call returns. + * * \param priority the SDL_LogPriority to modify. * \param prefix the prefix to use for that log priority, or NULL to use no * prefix. @@ -263,7 +266,6 @@ extern SDL_DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fm * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV - * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ diff --git a/vendor/sdl3/include/SDL_main.h b/vendor/sdl3/include/SDL_main.h index 905d78e96..ee4d9ca71 100644 --- a/vendor/sdl3/include/SDL_main.h +++ b/vendor/sdl3/include/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -47,7 +47,7 @@ * * For more information, see: * - * https://wiki.libsdl.org/SDL3/README/main-functions + * https://wiki.libsdl.org/SDL3/README-main-functions */ #ifndef SDL_main_h_ @@ -68,7 +68,7 @@ * proper entry point for the platform, and all the other magic details * needed, like manually calling SDL_SetMainReady. * - * Please see [README/main-functions](README/main-functions), (or + * Please see [README-main-functions](README-main-functions), (or * docs/README-main-functions.md in the source tree) for a more detailed * explanation. * @@ -85,7 +85,7 @@ * SDL_AppQuit. The app should not provide a `main` function in this case, and * doing so will likely cause the build to fail. * - * Please see [README/main-functions](README/main-functions), (or + * Please see [README-main-functions](README-main-functions), (or * docs/README-main-functions.md in the source tree) for a more detailed * explanation. * @@ -110,7 +110,8 @@ * Even if available, an app can define SDL_MAIN_HANDLED and provide their * own, if they know what they're doing. * - * This macro is used internally by SDL, and apps probably shouldn't rely on it. + * This macro is used internally by SDL, and apps probably shouldn't rely on + * it. * * \since This macro is available since SDL 3.2.0. */ @@ -125,10 +126,11 @@ * This macro is defined by `SDL_main.h`, which is not automatically included * by `SDL.h`. * - * Even if required, an app can define SDL_MAIN_HANDLED and provide their - * own, if they know what they're doing. + * Even if required, an app can define SDL_MAIN_HANDLED and provide their own, + * if they know what they're doing. * - * This macro is used internally by SDL, and apps probably shouldn't rely on it. + * This macro is used internally by SDL, and apps probably shouldn't rely on + * it. * * \since This macro is available since SDL 3.2.0. */ @@ -165,12 +167,10 @@ */ #define SDL_MAIN_NEEDED - #elif defined(SDL_PLATFORM_IOS) - /* On iOS SDL provides a main function that creates an application delegate - and starts the iOS application run loop. + #elif defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) + /* On iOS and tvOS SDL provides a main function that creates an application delegate and starts the application run loop. - To use it, just #include SDL_main.h in the source file that contains your - main() function. + To use it, just #include in the source file that contains your main() function. See src/video/uikit/SDL_uikitappdelegate.m for more details. */ @@ -333,6 +333,8 @@ extern "C" { * \returns SDL_APP_FAILURE to terminate with an error, SDL_APP_SUCCESS to * terminate with success, SDL_APP_CONTINUE to continue. * + * \threadsafety This function is called once by SDL, at startup, on a single thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AppIterate @@ -347,10 +349,10 @@ extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppInit(void **appstate, int a * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If using a * standard "main" function, you should not supply this. * - * This function is called repeatedly by SDL after SDL_AppInit returns 0. The - * function should operate as a single iteration the program's primary loop; - * it should update whatever state it needs and draw a new frame of video, - * usually. + * This function is called repeatedly by SDL after SDL_AppInit returns + * SDL_APP_CONTINUE. The function should operate as a single iteration the + * program's primary loop; it should update whatever state it needs and draw a + * new frame of video, usually. * * On some platforms, this function will be called at the refresh rate of the * display (which might change during the life of your app!). There are no @@ -449,8 +451,8 @@ extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_E * * This function is called once by SDL before terminating the program. * - * This function will be called no matter what, even if SDL_AppInit requests - * termination. + * This function will be called in all cases, even if SDL_AppInit requests + * termination at startup. * * This function should not go into an infinite mainloop; it should * deinitialize any resources necessary, perform whatever shutdown activities, @@ -512,7 +514,7 @@ typedef int (SDLCALL *SDL_main_func)(int argc, char *argv[]); * SDL_MAIN_USE_CALLBACKS. * * Program startup is a surprisingly complex topic. Please see - * [README/main-functions](README/main-functions), (or + * [README-main-functions](README-main-functions), (or * docs/README-main-functions.md in the source tree) for a more detailed * explanation. * @@ -537,6 +539,8 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_main(int argc, char *argv[]); * will not be changed it is necessary to define SDL_MAIN_HANDLED before * including SDL.h. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Init @@ -553,6 +557,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetMainReady(void); * using SDL_main (like when using SDL_MAIN_HANDLED). When using this, you do * *not* need SDL_SetMainReady(). * + * If `argv` is NULL, SDL will provide command line arguments, either by + * querying the OS for them if possible, or supplying a filler array if not. + * * \param argc the argc parameter from the application's main() function, or 0 * if the platform's main-equivalent has no argc. * \param argv the argv parameter from the application's main() function, or @@ -615,16 +622,19 @@ extern SDL_DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char *argv[] * Most applications do not need to, and should not, call this directly; SDL * will call it when initializing the video subsystem. * + * If `name` is NULL, SDL currently uses `(CS_BYTEALIGNCLIENT | CS_OWNDC)` for + * the style, regardless of what is specified here. + * * \param name the window class name, in UTF-8 encoding. If NULL, SDL * currently uses "SDL_app" but this isn't guaranteed. - * \param style the value to use in WNDCLASSEX::style. If `name` is NULL, SDL - * currently uses `(CS_BYTEALIGNCLIENT | CS_OWNDC)` regardless of - * what is specified here. + * \param style the value to use in WNDCLASSEX::style. * \param hInst the HINSTANCE to use in WNDCLASSEX::hInstance. If zero, SDL * will use `GetModuleHandle(NULL)` instead. * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); @@ -642,6 +652,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RegisterApp(const char *name, Uint32 style, * deregistered when the registration counter in SDL_RegisterApp decrements to * zero through calls to this function. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void); @@ -654,6 +666,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void); * This function is only needed for Xbox GDK support; all other platforms will * do nothing and set an "unsupported" error message. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); diff --git a/vendor/sdl3/include/SDL_main_impl.h b/vendor/sdl3/include/SDL_main_impl.h index 14ebb4291..bf5f58363 100644 --- a/vendor/sdl3/include/SDL_main_impl.h +++ b/vendor/sdl3/include/SDL_main_impl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_messagebox.h b/vendor/sdl3/include/SDL_messagebox.h index 365ae36a5..af604e2c7 100644 --- a/vendor/sdl3/include/SDL_messagebox.h +++ b/vendor/sdl3/include/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -168,6 +168,8 @@ typedef struct SDL_MessageBoxData * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ShowSimpleMessageBox @@ -210,6 +212,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *me * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ShowMessageBox diff --git a/vendor/sdl3/include/SDL_metal.h b/vendor/sdl3/include/SDL_metal.h index 14b1bc87a..6b0e171b4 100644 --- a/vendor/sdl3/include/SDL_metal.h +++ b/vendor/sdl3/include/SDL_metal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,6 +65,8 @@ typedef void *SDL_MetalView; * \param window the window. * \returns handle NSView or UIView. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Metal_DestroyView @@ -80,6 +82,8 @@ extern SDL_DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window *windo * * \param view the SDL_MetalView object. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_Metal_CreateView @@ -92,6 +96,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view); * \param view the SDL_MetalView object. * \returns a pointer. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void * SDLCALL SDL_Metal_GetLayer(SDL_MetalView view); diff --git a/vendor/sdl3/include/SDL_misc.h b/vendor/sdl3/include/SDL_misc.h index 3dd6fcddd..654c00558 100644 --- a/vendor/sdl3/include/SDL_misc.h +++ b/vendor/sdl3/include/SDL_misc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,6 +65,8 @@ extern "C" { * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_OpenURL(const char *url); diff --git a/vendor/sdl3/include/SDL_mouse.h b/vendor/sdl3/include/SDL_mouse.h index 864135d2b..fb03c0178 100644 --- a/vendor/sdl3/include/SDL_mouse.h +++ b/vendor/sdl3/include/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -130,6 +130,17 @@ typedef enum SDL_MouseWheelDirection SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */ } SDL_MouseWheelDirection; +/** + * Animated cursor frame info. + * + * \since This struct is available since SDL 3.4.0. + */ +typedef struct SDL_CursorFrameInfo +{ + SDL_Surface *surface; /**< The surface data for this frame */ + Uint32 duration; /**< The frame duration in milliseconds (a duration of 0 is infinite) */ +} SDL_CursorFrameInfo; + /** * A bitmask of pressed mouse buttons, as reported by SDL_GetMouseState, etc. * @@ -160,6 +171,44 @@ typedef Uint32 SDL_MouseButtonFlags; #define SDL_BUTTON_X1MASK SDL_BUTTON_MASK(SDL_BUTTON_X1) #define SDL_BUTTON_X2MASK SDL_BUTTON_MASK(SDL_BUTTON_X2) +/** + * A callback used to transform mouse motion delta from raw values. + * + * This is called during SDL's handling of platform mouse events to scale the + * values of the resulting motion delta. + * + * \param userdata what was passed as `userdata` to + * SDL_SetRelativeMouseTransform(). + * \param timestamp the associated time at which this mouse motion event was + * received. + * \param window the associated window to which this mouse motion event was + * addressed. + * \param mouseID the associated mouse from which this mouse motion event was + * emitted. + * \param x pointer to a variable that will be treated as the resulting x-axis + * motion. + * \param y pointer to a variable that will be treated as the resulting y-axis + * motion. + * + * \threadsafety This callback is called by SDL's internal mouse input + * processing procedure, which may be a thread separate from the + * main event loop that is run at realtime priority. Stalling + * this thread with too much work in the callback can therefore + * potentially freeze the entire system. Care should be taken + * with proper synchronization practices when adding other side + * effects beyond mutation of the x and y values. + * + * \since This datatype is available since SDL 3.4.0. + * + * \sa SDL_SetRelativeMouseTransform + */ +typedef void (SDLCALL *SDL_MouseMotionTransformCallback)( + void *userdata, + Uint64 timestamp, + SDL_Window *window, + SDL_MouseID mouseID, + float *x, float *y +); /* Function prototypes */ @@ -380,6 +429,24 @@ extern SDL_DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window *window, */ extern SDL_DECLSPEC bool SDLCALL SDL_WarpMouseGlobal(float x, float y); +/** + * Set a user-defined function by which to transform relative mouse inputs. + * + * This overrides the relative system scale and relative speed scale hints. + * Should be called prior to enabling relative mouse mode, fails otherwise. + * + * \param callback a callback used to transform relative mouse motion, or NULL + * for default behavior. + * \param userdata a pointer that will be passed to `callback`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetRelativeMouseTransform(SDL_MouseMotionTransformCallback callback, void *userdata); + /** * Set relative mouse mode for a window. * @@ -509,6 +576,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CaptureMouse(bool enabled); * * \since This function is available since SDL 3.2.0. * + * \sa SDL_CreateAnimatedCursor * \sa SDL_CreateColorCursor * \sa SDL_CreateSystemCursor * \sa SDL_DestroyCursor @@ -522,15 +590,17 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data, /** * Create a color cursor. * - * If this function is passed a surface with alternate representations, the - * surface will be interpreted as the content to be used for 100% display - * scale, and the alternate representations will be used for high DPI - * situations. For example, if the original surface is 32x32, then on a 2x - * macOS display or 200% display scale on Windows, a 64x64 version of the - * image will be used, if available. If a matching version of the image isn't - * available, the closest larger size image will be downscaled to the - * appropriate size and be used instead, if available. Otherwise, the closest - * smaller image will be upscaled and be used instead. + * If this function is passed a surface with alternate representations added + * with SDL_AddSurfaceAlternateImage(), the surface will be interpreted as the + * content to be used for 100% display scale, and the alternate + * representations will be used for high DPI situations if + * SDL_HINT_MOUSE_DPI_SCALE_CURSORS is enabled. For example, if the original + * surface is 32x32, then on a 2x macOS display or 200% display scale on + * Windows, a 64x64 version of the image will be used, if available. If a + * matching version of the image isn't available, the closest larger size + * image will be downscaled to the appropriate size and be used instead, if + * available. Otherwise, the closest smaller image will be upscaled and be + * used instead. * * \param surface an SDL_Surface structure representing the cursor image. * \param hot_x the x position of the cursor hot spot. @@ -542,6 +612,8 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data, * * \since This function is available since SDL 3.2.0. * + * \sa SDL_AddSurfaceAlternateImage + * \sa SDL_CreateAnimatedCursor * \sa SDL_CreateCursor * \sa SDL_CreateSystemCursor * \sa SDL_DestroyCursor @@ -551,6 +623,57 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateColorCursor(SDL_Surface *surf int hot_x, int hot_y); +/** + * Create an animated color cursor. + * + * Animated cursors are composed of a sequential array of frames, specified as + * surfaces and durations in an array of SDL_CursorFrameInfo structs. The hot + * spot coordinates are universal to all frames, and all frames must have the + * same dimensions. + * + * Frame durations are specified in milliseconds. A duration of 0 implies an + * infinite frame time, and the animation will stop on that frame. To create a + * one-shot animation, set the duration of the last frame in the sequence to + * 0. + * + * If this function is passed surfaces with alternate representations added + * with SDL_AddSurfaceAlternateImage(), the surfaces will be interpreted as + * the content to be used for 100% display scale, and the alternate + * representations will be used for high DPI situations. For example, if the + * original surfaces are 32x32, then on a 2x macOS display or 200% display + * scale on Windows, a 64x64 version of the image will be used, if available. + * If a matching version of the image isn't available, the closest larger size + * image will be downscaled to the appropriate size and be used instead, if + * available. Otherwise, the closest smaller image will be upscaled and be + * used instead. + * + * If the underlying platform does not support animated cursors, this function + * will fall back to creating a static color cursor using the first frame in + * the sequence. + * + * \param frames an array of cursor images composing the animation. + * \param frame_count the number of frames in the sequence. + * \param hot_x the x position of the cursor hot spot. + * \param hot_y the y position of the cursor hot spot. + * \returns the new cursor on success or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_AddSurfaceAlternateImage + * \sa SDL_CreateCursor + * \sa SDL_CreateColorCursor + * \sa SDL_CreateSystemCursor + * \sa SDL_DestroyCursor + * \sa SDL_SetCursor + */ +extern SDL_DECLSPEC SDL_Cursor *SDLCALL SDL_CreateAnimatedCursor(SDL_CursorFrameInfo *frames, + int frame_count, + int hot_x, + int hot_y); + /** * Create a system cursor. * @@ -608,7 +731,7 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_GetCursor(void); * You do not have to call SDL_DestroyCursor() on the return value, but it is * safe to do so. * - * \returns the default cursor on success or NULL on failuree; call + * \returns the default cursor on success or NULL on failure; call * SDL_GetError() for more information. * * \threadsafety This function should only be called on the main thread. @@ -629,6 +752,7 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_GetDefaultCursor(void); * * \since This function is available since SDL 3.2.0. * + * \sa SDL_CreateAnimatedCursor * \sa SDL_CreateColorCursor * \sa SDL_CreateCursor * \sa SDL_CreateSystemCursor diff --git a/vendor/sdl3/include/SDL_mutex.h b/vendor/sdl3/include/SDL_mutex.h index c88ec1531..e477e2d30 100644 --- a/vendor/sdl3/include/SDL_mutex.h +++ b/vendor/sdl3/include/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -308,6 +308,8 @@ typedef struct SDL_Mutex SDL_Mutex; * \returns the initialized and unlocked mutex or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroyMutex @@ -334,6 +336,8 @@ extern SDL_DECLSPEC SDL_Mutex * SDLCALL SDL_CreateMutex(void); * * \param mutex the mutex to lock. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_TryLockMutex @@ -355,12 +359,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mut * \param mutex the mutex to try to lock. * \returns true on success, false if the mutex would block. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0, mutex); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(true, mutex); /** * Unlock the mutex. @@ -374,6 +380,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQU * * \param mutex the mutex to unlock. * + * \threadsafety This call must be paired with a previous locking call on the same thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockMutex @@ -392,6 +400,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(m * * \param mutex the mutex to destroy. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateMutex @@ -457,6 +467,8 @@ typedef struct SDL_RWLock SDL_RWLock; * \returns the initialized and unlocked read/write lock or NULL on failure; * call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroyRWLock @@ -497,6 +509,8 @@ extern SDL_DECLSPEC SDL_RWLock * SDLCALL SDL_CreateRWLock(void); * * \param rwlock the read/write lock to lock. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockRWLockForWriting @@ -528,6 +542,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SD * * \param rwlock the read/write lock to lock. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockRWLockForReading @@ -553,13 +569,15 @@ extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SD * \param rwlock the rwlock to try to lock. * \returns true on success, false if the lock would block. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockRWLockForReading * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(true, rwlock); /** * Try to lock a read/write lock _for writing_ without blocking. @@ -583,13 +601,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) * \param rwlock the rwlock to try to lock. * \returns true on success, false if the lock would block. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockRWLockForWriting * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ -extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(true, rwlock); /** * Unlock the read/write lock. @@ -607,6 +627,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) * * \param rwlock the rwlock to unlock. * + * \threadsafety This call must be paired with a previous locking call on the same thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockRWLockForReading @@ -627,6 +649,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEAS * * \param rwlock the rwlock to destroy. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateRWLock @@ -670,6 +694,8 @@ typedef struct SDL_Semaphore SDL_Semaphore; * \returns a new semaphore or NULL on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroySemaphore @@ -689,6 +715,8 @@ extern SDL_DECLSPEC SDL_Semaphore * SDLCALL SDL_CreateSemaphore(Uint32 initial_v * * \param sem the semaphore to destroy. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateSemaphore @@ -707,6 +735,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); * * \param sem the semaphore wait on. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SignalSemaphore @@ -726,6 +756,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); * \param sem the semaphore to wait on. * \returns true if the wait succeeds, false if the wait would block. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SignalSemaphore @@ -746,6 +778,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TryWaitSemaphore(SDL_Semaphore *sem); * indefinitely. * \returns true if the wait succeeds or false if the wait times out. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SignalSemaphore @@ -759,6 +793,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Si * * \param sem the semaphore to increment. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_TryWaitSemaphore @@ -773,6 +809,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SignalSemaphore(SDL_Semaphore *sem); * \param sem the semaphore to query. * \returns the current value of the semaphore. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem); @@ -806,6 +844,8 @@ typedef struct SDL_Condition SDL_Condition; * \returns a new condition variable or NULL on failure; call SDL_GetError() * for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_BroadcastCondition @@ -821,6 +861,8 @@ extern SDL_DECLSPEC SDL_Condition * SDLCALL SDL_CreateCondition(void); * * \param cond the condition variable to destroy. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateCondition @@ -942,7 +984,7 @@ typedef enum SDL_InitStatus * Here is an example of using this: * * ```c - * static SDL_AtomicInitState init; + * static SDL_InitState init; * * bool InitSystem(void) * { diff --git a/vendor/sdl3/include/SDL_oldnames.h b/vendor/sdl3/include/SDL_oldnames.h index c93607e3f..b9f88b295 100644 --- a/vendor/sdl3/include/SDL_oldnames.h +++ b/vendor/sdl3/include/SDL_oldnames.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_opengl.h b/vendor/sdl3/include/SDL_opengl.h index d1b8b02a3..733f2b51a 100644 --- a/vendor/sdl3/include/SDL_opengl.h +++ b/vendor/sdl3/include/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_opengles.h b/vendor/sdl3/include/SDL_opengles.h index 4fb9a4b70..227f51be4 100644 --- a/vendor/sdl3/include/SDL_opengles.h +++ b/vendor/sdl3/include/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_opengles2.h b/vendor/sdl3/include/SDL_opengles2.h index 365898a65..2c746143f 100644 --- a/vendor/sdl3/include/SDL_opengles2.h +++ b/vendor/sdl3/include/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_pen.h b/vendor/sdl3/include/SDL_pen.h index 5182eeb0c..978e0b6fd 100644 --- a/vendor/sdl3/include/SDL_pen.h +++ b/vendor/sdl3/include/SDL_pen.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -28,12 +28,37 @@ * handling, e.g., for input and drawing tablets or suitably equipped mobile / * tablet devices. * - * To get started with pens, simply handle SDL_EVENT_PEN_* events. When a pen - * starts providing input, SDL will assign it a unique SDL_PenID, which will - * remain for the life of the process, as long as the pen stays connected. + * To get started with pens, simply handle pen events: + * + * - SDL_EVENT_PEN_PROXIMITY_IN, SDL_EVENT_PEN_PROXIMITY_OUT + * (SDL_PenProximityEvent) + * - SDL_EVENT_PEN_DOWN, SDL_EVENT_PEN_UP (SDL_PenTouchEvent) + * - SDL_EVENT_PEN_MOTION (SDL_PenMotionEvent) + * - SDL_EVENT_PEN_BUTTON_DOWN, SDL_EVENT_PEN_BUTTON_UP (SDL_PenButtonEvent) + * - SDL_EVENT_PEN_AXIS (SDL_PenAxisEvent) * * Pens may provide more than simple touch input; they might have other axes, * such as pressure, tilt, rotation, etc. + * + * When a pen starts providing input, SDL will assign it a unique SDL_PenID, + * which will remain for the life of the process, as long as the pen stays + * connected. A pen leaving proximity (being taken far enough away from the + * digitizer tablet that it no longer reponds) and then coming back should + * fire proximity events, but the SDL_PenID should remain consistent. + * Unplugging the digitizer and reconnecting may cause future input to have a + * new SDL_PenID, as SDL may not know that this is the same hardware. + * + * Please note that various platforms vary wildly in how (and how well) they + * support pen input. If your pen supports some piece of functionality but SDL + * doesn't seem to, it might actually be the operating system's fault. For + * example, some platforms can manage multiple devices at the same time, but + * others will make any connected pens look like a single logical device, much + * how all USB mice connected to a computer will move the same system cursor. + * cursor. Other platforms might not support pen buttons, or the distance + * axis, etc. Very few platforms can even report _what_ functionality the pen + * supports in the first place, so best practices is to either build UI to let + * the user configure their pens, or be prepared to handle new functionality + * for a pen the first time an event is reported. */ #ifndef SDL_pen_h_ @@ -43,6 +68,7 @@ #include #include +#include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { @@ -55,7 +81,12 @@ extern "C" { * * These show up in pen events when SDL sees input from them. They remain * consistent as long as SDL can recognize a tool to be the same pen; but if a - * pen physically leaves the area and returns, it might get a new ID. + * pen's digitizer table is physically detached from the computer, it might + * get a new ID when reconnected, as SDL won't know it's the same device. + * + * These IDs are only stable within a single run of a program; the next time a + * program is run, the pen's ID will likely be different, even if the hardware + * hasn't been disconnected, etc. * * \since This datatype is available since SDL 3.2.0. */ @@ -75,7 +106,6 @@ typedef Uint32 SDL_PenID; */ #define SDL_PEN_TOUCHID ((SDL_TouchID)-2) - /** * Pen input flags, as reported by various pen events' `pen_state` field. * @@ -83,13 +113,14 @@ typedef Uint32 SDL_PenID; */ typedef Uint32 SDL_PenInputFlags; -#define SDL_PEN_INPUT_DOWN (1u << 0) /**< pen is pressed down */ -#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< button 1 is pressed */ -#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< button 2 is pressed */ -#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< button 3 is pressed */ -#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< button 4 is pressed */ -#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< button 5 is pressed */ -#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< eraser tip is used */ +#define SDL_PEN_INPUT_DOWN (1u << 0) /**< pen is pressed down */ +#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< button 1 is pressed */ +#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< button 2 is pressed */ +#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< button 3 is pressed */ +#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< button 4 is pressed */ +#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< button 5 is pressed */ +#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< eraser tip is used */ +#define SDL_PEN_INPUT_IN_PROXIMITY (1u << 31) /**< pen is in proximity (since SDL 3.4.0) */ /** * Pen axis indices. @@ -118,10 +149,50 @@ typedef enum SDL_PenAxis SDL_PEN_AXIS_COUNT /**< Total known pen axis types in this version of SDL. This number may grow in future releases! */ } SDL_PenAxis; +/** + * An enum that describes the type of a pen device. + * + * A "direct" device is a pen that touches a graphic display (like an Apple + * Pencil on an iPad's screen). "Indirect" devices touch an external tablet + * surface that is connected to the machine but is not a display (like a + * lower-end Wacom tablet connected over USB). + * + * Apps may use this information to decide if they should draw a cursor; if + * the pen is touching the screen directly, a cursor doesn't make sense and + * can be in the way, but becomes necessary for indirect devices to know where + * on the display they are interacting. + * + * \since This enum is available since SDL 3.4.0. + */ +typedef enum SDL_PenDeviceType +{ + SDL_PEN_DEVICE_TYPE_INVALID = -1, /**< Not a valid pen device. */ + SDL_PEN_DEVICE_TYPE_UNKNOWN, /**< Don't know specifics of this pen. */ + SDL_PEN_DEVICE_TYPE_DIRECT, /**< Pen touches display. */ + SDL_PEN_DEVICE_TYPE_INDIRECT /**< Pen touches something that isn't the display. */ +} SDL_PenDeviceType; + +/** + * Get the device type of the given pen. + * + * Many platforms do not supply this information, so an app must always be + * prepared to get an SDL_PEN_DEVICE_TYPE_UNKNOWN result. + * + * \param instance_id the pen instance ID. + * \returns the device type of the given pen, or SDL_PEN_DEVICE_TYPE_INVALID + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PenDeviceType SDLCALL SDL_GetPenDeviceType(SDL_PenID instance_id); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif +#include #endif /* SDL_pen_h_ */ diff --git a/vendor/sdl3/include/SDL_pixels.h b/vendor/sdl3/include/SDL_pixels.h index 4127ac06c..475e5f9c3 100644 --- a/vendor/sdl3/include/SDL_pixels.h +++ b/vendor/sdl3/include/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -451,7 +451,7 @@ typedef enum SDL_PackedLayout * expressions with side-effects here. * * \param format an SDL_PixelFormat to check. - * \returns true if the format is 10-bit, false otherwise. + * \returns true if the format is a floating point, false otherwise. * * \threadsafety It is safe to call this macro from any thread. * @@ -517,7 +517,7 @@ typedef enum SDL_PackedLayout * ABGR32, define a platform-independent encoding into bytes in the order * specified. For example, in RGB24 data, each pixel is encoded in 3 bytes * (red, green, blue) in that order, and in ABGR32 data, each pixel is - * encoded in 4 bytes alpha, blue, green, red) in that order. Use these + * encoded in 4 bytes (alpha, blue, green, red) in that order. Use these * names if the property of a format that is important to you is the order * of the bytes in memory or on disk. * - Names with a bit count per component, such as ARGB8888 and XRGB1555, are @@ -1096,7 +1096,7 @@ typedef enum SDL_Colorspace SDL_CHROMA_LOCATION_LEFT), */ SDL_COLORSPACE_RGB_DEFAULT = SDL_COLORSPACE_SRGB, /**< The default colorspace for RGB surfaces if no colorspace is specified */ - SDL_COLORSPACE_YUV_DEFAULT = SDL_COLORSPACE_JPEG /**< The default colorspace for YUV surfaces if no colorspace is specified */ + SDL_COLORSPACE_YUV_DEFAULT = SDL_COLORSPACE_BT601_LIMITED /**< The default colorspace for YUV surfaces if no colorspace is specified */ } SDL_Colorspace; /** @@ -1379,7 +1379,7 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormatDetails *for * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff, * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]). * - * \param pixel a pixel value. + * \param pixelvalue a pixel value. * \param format a pointer to SDL_PixelFormatDetails describing the pixel * format. * \param palette an optional palette for indexed formats, may be NULL. @@ -1397,7 +1397,7 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormatDetails *for * \sa SDL_MapRGB * \sa SDL_MapRGBA */ -extern SDL_DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b); +extern SDL_DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixelvalue, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b); /** * Get RGBA values from a pixel in the specified format. @@ -1410,7 +1410,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, const SDL_PixelFormatD * If the surface has no alpha component, the alpha will be returned as 0xff * (100% opaque). * - * \param pixel a pixel value. + * \param pixelvalue a pixel value. * \param format a pointer to SDL_PixelFormatDetails describing the pixel * format. * \param palette an optional palette for indexed formats, may be NULL. @@ -1429,7 +1429,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, const SDL_PixelFormatD * \sa SDL_MapRGB * \sa SDL_MapRGBA */ -extern SDL_DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); +extern SDL_DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixelvalue, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /* Ends C function definitions when using C++ */ diff --git a/vendor/sdl3/include/SDL_platform.h b/vendor/sdl3/include/SDL_platform.h index e40f009ba..9ad380bab 100644 --- a/vendor/sdl3/include/SDL_platform.h +++ b/vendor/sdl3/include/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -51,6 +51,8 @@ extern "C" { * \returns the name of the platform. If the correct platform name is not * available, returns a string beginning with the text "Unknown". * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC const char * SDLCALL SDL_GetPlatform(void); diff --git a/vendor/sdl3/include/SDL_platform_defines.h b/vendor/sdl3/include/SDL_platform_defines.h index 6b240a8be..79631491d 100644 --- a/vendor/sdl3/include/SDL_platform_defines.h +++ b/vendor/sdl3/include/SDL_platform_defines.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -190,7 +190,7 @@ #if TARGET_OS_VISION /** - * A preprocessor macro that is only defined if compiling for VisionOS. + * A preprocessor macro that is only defined if compiling for visionOS. * * \since This macro is available since SDL 3.2.0. * @@ -202,7 +202,7 @@ #if TARGET_OS_IPHONE /** - * A preprocessor macro that is only defined if compiling for iOS. + * A preprocessor macro that is only defined if compiling for iOS or visionOS. * * \since This macro is available since SDL 3.2.0. * @@ -317,7 +317,7 @@ #define SDL_PLATFORM_CYGWIN 1 #endif -#if defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) +#if (defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN)) && !defined(__NGAGE__) /** * A preprocessor macro that is only defined if compiling for Windows. @@ -473,4 +473,25 @@ #define SDL_PLATFORM_3DS 1 #endif +#ifdef __NGAGE__ + +/** + * A preprocessor macro that is only defined if compiling for the Nokia + * N-Gage. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_PLATFORM_NGAGE 1 +#endif + +#ifdef __GNU__ + +/** + * A preprocessor macro that is only defined if compiling for GNU/Hurd. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_PLATFORM_HURD 1 +#endif + #endif /* SDL_platform_defines_h_ */ diff --git a/vendor/sdl3/include/SDL_power.h b/vendor/sdl3/include/SDL_power.h index 694fb0924..0616cc275 100644 --- a/vendor/sdl3/include/SDL_power.h +++ b/vendor/sdl3/include/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -88,11 +88,13 @@ typedef enum SDL_PowerState * can't determine a value or there is no battery. * \param percent a pointer filled in with the percentage of battery life * left, between 0 and 100, or NULL to ignore. This will be - * filled in with -1 we can't determine a value or there is no - * battery. + * filled in with -1 when we can't determine a value or there + * is no battery. * \returns the current battery state or `SDL_POWERSTATE_ERROR` on failure; * call SDL_GetError() for more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *seconds, int *percent); diff --git a/vendor/sdl3/include/SDL_process.h b/vendor/sdl3/include/SDL_process.h index 511b2f9c5..b797890d8 100644 --- a/vendor/sdl3/include/SDL_process.h +++ b/vendor/sdl3/include/SDL_process.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -166,6 +166,9 @@ typedef enum SDL_ProcessIO * - `SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER`: an SDL_Environment * pointer. If this property is set, it will be the entire environment for * the process, otherwise the current environment is used. + * - `SDL_PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING`: a UTF-8 encoded + * string representing the working directory for the process, defaults to + * the current working directory. * - `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER`: an SDL_ProcessIO value describing * where standard input for the process comes from, defaults to * `SDL_PROCESS_STDIO_NULL`. @@ -192,6 +195,12 @@ typedef enum SDL_ProcessIO * run in the background. In this case the default input and output is * `SDL_PROCESS_STDIO_NULL` and the exitcode of the process is not * available, and will always be 0. + * - `SDL_PROP_PROCESS_CREATE_CMDLINE_STRING`: a string containing the program + * to run and any parameters. This string is passed directly to + * `CreateProcess` on Windows, and does nothing on other platforms. This + * property is only important if you want to start programs that does + * non-standard command-line processing, and in most cases using + * `SDL_PROP_PROCESS_CREATE_ARGS_POINTER` is sufficient. * * On POSIX platforms, wait() and waitpid(-1, ...) should not be called, and * SIGCHLD should not be ignored or handled because those would prevent SDL @@ -219,6 +228,7 @@ extern SDL_DECLSPEC SDL_Process * SDLCALL SDL_CreateProcessWithProperties(SDL_Pr #define SDL_PROP_PROCESS_CREATE_ARGS_POINTER "SDL.process.create.args" #define SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER "SDL.process.create.environment" +#define SDL_PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING "SDL.process.create.working_directory" #define SDL_PROP_PROCESS_CREATE_STDIN_NUMBER "SDL.process.create.stdin_option" #define SDL_PROP_PROCESS_CREATE_STDIN_POINTER "SDL.process.create.stdin_source" #define SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER "SDL.process.create.stdout_option" @@ -227,6 +237,7 @@ extern SDL_DECLSPEC SDL_Process * SDLCALL SDL_CreateProcessWithProperties(SDL_Pr #define SDL_PROP_PROCESS_CREATE_STDERR_POINTER "SDL.process.create.stderr_source" #define SDL_PROP_PROCESS_CREATE_STDERR_TO_STDOUT_BOOLEAN "SDL.process.create.stderr_to_stdout" #define SDL_PROP_PROCESS_CREATE_BACKGROUND_BOOLEAN "SDL.process.create.background" +#define SDL_PROP_PROCESS_CREATE_CMDLINE_STRING "SDL.process.create.cmdline" /** * Get the properties associated with a process. diff --git a/vendor/sdl3/include/SDL_properties.h b/vendor/sdl3/include/SDL_properties.h index 1f47d5f4a..abd7b2aa5 100644 --- a/vendor/sdl3/include/SDL_properties.h +++ b/vendor/sdl3/include/SDL_properties.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ extern "C" { #endif /** - * SDL properties ID + * An ID that represents a properties set. * * \since This datatype is available since SDL 3.2.0. */ @@ -80,12 +80,39 @@ typedef enum SDL_PropertyType SDL_PROPERTY_TYPE_BOOLEAN } SDL_PropertyType; +/** + * A generic property for naming things. + * + * This property is intended to be added to any SDL_PropertiesID that needs a + * generic name associated with the property set. It is not guaranteed that + * any property set will include this key, but it is convenient to have a + * standard key that any piece of code could reasonably agree to use. + * + * For example, the properties associated with an SDL_Texture might have a + * name string of "player sprites", or an SDL_AudioStream might have + * "background music", etc. This might also be useful for an SDL_IOStream to + * list the path to its asset. + * + * There is no format for the value set with this key; it is expected to be + * human-readable and informational in nature, possibly for logging or + * debugging purposes. + * + * SDL does not currently set this property on any objects it creates, but + * this may change in later versions; it is currently expected that apps and + * external libraries will take advantage of it, when appropriate. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_PROP_NAME_STRING "SDL.name" + /** * Get the global SDL properties. * * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); @@ -119,7 +146,9 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It is safe to call this function from any thread. This + * function acquires simultaneous mutex locks on both the source + * and destination property sets. * * \since This function is available since SDL 3.2.0. */ diff --git a/vendor/sdl3/include/SDL_rect.h b/vendor/sdl3/include/SDL_rect.h index eb2d34a69..883ca8d6c 100644 --- a/vendor/sdl3/include/SDL_rect.h +++ b/vendor/sdl3/include/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -88,8 +88,11 @@ typedef struct SDL_Rect /** - * A rectangle, with the origin at the upper left (using floating point - * values). + * A rectangle stored using floating point values. + * + * The origin of the coordinate space is in the top-left, with increasing + * values moving down and right. The properties `x` and `y` represent the + * coordinates of the top-left corner of the rectangle. * * \since This struct is available since SDL 3.2.0. * @@ -125,10 +128,10 @@ typedef struct SDL_FRect */ SDL_FORCE_INLINE void SDL_RectToFRect(const SDL_Rect *rect, SDL_FRect *frect) { - frect->x = (float)rect->x; - frect->y = (float)rect->y; - frect->w = (float)rect->w; - frect->h = (float)rect->h; + frect->x = SDL_static_cast(float, rect->x); + frect->y = SDL_static_cast(float, rect->y); + frect->w = SDL_static_cast(float, rect->w); + frect->h = SDL_static_cast(float, rect->h); } /** @@ -234,6 +237,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersection(const SDL_Rect *A, cons * rectangles `A` and `B`. * \returns true if there is an intersection, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_HasRectIntersection @@ -250,6 +255,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersection(const SDL_Rect *A, cons * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnion(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result); @@ -269,6 +276,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnion(const SDL_Rect *A, const SDL_R * \returns true if any points were enclosed or false if all the points were * outside of the clipping rectangle. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point *points, int count, const SDL_Rect *clip, SDL_Rect *result); @@ -289,6 +298,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point *poi * \param Y2 a pointer to the ending Y-coordinate of the line. * \returns true if there is an intersection, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersection(const SDL_Rect *rect, int *X1, int *Y1, int *X2, int *Y2); @@ -324,7 +335,7 @@ SDL_FORCE_INLINE bool SDL_PointInRectFloat(const SDL_FPoint *p, const SDL_FRect } /** - * Determine whether a floating point rectangle can contain any point. + * Determine whether a floating point rectangle takes no space. * * A rectangle is considered "empty" for this function if `r` is NULL, or if * `r`'s width and/or height are < 0.0f. @@ -420,6 +431,8 @@ SDL_FORCE_INLINE bool SDL_RectsEqualFloat(const SDL_FRect *a, const SDL_FRect *b * \param B an SDL_FRect structure representing the second rectangle. * \returns true if there is an intersection, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetRectIntersection @@ -437,6 +450,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersectionFloat(const SDL_FRect *A * rectangles `A` and `B`. * \returns true if there is an intersection, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_HasRectIntersectionFloat @@ -453,6 +468,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersectionFloat(const SDL_FRect *A * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnionFloat(const SDL_FRect *A, const SDL_FRect *B, SDL_FRect *result); @@ -473,6 +490,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnionFloat(const SDL_FRect *A, const * \returns true if any points were enclosed or false if all the points were * outside of the clipping rectangle. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoint *points, int count, const SDL_FRect *clip, SDL_FRect *result); @@ -494,6 +513,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoin * \param Y2 a pointer to the ending Y-coordinate of the line. * \returns true if there is an intersection, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersectionFloat(const SDL_FRect *rect, float *X1, float *Y1, float *X2, float *Y2); diff --git a/vendor/sdl3/include/SDL_render.h b/vendor/sdl3/include/SDL_render.h index 3352545d4..87257d115 100644 --- a/vendor/sdl3/include/SDL_render.h +++ b/vendor/sdl3/include/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -39,9 +39,9 @@ * may also be stretched with linear interpolation. * * This API is designed to accelerate simple 2D operations. You may want more - * functionality such as polygons and particle effects and in that case you - * should use SDL's OpenGL/Direct3D support, the SDL3 GPU API, or one of the - * many good 3D engines. + * functionality such as 3D polygons and particle effects, and in that case + * you should use SDL's OpenGL/Direct3D support, the SDL3 GPU API, or one of + * the many good 3D engines. * * These functions must be called from the main thread. See this bug for * details: https://github.com/libsdl-org/SDL/issues/986 @@ -59,6 +59,7 @@ #include #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -73,6 +74,13 @@ extern "C" { */ #define SDL_SOFTWARE_RENDERER "software" +/** + * The name of the GPU renderer. + * + * \since This macro is available since SDL 3.4.0. + */ +#define SDL_GPU_RENDERER "gpu" + /** * Vertex structure. * @@ -97,6 +105,25 @@ typedef enum SDL_TextureAccess SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */ } SDL_TextureAccess; +/** + * The addressing mode for a texture when used in SDL_RenderGeometry(). + * + * This affects how texture coordinates are interpreted outside of [0, 1] + * + * Texture wrapping is always supported for power of two texture sizes, and is + * supported for other texture sizes if + * SDL_PROP_RENDERER_TEXTURE_WRAPPING_BOOLEAN is set to true. + * + * \since This enum is available since SDL 3.4.0. + */ +typedef enum SDL_TextureAddressMode +{ + SDL_TEXTURE_ADDRESS_INVALID = -1, + SDL_TEXTURE_ADDRESS_AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */ + SDL_TEXTURE_ADDRESS_CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */ + SDL_TEXTURE_ADDRESS_WRAP /**< The texture is repeated (tiled) */ +} SDL_TextureAddressMode; + /** * How the logical size is mapped to the output. * @@ -106,7 +133,7 @@ typedef enum SDL_RendererLogicalPresentation { SDL_LOGICAL_PRESENTATION_DISABLED, /**< There is no logical size in effect */ SDL_LOGICAL_PRESENTATION_STRETCH, /**< The rendered content is stretched to the output resolution */ - SDL_LOGICAL_PRESENTATION_LETTERBOX, /**< The rendered content is fit to the largest dimension and the other dimension is letterboxed with black bars */ + SDL_LOGICAL_PRESENTATION_LETTERBOX, /**< The rendered content is fit to the largest dimension and the other dimension is letterboxed with the clear color */ SDL_LOGICAL_PRESENTATION_OVERSCAN, /**< The rendered content is fit to the smallest dimension and the other dimension extends beyond the output bounds */ SDL_LOGICAL_PRESENTATION_INTEGER_SCALE /**< The rendered content is scaled up by integer multiples to fit the output resolution */ } SDL_RendererLogicalPresentation; @@ -267,6 +294,17 @@ extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window * present synchronized with the refresh rate. This property can take any * value that is supported by SDL_SetRenderVSync() for the renderer. * + * With the SDL GPU renderer (since SDL 3.4.0): + * + * - `SDL_PROP_RENDERER_CREATE_GPU_DEVICE_POINTER`: the device to use with the + * renderer, optional. + * - `SDL_PROP_RENDERER_CREATE_GPU_SHADERS_SPIRV_BOOLEAN`: the app is able to + * provide SPIR-V shaders to SDL_GPURenderState, optional. + * - `SDL_PROP_RENDERER_CREATE_GPU_SHADERS_DXIL_BOOLEAN`: the app is able to + * provide DXIL shaders to SDL_GPURenderState, optional. + * - `SDL_PROP_RENDERER_CREATE_GPU_SHADERS_MSL_BOOLEAN`: the app is able to + * provide MSL shaders to SDL_GPURenderState, optional. + * * With the vulkan renderer: * * - `SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER`: the VkInstance to use @@ -303,6 +341,10 @@ extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_ #define SDL_PROP_RENDERER_CREATE_SURFACE_POINTER "SDL.renderer.create.surface" #define SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.create.output_colorspace" #define SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER "SDL.renderer.create.present_vsync" +#define SDL_PROP_RENDERER_CREATE_GPU_DEVICE_POINTER "SDL.renderer.create.gpu.device" +#define SDL_PROP_RENDERER_CREATE_GPU_SHADERS_SPIRV_BOOLEAN "SDL.renderer.create.gpu.shaders_spirv" +#define SDL_PROP_RENDERER_CREATE_GPU_SHADERS_DXIL_BOOLEAN "SDL.renderer.create.gpu.shaders_dxil" +#define SDL_PROP_RENDERER_CREATE_GPU_SHADERS_MSL_BOOLEAN "SDL.renderer.create.gpu.shaders_msl" #define SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER "SDL.renderer.create.vulkan.instance" #define SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER "SDL.renderer.create.vulkan.surface" #define SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER "SDL.renderer.create.vulkan.physical_device" @@ -310,6 +352,53 @@ extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_ #define SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.create.vulkan.graphics_queue_family_index" #define SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.create.vulkan.present_queue_family_index" +/** + * Create a 2D GPU rendering context. + * + * The GPU device to use is passed in as a parameter. If this is NULL, then a + * device will be created normally and can be retrieved using + * SDL_GetGPURendererDevice(). + * + * The window to use is passed in as a parameter. If this is NULL, then this + * will become an offscreen renderer. In that case, you should call + * SDL_SetRenderTarget() to setup rendering to a texture, and then call + * SDL_RenderPresent() normally to complete drawing a frame. + * + * \param device the GPU device to use with the renderer, or NULL to create a + * device. + * \param window the window where rendering is displayed, or NULL to create an + * offscreen renderer. + * \returns a valid rendering context or NULL if there was an error; call + * SDL_GetError() for more information. + * + * \threadsafety If this function is called with a valid GPU device, it should + * be called on the thread that created the device. If this + * function is called with a valid window, it should be called + * on the thread that created the window. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_CreateRendererWithProperties + * \sa SDL_GetGPURendererDevice + * \sa SDL_CreateGPUShader + * \sa SDL_CreateGPURenderState + * \sa SDL_SetGPURenderState + */ +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateGPURenderer(SDL_GPUDevice *device, SDL_Window *window); + +/** + * Return the GPU device used by a renderer. + * + * \param renderer the rendering context. + * \returns the GPU device used by the renderer, or NULL if the renderer is + * not a GPU renderer; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_GetGPURendererDevice(SDL_Renderer *renderer); + /** * Create a 2D software rendering context for a surface. * @@ -323,7 +412,7 @@ extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_ * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. * - * \threadsafety This function should only be called on the main thread. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. * @@ -389,6 +478,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetRendererName(SDL_Renderer *rende * - `SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER`: a (const SDL_PixelFormat *) * array of pixel formats, terminated with SDL_PIXELFORMAT_UNKNOWN, * representing the available texture formats for this renderer. + * - `SDL_PROP_RENDERER_TEXTURE_WRAPPING_BOOLEAN`: true if the renderer + * supports SDL_TEXTURE_ADDRESS_WRAP on non-power-of-two textures. * - `SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER`: an SDL_Colorspace value * describing the colorspace for output to the display, defaults to * SDL_COLORSPACE_SRGB. @@ -465,6 +556,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Rende #define SDL_PROP_RENDERER_VSYNC_NUMBER "SDL.renderer.vsync" #define SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER "SDL.renderer.max_texture_size" #define SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER "SDL.renderer.texture_formats" +#define SDL_PROP_RENDERER_TEXTURE_WRAPPING_BOOLEAN "SDL.renderer.texture_wrapping" #define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace" #define SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN "SDL.renderer.HDR_enabled" #define SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT "SDL.renderer.SDR_white_point" @@ -601,6 +693,9 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende * pixels, required * - `SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in * pixels, required + * - `SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER`: an SDL_Palette to use with + * palettized texture formats. This can be set later with + * SDL_SetTexturePalette() * - `SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating * point textures, this defines the value of 100% diffuse white, with higher * values being displayed in the High Dynamic Range headroom. This defaults @@ -673,9 +768,24 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende * * With the vulkan renderer: * - * - `SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER`: the VkImage with layout - * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if - * you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER`: the VkImage associated + * with the texture, if you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_VULKAN_LAYOUT_NUMBER`: the VkImageLayout for the + * VkImage, defaults to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. + * + * With the GPU renderer: + * + * - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER`: the SDL_GPUTexture + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_NUMBER`: the SDL_GPUTexture + * associated with the UV plane of an NV12 texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_NUMBER`: the SDL_GPUTexture + * associated with the U plane of a YUV texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_NUMBER`: the SDL_GPUTexture + * associated with the V plane of a YUV texture, if you want to wrap an + * existing texture. * * \param renderer the rendering context. * \param props the properties to use. @@ -695,29 +805,35 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Rende */ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); -#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace" -#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format" -#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access" -#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width" -#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height" -#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point" -#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v" -#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v" -#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture" +#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace" +#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format" +#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access" +#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width" +#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height" +#define SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER "SDL.texture.create.palette" +#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point" +#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v" +#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v" +#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture" +#define SDL_PROP_TEXTURE_CREATE_VULKAN_LAYOUT_NUMBER "SDL.texture.create.vulkan.layout" +#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER "SDL.texture.create.gpu.texture" +#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER "SDL.texture.create.gpu.texture_uv" +#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER "SDL.texture.create.gpu.texture_u" +#define SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER "SDL.texture.create.gpu.texture_v" /** * Get the properties associated with a texture. @@ -797,6 +913,17 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Re * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER`: the GLenum for the * texture target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc) * + * With the gpu renderer: + * + * - `SDL_PROP_TEXTURE_GPU_TEXTURE_POINTER`: the SDL_GPUTexture associated + * with the texture + * - `SDL_PROP_TEXTURE_GPU_TEXTURE_UV_POINTER`: the SDL_GPUTexture associated + * with the UV plane of an NV12 texture + * - `SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER`: the SDL_GPUTexture associated + * with the U plane of a YUV texture + * - `SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER`: the SDL_GPUTexture associated + * with the V plane of a YUV texture + * * \param texture the texture to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -833,6 +960,10 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Textur #define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" #define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER "SDL.texture.opengles2.target" #define SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER "SDL.texture.vulkan.texture" +#define SDL_PROP_TEXTURE_GPU_TEXTURE_POINTER "SDL.texture.gpu.texture" +#define SDL_PROP_TEXTURE_GPU_TEXTURE_UV_POINTER "SDL.texture.gpu.texture_uv" +#define SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER "SDL.texture.gpu.texture_u" +#define SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER "SDL.texture.gpu.texture_v" /** * Get the renderer that created an SDL_Texture. @@ -864,6 +995,43 @@ extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_GetRendererFromTexture(SDL_Textur */ extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureSize(SDL_Texture *texture, float *w, float *h); +/** + * Set the palette used by a texture. + * + * Setting the palette keeps an internal reference to the palette, which can + * be safely destroyed afterwards. + * + * A single palette can be shared with many textures. + * + * \param texture the texture to update. + * \param palette the SDL_Palette structure to use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_CreatePalette + * \sa SDL_GetTexturePalette + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetTexturePalette(SDL_Texture *texture, SDL_Palette *palette); + +/** + * Get the palette used by a texture. + * + * \param texture the texture to query. + * \returns a pointer to the palette used by the texture, or NULL if there is + * no palette used. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_SetTexturePalette + */ +extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetTexturePalette(SDL_Texture *texture); + /** * Set an additional color value multiplied into render copy operations. * @@ -1386,14 +1554,6 @@ extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *rend * specific dimensions but to make fonts look sharp, the app turns off logical * presentation while drawing text, for example. * - * For the renderer's window, letterboxing is drawn into the framebuffer if - * logical presentation is enabled during SDL_RenderPresent; be sure to - * reenable it before presenting if you were toggling it, otherwise the - * letterbox areas might have artifacts from previous frames (or artifacts - * from external overlays, etc). Letterboxing is never drawn into texture - * render targets; be sure to call SDL_RenderClear() before drawing into the - * texture so the letterboxing areas are cleared, if appropriate. - * * You can convert coordinates in an event into rendering coordinates using * SDL_ConvertEventToRenderCoordinates(). * @@ -1418,15 +1578,16 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer * * Get device independent resolution and presentation mode for rendering. * * This function gets the width and height of the logical rendering output, or - * the output size in pixels if a logical resolution is not enabled. + * 0 if a logical resolution is not enabled. * * Each render target has its own logical presentation state. This function * gets the state for the current render target. * * \param renderer the rendering context. - * \param w an int to be filled with the width. - * \param h an int to be filled with the height. - * \param mode the presentation mode used. + * \param w an int filled with the logical presentation width. + * \param h an int filled with the logical presentation height. + * \param mode a variable filled with the logical presentation mode being + * used. * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -1545,8 +1706,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *ren * * \param renderer the rendering context. * \param event the event to modify. - * \returns true on success or false on failure; call SDL_GetError() for more - * information. + * \returns true if the event is converted or doesn't need conversion, or + * false on failure; call SDL_GetError() for more information. * * \threadsafety This function should only be called on the main thread. * @@ -1607,8 +1768,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S * Return whether an explicit rectangle was set as the viewport. * * This is useful if you're saving and restoring the viewport and want to know - * whether you should restore a specific rectangle or NULL. Note that the - * viewport is always reset when changing rendering targets. + * whether you should restore a specific rectangle or NULL. * * Each render target has its own viewport. This function checks the viewport * for the current render target. @@ -2232,9 +2392,48 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTextureTiled(SDL_Renderer *renderer, * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderTexture + * \sa SDL_RenderTexture9GridTiled */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float left_width, float right_width, float top_height, float bottom_height, float scale, const SDL_FRect *dstrect); +/** + * Perform a scaled copy using the 9-grid algorithm to the current rendering + * target at subpixel precision. + * + * The pixels in the texture are split into a 3x3 grid, using the different + * corner sizes for each corner, and the sides and center making up the + * remaining pixels. The corners are then scaled using `scale` and fit into + * the corners of the destination rectangle. The sides and center are then + * tiled into place to cover the remaining destination rectangle. + * + * \param renderer the renderer which should copy parts of a texture. + * \param texture the source texture. + * \param srcrect the SDL_Rect structure representing the rectangle to be used + * for the 9-grid, or NULL to use the entire texture. + * \param left_width the width, in pixels, of the left corners in `srcrect`. + * \param right_width the width, in pixels, of the right corners in `srcrect`. + * \param top_height the height, in pixels, of the top corners in `srcrect`. + * \param bottom_height the height, in pixels, of the bottom corners in + * `srcrect`. + * \param scale the scale used to transform the corner of `srcrect` into the + * corner of `dstrect`, or 0.0f for an unscaled copy. + * \param dstrect a pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \param tileScale the scale used to transform the borders and center of + * `srcrect` into the borders and middle of `dstrect`, or + * 1.0f for an unscaled copy. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_RenderTexture + * \sa SDL_RenderTexture9Grid + */ +extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float left_width, float right_width, float top_height, float bottom_height, float scale, const SDL_FRect *dstrect, float tileScale); + /** * Render a list of triangles, optionally using a texture and indices into the * vertex array Color and alpha modulation is done per vertex @@ -2256,6 +2455,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9Grid(SDL_Renderer *renderer, * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometryRaw + * \sa SDL_SetRenderTextureAddressMode */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2288,6 +2488,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, * \since This function is available since SDL 3.2.0. * * \sa SDL_RenderGeometry + * \sa SDL_SetRenderTextureAddressMode */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, @@ -2297,6 +2498,48 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, int num_vertices, const void *indices, int num_indices, int size_indices); +/** + * Set the texture addressing mode used in SDL_RenderGeometry(). + * + * \param renderer the rendering context. + * \param u_mode the SDL_TextureAddressMode to use for horizontal texture + * coordinates in SDL_RenderGeometry(). + * \param v_mode the SDL_TextureAddressMode to use for vertical texture + * coordinates in SDL_RenderGeometry(). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_RenderGeometry + * \sa SDL_RenderGeometryRaw + * \sa SDL_GetRenderTextureAddressMode + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode); + +/** + * Get the texture addressing mode used in SDL_RenderGeometry(). + * + * \param renderer the rendering context. + * \param u_mode a pointer filled in with the SDL_TextureAddressMode to use + * for horizontal texture coordinates in SDL_RenderGeometry(), + * may be NULL. + * \param v_mode a pointer filled in with the SDL_TextureAddressMode to use + * for vertical texture coordinates in SDL_RenderGeometry(), may + * be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_SetRenderTextureAddressMode + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode); + /** * Read pixels from the current rendering target. * @@ -2348,8 +2591,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *ren * should not be done; you are only required to change back the rendering * target to default via `SDL_SetRenderTarget(renderer, NULL)` afterwards, as * textures by themselves do not have a concept of backbuffers. Calling - * SDL_RenderPresent while rendering to a texture will still update the screen - * with any current drawing that has been done _to the window itself_. + * SDL_RenderPresent while rendering to a texture will fail. * * \param renderer the rendering context. * \returns true on success or false on failure; call SDL_GetError() for more @@ -2578,8 +2820,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderVSync(SDL_Renderer *renderer, int * Among these limitations: * * - It accepts UTF-8 strings, but will only renders ASCII characters. - * - It has a single, tiny size (8x8 pixels). One can use logical presentation - * or scaling to adjust it, but it will be blurry. + * - It has a single, tiny size (8x8 pixels). You can use logical presentation + * or SDL_SetRenderScale() to adjust it. * - It uses a simple, hardcoded bitmap font. It does not allow different font * selections and it does not support truetype, for proper scaling. * - It does no word-wrapping and does not treat newline characters as a line @@ -2613,7 +2855,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderDebugText(SDL_Renderer *renderer, flo * Draw debug text to an SDL_Renderer. * * This function will render a printf()-style format string to a renderer. - * Note that this is a convinence function for debugging, with severe + * Note that this is a convenience function for debugging, with severe * limitations, and is not intended to be used for production apps and games. * * For the full list of limitations and other useful information, see @@ -2637,6 +2879,148 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderDebugText(SDL_Renderer *renderer, flo */ extern SDL_DECLSPEC bool SDLCALL SDL_RenderDebugTextFormat(SDL_Renderer *renderer, float x, float y, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(4); +/** + * Set default scale mode for new textures for given renderer. + * + * When a renderer is created, scale_mode defaults to SDL_SCALEMODE_LINEAR. + * + * \param renderer the renderer to update. + * \param scale_mode the scale mode to change to for new textures. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_GetDefaultTextureScaleMode + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode scale_mode); + +/** + * Get default texture scale mode of the given renderer. + * + * \param renderer the renderer to get data from. + * \param scale_mode a SDL_ScaleMode filled with current default scale mode. + * See SDL_SetDefaultTextureScaleMode() for the meaning of + * the value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_SetDefaultTextureScaleMode + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode *scale_mode); + +/** + * A structure specifying the parameters of a GPU render state. + * + * \since This struct is available since SDL 3.4.0. + * + * \sa SDL_CreateGPURenderState + */ +typedef struct SDL_GPURenderStateCreateInfo +{ + SDL_GPUShader *fragment_shader; /**< The fragment shader to use when this render state is active */ + + Sint32 num_sampler_bindings; /**< The number of additional fragment samplers to bind when this render state is active */ + const SDL_GPUTextureSamplerBinding *sampler_bindings; /**< Additional fragment samplers to bind when this render state is active */ + + Sint32 num_storage_textures; /**< The number of storage textures to bind when this render state is active */ + SDL_GPUTexture *const *storage_textures; /**< Storage textures to bind when this render state is active */ + + Sint32 num_storage_buffers; /**< The number of storage buffers to bind when this render state is active */ + SDL_GPUBuffer *const *storage_buffers; /**< Storage buffers to bind when this render state is active */ + + SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */ +} SDL_GPURenderStateCreateInfo; + +/** + * A custom GPU render state. + * + * \since This struct is available since SDL 3.4.0. + * + * \sa SDL_CreateGPURenderState + * \sa SDL_SetGPURenderStateFragmentUniforms + * \sa SDL_SetGPURenderState + * \sa SDL_DestroyGPURenderState + */ +typedef struct SDL_GPURenderState SDL_GPURenderState; + +/** + * Create custom GPU render state. + * + * \param renderer the renderer to use. + * \param createinfo a struct describing the GPU render state to create. + * \returns a custom GPU render state or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_SetGPURenderStateFragmentUniforms + * \sa SDL_SetGPURenderState + * \sa SDL_DestroyGPURenderState + */ +extern SDL_DECLSPEC SDL_GPURenderState * SDLCALL SDL_CreateGPURenderState(SDL_Renderer *renderer, const SDL_GPURenderStateCreateInfo *createinfo); + +/** + * Set fragment shader uniform variables in a custom GPU render state. + * + * The data is copied and will be pushed using + * SDL_PushGPUFragmentUniformData() during draw call execution. + * + * \param state the state to modify. + * \param slot_index the fragment uniform slot to push data to. + * \param data client data to write. + * \param length the length of the data to write. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetGPURenderStateFragmentUniforms(SDL_GPURenderState *state, Uint32 slot_index, const void *data, Uint32 length); + +/** + * Set custom GPU render state. + * + * This function sets custom GPU render state for subsequent draw calls. This + * allows using custom shaders with the GPU renderer. + * + * \param renderer the renderer to use. + * \param state the state to to use, or NULL to clear custom GPU render state. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetGPURenderState(SDL_Renderer *renderer, SDL_GPURenderState *state); + +/** + * Destroy custom GPU render state. + * + * \param state the state to destroy. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_CreateGPURenderState + */ +extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPURenderState(SDL_GPURenderState *state); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/vendor/sdl3/include/SDL_revision.h b/vendor/sdl3/include/SDL_revision.h index f99e03a95..3441b119c 100644 --- a/vendor/sdl3/include/SDL_revision.h +++ b/vendor/sdl3/include/SDL_revision.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -48,9 +48,9 @@ */ #define SDL_REVISION "Some arbitrary string decided at SDL build time" #elif defined(SDL_VENDOR_INFO) -#define SDL_REVISION "release-3.2.10-0-g877399b2b (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "SDL-release-3.4.2-0-g683181b47 (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "release-3.2.10-0-g877399b2b" +#define SDL_REVISION "SDL-release-3.4.2-0-g683181b47" #endif #endif /* SDL_revision_h_ */ diff --git a/vendor/sdl3/include/SDL_scancode.h b/vendor/sdl3/include/SDL_scancode.h index 9650a6cfe..cd5a1376a 100644 --- a/vendor/sdl3/include/SDL_scancode.h +++ b/vendor/sdl3/include/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -208,7 +208,7 @@ typedef enum SDL_Scancode SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO * keyboards have over ANSI ones, - * located between left shift and Y. + * located between left shift and Z. * Produces GRAVE ACCENT and TILDE in a * US or UK Mac layout, REVERSE SOLIDUS * (backslash) and VERTICAL LINE in a diff --git a/vendor/sdl3/include/SDL_sensor.h b/vendor/sdl3/include/SDL_sensor.h index b220f0538..bf890472f 100644 --- a/vendor/sdl3/include/SDL_sensor.h +++ b/vendor/sdl3/include/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -138,7 +138,8 @@ typedef enum SDL_SensorType SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */ SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */ SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */ - SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */ + SDL_SENSOR_GYRO_R, /**< Gyroscope for right Joy-Con controller */ + SDL_SENSOR_COUNT } SDL_SensorType; diff --git a/vendor/sdl3/include/SDL_stdinc.h b/vendor/sdl3/include/SDL_stdinc.h index b2728da2f..1c4d8da63 100644 --- a/vendor/sdl3/include/SDL_stdinc.h +++ b/vendor/sdl3/include/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -49,10 +49,37 @@ #include #include -#include #include #include +/* Most everything except Visual Studio 2008 and earlier has stdint.h now */ +#if defined(_MSC_VER) && (_MSC_VER < 1600) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef int intptr_t; +#endif +#endif +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef unsigned int uintptr_t; +#endif +#endif +#else +#include +#endif + #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ defined(SDL_INCLUDE_INTTYPES_H) #include @@ -227,12 +254,6 @@ void *alloca(size_t); /** * Macro useful for building other macros with strings in them. * - * For example: - * - * ```c - * #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")` - * ``` - * * \param arg the text to turn into a string literal. * * \since This macro is available since SDL 3.2.0. @@ -492,7 +513,7 @@ typedef uint64_t Uint64; * and SDL_SECONDS_TO_NS(), and between Windows FILETIME values with * SDL_TimeToWindows() and SDL_TimeFromWindows(). * - * \since This macro is available since SDL 3.2.0. + * \since This datatype is available since SDL 3.2.0. * * \sa SDL_MAX_SINT64 * \sa SDL_MIN_SINT64 @@ -1164,7 +1185,7 @@ typedef struct SDL_alignment_test void *b; } SDL_alignment_test; SDL_COMPILE_TIME_ASSERT(struct_alignment, sizeof(SDL_alignment_test) == (2 * sizeof(void *))); -SDL_COMPILE_TIME_ASSERT(two_s_complement, (int)~(int)0 == (int)(-1)); +SDL_COMPILE_TIME_ASSERT(two_s_complement, SDL_static_cast(int, ~SDL_static_cast(int, 0)) == SDL_static_cast(int, -1)); #endif /* DOXYGEN_SHOULD_IGNORE_THIS */ /** \endcond */ @@ -2119,7 +2140,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_abs(int x); * * \param x the first value to compare. * \param y the second value to compare. - * \returns the lesser of `x` and `y`. + * \returns the greater of `x` and `y`. * * \threadsafety It is safe to call this macro from any thread. * @@ -2640,7 +2661,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_memset4(void *dst, Uint32 val, size_t dwo * \since This macro is available since SDL 3.2.0. * * \sa SDL_zero - * \sa SDL_zeroa + * \sa SDL_zerop */ #define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x))) @@ -3426,7 +3447,7 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strnlen(const char *str, size_t bytes * Convert an integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3454,7 +3475,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_itoa(int value, char *str, int radix); * Convert an unsigned integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3482,7 +3503,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_uitoa(unsigned int value, char *str, int * Convert a long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3510,7 +3531,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ltoa(long value, char *str, int radix); * Convert an unsigned long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3540,7 +3561,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *str, int * Convert a long long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3568,7 +3589,7 @@ extern SDL_DECLSPEC char * SDLCALL SDL_lltoa(long long value, char *str, int rad * Convert an unsigned long long integer into a string. * * This requires a radix to specified for string format. Specifying 10 - * produces a decimal number, 16 hexidecimal, etc. Must be in the range of 2 + * produces a decimal number, 16 hexadecimal, etc. Must be in the range of 2 * to 36. * * Note that this function will overflow a buffer if `str` is not large enough @@ -3923,7 +3944,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen); /** - * Searches a string for the first occurence of any character contained in a + * Searches a string for the first occurrence of any character contained in a * breakset, and returns a pointer from the string to that character. * * \param str The null-terminated string to be searched. Must not be NULL, and @@ -3931,7 +3952,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *st * \param breakset A null-terminated string containing the list of characters * to look for. Must not be NULL, and must not overlap with * `str`. - * \returns A pointer to the location, in str, of the first occurence of a + * \returns A pointer to the location, in str, of the first occurrence of a * character present in the breakset, or NULL if none is found. * * \threadsafety It is safe to call this function from any thread. @@ -4656,7 +4677,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_atanf(float x); * * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` * - * Range: `-Pi/2 <= y <= Pi/2` + * Range: `-Pi <= y <= Pi` * * This function operates on double-precision floating point values, use * SDL_atan2f for single-precision floats. @@ -4692,7 +4713,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_atan2(double y, double x); * * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` * - * Range: `-Pi/2 <= y <= Pi/2` + * Range: `-Pi <= y <= Pi` * * This function operates on single-precision floating point values, use * SDL_atan2 for double-precision floats. @@ -4722,7 +4743,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_atan2f(float y, float x); /** * Compute the ceiling of `x`. * - * The ceiling of `x` is the smallest integer `y` such that `y > x`, i.e `x` + * The ceiling of `x` is the smallest integer `y` such that `y >= x`, i.e `x` * rounded up to the nearest integer. * * Domain: `-INF <= x <= INF` @@ -4750,7 +4771,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_ceil(double x); /** * Compute the ceiling of `x`. * - * The ceiling of `x` is the smallest integer `y` such that `y > x`, i.e `x` + * The ceiling of `x` is the smallest integer `y` such that `y >= x`, i.e `x` * rounded up to the nearest integer. * * Domain: `-INF <= x <= INF` @@ -4992,7 +5013,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_fabsf(float x); /** * Compute the floor of `x`. * - * The floor of `x` is the largest integer `y` such that `y > x`, i.e `x` + * The floor of `x` is the largest integer `y` such that `y <= x`, i.e `x` * rounded down to the nearest integer. * * Domain: `-INF <= x <= INF` @@ -5020,7 +5041,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_floor(double x); /** * Compute the floor of `x`. * - * The floor of `x` is the largest integer `y` such that `y > x`, i.e `x` + * The floor of `x` is the largest integer `y` such that `y <= x`, i.e `x` * rounded down to the nearest integer. * * Domain: `-INF <= x <= INF` @@ -5794,6 +5815,8 @@ typedef struct SDL_iconv_data_t *SDL_iconv_t; * \returns a handle that must be freed with SDL_iconv_close, or * SDL_ICONV_ERROR on failure. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_iconv @@ -5809,6 +5832,8 @@ extern SDL_DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, * \param cd The character set conversion handle. * \returns 0 on success, or -1 on failure. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_iconv @@ -5821,7 +5846,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); * This function converts text between encodings, reading from and writing to * a buffer. * - * It returns the number of succesful conversions on success. On error, + * It returns the number of successful conversions on success. On error, * SDL_ICONV_E2BIG is returned when the output buffer is too small, or * SDL_ICONV_EILSEQ is returned when an invalid input sequence is encountered, * or SDL_ICONV_EINVAL is returned when an incomplete input sequence is @@ -5847,6 +5872,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); * \param outbytesleft The number of bytes in the output buffer. * \returns the number of conversions on success, or a negative error code. * + * \threadsafety Do not use the same SDL_iconv_t from two threads at once. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_iconv_open @@ -5882,6 +5909,8 @@ extern SDL_DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, * \param inbytesleft the size of the input string _in bytes_. * \returns a new string, converted to the new encoding, or NULL on error. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_iconv_open @@ -5905,6 +5934,8 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * \param S the string to convert. * \returns a new string, converted to the new encoding, or NULL on error. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) @@ -5919,9 +5950,11 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * \param S the string to convert. * \returns a new string, converted to the new encoding, or NULL on error. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) SDL_reinterpret_cast(Uint16 *, SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1)) /** * Convert a UTF-8 string to UCS-4. @@ -5933,9 +5966,11 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * \param S the string to convert. * \returns a new string, converted to the new encoding, or NULL on error. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) SDL_reinterpret_cast(Uint32 *, SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1)) /** * Convert a wchar_t string to UTF-8. @@ -5947,9 +5982,11 @@ extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, * \param S the string to convert. * \returns a new string, converted to the new encoding, or NULL on error. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ -#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) +#define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", SDL_reinterpret_cast(const char *, S), (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime @@ -5974,8 +6011,16 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size); size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #endif +#if !defined(HAVE_STRTOK_R) && !defined(strtok_r) +char *strtok_r(char *str, const char *delim, char **saveptr); +#endif + +#ifndef _WIN32 /* strdup is not ANSI but POSIX, and its prototype might be hidden... */ +/* not for windows: might conflict with string.h where strdup may have + * dllimport attribute: https://github.com/libsdl-org/SDL/issues/12948 */ char *strdup(const char *str); +#endif /* Starting LLVM 16, the analyser errors out if these functions do not have their prototype defined (clang-diagnostic-implicit-function-declaration) */ diff --git a/vendor/sdl3/include/SDL_storage.h b/vendor/sdl3/include/SDL_storage.h index 6837ebaac..71d403c74 100644 --- a/vendor/sdl3/include/SDL_storage.h +++ b/vendor/sdl3/include/SDL_storage.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -334,6 +334,10 @@ typedef struct SDL_Storage SDL_Storage; /** * Opens up a read-only container for the application's filesystem. * + * By default, SDL_OpenTitleStorage uses the generic storage implementation. + * When the path override is not provided, the generic implementation will use + * the output of SDL_GetBasePath as the base path. + * * \param override a path to override the backend's default title root. * \param props a property list that may contain backend-specific information. * \returns a title storage container on success or NULL on failure; call diff --git a/vendor/sdl3/include/SDL_surface.h b/vendor/sdl3/include/SDL_surface.h index 7bff7cfb2..885f8f5d9 100644 --- a/vendor/sdl3/include/SDL_surface.h +++ b/vendor/sdl3/include/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -29,12 +29,16 @@ * provides a reasonable toolbox for transforming the data, including copying * between surfaces, filling rectangles in the image data, etc. * - * There is also a simple .bmp loader, SDL_LoadBMP(). SDL itself does not - * provide loaders for various other file formats, but there are several - * excellent external libraries that do, including its own satellite library, - * SDL_image: + * There is also a simple .bmp loader, SDL_LoadBMP(), and a simple .png + * loader, SDL_LoadPNG(). SDL itself does not provide loaders for other file + * formats, but there are several excellent external libraries that do, + * including its own satellite library, + * [SDL_image](https://wiki.libsdl.org/SDL3_image) + * . * - * https://github.com/libsdl-org/SDL_image + * In general these functions are thread-safe in that they can be called on + * different threads with different surfaces. You should not try to modify any + * surface from two threads simultaneously. */ #ifndef SDL_surface_h_ @@ -83,8 +87,9 @@ typedef Uint32 SDL_SurfaceFlags; typedef enum SDL_ScaleMode { SDL_SCALEMODE_INVALID = -1, - SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ - SDL_SCALEMODE_LINEAR /**< linear filtering */ + SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ + SDL_SCALEMODE_LINEAR, /**< linear filtering */ + SDL_SCALEMODE_PIXELART /**< nearest pixel sampling with improved scaling for pixel art, available since SDL 3.4.0 */ } SDL_ScaleMode; /** @@ -94,9 +99,10 @@ typedef enum SDL_ScaleMode */ typedef enum SDL_FlipMode { - SDL_FLIP_NONE, /**< Do not flip */ - SDL_FLIP_HORIZONTAL, /**< flip horizontally */ - SDL_FLIP_VERTICAL /**< flip vertically */ + SDL_FLIP_NONE, /**< Do not flip */ + SDL_FLIP_HORIZONTAL, /**< flip horizontally */ + SDL_FLIP_VERTICAL, /**< flip vertically */ + SDL_FLIP_HORIZONTAL_AND_VERTICAL = (SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL) /**< flip horizontally and vertically (not a diagonal flip) */ } SDL_FlipMode; #ifndef SDL_INTERNAL @@ -235,6 +241,12 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); * left edge of the image, if this surface is being used as a cursor. * - `SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER`: the hotspot pixel offset from the * top edge of the image, if this surface is being used as a cursor. + * - `SDL_PROP_SURFACE_ROTATION_FLOAT`: the number of degrees a surface's data + * is meant to be rotated clockwise to make the image right-side up. Default + * 0. This is used by the camera API, if a mobile device is oriented + * differently than what its camera provides (i.e. - the camera always + * provides portrait images but the phone is being held in landscape + * orientation). Since SDL 3.4.0. * * \param surface the SDL_Surface structure to query. * \returns a valid property ID on success or 0 on failure; call @@ -251,6 +263,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac #define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap" #define SDL_PROP_SURFACE_HOTSPOT_X_NUMBER "SDL.surface.hotspot.x" #define SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER "SDL.surface.hotspot.y" +#define SDL_PROP_SURFACE_ROTATION_FLOAT "SDL.surface.rotation" /** * Set the colorspace used by a surface. @@ -264,7 +277,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -283,7 +297,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, * \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if * the surface is NULL. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -313,7 +328,8 @@ extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface * the surface didn't have an index format); call SDL_GetError() for * more information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -324,6 +340,9 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface * /** * Set the palette used by a surface. * + * Setting the palette keeps an internal reference to the palette, which can + * be safely destroyed afterwards. + * * A single palette can be shared with many surfaces. * * \param surface the SDL_Surface structure to update. @@ -331,7 +350,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface * * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -372,7 +392,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetSurfacePalette(SDL_Surface *sur * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -415,7 +436,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasAlternateImages(SDL_Surface *surf * failure; call SDL_GetError() for more information. This should be * freed with SDL_free() when it is no longer needed. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -433,7 +455,8 @@ extern SDL_DECLSPEC SDL_Surface ** SDLCALL SDL_GetSurfaceImages(SDL_Surface *sur * * \param surface the SDL_Surface structure to update. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -459,9 +482,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_RemoveSurfaceAlternateImages(SDL_Surface *s * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. The locking referred to by - * this function is making the pixels available for direct - * access, not thread-safe locking. + * \threadsafety This function can be called on different threads with + * different surfaces. The locking referred to by this function + * is making the pixels available for direct access, not + * thread-safe locking. * * \since This function is available since SDL 3.2.0. * @@ -485,6 +509,46 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface); */ extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); +/** + * Load a BMP or PNG image from a seekable SDL data stream. + * + * The new surface should be freed with SDL_DestroySurface(). Not doing so + * will result in a memory leak. + * + * \param src the data stream for the surface. + * \param closeio if true, calls SDL_CloseIO() on `src` before returning, even + * in the case of an error. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_DestroySurface + * \sa SDL_LoadSurface + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface_IO(SDL_IOStream *src, bool closeio); + +/** + * Load a BMP or PNG image from a file. + * + * The new surface should be freed with SDL_DestroySurface(). Not doing so + * will result in a memory leak. + * + * \param file the file to load. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_DestroySurface + * \sa SDL_LoadSurface_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadSurface(const char *file); + /** * Load a BMP image from a seekable SDL data stream. * @@ -543,7 +607,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file); * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -553,7 +618,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file); extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); /** - * Save a surface to a file. + * Save a surface to a file in BMP format. * * Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the * BMP directly. Other RGB formats with 8-bit or higher get converted to a @@ -566,7 +631,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -575,6 +641,94 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre */ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); +/** + * Load a PNG image from a seekable SDL data stream. + * + * This is intended as a convenience function for loading images from trusted + * sources. If you want to load arbitrary images you should use libpng or + * another image loading library designed with security in mind. + * + * The new surface should be freed with SDL_DestroySurface(). Not doing so + * will result in a memory leak. + * + * \param src the data stream for the surface. + * \param closeio if true, calls SDL_CloseIO() on `src` before returning, even + * in the case of an error. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_DestroySurface + * \sa SDL_LoadPNG + * \sa SDL_SavePNG_IO + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadPNG_IO(SDL_IOStream *src, bool closeio); + +/** + * Load a PNG image from a file. + * + * This is intended as a convenience function for loading images from trusted + * sources. If you want to load arbitrary images you should use libpng or + * another image loading library designed with security in mind. + * + * The new surface should be freed with SDL_DestroySurface(). Not doing so + * will result in a memory leak. + * + * \param file the PNG file to load. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_DestroySurface + * \sa SDL_LoadPNG_IO + * \sa SDL_SavePNG + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadPNG(const char *file); + +/** + * Save a surface to a seekable SDL data stream in PNG format. + * + * \param surface the SDL_Surface structure containing the image to be saved. + * \param dst a data stream to save to. + * \param closeio if true, calls SDL_CloseIO() on `dst` before returning, even + * in the case of an error. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function can be called on different threads with + * different surfaces. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_LoadPNG_IO + * \sa SDL_SavePNG + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); + +/** + * Save a surface to a file in PNG format. + * + * \param surface the SDL_Surface structure containing the image to be saved. + * \param file a file to save to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function can be called on different threads with + * different surfaces. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_LoadPNG + * \sa SDL_SavePNG_IO + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SavePNG(SDL_Surface *surface, const char *file); + /** * Set the RLE acceleration hint for a surface. * @@ -586,7 +740,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *f * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -628,7 +783,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -693,7 +849,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -713,7 +870,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -735,7 +893,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -773,7 +932,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -812,7 +972,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, S * \returns true if the rectangle intersects the surface, otherwise false and * blits will be completely clipped. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -833,7 +994,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, co * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -849,12 +1011,42 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SD * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip); +/** + * Return a copy of a surface rotated clockwise a number of degrees. + * + * The angle of rotation can be negative for counter-clockwise rotation. + * + * When the rotation isn't a multiple of 90 degrees, the resulting surface is + * larger than the original, with the background filled in with the colorkey, + * if available, or RGBA 255/255/255/0 if not. + * + * If `surface` has the SDL_PROP_SURFACE_ROTATION_FLOAT property set on it, + * the new copy will have the adjusted value set: if the rotation property is + * 90 and `angle` was 30, the new surface will have a property value of 60 + * (that is: to be upright vs gravity, this surface needs to rotate 60 more + * degrees). However, note that further rotations on the new surface in this + * example will produce unexpected results, since the image will have resized + * and padded to accommodate the not-90 degree angle. + * + * \param surface the surface to rotate. + * \param angle the rotation angle, in degrees. + * \returns a rotated copy of the surface or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function can be called on different threads with + * different surfaces. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_RotateSurface(SDL_Surface *surface, float angle); + /** * Creates a new surface identical to the existing surface. * @@ -867,7 +1059,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipM * \returns a copy of the surface or NULL on failure; call SDL_GetError() for * more information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -888,7 +1081,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_DuplicateSurface(SDL_Surface *surf * \returns a copy of the surface or NULL on failure; call SDL_GetError() for * more information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -915,7 +1109,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ScaleSurface(SDL_Surface *surface, * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -943,7 +1138,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface(SDL_Surface *surfac * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -1046,7 +1242,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ @@ -1058,7 +1255,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surfac * This function handles all surface formats, and ignores any clip rectangle. * * If the surface is YUV, the color is assumed to be in the sRGB colorspace, - * otherwise the color is assumed to be in the colorspace of the suface. + * otherwise the color is assumed to be in the colorspace of the surface. * * \param surface the SDL_Surface to clear. * \param r the red component of the pixel, normally in the range 0-1. @@ -1068,7 +1265,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surfac * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ @@ -1093,7 +1291,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -1120,7 +1319,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -1135,9 +1335,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD * If either `srcrect` or `dstrect` are NULL, the entire surface (`src` or * `dst`) is copied while ensuring clipping to `dst->clip_rect`. * - * The final blit rectangles are saved in `srcrect` and `dstrect` after all - * clipping is performed. - * * The blit function should not be called on a locked surface. * * The blit semantics for surfaces with and without blending and colorkey are @@ -1282,10 +1479,11 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src * * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied, may not be NULL. + * copied, or NULL to copy the entire surface. * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface, may not be NULL. + * the destination surface, or NULL to fill the entire + * destination surface. * \param scaleMode the SDL_ScaleMode to be used. * \returns true on success or false on failure; call SDL_GetError() for more * information. @@ -1413,7 +1611,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SD * \param b the blue component of the pixel in the range 0-255. * \returns a pixel value. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -1446,7 +1645,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8 * \param a the alpha component of the pixel in the range 0-255. * \returns a pixel value. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. * @@ -1477,7 +1677,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ @@ -1503,7 +1704,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ @@ -1528,7 +1730,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ @@ -1550,7 +1753,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety This function is not thread safe. + * \threadsafety This function can be called on different threads with + * different surfaces. * * \since This function is available since SDL 3.2.0. */ diff --git a/vendor/sdl3/include/SDL_system.h b/vendor/sdl3/include/SDL_system.h index 294089ff4..ec23a1fe7 100644 --- a/vendor/sdl3/include/SDL_system.h +++ b/vendor/sdl3/include/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -86,6 +86,8 @@ typedef bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); * \param callback the SDL_WindowsMessageHook function to call. * \param userdata a pointer to pass to every iteration of `callback`. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_WindowsMessageHook @@ -169,6 +171,8 @@ typedef bool (SDLCALL *SDL_X11EventHook)(void *userdata, XEvent *xevent); * \param callback the SDL_X11EventHook function to call. * \param userdata a pointer to pass to every iteration of `callback`. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata); @@ -186,6 +190,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriority(Sint64 threadID, int priority); @@ -202,6 +208,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriority(Sint64 threadID, int * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); @@ -247,14 +255,14 @@ typedef void (SDLCALL *SDL_iOSAnimationCallback)(void *userdata); * * For more information see: * - * https://wiki.libsdl.org/SDL3/README/ios + * https://wiki.libsdl.org/SDL3/README-ios * * Note that if you use the "main callbacks" instead of a standard C `main` * function, you don't have to use this API, as SDL will manage this for you. * * Details on main callbacks are here: * - * https://wiki.libsdl.org/SDL3/README/main-functions + * https://wiki.libsdl.org/SDL3/README-main-functions * * \param window the window for which the animation callback should be set. * \param interval the number of frames after which **callback** will be @@ -264,6 +272,8 @@ typedef void (SDLCALL *SDL_iOSAnimationCallback)(void *userdata); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetiOSEventPump @@ -277,6 +287,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetiOSAnimationCallback(SDL_Window *window, * * \param enabled true to enable the event pump, false to disable it. * + * \threadsafety This function should only be called on the main thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetiOSAnimationCallback @@ -370,6 +382,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetAndroidActivity(void); * * \returns the Android API level. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); @@ -379,6 +393,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); * * \returns true if this is a Chromebook, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_IsChromebook(void); @@ -388,6 +404,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsChromebook(void); * * \returns true if this is a DeX docking station, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_IsDeXMode(void); @@ -605,6 +623,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SendAndroidMessage(Uint32 command, int para * * \returns true if the device is a tablet, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_IsTablet(void); @@ -616,6 +636,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsTablet(void); * * \returns true if the device is a TV, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_IsTV(void); diff --git a/vendor/sdl3/include/SDL_test.h b/vendor/sdl3/include/SDL_test.h index 8b285807c..59a3dd846 100644 --- a/vendor/sdl3/include/SDL_test.h +++ b/vendor/sdl3/include/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_assert.h b/vendor/sdl3/include/SDL_test_assert.h index c067608a5..ff41b31b9 100644 --- a/vendor/sdl3/include/SDL_test_assert.h +++ b/vendor/sdl3/include/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_common.h b/vendor/sdl3/include/SDL_test_common.h index 91efe8ac3..6afd85779 100644 --- a/vendor/sdl3/include/SDL_test_common.h +++ b/vendor/sdl3/include/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -153,6 +153,10 @@ typedef struct SDL_Rect confine; bool hide_cursor; + /* Misc. */ + int quit_after_ms_interval; + SDL_TimerID quit_after_ms_timer; + /* Options info */ SDLTest_ArgumentParser common_argparser; SDLTest_ArgumentParser video_argparser; diff --git a/vendor/sdl3/include/SDL_test_compare.h b/vendor/sdl3/include/SDL_test_compare.h index 7ff247793..58e55134e 100644 --- a/vendor/sdl3/include/SDL_test_compare.h +++ b/vendor/sdl3/include/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -52,6 +52,7 @@ extern "C" { * \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ. */ int SDLCALL SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); +int SDLCALL SDLTest_CompareSurfacesIgnoreTransparentPixels(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); /** * Compares 2 memory blocks for equality diff --git a/vendor/sdl3/include/SDL_test_crc32.h b/vendor/sdl3/include/SDL_test_crc32.h index 94fe1a345..f563d5dd2 100644 --- a/vendor/sdl3/include/SDL_test_crc32.h +++ b/vendor/sdl3/include/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_font.h b/vendor/sdl3/include/SDL_test_font.h index fb4079497..f5b567454 100644 --- a/vendor/sdl3/include/SDL_test_font.h +++ b/vendor/sdl3/include/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_fuzzer.h b/vendor/sdl3/include/SDL_test_fuzzer.h index caf11f252..e8ebc45c9 100644 --- a/vendor/sdl3/include/SDL_test_fuzzer.h +++ b/vendor/sdl3/include/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_harness.h b/vendor/sdl3/include/SDL_test_harness.h index 5d4963e77..37710455b 100644 --- a/vendor/sdl3/include/SDL_test_harness.h +++ b/vendor/sdl3/include/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_log.h b/vendor/sdl3/include/SDL_test_log.h index 0d48044a0..13933da95 100644 --- a/vendor/sdl3/include/SDL_test_log.h +++ b/vendor/sdl3/include/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,6 +42,14 @@ extern "C" { #endif +/** + * Prints given message with a timestamp in the TEST category and given priority. + * + * \param priority Priority of the message + * \param fmt Message to be logged + */ +void SDLCALL SDLTest_LogMessage(SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...); + /** * Prints given message with a timestamp in the TEST category and INFO priority. * diff --git a/vendor/sdl3/include/SDL_test_md5.h b/vendor/sdl3/include/SDL_test_md5.h index e9d96398a..7b86b05f7 100644 --- a/vendor/sdl3/include/SDL_test_md5.h +++ b/vendor/sdl3/include/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_test_memory.h b/vendor/sdl3/include/SDL_test_memory.h index 1bd946674..f07f1cba9 100644 --- a/vendor/sdl3/include/SDL_test_memory.h +++ b/vendor/sdl3/include/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_thread.h b/vendor/sdl3/include/SDL_thread.h index e981b5429..f74317cc6 100644 --- a/vendor/sdl3/include/SDL_thread.h +++ b/vendor/sdl3/include/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,7 +37,8 @@ * will report failure without doing anything. * * If you're going to work with threads, you almost certainly need to have a - * good understanding of [CategoryMutex](CategoryMutex) as well. + * good understanding of thread safety measures: locking and synchronization + * mechanisms are handled by the functions in SDL_mutex.h. */ #include @@ -207,6 +208,8 @@ typedef int (SDLCALL *SDL_ThreadFunction) (void *data); * new thread could not be created; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateThreadWithProperties @@ -273,6 +276,8 @@ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, * new thread could not be created; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateThread @@ -328,6 +333,8 @@ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithProperties(SDL_Prop * new thread could not be created; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadRuntime(SDL_ThreadFunction fn, const char *name, void *data, SDL_FunctionPointer pfnBeginThread, SDL_FunctionPointer pfnEndThread); @@ -342,6 +349,8 @@ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadRuntime(SDL_ThreadFunct * new thread could not be created; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props, SDL_FunctionPointer pfnBeginThread, SDL_FunctionPointer pfnEndThread); @@ -362,6 +371,8 @@ extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithPropertiesRuntime(S * \returns a pointer to a UTF-8 string that names the specified thread, or * NULL if it doesn't have a name. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC const char * SDLCALL SDL_GetThreadName(SDL_Thread *thread); @@ -378,6 +389,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetThreadName(SDL_Thread *thread); * * \returns the ID of the current thread. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetThreadID @@ -395,6 +408,8 @@ extern SDL_DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); * \returns the ID of the specified thread, or the ID of the current thread if * `thread` is NULL. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetCurrentThreadID @@ -412,6 +427,8 @@ extern SDL_DECLSPEC SDL_ThreadID SDLCALL SDL_GetThreadID(SDL_Thread *thread); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_SetCurrentThreadPriority(SDL_ThreadPriority priority); @@ -444,6 +461,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetCurrentThreadPriority(SDL_ThreadPriority * function by its 'return', or -1 if the thread has been * detached or isn't valid, may be NULL. * + * \threadsafety It is safe to call this function from any thread, but only + * a single thread can wait any specific thread to finish. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateThread @@ -458,6 +478,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status) * \returns the current state of a thread, or SDL_THREAD_UNKNOWN if the thread * isn't valid. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ThreadState @@ -490,6 +512,8 @@ extern SDL_DECLSPEC SDL_ThreadState SDLCALL SDL_GetThreadState(SDL_Thread *threa * * It is safe to pass NULL to this function; it is a no-op. * + * \threadsafety It is safe to call this function from any thread. + * * \param thread the SDL_Thread pointer that was returned from the * SDL_CreateThread() call that started this thread. * diff --git a/vendor/sdl3/include/SDL_time.h b/vendor/sdl3/include/SDL_time.h index b6d3f6d0d..2ae6022f9 100644 --- a/vendor/sdl3/include/SDL_time.h +++ b/vendor/sdl3/include/SDL_time.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer -Copyright (C) 1997-2025 Sam Lantinga +Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -106,6 +106,8 @@ typedef enum SDL_TimeFormat * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetDateTimeLocalePreferences(SDL_DateFormat *dateFormat, SDL_TimeFormat *timeFormat); @@ -118,6 +120,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetDateTimeLocalePreferences(SDL_DateFormat * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_GetCurrentTime(SDL_Time *ticks); @@ -134,6 +138,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetCurrentTime(SDL_Time *ticks); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, bool localTime); @@ -149,6 +155,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_Time *ticks); @@ -165,6 +173,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_ * \param dwHighDateTime a pointer filled in with the high portion of the * Windows FILETIME value. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC void SDLCALL SDL_TimeToWindows(SDL_Time ticks, Uint32 *dwLowDateTime, Uint32 *dwHighDateTime); @@ -180,6 +190,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_TimeToWindows(SDL_Time ticks, Uint32 *dwLow * \param dwHighDateTime the high portion of the Windows FILETIME value. * \returns the converted SDL time. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_Time SDLCALL SDL_TimeFromWindows(Uint32 dwLowDateTime, Uint32 dwHighDateTime); @@ -192,6 +204,8 @@ extern SDL_DECLSPEC SDL_Time SDLCALL SDL_TimeFromWindows(Uint32 dwLowDateTime, U * \returns the number of days in the requested month or -1 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC int SDLCALL SDL_GetDaysInMonth(int year, int month); @@ -205,6 +219,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetDaysInMonth(int year, int month); * \returns the day of year [0-365] if the date is valid or -1 on failure; * call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC int SDLCALL SDL_GetDayOfYear(int year, int month, int day); @@ -218,6 +234,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetDayOfYear(int year, int month, int day); * \returns a value between 0 and 6 (0 being Sunday) if the date is valid or * -1 on failure; call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC int SDLCALL SDL_GetDayOfWeek(int year, int month, int day); diff --git a/vendor/sdl3/include/SDL_timer.h b/vendor/sdl3/include/SDL_timer.h index cf94881d5..dfeec31f2 100644 --- a/vendor/sdl3/include/SDL_timer.h +++ b/vendor/sdl3/include/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,7 +34,7 @@ * This category covers measuring time elapsed (SDL_GetTicks(), * SDL_GetPerformanceCounter()), putting a thread to sleep for a certain * amount of time (SDL_Delay(), SDL_DelayNS(), SDL_DelayPrecise()), and firing - * a callback function after a certain amount of time has elasped + * a callback function after a certain amount of time has elapsed * (SDL_AddTimer(), etc). * * There are also useful macros to convert between time units, like @@ -185,14 +185,18 @@ extern "C" { #define SDL_NS_TO_US(NS) ((NS) / SDL_NS_PER_US) /** - * Get the number of milliseconds since SDL library initialization. + * Get the number of milliseconds that have elapsed since the SDL library + * initialization. * - * \returns an unsigned 64-bit value representing the number of milliseconds - * since the SDL library initialized. + * \returns an unsigned 64‑bit integer that represents the number of + * milliseconds that have elapsed since the SDL library was + * initialized (typically via a call to SDL_Init). * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_GetTicksNS */ extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetTicks(void); diff --git a/vendor/sdl3/include/SDL_touch.h b/vendor/sdl3/include/SDL_touch.h index 64845a156..e5576a5bc 100644 --- a/vendor/sdl3/include/SDL_touch.h +++ b/vendor/sdl3/include/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_tray.h b/vendor/sdl3/include/SDL_tray.h index 1780b0ba5..688278a1d 100644 --- a/vendor/sdl3/include/SDL_tray.h +++ b/vendor/sdl3/include/SDL_tray.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/vendor/sdl3/include/SDL_version.h b/vendor/sdl3/include/SDL_version.h index a3b6ae82d..7587a6e69 100644 --- a/vendor/sdl3/include/SDL_version.h +++ b/vendor/sdl3/include/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -53,7 +53,7 @@ extern "C" { * * \since This macro is available since SDL 3.2.0. */ -#define SDL_MINOR_VERSION 2 +#define SDL_MINOR_VERSION 4 /** * The current micro (or patchlevel) version of the SDL headers. @@ -62,7 +62,7 @@ extern "C" { * * \since This macro is available since SDL 3.2.0. */ -#define SDL_MICRO_VERSION 10 +#define SDL_MICRO_VERSION 2 /** * This macro turns the version numbers into a numeric value. @@ -85,6 +85,8 @@ extern "C" { * * \param version the version number. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ #define SDL_VERSIONNUM_MAJOR(version) ((version) / 1000000) @@ -96,6 +98,8 @@ extern "C" { * * \param version the version number. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ #define SDL_VERSIONNUM_MINOR(version) (((version) / 1000) % 1000) @@ -107,6 +111,8 @@ extern "C" { * * \param version the version number. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ #define SDL_VERSIONNUM_MICRO(version) ((version) % 1000) @@ -114,6 +120,8 @@ extern "C" { /** * This is the version number macro for the current SDL version. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. * * \sa SDL_GetVersion @@ -124,6 +132,8 @@ extern "C" { /** * This macro will evaluate to true if compiled with SDL at least X.Y.Z. * + * \threadsafety It is safe to call this macro from any thread. + * * \since This macro is available since SDL 3.2.0. */ #define SDL_VERSION_ATLEAST(X, Y, Z) \ @@ -141,6 +151,8 @@ extern "C" { * * \returns the version of the linked library. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetRevision @@ -148,13 +160,14 @@ extern "C" { extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void); /** - * Get the code revision of SDL that is linked against your program. + * Get the code revision of the SDL library that is linked against your + * program. * - * This value is the revision of the code you are linked with and may be + * This value is the revision of the code you are linking against and may be * different from the code you are compiling with, which is found in the - * constant SDL_REVISION. + * constant SDL_REVISION if you explicitly include SDL_revision.h * - * The revision is arbitrary string (a hash value) uniquely identifying the + * The revision is an arbitrary string (a hash value) uniquely identifying the * exact revision of the SDL library in use, and is only useful in comparing * against other revisions. It is NOT an incrementing number. * @@ -167,6 +180,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void); * \returns an arbitrary string, uniquely identifying the exact revision of * the SDL library in use. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetVersion diff --git a/vendor/sdl3/include/SDL_video.h b/vendor/sdl3/include/SDL_video.h index a7afc3267..2f062959f 100644 --- a/vendor/sdl3/include/SDL_video.h +++ b/vendor/sdl3/include/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga + Copyright (C) 1997-2026 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -97,6 +97,8 @@ typedef Uint32 SDL_WindowID; * uninitialized will either return the user provided value, if one was set * prior to initialization, or NULL. See docs/README-wayland.md for more * information. + * + * \since This macro is available since SDL 3.2.0. */ #define SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER "SDL.video.wayland.wl_display" @@ -180,6 +182,12 @@ typedef struct SDL_Window SDL_Window; * changed on existing windows by the app, and some of it might be altered by * the user or system outside of the app's control. * + * When creating windows with `SDL_WINDOW_RESIZABLE`, SDL will constrain + * resizable windows to the dimensions recommended by the compositor to fit it + * within the usable desktop space, although some compositors will do this + * automatically without intervention as well. Use `SDL_SetWindowResizable` + * after creation instead if you wish to create a window with a specific size. + * * \since This datatype is available since SDL 3.2.0. * * \sa SDL_GetWindowFlags @@ -207,6 +215,7 @@ typedef Uint64 SDL_WindowFlags; #define SDL_WINDOW_TOOLTIP SDL_UINT64_C(0x0000000000040000) /**< window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window */ #define SDL_WINDOW_POPUP_MENU SDL_UINT64_C(0x0000000000080000) /**< window should be treated as a popup menu, requires a parent window */ #define SDL_WINDOW_KEYBOARD_GRABBED SDL_UINT64_C(0x0000000000100000) /**< window has grabbed keyboard input */ +#define SDL_WINDOW_FILL_DOCUMENT SDL_UINT64_C(0x0000000000200000) /**< window is in fill-document mode (Emscripten only), since SDL 3.4.0 */ #define SDL_WINDOW_VULKAN SDL_UINT64_C(0x0000000010000000) /**< window usable for Vulkan surface */ #define SDL_WINDOW_METAL SDL_UINT64_C(0x0000000020000000) /**< window usable for Metal view */ #define SDL_WINDOW_TRANSPARENT SDL_UINT64_C(0x0000000040000000) /**< window with transparent buffer */ @@ -220,6 +229,8 @@ typedef Uint64 SDL_WindowFlags; * SDL_WINDOWPOS_UNDEFINED or SDL_WINDOWPOS_UNDEFINED_DISPLAY. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u @@ -232,6 +243,8 @@ typedef Uint64 SDL_WindowFlags; * \param X the SDL_DisplayID of the display to use. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X)) @@ -241,6 +254,8 @@ typedef Uint64 SDL_WindowFlags; * This always uses the primary display. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED_DISPLAY(0) @@ -250,6 +265,8 @@ typedef Uint64 SDL_WindowFlags; * \param X the window position value. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_ISUNDEFINED(X) (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK) @@ -260,6 +277,8 @@ typedef Uint64 SDL_WindowFlags; * SDL_WINDOWPOS_CENTERED or SDL_WINDOWPOS_CENTERED_DISPLAY. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u @@ -272,6 +291,8 @@ typedef Uint64 SDL_WindowFlags; * \param X the SDL_DisplayID of the display to use. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X)) @@ -281,6 +302,8 @@ typedef Uint64 SDL_WindowFlags; * This always uses the primary display. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_SetWindowPosition */ #define SDL_WINDOWPOS_CENTERED SDL_WINDOWPOS_CENTERED_DISPLAY(0) @@ -290,6 +313,8 @@ typedef Uint64 SDL_WindowFlags; * \param X the window position value. * * \since This macro is available since SDL 3.2.0. + * + * \sa SDL_GetWindowPosition */ #define SDL_WINDOWPOS_ISCENTERED(X) \ (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK) @@ -307,12 +332,30 @@ typedef enum SDL_FlashOperation SDL_FLASH_UNTIL_FOCUSED /**< Flash the window until it gets focus */ } SDL_FlashOperation; +/** + * Window progress state + * + * \since This enum is available since SDL 3.2.8. + */ +typedef enum SDL_ProgressState +{ + SDL_PROGRESS_STATE_INVALID = -1, /**< An invalid progress state indicating an error; check SDL_GetError() */ + SDL_PROGRESS_STATE_NONE, /**< No progress bar is shown */ + SDL_PROGRESS_STATE_INDETERMINATE, /**< The progress bar is shown in a indeterminate state */ + SDL_PROGRESS_STATE_NORMAL, /**< The progress bar is shown in a normal state */ + SDL_PROGRESS_STATE_PAUSED, /**< The progress bar is shown in a paused state */ + SDL_PROGRESS_STATE_ERROR /**< The progress bar is shown in a state indicating the application had an error */ +} SDL_ProgressState; + /** * An opaque handle to an OpenGL context. * * \since This datatype is available since SDL 3.2.0. * * \sa SDL_GL_CreateContext + * \sa SDL_GL_SetAttribute + * \sa SDL_GL_MakeCurrent + * \sa SDL_GL_DestroyContext */ typedef struct SDL_GLContextState *SDL_GLContext; @@ -426,10 +469,10 @@ typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata, SDL_EGLDi */ typedef enum SDL_GLAttr { - SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 3. */ - SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 3. */ - SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 2. */ - SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 0. */ + SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 8. */ + SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 8. */ + SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 8. */ + SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 8. */ SDL_GL_BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */ SDL_GL_DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */ SDL_GL_DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */ @@ -448,7 +491,7 @@ typedef enum SDL_GLAttr SDL_GL_CONTEXT_FLAGS, /**< some combination of 0 or more of elements of the SDL_GLContextFlag enumeration; defaults to 0. */ SDL_GL_CONTEXT_PROFILE_MASK, /**< type of GL context (Core, Compatibility, ES). See SDL_GLProfile; default value depends on platform. */ SDL_GL_SHARE_WITH_CURRENT_CONTEXT, /**< OpenGL context sharing; defaults to 0. */ - SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB capable visual; defaults to 0. */ + SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB-capable visual if 1. Defaults to -1 ("don't care"). This is a request; GL drivers might not comply! */ SDL_GL_CONTEXT_RELEASE_BEHAVIOR, /**< sets context the release behavior. See SDL_GLContextReleaseFlag; defaults to FLUSH. */ SDL_GL_CONTEXT_RESET_NOTIFICATION, /**< set context reset notification. See SDL_GLContextResetNotification; defaults to NO_NOTIFICATION. */ SDL_GL_CONTEXT_NO_ERROR, @@ -530,7 +573,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); * to be proper names. * * \param index the index of a video driver. - * \returns the name of the video driver with the given **index**. + * \returns the name of the video driver with the given **index**, or NULL if + * index is out of bounds. * * \threadsafety This function should only be called on the main thread. * @@ -617,6 +661,16 @@ extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); * responsible for any coordinate transformations needed to conform to the * requested display orientation. * + * On Wayland: + * + * - `SDL_PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER`: the wl_output associated + * with the display + * + * On Windows: + * + * - `SDL_PROP_DISPLAY_WINDOWS_HMONITOR_POINTER`: the monitor handle + * (HMONITOR) associated with the display + * * \param displayID the instance ID of the display to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -629,6 +683,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_Displa #define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled" #define SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER "SDL.display.KMSDRM.panel_orientation" +#define SDL_PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER "SDL.display.wayland.wl_output" +#define SDL_PROP_DISPLAY_WINDOWS_HMONITOR_POINTER "SDL.display.windows.hmonitor" /** * Get the name of a display in UTF-8 encoding. @@ -1041,12 +1097,14 @@ extern SDL_DECLSPEC SDL_Window ** SDLCALL SDL_GetWindows(int *count); /** * Create a window with the specified dimensions and flags. * + * The window size is a request and may be different than expected based on + * the desktop layout and window manager policies. Your application should be + * prepared to handle a window of any size. + * * `flags` may be any of the following OR'd together: * * - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context - * - `SDL_WINDOW_OCCLUDED`: window partially or completely obscured by another - * window * - `SDL_WINDOW_HIDDEN`: window is not visible * - `SDL_WINDOW_BORDERLESS`: no window decoration * - `SDL_WINDOW_RESIZABLE`: window can be resized @@ -1074,7 +1132,8 @@ extern SDL_DECLSPEC SDL_Window ** SDLCALL SDL_GetWindows(int *count); * - `SDL_WINDOW_TRANSPARENT`: window with transparent buffer * - `SDL_WINDOW_NOT_FOCUSABLE`: window should not be focusable * - * The SDL_Window is implicitly shown if SDL_WINDOW_HIDDEN is not set. + * The SDL_Window will be shown if SDL_WINDOW_HIDDEN is not set. If hidden at + * creation time, SDL_ShowWindow() can be used to show it later. * * On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist * property to YES, otherwise you will not receive a High-DPI OpenGL canvas. @@ -1127,6 +1186,10 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int /** * Create a child popup window of the specified parent window. * + * The window size is a request and may be different than expected based on + * the desktop layout and window manager policies. Your application should be + * prepared to handle a window of any size. + * * The flags parameter **must** contain at least one of the following: * * - `SDL_WINDOW_TOOLTIP`: The popup window is a tooltip and will not pass any @@ -1159,6 +1222,16 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int * Popup windows implicitly do not have a border/decorations and do not appear * on the taskbar/dock or in lists of windows such as alt-tab menus. * + * By default, popup window positions will automatically be constrained to + * keep the entire window within display bounds. This can be overridden with + * the `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN` property. + * + * By default, popup menus will automatically grab keyboard focus from the + * parent when shown. This behavior can be overridden by setting the + * `SDL_WINDOW_NOT_FOCUSABLE` flag, setting the + * `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN` property to false, or toggling + * it after creation via the `SDL_SetWindowFocusable()` function. + * * If a parent window is hidden or destroyed, any child popup windows will be * recursively hidden or destroyed as well. Child popup windows not explicitly * hidden will be restored when the parent is shown. @@ -1189,12 +1262,20 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren /** * Create a window with the specified properties. * + * The window size is a request and may be different than expected based on + * the desktop layout and window manager policies. Your application should be + * prepared to handle a window of any size. + * * These are the supported properties: * * - `SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window should * be always on top * - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no * window decoration + * - `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN`: true if the "tooltip" + * and "menu" window types should be automatically constrained to be + * entirely within display bounds (default), false if no constraints on the + * position are desired. * - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the * window will be used with an externally managed graphics context. * - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should @@ -1251,12 +1332,18 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren * - `SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER`: the `(__unsafe_unretained)` * NSView associated with the window, defaults to `[window contentView]` * + * These are additional supported properties on iOS, tvOS, and visionOS: + * + * - `SDL_PROP_WINDOW_CREATE_WINDOWSCENE_POINTER`: the `(__unsafe_unretained)` + * UIWindowScene associated with the window, defaults to the active window + * scene. + * * These are additional supported properties on Wayland: * * - `SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true if * the application wants to use the Wayland surface for a custom role and * does not want it attached to an XDG toplevel window. See - * [README/wayland](README/wayland) for more information on using custom + * [README-wayland](README-wayland) for more information on using custom * surfaces. * - `SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN` - true if the * application wants an associated `wl_egl_window` object to be created and @@ -1264,7 +1351,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren * property or `SDL_WINDOW_OPENGL` flag set. * - `SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` - the wl_surface * associated with the window, if you want to wrap an existing window. See - * [README/wayland](README/wayland) for more information. + * [README-wayland](README-wayland) for more information. * * These are additional supported properties on Windows: * @@ -1280,8 +1367,22 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren * * The window is implicitly shown if the "hidden" property is not set. * - * Windows with the "tooltip" and "menu" properties are popup windows and have - * the behaviors and guidelines outlined in SDL_CreatePopupWindow(). + * These are additional supported properties with Emscripten: + * + * - `SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING`: the id given to the + * canvas element. This should start with a '#' sign + * - `SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING`: override the + * binding element for keyboard inputs for this canvas. The variable can be + * one of: + * - "#window": the javascript window object (default) + * - "#document": the javascript document object + * - "#screen": the javascript window.screen object + * - "#canvas": the WebGL canvas element + * - "#none": Don't bind anything at all + * - any other string without a leading # sign applies to the element on the + * page with that ID. Windows with the "tooltip" and "menu" properties are + * popup windows and have the behaviors and guidelines outlined in + * SDL_CreatePopupWindow(). * * If this window is being created to be used with an SDL_Renderer, you should * not add a graphics API specific property @@ -1309,6 +1410,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop #define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top" #define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless" +#define SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN "SDL.window.create.constrain_popup" #define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable" #define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context" #define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags" @@ -1335,12 +1437,15 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop #define SDL_PROP_WINDOW_CREATE_Y_NUMBER "SDL.window.create.y" #define SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER "SDL.window.create.cocoa.window" #define SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER "SDL.window.create.cocoa.view" +#define SDL_PROP_WINDOW_CREATE_WINDOWSCENE_POINTER "SDL.window.create.uikit.windowscene" #define SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "SDL.window.create.wayland.surface_role_custom" #define SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "SDL.window.create.wayland.create_egl_window" #define SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER "SDL.window.create.wayland.wl_surface" #define SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER "SDL.window.create.win32.hwnd" #define SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "SDL.window.create.win32.pixel_format_hwnd" #define SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER "SDL.window.create.x11.window" +#define SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING "SDL.window.create.emscripten.canvas_id" +#define SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING "SDL.window.create.emscripten.keyboard_element" /** * Get the numeric ID of a window. @@ -1448,12 +1553,12 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window) * - `SDL_PROP_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)` * NSWindow associated with the window * - `SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag - * assocated with metal views on the window + * associated with metal views on the window * * On OpenVR: * - * - `SDL_PROP_WINDOW_OPENVR_OVERLAY_ID`: the OpenVR Overlay Handle ID for the - * associated overlay window. + * - `SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER`: the OpenVR Overlay Handle ID + * for the associated overlay window. * * On Vivante: * @@ -1505,6 +1610,13 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window) * - `SDL_PROP_WINDOW_X11_WINDOW_NUMBER`: the X11 Window associated with the * window * + * On Emscripten: + * + * - `SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING`: the id the canvas element + * will have + * - `SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING`: the keyboard + * element that associates keyboard events to this window + * * \param window the window to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -1531,7 +1643,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window #define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" #define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" #define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" -#define SDL_PROP_WINDOW_OPENVR_OVERLAY_ID "SDL.window.openvr.overlay_id" +#define SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER "SDL.window.openvr.overlay_id" #define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" #define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" #define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" @@ -1550,6 +1662,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window #define SDL_PROP_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" #define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" #define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" +#define SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING "SDL.window.emscripten.canvas_id" +#define SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING "SDL.window.emscripten.keyboard_element" /** * Get the window flags. @@ -1567,6 +1681,7 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window * \sa SDL_MinimizeWindow * \sa SDL_SetWindowFullscreen * \sa SDL_SetWindowMouseGrab + * \sa SDL_SetWindowFillDocument * \sa SDL_ShowWindow */ extern SDL_DECLSPEC SDL_WindowFlags SDLCALL SDL_GetWindowFlags(SDL_Window *window); @@ -1607,15 +1722,16 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window); /** * Set the icon for a window. * - * If this function is passed a surface with alternate representations, the - * surface will be interpreted as the content to be used for 100% display - * scale, and the alternate representations will be used for high DPI - * situations. For example, if the original surface is 32x32, then on a 2x - * macOS display or 200% display scale on Windows, a 64x64 version of the - * image will be used, if available. If a matching version of the image isn't - * available, the closest larger size image will be downscaled to the - * appropriate size and be used instead, if available. Otherwise, the closest - * smaller image will be upscaled and be used instead. + * If this function is passed a surface with alternate representations added + * using SDL_AddSurfaceAlternateImage(), the surface will be interpreted as + * the content to be used for 100% display scale, and the alternate + * representations will be used for high DPI situations. For example, if the + * original surface is 32x32, then on a 2x macOS display or 200% display scale + * on Windows, a 64x64 version of the image will be used, if available. If a + * matching version of the image isn't available, the closest larger size + * image will be downscaled to the appropriate size and be used instead, if + * available. Otherwise, the closest smaller image will be upscaled and be + * used instead. * * \param window the window to change. * \param icon an SDL_Surface structure containing the icon for the window. @@ -1625,6 +1741,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window); * \threadsafety This function should only be called on the main thread. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_AddSurfaceAlternateImage */ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); @@ -1751,6 +1869,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, in * \sa SDL_GetRenderOutputSize * \sa SDL_GetWindowSizeInPixels * \sa SDL_SetWindowSize + * \sa SDL_EVENT_WINDOW_RESIZED */ extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h); @@ -1762,7 +1881,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, i * notches, TV overscan, etc. This function provides the area of the window * which is safe to have interactable content. You should continue rendering * into the rest of the window, but it should not contain visually important - * or interactible content. + * or interactable content. * * \param window the window to query. * \param rect a pointer filled in with the client area that is safe for @@ -1818,7 +1937,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSafeArea(SDL_Window *window, SDL_R extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAspectRatio(SDL_Window *window, float min_aspect, float max_aspect); /** - * Get the size of a window's client area. + * Get the aspect ratio of a window's client area. * * \param window the window to query the width and height from. * \param min_aspect a pointer filled in with the minimum aspect ratio of the @@ -2032,6 +2151,37 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowResizable(SDL_Window *window, bool */ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window *window, bool on_top); +/** + * Set the window to fill the current document space (Emscripten only). + * + * This will add or remove the window's `SDL_WINDOW_FILL_DOCUMENT` flag. + * + * Currently this flag only applies to the Emscripten target. + * + * When enabled, the canvas element fills the entire document. Resize events + * will be generated as the browser window is resized, as that will adjust the + * canvas size as well. The canvas will cover anything else on the page, + * including any controls provided by Emscripten in its generated HTML file + * (in fact, any elements on the page that aren't the canvas will be moved + * into a hidden `div` element). + * + * Often times this is desirable for a browser-based game, but it means + * several things that we expect of an SDL window on other platforms might not + * work as expected, such as minimum window sizes and aspect ratios. + * + * \param window the window of which to change the fill-document state. + * \param fill true to set the window to fill the document, false to disable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_GetWindowFlags + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowFillDocument(SDL_Window *window, bool fill); + /** * Show a window. * @@ -2445,7 +2595,6 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window *window, b * * \sa SDL_GetWindowMouseRect * \sa SDL_SetWindowMouseRect - * \sa SDL_SetWindowMouseGrab * \sa SDL_SetWindowKeyboardGrab */ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowMouseGrab(SDL_Window *window, bool grabbed); @@ -2790,6 +2939,62 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowShape(SDL_Window *window, SDL_Surf */ extern SDL_DECLSPEC bool SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation); +/** + * Sets the state of the progress bar for the given window’s taskbar icon. + * + * \param window the window whose progress state is to be modified. + * \param state the progress state. `SDL_PROGRESS_STATE_NONE` stops displaying + * the progress bar. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressState(SDL_Window *window, SDL_ProgressState state); + +/** + * Get the state of the progress bar for the given window’s taskbar icon. + * + * \param window the window to get the current progress state from. + * \returns the progress state, or `SDL_PROGRESS_STATE_INVALID` on failure; + * call SDL_GetError() for more information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_ProgressState SDLCALL SDL_GetWindowProgressState(SDL_Window *window); + +/** + * Sets the value of the progress bar for the given window’s taskbar icon. + * + * \param window the window whose progress value is to be modified. + * \param value the progress value in the range of [0.0f - 1.0f]. If the value + * is outside the valid range, it gets clamped. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowProgressValue(SDL_Window *window, float value); + +/** + * Get the value of the progress bar for the given window’s taskbar icon. + * + * \param window the window to get the current progress value from. + * \returns the progress value in the range of [0.0f - 1.0f], or -1.0f on + * failure; call SDL_GetError() for more information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC float SDLCALL SDL_GetWindowProgressValue(SDL_Window *window); + /** * Destroy a window. * @@ -3025,8 +3230,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); * SDL_GL_GetAttribute() to check the values after creating the OpenGL * context, since the values obtained can differ from the requested ones. * - * \param attr an SDL_GLAttr enum value specifying the OpenGL attribute to - * set. + * \param attr an enum value specifying the OpenGL attribute to set. * \param value the desired value for the attribute. * \returns true on success or false on failure; call SDL_GetError() for more * information. @@ -3035,6 +3239,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); * * \since This function is available since SDL 3.2.0. * + * \sa SDL_GL_CreateContext * \sa SDL_GL_GetAttribute * \sa SDL_GL_ResetAttributes */ @@ -3061,6 +3266,12 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GL_GetAttribute(SDL_GLAttr attr, int *value /** * Create an OpenGL context for an OpenGL window, and make it current. * + * The OpenGL context will be created with the current states set through + * SDL_GL_SetAttribute(). + * + * The SDL_Window specified must have been created with the SDL_WINDOW_OPENGL + * flag, or context creation will fail. + * * Windows users new to OpenGL should note that, for historical reasons, GL * functions added after OpenGL version 1.1 are not available by default. * Those functions must be loaded at run-time, either with an OpenGL diff --git a/vendor/sdl3/include/SDL_vulkan.h b/vendor/sdl3/include/SDL_vulkan.h index 710afbe63..e91e14842 100644 --- a/vendor/sdl3/include/SDL_vulkan.h +++ b/vendor/sdl3/include/SDL_vulkan.h @@ -51,14 +51,14 @@ extern "C" { #endif -/* Avoid including vulkan.h, don't define VkInstance if it's already included */ -#ifdef VULKAN_H_ +/* Avoid including vulkan_core.h, don't define VkInstance if it's already included */ +#ifdef VULKAN_CORE_H_ #define NO_SDL_VULKAN_TYPEDEFS #endif #ifndef NO_SDL_VULKAN_TYPEDEFS #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; -#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64) #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; #else #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; diff --git a/vendor/sdl3/mixer/LICENSE.gme.txt b/vendor/sdl3/mixer/LICENSE.gme.txt new file mode 100644 index 000000000..5ab7695ab --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.gme.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/vendor/sdl3/mixer/LICENSE.ogg-vorbis.txt b/vendor/sdl3/mixer/LICENSE.ogg-vorbis.txt new file mode 100644 index 000000000..fb456a87b --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.ogg-vorbis.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002-2020 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sdl3/mixer/LICENSE.opus.txt b/vendor/sdl3/mixer/LICENSE.opus.txt new file mode 100644 index 000000000..9c739c34a --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.opus.txt @@ -0,0 +1,44 @@ +Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic, + Jean-Marc Valin, Timothy B. Terriberry, + CSIRO, Gregory Maxwell, Mark Borgerding, + Erik de Castro Lopo + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific contributors, may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Opus is subject to the royalty-free patent licenses which are +specified at: + +Xiph.Org Foundation: +https://datatracker.ietf.org/ipr/1524/ + +Microsoft Corporation: +https://datatracker.ietf.org/ipr/1914/ + +Broadcom Corporation: +https://datatracker.ietf.org/ipr/1526/ diff --git a/vendor/sdl3/mixer/LICENSE.opusfile.txt b/vendor/sdl3/mixer/LICENSE.opusfile.txt new file mode 100644 index 000000000..7b53d665d --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.opusfile.txt @@ -0,0 +1,28 @@ +Copyright (c) 1994-2013 Xiph.Org Foundation and contributors + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.Org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sdl3/mixer/LICENSE.txt b/vendor/sdl3/mixer/LICENSE.txt new file mode 100644 index 000000000..acaf5b21b --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.txt @@ -0,0 +1,17 @@ +Copyright (C) 1997-2026 Sam Lantinga + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/vendor/sdl3/mixer/LICENSE.wavpack.txt b/vendor/sdl3/mixer/LICENSE.wavpack.txt new file mode 100644 index 000000000..a0136963e --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.wavpack.txt @@ -0,0 +1,25 @@ + Copyright (c) 1998 - 2025 David Bryant + All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/sdl3/mixer/LICENSE.xmp.txt b/vendor/sdl3/mixer/LICENSE.xmp.txt new file mode 100644 index 000000000..ed3491ee5 --- /dev/null +++ b/vendor/sdl3/mixer/LICENSE.xmp.txt @@ -0,0 +1,20 @@ +Extended Module Player +Copyright (C) 1996-2024 Claudio Matsuoka and Hipolito Carraro Jr + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/sdl3/mixer/SDL3_mixer.dll b/vendor/sdl3/mixer/SDL3_mixer.dll new file mode 100644 index 000000000..fba705818 --- /dev/null +++ b/vendor/sdl3/mixer/SDL3_mixer.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8708c991962cee6fa30e69969d0261eb1c2bba1f5609f21cd096681664406a25 +size 434176 diff --git a/vendor/sdl3/mixer/SDL3_mixer.lib b/vendor/sdl3/mixer/SDL3_mixer.lib new file mode 100644 index 000000000..eef40ba35 --- /dev/null +++ b/vendor/sdl3/mixer/SDL3_mixer.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc07725d580297402884da96999a63ed844b3359e98b9ed257c20fef9f492a99 +size 22380 diff --git a/vendor/sdl3/mixer/include/SDL_mixer.h b/vendor/sdl3/mixer/include/SDL_mixer.h new file mode 100644 index 000000000..8eca47369 --- /dev/null +++ b/vendor/sdl3/mixer/include/SDL_mixer.h @@ -0,0 +1,3347 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2026 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* WIKI CATEGORY: SDLMixer */ + +/** + * # CategorySDLMixer + * + * SDL_mixer is a library to make complicated audio processing tasks easier. + * + * It offers audio file decoding, mixing multiple sounds together, basic 3D + * positional audio, and various audio effects. + * + * It can mix sound to multiple audio devices in real time, or generate mixed + * audio data to a memory buffer for any other use. It can do both at the same + * time! + * + * To use the library, first call MIX_Init(). Then create a mixer with + * MIX_CreateMixerDevice() (or MIX_CreateMixer() to render to memory). + * + * Once you have a mixer, you can load sound data with MIX_LoadAudio(), + * MIX_LoadAudio_IO(), or MIX_LoadAudioWithProperties(). Data gets loaded once + * and can be played over and over. + * + * When loading audio, SDL_mixer can parse out several metadata tag formats, + * such as ID3 and APE tags, and exposes this information through the + * MIX_GetAudioProperties() function. + * + * To play audio, you create a track with MIX_CreateTrack(). You need one + * track for each sound that will be played simultaneously; think of tracks as + * individual sliders on a mixer board. You might have loaded hundreds of + * audio files, but you probably only have a handful of tracks that you assign + * those loaded files to when they are ready to play, and reuse those tracks + * with different audio later. Tracks take their input from a MIX_Audio + * (static data to be played multiple times) or an SDL_AudioStream (streaming + * PCM audio the app supplies, possibly as needed). A third option is to + * supply an SDL_IOStream, to load and decode on the fly, which might be more + * efficient for background music that is only used once, etc. + * + * Assign input to a MIX_Track with MIX_SetTrackAudio(), + * MIX_SetTrackAudioStream(), or MIX_SetTrackIOStream(). + * + * Once a track has an input, start it playing with MIX_PlayTrack(). There are + * many options to this function to dictate mixing features: looping, fades, + * etc. + * + * Tracks can be tagged with arbitrary strings, like "music" or "ingame" or + * "ui". These tags can be used to start, stop, and pause a selection of + * tracks at the same moment. + * + * All significant portions of the mixing pipeline have callbacks, so that an + * app can hook in to the appropriate locations to examine or modify audio + * data as it passes through the mixer: a "raw" callback for raw PCM data + * decoded from an audio file without any modifications, a "cooked" callback + * for that same data after all transformations (fade, positioning, etc) have + * been processed, a "stopped" callback for when the track finishes mixing, a + * "postmix" callback for the final mixed audio about to be sent to the audio + * hardware to play. Additionally, you can use MIX_Group objects to mix a + * subset of playing tracks and access the data before it is mixed in with + * other tracks. All of this is optional, but allows for powerful access and + * control of the mixing process. + * + * SDL_mixer can also be used for decoding audio files without actually + * rendering a mix. This is done with MIX_AudioDecoder. Even though SDL_mixer + * handles decoding transparently when used as the audio engine for an app, + * and probably won't need this interface in that normal scenario, this can be + * useful when using a different audio library to access many file formats. + * + * This library offers several features on top of mixing sounds together: a + * track can have its own gain, to adjust its volume, in addition to a master + * gain applied as well. One can set the "frequency ratio" of a track or the + * final mixed output, to speed it up or slow it down, which also adjusts its + * pitch. A channel map can also be applied per-track, to change what speaker + * a given channel of audio is output to. + * + * Almost all timing in SDL_mixer is in _sample frames_. Stereo PCM audio data + * in Sint16 format takes 4 bytes per sample frame (2 bytes per sample times 2 + * channels), for example. This allows everything in SDL_mixer to run at + * sample-perfect accuracy, and it lets it run without concern for wall clock + * time--you can produce audio faster than real-time, if desired. The problem, + * though, is different pieces of audio at different _sample rates_ will + * produce a different number of sample frames for the same length of time. To + * deal with this, conversion routines are offered: MIX_TrackMSToFrames(), + * MIX_TrackFramesToMS(), etc. Functions that operate on multiple tracks at + * once will deal with time in milliseconds, so it can do these conversions + * internally; be sure to read the documentation for these small quirks! + * + * SDL_mixer offers basic positional audio: a simple 3D positioning API + * through MIX_SetTrack3DPosition() and MIX_SetTrackStereo(). The former will + * do simple distance attenuation and spatialization--on a stereo setup, you + * will hear sounds move from left to right--and on a surround-sound + * configuration, individual tracks can move around the user. The latter, + * MIX_SetTrackStereo(), will force a sound to the Front Left and Front Right + * speakers and let the app pan it left and right as desired. Either effect + * can be useful for different situations. SDL_mixer is not meant to be a full + * 3D audio engine, but rather Good Enough for many purposes; if something + * more powerful in terms of 3D audio is needed, consider a proper 3D library + * like OpenAL. + */ + +#ifndef SDL_MIXER_H_ +#define SDL_MIXER_H_ + +#include +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * An opaque object that represents a mixer. + * + * The MIX_Mixer is the toplevel object for this library. To use SDL_mixer, + * you must have at least one, but are allowed to have several. Each mixer is + * responsible for generating a single output stream of mixed audio, usually + * to an audio device for realtime playback. + * + * Mixers are either created to feed an audio device (through + * MIX_CreateMixerDevice()), or to generate audio to a buffer in memory, where + * it can be used for anything (through MIX_CreateMixer()). + * + * \since This datatype is available since SDL_mixer 3.0.0. + */ +typedef struct MIX_Mixer MIX_Mixer; + +/** + * An opaque object that represents audio data. + * + * Generally you load audio data (in whatever file format) into SDL_mixer with + * MIX_LoadAudio() or one of its several variants, producing a MIX_Audio + * object. + * + * A MIX_Audio represents static audio data; it could be background music, or + * maybe a laser gun sound effect. It is loaded into RAM and can be played + * multiple times, possibly on different tracks at the same time. + * + * Unlike most other objects, MIX_Audio objects can be shared between mixers. + * + * \since This datatype is available since SDL_mixer 3.0.0. + */ +typedef struct MIX_Audio MIX_Audio; + +/** + * An opaque object that represents a source of sound output to be mixed. + * + * A MIX_Mixer has an arbitrary number of tracks, and each track manages its + * own unique audio to be mixed together. + * + * Tracks also have other properties: gain, loop points, fading, 3D position, + * and other attributes that alter the produced sound; many can be altered + * during playback. + * + * \since This datatype is available since SDL_mixer 3.0.0. + */ +typedef struct MIX_Track MIX_Track; + +/** + * An opaque object that represents a grouping of tracks. + * + * SDL_mixer offers callbacks at various stages of the mixing pipeline to + * allow apps to view and manipulate data as it is transformed. Sometimes it + * is useful to hook in at a point where several tracks--but not all tracks-- + * have been mixed. For example, when a game is in some options menu, perhaps + * adjusting game audio but not UI sounds could be useful. + * + * SDL_mixer allows you to assign several tracks to a group, and receive a + * callback when that group has finished mixing, with a buffer of just that + * group's mixed audio, before it mixes into the final output. + * + * \since This datatype is available since SDL_mixer 3.0.0. + */ +typedef struct MIX_Group MIX_Group; + +/** + * The current major version of SDL_mixer headers. + * + * If this were SDL_mixer version 3.2.1, this value would be 3. + * + * \since This macro is available since SDL_mixer 3.0.0. + */ +#define SDL_MIXER_MAJOR_VERSION 3 + +/** + * The current minor version of the SDL_mixer headers. + * + * If this were SDL_mixer version 3.2.1, this value would be 2. + * + * \since This macro is available since SDL_mixer 3.0.0. + */ +#define SDL_MIXER_MINOR_VERSION 2 + +/** + * The current micro (or patchlevel) version of the SDL_mixer headers. + * + * If this were SDL_mixer version 3.2.1, this value would be 1. + * + * \since This macro is available since SDL_mixer 3.0.0. + */ +#define SDL_MIXER_MICRO_VERSION 0 + +/** + * This is the current version number macro of the SDL_mixer headers. + * + * \since This macro is available since SDL_mixer 3.0.0. + * + * \sa MIX_Version + */ +#define SDL_MIXER_VERSION SDL_VERSIONNUM(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_MICRO_VERSION) + +/** + * This macro will evaluate to true if compiled with SDL_mixer at least X.Y.Z. + * + * \since This macro is available since SDL_mixer 3.0.0. + */ +#define SDL_MIXER_VERSION_ATLEAST(X, Y, Z) \ + ((SDL_MIXER_MAJOR_VERSION >= X) && \ + (SDL_MIXER_MAJOR_VERSION > X || SDL_MIXER_MINOR_VERSION >= Y) && \ + (SDL_MIXER_MAJOR_VERSION > X || SDL_MIXER_MINOR_VERSION > Y || SDL_MIXER_MICRO_VERSION >= Z)) + +/** + * Get the version of SDL_mixer that is linked against your program. + * + * If you are linking to SDL_mixer dynamically, then it is possible that the + * current version will be different than the version you compiled against. + * This function returns the current version, while SDL_MIXER_VERSION is the + * version you compiled with. + * + * This function may be called safely at any time, even before MIX_Init(). + * + * \returns the version of the linked library. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa SDL_MIXER_VERSION + */ +extern SDL_DECLSPEC int SDLCALL MIX_Version(void); + +/** + * Initialize the SDL_mixer library. + * + * This must be successfully called once before (almost) any other SDL_mixer + * function can be used. + * + * It is safe to call this multiple times; the library will only initialize + * once, and won't deinitialize until MIX_Quit() has been called a matching + * number of times. Extra attempts to init report success. + * + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_Quit + */ +extern SDL_DECLSPEC bool SDLCALL MIX_Init(void); + +/** + * Deinitialize the SDL_mixer library. + * + * This must be called when done with the library, probably at the end of your + * program. + * + * It is safe to call this multiple times; the library will only deinitialize + * once, when this function is called the same number of times as MIX_Init was + * successfully called. + * + * Once you have successfully deinitialized the library, it is safe to call + * MIX_Init to reinitialize it for further use. + * + * On successful deinitialization, SDL_mixer will destroy almost all created + * objects, including objects of type: + * + * - MIX_Mixer + * - MIX_Track + * - MIX_Audio + * - MIX_Group + * - MIX_AudioDecoder + * + * ...which is to say: it's possible a single call to this function will clean + * up anything it allocated, stop all audio output, close audio devices, etc. + * Don't attempt to destroy objects after this call. The app is still + * encouraged to manage their resources carefully and clean up first, treating + * this function as a safety net against memory leaks. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_Init + */ +extern SDL_DECLSPEC void SDLCALL MIX_Quit(void); + +/** + * Report the number of audio decoders available for use. + * + * An audio decoder is what turns specific audio file formats into usable PCM + * data. For example, there might be an MP3 decoder, or a WAV decoder, etc. + * SDL_mixer probably has several decoders built in. + * + * The return value can be used to call MIX_GetAudioDecoder() in a loop. + * + * The number of decoders available is decided during MIX_Init() and does not + * change until the library is deinitialized. + * + * \returns the number of decoders available. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetAudioDecoder + */ +extern SDL_DECLSPEC int SDLCALL MIX_GetNumAudioDecoders(void); + +/** + * Report the name of a specific audio decoders. + * + * An audio decoder is what turns specific audio file formats into usable PCM + * data. For example, there might be an MP3 decoder, or a WAV decoder, etc. + * SDL_mixer probably has several decoders built in. + * + * The names are capital English letters and numbers, low-ASCII. They don't + * necessarily map to a specific file format; Some decoders, like "XMP" + * operate on multiple file types, and more than one decoder might handle the + * same file type, like "DRMP3" vs "MPG123". Note that in that last example, + * neither decoder is called "MP3". + * + * The index of a specific decoder is decided during MIX_Init() and does not + * change until the library is deinitialized. Valid indices are between zero + * and the return value of MIX_GetNumAudioDecoders(). + * + * The returned pointer is const memory owned by SDL_mixer; do not free it. + * + * \param index the index of the decoder to query. + * \returns a UTF-8 (really, ASCII) string of the decoder's name, or NULL if + * `index` is invalid. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetNumAudioDecoders + */ +extern SDL_DECLSPEC const char * SDLCALL MIX_GetAudioDecoder(int index); + +/** + * Create a mixer that plays sound directly to an audio device. + * + * This is usually the function you want, vs MIX_CreateMixer(). + * + * You can choose a specific device ID to open, following SDL's usual rules, + * but often the correct choice is to specify + * SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK and let SDL figure out what device to use + * (and seamlessly transition you to new hardware if the default changes). + * + * Only playback devices make sense here. Attempting to open a recording + * device will fail. + * + * This will call SDL_Init(SDL_INIT_AUDIO) internally; it's safe to call + * SDL_Init() before this call, too, if you intend to enumerate audio devices + * to choose one to open here. + * + * An audio format can be requested, and the system will try to set the + * hardware to those specifications, or as close as possible, but this is just + * a hint. SDL_mixer will handle all data conversion behind the scenes in any + * case, and specifying a NULL spec is a reasonable choice. The best reason to + * specify a format is because you know all your data is in that format and it + * might save some unnecessary CPU time on conversion. + * + * The actual device format chosen is available through MIX_GetMixerFormat(). + * + * Once a mixer is created, next steps are usually to load audio (through + * MIX_LoadAudio() and friends), create a track (MIX_CreateTrack()), and play + * that audio through that track. + * + * When done with the mixer, it can be destroyed with MIX_DestroyMixer(). + * + * \param devid the device to open for playback, or + * SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK for the default. + * \param spec the audio format to request from the device. May be NULL. + * \returns a mixer that can be used to play audio, or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should only be called on the main thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateMixer + * \sa MIX_DestroyMixer + */ +extern SDL_DECLSPEC MIX_Mixer * SDLCALL MIX_CreateMixerDevice(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec); + +/** + * Create a mixer that generates audio to a memory buffer. + * + * Usually you want MIX_CreateMixerDevice() instead of this function. The + * mixer created here can be used with MIX_Generate() to produce more data on + * demand, as fast as desired. + * + * An audio format must be specified. This is the format it will output in. + * This cannot be NULL. + * + * Once a mixer is created, next steps are usually to load audio (through + * MIX_LoadAudio() and friends), create a track (MIX_CreateTrack()), and play + * that audio through that track. + * + * When done with the mixer, it can be destroyed with MIX_DestroyMixer(). + * + * \param spec the audio format that mixer will generate. + * \returns a mixer that can be used to generate audio, or NULL on failure; + * call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateMixerDevice + * \sa MIX_DestroyMixer + */ +extern SDL_DECLSPEC MIX_Mixer * SDLCALL MIX_CreateMixer(const SDL_AudioSpec *spec); + +/** + * Free a mixer. + * + * If this mixer was created with MIX_CreateMixerDevice(), this function will + * also close the audio device and call SDL_QuitSubSystem(SDL_INIT_AUDIO). + * + * Any MIX_Group or MIX_Track created for this mixer will also be destroyed. + * Do not access them again or attempt to destroy them after the device is + * destroyed. MIX_Audio objects will not be destroyed, since they can be + * shared between mixers (but those will all be destroyed during MIX_Quit()). + * + * \param mixer the mixer to destroy. + * + * \threadsafety If this is used with a MIX_Mixer from MIX_CreateMixerDevice, + * then this function should only be called on the main thread. + * If this is used with a MIX_Mixer from MIX_CreateMixer, then + * it is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateMixerDevice + * \sa MIX_CreateMixer + */ +extern SDL_DECLSPEC void SDLCALL MIX_DestroyMixer(MIX_Mixer *mixer); + + +/** + * Get the properties associated with a mixer. + * + * The following read-only properties are provided by SDL_mixer: + * + * - `MIX_PROP_MIXER_DEVICE_NUMBER`: the SDL_AudioDeviceID that this mixer has + * opened for playback. This will be zero (no device) if the mixer was + * created with Mix_CreateMixer() instead of Mix_CreateMixerDevice(). + * + * \param mixer the mixer to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL MIX_GetMixerProperties(MIX_Mixer *mixer); + +#define MIX_PROP_MIXER_DEVICE_NUMBER "SDL_mixer.mixer.device" + + +/** + * Get the audio format a mixer is generating. + * + * Generally you don't need this information, as SDL_mixer will convert data + * as necessary between inputs you provide and its output format, but it might + * be useful if trying to match your inputs to reduce conversion and + * resampling costs. + * + * For mixers created with MIX_CreateMixerDevice(), this is the format of the + * audio device (and may change later if the device itself changes; SDL_mixer + * will seamlessly handle this change internally, though). + * + * For mixers created with MIX_CreateMixer(), this is the format that + * MIX_Generate() will produce, as requested at create time, and does not + * change. + * + * Note that internally, SDL_mixer will work in SDL_AUDIO_F32 format before + * outputting the format specified here, so it would be more efficient to + * match input data to that, not the final output format. + * + * \param mixer the mixer to query. + * \param spec where to store the mixer audio format. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_GetMixerFormat(MIX_Mixer *mixer, SDL_AudioSpec *spec); + +/** + * Lock a mixer by obtaining its internal mutex. + * + * While locked, the mixer will not be able to mix more audio or change its + * internal state in another thread. Those other threads will block until the + * mixer is unlocked again. + * + * Under the hood, this function calls SDL_LockMutex(), so all the same rules + * apply: the lock can be recursive, it must be unlocked the same number of + * times from the same thread that locked it, etc. + * + * Just about every SDL_mixer API _also_ locks the mixer while doing its work, + * as does the SDL audio device thread while actual mixing is in progress, so + * basic use of this library never requires the app to explicitly lock the + * device to be thread safe. There are two scenarios where this can be useful, + * however: + * + * - The app has a provided a callback that the mixing thread might call, and + * there is some app state that needs to be protected against race + * conditions as changes are made and mixing progresses simultaneously. Any + * lock can be used for this, but this is a conveniently-available lock. + * - The app wants to make multiple, atomic changes to the mix. For example, + * to start several tracks at the exact same moment, one would lock the + * mixer, call MIX_PlayTrack multiple times, and then unlock again; all the + * tracks will start mixing on the same sample frame. + * + * Each call to this function must be paired with a call to MIX_UnlockMixer + * from the same thread. It is safe to lock a mixer multiple times; it remains + * locked until the final matching unlock call. + * + * Do not lock the mixer for significant amounts of time, or it can cause + * audio dropouts. Just do simply things quickly and unlock again. + * + * Locking a NULL mixer is a safe no-op. + * + * \param mixer the mixer to lock. May be NULL. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_UnlockMixer + */ +extern SDL_DECLSPEC void SDLCALL MIX_LockMixer(MIX_Mixer *mixer); + +/** + * Unlock a mixer previously locked by a call to MIX_LockMixer(). + * + * While locked, the mixer will not be able to mix more audio or change its + * internal state another thread. Those other threads will block until the + * mixer is unlocked again. + * + * Under the hood, this function calls SDL_LockMutex(), so all the same rules + * apply: the lock can be recursive, it must be unlocked the same number of + * times from the same thread that locked it, etc. + * + * Unlocking a NULL mixer is a safe no-op. + * + * \param mixer the mixer to unlock. May be NULL. + * + * \threadsafety This call must be paired with a previous MIX_LockMixer call + * on the same thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_LockMixer + */ +extern SDL_DECLSPEC void SDLCALL MIX_UnlockMixer(MIX_Mixer *mixer); + +/** + * Load audio for playback from an SDL_IOStream. + * + * In normal usage, apps should load audio once, maybe at startup, then play + * it multiple times. + * + * When loading audio, it will be cached fully in RAM in its original data + * format. Each time it plays, the data will be decoded. For example, an MP3 + * will be stored in memory in MP3 format and be decompressed on the fly + * during playback. This is a tradeoff between i/o overhead and memory usage. + * + * If `predecode` is true, the data will be decompressed during load and + * stored as raw PCM data. This might dramatically increase loading time and + * memory usage, but there will be no need to decompress data during playback. + * + * (One could also use MIX_SetTrackIOStream() to bypass loading the data into + * RAM upfront at all, but this offers still different tradeoffs. The correct + * approach depends on the app's needs and employing different approaches in + * different situations can make sense.) + * + * MIX_Audio objects can be shared between mixers. This function takes a + * MIX_Mixer, to imply this is the most likely place it will be used and + * loading should try to match its audio format, but the resulting audio can + * be used elsewhere. If `mixer` is NULL, SDL_mixer will set reasonable + * defaults. + * + * Once a MIX_Audio is created, it can be assigned to a MIX_Track with + * MIX_SetTrackAudio(), or played without any management with MIX_PlayAudio(). + * + * When done with a MIX_Audio, it can be freed with MIX_DestroyAudio(). + * + * This function loads data from an SDL_IOStream. There is also a version that + * loads from a path on the filesystem (MIX_LoadAudio()), and one that accepts + * properties for ultimate control (MIX_LoadAudioWithProperties()). + * + * The SDL_IOStream provided must be able to seek, or loading will fail. If + * the stream can't seek (data is coming from an HTTP connection, etc), + * consider caching the data to memory or disk first and creating a new stream + * to read from there. + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param io the SDL_IOStream to load data from. + * \param predecode if true, data will be fully uncompressed before returning. + * \param closeio true if SDL_mixer should close `io` before returning + * (success or failure). + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadAudio + * \sa MIX_LoadAudioWithProperties + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadAudio_IO(MIX_Mixer *mixer, SDL_IOStream *io, bool predecode, bool closeio); + +/** + * Load audio for playback from a file. + * + * This is equivalent to calling: + * + * ```c + * MIX_LoadAudio_IO(mixer, SDL_IOFromFile(path, "rb"), predecode, true); + * ``` + * + * This function loads data from a path on the filesystem. There is also a + * version that loads from an SDL_IOStream (MIX_LoadAudio_IO()), and one that + * accepts properties for ultimate control (MIX_LoadAudioWithProperties()). + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param path the path on the filesystem to load data from. + * \param predecode if true, data will be fully uncompressed before returning. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadAudio_IO + * \sa MIX_LoadAudioWithProperties + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadAudio(MIX_Mixer *mixer, const char *path, bool predecode); + +/** + * Load audio for playback from a memory buffer without making a copy. + * + * When loading audio through most other LoadAudio functions, the data will be + * cached fully in RAM in its original data format, for decoding on-demand. + * This function does most of the same work as those functions, but instead + * uses a buffer of memory provided by the app that it does not make a copy + * of. + * + * This buffer must live for the entire time the returned MIX_Audio lives, as + * the mixer will access the buffer whenever it needs to mix more data. + * + * This function is meant to maximize efficiency: if the data is already in + * memory and can remain there, don't copy it. This data can be in any + * supported audio file format (WAV, MP3, etc); it will be decoded on the fly + * while mixing. Unlike MIX_LoadAudio(), there is no `predecode` option + * offered here, as this is meant to optimize for data that's already in + * memory and intends to exist there for significant time; since predecoding + * would only need the file format data once, upfront, one could simply wrap + * it in SDL_CreateIOFromConstMem() and pass that to MIX_LoadAudio_IO(). + * + * MIX_Audio objects can be shared between multiple mixers. The `mixer` + * parameter just suggests the most likely mixer to use this audio, in case + * some optimization might be applied, but this is not required, and a NULL + * mixer may be specified. + * + * If `free_when_done` is true, SDL_mixer will call `SDL_free(data)` when the + * returned MIX_Audio is eventually destroyed. This can be useful when the + * data is not static, but rather loaded elsewhere for this specific MIX_Audio + * and simply wants to avoid the extra copy. + * + * As audio format information is obtained from the file format metadata, this + * isn't useful for raw PCM data; in that case, use MIX_LoadRawAudioNoCopy() + * instead, which offers an SDL_AudioSpec. + * + * Once a MIX_Audio is created, it can be assigned to a MIX_Track with + * MIX_SetTrackAudio(), or played without any management with MIX_PlayAudio(). + * + * When done with a MIX_Audio, it can be freed with MIX_DestroyAudio(). + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param data the buffer where the audio data lives. + * \param datalen the size, in bytes, of the buffer. + * \param free_when_done if true, `data` will be given to SDL_free() when the + * MIX_Audio is destroyed. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadRawAudioNoCopy + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadAudioNoCopy(MIX_Mixer *mixer, const void *data, size_t datalen, bool free_when_done); + +/** + * Load audio for playback through a collection of properties. + * + * Please see MIX_LoadAudio_IO() for a description of what the various + * LoadAudio functions do. This function uses properties to dictate how it + * operates, and exposes functionality the other functions don't provide. + * + * SDL_PropertiesID are discussed in + * [SDL's documentation](https://wiki.libsdl.org/SDL3/CategoryProperties) + * . + * + * These are the supported properties: + * + * - `MIX_PROP_AUDIO_LOAD_IOSTREAM_POINTER`: a pointer to an SDL_IOStream to + * be used to load audio data. Required. This stream must be able to seek! + * - `MIX_PROP_AUDIO_LOAD_CLOSEIO_BOOLEAN`: true if SDL_mixer should close the + * SDL_IOStream before returning (success or failure). + * - `MIX_PROP_AUDIO_LOAD_PREDECODE_BOOLEAN`: true if SDL_mixer should fully + * decode and decompress the data before returning. Otherwise it will be + * stored in its original state and decompressed on demand. + * - `MIX_PROP_AUDIO_LOAD_PREFERRED_MIXER_POINTER`: a pointer to a MIX_Mixer, + * in case steps can be made to match its format when decoding. Optional. + * - `MIX_PROP_AUDIO_LOAD_SKIP_METADATA_TAGS_BOOLEAN`: true to skip parsing + * metadata tags, like ID3 and APE tags. This can be used to speed up + * loading _if the data definitely doesn't have these tags_. Some decoders + * will fail if these tags are present when this property is true. + * - `MIX_PROP_AUDIO_DECODER_STRING`: the name of the decoder to use for this + * data. Optional. If not specified, SDL_mixer will examine the data and + * choose the best decoder. These names are the same returned from + * MIX_GetAudioDecoder(). + * + * Specific decoders might accept additional custom properties, such as where + * to find soundfonts for MIDI playback, etc. + * + * \param props a set of properties on how to load audio. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadAudio + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadAudioWithProperties(SDL_PropertiesID props); + +#define MIX_PROP_AUDIO_LOAD_IOSTREAM_POINTER "SDL_mixer.audio.load.iostream" +#define MIX_PROP_AUDIO_LOAD_CLOSEIO_BOOLEAN "SDL_mixer.audio.load.closeio" +#define MIX_PROP_AUDIO_LOAD_PREDECODE_BOOLEAN "SDL_mixer.audio.load.predecode" +#define MIX_PROP_AUDIO_LOAD_PREFERRED_MIXER_POINTER "SDL_mixer.audio.load.preferred_mixer" +#define MIX_PROP_AUDIO_LOAD_SKIP_METADATA_TAGS_BOOLEAN "SDL_mixer.audio.load.skip_metadata_tags" +#define MIX_PROP_AUDIO_DECODER_STRING "SDL_mixer.audio.decoder" + +/** + * Load raw PCM data from an SDL_IOStream. + * + * There are other options for _streaming_ raw PCM: an SDL_AudioStream can be + * connected to a track, as can an SDL_IOStream, and will read from those + * sources on-demand when it is time to mix the audio. This function is useful + * for loading static audio data that is meant to be played multiple times. + * + * This function will load the raw data in its entirety and cache it in RAM. + * + * MIX_Audio objects can be shared between multiple mixers. The `mixer` + * parameter just suggests the most likely mixer to use this audio, in case + * some optimization might be applied, but this is not required, and a NULL + * mixer may be specified. + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param io the SDL_IOStream to load data from. + * \param spec what format the raw data is in. + * \param closeio true if SDL_mixer should close `io` before returning + * (success or failure). + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadRawAudio + * \sa MIX_LoadRawAudioNoCopy + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadRawAudio_IO(MIX_Mixer *mixer, SDL_IOStream *io, const SDL_AudioSpec *spec, bool closeio); + +/** + * Load raw PCM data from a memory buffer. + * + * There are other options for _streaming_ raw PCM: an SDL_AudioStream can be + * connected to a track, as can an SDL_IOStream, and will read from those + * sources on-demand when it is time to mix the audio. This function is useful + * for loading static audio data that is meant to be played multiple times. + * + * This function will load the raw data in its entirety and cache it in RAM, + * allocating a copy. If the original data will outlive the created MIX_Audio, + * you can use MIX_LoadRawAudioNoCopy() to avoid extra allocations and copies. + * + * MIX_Audio objects can be shared between multiple mixers. The `mixer` + * parameter just suggests the most likely mixer to use this audio, in case + * some optimization might be applied, but this is not required, and a NULL + * mixer may be specified. + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param data the raw PCM data to load. + * \param datalen the size, in bytes, of the raw PCM data. + * \param spec what format the raw data is in. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadRawAudio_IO + * \sa MIX_LoadRawAudioNoCopy + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadRawAudio(MIX_Mixer *mixer, const void *data, size_t datalen, const SDL_AudioSpec *spec); + +/** + * Load raw PCM data from a memory buffer without making a copy. + * + * This buffer must live for the entire time the returned MIX_Audio lives, as + * the mixer will access the buffer whenever it needs to mix more data. + * + * This function is meant to maximize efficiency: if the data is already in + * memory and can remain there, don't copy it. But it can also lead to some + * interesting tricks, like changing the buffer's contents to alter multiple + * playing tracks at once. (But, of course, be careful when being too clever.) + * + * MIX_Audio objects can be shared between multiple mixers. The `mixer` + * parameter just suggests the most likely mixer to use this audio, in case + * some optimization might be applied, but this is not required, and a NULL + * mixer may be specified. + * + * If `free_when_done` is true, SDL_mixer will call `SDL_free(data)` when the + * returned MIX_Audio is eventually destroyed. This can be useful when the + * data is not static, but rather composed dynamically for this specific + * MIX_Audio and simply wants to avoid the extra copy. + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param data the buffer where the raw PCM data lives. + * \param datalen the size, in bytes, of the buffer. + * \param spec what format the raw data is in. + * \param free_when_done if true, `data` will be given to SDL_free() when the + * MIX_Audio is destroyed. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadRawAudio + * \sa MIX_LoadRawAudio_IO + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_LoadRawAudioNoCopy(MIX_Mixer *mixer, const void *data, size_t datalen, const SDL_AudioSpec *spec, bool free_when_done); + +/** + * Create a MIX_Audio that generates a sinewave. + * + * This is useful just to have _something_ to play, perhaps for testing or + * debugging purposes. + * + * You specify its frequency in Hz (determines the pitch of the sinewave's + * audio) and amplitude (determines the volume of the sinewave: 1.0f is very + * loud, 0.0f is silent). + * + * A number of milliseconds of audio to generate can be specified. Specifying + * a value less than zero will generate infinite audio (when assigned to a + * MIX_Track, the sinewave will play forever). + * + * MIX_Audio objects can be shared between multiple mixers. The `mixer` + * parameter just suggests the most likely mixer to use this audio, in case + * some optimization might be applied, but this is not required, and a NULL + * mixer may be specified. + * + * \param mixer a mixer this audio is intended to be used with. May be NULL. + * \param hz the sinewave's frequency in Hz. + * \param amplitude the sinewave's amplitude from 0.0f to 1.0f. + * \param ms the maximum number of milliseconds of audio to generate, or less + * than zero to generate infinite audio. + * \returns an audio object that can be used to make sound on a mixer, or NULL + * on failure; call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyAudio + * \sa MIX_SetTrackAudio + * \sa MIX_LoadAudio_IO + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_CreateSineWaveAudio(MIX_Mixer *mixer, int hz, float amplitude, Sint64 ms); + + +/** + * Get the properties associated with a MIX_Audio. + * + * SDL_mixer offers some properties of its own, but this can also be a + * convenient place to store app-specific data. + * + * A SDL_PropertiesID is created the first time this function is called for a + * given MIX_Audio, if necessary. + * + * The following read-only properties are provided by SDL_mixer: + * + * - `MIX_PROP_METADATA_TITLE_STRING`: the audio's title ("Smells Like Teen + * Spirit"). + * - `MIX_PROP_METADATA_ARTIST_STRING`: the audio's artist name ("Nirvana"). + * - `MIX_PROP_METADATA_ALBUM_STRING`: the audio's album name ("Nevermind"). + * - `MIX_PROP_METADATA_COPYRIGHT_STRING`: the audio's copyright info + * ("Copyright (c) 1991") + * - `MIX_PROP_METADATA_TRACK_NUMBER`: the audio's track number on the album + * (1) + * - `MIX_PROP_METADATA_TOTAL_TRACKS_NUMBER`: the total tracks on the album + * (13) + * - `MIX_PROP_METADATA_YEAR_NUMBER`: the year the audio was released (1991) + * - `MIX_PROP_METADATA_DURATION_FRAMES_NUMBER`: The sample frames worth of + * PCM data that comprise this audio. It might be off by a little if the + * decoder only knows the duration as a unit of time. + * - `MIX_PROP_METADATA_DURATION_INFINITE_BOOLEAN`: if true, audio never runs + * out of sound to generate. This isn't necessarily always known to + * SDL_mixer, though. + * + * Other properties, documented with MIX_LoadAudioWithProperties(), may also + * be present. + * + * Note that the metadata properties are whatever SDL_mixer finds in things + * like ID3 tags, and they often have very little standardized formatting, may + * be missing, and can be completely wrong if the original data is + * untrustworthy (like an MP3 from a P2P file sharing service). + * + * \param audio the audio to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL MIX_GetAudioProperties(MIX_Audio *audio); + +#define MIX_PROP_METADATA_TITLE_STRING "SDL_mixer.metadata.title" +#define MIX_PROP_METADATA_ARTIST_STRING "SDL_mixer.metadata.artist" +#define MIX_PROP_METADATA_ALBUM_STRING "SDL_mixer.metadata.album" +#define MIX_PROP_METADATA_COPYRIGHT_STRING "SDL_mixer.metadata.copyright" +#define MIX_PROP_METADATA_TRACK_NUMBER "SDL_mixer.metadata.track" +#define MIX_PROP_METADATA_TOTAL_TRACKS_NUMBER "SDL_mixer.metadata.total_tracks" +#define MIX_PROP_METADATA_YEAR_NUMBER "SDL_mixer.metadata.year" +#define MIX_PROP_METADATA_DURATION_FRAMES_NUMBER "SDL_mixer.metadata.duration_frames" +#define MIX_PROP_METADATA_DURATION_INFINITE_BOOLEAN "SDL_mixer.metadata.duration_infinite" + + +/** + * Get the length of a MIX_Audio's playback in sample frames. + * + * This information is also available via the + * MIX_PROP_METADATA_DURATION_FRAMES_NUMBER property, but it's common enough + * to provide a simple accessor function. + * + * This reports the length of the data in _sample frames_, so sample-perfect + * mixing can be possible. Sample frames are only meaningful as a measure of + * time if the sample rate (frequency) is also known. To convert from sample + * frames to milliseconds, use MIX_AudioFramesToMS(). + * + * Not all audio file formats can report the complete length of the data they + * will produce through decoding: some can't calculate it, some might produce + * infinite audio. + * + * Also, some file formats can only report duration as a unit of time, which + * means SDL_mixer might have to estimate sample frames from that information. + * With less precision, the reported duration might be off by a few sample + * frames in either direction. + * + * This will return a value >= 0 if a duration is known. It might also return + * MIX_DURATION_UNKNOWN or MIX_DURATION_INFINITE. + * + * \param audio the audio to query. + * \returns the length of the audio in sample frames, or MIX_DURATION_UNKNOWN + * or MIX_DURATION_INFINITE. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_GetAudioDuration(MIX_Audio *audio); + +#define MIX_DURATION_UNKNOWN -1 +#define MIX_DURATION_INFINITE -2 + + +/** + * Query the initial audio format of a MIX_Audio. + * + * Note that some audio files can change format in the middle; some explicitly + * support this, but a more common example is two MP3 files concatenated + * together. In many cases, SDL_mixer will correctly handle these sort of + * files, but this function will only report the initial format a file uses. + * + * \param audio the audio to query. + * \param spec on success, audio format details will be stored here. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_GetAudioFormat(MIX_Audio *audio, SDL_AudioSpec *spec); + +/** + * Destroy the specified audio. + * + * MIX_Audio is reference-counted internally, so this function only unrefs it. + * If doing so causes the reference count to drop to zero, the MIX_Audio will + * be deallocated. This allows the system to safely operate if the audio is + * still assigned to a MIX_Track at the time of destruction. The actual + * destroying will happen when the track stops using it. + * + * But from the caller's perspective, once this function is called, it should + * assume the `audio` pointer has become invalid. + * + * Destroying a NULL MIX_Audio is a legal no-op. + * + * \param audio the audio to destroy. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC void SDLCALL MIX_DestroyAudio(MIX_Audio *audio); + +/** + * Create a new track on a mixer. + * + * A track provides a single source of audio. All currently-playing tracks + * will be processed and mixed together to form the final output from the + * mixer. + * + * There are no limits to the number of tracks one may create, beyond running + * out of memory, but in normal practice there are a small number of tracks + * that are reused between all loaded audio as appropriate. + * + * Tracks are unique to a specific MIX_Mixer and can't be transferred between + * them. + * + * \param mixer the mixer on which to create this track. + * \returns a new MIX_Track on success, NULL on error; call SDL_GetError() for + * more informations. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyTrack + */ +extern SDL_DECLSPEC MIX_Track * SDLCALL MIX_CreateTrack(MIX_Mixer *mixer); + +/** + * Destroy the specified track. + * + * If the track is currently playing, it will be stopped immediately, without + * any fadeout. If there is a callback set through + * MIX_SetTrackStoppedCallback(), it will _not_ be called. + * + * If the mixer is currently mixing in another thread, this will block until + * it finishes. + * + * Destroying a NULL MIX_Track is a legal no-op. + * + * \param track the track to destroy. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC void SDLCALL MIX_DestroyTrack(MIX_Track *track); + +/** + * Get the properties associated with a track. + * + * Currently SDL_mixer assigns no properties of its own to a track, but this + * can be a convenient place to store app-specific data. + * + * A SDL_PropertiesID is created the first time this function is called for a + * given track. + * + * \param track the track to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL MIX_GetTrackProperties(MIX_Track *track); + +/** + * Get the MIX_Mixer that owns a MIX_Track. + * + * This is the mixer pointer that was passed to MIX_CreateTrack(). + * + * \param track the track to query. + * \returns the mixer associated with the track, or NULL on error; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC MIX_Mixer * SDLCALL MIX_GetTrackMixer(MIX_Track *track); + +/** + * Set a MIX_Track's input to a MIX_Audio. + * + * A MIX_Audio is audio data stored in RAM (possibly still in a compressed + * form). One MIX_Audio can be assigned to multiple tracks at once. + * + * Once a track has a valid input, it can start mixing sound by calling + * MIX_PlayTrack(), or possibly MIX_PlayTag(). + * + * Calling this function with a NULL audio input is legal, and removes any + * input from the track. If the track was currently playing, the next time the + * mixer runs, it'll notice this and mark the track as stopped, calling any + * assigned MIX_TrackStoppedCallback. + * + * It is legal to change the input of a track while it's playing, however some + * states, like loop points, may cease to make sense with the new audio. In + * such a case, one can call MIX_PlayTrack again to adjust parameters. + * + * The track will hold a reference to the provided MIX_Audio, so it is safe to + * call MIX_DestroyAudio() on it while the track is still using it. The track + * will drop its reference (and possibly free the resources) once it is no + * longer using the MIX_Audio. + * + * \param track the track on which to set a new audio input. + * \param audio the new audio input to set. May be NULL. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackAudio(MIX_Track *track, MIX_Audio *audio); + +/** + * Set a MIX_Track's input to an SDL_AudioStream. + * + * Using an audio stream allows the application to generate any type of audio, + * in any format, possibly procedurally or on-demand, and mix in with all + * other tracks. + * + * When a track uses an audio stream, it will call SDL_GetAudioStreamData as + * it needs more audio to mix. The app can either buffer data to the stream + * ahead of time, or set a callback on the stream to provide data as needed. + * Please refer to SDL's documentation for details. + * + * A given audio stream may only be assigned to a single track at a time; + * duplicate assignments won't return an error, but assigning a stream to + * multiple tracks will cause each track to read from the stream arbitrarily, + * causing confusion and incorrect mixing. + * + * Once a track has a valid input, it can start mixing sound by calling + * MIX_PlayTrack(), or possibly MIX_PlayTag(). + * + * Calling this function with a NULL audio stream is legal, and removes any + * input from the track. If the track was currently playing, the next time the + * mixer runs, it'll notice this and mark the track as stopped, calling any + * assigned MIX_TrackStoppedCallback. + * + * It is legal to change the input of a track while it's playing, however some + * states, like loop points, may cease to make sense with the new audio. In + * such a case, one can call MIX_PlayTrack again to adjust parameters. + * + * The provided audio stream must remain valid until the track no longer needs + * it (either by changing the track's input or destroying the track). + * + * \param track the track on which to set a new audio input. + * \param stream the audio stream to use as the track's input. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackAudioStream(MIX_Track *track, SDL_AudioStream *stream); + +/** + * Set a MIX_Track's input to an SDL_IOStream. + * + * This is not the recommended way to set a track's input, but this can be + * useful for a very specific scenario: a large file, to be played once, that + * must be read from disk in small chunks as needed. In most cases, however, + * it is preferable to create a MIX_Audio ahead of time and use + * MIX_SetTrackAudio() instead. + * + * The stream supplied here should provide an audio file in a supported + * format. SDL_mixer will parse it during this call to make sure it's valid, + * and then will read file data from the stream as it needs to decode more + * during mixing. + * + * The stream must be able to seek through the complete set of data, or this + * function will fail. + * + * A given IOStream may only be assigned to a single track at a time; + * duplicate assignments won't return an error, but assigning a stream to + * multiple tracks will cause each track to read from the stream arbitrarily, + * causing confusion, incorrect mixing, or failure to decode. + * + * Once a track has a valid input, it can start mixing sound by calling + * MIX_PlayTrack(), or possibly MIX_PlayTag(). + * + * Calling this function with a NULL stream is legal, and removes any input + * from the track. If the track was currently playing, the next time the mixer + * runs, it'll notice this and mark the track as stopped, calling any assigned + * MIX_TrackStoppedCallback. + * + * It is legal to change the input of a track while it's playing, however some + * states, like loop points, may cease to make sense with the new audio. In + * such a case, one can call MIX_PlayTrack again to adjust parameters. + * + * The provided stream must remain valid until the track no longer needs it + * (either by changing the track's input or destroying the track). + * + * \param track the track on which to set a new audio input. + * \param io the new i/o stream to use as the track's input. + * \param closeio if true, close the stream when done with it. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackRawIOStream + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackIOStream(MIX_Track *track, SDL_IOStream *io, bool closeio); + +/** + * Set a MIX_Track's input to an SDL_IOStream providing raw PCM data. + * + * This is not the recommended way to set a track's input, but this can be + * useful for a very specific scenario: a large file, to be played once, that + * must be read from disk in small chunks as needed. In most cases, however, + * it is preferable to create a MIX_Audio ahead of time and use + * MIX_SetTrackAudio() instead. + * + * Also, an MIX_SetTrackAudioStream() can _also_ provide raw PCM audio to a + * track, via an SDL_AudioStream, which might be preferable unless the data is + * already coming directly from an SDL_IOStream. + * + * The stream supplied here should provide an audio in raw PCM format. + * + * A given IOStream may only be assigned to a single track at a time; + * duplicate assignments won't return an error, but assigning a stream to + * multiple tracks will cause each track to read from the stream arbitrarily, + * causing confusion and incorrect mixing. + * + * Once a track has a valid input, it can start mixing sound by calling + * MIX_PlayTrack(), or possibly MIX_PlayTag(). + * + * Calling this function with a NULL stream is legal, and removes any input + * from the track. If the track was currently playing, the next time the mixer + * runs, it'll notice this and mark the track as stopped, calling any assigned + * MIX_TrackStoppedCallback. + * + * It is legal to change the input of a track while it's playing, however some + * states, like loop points, may cease to make sense with the new audio. In + * such a case, one can call MIX_PlayTrack again to adjust parameters. + * + * The provided stream must remain valid until the track no longer needs it + * (either by changing the track's input or destroying the track). + * + * \param track the track on which to set a new audio input. + * \param io the new i/o stream to use as the track's input. + * \param spec the format of the PCM data that the SDL_IOStream will provide. + * \param closeio if true, close the stream when done with it. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackAudioStream + * \sa MIX_SetTrackIOStream + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackRawIOStream(MIX_Track *track, SDL_IOStream *io, const SDL_AudioSpec *spec, bool closeio); + + +/** + * Assign an arbitrary tag to a track. + * + * A tag can be any valid C string in UTF-8 encoding. It can be useful to + * group tracks in various ways. For example, everything in-game might be + * marked as "game", so when the user brings up the settings menu, the app can + * pause all tracks involved in gameplay at once, but keep background music + * and menu sound effects running. + * + * A track can have as many tags as desired, until the machine runs out of + * memory. + * + * It's legal to add the same tag to a track more than once; the extra + * attempts will report success but not change anything. + * + * Tags can later be removed with MIX_UntagTrack(). + * + * \param track the track to add a tag to. + * \param tag the tag to add. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_UntagTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_TagTrack(MIX_Track *track, const char *tag); + +/** + * Remove an arbitrary tag from a track. + * + * A tag can be any valid C string in UTF-8 encoding. It can be useful to + * group tracks in various ways. For example, everything in-game might be + * marked as "game", so when the user brings up the settings menu, the app can + * pause all tracks involved in gameplay at once, but keep background music + * and menu sound effects running. + * + * It's legal to remove a tag that the track doesn't have; this function + * doesn't report errors, so this simply does nothing. + * + * Specifying a NULL tag will remove all tags on a track. + * + * \param track the track from which to remove a tag. + * \param tag the tag to remove, or NULL to remove all current tags. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TagTrack + */ +extern SDL_DECLSPEC void SDLCALL MIX_UntagTrack(MIX_Track *track, const char *tag); + +/** + * Get the tags currently associated with a track. + * + * Tags are not provided in any guaranteed order. + * + * \param track the track to query. + * \param count a pointer filled in with the number of tags returned, can be + * NULL. + * \returns an array of the tags, NULL-terminated, or NULL on failure; call + * SDL_GetError() for more information. This is a single allocation + * that should be freed with SDL_free() when it is no longer needed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC char ** SDLCALL MIX_GetTrackTags(MIX_Track *track, int *count); + +/** + * Get all tracks with a specific tag. + * + * Tracks are not provided in any guaranteed order. + * + * \param mixer the mixer to query. + * \param tag the tag to search. + * \param count a pointer filled in with the number of tracks returned, can be + * NULL. + * \returns an array of the tracks, NULL-terminated, or NULL on failure; call + * SDL_GetError() for more information. The returned pointer should + * be freed with SDL_free() when it is no longer needed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC MIX_Track ** SDLCALL MIX_GetTaggedTracks(MIX_Mixer *mixer, const char *tag, int *count); + +/** + * Seek a playing track to a new position in its input. + * + * (Not to be confused with MIX_SetTrack3DPosition(), which is positioning of + * the track in 3D space, not the playback position of its audio data.) + * + * On a playing track, the next time the mixer runs, it will start mixing from + * the new position. + * + * Position is defined in _sample frames_ of decoded audio, not units of time, + * so that sample-perfect mixing can be achieved. To instead operate in units + * of time, use MIX_TrackMSToFrames() to get the approximate sample frames for + * a given tick. + * + * This function requires an input that can seek (so it can not be used if the + * input was set with MIX_SetTrackAudioStream()), and a audio file format that + * allows seeking. SDL_mixer's decoders for some file formats do not offer + * seeking, or can only seek to times, not exact sample frames, in which case + * the final position may be off by some amount of sample frames. Please check + * your audio data and file bug reports if appropriate. + * + * It's legal to call this function on a track that is stopped, but a future + * call to MIX_PlayTrack() will reset the start position anyhow. Paused tracks + * will resume at the new input position. + * + * \param track the track to change. + * \param frames the sample frame position to seek to. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackPlaybackPosition + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackPlaybackPosition(MIX_Track *track, Sint64 frames); + +/** + * Get the current input position of a playing track. + * + * (Not to be confused with MIX_GetTrack3DPosition(), which is positioning of + * the track in 3D space, not the playback position of its audio data.) + * + * Position is defined in _sample frames_ of decoded audio, not units of time, + * so that sample-perfect mixing can be achieved. To instead operate in units + * of time, use MIX_TrackFramesToMS() to convert the return value to + * milliseconds. + * + * Stopped and paused tracks will report the position when they halted. + * Playing tracks will report the current position, which will change over + * time. + * + * \param track the track to change. + * \returns the track's current sample frame position, or -1 on error; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackPlaybackPosition + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_GetTrackPlaybackPosition(MIX_Track *track); + +/** + * Query whether a given track is fading. + * + * This specifically checks if the track is _not stopped_ (paused or playing), + * and it is fading in or out, and returns the number of frames remaining in + * the fade. + * + * If fading out, the returned value will be negative. When fading in, the + * returned value will be positive. If not fading, this function returns zero. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns 0, but there is no mechanism to distinguish errors from tracks that + * aren't fading. + * + * \param track the track to query. + * \returns less than 0 if the track is fading out, greater than 0 if fading + * in, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_GetTrackFadeFrames(MIX_Track *track); + +/** + * Query how many loops remain for a given track. + * + * This returns the number of loops still pending; if a track will eventually + * complete and loop to play again one more time, this will return 1. If a + * track _was_ looping but is on its final iteration of the loop (will stop + * when this iteration completes), this will return zero. + * + * A track that is looping infinitely will return -1. This value does not + * report an error in this case. + * + * A track that is stopped (not playing and not paused) will have zero loops + * remaining. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns zero, but there is no mechanism to distinguish errors from + * non-looping tracks. + * + * \param track the track to query. + * \returns the number of pending loops, zero if not looping, and -1 if + * looping infinitely. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL MIX_GetTrackLoops(MIX_Track *track); + +/** + * Change the number of times a currently-playing track will loop. + * + * This replaces any previously-set remaining loops. A value of 1 will loop to + * the start of playback one time. Zero will not loop at all. A value of -1 + * requests infinite loops. If the input is not seekable and `num_loops` isn't + * zero, this function will report success but the track will stop at the + * point it should loop. + * + * The new loop count replaces any previous state, even if the track has + * already looped. + * + * This has no effect on a track that is stopped, or rather, starting a + * stopped track later will set a new loop count, replacing this value. + * Stopped tracks can specify a loop count while starting via + * MIX_PROP_PLAY_LOOPS_NUMBER. This function is intended to alter that count + * in the middle of playback. + * + * \param track the track to configure. + * \param num_loops new number of times to loop. Zero to disable looping, -1 + * to loop infinitely. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackLoops + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackLoops(MIX_Track *track, int num_loops); + +/** + * Query the MIX_Audio assigned to a track. + * + * This returns the MIX_Audio object currently assigned to `track` through a + * call to MIX_SetTrackAudio(). If there is none assigned, or the track has an + * input that isn't a MIX_Audio (such as an SDL_AudioStream or SDL_IOStream), + * this will return NULL. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns NULL, but there is no mechanism to distinguish errors from tracks + * without a valid input. + * + * \param track the track to query. + * \returns a MIX_Audio if available, NULL if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackAudioStream + */ +extern SDL_DECLSPEC MIX_Audio * SDLCALL MIX_GetTrackAudio(MIX_Track *track); + +/** + * Query the SDL_AudioStream assigned to a track. + * + * This returns the SDL_AudioStream object currently assigned to `track` + * through a call to MIX_SetTrackAudioStream(). If there is none assigned, or + * the track has an input that isn't an SDL_AudioStream (such as a MIX_Audio + * or SDL_IOStream), this will return NULL. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns NULL, but there is no mechanism to distinguish errors from tracks + * without a valid input. + * + * \param track the track to query. + * \returns an SDL_AudioStream if available, NULL if not. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackAudio + */ +extern SDL_DECLSPEC SDL_AudioStream * SDLCALL MIX_GetTrackAudioStream(MIX_Track *track); + +/** + * Return the number of sample frames remaining to be mixed in a track. + * + * If the track is playing or paused, and its total duration is known, this + * will report how much audio is left to mix. If the track is playing, future + * calls to this function will report different values. + * + * Remaining audio is defined in _sample frames_ of decoded audio, not units + * of time, so that sample-perfect mixing can be achieved. To instead operate + * in units of time, use MIX_TrackFramesToMS() to convert the return value to + * milliseconds. + * + * This function does not take into account fade-outs or looping, just the + * current mixing position vs the duration of the track. + * + * If the duration of the track isn't known, or `track` is NULL, this function + * returns -1. A stopped track reports 0. + * + * \param track the track to query. + * \returns the total sample frames still to be mixed, or -1 if unknown. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_GetTrackRemaining(MIX_Track *track); + +/** + * Convert milliseconds to sample frames for a track's current format. + * + * This calculates time based on the track's current input format, which can + * change when its input does, and also if that input changes formats + * mid-stream (for example, if decoding a file that is two MP3s concatenated + * together). + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns -1. If the track has no input, this returns -1. If `ms` is < 0, + * this returns -1. + * + * \param track the track to query. + * \param ms the milliseconds to convert to track-specific sample frames. + * \returns Converted number of sample frames, or -1 for errors/no input; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TrackFramesToMS + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_TrackMSToFrames(MIX_Track *track, Sint64 ms); + +/** + * Convert sample frames for a track's current format to milliseconds. + * + * This calculates time based on the track's current input format, which can + * change when its input does, and also if that input changes formats + * mid-stream (for example, if decoding a file that is two MP3s concatenated + * together). + * + * Sample frames are more precise than milliseconds, so out of necessity, this + * function will approximate by rounding down to the closest full millisecond. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns -1. If the track has no input, this returns -1. If `frames` is < 0, + * this returns -1. + * + * \param track the track to query. + * \param frames the track-specific sample frames to convert to milliseconds. + * \returns Converted number of milliseconds, or -1 for errors/no input; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TrackMSToFrames + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_TrackFramesToMS(MIX_Track *track, Sint64 frames); + +/** + * Convert milliseconds to sample frames for a MIX_Audio's format. + * + * This calculates time based on the audio's initial format, even if the + * format would change mid-stream. + * + * If `ms` is < 0, this returns -1. + * + * \param audio the audio to query. + * \param ms the milliseconds to convert to audio-specific sample frames. + * \returns Converted number of sample frames, or -1 for errors/no input; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_AudioFramesToMS + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_AudioMSToFrames(MIX_Audio *audio, Sint64 ms); + +/** + * Convert sample frames for a MIX_Audio's format to milliseconds. + * + * This calculates time based on the audio's initial format, even if the + * format would change mid-stream. + * + * Sample frames are more precise than milliseconds, so out of necessity, this + * function will approximate by rounding down to the closest full millisecond. + * + * If `frames` is < 0, this returns -1. + * + * \param audio the audio to query. + * \param frames the audio-specific sample frames to convert to milliseconds. + * \returns Converted number of milliseconds, or -1 for errors/no input; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_AudioMSToFrames + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_AudioFramesToMS(MIX_Audio *audio, Sint64 frames); + +/** + * Convert milliseconds to sample frames at a specific sample rate. + * + * If `sample_rate` is <= 0, this returns -1. If `ms` is < 0, this returns -1. + * + * \param sample_rate the sample rate to use for conversion. + * \param ms the milliseconds to convert to rate-specific sample frames. + * \returns Converted number of sample frames, or -1 for errors; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_FramesToMS + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_MSToFrames(int sample_rate, Sint64 ms); + +/** + * Convert sample frames, at a specific sample rate, to milliseconds. + * + * Sample frames are more precise than milliseconds, so out of necessity, this + * function will approximate by rounding down to the closest full millisecond. + * + * If `sample_rate` is <= 0, this returns -1. If `frames` is < 0, this returns + * -1. + * + * \param sample_rate the sample rate to use for conversion. + * \param frames the rate-specific sample frames to convert to milliseconds. + * \returns Converted number of milliseconds, or -1 for errors; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_MSToFrames + */ +extern SDL_DECLSPEC Sint64 SDLCALL MIX_FramesToMS(int sample_rate, Sint64 frames); + + +/* operations that deal with actual mixing/playback... */ + +/** + * Start (or restart) mixing a track for playback. + * + * The track will use whatever input was last assigned to it when playing; an + * input must be assigned to this track or this function will fail. Inputs are + * assigned with calls to MIX_SetTrackAudio(), MIX_SetTrackAudioStream(), or + * MIX_SetTrackIOStream(). + * + * If the track is already playing, or paused, this will restart the track + * with the newly-specified parameters. + * + * As there are several parameters, and more may be added in the future, they + * are specified with an SDL_PropertiesID. The parameters have reasonable + * defaults, and specifying a 0 for `options` will choose defaults for + * everything. + * + * SDL_PropertiesID are discussed in + * [SDL's documentation](https://wiki.libsdl.org/SDL3/CategoryProperties) + * . + * + * These are the supported properties: + * + * - `MIX_PROP_PLAY_LOOPS_NUMBER`: The number of times to loop the track when + * it reaches the end. A value of 1 will loop to the start one time. Zero + * will not loop at all. A value of -1 requests infinite loops. If the input + * is not seekable and this value isn't zero, this function will report + * success but the track will stop at the point it should loop. Default 0. + * - `MIX_PROP_PLAY_MAX_FRAME_NUMBER`: Mix at most to this sample frame + * position in the track. This will be treated as if the input reach EOF at + * this point in the audio file. If -1, mix all available audio without a + * limit. Default -1. + * - `MIX_PROP_PLAY_MAX_MILLISECONDS_NUMBER`: The same as using the + * MIX_PROP_PLAY_MAX_FRAME_NUMBER property, but the value is specified in + * milliseconds instead of sample frames. If both properties are specified, + * the sample frames value is favored. Default -1. + * - `MIX_PROP_PLAY_START_FRAME_NUMBER`: Start mixing from this sample frame + * position in the track's input. A value <= 0 will begin from the start of + * the track's input. If the input is not seekable and this value is > 0, + * this function will report failure. Default 0. + * - `MIX_PROP_PLAY_START_MILLISECOND_NUMBER`: The same as using the + * MIX_PROP_PLAY_START_FRAME_NUMBER property, but the value is specified in + * milliseconds instead of sample frames. If both properties are specified, + * the sample frames value is favored. Default 0. + * - `MIX_PROP_PLAY_LOOP_START_FRAME_NUMBER`: If the track is looping, this is + * the sample frame position that the track will loop back to; this lets one + * play an intro at the start of a track on the first iteration, but have a + * loop point somewhere in the middle thereafter. A value <= 0 will begin + * the loop from the start of the track's input. Default 0. + * - `MIX_PROP_PLAY_LOOP_START_MILLISECOND_NUMBER`: The same as using the + * MIX_PROP_PLAY_LOOP_START_FRAME_NUMBER property, but the value is + * specified in milliseconds instead of sample frames. If both properties + * are specified, the sample frames value is favored. Default 0. + * - `MIX_PROP_PLAY_FADE_IN_FRAMES_NUMBER`: The number of sample frames over + * which to fade in the newly-started track. The track will begin mixing + * silence and reach full volume smoothly over this many sample frames. If + * the track loops before the fade-in is complete, it will continue to fade + * correctly from the loop point. A value <= 0 will disable fade-in, so the + * track starts mixing at full volume. Default 0. + * - `MIX_PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER`: The same as using the + * MIX_PROP_PLAY_FADE_IN_FRAMES_NUMBER property, but the value is specified + * in milliseconds instead of sample frames. If both properties are + * specified, the sample frames value is favored. Default 0. + * - `MIX_PROP_PLAY_FADE_IN_START_GAIN_FLOAT`: If fading in, start fading from + * this volume level. 0.0f is silence and 1.0f is full volume, every in + * between is a linear change in gain. The specified value will be clamped + * between 0.0f and 1.0f. Default 0.0f. + * - `MIX_PROP_PLAY_APPEND_SILENCE_FRAMES_NUMBER`: At the end of mixing this + * track, after all loops are complete, append this many sample frames of + * silence as if it were part of the audio file. This allows for apps to + * implement effects in callbacks, like reverb, that need to generate + * samples past the end of the stream's audio, or perhaps introduce a delay + * before starting a new sound on the track without having to manage it + * directly. A value <= 0 generates no silence before stopping the track. + * Default 0. + * - `MIX_PROP_PLAY_APPEND_SILENCE_MILLISECONDS_NUMBER`: The same as using the + * MIX_PROP_PLAY_APPEND_SILENCE_FRAMES_NUMBER property, but the value is + * specified in milliseconds instead of sample frames. If both properties + * are specified, the sample frames value is favored. Default 0. + * - `MIX_PROP_PLAY_HALT_WHEN_EXHAUSTED_BOOLEAN`: If true, when input is + * completely consumed for the track, the mixer will mark the track as + * stopped (and call any appropriate MIX_TrackStoppedCallback, etc); to play + * more, the track will need to be restarted. If false, the track will just + * not contribute to the mix, but it will not be marked as stopped. There + * may be clever logic tricks this exposes generally, but this property is + * specifically useful when the track's input is an SDL_AudioStream assigned + * via MIX_SetTrackAudioStream(). Setting this property to true can be + * useful when pushing a complete piece of audio to the stream that has a + * definite ending, as the track will operate like any other audio was + * applied. Setting to false means as new data is added to the stream, the + * mixer will start using it as soon as possible, which is useful when audio + * should play immediately as it drips in: new VoIP packets, etc. Note that + * in this situation, if the audio runs out when needed, there _will_ be + * gaps in the mixed output, so try to buffer enough data to avoid this when + * possible. Note that a track is not consider exhausted until all its loops + * and appended silence have been mixed (and also, that loops don't mean + * anything when the input is an AudioStream). Default true. + * + * If this function fails, mixing of this track will not start (or restart, if + * it was already started). + * + * \param track the track to start (or restart) mixing. + * \param options a set of properties that control playback. May be zero. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTag + * \sa MIX_PlayAudio + * \sa MIX_StopTrack + * \sa MIX_PauseTrack + * \sa MIX_TrackPlaying + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PlayTrack(MIX_Track *track, SDL_PropertiesID options); + +#define MIX_PROP_PLAY_LOOPS_NUMBER "SDL_mixer.play.loops" +#define MIX_PROP_PLAY_MAX_FRAME_NUMBER "SDL_mixer.play.max_frame" +#define MIX_PROP_PLAY_MAX_MILLISECONDS_NUMBER "SDL_mixer.play.max_milliseconds" +#define MIX_PROP_PLAY_START_FRAME_NUMBER "SDL_mixer.play.start_frame" +#define MIX_PROP_PLAY_START_MILLISECOND_NUMBER "SDL_mixer.play.start_millisecond" +#define MIX_PROP_PLAY_LOOP_START_FRAME_NUMBER "SDL_mixer.play.loop_start_frame" +#define MIX_PROP_PLAY_LOOP_START_MILLISECOND_NUMBER "SDL_mixer.play.loop_start_millisecond" +#define MIX_PROP_PLAY_FADE_IN_FRAMES_NUMBER "SDL_mixer.play.fade_in_frames" +#define MIX_PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER "SDL_mixer.play.fade_in_milliseconds" +#define MIX_PROP_PLAY_FADE_IN_START_GAIN_FLOAT "SDL_mixer.play.fade_in_start_gain" +#define MIX_PROP_PLAY_APPEND_SILENCE_FRAMES_NUMBER "SDL_mixer.play.append_silence_frames" +#define MIX_PROP_PLAY_APPEND_SILENCE_MILLISECONDS_NUMBER "SDL_mixer.play.append_silence_milliseconds" +#define MIX_PROP_PLAY_HALT_WHEN_EXHAUSTED_BOOLEAN "SDL_mixer.play.halt_when_exhausted" + +/** + * Start (or restart) mixing all tracks with a specific tag for playback. + * + * This function follows all the same rules as MIX_PlayTrack(); please refer + * to its documentation for the details. Unlike that function, MIX_PlayTag() + * operates on multiple tracks at once that have the specified tag applied, + * via MIX_TagTrack(). + * + * If all of your tagged tracks have different sample rates, it would make + * sense to use the `*_MILLISECONDS_NUMBER` properties in your `options`, + * instead of `*_FRAMES_NUMBER`, and let SDL_mixer figure out how to apply it + * to each track. + * + * This function returns true if all tagged tracks are started (or restarted). + * If any track fails, this function returns false, but all tracks that could + * start will still be started even when this function reports failure. + * + * From the point of view of the mixing process, all tracks that successfully + * (re)start will do so at the exact same moment. + * + * \param mixer the mixer on which to look for tagged tracks. + * \param tag the tag to use when searching for tracks. + * \param options the set of options that will be applied to each track. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTrack + * \sa MIX_TagTrack + * \sa MIX_StopTrack + * \sa MIX_PauseTrack + * \sa MIX_TrackPlaying + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PlayTag(MIX_Mixer *mixer, const char *tag, SDL_PropertiesID options); + +/** + * Play a MIX_Audio from start to finish without any management. + * + * This is what we term a "fire-and-forget" sound. Internally, SDL_mixer will + * manage a temporary track to mix the specified MIX_Audio, cleaning it up + * when complete. No options can be provided for how to do the mixing, like + * MIX_PlayTrack() offers, and since the track is not available to the caller, + * no adjustments can be made to mixing over time. + * + * This is not the function to build an entire game of any complexity around, + * but it can be convenient to play simple, one-off sounds that can't be + * stopped early. An example would be a voice saying "GAME OVER" during an + * unpausable endgame sequence. + * + * There are no limits to the number of fire-and-forget sounds that can mix at + * once (short of running out of memory), and SDL_mixer keeps an internal pool + * of temporary tracks it creates as needed and reuses when available. + * + * \param mixer the mixer on which to play this audio. + * \param audio the audio input to play. + * \returns true if the track has begun mixing, false on error; call + * SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTrack + * \sa MIX_LoadAudio + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PlayAudio(MIX_Mixer *mixer, MIX_Audio *audio); + +/** + * Halt a currently-playing track, possibly fading out over time. + * + * If `fade_out_frames` is > 0, the track does not stop mixing immediately, + * but rather fades to silence over that many sample frames before stopping. + * Sample frames are specific to the input assigned to the track, to allow for + * sample-perfect mixing. MIX_TrackMSToFrames() can be used to convert + * milliseconds to an appropriate value here. + * + * If the track ends normally while the fade-out is still in progress, the + * audio stops there; the fade is not adjusted to be shorter if it will last + * longer than the audio remaining. + * + * Once a track has completed any fadeout and come to a stop, it will call its + * MIX_TrackStoppedCallback, if any. It is legal to assign the track a new + * input and/or restart it during this callback. + * + * It is legal to halt a track that's already stopped. It does nothing, and + * returns true. + * + * \param track the track to halt. + * \param fade_out_frames the number of sample frames to spend fading out to + * silence before halting. 0 to stop immediately. + * \returns true if the track has stopped, false on error; call SDL_GetError() + * for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_StopTrack(MIX_Track *track, Sint64 fade_out_frames); + +/** + * Halt all currently-playing tracks, possibly fading out over time. + * + * If `fade_out_ms` is > 0, the tracks do not stop mixing immediately, but + * rather fades to silence over that many milliseconds before stopping. Note + * that this is different than MIX_StopTrack(), which wants sample frames; + * this function takes milliseconds because different tracks might have + * different sample rates. + * + * If a track ends normally while the fade-out is still in progress, the audio + * stops there; the fade is not adjusted to be shorter if it will last longer + * than the audio remaining. + * + * Once a track has completed any fadeout and come to a stop, it will call its + * MIX_TrackStoppedCallback, if any. It is legal to assign the track a new + * input and/or restart it during this callback. This function does not + * prevent new play requests from being made. + * + * \param mixer the mixer on which to stop all tracks. + * \param fade_out_ms the number of milliseconds to spend fading out to + * silence before halting. 0 to stop immediately. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_StopTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_StopAllTracks(MIX_Mixer *mixer, Sint64 fade_out_ms); + +/** + * Halt all tracks with a specific tag, possibly fading out over time. + * + * If `fade_out_ms` is > 0, the tracks do not stop mixing immediately, but + * rather fades to silence over that many milliseconds before stopping. Note + * that this is different than MIX_StopTrack(), which wants sample frames; + * this function takes milliseconds because different tracks might have + * different sample rates. + * + * If a track ends normally while the fade-out is still in progress, the audio + * stops there; the fade is not adjusted to be shorter if it will last longer + * than the audio remaining. + * + * Once a track has completed any fadeout and come to a stop, it will call its + * MIX_TrackStoppedCallback, if any. It is legal to assign the track a new + * input and/or restart it during this callback. This function does not + * prevent new play requests from being made. + * + * \param mixer the mixer on which to stop tracks. + * \param tag the tag to use when searching for tracks. + * \param fade_out_ms the number of milliseconds to spend fading out to + * silence before halting. 0 to stop immediately. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_StopTrack + * \sa MIX_TagTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_StopTag(MIX_Mixer *mixer, const char *tag, Sint64 fade_out_ms); + +/** + * Pause a currently-playing track. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * It is legal to pause a track that's in any state (playing, already paused, + * or stopped). Unless the track is currently playing, pausing does nothing, + * and returns true. A false return is only used to signal errors here (such + * as MIX_Init not being called or `track` being NULL). + * + * \param track the track to pause. + * \returns true if the track has paused, false on error; call SDL_GetError() + * for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_ResumeTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PauseTrack(MIX_Track *track); + +/** + * Pause all currently-playing tracks. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * This function makes all tracks on the specified mixer that are currently + * playing move to a paused state. They can later be resumed. + * + * \param mixer the mixer on which to pause all tracks. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_ResumeTrack + * \sa MIX_ResumeAllTracks + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PauseAllTracks(MIX_Mixer *mixer); + +/** + * Pause all tracks with a specific tag. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * This function makes all currently-playing tracks on the specified mixer, + * with a specific tag, move to a paused state. They can later be resumed. + * + * Tracks that match the specified tag that aren't currently playing are + * ignored. + * + * \param mixer the mixer on which to pause tracks. + * \param tag the tag to use when searching for tracks. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PauseTrack + * \sa MIX_ResumeTrack + * \sa MIX_ResumeTag + * \sa MIX_TagTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_PauseTag(MIX_Mixer *mixer, const char *tag); + +/** + * Resume a currently-paused track. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * It is legal to resume a track that's in any state (playing, paused, or + * stopped). Unless the track is currently paused, resuming does nothing, and + * returns true. A false return is only used to signal errors here (such as + * MIX_Init not being called or `track` being NULL). + * + * \param track the track to resume. + * \returns true if the track has resumed, false on error; call SDL_GetError() + * for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PauseTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_ResumeTrack(MIX_Track *track); + +/** + * Resume all currently-paused tracks. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * This function makes all tracks on the specified mixer that are currently + * paused move to a playing state. + * + * \param mixer the mixer on which to resume all tracks. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PauseTrack + * \sa MIX_PauseAllTracks + */ +extern SDL_DECLSPEC bool SDLCALL MIX_ResumeAllTracks(MIX_Mixer *mixer); + +/** + * Resume all tracks with a specific tag. + * + * A paused track is not considered "stopped," so its MIX_TrackStoppedCallback + * will not fire if paused, but it won't change state by default, generate + * audio, or generally make progress, until it is resumed. + * + * This function makes all currently-paused tracks on the specified mixer, + * with a specific tag, move to a playing state. + * + * Tracks that match the specified tag that aren't currently paused are + * ignored. + * + * \param mixer the mixer on which to resume tracks. + * \param tag the tag to use when searching for tracks. + * \returns true on success, false on error; call SDL_GetError() for details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_ResumeTrack + * \sa MIX_PauseTrack + * \sa MIX_PauseTag + * \sa MIX_TagTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_ResumeTag(MIX_Mixer *mixer, const char *tag); + +/** + * Query if a track is currently playing. + * + * If this returns true, the track is currently contributing to the mixer's + * output (it's "playing"). It is not stopped nor paused. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns false, but there is no mechanism to distinguish errors from + * non-playing tracks. + * + * \param track the track to query. + * \returns true if playing, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTrack + * \sa MIX_PauseTrack + * \sa MIX_ResumeTrack + * \sa MIX_StopTrack + * \sa MIX_TrackPaused + */ +extern SDL_DECLSPEC bool SDLCALL MIX_TrackPlaying(MIX_Track *track); + +/** + * Query if a track is currently paused. + * + * If this returns true, the track is not currently contributing to the + * mixer's output but will when resumed (it's "paused"). It is not playing nor + * stopped. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns false, but there is no mechanism to distinguish errors from + * non-playing tracks. + * + * \param track the track to query. + * \returns true if paused, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PlayTrack + * \sa MIX_PauseTrack + * \sa MIX_ResumeTrack + * \sa MIX_StopTrack + * \sa MIX_TrackPlaying + */ +extern SDL_DECLSPEC bool SDLCALL MIX_TrackPaused(MIX_Track *track); + + +/* volume control... */ + +/** + * Set a mixer's master gain control. + * + * Each mixer has a master gain, to adjust the volume of the entire mix. Each + * sample passing through the pipeline is modulated by this gain value. A gain + * of zero will generate silence, 1.0f will not change the mixed volume, and + * larger than 1.0f will increase the volume. Negative values are illegal. + * There is no maximum gain specified, but this can quickly get extremely + * loud, so please be careful with this setting. + * + * A mixer's master gain defaults to 1.0f. + * + * This value can be changed at any time to adjust the future mix. + * + * \param mixer the mixer to adjust. + * \param gain the new gain value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetMixerGain + * \sa MIX_SetTrackGain + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetMixerGain(MIX_Mixer *mixer, float gain); + +/** + * Get a mixer's master gain control. + * + * This returns the last value set through MIX_SetMixerGain(), or 1.0f if no + * value has ever been explicitly set. + * + * \param mixer the mixer to query. + * \returns the mixer's current master gain. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetMixerGain + * \sa MIX_GetTrackGain + */ +extern SDL_DECLSPEC float SDLCALL MIX_GetMixerGain(MIX_Mixer *mixer); + +/** + * Set a track's gain control. + * + * Each track has its own gain, to adjust its overall volume. Each sample from + * this track is modulated by this gain value. A gain of zero will generate + * silence, 1.0f will not change the mixed volume, and larger than 1.0f will + * increase the volume. Negative values are illegal. There is no maximum gain + * specified, but this can quickly get extremely loud, so please be careful + * with this setting. + * + * A track's gain defaults to 1.0f. + * + * This value can be changed at any time to adjust the future mix. + * + * \param track the track to adjust. + * \param gain the new gain value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackGain + * \sa MIX_SetMixerGain + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackGain(MIX_Track *track, float gain); + +/** + * Get a track's gain control. + * + * This returns the last value set through MIX_SetTrackGain(), or 1.0f if no + * value has ever been explicitly set. + * + * \param track the track to query. + * \returns the track's current gain. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackGain + * \sa MIX_GetMixerGain + */ +extern SDL_DECLSPEC float SDLCALL MIX_GetTrackGain(MIX_Track *track); + +/** + * Set the gain control of all tracks with a specific tag. + * + * Each track has its own gain, to adjust its overall volume. Each sample from + * this track is modulated by this gain value. A gain of zero will generate + * silence, 1.0f will not change the mixed volume, and larger than 1.0f will + * increase the volume. Negative values are illegal. There is no maximum gain + * specified, but this can quickly get extremely loud, so please be careful + * with this setting. + * + * A track's gain defaults to 1.0f. + * + * This will change the gain control on tracks on the specified mixer that + * have the specified tag. + * + * From the point of view of the mixing process, all tracks that successfully + * change gain values will do so at the exact same moment. + * + * This value can be changed at any time to adjust the future mix. + * + * \param mixer the mixer on which to look for tagged tracks. + * \param tag the tag to use when searching for tracks. + * \param gain the new gain value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackGain + * \sa MIX_SetTrackGain + * \sa MIX_SetMixerGain + * \sa MIX_TagTrack + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTagGain(MIX_Mixer *mixer, const char *tag, float gain); + + +/* frequency ratio ... */ + +/** + * Set a mixer's master frequency ratio. + * + * Each mixer has a master frequency ratio, that affects the entire mix. This + * can cause the final output to change speed and pitch. A value greater than + * 1.0f will play the audio faster, and at a higher pitch. A value less than + * 1.0f will play the audio slower, and at a lower pitch. 1.0f is normal + * speed. + * + * Each track _also_ has a frequency ratio; it will be applied when mixing + * that track's audio regardless of the master setting. The master setting + * affects the final output after all mixing has been completed. + * + * A mixer's master frequency ratio defaults to 1.0f. + * + * This value can be changed at any time to adjust the future mix. + * + * \param mixer the mixer to adjust. + * \param ratio the frequency ratio. Must be between 0.01f and 100.0f. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetMixerFrequencyRatio + * \sa MIX_SetTrackFrequencyRatio + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetMixerFrequencyRatio(MIX_Mixer *mixer, float ratio); + +/** + * Get a mixer's master frequency ratio. + * + * This returns the last value set through MIX_SetMixerFrequencyRatio(), or + * 1.0f if no value has ever been explicitly set. + * + * \param mixer the mixer to query. + * \returns the mixer's current master frequency ratio. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetMixerFrequencyRatio + * \sa MIX_GetTrackFrequencyRatio + */ +extern SDL_DECLSPEC float SDLCALL MIX_GetMixerFrequencyRatio(MIX_Mixer *mixer); + + +/** + * Change the frequency ratio of a track. + * + * The frequency ratio is used to adjust the rate at which audio data is + * consumed. Changing this effectively modifies the speed and pitch of the + * track's audio. A value greater than 1.0f will play the audio faster, and at + * a higher pitch. A value less than 1.0f will play the audio slower, and at a + * lower pitch. 1.0f is normal speed. + * + * The default value is 1.0f. + * + * This value can be changed at any time to adjust the future mix. + * + * \param track the track on which to change the frequency ratio. + * \param ratio the frequency ratio. Must be between 0.01f and 100.0f. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackFrequencyRatio + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackFrequencyRatio(MIX_Track *track, float ratio); + +/** + * Query the frequency ratio of a track. + * + * The frequency ratio is used to adjust the rate at which audio data is + * consumed. Changing this effectively modifies the speed and pitch of the + * track's audio. A value greater than 1.0f will play the audio faster, and at + * a higher pitch. A value less than 1.0f will play the audio slower, and at a + * lower pitch. 1.0f is normal speed. + * + * The default value is 1.0f. + * + * On various errors (MIX_Init() was not called, the track is NULL), this + * returns 0.0f. Since this is not a valid value to set, this can be seen as + * an error state. + * + * \param track the track on which to query the frequency ratio. + * \returns the current frequency ratio, or 0.0f on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrackFrequencyRatio + */ +extern SDL_DECLSPEC float SDLCALL MIX_GetTrackFrequencyRatio(MIX_Track *track); + + +/* channel maps... */ + +/** + * Set the current output channel map of a track. + * + * Channel maps are optional; most things do not need them, instead passing + * data in the order that SDL expects. + * + * The output channel map reorders track data after transformations and before + * it is mixed into a mixer group. This can be useful for reversing stereo + * channels, for example. + * + * Each item in the array represents an input channel, and its value is the + * channel that it should be remapped to. To reverse a stereo signal's left + * and right values, you'd have an array of `{ 1, 0 }`. It is legal to remap + * multiple channels to the same thing, so `{ 1, 1 }` would duplicate the + * right channel to both channels of a stereo signal. An element in the + * channel map set to -1 instead of a valid channel will mute that channel, + * setting it to a silence value. + * + * You cannot change the number of channels through a channel map, just + * reorder/mute them. + * + * Tracks default to no remapping applied. Passing a NULL channel map is + * legal, and turns off remapping. + * + * SDL_mixer will copy the channel map; the caller does not have to save this + * array after this call. + * + * \param track the track to change. + * \param chmap the new channel map, NULL to reset to default. + * \param count The number of channels in the map. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackOutputChannelMap(MIX_Track *track, const int *chmap, int count); + + +/* positional audio... */ + +/** + * A set of per-channel gains for tracks using MIX_SetTrackStereo(). + * + * When forcing a track to stereo, the app can specify a per-channel gain, to + * further adjust the left or right outputs. + * + * When mixing audio that has been forced to stereo, each channel is modulated + * by these values. A value of 1.0f produces no change, 0.0f produces silence. + * + * A simple panning effect would be to set `left` to the desired value and + * `right` to `1.0f - left`. + * + * \since This struct is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackStereo + */ +typedef struct MIX_StereoGains +{ + float left; /**< left channel gain */ + float right; /**< right channel gain */ +} MIX_StereoGains; + +/** + * Force a track to stereo output, with optionally left/right panning. + * + * This will cause the output of the track to convert to stereo, and then mix + * it only onto the Front Left and Front Right speakers, regardless of the + * speaker configuration. The left and right channels are modulated by + * `gains`, which can be used to produce panning effects. This function may be + * called to adjust the gains at any time. + * + * If `gains` is not NULL, this track will be switched into forced-stereo + * mode. If `gains` is NULL, this will disable spatialization (both the + * forced-stereo mode of this function and full 3D spatialization of + * MIX_SetTrack3DPosition()). + * + * Negative gains are clamped to zero; there is no clamp for maximum, so one + * could set the value > 1.0f to make a channel louder. + * + * The track's 3D position, reported by MIX_GetTrack3DPosition(), will be + * reset to (0, 0, 0). + * + * \param track the track to adjust. + * \param gains the per-channel gains, or NULL to disable spatialization. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrack3DPosition + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackStereo(MIX_Track *track, const MIX_StereoGains *gains); + + +/** + * 3D coordinates for MIX_SetTrack3DPosition. + * + * The coordinates use a "right-handed" coordinate system, like OpenGL and + * OpenAL. + * + * \since This struct is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrack3DPosition + */ +typedef struct MIX_Point3D +{ + float x; /**< X coordinate (negative left, positive right). */ + float y; /**< Y coordinate (negative down, positive up). */ + float z; /**< Z coordinate (negative forward, positive back). */ +} MIX_Point3D; + +/** + * Set a track's position in 3D space. + * + * (Please note that SDL_mixer is not intended to be a extremely powerful 3D + * API. It lacks 3D features that other APIs like OpenAL offer: there's no + * doppler effect, distance models, rolloff, etc. This is meant to be Good + * Enough for games that can use some positional sounds and can even take + * advantage of surround-sound configurations.) + * + * If `position` is not NULL, this track will be switched into 3D positional + * mode. If `position` is NULL, this will disable positional mixing (both the + * full 3D spatialization of this function and forced-stereo mode of + * MIX_SetTrackStereo()). + * + * In 3D positional mode, SDL_mixer will mix this track as if it were + * positioned in 3D space, including distance attenuation (quieter as it gets + * further from the listener) and spatialization (positioned on the correct + * speakers to suggest direction, either with stereo outputs or full surround + * sound). + * + * For a mono speaker output, spatialization is effectively disabled but + * distance attenuation will still work, which is all you can really do with a + * single speaker. + * + * The coordinate system operates like OpenGL or OpenAL: a "right-handed" + * coordinate system. See MIX_Point3D for the details. + * + * The listener is always at coordinate (0,0,0) and can't be changed. + * + * The track's input will be converted to mono (1 channel) so it can be + * rendered across the correct speakers. + * + * \param track the track for which to set 3D position. + * \param position the new 3D position for the track. May be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetTrack3DPosition + * \sa MIX_SetTrackStereo + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrack3DPosition(MIX_Track *track, const MIX_Point3D *position); + +/** + * Get a track's current position in 3D space. + * + * If 3D positioning isn't enabled for this track, through a call to + * MIX_SetTrack3DPosition(), this will return (0,0,0). + * + * \param track the track to query. + * \param position on successful return, will contain the track's position. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrack3DPosition + */ +extern SDL_DECLSPEC bool SDLCALL MIX_GetTrack3DPosition(MIX_Track *track, MIX_Point3D *position); + + +/* Mix groups... */ + +/** + * Create a mixing group. + * + * Tracks are assigned to a mixing group (or if unassigned, they live in a + * mixer's internal default group). All tracks in a group are mixed together + * and the app can access this mixed data before it is mixed with all other + * groups to produce the final output. + * + * This can be a useful feature, but is completely optional; apps can ignore + * mixing groups entirely and still have a full experience with SDL_mixer. + * + * After creating a group, assign tracks to it with MIX_SetTrackGroup(). Use + * MIX_SetGroupPostMixCallback() to access the group's mixed data. + * + * A mixing group can be destroyed with MIX_DestroyGroup() when no longer + * needed. Destroying the mixer will also destroy all its still-existing + * mixing groups. + * + * \param mixer the mixer on which to create a mixing group. + * \returns a newly-created mixing group, or NULL on error; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_DestroyGroup + * \sa MIX_SetTrackGroup + * \sa MIX_SetGroupPostMixCallback + */ +extern SDL_DECLSPEC MIX_Group * SDLCALL MIX_CreateGroup(MIX_Mixer *mixer); + +/** + * Destroy a mixing group. + * + * Any tracks currently assigned to this group will be reassigned to the + * mixer's internal default group. + * + * \param group the mixing group to destroy. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateGroup + */ +extern SDL_DECLSPEC void SDLCALL MIX_DestroyGroup(MIX_Group *group); + +/** + * Get the properties associated with a group. + * + * Currently SDL_mixer assigns no properties of its own to a group, but this + * can be a convenient place to store app-specific data. + * + * A SDL_PropertiesID is created the first time this function is called for a + * given group. + * + * \param group the group to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL MIX_GetGroupProperties(MIX_Group *group); + +/** + * Get the MIX_Mixer that owns a MIX_Group. + * + * This is the mixer pointer that was passed to MIX_CreateGroup(). + * + * \param group the group to query. + * \returns the mixer associated with the group, or NULL on error; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC MIX_Mixer * SDLCALL MIX_GetGroupMixer(MIX_Group *group); + +/** + * Assign a track to a mixing group. + * + * All tracks in a group are mixed together, and that output is made available + * to the app before it is mixed into the final output. + * + * Tracks can only be in one group at a time, and the track and group must + * have been created on the same MIX_Mixer. + * + * Setting a track to a NULL group will remove it from any app-created groups, + * and reassign it to the mixer's internal default group. + * + * \param track the track to set mixing group assignment. + * \param group the new mixing group to assign to. May be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateGroup + * \sa MIX_SetGroupPostMixCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackGroup(MIX_Track *track, MIX_Group *group); + + + +/* Hooks... */ + +/** + * A callback that fires when a MIX_Track is stopped. + * + * This callback is fired when a track completes playback, either because it + * ran out of data to mix (and all loops were completed as well), or it was + * explicitly stopped by the app. Pausing a track will not fire this callback. + * + * It is legal to adjust the track, including changing its input and + * restarting it. If this is done because it ran out of data in the middle of + * mixing, the mixer will start mixing the new track state in its current run + * without any gap in the audio. + * + * This callback will not fire when a playing track is destroyed. + * + * \param userdata an opaque pointer provided by the app for its personal use. + * \param track the track that has stopped. + * + * \since This datatype is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackStoppedCallback + */ +typedef void (SDLCALL *MIX_TrackStoppedCallback)(void *userdata, MIX_Track *track); + +/** + * Set a callback that fires when a MIX_Track is stopped. + * + * When a track completes playback, either because it ran out of data to mix + * (and all loops were completed as well), or it was explicitly stopped by the + * app, it will fire the callback specified here. + * + * Each track has its own unique callback. + * + * Passing a NULL callback here is legal; it disables this track's callback. + * + * Pausing a track will not fire the callback, nor will the callback fire on a + * playing track that is being destroyed. + * + * It is legal to adjust the track, including changing its input and + * restarting it. If this is done because it ran out of data in the middle of + * mixing, the mixer will start mixing the new track state in its current run + * without any gap in the audio. + * + * \param track the track to assign this callback to. + * \param cb the function to call when the track stops. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TrackStoppedCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackStoppedCallback(MIX_Track *track, MIX_TrackStoppedCallback cb, void *userdata); + +/** + * A callback that fires when a MIX_Track is mixing at various stages. + * + * This callback is fired for different parts of the mixing pipeline, and + * gives the app visbility into the audio data that is being generated at + * various stages. + * + * The audio data passed through here is _not_ const data; the app is + * permitted to change it in any way it likes, and those changes will + * propagate through the mixing pipeline. + * + * An audiospec is provided. Different tracks might be in different formats, + * and an app needs to be able to handle that, but SDL_mixer always does its + * mixing work in 32-bit float samples, even if the inputs or final output are + * not floating point. As such, `spec->format` will always be `SDL_AUDIO_F32` + * and `pcm` hardcoded to be a float pointer. + * + * `samples` is the number of float values pointed to by `pcm`: samples, not + * sample frames! There are no promises how many samples will be provided + * per-callback, and this number can vary wildly from call to call, depending + * on many factors. + * + * Making changes to the track during this callback is undefined behavior. + * Change the data in `pcm` but not the track itself. + * + * \param userdata an opaque pointer provided by the app for its personal use. + * \param track the track that is being mixed. + * \param spec the format of the data in `pcm`. + * \param pcm the raw PCM data in float32 format. + * \param samples the number of float values pointed to by `pcm`. + * + * \since This datatype is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetTrackRawCallback + * \sa MIX_SetTrackCookedCallback + */ +typedef void (SDLCALL *MIX_TrackMixCallback)(void *userdata, MIX_Track *track, const SDL_AudioSpec *spec, float *pcm, int samples); + +/** + * Set a callback that fires when a MIX_Track has initial decoded audio. + * + * As a track needs to mix more data, it pulls from its input (a MIX_Audio, an + * SDL_AudioStream, etc). This input might be a compressed file format, like + * MP3, so a little more data is uncompressed from it. + * + * Once the track has PCM data to start operating on, it can fire a callback + * before _any_ changes to the raw PCM input have happened. This lets an app + * view the data before it has gone through transformations such as gain, 3D + * positioning, fading, etc. It can also change the data in any way it pleases + * during this callback, and the mixer will continue as if this data came + * directly from the input. + * + * Each track has its own unique raw callback. + * + * Passing a NULL callback here is legal; it disables this track's callback. + * + * \param track the track to assign this callback to. + * \param cb the function to call when the track mixes. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TrackMixCallback + * \sa MIX_SetTrackCookedCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackRawCallback(MIX_Track *track, MIX_TrackMixCallback cb, void *userdata); + +/** + * Set a callback that fires when the mixer has transformed a track's audio. + * + * As a track needs to mix more data, it pulls from its input (a MIX_Audio, an + * SDL_AudioStream, etc). This input might be a compressed file format, like + * MP3, so a little more data is uncompressed from it. + * + * Once the track has PCM data to start operating on, and its raw callback has + * completed, it will begin to transform the audio: gain, fading, frequency + * ratio, 3D positioning, etc. + * + * A callback can be fired after all these transformations, but before the + * transformed data is mixed into other tracks. This lets an app view the data + * at the last moment that it is still a part of this track. It can also + * change the data in any way it pleases during this callback, and the mixer + * will continue as if this data came directly from the input. + * + * Each track has its own unique cooked callback. + * + * Passing a NULL callback here is legal; it disables this track's callback. + * + * \param track the track to assign this callback to. + * \param cb the function to call when the track mixes. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_TrackMixCallback + * \sa MIX_SetTrackRawCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetTrackCookedCallback(MIX_Track *track, MIX_TrackMixCallback cb, void *userdata); + +/** + * A callback that fires when a MIX_Group has completed mixing. + * + * This callback is fired when a mixing group has finished mixing: all tracks + * in the group have mixed into a single buffer and are prepared to be mixed + * into all other groups for the final mix output. + * + * The audio data passed through here is _not_ const data; the app is + * permitted to change it in any way it likes, and those changes will + * propagate through the mixing pipeline. + * + * An audiospec is provided. Different groups might be in different formats, + * and an app needs to be able to handle that, but SDL_mixer always does its + * mixing work in 32-bit float samples, even if the inputs or final output are + * not floating point. As such, `spec->format` will always be `SDL_AUDIO_F32` + * and `pcm` hardcoded to be a float pointer. + * + * `samples` is the number of float values pointed to by `pcm`: samples, not + * sample frames! There are no promises how many samples will be provided + * per-callback, and this number can vary wildly from call to call, depending + * on many factors. + * + * \param userdata an opaque pointer provided by the app for its personal use. + * \param group the group that is being mixed. + * \param spec the format of the data in `pcm`. + * \param pcm the raw PCM data in float32 format. + * \param samples the number of float values pointed to by `pcm`. + * + * \since This datatype is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetGroupPostMixCallback + */ +typedef void (SDLCALL *MIX_GroupMixCallback)(void *userdata, MIX_Group *group, const SDL_AudioSpec *spec, float *pcm, int samples); + +/** + * Set a callback that fires when a mixer group has completed mixing. + * + * After all playing tracks in a mixer group have pulled in more data from + * their inputs, transformed it, and mixed together into a single buffer, a + * callback can be fired. This lets an app view the data at the last moment + * that it is still a part of this group. It can also change the data in any + * way it pleases during this callback, and the mixer will continue as if this + * data came directly from the group's mix buffer. + * + * Each group has its own unique callback. Tracks that aren't in an explicit + * MIX_Group are mixed in an internal grouping that is not available to the + * app. + * + * Passing a NULL callback here is legal; it disables this group's callback. + * + * \param group the mixing group to assign this callback to. + * \param cb the function to call when the group mixes. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GroupMixCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetGroupPostMixCallback(MIX_Group *group, MIX_GroupMixCallback cb, void *userdata); + +/** + * A callback that fires when all mixing has completed. + * + * This callback is fired when the mixer has completed all its work. If this + * mixer was created with MIX_CreateMixerDevice(), the data provided by this + * callback is what is being sent to the audio hardware, minus last + * conversions for format requirements. If this mixer was created with + * MIX_CreateMixer(), this is what is being output from MIX_Generate(), after + * final conversions. + * + * The audio data passed through here is _not_ const data; the app is + * permitted to change it in any way it likes, and those changes will replace + * the final mixer pipeline output. + * + * An audiospec is provided. SDL_mixer always does its mixing work in 32-bit + * float samples, even if the inputs or final output are not floating point. + * As such, `spec->format` will always be `SDL_AUDIO_F32` and `pcm` hardcoded + * to be a float pointer. + * + * `samples` is the number of float values pointed to by `pcm`: samples, not + * sample frames! There are no promises how many samples will be provided + * per-callback, and this number can vary wildly from call to call, depending + * on many factors. + * + * \param userdata an opaque pointer provided by the app for its personal use. + * \param mixer the mixer that is generating audio. + * \param spec the format of the data in `pcm`. + * \param pcm the raw PCM data in float32 format. + * \param samples the number of float values pointed to by `pcm`. + * + * \since This datatype is available since SDL_mixer 3.0.0. + * + * \sa MIX_SetPostMixCallback + */ +typedef void (SDLCALL *MIX_PostMixCallback)(void *userdata, MIX_Mixer *mixer, const SDL_AudioSpec *spec, float *pcm, int samples); + +/** + * Set a callback that fires when all mixing has completed. + * + * After all mixer groups have processed, their buffers are mixed together + * into a single buffer for the final output, at which point a callback can be + * fired. This lets an app view the data at the last moment before mixing + * completes. It can also change the data in any way it pleases during this + * callback, and the mixer will continue as if this data is the final output. + * + * Each mixer has its own unique callback. + * + * Passing a NULL callback here is legal; it disables this mixer's callback. + * + * \param mixer the mixer to assign this callback to. + * \param cb the function to call when the mixer mixes. May be NULL. + * \param userdata an opaque pointer provided to the callback for its own + * personal use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_PostMixCallback + */ +extern SDL_DECLSPEC bool SDLCALL MIX_SetPostMixCallback(MIX_Mixer *mixer, MIX_PostMixCallback cb, void *userdata); + + +/* Audio generation without an audio device... */ + +/** + * Generate mixer output when not driving an audio device. + * + * SDL_mixer allows the creation of MIX_Mixer objects that are not connected + * to an audio device, by calling MIX_CreateMixer() instead of + * MIX_CreateMixerDevice(). Such mixers will not generate output until + * explicitly requested through this function. + * + * The caller may request as much audio as desired, so long as `buflen` is a + * multiple of the sample frame size specified when creating the mixer (for + * example, if requesting stereo Sint16 audio, buflen must be a multiple of 4: + * 2 bytes-per-channel times 2 channels). + * + * The mixer will mix as quickly as possible; since it works in sample frames + * instead of time, it can potentially generate enormous amounts of audio in a + * small amount of time. + * + * On success, this always fills `buffer` with `buflen` bytes of audio; if all + * playing tracks finish mixing, it will fill the remaining buffer with + * silence. + * + * Each call to this function will pick up where it left off, playing tracks + * will continue to mix from the point the previous call completed, etc. The + * mixer state can be changed between each call in any way desired: tracks can + * be added, played, stopped, changed, removed, etc. Effectively this function + * does the same thing SDL_mixer does internally when the audio device needs + * more audio to play. + * + * This function can not be used with mixers from MIX_CreateMixerDevice(); + * those generate audio as needed internally. + * + * This function returns the number of _bytes_ of real audio mixed, which + * might be less than `buflen`. While all `buflen` bytes of `buffer` will be + * initialized, if available tracks to mix run out, the end of the buffer will + * be initialized with silence; this silence will not be counted in the return + * value, so the caller has the option to identify how much of the buffer has + * legimitate contents vs appended silence. As such, any value >= 0 signifies + * success. A return value of -1 means failure (out of memory, invalid + * parameters, etc). + * + * \param mixer the mixer for which to generate more audio. + * \param buffer a pointer to a buffer to store audio in. + * \param buflen the number of bytes to store in buffer. + * \returns The number of bytes of mixed audio, discounting appended silence, + * on success, or -1 on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateMixer + */ +extern SDL_DECLSPEC int SDLCALL MIX_Generate(MIX_Mixer *mixer, void *buffer, int buflen); + + +/* Decode audio files directly without a mixer ... */ + +/** + * An opaque object that represents an audio decoder. + * + * Most apps won't need this, as SDL_mixer's usual interfaces will decode + * audio as needed. However, if one wants to decode an audio file into a + * memory buffer without playing it, this interface offers that. + * + * These objects are created with MIX_CreateAudioDecoder() or + * MIX_CreateAudioDecoder_IO(), and then can use MIX_DecodeAudio() to retrieve + * the raw PCM data. + * + * \since This struct is available since SDL_mixer 3.0.0. + */ +typedef struct MIX_AudioDecoder MIX_AudioDecoder; + +/** + * Create a MIX_AudioDecoder from a path on the filesystem. + * + * Most apps won't need this, as SDL_mixer's usual interfaces will decode + * audio as needed. However, if one wants to decode an audio file into a + * memory buffer without playing it, this interface offers that. + * + * This function allows properties to be specified. This is intended to supply + * file-specific settings, such as where to find SoundFonts for a MIDI file, + * etc. In most cases, the caller should pass a zero to specify no extra + * properties. + * + * SDL_PropertiesID are discussed in + * [SDL's documentation](https://wiki.libsdl.org/SDL3/CategoryProperties) + * . + * + * When done with the audio decoder, it can be destroyed with + * MIX_DestroyAudioDecoder(). + * + * This function requires SDL_mixer to have been initialized with a successful + * call to MIX_Init(), but does not need an actual MIX_Mixer to have been + * created. + * + * \param path the path on the filesystem from which to load data. + * \param props decoder-specific properties. May be zero. + * \returns an audio decoder, ready to decode. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateAudioDecoder_IO + * \sa MIX_DecodeAudio + * \sa MIX_DestroyAudioDecoder + */ +extern SDL_DECLSPEC MIX_AudioDecoder * SDLCALL MIX_CreateAudioDecoder(const char *path, SDL_PropertiesID props); + +/** + * Create a MIX_AudioDecoder from an SDL_IOStream. + * + * Most apps won't need this, as SDL_mixer's usual interfaces will decode + * audio as needed. However, if one wants to decode an audio file into a + * memory buffer without playing it, this interface offers that. + * + * This function allows properties to be specified. This is intended to supply + * file-specific settings, such as where to find SoundFonts for a MIDI file, + * etc. In most cases, the caller should pass a zero to specify no extra + * properties. + * + * If `closeio` is true, then `io` will be closed when this decoder is done + * with it. If this function fails and `closeio` is true, then `io` will be + * closed before this function returns. + * + * When done with the audio decoder, it can be destroyed with + * MIX_DestroyAudioDecoder(). + * + * This function requires SDL_mixer to have been initialized with a successful + * call to MIX_Init(), but does not need an actual MIX_Mixer to have been + * created. + * + * \param io the i/o stream from which to load data. + * \param closeio if true, close the i/o stream when done with it. + * \param props decoder-specific properties. May be zero. + * \returns an audio decoder, ready to decode. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_CreateAudioDecoder_IO + * \sa MIX_DecodeAudio + * \sa MIX_DestroyAudioDecoder + */ +extern SDL_DECLSPEC MIX_AudioDecoder * SDLCALL MIX_CreateAudioDecoder_IO(SDL_IOStream *io, bool closeio, SDL_PropertiesID props); + +/** + * Destroy the specified audio decoder. + * + * Destroying a NULL MIX_AudioDecoder is a legal no-op. + * + * \param audiodecoder the audio to destroy. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC void SDLCALL MIX_DestroyAudioDecoder(MIX_AudioDecoder *audiodecoder); + +/** + * Get the properties associated with a MIX_AudioDecoder. + * + * SDL_mixer offers some properties of its own, but this can also be a + * convenient place to store app-specific data. + * + * A SDL_PropertiesID is created the first time this function is called for a + * given MIX_AudioDecoder, if necessary. + * + * The file-specific metadata exposed through this function is identical to + * those available through MIX_GetAudioProperties(). Please refer to that + * function's documentation for details. + * + * \param audiodecoder the audio decoder to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + * + * \sa MIX_GetAudioProperties + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL MIX_GetAudioDecoderProperties(MIX_AudioDecoder *audiodecoder); + +/** + * Query the initial audio format of a MIX_AudioDecoder. + * + * Note that some audio files can change format in the middle; some explicitly + * support this, but a more common example is two MP3 files concatenated + * together. In many cases, SDL_mixer will correctly handle these sort of + * files, but this function will only report the initial format a file uses. + * + * \param audiodecoder the audio decoder to query. + * \param spec on success, audio format details will be stored here. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL MIX_GetAudioDecoderFormat(MIX_AudioDecoder *audiodecoder, SDL_AudioSpec *spec); + +/** + * Decode more audio from a MIX_AudioDecoder. + * + * Data is decoded on demand in whatever format is requested. The format is + * permitted to change between calls. + * + * This function will return the number of bytes decoded, which may be less + * than requested if there was an error or end-of-file. A return value of zero + * means the entire file was decoded, -1 means an unrecoverable error + * happened. + * + * \param audiodecoder the decoder from which to retrieve more data. + * \param buffer the memory buffer to store decoded audio. + * \param buflen the maximum number of bytes to store to `buffer`. + * \param spec the format that audio data will be stored to `buffer`. + * \returns number of bytes decoded, or -1 on error; call SDL_GetError() for + * more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_mixer 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL MIX_DecodeAudio(MIX_AudioDecoder *audiodecoder, void *buffer, int buflen, const SDL_AudioSpec *spec); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_MIXER_H_ */ diff --git a/vendor/sdl3/mixer/libgme.dll b/vendor/sdl3/mixer/libgme.dll new file mode 100644 index 000000000..6d1ef9ca7 --- /dev/null +++ b/vendor/sdl3/mixer/libgme.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50b739c925702d381e163e66887699eb980e03681577d8d7a19cd9972a315dea +size 445440 diff --git a/vendor/sdl3/mixer/libogg-0.dll b/vendor/sdl3/mixer/libogg-0.dll new file mode 100644 index 000000000..d2de59965 --- /dev/null +++ b/vendor/sdl3/mixer/libogg-0.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76344182f53695db65fca5921ab4e478cdf2f954d86628b27dab0fb9327bf2e7 +size 32768 diff --git a/vendor/sdl3/mixer/libopus-0.dll b/vendor/sdl3/mixer/libopus-0.dll new file mode 100644 index 000000000..3f7865d5d --- /dev/null +++ b/vendor/sdl3/mixer/libopus-0.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:064aaa2aee76ac93df0f9ec78a670a49954e3f4ac1bc1fd70ebda2f035ccc073 +size 367616 diff --git a/vendor/sdl3/mixer/libopusfile-0.dll b/vendor/sdl3/mixer/libopusfile-0.dll new file mode 100644 index 000000000..c664cf7f4 --- /dev/null +++ b/vendor/sdl3/mixer/libopusfile-0.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2e7edcdfb87f12763508b0234e2f945b6e8a3706bda740911e0d1a8ef24c758 +size 48640 diff --git a/vendor/sdl3/mixer/libwavpack-1.dll b/vendor/sdl3/mixer/libwavpack-1.dll new file mode 100644 index 000000000..2278390c9 --- /dev/null +++ b/vendor/sdl3/mixer/libwavpack-1.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e07f0623d14cbf19f6f3ee75ed6f45191088033e7167877a8ccbb41f1589f1a1 +size 178688 diff --git a/vendor/sdl3/mixer/libxmp.dll b/vendor/sdl3/mixer/libxmp.dll new file mode 100644 index 000000000..5923fd353 --- /dev/null +++ b/vendor/sdl3/mixer/libxmp.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a5f1198d976d7ea5aeb8433905c47a71906c2c9b0733166d88ec4a4525e0dee +size 417792 diff --git a/vendor/sdl3/mixer/sdl3_mixer.odin b/vendor/sdl3/mixer/sdl3_mixer.odin new file mode 100644 index 000000000..276f94c8e --- /dev/null +++ b/vendor/sdl3/mixer/sdl3_mixer.odin @@ -0,0 +1,168 @@ +package sdl3_mixer + +import "core:c" + +import SDL "vendor:sdl3" + +when ODIN_OS == .Windows { + foreign import lib "SDL3_mixer.lib" +} else { + foreign import lib "system:SDL3_mixer" +} + +Mixer :: struct {} +Audio :: struct {} +Track :: struct {} +Group :: struct {} + +StereoGains :: struct { + left, right: c.float, +} +Point3D :: struct { + x, y, z: c.float, +} + +TrackStoppedCallback :: #type proc(userdata: rawptr, track: ^Track) +TrackMixCallback :: #type proc(userdata: rawptr, track: ^Track, spec: ^SDL.AudioSpec, pcm: ^c.float, samples: c.int) +GroupMixCallback :: #type proc(userdata: rawptr, group: ^Group, spec: ^SDL.AudioSpec, pcm: ^c.float, samples: c.int) +PostMixCallback :: #type proc( userdata: rawptr, mixer: ^Mixer, spec: ^SDL.AudioSpec, pcm: ^c.float, samples: c.int) + +AudioDecoder :: struct {} + +MAJOR_VERSION :: 3 +MINOR_VERSION :: 2 +MICRO_VERSION :: 0 + +PROP_MIXER_DEVICE_NUMBER :: "SDL_mixer.mixer.device" + +PROP_AUDIO_LOAD_IOSTREAM_POINTER :: "SDL_mixer.audio.load.iostream" +PROP_AUDIO_LOAD_CLOSEIO_BOOLEAN :: "SDL_mixer.audio.load.closeio" +PROP_AUDIO_LOAD_PREDECODE_BOOLEAN :: "SDL_mixer.audio.load.predecode" +PROP_AUDIO_LOAD_PREFERRED_MIXER_POINTER :: "SDL_mixer.audio.load.preferred_mixer" +PROP_AUDIO_LOAD_SKIP_METADATA_TAGS_BOOLEAN :: "SDL_mixer.audio.load.skip_metadata_tags" +PROP_AUDIO_DECODER_STRING :: "SDL_mixer.audio.decoder" + +PROP_METADATA_TITLE_STRING :: "SDL_mixer.metadata.title" +PROP_METADATA_ARTIST_STRING :: "SDL_mixer.metadata.artist" +PROP_METADATA_ALBUM_STRING :: "SDL_mixer.metadata.album" +PROP_METADATA_COPYRIGHT_STRING :: "SDL_mixer.metadata.copyright" +PROP_METADATA_TRACK_NUMBER :: "SDL_mixer.metadata.track" +PROP_METADATA_TOTAL_TRACKS_NUMBER :: "SDL_mixer.metadata.total_tracks" +PROP_METADATA_YEAR_NUMBER :: "SDL_mixer.metadata.year" +PROP_METADATA_DURATION_FRAMES_NUMBER :: "SDL_mixer.metadata.duration_frames" +PROP_METADATA_DURATION_INFINITE_BOOLEAN :: "SDL_mixer.metadata.duration_infinite" + +PROP_PLAY_LOOPS_NUMBER :: "SDL_mixer.play.loops" +PROP_PLAY_MAX_FRAME_NUMBER :: "SDL_mixer.play.max_frame" +PROP_PLAY_MAX_MILLISECONDS_NUMBER :: "SDL_mixer.play.max_milliseconds" +PROP_PLAY_START_FRAME_NUMBER :: "SDL_mixer.play.start_frame" +PROP_PLAY_START_MILLISECOND_NUMBER :: "SDL_mixer.play.start_millisecond" +PROP_PLAY_LOOP_START_FRAME_NUMBER :: "SDL_mixer.play.loop_start_frame" +PROP_PLAY_LOOP_START_MILLISECOND_NUMBER :: "SDL_mixer.play.loop_start_millisecond" +PROP_PLAY_FADE_IN_FRAMES_NUMBER :: "SDL_mixer.play.fade_in_frames" +PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER :: "SDL_mixer.play.fade_in_milliseconds" +PROP_PLAY_FADE_IN_START_GAIN_FLOAT :: "SDL_mixer.play.fade_in_start_gain" +PROP_PLAY_APPEND_SILENCE_FRAMES_NUMBER :: "SDL_mixer.play.append_silence_frames" +PROP_PLAY_APPEND_SILENCE_MILLISECONDS_NUMBER :: "SDL_mixer.play.append_silence_milliseconds" +PROP_PLAY_HALT_WHEN_EXHAUSTED_BOOLEAN :: "SDL_mixer.play.halt_when_exhausted" + +DURATION_UNKNOWN :: -1 +DURATION_INFINITE :: -2 + +@(default_calling_convention = "c", link_prefix = "MIX_", require_results) +foreign lib { + Version :: proc() -> c.int --- + Init :: proc() -> c.bool --- + Quit :: proc() --- + GetNumAudioDecoders :: proc() -> c.int --- + GetAudioDecoder :: proc(index: c.int) -> cstring --- + CreateMixerDevice :: proc(devid: SDL.AudioDeviceID, spec: Maybe(^SDL.AudioSpec)) -> ^Mixer --- + CreateMixer :: proc(spec: Maybe(^SDL.AudioSpec)) -> ^Mixer --- + DestroyMixer :: proc(mixer: ^Mixer) --- + GetMixerProperties :: proc(mixer: ^Mixer) -> SDL.PropertiesID --- + GetMixerFormat :: proc(mixer: ^Mixer, spec: ^SDL.AudioSpec) -> c.bool --- + LockMixer :: proc(mixer: ^Mixer) --- + UnlockMixer :: proc(mixer: ^Mixer) --- + LoadAudio_IO :: proc(mixer: ^Mixer, io: ^SDL.IOStream, predecode, closeio: c.bool) -> ^Audio --- + LoadAudio :: proc(mixer: ^Mixer, path: cstring, predecode: c.bool) -> ^Audio --- + LoadAudioNoCopy :: proc(mixer: ^Mixer, data: rawptr, datalen: c.size_t, free_when_done: c.bool) -> ^Audio --- + LoadAudioWithProperties :: proc(props: SDL.PropertiesID) -> ^Audio --- + LoadRawAudio_IO :: proc(mixer: ^Mixer, io: ^SDL.IOStream, #by_ptr spec: SDL.AudioSpec, closeio: c.bool) -> ^Audio --- + LoadRawAudio :: proc(mixer: ^Mixer, data: rawptr, datalen: c.size_t, #by_ptr spec: SDL.AudioSpec) -> ^Audio --- + LoadRawAudioNoCopy :: proc(mixer: ^Mixer, data: rawptr, datalen: c.size_t, #by_ptr spec: SDL.AudioSpec, free_when_done: c.bool) -> ^Audio --- + CreateSineWaveAudio :: proc(mixer: ^Mixer, hz: c.int, amplitude: c.float, ms: SDL.Sint64) -> ^Audio --- + GetAudioProperties :: proc(audio: ^Audio) -> SDL.PropertiesID --- + GetAudioDuration :: proc(audio: ^Audio) -> SDL.Sint64 --- + GetAudioFormat :: proc(audio: ^Audio, spec: ^SDL.AudioSpec) -> c.bool --- + DestroyAudio :: proc(audio: ^Audio) --- + CreateTrack :: proc(mixer: ^Mixer) -> ^Track --- + DestroyTrack :: proc(track: ^Track) --- + GetTrackProperties :: proc(track: ^Track) -> SDL.PropertiesID --- + GetTrackMixer :: proc(track: ^Track) -> ^Mixer --- + SetTrackAudio :: proc(track: ^Track, audio: ^Audio) -> c.bool --- + SetTrackAudioStream :: proc(track: ^Track, stream: ^SDL.AudioStream) -> c.bool --- + SetTrackIOStream :: proc(track: ^Track, io: ^SDL.IOStream, closeio: c.bool) -> c.bool --- + SetTrackRawIOStream :: proc(track: ^Track, io: ^SDL.IOStream, #by_ptr spec: SDL.AudioSpec, closeio: c.bool) -> c.bool --- + TagTrack :: proc(track: ^Track, tag: cstring) -> c.bool --- + UntagTrack :: proc(track: ^Track, tag: cstring) --- + GetTrackTags :: proc(track: ^Track, count: ^c.int) -> [^]cstring --- + GetTaggedTracks :: proc(mixer: ^Mixer, tag: cstring, count: ^c.int) -> [^]^Track --- + SetTrackPlaybackPosition :: proc(track: ^Track, frames: SDL.Sint64) -> c.bool --- + GetTrackPlaybackPosition :: proc(track: ^Track) -> SDL.Sint64 --- + GetTrackFadeFrames :: proc(track: ^Track) -> SDL.Sint64 --- + GetTrackLoops :: proc(track: ^Track) -> c.int --- + SetTrackLoops :: proc(track: ^Track, num_loops: c.int) -> c.bool --- + GetTrackAudio :: proc(track: ^Track) -> ^Audio --- + GetTrackAudioStream :: proc(track: ^Track) -> ^SDL.AudioStream --- + GetTrackRemaining :: proc(track: ^Track) -> SDL.Sint64 --- + TrackMSToFrames :: proc(track: ^Track, ms: SDL.Sint64) -> SDL.Sint64 --- + TrackFramesToMS :: proc(track: ^Track, frames: SDL.Sint64) -> SDL.Sint64 --- + AudioMSToFrames :: proc(audio: ^Audio, ms: SDL.Sint64) -> SDL.Sint64 --- + AudioFramesToMS :: proc(audio: ^Audio, frames: SDL.Sint64) -> SDL.Sint64 --- + MSToFrames :: proc(sample_rate: c.int, ms: SDL.Sint64) -> SDL.Sint64 --- + FramesToMS :: proc(sample_rate: c.int, frames: SDL.Sint64) -> SDL.Sint64 --- + PlayTrack :: proc(track: ^Track, options: SDL.PropertiesID) -> c.bool --- + PlayTag :: proc(mixer: ^Mixer, tag: cstring, options: SDL.PropertiesID) -> c.bool --- + PlayAudio :: proc(mixer: ^Mixer, audio: ^Audio) -> c.bool --- + StopTrack :: proc(track: ^Track, fade_out_frames: SDL.Sint64) -> c.bool --- + StopAllTracks :: proc(mixer: ^Mixer, fade_out_ms: SDL.Sint64) -> c.bool --- + StopTag :: proc(mixer: ^Mixer, tag: cstring, fade_out_ms: SDL.Sint64) -> c.bool --- + PauseTrack :: proc(track: ^Track) -> c.bool --- + PauseAllTracks :: proc(mixer: ^Mixer) -> c.bool --- + PauseTag :: proc(mixer: ^Mixer, tag: cstring) -> c.bool --- + ResumeTrack :: proc(track: ^Track) -> c.bool --- + ResumeAllTracks :: proc(mixer: ^Mixer) -> c.bool --- + ResumeTag :: proc(mixer: ^Mixer, tag: cstring) -> c.bool --- + TrackPlaying :: proc(track: ^Track) -> c.bool --- + TrackPaused :: proc(track: ^Track) -> c.bool --- + SetMixerGain :: proc(mixer: ^Mixer, gain: c.float) -> c.bool --- + GetMixerGain :: proc(mixer: ^Mixer) -> c.float --- + SetTrackGain :: proc(track: ^Track, gain: c.float) -> c.bool --- + GetTrackGain :: proc(track: ^Track) -> c.float --- + SetTagGain :: proc(mixer: ^Mixer, tag: cstring, gain: c.float) -> c.bool --- + SetMixerFrequencyRatio :: proc(mixer: ^Mixer, ratio: c.float) -> c.bool --- + GetMixerFrequencyRatio :: proc(mixer: ^Mixer) -> c.float --- + SetTrackFrequencyRatio :: proc(track: ^Track, ratio: c.float) -> c.bool --- + GetTrackFrequencyRatio :: proc(track: ^Track) -> c.float --- + SetTrackOutputChannelMap :: proc(track: ^Track, chmap: [^]c.int, count: c.int) -> c.bool --- + SetTrackStereo :: proc(track: ^Track, gains: Maybe(^StereoGains)) -> c.bool --- + SetTrack3DPosition :: proc(track: ^Track, position: Maybe(^Point3D)) -> c.bool --- + GetTrack3DPosition :: proc(track: ^Track, position: ^Point3D) -> c.bool --- + CreateGroup :: proc(mixer: ^Mixer) -> ^Group --- + DestroyGroup :: proc(group: ^Group) --- + GetGroupProperties :: proc(group: ^Group) -> SDL.PropertiesID --- + GetGroupMixer :: proc(group: ^Group) -> ^Mixer --- + SetTrackGroup :: proc(track: ^Track, group: ^Group) -> c.bool --- + SetTrackStoppedCallback :: proc(track: ^Track, cb: TrackStoppedCallback, userdata: rawptr) -> c.bool --- + SetTrackRawCallback :: proc(track: ^Track, cb: TrackMixCallback, userdata: rawptr) -> c.bool --- + SetTrackCookedCallback :: proc(track: ^Track, cb: TrackMixCallback, userdata: rawptr) -> c.bool --- + SetGroupPostMixCallback :: proc(group: ^Group, cb: GroupMixCallback, userdata: rawptr) -> c.bool --- + SetPostMixCallback :: proc(mixer: ^Mixer, cb: PostMixCallback, userdata: rawptr) -> c.bool --- + Generate :: proc(mixer: ^Mixer, buffer: rawptr, buflen: c.int) -> c.int --- + CreateAudioDecoder :: proc(path: cstring, props: SDL.PropertiesID) -> ^AudioDecoder --- + CreateAudioDecoder_IO :: proc(io: ^SDL.IOStream, closeio: c.bool, props: SDL.PropertiesID) -> ^AudioDecoder --- + DestroyAudioDecoder :: proc(audiodecoder: ^AudioDecoder) --- + GetAudioDecoderProperties :: proc(audiodecoder: ^AudioDecoder) -> SDL.PropertiesID --- + GetAudioDecoderFormat :: proc(audiodecoder: ^AudioDecoder, spec: ^SDL.AudioSpec) -> c.bool --- + DecodeAudio :: proc(audiodecoder: ^AudioDecoder, buffer: rawptr, buflen: c.int, #by_ptr spec: SDL.AudioSpec) -> c.int --- +} diff --git a/vendor/sdl3/sdl3_atomic.odin b/vendor/sdl3/sdl3_atomic.odin index 178a44a5b..fefe8c861 100644 --- a/vendor/sdl3/sdl3_atomic.odin +++ b/vendor/sdl3/sdl3_atomic.odin @@ -36,7 +36,8 @@ foreign lib { CompareAndSwapAtomicU32 :: proc(a: ^AtomicU32, oldval, newval: Uint32) -> bool --- SetAtomicU32 :: proc(a: ^AtomicU32, v: Uint32) -> Uint32 --- GetAtomicU32 :: proc(a: ^AtomicU32) -> Uint32 --- + AddAtomicU32 :: proc(a: ^AtomicU32) -> Uint32 --- CompareAndSwapAtomicPointer :: proc(a: ^rawptr, oldval, newval: rawptr) -> bool --- SetAtomicPointer :: proc(a: ^rawptr, v: rawptr) -> rawptr --- GetAtomicPointer :: proc(a: ^rawptr) -> rawptr --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_audio.odin b/vendor/sdl3/sdl3_audio.odin index 045f4780e..72afd8c98 100644 --- a/vendor/sdl3/sdl3_audio.odin +++ b/vendor/sdl3/sdl3_audio.odin @@ -38,14 +38,14 @@ AudioFormat :: enum c.int { F32 = F32LE when BYTEORDER == LIL_ENDIAN else F32BE, } -@(require_results) AUDIO_BITSIZE :: proc "c" (x: AudioFormat) -> Uint16 { return (Uint16(x) & AUDIO_MASK_BITSIZE) } -@(require_results) AUDIO_BYTESIZE :: proc "c" (x: AudioFormat) -> Uint16 { return AUDIO_BITSIZE(x) / 8 } -@(require_results) AUDIO_ISFLOAT :: proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_FLOAT) != 0 } -@(require_results) AUDIO_ISBIGENDIAN :: proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_BIG_ENDIAN) != 0 } -@(require_results) AUDIO_ISLITTLEENDIAN :: proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISBIGENDIAN(x) } -@(require_results) AUDIO_ISSIGNED :: proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_SIGNED) != 0 } -@(require_results) AUDIO_ISINT :: proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISFLOAT(x) } -@(require_results) AUDIO_ISUNSIGNED :: proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISSIGNED(x) } +@(require_results) AUDIO_BITSIZE :: #force_inline proc "c" (x: AudioFormat) -> Uint16 { return (Uint16(x) & AUDIO_MASK_BITSIZE) } +@(require_results) AUDIO_BYTESIZE :: #force_inline proc "c" (x: AudioFormat) -> Uint16 { return AUDIO_BITSIZE(x) / 8 } +@(require_results) AUDIO_ISFLOAT :: #force_inline proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_FLOAT) != 0 } +@(require_results) AUDIO_ISBIGENDIAN :: #force_inline proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_BIG_ENDIAN) != 0 } +@(require_results) AUDIO_ISLITTLEENDIAN :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISBIGENDIAN(x) } +@(require_results) AUDIO_ISSIGNED :: #force_inline proc "c" (x: AudioFormat) -> bool { return (Uint16(x) & AUDIO_MASK_SIGNED) != 0 } +@(require_results) AUDIO_ISINT :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISFLOAT(x) } +@(require_results) AUDIO_ISUNSIGNED :: #force_inline proc "c" (x: AudioFormat) -> bool { return !AUDIO_ISSIGNED(x) } AudioDeviceID :: distinct Uint32 @@ -60,15 +60,18 @@ AudioSpec :: struct { } @(require_results) -AUDIO_FRAMESIZE :: proc "c" (x: AudioSpec) -> c.int { +AUDIO_FRAMESIZE :: #force_inline proc "c" (x: AudioSpec) -> c.int { return c.int(AUDIO_BYTESIZE(x.format)) * x.channels } AudioStream :: struct {} -AudioStreamCallback :: #type proc "c" (userdata: rawptr, stream: ^AudioStream, additional_amount, total_amount: c.int) -AudioPostmixCallback :: #type proc "c" (userdata: rawptr, spec: ^AudioSpec, buffer: [^]f32, buflen: c.int) +AudioStreamCallback :: #type proc "c" (userdata: rawptr, stream: ^AudioStream, additional_amount, total_amount: c.int) +AudioStreamDataCompleteCallback :: #type proc "c" (userdata: rawptr, buf: rawptr, buflen: c.int) +AudioPostmixCallback :: #type proc "c" (userdata: rawptr, spec: ^AudioSpec, buffer: [^]f32, buflen: c.int) + +AUDIOSTREAM_AUTO_CLEANUP_BOOLEAN :: "SDL.audiostream.auto_cleanup" @(default_calling_convention="c", link_prefix="SDL_") foreign lib { @@ -107,6 +110,8 @@ foreign lib { SetAudioStreamInputChannelMap :: proc(stream: ^AudioStream, chmap: [^]c.int, count: c.int) -> bool --- SetAudioStreamOutputChannelMap :: proc(stream: ^AudioStream, chmap: [^]c.int, count: c.int) -> bool --- PutAudioStreamData :: proc(stream: ^AudioStream, buf: rawptr, len: c.int) -> bool --- + PutAudioStreamDataNoCopy :: proc(stream: ^AudioStream, buf: rawptr, len: c.int, callback: AudioStreamDataCompleteCallback, userdata: rawptr) -> bool --- + PutAudioStreamPlanarData :: proc(stream: ^AudioStream, channel_buffers: [^]rawptr, num_channels, num_samples: c.int) -> bool --- GetAudioStreamData :: proc(stream: ^AudioStream, buf: rawptr, len: c.int) -> c.int --- GetAudioStreamAvailable :: proc(stream: ^AudioStream) -> c.int --- GetAudioStreamQueued :: proc(stream: ^AudioStream) -> c.int --- @@ -128,4 +133,4 @@ foreign lib { ConvertAudioSamples :: proc(src_spec: ^AudioSpec, src_data: [^]Uint8, src_len: c.int, dst_spec: ^AudioSpec, dst_data: ^[^]Uint8, dst_len: ^c.int) -> bool --- GetAudioFormatName :: proc(format: AudioFormat) -> cstring --- GetSilenceValueForFormat :: proc(format: AudioFormat) -> c.int --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_camera.odin b/vendor/sdl3/sdl3_camera.odin index 7d46bd2bd..a6a895245 100644 --- a/vendor/sdl3/sdl3_camera.odin +++ b/vendor/sdl3/sdl3_camera.odin @@ -21,6 +21,12 @@ CameraPosition :: enum c.int { BACK_FACING, } +CameraPermissionState :: enum c.int { + DENIED = -1, + PENDING, + APPROVED, +} + @(default_calling_convention="c", link_prefix="SDL_") foreign lib { GetNumCameraDrivers :: proc() -> c.int --- @@ -31,11 +37,11 @@ foreign lib { GetCameraName :: proc(instance_id: CameraID) -> cstring --- GetCameraPosition :: proc(instance_id: CameraID) -> CameraPosition --- OpenCamera :: proc(instance_id: CameraID, spec: ^CameraSpec) -> ^Camera --- - GetCameraPermissionState :: proc(camera: ^Camera) -> c.int --- + GetCameraPermissionState :: proc(camera: ^Camera) -> CameraPermissionState --- GetCameraID :: proc(camera: ^Camera) -> CameraID --- GetCameraProperties :: proc(camera: ^Camera) -> PropertiesID --- GetCameraFormat :: proc(camera: ^Camera, spec: ^CameraSpec) -> bool --- AcquireCameraFrame :: proc(camera: ^Camera, timestampNS: ^Uint64) -> ^Surface --- ReleaseCameraFrame :: proc(camera: ^Camera, frame: ^Surface) --- CloseCamera :: proc(camera: ^Camera) --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_cpuinfo.odin b/vendor/sdl3/sdl3_cpuinfo.odin index 959286c71..a97a5a324 100644 --- a/vendor/sdl3/sdl3_cpuinfo.odin +++ b/vendor/sdl3/sdl3_cpuinfo.odin @@ -24,4 +24,5 @@ foreign lib { HasLASX :: proc() -> bool --- GetSystemRAM :: proc() -> c.int --- GetSIMDAlignment :: proc() -> uint --- -} \ No newline at end of file + GetSystemPageSize :: proc() -> c.int --- +} diff --git a/vendor/sdl3/sdl3_events.odin b/vendor/sdl3/sdl3_events.odin index 2eb2a4505..7e871156e 100644 --- a/vendor/sdl3/sdl3_events.odin +++ b/vendor/sdl3/sdl3_events.odin @@ -46,9 +46,10 @@ EventType :: enum Uint32 { DISPLAY_MOVED, /**< Display has changed position */ DISPLAY_DESKTOP_MODE_CHANGED, /**< Display has changed desktop mode */ DISPLAY_CURRENT_MODE_CHANGED, /**< Display has changed current mode */ - DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */ + DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed usable bounds */ + DISPLAY_USABLE_BOUNDS_CHANGED, DISPLAY_FIRST = DISPLAY_ORIENTATION, - DISPLAY_LAST = DISPLAY_CONTENT_SCALE_CHANGED, + DISPLAY_LAST = DISPLAY_USABLE_BOUNDS_CHANGED, /* Window events */ /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */ @@ -94,6 +95,8 @@ EventType :: enum Uint32 { KEYBOARD_ADDED, /**< A new keyboard has been inserted into the system */ KEYBOARD_REMOVED, /**< A keyboard has been removed */ TEXT_EDITING_CANDIDATES, /**< Keyboard text editing candidates */ + SCREEN_KEYBOARD_SHOWN, /**< The on-screen keyboard has been shown */ + SCREEN_KEYBOARD_HIDDEN, /**< The on-screen keyboard has been hidden */ /* Mouse events */ MOUSE_MOTION = 0x400, /**< Mouse moved */ @@ -134,10 +137,15 @@ EventType :: enum Uint32 { FINGER_MOTION, FINGER_CANCELED, + /* Pinch events */ + PINCH_BEGIN = 0x710, /**< Pinch gesture started */ + PINCH_UPDATE, /**< Pinch gesture updated */ + PINCH_END, /**< Pinch gesture ended */ + /* 0x800, 0x801, and 0x802 were the Gesture events from SDL2. Do not reuse these values! sdl2-compat needs them! */ /* Clipboard events */ - CLIPBOARD_UPDATE = 0x900, /**< The clipboard or primary selection changed */ + CLIPBOARD_UPDATE = 0x900, /**< The clipboard changed */ /* Drag and drop events */ DROP_FILE = 0x1000, /**< The system requests a file open */ @@ -295,6 +303,8 @@ MouseWheelEvent :: struct { direction: MouseWheelDirection, /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ mouse_x: f32, /**< X coordinate, relative to window */ mouse_y: f32, /**< Y coordinate, relative to window */ + integer_x: i32, /**< The amount scrolled horizontally, accumulated to whole scroll "ticks" (added in 3.2.12) */ + integer_y: i32, /**< The amount scrolled vertically, accumulated to whole scroll "ticks" (added in 3.2.12) */ } JoyAxisEvent :: struct { @@ -429,6 +439,12 @@ TouchFingerEvent :: struct { windowID: WindowID, /**< The window underneath the finger, if any */ } +PinchFingerEvent :: struct { + using commonEvent: CommonEvent, + scale: f32, /**< The scale change since the last SDL_EVENT_PINCH_UPDATE. Scale < 1 is "zoom out". Scale > 1 is "zoom in". */ + windowID: WindowID, /**< The window underneath the finger, if any */ +} + PenProximityEvent :: struct { using commonEvent: CommonEvent, /**< SDL_EVENT_PEN_PROXIMITY_IN or SDL_EVENT_PEN_PROXIMITY_OUT */ windowID: WindowID, /**< The window with pen focus, if any */ @@ -506,7 +522,7 @@ QuitEvent :: struct { } UserEvent :: struct { - using commonEvent: CommonEvent, /**< SDL_EVENT_USER through SDL_EVENT_LAST-1, Uint32 because these are not in the SDL_EventType enumeration */ + using commonEvent: CommonEvent, /**< SDL_EVENT_USER through SDL_EVENT_LAST, Uint32 because these are not in the SDL_EventType enumeration */ windowID: WindowID, /**< The associated window if any */ code: Sint32, /**< User defined event code */ data1: rawptr, /**< User defined data pointer */ @@ -517,44 +533,84 @@ UserEvent :: struct { Event :: struct #raw_union { - type: EventType, /**< Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration */ - common: CommonEvent, /**< Common event data */ - display: DisplayEvent, /**< Display event data */ - window: WindowEvent, /**< Window event data */ - kdevice: KeyboardDeviceEvent, /**< Keyboard device change event data */ - key: KeyboardEvent, /**< Keyboard event data */ - edit: TextEditingEvent, /**< Text editing event data */ - edit_candidates: TextEditingCandidatesEvent, /**< Text editing candidates event data */ - text: TextInputEvent, /**< Text input event data */ - mdevice: MouseDeviceEvent, /**< Mouse device change event data */ - motion: MouseMotionEvent, /**< Mouse motion event data */ - button: MouseButtonEvent, /**< Mouse button event data */ - wheel: MouseWheelEvent, /**< Mouse wheel event data */ - jdevice: JoyDeviceEvent, /**< Joystick device change event data */ - jaxis: JoyAxisEvent, /**< Joystick axis event data */ - jball: JoyBallEvent, /**< Joystick ball event data */ - jhat: JoyHatEvent, /**< Joystick hat event data */ - jbutton: JoyButtonEvent, /**< Joystick button event data */ - jbattery: JoyBatteryEvent, /**< Joystick battery event data */ - gdevice: GamepadDeviceEvent, /**< Gamepad device event data */ - gaxis: GamepadAxisEvent, /**< Gamepad axis event data */ - gbutton: GamepadButtonEvent, /**< Gamepad button event data */ - gtouchpad: GamepadTouchpadEvent, /**< Gamepad touchpad event data */ - gsensor: GamepadSensorEvent, /**< Gamepad sensor event data */ - adevice: AudioDeviceEvent, /**< Audio device event data */ - cdevice: CameraDeviceEvent, /**< Camera device event data */ - sensor: SensorEvent, /**< Sensor event data */ - quit: QuitEvent, /**< Quit request event data */ - user: UserEvent, /**< Custom event data */ - tfinger: TouchFingerEvent, /**< Touch finger event data */ - pproximity: PenProximityEvent, /**< Pen proximity event data */ - ptouch: PenTouchEvent, /**< Pen tip touching event data */ - pmotion: PenMotionEvent, /**< Pen motion event data */ - pbutton: PenButtonEvent, /**< Pen button event data */ - paxis: PenAxisEvent, /**< Pen axis event data */ - render: RenderEvent, /**< Render event data */ - drop: DropEvent, /**< Drag and drop event data */ - clipboard: ClipboardEvent, /**< Clipboard event data */ + /**< Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration */ + type: EventType `raw_union_tag:"type=FIRST"`, + /**< Common event data */ + common: CommonEvent `raw_union_tag:"type=TERMINATE,LOW_MEMORY,WILL_ENTER_BACKGROUND,DID_ENTER_BACKGROUND,WILL_ENTER_FOREGROUND,DID_ENTER_FOREGROUND,LOCALE_CHANGED,SYSTEM_THEME_CHANGED,POLL_SENTINEL"`, + /**< Display event data */ + display: DisplayEvent `raw_union_tag:"type=DISPLAY_ORIENTATION,DISPLAY_ADDED,DISPLAY_REMOVED,DISPLAY_MOVED,DISPLAY_DESKTOP_MODE_CHANGED,DISPLAY_CURRENT_MODE_CHANGED,DISPLAY_CONTENT_SCALE_CHANGED"`, + /**< Window event data */ + window: WindowEvent `raw_union_tag:"type=WINDOW_SHOWN,WINDOW_HIDDEN,WINDOW_EXPOSED,WINDOW_MOVED,WINDOW_RESIZED,WINDOW_PIXEL_SIZE_CHANGED,WINDOW_METAL_VIEW_RESIZED,WINDOW_MINIMIZED,WINDOW_MAXIMIZED,WINDOW_RESTORED,WINDOW_MOUSE_ENTER,WINDOW_MOUSE_LEAVE,WINDOW_FOCUS_GAINED,WINDOW_FOCUS_LOST,WINDOW_CLOSE_REQUESTED,WINDOW_HIT_TEST,WINDOW_ICCPROF_CHANGED,WINDOW_DISPLAY_CHANGED,WINDOW_DISPLAY_SCALE_CHANGED,WINDOW_SAFE_AREA_CHANGED,WINDOW_OCCLUDED,WINDOW_ENTER_FULLSCREEN,WINDOW_LEAVE_FULLSCREEN,WINDOW_DESTROYED"`, + /**< Keyboard device change event data */ + kdevice: KeyboardDeviceEvent `raw_union_tag:"type=KEYMAP_CHANGED,KEYBOARD_ADDED,KEYBOARD_REMOVED"`, + /**< Keyboard event data */ + key: KeyboardEvent `raw_union_tag:"type=KEY_DOWN,KEY_UP"`, + /**< Text editing event data */ + edit: TextEditingEvent `raw_union_tag:"type=TEXT_EDITING"`, + /**< Text editing candidates event data */ + edit_candidates: TextEditingCandidatesEvent `raw_union_tag:"type=TEXT_EDITING_CANDIDATES"`, + /**< Text input event data */ + text: TextInputEvent `raw_union_tag:"type=TEXT_INPUT"`, + /**< Mouse device change event data */ + mdevice: MouseDeviceEvent `raw_union_tag:"type=MOUSE_ADDED,MOUSE_REMOVED"`, + /**< Mouse motion event data */ + motion: MouseMotionEvent `raw_union_tag:"type=MOUSE_MOTION"`, + /**< Mouse button event data */ + button: MouseButtonEvent `raw_union_tag:"type=MOUSE_BUTTON_DOWN,MOUSE_BUTTON_UP"`, + /**< Mouse wheel event data */ + wheel: MouseWheelEvent `raw_union_tag:"type=MOUSE_WHEEL"`, + /**< Joystick device change event data */ + jdevice: JoyDeviceEvent `raw_union_tag:"type=JOYSTICK_ADDED,JOYSTICK_REMOVED,JOYSTICK_UPDATE_COMPLETE"`, + /**< Joystick axis event data */ + jaxis: JoyAxisEvent `raw_union_tag:"type=JOYSTICK_AXIS_MOTION"`, + /**< Joystick ball event data */ + jball: JoyBallEvent `raw_union_tag:"type=JOYSTICK_BALL_MOTION"`, + /**< Joystick hat event data */ + jhat: JoyHatEvent `raw_union_tag:"type=JOYSTICK_HAT_MOTION"`, + /**< Joystick button event data */ + jbutton: JoyButtonEvent `raw_union_tag:"type=JOYSTICK_BUTTON_DOWN,JOYSTICK_BUTTON_UP"`, + /**< Joystick battery event data */ + jbattery: JoyBatteryEvent `raw_union_tag:"type=JOYSTICK_BATTERY_UPDATED"`, + /**< Gamepad device event data */ + gdevice: GamepadDeviceEvent `raw_union_tag:"type=GAMEPAD_ADDED,GAMEPAD_REMOVED,GAMEPAD_REMAPPED,GAMEPAD_UPDATE_COMPLETE,GAMEPAD_STEAM_HANDLE_UPDATED"`, + /**< Gamepad axis event data */ + gaxis: GamepadAxisEvent `raw_union_tag:"type=GAMEPAD_AXIS_MOTION"`, + /**< Gamepad button event data */ + gbutton: GamepadButtonEvent `raw_union_tag:"type=GAMEPAD_BUTTON_DOWN,GAMEPAD_BUTTON_UP"`, + /**< Gamepad touchpad event data */ + gtouchpad: GamepadTouchpadEvent `raw_union_tag:"type=GAMEPAD_TOUCHPAD_DOWN,GAMEPAD_TOUCHPAD_MOTION,GAMEPAD_TOUCHPAD_UP"`, + /**< Gamepad sensor event data */ + gsensor: GamepadSensorEvent `raw_union_tag:"type=GAMEPAD_SENSOR_UPDATE"`, + /**< Audio device event data */ + adevice: AudioDeviceEvent `raw_union_tag:"type=AUDIO_DEVICE_ADDED,AUDIO_DEVICE_REMOVED,AUDIO_DEVICE_FORMAT_CHANGED"`, + /**< Camera device event data */ + cdevice: CameraDeviceEvent `raw_union_tag:"type=CAMERA_DEVICE_ADDED,CAMERA_DEVICE_REMOVED,CAMERA_DEVICE_APPROVED,CAMERA_DEVICE_DENIED"`, + /**< Sensor event data */ + sensor: SensorEvent `raw_union_tag:"type=SENSOR_UPDATE"`, + /**< Quit request event data */ + quit: QuitEvent `raw_union_tag:"type=QUIT"`, + /**< Custom event data */ + user: UserEvent `raw_union_tag:"type=USER"`, + /**< Touch finger event data */ + tfinger: TouchFingerEvent `raw_union_tag:"type=FINGER_DOWN,FINGER_UP,FINGER_MOTION,FINGER_CANCELED"`, + /**< Pinch event data */ + pinch: PinchFingerEvent `raw_union_tag:"type=PINCH_BEGIN,PINCH_UPDATE,PINCH_END"`, + /**< Pen proximity event data */ + pproximity: PenProximityEvent `raw_union_tag:"type=PEN_PROXIMITY_IN,PEN_PROXIMITY_OUT"`, + /**< Pen tip touching event data */ + ptouch: PenTouchEvent `raw_union_tag:"type=PEN_DOWN,PEN_UP"`, + /**< Pen motion event data */ + pmotion: PenMotionEvent `raw_union_tag:"type=PEN_MOTION"`, + /**< Pen button event data */ + pbutton: PenButtonEvent `raw_union_tag:"type=PEN_BUTTON_DOWN,PEN_BUTTON_UP"`, + /**< Pen axis event data */ + paxis: PenAxisEvent `raw_union_tag:"type=PEN_AXIS"`, + /**< Render event data */ + render: RenderEvent `raw_union_tag:"type=RENDER_TARGETS_RESET,RENDER_DEVICE_RESET,RENDER_DEVICE_LOST"`, + /**< Drag and drop event data */ + drop: DropEvent `raw_union_tag:"type=DROP_FILE,DROP_TEXT,DROP_BEGIN,DROP_COMPLETE,DROP_POSITION"`, + /**< Clipboard event data */ + clipboard: ClipboardEvent `raw_union_tag:"type=CLIPBOARD_UPDATE"`, /* This is necessary for ABI compatibility between Visual C++ and GCC. Visual C++ will respect the push pack pragma and use 52 bytes (size of @@ -586,23 +642,24 @@ EventFilter :: proc "c" (userdata: rawptr, event: ^Event) -> bool @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { - PumpEvents :: proc() --- - PeepEvents :: proc(events: [^]Event, numevents: c.int, action: EventAction, minType, maxType: EventType) -> int --- - HasEvent :: proc(type: EventType) -> bool --- - HasEvents :: proc(minType, maxType: EventType) -> bool --- - FlushEvent :: proc(type: EventType) --- - FlushEvents :: proc(minType, maxType: EventType) --- - PollEvent :: proc(event: ^Event) -> bool --- - WaitEvent :: proc(event: ^Event) -> bool --- - WaitEventTimeout :: proc(event: ^Event, timeoutMS: Sint32) -> bool --- - PushEvent :: proc(event: ^Event) -> bool --- - SetEventFilter :: proc(filter: EventFilter, userdata: rawptr) --- - GetEventFilter :: proc(filter: ^EventFilter, userdata: ^rawptr) -> bool --- - AddEventWatch :: proc(filter: EventFilter, userdata: rawptr) -> bool --- - RemoveEventWatch :: proc(filter: EventFilter, userdata: rawptr) --- - FilterEvents :: proc(filter: EventFilter, userdata: rawptr) --- - SetEventEnabled :: proc(type: EventType, enabled: bool) --- - EventEnabled :: proc(type: EventType) -> bool --- - RegisterEvents :: proc(numevents: c.int) -> Uint32 --- - GetWindowFromEvent :: proc(#by_ptr event: Event) -> ^Window --- -} \ No newline at end of file + PumpEvents :: proc() --- + PeepEvents :: proc(events: [^]Event, numevents: c.int, action: EventAction, minType, maxType: EventType) -> int --- + HasEvent :: proc(type: EventType) -> bool --- + HasEvents :: proc(minType, maxType: EventType) -> bool --- + FlushEvent :: proc(type: EventType) --- + FlushEvents :: proc(minType, maxType: EventType) --- + PollEvent :: proc(event: ^Event) -> bool --- + WaitEvent :: proc(event: ^Event) -> bool --- + WaitEventTimeout :: proc(event: ^Event, timeoutMS: Sint32) -> bool --- + PushEvent :: proc(event: ^Event) -> bool --- + SetEventFilter :: proc(filter: EventFilter, userdata: rawptr) --- + GetEventFilter :: proc(filter: ^EventFilter, userdata: ^rawptr) -> bool --- + AddEventWatch :: proc(filter: EventFilter, userdata: rawptr) -> bool --- + RemoveEventWatch :: proc(filter: EventFilter, userdata: rawptr) --- + FilterEvents :: proc(filter: EventFilter, userdata: rawptr) --- + SetEventEnabled :: proc(type: EventType, enabled: bool) --- + EventEnabled :: proc(type: EventType) -> bool --- + RegisterEvents :: proc(numevents: c.int) -> Uint32 --- + GetWindowFromEvent :: proc(#by_ptr event: Event) -> ^Window --- + GetEventDescription :: proc(#by_ptr event: Event, buf: [^]u8, buflen: c.int) -> c.int --- +} diff --git a/vendor/sdl3/sdl3_gamepad.odin b/vendor/sdl3/sdl3_gamepad.odin index 225accaee..2366f8704 100644 --- a/vendor/sdl3/sdl3_gamepad.odin +++ b/vendor/sdl3/sdl3_gamepad.odin @@ -81,29 +81,29 @@ GamepadBindingType :: enum c.int { GamepadBinding :: struct { input_type: GamepadBindingType, input: struct #raw_union { - button: c.int, + button: c.int `raw_union_tag:"input_type=.BUTTON"`, axis: struct { axis: c.int, axis_min: c.int, axis_max: c.int, - }, + } `raw_union_tag:"input_type=.AXIS"`, hat: struct { hat: c.int, hat_mask: c.int, - }, + } `raw_union_tag:"input_type=.HAT"`, }, output_type: GamepadBindingType, output: struct #raw_union { - button: GamepadButton, + button: GamepadButton `raw_union_tag:"output_type=.BUTTON"`, axis: struct { axis: GamepadAxis, axis_min: c.int, axis_max: c.int, - }, + } `raw_union_tag:"output_type=.AXIS"`, }, } diff --git a/vendor/sdl3/sdl3_gpu.odin b/vendor/sdl3/sdl3_gpu.odin index ec414f98e..18b872e95 100644 --- a/vendor/sdl3/sdl3_gpu.odin +++ b/vendor/sdl3/sdl3_gpu.odin @@ -46,7 +46,7 @@ GPUIndexElementSize :: enum c.int { GPUTextureFormat :: enum c.int { INVALID, - /* Unsigned Normalized Float Color Formats */ + /* Unsigned Normalized Float Color Formats */ A8_UNORM, R8_UNORM, R8G8_UNORM, @@ -59,34 +59,41 @@ GPUTextureFormat :: enum c.int { B5G5R5A1_UNORM, B4G4R4A4_UNORM, B8G8R8A8_UNORM, - /* Compressed Unsigned Normalized Float Color Formats */ + + /* Compressed Unsigned Normalized Float Color Formats */ BC1_RGBA_UNORM, BC2_RGBA_UNORM, BC3_RGBA_UNORM, BC4_R_UNORM, BC5_RG_UNORM, BC7_RGBA_UNORM, - /* Compressed Signed Float Color Formats */ + + /* Compressed Signed Float Color Formats */ BC6H_RGB_FLOAT, - /* Compressed Unsigned Float Color Formats */ + + /* Compressed Unsigned Float Color Formats */ BC6H_RGB_UFLOAT, - /* Signed Normalized Float Color Formats */ + + /* Signed Normalized Float Color Formats */ R8_SNORM, R8G8_SNORM, R8G8B8A8_SNORM, R16_SNORM, R16G16_SNORM, R16G16B16A16_SNORM, - /* Signed Float Color Formats */ + + /* Signed Float Color Formats */ R16_FLOAT, R16G16_FLOAT, R16G16B16A16_FLOAT, R32_FLOAT, R32G32_FLOAT, R32G32B32A32_FLOAT, - /* Unsigned Float Color Formats */ + + /* Unsigned Float Color Formats */ R11G11B10_UFLOAT, - /* Unsigned Integer Color Formats */ + + /* Unsigned Integer Color Formats */ R8_UINT, R8G8_UINT, R8G8B8A8_UINT, @@ -96,7 +103,8 @@ GPUTextureFormat :: enum c.int { R32_UINT, R32G32_UINT, R32G32B32A32_UINT, - /* Signed Integer Color Formats */ + + /* Signed Integer Color Formats */ R8_INT, R8G8_INT, R8G8B8A8_INT, @@ -106,21 +114,25 @@ GPUTextureFormat :: enum c.int { R32_INT, R32G32_INT, R32G32B32A32_INT, - /* SRGB Unsigned Normalized Color Formats */ + + /* SRGB Unsigned Normalized Color Formats */ R8G8B8A8_UNORM_SRGB, B8G8R8A8_UNORM_SRGB, - /* Compressed SRGB Unsigned Normalized Color Formats */ + + /* Compressed SRGB Unsigned Normalized Color Formats */ BC1_RGBA_UNORM_SRGB, BC2_RGBA_UNORM_SRGB, BC3_RGBA_UNORM_SRGB, BC7_RGBA_UNORM_SRGB, - /* Depth Formats */ + + /* Depth Formats */ D16_UNORM, D24_UNORM, D32_FLOAT, D24_UNORM_S8_UINT, D32_FLOAT_S8_UINT, - /* Compressed ASTC Normalized Float Color Formats*/ + + /* Compressed ASTC Normalized Float Color Formats*/ ASTC_4x4_UNORM, ASTC_5x4_UNORM, ASTC_5x5_UNORM, @@ -135,7 +147,8 @@ GPUTextureFormat :: enum c.int { ASTC_10x10_UNORM, ASTC_12x10_UNORM, ASTC_12x12_UNORM, - /* Compressed SRGB ASTC Normalized Float Color Formats*/ + + /* Compressed SRGB ASTC Normalized Float Color Formats*/ ASTC_4x4_UNORM_SRGB, ASTC_5x4_UNORM_SRGB, ASTC_5x5_UNORM_SRGB, @@ -150,7 +163,8 @@ GPUTextureFormat :: enum c.int { ASTC_10x10_UNORM_SRGB, ASTC_12x10_UNORM_SRGB, ASTC_12x12_UNORM_SRGB, - /* Compressed ASTC Signed Float Color Formats*/ + + /* Compressed ASTC Signed Float Color Formats*/ ASTC_4x4_FLOAT, ASTC_5x4_FLOAT, ASTC_5x5_FLOAT, @@ -610,10 +624,10 @@ GPURasterizerState :: struct { GPUMultisampleState :: struct { - sample_count: GPUSampleCount, /**< The number of samples to be used in rasterization. */ - sample_mask: Uint32, /**< Reserved for future use. Must be set to 0. */ - enable_mask: bool, /**< Reserved for future use. Must be set to false. */ - _: Uint8, + sample_count: GPUSampleCount, /**< The number of samples to be used in rasterization. */ + sample_mask: Uint32, /**< Reserved for future use. Must be set to 0. */ + enable_mask: bool, /**< Reserved for future use. Must be set to false. */ + enable_alpha_to_coverage: bool, /**< true enables the alpha-to-coverage feature. */ _: Uint8, _: Uint8, } @@ -704,8 +718,8 @@ GPUDepthStencilTargetInfo :: struct { stencil_store_op: GPUStoreOp, /**< What is done with the stencil results of the render pass. */ cycle: bool, /**< true cycles the texture if the texture is bound and any load ops are not LOAD */ clear_stencil: Uint8, /**< The value to clear the stencil component to at the beginning of the render pass. Ignored if GPU_LOADOP_CLEAR is not used. */ - _: Uint8, - _: Uint8, + mip_level: Uint8, /**< The mip level to use as the depth stencil target. */ + layer: Uint8, /**< The layer index to use as the depth stencil target. */ } @@ -751,30 +765,56 @@ GPUStorageTextureReadWriteBinding :: struct { } -PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN :: "SDL.gpu.device.create.debugmode" -PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN :: "SDL.gpu.device.create.preferlowpower" -PROP_GPU_DEVICE_CREATE_NAME_STRING :: "SDL.gpu.device.create.name" -PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN :: "SDL.gpu.device.create.shaders.private" -PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN :: "SDL.gpu.device.create.shaders.spirv" -PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN :: "SDL.gpu.device.create.shaders.dxbc" -PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN :: "SDL.gpu.device.create.shaders.dxil" -PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN :: "SDL.gpu.device.create.shaders.msl" -PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN :: "SDL.gpu.device.create.shaders.metallib" -PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING :: "SDL.gpu.device.create.d3d12.semantic" +PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN :: "SDL.gpu.device.create.debugmode" +PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN :: "SDL.gpu.device.create.preferlowpower" +PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN :: "SDL.gpu.device.create.verbose" +PROP_GPU_DEVICE_CREATE_NAME_STRING :: "SDL.gpu.device.create.name" +PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN :: "SDL.gpu.device.create.feature.clip_distance" +PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN :: "SDL.gpu.device.create.feature.depth_clamping" +PROP_GPU_DEVICE_CREATE_FEATURE_INDIRECT_DRAW_FIRST_INSTANCE_BOOLEAN :: "SDL.gpu.device.create.feature.indirect_draw_first_instance" +PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN :: "SDL.gpu.device.create.feature.anisotropy" +PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN :: "SDL.gpu.device.create.shaders.private" +PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN :: "SDL.gpu.device.create.shaders.spirv" +PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN :: "SDL.gpu.device.create.shaders.dxbc" +PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN :: "SDL.gpu.device.create.shaders.dxil" +PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN :: "SDL.gpu.device.create.shaders.msl" +PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN :: "SDL.gpu.device.create.shaders.metallib" +PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN :: "SDL.gpu.device.create.d3d12.allowtier1resourcebinding" +PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING :: "SDL.gpu.device.create.d3d12.semantic" +PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_VERSION_NUMBER :: "SDL.gpu.device.create.d3d12.agility_sdk_version" +PROP_GPU_DEVICE_CREATE_D3D12_AGILITY_SDK_PATH_STRING :: "SDL.gpu.device.create.d3d12.agility_sdk_path" +PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION_BOOLEAN :: "SDL.gpu.device.create.vulkan.requirehardwareacceleration" +PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER :: "SDL.gpu.device.create.vulkan.options" +PROP_GPU_DEVICE_CREATE_METAL_ALLOW_MACFAMILY1_BOOLEAN :: "SDL.gpu.device.create.metal.allowmacfamily1" -PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING :: "SDL.gpu.computepipeline.create.name" -PROP_GPU_GRAPHICSPIPELINE_CREATE_NAME_STRING :: "SDL.gpu.graphicspipeline.create.name" -PROP_GPU_SAMPLER_CREATE_NAME_STRING :: "SDL.gpu.sampler.create.name" -PROP_GPU_SHADER_CREATE_NAME_STRING :: "SDL.gpu.shader.create.name" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.r" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.g" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.b" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.a" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.depth" -PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_UINT8 :: "SDL.gpu.texture.create.d3d12.clear.stencil" -PROP_GPU_TEXTURE_CREATE_NAME_STRING :: "SDL.gpu.texture.create.name" -PROP_GPU_BUFFER_CREATE_NAME_STRING :: "SDL.gpu.buffer.create.name" -PROP_GPU_TRANSFERBUFFER_CREATE_NAME_STRING :: "SDL.gpu.transferbuffer.create.name" +GPUVulkanOptions :: struct { + vulkan_api_version: Uint32, /**< The Vulkan API version to request for the instance. Use Vulkan's VK_MAKE_VERSION or VK_MAKE_API_VERSION. */ + feature_list: rawptr, /**< Pointer to the first element of a chain of Vulkan feature structs. (Requires API version 1.1 or higher.)*/ + vulkan_10_physical_device_features: rawptr, /**< Pointer to a VkPhysicalDeviceFeatures struct to enable additional Vulkan 1.0 features. */ + device_extension_count: Uint32, /**< Number of additional device extensions to require. */ + device_extension_names: [^]cstring, /**< Pointer to a list of additional device extensions to require. */ + instance_extension_count: Uint32, /**< Number of additional instance extensions to require. */ + instance_extension_names: [^]cstring, /**< Pointer to a list of additional instance extensions to require. */ +} + +PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING :: "SDL.gpu.computepipeline.create.name" +PROP_GPU_GRAPHICSPIPELINE_CREATE_NAME_STRING :: "SDL.gpu.graphicspipeline.create.name" +PROP_GPU_SAMPLER_CREATE_NAME_STRING :: "SDL.gpu.sampler.create.name" +PROP_GPU_SHADER_CREATE_NAME_STRING :: "SDL.gpu.shader.create.name" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.r" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.g" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.b" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.a" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT :: "SDL.gpu.texture.create.d3d12.clear.depth" +PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER :: "SDL.gpu.texture.create.d3d12.clear.stencil" +PROP_GPU_TEXTURE_CREATE_NAME_STRING :: "SDL.gpu.texture.create.name" +PROP_GPU_BUFFER_CREATE_NAME_STRING :: "SDL.gpu.buffer.create.name" +PROP_GPU_TRANSFERBUFFER_CREATE_NAME_STRING :: "SDL.gpu.transferbuffer.create.name" + +PROP_GPU_DEVICE_NAME_STRING :: "SDL.gpu.device.name" +PROP_GPU_DEVICE_DRIVER_NAME_STRING :: "SDL.gpu.device.driver_name" +PROP_GPU_DEVICE_DRIVER_VERSION_STRING :: "SDL.gpu.device.driver_version" +PROP_GPU_DEVICE_DRIVER_INFO_STRING :: "SDL.gpu.device.driver_info" @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { @@ -787,6 +827,7 @@ foreign lib { GetGPUDriver :: proc(index: c.int) -> cstring --- GetGPUDeviceDriver :: proc(device: ^GPUDevice) -> cstring --- GetGPUShaderFormats :: proc(device: ^GPUDevice) -> GPUShaderFormat --- + GetGPUDeviceProperties :: proc(device: ^GPUDevice) -> PropertiesID --- CreateGPUComputePipeline :: proc(device: ^GPUDevice, #by_ptr createinfo: GPUComputePipelineCreateInfo) -> ^GPUComputePipeline --- CreateGPUGraphicsPipeline :: proc(device: ^GPUDevice, #by_ptr createinfo: GPUGraphicsPipelineCreateInfo) -> ^GPUGraphicsPipeline --- CreateGPUSampler :: proc(device: ^GPUDevice, #by_ptr createinfo: GPUSamplerCreateInfo) -> ^GPUSampler --- @@ -870,6 +911,8 @@ foreign lib { GPUTextureSupportsFormat :: proc(device: ^GPUDevice, format: GPUTextureFormat, type: GPUTextureType, usage: GPUTextureUsageFlags) -> bool --- GPUTextureSupportsSampleCount :: proc(device: ^GPUDevice, format: GPUTextureFormat, sample_count: GPUSampleCount) -> bool --- CalculateGPUTextureFormatSize :: proc(format: GPUTextureFormat, width, height: Uint32, depth_or_layer_count: Uint32) -> Uint32 --- + GetPixelFormatFromGPUTextureFormat :: proc(format: GPUTextureFormat) -> PixelFormat --- + GetGPUTextureFormatFromPixelFormat :: proc(format: PixelFormat) -> GPUTextureFormat --- } diff --git a/vendor/sdl3/sdl3_haptic.odin b/vendor/sdl3/sdl3_haptic.odin index d5efadcf3..adf055ee6 100644 --- a/vendor/sdl3/sdl3_haptic.odin +++ b/vendor/sdl3/sdl3_haptic.odin @@ -5,6 +5,7 @@ import "core:c" Haptic :: struct {} HapticType :: Uint16 +HapticEffectId :: c.int HAPTIC_CONSTANT :: 1<<0 HAPTIC_SINE :: 1<<1 @@ -215,12 +216,12 @@ foreign lib { GetHapticFeatures :: proc(haptic: ^Haptic) -> Uint32 --- GetNumHapticAxes :: proc(haptic: ^Haptic) -> c.int --- HapticEffectSupported :: proc(haptic: ^Haptic, #by_ptr effect: HapticEffect) -> bool --- - CreateHapticEffect :: proc(haptic: ^Haptic, #by_ptr effect: HapticEffect) -> c.int --- - UpdateHapticEffect :: proc(haptic: ^Haptic, effect: c.int, #by_ptr data: HapticEffect) -> bool --- - RunHapticEffect :: proc(haptic: ^Haptic, effect: c.int, iterations: Uint32) -> bool --- - StopHapticEffect :: proc(haptic: ^Haptic, effect: c.int) -> bool --- - DestroyHapticEffect :: proc(haptic: ^Haptic, effect: c.int) --- - GetHapticEffectStatus :: proc(haptic: ^Haptic, effect: c.int) -> bool --- + CreateHapticEffect :: proc(haptic: ^Haptic, #by_ptr effect: HapticEffect) -> HapticEffectId --- + UpdateHapticEffect :: proc(haptic: ^Haptic, effect: HapticEffectId, #by_ptr data: HapticEffect) -> bool --- + RunHapticEffect :: proc(haptic: ^Haptic, effect: HapticEffectId, iterations: Uint32) -> bool --- + StopHapticEffect :: proc(haptic: ^Haptic, effect: HapticEffectId) -> bool --- + DestroyHapticEffect :: proc(haptic: ^Haptic, effect: HapticEffectId) --- + GetHapticEffectStatus :: proc(haptic: ^Haptic, effect: HapticEffectId) -> bool --- SetHapticGain :: proc(haptic: ^Haptic, gain: c.int) -> bool --- SetHapticAutocenter :: proc(haptic: ^Haptic, autocenter: c.int) -> bool --- PauseHaptic :: proc(haptic: ^Haptic) -> bool --- @@ -230,4 +231,4 @@ foreign lib { InitHapticRumble :: proc(haptic: ^Haptic) -> bool --- PlayHapticRumble :: proc(haptic: ^Haptic, strength: f32, length: Uint32) -> bool --- StopHapticRumble :: proc(haptic: ^Haptic) -> bool --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_hidapi.odin b/vendor/sdl3/sdl3_hidapi.odin index 6817bffa2..71286cb3d 100644 --- a/vendor/sdl3/sdl3_hidapi.odin +++ b/vendor/sdl3/sdl3_hidapi.odin @@ -75,6 +75,7 @@ hid_device_info :: struct { next: ^hid_device_info, } +PROP_HIDAPI_LIBUSB_DEVICE_HANDLE_POINTER :: "SDL.hidapi.libusb.device.handle" @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { @@ -85,6 +86,7 @@ foreign lib { hid_free_enumeration :: proc(devs: ^hid_device_info) --- hid_open :: proc(vendor_id, product_id: c.ushort, serial_number: [^]c.wchar_t) -> ^hid_device --- hid_open_path :: proc(path: cstring) -> ^hid_device --- + hid_get_properties :: proc(dev: ^hid_device) -> PropertiesID --- hid_write :: proc(dev: ^hid_device, data: [^]byte, length: uint) -> c.int --- hid_read_timeout :: proc(dev: ^hid_device, data: [^]byte, length: uint, milliseconds: c.int) -> c.int --- hid_read :: proc(dev: ^hid_device, data: [^]byte, length: uint) -> c.int --- @@ -100,4 +102,4 @@ foreign lib { hid_get_device_info :: proc(dev: ^hid_device) -> ^hid_device_info --- hid_get_report_descriptor :: proc(dev: ^hid_device, buf: [^]byte, buf_size: uint) -> c.int --- hid_ble_scan :: proc(active: bool) --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_hints.odin b/vendor/sdl3/sdl3_hints.odin index 987010c57..64fe486a1 100644 --- a/vendor/sdl3/sdl3_hints.odin +++ b/vendor/sdl3/sdl3_hints.odin @@ -20,6 +20,7 @@ HINT_AUDIO_DEVICE_APP_ICON_NAME :: "SDL_AUDIO_DEVICE_APP_ICON_NAME" HINT_AUDIO_DEVICE_SAMPLE_FRAMES :: "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" HINT_AUDIO_DEVICE_STREAM_NAME :: "SDL_AUDIO_DEVICE_STREAM_NAME" HINT_AUDIO_DEVICE_STREAM_ROLE :: "SDL_AUDIO_DEVICE_STREAM_ROLE" +HINT_AUDIO_DEVICE_RAW_STREAM :: "SDL_AUDIO_DEVICE_RAW_STREAM" HINT_AUDIO_DISK_INPUT_FILE :: "SDL_AUDIO_DISK_INPUT_FILE" HINT_AUDIO_DISK_OUTPUT_FILE :: "SDL_AUDIO_DISK_OUTPUT_FILE" HINT_AUDIO_DISK_TIMESCALE :: "SDL_AUDIO_DISK_TIMESCALE" @@ -36,6 +37,7 @@ HINT_CPU_FEATURE_MASK :: "SDL_CPU_FEATURE_MASK" HINT_JOYSTICK_DIRECTINPUT :: "SDL_JOYSTICK_DIRECTINPUT" HINT_FILE_DIALOG_DRIVER :: "SDL_FILE_DIALOG_DRIVER" HINT_DISPLAY_USABLE_BOUNDS :: "SDL_DISPLAY_USABLE_BOUNDS" +HINT_INVALID_PARAM_CHECKS :: "SDL_INVALID_PARAM_CHECKS" HINT_EMSCRIPTEN_ASYNCIFY :: "SDL_EMSCRIPTEN_ASYNCIFY" HINT_EMSCRIPTEN_CANVAS_SELECTOR :: "SDL_EMSCRIPTEN_CANVAS_SELECTOR" HINT_EMSCRIPTEN_KEYBOARD_ELEMENT :: "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" @@ -56,6 +58,7 @@ HINT_GDK_TEXTINPUT_MAX_LENGTH :: "SDL_GDK_TEXTINPUT_MAX_LENGTH" HINT_GDK_TEXTINPUT_SCOPE :: "SDL_GDK_TEXTINPUT_SCOPE" HINT_GDK_TEXTINPUT_TITLE :: "SDL_GDK_TEXTINPUT_TITLE" HINT_HIDAPI_LIBUSB :: "SDL_HIDAPI_LIBUSB" +HINT_HIDAPI_LIBUSB_GAMECUBE :: "SDL_HIDAPI_LIBUSB_GAMECUBE" HINT_HIDAPI_LIBUSB_WHITELIST :: "SDL_HIDAPI_LIBUSB_WHITELIST" HINT_HIDAPI_UDEV :: "SDL_HIDAPI_UDEV" HINT_GPU_DRIVER :: "SDL_GPU_DRIVER" @@ -95,9 +98,15 @@ HINT_JOYSTICK_HIDAPI_STEAM :: "SDL_JOYSTICK_HIDAPI_STEAM" HINT_JOYSTICK_HIDAPI_STEAM_HOME_LED :: "SDL_JOYSTICK_HIDAPI_STEAM_HOME_LED" HINT_JOYSTICK_HIDAPI_STEAMDECK :: "SDL_JOYSTICK_HIDAPI_STEAMDECK" HINT_JOYSTICK_HIDAPI_STEAM_HORI :: "SDL_JOYSTICK_HIDAPI_STEAM_HORI" +HINT_JOYSTICK_HIDAPI_LG4FF :: "SDL_JOYSTICK_HIDAPI_LG4FF" +HINT_JOYSTICK_HIDAPI_8BITDO :: "SDL_JOYSTICK_HIDAPI_8BITDO" +HINT_JOYSTICK_HIDAPI_SINPUT :: "SDL_JOYSTICK_HIDAPI_SINPUT" +HINT_JOYSTICK_HIDAPI_ZUIKI :: "SDL_JOYSTICK_HIDAPI_ZUIKI" +HINT_JOYSTICK_HIDAPI_FLYDIGI :: "SDL_JOYSTICK_HIDAPI_FLYDIGI" HINT_JOYSTICK_HIDAPI_SWITCH :: "SDL_JOYSTICK_HIDAPI_SWITCH" HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED :: "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED :: "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" +HINT_JOYSTICK_HIDAPI_SWITCH2 :: "SDL_JOYSTICK_HIDAPI_SWITCH2" HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS :: "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS" HINT_JOYSTICK_HIDAPI_WII :: "SDL_JOYSTICK_HIDAPI_WII" HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED :: "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED" @@ -107,6 +116,8 @@ HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED :: "SDL_JOYSTICK_HIDAPI_XBOX_360_PL HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS :: "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS" HINT_JOYSTICK_HIDAPI_XBOX_ONE :: "SDL_JOYSTICK_HIDAPI_XBOX_ONE" HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED :: "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" +HINT_JOYSTICK_HIDAPI_GIP :: "SDL_JOYSTICK_HIDAPI_GIP" +HINT_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA :: "SDL_JOYSTICK_HIDAPI_GIP_RESET_FOR_METADATA" HINT_JOYSTICK_IOKIT :: "SDL_JOYSTICK_IOKIT" HINT_JOYSTICK_LINUX_CLASSIC :: "SDL_JOYSTICK_LINUX_CLASSIC" HINT_JOYSTICK_LINUX_DEADZONES :: "SDL_JOYSTICK_LINUX_DEADZONES" @@ -127,17 +138,20 @@ HINT_JOYSTICK_HAPTIC_AXES :: "SDL_JOYSTICK_HAPTIC_AXES" HINT_KEYCODE_OPTIONS :: "SDL_KEYCODE_OPTIONS" HINT_KMSDRM_DEVICE_INDEX :: "SDL_KMSDRM_DEVICE_INDEX" HINT_KMSDRM_REQUIRE_DRM_MASTER :: "SDL_KMSDRM_REQUIRE_DRM_MASTER" +HINT_KMSDRM_ATOMIC :: "SDL_KMSDRM_ATOMIC" HINT_LOGGING :: "SDL_LOGGING" HINT_MAC_BACKGROUND_APP :: "SDL_MAC_BACKGROUND_APP" HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK :: "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK" HINT_MAC_OPENGL_ASYNC_DISPATCH :: "SDL_MAC_OPENGL_ASYNC_DISPATCH" HINT_MAC_OPTION_AS_ALT :: "SDL_MAC_OPTION_AS_ALT" HINT_MAC_SCROLL_MOMENTUM :: "SDL_MAC_SCROLL_MOMENTUM" +HINT_MAC_PRESS_AND_HOLD :: "SDL_MAC_PRESS_AND_HOLD" HINT_MAIN_CALLBACK_RATE :: "SDL_MAIN_CALLBACK_RATE" HINT_MOUSE_AUTO_CAPTURE :: "SDL_MOUSE_AUTO_CAPTURE" HINT_MOUSE_DOUBLE_CLICK_RADIUS :: "SDL_MOUSE_DOUBLE_CLICK_RADIUS" HINT_MOUSE_DOUBLE_CLICK_TIME :: "SDL_MOUSE_DOUBLE_CLICK_TIME" HINT_MOUSE_DEFAULT_SYSTEM_CURSOR :: "SDL_MOUSE_DEFAULT_SYSTEM_CURSOR" +HINT_MOUSE_DPI_SCALE_CURSORS :: "SDL_MOUSE_DPI_SCALE_CURSORS" HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE :: "SDL_MOUSE_EMULATE_WARP_WITH_RELATIVE" HINT_MOUSE_FOCUS_CLICKTHROUGH :: "SDL_MOUSE_FOCUS_CLICKTHROUGH" HINT_MOUSE_NORMAL_SPEED_SCALE :: "SDL_MOUSE_NORMAL_SPEED_SCALE" @@ -152,6 +166,7 @@ HINT_NO_SIGNAL_HANDLERS :: "SDL_NO_SIGNAL_HANDLERS" HINT_OPENGL_LIBRARY :: "SDL_OPENGL_LIBRARY" HINT_EGL_LIBRARY :: "SDL_EGL_LIBRARY" HINT_OPENGL_ES_DRIVER :: "SDL_OPENGL_ES_DRIVER" +HINT_OPENGL_FORCE_SRGB_FRAMEBUFFER :: "SDL_OPENGL_FORCE_SRGB_FRAMEBUFFER" HINT_OPENVR_LIBRARY :: "SDL_OPENVR_LIBRARY" HINT_ORIENTATIONS :: "SDL_ORIENTATIONS" HINT_POLL_SENTINEL :: "SDL_POLL_SENTINEL" @@ -159,6 +174,7 @@ HINT_PREFERRED_LOCALES :: "SDL_PREFERRED_LOCALES" HINT_QUIT_ON_LAST_WINDOW_CLOSE :: "SDL_QUIT_ON_LAST_WINDOW_CLOSE" HINT_RENDER_DIRECT3D_THREADSAFE :: "SDL_RENDER_DIRECT3D_THREADSAFE" HINT_RENDER_DIRECT3D11_DEBUG :: "SDL_RENDER_DIRECT3D11_DEBUG" +HINT_RENDER_DIRECT3D11_WARP :: "SDL_RENDER_DIRECT3D11_WARP" HINT_RENDER_VULKAN_DEBUG :: "SDL_RENDER_VULKAN_DEBUG" HINT_RENDER_GPU_DEBUG :: "SDL_RENDER_GPU_DEBUG" HINT_RENDER_GPU_LOW_POWER :: "SDL_RENDER_GPU_LOW_POWER" @@ -169,6 +185,10 @@ HINT_RENDER_VSYNC :: "SDL_RENDER_VSYNC" HINT_RETURN_KEY_HIDES_IME :: "SDL_RETURN_KEY_HIDES_IME" HINT_ROG_GAMEPAD_MICE :: "SDL_ROG_GAMEPAD_MICE" HINT_ROG_GAMEPAD_MICE_EXCLUDED :: "SDL_ROG_GAMEPAD_MICE_EXCLUDED" +HINT_PS2_GS_WIDTH :: "SDL_PS2_GS_WIDTH" +HINT_PS2_GS_HEIGHT :: "SDL_PS2_GS_HEIGHT" +HINT_PS2_GS_PROGRESSIVE :: "SDL_PS2_GS_PROGRESSIVE" +HINT_PS2_GS_MODE :: "SDL_PS2_GS_MODE" HINT_RPI_VIDEO_LAYER :: "SDL_RPI_VIDEO_LAYER" HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME :: "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME" HINT_SHUTDOWN_DBUS_ON_QUIT :: "SDL_SHUTDOWN_DBUS_ON_QUIT" @@ -189,6 +209,8 @@ HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK :: "SDL_VIDEO_EGL_ALLOW_GETDISPLAY_ HINT_VIDEO_FORCE_EGL :: "SDL_VIDEO_FORCE_EGL" HINT_VIDEO_MAC_FULLSCREEN_SPACES :: "SDL_VIDEO_MAC_FULLSCREEN_SPACES" HINT_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY :: "SDL_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY" +HINT_VIDEO_METAL_AUTO_RESIZE_DRAWABLE :: "SDL_VIDEO_METAL_AUTO_RESIZE_DRAWABLE" +HINT_VIDEO_MATCH_EXCLUSIVE_MODE_ON_MOVE :: "SDL_VIDEO_MATCH_EXCLUSIVE_MODE_ON_MOVE" HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS :: "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" HINT_VIDEO_OFFSCREEN_SAVE_FRAMES :: "SDL_VIDEO_OFFSCREEN_SAVE_FRAMES" HINT_VIDEO_SYNC_WINDOW_OPERATIONS :: "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" @@ -228,6 +250,7 @@ HINT_WINDOWS_ENABLE_MENU_MNEMONICS :: "SDL_WINDOWS_ENABLE_MENU_MNEMONI HINT_WINDOWS_ENABLE_MESSAGELOOP :: "SDL_WINDOWS_ENABLE_MESSAGELOOP" HINT_WINDOWS_GAMEINPUT :: "SDL_WINDOWS_GAMEINPUT" HINT_WINDOWS_RAW_KEYBOARD :: "SDL_WINDOWS_RAW_KEYBOARD" +HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS :: "SDL_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS" HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL :: "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL" HINT_WINDOWS_INTRESOURCE_ICON :: "SDL_WINDOWS_INTRESOURCE_ICON" HINT_WINDOWS_INTRESOURCE_ICON_SMALL :: "SDL_WINDOWS_INTRESOURCE_ICON_SMALL" @@ -263,4 +286,4 @@ foreign lib { ResetHints :: proc() --- AddHintCallback :: proc(name: cstring, callback: HintCallback, userdata: rawptr) -> bool --- RemoveHintCallback :: proc(name: cstring, callback: HintCallback, userdata: rawptr) --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_init.odin b/vendor/sdl3/sdl3_init.odin index 0d10ad357..97daebf03 100644 --- a/vendor/sdl3/sdl3_init.odin +++ b/vendor/sdl3/sdl3_init.odin @@ -6,7 +6,7 @@ InitFlags :: distinct bit_set[InitFlag; Uint32] InitFlag :: enum Uint32 { AUDIO = 4, /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */ VIDEO = 5, /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread */ - JOYSTICK = 9, /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD */ + JOYSTICK = 9, /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS` */ HAPTIC = 12, GAMEPAD = 13, /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ EVENTS = 14, diff --git a/vendor/sdl3/sdl3_iostream.odin b/vendor/sdl3/sdl3_iostream.odin index 2f89c2ba6..f57dc947d 100644 --- a/vendor/sdl3/sdl3_iostream.odin +++ b/vendor/sdl3/sdl3_iostream.odin @@ -44,6 +44,7 @@ PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER :: "SDL.iostream.file_descriptor" PROP_IOSTREAM_ANDROID_AASSET_POINTER :: "SDL.iostream.android.aasset" PROP_IOSTREAM_MEMORY_POINTER :: "SDL.iostream.memory.base" PROP_IOSTREAM_MEMORY_SIZE_NUMBER :: "SDL.iostream.memory.size" +PROP_IOSTREAM_MEMORY_FREE_FUNC_POINTER :: "SDL.iostream.memory.free" PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER :: "SDL.iostream.dynamic.memory" PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER :: "SDL.iostream.dynamic.chunksize" diff --git a/vendor/sdl3/sdl3_joystick.odin b/vendor/sdl3/sdl3_joystick.odin index 78da26923..ea998d8f9 100644 --- a/vendor/sdl3/sdl3_joystick.odin +++ b/vendor/sdl3/sdl3_joystick.odin @@ -2,10 +2,6 @@ package sdl3 import "core:c" -@(link_prefix="SDL_") -foreign lib { - joystick_lock: ^Mutex -} Joystick :: struct {} JoystickID :: distinct Uint32 diff --git a/vendor/sdl3/sdl3_main.odin b/vendor/sdl3/sdl3_main.odin index f5f9b7f52..8c737b5b8 100644 --- a/vendor/sdl3/sdl3_main.odin +++ b/vendor/sdl3/sdl3_main.odin @@ -1,8 +1,9 @@ +// Bindings for [[ SDL3 ; https://wiki.libsdl.org/SDL3/FrontPage ]]. package sdl3 import "core:c" -main_func :: #type proc(argc: c.int, argv: [^]cstring) +main_func :: #type proc "c" (argc: c.int, argv: [^]cstring) -> c.int @(default_calling_convention="c", link_prefix="SDL_") foreign lib { diff --git a/vendor/sdl3/sdl3_mouse.odin b/vendor/sdl3/sdl3_mouse.odin index 3bc3aa57f..2a087a34c 100644 --- a/vendor/sdl3/sdl3_mouse.odin +++ b/vendor/sdl3/sdl3_mouse.odin @@ -34,6 +34,11 @@ MouseWheelDirection :: enum c.int { FLIPPED, /**< The scroll direction is flipped / natural */ } +CursorFrameInfo :: struct { + surface: ^Surface, + duration: Uint32, +} + MouseButtonFlags :: distinct bit_set[MouseButtonFlag; Uint32] MouseButtonFlag :: enum Uint32 { LEFT = 1 - 1, @@ -55,6 +60,8 @@ BUTTON_RMASK :: MouseButtonFlags{.RIGHT} BUTTON_X1MASK :: MouseButtonFlags{.X1} BUTTON_X2MASK :: MouseButtonFlags{.X2} +MouseMotionTransformCallback :: #type proc "c" (userdata: rawptr, timestamp: Uint64, window: ^Window, mouseID: MouseID, x, y: ^f32) + @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { HasMouse :: proc() -> bool --- @@ -66,11 +73,13 @@ foreign lib { GetRelativeMouseState :: proc(x, y: ^f32) -> MouseButtonFlags --- WarpMouseInWindow :: proc(window: ^Window, x, y: f32) --- WarpMouseGlobal :: proc(x, y: f32) -> bool --- + SetRelativeMouseTransform :: proc(callback: MouseMotionTransformCallback, userdata: rawptr) -> bool --- SetWindowRelativeMouseMode :: proc(window: ^Window, enabled: bool) -> bool --- GetWindowRelativeMouseMode :: proc(window: ^Window) -> bool --- CaptureMouse :: proc(enabled: bool) -> bool --- CreateCursor :: proc(data: [^]byte, mask: [^]Uint8, w, h, hot_x, hot_y: c.int) -> ^Cursor --- CreateColorCursor :: proc(surface: ^Surface, hot_x, hot_y: c.int) -> ^Cursor --- + CreateAnimatedCursor :: proc(frames: [^]CursorFrameInfo, frame_count, hot_x, hot_y: c.int) -> ^Cursor --- CreateSystemCursor :: proc(id: SystemCursor) -> ^Cursor --- SetCursor :: proc(cursor: ^Cursor) -> bool --- GetCursor :: proc() -> ^Cursor --- @@ -79,4 +88,4 @@ foreign lib { ShowCursor :: proc() -> bool --- HideCursor :: proc() -> bool --- CursorVisible :: proc() -> bool --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_mutex.odin b/vendor/sdl3/sdl3_mutex.odin index ada8006bc..7d48c0b5d 100644 --- a/vendor/sdl3/sdl3_mutex.odin +++ b/vendor/sdl3/sdl3_mutex.odin @@ -1,8 +1,24 @@ package sdl3 -Mutex :: struct {} -RWLock :: struct {} +import "core:c" +Mutex :: struct {} +RWLock :: struct {} +Semaphore :: struct {} +Condition :: struct {} + +InitStatus :: enum c.int { + UNINITIALIZED, + INITIALIZING, + INITIALIZED, + UNINITIALIZING, +} + +InitState :: struct { + status: AtomicInt, + thread: ThreadID, + reserved: rawptr, +} @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { @@ -19,4 +35,23 @@ foreign lib { TryLockRWLockForWriting :: proc(rwlock: ^RWLock) -> bool --- UnlockRWLock :: proc(rwlock: ^RWLock) --- DestroyRWLock :: proc(rwlock: ^RWLock) --- -} \ No newline at end of file + + CreateSemaphore :: proc(initial_value: Uint32) -> ^Semaphore --- + DestroySemaphore :: proc(sem: ^Semaphore) --- + GetSemaphoreValue :: proc(sem: ^Semaphore) -> Uint32 --- + SignalSemaphore :: proc(sem: ^Semaphore) --- + TryWaitSemaphore :: proc(sem: ^Semaphore) -> bool --- + WaitSemaphore :: proc(sem: ^Semaphore) --- + WaitSemaphoreTimeout :: proc(sem: ^Semaphore, timeout_ms: Sint32) --- + + CreateCondition :: proc() -> ^Condition --- + DestroyCondition :: proc(cond: ^Condition) --- + SignalCondition :: proc(cond: ^Condition) --- + BroadcastCondition :: proc(cond: ^Condition) --- + WaitCondition :: proc(cond: ^Condition, mutex: ^Mutex) --- + WaitConditionTimeout :: proc(cond: ^Condition, mutex: ^Mutex, timeout_ms: Sint32) -> bool --- + + ShouldInit :: proc(state: ^InitState) -> bool --- + ShouldQuit :: proc(state: ^InitState) -> bool --- + SetInitialized :: proc(state: ^InitState, initialized: bool) --- +} diff --git a/vendor/sdl3/sdl3_pen.odin b/vendor/sdl3/sdl3_pen.odin index 81e820e6b..d96848fed 100644 --- a/vendor/sdl3/sdl3_pen.odin +++ b/vendor/sdl3/sdl3_pen.odin @@ -10,13 +10,14 @@ PEN_TOUCHID :: TouchID(1<<64 - 2) PenInputFlags :: distinct bit_set[PenInputFlag; Uint32] PenInputFlag :: enum Uint32 { - DOWN = 0, /**< pen is pressed down */ - BUTTON_1 = 1, /**< button 1 is pressed */ - BUTTON_2 = 2, /**< button 2 is pressed */ - BUTTON_3 = 3, /**< button 3 is pressed */ - BUTTON_4 = 4, /**< button 4 is pressed */ - BUTTON_5 = 5, /**< button 5 is pressed */ - ERASER_TIP = 30, /**< eraser tip is used */ + DOWN = 0, /**< pen is pressed down */ + BUTTON_1 = 1, /**< button 1 is pressed */ + BUTTON_2 = 2, /**< button 2 is pressed */ + BUTTON_3 = 3, /**< button 3 is pressed */ + BUTTON_4 = 4, /**< button 4 is pressed */ + BUTTON_5 = 5, /**< button 5 is pressed */ + ERASER_TIP = 30, /**< eraser tip is used */ + IN_PROXIMITY = 31, /**< pen is in proximity (since SDL 3.4.0) */ } PenAxis :: enum c.int { @@ -27,4 +28,16 @@ PenAxis :: enum c.int { ROTATION, /**< Pen barrel rotation. Bidirectional: -180 to 179.9 (clockwise, 0 is facing up, -180.0 is facing down). */ SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0 to 1.0 */ TANGENTIAL_PRESSURE, /**< Pressure from squeezing the pen ("barrel pressure"). */ -} \ No newline at end of file +} + +PenDeviceType :: enum c.int { + INVALID = -1, /**< Not a valid pen device. */ + UNKNOWN, /**< Don't know specifics of this pen. */ + DIRECT, /**< Pen touches display. */ + INDIRECT, /**< Pen touches something that isn't the display. */ +} + +@(default_calling_convention="c", link_prefix="SDL_", require_results) +foreign lib { + GetPenDeviceType :: proc(instance_id: PenID) --- +} diff --git a/vendor/sdl3/sdl3_pixels.odin b/vendor/sdl3/sdl3_pixels.odin index a636d13ff..af6541757 100644 --- a/vendor/sdl3/sdl3_pixels.odin +++ b/vendor/sdl3/sdl3_pixels.odin @@ -75,20 +75,20 @@ DEFINE_PIXELFORMAT :: #force_inline proc "c" (type: PixelType, order: PackedOrde return PixelFormat(((1 << 28) | (Uint32(type) << 24) | (Uint32(order) << 20) | (Uint32(layout) << 16) | (Uint32(bits) << 8) | (Uint32(bytes) << 0))) } -@(require_results) PIXELFLAG :: proc "c" (format: PixelFormat) -> Uint32 { return ((Uint32(format) >> 28) & 0x0F) } -@(require_results) PIXELTYPE :: proc "c" (format: PixelFormat) -> PixelType { return PixelType((Uint32(format) >> 24) & 0x0F) } -@(require_results) PIXELORDER :: proc "c" (format: PixelFormat) -> PackedOrder { return PackedOrder((Uint32(format) >> 20) & 0x0F) } -@(require_results) PIXELLAYOUT :: proc "c" (format: PixelFormat) -> PackedLayout { return PackedLayout((Uint32(format) >> 16) & 0x0F) } -@(require_results) PIXELARRAYORDER :: proc "c" (format: PixelFormat) -> ArrayOrder { return ArrayOrder((Uint32(format) >> 20) & 0x0F) } +@(require_results) PIXELFLAG :: #force_inline proc "c" (format: PixelFormat) -> Uint32 { return ((Uint32(format) >> 28) & 0x0F) } +@(require_results) PIXELTYPE :: #force_inline proc "c" (format: PixelFormat) -> PixelType { return PixelType((Uint32(format) >> 24) & 0x0F) } +@(require_results) PIXELORDER :: #force_inline proc "c" (format: PixelFormat) -> PackedOrder { return PackedOrder((Uint32(format) >> 20) & 0x0F) } +@(require_results) PIXELLAYOUT :: #force_inline proc "c" (format: PixelFormat) -> PackedLayout { return PackedLayout((Uint32(format) >> 16) & 0x0F) } +@(require_results) PIXELARRAYORDER :: #force_inline proc "c" (format: PixelFormat) -> ArrayOrder { return ArrayOrder((Uint32(format) >> 20) & 0x0F) } @(require_results) -BITSPERPIXEL :: proc "c" (format: PixelFormat) -> Uint32 { +BITSPERPIXEL :: #force_inline proc "c" (format: PixelFormat) -> Uint32 { return ISPIXELFORMAT_FOURCC(format) ? 0 : ((Uint32(format) >> 8) & 0xFF) } @(require_results) -ISPIXELFORMAT_INDEXED :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_INDEXED :: #force_inline proc "c" (format: PixelFormat) -> bool { return (!ISPIXELFORMAT_FOURCC(format) && ((PIXELTYPE(format) == .INDEX1) || (PIXELTYPE(format) == .INDEX2) || @@ -98,7 +98,7 @@ ISPIXELFORMAT_INDEXED :: proc "c" (format: PixelFormat) -> bool { @(require_results) -ISPIXELFORMAT_PACKED :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_PACKED :: #force_inline proc "c" (format: PixelFormat) -> bool { return (!ISPIXELFORMAT_FOURCC(format) && ((PIXELTYPE(format) == .PACKED8) || (PIXELTYPE(format) == .PACKED16) || @@ -106,7 +106,7 @@ ISPIXELFORMAT_PACKED :: proc "c" (format: PixelFormat) -> bool { } @(require_results) -ISPIXELFORMAT_ARRAY :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_ARRAY :: #force_inline proc "c" (format: PixelFormat) -> bool { return (!ISPIXELFORMAT_FOURCC(format) && ((PIXELTYPE(format) == .ARRAYU8) || (PIXELTYPE(format) == .ARRAYU16) || @@ -116,21 +116,21 @@ ISPIXELFORMAT_ARRAY :: proc "c" (format: PixelFormat) -> bool { } @(require_results) -ISPIXELFORMAT_10BIT :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_10BIT :: #force_inline proc "c" (format: PixelFormat) -> bool { return (!ISPIXELFORMAT_FOURCC(format) && ((PIXELTYPE(format) == .PACKED32) && (PIXELLAYOUT(format) == .LAYOUT_2101010))) } @(require_results) -ISPIXELFORMAT_FLOAT :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_FLOAT :: #force_inline proc "c" (format: PixelFormat) -> bool { return (!ISPIXELFORMAT_FOURCC(format) && ((PIXELTYPE(format) == .ARRAYF16) || (PIXELTYPE(format) == .ARRAYF32))) } @(require_results) -ISPIXELFORMAT_ALPHA :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_ALPHA :: #force_inline proc "c" (format: PixelFormat) -> bool { return ((ISPIXELFORMAT_PACKED(format) && ((PIXELORDER(format) == .ARGB) || (PIXELORDER(format) == .RGBA) || @@ -144,7 +144,7 @@ ISPIXELFORMAT_ALPHA :: proc "c" (format: PixelFormat) -> bool { } @(require_results) -ISPIXELFORMAT_FOURCC :: proc "c" (format: PixelFormat) -> bool { +ISPIXELFORMAT_FOURCC :: #force_inline proc "c" (format: PixelFormat) -> bool { return format != nil && PIXELFLAG(format) != 1 } @@ -369,63 +369,63 @@ ChromaLocation :: enum c.int { @(require_results) -DEFINE_COLORSPACE :: proc "c" (type: ColorType, range: ColorRange, primaries: ColorPrimaries, transfer: TransferCharacteristics, matrix_: MatrixCoefficients, chroma: ChromaLocation) -> Colorspace { +DEFINE_COLORSPACE :: #force_inline proc "c" (type: ColorType, range: ColorRange, primaries: ColorPrimaries, transfer: TransferCharacteristics, matrix_: MatrixCoefficients, chroma: ChromaLocation) -> Colorspace { return Colorspace((Uint32(type) << 28) | (Uint32(range) << 24) | (Uint32(chroma) << 20) | (Uint32(primaries) << 10) | (Uint32(transfer) << 5) | (Uint32(matrix_) << 0)) } @(require_results) -COLORSPACETYPE :: proc "c" (cspace: Colorspace) -> ColorType { +COLORSPACETYPE :: #force_inline proc "c" (cspace: Colorspace) -> ColorType { return ColorType((Uint32(cspace) >> 28) & 0x0F) } @(require_results) -COLORSPACERANGE :: proc "c" (cspace: Colorspace) -> ColorRange { +COLORSPACERANGE :: #force_inline proc "c" (cspace: Colorspace) -> ColorRange { return ColorRange((Uint32(cspace) >> 24) & 0x0F) } @(require_results) -COLORSPACECHROMA :: proc "c" (cspace: Colorspace) -> ChromaLocation { +COLORSPACECHROMA :: #force_inline proc "c" (cspace: Colorspace) -> ChromaLocation { return ChromaLocation((Uint32(cspace) >> 20) & 0x0F) } @(require_results) -COLORSPACEPRIMARIES :: proc "c" (cspace: Colorspace) -> ColorPrimaries { +COLORSPACEPRIMARIES :: #force_inline proc "c" (cspace: Colorspace) -> ColorPrimaries { return ColorPrimaries((Uint32(cspace) >> 10) & 0x1F) } @(require_results) -COLORSPACETRANSFER :: proc "c" (cspace: Colorspace) -> TransferCharacteristics { +COLORSPACETRANSFER :: #force_inline proc "c" (cspace: Colorspace) -> TransferCharacteristics { return TransferCharacteristics((Uint32(cspace) >> 5) & 0x1F) } @(require_results) -COLORSPACEMATRIX :: proc "c" (cspace: Colorspace) -> MatrixCoefficients { +COLORSPACEMATRIX :: #force_inline proc "c" (cspace: Colorspace) -> MatrixCoefficients { return MatrixCoefficients(Uint32(cspace) & 0x1F) } @(require_results) -ISCOLORSPACE_MATRIX_BT601 :: proc "c" (cspace: Colorspace) -> bool { +ISCOLORSPACE_MATRIX_BT601 :: #force_inline proc "c" (cspace: Colorspace) -> bool { return COLORSPACEMATRIX(cspace) == .BT601 || COLORSPACEMATRIX(cspace) == .BT470BG } @(require_results) -ISCOLORSPACE_MATRIX_BT709 :: proc "c" (cspace: Colorspace) -> bool { +ISCOLORSPACE_MATRIX_BT709 :: #force_inline proc "c" (cspace: Colorspace) -> bool { return COLORSPACEMATRIX(cspace) == .BT709 } @(require_results) -ISCOLORSPACE_MATRIX_BT2020_NCL :: proc "c" (cspace: Colorspace) -> bool { +ISCOLORSPACE_MATRIX_BT2020_NCL :: #force_inline proc "c" (cspace: Colorspace) -> bool { return COLORSPACEMATRIX(cspace) == .BT2020_NCL } @(require_results) -ISCOLORSPACE_LIMITED_RANGE :: proc "c" (cspace: Colorspace) -> bool { +ISCOLORSPACE_LIMITED_RANGE :: #force_inline proc "c" (cspace: Colorspace) -> bool { return COLORSPACERANGE(cspace) != .FULL } @(require_results) -ISCOLORSPACE_FULL_RANGE :: proc "c" (cspace: Colorspace) -> bool { +ISCOLORSPACE_FULL_RANGE :: #force_inline proc "c" (cspace: Colorspace) -> bool { return COLORSPACERANGE(cspace) == .FULL } @@ -518,7 +518,7 @@ Colorspace :: enum c.int { SDL_CHROMA_LOCATION_LEFT), */ RGB_DEFAULT = SRGB, /**< The default colorspace for RGB surfaces if no colorspace is specified */ - YUV_DEFAULT = JPEG, /**< The default colorspace for YUV surfaces if no colorspace is specified */ + YUV_DEFAULT = BT601_LIMITED, /**< The default colorspace for YUV surfaces if no colorspace is specified */ } Color :: distinct [4]Uint8 @@ -561,6 +561,6 @@ foreign lib { DestroyPalette :: proc(palette: ^Palette) --- MapRGB :: proc(format: ^PixelFormatDetails, palette: ^Palette, r, g, b: Uint8) -> Uint32 --- MapRGBA :: proc(format: ^PixelFormatDetails, palette: ^Palette, r, g, b, a: Uint8) -> Uint32 --- - GetRGB :: proc(pixel: Uint32, format: ^PixelFormatDetails, palette: ^Palette, r, g, b: ^Uint8) --- - GetRGBA :: proc(pixel: Uint32, format: ^PixelFormatDetails, palette: ^Palette, r, g, b, a: ^Uint8) --- + GetRGB :: proc(pixelvalue: Uint32, format: ^PixelFormatDetails, palette: ^Palette, r, g, b: ^Uint8) --- + GetRGBA :: proc(pixelvalue: Uint32, format: ^PixelFormatDetails, palette: ^Palette, r, g, b, a: ^Uint8) --- } diff --git a/vendor/sdl3/sdl3_process.odin b/vendor/sdl3/sdl3_process.odin index d3ba6f2ba..71686a444 100644 --- a/vendor/sdl3/sdl3_process.odin +++ b/vendor/sdl3/sdl3_process.odin @@ -13,6 +13,7 @@ ProcessIO :: enum c.int { PROP_PROCESS_CREATE_ARGS_POINTER :: "SDL.process.create.args" PROP_PROCESS_CREATE_ENVIRONMENT_POINTER :: "SDL.process.create.environment" +PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING :: "SDL.process.create.working_directory" PROP_PROCESS_CREATE_STDIN_NUMBER :: "SDL.process.create.stdin_option" PROP_PROCESS_CREATE_STDIN_POINTER :: "SDL.process.create.stdin_source" PROP_PROCESS_CREATE_STDOUT_NUMBER :: "SDL.process.create.stdout_option" @@ -21,6 +22,7 @@ PROP_PROCESS_CREATE_STDERR_NUMBER :: "SDL.process.create.stderr_op PROP_PROCESS_CREATE_STDERR_POINTER :: "SDL.process.create.stderr_source" PROP_PROCESS_CREATE_STDERR_TO_STDOUT_BOOLEAN :: "SDL.process.create.stderr_to_stdout" PROP_PROCESS_CREATE_BACKGROUND_BOOLEAN :: "SDL.process.create.background" +PROP_PROCESS_CREATE_CMDLINE_STRING :: "SDL.process.create.cmdline" PROP_PROCESS_PID_NUMBER :: "SDL.process.pid" PROP_PROCESS_STDIN_POINTER :: "SDL.process.stdin" @@ -39,4 +41,4 @@ foreign lib { KillProcess :: proc(process: ^Process, force: bool) -> bool --- WaitProcess :: proc(process: ^Process, block: bool, exitcode: ^c.int) -> bool --- DestroyProcess :: proc(process: ^Process) --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_properties.odin b/vendor/sdl3/sdl3_properties.odin index 73372c290..01bdff59b 100644 --- a/vendor/sdl3/sdl3_properties.odin +++ b/vendor/sdl3/sdl3_properties.odin @@ -4,6 +4,8 @@ import "core:c" PropertiesID :: distinct Uint32 +PROP_NAME_STRING :: "SDL.name" + PropertyType :: enum c.int { INVALID, POINTER, @@ -41,4 +43,4 @@ foreign lib { ClearProperty :: proc(props: PropertiesID, name: cstring) -> bool --- EnumerateProperties :: proc(props: PropertiesID, callback: EnumeratePropertiesCallback, userdata: rawptr) -> bool --- DestroyProperties :: proc(props: PropertiesID) --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_rect.odin b/vendor/sdl3/sdl3_rect.odin index 53470dec4..be082119e 100644 --- a/vendor/sdl3/sdl3_rect.odin +++ b/vendor/sdl3/sdl3_rect.odin @@ -24,32 +24,51 @@ RectToFRect :: #force_inline proc "c" (rect: Rect, frect: ^FRect) { @(require_results) -PointInRect :: proc "c" (p: Point, r: Rect) -> bool { +PointInRect :: #force_inline proc "c" (p: Point, r: Rect) -> bool { return ( (p.x >= r.x) && (p.x < (r.x + r.w)) && (p.y >= r.y) && (p.y < (r.y + r.h)) ) } @(require_results) -RectEmpty :: proc "c" (r: Rect) -> bool { +PointInRectFloat :: #force_inline proc "c" (p: FPoint, r: FRect) -> bool { + return ( (p.x >= r.x) && (p.x <= (r.x + r.w)) && + (p.y >= r.y) && (p.y <= (r.y + r.h)) ) +} + +@(require_results) +RectEmpty :: #force_inline proc "c" (r: Rect) -> bool { return r.w <= 0 || r.h <= 0 } @(require_results) -RectEqual :: proc "c" (a, b: Rect) -> bool { +RectEqual :: #force_inline proc "c" (a, b: Rect) -> bool { return a == b } +@(require_results) +RectsEqualEpsilon :: #force_inline proc "c" (a, b: FRect, epsilon: f32) -> bool { + return abs(a.x - b.x) <= epsilon && + abs(a.y - b.y) <= epsilon && + abs(a.w - b.w) <= epsilon && + abs(a.h - b.h) <= epsilon +} + +@(require_results) +RectsEqualFloat :: #force_inline proc "c" (a, b: FRect) -> bool { + return RectsEqualEpsilon(a, b, FLT_EPSILON) +} + @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { HasRectIntersection :: proc(#by_ptr A, B: Rect) -> bool --- GetRectIntersection :: proc(#by_ptr A, B: Rect, result: ^Rect) -> bool --- GetRectUnion :: proc(#by_ptr A, B: Rect, result: ^Rect) -> bool --- - GetRectEnclosingPoints :: proc(points: [^]Point, count: c.int, #by_ptr clip: Rect, result: ^Rect) -> bool --- + GetRectEnclosingPoints :: proc(points: [^]Point, count: c.int, clip: Maybe(^Rect), result: ^Rect) -> bool --- GetRectAndLineIntersection :: proc(#by_ptr rect: Rect, X1, Y1, X2, Y2: ^c.int) -> bool --- HasRectIntersectionFloat :: proc(#by_ptr A, B: FRect) -> bool --- GetRectIntersectionFloat :: proc(#by_ptr A, B: FRect, result: ^FRect) -> bool --- GetRectUnionFloat :: proc(#by_ptr A, B: FRect, result: ^FRect) -> bool --- - GetRectEnclosingPointsFloat :: proc(points: [^]FPoint, count: c.int, #by_ptr clip: FRect, result: ^FRect) -> bool --- + GetRectEnclosingPointsFloat :: proc(points: [^]FPoint, count: c.int, clip: Maybe(^FRect), result: ^FRect) -> bool --- GetRectAndLineIntersectionFloat :: proc(#by_ptr rect: FRect, X1, Y1, X2, Y2: ^f32) -> bool --- } \ No newline at end of file diff --git a/vendor/sdl3/sdl3_render.odin b/vendor/sdl3/sdl3_render.odin index 5af4bb055..759683dfe 100644 --- a/vendor/sdl3/sdl3_render.odin +++ b/vendor/sdl3/sdl3_render.odin @@ -4,6 +4,7 @@ import "core:c" SOFTWARE_RENDERER :: "software" +GPU_RENDER :: "gpu" Vertex :: struct { position: FPoint, /**< Vertex position, in SDL_Renderer coordinates */ @@ -17,6 +18,13 @@ TextureAccess :: enum c.int { TARGET, /**< Texture can be used as a render target */ } +TextureAddressMode :: enum c.int { + INVALID = -1, + AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */ + CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */ + WRAP, /**< The texture is repeated (tiled) */ +} + RendererLogicalPresentation :: enum c.int { DISABLED, /**< There is no logical size in effect */ STRETCH, /**< The rendered content is stretched to the output resolution */ @@ -40,6 +48,10 @@ PROP_RENDERER_CREATE_WINDOW_POINTER :: "SDL.renderer PROP_RENDERER_CREATE_SURFACE_POINTER :: "SDL.renderer.create.surface" PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER :: "SDL.renderer.create.output_colorspace" PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER :: "SDL.renderer.create.present_vsync" +PROP_RENDERER_CREATE_GPU_DEVICE_POINTER :: "SDL.renderer.create.gpu.device" +PROP_RENDERER_CREATE_GPU_SHADERS_SPIRV_BOOLEAN :: "SDL.renderer.create.gpu.shaders_spirv" +PROP_RENDERER_CREATE_GPU_SHADERS_DXIL_BOOLEAN :: "SDL.renderer.create.gpu.shaders_dxil" +PROP_RENDERER_CREATE_GPU_SHADERS_MSL_BOOLEAN :: "SDL.renderer.create.gpu.shaders_msl" PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER :: "SDL.renderer.create.vulkan.instance" PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER :: "SDL.renderer.create.vulkan.surface" PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER :: "SDL.renderer.create.vulkan.physical_device" @@ -53,6 +65,7 @@ PROP_RENDERER_SURFACE_POINTER :: "SDL.renderer.surface PROP_RENDERER_VSYNC_NUMBER :: "SDL.renderer.vsync" PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER :: "SDL.renderer.max_texture_size" PROP_RENDERER_TEXTURE_FORMATS_POINTER :: "SDL.renderer.texture_formats" +PROP_RENDERER_TEXTURE_WRAPPING_BOOLEAN :: "SDL.renderer.texture_wrapping" PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER :: "SDL.renderer.output_colorspace" PROP_RENDERER_HDR_ENABLED_BOOLEAN :: "SDL.renderer.HDR_enabled" PROP_RENDERER_SDR_WHITE_POINT_FLOAT :: "SDL.renderer.SDR_white_point" @@ -72,29 +85,35 @@ PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER :: "SDL.renderer.vulkan. PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER :: "SDL.renderer.vulkan.swapchain_image_count" PROP_RENDERER_GPU_DEVICE_POINTER :: "SDL.renderer.gpu.device" -PROP_TEXTURE_CREATE_COLORSPACE_NUMBER :: "SDL.texture.create.colorspace" -PROP_TEXTURE_CREATE_FORMAT_NUMBER :: "SDL.texture.create.format" -PROP_TEXTURE_CREATE_ACCESS_NUMBER :: "SDL.texture.create.access" -PROP_TEXTURE_CREATE_WIDTH_NUMBER :: "SDL.texture.create.width" -PROP_TEXTURE_CREATE_HEIGHT_NUMBER :: "SDL.texture.create.height" -PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT :: "SDL.texture.create.SDR_white_point" -PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT :: "SDL.texture.create.HDR_headroom" -PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER :: "SDL.texture.create.d3d11.texture" -PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER :: "SDL.texture.create.d3d11.texture_u" -PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER :: "SDL.texture.create.d3d11.texture_v" -PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER :: "SDL.texture.create.d3d12.texture" -PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER :: "SDL.texture.create.d3d12.texture_u" -PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER :: "SDL.texture.create.d3d12.texture_v" -PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER :: "SDL.texture.create.metal.pixelbuffer" -PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER :: "SDL.texture.create.opengl.texture" -PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER :: "SDL.texture.create.opengl.texture_uv" -PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER :: "SDL.texture.create.opengl.texture_u" -PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER :: "SDL.texture.create.opengl.texture_v" -PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER :: "SDL.texture.create.opengles2.texture" -PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER :: "SDL.texture.create.opengles2.texture_uv" -PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER :: "SDL.texture.create.opengles2.texture_u" -PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER :: "SDL.texture.create.opengles2.texture_v" -PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER :: "SDL.texture.create.vulkan.texture" +PROP_TEXTURE_CREATE_COLORSPACE_NUMBER :: "SDL.texture.create.colorspace" +PROP_TEXTURE_CREATE_FORMAT_NUMBER :: "SDL.texture.create.format" +PROP_TEXTURE_CREATE_ACCESS_NUMBER :: "SDL.texture.create.access" +PROP_TEXTURE_CREATE_WIDTH_NUMBER :: "SDL.texture.create.width" +PROP_TEXTURE_CREATE_HEIGHT_NUMBER :: "SDL.texture.create.height" +PROP_TEXTURE_CREATE_PALETTE_POINTER :: "SDL.texture.create.palette" +PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT :: "SDL.texture.create.SDR_white_point" +PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT :: "SDL.texture.create.HDR_headroom" +PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER :: "SDL.texture.create.d3d11.texture" +PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER :: "SDL.texture.create.d3d11.texture_u" +PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER :: "SDL.texture.create.d3d11.texture_v" +PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER :: "SDL.texture.create.d3d12.texture" +PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER :: "SDL.texture.create.d3d12.texture_u" +PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER :: "SDL.texture.create.d3d12.texture_v" +PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER :: "SDL.texture.create.metal.pixelbuffer" +PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER :: "SDL.texture.create.opengl.texture" +PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER :: "SDL.texture.create.opengl.texture_uv" +PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER :: "SDL.texture.create.opengl.texture_u" +PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER :: "SDL.texture.create.opengl.texture_v" +PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER :: "SDL.texture.create.opengles2.texture" +PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER :: "SDL.texture.create.opengles2.texture_uv" +PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER :: "SDL.texture.create.opengles2.texture_u" +PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER :: "SDL.texture.create.opengles2.texture_v" +PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER :: "SDL.texture.create.vulkan.texture" +PROP_TEXTURE_CREATE_VULKAN_LAYOUT_NUMBER :: "SDL.texture.create.vulkan.layout" +PROP_TEXTURE_CREATE_GPU_TEXTURE_POINTER :: "SDL.texture.create.gpu.texture" +PROP_TEXTURE_CREATE_GPU_TEXTURE_UV_POINTER :: "SDL.texture.create.gpu.texture_uv" +PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER :: "SDL.texture.create.gpu.texture_u" +PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER :: "SDL.texture.create.gpu.texture_v" PROP_TEXTURE_COLORSPACE_NUMBER :: "SDL.texture.colorspace" PROP_TEXTURE_FORMAT_NUMBER :: "SDL.texture.format" @@ -122,6 +141,10 @@ PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER :: "SDL.texture.opengles2.textur PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER :: "SDL.texture.opengles2.texture_v" PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER :: "SDL.texture.opengles2.target" PROP_TEXTURE_VULKAN_TEXTURE_NUMBER :: "SDL.texture.vulkan.texture" +PROP_TEXTURE_GPU_TEXTURE_POINTER :: "SDL.texture.gpu.texture" +PROP_TEXTURE_GPU_TEXTURE_UV_POINTER :: "SDL.texture.gpu.texture_uv" +PROP_TEXTURE_GPU_TEXTURE_U_POINTER :: "SDL.texture.gpu.texture_u" +PROP_TEXTURE_GPU_TEXTURE_V_POINTER :: "SDL.texture.gpu.texture_v" RENDERER_VSYNC_DISABLED :: 0 RENDERER_VSYNC_ADAPTIVE :: -1 @@ -134,6 +157,8 @@ foreign lib { GetRenderDriver :: proc(index: c.int) -> cstring --- CreateRenderer :: proc(window: ^Window, name: cstring) -> ^Renderer --- CreateRendererWithProperties :: proc(props: PropertiesID) -> ^Renderer --- + CreateGPURenderer :: proc(device: ^GPUDevice, window: ^Window) -> ^Renderer --- + GetGPURendererDevice :: proc(device: ^Renderer) -> ^GPUDevice --- CreateSoftwareRenderer :: proc(surface: ^Surface) -> ^Renderer --- GetRenderer :: proc(window: ^Window) -> ^Renderer --- GetRenderWindow :: proc(renderer: ^Renderer) -> ^Window --- @@ -158,6 +183,8 @@ foreign lib { GetRenderOutputSize :: proc(renderer: ^Renderer, w, h: ^c.int) -> bool --- GetCurrentRenderOutputSize :: proc(renderer: ^Renderer, w, h: ^c.int) -> bool --- GetTextureSize :: proc(texture: ^Texture, w, h: ^f32) -> bool --- + SetTexturePalette :: proc(texture: ^Texture, palette: ^Palette) -> bool --- + GetTexturePalette :: proc(texture: ^Texture) -> ^Palette --- SetTextureColorMod :: proc(texture: ^Texture, r, g, b: Uint8) -> bool --- SetTextureColorModFloat :: proc(texture: ^Texture, r, g, b: f32) -> bool --- GetTextureColorMod :: proc(texture: ^Texture, r, g, b: ^Uint8) -> bool --- @@ -208,12 +235,15 @@ foreign lib { RenderFillRect :: proc(renderer: ^Renderer, rect: Maybe(^FRect)) -> bool --- RenderFillRects :: proc(renderer: ^Renderer, rects: [^]FRect, count: c.int) -> bool --- RenderTexture :: proc(renderer: ^Renderer, texture: ^Texture, srcrect, dstrect: Maybe(^FRect)) -> bool --- - RenderTextureRotated :: proc(renderer: ^Renderer, texture: ^Texture, srcrect, dstrect: Maybe(^FRect), angle: f64, #by_ptr center: FPoint, flip: FlipMode) -> bool --- + RenderTextureRotated :: proc(renderer: ^Renderer, texture: ^Texture, srcrect, dstrect: Maybe(^FRect), angle: f64, center: Maybe(^FPoint), flip: FlipMode) -> bool --- RenderTextureAffine :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: Maybe(^FRect), origin, right, down: Maybe(^FPoint)) -> bool --- RenderTextureTiled :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: Maybe(^FRect), scale: f32, dstrect: Maybe(^FRect)) -> bool --- RenderTexture9Grid :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: Maybe(^FRect), left_width, right_width, top_height, bottom_height: f32, scale: f32, dstrect: Maybe(^FRect)) -> bool --- - RenderGeometry :: proc(renderer: ^Renderer, texture: ^Texture, vertices: [^]Vertex, num_vertices: c.int, indices: [^]c.int, num_indices: c.int) -> bool --- - RenderGeometryRaw :: proc(renderer: ^Renderer, texture: ^Texture, xy: [^]f32, xy_stride: c.int, color: [^]FColor, color_stride: c.int, uv: [^]f32, uv_stride: c.int, num_vertices: c.int, indices: rawptr, num_indices: c.int, size_indices: c.int) -> bool --- + RenderTexture9GridTiled :: proc(renderer: ^Renderer, texture: ^Texture, srcrect: Maybe(^FRect), left_width, right_width, top_height, bottom_height: f32, scale: f32, dstrect: Maybe(^FRect), tileScale: f32) -> bool --- + RenderGeometry :: proc(renderer: ^Renderer, texture: Maybe(^Texture), vertices: [^]Vertex, num_vertices: c.int, indices: [^]c.int, num_indices: c.int) -> bool --- + RenderGeometryRaw :: proc(renderer: ^Renderer, texture: Maybe(^Texture), xy: [^]f32, xy_stride: c.int, color: [^]FColor, color_stride: c.int, uv: [^]f32, uv_stride: c.int, num_vertices: c.int, indices: rawptr, num_indices: c.int, size_indices: c.int) -> bool --- + SetRenderTextureAddressMode :: proc(renderer: ^Renderer, u_mode, v_mode: TextureAddressMode) -> bool --- + GetRenderTextureAddressMode :: proc(renderer: ^Renderer, u_mode, v_mode: ^TextureAddressMode) -> bool --- RenderPresent :: proc(renderer: ^Renderer) -> bool --- DestroyTexture :: proc(texture: ^Texture) --- DestroyRenderer :: proc(renderer: ^Renderer) --- @@ -223,4 +253,28 @@ foreign lib { GetRenderVSync :: proc(renderer: ^Renderer, vsync: ^c.int) -> bool --- RenderDebugText :: proc(renderer: ^Renderer, x, y: f32, str: cstring) -> bool --- RenderDebugTextFormat :: proc(renderer: ^Renderer, x, y: f32, fmt: cstring, #c_vararg args: ..any) -> bool --- -} \ No newline at end of file + SetDefaultTextureAddressMode :: proc(renderer: ^Renderer, scale_mode: ScaleMode) -> bool --- + GetDefaultTextureAddressMode :: proc(renderer: ^Renderer, scale_mode: ^ScaleMode) -> bool --- +} + + +GPURenderStateCreateInfo :: struct { + fragment_shader: ^GPUShader, /**< The fragment shader to use when this render state is active */ + num_sampler_bindings: Sint32, /**< The number of additional fragment samplers to bind when this render state is active */ + sampler_bindings: [^]GPUTextureSamplerBinding, /**< Additional fragment samplers to bind when this render state is active */ + num_storage_textures: Sint32, /**< The number of storage textures to bind when this render state is active */ + storage_textures: [^]^GPUTexture, /**< Storage textures to bind when this render state is active */ + num_storage_buffers: Sint32, /**< The number of storage buffers to bind when this render state is active */ + storage_buffers: [^]^GPUBuffer, /**< Storage buffers to bind when this render state is active */ + props: PropertiesID, /**< A properties ID for extensions. Should be 0 if no extensions are needed. */ +} + +GPURenderState :: struct {} + +@(default_calling_convention="c", link_prefix="SDL_", require_results) +foreign lib { + CreateGPURenderState :: proc(renderer: ^Renderer, #by_ptr createinfo: GPURenderStateCreateInfo) -> ^GPURenderState --- + SetGPURenderStateFragmentUniforms :: proc(state: ^GPURenderState, slot_index: Uint32, data: rawptr, length: Uint32) -> bool --- + SetGPURenderState :: proc(renderer: ^Renderer, state: ^GPURenderState) -> bool --- + DestroyGPURenderState :: proc(renderer: ^GPURenderState) --- +} diff --git a/vendor/sdl3/sdl3_surface.odin b/vendor/sdl3/sdl3_surface.odin index 526940147..9aaf54cec 100644 --- a/vendor/sdl3/sdl3_surface.odin +++ b/vendor/sdl3/sdl3_surface.odin @@ -23,14 +23,16 @@ MUSTLOCK :: proc "c" (S: ^Surface) -> bool { ScaleMode :: enum c.int { INVALID = -1, - NEAREST, /**< nearest pixel sampling */ - LINEAR, /**< linear filtering */ + NEAREST, /**< nearest pixel sampling */ + LINEAR, /**< linear filtering */ + PIXELART, /**< nearest pixel sampling with improved scaling for pixel art, available since SDL 3.4.0 */ } FlipMode :: enum c.int { - NONE, /**< Do not flip */ - HORIZONTAL, /**< flip horizontally */ - VERTICAL, /**< flip vertically */ + NONE, /**< Do not flip */ + HORIZONTAL, /**< flip horizontally */ + VERTICAL, /**< flip vertically */ + HORIZONTAL_AND_VERTICAL = HORIZONTAL | VERTICAL, /**< flip horizontally and vertically (not a diagonal flip) */ } Surface :: struct { @@ -51,6 +53,7 @@ PROP_SURFACE_HDR_HEADROOM_FLOAT :: "SDL.surface.HDR_headroom" PROP_SURFACE_TONEMAP_OPERATOR_STRING :: "SDL.surface.tonemap" PROP_SURFACE_HOTSPOT_X_NUMBER :: "SDL.surface.hotspot.x" PROP_SURFACE_HOTSPOT_Y_NUMBER :: "SDL.surface.hotspot.y" +PROP_SURFACE_ROTATION_FLOAT :: "SDL.surface.rotation" @(default_calling_convention="c", link_prefix="SDL_") foreign lib { @@ -69,10 +72,16 @@ foreign lib { RemoveSurfaceAlternateImages :: proc(surface: ^Surface) --- LockSurface :: proc(surface: ^Surface) -> bool --- UnlockSurface :: proc(surface: ^Surface) --- + LoadSurface_IO :: proc(src: ^IOStream, closeio: bool) -> ^Surface --- + LoadSurface :: proc(file: cstring) -> ^Surface --- LoadBMP_IO :: proc(src: ^IOStream, closeio: bool) -> ^Surface --- LoadBMP :: proc(file: cstring) -> ^Surface --- SaveBMP_IO :: proc(surface: ^Surface, dst: ^IOStream, closeio: bool) -> bool --- SaveBMP :: proc(surface: ^Surface, file: cstring) -> bool --- + LoadPNG_IO :: proc(src: ^IOStream, closeio: bool) -> ^Surface --- + LoadPNG :: proc(file: cstring) -> ^Surface --- + SavePNG_IO :: proc(surface: ^Surface, dst: ^IOStream, closeio: bool) -> bool --- + SavePNG :: proc(surface: ^Surface, file: cstring) -> bool --- SetSurfaceRLE :: proc(surface: ^Surface, enabled: bool) -> bool --- SurfaceHasRLE :: proc(surface: ^Surface) -> bool --- SetSurfaceColorKey :: proc(surface: ^Surface, enabled: bool, key: Uint32) -> bool --- @@ -87,6 +96,7 @@ foreign lib { SetSurfaceClipRect :: proc(surface: ^Surface, rect: Maybe(^Rect)) -> bool --- GetSurfaceClipRect :: proc(surface: ^Surface, rect: ^Rect) -> bool --- FlipSurface :: proc(surface: ^Surface, flip: FlipMode) -> bool --- + RotateSurface :: proc(surface: ^Surface, angle: f32) -> ^Surface --- DuplicateSurface :: proc(surface: ^Surface) -> ^Surface --- ScaleSurface :: proc(surface: ^Surface, width, height: c.int, scaleMode: ScaleMode) -> ^Surface --- ConvertSurface :: proc(surface: ^Surface, format: PixelFormat) -> ^Surface --- @@ -112,4 +122,4 @@ foreign lib { ReadSurfacePixelFloat :: proc(surface: ^Surface, x, y: c.int, r, g, b, a: ^f32) -> bool --- WriteSurfacePixel :: proc(surface: ^Surface, x, y: c.int, r, g, b, a: Uint8) -> bool --- WriteSurfacePixelFloat :: proc(surface: ^Surface, x, y: c.int, r, g, b, a: f32) -> bool --- -} \ No newline at end of file +} diff --git a/vendor/sdl3/sdl3_system.odin b/vendor/sdl3/sdl3_system.odin index 44c026e82..63b0637d7 100644 --- a/vendor/sdl3/sdl3_system.odin +++ b/vendor/sdl3/sdl3_system.odin @@ -6,7 +6,7 @@ import "core:c" import win32 "core:sys/windows" -WindowsMessageHook :: #type proc(userdata: rawptr, msg: ^win32.MSG) -> bool +WindowsMessageHook :: #type proc "c" (userdata: rawptr, msg: ^win32.MSG) -> bool @(default_calling_convention="c", link_prefix="SDL_") foreign lib { @@ -46,6 +46,11 @@ foreign lib { RequestAndroidPermissionCallback :: #type proc "c" (userdata: rawptr, permission: cstring, granted: bool) +AndroidExternalStorageFlags :: distinct bit_set[AndroidExternalStorageFlag; Uint32] +AndroidExternalStorageFlag :: enum Uint32 { + Read, + Write, +} @(default_calling_convention="c", link_prefix="SDL_", require_results) foreign lib { @@ -56,7 +61,7 @@ foreign lib { IsDeXMode :: proc() -> bool --- SendAndroidBackButton :: proc() --- GetAndroidInternalStoragePath :: proc() -> cstring --- - GetAndroidExternalStorageState :: proc() -> Uint32 --- + GetAndroidExternalStorageState :: proc() -> AndroidExternalStorageFlags --- GetAndroidExternalStoragePath :: proc() -> cstring --- GetAndroidCachePath :: proc() -> cstring --- RequestAndroidPermission :: proc(permission: cstring, cb: RequestAndroidPermissionCallback, userdata: rawptr) -> bool --- diff --git a/vendor/sdl3/sdl3_thread.odin b/vendor/sdl3/sdl3_thread.odin index 9b2d068d9..e6bbf7d16 100644 --- a/vendor/sdl3/sdl3_thread.odin +++ b/vendor/sdl3/sdl3_thread.odin @@ -49,7 +49,7 @@ PROP_THREAD_CREATE_STACKSIZE_NUMBER :: "SDL.thread.create.stacksize" BeginThreadFunction :: proc "c" () -> FunctionPointer { when ODIN_OS == .Windows { foreign { - _beginthreadx :: proc "c" ( + _beginthreadex :: proc "c" ( security: rawptr, stack_size: c.uint, start_address: proc "c" (rawptr), @@ -58,7 +58,7 @@ BeginThreadFunction :: proc "c" () -> FunctionPointer { thraddr: ^c.uint, ) -> uintptr --- } - return FunctionPointer(_beginthreadx) + return FunctionPointer(_beginthreadex) } else { return nil } diff --git a/vendor/sdl3/sdl3_version.odin b/vendor/sdl3/sdl3_version.odin index 9143a977b..271771a4b 100644 --- a/vendor/sdl3/sdl3_version.odin +++ b/vendor/sdl3/sdl3_version.odin @@ -3,8 +3,8 @@ package sdl3 import "core:c" MAJOR_VERSION :: 3 -MINOR_VERSION :: 2 -MICRO_VERSION :: 10 +MINOR_VERSION :: 4 +MICRO_VERSION :: 2 @(require_results) VERSIONNUM :: #force_inline proc "c" (major, minor, patch: c.int) -> c.int { return (major * 1000000) + (minor * 1000) + patch } @(require_results) VERSIONNUM_MAJOR :: #force_inline proc "c" (version: c.int) -> c.int { return version / 1000000 } diff --git a/vendor/sdl3/sdl3_video.odin b/vendor/sdl3/sdl3_video.odin index 3dd045214..3ddcfedc6 100644 --- a/vendor/sdl3/sdl3_video.odin +++ b/vendor/sdl3/sdl3_video.odin @@ -61,6 +61,7 @@ WindowFlag :: enum Uint64 { TOOLTIP = 18, POPUP_MENU = 19, KEYBOARD_GRABBED = 20, + FILL_DOCUMENT = 21, VULKAN = 28, METAL = 29, @@ -133,6 +134,15 @@ FlashOperation :: enum c.int { UNTIL_FOCUSED, /**< Flash the window until it gets focus */ } +ProgressState :: enum c.int { + INVALID = -1, /**< An invalid progress state indicating an error; check SDL_GetError() */ + NONE, /**< No progress bar is shown */ + INDETERMINATE, /**< The progress bar is shown in a indeterminate state */ + NORMAL, /**< The progress bar is shown in a normal state */ + PAUSED, /**< The progress bar is shown in a paused state */ + ERROR, /**< The progress bar is shown in a state indicating the application had an error */ +} + GLContextState :: struct {} GLContext :: ^GLContextState EGLDisplay :: distinct rawptr @@ -141,14 +151,14 @@ EGLSurface :: distinct rawptr EGLAttrib :: distinct uintptr EGLint :: distinct c.int -EGLAttribArrayCallback :: #type proc "c" (userdata: rawptr) -> ^EGLint +EGLAttribArrayCallback :: #type proc "c" (userdata: rawptr) -> [^]EGLint EGLIntArrayCallback :: #type proc "c" (userdata: rawptr, display: EGLDisplay, config: EGLConfig) -> [^]EGLint GLAttr :: enum c.int { - RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 3. */ - GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 3. */ - BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 2. */ - ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 0. */ + RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 8. */ + GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 8. */ + BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 8. */ + ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 8. */ BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */ DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */ DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */ @@ -167,7 +177,7 @@ GLAttr :: enum c.int { CONTEXT_FLAGS, /**< some combination of 0 or more of elements of the SDL_GLContextFlag enumeration; defaults to 0. */ CONTEXT_PROFILE_MASK, /**< type of GL context (Core, Compatibility, ES). See SDL_GLProfile; default value depends on platform. */ SHARE_WITH_CURRENT_CONTEXT, /**< OpenGL context sharing; defaults to 0. */ - FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB capable visual; defaults to 0. */ + FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB-capable visual if 1. Defaults to -1 ("don't care"). This is a request; GL drivers might not comply! */ CONTEXT_RELEASE_BEHAVIOR, /**< sets context the release behavior. See SDL_GLContextReleaseFlag; defaults to FLUSH. */ CONTEXT_RESET_NOTIFICATION, /**< set context reset notification. See SDL_GLContextResetNotification; defaults to NO_NOTIFICATION. */ CONTEXT_NO_ERROR, @@ -246,9 +256,12 @@ GL_CONTEXT_RESET_LOSE_CONTEXT :: GLContextResetNotification{.LOSE_CONTEXT} PROP_DISPLAY_HDR_ENABLED_BOOLEAN :: "SDL.display.HDR_enabled" PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER :: "SDL.display.KMSDRM.panel_orientation" +PROP_DISPLAY_WAYLAND_WL_OUTPUT_POINTER :: "SDL.display.wayland.wl_output" +PROP_DISPLAY_WINDOWS_HMONITOR_POINTER :: "SDL.display.windows.hmonitor" PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN :: "SDL.window.create.always_on_top" PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN :: "SDL.window.create.borderless" +PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN :: "SDL.window.create.constrain_popup" PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN :: "SDL.window.create.focusable" PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN :: "SDL.window.create.external_graphics_context" PROP_WINDOW_CREATE_FLAGS_NUMBER :: "SDL.window.create.flags" @@ -275,12 +288,15 @@ PROP_WINDOW_CREATE_X_NUMBER :: "SDL.window.create.x" PROP_WINDOW_CREATE_Y_NUMBER :: "SDL.window.create.y" PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER :: "SDL.window.create.cocoa.window" PROP_WINDOW_CREATE_COCOA_VIEW_POINTER :: "SDL.window.create.cocoa.view" +PROP_WINDOW_CREATE_WINDOWSCENE_POINTER :: "SDL.window.create.uikit.windowscene" PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN :: "SDL.window.create.wayland.surface_role_custom" PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN :: "SDL.window.create.wayland.create_egl_window" PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER :: "SDL.window.create.wayland.wl_surface" PROP_WINDOW_CREATE_WIN32_HWND_POINTER :: "SDL.window.create.win32.hwnd" PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER :: "SDL.window.create.win32.pixel_format_hwnd" PROP_WINDOW_CREATE_X11_WINDOW_NUMBER :: "SDL.window.create.x11.window" +PROP_WINDOW_CREATE_EMSCRIPTEN_CANVAS_ID_STRING :: "SDL.window.create.emscripten.canvas_id" +PROP_WINDOW_CREATE_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING :: "SDL.window.create.emscripten.keyboard_element" PROP_WINDOW_SHAPE_POINTER :: "SDL.window.shape" PROP_WINDOW_HDR_ENABLED_BOOLEAN :: "SDL.window.HDR_enabled" @@ -298,7 +314,7 @@ PROP_WINDOW_KMSDRM_DRM_FD_NUMBER :: "SDL.window.kmsdrm.drm_ PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER :: "SDL.window.kmsdrm.gbm_dev" PROP_WINDOW_COCOA_WINDOW_POINTER :: "SDL.window.cocoa.window" PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER :: "SDL.window.cocoa.metal_view_tag" -PROP_WINDOW_OPENVR_OVERLAY_ID :: "SDL.window.openvr.overlay_id" +PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER :: "SDL.window.openvr.overlay_id" PROP_WINDOW_VIVANTE_DISPLAY_POINTER :: "SDL.window.vivante.display" PROP_WINDOW_VIVANTE_WINDOW_POINTER :: "SDL.window.vivante.window" PROP_WINDOW_VIVANTE_SURFACE_POINTER :: "SDL.window.vivante.surface" @@ -317,6 +333,8 @@ PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER :: "SDL.window.wayland.xdg PROP_WINDOW_X11_DISPLAY_POINTER :: "SDL.window.x11.display" PROP_WINDOW_X11_SCREEN_NUMBER :: "SDL.window.x11.screen" PROP_WINDOW_X11_WINDOW_NUMBER :: "SDL.window.x11.window" +PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING :: "SDL.window.emscripten.canvas_id" +PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING :: "SDL.window.emscripten.keyboard_element" WINDOW_SURFACE_VSYNC_DISABLED :: 0 WINDOW_SURFACE_VSYNC_ADAPTIVE :: -1 @@ -377,6 +395,7 @@ foreign lib { SetWindowBordered :: proc(window: ^Window, bordered: bool) -> bool --- SetWindowResizable :: proc(window: ^Window, resizable: bool) -> bool --- SetWindowAlwaysOnTop :: proc(window: ^Window, on_top: bool) -> bool --- + SetWindowFillDocument :: proc(window: ^Window, fill: bool) -> bool --- ShowWindow :: proc(window: ^Window) -> bool --- HideWindow :: proc(window: ^Window) -> bool --- RaiseWindow :: proc(window: ^Window) -> bool --- @@ -427,6 +446,10 @@ foreign lib { SetWindowHitTest :: proc(window: ^Window, callback: HitTest, callback_data: rawptr) -> bool --- SetWindowShape :: proc(window: ^Window, shape: ^Surface) -> bool --- FlashWindow :: proc(window: ^Window, operation: FlashOperation) -> bool --- + SetWindowProgressState :: proc(window: ^Window, state: ProgressState) -> bool --- + GetWindowProgressState :: proc(window: ^Window) -> ProgressState --- + SetWindowProgressValue :: proc(window: ^Window, value: f32) -> bool --- + GetWindowProgressValue :: proc(window: ^Window) -> f32 --- DestroyWindow :: proc(window: ^Window) --- ScreenSaverEnabled :: proc() -> bool --- EnableScreenSaver :: proc() -> bool --- @@ -461,4 +484,4 @@ foreign lib { // Used by vendor:OpenGL gl_set_proc_address :: proc(p: rawptr, name: cstring) { (^FunctionPointer)(p)^ = GL_GetProcAddress(name) -} \ No newline at end of file +} diff --git a/vendor/sdl3/ttf/LICENSE.freetype.txt b/vendor/sdl3/ttf/LICENSE.freetype.txt new file mode 100644 index 000000000..c406d150f --- /dev/null +++ b/vendor/sdl3/ttf/LICENSE.freetype.txt @@ -0,0 +1,169 @@ + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + https://www.freetype.org + + +--- end of FTL.TXT --- diff --git a/vendor/sdl3/ttf/LICENSE.harfbuzz.txt b/vendor/sdl3/ttf/LICENSE.harfbuzz.txt new file mode 100644 index 000000000..1dd917e9f --- /dev/null +++ b/vendor/sdl3/ttf/LICENSE.harfbuzz.txt @@ -0,0 +1,42 @@ +HarfBuzz is licensed under the so-called "Old MIT" license. Details follow. +For parts of HarfBuzz that are licensed under different licenses see individual +files names COPYING in subdirectories where applicable. + +Copyright © 2010-2022 Google, Inc. +Copyright © 2015-2020 Ebrahim Byagowi +Copyright © 2019,2020 Facebook, Inc. +Copyright © 2012,2015 Mozilla Foundation +Copyright © 2011 Codethink Limited +Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies) +Copyright © 2009 Keith Stribley +Copyright © 2011 Martin Hosken and SIL International +Copyright © 2007 Chris Wilson +Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod +Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc. +Copyright © 1998-2005 David Turner and Werner Lemberg +Copyright © 2016 Igalia S.L. +Copyright © 2022 Matthias Clasen +Copyright © 2018,2021 Khaled Hosny +Copyright © 2018,2019,2020 Adobe, Inc +Copyright © 2013-2015 Alexei Podtelezhnikov + +For full copyright notices consult the individual files in the package. + + +Permission is hereby granted, without written agreement and without +license or royalty fees, to use, copy, modify, and distribute this +software and its documentation for any purpose, provided that the +above copyright notice and the following two paragraphs appear in +all copies of this software. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. diff --git a/vendor/sdl3/ttf/LICENSE.plutosvg.txt b/vendor/sdl3/ttf/LICENSE.plutosvg.txt new file mode 100644 index 000000000..62a964e73 --- /dev/null +++ b/vendor/sdl3/ttf/LICENSE.plutosvg.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2025 Samuel Ugochukwu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/sdl3/ttf/LICENSE.plutovg.txt b/vendor/sdl3/ttf/LICENSE.plutovg.txt new file mode 100644 index 000000000..62a964e73 --- /dev/null +++ b/vendor/sdl3/ttf/LICENSE.plutovg.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2025 Samuel Ugochukwu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/sdl3/ttf/LICENSE.txt b/vendor/sdl3/ttf/LICENSE.txt new file mode 100644 index 000000000..52d0ed38b --- /dev/null +++ b/vendor/sdl3/ttf/LICENSE.txt @@ -0,0 +1,17 @@ +Copyright (C) 1997-2025 Sam Lantinga + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/vendor/sdl3/ttf/SDL3_ttf.dll b/vendor/sdl3/ttf/SDL3_ttf.dll new file mode 100644 index 000000000..b1616f966 Binary files /dev/null and b/vendor/sdl3/ttf/SDL3_ttf.dll differ diff --git a/vendor/sdl3/ttf/SDL3_ttf.lib b/vendor/sdl3/ttf/SDL3_ttf.lib new file mode 100644 index 000000000..5716c5661 Binary files /dev/null and b/vendor/sdl3/ttf/SDL3_ttf.lib differ diff --git a/vendor/sdl3/ttf/include/SDL_textengine.h b/vendor/sdl3/ttf/include/SDL_textengine.h new file mode 100644 index 000000000..9f5f1f0c3 --- /dev/null +++ b/vendor/sdl3/ttf/include/SDL_textengine.h @@ -0,0 +1,181 @@ +/* + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 2001-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +/** + * \file SDL_textengine.h + * + * Definitions for implementations of the TTF_TextEngine interface. + */ +#ifndef SDL_TTF_TEXTENGINE_H_ +#define SDL_TTF_TEXTENGINE_H_ + +#include +#include + +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A font atlas draw command. + * + * \since This enum is available since SDL_ttf 3.0.0. + */ +typedef enum TTF_DrawCommand +{ + TTF_DRAW_COMMAND_NOOP, + TTF_DRAW_COMMAND_FILL, + TTF_DRAW_COMMAND_COPY +} TTF_DrawCommand; + +/** + * A filled rectangle draw operation. + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa TTF_DrawOperation + */ +typedef struct TTF_FillOperation +{ + TTF_DrawCommand cmd; /**< TTF_DRAW_COMMAND_FILL */ + SDL_Rect rect; /**< The rectangle to fill, in pixels. The x coordinate is relative to the left side of the text area, going right, and the y coordinate is relative to the top side of the text area, going down. */ +} TTF_FillOperation; + +/** + * A texture copy draw operation. + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa TTF_DrawOperation + */ +typedef struct TTF_CopyOperation +{ + TTF_DrawCommand cmd; /**< TTF_DRAW_COMMAND_COPY */ + int text_offset; /**< The offset in the text corresponding to this glyph. + There may be multiple glyphs with the same text offset + and the next text offset might be several Unicode codepoints + later. In this case the glyphs and codepoints are grouped + together and the group bounding box is the union of the dst + rectangles for the corresponding glyphs. */ + TTF_Font *glyph_font; /**< The font containing the glyph to be drawn, can be passed to TTF_GetGlyphImageForIndex() */ + Uint32 glyph_index; /**< The glyph index of the glyph to be drawn, can be passed to TTF_GetGlyphImageForIndex() */ + SDL_Rect src; /**< The area within the glyph to be drawn */ + SDL_Rect dst; /**< The drawing coordinates of the glyph, in pixels. The x coordinate is relative to the left side of the text area, going right, and the y coordinate is relative to the top side of the text area, going down. */ + void *reserved; +} TTF_CopyOperation; + +/** + * A text engine draw operation. + * + * \since This struct is available since SDL_ttf 3.0.0. + */ +typedef union TTF_DrawOperation +{ + TTF_DrawCommand cmd; + TTF_FillOperation fill; + TTF_CopyOperation copy; +} TTF_DrawOperation; + + +/* Private data in TTF_Text, to assist in text measurement and layout */ +typedef struct TTF_TextLayout TTF_TextLayout; + + +/* Private data in TTF_Text, available to implementations */ +struct TTF_TextData +{ + TTF_Font *font; /**< The font used by this text, read-only. */ + SDL_FColor color; /**< The color of the text, read-only. */ + + bool needs_layout_update; /**< True if the layout needs to be updated */ + TTF_TextLayout *layout; /**< Cached layout information, read-only. */ + int x; /**< The x offset of the upper left corner of this text, in pixels, read-only. */ + int y; /**< The y offset of the upper left corner of this text, in pixels, read-only. */ + int w; /**< The width of this text, in pixels, read-only. */ + int h; /**< The height of this text, in pixels, read-only. */ + int num_ops; /**< The number of drawing operations to render this text, read-only. */ + TTF_DrawOperation *ops; /**< The drawing operations used to render this text, read-only. */ + int num_clusters; /**< The number of substrings representing clusters of glyphs in the string, read-only */ + TTF_SubString *clusters; /**< Substrings representing clusters of glyphs in the string, read-only */ + + SDL_PropertiesID props; /**< Custom properties associated with this text, read-only. This field is created as-needed using TTF_GetTextProperties() and the properties may be then set and read normally */ + + bool needs_engine_update; /**< True if the engine text needs to be updated */ + TTF_TextEngine *engine; /**< The engine used to render this text, read-only. */ + void *engine_text; /**< The implementation-specific representation of this text */ +}; + +/** + * A text engine interface. + * + * This structure should be initialized using SDL_INIT_INTERFACE() + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa SDL_INIT_INTERFACE + */ +struct TTF_TextEngine +{ + Uint32 version; /**< The version of this interface */ + + void *userdata; /**< User data pointer passed to callbacks */ + + /* Create a text representation from draw instructions. + * + * All fields of `text` except `internal->engine_text` will already be filled out. + * + * This function should set the `internal->engine_text` field to a non-NULL value. + * + * \param userdata the userdata pointer in this interface. + * \param text the text object being created. + */ + bool (SDLCALL *CreateText)(void *userdata, TTF_Text *text); + + /** + * Destroy a text representation. + */ + void (SDLCALL *DestroyText)(void *userdata, TTF_Text *text); + +}; + +/* Check the size of TTF_TextEngine + * + * If this assert fails, either the compiler is padding to an unexpected size, + * or the interface has been updated and this should be updated to match and + * the code using this interface should be updated to handle the old version. + */ +SDL_COMPILE_TIME_ASSERT(TTF_TextEngine_SIZE, + (sizeof(void *) == 4 && sizeof(TTF_TextEngine) == 16) || + (sizeof(void *) == 8 && sizeof(TTF_TextEngine) == 32)); + + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_TTF_TEXTENGINE_H_ */ + diff --git a/vendor/sdl3/ttf/include/SDL_ttf.h b/vendor/sdl3/ttf/include/SDL_ttf.h new file mode 100644 index 000000000..b723bc74e --- /dev/null +++ b/vendor/sdl3/ttf/include/SDL_ttf.h @@ -0,0 +1,2833 @@ +/* + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 2001-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* WIKI CATEGORY: SDLTTF */ + +/** + * # CategorySDLTTF + * + * Header file for SDL_ttf library + * + * This library is a wrapper around the excellent FreeType 2.0 library, + * available at: https://www.freetype.org/ + */ + +#ifndef SDL_TTF_H_ +#define SDL_TTF_H_ + +#include +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Printable format: "%d.%d.%d", MAJOR, MINOR, MICRO + */ +#define SDL_TTF_MAJOR_VERSION 3 +#define SDL_TTF_MINOR_VERSION 2 +#define SDL_TTF_MICRO_VERSION 2 + +/** + * This is the version number macro for the current SDL_ttf version. + */ +#define SDL_TTF_VERSION \ + SDL_VERSIONNUM(SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_MICRO_VERSION) + +/** + * This macro will evaluate to true if compiled with SDL_ttf at least X.Y.Z. + */ +#define SDL_TTF_VERSION_ATLEAST(X, Y, Z) \ + ((SDL_TTF_MAJOR_VERSION >= X) && \ + (SDL_TTF_MAJOR_VERSION > X || SDL_TTF_MINOR_VERSION >= Y) && \ + (SDL_TTF_MAJOR_VERSION > X || SDL_TTF_MINOR_VERSION > Y || SDL_TTF_MICRO_VERSION >= Z)) + +/** + * This function gets the version of the dynamically linked SDL_ttf library. + * + * \returns SDL_ttf version. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_Version(void); + +/** + * Query the version of the FreeType library in use. + * + * TTF_Init() should be called before calling this function. + * + * \param major to be filled in with the major version number. Can be NULL. + * \param minor to be filled in with the minor version number. Can be NULL. + * \param patch to be filled in with the param version number. Can be NULL. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_Init + */ +extern SDL_DECLSPEC void SDLCALL TTF_GetFreeTypeVersion(int *major, int *minor, int *patch); + +/** + * Query the version of the HarfBuzz library in use. + * + * If HarfBuzz is not available, the version reported is 0.0.0. + * + * \param major to be filled in with the major version number. Can be NULL. + * \param minor to be filled in with the minor version number. Can be NULL. + * \param patch to be filled in with the param version number. Can be NULL. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC void SDLCALL TTF_GetHarfBuzzVersion(int *major, int *minor, int *patch); + +/** + * The internal structure containing font information. + * + * Opaque data! + */ +typedef struct TTF_Font TTF_Font; + +/** + * Initialize SDL_ttf. + * + * You must successfully call this function before it is safe to call any + * other function in this library. + * + * It is safe to call this more than once, and each successful TTF_Init() call + * should be paired with a matching TTF_Quit() call. + * + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_Quit + */ +extern SDL_DECLSPEC bool SDLCALL TTF_Init(void); + +/** + * Create a font from a file, using a specified point size. + * + * Some .fon fonts will have several sizes embedded in the file, so the point + * size becomes the index of choosing which size. If the value is too high, + * the last indexed size will be the default. + * + * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. + * + * \param file path to font file. + * \param ptsize point size to use for the newly-opened font. + * \returns a valid TTF_Font, or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CloseFont + */ +extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, float ptsize); + +/** + * Create a font from an SDL_IOStream, using a specified point size. + * + * Some .fon fonts will have several sizes embedded in the file, so the point + * size becomes the index of choosing which size. If the value is too high, + * the last indexed size will be the default. + * + * If `closeio` is true, `src` will be automatically closed once the font is + * closed. Otherwise you should close `src` yourself after closing the font. + * + * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. + * + * \param src an SDL_IOStream to provide a font file's data. + * \param closeio true to close `src` when the font is closed, false to leave + * it open. + * \param ptsize point size to use for the newly-opened font. + * \returns a valid TTF_Font, or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CloseFont + */ +extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIO(SDL_IOStream *src, bool closeio, float ptsize); + +/** + * Create a font with the specified properties. + * + * These are the supported properties: + * + * - `TTF_PROP_FONT_CREATE_FILENAME_STRING`: the font file to open, if an + * SDL_IOStream isn't being used. This is required if + * `TTF_PROP_FONT_CREATE_IOSTREAM_POINTER` and + * `TTF_PROP_FONT_CREATE_EXISTING_FONT` aren't set. + * - `TTF_PROP_FONT_CREATE_IOSTREAM_POINTER`: an SDL_IOStream containing the + * font to be opened. This should not be closed until the font is closed. + * This is required if `TTF_PROP_FONT_CREATE_FILENAME_STRING` and + * `TTF_PROP_FONT_CREATE_EXISTING_FONT` aren't set. + * - `TTF_PROP_FONT_CREATE_IOSTREAM_OFFSET_NUMBER`: the offset in the iostream + * for the beginning of the font, defaults to 0. + * - `TTF_PROP_FONT_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN`: true if closing the + * font should also close the associated SDL_IOStream. + * - `TTF_PROP_FONT_CREATE_SIZE_FLOAT`: the point size of the font. Some .fon + * fonts will have several sizes embedded in the file, so the point size + * becomes the index of choosing which size. If the value is too high, the + * last indexed size will be the default. + * - `TTF_PROP_FONT_CREATE_FACE_NUMBER`: the face index of the font, if the + * font contains multiple font faces. + * - `TTF_PROP_FONT_CREATE_HORIZONTAL_DPI_NUMBER`: the horizontal DPI to use + * for font rendering, defaults to + * `TTF_PROP_FONT_CREATE_VERTICAL_DPI_NUMBER` if set, or 72 otherwise. + * - `TTF_PROP_FONT_CREATE_VERTICAL_DPI_NUMBER`: the vertical DPI to use for + * font rendering, defaults to `TTF_PROP_FONT_CREATE_HORIZONTAL_DPI_NUMBER` + * if set, or 72 otherwise. + * - `TTF_PROP_FONT_CREATE_EXISTING_FONT`: an optional TTF_Font that, if set, + * will be used as the font data source and the initial size and style of + * the new font. + * + * \param props the properties to use. + * \returns a valid TTF_Font, or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CloseFont + */ +extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_OpenFontWithProperties(SDL_PropertiesID props); + +#define TTF_PROP_FONT_CREATE_FILENAME_STRING "SDL_ttf.font.create.filename" +#define TTF_PROP_FONT_CREATE_IOSTREAM_POINTER "SDL_ttf.font.create.iostream" +#define TTF_PROP_FONT_CREATE_IOSTREAM_OFFSET_NUMBER "SDL_ttf.font.create.iostream.offset" +#define TTF_PROP_FONT_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN "SDL_ttf.font.create.iostream.autoclose" +#define TTF_PROP_FONT_CREATE_SIZE_FLOAT "SDL_ttf.font.create.size" +#define TTF_PROP_FONT_CREATE_FACE_NUMBER "SDL_ttf.font.create.face" +#define TTF_PROP_FONT_CREATE_HORIZONTAL_DPI_NUMBER "SDL_ttf.font.create.hdpi" +#define TTF_PROP_FONT_CREATE_VERTICAL_DPI_NUMBER "SDL_ttf.font.create.vdpi" +#define TTF_PROP_FONT_CREATE_EXISTING_FONT "SDL_ttf.font.create.existing_font" + +/** + * Create a copy of an existing font. + * + * The copy will be distinct from the original, but will share the font file + * and have the same size and style as the original. + * + * When done with the returned TTF_Font, use TTF_CloseFont() to dispose of it. + * + * \param existing_font the font to copy. + * \returns a valid TTF_Font, or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * original font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CloseFont + */ +extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_CopyFont(TTF_Font *existing_font); + +/** + * Get the properties associated with a font. + * + * The following read-write properties are provided by SDL: + * + * - `TTF_PROP_FONT_OUTLINE_LINE_CAP_NUMBER`: The FT_Stroker_LineCap value + * used when setting the font outline, defaults to + * `FT_STROKER_LINECAP_ROUND`. + * - `TTF_PROP_FONT_OUTLINE_LINE_JOIN_NUMBER`: The FT_Stroker_LineJoin value + * used when setting the font outline, defaults to + * `FT_STROKER_LINEJOIN_ROUND`. + * - `TTF_PROP_FONT_OUTLINE_MITER_LIMIT_NUMBER`: The FT_Fixed miter limit used + * when setting the font outline, defaults to 0. + * + * \param font the font to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL TTF_GetFontProperties(TTF_Font *font); + +#define TTF_PROP_FONT_OUTLINE_LINE_CAP_NUMBER "SDL_ttf.font.outline.line_cap" +#define TTF_PROP_FONT_OUTLINE_LINE_JOIN_NUMBER "SDL_ttf.font.outline.line_join" +#define TTF_PROP_FONT_OUTLINE_MITER_LIMIT_NUMBER "SDL_ttf.font.outline.miter_limit" + +/** + * Get the font generation. + * + * The generation is incremented each time font properties change that require + * rebuilding glyphs, such as style, size, etc. + * + * \param font the font to query. + * \returns the font generation or 0 on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC Uint32 SDLCALL TTF_GetFontGeneration(TTF_Font *font); + +/** + * Add a fallback font. + * + * Add a font that will be used for glyphs that are not in the current font. + * The fallback font should have the same size and style as the current font. + * + * If there are multiple fallback fonts, they are used in the order added. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * \param fallback the font to add as a fallback. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created + * both fonts. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_ClearFallbackFonts + * \sa TTF_RemoveFallbackFont + */ +extern SDL_DECLSPEC bool SDLCALL TTF_AddFallbackFont(TTF_Font *font, TTF_Font *fallback); + +/** + * Remove a fallback font. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * \param fallback the font to remove as a fallback. + * + * \threadsafety This function should be called on the thread that created + * both fonts. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AddFallbackFont + * \sa TTF_ClearFallbackFonts + */ +extern SDL_DECLSPEC void SDLCALL TTF_RemoveFallbackFont(TTF_Font *font, TTF_Font *fallback); + +/** + * Remove all fallback fonts. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AddFallbackFont + * \sa TTF_RemoveFallbackFont + */ +extern SDL_DECLSPEC void SDLCALL TTF_ClearFallbackFonts(TTF_Font *font); + +/** + * Set a font's size dynamically. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * \param font the font to resize. + * \param ptsize the new point size. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontSize + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontSize(TTF_Font *font, float ptsize); + +/** + * Set font size dynamically with target resolutions, in dots per inch. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * \param font the font to resize. + * \param ptsize the new point size. + * \param hdpi the target horizontal DPI. + * \param vdpi the target vertical DPI. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontSize + * \sa TTF_GetFontSizeDPI + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontSizeDPI(TTF_Font *font, float ptsize, int hdpi, int vdpi); + +/** + * Get the size of a font. + * + * \param font the font to query. + * \returns the size of the font, or 0.0f on failure; call SDL_GetError() for + * more information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontSize + * \sa TTF_SetFontSizeDPI + */ +extern SDL_DECLSPEC float SDLCALL TTF_GetFontSize(TTF_Font *font); + +/** + * Get font target resolutions, in dots per inch. + * + * \param font the font to query. + * \param hdpi a pointer filled in with the target horizontal DPI. + * \param vdpi a pointer filled in with the target vertical DPI. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontSizeDPI + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetFontDPI(TTF_Font *font, int *hdpi, int *vdpi); + +/** + * Font style flags for TTF_Font + * + * These are the flags which can be used to set the style of a font in + * SDL_ttf. A combination of these flags can be used with functions that set + * or query font style, such as TTF_SetFontStyle or TTF_GetFontStyle. + * + * \since This datatype is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontStyle + * \sa TTF_GetFontStyle + */ +typedef Uint32 TTF_FontStyleFlags; + +#define TTF_STYLE_NORMAL 0x00 /**< No special style */ +#define TTF_STYLE_BOLD 0x01 /**< Bold style */ +#define TTF_STYLE_ITALIC 0x02 /**< Italic style */ +#define TTF_STYLE_UNDERLINE 0x04 /**< Underlined text */ +#define TTF_STYLE_STRIKETHROUGH 0x08 /**< Strikethrough text */ + +/** + * Set a font's current style. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * The font styles are a set of bit flags, OR'd together: + * + * - `TTF_STYLE_NORMAL` (is zero) + * - `TTF_STYLE_BOLD` + * - `TTF_STYLE_ITALIC` + * - `TTF_STYLE_UNDERLINE` + * - `TTF_STYLE_STRIKETHROUGH` + * + * \param font the font to set a new style on. + * \param style the new style values to set, OR'd together. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontStyle + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, TTF_FontStyleFlags style); + +/** + * Query a font's current style. + * + * The font styles are a set of bit flags, OR'd together: + * + * - `TTF_STYLE_NORMAL` (is zero) + * - `TTF_STYLE_BOLD` + * - `TTF_STYLE_ITALIC` + * - `TTF_STYLE_UNDERLINE` + * - `TTF_STYLE_STRIKETHROUGH` + * + * \param font the font to query. + * \returns the current font style, as a set of bit flags. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontStyle + */ +extern SDL_DECLSPEC TTF_FontStyleFlags SDLCALL TTF_GetFontStyle(const TTF_Font *font); + +/** + * Set a font's current outline. + * + * This uses the font properties `TTF_PROP_FONT_OUTLINE_LINE_CAP_NUMBER`, + * `TTF_PROP_FONT_OUTLINE_LINE_JOIN_NUMBER`, and + * `TTF_PROP_FONT_OUTLINE_MITER_LIMIT_NUMBER` when setting the font outline. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * \param font the font to set a new outline on. + * \param outline positive outline value, 0 to default. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontOutline + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline); + +/** + * Query a font's current outline. + * + * \param font the font to query. + * \returns the font's current outline value. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontOutline + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font); + +/** + * Hinting flags for TTF (TrueType Fonts) + * + * This enum specifies the level of hinting to be applied to the font + * rendering. The hinting level determines how much the font's outlines are + * adjusted for better alignment on the pixel grid. + * + * \since This enum is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontHinting + * \sa TTF_GetFontHinting + */ +typedef enum TTF_HintingFlags +{ + TTF_HINTING_INVALID = -1, + TTF_HINTING_NORMAL, /**< Normal hinting applies standard grid-fitting. */ + TTF_HINTING_LIGHT, /**< Light hinting applies subtle adjustments to improve rendering. */ + TTF_HINTING_MONO, /**< Monochrome hinting adjusts the font for better rendering at lower resolutions. */ + TTF_HINTING_NONE, /**< No hinting, the font is rendered without any grid-fitting. */ + TTF_HINTING_LIGHT_SUBPIXEL /**< Light hinting with subpixel rendering for more precise font edges. */ +} TTF_HintingFlags; + +/** + * Set a font's current hinter setting. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * The hinter setting is a single value: + * + * - `TTF_HINTING_NORMAL` + * - `TTF_HINTING_LIGHT` + * - `TTF_HINTING_MONO` + * - `TTF_HINTING_NONE` + * - `TTF_HINTING_LIGHT_SUBPIXEL` (available in SDL_ttf 3.0.0 and later) + * + * \param font the font to set a new hinter setting on. + * \param hinting the new hinter setting. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontHinting + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, TTF_HintingFlags hinting); + +/** + * Query the number of faces of a font. + * + * \param font the font to query. + * \returns the number of FreeType font faces. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetNumFontFaces(const TTF_Font *font); + +/** + * Query a font's current FreeType hinter setting. + * + * The hinter setting is a single value: + * + * - `TTF_HINTING_NORMAL` + * - `TTF_HINTING_LIGHT` + * - `TTF_HINTING_MONO` + * - `TTF_HINTING_NONE` + * - `TTF_HINTING_LIGHT_SUBPIXEL` (available in SDL_ttf 3.0.0 and later) + * + * \param font the font to query. + * \returns the font's current hinter value, or TTF_HINTING_INVALID if the + * font is invalid. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontHinting + */ +extern SDL_DECLSPEC TTF_HintingFlags SDLCALL TTF_GetFontHinting(const TTF_Font *font); + +/** + * Enable Signed Distance Field rendering for a font. + * + * SDF is a technique that helps fonts look sharp even when scaling and + * rotating, and requires special shader support for display. + * + * This works with Blended APIs, and generates the raw signed distance values + * in the alpha channel of the resulting texture. + * + * This updates any TTF_Text objects using this font, and clears + * already-generated glyphs, if any, from the cache. + * + * \param font the font to set SDF support on. + * \param enabled true to enable SDF, false to disable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontSDF + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontSDF(TTF_Font *font, bool enabled); + +/** + * Query whether Signed Distance Field rendering is enabled for a font. + * + * \param font the font to query. + * \returns true if enabled, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontSDF + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetFontSDF(const TTF_Font *font); + +/** + * Query a font's weight, in terms of the lightness/heaviness of the strokes. + * + * \param font the font to query. + * \returns the font's current weight. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.4.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontWeight(const TTF_Font *font); + +#define TTF_FONT_WEIGHT_THIN 100 /**< Thin (100) named font weight value */ +#define TTF_FONT_WEIGHT_EXTRA_LIGHT 200 /**< ExtraLight (200) named font weight value */ +#define TTF_FONT_WEIGHT_LIGHT 300 /**< Light (300) named font weight value */ +#define TTF_FONT_WEIGHT_NORMAL 400 /**< Normal (400) named font weight value */ +#define TTF_FONT_WEIGHT_MEDIUM 500 /**< Medium (500) named font weight value */ +#define TTF_FONT_WEIGHT_SEMI_BOLD 600 /**< SemiBold (600) named font weight value */ +#define TTF_FONT_WEIGHT_BOLD 700 /**< Bold (700) named font weight value */ +#define TTF_FONT_WEIGHT_EXTRA_BOLD 800 /**< ExtraBold (800) named font weight value */ +#define TTF_FONT_WEIGHT_BLACK 900 /**< Black (900) named font weight value */ +#define TTF_FONT_WEIGHT_EXTRA_BLACK 950 /**< ExtraBlack (950) named font weight value */ + +/** + * The horizontal alignment used when rendering wrapped text. + * + * \since This enum is available since SDL_ttf 3.0.0. + */ +typedef enum TTF_HorizontalAlignment +{ + TTF_HORIZONTAL_ALIGN_INVALID = -1, + TTF_HORIZONTAL_ALIGN_LEFT, + TTF_HORIZONTAL_ALIGN_CENTER, + TTF_HORIZONTAL_ALIGN_RIGHT +} TTF_HorizontalAlignment; + +/** + * Set a font's current wrap alignment option. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to set a new wrap alignment option on. + * \param align the new wrap alignment option. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontWrapAlignment + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetFontWrapAlignment(TTF_Font *font, TTF_HorizontalAlignment align); + +/** + * Query a font's current wrap alignment option. + * + * \param font the font to query. + * \returns the font's current wrap alignment option. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontWrapAlignment + */ +extern SDL_DECLSPEC TTF_HorizontalAlignment SDLCALL TTF_GetFontWrapAlignment(const TTF_Font *font); + +/** + * Query the total height of a font. + * + * This is usually equal to point size. + * + * \param font the font to query. + * \returns the font's height. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontHeight(const TTF_Font *font); + +/** + * Query the offset from the baseline to the top of a font. + * + * This is a positive value, relative to the baseline. + * + * \param font the font to query. + * \returns the font's ascent. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontAscent(const TTF_Font *font); + +/** + * Query the offset from the baseline to the bottom of a font. + * + * This is a negative value, relative to the baseline. + * + * \param font the font to query. + * \returns the font's descent. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontDescent(const TTF_Font *font); + +/** + * Set the spacing between lines of text for a font. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * \param lineskip the new line spacing for the font. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontLineSkip + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetFontLineSkip(TTF_Font *font, int lineskip); + +/** + * Query the spacing between lines of text for a font. + * + * \param font the font to query. + * \returns the font's recommended spacing. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontLineSkip + */ +extern SDL_DECLSPEC int SDLCALL TTF_GetFontLineSkip(const TTF_Font *font); + +/** + * Set if kerning is enabled for a font. + * + * Newly-opened fonts default to allowing kerning. This is generally a good + * policy unless you have a strong reason to disable it, as it tends to + * produce better rendering (with kerning disabled, some fonts might render + * the word `kerning` as something that looks like `keming` for example). + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to set kerning on. + * \param enabled true to enable kerning, false to disable. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetFontKerning + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, bool enabled); + +/** + * Query whether or not kerning is enabled for a font. + * + * \param font the font to query. + * \returns true if kerning is enabled, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontKerning + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetFontKerning(const TTF_Font *font); + +/** + * Query whether a font is fixed-width. + * + * A "fixed-width" font means all glyphs are the same width across; a + * lowercase 'i' will be the same size across as a capital 'W', for example. + * This is common for terminals and text editors, and other apps that treat + * text as a grid. Most other things (WYSIWYG word processors, web pages, etc) + * are more likely to not be fixed-width in most cases. + * + * \param font the font to query. + * \returns true if the font is fixed-width, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_FontIsFixedWidth(const TTF_Font *font); + +/** + * Query whether a font is scalable or not. + * + * Scalability lets us distinguish between outline and bitmap fonts. + * + * \param font the font to query. + * \returns true if the font is scalable, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontSDF + */ +extern SDL_DECLSPEC bool SDLCALL TTF_FontIsScalable(const TTF_Font *font); + +/** + * Query a font's family name. + * + * This string is dictated by the contents of the font file. + * + * Note that the returned string is to internal storage, and should not be + * modified or free'd by the caller. The string becomes invalid, with the rest + * of the font, when `font` is handed to TTF_CloseFont(). + * + * \param font the font to query. + * \returns the font's family name. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC const char * SDLCALL TTF_GetFontFamilyName(const TTF_Font *font); + +/** + * Query a font's style name. + * + * This string is dictated by the contents of the font file. + * + * Note that the returned string is to internal storage, and should not be + * modified or free'd by the caller. The string becomes invalid, with the rest + * of the font, when `font` is handed to TTF_CloseFont(). + * + * \param font the font to query. + * \returns the font's style name. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC const char * SDLCALL TTF_GetFontStyleName(const TTF_Font *font); + +/** + * Direction flags + * + * The values here are chosen to match + * [hb_direction_t](https://harfbuzz.github.io/harfbuzz-hb-common.html#hb-direction-t) + * . + * + * \since This enum is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetFontDirection + */ +typedef enum TTF_Direction +{ + TTF_DIRECTION_INVALID = 0, + TTF_DIRECTION_LTR = 4, /**< Left to Right */ + TTF_DIRECTION_RTL, /**< Right to Left */ + TTF_DIRECTION_TTB, /**< Top to Bottom */ + TTF_DIRECTION_BTT /**< Bottom to Top */ +} TTF_Direction; + +/** + * Set the direction to be used for text shaping by a font. + * + * This function only supports left-to-right text shaping if SDL_ttf was not + * built with HarfBuzz support. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * \param direction the new direction for text to flow. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontDirection(TTF_Font *font, TTF_Direction direction); + +/** + * Get the direction to be used for text shaping by a font. + * + * This defaults to TTF_DIRECTION_INVALID if it hasn't been set. + * + * \param font the font to query. + * \returns the direction to be used for text shaping. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC TTF_Direction SDLCALL TTF_GetFontDirection(TTF_Font *font); + +/** + * Convert from a 4 character string to a 32-bit tag. + * + * \param string the 4 character string to convert. + * \returns the 32-bit representation of the string. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TagToString + */ +extern SDL_DECLSPEC Uint32 SDLCALL TTF_StringToTag(const char *string); + +/** + * Convert from a 32-bit tag to a 4 character string. + * + * \param tag the 32-bit tag to convert. + * \param string a pointer filled in with the 4 character representation of + * the tag. + * \param size the size of the buffer pointed at by string, should be at least + * 4. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TagToString + */ +extern SDL_DECLSPEC void SDLCALL TTF_TagToString(Uint32 tag, char *string, size_t size); + +/** + * Set the script to be used for text shaping by a font. + * + * This returns false if SDL_ttf isn't built with HarfBuzz support. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to modify. + * \param script an + * [ISO 15924 code](https://unicode.org/iso15924/iso15924-codes.html) + * . + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_StringToTag + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontScript(TTF_Font *font, Uint32 script); + +/** + * Get the script used for text shaping a font. + * + * \param font the font to query. + * \returns an + * [ISO 15924 code](https://unicode.org/iso15924/iso15924-codes.html) + * or 0 if a script hasn't been set. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TagToString + */ +extern SDL_DECLSPEC Uint32 SDLCALL TTF_GetFontScript(TTF_Font *font); + +/** + * Get the script used by a 32-bit codepoint. + * + * \param ch the character code to check. + * \returns an + * [ISO 15924 code](https://unicode.org/iso15924/iso15924-codes.html) + * on success, or 0 on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function is thread-safe. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TagToString + */ +extern SDL_DECLSPEC Uint32 SDLCALL TTF_GetGlyphScript(Uint32 ch); + +/** + * Set language to be used for text shaping by a font. + * + * If SDL_ttf was not built with HarfBuzz support, this function returns + * false. + * + * This updates any TTF_Text objects using this font. + * + * \param font the font to specify a language for. + * \param language_bcp47 a null-terminated string containing the desired + * language's BCP47 code. Or null to reset the value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetFontLanguage(TTF_Font *font, const char *language_bcp47); + +/** + * Check whether a glyph is provided by the font for a UNICODE codepoint. + * + * \param font the font to query. + * \param ch the codepoint to check. + * \returns true if font provides a glyph for this character, false if not. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_FontHasGlyph(TTF_Font *font, Uint32 ch); + +/** + * The type of data in a glyph image + * + * \since This enum is available since SDL_ttf 3.0.0. + */ +typedef enum TTF_ImageType +{ + TTF_IMAGE_INVALID, + TTF_IMAGE_ALPHA, /**< The color channels are white */ + TTF_IMAGE_COLOR, /**< The color channels have image data */ + TTF_IMAGE_SDF, /**< The alpha channel has signed distance field information */ +} TTF_ImageType; + +/** + * Get the pixel image for a UNICODE codepoint. + * + * \param font the font to query. + * \param ch the codepoint to check. + * \param image_type a pointer filled in with the glyph image type, may be + * NULL. + * \returns an SDL_Surface containing the glyph, or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_GetGlyphImage(TTF_Font *font, Uint32 ch, TTF_ImageType *image_type); + +/** + * Get the pixel image for a character index. + * + * This is useful for text engine implementations, which can call this with + * the `glyph_index` in a TTF_CopyOperation + * + * \param font the font to query. + * \param glyph_index the index of the glyph to return. + * \param image_type a pointer filled in with the glyph image type, may be + * NULL. + * \returns an SDL_Surface containing the glyph, or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_GetGlyphImageForIndex(TTF_Font *font, Uint32 glyph_index, TTF_ImageType *image_type); + +/** + * Query the metrics (dimensions) of a font's glyph for a UNICODE codepoint. + * + * To understand what these metrics mean, here is a useful link: + * + * https://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html + * + * \param font the font to query. + * \param ch the codepoint to check. + * \param minx a pointer filled in with the minimum x coordinate of the glyph + * from the left edge of its bounding box. This value may be + * negative. + * \param maxx a pointer filled in with the maximum x coordinate of the glyph + * from the left edge of its bounding box. + * \param miny a pointer filled in with the minimum y coordinate of the glyph + * from the bottom edge of its bounding box. This value may be + * negative. + * \param maxy a pointer filled in with the maximum y coordinate of the glyph + * from the bottom edge of its bounding box. + * \param advance a pointer filled in with the distance to the next glyph from + * the left edge of this glyph's bounding box. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetGlyphMetrics(TTF_Font *font, Uint32 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance); + +/** + * Query the kerning size between the glyphs of two UNICODE codepoints. + * + * \param font the font to query. + * \param previous_ch the previous codepoint. + * \param ch the current codepoint. + * \param kerning a pointer filled in with the kerning size between the two + * glyphs, in pixels, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetGlyphKerning(TTF_Font *font, Uint32 previous_ch, Uint32 ch, int *kerning); + +/** + * Calculate the dimensions of a rendered string of UTF-8 text. + * + * This will report the width and height, in pixels, of the space that the + * specified string will take to fully render. + * + * \param font the font to query. + * \param text text to calculate, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param w will be filled with width, in pixels, on return. + * \param h will be filled with height, in pixels, on return. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSize(TTF_Font *font, const char *text, size_t length, int *w, int *h); + +/** + * Calculate the dimensions of a rendered string of UTF-8 text. + * + * This will report the width and height, in pixels, of the space that the + * specified string will take to fully render. + * + * Text is wrapped to multiple lines on line endings and on word boundaries if + * it extends beyond `wrap_width` in pixels. + * + * If wrap_width is 0, this function will only wrap on newline characters. + * + * \param font the font to query. + * \param text text to calculate, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param wrap_width the maximum width or 0 to wrap on newline characters. + * \param w will be filled with width, in pixels, on return. + * \param h will be filled with height, in pixels, on return. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrap_width, int *w, int *h); + +/** + * Calculate how much of a UTF-8 string will fit in a given width. + * + * This reports the number of characters that can be rendered before reaching + * `max_width`. + * + * This does not need to render the string to do this calculation. + * + * \param font the font to query. + * \param text text to calculate, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param max_width maximum width, in pixels, available for the string, or 0 + * for unbounded width. + * \param measured_width a pointer filled in with the width, in pixels, of the + * string that will fit, may be NULL. + * \param measured_length a pointer filled in with the length, in bytes, of + * the string that will fit, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_MeasureString(TTF_Font *font, const char *text, size_t length, int max_width, int *measured_width, size_t *measured_length); + +/** + * Render UTF-8 text at fast quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel + * will be set to the text color. + * + * This will not word-wrap the string; you'll get a surface with a single line + * of text, as long as the string requires. You can use + * TTF_RenderText_Solid_Wrapped() instead if you need to wrap the output to + * multiple lines. + * + * This will not wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Shaded, + * TTF_RenderText_Blended, and TTF_RenderText_LCD. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended + * \sa TTF_RenderText_LCD + * \sa TTF_RenderText_Shaded + * \sa TTF_RenderText_Solid + * \sa TTF_RenderText_Solid_Wrapped + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font, const char *text, size_t length, SDL_Color fg); + +/** + * Render word-wrapped UTF-8 text at fast quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel + * will be set to the text color. + * + * Text is wrapped to multiple lines on line endings and on word boundaries if + * it extends beyond `wrapLength` in pixels. + * + * If wrapLength is 0, this function will only wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Shaded_Wrapped, + * TTF_RenderText_Blended_Wrapped, and TTF_RenderText_LCD_Wrapped. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param wrapLength the maximum width of the text surface or 0 to wrap on + * newline characters. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended_Wrapped + * \sa TTF_RenderText_LCD_Wrapped + * \sa TTF_RenderText_Shaded_Wrapped + * \sa TTF_RenderText_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, int wrapLength); + +/** + * Render a single 32-bit glyph at fast quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the colorkey, giving a transparent background. The 1 pixel + * will be set to the text color. + * + * The glyph is rendered without any padding or centering in the X direction, + * and aligned normally in the Y direction. + * + * You can render at other quality levels with TTF_RenderGlyph_Shaded, + * TTF_RenderGlyph_Blended, and TTF_RenderGlyph_LCD. + * + * \param font the font to render with. + * \param ch the character to render. + * \param fg the foreground color for the text. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderGlyph_Blended + * \sa TTF_RenderGlyph_LCD + * \sa TTF_RenderGlyph_Shaded + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font, Uint32 ch, SDL_Color fg); + +/** + * Render UTF-8 text at high quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the specified background color, while other pixels have + * varying degrees of the foreground color. This function returns the new + * surface, or NULL if there was an error. + * + * This will not word-wrap the string; you'll get a surface with a single line + * of text, as long as the string requires. You can use + * TTF_RenderText_Shaded_Wrapped() instead if you need to wrap the output to + * multiple lines. + * + * This will not wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid, + * TTF_RenderText_Blended, and TTF_RenderText_LCD. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended + * \sa TTF_RenderText_LCD + * \sa TTF_RenderText_Shaded_Wrapped + * \sa TTF_RenderText_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg); + +/** + * Render word-wrapped UTF-8 text at high quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the specified background color, while other pixels have + * varying degrees of the foreground color. This function returns the new + * surface, or NULL if there was an error. + * + * Text is wrapped to multiple lines on line endings and on word boundaries if + * it extends beyond `wrap_width` in pixels. + * + * If wrap_width is 0, this function will only wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, + * TTF_RenderText_Blended_Wrapped, and TTF_RenderText_LCD_Wrapped. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \param wrap_width the maximum width of the text surface or 0 to wrap on + * newline characters. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended_Wrapped + * \sa TTF_RenderText_LCD_Wrapped + * \sa TTF_RenderText_Shaded + * \sa TTF_RenderText_Solid_Wrapped + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrap_width); + +/** + * Render a single UNICODE codepoint at high quality to a new 8-bit surface. + * + * This function will allocate a new 8-bit, palettized surface. The surface's + * 0 pixel will be the specified background color, while other pixels have + * varying degrees of the foreground color. This function returns the new + * surface, or NULL if there was an error. + * + * The glyph is rendered without any padding or centering in the X direction, + * and aligned normally in the Y direction. + * + * You can render at other quality levels with TTF_RenderGlyph_Solid, + * TTF_RenderGlyph_Blended, and TTF_RenderGlyph_LCD. + * + * \param font the font to render with. + * \param ch the codepoint to render. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \returns a new 8-bit, palettized surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderGlyph_Blended + * \sa TTF_RenderGlyph_LCD + * \sa TTF_RenderGlyph_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg); + +/** + * Render UTF-8 text at high quality to a new ARGB surface. + * + * This function will allocate a new 32-bit, ARGB surface, using alpha + * blending to dither the font with the given color. This function returns the + * new surface, or NULL if there was an error. + * + * This will not word-wrap the string; you'll get a surface with a single line + * of text, as long as the string requires. You can use + * TTF_RenderText_Blended_Wrapped() instead if you need to wrap the output to + * multiple lines. + * + * This will not wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid, + * TTF_RenderText_Shaded, and TTF_RenderText_LCD. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended_Wrapped + * \sa TTF_RenderText_LCD + * \sa TTF_RenderText_Shaded + * \sa TTF_RenderText_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font, const char *text, size_t length, SDL_Color fg); + +/** + * Render word-wrapped UTF-8 text at high quality to a new ARGB surface. + * + * This function will allocate a new 32-bit, ARGB surface, using alpha + * blending to dither the font with the given color. This function returns the + * new surface, or NULL if there was an error. + * + * Text is wrapped to multiple lines on line endings and on word boundaries if + * it extends beyond `wrap_width` in pixels. + * + * If wrap_width is 0, this function will only wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, + * TTF_RenderText_Shaded_Wrapped, and TTF_RenderText_LCD_Wrapped. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param wrap_width the maximum width of the text surface or 0 to wrap on + * newline characters. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended + * \sa TTF_RenderText_LCD_Wrapped + * \sa TTF_RenderText_Shaded_Wrapped + * \sa TTF_RenderText_Solid_Wrapped + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, int wrap_width); + +/** + * Render a single UNICODE codepoint at high quality to a new ARGB surface. + * + * This function will allocate a new 32-bit, ARGB surface, using alpha + * blending to dither the font with the given color. This function returns the + * new surface, or NULL if there was an error. + * + * The glyph is rendered without any padding or centering in the X direction, + * and aligned normally in the Y direction. + * + * You can render at other quality levels with TTF_RenderGlyph_Solid, + * TTF_RenderGlyph_Shaded, and TTF_RenderGlyph_LCD. + * + * \param font the font to render with. + * \param ch the codepoint to render. + * \param fg the foreground color for the text. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderGlyph_LCD + * \sa TTF_RenderGlyph_Shaded + * \sa TTF_RenderGlyph_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font, Uint32 ch, SDL_Color fg); + +/** + * Render UTF-8 text at LCD subpixel quality to a new ARGB surface. + * + * This function will allocate a new 32-bit, ARGB surface, and render + * alpha-blended text using FreeType's LCD subpixel rendering. This function + * returns the new surface, or NULL if there was an error. + * + * This will not word-wrap the string; you'll get a surface with a single line + * of text, as long as the string requires. You can use + * TTF_RenderText_LCD_Wrapped() instead if you need to wrap the output to + * multiple lines. + * + * This will not wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid, + * TTF_RenderText_Shaded, and TTF_RenderText_Blended. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended + * \sa TTF_RenderText_LCD_Wrapped + * \sa TTF_RenderText_Shaded + * \sa TTF_RenderText_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg); + +/** + * Render word-wrapped UTF-8 text at LCD subpixel quality to a new ARGB + * surface. + * + * This function will allocate a new 32-bit, ARGB surface, and render + * alpha-blended text using FreeType's LCD subpixel rendering. This function + * returns the new surface, or NULL if there was an error. + * + * Text is wrapped to multiple lines on line endings and on word boundaries if + * it extends beyond `wrap_width` in pixels. + * + * If wrap_width is 0, this function will only wrap on newline characters. + * + * You can render at other quality levels with TTF_RenderText_Solid_Wrapped, + * TTF_RenderText_Shaded_Wrapped, and TTF_RenderText_Blended_Wrapped. + * + * \param font the font to render with. + * \param text text to render, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \param wrap_width the maximum width of the text surface or 0 to wrap on + * newline characters. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderText_Blended_Wrapped + * \sa TTF_RenderText_LCD + * \sa TTF_RenderText_Shaded_Wrapped + * \sa TTF_RenderText_Solid_Wrapped + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrap_width); + +/** + * Render a single UNICODE codepoint at LCD subpixel quality to a new ARGB + * surface. + * + * This function will allocate a new 32-bit, ARGB surface, and render + * alpha-blended text using FreeType's LCD subpixel rendering. This function + * returns the new surface, or NULL if there was an error. + * + * The glyph is rendered without any padding or centering in the X direction, + * and aligned normally in the Y direction. + * + * You can render at other quality levels with TTF_RenderGlyph_Solid, + * TTF_RenderGlyph_Shaded, and TTF_RenderGlyph_Blended. + * + * \param font the font to render with. + * \param ch the codepoint to render. + * \param fg the foreground color for the text. + * \param bg the background color for the text. + * \returns a new 32-bit, ARGB surface, or NULL if there was an error. + * + * \threadsafety This function should be called on the thread that created the + * font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_RenderGlyph_Blended + * \sa TTF_RenderGlyph_Shaded + * \sa TTF_RenderGlyph_Solid + */ +extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_LCD(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg); + + +/** + * A text engine used to create text objects. + * + * This is a public interface that can be used by applications and libraries + * to perform customize rendering with text objects. See + * for details. + * + * There are three text engines provided with the library: + * + * - Drawing to an SDL_Surface, created with TTF_CreateSurfaceTextEngine() + * - Drawing with an SDL 2D renderer, created with + * TTF_CreateRendererTextEngine() + * - Drawing with the SDL GPU API, created with TTF_CreateGPUTextEngine() + * + * \since This struct is available since SDL_ttf 3.0.0. + */ +typedef struct TTF_TextEngine TTF_TextEngine; + +/** + * Internal data for TTF_Text + * + * \since This struct is available since SDL_ttf 3.0.0. + */ +typedef struct TTF_TextData TTF_TextData; + +/** + * Text created with TTF_CreateText() + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateText + * \sa TTF_GetTextProperties + * \sa TTF_DestroyText + */ +typedef struct TTF_Text +{ + char *text; /**< A copy of the UTF-8 string that this text object represents, useful for layout, debugging and retrieving substring text. This is updated when the text object is modified and will be freed automatically when the object is destroyed. */ + int num_lines; /**< The number of lines in the text, 0 if it's empty */ + + int refcount; /**< Application reference count, used when freeing surface */ + + TTF_TextData *internal; /**< Private */ + +} TTF_Text; + +/** + * Create a text engine for drawing text on SDL surfaces. + * + * \returns a TTF_TextEngine object or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_DestroySurfaceTextEngine + * \sa TTF_DrawSurfaceText + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateSurfaceTextEngine(void); + +/** + * Draw text to an SDL surface. + * + * `text` must have been created using a TTF_TextEngine from + * TTF_CreateSurfaceTextEngine(). + * + * \param text the text to draw. + * \param x the x coordinate in pixels, positive from the left edge towards + * the right. + * \param y the y coordinate in pixels, positive from the top edge towards the + * bottom. + * \param surface the surface to draw on. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateSurfaceTextEngine + * \sa TTF_CreateText + */ +extern SDL_DECLSPEC bool SDLCALL TTF_DrawSurfaceText(TTF_Text *text, int x, int y, SDL_Surface *surface); + +/** + * Destroy a text engine created for drawing text on SDL surfaces. + * + * All text created by this engine should be destroyed before calling this + * function. + * + * \param engine a TTF_TextEngine object created with + * TTF_CreateSurfaceTextEngine(). + * + * \threadsafety This function should be called on the thread that created the + * engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateSurfaceTextEngine + */ +extern SDL_DECLSPEC void SDLCALL TTF_DestroySurfaceTextEngine(TTF_TextEngine *engine); + +/** + * Create a text engine for drawing text on an SDL renderer. + * + * \param renderer the renderer to use for creating textures and drawing text. + * \returns a TTF_TextEngine object or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_DestroyRendererTextEngine + * \sa TTF_DrawRendererText + * \sa TTF_CreateRendererTextEngineWithProperties + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateRendererTextEngine(SDL_Renderer *renderer); + +/** + * Create a text engine for drawing text on an SDL renderer, with the + * specified properties. + * + * These are the supported properties: + * + * - `TTF_PROP_RENDERER_TEXT_ENGINE_RENDERER`: the renderer to use for + * creating textures and drawing text + * - `TTF_PROP_RENDERER_TEXT_ENGINE_ATLAS_TEXTURE_SIZE`: the size of the + * texture atlas + * + * \param props the properties to use. + * \returns a TTF_TextEngine object or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateRendererTextEngine + * \sa TTF_DestroyRendererTextEngine + * \sa TTF_DrawRendererText + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateRendererTextEngineWithProperties(SDL_PropertiesID props); + +#define TTF_PROP_RENDERER_TEXT_ENGINE_RENDERER "SDL_ttf.renderer_text_engine.create.renderer" +#define TTF_PROP_RENDERER_TEXT_ENGINE_ATLAS_TEXTURE_SIZE "SDL_ttf.renderer_text_engine.create.atlas_texture_size" + +/** + * Draw text to an SDL renderer. + * + * `text` must have been created using a TTF_TextEngine from + * TTF_CreateRendererTextEngine(), and will draw using the renderer passed to + * that function. + * + * \param text the text to draw. + * \param x the x coordinate in pixels, positive from the left edge towards + * the right. + * \param y the y coordinate in pixels, positive from the top edge towards the + * bottom. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateRendererTextEngine + * \sa TTF_CreateText + */ +extern SDL_DECLSPEC bool SDLCALL TTF_DrawRendererText(TTF_Text *text, float x, float y); + +/** + * Destroy a text engine created for drawing text on an SDL renderer. + * + * All text created by this engine should be destroyed before calling this + * function. + * + * \param engine a TTF_TextEngine object created with + * TTF_CreateRendererTextEngine(). + * + * \threadsafety This function should be called on the thread that created the + * engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateRendererTextEngine + */ +extern SDL_DECLSPEC void SDLCALL TTF_DestroyRendererTextEngine(TTF_TextEngine *engine); + +/** + * Create a text engine for drawing text with the SDL GPU API. + * + * \param device the SDL_GPUDevice to use for creating textures and drawing + * text. + * \returns a TTF_TextEngine object or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should be called on the thread that created the + * device. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateGPUTextEngineWithProperties + * \sa TTF_DestroyGPUTextEngine + * \sa TTF_GetGPUTextDrawData + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateGPUTextEngine(SDL_GPUDevice *device); + +/** + * Create a text engine for drawing text with the SDL GPU API, with the + * specified properties. + * + * These are the supported properties: + * + * - `TTF_PROP_GPU_TEXT_ENGINE_DEVICE`: the SDL_GPUDevice to use for creating + * textures and drawing text. + * - `TTF_PROP_GPU_TEXT_ENGINE_ATLAS_TEXTURE_SIZE`: the size of the texture + * atlas + * + * \param props the properties to use. + * \returns a TTF_TextEngine object or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety This function should be called on the thread that created the + * device. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateGPUTextEngine + * \sa TTF_DestroyGPUTextEngine + * \sa TTF_GetGPUTextDrawData + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateGPUTextEngineWithProperties(SDL_PropertiesID props); + +#define TTF_PROP_GPU_TEXT_ENGINE_DEVICE "SDL_ttf.gpu_text_engine.create.device" +#define TTF_PROP_GPU_TEXT_ENGINE_ATLAS_TEXTURE_SIZE "SDL_ttf.gpu_text_engine.create.atlas_texture_size" + +/** + * Draw sequence returned by TTF_GetGPUTextDrawData + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetGPUTextDrawData + */ +typedef struct TTF_GPUAtlasDrawSequence +{ + SDL_GPUTexture *atlas_texture; /**< Texture atlas that stores the glyphs */ + SDL_FPoint *xy; /**< An array of vertex positions */ + SDL_FPoint *uv; /**< An array of normalized texture coordinates for each vertex */ + int num_vertices; /**< Number of vertices */ + int *indices; /**< An array of indices into the 'vertices' arrays */ + int num_indices; /**< Number of indices */ + TTF_ImageType image_type; /**< The image type of this draw sequence */ + + struct TTF_GPUAtlasDrawSequence *next; /**< The next sequence (will be NULL in case of the last sequence) */ +} TTF_GPUAtlasDrawSequence; + +/** + * Get the geometry data needed for drawing the text. + * + * `text` must have been created using a TTF_TextEngine from + * TTF_CreateGPUTextEngine(). + * + * The positive X-axis is taken towards the right and the positive Y-axis is + * taken upwards for both the vertex and the texture coordinates, i.e, it + * follows the same convention used by the SDL_GPU API. If you want to use a + * different coordinate system you will need to transform the vertices + * yourself. + * + * If the text looks blocky use linear filtering. + * + * \param text the text to draw. + * \returns a NULL terminated linked list of TTF_GPUAtlasDrawSequence objects + * or NULL if the passed text is empty or in case of failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateGPUTextEngine + * \sa TTF_CreateText + */ +extern SDL_DECLSPEC TTF_GPUAtlasDrawSequence * SDLCALL TTF_GetGPUTextDrawData(TTF_Text *text); + +/** + * Destroy a text engine created for drawing text with the SDL GPU API. + * + * All text created by this engine should be destroyed before calling this + * function. + * + * \param engine a TTF_TextEngine object created with + * TTF_CreateGPUTextEngine(). + * + * \threadsafety This function should be called on the thread that created the + * engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateGPUTextEngine + */ +extern SDL_DECLSPEC void SDLCALL TTF_DestroyGPUTextEngine(TTF_TextEngine *engine); + +/** + * The winding order of the vertices returned by TTF_GetGPUTextDrawData + * + * \since This enum is available since SDL_ttf 3.0.0. + */ +typedef enum TTF_GPUTextEngineWinding +{ + TTF_GPU_TEXTENGINE_WINDING_INVALID = -1, + TTF_GPU_TEXTENGINE_WINDING_CLOCKWISE, + TTF_GPU_TEXTENGINE_WINDING_COUNTER_CLOCKWISE +} TTF_GPUTextEngineWinding; + +/** + * Sets the winding order of the vertices returned by TTF_GetGPUTextDrawData + * for a particular GPU text engine. + * + * \param engine a TTF_TextEngine object created with + * TTF_CreateGPUTextEngine(). + * \param winding the new winding order option. + * + * \threadsafety This function should be called on the thread that created the + * engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetGPUTextEngineWinding + */ +extern SDL_DECLSPEC void SDLCALL TTF_SetGPUTextEngineWinding(TTF_TextEngine *engine, TTF_GPUTextEngineWinding winding); + +/** + * Get the winding order of the vertices returned by TTF_GetGPUTextDrawData + * for a particular GPU text engine + * + * \param engine a TTF_TextEngine object created with + * TTF_CreateGPUTextEngine(). + * \returns the winding order used by the GPU text engine or + * TTF_GPU_TEXTENGINE_WINDING_INVALID in case of error. + * + * \threadsafety This function should be called on the thread that created the + * engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetGPUTextEngineWinding + */ +extern SDL_DECLSPEC TTF_GPUTextEngineWinding SDLCALL TTF_GetGPUTextEngineWinding(const TTF_TextEngine *engine); + +/** + * Create a text object from UTF-8 text and a text engine. + * + * \param engine the text engine to use when creating the text object, may be + * NULL. + * \param font the font to render with. + * \param text the text to use, in UTF-8 encoding. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \returns a TTF_Text object or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * font and text engine. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_DestroyText + */ +extern SDL_DECLSPEC TTF_Text * SDLCALL TTF_CreateText(TTF_TextEngine *engine, TTF_Font *font, const char *text, size_t length); + +/** + * Get the properties associated with a text object. + * + * \param text the TTF_Text to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL TTF_GetTextProperties(TTF_Text *text); + +/** + * Set the text engine used by a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param engine the text engine to use for drawing. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextEngine + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextEngine(TTF_Text *text, TTF_TextEngine *engine); + +/** + * Get the text engine used by a text object. + * + * \param text the TTF_Text to query. + * \returns the TTF_TextEngine used by the text on success or NULL on failure; + * call SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextEngine + */ +extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_GetTextEngine(TTF_Text *text); + +/** + * Set the font used by a text object. + * + * When a text object has a font, any changes to the font will automatically + * regenerate the text. If you set the font to NULL, the text will continue to + * render but changes to the font will no longer affect the text. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param font the font to use, may be NULL. + * \returns false if the text pointer is null; otherwise, true. call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextFont + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextFont(TTF_Text *text, TTF_Font *font); + +/** + * Get the font used by a text object. + * + * \param text the TTF_Text to query. + * \returns the TTF_Font used by the text on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextFont + */ +extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_GetTextFont(TTF_Text *text); + +/** + * Set the direction to be used for text shaping a text object. + * + * This function only supports left-to-right text shaping if SDL_ttf was not + * built with HarfBuzz support. + * + * \param text the text to modify. + * \param direction the new direction for text to flow. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextDirection(TTF_Text *text, TTF_Direction direction); + +/** + * Get the direction to be used for text shaping a text object. + * + * This defaults to the direction of the font used by the text object. + * + * \param text the text to query. + * \returns the direction to be used for text shaping. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC TTF_Direction SDLCALL TTF_GetTextDirection(TTF_Text *text); + +/** + * Set the script to be used for text shaping a text object. + * + * This returns false if SDL_ttf isn't built with HarfBuzz support. + * + * \param text the text to modify. + * \param script an + * [ISO 15924 code](https://unicode.org/iso15924/iso15924-codes.html) + * . + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_StringToTag + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextScript(TTF_Text *text, Uint32 script); + +/** + * Get the script used for text shaping a text object. + * + * This defaults to the script of the font used by the text object. + * + * \param text the text to query. + * \returns an + * [ISO 15924 code](https://unicode.org/iso15924/iso15924-codes.html) + * or 0 if a script hasn't been set on either the text object or the + * font. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TagToString + */ +extern SDL_DECLSPEC Uint32 SDLCALL TTF_GetTextScript(TTF_Text *text); + +/** + * Set the color of a text object. + * + * The default text color is white (255, 255, 255, 255). + * + * \param text the TTF_Text to modify. + * \param r the red color value in the range of 0-255. + * \param g the green color value in the range of 0-255. + * \param b the blue color value in the range of 0-255. + * \param a the alpha value in the range of 0-255. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColor + * \sa TTF_SetTextColorFloat + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextColor(TTF_Text *text, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/** + * Set the color of a text object. + * + * The default text color is white (1.0f, 1.0f, 1.0f, 1.0f). + * + * \param text the TTF_Text to modify. + * \param r the red color value, normally in the range of 0-1. + * \param g the green color value, normally in the range of 0-1. + * \param b the blue color value, normally in the range of 0-1. + * \param a the alpha value in the range of 0-1. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColorFloat + * \sa TTF_SetTextColor + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextColorFloat(TTF_Text *text, float r, float g, float b, float a); + +/** + * Get the color of a text object. + * + * \param text the TTF_Text to query. + * \param r a pointer filled in with the red color value in the range of + * 0-255, may be NULL. + * \param g a pointer filled in with the green color value in the range of + * 0-255, may be NULL. + * \param b a pointer filled in with the blue color value in the range of + * 0-255, may be NULL. + * \param a a pointer filled in with the alpha value in the range of 0-255, + * may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColorFloat + * \sa TTF_SetTextColor + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextColor(TTF_Text *text, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + +/** + * Get the color of a text object. + * + * \param text the TTF_Text to query. + * \param r a pointer filled in with the red color value, normally in the + * range of 0-1, may be NULL. + * \param g a pointer filled in with the green color value, normally in the + * range of 0-1, may be NULL. + * \param b a pointer filled in with the blue color value, normally in the + * range of 0-1, may be NULL. + * \param a a pointer filled in with the alpha value in the range of 0-1, may + * be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColor + * \sa TTF_SetTextColorFloat + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextColorFloat(TTF_Text *text, float *r, float *g, float *b, float *a); + +/** + * Set the position of a text object. + * + * This can be used to position multiple text objects within a single wrapping + * text area. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param x the x offset of the upper left corner of this text in pixels. + * \param y the y offset of the upper left corner of this text in pixels. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextPosition + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextPosition(TTF_Text *text, int x, int y); + +/** + * Get the position of a text object. + * + * \param text the TTF_Text to query. + * \param x a pointer filled in with the x offset of the upper left corner of + * this text in pixels, may be NULL. + * \param y a pointer filled in with the y offset of the upper left corner of + * this text in pixels, may be NULL. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextPosition + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextPosition(TTF_Text *text, int *x, int *y); + +/** + * Set whether wrapping is enabled on a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param wrap_width the maximum width in pixels, 0 to wrap on newline + * characters. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextWrapWidth + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWidth(TTF_Text *text, int wrap_width); + +/** + * Get whether wrapping is enabled on a text object. + * + * \param text the TTF_Text to query. + * \param wrap_width a pointer filled in with the maximum width in pixels or 0 + * if the text is being wrapped on newline characters. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextWrapWidth + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapWidth(TTF_Text *text, int *wrap_width); + +/** + * Set whether whitespace should be visible when wrapping a text object. + * + * If the whitespace is visible, it will take up space for purposes of + * alignment and wrapping. This is good for editing, but looks better when + * centered or aligned if whitespace around line wrapping is hidden. This + * defaults false. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param visible true to show whitespace when wrapping text, false to hide + * it. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TextWrapWhitespaceVisible + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible); + +/** + * Return whether whitespace is shown when wrapping a text object. + * + * \param text the TTF_Text to query. + * \returns true if whitespace is shown when wrapping text, or false + * otherwise. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextWrapWhitespaceVisible + */ +extern SDL_DECLSPEC bool SDLCALL TTF_TextWrapWhitespaceVisible(TTF_Text *text); + +/** + * Set the UTF-8 text used by a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param string the UTF-8 text to use, may be NULL. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_DeleteTextString + * \sa TTF_InsertTextString + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *string, size_t length); + +/** + * Insert UTF-8 text into a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param offset the offset, in bytes, from the beginning of the string if >= + * 0, the offset from the end of the string if < 0. Note that + * this does not do UTF-8 validation, so you should only insert + * at UTF-8 sequence boundaries. + * \param string the UTF-8 text to insert. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_DeleteTextString + * \sa TTF_SetTextString + */ +extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset, const char *string, size_t length); + +/** + * Append UTF-8 text to a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param string the UTF-8 text to insert. + * \param length the length of the text, in bytes, or 0 for null terminated + * text. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_DeleteTextString + * \sa TTF_InsertTextString + * \sa TTF_SetTextString + */ +extern SDL_DECLSPEC bool SDLCALL TTF_AppendTextString(TTF_Text *text, const char *string, size_t length); + +/** + * Delete UTF-8 text from a text object. + * + * This function may cause the internal text representation to be rebuilt. + * + * \param text the TTF_Text to modify. + * \param offset the offset, in bytes, from the beginning of the string if >= + * 0, the offset from the end of the string if < 0. Note that + * this does not do UTF-8 validation, so you should only delete + * at UTF-8 sequence boundaries. + * \param length the length of text to delete, in bytes, or -1 for the + * remainder of the string. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_InsertTextString + * \sa TTF_SetTextString + */ +extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset, int length); + +/** + * Get the size of a text object. + * + * The size of the text may change when the font or font style and size + * change. + * + * \param text the TTF_Text to query. + * \param w a pointer filled in with the width of the text, in pixels, may be + * NULL. + * \param h a pointer filled in with the height of the text, in pixels, may be + * NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSize(TTF_Text *text, int *w, int *h); + +/** + * Flags for TTF_SubString + * + * \since This datatype is available since SDL_ttf 3.0.0. + * + * \sa TTF_SubString + */ +typedef Uint32 TTF_SubStringFlags; + +#define TTF_SUBSTRING_DIRECTION_MASK 0x000000FF /**< The mask for the flow direction for this substring */ +#define TTF_SUBSTRING_TEXT_START 0x00000100 /**< This substring contains the beginning of the text */ +#define TTF_SUBSTRING_LINE_START 0x00000200 /**< This substring contains the beginning of line `line_index` */ +#define TTF_SUBSTRING_LINE_END 0x00000400 /**< This substring contains the end of line `line_index` */ +#define TTF_SUBSTRING_TEXT_END 0x00000800 /**< This substring contains the end of the text */ + +/** + * The representation of a substring within text. + * + * \since This struct is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetNextTextSubString + * \sa TTF_GetPreviousTextSubString + * \sa TTF_GetTextSubString + * \sa TTF_GetTextSubStringForLine + * \sa TTF_GetTextSubStringForPoint + * \sa TTF_GetTextSubStringsForRange + */ +typedef struct TTF_SubString +{ + TTF_SubStringFlags flags; /**< The flags for this substring */ + int offset; /**< The byte offset from the beginning of the text */ + int length; /**< The byte length starting at the offset */ + int line_index; /**< The index of the line that contains this substring */ + int cluster_index; /**< The internal cluster index, used for quickly iterating */ + SDL_Rect rect; /**< The rectangle, relative to the top left of the text, containing the substring */ +} TTF_SubString; + +/** + * Get the substring of a text object that surrounds a text offset. + * + * If `offset` is less than 0, this will return a zero length substring at the + * beginning of the text with the TTF_SUBSTRING_TEXT_START flag set. If + * `offset` is greater than or equal to the length of the text string, this + * will return a zero length substring at the end of the text with the + * TTF_SUBSTRING_TEXT_END flag set. + * + * \param text the TTF_Text to query. + * \param offset a byte offset into the text string. + * \param substring a pointer filled in with the substring containing the + * offset. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSubString(TTF_Text *text, int offset, TTF_SubString *substring); + +/** + * Get the substring of a text object that contains the given line. + * + * If `line` is less than 0, this will return a zero length substring at the + * beginning of the text with the TTF_SUBSTRING_TEXT_START flag set. If `line` + * is greater than or equal to `text->num_lines` this will return a zero + * length substring at the end of the text with the TTF_SUBSTRING_TEXT_END + * flag set. + * + * \param text the TTF_Text to query. + * \param line a zero-based line index, in the range [0 .. text->num_lines-1]. + * \param substring a pointer filled in with the substring containing the + * offset. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSubStringForLine(TTF_Text *text, int line, TTF_SubString *substring); + +/** + * Get the substrings of a text object that contain a range of text. + * + * \param text the TTF_Text to query. + * \param offset a byte offset into the text string. + * \param length the length of the range being queried, in bytes, or -1 for + * the remainder of the string. + * \param count a pointer filled in with the number of substrings returned, + * may be NULL. + * \returns a NULL terminated array of substring pointers or NULL on failure; + * call SDL_GetError() for more information. This is a single + * allocation that should be freed with SDL_free() when it is no + * longer needed. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC TTF_SubString ** SDLCALL TTF_GetTextSubStringsForRange(TTF_Text *text, int offset, int length, int *count); + +/** + * Get the portion of a text string that is closest to a point. + * + * This will return the closest substring of text to the given point. + * + * \param text the TTF_Text to query. + * \param x the x coordinate relative to the left side of the text, may be + * outside the bounds of the text area. + * \param y the y coordinate relative to the top side of the text, may be + * outside the bounds of the text area. + * \param substring a pointer filled in with the closest substring of text to + * the given point. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSubStringForPoint(TTF_Text *text, int x, int y, TTF_SubString *substring); + +/** + * Get the previous substring in a text object + * + * If called at the start of the text, this will return a zero length + * substring with the TTF_SUBSTRING_TEXT_START flag set. + * + * \param text the TTF_Text to query. + * \param substring the TTF_SubString to query. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetPreviousTextSubString(TTF_Text *text, const TTF_SubString *substring, TTF_SubString *previous); + +/** + * Get the next substring in a text object + * + * If called at the end of the text, this will return a zero length substring + * with the TTF_SUBSTRING_TEXT_END flag set. + * + * \param text the TTF_Text to query. + * \param substring the TTF_SubString to query. + * \param next a pointer filled in with the next substring. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetNextTextSubString(TTF_Text *text, const TTF_SubString *substring, TTF_SubString *next); + +/** + * Update the layout of a text object. + * + * This is automatically done when the layout is requested or the text is + * rendered, but you can call this if you need more control over the timing of + * when the layout and text engine representation are updated. + * + * \param text the TTF_Text to update. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_UpdateText(TTF_Text *text); + +/** + * Destroy a text object created by a text engine. + * + * \param text the text to destroy. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_CreateText + */ +extern SDL_DECLSPEC void SDLCALL TTF_DestroyText(TTF_Text *text); + +/** + * Dispose of a previously-created font. + * + * Call this when done with a font. This function will free any resources + * associated with it. It is safe to call this function on NULL, for example + * on the result of a failed call to TTF_OpenFont(). + * + * The font is not valid after being passed to this function. String pointers + * from functions that return information on this font, such as + * TTF_GetFontFamilyName() and TTF_GetFontStyleName(), are no longer valid + * after this call, as well. + * + * \param font the font to dispose of. + * + * \threadsafety This function should not be called while any other thread is + * using the font. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_OpenFont + * \sa TTF_OpenFontIO + */ +extern SDL_DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font); + +/** + * Deinitialize SDL_ttf. + * + * You must call this when done with the library, to free internal resources. + * It is safe to call this when the library isn't initialized, as it will just + * return immediately. + * + * Once you have as many quit calls as you have had successful calls to + * TTF_Init, the library will actually deinitialize. + * + * Please note that this does not automatically close any fonts that are still + * open at the time of deinitialization, and it is possibly not safe to close + * them afterwards, as parts of the library will no longer be initialized to + * deal with it. A well-written program should call TTF_CloseFont() on any + * open fonts before calling this function! + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC void SDLCALL TTF_Quit(void); + +/** + * Check if SDL_ttf is initialized. + * + * This reports the number of times the library has been initialized by a call + * to TTF_Init(), without a paired deinitialization request from TTF_Quit(). + * + * In short: if it's greater than zero, the library is currently initialized + * and ready to work. If zero, it is not initialized. + * + * Despite the return value being a signed integer, this function should not + * return a negative number. + * + * \returns the current number of initialization calls, that need to + * eventually be paired with this many calls to TTF_Quit(). + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_Init + * \sa TTF_Quit + */ +extern SDL_DECLSPEC int SDLCALL TTF_WasInit(void); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_TTF_H_ */ + diff --git a/vendor/sdl3/ttf/sdl3_textengine.odin b/vendor/sdl3/ttf/sdl3_textengine.odin new file mode 100644 index 000000000..00bf881dd --- /dev/null +++ b/vendor/sdl3/ttf/sdl3_textengine.odin @@ -0,0 +1,62 @@ +package sdl3_ttf + +import "core:c" +import SDL "vendor:sdl3" + +DrawCommand :: enum c.int { + NOOP, + FILL, + COPY, +} + +FillOperation :: struct { + cmd: DrawCommand, + rect: SDL.Rect, +} + +CopyOperation :: struct { + cmd: DrawCommand, + text_offset: c.int, + glyph_font: ^Font, + glyph_index: u32, + src: SDL.Rect, + dst: SDL.Rect, + reserved: rawptr, +} + +DrawOperation :: struct #raw_union { + cmd: DrawCommand, + fill: FillOperation, + copy: CopyOperation, +} + +TextLayout :: struct {} + +TextData :: struct { + font: ^Font, + color: SDL.FColor, + needs_layout_update: bool, + layout: ^TextLayout, + x, y: c.int, + w, h: c.int, + num_ops: c.int, + ops: [^]DrawOperation `fmt:"v,num_ops"`, + num_clusters: c.int, + clusters: [^]SubString `fmt:"v,num_clusters"`, + props: SDL.PropertiesID, + needs_engine_update: bool, + engine: ^TextEngine, + engine_text: rawptr, +} + +TextEngine :: struct { + version: u32, + userdata: rawptr, + CreateText: proc "c" (userdata: rawptr, text: ^Text) -> bool, + DestroyText: proc "c" (userdata: rawptr, Textext: ^Text), +} + +#assert( + (size_of(TextEngine) == 16 && size_of(rawptr) == 4) || + (size_of(TextEngine) == 32 && size_of(rawptr) == 8), +) diff --git a/vendor/sdl3/ttf/sdl3_ttf.odin b/vendor/sdl3/ttf/sdl3_ttf.odin new file mode 100644 index 000000000..10d313fbb --- /dev/null +++ b/vendor/sdl3/ttf/sdl3_ttf.odin @@ -0,0 +1,293 @@ +// Bindings for [[ SDL3 TTF ; https://wiki.libsdl.org/SDL3_ttf/FrontPage ]]. +package sdl3_ttf + +import "core:c" +import SDL "vendor:sdl3" + +when ODIN_OS == .Windows { + foreign import lib "SDL3_ttf.lib" +} else { + foreign import lib "system:SDL3_ttf" +} + + +PROP_FONT_CREATE_FILENAME_STRING :: "SDL_ttf.font.create.filename" +PROP_FONT_CREATE_IOSTREAM_POINTER :: "SDL_ttf.font.create.iostream" +PROP_FONT_CREATE_IOSTREAM_OFFSET_NUMBER :: "SDL_ttf.font.create.iostream.offset" +PROP_FONT_CREATE_IOSTREAM_AUTOCLOSE_BOOLEAN :: "SDL_ttf.font.create.iostream.autoclose" +PROP_FONT_CREATE_SIZE_FLOAT :: "SDL_ttf.font.create.size" +PROP_FONT_CREATE_FACE_NUMBER :: "SDL_ttf.font.create.face" +PROP_FONT_CREATE_HORIZONTAL_DPI_NUMBER :: "SDL_ttf.font.create.hdpi" +PROP_FONT_CREATE_VERTICAL_DPI_NUMBER :: "SDL_ttf.font.create.vdpi" +PROP_FONT_CREATE_EXISTING_FONT :: "SDL_ttf.font.create.existing_font" + +FONT_WEIGHT_THIN :: 100 /**< Thin (100) named font weight value */ +FONT_WEIGHT_EXTRA_LIGHT :: 200 /**< ExtraLight (200) named font weight value */ +FONT_WEIGHT_LIGHT :: 300 /**< Light (300) named font weight value */ +FONT_WEIGHT_NORMAL :: 400 /**< Normal (400) named font weight value */ +FONT_WEIGHT_MEDIUM :: 500 /**< Medium (500) named font weight value */ +FONT_WEIGHT_SEMI_BOLD :: 600 /**< SemiBold (600) named font weight value */ +FONT_WEIGHT_BOLD :: 700 /**< Bold (700) named font weight value */ +FONT_WEIGHT_EXTRA_BOLD :: 800 /**< ExtraBold (800) named font weight value */ +FONT_WEIGHT_BLACK :: 900 /**< Black (900) named font weight value */ +FONT_WEIGHT_EXTRA_BLACK :: 950 /**< ExtraBlack (950) named font weight value */ + +PROP_RENDERER_TEXT_ENGINE_RENDERER :: "SDL_ttf.renderer_text_engine.create.renderer" +PROP_RENDERER_TEXT_ENGINE_ATLAS_TEXTURE_SIZE :: "SDL_ttf.renderer_text_engine.create.atlas_texture_size" + +PROP_GPU_TEXT_ENGINE_DEVICE :: "SDL_ttf.gpu_text_engine.create.device" +PROP_GPU_TEXT_ENGINE_ATLAS_TEXTURE_SIZE :: "SDL_ttf.gpu_text_engine.create.atlas_texture_size" + +MAJOR_VERSION :: 3 +MINOR_VERSION :: 2 +PATCHLEVEL :: 2 + +Font :: struct {} + +Text :: struct { + text: [^]u8, + num_lines: c.int, + refcount: c.int, + internal: ^TextData, +} + +FontStyle :: enum u32 { + BOLD, + ITALIC, + UNDERLINE, + STRIKETHROUGH, +} + +FontStyleFlags :: distinct bit_set[FontStyle; u32] + +// NOTE: This is called TTF_HintingFlags but its not a bit_set so +// the "flags" doesn't really make sense, its just the hinting. +Hinting :: enum c.int { + INVALID = -1, + NORMAL, + LIGHT, + MONO, + NONE, + LIGHT_SUBPIXEL, +} + +HorizontalAlignment :: enum c.int { + INVALID = -1, + LEFT, + CENTER, + RIGHT, +} + +Direction :: enum c.int { + INVALID, + LTR = 4, + RTL, + TTB, + BTT, +} + +ImageType :: enum c.int { + INVALID, + ALPHA, + COLOR, + SDF, +} + +GPUAtlasDrawSequence :: struct { + atlas_texture: ^SDL.GPUTexture, + xy, uv: [^]SDL.FPoint `fmt:"v,num_vertices"`, + num_vertices: c.int, + indices: [^]c.int `fmt:"v,num_indices"`, + num_indices: c.int, + image_type: ImageType, + next: ^GPUAtlasDrawSequence, +} + +GPUTextEngineWinding :: enum c.int { + INVALID = -1, + CLOCKWISE = 0, + COUNTER_CLOCKWISE = +1, +} + +SubStringFlags :: bit_field u32 { + direction: u8 | 8, + text_start: bool | 1, + line_start: bool | 1, + line_end: bool | 1, + text_end: bool | 1, +} + +SubString :: struct { + flags: SubStringFlags, + offset, length: c.int, + line_index, cluster_index: c.int, + rect: SDL.Rect, +} + +@(default_calling_convention="c", link_prefix="TTF_", require_results) +foreign lib { + Version :: proc() -> c.int --- + WasInit :: proc() -> c.int --- + + OpenFont :: proc(file: cstring, ptsize: f32) -> ^Font --- + OpenFontIO :: proc(src: ^SDL.IOStream, closeio: bool, ptsize: f32) -> ^Font --- + OpenFontWithProperties :: proc(props: SDL.PropertiesID) -> ^Font --- + + CopyFont :: proc(existing_font: ^Font) -> ^Font --- + + GetFontProperties :: proc(font: ^Font) -> SDL.PropertiesID --- + GetFontGeneration :: proc(font: ^Font) -> u32 --- + + GetFontSize :: proc(font: ^Font) -> f32 --- + + SetFontStyle :: proc(font: ^Font, style: FontStyleFlags) --- + GetFontStyle :: proc(font: ^Font) -> FontStyleFlags --- + + SetFontOutline :: proc(font: ^Font, outline: c.int) -> bool --- + GetFontOutline :: proc(font: ^Font) -> c.int --- + + SetFontHinting :: proc(font: ^Font, hinting: Hinting) --- + GetFontHinting :: proc(font: ^Font) -> Hinting --- + + GetNumFontFaces :: proc(font: ^Font) -> c.int --- + + SetFontSDF :: proc(font: ^Font, enabled: bool) -> bool --- + GetFontSDF :: proc(font: ^Font) -> bool --- + + GetFontWeight :: proc(font: ^Font) -> c.int --- + + SetFontWrapAlignment :: proc(font: ^Font, align: HorizontalAlignment) --- + GetFontWrapAlignment :: proc(font: ^Font) -> HorizontalAlignment --- + + GetFontHeight :: proc(font: ^Font) -> c.int --- + GetFontAscent :: proc(font: ^Font) -> c.int --- + GetFontDescent :: proc(font: ^Font) -> c.int --- + + SetFontLineSkip :: proc(font: ^Font, lineskip: c.int) --- + GetFontLineSkip :: proc(font: ^Font) -> c.int --- + + SetFontKerning :: proc(font: ^Font, enabled: bool) --- + GetFontKerning :: proc(font: ^Font) -> bool --- + + FontIsFixedWidth :: proc(font: ^Font) -> bool --- + FontIsScalable :: proc(font: ^Font) -> bool --- + + GetFontFamilyName :: proc(font: ^Font) -> cstring --- + GetFontStyleName :: proc(font: ^Font) -> cstring --- + + GetFontDirection :: proc(font: ^Font) -> Direction --- + + StringToTag :: proc(string: cstring) -> u32 --- + + GetFontScript :: proc(font: ^Font) -> u32 --- + + GetGlyphScript :: proc(ch: u32) -> u32 --- + FontHasGlyph :: proc(font: ^Font, ch: u32) -> bool --- + GetGlyphImage :: proc(font: ^Font, ch: u32, image_type: ^ImageType) -> ^SDL.Surface --- + GetGlyphImageForIndex :: proc(font: ^Font, glyph_index: u32, image_type: ^ImageType) -> ^SDL.Surface --- + + RenderText_Solid :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color) -> ^SDL.Surface --- + RenderText_Solid_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color, wrap_Length: c.int) -> ^SDL.Surface --- + RenderGlyph_Solid :: proc(font: ^Font, ch: u32, fg: SDL.Color) -> ^SDL.Surface --- + RenderText_Shaded :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color) -> ^SDL.Surface --- + RenderText_Shaded_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color, wrap_width: c.int) -> ^SDL.Surface --- + RenderGlyph_Shaded :: proc(font: ^Font, ch: u32, fg, bg: SDL.Color) -> ^SDL.Surface --- + RenderText_Blended :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color) -> ^SDL.Surface --- + RenderText_Blended_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color, wrap_width: c.int) -> ^SDL.Surface --- + RenderGlyph_Blended :: proc(font: ^Font, ch: u32, fg: SDL.Color) -> ^SDL.Surface --- + RenderText_LCD :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color) -> ^SDL.Surface --- + RenderText_LCD_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color, wrap_width: c.int) -> ^SDL.Surface --- + RenderGlyph_LCD :: proc(font: ^Font, ch: u32, fg, bg: SDL.Color) -> ^SDL.Surface --- + + CreateSurfaceTextEngine :: proc() -> ^TextEngine --- + + CreateRendererTextEngine :: proc(renderer: ^SDL.Renderer) -> ^TextEngine --- + CreateRendererTextEngineWithProperties :: proc(props: SDL.PropertiesID) -> ^TextEngine --- + + CreateGPUTextEngine :: proc(device: ^SDL.GPUDevice) -> ^TextEngine --- + CreateGPUTextEngineWithProperties :: proc(props: SDL.PropertiesID) -> ^TextEngine --- + GetGPUTextDrawData :: proc(text: ^Text) -> ^GPUAtlasDrawSequence --- + SetGPUTextEngineWinding :: proc(engine: ^TextEngine, winding: GPUTextEngineWinding) --- + GetGPUTextEngineWinding :: proc(#by_ptr engine: TextEngine) -> GPUTextEngineWinding --- + + CreateText :: proc(engine: ^TextEngine, font: ^Font, text: cstring, length: c.size_t) -> ^Text --- + GetTextProperties :: proc(text: ^Text) -> SDL.PropertiesID --- + GetTextEngine :: proc(text: ^Text) -> ^TextEngine --- + GetTextFont :: proc(text: ^Text) -> ^Font --- + GetTextDirection :: proc(text: ^Text) -> Direction --- + GetTextScript :: proc(text: ^Text) -> u32 --- + TextWrapWhitespaceVisible :: proc(text: ^Text) -> bool --- + + GetTextSubStringsForRange :: proc(text: ^Text, offset, length: c.int, count: ^c.int) -> [^]^SubString --- +} + +@(default_calling_convention="c", link_prefix="TTF_") +foreign lib { + GetFreeTypeVersion :: proc(major, minor, patch: ^c.int) --- + GetHarfBuzzVersion :: proc(major, minor, patch: ^c.int) --- + + Init :: proc() -> bool --- + + AddFallbackFont :: proc(font: ^Font, fallback: ^Font) -> bool --- + RemoveFallbackFont :: proc(font: ^Font, fallback: ^Font) --- + ClearFallbackFonts :: proc(font: ^Font) --- + + SetFontSize :: proc(font: ^Font, ptsize: f32) -> bool --- + SetFontSizeDPI :: proc(font: ^Font, ptsize: f32, hdpi: c.int, vdpi: c.int) -> bool --- + GetFontDPI :: proc(font: ^Font, hdpi: ^c.int, vdpi: ^c.int) -> bool --- + + SetFontDirection :: proc(font: ^Font, direction: Direction) -> bool --- + + TagToString :: proc(tag: u32, string: [^]c.char, size: c.size_t) --- + + SetFontScript :: proc(font: ^Font, script: u32) -> bool --- + + SetFontLanguage :: proc(font: ^Font, language_bcp47: cstring) -> bool --- + + GetGlyphMetrics :: proc(font: ^Font, ch: u32, minx, maxx, miny, maxy, advance: ^c.int) -> bool --- + GetGlyphKerning :: proc(font: ^Font, previous_ch: u32, ch: u32, kerning: ^c.int) -> bool --- + + GetStringSize :: proc(font: ^Font, text: cstring, length: c.size_t, w, h: ^c.int) -> bool --- + GetStringSizeWrapped :: proc(font: ^Font, text: cstring, length: c.size_t, wrap_width: c.int, w, h: ^c.int) -> bool --- + MeasureString :: proc(font: ^Font, text: cstring, length: c.size_t, max_width: c.int, measured_width: ^c.int, measured_length: ^c.size_t) -> bool --- + + DrawSurfaceText :: proc(text: ^Text, x, y: c.int, surface: ^SDL.Surface) -> bool --- + DestroySurfaceTextEngine :: proc(engine: ^TextEngine) --- + + DrawRendererText :: proc(text: ^Text, x, y: f32) -> bool --- + DestroyRendererTextEngine :: proc(engine: ^TextEngine) --- + + DestroyGPUTextEngine :: proc(engine: ^TextEngine) --- + + SetTextEngine :: proc(text: ^Text, engine: ^TextEngine) -> bool --- + SetTextFont :: proc(text: ^Text, font: ^Font) -> bool --- + SetTextDirection :: proc(text: ^Text, direction: Direction) -> bool --- + SetTextScript :: proc(text: ^Text, script: u32) -> bool --- + SetTextColor :: proc(text: ^Text, r, g, b, a: u8) -> bool --- + SetTextColorFloat :: proc(text: ^Text, r, g, b, a: f32) -> bool --- + GetTextColor :: proc(text: ^Text, r, g, b, a: ^u8) -> bool --- + GetTextColorFloat :: proc(text: ^Text, r, g, b, a: ^f32) -> bool --- + SetTextPosition :: proc(text: ^Text, x, y: c.int) -> bool --- + GetTextPosition :: proc(text: ^Text, x, y: ^c.int) -> bool --- + SetTextWrapWidth :: proc(text: ^Text, wrap_width: c.int) -> bool --- + GetTextWrapWidth :: proc(text: ^Text, wrap_width: ^c.int) -> bool --- + SetTextWrapWhitespaceVisible :: proc(text: ^Text, visible: bool) -> bool --- + + SetTextString :: proc(text: ^Text, string: cstring, length: c.size_t) -> bool --- + InsertTextString :: proc(text: ^Text, offset: c.int, string: cstring, length: c.size_t) -> bool --- + AppendTextString :: proc(text: ^Text, string: cstring, length: c.size_t) -> bool --- + DeleteTextString :: proc(text: ^Text, offset, length: c.int) -> bool --- + + GetTextSize :: proc(text: ^Text, w, h: ^c.int) -> bool --- + + GetTextSubString :: proc(text: ^Text, offset: c.int, substring: ^SubString) -> bool --- + GetTextSubStringForLine :: proc(text: ^Text, line: c.int, substring: ^SubString) -> bool --- + GetTextSubStringForPoint :: proc(text: ^Text, x, y: c.int, substring: ^SubString) -> bool --- + GetPreviousTextSubString :: proc(text: ^Text, #by_ptr substring: SubString, previous: ^SubString) -> bool --- + GetNextTextSubString :: proc(text: ^Text, #by_ptr substring: SubString, next: ^SubString) -> bool --- + + UpdateText :: proc(text: ^Text) -> bool --- + DestroyText :: proc(text: ^Text) --- + CloseFont :: proc(font: ^Font) --- + Quit :: proc() --- +} diff --git a/vendor/stb/easy_font/stb_easy_font.odin b/vendor/stb/easy_font/stb_easy_font.odin index 0208ca316..17e8127e9 100644 --- a/vendor/stb/easy_font/stb_easy_font.odin +++ b/vendor/stb/easy_font/stb_easy_font.odin @@ -1,26 +1,7 @@ -package stb_easy_font - /* - Source port of stb_easy_font.h - - Original port: gingerBill - Bugfixes: Florian Behr & Jeroen van Rijn - Additions: Jeroen van Rijn - - Changelog: - 2022-04-03 - Bug fixes - Add `print(x, y, text, color, quad_buffer)` version that takes `[]quad`. - (Same internal memory layout as []u8 API, but more convenient for the caller.) - Add optional `scale := f32(1.0)` param to `print` to embiggen the glyph quads. - - 2021-09-14 - Original Odin version -*/ - -/* - // Example for use with vendor:raylib +An Odin-native source port of [[ stb_easy_font.h ; https://github.com/nothings/stb/blob/master/stb_easy_font.h ]]. +Example: quads: [999]easy_font.Quad = --- color := rl.GREEN @@ -38,7 +19,24 @@ package stb_easy_font // And in practice this code will likely not live as close to the `easy_font` call. rl.DrawRectangleRec(r, color) } + + +Changelog: + 2022-04-03 + Bug fixes + Add `print(x, y, text, color, quad_buffer)` version that takes `[]quad`. + (Same internal memory layout as []u8 API, but more convenient for the caller.) + Add optional `scale := f32(1.0)` param to `print` to embiggen the glyph quads. + + 2021-09-14 + Original Odin version + +Credits: + Original port: gingerBill + Bugfixes: Florian Behr & Jeroen van Rijn + Additions: Jeroen van Rijn */ +package stb_easy_font import "core:math" import "core:mem" diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin index 1ba63dc47..ac0892d0a 100644 --- a/vendor/stb/image/stb_image.odin +++ b/vendor/stb/image/stb_image.odin @@ -1,3 +1,4 @@ +// Bindings for [[ stb_image.h ; https://github.com/nothings/stb/blob/master/stb_image.h ]]. package stb_image import "core:c" diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin index 43909856e..ebdb3cd84 100644 --- a/vendor/stb/image/stb_image_resize.odin +++ b/vendor/stb/image/stb_image_resize.odin @@ -79,13 +79,13 @@ edge :: enum c.int { foreign lib { resize_uint8_srgb :: proc(input_pixels: [^]u8, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: [^]u8, output_w, output_h, output_stride_in_bytes: c.int, - num_channels: c.int, alpha_channel: b32, flags: c.int) -> c.int --- + num_channels: c.int, alpha_channel: c.int, flags: c.int) -> c.int --- // This function adds the ability to specify how requests to sample off the edge of the image are handled. resize_uint8_srgb_edgemode :: proc(input_pixels: [^]u8, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: [^]u8, output_w, output_h, output_stride_in_bytes: c.int, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_wrap_mode: edge) -> c.int --- } @@ -126,25 +126,25 @@ colorspace :: enum c.int { @(default_calling_convention="c", link_prefix="stbir_") foreign lib { // The following functions are all identical except for the type of the image data - + resize_uint8_generic :: proc(input_pixels: [^]u8, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: [^]u8, output_w, output_h, output_stride_in_bytes: c.int, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_wrap_mode: edge, filter: filter, space: colorspace, alloc_context: rawptr) -> c.int --- resize_uint16_generic :: proc(input_pixels: [^]u16, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: [^]u16, output_w, output_h, output_stride_in_bytes: c.int, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_wrap_mode: edge, filter: filter, space: colorspace, alloc_context: rawptr) -> c.int --- resize_float_generic :: proc(input_pixels: [^]f32, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: [^]f32, output_w, output_h, output_stride_in_bytes: c.int, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_wrap_mode: edge, filter: filter, space: colorspace, - alloc_context: rawptr) -> c.int --- - + alloc_context: rawptr) -> c.int --- + } ////////////////////////////////////////////////////////////////////////////// @@ -173,11 +173,11 @@ datatype :: enum c.int { @(default_calling_convention="c", link_prefix="stbir_") foreign lib { // (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. - + resize :: proc(input_pixels: rawptr, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: rawptr, output_w, output_h, output_stride_in_bytes: c.int, datatype: datatype, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_mode_horizontal, edge_mode_vertical: edge, filter_horizontal, filter_vertical: filter, space: colorspace, alloc_context: rawptr) -> c.int --- @@ -185,7 +185,7 @@ foreign lib { resize_subpixel :: proc(input_pixels: rawptr, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: rawptr, output_w, output_h, output_stride_in_bytes: c.int, datatype: datatype, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_mode_horizontal, edge_mode_vertical: edge, filter_horizontal, filter_vertical: filter, space: colorspace, alloc_context: rawptr, @@ -195,10 +195,10 @@ foreign lib { resize_region :: proc(input_pixels: rawptr, input_w, input_h, input_stride_in_bytes: c.int, output_pixels: rawptr, output_w, output_h, output_stride_in_bytes: c.int, datatype: datatype, - num_channels: c.int, alpha_channel: b32, flags: c.int, + num_channels: c.int, alpha_channel: c.int, flags: c.int, edge_mode_horizontal, edge_mode_vertical: edge, filter_horizontal, filter_vertical: filter, space: colorspace, alloc_context: rawptr, s0, t0, s1, t1: f32) -> c.int --- - + } diff --git a/vendor/stb/image/stb_image_wasm.odin b/vendor/stb/image/stb_image_wasm.odin index f43012383..cfad4725a 100644 --- a/vendor/stb/image/stb_image_wasm.odin +++ b/vendor/stb/image/stb_image_wasm.odin @@ -1,4 +1,4 @@ #+build wasm32, wasm64p32 package stb_image -@(require) import _ "vendor:libc" +@(require) import _ "vendor:libc-shim" diff --git a/vendor/stb/lib/stb_image.lib b/vendor/stb/lib/stb_image.lib index f0cffb1fc..b36fef6dc 100644 Binary files a/vendor/stb/lib/stb_image.lib and b/vendor/stb/lib/stb_image.lib differ diff --git a/vendor/stb/lib/stb_image_resize.lib b/vendor/stb/lib/stb_image_resize.lib index 30f6bd943..9d4315b1f 100644 Binary files a/vendor/stb/lib/stb_image_resize.lib and b/vendor/stb/lib/stb_image_resize.lib differ diff --git a/vendor/stb/lib/stb_image_write.lib b/vendor/stb/lib/stb_image_write.lib index 415a62996..34e724fc8 100644 Binary files a/vendor/stb/lib/stb_image_write.lib and b/vendor/stb/lib/stb_image_write.lib differ diff --git a/vendor/stb/lib/stb_rect_pack.lib b/vendor/stb/lib/stb_rect_pack.lib index a0a139ace..47344b366 100644 Binary files a/vendor/stb/lib/stb_rect_pack.lib and b/vendor/stb/lib/stb_rect_pack.lib differ diff --git a/vendor/stb/lib/stb_sprintf.lib b/vendor/stb/lib/stb_sprintf.lib index 35c2cecc9..892e56c42 100644 Binary files a/vendor/stb/lib/stb_sprintf.lib and b/vendor/stb/lib/stb_sprintf.lib differ diff --git a/vendor/stb/lib/stb_truetype.lib b/vendor/stb/lib/stb_truetype.lib index 16ecf944d..f86ddcc5e 100644 Binary files a/vendor/stb/lib/stb_truetype.lib and b/vendor/stb/lib/stb_truetype.lib differ diff --git a/vendor/stb/lib/stb_vorbis.lib b/vendor/stb/lib/stb_vorbis.lib index bf47eda26..ddf088ebe 100644 Binary files a/vendor/stb/lib/stb_vorbis.lib and b/vendor/stb/lib/stb_vorbis.lib differ diff --git a/vendor/stb/lib/stb_vorbis_wasm.o b/vendor/stb/lib/stb_vorbis_wasm.o new file mode 100644 index 000000000..156696d78 Binary files /dev/null and b/vendor/stb/lib/stb_vorbis_wasm.o differ diff --git a/vendor/stb/rect_pack/stb_rect_pack.odin b/vendor/stb/rect_pack/stb_rect_pack.odin index 696b9c8c0..0ba975b15 100644 --- a/vendor/stb/rect_pack/stb_rect_pack.odin +++ b/vendor/stb/rect_pack/stb_rect_pack.odin @@ -1,3 +1,4 @@ +// Bindings for [[ stb_rect_pack.h ; https://github.com/nothings/stb/blob/master/stb_rect_pack.h ]]. package stb_rect_pack import "core:c" diff --git a/vendor/stb/rect_pack/stb_rect_pack_wasm.odin b/vendor/stb/rect_pack/stb_rect_pack_wasm.odin index c4e2e5160..c9b6f3de8 100644 --- a/vendor/stb/rect_pack/stb_rect_pack_wasm.odin +++ b/vendor/stb/rect_pack/stb_rect_pack_wasm.odin @@ -1,4 +1,4 @@ #+build wasm32, wasm64p32 package stb_rect_pack -@(require) import _ "vendor:libc" +@(require) import _ "vendor:libc-shim" diff --git a/vendor/stb/src/Makefile b/vendor/stb/src/Makefile index 194ea5e75..521eead93 100644 --- a/vendor/stb/src/Makefile +++ b/vendor/stb/src/Makefile @@ -8,12 +8,13 @@ endif wasm: mkdir -p ../lib - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image.c -o ../lib/stb_image_wasm.o -DSTBI_NO_STDIO - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image_write.c -o ../lib/stb_image_write_wasm.o -DSTBI_WRITE_NO_STDIO - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_image_resize.c -o ../lib/stb_image_resize_wasm.o - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_truetype.c -o ../lib/stb_truetype_wasm.o - # $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_vorbis.c -o ../lib/stb_vorbis_wasm.o -DSTB_VORBIS_NO_STDIO - $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc stb_rect_pack.c -o ../lib/stb_rect_pack_wasm.o + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_image.c -o ../lib/stb_image_wasm.o -DSTBI_NO_STDIO + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_image_write.c -o ../lib/stb_image_write_wasm.o -DSTBI_WRITE_NO_STDIO + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_image_resize.c -o ../lib/stb_image_resize_wasm.o + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_truetype.c -o ../lib/stb_truetype_wasm.o + # Pretends to be emscripten so stb vorbis takes the right code path for including alloca.h + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_vorbis.c -o ../lib/stb_vorbis_wasm.o -DSTB_VORBIS_NO_STDIO -D__EMSCRIPTEN__ + $(CC) -c -Os --target=wasm32 --sysroot=$(shell odin root)/vendor/libc-shim stb_rect_pack.c -o ../lib/stb_rect_pack_wasm.o $(CC) -c -Os --target=wasm32 stb_sprintf.c -o ../lib/stb_sprintf_wasm.o unix: diff --git a/vendor/stb/src/stb_truetype.c b/vendor/stb/src/stb_truetype.c index 05c23f583..974a0bdce 100644 --- a/vendor/stb/src/stb_truetype.c +++ b/vendor/stb/src/stb_truetype.c @@ -1,2 +1,6 @@ +#define STBRP_STATIC +#define STB_RECT_PACK_IMPLEMENTATION +#include "stb_rect_pack.h" + #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" \ No newline at end of file diff --git a/vendor/stb/src/stb_vorbis.c b/vendor/stb/src/stb_vorbis.c index 7e5daa367..db09fff42 100644 --- a/vendor/stb/src/stb_vorbis.c +++ b/vendor/stb/src/stb_vorbis.c @@ -1401,7 +1401,11 @@ static int set_file_offset(stb_vorbis *f, unsigned int loc) #endif f->eof = 0; if (USE_MEMORY(f)) { - if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + // Known problem upstream: https://github.com/nothings/stb/issues/1745 + // But pull request hasn't been merged: https://github.com/nothings/stb/pull/1746 + // So we cherry pick it. + // if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + if (loc >= f->stream_len) { f->stream = f->stream_end; f->eof = 1; return 0; diff --git a/vendor/stb/truetype/stb_truetype.odin b/vendor/stb/truetype/stb_truetype.odin index f1dcdf2a2..9d8674941 100644 --- a/vendor/stb/truetype/stb_truetype.odin +++ b/vendor/stb/truetype/stb_truetype.odin @@ -1,3 +1,4 @@ +// Bindings for [[ stb_truetype.h ; https://github.com/nothings/stb/blob/master/stb_truetype.h ]]. package stb_truetype import c "core:c" @@ -110,7 +111,7 @@ pack_range :: struct { first_unicode_codepoint_in_range: c.int, array_of_unicode_codepoints: [^]rune, num_chars: c.int, - chardata_for_range: ^packedchar, + chardata_for_range: [^]packedchar, _, _: u8, // used internally to store oversample info } @@ -137,7 +138,7 @@ foreign stbtt { // bilinear filtering). // // Returns 0 on failure, 1 on success. - PackBegin :: proc(spc: ^pack_context, pixels: [^]byte, width, height, stride_in_bytes, padding: c.int, alloc_context: rawptr) -> c.int --- + PackBegin :: proc(spc: ^pack_context, pixels: [^]byte, width, height, stride_in_bytes, padding: c.int, alloc_context: rawptr) -> b32 --- // Cleans up the packing context and frees all memory. PackEnd :: proc(spc: ^pack_context) --- @@ -154,13 +155,17 @@ foreign stbtt { // and pass that result as 'font_size': // ..., 20 , ... // font max minus min y is 20 pixels tall // ..., POINT_SIZE(20), ... // 'M' is 20 pixels tall - PackFontRange :: proc(spc: ^pack_context, fontdata: [^]byte, font_index: c.int, font_size: f32, first_unicode_char_in_range, num_chars_in_range: c.int, chardata_for_range: ^packedchar) -> c.int --- + // + // Returns 0 on failure, 1 on success. + PackFontRange :: proc(spc: ^pack_context, fontdata: [^]byte, font_index: c.int, font_size: f32, first_unicode_char_in_range, num_chars_in_range: c.int, chardata_for_range: [^]packedchar) -> b32 --- // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple // times within a single PackBegin/PackEnd. - PackFontRanges :: proc(spc: ^pack_context, fontdata: [^]byte, font_index: c.int, ranges: [^]pack_range, num_ranges: c.int) -> c.int --- + // + // Returns 0 on failure, 1 on success. + PackFontRanges :: proc(spc: ^pack_context, fontdata: [^]byte, font_index: c.int, ranges: [^]pack_range, num_ranges: c.int) -> b32 --- // Oversampling a font increases the quality by allowing higher-quality subpixel // positioning, and is especially valuable at smaller text sizes. @@ -200,9 +205,13 @@ foreign stbtt { // then call RenderIntoRects repeatedly. This may result in a // better packing than calling PackFontRanges multiple times // (or it may not). - PackFontRangesGatherRects :: proc(spc: ^pack_context, info: ^fontinfo, ranges: ^pack_range, num_ranges: c.int, rects: [^]stbrp.Rect) -> c.int --- + // + // Returns the number of rects which were not skipped. + // PackSetSkipMissingCodepoints controls this behavior. + PackFontRangesGatherRects :: proc(spc: ^pack_context, info: ^fontinfo, ranges: [^]pack_range, num_ranges: c.int, rects: [^]stbrp.Rect) -> c.int --- PackFontRangesPackRects :: proc(spc: ^pack_context, rects: [^]stbrp.Rect, num_rects: c.int) --- - PackFontRangesRenderIntoRects :: proc(spc: ^pack_context, info: ^fontinfo, ranges: ^pack_range, num_ranges: c.int, rects: [^]stbrp.Rect) -> c.int --- + // Returns 0 on failure, 1 on success. + PackFontRangesRenderIntoRects :: proc(spc: ^pack_context, info: ^fontinfo, ranges: [^]pack_range, num_ranges: c.int, rects: [^]stbrp.Rect) -> b32 --- } ////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/stb/truetype/stb_truetype_wasm.odin b/vendor/stb/truetype/stb_truetype_wasm.odin index f36239086..727ba3ef0 100644 --- a/vendor/stb/truetype/stb_truetype_wasm.odin +++ b/vendor/stb/truetype/stb_truetype_wasm.odin @@ -1,4 +1,4 @@ #+build wasm32, wasm64p32 package stb_truetype -@(require) import _ "vendor:libc" +@(require) import _ "vendor:libc-shim" diff --git a/vendor/stb/vorbis/stb_vorbis.odin b/vendor/stb/vorbis/stb_vorbis.odin index 867ffb86d..7dbfafab8 100644 --- a/vendor/stb/vorbis/stb_vorbis.odin +++ b/vendor/stb/vorbis/stb_vorbis.odin @@ -1,12 +1,14 @@ +// Bindings for [[ stb_vorbis.c ; https://github.com/nothings/stb/blob/master/stb_vorbis.c ]]. package stb_vorbis -import c "core:c/libc" +import c "core:c" @(private) LIB :: ( "../lib/stb_vorbis.lib" when ODIN_OS == .Windows else "../lib/stb_vorbis.a" when ODIN_OS == .Linux else "../lib/darwin/stb_vorbis.a" when ODIN_OS == .Darwin + else "../lib/stb_vorbis_wasm.o" when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else "" ) @@ -14,12 +16,18 @@ when LIB != "" { when !#exists(LIB) { #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") } +} +when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { + foreign import lib "../lib/stb_vorbis_wasm.o" +} else when LIB != "" { foreign import lib { LIB } } else { foreign import lib "system:stb_vorbis" } +NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 + /////////// THREAD SAFETY // Individual stb_vorbis* handles are not thread-safe; you cannot decode from @@ -189,11 +197,13 @@ foreign lib { @(default_calling_convention="c", link_prefix="stb_vorbis_") foreign lib { - // decode an entire file and output the data interleaved into a malloc()ed - // buffer stored in *output. The return value is the number of samples - // decoded, or -1 if the file could not be opened or was not an ogg vorbis file. - // When you're done with it, just free() the pointer returned in *output. - decode_filename :: proc(filename: cstring, channels, sample_rate: ^c.int, output: ^[^]c.short) -> c.int --- + when !NO_STDIO { + // decode an entire file and output the data interleaved into a malloc()ed + // buffer stored in *output. The return value is the number of samples + // decoded, or -1 if the file could not be opened or was not an ogg vorbis file. + // When you're done with it, just free() the pointer returned in *output. + decode_filename :: proc(filename: cstring, channels, sample_rate: ^c.int, output: ^[^]c.short) -> c.int --- + } decode_memory :: proc(mem: [^]byte, len: c.int, channels, sample_rate: ^c.int, output: ^[^]c.short) -> c.int --- @@ -203,28 +213,30 @@ foreign lib { open_memory :: proc(data: [^]byte, len: c.int, error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis --- - // create an ogg vorbis decoder from a filename via fopen(). on failure, - // returns NULL and sets *error (possibly to VORBIS_file_open_failure). - open_filename :: proc(filename: cstring, - error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis --- + when !NO_STDIO { + // create an ogg vorbis decoder from a filename via fopen(). on failure, + // returns NULL and sets *error (possibly to VORBIS_file_open_failure). + open_filename :: proc(filename: cstring, + error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis --- - // create an ogg vorbis decoder from an open FILE *, looking for a stream at - // the _current_ seek point (ftell). on failure, returns NULL and sets *error. - // note that stb_vorbis must "own" this stream; if you seek it in between - // calls to stb_vorbis, it will become confused. Moreover, if you attempt to - // perform stb_vorbis_seek_*() operations on this file, it will assume it - // owns the _entire_ rest of the file after the start point. Use the next - // function, stb_vorbis_open_file_section(), to limit it. - open_file :: proc(f: ^c.FILE, close_handle_on_close: b32, - error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis --- + // create an ogg vorbis decoder from an open FILE *, looking for a stream at + // the _current_ seek point (ftell). on failure, returns NULL and sets *error. + // note that stb_vorbis must "own" this stream; if you seek it in between + // calls to stb_vorbis, it will become confused. Moreover, if you attempt to + // perform stb_vorbis_seek_*() operations on this file, it will assume it + // owns the _entire_ rest of the file after the start point. Use the next + // function, stb_vorbis_open_file_section(), to limit it. + open_file :: proc(f: ^c.FILE, close_handle_on_close: b32, + error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis --- - // create an ogg vorbis decoder from an open FILE *, looking for a stream at - // the _current_ seek point (ftell); the stream will be of length 'len' bytes. - // on failure, returns NULL and sets *error. note that stb_vorbis must "own" - // this stream; if you seek it in between calls to stb_vorbis, it will become - // confused. - open_file_section :: proc(f: ^c.FILE, close_handle_on_close: b32, - error: ^Error, alloc_buffer: ^vorbis_alloc, len: c.uint) -> ^vorbis --- + // create an ogg vorbis decoder from an open FILE *, looking for a stream at + // the _current_ seek point (ftell); the stream will be of length 'len' bytes. + // on failure, returns NULL and sets *error. note that stb_vorbis must "own" + // this stream; if you seek it in between calls to stb_vorbis, it will become + // confused. + open_file_section :: proc(f: ^c.FILE, close_handle_on_close: b32, + error: ^Error, alloc_buffer: ^vorbis_alloc, len: c.uint) -> ^vorbis --- + } // these functions seek in the Vorbis file to (approximately) 'sample_number'. // after calling seek_frame(), the next call to get_frame_*() will include diff --git a/vendor/stb/vorbis/stb_vorbis_wasm.odin b/vendor/stb/vorbis/stb_vorbis_wasm.odin new file mode 100644 index 000000000..324b7e025 --- /dev/null +++ b/vendor/stb/vorbis/stb_vorbis_wasm.odin @@ -0,0 +1,4 @@ +#+build wasm32, wasm64p32 +package stb_vorbis + +@(require) import _ "vendor:libc-shim" diff --git a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py index 9da3ee239..bb133439c 100644 --- a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py +++ b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py @@ -6,6 +6,13 @@ import string import os.path import math +PACKAGE_LINE = "package vulkan" + +BASE = """ +// Vulkan wrapper generated from [[ vulkan_core.h ; https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h ]]. +"""[1::] + + file_and_urls = [ ("vk_platform.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vk_platform.h', True), ("vulkan_core.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_core.h', False), @@ -29,6 +36,8 @@ file_and_urls = [ ("vulkan_video_codec_h265std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std.h', False), ("vulkan_video_codec_h265std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std_decode.h', False), ("vulkan_video_codec_h265std_encode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_h265std_encode.h', False), + ("vulkan_video_codec_vp9std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_vp9std_decode.h', False), + ("vulkan_video_codec_vp9std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_vp9std.h', False), ] for file, url, _ in file_and_urls: @@ -91,6 +100,7 @@ def convert_type(t, prev_name, curr_name): "const AccelerationStructureGeometryKHR* const*": "^[^]AccelerationStructureGeometryKHR", "const AccelerationStructureBuildRangeInfoKHR* const*": "^[^]AccelerationStructureBuildRangeInfoKHR", "const MicromapUsageEXT* const*": "^[^]MicromapUsageEXT", + "const MicromapUsageKHR* const*": "^[^]MicromapUsageKHR", "struct BaseOutStructure": "BaseOutStructure", "struct BaseInStructure": "BaseInStructure", "struct wl_display": "wl_display", @@ -155,7 +165,7 @@ def to_snake_case(name): s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() -ext_suffixes = ["KHR", "EXT", "AMD", "NV", "NVX", "GOOGLE", "KHX"] +ext_suffixes = ["KHR", "EXT", "AMD", "NV", "NVX", "GOOGLE", "KHX", "ARM", "QCOM"] ext_suffixes_title = [ext.title() for ext in ext_suffixes] @@ -301,7 +311,7 @@ def parse_constants(f): f.write("\n// Vendor Constants\n") fixes = '|'.join(ext_suffixes) - inner = r"((?:(?:" + fixes + r")\w+)|(?:\w+" + fixes + r"))" + inner = r"((?:(?:" + fixes + r")\w+)|(?:\w+(?:" + fixes + r")\b))" pattern = r"#define\s+VK_" + inner + r"\s*(.*?)\n" data = re.findall(pattern, src, re.S) @@ -311,7 +321,11 @@ def parse_constants(f): for name, value in data: value = remove_prefix(value, 'VK_') v = number_suffix_re.findall(value) - if v: + if value == "(~0U)": + value = "~u32(0)" + elif value == "(~0ULL)": + value = "~u64(0)" + elif v: value = v[0] f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value)) f.write("\n") @@ -362,10 +376,17 @@ def parse_enums(f): names_and_values = re.findall(r"VK_(\w+?) = (.*?)(?:,|})", fields, re.S) + ignore_names = set([ + "HOST_IMAGE_COPY_MEMCPY_EXT", + "PIPELINE_CREATE_DISPATCH_BASE_KHR" + ]) groups = [] flags = {} for name, value in names_and_values: + if name in ignore_names: + continue + n = fix_enum_name(name, prefix, suffix, is_flag_bit) try: v = fix_enum_value(value, prefix, suffix, is_flag_bit) @@ -885,18 +906,10 @@ load_proc_addresses :: proc{ }\n """[1::]) - - -BASE = """ -// -// Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h" -// -package vulkan -"""[1::] - - with open("../core.odin", 'w', encoding='utf-8') as f: f.write(BASE) + f.write(PACKAGE_LINE) + f.write("\n") f.write(""" // Core API API_VERSION_1_0 :: (1<<22) | (0<<12) | (0) @@ -905,10 +918,38 @@ API_VERSION_1_2 :: (1<<22) | (2<<12) | (0) API_VERSION_1_3 :: (1<<22) | (3<<12) | (0) API_VERSION_1_4 :: (1<<22) | (4<<12) | (0) -MAKE_VERSION :: proc(major, minor, patch: u32) -> u32 { +MAKE_API_VERSION :: proc "contextless" (variant, major, minor, patch: u32) -> u32 { +\treturn (variant<<29) | (major<<22) | (minor<<12) | (patch) +} + +MAKE_VERSION :: proc "contextless" (major, minor, patch: u32) -> u32 { \treturn (major<<22) | (minor<<12) | (patch) } +API_VERSION_MAJOR :: proc "contextless" (version: u32) -> u32 { +\treturn (version>>22) & 0x7F +} + +VERSION_MAJOR :: proc "contextless" (version: u32) -> u32 { +\treturn (version>>22) +} + +API_VERSION_MINOR :: proc "contextless" (version: u32) -> u32 { +\treturn (version>>12) & 0x3FF +} + +VERSION_MINOR :: API_VERSION_MINOR + +API_VERSION_PATCH :: proc "contextless" (version: u32) -> u32 { +\treturn (version & 0xFFF) +} + +VERSION_PATCH :: API_VERSION_PATCH + +API_VERSION_VARIANT :: proc "contextless" (version: u32) -> u32 { +\treturn (version>>29) +} + // Base types Flags :: distinct u32 Flags64 :: distinct u64 @@ -935,7 +976,6 @@ FALSE :: 0 QUEUE_FAMILY_IGNORED :: ~u32(0) SUBPASS_EXTERNAL :: ~u32(0) MAX_PHYSICAL_DEVICE_NAME_SIZE :: 256 -MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT :: 32 UUID_SIZE :: 16 MAX_MEMORY_TYPES :: 32 MAX_MEMORY_HEAPS :: 16 @@ -946,7 +986,6 @@ LUID_SIZE_KHX :: 8 LUID_SIZE :: 8 MAX_QUEUE_FAMILY_EXTERNAL :: ~u32(1) MAX_GLOBAL_PRIORITY_SIZE :: 16 -MAX_GLOBAL_PRIORITY_SIZE_EXT :: MAX_GLOBAL_PRIORITY_SIZE QUEUE_FAMILY_EXTERNAL :: MAX_QUEUE_FAMILY_EXTERNAL // Vulkan Video API Constants @@ -972,13 +1011,14 @@ MAKE_VIDEO_STD_VERSION :: MAKE_VERSION f.write("\n\n") parse_flags_def(f) with open("../enums.odin", 'w', encoding='utf-8') as f: - f.write(BASE) - f.write("\n") + f.write(PACKAGE_LINE) + f.write("\n\n") parse_enums(f) parse_fake_enums(f) f.write("\n\n") with open("../structs.odin", 'w', encoding='utf-8') as f: - f.write(BASE) + f.write(PACKAGE_LINE) + f.write("\n") f.write(""" import "core:c" @@ -1039,8 +1079,8 @@ MTLCommandQueue_id :: rawptr parse_structs(f) f.write("\n\n") with open("../procedures.odin", 'w', encoding='utf-8') as f: - f.write(BASE) - f.write("\n") + f.write(PACKAGE_LINE) + f.write("\n\n") parse_procedures(f) f.write("\n") group_functions(f) diff --git a/vendor/vulkan/_gen/vk_icd.h b/vendor/vulkan/_gen/vk_icd.h index 59204a341..d71f5682a 100644 --- a/vendor/vulkan/_gen/vk_icd.h +++ b/vendor/vulkan/_gen/vk_icd.h @@ -44,8 +44,9 @@ typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion); // This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this // file directly, it won't be found. -#ifndef PFN_GetPhysicalDeviceProcAddr +#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName); +#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr #endif // Typedefs for loader/ICD interface diff --git a/vendor/vulkan/_gen/vk_layer.h b/vendor/vulkan/_gen/vk_layer.h index 19d88fce4..19cf5880c 100644 --- a/vendor/vulkan/_gen/vk_layer.h +++ b/vendor/vulkan/_gen/vk_layer.h @@ -27,7 +27,10 @@ #define VK_CURRENT_CHAIN_VERSION 1 // Typedef for use in the interfaces below +#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName); +#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr +#endif // Version negotiation values typedef enum VkNegotiateLayerStructType { diff --git a/vendor/vulkan/_gen/vk_platform.h b/vendor/vulkan/_gen/vk_platform.h index 18e5ca34c..e431c7631 100644 --- a/vendor/vulkan/_gen/vk_platform.h +++ b/vendor/vulkan/_gen/vk_platform.h @@ -2,7 +2,7 @@ // File: vk_platform.h // /* -** Copyright 2014-2025 The Khronos Group Inc. +** Copyright 2014-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_beta.h b/vendor/vulkan/_gen/vulkan_beta.h index 867483d08..147a3f3cc 100644 --- a/vendor/vulkan/_gen/vulkan_beta.h +++ b/vendor/vulkan/_gen/vulkan_beta.h @@ -2,7 +2,7 @@ #define VULKAN_BETA_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -120,7 +120,7 @@ typedef struct VkPipelineShaderStageNodeCreateInfoAMDX { uint32_t index; } VkPipelineShaderStageNodeCreateInfoAMDX; -typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)(VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)(VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); typedef void (VKAPI_PTR *PFN_vkCmdInitializeGraphScratchMemoryAMDX)(VkCommandBuffer commandBuffer, VkPipeline executionGraph, VkDeviceAddress scratch, VkDeviceSize scratchSize); @@ -129,6 +129,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectAMDX)(VkCommandBuffer typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectCountAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, VkDeviceAddress countInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( VkDevice device, VkPipelineCache pipelineCache, @@ -136,42 +137,159 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( VkCommandBuffer commandBuffer, VkPipeline executionGraph, VkDeviceAddress scratch, VkDeviceSize scratchSize); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, VkDeviceAddress countInfo); #endif +#endif + + +// VK_NV_cuda_kernel_launch is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cuda_kernel_launch 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV) +#define VK_NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION 2 +#define VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME "VK_NV_cuda_kernel_launch" +typedef struct VkCudaModuleCreateInfoNV { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCudaModuleCreateInfoNV; + +typedef struct VkCudaFunctionCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaModuleNV module; + const char* pName; +} VkCudaFunctionCreateInfoNV; + +typedef struct VkCudaLaunchInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaFunctionNV function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCudaLaunchInfoNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cudaKernelLaunchFeatures; +} VkPhysicalDeviceCudaKernelLaunchFeaturesNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t computeCapabilityMinor; + uint32_t computeCapabilityMajor; +} VkPhysicalDeviceCudaKernelLaunchPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaModuleNV)(VkDevice device, const VkCudaModuleCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaModuleNV* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkGetCudaModuleCacheNV)(VkDevice device, VkCudaModuleNV module, size_t* pCacheSize, void* pCacheData); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaFunctionNV)(VkDevice device, const VkCudaFunctionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaFunctionNV* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaModuleNV)(VkDevice device, VkCudaModuleNV module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaFunctionNV)(VkDevice device, VkCudaFunctionNV function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCudaLaunchKernelNV)(VkCommandBuffer commandBuffer, const VkCudaLaunchInfoNV* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaModuleNV( + VkDevice device, + const VkCudaModuleCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaModuleNV* pModule); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetCudaModuleCacheNV( + VkDevice device, + VkCudaModuleNV module, + size_t* pCacheSize, + void* pCacheData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaFunctionNV( + VkDevice device, + const VkCudaFunctionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaFunctionNV* pFunction); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaModuleNV( + VkDevice device, + VkCudaModuleNV module, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaFunctionNV( + VkDevice device, + VkCudaFunctionNV function, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCudaLaunchKernelNV( + VkCommandBuffer commandBuffer, + const VkCudaLaunchInfoNV* pLaunchInfo); +#endif +#endif // VK_NV_displacement_micromap is a preprocessor guard. Do not pass it to API calls. @@ -219,6 +337,37 @@ typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { } VkAccelerationStructureTrianglesDisplacementMicromapNV; + +// VK_AMDX_dense_geometry_format is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_dense_geometry_format 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_SPEC_VERSION 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_EXTENSION_NAME "VK_AMDX_dense_geometry_format" +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_ALIGNMENT_AMDX 128U +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_STRIDE_AMDX 128U + +typedef enum VkCompressedTriangleFormatAMDX { + VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_AMDX = 0, + VK_COMPRESSED_TRIANGLE_FORMAT_MAX_ENUM_AMDX = 0x7FFFFFFF +} VkCompressedTriangleFormatAMDX; +typedef struct VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 denseGeometryFormat; +} VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX; + +typedef struct VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR compressedData; + VkDeviceSize dataSize; + uint32_t numTriangles; + uint32_t numVertices; + uint32_t maxPrimitiveIndex; + uint32_t maxGeometryIndex; + VkCompressedTriangleFormatAMDX format; +} VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX; + + #ifdef __cplusplus } #endif diff --git a/vendor/vulkan/_gen/vulkan_core.h b/vendor/vulkan/_gen/vulkan_core.h index 26e53459b..96931f5a1 100644 --- a/vendor/vulkan/_gen/vulkan_core.h +++ b/vendor/vulkan/_gen/vulkan_core.h @@ -2,7 +2,7 @@ #define VULKAN_CORE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -62,46 +62,40 @@ extern "C" { #define VK_MAKE_API_VERSION(variant, major, minor, patch) \ ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) -// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. + //#define VK_API_VERSION VK_MAKE_API_VERSION(0, 1, 0, 0) // Patch version should always be set to 0 -// Vulkan 1.0 version number -#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 - // Version of this file -#define VK_HEADER_VERSION 309 +#define VK_HEADER_VERSION 354 // Complete version of this file #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 4, VK_HEADER_VERSION) -// VK_MAKE_VERSION is deprecated, but no reason was given in the API XML -// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. + #define VK_MAKE_VERSION(major, minor, patch) \ ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) -// VK_VERSION_MAJOR is deprecated, but no reason was given in the API XML -// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. + #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22U) -// VK_VERSION_MINOR is deprecated, but no reason was given in the API XML -// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. + #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) -// VK_VERSION_PATCH is deprecated, but no reason was given in the API XML -// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. + #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) #define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) #define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) #define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) #define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) +// Vulkan 1.0 version number +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0 + typedef uint32_t VkBool32; typedef uint64_t VkDeviceAddress; typedef uint64_t VkDeviceSize; typedef uint32_t VkFlags; typedef uint32_t VkSampleMask; -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_HANDLE(VkInstance) VK_DEFINE_HANDLE(VkPhysicalDevice) VK_DEFINE_HANDLE(VkDevice) @@ -110,28 +104,28 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) VK_DEFINE_HANDLE(VkCommandBuffer) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) -#define VK_ATTACHMENT_UNUSED (~0U) #define VK_FALSE 0U #define VK_LOD_CLAMP_NONE 1000.0F #define VK_QUEUE_FAMILY_IGNORED (~0U) #define VK_REMAINING_ARRAY_LAYERS (~0U) #define VK_REMAINING_MIP_LEVELS (~0U) -#define VK_SUBPASS_EXTERNAL (~0U) #define VK_TRUE 1U #define VK_WHOLE_SIZE (~0ULL) #define VK_MAX_MEMORY_TYPES 32U @@ -140,6 +134,8 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) #define VK_MAX_EXTENSION_NAME_SIZE 256U #define VK_MAX_DESCRIPTION_SIZE 256U #define VK_MAX_MEMORY_HEAPS 16U +#define VK_ATTACHMENT_UNUSED (~0U) +#define VK_SUBPASS_EXTERNAL (~0U) typedef enum VkResult { VK_SUCCESS = 0, @@ -161,10 +157,11 @@ typedef enum VkResult { VK_ERROR_FORMAT_NOT_SUPPORTED = -11, VK_ERROR_FRAGMENTED_POOL = -12, VK_ERROR_UNKNOWN = -13, + VK_ERROR_VALIDATION_FAILED = -1000011001, VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, - VK_ERROR_FRAGMENTATION = -1000161000, VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + VK_ERROR_FRAGMENTATION = -1000161000, VK_PIPELINE_COMPILE_REQUIRED = 1000297000, VK_ERROR_NOT_PERMITTED = -1000174001, VK_ERROR_SURFACE_LOST_KHR = -1000000000, @@ -172,7 +169,6 @@ typedef enum VkResult { VK_SUBOPTIMAL_KHR = 1000001003, VK_ERROR_OUT_OF_DATE_KHR = -1000001004, VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, - VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_INVALID_SHADER_NV = -1000012000, VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000, VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001, @@ -181,6 +177,7 @@ typedef enum VkResult { VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004, VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005, VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, + VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT = -1000208000, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, VK_THREAD_IDLE_KHR = 1000268000, VK_THREAD_DONE_KHR = 1000268001, @@ -191,6 +188,7 @@ typedef enum VkResult { VK_INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, VK_PIPELINE_BINARY_MISSING_KHR = 1000483000, VK_ERROR_NOT_ENOUGH_SPACE_KHR = -1000483000, + VK_ERROR_VALIDATION_FAILED_EXT = VK_ERROR_VALIDATION_FAILED, VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY, VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE, VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION, @@ -200,7 +198,7 @@ typedef enum VkResult { VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS, VK_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED, - // VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT is a deprecated alias + // VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT is a legacy alias VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT = VK_INCOMPATIBLE_SHADER_BINARY_EXT, VK_RESULT_MAX_ENUM = 0x7FFFFFFF } VkResult; @@ -255,14 +253,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46, VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47, VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000, VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, - VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004, VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005, VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006, @@ -284,25 +279,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, - VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, - VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, - VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, - VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, - VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000, VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002, @@ -317,47 +298,33 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, + VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, + VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, + VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, + VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, + VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, + VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, - VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000, - VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001, - VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002, - VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003, - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004, - VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005, - VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, - VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, - VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, - VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, - VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, - VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, - VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, - VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, - VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, @@ -370,16 +337,43 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, - VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000, VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002, @@ -388,19 +382,25 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005, VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000, VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001, VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, - VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, - VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006, VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007, - VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009, - VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, @@ -408,60 +408,35 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001, VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, - VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, - VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, - VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES = 55, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES = 56, VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO = 1000174000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES = 1000388000, VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES = 1000388001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES = 1000416000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES = 1000528000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES = 1000544000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES = 1000259000, - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO = 1000259001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES = 1000259002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES = 1000525000, - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO = 1000190001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES = 1000190002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES = 1000265000, VK_STRUCTURE_TYPE_MEMORY_MAP_INFO = 1000271000, VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO = 1000271001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES = 1000470000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES = 1000470001, - VK_STRUCTURE_TYPE_RENDERING_AREA_INFO = 1000470003, VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO = 1000470004, VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2 = 1000338002, VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2 = 1000338003, - VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO = 1000470005, VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO = 1000470006, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES = 1000080000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES = 1000232000, - VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO = 1000232001, - VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO = 1000232002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES = 1000545000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES = 1000545001, VK_STRUCTURE_TYPE_BIND_MEMORY_STATUS = 1000545002, - VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO = 1000545003, - VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO = 1000545004, - VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO = 1000545005, - VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO = 1000545006, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES = 1000466000, - VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO = 1000068000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES = 1000068001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES = 1000068002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES = 1000270000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES = 1000270001, VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY = 1000270002, @@ -472,6 +447,29 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO = 1000270007, VK_STRUCTURE_TYPE_SUBRESOURCE_HOST_MEMCPY_SIZE = 1000270008, VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY = 1000270009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES = 1000416000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES = 1000528000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES = 1000544000, + VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO = 1000470005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES = 1000080000, + VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO = 1000545003, + VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO = 1000545004, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO = 1000545005, + VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO = 1000545006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES = 1000466000, + VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO = 1000068000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES = 1000068001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES = 1000068002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES = 1000259000, + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO = 1000259001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES = 1000259002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES = 1000525000, + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO = 1000190001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES = 1000190002, + VK_STRUCTURE_TYPE_RENDERING_AREA_INFO = 1000470003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES = 1000232000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO = 1000232001, + VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO = 1000232002, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, @@ -642,6 +640,13 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_FEATURES_AMD = 1000133000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_AMD = 1000133001, + VK_STRUCTURE_TYPE_GPA_SAMPLE_BEGIN_INFO_AMD = 1000133002, + VK_STRUCTURE_TYPE_GPA_SESSION_CREATE_INFO_AMD = 1000133003, + VK_STRUCTURE_TYPE_GPA_DEVICE_CLOCK_MODE_INFO_AMD = 1000133004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GPA_PROPERTIES_2_AMD = 1000133005, + VK_STRUCTURE_TYPE_GPA_DEVICE_GET_CLOCK_INFO_AMD = 1000133006, #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, #endif @@ -657,7 +662,23 @@ typedef enum VkStructureType { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, #endif + VK_STRUCTURE_TYPE_TEXEL_BUFFER_DESCRIPTOR_INFO_EXT = 1000135000, + VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT = 1000135001, + VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT = 1000135002, + VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT = 1000135003, + VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT = 1000135004, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_AND_BINDING_MAPPING_EXT = 1000135005, + VK_STRUCTURE_TYPE_SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT = 1000135006, + VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DATA_CREATE_INFO_EXT = 1000135007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_PROPERTIES_EXT = 1000135008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_FEATURES_EXT = 1000135009, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_DESCRIPTOR_HEAP_INFO_EXT = 1000135010, + VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_INDEX_CREATE_INFO_EXT = 1000135011, + VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_PUSH_DATA_TOKEN_NV = 1000135012, + VK_STRUCTURE_TYPE_SUBSAMPLED_IMAGE_FORMAT_PROPERTIES_EXT = 1000135013, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_TENSOR_PROPERTIES_ARM = 1000135014, VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_BFLOAT16_FEATURES_KHR = 1000141000, VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, @@ -724,6 +745,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_CONVERSION_FEATURES_QCOM = 1000172000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ELAPSED_TIMER_QUERY_FEATURES_QCOM = 1000173000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, @@ -748,6 +771,16 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV = 1000314009, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT = 1000208000, + VK_STRUCTURE_TYPE_SWAPCHAIN_TIMING_PROPERTIES_EXT = 1000208001, + VK_STRUCTURE_TYPE_SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT = 1000208002, + VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT = 1000208003, + VK_STRUCTURE_TYPE_PRESENT_TIMING_INFO_EXT = 1000208004, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_INFO_EXT = 1000208005, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_PROPERTIES_EXT = 1000208006, + VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_EXT = 1000208007, + VK_STRUCTURE_TYPE_PRESENT_TIMING_SURFACE_CAPABILITIES_EXT = 1000208008, + VK_STRUCTURE_TYPE_SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT = 1000208009, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, @@ -772,6 +805,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CONSTANT_DATA_FEATURES_KHR = 1000231000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ABORT_FEATURES_KHR = 1000233000, + VK_STRUCTURE_TYPE_DEVICE_FAULT_SHADER_ABORT_MESSAGE_INFO_KHR = 1000233001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ABORT_PROPERTIES_KHR = 1000233002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR = 1000235000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, @@ -810,15 +847,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT = 1000272001, VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT = 1000272002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, - VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000, - VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, - VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000, - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001, - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002, - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003, - VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004, - VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, @@ -838,11 +866,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_3D_FEATURES_EXT = 1000288000, VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000, VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001, @@ -862,11 +889,35 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + VK_STRUCTURE_TYPE_PERF_HINT_INFO_QCOM = 1000302000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_PERF_HINT_FEATURES_QCOM = 1000302001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_PERF_HINT_PROPERTIES_QCOM = 1000302002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_3_FEATURES_QCOM = 1000303000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_FEATURES_QCOM = 1000304000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_PROPERTIES_QCOM = 1000304001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_FEATURES_EXT = 1000305000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_PROPERTIES_EXT = 1000305001, +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_CUDA_MODULE_CREATE_INFO_NV = 1000307000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_CUDA_FUNCTION_CREATE_INFO_NV = 1000307001, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_CUDA_LAUNCH_INFO_NV = 1000307002, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV = 1000307003, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV = 1000307004, +#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_SHADING_FEATURES_QCOM = 1000309000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_SHADING_PROPERTIES_QCOM = 1000309001, + VK_STRUCTURE_TYPE_RENDER_PASS_TILE_SHADING_CREATE_INFO_QCOM = 1000309002, + VK_STRUCTURE_TYPE_PER_TILE_BEGIN_INFO_QCOM = 1000309003, + VK_STRUCTURE_TYPE_PER_TILE_END_INFO_QCOM = 1000309004, + VK_STRUCTURE_TYPE_DISPATCH_TILE_INFO_QCOM = 1000309005, VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, @@ -893,6 +944,22 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011, VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_COPY_KHR = 1000318000, + VK_STRUCTURE_TYPE_COPY_DEVICE_MEMORY_INFO_KHR = 1000318001, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_IMAGE_COPY_KHR = 1000318002, + VK_STRUCTURE_TYPE_COPY_DEVICE_MEMORY_IMAGE_INFO_KHR = 1000318003, + VK_STRUCTURE_TYPE_MEMORY_RANGE_BARRIERS_INFO_KHR = 1000318004, + VK_STRUCTURE_TYPE_MEMORY_RANGE_BARRIER_KHR = 1000318005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_ADDRESS_COMMANDS_FEATURES_KHR = 1000318006, + VK_STRUCTURE_TYPE_BIND_INDEX_BUFFER_3_INFO_KHR = 1000318007, + VK_STRUCTURE_TYPE_BIND_VERTEX_BUFFER_3_INFO_KHR = 1000318008, + VK_STRUCTURE_TYPE_DRAW_INDIRECT_2_INFO_KHR = 1000318009, + VK_STRUCTURE_TYPE_DRAW_INDIRECT_COUNT_2_INFO_KHR = 1000318010, + VK_STRUCTURE_TYPE_DISPATCH_INDIRECT_2_INFO_KHR = 1000318011, + VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_2_EXT = 1000318012, + VK_STRUCTURE_TYPE_BIND_TRANSFORM_FEEDBACK_BUFFER_2_INFO_EXT = 1000318013, + VK_STRUCTURE_TYPE_MEMORY_MARKER_INFO_AMD = 1000318014, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_2_KHR = 1000318015, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001, VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002, @@ -932,7 +999,6 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_EXT = 1000361000, VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, @@ -967,6 +1033,11 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNTYPED_POINTERS_FEATURES_KHR = 1000387000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_RGB_CONVERSION_FEATURES_VALVE = 1000390000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_RGB_CONVERSION_CAPABILITIES_VALVE = 1000390001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_PROFILE_RGB_CONVERSION_INFO_VALVE = 1000390002, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_RGB_CONVERSION_CREATE_INFO_VALVE = 1000390003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000, VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, @@ -1003,6 +1074,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM = 1000417000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM = 1000417001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM = 1000417002, + VK_STRUCTURE_TYPE_DISPATCH_PARAMETERS_ARM = 1000417003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_DISPATCH_PARAMETERS_PROPERTIES_ARM = 1000417004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, VK_STRUCTURE_TYPE_IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, @@ -1014,13 +1087,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_BEGIN_INFO_ARM = 1000424002, VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_INFO_ARM = 1000424003, VK_STRUCTURE_TYPE_RENDER_PASS_STRIPE_SUBMIT_INFO_ARM = 1000424004, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001, - VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, VK_STRUCTURE_TYPE_PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, @@ -1035,6 +1102,12 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_USAGE_OHOS = 1000452000, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_PROPERTIES_OHOS = 1000452001, + VK_STRUCTURE_TYPE_NATIVE_BUFFER_FORMAT_PROPERTIES_OHOS = 1000452002, + VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS = 1000452003, + VK_STRUCTURE_TYPE_MEMORY_GET_NATIVE_BUFFER_INFO_OHOS = 1000452004, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS = 1000452005, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, @@ -1044,6 +1117,30 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003, VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000, VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001, + VK_STRUCTURE_TYPE_TENSOR_CREATE_INFO_ARM = 1000460000, + VK_STRUCTURE_TYPE_TENSOR_VIEW_CREATE_INFO_ARM = 1000460001, + VK_STRUCTURE_TYPE_BIND_TENSOR_MEMORY_INFO_ARM = 1000460002, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_TENSOR_ARM = 1000460003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TENSOR_PROPERTIES_ARM = 1000460004, + VK_STRUCTURE_TYPE_TENSOR_FORMAT_PROPERTIES_ARM = 1000460005, + VK_STRUCTURE_TYPE_TENSOR_DESCRIPTION_ARM = 1000460006, + VK_STRUCTURE_TYPE_TENSOR_MEMORY_REQUIREMENTS_INFO_ARM = 1000460007, + VK_STRUCTURE_TYPE_TENSOR_MEMORY_BARRIER_ARM = 1000460008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TENSOR_FEATURES_ARM = 1000460009, + VK_STRUCTURE_TYPE_DEVICE_TENSOR_MEMORY_REQUIREMENTS_ARM = 1000460010, + VK_STRUCTURE_TYPE_COPY_TENSOR_INFO_ARM = 1000460011, + VK_STRUCTURE_TYPE_TENSOR_COPY_ARM = 1000460012, + VK_STRUCTURE_TYPE_TENSOR_DEPENDENCY_INFO_ARM = 1000460013, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_TENSOR_ARM = 1000460014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_TENSOR_INFO_ARM = 1000460015, + VK_STRUCTURE_TYPE_EXTERNAL_TENSOR_PROPERTIES_ARM = 1000460016, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_TENSOR_CREATE_INFO_ARM = 1000460017, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_FEATURES_ARM = 1000460018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_PROPERTIES_ARM = 1000460019, + VK_STRUCTURE_TYPE_DESCRIPTOR_GET_TENSOR_INFO_ARM = 1000460020, + VK_STRUCTURE_TYPE_TENSOR_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460021, + VK_STRUCTURE_TYPE_TENSOR_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460022, + VK_STRUCTURE_TYPE_FRAME_BOUNDARY_TENSORS_ARM = 1000460023, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002, @@ -1063,6 +1160,18 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD = 1000476000, VK_STRUCTURE_TYPE_ANTI_LAG_DATA_AMD = 1000476001, VK_STRUCTURE_TYPE_ANTI_LAG_PRESENTATION_INFO_AMD = 1000476002, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DENSE_GEOMETRY_FORMAT_FEATURES_AMDX = 1000478000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DENSE_GEOMETRY_FORMAT_TRIANGLES_DATA_AMDX = 1000478001, +#endif + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_ID_2_KHR = 1000479000, + VK_STRUCTURE_TYPE_PRESENT_ID_2_KHR = 1000479001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_2_FEATURES_KHR = 1000479002, + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_PRESENT_WAIT_2_KHR = 1000480000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_2_FEATURES_KHR = 1000480001, + VK_STRUCTURE_TYPE_PRESENT_WAIT_2_INFO_KHR = 1000480002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, @@ -1081,6 +1190,15 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, VK_STRUCTURE_TYPE_AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_KHR = 1000274000, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_KHR = 1000274001, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_KHR = 1000274002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR = 1000275000, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_KHR = 1000275001, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR = 1000275002, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_KHR = 1000275003, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR = 1000275004, + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_KHR = 1000275005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, @@ -1099,6 +1217,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR = 1000504000, VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV = 1000505000, VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV = 1000505001, VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV = 1000505002, @@ -1111,6 +1230,27 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CREATE_INFO_ARM = 1000507000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_CREATE_INFO_ARM = 1000507001, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_RESOURCE_INFO_ARM = 1000507002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CONSTANT_ARM = 1000507003, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_MEMORY_REQUIREMENTS_INFO_ARM = 1000507004, + VK_STRUCTURE_TYPE_BIND_DATA_GRAPH_PIPELINE_SESSION_MEMORY_INFO_ARM = 1000507005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_FEATURES_ARM = 1000507006, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SHADER_MODULE_CREATE_INFO_ARM = 1000507007, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_PROPERTY_QUERY_RESULT_ARM = 1000507008, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_INFO_ARM = 1000507009, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_COMPILER_CONTROL_CREATE_INFO_ARM = 1000507010, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENTS_INFO_ARM = 1000507011, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENT_ARM = 1000507012, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_IDENTIFIER_CREATE_INFO_ARM = 1000507013, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_DISPATCH_INFO_ARM = 1000507014, + VK_STRUCTURE_TYPE_DATA_GRAPH_PROCESSING_ENGINE_CREATE_INFO_ARM = 1000507016, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_PROPERTIES_ARM = 1000507017, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM = 1000507018, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_INFO_ARM = 1000507019, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_CONSTANT_TENSOR_SEMI_STRUCTURED_SPARSITY_INFO_ARM = 1000507015, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_TOSA_PROPERTIES_ARM = 1000508000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR = 1000201000, @@ -1131,6 +1271,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR = 1000513008, VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_CREATE_INFO_KHR = 1000513009, VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR = 1000513010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR = 1000514000, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_CAPABILITIES_KHR = 1000514001, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PICTURE_INFO_KHR = 1000514002, + VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR = 1000514003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR = 1000515000, VK_STRUCTURE_TYPE_VIDEO_INLINE_QUERY_INFO_KHR = 1000515001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PER_STAGE_DESCRIPTOR_SET_FEATURES_NV = 1000516000, @@ -1144,6 +1288,8 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR = 1000527000, + VK_STRUCTURE_TYPE_ATTACHMENT_FEEDBACK_LOOP_INFO_EXT = 1000527001, VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, @@ -1154,8 +1300,25 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT = 1000545007, VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT = 1000545008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_FEATURES_QCOM = 1000547000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_MEMORY_HEAP_PROPERTIES_QCOM = 1000547001, + VK_STRUCTURE_TYPE_TILE_MEMORY_REQUIREMENTS_QCOM = 1000547002, + VK_STRUCTURE_TYPE_TILE_MEMORY_BIND_INFO_QCOM = 1000547003, + VK_STRUCTURE_TYPE_TILE_MEMORY_SIZE_INFO_QCOM = 1000547004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_KHR = 1000549000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR = 1000426001, + VK_STRUCTURE_TYPE_COPY_MEMORY_INDIRECT_INFO_KHR = 1000549002, + VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INDIRECT_INFO_KHR = 1000549003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT = 1000427000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT = 1000427001, + VK_STRUCTURE_TYPE_DECOMPRESS_MEMORY_INFO_EXT = 1000550002, VK_STRUCTURE_TYPE_DISPLAY_SURFACE_STEREO_CREATE_INFO_NV = 1000551000, VK_STRUCTURE_TYPE_DISPLAY_MODE_STEREO_PROPERTIES_NV = 1000551001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR = 1000552000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_INTRA_REFRESH_CREATE_INFO_KHR = 1000552001, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_INTRA_REFRESH_INFO_KHR = 1000552002, + VK_STRUCTURE_TYPE_VIDEO_REFERENCE_INTRA_REFRESH_INFO_KHR = 1000552003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_INTRA_REFRESH_FEATURES_KHR = 1000552004, VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553000, VK_STRUCTURE_TYPE_VIDEO_FORMAT_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553001, VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUANTIZATION_MAP_INFO_KHR = 1000553002, @@ -1167,6 +1330,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553007, VK_STRUCTURE_TYPE_VIDEO_FORMAT_AV1_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553008, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV = 1000555000, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_DEVICE_CREATE_INFO_NV = 1000556000, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_CREATE_INFO_NV = 1000556001, + VK_STRUCTURE_TYPE_EXTERNAL_COMPUTE_QUEUE_DATA_PARAMS_NV = 1000556002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_COMPUTE_QUEUE_PROPERTIES_NV = 1000556003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR = 1000558000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV = 1000559000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR = 1000562000, @@ -1176,6 +1343,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_VULKAN_PROPERTIES_KHR = 1000562004, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV = 1000563000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT = 1000564000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT8_FEATURES_EXT = 1000567000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV = 1000568000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_FEATURES_NV = 1000569000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000569001, @@ -1205,37 +1373,121 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_INDIRECT_EXECUTION_SET_SHADER_LAYOUT_INFO_EXT = 1000572012, VK_STRUCTURE_TYPE_GENERATED_COMMANDS_PIPELINE_INFO_EXT = 1000572013, VK_STRUCTURE_TYPE_GENERATED_COMMANDS_SHADER_INFO_EXT = 1000572014, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_KHR = 1000573000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_PROPERTIES_KHR = 1000573001, + VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_KHR = 1000573002, + VK_STRUCTURE_TYPE_DEVICE_FAULT_DEBUG_INFO_KHR = 1000573003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR = 1000574000, VK_STRUCTURE_TYPE_MEMORY_BARRIER_ACCESS_FLAGS_3_KHR = 1000574002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA = 1000575000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_PROPERTIES_MESA = 1000575001, VK_STRUCTURE_TYPE_IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA = 1000575002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR = 1000579000, + VK_STRUCTURE_TYPE_PUSH_CONSTANT_BANK_INFO_NV = 1000580000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_FEATURES_NV = 1000580001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_PROPERTIES_NV = 1000580002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_EXT = 1000581000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_EXT = 1000581001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR = 1000584000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_PROPERTIES_KHR = 1000584001, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR = 1000584002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR = 1000586000, VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586001, VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586002, VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586003, + VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS = 1000685000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HDR_VIVID_FEATURES_HUAWEI = 1000590000, VK_STRUCTURE_TYPE_HDR_VIVID_DYNAMIC_METADATA_HUAWEI = 1000590001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV = 1000593000, VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV = 1000593001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_PROPERTIES_NV = 1000593002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_OPACITY_MICROMAP_FEATURES_ARM = 1000596000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_FEEDBACK_2_FEATURES_KHR = 1000598000, + VK_STRUCTURE_TYPE_VIDEO_ENCODE_FEEDBACK_2_CAPABILITIES_KHR = 1000598001, + VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_CREATE_INFO_KHR = 1000598002, VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT = 1000602000, VK_STRUCTURE_TYPE_MEMORY_METAL_HANDLE_PROPERTIES_EXT = 1000602001, VK_STRUCTURE_TYPE_MEMORY_GET_METAL_HANDLE_INFO_EXT = 1000602002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR = 1000421000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_FEATURES_ARM = 1000605000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_PROPERTIES_ARM = 1000605001, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_ARM = 1000605002, + VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_ARM = 1000605003, + VK_STRUCTURE_TYPE_RENDER_PASS_PERFORMANCE_COUNTERS_BY_REGION_BEGIN_INFO_ARM = 1000605004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_FEATURES_ARM = 1000607000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_PROPERTIES_ARM = 1000607001, + VK_STRUCTURE_TYPE_SHADER_INSTRUMENTATION_CREATE_INFO_ARM = 1000607002, + VK_STRUCTURE_TYPE_SHADER_INSTRUMENTATION_METRIC_DESCRIPTION_ARM = 1000607003, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, -#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FORMAT_PACK_FEATURES_ARM = 1000609000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_FEATURES_VALVE = 1000611000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_PROPERTIES_VALVE = 1000611001, + VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_DENSITY_MAP_LAYERED_CREATE_INFO_VALVE = 1000611002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR = 1000286000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR = 1000286001, VK_STRUCTURE_TYPE_SET_PRESENT_CONFIG_NV = 1000613000, -#endif -#ifdef VK_ENABLE_BETA_EXTENSIONS VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, -#endif + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SWAPCHAIN_FEATURES_EXT = 1000616000, + VK_STRUCTURE_TYPE_SWAPCHAIN_FLAGS_SURFACE_CAPABILITIES_EXT = 1000616001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT = 1000425000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT = 1000425001, + VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT = 1000425002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_DEVICE_MEMORY_FEATURES_EXT = 1000620000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR = 1000361000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_KHR = 1000623000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_KHR = 1000623001, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MICROMAP_DATA_KHR = 1000623002, + VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_KHR = 1000623003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_64_BIT_INDEXING_FEATURES_EXT = 1000627000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_RESOLVE_FEATURES_EXT = 1000628000, + VK_STRUCTURE_TYPE_BEGIN_CUSTOM_RESOLVE_INFO_EXT = 1000628001, + VK_STRUCTURE_TYPE_CUSTOM_RESOLVE_CREATE_INFO_EXT = 1000628002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_MODEL_FEATURES_QCOM = 1000629000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_BUILTIN_MODEL_CREATE_INFO_QCOM = 1000629001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_10_FEATURES_KHR = 1000630000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_10_PROPERTIES_KHR = 1000630001, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_FLAGS_INFO_KHR = 1000630002, + VK_STRUCTURE_TYPE_RENDERING_END_INFO_KHR = 1000619003, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_MODE_INFO_KHR = 1000630004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_OPTICAL_FLOW_FEATURES_ARM = 1000631000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_DATA_GRAPH_OPTICAL_FLOW_PROPERTIES_ARM = 1000631001, + VK_STRUCTURE_TYPE_DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_INFO_ARM = 1000631003, + VK_STRUCTURE_TYPE_DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_ARM = 1000631004, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_OPTICAL_FLOW_DISPATCH_INFO_ARM = 1000631005, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_OPTICAL_FLOW_CREATE_INFO_ARM = 1000631002, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_RESOURCE_INFO_IMAGE_LAYOUT_ARM = 1000631006, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SINGLE_NODE_CREATE_INFO_ARM = 1000631007, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SINGLE_NODE_CONNECTION_ARM = 1000631008, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_FEATURES_EXT = 1000635000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT = 1000635001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CACHE_INCREMENTAL_MODE_FEATURES_SEC = 1000637000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_FEATURES_EXT = 1000642000, + VK_STRUCTURE_TYPE_COMPUTE_OCCUPANCY_PRIORITY_PARAMETERS_NV = 1000645000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_OCCUPANCY_PRIORITY_FEATURES_NV = 1000645001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_11_FEATURES_KHR = 1000657000, + VK_STRUCTURE_TYPE_QUEUE_FAMILY_OPTIMAL_IMAGE_TRANSFER_GRANULARITY_PROPERTIES_KHR = 1000657001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_PARTITIONED_FEATURES_EXT = 1000662000, + VK_STRUCTURE_TYPE_UBM_SURFACE_CREATE_INFO_SEC = 1000664000, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_4_KHR = 1000668000, + VK_STRUCTURE_TYPE_IMAGE_CREATE_FLAGS_2_CREATE_INFO_KHR = 1000668001, + VK_STRUCTURE_TYPE_IMAGE_USAGE_FLAGS_2_CREATE_INFO_KHR = 1000668002, + VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_2_CREATE_INFO_KHR = 1000668003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_FLAGS_FEATURES_KHR = 1000668004, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_2_CREATE_INFO_KHR = 1000668005, + VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_2_KHR = 1000668006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MIXED_FLOAT_DOT_PRODUCT_FEATURES_VALVE = 1000673000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_THROTTLE_HINT_FEATURES_SEC = 1000674000, + VK_STRUCTURE_TYPE_THROTTLE_HINT_SUBMIT_INFO_SEC = 1000674001, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676000, + VK_STRUCTURE_TYPE_DATA_GRAPH_PIPELINE_SESSION_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_FEATURES_ARM = 1000676002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_RESTART_INDEX_FEATURES_EXT = 1000678000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_DECODE_VECTOR_FEATURES_NV = 1000689000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, - // VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT is a deprecated alias + // VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT is a legacy alias VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, VK_STRUCTURE_TYPE_RENDERING_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_INFO, VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, @@ -1283,7 +1535,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, - // VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT is a deprecated alias + // VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT is a legacy alias VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, @@ -1358,7 +1610,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, - // VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL is a deprecated alias + // VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL is a legacy alias VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, @@ -1399,10 +1651,21 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY, VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_MAP_INFO, VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_KHR, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_KHR, + VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_KHR, + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR, + VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO, VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO, @@ -1434,6 +1697,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR, VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, @@ -1443,6 +1707,12 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT, + VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES, @@ -1469,58 +1739,10 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO, VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_INFO, VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR = VK_STRUCTURE_TYPE_PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO, + VK_STRUCTURE_TYPE_RENDERING_END_INFO_EXT = VK_STRUCTURE_TYPE_RENDERING_END_INFO_KHR, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; -typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, - VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCacheHeaderVersion; - -typedef enum VkImageLayout { - VK_IMAGE_LAYOUT_UNDEFINED = 0, - VK_IMAGE_LAYOUT_GENERAL = 1, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, - VK_IMAGE_LAYOUT_PREINITIALIZED = 8, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, - VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, - VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000, - VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, - VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ = 1000232000, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, - VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, - VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, - VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, - VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, - VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, - VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, - VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000, - VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001, - VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, - VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000, - VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR = 1000553000, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, - VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF -} VkImageLayout; - typedef enum VkObjectType { VK_OBJECT_TYPE_UNKNOWN = 0, VK_OBJECT_TYPE_INSTANCE = 1, @@ -1548,8 +1770,8 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_DESCRIPTOR_SET = 23, VK_OBJECT_TYPE_FRAMEBUFFER = 24, VK_OBJECT_TYPE_COMMAND_POOL = 25, - VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000, VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, @@ -1561,21 +1783,31 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_CU_MODULE_NVX = 1000029000, VK_OBJECT_TYPE_CU_FUNCTION_NVX = 1000029001, VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000, + VK_OBJECT_TYPE_GPA_SESSION_AMD = 1000133000, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000, VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000, +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_OBJECT_TYPE_CUDA_MODULE_NV = 1000307000, +#endif +#ifdef VK_ENABLE_BETA_EXTENSIONS VK_OBJECT_TYPE_CUDA_FUNCTION_NV = 1000307001, +#endif VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA = 1000366000, VK_OBJECT_TYPE_MICROMAP_EXT = 1000396000, + VK_OBJECT_TYPE_TENSOR_ARM = 1000460000, + VK_OBJECT_TYPE_TENSOR_VIEW_ARM = 1000460001, VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV = 1000464000, VK_OBJECT_TYPE_SHADER_EXT = 1000482000, VK_OBJECT_TYPE_PIPELINE_BINARY_KHR = 1000483000, + VK_OBJECT_TYPE_DATA_GRAPH_PIPELINE_SESSION_ARM = 1000507000, + VK_OBJECT_TYPE_EXTERNAL_COMPUTE_QUEUE_NV = 1000556000, VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_EXT = 1000572000, VK_OBJECT_TYPE_INDIRECT_EXECUTION_SET_EXT = 1000572001, + VK_OBJECT_TYPE_SHADER_INSTRUMENTATION_ARM = 1000607000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, @@ -1591,6 +1823,7 @@ typedef enum VkVendorId { VK_VENDOR_ID_MESA = 0x10005, VK_VENDOR_ID_POCL = 0x10006, VK_VENDOR_ID_MOBILEYE = 0x10007, + VK_VENDOR_ID_APE = 0x10008, VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; @@ -1858,7 +2091,55 @@ typedef enum VkFormat { VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, + VK_FORMAT_ASTC_3x3x3_UNORM_BLOCK_EXT = 1000288000, + VK_FORMAT_ASTC_3x3x3_SRGB_BLOCK_EXT = 1000288001, + VK_FORMAT_ASTC_3x3x3_SFLOAT_BLOCK_EXT = 1000288002, + VK_FORMAT_ASTC_4x3x3_UNORM_BLOCK_EXT = 1000288003, + VK_FORMAT_ASTC_4x3x3_SRGB_BLOCK_EXT = 1000288004, + VK_FORMAT_ASTC_4x3x3_SFLOAT_BLOCK_EXT = 1000288005, + VK_FORMAT_ASTC_4x4x3_UNORM_BLOCK_EXT = 1000288006, + VK_FORMAT_ASTC_4x4x3_SRGB_BLOCK_EXT = 1000288007, + VK_FORMAT_ASTC_4x4x3_SFLOAT_BLOCK_EXT = 1000288008, + VK_FORMAT_ASTC_4x4x4_UNORM_BLOCK_EXT = 1000288009, + VK_FORMAT_ASTC_4x4x4_SRGB_BLOCK_EXT = 1000288010, + VK_FORMAT_ASTC_4x4x4_SFLOAT_BLOCK_EXT = 1000288011, + VK_FORMAT_ASTC_5x4x4_UNORM_BLOCK_EXT = 1000288012, + VK_FORMAT_ASTC_5x4x4_SRGB_BLOCK_EXT = 1000288013, + VK_FORMAT_ASTC_5x4x4_SFLOAT_BLOCK_EXT = 1000288014, + VK_FORMAT_ASTC_5x5x4_UNORM_BLOCK_EXT = 1000288015, + VK_FORMAT_ASTC_5x5x4_SRGB_BLOCK_EXT = 1000288016, + VK_FORMAT_ASTC_5x5x4_SFLOAT_BLOCK_EXT = 1000288017, + VK_FORMAT_ASTC_5x5x5_UNORM_BLOCK_EXT = 1000288018, + VK_FORMAT_ASTC_5x5x5_SRGB_BLOCK_EXT = 1000288019, + VK_FORMAT_ASTC_5x5x5_SFLOAT_BLOCK_EXT = 1000288020, + VK_FORMAT_ASTC_6x5x5_UNORM_BLOCK_EXT = 1000288021, + VK_FORMAT_ASTC_6x5x5_SRGB_BLOCK_EXT = 1000288022, + VK_FORMAT_ASTC_6x5x5_SFLOAT_BLOCK_EXT = 1000288023, + VK_FORMAT_ASTC_6x6x5_UNORM_BLOCK_EXT = 1000288024, + VK_FORMAT_ASTC_6x6x5_SRGB_BLOCK_EXT = 1000288025, + VK_FORMAT_ASTC_6x6x5_SFLOAT_BLOCK_EXT = 1000288026, + VK_FORMAT_ASTC_6x6x6_UNORM_BLOCK_EXT = 1000288027, + VK_FORMAT_ASTC_6x6x6_SRGB_BLOCK_EXT = 1000288028, + VK_FORMAT_ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029, + VK_FORMAT_R8_BOOL_ARM = 1000460000, + VK_FORMAT_R16_SFLOAT_FPENCODING_BFLOAT16_ARM = 1000460001, + VK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM = 1000460002, + VK_FORMAT_R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM = 1000460003, VK_FORMAT_R16G16_SFIXED5_NV = 1000464000, + VK_FORMAT_R10X6_UINT_PACK16_ARM = 1000609000, + VK_FORMAT_R10X6G10X6_UINT_2PACK16_ARM = 1000609001, + VK_FORMAT_R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM = 1000609002, + VK_FORMAT_R12X4_UINT_PACK16_ARM = 1000609003, + VK_FORMAT_R12X4G12X4_UINT_2PACK16_ARM = 1000609004, + VK_FORMAT_R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM = 1000609005, + VK_FORMAT_R14X2_UINT_PACK16_ARM = 1000609006, + VK_FORMAT_R14X2G14X2_UINT_2PACK16_ARM = 1000609007, + VK_FORMAT_R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM = 1000609008, + VK_FORMAT_R14X2_UNORM_PACK16_ARM = 1000609009, + VK_FORMAT_R14X2G14X2_UNORM_2PACK16_ARM = 1000609010, + VK_FORMAT_R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM = 1000609011, + VK_FORMAT_G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM = 1000609012, + VK_FORMAT_G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM = 1000609013, VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, @@ -1913,7 +2194,7 @@ typedef enum VkFormat { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT = VK_FORMAT_A4R4G4B4_UNORM_PACK16, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT = VK_FORMAT_A4B4G4R4_UNORM_PACK16, - // VK_FORMAT_R16G16_S10_5_NV is a deprecated alias + // VK_FORMAT_R16G16_S10_5_NV is a legacy alias VK_FORMAT_R16G16_S10_5_NV = VK_FORMAT_R16G16_SFIXED5_NV, VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR = VK_FORMAT_A1B5G5R5_UNORM_PACK16, VK_FORMAT_A8_UNORM_KHR = VK_FORMAT_A8_UNORM, @@ -1953,6 +2234,7 @@ typedef enum VkQueryType { VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, + VK_QUERY_TYPE_TIME_ELAPSED_QCOM = 1000173000, VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR = 1000299000, VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000, @@ -1970,6 +2252,52 @@ typedef enum VkSharingMode { VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF } VkSharingMode; +typedef enum VkImageLayout { + VK_IMAGE_LAYOUT_UNDEFINED = 0, + VK_IMAGE_LAYOUT_GENERAL = 1, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7, + VK_IMAGE_LAYOUT_PREINITIALIZED = 8, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ = 1000232000, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, + VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR = 1000024000, + VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR = 1000024001, + VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR = 1000024002, + VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, + VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, + VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR = 1000164003, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR = 1000299000, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR = 1000299001, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR = 1000299002, + VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000, + VK_IMAGE_LAYOUT_TENSOR_ALIASING_ARM = 1000460000, + VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR = 1000553000, + VK_IMAGE_LAYOUT_ZERO_INITIALIZED_EXT = 1000620000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF +} VkImageLayout; + typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_IDENTITY = 0, VK_COMPONENT_SWIZZLE_ZERO = 1, @@ -1992,6 +2320,116 @@ typedef enum VkImageViewType { VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF } VkImageViewType; +typedef enum VkCommandBufferLevel { + VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, + VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferLevel; + +typedef enum VkIndexType { + VK_INDEX_TYPE_UINT16 = 0, + VK_INDEX_TYPE_UINT32 = 1, + VK_INDEX_TYPE_UINT8 = 1000265000, + VK_INDEX_TYPE_NONE_KHR = 1000165000, + VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, + VK_INDEX_TYPE_UINT8_EXT = VK_INDEX_TYPE_UINT8, + VK_INDEX_TYPE_UINT8_KHR = VK_INDEX_TYPE_UINT8, + VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkIndexType; + +typedef enum VkPipelineCacheHeaderVersion { + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_DATA_GRAPH_QCOM = 1000629000, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheHeaderVersion; + +typedef enum VkBorderColor { + VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, + VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, + VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, + VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, + VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, + VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, + VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, + VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, + VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF +} VkBorderColor; + +typedef enum VkFilter { + VK_FILTER_NEAREST = 0, + VK_FILTER_LINEAR = 1, + VK_FILTER_CUBIC_EXT = 1000015000, + VK_FILTER_CUBIC_IMG = VK_FILTER_CUBIC_EXT, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF +} VkFilter; + +typedef enum VkSamplerAddressMode { + VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, + VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + // VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR is a legacy alias + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerAddressMode; + +typedef enum VkCompareOp { + VK_COMPARE_OP_NEVER = 0, + VK_COMPARE_OP_LESS = 1, + VK_COMPARE_OP_EQUAL = 2, + VK_COMPARE_OP_LESS_OR_EQUAL = 3, + VK_COMPARE_OP_GREATER = 4, + VK_COMPARE_OP_NOT_EQUAL = 5, + VK_COMPARE_OP_GREATER_OR_EQUAL = 6, + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF +} VkCompareOp; + +typedef enum VkSamplerMipmapMode { + VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerMipmapMode; + +typedef enum VkDescriptorType { + VK_DESCRIPTOR_TYPE_SAMPLER = 0, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, + VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, + VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, + VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, + VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, + VK_DESCRIPTOR_TYPE_TENSOR_ARM = 1000460000, + VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000, + VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, + VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT, + VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorType; + +typedef enum VkPipelineBindPoint { + VK_PIPELINE_BIND_POINT_GRAPHICS = 0, + VK_PIPELINE_BIND_POINT_COMPUTE = 1, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX = 1000134000, +#endif + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, + VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM = 1000507000, + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF +} VkPipelineBindPoint; + typedef enum VkBlendFactor { VK_BLEND_FACTOR_ZERO = 0, VK_BLEND_FACTOR_ONE = 1, @@ -2070,18 +2508,6 @@ typedef enum VkBlendOp { VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF } VkBlendOp; -typedef enum VkCompareOp { - VK_COMPARE_OP_NEVER = 0, - VK_COMPARE_OP_LESS = 1, - VK_COMPARE_OP_EQUAL = 2, - VK_COMPARE_OP_LESS_OR_EQUAL = 3, - VK_COMPARE_OP_GREATER = 4, - VK_COMPARE_OP_NOT_EQUAL = 5, - VK_COMPARE_OP_GREATER_OR_EQUAL = 6, - VK_COMPARE_OP_ALWAYS = 7, - VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF -} VkCompareOp; - typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT = 0, VK_DYNAMIC_STATE_SCISSOR = 1, @@ -2182,6 +2608,38 @@ typedef enum VkFrontFace { VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF } VkFrontFace; +typedef enum VkLogicOp { + VK_LOGIC_OP_CLEAR = 0, + VK_LOGIC_OP_AND = 1, + VK_LOGIC_OP_AND_REVERSE = 2, + VK_LOGIC_OP_COPY = 3, + VK_LOGIC_OP_AND_INVERTED = 4, + VK_LOGIC_OP_NO_OP = 5, + VK_LOGIC_OP_XOR = 6, + VK_LOGIC_OP_OR = 7, + VK_LOGIC_OP_NOR = 8, + VK_LOGIC_OP_EQUIVALENT = 9, + VK_LOGIC_OP_INVERT = 10, + VK_LOGIC_OP_OR_REVERSE = 11, + VK_LOGIC_OP_COPY_INVERTED = 12, + VK_LOGIC_OP_OR_INVERTED = 13, + VK_LOGIC_OP_NAND = 14, + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF +} VkLogicOp; + +typedef enum VkStencilOp { + VK_STENCIL_OP_KEEP = 0, + VK_STENCIL_OP_ZERO = 1, + VK_STENCIL_OP_REPLACE = 2, + VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, + VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, + VK_STENCIL_OP_INVERT = 5, + VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF +} VkStencilOp; + typedef enum VkVertexInputRate { VK_VERTEX_INPUT_RATE_VERTEX = 0, VK_VERTEX_INPUT_RATE_INSTANCE = 1, @@ -2211,99 +2669,6 @@ typedef enum VkPolygonMode { VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF } VkPolygonMode; -typedef enum VkStencilOp { - VK_STENCIL_OP_KEEP = 0, - VK_STENCIL_OP_ZERO = 1, - VK_STENCIL_OP_REPLACE = 2, - VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3, - VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, - VK_STENCIL_OP_INVERT = 5, - VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, - VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF -} VkStencilOp; - -typedef enum VkLogicOp { - VK_LOGIC_OP_CLEAR = 0, - VK_LOGIC_OP_AND = 1, - VK_LOGIC_OP_AND_REVERSE = 2, - VK_LOGIC_OP_COPY = 3, - VK_LOGIC_OP_AND_INVERTED = 4, - VK_LOGIC_OP_NO_OP = 5, - VK_LOGIC_OP_XOR = 6, - VK_LOGIC_OP_OR = 7, - VK_LOGIC_OP_NOR = 8, - VK_LOGIC_OP_EQUIVALENT = 9, - VK_LOGIC_OP_INVERT = 10, - VK_LOGIC_OP_OR_REVERSE = 11, - VK_LOGIC_OP_COPY_INVERTED = 12, - VK_LOGIC_OP_OR_INVERTED = 13, - VK_LOGIC_OP_NAND = 14, - VK_LOGIC_OP_SET = 15, - VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF -} VkLogicOp; - -typedef enum VkBorderColor { - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, - VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, - VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, - VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, - VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, - VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, - VK_BORDER_COLOR_FLOAT_CUSTOM_EXT = 1000287003, - VK_BORDER_COLOR_INT_CUSTOM_EXT = 1000287004, - VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF -} VkBorderColor; - -typedef enum VkFilter { - VK_FILTER_NEAREST = 0, - VK_FILTER_LINEAR = 1, - VK_FILTER_CUBIC_EXT = 1000015000, - VK_FILTER_CUBIC_IMG = VK_FILTER_CUBIC_EXT, - VK_FILTER_MAX_ENUM = 0x7FFFFFFF -} VkFilter; - -typedef enum VkSamplerAddressMode { - VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, - // VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR is a deprecated alias - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerAddressMode; - -typedef enum VkSamplerMipmapMode { - VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, - VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF -} VkSamplerMipmapMode; - -typedef enum VkDescriptorType { - VK_DESCRIPTOR_TYPE_SAMPLER = 0, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, - VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, - VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, - VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, - VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000, - VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, - VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, - VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001, - VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000, - VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000, - VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, - VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT, - VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorType; - typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, VK_ATTACHMENT_LOAD_OP_CLEAR = 1, @@ -2324,35 +2689,6 @@ typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; -typedef enum VkPipelineBindPoint { - VK_PIPELINE_BIND_POINT_GRAPHICS = 0, - VK_PIPELINE_BIND_POINT_COMPUTE = 1, -#ifdef VK_ENABLE_BETA_EXTENSIONS - VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX = 1000134000, -#endif - VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000, - VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI = 1000369003, - VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, - VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF -} VkPipelineBindPoint; - -typedef enum VkCommandBufferLevel { - VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, - VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, - VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferLevel; - -typedef enum VkIndexType { - VK_INDEX_TYPE_UINT16 = 0, - VK_INDEX_TYPE_UINT32 = 1, - VK_INDEX_TYPE_UINT8 = 1000265000, - VK_INDEX_TYPE_NONE_KHR = 1000165000, - VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR, - VK_INDEX_TYPE_UINT8_EXT = VK_INDEX_TYPE_UINT8, - VK_INDEX_TYPE_UINT8_KHR = VK_INDEX_TYPE_UINT8, - VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkIndexType; - typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, @@ -2361,67 +2697,6 @@ typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; -typedef enum VkAccessFlagBits { - VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, - VK_ACCESS_INDEX_READ_BIT = 0x00000002, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, - VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, - VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, - VK_ACCESS_SHADER_READ_BIT = 0x00000020, - VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, - VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, - VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, - VK_ACCESS_HOST_READ_BIT = 0x00002000, - VK_ACCESS_HOST_WRITE_BIT = 0x00004000, - VK_ACCESS_MEMORY_READ_BIT = 0x00008000, - VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, - VK_ACCESS_NONE = 0, - VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, - VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, - VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, - VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, - VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, - VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, - VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, - VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, - VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000, - VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000, - VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, - VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, - VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, - VK_ACCESS_NONE_KHR = VK_ACCESS_NONE, - VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV, - VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV, - VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkAccessFlagBits; -typedef VkFlags VkAccessFlags; - -typedef enum VkImageAspectFlagBits { - VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, - VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, - VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, - VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, - VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, - VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, - VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, - VK_IMAGE_ASPECT_NONE = 0, - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, - VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, - VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, - VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, - VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, - VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, - VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, - VK_IMAGE_ASPECT_NONE_KHR = VK_IMAGE_ASPECT_NONE, - VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkImageAspectFlagBits; -typedef VkFlags VkImageAspectFlags; - typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002, @@ -2483,19 +2758,22 @@ typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800, VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200, VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000, + VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT = 0x00010000, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000, VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT = 0x00004000, - VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00010000, VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0x00040000, VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT = 0x00020000, - VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = 0x00008000, VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR = 0x00100000, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_EXT = 0x00008000, + VK_IMAGE_CREATE_ALIAS_SINGLE_LAYER_DESCRIPTOR_BIT_KHR = 0x00400000, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = VK_IMAGE_CREATE_EXTENDED_USAGE_BIT, VK_IMAGE_CREATE_DISJOINT_BIT_KHR = VK_IMAGE_CREATE_DISJOINT_BIT, VK_IMAGE_CREATE_ALIAS_BIT_KHR = VK_IMAGE_CREATE_ALIAS_BIT, + VK_IMAGE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT, + VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM = VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_EXT, VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageCreateFlagBits; typedef VkFlags VkImageCreateFlags; @@ -2534,6 +2812,8 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI = 0x00040000, VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM = 0x00100000, VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0x00200000, + VK_IMAGE_USAGE_TENSOR_ALIASING_BIT_ARM = 0x00800000, + VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM = 0x08000000, VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x02000000, VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x04000000, VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, @@ -2551,6 +2831,7 @@ typedef VkFlags VkInstanceCreateFlags; typedef enum VkMemoryHeapFlagBits { VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002, + VK_MEMORY_HEAP_TILE_MEMORY_BIT_QCOM = 0x00000008, VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT, VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryHeapFlagBits; @@ -2579,13 +2860,46 @@ typedef enum VkQueueFlagBits { VK_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, VK_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, VK_QUEUE_OPTICAL_FLOW_BIT_NV = 0x00000100, + VK_QUEUE_DATA_GRAPH_BIT_ARM = 0x00000400, VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueueFlagBits; typedef VkFlags VkQueueFlags; + +typedef enum VkShaderStageFlagBits { + VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, + VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, + VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, + VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, + VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, + VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, + VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, + VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, + VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, + VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, + VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, + VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, + VK_SHADER_STAGE_TASK_BIT_EXT = 0x00000040, + VK_SHADER_STAGE_MESH_BIT_EXT = 0x00000080, + VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, + VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0x00080000, + VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, + VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, + VK_SHADER_STAGE_TASK_BIT_NV = VK_SHADER_STAGE_TASK_BIT_EXT, + VK_SHADER_STAGE_MESH_BIT_NV = VK_SHADER_STAGE_MESH_BIT_EXT, + VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkShaderStageFlagBits; +typedef VkFlags VkShaderStageFlags; typedef VkFlags VkDeviceCreateFlags; typedef enum VkDeviceQueueCreateFlagBits { VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001, + VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR = 0x00000004, VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDeviceQueueCreateFlagBits; typedef VkFlags VkDeviceQueueCreateFlags; @@ -2615,16 +2929,16 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000, VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000, - VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000, VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0x00080000, VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0x00100000, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT = 0x00020000, VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT, VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE, - VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV, VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; typedef VkFlags VkPipelineStageFlags; @@ -2635,11 +2949,26 @@ typedef enum VkMemoryMapFlagBits { } VkMemoryMapFlagBits; typedef VkFlags VkMemoryMapFlags; -typedef enum VkSparseMemoryBindFlagBits { - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, - VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSparseMemoryBindFlagBits; -typedef VkFlags VkSparseMemoryBindFlags; +typedef enum VkImageAspectFlagBits { + VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001, + VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, + VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, + VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, + VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010, + VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020, + VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040, + VK_IMAGE_ASPECT_NONE = 0, + VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT = 0x00000080, + VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT = 0x00000100, + VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT = 0x00000200, + VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT = 0x00000400, + VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = VK_IMAGE_ASPECT_PLANE_0_BIT, + VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = VK_IMAGE_ASPECT_PLANE_1_BIT, + VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = VK_IMAGE_ASPECT_PLANE_2_BIT, + VK_IMAGE_ASPECT_NONE_KHR = VK_IMAGE_ASPECT_NONE, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkImageAspectFlagBits; +typedef VkFlags VkImageAspectFlags; typedef enum VkSparseImageFormatFlagBits { VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, @@ -2649,6 +2978,12 @@ typedef enum VkSparseImageFormatFlagBits { } VkSparseImageFormatFlagBits; typedef VkFlags VkSparseImageFormatFlags; +typedef enum VkSparseMemoryBindFlagBits { + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSparseMemoryBindFlagBits; +typedef VkFlags VkSparseMemoryBindFlags; + typedef enum VkFenceCreateFlagBits { VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -2656,12 +2991,11 @@ typedef enum VkFenceCreateFlagBits { typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkSemaphoreCreateFlags; -typedef enum VkEventCreateFlagBits { - VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001, - VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT, - VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkEventCreateFlagBits; -typedef VkFlags VkEventCreateFlags; +typedef enum VkQueryPoolCreateFlagBits { + VK_QUERY_POOL_CREATE_RESET_BIT_KHR = 0x00000001, + VK_QUERY_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryPoolCreateFlagBits; +typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001, @@ -2681,7 +3015,6 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; typedef VkFlags VkQueryPipelineStatisticFlags; -typedef VkFlags VkQueryPoolCreateFlags; typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_64_BIT = 0x00000001, @@ -2726,6 +3059,7 @@ typedef enum VkBufferUsageFlagBits { #ifdef VK_ENABLE_BETA_EXTENSIONS VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000, #endif + VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT = 0x10000000, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400, @@ -2736,13 +3070,13 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000, VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000, VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT = 0x01000000, + VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM = 0x08000000, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferUsageFlagBits; typedef VkFlags VkBufferUsageFlags; -typedef VkFlags VkBufferViewCreateFlags; typedef enum VkImageViewCreateFlagBits { VK_IMAGE_VIEW_CREATE_FRAGMENT_DENSITY_MAP_DYNAMIC_BIT_EXT = 0x00000001, @@ -2751,6 +3085,101 @@ typedef enum VkImageViewCreateFlagBits { VK_IMAGE_VIEW_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageViewCreateFlagBits; typedef VkFlags VkImageViewCreateFlags; + +typedef enum VkAccessFlagBits { + VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001, + VK_ACCESS_INDEX_READ_BIT = 0x00000002, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004, + VK_ACCESS_UNIFORM_READ_BIT = 0x00000008, + VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010, + VK_ACCESS_SHADER_READ_BIT = 0x00000020, + VK_ACCESS_SHADER_WRITE_BIT = 0x00000040, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400, + VK_ACCESS_TRANSFER_READ_BIT = 0x00000800, + VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000, + VK_ACCESS_HOST_READ_BIT = 0x00002000, + VK_ACCESS_HOST_WRITE_BIT = 0x00004000, + VK_ACCESS_MEMORY_READ_BIT = 0x00008000, + VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, + VK_ACCESS_NONE = 0, + VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000, + VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000, + VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000, + VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000, + VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000, + VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT = 0x00020000, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT = 0x00040000, + VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT, + VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT, + VK_ACCESS_NONE_KHR = VK_ACCESS_NONE, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkAccessFlagBits; +typedef VkFlags VkAccessFlags; + +typedef enum VkDependencyFlagBits { + VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, + VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, + VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, + VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008, + VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR = 0x00000020, + VK_DEPENDENCY_ASYMMETRIC_EVENT_BIT_KHR = 0x00000040, + VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, + VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, + VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDependencyFlagBits; +typedef VkFlags VkDependencyFlags; + +typedef enum VkCommandPoolCreateFlagBits { + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004, + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolCreateFlagBits; +typedef VkFlags VkCommandPoolCreateFlags; + +typedef enum VkCommandPoolResetFlagBits { + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandPoolResetFlagBits; +typedef VkFlags VkCommandPoolResetFlags; + +typedef enum VkQueryControlFlagBits { + VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, + VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkQueryControlFlagBits; +typedef VkFlags VkQueryControlFlags; + +typedef enum VkCommandBufferUsageFlagBits { + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferUsageFlagBits; +typedef VkFlags VkCommandBufferUsageFlags; + +typedef enum VkCommandBufferResetFlagBits { + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, + VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCommandBufferResetFlagBits; +typedef VkFlags VkCommandBufferResetFlags; + +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001, + VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; +typedef VkFlags VkEventCreateFlags; +typedef VkFlags VkBufferViewCreateFlags; typedef VkFlags VkShaderModuleCreateFlags; typedef enum VkPipelineCacheCreateFlagBits { @@ -2761,21 +3190,12 @@ typedef enum VkPipelineCacheCreateFlagBits { } VkPipelineCacheCreateFlagBits; typedef VkFlags VkPipelineCacheCreateFlags; -typedef enum VkColorComponentFlagBits { - VK_COLOR_COMPONENT_R_BIT = 0x00000001, - VK_COLOR_COMPONENT_G_BIT = 0x00000002, - VK_COLOR_COMPONENT_B_BIT = 0x00000004, - VK_COLOR_COMPONENT_A_BIT = 0x00000008, - VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkColorComponentFlagBits; -typedef VkFlags VkColorComponentFlags; - typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, - VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010, + VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008, VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 0x00000100, VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 0x00000200, VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT = 0x08000000, @@ -2800,25 +3220,36 @@ typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000, VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000, VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000, - VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000, #ifdef VK_ENABLE_BETA_EXTENSIONS VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000, #endif + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR = 0x01000000, + // VK_PIPELINE_CREATE_DISPATCH_BASE is a legacy alias VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT, - VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE, - // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT is a deprecated alias + VK_PIPELINE_CREATE_DISPATCH_BASE_BIT_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + // VK_PIPELINE_CREATE_DISPATCH_BASE_KHR is a legacy alias + VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT is a legacy alias VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT, - // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR is a deprecated alias + // VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR is a legacy alias VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT, VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT, + VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR, VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT = VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT, VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT = VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT, VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineCreateFlagBits; typedef VkFlags VkPipelineCreateFlags; +typedef enum VkPipelineLayoutCreateFlagBits { + VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, + VK_PIPELINE_LAYOUT_CREATE_NO_TASK_SHADER_BIT_KHR = 0x00000004, + VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineLayoutCreateFlagBits; +typedef VkFlags VkPipelineLayoutCreateFlags; + typedef enum VkPipelineShaderStageCreateFlagBits { VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 0x00000001, VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 0x00000002, @@ -2828,75 +3259,6 @@ typedef enum VkPipelineShaderStageCreateFlagBits { } VkPipelineShaderStageCreateFlagBits; typedef VkFlags VkPipelineShaderStageCreateFlags; -typedef enum VkShaderStageFlagBits { - VK_SHADER_STAGE_VERTEX_BIT = 0x00000001, - VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, - VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, - VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, - VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, - VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, - VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, - VK_SHADER_STAGE_ALL = 0x7FFFFFFF, - VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, - VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, - VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, - VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, - VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, - VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, - VK_SHADER_STAGE_TASK_BIT_EXT = 0x00000040, - VK_SHADER_STAGE_MESH_BIT_EXT = 0x00000080, - VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI = 0x00004000, - VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI = 0x00080000, - VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR, - VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, - VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, - VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR, - VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, - VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR, - VK_SHADER_STAGE_TASK_BIT_NV = VK_SHADER_STAGE_TASK_BIT_EXT, - VK_SHADER_STAGE_MESH_BIT_NV = VK_SHADER_STAGE_MESH_BIT_EXT, - VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkShaderStageFlagBits; - -typedef enum VkCullModeFlagBits { - VK_CULL_MODE_NONE = 0, - VK_CULL_MODE_FRONT_BIT = 0x00000001, - VK_CULL_MODE_BACK_BIT = 0x00000002, - VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, - VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCullModeFlagBits; -typedef VkFlags VkCullModeFlags; -typedef VkFlags VkPipelineVertexInputStateCreateFlags; -typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; -typedef VkFlags VkPipelineTessellationStateCreateFlags; -typedef VkFlags VkPipelineViewportStateCreateFlags; -typedef VkFlags VkPipelineRasterizationStateCreateFlags; -typedef VkFlags VkPipelineMultisampleStateCreateFlags; - -typedef enum VkPipelineDepthStencilStateCreateFlagBits { - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000001, - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000002, - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, - VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineDepthStencilStateCreateFlagBits; -typedef VkFlags VkPipelineDepthStencilStateCreateFlags; - -typedef enum VkPipelineColorBlendStateCreateFlagBits { - VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0x00000001, - VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT, - VK_PIPELINE_COLOR_BLEND_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineColorBlendStateCreateFlagBits; -typedef VkFlags VkPipelineColorBlendStateCreateFlags; -typedef VkFlags VkPipelineDynamicStateCreateFlags; - -typedef enum VkPipelineLayoutCreateFlagBits { - VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002, - VK_PIPELINE_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineLayoutCreateFlagBits; -typedef VkFlags VkPipelineLayoutCreateFlags; -typedef VkFlags VkShaderStageFlags; - typedef enum VkSamplerCreateFlagBits { VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT = 0x00000001, VK_SAMPLER_CREATE_SUBSAMPLED_COARSE_RECONSTRUCTION_BIT_EXT = 0x00000002, @@ -2935,24 +3297,55 @@ typedef enum VkDescriptorSetLayoutCreateFlagBits { } VkDescriptorSetLayoutCreateFlagBits; typedef VkFlags VkDescriptorSetLayoutCreateFlags; +typedef enum VkColorComponentFlagBits { + VK_COLOR_COMPONENT_R_BIT = 0x00000001, + VK_COLOR_COMPONENT_G_BIT = 0x00000002, + VK_COLOR_COMPONENT_B_BIT = 0x00000004, + VK_COLOR_COMPONENT_A_BIT = 0x00000008, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkColorComponentFlagBits; +typedef VkFlags VkColorComponentFlags; + +typedef enum VkCullModeFlagBits { + VK_CULL_MODE_NONE = 0, + VK_CULL_MODE_FRONT_BIT = 0x00000001, + VK_CULL_MODE_BACK_BIT = 0x00000002, + VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, + VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkCullModeFlagBits; +typedef VkFlags VkCullModeFlags; + +typedef enum VkPipelineColorBlendStateCreateFlagBits { + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT, + VK_PIPELINE_COLOR_BLEND_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineColorBlendStateCreateFlagBits; +typedef VkFlags VkPipelineColorBlendStateCreateFlags; + +typedef enum VkPipelineDepthStencilStateCreateFlagBits { + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000001, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000002, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, + VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineDepthStencilStateCreateFlagBits; +typedef VkFlags VkPipelineDepthStencilStateCreateFlags; +typedef VkFlags VkPipelineDynamicStateCreateFlags; +typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; +typedef VkFlags VkPipelineMultisampleStateCreateFlags; +typedef VkFlags VkPipelineRasterizationStateCreateFlags; +typedef VkFlags VkPipelineTessellationStateCreateFlags; +typedef VkFlags VkPipelineVertexInputStateCreateFlags; +typedef VkFlags VkPipelineViewportStateCreateFlags; + typedef enum VkAttachmentDescriptionFlagBits { VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, + VK_ATTACHMENT_DESCRIPTION_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_ATTACHMENT_DESCRIPTION_RESOLVE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000004, VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAttachmentDescriptionFlagBits; typedef VkFlags VkAttachmentDescriptionFlags; -typedef enum VkDependencyFlagBits { - VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, - VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004, - VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002, - VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008, - VK_DEPENDENCY_QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_BIT_KHR = 0x00000020, - VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT, - VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT, - VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkDependencyFlagBits; -typedef VkFlags VkDependencyFlags; - typedef enum VkFramebufferCreateFlagBits { VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 0x00000001, VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, @@ -2962,6 +3355,7 @@ typedef VkFlags VkFramebufferCreateFlags; typedef enum VkRenderPassCreateFlagBits { VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM = 0x00000002, + VK_RENDER_PASS_CREATE_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x00000004, VK_RENDER_PASS_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkRenderPassCreateFlagBits; typedef VkFlags VkRenderPassCreateFlags; @@ -2969,12 +3363,15 @@ typedef VkFlags VkRenderPassCreateFlags; typedef enum VkSubpassDescriptionFlagBits { VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001, VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002, - VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = 0x00000004, - VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = 0x00000008, + VK_SUBPASS_DESCRIPTION_TILE_SHADING_APRON_BIT_QCOM = 0x00000100, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT = 0x00000010, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT = 0x00000020, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT = 0x00000040, VK_SUBPASS_DESCRIPTION_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000080, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_EXT = 0x00000004, + VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT = 0x00000008, + VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM = VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_EXT, + VK_SUBPASS_DESCRIPTION_SHADER_RESOLVE_BIT_QCOM = VK_SUBPASS_DESCRIPTION_CUSTOM_RESOLVE_BIT_EXT, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT, VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT, @@ -2982,45 +3379,11 @@ typedef enum VkSubpassDescriptionFlagBits { } VkSubpassDescriptionFlagBits; typedef VkFlags VkSubpassDescriptionFlags; -typedef enum VkCommandPoolCreateFlagBits { - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, - VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004, - VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandPoolCreateFlagBits; -typedef VkFlags VkCommandPoolCreateFlags; - -typedef enum VkCommandPoolResetFlagBits { - VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, - VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandPoolResetFlagBits; -typedef VkFlags VkCommandPoolResetFlags; - -typedef enum VkCommandBufferUsageFlagBits { - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, - VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, - VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferUsageFlagBits; -typedef VkFlags VkCommandBufferUsageFlags; - -typedef enum VkQueryControlFlagBits { - VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, - VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkQueryControlFlagBits; -typedef VkFlags VkQueryControlFlags; - -typedef enum VkCommandBufferResetFlagBits { - VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, - VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkCommandBufferResetFlagBits; -typedef VkFlags VkCommandBufferResetFlags; - typedef enum VkStencilFaceFlagBits { VK_STENCIL_FACE_FRONT_BIT = 0x00000001, VK_STENCIL_FACE_BACK_BIT = 0x00000002, VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003, - // VK_STENCIL_FRONT_AND_BACK is a deprecated alias + // VK_STENCIL_FRONT_AND_BACK is a legacy alias VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkStencilFaceFlagBits; @@ -3062,75 +3425,6 @@ typedef struct VkBaseOutStructure { struct VkBaseOutStructure* pNext; } VkBaseOutStructure; -typedef struct VkBufferMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkBuffer buffer; - VkDeviceSize offset; - VkDeviceSize size; -} VkBufferMemoryBarrier; - -typedef struct VkDispatchIndirectCommand { - uint32_t x; - uint32_t y; - uint32_t z; -} VkDispatchIndirectCommand; - -typedef struct VkDrawIndexedIndirectCommand { - uint32_t indexCount; - uint32_t instanceCount; - uint32_t firstIndex; - int32_t vertexOffset; - uint32_t firstInstance; -} VkDrawIndexedIndirectCommand; - -typedef struct VkDrawIndirectCommand { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; -} VkDrawIndirectCommand; - -typedef struct VkImageSubresourceRange { - VkImageAspectFlags aspectMask; - uint32_t baseMipLevel; - uint32_t levelCount; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceRange; - -typedef struct VkImageMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkImageLayout oldLayout; - VkImageLayout newLayout; - uint32_t srcQueueFamilyIndex; - uint32_t dstQueueFamilyIndex; - VkImage image; - VkImageSubresourceRange subresourceRange; -} VkImageMemoryBarrier; - -typedef struct VkMemoryBarrier { - VkStructureType sType; - const void* pNext; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; -} VkMemoryBarrier; - -typedef struct VkPipelineCacheHeaderVersionOne { - uint32_t headerSize; - VkPipelineCacheHeaderVersion headerVersion; - uint32_t vendorID; - uint32_t deviceID; - uint8_t pipelineCacheUUID[VK_UUID_SIZE]; -} VkPipelineCacheHeaderVersionOne; - typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( void* pUserData, size_t size, @@ -3431,9 +3725,9 @@ typedef struct VkDeviceCreateInfo { VkDeviceCreateFlags flags; uint32_t queueCreateInfoCount; const VkDeviceQueueCreateInfo* pQueueCreateInfos; - // enabledLayerCount is deprecated and should not be used + // enabledLayerCount is legacy and not used uint32_t enabledLayerCount; - // ppEnabledLayerNames is deprecated and should not be used + // ppEnabledLayerNames is legacy and not used const char* const* ppEnabledLayerNames; uint32_t enabledExtensionCount; const char* const* ppEnabledExtensionNames; @@ -3485,6 +3779,41 @@ typedef struct VkMemoryRequirements { uint32_t memoryTypeBits; } VkMemoryRequirements; +typedef struct VkImageSubresource { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t arrayLayer; +} VkImageSubresource; + +typedef struct VkSparseImageFormatProperties { + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; + VkSparseImageFormatFlags flags; +} VkSparseImageFormatProperties; + +typedef struct VkSparseImageMemoryBind { + VkImageSubresource subresource; + VkOffset3D offset; + VkExtent3D extent; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; + VkSparseMemoryBindFlags flags; +} VkSparseImageMemoryBind; + +typedef struct VkSparseImageMemoryBindInfo { + VkImage image; + uint32_t bindCount; + const VkSparseImageMemoryBind* pBinds; +} VkSparseImageMemoryBindInfo; + +typedef struct VkSparseImageMemoryRequirements { + VkSparseImageFormatProperties formatProperties; + uint32_t imageMipTailFirstLod; + VkDeviceSize imageMipTailSize; + VkDeviceSize imageMipTailOffset; + VkDeviceSize imageMipTailStride; +} VkSparseImageMemoryRequirements; + typedef struct VkSparseMemoryBind { VkDeviceSize resourceOffset; VkDeviceSize size; @@ -3505,27 +3834,6 @@ typedef struct VkSparseImageOpaqueMemoryBindInfo { const VkSparseMemoryBind* pBinds; } VkSparseImageOpaqueMemoryBindInfo; -typedef struct VkImageSubresource { - VkImageAspectFlags aspectMask; - uint32_t mipLevel; - uint32_t arrayLayer; -} VkImageSubresource; - -typedef struct VkSparseImageMemoryBind { - VkImageSubresource subresource; - VkOffset3D offset; - VkExtent3D extent; - VkDeviceMemory memory; - VkDeviceSize memoryOffset; - VkSparseMemoryBindFlags flags; -} VkSparseImageMemoryBind; - -typedef struct VkSparseImageMemoryBindInfo { - VkImage image; - uint32_t bindCount; - const VkSparseImageMemoryBind* pBinds; -} VkSparseImageMemoryBindInfo; - typedef struct VkBindSparseInfo { VkStructureType sType; const void* pNext; @@ -3541,20 +3849,6 @@ typedef struct VkBindSparseInfo { const VkSemaphore* pSignalSemaphores; } VkBindSparseInfo; -typedef struct VkSparseImageFormatProperties { - VkImageAspectFlags aspectMask; - VkExtent3D imageGranularity; - VkSparseImageFormatFlags flags; -} VkSparseImageFormatProperties; - -typedef struct VkSparseImageMemoryRequirements { - VkSparseImageFormatProperties formatProperties; - uint32_t imageMipTailFirstLod; - VkDeviceSize imageMipTailSize; - VkDeviceSize imageMipTailOffset; - VkDeviceSize imageMipTailStride; -} VkSparseImageMemoryRequirements; - typedef struct VkFenceCreateInfo { VkStructureType sType; const void* pNext; @@ -3567,12 +3861,6 @@ typedef struct VkSemaphoreCreateInfo { VkSemaphoreCreateFlags flags; } VkSemaphoreCreateInfo; -typedef struct VkEventCreateInfo { - VkStructureType sType; - const void* pNext; - VkEventCreateFlags flags; -} VkEventCreateInfo; - typedef struct VkQueryPoolCreateInfo { VkStructureType sType; const void* pNext; @@ -3593,16 +3881,6 @@ typedef struct VkBufferCreateInfo { const uint32_t* pQueueFamilyIndices; } VkBufferCreateInfo; -typedef struct VkBufferViewCreateInfo { - VkStructureType sType; - const void* pNext; - VkBufferViewCreateFlags flags; - VkBuffer buffer; - VkFormat format; - VkDeviceSize offset; - VkDeviceSize range; -} VkBufferViewCreateInfo; - typedef struct VkImageCreateInfo { VkStructureType sType; const void* pNext; @@ -3636,6 +3914,14 @@ typedef struct VkComponentMapping { VkComponentSwizzle a; } VkComponentMapping; +typedef struct VkImageSubresourceRange { + VkImageAspectFlags aspectMask; + uint32_t baseMipLevel; + uint32_t levelCount; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceRange; + typedef struct VkImageViewCreateInfo { VkStructureType sType; const void* pNext; @@ -3647,6 +3933,131 @@ typedef struct VkImageViewCreateInfo { VkImageSubresourceRange subresourceRange; } VkImageViewCreateInfo; +typedef struct VkCommandPoolCreateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPoolCreateFlags flags; + uint32_t queueFamilyIndex; +} VkCommandPoolCreateInfo; + +typedef struct VkCommandBufferAllocateInfo { + VkStructureType sType; + const void* pNext; + VkCommandPool commandPool; + VkCommandBufferLevel level; + uint32_t commandBufferCount; +} VkCommandBufferAllocateInfo; + +typedef struct VkCommandBufferInheritanceInfo { + VkStructureType sType; + const void* pNext; + VkRenderPass renderPass; + uint32_t subpass; + VkFramebuffer framebuffer; + VkBool32 occlusionQueryEnable; + VkQueryControlFlags queryFlags; + VkQueryPipelineStatisticFlags pipelineStatistics; +} VkCommandBufferInheritanceInfo; + +typedef struct VkCommandBufferBeginInfo { + VkStructureType sType; + const void* pNext; + VkCommandBufferUsageFlags flags; + const VkCommandBufferInheritanceInfo* pInheritanceInfo; +} VkCommandBufferBeginInfo; + +typedef struct VkBufferCopy { + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy; + +typedef struct VkImageSubresourceLayers { + VkImageAspectFlags aspectMask; + uint32_t mipLevel; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkImageSubresourceLayers; + +typedef struct VkBufferImageCopy { + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy; + +typedef struct VkImageCopy { + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy; + +typedef struct VkBufferMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier; + +typedef struct VkImageMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier; + +typedef struct VkMemoryBarrier { + VkStructureType sType; + const void* pNext; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; +} VkMemoryBarrier; + +typedef struct VkDispatchIndirectCommand { + uint32_t x; + uint32_t y; + uint32_t z; +} VkDispatchIndirectCommand; + +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; +} VkPipelineCacheHeaderVersionOne; + +typedef struct VkEventCreateInfo { + VkStructureType sType; + const void* pNext; + VkEventCreateFlags flags; +} VkEventCreateInfo; + +typedef struct VkBufferViewCreateInfo { + VkStructureType sType; + const void* pNext; + VkBufferViewCreateFlags flags; + VkBuffer buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +} VkBufferViewCreateInfo; + typedef struct VkShaderModuleCreateInfo { VkStructureType sType; const void* pNext; @@ -3696,168 +4107,6 @@ typedef struct VkComputePipelineCreateInfo { int32_t basePipelineIndex; } VkComputePipelineCreateInfo; -typedef struct VkVertexInputBindingDescription { - uint32_t binding; - uint32_t stride; - VkVertexInputRate inputRate; -} VkVertexInputBindingDescription; - -typedef struct VkVertexInputAttributeDescription { - uint32_t location; - uint32_t binding; - VkFormat format; - uint32_t offset; -} VkVertexInputAttributeDescription; - -typedef struct VkPipelineVertexInputStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineVertexInputStateCreateFlags flags; - uint32_t vertexBindingDescriptionCount; - const VkVertexInputBindingDescription* pVertexBindingDescriptions; - uint32_t vertexAttributeDescriptionCount; - const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; -} VkPipelineVertexInputStateCreateInfo; - -typedef struct VkPipelineInputAssemblyStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineInputAssemblyStateCreateFlags flags; - VkPrimitiveTopology topology; - VkBool32 primitiveRestartEnable; -} VkPipelineInputAssemblyStateCreateInfo; - -typedef struct VkPipelineTessellationStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineTessellationStateCreateFlags flags; - uint32_t patchControlPoints; -} VkPipelineTessellationStateCreateInfo; - -typedef struct VkViewport { - float x; - float y; - float width; - float height; - float minDepth; - float maxDepth; -} VkViewport; - -typedef struct VkPipelineViewportStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineViewportStateCreateFlags flags; - uint32_t viewportCount; - const VkViewport* pViewports; - uint32_t scissorCount; - const VkRect2D* pScissors; -} VkPipelineViewportStateCreateInfo; - -typedef struct VkPipelineRasterizationStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineRasterizationStateCreateFlags flags; - VkBool32 depthClampEnable; - VkBool32 rasterizerDiscardEnable; - VkPolygonMode polygonMode; - VkCullModeFlags cullMode; - VkFrontFace frontFace; - VkBool32 depthBiasEnable; - float depthBiasConstantFactor; - float depthBiasClamp; - float depthBiasSlopeFactor; - float lineWidth; -} VkPipelineRasterizationStateCreateInfo; - -typedef struct VkPipelineMultisampleStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineMultisampleStateCreateFlags flags; - VkSampleCountFlagBits rasterizationSamples; - VkBool32 sampleShadingEnable; - float minSampleShading; - const VkSampleMask* pSampleMask; - VkBool32 alphaToCoverageEnable; - VkBool32 alphaToOneEnable; -} VkPipelineMultisampleStateCreateInfo; - -typedef struct VkStencilOpState { - VkStencilOp failOp; - VkStencilOp passOp; - VkStencilOp depthFailOp; - VkCompareOp compareOp; - uint32_t compareMask; - uint32_t writeMask; - uint32_t reference; -} VkStencilOpState; - -typedef struct VkPipelineDepthStencilStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineDepthStencilStateCreateFlags flags; - VkBool32 depthTestEnable; - VkBool32 depthWriteEnable; - VkCompareOp depthCompareOp; - VkBool32 depthBoundsTestEnable; - VkBool32 stencilTestEnable; - VkStencilOpState front; - VkStencilOpState back; - float minDepthBounds; - float maxDepthBounds; -} VkPipelineDepthStencilStateCreateInfo; - -typedef struct VkPipelineColorBlendAttachmentState { - VkBool32 blendEnable; - VkBlendFactor srcColorBlendFactor; - VkBlendFactor dstColorBlendFactor; - VkBlendOp colorBlendOp; - VkBlendFactor srcAlphaBlendFactor; - VkBlendFactor dstAlphaBlendFactor; - VkBlendOp alphaBlendOp; - VkColorComponentFlags colorWriteMask; -} VkPipelineColorBlendAttachmentState; - -typedef struct VkPipelineColorBlendStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineColorBlendStateCreateFlags flags; - VkBool32 logicOpEnable; - VkLogicOp logicOp; - uint32_t attachmentCount; - const VkPipelineColorBlendAttachmentState* pAttachments; - float blendConstants[4]; -} VkPipelineColorBlendStateCreateInfo; - -typedef struct VkPipelineDynamicStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineDynamicStateCreateFlags flags; - uint32_t dynamicStateCount; - const VkDynamicState* pDynamicStates; -} VkPipelineDynamicStateCreateInfo; - -typedef struct VkGraphicsPipelineCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags flags; - uint32_t stageCount; - const VkPipelineShaderStageCreateInfo* pStages; - const VkPipelineVertexInputStateCreateInfo* pVertexInputState; - const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; - const VkPipelineTessellationStateCreateInfo* pTessellationState; - const VkPipelineViewportStateCreateInfo* pViewportState; - const VkPipelineRasterizationStateCreateInfo* pRasterizationState; - const VkPipelineMultisampleStateCreateInfo* pMultisampleState; - const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; - const VkPipelineColorBlendStateCreateInfo* pColorBlendState; - const VkPipelineDynamicStateCreateInfo* pDynamicState; - VkPipelineLayout layout; - VkRenderPass renderPass; - uint32_t subpass; - VkPipeline basePipelineHandle; - int32_t basePipelineIndex; -} VkGraphicsPipelineCreateInfo; - typedef struct VkPushConstantRange { VkShaderStageFlags stageFlags; uint32_t offset; @@ -3970,6 +4219,189 @@ typedef struct VkWriteDescriptorSet { const VkBufferView* pTexelBufferView; } VkWriteDescriptorSet; +typedef union VkClearColorValue { + float float32[4]; + int32_t int32[4]; + uint32_t uint32[4]; +} VkClearColorValue; + +typedef struct VkDrawIndexedIndirectCommand { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; +} VkDrawIndexedIndirectCommand; + +typedef struct VkDrawIndirectCommand { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; +} VkDrawIndirectCommand; + +typedef struct VkStencilOpState { + VkStencilOp failOp; + VkStencilOp passOp; + VkStencilOp depthFailOp; + VkCompareOp compareOp; + uint32_t compareMask; + uint32_t writeMask; + uint32_t reference; +} VkStencilOpState; + +typedef struct VkVertexInputAttributeDescription { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; +} VkVertexInputAttributeDescription; + +typedef struct VkVertexInputBindingDescription { + uint32_t binding; + uint32_t stride; + VkVertexInputRate inputRate; +} VkVertexInputBindingDescription; + +typedef struct VkViewport { + float x; + float y; + float width; + float height; + float minDepth; + float maxDepth; +} VkViewport; + +typedef struct VkPipelineColorBlendAttachmentState { + VkBool32 blendEnable; + VkBlendFactor srcColorBlendFactor; + VkBlendFactor dstColorBlendFactor; + VkBlendOp colorBlendOp; + VkBlendFactor srcAlphaBlendFactor; + VkBlendFactor dstAlphaBlendFactor; + VkBlendOp alphaBlendOp; + VkColorComponentFlags colorWriteMask; +} VkPipelineColorBlendAttachmentState; + +typedef struct VkPipelineColorBlendStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineColorBlendStateCreateFlags flags; + VkBool32 logicOpEnable; + VkLogicOp logicOp; + uint32_t attachmentCount; + const VkPipelineColorBlendAttachmentState* pAttachments; + float blendConstants[4]; +} VkPipelineColorBlendStateCreateInfo; + +typedef struct VkPipelineDepthStencilStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDepthStencilStateCreateFlags flags; + VkBool32 depthTestEnable; + VkBool32 depthWriteEnable; + VkCompareOp depthCompareOp; + VkBool32 depthBoundsTestEnable; + VkBool32 stencilTestEnable; + VkStencilOpState front; + VkStencilOpState back; + float minDepthBounds; + float maxDepthBounds; +} VkPipelineDepthStencilStateCreateInfo; + +typedef struct VkPipelineDynamicStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineDynamicStateCreateFlags flags; + uint32_t dynamicStateCount; + const VkDynamicState* pDynamicStates; +} VkPipelineDynamicStateCreateInfo; + +typedef struct VkPipelineInputAssemblyStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineInputAssemblyStateCreateFlags flags; + VkPrimitiveTopology topology; + VkBool32 primitiveRestartEnable; +} VkPipelineInputAssemblyStateCreateInfo; + +typedef struct VkPipelineMultisampleStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineMultisampleStateCreateFlags flags; + VkSampleCountFlagBits rasterizationSamples; + VkBool32 sampleShadingEnable; + float minSampleShading; + const VkSampleMask* pSampleMask; + VkBool32 alphaToCoverageEnable; + VkBool32 alphaToOneEnable; +} VkPipelineMultisampleStateCreateInfo; + +typedef struct VkPipelineRasterizationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRasterizationStateCreateFlags flags; + VkBool32 depthClampEnable; + VkBool32 rasterizerDiscardEnable; + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthBiasEnable; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; +} VkPipelineRasterizationStateCreateInfo; + +typedef struct VkPipelineTessellationStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineTessellationStateCreateFlags flags; + uint32_t patchControlPoints; +} VkPipelineTessellationStateCreateInfo; + +typedef struct VkPipelineVertexInputStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineVertexInputStateCreateFlags flags; + uint32_t vertexBindingDescriptionCount; + const VkVertexInputBindingDescription* pVertexBindingDescriptions; + uint32_t vertexAttributeDescriptionCount; + const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; +} VkPipelineVertexInputStateCreateInfo; + +typedef struct VkPipelineViewportStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineViewportStateCreateFlags flags; + uint32_t viewportCount; + const VkViewport* pViewports; + uint32_t scissorCount; + const VkRect2D* pScissors; +} VkPipelineViewportStateCreateInfo; + +typedef struct VkGraphicsPipelineCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + const VkPipelineTessellationStateCreateInfo* pTessellationState; + const VkPipelineViewportStateCreateInfo* pViewportState; + const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + const VkPipelineDynamicStateCreateInfo* pDynamicState; + VkPipelineLayout layout; + VkRenderPass renderPass; + uint32_t subpass; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkGraphicsPipelineCreateInfo; + typedef struct VkAttachmentDescription { VkAttachmentDescriptionFlags flags; VkFormat format; @@ -3999,6 +4431,16 @@ typedef struct VkFramebufferCreateInfo { uint32_t layers; } VkFramebufferCreateInfo; +typedef struct VkSubpassDependency { + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; +} VkSubpassDependency; + typedef struct VkSubpassDescription { VkSubpassDescriptionFlags flags; VkPipelineBindPoint pipelineBindPoint; @@ -4012,16 +4454,6 @@ typedef struct VkSubpassDescription { const uint32_t* pPreserveAttachments; } VkSubpassDescription; -typedef struct VkSubpassDependency { - uint32_t srcSubpass; - uint32_t dstSubpass; - VkPipelineStageFlags srcStageMask; - VkPipelineStageFlags dstStageMask; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkDependencyFlags dependencyFlags; -} VkSubpassDependency; - typedef struct VkRenderPassCreateInfo { VkStructureType sType; const void* pNext; @@ -4034,72 +4466,17 @@ typedef struct VkRenderPassCreateInfo { const VkSubpassDependency* pDependencies; } VkRenderPassCreateInfo; -typedef struct VkCommandPoolCreateInfo { - VkStructureType sType; - const void* pNext; - VkCommandPoolCreateFlags flags; - uint32_t queueFamilyIndex; -} VkCommandPoolCreateInfo; - -typedef struct VkCommandBufferAllocateInfo { - VkStructureType sType; - const void* pNext; - VkCommandPool commandPool; - VkCommandBufferLevel level; - uint32_t commandBufferCount; -} VkCommandBufferAllocateInfo; - -typedef struct VkCommandBufferInheritanceInfo { - VkStructureType sType; - const void* pNext; - VkRenderPass renderPass; - uint32_t subpass; - VkFramebuffer framebuffer; - VkBool32 occlusionQueryEnable; - VkQueryControlFlags queryFlags; - VkQueryPipelineStatisticFlags pipelineStatistics; -} VkCommandBufferInheritanceInfo; - -typedef struct VkCommandBufferBeginInfo { - VkStructureType sType; - const void* pNext; - VkCommandBufferUsageFlags flags; - const VkCommandBufferInheritanceInfo* pInheritanceInfo; -} VkCommandBufferBeginInfo; - -typedef struct VkBufferCopy { - VkDeviceSize srcOffset; - VkDeviceSize dstOffset; - VkDeviceSize size; -} VkBufferCopy; - -typedef struct VkImageSubresourceLayers { - VkImageAspectFlags aspectMask; - uint32_t mipLevel; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkImageSubresourceLayers; - -typedef struct VkBufferImageCopy { - VkDeviceSize bufferOffset; - uint32_t bufferRowLength; - uint32_t bufferImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkBufferImageCopy; - -typedef union VkClearColorValue { - float float32[4]; - int32_t int32[4]; - uint32_t uint32[4]; -} VkClearColorValue; - typedef struct VkClearDepthStencilValue { float depth; uint32_t stencil; } VkClearDepthStencilValue; +typedef struct VkClearRect { + VkRect2D rect; + uint32_t baseArrayLayer; + uint32_t layerCount; +} VkClearRect; + typedef union VkClearValue { VkClearColorValue color; VkClearDepthStencilValue depthStencil; @@ -4111,12 +4488,6 @@ typedef struct VkClearAttachment { VkClearValue clearValue; } VkClearAttachment; -typedef struct VkClearRect { - VkRect2D rect; - uint32_t baseArrayLayer; - uint32_t layerCount; -} VkClearRect; - typedef struct VkImageBlit { VkImageSubresourceLayers srcSubresource; VkOffset3D srcOffsets[2]; @@ -4124,14 +4495,6 @@ typedef struct VkImageBlit { VkOffset3D dstOffsets[2]; } VkImageBlit; -typedef struct VkImageCopy { - VkImageSubresourceLayers srcSubresource; - VkOffset3D srcOffset; - VkImageSubresourceLayers dstSubresource; - VkOffset3D dstOffset; - VkExtent3D extent; -} VkImageCopy; - typedef struct VkImageResolve { VkImageSubresourceLayers srcSubresource; VkOffset3D srcOffset; @@ -4192,30 +4555,50 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fenc typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout); typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore); typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); -typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); -typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); -typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool); typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags); typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer); typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); -typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage); typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout); typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView); typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); +typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); +typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); +typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); +typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); +typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); +typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); +typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent); +typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); +typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule); typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache); typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData); typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); -typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout); @@ -4230,20 +4613,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescr typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets); typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets); typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); +typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); +typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); +typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); +typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer); typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator); typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity); -typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool); -typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); -typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers); -typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); -typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo); -typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer); -typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports); typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors); typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); @@ -4253,40 +4637,19 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); -typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets); typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets); typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions); typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter); -typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); -typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges); typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects); typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions); -typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); -typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers); -typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); -typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); -typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); -typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); -typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues); typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); -typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( @@ -4510,29 +4873,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore( VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( - VkDevice device, - const VkEventCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkEvent* pEvent); - -VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( - VkDevice device, - VkEvent event, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( - VkDevice device, - VkEvent event); - -VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( - VkDevice device, - VkEvent event); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( - VkDevice device, - VkEvent event); - VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool( VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, @@ -4565,17 +4905,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer( VkBuffer buffer, const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( - VkDevice device, - const VkBufferViewCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkBufferView* pView); - -VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( - VkDevice device, - VkBufferView bufferView, - const VkAllocationCallbacks* pAllocator); - VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage( VkDevice device, const VkImageCreateInfo* pCreateInfo, @@ -4604,6 +4933,174 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyImageView( VkImageView imageView, const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool); + +VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( + VkDevice device, + VkCommandPool commandPool, + VkCommandPoolResetFlags flags); + +VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo); + +VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( + VkCommandBuffer commandBuffer); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( + VkCommandBuffer commandBuffer, + VkCommandBufferResetFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( + VkCommandBuffer commandBuffer, + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkBuffer dstBuffer, + uint32_t regionCount, + const VkBufferImageCopy* pRegions); + +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize dataSize, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( + VkCommandBuffer commandBuffer, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize size, + uint32_t data); + +VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query, + VkQueryControlFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( + VkCommandBuffer commandBuffer, + VkPipelineStageFlagBits pipelineStage, + VkQueryPool queryPool, + uint32_t query); + +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + VkBuffer dstBuffer, + VkDeviceSize dstOffset, + VkDeviceSize stride, + VkQueryResultFlags flags); + +VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( + VkCommandBuffer commandBuffer, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent( + VkDevice device, + const VkEventCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkEvent* pEvent); + +VKAPI_ATTR void VKAPI_CALL vkDestroyEvent( + VkDevice device, + VkEvent event, + const VkAllocationCallbacks* pAllocator); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent( + VkDevice device, + VkEvent event); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView( + VkDevice device, + const VkBufferViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBufferView* pView); + +VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView( + VkDevice device, + VkBufferView bufferView, + const VkAllocationCallbacks* pAllocator); + VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule( VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, @@ -4638,14 +5135,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches( uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( - VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkGraphicsPipelineCreateInfo* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines); - VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines( VkDevice device, VkPipelineCache pipelineCache, @@ -4726,6 +5215,79 @@ VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets( uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies); +VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipeline pipeline); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t firstSet, + uint32_t descriptorSetCount, + const VkDescriptorSet* pDescriptorSets, + uint32_t dynamicOffsetCount, + const uint32_t* pDynamicOffsets); + +VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( + VkCommandBuffer commandBuffer, + VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue* pColor, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( + VkCommandBuffer commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( + VkCommandBuffer commandBuffer, + VkPipelineLayout layout, + VkShaderStageFlags stageFlags, + uint32_t offset, + uint32_t size, + const void* pValues); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkGraphicsPipelineCreateInfo* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); + VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer( VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, @@ -4753,49 +5315,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity( VkRenderPass renderPass, VkExtent2D* pGranularity); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool( - VkDevice device, - const VkCommandPoolCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCommandPool* pCommandPool); - -VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool( - VkDevice device, - VkCommandPool commandPool, - const VkAllocationCallbacks* pAllocator); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool( - VkDevice device, - VkCommandPool commandPool, - VkCommandPoolResetFlags flags); - -VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers( - VkDevice device, - const VkCommandBufferAllocateInfo* pAllocateInfo, - VkCommandBuffer* pCommandBuffers); - -VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers( - VkDevice device, - VkCommandPool commandPool, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers); - -VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer( - VkCommandBuffer commandBuffer, - const VkCommandBufferBeginInfo* pBeginInfo); - -VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer( - VkCommandBuffer commandBuffer); - -VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer( - VkCommandBuffer commandBuffer, - VkCommandBufferResetFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipeline pipeline); - VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport( VkCommandBuffer commandBuffer, uint32_t firstViewport, @@ -4842,16 +5361,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference( VkStencilFaceFlags faceMask, uint32_t reference); -VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipelineLayout layout, - uint32_t firstSet, - uint32_t descriptorSetCount, - const VkDescriptorSet* pDescriptorSets, - uint32_t dynamicOffsetCount, - const uint32_t* pDynamicOffsets); - VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -4894,33 +5403,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect( uint32_t drawCount, uint32_t stride); -VKAPI_ATTR void VKAPI_CALL vkCmdDispatch( - VkCommandBuffer commandBuffer, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ); - -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkBuffer dstBuffer, - uint32_t regionCount, - const VkBufferCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkImageCopy* pRegions); - VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( VkCommandBuffer commandBuffer, VkImage srcImage, @@ -4931,44 +5413,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage( const VkImageBlit* pRegions, VkFilter filter); -VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage( - VkCommandBuffer commandBuffer, - VkBuffer srcBuffer, - VkImage dstImage, - VkImageLayout dstImageLayout, - uint32_t regionCount, - const VkBufferImageCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer( - VkCommandBuffer commandBuffer, - VkImage srcImage, - VkImageLayout srcImageLayout, - VkBuffer dstBuffer, - uint32_t regionCount, - const VkBufferImageCopy* pRegions); - -VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer( - VkCommandBuffer commandBuffer, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize dataSize, - const void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer( - VkCommandBuffer commandBuffer, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize size, - uint32_t data); - -VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( - VkCommandBuffer commandBuffer, - VkImage image, - VkImageLayout imageLayout, - const VkClearColorValue* pColor, - uint32_t rangeCount, - const VkImageSubresourceRange* pRanges); - VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage( VkCommandBuffer commandBuffer, VkImage image, @@ -4993,82 +5437,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage( uint32_t regionCount, const VkImageResolve* pRegions); -VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags stageMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags stageMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents( - VkCommandBuffer commandBuffer, - uint32_t eventCount, - const VkEvent* pEvents, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - uint32_t memoryBarrierCount, - const VkMemoryBarrier* pMemoryBarriers, - uint32_t bufferMemoryBarrierCount, - const VkBufferMemoryBarrier* pBufferMemoryBarriers, - uint32_t imageMemoryBarrierCount, - const VkImageMemoryBarrier* pImageMemoryBarriers); - -VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier( - VkCommandBuffer commandBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - uint32_t memoryBarrierCount, - const VkMemoryBarrier* pMemoryBarriers, - uint32_t bufferMemoryBarrierCount, - const VkBufferMemoryBarrier* pBufferMemoryBarriers, - uint32_t imageMemoryBarrierCount, - const VkImageMemoryBarrier* pImageMemoryBarriers); - -VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query, - VkQueryControlFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t query); - -VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount); - -VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp( - VkCommandBuffer commandBuffer, - VkPipelineStageFlagBits pipelineStage, - VkQueryPool queryPool, - uint32_t query); - -VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults( - VkCommandBuffer commandBuffer, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount, - VkBuffer dstBuffer, - VkDeviceSize dstOffset, - VkDeviceSize stride, - VkQueryResultFlags flags); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants( - VkCommandBuffer commandBuffer, - VkPipelineLayout layout, - VkShaderStageFlags stageFlags, - uint32_t offset, - uint32_t size, - const void* pValues); - VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass( VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, @@ -5080,11 +5448,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass( VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass( VkCommandBuffer commandBuffer); - -VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( - VkCommandBuffer commandBuffer, - uint32_t commandBufferCount, - const VkCommandBuffer* pCommandBuffers); #endif @@ -5093,8 +5456,8 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( // Vulkan 1.1 version number #define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)// Patch version should always be set to 0 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) #define VK_MAX_DEVICE_GROUP_SIZE 32U #define VK_LUID_SIZE 8U #define VK_QUEUE_FAMILY_EXTERNAL (~1U) @@ -5107,13 +5470,13 @@ typedef enum VkPointClippingBehavior { VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF } VkPointClippingBehavior; -typedef enum VkTessellationDomainOrigin { - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, - VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, - VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF -} VkTessellationDomainOrigin; +typedef enum VkDescriptorUpdateTemplateType { + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS = 1, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorUpdateTemplateType; typedef enum VkSamplerYcbcrModelConversion { VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, @@ -5145,13 +5508,13 @@ typedef enum VkChromaLocation { VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF } VkChromaLocation; -typedef enum VkDescriptorUpdateTemplateType { - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS = 1, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkDescriptorUpdateTemplateType; +typedef enum VkTessellationDomainOrigin { + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, + VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT, + VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF +} VkTessellationDomainOrigin; typedef enum VkSubgroupFeatureFlagBits { VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001, @@ -5164,7 +5527,8 @@ typedef enum VkSubgroupFeatureFlagBits { VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080, VK_SUBGROUP_FEATURE_ROTATE_BIT = 0x00000200, VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT = 0x00000400, - VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = 0x00000100, + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_EXT = 0x00000100, + VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV = VK_SUBGROUP_FEATURE_PARTITIONED_BIT_EXT, VK_SUBGROUP_FEATURE_ROTATE_BIT_KHR = VK_SUBGROUP_FEATURE_ROTATE_BIT, VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT_KHR = VK_SUBGROUP_FEATURE_ROTATE_CLUSTERED_BIT, VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF @@ -5188,6 +5552,7 @@ typedef enum VkMemoryAllocateFlagBits { VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004, + VK_MEMORY_ALLOCATE_ZERO_INITIALIZE_BIT_EXT = 0x00000008, VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, @@ -5195,7 +5560,6 @@ typedef enum VkMemoryAllocateFlagBits { } VkMemoryAllocateFlagBits; typedef VkFlags VkMemoryAllocateFlags; typedef VkFlags VkCommandPoolTrimFlags; -typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001, @@ -5211,6 +5575,7 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT = 0x00000100, VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA = 0x00000800, VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV = 0x00001000, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OH_NATIVE_BUFFER_BIT_OHOS = 0x00008000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX = 0x00004000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT = 0x00010000, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT = 0x00020000, @@ -5298,15 +5663,7 @@ typedef enum VkExternalSemaphoreFeatureFlagBits { VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalSemaphoreFeatureFlagBits; typedef VkFlags VkExternalSemaphoreFeatureFlags; -typedef struct VkPhysicalDeviceSubgroupProperties { - VkStructureType sType; - void* pNext; - uint32_t subgroupSize; - VkShaderStageFlags supportedStages; - VkSubgroupFeatureFlags supportedOperations; - VkBool32 quadOperationsInAllStages; -} VkPhysicalDeviceSubgroupProperties; - +typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; typedef struct VkBindBufferMemoryInfo { VkStructureType sType; const void* pNext; @@ -5323,15 +5680,6 @@ typedef struct VkBindImageMemoryInfo { VkDeviceSize memoryOffset; } VkBindImageMemoryInfo; -typedef struct VkPhysicalDevice16BitStorageFeatures { - VkStructureType sType; - void* pNext; - VkBool32 storageBuffer16BitAccess; - VkBool32 uniformAndStorageBuffer16BitAccess; - VkBool32 storagePushConstant16; - VkBool32 storageInputOutput16; -} VkPhysicalDevice16BitStorageFeatures; - typedef struct VkMemoryDedicatedRequirements { VkStructureType sType; void* pNext; @@ -5353,14 +5701,6 @@ typedef struct VkMemoryAllocateFlagsInfo { uint32_t deviceMask; } VkMemoryAllocateFlagsInfo; -typedef struct VkDeviceGroupRenderPassBeginInfo { - VkStructureType sType; - const void* pNext; - uint32_t deviceMask; - uint32_t deviceRenderAreaCount; - const VkRect2D* pDeviceRenderAreas; -} VkDeviceGroupRenderPassBeginInfo; - typedef struct VkDeviceGroupCommandBufferBeginInfo { VkStructureType sType; const void* pNext; @@ -5508,72 +5848,12 @@ typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { VkImageTiling tiling; } VkPhysicalDeviceSparseImageFormatInfo2; -typedef struct VkPhysicalDevicePointClippingProperties { - VkStructureType sType; - void* pNext; - VkPointClippingBehavior pointClippingBehavior; -} VkPhysicalDevicePointClippingProperties; - -typedef struct VkInputAttachmentAspectReference { - uint32_t subpass; - uint32_t inputAttachmentIndex; - VkImageAspectFlags aspectMask; -} VkInputAttachmentAspectReference; - -typedef struct VkRenderPassInputAttachmentAspectCreateInfo { - VkStructureType sType; - const void* pNext; - uint32_t aspectReferenceCount; - const VkInputAttachmentAspectReference* pAspectReferences; -} VkRenderPassInputAttachmentAspectCreateInfo; - typedef struct VkImageViewUsageCreateInfo { VkStructureType sType; const void* pNext; VkImageUsageFlags usage; } VkImageViewUsageCreateInfo; -typedef struct VkPipelineTessellationDomainOriginStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkTessellationDomainOrigin domainOrigin; -} VkPipelineTessellationDomainOriginStateCreateInfo; - -typedef struct VkRenderPassMultiviewCreateInfo { - VkStructureType sType; - const void* pNext; - uint32_t subpassCount; - const uint32_t* pViewMasks; - uint32_t dependencyCount; - const int32_t* pViewOffsets; - uint32_t correlationMaskCount; - const uint32_t* pCorrelationMasks; -} VkRenderPassMultiviewCreateInfo; - -typedef struct VkPhysicalDeviceMultiviewFeatures { - VkStructureType sType; - void* pNext; - VkBool32 multiview; - VkBool32 multiviewGeometryShader; - VkBool32 multiviewTessellationShader; -} VkPhysicalDeviceMultiviewFeatures; - -typedef struct VkPhysicalDeviceMultiviewProperties { - VkStructureType sType; - void* pNext; - uint32_t maxMultiviewViewCount; - uint32_t maxMultiviewInstanceIndex; -} VkPhysicalDeviceMultiviewProperties; - -typedef struct VkPhysicalDeviceVariablePointersFeatures { - VkStructureType sType; - void* pNext; - VkBool32 variablePointersStorageBuffer; - VkBool32 variablePointers; -} VkPhysicalDeviceVariablePointersFeatures; - -typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures; - typedef struct VkPhysicalDeviceProtectedMemoryFeatures { VkStructureType sType; void* pNext; @@ -5600,25 +5880,6 @@ typedef struct VkProtectedSubmitInfo { VkBool32 protectedSubmit; } VkProtectedSubmitInfo; -typedef struct VkSamplerYcbcrConversionCreateInfo { - VkStructureType sType; - const void* pNext; - VkFormat format; - VkSamplerYcbcrModelConversion ycbcrModel; - VkSamplerYcbcrRange ycbcrRange; - VkComponentMapping components; - VkChromaLocation xChromaOffset; - VkChromaLocation yChromaOffset; - VkFilter chromaFilter; - VkBool32 forceExplicitReconstruction; -} VkSamplerYcbcrConversionCreateInfo; - -typedef struct VkSamplerYcbcrConversionInfo { - VkStructureType sType; - const void* pNext; - VkSamplerYcbcrConversion conversion; -} VkSamplerYcbcrConversionInfo; - typedef struct VkBindImagePlaneMemoryInfo { VkStructureType sType; const void* pNext; @@ -5631,40 +5892,6 @@ typedef struct VkImagePlaneMemoryRequirementsInfo { VkImageAspectFlagBits planeAspect; } VkImagePlaneMemoryRequirementsInfo; -typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures { - VkStructureType sType; - void* pNext; - VkBool32 samplerYcbcrConversion; -} VkPhysicalDeviceSamplerYcbcrConversionFeatures; - -typedef struct VkSamplerYcbcrConversionImageFormatProperties { - VkStructureType sType; - void* pNext; - uint32_t combinedImageSamplerDescriptorCount; -} VkSamplerYcbcrConversionImageFormatProperties; - -typedef struct VkDescriptorUpdateTemplateEntry { - uint32_t dstBinding; - uint32_t dstArrayElement; - uint32_t descriptorCount; - VkDescriptorType descriptorType; - size_t offset; - size_t stride; -} VkDescriptorUpdateTemplateEntry; - -typedef struct VkDescriptorUpdateTemplateCreateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorUpdateTemplateCreateFlags flags; - uint32_t descriptorUpdateEntryCount; - const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; - VkDescriptorUpdateTemplateType templateType; - VkDescriptorSetLayout descriptorSetLayout; - VkPipelineBindPoint pipelineBindPoint; - VkPipelineLayout pipelineLayout; - uint32_t set; -} VkDescriptorUpdateTemplateCreateInfo; - typedef struct VkExternalMemoryProperties { VkExternalMemoryFeatureFlags externalMemoryFeatures; VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes; @@ -5765,6 +5992,55 @@ typedef struct VkExternalSemaphoreProperties { VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures; } VkExternalSemaphoreProperties; +typedef struct VkPhysicalDeviceSubgroupProperties { + VkStructureType sType; + void* pNext; + uint32_t subgroupSize; + VkShaderStageFlags supportedStages; + VkSubgroupFeatureFlags supportedOperations; + VkBool32 quadOperationsInAllStages; +} VkPhysicalDeviceSubgroupProperties; + +typedef struct VkPhysicalDevice16BitStorageFeatures { + VkStructureType sType; + void* pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; +} VkPhysicalDevice16BitStorageFeatures; + +typedef struct VkPhysicalDeviceVariablePointersFeatures { + VkStructureType sType; + void* pNext; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; +} VkPhysicalDeviceVariablePointersFeatures; + +typedef VkPhysicalDeviceVariablePointersFeatures VkPhysicalDeviceVariablePointerFeatures; + +typedef struct VkDescriptorUpdateTemplateEntry { + uint32_t dstBinding; + uint32_t dstArrayElement; + uint32_t descriptorCount; + VkDescriptorType descriptorType; + size_t offset; + size_t stride; +} VkDescriptorUpdateTemplateEntry; + +typedef struct VkDescriptorUpdateTemplateCreateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorUpdateTemplateCreateFlags flags; + uint32_t descriptorUpdateEntryCount; + const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries; + VkDescriptorUpdateTemplateType templateType; + VkDescriptorSetLayout descriptorSetLayout; + VkPipelineBindPoint pipelineBindPoint; + VkPipelineLayout pipelineLayout; + uint32_t set; +} VkDescriptorUpdateTemplateCreateInfo; + typedef struct VkPhysicalDeviceMaintenance3Properties { VkStructureType sType; void* pNext; @@ -5778,6 +6054,96 @@ typedef struct VkDescriptorSetLayoutSupport { VkBool32 supported; } VkDescriptorSetLayoutSupport; +typedef struct VkSamplerYcbcrConversionCreateInfo { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkSamplerYcbcrModelConversion ycbcrModel; + VkSamplerYcbcrRange ycbcrRange; + VkComponentMapping components; + VkChromaLocation xChromaOffset; + VkChromaLocation yChromaOffset; + VkFilter chromaFilter; + VkBool32 forceExplicitReconstruction; +} VkSamplerYcbcrConversionCreateInfo; + +typedef struct VkSamplerYcbcrConversionInfo { + VkStructureType sType; + const void* pNext; + VkSamplerYcbcrConversion conversion; +} VkSamplerYcbcrConversionInfo; + +typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures { + VkStructureType sType; + void* pNext; + VkBool32 samplerYcbcrConversion; +} VkPhysicalDeviceSamplerYcbcrConversionFeatures; + +typedef struct VkSamplerYcbcrConversionImageFormatProperties { + VkStructureType sType; + void* pNext; + uint32_t combinedImageSamplerDescriptorCount; +} VkSamplerYcbcrConversionImageFormatProperties; + +typedef struct VkDeviceGroupRenderPassBeginInfo { + VkStructureType sType; + const void* pNext; + uint32_t deviceMask; + uint32_t deviceRenderAreaCount; + const VkRect2D* pDeviceRenderAreas; +} VkDeviceGroupRenderPassBeginInfo; + +typedef struct VkPhysicalDevicePointClippingProperties { + VkStructureType sType; + void* pNext; + VkPointClippingBehavior pointClippingBehavior; +} VkPhysicalDevicePointClippingProperties; + +typedef struct VkInputAttachmentAspectReference { + uint32_t subpass; + uint32_t inputAttachmentIndex; + VkImageAspectFlags aspectMask; +} VkInputAttachmentAspectReference; + +typedef struct VkRenderPassInputAttachmentAspectCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t aspectReferenceCount; + const VkInputAttachmentAspectReference* pAspectReferences; +} VkRenderPassInputAttachmentAspectCreateInfo; + +typedef struct VkPipelineTessellationDomainOriginStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkTessellationDomainOrigin domainOrigin; +} VkPipelineTessellationDomainOriginStateCreateInfo; + +typedef struct VkRenderPassMultiviewCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t subpassCount; + const uint32_t* pViewMasks; + uint32_t dependencyCount; + const int32_t* pViewOffsets; + uint32_t correlationMaskCount; + const uint32_t* pCorrelationMasks; +} VkRenderPassMultiviewCreateInfo; + +typedef struct VkPhysicalDeviceMultiviewFeatures { + VkStructureType sType; + void* pNext; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; +} VkPhysicalDeviceMultiviewFeatures; + +typedef struct VkPhysicalDeviceMultiviewProperties { + VkStructureType sType; + void* pNext; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; +} VkPhysicalDeviceMultiviewProperties; + typedef struct VkPhysicalDeviceShaderDrawParametersFeatures { VkStructureType sType; void* pNext; @@ -5791,7 +6157,6 @@ typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask); -typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); @@ -5805,15 +6170,16 @@ typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDev typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue); -typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); -typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); -typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); -typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); +typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion( @@ -5840,15 +6206,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask( VkCommandBuffer commandBuffer, uint32_t deviceMask); -VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase( - VkCommandBuffer commandBuffer, - uint32_t baseGroupX, - uint32_t baseGroupY, - uint32_t baseGroupZ, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ); - VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups( VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, @@ -5913,16 +6270,29 @@ VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2( const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion( - VkDevice device, - const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSamplerYcbcrConversion* pYcbcrConversion); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, + VkExternalBufferProperties* pExternalBufferProperties); -VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion( - VkDevice device, - VkSamplerYcbcrConversion ycbcrConversion, - const VkAllocationCallbacks* pAllocator); +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, + VkExternalFenceProperties* pExternalFenceProperties); + +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, + VkExternalSemaphoreProperties* pExternalSemaphoreProperties); + +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase( + VkCommandBuffer commandBuffer, + uint32_t baseGroupX, + uint32_t baseGroupY, + uint32_t baseGroupZ, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ); VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate( VkDevice device, @@ -5941,25 +6311,21 @@ VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate( VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, - VkExternalBufferProperties* pExternalBufferProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, - VkExternalFenceProperties* pExternalFenceProperties); - -VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, - VkExternalSemaphoreProperties* pExternalSemaphoreProperties); - VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion( + VkDevice device, + const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversion* pYcbcrConversion); + +VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion( + VkDevice device, + VkSamplerYcbcrConversion ycbcrConversion, + const VkAllocationCallbacks* pAllocator); #endif @@ -5999,6 +6365,9 @@ typedef enum VkDriverId { VK_DRIVER_ID_IMAGINATION_OPEN_SOURCE_MESA = 25, VK_DRIVER_ID_MESA_HONEYKRISP = 26, VK_DRIVER_ID_VULKAN_SC_EMULATION_ON_VULKAN = 27, + VK_DRIVER_ID_MESA_KOSMICKRISP = 28, + VK_DRIVER_ID_MESA_GFXSTREAM = 29, + VK_DRIVER_ID_APE_SOFT = 30, VK_DRIVER_ID_AMD_PROPRIETARY_KHR = VK_DRIVER_ID_AMD_PROPRIETARY, VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = VK_DRIVER_ID_AMD_OPEN_SOURCE, VK_DRIVER_ID_MESA_RADV_KHR = VK_DRIVER_ID_MESA_RADV, @@ -6024,6 +6393,14 @@ typedef enum VkShaderFloatControlsIndependence { VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF } VkShaderFloatControlsIndependence; +typedef enum VkSemaphoreType { + VK_SEMAPHORE_TYPE_BINARY = 0, + VK_SEMAPHORE_TYPE_TIMELINE = 1, + VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, + VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, + VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreType; + typedef enum VkSamplerReductionMode { VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, VK_SAMPLER_REDUCTION_MODE_MIN = 1, @@ -6035,30 +6412,32 @@ typedef enum VkSamplerReductionMode { VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerReductionMode; -typedef enum VkSemaphoreType { - VK_SEMAPHORE_TYPE_BINARY = 0, - VK_SEMAPHORE_TYPE_TIMELINE = 1, - VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY, - VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE, - VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF -} VkSemaphoreType; - typedef enum VkResolveModeFlagBits { VK_RESOLVE_MODE_NONE = 0, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 0x00000001, VK_RESOLVE_MODE_AVERAGE_BIT = 0x00000002, VK_RESOLVE_MODE_MIN_BIT = 0x00000004, VK_RESOLVE_MODE_MAX_BIT = 0x00000008, - VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = 0x00000010, + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_BIT_ANDROID = 0x00000010, + VK_RESOLVE_MODE_CUSTOM_BIT_EXT = 0x00000020, VK_RESOLVE_MODE_NONE_KHR = VK_RESOLVE_MODE_NONE, VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, VK_RESOLVE_MODE_AVERAGE_BIT_KHR = VK_RESOLVE_MODE_AVERAGE_BIT, VK_RESOLVE_MODE_MIN_BIT_KHR = VK_RESOLVE_MODE_MIN_BIT, VK_RESOLVE_MODE_MAX_BIT_KHR = VK_RESOLVE_MODE_MAX_BIT, + // VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID is a legacy alias + VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = VK_RESOLVE_MODE_EXTERNAL_FORMAT_DOWNSAMPLE_BIT_ANDROID, VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkResolveModeFlagBits; typedef VkFlags VkResolveModeFlags; +typedef enum VkSemaphoreWaitFlagBits { + VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001, + VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT, + VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreWaitFlagBits; +typedef VkFlags VkSemaphoreWaitFlags; + typedef enum VkDescriptorBindingFlagBits { VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001, VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, @@ -6071,13 +6450,22 @@ typedef enum VkDescriptorBindingFlagBits { VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorBindingFlagBits; typedef VkFlags VkDescriptorBindingFlags; +typedef struct VkConformanceVersion { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersion; + +typedef struct VkPhysicalDeviceDriverProperties { + VkStructureType sType; + void* pNext; + VkDriverId driverID; + char driverName[VK_MAX_DRIVER_NAME_SIZE]; + char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; + VkConformanceVersion conformanceVersion; +} VkPhysicalDeviceDriverProperties; -typedef enum VkSemaphoreWaitFlagBits { - VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001, - VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT, - VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkSemaphoreWaitFlagBits; -typedef VkFlags VkSemaphoreWaitFlags; typedef struct VkPhysicalDeviceVulkan11Features { VkStructureType sType; void* pNext; @@ -6167,13 +6555,6 @@ typedef struct VkPhysicalDeviceVulkan12Features { VkBool32 subgroupBroadcastDynamicId; } VkPhysicalDeviceVulkan12Features; -typedef struct VkConformanceVersion { - uint8_t major; - uint8_t minor; - uint8_t subminor; - uint8_t patch; -} VkConformanceVersion; - typedef struct VkPhysicalDeviceVulkan12Properties { VkStructureType sType; void* pNext; @@ -6238,81 +6619,95 @@ typedef struct VkImageFormatListCreateInfo { const VkFormat* pViewFormats; } VkImageFormatListCreateInfo; -typedef struct VkAttachmentDescription2 { - VkStructureType sType; - const void* pNext; - VkAttachmentDescriptionFlags flags; - VkFormat format; - VkSampleCountFlagBits samples; - VkAttachmentLoadOp loadOp; - VkAttachmentStoreOp storeOp; - VkAttachmentLoadOp stencilLoadOp; - VkAttachmentStoreOp stencilStoreOp; - VkImageLayout initialLayout; - VkImageLayout finalLayout; -} VkAttachmentDescription2; +typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; +} VkPhysicalDeviceVulkanMemoryModelFeatures; -typedef struct VkAttachmentReference2 { - VkStructureType sType; - const void* pNext; - uint32_t attachment; - VkImageLayout layout; - VkImageAspectFlags aspectMask; -} VkAttachmentReference2; +typedef struct VkPhysicalDeviceHostQueryResetFeatures { + VkStructureType sType; + void* pNext; + VkBool32 hostQueryReset; +} VkPhysicalDeviceHostQueryResetFeatures; -typedef struct VkSubpassDescription2 { - VkStructureType sType; - const void* pNext; - VkSubpassDescriptionFlags flags; - VkPipelineBindPoint pipelineBindPoint; - uint32_t viewMask; - uint32_t inputAttachmentCount; - const VkAttachmentReference2* pInputAttachments; - uint32_t colorAttachmentCount; - const VkAttachmentReference2* pColorAttachments; - const VkAttachmentReference2* pResolveAttachments; - const VkAttachmentReference2* pDepthStencilAttachment; - uint32_t preserveAttachmentCount; - const uint32_t* pPreserveAttachments; -} VkSubpassDescription2; +typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { + VkStructureType sType; + void* pNext; + VkBool32 timelineSemaphore; +} VkPhysicalDeviceTimelineSemaphoreFeatures; -typedef struct VkSubpassDependency2 { - VkStructureType sType; - const void* pNext; - uint32_t srcSubpass; - uint32_t dstSubpass; - VkPipelineStageFlags srcStageMask; - VkPipelineStageFlags dstStageMask; - VkAccessFlags srcAccessMask; - VkAccessFlags dstAccessMask; - VkDependencyFlags dependencyFlags; - int32_t viewOffset; -} VkSubpassDependency2; +typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { + VkStructureType sType; + void* pNext; + uint64_t maxTimelineSemaphoreValueDifference; +} VkPhysicalDeviceTimelineSemaphoreProperties; -typedef struct VkRenderPassCreateInfo2 { - VkStructureType sType; - const void* pNext; - VkRenderPassCreateFlags flags; - uint32_t attachmentCount; - const VkAttachmentDescription2* pAttachments; - uint32_t subpassCount; - const VkSubpassDescription2* pSubpasses; - uint32_t dependencyCount; - const VkSubpassDependency2* pDependencies; - uint32_t correlatedViewMaskCount; - const uint32_t* pCorrelatedViewMasks; -} VkRenderPassCreateInfo2; - -typedef struct VkSubpassBeginInfo { - VkStructureType sType; - const void* pNext; - VkSubpassContents contents; -} VkSubpassBeginInfo; - -typedef struct VkSubpassEndInfo { +typedef struct VkSemaphoreTypeCreateInfo { VkStructureType sType; const void* pNext; -} VkSubpassEndInfo; + VkSemaphoreType semaphoreType; + uint64_t initialValue; +} VkSemaphoreTypeCreateInfo; + +typedef struct VkTimelineSemaphoreSubmitInfo { + VkStructureType sType; + const void* pNext; + uint32_t waitSemaphoreValueCount; + const uint64_t* pWaitSemaphoreValues; + uint32_t signalSemaphoreValueCount; + const uint64_t* pSignalSemaphoreValues; +} VkTimelineSemaphoreSubmitInfo; + +typedef struct VkSemaphoreWaitInfo { + VkStructureType sType; + const void* pNext; + VkSemaphoreWaitFlags flags; + uint32_t semaphoreCount; + const VkSemaphore* pSemaphores; + const uint64_t* pValues; +} VkSemaphoreWaitInfo; + +typedef struct VkSemaphoreSignalInfo { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + uint64_t value; +} VkSemaphoreSignalInfo; + +typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { + VkStructureType sType; + void* pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeatures; + +typedef struct VkBufferDeviceAddressInfo { + VkStructureType sType; + const void* pNext; + VkBuffer buffer; +} VkBufferDeviceAddressInfo; + +typedef struct VkBufferOpaqueCaptureAddressCreateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkBufferOpaqueCaptureAddressCreateInfo; + +typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { + VkStructureType sType; + const void* pNext; + uint64_t opaqueCaptureAddress; +} VkMemoryOpaqueCaptureAddressAllocateInfo; + +typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkDeviceMemoryOpaqueCaptureAddressInfo; typedef struct VkPhysicalDevice8BitStorageFeatures { VkStructureType sType; @@ -6322,15 +6717,6 @@ typedef struct VkPhysicalDevice8BitStorageFeatures { VkBool32 storagePushConstant8; } VkPhysicalDevice8BitStorageFeatures; -typedef struct VkPhysicalDeviceDriverProperties { - VkStructureType sType; - void* pNext; - VkDriverId driverID; - char driverName[VK_MAX_DRIVER_NAME_SIZE]; - char driverInfo[VK_MAX_DRIVER_INFO_SIZE]; - VkConformanceVersion conformanceVersion; -} VkPhysicalDeviceDriverProperties; - typedef struct VkPhysicalDeviceShaderAtomicInt64Features { VkStructureType sType; void* pNext; @@ -6440,6 +6826,113 @@ typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport { uint32_t maxVariableDescriptorCount; } VkDescriptorSetVariableDescriptorCountLayoutSupport; +typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 scalarBlockLayout; +} VkPhysicalDeviceScalarBlockLayoutFeatures; + +typedef struct VkSamplerReductionModeCreateInfo { + VkStructureType sType; + const void* pNext; + VkSamplerReductionMode reductionMode; +} VkSamplerReductionModeCreateInfo; + +typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { + VkStructureType sType; + void* pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxProperties; + +typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { + VkStructureType sType; + void* pNext; + VkBool32 uniformBufferStandardLayout; +} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; + +typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupExtendedTypes; +} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; + +typedef struct VkAttachmentDescription2 { + VkStructureType sType; + const void* pNext; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription2; + +typedef struct VkAttachmentReference2 { + VkStructureType sType; + const void* pNext; + uint32_t attachment; + VkImageLayout layout; + VkImageAspectFlags aspectMask; +} VkAttachmentReference2; + +typedef struct VkSubpassDescription2 { + VkStructureType sType; + const void* pNext; + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t viewMask; + uint32_t inputAttachmentCount; + const VkAttachmentReference2* pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference2* pColorAttachments; + const VkAttachmentReference2* pResolveAttachments; + const VkAttachmentReference2* pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t* pPreserveAttachments; +} VkSubpassDescription2; + +typedef struct VkSubpassDependency2 { + VkStructureType sType; + const void* pNext; + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; + int32_t viewOffset; +} VkSubpassDependency2; + +typedef struct VkSubpassBeginInfo { + VkStructureType sType; + const void* pNext; + VkSubpassContents contents; +} VkSubpassBeginInfo; + +typedef struct VkSubpassEndInfo { + VkStructureType sType; + const void* pNext; +} VkSubpassEndInfo; + +typedef struct VkRenderPassCreateInfo2 { + VkStructureType sType; + const void* pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription2* pAttachments; + uint32_t subpassCount; + const VkSubpassDescription2* pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency2* pDependencies; + uint32_t correlatedViewMaskCount; + const uint32_t* pCorrelatedViewMasks; +} VkRenderPassCreateInfo2; + typedef struct VkSubpassDescriptionDepthStencilResolve { VkStructureType sType; const void* pNext; @@ -6457,39 +6950,12 @@ typedef struct VkPhysicalDeviceDepthStencilResolveProperties { VkBool32 independentResolve; } VkPhysicalDeviceDepthStencilResolveProperties; -typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { - VkStructureType sType; - void* pNext; - VkBool32 scalarBlockLayout; -} VkPhysicalDeviceScalarBlockLayoutFeatures; - typedef struct VkImageStencilUsageCreateInfo { VkStructureType sType; const void* pNext; VkImageUsageFlags stencilUsage; } VkImageStencilUsageCreateInfo; -typedef struct VkSamplerReductionModeCreateInfo { - VkStructureType sType; - const void* pNext; - VkSamplerReductionMode reductionMode; -} VkSamplerReductionModeCreateInfo; - -typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { - VkStructureType sType; - void* pNext; - VkBool32 filterMinmaxSingleComponentFormats; - VkBool32 filterMinmaxImageComponentMapping; -} VkPhysicalDeviceSamplerFilterMinmaxProperties; - -typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { - VkStructureType sType; - void* pNext; - VkBool32 vulkanMemoryModel; - VkBool32 vulkanMemoryModelDeviceScope; - VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; -} VkPhysicalDeviceVulkanMemoryModelFeatures; - typedef struct VkPhysicalDeviceImagelessFramebufferFeatures { VkStructureType sType; void* pNext; @@ -6508,13 +6974,6 @@ typedef struct VkFramebufferAttachmentImageInfo { const VkFormat* pViewFormats; } VkFramebufferAttachmentImageInfo; -typedef struct VkFramebufferAttachmentsCreateInfo { - VkStructureType sType; - const void* pNext; - uint32_t attachmentImageInfoCount; - const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos; -} VkFramebufferAttachmentsCreateInfo; - typedef struct VkRenderPassAttachmentBeginInfo { VkStructureType sType; const void* pNext; @@ -6522,17 +6981,12 @@ typedef struct VkRenderPassAttachmentBeginInfo { const VkImageView* pAttachments; } VkRenderPassAttachmentBeginInfo; -typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { - VkStructureType sType; - void* pNext; - VkBool32 uniformBufferStandardLayout; -} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; - -typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderSubgroupExtendedTypes; -} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; +typedef struct VkFramebufferAttachmentsCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t attachmentImageInfoCount; + const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos; +} VkFramebufferAttachmentsCreateInfo; typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures { VkStructureType sType; @@ -6553,94 +7007,6 @@ typedef struct VkAttachmentDescriptionStencilLayout { VkImageLayout stencilFinalLayout; } VkAttachmentDescriptionStencilLayout; -typedef struct VkPhysicalDeviceHostQueryResetFeatures { - VkStructureType sType; - void* pNext; - VkBool32 hostQueryReset; -} VkPhysicalDeviceHostQueryResetFeatures; - -typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { - VkStructureType sType; - void* pNext; - VkBool32 timelineSemaphore; -} VkPhysicalDeviceTimelineSemaphoreFeatures; - -typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { - VkStructureType sType; - void* pNext; - uint64_t maxTimelineSemaphoreValueDifference; -} VkPhysicalDeviceTimelineSemaphoreProperties; - -typedef struct VkSemaphoreTypeCreateInfo { - VkStructureType sType; - const void* pNext; - VkSemaphoreType semaphoreType; - uint64_t initialValue; -} VkSemaphoreTypeCreateInfo; - -typedef struct VkTimelineSemaphoreSubmitInfo { - VkStructureType sType; - const void* pNext; - uint32_t waitSemaphoreValueCount; - const uint64_t* pWaitSemaphoreValues; - uint32_t signalSemaphoreValueCount; - const uint64_t* pSignalSemaphoreValues; -} VkTimelineSemaphoreSubmitInfo; - -typedef struct VkSemaphoreWaitInfo { - VkStructureType sType; - const void* pNext; - VkSemaphoreWaitFlags flags; - uint32_t semaphoreCount; - const VkSemaphore* pSemaphores; - const uint64_t* pValues; -} VkSemaphoreWaitInfo; - -typedef struct VkSemaphoreSignalInfo { - VkStructureType sType; - const void* pNext; - VkSemaphore semaphore; - uint64_t value; -} VkSemaphoreSignalInfo; - -typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { - VkStructureType sType; - void* pNext; - VkBool32 bufferDeviceAddress; - VkBool32 bufferDeviceAddressCaptureReplay; - VkBool32 bufferDeviceAddressMultiDevice; -} VkPhysicalDeviceBufferDeviceAddressFeatures; - -typedef struct VkBufferDeviceAddressInfo { - VkStructureType sType; - const void* pNext; - VkBuffer buffer; -} VkBufferDeviceAddressInfo; - -typedef struct VkBufferOpaqueCaptureAddressCreateInfo { - VkStructureType sType; - const void* pNext; - uint64_t opaqueCaptureAddress; -} VkBufferOpaqueCaptureAddressCreateInfo; - -typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { - VkStructureType sType; - const void* pNext; - uint64_t opaqueCaptureAddress; -} VkMemoryOpaqueCaptureAddressAllocateInfo; - -typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { - VkStructureType sType; - const void* pNext; - VkDeviceMemory memory; -} VkDeviceMemoryOpaqueCaptureAddressInfo; - -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); -typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); -typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); -typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); -typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); typedef void (VKAPI_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t* pValue); typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); @@ -6648,8 +7014,46 @@ typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSem typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); #ifndef VK_NO_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkResetQueryPool( + VkDevice device, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount); + +VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue); + +VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores( + VkDevice device, + const VkSemaphoreWaitInfo* pWaitInfo, + uint64_t timeout); + +VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore( + VkDevice device, + const VkSemaphoreSignalInfo* pSignalInfo); + +VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress( + VkDevice device, + const VkBufferDeviceAddressInfo* pInfo); + +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( + VkDevice device, + const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); + VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -6687,38 +7091,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2( VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2( VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); - -VKAPI_ATTR void VKAPI_CALL vkResetQueryPool( - VkDevice device, - VkQueryPool queryPool, - uint32_t firstQuery, - uint32_t queryCount); - -VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValue( - VkDevice device, - VkSemaphore semaphore, - uint64_t* pValue); - -VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphores( - VkDevice device, - const VkSemaphoreWaitInfo* pWaitInfo, - uint64_t timeout); - -VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphore( - VkDevice device, - const VkSemaphoreSignalInfo* pSignalInfo); - -VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddress( - VkDevice device, - const VkBufferDeviceAddressInfo* pInfo); - -VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddress( - VkDevice device, - const VkBufferDeviceAddressInfo* pInfo); - -VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( - VkDevice device, - const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); #endif @@ -6730,17 +7102,6 @@ VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddress( typedef uint64_t VkFlags64; VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot) -typedef enum VkPipelineCreationFeedbackFlagBits { - VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0x00000001, - VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0x00000002, - VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0x00000004, - VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, - VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, - VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, - VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkPipelineCreationFeedbackFlagBits; -typedef VkFlags VkPipelineCreationFeedbackFlags; - typedef enum VkToolPurposeFlagBits { VK_TOOL_PURPOSE_VALIDATION_BIT = 0x00000001, VK_TOOL_PURPOSE_PROFILING_BIT = 0x00000002, @@ -6832,7 +7193,7 @@ static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0 static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL; -// VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI is a deprecated alias +// VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI is a legacy alias static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL; @@ -6840,6 +7201,9 @@ static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL; static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONVERT_COOPERATIVE_VECTOR_MATRIX_BIT_NV = 0x100000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DATA_GRAPH_BIT_ARM = 0x40000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_INDIRECT_BIT_KHR = 0x400000000000ULL; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MEMORY_DECOMPRESSION_BIT_EXT = 0x200000000000ULL; typedef VkFlags64 VkAccessFlags2; @@ -6868,8 +7232,12 @@ static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000 static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SAMPLER_HEAP_READ_BIT_EXT = 0x200000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_RESOURCE_HEAP_READ_BIT_EXT = 0x400000000000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_TILE_ATTACHMENT_READ_BIT_QCOM = 0x8000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_TILE_ATTACHMENT_WRITE_BIT_QCOM = 0x10000000000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL; static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL; static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL; @@ -6914,6 +7282,10 @@ static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0x10000000000 static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0x200000000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0x40000000000ULL; static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0x80000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DATA_GRAPH_READ_BIT_ARM = 0x800000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_DATA_GRAPH_WRITE_BIT_ARM = 0x1000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT = 0x80000000000000ULL; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT = 0x100000000000000ULL; typedef enum VkSubmitFlagBits { @@ -6922,20 +7294,6 @@ typedef enum VkSubmitFlagBits { VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSubmitFlagBits; typedef VkFlags VkSubmitFlags; - -typedef enum VkRenderingFlagBits { - VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, - VK_RENDERING_SUSPENDING_BIT = 0x00000002, - VK_RENDERING_RESUMING_BIT = 0x00000004, - VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000008, - VK_RENDERING_CONTENTS_INLINE_BIT_KHR = 0x00000010, - VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, - VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, - VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, - VK_RENDERING_CONTENTS_INLINE_BIT_EXT = VK_RENDERING_CONTENTS_INLINE_BIT_KHR, - VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkRenderingFlagBits; -typedef VkFlags VkRenderingFlags; typedef VkFlags64 VkFormatFeatureFlags2; // Flag bits for VkFormatFeatureFlagBits2 @@ -6976,6 +7334,7 @@ static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT = 0x400000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR = 0x08000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x10000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLOCK_MATCHING_SXD_BIT_QCOM = 0x100000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 0x00000001ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 0x00000002ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 0x00000004ULL; @@ -7009,12 +7368,53 @@ static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM = 0x800000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM = 0x1000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM = 0x2000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_SHADER_BIT_ARM = 0x8000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_IMAGE_ALIASING_BIT_ARM = 0x80000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV = 0x10000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV = 0x20000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV = 0x40000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TENSOR_DATA_GRAPH_BIT_ARM = 0x1000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COPY_IMAGE_INDIRECT_DST_BIT_KHR = 0x800000000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x2000000000000ULL; static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x4000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_2D_BIT_IMG = 0x200000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_COPY_ON_COMPUTE_QUEUE_BIT_KHR = 0x10000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_COPY_ON_TRANSFER_QUEUE_BIT_KHR = 0x20000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STENCIL_COPY_ON_COMPUTE_QUEUE_BIT_KHR = 0x40000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STENCIL_COPY_ON_TRANSFER_QUEUE_BIT_KHR = 0x80000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_IMAGE_BIT_ARM = 0x100000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_VECTOR_BIT_ARM = 0x200000000000000ULL; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DATA_GRAPH_OPTICAL_FLOW_COST_BIT_ARM = 0x400000000000000ULL; + +typedef enum VkPipelineCreationFeedbackFlagBits { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 0x00000001, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 0x00000002, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 0x00000004, + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBits; +typedef VkFlags VkPipelineCreationFeedbackFlags; + +typedef enum VkRenderingFlagBits { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 0x00000001, + VK_RENDERING_SUSPENDING_BIT = 0x00000002, + VK_RENDERING_RESUMING_BIT = 0x00000004, + VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x00000008, + VK_RENDERING_CONTENTS_INLINE_BIT_KHR = 0x00000010, + VK_RENDERING_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x00000020, + VK_RENDERING_FRAGMENT_REGION_BIT_EXT = 0x00000040, + VK_RENDERING_CUSTOM_RESOLVE_BIT_EXT = 0x00000080, + VK_RENDERING_LOCAL_READ_CONCURRENT_ACCESS_CONTROL_BIT_KHR = 0x00000100, + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, + VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, + VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, + VK_RENDERING_CONTENTS_INLINE_BIT_EXT = VK_RENDERING_CONTENTS_INLINE_BIT_KHR, + VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderingFlagBits; +typedef VkFlags VkRenderingFlags; typedef struct VkPhysicalDeviceVulkan13Features { VkStructureType sType; void* pNext; @@ -7085,25 +7485,6 @@ typedef struct VkPhysicalDeviceVulkan13Properties { VkDeviceSize maxBufferSize; } VkPhysicalDeviceVulkan13Properties; -typedef struct VkPipelineCreationFeedback { - VkPipelineCreationFeedbackFlags flags; - uint64_t duration; -} VkPipelineCreationFeedback; - -typedef struct VkPipelineCreationFeedbackCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreationFeedback* pPipelineCreationFeedback; - uint32_t pipelineStageCreationFeedbackCount; - VkPipelineCreationFeedback* pPipelineStageCreationFeedbacks; -} VkPipelineCreationFeedbackCreateInfo; - -typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderTerminateInvocation; -} VkPhysicalDeviceShaderTerminateInvocationFeatures; - typedef struct VkPhysicalDeviceToolProperties { VkStructureType sType; void* pNext; @@ -7114,12 +7495,6 @@ typedef struct VkPhysicalDeviceToolProperties { char layer[VK_MAX_EXTENSION_NAME_SIZE]; } VkPhysicalDeviceToolProperties; -typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderDemoteToHelperInvocation; -} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; - typedef struct VkPhysicalDevicePrivateDataFeatures { VkStructureType sType; void* pNext; @@ -7138,12 +7513,6 @@ typedef struct VkPrivateDataSlotCreateInfo { VkPrivateDataSlotCreateFlags flags; } VkPrivateDataSlotCreateInfo; -typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { - VkStructureType sType; - void* pNext; - VkBool32 pipelineCreationCacheControl; -} VkPhysicalDevicePipelineCreationCacheControlFeatures; - typedef struct VkMemoryBarrier2 { VkStructureType sType; const void* pNext; @@ -7228,18 +7597,6 @@ typedef struct VkPhysicalDeviceSynchronization2Features { VkBool32 synchronization2; } VkPhysicalDeviceSynchronization2Features; -typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderZeroInitializeWorkgroupMemory; -} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; - -typedef struct VkPhysicalDeviceImageRobustnessFeatures { - VkStructureType sType; - void* pNext; - VkBool32 robustImageAccess; -} VkPhysicalDeviceImageRobustnessFeatures; - typedef struct VkBufferCopy2 { VkStructureType sType; const void* pNext; @@ -7309,6 +7666,190 @@ typedef struct VkCopyImageToBufferInfo2 { const VkBufferImageCopy2* pRegions; } VkCopyImageToBufferInfo2; +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; + +typedef struct VkFormatProperties3 { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 linearTilingFeatures; + VkFormatFeatureFlags2 optimalTilingFeatures; + VkFormatFeatureFlags2 bufferFeatures; +} VkFormatProperties3; + +typedef struct VkPhysicalDeviceMaintenance4Features { + VkStructureType sType; + void* pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4Features; + +typedef struct VkPhysicalDeviceMaintenance4Properties { + VkStructureType sType; + void* pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4Properties; + +typedef struct VkDeviceBufferMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkBufferCreateInfo* pCreateInfo; +} VkDeviceBufferMemoryRequirements; + +typedef struct VkDeviceImageMemoryRequirements { + VkStructureType sType; + const void* pNext; + const VkImageCreateInfo* pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirements; + +typedef struct VkPipelineCreationFeedback { + VkPipelineCreationFeedbackFlags flags; + uint64_t duration; +} VkPipelineCreationFeedback; + +typedef struct VkPipelineCreationFeedbackCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreationFeedback* pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedback* pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfo; + +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeatures; + +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; + +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeatures; + +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; + +typedef struct VkPhysicalDeviceImageRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { + VkStructureType sType; + void* pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { + VkStructureType sType; + void* pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlProperties; + +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; + +typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { + VkStructureType sType; + void* pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeatures; + +typedef struct VkPhysicalDeviceInlineUniformBlockProperties { + VkStructureType sType; + void* pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockProperties; + +typedef struct VkWriteDescriptorSetInlineUniformBlock { + VkStructureType sType; + const void* pNext; + uint32_t dataSize; + const void* pData; +} VkWriteDescriptorSetInlineUniformBlock; + +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfo; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeatures; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { + VkStructureType sType; + void* pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductProperties; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { + VkStructureType sType; + void* pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentProperties; + typedef struct VkImageBlit2 { VkStructureType sType; const void* pNext; @@ -7351,64 +7892,6 @@ typedef struct VkResolveImageInfo2 { const VkImageResolve2* pRegions; } VkResolveImageInfo2; -typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { - VkStructureType sType; - void* pNext; - VkBool32 subgroupSizeControl; - VkBool32 computeFullSubgroups; -} VkPhysicalDeviceSubgroupSizeControlFeatures; - -typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { - VkStructureType sType; - void* pNext; - uint32_t minSubgroupSize; - uint32_t maxSubgroupSize; - uint32_t maxComputeWorkgroupSubgroups; - VkShaderStageFlags requiredSubgroupSizeStages; -} VkPhysicalDeviceSubgroupSizeControlProperties; - -typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { - VkStructureType sType; - void* pNext; - uint32_t requiredSubgroupSize; -} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; - -typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { - VkStructureType sType; - void* pNext; - VkBool32 inlineUniformBlock; - VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; -} VkPhysicalDeviceInlineUniformBlockFeatures; - -typedef struct VkPhysicalDeviceInlineUniformBlockProperties { - VkStructureType sType; - void* pNext; - uint32_t maxInlineUniformBlockSize; - uint32_t maxPerStageDescriptorInlineUniformBlocks; - uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; - uint32_t maxDescriptorSetInlineUniformBlocks; - uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; -} VkPhysicalDeviceInlineUniformBlockProperties; - -typedef struct VkWriteDescriptorSetInlineUniformBlock { - VkStructureType sType; - const void* pNext; - uint32_t dataSize; - const void* pData; -} VkWriteDescriptorSetInlineUniformBlock; - -typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { - VkStructureType sType; - const void* pNext; - uint32_t maxInlineUniformBlockBindings; -} VkDescriptorPoolInlineUniformBlockCreateInfo; - -typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { - VkStructureType sType; - void* pNext; - VkBool32 textureCompressionASTC_HDR; -} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; - typedef struct VkRenderingAttachmentInfo { VkStructureType sType; const void* pNext; @@ -7463,104 +7946,24 @@ typedef struct VkCommandBufferInheritanceRenderingInfo { VkSampleCountFlagBits rasterizationSamples; } VkCommandBufferInheritanceRenderingInfo; -typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderIntegerDotProduct; -} VkPhysicalDeviceShaderIntegerDotProductFeatures; - -typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { - VkStructureType sType; - void* pNext; - VkBool32 integerDotProduct8BitUnsignedAccelerated; - VkBool32 integerDotProduct8BitSignedAccelerated; - VkBool32 integerDotProduct8BitMixedSignednessAccelerated; - VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; - VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; - VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; - VkBool32 integerDotProduct16BitUnsignedAccelerated; - VkBool32 integerDotProduct16BitSignedAccelerated; - VkBool32 integerDotProduct16BitMixedSignednessAccelerated; - VkBool32 integerDotProduct32BitUnsignedAccelerated; - VkBool32 integerDotProduct32BitSignedAccelerated; - VkBool32 integerDotProduct32BitMixedSignednessAccelerated; - VkBool32 integerDotProduct64BitUnsignedAccelerated; - VkBool32 integerDotProduct64BitSignedAccelerated; - VkBool32 integerDotProduct64BitMixedSignednessAccelerated; - VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; - VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; - VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; - VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; - VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; - VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; -} VkPhysicalDeviceShaderIntegerDotProductProperties; - -typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { - VkStructureType sType; - void* pNext; - VkDeviceSize storageTexelBufferOffsetAlignmentBytes; - VkBool32 storageTexelBufferOffsetSingleTexelAlignment; - VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; - VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; -} VkPhysicalDeviceTexelBufferAlignmentProperties; - -typedef struct VkFormatProperties3 { - VkStructureType sType; - void* pNext; - VkFormatFeatureFlags2 linearTilingFeatures; - VkFormatFeatureFlags2 optimalTilingFeatures; - VkFormatFeatureFlags2 bufferFeatures; -} VkFormatProperties3; - -typedef struct VkPhysicalDeviceMaintenance4Features { - VkStructureType sType; - void* pNext; - VkBool32 maintenance4; -} VkPhysicalDeviceMaintenance4Features; - -typedef struct VkPhysicalDeviceMaintenance4Properties { - VkStructureType sType; - void* pNext; - VkDeviceSize maxBufferSize; -} VkPhysicalDeviceMaintenance4Properties; - -typedef struct VkDeviceBufferMemoryRequirements { - VkStructureType sType; - const void* pNext; - const VkBufferCreateInfo* pCreateInfo; -} VkDeviceBufferMemoryRequirements; - -typedef struct VkDeviceImageMemoryRequirements { - VkStructureType sType; - const void* pNext; - const VkImageCreateInfo* pCreateInfo; - VkImageAspectFlagBits planeAspect; -} VkDeviceImageMemoryRequirements; - typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); typedef VkResult (VKAPI_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); typedef void (VKAPI_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); typedef void (VKAPI_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); -typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); -typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); -typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); -typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); typedef void (VKAPI_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); typedef void (VKAPI_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); @@ -7580,9 +7983,6 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, V typedef void (VKAPI_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); -typedef void (VKAPI_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); -typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #ifndef VK_NO_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolProperties( @@ -7615,22 +8015,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetPrivateData( VkPrivateDataSlot privateDataSlot, uint64_t* pData); -VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2( - VkCommandBuffer commandBuffer, - VkEvent event, - const VkDependencyInfo* pDependencyInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2( - VkCommandBuffer commandBuffer, - VkEvent event, - VkPipelineStageFlags2 stageMask); - -VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2( - VkCommandBuffer commandBuffer, - uint32_t eventCount, - const VkEvent* pEvents, - const VkDependencyInfo* pDependencyInfos); - VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2( VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); @@ -7663,6 +8047,38 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2( VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirements( + VkDevice device, + const VkDeviceBufferMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + VkMemoryRequirements2* pMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( + VkDevice device, + const VkDeviceImageMemoryRequirements* pInfo, + uint32_t* pSparseMemoryRequirementCount, + VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + const VkDependencyInfo* pDependencyInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2( + VkCommandBuffer commandBuffer, + VkEvent event, + VkPipelineStageFlags2 stageMask); + +VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2( + VkCommandBuffer commandBuffer, + uint32_t eventCount, + const VkEvent* pEvents, + const VkDependencyInfo* pDependencyInfos); + VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2( VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); @@ -7748,22 +8164,6 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnable( VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnable( VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirements( - VkDevice device, - const VkDeviceBufferMemoryRequirements* pInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirements( - VkDevice device, - const VkDeviceImageMemoryRequirements* pInfo, - VkMemoryRequirements2* pMemoryRequirements); - -VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirements( - VkDevice device, - const VkDeviceImageMemoryRequirements* pInfo, - uint32_t* pSparseMemoryRequirementCount, - VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #endif @@ -7835,6 +8235,69 @@ typedef enum VkMemoryUnmapFlagBits { VK_MEMORY_UNMAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryUnmapFlagBits; typedef VkFlags VkMemoryUnmapFlags; +typedef VkFlags64 VkBufferUsageFlags2; + +// Flag bits for VkBufferUsageFlagBits2 +typedef VkFlags64 VkBufferUsageFlagBits2; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT = 0x00000001ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT = 0x00000002ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000008ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT = 0x00000010ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT = 0x00000020ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT = 0x00000040ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT = 0x00000080ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT = 0x00000100ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT = 0x00020000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000ULL; +#endif +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT = 0x10000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT = 0x01000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000004ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR = 0x00000010ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR = 0x00000020ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR = 0x00000040ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR = 0x00000080ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR = 0x00000100ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RAY_TRACING_BIT_NV = 0x00000400ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00004000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR = 0x00020000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_COMPRESSED_DATA_DGF1_BIT_AMDX = 0x200000000ULL; +#endif +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_DATA_GRAPH_FOREIGN_DESCRIPTOR_BIT_ARM = 0x20000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TILE_MEMORY_BIT_QCOM = 0x08000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MEMORY_DECOMPRESSION_BIT_EXT = 0x100000000ULL; +static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT = 0x80000000ULL; + + +typedef enum VkHostImageCopyFlagBits { + VK_HOST_IMAGE_COPY_MEMCPY_BIT = 0x00000001, + // VK_HOST_IMAGE_COPY_MEMCPY is a legacy alias + VK_HOST_IMAGE_COPY_MEMCPY = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + VK_HOST_IMAGE_COPY_MEMCPY_BIT_EXT = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + // VK_HOST_IMAGE_COPY_MEMCPY_EXT is a legacy alias + VK_HOST_IMAGE_COPY_MEMCPY_EXT = VK_HOST_IMAGE_COPY_MEMCPY_BIT, + VK_HOST_IMAGE_COPY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkHostImageCopyFlagBits; +typedef VkFlags VkHostImageCopyFlags; typedef VkFlags64 VkPipelineCreateFlags2; // Flag bits for VkPipelineCreateFlagBits2 @@ -7851,7 +8314,9 @@ static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONL #ifdef VK_ENABLE_BETA_EXTENSIONS static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_EXECUTION_GRAPH_BIT_AMDX = 0x100000000ULL; #endif +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT = 0x1000000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_BUILT_IN_PRIMITIVES_BIT_KHR = 0x00001000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_SPHERES_AND_LINEAR_SWEPT_SPHERES_BIT_NV = 0x200000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_ENABLE_LEGACY_DITHERING_BIT_EXT = 0x400000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISABLE_OPTIMIZATION_BIT_KHR = 0x00000001ULL; @@ -7878,69 +8343,23 @@ static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BI static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_ALLOW_MOTION_BIT_NV = 0x00100000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00200000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00400000ULL; -static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 0x01000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x02000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x04000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_NO_PROTECTED_ACCESS_BIT_EXT = 0x08000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PROTECTED_ACCESS_ONLY_BIT_EXT = 0x40000000ULL; +#ifdef VK_ENABLE_BETA_EXTENSIONS static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV = 0x10000000ULL; +#endif static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DESCRIPTOR_BUFFER_BIT_EXT = 0x20000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_DISALLOW_OPACITY_MICROMAP_BIT_ARM = 0x2000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INSTRUMENT_SHADERS_BIT_ARM = 0x8000000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_CAPTURE_DATA_BIT_KHR = 0x80000000ULL; static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_INDIRECT_BINDABLE_BIT_EXT = 0x4000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE = 0x10000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_RAY_TRACING_OPACITY_MICROMAP_BIT_KHR = 0x01000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX_BIT_KHR = 0x20000000000ULL; +static const VkPipelineCreateFlagBits2 VK_PIPELINE_CREATE_2_64_BIT_INDEXING_BIT_EXT = 0x80000000000ULL; -typedef VkFlags64 VkBufferUsageFlags2; - -// Flag bits for VkBufferUsageFlagBits2 -typedef VkFlags64 VkBufferUsageFlagBits2; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT = 0x00000001ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT = 0x00000002ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT = 0x00000008ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT = 0x00000010ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT = 0x00000020ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT = 0x00000040ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT = 0x00000080ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT = 0x00000100ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT = 0x00020000ULL; -#ifdef VK_ENABLE_BETA_EXTENSIONS -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_EXECUTION_GRAPH_SCRATCH_BIT_AMDX = 0x02000000ULL; -#endif -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 0x00000004ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 0x00000008ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT_KHR = 0x00000010ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT_KHR = 0x00000020ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT_KHR = 0x00000040ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT_KHR = 0x00000080ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR = 0x00000100ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR = 0x00000400ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RAY_TRACING_BIT_NV = 0x00000400ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00002000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00004000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00008000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00010000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR = 0x00020000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR = 0x00080000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR = 0x00100000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT = 0x00200000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00400000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT = 0x04000000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT = 0x00800000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_MICROMAP_STORAGE_BIT_EXT = 0x01000000ULL; -static const VkBufferUsageFlagBits2 VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT = 0x80000000ULL; - - -typedef enum VkHostImageCopyFlagBits { - VK_HOST_IMAGE_COPY_MEMCPY = 0x00000001, - VK_HOST_IMAGE_COPY_MEMCPY_EXT = VK_HOST_IMAGE_COPY_MEMCPY, - VK_HOST_IMAGE_COPY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF -} VkHostImageCopyFlagBits; -typedef VkFlags VkHostImageCopyFlags; typedef struct VkPhysicalDeviceVulkan14Features { VkStructureType sType; void* pNext; @@ -8016,77 +8435,6 @@ typedef struct VkQueueFamilyGlobalPriorityProperties { VkQueueGlobalPriority priorities[VK_MAX_GLOBAL_PRIORITY_SIZE]; } VkQueueFamilyGlobalPriorityProperties; -typedef struct VkPhysicalDeviceShaderSubgroupRotateFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderSubgroupRotate; - VkBool32 shaderSubgroupRotateClustered; -} VkPhysicalDeviceShaderSubgroupRotateFeatures; - -typedef struct VkPhysicalDeviceShaderFloatControls2Features { - VkStructureType sType; - void* pNext; - VkBool32 shaderFloatControls2; -} VkPhysicalDeviceShaderFloatControls2Features; - -typedef struct VkPhysicalDeviceShaderExpectAssumeFeatures { - VkStructureType sType; - void* pNext; - VkBool32 shaderExpectAssume; -} VkPhysicalDeviceShaderExpectAssumeFeatures; - -typedef struct VkPhysicalDeviceLineRasterizationFeatures { - VkStructureType sType; - void* pNext; - VkBool32 rectangularLines; - VkBool32 bresenhamLines; - VkBool32 smoothLines; - VkBool32 stippledRectangularLines; - VkBool32 stippledBresenhamLines; - VkBool32 stippledSmoothLines; -} VkPhysicalDeviceLineRasterizationFeatures; - -typedef struct VkPhysicalDeviceLineRasterizationProperties { - VkStructureType sType; - void* pNext; - uint32_t lineSubPixelPrecisionBits; -} VkPhysicalDeviceLineRasterizationProperties; - -typedef struct VkPipelineRasterizationLineStateCreateInfo { - VkStructureType sType; - const void* pNext; - VkLineRasterizationMode lineRasterizationMode; - VkBool32 stippledLineEnable; - uint32_t lineStippleFactor; - uint16_t lineStipplePattern; -} VkPipelineRasterizationLineStateCreateInfo; - -typedef struct VkPhysicalDeviceVertexAttributeDivisorProperties { - VkStructureType sType; - void* pNext; - uint32_t maxVertexAttribDivisor; - VkBool32 supportsNonZeroFirstInstance; -} VkPhysicalDeviceVertexAttributeDivisorProperties; - -typedef struct VkVertexInputBindingDivisorDescription { - uint32_t binding; - uint32_t divisor; -} VkVertexInputBindingDivisorDescription; - -typedef struct VkPipelineVertexInputDivisorStateCreateInfo { - VkStructureType sType; - const void* pNext; - uint32_t vertexBindingDivisorCount; - const VkVertexInputBindingDivisorDescription* pVertexBindingDivisors; -} VkPipelineVertexInputDivisorStateCreateInfo; - -typedef struct VkPhysicalDeviceVertexAttributeDivisorFeatures { - VkStructureType sType; - void* pNext; - VkBool32 vertexAttributeInstanceRateDivisor; - VkBool32 vertexAttributeInstanceRateZeroDivisor; -} VkPhysicalDeviceVertexAttributeDivisorFeatures; - typedef struct VkPhysicalDeviceIndexTypeUint8Features { VkStructureType sType; void* pNext; @@ -8126,15 +8474,11 @@ typedef struct VkPhysicalDeviceMaintenance5Properties { VkBool32 nonStrictWideLinesUseParallelogram; } VkPhysicalDeviceMaintenance5Properties; -typedef struct VkRenderingAreaInfo { - VkStructureType sType; - const void* pNext; - uint32_t viewMask; - uint32_t colorAttachmentCount; - const VkFormat* pColorAttachmentFormats; - VkFormat depthAttachmentFormat; - VkFormat stencilAttachmentFormat; -} VkRenderingAreaInfo; +typedef struct VkSubresourceLayout2 { + VkStructureType sType; + void* pNext; + VkSubresourceLayout subresourceLayout; +} VkSubresourceLayout2; typedef struct VkImageSubresource2 { VkStructureType sType; @@ -8149,52 +8493,12 @@ typedef struct VkDeviceImageSubresourceInfo { const VkImageSubresource2* pSubresource; } VkDeviceImageSubresourceInfo; -typedef struct VkSubresourceLayout2 { - VkStructureType sType; - void* pNext; - VkSubresourceLayout subresourceLayout; -} VkSubresourceLayout2; - -typedef struct VkPipelineCreateFlags2CreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineCreateFlags2 flags; -} VkPipelineCreateFlags2CreateInfo; - typedef struct VkBufferUsageFlags2CreateInfo { VkStructureType sType; const void* pNext; VkBufferUsageFlags2 usage; } VkBufferUsageFlags2CreateInfo; -typedef struct VkPhysicalDevicePushDescriptorProperties { - VkStructureType sType; - void* pNext; - uint32_t maxPushDescriptors; -} VkPhysicalDevicePushDescriptorProperties; - -typedef struct VkPhysicalDeviceDynamicRenderingLocalReadFeatures { - VkStructureType sType; - void* pNext; - VkBool32 dynamicRenderingLocalRead; -} VkPhysicalDeviceDynamicRenderingLocalReadFeatures; - -typedef struct VkRenderingAttachmentLocationInfo { - VkStructureType sType; - const void* pNext; - uint32_t colorAttachmentCount; - const uint32_t* pColorAttachmentLocations; -} VkRenderingAttachmentLocationInfo; - -typedef struct VkRenderingInputAttachmentIndexInfo { - VkStructureType sType; - const void* pNext; - uint32_t colorAttachmentCount; - const uint32_t* pColorAttachmentInputIndices; - const uint32_t* pDepthInputAttachmentIndex; - const uint32_t* pStencilInputAttachmentIndex; -} VkRenderingInputAttachmentIndexInfo; - typedef struct VkPhysicalDeviceMaintenance6Features { VkStructureType sType; void* pNext; @@ -8215,77 +8519,6 @@ typedef struct VkBindMemoryStatus { VkResult* pResult; } VkBindMemoryStatus; -typedef struct VkBindDescriptorSetsInfo { - VkStructureType sType; - const void* pNext; - VkShaderStageFlags stageFlags; - VkPipelineLayout layout; - uint32_t firstSet; - uint32_t descriptorSetCount; - const VkDescriptorSet* pDescriptorSets; - uint32_t dynamicOffsetCount; - const uint32_t* pDynamicOffsets; -} VkBindDescriptorSetsInfo; - -typedef struct VkPushConstantsInfo { - VkStructureType sType; - const void* pNext; - VkPipelineLayout layout; - VkShaderStageFlags stageFlags; - uint32_t offset; - uint32_t size; - const void* pValues; -} VkPushConstantsInfo; - -typedef struct VkPushDescriptorSetInfo { - VkStructureType sType; - const void* pNext; - VkShaderStageFlags stageFlags; - VkPipelineLayout layout; - uint32_t set; - uint32_t descriptorWriteCount; - const VkWriteDescriptorSet* pDescriptorWrites; -} VkPushDescriptorSetInfo; - -typedef struct VkPushDescriptorSetWithTemplateInfo { - VkStructureType sType; - const void* pNext; - VkDescriptorUpdateTemplate descriptorUpdateTemplate; - VkPipelineLayout layout; - uint32_t set; - const void* pData; -} VkPushDescriptorSetWithTemplateInfo; - -typedef struct VkPhysicalDevicePipelineProtectedAccessFeatures { - VkStructureType sType; - void* pNext; - VkBool32 pipelineProtectedAccess; -} VkPhysicalDevicePipelineProtectedAccessFeatures; - -typedef struct VkPhysicalDevicePipelineRobustnessFeatures { - VkStructureType sType; - void* pNext; - VkBool32 pipelineRobustness; -} VkPhysicalDevicePipelineRobustnessFeatures; - -typedef struct VkPhysicalDevicePipelineRobustnessProperties { - VkStructureType sType; - void* pNext; - VkPipelineRobustnessBufferBehavior defaultRobustnessStorageBuffers; - VkPipelineRobustnessBufferBehavior defaultRobustnessUniformBuffers; - VkPipelineRobustnessBufferBehavior defaultRobustnessVertexInputs; - VkPipelineRobustnessImageBehavior defaultRobustnessImages; -} VkPhysicalDevicePipelineRobustnessProperties; - -typedef struct VkPipelineRobustnessCreateInfo { - VkStructureType sType; - const void* pNext; - VkPipelineRobustnessBufferBehavior storageBuffers; - VkPipelineRobustnessBufferBehavior uniformBuffers; - VkPipelineRobustnessBufferBehavior vertexInputs; - VkPipelineRobustnessImageBehavior images; -} VkPipelineRobustnessCreateInfo; - typedef struct VkPhysicalDeviceHostImageCopyFeatures { VkStructureType sType; void* pNext; @@ -8379,32 +8612,213 @@ typedef struct VkHostImageCopyDevicePerformanceQuery { VkBool32 identicalMemoryLayout; } VkHostImageCopyDevicePerformanceQuery; -typedef void (VKAPI_PTR *PFN_vkCmdSetLineStipple)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); +typedef struct VkPhysicalDeviceShaderSubgroupRotateFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupRotate; + VkBool32 shaderSubgroupRotateClustered; +} VkPhysicalDeviceShaderSubgroupRotateFeatures; + +typedef struct VkPhysicalDeviceShaderFloatControls2Features { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloatControls2; +} VkPhysicalDeviceShaderFloatControls2Features; + +typedef struct VkPhysicalDeviceShaderExpectAssumeFeatures { + VkStructureType sType; + void* pNext; + VkBool32 shaderExpectAssume; +} VkPhysicalDeviceShaderExpectAssumeFeatures; + +typedef struct VkPipelineCreateFlags2CreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags2 flags; +} VkPipelineCreateFlags2CreateInfo; + +typedef struct VkPhysicalDevicePushDescriptorProperties { + VkStructureType sType; + void* pNext; + uint32_t maxPushDescriptors; +} VkPhysicalDevicePushDescriptorProperties; + +typedef struct VkBindDescriptorSetsInfo { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t firstSet; + uint32_t descriptorSetCount; + const VkDescriptorSet* pDescriptorSets; + uint32_t dynamicOffsetCount; + const uint32_t* pDynamicOffsets; +} VkBindDescriptorSetsInfo; + +typedef struct VkPushConstantsInfo { + VkStructureType sType; + const void* pNext; + VkPipelineLayout layout; + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; + const void* pValues; +} VkPushConstantsInfo; + +typedef struct VkPushDescriptorSetInfo { + VkStructureType sType; + const void* pNext; + VkShaderStageFlags stageFlags; + VkPipelineLayout layout; + uint32_t set; + uint32_t descriptorWriteCount; + const VkWriteDescriptorSet* pDescriptorWrites; +} VkPushDescriptorSetInfo; + +typedef struct VkPushDescriptorSetWithTemplateInfo { + VkStructureType sType; + const void* pNext; + VkDescriptorUpdateTemplate descriptorUpdateTemplate; + VkPipelineLayout layout; + uint32_t set; + const void* pData; +} VkPushDescriptorSetWithTemplateInfo; + +typedef struct VkPhysicalDevicePipelineProtectedAccessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineProtectedAccess; +} VkPhysicalDevicePipelineProtectedAccessFeatures; + +typedef struct VkPhysicalDevicePipelineRobustnessFeatures { + VkStructureType sType; + void* pNext; + VkBool32 pipelineRobustness; +} VkPhysicalDevicePipelineRobustnessFeatures; + +typedef struct VkPhysicalDevicePipelineRobustnessProperties { + VkStructureType sType; + void* pNext; + VkPipelineRobustnessBufferBehavior defaultRobustnessStorageBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessUniformBuffers; + VkPipelineRobustnessBufferBehavior defaultRobustnessVertexInputs; + VkPipelineRobustnessImageBehavior defaultRobustnessImages; +} VkPhysicalDevicePipelineRobustnessProperties; + +typedef struct VkPipelineRobustnessCreateInfo { + VkStructureType sType; + const void* pNext; + VkPipelineRobustnessBufferBehavior storageBuffers; + VkPipelineRobustnessBufferBehavior uniformBuffers; + VkPipelineRobustnessBufferBehavior vertexInputs; + VkPipelineRobustnessImageBehavior images; +} VkPipelineRobustnessCreateInfo; + +typedef struct VkPhysicalDeviceLineRasterizationFeatures { + VkStructureType sType; + void* pNext; + VkBool32 rectangularLines; + VkBool32 bresenhamLines; + VkBool32 smoothLines; + VkBool32 stippledRectangularLines; + VkBool32 stippledBresenhamLines; + VkBool32 stippledSmoothLines; +} VkPhysicalDeviceLineRasterizationFeatures; + +typedef struct VkPhysicalDeviceLineRasterizationProperties { + VkStructureType sType; + void* pNext; + uint32_t lineSubPixelPrecisionBits; +} VkPhysicalDeviceLineRasterizationProperties; + +typedef struct VkPipelineRasterizationLineStateCreateInfo { + VkStructureType sType; + const void* pNext; + VkLineRasterizationMode lineRasterizationMode; + VkBool32 stippledLineEnable; + uint32_t lineStippleFactor; + uint16_t lineStipplePattern; +} VkPipelineRasterizationLineStateCreateInfo; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorProperties { + VkStructureType sType; + void* pNext; + uint32_t maxVertexAttribDivisor; + VkBool32 supportsNonZeroFirstInstance; +} VkPhysicalDeviceVertexAttributeDivisorProperties; + +typedef struct VkVertexInputBindingDivisorDescription { + uint32_t binding; + uint32_t divisor; +} VkVertexInputBindingDivisorDescription; + +typedef struct VkPipelineVertexInputDivisorStateCreateInfo { + VkStructureType sType; + const void* pNext; + uint32_t vertexBindingDivisorCount; + const VkVertexInputBindingDivisorDescription* pVertexBindingDivisors; +} VkPipelineVertexInputDivisorStateCreateInfo; + +typedef struct VkPhysicalDeviceVertexAttributeDivisorFeatures { + VkStructureType sType; + void* pNext; + VkBool32 vertexAttributeInstanceRateDivisor; + VkBool32 vertexAttributeInstanceRateZeroDivisor; +} VkPhysicalDeviceVertexAttributeDivisorFeatures; + +typedef struct VkRenderingAreaInfo { + VkStructureType sType; + const void* pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkRenderingAreaInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingLocalReadFeatures { + VkStructureType sType; + void* pNext; + VkBool32 dynamicRenderingLocalRead; +} VkPhysicalDeviceDynamicRenderingLocalReadFeatures; + +typedef struct VkRenderingAttachmentLocationInfo { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const uint32_t* pColorAttachmentLocations; +} VkRenderingAttachmentLocationInfo; + +typedef struct VkRenderingInputAttachmentIndexInfo { + VkStructureType sType; + const void* pNext; + uint32_t colorAttachmentCount; + const uint32_t* pColorAttachmentInputIndices; + const uint32_t* pDepthInputAttachmentIndex; + const uint32_t* pStencilInputAttachmentIndex; +} VkRenderingInputAttachmentIndexInfo; + typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2)(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData); typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2)(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); -typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); -typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularity)(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity); typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayout)(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout); typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); -typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingAttachmentLocations)(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo); -typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingInputAttachmentIndices)(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); -typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets2)(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdPushConstants2)(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); -typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToImage)(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToMemory)(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); typedef VkResult (VKAPI_PTR *PFN_vkCopyImageToImage)(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo); typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayout)(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets2)(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushConstants2)(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSet2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplate2)(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetLineStipple)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer2)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); +typedef void (VKAPI_PTR *PFN_vkGetRenderingAreaGranularity)(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity); +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingAttachmentLocations)(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo); +typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingInputAttachmentIndices)(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStipple( - VkCommandBuffer commandBuffer, - uint32_t lineStippleFactor, - uint16_t lineStipplePattern); - VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2( VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, @@ -8414,18 +8828,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2( VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); -VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2( - VkCommandBuffer commandBuffer, - VkBuffer buffer, - VkDeviceSize offset, - VkDeviceSize size, - VkIndexType indexType); - -VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularity( - VkDevice device, - const VkRenderingAreaInfo* pRenderingAreaInfo, - VkExtent2D* pGranularity); - VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayout( VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, @@ -8437,45 +8839,6 @@ VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2( const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet( - VkCommandBuffer commandBuffer, - VkPipelineBindPoint pipelineBindPoint, - VkPipelineLayout layout, - uint32_t set, - uint32_t descriptorWriteCount, - const VkWriteDescriptorSet* pDescriptorWrites); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate( - VkCommandBuffer commandBuffer, - VkDescriptorUpdateTemplate descriptorUpdateTemplate, - VkPipelineLayout layout, - uint32_t set, - const void* pData); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingAttachmentLocations( - VkCommandBuffer commandBuffer, - const VkRenderingAttachmentLocationInfo* pLocationInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingInputAttachmentIndices( - VkCommandBuffer commandBuffer, - const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets2( - VkCommandBuffer commandBuffer, - const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants2( - VkCommandBuffer commandBuffer, - const VkPushConstantsInfo* pPushConstantsInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet2( - VkCommandBuffer commandBuffer, - const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); - -VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate2( - VkCommandBuffer commandBuffer, - const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); - VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImage( VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); @@ -8492,6 +8855,62 @@ VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayout( VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet( + VkCommandBuffer commandBuffer, + VkPipelineBindPoint pipelineBindPoint, + VkPipelineLayout layout, + uint32_t set, + uint32_t descriptorWriteCount, + const VkWriteDescriptorSet* pDescriptorWrites); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate( + VkCommandBuffer commandBuffer, + VkDescriptorUpdateTemplate descriptorUpdateTemplate, + VkPipelineLayout layout, + uint32_t set, + const void* pData); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets2( + VkCommandBuffer commandBuffer, + const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants2( + VkCommandBuffer commandBuffer, + const VkPushConstantsInfo* pPushConstantsInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet2( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate2( + VkCommandBuffer commandBuffer, + const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStipple( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern); + +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2( + VkCommandBuffer commandBuffer, + VkBuffer buffer, + VkDeviceSize offset, + VkDeviceSize size, + VkIndexType indexType); + +VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularity( + VkDevice device, + const VkRenderingAreaInfo* pRenderingAreaInfo, + VkExtent2D* pGranularity); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingAttachmentLocations( + VkCommandBuffer commandBuffer, + const VkRenderingAttachmentLocationInfo* pLocationInfo); + +VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingInputAttachmentIndices( + VkCommandBuffer commandBuffer, + const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); #endif @@ -8508,7 +8927,8 @@ typedef enum VkPresentModeKHR { VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001, - VK_PRESENT_MODE_FIFO_LATEST_READY_EXT = 1000361000, + VK_PRESENT_MODE_FIFO_LATEST_READY_KHR = 1000361000, + VK_PRESENT_MODE_FIFO_LATEST_READY_EXT = VK_PRESENT_MODE_FIFO_LATEST_READY_KHR, VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF } VkPresentModeKHR; @@ -8522,7 +8942,7 @@ typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006, VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007, VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008, - // VK_COLOR_SPACE_DOLBYVISION_EXT is deprecated, but no reason was given in the API XML + // VK_COLOR_SPACE_DOLBYVISION_EXT is legacy, but no reason was given in the API XML VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009, VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010, VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011, @@ -8530,9 +8950,9 @@ typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013, VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014, VK_COLOR_SPACE_DISPLAY_NATIVE_AMD = 1000213000, - // VK_COLORSPACE_SRGB_NONLINEAR_KHR is a deprecated alias + // VK_COLORSPACE_SRGB_NONLINEAR_KHR is a legacy alias VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, - // VK_COLOR_SPACE_DCI_P3_LINEAR_EXT is a deprecated alias + // VK_COLOR_SPACE_DCI_P3_LINEAR_EXT is a legacy alias VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF } VkColorSpaceKHR; @@ -8549,6 +8969,7 @@ typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSurfaceTransformFlagBitsKHR; +typedef VkFlags VkSurfaceTransformFlagsKHR; typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001, @@ -8558,7 +8979,6 @@ typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkCompositeAlphaFlagBitsKHR; typedef VkFlags VkCompositeAlphaFlagsKHR; -typedef VkFlags VkSurfaceTransformFlagsKHR; typedef struct VkSurfaceCapabilitiesKHR { uint32_t minImageCount; uint32_t maxImageCount; @@ -8584,34 +9004,44 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysica typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR( VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); #endif +#endif // VK_KHR_swapchain is a preprocessor guard. Do not pass it to API calls. @@ -8624,7 +9054,12 @@ typedef enum VkSwapchainCreateFlagBitsKHR { VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000001, VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002, VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR = 0x00000004, - VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = 0x00000008, + VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT = 0x00000200, + VK_SWAPCHAIN_CREATE_PRESENT_ID_2_BIT_KHR = 0x00000040, + VK_SWAPCHAIN_CREATE_PRESENT_WAIT_2_BIT_KHR = 0x00000080, + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_KHR = 0x00000008, + VK_SWAPCHAIN_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0x00000100, + VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT = VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_KHR, VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSwapchainCreateFlagBitsKHR; typedef VkFlags VkSwapchainCreateFlagsKHR; @@ -8724,23 +9159,30 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhys typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( VkDevice device, VkSwapchainKHR swapchain, @@ -8748,31 +9190,42 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( VkQueue queue, const VkPresentInfoKHR* pPresentInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR( VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR( VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR( VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex); #endif +#endif // VK_KHR_display is a preprocessor guard. Do not pass it to API calls. @@ -8858,47 +9311,61 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDev typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR( VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR( VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR( VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #endif +#endif // VK_KHR_display_swapchain is a preprocessor guard. Do not pass it to API calls. @@ -8916,6 +9383,7 @@ typedef struct VkDisplayPresentInfoKHR { typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( VkDevice device, uint32_t swapchainCount, @@ -8923,6 +9391,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR( const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains); #endif +#endif // VK_KHR_sampler_mirror_clamp_to_edge is a preprocessor guard. Do not pass it to API calls. @@ -8954,6 +9423,7 @@ typedef enum VkVideoCodecOperationFlagBitsKHR { VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR = 0x00000002, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR = 0x00000004, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR = 0x00040000, + VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR = 0x00000008, VK_VIDEO_CODEC_OPERATION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoCodecOperationFlagBitsKHR; typedef VkFlags VkVideoCodecOperationFlagsKHR; @@ -9165,68 +9635,92 @@ typedef void (VKAPI_PTR *PFN_vkCmdEndVideoCodingKHR)(VkCommandBuffer commandBuff typedef void (VKAPI_PTR *PFN_vkCmdControlVideoCodingKHR)(VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoCapabilitiesKHR( VkPhysicalDevice physicalDevice, const VkVideoProfileInfoKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoFormatPropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoFormatInfoKHR* pVideoFormatInfo, uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionKHR( VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionKHR( VkDevice device, VkVideoSessionKHR videoSession, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetVideoSessionMemoryRequirementsKHR( VkDevice device, VkVideoSessionKHR videoSession, uint32_t* pMemoryRequirementsCount, VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBindVideoSessionMemoryKHR( VkDevice device, VkVideoSessionKHR videoSession, uint32_t bindSessionMemoryInfoCount, const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateVideoSessionParametersKHR( VkDevice device, const VkVideoSessionParametersCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkVideoSessionParametersKHR* pVideoSessionParameters); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkUpdateVideoSessionParametersKHR( VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyVideoSessionParametersKHR( VkDevice device, VkVideoSessionParametersKHR videoSessionParameters, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginVideoCodingKHR( VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndVideoCodingKHR( VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdControlVideoCodingKHR( VkCommandBuffer commandBuffer, const VkVideoCodingControlInfoKHR* pCodingControlInfo); #endif +#endif // VK_KHR_video_decode_queue is a preprocessor guard. Do not pass it to API calls. @@ -9278,10 +9772,12 @@ typedef struct VkVideoDecodeInfoKHR { typedef void (VKAPI_PTR *PFN_vkCmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDecodeVideoKHR( VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo); #endif +#endif // VK_KHR_video_encode_h264 is a preprocessor guard. Do not pass it to API calls. @@ -9301,6 +9797,7 @@ typedef enum VkVideoEncodeH264CapabilityFlagBitsKHR { VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR = 0x00000040, VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR = 0x00000080, VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_H264_CAPABILITY_B_PICTURE_INTRA_REFRESH_BIT_KHR = 0x00000400, VK_VIDEO_ENCODE_H264_CAPABILITY_MB_QP_DIFF_WRAPAROUND_BIT_KHR = 0x00000200, VK_VIDEO_ENCODE_H264_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeH264CapabilityFlagBitsKHR; @@ -9502,6 +9999,7 @@ typedef enum VkVideoEncodeH265CapabilityFlagBitsKHR { VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR = 0x00000080, VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_KHR = 0x00000100, VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_KHR = 0x00000200, + VK_VIDEO_ENCODE_H265_CAPABILITY_B_PICTURE_INTRA_REFRESH_BIT_KHR = 0x00000800, VK_VIDEO_ENCODE_H265_CAPABILITY_CU_QP_DIFF_WRAPAROUND_BIT_KHR = 0x00000400, VK_VIDEO_ENCODE_H265_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeH265CapabilityFlagBitsKHR; @@ -9792,13 +10290,17 @@ typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderingKHR)(VkCommandBuffer typedef void (VKAPI_PTR *PFN_vkCmdEndRenderingKHR)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderingKHR( VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderingKHR( VkCommandBuffer commandBuffer); #endif +#endif // VK_KHR_multiview is a preprocessor guard. Do not pass it to API calls. @@ -9844,39 +10346,53 @@ typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysical typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR( VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties); #endif +#endif // VK_KHR_device_group is a preprocessor guard. Do not pass it to API calls. @@ -9910,17 +10426,22 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffe typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR( VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR( VkCommandBuffer commandBuffer, uint32_t deviceMask); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( VkCommandBuffer commandBuffer, uint32_t baseGroupX, @@ -9930,6 +10451,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( uint32_t groupCountY, uint32_t groupCountZ); #endif +#endif // VK_KHR_shader_draw_parameters is a preprocessor guard. Do not pass it to API calls. @@ -9942,20 +10464,22 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR( #define VK_KHR_maintenance1 1 #define VK_KHR_MAINTENANCE_1_SPEC_VERSION 2 #define VK_KHR_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_maintenance1" -// VK_KHR_MAINTENANCE1_SPEC_VERSION is a deprecated alias +// VK_KHR_MAINTENANCE1_SPEC_VERSION is a legacy alias #define VK_KHR_MAINTENANCE1_SPEC_VERSION VK_KHR_MAINTENANCE_1_SPEC_VERSION -// VK_KHR_MAINTENANCE1_EXTENSION_NAME is a deprecated alias +// VK_KHR_MAINTENANCE1_EXTENSION_NAME is a legacy alias #define VK_KHR_MAINTENANCE1_EXTENSION_NAME VK_KHR_MAINTENANCE_1_EXTENSION_NAME typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR; typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR( VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); #endif +#endif // VK_KHR_device_group_creation is a preprocessor guard. Do not pass it to API calls. @@ -9970,11 +10494,13 @@ typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR; typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR( VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties); #endif +#endif // VK_KHR_external_memory_capabilities is a preprocessor guard. Do not pass it to API calls. @@ -10005,11 +10531,13 @@ typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR; typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties); #endif +#endif // VK_KHR_external_memory is a preprocessor guard. Do not pass it to API calls. @@ -10053,17 +10581,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemo typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR( VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties); #endif +#endif // VK_KHR_external_semaphore_capabilities is a preprocessor guard. Do not pass it to API calls. @@ -10085,11 +10617,13 @@ typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR; typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties); #endif +#endif // VK_KHR_external_semaphore is a preprocessor guard. Do not pass it to API calls. @@ -10128,15 +10662,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHR)(VkDevice device, const typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHR)(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHR( VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHR( VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd); #endif +#endif // VK_KHR_push_descriptor is a preprocessor guard. Do not pass it to API calls. @@ -10149,6 +10687,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandB typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, @@ -10156,7 +10695,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR( uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, @@ -10164,6 +10705,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR( uint32_t set, const void* pData); #endif +#endif // VK_KHR_shader_float16_int8 is a preprocessor guard. Do not pass it to API calls. @@ -10227,23 +10769,29 @@ typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice devi typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR( VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR( VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR( VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData); #endif +#endif // VK_KHR_imageless_framebuffer is a preprocessor guard. Do not pass it to API calls. @@ -10284,26 +10832,34 @@ typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass2KHR)(VkCommandBuffer commandBuffer typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass2KHR)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR( VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR( VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR( VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo, const VkSubpassEndInfo* pSubpassEndInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR( VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo); #endif +#endif // VK_KHR_shared_presentable_image is a preprocessor guard. Do not pass it to API calls. @@ -10319,10 +10875,12 @@ typedef struct VkSharedPresentSurfaceCapabilitiesKHR { typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR( VkDevice device, VkSwapchainKHR swapchain); #endif +#endif // VK_KHR_external_fence_capabilities is a preprocessor guard. Do not pass it to API calls. @@ -10344,11 +10902,13 @@ typedef VkExternalFenceProperties VkExternalFencePropertiesKHR; typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties); #endif +#endif // VK_KHR_external_fence is a preprocessor guard. Do not pass it to API calls. @@ -10387,15 +10947,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkImportFenceFdKHR)(VkDevice device, const VkIm typedef VkResult (VKAPI_PTR *PFN_vkGetFenceFdKHR)(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceFdKHR( VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceFdKHR( VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd); #endif +#endif // VK_KHR_performance_query is a preprocessor guard. Do not pass it to API calls. @@ -10422,11 +10986,11 @@ typedef enum VkPerformanceCounterScopeKHR { VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR = 0, VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR = 1, VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR = 2, - // VK_QUERY_SCOPE_COMMAND_BUFFER_KHR is a deprecated alias + // VK_QUERY_SCOPE_COMMAND_BUFFER_KHR is a legacy alias VK_QUERY_SCOPE_COMMAND_BUFFER_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR, - // VK_QUERY_SCOPE_RENDER_PASS_KHR is a deprecated alias + // VK_QUERY_SCOPE_RENDER_PASS_KHR is a legacy alias VK_QUERY_SCOPE_RENDER_PASS_KHR = VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR, - // VK_QUERY_SCOPE_COMMAND_KHR is a deprecated alias + // VK_QUERY_SCOPE_COMMAND_KHR is a legacy alias VK_QUERY_SCOPE_COMMAND_KHR = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR, VK_PERFORMANCE_COUNTER_SCOPE_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterScopeKHR; @@ -10444,9 +11008,9 @@ typedef enum VkPerformanceCounterStorageKHR { typedef enum VkPerformanceCounterDescriptionFlagBitsKHR { VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR = 0x00000001, VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR = 0x00000002, - // VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR is a deprecated alias + // VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR is a legacy alias VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_PERFORMANCE_IMPACTING_BIT_KHR, - // VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR is a deprecated alias + // VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR is a legacy alias VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_KHR = VK_PERFORMANCE_COUNTER_DESCRIPTION_CONCURRENTLY_IMPACTED_BIT_KHR, VK_PERFORMANCE_COUNTER_DESCRIPTION_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkPerformanceCounterDescriptionFlagBitsKHR; @@ -10523,34 +11087,42 @@ typedef VkResult (VKAPI_PTR *PFN_vkAcquireProfilingLockKHR)(VkDevice device, con typedef void (VKAPI_PTR *PFN_vkReleaseProfilingLockKHR)(VkDevice device); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterKHR* pCounters, VkPerformanceCounterDescriptionKHR* pCounterDescriptions); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR( VkPhysicalDevice physicalDevice, const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo, uint32_t* pNumPasses); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireProfilingLockKHR( VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkReleaseProfilingLockKHR( VkDevice device); #endif +#endif // VK_KHR_maintenance2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance2 1 #define VK_KHR_MAINTENANCE_2_SPEC_VERSION 1 #define VK_KHR_MAINTENANCE_2_EXTENSION_NAME "VK_KHR_maintenance2" -// VK_KHR_MAINTENANCE2_SPEC_VERSION is a deprecated alias +// VK_KHR_MAINTENANCE2_SPEC_VERSION is a legacy alias #define VK_KHR_MAINTENANCE2_SPEC_VERSION VK_KHR_MAINTENANCE_2_SPEC_VERSION -// VK_KHR_MAINTENANCE2_EXTENSION_NAME is a deprecated alias +// VK_KHR_MAINTENANCE2_EXTENSION_NAME is a legacy alias #define VK_KHR_MAINTENANCE2_EXTENSION_NAME VK_KHR_MAINTENANCE_2_EXTENSION_NAME typedef VkPointClippingBehavior VkPointClippingBehaviorKHR; @@ -10594,17 +11166,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkP typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats); #endif +#endif // VK_KHR_variable_pointers is a preprocessor guard. Do not pass it to API calls. @@ -10658,27 +11234,35 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModeProperties2KHR)(VkPhysicalDevic typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayProperties2KHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlaneProperties2KHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR( VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModeProperties2KHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR( VkPhysicalDevice physicalDevice, const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR* pCapabilities); #endif +#endif // VK_KHR_dedicated_allocation is a preprocessor guard. Do not pass it to API calls. @@ -10697,6 +11281,20 @@ typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR; #define VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME "VK_KHR_storage_buffer_storage_class" +// VK_KHR_shader_bfloat16 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_bfloat16 1 +#define VK_KHR_SHADER_BFLOAT16_SPEC_VERSION 1 +#define VK_KHR_SHADER_BFLOAT16_EXTENSION_NAME "VK_KHR_shader_bfloat16" +typedef struct VkPhysicalDeviceShaderBfloat16FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderBFloat16Type; + VkBool32 shaderBFloat16DotProduct; + VkBool32 shaderBFloat16CooperativeMatrix; +} VkPhysicalDeviceShaderBfloat16FeaturesKHR; + + + // VK_KHR_relaxed_block_layout is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_relaxed_block_layout 1 #define VK_KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION 1 @@ -10722,22 +11320,28 @@ typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR( VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR( VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR( VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #endif +#endif // VK_KHR_image_format_list is a preprocessor guard. Do not pass it to API calls. @@ -10776,17 +11380,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice dev typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR( VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR( VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator); #endif +#endif // VK_KHR_bind_memory2 is a preprocessor guard. Do not pass it to API calls. @@ -10801,25 +11409,29 @@ typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32 typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR( VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR( VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos); #endif +#endif // VK_KHR_maintenance3 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance3 1 #define VK_KHR_MAINTENANCE_3_SPEC_VERSION 1 #define VK_KHR_MAINTENANCE_3_EXTENSION_NAME "VK_KHR_maintenance3" -// VK_KHR_MAINTENANCE3_SPEC_VERSION is a deprecated alias +// VK_KHR_MAINTENANCE3_SPEC_VERSION is a legacy alias #define VK_KHR_MAINTENANCE3_SPEC_VERSION VK_KHR_MAINTENANCE_3_SPEC_VERSION -// VK_KHR_MAINTENANCE3_EXTENSION_NAME is a deprecated alias +// VK_KHR_MAINTENANCE3_EXTENSION_NAME is a legacy alias #define VK_KHR_MAINTENANCE3_EXTENSION_NAME VK_KHR_MAINTENANCE_3_EXTENSION_NAME typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR; @@ -10828,11 +11440,13 @@ typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR; typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport); #endif +#endif // VK_KHR_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. @@ -10843,6 +11457,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandB typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -10851,7 +11466,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR( VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -10861,6 +11478,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR( uint32_t maxDrawCount, uint32_t stride); #endif +#endif // VK_KHR_shader_subgroup_extended_types is a preprocessor guard. Do not pass it to API calls. @@ -11039,20 +11657,26 @@ typedef VkResult (VKAPI_PTR *PFN_vkWaitSemaphoresKHR)(VkDevice device, const VkS typedef VkResult (VKAPI_PTR *PFN_vkSignalSemaphoreKHR)(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreCounterValueKHR( VkDevice device, VkSemaphore semaphore, uint64_t* pValue); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkWaitSemaphoresKHR( VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkSignalSemaphoreKHR( VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo); #endif +#endif // VK_KHR_vulkan_memory_model is a preprocessor guard. Do not pass it to API calls. @@ -11147,16 +11771,32 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR)(VkP typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateKHR)(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceFragmentShadingRatesKHR( VkPhysicalDevice physicalDevice, uint32_t* pFragmentShadingRateCount, VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateKHR( VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #endif +#endif + + +// VK_KHR_shader_constant_data is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_constant_data 1 +#define VK_KHR_SHADER_CONSTANT_DATA_SPEC_VERSION 1 +#define VK_KHR_SHADER_CONSTANT_DATA_EXTENSION_NAME "VK_KHR_shader_constant_data" +typedef struct VkPhysicalDeviceShaderConstantDataFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderConstantData; +} VkPhysicalDeviceShaderConstantDataFeaturesKHR; + // VK_KHR_dynamic_rendering_local_read is a preprocessor guard. Do not pass it to API calls. @@ -11173,14 +11813,43 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingAttachmentLocationsKHR)(VkCommandB typedef void (VKAPI_PTR *PFN_vkCmdSetRenderingInputAttachmentIndicesKHR)(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingAttachmentLocationsKHR( VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRenderingInputAttachmentIndicesKHR( VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo); #endif +#endif + + +// VK_KHR_shader_abort is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_abort 1 +#define VK_KHR_SHADER_ABORT_SPEC_VERSION 1 +#define VK_KHR_SHADER_ABORT_EXTENSION_NAME "VK_KHR_shader_abort" +typedef struct VkPhysicalDeviceShaderAbortFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderAbort; +} VkPhysicalDeviceShaderAbortFeaturesKHR; + +typedef struct VkDeviceFaultShaderAbortMessageInfoKHR { + VkStructureType sType; + void* pNext; + uint64_t messageDataSize; + void* pMessageData; +} VkDeviceFaultShaderAbortMessageInfoKHR; + +typedef struct VkPhysicalDeviceShaderAbortPropertiesKHR { + VkStructureType sType; + void* pNext; + uint64_t maxShaderAbortMessageSize; +} VkPhysicalDeviceShaderAbortPropertiesKHR; + // VK_KHR_shader_quad_control is a preprocessor guard. Do not pass it to API calls. @@ -11207,7 +11876,7 @@ typedef struct VkPhysicalDeviceShaderQuadControlFeaturesKHR { #define VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME "VK_KHR_surface_protected_capabilities" typedef struct VkSurfaceProtectedCapabilitiesKHR { VkStructureType sType; - const void* pNext; + void* pNext; VkBool32 supportsProtected; } VkSurfaceProtectedCapabilitiesKHR; @@ -11238,12 +11907,14 @@ typedef struct VkPhysicalDevicePresentWaitFeaturesKHR { typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresentKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresentKHR( VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout); #endif +#endif // VK_KHR_uniform_buffer_standard_layout is a preprocessor guard. Do not pass it to API calls. @@ -11273,18 +11944,24 @@ typedef uint64_t (VKAPI_PTR *PFN_vkGetBufferOpaqueCaptureAddressKHR)(VkDevice de typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddressKHR)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressKHR( VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR uint64_t VKAPI_CALL vkGetBufferOpaqueCaptureAddressKHR( VkDevice device, const VkBufferDeviceAddressInfo* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceMemoryOpaqueCaptureAddressKHR( VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo); #endif +#endif // VK_KHR_deferred_host_operations is a preprocessor guard. Do not pass it to API calls. @@ -11299,28 +11976,38 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice devic typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR( VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR( VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR( VkDevice device, VkDeferredOperationKHR operation); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR( VkDevice device, VkDeferredOperationKHR operation); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR( VkDevice device, VkDeferredOperationKHR operation); #endif +#endif // VK_KHR_pipeline_executable_properties is a preprocessor guard. Do not pass it to API calls. @@ -11394,24 +12081,30 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableStatisticsKHR)(VkDevice typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineExecutableInternalRepresentationsKHR)(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutablePropertiesKHR( VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableStatisticsKHR( VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineExecutableInternalRepresentationsKHR( VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations); #endif +#endif // VK_KHR_map_memory2 is a preprocessor guard. Do not pass it to API calls. @@ -11430,15 +12123,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkMapMemory2KHR)(VkDevice device, const VkMemor typedef VkResult (VKAPI_PTR *PFN_vkUnmapMemory2KHR)(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory2KHR( VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkUnmapMemory2KHR( VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo); #endif +#endif // VK_KHR_shader_integer_dot_product is a preprocessor guard. Do not pass it to API calls. @@ -11504,6 +12201,7 @@ typedef enum VkVideoEncodeTuningModeKHR { } VkVideoEncodeTuningModeKHR; typedef enum VkVideoEncodeFlagBitsKHR { + VK_VIDEO_ENCODE_INTRA_REFRESH_BIT_KHR = 0x00000004, VK_VIDEO_ENCODE_WITH_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x00000001, VK_VIDEO_ENCODE_WITH_EMPHASIS_MAP_BIT_KHR = 0x00000002, VK_VIDEO_ENCODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF @@ -11532,6 +12230,13 @@ typedef enum VkVideoEncodeFeedbackFlagBitsKHR { VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000001, VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000002, VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_FEEDBACK_AVERAGE_QUANTIZATION_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_FEEDBACK_MIN_QUANTIZATION_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_FEEDBACK_MAX_QUANTIZATION_BIT_KHR = 0x00000020, + VK_VIDEO_ENCODE_FEEDBACK_INTRA_PIXELS_BIT_KHR = 0x00000040, + VK_VIDEO_ENCODE_FEEDBACK_INTER_PIXELS_BIT_KHR = 0x00000080, + VK_VIDEO_ENCODE_FEEDBACK_SKIPPED_PIXELS_BIT_KHR = 0x00000100, + VK_VIDEO_ENCODE_FEEDBACK_PICTURE_PARTITION_COUNT_BIT_KHR = 0x00000200, VK_VIDEO_ENCODE_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeFeedbackFlagBitsKHR; typedef VkFlags VkVideoEncodeFeedbackFlagsKHR; @@ -11652,22 +12357,28 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetEncodedVideoSessionParametersKHR)(VkDevice typedef void (VKAPI_PTR *PFN_vkCmdEncodeVideoKHR)(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR* pQualityLevelInfo, VkVideoEncodeQualityLevelPropertiesKHR* pQualityLevelProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetEncodedVideoSessionParametersKHR( VkDevice device, const VkVideoEncodeSessionParametersGetInfoKHR* pVideoSessionParametersInfo, VkVideoEncodeSessionParametersFeedbackInfoKHR* pFeedbackInfo, size_t* pDataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEncodeVideoKHR( VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo); #endif +#endif // VK_KHR_synchronization2 is a preprocessor guard. Do not pass it to API calls. @@ -11707,41 +12418,423 @@ typedef void (VKAPI_PTR *PFN_vkCmdResetEvent2KHR)(VkCommandBuffer typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents2KHR)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier2KHR)(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp2KHR)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); -typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit2KHR)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent2KHR( VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent2KHR( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents2KHR( VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, const VkDependencyInfo* pDependencyInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier2KHR( VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp2KHR( VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit2KHR( VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence); #endif +#endif + + +// VK_KHR_device_address_commands is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_address_commands 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) +#define VK_KHR_DEVICE_ADDRESS_COMMANDS_SPEC_VERSION 1 +#define VK_KHR_DEVICE_ADDRESS_COMMANDS_EXTENSION_NAME "VK_KHR_device_address_commands" + +typedef enum VkAccelerationStructureTypeKHR { + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, + VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, + VK_ACCELERATION_STRUCTURE_TYPE_OPACITY_MICROMAP_KHR = 1000623000, + VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, + VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureTypeKHR; + +typedef enum VkAddressCommandFlagBitsKHR { + VK_ADDRESS_COMMAND_PROTECTED_BIT_KHR = 0x00000001, + VK_ADDRESS_COMMAND_FULLY_BOUND_BIT_KHR = 0x00000002, + VK_ADDRESS_COMMAND_STORAGE_BUFFER_USAGE_BIT_KHR = 0x00000004, + VK_ADDRESS_COMMAND_UNKNOWN_STORAGE_BUFFER_USAGE_BIT_KHR = 0x00000008, + VK_ADDRESS_COMMAND_TRANSFORM_FEEDBACK_BUFFER_USAGE_BIT_KHR = 0x00000010, + VK_ADDRESS_COMMAND_UNKNOWN_TRANSFORM_FEEDBACK_BUFFER_USAGE_BIT_KHR = 0x00000020, + VK_ADDRESS_COMMAND_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAddressCommandFlagBitsKHR; +typedef VkFlags VkAddressCommandFlagsKHR; + +typedef enum VkConditionalRenderingFlagBitsEXT { + VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, + VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkConditionalRenderingFlagBitsEXT; +typedef VkFlags VkConditionalRenderingFlagsEXT; + +typedef enum VkAccelerationStructureCreateFlagBitsKHR { + VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, + VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, + VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, + VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureCreateFlagBitsKHR; +typedef VkFlags VkAccelerationStructureCreateFlagsKHR; +typedef struct VkDeviceAddressRangeKHR { + VkDeviceAddress address; + VkDeviceSize size; +} VkDeviceAddressRangeKHR; + +typedef struct VkStridedDeviceAddressRangeKHR { + VkDeviceAddress address; + VkDeviceSize size; + VkDeviceSize stride; +} VkStridedDeviceAddressRangeKHR; + +typedef struct VkDeviceMemoryCopyKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR srcRange; + VkAddressCommandFlagsKHR srcFlags; + VkDeviceAddressRangeKHR dstRange; + VkAddressCommandFlagsKHR dstFlags; +} VkDeviceMemoryCopyKHR; + +typedef struct VkCopyDeviceMemoryInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t regionCount; + const VkDeviceMemoryCopyKHR* pRegions; +} VkCopyDeviceMemoryInfoKHR; + +typedef struct VkDeviceMemoryImageCopyKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + uint32_t addressRowLength; + uint32_t addressImageHeight; + VkImageSubresourceLayers imageSubresource; + VkImageLayout imageLayout; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkDeviceMemoryImageCopyKHR; + +typedef struct VkCopyDeviceMemoryImageInfoKHR { + VkStructureType sType; + const void* pNext; + VkImage image; + uint32_t regionCount; + const VkDeviceMemoryImageCopyKHR* pRegions; +} VkCopyDeviceMemoryImageInfoKHR; + +typedef struct VkMemoryRangeBarrierKHR { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkMemoryRangeBarrierKHR; + +typedef struct VkMemoryRangeBarriersInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t memoryRangeBarrierCount; + const VkMemoryRangeBarrierKHR* pMemoryRangeBarriers; +} VkMemoryRangeBarriersInfoKHR; + +typedef struct VkPhysicalDeviceDeviceAddressCommandsFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 deviceAddressCommands; +} VkPhysicalDeviceDeviceAddressCommandsFeaturesKHR; + +typedef struct VkBindIndexBuffer3InfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkIndexType indexType; +} VkBindIndexBuffer3InfoKHR; + +typedef struct VkBindVertexBuffer3InfoKHR { + VkStructureType sType; + const void* pNext; + VkBool32 setStride; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkBindVertexBuffer3InfoKHR; + +typedef struct VkDrawIndirect2InfoKHR { + VkStructureType sType; + const void* pNext; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + uint32_t drawCount; +} VkDrawIndirect2InfoKHR; + +typedef struct VkDrawIndirectCount2InfoKHR { + VkStructureType sType; + const void* pNext; + VkStridedDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkDeviceAddressRangeKHR countAddressRange; + VkAddressCommandFlagsKHR countAddressFlags; + uint32_t maxDrawCount; +} VkDrawIndirectCount2InfoKHR; + +typedef struct VkDispatchIndirect2InfoKHR { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkDispatchIndirect2InfoKHR; + +typedef struct VkConditionalRenderingBeginInfo2EXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkConditionalRenderingFlagsEXT flags; +} VkConditionalRenderingBeginInfo2EXT; + +typedef struct VkBindTransformFeedbackBuffer2InfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; +} VkBindTransformFeedbackBuffer2InfoEXT; + +typedef struct VkMemoryMarkerInfoAMD { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2KHR stage; + VkDeviceAddressRangeKHR dstRange; + VkAddressCommandFlagsKHR dstFlags; + uint32_t marker; +} VkMemoryMarkerInfoAMD; + +typedef struct VkAccelerationStructureCreateInfo2KHR { + VkStructureType sType; + const void* pNext; + VkAccelerationStructureCreateFlagsKHR createFlags; + VkDeviceAddressRangeKHR addressRange; + VkAddressCommandFlagsKHR addressFlags; + VkAccelerationStructureTypeKHR type; +} VkAccelerationStructureCreateInfo2KHR; + +typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer3KHR)(VkCommandBuffer commandBuffer, const VkBindIndexBuffer3InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers3KHR)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBindVertexBuffer3InfoKHR* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect2KHR)(VkCommandBuffer commandBuffer, const VkDispatchIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +typedef void (VKAPI_PTR *PFN_vkCmdUpdateMemoryKHR)(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, VkDeviceSize dataSize, const void* pData); +typedef void (VKAPI_PTR *PFN_vkCmdFillMemoryKHR)(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, uint32_t data); +typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResultsToMemoryKHR)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, const VkStridedDeviceAddressRangeKHR* pDstRange, VkAddressCommandFlagsKHR dstFlags, VkQueryResultFlags queryResultFlags); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCount2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCount2KHR)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRendering2EXT)(VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfo2EXT* pConditionalRenderingBegin); +typedef void (VKAPI_PTR *PFN_vkCmdBindTransformFeedbackBuffers2EXT)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBindTransformFeedbackBuffer2InfoEXT* pBindingInfos); +typedef void (VKAPI_PTR *PFN_vkCmdBeginTransformFeedback2EXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterRange, uint32_t counterRangeCount, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +typedef void (VKAPI_PTR *PFN_vkCmdEndTransformFeedback2EXT)(VkCommandBuffer commandBuffer, uint32_t firstCounterRange, uint32_t counterRangeCount, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCount2EXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfo, uint32_t counterOffset, uint32_t vertexStride); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirect2EXT)(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCount2EXT)(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteMarkerToMemoryAMD)(VkCommandBuffer commandBuffer, const VkMemoryMarkerInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructure2KHR)(VkDevice device, const VkAccelerationStructureCreateInfo2KHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer3KHR( + VkCommandBuffer commandBuffer, + const VkBindIndexBuffer3InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers3KHR( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBindVertexBuffer3InfoKHR* pBindingInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect2KHR( + VkCommandBuffer commandBuffer, + const VkDispatchIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToMemoryKHR( + VkCommandBuffer commandBuffer, + const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdUpdateMemoryKHR( + VkCommandBuffer commandBuffer, + const VkDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + VkDeviceSize dataSize, + const void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdFillMemoryKHR( + VkCommandBuffer commandBuffer, + const VkDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + uint32_t data); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResultsToMemoryKHR( + VkCommandBuffer commandBuffer, + VkQueryPool queryPool, + uint32_t firstQuery, + uint32_t queryCount, + const VkStridedDeviceAddressRangeKHR* pDstRange, + VkAddressCommandFlagsKHR dstFlags, + VkQueryResultFlags queryResultFlags); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCount2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCount2KHR( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRendering2EXT( + VkCommandBuffer commandBuffer, + const VkConditionalRenderingBeginInfo2EXT* pConditionalRenderingBegin); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffers2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pBindingInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedback2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterRange, + uint32_t counterRangeCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedback2EXT( + VkCommandBuffer commandBuffer, + uint32_t firstCounterRange, + uint32_t counterRangeCount, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCount2EXT( + VkCommandBuffer commandBuffer, + uint32_t instanceCount, + uint32_t firstInstance, + const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfo, + uint32_t counterOffset, + uint32_t vertexStride); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirect2EXT( + VkCommandBuffer commandBuffer, + const VkDrawIndirect2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCount2EXT( + VkCommandBuffer commandBuffer, + const VkDrawIndirectCount2InfoKHR* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdWriteMarkerToMemoryAMD( + VkCommandBuffer commandBuffer, + const VkMemoryMarkerInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructure2KHR( + VkDevice device, + const VkAccelerationStructureCreateInfo2KHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkAccelerationStructureKHR* pAccelerationStructure); +#endif +#endif // VK_KHR_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. @@ -11831,30 +12924,42 @@ typedef void (VKAPI_PTR *PFN_vkCmdBlitImage2KHR)(VkCommandBuffer commandBuffer, typedef void (VKAPI_PTR *PFN_vkCmdResolveImage2KHR)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer2KHR( VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage2KHR( VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage2KHR( VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer2KHR( VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage2KHR( VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage2KHR( VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo); #endif +#endif // VK_KHR_format_feature_flags2 is a preprocessor guard. Do not pass it to API calls. @@ -11900,10 +13005,24 @@ typedef struct VkTraceRaysIndirectCommand2KHR { typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirect2KHR)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirect2KHR( VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress); #endif +#endif + + +// VK_KHR_shader_untyped_pointers is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_untyped_pointers 1 +#define VK_KHR_SHADER_UNTYPED_POINTERS_SPEC_VERSION 1 +#define VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME "VK_KHR_shader_untyped_pointers" +typedef struct VkPhysicalDeviceShaderUntypedPointersFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderUntypedPointers; +} VkPhysicalDeviceShaderUntypedPointersFeaturesKHR; + // VK_KHR_portability_enumeration is a preprocessor guard. Do not pass it to API calls. @@ -11929,22 +13048,28 @@ typedef void (VKAPI_PTR *PFN_vkGetDeviceImageMemoryRequirementsKHR)(VkDevice dev typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)(VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceBufferMemoryRequirementsKHR( VkDevice device, const VkDeviceBufferMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageMemoryRequirementsKHR( VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSparseMemoryRequirementsKHR( VkDevice device, const VkDeviceImageMemoryRequirements* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements); #endif +#endif // VK_KHR_shader_subgroup_rotate is a preprocessor guard. Do not pass it to API calls. @@ -12001,29 +13126,97 @@ typedef void (VKAPI_PTR *PFN_vkGetDeviceImageSubresourceLayoutKHR)(VkDevice devi typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2KHR)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer2KHR( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetRenderingAreaGranularityKHR( VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceImageSubresourceLayoutKHR( VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2KHR( VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); #endif +#endif + + +// VK_KHR_present_id2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_id2 1 +#define VK_KHR_PRESENT_ID_2_SPEC_VERSION 1 +#define VK_KHR_PRESENT_ID_2_EXTENSION_NAME "VK_KHR_present_id2" +typedef struct VkSurfaceCapabilitiesPresentId2KHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId2Supported; +} VkSurfaceCapabilitiesPresentId2KHR; + +typedef struct VkPresentId2KHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const uint64_t* pPresentIds; +} VkPresentId2KHR; + +typedef struct VkPhysicalDevicePresentId2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentId2; +} VkPhysicalDevicePresentId2FeaturesKHR; + + + +// VK_KHR_present_wait2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_wait2 1 +#define VK_KHR_PRESENT_WAIT_2_SPEC_VERSION 1 +#define VK_KHR_PRESENT_WAIT_2_EXTENSION_NAME "VK_KHR_present_wait2" +typedef struct VkSurfaceCapabilitiesPresentWait2KHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait2Supported; +} VkSurfaceCapabilitiesPresentWait2KHR; + +typedef struct VkPhysicalDevicePresentWait2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentWait2; +} VkPhysicalDevicePresentWait2FeaturesKHR; + +typedef struct VkPresentWait2InfoKHR { + VkStructureType sType; + const void* pNext; + uint64_t presentId; + uint64_t timeout; +} VkPresentWait2InfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkWaitForPresent2KHR)(VkDevice device, VkSwapchainKHR swapchain, const VkPresentWait2InfoKHR* pPresentWait2Info); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWaitForPresent2KHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkPresentWait2InfoKHR* pPresentWait2Info); +#endif +#endif // VK_KHR_ray_tracing_position_fetch is a preprocessor guard. Do not pass it to API calls. @@ -12130,34 +13323,165 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineBinaryDataKHR)(VkDevice device, co typedef VkResult (VKAPI_PTR *PFN_vkReleaseCapturedPipelineDataKHR)(VkDevice device, const VkReleaseCapturedPipelineDataInfoKHR* pInfo, const VkAllocationCallbacks* pAllocator); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineBinariesKHR( VkDevice device, const VkPipelineBinaryCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineBinaryHandlesInfoKHR* pBinaries); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineBinaryKHR( VkDevice device, VkPipelineBinaryKHR pipelineBinary, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineKeyKHR( VkDevice device, const VkPipelineCreateInfoKHR* pPipelineCreateInfo, VkPipelineBinaryKeyKHR* pPipelineKey); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineBinaryDataKHR( VkDevice device, const VkPipelineBinaryDataInfoKHR* pInfo, VkPipelineBinaryKeyKHR* pPipelineBinaryKey, size_t* pPipelineBinaryDataSize, void* pPipelineBinaryData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkReleaseCapturedPipelineDataKHR( VkDevice device, const VkReleaseCapturedPipelineDataInfoKHR* pInfo, const VkAllocationCallbacks* pAllocator); #endif +#endif + + +// VK_KHR_surface_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_surface_maintenance1 1 +#define VK_KHR_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_surface_maintenance1" + +typedef enum VkPresentScalingFlagBitsKHR { + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_KHR = 0x00000001, + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_KHR = 0x00000002, + VK_PRESENT_SCALING_STRETCH_BIT_KHR = 0x00000004, + VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = VK_PRESENT_SCALING_ONE_TO_ONE_BIT_KHR, + VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_KHR, + VK_PRESENT_SCALING_STRETCH_BIT_EXT = VK_PRESENT_SCALING_STRETCH_BIT_KHR, + VK_PRESENT_SCALING_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentScalingFlagBitsKHR; +typedef VkFlags VkPresentScalingFlagsKHR; + +typedef enum VkPresentGravityFlagBitsKHR { + VK_PRESENT_GRAVITY_MIN_BIT_KHR = 0x00000001, + VK_PRESENT_GRAVITY_MAX_BIT_KHR = 0x00000002, + VK_PRESENT_GRAVITY_CENTERED_BIT_KHR = 0x00000004, + VK_PRESENT_GRAVITY_MIN_BIT_EXT = VK_PRESENT_GRAVITY_MIN_BIT_KHR, + VK_PRESENT_GRAVITY_MAX_BIT_EXT = VK_PRESENT_GRAVITY_MAX_BIT_KHR, + VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = VK_PRESENT_GRAVITY_CENTERED_BIT_KHR, + VK_PRESENT_GRAVITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkPresentGravityFlagBitsKHR; +typedef VkFlags VkPresentGravityFlagsKHR; +typedef struct VkSurfacePresentModeKHR { + VkStructureType sType; + void* pNext; + VkPresentModeKHR presentMode; +} VkSurfacePresentModeKHR; + +typedef struct VkSurfacePresentScalingCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkPresentScalingFlagsKHR supportedPresentScaling; + VkPresentGravityFlagsKHR supportedPresentGravityX; + VkPresentGravityFlagsKHR supportedPresentGravityY; + VkExtent2D minScaledImageExtent; + VkExtent2D maxScaledImageExtent; +} VkSurfacePresentScalingCapabilitiesKHR; + +typedef struct VkSurfacePresentModeCompatibilityKHR { + VkStructureType sType; + void* pNext; + uint32_t presentModeCount; + VkPresentModeKHR* pPresentModes; +} VkSurfacePresentModeCompatibilityKHR; + + + +// VK_KHR_swapchain_maintenance1 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_swapchain_maintenance1 1 +#define VK_KHR_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 +#define VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_KHR_swapchain_maintenance1" +typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 swapchainMaintenance1; +} VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR; + +typedef struct VkSwapchainPresentFenceInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkFence* pFences; +} VkSwapchainPresentFenceInfoKHR; + +typedef struct VkSwapchainPresentModesCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t presentModeCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModesCreateInfoKHR; + +typedef struct VkSwapchainPresentModeInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentModeKHR* pPresentModes; +} VkSwapchainPresentModeInfoKHR; + +typedef struct VkSwapchainPresentScalingCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkPresentScalingFlagsKHR scalingBehavior; + VkPresentGravityFlagsKHR presentGravityX; + VkPresentGravityFlagsKHR presentGravityY; +} VkSwapchainPresentScalingCreateInfoKHR; + +typedef struct VkReleaseSwapchainImagesInfoKHR { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + uint32_t imageIndexCount; + const uint32_t* pImageIndices; +} VkReleaseSwapchainImagesInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesKHR)(VkDevice device, const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesKHR( + VkDevice device, + const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); +#endif +#endif + + +// VK_KHR_internally_synchronized_queues is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_internally_synchronized_queues 1 +#define VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_SPEC_VERSION 1 +#define VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME "VK_KHR_internally_synchronized_queues" +typedef struct VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 internallySynchronizedQueues; +} VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR; + // VK_KHR_cooperative_matrix is a preprocessor guard. Do not pass it to API calls. @@ -12177,10 +13501,11 @@ typedef enum VkComponentTypeKHR { VK_COMPONENT_TYPE_UINT16_KHR = 8, VK_COMPONENT_TYPE_UINT32_KHR = 9, VK_COMPONENT_TYPE_UINT64_KHR = 10, + VK_COMPONENT_TYPE_BFLOAT16_KHR = 1000141000, VK_COMPONENT_TYPE_SINT8_PACKED_NV = 1000491000, VK_COMPONENT_TYPE_UINT8_PACKED_NV = 1000491001, - VK_COMPONENT_TYPE_FLOAT_E4M3_NV = 1000491002, - VK_COMPONENT_TYPE_FLOAT_E5M2_NV = 1000491003, + VK_COMPONENT_TYPE_FLOAT8_E4M3_EXT = 1000491002, + VK_COMPONENT_TYPE_FLOAT8_E5M2_EXT = 1000491003, VK_COMPONENT_TYPE_FLOAT16_NV = VK_COMPONENT_TYPE_FLOAT16_KHR, VK_COMPONENT_TYPE_FLOAT32_NV = VK_COMPONENT_TYPE_FLOAT32_KHR, VK_COMPONENT_TYPE_FLOAT64_NV = VK_COMPONENT_TYPE_FLOAT64_KHR, @@ -12192,6 +13517,8 @@ typedef enum VkComponentTypeKHR { VK_COMPONENT_TYPE_UINT16_NV = VK_COMPONENT_TYPE_UINT16_KHR, VK_COMPONENT_TYPE_UINT32_NV = VK_COMPONENT_TYPE_UINT32_KHR, VK_COMPONENT_TYPE_UINT64_NV = VK_COMPONENT_TYPE_UINT64_KHR, + VK_COMPONENT_TYPE_FLOAT_E4M3_NV = VK_COMPONENT_TYPE_FLOAT8_E4M3_EXT, + VK_COMPONENT_TYPE_FLOAT_E5M2_NV = VK_COMPONENT_TYPE_FLOAT8_E5M2_EXT, VK_COMPONENT_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF } VkComponentTypeKHR; @@ -12236,11 +13563,13 @@ typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesKHR { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesKHR* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesKHR* pProperties); #endif +#endif // VK_KHR_compute_shader_derivatives is a preprocessor guard. Do not pass it to API calls. @@ -12334,6 +13663,7 @@ typedef enum VkVideoEncodeAV1CapabilityFlagBitsKHR { VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR = 0x00000004, VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR = 0x00000008, VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR = 0x00000010, + VK_VIDEO_ENCODE_AV1_CAPABILITY_COMPOUND_PREDICTION_INTRA_REFRESH_BIT_KHR = 0x00000020, VK_VIDEO_ENCODE_AV1_CAPABILITY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkVideoEncodeAV1CapabilityFlagBitsKHR; typedef VkFlags VkVideoEncodeAV1CapabilityFlagsKHR; @@ -12501,6 +13831,43 @@ typedef struct VkVideoEncodeAV1RateControlLayerInfoKHR { +// VK_KHR_video_decode_vp9 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_decode_vp9 1 +#include "vk_video/vulkan_video_codec_vp9std.h" +#include "vk_video/vulkan_video_codec_vp9std_decode.h" +#define VK_MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR 3U +#define VK_KHR_VIDEO_DECODE_VP9_SPEC_VERSION 1 +#define VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME "VK_KHR_video_decode_vp9" +typedef struct VkPhysicalDeviceVideoDecodeVP9FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoDecodeVP9; +} VkPhysicalDeviceVideoDecodeVP9FeaturesKHR; + +typedef struct VkVideoDecodeVP9ProfileInfoKHR { + VkStructureType sType; + const void* pNext; + StdVideoVP9Profile stdProfile; +} VkVideoDecodeVP9ProfileInfoKHR; + +typedef struct VkVideoDecodeVP9CapabilitiesKHR { + VkStructureType sType; + void* pNext; + StdVideoVP9Level maxLevel; +} VkVideoDecodeVP9CapabilitiesKHR; + +typedef struct VkVideoDecodeVP9PictureInfoKHR { + VkStructureType sType; + const void* pNext; + const StdVideoDecodeVP9PictureInfo* pStdPictureInfo; + int32_t referenceNameSlotIndices[VK_MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR]; + uint32_t uncompressedHeaderOffset; + uint32_t compressedHeaderOffset; + uint32_t tilesOffset; +} VkVideoDecodeVP9PictureInfoKHR; + + + // VK_KHR_video_maintenance1 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_video_maintenance1 1 #define VK_KHR_VIDEO_MAINTENANCE_1_SPEC_VERSION 1 @@ -12541,6 +13908,25 @@ typedef VkPhysicalDeviceVertexAttributeDivisorFeatures VkPhysicalDeviceVertexAtt #define VK_KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME "VK_KHR_load_store_op_none" +// VK_KHR_unified_image_layouts is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_unified_image_layouts 1 +#define VK_KHR_UNIFIED_IMAGE_LAYOUTS_SPEC_VERSION 1 +#define VK_KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME "VK_KHR_unified_image_layouts" +typedef struct VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 unifiedImageLayouts; + VkBool32 unifiedImageLayoutsVideo; +} VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR; + +typedef struct VkAttachmentFeedbackLoopInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 feedbackLoopEnable; +} VkAttachmentFeedbackLoopInfoEXT; + + + // VK_KHR_shader_float_controls2 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_shader_float_controls2 1 #define VK_KHR_SHADER_FLOAT_CONTROLS_2_SPEC_VERSION 1 @@ -12572,11 +13958,13 @@ typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineSt typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleKHR)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleKHR( VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); #endif +#endif // VK_KHR_calibrated_timestamps is a preprocessor guard. Do not pass it to API calls. @@ -12589,6 +13977,8 @@ typedef enum VkTimeDomainKHR { VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR = 1, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR = 2, VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR = 3, + VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT = 1000208000, + VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT = 1000208001, VK_TIME_DOMAIN_DEVICE_EXT = VK_TIME_DOMAIN_DEVICE_KHR, VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR, VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR, @@ -12605,11 +13995,14 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR) typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsKHR)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsKHR( VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainKHR* pTimeDomains); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsKHR( VkDevice device, uint32_t timestampCount, @@ -12617,6 +14010,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsKHR( uint64_t* pTimestamps, uint64_t* pMaxDeviation); #endif +#endif // VK_KHR_shader_expect_assume is a preprocessor guard. Do not pass it to API calls. @@ -12672,30 +14066,171 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetDescriptorBufferOffsets2EXT)(VkCommandBuffe typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT)(VkCommandBuffer commandBuffer, const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets2KHR( VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants2KHR( VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSet2KHR( VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplate2KHR( VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsets2EXT( VkCommandBuffer commandBuffer, const VkSetDescriptorBufferOffsetsInfoEXT* pSetDescriptorBufferOffsetsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBufferEmbeddedSamplers2EXT( VkCommandBuffer commandBuffer, const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo); #endif +#endif + + +// VK_KHR_copy_memory_indirect is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_copy_memory_indirect 1 +#define VK_KHR_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 +#define VK_KHR_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_KHR_copy_memory_indirect" + +typedef enum VkAddressCopyFlagBitsKHR { + VK_ADDRESS_COPY_DEVICE_LOCAL_BIT_KHR = 0x00000001, + VK_ADDRESS_COPY_SPARSE_BIT_KHR = 0x00000002, + VK_ADDRESS_COPY_PROTECTED_BIT_KHR = 0x00000004, + VK_ADDRESS_COPY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAddressCopyFlagBitsKHR; +typedef VkFlags VkAddressCopyFlagsKHR; +typedef struct VkCopyMemoryIndirectCommandKHR { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize size; +} VkCopyMemoryIndirectCommandKHR; + +typedef struct VkCopyMemoryIndirectInfoKHR { + VkStructureType sType; + const void* pNext; + VkAddressCopyFlagsKHR srcCopyFlags; + VkAddressCopyFlagsKHR dstCopyFlags; + uint32_t copyCount; + VkStridedDeviceAddressRangeKHR copyAddressRange; +} VkCopyMemoryIndirectInfoKHR; + +typedef struct VkCopyMemoryToImageIndirectCommandKHR { + VkDeviceAddress srcAddress; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkCopyMemoryToImageIndirectCommandKHR; + +typedef struct VkCopyMemoryToImageIndirectInfoKHR { + VkStructureType sType; + const void* pNext; + VkAddressCopyFlagsKHR srcCopyFlags; + uint32_t copyCount; + VkStridedDeviceAddressRangeKHR copyAddressRange; + VkImage dstImage; + VkImageLayout dstImageLayout; + const VkImageSubresourceLayers* pImageSubresources; +} VkCopyMemoryToImageIndirectInfoKHR; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 indirectMemoryCopy; + VkBool32 indirectMemoryToImageCopy; +} VkPhysicalDeviceCopyMemoryIndirectFeaturesKHR; + +typedef struct VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR { + VkStructureType sType; + void* pNext; + VkQueueFlags supportedQueues; +} VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryIndirectKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryIndirectInfoKHR* pCopyMemoryIndirectInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageIndirectKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToImageIndirectInfoKHR* pCopyMemoryToImageIndirectInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryIndirectKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryIndirectInfoKHR* pCopyMemoryIndirectInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectKHR( + VkCommandBuffer commandBuffer, + const VkCopyMemoryToImageIndirectInfoKHR* pCopyMemoryToImageIndirectInfo); +#endif +#endif + + +// VK_KHR_video_encode_intra_refresh is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_intra_refresh 1 +#define VK_KHR_VIDEO_ENCODE_INTRA_REFRESH_SPEC_VERSION 1 +#define VK_KHR_VIDEO_ENCODE_INTRA_REFRESH_EXTENSION_NAME "VK_KHR_video_encode_intra_refresh" + +typedef enum VkVideoEncodeIntraRefreshModeFlagBitsKHR { + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_NONE_KHR = 0, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_PER_PICTURE_PARTITION_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_BASED_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_ROW_BASED_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_COLUMN_BASED_BIT_KHR = 0x00000008, + VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodeIntraRefreshModeFlagBitsKHR; +typedef VkFlags VkVideoEncodeIntraRefreshModeFlagsKHR; +typedef struct VkVideoEncodeIntraRefreshCapabilitiesKHR { + VkStructureType sType; + void* pNext; + VkVideoEncodeIntraRefreshModeFlagsKHR intraRefreshModes; + uint32_t maxIntraRefreshCycleDuration; + uint32_t maxIntraRefreshActiveReferencePictures; + VkBool32 partitionIndependentIntraRefreshRegions; + VkBool32 nonRectangularIntraRefreshRegions; +} VkVideoEncodeIntraRefreshCapabilitiesKHR; + +typedef struct VkVideoEncodeSessionIntraRefreshCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkVideoEncodeIntraRefreshModeFlagBitsKHR intraRefreshMode; +} VkVideoEncodeSessionIntraRefreshCreateInfoKHR; + +typedef struct VkVideoEncodeIntraRefreshInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t intraRefreshCycleDuration; + uint32_t intraRefreshIndex; +} VkVideoEncodeIntraRefreshInfoKHR; + +typedef struct VkVideoReferenceIntraRefreshInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t dirtyIntraRefreshRegions; +} VkVideoReferenceIntraRefreshInfoKHR; + +typedef struct VkPhysicalDeviceVideoEncodeIntraRefreshFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeIntraRefresh; +} VkPhysicalDeviceVideoEncodeIntraRefreshFeaturesKHR; + // VK_KHR_video_encode_quantization_map is a preprocessor guard. Do not pass it to API calls. @@ -12836,6 +14371,124 @@ typedef struct VkPhysicalDeviceLayeredApiVulkanPropertiesKHR { +// VK_KHR_device_fault is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_device_fault 1 +#define VK_KHR_DEVICE_FAULT_SPEC_VERSION 1 +#define VK_KHR_DEVICE_FAULT_EXTENSION_NAME "VK_KHR_device_fault" + +typedef enum VkDeviceFaultAddressTypeKHR { + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_KHR = 0, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_KHR = 1, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_KHR = 2, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_KHR = 3, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_KHR = 4, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_KHR = 5, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_KHR = 6, + VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_KHR, + VK_DEVICE_FAULT_ADDRESS_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultAddressTypeKHR; + +typedef enum VkDeviceFaultVendorBinaryHeaderVersionKHR { + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_KHR = 1, + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT = VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_KHR, + VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultVendorBinaryHeaderVersionKHR; + +typedef enum VkDeviceFaultFlagBitsKHR { + VK_DEVICE_FAULT_FLAG_DEVICE_LOST_KHR = 0x00000001, + VK_DEVICE_FAULT_FLAG_MEMORY_ADDRESS_KHR = 0x00000002, + VK_DEVICE_FAULT_FLAG_INSTRUCTION_ADDRESS_KHR = 0x00000004, + VK_DEVICE_FAULT_FLAG_VENDOR_KHR = 0x00000008, + VK_DEVICE_FAULT_FLAG_WATCHDOG_TIMEOUT_KHR = 0x00000010, + VK_DEVICE_FAULT_FLAG_OVERFLOW_KHR = 0x00000020, + VK_DEVICE_FAULT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDeviceFaultFlagBitsKHR; +typedef VkFlags VkDeviceFaultFlagsKHR; +typedef struct VkPhysicalDeviceFaultFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 deviceFault; + VkBool32 deviceFaultVendorBinary; + VkBool32 deviceFaultReportMasked; + VkBool32 deviceFaultDeviceLostOnMasked; +} VkPhysicalDeviceFaultFeaturesKHR; + +typedef struct VkPhysicalDeviceFaultPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxDeviceFaultCount; +} VkPhysicalDeviceFaultPropertiesKHR; + +typedef struct VkDeviceFaultAddressInfoKHR { + VkDeviceFaultAddressTypeKHR addressType; + VkDeviceAddress reportedAddress; + VkDeviceSize addressPrecision; +} VkDeviceFaultAddressInfoKHR; + +typedef struct VkDeviceFaultVendorInfoKHR { + char description[VK_MAX_DESCRIPTION_SIZE]; + uint64_t vendorFaultCode; + uint64_t vendorFaultData; +} VkDeviceFaultVendorInfoKHR; + +typedef struct VkDeviceFaultInfoKHR { + VkStructureType sType; + void* pNext; + VkDeviceFaultFlagsKHR flags; + uint64_t groupId; + char description[VK_MAX_DESCRIPTION_SIZE]; + VkDeviceFaultAddressInfoKHR faultAddressInfo; + VkDeviceFaultAddressInfoKHR instructionAddressInfo; + VkDeviceFaultVendorInfoKHR vendorInfo; +} VkDeviceFaultInfoKHR; + +typedef struct VkDeviceFaultDebugInfoKHR { + VkStructureType sType; + void* pNext; + uint32_t vendorBinarySize; + void* pVendorBinaryData; +} VkDeviceFaultDebugInfoKHR; + +typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneKHR { + uint32_t headerSize; + VkDeviceFaultVendorBinaryHeaderVersionKHR headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint32_t driverVersion; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + uint32_t applicationNameOffset; + uint32_t applicationVersion; + uint32_t engineNameOffset; + uint32_t engineVersion; + uint32_t apiVersion; +} VkDeviceFaultVendorBinaryHeaderVersionOneKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultReportsKHR)(VkDevice device, uint64_t timeout, uint32_t* pFaultCounts, VkDeviceFaultInfoKHR* pFaultInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultDebugInfoKHR)(VkDevice device, VkDeviceFaultDebugInfoKHR* pDebugInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultReportsKHR( + VkDevice device, + uint64_t timeout, + uint32_t* pFaultCounts, + VkDeviceFaultInfoKHR* pFaultInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultDebugInfoKHR( + VkDevice device, + VkDeviceFaultDebugInfoKHR* pDebugInfo); +#endif +#endif + + // VK_KHR_maintenance8 is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_maintenance8 1 #define VK_KHR_MAINTENANCE_8_SPEC_VERSION 1 @@ -12846,12 +14499,6 @@ typedef VkFlags64 VkAccessFlags3KHR; typedef VkFlags64 VkAccessFlagBits3KHR; static const VkAccessFlagBits3KHR VK_ACCESS_3_NONE_KHR = 0ULL; -typedef struct VkPhysicalDeviceMaintenance8FeaturesKHR { - VkStructureType sType; - void* pNext; - VkBool32 maintenance8; -} VkPhysicalDeviceMaintenance8FeaturesKHR; - typedef struct VkMemoryBarrierAccessFlags3KHR { VkStructureType sType; const void* pNext; @@ -12859,6 +14506,57 @@ typedef struct VkMemoryBarrierAccessFlags3KHR { VkAccessFlags3KHR dstAccessMask3; } VkMemoryBarrierAccessFlags3KHR; +typedef struct VkPhysicalDeviceMaintenance8FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance8; +} VkPhysicalDeviceMaintenance8FeaturesKHR; + + + +// VK_KHR_shader_fma is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_shader_fma 1 +#define VK_KHR_SHADER_FMA_SPEC_VERSION 1 +#define VK_KHR_SHADER_FMA_EXTENSION_NAME "VK_KHR_shader_fma" +typedef struct VkPhysicalDeviceShaderFmaFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 shaderFmaFloat16; + VkBool32 shaderFmaFloat32; + VkBool32 shaderFmaFloat64; +} VkPhysicalDeviceShaderFmaFeaturesKHR; + + + +// VK_KHR_maintenance9 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance9 1 +#define VK_KHR_MAINTENANCE_9_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_9_EXTENSION_NAME "VK_KHR_maintenance9" + +typedef enum VkDefaultVertexAttributeValueKHR { + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_ZERO_ZERO_ZERO_ZERO_KHR = 0, + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_ZERO_ZERO_ZERO_ONE_KHR = 1, + VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkDefaultVertexAttributeValueKHR; +typedef struct VkPhysicalDeviceMaintenance9FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance9; +} VkPhysicalDeviceMaintenance9FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance9PropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 image2DViewOf3DSparse; + VkDefaultVertexAttributeValueKHR defaultVertexAttributeValue; +} VkPhysicalDeviceMaintenance9PropertiesKHR; + +typedef struct VkQueueFamilyOwnershipTransferPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t optimalImageTransferToQueueFamilies; +} VkQueueFamilyOwnershipTransferPropertiesKHR; + // VK_KHR_video_maintenance2 is a preprocessor guard. Do not pass it to API calls. @@ -12894,6 +14592,40 @@ typedef struct VkVideoDecodeAV1InlineSessionParametersInfoKHR { +// VK_KHR_video_encode_feedback2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_video_encode_feedback2 1 +#define VK_KHR_VIDEO_ENCODE_FEEDBACK_2_SPEC_VERSION 1 +#define VK_KHR_VIDEO_ENCODE_FEEDBACK_2_EXTENSION_NAME "VK_KHR_video_encode_feedback2" + +typedef enum VkVideoEncodePerPartitionFeedbackFlagBitsKHR { + VK_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_STATUS_BIT_KHR = 0x00000001, + VK_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR = 0x00000002, + VK_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR = 0x00000004, + VK_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkVideoEncodePerPartitionFeedbackFlagBitsKHR; +typedef VkFlags VkVideoEncodePerPartitionFeedbackFlagsKHR; +typedef struct VkPhysicalDeviceVideoEncodeFeedback2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeFeedback2; +} VkPhysicalDeviceVideoEncodeFeedback2FeaturesKHR; + +typedef struct VkVideoEncodeFeedback2CapabilitiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxPerPartitionFeedbackEntries; + VkVideoEncodePerPartitionFeedbackFlagsKHR supportedPerPartitionEncodeFeedbackFlags; +} VkVideoEncodeFeedback2CapabilitiesKHR; + +typedef struct VkQueryPoolVideoEncodePerPartitionFeedbackCreateInfoKHR { + VkStructureType sType; + const void* pNext; + uint32_t maxPerPartitionFeedbackEntries; + VkVideoEncodePerPartitionFeedbackFlagsKHR perPartitionEncodeFeedbackFlags; +} VkQueryPoolVideoEncodePerPartitionFeedbackCreateInfoKHR; + + + // VK_KHR_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_depth_clamp_zero_one 1 #define VK_KHR_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION 1 @@ -12906,6 +14638,311 @@ typedef struct VkPhysicalDeviceDepthClampZeroOneFeaturesKHR { +// VK_KHR_robustness2 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_robustness2 1 +#define VK_KHR_ROBUSTNESS_2_SPEC_VERSION 1 +#define VK_KHR_ROBUSTNESS_2_EXTENSION_NAME "VK_KHR_robustness2" +typedef struct VkPhysicalDeviceRobustness2FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 robustBufferAccess2; + VkBool32 robustImageAccess2; + VkBool32 nullDescriptor; +} VkPhysicalDeviceRobustness2FeaturesKHR; + +typedef struct VkPhysicalDeviceRobustness2PropertiesKHR { + VkStructureType sType; + void* pNext; + VkDeviceSize robustStorageBufferAccessSizeAlignment; + VkDeviceSize robustUniformBufferAccessSizeAlignment; +} VkPhysicalDeviceRobustness2PropertiesKHR; + + + +// VK_KHR_present_mode_fifo_latest_ready is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_present_mode_fifo_latest_ready 1 +#define VK_KHR_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION 1 +#define VK_KHR_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME "VK_KHR_present_mode_fifo_latest_ready" +typedef struct VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 presentModeFifoLatestReady; +} VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR; + + + +// VK_KHR_opacity_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_opacity_micromap 1 +#define VK_KHR_OPACITY_MICROMAP_SPEC_VERSION 1 +#define VK_KHR_OPACITY_MICROMAP_EXTENSION_NAME "VK_KHR_opacity_micromap" + +typedef enum VkOpacityMicromapFormatKHR { + VK_OPACITY_MICROMAP_FORMAT_2_STATE_KHR = 1, + VK_OPACITY_MICROMAP_FORMAT_4_STATE_KHR = 2, + VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = VK_OPACITY_MICROMAP_FORMAT_2_STATE_KHR, + VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = VK_OPACITY_MICROMAP_FORMAT_4_STATE_KHR, + VK_OPACITY_MICROMAP_FORMAT_MAX_ENUM_KHR = 0x7FFFFFFF +} VkOpacityMicromapFormatKHR; + +typedef enum VkOpacityMicromapSpecialIndexKHR { + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_KHR = -1, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_KHR = -2, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_KHR = -3, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_KHR = -4, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_KHR, + VK_OPACITY_MICROMAP_SPECIAL_INDEX_MAX_ENUM_KHR = 0x7FFFFFFF +} VkOpacityMicromapSpecialIndexKHR; + +typedef enum VkAccelerationStructureSerializedBlockTypeKHR { + VK_ACCELERATION_STRUCTURE_SERIALIZED_BLOCK_TYPE_OPACITY_MICROMAP_KHR = 0, + VK_ACCELERATION_STRUCTURE_SERIALIZED_BLOCK_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF +} VkAccelerationStructureSerializedBlockTypeKHR; +typedef struct VkMicromapUsageKHR { + uint32_t count; + uint32_t subdivisionLevel; + VkOpacityMicromapFormatKHR format; +} VkMicromapUsageKHR; + +typedef struct VkAccelerationStructureGeometryMicromapDataKHR { + VkStructureType sType; + const void* pNext; + uint32_t usageCountsCount; + const VkMicromapUsageKHR* pUsageCounts; + const VkMicromapUsageKHR* const* ppUsageCounts; + VkDeviceAddress data; + VkDeviceAddress triangleArray; + VkDeviceSize triangleArrayStride; +} VkAccelerationStructureGeometryMicromapDataKHR; + +typedef struct VkPhysicalDeviceOpacityMicromapFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 micromap; +} VkPhysicalDeviceOpacityMicromapFeaturesKHR; + +typedef struct VkPhysicalDeviceOpacityMicromapPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t maxOpacity2StateSubdivisionLevel; + uint32_t maxOpacity4StateSubdivisionLevel; + uint32_t maxOpacityLossy4StateSubdivisionLevel; + uint64_t maxMicromapTriangles; +} VkPhysicalDeviceOpacityMicromapPropertiesKHR; + +typedef struct VkMicromapTriangleKHR { + uint32_t dataOffset; + uint16_t subdivisionLevel; + uint16_t format; +} VkMicromapTriangleKHR; + +typedef struct VkAccelerationStructureTrianglesOpacityMicromapKHR { + VkStructureType sType; + void* pNext; + VkIndexType indexType; + VkDeviceAddress indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + VkAccelerationStructureKHR micromap; +} VkAccelerationStructureTrianglesOpacityMicromapKHR; + + + +// VK_KHR_maintenance10 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance10 1 +#define VK_KHR_MAINTENANCE_10_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_10_EXTENSION_NAME "VK_KHR_maintenance10" + +typedef enum VkRenderingAttachmentFlagBitsKHR { + VK_RENDERING_ATTACHMENT_INPUT_ATTACHMENT_FEEDBACK_BIT_KHR = 0x00000001, + VK_RENDERING_ATTACHMENT_RESOLVE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_RENDERING_ATTACHMENT_RESOLVE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000004, + VK_RENDERING_ATTACHMENT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkRenderingAttachmentFlagBitsKHR; +typedef VkFlags VkRenderingAttachmentFlagsKHR; + +typedef enum VkResolveImageFlagBitsKHR { + VK_RESOLVE_IMAGE_SKIP_TRANSFER_FUNCTION_BIT_KHR = 0x00000001, + VK_RESOLVE_IMAGE_ENABLE_TRANSFER_FUNCTION_BIT_KHR = 0x00000002, + VK_RESOLVE_IMAGE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF +} VkResolveImageFlagBitsKHR; +typedef VkFlags VkResolveImageFlagsKHR; +typedef struct VkPhysicalDeviceMaintenance10FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance10; +} VkPhysicalDeviceMaintenance10FeaturesKHR; + +typedef struct VkPhysicalDeviceMaintenance10PropertiesKHR { + VkStructureType sType; + void* pNext; + VkBool32 rgba4OpaqueBlackSwizzled; + VkBool32 resolveSrgbFormatAppliesTransferFunction; + VkBool32 resolveSrgbFormatSupportsTransferFunctionControl; +} VkPhysicalDeviceMaintenance10PropertiesKHR; + +typedef struct VkRenderingEndInfoKHR { + VkStructureType sType; + const void* pNext; +} VkRenderingEndInfoKHR; + +typedef struct VkRenderingAttachmentFlagsInfoKHR { + VkStructureType sType; + const void* pNext; + VkRenderingAttachmentFlagsKHR flags; +} VkRenderingAttachmentFlagsInfoKHR; + +typedef struct VkResolveImageModeInfoKHR { + VkStructureType sType; + const void* pNext; + VkResolveImageFlagsKHR flags; + VkResolveModeFlagBits resolveMode; + VkResolveModeFlagBits stencilResolveMode; +} VkResolveImageModeInfoKHR; + +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering2KHR)(VkCommandBuffer commandBuffer, const VkRenderingEndInfoKHR* pRenderingEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering2KHR( + VkCommandBuffer commandBuffer, + const VkRenderingEndInfoKHR* pRenderingEndInfo); +#endif +#endif + + +// VK_KHR_maintenance11 is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_maintenance11 1 +#define VK_KHR_MAINTENANCE_11_SPEC_VERSION 1 +#define VK_KHR_MAINTENANCE_11_EXTENSION_NAME "VK_KHR_maintenance11" +typedef struct VkPhysicalDeviceMaintenance11FeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 maintenance11; +} VkPhysicalDeviceMaintenance11FeaturesKHR; + +typedef struct VkQueueFamilyOptimalImageTransferGranularityPropertiesKHR { + VkStructureType sType; + void* pNext; + VkExtent3D optimalImageTransferGranularity; +} VkQueueFamilyOptimalImageTransferGranularityPropertiesKHR; + + + +// VK_KHR_extended_flags is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_extended_flags 1 +#define VK_KHR_EXTENDED_FLAGS_SPEC_VERSION 1 +#define VK_KHR_EXTENDED_FLAGS_EXTENSION_NAME "VK_KHR_extended_flags" +typedef VkFlags64 VkFormatFeatureFlags4KHR; + +// Flag bits for VkFormatFeatureFlagBits4KHR +typedef VkFlags64 VkFormatFeatureFlagBits4KHR; + +typedef VkFlags64 VkImageUsageFlags2KHR; + +// Flag bits for VkImageUsageFlagBits2KHR +typedef VkFlags64 VkImageUsageFlagBits2KHR; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_TRANSFER_SRC_BIT_KHR = 0x00000001ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_TRANSFER_DST_BIT_KHR = 0x00000002ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_SAMPLED_BIT_KHR = 0x00000004ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_STORAGE_BIT_KHR = 0x00000008ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_COLOR_ATTACHMENT_BIT_KHR = 0x00000010ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 0x00000020ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_TRANSIENT_ATTACHMENT_BIT_KHR = 0x00000040ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_INPUT_ATTACHMENT_BIT_KHR = 0x00000080ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00000100ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x00000200ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_DECODE_DST_BIT_KHR = 0x00000400ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR = 0x00000800ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_DECODE_DPB_BIT_KHR = 0x00001000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR = 0x00002000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR = 0x00004000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_ENCODE_DPB_BIT_KHR = 0x00008000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x00040000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 0x00080000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_SAMPLE_WEIGHT_BIT_QCOM = 0x00100000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_SAMPLE_BLOCK_MATCH_BIT_QCOM = 0x00200000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_HOST_TRANSFER_BIT_KHR = 0x00400000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_TENSOR_ALIASING_BIT_ARM = 0x00800000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR = 0x02000000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR = 0x04000000ULL; +static const VkImageUsageFlagBits2KHR VK_IMAGE_USAGE_2_TILE_MEMORY_BIT_QCOM = 0x08000000ULL; + +typedef VkFlags64 VkImageCreateFlags2KHR; + +// Flag bits for VkImageCreateFlagBits2KHR +typedef VkFlags64 VkImageCreateFlagBits2KHR; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SPARSE_BINDING_BIT_KHR = 0x00000001ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SPARSE_RESIDENCY_BIT_KHR = 0x00000002ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SPARSE_ALIASED_BIT_KHR = 0x00000004ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_MUTABLE_FORMAT_BIT_KHR = 0x00000008ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_CUBE_COMPATIBLE_BIT_KHR = 0x00000010ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_ALIAS_SINGLE_LAYER_DESCRIPTOR_BIT_KHR = 0x00400000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 0x00000040ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_EXTENDED_USAGE_BIT_KHR = 0x00000100ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_DISJOINT_BIT_KHR = 0x00000200ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_ALIAS_BIT_KHR = 0x00000400ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_PROTECTED_BIT_KHR = 0x00000800ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_CORNER_SAMPLED_BIT_NV = 0x00002000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_SUBSAMPLED_BIT_EXT = 0x00004000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_FRAGMENT_DENSITY_MAP_OFFSET_BIT_EXT = 0x00008000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00010000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_2D_VIEW_COMPATIBLE_BIT_EXT = 0x00020000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT = 0x00040000ULL; +static const VkImageCreateFlagBits2KHR VK_IMAGE_CREATE_2_VIDEO_PROFILE_INDEPENDENT_BIT_KHR = 0x00100000ULL; + +typedef struct VkFormatProperties4KHR { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags4KHR linearTilingFeatures; + VkFormatFeatureFlags4KHR optimalTilingFeatures; + VkFormatFeatureFlags4KHR bufferFeatures; +} VkFormatProperties4KHR; + +typedef struct VkImageUsageFlags2CreateInfoKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags2KHR usage; +} VkImageUsageFlags2CreateInfoKHR; + +typedef struct VkImageCreateFlags2CreateInfoKHR { + VkStructureType sType; + void* pNext; + VkImageCreateFlags2KHR flags; +} VkImageCreateFlags2CreateInfoKHR; + +typedef struct VkImageViewUsage2CreateInfoKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags2KHR usage; +} VkImageViewUsage2CreateInfoKHR; + +typedef struct VkPhysicalDeviceExtendedFlagsFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 extendedFlags; +} VkPhysicalDeviceExtendedFlagsFeaturesKHR; + +typedef struct VkImageStencilUsage2CreateInfoKHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags2KHR stencilUsage; +} VkImageStencilUsage2CreateInfoKHR; + +typedef struct VkSharedPresentSurfaceCapabilities2KHR { + VkStructureType sType; + void* pNext; + VkImageUsageFlags2KHR sharedPresentSupportedUsageFlags; +} VkSharedPresentSurfaceCapabilities2KHR; + + + // VK_EXT_debug_report is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) @@ -12954,9 +14991,9 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT = 1000307000, VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT = 1000307001, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT = 1000366000, - // VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT is a deprecated alias + // VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT is a legacy alias VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT, - // VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT is a deprecated alias + // VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT is a legacy alias VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT, @@ -12995,17 +15032,22 @@ typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instanc typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT( VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( VkInstance instance, VkDebugReportFlagsEXT flags, @@ -13016,6 +15058,7 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT( const char* pLayerPrefix, const char* pMessage); #endif +#endif // VK_NV_glsl_shader is a preprocessor guard. Do not pass it to API calls. @@ -13102,25 +15145,35 @@ typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerEndEXT)(VkCommandBuffer commandBuff typedef void (VKAPI_PTR *PFN_vkCmdDebugMarkerInsertEXT)(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectTagEXT( VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkDebugMarkerSetObjectNameEXT( VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerBeginEXT( VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerEndEXT( VkCommandBuffer commandBuffer); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT( VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo); #endif +#endif // VK_AMD_gcn_shader is a preprocessor guard. Do not pass it to API calls. @@ -13196,6 +15249,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdEndQueryIndexedEXT)(VkCommandBuffer commandBuf typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectByteCountEXT)(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( VkCommandBuffer commandBuffer, uint32_t firstBinding, @@ -13203,34 +15257,44 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBindTransformFeedbackBuffersEXT( const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginTransformFeedbackEXT( VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndTransformFeedbackEXT( VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer, uint32_t counterBufferCount, const VkBuffer* pCounterBuffers, const VkDeviceSize* pCounterBufferOffsets); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginQueryIndexedEXT( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags, uint32_t index); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndQueryIndexedEXT( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, uint32_t index); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( VkCommandBuffer commandBuffer, uint32_t instanceCount, @@ -13240,6 +15304,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectByteCountEXT( uint32_t counterOffset, uint32_t vertexStride); #endif +#endif // VK_NVX_binary_import is a preprocessor guard. Do not pass it to API calls. @@ -13292,37 +15357,47 @@ typedef void (VKAPI_PTR *PFN_vkDestroyCuFunctionNVX)(VkDevice device, VkCuFuncti typedef void (VKAPI_PTR *PFN_vkCmdCuLaunchKernelNVX)(VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuModuleNVX( VkDevice device, const VkCuModuleCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuModuleNVX* pModule); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateCuFunctionNVX( VkDevice device, const VkCuFunctionCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCuFunctionNVX* pFunction); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyCuModuleNVX( VkDevice device, VkCuModuleNVX module, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyCuFunctionNVX( VkDevice device, VkCuFunctionNVX function, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCuLaunchKernelNVX( VkCommandBuffer commandBuffer, const VkCuLaunchInfoNVX* pLaunchInfo); #endif +#endif // VK_NVX_image_view_handle is a preprocessor guard. Do not pass it to API calls. #define VK_NVX_image_view_handle 1 -#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 3 +#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 4 #define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle" typedef struct VkImageViewHandleInfoNVX { VkStructureType sType; @@ -13342,22 +15417,36 @@ typedef struct VkImageViewAddressPropertiesNVX { typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); typedef uint64_t (VKAPI_PTR *PFN_vkGetImageViewHandle64NVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo); typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); +typedef uint64_t (VKAPI_PTR *PFN_vkGetDeviceCombinedImageSamplerIndexNVX)(VkDevice device, uint64_t imageViewIndex, uint64_t samplerIndex); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX( VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR uint64_t VKAPI_CALL vkGetImageViewHandle64NVX( VkDevice device, const VkImageViewHandleInfoNVX* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX( VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties); #endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR uint64_t VKAPI_CALL vkGetDeviceCombinedImageSamplerIndexNVX( + VkDevice device, + uint64_t imageViewIndex, + uint64_t samplerIndex); +#endif +#endif + // VK_AMD_draw_indirect_count is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_draw_indirect_count 1 @@ -13367,6 +15456,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandB typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -13375,7 +15465,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD( VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -13385,6 +15477,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD( uint32_t maxDrawCount, uint32_t stride); #endif +#endif // VK_AMD_negative_viewport_height is a preprocessor guard. Do not pass it to API calls. @@ -13449,6 +15542,7 @@ typedef struct VkShaderStatisticsInfoAMD { typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInfoAMD)(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage, VkShaderInfoTypeAMD infoType, size_t* pInfoSize, void* pInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( VkDevice device, VkPipeline pipeline, @@ -13457,6 +15551,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInfoAMD( size_t* pInfoSize, void* pInfo); #endif +#endif // VK_AMD_shader_image_load_store_lod is a preprocessor guard. Do not pass it to API calls. @@ -13514,6 +15609,7 @@ typedef struct VkExternalImageFormatPropertiesNV { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV( VkPhysicalDevice physicalDevice, VkFormat format, @@ -13524,6 +15620,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesN VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties); #endif +#endif // VK_NV_external_memory is a preprocessor guard. Do not pass it to API calls. @@ -13621,12 +15718,6 @@ typedef VkPipelineRobustnessCreateInfo VkPipelineRobustnessCreateInfoEXT; #define VK_EXT_conditional_rendering 1 #define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 2 #define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering" - -typedef enum VkConditionalRenderingFlagBitsEXT { - VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT = 0x00000001, - VK_CONDITIONAL_RENDERING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkConditionalRenderingFlagBitsEXT; -typedef VkFlags VkConditionalRenderingFlagsEXT; typedef struct VkConditionalRenderingBeginInfoEXT { VkStructureType sType; const void* pNext; @@ -13652,13 +15743,17 @@ typedef void (VKAPI_PTR *PFN_vkCmdBeginConditionalRenderingEXT)(VkCommandBuffer typedef void (VKAPI_PTR *PFN_vkCmdEndConditionalRenderingEXT)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginConditionalRenderingEXT( VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndConditionalRenderingEXT( VkCommandBuffer commandBuffer); #endif +#endif // VK_NV_clip_space_w_scaling is a preprocessor guard. Do not pass it to API calls. @@ -13681,12 +15776,14 @@ typedef struct VkPipelineViewportWScalingStateCreateInfoNV { typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings); #endif +#endif // VK_EXT_direct_mode_display is a preprocessor guard. Do not pass it to API calls. @@ -13696,10 +15793,12 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV( typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( VkPhysicalDevice physicalDevice, VkDisplayKHR display); #endif +#endif // VK_EXT_display_surface_counter is a preprocessor guard. Do not pass it to API calls. @@ -13709,7 +15808,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT( typedef enum VkSurfaceCounterFlagBitsEXT { VK_SURFACE_COUNTER_VBLANK_BIT_EXT = 0x00000001, - // VK_SURFACE_COUNTER_VBLANK_EXT is a deprecated alias + // VK_SURFACE_COUNTER_VBLANK_EXT is a legacy alias VK_SURFACE_COUNTER_VBLANK_EXT = VK_SURFACE_COUNTER_VBLANK_BIT_EXT, VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkSurfaceCounterFlagBitsEXT; @@ -13733,11 +15832,13 @@ typedef struct VkSurfaceCapabilities2EXT { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT( VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities); #endif +#endif // VK_EXT_display_control is a preprocessor guard. Do not pass it to API calls. @@ -13791,30 +15892,38 @@ typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkD typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT( VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT( VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT( VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT( VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue); #endif +#endif // VK_GOOGLE_display_timing is a preprocessor guard. Do not pass it to API calls. @@ -13849,17 +15958,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice devic typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE( VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings); #endif +#endif // VK_NV_sample_mask_override_coverage is a preprocessor guard. Do not pass it to API calls. @@ -13878,9 +15991,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE( #define VK_NV_viewport_array2 1 #define VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION 1 #define VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME "VK_NV_viewport_array2" -// VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION is a deprecated alias +// VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION is a legacy alias #define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION -// VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME is a deprecated alias +// VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME is a legacy alias #define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME @@ -13968,20 +16081,26 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEnableEXT)(VkCommandBuffer typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleModeEXT)(VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT( VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEnableEXT( VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleModeEXT( VkCommandBuffer commandBuffer, VkDiscardRectangleModeEXT discardRectangleMode); #endif +#endif // VK_EXT_conservative_rasterization is a preprocessor guard. Do not pass it to API calls. @@ -14071,12 +16190,14 @@ typedef struct VkHdrMetadataEXT { typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT( VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata); #endif +#endif // VK_IMG_relaxed_line_rasterization is a preprocessor guard. Do not pass it to API calls. @@ -14160,10 +16281,10 @@ typedef struct VkDebugUtilsMessengerCallbackDataEXT { } VkDebugUtilsMessengerCallbackDataEXT; typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageTypes, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData); + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); typedef struct VkDebugUtilsMessengerCreateInfoEXT { VkStructureType sType; @@ -14198,53 +16319,75 @@ typedef void (VKAPI_PTR *PFN_vkDestroyDebugUtilsMessengerEXT)(VkInstance instanc typedef void (VKAPI_PTR *PFN_vkSubmitDebugUtilsMessageEXT)(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectNameEXT( VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkSetDebugUtilsObjectTagEXT( VkDevice device, const VkDebugUtilsObjectTagInfoEXT* pTagInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkQueueBeginDebugUtilsLabelEXT( VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkQueueEndDebugUtilsLabelEXT( VkQueue queue); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkQueueInsertDebugUtilsLabelEXT( VkQueue queue, const VkDebugUtilsLabelEXT* pLabelInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBeginDebugUtilsLabelEXT( VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdEndDebugUtilsLabelEXT( VkCommandBuffer commandBuffer); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdInsertDebugUtilsLabelEXT( VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT( VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData); #endif +#endif // VK_EXT_sampler_filter_minmax is a preprocessor guard. Do not pass it to API calls. @@ -14265,6 +16408,656 @@ typedef VkPhysicalDeviceSamplerFilterMinmaxProperties VkPhysicalDeviceSamplerFil #define VK_AMD_GPU_SHADER_INT16_EXTENSION_NAME "VK_AMD_gpu_shader_int16" +// VK_AMD_gpa_interface is a preprocessor guard. Do not pass it to API calls. +#define VK_AMD_gpa_interface 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkGpaSessionAMD) +#define VK_AMD_GPA_INTERFACE_SPEC_VERSION 1 +#define VK_AMD_GPA_INTERFACE_EXTENSION_NAME "VK_AMD_gpa_interface" + +typedef enum VkGpaPerfBlockAMD { + VK_GPA_PERF_BLOCK_CPF_AMD = 0, + VK_GPA_PERF_BLOCK_IA_AMD = 1, + VK_GPA_PERF_BLOCK_VGT_AMD = 2, + VK_GPA_PERF_BLOCK_PA_AMD = 3, + VK_GPA_PERF_BLOCK_SC_AMD = 4, + VK_GPA_PERF_BLOCK_SPI_AMD = 5, + VK_GPA_PERF_BLOCK_SQ_AMD = 6, + VK_GPA_PERF_BLOCK_SX_AMD = 7, + VK_GPA_PERF_BLOCK_TA_AMD = 8, + VK_GPA_PERF_BLOCK_TD_AMD = 9, + VK_GPA_PERF_BLOCK_TCP_AMD = 10, + VK_GPA_PERF_BLOCK_TCC_AMD = 11, + VK_GPA_PERF_BLOCK_TCA_AMD = 12, + VK_GPA_PERF_BLOCK_DB_AMD = 13, + VK_GPA_PERF_BLOCK_CB_AMD = 14, + VK_GPA_PERF_BLOCK_GDS_AMD = 15, + VK_GPA_PERF_BLOCK_SRBM_AMD = 16, + VK_GPA_PERF_BLOCK_GRBM_AMD = 17, + VK_GPA_PERF_BLOCK_GRBM_SE_AMD = 18, + VK_GPA_PERF_BLOCK_RLC_AMD = 19, + VK_GPA_PERF_BLOCK_DMA_AMD = 20, + VK_GPA_PERF_BLOCK_MC_AMD = 21, + VK_GPA_PERF_BLOCK_CPG_AMD = 22, + VK_GPA_PERF_BLOCK_CPC_AMD = 23, + VK_GPA_PERF_BLOCK_WD_AMD = 24, + VK_GPA_PERF_BLOCK_TCS_AMD = 25, + VK_GPA_PERF_BLOCK_ATC_AMD = 26, + VK_GPA_PERF_BLOCK_ATC_L2_AMD = 27, + VK_GPA_PERF_BLOCK_MC_VM_L2_AMD = 28, + VK_GPA_PERF_BLOCK_EA_AMD = 29, + VK_GPA_PERF_BLOCK_RPB_AMD = 30, + VK_GPA_PERF_BLOCK_RMI_AMD = 31, + VK_GPA_PERF_BLOCK_UMCCH_AMD = 32, + VK_GPA_PERF_BLOCK_GE_AMD = 33, + VK_GPA_PERF_BLOCK_GL1A_AMD = 34, + VK_GPA_PERF_BLOCK_GL1C_AMD = 35, + VK_GPA_PERF_BLOCK_GL1CG_AMD = 36, + VK_GPA_PERF_BLOCK_GL2A_AMD = 37, + VK_GPA_PERF_BLOCK_GL2C_AMD = 38, + VK_GPA_PERF_BLOCK_CHA_AMD = 39, + VK_GPA_PERF_BLOCK_CHC_AMD = 40, + VK_GPA_PERF_BLOCK_CHCG_AMD = 41, + VK_GPA_PERF_BLOCK_GUS_AMD = 42, + VK_GPA_PERF_BLOCK_GCR_AMD = 43, + VK_GPA_PERF_BLOCK_PH_AMD = 44, + VK_GPA_PERF_BLOCK_UTCL1_AMD = 45, + VK_GPA_PERF_BLOCK_GE_DIST_AMD = 46, + VK_GPA_PERF_BLOCK_GE_SE_AMD = 47, + VK_GPA_PERF_BLOCK_DF_MALL_AMD = 48, + VK_GPA_PERF_BLOCK_SQ_WGP_AMD = 49, + VK_GPA_PERF_BLOCK_PC_AMD = 50, + VK_GPA_PERF_BLOCK_GL1XA_AMD = 51, + VK_GPA_PERF_BLOCK_GL1XC_AMD = 52, + VK_GPA_PERF_BLOCK_WGS_AMD = 53, + VK_GPA_PERF_BLOCK_EACPWD_AMD = 54, + VK_GPA_PERF_BLOCK_EASE_AMD = 55, + VK_GPA_PERF_BLOCK_RLCUSER_AMD = 56, + VK_GPA_PERF_BLOCK_GE1_AMD = VK_GPA_PERF_BLOCK_GE_AMD, + VK_GPA_PERF_BLOCK_RLCLOCAL_AMD = VK_GPA_PERF_BLOCK_RLCUSER_AMD, + VK_GPA_PERF_BLOCK_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaPerfBlockAMD; + +typedef enum VkGpaSampleTypeAMD { + VK_GPA_SAMPLE_TYPE_CUMULATIVE_AMD = 0, + VK_GPA_SAMPLE_TYPE_TRACE_AMD = 1, + VK_GPA_SAMPLE_TYPE_TIMING_AMD = 2, + VK_GPA_SAMPLE_TYPE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaSampleTypeAMD; + +typedef enum VkGpaDeviceClockModeAMD { + VK_GPA_DEVICE_CLOCK_MODE_DEFAULT_AMD = 0, + VK_GPA_DEVICE_CLOCK_MODE_QUERY_AMD = 1, + VK_GPA_DEVICE_CLOCK_MODE_PROFILING_AMD = 2, + VK_GPA_DEVICE_CLOCK_MODE_MIN_MEMORY_AMD = 3, + VK_GPA_DEVICE_CLOCK_MODE_MIN_ENGINE_AMD = 4, + VK_GPA_DEVICE_CLOCK_MODE_PEAK_AMD = 5, + VK_GPA_DEVICE_CLOCK_MODE_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaDeviceClockModeAMD; + +typedef enum VkGpaSqShaderStageFlagBitsAMD { + VK_GPA_SQ_SHADER_STAGE_PS_BIT_AMD = 0x00000001, + VK_GPA_SQ_SHADER_STAGE_VS_BIT_AMD = 0x00000002, + VK_GPA_SQ_SHADER_STAGE_GS_BIT_AMD = 0x00000004, + VK_GPA_SQ_SHADER_STAGE_ES_BIT_AMD = 0x00000008, + VK_GPA_SQ_SHADER_STAGE_HS_BIT_AMD = 0x00000010, + VK_GPA_SQ_SHADER_STAGE_LS_BIT_AMD = 0x00000020, + VK_GPA_SQ_SHADER_STAGE_CS_BIT_AMD = 0x00000040, + VK_GPA_SQ_SHADER_STAGE_FLAG_BITS_MAX_ENUM_AMD = 0x7FFFFFFF +} VkGpaSqShaderStageFlagBitsAMD; +typedef VkFlags VkGpaSqShaderStageFlagsAMD; +typedef VkFlags VkGpaPerfBlockPropertiesFlagsAMD; +typedef VkFlags VkPhysicalDeviceGpaPropertiesFlagsAMD; +typedef struct VkGpaPerfBlockPropertiesAMD { + VkGpaPerfBlockAMD blockType; + VkGpaPerfBlockPropertiesFlagsAMD flags; + uint32_t instanceCount; + uint32_t maxEventID; + uint32_t maxGlobalOnlyCounters; + uint32_t maxGlobalSharedCounters; + uint32_t maxStreamingCounters; +} VkGpaPerfBlockPropertiesAMD; + +typedef struct VkPhysicalDeviceGpaFeaturesAMD { + VkStructureType sType; + void* pNext; + VkBool32 perfCounters; + VkBool32 streamingPerfCounters; + VkBool32 sqThreadTracing; + VkBool32 clockModes; +} VkPhysicalDeviceGpaFeaturesAMD; + +typedef struct VkPhysicalDeviceGpaPropertiesAMD { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceGpaPropertiesFlagsAMD flags; + VkDeviceSize maxSqttSeBufferSize; + uint32_t shaderEngineCount; + uint32_t perfBlockCount; + VkGpaPerfBlockPropertiesAMD* pPerfBlocks; +} VkPhysicalDeviceGpaPropertiesAMD; + +typedef struct VkPhysicalDeviceGpaProperties2AMD { + VkStructureType sType; + void* pNext; + uint32_t revisionId; +} VkPhysicalDeviceGpaProperties2AMD; + +typedef struct VkGpaPerfCounterAMD { + VkGpaPerfBlockAMD blockType; + uint32_t blockInstance; + uint32_t eventID; +} VkGpaPerfCounterAMD; + +typedef struct VkGpaSampleBeginInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaSampleTypeAMD sampleType; + VkBool32 sampleInternalOperations; + VkBool32 cacheFlushOnCounterCollection; + VkBool32 sqShaderMaskEnable; + VkGpaSqShaderStageFlagsAMD sqShaderMask; + uint32_t perfCounterCount; + const VkGpaPerfCounterAMD* pPerfCounters; + uint32_t streamingPerfTraceSampleInterval; + VkDeviceSize perfCounterDeviceMemoryLimit; + VkBool32 sqThreadTraceEnable; + VkBool32 sqThreadTraceSuppressInstructionTokens; + VkDeviceSize sqThreadTraceDeviceMemoryLimit; + VkPipelineStageFlags timingPreSample; + VkPipelineStageFlags timingPostSample; +} VkGpaSampleBeginInfoAMD; + +typedef struct VkGpaDeviceClockModeInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaDeviceClockModeAMD clockMode; + float memoryClockRatioToPeak; + float engineClockRatioToPeak; +} VkGpaDeviceClockModeInfoAMD; + +typedef struct VkGpaDeviceGetClockInfoAMD { + VkStructureType sType; + void* pNext; + float memoryClockRatioToPeak; + float engineClockRatioToPeak; + uint32_t memoryClockFrequency; + uint32_t engineClockFrequency; +} VkGpaDeviceGetClockInfoAMD; + +typedef struct VkGpaSessionCreateInfoAMD { + VkStructureType sType; + const void* pNext; + VkGpaSessionAMD secondaryCopySource; +} VkGpaSessionCreateInfoAMD; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateGpaSessionAMD)(VkDevice device, const VkGpaSessionCreateInfoAMD* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkGpaSessionAMD* pGpaSession); +typedef void (VKAPI_PTR *PFN_vkDestroyGpaSessionAMD)(VkDevice device, VkGpaSessionAMD gpaSession, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkSetGpaDeviceClockModeAMD)(VkDevice device, VkGpaDeviceClockModeInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaDeviceClockInfoAMD)(VkDevice device, VkGpaDeviceGetClockInfoAMD* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCmdBeginGpaSessionAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkCmdEndGpaSessionAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkCmdBeginGpaSampleAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession, const VkGpaSampleBeginInfoAMD* pGpaSampleBeginInfo, uint32_t* pSampleID); +typedef void (VKAPI_PTR *PFN_vkCmdEndGpaSampleAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession, uint32_t sampleID); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaSessionStatusAMD)(VkDevice device, VkGpaSessionAMD gpaSession); +typedef VkResult (VKAPI_PTR *PFN_vkGetGpaSessionResultsAMD)(VkDevice device, VkGpaSessionAMD gpaSession, uint32_t sampleID, size_t* pSizeInBytes, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkResetGpaSessionAMD)(VkDevice device, VkGpaSessionAMD gpaSession); +typedef void (VKAPI_PTR *PFN_vkCmdCopyGpaSessionResultsAMD)(VkCommandBuffer commandBuffer, VkGpaSessionAMD gpaSession); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateGpaSessionAMD( + VkDevice device, + const VkGpaSessionCreateInfoAMD* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkGpaSessionAMD* pGpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyGpaSessionAMD( + VkDevice device, + VkGpaSessionAMD gpaSession, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetGpaDeviceClockModeAMD( + VkDevice device, + VkGpaDeviceClockModeInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaDeviceClockInfoAMD( + VkDevice device, + VkGpaDeviceGetClockInfoAMD* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdBeginGpaSessionAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdEndGpaSessionAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCmdBeginGpaSampleAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession, + const VkGpaSampleBeginInfoAMD* pGpaSampleBeginInfo, + uint32_t* pSampleID); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndGpaSampleAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession, + uint32_t sampleID); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaSessionStatusAMD( + VkDevice device, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetGpaSessionResultsAMD( + VkDevice device, + VkGpaSessionAMD gpaSession, + uint32_t sampleID, + size_t* pSizeInBytes, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkResetGpaSessionAMD( + VkDevice device, + VkGpaSessionAMD gpaSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyGpaSessionResultsAMD( + VkCommandBuffer commandBuffer, + VkGpaSessionAMD gpaSession); +#endif +#endif + + +// VK_EXT_descriptor_heap is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_descriptor_heap 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkTensorARM) +#define VK_EXT_DESCRIPTOR_HEAP_SPEC_VERSION 1 +#define VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME "VK_EXT_descriptor_heap" + +typedef enum VkDescriptorMappingSourceEXT { + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT = 0, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT = 1, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_EXT = 2, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_INDIRECT_INDEX_ARRAY_EXT = 3, + VK_DESCRIPTOR_MAPPING_SOURCE_RESOURCE_HEAP_DATA_EXT = 4, + VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT = 5, + VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_ADDRESS_EXT = 6, + VK_DESCRIPTOR_MAPPING_SOURCE_INDIRECT_ADDRESS_EXT = 7, + VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_SHADER_RECORD_INDEX_EXT = 8, + VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_DATA_EXT = 9, + VK_DESCRIPTOR_MAPPING_SOURCE_SHADER_RECORD_ADDRESS_EXT = 10, + VK_DESCRIPTOR_MAPPING_SOURCE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkDescriptorMappingSourceEXT; +typedef VkFlags64 VkTensorViewCreateFlagsARM; + +// Flag bits for VkTensorViewCreateFlagBitsARM +typedef VkFlags64 VkTensorViewCreateFlagBitsARM; +static const VkTensorViewCreateFlagBitsARM VK_TENSOR_VIEW_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM = 0x00000001ULL; + + +typedef enum VkSpirvResourceTypeFlagBitsEXT { + VK_SPIRV_RESOURCE_TYPE_ALL_EXT = 0x7FFFFFFF, + VK_SPIRV_RESOURCE_TYPE_SAMPLER_BIT_EXT = 0x00000001, + VK_SPIRV_RESOURCE_TYPE_SAMPLED_IMAGE_BIT_EXT = 0x00000002, + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_IMAGE_BIT_EXT = 0x00000004, + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_IMAGE_BIT_EXT = 0x00000008, + VK_SPIRV_RESOURCE_TYPE_COMBINED_SAMPLED_IMAGE_BIT_EXT = 0x00000010, + VK_SPIRV_RESOURCE_TYPE_UNIFORM_BUFFER_BIT_EXT = 0x00000020, + VK_SPIRV_RESOURCE_TYPE_READ_ONLY_STORAGE_BUFFER_BIT_EXT = 0x00000040, + VK_SPIRV_RESOURCE_TYPE_READ_WRITE_STORAGE_BUFFER_BIT_EXT = 0x00000080, + VK_SPIRV_RESOURCE_TYPE_ACCELERATION_STRUCTURE_BIT_EXT = 0x00000100, + VK_SPIRV_RESOURCE_TYPE_TENSOR_BIT_ARM = 0x00000200, + VK_SPIRV_RESOURCE_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkSpirvResourceTypeFlagBitsEXT; +typedef VkFlags VkSpirvResourceTypeFlagsEXT; +typedef struct VkHostAddressRangeEXT { + void* address; + size_t size; +} VkHostAddressRangeEXT; + +typedef struct VkHostAddressRangeConstEXT { + const void* address; + size_t size; +} VkHostAddressRangeConstEXT; + +typedef VkDeviceAddressRangeKHR VkDeviceAddressRangeEXT; + +typedef struct VkTexelBufferDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + VkFormat format; + VkDeviceAddressRangeEXT addressRange; +} VkTexelBufferDescriptorInfoEXT; + +typedef struct VkImageDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + const VkImageViewCreateInfo* pView; + VkImageLayout layout; +} VkImageDescriptorInfoEXT; + +typedef struct VkTensorViewCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewCreateFlagsARM flags; + VkTensorARM tensor; + VkFormat format; +} VkTensorViewCreateInfoARM; + +typedef union VkResourceDescriptorDataEXT { + const VkImageDescriptorInfoEXT* pImage; + const VkTexelBufferDescriptorInfoEXT* pTexelBuffer; + const VkDeviceAddressRangeEXT* pAddressRange; + const VkTensorViewCreateInfoARM* pTensorARM; +} VkResourceDescriptorDataEXT; + +typedef struct VkResourceDescriptorInfoEXT { + VkStructureType sType; + const void* pNext; + VkDescriptorType type; + VkResourceDescriptorDataEXT data; +} VkResourceDescriptorInfoEXT; + +typedef struct VkBindHeapInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceAddressRangeEXT heapRange; + VkDeviceSize reservedRangeOffset; + VkDeviceSize reservedRangeSize; +} VkBindHeapInfoEXT; + +typedef struct VkPushDataInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t offset; + VkHostAddressRangeConstEXT data; +} VkPushDataInfoEXT; + +typedef struct VkDescriptorMappingSourceConstantOffsetEXT { + uint32_t heapOffset; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + uint32_t samplerHeapOffset; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceConstantOffsetEXT; + +typedef struct VkDescriptorMappingSourcePushIndexEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourcePushIndexEXT; + +typedef struct VkDescriptorMappingSourceIndirectIndexEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t addressOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerAddressOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceIndirectIndexEXT; + +typedef struct VkDescriptorMappingSourceHeapDataEXT { + uint32_t heapOffset; + uint32_t pushOffset; +} VkDescriptorMappingSourceHeapDataEXT; + +typedef struct VkDescriptorMappingSourceIndirectAddressEXT { + uint32_t pushOffset; + uint32_t addressOffset; +} VkDescriptorMappingSourceIndirectAddressEXT; + +typedef struct VkDescriptorMappingSourceShaderRecordIndexEXT { + uint32_t heapOffset; + uint32_t shaderRecordOffset; + uint32_t heapIndexStride; + uint32_t heapArrayStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerShaderRecordOffset; + uint32_t samplerHeapIndexStride; + uint32_t samplerHeapArrayStride; +} VkDescriptorMappingSourceShaderRecordIndexEXT; + +typedef struct VkDescriptorMappingSourceIndirectIndexArrayEXT { + uint32_t heapOffset; + uint32_t pushOffset; + uint32_t addressOffset; + uint32_t heapIndexStride; + const VkSamplerCreateInfo* pEmbeddedSampler; + VkBool32 useCombinedImageSamplerIndex; + uint32_t samplerHeapOffset; + uint32_t samplerPushOffset; + uint32_t samplerAddressOffset; + uint32_t samplerHeapIndexStride; +} VkDescriptorMappingSourceIndirectIndexArrayEXT; + +typedef union VkDescriptorMappingSourceDataEXT { + VkDescriptorMappingSourceConstantOffsetEXT constantOffset; + VkDescriptorMappingSourcePushIndexEXT pushIndex; + VkDescriptorMappingSourceIndirectIndexEXT indirectIndex; + VkDescriptorMappingSourceIndirectIndexArrayEXT indirectIndexArray; + VkDescriptorMappingSourceHeapDataEXT heapData; + uint32_t pushDataOffset; + uint32_t pushAddressOffset; + VkDescriptorMappingSourceIndirectAddressEXT indirectAddress; + VkDescriptorMappingSourceShaderRecordIndexEXT shaderRecordIndex; + uint32_t shaderRecordDataOffset; + uint32_t shaderRecordAddressOffset; +} VkDescriptorMappingSourceDataEXT; + +typedef struct VkDescriptorSetAndBindingMappingEXT { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSet; + uint32_t firstBinding; + uint32_t bindingCount; + VkSpirvResourceTypeFlagsEXT resourceMask; + VkDescriptorMappingSourceEXT source; + VkDescriptorMappingSourceDataEXT sourceData; +} VkDescriptorSetAndBindingMappingEXT; + +typedef struct VkShaderDescriptorSetAndBindingMappingInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t mappingCount; + const VkDescriptorSetAndBindingMappingEXT* pMappings; +} VkShaderDescriptorSetAndBindingMappingInfoEXT; + +typedef struct VkOpaqueCaptureDataCreateInfoEXT { + VkStructureType sType; + const void* pNext; + const VkHostAddressRangeConstEXT* pData; +} VkOpaqueCaptureDataCreateInfoEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 descriptorHeap; + VkBool32 descriptorHeapCaptureReplay; +} VkPhysicalDeviceDescriptorHeapFeaturesEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapPropertiesEXT { + VkStructureType sType; + void* pNext; + VkDeviceSize samplerHeapAlignment; + VkDeviceSize resourceHeapAlignment; + VkDeviceSize maxSamplerHeapSize; + VkDeviceSize maxResourceHeapSize; + VkDeviceSize minSamplerHeapReservedRange; + VkDeviceSize minSamplerHeapReservedRangeWithEmbedded; + VkDeviceSize minResourceHeapReservedRange; + VkDeviceSize samplerDescriptorSize; + VkDeviceSize imageDescriptorSize; + VkDeviceSize bufferDescriptorSize; + VkDeviceSize samplerDescriptorAlignment; + VkDeviceSize imageDescriptorAlignment; + VkDeviceSize bufferDescriptorAlignment; + VkDeviceSize maxPushDataSize; + size_t imageCaptureReplayOpaqueDataSize; + uint32_t maxDescriptorHeapEmbeddedSamplers; + uint32_t samplerYcbcrConversionCount; + VkBool32 sparseDescriptorHeaps; + VkBool32 protectedDescriptorHeaps; +} VkPhysicalDeviceDescriptorHeapPropertiesEXT; + +typedef struct VkCommandBufferInheritanceDescriptorHeapInfoEXT { + VkStructureType sType; + const void* pNext; + const VkBindHeapInfoEXT* pSamplerHeapBindInfo; + const VkBindHeapInfoEXT* pResourceHeapBindInfo; +} VkCommandBufferInheritanceDescriptorHeapInfoEXT; + +typedef struct VkSamplerCustomBorderColorIndexCreateInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t index; +} VkSamplerCustomBorderColorIndexCreateInfoEXT; + +typedef struct VkSamplerCustomBorderColorCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkClearColorValue customBorderColor; + VkFormat format; +} VkSamplerCustomBorderColorCreateInfoEXT; + +typedef struct VkIndirectCommandsLayoutPushDataTokenNV { + VkStructureType sType; + const void* pNext; + uint32_t pushDataOffset; + uint32_t pushDataSize; +} VkIndirectCommandsLayoutPushDataTokenNV; + +typedef struct VkSubsampledImageFormatPropertiesEXT { + VkStructureType sType; + const void* pNext; + uint32_t subsampledImageDescriptorCount; +} VkSubsampledImageFormatPropertiesEXT; + +typedef struct VkPhysicalDeviceDescriptorHeapTensorPropertiesARM { + VkStructureType sType; + void* pNext; + VkDeviceSize tensorDescriptorSize; + VkDeviceSize tensorDescriptorAlignment; + size_t tensorCaptureReplayOpaqueDataSize; +} VkPhysicalDeviceDescriptorHeapTensorPropertiesARM; + +typedef VkResult (VKAPI_PTR *PFN_vkWriteSamplerDescriptorsEXT)(VkDevice device, uint32_t samplerCount, const VkSamplerCreateInfo* pSamplers, const VkHostAddressRangeEXT* pDescriptors); +typedef VkResult (VKAPI_PTR *PFN_vkWriteResourceDescriptorsEXT)(VkDevice device, uint32_t resourceCount, const VkResourceDescriptorInfoEXT* pResources, const VkHostAddressRangeEXT* pDescriptors); +typedef void (VKAPI_PTR *PFN_vkCmdBindSamplerHeapEXT)(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBindResourceHeapEXT)(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo); +typedef void (VKAPI_PTR *PFN_vkCmdPushDataEXT)(VkCommandBuffer commandBuffer, const VkPushDataInfoEXT* pPushDataInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetImageOpaqueCaptureDataEXT)(VkDevice device, uint32_t imageCount, const VkImage* pImages, VkHostAddressRangeEXT* pDatas); +typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetPhysicalDeviceDescriptorSizeEXT)(VkPhysicalDevice physicalDevice, VkDescriptorType descriptorType); +typedef VkResult (VKAPI_PTR *PFN_vkRegisterCustomBorderColorEXT)(VkDevice device, const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor, VkBool32 requestIndex, uint32_t* pIndex); +typedef void (VKAPI_PTR *PFN_vkUnregisterCustomBorderColorEXT)(VkDevice device, uint32_t index); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorOpaqueCaptureDataARM)(VkDevice device, uint32_t tensorCount, const VkTensorARM* pTensors, VkHostAddressRangeEXT* pDatas); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteSamplerDescriptorsEXT( + VkDevice device, + uint32_t samplerCount, + const VkSamplerCreateInfo* pSamplers, + const VkHostAddressRangeEXT* pDescriptors); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkWriteResourceDescriptorsEXT( + VkDevice device, + uint32_t resourceCount, + const VkResourceDescriptorInfoEXT* pResources, + const VkHostAddressRangeEXT* pDescriptors); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindSamplerHeapEXT( + VkCommandBuffer commandBuffer, + const VkBindHeapInfoEXT* pBindInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindResourceHeapEXT( + VkCommandBuffer commandBuffer, + const VkBindHeapInfoEXT* pBindInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdPushDataEXT( + VkCommandBuffer commandBuffer, + const VkPushDataInfoEXT* pPushDataInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetImageOpaqueCaptureDataEXT( + VkDevice device, + uint32_t imageCount, + const VkImage* pImages, + VkHostAddressRangeEXT* pDatas); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetPhysicalDeviceDescriptorSizeEXT( + VkPhysicalDevice physicalDevice, + VkDescriptorType descriptorType); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkRegisterCustomBorderColorEXT( + VkDevice device, + const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor, + VkBool32 requestIndex, + uint32_t* pIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkUnregisterCustomBorderColorEXT( + VkDevice device, + uint32_t index); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorOpaqueCaptureDataARM( + VkDevice device, + uint32_t tensorCount, + const VkTensorARM* pTensors, + VkHostAddressRangeEXT* pDatas); +#endif +#endif + + // VK_AMD_mixed_attachment_samples is a preprocessor guard. Do not pass it to API calls. #define VK_AMD_mixed_attachment_samples 1 #define VK_AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION 1 @@ -14369,15 +17162,19 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetSampleLocationsEXT)(VkCommandBuffer command typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT)(VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEXT( VkCommandBuffer commandBuffer, const VkSampleLocationsInfoEXT* pSampleLocationsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMultisamplePropertiesEXT( VkPhysicalDevice physicalDevice, VkSampleCountFlagBits samples, VkMultisamplePropertiesEXT* pMultisampleProperties); #endif +#endif // VK_EXT_blend_operation_advanced is a preprocessor guard. Do not pass it to API calls. @@ -14554,11 +17351,13 @@ typedef struct VkDrmFormatModifierPropertiesList2EXT { typedef VkResult (VKAPI_PTR *PFN_vkGetImageDrmFormatModifierPropertiesEXT)(VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetImageDrmFormatModifierPropertiesEXT( VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties); #endif +#endif // VK_EXT_validation_cache is a preprocessor guard. Do not pass it to API calls. @@ -14592,29 +17391,37 @@ typedef VkResult (VKAPI_PTR *PFN_vkMergeValidationCachesEXT)(VkDevice device, Vk typedef VkResult (VKAPI_PTR *PFN_vkGetValidationCacheDataEXT)(VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateValidationCacheEXT( VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyValidationCacheEXT( VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkMergeValidationCachesEXT( VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetValidationCacheDataEXT( VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData); #endif +#endif // VK_EXT_descriptor_indexing is a preprocessor guard. Do not pass it to API calls. @@ -14725,23 +17532,29 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuff typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV( VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV( VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders); #endif +#endif // VK_NV_ray_tracing is a preprocessor guard. Do not pass it to API calls. @@ -14770,21 +17583,16 @@ typedef enum VkGeometryTypeKHR { VK_GEOMETRY_TYPE_INSTANCES_KHR = 2, VK_GEOMETRY_TYPE_SPHERES_NV = 1000429004, VK_GEOMETRY_TYPE_LINEAR_SWEPT_SPHERES_NV = 1000429005, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_GEOMETRY_TYPE_DENSE_GEOMETRY_FORMAT_TRIANGLES_AMDX = 1000478000, +#endif + VK_GEOMETRY_TYPE_MICROMAP_KHR = 1000623000, VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR, VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF } VkGeometryTypeKHR; typedef VkGeometryTypeKHR VkGeometryTypeNV; - -typedef enum VkAccelerationStructureTypeKHR { - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1, - VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR = 2, - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, - VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, - VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureTypeKHR; typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV; @@ -14825,13 +17633,19 @@ typedef enum VkGeometryInstanceFlagBitsKHR { VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR = 0x00000002, VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004, VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008, - VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = 0x00000010, - VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000020, + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_KHR = 0x00000010, + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_KHR = 0x00000020, VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR, VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR, VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR, VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR, VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR, + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_EXT = VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_KHR, + // VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT is a legacy alias + VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT = VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_BIT_EXT, + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_EXT = VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_KHR, + // VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT is a legacy alias + VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_EXT = VK_GEOMETRY_INSTANCE_DISABLE_OPACITY_MICROMAPS_BIT_EXT, VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkGeometryInstanceFlagBitsKHR; typedef VkFlags VkGeometryInstanceFlagsKHR; @@ -14847,25 +17661,41 @@ typedef enum VkBuildAccelerationStructureFlagBitsKHR { VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008, VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010, VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV = 0x00000020, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 0x00000040, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 0x00000080, - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 0x00000100, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_BIT_EXT = 0x00000100, #ifdef VK_ENABLE_BETA_EXTENSIONS - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = 0x00000200, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_BIT_NV = 0x00000200, #endif - VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = 0x00000800, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_BIT_KHR = 0x00000800, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_CLUSTER_OPACITY_MICROMAPS_BIT_NV = 0x00001000, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_KHR = 0x00000040, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_KHR = 0x00000080, + VK_BUILD_ACCELERATION_STRUCTURE_MICROMAP_LOSSY_BIT_KHR = 0x00000400, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_KHR, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_BIT_EXT, + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_KHR, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISABLE_OPACITY_MICROMAPS_BIT_EXT, + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_DATA_UPDATE_BIT_EXT, +#ifdef VK_ENABLE_BETA_EXTENSIONS + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_BIT_NV, +#endif + // VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR is a legacy alias + VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_KHR = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DATA_ACCESS_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkBuildAccelerationStructureFlagBitsKHR; typedef VkFlags VkBuildAccelerationStructureFlagsKHR; -typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; - typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV; +typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV; + typedef struct VkRayTracingShaderGroupCreateInfoNV { VkStructureType sType; const void* pNext; @@ -14929,13 +17759,13 @@ typedef struct VkGeometryNV { } VkGeometryNV; typedef struct VkAccelerationStructureInfoNV { - VkStructureType sType; - const void* pNext; - VkAccelerationStructureTypeNV type; - VkBuildAccelerationStructureFlagsNV flags; - uint32_t instanceCount; - uint32_t geometryCount; - const VkGeometryNV* pGeometries; + VkStructureType sType; + const void* pNext; + VkAccelerationStructureTypeNV type; + VkBuildAccelerationStructureFlagsKHR flags; + uint32_t instanceCount; + uint32_t geometryCount; + const VkGeometryNV* pGeometries; } VkAccelerationStructureInfoNV; typedef struct VkAccelerationStructureCreateInfoNV { @@ -15012,7 +17842,7 @@ typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV; typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); @@ -15025,27 +17855,36 @@ typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCom typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNV( VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV( VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements); + VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, @@ -15056,13 +17895,17 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV( VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeKHR mode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, @@ -15079,7 +17922,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV( uint32_t width, uint32_t height, uint32_t depth); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( VkDevice device, VkPipelineCache pipelineCache, @@ -15087,7 +17932,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesNV( const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( VkDevice device, VkPipeline pipeline, @@ -15095,7 +17942,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR( uint32_t groupCount, size_t dataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( VkDevice device, VkPipeline pipeline, @@ -15103,13 +17952,17 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV( uint32_t groupCount, size_t dataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, @@ -15117,12 +17970,15 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV( VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNV( VkDevice device, VkPipeline pipeline, uint32_t shader); #endif +#endif // VK_NV_representative_fragment_test is a preprocessor guard. Do not pass it to API calls. @@ -15168,6 +18024,30 @@ typedef struct VkFilterCubicImageViewImageFormatPropertiesEXT { #define VK_QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME "VK_QCOM_render_pass_shader_resolve" +// VK_QCOM_cooperative_matrix_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_cooperative_matrix_conversion 1 +#define VK_QCOM_COOPERATIVE_MATRIX_CONVERSION_SPEC_VERSION 1 +#define VK_QCOM_COOPERATIVE_MATRIX_CONVERSION_EXTENSION_NAME "VK_QCOM_cooperative_matrix_conversion" +typedef struct VkPhysicalDeviceCooperativeMatrixConversionFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrixConversion; +} VkPhysicalDeviceCooperativeMatrixConversionFeaturesQCOM; + + + +// VK_QCOM_elapsed_timer_query is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_elapsed_timer_query 1 +#define VK_QCOM_ELAPSED_TIMER_QUERY_SPEC_VERSION 1 +#define VK_QCOM_ELAPSED_TIMER_QUERY_EXTENSION_NAME "VK_QCOM_elapsed_timer_query" +typedef struct VkPhysicalDeviceElapsedTimerQueryFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 elapsedTimerQuery; +} VkPhysicalDeviceElapsedTimerQueryFeaturesQCOM; + + + // VK_EXT_global_priority is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_global_priority 1 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2 @@ -15204,12 +18084,14 @@ typedef struct VkPhysicalDeviceExternalMemoryHostPropertiesEXT { typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostPointerPropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHostPointer, VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties); #endif +#endif // VK_AMD_buffer_marker is a preprocessor guard. Do not pass it to API calls. @@ -15220,13 +18102,16 @@ typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarkerAMD)(VkCommandBuffer commandB typedef void (VKAPI_PTR *PFN_vkCmdWriteBufferMarker2AMD)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarkerAMD( VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, @@ -15234,6 +18119,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteBufferMarker2AMD( VkDeviceSize dstOffset, uint32_t marker); #endif +#endif // VK_AMD_pipeline_compiler_control is a preprocessor guard. Do not pass it to API calls. @@ -15265,11 +18151,14 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT) typedef VkResult (VKAPI_PTR *PFN_vkGetCalibratedTimestampsEXT)(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoKHR* pTimestampInfos, uint64_t* pTimestamps, uint64_t* pMaxDeviation); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCalibrateableTimeDomainsEXT( VkPhysicalDevice physicalDevice, uint32_t* pTimeDomainCount, VkTimeDomainKHR* pTimeDomains); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( VkDevice device, uint32_t timestampCount, @@ -15277,6 +18166,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetCalibratedTimestampsEXT( uint64_t* pTimestamps, uint64_t* pMaxDeviation); #endif +#endif // VK_AMD_shader_core_properties is a preprocessor guard. Do not pass it to API calls. @@ -15408,18 +18298,23 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer comma typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV( VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -15429,6 +18324,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV( uint32_t maxDrawCount, uint32_t stride); #endif +#endif // VK_NV_fragment_shader_barycentric is a preprocessor guard. Do not pass it to API calls. @@ -15472,18 +18368,22 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorEnableNV)(VkCommandBuffer c typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorEnableNV( VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkBool32* pExclusiveScissorEnables); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV( VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors); #endif +#endif // VK_NV_device_diagnostic_checkpoints is a preprocessor guard. Do not pass it to API calls. @@ -15521,20 +18421,181 @@ typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointDataNV)(VkQueue queue, uint32_t typedef void (VKAPI_PTR *PFN_vkGetQueueCheckpointData2NV)(VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCheckpointNV( VkCommandBuffer commandBuffer, const void* pCheckpointMarker); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointDataNV( VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointDataNV* pCheckpointData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetQueueCheckpointData2NV( VkQueue queue, uint32_t* pCheckpointDataCount, VkCheckpointData2NV* pCheckpointData); #endif +#endif + + +// VK_EXT_present_timing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_present_timing 1 +#define VK_EXT_PRESENT_TIMING_SPEC_VERSION 3 +#define VK_EXT_PRESENT_TIMING_EXTENSION_NAME "VK_EXT_present_timing" + +typedef enum VkPresentStageFlagBitsEXT { + VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT = 0x00000001, + VK_PRESENT_STAGE_REQUEST_DEQUEUED_BIT_EXT = 0x00000002, + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT = 0x00000004, + VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT = 0x00000008, + VK_PRESENT_STAGE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentStageFlagBitsEXT; +typedef VkFlags VkPresentStageFlagsEXT; + +typedef enum VkPastPresentationTimingFlagBitsEXT { + VK_PAST_PRESENTATION_TIMING_ALLOW_PARTIAL_RESULTS_BIT_EXT = 0x00000001, + VK_PAST_PRESENTATION_TIMING_ALLOW_OUT_OF_ORDER_RESULTS_BIT_EXT = 0x00000002, + VK_PAST_PRESENTATION_TIMING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPastPresentationTimingFlagBitsEXT; +typedef VkFlags VkPastPresentationTimingFlagsEXT; + +typedef enum VkPresentTimingInfoFlagBitsEXT { + VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT = 0x00000001, + VK_PRESENT_TIMING_INFO_PRESENT_AT_NEAREST_REFRESH_CYCLE_BIT_EXT = 0x00000002, + VK_PRESENT_TIMING_INFO_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkPresentTimingInfoFlagBitsEXT; +typedef VkFlags VkPresentTimingInfoFlagsEXT; +typedef struct VkPhysicalDevicePresentTimingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 presentTiming; + VkBool32 presentAtAbsoluteTime; + VkBool32 presentAtRelativeTime; +} VkPhysicalDevicePresentTimingFeaturesEXT; + +typedef struct VkPresentTimingSurfaceCapabilitiesEXT { + VkStructureType sType; + void* pNext; + VkBool32 presentTimingSupported; + VkBool32 presentAtAbsoluteTimeSupported; + VkBool32 presentAtRelativeTimeSupported; + VkPresentStageFlagsEXT presentStageQueries; +} VkPresentTimingSurfaceCapabilitiesEXT; + +typedef struct VkSwapchainCalibratedTimestampInfoEXT { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; + VkPresentStageFlagsEXT presentStage; + uint64_t timeDomainId; +} VkSwapchainCalibratedTimestampInfoEXT; + +typedef struct VkSwapchainTimingPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t refreshDuration; + uint64_t refreshInterval; +} VkSwapchainTimingPropertiesEXT; + +typedef struct VkSwapchainTimeDomainPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t timeDomainCount; + VkTimeDomainKHR* pTimeDomains; + uint64_t* pTimeDomainIds; +} VkSwapchainTimeDomainPropertiesEXT; + +typedef struct VkPastPresentationTimingInfoEXT { + VkStructureType sType; + const void* pNext; + VkPastPresentationTimingFlagsEXT flags; + VkSwapchainKHR swapchain; +} VkPastPresentationTimingInfoEXT; + +typedef struct VkPresentStageTimeEXT { + VkPresentStageFlagsEXT stage; + uint64_t time; +} VkPresentStageTimeEXT; + +typedef struct VkPastPresentationTimingEXT { + VkStructureType sType; + void* pNext; + uint64_t presentId; + uint64_t targetTime; + uint32_t presentStageCount; + VkPresentStageTimeEXT* pPresentStages; + VkTimeDomainKHR timeDomain; + uint64_t timeDomainId; + VkBool32 reportComplete; +} VkPastPresentationTimingEXT; + +typedef struct VkPastPresentationTimingPropertiesEXT { + VkStructureType sType; + void* pNext; + uint64_t timingPropertiesCounter; + uint64_t timeDomainsCounter; + uint32_t presentationTimingCount; + VkPastPresentationTimingEXT* pPresentationTimings; +} VkPastPresentationTimingPropertiesEXT; + +typedef struct VkPresentTimingInfoEXT { + VkStructureType sType; + const void* pNext; + VkPresentTimingInfoFlagsEXT flags; + uint64_t targetTime; + uint64_t timeDomainId; + VkPresentStageFlagsEXT presentStageQueries; + VkPresentStageFlagsEXT targetTimeDomainPresentStage; +} VkPresentTimingInfoEXT; + +typedef struct VkPresentTimingsInfoEXT { + VkStructureType sType; + const void* pNext; + uint32_t swapchainCount; + const VkPresentTimingInfoEXT* pTimingInfos; +} VkPresentTimingsInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkSetSwapchainPresentTimingQueueSizeEXT)(VkDevice device, VkSwapchainKHR swapchain, uint32_t size); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainTimingPropertiesEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties, uint64_t* pSwapchainTimingPropertiesCounter); +typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainTimeDomainPropertiesEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties, uint64_t* pTimeDomainsCounter); +typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingEXT)(VkDevice device, const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo, VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkSetSwapchainPresentTimingQueueSizeEXT( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t size); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainTimingPropertiesEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties, + uint64_t* pSwapchainTimingPropertiesCounter); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainTimeDomainPropertiesEXT( + VkDevice device, + VkSwapchainKHR swapchain, + VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties, + uint64_t* pTimeDomainsCounter); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingEXT( + VkDevice device, + const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo, + VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties); +#endif +#endif // VK_INTEL_shader_integer_functions2 is a preprocessor guard. Do not pass it to API calls. @@ -15649,43 +18710,61 @@ typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerformanceConfigurationINTEL)(VkQueu typedef VkResult (VKAPI_PTR *PFN_vkGetPerformanceParameterINTEL)(VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkInitializePerformanceApiINTEL( VkDevice device, const VkInitializePerformanceApiInfoINTEL* pInitializeInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkUninitializePerformanceApiINTEL( VkDevice device); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceMarkerINTEL( VkCommandBuffer commandBuffer, const VkPerformanceMarkerInfoINTEL* pMarkerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceStreamMarkerINTEL( VkCommandBuffer commandBuffer, const VkPerformanceStreamMarkerInfoINTEL* pMarkerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCmdSetPerformanceOverrideINTEL( VkCommandBuffer commandBuffer, const VkPerformanceOverrideInfoINTEL* pOverrideInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquirePerformanceConfigurationINTEL( VkDevice device, const VkPerformanceConfigurationAcquireInfoINTEL* pAcquireInfo, VkPerformanceConfigurationINTEL* pConfiguration); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkReleasePerformanceConfigurationINTEL( VkDevice device, VkPerformanceConfigurationINTEL configuration); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerformanceConfigurationINTEL( VkQueue queue, VkPerformanceConfigurationINTEL configuration); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPerformanceParameterINTEL( VkDevice device, VkPerformanceParameterTypeINTEL parameter, VkPerformanceValueINTEL* pValue); #endif +#endif // VK_EXT_pci_bus_info is a preprocessor guard. Do not pass it to API calls. @@ -15722,16 +18801,18 @@ typedef struct VkSwapchainDisplayNativeHdrCreateInfoAMD { typedef void (VKAPI_PTR *PFN_vkSetLocalDimmingAMD)(VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkSetLocalDimmingAMD( VkDevice device, VkSwapchainKHR swapChain, VkBool32 localDimmingEnable); #endif +#endif // VK_EXT_fragment_density_map is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_fragment_density_map 1 -#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 2 +#define VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION 3 #define VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME "VK_EXT_fragment_density_map" typedef struct VkPhysicalDeviceFragmentDensityMapFeaturesEXT { VkStructureType sType; @@ -15776,9 +18857,9 @@ typedef VkPhysicalDeviceScalarBlockLayoutFeatures VkPhysicalDeviceScalarBlockLay #define VK_GOOGLE_hlsl_functionality1 1 #define VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION 1 #define VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME "VK_GOOGLE_hlsl_functionality1" -// VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION is a deprecated alias +// VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION is a legacy alias #define VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION -// VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME is a deprecated alias +// VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME is a legacy alias #define VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME @@ -15911,10 +18992,12 @@ typedef struct VkBufferDeviceAddressCreateInfoEXT { typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetBufferDeviceAddressEXT)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetBufferDeviceAddressEXT( VkDevice device, const VkBufferDeviceAddressInfo* pInfo); #endif +#endif // VK_EXT_tooling_info is a preprocessor guard. Do not pass it to API calls. @@ -15930,11 +19013,13 @@ typedef VkPhysicalDeviceToolProperties VkPhysicalDeviceToolPropertiesEXT; typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceToolPropertiesEXT)(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceToolPropertiesEXT( VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties); #endif +#endif // VK_EXT_separate_stencil_usage is a preprocessor guard. Do not pass it to API calls. @@ -16018,11 +19103,13 @@ typedef struct VkPhysicalDeviceCooperativeMatrixPropertiesNV { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties); #endif +#endif // VK_NV_coverage_reduction_mode is a preprocessor guard. Do not pass it to API calls. @@ -16061,11 +19148,13 @@ typedef struct VkFramebufferMixedSamplesCombinationNV { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV)(VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV( VkPhysicalDevice physicalDevice, uint32_t* pCombinationCount, VkFramebufferMixedSamplesCombinationNV* pCombinations); #endif +#endif // VK_EXT_fragment_shader_interlock is a preprocessor guard. Do not pass it to API calls. @@ -16140,12 +19229,14 @@ typedef struct VkHeadlessSurfaceCreateInfoEXT { typedef VkResult (VKAPI_PTR *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT( VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #endif +#endif // VK_EXT_line_rasterization is a preprocessor guard. Do not pass it to API calls. @@ -16163,11 +19254,13 @@ typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineSt typedef void (VKAPI_PTR *PFN_vkCmdSetLineStippleEXT)(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEXT( VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern); #endif +#endif // VK_EXT_shader_atomic_float is a preprocessor guard. Do not pass it to API calls. @@ -16202,12 +19295,14 @@ typedef VkPhysicalDeviceHostQueryResetFeatures VkPhysicalDeviceHostQueryResetFea typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkResetQueryPoolEXT( VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); #endif +#endif // VK_EXT_index_type_uint8 is a preprocessor guard. Do not pass it to API calls. @@ -16242,28 +19337,39 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetStencilTestEnableEXT)(VkCommandBuffer comma typedef void (VKAPI_PTR *PFN_vkCmdSetStencilOpEXT)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCullModeEXT( VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetFrontFaceEXT( VkCommandBuffer commandBuffer, VkFrontFace frontFace); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveTopologyEXT( VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWithCountEXT( VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetScissorWithCountEXT( VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( VkCommandBuffer commandBuffer, uint32_t firstBinding, @@ -16272,27 +19378,39 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers2EXT( const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthTestEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthWriteEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthCompareOpEXT( VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBoundsTestEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilTestEnableEXT( VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, @@ -16301,6 +19419,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilOpEXT( VkStencilOp depthFailOp, VkCompareOp compareOp); #endif +#endif // VK_EXT_host_image_copy is a preprocessor guard. Do not pass it to API calls. @@ -16342,29 +19461,39 @@ typedef VkResult (VKAPI_PTR *PFN_vkTransitionImageLayoutEXT)(VkDevice device, ui typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout2EXT)(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToImageEXT( VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToMemoryEXT( VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyImageToImageEXT( VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkTransitionImageLayoutEXT( VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout2EXT( VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout); #endif +#endif // VK_EXT_map_memory_placed is a preprocessor guard. Do not pass it to API calls. @@ -16420,44 +19549,19 @@ typedef struct VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT { #define VK_EXT_surface_maintenance1 1 #define VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 #define VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_surface_maintenance1" +typedef VkPresentScalingFlagBitsKHR VkPresentScalingFlagBitsEXT; -typedef enum VkPresentScalingFlagBitsEXT { - VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = 0x00000001, - VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = 0x00000002, - VK_PRESENT_SCALING_STRETCH_BIT_EXT = 0x00000004, - VK_PRESENT_SCALING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkPresentScalingFlagBitsEXT; -typedef VkFlags VkPresentScalingFlagsEXT; +typedef VkPresentScalingFlagsKHR VkPresentScalingFlagsEXT; -typedef enum VkPresentGravityFlagBitsEXT { - VK_PRESENT_GRAVITY_MIN_BIT_EXT = 0x00000001, - VK_PRESENT_GRAVITY_MAX_BIT_EXT = 0x00000002, - VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = 0x00000004, - VK_PRESENT_GRAVITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF -} VkPresentGravityFlagBitsEXT; -typedef VkFlags VkPresentGravityFlagsEXT; -typedef struct VkSurfacePresentModeEXT { - VkStructureType sType; - void* pNext; - VkPresentModeKHR presentMode; -} VkSurfacePresentModeEXT; +typedef VkPresentGravityFlagBitsKHR VkPresentGravityFlagBitsEXT; -typedef struct VkSurfacePresentScalingCapabilitiesEXT { - VkStructureType sType; - void* pNext; - VkPresentScalingFlagsEXT supportedPresentScaling; - VkPresentGravityFlagsEXT supportedPresentGravityX; - VkPresentGravityFlagsEXT supportedPresentGravityY; - VkExtent2D minScaledImageExtent; - VkExtent2D maxScaledImageExtent; -} VkSurfacePresentScalingCapabilitiesEXT; +typedef VkPresentGravityFlagsKHR VkPresentGravityFlagsEXT; -typedef struct VkSurfacePresentModeCompatibilityEXT { - VkStructureType sType; - void* pNext; - uint32_t presentModeCount; - VkPresentModeKHR* pPresentModes; -} VkSurfacePresentModeCompatibilityEXT; +typedef VkSurfacePresentModeKHR VkSurfacePresentModeEXT; + +typedef VkSurfacePresentScalingCapabilitiesKHR VkSurfacePresentScalingCapabilitiesEXT; + +typedef VkSurfacePresentModeCompatibilityKHR VkSurfacePresentModeCompatibilityEXT; @@ -16465,55 +19569,26 @@ typedef struct VkSurfacePresentModeCompatibilityEXT { #define VK_EXT_swapchain_maintenance1 1 #define VK_EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION 1 #define VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME "VK_EXT_swapchain_maintenance1" -typedef struct VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 swapchainMaintenance1; -} VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT; +typedef VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT; -typedef struct VkSwapchainPresentFenceInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkFence* pFences; -} VkSwapchainPresentFenceInfoEXT; +typedef VkSwapchainPresentFenceInfoKHR VkSwapchainPresentFenceInfoEXT; -typedef struct VkSwapchainPresentModesCreateInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t presentModeCount; - const VkPresentModeKHR* pPresentModes; -} VkSwapchainPresentModesCreateInfoEXT; +typedef VkSwapchainPresentModesCreateInfoKHR VkSwapchainPresentModesCreateInfoEXT; -typedef struct VkSwapchainPresentModeInfoEXT { - VkStructureType sType; - const void* pNext; - uint32_t swapchainCount; - const VkPresentModeKHR* pPresentModes; -} VkSwapchainPresentModeInfoEXT; +typedef VkSwapchainPresentModeInfoKHR VkSwapchainPresentModeInfoEXT; -typedef struct VkSwapchainPresentScalingCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkPresentScalingFlagsEXT scalingBehavior; - VkPresentGravityFlagsEXT presentGravityX; - VkPresentGravityFlagsEXT presentGravityY; -} VkSwapchainPresentScalingCreateInfoEXT; +typedef VkSwapchainPresentScalingCreateInfoKHR VkSwapchainPresentScalingCreateInfoEXT; -typedef struct VkReleaseSwapchainImagesInfoEXT { - VkStructureType sType; - const void* pNext; - VkSwapchainKHR swapchain; - uint32_t imageIndexCount; - const uint32_t* pImageIndices; -} VkReleaseSwapchainImagesInfoEXT; +typedef VkReleaseSwapchainImagesInfoKHR VkReleaseSwapchainImagesInfoEXT; -typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesEXT)(VkDevice device, const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo); +typedef VkResult (VKAPI_PTR *PFN_vkReleaseSwapchainImagesEXT)(VkDevice device, const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkReleaseSwapchainImagesEXT( VkDevice device, - const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo); + const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo); +#endif #endif @@ -16540,6 +19615,7 @@ typedef enum VkIndirectCommandsTokenTypeNV { VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_NV = 1000135000, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000, VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV = 1000428003, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV = 1000428004, @@ -16686,37 +19762,49 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice devi typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV( VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV( VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV( VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV( VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV( VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); #endif +#endif // VK_NV_inherited_viewport_scissor is a preprocessor guard. Do not pass it to API calls. @@ -16755,17 +19843,17 @@ typedef VkPhysicalDeviceTexelBufferAlignmentProperties VkPhysicalDeviceTexelBuff // VK_QCOM_render_pass_transform is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_render_pass_transform 1 -#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 4 +#define VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION 5 #define VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME "VK_QCOM_render_pass_transform" typedef struct VkRenderPassTransformBeginInfoQCOM { VkStructureType sType; - void* pNext; + const void* pNext; VkSurfaceTransformFlagBitsKHR transform; } VkRenderPassTransformBeginInfoQCOM; typedef struct VkCommandBufferInheritanceRenderPassTransformInfoQCOM { VkStructureType sType; - void* pNext; + const void* pNext; VkSurfaceTransformFlagBitsKHR transform; VkRect2D renderArea; } VkCommandBufferInheritanceRenderPassTransformInfoQCOM; @@ -16810,10 +19898,12 @@ typedef struct VkDepthBiasRepresentationInfoEXT { typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias2EXT)(VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias2EXT( VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo); #endif +#endif // VK_EXT_device_memory_report is a preprocessor guard. Do not pass it to API calls. @@ -16870,37 +19960,30 @@ typedef VkResult (VKAPI_PTR *PFN_vkAcquireDrmDisplayEXT)(VkPhysicalDevice physic typedef VkResult (VKAPI_PTR *PFN_vkGetDrmDisplayEXT)(VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireDrmDisplayEXT( VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDrmDisplayEXT( VkPhysicalDevice physicalDevice, int32_t drmFd, uint32_t connectorId, VkDisplayKHR* display); #endif +#endif // VK_EXT_robustness2 is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_robustness2 1 #define VK_EXT_ROBUSTNESS_2_SPEC_VERSION 1 #define VK_EXT_ROBUSTNESS_2_EXTENSION_NAME "VK_EXT_robustness2" -typedef struct VkPhysicalDeviceRobustness2FeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 robustBufferAccess2; - VkBool32 robustImageAccess2; - VkBool32 nullDescriptor; -} VkPhysicalDeviceRobustness2FeaturesEXT; +typedef VkPhysicalDeviceRobustness2FeaturesKHR VkPhysicalDeviceRobustness2FeaturesEXT; -typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { - VkStructureType sType; - void* pNext; - VkDeviceSize robustStorageBufferAccessSizeAlignment; - VkDeviceSize robustUniformBufferAccessSizeAlignment; -} VkPhysicalDeviceRobustness2PropertiesEXT; +typedef VkPhysicalDeviceRobustness2PropertiesKHR VkPhysicalDeviceRobustness2PropertiesEXT; @@ -16908,13 +19991,6 @@ typedef struct VkPhysicalDeviceRobustness2PropertiesEXT { #define VK_EXT_custom_border_color 1 #define VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION 12 #define VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME "VK_EXT_custom_border_color" -typedef struct VkSamplerCustomBorderColorCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkClearColorValue customBorderColor; - VkFormat format; -} VkSamplerCustomBorderColorCreateInfoEXT; - typedef struct VkPhysicalDeviceCustomBorderColorPropertiesEXT { VkStructureType sType; void* pNext; @@ -16930,6 +20006,18 @@ typedef struct VkPhysicalDeviceCustomBorderColorFeaturesEXT { +// VK_EXT_texture_compression_astc_3d is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_texture_compression_astc_3d 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_SPEC_VERSION 1 +#define VK_EXT_TEXTURE_COMPRESSION_ASTC_3D_EXTENSION_NAME "VK_EXT_texture_compression_astc_3d" +typedef struct VkPhysicalDeviceTextureCompressionASTC3DFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 textureCompressionASTC_3D; +} VkPhysicalDeviceTextureCompressionASTC3DFeaturesEXT; + + + // VK_GOOGLE_user_type is a preprocessor guard. Do not pass it to API calls. #define VK_GOOGLE_user_type 1 #define VK_GOOGLE_USER_TYPE_SPEC_VERSION 1 @@ -16980,24 +20068,31 @@ typedef VkResult (VKAPI_PTR *PFN_vkSetPrivateDataEXT)(VkDevice device, VkObjectT typedef void (VKAPI_PTR *PFN_vkGetPrivateDataEXT)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreatePrivateDataSlotEXT( VkDevice device, const VkPrivateDataSlotCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPrivateDataSlot* pPrivateDataSlot); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyPrivateDataSlotEXT( VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkSetPrivateDataEXT( VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( VkDevice device, VkObjectType objectType, @@ -17005,6 +20100,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetPrivateDataEXT( VkPrivateDataSlot privateDataSlot, uint64_t* pData); #endif +#endif // VK_EXT_pipeline_creation_cache_control is a preprocessor guard. Do not pass it to API calls. @@ -17048,95 +20144,181 @@ typedef struct VkDeviceDiagnosticsConfigCreateInfoNV { #define VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME "VK_QCOM_render_pass_store_ops" -// VK_NV_cuda_kernel_launch is a preprocessor guard. Do not pass it to API calls. -#define VK_NV_cuda_kernel_launch 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV) -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV) -#define VK_NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION 2 -#define VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME "VK_NV_cuda_kernel_launch" -typedef struct VkCudaModuleCreateInfoNV { - VkStructureType sType; - const void* pNext; - size_t dataSize; - const void* pData; -} VkCudaModuleCreateInfoNV; +// VK_QCOM_queue_perf_hint is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_queue_perf_hint 1 +#define VK_QCOM_QUEUE_PERF_HINT_SPEC_VERSION 1 +#define VK_QCOM_QUEUE_PERF_HINT_EXTENSION_NAME "VK_QCOM_queue_perf_hint" -typedef struct VkCudaFunctionCreateInfoNV { - VkStructureType sType; - const void* pNext; - VkCudaModuleNV module; - const char* pName; -} VkCudaFunctionCreateInfoNV; +typedef enum VkPerfHintTypeQCOM { + VK_PERF_HINT_TYPE_DEFAULT_QCOM = 0, + VK_PERF_HINT_TYPE_FREQUENCY_MIN_QCOM = 1, + VK_PERF_HINT_TYPE_FREQUENCY_MAX_QCOM = 2, + VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM = 3, + VK_PERF_HINT_TYPE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkPerfHintTypeQCOM; +typedef struct VkPerfHintInfoQCOM { + VkStructureType sType; + void* pNext; + VkPerfHintTypeQCOM type; + uint32_t scale; +} VkPerfHintInfoQCOM; -typedef struct VkCudaLaunchInfoNV { - VkStructureType sType; - const void* pNext; - VkCudaFunctionNV function; - uint32_t gridDimX; - uint32_t gridDimY; - uint32_t gridDimZ; - uint32_t blockDimX; - uint32_t blockDimY; - uint32_t blockDimZ; - uint32_t sharedMemBytes; - size_t paramCount; - const void* const * pParams; - size_t extraCount; - const void* const * pExtras; -} VkCudaLaunchInfoNV; - -typedef struct VkPhysicalDeviceCudaKernelLaunchFeaturesNV { +typedef struct VkPhysicalDeviceQueuePerfHintFeaturesQCOM { VkStructureType sType; void* pNext; - VkBool32 cudaKernelLaunchFeatures; -} VkPhysicalDeviceCudaKernelLaunchFeaturesNV; + VkBool32 queuePerfHint; +} VkPhysicalDeviceQueuePerfHintFeaturesQCOM; -typedef struct VkPhysicalDeviceCudaKernelLaunchPropertiesNV { +typedef struct VkPhysicalDeviceQueuePerfHintPropertiesQCOM { VkStructureType sType; void* pNext; - uint32_t computeCapabilityMinor; - uint32_t computeCapabilityMajor; -} VkPhysicalDeviceCudaKernelLaunchPropertiesNV; + VkQueueFlags supportedQueues; +} VkPhysicalDeviceQueuePerfHintPropertiesQCOM; -typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaModuleNV)(VkDevice device, const VkCudaModuleCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaModuleNV* pModule); -typedef VkResult (VKAPI_PTR *PFN_vkGetCudaModuleCacheNV)(VkDevice device, VkCudaModuleNV module, size_t* pCacheSize, void* pCacheData); -typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaFunctionNV)(VkDevice device, const VkCudaFunctionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaFunctionNV* pFunction); -typedef void (VKAPI_PTR *PFN_vkDestroyCudaModuleNV)(VkDevice device, VkCudaModuleNV module, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkDestroyCudaFunctionNV)(VkDevice device, VkCudaFunctionNV function, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkCmdCudaLaunchKernelNV)(VkCommandBuffer commandBuffer, const VkCudaLaunchInfoNV* pLaunchInfo); +typedef VkResult (VKAPI_PTR *PFN_vkQueueSetPerfHintQCOM)(VkQueue queue, const VkPerfHintInfoQCOM* pPerfHintInfo); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaModuleNV( - VkDevice device, - const VkCudaModuleCreateInfoNV* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCudaModuleNV* pModule); +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkQueueSetPerfHintQCOM( + VkQueue queue, + const VkPerfHintInfoQCOM* pPerfHintInfo); +#endif +#endif -VKAPI_ATTR VkResult VKAPI_CALL vkGetCudaModuleCacheNV( - VkDevice device, - VkCudaModuleNV module, - size_t* pCacheSize, - void* pCacheData); -VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaFunctionNV( - VkDevice device, - const VkCudaFunctionCreateInfoNV* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkCudaFunctionNV* pFunction); +// VK_QCOM_image_processing3 is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_image_processing3 1 +#define VK_QCOM_IMAGE_PROCESSING_3_SPEC_VERSION 1 +#define VK_QCOM_IMAGE_PROCESSING_3_EXTENSION_NAME "VK_QCOM_image_processing3" +typedef struct VkPhysicalDeviceImageProcessing3FeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 imageGatherLinear; + VkBool32 imageGatherExtendedModes; + VkBool32 blockMatchExtendedClampToEdge; +} VkPhysicalDeviceImageProcessing3FeaturesQCOM; -VKAPI_ATTR void VKAPI_CALL vkDestroyCudaModuleNV( - VkDevice device, - VkCudaModuleNV module, - const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR void VKAPI_CALL vkDestroyCudaFunctionNV( - VkDevice device, - VkCudaFunctionNV function, - const VkAllocationCallbacks* pAllocator); -VKAPI_ATTR void VKAPI_CALL vkCmdCudaLaunchKernelNV( +// VK_QCOM_shader_multiple_wait_queues is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_shader_multiple_wait_queues 1 +#define VK_QCOM_SHADER_MULTIPLE_WAIT_QUEUES_SPEC_VERSION 1 +#define VK_QCOM_SHADER_MULTIPLE_WAIT_QUEUES_EXTENSION_NAME "VK_QCOM_shader_multiple_wait_queues" +typedef struct VkPhysicalDeviceShaderMultipleWaitQueuesFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 shaderMultipleWaitQueues; +} VkPhysicalDeviceShaderMultipleWaitQueuesFeaturesQCOM; + +typedef struct VkPhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxShaderWaitQueues; +} VkPhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM; + + + +// VK_EXT_shader_split_barrier is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_split_barrier 1 +#define VK_EXT_SHADER_SPLIT_BARRIER_SPEC_VERSION 1 +#define VK_EXT_SHADER_SPLIT_BARRIER_EXTENSION_NAME "VK_EXT_shader_split_barrier" +typedef struct VkPhysicalDeviceShaderSplitBarrierFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderSplitBarrier; +} VkPhysicalDeviceShaderSplitBarrierFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderSplitBarrierPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t splitBarrierReservedSharedMemory; +} VkPhysicalDeviceShaderSplitBarrierPropertiesEXT; + + + +// VK_QCOM_tile_shading is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_shading 1 +#define VK_QCOM_TILE_SHADING_SPEC_VERSION 2 +#define VK_QCOM_TILE_SHADING_EXTENSION_NAME "VK_QCOM_tile_shading" + +typedef enum VkTileShadingRenderPassFlagBitsQCOM { + VK_TILE_SHADING_RENDER_PASS_ENABLE_BIT_QCOM = 0x00000001, + VK_TILE_SHADING_RENDER_PASS_PER_TILE_EXECUTION_BIT_QCOM = 0x00000002, + VK_TILE_SHADING_RENDER_PASS_FLAG_BITS_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkTileShadingRenderPassFlagBitsQCOM; +typedef VkFlags VkTileShadingRenderPassFlagsQCOM; +typedef struct VkPhysicalDeviceTileShadingFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 tileShading; + VkBool32 tileShadingFragmentStage; + VkBool32 tileShadingColorAttachments; + VkBool32 tileShadingDepthAttachments; + VkBool32 tileShadingStencilAttachments; + VkBool32 tileShadingInputAttachments; + VkBool32 tileShadingSampledAttachments; + VkBool32 tileShadingPerTileDraw; + VkBool32 tileShadingPerTileDispatch; + VkBool32 tileShadingDispatchTile; + VkBool32 tileShadingApron; + VkBool32 tileShadingAnisotropicApron; + VkBool32 tileShadingAtomicOps; + VkBool32 tileShadingImageProcessing; +} VkPhysicalDeviceTileShadingFeaturesQCOM; + +typedef struct VkPhysicalDeviceTileShadingPropertiesQCOM { + VkStructureType sType; + void* pNext; + uint32_t maxApronSize; + VkBool32 preferNonCoherent; + VkExtent2D tileGranularity; + VkExtent2D maxTileShadingRate; +} VkPhysicalDeviceTileShadingPropertiesQCOM; + +typedef struct VkRenderPassTileShadingCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + VkTileShadingRenderPassFlagsQCOM flags; + VkExtent2D tileApronSize; +} VkRenderPassTileShadingCreateInfoQCOM; + +typedef struct VkPerTileBeginInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkPerTileBeginInfoQCOM; + +typedef struct VkPerTileEndInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkPerTileEndInfoQCOM; + +typedef struct VkDispatchTileInfoQCOM { + VkStructureType sType; + const void* pNext; +} VkDispatchTileInfoQCOM; + +typedef void (VKAPI_PTR *PFN_vkCmdDispatchTileQCOM)(VkCommandBuffer commandBuffer, const VkDispatchTileInfoQCOM* pDispatchTileInfo); +typedef void (VKAPI_PTR *PFN_vkCmdBeginPerTileExecutionQCOM)(VkCommandBuffer commandBuffer, const VkPerTileBeginInfoQCOM* pPerTileBeginInfo); +typedef void (VKAPI_PTR *PFN_vkCmdEndPerTileExecutionQCOM)(VkCommandBuffer commandBuffer, const VkPerTileEndInfoQCOM* pPerTileEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchTileQCOM( VkCommandBuffer commandBuffer, - const VkCudaLaunchInfoNV* pLaunchInfo); + const VkDispatchTileInfoQCOM* pDispatchTileInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginPerTileExecutionQCOM( + VkCommandBuffer commandBuffer, + const VkPerTileBeginInfoQCOM* pPerTileBeginInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndPerTileExecutionQCOM( + VkCommandBuffer commandBuffer, + const VkPerTileEndInfoQCOM* pPerTileEndInfo); +#endif #endif @@ -17154,7 +20336,6 @@ typedef struct VkQueryLowLatencySupportNV { // VK_EXT_descriptor_buffer is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_descriptor_buffer 1 -VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR) #define VK_EXT_DESCRIPTOR_BUFFER_SPEC_VERSION 1 #define VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME "VK_EXT_descriptor_buffer" typedef struct VkPhysicalDeviceDescriptorBufferPropertiesEXT { @@ -17195,12 +20376,6 @@ typedef struct VkPhysicalDeviceDescriptorBufferPropertiesEXT { VkDeviceSize descriptorBufferAddressSpaceSize; } VkPhysicalDeviceDescriptorBufferPropertiesEXT; -typedef struct VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { - VkStructureType sType; - void* pNext; - size_t combinedImageSamplerDensityMapDescriptorSize; -} VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT; - typedef struct VkPhysicalDeviceDescriptorBufferFeaturesEXT { VkStructureType sType; void* pNext; @@ -17288,6 +20463,12 @@ typedef struct VkAccelerationStructureCaptureDescriptorDataInfoEXT { VkAccelerationStructureNV accelerationStructureNV; } VkAccelerationStructureCaptureDescriptorDataInfoEXT; +typedef struct VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { + VkStructureType sType; + void* pNext; + size_t combinedImageSamplerDensityMapDescriptorSize; +} VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT; + typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSizeEXT)(VkDevice device, VkDescriptorSetLayout layout, VkDeviceSize* pLayoutSizeInBytes); typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutBindingOffsetEXT)(VkDevice device, VkDescriptorSetLayout layout, uint32_t binding, VkDeviceSize* pOffset); typedef void (VKAPI_PTR *PFN_vkGetDescriptorEXT)(VkDevice device, const VkDescriptorGetInfoEXT* pDescriptorInfo, size_t dataSize, void* pDescriptor); @@ -17301,28 +20482,37 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT)(VkD typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT)(VkDevice device, const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, void* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSizeEXT( VkDevice device, VkDescriptorSetLayout layout, VkDeviceSize* pLayoutSizeInBytes); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutBindingOffsetEXT( VkDevice device, VkDescriptorSetLayout layout, uint32_t binding, VkDeviceSize* pOffset); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorEXT( VkDevice device, const VkDescriptorGetInfoEXT* pDescriptorInfo, size_t dataSize, void* pDescriptor); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBuffersEXT( VkCommandBuffer commandBuffer, uint32_t bufferCount, const VkDescriptorBufferBindingInfoEXT* pBindingInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsetsEXT( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, @@ -17331,38 +20521,51 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetDescriptorBufferOffsetsEXT( uint32_t setCount, const uint32_t* pBufferIndices, const VkDeviceSize* pOffsets); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorBufferEmbeddedSamplersEXT( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetBufferOpaqueCaptureDescriptorDataEXT( VkDevice device, const VkBufferCaptureDescriptorDataInfoEXT* pInfo, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetImageOpaqueCaptureDescriptorDataEXT( VkDevice device, const VkImageCaptureDescriptorDataInfoEXT* pInfo, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewOpaqueCaptureDescriptorDataEXT( VkDevice device, const VkImageViewCaptureDescriptorDataInfoEXT* pInfo, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSamplerOpaqueCaptureDescriptorDataEXT( VkDevice device, const VkSamplerCaptureDescriptorDataInfoEXT* pInfo, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT( VkDevice device, const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo, void* pData); #endif +#endif // VK_EXT_graphics_pipeline_library is a preprocessor guard. Do not pass it to API calls. @@ -17462,11 +20665,13 @@ typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV { typedef void (VKAPI_PTR *PFN_vkCmdSetFragmentShadingRateEnumNV)(VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetFragmentShadingRateEnumNV( VkCommandBuffer commandBuffer, VkFragmentShadingRateNV shadingRate, const VkFragmentShadingRateCombinerOpKHR combinerOps[2]); #endif +#endif // VK_NV_ray_tracing_motion_blur is a preprocessor guard. Do not pass it to API calls. @@ -17708,22 +20913,10 @@ typedef struct VkPhysicalDevice4444FormatsFeaturesEXT { #define VK_EXT_device_fault 1 #define VK_EXT_DEVICE_FAULT_SPEC_VERSION 2 #define VK_EXT_DEVICE_FAULT_EXTENSION_NAME "VK_EXT_device_fault" +typedef VkDeviceFaultAddressTypeKHR VkDeviceFaultAddressTypeEXT; -typedef enum VkDeviceFaultAddressTypeEXT { - VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT = 0, - VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT = 1, - VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT = 2, - VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT = 3, - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT = 4, - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT = 5, - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT = 6, - VK_DEVICE_FAULT_ADDRESS_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDeviceFaultAddressTypeEXT; +typedef VkDeviceFaultVendorBinaryHeaderVersionKHR VkDeviceFaultVendorBinaryHeaderVersionEXT; -typedef enum VkDeviceFaultVendorBinaryHeaderVersionEXT { - VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT = 1, - VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_MAX_ENUM_EXT = 0x7FFFFFFF -} VkDeviceFaultVendorBinaryHeaderVersionEXT; typedef struct VkPhysicalDeviceFaultFeaturesEXT { VkStructureType sType; void* pNext; @@ -17739,49 +20932,31 @@ typedef struct VkDeviceFaultCountsEXT { VkDeviceSize vendorBinarySize; } VkDeviceFaultCountsEXT; -typedef struct VkDeviceFaultAddressInfoEXT { - VkDeviceFaultAddressTypeEXT addressType; - VkDeviceAddress reportedAddress; - VkDeviceSize addressPrecision; -} VkDeviceFaultAddressInfoEXT; - -typedef struct VkDeviceFaultVendorInfoEXT { - char description[VK_MAX_DESCRIPTION_SIZE]; - uint64_t vendorFaultCode; - uint64_t vendorFaultData; -} VkDeviceFaultVendorInfoEXT; - typedef struct VkDeviceFaultInfoEXT { VkStructureType sType; void* pNext; char description[VK_MAX_DESCRIPTION_SIZE]; - VkDeviceFaultAddressInfoEXT* pAddressInfos; - VkDeviceFaultVendorInfoEXT* pVendorInfos; + VkDeviceFaultAddressInfoKHR* pAddressInfos; + VkDeviceFaultVendorInfoKHR* pVendorInfos; void* pVendorBinaryData; } VkDeviceFaultInfoEXT; -typedef struct VkDeviceFaultVendorBinaryHeaderVersionOneEXT { - uint32_t headerSize; - VkDeviceFaultVendorBinaryHeaderVersionEXT headerVersion; - uint32_t vendorID; - uint32_t deviceID; - uint32_t driverVersion; - uint8_t pipelineCacheUUID[VK_UUID_SIZE]; - uint32_t applicationNameOffset; - uint32_t applicationVersion; - uint32_t engineNameOffset; - uint32_t engineVersion; - uint32_t apiVersion; -} VkDeviceFaultVendorBinaryHeaderVersionOneEXT; +typedef VkDeviceFaultAddressInfoKHR VkDeviceFaultAddressInfoEXT; + +typedef VkDeviceFaultVendorInfoKHR VkDeviceFaultVendorInfoEXT; + +typedef VkDeviceFaultVendorBinaryHeaderVersionOneKHR VkDeviceFaultVendorBinaryHeaderVersionOneEXT; typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceFaultInfoEXT)(VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceFaultInfoEXT( VkDevice device, VkDeviceFaultCountsEXT* pFaultCounts, VkDeviceFaultInfoEXT* pFaultInfo); #endif +#endif // VK_ARM_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. @@ -17873,6 +21048,7 @@ typedef struct VkVertexInputAttributeDescription2EXT { typedef void (VKAPI_PTR *PFN_vkCmdSetVertexInputEXT)(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions, uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount, @@ -17880,6 +21056,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdSetVertexInputEXT( uint32_t vertexAttributeDescriptionCount, const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions); #endif +#endif // VK_EXT_physical_device_drm is a preprocessor guard. Do not pass it to API calls. @@ -17967,11 +21144,7 @@ typedef struct VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT { #define VK_EXT_present_mode_fifo_latest_ready 1 #define VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION 1 #define VK_EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME "VK_EXT_present_mode_fifo_latest_ready" -typedef struct VkPhysicalDevicePresentModeFifoLatestReadyFeaturesEXT { - VkStructureType sType; - void* pNext; - VkBool32 presentModeFifoLatestReady; -} VkPhysicalDevicePresentModeFifoLatestReadyFeaturesEXT; +typedef VkPhysicalDevicePresentModeFifoLatestReadyFeaturesKHR VkPhysicalDevicePresentModeFifoLatestReadyFeaturesEXT; @@ -18002,14 +21175,18 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI typedef void (VKAPI_PTR *PFN_vkCmdSubpassShadingHUAWEI)(VkCommandBuffer commandBuffer); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI( VkDevice device, VkRenderPass renderpass, VkExtent2D* pMaxWorkgroupSize); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSubpassShadingHUAWEI( VkCommandBuffer commandBuffer); #endif +#endif // VK_HUAWEI_invocation_mask is a preprocessor guard. Do not pass it to API calls. @@ -18025,11 +21202,13 @@ typedef struct VkPhysicalDeviceInvocationMaskFeaturesHUAWEI { typedef void (VKAPI_PTR *PFN_vkCmdBindInvocationMaskHUAWEI)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindInvocationMaskHUAWEI( VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout); #endif +#endif // VK_NV_external_memory_rdma is a preprocessor guard. Do not pass it to API calls. @@ -18053,11 +21232,13 @@ typedef struct VkPhysicalDeviceExternalMemoryRDMAFeaturesNV { typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryRemoteAddressNV)(VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryRemoteAddressNV( VkDevice device, const VkMemoryGetRemoteAddressInfoNV* pMemoryGetRemoteAddressInfo, VkRemoteAddressNV* pAddress); #endif +#endif // VK_EXT_pipeline_properties is a preprocessor guard. Do not pass it to API calls. @@ -18078,14 +21259,16 @@ typedef struct VkPhysicalDevicePipelinePropertiesFeaturesEXT { VkBool32 pipelinePropertiesIdentifier; } VkPhysicalDevicePipelinePropertiesFeaturesEXT; -typedef VkResult (VKAPI_PTR *PFN_vkGetPipelinePropertiesEXT)(VkDevice device, const VkPipelineInfoEXT* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPipelinePropertiesEXT)(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelinePropertiesEXT( VkDevice device, - const VkPipelineInfoEXT* pPipelineInfo, + const VkPipelineInfoKHR* pPipelineInfo, VkBaseOutStructure* pPipelineProperties); #endif +#endif // VK_EXT_frame_boundary is a preprocessor guard. Do not pass it to API calls. @@ -18164,26 +21347,36 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetLogicOpEXT)(VkCommandBuffer commandBuffer, typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartEnableEXT)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetPatchControlPointsEXT( VkCommandBuffer commandBuffer, uint32_t patchControlPoints); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizerDiscardEnableEXT( VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBiasEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEXT( VkCommandBuffer commandBuffer, VkLogicOp logicOp); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartEnableEXT( VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); #endif +#endif // VK_EXT_color_write_enable is a preprocessor guard. Do not pass it to API calls. @@ -18203,14 +21396,16 @@ typedef struct VkPipelineColorWriteCreateInfoEXT { const VkBool32* pColorWriteEnables; } VkPipelineColorWriteCreateInfoEXT; -typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); +typedef void (VKAPI_PTR *PFN_vkCmdSetColorWriteEnableEXT)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); #ifndef VK_NO_PROTOTYPES -VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteEnableEXT( VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkBool32* pColorWriteEnables); #endif +#endif // VK_EXT_primitives_generated_query is a preprocessor guard. Do not pass it to API calls. @@ -18238,6 +21433,66 @@ typedef VkQueueFamilyGlobalPriorityProperties VkQueueFamilyGlobalPriorityPropert +// VK_VALVE_video_encode_rgb_conversion is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_video_encode_rgb_conversion 1 +#define VK_VALVE_VIDEO_ENCODE_RGB_CONVERSION_SPEC_VERSION 1 +#define VK_VALVE_VIDEO_ENCODE_RGB_CONVERSION_EXTENSION_NAME "VK_VALVE_video_encode_rgb_conversion" + +typedef enum VkVideoEncodeRgbModelConversionFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_RGB_IDENTITY_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_IDENTITY_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_709_BIT_VALVE = 0x00000004, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_601_BIT_VALVE = 0x00000008, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_2020_BIT_VALVE = 0x00000010, + VK_VIDEO_ENCODE_RGB_MODEL_CONVERSION_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbModelConversionFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbModelConversionFlagsVALVE; + +typedef enum VkVideoEncodeRgbRangeCompressionFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_FULL_RANGE_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_NARROW_RANGE_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_RANGE_COMPRESSION_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbRangeCompressionFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbRangeCompressionFlagsVALVE; + +typedef enum VkVideoEncodeRgbChromaOffsetFlagBitsVALVE { + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_COSITED_EVEN_BIT_VALVE = 0x00000001, + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_MIDPOINT_BIT_VALVE = 0x00000002, + VK_VIDEO_ENCODE_RGB_CHROMA_OFFSET_FLAG_BITS_MAX_ENUM_VALVE = 0x7FFFFFFF +} VkVideoEncodeRgbChromaOffsetFlagBitsVALVE; +typedef VkFlags VkVideoEncodeRgbChromaOffsetFlagsVALVE; +typedef struct VkPhysicalDeviceVideoEncodeRgbConversionFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 videoEncodeRgbConversion; +} VkPhysicalDeviceVideoEncodeRgbConversionFeaturesVALVE; + +typedef struct VkVideoEncodeRgbConversionCapabilitiesVALVE { + VkStructureType sType; + void* pNext; + VkVideoEncodeRgbModelConversionFlagsVALVE rgbModels; + VkVideoEncodeRgbRangeCompressionFlagsVALVE rgbRanges; + VkVideoEncodeRgbChromaOffsetFlagsVALVE xChromaOffsets; + VkVideoEncodeRgbChromaOffsetFlagsVALVE yChromaOffsets; +} VkVideoEncodeRgbConversionCapabilitiesVALVE; + +typedef struct VkVideoEncodeProfileRgbConversionInfoVALVE { + VkStructureType sType; + const void* pNext; + VkBool32 performEncodeRgbConversion; +} VkVideoEncodeProfileRgbConversionInfoVALVE; + +typedef struct VkVideoEncodeSessionRgbConversionCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + VkVideoEncodeRgbModelConversionFlagBitsVALVE rgbModel; + VkVideoEncodeRgbRangeCompressionFlagBitsVALVE rgbRange; + VkVideoEncodeRgbChromaOffsetFlagBitsVALVE xChromaOffset; + VkVideoEncodeRgbChromaOffsetFlagBitsVALVE yChromaOffset; +} VkVideoEncodeSessionRgbConversionCreateInfoVALVE; + + + // VK_EXT_image_view_min_lod is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_image_view_min_lod 1 #define VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION 1 @@ -18287,6 +21542,7 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiEXT)(VkCommandBuffer commandBuffer, u typedef void (VKAPI_PTR *PFN_vkCmdDrawMultiIndexedEXT)(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( VkCommandBuffer commandBuffer, uint32_t drawCount, @@ -18294,7 +21550,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiEXT( uint32_t instanceCount, uint32_t firstInstance, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( VkCommandBuffer commandBuffer, uint32_t drawCount, @@ -18304,6 +21562,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMultiIndexedEXT( uint32_t stride, const int32_t* pVertexOffset); #endif +#endif // VK_EXT_image_2d_view_of_3d is a preprocessor guard. Do not pass it to API calls. @@ -18367,21 +21626,10 @@ typedef enum VkCopyMicromapModeEXT { VK_COPY_MICROMAP_MODE_COMPACT_EXT = 3, VK_COPY_MICROMAP_MODE_MAX_ENUM_EXT = 0x7FFFFFFF } VkCopyMicromapModeEXT; +typedef VkOpacityMicromapFormatKHR VkOpacityMicromapFormatEXT; -typedef enum VkOpacityMicromapFormatEXT { - VK_OPACITY_MICROMAP_FORMAT_2_STATE_EXT = 1, - VK_OPACITY_MICROMAP_FORMAT_4_STATE_EXT = 2, - VK_OPACITY_MICROMAP_FORMAT_MAX_ENUM_EXT = 0x7FFFFFFF -} VkOpacityMicromapFormatEXT; +typedef VkOpacityMicromapSpecialIndexKHR VkOpacityMicromapSpecialIndexEXT; -typedef enum VkOpacityMicromapSpecialIndexEXT { - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_TRANSPARENT_EXT = -1, - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_OPAQUE_EXT = -2, - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_TRANSPARENT_EXT = -3, - VK_OPACITY_MICROMAP_SPECIAL_INDEX_FULLY_UNKNOWN_OPAQUE_EXT = -4, - VK_OPACITY_MICROMAP_SPECIAL_INDEX_CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, - VK_OPACITY_MICROMAP_SPECIAL_INDEX_MAX_ENUM_EXT = 0x7FFFFFFF -} VkOpacityMicromapSpecialIndexEXT; typedef enum VkAccelerationStructureCompatibilityKHR { VK_ACCELERATION_STRUCTURE_COMPATIBILITY_COMPATIBLE_KHR = 0, @@ -18513,65 +21761,76 @@ typedef struct VkAccelerationStructureTrianglesOpacityMicromapEXT { VkMicromapEXT micromap; } VkAccelerationStructureTrianglesOpacityMicromapEXT; -typedef struct VkMicromapTriangleEXT { - uint32_t dataOffset; - uint16_t subdivisionLevel; - uint16_t format; -} VkMicromapTriangleEXT; +typedef VkMicromapTriangleKHR VkMicromapTriangleEXT; -typedef VkResult (VKAPI_PTR *PFN_vkCreateMicromapEXT)(VkDevice device, const VkMicromapCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkMicromapEXT* pMicromap); -typedef void (VKAPI_PTR *PFN_vkDestroyMicromapEXT)(VkDevice device, VkMicromapEXT micromap, const VkAllocationCallbacks* pAllocator); -typedef void (VKAPI_PTR *PFN_vkCmdBuildMicromapsEXT)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); -typedef VkResult (VKAPI_PTR *PFN_vkBuildMicromapsEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); -typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapInfoEXT* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapToMemoryEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapToMemoryInfoEXT* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToMicromapInfoEXT* pInfo); -typedef VkResult (VKAPI_PTR *PFN_vkWriteMicromapsPropertiesEXT)(VkDevice device, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); -typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapInfoEXT* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapToMemoryEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapToMemoryInfoEXT* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMemoryToMicromapInfoEXT* pInfo); -typedef void (VKAPI_PTR *PFN_vkCmdWriteMicromapsPropertiesEXT)(VkCommandBuffer commandBuffer, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); -typedef void (VKAPI_PTR *PFN_vkGetDeviceMicromapCompatibilityEXT)(VkDevice device, const VkMicromapVersionInfoEXT* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); -typedef void (VKAPI_PTR *PFN_vkGetMicromapBuildSizesEXT)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkMicromapBuildInfoEXT* pBuildInfo, VkMicromapBuildSizesInfoEXT* pSizeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCreateMicromapEXT)(VkDevice device, const VkMicromapCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkMicromapEXT* pMicromap); +typedef void (VKAPI_PTR *PFN_vkDestroyMicromapEXT)(VkDevice device, VkMicromapEXT micromap, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBuildMicromapsEXT)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkBuildMicromapsEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMicromapToMemoryEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToMicromapEXT)(VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkWriteMicromapsPropertiesEXT)(VkDevice device, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, size_t dataSize, void* pData, size_t stride); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMicromapToMemoryEXT)(VkCommandBuffer commandBuffer, const VkCopyMicromapToMemoryInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToMicromapEXT)(VkCommandBuffer commandBuffer, const VkCopyMemoryToMicromapInfoEXT* pInfo); +typedef void (VKAPI_PTR *PFN_vkCmdWriteMicromapsPropertiesEXT)(VkCommandBuffer commandBuffer, uint32_t micromapCount, const VkMicromapEXT* pMicromaps, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +typedef void (VKAPI_PTR *PFN_vkGetDeviceMicromapCompatibilityEXT)(VkDevice device, const VkMicromapVersionInfoEXT* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +typedef void (VKAPI_PTR *PFN_vkGetMicromapBuildSizesEXT)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkMicromapBuildInfoEXT* pBuildInfo, VkMicromapBuildSizesInfoEXT* pSizeInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateMicromapEXT( VkDevice device, const VkMicromapCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkMicromapEXT* pMicromap); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyMicromapEXT( VkDevice device, VkMicromapEXT micromap, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildMicromapsEXT( VkCommandBuffer commandBuffer, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBuildMicromapsEXT( VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkMicromapBuildInfoEXT* pInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapEXT( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyMicromapToMemoryEXT( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMicromapToMemoryInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToMicromapEXT( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToMicromapInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkWriteMicromapsPropertiesEXT( VkDevice device, uint32_t micromapCount, @@ -18580,19 +21839,27 @@ VKAPI_ATTR VkResult VKAPI_CALL vkWriteMicromapsPropertiesEXT( size_t dataSize, void* pData, size_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapEXT( VkCommandBuffer commandBuffer, const VkCopyMicromapInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMicromapToMemoryEXT( VkCommandBuffer commandBuffer, const VkCopyMicromapToMemoryInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToMicromapEXT( VkCommandBuffer commandBuffer, const VkCopyMemoryToMicromapInfoEXT* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteMicromapsPropertiesEXT( VkCommandBuffer commandBuffer, uint32_t micromapCount, @@ -18600,18 +21867,23 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteMicromapsPropertiesEXT( VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceMicromapCompatibilityEXT( VkDevice device, const VkMicromapVersionInfoEXT* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetMicromapBuildSizesEXT( VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkMicromapBuildInfoEXT* pBuildInfo, VkMicromapBuildSizesInfoEXT* pSizeInfo); #endif +#endif // VK_EXT_load_store_op_none is a preprocessor guard. Do not pass it to API calls. @@ -18650,17 +21922,21 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterHUAWEI)(VkCommandBuffer commandBuff typedef void (VKAPI_PTR *PFN_vkCmdDrawClusterIndirectHUAWEI)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterHUAWEI( VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawClusterIndirectHUAWEI( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset); #endif +#endif // VK_EXT_border_color_swizzle is a preprocessor guard. Do not pass it to API calls. @@ -18696,11 +21972,13 @@ typedef struct VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT { typedef void (VKAPI_PTR *PFN_vkSetDeviceMemoryPriorityEXT)(VkDevice device, VkDeviceMemory memory, float priority); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkSetDeviceMemoryPriorityEXT( VkDevice device, VkDeviceMemory memory, float priority); #endif +#endif // VK_ARM_shader_core_properties is a preprocessor guard. Do not pass it to API calls. @@ -18719,13 +21997,14 @@ typedef struct VkPhysicalDeviceShaderCorePropertiesARM { // VK_ARM_scheduling_controls is a preprocessor guard. Do not pass it to API calls. #define VK_ARM_scheduling_controls 1 -#define VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION 1 +#define VK_ARM_SCHEDULING_CONTROLS_SPEC_VERSION 2 #define VK_ARM_SCHEDULING_CONTROLS_EXTENSION_NAME "VK_ARM_scheduling_controls" typedef VkFlags64 VkPhysicalDeviceSchedulingControlsFlagsARM; // Flag bits for VkPhysicalDeviceSchedulingControlsFlagBitsARM typedef VkFlags64 VkPhysicalDeviceSchedulingControlsFlagBitsARM; static const VkPhysicalDeviceSchedulingControlsFlagBitsARM VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_SHADER_CORE_COUNT_ARM = 0x00000001ULL; +static const VkPhysicalDeviceSchedulingControlsFlagBitsARM VK_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_DISPATCH_PARAMETERS_ARM = 0x00000002ULL; typedef struct VkDeviceQueueShaderCoreControlCreateInfoARM { VkStructureType sType; @@ -18745,6 +22024,31 @@ typedef struct VkPhysicalDeviceSchedulingControlsPropertiesARM { VkPhysicalDeviceSchedulingControlsFlagsARM schedulingControlsFlags; } VkPhysicalDeviceSchedulingControlsPropertiesARM; +typedef struct VkDispatchParametersARM { + VkStructureType sType; + void* pNext; + uint32_t workGroupBatchSize; + uint32_t maxQueuedWorkGroupBatches; + uint32_t maxWarpsPerShaderCore; +} VkDispatchParametersARM; + +typedef struct VkPhysicalDeviceSchedulingControlsDispatchParametersPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t schedulingControlsMaxWarpsCount; + uint32_t schedulingControlsMaxQueuedBatchesCount; + uint32_t schedulingControlsMaxWorkGroupBatchSize; +} VkPhysicalDeviceSchedulingControlsDispatchParametersPropertiesARM; + +typedef void (VKAPI_PTR *PFN_vkCmdSetDispatchParametersARM)(VkCommandBuffer commandBuffer, const VkDispatchParametersARM* pDispatchParameters); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetDispatchParametersARM( + VkCommandBuffer commandBuffer, + const VkDispatchParametersARM* pDispatchParameters); +#endif +#endif // VK_EXT_image_sliced_view_of_3d is a preprocessor guard. Do not pass it to API calls. @@ -18795,16 +22099,20 @@ typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE)(VkDev typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetHostMappingVALVE)(VkDevice device, VkDescriptorSet descriptorSet, void** ppData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutHostMappingInfoVALVE( VkDevice device, const VkDescriptorSetBindingReferenceVALVE* pBindingReference, VkDescriptorSetLayoutHostMappingInfoVALVE* pHostMapping); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetHostMappingVALVE( VkDevice device, VkDescriptorSet descriptorSet, void** ppData); #endif +#endif // VK_EXT_depth_clamp_zero_one is a preprocessor guard. Do not pass it to API calls. @@ -18868,26 +22176,32 @@ typedef struct VkRenderPassStripeSubmitInfoARM { // VK_QCOM_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. #define VK_QCOM_fragment_density_map_offset 1 -#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 2 +#define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 3 #define VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_QCOM_fragment_density_map_offset" -typedef struct VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM { +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT { VkStructureType sType; void* pNext; VkBool32 fragmentDensityMapOffset; -} VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM; +} VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT; -typedef struct VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM { +typedef VkPhysicalDeviceFragmentDensityMapOffsetFeaturesEXT VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM; + +typedef struct VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT { VkStructureType sType; void* pNext; VkExtent2D fragmentDensityOffsetGranularity; -} VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM; +} VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT; -typedef struct VkSubpassFragmentDensityMapOffsetEndInfoQCOM { +typedef VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM; + +typedef struct VkRenderPassFragmentDensityMapOffsetEndInfoEXT { VkStructureType sType; const void* pNext; uint32_t fragmentDensityOffsetCount; const VkOffset2D* pFragmentDensityOffsets; -} VkSubpassFragmentDensityMapOffsetEndInfoQCOM; +} VkRenderPassFragmentDensityMapOffsetEndInfoEXT; + +typedef VkRenderPassFragmentDensityMapOffsetEndInfoEXT VkSubpassFragmentDensityMapOffsetEndInfoQCOM; @@ -18895,20 +22209,9 @@ typedef struct VkSubpassFragmentDensityMapOffsetEndInfoQCOM { #define VK_NV_copy_memory_indirect 1 #define VK_NV_COPY_MEMORY_INDIRECT_SPEC_VERSION 1 #define VK_NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME "VK_NV_copy_memory_indirect" -typedef struct VkCopyMemoryIndirectCommandNV { - VkDeviceAddress srcAddress; - VkDeviceAddress dstAddress; - VkDeviceSize size; -} VkCopyMemoryIndirectCommandNV; +typedef VkCopyMemoryIndirectCommandKHR VkCopyMemoryIndirectCommandNV; -typedef struct VkCopyMemoryToImageIndirectCommandNV { - VkDeviceAddress srcAddress; - uint32_t bufferRowLength; - uint32_t bufferImageHeight; - VkImageSubresourceLayers imageSubresource; - VkOffset3D imageOffset; - VkExtent3D imageExtent; -} VkCopyMemoryToImageIndirectCommandNV; +typedef VkCopyMemoryToImageIndirectCommandKHR VkCopyMemoryToImageIndirectCommandNV; typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesNV { VkStructureType sType; @@ -18916,22 +22219,21 @@ typedef struct VkPhysicalDeviceCopyMemoryIndirectFeaturesNV { VkBool32 indirectCopy; } VkPhysicalDeviceCopyMemoryIndirectFeaturesNV; -typedef struct VkPhysicalDeviceCopyMemoryIndirectPropertiesNV { - VkStructureType sType; - void* pNext; - VkQueueFlags supportedQueues; -} VkPhysicalDeviceCopyMemoryIndirectPropertiesNV; +typedef VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR VkPhysicalDeviceCopyMemoryIndirectPropertiesNV; typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride); typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToImageIndirectNV)(VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageSubresourceLayers* pImageSubresources); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryIndirectNV( VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, uint32_t copyCount, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( VkCommandBuffer commandBuffer, VkDeviceAddress copyBufferAddress, @@ -18941,6 +22243,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( VkImageLayout dstImageLayout, const VkImageSubresourceLayers* pImageSubresources); #endif +#endif // VK_NV_memory_decompression is a preprocessor guard. Do not pass it to API calls. @@ -18948,47 +22251,60 @@ VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToImageIndirectNV( #define VK_NV_MEMORY_DECOMPRESSION_SPEC_VERSION 1 #define VK_NV_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_NV_memory_decompression" -// Flag bits for VkMemoryDecompressionMethodFlagBitsNV -typedef VkFlags64 VkMemoryDecompressionMethodFlagBitsNV; -static const VkMemoryDecompressionMethodFlagBitsNV VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0x00000001ULL; +// Flag bits for VkMemoryDecompressionMethodFlagBitsEXT +typedef VkFlags64 VkMemoryDecompressionMethodFlagBitsEXT; +static const VkMemoryDecompressionMethodFlagBitsEXT VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT = 0x00000001ULL; +static const VkMemoryDecompressionMethodFlagBitsEXT VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_NV = 0x00000001ULL; + +typedef VkMemoryDecompressionMethodFlagBitsEXT VkMemoryDecompressionMethodFlagBitsNV; + +typedef VkFlags64 VkMemoryDecompressionMethodFlagsEXT; +typedef VkMemoryDecompressionMethodFlagsEXT VkMemoryDecompressionMethodFlagsNV; -typedef VkFlags64 VkMemoryDecompressionMethodFlagsNV; typedef struct VkDecompressMemoryRegionNV { - VkDeviceAddress srcAddress; - VkDeviceAddress dstAddress; - VkDeviceSize compressedSize; - VkDeviceSize decompressedSize; - VkMemoryDecompressionMethodFlagsNV decompressionMethod; + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize compressedSize; + VkDeviceSize decompressedSize; + VkMemoryDecompressionMethodFlagsEXT decompressionMethod; } VkDecompressMemoryRegionNV; -typedef struct VkPhysicalDeviceMemoryDecompressionFeaturesNV { +typedef struct VkPhysicalDeviceMemoryDecompressionFeaturesEXT { VkStructureType sType; void* pNext; VkBool32 memoryDecompression; -} VkPhysicalDeviceMemoryDecompressionFeaturesNV; +} VkPhysicalDeviceMemoryDecompressionFeaturesEXT; -typedef struct VkPhysicalDeviceMemoryDecompressionPropertiesNV { - VkStructureType sType; - void* pNext; - VkMemoryDecompressionMethodFlagsNV decompressionMethods; - uint64_t maxDecompressionIndirectCount; -} VkPhysicalDeviceMemoryDecompressionPropertiesNV; +typedef VkPhysicalDeviceMemoryDecompressionFeaturesEXT VkPhysicalDeviceMemoryDecompressionFeaturesNV; + +typedef struct VkPhysicalDeviceMemoryDecompressionPropertiesEXT { + VkStructureType sType; + void* pNext; + VkMemoryDecompressionMethodFlagsEXT decompressionMethods; + uint64_t maxDecompressionIndirectCount; +} VkPhysicalDeviceMemoryDecompressionPropertiesEXT; + +typedef VkPhysicalDeviceMemoryDecompressionPropertiesEXT VkPhysicalDeviceMemoryDecompressionPropertiesNV; typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryNV)(VkCommandBuffer commandBuffer, uint32_t decompressRegionCount, const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryIndirectCountNV)(VkCommandBuffer commandBuffer, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t stride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryNV( VkCommandBuffer commandBuffer, uint32_t decompressRegionCount, const VkDecompressMemoryRegionNV* pDecompressMemoryRegions); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountNV( VkCommandBuffer commandBuffer, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t stride); #endif +#endif // VK_NV_device_generated_commands_compute is a preprocessor guard. Do not pass it to API calls. @@ -19027,20 +22343,26 @@ typedef void (VKAPI_PTR *PFN_vkCmdUpdatePipelineIndirectBufferNV)(VkCommandBuffe typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetPipelineIndirectDeviceAddressNV)(VkDevice device, const VkPipelineIndirectDeviceAddressInfoNV* pInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPipelineIndirectMemoryRequirementsNV( VkDevice device, const VkComputePipelineCreateInfo* pCreateInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdUpdatePipelineIndirectBufferNV( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetPipelineIndirectDeviceAddressNV( VkDevice device, const VkPipelineIndirectDeviceAddressInfoNV* pInfo); #endif +#endif // VK_NV_ray_tracing_linear_swept_spheres is a preprocessor guard. Do not pass it to API calls. @@ -19287,142 +22609,204 @@ typedef void (VKAPI_PTR *PFN_vkCmdSetRepresentativeFragmentTestEnableNV)(VkComma typedef void (VKAPI_PTR *PFN_vkCmdSetCoverageReductionModeNV)(VkCommandBuffer commandBuffer, VkCoverageReductionModeNV coverageReductionMode); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthClampEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetPolygonModeEXT( VkCommandBuffer commandBuffer, VkPolygonMode polygonMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationSamplesEXT( VkCommandBuffer commandBuffer, VkSampleCountFlagBits rasterizationSamples); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleMaskEXT( VkCommandBuffer commandBuffer, VkSampleCountFlagBits samples, const VkSampleMask* pSampleMask); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToCoverageEnableEXT( VkCommandBuffer commandBuffer, VkBool32 alphaToCoverageEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetAlphaToOneEnableEXT( VkCommandBuffer commandBuffer, VkBool32 alphaToOneEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLogicOpEnableEXT( VkCommandBuffer commandBuffer, VkBool32 logicOpEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEnableEXT( VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkBool32* pColorBlendEnables); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendEquationEXT( VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendEquationEXT* pColorBlendEquations); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetColorWriteMaskEXT( VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorComponentFlags* pColorWriteMasks); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetTessellationDomainOriginEXT( VkCommandBuffer commandBuffer, VkTessellationDomainOrigin domainOrigin); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRasterizationStreamEXT( VkCommandBuffer commandBuffer, uint32_t rasterizationStream); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetConservativeRasterizationModeEXT( VkCommandBuffer commandBuffer, VkConservativeRasterizationModeEXT conservativeRasterizationMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetExtraPrimitiveOverestimationSizeEXT( VkCommandBuffer commandBuffer, float extraPrimitiveOverestimationSize); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipEnableEXT( VkCommandBuffer commandBuffer, VkBool32 depthClipEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetSampleLocationsEnableEXT( VkCommandBuffer commandBuffer, VkBool32 sampleLocationsEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetColorBlendAdvancedEXT( VkCommandBuffer commandBuffer, uint32_t firstAttachment, uint32_t attachmentCount, const VkColorBlendAdvancedEXT* pColorBlendAdvanced); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetProvokingVertexModeEXT( VkCommandBuffer commandBuffer, VkProvokingVertexModeEXT provokingVertexMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLineRasterizationModeEXT( VkCommandBuffer commandBuffer, VkLineRasterizationModeEXT lineRasterizationMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetLineStippleEnableEXT( VkCommandBuffer commandBuffer, VkBool32 stippledLineEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClipNegativeOneToOneEXT( VkCommandBuffer commandBuffer, VkBool32 negativeOneToOne); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingEnableNV( VkCommandBuffer commandBuffer, VkBool32 viewportWScalingEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportSwizzleNV( VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportSwizzleNV* pViewportSwizzles); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorEnableNV( VkCommandBuffer commandBuffer, VkBool32 coverageToColorEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageToColorLocationNV( VkCommandBuffer commandBuffer, uint32_t coverageToColorLocation); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationModeNV( VkCommandBuffer commandBuffer, VkCoverageModulationModeNV coverageModulationMode); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableEnableNV( VkCommandBuffer commandBuffer, VkBool32 coverageModulationTableEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageModulationTableNV( VkCommandBuffer commandBuffer, uint32_t coverageModulationTableCount, const float* pCoverageModulationTable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetShadingRateImageEnableNV( VkCommandBuffer commandBuffer, VkBool32 shadingRateImageEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRepresentativeFragmentTestEnableNV( VkCommandBuffer commandBuffer, VkBool32 representativeFragmentTestEnable); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetCoverageReductionModeNV( VkCommandBuffer commandBuffer, VkCoverageReductionModeNV coverageReductionMode); #endif +#endif // VK_EXT_subpass_merge_feedback is a preprocessor guard. Do not pass it to API calls. @@ -19495,7 +22879,8 @@ typedef enum VkDirectDriverLoadingModeLUNARG { } VkDirectDriverLoadingModeLUNARG; typedef VkFlags VkDirectDriverLoadingFlagsLUNARG; typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddrLUNARG)( - VkInstance instance, const char* pName); + VkInstance instance, + const char* pName); typedef struct VkDirectDriverLoadingInfoLUNARG { VkStructureType sType; @@ -19514,6 +22899,315 @@ typedef struct VkDirectDriverLoadingListLUNARG { +// VK_ARM_tensors is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_tensors 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkTensorViewARM) +#define VK_ARM_TENSORS_SPEC_VERSION 2 +#define VK_ARM_TENSORS_EXTENSION_NAME "VK_ARM_tensors" + +typedef enum VkTensorTilingARM { + VK_TENSOR_TILING_OPTIMAL_ARM = 0, + VK_TENSOR_TILING_LINEAR_ARM = 1, + VK_TENSOR_TILING_MAX_ENUM_ARM = 0x7FFFFFFF +} VkTensorTilingARM; +typedef VkFlags64 VkTensorCreateFlagsARM; + +// Flag bits for VkTensorCreateFlagBitsARM +typedef VkFlags64 VkTensorCreateFlagBitsARM; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_MUTABLE_FORMAT_BIT_ARM = 0x00000001ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_PROTECTED_BIT_ARM = 0x00000002ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_ARM = 0x00000008ULL; +static const VkTensorCreateFlagBitsARM VK_TENSOR_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_ARM = 0x00000004ULL; + +typedef VkFlags64 VkTensorUsageFlagsARM; + +// Flag bits for VkTensorUsageFlagBitsARM +typedef VkFlags64 VkTensorUsageFlagBitsARM; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_SHADER_BIT_ARM = 0x00000002ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_TRANSFER_SRC_BIT_ARM = 0x00000004ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_TRANSFER_DST_BIT_ARM = 0x00000008ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_IMAGE_ALIASING_BIT_ARM = 0x00000010ULL; +static const VkTensorUsageFlagBitsARM VK_TENSOR_USAGE_DATA_GRAPH_BIT_ARM = 0x00000020ULL; + +typedef struct VkTensorDescriptionARM { + VkStructureType sType; + const void* pNext; + VkTensorTilingARM tiling; + VkFormat format; + uint32_t dimensionCount; + const int64_t* pDimensions; + const int64_t* pStrides; + VkTensorUsageFlagsARM usage; +} VkTensorDescriptionARM; + +typedef struct VkTensorCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorCreateFlagsARM flags; + const VkTensorDescriptionARM* pDescription; + VkSharingMode sharingMode; + uint32_t queueFamilyIndexCount; + const uint32_t* pQueueFamilyIndices; +} VkTensorCreateInfoARM; + +typedef struct VkTensorMemoryRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkTensorMemoryRequirementsInfoARM; + +typedef struct VkBindTensorMemoryInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindTensorMemoryInfoARM; + +typedef struct VkWriteDescriptorSetTensorARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorViewCount; + const VkTensorViewARM* pTensorViews; +} VkWriteDescriptorSetTensorARM; + +typedef struct VkTensorFormatPropertiesARM { + VkStructureType sType; + void* pNext; + VkFormatFeatureFlags2 optimalTilingTensorFeatures; + VkFormatFeatureFlags2 linearTilingTensorFeatures; +} VkTensorFormatPropertiesARM; + +typedef struct VkPhysicalDeviceTensorPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t maxTensorDimensionCount; + uint64_t maxTensorElements; + uint64_t maxPerDimensionTensorElements; + int64_t maxTensorStride; + uint64_t maxTensorSize; + uint32_t maxTensorShaderAccessArrayLength; + uint32_t maxTensorShaderAccessSize; + uint32_t maxDescriptorSetStorageTensors; + uint32_t maxPerStageDescriptorSetStorageTensors; + uint32_t maxDescriptorSetUpdateAfterBindStorageTensors; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageTensors; + VkBool32 shaderStorageTensorArrayNonUniformIndexingNative; + VkShaderStageFlags shaderTensorSupportedStages; +} VkPhysicalDeviceTensorPropertiesARM; + +typedef struct VkTensorMemoryBarrierARM { + VkStructureType sType; + const void* pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkTensorARM tensor; +} VkTensorMemoryBarrierARM; + +typedef struct VkTensorDependencyInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorMemoryBarrierCount; + const VkTensorMemoryBarrierARM* pTensorMemoryBarriers; +} VkTensorDependencyInfoARM; + +typedef struct VkPhysicalDeviceTensorFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 tensorNonPacked; + VkBool32 shaderTensorAccess; + VkBool32 shaderStorageTensorArrayDynamicIndexing; + VkBool32 shaderStorageTensorArrayNonUniformIndexing; + VkBool32 descriptorBindingStorageTensorUpdateAfterBind; + VkBool32 tensors; +} VkPhysicalDeviceTensorFeaturesARM; + +typedef struct VkDeviceTensorMemoryRequirementsARM { + VkStructureType sType; + const void* pNext; + const VkTensorCreateInfoARM* pCreateInfo; +} VkDeviceTensorMemoryRequirementsARM; + +typedef struct VkTensorCopyARM { + VkStructureType sType; + const void* pNext; + uint32_t dimensionCount; + const uint64_t* pSrcOffset; + const uint64_t* pDstOffset; + const uint64_t* pExtent; +} VkTensorCopyARM; + +typedef struct VkCopyTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM srcTensor; + VkTensorARM dstTensor; + uint32_t regionCount; + const VkTensorCopyARM* pRegions; +} VkCopyTensorInfoARM; + +typedef struct VkMemoryDedicatedAllocateInfoTensorARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkMemoryDedicatedAllocateInfoTensorARM; + +typedef struct VkPhysicalDeviceExternalTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorCreateFlagsARM flags; + const VkTensorDescriptionARM* pDescription; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkPhysicalDeviceExternalTensorInfoARM; + +typedef struct VkExternalTensorPropertiesARM { + VkStructureType sType; + const void* pNext; + VkExternalMemoryProperties externalMemoryProperties; +} VkExternalTensorPropertiesARM; + +typedef struct VkExternalMemoryTensorCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlags handleTypes; +} VkExternalMemoryTensorCreateInfoARM; + +typedef struct VkPhysicalDeviceDescriptorBufferTensorFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 descriptorBufferTensorDescriptors; +} VkPhysicalDeviceDescriptorBufferTensorFeaturesARM; + +typedef struct VkPhysicalDeviceDescriptorBufferTensorPropertiesARM { + VkStructureType sType; + void* pNext; + size_t tensorCaptureReplayDescriptorDataSize; + size_t tensorViewCaptureReplayDescriptorDataSize; + size_t tensorDescriptorSize; +} VkPhysicalDeviceDescriptorBufferTensorPropertiesARM; + +typedef struct VkDescriptorGetTensorInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewARM tensorView; +} VkDescriptorGetTensorInfoARM; + +typedef struct VkTensorCaptureDescriptorDataInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorARM tensor; +} VkTensorCaptureDescriptorDataInfoARM; + +typedef struct VkTensorViewCaptureDescriptorDataInfoARM { + VkStructureType sType; + const void* pNext; + VkTensorViewARM tensorView; +} VkTensorViewCaptureDescriptorDataInfoARM; + +typedef struct VkFrameBoundaryTensorsARM { + VkStructureType sType; + const void* pNext; + uint32_t tensorCount; + const VkTensorARM* pTensors; +} VkFrameBoundaryTensorsARM; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateTensorARM)(VkDevice device, const VkTensorCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkTensorARM* pTensor); +typedef void (VKAPI_PTR *PFN_vkDestroyTensorARM)(VkDevice device, VkTensorARM tensor, const VkAllocationCallbacks* pAllocator); +typedef VkResult (VKAPI_PTR *PFN_vkCreateTensorViewARM)(VkDevice device, const VkTensorViewCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkTensorViewARM* pView); +typedef void (VKAPI_PTR *PFN_vkDestroyTensorViewARM)(VkDevice device, VkTensorViewARM tensorView, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetTensorMemoryRequirementsARM)(VkDevice device, const VkTensorMemoryRequirementsInfoARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindTensorMemoryARM)(VkDevice device, uint32_t bindInfoCount, const VkBindTensorMemoryInfoARM* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkGetDeviceTensorMemoryRequirementsARM)(VkDevice device, const VkDeviceTensorMemoryRequirementsARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef void (VKAPI_PTR *PFN_vkCmdCopyTensorARM)(VkCommandBuffer commandBuffer, const VkCopyTensorInfoARM* pCopyTensorInfo); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalTensorPropertiesARM)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalTensorInfoARM* pExternalTensorInfo, VkExternalTensorPropertiesARM* pExternalTensorProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorOpaqueCaptureDescriptorDataARM)(VkDevice device, const VkTensorCaptureDescriptorDataInfoARM* pInfo, void* pData); +typedef VkResult (VKAPI_PTR *PFN_vkGetTensorViewOpaqueCaptureDescriptorDataARM)(VkDevice device, const VkTensorViewCaptureDescriptorDataInfoARM* pInfo, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateTensorARM( + VkDevice device, + const VkTensorCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkTensorARM* pTensor); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyTensorARM( + VkDevice device, + VkTensorARM tensor, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateTensorViewARM( + VkDevice device, + const VkTensorViewCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkTensorViewARM* pView); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyTensorViewARM( + VkDevice device, + VkTensorViewARM tensorView, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetTensorMemoryRequirementsARM( + VkDevice device, + const VkTensorMemoryRequirementsInfoARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindTensorMemoryARM( + VkDevice device, + uint32_t bindInfoCount, + const VkBindTensorMemoryInfoARM* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDeviceTensorMemoryRequirementsARM( + VkDevice device, + const VkDeviceTensorMemoryRequirementsARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCopyTensorARM( + VkCommandBuffer commandBuffer, + const VkCopyTensorInfoARM* pCopyTensorInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalTensorPropertiesARM( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalTensorInfoARM* pExternalTensorInfo, + VkExternalTensorPropertiesARM* pExternalTensorProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorOpaqueCaptureDescriptorDataARM( + VkDevice device, + const VkTensorCaptureDescriptorDataInfoARM* pInfo, + void* pData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetTensorViewOpaqueCaptureDescriptorDataARM( + VkDevice device, + const VkTensorViewCaptureDescriptorDataInfoARM* pInfo, + void* pData); +#endif +#endif + + // VK_EXT_shader_module_identifier is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_shader_module_identifier 1 #define VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 32U @@ -19549,16 +23243,20 @@ typedef void (VKAPI_PTR *PFN_vkGetShaderModuleIdentifierEXT)(VkDevice device, Vk typedef void (VKAPI_PTR *PFN_vkGetShaderModuleCreateInfoIdentifierEXT)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModuleIdentifierEXT* pIdentifier); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleIdentifierEXT( VkDevice device, VkShaderModule shaderModule, VkShaderModuleIdentifierEXT* pIdentifier); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetShaderModuleCreateInfoIdentifierEXT( VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModuleIdentifierEXT* pIdentifier); #endif +#endif // VK_EXT_rasterization_order_attachment_access is a preprocessor guard. Do not pass it to API calls. @@ -19660,7 +23358,7 @@ typedef struct VkOpticalFlowImageFormatInfoNV { typedef struct VkOpticalFlowImageFormatPropertiesNV { VkStructureType sType; - const void* pNext; + void* pNext; VkFormat format; } VkOpticalFlowImageFormatPropertiesNV; @@ -19701,35 +23399,45 @@ typedef VkResult (VKAPI_PTR *PFN_vkBindOpticalFlowSessionImageNV)(VkDevice devic typedef void (VKAPI_PTR *PFN_vkCmdOpticalFlowExecuteNV)(VkCommandBuffer commandBuffer, VkOpticalFlowSessionNV session, const VkOpticalFlowExecuteInfoNV* pExecuteInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceOpticalFlowImageFormatsNV( VkPhysicalDevice physicalDevice, const VkOpticalFlowImageFormatInfoNV* pOpticalFlowImageFormatInfo, uint32_t* pFormatCount, VkOpticalFlowImageFormatPropertiesNV* pImageFormatProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateOpticalFlowSessionNV( VkDevice device, const VkOpticalFlowSessionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkOpticalFlowSessionNV* pSession); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyOpticalFlowSessionNV( VkDevice device, VkOpticalFlowSessionNV session, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBindOpticalFlowSessionImageNV( VkDevice device, VkOpticalFlowSessionNV session, VkOpticalFlowSessionBindingPointNV bindingPoint, VkImageView view, VkImageLayout layout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdOpticalFlowExecuteNV( VkCommandBuffer commandBuffer, VkOpticalFlowSessionNV session, const VkOpticalFlowExecuteInfoNV* pExecuteInfo); #endif +#endif // VK_EXT_legacy_dithering is a preprocessor guard. Do not pass it to API calls. @@ -19793,10 +23501,12 @@ typedef struct VkAntiLagDataAMD { typedef void (VKAPI_PTR *PFN_vkAntiLagUpdateAMD)(VkDevice device, const VkAntiLagDataAMD* pData); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkAntiLagUpdateAMD( VkDevice device, const VkAntiLagDataAMD* pData); #endif +#endif // VK_EXT_shader_object is a preprocessor guard. Do not pass it to API calls. @@ -19819,6 +23529,8 @@ typedef enum VkDepthClampModeEXT { typedef enum VkShaderCreateFlagBitsEXT { VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001, + VK_SHADER_CREATE_DESCRIPTOR_HEAP_BIT_EXT = 0x00000400, + VK_SHADER_CREATE_INSTRUMENT_SHADER_BIT_ARM = 0x00000800, VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002, VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004, VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008, @@ -19826,6 +23538,9 @@ typedef enum VkShaderCreateFlagBitsEXT { VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020, VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040, VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT = 0x00000080, + VK_SHADER_CREATE_OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX_BIT_EXT = 0x00001000, + VK_SHADER_CREATE_64_BIT_INDEXING_BIT_EXT = 0x00008000, + VK_SHADER_CREATE_INDEPENDENT_SETS_BIT_KHR = 0x00040000, VK_SHADER_CREATE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkShaderCreateFlagBitsEXT; typedef VkFlags VkShaderCreateFlagsEXT; @@ -19873,35 +23588,45 @@ typedef void (VKAPI_PTR *PFN_vkCmdBindShadersEXT)(VkCommandBuffer commandBuffer, typedef void (VKAPI_PTR *PFN_vkCmdSetDepthClampRangeEXT)(VkCommandBuffer commandBuffer, VkDepthClampModeEXT depthClampMode, const VkDepthClampRangeEXT* pDepthClampRange); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateShadersEXT( VkDevice device, uint32_t createInfoCount, const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkShaderEXT* pShaders); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyShaderEXT( VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderBinaryDataEXT( VkDevice device, VkShaderEXT shader, size_t* pDataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBindShadersEXT( VkCommandBuffer commandBuffer, uint32_t stageCount, const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthClampRangeEXT( VkCommandBuffer commandBuffer, VkDepthClampModeEXT depthClampMode, const VkDepthClampRangeEXT* pDepthClampRange); #endif +#endif // VK_QCOM_tile_properties is a preprocessor guard. Do not pass it to API calls. @@ -19926,17 +23651,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetFramebufferTilePropertiesQCOM)(VkDevice de typedef VkResult (VKAPI_PTR *PFN_vkGetDynamicRenderingTilePropertiesQCOM)(VkDevice device, const VkRenderingInfo* pRenderingInfo, VkTilePropertiesQCOM* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetFramebufferTilePropertiesQCOM( VkDevice device, VkFramebuffer framebuffer, uint32_t* pPropertiesCount, VkTilePropertiesQCOM* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDynamicRenderingTilePropertiesQCOM( VkDevice device, const VkRenderingInfo* pRenderingInfo, VkTilePropertiesQCOM* pProperties); #endif +#endif // VK_SEC_amigo_profiling is a preprocessor guard. Do not pass it to API calls. @@ -19975,15 +23704,19 @@ typedef struct VkPhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM { #define VK_NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 1 #define VK_NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_NV_ray_tracing_invocation_reorder" -typedef enum VkRayTracingInvocationReorderModeNV { - VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = 0, - VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = 1, - VK_RAY_TRACING_INVOCATION_REORDER_MODE_MAX_ENUM_NV = 0x7FFFFFFF -} VkRayTracingInvocationReorderModeNV; +typedef enum VkRayTracingInvocationReorderModeEXT { + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_EXT = 0, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_EXT = 1, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_NV = VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_EXT, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_NV = VK_RAY_TRACING_INVOCATION_REORDER_MODE_REORDER_EXT, + VK_RAY_TRACING_INVOCATION_REORDER_MODE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkRayTracingInvocationReorderModeEXT; +typedef VkRayTracingInvocationReorderModeEXT VkRayTracingInvocationReorderModeNV; + typedef struct VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV { - VkStructureType sType; - void* pNext; - VkRayTracingInvocationReorderModeNV rayTracingInvocationReorderReorderingHint; + VkStructureType sType; + void* pNext; + VkRayTracingInvocationReorderModeEXT rayTracingInvocationReorderReorderingHint; } VkPhysicalDeviceRayTracingInvocationReorderPropertiesNV; typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesNV { @@ -20055,20 +23788,26 @@ typedef VkResult (VKAPI_PTR *PFN_vkConvertCooperativeVectorMatrixNV)(VkDevice de typedef void (VKAPI_PTR *PFN_vkCmdConvertCooperativeVectorMatrixNV)(VkCommandBuffer commandBuffer, uint32_t infoCount, const VkConvertCooperativeVectorMatrixInfoNV* pInfos); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeVectorPropertiesNV( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeVectorPropertiesNV* pProperties); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkConvertCooperativeVectorMatrixNV( VkDevice device, const VkConvertCooperativeVectorMatrixInfoNV* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdConvertCooperativeVectorMatrixNV( VkCommandBuffer commandBuffer, uint32_t infoCount, const VkConvertCooperativeVectorMatrixInfoNV* pInfos); #endif +#endif // VK_NV_extended_sparse_address_space is a preprocessor guard. Do not pass it to API calls. @@ -20242,7 +23981,7 @@ typedef struct VkSetLatencyMarkerInfoNV { typedef struct VkLatencyTimingsFrameReportNV { VkStructureType sType; - const void* pNext; + void* pNext; uint64_t presentID; uint64_t inputSampleTimeUs; uint64_t simStartTimeUs; @@ -20298,30 +24037,406 @@ typedef void (VKAPI_PTR *PFN_vkGetLatencyTimingsNV)(VkDevice device, VkSwapchain typedef void (VKAPI_PTR *PFN_vkQueueNotifyOutOfBandNV)(VkQueue queue, const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkSetLatencySleepModeNV( VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepModeInfoNV* pSleepModeInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkLatencySleepNV( VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkSetLatencyMarkerNV( VkDevice device, VkSwapchainKHR swapchain, const VkSetLatencyMarkerInfoNV* pLatencyMarkerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetLatencyTimingsNV( VkDevice device, VkSwapchainKHR swapchain, VkGetLatencyMarkerInfoNV* pLatencyMarkerInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkQueueNotifyOutOfBandNV( VkQueue queue, const VkOutOfBandQueueTypeInfoNV* pQueueTypeInfo); #endif +#endif + + +// VK_ARM_data_graph is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDataGraphPipelineSessionARM) +#define VK_MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM 128U +#define VK_ARM_DATA_GRAPH_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_EXTENSION_NAME "VK_ARM_data_graph" + +typedef enum VkDataGraphPipelineSessionBindPointARM { + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TRANSIENT_ARM = 0, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_OPTICAL_FLOW_CACHE_ARM = 1000631001, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_NEURAL_ACCELERATOR_STATISTICS_ARM = 1000676000, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineSessionBindPointARM; + +typedef enum VkDataGraphPipelineSessionBindPointTypeARM { + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TYPE_MEMORY_ARM = 0, + VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineSessionBindPointTypeARM; + +typedef enum VkDataGraphPipelinePropertyARM { + VK_DATA_GRAPH_PIPELINE_PROPERTY_CREATION_LOG_ARM = 0, + VK_DATA_GRAPH_PIPELINE_PROPERTY_IDENTIFIER_ARM = 1, + VK_DATA_GRAPH_PIPELINE_PROPERTY_NEURAL_ACCELERATOR_DEBUG_DATABASE_ARM = 1000676000, + VK_DATA_GRAPH_PIPELINE_PROPERTY_NEURAL_ACCELERATOR_STATISTICS_INFO_ARM = 1000676001, + VK_DATA_GRAPH_PIPELINE_PROPERTY_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelinePropertyARM; + +typedef enum VkPhysicalDeviceDataGraphProcessingEngineTypeARM { + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_DEFAULT_ARM = 0, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_NEURAL_QCOM = 1000629000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_COMPUTE_QCOM = 1000629001, + VK_PHYSICAL_DEVICE_DATA_GRAPH_PROCESSING_ENGINE_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkPhysicalDeviceDataGraphProcessingEngineTypeARM; + +typedef enum VkPhysicalDeviceDataGraphOperationTypeARM { + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_SPIRV_EXTENDED_INSTRUCTION_SET_ARM = 0, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_NEURAL_MODEL_QCOM = 1000629000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_BUILTIN_MODEL_QCOM = 1000629001, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_OPTICAL_FLOW_ARM = 1000631000, + VK_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkPhysicalDeviceDataGraphOperationTypeARM; +typedef VkFlags64 VkDataGraphPipelineSessionCreateFlagsARM; + +// Flag bits for VkDataGraphPipelineSessionCreateFlagBitsARM +typedef VkFlags64 VkDataGraphPipelineSessionCreateFlagBitsARM; +static const VkDataGraphPipelineSessionCreateFlagBitsARM VK_DATA_GRAPH_PIPELINE_SESSION_CREATE_PROTECTED_BIT_ARM = 0x00000001ULL; +static const VkDataGraphPipelineSessionCreateFlagBitsARM VK_DATA_GRAPH_PIPELINE_SESSION_CREATE_OPTICAL_FLOW_CACHE_BIT_ARM = 0x00000002ULL; + +typedef VkFlags64 VkDataGraphPipelineDispatchFlagsARM; + +// Flag bits for VkDataGraphPipelineDispatchFlagBitsARM +typedef VkFlags64 VkDataGraphPipelineDispatchFlagBitsARM; + +typedef struct VkPhysicalDeviceDataGraphFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraph; + VkBool32 dataGraphUpdateAfterBind; + VkBool32 dataGraphSpecializationConstants; + VkBool32 dataGraphDescriptorBuffer; + VkBool32 dataGraphShaderModule; +} VkPhysicalDeviceDataGraphFeaturesARM; + +typedef struct VkDataGraphPipelineConstantARM { + VkStructureType sType; + const void* pNext; + uint32_t id; + const void* pConstantData; +} VkDataGraphPipelineConstantARM; + +typedef struct VkDataGraphPipelineResourceInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t descriptorSet; + uint32_t binding; + uint32_t arrayElement; +} VkDataGraphPipelineResourceInfoARM; + +typedef struct VkDataGraphPipelineCompilerControlCreateInfoARM { + VkStructureType sType; + const void* pNext; + const char* pVendorOptions; +} VkDataGraphPipelineCompilerControlCreateInfoARM; + +typedef struct VkDataGraphPipelineCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags2 flags; + VkPipelineLayout layout; + uint32_t resourceInfoCount; + const VkDataGraphPipelineResourceInfoARM* pResourceInfos; +} VkDataGraphPipelineCreateInfoARM; + +typedef struct VkDataGraphPipelineShaderModuleCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkShaderModule module; + const char* pName; + const VkSpecializationInfo* pSpecializationInfo; + uint32_t constantCount; + const VkDataGraphPipelineConstantARM* pConstants; +} VkDataGraphPipelineShaderModuleCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionCreateFlagsARM flags; + VkPipeline dataGraphPipeline; +} VkDataGraphPipelineSessionCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionBindPointRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; +} VkDataGraphPipelineSessionBindPointRequirementsInfoARM; + +typedef struct VkDataGraphPipelineSessionBindPointRequirementARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineSessionBindPointARM bindPoint; + VkDataGraphPipelineSessionBindPointTypeARM bindPointType; + uint32_t numObjects; +} VkDataGraphPipelineSessionBindPointRequirementARM; + +typedef struct VkDataGraphPipelineSessionMemoryRequirementsInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; + VkDataGraphPipelineSessionBindPointARM bindPoint; + uint32_t objectIndex; +} VkDataGraphPipelineSessionMemoryRequirementsInfoARM; + +typedef struct VkBindDataGraphPipelineSessionMemoryInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphPipelineSessionARM session; + VkDataGraphPipelineSessionBindPointARM bindPoint; + uint32_t objectIndex; + VkDeviceMemory memory; + VkDeviceSize memoryOffset; +} VkBindDataGraphPipelineSessionMemoryInfoARM; + +typedef struct VkDataGraphPipelineInfoARM { + VkStructureType sType; + const void* pNext; + VkPipeline dataGraphPipeline; +} VkDataGraphPipelineInfoARM; + +typedef struct VkDataGraphPipelinePropertyQueryResultARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelinePropertyARM property; + VkBool32 isText; + size_t dataSize; + void* pData; +} VkDataGraphPipelinePropertyQueryResultARM; + +typedef struct VkDataGraphPipelineIdentifierCreateInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t identifierSize; + const uint8_t* pIdentifier; +} VkDataGraphPipelineIdentifierCreateInfoARM; + +typedef struct VkDataGraphPipelineDispatchInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineDispatchFlagsARM flags; +} VkDataGraphPipelineDispatchInfoARM; + +typedef struct VkPhysicalDeviceDataGraphProcessingEngineARM { + VkPhysicalDeviceDataGraphProcessingEngineTypeARM type; + VkBool32 isForeign; +} VkPhysicalDeviceDataGraphProcessingEngineARM; + +typedef struct VkPhysicalDeviceDataGraphOperationSupportARM { + VkPhysicalDeviceDataGraphOperationTypeARM operationType; + char name[VK_MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM]; + uint32_t version; +} VkPhysicalDeviceDataGraphOperationSupportARM; + +typedef struct VkQueueFamilyDataGraphPropertiesARM { + VkStructureType sType; + void* pNext; + VkPhysicalDeviceDataGraphProcessingEngineARM engine; + VkPhysicalDeviceDataGraphOperationSupportARM operation; +} VkQueueFamilyDataGraphPropertiesARM; + +typedef struct VkDataGraphProcessingEngineCreateInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t processingEngineCount; + VkPhysicalDeviceDataGraphProcessingEngineARM* pProcessingEngines; +} VkDataGraphProcessingEngineCreateInfoARM; + +typedef struct VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t queueFamilyIndex; + VkPhysicalDeviceDataGraphProcessingEngineTypeARM engineType; +} VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM; + +typedef struct VkQueueFamilyDataGraphProcessingEnginePropertiesARM { + VkStructureType sType; + void* pNext; + VkExternalSemaphoreHandleTypeFlags foreignSemaphoreHandleTypes; + VkExternalMemoryHandleTypeFlags foreignMemoryHandleTypes; +} VkQueueFamilyDataGraphProcessingEnginePropertiesARM; + +typedef struct VkDataGraphPipelineConstantTensorSemiStructuredSparsityInfoARM { + VkStructureType sType; + const void* pNext; + uint32_t dimension; + uint32_t zeroCount; + uint32_t groupSize; +} VkDataGraphPipelineConstantTensorSemiStructuredSparsityInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateDataGraphPipelinesARM)(VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkDataGraphPipelineCreateInfoARM* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkCreateDataGraphPipelineSessionARM)(VkDevice device, const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDataGraphPipelineSessionARM* pSession); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelineSessionBindPointRequirementsARM)(VkDevice device, const VkDataGraphPipelineSessionBindPointRequirementsInfoARM* pInfo, uint32_t* pBindPointRequirementCount, VkDataGraphPipelineSessionBindPointRequirementARM* pBindPointRequirements); +typedef void (VKAPI_PTR *PFN_vkGetDataGraphPipelineSessionMemoryRequirementsARM)(VkDevice device, const VkDataGraphPipelineSessionMemoryRequirementsInfoARM* pInfo, VkMemoryRequirements2* pMemoryRequirements); +typedef VkResult (VKAPI_PTR *PFN_vkBindDataGraphPipelineSessionMemoryARM)(VkDevice device, uint32_t bindInfoCount, const VkBindDataGraphPipelineSessionMemoryInfoARM* pBindInfos); +typedef void (VKAPI_PTR *PFN_vkDestroyDataGraphPipelineSessionARM)(VkDevice device, VkDataGraphPipelineSessionARM session, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchDataGraphARM)(VkCommandBuffer commandBuffer, VkDataGraphPipelineSessionARM session, const VkDataGraphPipelineDispatchInfoARM* pInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelineAvailablePropertiesARM)(VkDevice device, const VkDataGraphPipelineInfoARM* pPipelineInfo, uint32_t* pPropertiesCount, VkDataGraphPipelinePropertyARM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetDataGraphPipelinePropertiesARM)(VkDevice device, const VkDataGraphPipelineInfoARM* pPipelineInfo, uint32_t propertiesCount, VkDataGraphPipelinePropertyQueryResultARM* pProperties); +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pQueueFamilyDataGraphPropertyCount, VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties); +typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo, VkQueueFamilyDataGraphProcessingEnginePropertiesARM* pQueueFamilyDataGraphProcessingEngineProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDataGraphPipelinesARM( + VkDevice device, + VkDeferredOperationKHR deferredOperation, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkDataGraphPipelineCreateInfoARM* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDataGraphPipelineSessionARM( + VkDevice device, + const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDataGraphPipelineSessionARM* pSession); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelineSessionBindPointRequirementsARM( + VkDevice device, + const VkDataGraphPipelineSessionBindPointRequirementsInfoARM* pInfo, + uint32_t* pBindPointRequirementCount, + VkDataGraphPipelineSessionBindPointRequirementARM* pBindPointRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetDataGraphPipelineSessionMemoryRequirementsARM( + VkDevice device, + const VkDataGraphPipelineSessionMemoryRequirementsInfoARM* pInfo, + VkMemoryRequirements2* pMemoryRequirements); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkBindDataGraphPipelineSessionMemoryARM( + VkDevice device, + uint32_t bindInfoCount, + const VkBindDataGraphPipelineSessionMemoryInfoARM* pBindInfos); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyDataGraphPipelineSessionARM( + VkDevice device, + VkDataGraphPipelineSessionARM session, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchDataGraphARM( + VkCommandBuffer commandBuffer, + VkDataGraphPipelineSessionARM session, + const VkDataGraphPipelineDispatchInfoARM* pInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelineAvailablePropertiesARM( + VkDevice device, + const VkDataGraphPipelineInfoARM* pPipelineInfo, + uint32_t* pPropertiesCount, + VkDataGraphPipelinePropertyARM* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetDataGraphPipelinePropertiesARM( + VkDevice device, + const VkDataGraphPipelineInfoARM* pPipelineInfo, + uint32_t propertiesCount, + VkDataGraphPipelinePropertyQueryResultARM* pProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pQueueFamilyDataGraphPropertyCount, + VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM* pQueueFamilyDataGraphProcessingEngineInfo, + VkQueueFamilyDataGraphProcessingEnginePropertiesARM* pQueueFamilyDataGraphProcessingEngineProperties); +#endif +#endif + + +// VK_ARM_data_graph_instruction_set_tosa is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_instruction_set_tosa 1 +#define VK_MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM 128U +#define VK_ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_EXTENSION_NAME "VK_ARM_data_graph_instruction_set_tosa" + +typedef enum VkDataGraphTOSALevelARM { + VK_DATA_GRAPH_TOSA_LEVEL_NONE_ARM = 0, + VK_DATA_GRAPH_TOSA_LEVEL_8K_ARM = 1, + VK_DATA_GRAPH_TOSALEVEL_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphTOSALevelARM; + +typedef enum VkDataGraphTOSAQualityFlagBitsARM { + VK_DATA_GRAPH_TOSA_QUALITY_ACCELERATED_ARM = 0x00000001, + VK_DATA_GRAPH_TOSA_QUALITY_CONFORMANT_ARM = 0x00000002, + VK_DATA_GRAPH_TOSA_QUALITY_EXPERIMENTAL_ARM = 0x00000004, + VK_DATA_GRAPH_TOSA_QUALITY_DEPRECATED_ARM = 0x00000008, + VK_DATA_GRAPH_TOSAQUALITY_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphTOSAQualityFlagBitsARM; +typedef VkFlags VkDataGraphTOSAQualityFlagsARM; +typedef struct VkDataGraphTOSANameQualityARM { + char name[VK_MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM]; + VkDataGraphTOSAQualityFlagsARM qualityFlags; +} VkDataGraphTOSANameQualityARM; + +typedef struct VkQueueFamilyDataGraphTOSAPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t profileCount; + const VkDataGraphTOSANameQualityARM* pProfiles; + uint32_t extensionCount; + const VkDataGraphTOSANameQualityARM* pExtensions; + VkDataGraphTOSALevelARM level; +} VkQueueFamilyDataGraphTOSAPropertiesARM; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, VkBaseOutStructure* pProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, + VkBaseOutStructure* pProperties); +#endif +#endif // VK_QCOM_multiview_per_view_render_areas is a preprocessor guard. Do not pass it to API calls. @@ -20463,10 +24578,12 @@ typedef struct VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT { typedef void (VKAPI_PTR *PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT)(VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetAttachmentFeedbackLoopEnableEXT( VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask); #endif +#endif // VK_MSFT_layered_driver is a preprocessor guard. Do not pass it to API calls. @@ -20499,6 +24616,94 @@ typedef struct VkPhysicalDeviceDescriptorPoolOverallocationFeaturesNV { +// VK_QCOM_tile_memory_heap is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_tile_memory_heap 1 +#define VK_QCOM_TILE_MEMORY_HEAP_SPEC_VERSION 1 +#define VK_QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME "VK_QCOM_tile_memory_heap" +typedef struct VkPhysicalDeviceTileMemoryHeapFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 tileMemoryHeap; +} VkPhysicalDeviceTileMemoryHeapFeaturesQCOM; + +typedef struct VkPhysicalDeviceTileMemoryHeapPropertiesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 queueSubmitBoundary; + VkBool32 tileBufferTransfers; +} VkPhysicalDeviceTileMemoryHeapPropertiesQCOM; + +typedef struct VkTileMemoryRequirementsQCOM { + VkStructureType sType; + void* pNext; + VkDeviceSize size; + VkDeviceSize alignment; +} VkTileMemoryRequirementsQCOM; + +typedef struct VkTileMemoryBindInfoQCOM { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; +} VkTileMemoryBindInfoQCOM; + +typedef struct VkTileMemorySizeInfoQCOM { + VkStructureType sType; + const void* pNext; + VkDeviceSize size; +} VkTileMemorySizeInfoQCOM; + +typedef void (VKAPI_PTR *PFN_vkCmdBindTileMemoryQCOM)(VkCommandBuffer commandBuffer, const VkTileMemoryBindInfoQCOM* pTileMemoryBindInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBindTileMemoryQCOM( + VkCommandBuffer commandBuffer, + const VkTileMemoryBindInfoQCOM* pTileMemoryBindInfo); +#endif +#endif + + +// VK_EXT_memory_decompression is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_memory_decompression 1 +#define VK_EXT_MEMORY_DECOMPRESSION_SPEC_VERSION 1 +#define VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME "VK_EXT_memory_decompression" +typedef struct VkDecompressMemoryRegionEXT { + VkDeviceAddress srcAddress; + VkDeviceAddress dstAddress; + VkDeviceSize compressedSize; + VkDeviceSize decompressedSize; +} VkDecompressMemoryRegionEXT; + +typedef struct VkDecompressMemoryInfoEXT { + VkStructureType sType; + const void* pNext; + VkMemoryDecompressionMethodFlagsEXT decompressionMethod; + uint32_t regionCount; + const VkDecompressMemoryRegionEXT* pRegions; +} VkDecompressMemoryInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryEXT)(VkCommandBuffer commandBuffer, const VkDecompressMemoryInfoEXT* pDecompressMemoryInfoEXT); +typedef void (VKAPI_PTR *PFN_vkCmdDecompressMemoryIndirectCountEXT)(VkCommandBuffer commandBuffer, VkMemoryDecompressionMethodFlagsEXT decompressionMethod, VkDeviceAddress indirectCommandsAddress, VkDeviceAddress indirectCommandsCountAddress, uint32_t maxDecompressionCount, uint32_t stride); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryEXT( + VkCommandBuffer commandBuffer, + const VkDecompressMemoryInfoEXT* pDecompressMemoryInfoEXT); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDecompressMemoryIndirectCountEXT( + VkCommandBuffer commandBuffer, + VkMemoryDecompressionMethodFlagsEXT decompressionMethod, + VkDeviceAddress indirectCommandsAddress, + VkDeviceAddress indirectCommandsCountAddress, + uint32_t maxDecompressionCount, + uint32_t stride); +#endif +#endif + + // VK_NV_display_stereo is a preprocessor guard. Do not pass it to API calls. #define VK_NV_display_stereo 1 #define VK_NV_DISPLAY_STEREO_SPEC_VERSION 1 @@ -20519,7 +24724,7 @@ typedef struct VkDisplaySurfaceStereoCreateInfoNV { typedef struct VkDisplayModeStereoPropertiesNV { VkStructureType sType; - const void* pNext; + void* pNext; VkBool32 hdmi3DSupported; } VkDisplayModeStereoPropertiesNV; @@ -20537,6 +24742,65 @@ typedef struct VkPhysicalDeviceRawAccessChainsFeaturesNV { +// VK_NV_external_compute_queue is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_external_compute_queue 1 +VK_DEFINE_HANDLE(VkExternalComputeQueueNV) +#define VK_NV_EXTERNAL_COMPUTE_QUEUE_SPEC_VERSION 1 +#define VK_NV_EXTERNAL_COMPUTE_QUEUE_EXTENSION_NAME "VK_NV_external_compute_queue" +typedef struct VkExternalComputeQueueDeviceCreateInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t reservedExternalQueues; +} VkExternalComputeQueueDeviceCreateInfoNV; + +typedef struct VkExternalComputeQueueCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkQueue preferredQueue; +} VkExternalComputeQueueCreateInfoNV; + +typedef struct VkExternalComputeQueueDataParamsNV { + VkStructureType sType; + const void* pNext; + uint32_t deviceIndex; +} VkExternalComputeQueueDataParamsNV; + +typedef struct VkPhysicalDeviceExternalComputeQueuePropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t externalDataSize; + uint32_t maxExternalQueues; +} VkPhysicalDeviceExternalComputeQueuePropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateExternalComputeQueueNV)(VkDevice device, const VkExternalComputeQueueCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkExternalComputeQueueNV* pExternalQueue); +typedef void (VKAPI_PTR *PFN_vkDestroyExternalComputeQueueNV)(VkDevice device, VkExternalComputeQueueNV externalQueue, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkGetExternalComputeQueueDataNV)(VkExternalComputeQueueNV externalQueue, VkExternalComputeQueueDataParamsNV* params, void* pData); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExternalComputeQueueNV( + VkDevice device, + const VkExternalComputeQueueCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkExternalComputeQueueNV* pExternalQueue); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyExternalComputeQueueNV( + VkDevice device, + VkExternalComputeQueueNV externalQueue, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkGetExternalComputeQueueDataNV( + VkExternalComputeQueueNV externalQueue, + VkExternalComputeQueueDataParamsNV* params, + void* pData); +#endif +#endif + + // VK_NV_command_buffer_inheritance is a preprocessor guard. Do not pass it to API calls. #define VK_NV_command_buffer_inheritance 1 #define VK_NV_COMMAND_BUFFER_INHERITANCE_SPEC_VERSION 1 @@ -20573,6 +24837,19 @@ typedef struct VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT { +// VK_EXT_shader_float8 is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_float8 1 +#define VK_EXT_SHADER_FLOAT8_SPEC_VERSION 1 +#define VK_EXT_SHADER_FLOAT8_EXTENSION_NAME "VK_EXT_shader_float8" +typedef struct VkPhysicalDeviceShaderFloat8FeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderFloat8; + VkBool32 shaderFloat8CooperativeMatrix; +} VkPhysicalDeviceShaderFloat8FeaturesEXT; + + + // VK_NV_ray_tracing_validation is a preprocessor guard. Do not pass it to API calls. #define VK_NV_ray_tracing_validation 1 #define VK_NV_RAY_TRACING_VALIDATION_SPEC_VERSION 1 @@ -20587,7 +24864,7 @@ typedef struct VkPhysicalDeviceRayTracingValidationFeaturesNV { // VK_NV_cluster_acceleration_structure is a preprocessor guard. Do not pass it to API calls. #define VK_NV_cluster_acceleration_structure 1 -#define VK_NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION 2 +#define VK_NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION 4 #define VK_NV_CLUSTER_ACCELERATION_STRUCTURE_EXTENSION_NAME "VK_NV_cluster_acceleration_structure" typedef enum VkClusterAccelerationStructureTypeNV { @@ -20603,6 +24880,7 @@ typedef enum VkClusterAccelerationStructureOpTypeNV { VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_BUILD_TRIANGLE_CLUSTER_NV = 2, VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_BUILD_TRIANGLE_CLUSTER_TEMPLATE_NV = 3, VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_INSTANTIATE_TRIANGLE_CLUSTER_NV = 4, + VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_GET_CLUSTER_TEMPLATE_INDICES_NV = 5, VK_CLUSTER_ACCELERATION_STRUCTURE_OP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF } VkClusterAccelerationStructureOpTypeNV; @@ -20614,6 +24892,7 @@ typedef enum VkClusterAccelerationStructureOpModeNV { } VkClusterAccelerationStructureOpModeNV; typedef enum VkClusterAccelerationStructureAddressResolutionFlagBitsNV { + VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_NONE_NV = 0, VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_DST_IMPLICIT_DATA_BIT_NV = 0x00000001, VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_SCRATCH_DATA_BIT_NV = 0x00000002, VK_CLUSTER_ACCELERATION_STRUCTURE_ADDRESS_RESOLUTION_INDIRECTED_DST_ADDRESS_ARRAY_BIT_NV = 0x00000004, @@ -20797,9 +25076,13 @@ typedef struct VkClusterAccelerationStructureInstantiateClusterInfoNV { VkStridedDeviceAddressNV vertexBuffer; } VkClusterAccelerationStructureInstantiateClusterInfoNV; +typedef struct VkClusterAccelerationStructureGetTemplateIndicesInfoNV { + VkDeviceAddress clusterTemplateAddress; +} VkClusterAccelerationStructureGetTemplateIndicesInfoNV; + typedef struct VkAccelerationStructureBuildSizesInfoKHR { VkStructureType sType; - const void* pNext; + void* pNext; VkDeviceSize accelerationStructureSize; VkDeviceSize updateScratchSize; VkDeviceSize buildScratchSize; @@ -20815,15 +25098,19 @@ typedef void (VKAPI_PTR *PFN_vkGetClusterAccelerationStructureBuildSizesNV)(VkDe typedef void (VKAPI_PTR *PFN_vkCmdBuildClusterAccelerationStructureIndirectNV)(VkCommandBuffer commandBuffer, const VkClusterAccelerationStructureCommandsInfoNV* pCommandInfos); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetClusterAccelerationStructureBuildSizesNV( VkDevice device, const VkClusterAccelerationStructureInputInfoNV* pInfo, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildClusterAccelerationStructureIndirectNV( VkCommandBuffer commandBuffer, const VkClusterAccelerationStructureCommandsInfoNV* pCommandInfos); #endif +#endif // VK_NV_partitioned_acceleration_structure is a preprocessor guard. Do not pass it to API calls. @@ -20927,15 +25214,19 @@ typedef void (VKAPI_PTR *PFN_vkGetPartitionedAccelerationStructuresBuildSizesNV) typedef void (VKAPI_PTR *PFN_vkCmdBuildPartitionedAccelerationStructuresNV)(VkCommandBuffer commandBuffer, const VkBuildPartitionedAccelerationStructureInfoNV* pBuildInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetPartitionedAccelerationStructuresBuildSizesNV( VkDevice device, const VkPartitionedAccelerationStructureInstancesInputNV* pInfo, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildPartitionedAccelerationStructuresNV( VkCommandBuffer commandBuffer, const VkBuildPartitionedAccelerationStructureInfoNV* pBuildInfo); #endif +#endif // VK_EXT_device_generated_commands is a preprocessor guard. Do not pass it to API calls. @@ -20962,6 +25253,8 @@ typedef enum VkIndirectCommandsTokenTypeEXT { VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_COUNT_EXT = 7, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_COUNT_EXT = 8, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT = 9, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_EXT = 1000135000, + VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_DATA_SEQUENCE_INDEX_EXT = 1000135001, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV_EXT = 1000202002, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_NV_EXT = 1000202003, VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT = 1000328000, @@ -21167,55 +25460,73 @@ typedef void (VKAPI_PTR *PFN_vkUpdateIndirectExecutionSetPipelineEXT)(VkDevice d typedef void (VKAPI_PTR *PFN_vkUpdateIndirectExecutionSetShaderEXT)(VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, uint32_t executionSetWriteCount, const VkWriteIndirectExecutionSetShaderEXT* pExecutionSetWrites); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsEXT( VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoEXT* pInfo, VkMemoryRequirements2* pMemoryRequirements); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsEXT( VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo, VkCommandBuffer stateCommandBuffer); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsEXT( VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutEXT( VkDevice device, const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutEXT* pIndirectCommandsLayout); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutEXT( VkDevice device, VkIndirectCommandsLayoutEXT indirectCommandsLayout, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectExecutionSetEXT( VkDevice device, const VkIndirectExecutionSetCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectExecutionSetEXT* pIndirectExecutionSet); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectExecutionSetEXT( VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkUpdateIndirectExecutionSetPipelineEXT( VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, uint32_t executionSetWriteCount, const VkWriteIndirectExecutionSetPipelineEXT* pExecutionSetWrites); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkUpdateIndirectExecutionSetShaderEXT( VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet, uint32_t executionSetWriteCount, const VkWriteIndirectExecutionSetShaderEXT* pExecutionSetWrites); #endif +#endif // VK_MESA_image_alignment_control is a preprocessor guard. Do not pass it to API calls. @@ -21242,6 +25553,52 @@ typedef struct VkImageAlignmentControlCreateInfoMESA { +// VK_NV_push_constant_bank is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_push_constant_bank 1 +#define VK_NV_PUSH_CONSTANT_BANK_SPEC_VERSION 1 +#define VK_NV_PUSH_CONSTANT_BANK_EXTENSION_NAME "VK_NV_push_constant_bank" +typedef struct VkPushConstantBankInfoNV { + VkStructureType sType; + const void* pNext; + uint32_t bank; +} VkPushConstantBankInfoNV; + +typedef struct VkPhysicalDevicePushConstantBankFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 pushConstantBank; +} VkPhysicalDevicePushConstantBankFeaturesNV; + +typedef struct VkPhysicalDevicePushConstantBankPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxGraphicsPushConstantBanks; + uint32_t maxComputePushConstantBanks; + uint32_t maxGraphicsPushDataBanks; + uint32_t maxComputePushDataBanks; +} VkPhysicalDevicePushConstantBankPropertiesNV; + + + +// VK_EXT_ray_tracing_invocation_reorder is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_ray_tracing_invocation_reorder 1 +#define VK_EXT_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION 2 +#define VK_EXT_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME "VK_EXT_ray_tracing_invocation_reorder" +typedef struct VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT { + VkStructureType sType; + void* pNext; + VkRayTracingInvocationReorderModeEXT rayTracingInvocationReorderReorderingHint; + uint32_t maxShaderBindingTableRecordIndex; +} VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT; + +typedef struct VkPhysicalDeviceRayTracingInvocationReorderFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 rayTracingInvocationReorder; +} VkPhysicalDeviceRayTracingInvocationReorderFeaturesEXT; + + + // VK_EXT_depth_clamp_control is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_depth_clamp_control 1 #define VK_EXT_DEPTH_CLAMP_CONTROL_SPEC_VERSION 1 @@ -21322,11 +25679,13 @@ typedef struct VkPhysicalDeviceCooperativeMatrix2PropertiesNV { typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixFlexibleDimensionsPropertiesNV* pProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixFlexibleDimensionsPropertiesNV* pProperties); #endif +#endif // VK_ARM_pipeline_opacity_micromap is a preprocessor guard. Do not pass it to API calls. @@ -21341,6 +25700,167 @@ typedef struct VkPhysicalDevicePipelineOpacityMicromapFeaturesARM { +// VK_IMG_filter_linear_2d is a preprocessor guard. Do not pass it to API calls. +#define VK_IMG_filter_linear_2d 1 +#define VK_IMG_FILTER_LINEAR_2D_SPEC_VERSION 1 +#define VK_IMG_FILTER_LINEAR_2D_EXTENSION_NAME "VK_IMG_filter_linear_2d" + + +// VK_ARM_performance_counters_by_region is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_performance_counters_by_region 1 +#define VK_ARM_PERFORMANCE_COUNTERS_BY_REGION_SPEC_VERSION 1 +#define VK_ARM_PERFORMANCE_COUNTERS_BY_REGION_EXTENSION_NAME "VK_ARM_performance_counters_by_region" +typedef VkFlags VkPerformanceCounterDescriptionFlagsARM; +typedef struct VkPhysicalDevicePerformanceCountersByRegionFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 performanceCountersByRegion; +} VkPhysicalDevicePerformanceCountersByRegionFeaturesARM; + +typedef struct VkPhysicalDevicePerformanceCountersByRegionPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t maxPerRegionPerformanceCounters; + VkExtent2D performanceCounterRegionSize; + uint32_t rowStrideAlignment; + uint32_t regionAlignment; + VkBool32 identityTransformOrder; +} VkPhysicalDevicePerformanceCountersByRegionPropertiesARM; + +typedef struct VkPerformanceCounterARM { + VkStructureType sType; + void* pNext; + uint32_t counterID; +} VkPerformanceCounterARM; + +typedef struct VkPerformanceCounterDescriptionARM { + VkStructureType sType; + void* pNext; + VkPerformanceCounterDescriptionFlagsARM flags; + char name[VK_MAX_DESCRIPTION_SIZE]; +} VkPerformanceCounterDescriptionARM; + +typedef struct VkRenderPassPerformanceCountersByRegionBeginInfoARM { + VkStructureType sType; + void* pNext; + uint32_t counterAddressCount; + const VkDeviceAddress* pCounterAddresses; + VkBool32 serializeRegions; + uint32_t counterIndexCount; + uint32_t* pCounterIndices; +} VkRenderPassPerformanceCountersByRegionBeginInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, uint32_t* pCounterCount, VkPerformanceCounterARM* pCounters, VkPerformanceCounterDescriptionARM* pCounterDescriptions); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + uint32_t* pCounterCount, + VkPerformanceCounterARM* pCounters, + VkPerformanceCounterDescriptionARM* pCounterDescriptions); +#endif +#endif + + +// VK_ARM_shader_instrumentation is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_shader_instrumentation 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderInstrumentationARM) +#define VK_ARM_SHADER_INSTRUMENTATION_SPEC_VERSION 1 +#define VK_ARM_SHADER_INSTRUMENTATION_EXTENSION_NAME "VK_ARM_shader_instrumentation" +typedef VkFlags VkShaderInstrumentationValuesFlagsARM; +typedef struct VkPhysicalDeviceShaderInstrumentationFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 shaderInstrumentation; +} VkPhysicalDeviceShaderInstrumentationFeaturesARM; + +typedef struct VkPhysicalDeviceShaderInstrumentationPropertiesARM { + VkStructureType sType; + void* pNext; + uint32_t numMetrics; + VkBool32 perBasicBlockGranularity; +} VkPhysicalDeviceShaderInstrumentationPropertiesARM; + +typedef struct VkShaderInstrumentationCreateInfoARM { + VkStructureType sType; + void* pNext; +} VkShaderInstrumentationCreateInfoARM; + +typedef struct VkShaderInstrumentationMetricDescriptionARM { + VkStructureType sType; + void* pNext; + char name[VK_MAX_DESCRIPTION_SIZE]; + char description[VK_MAX_DESCRIPTION_SIZE]; +} VkShaderInstrumentationMetricDescriptionARM; + +typedef struct VkShaderInstrumentationMetricDataHeaderARM { + uint32_t resultIndex; + uint32_t resultSubIndex; + VkShaderStageFlags stages; + uint32_t basicBlockIndex; +} VkShaderInstrumentationMetricDataHeaderARM; + +typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM)(VkPhysicalDevice physicalDevice, uint32_t* pDescriptionCount, VkShaderInstrumentationMetricDescriptionARM* pDescriptions); +typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderInstrumentationARM)(VkDevice device, const VkShaderInstrumentationCreateInfoARM* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderInstrumentationARM* pInstrumentation); +typedef void (VKAPI_PTR *PFN_vkDestroyShaderInstrumentationARM)(VkDevice device, VkShaderInstrumentationARM instrumentation, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdBeginShaderInstrumentationARM)(VkCommandBuffer commandBuffer, VkShaderInstrumentationARM instrumentation); +typedef void (VKAPI_PTR *PFN_vkCmdEndShaderInstrumentationARM)(VkCommandBuffer commandBuffer); +typedef VkResult (VKAPI_PTR *PFN_vkGetShaderInstrumentationValuesARM)(VkDevice device, VkShaderInstrumentationARM instrumentation, uint32_t* pMetricBlockCount, void* pMetricValues, VkShaderInstrumentationValuesFlagsARM flags); +typedef void (VKAPI_PTR *PFN_vkClearShaderInstrumentationMetricsARM)(VkDevice device, VkShaderInstrumentationARM instrumentation); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM( + VkPhysicalDevice physicalDevice, + uint32_t* pDescriptionCount, + VkShaderInstrumentationMetricDescriptionARM* pDescriptions); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderInstrumentationARM( + VkDevice device, + const VkShaderInstrumentationCreateInfoARM* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderInstrumentationARM* pInstrumentation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyShaderInstrumentationARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginShaderInstrumentationARM( + VkCommandBuffer commandBuffer, + VkShaderInstrumentationARM instrumentation); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndShaderInstrumentationARM( + VkCommandBuffer commandBuffer); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetShaderInstrumentationValuesARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation, + uint32_t* pMetricBlockCount, + void* pMetricValues, + VkShaderInstrumentationValuesFlagsARM flags); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkClearShaderInstrumentationMetricsARM( + VkDevice device, + VkShaderInstrumentationARM instrumentation); +#endif +#endif + + // VK_EXT_vertex_attribute_robustness is a preprocessor guard. Do not pass it to API calls. #define VK_EXT_vertex_attribute_robustness 1 #define VK_EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_SPEC_VERSION 1 @@ -21353,6 +25873,42 @@ typedef struct VkPhysicalDeviceVertexAttributeRobustnessFeaturesEXT { +// VK_ARM_format_pack is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_format_pack 1 +#define VK_ARM_FORMAT_PACK_SPEC_VERSION 1 +#define VK_ARM_FORMAT_PACK_EXTENSION_NAME "VK_ARM_format_pack" +typedef struct VkPhysicalDeviceFormatPackFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 formatPack; +} VkPhysicalDeviceFormatPackFeaturesARM; + + + +// VK_VALVE_fragment_density_map_layered is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_fragment_density_map_layered 1 +#define VK_VALVE_FRAGMENT_DENSITY_MAP_LAYERED_SPEC_VERSION 1 +#define VK_VALVE_FRAGMENT_DENSITY_MAP_LAYERED_EXTENSION_NAME "VK_VALVE_fragment_density_map_layered" +typedef struct VkPhysicalDeviceFragmentDensityMapLayeredFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 fragmentDensityMapLayered; +} VkPhysicalDeviceFragmentDensityMapLayeredFeaturesVALVE; + +typedef struct VkPhysicalDeviceFragmentDensityMapLayeredPropertiesVALVE { + VkStructureType sType; + void* pNext; + uint32_t maxFragmentDensityMapLayers; +} VkPhysicalDeviceFragmentDensityMapLayeredPropertiesVALVE; + +typedef struct VkPipelineFragmentDensityMapLayeredCreateInfoVALVE { + VkStructureType sType; + const void* pNext; + uint32_t maxFragmentDensityMapLayers; +} VkPipelineFragmentDensityMapLayeredCreateInfoVALVE; + + + // VK_NV_present_metering is a preprocessor guard. Do not pass it to API calls. #define VK_NV_present_metering 1 #define VK_NV_PRESENT_METERING_SPEC_VERSION 1 @@ -21372,6 +25928,475 @@ typedef struct VkPhysicalDevicePresentMeteringFeaturesNV { +// VK_EXT_multisampled_render_to_swapchain is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_multisampled_render_to_swapchain 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SWAPCHAIN_SPEC_VERSION 1 +#define VK_EXT_MULTISAMPLED_RENDER_TO_SWAPCHAIN_EXTENSION_NAME "VK_EXT_multisampled_render_to_swapchain" +typedef struct VkPhysicalDeviceMultisampledRenderToSwapchainFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 multisampledRenderToSwapchain; +} VkPhysicalDeviceMultisampledRenderToSwapchainFeaturesEXT; + +typedef struct VkSwapchainFlagsSurfaceCapabilitiesEXT { + VkStructureType sType; + void* pNext; + VkSwapchainCreateFlagsKHR swapchainSupportedFlags; +} VkSwapchainFlagsSurfaceCapabilitiesEXT; + + + +// VK_EXT_fragment_density_map_offset is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_fragment_density_map_offset 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION 1 +#define VK_EXT_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME "VK_EXT_fragment_density_map_offset" +typedef VkRenderingEndInfoKHR VkRenderingEndInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdEndRendering2EXT)(VkCommandBuffer commandBuffer, const VkRenderingEndInfoKHR* pRenderingEndInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdEndRendering2EXT( + VkCommandBuffer commandBuffer, + const VkRenderingEndInfoKHR* pRenderingEndInfo); +#endif +#endif + + +// VK_EXT_zero_initialize_device_memory is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_zero_initialize_device_memory 1 +#define VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_SPEC_VERSION 1 +#define VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME "VK_EXT_zero_initialize_device_memory" +typedef struct VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 zeroInitializeDeviceMemory; +} VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT; + + + +// VK_EXT_shader_64bit_indexing is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_64bit_indexing 1 +#define VK_EXT_SHADER_64BIT_INDEXING_SPEC_VERSION 1 +#define VK_EXT_SHADER_64BIT_INDEXING_EXTENSION_NAME "VK_EXT_shader_64bit_indexing" +typedef struct VkPhysicalDeviceShader64BitIndexingFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shader64BitIndexing; +} VkPhysicalDeviceShader64BitIndexingFeaturesEXT; + + + +// VK_EXT_custom_resolve is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_custom_resolve 1 +#define VK_EXT_CUSTOM_RESOLVE_SPEC_VERSION 1 +#define VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME "VK_EXT_custom_resolve" +typedef struct VkPhysicalDeviceCustomResolveFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 customResolve; +} VkPhysicalDeviceCustomResolveFeaturesEXT; + +typedef struct VkBeginCustomResolveInfoEXT { + VkStructureType sType; + void* pNext; +} VkBeginCustomResolveInfoEXT; + +typedef struct VkCustomResolveCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkBool32 customResolve; + uint32_t colorAttachmentCount; + const VkFormat* pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkCustomResolveCreateInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdBeginCustomResolveEXT)(VkCommandBuffer commandBuffer, const VkBeginCustomResolveInfoEXT* pBeginCustomResolveInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdBeginCustomResolveEXT( + VkCommandBuffer commandBuffer, + const VkBeginCustomResolveInfoEXT* pBeginCustomResolveInfo); +#endif +#endif + + +// VK_QCOM_data_graph_model is a preprocessor guard. Do not pass it to API calls. +#define VK_QCOM_data_graph_model 1 +#define VK_DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM 3U +#define VK_QCOM_DATA_GRAPH_MODEL_SPEC_VERSION 1 +#define VK_QCOM_DATA_GRAPH_MODEL_EXTENSION_NAME "VK_QCOM_data_graph_model" + +typedef enum VkDataGraphModelCacheTypeQCOM { + VK_DATA_GRAPH_MODEL_CACHE_TYPE_GENERIC_BINARY_QCOM = 0, + VK_DATA_GRAPH_MODEL_CACHE_TYPE_MAX_ENUM_QCOM = 0x7FFFFFFF +} VkDataGraphModelCacheTypeQCOM; +typedef struct VkPipelineCacheHeaderVersionDataGraphQCOM { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + VkDataGraphModelCacheTypeQCOM cacheType; + uint32_t cacheVersion; + uint32_t toolchainVersion[VK_DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM]; +} VkPipelineCacheHeaderVersionDataGraphQCOM; + +typedef struct VkDataGraphPipelineBuiltinModelCreateInfoQCOM { + VkStructureType sType; + const void* pNext; + const VkPhysicalDeviceDataGraphOperationSupportARM* pOperation; +} VkDataGraphPipelineBuiltinModelCreateInfoQCOM; + +typedef struct VkPhysicalDeviceDataGraphModelFeaturesQCOM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphModel; +} VkPhysicalDeviceDataGraphModelFeaturesQCOM; + + + +// VK_ARM_data_graph_optical_flow is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_optical_flow 1 +#define VK_ARM_DATA_GRAPH_OPTICAL_FLOW_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_OPTICAL_FLOW_EXTENSION_NAME "VK_ARM_data_graph_optical_flow" + +typedef enum VkDataGraphOpticalFlowPerformanceLevelARM { + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_SLOW_ARM = 1, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_MEDIUM_ARM = 2, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_FAST_ARM = 3, + VK_DATA_GRAPH_OPTICAL_FLOW_PERFORMANCE_LEVEL_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowPerformanceLevelARM; + +typedef enum VkDataGraphPipelineNodeTypeARM { + VK_DATA_GRAPH_PIPELINE_NODE_TYPE_OPTICAL_FLOW_ARM = 1000631000, + VK_DATA_GRAPH_PIPELINE_NODE_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineNodeTypeARM; + +typedef enum VkDataGraphPipelineNodeConnectionTypeARM { + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_INPUT_ARM = 1000631000, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_REFERENCE_ARM = 1000631001, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_HINT_ARM = 1000631002, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_FLOW_VECTOR_ARM = 1000631003, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_OPTICAL_FLOW_COST_ARM = 1000631004, + VK_DATA_GRAPH_PIPELINE_NODE_CONNECTION_TYPE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphPipelineNodeConnectionTypeARM; + +typedef enum VkDataGraphOpticalFlowGridSizeFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_1X1_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_2X2_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_4X4_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_8X8_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_GRID_SIZE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowGridSizeFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowGridSizeFlagsARM; + +typedef enum VkDataGraphOpticalFlowCreateFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_ENABLE_HINT_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_ENABLE_COST_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_RESERVED_30_BIT_ARM = 0x40000000, + VK_DATA_GRAPH_OPTICAL_FLOW_CREATE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowCreateFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowCreateFlagsARM; + +typedef enum VkDataGraphOpticalFlowImageUsageFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_UNKNOWN_ARM = 0, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_INPUT_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_OUTPUT_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_HINT_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_COST_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_IMAGE_USAGE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowImageUsageFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowImageUsageFlagsARM; + +typedef enum VkDataGraphOpticalFlowExecuteFlagBitsARM { + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_DISABLE_TEMPORAL_HINTS_BIT_ARM = 0x00000001, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_INPUT_UNCHANGED_BIT_ARM = 0x00000002, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_REFERENCE_UNCHANGED_BIT_ARM = 0x00000004, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_INPUT_IS_PREVIOUS_REFERENCE_BIT_ARM = 0x00000008, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_REFERENCE_IS_PREVIOUS_INPUT_BIT_ARM = 0x00000010, + VK_DATA_GRAPH_OPTICAL_FLOW_EXECUTE_FLAG_BITS_MAX_ENUM_ARM = 0x7FFFFFFF +} VkDataGraphOpticalFlowExecuteFlagBitsARM; +typedef VkFlags VkDataGraphOpticalFlowExecuteFlagsARM; +typedef struct VkPhysicalDeviceDataGraphOpticalFlowFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphOpticalFlow; +} VkPhysicalDeviceDataGraphOpticalFlowFeaturesARM; + +typedef struct VkQueueFamilyDataGraphOpticalFlowPropertiesARM { + VkStructureType sType; + void* pNext; + VkDataGraphOpticalFlowGridSizeFlagsARM supportedOutputGridSizes; + VkDataGraphOpticalFlowGridSizeFlagsARM supportedHintGridSizes; + VkBool32 hintSupported; + VkBool32 costSupported; + uint32_t minWidth; + uint32_t minHeight; + uint32_t maxWidth; + uint32_t maxHeight; +} VkQueueFamilyDataGraphOpticalFlowPropertiesARM; + +typedef struct VkDataGraphPipelineOpticalFlowCreateInfoARM { + VkStructureType sType; + void* pNext; + uint32_t width; + uint32_t height; + VkFormat imageFormat; + VkFormat flowVectorFormat; + VkFormat costFormat; + VkDataGraphOpticalFlowGridSizeFlagsARM outputGridSize; + VkDataGraphOpticalFlowGridSizeFlagsARM hintGridSize; + VkDataGraphOpticalFlowPerformanceLevelARM performanceLevel; + VkDataGraphOpticalFlowCreateFlagsARM flags; +} VkDataGraphPipelineOpticalFlowCreateInfoARM; + +typedef struct VkDataGraphOpticalFlowImageFormatPropertiesARM { + VkStructureType sType; + void* pNext; + VkFormat format; +} VkDataGraphOpticalFlowImageFormatPropertiesARM; + +typedef struct VkDataGraphOpticalFlowImageFormatInfoARM { + VkStructureType sType; + const void* pNext; + VkDataGraphOpticalFlowImageUsageFlagsARM usage; +} VkDataGraphOpticalFlowImageFormatInfoARM; + +typedef struct VkDataGraphPipelineOpticalFlowDispatchInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphOpticalFlowExecuteFlagsARM flags; + uint32_t meanFlowL1NormHint; +} VkDataGraphPipelineOpticalFlowDispatchInfoARM; + +typedef struct VkDataGraphPipelineResourceInfoImageLayoutARM { + VkStructureType sType; + const void* pNext; + VkImageLayout layout; +} VkDataGraphPipelineResourceInfoImageLayoutARM; + +typedef struct VkDataGraphPipelineSingleNodeConnectionARM { + VkStructureType sType; + void* pNext; + uint32_t set; + uint32_t binding; + VkDataGraphPipelineNodeConnectionTypeARM connection; +} VkDataGraphPipelineSingleNodeConnectionARM; + +typedef struct VkDataGraphPipelineSingleNodeCreateInfoARM { + VkStructureType sType; + void* pNext; + VkDataGraphPipelineNodeTypeARM nodeType; + uint32_t connectionCount; + const VkDataGraphPipelineSingleNodeConnectionARM* pConnections; +} VkDataGraphPipelineSingleNodeCreateInfoARM; + +typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, const VkDataGraphOpticalFlowImageFormatInfoARM* pOpticalFlowImageFormatInfo, uint32_t* pFormatCount, VkDataGraphOpticalFlowImageFormatPropertiesARM* pImageFormatProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + const VkQueueFamilyDataGraphPropertiesARM* pQueueFamilyDataGraphProperties, + const VkDataGraphOpticalFlowImageFormatInfoARM* pOpticalFlowImageFormatInfo, + uint32_t* pFormatCount, + VkDataGraphOpticalFlowImageFormatPropertiesARM* pImageFormatProperties); +#endif +#endif + + +// VK_EXT_shader_long_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_long_vector 1 +#define VK_EXT_SHADER_LONG_VECTOR_SPEC_VERSION 1 +#define VK_EXT_SHADER_LONG_VECTOR_EXTENSION_NAME "VK_EXT_shader_long_vector" +typedef struct VkPhysicalDeviceShaderLongVectorFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 longVector; +} VkPhysicalDeviceShaderLongVectorFeaturesEXT; + +typedef struct VkPhysicalDeviceShaderLongVectorPropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t maxVectorComponents; +} VkPhysicalDeviceShaderLongVectorPropertiesEXT; + + + +// VK_SEC_pipeline_cache_incremental_mode is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_pipeline_cache_incremental_mode 1 +#define VK_SEC_PIPELINE_CACHE_INCREMENTAL_MODE_SPEC_VERSION 1 +#define VK_SEC_PIPELINE_CACHE_INCREMENTAL_MODE_EXTENSION_NAME "VK_SEC_pipeline_cache_incremental_mode" +typedef struct VkPhysicalDevicePipelineCacheIncrementalModeFeaturesSEC { + VkStructureType sType; + void* pNext; + VkBool32 pipelineCacheIncrementalMode; +} VkPhysicalDevicePipelineCacheIncrementalModeFeaturesSEC; + + + +// VK_EXT_shader_uniform_buffer_unsized_array is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_uniform_buffer_unsized_array 1 +#define VK_EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_SPEC_VERSION 1 +#define VK_EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_EXTENSION_NAME "VK_EXT_shader_uniform_buffer_unsized_array" +typedef struct VkPhysicalDeviceShaderUniformBufferUnsizedArrayFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderUniformBufferUnsizedArray; +} VkPhysicalDeviceShaderUniformBufferUnsizedArrayFeaturesEXT; + + + +// VK_NV_compute_occupancy_priority is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_compute_occupancy_priority 1 +#define VK_NV_COMPUTE_OCCUPANCY_PRIORITY_SPEC_VERSION 1 +#define VK_NV_COMPUTE_OCCUPANCY_PRIORITY_EXTENSION_NAME "VK_NV_compute_occupancy_priority" +#define VK_COMPUTE_OCCUPANCY_PRIORITY_LOW_NV 0.25f +#define VK_COMPUTE_OCCUPANCY_PRIORITY_NORMAL_NV 0.50f +#define VK_COMPUTE_OCCUPANCY_PRIORITY_HIGH_NV 0.75f +typedef struct VkComputeOccupancyPriorityParametersNV { + VkStructureType sType; + const void* pNext; + float occupancyPriority; + float occupancyThrottling; +} VkComputeOccupancyPriorityParametersNV; + +typedef struct VkPhysicalDeviceComputeOccupancyPriorityFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 computeOccupancyPriority; +} VkPhysicalDeviceComputeOccupancyPriorityFeaturesNV; + +typedef void (VKAPI_PTR *PFN_vkCmdSetComputeOccupancyPriorityNV)(VkCommandBuffer commandBuffer, const VkComputeOccupancyPriorityParametersNV* pParameters); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetComputeOccupancyPriorityNV( + VkCommandBuffer commandBuffer, + const VkComputeOccupancyPriorityParametersNV* pParameters); +#endif +#endif + + +// VK_EXT_shader_subgroup_partitioned is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_shader_subgroup_partitioned 1 +#define VK_EXT_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1 +#define VK_EXT_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_EXT_shader_subgroup_partitioned" +typedef struct VkPhysicalDeviceShaderSubgroupPartitionedFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 shaderSubgroupPartitioned; +} VkPhysicalDeviceShaderSubgroupPartitionedFeaturesEXT; + + + +// VK_VALVE_shader_mixed_float_dot_product is a preprocessor guard. Do not pass it to API calls. +#define VK_VALVE_shader_mixed_float_dot_product 1 +#define VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_SPEC_VERSION 1 +#define VK_VALVE_SHADER_MIXED_FLOAT_DOT_PRODUCT_EXTENSION_NAME "VK_VALVE_shader_mixed_float_dot_product" +typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE { + VkStructureType sType; + void* pNext; + VkBool32 shaderMixedFloatDotProductFloat16AccFloat32; + VkBool32 shaderMixedFloatDotProductFloat16AccFloat16; + VkBool32 shaderMixedFloatDotProductBFloat16Acc; + VkBool32 shaderMixedFloatDotProductFloat8AccFloat32; +} VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE; + + + +// VK_SEC_throttle_hint is a preprocessor guard. Do not pass it to API calls. +#define VK_SEC_throttle_hint 1 +#define VK_SEC_THROTTLE_HINT_SPEC_VERSION 1 +#define VK_SEC_THROTTLE_HINT_EXTENSION_NAME "VK_SEC_throttle_hint" + +typedef enum VkThrottleHintTypeSEC { + VK_THROTTLE_HINT_TYPE_DEFAULT_SEC = 0, + VK_THROTTLE_HINT_TYPE_LOW_SEC = 1, + VK_THROTTLE_HINT_TYPE_HIGH_SEC = 2, + VK_THROTTLE_HINT_TYPE_MAX_ENUM_SEC = 0x7FFFFFFF +} VkThrottleHintTypeSEC; +typedef struct VkThrottleHintSubmitInfoSEC { + VkStructureType sType; + const void* pNext; + VkThrottleHintTypeSEC throttleHint; +} VkThrottleHintSubmitInfoSEC; + +typedef struct VkPhysicalDeviceThrottleHintFeaturesSEC { + VkStructureType sType; + void* pNext; + VkBool32 throttleHint; +} VkPhysicalDeviceThrottleHintFeaturesSEC; + + + +// VK_ARM_data_graph_neural_accelerator_statistics is a preprocessor guard. Do not pass it to API calls. +#define VK_ARM_data_graph_neural_accelerator_statistics 1 +#define VK_ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_SPEC_VERSION 1 +#define VK_ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_EXTENSION_NAME "VK_ARM_data_graph_neural_accelerator_statistics" + +typedef enum VkNeuralAcceleratorStatisticsModeARM { + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_DISABLED_ARM = 0, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_STATISTICS0_ARM = 1, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_STATISTICS1_ARM = 2, + VK_NEURAL_ACCELERATOR_STATISTICS_MODE_MAX_ENUM_ARM = 0x7FFFFFFF +} VkNeuralAcceleratorStatisticsModeARM; +typedef struct VkPhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM { + VkStructureType sType; + void* pNext; + VkBool32 dataGraphNeuralAcceleratorStatistics; +} VkPhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM; + +typedef struct VkDataGraphPipelineNeuralStatisticsCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkBool32 allowNeuralStatistics; +} VkDataGraphPipelineNeuralStatisticsCreateInfoARM; + +typedef struct VkDataGraphPipelineSessionNeuralStatisticsCreateInfoARM { + VkStructureType sType; + const void* pNext; + VkNeuralAcceleratorStatisticsModeARM mode; +} VkDataGraphPipelineSessionNeuralStatisticsCreateInfoARM; + + + +// VK_EXT_primitive_restart_index is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_primitive_restart_index 1 +#define VK_EXT_PRIMITIVE_RESTART_INDEX_SPEC_VERSION 1 +#define VK_EXT_PRIMITIVE_RESTART_INDEX_EXTENSION_NAME "VK_EXT_primitive_restart_index" +typedef struct VkPhysicalDevicePrimitiveRestartIndexFeaturesEXT { + VkStructureType sType; + void* pNext; + VkBool32 primitiveRestartIndex; +} VkPhysicalDevicePrimitiveRestartIndexFeaturesEXT; + +typedef void (VKAPI_PTR *PFN_vkCmdSetPrimitiveRestartIndexEXT)(VkCommandBuffer commandBuffer, uint32_t primitiveRestartIndex); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdSetPrimitiveRestartIndexEXT( + VkCommandBuffer commandBuffer, + uint32_t primitiveRestartIndex); +#endif +#endif + + +// VK_NV_cooperative_matrix_decode_vector is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cooperative_matrix_decode_vector 1 +#define VK_NV_COOPERATIVE_MATRIX_DECODE_VECTOR_SPEC_VERSION 1 +#define VK_NV_COOPERATIVE_MATRIX_DECODE_VECTOR_EXTENSION_NAME "VK_NV_cooperative_matrix_decode_vector" +typedef struct VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cooperativeMatrixDecodeVector; +} VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV; + + + // VK_KHR_acceleration_structure is a preprocessor guard. Do not pass it to API calls. #define VK_KHR_acceleration_structure 1 #define VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION 13 @@ -21382,14 +26407,6 @@ typedef enum VkBuildAccelerationStructureModeKHR { VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR = 1, VK_BUILD_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF } VkBuildAccelerationStructureModeKHR; - -typedef enum VkAccelerationStructureCreateFlagBitsKHR { - VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = 0x00000001, - VK_ACCELERATION_STRUCTURE_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT = 0x00000008, - VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV = 0x00000004, - VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF -} VkAccelerationStructureCreateFlagBitsKHR; -typedef VkFlags VkAccelerationStructureCreateFlagsKHR; typedef struct VkAccelerationStructureBuildRangeInfoKHR { uint32_t primitiveCount; uint32_t primitiveOffset; @@ -21546,23 +26563,30 @@ typedef void (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(V typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureBuildSizesKHR)(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR( VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR( VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresKHR( VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( VkCommandBuffer commandBuffer, uint32_t infoCount, @@ -21570,29 +26594,39 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructuresIndirectKHR( const VkDeviceAddress* pIndirectDeviceAddresses, const uint32_t* pIndirectStrides, const uint32_t* const* ppMaxPrimitiveCounts); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructuresKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( VkDevice device, uint32_t accelerationStructureCount, @@ -21601,23 +26635,33 @@ VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR( size_t dataSize, void* pData, size_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR( VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR( VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR( VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR( VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, @@ -21625,12 +26669,16 @@ VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR( VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR( VkDevice device, const VkAccelerationStructureVersionInfoKHR* pVersionInfo, VkAccelerationStructureCompatibilityKHR* pCompatibility); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( VkDevice device, VkAccelerationStructureBuildTypeKHR buildType, @@ -21638,6 +26686,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureBuildSizesKHR( const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo); #endif +#endif // VK_KHR_ray_tracing_pipeline is a preprocessor guard. Do not pass it to API calls. @@ -21724,6 +26773,7 @@ typedef VkDeviceSize (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupStackSizeKHR)(VkD typedef void (VKAPI_PTR *PFN_vkCmdSetRayTracingPipelineStackSizeKHR)(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, @@ -21733,7 +26783,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR( uint32_t width, uint32_t height, uint32_t depth); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( VkDevice device, VkDeferredOperationKHR deferredOperation, @@ -21742,7 +26794,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR( const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( VkDevice device, VkPipeline pipeline, @@ -21750,7 +26804,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR uint32_t groupCount, size_t dataSize, void* pData); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, @@ -21758,17 +26814,22 @@ VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR( const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkDeviceSize VKAPI_CALL vkGetRayTracingShaderGroupStackSizeKHR( VkDevice device, VkPipeline pipeline, uint32_t group, VkShaderGroupShaderKHR groupShader); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdSetRayTracingPipelineStackSizeKHR( VkCommandBuffer commandBuffer, uint32_t pipelineStackSize); #endif +#endif // VK_KHR_ray_query is a preprocessor guard. Do not pass it to API calls. @@ -21841,19 +26902,24 @@ typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectEXT)(VkCommandBuffer comm typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountEXT)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksEXT( VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectEXT( VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountEXT( VkCommandBuffer commandBuffer, VkBuffer buffer, @@ -21863,6 +26929,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountEXT( uint32_t maxDrawCount, uint32_t stride); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_ios.h b/vendor/vulkan/_gen/vulkan_ios.h index a705dc600..089991a4f 100644 --- a/vendor/vulkan/_gen/vulkan_ios.h +++ b/vendor/vulkan/_gen/vulkan_ios.h @@ -2,7 +2,7 @@ #define VULKAN_IOS_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -34,12 +34,14 @@ typedef struct VkIOSSurfaceCreateInfoMVK { typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK( VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_macos.h b/vendor/vulkan/_gen/vulkan_macos.h index 8d5dd05a7..7d5d8a1b3 100644 --- a/vendor/vulkan/_gen/vulkan_macos.h +++ b/vendor/vulkan/_gen/vulkan_macos.h @@ -2,7 +2,7 @@ #define VULKAN_MACOS_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -34,12 +34,14 @@ typedef struct VkMacOSSurfaceCreateInfoMVK { typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK( VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_metal.h b/vendor/vulkan/_gen/vulkan_metal.h index 7e44f54cb..501c36388 100644 --- a/vendor/vulkan/_gen/vulkan_metal.h +++ b/vendor/vulkan/_gen/vulkan_metal.h @@ -2,7 +2,7 @@ #define VULKAN_METAL_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -40,12 +40,14 @@ typedef struct VkMetalSurfaceCreateInfoEXT { typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); #endif +#endif // VK_EXT_metal_objects is a preprocessor guard. Do not pass it to API calls. @@ -183,10 +185,12 @@ typedef struct VkImportMetalSharedEventInfoEXT { typedef void (VKAPI_PTR *PFN_vkExportMetalObjectsEXT)(VkDevice device, VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR void VKAPI_CALL vkExportMetalObjectsEXT( VkDevice device, VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); #endif +#endif // VK_EXT_external_memory_metal is a preprocessor guard. Do not pass it to API calls. @@ -217,17 +221,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandleEXT)(VkDevice device, con typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandlePropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHandle, VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandleEXT( VkDevice device, const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, void** pHandle); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandlePropertiesEXT( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHandle, VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std.h index 347e0d2ae..75cebd74c 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -22,27 +22,27 @@ extern "C" { // vulkan_video_codec_av1std is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_av1std 1 #include "vulkan_video_codecs_common.h" -#define STD_VIDEO_AV1_NUM_REF_FRAMES 8 -#define STD_VIDEO_AV1_REFS_PER_FRAME 7 -#define STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME 8 -#define STD_VIDEO_AV1_MAX_TILE_COLS 64 -#define STD_VIDEO_AV1_MAX_TILE_ROWS 64 -#define STD_VIDEO_AV1_MAX_SEGMENTS 8 -#define STD_VIDEO_AV1_SEG_LVL_MAX 8 -#define STD_VIDEO_AV1_PRIMARY_REF_NONE 7 -#define STD_VIDEO_AV1_SELECT_INTEGER_MV 2 -#define STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS 2 -#define STD_VIDEO_AV1_SKIP_MODE_FRAMES 2 -#define STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS 4 -#define STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS 2 -#define STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS 8 -#define STD_VIDEO_AV1_MAX_NUM_PLANES 3 -#define STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS 6 -#define STD_VIDEO_AV1_MAX_NUM_Y_POINTS 14 -#define STD_VIDEO_AV1_MAX_NUM_CB_POINTS 10 -#define STD_VIDEO_AV1_MAX_NUM_CR_POINTS 10 -#define STD_VIDEO_AV1_MAX_NUM_POS_LUMA 24 -#define STD_VIDEO_AV1_MAX_NUM_POS_CHROMA 25 +#define STD_VIDEO_AV1_NUM_REF_FRAMES 8U +#define STD_VIDEO_AV1_REFS_PER_FRAME 7U +#define STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME 8U +#define STD_VIDEO_AV1_MAX_TILE_COLS 64U +#define STD_VIDEO_AV1_MAX_TILE_ROWS 64U +#define STD_VIDEO_AV1_MAX_SEGMENTS 8U +#define STD_VIDEO_AV1_SEG_LVL_MAX 8U +#define STD_VIDEO_AV1_PRIMARY_REF_NONE 7U +#define STD_VIDEO_AV1_SELECT_INTEGER_MV 2U +#define STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS 2U +#define STD_VIDEO_AV1_SKIP_MODE_FRAMES 2U +#define STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS 4U +#define STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS 2U +#define STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS 8U +#define STD_VIDEO_AV1_MAX_NUM_PLANES 3U +#define STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS 6U +#define STD_VIDEO_AV1_MAX_NUM_Y_POINTS 14U +#define STD_VIDEO_AV1_MAX_NUM_CB_POINTS 10U +#define STD_VIDEO_AV1_MAX_NUM_CR_POINTS 10U +#define STD_VIDEO_AV1_MAX_NUM_POS_LUMA 24U +#define STD_VIDEO_AV1_MAX_NUM_POS_CHROMA 25U typedef enum StdVideoAV1Profile { STD_VIDEO_AV1_PROFILE_MAIN = 0, @@ -144,7 +144,7 @@ typedef enum StdVideoAV1ColorPrimaries { STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_432 = 12, STD_VIDEO_AV1_COLOR_PRIMARIES_EBU_3213 = 22, STD_VIDEO_AV1_COLOR_PRIMARIES_INVALID = 0x7FFFFFFF, - // STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED is a deprecated alias + // STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED is a legacy alias STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED = STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED, STD_VIDEO_AV1_COLOR_PRIMARIES_MAX_ENUM = 0x7FFFFFFF } StdVideoAV1ColorPrimaries; diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h index 522628e86..60bf2c039 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h index ca5f6f474..3602fe125 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_av1std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std.h index 6fd381066..48621b695 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -22,14 +22,14 @@ extern "C" { // vulkan_video_codec_h264std is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h264std 1 #include "vulkan_video_codecs_common.h" -#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32 -#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6 -#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16 -#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6 -#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64 -#define STD_VIDEO_H264_MAX_NUM_LIST_REF 32 -#define STD_VIDEO_H264_MAX_CHROMA_PLANES 2 -#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFF +#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE 32U +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6U +#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16U +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6U +#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64U +#define STD_VIDEO_H264_MAX_NUM_LIST_REF 32U +#define STD_VIDEO_H264_MAX_CHROMA_PLANES 2U +#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFFU typedef enum StdVideoH264ChromaFormatIdc { STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0, diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h index d6a90b498..a6bfe9d82 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,7 @@ extern "C" { #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_API_VERSION_1_0_0 #define VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h264_decode" -#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2 +#define STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_LIST_SIZE 2U typedef enum StdVideoDecodeH264FieldOrderCount { STD_VIDEO_DECODE_H264_FIELD_ORDER_COUNT_TOP = 0, diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h index 410b1b254..2d42ac321 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h264std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std.h index 3eecd6011..23617b8f9 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -22,29 +22,29 @@ extern "C" { // vulkan_video_codec_h265std is a preprocessor guard. Do not pass it to API calls. #define vulkan_video_codec_h265std 1 #include "vulkan_video_codecs_common.h" -#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32 -#define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7 -#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6 -#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16 -#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6 -#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS 64 -#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS 6 -#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64 -#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2 -#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64 -#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6 -#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19 -#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21 -#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3 -#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128 -#define STD_VIDEO_H265_MAX_NUM_LIST_REF 15 -#define STD_VIDEO_H265_MAX_CHROMA_PLANES 2 -#define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64 -#define STD_VIDEO_H265_MAX_DPB_SIZE 16 -#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 -#define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16 -#define STD_VIDEO_H265_MAX_DELTA_POC 48 -#define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFF +#define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32U +#define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7U +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16U +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS 6U +#define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2U +#define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19U +#define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21U +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3U +#define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128U +#define STD_VIDEO_H265_MAX_NUM_LIST_REF 15U +#define STD_VIDEO_H265_MAX_CHROMA_PLANES 2U +#define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64U +#define STD_VIDEO_H265_MAX_DPB_SIZE 16U +#define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32U +#define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16U +#define STD_VIDEO_H265_MAX_DELTA_POC 48U +#define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFFU typedef enum StdVideoH265ChromaFormatIdc { STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0, diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h index a9e1a0964..1758d4a88 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std_decode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,7 @@ extern "C" { #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_API_VERSION_1_0_0 #define VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_decode" -#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8 +#define STD_VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE 8U typedef struct StdVideoDecodeH265PictureInfoFlags { uint32_t IrapPicFlag : 1; uint32_t IdrPicFlag : 1; diff --git a/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h b/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h index fe2f28d57..e584a7262 100644 --- a/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h +++ b/vendor/vulkan/_gen/vulkan_video_codec_h265std_encode.h @@ -2,7 +2,7 @@ #define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ diff --git a/vendor/vulkan/_gen/vulkan_video_codec_vp9std.h b/vendor/vulkan/_gen/vulkan_video_codec_vp9std.h new file mode 100644 index 000000000..3c62f287e --- /dev/null +++ b/vendor/vulkan/_gen/vulkan_video_codec_vp9std.h @@ -0,0 +1,151 @@ +#ifndef VULKAN_VIDEO_CODEC_VP9STD_H_ +#define VULKAN_VIDEO_CODEC_VP9STD_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_vp9std is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_vp9std 1 +#include "vulkan_video_codecs_common.h" +#define STD_VIDEO_VP9_NUM_REF_FRAMES 8U +#define STD_VIDEO_VP9_REFS_PER_FRAME 3U +#define STD_VIDEO_VP9_MAX_REF_FRAMES 4U +#define STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS 2U +#define STD_VIDEO_VP9_MAX_SEGMENTS 8U +#define STD_VIDEO_VP9_SEG_LVL_MAX 4U +#define STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS 7U +#define STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB 3U + +typedef enum StdVideoVP9Profile { + STD_VIDEO_VP9_PROFILE_0 = 0, + STD_VIDEO_VP9_PROFILE_1 = 1, + STD_VIDEO_VP9_PROFILE_2 = 2, + STD_VIDEO_VP9_PROFILE_3 = 3, + STD_VIDEO_VP9_PROFILE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_PROFILE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9Profile; + +typedef enum StdVideoVP9Level { + STD_VIDEO_VP9_LEVEL_1_0 = 0, + STD_VIDEO_VP9_LEVEL_1_1 = 1, + STD_VIDEO_VP9_LEVEL_2_0 = 2, + STD_VIDEO_VP9_LEVEL_2_1 = 3, + STD_VIDEO_VP9_LEVEL_3_0 = 4, + STD_VIDEO_VP9_LEVEL_3_1 = 5, + STD_VIDEO_VP9_LEVEL_4_0 = 6, + STD_VIDEO_VP9_LEVEL_4_1 = 7, + STD_VIDEO_VP9_LEVEL_5_0 = 8, + STD_VIDEO_VP9_LEVEL_5_1 = 9, + STD_VIDEO_VP9_LEVEL_5_2 = 10, + STD_VIDEO_VP9_LEVEL_6_0 = 11, + STD_VIDEO_VP9_LEVEL_6_1 = 12, + STD_VIDEO_VP9_LEVEL_6_2 = 13, + STD_VIDEO_VP9_LEVEL_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_LEVEL_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9Level; + +typedef enum StdVideoVP9FrameType { + STD_VIDEO_VP9_FRAME_TYPE_KEY = 0, + STD_VIDEO_VP9_FRAME_TYPE_NON_KEY = 1, + STD_VIDEO_VP9_FRAME_TYPE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_FRAME_TYPE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9FrameType; + +typedef enum StdVideoVP9ReferenceName { + STD_VIDEO_VP9_REFERENCE_NAME_INTRA_FRAME = 0, + STD_VIDEO_VP9_REFERENCE_NAME_LAST_FRAME = 1, + STD_VIDEO_VP9_REFERENCE_NAME_GOLDEN_FRAME = 2, + STD_VIDEO_VP9_REFERENCE_NAME_ALTREF_FRAME = 3, + STD_VIDEO_VP9_REFERENCE_NAME_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_REFERENCE_NAME_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9ReferenceName; + +typedef enum StdVideoVP9InterpolationFilter { + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP = 0, + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1, + STD_VIDEO_VP9_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2, + STD_VIDEO_VP9_INTERPOLATION_FILTER_BILINEAR = 3, + STD_VIDEO_VP9_INTERPOLATION_FILTER_SWITCHABLE = 4, + STD_VIDEO_VP9_INTERPOLATION_FILTER_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_INTERPOLATION_FILTER_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9InterpolationFilter; + +typedef enum StdVideoVP9ColorSpace { + STD_VIDEO_VP9_COLOR_SPACE_UNKNOWN = 0, + STD_VIDEO_VP9_COLOR_SPACE_BT_601 = 1, + STD_VIDEO_VP9_COLOR_SPACE_BT_709 = 2, + STD_VIDEO_VP9_COLOR_SPACE_SMPTE_170 = 3, + STD_VIDEO_VP9_COLOR_SPACE_SMPTE_240 = 4, + STD_VIDEO_VP9_COLOR_SPACE_BT_2020 = 5, + STD_VIDEO_VP9_COLOR_SPACE_RESERVED = 6, + STD_VIDEO_VP9_COLOR_SPACE_RGB = 7, + STD_VIDEO_VP9_COLOR_SPACE_INVALID = 0x7FFFFFFF, + STD_VIDEO_VP9_COLOR_SPACE_MAX_ENUM = 0x7FFFFFFF +} StdVideoVP9ColorSpace; +typedef struct StdVideoVP9ColorConfigFlags { + uint32_t color_range : 1; + uint32_t reserved : 31; +} StdVideoVP9ColorConfigFlags; + +typedef struct StdVideoVP9ColorConfig { + StdVideoVP9ColorConfigFlags flags; + uint8_t BitDepth; + uint8_t subsampling_x; + uint8_t subsampling_y; + uint8_t reserved1; + StdVideoVP9ColorSpace color_space; +} StdVideoVP9ColorConfig; + +typedef struct StdVideoVP9LoopFilterFlags { + uint32_t loop_filter_delta_enabled : 1; + uint32_t loop_filter_delta_update : 1; + uint32_t reserved : 30; +} StdVideoVP9LoopFilterFlags; + +typedef struct StdVideoVP9LoopFilter { + StdVideoVP9LoopFilterFlags flags; + uint8_t loop_filter_level; + uint8_t loop_filter_sharpness; + uint8_t update_ref_delta; + int8_t loop_filter_ref_deltas[STD_VIDEO_VP9_MAX_REF_FRAMES]; + uint8_t update_mode_delta; + int8_t loop_filter_mode_deltas[STD_VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS]; +} StdVideoVP9LoopFilter; + +typedef struct StdVideoVP9SegmentationFlags { + uint32_t segmentation_update_map : 1; + uint32_t segmentation_temporal_update : 1; + uint32_t segmentation_update_data : 1; + uint32_t segmentation_abs_or_delta_update : 1; + uint32_t reserved : 28; +} StdVideoVP9SegmentationFlags; + +typedef struct StdVideoVP9Segmentation { + StdVideoVP9SegmentationFlags flags; + uint8_t segmentation_tree_probs[STD_VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS]; + uint8_t segmentation_pred_prob[STD_VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB]; + uint8_t FeatureEnabled[STD_VIDEO_VP9_MAX_SEGMENTS]; + int16_t FeatureData[STD_VIDEO_VP9_MAX_SEGMENTS][STD_VIDEO_VP9_SEG_LVL_MAX]; +} StdVideoVP9Segmentation; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/vulkan/_gen/vulkan_video_codec_vp9std_decode.h b/vendor/vulkan/_gen/vulkan_video_codec_vp9std_decode.h new file mode 100644 index 000000000..ac7fa7be8 --- /dev/null +++ b/vendor/vulkan/_gen/vulkan_video_codec_vp9std_decode.h @@ -0,0 +1,68 @@ +#ifndef VULKAN_VIDEO_CODEC_VP9STD_DECODE_H_ +#define VULKAN_VIDEO_CODEC_VP9STD_DECODE_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// vulkan_video_codec_vp9std_decode is a preprocessor guard. Do not pass it to API calls. +#define vulkan_video_codec_vp9std_decode 1 +#include "vulkan_video_codec_vp9std.h" + +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0) + +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_API_VERSION_1_0_0 +#define VK_STD_VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_vp9_decode" +typedef struct StdVideoDecodeVP9PictureInfoFlags { + uint32_t error_resilient_mode : 1; + uint32_t intra_only : 1; + uint32_t allow_high_precision_mv : 1; + uint32_t refresh_frame_context : 1; + uint32_t frame_parallel_decoding_mode : 1; + uint32_t segmentation_enabled : 1; + uint32_t show_frame : 1; + uint32_t UsePrevFrameMvs : 1; + uint32_t reserved : 24; +} StdVideoDecodeVP9PictureInfoFlags; + +typedef struct StdVideoDecodeVP9PictureInfo { + StdVideoDecodeVP9PictureInfoFlags flags; + StdVideoVP9Profile profile; + StdVideoVP9FrameType frame_type; + uint8_t frame_context_idx; + uint8_t reset_frame_context; + uint8_t refresh_frame_flags; + uint8_t ref_frame_sign_bias_mask; + StdVideoVP9InterpolationFilter interpolation_filter; + uint8_t base_q_idx; + int8_t delta_q_y_dc; + int8_t delta_q_uv_dc; + int8_t delta_q_uv_ac; + uint8_t tile_cols_log2; + uint8_t tile_rows_log2; + uint16_t reserved1[3]; + const StdVideoVP9ColorConfig* pColorConfig; + const StdVideoVP9LoopFilter* pLoopFilter; + const StdVideoVP9Segmentation* pSegmentation; +} StdVideoDecodeVP9PictureInfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/vulkan/_gen/vulkan_wayland.h b/vendor/vulkan/_gen/vulkan_wayland.h index 5a2dcb5f0..41025db43 100644 --- a/vendor/vulkan/_gen/vulkan_wayland.h +++ b/vendor/vulkan/_gen/vulkan_wayland.h @@ -1,55 +1,59 @@ -#ifndef VULKAN_WAYLAND_H_ -#define VULKAN_WAYLAND_H_ 1 - -/* -** Copyright 2015-2025 The Khronos Group Inc. -** -** SPDX-License-Identifier: Apache-2.0 -*/ - -/* -** This header is generated from the Khronos Vulkan XML API Registry. -** -*/ - - -#ifdef __cplusplus -extern "C" { -#endif - - - -// VK_KHR_wayland_surface is a preprocessor guard. Do not pass it to API calls. -#define VK_KHR_wayland_surface 1 -#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 -#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" -typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; -typedef struct VkWaylandSurfaceCreateInfoKHR { - VkStructureType sType; - const void* pNext; - VkWaylandSurfaceCreateFlagsKHR flags; - struct wl_display* display; - struct wl_surface* surface; -} VkWaylandSurfaceCreateInfoKHR; - -typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); -typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); - -#ifndef VK_NO_PROTOTYPES -VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( - VkInstance instance, - const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface); - -VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( - VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, - struct wl_display* display); -#endif - -#ifdef __cplusplus -} -#endif - -#endif +#ifndef VULKAN_WAYLAND_H_ +#define VULKAN_WAYLAND_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_wayland_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_wayland_surface 1 +#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6 +#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface" +typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; +typedef struct VkWaylandSurfaceCreateInfoKHR { + VkStructureType sType; + const void* pNext; + VkWaylandSurfaceCreateFlagsKHR flags; + struct wl_display* display; + struct wl_surface* surface; +} VkWaylandSurfaceCreateInfoKHR; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR( + VkInstance instance, + const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR( + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex, + struct wl_display* display); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/vulkan/_gen/vulkan_win32.h b/vendor/vulkan/_gen/vulkan_win32.h index e66ed1fcd..5c7e8bd6d 100644 --- a/vendor/vulkan/_gen/vulkan_win32.h +++ b/vendor/vulkan/_gen/vulkan_win32.h @@ -2,7 +2,7 @@ #define VULKAN_WIN32_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -36,16 +36,20 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, c typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR( VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); #endif +#endif // VK_KHR_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. @@ -85,17 +89,21 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, con typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR( VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR( VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties); #endif +#endif // VK_KHR_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. @@ -158,15 +166,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice devic typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR( VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR( VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); #endif +#endif // VK_KHR_external_fence_win32 is a preprocessor guard. Do not pass it to API calls. @@ -202,15 +214,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, c typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR( VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR( VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle); #endif +#endif // VK_NV_external_memory_win32 is a preprocessor guard. Do not pass it to API calls. @@ -234,12 +250,14 @@ typedef struct VkExportMemoryWin32HandleInfoNV { typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV( VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle); #endif +#endif // VK_NV_win32_keyed_mutex is a preprocessor guard. Do not pass it to API calls. @@ -296,25 +314,33 @@ typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice d typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT( VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT( VkDevice device, VkSwapchainKHR swapchain); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT( VkDevice device, VkSwapchainKHR swapchain); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT( VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes); #endif +#endif // VK_NV_acquire_winrt_display is a preprocessor guard. Do not pass it to API calls. @@ -325,15 +351,19 @@ typedef VkResult (VKAPI_PTR *PFN_vkAcquireWinrtDisplayNV)(VkPhysicalDevice physi typedef VkResult (VKAPI_PTR *PFN_vkGetWinrtDisplayNV)(VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkAcquireWinrtDisplayNV( VkPhysicalDevice physicalDevice, VkDisplayKHR display); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkGetWinrtDisplayNV( VkPhysicalDevice physicalDevice, uint32_t deviceRelativeId, VkDisplayKHR* pDisplay); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_xcb.h b/vendor/vulkan/_gen/vulkan_xcb.h index 4e0627559..473f8c288 100644 --- a/vendor/vulkan/_gen/vulkan_xcb.h +++ b/vendor/vulkan/_gen/vulkan_xcb.h @@ -2,7 +2,7 @@ #define VULKAN_XCB_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -36,18 +36,22 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, con typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR( VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/_gen/vulkan_xlib.h b/vendor/vulkan/_gen/vulkan_xlib.h index b581779c1..dfd107c3e 100644 --- a/vendor/vulkan/_gen/vulkan_xlib.h +++ b/vendor/vulkan/_gen/vulkan_xlib.h @@ -2,7 +2,7 @@ #define VULKAN_XLIB_H_ 1 /* -** Copyright 2015-2025 The Khronos Group Inc. +** Copyright 2015-2026 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -36,18 +36,22 @@ typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, co typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); #ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR( VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +#endif +#ifndef VK_ONLY_EXPORTED_PROTOTYPES VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR( VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID); #endif +#endif #ifdef __cplusplus } diff --git a/vendor/vulkan/core.odin b/vendor/vulkan/core.odin index b258bc85a..7ae53e713 100644 --- a/vendor/vulkan/core.odin +++ b/vendor/vulkan/core.odin @@ -1,6 +1,4 @@ -// -// Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h" -// +// Vulkan wrapper generated from [[ vulkan_core.h ; https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h ]]. package vulkan // Core API API_VERSION_1_0 :: (1<<22) | (0<<12) | (0) @@ -9,10 +7,38 @@ API_VERSION_1_2 :: (1<<22) | (2<<12) | (0) API_VERSION_1_3 :: (1<<22) | (3<<12) | (0) API_VERSION_1_4 :: (1<<22) | (4<<12) | (0) -MAKE_VERSION :: proc(major, minor, patch: u32) -> u32 { +MAKE_API_VERSION :: proc "contextless" (variant, major, minor, patch: u32) -> u32 { + return (variant<<29) | (major<<22) | (minor<<12) | (patch) +} + +MAKE_VERSION :: proc "contextless" (major, minor, patch: u32) -> u32 { return (major<<22) | (minor<<12) | (patch) } +API_VERSION_MAJOR :: proc "contextless" (version: u32) -> u32 { + return (version>>22) & 0x7F +} + +VERSION_MAJOR :: proc "contextless" (version: u32) -> u32 { + return (version>>22) +} + +API_VERSION_MINOR :: proc "contextless" (version: u32) -> u32 { + return (version>>12) & 0x3FF +} + +VERSION_MINOR :: API_VERSION_MINOR + +API_VERSION_PATCH :: proc "contextless" (version: u32) -> u32 { + return (version & 0xFFF) +} + +VERSION_PATCH :: API_VERSION_PATCH + +API_VERSION_VARIANT :: proc "contextless" (version: u32) -> u32 { + return (version>>29) +} + // Base types Flags :: distinct u32 Flags64 :: distinct u64 @@ -39,7 +65,6 @@ FALSE :: 0 QUEUE_FAMILY_IGNORED :: ~u32(0) SUBPASS_EXTERNAL :: ~u32(0) MAX_PHYSICAL_DEVICE_NAME_SIZE :: 256 -MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT :: 32 UUID_SIZE :: 16 MAX_MEMORY_TYPES :: 32 MAX_MEMORY_HEAPS :: 16 @@ -50,7 +75,6 @@ LUID_SIZE_KHX :: 8 LUID_SIZE :: 8 MAX_QUEUE_FAMILY_EXTERNAL :: ~u32(1) MAX_GLOBAL_PRIORITY_SIZE :: 16 -MAX_GLOBAL_PRIORITY_SIZE_EXT :: MAX_GLOBAL_PRIORITY_SIZE QUEUE_FAMILY_EXTERNAL :: MAX_QUEUE_FAMILY_EXTERNAL // Vulkan Video API Constants @@ -71,7 +95,7 @@ VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION :: VULKAN_VIDEO_CODEC_H265_ENCODE_AP MAKE_VIDEO_STD_VERSION :: MAKE_VERSION // General Constants -HEADER_VERSION :: 309 +HEADER_VERSION :: 354 MAX_DRIVER_NAME_SIZE :: 256 MAX_DRIVER_INFO_SIZE :: 256 @@ -130,6 +154,14 @@ VIDEO_H265_MAX_LONG_TERM_PICS :: 16 VIDEO_H265_MAX_DELTA_POC :: 48 VIDEO_H265_NO_REFERENCE_PICTURE :: 0xFF VIDEO_DECODE_H265_REF_PIC_SET_LIST_SIZE :: 8 +VIDEO_VP9_NUM_REF_FRAMES :: 8 +VIDEO_VP9_REFS_PER_FRAME :: 3 +VIDEO_VP9_MAX_REF_FRAMES :: 4 +VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS :: 2 +VIDEO_VP9_MAX_SEGMENTS :: 8 +VIDEO_VP9_SEG_LVL_MAX :: 4 +VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS :: 7 +VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB :: 3 // Vulkan Video Codec Constants VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_av1_decode" @@ -138,1100 +170,1358 @@ VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_h264 VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_h264_encode" VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_h265_decode" VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_h265_encode" +VULKAN_VIDEO_CODEC_VP9_DECODE_EXTENSION_NAME :: "VK_STD_vulkan_video_codec_vp9_decode" // Vendor Constants -KHR_surface :: 1 -KHR_SURFACE_SPEC_VERSION :: 25 -KHR_SURFACE_EXTENSION_NAME :: "VK_KHR_surface" -KHR_swapchain :: 1 -KHR_SWAPCHAIN_SPEC_VERSION :: 70 -KHR_SWAPCHAIN_EXTENSION_NAME :: "VK_KHR_swapchain" -KHR_display :: 1 -KHR_DISPLAY_SPEC_VERSION :: 23 -KHR_DISPLAY_EXTENSION_NAME :: "VK_KHR_display" -KHR_display_swapchain :: 1 -KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION :: 10 -KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME :: "VK_KHR_display_swapchain" -KHR_sampler_mirror_clamp_to_edge :: 1 -KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION :: 3 -KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME :: "VK_KHR_sampler_mirror_clamp_to_edge" -KHR_video_queue :: 1 -KHR_VIDEO_QUEUE_SPEC_VERSION :: 8 -KHR_VIDEO_QUEUE_EXTENSION_NAME :: "VK_KHR_video_queue" -KHR_video_decode_queue :: 1 -KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION :: 8 -KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME :: "VK_KHR_video_decode_queue" -KHR_video_encode_h264 :: 1 -KHR_VIDEO_ENCODE_H264_SPEC_VERSION :: 14 -KHR_VIDEO_ENCODE_H264_EXTENSION_NAME :: "VK_KHR_video_encode_h264" -KHR_video_encode_h265 :: 1 -KHR_VIDEO_ENCODE_H265_SPEC_VERSION :: 14 -KHR_VIDEO_ENCODE_H265_EXTENSION_NAME :: "VK_KHR_video_encode_h265" -KHR_video_decode_h264 :: 1 -KHR_VIDEO_DECODE_H264_SPEC_VERSION :: 9 -KHR_VIDEO_DECODE_H264_EXTENSION_NAME :: "VK_KHR_video_decode_h264" -KHR_dynamic_rendering :: 1 -KHR_DYNAMIC_RENDERING_SPEC_VERSION :: 1 -KHR_DYNAMIC_RENDERING_EXTENSION_NAME :: "VK_KHR_dynamic_rendering" -KHR_multiview :: 1 -KHR_MULTIVIEW_SPEC_VERSION :: 1 -KHR_MULTIVIEW_EXTENSION_NAME :: "VK_KHR_multiview" -KHR_get_physical_device_properties2 :: 1 -KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION :: 2 -KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME :: "VK_KHR_get_physical_device_properties2" -KHR_device_group :: 1 -KHR_DEVICE_GROUP_SPEC_VERSION :: 4 -KHR_DEVICE_GROUP_EXTENSION_NAME :: "VK_KHR_device_group" -KHR_shader_draw_parameters :: 1 -KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION :: 1 -KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME :: "VK_KHR_shader_draw_parameters" -KHR_maintenance1 :: 1 -KHR_MAINTENANCE_1_SPEC_VERSION :: 2 -KHR_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_maintenance1" -KHR_MAINTENANCE1_SPEC_VERSION :: KHR_MAINTENANCE_1_SPEC_VERSION -KHR_MAINTENANCE1_EXTENSION_NAME :: KHR_MAINTENANCE_1_EXTENSION_NAME -KHR_device_group_creation :: 1 -KHR_DEVICE_GROUP_CREATION_SPEC_VERSION :: 1 -KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME :: "VK_KHR_device_group_creation" -MAX_DEVICE_GROUP_SIZE_KHR :: MAX_DEVICE_GROUP_SIZE -KHR_external_memory_capabilities :: 1 -KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION :: 1 -KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_memory_capabilities" -LUID_SIZE_KHR :: LUID_SIZE -KHR_external_memory :: 1 -KHR_EXTERNAL_MEMORY_SPEC_VERSION :: 1 -KHR_EXTERNAL_MEMORY_EXTENSION_NAME :: "VK_KHR_external_memory" -QUEUE_FAMILY_EXTERNAL_KHR :: QUEUE_FAMILY_EXTERNAL -KHR_external_memory_fd :: 1 -KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION :: 1 -KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME :: "VK_KHR_external_memory_fd" -KHR_external_semaphore_capabilities :: 1 -KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION :: 1 -KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_semaphore_capabilities" -KHR_external_semaphore :: 1 -KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION :: 1 -KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME :: "VK_KHR_external_semaphore" -KHR_external_semaphore_fd :: 1 -KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION :: 1 -KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME :: "VK_KHR_external_semaphore_fd" -KHR_push_descriptor :: 1 -KHR_PUSH_DESCRIPTOR_SPEC_VERSION :: 2 -KHR_PUSH_DESCRIPTOR_EXTENSION_NAME :: "VK_KHR_push_descriptor" -KHR_shader_float16_int8 :: 1 -KHR_SHADER_FLOAT16_INT8_SPEC_VERSION :: 1 -KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME :: "VK_KHR_shader_float16_int8" -KHR_16bit_storage :: 1 -KHR_16BIT_STORAGE_SPEC_VERSION :: 1 -KHR_16BIT_STORAGE_EXTENSION_NAME :: "VK_KHR_16bit_storage" -KHR_incremental_present :: 1 -KHR_INCREMENTAL_PRESENT_SPEC_VERSION :: 2 -KHR_INCREMENTAL_PRESENT_EXTENSION_NAME :: "VK_KHR_incremental_present" -KHR_descriptor_update_template :: 1 -KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION :: 1 -KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME :: "VK_KHR_descriptor_update_template" -KHR_imageless_framebuffer :: 1 -KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION :: 1 -KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME :: "VK_KHR_imageless_framebuffer" -KHR_create_renderpass2 :: 1 -KHR_CREATE_RENDERPASS_2_SPEC_VERSION :: 1 -KHR_CREATE_RENDERPASS_2_EXTENSION_NAME :: "VK_KHR_create_renderpass2" -KHR_shared_presentable_image :: 1 -KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION :: 1 -KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME :: "VK_KHR_shared_presentable_image" -KHR_external_fence_capabilities :: 1 -KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION :: 1 -KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_fence_capabilities" -KHR_external_fence :: 1 -KHR_EXTERNAL_FENCE_SPEC_VERSION :: 1 -KHR_EXTERNAL_FENCE_EXTENSION_NAME :: "VK_KHR_external_fence" -KHR_external_fence_fd :: 1 -KHR_EXTERNAL_FENCE_FD_SPEC_VERSION :: 1 -KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME :: "VK_KHR_external_fence_fd" -KHR_performance_query :: 1 -KHR_PERFORMANCE_QUERY_SPEC_VERSION :: 1 -KHR_PERFORMANCE_QUERY_EXTENSION_NAME :: "VK_KHR_performance_query" -KHR_maintenance2 :: 1 -KHR_MAINTENANCE_2_SPEC_VERSION :: 1 -KHR_MAINTENANCE_2_EXTENSION_NAME :: "VK_KHR_maintenance2" -KHR_MAINTENANCE2_SPEC_VERSION :: KHR_MAINTENANCE_2_SPEC_VERSION -KHR_MAINTENANCE2_EXTENSION_NAME :: KHR_MAINTENANCE_2_EXTENSION_NAME -KHR_get_surface_capabilities2 :: 1 -KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION :: 1 -KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME :: "VK_KHR_get_surface_capabilities2" -KHR_variable_pointers :: 1 -KHR_VARIABLE_POINTERS_SPEC_VERSION :: 1 -KHR_VARIABLE_POINTERS_EXTENSION_NAME :: "VK_KHR_variable_pointers" -KHR_get_display_properties2 :: 1 -KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION :: 1 -KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME :: "VK_KHR_get_display_properties2" -KHR_dedicated_allocation :: 1 -KHR_DEDICATED_ALLOCATION_SPEC_VERSION :: 3 -KHR_DEDICATED_ALLOCATION_EXTENSION_NAME :: "VK_KHR_dedicated_allocation" -KHR_storage_buffer_storage_class :: 1 -KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION :: 1 -KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME :: "VK_KHR_storage_buffer_storage_class" -KHR_relaxed_block_layout :: 1 -KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION :: 1 -KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME :: "VK_KHR_relaxed_block_layout" -KHR_get_memory_requirements2 :: 1 -KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION :: 1 -KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME :: "VK_KHR_get_memory_requirements2" -KHR_image_format_list :: 1 -KHR_IMAGE_FORMAT_LIST_SPEC_VERSION :: 1 -KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME :: "VK_KHR_image_format_list" -KHR_sampler_ycbcr_conversion :: 1 -KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION :: 14 -KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME :: "VK_KHR_sampler_ycbcr_conversion" -KHR_bind_memory2 :: 1 -KHR_BIND_MEMORY_2_SPEC_VERSION :: 1 -KHR_BIND_MEMORY_2_EXTENSION_NAME :: "VK_KHR_bind_memory2" -KHR_maintenance3 :: 1 -KHR_MAINTENANCE_3_SPEC_VERSION :: 1 -KHR_MAINTENANCE_3_EXTENSION_NAME :: "VK_KHR_maintenance3" -KHR_MAINTENANCE3_SPEC_VERSION :: KHR_MAINTENANCE_3_SPEC_VERSION -KHR_MAINTENANCE3_EXTENSION_NAME :: KHR_MAINTENANCE_3_EXTENSION_NAME -KHR_draw_indirect_count :: 1 -KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION :: 1 -KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME :: "VK_KHR_draw_indirect_count" -KHR_shader_subgroup_extended_types :: 1 -KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION :: 1 -KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME :: "VK_KHR_shader_subgroup_extended_types" -KHR_8bit_storage :: 1 -KHR_8BIT_STORAGE_SPEC_VERSION :: 1 -KHR_8BIT_STORAGE_EXTENSION_NAME :: "VK_KHR_8bit_storage" -KHR_shader_atomic_int64 :: 1 -KHR_SHADER_ATOMIC_INT64_SPEC_VERSION :: 1 -KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME :: "VK_KHR_shader_atomic_int64" -KHR_shader_clock :: 1 -KHR_SHADER_CLOCK_SPEC_VERSION :: 1 -KHR_SHADER_CLOCK_EXTENSION_NAME :: "VK_KHR_shader_clock" -KHR_video_decode_h265 :: 1 -KHR_VIDEO_DECODE_H265_SPEC_VERSION :: 8 -KHR_VIDEO_DECODE_H265_EXTENSION_NAME :: "VK_KHR_video_decode_h265" -KHR_global_priority :: 1 -KHR_GLOBAL_PRIORITY_SPEC_VERSION :: 1 -KHR_GLOBAL_PRIORITY_EXTENSION_NAME :: "VK_KHR_global_priority" -MAX_GLOBAL_PRIORITY_SIZE_KHR :: MAX_GLOBAL_PRIORITY_SIZE -KHR_driver_properties :: 1 -KHR_DRIVER_PROPERTIES_SPEC_VERSION :: 1 -KHR_DRIVER_PROPERTIES_EXTENSION_NAME :: "VK_KHR_driver_properties" -MAX_DRIVER_NAME_SIZE_KHR :: MAX_DRIVER_NAME_SIZE -MAX_DRIVER_INFO_SIZE_KHR :: MAX_DRIVER_INFO_SIZE -KHR_shader_float_controls :: 1 -KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION :: 4 -KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME :: "VK_KHR_shader_float_controls" -KHR_depth_stencil_resolve :: 1 -KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION :: 1 -KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME :: "VK_KHR_depth_stencil_resolve" -KHR_swapchain_mutable_format :: 1 -KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION :: 1 -KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME :: "VK_KHR_swapchain_mutable_format" -KHR_timeline_semaphore :: 1 -KHR_TIMELINE_SEMAPHORE_SPEC_VERSION :: 2 -KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME :: "VK_KHR_timeline_semaphore" -KHR_vulkan_memory_model :: 1 -KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION :: 3 -KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME :: "VK_KHR_vulkan_memory_model" -KHR_shader_terminate_invocation :: 1 -KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION :: 1 -KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME :: "VK_KHR_shader_terminate_invocation" -KHR_fragment_shading_rate :: 1 -KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION :: 2 -KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME :: "VK_KHR_fragment_shading_rate" -KHR_dynamic_rendering_local_read :: 1 -KHR_DYNAMIC_RENDERING_LOCAL_READ_SPEC_VERSION :: 1 -KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME :: "VK_KHR_dynamic_rendering_local_read" -KHR_shader_quad_control :: 1 -KHR_SHADER_QUAD_CONTROL_SPEC_VERSION :: 1 -KHR_SHADER_QUAD_CONTROL_EXTENSION_NAME :: "VK_KHR_shader_quad_control" -KHR_spirv_1_4 :: 1 -KHR_SPIRV_1_4_SPEC_VERSION :: 1 -KHR_SPIRV_1_4_EXTENSION_NAME :: "VK_KHR_spirv_1_4" -KHR_surface_protected_capabilities :: 1 -KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION :: 1 -KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_surface_protected_capabilities" -KHR_separate_depth_stencil_layouts :: 1 -KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION :: 1 -KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME :: "VK_KHR_separate_depth_stencil_layouts" -KHR_present_wait :: 1 -KHR_PRESENT_WAIT_SPEC_VERSION :: 1 -KHR_PRESENT_WAIT_EXTENSION_NAME :: "VK_KHR_present_wait" -KHR_uniform_buffer_standard_layout :: 1 -KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION :: 1 -KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME :: "VK_KHR_uniform_buffer_standard_layout" -KHR_buffer_device_address :: 1 -KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION :: 1 -KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME :: "VK_KHR_buffer_device_address" -KHR_deferred_host_operations :: 1 -KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION :: 4 -KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME :: "VK_KHR_deferred_host_operations" -KHR_pipeline_executable_properties :: 1 -KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION :: 1 -KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME :: "VK_KHR_pipeline_executable_properties" -KHR_map_memory2 :: 1 -KHR_MAP_MEMORY_2_SPEC_VERSION :: 1 -KHR_MAP_MEMORY_2_EXTENSION_NAME :: "VK_KHR_map_memory2" -KHR_shader_integer_dot_product :: 1 -KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION :: 1 -KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME :: "VK_KHR_shader_integer_dot_product" -KHR_pipeline_library :: 1 -KHR_PIPELINE_LIBRARY_SPEC_VERSION :: 1 -KHR_PIPELINE_LIBRARY_EXTENSION_NAME :: "VK_KHR_pipeline_library" -KHR_shader_non_semantic_info :: 1 -KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION :: 1 -KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME :: "VK_KHR_shader_non_semantic_info" -KHR_present_id :: 1 -KHR_PRESENT_ID_SPEC_VERSION :: 1 -KHR_PRESENT_ID_EXTENSION_NAME :: "VK_KHR_present_id" -KHR_video_encode_queue :: 1 -KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION :: 12 -KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME :: "VK_KHR_video_encode_queue" -KHR_synchronization2 :: 1 -KHR_SYNCHRONIZATION_2_SPEC_VERSION :: 1 -KHR_SYNCHRONIZATION_2_EXTENSION_NAME :: "VK_KHR_synchronization2" -KHR_fragment_shader_barycentric :: 1 -KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION :: 1 -KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME :: "VK_KHR_fragment_shader_barycentric" -KHR_shader_subgroup_uniform_control_flow :: 1 -KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION :: 1 -KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME :: "VK_KHR_shader_subgroup_uniform_control_flow" -KHR_zero_initialize_workgroup_memory :: 1 -KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION :: 1 -KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME :: "VK_KHR_zero_initialize_workgroup_memory" -KHR_workgroup_memory_explicit_layout :: 1 -KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION :: 1 -KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME :: "VK_KHR_workgroup_memory_explicit_layout" -KHR_copy_commands2 :: 1 -KHR_COPY_COMMANDS_2_SPEC_VERSION :: 1 -KHR_COPY_COMMANDS_2_EXTENSION_NAME :: "VK_KHR_copy_commands2" -KHR_format_feature_flags2 :: 1 -KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION :: 2 -KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME :: "VK_KHR_format_feature_flags2" -KHR_ray_tracing_maintenance1 :: 1 -KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION :: 1 -KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_ray_tracing_maintenance1" -KHR_portability_enumeration :: 1 -KHR_PORTABILITY_ENUMERATION_SPEC_VERSION :: 1 -KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME :: "VK_KHR_portability_enumeration" -KHR_maintenance4 :: 1 -KHR_MAINTENANCE_4_SPEC_VERSION :: 2 -KHR_MAINTENANCE_4_EXTENSION_NAME :: "VK_KHR_maintenance4" -KHR_shader_subgroup_rotate :: 1 -KHR_SHADER_SUBGROUP_ROTATE_SPEC_VERSION :: 2 -KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME :: "VK_KHR_shader_subgroup_rotate" -KHR_shader_maximal_reconvergence :: 1 -KHR_SHADER_MAXIMAL_RECONVERGENCE_SPEC_VERSION :: 1 -KHR_SHADER_MAXIMAL_RECONVERGENCE_EXTENSION_NAME :: "VK_KHR_shader_maximal_reconvergence" -KHR_maintenance5 :: 1 -KHR_MAINTENANCE_5_SPEC_VERSION :: 1 -KHR_MAINTENANCE_5_EXTENSION_NAME :: "VK_KHR_maintenance5" -KHR_ray_tracing_position_fetch :: 1 -KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION :: 1 -KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME :: "VK_KHR_ray_tracing_position_fetch" -KHR_pipeline_binary :: 1 -MAX_PIPELINE_BINARY_KEY_SIZE_KHR :: 32 -KHR_PIPELINE_BINARY_SPEC_VERSION :: 1 -KHR_PIPELINE_BINARY_EXTENSION_NAME :: "VK_KHR_pipeline_binary" -KHR_cooperative_matrix :: 1 -KHR_COOPERATIVE_MATRIX_SPEC_VERSION :: 2 -KHR_COOPERATIVE_MATRIX_EXTENSION_NAME :: "VK_KHR_cooperative_matrix" -KHR_compute_shader_derivatives :: 1 -KHR_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION :: 1 -KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME :: "VK_KHR_compute_shader_derivatives" -KHR_video_decode_av1 :: 1 -MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR :: 7 -KHR_VIDEO_DECODE_AV1_SPEC_VERSION :: 1 -KHR_VIDEO_DECODE_AV1_EXTENSION_NAME :: "VK_KHR_video_decode_av1" -KHR_video_encode_av1 :: 1 -KHR_VIDEO_ENCODE_AV1_SPEC_VERSION :: 1 -KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME :: "VK_KHR_video_encode_av1" -KHR_video_maintenance1 :: 1 -KHR_VIDEO_MAINTENANCE_1_SPEC_VERSION :: 1 -KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_video_maintenance1" -KHR_vertex_attribute_divisor :: 1 -KHR_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION :: 1 -KHR_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME :: "VK_KHR_vertex_attribute_divisor" -KHR_load_store_op_none :: 1 -KHR_LOAD_STORE_OP_NONE_SPEC_VERSION :: 1 -KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME :: "VK_KHR_load_store_op_none" -KHR_shader_float_controls2 :: 1 -KHR_SHADER_FLOAT_CONTROLS_2_SPEC_VERSION :: 1 -KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME :: "VK_KHR_shader_float_controls2" -KHR_index_type_uint8 :: 1 -KHR_INDEX_TYPE_UINT8_SPEC_VERSION :: 1 -KHR_INDEX_TYPE_UINT8_EXTENSION_NAME :: "VK_KHR_index_type_uint8" -KHR_line_rasterization :: 1 -KHR_LINE_RASTERIZATION_SPEC_VERSION :: 1 -KHR_LINE_RASTERIZATION_EXTENSION_NAME :: "VK_KHR_line_rasterization" -KHR_calibrated_timestamps :: 1 -KHR_CALIBRATED_TIMESTAMPS_SPEC_VERSION :: 1 -KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME :: "VK_KHR_calibrated_timestamps" -KHR_shader_expect_assume :: 1 -KHR_SHADER_EXPECT_ASSUME_SPEC_VERSION :: 1 -KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME :: "VK_KHR_shader_expect_assume" -KHR_maintenance6 :: 1 -KHR_MAINTENANCE_6_SPEC_VERSION :: 1 -KHR_MAINTENANCE_6_EXTENSION_NAME :: "VK_KHR_maintenance6" -KHR_video_encode_quantization_map :: 1 -KHR_VIDEO_ENCODE_QUANTIZATION_MAP_SPEC_VERSION :: 2 -KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME :: "VK_KHR_video_encode_quantization_map" -KHR_shader_relaxed_extended_instruction :: 1 -KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_SPEC_VERSION :: 1 -KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME :: "VK_KHR_shader_relaxed_extended_instruction" -KHR_maintenance7 :: 1 -KHR_MAINTENANCE_7_SPEC_VERSION :: 1 -KHR_MAINTENANCE_7_EXTENSION_NAME :: "VK_KHR_maintenance7" -KHR_maintenance8 :: 1 -KHR_MAINTENANCE_8_SPEC_VERSION :: 1 -KHR_MAINTENANCE_8_EXTENSION_NAME :: "VK_KHR_maintenance8" -KHR_video_maintenance2 :: 1 -KHR_VIDEO_MAINTENANCE_2_SPEC_VERSION :: 1 -KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME :: "VK_KHR_video_maintenance2" -KHR_depth_clamp_zero_one :: 1 -KHR_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION :: 1 -KHR_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME :: "VK_KHR_depth_clamp_zero_one" -EXT_debug_report :: 1 -EXT_DEBUG_REPORT_SPEC_VERSION :: 10 -EXT_DEBUG_REPORT_EXTENSION_NAME :: "VK_EXT_debug_report" -NV_glsl_shader :: 1 -NV_GLSL_SHADER_SPEC_VERSION :: 1 -NV_GLSL_SHADER_EXTENSION_NAME :: "VK_NV_glsl_shader" -EXT_depth_range_unrestricted :: 1 -EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION :: 1 -EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME :: "VK_EXT_depth_range_unrestricted" -AMD_rasterization_order :: 1 -AMD_RASTERIZATION_ORDER_SPEC_VERSION :: 1 -AMD_RASTERIZATION_ORDER_EXTENSION_NAME :: "VK_AMD_rasterization_order" -AMD_shader_trinary_minmax :: 1 -AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION :: 1 -AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME :: "VK_AMD_shader_trinary_minmax" -AMD_shader_explicit_vertex_parameter :: 1 -AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION :: 1 -AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME :: "VK_AMD_shader_explicit_vertex_parameter" -EXT_debug_marker :: 1 -EXT_DEBUG_MARKER_SPEC_VERSION :: 4 -EXT_DEBUG_MARKER_EXTENSION_NAME :: "VK_EXT_debug_marker" -AMD_gcn_shader :: 1 -AMD_GCN_SHADER_SPEC_VERSION :: 1 -AMD_GCN_SHADER_EXTENSION_NAME :: "VK_AMD_gcn_shader" -NV_dedicated_allocation :: 1 -NV_DEDICATED_ALLOCATION_SPEC_VERSION :: 1 -NV_DEDICATED_ALLOCATION_EXTENSION_NAME :: "VK_NV_dedicated_allocation" -EXT_transform_feedback :: 1 -EXT_TRANSFORM_FEEDBACK_SPEC_VERSION :: 1 -EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME :: "VK_EXT_transform_feedback" -NVX_binary_import :: 1 -NVX_BINARY_IMPORT_SPEC_VERSION :: 2 -NVX_BINARY_IMPORT_EXTENSION_NAME :: "VK_NVX_binary_import" -NVX_image_view_handle :: 1 -NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION :: 3 -NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME :: "VK_NVX_image_view_handle" -AMD_draw_indirect_count :: 1 -AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION :: 2 -AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME :: "VK_AMD_draw_indirect_count" -AMD_negative_viewport_height :: 1 -AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION :: 1 -AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME :: "VK_AMD_negative_viewport_height" -AMD_gpu_shader_half_float :: 1 -AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION :: 2 -AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME :: "VK_AMD_gpu_shader_half_float" -AMD_shader_ballot :: 1 -AMD_SHADER_BALLOT_SPEC_VERSION :: 1 -AMD_SHADER_BALLOT_EXTENSION_NAME :: "VK_AMD_shader_ballot" -AMD_texture_gather_bias_lod :: 1 -AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION :: 1 -AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME :: "VK_AMD_texture_gather_bias_lod" -AMD_shader_info :: 1 -AMD_SHADER_INFO_SPEC_VERSION :: 1 -AMD_SHADER_INFO_EXTENSION_NAME :: "VK_AMD_shader_info" -AMD_shader_image_load_store_lod :: 1 -AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION :: 1 -AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME :: "VK_AMD_shader_image_load_store_lod" -NV_corner_sampled_image :: 1 -NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION :: 2 -NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME :: "VK_NV_corner_sampled_image" -NV_external_memory_capabilities :: 1 -NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION :: 1 -NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME :: "VK_NV_external_memory_capabilities" -NV_external_memory :: 1 -NV_EXTERNAL_MEMORY_SPEC_VERSION :: 1 -NV_EXTERNAL_MEMORY_EXTENSION_NAME :: "VK_NV_external_memory" -EXT_validation_flags :: 1 -EXT_VALIDATION_FLAGS_SPEC_VERSION :: 3 -EXT_VALIDATION_FLAGS_EXTENSION_NAME :: "VK_EXT_validation_flags" -EXT_shader_subgroup_ballot :: 1 -EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION :: 1 -EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME :: "VK_EXT_shader_subgroup_ballot" -EXT_shader_subgroup_vote :: 1 -EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION :: 1 -EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME :: "VK_EXT_shader_subgroup_vote" -EXT_texture_compression_astc_hdr :: 1 -EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION :: 1 -EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME :: "VK_EXT_texture_compression_astc_hdr" -EXT_astc_decode_mode :: 1 -EXT_ASTC_DECODE_MODE_SPEC_VERSION :: 1 -EXT_ASTC_DECODE_MODE_EXTENSION_NAME :: "VK_EXT_astc_decode_mode" -EXT_pipeline_robustness :: 1 -EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION :: 1 -EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_pipeline_robustness" -EXT_conditional_rendering :: 1 -EXT_CONDITIONAL_RENDERING_SPEC_VERSION :: 2 -EXT_CONDITIONAL_RENDERING_EXTENSION_NAME :: "VK_EXT_conditional_rendering" -NV_clip_space_w_scaling :: 1 -NV_CLIP_SPACE_W_SCALING_SPEC_VERSION :: 1 -NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME :: "VK_NV_clip_space_w_scaling" -EXT_direct_mode_display :: 1 -EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION :: 1 -EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME :: "VK_EXT_direct_mode_display" -EXT_display_surface_counter :: 1 -EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION :: 1 -EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME :: "VK_EXT_display_surface_counter" -EXT_display_control :: 1 -EXT_DISPLAY_CONTROL_SPEC_VERSION :: 1 -EXT_DISPLAY_CONTROL_EXTENSION_NAME :: "VK_EXT_display_control" -GOOGLE_display_timing :: 1 -GOOGLE_DISPLAY_TIMING_SPEC_VERSION :: 1 -GOOGLE_DISPLAY_TIMING_EXTENSION_NAME :: "VK_GOOGLE_display_timing" -NV_sample_mask_override_coverage :: 1 -NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION :: 1 -NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME :: "VK_NV_sample_mask_override_coverage" -NV_geometry_shader_passthrough :: 1 -NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION :: 1 -NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME :: "VK_NV_geometry_shader_passthrough" -NV_viewport_array2 :: 1 -NV_VIEWPORT_ARRAY_2_SPEC_VERSION :: 1 -NV_VIEWPORT_ARRAY_2_EXTENSION_NAME :: "VK_NV_viewport_array2" -NV_VIEWPORT_ARRAY2_SPEC_VERSION :: NV_VIEWPORT_ARRAY_2_SPEC_VERSION -NV_VIEWPORT_ARRAY2_EXTENSION_NAME :: NV_VIEWPORT_ARRAY_2_EXTENSION_NAME -NVX_multiview_per_view_attributes :: 1 -NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION :: 1 -NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME :: "VK_NVX_multiview_per_view_attributes" -NV_viewport_swizzle :: 1 -NV_VIEWPORT_SWIZZLE_SPEC_VERSION :: 1 -NV_VIEWPORT_SWIZZLE_EXTENSION_NAME :: "VK_NV_viewport_swizzle" -EXT_discard_rectangles :: 1 -EXT_DISCARD_RECTANGLES_SPEC_VERSION :: 2 -EXT_DISCARD_RECTANGLES_EXTENSION_NAME :: "VK_EXT_discard_rectangles" -EXT_conservative_rasterization :: 1 -EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION :: 1 -EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME :: "VK_EXT_conservative_rasterization" -EXT_depth_clip_enable :: 1 -EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION :: 1 -EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME :: "VK_EXT_depth_clip_enable" -EXT_swapchain_colorspace :: 1 -EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION :: 5 -EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME :: "VK_EXT_swapchain_colorspace" -EXT_hdr_metadata :: 1 -EXT_HDR_METADATA_SPEC_VERSION :: 3 -EXT_HDR_METADATA_EXTENSION_NAME :: "VK_EXT_hdr_metadata" -EXT_external_memory_dma_buf :: 1 -EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION :: 1 -EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME :: "VK_EXT_external_memory_dma_buf" -EXT_queue_family_foreign :: 1 -EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION :: 1 -EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME :: "VK_EXT_queue_family_foreign" -EXT_debug_utils :: 1 -EXT_DEBUG_UTILS_SPEC_VERSION :: 2 -EXT_DEBUG_UTILS_EXTENSION_NAME :: "VK_EXT_debug_utils" -EXT_sampler_filter_minmax :: 1 -EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION :: 2 -EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME :: "VK_EXT_sampler_filter_minmax" -AMD_gpu_shader_int16 :: 1 -AMD_GPU_SHADER_INT16_SPEC_VERSION :: 2 -AMD_GPU_SHADER_INT16_EXTENSION_NAME :: "VK_AMD_gpu_shader_int16" -AMD_mixed_attachment_samples :: 1 -AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION :: 1 -AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME :: "VK_AMD_mixed_attachment_samples" -AMD_shader_fragment_mask :: 1 -AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION :: 1 -AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME :: "VK_AMD_shader_fragment_mask" -EXT_inline_uniform_block :: 1 -EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION :: 1 -EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME :: "VK_EXT_inline_uniform_block" -EXT_shader_stencil_export :: 1 -EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION :: 1 -EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME :: "VK_EXT_shader_stencil_export" -EXT_sample_locations :: 1 -EXT_SAMPLE_LOCATIONS_SPEC_VERSION :: 1 -EXT_SAMPLE_LOCATIONS_EXTENSION_NAME :: "VK_EXT_sample_locations" -EXT_blend_operation_advanced :: 1 -EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION :: 2 -EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME :: "VK_EXT_blend_operation_advanced" -NV_fragment_coverage_to_color :: 1 -NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION :: 1 -NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME :: "VK_NV_fragment_coverage_to_color" -NV_framebuffer_mixed_samples :: 1 -NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION :: 1 -NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME :: "VK_NV_framebuffer_mixed_samples" -NV_fill_rectangle :: 1 -NV_FILL_RECTANGLE_SPEC_VERSION :: 1 -NV_FILL_RECTANGLE_EXTENSION_NAME :: "VK_NV_fill_rectangle" -NV_shader_sm_builtins :: 1 -NV_SHADER_SM_BUILTINS_SPEC_VERSION :: 1 -NV_SHADER_SM_BUILTINS_EXTENSION_NAME :: "VK_NV_shader_sm_builtins" -EXT_post_depth_coverage :: 1 -EXT_POST_DEPTH_COVERAGE_SPEC_VERSION :: 1 -EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME :: "VK_EXT_post_depth_coverage" -EXT_image_drm_format_modifier :: 1 -EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION :: 2 -EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME :: "VK_EXT_image_drm_format_modifier" -EXT_validation_cache :: 1 -EXT_VALIDATION_CACHE_SPEC_VERSION :: 1 -EXT_VALIDATION_CACHE_EXTENSION_NAME :: "VK_EXT_validation_cache" -EXT_descriptor_indexing :: 1 -EXT_DESCRIPTOR_INDEXING_SPEC_VERSION :: 2 -EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME :: "VK_EXT_descriptor_indexing" -EXT_shader_viewport_index_layer :: 1 -EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION :: 1 -EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME :: "VK_EXT_shader_viewport_index_layer" -NV_shading_rate_image :: 1 -NV_SHADING_RATE_IMAGE_SPEC_VERSION :: 3 -NV_SHADING_RATE_IMAGE_EXTENSION_NAME :: "VK_NV_shading_rate_image" -NV_ray_tracing :: 1 -NV_RAY_TRACING_SPEC_VERSION :: 3 -NV_RAY_TRACING_EXTENSION_NAME :: "VK_NV_ray_tracing" -SHADER_UNUSED_KHR :: 0 -NV_representative_fragment_test :: 1 -NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION :: 2 -NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME :: "VK_NV_representative_fragment_test" -EXT_filter_cubic :: 1 -EXT_FILTER_CUBIC_SPEC_VERSION :: 3 -EXT_FILTER_CUBIC_EXTENSION_NAME :: "VK_EXT_filter_cubic" -EXT_global_priority :: 1 -EXT_GLOBAL_PRIORITY_SPEC_VERSION :: 2 -EXT_GLOBAL_PRIORITY_EXTENSION_NAME :: "VK_EXT_global_priority" -EXT_external_memory_host :: 1 -EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION :: 1 -EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME :: "VK_EXT_external_memory_host" -AMD_buffer_marker :: 1 -AMD_BUFFER_MARKER_SPEC_VERSION :: 1 -AMD_BUFFER_MARKER_EXTENSION_NAME :: "VK_AMD_buffer_marker" -AMD_pipeline_compiler_control :: 1 -AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION :: 1 -AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME :: "VK_AMD_pipeline_compiler_control" -EXT_calibrated_timestamps :: 1 -EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION :: 2 -EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME :: "VK_EXT_calibrated_timestamps" -AMD_shader_core_properties :: 1 -AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION :: 2 -AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME :: "VK_AMD_shader_core_properties" -AMD_memory_overallocation_behavior :: 1 -AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION :: 1 -AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME :: "VK_AMD_memory_overallocation_behavior" -EXT_vertex_attribute_divisor :: 1 -EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION :: 3 -EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME :: "VK_EXT_vertex_attribute_divisor" -EXT_pipeline_creation_feedback :: 1 -EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION :: 1 -EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME :: "VK_EXT_pipeline_creation_feedback" -NV_shader_subgroup_partitioned :: 1 -NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION :: 1 -NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME :: "VK_NV_shader_subgroup_partitioned" -NV_compute_shader_derivatives :: 1 -NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION :: 1 -NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME :: "VK_NV_compute_shader_derivatives" -NV_mesh_shader :: 1 -NV_MESH_SHADER_SPEC_VERSION :: 1 -NV_MESH_SHADER_EXTENSION_NAME :: "VK_NV_mesh_shader" -NV_fragment_shader_barycentric :: 1 -NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION :: 1 -NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME :: "VK_NV_fragment_shader_barycentric" -NV_shader_image_footprint :: 1 -NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION :: 2 -NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME :: "VK_NV_shader_image_footprint" -NV_scissor_exclusive :: 1 -NV_SCISSOR_EXCLUSIVE_SPEC_VERSION :: 2 -NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME :: "VK_NV_scissor_exclusive" -NV_device_diagnostic_checkpoints :: 1 -NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION :: 2 -NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME :: "VK_NV_device_diagnostic_checkpoints" -EXT_pci_bus_info :: 1 -EXT_PCI_BUS_INFO_SPEC_VERSION :: 2 -EXT_PCI_BUS_INFO_EXTENSION_NAME :: "VK_EXT_pci_bus_info" -AMD_display_native_hdr :: 1 -AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION :: 1 -AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME :: "VK_AMD_display_native_hdr" -EXT_fragment_density_map :: 1 -EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION :: 2 -EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME :: "VK_EXT_fragment_density_map" -EXT_scalar_block_layout :: 1 -EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION :: 1 -EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME :: "VK_EXT_scalar_block_layout" -GOOGLE_hlsl_functionality1 :: 1 -GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION :: 1 -GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME :: "VK_GOOGLE_hlsl_functionality1" -GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION :: GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION -GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME :: GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME -GOOGLE_decorate_string :: 1 -GOOGLE_DECORATE_STRING_SPEC_VERSION :: 1 -GOOGLE_DECORATE_STRING_EXTENSION_NAME :: "VK_GOOGLE_decorate_string" -EXT_subgroup_size_control :: 1 -EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION :: 2 -EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME :: "VK_EXT_subgroup_size_control" -AMD_shader_core_properties2 :: 1 -AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION :: 1 -AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME :: "VK_AMD_shader_core_properties2" -AMD_device_coherent_memory :: 1 -AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION :: 1 -AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME :: "VK_AMD_device_coherent_memory" -EXT_shader_image_atomic_int64 :: 1 -EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION :: 1 -EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME :: "VK_EXT_shader_image_atomic_int64" -EXT_memory_budget :: 1 -EXT_MEMORY_BUDGET_SPEC_VERSION :: 1 -EXT_MEMORY_BUDGET_EXTENSION_NAME :: "VK_EXT_memory_budget" -EXT_memory_priority :: 1 -EXT_MEMORY_PRIORITY_SPEC_VERSION :: 1 -EXT_MEMORY_PRIORITY_EXTENSION_NAME :: "VK_EXT_memory_priority" -NV_dedicated_allocation_image_aliasing :: 1 -NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION :: 1 -NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME :: "VK_NV_dedicated_allocation_image_aliasing" -EXT_buffer_device_address :: 1 -EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION :: 2 -EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME :: "VK_EXT_buffer_device_address" -EXT_tooling_info :: 1 -EXT_TOOLING_INFO_SPEC_VERSION :: 1 -EXT_TOOLING_INFO_EXTENSION_NAME :: "VK_EXT_tooling_info" -EXT_separate_stencil_usage :: 1 -EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION :: 1 -EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME :: "VK_EXT_separate_stencil_usage" -EXT_validation_features :: 1 -EXT_VALIDATION_FEATURES_SPEC_VERSION :: 6 -EXT_VALIDATION_FEATURES_EXTENSION_NAME :: "VK_EXT_validation_features" -NV_cooperative_matrix :: 1 -NV_COOPERATIVE_MATRIX_SPEC_VERSION :: 1 -NV_COOPERATIVE_MATRIX_EXTENSION_NAME :: "VK_NV_cooperative_matrix" -NV_coverage_reduction_mode :: 1 -NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION :: 1 -NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME :: "VK_NV_coverage_reduction_mode" -EXT_fragment_shader_interlock :: 1 -EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION :: 1 -EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME :: "VK_EXT_fragment_shader_interlock" -EXT_ycbcr_image_arrays :: 1 -EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION :: 1 -EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME :: "VK_EXT_ycbcr_image_arrays" -EXT_provoking_vertex :: 1 -EXT_PROVOKING_VERTEX_SPEC_VERSION :: 1 -EXT_PROVOKING_VERTEX_EXTENSION_NAME :: "VK_EXT_provoking_vertex" -EXT_headless_surface :: 1 -EXT_HEADLESS_SURFACE_SPEC_VERSION :: 1 -EXT_HEADLESS_SURFACE_EXTENSION_NAME :: "VK_EXT_headless_surface" -EXT_line_rasterization :: 1 -EXT_LINE_RASTERIZATION_SPEC_VERSION :: 1 -EXT_LINE_RASTERIZATION_EXTENSION_NAME :: "VK_EXT_line_rasterization" -EXT_shader_atomic_float :: 1 -EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION :: 1 -EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME :: "VK_EXT_shader_atomic_float" -EXT_host_query_reset :: 1 -EXT_HOST_QUERY_RESET_SPEC_VERSION :: 1 -EXT_HOST_QUERY_RESET_EXTENSION_NAME :: "VK_EXT_host_query_reset" -EXT_index_type_uint8 :: 1 -EXT_INDEX_TYPE_UINT8_SPEC_VERSION :: 1 -EXT_INDEX_TYPE_UINT8_EXTENSION_NAME :: "VK_EXT_index_type_uint8" -EXT_extended_dynamic_state :: 1 -EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION :: 1 -EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state" -EXT_host_image_copy :: 1 -EXT_HOST_IMAGE_COPY_SPEC_VERSION :: 1 -EXT_HOST_IMAGE_COPY_EXTENSION_NAME :: "VK_EXT_host_image_copy" -EXT_map_memory_placed :: 1 -EXT_MAP_MEMORY_PLACED_SPEC_VERSION :: 1 -EXT_MAP_MEMORY_PLACED_EXTENSION_NAME :: "VK_EXT_map_memory_placed" -EXT_shader_atomic_float2 :: 1 -EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION :: 1 -EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME :: "VK_EXT_shader_atomic_float2" -EXT_surface_maintenance1 :: 1 -EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION :: 1 -EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME :: "VK_EXT_surface_maintenance1" -EXT_swapchain_maintenance1 :: 1 -EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION :: 1 -EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME :: "VK_EXT_swapchain_maintenance1" -EXT_shader_demote_to_helper_invocation :: 1 -EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION :: 1 -EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME :: "VK_EXT_shader_demote_to_helper_invocation" -NV_device_generated_commands :: 1 -NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION :: 3 -NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME :: "VK_NV_device_generated_commands" -NV_inherited_viewport_scissor :: 1 -NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION :: 1 -NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME :: "VK_NV_inherited_viewport_scissor" -EXT_texel_buffer_alignment :: 1 -EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION :: 1 -EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME :: "VK_EXT_texel_buffer_alignment" -EXT_depth_bias_control :: 1 -EXT_DEPTH_BIAS_CONTROL_SPEC_VERSION :: 1 -EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_bias_control" -EXT_device_memory_report :: 1 -EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION :: 2 -EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME :: "VK_EXT_device_memory_report" -EXT_acquire_drm_display :: 1 -EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION :: 1 -EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME :: "VK_EXT_acquire_drm_display" -EXT_robustness2 :: 1 -EXT_ROBUSTNESS_2_SPEC_VERSION :: 1 -EXT_ROBUSTNESS_2_EXTENSION_NAME :: "VK_EXT_robustness2" -EXT_custom_border_color :: 1 -EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION :: 12 -EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME :: "VK_EXT_custom_border_color" -GOOGLE_user_type :: 1 -GOOGLE_USER_TYPE_SPEC_VERSION :: 1 -GOOGLE_USER_TYPE_EXTENSION_NAME :: "VK_GOOGLE_user_type" -NV_present_barrier :: 1 -NV_PRESENT_BARRIER_SPEC_VERSION :: 1 -NV_PRESENT_BARRIER_EXTENSION_NAME :: "VK_NV_present_barrier" -EXT_private_data :: 1 -EXT_PRIVATE_DATA_SPEC_VERSION :: 1 -EXT_PRIVATE_DATA_EXTENSION_NAME :: "VK_EXT_private_data" -EXT_pipeline_creation_cache_control :: 1 -EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION :: 3 -EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME :: "VK_EXT_pipeline_creation_cache_control" -NV_device_diagnostics_config :: 1 -NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION :: 2 -NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME :: "VK_NV_device_diagnostics_config" -NV_cuda_kernel_launch :: 1 -NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION :: 2 -NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME :: "VK_NV_cuda_kernel_launch" -NV_low_latency :: 1 -NV_LOW_LATENCY_SPEC_VERSION :: 1 -NV_LOW_LATENCY_EXTENSION_NAME :: "VK_NV_low_latency" -EXT_descriptor_buffer :: 1 -EXT_DESCRIPTOR_BUFFER_SPEC_VERSION :: 1 -EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME :: "VK_EXT_descriptor_buffer" -EXT_graphics_pipeline_library :: 1 -EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION :: 1 -EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME :: "VK_EXT_graphics_pipeline_library" -AMD_shader_early_and_late_fragment_tests :: 1 -AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION :: 1 -AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME :: "VK_AMD_shader_early_and_late_fragment_tests" -NV_fragment_shading_rate_enums :: 1 -NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION :: 1 -NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME :: "VK_NV_fragment_shading_rate_enums" -NV_ray_tracing_motion_blur :: 1 -NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION :: 1 -NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME :: "VK_NV_ray_tracing_motion_blur" -EXT_ycbcr_2plane_444_formats :: 1 -EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION :: 1 -EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME :: "VK_EXT_ycbcr_2plane_444_formats" -EXT_fragment_density_map2 :: 1 -EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION :: 1 -EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME :: "VK_EXT_fragment_density_map2" -EXT_image_robustness :: 1 -EXT_IMAGE_ROBUSTNESS_SPEC_VERSION :: 1 -EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_image_robustness" -EXT_image_compression_control :: 1 -EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION :: 1 -EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME :: "VK_EXT_image_compression_control" -EXT_attachment_feedback_loop_layout :: 1 -EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_SPEC_VERSION :: 2 -EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME :: "VK_EXT_attachment_feedback_loop_layout" -EXT_4444_formats :: 1 -EXT_4444_FORMATS_SPEC_VERSION :: 1 -EXT_4444_FORMATS_EXTENSION_NAME :: "VK_EXT_4444_formats" -EXT_device_fault :: 1 -EXT_DEVICE_FAULT_SPEC_VERSION :: 2 -EXT_DEVICE_FAULT_EXTENSION_NAME :: "VK_EXT_device_fault" -EXT_rgba10x6_formats :: 1 -EXT_RGBA10X6_FORMATS_SPEC_VERSION :: 1 -EXT_RGBA10X6_FORMATS_EXTENSION_NAME :: "VK_EXT_rgba10x6_formats" -EXT_vertex_input_dynamic_state :: 1 -EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION :: 2 -EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_vertex_input_dynamic_state" -EXT_physical_device_drm :: 1 -EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION :: 1 -EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME :: "VK_EXT_physical_device_drm" -EXT_device_address_binding_report :: 1 -EXT_DEVICE_ADDRESS_BINDING_REPORT_SPEC_VERSION :: 1 -EXT_DEVICE_ADDRESS_BINDING_REPORT_EXTENSION_NAME :: "VK_EXT_device_address_binding_report" -EXT_depth_clip_control :: 1 -EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION :: 1 -EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_clip_control" -EXT_primitive_topology_list_restart :: 1 -EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION :: 1 -EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME :: "VK_EXT_primitive_topology_list_restart" -EXT_present_mode_fifo_latest_ready :: 1 -EXT_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION :: 1 -EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME :: "VK_EXT_present_mode_fifo_latest_ready" -NV_external_memory_rdma :: 1 -NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION :: 1 -NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME :: "VK_NV_external_memory_rdma" -EXT_pipeline_properties :: 1 -EXT_PIPELINE_PROPERTIES_SPEC_VERSION :: 1 -EXT_PIPELINE_PROPERTIES_EXTENSION_NAME :: "VK_EXT_pipeline_properties" -EXT_frame_boundary :: 1 -EXT_FRAME_BOUNDARY_SPEC_VERSION :: 1 -EXT_FRAME_BOUNDARY_EXTENSION_NAME :: "VK_EXT_frame_boundary" -EXT_multisampled_render_to_single_sampled :: 1 -EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION :: 1 -EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME :: "VK_EXT_multisampled_render_to_single_sampled" -EXT_extended_dynamic_state2 :: 1 -EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION :: 1 -EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state2" -EXT_color_write_enable :: 1 -EXT_COLOR_WRITE_ENABLE_SPEC_VERSION :: 1 -EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME :: "VK_EXT_color_write_enable" -EXT_primitives_generated_query :: 1 -EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION :: 1 -EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME :: "VK_EXT_primitives_generated_query" -EXT_global_priority_query :: 1 -EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION :: 1 -EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME :: "VK_EXT_global_priority_query" -EXT_image_view_min_lod :: 1 -EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION :: 1 -EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME :: "VK_EXT_image_view_min_lod" -EXT_multi_draw :: 1 -EXT_MULTI_DRAW_SPEC_VERSION :: 1 -EXT_MULTI_DRAW_EXTENSION_NAME :: "VK_EXT_multi_draw" -EXT_image_2d_view_of_3d :: 1 -EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION :: 1 -EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME :: "VK_EXT_image_2d_view_of_3d" -EXT_shader_tile_image :: 1 -EXT_SHADER_TILE_IMAGE_SPEC_VERSION :: 1 -EXT_SHADER_TILE_IMAGE_EXTENSION_NAME :: "VK_EXT_shader_tile_image" -EXT_opacity_micromap :: 1 -EXT_OPACITY_MICROMAP_SPEC_VERSION :: 2 -EXT_OPACITY_MICROMAP_EXTENSION_NAME :: "VK_EXT_opacity_micromap" -EXT_load_store_op_none :: 1 -EXT_LOAD_STORE_OP_NONE_SPEC_VERSION :: 1 -EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME :: "VK_EXT_load_store_op_none" -EXT_border_color_swizzle :: 1 -EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION :: 1 -EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME :: "VK_EXT_border_color_swizzle" -EXT_pageable_device_local_memory :: 1 -EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION :: 1 -EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME :: "VK_EXT_pageable_device_local_memory" -EXT_image_sliced_view_of_3d :: 1 -EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION :: 1 -EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME :: "VK_EXT_image_sliced_view_of_3d" -EXT_depth_clamp_zero_one :: 1 -EXT_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION :: 1 -EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME :: "VK_EXT_depth_clamp_zero_one" -EXT_non_seamless_cube_map :: 1 -EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION :: 1 -EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME :: "VK_EXT_non_seamless_cube_map" -NV_copy_memory_indirect :: 1 -NV_COPY_MEMORY_INDIRECT_SPEC_VERSION :: 1 -NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME :: "VK_NV_copy_memory_indirect" -NV_memory_decompression :: 1 -NV_MEMORY_DECOMPRESSION_SPEC_VERSION :: 1 -NV_MEMORY_DECOMPRESSION_EXTENSION_NAME :: "VK_NV_memory_decompression" -NV_device_generated_commands_compute :: 1 -NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION :: 2 -NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME :: "VK_NV_device_generated_commands_compute" -NV_ray_tracing_linear_swept_spheres :: 1 -NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_SPEC_VERSION :: 1 -NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_EXTENSION_NAME :: "VK_NV_ray_tracing_linear_swept_spheres" -NV_linear_color_attachment :: 1 -NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION :: 1 -NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME :: "VK_NV_linear_color_attachment" -GOOGLE_surfaceless_query :: 1 -GOOGLE_SURFACELESS_QUERY_SPEC_VERSION :: 2 -GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME :: "VK_GOOGLE_surfaceless_query" -EXT_image_compression_control_swapchain :: 1 -EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION :: 1 -EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME :: "VK_EXT_image_compression_control_swapchain" -EXT_nested_command_buffer :: 1 -EXT_NESTED_COMMAND_BUFFER_SPEC_VERSION :: 1 -EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME :: "VK_EXT_nested_command_buffer" -EXT_external_memory_acquire_unmodified :: 1 -EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION :: 1 -EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXTENSION_NAME :: "VK_EXT_external_memory_acquire_unmodified" -EXT_extended_dynamic_state3 :: 1 -EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION :: 2 -EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state3" -EXT_subpass_merge_feedback :: 1 -EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION :: 2 -EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME :: "VK_EXT_subpass_merge_feedback" -EXT_shader_module_identifier :: 1 -EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION :: 1 -EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME :: "VK_EXT_shader_module_identifier" -EXT_rasterization_order_attachment_access :: 1 -EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION :: 1 -EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME :: "VK_EXT_rasterization_order_attachment_access" -NV_optical_flow :: 1 -NV_OPTICAL_FLOW_SPEC_VERSION :: 1 -NV_OPTICAL_FLOW_EXTENSION_NAME :: "VK_NV_optical_flow" -EXT_legacy_dithering :: 1 -EXT_LEGACY_DITHERING_SPEC_VERSION :: 2 -EXT_LEGACY_DITHERING_EXTENSION_NAME :: "VK_EXT_legacy_dithering" -EXT_pipeline_protected_access :: 1 -EXT_PIPELINE_PROTECTED_ACCESS_SPEC_VERSION :: 1 -EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME :: "VK_EXT_pipeline_protected_access" -AMD_anti_lag :: 1 -AMD_ANTI_LAG_SPEC_VERSION :: 1 -AMD_ANTI_LAG_EXTENSION_NAME :: "VK_AMD_anti_lag" -EXT_shader_object :: 1 -EXT_SHADER_OBJECT_SPEC_VERSION :: 1 -EXT_SHADER_OBJECT_EXTENSION_NAME :: "VK_EXT_shader_object" -NV_ray_tracing_invocation_reorder :: 1 -NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION :: 1 -NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME :: "VK_NV_ray_tracing_invocation_reorder" -NV_cooperative_vector :: 1 -NV_COOPERATIVE_VECTOR_SPEC_VERSION :: 4 -NV_COOPERATIVE_VECTOR_EXTENSION_NAME :: "VK_NV_cooperative_vector" -NV_extended_sparse_address_space :: 1 -NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION :: 1 -NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME :: "VK_NV_extended_sparse_address_space" -EXT_mutable_descriptor_type :: 1 -EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION :: 1 -EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME :: "VK_EXT_mutable_descriptor_type" -EXT_legacy_vertex_attributes :: 1 -EXT_LEGACY_VERTEX_ATTRIBUTES_SPEC_VERSION :: 1 -EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME :: "VK_EXT_legacy_vertex_attributes" -EXT_layer_settings :: 1 -EXT_LAYER_SETTINGS_SPEC_VERSION :: 2 -EXT_LAYER_SETTINGS_EXTENSION_NAME :: "VK_EXT_layer_settings" -EXT_pipeline_library_group_handles :: 1 -EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION :: 1 -EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME :: "VK_EXT_pipeline_library_group_handles" -EXT_dynamic_rendering_unused_attachments :: 1 -EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_SPEC_VERSION :: 1 -EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME :: "VK_EXT_dynamic_rendering_unused_attachments" -NV_low_latency2 :: 1 -NV_LOW_LATENCY_2_SPEC_VERSION :: 2 -NV_LOW_LATENCY_2_EXTENSION_NAME :: "VK_NV_low_latency2" -NV_per_stage_descriptor_set :: 1 -NV_PER_STAGE_DESCRIPTOR_SET_SPEC_VERSION :: 1 -NV_PER_STAGE_DESCRIPTOR_SET_EXTENSION_NAME :: "VK_NV_per_stage_descriptor_set" -EXT_attachment_feedback_loop_dynamic_state :: 1 -EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION :: 1 -EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_attachment_feedback_loop_dynamic_state" -NV_descriptor_pool_overallocation :: 1 -NV_DESCRIPTOR_POOL_OVERALLOCATION_SPEC_VERSION :: 1 -NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME :: "VK_NV_descriptor_pool_overallocation" -NV_display_stereo :: 1 -NV_DISPLAY_STEREO_SPEC_VERSION :: 1 -NV_DISPLAY_STEREO_EXTENSION_NAME :: "VK_NV_display_stereo" -NV_raw_access_chains :: 1 -NV_RAW_ACCESS_CHAINS_SPEC_VERSION :: 1 -NV_RAW_ACCESS_CHAINS_EXTENSION_NAME :: "VK_NV_raw_access_chains" -NV_command_buffer_inheritance :: 1 -NV_COMMAND_BUFFER_INHERITANCE_SPEC_VERSION :: 1 -NV_COMMAND_BUFFER_INHERITANCE_EXTENSION_NAME :: "VK_NV_command_buffer_inheritance" -NV_shader_atomic_float16_vector :: 1 -NV_SHADER_ATOMIC_FLOAT16_VECTOR_SPEC_VERSION :: 1 -NV_SHADER_ATOMIC_FLOAT16_VECTOR_EXTENSION_NAME :: "VK_NV_shader_atomic_float16_vector" -EXT_shader_replicated_composites :: 1 -EXT_SHADER_REPLICATED_COMPOSITES_SPEC_VERSION :: 1 -EXT_SHADER_REPLICATED_COMPOSITES_EXTENSION_NAME :: "VK_EXT_shader_replicated_composites" -NV_ray_tracing_validation :: 1 -NV_RAY_TRACING_VALIDATION_SPEC_VERSION :: 1 -NV_RAY_TRACING_VALIDATION_EXTENSION_NAME :: "VK_NV_ray_tracing_validation" -NV_cluster_acceleration_structure :: 1 -NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION :: 2 -NV_CLUSTER_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_cluster_acceleration_structure" -NV_partitioned_acceleration_structure :: 1 -NV_PARTITIONED_ACCELERATION_STRUCTURE_SPEC_VERSION :: 1 -NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_partitioned_acceleration_structure" -EXT_device_generated_commands :: 1 -EXT_DEVICE_GENERATED_COMMANDS_SPEC_VERSION :: 1 -EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME :: "VK_EXT_device_generated_commands" -EXT_depth_clamp_control :: 1 -EXT_DEPTH_CLAMP_CONTROL_SPEC_VERSION :: 1 -EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_clamp_control" -NV_cooperative_matrix2 :: 1 -NV_COOPERATIVE_MATRIX_2_SPEC_VERSION :: 1 -NV_COOPERATIVE_MATRIX_2_EXTENSION_NAME :: "VK_NV_cooperative_matrix2" -EXT_vertex_attribute_robustness :: 1 -EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_SPEC_VERSION :: 1 -EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_vertex_attribute_robustness" -NV_present_metering :: 1 -NV_PRESENT_METERING_SPEC_VERSION :: 1 -NV_PRESENT_METERING_EXTENSION_NAME :: "VK_NV_present_metering" -KHR_acceleration_structure :: 1 -KHR_ACCELERATION_STRUCTURE_SPEC_VERSION :: 13 -KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_KHR_acceleration_structure" -KHR_ray_tracing_pipeline :: 1 -KHR_RAY_TRACING_PIPELINE_SPEC_VERSION :: 1 -KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME :: "VK_KHR_ray_tracing_pipeline" -KHR_ray_query :: 1 -KHR_RAY_QUERY_SPEC_VERSION :: 1 -KHR_RAY_QUERY_EXTENSION_NAME :: "VK_KHR_ray_query" -EXT_mesh_shader :: 1 -EXT_MESH_SHADER_SPEC_VERSION :: 1 -EXT_MESH_SHADER_EXTENSION_NAME :: "VK_EXT_mesh_shader" -KHR_win32_surface :: 1 -KHR_WIN32_SURFACE_SPEC_VERSION :: 6 -KHR_WIN32_SURFACE_EXTENSION_NAME :: "VK_KHR_win32_surface" -KHR_external_memory_win32 :: 1 -KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION :: 1 -KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME :: "VK_KHR_external_memory_win32" -KHR_win32_keyed_mutex :: 1 -KHR_WIN32_KEYED_MUTEX_SPEC_VERSION :: 1 -KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME :: "VK_KHR_win32_keyed_mutex" -KHR_external_semaphore_win32 :: 1 -KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION :: 1 -KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME :: "VK_KHR_external_semaphore_win32" -KHR_external_fence_win32 :: 1 -KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION :: 1 -KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME :: "VK_KHR_external_fence_win32" -NV_external_memory_win32 :: 1 -NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION :: 1 -NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME :: "VK_NV_external_memory_win32" -NV_win32_keyed_mutex :: 1 -NV_WIN32_KEYED_MUTEX_SPEC_VERSION :: 2 -NV_WIN32_KEYED_MUTEX_EXTENSION_NAME :: "VK_NV_win32_keyed_mutex" -EXT_full_screen_exclusive :: 1 -EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION :: 4 -EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME :: "VK_EXT_full_screen_exclusive" -NV_acquire_winrt_display :: 1 -NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION :: 1 -NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME :: "VK_NV_acquire_winrt_display" -EXT_metal_surface :: 1 -EXT_METAL_SURFACE_SPEC_VERSION :: 1 -EXT_METAL_SURFACE_EXTENSION_NAME :: "VK_EXT_metal_surface" -EXT_metal_objects :: 1 -EXT_METAL_OBJECTS_SPEC_VERSION :: 2 -EXT_METAL_OBJECTS_EXTENSION_NAME :: "VK_EXT_metal_objects" -EXT_external_memory_metal :: 1 -EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION :: 1 -EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME :: "VK_EXT_external_memory_metal" -KHR_wayland_surface :: 1 -KHR_WAYLAND_SURFACE_SPEC_VERSION :: 6 -KHR_WAYLAND_SURFACE_EXTENSION_NAME :: "VK_KHR_wayland_surface" -KHR_xlib_surface :: 1 -KHR_XLIB_SURFACE_SPEC_VERSION :: 6 -KHR_XLIB_SURFACE_EXTENSION_NAME :: "VK_KHR_xlib_surface" -KHR_xcb_surface :: 1 -KHR_XCB_SURFACE_SPEC_VERSION :: 6 -KHR_XCB_SURFACE_EXTENSION_NAME :: "VK_KHR_xcb_surface" -KHR_portability_subset :: 1 -KHR_PORTABILITY_SUBSET_SPEC_VERSION :: 1 -KHR_PORTABILITY_SUBSET_EXTENSION_NAME :: "VK_KHR_portability_subset" -AMDX_shader_enqueue :: 1 -AMDX_SHADER_ENQUEUE_SPEC_VERSION :: 2 -AMDX_SHADER_ENQUEUE_EXTENSION_NAME :: "VK_AMDX_shader_enqueue" -NV_displacement_micromap :: 1 -NV_DISPLACEMENT_MICROMAP_SPEC_VERSION :: 2 -NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME :: "VK_NV_displacement_micromap" +KHR_surface :: 1 +KHR_SURFACE_SPEC_VERSION :: 25 +KHR_SURFACE_EXTENSION_NAME :: "VK_KHR_surface" +KHR_swapchain :: 1 +KHR_SWAPCHAIN_SPEC_VERSION :: 70 +KHR_SWAPCHAIN_EXTENSION_NAME :: "VK_KHR_swapchain" +KHR_display :: 1 +KHR_DISPLAY_SPEC_VERSION :: 23 +KHR_DISPLAY_EXTENSION_NAME :: "VK_KHR_display" +KHR_display_swapchain :: 1 +KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION :: 10 +KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME :: "VK_KHR_display_swapchain" +KHR_sampler_mirror_clamp_to_edge :: 1 +KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION :: 3 +KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME :: "VK_KHR_sampler_mirror_clamp_to_edge" +KHR_video_queue :: 1 +KHR_VIDEO_QUEUE_SPEC_VERSION :: 8 +KHR_VIDEO_QUEUE_EXTENSION_NAME :: "VK_KHR_video_queue" +KHR_video_decode_queue :: 1 +KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION :: 8 +KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME :: "VK_KHR_video_decode_queue" +KHR_video_encode_h264 :: 1 +KHR_VIDEO_ENCODE_H264_SPEC_VERSION :: 14 +KHR_VIDEO_ENCODE_H264_EXTENSION_NAME :: "VK_KHR_video_encode_h264" +KHR_video_encode_h265 :: 1 +KHR_VIDEO_ENCODE_H265_SPEC_VERSION :: 14 +KHR_VIDEO_ENCODE_H265_EXTENSION_NAME :: "VK_KHR_video_encode_h265" +KHR_video_decode_h264 :: 1 +KHR_VIDEO_DECODE_H264_SPEC_VERSION :: 9 +KHR_VIDEO_DECODE_H264_EXTENSION_NAME :: "VK_KHR_video_decode_h264" +KHR_dynamic_rendering :: 1 +KHR_DYNAMIC_RENDERING_SPEC_VERSION :: 1 +KHR_DYNAMIC_RENDERING_EXTENSION_NAME :: "VK_KHR_dynamic_rendering" +KHR_multiview :: 1 +KHR_MULTIVIEW_SPEC_VERSION :: 1 +KHR_MULTIVIEW_EXTENSION_NAME :: "VK_KHR_multiview" +KHR_get_physical_device_properties2 :: 1 +KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION :: 2 +KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME :: "VK_KHR_get_physical_device_properties2" +KHR_device_group :: 1 +KHR_DEVICE_GROUP_SPEC_VERSION :: 4 +KHR_DEVICE_GROUP_EXTENSION_NAME :: "VK_KHR_device_group" +KHR_shader_draw_parameters :: 1 +KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION :: 1 +KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME :: "VK_KHR_shader_draw_parameters" +KHR_maintenance1 :: 1 +KHR_MAINTENANCE_1_SPEC_VERSION :: 2 +KHR_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_maintenance1" +KHR_MAINTENANCE1_SPEC_VERSION :: KHR_MAINTENANCE_1_SPEC_VERSION +KHR_MAINTENANCE1_EXTENSION_NAME :: KHR_MAINTENANCE_1_EXTENSION_NAME +KHR_device_group_creation :: 1 +KHR_DEVICE_GROUP_CREATION_SPEC_VERSION :: 1 +KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME :: "VK_KHR_device_group_creation" +MAX_DEVICE_GROUP_SIZE_KHR :: MAX_DEVICE_GROUP_SIZE +KHR_external_memory_capabilities :: 1 +KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION :: 1 +KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_memory_capabilities" +LUID_SIZE_KHR :: LUID_SIZE +KHR_external_memory :: 1 +KHR_EXTERNAL_MEMORY_SPEC_VERSION :: 1 +KHR_EXTERNAL_MEMORY_EXTENSION_NAME :: "VK_KHR_external_memory" +QUEUE_FAMILY_EXTERNAL_KHR :: QUEUE_FAMILY_EXTERNAL +KHR_external_memory_fd :: 1 +KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION :: 1 +KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME :: "VK_KHR_external_memory_fd" +KHR_external_semaphore_capabilities :: 1 +KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION :: 1 +KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_semaphore_capabilities" +KHR_external_semaphore :: 1 +KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION :: 1 +KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME :: "VK_KHR_external_semaphore" +KHR_external_semaphore_fd :: 1 +KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION :: 1 +KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME :: "VK_KHR_external_semaphore_fd" +KHR_push_descriptor :: 1 +KHR_PUSH_DESCRIPTOR_SPEC_VERSION :: 2 +KHR_PUSH_DESCRIPTOR_EXTENSION_NAME :: "VK_KHR_push_descriptor" +KHR_shader_float16_int8 :: 1 +KHR_SHADER_FLOAT16_INT8_SPEC_VERSION :: 1 +KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME :: "VK_KHR_shader_float16_int8" +KHR_16bit_storage :: 1 +KHR_16BIT_STORAGE_SPEC_VERSION :: 1 +KHR_16BIT_STORAGE_EXTENSION_NAME :: "VK_KHR_16bit_storage" +KHR_incremental_present :: 1 +KHR_INCREMENTAL_PRESENT_SPEC_VERSION :: 2 +KHR_INCREMENTAL_PRESENT_EXTENSION_NAME :: "VK_KHR_incremental_present" +KHR_descriptor_update_template :: 1 +KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION :: 1 +KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME :: "VK_KHR_descriptor_update_template" +KHR_imageless_framebuffer :: 1 +KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION :: 1 +KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME :: "VK_KHR_imageless_framebuffer" +KHR_create_renderpass2 :: 1 +KHR_CREATE_RENDERPASS_2_SPEC_VERSION :: 1 +KHR_CREATE_RENDERPASS_2_EXTENSION_NAME :: "VK_KHR_create_renderpass2" +KHR_shared_presentable_image :: 1 +KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION :: 1 +KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME :: "VK_KHR_shared_presentable_image" +KHR_external_fence_capabilities :: 1 +KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION :: 1 +KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_external_fence_capabilities" +KHR_external_fence :: 1 +KHR_EXTERNAL_FENCE_SPEC_VERSION :: 1 +KHR_EXTERNAL_FENCE_EXTENSION_NAME :: "VK_KHR_external_fence" +KHR_external_fence_fd :: 1 +KHR_EXTERNAL_FENCE_FD_SPEC_VERSION :: 1 +KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME :: "VK_KHR_external_fence_fd" +KHR_performance_query :: 1 +KHR_PERFORMANCE_QUERY_SPEC_VERSION :: 1 +KHR_PERFORMANCE_QUERY_EXTENSION_NAME :: "VK_KHR_performance_query" +KHR_maintenance2 :: 1 +KHR_MAINTENANCE_2_SPEC_VERSION :: 1 +KHR_MAINTENANCE_2_EXTENSION_NAME :: "VK_KHR_maintenance2" +KHR_MAINTENANCE2_SPEC_VERSION :: KHR_MAINTENANCE_2_SPEC_VERSION +KHR_MAINTENANCE2_EXTENSION_NAME :: KHR_MAINTENANCE_2_EXTENSION_NAME +KHR_get_surface_capabilities2 :: 1 +KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION :: 1 +KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME :: "VK_KHR_get_surface_capabilities2" +KHR_variable_pointers :: 1 +KHR_VARIABLE_POINTERS_SPEC_VERSION :: 1 +KHR_VARIABLE_POINTERS_EXTENSION_NAME :: "VK_KHR_variable_pointers" +KHR_get_display_properties2 :: 1 +KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION :: 1 +KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME :: "VK_KHR_get_display_properties2" +KHR_dedicated_allocation :: 1 +KHR_DEDICATED_ALLOCATION_SPEC_VERSION :: 3 +KHR_DEDICATED_ALLOCATION_EXTENSION_NAME :: "VK_KHR_dedicated_allocation" +KHR_storage_buffer_storage_class :: 1 +KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION :: 1 +KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME :: "VK_KHR_storage_buffer_storage_class" +KHR_shader_bfloat16 :: 1 +KHR_SHADER_BFLOAT16_SPEC_VERSION :: 1 +KHR_SHADER_BFLOAT16_EXTENSION_NAME :: "VK_KHR_shader_bfloat16" +KHR_relaxed_block_layout :: 1 +KHR_RELAXED_BLOCK_LAYOUT_SPEC_VERSION :: 1 +KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME :: "VK_KHR_relaxed_block_layout" +KHR_get_memory_requirements2 :: 1 +KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION :: 1 +KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME :: "VK_KHR_get_memory_requirements2" +KHR_image_format_list :: 1 +KHR_IMAGE_FORMAT_LIST_SPEC_VERSION :: 1 +KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME :: "VK_KHR_image_format_list" +KHR_sampler_ycbcr_conversion :: 1 +KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION :: 14 +KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME :: "VK_KHR_sampler_ycbcr_conversion" +KHR_bind_memory2 :: 1 +KHR_BIND_MEMORY_2_SPEC_VERSION :: 1 +KHR_BIND_MEMORY_2_EXTENSION_NAME :: "VK_KHR_bind_memory2" +KHR_maintenance3 :: 1 +KHR_MAINTENANCE_3_SPEC_VERSION :: 1 +KHR_MAINTENANCE_3_EXTENSION_NAME :: "VK_KHR_maintenance3" +KHR_MAINTENANCE3_SPEC_VERSION :: KHR_MAINTENANCE_3_SPEC_VERSION +KHR_MAINTENANCE3_EXTENSION_NAME :: KHR_MAINTENANCE_3_EXTENSION_NAME +KHR_draw_indirect_count :: 1 +KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION :: 1 +KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME :: "VK_KHR_draw_indirect_count" +KHR_shader_subgroup_extended_types :: 1 +KHR_SHADER_SUBGROUP_EXTENDED_TYPES_SPEC_VERSION :: 1 +KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME :: "VK_KHR_shader_subgroup_extended_types" +KHR_8bit_storage :: 1 +KHR_8BIT_STORAGE_SPEC_VERSION :: 1 +KHR_8BIT_STORAGE_EXTENSION_NAME :: "VK_KHR_8bit_storage" +KHR_shader_atomic_int64 :: 1 +KHR_SHADER_ATOMIC_INT64_SPEC_VERSION :: 1 +KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME :: "VK_KHR_shader_atomic_int64" +KHR_shader_clock :: 1 +KHR_SHADER_CLOCK_SPEC_VERSION :: 1 +KHR_SHADER_CLOCK_EXTENSION_NAME :: "VK_KHR_shader_clock" +KHR_video_decode_h265 :: 1 +KHR_VIDEO_DECODE_H265_SPEC_VERSION :: 8 +KHR_VIDEO_DECODE_H265_EXTENSION_NAME :: "VK_KHR_video_decode_h265" +KHR_global_priority :: 1 +KHR_GLOBAL_PRIORITY_SPEC_VERSION :: 1 +KHR_GLOBAL_PRIORITY_EXTENSION_NAME :: "VK_KHR_global_priority" +MAX_GLOBAL_PRIORITY_SIZE_KHR :: MAX_GLOBAL_PRIORITY_SIZE +KHR_driver_properties :: 1 +KHR_DRIVER_PROPERTIES_SPEC_VERSION :: 1 +KHR_DRIVER_PROPERTIES_EXTENSION_NAME :: "VK_KHR_driver_properties" +MAX_DRIVER_NAME_SIZE_KHR :: MAX_DRIVER_NAME_SIZE +MAX_DRIVER_INFO_SIZE_KHR :: MAX_DRIVER_INFO_SIZE +KHR_shader_float_controls :: 1 +KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION :: 4 +KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME :: "VK_KHR_shader_float_controls" +KHR_depth_stencil_resolve :: 1 +KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION :: 1 +KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME :: "VK_KHR_depth_stencil_resolve" +KHR_swapchain_mutable_format :: 1 +KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION :: 1 +KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME :: "VK_KHR_swapchain_mutable_format" +KHR_timeline_semaphore :: 1 +KHR_TIMELINE_SEMAPHORE_SPEC_VERSION :: 2 +KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME :: "VK_KHR_timeline_semaphore" +KHR_vulkan_memory_model :: 1 +KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION :: 3 +KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME :: "VK_KHR_vulkan_memory_model" +KHR_shader_terminate_invocation :: 1 +KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION :: 1 +KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME :: "VK_KHR_shader_terminate_invocation" +KHR_fragment_shading_rate :: 1 +KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION :: 2 +KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME :: "VK_KHR_fragment_shading_rate" +KHR_shader_constant_data :: 1 +KHR_SHADER_CONSTANT_DATA_SPEC_VERSION :: 1 +KHR_SHADER_CONSTANT_DATA_EXTENSION_NAME :: "VK_KHR_shader_constant_data" +KHR_dynamic_rendering_local_read :: 1 +KHR_DYNAMIC_RENDERING_LOCAL_READ_SPEC_VERSION :: 1 +KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME :: "VK_KHR_dynamic_rendering_local_read" +KHR_shader_abort :: 1 +KHR_SHADER_ABORT_SPEC_VERSION :: 1 +KHR_SHADER_ABORT_EXTENSION_NAME :: "VK_KHR_shader_abort" +KHR_shader_quad_control :: 1 +KHR_SHADER_QUAD_CONTROL_SPEC_VERSION :: 1 +KHR_SHADER_QUAD_CONTROL_EXTENSION_NAME :: "VK_KHR_shader_quad_control" +KHR_spirv_1_4 :: 1 +KHR_SPIRV_1_4_SPEC_VERSION :: 1 +KHR_SPIRV_1_4_EXTENSION_NAME :: "VK_KHR_spirv_1_4" +KHR_surface_protected_capabilities :: 1 +KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION :: 1 +KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME :: "VK_KHR_surface_protected_capabilities" +KHR_separate_depth_stencil_layouts :: 1 +KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_SPEC_VERSION :: 1 +KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME :: "VK_KHR_separate_depth_stencil_layouts" +KHR_present_wait :: 1 +KHR_PRESENT_WAIT_SPEC_VERSION :: 1 +KHR_PRESENT_WAIT_EXTENSION_NAME :: "VK_KHR_present_wait" +KHR_uniform_buffer_standard_layout :: 1 +KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_SPEC_VERSION :: 1 +KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME :: "VK_KHR_uniform_buffer_standard_layout" +KHR_buffer_device_address :: 1 +KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION :: 1 +KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME :: "VK_KHR_buffer_device_address" +KHR_deferred_host_operations :: 1 +KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION :: 4 +KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME :: "VK_KHR_deferred_host_operations" +KHR_pipeline_executable_properties :: 1 +KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION :: 1 +KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME :: "VK_KHR_pipeline_executable_properties" +KHR_map_memory2 :: 1 +KHR_MAP_MEMORY_2_SPEC_VERSION :: 1 +KHR_MAP_MEMORY_2_EXTENSION_NAME :: "VK_KHR_map_memory2" +KHR_shader_integer_dot_product :: 1 +KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION :: 1 +KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME :: "VK_KHR_shader_integer_dot_product" +KHR_pipeline_library :: 1 +KHR_PIPELINE_LIBRARY_SPEC_VERSION :: 1 +KHR_PIPELINE_LIBRARY_EXTENSION_NAME :: "VK_KHR_pipeline_library" +KHR_shader_non_semantic_info :: 1 +KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION :: 1 +KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME :: "VK_KHR_shader_non_semantic_info" +KHR_present_id :: 1 +KHR_PRESENT_ID_SPEC_VERSION :: 1 +KHR_PRESENT_ID_EXTENSION_NAME :: "VK_KHR_present_id" +KHR_video_encode_queue :: 1 +KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION :: 12 +KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME :: "VK_KHR_video_encode_queue" +KHR_synchronization2 :: 1 +KHR_SYNCHRONIZATION_2_SPEC_VERSION :: 1 +KHR_SYNCHRONIZATION_2_EXTENSION_NAME :: "VK_KHR_synchronization2" +KHR_device_address_commands :: 1 +KHR_DEVICE_ADDRESS_COMMANDS_SPEC_VERSION :: 1 +KHR_DEVICE_ADDRESS_COMMANDS_EXTENSION_NAME :: "VK_KHR_device_address_commands" +KHR_fragment_shader_barycentric :: 1 +KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION :: 1 +KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME :: "VK_KHR_fragment_shader_barycentric" +KHR_shader_subgroup_uniform_control_flow :: 1 +KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION :: 1 +KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME :: "VK_KHR_shader_subgroup_uniform_control_flow" +KHR_zero_initialize_workgroup_memory :: 1 +KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION :: 1 +KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME :: "VK_KHR_zero_initialize_workgroup_memory" +KHR_workgroup_memory_explicit_layout :: 1 +KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION :: 1 +KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME :: "VK_KHR_workgroup_memory_explicit_layout" +KHR_copy_commands2 :: 1 +KHR_COPY_COMMANDS_2_SPEC_VERSION :: 1 +KHR_COPY_COMMANDS_2_EXTENSION_NAME :: "VK_KHR_copy_commands2" +KHR_format_feature_flags2 :: 1 +KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION :: 2 +KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME :: "VK_KHR_format_feature_flags2" +KHR_ray_tracing_maintenance1 :: 1 +KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION :: 1 +KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_ray_tracing_maintenance1" +KHR_shader_untyped_pointers :: 1 +KHR_SHADER_UNTYPED_POINTERS_SPEC_VERSION :: 1 +KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME :: "VK_KHR_shader_untyped_pointers" +KHR_portability_enumeration :: 1 +KHR_PORTABILITY_ENUMERATION_SPEC_VERSION :: 1 +KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME :: "VK_KHR_portability_enumeration" +KHR_maintenance4 :: 1 +KHR_MAINTENANCE_4_SPEC_VERSION :: 2 +KHR_MAINTENANCE_4_EXTENSION_NAME :: "VK_KHR_maintenance4" +KHR_shader_subgroup_rotate :: 1 +KHR_SHADER_SUBGROUP_ROTATE_SPEC_VERSION :: 2 +KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME :: "VK_KHR_shader_subgroup_rotate" +KHR_shader_maximal_reconvergence :: 1 +KHR_SHADER_MAXIMAL_RECONVERGENCE_SPEC_VERSION :: 1 +KHR_SHADER_MAXIMAL_RECONVERGENCE_EXTENSION_NAME :: "VK_KHR_shader_maximal_reconvergence" +KHR_maintenance5 :: 1 +KHR_MAINTENANCE_5_SPEC_VERSION :: 1 +KHR_MAINTENANCE_5_EXTENSION_NAME :: "VK_KHR_maintenance5" +KHR_present_id2 :: 1 +KHR_PRESENT_ID_2_SPEC_VERSION :: 1 +KHR_PRESENT_ID_2_EXTENSION_NAME :: "VK_KHR_present_id2" +KHR_present_wait2 :: 1 +KHR_PRESENT_WAIT_2_SPEC_VERSION :: 1 +KHR_PRESENT_WAIT_2_EXTENSION_NAME :: "VK_KHR_present_wait2" +KHR_ray_tracing_position_fetch :: 1 +KHR_RAY_TRACING_POSITION_FETCH_SPEC_VERSION :: 1 +KHR_RAY_TRACING_POSITION_FETCH_EXTENSION_NAME :: "VK_KHR_ray_tracing_position_fetch" +KHR_pipeline_binary :: 1 +MAX_PIPELINE_BINARY_KEY_SIZE_KHR :: 32 +KHR_PIPELINE_BINARY_SPEC_VERSION :: 1 +KHR_PIPELINE_BINARY_EXTENSION_NAME :: "VK_KHR_pipeline_binary" +KHR_surface_maintenance1 :: 1 +KHR_SURFACE_MAINTENANCE_1_SPEC_VERSION :: 1 +KHR_SURFACE_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_surface_maintenance1" +KHR_swapchain_maintenance1 :: 1 +KHR_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION :: 1 +KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_swapchain_maintenance1" +KHR_internally_synchronized_queues :: 1 +KHR_INTERNALLY_SYNCHRONIZED_QUEUES_SPEC_VERSION :: 1 +KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME :: "VK_KHR_internally_synchronized_queues" +KHR_cooperative_matrix :: 1 +KHR_COOPERATIVE_MATRIX_SPEC_VERSION :: 2 +KHR_COOPERATIVE_MATRIX_EXTENSION_NAME :: "VK_KHR_cooperative_matrix" +KHR_compute_shader_derivatives :: 1 +KHR_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION :: 1 +KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME :: "VK_KHR_compute_shader_derivatives" +KHR_video_decode_av1 :: 1 +MAX_VIDEO_AV1_REFERENCES_PER_FRAME_KHR :: 7 +KHR_VIDEO_DECODE_AV1_SPEC_VERSION :: 1 +KHR_VIDEO_DECODE_AV1_EXTENSION_NAME :: "VK_KHR_video_decode_av1" +KHR_video_encode_av1 :: 1 +KHR_VIDEO_ENCODE_AV1_SPEC_VERSION :: 1 +KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME :: "VK_KHR_video_encode_av1" +KHR_video_decode_vp9 :: 1 +MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR :: 3 +KHR_VIDEO_DECODE_VP9_SPEC_VERSION :: 1 +KHR_VIDEO_DECODE_VP9_EXTENSION_NAME :: "VK_KHR_video_decode_vp9" +KHR_video_maintenance1 :: 1 +KHR_VIDEO_MAINTENANCE_1_SPEC_VERSION :: 1 +KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME :: "VK_KHR_video_maintenance1" +KHR_vertex_attribute_divisor :: 1 +KHR_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION :: 1 +KHR_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME :: "VK_KHR_vertex_attribute_divisor" +KHR_load_store_op_none :: 1 +KHR_LOAD_STORE_OP_NONE_SPEC_VERSION :: 1 +KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME :: "VK_KHR_load_store_op_none" +KHR_unified_image_layouts :: 1 +KHR_UNIFIED_IMAGE_LAYOUTS_SPEC_VERSION :: 1 +KHR_UNIFIED_IMAGE_LAYOUTS_EXTENSION_NAME :: "VK_KHR_unified_image_layouts" +KHR_shader_float_controls2 :: 1 +KHR_SHADER_FLOAT_CONTROLS_2_SPEC_VERSION :: 1 +KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME :: "VK_KHR_shader_float_controls2" +KHR_index_type_uint8 :: 1 +KHR_INDEX_TYPE_UINT8_SPEC_VERSION :: 1 +KHR_INDEX_TYPE_UINT8_EXTENSION_NAME :: "VK_KHR_index_type_uint8" +KHR_line_rasterization :: 1 +KHR_LINE_RASTERIZATION_SPEC_VERSION :: 1 +KHR_LINE_RASTERIZATION_EXTENSION_NAME :: "VK_KHR_line_rasterization" +KHR_calibrated_timestamps :: 1 +KHR_CALIBRATED_TIMESTAMPS_SPEC_VERSION :: 1 +KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME :: "VK_KHR_calibrated_timestamps" +KHR_shader_expect_assume :: 1 +KHR_SHADER_EXPECT_ASSUME_SPEC_VERSION :: 1 +KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME :: "VK_KHR_shader_expect_assume" +KHR_maintenance6 :: 1 +KHR_MAINTENANCE_6_SPEC_VERSION :: 1 +KHR_MAINTENANCE_6_EXTENSION_NAME :: "VK_KHR_maintenance6" +KHR_copy_memory_indirect :: 1 +KHR_COPY_MEMORY_INDIRECT_SPEC_VERSION :: 1 +KHR_COPY_MEMORY_INDIRECT_EXTENSION_NAME :: "VK_KHR_copy_memory_indirect" +KHR_video_encode_intra_refresh :: 1 +KHR_VIDEO_ENCODE_INTRA_REFRESH_SPEC_VERSION :: 1 +KHR_VIDEO_ENCODE_INTRA_REFRESH_EXTENSION_NAME :: "VK_KHR_video_encode_intra_refresh" +KHR_video_encode_quantization_map :: 1 +KHR_VIDEO_ENCODE_QUANTIZATION_MAP_SPEC_VERSION :: 2 +KHR_VIDEO_ENCODE_QUANTIZATION_MAP_EXTENSION_NAME :: "VK_KHR_video_encode_quantization_map" +KHR_shader_relaxed_extended_instruction :: 1 +KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_SPEC_VERSION :: 1 +KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME :: "VK_KHR_shader_relaxed_extended_instruction" +KHR_maintenance7 :: 1 +KHR_MAINTENANCE_7_SPEC_VERSION :: 1 +KHR_MAINTENANCE_7_EXTENSION_NAME :: "VK_KHR_maintenance7" +KHR_device_fault :: 1 +KHR_DEVICE_FAULT_SPEC_VERSION :: 1 +KHR_DEVICE_FAULT_EXTENSION_NAME :: "VK_KHR_device_fault" +KHR_maintenance8 :: 1 +KHR_MAINTENANCE_8_SPEC_VERSION :: 1 +KHR_MAINTENANCE_8_EXTENSION_NAME :: "VK_KHR_maintenance8" +KHR_shader_fma :: 1 +KHR_SHADER_FMA_SPEC_VERSION :: 1 +KHR_SHADER_FMA_EXTENSION_NAME :: "VK_KHR_shader_fma" +KHR_maintenance9 :: 1 +KHR_MAINTENANCE_9_SPEC_VERSION :: 1 +KHR_MAINTENANCE_9_EXTENSION_NAME :: "VK_KHR_maintenance9" +KHR_video_maintenance2 :: 1 +KHR_VIDEO_MAINTENANCE_2_SPEC_VERSION :: 1 +KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME :: "VK_KHR_video_maintenance2" +KHR_video_encode_feedback2 :: 1 +KHR_VIDEO_ENCODE_FEEDBACK_2_SPEC_VERSION :: 1 +KHR_VIDEO_ENCODE_FEEDBACK_2_EXTENSION_NAME :: "VK_KHR_video_encode_feedback2" +KHR_depth_clamp_zero_one :: 1 +KHR_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION :: 1 +KHR_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME :: "VK_KHR_depth_clamp_zero_one" +KHR_robustness2 :: 1 +KHR_ROBUSTNESS_2_SPEC_VERSION :: 1 +KHR_ROBUSTNESS_2_EXTENSION_NAME :: "VK_KHR_robustness2" +KHR_present_mode_fifo_latest_ready :: 1 +KHR_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION :: 1 +KHR_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME :: "VK_KHR_present_mode_fifo_latest_ready" +KHR_opacity_micromap :: 1 +KHR_OPACITY_MICROMAP_SPEC_VERSION :: 1 +KHR_OPACITY_MICROMAP_EXTENSION_NAME :: "VK_KHR_opacity_micromap" +KHR_maintenance10 :: 1 +KHR_MAINTENANCE_10_SPEC_VERSION :: 1 +KHR_MAINTENANCE_10_EXTENSION_NAME :: "VK_KHR_maintenance10" +KHR_maintenance11 :: 1 +KHR_MAINTENANCE_11_SPEC_VERSION :: 1 +KHR_MAINTENANCE_11_EXTENSION_NAME :: "VK_KHR_maintenance11" +KHR_extended_flags :: 1 +KHR_EXTENDED_FLAGS_SPEC_VERSION :: 1 +KHR_EXTENDED_FLAGS_EXTENSION_NAME :: "VK_KHR_extended_flags" +EXT_debug_report :: 1 +EXT_DEBUG_REPORT_SPEC_VERSION :: 10 +EXT_DEBUG_REPORT_EXTENSION_NAME :: "VK_EXT_debug_report" +NV_glsl_shader :: 1 +NV_GLSL_SHADER_SPEC_VERSION :: 1 +NV_GLSL_SHADER_EXTENSION_NAME :: "VK_NV_glsl_shader" +EXT_depth_range_unrestricted :: 1 +EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION :: 1 +EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME :: "VK_EXT_depth_range_unrestricted" +AMD_rasterization_order :: 1 +AMD_RASTERIZATION_ORDER_SPEC_VERSION :: 1 +AMD_RASTERIZATION_ORDER_EXTENSION_NAME :: "VK_AMD_rasterization_order" +AMD_shader_trinary_minmax :: 1 +AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION :: 1 +AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME :: "VK_AMD_shader_trinary_minmax" +AMD_shader_explicit_vertex_parameter :: 1 +AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION :: 1 +AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME :: "VK_AMD_shader_explicit_vertex_parameter" +EXT_debug_marker :: 1 +EXT_DEBUG_MARKER_SPEC_VERSION :: 4 +EXT_DEBUG_MARKER_EXTENSION_NAME :: "VK_EXT_debug_marker" +AMD_gcn_shader :: 1 +AMD_GCN_SHADER_SPEC_VERSION :: 1 +AMD_GCN_SHADER_EXTENSION_NAME :: "VK_AMD_gcn_shader" +NV_dedicated_allocation :: 1 +NV_DEDICATED_ALLOCATION_SPEC_VERSION :: 1 +NV_DEDICATED_ALLOCATION_EXTENSION_NAME :: "VK_NV_dedicated_allocation" +EXT_transform_feedback :: 1 +EXT_TRANSFORM_FEEDBACK_SPEC_VERSION :: 1 +EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME :: "VK_EXT_transform_feedback" +NVX_binary_import :: 1 +NVX_BINARY_IMPORT_SPEC_VERSION :: 2 +NVX_BINARY_IMPORT_EXTENSION_NAME :: "VK_NVX_binary_import" +NVX_image_view_handle :: 1 +NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION :: 4 +NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME :: "VK_NVX_image_view_handle" +AMD_draw_indirect_count :: 1 +AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION :: 2 +AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME :: "VK_AMD_draw_indirect_count" +AMD_negative_viewport_height :: 1 +AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION :: 1 +AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME :: "VK_AMD_negative_viewport_height" +AMD_gpu_shader_half_float :: 1 +AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION :: 2 +AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME :: "VK_AMD_gpu_shader_half_float" +AMD_shader_ballot :: 1 +AMD_SHADER_BALLOT_SPEC_VERSION :: 1 +AMD_SHADER_BALLOT_EXTENSION_NAME :: "VK_AMD_shader_ballot" +AMD_texture_gather_bias_lod :: 1 +AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION :: 1 +AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME :: "VK_AMD_texture_gather_bias_lod" +AMD_shader_info :: 1 +AMD_SHADER_INFO_SPEC_VERSION :: 1 +AMD_SHADER_INFO_EXTENSION_NAME :: "VK_AMD_shader_info" +AMD_shader_image_load_store_lod :: 1 +AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION :: 1 +AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME :: "VK_AMD_shader_image_load_store_lod" +NV_corner_sampled_image :: 1 +NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION :: 2 +NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME :: "VK_NV_corner_sampled_image" +NV_external_memory_capabilities :: 1 +NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION :: 1 +NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME :: "VK_NV_external_memory_capabilities" +NV_external_memory :: 1 +NV_EXTERNAL_MEMORY_SPEC_VERSION :: 1 +NV_EXTERNAL_MEMORY_EXTENSION_NAME :: "VK_NV_external_memory" +EXT_validation_flags :: 1 +EXT_VALIDATION_FLAGS_SPEC_VERSION :: 3 +EXT_VALIDATION_FLAGS_EXTENSION_NAME :: "VK_EXT_validation_flags" +EXT_shader_subgroup_ballot :: 1 +EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION :: 1 +EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME :: "VK_EXT_shader_subgroup_ballot" +EXT_shader_subgroup_vote :: 1 +EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION :: 1 +EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME :: "VK_EXT_shader_subgroup_vote" +EXT_texture_compression_astc_hdr :: 1 +EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION :: 1 +EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME :: "VK_EXT_texture_compression_astc_hdr" +EXT_astc_decode_mode :: 1 +EXT_ASTC_DECODE_MODE_SPEC_VERSION :: 1 +EXT_ASTC_DECODE_MODE_EXTENSION_NAME :: "VK_EXT_astc_decode_mode" +EXT_pipeline_robustness :: 1 +EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION :: 1 +EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_pipeline_robustness" +EXT_conditional_rendering :: 1 +EXT_CONDITIONAL_RENDERING_SPEC_VERSION :: 2 +EXT_CONDITIONAL_RENDERING_EXTENSION_NAME :: "VK_EXT_conditional_rendering" +NV_clip_space_w_scaling :: 1 +NV_CLIP_SPACE_W_SCALING_SPEC_VERSION :: 1 +NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME :: "VK_NV_clip_space_w_scaling" +EXT_direct_mode_display :: 1 +EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION :: 1 +EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME :: "VK_EXT_direct_mode_display" +EXT_display_surface_counter :: 1 +EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION :: 1 +EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME :: "VK_EXT_display_surface_counter" +EXT_display_control :: 1 +EXT_DISPLAY_CONTROL_SPEC_VERSION :: 1 +EXT_DISPLAY_CONTROL_EXTENSION_NAME :: "VK_EXT_display_control" +GOOGLE_display_timing :: 1 +GOOGLE_DISPLAY_TIMING_SPEC_VERSION :: 1 +GOOGLE_DISPLAY_TIMING_EXTENSION_NAME :: "VK_GOOGLE_display_timing" +NV_sample_mask_override_coverage :: 1 +NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION :: 1 +NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME :: "VK_NV_sample_mask_override_coverage" +NV_geometry_shader_passthrough :: 1 +NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION :: 1 +NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME :: "VK_NV_geometry_shader_passthrough" +NV_viewport_array2 :: 1 +NV_VIEWPORT_ARRAY_2_SPEC_VERSION :: 1 +NV_VIEWPORT_ARRAY_2_EXTENSION_NAME :: "VK_NV_viewport_array2" +NV_VIEWPORT_ARRAY2_SPEC_VERSION :: NV_VIEWPORT_ARRAY_2_SPEC_VERSION +NV_VIEWPORT_ARRAY2_EXTENSION_NAME :: NV_VIEWPORT_ARRAY_2_EXTENSION_NAME +NVX_multiview_per_view_attributes :: 1 +NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION :: 1 +NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME :: "VK_NVX_multiview_per_view_attributes" +NV_viewport_swizzle :: 1 +NV_VIEWPORT_SWIZZLE_SPEC_VERSION :: 1 +NV_VIEWPORT_SWIZZLE_EXTENSION_NAME :: "VK_NV_viewport_swizzle" +EXT_discard_rectangles :: 1 +EXT_DISCARD_RECTANGLES_SPEC_VERSION :: 2 +EXT_DISCARD_RECTANGLES_EXTENSION_NAME :: "VK_EXT_discard_rectangles" +EXT_conservative_rasterization :: 1 +EXT_CONSERVATIVE_RASTERIZATION_SPEC_VERSION :: 1 +EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME :: "VK_EXT_conservative_rasterization" +EXT_depth_clip_enable :: 1 +EXT_DEPTH_CLIP_ENABLE_SPEC_VERSION :: 1 +EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME :: "VK_EXT_depth_clip_enable" +EXT_swapchain_colorspace :: 1 +EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION :: 5 +EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME :: "VK_EXT_swapchain_colorspace" +EXT_hdr_metadata :: 1 +EXT_HDR_METADATA_SPEC_VERSION :: 3 +EXT_HDR_METADATA_EXTENSION_NAME :: "VK_EXT_hdr_metadata" +EXT_external_memory_dma_buf :: 1 +EXT_EXTERNAL_MEMORY_DMA_BUF_SPEC_VERSION :: 1 +EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME :: "VK_EXT_external_memory_dma_buf" +EXT_queue_family_foreign :: 1 +EXT_QUEUE_FAMILY_FOREIGN_SPEC_VERSION :: 1 +EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME :: "VK_EXT_queue_family_foreign" +QUEUE_FAMILY_FOREIGN_EXT :: 2 +EXT_debug_utils :: 1 +EXT_DEBUG_UTILS_SPEC_VERSION :: 2 +EXT_DEBUG_UTILS_EXTENSION_NAME :: "VK_EXT_debug_utils" +EXT_sampler_filter_minmax :: 1 +EXT_SAMPLER_FILTER_MINMAX_SPEC_VERSION :: 2 +EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME :: "VK_EXT_sampler_filter_minmax" +AMD_gpu_shader_int16 :: 1 +AMD_GPU_SHADER_INT16_SPEC_VERSION :: 2 +AMD_GPU_SHADER_INT16_EXTENSION_NAME :: "VK_AMD_gpu_shader_int16" +AMD_gpa_interface :: 1 +AMD_GPA_INTERFACE_SPEC_VERSION :: 1 +AMD_GPA_INTERFACE_EXTENSION_NAME :: "VK_AMD_gpa_interface" +EXT_descriptor_heap :: 1 +EXT_DESCRIPTOR_HEAP_SPEC_VERSION :: 1 +EXT_DESCRIPTOR_HEAP_EXTENSION_NAME :: "VK_EXT_descriptor_heap" +AMD_mixed_attachment_samples :: 1 +AMD_MIXED_ATTACHMENT_SAMPLES_SPEC_VERSION :: 1 +AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME :: "VK_AMD_mixed_attachment_samples" +AMD_shader_fragment_mask :: 1 +AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION :: 1 +AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME :: "VK_AMD_shader_fragment_mask" +EXT_inline_uniform_block :: 1 +EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION :: 1 +EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME :: "VK_EXT_inline_uniform_block" +EXT_shader_stencil_export :: 1 +EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION :: 1 +EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME :: "VK_EXT_shader_stencil_export" +EXT_sample_locations :: 1 +EXT_SAMPLE_LOCATIONS_SPEC_VERSION :: 1 +EXT_SAMPLE_LOCATIONS_EXTENSION_NAME :: "VK_EXT_sample_locations" +EXT_blend_operation_advanced :: 1 +EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION :: 2 +EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME :: "VK_EXT_blend_operation_advanced" +NV_fragment_coverage_to_color :: 1 +NV_FRAGMENT_COVERAGE_TO_COLOR_SPEC_VERSION :: 1 +NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME :: "VK_NV_fragment_coverage_to_color" +NV_framebuffer_mixed_samples :: 1 +NV_FRAMEBUFFER_MIXED_SAMPLES_SPEC_VERSION :: 1 +NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME :: "VK_NV_framebuffer_mixed_samples" +NV_fill_rectangle :: 1 +NV_FILL_RECTANGLE_SPEC_VERSION :: 1 +NV_FILL_RECTANGLE_EXTENSION_NAME :: "VK_NV_fill_rectangle" +NV_shader_sm_builtins :: 1 +NV_SHADER_SM_BUILTINS_SPEC_VERSION :: 1 +NV_SHADER_SM_BUILTINS_EXTENSION_NAME :: "VK_NV_shader_sm_builtins" +EXT_post_depth_coverage :: 1 +EXT_POST_DEPTH_COVERAGE_SPEC_VERSION :: 1 +EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME :: "VK_EXT_post_depth_coverage" +EXT_image_drm_format_modifier :: 1 +EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION :: 2 +EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME :: "VK_EXT_image_drm_format_modifier" +EXT_validation_cache :: 1 +EXT_VALIDATION_CACHE_SPEC_VERSION :: 1 +EXT_VALIDATION_CACHE_EXTENSION_NAME :: "VK_EXT_validation_cache" +EXT_descriptor_indexing :: 1 +EXT_DESCRIPTOR_INDEXING_SPEC_VERSION :: 2 +EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME :: "VK_EXT_descriptor_indexing" +EXT_shader_viewport_index_layer :: 1 +EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION :: 1 +EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME :: "VK_EXT_shader_viewport_index_layer" +NV_shading_rate_image :: 1 +NV_SHADING_RATE_IMAGE_SPEC_VERSION :: 3 +NV_SHADING_RATE_IMAGE_EXTENSION_NAME :: "VK_NV_shading_rate_image" +NV_ray_tracing :: 1 +NV_RAY_TRACING_SPEC_VERSION :: 3 +NV_RAY_TRACING_EXTENSION_NAME :: "VK_NV_ray_tracing" +SHADER_UNUSED_KHR :: ~u32(0) +SHADER_UNUSED_NV :: SHADER_UNUSED_KHR +NV_representative_fragment_test :: 1 +NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION :: 2 +NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME :: "VK_NV_representative_fragment_test" +EXT_filter_cubic :: 1 +EXT_FILTER_CUBIC_SPEC_VERSION :: 3 +EXT_FILTER_CUBIC_EXTENSION_NAME :: "VK_EXT_filter_cubic" +QCOM_render_pass_shader_resolve :: 1 +QCOM_RENDER_PASS_SHADER_RESOLVE_SPEC_VERSION :: 4 +QCOM_RENDER_PASS_SHADER_RESOLVE_EXTENSION_NAME :: "VK_QCOM_render_pass_shader_resolve" +QCOM_cooperative_matrix_conversion :: 1 +QCOM_COOPERATIVE_MATRIX_CONVERSION_SPEC_VERSION :: 1 +QCOM_COOPERATIVE_MATRIX_CONVERSION_EXTENSION_NAME :: "VK_QCOM_cooperative_matrix_conversion" +QCOM_elapsed_timer_query :: 1 +QCOM_ELAPSED_TIMER_QUERY_SPEC_VERSION :: 1 +QCOM_ELAPSED_TIMER_QUERY_EXTENSION_NAME :: "VK_QCOM_elapsed_timer_query" +EXT_global_priority :: 1 +EXT_GLOBAL_PRIORITY_SPEC_VERSION :: 2 +EXT_GLOBAL_PRIORITY_EXTENSION_NAME :: "VK_EXT_global_priority" +EXT_external_memory_host :: 1 +EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION :: 1 +EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME :: "VK_EXT_external_memory_host" +AMD_buffer_marker :: 1 +AMD_BUFFER_MARKER_SPEC_VERSION :: 1 +AMD_BUFFER_MARKER_EXTENSION_NAME :: "VK_AMD_buffer_marker" +AMD_pipeline_compiler_control :: 1 +AMD_PIPELINE_COMPILER_CONTROL_SPEC_VERSION :: 1 +AMD_PIPELINE_COMPILER_CONTROL_EXTENSION_NAME :: "VK_AMD_pipeline_compiler_control" +EXT_calibrated_timestamps :: 1 +EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION :: 2 +EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME :: "VK_EXT_calibrated_timestamps" +AMD_shader_core_properties :: 1 +AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION :: 2 +AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME :: "VK_AMD_shader_core_properties" +AMD_memory_overallocation_behavior :: 1 +AMD_MEMORY_OVERALLOCATION_BEHAVIOR_SPEC_VERSION :: 1 +AMD_MEMORY_OVERALLOCATION_BEHAVIOR_EXTENSION_NAME :: "VK_AMD_memory_overallocation_behavior" +EXT_vertex_attribute_divisor :: 1 +EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION :: 3 +EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME :: "VK_EXT_vertex_attribute_divisor" +EXT_pipeline_creation_feedback :: 1 +EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION :: 1 +EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME :: "VK_EXT_pipeline_creation_feedback" +NV_shader_subgroup_partitioned :: 1 +NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION :: 1 +NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME :: "VK_NV_shader_subgroup_partitioned" +NV_compute_shader_derivatives :: 1 +NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION :: 1 +NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME :: "VK_NV_compute_shader_derivatives" +NV_mesh_shader :: 1 +NV_MESH_SHADER_SPEC_VERSION :: 1 +NV_MESH_SHADER_EXTENSION_NAME :: "VK_NV_mesh_shader" +NV_fragment_shader_barycentric :: 1 +NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION :: 1 +NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME :: "VK_NV_fragment_shader_barycentric" +NV_shader_image_footprint :: 1 +NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION :: 2 +NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME :: "VK_NV_shader_image_footprint" +NV_scissor_exclusive :: 1 +NV_SCISSOR_EXCLUSIVE_SPEC_VERSION :: 2 +NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME :: "VK_NV_scissor_exclusive" +NV_device_diagnostic_checkpoints :: 1 +NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION :: 2 +NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME :: "VK_NV_device_diagnostic_checkpoints" +EXT_present_timing :: 1 +EXT_PRESENT_TIMING_SPEC_VERSION :: 3 +EXT_PRESENT_TIMING_EXTENSION_NAME :: "VK_EXT_present_timing" +EXT_pci_bus_info :: 1 +EXT_PCI_BUS_INFO_SPEC_VERSION :: 2 +EXT_PCI_BUS_INFO_EXTENSION_NAME :: "VK_EXT_pci_bus_info" +AMD_display_native_hdr :: 1 +AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION :: 1 +AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME :: "VK_AMD_display_native_hdr" +EXT_fragment_density_map :: 1 +EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION :: 3 +EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME :: "VK_EXT_fragment_density_map" +EXT_scalar_block_layout :: 1 +EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION :: 1 +EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME :: "VK_EXT_scalar_block_layout" +GOOGLE_hlsl_functionality1 :: 1 +GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION :: 1 +GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME :: "VK_GOOGLE_hlsl_functionality1" +GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION :: GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION +GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME :: GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME +GOOGLE_decorate_string :: 1 +GOOGLE_DECORATE_STRING_SPEC_VERSION :: 1 +GOOGLE_DECORATE_STRING_EXTENSION_NAME :: "VK_GOOGLE_decorate_string" +EXT_subgroup_size_control :: 1 +EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION :: 2 +EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME :: "VK_EXT_subgroup_size_control" +AMD_shader_core_properties2 :: 1 +AMD_SHADER_CORE_PROPERTIES_2_SPEC_VERSION :: 1 +AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME :: "VK_AMD_shader_core_properties2" +AMD_device_coherent_memory :: 1 +AMD_DEVICE_COHERENT_MEMORY_SPEC_VERSION :: 1 +AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME :: "VK_AMD_device_coherent_memory" +EXT_shader_image_atomic_int64 :: 1 +EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION :: 1 +EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME :: "VK_EXT_shader_image_atomic_int64" +EXT_memory_budget :: 1 +EXT_MEMORY_BUDGET_SPEC_VERSION :: 1 +EXT_MEMORY_BUDGET_EXTENSION_NAME :: "VK_EXT_memory_budget" +EXT_memory_priority :: 1 +EXT_MEMORY_PRIORITY_SPEC_VERSION :: 1 +EXT_MEMORY_PRIORITY_EXTENSION_NAME :: "VK_EXT_memory_priority" +NV_dedicated_allocation_image_aliasing :: 1 +NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_SPEC_VERSION :: 1 +NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME :: "VK_NV_dedicated_allocation_image_aliasing" +EXT_buffer_device_address :: 1 +EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION :: 2 +EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME :: "VK_EXT_buffer_device_address" +EXT_tooling_info :: 1 +EXT_TOOLING_INFO_SPEC_VERSION :: 1 +EXT_TOOLING_INFO_EXTENSION_NAME :: "VK_EXT_tooling_info" +EXT_separate_stencil_usage :: 1 +EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION :: 1 +EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME :: "VK_EXT_separate_stencil_usage" +EXT_validation_features :: 1 +EXT_VALIDATION_FEATURES_SPEC_VERSION :: 6 +EXT_VALIDATION_FEATURES_EXTENSION_NAME :: "VK_EXT_validation_features" +NV_cooperative_matrix :: 1 +NV_COOPERATIVE_MATRIX_SPEC_VERSION :: 1 +NV_COOPERATIVE_MATRIX_EXTENSION_NAME :: "VK_NV_cooperative_matrix" +NV_coverage_reduction_mode :: 1 +NV_COVERAGE_REDUCTION_MODE_SPEC_VERSION :: 1 +NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME :: "VK_NV_coverage_reduction_mode" +EXT_fragment_shader_interlock :: 1 +EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION :: 1 +EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME :: "VK_EXT_fragment_shader_interlock" +EXT_ycbcr_image_arrays :: 1 +EXT_YCBCR_IMAGE_ARRAYS_SPEC_VERSION :: 1 +EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME :: "VK_EXT_ycbcr_image_arrays" +EXT_provoking_vertex :: 1 +EXT_PROVOKING_VERTEX_SPEC_VERSION :: 1 +EXT_PROVOKING_VERTEX_EXTENSION_NAME :: "VK_EXT_provoking_vertex" +EXT_headless_surface :: 1 +EXT_HEADLESS_SURFACE_SPEC_VERSION :: 1 +EXT_HEADLESS_SURFACE_EXTENSION_NAME :: "VK_EXT_headless_surface" +EXT_line_rasterization :: 1 +EXT_LINE_RASTERIZATION_SPEC_VERSION :: 1 +EXT_LINE_RASTERIZATION_EXTENSION_NAME :: "VK_EXT_line_rasterization" +EXT_shader_atomic_float :: 1 +EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION :: 1 +EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME :: "VK_EXT_shader_atomic_float" +EXT_host_query_reset :: 1 +EXT_HOST_QUERY_RESET_SPEC_VERSION :: 1 +EXT_HOST_QUERY_RESET_EXTENSION_NAME :: "VK_EXT_host_query_reset" +EXT_index_type_uint8 :: 1 +EXT_INDEX_TYPE_UINT8_SPEC_VERSION :: 1 +EXT_INDEX_TYPE_UINT8_EXTENSION_NAME :: "VK_EXT_index_type_uint8" +EXT_extended_dynamic_state :: 1 +EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION :: 1 +EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state" +EXT_host_image_copy :: 1 +EXT_HOST_IMAGE_COPY_SPEC_VERSION :: 1 +EXT_HOST_IMAGE_COPY_EXTENSION_NAME :: "VK_EXT_host_image_copy" +EXT_map_memory_placed :: 1 +EXT_MAP_MEMORY_PLACED_SPEC_VERSION :: 1 +EXT_MAP_MEMORY_PLACED_EXTENSION_NAME :: "VK_EXT_map_memory_placed" +EXT_shader_atomic_float2 :: 1 +EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION :: 1 +EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME :: "VK_EXT_shader_atomic_float2" +EXT_surface_maintenance1 :: 1 +EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION :: 1 +EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME :: "VK_EXT_surface_maintenance1" +EXT_swapchain_maintenance1 :: 1 +EXT_SWAPCHAIN_MAINTENANCE_1_SPEC_VERSION :: 1 +EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME :: "VK_EXT_swapchain_maintenance1" +EXT_shader_demote_to_helper_invocation :: 1 +EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION :: 1 +EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME :: "VK_EXT_shader_demote_to_helper_invocation" +NV_device_generated_commands :: 1 +NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION :: 3 +NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME :: "VK_NV_device_generated_commands" +NV_inherited_viewport_scissor :: 1 +NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION :: 1 +NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME :: "VK_NV_inherited_viewport_scissor" +EXT_texel_buffer_alignment :: 1 +EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION :: 1 +EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME :: "VK_EXT_texel_buffer_alignment" +QCOM_render_pass_transform :: 1 +QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION :: 5 +QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME :: "VK_QCOM_render_pass_transform" +EXT_depth_bias_control :: 1 +EXT_DEPTH_BIAS_CONTROL_SPEC_VERSION :: 1 +EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_bias_control" +EXT_device_memory_report :: 1 +EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION :: 2 +EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME :: "VK_EXT_device_memory_report" +EXT_acquire_drm_display :: 1 +EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION :: 1 +EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME :: "VK_EXT_acquire_drm_display" +EXT_robustness2 :: 1 +EXT_ROBUSTNESS_2_SPEC_VERSION :: 1 +EXT_ROBUSTNESS_2_EXTENSION_NAME :: "VK_EXT_robustness2" +EXT_custom_border_color :: 1 +EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION :: 12 +EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME :: "VK_EXT_custom_border_color" +EXT_texture_compression_astc_3d :: 1 +EXT_TEXTURE_COMPRESSION_ASTC_3D_SPEC_VERSION :: 1 +EXT_TEXTURE_COMPRESSION_ASTC_3D_EXTENSION_NAME :: "VK_EXT_texture_compression_astc_3d" +GOOGLE_user_type :: 1 +GOOGLE_USER_TYPE_SPEC_VERSION :: 1 +GOOGLE_USER_TYPE_EXTENSION_NAME :: "VK_GOOGLE_user_type" +NV_present_barrier :: 1 +NV_PRESENT_BARRIER_SPEC_VERSION :: 1 +NV_PRESENT_BARRIER_EXTENSION_NAME :: "VK_NV_present_barrier" +EXT_private_data :: 1 +EXT_PRIVATE_DATA_SPEC_VERSION :: 1 +EXT_PRIVATE_DATA_EXTENSION_NAME :: "VK_EXT_private_data" +EXT_pipeline_creation_cache_control :: 1 +EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION :: 3 +EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME :: "VK_EXT_pipeline_creation_cache_control" +NV_device_diagnostics_config :: 1 +NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION :: 2 +NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME :: "VK_NV_device_diagnostics_config" +QCOM_render_pass_store_ops :: 1 +QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION :: 2 +QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME :: "VK_QCOM_render_pass_store_ops" +QCOM_queue_perf_hint :: 1 +QCOM_QUEUE_PERF_HINT_SPEC_VERSION :: 1 +QCOM_QUEUE_PERF_HINT_EXTENSION_NAME :: "VK_QCOM_queue_perf_hint" +QCOM_image_processing3 :: 1 +QCOM_IMAGE_PROCESSING_3_SPEC_VERSION :: 1 +QCOM_IMAGE_PROCESSING_3_EXTENSION_NAME :: "VK_QCOM_image_processing3" +QCOM_shader_multiple_wait_queues :: 1 +QCOM_SHADER_MULTIPLE_WAIT_QUEUES_SPEC_VERSION :: 1 +QCOM_SHADER_MULTIPLE_WAIT_QUEUES_EXTENSION_NAME :: "VK_QCOM_shader_multiple_wait_queues" +EXT_shader_split_barrier :: 1 +EXT_SHADER_SPLIT_BARRIER_SPEC_VERSION :: 1 +EXT_SHADER_SPLIT_BARRIER_EXTENSION_NAME :: "VK_EXT_shader_split_barrier" +QCOM_tile_shading :: 1 +QCOM_TILE_SHADING_SPEC_VERSION :: 2 +QCOM_TILE_SHADING_EXTENSION_NAME :: "VK_QCOM_tile_shading" +NV_low_latency :: 1 +NV_LOW_LATENCY_SPEC_VERSION :: 1 +NV_LOW_LATENCY_EXTENSION_NAME :: "VK_NV_low_latency" +EXT_descriptor_buffer :: 1 +EXT_DESCRIPTOR_BUFFER_SPEC_VERSION :: 1 +EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME :: "VK_EXT_descriptor_buffer" +EXT_graphics_pipeline_library :: 1 +EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION :: 1 +EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME :: "VK_EXT_graphics_pipeline_library" +AMD_shader_early_and_late_fragment_tests :: 1 +AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION :: 1 +AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME :: "VK_AMD_shader_early_and_late_fragment_tests" +NV_fragment_shading_rate_enums :: 1 +NV_FRAGMENT_SHADING_RATE_ENUMS_SPEC_VERSION :: 1 +NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME :: "VK_NV_fragment_shading_rate_enums" +NV_ray_tracing_motion_blur :: 1 +NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION :: 1 +NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME :: "VK_NV_ray_tracing_motion_blur" +EXT_ycbcr_2plane_444_formats :: 1 +EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION :: 1 +EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME :: "VK_EXT_ycbcr_2plane_444_formats" +EXT_fragment_density_map2 :: 1 +EXT_FRAGMENT_DENSITY_MAP_2_SPEC_VERSION :: 1 +EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME :: "VK_EXT_fragment_density_map2" +QCOM_rotated_copy_commands :: 1 +QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION :: 2 +QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME :: "VK_QCOM_rotated_copy_commands" +EXT_image_robustness :: 1 +EXT_IMAGE_ROBUSTNESS_SPEC_VERSION :: 1 +EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_image_robustness" +EXT_image_compression_control :: 1 +EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION :: 1 +EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME :: "VK_EXT_image_compression_control" +EXT_attachment_feedback_loop_layout :: 1 +EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_SPEC_VERSION :: 2 +EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME :: "VK_EXT_attachment_feedback_loop_layout" +EXT_4444_formats :: 1 +EXT_4444_FORMATS_SPEC_VERSION :: 1 +EXT_4444_FORMATS_EXTENSION_NAME :: "VK_EXT_4444_formats" +EXT_device_fault :: 1 +EXT_DEVICE_FAULT_SPEC_VERSION :: 2 +EXT_DEVICE_FAULT_EXTENSION_NAME :: "VK_EXT_device_fault" +ARM_rasterization_order_attachment_access :: 1 +ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION :: 1 +ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME :: "VK_ARM_rasterization_order_attachment_access" +EXT_rgba10x6_formats :: 1 +EXT_RGBA10X6_FORMATS_SPEC_VERSION :: 1 +EXT_RGBA10X6_FORMATS_EXTENSION_NAME :: "VK_EXT_rgba10x6_formats" +EXT_vertex_input_dynamic_state :: 1 +EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION :: 2 +EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_vertex_input_dynamic_state" +EXT_physical_device_drm :: 1 +EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION :: 1 +EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME :: "VK_EXT_physical_device_drm" +EXT_device_address_binding_report :: 1 +EXT_DEVICE_ADDRESS_BINDING_REPORT_SPEC_VERSION :: 1 +EXT_DEVICE_ADDRESS_BINDING_REPORT_EXTENSION_NAME :: "VK_EXT_device_address_binding_report" +EXT_depth_clip_control :: 1 +EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION :: 1 +EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_clip_control" +EXT_primitive_topology_list_restart :: 1 +EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION :: 1 +EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME :: "VK_EXT_primitive_topology_list_restart" +EXT_present_mode_fifo_latest_ready :: 1 +EXT_PRESENT_MODE_FIFO_LATEST_READY_SPEC_VERSION :: 1 +EXT_PRESENT_MODE_FIFO_LATEST_READY_EXTENSION_NAME :: "VK_EXT_present_mode_fifo_latest_ready" +NV_external_memory_rdma :: 1 +NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION :: 1 +NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME :: "VK_NV_external_memory_rdma" +EXT_pipeline_properties :: 1 +EXT_PIPELINE_PROPERTIES_SPEC_VERSION :: 1 +EXT_PIPELINE_PROPERTIES_EXTENSION_NAME :: "VK_EXT_pipeline_properties" +EXT_frame_boundary :: 1 +EXT_FRAME_BOUNDARY_SPEC_VERSION :: 1 +EXT_FRAME_BOUNDARY_EXTENSION_NAME :: "VK_EXT_frame_boundary" +EXT_multisampled_render_to_single_sampled :: 1 +EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION :: 1 +EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME :: "VK_EXT_multisampled_render_to_single_sampled" +EXT_extended_dynamic_state2 :: 1 +EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION :: 1 +EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state2" +EXT_color_write_enable :: 1 +EXT_COLOR_WRITE_ENABLE_SPEC_VERSION :: 1 +EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME :: "VK_EXT_color_write_enable" +EXT_primitives_generated_query :: 1 +EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION :: 1 +EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME :: "VK_EXT_primitives_generated_query" +EXT_global_priority_query :: 1 +EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION :: 1 +EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME :: "VK_EXT_global_priority_query" +MAX_GLOBAL_PRIORITY_SIZE_EXT :: MAX_GLOBAL_PRIORITY_SIZE +EXT_image_view_min_lod :: 1 +EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION :: 1 +EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME :: "VK_EXT_image_view_min_lod" +EXT_multi_draw :: 1 +EXT_MULTI_DRAW_SPEC_VERSION :: 1 +EXT_MULTI_DRAW_EXTENSION_NAME :: "VK_EXT_multi_draw" +EXT_image_2d_view_of_3d :: 1 +EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION :: 1 +EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME :: "VK_EXT_image_2d_view_of_3d" +EXT_shader_tile_image :: 1 +EXT_SHADER_TILE_IMAGE_SPEC_VERSION :: 1 +EXT_SHADER_TILE_IMAGE_EXTENSION_NAME :: "VK_EXT_shader_tile_image" +EXT_opacity_micromap :: 1 +EXT_OPACITY_MICROMAP_SPEC_VERSION :: 2 +EXT_OPACITY_MICROMAP_EXTENSION_NAME :: "VK_EXT_opacity_micromap" +EXT_load_store_op_none :: 1 +EXT_LOAD_STORE_OP_NONE_SPEC_VERSION :: 1 +EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME :: "VK_EXT_load_store_op_none" +EXT_border_color_swizzle :: 1 +EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION :: 1 +EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME :: "VK_EXT_border_color_swizzle" +EXT_pageable_device_local_memory :: 1 +EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION :: 1 +EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME :: "VK_EXT_pageable_device_local_memory" +ARM_shader_core_properties :: 1 +ARM_SHADER_CORE_PROPERTIES_SPEC_VERSION :: 1 +ARM_SHADER_CORE_PROPERTIES_EXTENSION_NAME :: "VK_ARM_shader_core_properties" +ARM_scheduling_controls :: 1 +ARM_SCHEDULING_CONTROLS_SPEC_VERSION :: 2 +ARM_SCHEDULING_CONTROLS_EXTENSION_NAME :: "VK_ARM_scheduling_controls" +EXT_image_sliced_view_of_3d :: 1 +EXT_IMAGE_SLICED_VIEW_OF_3D_SPEC_VERSION :: 1 +EXT_IMAGE_SLICED_VIEW_OF_3D_EXTENSION_NAME :: "VK_EXT_image_sliced_view_of_3d" +REMAINING_3D_SLICES_EXT :: ~u32(0) +EXT_depth_clamp_zero_one :: 1 +EXT_DEPTH_CLAMP_ZERO_ONE_SPEC_VERSION :: 1 +EXT_DEPTH_CLAMP_ZERO_ONE_EXTENSION_NAME :: "VK_EXT_depth_clamp_zero_one" +EXT_non_seamless_cube_map :: 1 +EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION :: 1 +EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME :: "VK_EXT_non_seamless_cube_map" +ARM_render_pass_striped :: 1 +ARM_RENDER_PASS_STRIPED_SPEC_VERSION :: 1 +ARM_RENDER_PASS_STRIPED_EXTENSION_NAME :: "VK_ARM_render_pass_striped" +QCOM_fragment_density_map_offset :: 1 +QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION :: 3 +QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME :: "VK_QCOM_fragment_density_map_offset" +NV_copy_memory_indirect :: 1 +NV_COPY_MEMORY_INDIRECT_SPEC_VERSION :: 1 +NV_COPY_MEMORY_INDIRECT_EXTENSION_NAME :: "VK_NV_copy_memory_indirect" +NV_memory_decompression :: 1 +NV_MEMORY_DECOMPRESSION_SPEC_VERSION :: 1 +NV_MEMORY_DECOMPRESSION_EXTENSION_NAME :: "VK_NV_memory_decompression" +NV_device_generated_commands_compute :: 1 +NV_DEVICE_GENERATED_COMMANDS_COMPUTE_SPEC_VERSION :: 2 +NV_DEVICE_GENERATED_COMMANDS_COMPUTE_EXTENSION_NAME :: "VK_NV_device_generated_commands_compute" +NV_ray_tracing_linear_swept_spheres :: 1 +NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_SPEC_VERSION :: 1 +NV_RAY_TRACING_LINEAR_SWEPT_SPHERES_EXTENSION_NAME :: "VK_NV_ray_tracing_linear_swept_spheres" +NV_linear_color_attachment :: 1 +NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION :: 1 +NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME :: "VK_NV_linear_color_attachment" +GOOGLE_surfaceless_query :: 1 +GOOGLE_SURFACELESS_QUERY_SPEC_VERSION :: 2 +GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME :: "VK_GOOGLE_surfaceless_query" +EXT_image_compression_control_swapchain :: 1 +EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION :: 1 +EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME :: "VK_EXT_image_compression_control_swapchain" +QCOM_image_processing :: 1 +QCOM_IMAGE_PROCESSING_SPEC_VERSION :: 1 +QCOM_IMAGE_PROCESSING_EXTENSION_NAME :: "VK_QCOM_image_processing" +EXT_nested_command_buffer :: 1 +EXT_NESTED_COMMAND_BUFFER_SPEC_VERSION :: 1 +EXT_NESTED_COMMAND_BUFFER_EXTENSION_NAME :: "VK_EXT_nested_command_buffer" +EXT_external_memory_acquire_unmodified :: 1 +EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_SPEC_VERSION :: 1 +EXT_EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXTENSION_NAME :: "VK_EXT_external_memory_acquire_unmodified" +EXT_extended_dynamic_state3 :: 1 +EXT_EXTENDED_DYNAMIC_STATE_3_SPEC_VERSION :: 2 +EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME :: "VK_EXT_extended_dynamic_state3" +EXT_subpass_merge_feedback :: 1 +EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION :: 2 +EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME :: "VK_EXT_subpass_merge_feedback" +ARM_tensors :: 1 +ARM_TENSORS_SPEC_VERSION :: 2 +ARM_TENSORS_EXTENSION_NAME :: "VK_ARM_tensors" +EXT_shader_module_identifier :: 1 +MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT :: 32 +EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION :: 1 +EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME :: "VK_EXT_shader_module_identifier" +EXT_rasterization_order_attachment_access :: 1 +EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION :: 1 +EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME :: "VK_EXT_rasterization_order_attachment_access" +NV_optical_flow :: 1 +NV_OPTICAL_FLOW_SPEC_VERSION :: 1 +NV_OPTICAL_FLOW_EXTENSION_NAME :: "VK_NV_optical_flow" +EXT_legacy_dithering :: 1 +EXT_LEGACY_DITHERING_SPEC_VERSION :: 2 +EXT_LEGACY_DITHERING_EXTENSION_NAME :: "VK_EXT_legacy_dithering" +EXT_pipeline_protected_access :: 1 +EXT_PIPELINE_PROTECTED_ACCESS_SPEC_VERSION :: 1 +EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME :: "VK_EXT_pipeline_protected_access" +AMD_anti_lag :: 1 +AMD_ANTI_LAG_SPEC_VERSION :: 1 +AMD_ANTI_LAG_EXTENSION_NAME :: "VK_AMD_anti_lag" +EXT_shader_object :: 1 +EXT_SHADER_OBJECT_SPEC_VERSION :: 1 +EXT_SHADER_OBJECT_EXTENSION_NAME :: "VK_EXT_shader_object" +QCOM_tile_properties :: 1 +QCOM_TILE_PROPERTIES_SPEC_VERSION :: 1 +QCOM_TILE_PROPERTIES_EXTENSION_NAME :: "VK_QCOM_tile_properties" +QCOM_multiview_per_view_viewports :: 1 +QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_SPEC_VERSION :: 1 +QCOM_MULTIVIEW_PER_VIEW_VIEWPORTS_EXTENSION_NAME :: "VK_QCOM_multiview_per_view_viewports" +NV_ray_tracing_invocation_reorder :: 1 +NV_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION :: 1 +NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME :: "VK_NV_ray_tracing_invocation_reorder" +NV_cooperative_vector :: 1 +NV_COOPERATIVE_VECTOR_SPEC_VERSION :: 4 +NV_COOPERATIVE_VECTOR_EXTENSION_NAME :: "VK_NV_cooperative_vector" +NV_extended_sparse_address_space :: 1 +NV_EXTENDED_SPARSE_ADDRESS_SPACE_SPEC_VERSION :: 1 +NV_EXTENDED_SPARSE_ADDRESS_SPACE_EXTENSION_NAME :: "VK_NV_extended_sparse_address_space" +EXT_mutable_descriptor_type :: 1 +EXT_MUTABLE_DESCRIPTOR_TYPE_SPEC_VERSION :: 1 +EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME :: "VK_EXT_mutable_descriptor_type" +EXT_legacy_vertex_attributes :: 1 +EXT_LEGACY_VERTEX_ATTRIBUTES_SPEC_VERSION :: 1 +EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME :: "VK_EXT_legacy_vertex_attributes" +EXT_layer_settings :: 1 +EXT_LAYER_SETTINGS_SPEC_VERSION :: 2 +EXT_LAYER_SETTINGS_EXTENSION_NAME :: "VK_EXT_layer_settings" +ARM_shader_core_builtins :: 1 +ARM_SHADER_CORE_BUILTINS_SPEC_VERSION :: 2 +ARM_SHADER_CORE_BUILTINS_EXTENSION_NAME :: "VK_ARM_shader_core_builtins" +EXT_pipeline_library_group_handles :: 1 +EXT_PIPELINE_LIBRARY_GROUP_HANDLES_SPEC_VERSION :: 1 +EXT_PIPELINE_LIBRARY_GROUP_HANDLES_EXTENSION_NAME :: "VK_EXT_pipeline_library_group_handles" +EXT_dynamic_rendering_unused_attachments :: 1 +EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_SPEC_VERSION :: 1 +EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME :: "VK_EXT_dynamic_rendering_unused_attachments" +NV_low_latency2 :: 1 +NV_LOW_LATENCY_2_SPEC_VERSION :: 2 +NV_LOW_LATENCY_2_EXTENSION_NAME :: "VK_NV_low_latency2" +ARM_data_graph :: 1 +MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM :: 128 +ARM_DATA_GRAPH_SPEC_VERSION :: 1 +ARM_DATA_GRAPH_EXTENSION_NAME :: "VK_ARM_data_graph" +ARM_data_graph_instruction_set_tosa :: 1 +MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM :: 128 +ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_SPEC_VERSION :: 1 +ARM_DATA_GRAPH_INSTRUCTION_SET_TOSA_EXTENSION_NAME :: "VK_ARM_data_graph_instruction_set_tosa" +QCOM_multiview_per_view_render_areas :: 1 +QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_SPEC_VERSION :: 1 +QCOM_MULTIVIEW_PER_VIEW_RENDER_AREAS_EXTENSION_NAME :: "VK_QCOM_multiview_per_view_render_areas" +NV_per_stage_descriptor_set :: 1 +NV_PER_STAGE_DESCRIPTOR_SET_SPEC_VERSION :: 1 +NV_PER_STAGE_DESCRIPTOR_SET_EXTENSION_NAME :: "VK_NV_per_stage_descriptor_set" +QCOM_image_processing2 :: 1 +QCOM_IMAGE_PROCESSING_2_SPEC_VERSION :: 1 +QCOM_IMAGE_PROCESSING_2_EXTENSION_NAME :: "VK_QCOM_image_processing2" +QCOM_filter_cubic_weights :: 1 +QCOM_FILTER_CUBIC_WEIGHTS_SPEC_VERSION :: 1 +QCOM_FILTER_CUBIC_WEIGHTS_EXTENSION_NAME :: "VK_QCOM_filter_cubic_weights" +QCOM_ycbcr_degamma :: 1 +QCOM_YCBCR_DEGAMMA_SPEC_VERSION :: 1 +QCOM_YCBCR_DEGAMMA_EXTENSION_NAME :: "VK_QCOM_ycbcr_degamma" +QCOM_filter_cubic_clamp :: 1 +QCOM_FILTER_CUBIC_CLAMP_SPEC_VERSION :: 1 +QCOM_FILTER_CUBIC_CLAMP_EXTENSION_NAME :: "VK_QCOM_filter_cubic_clamp" +EXT_attachment_feedback_loop_dynamic_state :: 1 +EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_SPEC_VERSION :: 1 +EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME :: "VK_EXT_attachment_feedback_loop_dynamic_state" +NV_descriptor_pool_overallocation :: 1 +NV_DESCRIPTOR_POOL_OVERALLOCATION_SPEC_VERSION :: 1 +NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME :: "VK_NV_descriptor_pool_overallocation" +QCOM_tile_memory_heap :: 1 +QCOM_TILE_MEMORY_HEAP_SPEC_VERSION :: 1 +QCOM_TILE_MEMORY_HEAP_EXTENSION_NAME :: "VK_QCOM_tile_memory_heap" +EXT_memory_decompression :: 1 +EXT_MEMORY_DECOMPRESSION_SPEC_VERSION :: 1 +EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME :: "VK_EXT_memory_decompression" +NV_display_stereo :: 1 +NV_DISPLAY_STEREO_SPEC_VERSION :: 1 +NV_DISPLAY_STEREO_EXTENSION_NAME :: "VK_NV_display_stereo" +NV_raw_access_chains :: 1 +NV_RAW_ACCESS_CHAINS_SPEC_VERSION :: 1 +NV_RAW_ACCESS_CHAINS_EXTENSION_NAME :: "VK_NV_raw_access_chains" +NV_external_compute_queue :: 1 +NV_EXTERNAL_COMPUTE_QUEUE_SPEC_VERSION :: 1 +NV_EXTERNAL_COMPUTE_QUEUE_EXTENSION_NAME :: "VK_NV_external_compute_queue" +NV_command_buffer_inheritance :: 1 +NV_COMMAND_BUFFER_INHERITANCE_SPEC_VERSION :: 1 +NV_COMMAND_BUFFER_INHERITANCE_EXTENSION_NAME :: "VK_NV_command_buffer_inheritance" +NV_shader_atomic_float16_vector :: 1 +NV_SHADER_ATOMIC_FLOAT16_VECTOR_SPEC_VERSION :: 1 +NV_SHADER_ATOMIC_FLOAT16_VECTOR_EXTENSION_NAME :: "VK_NV_shader_atomic_float16_vector" +EXT_shader_replicated_composites :: 1 +EXT_SHADER_REPLICATED_COMPOSITES_SPEC_VERSION :: 1 +EXT_SHADER_REPLICATED_COMPOSITES_EXTENSION_NAME :: "VK_EXT_shader_replicated_composites" +EXT_shader_float8 :: 1 +EXT_SHADER_FLOAT8_SPEC_VERSION :: 1 +EXT_SHADER_FLOAT8_EXTENSION_NAME :: "VK_EXT_shader_float8" +NV_ray_tracing_validation :: 1 +NV_RAY_TRACING_VALIDATION_SPEC_VERSION :: 1 +NV_RAY_TRACING_VALIDATION_EXTENSION_NAME :: "VK_NV_ray_tracing_validation" +NV_cluster_acceleration_structure :: 1 +NV_CLUSTER_ACCELERATION_STRUCTURE_SPEC_VERSION :: 4 +NV_CLUSTER_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_cluster_acceleration_structure" +NV_partitioned_acceleration_structure :: 1 +NV_PARTITIONED_ACCELERATION_STRUCTURE_SPEC_VERSION :: 1 +NV_PARTITIONED_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_NV_partitioned_acceleration_structure" +PARTITIONED_ACCELERATION_STRUCTURE_PARTITION_INDEX_GLOBAL_NV :: ~u32(0) +EXT_device_generated_commands :: 1 +EXT_DEVICE_GENERATED_COMMANDS_SPEC_VERSION :: 1 +EXT_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME :: "VK_EXT_device_generated_commands" +NV_push_constant_bank :: 1 +NV_PUSH_CONSTANT_BANK_SPEC_VERSION :: 1 +NV_PUSH_CONSTANT_BANK_EXTENSION_NAME :: "VK_NV_push_constant_bank" +EXT_ray_tracing_invocation_reorder :: 1 +EXT_RAY_TRACING_INVOCATION_REORDER_SPEC_VERSION :: 2 +EXT_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME :: "VK_EXT_ray_tracing_invocation_reorder" +EXT_depth_clamp_control :: 1 +EXT_DEPTH_CLAMP_CONTROL_SPEC_VERSION :: 1 +EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME :: "VK_EXT_depth_clamp_control" +NV_cooperative_matrix2 :: 1 +NV_COOPERATIVE_MATRIX_2_SPEC_VERSION :: 1 +NV_COOPERATIVE_MATRIX_2_EXTENSION_NAME :: "VK_NV_cooperative_matrix2" +ARM_pipeline_opacity_micromap :: 1 +ARM_PIPELINE_OPACITY_MICROMAP_SPEC_VERSION :: 1 +ARM_PIPELINE_OPACITY_MICROMAP_EXTENSION_NAME :: "VK_ARM_pipeline_opacity_micromap" +ARM_performance_counters_by_region :: 1 +ARM_PERFORMANCE_COUNTERS_BY_REGION_SPEC_VERSION :: 1 +ARM_PERFORMANCE_COUNTERS_BY_REGION_EXTENSION_NAME :: "VK_ARM_performance_counters_by_region" +ARM_shader_instrumentation :: 1 +ARM_SHADER_INSTRUMENTATION_SPEC_VERSION :: 1 +ARM_SHADER_INSTRUMENTATION_EXTENSION_NAME :: "VK_ARM_shader_instrumentation" +EXT_vertex_attribute_robustness :: 1 +EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_SPEC_VERSION :: 1 +EXT_VERTEX_ATTRIBUTE_ROBUSTNESS_EXTENSION_NAME :: "VK_EXT_vertex_attribute_robustness" +ARM_format_pack :: 1 +ARM_FORMAT_PACK_SPEC_VERSION :: 1 +ARM_FORMAT_PACK_EXTENSION_NAME :: "VK_ARM_format_pack" +NV_present_metering :: 1 +NV_PRESENT_METERING_SPEC_VERSION :: 1 +NV_PRESENT_METERING_EXTENSION_NAME :: "VK_NV_present_metering" +EXT_multisampled_render_to_swapchain :: 1 +EXT_MULTISAMPLED_RENDER_TO_SWAPCHAIN_SPEC_VERSION :: 1 +EXT_MULTISAMPLED_RENDER_TO_SWAPCHAIN_EXTENSION_NAME :: "VK_EXT_multisampled_render_to_swapchain" +EXT_fragment_density_map_offset :: 1 +EXT_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION :: 1 +EXT_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME :: "VK_EXT_fragment_density_map_offset" +EXT_zero_initialize_device_memory :: 1 +EXT_ZERO_INITIALIZE_DEVICE_MEMORY_SPEC_VERSION :: 1 +EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME :: "VK_EXT_zero_initialize_device_memory" +EXT_shader_64bit_indexing :: 1 +EXT_SHADER_64BIT_INDEXING_SPEC_VERSION :: 1 +EXT_SHADER_64BIT_INDEXING_EXTENSION_NAME :: "VK_EXT_shader_64bit_indexing" +EXT_custom_resolve :: 1 +EXT_CUSTOM_RESOLVE_SPEC_VERSION :: 1 +EXT_CUSTOM_RESOLVE_EXTENSION_NAME :: "VK_EXT_custom_resolve" +QCOM_data_graph_model :: 1 +DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM :: 3 +QCOM_DATA_GRAPH_MODEL_SPEC_VERSION :: 1 +QCOM_DATA_GRAPH_MODEL_EXTENSION_NAME :: "VK_QCOM_data_graph_model" +ARM_data_graph_optical_flow :: 1 +ARM_DATA_GRAPH_OPTICAL_FLOW_SPEC_VERSION :: 1 +ARM_DATA_GRAPH_OPTICAL_FLOW_EXTENSION_NAME :: "VK_ARM_data_graph_optical_flow" +EXT_shader_long_vector :: 1 +EXT_SHADER_LONG_VECTOR_SPEC_VERSION :: 1 +EXT_SHADER_LONG_VECTOR_EXTENSION_NAME :: "VK_EXT_shader_long_vector" +EXT_shader_uniform_buffer_unsized_array :: 1 +EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_SPEC_VERSION :: 1 +EXT_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_EXTENSION_NAME :: "VK_EXT_shader_uniform_buffer_unsized_array" +NV_compute_occupancy_priority :: 1 +NV_COMPUTE_OCCUPANCY_PRIORITY_SPEC_VERSION :: 1 +NV_COMPUTE_OCCUPANCY_PRIORITY_EXTENSION_NAME :: "VK_NV_compute_occupancy_priority" +COMPUTE_OCCUPANCY_PRIORITY_LOW_NV :: 25 +COMPUTE_OCCUPANCY_PRIORITY_NORMAL_NV :: 50 +COMPUTE_OCCUPANCY_PRIORITY_HIGH_NV :: 75 +EXT_shader_subgroup_partitioned :: 1 +EXT_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION :: 1 +EXT_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME :: "VK_EXT_shader_subgroup_partitioned" +ARM_data_graph_neural_accelerator_statistics :: 1 +ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_SPEC_VERSION :: 1 +ARM_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_EXTENSION_NAME :: "VK_ARM_data_graph_neural_accelerator_statistics" +EXT_primitive_restart_index :: 1 +EXT_PRIMITIVE_RESTART_INDEX_SPEC_VERSION :: 1 +EXT_PRIMITIVE_RESTART_INDEX_EXTENSION_NAME :: "VK_EXT_primitive_restart_index" +NV_cooperative_matrix_decode_vector :: 1 +NV_COOPERATIVE_MATRIX_DECODE_VECTOR_SPEC_VERSION :: 1 +NV_COOPERATIVE_MATRIX_DECODE_VECTOR_EXTENSION_NAME :: "VK_NV_cooperative_matrix_decode_vector" +KHR_acceleration_structure :: 1 +KHR_ACCELERATION_STRUCTURE_SPEC_VERSION :: 13 +KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME :: "VK_KHR_acceleration_structure" +KHR_ray_tracing_pipeline :: 1 +KHR_RAY_TRACING_PIPELINE_SPEC_VERSION :: 1 +KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME :: "VK_KHR_ray_tracing_pipeline" +KHR_ray_query :: 1 +KHR_RAY_QUERY_SPEC_VERSION :: 1 +KHR_RAY_QUERY_EXTENSION_NAME :: "VK_KHR_ray_query" +EXT_mesh_shader :: 1 +EXT_MESH_SHADER_SPEC_VERSION :: 1 +EXT_MESH_SHADER_EXTENSION_NAME :: "VK_EXT_mesh_shader" +KHR_win32_surface :: 1 +KHR_WIN32_SURFACE_SPEC_VERSION :: 6 +KHR_WIN32_SURFACE_EXTENSION_NAME :: "VK_KHR_win32_surface" +KHR_external_memory_win32 :: 1 +KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION :: 1 +KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME :: "VK_KHR_external_memory_win32" +KHR_win32_keyed_mutex :: 1 +KHR_WIN32_KEYED_MUTEX_SPEC_VERSION :: 1 +KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME :: "VK_KHR_win32_keyed_mutex" +KHR_external_semaphore_win32 :: 1 +KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION :: 1 +KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME :: "VK_KHR_external_semaphore_win32" +KHR_external_fence_win32 :: 1 +KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION :: 1 +KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME :: "VK_KHR_external_fence_win32" +NV_external_memory_win32 :: 1 +NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION :: 1 +NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME :: "VK_NV_external_memory_win32" +NV_win32_keyed_mutex :: 1 +NV_WIN32_KEYED_MUTEX_SPEC_VERSION :: 2 +NV_WIN32_KEYED_MUTEX_EXTENSION_NAME :: "VK_NV_win32_keyed_mutex" +EXT_full_screen_exclusive :: 1 +EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION :: 4 +EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME :: "VK_EXT_full_screen_exclusive" +NV_acquire_winrt_display :: 1 +NV_ACQUIRE_WINRT_DISPLAY_SPEC_VERSION :: 1 +NV_ACQUIRE_WINRT_DISPLAY_EXTENSION_NAME :: "VK_NV_acquire_winrt_display" +EXT_metal_surface :: 1 +EXT_METAL_SURFACE_SPEC_VERSION :: 1 +EXT_METAL_SURFACE_EXTENSION_NAME :: "VK_EXT_metal_surface" +EXT_metal_objects :: 1 +EXT_METAL_OBJECTS_SPEC_VERSION :: 2 +EXT_METAL_OBJECTS_EXTENSION_NAME :: "VK_EXT_metal_objects" +EXT_external_memory_metal :: 1 +EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION :: 1 +EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME :: "VK_EXT_external_memory_metal" +KHR_wayland_surface :: 1 +KHR_WAYLAND_SURFACE_SPEC_VERSION :: 6 +KHR_WAYLAND_SURFACE_EXTENSION_NAME :: "VK_KHR_wayland_surface" +KHR_xlib_surface :: 1 +KHR_XLIB_SURFACE_SPEC_VERSION :: 6 +KHR_XLIB_SURFACE_EXTENSION_NAME :: "VK_KHR_xlib_surface" +KHR_xcb_surface :: 1 +KHR_XCB_SURFACE_SPEC_VERSION :: 6 +KHR_XCB_SURFACE_EXTENSION_NAME :: "VK_KHR_xcb_surface" +KHR_portability_subset :: 1 +KHR_PORTABILITY_SUBSET_SPEC_VERSION :: 1 +KHR_PORTABILITY_SUBSET_EXTENSION_NAME :: "VK_KHR_portability_subset" +AMDX_shader_enqueue :: 1 +AMDX_SHADER_ENQUEUE_SPEC_VERSION :: 2 +AMDX_SHADER_ENQUEUE_EXTENSION_NAME :: "VK_AMDX_shader_enqueue" +NV_cuda_kernel_launch :: 1 +NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION :: 2 +NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME :: "VK_NV_cuda_kernel_launch" +NV_displacement_micromap :: 1 +NV_DISPLACEMENT_MICROMAP_SPEC_VERSION :: 2 +NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME :: "VK_NV_displacement_micromap" +AMDX_dense_geometry_format :: 1 +AMDX_DENSE_GEOMETRY_FORMAT_SPEC_VERSION :: 1 +AMDX_DENSE_GEOMETRY_FORMAT_EXTENSION_NAME :: "VK_AMDX_dense_geometry_format" // Handles types -Instance :: distinct Handle -PhysicalDevice :: distinct Handle -Device :: distinct Handle -Queue :: distinct Handle -CommandBuffer :: distinct Handle -Buffer :: distinct NonDispatchableHandle -Image :: distinct NonDispatchableHandle +Instance :: distinct Handle +PhysicalDevice :: distinct Handle +Device :: distinct Handle +Queue :: distinct Handle +CommandBuffer :: distinct Handle +ExternalComputeQueueNV :: distinct Handle Semaphore :: distinct NonDispatchableHandle Fence :: distinct NonDispatchableHandle DeviceMemory :: distinct NonDispatchableHandle -Event :: distinct NonDispatchableHandle +Buffer :: distinct NonDispatchableHandle +Image :: distinct NonDispatchableHandle QueryPool :: distinct NonDispatchableHandle -BufferView :: distinct NonDispatchableHandle ImageView :: distinct NonDispatchableHandle +CommandPool :: distinct NonDispatchableHandle +RenderPass :: distinct NonDispatchableHandle +Framebuffer :: distinct NonDispatchableHandle +Event :: distinct NonDispatchableHandle +BufferView :: distinct NonDispatchableHandle ShaderModule :: distinct NonDispatchableHandle PipelineCache :: distinct NonDispatchableHandle -PipelineLayout :: distinct NonDispatchableHandle Pipeline :: distinct NonDispatchableHandle -RenderPass :: distinct NonDispatchableHandle +PipelineLayout :: distinct NonDispatchableHandle DescriptorSetLayout :: distinct NonDispatchableHandle Sampler :: distinct NonDispatchableHandle DescriptorSet :: distinct NonDispatchableHandle DescriptorPool :: distinct NonDispatchableHandle -Framebuffer :: distinct NonDispatchableHandle -CommandPool :: distinct NonDispatchableHandle -SamplerYcbcrConversion :: distinct NonDispatchableHandle DescriptorUpdateTemplate :: distinct NonDispatchableHandle +SamplerYcbcrConversion :: distinct NonDispatchableHandle PrivateDataSlot :: distinct NonDispatchableHandle SurfaceKHR :: distinct NonDispatchableHandle SwapchainKHR :: distinct NonDispatchableHandle @@ -1240,22 +1530,27 @@ DisplayModeKHR :: distinct NonDispatchableHandle VideoSessionKHR :: distinct NonDispatchableHandle VideoSessionParametersKHR :: distinct NonDispatchableHandle DeferredOperationKHR :: distinct NonDispatchableHandle +AccelerationStructureKHR :: distinct NonDispatchableHandle PipelineBinaryKHR :: distinct NonDispatchableHandle DebugReportCallbackEXT :: distinct NonDispatchableHandle CuModuleNVX :: distinct NonDispatchableHandle CuFunctionNVX :: distinct NonDispatchableHandle DebugUtilsMessengerEXT :: distinct NonDispatchableHandle +GpaSessionAMD :: distinct NonDispatchableHandle +TensorARM :: distinct NonDispatchableHandle ValidationCacheEXT :: distinct NonDispatchableHandle AccelerationStructureNV :: distinct NonDispatchableHandle PerformanceConfigurationINTEL :: distinct NonDispatchableHandle IndirectCommandsLayoutNV :: distinct NonDispatchableHandle -CudaModuleNV :: distinct NonDispatchableHandle -CudaFunctionNV :: distinct NonDispatchableHandle -AccelerationStructureKHR :: distinct NonDispatchableHandle MicromapEXT :: distinct NonDispatchableHandle +TensorViewARM :: distinct NonDispatchableHandle OpticalFlowSessionNV :: distinct NonDispatchableHandle ShaderEXT :: distinct NonDispatchableHandle +DataGraphPipelineSessionARM :: distinct NonDispatchableHandle IndirectExecutionSetEXT :: distinct NonDispatchableHandle IndirectCommandsLayoutEXT :: distinct NonDispatchableHandle +ShaderInstrumentationARM :: distinct NonDispatchableHandle +CudaModuleNV :: distinct NonDispatchableHandle +CudaFunctionNV :: distinct NonDispatchableHandle diff --git a/vendor/vulkan/enums.odin b/vendor/vulkan/enums.odin index 418c7c8b1..8e85924de 100644 --- a/vendor/vulkan/enums.odin +++ b/vendor/vulkan/enums.odin @@ -1,6 +1,3 @@ -// -// Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h" -// package vulkan import "core:c" @@ -36,12 +33,17 @@ AccelerationStructureMotionInstanceTypeNV :: enum c.int { SRT_MOTION = 2, } +AccelerationStructureSerializedBlockTypeKHR :: enum c.int { + OPACITY_MICROMAP = 0, +} + AccelerationStructureTypeKHR :: enum c.int { - TOP_LEVEL = 0, - BOTTOM_LEVEL = 1, - GENERIC = 2, - TOP_LEVEL_NV = TOP_LEVEL, - BOTTOM_LEVEL_NV = BOTTOM_LEVEL, + TOP_LEVEL = 0, + BOTTOM_LEVEL = 1, + GENERIC = 2, + OPACITY_MICROMAP = 1000623000, + TOP_LEVEL_NV = TOP_LEVEL, + BOTTOM_LEVEL_NV = BOTTOM_LEVEL, } AccessFlags :: distinct bit_set[AccessFlag; Flags] @@ -72,13 +74,13 @@ AccessFlag :: enum Flags { ACCELERATION_STRUCTURE_WRITE_KHR = 22, FRAGMENT_DENSITY_MAP_READ_EXT = 24, FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR = 23, - COMMAND_PREPROCESS_READ_NV = 17, - COMMAND_PREPROCESS_WRITE_NV = 18, + COMMAND_PREPROCESS_READ_EXT = 17, + COMMAND_PREPROCESS_WRITE_EXT = 18, SHADING_RATE_IMAGE_READ_NV = FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR, ACCELERATION_STRUCTURE_READ_NV = ACCELERATION_STRUCTURE_READ_KHR, ACCELERATION_STRUCTURE_WRITE_NV = ACCELERATION_STRUCTURE_WRITE_KHR, - COMMAND_PREPROCESS_READ_EXT = COMMAND_PREPROCESS_READ_NV, - COMMAND_PREPROCESS_WRITE_EXT = COMMAND_PREPROCESS_WRITE_NV, + COMMAND_PREPROCESS_READ_NV = COMMAND_PREPROCESS_READ_EXT, + COMMAND_PREPROCESS_WRITE_NV = COMMAND_PREPROCESS_WRITE_EXT, } AccessFlags_NONE :: AccessFlags{} @@ -88,6 +90,23 @@ AcquireProfilingLockFlagsKHR :: distinct bit_set[AcquireProfilingLockFlagKHR; Fl AcquireProfilingLockFlagKHR :: enum Flags { } +AddressCommandFlagsKHR :: distinct bit_set[AddressCommandFlagKHR; Flags] +AddressCommandFlagKHR :: enum Flags { + PROTECTED = 0, + FULLY_BOUND = 1, + STORAGE_BUFFER_USAGE = 2, + UNKNOWN_STORAGE_BUFFER_USAGE = 3, + TRANSFORM_FEEDBACK_BUFFER_USAGE = 4, + UNKNOWN_TRANSFORM_FEEDBACK_BUFFER_USAGE = 5, +} + +AddressCopyFlagsKHR :: distinct bit_set[AddressCopyFlagKHR; Flags] +AddressCopyFlagKHR :: enum Flags { + DEVICE_LOCAL = 0, + SPARSE = 1, + PROTECTED = 2, +} + AntiLagModeAMD :: enum c.int { DRIVER_CONTROL = 0, ON = 1, @@ -101,7 +120,9 @@ AntiLagStageAMD :: enum c.int { AttachmentDescriptionFlags :: distinct bit_set[AttachmentDescriptionFlag; Flags] AttachmentDescriptionFlag :: enum Flags { - MAY_ALIAS = 0, + MAY_ALIAS = 0, + RESOLVE_SKIP_TRANSFER_FUNCTION_KHR = 1, + RESOLVE_ENABLE_TRANSFER_FUNCTION_KHR = 2, } AttachmentLoadOp :: enum c.int { @@ -200,8 +221,8 @@ BlendOverlapEXT :: enum c.int { } BlockMatchWindowCompareModeQCOM :: enum c.int { - BLOCK_MATCH_WINDOW_COMPARE_MODE_MIN_QCOM = 0, - BLOCK_MATCH_WINDOW_COMPARE_MODE_MAX_QCOM = 1, + MIN = 0, + MAX = 1, } BorderColor :: enum c.int { @@ -246,6 +267,7 @@ BufferUsageFlag :: enum Flags { TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT = 12, CONDITIONAL_RENDERING_EXT = 9, EXECUTION_GRAPH_SCRATCH_AMDX = 25, + DESCRIPTOR_HEAP_EXT = 28, ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR = 19, ACCELERATION_STRUCTURE_STORAGE_KHR = 20, SHADER_BINDING_TABLE_KHR = 10, @@ -256,6 +278,7 @@ BufferUsageFlag :: enum Flags { PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_EXT = 26, MICROMAP_BUILD_INPUT_READ_ONLY_EXT = 23, MICROMAP_STORAGE_EXT = 24, + TILE_MEMORY_QCOM = 27, RAY_TRACING_NV = SHADER_BINDING_TABLE_KHR, SHADER_DEVICE_ADDRESS_EXT = SHADER_DEVICE_ADDRESS, SHADER_DEVICE_ADDRESS_KHR = SHADER_DEVICE_ADDRESS, @@ -269,16 +292,20 @@ BuildAccelerationStructureFlagKHR :: enum Flags { PREFER_FAST_BUILD = 3, LOW_MEMORY = 4, MOTION_NV = 5, - ALLOW_OPACITY_MICROMAP_UPDATE_EXT = 6, - ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = 7, ALLOW_OPACITY_MICROMAP_DATA_UPDATE_EXT = 8, ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV = 9, ALLOW_DATA_ACCESS = 11, + ALLOW_CLUSTER_OPACITY_MICROMAPS_NV = 12, + ALLOW_OPACITY_MICROMAP_UPDATE = 6, + ALLOW_DISABLE_OPACITY_MICROMAPS = 7, + MICROMAP_LOSSY = 10, ALLOW_UPDATE_NV = ALLOW_UPDATE, ALLOW_COMPACTION_NV = ALLOW_COMPACTION, PREFER_FAST_TRACE_NV = PREFER_FAST_TRACE, PREFER_FAST_BUILD_NV = PREFER_FAST_BUILD, LOW_MEMORY_NV = LOW_MEMORY, + ALLOW_OPACITY_MICROMAP_UPDATE_EXT = ALLOW_OPACITY_MICROMAP_UPDATE, + ALLOW_DISABLE_OPACITY_MICROMAPS_EXT = ALLOW_DISABLE_OPACITY_MICROMAPS, } BuildAccelerationStructureModeKHR :: enum c.int { @@ -314,6 +341,9 @@ ClusterAccelerationStructureAddressResolutionFlagNV :: enum Flags { INDIRECTED_SRC_INFOS_COUNT = 5, } +ClusterAccelerationStructureAddressResolutionFlagsNV_NONE :: ClusterAccelerationStructureAddressResolutionFlagsNV{} + + ClusterAccelerationStructureClusterFlagsNV :: distinct bit_set[ClusterAccelerationStructureClusterFlagNV; Flags] ClusterAccelerationStructureClusterFlagNV :: enum Flags { ALLOW_DISABLE_OPACITY_MICROMAPS = 0, @@ -345,6 +375,7 @@ ClusterAccelerationStructureOpTypeNV :: enum c.int { BUILD_TRIANGLE_CLUSTER = 2, BUILD_TRIANGLE_CLUSTER_TEMPLATE = 3, INSTANTIATE_TRIANGLE_CLUSTER = 4, + GET_CLUSTER_TEMPLATE_INDICES = 5, } ClusterAccelerationStructureTypeNV :: enum c.int { @@ -451,10 +482,11 @@ ComponentTypeKHR :: enum c.int { UINT16 = 8, UINT32 = 9, UINT64 = 10, + BFLOAT16 = 1000141000, SINT8_PACKED_NV = 1000491000, UINT8_PACKED_NV = 1000491001, - FLOAT_E4M3_NV = 1000491002, - FLOAT_E5M2_NV = 1000491003, + FLOAT8_E4M3_EXT = 1000491002, + FLOAT8_E5M2_EXT = 1000491003, FLOAT16_NV = FLOAT16, FLOAT32_NV = FLOAT32, FLOAT64_NV = FLOAT64, @@ -466,6 +498,8 @@ ComponentTypeKHR :: enum c.int { UINT16_NV = UINT16, UINT32_NV = UINT32, UINT64_NV = UINT64, + FLOAT_E4M3_NV = FLOAT8_E4M3_EXT, + FLOAT_E5M2_NV = FLOAT8_E5M2_EXT, } CompositeAlphaFlagsKHR :: distinct bit_set[CompositeAlphaFlagKHR; Flags] @@ -476,6 +510,10 @@ CompositeAlphaFlagKHR :: enum Flags { INHERIT = 3, } +CompressedTriangleFormatAMDX :: enum c.int { + COMPRESSED_TRIANGLE_FORMAT_DGF1_AMDX = 0, +} + ConditionalRenderingFlagsEXT :: distinct bit_set[ConditionalRenderingFlagEXT; Flags] ConditionalRenderingFlagEXT :: enum Flags { INVERTED = 0, @@ -523,10 +561,10 @@ CoverageReductionModeNV :: enum c.int { } CubicFilterWeightsQCOM :: enum c.int { - CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM = 0, - CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM = 1, - CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM = 2, - CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM = 3, + CATMULL_ROM = 0, + ZERO_TANGENT_CARDINAL = 1, + B_SPLINE = 2, + MITCHELL_NETRAVALI = 3, } CullModeFlags :: distinct bit_set[CullModeFlag; Flags] @@ -539,6 +577,97 @@ CullModeFlags_NONE :: CullModeFlags{} CullModeFlags_FRONT_AND_BACK :: CullModeFlags{.FRONT, .BACK} +DataGraphModelCacheTypeQCOM :: enum c.int { + GENERIC_BINARY = 0, +} + +DataGraphOpticalFlowCreateFlagsARM :: distinct bit_set[DataGraphOpticalFlowCreateFlagARM; Flags] +DataGraphOpticalFlowCreateFlagARM :: enum Flags { + ENABLE_HINT = 0, + ENABLE_COST = 1, + RESERVED_30 = 30, +} + +DataGraphOpticalFlowExecuteFlagsARM :: distinct bit_set[DataGraphOpticalFlowExecuteFlagARM; Flags] +DataGraphOpticalFlowExecuteFlagARM :: enum Flags { + DISABLE_TEMPORAL_HINTS = 0, + INPUT_UNCHANGED = 1, + REFERENCE_UNCHANGED = 2, + INPUT_IS_PREVIOUS_REFERENCE = 3, + REFERENCE_IS_PREVIOUS_INPUT = 4, +} + +DataGraphOpticalFlowGridSizeFlagsARM :: distinct bit_set[DataGraphOpticalFlowGridSizeFlagARM; Flags] +DataGraphOpticalFlowGridSizeFlagARM :: enum Flags { + _1X1 = 0, + _2X2 = 1, + _4X4 = 2, + _8X8 = 3, +} + +DataGraphOpticalFlowGridSizeFlagsARM_UNKNOWN :: DataGraphOpticalFlowGridSizeFlagsARM{} + + +DataGraphOpticalFlowImageUsageFlagsARM :: distinct bit_set[DataGraphOpticalFlowImageUsageFlagARM; Flags] +DataGraphOpticalFlowImageUsageFlagARM :: enum Flags { + INPUT = 0, + OUTPUT = 1, + HINT = 2, + COST = 3, +} + +DataGraphOpticalFlowImageUsageFlagsARM_UNKNOWN :: DataGraphOpticalFlowImageUsageFlagsARM{} + + +DataGraphOpticalFlowPerformanceLevelARM :: enum c.int { + UNKNOWN = 0, + SLOW = 1, + MEDIUM = 2, + FAST = 3, +} + +DataGraphPipelineNodeConnectionTypeARM :: enum c.int { + OPTICAL_FLOW_INPUT = 1000631000, + OPTICAL_FLOW_REFERENCE = 1000631001, + OPTICAL_FLOW_HINT = 1000631002, + OPTICAL_FLOW_FLOW_VECTOR = 1000631003, + OPTICAL_FLOW_COST = 1000631004, +} + +DataGraphPipelineNodeTypeARM :: enum c.int { + OPTICAL_FLOW = 1000631000, +} + +DataGraphPipelinePropertyARM :: enum c.int { + CREATION_LOG = 0, + IDENTIFIER = 1, + NEURAL_ACCELERATOR_DEBUG_DATABASE = 1000676000, + NEURAL_ACCELERATOR_STATISTICS_INFO = 1000676001, +} + +DataGraphPipelineSessionBindPointARM :: enum c.int { + TRANSIENT = 0, + OPTICAL_FLOW_CACHE = 1000631001, + NEURAL_ACCELERATOR_STATISTICS = 1000676000, +} + +DataGraphPipelineSessionBindPointTypeARM :: enum c.int { + MEMORY = 0, +} + +DataGraphTOSALevelARM :: enum c.int { + NONE = 0, + _8K = 1, +} + +DataGraphTOSAQualityFlagsARM :: distinct bit_set[DataGraphTOSAQualityFlagARM; Flags] +DataGraphTOSAQualityFlagARM :: enum Flags { + ACCELERATED = 0, + CONFORMANT = 1, + EXPERIMENTAL = 2, + DEPRECATED = 3, +} + DebugReportFlagsEXT :: distinct bit_set[DebugReportFlagEXT; Flags] DebugReportFlagEXT :: enum Flags { INFORMATION = 0, @@ -612,6 +741,11 @@ DebugUtilsMessageTypeFlagEXT :: enum Flags { DEVICE_ADDRESS_BINDING = 3, } +DefaultVertexAttributeValueKHR :: enum c.int { + ZERO_ZERO_ZERO_ZERO = 0, + ZERO_ZERO_ZERO_ONE = 1, +} + DependencyFlags :: distinct bit_set[DependencyFlag; Flags] DependencyFlag :: enum Flags { BY_REGION = 0, @@ -619,6 +753,7 @@ DependencyFlag :: enum Flags { VIEW_LOCAL = 1, FEEDBACK_LOOP_EXT = 3, QUEUE_FAMILY_OWNERSHIP_TRANSFER_USE_ALL_STAGES_KHR = 5, + ASYMMETRIC_EVENT_KHR = 6, VIEW_LOCAL_KHR = VIEW_LOCAL, DEVICE_GROUP_KHR = DEVICE_GROUP, } @@ -646,6 +781,20 @@ DescriptorBindingFlag :: enum Flags { VARIABLE_DESCRIPTOR_COUNT_EXT = VARIABLE_DESCRIPTOR_COUNT, } +DescriptorMappingSourceEXT :: enum c.int { + HEAP_WITH_CONSTANT_OFFSET = 0, + HEAP_WITH_PUSH_INDEX = 1, + HEAP_WITH_INDIRECT_INDEX = 2, + HEAP_WITH_INDIRECT_INDEX_ARRAY = 3, + RESOURCE_HEAP_DATA = 4, + PUSH_DATA = 5, + PUSH_ADDRESS = 6, + INDIRECT_ADDRESS = 7, + HEAP_WITH_SHADER_RECORD_INDEX = 8, + SHADER_RECORD_DATA = 9, + SHADER_RECORD_ADDRESS = 10, +} + DescriptorPoolCreateFlags :: distinct bit_set[DescriptorPoolCreateFlag; Flags] DescriptorPoolCreateFlag :: enum Flags { FREE_DESCRIPTOR_SET = 0, @@ -688,6 +837,7 @@ DescriptorType :: enum c.int { ACCELERATION_STRUCTURE_NV = 1000165000, SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000, BLOCK_MATCH_IMAGE_QCOM = 1000440001, + TENSOR_ARM = 1000460000, MUTABLE_EXT = 1000351000, PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000, INLINE_UNIFORM_BLOCK_EXT = INLINE_UNIFORM_BLOCK, @@ -723,18 +873,35 @@ DeviceEventTypeEXT :: enum c.int { DISPLAY_HOTPLUG = 0, } -DeviceFaultAddressTypeEXT :: enum c.int { - NONE = 0, - READ_INVALID = 1, - WRITE_INVALID = 2, - EXECUTE_INVALID = 3, - INSTRUCTION_POINTER_UNKNOWN = 4, - INSTRUCTION_POINTER_INVALID = 5, - INSTRUCTION_POINTER_FAULT = 6, +DeviceFaultAddressTypeKHR :: enum c.int { + NONE = 0, + READ_INVALID = 1, + WRITE_INVALID = 2, + EXECUTE_INVALID = 3, + INSTRUCTION_POINTER_UNKNOWN = 4, + INSTRUCTION_POINTER_INVALID = 5, + INSTRUCTION_POINTER_FAULT = 6, + READ_INVALID_EXT = READ_INVALID, + WRITE_INVALID_EXT = WRITE_INVALID, + EXECUTE_INVALID_EXT = EXECUTE_INVALID, + INSTRUCTION_POINTER_UNKNOWN_EXT = INSTRUCTION_POINTER_UNKNOWN, + INSTRUCTION_POINTER_INVALID_EXT = INSTRUCTION_POINTER_INVALID, + INSTRUCTION_POINTER_FAULT_EXT = INSTRUCTION_POINTER_FAULT, } -DeviceFaultVendorBinaryHeaderVersionEXT :: enum c.int { - ONE = 1, +DeviceFaultFlagsKHR :: distinct bit_set[DeviceFaultFlagKHR; Flags] +DeviceFaultFlagKHR :: enum Flags { + FLAG_DEVICE_LOST = 0, + FLAG_MEMORY_ADDRESS = 1, + FLAG_INSTRUCTION_ADDRESS = 2, + FLAG_VENDOR = 3, + FLAG_WATCHDOG_TIMEOUT = 4, + FLAG_OVERFLOW = 5, +} + +DeviceFaultVendorBinaryHeaderVersionKHR :: enum c.int { + ONE = 1, + ONE_EXT = ONE, } DeviceGroupPresentModeFlagsKHR :: distinct bit_set[DeviceGroupPresentModeFlagKHR; Flags] @@ -755,7 +922,8 @@ DeviceMemoryReportEventTypeEXT :: enum c.int { DeviceQueueCreateFlags :: distinct bit_set[DeviceQueueCreateFlag; Flags] DeviceQueueCreateFlag :: enum Flags { - PROTECTED = 0, + PROTECTED = 0, + INTERNALLY_SYNCHRONIZED_KHR = 2, } DirectDriverLoadingModeLUNARG :: enum c.int { @@ -827,6 +995,9 @@ DriverId :: enum c.int { IMAGINATION_OPEN_SOURCE_MESA = 25, MESA_HONEYKRISP = 26, VULKAN_SC_EMULATION_ON_VULKAN = 27, + MESA_KOSMICKRISP = 28, + MESA_GFXSTREAM = 29, + APE_SOFT = 30, AMD_PROPRIETARY_KHR = AMD_PROPRIETARY, AMD_OPEN_SOURCE_KHR = AMD_OPEN_SOURCE, MESA_RADV_KHR = MESA_RADV, @@ -1002,6 +1173,7 @@ ExternalMemoryHandleTypeFlag :: enum Flags { HOST_MAPPED_FOREIGN_MEMORY_EXT = 8, ZIRCON_VMO_FUCHSIA = 11, RDMA_ADDRESS_NV = 12, + OH_NATIVE_BUFFER_OHOS = 15, SCREEN_BUFFER_QNX = 14, MTLBUFFER_EXT = 16, MTLTEXTURE_EXT = 17, @@ -1315,7 +1487,55 @@ Format :: enum c.int { PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005, PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006, PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007, + ASTC_3x3x3_UNORM_BLOCK_EXT = 1000288000, + ASTC_3x3x3_SRGB_BLOCK_EXT = 1000288001, + ASTC_3x3x3_SFLOAT_BLOCK_EXT = 1000288002, + ASTC_4x3x3_UNORM_BLOCK_EXT = 1000288003, + ASTC_4x3x3_SRGB_BLOCK_EXT = 1000288004, + ASTC_4x3x3_SFLOAT_BLOCK_EXT = 1000288005, + ASTC_4x4x3_UNORM_BLOCK_EXT = 1000288006, + ASTC_4x4x3_SRGB_BLOCK_EXT = 1000288007, + ASTC_4x4x3_SFLOAT_BLOCK_EXT = 1000288008, + ASTC_4x4x4_UNORM_BLOCK_EXT = 1000288009, + ASTC_4x4x4_SRGB_BLOCK_EXT = 1000288010, + ASTC_4x4x4_SFLOAT_BLOCK_EXT = 1000288011, + ASTC_5x4x4_UNORM_BLOCK_EXT = 1000288012, + ASTC_5x4x4_SRGB_BLOCK_EXT = 1000288013, + ASTC_5x4x4_SFLOAT_BLOCK_EXT = 1000288014, + ASTC_5x5x4_UNORM_BLOCK_EXT = 1000288015, + ASTC_5x5x4_SRGB_BLOCK_EXT = 1000288016, + ASTC_5x5x4_SFLOAT_BLOCK_EXT = 1000288017, + ASTC_5x5x5_UNORM_BLOCK_EXT = 1000288018, + ASTC_5x5x5_SRGB_BLOCK_EXT = 1000288019, + ASTC_5x5x5_SFLOAT_BLOCK_EXT = 1000288020, + ASTC_6x5x5_UNORM_BLOCK_EXT = 1000288021, + ASTC_6x5x5_SRGB_BLOCK_EXT = 1000288022, + ASTC_6x5x5_SFLOAT_BLOCK_EXT = 1000288023, + ASTC_6x6x5_UNORM_BLOCK_EXT = 1000288024, + ASTC_6x6x5_SRGB_BLOCK_EXT = 1000288025, + ASTC_6x6x5_SFLOAT_BLOCK_EXT = 1000288026, + ASTC_6x6x6_UNORM_BLOCK_EXT = 1000288027, + ASTC_6x6x6_SRGB_BLOCK_EXT = 1000288028, + ASTC_6x6x6_SFLOAT_BLOCK_EXT = 1000288029, + R8_BOOL_ARM = 1000460000, + R16_SFLOAT_FPENCODING_BFLOAT16_ARM = 1000460001, + R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM = 1000460002, + R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM = 1000460003, R16G16_SFIXED5_NV = 1000464000, + R10X6_UINT_PACK16_ARM = 1000609000, + R10X6G10X6_UINT_2PACK16_ARM = 1000609001, + R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM = 1000609002, + R12X4_UINT_PACK16_ARM = 1000609003, + R12X4G12X4_UINT_2PACK16_ARM = 1000609004, + R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM = 1000609005, + R14X2_UINT_PACK16_ARM = 1000609006, + R14X2G14X2_UINT_2PACK16_ARM = 1000609007, + R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM = 1000609008, + R14X2_UNORM_PACK16_ARM = 1000609009, + R14X2G14X2_UNORM_2PACK16_ARM = 1000609010, + R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM = 1000609011, + G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM = 1000609012, + G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM = 1000609013, ASTC_4x4_SFLOAT_BLOCK_EXT = ASTC_4x4_SFLOAT_BLOCK, ASTC_5x4_SFLOAT_BLOCK_EXT = ASTC_5x4_SFLOAT_BLOCK, ASTC_5x5_SFLOAT_BLOCK_EXT = ASTC_5x5_SFLOAT_BLOCK, @@ -1486,23 +1706,115 @@ GeometryInstanceFlagKHR :: enum Flags { TRIANGLE_FLIP_FACING = 1, FORCE_OPAQUE = 2, FORCE_NO_OPAQUE = 3, - FORCE_OPACITY_MICROMAP_2_STATE_EXT = 4, - DISABLE_OPACITY_MICROMAPS_EXT = 5, + FORCE_OPACITY_MICROMAP_2_STATE = 4, + DISABLE_OPACITY_MICROMAPS = 5, TRIANGLE_FRONT_COUNTERCLOCKWISE = TRIANGLE_FLIP_FACING, TRIANGLE_CULL_DISABLE_NV = TRIANGLE_FACING_CULL_DISABLE, TRIANGLE_FRONT_COUNTERCLOCKWISE_NV = TRIANGLE_FRONT_COUNTERCLOCKWISE, FORCE_OPAQUE_NV = FORCE_OPAQUE, FORCE_NO_OPAQUE_NV = FORCE_NO_OPAQUE, + FORCE_OPACITY_MICROMAP_2_STATE_EXT = FORCE_OPACITY_MICROMAP_2_STATE, + DISABLE_OPACITY_MICROMAPS_EXT = DISABLE_OPACITY_MICROMAPS, } GeometryTypeKHR :: enum c.int { - TRIANGLES = 0, - AABBS = 1, - INSTANCES = 2, - SPHERES_NV = 1000429004, - LINEAR_SWEPT_SPHERES_NV = 1000429005, - TRIANGLES_NV = TRIANGLES, - AABBS_NV = AABBS, + TRIANGLES = 0, + AABBS = 1, + INSTANCES = 2, + SPHERES_NV = 1000429004, + LINEAR_SWEPT_SPHERES_NV = 1000429005, + DENSE_GEOMETRY_FORMAT_TRIANGLES_AMDX = 1000478000, + MICROMAP = 1000623000, + TRIANGLES_NV = TRIANGLES, + AABBS_NV = AABBS, +} + +GpaDeviceClockModeAMD :: enum c.int { + DEFAULT = 0, + QUERY = 1, + PROFILING = 2, + MIN_MEMORY = 3, + MIN_ENGINE = 4, + PEAK = 5, +} + +GpaPerfBlockAMD :: enum c.int { + CPF = 0, + IA = 1, + VGT = 2, + PA = 3, + SC = 4, + SPI = 5, + SQ = 6, + SX = 7, + TA = 8, + TD = 9, + TCP = 10, + TCC = 11, + TCA = 12, + DB = 13, + CB = 14, + GDS = 15, + SRBM = 16, + GRBM = 17, + GRBM_SE = 18, + RLC = 19, + DMA = 20, + MC = 21, + CPG = 22, + CPC = 23, + WD = 24, + TCS = 25, + ATC = 26, + ATC_L2 = 27, + MC_VM_L2 = 28, + EA = 29, + RPB = 30, + RMI = 31, + UMCCH = 32, + GE = 33, + GL1A = 34, + GL1C = 35, + GL1CG = 36, + GL2A = 37, + GL2C = 38, + CHA = 39, + CHC = 40, + CHCG = 41, + GUS = 42, + GCR = 43, + PH = 44, + UTCL1 = 45, + GE_DIST = 46, + GE_SE = 47, + DF_MALL = 48, + SQ_WGP = 49, + PC = 50, + GL1XA = 51, + GL1XC = 52, + WGS = 53, + EACPWD = 54, + EASE = 55, + RLCUSER = 56, + GE1 = GE, + RLCLOCAL = RLCUSER, +} + +GpaSampleTypeAMD :: enum c.int { + CUMULATIVE = 0, + TRACE = 1, + TIMING = 2, +} + +GpaSqShaderStageFlagsAMD :: distinct bit_set[GpaSqShaderStageFlagAMD; Flags] +GpaSqShaderStageFlagAMD :: enum Flags { + PS = 0, + VS = 1, + GS = 2, + ES = 3, + HS = 4, + LS = 5, + CS = 6, } GraphicsPipelineLibraryFlagsEXT :: distinct bit_set[GraphicsPipelineLibraryFlagEXT; Flags] @@ -1596,19 +1908,22 @@ ImageCreateFlag :: enum Flags { PROTECTED = 11, DISJOINT = 9, CORNER_SAMPLED_NV = 13, + DESCRIPTOR_HEAP_CAPTURE_REPLAY_EXT = 16, SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_EXT = 12, SUBSAMPLED_EXT = 14, - DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT = 16, MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT = 18, D2_VIEW_COMPATIBLE_EXT = 17, - FRAGMENT_DENSITY_MAP_OFFSET_QCOM = 15, VIDEO_PROFILE_INDEPENDENT_KHR = 20, + FRAGMENT_DENSITY_MAP_OFFSET_EXT = 15, + ALIAS_SINGLE_LAYER_DESCRIPTOR_KHR = 22, SPLIT_INSTANCE_BIND_REGIONS_KHR = SPLIT_INSTANCE_BIND_REGIONS, D2_ARRAY_COMPATIBLE_KHR = D2_ARRAY_COMPATIBLE, BLOCK_TEXEL_VIEW_COMPATIBLE_KHR = BLOCK_TEXEL_VIEW_COMPATIBLE, EXTENDED_USAGE_KHR = EXTENDED_USAGE, DISJOINT_KHR = DISJOINT, ALIAS_KHR = ALIAS, + DESCRIPTOR_BUFFER_CAPTURE_REPLAY_EXT = DESCRIPTOR_HEAP_CAPTURE_REPLAY_EXT, + FRAGMENT_DENSITY_MAP_OFFSET_QCOM = FRAGMENT_DENSITY_MAP_OFFSET_EXT, } ImageLayout :: enum c.int { @@ -1641,7 +1956,9 @@ ImageLayout :: enum c.int { VIDEO_ENCODE_SRC_KHR = 1000299001, VIDEO_ENCODE_DPB_KHR = 1000299002, ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT = 1000339000, + TENSOR_ALIASING_ARM = 1000460000, VIDEO_ENCODE_QUANTIZATION_MAP_KHR = 1000553000, + ZERO_INITIALIZED_EXT = 1000620000, DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, SHADING_RATE_OPTIMAL_NV = FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, @@ -1689,6 +2006,8 @@ ImageUsageFlag :: enum Flags { INVOCATION_MASK_HUAWEI = 18, SAMPLE_WEIGHT_QCOM = 20, SAMPLE_BLOCK_MATCH_QCOM = 21, + TENSOR_ALIASING_ARM = 23, + TILE_MEMORY_QCOM = 27, VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_KHR = 25, VIDEO_ENCODE_EMPHASIS_MAP_KHR = 26, SHADING_RATE_IMAGE_NV = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR, @@ -1752,6 +2071,8 @@ IndirectCommandsTokenTypeEXT :: enum c.int { DRAW_INDEXED_COUNT = 7, DRAW_COUNT = 8, DISPATCH = 9, + PUSH_DATA = 1000135000, + PUSH_DATA_SEQUENCE_INDEX = 1000135001, DRAW_MESH_TASKS_NV = 1000202002, DRAW_MESH_TASKS_COUNT_NV = 1000202003, DRAW_MESH_TASKS = 1000328000, @@ -1768,6 +2089,7 @@ IndirectCommandsTokenTypeNV :: enum c.int { DRAW_INDEXED = 5, DRAW = 6, DRAW_TASKS = 7, + PUSH_DATA = 1000135000, DRAW_MESH_TASKS = 1000328000, PIPELINE = 1000428003, DISPATCH = 1000428004, @@ -1862,6 +2184,7 @@ MemoryAllocateFlag :: enum Flags { DEVICE_MASK = 0, DEVICE_ADDRESS = 1, DEVICE_ADDRESS_CAPTURE_REPLAY = 2, + ZERO_INITIALIZE_EXT = 3, DEVICE_MASK_KHR = DEVICE_MASK, DEVICE_ADDRESS_KHR = DEVICE_ADDRESS, DEVICE_ADDRESS_CAPTURE_REPLAY_KHR = DEVICE_ADDRESS_CAPTURE_REPLAY, @@ -1871,6 +2194,7 @@ MemoryHeapFlags :: distinct bit_set[MemoryHeapFlag; Flags] MemoryHeapFlag :: enum Flags { DEVICE_LOCAL = 0, MULTI_INSTANCE = 1, + TILE_MEMORY_QCOM = 3, MULTI_INSTANCE_KHR = MULTI_INSTANCE, } @@ -1913,6 +2237,12 @@ MicromapTypeEXT :: enum c.int { DISPLACEMENT_MICROMAP_NV = 1000397000, } +NeuralAcceleratorStatisticsModeARM :: enum c.int { + DISABLED = 0, + STATISTICS0 = 1, + STATISTICS1 = 2, +} + ObjectType :: enum c.int { UNKNOWN = 0, INSTANCE = 1, @@ -1940,8 +2270,8 @@ ObjectType :: enum c.int { DESCRIPTOR_SET = 23, FRAMEBUFFER = 24, COMMAND_POOL = 25, - SAMPLER_YCBCR_CONVERSION = 1000156000, DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + SAMPLER_YCBCR_CONVERSION = 1000156000, PRIVATE_DATA_SLOT = 1000295000, SURFACE_KHR = 1000000000, SWAPCHAIN_KHR = 1000001000, @@ -1953,6 +2283,7 @@ ObjectType :: enum c.int { CU_MODULE_NVX = 1000029000, CU_FUNCTION_NVX = 1000029001, DEBUG_UTILS_MESSENGER_EXT = 1000128000, + GPA_SESSION_AMD = 1000133000, ACCELERATION_STRUCTURE_KHR = 1000150000, VALIDATION_CACHE_EXT = 1000160000, ACCELERATION_STRUCTURE_NV = 1000165000, @@ -1963,27 +2294,38 @@ ObjectType :: enum c.int { CUDA_FUNCTION_NV = 1000307001, BUFFER_COLLECTION_FUCHSIA = 1000366000, MICROMAP_EXT = 1000396000, + TENSOR_ARM = 1000460000, + TENSOR_VIEW_ARM = 1000460001, OPTICAL_FLOW_SESSION_NV = 1000464000, SHADER_EXT = 1000482000, PIPELINE_BINARY_KHR = 1000483000, + DATA_GRAPH_PIPELINE_SESSION_ARM = 1000507000, + EXTERNAL_COMPUTE_QUEUE_NV = 1000556000, INDIRECT_COMMANDS_LAYOUT_EXT = 1000572000, INDIRECT_EXECUTION_SET_EXT = 1000572001, + SHADER_INSTRUMENTATION_ARM = 1000607000, DESCRIPTOR_UPDATE_TEMPLATE_KHR = DESCRIPTOR_UPDATE_TEMPLATE, SAMPLER_YCBCR_CONVERSION_KHR = SAMPLER_YCBCR_CONVERSION, PRIVATE_DATA_SLOT_EXT = PRIVATE_DATA_SLOT, } -OpacityMicromapFormatEXT :: enum c.int { - _2_STATE = 1, - _4_STATE = 2, +OpacityMicromapFormatKHR :: enum c.int { + _2_STATE = 1, + _4_STATE = 2, + _2_STATE_EXT = _2_STATE, + _4_STATE_EXT = _4_STATE, } -OpacityMicromapSpecialIndexEXT :: enum c.int { +OpacityMicromapSpecialIndexKHR :: enum c.int { FULLY_TRANSPARENT = -1, FULLY_OPAQUE = -2, FULLY_UNKNOWN_TRANSPARENT = -3, FULLY_UNKNOWN_OPAQUE = -4, CLUSTER_GEOMETRY_DISABLE_OPACITY_MICROMAP_NV = -5, + FULLY_TRANSPARENT_EXT = FULLY_TRANSPARENT, + FULLY_OPAQUE_EXT = FULLY_OPAQUE, + FULLY_UNKNOWN_TRANSPARENT_EXT = FULLY_UNKNOWN_TRANSPARENT, + FULLY_UNKNOWN_OPAQUE_EXT = FULLY_UNKNOWN_OPAQUE, } OpticalFlowExecuteFlagsNV :: distinct bit_set[OpticalFlowExecuteFlagNV; Flags] @@ -2062,6 +2404,12 @@ PartitionedAccelerationStructureOpTypeNV :: enum c.int { WRITE_PARTITION_TRANSLATION = 2, } +PastPresentationTimingFlagsEXT :: distinct bit_set[PastPresentationTimingFlagEXT; Flags] +PastPresentationTimingFlagEXT :: enum Flags { + ALLOW_PARTIAL_RESULTS = 0, + ALLOW_OUT_OF_ORDER_RESULTS = 1, +} + PeerMemoryFeatureFlags :: distinct bit_set[PeerMemoryFeatureFlag; Flags] PeerMemoryFeatureFlag :: enum Flags { COPY_SRC = 0, @@ -2074,6 +2422,13 @@ PeerMemoryFeatureFlag :: enum Flags { GENERIC_DST_KHR = GENERIC_DST, } +PerfHintTypeQCOM :: enum c.int { + DEFAULT = 0, + FREQUENCY_MIN = 1, + FREQUENCY_MAX = 2, + FREQUENCY_SCALED = 3, +} + PerformanceConfigurationTypeINTEL :: enum c.int { PERFORMANCE_CONFIGURATION_TYPE_COMMAND_QUEUE_METRICS_DISCOVERY_ACTIVATED_INTEL = 0, } @@ -2134,6 +2489,19 @@ PerformanceValueTypeINTEL :: enum c.int { PERFORMANCE_VALUE_TYPE_STRING_INTEL = 4, } +PhysicalDeviceDataGraphOperationTypeARM :: enum c.int { + SPIRV_EXTENDED_INSTRUCTION_SET = 0, + NEURAL_MODEL_QCOM = 1000629000, + BUILTIN_MODEL_QCOM = 1000629001, + OPTICAL_FLOW = 1000631000, +} + +PhysicalDeviceDataGraphProcessingEngineTypeARM :: enum c.int { + DEFAULT = 0, + NEURAL_QCOM = 1000629000, + COMPUTE_QCOM = 1000629001, +} + PhysicalDeviceLayeredApiKHR :: enum c.int { VULKAN = 0, D3D12 = 1, @@ -2156,6 +2524,7 @@ PipelineBindPoint :: enum c.int { EXECUTION_GRAPH_AMDX = 1000134000, RAY_TRACING_KHR = 1000165000, SUBPASS_SHADING_HUAWEI = 1000369003, + DATA_GRAPH_ARM = 1000507000, RAY_TRACING_NV = RAY_TRACING_KHR, } @@ -2167,7 +2536,8 @@ PipelineCacheCreateFlag :: enum Flags { } PipelineCacheHeaderVersion :: enum c.int { - ONE = 1, + ONE = 1, + DATA_GRAPH_QCOM = 1000629000, } PipelineColorBlendStateCreateFlags :: distinct bit_set[PipelineColorBlendStateCreateFlag; Flags] @@ -2185,8 +2555,8 @@ PipelineCreateFlag :: enum Flags { DISABLE_OPTIMIZATION = 0, ALLOW_DERIVATIVES = 1, DERIVATIVE = 2, - VIEW_INDEX_FROM_DEVICE_INDEX = 3, DISPATCH_BASE = 4, + VIEW_INDEX_FROM_DEVICE_INDEX = 3, FAIL_ON_PIPELINE_COMPILE_REQUIRED = 8, EARLY_RETURN_ON_FAILURE = 9, NO_PROTECTED_ACCESS = 27, @@ -2211,14 +2581,15 @@ PipelineCreateFlag :: enum Flags { RAY_TRACING_ALLOW_MOTION_NV = 20, COLOR_ATTACHMENT_FEEDBACK_LOOP_EXT = 25, DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_EXT = 26, - RAY_TRACING_OPACITY_MICROMAP_EXT = 24, RAY_TRACING_DISPLACEMENT_MICROMAP_NV = 28, + RAY_TRACING_OPACITY_MICROMAP_KHR = 24, VIEW_INDEX_FROM_DEVICE_INDEX_KHR = VIEW_INDEX_FROM_DEVICE_INDEX, DISPATCH_BASE_KHR = DISPATCH_BASE, PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_EXT = RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_EXT, PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_KHR = RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_KHR, FAIL_ON_PIPELINE_COMPILE_REQUIRED_EXT = FAIL_ON_PIPELINE_COMPILE_REQUIRED, EARLY_RETURN_ON_FAILURE_EXT = EARLY_RETURN_ON_FAILURE, + RAY_TRACING_OPACITY_MICROMAP_EXT = RAY_TRACING_OPACITY_MICROMAP_KHR, NO_PROTECTED_ACCESS_EXT = NO_PROTECTED_ACCESS, PROTECTED_ACCESS_ONLY_EXT = PROTECTED_ACCESS_ONLY, } @@ -2251,6 +2622,7 @@ PipelineExecutableStatisticFormatKHR :: enum c.int { PipelineLayoutCreateFlags :: distinct bit_set[PipelineLayoutCreateFlag; Flags] PipelineLayoutCreateFlag :: enum Flags { INDEPENDENT_SETS_EXT = 1, + NO_TASK_SHADER_KHR = 2, } PipelineRobustnessBufferBehavior :: enum c.int { @@ -2308,15 +2680,15 @@ PipelineStageFlag :: enum Flags { RAY_TRACING_SHADER_KHR = 21, FRAGMENT_DENSITY_PROCESS_EXT = 23, FRAGMENT_SHADING_RATE_ATTACHMENT_KHR = 22, - COMMAND_PREPROCESS_NV = 17, TASK_SHADER_EXT = 19, MESH_SHADER_EXT = 20, + COMMAND_PREPROCESS_EXT = 17, SHADING_RATE_IMAGE_NV = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR, RAY_TRACING_SHADER_NV = RAY_TRACING_SHADER_KHR, ACCELERATION_STRUCTURE_BUILD_NV = ACCELERATION_STRUCTURE_BUILD_KHR, TASK_SHADER_NV = TASK_SHADER_EXT, MESH_SHADER_NV = MESH_SHADER_EXT, - COMMAND_PREPROCESS_EXT = COMMAND_PREPROCESS_NV, + COMMAND_PREPROCESS_NV = COMMAND_PREPROCESS_EXT, } PipelineStageFlags_NONE :: PipelineStageFlags{} @@ -2336,11 +2708,14 @@ PolygonMode :: enum c.int { FILL_RECTANGLE_NV = 1000153000, } -PresentGravityFlagsEXT :: distinct bit_set[PresentGravityFlagEXT; Flags] -PresentGravityFlagEXT :: enum Flags { - MIN = 0, - MAX = 1, - CENTERED = 2, +PresentGravityFlagsKHR :: distinct bit_set[PresentGravityFlagKHR; Flags] +PresentGravityFlagKHR :: enum Flags { + MIN = 0, + MAX = 1, + CENTERED = 2, + MIN_EXT = MIN, + MAX_EXT = MAX, + CENTERED_EXT = CENTERED, } PresentModeKHR :: enum c.int { @@ -2350,14 +2725,32 @@ PresentModeKHR :: enum c.int { FIFO_RELAXED = 3, SHARED_DEMAND_REFRESH = 1000111000, SHARED_CONTINUOUS_REFRESH = 1000111001, - FIFO_LATEST_READY_EXT = 1000361000, + FIFO_LATEST_READY = 1000361000, + FIFO_LATEST_READY_EXT = FIFO_LATEST_READY, } -PresentScalingFlagsEXT :: distinct bit_set[PresentScalingFlagEXT; Flags] -PresentScalingFlagEXT :: enum Flags { - ONE_TO_ONE = 0, - ASPECT_RATIO_STRETCH = 1, - STRETCH = 2, +PresentScalingFlagsKHR :: distinct bit_set[PresentScalingFlagKHR; Flags] +PresentScalingFlagKHR :: enum Flags { + ONE_TO_ONE = 0, + ASPECT_RATIO_STRETCH = 1, + STRETCH = 2, + ONE_TO_ONE_EXT = ONE_TO_ONE, + ASPECT_RATIO_STRETCH_EXT = ASPECT_RATIO_STRETCH, + STRETCH_EXT = STRETCH, +} + +PresentStageFlagsEXT :: distinct bit_set[PresentStageFlagEXT; Flags] +PresentStageFlagEXT :: enum Flags { + QUEUE_OPERATIONS_END = 0, + REQUEST_DEQUEUED = 1, + IMAGE_FIRST_PIXEL_OUT = 2, + IMAGE_FIRST_PIXEL_VISIBLE = 3, +} + +PresentTimingInfoFlagsEXT :: distinct bit_set[PresentTimingInfoFlagEXT; Flags] +PresentTimingInfoFlagEXT :: enum Flags { + PRESENT_AT_RELATIVE_TIME = 0, + PRESENT_AT_NEAREST_REFRESH_CYCLE = 1, } PrimitiveTopology :: enum c.int { @@ -2402,6 +2795,11 @@ QueryPipelineStatisticFlag :: enum Flags { CLUSTER_CULLING_SHADER_INVOCATIONS_HUAWEI = 13, } +QueryPoolCreateFlags :: distinct bit_set[QueryPoolCreateFlag; Flags] +QueryPoolCreateFlag :: enum Flags { + RESET_KHR = 0, +} + QueryPoolSamplingModeINTEL :: enum c.int { QUERY_POOL_SAMPLING_MODE_MANUAL_INTEL = 0, } @@ -2432,6 +2830,7 @@ QueryType :: enum c.int { ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000150000, ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150001, ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, + TIME_ELAPSED_QCOM = 1000173000, PERFORMANCE_QUERY_INTEL = 1000210000, VIDEO_ENCODE_FEEDBACK_KHR = 1000299000, MESH_PRIMITIVES_GENERATED_EXT = 1000328000, @@ -2452,6 +2851,7 @@ QueueFlag :: enum Flags { VIDEO_DECODE_KHR = 5, VIDEO_ENCODE_KHR = 6, OPTICAL_FLOW_NV = 8, + DATA_GRAPH_ARM = 10, } QueueGlobalPriority :: enum c.int { @@ -2474,9 +2874,10 @@ RasterizationOrderAMD :: enum c.int { RELAXED = 1, } -RayTracingInvocationReorderModeNV :: enum c.int { - NONE = 0, - REORDER = 1, +RayTracingInvocationReorderModeEXT :: enum c.int { + NONE = 0, + REORDER = 1, + REORDER_NV = REORDER, } RayTracingLssIndexingModeNV :: enum c.int { @@ -2500,20 +2901,38 @@ RayTracingShaderGroupTypeKHR :: enum c.int { RenderPassCreateFlags :: distinct bit_set[RenderPassCreateFlag; Flags] RenderPassCreateFlag :: enum Flags { - TRANSFORM_QCOM = 1, + TRANSFORM_QCOM = 1, + PER_LAYER_FRAGMENT_DENSITY_VALVE = 2, +} + +RenderingAttachmentFlagsKHR :: distinct bit_set[RenderingAttachmentFlagKHR; Flags] +RenderingAttachmentFlagKHR :: enum Flags { + INPUT_ATTACHMENT_FEEDBACK = 0, + RESOLVE_SKIP_TRANSFER_FUNCTION = 1, + RESOLVE_ENABLE_TRANSFER_FUNCTION = 2, } RenderingFlags :: distinct bit_set[RenderingFlag; Flags] RenderingFlag :: enum Flags { - CONTENTS_SECONDARY_COMMAND_BUFFERS = 0, - SUSPENDING = 1, - RESUMING = 2, - ENABLE_LEGACY_DITHERING_EXT = 3, - CONTENTS_INLINE_KHR = 4, - CONTENTS_SECONDARY_COMMAND_BUFFERS_KHR = CONTENTS_SECONDARY_COMMAND_BUFFERS, - SUSPENDING_KHR = SUSPENDING, - RESUMING_KHR = RESUMING, - CONTENTS_INLINE_EXT = CONTENTS_INLINE_KHR, + CONTENTS_SECONDARY_COMMAND_BUFFERS = 0, + SUSPENDING = 1, + RESUMING = 2, + ENABLE_LEGACY_DITHERING_EXT = 3, + CONTENTS_INLINE_KHR = 4, + PER_LAYER_FRAGMENT_DENSITY_VALVE = 5, + FRAGMENT_REGION_EXT = 6, + CUSTOM_RESOLVE_EXT = 7, + LOCAL_READ_CONCURRENT_ACCESS_CONTROL_KHR = 8, + CONTENTS_SECONDARY_COMMAND_BUFFERS_KHR = CONTENTS_SECONDARY_COMMAND_BUFFERS, + SUSPENDING_KHR = SUSPENDING, + RESUMING_KHR = RESUMING, + CONTENTS_INLINE_EXT = CONTENTS_INLINE_KHR, +} + +ResolveImageFlagsKHR :: distinct bit_set[ResolveImageFlagKHR; Flags] +ResolveImageFlagKHR :: enum Flags { + SKIP_TRANSFER_FUNCTION = 0, + ENABLE_TRANSFER_FUNCTION = 1, } ResolveModeFlags :: distinct bit_set[ResolveModeFlag; Flags] @@ -2523,6 +2942,7 @@ ResolveModeFlag :: enum Flags { MIN = 2, MAX = 3, EXTERNAL_FORMAT_DOWNSAMPLE_ANDROID = 4, + CUSTOM_EXT = 5, SAMPLE_ZERO_KHR = SAMPLE_ZERO, AVERAGE_KHR = AVERAGE, MIN_KHR = MIN, @@ -2552,10 +2972,11 @@ Result :: enum c.int { ERROR_FORMAT_NOT_SUPPORTED = -11, ERROR_FRAGMENTED_POOL = -12, ERROR_UNKNOWN = -13, + ERROR_VALIDATION_FAILED = -1000011001, ERROR_OUT_OF_POOL_MEMORY = -1000069000, ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, - ERROR_FRAGMENTATION = -1000161000, ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + ERROR_FRAGMENTATION = -1000161000, PIPELINE_COMPILE_REQUIRED = 1000297000, ERROR_NOT_PERMITTED = -1000174001, ERROR_SURFACE_LOST_KHR = -1000000000, @@ -2563,7 +2984,6 @@ Result :: enum c.int { SUBOPTIMAL_KHR = 1000001003, ERROR_OUT_OF_DATE_KHR = -1000001004, ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, - ERROR_VALIDATION_FAILED_EXT = -1000011001, ERROR_INVALID_SHADER_NV = -1000012000, ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR = -1000023000, ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR = -1000023001, @@ -2572,6 +2992,7 @@ Result :: enum c.int { ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR = -1000023004, ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR = -1000023005, ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000, + ERROR_PRESENT_TIMING_QUEUE_FULL_EXT = -1000208000, ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, THREAD_IDLE_KHR = 1000268000, THREAD_DONE_KHR = 1000268001, @@ -2582,6 +3003,7 @@ Result :: enum c.int { INCOMPATIBLE_SHADER_BINARY_EXT = 1000482000, PIPELINE_BINARY_MISSING_KHR = 1000483000, ERROR_NOT_ENOUGH_SPACE_KHR = -1000483000, + ERROR_VALIDATION_FAILED_EXT = ERROR_VALIDATION_FAILED, ERROR_OUT_OF_POOL_MEMORY_KHR = ERROR_OUT_OF_POOL_MEMORY, ERROR_INVALID_EXTERNAL_HANDLE_KHR = ERROR_INVALID_EXTERNAL_HANDLE, ERROR_FRAGMENTATION_EXT = ERROR_FRAGMENTATION, @@ -2699,14 +3121,19 @@ ShaderCorePropertiesFlagAMD :: enum Flags { ShaderCreateFlagsEXT :: distinct bit_set[ShaderCreateFlagEXT; Flags] ShaderCreateFlagEXT :: enum Flags { - LINK_STAGE = 0, - ALLOW_VARYING_SUBGROUP_SIZE = 1, - REQUIRE_FULL_SUBGROUPS = 2, - NO_TASK_SHADER = 3, - DISPATCH_BASE = 4, - FRAGMENT_SHADING_RATE_ATTACHMENT = 5, - FRAGMENT_DENSITY_MAP_ATTACHMENT = 6, - INDIRECT_BINDABLE = 7, + LINK_STAGE = 0, + DESCRIPTOR_HEAP = 10, + INSTRUMENT_SHADER_ARM = 11, + ALLOW_VARYING_SUBGROUP_SIZE = 1, + REQUIRE_FULL_SUBGROUPS = 2, + NO_TASK_SHADER = 3, + DISPATCH_BASE = 4, + FRAGMENT_SHADING_RATE_ATTACHMENT = 5, + FRAGMENT_DENSITY_MAP_ATTACHMENT = 6, + INDIRECT_BINDABLE = 7, + OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX = 12, + _64_INDEXING = 15, + INDEPENDENT_SETS_KHR = 18, } ShaderFloatControlsIndependence :: enum c.int { @@ -2795,6 +3222,24 @@ SparseMemoryBindFlag :: enum Flags { METADATA = 0, } +SpirvResourceTypeFlagsEXT :: distinct bit_set[SpirvResourceTypeFlagEXT; Flags] +SpirvResourceTypeFlagEXT :: enum Flags { + SAMPLER = 0, + SAMPLED_IMAGE = 1, + READ_ONLY_IMAGE = 2, + READ_WRITE_IMAGE = 3, + COMBINED_SAMPLED_IMAGE = 4, + UNIFORM_BUFFER = 5, + READ_ONLY_STORAGE_BUFFER = 6, + READ_WRITE_STORAGE_BUFFER = 7, + ACCELERATION_STRUCTURE = 8, + TENSOR_ARM = 9, + _MAX = 31, // Needed for the *_ALL bit set +} + +SpirvResourceTypeFlagsEXT_ALL :: SpirvResourceTypeFlagsEXT{.SAMPLER, .SAMPLED_IMAGE, .READ_ONLY_IMAGE, .READ_WRITE_IMAGE, .COMBINED_SAMPLED_IMAGE, .UNIFORM_BUFFER, .READ_ONLY_STORAGE_BUFFER, .READ_WRITE_STORAGE_BUFFER, .ACCELERATION_STRUCTURE, .TENSOR_ARM, SpirvResourceTypeFlagEXT(10), SpirvResourceTypeFlagEXT(11), SpirvResourceTypeFlagEXT(12), SpirvResourceTypeFlagEXT(13), SpirvResourceTypeFlagEXT(14), SpirvResourceTypeFlagEXT(15), SpirvResourceTypeFlagEXT(16), SpirvResourceTypeFlagEXT(17), SpirvResourceTypeFlagEXT(18), SpirvResourceTypeFlagEXT(19), SpirvResourceTypeFlagEXT(20), SpirvResourceTypeFlagEXT(21), SpirvResourceTypeFlagEXT(22), SpirvResourceTypeFlagEXT(23), SpirvResourceTypeFlagEXT(24), SpirvResourceTypeFlagEXT(25), SpirvResourceTypeFlagEXT(26), SpirvResourceTypeFlagEXT(27), SpirvResourceTypeFlagEXT(28), SpirvResourceTypeFlagEXT(29), SpirvResourceTypeFlagEXT(30)} + + StencilFaceFlags :: distinct bit_set[StencilFaceFlag; Flags] StencilFaceFlag :: enum Flags { FRONT = 0, @@ -2816,1242 +3261,1505 @@ StencilOp :: enum c.int { } StructureType :: enum c.int { - APPLICATION_INFO = 0, - INSTANCE_CREATE_INFO = 1, - DEVICE_QUEUE_CREATE_INFO = 2, - DEVICE_CREATE_INFO = 3, - SUBMIT_INFO = 4, - MEMORY_ALLOCATE_INFO = 5, - MAPPED_MEMORY_RANGE = 6, - BIND_SPARSE_INFO = 7, - FENCE_CREATE_INFO = 8, - SEMAPHORE_CREATE_INFO = 9, - EVENT_CREATE_INFO = 10, - QUERY_POOL_CREATE_INFO = 11, - BUFFER_CREATE_INFO = 12, - BUFFER_VIEW_CREATE_INFO = 13, - IMAGE_CREATE_INFO = 14, - IMAGE_VIEW_CREATE_INFO = 15, - SHADER_MODULE_CREATE_INFO = 16, - PIPELINE_CACHE_CREATE_INFO = 17, - PIPELINE_SHADER_STAGE_CREATE_INFO = 18, - PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19, - PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20, - PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21, - PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22, - PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23, - PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24, - PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25, - PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26, - PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27, - GRAPHICS_PIPELINE_CREATE_INFO = 28, - COMPUTE_PIPELINE_CREATE_INFO = 29, - PIPELINE_LAYOUT_CREATE_INFO = 30, - SAMPLER_CREATE_INFO = 31, - DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32, - DESCRIPTOR_POOL_CREATE_INFO = 33, - DESCRIPTOR_SET_ALLOCATE_INFO = 34, - WRITE_DESCRIPTOR_SET = 35, - COPY_DESCRIPTOR_SET = 36, - FRAMEBUFFER_CREATE_INFO = 37, - RENDER_PASS_CREATE_INFO = 38, - COMMAND_POOL_CREATE_INFO = 39, - COMMAND_BUFFER_ALLOCATE_INFO = 40, - COMMAND_BUFFER_INHERITANCE_INFO = 41, - COMMAND_BUFFER_BEGIN_INFO = 42, - RENDER_PASS_BEGIN_INFO = 43, - BUFFER_MEMORY_BARRIER = 44, - IMAGE_MEMORY_BARRIER = 45, - MEMORY_BARRIER = 46, - LOADER_INSTANCE_CREATE_INFO = 47, - LOADER_DEVICE_CREATE_INFO = 48, - PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, - BIND_BUFFER_MEMORY_INFO = 1000157000, - BIND_IMAGE_MEMORY_INFO = 1000157001, - PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, - MEMORY_DEDICATED_REQUIREMENTS = 1000127000, - MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, - MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, - DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, - DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004, - DEVICE_GROUP_SUBMIT_INFO = 1000060005, - DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006, - BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013, - BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014, - PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000, - DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001, - BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000, - IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001, - IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002, - MEMORY_REQUIREMENTS_2 = 1000146003, - SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004, - PHYSICAL_DEVICE_FEATURES_2 = 1000059000, - PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001, - FORMAT_PROPERTIES_2 = 1000059002, - IMAGE_FORMAT_PROPERTIES_2 = 1000059003, - PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004, - QUEUE_FAMILY_PROPERTIES_2 = 1000059005, - PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, - SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, - PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, - PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, - RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, - IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, - PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, - RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, - PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, - PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, - PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, - PROTECTED_SUBMIT_INFO = 1000145000, - PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, - PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, - DEVICE_QUEUE_INFO_2 = 1000145003, - SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, - SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, - BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, - IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, - PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, - SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, - DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, - PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000, - EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001, - PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002, - EXTERNAL_BUFFER_PROPERTIES = 1000071003, - PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004, - EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000, - EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001, - EXPORT_MEMORY_ALLOCATE_INFO = 1000072002, - PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000, - EXTERNAL_FENCE_PROPERTIES = 1000112001, - EXPORT_FENCE_CREATE_INFO = 1000113000, - EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, - PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, - EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, - PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, - DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, - PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, - PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, - PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, - PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, - PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, - IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, - ATTACHMENT_DESCRIPTION_2 = 1000109000, - ATTACHMENT_REFERENCE_2 = 1000109001, - SUBPASS_DESCRIPTION_2 = 1000109002, - SUBPASS_DEPENDENCY_2 = 1000109003, - RENDER_PASS_CREATE_INFO_2 = 1000109004, - SUBPASS_BEGIN_INFO = 1000109005, - SUBPASS_END_INFO = 1000109006, - PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, - PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, - PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, - PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, - PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, - DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, - PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, - PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, - DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, - DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, - PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, - SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, - PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, - IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, - PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, - SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, - PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, - PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, - FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, - FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, - RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, - PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, - PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, - PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, - ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, - ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, - PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, - PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, - PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, - SEMAPHORE_TYPE_CREATE_INFO = 1000207002, - TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003, - SEMAPHORE_WAIT_INFO = 1000207004, - SEMAPHORE_SIGNAL_INFO = 1000207005, - PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, - BUFFER_DEVICE_ADDRESS_INFO = 1000244001, - BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, - MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, - DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, - PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, - PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, - PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, - PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, - PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, - PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, - PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, - DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, - PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, - PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, - MEMORY_BARRIER_2 = 1000314000, - BUFFER_MEMORY_BARRIER_2 = 1000314001, - IMAGE_MEMORY_BARRIER_2 = 1000314002, - DEPENDENCY_INFO = 1000314003, - SUBMIT_INFO_2 = 1000314004, - SEMAPHORE_SUBMIT_INFO = 1000314005, - COMMAND_BUFFER_SUBMIT_INFO = 1000314006, - PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, - PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, - PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, - COPY_BUFFER_INFO_2 = 1000337000, - COPY_IMAGE_INFO_2 = 1000337001, - COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, - COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, - BLIT_IMAGE_INFO_2 = 1000337004, - RESOLVE_IMAGE_INFO_2 = 1000337005, - BUFFER_COPY_2 = 1000337006, - IMAGE_COPY_2 = 1000337007, - IMAGE_BLIT_2 = 1000337008, - BUFFER_IMAGE_COPY_2 = 1000337009, - IMAGE_RESOLVE_2 = 1000337010, - PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, - PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, - PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, - PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000, - PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, - WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, - DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, - PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, - RENDERING_INFO = 1000044000, - RENDERING_ATTACHMENT_INFO = 1000044001, - PIPELINE_RENDERING_CREATE_INFO = 1000044002, - PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, - COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, - PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, - PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, - PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, - FORMAT_PROPERTIES_3 = 1000360000, - PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, - PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, - DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, - DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, - PHYSICAL_DEVICE_VULKAN_1_4_FEATURES = 55, - PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES = 56, - DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO = 1000174000, - PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES = 1000388000, - QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES = 1000388001, - PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES = 1000416000, - PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES = 1000528000, - PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES = 1000544000, - PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES = 1000259000, - PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO = 1000259001, - PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES = 1000259002, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES = 1000525000, - PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO = 1000190001, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES = 1000190002, - PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES = 1000265000, - MEMORY_MAP_INFO = 1000271000, - MEMORY_UNMAP_INFO = 1000271001, - PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES = 1000470000, - PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES = 1000470001, - RENDERING_AREA_INFO = 1000470003, - DEVICE_IMAGE_SUBRESOURCE_INFO = 1000470004, - SUBRESOURCE_LAYOUT_2 = 1000338002, - IMAGE_SUBRESOURCE_2 = 1000338003, - PIPELINE_CREATE_FLAGS_2_CREATE_INFO = 1000470005, - BUFFER_USAGE_FLAGS_2_CREATE_INFO = 1000470006, - PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES = 1000080000, - PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES = 1000232000, - RENDERING_ATTACHMENT_LOCATION_INFO = 1000232001, - RENDERING_INPUT_ATTACHMENT_INDEX_INFO = 1000232002, - PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES = 1000545000, - PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES = 1000545001, - BIND_MEMORY_STATUS = 1000545002, - BIND_DESCRIPTOR_SETS_INFO = 1000545003, - PUSH_CONSTANTS_INFO = 1000545004, - PUSH_DESCRIPTOR_SET_INFO = 1000545005, - PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO = 1000545006, - PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES = 1000466000, - PIPELINE_ROBUSTNESS_CREATE_INFO = 1000068000, - PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES = 1000068001, - PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES = 1000068002, - PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES = 1000270000, - PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES = 1000270001, - MEMORY_TO_IMAGE_COPY = 1000270002, - IMAGE_TO_MEMORY_COPY = 1000270003, - COPY_IMAGE_TO_MEMORY_INFO = 1000270004, - COPY_MEMORY_TO_IMAGE_INFO = 1000270005, - HOST_IMAGE_LAYOUT_TRANSITION_INFO = 1000270006, - COPY_IMAGE_TO_IMAGE_INFO = 1000270007, - SUBRESOURCE_HOST_MEMCPY_SIZE = 1000270008, - HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY = 1000270009, - SWAPCHAIN_CREATE_INFO_KHR = 1000001000, - PRESENT_INFO_KHR = 1000001001, - DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, - IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008, - BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009, - ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010, - DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011, - DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, - DISPLAY_MODE_CREATE_INFO_KHR = 1000002000, - DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001, - DISPLAY_PRESENT_INFO_KHR = 1000003000, - XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, - XCB_SURFACE_CREATE_INFO_KHR = 1000005000, - WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, - ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, - WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, - DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, - PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000, - DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, - DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, - DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, - VIDEO_PROFILE_INFO_KHR = 1000023000, - VIDEO_CAPABILITIES_KHR = 1000023001, - VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002, - VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003, - BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004, - VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, - VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, - VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, - VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, - VIDEO_END_CODING_INFO_KHR = 1000023009, - VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, - VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011, - QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012, - VIDEO_PROFILE_LIST_INFO_KHR = 1000023013, - PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, - VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, - QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016, - VIDEO_DECODE_INFO_KHR = 1000024000, - VIDEO_DECODE_CAPABILITIES_KHR = 1000024001, - VIDEO_DECODE_USAGE_INFO_KHR = 1000024002, - DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, - DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, - DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, - PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, - PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, - PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, - CU_MODULE_CREATE_INFO_NVX = 1000029000, - CU_FUNCTION_CREATE_INFO_NVX = 1000029001, - CU_LAUNCH_INFO_NVX = 1000029002, - CU_MODULE_TEXTURING_MODE_CREATE_INFO_NVX = 1000029004, - IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, - IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, - VIDEO_ENCODE_H264_CAPABILITIES_KHR = 1000038000, - VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000038001, - VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000038002, - VIDEO_ENCODE_H264_PICTURE_INFO_KHR = 1000038003, - VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR = 1000038004, - VIDEO_ENCODE_H264_NALU_SLICE_INFO_KHR = 1000038005, - VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_KHR = 1000038006, - VIDEO_ENCODE_H264_PROFILE_INFO_KHR = 1000038007, - VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR = 1000038008, - VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_KHR = 1000038009, - VIDEO_ENCODE_H264_SESSION_CREATE_INFO_KHR = 1000038010, - VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR = 1000038011, - VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR = 1000038012, - VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000038013, - VIDEO_ENCODE_H265_CAPABILITIES_KHR = 1000039000, - VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000039001, - VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000039002, - VIDEO_ENCODE_H265_PICTURE_INFO_KHR = 1000039003, - VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR = 1000039004, - VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR = 1000039005, - VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_KHR = 1000039006, - VIDEO_ENCODE_H265_PROFILE_INFO_KHR = 1000039007, - VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR = 1000039009, - VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR = 1000039010, - VIDEO_ENCODE_H265_SESSION_CREATE_INFO_KHR = 1000039011, - VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR = 1000039012, - VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR = 1000039013, - VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000039014, - VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000, - VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001, - VIDEO_DECODE_H264_PROFILE_INFO_KHR = 1000040003, - VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000040004, - VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000040005, - VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR = 1000040006, - TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, - STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, - PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, - EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, - EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, - IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, - EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001, - WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, - VALIDATION_FLAGS_EXT = 1000061000, - VI_SURFACE_CREATE_INFO_NN = 1000062000, - IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, - PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, - IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, - EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, - MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, - MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003, - IMPORT_MEMORY_FD_INFO_KHR = 1000074000, - MEMORY_FD_PROPERTIES_KHR = 1000074001, - MEMORY_GET_FD_INFO_KHR = 1000074002, - WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000, - IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000, - EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001, - D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002, - SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003, - IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, - SEMAPHORE_GET_FD_INFO_KHR = 1000079001, - COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000, - PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, - CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, - PRESENT_REGIONS_KHR = 1000084000, - PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, - SURFACE_CAPABILITIES_2_EXT = 1000090000, - DISPLAY_POWER_INFO_EXT = 1000091000, - DEVICE_EVENT_INFO_EXT = 1000091001, - DISPLAY_EVENT_INFO_EXT = 1000091002, - SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003, - PRESENT_TIMES_INFO_GOOGLE = 1000092000, - PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, - MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, - PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000, - PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000, - PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, - PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000, - PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001, - PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000, - PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001, - HDR_METADATA_EXT = 1000105000, - PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG = 1000110000, - SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, - IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, - EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, - FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, - IMPORT_FENCE_FD_INFO_KHR = 1000115000, - FENCE_GET_FD_INFO_KHR = 1000115001, - PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000, - PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001, - QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002, - PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003, - ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004, - PERFORMANCE_COUNTER_KHR = 1000116005, - PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006, - PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, - SURFACE_CAPABILITIES_2_KHR = 1000119001, - SURFACE_FORMAT_2_KHR = 1000119002, - DISPLAY_PROPERTIES_2_KHR = 1000121000, - DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001, - DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002, - DISPLAY_PLANE_INFO_2_KHR = 1000121003, - DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004, - IOS_SURFACE_CREATE_INFO_MVK = 1000122000, - MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, - DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, - DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001, - DEBUG_UTILS_LABEL_EXT = 1000128002, - DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003, - DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004, - ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000, - ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001, - ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002, - IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, - MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, - EXTERNAL_FORMAT_ANDROID = 1000129005, - ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, - PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, - PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX = 1000134001, - EXECUTION_GRAPH_PIPELINE_SCRATCH_SIZE_AMDX = 1000134002, - EXECUTION_GRAPH_PIPELINE_CREATE_INFO_AMDX = 1000134003, - PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, - ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, - SAMPLE_LOCATIONS_INFO_EXT = 1000143000, - RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, - PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, - PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, - MULTISAMPLE_PROPERTIES_EXT = 1000143004, - PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, - PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, - PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, - PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, - WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, - ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, - ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, - ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, - ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, - ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, - ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, - ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, - COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, - COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, - COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, - PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, - PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, - ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, - ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, - PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, - PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, - RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, - RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, - RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, - PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, - PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, - PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, - PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, - DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, - PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, - IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, - IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, - IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, - DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, - VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, - SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, - PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, - PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, - PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, - PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, - PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, - PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005, - RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000, - ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001, - GEOMETRY_NV = 1000165003, - GEOMETRY_TRIANGLES_NV = 1000165004, - GEOMETRY_AABB_NV = 1000165005, - BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, - WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, - ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, - PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, - RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, - ACCELERATION_STRUCTURE_INFO_NV = 1000165012, - PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000, - PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, - PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, - FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, - IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, - MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, - PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, - PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000, - PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, - PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, - VIDEO_DECODE_H265_CAPABILITIES_KHR = 1000187000, - VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000187001, - VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000187002, - VIDEO_DECODE_H265_PROFILE_INFO_KHR = 1000187003, - VIDEO_DECODE_H265_PICTURE_INFO_KHR = 1000187004, - VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR = 1000187005, - DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, - PRESENT_FRAME_TOKEN_GGP = 1000191000, - PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, - PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, - PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, - PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, - PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, - CHECKPOINT_DATA_NV = 1000206000, - QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, - QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, - CHECKPOINT_DATA_2_NV = 1000314009, - PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, - QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, - INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, - PERFORMANCE_MARKER_INFO_INTEL = 1000210002, - PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003, - PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004, - PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005, - PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000, - DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, - SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, - IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, - METAL_SURFACE_CREATE_INFO_EXT = 1000217000, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, - RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002, - RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, - FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, - PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, - PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, - PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, - PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, - RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, - PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, - PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, - PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, - PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR = 1000235000, - PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, - PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, - MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, - SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000, - PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000, - PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, - BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, - VALIDATION_FEATURES_EXT = 1000247000, - PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, - COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002, - PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000, - PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001, - FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002, - PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000, - PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000, - PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000, - PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001, - PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002, - SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000, - SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, - SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, - HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, - PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, - PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, - PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, - PIPELINE_INFO_KHR = 1000269001, - PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, - PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, - PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, - PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, - PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT = 1000272000, - PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT = 1000272001, - MEMORY_MAP_PLACED_INFO_EXT = 1000272002, - PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, - SURFACE_PRESENT_MODE_EXT = 1000274000, - SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, - SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = 1000274002, - PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = 1000275000, - SWAPCHAIN_PRESENT_FENCE_INFO_EXT = 1000275001, - SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = 1000275002, - SWAPCHAIN_PRESENT_MODE_INFO_EXT = 1000275003, - SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = 1000275004, - RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = 1000275005, - PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, - GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, - GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, - INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, - INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, - GENERATED_COMMANDS_INFO_NV = 1000277005, - GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, - PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, - PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, - COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, - PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, - COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, - RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, - PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000, - DEPTH_BIAS_INFO_EXT = 1000283001, - DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002, - PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, - DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, - DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, - PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = 1000286000, - PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = 1000286001, - SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, - PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, - PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, - PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, - PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000, - SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001, - SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002, - PRESENT_ID_KHR = 1000294000, - PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, - VIDEO_ENCODE_INFO_KHR = 1000299000, - VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, - VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002, - VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003, - VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004, - QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, - PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299006, - VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR = 1000299007, - VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299008, - VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR = 1000299009, - VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, - PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, - DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, - CUDA_MODULE_CREATE_INFO_NV = 1000307000, - CUDA_FUNCTION_CREATE_INFO_NV = 1000307001, - CUDA_LAUNCH_INFO_NV = 1000307002, - PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV = 1000307003, - PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV = 1000307004, - QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, - EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, - EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, - EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, - EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003, - EXPORT_METAL_BUFFER_INFO_EXT = 1000311004, - IMPORT_METAL_BUFFER_INFO_EXT = 1000311005, - EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006, - IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007, - EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008, - IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009, - EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010, - IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011, - PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT = 1000316000, - PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT = 1000316001, - PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT = 1000316002, - DESCRIPTOR_ADDRESS_INFO_EXT = 1000316003, - DESCRIPTOR_GET_INFO_EXT = 1000316004, - BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316005, - IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316006, - IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316007, - SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316008, - OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT = 1000316010, - DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011, - DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012, - ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009, - PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000, - PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001, - GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002, - PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000, - PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000, - PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000, - PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, - PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, - PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, - PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, - ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, - PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, - ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, - PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000, - PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001, - PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, - COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, - PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, - PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, - IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, - IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004, - PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000, - PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, - PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000, - DEVICE_FAULT_COUNTS_EXT = 1000341001, - DEVICE_FAULT_INFO_EXT = 1000341002, - PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, - DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, - PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, - VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, - VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, - PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, - PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000, - DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001, - PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000, - PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001, - PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, - PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_EXT = 1000361000, - IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, - MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, - MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, - IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, - SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, - BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, - IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, - BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, - BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, - BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, - BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, - IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, - IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, - SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, - BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, - SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, - PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, - PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, - PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, - MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, - PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, - PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000, - PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001, - PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT = 1000375000, - FRAME_BOUNDARY_EXT = 1000375001, - PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000, - SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001, - MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002, - PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, - SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, - PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, - PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, - PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000, - PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000, - PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000, - IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001, - PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, - PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, - PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, - PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, - PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, - MICROMAP_BUILD_INFO_EXT = 1000396000, - MICROMAP_VERSION_INFO_EXT = 1000396001, - COPY_MICROMAP_INFO_EXT = 1000396002, - COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003, - COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004, - PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005, - PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006, - MICROMAP_CREATE_INFO_EXT = 1000396007, - MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008, - ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009, - PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, - PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, - ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, - PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000, - PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001, - PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_VRS_FEATURES_HUAWEI = 1000404002, - PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, - SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, - PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, - PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000, - DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM = 1000417000, - PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM = 1000417001, - PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM = 1000417002, - PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, - IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, - PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, - DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, - DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, - PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, - PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM = 1000424000, - PHYSICAL_DEVICE_RENDER_PASS_STRIPED_PROPERTIES_ARM = 1000424001, - RENDER_PASS_STRIPE_BEGIN_INFO_ARM = 1000424002, - RENDER_PASS_STRIPE_INFO_ARM = 1000424003, - RENDER_PASS_STRIPE_SUBMIT_INFO_ARM = 1000424004, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = 1000425000, - PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = 1000425001, - SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = 1000425002, - PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000, - PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = 1000426001, - PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = 1000427000, - PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = 1000427001, - PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, - COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, - PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, - PHYSICAL_DEVICE_RAY_TRACING_LINEAR_SWEPT_SPHERES_FEATURES_NV = 1000429008, - ACCELERATION_STRUCTURE_GEOMETRY_LINEAR_SWEPT_SPHERES_DATA_NV = 1000429009, - ACCELERATION_STRUCTURE_GEOMETRY_SPHERES_DATA_NV = 1000429010, - PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, - PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR = 1000434000, - PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, - PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000, - PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001, - IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, - PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, - PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, - EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, - PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, - PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, - PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000, - RENDER_PASS_CREATION_CONTROL_EXT = 1000458001, - RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002, - RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003, - DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000, - DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001, - PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000, - PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001, - PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002, - SHADER_MODULE_IDENTIFIER_EXT = 1000462003, - PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000, - PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000, - PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001, - OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002, - OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003, - OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004, - OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005, - OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, - PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, - PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID = 1000468000, - PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468001, - ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468002, - PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD = 1000476000, - ANTI_LAG_DATA_AMD = 1000476001, - ANTI_LAG_PRESENTATION_INFO_AMD = 1000476002, - PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, - PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, - PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, - SHADER_CREATE_INFO_EXT = 1000482002, - PHYSICAL_DEVICE_PIPELINE_BINARY_FEATURES_KHR = 1000483000, - PIPELINE_BINARY_CREATE_INFO_KHR = 1000483001, - PIPELINE_BINARY_INFO_KHR = 1000483002, - PIPELINE_BINARY_KEY_KHR = 1000483003, - PHYSICAL_DEVICE_PIPELINE_BINARY_PROPERTIES_KHR = 1000483004, - RELEASE_CAPTURED_PIPELINE_DATA_INFO_KHR = 1000483005, - PIPELINE_BINARY_DATA_INFO_KHR = 1000483006, - PIPELINE_CREATE_INFO_KHR = 1000483007, - DEVICE_PIPELINE_BINARY_INTERNAL_CACHE_CONTROL_KHR = 1000483008, - PIPELINE_BINARY_HANDLES_INFO_KHR = 1000483009, - PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000, - TILE_PROPERTIES_QCOM = 1000484001, - PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, - AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001, - PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, - PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, - PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, - PHYSICAL_DEVICE_COOPERATIVE_VECTOR_FEATURES_NV = 1000491000, - PHYSICAL_DEVICE_COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491001, - COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491002, - CONVERT_COOPERATIVE_VECTOR_MATRIX_INFO_NV = 1000491004, - PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, - PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, - PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000, - MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, - PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_FEATURES_EXT = 1000495000, - PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_PROPERTIES_EXT = 1000495001, - LAYER_SETTINGS_CREATE_INFO_EXT = 1000496000, - PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, - PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, - PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, - PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, - LATENCY_SLEEP_MODE_INFO_NV = 1000505000, - LATENCY_SLEEP_INFO_NV = 1000505001, - SET_LATENCY_MARKER_INFO_NV = 1000505002, - GET_LATENCY_MARKER_INFO_NV = 1000505003, - LATENCY_TIMINGS_FRAME_REPORT_NV = 1000505004, - LATENCY_SUBMISSION_PRESENT_ID_NV = 1000505005, - OUT_OF_BAND_QUEUE_TYPE_INFO_NV = 1000505006, - SWAPCHAIN_LATENCY_CREATE_INFO_NV = 1000505007, - LATENCY_SURFACE_CAPABILITIES_NV = 1000505008, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, - COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, - PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, - MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, - PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR = 1000201000, - PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_PROPERTIES_KHR = 1000511000, - VIDEO_DECODE_AV1_CAPABILITIES_KHR = 1000512000, - VIDEO_DECODE_AV1_PICTURE_INFO_KHR = 1000512001, - VIDEO_DECODE_AV1_PROFILE_INFO_KHR = 1000512003, - VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000512004, - VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR = 1000512005, - VIDEO_ENCODE_AV1_CAPABILITIES_KHR = 1000513000, - VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000513001, - VIDEO_ENCODE_AV1_PICTURE_INFO_KHR = 1000513002, - VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR = 1000513003, - PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR = 1000513004, - VIDEO_ENCODE_AV1_PROFILE_INFO_KHR = 1000513005, - VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR = 1000513006, - VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR = 1000513007, - VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR = 1000513008, - VIDEO_ENCODE_AV1_SESSION_CREATE_INFO_KHR = 1000513009, - VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR = 1000513010, - PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR = 1000515000, - VIDEO_INLINE_QUERY_INFO_KHR = 1000515001, - PHYSICAL_DEVICE_PER_STAGE_DESCRIPTOR_SET_FEATURES_NV = 1000516000, - PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM = 1000518000, - PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM = 1000518001, - SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM = 1000518002, - SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM = 1000519000, - PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM = 1000519001, - BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM = 1000519002, - PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM = 1000520000, - SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, - PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, - PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, - SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, - SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, - IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, - EXTERNAL_FORMAT_QNX = 1000529003, - PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, - PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT = 1000530000, - CALIBRATED_TIMESTAMP_INFO_KHR = 1000184000, - SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT = 1000545007, - BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT = 1000545008, - PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, - DISPLAY_SURFACE_STEREO_CREATE_INFO_NV = 1000551000, - DISPLAY_MODE_STEREO_PROPERTIES_NV = 1000551001, - VIDEO_ENCODE_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553000, - VIDEO_FORMAT_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553001, - VIDEO_ENCODE_QUANTIZATION_MAP_INFO_KHR = 1000553002, - VIDEO_ENCODE_QUANTIZATION_MAP_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000553005, - PHYSICAL_DEVICE_VIDEO_ENCODE_QUANTIZATION_MAP_FEATURES_KHR = 1000553009, - VIDEO_ENCODE_H264_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553003, - VIDEO_ENCODE_H265_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553004, - VIDEO_FORMAT_H265_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553006, - VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553007, - VIDEO_FORMAT_AV1_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553008, - PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV = 1000555000, - PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR = 1000558000, - PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV = 1000559000, - PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR = 1000562000, - PHYSICAL_DEVICE_MAINTENANCE_7_PROPERTIES_KHR = 1000562001, - PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_LIST_KHR = 1000562002, - PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_KHR = 1000562003, - PHYSICAL_DEVICE_LAYERED_API_VULKAN_PROPERTIES_KHR = 1000562004, - PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV = 1000563000, - PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT = 1000564000, - PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV = 1000568000, - PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_FEATURES_NV = 1000569000, - PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000569001, - CLUSTER_ACCELERATION_STRUCTURE_CLUSTERS_BOTTOM_LEVEL_INPUT_NV = 1000569002, - CLUSTER_ACCELERATION_STRUCTURE_TRIANGLE_CLUSTER_INPUT_NV = 1000569003, - CLUSTER_ACCELERATION_STRUCTURE_MOVE_OBJECTS_INPUT_NV = 1000569004, - CLUSTER_ACCELERATION_STRUCTURE_INPUT_INFO_NV = 1000569005, - CLUSTER_ACCELERATION_STRUCTURE_COMMANDS_INFO_NV = 1000569006, - RAY_TRACING_PIPELINE_CLUSTER_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000569007, - PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_FEATURES_NV = 1000570000, - PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000570001, - WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570002, - PARTITIONED_ACCELERATION_STRUCTURE_INSTANCES_INPUT_NV = 1000570003, - BUILD_PARTITIONED_ACCELERATION_STRUCTURE_INFO_NV = 1000570004, - PARTITIONED_ACCELERATION_STRUCTURE_FLAGS_NV = 1000570005, - PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_EXT = 1000572000, - PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT = 1000572001, - GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_EXT = 1000572002, - INDIRECT_EXECUTION_SET_CREATE_INFO_EXT = 1000572003, - GENERATED_COMMANDS_INFO_EXT = 1000572004, - INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_EXT = 1000572006, - INDIRECT_COMMANDS_LAYOUT_TOKEN_EXT = 1000572007, - WRITE_INDIRECT_EXECUTION_SET_PIPELINE_EXT = 1000572008, - WRITE_INDIRECT_EXECUTION_SET_SHADER_EXT = 1000572009, - INDIRECT_EXECUTION_SET_PIPELINE_INFO_EXT = 1000572010, - INDIRECT_EXECUTION_SET_SHADER_INFO_EXT = 1000572011, - INDIRECT_EXECUTION_SET_SHADER_LAYOUT_INFO_EXT = 1000572012, - GENERATED_COMMANDS_PIPELINE_INFO_EXT = 1000572013, - GENERATED_COMMANDS_SHADER_INFO_EXT = 1000572014, - PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR = 1000574000, - MEMORY_BARRIER_ACCESS_FLAGS_3_KHR = 1000574002, - PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA = 1000575000, - PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_PROPERTIES_MESA = 1000575001, - IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA = 1000575002, - PHYSICAL_DEVICE_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, - PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, - PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR = 1000586000, - VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586001, - VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586002, - VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586003, - PHYSICAL_DEVICE_HDR_VIVID_FEATURES_HUAWEI = 1000590000, - HDR_VIVID_DYNAMIC_METADATA_HUAWEI = 1000590001, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV = 1000593000, - COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV = 1000593001, - PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_PROPERTIES_NV = 1000593002, - PHYSICAL_DEVICE_PIPELINE_OPACITY_MICROMAP_FEATURES_ARM = 1000596000, - IMPORT_MEMORY_METAL_HANDLE_INFO_EXT = 1000602000, - MEMORY_METAL_HANDLE_PROPERTIES_EXT = 1000602001, - MEMORY_GET_METAL_HANDLE_INFO_EXT = 1000602002, - PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR = 1000421000, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, - SET_PRESENT_CONFIG_NV = 1000613000, - PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, - PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, - PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, - DEBUG_REPORT_CREATE_INFO_EXT = DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, - RENDERING_INFO_KHR = RENDERING_INFO, - RENDERING_ATTACHMENT_INFO_KHR = RENDERING_ATTACHMENT_INFO, - PIPELINE_RENDERING_CREATE_INFO_KHR = PIPELINE_RENDERING_CREATE_INFO, - PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, - COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, - RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = RENDER_PASS_MULTIVIEW_CREATE_INFO, - PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = PHYSICAL_DEVICE_MULTIVIEW_FEATURES, - PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, - PHYSICAL_DEVICE_FEATURES_2_KHR = PHYSICAL_DEVICE_FEATURES_2, - PHYSICAL_DEVICE_PROPERTIES_2_KHR = PHYSICAL_DEVICE_PROPERTIES_2, - FORMAT_PROPERTIES_2_KHR = FORMAT_PROPERTIES_2, - IMAGE_FORMAT_PROPERTIES_2_KHR = IMAGE_FORMAT_PROPERTIES_2, - PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, - QUEUE_FAMILY_PROPERTIES_2_KHR = QUEUE_FAMILY_PROPERTIES_2, - PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, - SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = SPARSE_IMAGE_FORMAT_PROPERTIES_2, - PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, - MEMORY_ALLOCATE_FLAGS_INFO_KHR = MEMORY_ALLOCATE_FLAGS_INFO, - DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, - DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, - DEVICE_GROUP_SUBMIT_INFO_KHR = DEVICE_GROUP_SUBMIT_INFO, - DEVICE_GROUP_BIND_SPARSE_INFO_KHR = DEVICE_GROUP_BIND_SPARSE_INFO, - BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, - BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, - PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES, - PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = PIPELINE_ROBUSTNESS_CREATE_INFO, - PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES, - PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES, - PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = PHYSICAL_DEVICE_GROUP_PROPERTIES, - DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = DEVICE_GROUP_DEVICE_CREATE_INFO, - PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, - EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = EXTERNAL_IMAGE_FORMAT_PROPERTIES, - PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, - EXTERNAL_BUFFER_PROPERTIES_KHR = EXTERNAL_BUFFER_PROPERTIES, - PHYSICAL_DEVICE_ID_PROPERTIES_KHR = PHYSICAL_DEVICE_ID_PROPERTIES, - EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = EXTERNAL_MEMORY_BUFFER_CREATE_INFO, - EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = EXTERNAL_MEMORY_IMAGE_CREATE_INFO, - EXPORT_MEMORY_ALLOCATE_INFO_KHR = EXPORT_MEMORY_ALLOCATE_INFO, - PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, - EXTERNAL_SEMAPHORE_PROPERTIES_KHR = EXTERNAL_SEMAPHORE_PROPERTIES, - EXPORT_SEMAPHORE_CREATE_INFO_KHR = EXPORT_SEMAPHORE_CREATE_INFO, - PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES, - PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, - PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, - PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, - DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, - SURFACE_CAPABILITIES2_EXT = SURFACE_CAPABILITIES_2_EXT, - PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, - FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, - FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, - RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = RENDER_PASS_ATTACHMENT_BEGIN_INFO, - ATTACHMENT_DESCRIPTION_2_KHR = ATTACHMENT_DESCRIPTION_2, - ATTACHMENT_REFERENCE_2_KHR = ATTACHMENT_REFERENCE_2, - SUBPASS_DESCRIPTION_2_KHR = SUBPASS_DESCRIPTION_2, - SUBPASS_DEPENDENCY_2_KHR = SUBPASS_DEPENDENCY_2, - RENDER_PASS_CREATE_INFO_2_KHR = RENDER_PASS_CREATE_INFO_2, - SUBPASS_BEGIN_INFO_KHR = SUBPASS_BEGIN_INFO, - SUBPASS_END_INFO_KHR = SUBPASS_END_INFO, - PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, - EXTERNAL_FENCE_PROPERTIES_KHR = EXTERNAL_FENCE_PROPERTIES, - EXPORT_FENCE_CREATE_INFO_KHR = EXPORT_FENCE_CREATE_INFO, - PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, - RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, - IMAGE_VIEW_USAGE_CREATE_INFO_KHR = IMAGE_VIEW_USAGE_CREATE_INFO, - PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, - PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, - PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, - MEMORY_DEDICATED_REQUIREMENTS_KHR = MEMORY_DEDICATED_REQUIREMENTS, - MEMORY_DEDICATED_ALLOCATE_INFO_KHR = MEMORY_DEDICATED_ALLOCATE_INFO, - PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, - SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = SAMPLER_REDUCTION_MODE_CREATE_INFO, - PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, - PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES, - WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, - DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO, - BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = BUFFER_MEMORY_REQUIREMENTS_INFO_2, - IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = IMAGE_MEMORY_REQUIREMENTS_INFO_2, - IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, - MEMORY_REQUIREMENTS_2_KHR = MEMORY_REQUIREMENTS_2, - SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, - IMAGE_FORMAT_LIST_CREATE_INFO_KHR = IMAGE_FORMAT_LIST_CREATE_INFO, - ATTACHMENT_SAMPLE_COUNT_INFO_NV = ATTACHMENT_SAMPLE_COUNT_INFO_AMD, - SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = SAMPLER_YCBCR_CONVERSION_CREATE_INFO, - SAMPLER_YCBCR_CONVERSION_INFO_KHR = SAMPLER_YCBCR_CONVERSION_INFO, - BIND_IMAGE_PLANE_MEMORY_INFO_KHR = BIND_IMAGE_PLANE_MEMORY_INFO, - IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, - PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, - SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, - BIND_BUFFER_MEMORY_INFO_KHR = BIND_BUFFER_MEMORY_INFO, - BIND_IMAGE_MEMORY_INFO_KHR = BIND_IMAGE_MEMORY_INFO, - DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, - PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, - PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, - DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, - DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, - PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, - DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = DESCRIPTOR_SET_LAYOUT_SUPPORT, - DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, - PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, - PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, - PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, - CALIBRATED_TIMESTAMP_INFO_EXT = CALIBRATED_TIMESTAMP_INFO_KHR, - DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, - PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, - QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, - PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, - PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = PIPELINE_CREATION_FEEDBACK_CREATE_INFO, - PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = PHYSICAL_DEVICE_DRIVER_PROPERTIES, - PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, - PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, - SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, - PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR, - PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, - PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, - PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, - SEMAPHORE_TYPE_CREATE_INFO_KHR = SEMAPHORE_TYPE_CREATE_INFO, - TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = TIMELINE_SEMAPHORE_SUBMIT_INFO, - SEMAPHORE_WAIT_INFO_KHR = SEMAPHORE_WAIT_INFO, - SEMAPHORE_SIGNAL_INFO_KHR = SEMAPHORE_SIGNAL_INFO, - QUERY_POOL_CREATE_INFO_INTEL = QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, - PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, - PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, - PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, - PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, - PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, - PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, - PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR = PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES, - RENDERING_ATTACHMENT_LOCATION_INFO_KHR = RENDERING_ATTACHMENT_LOCATION_INFO, - RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR = RENDERING_INPUT_ATTACHMENT_INDEX_INFO, - PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, - ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = ATTACHMENT_REFERENCE_STENCIL_LAYOUT, - ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, - PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, - BUFFER_DEVICE_ADDRESS_INFO_EXT = BUFFER_DEVICE_ADDRESS_INFO, - PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = PHYSICAL_DEVICE_TOOL_PROPERTIES, - IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = IMAGE_STENCIL_USAGE_CREATE_INFO, - PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, - PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, - BUFFER_DEVICE_ADDRESS_INFO_KHR = BUFFER_DEVICE_ADDRESS_INFO, - BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, - MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, - DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, - PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, - PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, - PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, - PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, - PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, - PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT = PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES, - PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT = PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES, - MEMORY_TO_IMAGE_COPY_EXT = MEMORY_TO_IMAGE_COPY, - IMAGE_TO_MEMORY_COPY_EXT = IMAGE_TO_MEMORY_COPY, - COPY_IMAGE_TO_MEMORY_INFO_EXT = COPY_IMAGE_TO_MEMORY_INFO, - COPY_MEMORY_TO_IMAGE_INFO_EXT = COPY_MEMORY_TO_IMAGE_INFO, - HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT = HOST_IMAGE_LAYOUT_TRANSITION_INFO, - COPY_IMAGE_TO_IMAGE_INFO_EXT = COPY_IMAGE_TO_IMAGE_INFO, - SUBRESOURCE_HOST_MEMCPY_SIZE_EXT = SUBRESOURCE_HOST_MEMCPY_SIZE, - HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY, - MEMORY_MAP_INFO_KHR = MEMORY_MAP_INFO, - MEMORY_UNMAP_INFO_KHR = MEMORY_UNMAP_INFO, - PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, - PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, - PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, - PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, - PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, - DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = DEVICE_PRIVATE_DATA_CREATE_INFO, - PRIVATE_DATA_SLOT_CREATE_INFO_EXT = PRIVATE_DATA_SLOT_CREATE_INFO, - PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, - MEMORY_BARRIER_2_KHR = MEMORY_BARRIER_2, - BUFFER_MEMORY_BARRIER_2_KHR = BUFFER_MEMORY_BARRIER_2, - IMAGE_MEMORY_BARRIER_2_KHR = IMAGE_MEMORY_BARRIER_2, - DEPENDENCY_INFO_KHR = DEPENDENCY_INFO, - SUBMIT_INFO_2_KHR = SUBMIT_INFO_2, - SEMAPHORE_SUBMIT_INFO_KHR = SEMAPHORE_SUBMIT_INFO, - COMMAND_BUFFER_SUBMIT_INFO_KHR = COMMAND_BUFFER_SUBMIT_INFO, - PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, - PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES, - PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES, - COPY_BUFFER_INFO_2_KHR = COPY_BUFFER_INFO_2, - COPY_IMAGE_INFO_2_KHR = COPY_IMAGE_INFO_2, - COPY_BUFFER_TO_IMAGE_INFO_2_KHR = COPY_BUFFER_TO_IMAGE_INFO_2, - COPY_IMAGE_TO_BUFFER_INFO_2_KHR = COPY_IMAGE_TO_BUFFER_INFO_2, - BLIT_IMAGE_INFO_2_KHR = BLIT_IMAGE_INFO_2, - RESOLVE_IMAGE_INFO_2_KHR = RESOLVE_IMAGE_INFO_2, - BUFFER_COPY_2_KHR = BUFFER_COPY_2, - IMAGE_COPY_2_KHR = IMAGE_COPY_2, - IMAGE_BLIT_2_KHR = IMAGE_BLIT_2, - BUFFER_IMAGE_COPY_2_KHR = BUFFER_IMAGE_COPY_2, - IMAGE_RESOLVE_2_KHR = IMAGE_RESOLVE_2, - SUBRESOURCE_LAYOUT_2_EXT = SUBRESOURCE_LAYOUT_2, - IMAGE_SUBRESOURCE_2_EXT = IMAGE_SUBRESOURCE_2, - PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, - PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, - MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, - FORMAT_PROPERTIES_3_KHR = FORMAT_PROPERTIES_3, - PIPELINE_INFO_EXT = PIPELINE_INFO_KHR, - PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, - QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, - PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, - PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, - DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = DEVICE_BUFFER_MEMORY_REQUIREMENTS, - DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = DEVICE_IMAGE_MEMORY_REQUIREMENTS, - PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, - PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR, - PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, - PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, - PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES, - RENDERING_AREA_INFO_KHR = RENDERING_AREA_INFO, - DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = DEVICE_IMAGE_SUBRESOURCE_INFO, - SUBRESOURCE_LAYOUT_2_KHR = SUBRESOURCE_LAYOUT_2, - IMAGE_SUBRESOURCE_2_KHR = IMAGE_SUBRESOURCE_2, - PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = PIPELINE_CREATE_FLAGS_2_CREATE_INFO, - BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = BUFFER_USAGE_FLAGS_2_CREATE_INFO, - SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_KHR = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES, - PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_KHR = PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, - PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, - PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, - PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_KHR = PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, - PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_KHR = PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, - PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_KHR = PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, - PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_KHR = PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, - PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES, - PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES, - PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES, - BIND_MEMORY_STATUS_KHR = BIND_MEMORY_STATUS, - BIND_DESCRIPTOR_SETS_INFO_KHR = BIND_DESCRIPTOR_SETS_INFO, - PUSH_CONSTANTS_INFO_KHR = PUSH_CONSTANTS_INFO, - PUSH_DESCRIPTOR_SET_INFO_KHR = PUSH_DESCRIPTOR_SET_INFO, - PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR = PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO, + APPLICATION_INFO = 0, + INSTANCE_CREATE_INFO = 1, + DEVICE_QUEUE_CREATE_INFO = 2, + DEVICE_CREATE_INFO = 3, + SUBMIT_INFO = 4, + MEMORY_ALLOCATE_INFO = 5, + MAPPED_MEMORY_RANGE = 6, + BIND_SPARSE_INFO = 7, + FENCE_CREATE_INFO = 8, + SEMAPHORE_CREATE_INFO = 9, + EVENT_CREATE_INFO = 10, + QUERY_POOL_CREATE_INFO = 11, + BUFFER_CREATE_INFO = 12, + BUFFER_VIEW_CREATE_INFO = 13, + IMAGE_CREATE_INFO = 14, + IMAGE_VIEW_CREATE_INFO = 15, + SHADER_MODULE_CREATE_INFO = 16, + PIPELINE_CACHE_CREATE_INFO = 17, + PIPELINE_SHADER_STAGE_CREATE_INFO = 18, + PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19, + PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20, + PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21, + PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22, + PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23, + PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24, + PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25, + PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26, + PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27, + GRAPHICS_PIPELINE_CREATE_INFO = 28, + COMPUTE_PIPELINE_CREATE_INFO = 29, + PIPELINE_LAYOUT_CREATE_INFO = 30, + SAMPLER_CREATE_INFO = 31, + DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32, + DESCRIPTOR_POOL_CREATE_INFO = 33, + DESCRIPTOR_SET_ALLOCATE_INFO = 34, + WRITE_DESCRIPTOR_SET = 35, + COPY_DESCRIPTOR_SET = 36, + FRAMEBUFFER_CREATE_INFO = 37, + RENDER_PASS_CREATE_INFO = 38, + COMMAND_POOL_CREATE_INFO = 39, + COMMAND_BUFFER_ALLOCATE_INFO = 40, + COMMAND_BUFFER_INHERITANCE_INFO = 41, + COMMAND_BUFFER_BEGIN_INFO = 42, + RENDER_PASS_BEGIN_INFO = 43, + BUFFER_MEMORY_BARRIER = 44, + IMAGE_MEMORY_BARRIER = 45, + MEMORY_BARRIER = 46, + LOADER_INSTANCE_CREATE_INFO = 47, + LOADER_DEVICE_CREATE_INFO = 48, + BIND_BUFFER_MEMORY_INFO = 1000157000, + BIND_IMAGE_MEMORY_INFO = 1000157001, + MEMORY_DEDICATED_REQUIREMENTS = 1000127000, + MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001, + MEMORY_ALLOCATE_FLAGS_INFO = 1000060000, + DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004, + DEVICE_GROUP_SUBMIT_INFO = 1000060005, + DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006, + BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013, + BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014, + PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000, + DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001, + BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000, + IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001, + IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002, + MEMORY_REQUIREMENTS_2 = 1000146003, + SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004, + PHYSICAL_DEVICE_FEATURES_2 = 1000059000, + PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001, + FORMAT_PROPERTIES_2 = 1000059002, + IMAGE_FORMAT_PROPERTIES_2 = 1000059003, + PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004, + QUEUE_FAMILY_PROPERTIES_2 = 1000059005, + PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006, + SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007, + PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008, + IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002, + PROTECTED_SUBMIT_INFO = 1000145000, + PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001, + PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002, + DEVICE_QUEUE_INFO_2 = 1000145003, + PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000, + EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001, + PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002, + EXTERNAL_BUFFER_PROPERTIES = 1000071003, + PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004, + EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000, + EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001, + EXPORT_MEMORY_ALLOCATE_INFO = 1000072002, + PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000, + EXTERNAL_FENCE_PROPERTIES = 1000112001, + EXPORT_FENCE_CREATE_INFO = 1000113000, + EXPORT_SEMAPHORE_CREATE_INFO = 1000077000, + PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000, + EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001, + PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000, + PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000, + PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES = 1000120000, + DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000, + PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000, + DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, + SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000, + SAMPLER_YCBCR_CONVERSION_INFO = 1000156001, + BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002, + IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003, + PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004, + SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005, + DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003, + PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000, + RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001, + PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003, + RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000, + PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001, + PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002, + PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, + PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, + PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, + PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, + PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, + PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, + IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, + PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, + PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, + PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, + PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, + SEMAPHORE_TYPE_CREATE_INFO = 1000207002, + TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003, + SEMAPHORE_WAIT_INFO = 1000207004, + SEMAPHORE_SIGNAL_INFO = 1000207005, + PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, + BUFFER_DEVICE_ADDRESS_INFO = 1000244001, + BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, + MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, + DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, + PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, + PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, + PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, + PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, + DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, + DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, + PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + ATTACHMENT_DESCRIPTION_2 = 1000109000, + ATTACHMENT_REFERENCE_2 = 1000109001, + SUBPASS_DESCRIPTION_2 = 1000109002, + SUBPASS_DEPENDENCY_2 = 1000109003, + RENDER_PASS_CREATE_INFO_2 = 1000109004, + SUBPASS_BEGIN_INFO = 1000109005, + SUBPASS_END_INFO = 1000109006, + PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, + FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, + FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, + RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, + PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, + ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, + ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, + PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, + PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, + PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, + PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, + DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, + PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, + MEMORY_BARRIER_2 = 1000314000, + BUFFER_MEMORY_BARRIER_2 = 1000314001, + IMAGE_MEMORY_BARRIER_2 = 1000314002, + DEPENDENCY_INFO = 1000314003, + SUBMIT_INFO_2 = 1000314004, + SEMAPHORE_SUBMIT_INFO = 1000314005, + COMMAND_BUFFER_SUBMIT_INFO = 1000314006, + PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, + COPY_BUFFER_INFO_2 = 1000337000, + COPY_IMAGE_INFO_2 = 1000337001, + COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, + COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, + BUFFER_COPY_2 = 1000337006, + IMAGE_COPY_2 = 1000337007, + BUFFER_IMAGE_COPY_2 = 1000337009, + PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + FORMAT_PROPERTIES_3 = 1000360000, + PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, + PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, + DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, + DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, + PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, + PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, + PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, + PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, + PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000, + PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, + WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, + DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, + PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, + PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, + PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, + BLIT_IMAGE_INFO_2 = 1000337004, + RESOLVE_IMAGE_INFO_2 = 1000337005, + IMAGE_BLIT_2 = 1000337008, + IMAGE_RESOLVE_2 = 1000337010, + RENDERING_INFO = 1000044000, + RENDERING_ATTACHMENT_INFO = 1000044001, + PIPELINE_RENDERING_CREATE_INFO = 1000044002, + PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, + COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, + PHYSICAL_DEVICE_VULKAN_1_4_FEATURES = 55, + PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES = 56, + DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO = 1000174000, + PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES = 1000388000, + QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES = 1000388001, + PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES = 1000265000, + MEMORY_MAP_INFO = 1000271000, + MEMORY_UNMAP_INFO = 1000271001, + PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES = 1000470000, + PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES = 1000470001, + DEVICE_IMAGE_SUBRESOURCE_INFO = 1000470004, + SUBRESOURCE_LAYOUT_2 = 1000338002, + IMAGE_SUBRESOURCE_2 = 1000338003, + BUFFER_USAGE_FLAGS_2_CREATE_INFO = 1000470006, + PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES = 1000545000, + PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES = 1000545001, + BIND_MEMORY_STATUS = 1000545002, + PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES = 1000270000, + PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES = 1000270001, + MEMORY_TO_IMAGE_COPY = 1000270002, + IMAGE_TO_MEMORY_COPY = 1000270003, + COPY_IMAGE_TO_MEMORY_INFO = 1000270004, + COPY_MEMORY_TO_IMAGE_INFO = 1000270005, + HOST_IMAGE_LAYOUT_TRANSITION_INFO = 1000270006, + COPY_IMAGE_TO_IMAGE_INFO = 1000270007, + SUBRESOURCE_HOST_MEMCPY_SIZE = 1000270008, + HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY = 1000270009, + PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES = 1000416000, + PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES = 1000528000, + PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES = 1000544000, + PIPELINE_CREATE_FLAGS_2_CREATE_INFO = 1000470005, + PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES = 1000080000, + BIND_DESCRIPTOR_SETS_INFO = 1000545003, + PUSH_CONSTANTS_INFO = 1000545004, + PUSH_DESCRIPTOR_SET_INFO = 1000545005, + PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO = 1000545006, + PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES = 1000466000, + PIPELINE_ROBUSTNESS_CREATE_INFO = 1000068000, + PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES = 1000068001, + PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES = 1000068002, + PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES = 1000259000, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO = 1000259001, + PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES = 1000259002, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES = 1000525000, + PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO = 1000190001, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES = 1000190002, + RENDERING_AREA_INFO = 1000470003, + PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES = 1000232000, + RENDERING_ATTACHMENT_LOCATION_INFO = 1000232001, + RENDERING_INPUT_ATTACHMENT_INDEX_INFO = 1000232002, + SWAPCHAIN_CREATE_INFO_KHR = 1000001000, + PRESENT_INFO_KHR = 1000001001, + DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, + IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008, + BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009, + ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010, + DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011, + DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, + DISPLAY_MODE_CREATE_INFO_KHR = 1000002000, + DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001, + DISPLAY_PRESENT_INFO_KHR = 1000003000, + XLIB_SURFACE_CREATE_INFO_KHR = 1000004000, + XCB_SURFACE_CREATE_INFO_KHR = 1000005000, + WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, + ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, + WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, + DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, + PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000, + DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000, + DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001, + DEBUG_MARKER_MARKER_INFO_EXT = 1000022002, + VIDEO_PROFILE_INFO_KHR = 1000023000, + VIDEO_CAPABILITIES_KHR = 1000023001, + VIDEO_PICTURE_RESOURCE_INFO_KHR = 1000023002, + VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR = 1000023003, + BIND_VIDEO_SESSION_MEMORY_INFO_KHR = 1000023004, + VIDEO_SESSION_CREATE_INFO_KHR = 1000023005, + VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000023006, + VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR = 1000023007, + VIDEO_BEGIN_CODING_INFO_KHR = 1000023008, + VIDEO_END_CODING_INFO_KHR = 1000023009, + VIDEO_CODING_CONTROL_INFO_KHR = 1000023010, + VIDEO_REFERENCE_SLOT_INFO_KHR = 1000023011, + QUEUE_FAMILY_VIDEO_PROPERTIES_KHR = 1000023012, + VIDEO_PROFILE_LIST_INFO_KHR = 1000023013, + PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR = 1000023014, + VIDEO_FORMAT_PROPERTIES_KHR = 1000023015, + QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR = 1000023016, + VIDEO_DECODE_INFO_KHR = 1000024000, + VIDEO_DECODE_CAPABILITIES_KHR = 1000024001, + VIDEO_DECODE_USAGE_INFO_KHR = 1000024002, + DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000, + DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001, + DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002, + PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT = 1000028000, + PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001, + PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002, + CU_MODULE_CREATE_INFO_NVX = 1000029000, + CU_FUNCTION_CREATE_INFO_NVX = 1000029001, + CU_LAUNCH_INFO_NVX = 1000029002, + CU_MODULE_TEXTURING_MODE_CREATE_INFO_NVX = 1000029004, + IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000, + IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001, + VIDEO_ENCODE_H264_CAPABILITIES_KHR = 1000038000, + VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000038001, + VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000038002, + VIDEO_ENCODE_H264_PICTURE_INFO_KHR = 1000038003, + VIDEO_ENCODE_H264_DPB_SLOT_INFO_KHR = 1000038004, + VIDEO_ENCODE_H264_NALU_SLICE_INFO_KHR = 1000038005, + VIDEO_ENCODE_H264_GOP_REMAINING_FRAME_INFO_KHR = 1000038006, + VIDEO_ENCODE_H264_PROFILE_INFO_KHR = 1000038007, + VIDEO_ENCODE_H264_RATE_CONTROL_INFO_KHR = 1000038008, + VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_KHR = 1000038009, + VIDEO_ENCODE_H264_SESSION_CREATE_INFO_KHR = 1000038010, + VIDEO_ENCODE_H264_QUALITY_LEVEL_PROPERTIES_KHR = 1000038011, + VIDEO_ENCODE_H264_SESSION_PARAMETERS_GET_INFO_KHR = 1000038012, + VIDEO_ENCODE_H264_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000038013, + VIDEO_ENCODE_H265_CAPABILITIES_KHR = 1000039000, + VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000039001, + VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000039002, + VIDEO_ENCODE_H265_PICTURE_INFO_KHR = 1000039003, + VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR = 1000039004, + VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR = 1000039005, + VIDEO_ENCODE_H265_GOP_REMAINING_FRAME_INFO_KHR = 1000039006, + VIDEO_ENCODE_H265_PROFILE_INFO_KHR = 1000039007, + VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR = 1000039009, + VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR = 1000039010, + VIDEO_ENCODE_H265_SESSION_CREATE_INFO_KHR = 1000039011, + VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR = 1000039012, + VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR = 1000039013, + VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000039014, + VIDEO_DECODE_H264_CAPABILITIES_KHR = 1000040000, + VIDEO_DECODE_H264_PICTURE_INFO_KHR = 1000040001, + VIDEO_DECODE_H264_PROFILE_INFO_KHR = 1000040003, + VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000040004, + VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR = 1000040005, + VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR = 1000040006, + TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000, + STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000, + PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000, + EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000, + EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001, + IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000, + EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001, + WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000, + VALIDATION_FLAGS_EXT = 1000061000, + VI_SURFACE_CREATE_INFO_NN = 1000062000, + IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000, + PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001, + IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000, + EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001, + MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002, + MEMORY_GET_WIN32_HANDLE_INFO_KHR = 1000073003, + IMPORT_MEMORY_FD_INFO_KHR = 1000074000, + MEMORY_FD_PROPERTIES_KHR = 1000074001, + MEMORY_GET_FD_INFO_KHR = 1000074002, + WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000, + IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000, + EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001, + D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002, + SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR = 1000078003, + IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000, + SEMAPHORE_GET_FD_INFO_KHR = 1000079001, + COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000, + PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001, + CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002, + PRESENT_REGIONS_KHR = 1000084000, + PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000, + SURFACE_CAPABILITIES_2_EXT = 1000090000, + DISPLAY_POWER_INFO_EXT = 1000091000, + DEVICE_EVENT_INFO_EXT = 1000091001, + DISPLAY_EVENT_INFO_EXT = 1000091002, + SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003, + PRESENT_TIMES_INFO_GOOGLE = 1000092000, + PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000, + MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX = 1000044009, + PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000, + PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000, + PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001, + PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT = 1000101000, + PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT = 1000101001, + PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT = 1000102000, + PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT = 1000102001, + HDR_METADATA_EXT = 1000105000, + PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG = 1000110000, + SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000, + IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000, + EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001, + FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002, + IMPORT_FENCE_FD_INFO_KHR = 1000115000, + FENCE_GET_FD_INFO_KHR = 1000115001, + PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR = 1000116000, + PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR = 1000116001, + QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR = 1000116002, + PERFORMANCE_QUERY_SUBMIT_INFO_KHR = 1000116003, + ACQUIRE_PROFILING_LOCK_INFO_KHR = 1000116004, + PERFORMANCE_COUNTER_KHR = 1000116005, + PERFORMANCE_COUNTER_DESCRIPTION_KHR = 1000116006, + PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000, + SURFACE_CAPABILITIES_2_KHR = 1000119001, + SURFACE_FORMAT_2_KHR = 1000119002, + DISPLAY_PROPERTIES_2_KHR = 1000121000, + DISPLAY_PLANE_PROPERTIES_2_KHR = 1000121001, + DISPLAY_MODE_PROPERTIES_2_KHR = 1000121002, + DISPLAY_PLANE_INFO_2_KHR = 1000121003, + DISPLAY_PLANE_CAPABILITIES_2_KHR = 1000121004, + IOS_SURFACE_CREATE_INFO_MVK = 1000122000, + MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, + DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000128000, + DEBUG_UTILS_OBJECT_TAG_INFO_EXT = 1000128001, + DEBUG_UTILS_LABEL_EXT = 1000128002, + DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000128003, + DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000128004, + ANDROID_HARDWARE_BUFFER_USAGE_ANDROID = 1000129000, + ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID = 1000129001, + ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID = 1000129002, + IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, + MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, + EXTERNAL_FORMAT_ANDROID = 1000129005, + ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID = 1000129006, + PHYSICAL_DEVICE_GPA_FEATURES_AMD = 1000133000, + PHYSICAL_DEVICE_GPA_PROPERTIES_AMD = 1000133001, + GPA_SAMPLE_BEGIN_INFO_AMD = 1000133002, + GPA_SESSION_CREATE_INFO_AMD = 1000133003, + GPA_DEVICE_CLOCK_MODE_INFO_AMD = 1000133004, + PHYSICAL_DEVICE_GPA_PROPERTIES_2_AMD = 1000133005, + GPA_DEVICE_GET_CLOCK_INFO_AMD = 1000133006, + PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX = 1000134000, + PHYSICAL_DEVICE_SHADER_ENQUEUE_PROPERTIES_AMDX = 1000134001, + EXECUTION_GRAPH_PIPELINE_SCRATCH_SIZE_AMDX = 1000134002, + EXECUTION_GRAPH_PIPELINE_CREATE_INFO_AMDX = 1000134003, + PIPELINE_SHADER_STAGE_NODE_CREATE_INFO_AMDX = 1000134004, + TEXEL_BUFFER_DESCRIPTOR_INFO_EXT = 1000135000, + IMAGE_DESCRIPTOR_INFO_EXT = 1000135001, + RESOURCE_DESCRIPTOR_INFO_EXT = 1000135002, + BIND_HEAP_INFO_EXT = 1000135003, + PUSH_DATA_INFO_EXT = 1000135004, + DESCRIPTOR_SET_AND_BINDING_MAPPING_EXT = 1000135005, + SHADER_DESCRIPTOR_SET_AND_BINDING_MAPPING_INFO_EXT = 1000135006, + OPAQUE_CAPTURE_DATA_CREATE_INFO_EXT = 1000135007, + PHYSICAL_DEVICE_DESCRIPTOR_HEAP_PROPERTIES_EXT = 1000135008, + PHYSICAL_DEVICE_DESCRIPTOR_HEAP_FEATURES_EXT = 1000135009, + COMMAND_BUFFER_INHERITANCE_DESCRIPTOR_HEAP_INFO_EXT = 1000135010, + SAMPLER_CUSTOM_BORDER_COLOR_INDEX_CREATE_INFO_EXT = 1000135011, + INDIRECT_COMMANDS_LAYOUT_PUSH_DATA_TOKEN_NV = 1000135012, + SUBSAMPLED_IMAGE_FORMAT_PROPERTIES_EXT = 1000135013, + PHYSICAL_DEVICE_DESCRIPTOR_HEAP_TENSOR_PROPERTIES_ARM = 1000135014, + ATTACHMENT_SAMPLE_COUNT_INFO_AMD = 1000044008, + PHYSICAL_DEVICE_SHADER_BFLOAT16_FEATURES_KHR = 1000141000, + SAMPLE_LOCATIONS_INFO_EXT = 1000143000, + RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001, + PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002, + PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003, + MULTISAMPLE_PROPERTIES_EXT = 1000143004, + PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000, + PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001, + PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002, + PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000, + WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000150007, + ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000, + ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002, + ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003, + ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004, + ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005, + ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006, + ACCELERATION_STRUCTURE_VERSION_INFO_KHR = 1000150009, + COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010, + COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011, + COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012, + PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR = 1000150013, + PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR = 1000150014, + ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017, + ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR = 1000150020, + PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR = 1000347000, + PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR = 1000347001, + RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015, + RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016, + RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018, + PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR = 1000348013, + PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000, + PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000, + PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001, + DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT = 1000158000, + PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT = 1000158002, + IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT = 1000158003, + IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT = 1000158004, + IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT = 1000158005, + DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT = 1000158006, + VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000, + SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001, + PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR = 1000163000, + PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR = 1000163001, + PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000, + PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001, + PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002, + PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005, + RAY_TRACING_PIPELINE_CREATE_INFO_NV = 1000165000, + ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000165001, + GEOMETRY_NV = 1000165003, + GEOMETRY_TRIANGLES_NV = 1000165004, + GEOMETRY_AABB_NV = 1000165005, + BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006, + WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007, + ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008, + PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009, + RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011, + ACCELERATION_STRUCTURE_INFO_NV = 1000165012, + PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000, + PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001, + PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT = 1000170000, + FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT = 1000170001, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_CONVERSION_FEATURES_QCOM = 1000172000, + PHYSICAL_DEVICE_ELAPSED_TIMER_QUERY_FEATURES_QCOM = 1000173000, + IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000, + MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001, + PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002, + PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR = 1000181000, + PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD = 1000183000, + PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000, + VIDEO_DECODE_H265_CAPABILITIES_KHR = 1000187000, + VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000187001, + VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR = 1000187002, + VIDEO_DECODE_H265_PROFILE_INFO_KHR = 1000187003, + VIDEO_DECODE_H265_PICTURE_INFO_KHR = 1000187004, + VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR = 1000187005, + DEVICE_MEMORY_OVERALLOCATION_CREATE_INFO_AMD = 1000189000, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000, + PRESENT_FRAME_TOKEN_GGP = 1000191000, + PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000, + PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001, + PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000, + PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000, + PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002, + CHECKPOINT_DATA_NV = 1000206000, + QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001, + QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV = 1000314008, + CHECKPOINT_DATA_2_NV = 1000314009, + PHYSICAL_DEVICE_PRESENT_TIMING_FEATURES_EXT = 1000208000, + SWAPCHAIN_TIMING_PROPERTIES_EXT = 1000208001, + SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT = 1000208002, + PRESENT_TIMINGS_INFO_EXT = 1000208003, + PRESENT_TIMING_INFO_EXT = 1000208004, + PAST_PRESENTATION_TIMING_INFO_EXT = 1000208005, + PAST_PRESENTATION_TIMING_PROPERTIES_EXT = 1000208006, + PAST_PRESENTATION_TIMING_EXT = 1000208007, + PRESENT_TIMING_SURFACE_CAPABILITIES_EXT = 1000208008, + SWAPCHAIN_CALIBRATED_TIMESTAMP_INFO_EXT = 1000208009, + PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000, + QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000, + INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001, + PERFORMANCE_MARKER_INFO_INTEL = 1000210002, + PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003, + PERFORMANCE_OVERRIDE_INFO_INTEL = 1000210004, + PERFORMANCE_CONFIGURATION_ACQUIRE_INFO_INTEL = 1000210005, + PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT = 1000212000, + DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD = 1000213000, + SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD = 1000213001, + IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA = 1000214000, + METAL_SURFACE_CREATE_INFO_EXT = 1000217000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT = 1000218000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT = 1000218001, + RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT = 1000218002, + RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT = 1000044007, + FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000226000, + PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR = 1000226001, + PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR = 1000226002, + PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR = 1000226003, + PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR = 1000226004, + RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR = 1000044006, + PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD = 1000227000, + PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD = 1000229000, + PHYSICAL_DEVICE_SHADER_CONSTANT_DATA_FEATURES_KHR = 1000231000, + PHYSICAL_DEVICE_SHADER_ABORT_FEATURES_KHR = 1000233000, + DEVICE_FAULT_SHADER_ABORT_MESSAGE_INFO_KHR = 1000233001, + PHYSICAL_DEVICE_SHADER_ABORT_PROPERTIES_KHR = 1000233002, + PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT = 1000234000, + PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR = 1000235000, + PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT = 1000237000, + PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT = 1000238000, + MEMORY_PRIORITY_ALLOCATE_INFO_EXT = 1000238001, + SURFACE_PROTECTED_CAPABILITIES_KHR = 1000239000, + PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV = 1000240000, + PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT = 1000244000, + BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT = 1000244002, + VALIDATION_FEATURES_EXT = 1000247000, + PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR = 1000248000, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV = 1000249000, + COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249001, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV = 1000249002, + PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV = 1000250000, + PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV = 1000250001, + FRAMEBUFFER_MIXED_SAMPLES_COMBINATION_NV = 1000250002, + PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT = 1000251000, + PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT = 1000252000, + PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT = 1000254000, + PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT = 1000254001, + PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT = 1000254002, + SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT = 1000255000, + SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT = 1000255002, + SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT = 1000255001, + HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, + PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT = 1000260000, + PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT = 1000267000, + PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000, + PIPELINE_INFO_KHR = 1000269001, + PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002, + PIPELINE_EXECUTABLE_INFO_KHR = 1000269003, + PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004, + PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005, + PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT = 1000272000, + PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT = 1000272001, + MEMORY_MAP_PLACED_INFO_EXT = 1000272002, + PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, + PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000, + GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001, + GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002, + INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003, + INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004, + GENERATED_COMMANDS_INFO_NV = 1000277005, + GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006, + PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007, + PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV = 1000278000, + COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV = 1000278001, + PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, + COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000, + RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001, + PHYSICAL_DEVICE_DEPTH_BIAS_CONTROL_FEATURES_EXT = 1000283000, + DEPTH_BIAS_INFO_EXT = 1000283001, + DEPTH_BIAS_REPRESENTATION_INFO_EXT = 1000283002, + PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT = 1000284000, + DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT = 1000284001, + DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT = 1000284002, + SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT = 1000287000, + PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT = 1000287001, + PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT = 1000287002, + PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_3D_FEATURES_EXT = 1000288000, + PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000, + PHYSICAL_DEVICE_PRESENT_BARRIER_FEATURES_NV = 1000292000, + SURFACE_CAPABILITIES_PRESENT_BARRIER_NV = 1000292001, + SWAPCHAIN_PRESENT_BARRIER_CREATE_INFO_NV = 1000292002, + PRESENT_ID_KHR = 1000294000, + PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR = 1000294001, + VIDEO_ENCODE_INFO_KHR = 1000299000, + VIDEO_ENCODE_RATE_CONTROL_INFO_KHR = 1000299001, + VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR = 1000299002, + VIDEO_ENCODE_CAPABILITIES_KHR = 1000299003, + VIDEO_ENCODE_USAGE_INFO_KHR = 1000299004, + QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR = 1000299005, + PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299006, + VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR = 1000299007, + VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR = 1000299008, + VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR = 1000299009, + VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR = 1000299010, + PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000, + DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001, + PERF_HINT_INFO_QCOM = 1000302000, + PHYSICAL_DEVICE_QUEUE_PERF_HINT_FEATURES_QCOM = 1000302001, + PHYSICAL_DEVICE_QUEUE_PERF_HINT_PROPERTIES_QCOM = 1000302002, + PHYSICAL_DEVICE_IMAGE_PROCESSING_3_FEATURES_QCOM = 1000303000, + PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_FEATURES_QCOM = 1000304000, + PHYSICAL_DEVICE_SHADER_MULTIPLE_WAIT_QUEUES_PROPERTIES_QCOM = 1000304001, + PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_FEATURES_EXT = 1000305000, + PHYSICAL_DEVICE_SHADER_SPLIT_BARRIER_PROPERTIES_EXT = 1000305001, + CUDA_MODULE_CREATE_INFO_NV = 1000307000, + CUDA_FUNCTION_CREATE_INFO_NV = 1000307001, + CUDA_LAUNCH_INFO_NV = 1000307002, + PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_FEATURES_NV = 1000307003, + PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV = 1000307004, + PHYSICAL_DEVICE_TILE_SHADING_FEATURES_QCOM = 1000309000, + PHYSICAL_DEVICE_TILE_SHADING_PROPERTIES_QCOM = 1000309001, + RENDER_PASS_TILE_SHADING_CREATE_INFO_QCOM = 1000309002, + PER_TILE_BEGIN_INFO_QCOM = 1000309003, + PER_TILE_END_INFO_QCOM = 1000309004, + DISPATCH_TILE_INFO_QCOM = 1000309005, + QUERY_LOW_LATENCY_SUPPORT_NV = 1000310000, + EXPORT_METAL_OBJECT_CREATE_INFO_EXT = 1000311000, + EXPORT_METAL_OBJECTS_INFO_EXT = 1000311001, + EXPORT_METAL_DEVICE_INFO_EXT = 1000311002, + EXPORT_METAL_COMMAND_QUEUE_INFO_EXT = 1000311003, + EXPORT_METAL_BUFFER_INFO_EXT = 1000311004, + IMPORT_METAL_BUFFER_INFO_EXT = 1000311005, + EXPORT_METAL_TEXTURE_INFO_EXT = 1000311006, + IMPORT_METAL_TEXTURE_INFO_EXT = 1000311007, + EXPORT_METAL_IO_SURFACE_INFO_EXT = 1000311008, + IMPORT_METAL_IO_SURFACE_INFO_EXT = 1000311009, + EXPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311010, + IMPORT_METAL_SHARED_EVENT_INFO_EXT = 1000311011, + PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT = 1000316000, + PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT = 1000316001, + PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT = 1000316002, + DESCRIPTOR_ADDRESS_INFO_EXT = 1000316003, + DESCRIPTOR_GET_INFO_EXT = 1000316004, + BUFFER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316005, + IMAGE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316006, + IMAGE_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316007, + SAMPLER_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316008, + OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT = 1000316010, + DESCRIPTOR_BUFFER_BINDING_INFO_EXT = 1000316011, + DESCRIPTOR_BUFFER_BINDING_PUSH_DESCRIPTOR_BUFFER_HANDLE_EXT = 1000316012, + ACCELERATION_STRUCTURE_CAPTURE_DESCRIPTOR_DATA_INFO_EXT = 1000316009, + DEVICE_MEMORY_COPY_KHR = 1000318000, + COPY_DEVICE_MEMORY_INFO_KHR = 1000318001, + DEVICE_MEMORY_IMAGE_COPY_KHR = 1000318002, + COPY_DEVICE_MEMORY_IMAGE_INFO_KHR = 1000318003, + MEMORY_RANGE_BARRIERS_INFO_KHR = 1000318004, + MEMORY_RANGE_BARRIER_KHR = 1000318005, + PHYSICAL_DEVICE_DEVICE_ADDRESS_COMMANDS_FEATURES_KHR = 1000318006, + BIND_INDEX_BUFFER_3_INFO_KHR = 1000318007, + BIND_VERTEX_BUFFER_3_INFO_KHR = 1000318008, + DRAW_INDIRECT_2_INFO_KHR = 1000318009, + DRAW_INDIRECT_COUNT_2_INFO_KHR = 1000318010, + DISPATCH_INDIRECT_2_INFO_KHR = 1000318011, + CONDITIONAL_RENDERING_BEGIN_INFO_2_EXT = 1000318012, + BIND_TRANSFORM_FEEDBACK_BUFFER_2_INFO_EXT = 1000318013, + MEMORY_MARKER_INFO_AMD = 1000318014, + ACCELERATION_STRUCTURE_CREATE_INFO_2_KHR = 1000318015, + PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT = 1000320000, + PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT = 1000320001, + GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT = 1000320002, + PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD = 1000321000, + PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR = 1000203000, + PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR = 1000322000, + PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR = 1000323000, + PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV = 1000326000, + PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV = 1000326001, + PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV = 1000326002, + ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV = 1000327000, + PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV = 1000327001, + ACCELERATION_STRUCTURE_MOTION_INFO_NV = 1000327002, + PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT = 1000328000, + PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT = 1000328001, + PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT = 1000330000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT = 1000332000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT = 1000332001, + COPY_COMMAND_TRANSFORM_INFO_QCOM = 1000333000, + PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR = 1000336000, + PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT = 1000338000, + IMAGE_COMPRESSION_CONTROL_EXT = 1000338001, + IMAGE_COMPRESSION_PROPERTIES_EXT = 1000338004, + PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT = 1000339000, + PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT = 1000340000, + PHYSICAL_DEVICE_FAULT_FEATURES_EXT = 1000341000, + DEVICE_FAULT_COUNTS_EXT = 1000341001, + DEVICE_FAULT_INFO_EXT = 1000341002, + PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT = 1000344000, + DIRECTFB_SURFACE_CREATE_INFO_EXT = 1000346000, + PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT = 1000352000, + VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT = 1000352001, + VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT = 1000352002, + PHYSICAL_DEVICE_DRM_PROPERTIES_EXT = 1000353000, + PHYSICAL_DEVICE_ADDRESS_BINDING_REPORT_FEATURES_EXT = 1000354000, + DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT = 1000354001, + PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT = 1000355000, + PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT = 1000355001, + PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT = 1000356000, + IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364000, + MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA = 1000364001, + MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000364002, + IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365000, + SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA = 1000365001, + BUFFER_COLLECTION_CREATE_INFO_FUCHSIA = 1000366000, + IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA = 1000366001, + BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA = 1000366002, + BUFFER_COLLECTION_PROPERTIES_FUCHSIA = 1000366003, + BUFFER_CONSTRAINTS_INFO_FUCHSIA = 1000366004, + BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA = 1000366005, + IMAGE_CONSTRAINTS_INFO_FUCHSIA = 1000366006, + IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA = 1000366007, + SYSMEM_COLOR_SPACE_FUCHSIA = 1000366008, + BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA = 1000366009, + SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI = 1000369000, + PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI = 1000369001, + PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI = 1000369002, + PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI = 1000370000, + MEMORY_GET_REMOTE_ADDRESS_INFO_NV = 1000371000, + PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV = 1000371001, + PIPELINE_PROPERTIES_IDENTIFIER_EXT = 1000372000, + PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT = 1000372001, + PHYSICAL_DEVICE_FRAME_BOUNDARY_FEATURES_EXT = 1000375000, + FRAME_BOUNDARY_EXT = 1000375001, + PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT = 1000376000, + SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT = 1000376001, + MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT = 1000376002, + PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT = 1000377000, + SCREEN_SURFACE_CREATE_INFO_QNX = 1000378000, + PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT = 1000381000, + PIPELINE_COLOR_WRITE_CREATE_INFO_EXT = 1000381001, + PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT = 1000382000, + PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR = 1000386000, + PHYSICAL_DEVICE_SHADER_UNTYPED_POINTERS_FEATURES_KHR = 1000387000, + PHYSICAL_DEVICE_VIDEO_ENCODE_RGB_CONVERSION_FEATURES_VALVE = 1000390000, + VIDEO_ENCODE_RGB_CONVERSION_CAPABILITIES_VALVE = 1000390001, + VIDEO_ENCODE_PROFILE_RGB_CONVERSION_INFO_VALVE = 1000390002, + VIDEO_ENCODE_SESSION_RGB_CONVERSION_CREATE_INFO_VALVE = 1000390003, + PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT = 1000391000, + IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT = 1000391001, + PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT = 1000392000, + PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT = 1000392001, + PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT = 1000393000, + PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT = 1000395000, + PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT = 1000395001, + MICROMAP_BUILD_INFO_EXT = 1000396000, + MICROMAP_VERSION_INFO_EXT = 1000396001, + COPY_MICROMAP_INFO_EXT = 1000396002, + COPY_MICROMAP_TO_MEMORY_INFO_EXT = 1000396003, + COPY_MEMORY_TO_MICROMAP_INFO_EXT = 1000396004, + PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_EXT = 1000396005, + PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT = 1000396006, + MICROMAP_CREATE_INFO_EXT = 1000396007, + MICROMAP_BUILD_SIZES_INFO_EXT = 1000396008, + ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_EXT = 1000396009, + PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_FEATURES_NV = 1000397000, + PHYSICAL_DEVICE_DISPLACEMENT_MICROMAP_PROPERTIES_NV = 1000397001, + ACCELERATION_STRUCTURE_TRIANGLES_DISPLACEMENT_MICROMAP_NV = 1000397002, + PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_FEATURES_HUAWEI = 1000404000, + PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_PROPERTIES_HUAWEI = 1000404001, + PHYSICAL_DEVICE_CLUSTER_CULLING_SHADER_VRS_FEATURES_HUAWEI = 1000404002, + PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT = 1000411000, + SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT = 1000411001, + PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT = 1000412000, + PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM = 1000415000, + DEVICE_QUEUE_SHADER_CORE_CONTROL_CREATE_INFO_ARM = 1000417000, + PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM = 1000417001, + PHYSICAL_DEVICE_SCHEDULING_CONTROLS_PROPERTIES_ARM = 1000417002, + DISPATCH_PARAMETERS_ARM = 1000417003, + PHYSICAL_DEVICE_SCHEDULING_CONTROLS_DISPATCH_PARAMETERS_PROPERTIES_ARM = 1000417004, + PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT = 1000418000, + IMAGE_VIEW_SLICED_CREATE_INFO_EXT = 1000418001, + PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE = 1000420000, + DESCRIPTOR_SET_BINDING_REFERENCE_VALVE = 1000420001, + DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE = 1000420002, + PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT = 1000422000, + PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM = 1000424000, + PHYSICAL_DEVICE_RENDER_PASS_STRIPED_PROPERTIES_ARM = 1000424001, + RENDER_PASS_STRIPE_BEGIN_INFO_ARM = 1000424002, + RENDER_PASS_STRIPE_INFO_ARM = 1000424003, + RENDER_PASS_STRIPE_SUBMIT_INFO_ARM = 1000424004, + PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV = 1000426000, + PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_COMPUTE_FEATURES_NV = 1000428000, + COMPUTE_PIPELINE_INDIRECT_BUFFER_INFO_NV = 1000428001, + PIPELINE_INDIRECT_DEVICE_ADDRESS_INFO_NV = 1000428002, + PHYSICAL_DEVICE_RAY_TRACING_LINEAR_SWEPT_SPHERES_FEATURES_NV = 1000429008, + ACCELERATION_STRUCTURE_GEOMETRY_LINEAR_SWEPT_SPHERES_DATA_NV = 1000429009, + ACCELERATION_STRUCTURE_GEOMETRY_SPHERES_DATA_NV = 1000429010, + PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV = 1000430000, + PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR = 1000434000, + PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT = 1000437000, + PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM = 1000440000, + PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM = 1000440001, + IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM = 1000440002, + PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT = 1000451000, + PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT = 1000451001, + NATIVE_BUFFER_USAGE_OHOS = 1000452000, + NATIVE_BUFFER_PROPERTIES_OHOS = 1000452001, + NATIVE_BUFFER_FORMAT_PROPERTIES_OHOS = 1000452002, + IMPORT_NATIVE_BUFFER_INFO_OHOS = 1000452003, + MEMORY_GET_NATIVE_BUFFER_INFO_OHOS = 1000452004, + EXTERNAL_FORMAT_OHOS = 1000452005, + EXTERNAL_MEMORY_ACQUIRE_UNMODIFIED_EXT = 1000453000, + PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT = 1000455000, + PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT = 1000455001, + PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT = 1000458000, + RENDER_PASS_CREATION_CONTROL_EXT = 1000458001, + RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT = 1000458002, + RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT = 1000458003, + DIRECT_DRIVER_LOADING_INFO_LUNARG = 1000459000, + DIRECT_DRIVER_LOADING_LIST_LUNARG = 1000459001, + TENSOR_CREATE_INFO_ARM = 1000460000, + TENSOR_VIEW_CREATE_INFO_ARM = 1000460001, + BIND_TENSOR_MEMORY_INFO_ARM = 1000460002, + WRITE_DESCRIPTOR_SET_TENSOR_ARM = 1000460003, + PHYSICAL_DEVICE_TENSOR_PROPERTIES_ARM = 1000460004, + TENSOR_FORMAT_PROPERTIES_ARM = 1000460005, + TENSOR_DESCRIPTION_ARM = 1000460006, + TENSOR_MEMORY_REQUIREMENTS_INFO_ARM = 1000460007, + TENSOR_MEMORY_BARRIER_ARM = 1000460008, + PHYSICAL_DEVICE_TENSOR_FEATURES_ARM = 1000460009, + DEVICE_TENSOR_MEMORY_REQUIREMENTS_ARM = 1000460010, + COPY_TENSOR_INFO_ARM = 1000460011, + TENSOR_COPY_ARM = 1000460012, + TENSOR_DEPENDENCY_INFO_ARM = 1000460013, + MEMORY_DEDICATED_ALLOCATE_INFO_TENSOR_ARM = 1000460014, + PHYSICAL_DEVICE_EXTERNAL_TENSOR_INFO_ARM = 1000460015, + EXTERNAL_TENSOR_PROPERTIES_ARM = 1000460016, + EXTERNAL_MEMORY_TENSOR_CREATE_INFO_ARM = 1000460017, + PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_FEATURES_ARM = 1000460018, + PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_TENSOR_PROPERTIES_ARM = 1000460019, + DESCRIPTOR_GET_TENSOR_INFO_ARM = 1000460020, + TENSOR_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460021, + TENSOR_VIEW_CAPTURE_DESCRIPTOR_DATA_INFO_ARM = 1000460022, + FRAME_BOUNDARY_TENSORS_ARM = 1000460023, + PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT = 1000462000, + PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT = 1000462001, + PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT = 1000462002, + SHADER_MODULE_IDENTIFIER_EXT = 1000462003, + PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT = 1000342000, + PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV = 1000464000, + PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV = 1000464001, + OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV = 1000464002, + OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV = 1000464003, + OPTICAL_FLOW_SESSION_CREATE_INFO_NV = 1000464004, + OPTICAL_FLOW_EXECUTE_INFO_NV = 1000464005, + OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010, + PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000, + PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_FEATURES_ANDROID = 1000468000, + PHYSICAL_DEVICE_EXTERNAL_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468001, + ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID = 1000468002, + PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD = 1000476000, + ANTI_LAG_DATA_AMD = 1000476001, + ANTI_LAG_PRESENTATION_INFO_AMD = 1000476002, + PHYSICAL_DEVICE_DENSE_GEOMETRY_FORMAT_FEATURES_AMDX = 1000478000, + ACCELERATION_STRUCTURE_DENSE_GEOMETRY_FORMAT_TRIANGLES_DATA_AMDX = 1000478001, + SURFACE_CAPABILITIES_PRESENT_ID_2_KHR = 1000479000, + PRESENT_ID_2_KHR = 1000479001, + PHYSICAL_DEVICE_PRESENT_ID_2_FEATURES_KHR = 1000479002, + SURFACE_CAPABILITIES_PRESENT_WAIT_2_KHR = 1000480000, + PHYSICAL_DEVICE_PRESENT_WAIT_2_FEATURES_KHR = 1000480001, + PRESENT_WAIT_2_INFO_KHR = 1000480002, + PHYSICAL_DEVICE_RAY_TRACING_POSITION_FETCH_FEATURES_KHR = 1000481000, + PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT = 1000482000, + PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT = 1000482001, + SHADER_CREATE_INFO_EXT = 1000482002, + PHYSICAL_DEVICE_PIPELINE_BINARY_FEATURES_KHR = 1000483000, + PIPELINE_BINARY_CREATE_INFO_KHR = 1000483001, + PIPELINE_BINARY_INFO_KHR = 1000483002, + PIPELINE_BINARY_KEY_KHR = 1000483003, + PHYSICAL_DEVICE_PIPELINE_BINARY_PROPERTIES_KHR = 1000483004, + RELEASE_CAPTURED_PIPELINE_DATA_INFO_KHR = 1000483005, + PIPELINE_BINARY_DATA_INFO_KHR = 1000483006, + PIPELINE_CREATE_INFO_KHR = 1000483007, + DEVICE_PIPELINE_BINARY_INTERNAL_CACHE_CONTROL_KHR = 1000483008, + PIPELINE_BINARY_HANDLES_INFO_KHR = 1000483009, + PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000, + TILE_PROPERTIES_QCOM = 1000484001, + PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000, + AMIGO_PROFILING_SUBMIT_INFO_SEC = 1000485001, + SURFACE_PRESENT_MODE_KHR = 1000274000, + SURFACE_PRESENT_SCALING_CAPABILITIES_KHR = 1000274001, + SURFACE_PRESENT_MODE_COMPATIBILITY_KHR = 1000274002, + PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR = 1000275000, + SWAPCHAIN_PRESENT_FENCE_INFO_KHR = 1000275001, + SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR = 1000275002, + SWAPCHAIN_PRESENT_MODE_INFO_KHR = 1000275003, + SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR = 1000275004, + RELEASE_SWAPCHAIN_IMAGES_INFO_KHR = 1000275005, + PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_VIEWPORTS_FEATURES_QCOM = 1000488000, + PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_NV = 1000490000, + PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_NV = 1000490001, + PHYSICAL_DEVICE_COOPERATIVE_VECTOR_FEATURES_NV = 1000491000, + PHYSICAL_DEVICE_COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491001, + COOPERATIVE_VECTOR_PROPERTIES_NV = 1000491002, + CONVERT_COOPERATIVE_VECTOR_MATRIX_INFO_NV = 1000491004, + PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_FEATURES_NV = 1000492000, + PHYSICAL_DEVICE_EXTENDED_SPARSE_ADDRESS_SPACE_PROPERTIES_NV = 1000492001, + PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT = 1000351000, + MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT = 1000351002, + PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_FEATURES_EXT = 1000495000, + PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_PROPERTIES_EXT = 1000495001, + LAYER_SETTINGS_CREATE_INFO_EXT = 1000496000, + PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_FEATURES_ARM = 1000497000, + PHYSICAL_DEVICE_SHADER_CORE_BUILTINS_PROPERTIES_ARM = 1000497001, + PHYSICAL_DEVICE_PIPELINE_LIBRARY_GROUP_HANDLES_FEATURES_EXT = 1000498000, + PHYSICAL_DEVICE_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_FEATURES_EXT = 1000499000, + PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR = 1000504000, + LATENCY_SLEEP_MODE_INFO_NV = 1000505000, + LATENCY_SLEEP_INFO_NV = 1000505001, + SET_LATENCY_MARKER_INFO_NV = 1000505002, + GET_LATENCY_MARKER_INFO_NV = 1000505003, + LATENCY_TIMINGS_FRAME_REPORT_NV = 1000505004, + LATENCY_SUBMISSION_PRESENT_ID_NV = 1000505005, + OUT_OF_BAND_QUEUE_TYPE_INFO_NV = 1000505006, + SWAPCHAIN_LATENCY_CREATE_INFO_NV = 1000505007, + LATENCY_SURFACE_CAPABILITIES_NV = 1000505008, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR = 1000506000, + COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506001, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR = 1000506002, + DATA_GRAPH_PIPELINE_CREATE_INFO_ARM = 1000507000, + DATA_GRAPH_PIPELINE_SESSION_CREATE_INFO_ARM = 1000507001, + DATA_GRAPH_PIPELINE_RESOURCE_INFO_ARM = 1000507002, + DATA_GRAPH_PIPELINE_CONSTANT_ARM = 1000507003, + DATA_GRAPH_PIPELINE_SESSION_MEMORY_REQUIREMENTS_INFO_ARM = 1000507004, + BIND_DATA_GRAPH_PIPELINE_SESSION_MEMORY_INFO_ARM = 1000507005, + PHYSICAL_DEVICE_DATA_GRAPH_FEATURES_ARM = 1000507006, + DATA_GRAPH_PIPELINE_SHADER_MODULE_CREATE_INFO_ARM = 1000507007, + DATA_GRAPH_PIPELINE_PROPERTY_QUERY_RESULT_ARM = 1000507008, + DATA_GRAPH_PIPELINE_INFO_ARM = 1000507009, + DATA_GRAPH_PIPELINE_COMPILER_CONTROL_CREATE_INFO_ARM = 1000507010, + DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENTS_INFO_ARM = 1000507011, + DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_REQUIREMENT_ARM = 1000507012, + DATA_GRAPH_PIPELINE_IDENTIFIER_CREATE_INFO_ARM = 1000507013, + DATA_GRAPH_PIPELINE_DISPATCH_INFO_ARM = 1000507014, + DATA_GRAPH_PROCESSING_ENGINE_CREATE_INFO_ARM = 1000507016, + QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_PROPERTIES_ARM = 1000507017, + QUEUE_FAMILY_DATA_GRAPH_PROPERTIES_ARM = 1000507018, + PHYSICAL_DEVICE_QUEUE_FAMILY_DATA_GRAPH_PROCESSING_ENGINE_INFO_ARM = 1000507019, + DATA_GRAPH_PIPELINE_CONSTANT_TENSOR_SEMI_STRUCTURED_SPARSITY_INFO_ARM = 1000507015, + QUEUE_FAMILY_DATA_GRAPH_TOSA_PROPERTIES_ARM = 1000508000, + PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_RENDER_AREAS_FEATURES_QCOM = 1000510000, + MULTIVIEW_PER_VIEW_RENDER_AREAS_RENDER_PASS_BEGIN_INFO_QCOM = 1000510001, + PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR = 1000201000, + PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_PROPERTIES_KHR = 1000511000, + VIDEO_DECODE_AV1_CAPABILITIES_KHR = 1000512000, + VIDEO_DECODE_AV1_PICTURE_INFO_KHR = 1000512001, + VIDEO_DECODE_AV1_PROFILE_INFO_KHR = 1000512003, + VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000512004, + VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR = 1000512005, + VIDEO_ENCODE_AV1_CAPABILITIES_KHR = 1000513000, + VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000513001, + VIDEO_ENCODE_AV1_PICTURE_INFO_KHR = 1000513002, + VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR = 1000513003, + PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR = 1000513004, + VIDEO_ENCODE_AV1_PROFILE_INFO_KHR = 1000513005, + VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR = 1000513006, + VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR = 1000513007, + VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR = 1000513008, + VIDEO_ENCODE_AV1_SESSION_CREATE_INFO_KHR = 1000513009, + VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR = 1000513010, + PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR = 1000514000, + VIDEO_DECODE_VP9_CAPABILITIES_KHR = 1000514001, + VIDEO_DECODE_VP9_PICTURE_INFO_KHR = 1000514002, + VIDEO_DECODE_VP9_PROFILE_INFO_KHR = 1000514003, + PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR = 1000515000, + VIDEO_INLINE_QUERY_INFO_KHR = 1000515001, + PHYSICAL_DEVICE_PER_STAGE_DESCRIPTOR_SET_FEATURES_NV = 1000516000, + PHYSICAL_DEVICE_IMAGE_PROCESSING_2_FEATURES_QCOM = 1000518000, + PHYSICAL_DEVICE_IMAGE_PROCESSING_2_PROPERTIES_QCOM = 1000518001, + SAMPLER_BLOCK_MATCH_WINDOW_CREATE_INFO_QCOM = 1000518002, + SAMPLER_CUBIC_WEIGHTS_CREATE_INFO_QCOM = 1000519000, + PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM = 1000519001, + BLIT_IMAGE_CUBIC_WEIGHTS_INFO_QCOM = 1000519002, + PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM = 1000520000, + SAMPLER_YCBCR_CONVERSION_YCBCR_DEGAMMA_CREATE_INFO_QCOM = 1000520001, + PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM = 1000521000, + PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT = 1000524000, + PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR = 1000527000, + ATTACHMENT_FEEDBACK_LOOP_INFO_EXT = 1000527001, + SCREEN_BUFFER_PROPERTIES_QNX = 1000529000, + SCREEN_BUFFER_FORMAT_PROPERTIES_QNX = 1000529001, + IMPORT_SCREEN_BUFFER_INFO_QNX = 1000529002, + EXTERNAL_FORMAT_QNX = 1000529003, + PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX = 1000529004, + PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT = 1000530000, + CALIBRATED_TIMESTAMP_INFO_KHR = 1000184000, + SET_DESCRIPTOR_BUFFER_OFFSETS_INFO_EXT = 1000545007, + BIND_DESCRIPTOR_BUFFER_EMBEDDED_SAMPLERS_INFO_EXT = 1000545008, + PHYSICAL_DEVICE_DESCRIPTOR_POOL_OVERALLOCATION_FEATURES_NV = 1000546000, + PHYSICAL_DEVICE_TILE_MEMORY_HEAP_FEATURES_QCOM = 1000547000, + PHYSICAL_DEVICE_TILE_MEMORY_HEAP_PROPERTIES_QCOM = 1000547001, + TILE_MEMORY_REQUIREMENTS_QCOM = 1000547002, + TILE_MEMORY_BIND_INFO_QCOM = 1000547003, + TILE_MEMORY_SIZE_INFO_QCOM = 1000547004, + PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_KHR = 1000549000, + PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR = 1000426001, + COPY_MEMORY_INDIRECT_INFO_KHR = 1000549002, + COPY_MEMORY_TO_IMAGE_INDIRECT_INFO_KHR = 1000549003, + PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT = 1000427000, + PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT = 1000427001, + DECOMPRESS_MEMORY_INFO_EXT = 1000550002, + DISPLAY_SURFACE_STEREO_CREATE_INFO_NV = 1000551000, + DISPLAY_MODE_STEREO_PROPERTIES_NV = 1000551001, + VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR = 1000552000, + VIDEO_ENCODE_SESSION_INTRA_REFRESH_CREATE_INFO_KHR = 1000552001, + VIDEO_ENCODE_INTRA_REFRESH_INFO_KHR = 1000552002, + VIDEO_REFERENCE_INTRA_REFRESH_INFO_KHR = 1000552003, + PHYSICAL_DEVICE_VIDEO_ENCODE_INTRA_REFRESH_FEATURES_KHR = 1000552004, + VIDEO_ENCODE_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553000, + VIDEO_FORMAT_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553001, + VIDEO_ENCODE_QUANTIZATION_MAP_INFO_KHR = 1000553002, + VIDEO_ENCODE_QUANTIZATION_MAP_SESSION_PARAMETERS_CREATE_INFO_KHR = 1000553005, + PHYSICAL_DEVICE_VIDEO_ENCODE_QUANTIZATION_MAP_FEATURES_KHR = 1000553009, + VIDEO_ENCODE_H264_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553003, + VIDEO_ENCODE_H265_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553004, + VIDEO_FORMAT_H265_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553006, + VIDEO_ENCODE_AV1_QUANTIZATION_MAP_CAPABILITIES_KHR = 1000553007, + VIDEO_FORMAT_AV1_QUANTIZATION_MAP_PROPERTIES_KHR = 1000553008, + PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV = 1000555000, + EXTERNAL_COMPUTE_QUEUE_DEVICE_CREATE_INFO_NV = 1000556000, + EXTERNAL_COMPUTE_QUEUE_CREATE_INFO_NV = 1000556001, + EXTERNAL_COMPUTE_QUEUE_DATA_PARAMS_NV = 1000556002, + PHYSICAL_DEVICE_EXTERNAL_COMPUTE_QUEUE_PROPERTIES_NV = 1000556003, + PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR = 1000558000, + PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV = 1000559000, + PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR = 1000562000, + PHYSICAL_DEVICE_MAINTENANCE_7_PROPERTIES_KHR = 1000562001, + PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_LIST_KHR = 1000562002, + PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_KHR = 1000562003, + PHYSICAL_DEVICE_LAYERED_API_VULKAN_PROPERTIES_KHR = 1000562004, + PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV = 1000563000, + PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT = 1000564000, + PHYSICAL_DEVICE_SHADER_FLOAT8_FEATURES_EXT = 1000567000, + PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV = 1000568000, + PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_FEATURES_NV = 1000569000, + PHYSICAL_DEVICE_CLUSTER_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000569001, + CLUSTER_ACCELERATION_STRUCTURE_CLUSTERS_BOTTOM_LEVEL_INPUT_NV = 1000569002, + CLUSTER_ACCELERATION_STRUCTURE_TRIANGLE_CLUSTER_INPUT_NV = 1000569003, + CLUSTER_ACCELERATION_STRUCTURE_MOVE_OBJECTS_INPUT_NV = 1000569004, + CLUSTER_ACCELERATION_STRUCTURE_INPUT_INFO_NV = 1000569005, + CLUSTER_ACCELERATION_STRUCTURE_COMMANDS_INFO_NV = 1000569006, + RAY_TRACING_PIPELINE_CLUSTER_ACCELERATION_STRUCTURE_CREATE_INFO_NV = 1000569007, + PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_FEATURES_NV = 1000570000, + PHYSICAL_DEVICE_PARTITIONED_ACCELERATION_STRUCTURE_PROPERTIES_NV = 1000570001, + WRITE_DESCRIPTOR_SET_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570002, + PARTITIONED_ACCELERATION_STRUCTURE_INSTANCES_INPUT_NV = 1000570003, + BUILD_PARTITIONED_ACCELERATION_STRUCTURE_INFO_NV = 1000570004, + PARTITIONED_ACCELERATION_STRUCTURE_FLAGS_NV = 1000570005, + PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_EXT = 1000572000, + PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT = 1000572001, + GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_EXT = 1000572002, + INDIRECT_EXECUTION_SET_CREATE_INFO_EXT = 1000572003, + GENERATED_COMMANDS_INFO_EXT = 1000572004, + INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_EXT = 1000572006, + INDIRECT_COMMANDS_LAYOUT_TOKEN_EXT = 1000572007, + WRITE_INDIRECT_EXECUTION_SET_PIPELINE_EXT = 1000572008, + WRITE_INDIRECT_EXECUTION_SET_SHADER_EXT = 1000572009, + INDIRECT_EXECUTION_SET_PIPELINE_INFO_EXT = 1000572010, + INDIRECT_EXECUTION_SET_SHADER_INFO_EXT = 1000572011, + INDIRECT_EXECUTION_SET_SHADER_LAYOUT_INFO_EXT = 1000572012, + GENERATED_COMMANDS_PIPELINE_INFO_EXT = 1000572013, + GENERATED_COMMANDS_SHADER_INFO_EXT = 1000572014, + PHYSICAL_DEVICE_FAULT_FEATURES_KHR = 1000573000, + PHYSICAL_DEVICE_FAULT_PROPERTIES_KHR = 1000573001, + DEVICE_FAULT_INFO_KHR = 1000573002, + DEVICE_FAULT_DEBUG_INFO_KHR = 1000573003, + PHYSICAL_DEVICE_MAINTENANCE_8_FEATURES_KHR = 1000574000, + MEMORY_BARRIER_ACCESS_FLAGS_3_KHR = 1000574002, + PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA = 1000575000, + PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_PROPERTIES_MESA = 1000575001, + IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA = 1000575002, + PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR = 1000579000, + PUSH_CONSTANT_BANK_INFO_NV = 1000580000, + PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_FEATURES_NV = 1000580001, + PHYSICAL_DEVICE_PUSH_CONSTANT_BANK_PROPERTIES_NV = 1000580002, + PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_FEATURES_EXT = 1000581000, + PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_EXT = 1000581001, + PHYSICAL_DEVICE_DEPTH_CLAMP_CONTROL_FEATURES_EXT = 1000582000, + PIPELINE_VIEWPORT_DEPTH_CLAMP_CONTROL_CREATE_INFO_EXT = 1000582001, + PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR = 1000584000, + PHYSICAL_DEVICE_MAINTENANCE_9_PROPERTIES_KHR = 1000584001, + QUEUE_FAMILY_OWNERSHIP_TRANSFER_PROPERTIES_KHR = 1000584002, + PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR = 1000586000, + VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586001, + VIDEO_DECODE_H265_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586002, + VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR = 1000586003, + SURFACE_CREATE_INFO_OHOS = 1000685000, + PHYSICAL_DEVICE_HDR_VIVID_FEATURES_HUAWEI = 1000590000, + HDR_VIVID_DYNAMIC_METADATA_HUAWEI = 1000590001, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_FEATURES_NV = 1000593000, + COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV = 1000593001, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_2_PROPERTIES_NV = 1000593002, + PHYSICAL_DEVICE_PIPELINE_OPACITY_MICROMAP_FEATURES_ARM = 1000596000, + PHYSICAL_DEVICE_VIDEO_ENCODE_FEEDBACK_2_FEATURES_KHR = 1000598000, + VIDEO_ENCODE_FEEDBACK_2_CAPABILITIES_KHR = 1000598001, + QUERY_POOL_VIDEO_ENCODE_PER_PARTITION_FEEDBACK_CREATE_INFO_KHR = 1000598002, + IMPORT_MEMORY_METAL_HANDLE_INFO_EXT = 1000602000, + MEMORY_METAL_HANDLE_PROPERTIES_EXT = 1000602001, + MEMORY_GET_METAL_HANDLE_INFO_EXT = 1000602002, + PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR = 1000421000, + PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_FEATURES_ARM = 1000605000, + PHYSICAL_DEVICE_PERFORMANCE_COUNTERS_BY_REGION_PROPERTIES_ARM = 1000605001, + PERFORMANCE_COUNTER_ARM = 1000605002, + PERFORMANCE_COUNTER_DESCRIPTION_ARM = 1000605003, + RENDER_PASS_PERFORMANCE_COUNTERS_BY_REGION_BEGIN_INFO_ARM = 1000605004, + PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_FEATURES_ARM = 1000607000, + PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_PROPERTIES_ARM = 1000607001, + SHADER_INSTRUMENTATION_CREATE_INFO_ARM = 1000607002, + SHADER_INSTRUMENTATION_METRIC_DESCRIPTION_ARM = 1000607003, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_ROBUSTNESS_FEATURES_EXT = 1000608000, + PHYSICAL_DEVICE_FORMAT_PACK_FEATURES_ARM = 1000609000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_FEATURES_VALVE = 1000611000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_LAYERED_PROPERTIES_VALVE = 1000611001, + PIPELINE_FRAGMENT_DENSITY_MAP_LAYERED_CREATE_INFO_VALVE = 1000611002, + PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR = 1000286000, + PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR = 1000286001, + SET_PRESENT_CONFIG_NV = 1000613000, + PHYSICAL_DEVICE_PRESENT_METERING_FEATURES_NV = 1000613001, + PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SWAPCHAIN_FEATURES_EXT = 1000616000, + SWAPCHAIN_FLAGS_SURFACE_CAPABILITIES_EXT = 1000616001, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT = 1000425000, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT = 1000425001, + RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT = 1000425002, + PHYSICAL_DEVICE_ZERO_INITIALIZE_DEVICE_MEMORY_FEATURES_EXT = 1000620000, + PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR = 1000361000, + PHYSICAL_DEVICE_OPACITY_MICROMAP_FEATURES_KHR = 1000623000, + PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_KHR = 1000623001, + ACCELERATION_STRUCTURE_GEOMETRY_MICROMAP_DATA_KHR = 1000623002, + ACCELERATION_STRUCTURE_TRIANGLES_OPACITY_MICROMAP_KHR = 1000623003, + PHYSICAL_DEVICE_SHADER_64_BIT_INDEXING_FEATURES_EXT = 1000627000, + PHYSICAL_DEVICE_CUSTOM_RESOLVE_FEATURES_EXT = 1000628000, + BEGIN_CUSTOM_RESOLVE_INFO_EXT = 1000628001, + CUSTOM_RESOLVE_CREATE_INFO_EXT = 1000628002, + PHYSICAL_DEVICE_DATA_GRAPH_MODEL_FEATURES_QCOM = 1000629000, + DATA_GRAPH_PIPELINE_BUILTIN_MODEL_CREATE_INFO_QCOM = 1000629001, + PHYSICAL_DEVICE_MAINTENANCE_10_FEATURES_KHR = 1000630000, + PHYSICAL_DEVICE_MAINTENANCE_10_PROPERTIES_KHR = 1000630001, + RENDERING_ATTACHMENT_FLAGS_INFO_KHR = 1000630002, + RENDERING_END_INFO_KHR = 1000619003, + RESOLVE_IMAGE_MODE_INFO_KHR = 1000630004, + PHYSICAL_DEVICE_DATA_GRAPH_OPTICAL_FLOW_FEATURES_ARM = 1000631000, + QUEUE_FAMILY_DATA_GRAPH_OPTICAL_FLOW_PROPERTIES_ARM = 1000631001, + DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_INFO_ARM = 1000631003, + DATA_GRAPH_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_ARM = 1000631004, + DATA_GRAPH_PIPELINE_OPTICAL_FLOW_DISPATCH_INFO_ARM = 1000631005, + DATA_GRAPH_PIPELINE_OPTICAL_FLOW_CREATE_INFO_ARM = 1000631002, + DATA_GRAPH_PIPELINE_RESOURCE_INFO_IMAGE_LAYOUT_ARM = 1000631006, + DATA_GRAPH_PIPELINE_SINGLE_NODE_CREATE_INFO_ARM = 1000631007, + DATA_GRAPH_PIPELINE_SINGLE_NODE_CONNECTION_ARM = 1000631008, + PHYSICAL_DEVICE_SHADER_LONG_VECTOR_FEATURES_EXT = 1000635000, + PHYSICAL_DEVICE_SHADER_LONG_VECTOR_PROPERTIES_EXT = 1000635001, + PHYSICAL_DEVICE_PIPELINE_CACHE_INCREMENTAL_MODE_FEATURES_SEC = 1000637000, + PHYSICAL_DEVICE_SHADER_UNIFORM_BUFFER_UNSIZED_ARRAY_FEATURES_EXT = 1000642000, + COMPUTE_OCCUPANCY_PRIORITY_PARAMETERS_NV = 1000645000, + PHYSICAL_DEVICE_COMPUTE_OCCUPANCY_PRIORITY_FEATURES_NV = 1000645001, + PHYSICAL_DEVICE_MAINTENANCE_11_FEATURES_KHR = 1000657000, + QUEUE_FAMILY_OPTIMAL_IMAGE_TRANSFER_GRANULARITY_PROPERTIES_KHR = 1000657001, + PHYSICAL_DEVICE_SHADER_SUBGROUP_PARTITIONED_FEATURES_EXT = 1000662000, + UBM_SURFACE_CREATE_INFO_SEC = 1000664000, + FORMAT_PROPERTIES_4_KHR = 1000668000, + IMAGE_CREATE_FLAGS_2_CREATE_INFO_KHR = 1000668001, + IMAGE_USAGE_FLAGS_2_CREATE_INFO_KHR = 1000668002, + IMAGE_VIEW_USAGE_2_CREATE_INFO_KHR = 1000668003, + PHYSICAL_DEVICE_EXTENDED_FLAGS_FEATURES_KHR = 1000668004, + IMAGE_STENCIL_USAGE_2_CREATE_INFO_KHR = 1000668005, + SHARED_PRESENT_SURFACE_CAPABILITIES_2_KHR = 1000668006, + PHYSICAL_DEVICE_SHADER_MIXED_FLOAT_DOT_PRODUCT_FEATURES_VALVE = 1000673000, + PHYSICAL_DEVICE_THROTTLE_HINT_FEATURES_SEC = 1000674000, + THROTTLE_HINT_SUBMIT_INFO_SEC = 1000674001, + DATA_GRAPH_PIPELINE_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676000, + DATA_GRAPH_PIPELINE_SESSION_NEURAL_STATISTICS_CREATE_INFO_ARM = 1000676001, + PHYSICAL_DEVICE_DATA_GRAPH_NEURAL_ACCELERATOR_STATISTICS_FEATURES_ARM = 1000676002, + PHYSICAL_DEVICE_PRIMITIVE_RESTART_INDEX_FEATURES_EXT = 1000678000, + PHYSICAL_DEVICE_COOPERATIVE_MATRIX_DECODE_VECTOR_FEATURES_NV = 1000689000, + PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, + DEBUG_REPORT_CREATE_INFO_EXT = DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + RENDERING_INFO_KHR = RENDERING_INFO, + RENDERING_ATTACHMENT_INFO_KHR = RENDERING_ATTACHMENT_INFO, + PIPELINE_RENDERING_CREATE_INFO_KHR = PIPELINE_RENDERING_CREATE_INFO, + PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR = PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, + COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR = COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, + RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = RENDER_PASS_MULTIVIEW_CREATE_INFO, + PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = PHYSICAL_DEVICE_MULTIVIEW_FEATURES, + PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, + PHYSICAL_DEVICE_FEATURES_2_KHR = PHYSICAL_DEVICE_FEATURES_2, + PHYSICAL_DEVICE_PROPERTIES_2_KHR = PHYSICAL_DEVICE_PROPERTIES_2, + FORMAT_PROPERTIES_2_KHR = FORMAT_PROPERTIES_2, + IMAGE_FORMAT_PROPERTIES_2_KHR = IMAGE_FORMAT_PROPERTIES_2, + PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + QUEUE_FAMILY_PROPERTIES_2_KHR = QUEUE_FAMILY_PROPERTIES_2, + PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, + SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = SPARSE_IMAGE_FORMAT_PROPERTIES_2, + PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, + MEMORY_ALLOCATE_FLAGS_INFO_KHR = MEMORY_ALLOCATE_FLAGS_INFO, + DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, + DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, + DEVICE_GROUP_SUBMIT_INFO_KHR = DEVICE_GROUP_SUBMIT_INFO, + DEVICE_GROUP_BIND_SPARSE_INFO_KHR = DEVICE_GROUP_BIND_SPARSE_INFO, + BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, + BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, + PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT = PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES, + PIPELINE_ROBUSTNESS_CREATE_INFO_EXT = PIPELINE_ROBUSTNESS_CREATE_INFO, + PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES, + PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT = PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES, + PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = PHYSICAL_DEVICE_GROUP_PROPERTIES, + DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = DEVICE_GROUP_DEVICE_CREATE_INFO, + PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = EXTERNAL_IMAGE_FORMAT_PROPERTIES, + PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, + EXTERNAL_BUFFER_PROPERTIES_KHR = EXTERNAL_BUFFER_PROPERTIES, + PHYSICAL_DEVICE_ID_PROPERTIES_KHR = PHYSICAL_DEVICE_ID_PROPERTIES, + EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + EXPORT_MEMORY_ALLOCATE_INFO_KHR = EXPORT_MEMORY_ALLOCATE_INFO, + PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, + EXTERNAL_SEMAPHORE_PROPERTIES_KHR = EXTERNAL_SEMAPHORE_PROPERTIES, + EXPORT_SEMAPHORE_CREATE_INFO_KHR = EXPORT_SEMAPHORE_CREATE_INFO, + PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES, + PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, + PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, + DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, + SURFACE_CAPABILITIES2_EXT = SURFACE_CAPABILITIES_2_EXT, + PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR = PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, + FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR = FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, + FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR = FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, + RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR = RENDER_PASS_ATTACHMENT_BEGIN_INFO, + ATTACHMENT_DESCRIPTION_2_KHR = ATTACHMENT_DESCRIPTION_2, + ATTACHMENT_REFERENCE_2_KHR = ATTACHMENT_REFERENCE_2, + SUBPASS_DESCRIPTION_2_KHR = SUBPASS_DESCRIPTION_2, + SUBPASS_DEPENDENCY_2_KHR = SUBPASS_DEPENDENCY_2, + RENDER_PASS_CREATE_INFO_2_KHR = RENDER_PASS_CREATE_INFO_2, + SUBPASS_BEGIN_INFO_KHR = SUBPASS_BEGIN_INFO, + SUBPASS_END_INFO_KHR = SUBPASS_END_INFO, + PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, + EXTERNAL_FENCE_PROPERTIES_KHR = EXTERNAL_FENCE_PROPERTIES, + EXPORT_FENCE_CREATE_INFO_KHR = EXPORT_FENCE_CREATE_INFO, + PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, + RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, + IMAGE_VIEW_USAGE_CREATE_INFO_KHR = IMAGE_VIEW_USAGE_CREATE_INFO, + PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, + PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, + PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, + MEMORY_DEDICATED_REQUIREMENTS_KHR = MEMORY_DEDICATED_REQUIREMENTS, + MEMORY_DEDICATED_ALLOCATE_INFO_KHR = MEMORY_DEDICATED_ALLOCATE_INFO, + PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, + SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = SAMPLER_REDUCTION_MODE_CREATE_INFO, + PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, + PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES, + WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK, + DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO, + BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = BUFFER_MEMORY_REQUIREMENTS_INFO_2, + IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = IMAGE_MEMORY_REQUIREMENTS_INFO_2, + IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, + MEMORY_REQUIREMENTS_2_KHR = MEMORY_REQUIREMENTS_2, + SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, + IMAGE_FORMAT_LIST_CREATE_INFO_KHR = IMAGE_FORMAT_LIST_CREATE_INFO, + ATTACHMENT_SAMPLE_COUNT_INFO_NV = ATTACHMENT_SAMPLE_COUNT_INFO_AMD, + SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = SAMPLER_YCBCR_CONVERSION_CREATE_INFO, + SAMPLER_YCBCR_CONVERSION_INFO_KHR = SAMPLER_YCBCR_CONVERSION_INFO, + BIND_IMAGE_PLANE_MEMORY_INFO_KHR = BIND_IMAGE_PLANE_MEMORY_INFO, + IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, + PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, + SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, + BIND_BUFFER_MEMORY_INFO_KHR = BIND_BUFFER_MEMORY_INFO, + BIND_IMAGE_MEMORY_INFO_KHR = BIND_IMAGE_MEMORY_INFO, + DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT = DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT = PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, + PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, + DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT, + PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, + DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = DESCRIPTOR_SET_LAYOUT_SUPPORT, + DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, + PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES, + PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, + PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, + CALIBRATED_TIMESTAMP_INFO_EXT = CALIBRATED_TIMESTAMP_INFO_KHR, + DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR = DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO, + PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR = PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, + QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR = QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, + PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, + PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT = PIPELINE_CREATION_FEEDBACK_CREATE_INFO, + PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = PHYSICAL_DEVICE_DRIVER_PROPERTIES, + PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, + PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR = PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES, + SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR = SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, + PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR, + PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, + PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR = PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, + PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR = PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES, + SEMAPHORE_TYPE_CREATE_INFO_KHR = SEMAPHORE_TYPE_CREATE_INFO, + TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = TIMELINE_SEMAPHORE_SUBMIT_INFO, + SEMAPHORE_WAIT_INFO_KHR = SEMAPHORE_WAIT_INFO, + SEMAPHORE_SIGNAL_INFO_KHR = SEMAPHORE_SIGNAL_INFO, + QUERY_POOL_CREATE_INFO_INTEL = QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL, + PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES, + PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES, + PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES, + PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT = PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, + PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT = PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, + PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR = PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES, + RENDERING_ATTACHMENT_LOCATION_INFO_KHR = RENDERING_ATTACHMENT_LOCATION_INFO, + RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR = RENDERING_INPUT_ATTACHMENT_INDEX_INFO, + PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, + ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR = ATTACHMENT_REFERENCE_STENCIL_LAYOUT, + ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR = ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, + PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, + BUFFER_DEVICE_ADDRESS_INFO_EXT = BUFFER_DEVICE_ADDRESS_INFO, + PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT = PHYSICAL_DEVICE_TOOL_PROPERTIES, + IMAGE_STENCIL_USAGE_CREATE_INFO_EXT = IMAGE_STENCIL_USAGE_CREATE_INFO, + PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR = PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, + PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR = PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, + BUFFER_DEVICE_ADDRESS_INFO_KHR = BUFFER_DEVICE_ADDRESS_INFO, + BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO_KHR = BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO, + MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO_KHR = MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO, + DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO_KHR = DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO, + PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT = PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, + PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, + PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT = PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, + PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, + PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT = PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES, + PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT = PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES, + MEMORY_TO_IMAGE_COPY_EXT = MEMORY_TO_IMAGE_COPY, + IMAGE_TO_MEMORY_COPY_EXT = IMAGE_TO_MEMORY_COPY, + COPY_IMAGE_TO_MEMORY_INFO_EXT = COPY_IMAGE_TO_MEMORY_INFO, + COPY_MEMORY_TO_IMAGE_INFO_EXT = COPY_MEMORY_TO_IMAGE_INFO, + HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT = HOST_IMAGE_LAYOUT_TRANSITION_INFO, + COPY_IMAGE_TO_IMAGE_INFO_EXT = COPY_IMAGE_TO_IMAGE_INFO, + SUBRESOURCE_HOST_MEMCPY_SIZE_EXT = SUBRESOURCE_HOST_MEMCPY_SIZE, + HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY, + MEMORY_MAP_INFO_KHR = MEMORY_MAP_INFO, + MEMORY_UNMAP_INFO_KHR = MEMORY_UNMAP_INFO, + SURFACE_PRESENT_MODE_EXT = SURFACE_PRESENT_MODE_KHR, + SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = SURFACE_PRESENT_SCALING_CAPABILITIES_KHR, + SURFACE_PRESENT_MODE_COMPATIBILITY_EXT = SURFACE_PRESENT_MODE_COMPATIBILITY_KHR, + PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT = PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR, + SWAPCHAIN_PRESENT_FENCE_INFO_EXT = SWAPCHAIN_PRESENT_FENCE_INFO_KHR, + SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT = SWAPCHAIN_PRESENT_MODES_CREATE_INFO_KHR, + SWAPCHAIN_PRESENT_MODE_INFO_EXT = SWAPCHAIN_PRESENT_MODE_INFO_KHR, + SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT = SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_KHR, + RELEASE_SWAPCHAIN_IMAGES_INFO_EXT = RELEASE_SWAPCHAIN_IMAGES_INFO_KHR, + PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, + PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, + PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR = PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES, + PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES, + PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT = PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_KHR, + PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT = PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_KHR, + PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT = PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES, + DEVICE_PRIVATE_DATA_CREATE_INFO_EXT = DEVICE_PRIVATE_DATA_CREATE_INFO, + PRIVATE_DATA_SLOT_CREATE_INFO_EXT = PRIVATE_DATA_SLOT_CREATE_INFO, + PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, + MEMORY_BARRIER_2_KHR = MEMORY_BARRIER_2, + BUFFER_MEMORY_BARRIER_2_KHR = BUFFER_MEMORY_BARRIER_2, + IMAGE_MEMORY_BARRIER_2_KHR = IMAGE_MEMORY_BARRIER_2, + DEPENDENCY_INFO_KHR = DEPENDENCY_INFO, + SUBMIT_INFO_2_KHR = SUBMIT_INFO_2, + SEMAPHORE_SUBMIT_INFO_KHR = SEMAPHORE_SUBMIT_INFO, + COMMAND_BUFFER_SUBMIT_INFO_KHR = COMMAND_BUFFER_SUBMIT_INFO, + PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR = PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, + PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR = PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES, + PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT = PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES, + COPY_BUFFER_INFO_2_KHR = COPY_BUFFER_INFO_2, + COPY_IMAGE_INFO_2_KHR = COPY_IMAGE_INFO_2, + COPY_BUFFER_TO_IMAGE_INFO_2_KHR = COPY_BUFFER_TO_IMAGE_INFO_2, + COPY_IMAGE_TO_BUFFER_INFO_2_KHR = COPY_IMAGE_TO_BUFFER_INFO_2, + BLIT_IMAGE_INFO_2_KHR = BLIT_IMAGE_INFO_2, + RESOLVE_IMAGE_INFO_2_KHR = RESOLVE_IMAGE_INFO_2, + BUFFER_COPY_2_KHR = BUFFER_COPY_2, + IMAGE_COPY_2_KHR = IMAGE_COPY_2, + IMAGE_BLIT_2_KHR = IMAGE_BLIT_2, + BUFFER_IMAGE_COPY_2_KHR = BUFFER_IMAGE_COPY_2, + IMAGE_RESOLVE_2_KHR = IMAGE_RESOLVE_2, + SUBRESOURCE_LAYOUT_2_EXT = SUBRESOURCE_LAYOUT_2, + IMAGE_SUBRESOURCE_2_EXT = IMAGE_SUBRESOURCE_2, + PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM = PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, + PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE = PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, + MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE = MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT, + FORMAT_PROPERTIES_3_KHR = FORMAT_PROPERTIES_3, + PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_EXT = PHYSICAL_DEVICE_PRESENT_MODE_FIFO_LATEST_READY_FEATURES_KHR, + PIPELINE_INFO_EXT = PIPELINE_INFO_KHR, + PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT = PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, + QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT = QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES, + PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, + PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES, + DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR = DEVICE_BUFFER_MEMORY_REQUIREMENTS, + DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR = DEVICE_IMAGE_MEMORY_REQUIREMENTS, + PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, + PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_EXT = PHYSICAL_DEVICE_DEPTH_CLAMP_ZERO_ONE_FEATURES_KHR, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM = PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_EXT, + PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM = PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT, + SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM = RENDER_PASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_EXT, + PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_NV = PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR, + PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_NV = PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT, + PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_NV = PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT, + PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, + PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, + PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES, + RENDERING_AREA_INFO_KHR = RENDERING_AREA_INFO, + DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = DEVICE_IMAGE_SUBRESOURCE_INFO, + SUBRESOURCE_LAYOUT_2_KHR = SUBRESOURCE_LAYOUT_2, + IMAGE_SUBRESOURCE_2_KHR = IMAGE_SUBRESOURCE_2, + PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = PIPELINE_CREATE_FLAGS_2_CREATE_INFO, + BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = BUFFER_USAGE_FLAGS_2_CREATE_INFO, + SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT = PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_KHR = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES, + PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_KHR = PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO, + PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR = PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, + PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, + PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_KHR = PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, + PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_KHR = PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_KHR = PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO, + PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_KHR = PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES, + PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR = PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES, + PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR = PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES, + PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES_KHR = PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES, + BIND_MEMORY_STATUS_KHR = BIND_MEMORY_STATUS, + BIND_DESCRIPTOR_SETS_INFO_KHR = BIND_DESCRIPTOR_SETS_INFO, + PUSH_CONSTANTS_INFO_KHR = PUSH_CONSTANTS_INFO, + PUSH_DESCRIPTOR_SET_INFO_KHR = PUSH_DESCRIPTOR_SET_INFO, + PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO_KHR = PUSH_DESCRIPTOR_SET_WITH_TEMPLATE_INFO, + RENDERING_END_INFO_EXT = RENDERING_END_INFO_KHR, } SubgroupFeatureFlags :: distinct bit_set[SubgroupFeatureFlag; Flags] @@ -4066,7 +4774,8 @@ SubgroupFeatureFlag :: enum Flags { QUAD = 7, ROTATE = 9, ROTATE_CLUSTERED = 10, - PARTITIONED_NV = 8, + PARTITIONED_EXT = 8, + PARTITIONED_NV = PARTITIONED_EXT, ROTATE_KHR = ROTATE, ROTATE_CLUSTERED_KHR = ROTATE_CLUSTERED, } @@ -4088,12 +4797,15 @@ SubpassDescriptionFlags :: distinct bit_set[SubpassDescriptionFlag; Flags] SubpassDescriptionFlag :: enum Flags { PER_VIEW_ATTRIBUTES_NVX = 0, PER_VIEW_POSITION_X_ONLY_NVX = 1, - FRAGMENT_REGION_QCOM = 2, - SHADER_RESOLVE_QCOM = 3, + TILE_SHADING_APRON_QCOM = 8, RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_EXT = 4, RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_EXT = 5, RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_EXT = 6, ENABLE_LEGACY_DITHERING_EXT = 7, + FRAGMENT_REGION_EXT = 2, + CUSTOM_RESOLVE_EXT = 3, + FRAGMENT_REGION_QCOM = FRAGMENT_REGION_EXT, + SHADER_RESOLVE_QCOM = CUSTOM_RESOLVE_EXT, RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_ARM = RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_EXT, RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_ARM = RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_EXT, RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_ARM = RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_EXT, @@ -4136,10 +4848,15 @@ SurfaceTransformFlagKHR :: enum Flags { SwapchainCreateFlagsKHR :: distinct bit_set[SwapchainCreateFlagKHR; Flags] SwapchainCreateFlagKHR :: enum Flags { - SPLIT_INSTANCE_BIND_REGIONS = 0, - PROTECTED = 1, - MUTABLE_FORMAT = 2, - DEFERRED_MEMORY_ALLOCATION_EXT = 3, + SPLIT_INSTANCE_BIND_REGIONS = 0, + PROTECTED = 1, + MUTABLE_FORMAT = 2, + PRESENT_TIMING_EXT = 9, + PRESENT_ID_2 = 6, + PRESENT_WAIT_2 = 7, + DEFERRED_MEMORY_ALLOCATION = 3, + MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXT = 8, + DEFERRED_MEMORY_ALLOCATION_EXT = DEFERRED_MEMORY_ALLOCATION, } SystemAllocationScope :: enum c.int { @@ -4150,6 +4867,11 @@ SystemAllocationScope :: enum c.int { INSTANCE = 4, } +TensorTilingARM :: enum c.int { + OPTIMAL = 0, + LINEAR = 1, +} + TessellationDomainOrigin :: enum c.int { UPPER_LEFT = 0, LOWER_LEFT = 1, @@ -4157,11 +4879,25 @@ TessellationDomainOrigin :: enum c.int { LOWER_LEFT_KHR = LOWER_LEFT, } +ThrottleHintTypeSEC :: enum c.int { + THROTTLE_HINT_TYPE_DEFAULT_SEC = 0, + THROTTLE_HINT_TYPE_LOW_SEC = 1, + THROTTLE_HINT_TYPE_HIGH_SEC = 2, +} + +TileShadingRenderPassFlagsQCOM :: distinct bit_set[TileShadingRenderPassFlagQCOM; Flags] +TileShadingRenderPassFlagQCOM :: enum Flags { + ENABLE = 0, + PER_TILE_EXECUTION = 1, +} + TimeDomainKHR :: enum c.int { DEVICE = 0, CLOCK_MONOTONIC = 1, CLOCK_MONOTONIC_RAW = 2, QUERY_PERFORMANCE_COUNTER = 3, + PRESENT_STAGE_LOCAL_EXT = 1000208000, + SWAPCHAIN_LOCAL_EXT = 1000208001, DEVICE_EXT = DEVICE, CLOCK_MONOTONIC_EXT = CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW_EXT = CLOCK_MONOTONIC_RAW, @@ -4221,6 +4957,7 @@ VendorId :: enum c.int { MESA = 0x10005, POCL = 0x10006, MOBILEYE = 0x10007, + APE = 0x10008, } VertexInputRate :: enum c.int { @@ -4286,6 +5023,7 @@ VideoCodecOperationFlagKHR :: enum Flags { DECODE_H265 = 1, DECODE_AV1 = 2, ENCODE_AV1 = 18, + DECODE_VP9 = 3, } VideoCodecOperationFlagsKHR_NONE :: VideoCodecOperationFlagsKHR{} @@ -4343,6 +5081,7 @@ VideoEncodeAV1CapabilityFlagKHR :: enum Flags { PRIMARY_REFERENCE_CDF_ONLY = 2, FRAME_SIZE_OVERRIDE = 3, MOTION_VECTOR_SCALING = 4, + COMPOUND_PREDICTION_INTRA_REFRESH = 5, } VideoEncodeAV1PredictionModeKHR :: enum c.int { @@ -4403,10 +5142,18 @@ VideoEncodeFeedbackFlagKHR :: enum Flags { BITSTREAM_BUFFER_OFFSET = 0, BITSTREAM_BYTES_WRITTEN = 1, BITSTREAM_HAS_OVERRIDES = 2, + AVERAGE_QUANTIZATION = 3, + MIN_QUANTIZATION = 4, + MAX_QUANTIZATION = 5, + INTRA_PIXELS = 6, + INTER_PIXELS = 7, + SKIPPED_PIXELS = 8, + PICTURE_PARTITION_COUNT = 9, } VideoEncodeFlagsKHR :: distinct bit_set[VideoEncodeFlagKHR; Flags] VideoEncodeFlagKHR :: enum Flags { + INTRA_REFRESH = 2, WITH_QUANTIZATION_DELTA_MAP = 0, WITH_EMPHASIS_MAP = 1, } @@ -4422,6 +5169,7 @@ VideoEncodeH264CapabilityFlagKHR :: enum Flags { PER_PICTURE_TYPE_MIN_MAX_QP = 6, PER_SLICE_CONSTANT_QP = 7, GENERATE_PREFIX_NALU = 8, + B_PICTURE_INTRA_REFRESH = 10, MB_QP_DIFF_WRAPAROUND = 9, } @@ -4470,6 +5218,7 @@ VideoEncodeH265CapabilityFlagKHR :: enum Flags { PER_SLICE_SEGMENT_CONSTANT_QP = 7, MULTIPLE_TILES_PER_SLICE_SEGMENT = 8, MULTIPLE_SLICE_SEGMENTS_PER_TILE = 9, + B_PICTURE_INTRA_REFRESH = 11, CU_QP_DIFF_WRAPAROUND = 10, } @@ -4522,6 +5271,24 @@ VideoEncodeH265TransformBlockSizeFlagKHR :: enum Flags { _32 = 3, } +VideoEncodeIntraRefreshModeFlagsKHR :: distinct bit_set[VideoEncodeIntraRefreshModeFlagKHR; Flags] +VideoEncodeIntraRefreshModeFlagKHR :: enum Flags { + PER_PICTURE_PARTITION = 0, + BLOCK_BASED = 1, + BLOCK_ROW_BASED = 2, + BLOCK_COLUMN_BASED = 3, +} + +VideoEncodeIntraRefreshModeFlagsKHR_NONE :: VideoEncodeIntraRefreshModeFlagsKHR{} + + +VideoEncodePerPartitionFeedbackFlagsKHR :: distinct bit_set[VideoEncodePerPartitionFeedbackFlagKHR; Flags] +VideoEncodePerPartitionFeedbackFlagKHR :: enum Flags { + STATUS = 0, + BITSTREAM_BUFFER_OFFSET = 1, + BITSTREAM_BYTES_WRITTEN = 2, +} + VideoEncodeRateControlModeFlagsKHR :: distinct bit_set[VideoEncodeRateControlModeFlagKHR; Flags] VideoEncodeRateControlModeFlagKHR :: enum Flags { DISABLED = 0, @@ -4532,6 +5299,27 @@ VideoEncodeRateControlModeFlagKHR :: enum Flags { VideoEncodeRateControlModeFlagsKHR_DEFAULT :: VideoEncodeRateControlModeFlagsKHR{} +VideoEncodeRgbChromaOffsetFlagsVALVE :: distinct bit_set[VideoEncodeRgbChromaOffsetFlagVALVE; Flags] +VideoEncodeRgbChromaOffsetFlagVALVE :: enum Flags { + VIDEO_ENCODE_RGB_CHROMA_OFFSET_COSITED_EVEN_VALVE = 0, + VIDEO_ENCODE_RGB_CHROMA_OFFSET_MIDPOINT_VALVE = 1, +} + +VideoEncodeRgbModelConversionFlagsVALVE :: distinct bit_set[VideoEncodeRgbModelConversionFlagVALVE; Flags] +VideoEncodeRgbModelConversionFlagVALVE :: enum Flags { + VIDEO_ENCODE_RGB_MODEL_CONVERSION_RGB_IDENTITY_VALVE = 0, + VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_IDENTITY_VALVE = 1, + VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_709_VALVE = 2, + VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_601_VALVE = 3, + VIDEO_ENCODE_RGB_MODEL_CONVERSION_YCBCR_2020_VALVE = 4, +} + +VideoEncodeRgbRangeCompressionFlagsVALVE :: distinct bit_set[VideoEncodeRgbRangeCompressionFlagVALVE; Flags] +VideoEncodeRgbRangeCompressionFlagVALVE :: enum Flags { + VIDEO_ENCODE_RGB_RANGE_COMPRESSION_FULL_RANGE_VALVE = 0, + VIDEO_ENCODE_RGB_RANGE_COMPRESSION_NARROW_RANGE_VALVE = 1, +} + VideoEncodeTuningModeKHR :: enum c.int { DEFAULT = 0, HIGH_QUALITY = 1, @@ -4623,6 +5411,24 @@ VideoSessionParametersCreateFlagKHR :: enum Flags { QUANTIZATION_MAP_COMPATIBLE = 0, } +VideoVP9ColorSpace :: enum c.int { +} + +VideoVP9FrameType :: enum c.int { +} + +VideoVP9InterpolationFilter :: enum c.int { +} + +VideoVP9Level :: enum c.int { +} + +VideoVP9Profile :: enum c.int { +} + +VideoVP9ReferenceName :: enum c.int { +} + ViewportCoordinateSwizzleNV :: enum c.int { POSITIVE_X = 0, NEGATIVE_X = 1, @@ -4660,6 +5466,8 @@ DisplayModeCreateFlagsKHR :: distinct bit_set[Display DisplayModeCreateFlagKHR :: enum u32 {} DisplaySurfaceCreateFlagsKHR :: distinct bit_set[DisplaySurfaceCreateFlagKHR; Flags] DisplaySurfaceCreateFlagKHR :: enum u32 {} +GpaPerfBlockPropertiesFlagsAMD :: distinct bit_set[GpaPerfBlockPropertiesFlagAMD; Flags] +GpaPerfBlockPropertiesFlagAMD :: enum u32 {} HeadlessSurfaceCreateFlagsEXT :: distinct bit_set[HeadlessSurfaceCreateFlagEXT; Flags] HeadlessSurfaceCreateFlagEXT :: enum u32 {} IOSSurfaceCreateFlagsMVK :: distinct bit_set[IOSSurfaceCreateFlagMVK; Flags] @@ -4668,6 +5476,10 @@ MacOSSurfaceCreateFlagsMVK :: distinct bit_set[MacOSSu MacOSSurfaceCreateFlagMVK :: enum u32 {} MetalSurfaceCreateFlagsEXT :: distinct bit_set[MetalSurfaceCreateFlagEXT; Flags] MetalSurfaceCreateFlagEXT :: enum u32 {} +PerformanceCounterDescriptionFlagsARM :: distinct bit_set[PerformanceCounterDescriptionFlagARM; Flags] +PerformanceCounterDescriptionFlagARM :: enum u32 {} +PhysicalDeviceGpaPropertiesFlagsAMD :: distinct bit_set[PhysicalDeviceGpaPropertiesFlagAMD; Flags] +PhysicalDeviceGpaPropertiesFlagAMD :: enum u32 {} PipelineCoverageModulationStateCreateFlagsNV :: distinct bit_set[PipelineCoverageModulationStateCreateFlagNV; Flags] PipelineCoverageModulationStateCreateFlagNV :: enum u32 {} PipelineCoverageReductionStateCreateFlagsNV :: distinct bit_set[PipelineCoverageReductionStateCreateFlagNV; Flags] @@ -4700,10 +5512,10 @@ PipelineViewportSwizzleStateCreateFlagsNV :: distinct bit_set[Pipelin PipelineViewportSwizzleStateCreateFlagNV :: enum u32 {} PrivateDataSlotCreateFlags :: distinct bit_set[PrivateDataSlotCreateFlag; Flags] PrivateDataSlotCreateFlag :: enum u32 {} -QueryPoolCreateFlags :: distinct bit_set[QueryPoolCreateFlag; Flags] -QueryPoolCreateFlag :: enum u32 {} SemaphoreCreateFlags :: distinct bit_set[SemaphoreCreateFlag; Flags] SemaphoreCreateFlag :: enum u32 {} +ShaderInstrumentationValuesFlagsARM :: distinct bit_set[ShaderInstrumentationValuesFlagARM; Flags] +ShaderInstrumentationValuesFlagARM :: enum u32 {} ShaderModuleCreateFlags :: distinct bit_set[ShaderModuleCreateFlag; Flags] ShaderModuleCreateFlag :: enum u32 {} ValidationCacheCreateFlagsEXT :: distinct bit_set[ValidationCacheCreateFlagEXT; Flags] @@ -4748,8 +5560,12 @@ AccessFlag2 :: enum Flags64 { SHADER_STORAGE_WRITE = 34, VIDEO_DECODE_READ_KHR = 35, VIDEO_DECODE_WRITE_KHR = 36, + SAMPLER_HEAP_READ_EXT = 57, + RESOURCE_HEAP_READ_EXT = 58, VIDEO_ENCODE_READ_KHR = 37, VIDEO_ENCODE_WRITE_KHR = 38, + SHADER_TILE_ATTACHMENT_READ_QCOM = 51, + SHADER_TILE_ATTACHMENT_WRITE_QCOM = 52, INDIRECT_COMMAND_READ_KHR = 0, INDEX_READ_KHR = 1, VERTEX_ATTRIBUTE_READ_KHR = 2, @@ -4793,6 +5609,10 @@ AccessFlag2 :: enum Flags64 { MICROMAP_WRITE_EXT = 45, OPTICAL_FLOW_READ_NV = 42, OPTICAL_FLOW_WRITE_NV = 43, + DATA_GRAPH_READ_ARM = 47, + DATA_GRAPH_WRITE_ARM = 48, + MEMORY_DECOMPRESSION_READ_EXT = 55, + MEMORY_DECOMPRESSION_WRITE_EXT = 56, } BufferUsageFlags2 :: distinct bit_set[BufferUsageFlag2; Flags64] @@ -4808,6 +5628,9 @@ BufferUsageFlag2 :: enum Flags64 { INDIRECT_BUFFER = 8, SHADER_DEVICE_ADDRESS = 17, EXECUTION_GRAPH_SCRATCH_AMDX = 25, + DESCRIPTOR_HEAP_EXT = 28, + MICROMAP_BUILD_INPUT_READ_ONLY_EXT = 23, + MICROMAP_STORAGE_EXT = 24, TRANSFER_SRC_KHR = 0, TRANSFER_DST_KHR = 1, UNIFORM_TEXEL_BUFFER_KHR = 2, @@ -4832,8 +5655,10 @@ BufferUsageFlag2 :: enum Flags64 { SAMPLER_DESCRIPTOR_BUFFER_EXT = 21, RESOURCE_DESCRIPTOR_BUFFER_EXT = 22, PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_EXT = 26, - MICROMAP_BUILD_INPUT_READ_ONLY_EXT = 23, - MICROMAP_STORAGE_EXT = 24, + COMPRESSED_DATA_DGF1_AMDX = 33, + DATA_GRAPH_FOREIGN_DESCRIPTOR_ARM = 29, + TILE_MEMORY_QCOM = 27, + MEMORY_DECOMPRESSION_EXT = 32, PREPROCESS_BUFFER_EXT = 31, } @@ -4875,6 +5700,7 @@ FormatFeatureFlag2 :: enum Flags64 { HOST_IMAGE_TRANSFER_EXT = 46, VIDEO_ENCODE_INPUT_KHR = 27, VIDEO_ENCODE_DPB_KHR = 28, + BLOCK_MATCHING_SXD_QCOM = 44, SAMPLED_IMAGE_KHR = 0, STORAGE_IMAGE_KHR = 1, STORAGE_IMAGE_ATOMIC_KHR = 2, @@ -4908,11 +5734,23 @@ FormatFeatureFlag2 :: enum Flags64 { WEIGHT_SAMPLED_IMAGE_QCOM = 35, BLOCK_MATCHING_QCOM = 36, BOX_FILTER_SAMPLED_QCOM = 37, + TENSOR_SHADER_ARM = 39, + TENSOR_IMAGE_ALIASING_ARM = 43, OPTICAL_FLOW_IMAGE_NV = 40, OPTICAL_FLOW_VECTOR_NV = 41, OPTICAL_FLOW_COST_NV = 42, + TENSOR_DATA_GRAPH_ARM = 48, + COPY_IMAGE_INDIRECT_DST_KHR = 59, VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_KHR = 49, VIDEO_ENCODE_EMPHASIS_MAP_KHR = 50, + SAMPLED_IMAGE_FILTER_LINEAR_2D_IMG = 45, + DEPTH_COPY_ON_COMPUTE_QUEUE_KHR = 52, + DEPTH_COPY_ON_TRANSFER_QUEUE_KHR = 53, + STENCIL_COPY_ON_COMPUTE_QUEUE_KHR = 54, + STENCIL_COPY_ON_TRANSFER_QUEUE_KHR = 55, + DATA_GRAPH_OPTICAL_FLOW_IMAGE_ARM = 56, + DATA_GRAPH_OPTICAL_FLOW_VECTOR_ARM = 57, + DATA_GRAPH_OPTICAL_FLOW_COST_ARM = 58, } PipelineCreateFlags2 :: distinct bit_set[PipelineCreateFlag2; Flags64] @@ -4927,7 +5765,9 @@ PipelineCreateFlag2 :: enum Flags64 { NO_PROTECTED_ACCESS = 27, PROTECTED_ACCESS_ONLY = 30, EXECUTION_GRAPH_AMDX = 32, + DESCRIPTOR_HEAP_EXT = 36, RAY_TRACING_SKIP_BUILT_IN_PRIMITIVES_KHR = 12, + RAY_TRACING_OPACITY_MICROMAP_EXT = 24, RAY_TRACING_ALLOW_SPHERES_AND_LINEAR_SWEPT_SPHERES_NV = 33, ENABLE_LEGACY_DITHERING_EXT = 34, DISABLE_OPTIMIZATION_KHR = 0, @@ -4954,7 +5794,6 @@ PipelineCreateFlag2 :: enum Flags64 { RAY_TRACING_ALLOW_MOTION_NV = 20, RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_KHR = 21, RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_EXT = 22, - RAY_TRACING_OPACITY_MICROMAP_EXT = 24, COLOR_ATTACHMENT_FEEDBACK_LOOP_EXT = 25, DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_EXT = 26, NO_PROTECTED_ACCESS_EXT = 27, @@ -4962,8 +5801,13 @@ PipelineCreateFlag2 :: enum Flags64 { RAY_TRACING_DISPLACEMENT_MICROMAP_NV = 28, DESCRIPTOR_BUFFER_EXT = 29, DISALLOW_OPACITY_MICROMAP_ARM = 37, + INSTRUMENT_SHADERS_ARM = 39, CAPTURE_DATA_KHR = 31, INDIRECT_BINDABLE_EXT = 38, + PER_LAYER_FRAGMENT_DENSITY_VALVE = 40, + RAY_TRACING_OPACITY_MICROMAP_KHR = 24, + OPACITY_MICROMAP_DISALLOW_MIXED_SPECIAL_INDEX_KHR = 41, + _64_INDEXING_EXT = 43, } PipelineStageFlags2 :: distinct bit_set[PipelineStageFlag2; Flags64] @@ -5043,6 +5887,9 @@ PipelineStageFlag2 :: enum Flags64 { CLUSTER_CULLING_SHADER_HUAWEI = 41, OPTICAL_FLOW_NV = 29, CONVERT_COOPERATIVE_VECTOR_MATRIX_NV = 44, + DATA_GRAPH_ARM = 42, + COPY_INDIRECT_KHR = 46, + MEMORY_DECOMPRESSION_EXT = 45, } diff --git a/vendor/vulkan/procedures.odin b/vendor/vulkan/procedures.odin index 6a63c83d0..bb1a05ac0 100644 --- a/vendor/vulkan/procedures.odin +++ b/vendor/vulkan/procedures.odin @@ -1,6 +1,3 @@ -// -// Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h" -// package vulkan import "core:c" @@ -12,6 +9,7 @@ ProcDeviceMemoryReportCallbackEXT :: #type proc "system" (pCallbackData: ProcEnumerateInstanceExtensionProperties :: #type proc "system" (pLayerName: cstring, pPropertyCount: ^u32, pProperties: [^]ExtensionProperties) -> Result ProcEnumerateInstanceLayerProperties :: #type proc "system" (pPropertyCount: ^u32, pProperties: [^]LayerProperties) -> Result ProcEnumerateInstanceVersion :: #type proc "system" (pApiVersion: ^u32) -> Result +ProcGetExternalComputeQueueDataNV :: #type proc "system" (externalQueue: ExternalComputeQueueNV, params: [^]ExternalComputeQueueDataParamsNV, pData: rawptr) // Misc Procedure Types ProcAllocationFunction :: #type proc "system" (pUserData: rawptr, size: int, alignment: int, allocationScope: SystemAllocationScope) -> rawptr @@ -23,104 +21,112 @@ ProcReallocationFunction :: #type proc "system" (pUserData: rawptr, pO ProcVoidFunction :: #type proc "system" () // Instance Procedure Types -ProcAcquireDrmDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, drmFd: i32, display: DisplayKHR) -> Result -ProcAcquireWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result -ProcCreateDebugReportCallbackEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^DebugReportCallbackCreateInfoEXT, pAllocator: ^AllocationCallbacks, pCallback: ^DebugReportCallbackEXT) -> Result -ProcCreateDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^DebugUtilsMessengerCreateInfoEXT, pAllocator: ^AllocationCallbacks, pMessenger: ^DebugUtilsMessengerEXT) -> Result -ProcCreateDevice :: #type proc "system" (physicalDevice: PhysicalDevice, pCreateInfo: ^DeviceCreateInfo, pAllocator: ^AllocationCallbacks, pDevice: ^Device) -> Result -ProcCreateDisplayModeKHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pCreateInfo: ^DisplayModeCreateInfoKHR, pAllocator: ^AllocationCallbacks, pMode: ^DisplayModeKHR) -> Result -ProcCreateDisplayPlaneSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^DisplaySurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateHeadlessSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^HeadlessSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateIOSSurfaceMVK :: #type proc "system" (instance: Instance, pCreateInfo: ^IOSSurfaceCreateInfoMVK, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateMacOSSurfaceMVK :: #type proc "system" (instance: Instance, pCreateInfo: ^MacOSSurfaceCreateInfoMVK, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateMetalSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^MetalSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateWaylandSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^WaylandSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateWin32SurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^Win32SurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateXcbSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XcbSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcCreateXlibSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XlibSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result -ProcDebugReportMessageEXT :: #type proc "system" (instance: Instance, flags: DebugReportFlagsEXT, objectType: DebugReportObjectTypeEXT, object: u64, location: int, messageCode: i32, pLayerPrefix: cstring, pMessage: cstring) -ProcDestroyDebugReportCallbackEXT :: #type proc "system" (instance: Instance, callback: DebugReportCallbackEXT, pAllocator: ^AllocationCallbacks) -ProcDestroyDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, messenger: DebugUtilsMessengerEXT, pAllocator: ^AllocationCallbacks) -ProcDestroyInstance :: #type proc "system" (instance: Instance, pAllocator: ^AllocationCallbacks) -ProcDestroySurfaceKHR :: #type proc "system" (instance: Instance, surface: SurfaceKHR, pAllocator: ^AllocationCallbacks) -ProcEnumerateDeviceExtensionProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pLayerName: cstring, pPropertyCount: ^u32, pProperties: [^]ExtensionProperties) -> Result -ProcEnumerateDeviceLayerProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]LayerProperties) -> Result -ProcEnumeratePhysicalDeviceGroups :: #type proc "system" (instance: Instance, pPhysicalDeviceGroupCount: ^u32, pPhysicalDeviceGroupProperties: [^]PhysicalDeviceGroupProperties) -> Result -ProcEnumeratePhysicalDeviceGroupsKHR :: #type proc "system" (instance: Instance, pPhysicalDeviceGroupCount: ^u32, pPhysicalDeviceGroupProperties: [^]PhysicalDeviceGroupProperties) -> Result -ProcEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pCounterCount: ^u32, pCounters: [^]PerformanceCounterKHR, pCounterDescriptions: [^]PerformanceCounterDescriptionKHR) -> Result -ProcEnumeratePhysicalDevices :: #type proc "system" (instance: Instance, pPhysicalDeviceCount: ^u32, pPhysicalDevices: [^]PhysicalDevice) -> Result -ProcGetDisplayModeProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pPropertyCount: ^u32, pProperties: [^]DisplayModeProperties2KHR) -> Result -ProcGetDisplayModePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pPropertyCount: ^u32, pProperties: [^]DisplayModePropertiesKHR) -> Result -ProcGetDisplayPlaneCapabilities2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pDisplayPlaneInfo: ^DisplayPlaneInfo2KHR, pCapabilities: [^]DisplayPlaneCapabilities2KHR) -> Result -ProcGetDisplayPlaneCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, mode: DisplayModeKHR, planeIndex: u32, pCapabilities: [^]DisplayPlaneCapabilitiesKHR) -> Result -ProcGetDisplayPlaneSupportedDisplaysKHR :: #type proc "system" (physicalDevice: PhysicalDevice, planeIndex: u32, pDisplayCount: ^u32, pDisplays: [^]DisplayKHR) -> Result -ProcGetDrmDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, drmFd: i32, connectorId: u32, display: ^DisplayKHR) -> Result -ProcGetInstanceProcAddr :: #type proc "system" (instance: Instance, pName: cstring) -> ProcVoidFunction -ProcGetInstanceProcAddrLUNARG :: #type proc "system" (instance: Instance, pName: cstring) -> ProcVoidFunction -ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT :: #type proc "system" (physicalDevice: PhysicalDevice, pTimeDomainCount: ^u32, pTimeDomains: [^]TimeDomainKHR) -> Result -ProcGetPhysicalDeviceCalibrateableTimeDomainsKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pTimeDomainCount: ^u32, pTimeDomains: [^]TimeDomainKHR) -> Result -ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixFlexibleDimensionsPropertiesNV) -> Result -ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesKHR) -> Result -ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesNV) -> Result -ProcGetPhysicalDeviceCooperativeVectorPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeVectorPropertiesNV) -> Result -ProcGetPhysicalDeviceDisplayPlaneProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlaneProperties2KHR) -> Result -ProcGetPhysicalDeviceDisplayPlanePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlanePropertiesKHR) -> Result -ProcGetPhysicalDeviceDisplayProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayProperties2KHR) -> Result -ProcGetPhysicalDeviceDisplayPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPropertiesKHR) -> Result -ProcGetPhysicalDeviceExternalBufferProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalBufferInfo: ^PhysicalDeviceExternalBufferInfo, pExternalBufferProperties: [^]ExternalBufferProperties) -ProcGetPhysicalDeviceExternalBufferPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalBufferInfo: ^PhysicalDeviceExternalBufferInfo, pExternalBufferProperties: [^]ExternalBufferProperties) -ProcGetPhysicalDeviceExternalFenceProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalFenceInfo: ^PhysicalDeviceExternalFenceInfo, pExternalFenceProperties: [^]ExternalFenceProperties) -ProcGetPhysicalDeviceExternalFencePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalFenceInfo: ^PhysicalDeviceExternalFenceInfo, pExternalFenceProperties: [^]ExternalFenceProperties) -ProcGetPhysicalDeviceExternalImageFormatPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, tiling: ImageTiling, usage: ImageUsageFlags, flags: ImageCreateFlags, externalHandleType: ExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: [^]ExternalImageFormatPropertiesNV) -> Result -ProcGetPhysicalDeviceExternalSemaphoreProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalSemaphoreInfo: ^PhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: [^]ExternalSemaphoreProperties) -ProcGetPhysicalDeviceExternalSemaphorePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalSemaphoreInfo: ^PhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: [^]ExternalSemaphoreProperties) -ProcGetPhysicalDeviceFeatures :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures) -ProcGetPhysicalDeviceFeatures2 :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures2) -ProcGetPhysicalDeviceFeatures2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures2) -ProcGetPhysicalDeviceFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties) -ProcGetPhysicalDeviceFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties2) -ProcGetPhysicalDeviceFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties2) -ProcGetPhysicalDeviceFragmentShadingRatesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFragmentShadingRateCount: ^u32, pFragmentShadingRates: [^]PhysicalDeviceFragmentShadingRateKHR) -> Result -ProcGetPhysicalDeviceImageFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, tiling: ImageTiling, usage: ImageUsageFlags, flags: ImageCreateFlags, pImageFormatProperties: [^]ImageFormatProperties) -> Result -ProcGetPhysicalDeviceImageFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pImageFormatInfo: ^PhysicalDeviceImageFormatInfo2, pImageFormatProperties: [^]ImageFormatProperties2) -> Result -ProcGetPhysicalDeviceImageFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pImageFormatInfo: ^PhysicalDeviceImageFormatInfo2, pImageFormatProperties: [^]ImageFormatProperties2) -> Result -ProcGetPhysicalDeviceMemoryProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties) -ProcGetPhysicalDeviceMemoryProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties2) -ProcGetPhysicalDeviceMemoryProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties2) -ProcGetPhysicalDeviceMultisamplePropertiesEXT :: #type proc "system" (physicalDevice: PhysicalDevice, samples: SampleCountFlags, pMultisampleProperties: [^]MultisamplePropertiesEXT) -ProcGetPhysicalDeviceOpticalFlowImageFormatsNV :: #type proc "system" (physicalDevice: PhysicalDevice, pOpticalFlowImageFormatInfo: ^OpticalFlowImageFormatInfoNV, pFormatCount: ^u32, pImageFormatProperties: [^]OpticalFlowImageFormatPropertiesNV) -> Result -ProcGetPhysicalDevicePresentRectanglesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pRectCount: ^u32, pRects: [^]Rect2D) -> Result -ProcGetPhysicalDeviceProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties) -ProcGetPhysicalDeviceProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties2) -ProcGetPhysicalDeviceProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties2) -ProcGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPerformanceQueryCreateInfo: ^QueryPoolPerformanceCreateInfoKHR, pNumPasses: [^]u32) -ProcGetPhysicalDeviceQueueFamilyProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties) -ProcGetPhysicalDeviceQueueFamilyProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties2) -ProcGetPhysicalDeviceQueueFamilyProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties2) -ProcGetPhysicalDeviceSparseImageFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, samples: SampleCountFlags, usage: ImageUsageFlags, tiling: ImageTiling, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties) -ProcGetPhysicalDeviceSparseImageFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pFormatInfo: ^PhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties2) -ProcGetPhysicalDeviceSparseImageFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFormatInfo: ^PhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties2) -ProcGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV :: #type proc "system" (physicalDevice: PhysicalDevice, pCombinationCount: ^u32, pCombinations: [^]FramebufferMixedSamplesCombinationNV) -> Result -ProcGetPhysicalDeviceSurfaceCapabilities2EXT :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceCapabilities: [^]SurfaceCapabilities2EXT) -> Result -ProcGetPhysicalDeviceSurfaceCapabilities2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: [^]SurfaceCapabilities2KHR) -> Result -ProcGetPhysicalDeviceSurfaceCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceCapabilities: [^]SurfaceCapabilitiesKHR) -> Result -ProcGetPhysicalDeviceSurfaceFormats2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ^u32, pSurfaceFormats: [^]SurfaceFormat2KHR) -> Result -ProcGetPhysicalDeviceSurfaceFormatsKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceFormatCount: ^u32, pSurfaceFormats: [^]SurfaceFormatKHR) -> Result -ProcGetPhysicalDeviceSurfacePresentModes2EXT :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ^u32, pPresentModes: [^]PresentModeKHR) -> Result -ProcGetPhysicalDeviceSurfacePresentModesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pPresentModeCount: ^u32, pPresentModes: [^]PresentModeKHR) -> Result -ProcGetPhysicalDeviceSurfaceSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, surface: SurfaceKHR, pSupported: ^b32) -> Result -ProcGetPhysicalDeviceToolProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pToolCount: ^u32, pToolProperties: [^]PhysicalDeviceToolProperties) -> Result -ProcGetPhysicalDeviceToolPropertiesEXT :: #type proc "system" (physicalDevice: PhysicalDevice, pToolCount: ^u32, pToolProperties: [^]PhysicalDeviceToolProperties) -> Result -ProcGetPhysicalDeviceVideoCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoProfile: ^VideoProfileInfoKHR, pCapabilities: [^]VideoCapabilitiesKHR) -> Result -ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pQualityLevelInfo: ^PhysicalDeviceVideoEncodeQualityLevelInfoKHR, pQualityLevelProperties: [^]VideoEncodeQualityLevelPropertiesKHR) -> Result -ProcGetPhysicalDeviceVideoFormatPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoFormatInfo: ^PhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ^u32, pVideoFormatProperties: [^]VideoFormatPropertiesKHR) -> Result -ProcGetPhysicalDeviceWaylandPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, display: ^wl_display) -> b32 -ProcGetPhysicalDeviceWin32PresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32) -> b32 -ProcGetPhysicalDeviceXcbPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, connection: ^xcb_connection_t, visual_id: xcb_visualid_t) -> b32 -ProcGetPhysicalDeviceXlibPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, dpy: ^XlibDisplay, visualID: XlibVisualID) -> b32 -ProcGetWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, deviceRelativeId: u32, pDisplay: ^DisplayKHR) -> Result -ProcReleaseDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result -ProcSubmitDebugUtilsMessageEXT :: #type proc "system" (instance: Instance, messageSeverity: DebugUtilsMessageSeverityFlagsEXT, messageTypes: DebugUtilsMessageTypeFlagsEXT, pCallbackData: ^DebugUtilsMessengerCallbackDataEXT) +ProcAcquireDrmDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, drmFd: i32, display: DisplayKHR) -> Result +ProcAcquireWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result +ProcCreateDebugReportCallbackEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^DebugReportCallbackCreateInfoEXT, pAllocator: ^AllocationCallbacks, pCallback: ^DebugReportCallbackEXT) -> Result +ProcCreateDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^DebugUtilsMessengerCreateInfoEXT, pAllocator: ^AllocationCallbacks, pMessenger: ^DebugUtilsMessengerEXT) -> Result +ProcCreateDevice :: #type proc "system" (physicalDevice: PhysicalDevice, pCreateInfo: ^DeviceCreateInfo, pAllocator: ^AllocationCallbacks, pDevice: ^Device) -> Result +ProcCreateDisplayModeKHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pCreateInfo: ^DisplayModeCreateInfoKHR, pAllocator: ^AllocationCallbacks, pMode: ^DisplayModeKHR) -> Result +ProcCreateDisplayPlaneSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^DisplaySurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateHeadlessSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^HeadlessSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateIOSSurfaceMVK :: #type proc "system" (instance: Instance, pCreateInfo: ^IOSSurfaceCreateInfoMVK, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateMacOSSurfaceMVK :: #type proc "system" (instance: Instance, pCreateInfo: ^MacOSSurfaceCreateInfoMVK, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateMetalSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^MetalSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateWaylandSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^WaylandSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateWin32SurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^Win32SurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateXcbSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XcbSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcCreateXlibSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XlibSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result +ProcDebugReportMessageEXT :: #type proc "system" (instance: Instance, flags: DebugReportFlagsEXT, objectType: DebugReportObjectTypeEXT, object: u64, location: int, messageCode: i32, pLayerPrefix: cstring, pMessage: cstring) +ProcDestroyDebugReportCallbackEXT :: #type proc "system" (instance: Instance, callback: DebugReportCallbackEXT, pAllocator: ^AllocationCallbacks) +ProcDestroyDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, messenger: DebugUtilsMessengerEXT, pAllocator: ^AllocationCallbacks) +ProcDestroyInstance :: #type proc "system" (instance: Instance, pAllocator: ^AllocationCallbacks) +ProcDestroySurfaceKHR :: #type proc "system" (instance: Instance, surface: SurfaceKHR, pAllocator: ^AllocationCallbacks) +ProcEnumerateDeviceExtensionProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pLayerName: cstring, pPropertyCount: ^u32, pProperties: [^]ExtensionProperties) -> Result +ProcEnumerateDeviceLayerProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]LayerProperties) -> Result +ProcEnumeratePhysicalDeviceGroups :: #type proc "system" (instance: Instance, pPhysicalDeviceGroupCount: ^u32, pPhysicalDeviceGroupProperties: [^]PhysicalDeviceGroupProperties) -> Result +ProcEnumeratePhysicalDeviceGroupsKHR :: #type proc "system" (instance: Instance, pPhysicalDeviceGroupCount: ^u32, pPhysicalDeviceGroupProperties: [^]PhysicalDeviceGroupProperties) -> Result +ProcEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pCounterCount: ^u32, pCounters: [^]PerformanceCounterARM, pCounterDescriptions: [^]PerformanceCounterDescriptionARM) -> Result +ProcEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pCounterCount: ^u32, pCounters: [^]PerformanceCounterKHR, pCounterDescriptions: [^]PerformanceCounterDescriptionKHR) -> Result +ProcEnumeratePhysicalDeviceShaderInstrumentationMetricsARM :: #type proc "system" (physicalDevice: PhysicalDevice, pDescriptionCount: ^u32, pDescriptions: [^]ShaderInstrumentationMetricDescriptionARM) -> Result +ProcEnumeratePhysicalDevices :: #type proc "system" (instance: Instance, pPhysicalDeviceCount: ^u32, pPhysicalDevices: [^]PhysicalDevice) -> Result +ProcGetDisplayModeProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pPropertyCount: ^u32, pProperties: [^]DisplayModeProperties2KHR) -> Result +ProcGetDisplayModePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR, pPropertyCount: ^u32, pProperties: [^]DisplayModePropertiesKHR) -> Result +ProcGetDisplayPlaneCapabilities2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pDisplayPlaneInfo: ^DisplayPlaneInfo2KHR, pCapabilities: [^]DisplayPlaneCapabilities2KHR) -> Result +ProcGetDisplayPlaneCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, mode: DisplayModeKHR, planeIndex: u32, pCapabilities: [^]DisplayPlaneCapabilitiesKHR) -> Result +ProcGetDisplayPlaneSupportedDisplaysKHR :: #type proc "system" (physicalDevice: PhysicalDevice, planeIndex: u32, pDisplayCount: ^u32, pDisplays: [^]DisplayKHR) -> Result +ProcGetDrmDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, drmFd: i32, connectorId: u32, display: ^DisplayKHR) -> Result +ProcGetInstanceProcAddr :: #type proc "system" (instance: Instance, pName: cstring) -> ProcVoidFunction +ProcGetInstanceProcAddrLUNARG :: #type proc "system" (instance: Instance, pName: cstring) -> ProcVoidFunction +ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT :: #type proc "system" (physicalDevice: PhysicalDevice, pTimeDomainCount: ^u32, pTimeDomains: [^]TimeDomainKHR) -> Result +ProcGetPhysicalDeviceCalibrateableTimeDomainsKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pTimeDomainCount: ^u32, pTimeDomains: [^]TimeDomainKHR) -> Result +ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixFlexibleDimensionsPropertiesNV) -> Result +ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesKHR) -> Result +ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeMatrixPropertiesNV) -> Result +ProcGetPhysicalDeviceCooperativeVectorPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]CooperativeVectorPropertiesNV) -> Result +ProcGetPhysicalDeviceDescriptorSizeEXT :: #type proc "system" (physicalDevice: PhysicalDevice, descriptorType: DescriptorType) -> DeviceSize +ProcGetPhysicalDeviceDisplayPlaneProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlaneProperties2KHR) -> Result +ProcGetPhysicalDeviceDisplayPlanePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPlanePropertiesKHR) -> Result +ProcGetPhysicalDeviceDisplayProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayProperties2KHR) -> Result +ProcGetPhysicalDeviceDisplayPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPropertyCount: ^u32, pProperties: [^]DisplayPropertiesKHR) -> Result +ProcGetPhysicalDeviceExternalBufferProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalBufferInfo: ^PhysicalDeviceExternalBufferInfo, pExternalBufferProperties: [^]ExternalBufferProperties) +ProcGetPhysicalDeviceExternalBufferPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalBufferInfo: ^PhysicalDeviceExternalBufferInfo, pExternalBufferProperties: [^]ExternalBufferProperties) +ProcGetPhysicalDeviceExternalFenceProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalFenceInfo: ^PhysicalDeviceExternalFenceInfo, pExternalFenceProperties: [^]ExternalFenceProperties) +ProcGetPhysicalDeviceExternalFencePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalFenceInfo: ^PhysicalDeviceExternalFenceInfo, pExternalFenceProperties: [^]ExternalFenceProperties) +ProcGetPhysicalDeviceExternalImageFormatPropertiesNV :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, tiling: ImageTiling, usage: ImageUsageFlags, flags: ImageCreateFlags, externalHandleType: ExternalMemoryHandleTypeFlagsNV, pExternalImageFormatProperties: [^]ExternalImageFormatPropertiesNV) -> Result +ProcGetPhysicalDeviceExternalSemaphoreProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalSemaphoreInfo: ^PhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: [^]ExternalSemaphoreProperties) +ProcGetPhysicalDeviceExternalSemaphorePropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalSemaphoreInfo: ^PhysicalDeviceExternalSemaphoreInfo, pExternalSemaphoreProperties: [^]ExternalSemaphoreProperties) +ProcGetPhysicalDeviceExternalTensorPropertiesARM :: #type proc "system" (physicalDevice: PhysicalDevice, pExternalTensorInfo: ^PhysicalDeviceExternalTensorInfoARM, pExternalTensorProperties: [^]ExternalTensorPropertiesARM) +ProcGetPhysicalDeviceFeatures :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures) +ProcGetPhysicalDeviceFeatures2 :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures2) +ProcGetPhysicalDeviceFeatures2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFeatures: [^]PhysicalDeviceFeatures2) +ProcGetPhysicalDeviceFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties) +ProcGetPhysicalDeviceFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties2) +ProcGetPhysicalDeviceFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, pFormatProperties: [^]FormatProperties2) +ProcGetPhysicalDeviceFragmentShadingRatesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFragmentShadingRateCount: ^u32, pFragmentShadingRates: [^]PhysicalDeviceFragmentShadingRateKHR) -> Result +ProcGetPhysicalDeviceImageFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, tiling: ImageTiling, usage: ImageUsageFlags, flags: ImageCreateFlags, pImageFormatProperties: [^]ImageFormatProperties) -> Result +ProcGetPhysicalDeviceImageFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pImageFormatInfo: ^PhysicalDeviceImageFormatInfo2, pImageFormatProperties: [^]ImageFormatProperties2) -> Result +ProcGetPhysicalDeviceImageFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pImageFormatInfo: ^PhysicalDeviceImageFormatInfo2, pImageFormatProperties: [^]ImageFormatProperties2) -> Result +ProcGetPhysicalDeviceMemoryProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties) +ProcGetPhysicalDeviceMemoryProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties2) +ProcGetPhysicalDeviceMemoryProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pMemoryProperties: [^]PhysicalDeviceMemoryProperties2) +ProcGetPhysicalDeviceMultisamplePropertiesEXT :: #type proc "system" (physicalDevice: PhysicalDevice, samples: SampleCountFlags, pMultisampleProperties: [^]MultisamplePropertiesEXT) +ProcGetPhysicalDeviceOpticalFlowImageFormatsNV :: #type proc "system" (physicalDevice: PhysicalDevice, pOpticalFlowImageFormatInfo: ^OpticalFlowImageFormatInfoNV, pFormatCount: ^u32, pImageFormatProperties: [^]OpticalFlowImageFormatPropertiesNV) -> Result +ProcGetPhysicalDevicePresentRectanglesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pRectCount: ^u32, pRects: [^]Rect2D) -> Result +ProcGetPhysicalDeviceProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties) +ProcGetPhysicalDeviceProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties2) +ProcGetPhysicalDeviceProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pProperties: [^]PhysicalDeviceProperties2) +ProcGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pQueueFamilyDataGraphProperties: [^]QueueFamilyDataGraphPropertiesARM, pProperties: [^]BaseOutStructure) -> Result +ProcGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pQueueFamilyDataGraphProperties: [^]QueueFamilyDataGraphPropertiesARM, pOpticalFlowImageFormatInfo: ^DataGraphOpticalFlowImageFormatInfoARM, pFormatCount: ^u32, pImageFormatProperties: [^]DataGraphOpticalFlowImageFormatPropertiesARM) -> Result +ProcGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyDataGraphProcessingEngineInfo: ^PhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM, pQueueFamilyDataGraphProcessingEngineProperties: [^]QueueFamilyDataGraphProcessingEnginePropertiesARM) +ProcGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, pQueueFamilyDataGraphPropertyCount: ^u32, pQueueFamilyDataGraphProperties: [^]QueueFamilyDataGraphPropertiesARM) -> Result +ProcGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pPerformanceQueryCreateInfo: ^QueryPoolPerformanceCreateInfoKHR, pNumPasses: [^]u32) +ProcGetPhysicalDeviceQueueFamilyProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties) +ProcGetPhysicalDeviceQueueFamilyProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties2) +ProcGetPhysicalDeviceQueueFamilyProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pQueueFamilyPropertyCount: ^u32, pQueueFamilyProperties: [^]QueueFamilyProperties2) +ProcGetPhysicalDeviceSparseImageFormatProperties :: #type proc "system" (physicalDevice: PhysicalDevice, format: Format, type: ImageType, samples: SampleCountFlags, usage: ImageUsageFlags, tiling: ImageTiling, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties) +ProcGetPhysicalDeviceSparseImageFormatProperties2 :: #type proc "system" (physicalDevice: PhysicalDevice, pFormatInfo: ^PhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties2) +ProcGetPhysicalDeviceSparseImageFormatProperties2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pFormatInfo: ^PhysicalDeviceSparseImageFormatInfo2, pPropertyCount: ^u32, pProperties: [^]SparseImageFormatProperties2) +ProcGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV :: #type proc "system" (physicalDevice: PhysicalDevice, pCombinationCount: ^u32, pCombinations: [^]FramebufferMixedSamplesCombinationNV) -> Result +ProcGetPhysicalDeviceSurfaceCapabilities2EXT :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceCapabilities: [^]SurfaceCapabilities2EXT) -> Result +ProcGetPhysicalDeviceSurfaceCapabilities2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pSurfaceCapabilities: [^]SurfaceCapabilities2KHR) -> Result +ProcGetPhysicalDeviceSurfaceCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceCapabilities: [^]SurfaceCapabilitiesKHR) -> Result +ProcGetPhysicalDeviceSurfaceFormats2KHR :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pSurfaceFormatCount: ^u32, pSurfaceFormats: [^]SurfaceFormat2KHR) -> Result +ProcGetPhysicalDeviceSurfaceFormatsKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pSurfaceFormatCount: ^u32, pSurfaceFormats: [^]SurfaceFormatKHR) -> Result +ProcGetPhysicalDeviceSurfacePresentModes2EXT :: #type proc "system" (physicalDevice: PhysicalDevice, pSurfaceInfo: ^PhysicalDeviceSurfaceInfo2KHR, pPresentModeCount: ^u32, pPresentModes: [^]PresentModeKHR) -> Result +ProcGetPhysicalDeviceSurfacePresentModesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, surface: SurfaceKHR, pPresentModeCount: ^u32, pPresentModes: [^]PresentModeKHR) -> Result +ProcGetPhysicalDeviceSurfaceSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, surface: SurfaceKHR, pSupported: ^b32) -> Result +ProcGetPhysicalDeviceToolProperties :: #type proc "system" (physicalDevice: PhysicalDevice, pToolCount: ^u32, pToolProperties: [^]PhysicalDeviceToolProperties) -> Result +ProcGetPhysicalDeviceToolPropertiesEXT :: #type proc "system" (physicalDevice: PhysicalDevice, pToolCount: ^u32, pToolProperties: [^]PhysicalDeviceToolProperties) -> Result +ProcGetPhysicalDeviceVideoCapabilitiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoProfile: ^VideoProfileInfoKHR, pCapabilities: [^]VideoCapabilitiesKHR) -> Result +ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pQualityLevelInfo: ^PhysicalDeviceVideoEncodeQualityLevelInfoKHR, pQualityLevelProperties: [^]VideoEncodeQualityLevelPropertiesKHR) -> Result +ProcGetPhysicalDeviceVideoFormatPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoFormatInfo: ^PhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ^u32, pVideoFormatProperties: [^]VideoFormatPropertiesKHR) -> Result +ProcGetPhysicalDeviceWaylandPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, display: ^wl_display) -> b32 +ProcGetPhysicalDeviceWin32PresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32) -> b32 +ProcGetPhysicalDeviceXcbPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, connection: ^xcb_connection_t, visual_id: xcb_visualid_t) -> b32 +ProcGetPhysicalDeviceXlibPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, dpy: ^XlibDisplay, visualID: XlibVisualID) -> b32 +ProcGetWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, deviceRelativeId: u32, pDisplay: ^DisplayKHR) -> Result +ProcReleaseDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result +ProcSubmitDebugUtilsMessageEXT :: #type proc "system" (instance: Instance, messageSeverity: DebugUtilsMessageSeverityFlagsEXT, messageTypes: DebugUtilsMessageTypeFlagsEXT, pCallbackData: ^DebugUtilsMessengerCallbackDataEXT) // Device Procedure Types ProcAcquireFullScreenExclusiveModeEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR) -> Result @@ -137,15 +143,23 @@ ProcBindAccelerationStructureMemoryNV :: #type proc "system ProcBindBufferMemory :: #type proc "system" (device: Device, buffer: Buffer, memory: DeviceMemory, memoryOffset: DeviceSize) -> Result ProcBindBufferMemory2 :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindBufferMemoryInfo) -> Result ProcBindBufferMemory2KHR :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindBufferMemoryInfo) -> Result +ProcBindDataGraphPipelineSessionMemoryARM :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindDataGraphPipelineSessionMemoryInfoARM) -> Result ProcBindImageMemory :: #type proc "system" (device: Device, image: Image, memory: DeviceMemory, memoryOffset: DeviceSize) -> Result ProcBindImageMemory2 :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindImageMemoryInfo) -> Result ProcBindImageMemory2KHR :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindImageMemoryInfo) -> Result ProcBindOpticalFlowSessionImageNV :: #type proc "system" (device: Device, session: OpticalFlowSessionNV, bindingPoint: OpticalFlowSessionBindingPointNV, view: ImageView, layout: ImageLayout) -> Result +ProcBindTensorMemoryARM :: #type proc "system" (device: Device, bindInfoCount: u32, pBindInfos: [^]BindTensorMemoryInfoARM) -> Result ProcBindVideoSessionMemoryKHR :: #type proc "system" (device: Device, videoSession: VideoSessionKHR, bindSessionMemoryInfoCount: u32, pBindSessionMemoryInfos: [^]BindVideoSessionMemoryInfoKHR) -> Result ProcBuildAccelerationStructuresKHR :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, infoCount: u32, pInfos: [^]AccelerationStructureBuildGeometryInfoKHR, ppBuildRangeInfos: ^[^]AccelerationStructureBuildRangeInfoKHR) -> Result ProcBuildMicromapsEXT :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, infoCount: u32, pInfos: [^]MicromapBuildInfoEXT) -> Result +ProcClearShaderInstrumentationMetricsARM :: #type proc "system" (device: Device, instrumentation: ShaderInstrumentationARM) +ProcCmdBeginConditionalRendering2EXT :: #type proc "system" (commandBuffer: CommandBuffer, pConditionalRenderingBegin: ^ConditionalRenderingBeginInfo2EXT) ProcCmdBeginConditionalRenderingEXT :: #type proc "system" (commandBuffer: CommandBuffer, pConditionalRenderingBegin: ^ConditionalRenderingBeginInfoEXT) +ProcCmdBeginCustomResolveEXT :: #type proc "system" (commandBuffer: CommandBuffer, pBeginCustomResolveInfo: ^BeginCustomResolveInfoEXT) ProcCmdBeginDebugUtilsLabelEXT :: #type proc "system" (commandBuffer: CommandBuffer, pLabelInfo: ^DebugUtilsLabelEXT) +ProcCmdBeginGpaSampleAMD :: #type proc "system" (commandBuffer: CommandBuffer, gpaSession: GpaSessionAMD, pGpaSampleBeginInfo: ^GpaSampleBeginInfoAMD, pSampleID: ^u32) -> Result +ProcCmdBeginGpaSessionAMD :: #type proc "system" (commandBuffer: CommandBuffer, gpaSession: GpaSessionAMD) -> Result +ProcCmdBeginPerTileExecutionQCOM :: #type proc "system" (commandBuffer: CommandBuffer, pPerTileBeginInfo: ^PerTileBeginInfoQCOM) ProcCmdBeginQuery :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, query: u32, flags: QueryControlFlags) ProcCmdBeginQueryIndexedEXT :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, query: u32, flags: QueryControlFlags, index: u32) ProcCmdBeginRenderPass :: #type proc "system" (commandBuffer: CommandBuffer, pRenderPassBegin: ^RenderPassBeginInfo, contents: SubpassContents) @@ -153,6 +167,8 @@ ProcCmdBeginRenderPass2 :: #type proc "system ProcCmdBeginRenderPass2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pRenderPassBegin: ^RenderPassBeginInfo, pSubpassBeginInfo: ^SubpassBeginInfo) ProcCmdBeginRendering :: #type proc "system" (commandBuffer: CommandBuffer, pRenderingInfo: ^RenderingInfo) ProcCmdBeginRenderingKHR :: #type proc "system" (commandBuffer: CommandBuffer, pRenderingInfo: ^RenderingInfo) +ProcCmdBeginShaderInstrumentationARM :: #type proc "system" (commandBuffer: CommandBuffer, instrumentation: ShaderInstrumentationARM) +ProcCmdBeginTransformFeedback2EXT :: #type proc "system" (commandBuffer: CommandBuffer, firstCounterRange: u32, counterRangeCount: u32, pCounterInfos: [^]BindTransformFeedbackBuffer2InfoEXT) ProcCmdBeginTransformFeedbackEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstCounterBuffer: u32, counterBufferCount: u32, pCounterBuffers: [^]Buffer, pCounterBufferOffsets: [^]DeviceSize) ProcCmdBeginVideoCodingKHR :: #type proc "system" (commandBuffer: CommandBuffer, pBeginInfo: ^VideoBeginCodingInfoKHR) ProcCmdBindDescriptorBufferEmbeddedSamplers2EXT :: #type proc "system" (commandBuffer: CommandBuffer, pBindDescriptorBufferEmbeddedSamplersInfo: ^BindDescriptorBufferEmbeddedSamplersInfoEXT) @@ -164,15 +180,21 @@ ProcCmdBindDescriptorSets2KHR :: #type proc "system ProcCmdBindIndexBuffer :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, indexType: IndexType) ProcCmdBindIndexBuffer2 :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, size: DeviceSize, indexType: IndexType) ProcCmdBindIndexBuffer2KHR :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, size: DeviceSize, indexType: IndexType) +ProcCmdBindIndexBuffer3KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^BindIndexBuffer3InfoKHR) ProcCmdBindInvocationMaskHUAWEI :: #type proc "system" (commandBuffer: CommandBuffer, imageView: ImageView, imageLayout: ImageLayout) ProcCmdBindPipeline :: #type proc "system" (commandBuffer: CommandBuffer, pipelineBindPoint: PipelineBindPoint, pipeline: Pipeline) ProcCmdBindPipelineShaderGroupNV :: #type proc "system" (commandBuffer: CommandBuffer, pipelineBindPoint: PipelineBindPoint, pipeline: Pipeline, groupIndex: u32) +ProcCmdBindResourceHeapEXT :: #type proc "system" (commandBuffer: CommandBuffer, pBindInfo: ^BindHeapInfoEXT) +ProcCmdBindSamplerHeapEXT :: #type proc "system" (commandBuffer: CommandBuffer, pBindInfo: ^BindHeapInfoEXT) ProcCmdBindShadersEXT :: #type proc "system" (commandBuffer: CommandBuffer, stageCount: u32, pStages: [^]ShaderStageFlags, pShaders: [^]ShaderEXT) ProcCmdBindShadingRateImageNV :: #type proc "system" (commandBuffer: CommandBuffer, imageView: ImageView, imageLayout: ImageLayout) +ProcCmdBindTileMemoryQCOM :: #type proc "system" (commandBuffer: CommandBuffer, pTileMemoryBindInfo: ^TileMemoryBindInfoQCOM) +ProcCmdBindTransformFeedbackBuffers2EXT :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBindingInfos: [^]BindTransformFeedbackBuffer2InfoEXT) ProcCmdBindTransformFeedbackBuffersEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBuffers: [^]Buffer, pOffsets: [^]DeviceSize, pSizes: [^]DeviceSize) ProcCmdBindVertexBuffers :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBuffers: [^]Buffer, pOffsets: [^]DeviceSize) ProcCmdBindVertexBuffers2 :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBuffers: [^]Buffer, pOffsets: [^]DeviceSize, pSizes: [^]DeviceSize, pStrides: [^]DeviceSize) ProcCmdBindVertexBuffers2EXT :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBuffers: [^]Buffer, pOffsets: [^]DeviceSize, pSizes: [^]DeviceSize, pStrides: [^]DeviceSize) +ProcCmdBindVertexBuffers3KHR :: #type proc "system" (commandBuffer: CommandBuffer, firstBinding: u32, bindingCount: u32, pBindingInfos: [^]BindVertexBuffer3InfoKHR) ProcCmdBlitImage :: #type proc "system" (commandBuffer: CommandBuffer, srcImage: Image, srcImageLayout: ImageLayout, dstImage: Image, dstImageLayout: ImageLayout, regionCount: u32, pRegions: [^]ImageBlit, filter: Filter) ProcCmdBlitImage2 :: #type proc "system" (commandBuffer: CommandBuffer, pBlitImageInfo: ^BlitImageInfo2) ProcCmdBlitImage2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pBlitImageInfo: ^BlitImageInfo2) @@ -196,48 +218,68 @@ ProcCmdCopyBuffer2KHR :: #type proc "system ProcCmdCopyBufferToImage :: #type proc "system" (commandBuffer: CommandBuffer, srcBuffer: Buffer, dstImage: Image, dstImageLayout: ImageLayout, regionCount: u32, pRegions: [^]BufferImageCopy) ProcCmdCopyBufferToImage2 :: #type proc "system" (commandBuffer: CommandBuffer, pCopyBufferToImageInfo: ^CopyBufferToImageInfo2) ProcCmdCopyBufferToImage2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyBufferToImageInfo: ^CopyBufferToImageInfo2) +ProcCmdCopyGpaSessionResultsAMD :: #type proc "system" (commandBuffer: CommandBuffer, gpaSession: GpaSessionAMD) ProcCmdCopyImage :: #type proc "system" (commandBuffer: CommandBuffer, srcImage: Image, srcImageLayout: ImageLayout, dstImage: Image, dstImageLayout: ImageLayout, regionCount: u32, pRegions: [^]ImageCopy) ProcCmdCopyImage2 :: #type proc "system" (commandBuffer: CommandBuffer, pCopyImageInfo: ^CopyImageInfo2) ProcCmdCopyImage2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyImageInfo: ^CopyImageInfo2) ProcCmdCopyImageToBuffer :: #type proc "system" (commandBuffer: CommandBuffer, srcImage: Image, srcImageLayout: ImageLayout, dstBuffer: Buffer, regionCount: u32, pRegions: [^]BufferImageCopy) ProcCmdCopyImageToBuffer2 :: #type proc "system" (commandBuffer: CommandBuffer, pCopyImageToBufferInfo: ^CopyImageToBufferInfo2) ProcCmdCopyImageToBuffer2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyImageToBufferInfo: ^CopyImageToBufferInfo2) +ProcCmdCopyImageToMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyMemoryInfo: ^CopyDeviceMemoryImageInfoKHR) +ProcCmdCopyMemoryIndirectKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyMemoryIndirectInfo: ^CopyMemoryIndirectInfoKHR) ProcCmdCopyMemoryIndirectNV :: #type proc "system" (commandBuffer: CommandBuffer, copyBufferAddress: DeviceAddress, copyCount: u32, stride: u32) +ProcCmdCopyMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyMemoryInfo: ^CopyDeviceMemoryInfoKHR) ProcCmdCopyMemoryToAccelerationStructureKHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyMemoryToAccelerationStructureInfoKHR) +ProcCmdCopyMemoryToImageIndirectKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyMemoryToImageIndirectInfo: ^CopyMemoryToImageIndirectInfoKHR) ProcCmdCopyMemoryToImageIndirectNV :: #type proc "system" (commandBuffer: CommandBuffer, copyBufferAddress: DeviceAddress, copyCount: u32, stride: u32, dstImage: Image, dstImageLayout: ImageLayout, pImageSubresources: [^]ImageSubresourceLayers) +ProcCmdCopyMemoryToImageKHR :: #type proc "system" (commandBuffer: CommandBuffer, pCopyMemoryInfo: ^CopyDeviceMemoryImageInfoKHR) ProcCmdCopyMemoryToMicromapEXT :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyMemoryToMicromapInfoEXT) ProcCmdCopyMicromapEXT :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyMicromapInfoEXT) ProcCmdCopyMicromapToMemoryEXT :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^CopyMicromapToMemoryInfoEXT) ProcCmdCopyQueryPoolResults :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, firstQuery: u32, queryCount: u32, dstBuffer: Buffer, dstOffset: DeviceSize, stride: DeviceSize, flags: QueryResultFlags) +ProcCmdCopyQueryPoolResultsToMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, firstQuery: u32, queryCount: u32, pDstRange: ^StridedDeviceAddressRangeKHR, dstFlags: AddressCommandFlagsKHR, queryResultFlags: QueryResultFlags) +ProcCmdCopyTensorARM :: #type proc "system" (commandBuffer: CommandBuffer, pCopyTensorInfo: ^CopyTensorInfoARM) ProcCmdCuLaunchKernelNVX :: #type proc "system" (commandBuffer: CommandBuffer, pLaunchInfo: ^CuLaunchInfoNVX) ProcCmdCudaLaunchKernelNV :: #type proc "system" (commandBuffer: CommandBuffer, pLaunchInfo: ^CudaLaunchInfoNV) ProcCmdDebugMarkerBeginEXT :: #type proc "system" (commandBuffer: CommandBuffer, pMarkerInfo: ^DebugMarkerMarkerInfoEXT) ProcCmdDebugMarkerEndEXT :: #type proc "system" (commandBuffer: CommandBuffer) ProcCmdDebugMarkerInsertEXT :: #type proc "system" (commandBuffer: CommandBuffer, pMarkerInfo: ^DebugMarkerMarkerInfoEXT) ProcCmdDecodeVideoKHR :: #type proc "system" (commandBuffer: CommandBuffer, pDecodeInfo: ^VideoDecodeInfoKHR) +ProcCmdDecompressMemoryEXT :: #type proc "system" (commandBuffer: CommandBuffer, pDecompressMemoryInfoEXT: ^DecompressMemoryInfoEXT) +ProcCmdDecompressMemoryIndirectCountEXT :: #type proc "system" (commandBuffer: CommandBuffer, decompressionMethod: MemoryDecompressionMethodFlagsEXT, indirectCommandsAddress: DeviceAddress, indirectCommandsCountAddress: DeviceAddress, maxDecompressionCount: u32, stride: u32) ProcCmdDecompressMemoryIndirectCountNV :: #type proc "system" (commandBuffer: CommandBuffer, indirectCommandsAddress: DeviceAddress, indirectCommandsCountAddress: DeviceAddress, stride: u32) ProcCmdDecompressMemoryNV :: #type proc "system" (commandBuffer: CommandBuffer, decompressRegionCount: u32, pDecompressMemoryRegions: [^]DecompressMemoryRegionNV) ProcCmdDispatch :: #type proc "system" (commandBuffer: CommandBuffer, groupCountX: u32, groupCountY: u32, groupCountZ: u32) ProcCmdDispatchBase :: #type proc "system" (commandBuffer: CommandBuffer, baseGroupX: u32, baseGroupY: u32, baseGroupZ: u32, groupCountX: u32, groupCountY: u32, groupCountZ: u32) ProcCmdDispatchBaseKHR :: #type proc "system" (commandBuffer: CommandBuffer, baseGroupX: u32, baseGroupY: u32, baseGroupZ: u32, groupCountX: u32, groupCountY: u32, groupCountZ: u32) +ProcCmdDispatchDataGraphARM :: #type proc "system" (commandBuffer: CommandBuffer, session: DataGraphPipelineSessionARM, pInfo: ^DataGraphPipelineDispatchInfoARM) ProcCmdDispatchGraphAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, pCountInfo: ^DispatchGraphCountInfoAMDX) ProcCmdDispatchGraphIndirectAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, pCountInfo: ^DispatchGraphCountInfoAMDX) ProcCmdDispatchGraphIndirectCountAMDX :: #type proc "system" (commandBuffer: CommandBuffer, scratch: DeviceAddress, scratchSize: DeviceSize, countInfo: DeviceAddress) ProcCmdDispatchIndirect :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize) +ProcCmdDispatchIndirect2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DispatchIndirect2InfoKHR) +ProcCmdDispatchTileQCOM :: #type proc "system" (commandBuffer: CommandBuffer, pDispatchTileInfo: ^DispatchTileInfoQCOM) ProcCmdDraw :: #type proc "system" (commandBuffer: CommandBuffer, vertexCount: u32, instanceCount: u32, firstVertex: u32, firstInstance: u32) ProcCmdDrawClusterHUAWEI :: #type proc "system" (commandBuffer: CommandBuffer, groupCountX: u32, groupCountY: u32, groupCountZ: u32) ProcCmdDrawClusterIndirectHUAWEI :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize) ProcCmdDrawIndexed :: #type proc "system" (commandBuffer: CommandBuffer, indexCount: u32, instanceCount: u32, firstIndex: u32, vertexOffset: i32, firstInstance: u32) ProcCmdDrawIndexedIndirect :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, drawCount: u32, stride: u32) +ProcCmdDrawIndexedIndirect2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirect2InfoKHR) ProcCmdDrawIndexedIndirectCount :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) +ProcCmdDrawIndexedIndirectCount2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirectCount2InfoKHR) ProcCmdDrawIndexedIndirectCountAMD :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawIndexedIndirectCountKHR :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawIndirect :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, drawCount: u32, stride: u32) +ProcCmdDrawIndirect2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirect2InfoKHR) +ProcCmdDrawIndirectByteCount2EXT :: #type proc "system" (commandBuffer: CommandBuffer, instanceCount: u32, firstInstance: u32, pCounterInfo: ^BindTransformFeedbackBuffer2InfoEXT, counterOffset: u32, vertexStride: u32) ProcCmdDrawIndirectByteCountEXT :: #type proc "system" (commandBuffer: CommandBuffer, instanceCount: u32, firstInstance: u32, counterBuffer: Buffer, counterBufferOffset: DeviceSize, counterOffset: u32, vertexStride: u32) ProcCmdDrawIndirectCount :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) +ProcCmdDrawIndirectCount2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirectCount2InfoKHR) ProcCmdDrawIndirectCountAMD :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawIndirectCountKHR :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawMeshTasksEXT :: #type proc "system" (commandBuffer: CommandBuffer, groupCountX: u32, groupCountY: u32, groupCountZ: u32) +ProcCmdDrawMeshTasksIndirect2EXT :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirect2InfoKHR) +ProcCmdDrawMeshTasksIndirectCount2EXT :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^DrawIndirectCount2InfoKHR) ProcCmdDrawMeshTasksIndirectCountEXT :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawMeshTasksIndirectCountNV :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, countBuffer: Buffer, countBufferOffset: DeviceSize, maxDrawCount: u32, stride: u32) ProcCmdDrawMeshTasksIndirectEXT :: #type proc "system" (commandBuffer: CommandBuffer, buffer: Buffer, offset: DeviceSize, drawCount: u32, stride: u32) @@ -248,19 +290,27 @@ ProcCmdDrawMultiIndexedEXT :: #type proc "system ProcCmdEncodeVideoKHR :: #type proc "system" (commandBuffer: CommandBuffer, pEncodeInfo: ^VideoEncodeInfoKHR) ProcCmdEndConditionalRenderingEXT :: #type proc "system" (commandBuffer: CommandBuffer) ProcCmdEndDebugUtilsLabelEXT :: #type proc "system" (commandBuffer: CommandBuffer) +ProcCmdEndGpaSampleAMD :: #type proc "system" (commandBuffer: CommandBuffer, gpaSession: GpaSessionAMD, sampleID: u32) +ProcCmdEndGpaSessionAMD :: #type proc "system" (commandBuffer: CommandBuffer, gpaSession: GpaSessionAMD) -> Result +ProcCmdEndPerTileExecutionQCOM :: #type proc "system" (commandBuffer: CommandBuffer, pPerTileEndInfo: ^PerTileEndInfoQCOM) ProcCmdEndQuery :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, query: u32) ProcCmdEndQueryIndexedEXT :: #type proc "system" (commandBuffer: CommandBuffer, queryPool: QueryPool, query: u32, index: u32) ProcCmdEndRenderPass :: #type proc "system" (commandBuffer: CommandBuffer) ProcCmdEndRenderPass2 :: #type proc "system" (commandBuffer: CommandBuffer, pSubpassEndInfo: ^SubpassEndInfo) ProcCmdEndRenderPass2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pSubpassEndInfo: ^SubpassEndInfo) ProcCmdEndRendering :: #type proc "system" (commandBuffer: CommandBuffer) +ProcCmdEndRendering2EXT :: #type proc "system" (commandBuffer: CommandBuffer, pRenderingEndInfo: ^RenderingEndInfoKHR) +ProcCmdEndRendering2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pRenderingEndInfo: ^RenderingEndInfoKHR) ProcCmdEndRenderingKHR :: #type proc "system" (commandBuffer: CommandBuffer) +ProcCmdEndShaderInstrumentationARM :: #type proc "system" (commandBuffer: CommandBuffer) +ProcCmdEndTransformFeedback2EXT :: #type proc "system" (commandBuffer: CommandBuffer, firstCounterRange: u32, counterRangeCount: u32, pCounterInfos: [^]BindTransformFeedbackBuffer2InfoEXT) ProcCmdEndTransformFeedbackEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstCounterBuffer: u32, counterBufferCount: u32, pCounterBuffers: [^]Buffer, pCounterBufferOffsets: [^]DeviceSize) ProcCmdEndVideoCodingKHR :: #type proc "system" (commandBuffer: CommandBuffer, pEndCodingInfo: ^VideoEndCodingInfoKHR) ProcCmdExecuteCommands :: #type proc "system" (commandBuffer: CommandBuffer, commandBufferCount: u32, pCommandBuffers: [^]CommandBuffer) ProcCmdExecuteGeneratedCommandsEXT :: #type proc "system" (commandBuffer: CommandBuffer, isPreprocessed: b32, pGeneratedCommandsInfo: ^GeneratedCommandsInfoEXT) ProcCmdExecuteGeneratedCommandsNV :: #type proc "system" (commandBuffer: CommandBuffer, isPreprocessed: b32, pGeneratedCommandsInfo: ^GeneratedCommandsInfoNV) ProcCmdFillBuffer :: #type proc "system" (commandBuffer: CommandBuffer, dstBuffer: Buffer, dstOffset: DeviceSize, size: DeviceSize, data: u32) +ProcCmdFillMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, pDstRange: ^DeviceAddressRangeKHR, dstFlags: AddressCommandFlagsKHR, data: u32) ProcCmdInitializeGraphScratchMemoryAMDX :: #type proc "system" (commandBuffer: CommandBuffer, executionGraph: Pipeline, scratch: DeviceAddress, scratchSize: DeviceSize) ProcCmdInsertDebugUtilsLabelEXT :: #type proc "system" (commandBuffer: CommandBuffer, pLabelInfo: ^DebugUtilsLabelEXT) ProcCmdNextSubpass :: #type proc "system" (commandBuffer: CommandBuffer, contents: SubpassContents) @@ -275,6 +325,7 @@ ProcCmdPreprocessGeneratedCommandsNV :: #type proc "system ProcCmdPushConstants :: #type proc "system" (commandBuffer: CommandBuffer, layout: PipelineLayout, stageFlags: ShaderStageFlags, offset: u32, size: u32, pValues: rawptr) ProcCmdPushConstants2 :: #type proc "system" (commandBuffer: CommandBuffer, pPushConstantsInfo: ^PushConstantsInfo) ProcCmdPushConstants2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pPushConstantsInfo: ^PushConstantsInfo) +ProcCmdPushDataEXT :: #type proc "system" (commandBuffer: CommandBuffer, pPushDataInfo: ^PushDataInfoEXT) ProcCmdPushDescriptorSet :: #type proc "system" (commandBuffer: CommandBuffer, pipelineBindPoint: PipelineBindPoint, layout: PipelineLayout, set: u32, descriptorWriteCount: u32, pDescriptorWrites: [^]WriteDescriptorSet) ProcCmdPushDescriptorSet2 :: #type proc "system" (commandBuffer: CommandBuffer, pPushDescriptorSetInfo: ^PushDescriptorSetInfo) ProcCmdPushDescriptorSet2KHR :: #type proc "system" (commandBuffer: CommandBuffer, pPushDescriptorSetInfo: ^PushDescriptorSetInfo) @@ -299,7 +350,9 @@ ProcCmdSetCoarseSampleOrderNV :: #type proc "system ProcCmdSetColorBlendAdvancedEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstAttachment: u32, attachmentCount: u32, pColorBlendAdvanced: ^ColorBlendAdvancedEXT) ProcCmdSetColorBlendEnableEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstAttachment: u32, attachmentCount: u32, pColorBlendEnables: [^]b32) ProcCmdSetColorBlendEquationEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstAttachment: u32, attachmentCount: u32, pColorBlendEquations: [^]ColorBlendEquationEXT) +ProcCmdSetColorWriteEnableEXT :: #type proc "system" (commandBuffer: CommandBuffer, attachmentCount: u32, pColorWriteEnables: [^]b32) ProcCmdSetColorWriteMaskEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstAttachment: u32, attachmentCount: u32, pColorWriteMasks: [^]ColorComponentFlags) +ProcCmdSetComputeOccupancyPriorityNV :: #type proc "system" (commandBuffer: CommandBuffer, pParameters: [^]ComputeOccupancyPriorityParametersNV) ProcCmdSetConservativeRasterizationModeEXT :: #type proc "system" (commandBuffer: CommandBuffer, conservativeRasterizationMode: ConservativeRasterizationModeEXT) ProcCmdSetCoverageModulationModeNV :: #type proc "system" (commandBuffer: CommandBuffer, coverageModulationMode: CoverageModulationModeNV) ProcCmdSetCoverageModulationTableEnableNV :: #type proc "system" (commandBuffer: CommandBuffer, coverageModulationTableEnable: b32) @@ -333,6 +386,7 @@ ProcCmdSetDeviceMaskKHR :: #type proc "system ProcCmdSetDiscardRectangleEXT :: #type proc "system" (commandBuffer: CommandBuffer, firstDiscardRectangle: u32, discardRectangleCount: u32, pDiscardRectangles: [^]Rect2D) ProcCmdSetDiscardRectangleEnableEXT :: #type proc "system" (commandBuffer: CommandBuffer, discardRectangleEnable: b32) ProcCmdSetDiscardRectangleModeEXT :: #type proc "system" (commandBuffer: CommandBuffer, discardRectangleMode: DiscardRectangleModeEXT) +ProcCmdSetDispatchParametersARM :: #type proc "system" (commandBuffer: CommandBuffer, pDispatchParameters: [^]DispatchParametersARM) ProcCmdSetEvent :: #type proc "system" (commandBuffer: CommandBuffer, event: Event, stageMask: PipelineStageFlags) ProcCmdSetEvent2 :: #type proc "system" (commandBuffer: CommandBuffer, event: Event, pDependencyInfo: ^DependencyInfo) ProcCmdSetEvent2KHR :: #type proc "system" (commandBuffer: CommandBuffer, event: Event, pDependencyInfo: ^DependencyInfo) @@ -358,6 +412,7 @@ ProcCmdSetPerformanceStreamMarkerINTEL :: #type proc "system ProcCmdSetPolygonModeEXT :: #type proc "system" (commandBuffer: CommandBuffer, polygonMode: PolygonMode) ProcCmdSetPrimitiveRestartEnable :: #type proc "system" (commandBuffer: CommandBuffer, primitiveRestartEnable: b32) ProcCmdSetPrimitiveRestartEnableEXT :: #type proc "system" (commandBuffer: CommandBuffer, primitiveRestartEnable: b32) +ProcCmdSetPrimitiveRestartIndexEXT :: #type proc "system" (commandBuffer: CommandBuffer, primitiveRestartIndex: u32) ProcCmdSetPrimitiveTopology :: #type proc "system" (commandBuffer: CommandBuffer, primitiveTopology: PrimitiveTopology) ProcCmdSetPrimitiveTopologyEXT :: #type proc "system" (commandBuffer: CommandBuffer, primitiveTopology: PrimitiveTopology) ProcCmdSetProvokingVertexModeEXT :: #type proc "system" (commandBuffer: CommandBuffer, provokingVertexMode: ProvokingVertexModeEXT) @@ -400,6 +455,7 @@ ProcCmdTraceRaysIndirectKHR :: #type proc "system ProcCmdTraceRaysKHR :: #type proc "system" (commandBuffer: CommandBuffer, pRaygenShaderBindingTable: [^]StridedDeviceAddressRegionKHR, pMissShaderBindingTable: [^]StridedDeviceAddressRegionKHR, pHitShaderBindingTable: [^]StridedDeviceAddressRegionKHR, pCallableShaderBindingTable: [^]StridedDeviceAddressRegionKHR, width: u32, height: u32, depth: u32) ProcCmdTraceRaysNV :: #type proc "system" (commandBuffer: CommandBuffer, raygenShaderBindingTableBuffer: Buffer, raygenShaderBindingOffset: DeviceSize, missShaderBindingTableBuffer: Buffer, missShaderBindingOffset: DeviceSize, missShaderBindingStride: DeviceSize, hitShaderBindingTableBuffer: Buffer, hitShaderBindingOffset: DeviceSize, hitShaderBindingStride: DeviceSize, callableShaderBindingTableBuffer: Buffer, callableShaderBindingOffset: DeviceSize, callableShaderBindingStride: DeviceSize, width: u32, height: u32, depth: u32) ProcCmdUpdateBuffer :: #type proc "system" (commandBuffer: CommandBuffer, dstBuffer: Buffer, dstOffset: DeviceSize, dataSize: DeviceSize, pData: rawptr) +ProcCmdUpdateMemoryKHR :: #type proc "system" (commandBuffer: CommandBuffer, pDstRange: ^DeviceAddressRangeKHR, dstFlags: AddressCommandFlagsKHR, dataSize: DeviceSize, pData: rawptr) ProcCmdUpdatePipelineIndirectBufferNV :: #type proc "system" (commandBuffer: CommandBuffer, pipelineBindPoint: PipelineBindPoint, pipeline: Pipeline) ProcCmdWaitEvents :: #type proc "system" (commandBuffer: CommandBuffer, eventCount: u32, pEvents: [^]Event, srcStageMask: PipelineStageFlags, dstStageMask: PipelineStageFlags, memoryBarrierCount: u32, pMemoryBarriers: [^]MemoryBarrier, bufferMemoryBarrierCount: u32, pBufferMemoryBarriers: [^]BufferMemoryBarrier, imageMemoryBarrierCount: u32, pImageMemoryBarriers: [^]ImageMemoryBarrier) ProcCmdWaitEvents2 :: #type proc "system" (commandBuffer: CommandBuffer, eventCount: u32, pEvents: [^]Event, pDependencyInfos: [^]DependencyInfo) @@ -408,6 +464,7 @@ ProcCmdWriteAccelerationStructuresPropertiesKHR :: #type proc "system ProcCmdWriteAccelerationStructuresPropertiesNV :: #type proc "system" (commandBuffer: CommandBuffer, accelerationStructureCount: u32, pAccelerationStructures: [^]AccelerationStructureNV, queryType: QueryType, queryPool: QueryPool, firstQuery: u32) ProcCmdWriteBufferMarker2AMD :: #type proc "system" (commandBuffer: CommandBuffer, stage: PipelineStageFlags2, dstBuffer: Buffer, dstOffset: DeviceSize, marker: u32) ProcCmdWriteBufferMarkerAMD :: #type proc "system" (commandBuffer: CommandBuffer, pipelineStage: PipelineStageFlags, dstBuffer: Buffer, dstOffset: DeviceSize, marker: u32) +ProcCmdWriteMarkerToMemoryAMD :: #type proc "system" (commandBuffer: CommandBuffer, pInfo: ^MemoryMarkerInfoAMD) ProcCmdWriteMicromapsPropertiesEXT :: #type proc "system" (commandBuffer: CommandBuffer, micromapCount: u32, pMicromaps: [^]MicromapEXT, queryType: QueryType, queryPool: QueryPool, firstQuery: u32) ProcCmdWriteTimestamp :: #type proc "system" (commandBuffer: CommandBuffer, pipelineStage: PipelineStageFlags, queryPool: QueryPool, query: u32) ProcCmdWriteTimestamp2 :: #type proc "system" (commandBuffer: CommandBuffer, stage: PipelineStageFlags2, queryPool: QueryPool, query: u32) @@ -426,6 +483,7 @@ ProcCopyMemoryToImageEXT :: #type proc "system ProcCopyMemoryToMicromapEXT :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pInfo: ^CopyMemoryToMicromapInfoEXT) -> Result ProcCopyMicromapEXT :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pInfo: ^CopyMicromapInfoEXT) -> Result ProcCopyMicromapToMemoryEXT :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pInfo: ^CopyMicromapToMemoryInfoEXT) -> Result +ProcCreateAccelerationStructure2KHR :: #type proc "system" (device: Device, pCreateInfo: ^AccelerationStructureCreateInfo2KHR, pAllocator: ^AllocationCallbacks, pAccelerationStructure: ^AccelerationStructureKHR) -> Result ProcCreateAccelerationStructureKHR :: #type proc "system" (device: Device, pCreateInfo: ^AccelerationStructureCreateInfoKHR, pAllocator: ^AllocationCallbacks, pAccelerationStructure: ^AccelerationStructureKHR) -> Result ProcCreateAccelerationStructureNV :: #type proc "system" (device: Device, pCreateInfo: ^AccelerationStructureCreateInfoNV, pAllocator: ^AllocationCallbacks, pAccelerationStructure: ^AccelerationStructureNV) -> Result ProcCreateBuffer :: #type proc "system" (device: Device, pCreateInfo: ^BufferCreateInfo, pAllocator: ^AllocationCallbacks, pBuffer: ^Buffer) -> Result @@ -436,6 +494,8 @@ ProcCreateCuFunctionNVX :: #type proc "system ProcCreateCuModuleNVX :: #type proc "system" (device: Device, pCreateInfo: ^CuModuleCreateInfoNVX, pAllocator: ^AllocationCallbacks, pModule: ^CuModuleNVX) -> Result ProcCreateCudaFunctionNV :: #type proc "system" (device: Device, pCreateInfo: ^CudaFunctionCreateInfoNV, pAllocator: ^AllocationCallbacks, pFunction: ^CudaFunctionNV) -> Result ProcCreateCudaModuleNV :: #type proc "system" (device: Device, pCreateInfo: ^CudaModuleCreateInfoNV, pAllocator: ^AllocationCallbacks, pModule: ^CudaModuleNV) -> Result +ProcCreateDataGraphPipelineSessionARM :: #type proc "system" (device: Device, pCreateInfo: ^DataGraphPipelineSessionCreateInfoARM, pAllocator: ^AllocationCallbacks, pSession: ^DataGraphPipelineSessionARM) -> Result +ProcCreateDataGraphPipelinesARM :: #type proc "system" (device: Device, deferredOperation: DeferredOperationKHR, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: [^]DataGraphPipelineCreateInfoARM, pAllocator: ^AllocationCallbacks, pPipelines: [^]Pipeline) -> Result ProcCreateDeferredOperationKHR :: #type proc "system" (device: Device, pAllocator: ^AllocationCallbacks, pDeferredOperation: ^DeferredOperationKHR) -> Result ProcCreateDescriptorPool :: #type proc "system" (device: Device, pCreateInfo: ^DescriptorPoolCreateInfo, pAllocator: ^AllocationCallbacks, pDescriptorPool: ^DescriptorPool) -> Result ProcCreateDescriptorSetLayout :: #type proc "system" (device: Device, pCreateInfo: ^DescriptorSetLayoutCreateInfo, pAllocator: ^AllocationCallbacks, pSetLayout: ^DescriptorSetLayout) -> Result @@ -443,8 +503,10 @@ ProcCreateDescriptorUpdateTemplate :: #type proc "system ProcCreateDescriptorUpdateTemplateKHR :: #type proc "system" (device: Device, pCreateInfo: ^DescriptorUpdateTemplateCreateInfo, pAllocator: ^AllocationCallbacks, pDescriptorUpdateTemplate: ^DescriptorUpdateTemplate) -> Result ProcCreateEvent :: #type proc "system" (device: Device, pCreateInfo: ^EventCreateInfo, pAllocator: ^AllocationCallbacks, pEvent: ^Event) -> Result ProcCreateExecutionGraphPipelinesAMDX :: #type proc "system" (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: [^]ExecutionGraphPipelineCreateInfoAMDX, pAllocator: ^AllocationCallbacks, pPipelines: [^]Pipeline) -> Result +ProcCreateExternalComputeQueueNV :: #type proc "system" (device: Device, pCreateInfo: ^ExternalComputeQueueCreateInfoNV, pAllocator: ^AllocationCallbacks, pExternalQueue: ^ExternalComputeQueueNV) -> Result ProcCreateFence :: #type proc "system" (device: Device, pCreateInfo: ^FenceCreateInfo, pAllocator: ^AllocationCallbacks, pFence: ^Fence) -> Result ProcCreateFramebuffer :: #type proc "system" (device: Device, pCreateInfo: ^FramebufferCreateInfo, pAllocator: ^AllocationCallbacks, pFramebuffer: ^Framebuffer) -> Result +ProcCreateGpaSessionAMD :: #type proc "system" (device: Device, pCreateInfo: ^GpaSessionCreateInfoAMD, pAllocator: ^AllocationCallbacks, pGpaSession: ^GpaSessionAMD) -> Result ProcCreateGraphicsPipelines :: #type proc "system" (device: Device, pipelineCache: PipelineCache, createInfoCount: u32, pCreateInfos: [^]GraphicsPipelineCreateInfo, pAllocator: ^AllocationCallbacks, pPipelines: [^]Pipeline) -> Result ProcCreateImage :: #type proc "system" (device: Device, pCreateInfo: ^ImageCreateInfo, pAllocator: ^AllocationCallbacks, pImage: ^Image) -> Result ProcCreateImageView :: #type proc "system" (device: Device, pCreateInfo: ^ImageViewCreateInfo, pAllocator: ^AllocationCallbacks, pView: ^ImageView) -> Result @@ -468,10 +530,13 @@ ProcCreateSampler :: #type proc "system ProcCreateSamplerYcbcrConversion :: #type proc "system" (device: Device, pCreateInfo: ^SamplerYcbcrConversionCreateInfo, pAllocator: ^AllocationCallbacks, pYcbcrConversion: ^SamplerYcbcrConversion) -> Result ProcCreateSamplerYcbcrConversionKHR :: #type proc "system" (device: Device, pCreateInfo: ^SamplerYcbcrConversionCreateInfo, pAllocator: ^AllocationCallbacks, pYcbcrConversion: ^SamplerYcbcrConversion) -> Result ProcCreateSemaphore :: #type proc "system" (device: Device, pCreateInfo: ^SemaphoreCreateInfo, pAllocator: ^AllocationCallbacks, pSemaphore: ^Semaphore) -> Result +ProcCreateShaderInstrumentationARM :: #type proc "system" (device: Device, pCreateInfo: ^ShaderInstrumentationCreateInfoARM, pAllocator: ^AllocationCallbacks, pInstrumentation: ^ShaderInstrumentationARM) -> Result ProcCreateShaderModule :: #type proc "system" (device: Device, pCreateInfo: ^ShaderModuleCreateInfo, pAllocator: ^AllocationCallbacks, pShaderModule: ^ShaderModule) -> Result ProcCreateShadersEXT :: #type proc "system" (device: Device, createInfoCount: u32, pCreateInfos: [^]ShaderCreateInfoEXT, pAllocator: ^AllocationCallbacks, pShaders: [^]ShaderEXT) -> Result ProcCreateSharedSwapchainsKHR :: #type proc "system" (device: Device, swapchainCount: u32, pCreateInfos: [^]SwapchainCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSwapchains: [^]SwapchainKHR) -> Result ProcCreateSwapchainKHR :: #type proc "system" (device: Device, pCreateInfo: ^SwapchainCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSwapchain: ^SwapchainKHR) -> Result +ProcCreateTensorARM :: #type proc "system" (device: Device, pCreateInfo: ^TensorCreateInfoARM, pAllocator: ^AllocationCallbacks, pTensor: ^TensorARM) -> Result +ProcCreateTensorViewARM :: #type proc "system" (device: Device, pCreateInfo: ^TensorViewCreateInfoARM, pAllocator: ^AllocationCallbacks, pView: ^TensorViewARM) -> Result ProcCreateValidationCacheEXT :: #type proc "system" (device: Device, pCreateInfo: ^ValidationCacheCreateInfoEXT, pAllocator: ^AllocationCallbacks, pValidationCache: ^ValidationCacheEXT) -> Result ProcCreateVideoSessionKHR :: #type proc "system" (device: Device, pCreateInfo: ^VideoSessionCreateInfoKHR, pAllocator: ^AllocationCallbacks, pVideoSession: ^VideoSessionKHR) -> Result ProcCreateVideoSessionParametersKHR :: #type proc "system" (device: Device, pCreateInfo: ^VideoSessionParametersCreateInfoKHR, pAllocator: ^AllocationCallbacks, pVideoSessionParameters: [^]VideoSessionParametersKHR) -> Result @@ -487,6 +552,7 @@ ProcDestroyCuFunctionNVX :: #type proc "system ProcDestroyCuModuleNVX :: #type proc "system" (device: Device, module: CuModuleNVX, pAllocator: ^AllocationCallbacks) ProcDestroyCudaFunctionNV :: #type proc "system" (device: Device, function: CudaFunctionNV, pAllocator: ^AllocationCallbacks) ProcDestroyCudaModuleNV :: #type proc "system" (device: Device, module: CudaModuleNV, pAllocator: ^AllocationCallbacks) +ProcDestroyDataGraphPipelineSessionARM :: #type proc "system" (device: Device, session: DataGraphPipelineSessionARM, pAllocator: ^AllocationCallbacks) ProcDestroyDeferredOperationKHR :: #type proc "system" (device: Device, operation: DeferredOperationKHR, pAllocator: ^AllocationCallbacks) ProcDestroyDescriptorPool :: #type proc "system" (device: Device, descriptorPool: DescriptorPool, pAllocator: ^AllocationCallbacks) ProcDestroyDescriptorSetLayout :: #type proc "system" (device: Device, descriptorSetLayout: DescriptorSetLayout, pAllocator: ^AllocationCallbacks) @@ -494,8 +560,10 @@ ProcDestroyDescriptorUpdateTemplate :: #type proc "system ProcDestroyDescriptorUpdateTemplateKHR :: #type proc "system" (device: Device, descriptorUpdateTemplate: DescriptorUpdateTemplate, pAllocator: ^AllocationCallbacks) ProcDestroyDevice :: #type proc "system" (device: Device, pAllocator: ^AllocationCallbacks) ProcDestroyEvent :: #type proc "system" (device: Device, event: Event, pAllocator: ^AllocationCallbacks) +ProcDestroyExternalComputeQueueNV :: #type proc "system" (device: Device, externalQueue: ExternalComputeQueueNV, pAllocator: ^AllocationCallbacks) ProcDestroyFence :: #type proc "system" (device: Device, fence: Fence, pAllocator: ^AllocationCallbacks) ProcDestroyFramebuffer :: #type proc "system" (device: Device, framebuffer: Framebuffer, pAllocator: ^AllocationCallbacks) +ProcDestroyGpaSessionAMD :: #type proc "system" (device: Device, gpaSession: GpaSessionAMD, pAllocator: ^AllocationCallbacks) ProcDestroyImage :: #type proc "system" (device: Device, image: Image, pAllocator: ^AllocationCallbacks) ProcDestroyImageView :: #type proc "system" (device: Device, imageView: ImageView, pAllocator: ^AllocationCallbacks) ProcDestroyIndirectCommandsLayoutEXT :: #type proc "system" (device: Device, indirectCommandsLayout: IndirectCommandsLayoutEXT, pAllocator: ^AllocationCallbacks) @@ -516,8 +584,11 @@ ProcDestroySamplerYcbcrConversion :: #type proc "system ProcDestroySamplerYcbcrConversionKHR :: #type proc "system" (device: Device, ycbcrConversion: SamplerYcbcrConversion, pAllocator: ^AllocationCallbacks) ProcDestroySemaphore :: #type proc "system" (device: Device, semaphore: Semaphore, pAllocator: ^AllocationCallbacks) ProcDestroyShaderEXT :: #type proc "system" (device: Device, shader: ShaderEXT, pAllocator: ^AllocationCallbacks) +ProcDestroyShaderInstrumentationARM :: #type proc "system" (device: Device, instrumentation: ShaderInstrumentationARM, pAllocator: ^AllocationCallbacks) ProcDestroyShaderModule :: #type proc "system" (device: Device, shaderModule: ShaderModule, pAllocator: ^AllocationCallbacks) ProcDestroySwapchainKHR :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pAllocator: ^AllocationCallbacks) +ProcDestroyTensorARM :: #type proc "system" (device: Device, tensor: TensorARM, pAllocator: ^AllocationCallbacks) +ProcDestroyTensorViewARM :: #type proc "system" (device: Device, tensorView: TensorViewARM, pAllocator: ^AllocationCallbacks) ProcDestroyValidationCacheEXT :: #type proc "system" (device: Device, validationCache: ValidationCacheEXT, pAllocator: ^AllocationCallbacks) ProcDestroyVideoSessionKHR :: #type proc "system" (device: Device, videoSession: VideoSessionKHR, pAllocator: ^AllocationCallbacks) ProcDestroyVideoSessionParametersKHR :: #type proc "system" (device: Device, videoSessionParameters: VideoSessionParametersKHR, pAllocator: ^AllocationCallbacks) @@ -532,7 +603,7 @@ ProcFreeMemory :: #type proc "system ProcGetAccelerationStructureBuildSizesKHR :: #type proc "system" (device: Device, buildType: AccelerationStructureBuildTypeKHR, pBuildInfo: ^AccelerationStructureBuildGeometryInfoKHR, pMaxPrimitiveCounts: [^]u32, pSizeInfo: ^AccelerationStructureBuildSizesInfoKHR) ProcGetAccelerationStructureDeviceAddressKHR :: #type proc "system" (device: Device, pInfo: ^AccelerationStructureDeviceAddressInfoKHR) -> DeviceAddress ProcGetAccelerationStructureHandleNV :: #type proc "system" (device: Device, accelerationStructure: AccelerationStructureNV, dataSize: int, pData: rawptr) -> Result -ProcGetAccelerationStructureMemoryRequirementsNV :: #type proc "system" (device: Device, pInfo: ^AccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: [^]MemoryRequirements2KHR) +ProcGetAccelerationStructureMemoryRequirementsNV :: #type proc "system" (device: Device, pInfo: ^AccelerationStructureMemoryRequirementsInfoNV, pMemoryRequirements: [^]MemoryRequirements2) ProcGetAccelerationStructureOpaqueCaptureDescriptorDataEXT :: #type proc "system" (device: Device, pInfo: ^AccelerationStructureCaptureDescriptorDataInfoEXT, pData: rawptr) -> Result ProcGetBufferDeviceAddress :: #type proc "system" (device: Device, pInfo: ^BufferDeviceAddressInfo) -> DeviceAddress ProcGetBufferDeviceAddressEXT :: #type proc "system" (device: Device, pInfo: ^BufferDeviceAddressInfo) -> DeviceAddress @@ -547,6 +618,10 @@ ProcGetCalibratedTimestampsEXT :: #type proc "system ProcGetCalibratedTimestampsKHR :: #type proc "system" (device: Device, timestampCount: u32, pTimestampInfos: [^]CalibratedTimestampInfoKHR, pTimestamps: [^]u64, pMaxDeviation: ^u64) -> Result ProcGetClusterAccelerationStructureBuildSizesNV :: #type proc "system" (device: Device, pInfo: ^ClusterAccelerationStructureInputInfoNV, pSizeInfo: ^AccelerationStructureBuildSizesInfoKHR) ProcGetCudaModuleCacheNV :: #type proc "system" (device: Device, module: CudaModuleNV, pCacheSize: ^int, pCacheData: rawptr) -> Result +ProcGetDataGraphPipelineAvailablePropertiesARM :: #type proc "system" (device: Device, pPipelineInfo: ^DataGraphPipelineInfoARM, pPropertiesCount: ^u32, pProperties: [^]DataGraphPipelinePropertyARM) -> Result +ProcGetDataGraphPipelinePropertiesARM :: #type proc "system" (device: Device, pPipelineInfo: ^DataGraphPipelineInfoARM, propertiesCount: u32, pProperties: [^]DataGraphPipelinePropertyQueryResultARM) -> Result +ProcGetDataGraphPipelineSessionBindPointRequirementsARM :: #type proc "system" (device: Device, pInfo: ^DataGraphPipelineSessionBindPointRequirementsInfoARM, pBindPointRequirementCount: ^u32, pBindPointRequirements: [^]DataGraphPipelineSessionBindPointRequirementARM) -> Result +ProcGetDataGraphPipelineSessionMemoryRequirementsARM :: #type proc "system" (device: Device, pInfo: ^DataGraphPipelineSessionMemoryRequirementsInfoARM, pMemoryRequirements: [^]MemoryRequirements2) ProcGetDeferredOperationMaxConcurrencyKHR :: #type proc "system" (device: Device, operation: DeferredOperationKHR) -> u32 ProcGetDeferredOperationResultKHR :: #type proc "system" (device: Device, operation: DeferredOperationKHR) -> Result ProcGetDescriptorEXT :: #type proc "system" (device: Device, pDescriptorInfo: ^DescriptorGetInfoEXT, dataSize: int, pDescriptor: rawptr) @@ -559,7 +634,10 @@ ProcGetDescriptorSetLayoutSupportKHR :: #type proc "system ProcGetDeviceAccelerationStructureCompatibilityKHR :: #type proc "system" (device: Device, pVersionInfo: ^AccelerationStructureVersionInfoKHR, pCompatibility: ^AccelerationStructureCompatibilityKHR) ProcGetDeviceBufferMemoryRequirements :: #type proc "system" (device: Device, pInfo: ^DeviceBufferMemoryRequirements, pMemoryRequirements: [^]MemoryRequirements2) ProcGetDeviceBufferMemoryRequirementsKHR :: #type proc "system" (device: Device, pInfo: ^DeviceBufferMemoryRequirements, pMemoryRequirements: [^]MemoryRequirements2) +ProcGetDeviceCombinedImageSamplerIndexNVX :: #type proc "system" (device: Device, imageViewIndex: u64, samplerIndex: u64) -> u64 +ProcGetDeviceFaultDebugInfoKHR :: #type proc "system" (device: Device, pDebugInfo: ^DeviceFaultDebugInfoKHR) -> Result ProcGetDeviceFaultInfoEXT :: #type proc "system" (device: Device, pFaultCounts: [^]DeviceFaultCountsEXT, pFaultInfo: ^DeviceFaultInfoEXT) -> Result +ProcGetDeviceFaultReportsKHR :: #type proc "system" (device: Device, timeout: u64, pFaultCounts: [^]u32, pFaultInfo: ^DeviceFaultInfoKHR) -> Result ProcGetDeviceGroupPeerMemoryFeatures :: #type proc "system" (device: Device, heapIndex: u32, localDeviceIndex: u32, remoteDeviceIndex: u32, pPeerMemoryFeatures: [^]PeerMemoryFeatureFlags) ProcGetDeviceGroupPeerMemoryFeaturesKHR :: #type proc "system" (device: Device, heapIndex: u32, localDeviceIndex: u32, remoteDeviceIndex: u32, pPeerMemoryFeatures: [^]PeerMemoryFeatureFlags) ProcGetDeviceGroupPresentCapabilitiesKHR :: #type proc "system" (device: Device, pDeviceGroupPresentCapabilities: [^]DeviceGroupPresentCapabilitiesKHR) -> Result @@ -579,6 +657,7 @@ ProcGetDeviceProcAddr :: #type proc "system ProcGetDeviceQueue :: #type proc "system" (device: Device, queueFamilyIndex: u32, queueIndex: u32, pQueue: ^Queue) ProcGetDeviceQueue2 :: #type proc "system" (device: Device, pQueueInfo: ^DeviceQueueInfo2, pQueue: ^Queue) ProcGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI :: #type proc "system" (device: Device, renderpass: RenderPass, pMaxWorkgroupSize: ^Extent2D) -> Result +ProcGetDeviceTensorMemoryRequirementsARM :: #type proc "system" (device: Device, pInfo: ^DeviceTensorMemoryRequirementsARM, pMemoryRequirements: [^]MemoryRequirements2) ProcGetDynamicRenderingTilePropertiesQCOM :: #type proc "system" (device: Device, pRenderingInfo: ^RenderingInfo, pProperties: [^]TilePropertiesQCOM) -> Result ProcGetEncodedVideoSessionParametersKHR :: #type proc "system" (device: Device, pVideoSessionParametersInfo: ^VideoEncodeSessionParametersGetInfoKHR, pFeedbackInfo: ^VideoEncodeSessionParametersFeedbackInfoKHR, pDataSize: ^int, pData: rawptr) -> Result ProcGetEventStatus :: #type proc "system" (device: Device, event: Event) -> Result @@ -590,10 +669,14 @@ ProcGetFenceWin32HandleKHR :: #type proc "system ProcGetFramebufferTilePropertiesQCOM :: #type proc "system" (device: Device, framebuffer: Framebuffer, pPropertiesCount: ^u32, pProperties: [^]TilePropertiesQCOM) -> Result ProcGetGeneratedCommandsMemoryRequirementsEXT :: #type proc "system" (device: Device, pInfo: ^GeneratedCommandsMemoryRequirementsInfoEXT, pMemoryRequirements: [^]MemoryRequirements2) ProcGetGeneratedCommandsMemoryRequirementsNV :: #type proc "system" (device: Device, pInfo: ^GeneratedCommandsMemoryRequirementsInfoNV, pMemoryRequirements: [^]MemoryRequirements2) +ProcGetGpaDeviceClockInfoAMD :: #type proc "system" (device: Device, pInfo: ^GpaDeviceGetClockInfoAMD) -> Result +ProcGetGpaSessionResultsAMD :: #type proc "system" (device: Device, gpaSession: GpaSessionAMD, sampleID: u32, pSizeInBytes: [^]int, pData: rawptr) -> Result +ProcGetGpaSessionStatusAMD :: #type proc "system" (device: Device, gpaSession: GpaSessionAMD) -> Result ProcGetImageDrmFormatModifierPropertiesEXT :: #type proc "system" (device: Device, image: Image, pProperties: [^]ImageDrmFormatModifierPropertiesEXT) -> Result ProcGetImageMemoryRequirements :: #type proc "system" (device: Device, image: Image, pMemoryRequirements: [^]MemoryRequirements) ProcGetImageMemoryRequirements2 :: #type proc "system" (device: Device, pInfo: ^ImageMemoryRequirementsInfo2, pMemoryRequirements: [^]MemoryRequirements2) ProcGetImageMemoryRequirements2KHR :: #type proc "system" (device: Device, pInfo: ^ImageMemoryRequirementsInfo2, pMemoryRequirements: [^]MemoryRequirements2) +ProcGetImageOpaqueCaptureDataEXT :: #type proc "system" (device: Device, imageCount: u32, pImages: [^]Image, pDatas: [^]HostAddressRangeEXT) -> Result ProcGetImageOpaqueCaptureDescriptorDataEXT :: #type proc "system" (device: Device, pInfo: ^ImageCaptureDescriptorDataInfoEXT, pData: rawptr) -> Result ProcGetImageSparseMemoryRequirements :: #type proc "system" (device: Device, image: Image, pSparseMemoryRequirementCount: ^u32, pSparseMemoryRequirements: [^]SparseImageMemoryRequirements) ProcGetImageSparseMemoryRequirements2 :: #type proc "system" (device: Device, pInfo: ^ImageSparseMemoryRequirementsInfo2, pSparseMemoryRequirementCount: ^u32, pSparseMemoryRequirements: [^]SparseImageMemoryRequirements2) @@ -618,6 +701,7 @@ ProcGetMemoryWin32HandleNV :: #type proc "system ProcGetMemoryWin32HandlePropertiesKHR :: #type proc "system" (device: Device, handleType: ExternalMemoryHandleTypeFlags, handle: HANDLE, pMemoryWin32HandleProperties: [^]MemoryWin32HandlePropertiesKHR) -> Result ProcGetMicromapBuildSizesEXT :: #type proc "system" (device: Device, buildType: AccelerationStructureBuildTypeKHR, pBuildInfo: ^MicromapBuildInfoEXT, pSizeInfo: ^MicromapBuildSizesInfoEXT) ProcGetPartitionedAccelerationStructuresBuildSizesNV :: #type proc "system" (device: Device, pInfo: ^PartitionedAccelerationStructureInstancesInputNV, pSizeInfo: ^AccelerationStructureBuildSizesInfoKHR) +ProcGetPastPresentationTimingEXT :: #type proc "system" (device: Device, pPastPresentationTimingInfo: ^PastPresentationTimingInfoEXT, pPastPresentationTimingProperties: [^]PastPresentationTimingPropertiesEXT) -> Result ProcGetPastPresentationTimingGOOGLE :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pPresentationTimingCount: ^u32, pPresentationTimings: [^]PastPresentationTimingGOOGLE) -> Result ProcGetPerformanceParameterINTEL :: #type proc "system" (device: Device, parameter: PerformanceParameterTypeINTEL, pValue: ^PerformanceValueINTEL) -> Result ProcGetPipelineBinaryDataKHR :: #type proc "system" (device: Device, pInfo: ^PipelineBinaryDataInfoKHR, pPipelineBinaryKey: ^PipelineBinaryKeyKHR, pPipelineBinaryDataSize: ^int, pPipelineBinaryData: rawptr) -> Result @@ -628,7 +712,7 @@ ProcGetPipelineExecutableStatisticsKHR :: #type proc "system ProcGetPipelineIndirectDeviceAddressNV :: #type proc "system" (device: Device, pInfo: ^PipelineIndirectDeviceAddressInfoNV) -> DeviceAddress ProcGetPipelineIndirectMemoryRequirementsNV :: #type proc "system" (device: Device, pCreateInfo: ^ComputePipelineCreateInfo, pMemoryRequirements: [^]MemoryRequirements2) ProcGetPipelineKeyKHR :: #type proc "system" (device: Device, pPipelineCreateInfo: ^PipelineCreateInfoKHR, pPipelineKey: ^PipelineBinaryKeyKHR) -> Result -ProcGetPipelinePropertiesEXT :: #type proc "system" (device: Device, pPipelineInfo: ^PipelineInfoEXT, pPipelineProperties: [^]BaseOutStructure) -> Result +ProcGetPipelinePropertiesEXT :: #type proc "system" (device: Device, pPipelineInfo: ^PipelineInfoKHR, pPipelineProperties: [^]BaseOutStructure) -> Result ProcGetPrivateData :: #type proc "system" (device: Device, objectType: ObjectType, objectHandle: u64, privateDataSlot: PrivateDataSlot, pData: ^u64) ProcGetPrivateDataEXT :: #type proc "system" (device: Device, objectType: ObjectType, objectHandle: u64, privateDataSlot: PrivateDataSlot, pData: ^u64) ProcGetQueryPoolResults :: #type proc "system" (device: Device, queryPool: QueryPool, firstQuery: u32, queryCount: u32, dataSize: int, pData: rawptr, stride: DeviceSize, flags: QueryResultFlags) -> Result @@ -649,11 +733,18 @@ ProcGetSemaphoreFdKHR :: #type proc "system ProcGetSemaphoreWin32HandleKHR :: #type proc "system" (device: Device, pGetWin32HandleInfo: ^SemaphoreGetWin32HandleInfoKHR, pHandle: ^HANDLE) -> Result ProcGetShaderBinaryDataEXT :: #type proc "system" (device: Device, shader: ShaderEXT, pDataSize: ^int, pData: rawptr) -> Result ProcGetShaderInfoAMD :: #type proc "system" (device: Device, pipeline: Pipeline, shaderStage: ShaderStageFlags, infoType: ShaderInfoTypeAMD, pInfoSize: ^int, pInfo: rawptr) -> Result +ProcGetShaderInstrumentationValuesARM :: #type proc "system" (device: Device, instrumentation: ShaderInstrumentationARM, pMetricBlockCount: ^u32, pMetricValues: rawptr, flags: ShaderInstrumentationValuesFlagsARM) -> Result ProcGetShaderModuleCreateInfoIdentifierEXT :: #type proc "system" (device: Device, pCreateInfo: ^ShaderModuleCreateInfo, pIdentifier: ^ShaderModuleIdentifierEXT) ProcGetShaderModuleIdentifierEXT :: #type proc "system" (device: Device, shaderModule: ShaderModule, pIdentifier: ^ShaderModuleIdentifierEXT) ProcGetSwapchainCounterEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR, counter: SurfaceCounterFlagsEXT, pCounterValue: ^u64) -> Result ProcGetSwapchainImagesKHR :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pSwapchainImageCount: ^u32, pSwapchainImages: [^]Image) -> Result ProcGetSwapchainStatusKHR :: #type proc "system" (device: Device, swapchain: SwapchainKHR) -> Result +ProcGetSwapchainTimeDomainPropertiesEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pSwapchainTimeDomainProperties: [^]SwapchainTimeDomainPropertiesEXT, pTimeDomainsCounter: ^u64) -> Result +ProcGetSwapchainTimingPropertiesEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pSwapchainTimingProperties: [^]SwapchainTimingPropertiesEXT, pSwapchainTimingPropertiesCounter: ^u64) -> Result +ProcGetTensorMemoryRequirementsARM :: #type proc "system" (device: Device, pInfo: ^TensorMemoryRequirementsInfoARM, pMemoryRequirements: [^]MemoryRequirements2) +ProcGetTensorOpaqueCaptureDataARM :: #type proc "system" (device: Device, tensorCount: u32, pTensors: [^]TensorARM, pDatas: [^]HostAddressRangeEXT) -> Result +ProcGetTensorOpaqueCaptureDescriptorDataARM :: #type proc "system" (device: Device, pInfo: ^TensorCaptureDescriptorDataInfoARM, pData: rawptr) -> Result +ProcGetTensorViewOpaqueCaptureDescriptorDataARM :: #type proc "system" (device: Device, pInfo: ^TensorViewCaptureDescriptorDataInfoARM, pData: rawptr) -> Result ProcGetValidationCacheDataEXT :: #type proc "system" (device: Device, validationCache: ValidationCacheEXT, pDataSize: ^int, pData: rawptr) -> Result ProcGetVideoSessionMemoryRequirementsKHR :: #type proc "system" (device: Device, videoSession: VideoSessionKHR, pMemoryRequirementsCount: ^u32, pMemoryRequirements: [^]VideoSessionMemoryRequirementsKHR) -> Result ProcImportFenceFdKHR :: #type proc "system" (device: Device, pImportFenceFdInfo: ^ImportFenceFdInfoKHR) -> Result @@ -679,30 +770,35 @@ ProcQueueSubmit :: #type proc "system ProcQueueSubmit2 :: #type proc "system" (queue: Queue, submitCount: u32, pSubmits: [^]SubmitInfo2, fence: Fence) -> Result ProcQueueSubmit2KHR :: #type proc "system" (queue: Queue, submitCount: u32, pSubmits: [^]SubmitInfo2, fence: Fence) -> Result ProcQueueWaitIdle :: #type proc "system" (queue: Queue) -> Result +ProcRegisterCustomBorderColorEXT :: #type proc "system" (device: Device, pBorderColor: ^SamplerCustomBorderColorCreateInfoEXT, requestIndex: b32, pIndex: ^u32) -> Result ProcRegisterDeviceEventEXT :: #type proc "system" (device: Device, pDeviceEventInfo: ^DeviceEventInfoEXT, pAllocator: ^AllocationCallbacks, pFence: ^Fence) -> Result ProcRegisterDisplayEventEXT :: #type proc "system" (device: Device, display: DisplayKHR, pDisplayEventInfo: ^DisplayEventInfoEXT, pAllocator: ^AllocationCallbacks, pFence: ^Fence) -> Result ProcReleaseCapturedPipelineDataKHR :: #type proc "system" (device: Device, pInfo: ^ReleaseCapturedPipelineDataInfoKHR, pAllocator: ^AllocationCallbacks) -> Result ProcReleaseFullScreenExclusiveModeEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR) -> Result ProcReleasePerformanceConfigurationINTEL :: #type proc "system" (device: Device, configuration: PerformanceConfigurationINTEL) -> Result ProcReleaseProfilingLockKHR :: #type proc "system" (device: Device) -ProcReleaseSwapchainImagesEXT :: #type proc "system" (device: Device, pReleaseInfo: ^ReleaseSwapchainImagesInfoEXT) -> Result +ProcReleaseSwapchainImagesEXT :: #type proc "system" (device: Device, pReleaseInfo: ^ReleaseSwapchainImagesInfoKHR) -> Result +ProcReleaseSwapchainImagesKHR :: #type proc "system" (device: Device, pReleaseInfo: ^ReleaseSwapchainImagesInfoKHR) -> Result ProcResetCommandBuffer :: #type proc "system" (commandBuffer: CommandBuffer, flags: CommandBufferResetFlags) -> Result ProcResetCommandPool :: #type proc "system" (device: Device, commandPool: CommandPool, flags: CommandPoolResetFlags) -> Result ProcResetDescriptorPool :: #type proc "system" (device: Device, descriptorPool: DescriptorPool, flags: DescriptorPoolResetFlags) -> Result ProcResetEvent :: #type proc "system" (device: Device, event: Event) -> Result ProcResetFences :: #type proc "system" (device: Device, fenceCount: u32, pFences: [^]Fence) -> Result +ProcResetGpaSessionAMD :: #type proc "system" (device: Device, gpaSession: GpaSessionAMD) -> Result ProcResetQueryPool :: #type proc "system" (device: Device, queryPool: QueryPool, firstQuery: u32, queryCount: u32) ProcResetQueryPoolEXT :: #type proc "system" (device: Device, queryPool: QueryPool, firstQuery: u32, queryCount: u32) ProcSetDebugUtilsObjectNameEXT :: #type proc "system" (device: Device, pNameInfo: ^DebugUtilsObjectNameInfoEXT) -> Result ProcSetDebugUtilsObjectTagEXT :: #type proc "system" (device: Device, pTagInfo: ^DebugUtilsObjectTagInfoEXT) -> Result ProcSetDeviceMemoryPriorityEXT :: #type proc "system" (device: Device, memory: DeviceMemory, priority: f32) ProcSetEvent :: #type proc "system" (device: Device, event: Event) -> Result +ProcSetGpaDeviceClockModeAMD :: #type proc "system" (device: Device, pInfo: ^GpaDeviceClockModeInfoAMD) -> Result ProcSetHdrMetadataEXT :: #type proc "system" (device: Device, swapchainCount: u32, pSwapchains: [^]SwapchainKHR, pMetadata: ^HdrMetadataEXT) ProcSetLatencyMarkerNV :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pLatencyMarkerInfo: ^SetLatencyMarkerInfoNV) ProcSetLatencySleepModeNV :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pSleepModeInfo: ^LatencySleepModeInfoNV) -> Result ProcSetLocalDimmingAMD :: #type proc "system" (device: Device, swapChain: SwapchainKHR, localDimmingEnable: b32) ProcSetPrivateData :: #type proc "system" (device: Device, objectType: ObjectType, objectHandle: u64, privateDataSlot: PrivateDataSlot, data: u64) -> Result ProcSetPrivateDataEXT :: #type proc "system" (device: Device, objectType: ObjectType, objectHandle: u64, privateDataSlot: PrivateDataSlot, data: u64) -> Result +ProcSetSwapchainPresentTimingQueueSizeEXT :: #type proc "system" (device: Device, swapchain: SwapchainKHR, size: u32) -> Result ProcSignalSemaphore :: #type proc "system" (device: Device, pSignalInfo: ^SemaphoreSignalInfo) -> Result ProcSignalSemaphoreKHR :: #type proc "system" (device: Device, pSignalInfo: ^SemaphoreSignalInfo) -> Result ProcTransitionImageLayout :: #type proc "system" (device: Device, transitionCount: u32, pTransitions: [^]HostImageLayoutTransitionInfo) -> Result @@ -713,6 +809,7 @@ ProcUninitializePerformanceApiINTEL :: #type proc "system ProcUnmapMemory :: #type proc "system" (device: Device, memory: DeviceMemory) ProcUnmapMemory2 :: #type proc "system" (device: Device, pMemoryUnmapInfo: ^MemoryUnmapInfo) -> Result ProcUnmapMemory2KHR :: #type proc "system" (device: Device, pMemoryUnmapInfo: ^MemoryUnmapInfo) -> Result +ProcUnregisterCustomBorderColorEXT :: #type proc "system" (device: Device, index: u32) ProcUpdateDescriptorSetWithTemplate :: #type proc "system" (device: Device, descriptorSet: DescriptorSet, descriptorUpdateTemplate: DescriptorUpdateTemplate, pData: rawptr) ProcUpdateDescriptorSetWithTemplateKHR :: #type proc "system" (device: Device, descriptorSet: DescriptorSet, descriptorUpdateTemplate: DescriptorUpdateTemplate, pData: rawptr) ProcUpdateDescriptorSets :: #type proc "system" (device: Device, descriptorWriteCount: u32, pDescriptorWrites: [^]WriteDescriptorSet, descriptorCopyCount: u32, pDescriptorCopies: [^]CopyDescriptorSet) @@ -720,11 +817,14 @@ ProcUpdateIndirectExecutionSetPipelineEXT :: #type proc "system ProcUpdateIndirectExecutionSetShaderEXT :: #type proc "system" (device: Device, indirectExecutionSet: IndirectExecutionSetEXT, executionSetWriteCount: u32, pExecutionSetWrites: [^]WriteIndirectExecutionSetShaderEXT) ProcUpdateVideoSessionParametersKHR :: #type proc "system" (device: Device, videoSessionParameters: VideoSessionParametersKHR, pUpdateInfo: ^VideoSessionParametersUpdateInfoKHR) -> Result ProcWaitForFences :: #type proc "system" (device: Device, fenceCount: u32, pFences: [^]Fence, waitAll: b32, timeout: u64) -> Result +ProcWaitForPresent2KHR :: #type proc "system" (device: Device, swapchain: SwapchainKHR, pPresentWait2Info: ^PresentWait2InfoKHR) -> Result ProcWaitForPresentKHR :: #type proc "system" (device: Device, swapchain: SwapchainKHR, presentId: u64, timeout: u64) -> Result ProcWaitSemaphores :: #type proc "system" (device: Device, pWaitInfo: ^SemaphoreWaitInfo, timeout: u64) -> Result ProcWaitSemaphoresKHR :: #type proc "system" (device: Device, pWaitInfo: ^SemaphoreWaitInfo, timeout: u64) -> Result ProcWriteAccelerationStructuresPropertiesKHR :: #type proc "system" (device: Device, accelerationStructureCount: u32, pAccelerationStructures: [^]AccelerationStructureKHR, queryType: QueryType, dataSize: int, pData: rawptr, stride: int) -> Result ProcWriteMicromapsPropertiesEXT :: #type proc "system" (device: Device, micromapCount: u32, pMicromaps: [^]MicromapEXT, queryType: QueryType, dataSize: int, pData: rawptr, stride: int) -> Result +ProcWriteResourceDescriptorsEXT :: #type proc "system" (device: Device, resourceCount: u32, pResources: [^]ResourceDescriptorInfoEXT, pDescriptors: [^]HostAddressRangeEXT) -> Result +ProcWriteSamplerDescriptorsEXT :: #type proc "system" (device: Device, samplerCount: u32, pSamplers: [^]SamplerCreateInfo, pDescriptors: [^]HostAddressRangeEXT) -> Result // Loader Procedures @@ -734,106 +834,115 @@ DeviceMemoryReportCallbackEXT: ProcDeviceMemoryReportCallbackEXT EnumerateInstanceExtensionProperties: ProcEnumerateInstanceExtensionProperties EnumerateInstanceLayerProperties: ProcEnumerateInstanceLayerProperties EnumerateInstanceVersion: ProcEnumerateInstanceVersion +GetExternalComputeQueueDataNV: ProcGetExternalComputeQueueDataNV GetInstanceProcAddr: ProcGetInstanceProcAddr // Instance Procedures -AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT -AcquireWinrtDisplayNV: ProcAcquireWinrtDisplayNV -CreateDebugReportCallbackEXT: ProcCreateDebugReportCallbackEXT -CreateDebugUtilsMessengerEXT: ProcCreateDebugUtilsMessengerEXT -CreateDevice: ProcCreateDevice -CreateDisplayModeKHR: ProcCreateDisplayModeKHR -CreateDisplayPlaneSurfaceKHR: ProcCreateDisplayPlaneSurfaceKHR -CreateHeadlessSurfaceEXT: ProcCreateHeadlessSurfaceEXT -CreateIOSSurfaceMVK: ProcCreateIOSSurfaceMVK -CreateMacOSSurfaceMVK: ProcCreateMacOSSurfaceMVK -CreateMetalSurfaceEXT: ProcCreateMetalSurfaceEXT -CreateWaylandSurfaceKHR: ProcCreateWaylandSurfaceKHR -CreateWin32SurfaceKHR: ProcCreateWin32SurfaceKHR -CreateXcbSurfaceKHR: ProcCreateXcbSurfaceKHR -CreateXlibSurfaceKHR: ProcCreateXlibSurfaceKHR -DebugReportMessageEXT: ProcDebugReportMessageEXT -DestroyDebugReportCallbackEXT: ProcDestroyDebugReportCallbackEXT -DestroyDebugUtilsMessengerEXT: ProcDestroyDebugUtilsMessengerEXT -DestroyInstance: ProcDestroyInstance -DestroySurfaceKHR: ProcDestroySurfaceKHR -EnumerateDeviceExtensionProperties: ProcEnumerateDeviceExtensionProperties -EnumerateDeviceLayerProperties: ProcEnumerateDeviceLayerProperties -EnumeratePhysicalDeviceGroups: ProcEnumeratePhysicalDeviceGroups -EnumeratePhysicalDeviceGroupsKHR: ProcEnumeratePhysicalDeviceGroupsKHR -EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR: ProcEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR -EnumeratePhysicalDevices: ProcEnumeratePhysicalDevices -GetDisplayModeProperties2KHR: ProcGetDisplayModeProperties2KHR -GetDisplayModePropertiesKHR: ProcGetDisplayModePropertiesKHR -GetDisplayPlaneCapabilities2KHR: ProcGetDisplayPlaneCapabilities2KHR -GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR -GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR -GetDrmDisplayEXT: ProcGetDrmDisplayEXT -GetInstanceProcAddrLUNARG: ProcGetInstanceProcAddrLUNARG -GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT -GetPhysicalDeviceCalibrateableTimeDomainsKHR: ProcGetPhysicalDeviceCalibrateableTimeDomainsKHR -GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV -GetPhysicalDeviceCooperativeMatrixPropertiesKHR: ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR -GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV -GetPhysicalDeviceCooperativeVectorPropertiesNV: ProcGetPhysicalDeviceCooperativeVectorPropertiesNV -GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR -GetPhysicalDeviceDisplayPlanePropertiesKHR: ProcGetPhysicalDeviceDisplayPlanePropertiesKHR -GetPhysicalDeviceDisplayProperties2KHR: ProcGetPhysicalDeviceDisplayProperties2KHR -GetPhysicalDeviceDisplayPropertiesKHR: ProcGetPhysicalDeviceDisplayPropertiesKHR -GetPhysicalDeviceExternalBufferProperties: ProcGetPhysicalDeviceExternalBufferProperties -GetPhysicalDeviceExternalBufferPropertiesKHR: ProcGetPhysicalDeviceExternalBufferPropertiesKHR -GetPhysicalDeviceExternalFenceProperties: ProcGetPhysicalDeviceExternalFenceProperties -GetPhysicalDeviceExternalFencePropertiesKHR: ProcGetPhysicalDeviceExternalFencePropertiesKHR -GetPhysicalDeviceExternalImageFormatPropertiesNV: ProcGetPhysicalDeviceExternalImageFormatPropertiesNV -GetPhysicalDeviceExternalSemaphoreProperties: ProcGetPhysicalDeviceExternalSemaphoreProperties -GetPhysicalDeviceExternalSemaphorePropertiesKHR: ProcGetPhysicalDeviceExternalSemaphorePropertiesKHR -GetPhysicalDeviceFeatures: ProcGetPhysicalDeviceFeatures -GetPhysicalDeviceFeatures2: ProcGetPhysicalDeviceFeatures2 -GetPhysicalDeviceFeatures2KHR: ProcGetPhysicalDeviceFeatures2KHR -GetPhysicalDeviceFormatProperties: ProcGetPhysicalDeviceFormatProperties -GetPhysicalDeviceFormatProperties2: ProcGetPhysicalDeviceFormatProperties2 -GetPhysicalDeviceFormatProperties2KHR: ProcGetPhysicalDeviceFormatProperties2KHR -GetPhysicalDeviceFragmentShadingRatesKHR: ProcGetPhysicalDeviceFragmentShadingRatesKHR -GetPhysicalDeviceImageFormatProperties: ProcGetPhysicalDeviceImageFormatProperties -GetPhysicalDeviceImageFormatProperties2: ProcGetPhysicalDeviceImageFormatProperties2 -GetPhysicalDeviceImageFormatProperties2KHR: ProcGetPhysicalDeviceImageFormatProperties2KHR -GetPhysicalDeviceMemoryProperties: ProcGetPhysicalDeviceMemoryProperties -GetPhysicalDeviceMemoryProperties2: ProcGetPhysicalDeviceMemoryProperties2 -GetPhysicalDeviceMemoryProperties2KHR: ProcGetPhysicalDeviceMemoryProperties2KHR -GetPhysicalDeviceMultisamplePropertiesEXT: ProcGetPhysicalDeviceMultisamplePropertiesEXT -GetPhysicalDeviceOpticalFlowImageFormatsNV: ProcGetPhysicalDeviceOpticalFlowImageFormatsNV -GetPhysicalDevicePresentRectanglesKHR: ProcGetPhysicalDevicePresentRectanglesKHR -GetPhysicalDeviceProperties: ProcGetPhysicalDeviceProperties -GetPhysicalDeviceProperties2: ProcGetPhysicalDeviceProperties2 -GetPhysicalDeviceProperties2KHR: ProcGetPhysicalDeviceProperties2KHR -GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR: ProcGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR -GetPhysicalDeviceQueueFamilyProperties: ProcGetPhysicalDeviceQueueFamilyProperties -GetPhysicalDeviceQueueFamilyProperties2: ProcGetPhysicalDeviceQueueFamilyProperties2 -GetPhysicalDeviceQueueFamilyProperties2KHR: ProcGetPhysicalDeviceQueueFamilyProperties2KHR -GetPhysicalDeviceSparseImageFormatProperties: ProcGetPhysicalDeviceSparseImageFormatProperties -GetPhysicalDeviceSparseImageFormatProperties2: ProcGetPhysicalDeviceSparseImageFormatProperties2 -GetPhysicalDeviceSparseImageFormatProperties2KHR: ProcGetPhysicalDeviceSparseImageFormatProperties2KHR -GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV: ProcGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV -GetPhysicalDeviceSurfaceCapabilities2EXT: ProcGetPhysicalDeviceSurfaceCapabilities2EXT -GetPhysicalDeviceSurfaceCapabilities2KHR: ProcGetPhysicalDeviceSurfaceCapabilities2KHR -GetPhysicalDeviceSurfaceCapabilitiesKHR: ProcGetPhysicalDeviceSurfaceCapabilitiesKHR -GetPhysicalDeviceSurfaceFormats2KHR: ProcGetPhysicalDeviceSurfaceFormats2KHR -GetPhysicalDeviceSurfaceFormatsKHR: ProcGetPhysicalDeviceSurfaceFormatsKHR -GetPhysicalDeviceSurfacePresentModes2EXT: ProcGetPhysicalDeviceSurfacePresentModes2EXT -GetPhysicalDeviceSurfacePresentModesKHR: ProcGetPhysicalDeviceSurfacePresentModesKHR -GetPhysicalDeviceSurfaceSupportKHR: ProcGetPhysicalDeviceSurfaceSupportKHR -GetPhysicalDeviceToolProperties: ProcGetPhysicalDeviceToolProperties -GetPhysicalDeviceToolPropertiesEXT: ProcGetPhysicalDeviceToolPropertiesEXT -GetPhysicalDeviceVideoCapabilitiesKHR: ProcGetPhysicalDeviceVideoCapabilitiesKHR -GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR: ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR -GetPhysicalDeviceVideoFormatPropertiesKHR: ProcGetPhysicalDeviceVideoFormatPropertiesKHR -GetPhysicalDeviceWaylandPresentationSupportKHR: ProcGetPhysicalDeviceWaylandPresentationSupportKHR -GetPhysicalDeviceWin32PresentationSupportKHR: ProcGetPhysicalDeviceWin32PresentationSupportKHR -GetPhysicalDeviceXcbPresentationSupportKHR: ProcGetPhysicalDeviceXcbPresentationSupportKHR -GetPhysicalDeviceXlibPresentationSupportKHR: ProcGetPhysicalDeviceXlibPresentationSupportKHR -GetWinrtDisplayNV: ProcGetWinrtDisplayNV -ReleaseDisplayEXT: ProcReleaseDisplayEXT -SubmitDebugUtilsMessageEXT: ProcSubmitDebugUtilsMessageEXT +AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT +AcquireWinrtDisplayNV: ProcAcquireWinrtDisplayNV +CreateDebugReportCallbackEXT: ProcCreateDebugReportCallbackEXT +CreateDebugUtilsMessengerEXT: ProcCreateDebugUtilsMessengerEXT +CreateDevice: ProcCreateDevice +CreateDisplayModeKHR: ProcCreateDisplayModeKHR +CreateDisplayPlaneSurfaceKHR: ProcCreateDisplayPlaneSurfaceKHR +CreateHeadlessSurfaceEXT: ProcCreateHeadlessSurfaceEXT +CreateIOSSurfaceMVK: ProcCreateIOSSurfaceMVK +CreateMacOSSurfaceMVK: ProcCreateMacOSSurfaceMVK +CreateMetalSurfaceEXT: ProcCreateMetalSurfaceEXT +CreateWaylandSurfaceKHR: ProcCreateWaylandSurfaceKHR +CreateWin32SurfaceKHR: ProcCreateWin32SurfaceKHR +CreateXcbSurfaceKHR: ProcCreateXcbSurfaceKHR +CreateXlibSurfaceKHR: ProcCreateXlibSurfaceKHR +DebugReportMessageEXT: ProcDebugReportMessageEXT +DestroyDebugReportCallbackEXT: ProcDestroyDebugReportCallbackEXT +DestroyDebugUtilsMessengerEXT: ProcDestroyDebugUtilsMessengerEXT +DestroyInstance: ProcDestroyInstance +DestroySurfaceKHR: ProcDestroySurfaceKHR +EnumerateDeviceExtensionProperties: ProcEnumerateDeviceExtensionProperties +EnumerateDeviceLayerProperties: ProcEnumerateDeviceLayerProperties +EnumeratePhysicalDeviceGroups: ProcEnumeratePhysicalDeviceGroups +EnumeratePhysicalDeviceGroupsKHR: ProcEnumeratePhysicalDeviceGroupsKHR +EnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM: ProcEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM +EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR: ProcEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR +EnumeratePhysicalDeviceShaderInstrumentationMetricsARM: ProcEnumeratePhysicalDeviceShaderInstrumentationMetricsARM +EnumeratePhysicalDevices: ProcEnumeratePhysicalDevices +GetDisplayModeProperties2KHR: ProcGetDisplayModeProperties2KHR +GetDisplayModePropertiesKHR: ProcGetDisplayModePropertiesKHR +GetDisplayPlaneCapabilities2KHR: ProcGetDisplayPlaneCapabilities2KHR +GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR +GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR +GetDrmDisplayEXT: ProcGetDrmDisplayEXT +GetInstanceProcAddrLUNARG: ProcGetInstanceProcAddrLUNARG +GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT +GetPhysicalDeviceCalibrateableTimeDomainsKHR: ProcGetPhysicalDeviceCalibrateableTimeDomainsKHR +GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV +GetPhysicalDeviceCooperativeMatrixPropertiesKHR: ProcGetPhysicalDeviceCooperativeMatrixPropertiesKHR +GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV +GetPhysicalDeviceCooperativeVectorPropertiesNV: ProcGetPhysicalDeviceCooperativeVectorPropertiesNV +GetPhysicalDeviceDescriptorSizeEXT: ProcGetPhysicalDeviceDescriptorSizeEXT +GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR +GetPhysicalDeviceDisplayPlanePropertiesKHR: ProcGetPhysicalDeviceDisplayPlanePropertiesKHR +GetPhysicalDeviceDisplayProperties2KHR: ProcGetPhysicalDeviceDisplayProperties2KHR +GetPhysicalDeviceDisplayPropertiesKHR: ProcGetPhysicalDeviceDisplayPropertiesKHR +GetPhysicalDeviceExternalBufferProperties: ProcGetPhysicalDeviceExternalBufferProperties +GetPhysicalDeviceExternalBufferPropertiesKHR: ProcGetPhysicalDeviceExternalBufferPropertiesKHR +GetPhysicalDeviceExternalFenceProperties: ProcGetPhysicalDeviceExternalFenceProperties +GetPhysicalDeviceExternalFencePropertiesKHR: ProcGetPhysicalDeviceExternalFencePropertiesKHR +GetPhysicalDeviceExternalImageFormatPropertiesNV: ProcGetPhysicalDeviceExternalImageFormatPropertiesNV +GetPhysicalDeviceExternalSemaphoreProperties: ProcGetPhysicalDeviceExternalSemaphoreProperties +GetPhysicalDeviceExternalSemaphorePropertiesKHR: ProcGetPhysicalDeviceExternalSemaphorePropertiesKHR +GetPhysicalDeviceExternalTensorPropertiesARM: ProcGetPhysicalDeviceExternalTensorPropertiesARM +GetPhysicalDeviceFeatures: ProcGetPhysicalDeviceFeatures +GetPhysicalDeviceFeatures2: ProcGetPhysicalDeviceFeatures2 +GetPhysicalDeviceFeatures2KHR: ProcGetPhysicalDeviceFeatures2KHR +GetPhysicalDeviceFormatProperties: ProcGetPhysicalDeviceFormatProperties +GetPhysicalDeviceFormatProperties2: ProcGetPhysicalDeviceFormatProperties2 +GetPhysicalDeviceFormatProperties2KHR: ProcGetPhysicalDeviceFormatProperties2KHR +GetPhysicalDeviceFragmentShadingRatesKHR: ProcGetPhysicalDeviceFragmentShadingRatesKHR +GetPhysicalDeviceImageFormatProperties: ProcGetPhysicalDeviceImageFormatProperties +GetPhysicalDeviceImageFormatProperties2: ProcGetPhysicalDeviceImageFormatProperties2 +GetPhysicalDeviceImageFormatProperties2KHR: ProcGetPhysicalDeviceImageFormatProperties2KHR +GetPhysicalDeviceMemoryProperties: ProcGetPhysicalDeviceMemoryProperties +GetPhysicalDeviceMemoryProperties2: ProcGetPhysicalDeviceMemoryProperties2 +GetPhysicalDeviceMemoryProperties2KHR: ProcGetPhysicalDeviceMemoryProperties2KHR +GetPhysicalDeviceMultisamplePropertiesEXT: ProcGetPhysicalDeviceMultisamplePropertiesEXT +GetPhysicalDeviceOpticalFlowImageFormatsNV: ProcGetPhysicalDeviceOpticalFlowImageFormatsNV +GetPhysicalDevicePresentRectanglesKHR: ProcGetPhysicalDevicePresentRectanglesKHR +GetPhysicalDeviceProperties: ProcGetPhysicalDeviceProperties +GetPhysicalDeviceProperties2: ProcGetPhysicalDeviceProperties2 +GetPhysicalDeviceProperties2KHR: ProcGetPhysicalDeviceProperties2KHR +GetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM: ProcGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM +GetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM: ProcGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM +GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM: ProcGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM +GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM: ProcGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM +GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR: ProcGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR +GetPhysicalDeviceQueueFamilyProperties: ProcGetPhysicalDeviceQueueFamilyProperties +GetPhysicalDeviceQueueFamilyProperties2: ProcGetPhysicalDeviceQueueFamilyProperties2 +GetPhysicalDeviceQueueFamilyProperties2KHR: ProcGetPhysicalDeviceQueueFamilyProperties2KHR +GetPhysicalDeviceSparseImageFormatProperties: ProcGetPhysicalDeviceSparseImageFormatProperties +GetPhysicalDeviceSparseImageFormatProperties2: ProcGetPhysicalDeviceSparseImageFormatProperties2 +GetPhysicalDeviceSparseImageFormatProperties2KHR: ProcGetPhysicalDeviceSparseImageFormatProperties2KHR +GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV: ProcGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV +GetPhysicalDeviceSurfaceCapabilities2EXT: ProcGetPhysicalDeviceSurfaceCapabilities2EXT +GetPhysicalDeviceSurfaceCapabilities2KHR: ProcGetPhysicalDeviceSurfaceCapabilities2KHR +GetPhysicalDeviceSurfaceCapabilitiesKHR: ProcGetPhysicalDeviceSurfaceCapabilitiesKHR +GetPhysicalDeviceSurfaceFormats2KHR: ProcGetPhysicalDeviceSurfaceFormats2KHR +GetPhysicalDeviceSurfaceFormatsKHR: ProcGetPhysicalDeviceSurfaceFormatsKHR +GetPhysicalDeviceSurfacePresentModes2EXT: ProcGetPhysicalDeviceSurfacePresentModes2EXT +GetPhysicalDeviceSurfacePresentModesKHR: ProcGetPhysicalDeviceSurfacePresentModesKHR +GetPhysicalDeviceSurfaceSupportKHR: ProcGetPhysicalDeviceSurfaceSupportKHR +GetPhysicalDeviceToolProperties: ProcGetPhysicalDeviceToolProperties +GetPhysicalDeviceToolPropertiesEXT: ProcGetPhysicalDeviceToolPropertiesEXT +GetPhysicalDeviceVideoCapabilitiesKHR: ProcGetPhysicalDeviceVideoCapabilitiesKHR +GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR: ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR +GetPhysicalDeviceVideoFormatPropertiesKHR: ProcGetPhysicalDeviceVideoFormatPropertiesKHR +GetPhysicalDeviceWaylandPresentationSupportKHR: ProcGetPhysicalDeviceWaylandPresentationSupportKHR +GetPhysicalDeviceWin32PresentationSupportKHR: ProcGetPhysicalDeviceWin32PresentationSupportKHR +GetPhysicalDeviceXcbPresentationSupportKHR: ProcGetPhysicalDeviceXcbPresentationSupportKHR +GetPhysicalDeviceXlibPresentationSupportKHR: ProcGetPhysicalDeviceXlibPresentationSupportKHR +GetWinrtDisplayNV: ProcGetWinrtDisplayNV +ReleaseDisplayEXT: ProcReleaseDisplayEXT +SubmitDebugUtilsMessageEXT: ProcSubmitDebugUtilsMessageEXT // Device Procedures AcquireFullScreenExclusiveModeEXT: ProcAcquireFullScreenExclusiveModeEXT @@ -850,15 +959,23 @@ BindAccelerationStructureMemoryNV: ProcBindAccelerationStru BindBufferMemory: ProcBindBufferMemory BindBufferMemory2: ProcBindBufferMemory2 BindBufferMemory2KHR: ProcBindBufferMemory2KHR +BindDataGraphPipelineSessionMemoryARM: ProcBindDataGraphPipelineSessionMemoryARM BindImageMemory: ProcBindImageMemory BindImageMemory2: ProcBindImageMemory2 BindImageMemory2KHR: ProcBindImageMemory2KHR BindOpticalFlowSessionImageNV: ProcBindOpticalFlowSessionImageNV +BindTensorMemoryARM: ProcBindTensorMemoryARM BindVideoSessionMemoryKHR: ProcBindVideoSessionMemoryKHR BuildAccelerationStructuresKHR: ProcBuildAccelerationStructuresKHR BuildMicromapsEXT: ProcBuildMicromapsEXT +ClearShaderInstrumentationMetricsARM: ProcClearShaderInstrumentationMetricsARM +CmdBeginConditionalRendering2EXT: ProcCmdBeginConditionalRendering2EXT CmdBeginConditionalRenderingEXT: ProcCmdBeginConditionalRenderingEXT +CmdBeginCustomResolveEXT: ProcCmdBeginCustomResolveEXT CmdBeginDebugUtilsLabelEXT: ProcCmdBeginDebugUtilsLabelEXT +CmdBeginGpaSampleAMD: ProcCmdBeginGpaSampleAMD +CmdBeginGpaSessionAMD: ProcCmdBeginGpaSessionAMD +CmdBeginPerTileExecutionQCOM: ProcCmdBeginPerTileExecutionQCOM CmdBeginQuery: ProcCmdBeginQuery CmdBeginQueryIndexedEXT: ProcCmdBeginQueryIndexedEXT CmdBeginRenderPass: ProcCmdBeginRenderPass @@ -866,6 +983,8 @@ CmdBeginRenderPass2: ProcCmdBeginRenderPass2 CmdBeginRenderPass2KHR: ProcCmdBeginRenderPass2KHR CmdBeginRendering: ProcCmdBeginRendering CmdBeginRenderingKHR: ProcCmdBeginRenderingKHR +CmdBeginShaderInstrumentationARM: ProcCmdBeginShaderInstrumentationARM +CmdBeginTransformFeedback2EXT: ProcCmdBeginTransformFeedback2EXT CmdBeginTransformFeedbackEXT: ProcCmdBeginTransformFeedbackEXT CmdBeginVideoCodingKHR: ProcCmdBeginVideoCodingKHR CmdBindDescriptorBufferEmbeddedSamplers2EXT: ProcCmdBindDescriptorBufferEmbeddedSamplers2EXT @@ -877,15 +996,21 @@ CmdBindDescriptorSets2KHR: ProcCmdBindDescriptorSet CmdBindIndexBuffer: ProcCmdBindIndexBuffer CmdBindIndexBuffer2: ProcCmdBindIndexBuffer2 CmdBindIndexBuffer2KHR: ProcCmdBindIndexBuffer2KHR +CmdBindIndexBuffer3KHR: ProcCmdBindIndexBuffer3KHR CmdBindInvocationMaskHUAWEI: ProcCmdBindInvocationMaskHUAWEI CmdBindPipeline: ProcCmdBindPipeline CmdBindPipelineShaderGroupNV: ProcCmdBindPipelineShaderGroupNV +CmdBindResourceHeapEXT: ProcCmdBindResourceHeapEXT +CmdBindSamplerHeapEXT: ProcCmdBindSamplerHeapEXT CmdBindShadersEXT: ProcCmdBindShadersEXT CmdBindShadingRateImageNV: ProcCmdBindShadingRateImageNV +CmdBindTileMemoryQCOM: ProcCmdBindTileMemoryQCOM +CmdBindTransformFeedbackBuffers2EXT: ProcCmdBindTransformFeedbackBuffers2EXT CmdBindTransformFeedbackBuffersEXT: ProcCmdBindTransformFeedbackBuffersEXT CmdBindVertexBuffers: ProcCmdBindVertexBuffers CmdBindVertexBuffers2: ProcCmdBindVertexBuffers2 CmdBindVertexBuffers2EXT: ProcCmdBindVertexBuffers2EXT +CmdBindVertexBuffers3KHR: ProcCmdBindVertexBuffers3KHR CmdBlitImage: ProcCmdBlitImage CmdBlitImage2: ProcCmdBlitImage2 CmdBlitImage2KHR: ProcCmdBlitImage2KHR @@ -909,48 +1034,68 @@ CmdCopyBuffer2KHR: ProcCmdCopyBuffer2KHR CmdCopyBufferToImage: ProcCmdCopyBufferToImage CmdCopyBufferToImage2: ProcCmdCopyBufferToImage2 CmdCopyBufferToImage2KHR: ProcCmdCopyBufferToImage2KHR +CmdCopyGpaSessionResultsAMD: ProcCmdCopyGpaSessionResultsAMD CmdCopyImage: ProcCmdCopyImage CmdCopyImage2: ProcCmdCopyImage2 CmdCopyImage2KHR: ProcCmdCopyImage2KHR CmdCopyImageToBuffer: ProcCmdCopyImageToBuffer CmdCopyImageToBuffer2: ProcCmdCopyImageToBuffer2 CmdCopyImageToBuffer2KHR: ProcCmdCopyImageToBuffer2KHR +CmdCopyImageToMemoryKHR: ProcCmdCopyImageToMemoryKHR +CmdCopyMemoryIndirectKHR: ProcCmdCopyMemoryIndirectKHR CmdCopyMemoryIndirectNV: ProcCmdCopyMemoryIndirectNV +CmdCopyMemoryKHR: ProcCmdCopyMemoryKHR CmdCopyMemoryToAccelerationStructureKHR: ProcCmdCopyMemoryToAccelerationStructureKHR +CmdCopyMemoryToImageIndirectKHR: ProcCmdCopyMemoryToImageIndirectKHR CmdCopyMemoryToImageIndirectNV: ProcCmdCopyMemoryToImageIndirectNV +CmdCopyMemoryToImageKHR: ProcCmdCopyMemoryToImageKHR CmdCopyMemoryToMicromapEXT: ProcCmdCopyMemoryToMicromapEXT CmdCopyMicromapEXT: ProcCmdCopyMicromapEXT CmdCopyMicromapToMemoryEXT: ProcCmdCopyMicromapToMemoryEXT CmdCopyQueryPoolResults: ProcCmdCopyQueryPoolResults +CmdCopyQueryPoolResultsToMemoryKHR: ProcCmdCopyQueryPoolResultsToMemoryKHR +CmdCopyTensorARM: ProcCmdCopyTensorARM CmdCuLaunchKernelNVX: ProcCmdCuLaunchKernelNVX CmdCudaLaunchKernelNV: ProcCmdCudaLaunchKernelNV CmdDebugMarkerBeginEXT: ProcCmdDebugMarkerBeginEXT CmdDebugMarkerEndEXT: ProcCmdDebugMarkerEndEXT CmdDebugMarkerInsertEXT: ProcCmdDebugMarkerInsertEXT CmdDecodeVideoKHR: ProcCmdDecodeVideoKHR +CmdDecompressMemoryEXT: ProcCmdDecompressMemoryEXT +CmdDecompressMemoryIndirectCountEXT: ProcCmdDecompressMemoryIndirectCountEXT CmdDecompressMemoryIndirectCountNV: ProcCmdDecompressMemoryIndirectCountNV CmdDecompressMemoryNV: ProcCmdDecompressMemoryNV CmdDispatch: ProcCmdDispatch CmdDispatchBase: ProcCmdDispatchBase CmdDispatchBaseKHR: ProcCmdDispatchBaseKHR +CmdDispatchDataGraphARM: ProcCmdDispatchDataGraphARM CmdDispatchGraphAMDX: ProcCmdDispatchGraphAMDX CmdDispatchGraphIndirectAMDX: ProcCmdDispatchGraphIndirectAMDX CmdDispatchGraphIndirectCountAMDX: ProcCmdDispatchGraphIndirectCountAMDX CmdDispatchIndirect: ProcCmdDispatchIndirect +CmdDispatchIndirect2KHR: ProcCmdDispatchIndirect2KHR +CmdDispatchTileQCOM: ProcCmdDispatchTileQCOM CmdDraw: ProcCmdDraw CmdDrawClusterHUAWEI: ProcCmdDrawClusterHUAWEI CmdDrawClusterIndirectHUAWEI: ProcCmdDrawClusterIndirectHUAWEI CmdDrawIndexed: ProcCmdDrawIndexed CmdDrawIndexedIndirect: ProcCmdDrawIndexedIndirect +CmdDrawIndexedIndirect2KHR: ProcCmdDrawIndexedIndirect2KHR CmdDrawIndexedIndirectCount: ProcCmdDrawIndexedIndirectCount +CmdDrawIndexedIndirectCount2KHR: ProcCmdDrawIndexedIndirectCount2KHR CmdDrawIndexedIndirectCountAMD: ProcCmdDrawIndexedIndirectCountAMD CmdDrawIndexedIndirectCountKHR: ProcCmdDrawIndexedIndirectCountKHR CmdDrawIndirect: ProcCmdDrawIndirect +CmdDrawIndirect2KHR: ProcCmdDrawIndirect2KHR +CmdDrawIndirectByteCount2EXT: ProcCmdDrawIndirectByteCount2EXT CmdDrawIndirectByteCountEXT: ProcCmdDrawIndirectByteCountEXT CmdDrawIndirectCount: ProcCmdDrawIndirectCount +CmdDrawIndirectCount2KHR: ProcCmdDrawIndirectCount2KHR CmdDrawIndirectCountAMD: ProcCmdDrawIndirectCountAMD CmdDrawIndirectCountKHR: ProcCmdDrawIndirectCountKHR CmdDrawMeshTasksEXT: ProcCmdDrawMeshTasksEXT +CmdDrawMeshTasksIndirect2EXT: ProcCmdDrawMeshTasksIndirect2EXT +CmdDrawMeshTasksIndirectCount2EXT: ProcCmdDrawMeshTasksIndirectCount2EXT CmdDrawMeshTasksIndirectCountEXT: ProcCmdDrawMeshTasksIndirectCountEXT CmdDrawMeshTasksIndirectCountNV: ProcCmdDrawMeshTasksIndirectCountNV CmdDrawMeshTasksIndirectEXT: ProcCmdDrawMeshTasksIndirectEXT @@ -961,19 +1106,27 @@ CmdDrawMultiIndexedEXT: ProcCmdDrawMultiIndexedE CmdEncodeVideoKHR: ProcCmdEncodeVideoKHR CmdEndConditionalRenderingEXT: ProcCmdEndConditionalRenderingEXT CmdEndDebugUtilsLabelEXT: ProcCmdEndDebugUtilsLabelEXT +CmdEndGpaSampleAMD: ProcCmdEndGpaSampleAMD +CmdEndGpaSessionAMD: ProcCmdEndGpaSessionAMD +CmdEndPerTileExecutionQCOM: ProcCmdEndPerTileExecutionQCOM CmdEndQuery: ProcCmdEndQuery CmdEndQueryIndexedEXT: ProcCmdEndQueryIndexedEXT CmdEndRenderPass: ProcCmdEndRenderPass CmdEndRenderPass2: ProcCmdEndRenderPass2 CmdEndRenderPass2KHR: ProcCmdEndRenderPass2KHR CmdEndRendering: ProcCmdEndRendering +CmdEndRendering2EXT: ProcCmdEndRendering2EXT +CmdEndRendering2KHR: ProcCmdEndRendering2KHR CmdEndRenderingKHR: ProcCmdEndRenderingKHR +CmdEndShaderInstrumentationARM: ProcCmdEndShaderInstrumentationARM +CmdEndTransformFeedback2EXT: ProcCmdEndTransformFeedback2EXT CmdEndTransformFeedbackEXT: ProcCmdEndTransformFeedbackEXT CmdEndVideoCodingKHR: ProcCmdEndVideoCodingKHR CmdExecuteCommands: ProcCmdExecuteCommands CmdExecuteGeneratedCommandsEXT: ProcCmdExecuteGeneratedCommandsEXT CmdExecuteGeneratedCommandsNV: ProcCmdExecuteGeneratedCommandsNV CmdFillBuffer: ProcCmdFillBuffer +CmdFillMemoryKHR: ProcCmdFillMemoryKHR CmdInitializeGraphScratchMemoryAMDX: ProcCmdInitializeGraphScratchMemoryAMDX CmdInsertDebugUtilsLabelEXT: ProcCmdInsertDebugUtilsLabelEXT CmdNextSubpass: ProcCmdNextSubpass @@ -988,6 +1141,7 @@ CmdPreprocessGeneratedCommandsNV: ProcCmdPreprocessGenerat CmdPushConstants: ProcCmdPushConstants CmdPushConstants2: ProcCmdPushConstants2 CmdPushConstants2KHR: ProcCmdPushConstants2KHR +CmdPushDataEXT: ProcCmdPushDataEXT CmdPushDescriptorSet: ProcCmdPushDescriptorSet CmdPushDescriptorSet2: ProcCmdPushDescriptorSet2 CmdPushDescriptorSet2KHR: ProcCmdPushDescriptorSet2KHR @@ -1012,7 +1166,9 @@ CmdSetCoarseSampleOrderNV: ProcCmdSetCoarseSampleOr CmdSetColorBlendAdvancedEXT: ProcCmdSetColorBlendAdvancedEXT CmdSetColorBlendEnableEXT: ProcCmdSetColorBlendEnableEXT CmdSetColorBlendEquationEXT: ProcCmdSetColorBlendEquationEXT +CmdSetColorWriteEnableEXT: ProcCmdSetColorWriteEnableEXT CmdSetColorWriteMaskEXT: ProcCmdSetColorWriteMaskEXT +CmdSetComputeOccupancyPriorityNV: ProcCmdSetComputeOccupancyPriorityNV CmdSetConservativeRasterizationModeEXT: ProcCmdSetConservativeRasterizationModeEXT CmdSetCoverageModulationModeNV: ProcCmdSetCoverageModulationModeNV CmdSetCoverageModulationTableEnableNV: ProcCmdSetCoverageModulationTableEnableNV @@ -1046,6 +1202,7 @@ CmdSetDeviceMaskKHR: ProcCmdSetDeviceMaskKHR CmdSetDiscardRectangleEXT: ProcCmdSetDiscardRectangleEXT CmdSetDiscardRectangleEnableEXT: ProcCmdSetDiscardRectangleEnableEXT CmdSetDiscardRectangleModeEXT: ProcCmdSetDiscardRectangleModeEXT +CmdSetDispatchParametersARM: ProcCmdSetDispatchParametersARM CmdSetEvent: ProcCmdSetEvent CmdSetEvent2: ProcCmdSetEvent2 CmdSetEvent2KHR: ProcCmdSetEvent2KHR @@ -1071,6 +1228,7 @@ CmdSetPerformanceStreamMarkerINTEL: ProcCmdSetPerformanceStr CmdSetPolygonModeEXT: ProcCmdSetPolygonModeEXT CmdSetPrimitiveRestartEnable: ProcCmdSetPrimitiveRestartEnable CmdSetPrimitiveRestartEnableEXT: ProcCmdSetPrimitiveRestartEnableEXT +CmdSetPrimitiveRestartIndexEXT: ProcCmdSetPrimitiveRestartIndexEXT CmdSetPrimitiveTopology: ProcCmdSetPrimitiveTopology CmdSetPrimitiveTopologyEXT: ProcCmdSetPrimitiveTopologyEXT CmdSetProvokingVertexModeEXT: ProcCmdSetProvokingVertexModeEXT @@ -1113,6 +1271,7 @@ CmdTraceRaysIndirectKHR: ProcCmdTraceRaysIndirect CmdTraceRaysKHR: ProcCmdTraceRaysKHR CmdTraceRaysNV: ProcCmdTraceRaysNV CmdUpdateBuffer: ProcCmdUpdateBuffer +CmdUpdateMemoryKHR: ProcCmdUpdateMemoryKHR CmdUpdatePipelineIndirectBufferNV: ProcCmdUpdatePipelineIndirectBufferNV CmdWaitEvents: ProcCmdWaitEvents CmdWaitEvents2: ProcCmdWaitEvents2 @@ -1121,6 +1280,7 @@ CmdWriteAccelerationStructuresPropertiesKHR: ProcCmdWriteAcceleration CmdWriteAccelerationStructuresPropertiesNV: ProcCmdWriteAccelerationStructuresPropertiesNV CmdWriteBufferMarker2AMD: ProcCmdWriteBufferMarker2AMD CmdWriteBufferMarkerAMD: ProcCmdWriteBufferMarkerAMD +CmdWriteMarkerToMemoryAMD: ProcCmdWriteMarkerToMemoryAMD CmdWriteMicromapsPropertiesEXT: ProcCmdWriteMicromapsPropertiesEXT CmdWriteTimestamp: ProcCmdWriteTimestamp CmdWriteTimestamp2: ProcCmdWriteTimestamp2 @@ -1139,6 +1299,7 @@ CopyMemoryToImageEXT: ProcCopyMemoryToImageEXT CopyMemoryToMicromapEXT: ProcCopyMemoryToMicromapEXT CopyMicromapEXT: ProcCopyMicromapEXT CopyMicromapToMemoryEXT: ProcCopyMicromapToMemoryEXT +CreateAccelerationStructure2KHR: ProcCreateAccelerationStructure2KHR CreateAccelerationStructureKHR: ProcCreateAccelerationStructureKHR CreateAccelerationStructureNV: ProcCreateAccelerationStructureNV CreateBuffer: ProcCreateBuffer @@ -1149,6 +1310,8 @@ CreateCuFunctionNVX: ProcCreateCuFunctionNVX CreateCuModuleNVX: ProcCreateCuModuleNVX CreateCudaFunctionNV: ProcCreateCudaFunctionNV CreateCudaModuleNV: ProcCreateCudaModuleNV +CreateDataGraphPipelineSessionARM: ProcCreateDataGraphPipelineSessionARM +CreateDataGraphPipelinesARM: ProcCreateDataGraphPipelinesARM CreateDeferredOperationKHR: ProcCreateDeferredOperationKHR CreateDescriptorPool: ProcCreateDescriptorPool CreateDescriptorSetLayout: ProcCreateDescriptorSetLayout @@ -1156,8 +1319,10 @@ CreateDescriptorUpdateTemplate: ProcCreateDescriptorUpda CreateDescriptorUpdateTemplateKHR: ProcCreateDescriptorUpdateTemplateKHR CreateEvent: ProcCreateEvent CreateExecutionGraphPipelinesAMDX: ProcCreateExecutionGraphPipelinesAMDX +CreateExternalComputeQueueNV: ProcCreateExternalComputeQueueNV CreateFence: ProcCreateFence CreateFramebuffer: ProcCreateFramebuffer +CreateGpaSessionAMD: ProcCreateGpaSessionAMD CreateGraphicsPipelines: ProcCreateGraphicsPipelines CreateImage: ProcCreateImage CreateImageView: ProcCreateImageView @@ -1181,10 +1346,13 @@ CreateSampler: ProcCreateSampler CreateSamplerYcbcrConversion: ProcCreateSamplerYcbcrConversion CreateSamplerYcbcrConversionKHR: ProcCreateSamplerYcbcrConversionKHR CreateSemaphore: ProcCreateSemaphore +CreateShaderInstrumentationARM: ProcCreateShaderInstrumentationARM CreateShaderModule: ProcCreateShaderModule CreateShadersEXT: ProcCreateShadersEXT CreateSharedSwapchainsKHR: ProcCreateSharedSwapchainsKHR CreateSwapchainKHR: ProcCreateSwapchainKHR +CreateTensorARM: ProcCreateTensorARM +CreateTensorViewARM: ProcCreateTensorViewARM CreateValidationCacheEXT: ProcCreateValidationCacheEXT CreateVideoSessionKHR: ProcCreateVideoSessionKHR CreateVideoSessionParametersKHR: ProcCreateVideoSessionParametersKHR @@ -1200,6 +1368,7 @@ DestroyCuFunctionNVX: ProcDestroyCuFunctionNVX DestroyCuModuleNVX: ProcDestroyCuModuleNVX DestroyCudaFunctionNV: ProcDestroyCudaFunctionNV DestroyCudaModuleNV: ProcDestroyCudaModuleNV +DestroyDataGraphPipelineSessionARM: ProcDestroyDataGraphPipelineSessionARM DestroyDeferredOperationKHR: ProcDestroyDeferredOperationKHR DestroyDescriptorPool: ProcDestroyDescriptorPool DestroyDescriptorSetLayout: ProcDestroyDescriptorSetLayout @@ -1207,8 +1376,10 @@ DestroyDescriptorUpdateTemplate: ProcDestroyDescriptorUpd DestroyDescriptorUpdateTemplateKHR: ProcDestroyDescriptorUpdateTemplateKHR DestroyDevice: ProcDestroyDevice DestroyEvent: ProcDestroyEvent +DestroyExternalComputeQueueNV: ProcDestroyExternalComputeQueueNV DestroyFence: ProcDestroyFence DestroyFramebuffer: ProcDestroyFramebuffer +DestroyGpaSessionAMD: ProcDestroyGpaSessionAMD DestroyImage: ProcDestroyImage DestroyImageView: ProcDestroyImageView DestroyIndirectCommandsLayoutEXT: ProcDestroyIndirectCommandsLayoutEXT @@ -1229,8 +1400,11 @@ DestroySamplerYcbcrConversion: ProcDestroySamplerYcbcrC DestroySamplerYcbcrConversionKHR: ProcDestroySamplerYcbcrConversionKHR DestroySemaphore: ProcDestroySemaphore DestroyShaderEXT: ProcDestroyShaderEXT +DestroyShaderInstrumentationARM: ProcDestroyShaderInstrumentationARM DestroyShaderModule: ProcDestroyShaderModule DestroySwapchainKHR: ProcDestroySwapchainKHR +DestroyTensorARM: ProcDestroyTensorARM +DestroyTensorViewARM: ProcDestroyTensorViewARM DestroyValidationCacheEXT: ProcDestroyValidationCacheEXT DestroyVideoSessionKHR: ProcDestroyVideoSessionKHR DestroyVideoSessionParametersKHR: ProcDestroyVideoSessionParametersKHR @@ -1260,6 +1434,10 @@ GetCalibratedTimestampsEXT: ProcGetCalibratedTimesta GetCalibratedTimestampsKHR: ProcGetCalibratedTimestampsKHR GetClusterAccelerationStructureBuildSizesNV: ProcGetClusterAccelerationStructureBuildSizesNV GetCudaModuleCacheNV: ProcGetCudaModuleCacheNV +GetDataGraphPipelineAvailablePropertiesARM: ProcGetDataGraphPipelineAvailablePropertiesARM +GetDataGraphPipelinePropertiesARM: ProcGetDataGraphPipelinePropertiesARM +GetDataGraphPipelineSessionBindPointRequirementsARM: ProcGetDataGraphPipelineSessionBindPointRequirementsARM +GetDataGraphPipelineSessionMemoryRequirementsARM: ProcGetDataGraphPipelineSessionMemoryRequirementsARM GetDeferredOperationMaxConcurrencyKHR: ProcGetDeferredOperationMaxConcurrencyKHR GetDeferredOperationResultKHR: ProcGetDeferredOperationResultKHR GetDescriptorEXT: ProcGetDescriptorEXT @@ -1272,7 +1450,10 @@ GetDescriptorSetLayoutSupportKHR: ProcGetDescriptorSetLayo GetDeviceAccelerationStructureCompatibilityKHR: ProcGetDeviceAccelerationStructureCompatibilityKHR GetDeviceBufferMemoryRequirements: ProcGetDeviceBufferMemoryRequirements GetDeviceBufferMemoryRequirementsKHR: ProcGetDeviceBufferMemoryRequirementsKHR +GetDeviceCombinedImageSamplerIndexNVX: ProcGetDeviceCombinedImageSamplerIndexNVX +GetDeviceFaultDebugInfoKHR: ProcGetDeviceFaultDebugInfoKHR GetDeviceFaultInfoEXT: ProcGetDeviceFaultInfoEXT +GetDeviceFaultReportsKHR: ProcGetDeviceFaultReportsKHR GetDeviceGroupPeerMemoryFeatures: ProcGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeaturesKHR: ProcGetDeviceGroupPeerMemoryFeaturesKHR GetDeviceGroupPresentCapabilitiesKHR: ProcGetDeviceGroupPresentCapabilitiesKHR @@ -1292,6 +1473,7 @@ GetDeviceProcAddr: ProcGetDeviceProcAddr GetDeviceQueue: ProcGetDeviceQueue GetDeviceQueue2: ProcGetDeviceQueue2 GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI: ProcGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI +GetDeviceTensorMemoryRequirementsARM: ProcGetDeviceTensorMemoryRequirementsARM GetDynamicRenderingTilePropertiesQCOM: ProcGetDynamicRenderingTilePropertiesQCOM GetEncodedVideoSessionParametersKHR: ProcGetEncodedVideoSessionParametersKHR GetEventStatus: ProcGetEventStatus @@ -1303,10 +1485,14 @@ GetFenceWin32HandleKHR: ProcGetFenceWin32HandleK GetFramebufferTilePropertiesQCOM: ProcGetFramebufferTilePropertiesQCOM GetGeneratedCommandsMemoryRequirementsEXT: ProcGetGeneratedCommandsMemoryRequirementsEXT GetGeneratedCommandsMemoryRequirementsNV: ProcGetGeneratedCommandsMemoryRequirementsNV +GetGpaDeviceClockInfoAMD: ProcGetGpaDeviceClockInfoAMD +GetGpaSessionResultsAMD: ProcGetGpaSessionResultsAMD +GetGpaSessionStatusAMD: ProcGetGpaSessionStatusAMD GetImageDrmFormatModifierPropertiesEXT: ProcGetImageDrmFormatModifierPropertiesEXT GetImageMemoryRequirements: ProcGetImageMemoryRequirements GetImageMemoryRequirements2: ProcGetImageMemoryRequirements2 GetImageMemoryRequirements2KHR: ProcGetImageMemoryRequirements2KHR +GetImageOpaqueCaptureDataEXT: ProcGetImageOpaqueCaptureDataEXT GetImageOpaqueCaptureDescriptorDataEXT: ProcGetImageOpaqueCaptureDescriptorDataEXT GetImageSparseMemoryRequirements: ProcGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements2: ProcGetImageSparseMemoryRequirements2 @@ -1331,6 +1517,7 @@ GetMemoryWin32HandleNV: ProcGetMemoryWin32Handle GetMemoryWin32HandlePropertiesKHR: ProcGetMemoryWin32HandlePropertiesKHR GetMicromapBuildSizesEXT: ProcGetMicromapBuildSizesEXT GetPartitionedAccelerationStructuresBuildSizesNV: ProcGetPartitionedAccelerationStructuresBuildSizesNV +GetPastPresentationTimingEXT: ProcGetPastPresentationTimingEXT GetPastPresentationTimingGOOGLE: ProcGetPastPresentationTimingGOOGLE GetPerformanceParameterINTEL: ProcGetPerformanceParameterINTEL GetPipelineBinaryDataKHR: ProcGetPipelineBinaryDataKHR @@ -1362,11 +1549,18 @@ GetSemaphoreFdKHR: ProcGetSemaphoreFdKHR GetSemaphoreWin32HandleKHR: ProcGetSemaphoreWin32HandleKHR GetShaderBinaryDataEXT: ProcGetShaderBinaryDataEXT GetShaderInfoAMD: ProcGetShaderInfoAMD +GetShaderInstrumentationValuesARM: ProcGetShaderInstrumentationValuesARM GetShaderModuleCreateInfoIdentifierEXT: ProcGetShaderModuleCreateInfoIdentifierEXT GetShaderModuleIdentifierEXT: ProcGetShaderModuleIdentifierEXT GetSwapchainCounterEXT: ProcGetSwapchainCounterEXT GetSwapchainImagesKHR: ProcGetSwapchainImagesKHR GetSwapchainStatusKHR: ProcGetSwapchainStatusKHR +GetSwapchainTimeDomainPropertiesEXT: ProcGetSwapchainTimeDomainPropertiesEXT +GetSwapchainTimingPropertiesEXT: ProcGetSwapchainTimingPropertiesEXT +GetTensorMemoryRequirementsARM: ProcGetTensorMemoryRequirementsARM +GetTensorOpaqueCaptureDataARM: ProcGetTensorOpaqueCaptureDataARM +GetTensorOpaqueCaptureDescriptorDataARM: ProcGetTensorOpaqueCaptureDescriptorDataARM +GetTensorViewOpaqueCaptureDescriptorDataARM: ProcGetTensorViewOpaqueCaptureDescriptorDataARM GetValidationCacheDataEXT: ProcGetValidationCacheDataEXT GetVideoSessionMemoryRequirementsKHR: ProcGetVideoSessionMemoryRequirementsKHR ImportFenceFdKHR: ProcImportFenceFdKHR @@ -1392,6 +1586,7 @@ QueueSubmit: ProcQueueSubmit QueueSubmit2: ProcQueueSubmit2 QueueSubmit2KHR: ProcQueueSubmit2KHR QueueWaitIdle: ProcQueueWaitIdle +RegisterCustomBorderColorEXT: ProcRegisterCustomBorderColorEXT RegisterDeviceEventEXT: ProcRegisterDeviceEventEXT RegisterDisplayEventEXT: ProcRegisterDisplayEventEXT ReleaseCapturedPipelineDataKHR: ProcReleaseCapturedPipelineDataKHR @@ -1399,23 +1594,27 @@ ReleaseFullScreenExclusiveModeEXT: ProcReleaseFullScreenExc ReleasePerformanceConfigurationINTEL: ProcReleasePerformanceConfigurationINTEL ReleaseProfilingLockKHR: ProcReleaseProfilingLockKHR ReleaseSwapchainImagesEXT: ProcReleaseSwapchainImagesEXT +ReleaseSwapchainImagesKHR: ProcReleaseSwapchainImagesKHR ResetCommandBuffer: ProcResetCommandBuffer ResetCommandPool: ProcResetCommandPool ResetDescriptorPool: ProcResetDescriptorPool ResetEvent: ProcResetEvent ResetFences: ProcResetFences +ResetGpaSessionAMD: ProcResetGpaSessionAMD ResetQueryPool: ProcResetQueryPool ResetQueryPoolEXT: ProcResetQueryPoolEXT SetDebugUtilsObjectNameEXT: ProcSetDebugUtilsObjectNameEXT SetDebugUtilsObjectTagEXT: ProcSetDebugUtilsObjectTagEXT SetDeviceMemoryPriorityEXT: ProcSetDeviceMemoryPriorityEXT SetEvent: ProcSetEvent +SetGpaDeviceClockModeAMD: ProcSetGpaDeviceClockModeAMD SetHdrMetadataEXT: ProcSetHdrMetadataEXT SetLatencyMarkerNV: ProcSetLatencyMarkerNV SetLatencySleepModeNV: ProcSetLatencySleepModeNV SetLocalDimmingAMD: ProcSetLocalDimmingAMD SetPrivateData: ProcSetPrivateData SetPrivateDataEXT: ProcSetPrivateDataEXT +SetSwapchainPresentTimingQueueSizeEXT: ProcSetSwapchainPresentTimingQueueSizeEXT SignalSemaphore: ProcSignalSemaphore SignalSemaphoreKHR: ProcSignalSemaphoreKHR TransitionImageLayout: ProcTransitionImageLayout @@ -1426,6 +1625,7 @@ UninitializePerformanceApiINTEL: ProcUninitializePerforma UnmapMemory: ProcUnmapMemory UnmapMemory2: ProcUnmapMemory2 UnmapMemory2KHR: ProcUnmapMemory2KHR +UnregisterCustomBorderColorEXT: ProcUnregisterCustomBorderColorEXT UpdateDescriptorSetWithTemplate: ProcUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplateKHR: ProcUpdateDescriptorSetWithTemplateKHR UpdateDescriptorSets: ProcUpdateDescriptorSets @@ -1433,11 +1633,14 @@ UpdateIndirectExecutionSetPipelineEXT: ProcUpdateIndirectExecut UpdateIndirectExecutionSetShaderEXT: ProcUpdateIndirectExecutionSetShaderEXT UpdateVideoSessionParametersKHR: ProcUpdateVideoSessionParametersKHR WaitForFences: ProcWaitForFences +WaitForPresent2KHR: ProcWaitForPresent2KHR WaitForPresentKHR: ProcWaitForPresentKHR WaitSemaphores: ProcWaitSemaphores WaitSemaphoresKHR: ProcWaitSemaphoresKHR WriteAccelerationStructuresPropertiesKHR: ProcWriteAccelerationStructuresPropertiesKHR WriteMicromapsPropertiesEXT: ProcWriteMicromapsPropertiesEXT +WriteResourceDescriptorsEXT: ProcWriteResourceDescriptorsEXT +WriteSamplerDescriptorsEXT: ProcWriteSamplerDescriptorsEXT load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { // Loader Procedures @@ -1447,106 +1650,115 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties") set_proc_address(&EnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties") set_proc_address(&EnumerateInstanceVersion, "vkEnumerateInstanceVersion") + set_proc_address(&GetExternalComputeQueueDataNV, "vkGetExternalComputeQueueDataNV") set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr") // Instance Procedures - set_proc_address(&AcquireDrmDisplayEXT, "vkAcquireDrmDisplayEXT") - set_proc_address(&AcquireWinrtDisplayNV, "vkAcquireWinrtDisplayNV") - set_proc_address(&CreateDebugReportCallbackEXT, "vkCreateDebugReportCallbackEXT") - set_proc_address(&CreateDebugUtilsMessengerEXT, "vkCreateDebugUtilsMessengerEXT") - set_proc_address(&CreateDevice, "vkCreateDevice") - set_proc_address(&CreateDisplayModeKHR, "vkCreateDisplayModeKHR") - set_proc_address(&CreateDisplayPlaneSurfaceKHR, "vkCreateDisplayPlaneSurfaceKHR") - set_proc_address(&CreateHeadlessSurfaceEXT, "vkCreateHeadlessSurfaceEXT") - set_proc_address(&CreateIOSSurfaceMVK, "vkCreateIOSSurfaceMVK") - set_proc_address(&CreateMacOSSurfaceMVK, "vkCreateMacOSSurfaceMVK") - set_proc_address(&CreateMetalSurfaceEXT, "vkCreateMetalSurfaceEXT") - set_proc_address(&CreateWaylandSurfaceKHR, "vkCreateWaylandSurfaceKHR") - set_proc_address(&CreateWin32SurfaceKHR, "vkCreateWin32SurfaceKHR") - set_proc_address(&CreateXcbSurfaceKHR, "vkCreateXcbSurfaceKHR") - set_proc_address(&CreateXlibSurfaceKHR, "vkCreateXlibSurfaceKHR") - set_proc_address(&DebugReportMessageEXT, "vkDebugReportMessageEXT") - set_proc_address(&DestroyDebugReportCallbackEXT, "vkDestroyDebugReportCallbackEXT") - set_proc_address(&DestroyDebugUtilsMessengerEXT, "vkDestroyDebugUtilsMessengerEXT") - set_proc_address(&DestroyInstance, "vkDestroyInstance") - set_proc_address(&DestroySurfaceKHR, "vkDestroySurfaceKHR") - set_proc_address(&EnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties") - set_proc_address(&EnumerateDeviceLayerProperties, "vkEnumerateDeviceLayerProperties") - set_proc_address(&EnumeratePhysicalDeviceGroups, "vkEnumeratePhysicalDeviceGroups") - set_proc_address(&EnumeratePhysicalDeviceGroupsKHR, "vkEnumeratePhysicalDeviceGroupsKHR") - set_proc_address(&EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR") - set_proc_address(&EnumeratePhysicalDevices, "vkEnumeratePhysicalDevices") - set_proc_address(&GetDisplayModeProperties2KHR, "vkGetDisplayModeProperties2KHR") - set_proc_address(&GetDisplayModePropertiesKHR, "vkGetDisplayModePropertiesKHR") - set_proc_address(&GetDisplayPlaneCapabilities2KHR, "vkGetDisplayPlaneCapabilities2KHR") - set_proc_address(&GetDisplayPlaneCapabilitiesKHR, "vkGetDisplayPlaneCapabilitiesKHR") - set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR") - set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT") - set_proc_address(&GetInstanceProcAddrLUNARG, "vkGetInstanceProcAddrLUNARG") - set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") - set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsKHR, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR") - set_proc_address(&GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") - set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesKHR, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") - set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") - set_proc_address(&GetPhysicalDeviceCooperativeVectorPropertiesNV, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") - set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") - set_proc_address(&GetPhysicalDeviceDisplayPlanePropertiesKHR, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") - set_proc_address(&GetPhysicalDeviceDisplayProperties2KHR, "vkGetPhysicalDeviceDisplayProperties2KHR") - set_proc_address(&GetPhysicalDeviceDisplayPropertiesKHR, "vkGetPhysicalDeviceDisplayPropertiesKHR") - set_proc_address(&GetPhysicalDeviceExternalBufferProperties, "vkGetPhysicalDeviceExternalBufferProperties") - set_proc_address(&GetPhysicalDeviceExternalBufferPropertiesKHR, "vkGetPhysicalDeviceExternalBufferPropertiesKHR") - set_proc_address(&GetPhysicalDeviceExternalFenceProperties, "vkGetPhysicalDeviceExternalFenceProperties") - set_proc_address(&GetPhysicalDeviceExternalFencePropertiesKHR, "vkGetPhysicalDeviceExternalFencePropertiesKHR") - set_proc_address(&GetPhysicalDeviceExternalImageFormatPropertiesNV, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV") - set_proc_address(&GetPhysicalDeviceExternalSemaphoreProperties, "vkGetPhysicalDeviceExternalSemaphoreProperties") - set_proc_address(&GetPhysicalDeviceExternalSemaphorePropertiesKHR, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR") - set_proc_address(&GetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures") - set_proc_address(&GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2") - set_proc_address(&GetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR") - set_proc_address(&GetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties") - set_proc_address(&GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2") - set_proc_address(&GetPhysicalDeviceFormatProperties2KHR, "vkGetPhysicalDeviceFormatProperties2KHR") - set_proc_address(&GetPhysicalDeviceFragmentShadingRatesKHR, "vkGetPhysicalDeviceFragmentShadingRatesKHR") - set_proc_address(&GetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties") - set_proc_address(&GetPhysicalDeviceImageFormatProperties2, "vkGetPhysicalDeviceImageFormatProperties2") - set_proc_address(&GetPhysicalDeviceImageFormatProperties2KHR, "vkGetPhysicalDeviceImageFormatProperties2KHR") - set_proc_address(&GetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties") - set_proc_address(&GetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2") - set_proc_address(&GetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR") - set_proc_address(&GetPhysicalDeviceMultisamplePropertiesEXT, "vkGetPhysicalDeviceMultisamplePropertiesEXT") - set_proc_address(&GetPhysicalDeviceOpticalFlowImageFormatsNV, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV") - set_proc_address(&GetPhysicalDevicePresentRectanglesKHR, "vkGetPhysicalDevicePresentRectanglesKHR") - set_proc_address(&GetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties") - set_proc_address(&GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2") - set_proc_address(&GetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR") - set_proc_address(&GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR") - set_proc_address(&GetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties") - set_proc_address(&GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2") - set_proc_address(&GetPhysicalDeviceQueueFamilyProperties2KHR, "vkGetPhysicalDeviceQueueFamilyProperties2KHR") - set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties, "vkGetPhysicalDeviceSparseImageFormatProperties") - set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties2, "vkGetPhysicalDeviceSparseImageFormatProperties2") - set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties2KHR, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR") - set_proc_address(&GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV") - set_proc_address(&GetPhysicalDeviceSurfaceCapabilities2EXT, "vkGetPhysicalDeviceSurfaceCapabilities2EXT") - set_proc_address(&GetPhysicalDeviceSurfaceCapabilities2KHR, "vkGetPhysicalDeviceSurfaceCapabilities2KHR") - set_proc_address(&GetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") - set_proc_address(&GetPhysicalDeviceSurfaceFormats2KHR, "vkGetPhysicalDeviceSurfaceFormats2KHR") - set_proc_address(&GetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR") - set_proc_address(&GetPhysicalDeviceSurfacePresentModes2EXT, "vkGetPhysicalDeviceSurfacePresentModes2EXT") - set_proc_address(&GetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR") - set_proc_address(&GetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR") - set_proc_address(&GetPhysicalDeviceToolProperties, "vkGetPhysicalDeviceToolProperties") - set_proc_address(&GetPhysicalDeviceToolPropertiesEXT, "vkGetPhysicalDeviceToolPropertiesEXT") - set_proc_address(&GetPhysicalDeviceVideoCapabilitiesKHR, "vkGetPhysicalDeviceVideoCapabilitiesKHR") - set_proc_address(&GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR") - set_proc_address(&GetPhysicalDeviceVideoFormatPropertiesKHR, "vkGetPhysicalDeviceVideoFormatPropertiesKHR") - set_proc_address(&GetPhysicalDeviceWaylandPresentationSupportKHR, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") - set_proc_address(&GetPhysicalDeviceWin32PresentationSupportKHR, "vkGetPhysicalDeviceWin32PresentationSupportKHR") - set_proc_address(&GetPhysicalDeviceXcbPresentationSupportKHR, "vkGetPhysicalDeviceXcbPresentationSupportKHR") - set_proc_address(&GetPhysicalDeviceXlibPresentationSupportKHR, "vkGetPhysicalDeviceXlibPresentationSupportKHR") - set_proc_address(&GetWinrtDisplayNV, "vkGetWinrtDisplayNV") - set_proc_address(&ReleaseDisplayEXT, "vkReleaseDisplayEXT") - set_proc_address(&SubmitDebugUtilsMessageEXT, "vkSubmitDebugUtilsMessageEXT") + set_proc_address(&AcquireDrmDisplayEXT, "vkAcquireDrmDisplayEXT") + set_proc_address(&AcquireWinrtDisplayNV, "vkAcquireWinrtDisplayNV") + set_proc_address(&CreateDebugReportCallbackEXT, "vkCreateDebugReportCallbackEXT") + set_proc_address(&CreateDebugUtilsMessengerEXT, "vkCreateDebugUtilsMessengerEXT") + set_proc_address(&CreateDevice, "vkCreateDevice") + set_proc_address(&CreateDisplayModeKHR, "vkCreateDisplayModeKHR") + set_proc_address(&CreateDisplayPlaneSurfaceKHR, "vkCreateDisplayPlaneSurfaceKHR") + set_proc_address(&CreateHeadlessSurfaceEXT, "vkCreateHeadlessSurfaceEXT") + set_proc_address(&CreateIOSSurfaceMVK, "vkCreateIOSSurfaceMVK") + set_proc_address(&CreateMacOSSurfaceMVK, "vkCreateMacOSSurfaceMVK") + set_proc_address(&CreateMetalSurfaceEXT, "vkCreateMetalSurfaceEXT") + set_proc_address(&CreateWaylandSurfaceKHR, "vkCreateWaylandSurfaceKHR") + set_proc_address(&CreateWin32SurfaceKHR, "vkCreateWin32SurfaceKHR") + set_proc_address(&CreateXcbSurfaceKHR, "vkCreateXcbSurfaceKHR") + set_proc_address(&CreateXlibSurfaceKHR, "vkCreateXlibSurfaceKHR") + set_proc_address(&DebugReportMessageEXT, "vkDebugReportMessageEXT") + set_proc_address(&DestroyDebugReportCallbackEXT, "vkDestroyDebugReportCallbackEXT") + set_proc_address(&DestroyDebugUtilsMessengerEXT, "vkDestroyDebugUtilsMessengerEXT") + set_proc_address(&DestroyInstance, "vkDestroyInstance") + set_proc_address(&DestroySurfaceKHR, "vkDestroySurfaceKHR") + set_proc_address(&EnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties") + set_proc_address(&EnumerateDeviceLayerProperties, "vkEnumerateDeviceLayerProperties") + set_proc_address(&EnumeratePhysicalDeviceGroups, "vkEnumeratePhysicalDeviceGroups") + set_proc_address(&EnumeratePhysicalDeviceGroupsKHR, "vkEnumeratePhysicalDeviceGroupsKHR") + set_proc_address(&EnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM") + set_proc_address(&EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR") + set_proc_address(&EnumeratePhysicalDeviceShaderInstrumentationMetricsARM, "vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM") + set_proc_address(&EnumeratePhysicalDevices, "vkEnumeratePhysicalDevices") + set_proc_address(&GetDisplayModeProperties2KHR, "vkGetDisplayModeProperties2KHR") + set_proc_address(&GetDisplayModePropertiesKHR, "vkGetDisplayModePropertiesKHR") + set_proc_address(&GetDisplayPlaneCapabilities2KHR, "vkGetDisplayPlaneCapabilities2KHR") + set_proc_address(&GetDisplayPlaneCapabilitiesKHR, "vkGetDisplayPlaneCapabilitiesKHR") + set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR") + set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT") + set_proc_address(&GetInstanceProcAddrLUNARG, "vkGetInstanceProcAddrLUNARG") + set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") + set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsKHR, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR") + set_proc_address(&GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") + set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesKHR, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") + set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") + set_proc_address(&GetPhysicalDeviceCooperativeVectorPropertiesNV, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") + set_proc_address(&GetPhysicalDeviceDescriptorSizeEXT, "vkGetPhysicalDeviceDescriptorSizeEXT") + set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") + set_proc_address(&GetPhysicalDeviceDisplayPlanePropertiesKHR, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") + set_proc_address(&GetPhysicalDeviceDisplayProperties2KHR, "vkGetPhysicalDeviceDisplayProperties2KHR") + set_proc_address(&GetPhysicalDeviceDisplayPropertiesKHR, "vkGetPhysicalDeviceDisplayPropertiesKHR") + set_proc_address(&GetPhysicalDeviceExternalBufferProperties, "vkGetPhysicalDeviceExternalBufferProperties") + set_proc_address(&GetPhysicalDeviceExternalBufferPropertiesKHR, "vkGetPhysicalDeviceExternalBufferPropertiesKHR") + set_proc_address(&GetPhysicalDeviceExternalFenceProperties, "vkGetPhysicalDeviceExternalFenceProperties") + set_proc_address(&GetPhysicalDeviceExternalFencePropertiesKHR, "vkGetPhysicalDeviceExternalFencePropertiesKHR") + set_proc_address(&GetPhysicalDeviceExternalImageFormatPropertiesNV, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV") + set_proc_address(&GetPhysicalDeviceExternalSemaphoreProperties, "vkGetPhysicalDeviceExternalSemaphoreProperties") + set_proc_address(&GetPhysicalDeviceExternalSemaphorePropertiesKHR, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR") + set_proc_address(&GetPhysicalDeviceExternalTensorPropertiesARM, "vkGetPhysicalDeviceExternalTensorPropertiesARM") + set_proc_address(&GetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures") + set_proc_address(&GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2") + set_proc_address(&GetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR") + set_proc_address(&GetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties") + set_proc_address(&GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2") + set_proc_address(&GetPhysicalDeviceFormatProperties2KHR, "vkGetPhysicalDeviceFormatProperties2KHR") + set_proc_address(&GetPhysicalDeviceFragmentShadingRatesKHR, "vkGetPhysicalDeviceFragmentShadingRatesKHR") + set_proc_address(&GetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties") + set_proc_address(&GetPhysicalDeviceImageFormatProperties2, "vkGetPhysicalDeviceImageFormatProperties2") + set_proc_address(&GetPhysicalDeviceImageFormatProperties2KHR, "vkGetPhysicalDeviceImageFormatProperties2KHR") + set_proc_address(&GetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties") + set_proc_address(&GetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2") + set_proc_address(&GetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR") + set_proc_address(&GetPhysicalDeviceMultisamplePropertiesEXT, "vkGetPhysicalDeviceMultisamplePropertiesEXT") + set_proc_address(&GetPhysicalDeviceOpticalFlowImageFormatsNV, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV") + set_proc_address(&GetPhysicalDevicePresentRectanglesKHR, "vkGetPhysicalDevicePresentRectanglesKHR") + set_proc_address(&GetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties") + set_proc_address(&GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2") + set_proc_address(&GetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR") + set_proc_address(&GetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM, "vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM") + set_proc_address(&GetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM, "vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM") + set_proc_address(&GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM, "vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM") + set_proc_address(&GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM, "vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM") + set_proc_address(&GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR") + set_proc_address(&GetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties") + set_proc_address(&GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2") + set_proc_address(&GetPhysicalDeviceQueueFamilyProperties2KHR, "vkGetPhysicalDeviceQueueFamilyProperties2KHR") + set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties, "vkGetPhysicalDeviceSparseImageFormatProperties") + set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties2, "vkGetPhysicalDeviceSparseImageFormatProperties2") + set_proc_address(&GetPhysicalDeviceSparseImageFormatProperties2KHR, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR") + set_proc_address(&GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV") + set_proc_address(&GetPhysicalDeviceSurfaceCapabilities2EXT, "vkGetPhysicalDeviceSurfaceCapabilities2EXT") + set_proc_address(&GetPhysicalDeviceSurfaceCapabilities2KHR, "vkGetPhysicalDeviceSurfaceCapabilities2KHR") + set_proc_address(&GetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") + set_proc_address(&GetPhysicalDeviceSurfaceFormats2KHR, "vkGetPhysicalDeviceSurfaceFormats2KHR") + set_proc_address(&GetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR") + set_proc_address(&GetPhysicalDeviceSurfacePresentModes2EXT, "vkGetPhysicalDeviceSurfacePresentModes2EXT") + set_proc_address(&GetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR") + set_proc_address(&GetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR") + set_proc_address(&GetPhysicalDeviceToolProperties, "vkGetPhysicalDeviceToolProperties") + set_proc_address(&GetPhysicalDeviceToolPropertiesEXT, "vkGetPhysicalDeviceToolPropertiesEXT") + set_proc_address(&GetPhysicalDeviceVideoCapabilitiesKHR, "vkGetPhysicalDeviceVideoCapabilitiesKHR") + set_proc_address(&GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR") + set_proc_address(&GetPhysicalDeviceVideoFormatPropertiesKHR, "vkGetPhysicalDeviceVideoFormatPropertiesKHR") + set_proc_address(&GetPhysicalDeviceWaylandPresentationSupportKHR, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") + set_proc_address(&GetPhysicalDeviceWin32PresentationSupportKHR, "vkGetPhysicalDeviceWin32PresentationSupportKHR") + set_proc_address(&GetPhysicalDeviceXcbPresentationSupportKHR, "vkGetPhysicalDeviceXcbPresentationSupportKHR") + set_proc_address(&GetPhysicalDeviceXlibPresentationSupportKHR, "vkGetPhysicalDeviceXlibPresentationSupportKHR") + set_proc_address(&GetWinrtDisplayNV, "vkGetWinrtDisplayNV") + set_proc_address(&ReleaseDisplayEXT, "vkReleaseDisplayEXT") + set_proc_address(&SubmitDebugUtilsMessageEXT, "vkSubmitDebugUtilsMessageEXT") // Device Procedures set_proc_address(&AcquireFullScreenExclusiveModeEXT, "vkAcquireFullScreenExclusiveModeEXT") @@ -1563,15 +1775,23 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&BindBufferMemory, "vkBindBufferMemory") set_proc_address(&BindBufferMemory2, "vkBindBufferMemory2") set_proc_address(&BindBufferMemory2KHR, "vkBindBufferMemory2KHR") + set_proc_address(&BindDataGraphPipelineSessionMemoryARM, "vkBindDataGraphPipelineSessionMemoryARM") set_proc_address(&BindImageMemory, "vkBindImageMemory") set_proc_address(&BindImageMemory2, "vkBindImageMemory2") set_proc_address(&BindImageMemory2KHR, "vkBindImageMemory2KHR") set_proc_address(&BindOpticalFlowSessionImageNV, "vkBindOpticalFlowSessionImageNV") + set_proc_address(&BindTensorMemoryARM, "vkBindTensorMemoryARM") set_proc_address(&BindVideoSessionMemoryKHR, "vkBindVideoSessionMemoryKHR") set_proc_address(&BuildAccelerationStructuresKHR, "vkBuildAccelerationStructuresKHR") set_proc_address(&BuildMicromapsEXT, "vkBuildMicromapsEXT") + set_proc_address(&ClearShaderInstrumentationMetricsARM, "vkClearShaderInstrumentationMetricsARM") + set_proc_address(&CmdBeginConditionalRendering2EXT, "vkCmdBeginConditionalRendering2EXT") set_proc_address(&CmdBeginConditionalRenderingEXT, "vkCmdBeginConditionalRenderingEXT") + set_proc_address(&CmdBeginCustomResolveEXT, "vkCmdBeginCustomResolveEXT") set_proc_address(&CmdBeginDebugUtilsLabelEXT, "vkCmdBeginDebugUtilsLabelEXT") + set_proc_address(&CmdBeginGpaSampleAMD, "vkCmdBeginGpaSampleAMD") + set_proc_address(&CmdBeginGpaSessionAMD, "vkCmdBeginGpaSessionAMD") + set_proc_address(&CmdBeginPerTileExecutionQCOM, "vkCmdBeginPerTileExecutionQCOM") set_proc_address(&CmdBeginQuery, "vkCmdBeginQuery") set_proc_address(&CmdBeginQueryIndexedEXT, "vkCmdBeginQueryIndexedEXT") set_proc_address(&CmdBeginRenderPass, "vkCmdBeginRenderPass") @@ -1579,6 +1799,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdBeginRenderPass2KHR, "vkCmdBeginRenderPass2KHR") set_proc_address(&CmdBeginRendering, "vkCmdBeginRendering") set_proc_address(&CmdBeginRenderingKHR, "vkCmdBeginRenderingKHR") + set_proc_address(&CmdBeginShaderInstrumentationARM, "vkCmdBeginShaderInstrumentationARM") + set_proc_address(&CmdBeginTransformFeedback2EXT, "vkCmdBeginTransformFeedback2EXT") set_proc_address(&CmdBeginTransformFeedbackEXT, "vkCmdBeginTransformFeedbackEXT") set_proc_address(&CmdBeginVideoCodingKHR, "vkCmdBeginVideoCodingKHR") set_proc_address(&CmdBindDescriptorBufferEmbeddedSamplers2EXT, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT") @@ -1590,15 +1812,21 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdBindIndexBuffer, "vkCmdBindIndexBuffer") set_proc_address(&CmdBindIndexBuffer2, "vkCmdBindIndexBuffer2") set_proc_address(&CmdBindIndexBuffer2KHR, "vkCmdBindIndexBuffer2KHR") + set_proc_address(&CmdBindIndexBuffer3KHR, "vkCmdBindIndexBuffer3KHR") set_proc_address(&CmdBindInvocationMaskHUAWEI, "vkCmdBindInvocationMaskHUAWEI") set_proc_address(&CmdBindPipeline, "vkCmdBindPipeline") set_proc_address(&CmdBindPipelineShaderGroupNV, "vkCmdBindPipelineShaderGroupNV") + set_proc_address(&CmdBindResourceHeapEXT, "vkCmdBindResourceHeapEXT") + set_proc_address(&CmdBindSamplerHeapEXT, "vkCmdBindSamplerHeapEXT") set_proc_address(&CmdBindShadersEXT, "vkCmdBindShadersEXT") set_proc_address(&CmdBindShadingRateImageNV, "vkCmdBindShadingRateImageNV") + set_proc_address(&CmdBindTileMemoryQCOM, "vkCmdBindTileMemoryQCOM") + set_proc_address(&CmdBindTransformFeedbackBuffers2EXT, "vkCmdBindTransformFeedbackBuffers2EXT") set_proc_address(&CmdBindTransformFeedbackBuffersEXT, "vkCmdBindTransformFeedbackBuffersEXT") set_proc_address(&CmdBindVertexBuffers, "vkCmdBindVertexBuffers") set_proc_address(&CmdBindVertexBuffers2, "vkCmdBindVertexBuffers2") set_proc_address(&CmdBindVertexBuffers2EXT, "vkCmdBindVertexBuffers2EXT") + set_proc_address(&CmdBindVertexBuffers3KHR, "vkCmdBindVertexBuffers3KHR") set_proc_address(&CmdBlitImage, "vkCmdBlitImage") set_proc_address(&CmdBlitImage2, "vkCmdBlitImage2") set_proc_address(&CmdBlitImage2KHR, "vkCmdBlitImage2KHR") @@ -1622,48 +1850,68 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdCopyBufferToImage, "vkCmdCopyBufferToImage") set_proc_address(&CmdCopyBufferToImage2, "vkCmdCopyBufferToImage2") set_proc_address(&CmdCopyBufferToImage2KHR, "vkCmdCopyBufferToImage2KHR") + set_proc_address(&CmdCopyGpaSessionResultsAMD, "vkCmdCopyGpaSessionResultsAMD") set_proc_address(&CmdCopyImage, "vkCmdCopyImage") set_proc_address(&CmdCopyImage2, "vkCmdCopyImage2") set_proc_address(&CmdCopyImage2KHR, "vkCmdCopyImage2KHR") set_proc_address(&CmdCopyImageToBuffer, "vkCmdCopyImageToBuffer") set_proc_address(&CmdCopyImageToBuffer2, "vkCmdCopyImageToBuffer2") set_proc_address(&CmdCopyImageToBuffer2KHR, "vkCmdCopyImageToBuffer2KHR") + set_proc_address(&CmdCopyImageToMemoryKHR, "vkCmdCopyImageToMemoryKHR") + set_proc_address(&CmdCopyMemoryIndirectKHR, "vkCmdCopyMemoryIndirectKHR") set_proc_address(&CmdCopyMemoryIndirectNV, "vkCmdCopyMemoryIndirectNV") + set_proc_address(&CmdCopyMemoryKHR, "vkCmdCopyMemoryKHR") set_proc_address(&CmdCopyMemoryToAccelerationStructureKHR, "vkCmdCopyMemoryToAccelerationStructureKHR") + set_proc_address(&CmdCopyMemoryToImageIndirectKHR, "vkCmdCopyMemoryToImageIndirectKHR") set_proc_address(&CmdCopyMemoryToImageIndirectNV, "vkCmdCopyMemoryToImageIndirectNV") + set_proc_address(&CmdCopyMemoryToImageKHR, "vkCmdCopyMemoryToImageKHR") set_proc_address(&CmdCopyMemoryToMicromapEXT, "vkCmdCopyMemoryToMicromapEXT") set_proc_address(&CmdCopyMicromapEXT, "vkCmdCopyMicromapEXT") set_proc_address(&CmdCopyMicromapToMemoryEXT, "vkCmdCopyMicromapToMemoryEXT") set_proc_address(&CmdCopyQueryPoolResults, "vkCmdCopyQueryPoolResults") + set_proc_address(&CmdCopyQueryPoolResultsToMemoryKHR, "vkCmdCopyQueryPoolResultsToMemoryKHR") + set_proc_address(&CmdCopyTensorARM, "vkCmdCopyTensorARM") set_proc_address(&CmdCuLaunchKernelNVX, "vkCmdCuLaunchKernelNVX") set_proc_address(&CmdCudaLaunchKernelNV, "vkCmdCudaLaunchKernelNV") set_proc_address(&CmdDebugMarkerBeginEXT, "vkCmdDebugMarkerBeginEXT") set_proc_address(&CmdDebugMarkerEndEXT, "vkCmdDebugMarkerEndEXT") set_proc_address(&CmdDebugMarkerInsertEXT, "vkCmdDebugMarkerInsertEXT") set_proc_address(&CmdDecodeVideoKHR, "vkCmdDecodeVideoKHR") + set_proc_address(&CmdDecompressMemoryEXT, "vkCmdDecompressMemoryEXT") + set_proc_address(&CmdDecompressMemoryIndirectCountEXT, "vkCmdDecompressMemoryIndirectCountEXT") set_proc_address(&CmdDecompressMemoryIndirectCountNV, "vkCmdDecompressMemoryIndirectCountNV") set_proc_address(&CmdDecompressMemoryNV, "vkCmdDecompressMemoryNV") set_proc_address(&CmdDispatch, "vkCmdDispatch") set_proc_address(&CmdDispatchBase, "vkCmdDispatchBase") set_proc_address(&CmdDispatchBaseKHR, "vkCmdDispatchBaseKHR") + set_proc_address(&CmdDispatchDataGraphARM, "vkCmdDispatchDataGraphARM") set_proc_address(&CmdDispatchGraphAMDX, "vkCmdDispatchGraphAMDX") set_proc_address(&CmdDispatchGraphIndirectAMDX, "vkCmdDispatchGraphIndirectAMDX") set_proc_address(&CmdDispatchGraphIndirectCountAMDX, "vkCmdDispatchGraphIndirectCountAMDX") set_proc_address(&CmdDispatchIndirect, "vkCmdDispatchIndirect") + set_proc_address(&CmdDispatchIndirect2KHR, "vkCmdDispatchIndirect2KHR") + set_proc_address(&CmdDispatchTileQCOM, "vkCmdDispatchTileQCOM") set_proc_address(&CmdDraw, "vkCmdDraw") set_proc_address(&CmdDrawClusterHUAWEI, "vkCmdDrawClusterHUAWEI") set_proc_address(&CmdDrawClusterIndirectHUAWEI, "vkCmdDrawClusterIndirectHUAWEI") set_proc_address(&CmdDrawIndexed, "vkCmdDrawIndexed") set_proc_address(&CmdDrawIndexedIndirect, "vkCmdDrawIndexedIndirect") + set_proc_address(&CmdDrawIndexedIndirect2KHR, "vkCmdDrawIndexedIndirect2KHR") set_proc_address(&CmdDrawIndexedIndirectCount, "vkCmdDrawIndexedIndirectCount") + set_proc_address(&CmdDrawIndexedIndirectCount2KHR, "vkCmdDrawIndexedIndirectCount2KHR") set_proc_address(&CmdDrawIndexedIndirectCountAMD, "vkCmdDrawIndexedIndirectCountAMD") set_proc_address(&CmdDrawIndexedIndirectCountKHR, "vkCmdDrawIndexedIndirectCountKHR") set_proc_address(&CmdDrawIndirect, "vkCmdDrawIndirect") + set_proc_address(&CmdDrawIndirect2KHR, "vkCmdDrawIndirect2KHR") + set_proc_address(&CmdDrawIndirectByteCount2EXT, "vkCmdDrawIndirectByteCount2EXT") set_proc_address(&CmdDrawIndirectByteCountEXT, "vkCmdDrawIndirectByteCountEXT") set_proc_address(&CmdDrawIndirectCount, "vkCmdDrawIndirectCount") + set_proc_address(&CmdDrawIndirectCount2KHR, "vkCmdDrawIndirectCount2KHR") set_proc_address(&CmdDrawIndirectCountAMD, "vkCmdDrawIndirectCountAMD") set_proc_address(&CmdDrawIndirectCountKHR, "vkCmdDrawIndirectCountKHR") set_proc_address(&CmdDrawMeshTasksEXT, "vkCmdDrawMeshTasksEXT") + set_proc_address(&CmdDrawMeshTasksIndirect2EXT, "vkCmdDrawMeshTasksIndirect2EXT") + set_proc_address(&CmdDrawMeshTasksIndirectCount2EXT, "vkCmdDrawMeshTasksIndirectCount2EXT") set_proc_address(&CmdDrawMeshTasksIndirectCountEXT, "vkCmdDrawMeshTasksIndirectCountEXT") set_proc_address(&CmdDrawMeshTasksIndirectCountNV, "vkCmdDrawMeshTasksIndirectCountNV") set_proc_address(&CmdDrawMeshTasksIndirectEXT, "vkCmdDrawMeshTasksIndirectEXT") @@ -1674,19 +1922,27 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdEncodeVideoKHR, "vkCmdEncodeVideoKHR") set_proc_address(&CmdEndConditionalRenderingEXT, "vkCmdEndConditionalRenderingEXT") set_proc_address(&CmdEndDebugUtilsLabelEXT, "vkCmdEndDebugUtilsLabelEXT") + set_proc_address(&CmdEndGpaSampleAMD, "vkCmdEndGpaSampleAMD") + set_proc_address(&CmdEndGpaSessionAMD, "vkCmdEndGpaSessionAMD") + set_proc_address(&CmdEndPerTileExecutionQCOM, "vkCmdEndPerTileExecutionQCOM") set_proc_address(&CmdEndQuery, "vkCmdEndQuery") set_proc_address(&CmdEndQueryIndexedEXT, "vkCmdEndQueryIndexedEXT") set_proc_address(&CmdEndRenderPass, "vkCmdEndRenderPass") set_proc_address(&CmdEndRenderPass2, "vkCmdEndRenderPass2") set_proc_address(&CmdEndRenderPass2KHR, "vkCmdEndRenderPass2KHR") set_proc_address(&CmdEndRendering, "vkCmdEndRendering") + set_proc_address(&CmdEndRendering2EXT, "vkCmdEndRendering2EXT") + set_proc_address(&CmdEndRendering2KHR, "vkCmdEndRendering2KHR") set_proc_address(&CmdEndRenderingKHR, "vkCmdEndRenderingKHR") + set_proc_address(&CmdEndShaderInstrumentationARM, "vkCmdEndShaderInstrumentationARM") + set_proc_address(&CmdEndTransformFeedback2EXT, "vkCmdEndTransformFeedback2EXT") set_proc_address(&CmdEndTransformFeedbackEXT, "vkCmdEndTransformFeedbackEXT") set_proc_address(&CmdEndVideoCodingKHR, "vkCmdEndVideoCodingKHR") set_proc_address(&CmdExecuteCommands, "vkCmdExecuteCommands") set_proc_address(&CmdExecuteGeneratedCommandsEXT, "vkCmdExecuteGeneratedCommandsEXT") set_proc_address(&CmdExecuteGeneratedCommandsNV, "vkCmdExecuteGeneratedCommandsNV") set_proc_address(&CmdFillBuffer, "vkCmdFillBuffer") + set_proc_address(&CmdFillMemoryKHR, "vkCmdFillMemoryKHR") set_proc_address(&CmdInitializeGraphScratchMemoryAMDX, "vkCmdInitializeGraphScratchMemoryAMDX") set_proc_address(&CmdInsertDebugUtilsLabelEXT, "vkCmdInsertDebugUtilsLabelEXT") set_proc_address(&CmdNextSubpass, "vkCmdNextSubpass") @@ -1701,6 +1957,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdPushConstants, "vkCmdPushConstants") set_proc_address(&CmdPushConstants2, "vkCmdPushConstants2") set_proc_address(&CmdPushConstants2KHR, "vkCmdPushConstants2KHR") + set_proc_address(&CmdPushDataEXT, "vkCmdPushDataEXT") set_proc_address(&CmdPushDescriptorSet, "vkCmdPushDescriptorSet") set_proc_address(&CmdPushDescriptorSet2, "vkCmdPushDescriptorSet2") set_proc_address(&CmdPushDescriptorSet2KHR, "vkCmdPushDescriptorSet2KHR") @@ -1725,7 +1982,9 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdSetColorBlendAdvancedEXT, "vkCmdSetColorBlendAdvancedEXT") set_proc_address(&CmdSetColorBlendEnableEXT, "vkCmdSetColorBlendEnableEXT") set_proc_address(&CmdSetColorBlendEquationEXT, "vkCmdSetColorBlendEquationEXT") + set_proc_address(&CmdSetColorWriteEnableEXT, "vkCmdSetColorWriteEnableEXT") set_proc_address(&CmdSetColorWriteMaskEXT, "vkCmdSetColorWriteMaskEXT") + set_proc_address(&CmdSetComputeOccupancyPriorityNV, "vkCmdSetComputeOccupancyPriorityNV") set_proc_address(&CmdSetConservativeRasterizationModeEXT, "vkCmdSetConservativeRasterizationModeEXT") set_proc_address(&CmdSetCoverageModulationModeNV, "vkCmdSetCoverageModulationModeNV") set_proc_address(&CmdSetCoverageModulationTableEnableNV, "vkCmdSetCoverageModulationTableEnableNV") @@ -1759,6 +2018,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdSetDiscardRectangleEXT, "vkCmdSetDiscardRectangleEXT") set_proc_address(&CmdSetDiscardRectangleEnableEXT, "vkCmdSetDiscardRectangleEnableEXT") set_proc_address(&CmdSetDiscardRectangleModeEXT, "vkCmdSetDiscardRectangleModeEXT") + set_proc_address(&CmdSetDispatchParametersARM, "vkCmdSetDispatchParametersARM") set_proc_address(&CmdSetEvent, "vkCmdSetEvent") set_proc_address(&CmdSetEvent2, "vkCmdSetEvent2") set_proc_address(&CmdSetEvent2KHR, "vkCmdSetEvent2KHR") @@ -1784,6 +2044,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdSetPolygonModeEXT, "vkCmdSetPolygonModeEXT") set_proc_address(&CmdSetPrimitiveRestartEnable, "vkCmdSetPrimitiveRestartEnable") set_proc_address(&CmdSetPrimitiveRestartEnableEXT, "vkCmdSetPrimitiveRestartEnableEXT") + set_proc_address(&CmdSetPrimitiveRestartIndexEXT, "vkCmdSetPrimitiveRestartIndexEXT") set_proc_address(&CmdSetPrimitiveTopology, "vkCmdSetPrimitiveTopology") set_proc_address(&CmdSetPrimitiveTopologyEXT, "vkCmdSetPrimitiveTopologyEXT") set_proc_address(&CmdSetProvokingVertexModeEXT, "vkCmdSetProvokingVertexModeEXT") @@ -1826,6 +2087,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdTraceRaysKHR, "vkCmdTraceRaysKHR") set_proc_address(&CmdTraceRaysNV, "vkCmdTraceRaysNV") set_proc_address(&CmdUpdateBuffer, "vkCmdUpdateBuffer") + set_proc_address(&CmdUpdateMemoryKHR, "vkCmdUpdateMemoryKHR") set_proc_address(&CmdUpdatePipelineIndirectBufferNV, "vkCmdUpdatePipelineIndirectBufferNV") set_proc_address(&CmdWaitEvents, "vkCmdWaitEvents") set_proc_address(&CmdWaitEvents2, "vkCmdWaitEvents2") @@ -1834,6 +2096,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CmdWriteAccelerationStructuresPropertiesNV, "vkCmdWriteAccelerationStructuresPropertiesNV") set_proc_address(&CmdWriteBufferMarker2AMD, "vkCmdWriteBufferMarker2AMD") set_proc_address(&CmdWriteBufferMarkerAMD, "vkCmdWriteBufferMarkerAMD") + set_proc_address(&CmdWriteMarkerToMemoryAMD, "vkCmdWriteMarkerToMemoryAMD") set_proc_address(&CmdWriteMicromapsPropertiesEXT, "vkCmdWriteMicromapsPropertiesEXT") set_proc_address(&CmdWriteTimestamp, "vkCmdWriteTimestamp") set_proc_address(&CmdWriteTimestamp2, "vkCmdWriteTimestamp2") @@ -1852,6 +2115,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CopyMemoryToMicromapEXT, "vkCopyMemoryToMicromapEXT") set_proc_address(&CopyMicromapEXT, "vkCopyMicromapEXT") set_proc_address(&CopyMicromapToMemoryEXT, "vkCopyMicromapToMemoryEXT") + set_proc_address(&CreateAccelerationStructure2KHR, "vkCreateAccelerationStructure2KHR") set_proc_address(&CreateAccelerationStructureKHR, "vkCreateAccelerationStructureKHR") set_proc_address(&CreateAccelerationStructureNV, "vkCreateAccelerationStructureNV") set_proc_address(&CreateBuffer, "vkCreateBuffer") @@ -1862,6 +2126,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CreateCuModuleNVX, "vkCreateCuModuleNVX") set_proc_address(&CreateCudaFunctionNV, "vkCreateCudaFunctionNV") set_proc_address(&CreateCudaModuleNV, "vkCreateCudaModuleNV") + set_proc_address(&CreateDataGraphPipelineSessionARM, "vkCreateDataGraphPipelineSessionARM") + set_proc_address(&CreateDataGraphPipelinesARM, "vkCreateDataGraphPipelinesARM") set_proc_address(&CreateDeferredOperationKHR, "vkCreateDeferredOperationKHR") set_proc_address(&CreateDescriptorPool, "vkCreateDescriptorPool") set_proc_address(&CreateDescriptorSetLayout, "vkCreateDescriptorSetLayout") @@ -1869,8 +2135,10 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CreateDescriptorUpdateTemplateKHR, "vkCreateDescriptorUpdateTemplateKHR") set_proc_address(&CreateEvent, "vkCreateEvent") set_proc_address(&CreateExecutionGraphPipelinesAMDX, "vkCreateExecutionGraphPipelinesAMDX") + set_proc_address(&CreateExternalComputeQueueNV, "vkCreateExternalComputeQueueNV") set_proc_address(&CreateFence, "vkCreateFence") set_proc_address(&CreateFramebuffer, "vkCreateFramebuffer") + set_proc_address(&CreateGpaSessionAMD, "vkCreateGpaSessionAMD") set_proc_address(&CreateGraphicsPipelines, "vkCreateGraphicsPipelines") set_proc_address(&CreateImage, "vkCreateImage") set_proc_address(&CreateImageView, "vkCreateImageView") @@ -1894,10 +2162,13 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&CreateSamplerYcbcrConversion, "vkCreateSamplerYcbcrConversion") set_proc_address(&CreateSamplerYcbcrConversionKHR, "vkCreateSamplerYcbcrConversionKHR") set_proc_address(&CreateSemaphore, "vkCreateSemaphore") + set_proc_address(&CreateShaderInstrumentationARM, "vkCreateShaderInstrumentationARM") set_proc_address(&CreateShaderModule, "vkCreateShaderModule") set_proc_address(&CreateShadersEXT, "vkCreateShadersEXT") set_proc_address(&CreateSharedSwapchainsKHR, "vkCreateSharedSwapchainsKHR") set_proc_address(&CreateSwapchainKHR, "vkCreateSwapchainKHR") + set_proc_address(&CreateTensorARM, "vkCreateTensorARM") + set_proc_address(&CreateTensorViewARM, "vkCreateTensorViewARM") set_proc_address(&CreateValidationCacheEXT, "vkCreateValidationCacheEXT") set_proc_address(&CreateVideoSessionKHR, "vkCreateVideoSessionKHR") set_proc_address(&CreateVideoSessionParametersKHR, "vkCreateVideoSessionParametersKHR") @@ -1913,6 +2184,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&DestroyCuModuleNVX, "vkDestroyCuModuleNVX") set_proc_address(&DestroyCudaFunctionNV, "vkDestroyCudaFunctionNV") set_proc_address(&DestroyCudaModuleNV, "vkDestroyCudaModuleNV") + set_proc_address(&DestroyDataGraphPipelineSessionARM, "vkDestroyDataGraphPipelineSessionARM") set_proc_address(&DestroyDeferredOperationKHR, "vkDestroyDeferredOperationKHR") set_proc_address(&DestroyDescriptorPool, "vkDestroyDescriptorPool") set_proc_address(&DestroyDescriptorSetLayout, "vkDestroyDescriptorSetLayout") @@ -1920,8 +2192,10 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&DestroyDescriptorUpdateTemplateKHR, "vkDestroyDescriptorUpdateTemplateKHR") set_proc_address(&DestroyDevice, "vkDestroyDevice") set_proc_address(&DestroyEvent, "vkDestroyEvent") + set_proc_address(&DestroyExternalComputeQueueNV, "vkDestroyExternalComputeQueueNV") set_proc_address(&DestroyFence, "vkDestroyFence") set_proc_address(&DestroyFramebuffer, "vkDestroyFramebuffer") + set_proc_address(&DestroyGpaSessionAMD, "vkDestroyGpaSessionAMD") set_proc_address(&DestroyImage, "vkDestroyImage") set_proc_address(&DestroyImageView, "vkDestroyImageView") set_proc_address(&DestroyIndirectCommandsLayoutEXT, "vkDestroyIndirectCommandsLayoutEXT") @@ -1942,8 +2216,11 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&DestroySamplerYcbcrConversionKHR, "vkDestroySamplerYcbcrConversionKHR") set_proc_address(&DestroySemaphore, "vkDestroySemaphore") set_proc_address(&DestroyShaderEXT, "vkDestroyShaderEXT") + set_proc_address(&DestroyShaderInstrumentationARM, "vkDestroyShaderInstrumentationARM") set_proc_address(&DestroyShaderModule, "vkDestroyShaderModule") set_proc_address(&DestroySwapchainKHR, "vkDestroySwapchainKHR") + set_proc_address(&DestroyTensorARM, "vkDestroyTensorARM") + set_proc_address(&DestroyTensorViewARM, "vkDestroyTensorViewARM") set_proc_address(&DestroyValidationCacheEXT, "vkDestroyValidationCacheEXT") set_proc_address(&DestroyVideoSessionKHR, "vkDestroyVideoSessionKHR") set_proc_address(&DestroyVideoSessionParametersKHR, "vkDestroyVideoSessionParametersKHR") @@ -1973,6 +2250,10 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetCalibratedTimestampsKHR, "vkGetCalibratedTimestampsKHR") set_proc_address(&GetClusterAccelerationStructureBuildSizesNV, "vkGetClusterAccelerationStructureBuildSizesNV") set_proc_address(&GetCudaModuleCacheNV, "vkGetCudaModuleCacheNV") + set_proc_address(&GetDataGraphPipelineAvailablePropertiesARM, "vkGetDataGraphPipelineAvailablePropertiesARM") + set_proc_address(&GetDataGraphPipelinePropertiesARM, "vkGetDataGraphPipelinePropertiesARM") + set_proc_address(&GetDataGraphPipelineSessionBindPointRequirementsARM, "vkGetDataGraphPipelineSessionBindPointRequirementsARM") + set_proc_address(&GetDataGraphPipelineSessionMemoryRequirementsARM, "vkGetDataGraphPipelineSessionMemoryRequirementsARM") set_proc_address(&GetDeferredOperationMaxConcurrencyKHR, "vkGetDeferredOperationMaxConcurrencyKHR") set_proc_address(&GetDeferredOperationResultKHR, "vkGetDeferredOperationResultKHR") set_proc_address(&GetDescriptorEXT, "vkGetDescriptorEXT") @@ -1985,7 +2266,10 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetDeviceAccelerationStructureCompatibilityKHR, "vkGetDeviceAccelerationStructureCompatibilityKHR") set_proc_address(&GetDeviceBufferMemoryRequirements, "vkGetDeviceBufferMemoryRequirements") set_proc_address(&GetDeviceBufferMemoryRequirementsKHR, "vkGetDeviceBufferMemoryRequirementsKHR") + set_proc_address(&GetDeviceCombinedImageSamplerIndexNVX, "vkGetDeviceCombinedImageSamplerIndexNVX") + set_proc_address(&GetDeviceFaultDebugInfoKHR, "vkGetDeviceFaultDebugInfoKHR") set_proc_address(&GetDeviceFaultInfoEXT, "vkGetDeviceFaultInfoEXT") + set_proc_address(&GetDeviceFaultReportsKHR, "vkGetDeviceFaultReportsKHR") set_proc_address(&GetDeviceGroupPeerMemoryFeatures, "vkGetDeviceGroupPeerMemoryFeatures") set_proc_address(&GetDeviceGroupPeerMemoryFeaturesKHR, "vkGetDeviceGroupPeerMemoryFeaturesKHR") set_proc_address(&GetDeviceGroupPresentCapabilitiesKHR, "vkGetDeviceGroupPresentCapabilitiesKHR") @@ -2005,6 +2289,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetDeviceQueue, "vkGetDeviceQueue") set_proc_address(&GetDeviceQueue2, "vkGetDeviceQueue2") set_proc_address(&GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI") + set_proc_address(&GetDeviceTensorMemoryRequirementsARM, "vkGetDeviceTensorMemoryRequirementsARM") set_proc_address(&GetDynamicRenderingTilePropertiesQCOM, "vkGetDynamicRenderingTilePropertiesQCOM") set_proc_address(&GetEncodedVideoSessionParametersKHR, "vkGetEncodedVideoSessionParametersKHR") set_proc_address(&GetEventStatus, "vkGetEventStatus") @@ -2016,10 +2301,14 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetFramebufferTilePropertiesQCOM, "vkGetFramebufferTilePropertiesQCOM") set_proc_address(&GetGeneratedCommandsMemoryRequirementsEXT, "vkGetGeneratedCommandsMemoryRequirementsEXT") set_proc_address(&GetGeneratedCommandsMemoryRequirementsNV, "vkGetGeneratedCommandsMemoryRequirementsNV") + set_proc_address(&GetGpaDeviceClockInfoAMD, "vkGetGpaDeviceClockInfoAMD") + set_proc_address(&GetGpaSessionResultsAMD, "vkGetGpaSessionResultsAMD") + set_proc_address(&GetGpaSessionStatusAMD, "vkGetGpaSessionStatusAMD") set_proc_address(&GetImageDrmFormatModifierPropertiesEXT, "vkGetImageDrmFormatModifierPropertiesEXT") set_proc_address(&GetImageMemoryRequirements, "vkGetImageMemoryRequirements") set_proc_address(&GetImageMemoryRequirements2, "vkGetImageMemoryRequirements2") set_proc_address(&GetImageMemoryRequirements2KHR, "vkGetImageMemoryRequirements2KHR") + set_proc_address(&GetImageOpaqueCaptureDataEXT, "vkGetImageOpaqueCaptureDataEXT") set_proc_address(&GetImageOpaqueCaptureDescriptorDataEXT, "vkGetImageOpaqueCaptureDescriptorDataEXT") set_proc_address(&GetImageSparseMemoryRequirements, "vkGetImageSparseMemoryRequirements") set_proc_address(&GetImageSparseMemoryRequirements2, "vkGetImageSparseMemoryRequirements2") @@ -2044,6 +2333,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetMemoryWin32HandlePropertiesKHR, "vkGetMemoryWin32HandlePropertiesKHR") set_proc_address(&GetMicromapBuildSizesEXT, "vkGetMicromapBuildSizesEXT") set_proc_address(&GetPartitionedAccelerationStructuresBuildSizesNV, "vkGetPartitionedAccelerationStructuresBuildSizesNV") + set_proc_address(&GetPastPresentationTimingEXT, "vkGetPastPresentationTimingEXT") set_proc_address(&GetPastPresentationTimingGOOGLE, "vkGetPastPresentationTimingGOOGLE") set_proc_address(&GetPerformanceParameterINTEL, "vkGetPerformanceParameterINTEL") set_proc_address(&GetPipelineBinaryDataKHR, "vkGetPipelineBinaryDataKHR") @@ -2075,11 +2365,18 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetSemaphoreWin32HandleKHR, "vkGetSemaphoreWin32HandleKHR") set_proc_address(&GetShaderBinaryDataEXT, "vkGetShaderBinaryDataEXT") set_proc_address(&GetShaderInfoAMD, "vkGetShaderInfoAMD") + set_proc_address(&GetShaderInstrumentationValuesARM, "vkGetShaderInstrumentationValuesARM") set_proc_address(&GetShaderModuleCreateInfoIdentifierEXT, "vkGetShaderModuleCreateInfoIdentifierEXT") set_proc_address(&GetShaderModuleIdentifierEXT, "vkGetShaderModuleIdentifierEXT") set_proc_address(&GetSwapchainCounterEXT, "vkGetSwapchainCounterEXT") set_proc_address(&GetSwapchainImagesKHR, "vkGetSwapchainImagesKHR") set_proc_address(&GetSwapchainStatusKHR, "vkGetSwapchainStatusKHR") + set_proc_address(&GetSwapchainTimeDomainPropertiesEXT, "vkGetSwapchainTimeDomainPropertiesEXT") + set_proc_address(&GetSwapchainTimingPropertiesEXT, "vkGetSwapchainTimingPropertiesEXT") + set_proc_address(&GetTensorMemoryRequirementsARM, "vkGetTensorMemoryRequirementsARM") + set_proc_address(&GetTensorOpaqueCaptureDataARM, "vkGetTensorOpaqueCaptureDataARM") + set_proc_address(&GetTensorOpaqueCaptureDescriptorDataARM, "vkGetTensorOpaqueCaptureDescriptorDataARM") + set_proc_address(&GetTensorViewOpaqueCaptureDescriptorDataARM, "vkGetTensorViewOpaqueCaptureDescriptorDataARM") set_proc_address(&GetValidationCacheDataEXT, "vkGetValidationCacheDataEXT") set_proc_address(&GetVideoSessionMemoryRequirementsKHR, "vkGetVideoSessionMemoryRequirementsKHR") set_proc_address(&ImportFenceFdKHR, "vkImportFenceFdKHR") @@ -2105,6 +2402,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&QueueSubmit2, "vkQueueSubmit2") set_proc_address(&QueueSubmit2KHR, "vkQueueSubmit2KHR") set_proc_address(&QueueWaitIdle, "vkQueueWaitIdle") + set_proc_address(&RegisterCustomBorderColorEXT, "vkRegisterCustomBorderColorEXT") set_proc_address(&RegisterDeviceEventEXT, "vkRegisterDeviceEventEXT") set_proc_address(&RegisterDisplayEventEXT, "vkRegisterDisplayEventEXT") set_proc_address(&ReleaseCapturedPipelineDataKHR, "vkReleaseCapturedPipelineDataKHR") @@ -2112,23 +2410,27 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&ReleasePerformanceConfigurationINTEL, "vkReleasePerformanceConfigurationINTEL") set_proc_address(&ReleaseProfilingLockKHR, "vkReleaseProfilingLockKHR") set_proc_address(&ReleaseSwapchainImagesEXT, "vkReleaseSwapchainImagesEXT") + set_proc_address(&ReleaseSwapchainImagesKHR, "vkReleaseSwapchainImagesKHR") set_proc_address(&ResetCommandBuffer, "vkResetCommandBuffer") set_proc_address(&ResetCommandPool, "vkResetCommandPool") set_proc_address(&ResetDescriptorPool, "vkResetDescriptorPool") set_proc_address(&ResetEvent, "vkResetEvent") set_proc_address(&ResetFences, "vkResetFences") + set_proc_address(&ResetGpaSessionAMD, "vkResetGpaSessionAMD") set_proc_address(&ResetQueryPool, "vkResetQueryPool") set_proc_address(&ResetQueryPoolEXT, "vkResetQueryPoolEXT") set_proc_address(&SetDebugUtilsObjectNameEXT, "vkSetDebugUtilsObjectNameEXT") set_proc_address(&SetDebugUtilsObjectTagEXT, "vkSetDebugUtilsObjectTagEXT") set_proc_address(&SetDeviceMemoryPriorityEXT, "vkSetDeviceMemoryPriorityEXT") set_proc_address(&SetEvent, "vkSetEvent") + set_proc_address(&SetGpaDeviceClockModeAMD, "vkSetGpaDeviceClockModeAMD") set_proc_address(&SetHdrMetadataEXT, "vkSetHdrMetadataEXT") set_proc_address(&SetLatencyMarkerNV, "vkSetLatencyMarkerNV") set_proc_address(&SetLatencySleepModeNV, "vkSetLatencySleepModeNV") set_proc_address(&SetLocalDimmingAMD, "vkSetLocalDimmingAMD") set_proc_address(&SetPrivateData, "vkSetPrivateData") set_proc_address(&SetPrivateDataEXT, "vkSetPrivateDataEXT") + set_proc_address(&SetSwapchainPresentTimingQueueSizeEXT, "vkSetSwapchainPresentTimingQueueSizeEXT") set_proc_address(&SignalSemaphore, "vkSignalSemaphore") set_proc_address(&SignalSemaphoreKHR, "vkSignalSemaphoreKHR") set_proc_address(&TransitionImageLayout, "vkTransitionImageLayout") @@ -2139,6 +2441,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&UnmapMemory, "vkUnmapMemory") set_proc_address(&UnmapMemory2, "vkUnmapMemory2") set_proc_address(&UnmapMemory2KHR, "vkUnmapMemory2KHR") + set_proc_address(&UnregisterCustomBorderColorEXT, "vkUnregisterCustomBorderColorEXT") set_proc_address(&UpdateDescriptorSetWithTemplate, "vkUpdateDescriptorSetWithTemplate") set_proc_address(&UpdateDescriptorSetWithTemplateKHR, "vkUpdateDescriptorSetWithTemplateKHR") set_proc_address(&UpdateDescriptorSets, "vkUpdateDescriptorSets") @@ -2146,11 +2449,14 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&UpdateIndirectExecutionSetShaderEXT, "vkUpdateIndirectExecutionSetShaderEXT") set_proc_address(&UpdateVideoSessionParametersKHR, "vkUpdateVideoSessionParametersKHR") set_proc_address(&WaitForFences, "vkWaitForFences") + set_proc_address(&WaitForPresent2KHR, "vkWaitForPresent2KHR") set_proc_address(&WaitForPresentKHR, "vkWaitForPresentKHR") set_proc_address(&WaitSemaphores, "vkWaitSemaphores") set_proc_address(&WaitSemaphoresKHR, "vkWaitSemaphoresKHR") set_proc_address(&WriteAccelerationStructuresPropertiesKHR, "vkWriteAccelerationStructuresPropertiesKHR") set_proc_address(&WriteMicromapsPropertiesEXT, "vkWriteMicromapsPropertiesEXT") + set_proc_address(&WriteResourceDescriptorsEXT, "vkWriteResourceDescriptorsEXT") + set_proc_address(&WriteSamplerDescriptorsEXT, "vkWriteSamplerDescriptorsEXT") } @@ -2170,15 +2476,23 @@ Device_VTable :: struct { BindBufferMemory: ProcBindBufferMemory, BindBufferMemory2: ProcBindBufferMemory2, BindBufferMemory2KHR: ProcBindBufferMemory2KHR, + BindDataGraphPipelineSessionMemoryARM: ProcBindDataGraphPipelineSessionMemoryARM, BindImageMemory: ProcBindImageMemory, BindImageMemory2: ProcBindImageMemory2, BindImageMemory2KHR: ProcBindImageMemory2KHR, BindOpticalFlowSessionImageNV: ProcBindOpticalFlowSessionImageNV, + BindTensorMemoryARM: ProcBindTensorMemoryARM, BindVideoSessionMemoryKHR: ProcBindVideoSessionMemoryKHR, BuildAccelerationStructuresKHR: ProcBuildAccelerationStructuresKHR, BuildMicromapsEXT: ProcBuildMicromapsEXT, + ClearShaderInstrumentationMetricsARM: ProcClearShaderInstrumentationMetricsARM, + CmdBeginConditionalRendering2EXT: ProcCmdBeginConditionalRendering2EXT, CmdBeginConditionalRenderingEXT: ProcCmdBeginConditionalRenderingEXT, + CmdBeginCustomResolveEXT: ProcCmdBeginCustomResolveEXT, CmdBeginDebugUtilsLabelEXT: ProcCmdBeginDebugUtilsLabelEXT, + CmdBeginGpaSampleAMD: ProcCmdBeginGpaSampleAMD, + CmdBeginGpaSessionAMD: ProcCmdBeginGpaSessionAMD, + CmdBeginPerTileExecutionQCOM: ProcCmdBeginPerTileExecutionQCOM, CmdBeginQuery: ProcCmdBeginQuery, CmdBeginQueryIndexedEXT: ProcCmdBeginQueryIndexedEXT, CmdBeginRenderPass: ProcCmdBeginRenderPass, @@ -2186,6 +2500,8 @@ Device_VTable :: struct { CmdBeginRenderPass2KHR: ProcCmdBeginRenderPass2KHR, CmdBeginRendering: ProcCmdBeginRendering, CmdBeginRenderingKHR: ProcCmdBeginRenderingKHR, + CmdBeginShaderInstrumentationARM: ProcCmdBeginShaderInstrumentationARM, + CmdBeginTransformFeedback2EXT: ProcCmdBeginTransformFeedback2EXT, CmdBeginTransformFeedbackEXT: ProcCmdBeginTransformFeedbackEXT, CmdBeginVideoCodingKHR: ProcCmdBeginVideoCodingKHR, CmdBindDescriptorBufferEmbeddedSamplers2EXT: ProcCmdBindDescriptorBufferEmbeddedSamplers2EXT, @@ -2197,15 +2513,21 @@ Device_VTable :: struct { CmdBindIndexBuffer: ProcCmdBindIndexBuffer, CmdBindIndexBuffer2: ProcCmdBindIndexBuffer2, CmdBindIndexBuffer2KHR: ProcCmdBindIndexBuffer2KHR, + CmdBindIndexBuffer3KHR: ProcCmdBindIndexBuffer3KHR, CmdBindInvocationMaskHUAWEI: ProcCmdBindInvocationMaskHUAWEI, CmdBindPipeline: ProcCmdBindPipeline, CmdBindPipelineShaderGroupNV: ProcCmdBindPipelineShaderGroupNV, + CmdBindResourceHeapEXT: ProcCmdBindResourceHeapEXT, + CmdBindSamplerHeapEXT: ProcCmdBindSamplerHeapEXT, CmdBindShadersEXT: ProcCmdBindShadersEXT, CmdBindShadingRateImageNV: ProcCmdBindShadingRateImageNV, + CmdBindTileMemoryQCOM: ProcCmdBindTileMemoryQCOM, + CmdBindTransformFeedbackBuffers2EXT: ProcCmdBindTransformFeedbackBuffers2EXT, CmdBindTransformFeedbackBuffersEXT: ProcCmdBindTransformFeedbackBuffersEXT, CmdBindVertexBuffers: ProcCmdBindVertexBuffers, CmdBindVertexBuffers2: ProcCmdBindVertexBuffers2, CmdBindVertexBuffers2EXT: ProcCmdBindVertexBuffers2EXT, + CmdBindVertexBuffers3KHR: ProcCmdBindVertexBuffers3KHR, CmdBlitImage: ProcCmdBlitImage, CmdBlitImage2: ProcCmdBlitImage2, CmdBlitImage2KHR: ProcCmdBlitImage2KHR, @@ -2229,48 +2551,68 @@ Device_VTable :: struct { CmdCopyBufferToImage: ProcCmdCopyBufferToImage, CmdCopyBufferToImage2: ProcCmdCopyBufferToImage2, CmdCopyBufferToImage2KHR: ProcCmdCopyBufferToImage2KHR, + CmdCopyGpaSessionResultsAMD: ProcCmdCopyGpaSessionResultsAMD, CmdCopyImage: ProcCmdCopyImage, CmdCopyImage2: ProcCmdCopyImage2, CmdCopyImage2KHR: ProcCmdCopyImage2KHR, CmdCopyImageToBuffer: ProcCmdCopyImageToBuffer, CmdCopyImageToBuffer2: ProcCmdCopyImageToBuffer2, CmdCopyImageToBuffer2KHR: ProcCmdCopyImageToBuffer2KHR, + CmdCopyImageToMemoryKHR: ProcCmdCopyImageToMemoryKHR, + CmdCopyMemoryIndirectKHR: ProcCmdCopyMemoryIndirectKHR, CmdCopyMemoryIndirectNV: ProcCmdCopyMemoryIndirectNV, + CmdCopyMemoryKHR: ProcCmdCopyMemoryKHR, CmdCopyMemoryToAccelerationStructureKHR: ProcCmdCopyMemoryToAccelerationStructureKHR, + CmdCopyMemoryToImageIndirectKHR: ProcCmdCopyMemoryToImageIndirectKHR, CmdCopyMemoryToImageIndirectNV: ProcCmdCopyMemoryToImageIndirectNV, + CmdCopyMemoryToImageKHR: ProcCmdCopyMemoryToImageKHR, CmdCopyMemoryToMicromapEXT: ProcCmdCopyMemoryToMicromapEXT, CmdCopyMicromapEXT: ProcCmdCopyMicromapEXT, CmdCopyMicromapToMemoryEXT: ProcCmdCopyMicromapToMemoryEXT, CmdCopyQueryPoolResults: ProcCmdCopyQueryPoolResults, + CmdCopyQueryPoolResultsToMemoryKHR: ProcCmdCopyQueryPoolResultsToMemoryKHR, + CmdCopyTensorARM: ProcCmdCopyTensorARM, CmdCuLaunchKernelNVX: ProcCmdCuLaunchKernelNVX, CmdCudaLaunchKernelNV: ProcCmdCudaLaunchKernelNV, CmdDebugMarkerBeginEXT: ProcCmdDebugMarkerBeginEXT, CmdDebugMarkerEndEXT: ProcCmdDebugMarkerEndEXT, CmdDebugMarkerInsertEXT: ProcCmdDebugMarkerInsertEXT, CmdDecodeVideoKHR: ProcCmdDecodeVideoKHR, + CmdDecompressMemoryEXT: ProcCmdDecompressMemoryEXT, + CmdDecompressMemoryIndirectCountEXT: ProcCmdDecompressMemoryIndirectCountEXT, CmdDecompressMemoryIndirectCountNV: ProcCmdDecompressMemoryIndirectCountNV, CmdDecompressMemoryNV: ProcCmdDecompressMemoryNV, CmdDispatch: ProcCmdDispatch, CmdDispatchBase: ProcCmdDispatchBase, CmdDispatchBaseKHR: ProcCmdDispatchBaseKHR, + CmdDispatchDataGraphARM: ProcCmdDispatchDataGraphARM, CmdDispatchGraphAMDX: ProcCmdDispatchGraphAMDX, CmdDispatchGraphIndirectAMDX: ProcCmdDispatchGraphIndirectAMDX, CmdDispatchGraphIndirectCountAMDX: ProcCmdDispatchGraphIndirectCountAMDX, CmdDispatchIndirect: ProcCmdDispatchIndirect, + CmdDispatchIndirect2KHR: ProcCmdDispatchIndirect2KHR, + CmdDispatchTileQCOM: ProcCmdDispatchTileQCOM, CmdDraw: ProcCmdDraw, CmdDrawClusterHUAWEI: ProcCmdDrawClusterHUAWEI, CmdDrawClusterIndirectHUAWEI: ProcCmdDrawClusterIndirectHUAWEI, CmdDrawIndexed: ProcCmdDrawIndexed, CmdDrawIndexedIndirect: ProcCmdDrawIndexedIndirect, + CmdDrawIndexedIndirect2KHR: ProcCmdDrawIndexedIndirect2KHR, CmdDrawIndexedIndirectCount: ProcCmdDrawIndexedIndirectCount, + CmdDrawIndexedIndirectCount2KHR: ProcCmdDrawIndexedIndirectCount2KHR, CmdDrawIndexedIndirectCountAMD: ProcCmdDrawIndexedIndirectCountAMD, CmdDrawIndexedIndirectCountKHR: ProcCmdDrawIndexedIndirectCountKHR, CmdDrawIndirect: ProcCmdDrawIndirect, + CmdDrawIndirect2KHR: ProcCmdDrawIndirect2KHR, + CmdDrawIndirectByteCount2EXT: ProcCmdDrawIndirectByteCount2EXT, CmdDrawIndirectByteCountEXT: ProcCmdDrawIndirectByteCountEXT, CmdDrawIndirectCount: ProcCmdDrawIndirectCount, + CmdDrawIndirectCount2KHR: ProcCmdDrawIndirectCount2KHR, CmdDrawIndirectCountAMD: ProcCmdDrawIndirectCountAMD, CmdDrawIndirectCountKHR: ProcCmdDrawIndirectCountKHR, CmdDrawMeshTasksEXT: ProcCmdDrawMeshTasksEXT, + CmdDrawMeshTasksIndirect2EXT: ProcCmdDrawMeshTasksIndirect2EXT, + CmdDrawMeshTasksIndirectCount2EXT: ProcCmdDrawMeshTasksIndirectCount2EXT, CmdDrawMeshTasksIndirectCountEXT: ProcCmdDrawMeshTasksIndirectCountEXT, CmdDrawMeshTasksIndirectCountNV: ProcCmdDrawMeshTasksIndirectCountNV, CmdDrawMeshTasksIndirectEXT: ProcCmdDrawMeshTasksIndirectEXT, @@ -2281,19 +2623,27 @@ Device_VTable :: struct { CmdEncodeVideoKHR: ProcCmdEncodeVideoKHR, CmdEndConditionalRenderingEXT: ProcCmdEndConditionalRenderingEXT, CmdEndDebugUtilsLabelEXT: ProcCmdEndDebugUtilsLabelEXT, + CmdEndGpaSampleAMD: ProcCmdEndGpaSampleAMD, + CmdEndGpaSessionAMD: ProcCmdEndGpaSessionAMD, + CmdEndPerTileExecutionQCOM: ProcCmdEndPerTileExecutionQCOM, CmdEndQuery: ProcCmdEndQuery, CmdEndQueryIndexedEXT: ProcCmdEndQueryIndexedEXT, CmdEndRenderPass: ProcCmdEndRenderPass, CmdEndRenderPass2: ProcCmdEndRenderPass2, CmdEndRenderPass2KHR: ProcCmdEndRenderPass2KHR, CmdEndRendering: ProcCmdEndRendering, + CmdEndRendering2EXT: ProcCmdEndRendering2EXT, + CmdEndRendering2KHR: ProcCmdEndRendering2KHR, CmdEndRenderingKHR: ProcCmdEndRenderingKHR, + CmdEndShaderInstrumentationARM: ProcCmdEndShaderInstrumentationARM, + CmdEndTransformFeedback2EXT: ProcCmdEndTransformFeedback2EXT, CmdEndTransformFeedbackEXT: ProcCmdEndTransformFeedbackEXT, CmdEndVideoCodingKHR: ProcCmdEndVideoCodingKHR, CmdExecuteCommands: ProcCmdExecuteCommands, CmdExecuteGeneratedCommandsEXT: ProcCmdExecuteGeneratedCommandsEXT, CmdExecuteGeneratedCommandsNV: ProcCmdExecuteGeneratedCommandsNV, CmdFillBuffer: ProcCmdFillBuffer, + CmdFillMemoryKHR: ProcCmdFillMemoryKHR, CmdInitializeGraphScratchMemoryAMDX: ProcCmdInitializeGraphScratchMemoryAMDX, CmdInsertDebugUtilsLabelEXT: ProcCmdInsertDebugUtilsLabelEXT, CmdNextSubpass: ProcCmdNextSubpass, @@ -2308,6 +2658,7 @@ Device_VTable :: struct { CmdPushConstants: ProcCmdPushConstants, CmdPushConstants2: ProcCmdPushConstants2, CmdPushConstants2KHR: ProcCmdPushConstants2KHR, + CmdPushDataEXT: ProcCmdPushDataEXT, CmdPushDescriptorSet: ProcCmdPushDescriptorSet, CmdPushDescriptorSet2: ProcCmdPushDescriptorSet2, CmdPushDescriptorSet2KHR: ProcCmdPushDescriptorSet2KHR, @@ -2332,7 +2683,9 @@ Device_VTable :: struct { CmdSetColorBlendAdvancedEXT: ProcCmdSetColorBlendAdvancedEXT, CmdSetColorBlendEnableEXT: ProcCmdSetColorBlendEnableEXT, CmdSetColorBlendEquationEXT: ProcCmdSetColorBlendEquationEXT, + CmdSetColorWriteEnableEXT: ProcCmdSetColorWriteEnableEXT, CmdSetColorWriteMaskEXT: ProcCmdSetColorWriteMaskEXT, + CmdSetComputeOccupancyPriorityNV: ProcCmdSetComputeOccupancyPriorityNV, CmdSetConservativeRasterizationModeEXT: ProcCmdSetConservativeRasterizationModeEXT, CmdSetCoverageModulationModeNV: ProcCmdSetCoverageModulationModeNV, CmdSetCoverageModulationTableEnableNV: ProcCmdSetCoverageModulationTableEnableNV, @@ -2366,6 +2719,7 @@ Device_VTable :: struct { CmdSetDiscardRectangleEXT: ProcCmdSetDiscardRectangleEXT, CmdSetDiscardRectangleEnableEXT: ProcCmdSetDiscardRectangleEnableEXT, CmdSetDiscardRectangleModeEXT: ProcCmdSetDiscardRectangleModeEXT, + CmdSetDispatchParametersARM: ProcCmdSetDispatchParametersARM, CmdSetEvent: ProcCmdSetEvent, CmdSetEvent2: ProcCmdSetEvent2, CmdSetEvent2KHR: ProcCmdSetEvent2KHR, @@ -2391,6 +2745,7 @@ Device_VTable :: struct { CmdSetPolygonModeEXT: ProcCmdSetPolygonModeEXT, CmdSetPrimitiveRestartEnable: ProcCmdSetPrimitiveRestartEnable, CmdSetPrimitiveRestartEnableEXT: ProcCmdSetPrimitiveRestartEnableEXT, + CmdSetPrimitiveRestartIndexEXT: ProcCmdSetPrimitiveRestartIndexEXT, CmdSetPrimitiveTopology: ProcCmdSetPrimitiveTopology, CmdSetPrimitiveTopologyEXT: ProcCmdSetPrimitiveTopologyEXT, CmdSetProvokingVertexModeEXT: ProcCmdSetProvokingVertexModeEXT, @@ -2433,6 +2788,7 @@ Device_VTable :: struct { CmdTraceRaysKHR: ProcCmdTraceRaysKHR, CmdTraceRaysNV: ProcCmdTraceRaysNV, CmdUpdateBuffer: ProcCmdUpdateBuffer, + CmdUpdateMemoryKHR: ProcCmdUpdateMemoryKHR, CmdUpdatePipelineIndirectBufferNV: ProcCmdUpdatePipelineIndirectBufferNV, CmdWaitEvents: ProcCmdWaitEvents, CmdWaitEvents2: ProcCmdWaitEvents2, @@ -2441,6 +2797,7 @@ Device_VTable :: struct { CmdWriteAccelerationStructuresPropertiesNV: ProcCmdWriteAccelerationStructuresPropertiesNV, CmdWriteBufferMarker2AMD: ProcCmdWriteBufferMarker2AMD, CmdWriteBufferMarkerAMD: ProcCmdWriteBufferMarkerAMD, + CmdWriteMarkerToMemoryAMD: ProcCmdWriteMarkerToMemoryAMD, CmdWriteMicromapsPropertiesEXT: ProcCmdWriteMicromapsPropertiesEXT, CmdWriteTimestamp: ProcCmdWriteTimestamp, CmdWriteTimestamp2: ProcCmdWriteTimestamp2, @@ -2459,6 +2816,7 @@ Device_VTable :: struct { CopyMemoryToMicromapEXT: ProcCopyMemoryToMicromapEXT, CopyMicromapEXT: ProcCopyMicromapEXT, CopyMicromapToMemoryEXT: ProcCopyMicromapToMemoryEXT, + CreateAccelerationStructure2KHR: ProcCreateAccelerationStructure2KHR, CreateAccelerationStructureKHR: ProcCreateAccelerationStructureKHR, CreateAccelerationStructureNV: ProcCreateAccelerationStructureNV, CreateBuffer: ProcCreateBuffer, @@ -2469,6 +2827,8 @@ Device_VTable :: struct { CreateCuModuleNVX: ProcCreateCuModuleNVX, CreateCudaFunctionNV: ProcCreateCudaFunctionNV, CreateCudaModuleNV: ProcCreateCudaModuleNV, + CreateDataGraphPipelineSessionARM: ProcCreateDataGraphPipelineSessionARM, + CreateDataGraphPipelinesARM: ProcCreateDataGraphPipelinesARM, CreateDeferredOperationKHR: ProcCreateDeferredOperationKHR, CreateDescriptorPool: ProcCreateDescriptorPool, CreateDescriptorSetLayout: ProcCreateDescriptorSetLayout, @@ -2476,8 +2836,10 @@ Device_VTable :: struct { CreateDescriptorUpdateTemplateKHR: ProcCreateDescriptorUpdateTemplateKHR, CreateEvent: ProcCreateEvent, CreateExecutionGraphPipelinesAMDX: ProcCreateExecutionGraphPipelinesAMDX, + CreateExternalComputeQueueNV: ProcCreateExternalComputeQueueNV, CreateFence: ProcCreateFence, CreateFramebuffer: ProcCreateFramebuffer, + CreateGpaSessionAMD: ProcCreateGpaSessionAMD, CreateGraphicsPipelines: ProcCreateGraphicsPipelines, CreateImage: ProcCreateImage, CreateImageView: ProcCreateImageView, @@ -2501,10 +2863,13 @@ Device_VTable :: struct { CreateSamplerYcbcrConversion: ProcCreateSamplerYcbcrConversion, CreateSamplerYcbcrConversionKHR: ProcCreateSamplerYcbcrConversionKHR, CreateSemaphore: ProcCreateSemaphore, + CreateShaderInstrumentationARM: ProcCreateShaderInstrumentationARM, CreateShaderModule: ProcCreateShaderModule, CreateShadersEXT: ProcCreateShadersEXT, CreateSharedSwapchainsKHR: ProcCreateSharedSwapchainsKHR, CreateSwapchainKHR: ProcCreateSwapchainKHR, + CreateTensorARM: ProcCreateTensorARM, + CreateTensorViewARM: ProcCreateTensorViewARM, CreateValidationCacheEXT: ProcCreateValidationCacheEXT, CreateVideoSessionKHR: ProcCreateVideoSessionKHR, CreateVideoSessionParametersKHR: ProcCreateVideoSessionParametersKHR, @@ -2520,6 +2885,7 @@ Device_VTable :: struct { DestroyCuModuleNVX: ProcDestroyCuModuleNVX, DestroyCudaFunctionNV: ProcDestroyCudaFunctionNV, DestroyCudaModuleNV: ProcDestroyCudaModuleNV, + DestroyDataGraphPipelineSessionARM: ProcDestroyDataGraphPipelineSessionARM, DestroyDeferredOperationKHR: ProcDestroyDeferredOperationKHR, DestroyDescriptorPool: ProcDestroyDescriptorPool, DestroyDescriptorSetLayout: ProcDestroyDescriptorSetLayout, @@ -2527,8 +2893,10 @@ Device_VTable :: struct { DestroyDescriptorUpdateTemplateKHR: ProcDestroyDescriptorUpdateTemplateKHR, DestroyDevice: ProcDestroyDevice, DestroyEvent: ProcDestroyEvent, + DestroyExternalComputeQueueNV: ProcDestroyExternalComputeQueueNV, DestroyFence: ProcDestroyFence, DestroyFramebuffer: ProcDestroyFramebuffer, + DestroyGpaSessionAMD: ProcDestroyGpaSessionAMD, DestroyImage: ProcDestroyImage, DestroyImageView: ProcDestroyImageView, DestroyIndirectCommandsLayoutEXT: ProcDestroyIndirectCommandsLayoutEXT, @@ -2549,8 +2917,11 @@ Device_VTable :: struct { DestroySamplerYcbcrConversionKHR: ProcDestroySamplerYcbcrConversionKHR, DestroySemaphore: ProcDestroySemaphore, DestroyShaderEXT: ProcDestroyShaderEXT, + DestroyShaderInstrumentationARM: ProcDestroyShaderInstrumentationARM, DestroyShaderModule: ProcDestroyShaderModule, DestroySwapchainKHR: ProcDestroySwapchainKHR, + DestroyTensorARM: ProcDestroyTensorARM, + DestroyTensorViewARM: ProcDestroyTensorViewARM, DestroyValidationCacheEXT: ProcDestroyValidationCacheEXT, DestroyVideoSessionKHR: ProcDestroyVideoSessionKHR, DestroyVideoSessionParametersKHR: ProcDestroyVideoSessionParametersKHR, @@ -2580,6 +2951,10 @@ Device_VTable :: struct { GetCalibratedTimestampsKHR: ProcGetCalibratedTimestampsKHR, GetClusterAccelerationStructureBuildSizesNV: ProcGetClusterAccelerationStructureBuildSizesNV, GetCudaModuleCacheNV: ProcGetCudaModuleCacheNV, + GetDataGraphPipelineAvailablePropertiesARM: ProcGetDataGraphPipelineAvailablePropertiesARM, + GetDataGraphPipelinePropertiesARM: ProcGetDataGraphPipelinePropertiesARM, + GetDataGraphPipelineSessionBindPointRequirementsARM: ProcGetDataGraphPipelineSessionBindPointRequirementsARM, + GetDataGraphPipelineSessionMemoryRequirementsARM: ProcGetDataGraphPipelineSessionMemoryRequirementsARM, GetDeferredOperationMaxConcurrencyKHR: ProcGetDeferredOperationMaxConcurrencyKHR, GetDeferredOperationResultKHR: ProcGetDeferredOperationResultKHR, GetDescriptorEXT: ProcGetDescriptorEXT, @@ -2592,7 +2967,10 @@ Device_VTable :: struct { GetDeviceAccelerationStructureCompatibilityKHR: ProcGetDeviceAccelerationStructureCompatibilityKHR, GetDeviceBufferMemoryRequirements: ProcGetDeviceBufferMemoryRequirements, GetDeviceBufferMemoryRequirementsKHR: ProcGetDeviceBufferMemoryRequirementsKHR, + GetDeviceCombinedImageSamplerIndexNVX: ProcGetDeviceCombinedImageSamplerIndexNVX, + GetDeviceFaultDebugInfoKHR: ProcGetDeviceFaultDebugInfoKHR, GetDeviceFaultInfoEXT: ProcGetDeviceFaultInfoEXT, + GetDeviceFaultReportsKHR: ProcGetDeviceFaultReportsKHR, GetDeviceGroupPeerMemoryFeatures: ProcGetDeviceGroupPeerMemoryFeatures, GetDeviceGroupPeerMemoryFeaturesKHR: ProcGetDeviceGroupPeerMemoryFeaturesKHR, GetDeviceGroupPresentCapabilitiesKHR: ProcGetDeviceGroupPresentCapabilitiesKHR, @@ -2612,6 +2990,7 @@ Device_VTable :: struct { GetDeviceQueue: ProcGetDeviceQueue, GetDeviceQueue2: ProcGetDeviceQueue2, GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI: ProcGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI, + GetDeviceTensorMemoryRequirementsARM: ProcGetDeviceTensorMemoryRequirementsARM, GetDynamicRenderingTilePropertiesQCOM: ProcGetDynamicRenderingTilePropertiesQCOM, GetEncodedVideoSessionParametersKHR: ProcGetEncodedVideoSessionParametersKHR, GetEventStatus: ProcGetEventStatus, @@ -2623,10 +3002,14 @@ Device_VTable :: struct { GetFramebufferTilePropertiesQCOM: ProcGetFramebufferTilePropertiesQCOM, GetGeneratedCommandsMemoryRequirementsEXT: ProcGetGeneratedCommandsMemoryRequirementsEXT, GetGeneratedCommandsMemoryRequirementsNV: ProcGetGeneratedCommandsMemoryRequirementsNV, + GetGpaDeviceClockInfoAMD: ProcGetGpaDeviceClockInfoAMD, + GetGpaSessionResultsAMD: ProcGetGpaSessionResultsAMD, + GetGpaSessionStatusAMD: ProcGetGpaSessionStatusAMD, GetImageDrmFormatModifierPropertiesEXT: ProcGetImageDrmFormatModifierPropertiesEXT, GetImageMemoryRequirements: ProcGetImageMemoryRequirements, GetImageMemoryRequirements2: ProcGetImageMemoryRequirements2, GetImageMemoryRequirements2KHR: ProcGetImageMemoryRequirements2KHR, + GetImageOpaqueCaptureDataEXT: ProcGetImageOpaqueCaptureDataEXT, GetImageOpaqueCaptureDescriptorDataEXT: ProcGetImageOpaqueCaptureDescriptorDataEXT, GetImageSparseMemoryRequirements: ProcGetImageSparseMemoryRequirements, GetImageSparseMemoryRequirements2: ProcGetImageSparseMemoryRequirements2, @@ -2651,6 +3034,7 @@ Device_VTable :: struct { GetMemoryWin32HandlePropertiesKHR: ProcGetMemoryWin32HandlePropertiesKHR, GetMicromapBuildSizesEXT: ProcGetMicromapBuildSizesEXT, GetPartitionedAccelerationStructuresBuildSizesNV: ProcGetPartitionedAccelerationStructuresBuildSizesNV, + GetPastPresentationTimingEXT: ProcGetPastPresentationTimingEXT, GetPastPresentationTimingGOOGLE: ProcGetPastPresentationTimingGOOGLE, GetPerformanceParameterINTEL: ProcGetPerformanceParameterINTEL, GetPipelineBinaryDataKHR: ProcGetPipelineBinaryDataKHR, @@ -2682,11 +3066,18 @@ Device_VTable :: struct { GetSemaphoreWin32HandleKHR: ProcGetSemaphoreWin32HandleKHR, GetShaderBinaryDataEXT: ProcGetShaderBinaryDataEXT, GetShaderInfoAMD: ProcGetShaderInfoAMD, + GetShaderInstrumentationValuesARM: ProcGetShaderInstrumentationValuesARM, GetShaderModuleCreateInfoIdentifierEXT: ProcGetShaderModuleCreateInfoIdentifierEXT, GetShaderModuleIdentifierEXT: ProcGetShaderModuleIdentifierEXT, GetSwapchainCounterEXT: ProcGetSwapchainCounterEXT, GetSwapchainImagesKHR: ProcGetSwapchainImagesKHR, GetSwapchainStatusKHR: ProcGetSwapchainStatusKHR, + GetSwapchainTimeDomainPropertiesEXT: ProcGetSwapchainTimeDomainPropertiesEXT, + GetSwapchainTimingPropertiesEXT: ProcGetSwapchainTimingPropertiesEXT, + GetTensorMemoryRequirementsARM: ProcGetTensorMemoryRequirementsARM, + GetTensorOpaqueCaptureDataARM: ProcGetTensorOpaqueCaptureDataARM, + GetTensorOpaqueCaptureDescriptorDataARM: ProcGetTensorOpaqueCaptureDescriptorDataARM, + GetTensorViewOpaqueCaptureDescriptorDataARM: ProcGetTensorViewOpaqueCaptureDescriptorDataARM, GetValidationCacheDataEXT: ProcGetValidationCacheDataEXT, GetVideoSessionMemoryRequirementsKHR: ProcGetVideoSessionMemoryRequirementsKHR, ImportFenceFdKHR: ProcImportFenceFdKHR, @@ -2712,6 +3103,7 @@ Device_VTable :: struct { QueueSubmit2: ProcQueueSubmit2, QueueSubmit2KHR: ProcQueueSubmit2KHR, QueueWaitIdle: ProcQueueWaitIdle, + RegisterCustomBorderColorEXT: ProcRegisterCustomBorderColorEXT, RegisterDeviceEventEXT: ProcRegisterDeviceEventEXT, RegisterDisplayEventEXT: ProcRegisterDisplayEventEXT, ReleaseCapturedPipelineDataKHR: ProcReleaseCapturedPipelineDataKHR, @@ -2719,23 +3111,27 @@ Device_VTable :: struct { ReleasePerformanceConfigurationINTEL: ProcReleasePerformanceConfigurationINTEL, ReleaseProfilingLockKHR: ProcReleaseProfilingLockKHR, ReleaseSwapchainImagesEXT: ProcReleaseSwapchainImagesEXT, + ReleaseSwapchainImagesKHR: ProcReleaseSwapchainImagesKHR, ResetCommandBuffer: ProcResetCommandBuffer, ResetCommandPool: ProcResetCommandPool, ResetDescriptorPool: ProcResetDescriptorPool, ResetEvent: ProcResetEvent, ResetFences: ProcResetFences, + ResetGpaSessionAMD: ProcResetGpaSessionAMD, ResetQueryPool: ProcResetQueryPool, ResetQueryPoolEXT: ProcResetQueryPoolEXT, SetDebugUtilsObjectNameEXT: ProcSetDebugUtilsObjectNameEXT, SetDebugUtilsObjectTagEXT: ProcSetDebugUtilsObjectTagEXT, SetDeviceMemoryPriorityEXT: ProcSetDeviceMemoryPriorityEXT, SetEvent: ProcSetEvent, + SetGpaDeviceClockModeAMD: ProcSetGpaDeviceClockModeAMD, SetHdrMetadataEXT: ProcSetHdrMetadataEXT, SetLatencyMarkerNV: ProcSetLatencyMarkerNV, SetLatencySleepModeNV: ProcSetLatencySleepModeNV, SetLocalDimmingAMD: ProcSetLocalDimmingAMD, SetPrivateData: ProcSetPrivateData, SetPrivateDataEXT: ProcSetPrivateDataEXT, + SetSwapchainPresentTimingQueueSizeEXT: ProcSetSwapchainPresentTimingQueueSizeEXT, SignalSemaphore: ProcSignalSemaphore, SignalSemaphoreKHR: ProcSignalSemaphoreKHR, TransitionImageLayout: ProcTransitionImageLayout, @@ -2746,6 +3142,7 @@ Device_VTable :: struct { UnmapMemory: ProcUnmapMemory, UnmapMemory2: ProcUnmapMemory2, UnmapMemory2KHR: ProcUnmapMemory2KHR, + UnregisterCustomBorderColorEXT: ProcUnregisterCustomBorderColorEXT, UpdateDescriptorSetWithTemplate: ProcUpdateDescriptorSetWithTemplate, UpdateDescriptorSetWithTemplateKHR: ProcUpdateDescriptorSetWithTemplateKHR, UpdateDescriptorSets: ProcUpdateDescriptorSets, @@ -2753,11 +3150,14 @@ Device_VTable :: struct { UpdateIndirectExecutionSetShaderEXT: ProcUpdateIndirectExecutionSetShaderEXT, UpdateVideoSessionParametersKHR: ProcUpdateVideoSessionParametersKHR, WaitForFences: ProcWaitForFences, + WaitForPresent2KHR: ProcWaitForPresent2KHR, WaitForPresentKHR: ProcWaitForPresentKHR, WaitSemaphores: ProcWaitSemaphores, WaitSemaphoresKHR: ProcWaitSemaphoresKHR, WriteAccelerationStructuresPropertiesKHR: ProcWriteAccelerationStructuresPropertiesKHR, WriteMicromapsPropertiesEXT: ProcWriteMicromapsPropertiesEXT, + WriteResourceDescriptorsEXT: ProcWriteResourceDescriptorsEXT, + WriteSamplerDescriptorsEXT: ProcWriteSamplerDescriptorsEXT, } load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable) { @@ -2775,15 +3175,23 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.BindBufferMemory = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory") vtable.BindBufferMemory2 = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory2") vtable.BindBufferMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory2KHR") + vtable.BindDataGraphPipelineSessionMemoryARM = auto_cast GetDeviceProcAddr(device, "vkBindDataGraphPipelineSessionMemoryARM") vtable.BindImageMemory = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory") vtable.BindImageMemory2 = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory2") vtable.BindImageMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory2KHR") vtable.BindOpticalFlowSessionImageNV = auto_cast GetDeviceProcAddr(device, "vkBindOpticalFlowSessionImageNV") + vtable.BindTensorMemoryARM = auto_cast GetDeviceProcAddr(device, "vkBindTensorMemoryARM") vtable.BindVideoSessionMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkBindVideoSessionMemoryKHR") vtable.BuildAccelerationStructuresKHR = auto_cast GetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR") vtable.BuildMicromapsEXT = auto_cast GetDeviceProcAddr(device, "vkBuildMicromapsEXT") + vtable.ClearShaderInstrumentationMetricsARM = auto_cast GetDeviceProcAddr(device, "vkClearShaderInstrumentationMetricsARM") + vtable.CmdBeginConditionalRendering2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginConditionalRendering2EXT") vtable.CmdBeginConditionalRenderingEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginConditionalRenderingEXT") + vtable.CmdBeginCustomResolveEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginCustomResolveEXT") vtable.CmdBeginDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginDebugUtilsLabelEXT") + vtable.CmdBeginGpaSampleAMD = auto_cast GetDeviceProcAddr(device, "vkCmdBeginGpaSampleAMD") + vtable.CmdBeginGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCmdBeginGpaSessionAMD") + vtable.CmdBeginPerTileExecutionQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdBeginPerTileExecutionQCOM") vtable.CmdBeginQuery = auto_cast GetDeviceProcAddr(device, "vkCmdBeginQuery") vtable.CmdBeginQueryIndexedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginQueryIndexedEXT") vtable.CmdBeginRenderPass = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderPass") @@ -2791,6 +3199,8 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdBeginRenderPass2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderPass2KHR") vtable.CmdBeginRendering = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRendering") vtable.CmdBeginRenderingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderingKHR") + vtable.CmdBeginShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCmdBeginShaderInstrumentationARM") + vtable.CmdBeginTransformFeedback2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginTransformFeedback2EXT") vtable.CmdBeginTransformFeedbackEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginTransformFeedbackEXT") vtable.CmdBeginVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginVideoCodingKHR") vtable.CmdBindDescriptorBufferEmbeddedSamplers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT") @@ -2802,15 +3212,21 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdBindIndexBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer") vtable.CmdBindIndexBuffer2 = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer2") vtable.CmdBindIndexBuffer2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer2KHR") + vtable.CmdBindIndexBuffer3KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer3KHR") vtable.CmdBindInvocationMaskHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdBindInvocationMaskHUAWEI") vtable.CmdBindPipeline = auto_cast GetDeviceProcAddr(device, "vkCmdBindPipeline") vtable.CmdBindPipelineShaderGroupNV = auto_cast GetDeviceProcAddr(device, "vkCmdBindPipelineShaderGroupNV") + vtable.CmdBindResourceHeapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindResourceHeapEXT") + vtable.CmdBindSamplerHeapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindSamplerHeapEXT") vtable.CmdBindShadersEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindShadersEXT") vtable.CmdBindShadingRateImageNV = auto_cast GetDeviceProcAddr(device, "vkCmdBindShadingRateImageNV") + vtable.CmdBindTileMemoryQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdBindTileMemoryQCOM") + vtable.CmdBindTransformFeedbackBuffers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindTransformFeedbackBuffers2EXT") vtable.CmdBindTransformFeedbackBuffersEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindTransformFeedbackBuffersEXT") vtable.CmdBindVertexBuffers = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers") vtable.CmdBindVertexBuffers2 = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers2") vtable.CmdBindVertexBuffers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers2EXT") + vtable.CmdBindVertexBuffers3KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers3KHR") vtable.CmdBlitImage = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage") vtable.CmdBlitImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage2") vtable.CmdBlitImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage2KHR") @@ -2834,48 +3250,68 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdCopyBufferToImage = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage") vtable.CmdCopyBufferToImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage2") vtable.CmdCopyBufferToImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage2KHR") + vtable.CmdCopyGpaSessionResultsAMD = auto_cast GetDeviceProcAddr(device, "vkCmdCopyGpaSessionResultsAMD") vtable.CmdCopyImage = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage") vtable.CmdCopyImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage2") vtable.CmdCopyImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage2KHR") vtable.CmdCopyImageToBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer") vtable.CmdCopyImageToBuffer2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer2") vtable.CmdCopyImageToBuffer2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer2KHR") + vtable.CmdCopyImageToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToMemoryKHR") + vtable.CmdCopyMemoryIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryIndirectKHR") vtable.CmdCopyMemoryIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryIndirectNV") + vtable.CmdCopyMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryKHR") vtable.CmdCopyMemoryToAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToAccelerationStructureKHR") + vtable.CmdCopyMemoryToImageIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageIndirectKHR") vtable.CmdCopyMemoryToImageIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageIndirectNV") + vtable.CmdCopyMemoryToImageKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageKHR") vtable.CmdCopyMemoryToMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToMicromapEXT") vtable.CmdCopyMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMicromapEXT") vtable.CmdCopyMicromapToMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMicromapToMemoryEXT") vtable.CmdCopyQueryPoolResults = auto_cast GetDeviceProcAddr(device, "vkCmdCopyQueryPoolResults") + vtable.CmdCopyQueryPoolResultsToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyQueryPoolResultsToMemoryKHR") + vtable.CmdCopyTensorARM = auto_cast GetDeviceProcAddr(device, "vkCmdCopyTensorARM") vtable.CmdCuLaunchKernelNVX = auto_cast GetDeviceProcAddr(device, "vkCmdCuLaunchKernelNVX") vtable.CmdCudaLaunchKernelNV = auto_cast GetDeviceProcAddr(device, "vkCmdCudaLaunchKernelNV") vtable.CmdDebugMarkerBeginEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerBeginEXT") vtable.CmdDebugMarkerEndEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerEndEXT") vtable.CmdDebugMarkerInsertEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerInsertEXT") vtable.CmdDecodeVideoKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDecodeVideoKHR") + vtable.CmdDecompressMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryEXT") + vtable.CmdDecompressMemoryIndirectCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryIndirectCountEXT") vtable.CmdDecompressMemoryIndirectCountNV = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryIndirectCountNV") vtable.CmdDecompressMemoryNV = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryNV") vtable.CmdDispatch = auto_cast GetDeviceProcAddr(device, "vkCmdDispatch") vtable.CmdDispatchBase = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBase") vtable.CmdDispatchBaseKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBaseKHR") + vtable.CmdDispatchDataGraphARM = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchDataGraphARM") vtable.CmdDispatchGraphAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphAMDX") vtable.CmdDispatchGraphIndirectAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectAMDX") vtable.CmdDispatchGraphIndirectCountAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectCountAMDX") vtable.CmdDispatchIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect") + vtable.CmdDispatchIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect2KHR") + vtable.CmdDispatchTileQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchTileQCOM") vtable.CmdDraw = auto_cast GetDeviceProcAddr(device, "vkCmdDraw") vtable.CmdDrawClusterHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterHUAWEI") vtable.CmdDrawClusterIndirectHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterIndirectHUAWEI") vtable.CmdDrawIndexed = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexed") vtable.CmdDrawIndexedIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirect") + vtable.CmdDrawIndexedIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirect2KHR") vtable.CmdDrawIndexedIndirectCount = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCount") + vtable.CmdDrawIndexedIndirectCount2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCount2KHR") vtable.CmdDrawIndexedIndirectCountAMD = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCountAMD") vtable.CmdDrawIndexedIndirectCountKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCountKHR") vtable.CmdDrawIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirect") + vtable.CmdDrawIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirect2KHR") + vtable.CmdDrawIndirectByteCount2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectByteCount2EXT") vtable.CmdDrawIndirectByteCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectByteCountEXT") vtable.CmdDrawIndirectCount = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCount") + vtable.CmdDrawIndirectCount2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCount2KHR") vtable.CmdDrawIndirectCountAMD = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCountAMD") vtable.CmdDrawIndirectCountKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCountKHR") vtable.CmdDrawMeshTasksEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT") + vtable.CmdDrawMeshTasksIndirect2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirect2EXT") + vtable.CmdDrawMeshTasksIndirectCount2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCount2EXT") vtable.CmdDrawMeshTasksIndirectCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCountEXT") vtable.CmdDrawMeshTasksIndirectCountNV = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCountNV") vtable.CmdDrawMeshTasksIndirectEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectEXT") @@ -2886,19 +3322,27 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdEncodeVideoKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEncodeVideoKHR") vtable.CmdEndConditionalRenderingEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndConditionalRenderingEXT") vtable.CmdEndDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndDebugUtilsLabelEXT") + vtable.CmdEndGpaSampleAMD = auto_cast GetDeviceProcAddr(device, "vkCmdEndGpaSampleAMD") + vtable.CmdEndGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCmdEndGpaSessionAMD") + vtable.CmdEndPerTileExecutionQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdEndPerTileExecutionQCOM") vtable.CmdEndQuery = auto_cast GetDeviceProcAddr(device, "vkCmdEndQuery") vtable.CmdEndQueryIndexedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndQueryIndexedEXT") vtable.CmdEndRenderPass = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass") vtable.CmdEndRenderPass2 = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass2") vtable.CmdEndRenderPass2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass2KHR") vtable.CmdEndRendering = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering") + vtable.CmdEndRendering2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering2EXT") + vtable.CmdEndRendering2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering2KHR") vtable.CmdEndRenderingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderingKHR") + vtable.CmdEndShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCmdEndShaderInstrumentationARM") + vtable.CmdEndTransformFeedback2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndTransformFeedback2EXT") vtable.CmdEndTransformFeedbackEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndTransformFeedbackEXT") vtable.CmdEndVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndVideoCodingKHR") vtable.CmdExecuteCommands = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteCommands") vtable.CmdExecuteGeneratedCommandsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsEXT") vtable.CmdExecuteGeneratedCommandsNV = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsNV") vtable.CmdFillBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdFillBuffer") + vtable.CmdFillMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdFillMemoryKHR") vtable.CmdInitializeGraphScratchMemoryAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdInitializeGraphScratchMemoryAMDX") vtable.CmdInsertDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT") vtable.CmdNextSubpass = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass") @@ -2913,6 +3357,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdPushConstants = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants") vtable.CmdPushConstants2 = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants2") vtable.CmdPushConstants2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants2KHR") + vtable.CmdPushDataEXT = auto_cast GetDeviceProcAddr(device, "vkCmdPushDataEXT") vtable.CmdPushDescriptorSet = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet") vtable.CmdPushDescriptorSet2 = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet2") vtable.CmdPushDescriptorSet2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet2KHR") @@ -2937,7 +3382,9 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdSetColorBlendAdvancedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendAdvancedEXT") vtable.CmdSetColorBlendEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendEnableEXT") vtable.CmdSetColorBlendEquationEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendEquationEXT") + vtable.CmdSetColorWriteEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorWriteEnableEXT") vtable.CmdSetColorWriteMaskEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorWriteMaskEXT") + vtable.CmdSetComputeOccupancyPriorityNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetComputeOccupancyPriorityNV") vtable.CmdSetConservativeRasterizationModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetConservativeRasterizationModeEXT") vtable.CmdSetCoverageModulationModeNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetCoverageModulationModeNV") vtable.CmdSetCoverageModulationTableEnableNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetCoverageModulationTableEnableNV") @@ -2971,6 +3418,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdSetDiscardRectangleEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleEXT") vtable.CmdSetDiscardRectangleEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleEnableEXT") vtable.CmdSetDiscardRectangleModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleModeEXT") + vtable.CmdSetDispatchParametersARM = auto_cast GetDeviceProcAddr(device, "vkCmdSetDispatchParametersARM") vtable.CmdSetEvent = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent") vtable.CmdSetEvent2 = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent2") vtable.CmdSetEvent2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent2KHR") @@ -2996,6 +3444,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdSetPolygonModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPolygonModeEXT") vtable.CmdSetPrimitiveRestartEnable = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnable") vtable.CmdSetPrimitiveRestartEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnableEXT") + vtable.CmdSetPrimitiveRestartIndexEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartIndexEXT") vtable.CmdSetPrimitiveTopology = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveTopology") vtable.CmdSetPrimitiveTopologyEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT") vtable.CmdSetProvokingVertexModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetProvokingVertexModeEXT") @@ -3038,6 +3487,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdTraceRaysKHR = auto_cast GetDeviceProcAddr(device, "vkCmdTraceRaysKHR") vtable.CmdTraceRaysNV = auto_cast GetDeviceProcAddr(device, "vkCmdTraceRaysNV") vtable.CmdUpdateBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdUpdateBuffer") + vtable.CmdUpdateMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdUpdateMemoryKHR") vtable.CmdUpdatePipelineIndirectBufferNV = auto_cast GetDeviceProcAddr(device, "vkCmdUpdatePipelineIndirectBufferNV") vtable.CmdWaitEvents = auto_cast GetDeviceProcAddr(device, "vkCmdWaitEvents") vtable.CmdWaitEvents2 = auto_cast GetDeviceProcAddr(device, "vkCmdWaitEvents2") @@ -3046,6 +3496,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CmdWriteAccelerationStructuresPropertiesNV = auto_cast GetDeviceProcAddr(device, "vkCmdWriteAccelerationStructuresPropertiesNV") vtable.CmdWriteBufferMarker2AMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteBufferMarker2AMD") vtable.CmdWriteBufferMarkerAMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteBufferMarkerAMD") + vtable.CmdWriteMarkerToMemoryAMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteMarkerToMemoryAMD") vtable.CmdWriteMicromapsPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkCmdWriteMicromapsPropertiesEXT") vtable.CmdWriteTimestamp = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp") vtable.CmdWriteTimestamp2 = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2") @@ -3064,6 +3515,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CopyMemoryToMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMemoryToMicromapEXT") vtable.CopyMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMicromapEXT") vtable.CopyMicromapToMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMicromapToMemoryEXT") + vtable.CreateAccelerationStructure2KHR = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructure2KHR") vtable.CreateAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR") vtable.CreateAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructureNV") vtable.CreateBuffer = auto_cast GetDeviceProcAddr(device, "vkCreateBuffer") @@ -3074,6 +3526,8 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CreateCuModuleNVX = auto_cast GetDeviceProcAddr(device, "vkCreateCuModuleNVX") vtable.CreateCudaFunctionNV = auto_cast GetDeviceProcAddr(device, "vkCreateCudaFunctionNV") vtable.CreateCudaModuleNV = auto_cast GetDeviceProcAddr(device, "vkCreateCudaModuleNV") + vtable.CreateDataGraphPipelineSessionARM = auto_cast GetDeviceProcAddr(device, "vkCreateDataGraphPipelineSessionARM") + vtable.CreateDataGraphPipelinesARM = auto_cast GetDeviceProcAddr(device, "vkCreateDataGraphPipelinesARM") vtable.CreateDeferredOperationKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDeferredOperationKHR") vtable.CreateDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorPool") vtable.CreateDescriptorSetLayout = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorSetLayout") @@ -3081,8 +3535,10 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CreateDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplateKHR") vtable.CreateEvent = auto_cast GetDeviceProcAddr(device, "vkCreateEvent") vtable.CreateExecutionGraphPipelinesAMDX = auto_cast GetDeviceProcAddr(device, "vkCreateExecutionGraphPipelinesAMDX") + vtable.CreateExternalComputeQueueNV = auto_cast GetDeviceProcAddr(device, "vkCreateExternalComputeQueueNV") vtable.CreateFence = auto_cast GetDeviceProcAddr(device, "vkCreateFence") vtable.CreateFramebuffer = auto_cast GetDeviceProcAddr(device, "vkCreateFramebuffer") + vtable.CreateGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCreateGpaSessionAMD") vtable.CreateGraphicsPipelines = auto_cast GetDeviceProcAddr(device, "vkCreateGraphicsPipelines") vtable.CreateImage = auto_cast GetDeviceProcAddr(device, "vkCreateImage") vtable.CreateImageView = auto_cast GetDeviceProcAddr(device, "vkCreateImageView") @@ -3106,10 +3562,13 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.CreateSamplerYcbcrConversion = auto_cast GetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversion") vtable.CreateSamplerYcbcrConversionKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversionKHR") vtable.CreateSemaphore = auto_cast GetDeviceProcAddr(device, "vkCreateSemaphore") + vtable.CreateShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCreateShaderInstrumentationARM") vtable.CreateShaderModule = auto_cast GetDeviceProcAddr(device, "vkCreateShaderModule") vtable.CreateShadersEXT = auto_cast GetDeviceProcAddr(device, "vkCreateShadersEXT") vtable.CreateSharedSwapchainsKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSharedSwapchainsKHR") vtable.CreateSwapchainKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSwapchainKHR") + vtable.CreateTensorARM = auto_cast GetDeviceProcAddr(device, "vkCreateTensorARM") + vtable.CreateTensorViewARM = auto_cast GetDeviceProcAddr(device, "vkCreateTensorViewARM") vtable.CreateValidationCacheEXT = auto_cast GetDeviceProcAddr(device, "vkCreateValidationCacheEXT") vtable.CreateVideoSessionKHR = auto_cast GetDeviceProcAddr(device, "vkCreateVideoSessionKHR") vtable.CreateVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkCreateVideoSessionParametersKHR") @@ -3125,6 +3584,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.DestroyCuModuleNVX = auto_cast GetDeviceProcAddr(device, "vkDestroyCuModuleNVX") vtable.DestroyCudaFunctionNV = auto_cast GetDeviceProcAddr(device, "vkDestroyCudaFunctionNV") vtable.DestroyCudaModuleNV = auto_cast GetDeviceProcAddr(device, "vkDestroyCudaModuleNV") + vtable.DestroyDataGraphPipelineSessionARM = auto_cast GetDeviceProcAddr(device, "vkDestroyDataGraphPipelineSessionARM") vtable.DestroyDeferredOperationKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyDeferredOperationKHR") vtable.DestroyDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorPool") vtable.DestroyDescriptorSetLayout = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorSetLayout") @@ -3132,8 +3592,10 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.DestroyDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorUpdateTemplateKHR") vtable.DestroyDevice = auto_cast GetDeviceProcAddr(device, "vkDestroyDevice") vtable.DestroyEvent = auto_cast GetDeviceProcAddr(device, "vkDestroyEvent") + vtable.DestroyExternalComputeQueueNV = auto_cast GetDeviceProcAddr(device, "vkDestroyExternalComputeQueueNV") vtable.DestroyFence = auto_cast GetDeviceProcAddr(device, "vkDestroyFence") vtable.DestroyFramebuffer = auto_cast GetDeviceProcAddr(device, "vkDestroyFramebuffer") + vtable.DestroyGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkDestroyGpaSessionAMD") vtable.DestroyImage = auto_cast GetDeviceProcAddr(device, "vkDestroyImage") vtable.DestroyImageView = auto_cast GetDeviceProcAddr(device, "vkDestroyImageView") vtable.DestroyIndirectCommandsLayoutEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyIndirectCommandsLayoutEXT") @@ -3154,8 +3616,11 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.DestroySamplerYcbcrConversionKHR = auto_cast GetDeviceProcAddr(device, "vkDestroySamplerYcbcrConversionKHR") vtable.DestroySemaphore = auto_cast GetDeviceProcAddr(device, "vkDestroySemaphore") vtable.DestroyShaderEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderEXT") + vtable.DestroyShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderInstrumentationARM") vtable.DestroyShaderModule = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderModule") vtable.DestroySwapchainKHR = auto_cast GetDeviceProcAddr(device, "vkDestroySwapchainKHR") + vtable.DestroyTensorARM = auto_cast GetDeviceProcAddr(device, "vkDestroyTensorARM") + vtable.DestroyTensorViewARM = auto_cast GetDeviceProcAddr(device, "vkDestroyTensorViewARM") vtable.DestroyValidationCacheEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyValidationCacheEXT") vtable.DestroyVideoSessionKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyVideoSessionKHR") vtable.DestroyVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyVideoSessionParametersKHR") @@ -3185,6 +3650,10 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetCalibratedTimestampsKHR = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsKHR") vtable.GetClusterAccelerationStructureBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetClusterAccelerationStructureBuildSizesNV") vtable.GetCudaModuleCacheNV = auto_cast GetDeviceProcAddr(device, "vkGetCudaModuleCacheNV") + vtable.GetDataGraphPipelineAvailablePropertiesARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineAvailablePropertiesARM") + vtable.GetDataGraphPipelinePropertiesARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelinePropertiesARM") + vtable.GetDataGraphPipelineSessionBindPointRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineSessionBindPointRequirementsARM") + vtable.GetDataGraphPipelineSessionMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineSessionMemoryRequirementsARM") vtable.GetDeferredOperationMaxConcurrencyKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationMaxConcurrencyKHR") vtable.GetDeferredOperationResultKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationResultKHR") vtable.GetDescriptorEXT = auto_cast GetDeviceProcAddr(device, "vkGetDescriptorEXT") @@ -3197,7 +3666,10 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetDeviceAccelerationStructureCompatibilityKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceAccelerationStructureCompatibilityKHR") vtable.GetDeviceBufferMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirements") vtable.GetDeviceBufferMemoryRequirementsKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirementsKHR") + vtable.GetDeviceCombinedImageSamplerIndexNVX = auto_cast GetDeviceProcAddr(device, "vkGetDeviceCombinedImageSamplerIndexNVX") + vtable.GetDeviceFaultDebugInfoKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultDebugInfoKHR") vtable.GetDeviceFaultInfoEXT = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultInfoEXT") + vtable.GetDeviceFaultReportsKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultReportsKHR") vtable.GetDeviceGroupPeerMemoryFeatures = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPeerMemoryFeatures") vtable.GetDeviceGroupPeerMemoryFeaturesKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPeerMemoryFeaturesKHR") vtable.GetDeviceGroupPresentCapabilitiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPresentCapabilitiesKHR") @@ -3217,6 +3689,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetDeviceQueue = auto_cast GetDeviceProcAddr(device, "vkGetDeviceQueue") vtable.GetDeviceQueue2 = auto_cast GetDeviceProcAddr(device, "vkGetDeviceQueue2") vtable.GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = auto_cast GetDeviceProcAddr(device, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI") + vtable.GetDeviceTensorMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDeviceTensorMemoryRequirementsARM") vtable.GetDynamicRenderingTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetDynamicRenderingTilePropertiesQCOM") vtable.GetEncodedVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkGetEncodedVideoSessionParametersKHR") vtable.GetEventStatus = auto_cast GetDeviceProcAddr(device, "vkGetEventStatus") @@ -3228,10 +3701,14 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetFramebufferTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetFramebufferTilePropertiesQCOM") vtable.GetGeneratedCommandsMemoryRequirementsEXT = auto_cast GetDeviceProcAddr(device, "vkGetGeneratedCommandsMemoryRequirementsEXT") vtable.GetGeneratedCommandsMemoryRequirementsNV = auto_cast GetDeviceProcAddr(device, "vkGetGeneratedCommandsMemoryRequirementsNV") + vtable.GetGpaDeviceClockInfoAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaDeviceClockInfoAMD") + vtable.GetGpaSessionResultsAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaSessionResultsAMD") + vtable.GetGpaSessionStatusAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaSessionStatusAMD") vtable.GetImageDrmFormatModifierPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageDrmFormatModifierPropertiesEXT") vtable.GetImageMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements") vtable.GetImageMemoryRequirements2 = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements2") vtable.GetImageMemoryRequirements2KHR = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements2KHR") + vtable.GetImageOpaqueCaptureDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageOpaqueCaptureDataEXT") vtable.GetImageOpaqueCaptureDescriptorDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageOpaqueCaptureDescriptorDataEXT") vtable.GetImageSparseMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetImageSparseMemoryRequirements") vtable.GetImageSparseMemoryRequirements2 = auto_cast GetDeviceProcAddr(device, "vkGetImageSparseMemoryRequirements2") @@ -3256,6 +3733,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetMemoryWin32HandlePropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandlePropertiesKHR") vtable.GetMicromapBuildSizesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMicromapBuildSizesEXT") vtable.GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetPartitionedAccelerationStructuresBuildSizesNV") + vtable.GetPastPresentationTimingEXT = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingEXT") vtable.GetPastPresentationTimingGOOGLE = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingGOOGLE") vtable.GetPerformanceParameterINTEL = auto_cast GetDeviceProcAddr(device, "vkGetPerformanceParameterINTEL") vtable.GetPipelineBinaryDataKHR = auto_cast GetDeviceProcAddr(device, "vkGetPipelineBinaryDataKHR") @@ -3287,11 +3765,18 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.GetSemaphoreWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetSemaphoreWin32HandleKHR") vtable.GetShaderBinaryDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderBinaryDataEXT") vtable.GetShaderInfoAMD = auto_cast GetDeviceProcAddr(device, "vkGetShaderInfoAMD") + vtable.GetShaderInstrumentationValuesARM = auto_cast GetDeviceProcAddr(device, "vkGetShaderInstrumentationValuesARM") vtable.GetShaderModuleCreateInfoIdentifierEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderModuleCreateInfoIdentifierEXT") vtable.GetShaderModuleIdentifierEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderModuleIdentifierEXT") vtable.GetSwapchainCounterEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainCounterEXT") vtable.GetSwapchainImagesKHR = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainImagesKHR") vtable.GetSwapchainStatusKHR = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainStatusKHR") + vtable.GetSwapchainTimeDomainPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainTimeDomainPropertiesEXT") + vtable.GetSwapchainTimingPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainTimingPropertiesEXT") + vtable.GetTensorMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorMemoryRequirementsARM") + vtable.GetTensorOpaqueCaptureDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorOpaqueCaptureDataARM") + vtable.GetTensorOpaqueCaptureDescriptorDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorOpaqueCaptureDescriptorDataARM") + vtable.GetTensorViewOpaqueCaptureDescriptorDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorViewOpaqueCaptureDescriptorDataARM") vtable.GetValidationCacheDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetValidationCacheDataEXT") vtable.GetVideoSessionMemoryRequirementsKHR = auto_cast GetDeviceProcAddr(device, "vkGetVideoSessionMemoryRequirementsKHR") vtable.ImportFenceFdKHR = auto_cast GetDeviceProcAddr(device, "vkImportFenceFdKHR") @@ -3317,6 +3802,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.QueueSubmit2 = auto_cast GetDeviceProcAddr(device, "vkQueueSubmit2") vtable.QueueSubmit2KHR = auto_cast GetDeviceProcAddr(device, "vkQueueSubmit2KHR") vtable.QueueWaitIdle = auto_cast GetDeviceProcAddr(device, "vkQueueWaitIdle") + vtable.RegisterCustomBorderColorEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterCustomBorderColorEXT") vtable.RegisterDeviceEventEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterDeviceEventEXT") vtable.RegisterDisplayEventEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterDisplayEventEXT") vtable.ReleaseCapturedPipelineDataKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseCapturedPipelineDataKHR") @@ -3324,23 +3810,27 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.ReleasePerformanceConfigurationINTEL = auto_cast GetDeviceProcAddr(device, "vkReleasePerformanceConfigurationINTEL") vtable.ReleaseProfilingLockKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseProfilingLockKHR") vtable.ReleaseSwapchainImagesEXT = auto_cast GetDeviceProcAddr(device, "vkReleaseSwapchainImagesEXT") + vtable.ReleaseSwapchainImagesKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseSwapchainImagesKHR") vtable.ResetCommandBuffer = auto_cast GetDeviceProcAddr(device, "vkResetCommandBuffer") vtable.ResetCommandPool = auto_cast GetDeviceProcAddr(device, "vkResetCommandPool") vtable.ResetDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkResetDescriptorPool") vtable.ResetEvent = auto_cast GetDeviceProcAddr(device, "vkResetEvent") vtable.ResetFences = auto_cast GetDeviceProcAddr(device, "vkResetFences") + vtable.ResetGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkResetGpaSessionAMD") vtable.ResetQueryPool = auto_cast GetDeviceProcAddr(device, "vkResetQueryPool") vtable.ResetQueryPoolEXT = auto_cast GetDeviceProcAddr(device, "vkResetQueryPoolEXT") vtable.SetDebugUtilsObjectNameEXT = auto_cast GetDeviceProcAddr(device, "vkSetDebugUtilsObjectNameEXT") vtable.SetDebugUtilsObjectTagEXT = auto_cast GetDeviceProcAddr(device, "vkSetDebugUtilsObjectTagEXT") vtable.SetDeviceMemoryPriorityEXT = auto_cast GetDeviceProcAddr(device, "vkSetDeviceMemoryPriorityEXT") vtable.SetEvent = auto_cast GetDeviceProcAddr(device, "vkSetEvent") + vtable.SetGpaDeviceClockModeAMD = auto_cast GetDeviceProcAddr(device, "vkSetGpaDeviceClockModeAMD") vtable.SetHdrMetadataEXT = auto_cast GetDeviceProcAddr(device, "vkSetHdrMetadataEXT") vtable.SetLatencyMarkerNV = auto_cast GetDeviceProcAddr(device, "vkSetLatencyMarkerNV") vtable.SetLatencySleepModeNV = auto_cast GetDeviceProcAddr(device, "vkSetLatencySleepModeNV") vtable.SetLocalDimmingAMD = auto_cast GetDeviceProcAddr(device, "vkSetLocalDimmingAMD") vtable.SetPrivateData = auto_cast GetDeviceProcAddr(device, "vkSetPrivateData") vtable.SetPrivateDataEXT = auto_cast GetDeviceProcAddr(device, "vkSetPrivateDataEXT") + vtable.SetSwapchainPresentTimingQueueSizeEXT = auto_cast GetDeviceProcAddr(device, "vkSetSwapchainPresentTimingQueueSizeEXT") vtable.SignalSemaphore = auto_cast GetDeviceProcAddr(device, "vkSignalSemaphore") vtable.SignalSemaphoreKHR = auto_cast GetDeviceProcAddr(device, "vkSignalSemaphoreKHR") vtable.TransitionImageLayout = auto_cast GetDeviceProcAddr(device, "vkTransitionImageLayout") @@ -3351,6 +3841,7 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.UnmapMemory = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory") vtable.UnmapMemory2 = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory2") vtable.UnmapMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory2KHR") + vtable.UnregisterCustomBorderColorEXT = auto_cast GetDeviceProcAddr(device, "vkUnregisterCustomBorderColorEXT") vtable.UpdateDescriptorSetWithTemplate = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSetWithTemplate") vtable.UpdateDescriptorSetWithTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSetWithTemplateKHR") vtable.UpdateDescriptorSets = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSets") @@ -3358,11 +3849,14 @@ load_proc_addresses_device_vtable :: proc(device: Device, vtable: ^Device_VTable vtable.UpdateIndirectExecutionSetShaderEXT = auto_cast GetDeviceProcAddr(device, "vkUpdateIndirectExecutionSetShaderEXT") vtable.UpdateVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkUpdateVideoSessionParametersKHR") vtable.WaitForFences = auto_cast GetDeviceProcAddr(device, "vkWaitForFences") + vtable.WaitForPresent2KHR = auto_cast GetDeviceProcAddr(device, "vkWaitForPresent2KHR") vtable.WaitForPresentKHR = auto_cast GetDeviceProcAddr(device, "vkWaitForPresentKHR") vtable.WaitSemaphores = auto_cast GetDeviceProcAddr(device, "vkWaitSemaphores") vtable.WaitSemaphoresKHR = auto_cast GetDeviceProcAddr(device, "vkWaitSemaphoresKHR") vtable.WriteAccelerationStructuresPropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkWriteAccelerationStructuresPropertiesKHR") vtable.WriteMicromapsPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkWriteMicromapsPropertiesEXT") + vtable.WriteResourceDescriptorsEXT = auto_cast GetDeviceProcAddr(device, "vkWriteResourceDescriptorsEXT") + vtable.WriteSamplerDescriptorsEXT = auto_cast GetDeviceProcAddr(device, "vkWriteSamplerDescriptorsEXT") } load_proc_addresses_device :: proc(device: Device) { @@ -3380,15 +3874,23 @@ load_proc_addresses_device :: proc(device: Device) { BindBufferMemory = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory") BindBufferMemory2 = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory2") BindBufferMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkBindBufferMemory2KHR") + BindDataGraphPipelineSessionMemoryARM = auto_cast GetDeviceProcAddr(device, "vkBindDataGraphPipelineSessionMemoryARM") BindImageMemory = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory") BindImageMemory2 = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory2") BindImageMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkBindImageMemory2KHR") BindOpticalFlowSessionImageNV = auto_cast GetDeviceProcAddr(device, "vkBindOpticalFlowSessionImageNV") + BindTensorMemoryARM = auto_cast GetDeviceProcAddr(device, "vkBindTensorMemoryARM") BindVideoSessionMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkBindVideoSessionMemoryKHR") BuildAccelerationStructuresKHR = auto_cast GetDeviceProcAddr(device, "vkBuildAccelerationStructuresKHR") BuildMicromapsEXT = auto_cast GetDeviceProcAddr(device, "vkBuildMicromapsEXT") + ClearShaderInstrumentationMetricsARM = auto_cast GetDeviceProcAddr(device, "vkClearShaderInstrumentationMetricsARM") + CmdBeginConditionalRendering2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginConditionalRendering2EXT") CmdBeginConditionalRenderingEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginConditionalRenderingEXT") + CmdBeginCustomResolveEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginCustomResolveEXT") CmdBeginDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginDebugUtilsLabelEXT") + CmdBeginGpaSampleAMD = auto_cast GetDeviceProcAddr(device, "vkCmdBeginGpaSampleAMD") + CmdBeginGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCmdBeginGpaSessionAMD") + CmdBeginPerTileExecutionQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdBeginPerTileExecutionQCOM") CmdBeginQuery = auto_cast GetDeviceProcAddr(device, "vkCmdBeginQuery") CmdBeginQueryIndexedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginQueryIndexedEXT") CmdBeginRenderPass = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderPass") @@ -3396,6 +3898,8 @@ load_proc_addresses_device :: proc(device: Device) { CmdBeginRenderPass2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderPass2KHR") CmdBeginRendering = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRendering") CmdBeginRenderingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginRenderingKHR") + CmdBeginShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCmdBeginShaderInstrumentationARM") + CmdBeginTransformFeedback2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginTransformFeedback2EXT") CmdBeginTransformFeedbackEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBeginTransformFeedbackEXT") CmdBeginVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdBeginVideoCodingKHR") CmdBindDescriptorBufferEmbeddedSamplers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT") @@ -3407,15 +3911,21 @@ load_proc_addresses_device :: proc(device: Device) { CmdBindIndexBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer") CmdBindIndexBuffer2 = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer2") CmdBindIndexBuffer2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer2KHR") + CmdBindIndexBuffer3KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindIndexBuffer3KHR") CmdBindInvocationMaskHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdBindInvocationMaskHUAWEI") CmdBindPipeline = auto_cast GetDeviceProcAddr(device, "vkCmdBindPipeline") CmdBindPipelineShaderGroupNV = auto_cast GetDeviceProcAddr(device, "vkCmdBindPipelineShaderGroupNV") + CmdBindResourceHeapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindResourceHeapEXT") + CmdBindSamplerHeapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindSamplerHeapEXT") CmdBindShadersEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindShadersEXT") CmdBindShadingRateImageNV = auto_cast GetDeviceProcAddr(device, "vkCmdBindShadingRateImageNV") + CmdBindTileMemoryQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdBindTileMemoryQCOM") + CmdBindTransformFeedbackBuffers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindTransformFeedbackBuffers2EXT") CmdBindTransformFeedbackBuffersEXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindTransformFeedbackBuffersEXT") CmdBindVertexBuffers = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers") CmdBindVertexBuffers2 = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers2") CmdBindVertexBuffers2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers2EXT") + CmdBindVertexBuffers3KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBindVertexBuffers3KHR") CmdBlitImage = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage") CmdBlitImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage2") CmdBlitImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdBlitImage2KHR") @@ -3439,48 +3949,68 @@ load_proc_addresses_device :: proc(device: Device) { CmdCopyBufferToImage = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage") CmdCopyBufferToImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage2") CmdCopyBufferToImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyBufferToImage2KHR") + CmdCopyGpaSessionResultsAMD = auto_cast GetDeviceProcAddr(device, "vkCmdCopyGpaSessionResultsAMD") CmdCopyImage = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage") CmdCopyImage2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage2") CmdCopyImage2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImage2KHR") CmdCopyImageToBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer") CmdCopyImageToBuffer2 = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer2") CmdCopyImageToBuffer2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToBuffer2KHR") + CmdCopyImageToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyImageToMemoryKHR") + CmdCopyMemoryIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryIndirectKHR") CmdCopyMemoryIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryIndirectNV") + CmdCopyMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryKHR") CmdCopyMemoryToAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToAccelerationStructureKHR") + CmdCopyMemoryToImageIndirectKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageIndirectKHR") CmdCopyMemoryToImageIndirectNV = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageIndirectNV") + CmdCopyMemoryToImageKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToImageKHR") CmdCopyMemoryToMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMemoryToMicromapEXT") CmdCopyMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMicromapEXT") CmdCopyMicromapToMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCmdCopyMicromapToMemoryEXT") CmdCopyQueryPoolResults = auto_cast GetDeviceProcAddr(device, "vkCmdCopyQueryPoolResults") + CmdCopyQueryPoolResultsToMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdCopyQueryPoolResultsToMemoryKHR") + CmdCopyTensorARM = auto_cast GetDeviceProcAddr(device, "vkCmdCopyTensorARM") CmdCuLaunchKernelNVX = auto_cast GetDeviceProcAddr(device, "vkCmdCuLaunchKernelNVX") CmdCudaLaunchKernelNV = auto_cast GetDeviceProcAddr(device, "vkCmdCudaLaunchKernelNV") CmdDebugMarkerBeginEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerBeginEXT") CmdDebugMarkerEndEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerEndEXT") CmdDebugMarkerInsertEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDebugMarkerInsertEXT") CmdDecodeVideoKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDecodeVideoKHR") + CmdDecompressMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryEXT") + CmdDecompressMemoryIndirectCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryIndirectCountEXT") CmdDecompressMemoryIndirectCountNV = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryIndirectCountNV") CmdDecompressMemoryNV = auto_cast GetDeviceProcAddr(device, "vkCmdDecompressMemoryNV") CmdDispatch = auto_cast GetDeviceProcAddr(device, "vkCmdDispatch") CmdDispatchBase = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBase") CmdDispatchBaseKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchBaseKHR") + CmdDispatchDataGraphARM = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchDataGraphARM") CmdDispatchGraphAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphAMDX") CmdDispatchGraphIndirectAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectAMDX") CmdDispatchGraphIndirectCountAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchGraphIndirectCountAMDX") CmdDispatchIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect") + CmdDispatchIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchIndirect2KHR") + CmdDispatchTileQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdDispatchTileQCOM") CmdDraw = auto_cast GetDeviceProcAddr(device, "vkCmdDraw") CmdDrawClusterHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterHUAWEI") CmdDrawClusterIndirectHUAWEI = auto_cast GetDeviceProcAddr(device, "vkCmdDrawClusterIndirectHUAWEI") CmdDrawIndexed = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexed") CmdDrawIndexedIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirect") + CmdDrawIndexedIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirect2KHR") CmdDrawIndexedIndirectCount = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCount") + CmdDrawIndexedIndirectCount2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCount2KHR") CmdDrawIndexedIndirectCountAMD = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCountAMD") CmdDrawIndexedIndirectCountKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndexedIndirectCountKHR") CmdDrawIndirect = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirect") + CmdDrawIndirect2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirect2KHR") + CmdDrawIndirectByteCount2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectByteCount2EXT") CmdDrawIndirectByteCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectByteCountEXT") CmdDrawIndirectCount = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCount") + CmdDrawIndirectCount2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCount2KHR") CmdDrawIndirectCountAMD = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCountAMD") CmdDrawIndirectCountKHR = auto_cast GetDeviceProcAddr(device, "vkCmdDrawIndirectCountKHR") CmdDrawMeshTasksEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksEXT") + CmdDrawMeshTasksIndirect2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirect2EXT") + CmdDrawMeshTasksIndirectCount2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCount2EXT") CmdDrawMeshTasksIndirectCountEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCountEXT") CmdDrawMeshTasksIndirectCountNV = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectCountNV") CmdDrawMeshTasksIndirectEXT = auto_cast GetDeviceProcAddr(device, "vkCmdDrawMeshTasksIndirectEXT") @@ -3491,19 +4021,27 @@ load_proc_addresses_device :: proc(device: Device) { CmdEncodeVideoKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEncodeVideoKHR") CmdEndConditionalRenderingEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndConditionalRenderingEXT") CmdEndDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndDebugUtilsLabelEXT") + CmdEndGpaSampleAMD = auto_cast GetDeviceProcAddr(device, "vkCmdEndGpaSampleAMD") + CmdEndGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCmdEndGpaSessionAMD") + CmdEndPerTileExecutionQCOM = auto_cast GetDeviceProcAddr(device, "vkCmdEndPerTileExecutionQCOM") CmdEndQuery = auto_cast GetDeviceProcAddr(device, "vkCmdEndQuery") CmdEndQueryIndexedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndQueryIndexedEXT") CmdEndRenderPass = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass") CmdEndRenderPass2 = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass2") CmdEndRenderPass2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderPass2KHR") CmdEndRendering = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering") + CmdEndRendering2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering2EXT") + CmdEndRendering2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRendering2KHR") CmdEndRenderingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndRenderingKHR") + CmdEndShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCmdEndShaderInstrumentationARM") + CmdEndTransformFeedback2EXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndTransformFeedback2EXT") CmdEndTransformFeedbackEXT = auto_cast GetDeviceProcAddr(device, "vkCmdEndTransformFeedbackEXT") CmdEndVideoCodingKHR = auto_cast GetDeviceProcAddr(device, "vkCmdEndVideoCodingKHR") CmdExecuteCommands = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteCommands") CmdExecuteGeneratedCommandsEXT = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsEXT") CmdExecuteGeneratedCommandsNV = auto_cast GetDeviceProcAddr(device, "vkCmdExecuteGeneratedCommandsNV") CmdFillBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdFillBuffer") + CmdFillMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdFillMemoryKHR") CmdInitializeGraphScratchMemoryAMDX = auto_cast GetDeviceProcAddr(device, "vkCmdInitializeGraphScratchMemoryAMDX") CmdInsertDebugUtilsLabelEXT = auto_cast GetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT") CmdNextSubpass = auto_cast GetDeviceProcAddr(device, "vkCmdNextSubpass") @@ -3518,6 +4056,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdPushConstants = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants") CmdPushConstants2 = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants2") CmdPushConstants2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdPushConstants2KHR") + CmdPushDataEXT = auto_cast GetDeviceProcAddr(device, "vkCmdPushDataEXT") CmdPushDescriptorSet = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet") CmdPushDescriptorSet2 = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet2") CmdPushDescriptorSet2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdPushDescriptorSet2KHR") @@ -3542,7 +4081,9 @@ load_proc_addresses_device :: proc(device: Device) { CmdSetColorBlendAdvancedEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendAdvancedEXT") CmdSetColorBlendEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendEnableEXT") CmdSetColorBlendEquationEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorBlendEquationEXT") + CmdSetColorWriteEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorWriteEnableEXT") CmdSetColorWriteMaskEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetColorWriteMaskEXT") + CmdSetComputeOccupancyPriorityNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetComputeOccupancyPriorityNV") CmdSetConservativeRasterizationModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetConservativeRasterizationModeEXT") CmdSetCoverageModulationModeNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetCoverageModulationModeNV") CmdSetCoverageModulationTableEnableNV = auto_cast GetDeviceProcAddr(device, "vkCmdSetCoverageModulationTableEnableNV") @@ -3576,6 +4117,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdSetDiscardRectangleEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleEXT") CmdSetDiscardRectangleEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleEnableEXT") CmdSetDiscardRectangleModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetDiscardRectangleModeEXT") + CmdSetDispatchParametersARM = auto_cast GetDeviceProcAddr(device, "vkCmdSetDispatchParametersARM") CmdSetEvent = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent") CmdSetEvent2 = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent2") CmdSetEvent2KHR = auto_cast GetDeviceProcAddr(device, "vkCmdSetEvent2KHR") @@ -3601,6 +4143,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdSetPolygonModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPolygonModeEXT") CmdSetPrimitiveRestartEnable = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnable") CmdSetPrimitiveRestartEnableEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnableEXT") + CmdSetPrimitiveRestartIndexEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartIndexEXT") CmdSetPrimitiveTopology = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveTopology") CmdSetPrimitiveTopologyEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetPrimitiveTopologyEXT") CmdSetProvokingVertexModeEXT = auto_cast GetDeviceProcAddr(device, "vkCmdSetProvokingVertexModeEXT") @@ -3643,6 +4186,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdTraceRaysKHR = auto_cast GetDeviceProcAddr(device, "vkCmdTraceRaysKHR") CmdTraceRaysNV = auto_cast GetDeviceProcAddr(device, "vkCmdTraceRaysNV") CmdUpdateBuffer = auto_cast GetDeviceProcAddr(device, "vkCmdUpdateBuffer") + CmdUpdateMemoryKHR = auto_cast GetDeviceProcAddr(device, "vkCmdUpdateMemoryKHR") CmdUpdatePipelineIndirectBufferNV = auto_cast GetDeviceProcAddr(device, "vkCmdUpdatePipelineIndirectBufferNV") CmdWaitEvents = auto_cast GetDeviceProcAddr(device, "vkCmdWaitEvents") CmdWaitEvents2 = auto_cast GetDeviceProcAddr(device, "vkCmdWaitEvents2") @@ -3651,6 +4195,7 @@ load_proc_addresses_device :: proc(device: Device) { CmdWriteAccelerationStructuresPropertiesNV = auto_cast GetDeviceProcAddr(device, "vkCmdWriteAccelerationStructuresPropertiesNV") CmdWriteBufferMarker2AMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteBufferMarker2AMD") CmdWriteBufferMarkerAMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteBufferMarkerAMD") + CmdWriteMarkerToMemoryAMD = auto_cast GetDeviceProcAddr(device, "vkCmdWriteMarkerToMemoryAMD") CmdWriteMicromapsPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkCmdWriteMicromapsPropertiesEXT") CmdWriteTimestamp = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp") CmdWriteTimestamp2 = auto_cast GetDeviceProcAddr(device, "vkCmdWriteTimestamp2") @@ -3669,6 +4214,7 @@ load_proc_addresses_device :: proc(device: Device) { CopyMemoryToMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMemoryToMicromapEXT") CopyMicromapEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMicromapEXT") CopyMicromapToMemoryEXT = auto_cast GetDeviceProcAddr(device, "vkCopyMicromapToMemoryEXT") + CreateAccelerationStructure2KHR = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructure2KHR") CreateAccelerationStructureKHR = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR") CreateAccelerationStructureNV = auto_cast GetDeviceProcAddr(device, "vkCreateAccelerationStructureNV") CreateBuffer = auto_cast GetDeviceProcAddr(device, "vkCreateBuffer") @@ -3679,6 +4225,8 @@ load_proc_addresses_device :: proc(device: Device) { CreateCuModuleNVX = auto_cast GetDeviceProcAddr(device, "vkCreateCuModuleNVX") CreateCudaFunctionNV = auto_cast GetDeviceProcAddr(device, "vkCreateCudaFunctionNV") CreateCudaModuleNV = auto_cast GetDeviceProcAddr(device, "vkCreateCudaModuleNV") + CreateDataGraphPipelineSessionARM = auto_cast GetDeviceProcAddr(device, "vkCreateDataGraphPipelineSessionARM") + CreateDataGraphPipelinesARM = auto_cast GetDeviceProcAddr(device, "vkCreateDataGraphPipelinesARM") CreateDeferredOperationKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDeferredOperationKHR") CreateDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorPool") CreateDescriptorSetLayout = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorSetLayout") @@ -3686,8 +4234,10 @@ load_proc_addresses_device :: proc(device: Device) { CreateDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplateKHR") CreateEvent = auto_cast GetDeviceProcAddr(device, "vkCreateEvent") CreateExecutionGraphPipelinesAMDX = auto_cast GetDeviceProcAddr(device, "vkCreateExecutionGraphPipelinesAMDX") + CreateExternalComputeQueueNV = auto_cast GetDeviceProcAddr(device, "vkCreateExternalComputeQueueNV") CreateFence = auto_cast GetDeviceProcAddr(device, "vkCreateFence") CreateFramebuffer = auto_cast GetDeviceProcAddr(device, "vkCreateFramebuffer") + CreateGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkCreateGpaSessionAMD") CreateGraphicsPipelines = auto_cast GetDeviceProcAddr(device, "vkCreateGraphicsPipelines") CreateImage = auto_cast GetDeviceProcAddr(device, "vkCreateImage") CreateImageView = auto_cast GetDeviceProcAddr(device, "vkCreateImageView") @@ -3711,10 +4261,13 @@ load_proc_addresses_device :: proc(device: Device) { CreateSamplerYcbcrConversion = auto_cast GetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversion") CreateSamplerYcbcrConversionKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversionKHR") CreateSemaphore = auto_cast GetDeviceProcAddr(device, "vkCreateSemaphore") + CreateShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkCreateShaderInstrumentationARM") CreateShaderModule = auto_cast GetDeviceProcAddr(device, "vkCreateShaderModule") CreateShadersEXT = auto_cast GetDeviceProcAddr(device, "vkCreateShadersEXT") CreateSharedSwapchainsKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSharedSwapchainsKHR") CreateSwapchainKHR = auto_cast GetDeviceProcAddr(device, "vkCreateSwapchainKHR") + CreateTensorARM = auto_cast GetDeviceProcAddr(device, "vkCreateTensorARM") + CreateTensorViewARM = auto_cast GetDeviceProcAddr(device, "vkCreateTensorViewARM") CreateValidationCacheEXT = auto_cast GetDeviceProcAddr(device, "vkCreateValidationCacheEXT") CreateVideoSessionKHR = auto_cast GetDeviceProcAddr(device, "vkCreateVideoSessionKHR") CreateVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkCreateVideoSessionParametersKHR") @@ -3730,6 +4283,7 @@ load_proc_addresses_device :: proc(device: Device) { DestroyCuModuleNVX = auto_cast GetDeviceProcAddr(device, "vkDestroyCuModuleNVX") DestroyCudaFunctionNV = auto_cast GetDeviceProcAddr(device, "vkDestroyCudaFunctionNV") DestroyCudaModuleNV = auto_cast GetDeviceProcAddr(device, "vkDestroyCudaModuleNV") + DestroyDataGraphPipelineSessionARM = auto_cast GetDeviceProcAddr(device, "vkDestroyDataGraphPipelineSessionARM") DestroyDeferredOperationKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyDeferredOperationKHR") DestroyDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorPool") DestroyDescriptorSetLayout = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorSetLayout") @@ -3737,8 +4291,10 @@ load_proc_addresses_device :: proc(device: Device) { DestroyDescriptorUpdateTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyDescriptorUpdateTemplateKHR") DestroyDevice = auto_cast GetDeviceProcAddr(device, "vkDestroyDevice") DestroyEvent = auto_cast GetDeviceProcAddr(device, "vkDestroyEvent") + DestroyExternalComputeQueueNV = auto_cast GetDeviceProcAddr(device, "vkDestroyExternalComputeQueueNV") DestroyFence = auto_cast GetDeviceProcAddr(device, "vkDestroyFence") DestroyFramebuffer = auto_cast GetDeviceProcAddr(device, "vkDestroyFramebuffer") + DestroyGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkDestroyGpaSessionAMD") DestroyImage = auto_cast GetDeviceProcAddr(device, "vkDestroyImage") DestroyImageView = auto_cast GetDeviceProcAddr(device, "vkDestroyImageView") DestroyIndirectCommandsLayoutEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyIndirectCommandsLayoutEXT") @@ -3759,8 +4315,11 @@ load_proc_addresses_device :: proc(device: Device) { DestroySamplerYcbcrConversionKHR = auto_cast GetDeviceProcAddr(device, "vkDestroySamplerYcbcrConversionKHR") DestroySemaphore = auto_cast GetDeviceProcAddr(device, "vkDestroySemaphore") DestroyShaderEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderEXT") + DestroyShaderInstrumentationARM = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderInstrumentationARM") DestroyShaderModule = auto_cast GetDeviceProcAddr(device, "vkDestroyShaderModule") DestroySwapchainKHR = auto_cast GetDeviceProcAddr(device, "vkDestroySwapchainKHR") + DestroyTensorARM = auto_cast GetDeviceProcAddr(device, "vkDestroyTensorARM") + DestroyTensorViewARM = auto_cast GetDeviceProcAddr(device, "vkDestroyTensorViewARM") DestroyValidationCacheEXT = auto_cast GetDeviceProcAddr(device, "vkDestroyValidationCacheEXT") DestroyVideoSessionKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyVideoSessionKHR") DestroyVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkDestroyVideoSessionParametersKHR") @@ -3790,6 +4349,10 @@ load_proc_addresses_device :: proc(device: Device) { GetCalibratedTimestampsKHR = auto_cast GetDeviceProcAddr(device, "vkGetCalibratedTimestampsKHR") GetClusterAccelerationStructureBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetClusterAccelerationStructureBuildSizesNV") GetCudaModuleCacheNV = auto_cast GetDeviceProcAddr(device, "vkGetCudaModuleCacheNV") + GetDataGraphPipelineAvailablePropertiesARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineAvailablePropertiesARM") + GetDataGraphPipelinePropertiesARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelinePropertiesARM") + GetDataGraphPipelineSessionBindPointRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineSessionBindPointRequirementsARM") + GetDataGraphPipelineSessionMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDataGraphPipelineSessionMemoryRequirementsARM") GetDeferredOperationMaxConcurrencyKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationMaxConcurrencyKHR") GetDeferredOperationResultKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeferredOperationResultKHR") GetDescriptorEXT = auto_cast GetDeviceProcAddr(device, "vkGetDescriptorEXT") @@ -3802,7 +4365,10 @@ load_proc_addresses_device :: proc(device: Device) { GetDeviceAccelerationStructureCompatibilityKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceAccelerationStructureCompatibilityKHR") GetDeviceBufferMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirements") GetDeviceBufferMemoryRequirementsKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirementsKHR") + GetDeviceCombinedImageSamplerIndexNVX = auto_cast GetDeviceProcAddr(device, "vkGetDeviceCombinedImageSamplerIndexNVX") + GetDeviceFaultDebugInfoKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultDebugInfoKHR") GetDeviceFaultInfoEXT = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultInfoEXT") + GetDeviceFaultReportsKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceFaultReportsKHR") GetDeviceGroupPeerMemoryFeatures = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPeerMemoryFeatures") GetDeviceGroupPeerMemoryFeaturesKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPeerMemoryFeaturesKHR") GetDeviceGroupPresentCapabilitiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetDeviceGroupPresentCapabilitiesKHR") @@ -3822,6 +4388,7 @@ load_proc_addresses_device :: proc(device: Device) { GetDeviceQueue = auto_cast GetDeviceProcAddr(device, "vkGetDeviceQueue") GetDeviceQueue2 = auto_cast GetDeviceProcAddr(device, "vkGetDeviceQueue2") GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = auto_cast GetDeviceProcAddr(device, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI") + GetDeviceTensorMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetDeviceTensorMemoryRequirementsARM") GetDynamicRenderingTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetDynamicRenderingTilePropertiesQCOM") GetEncodedVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkGetEncodedVideoSessionParametersKHR") GetEventStatus = auto_cast GetDeviceProcAddr(device, "vkGetEventStatus") @@ -3833,10 +4400,14 @@ load_proc_addresses_device :: proc(device: Device) { GetFramebufferTilePropertiesQCOM = auto_cast GetDeviceProcAddr(device, "vkGetFramebufferTilePropertiesQCOM") GetGeneratedCommandsMemoryRequirementsEXT = auto_cast GetDeviceProcAddr(device, "vkGetGeneratedCommandsMemoryRequirementsEXT") GetGeneratedCommandsMemoryRequirementsNV = auto_cast GetDeviceProcAddr(device, "vkGetGeneratedCommandsMemoryRequirementsNV") + GetGpaDeviceClockInfoAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaDeviceClockInfoAMD") + GetGpaSessionResultsAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaSessionResultsAMD") + GetGpaSessionStatusAMD = auto_cast GetDeviceProcAddr(device, "vkGetGpaSessionStatusAMD") GetImageDrmFormatModifierPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageDrmFormatModifierPropertiesEXT") GetImageMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements") GetImageMemoryRequirements2 = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements2") GetImageMemoryRequirements2KHR = auto_cast GetDeviceProcAddr(device, "vkGetImageMemoryRequirements2KHR") + GetImageOpaqueCaptureDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageOpaqueCaptureDataEXT") GetImageOpaqueCaptureDescriptorDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetImageOpaqueCaptureDescriptorDataEXT") GetImageSparseMemoryRequirements = auto_cast GetDeviceProcAddr(device, "vkGetImageSparseMemoryRequirements") GetImageSparseMemoryRequirements2 = auto_cast GetDeviceProcAddr(device, "vkGetImageSparseMemoryRequirements2") @@ -3861,6 +4432,7 @@ load_proc_addresses_device :: proc(device: Device) { GetMemoryWin32HandlePropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkGetMemoryWin32HandlePropertiesKHR") GetMicromapBuildSizesEXT = auto_cast GetDeviceProcAddr(device, "vkGetMicromapBuildSizesEXT") GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetDeviceProcAddr(device, "vkGetPartitionedAccelerationStructuresBuildSizesNV") + GetPastPresentationTimingEXT = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingEXT") GetPastPresentationTimingGOOGLE = auto_cast GetDeviceProcAddr(device, "vkGetPastPresentationTimingGOOGLE") GetPerformanceParameterINTEL = auto_cast GetDeviceProcAddr(device, "vkGetPerformanceParameterINTEL") GetPipelineBinaryDataKHR = auto_cast GetDeviceProcAddr(device, "vkGetPipelineBinaryDataKHR") @@ -3892,11 +4464,18 @@ load_proc_addresses_device :: proc(device: Device) { GetSemaphoreWin32HandleKHR = auto_cast GetDeviceProcAddr(device, "vkGetSemaphoreWin32HandleKHR") GetShaderBinaryDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderBinaryDataEXT") GetShaderInfoAMD = auto_cast GetDeviceProcAddr(device, "vkGetShaderInfoAMD") + GetShaderInstrumentationValuesARM = auto_cast GetDeviceProcAddr(device, "vkGetShaderInstrumentationValuesARM") GetShaderModuleCreateInfoIdentifierEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderModuleCreateInfoIdentifierEXT") GetShaderModuleIdentifierEXT = auto_cast GetDeviceProcAddr(device, "vkGetShaderModuleIdentifierEXT") GetSwapchainCounterEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainCounterEXT") GetSwapchainImagesKHR = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainImagesKHR") GetSwapchainStatusKHR = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainStatusKHR") + GetSwapchainTimeDomainPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainTimeDomainPropertiesEXT") + GetSwapchainTimingPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkGetSwapchainTimingPropertiesEXT") + GetTensorMemoryRequirementsARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorMemoryRequirementsARM") + GetTensorOpaqueCaptureDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorOpaqueCaptureDataARM") + GetTensorOpaqueCaptureDescriptorDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorOpaqueCaptureDescriptorDataARM") + GetTensorViewOpaqueCaptureDescriptorDataARM = auto_cast GetDeviceProcAddr(device, "vkGetTensorViewOpaqueCaptureDescriptorDataARM") GetValidationCacheDataEXT = auto_cast GetDeviceProcAddr(device, "vkGetValidationCacheDataEXT") GetVideoSessionMemoryRequirementsKHR = auto_cast GetDeviceProcAddr(device, "vkGetVideoSessionMemoryRequirementsKHR") ImportFenceFdKHR = auto_cast GetDeviceProcAddr(device, "vkImportFenceFdKHR") @@ -3922,6 +4501,7 @@ load_proc_addresses_device :: proc(device: Device) { QueueSubmit2 = auto_cast GetDeviceProcAddr(device, "vkQueueSubmit2") QueueSubmit2KHR = auto_cast GetDeviceProcAddr(device, "vkQueueSubmit2KHR") QueueWaitIdle = auto_cast GetDeviceProcAddr(device, "vkQueueWaitIdle") + RegisterCustomBorderColorEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterCustomBorderColorEXT") RegisterDeviceEventEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterDeviceEventEXT") RegisterDisplayEventEXT = auto_cast GetDeviceProcAddr(device, "vkRegisterDisplayEventEXT") ReleaseCapturedPipelineDataKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseCapturedPipelineDataKHR") @@ -3929,23 +4509,27 @@ load_proc_addresses_device :: proc(device: Device) { ReleasePerformanceConfigurationINTEL = auto_cast GetDeviceProcAddr(device, "vkReleasePerformanceConfigurationINTEL") ReleaseProfilingLockKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseProfilingLockKHR") ReleaseSwapchainImagesEXT = auto_cast GetDeviceProcAddr(device, "vkReleaseSwapchainImagesEXT") + ReleaseSwapchainImagesKHR = auto_cast GetDeviceProcAddr(device, "vkReleaseSwapchainImagesKHR") ResetCommandBuffer = auto_cast GetDeviceProcAddr(device, "vkResetCommandBuffer") ResetCommandPool = auto_cast GetDeviceProcAddr(device, "vkResetCommandPool") ResetDescriptorPool = auto_cast GetDeviceProcAddr(device, "vkResetDescriptorPool") ResetEvent = auto_cast GetDeviceProcAddr(device, "vkResetEvent") ResetFences = auto_cast GetDeviceProcAddr(device, "vkResetFences") + ResetGpaSessionAMD = auto_cast GetDeviceProcAddr(device, "vkResetGpaSessionAMD") ResetQueryPool = auto_cast GetDeviceProcAddr(device, "vkResetQueryPool") ResetQueryPoolEXT = auto_cast GetDeviceProcAddr(device, "vkResetQueryPoolEXT") SetDebugUtilsObjectNameEXT = auto_cast GetDeviceProcAddr(device, "vkSetDebugUtilsObjectNameEXT") SetDebugUtilsObjectTagEXT = auto_cast GetDeviceProcAddr(device, "vkSetDebugUtilsObjectTagEXT") SetDeviceMemoryPriorityEXT = auto_cast GetDeviceProcAddr(device, "vkSetDeviceMemoryPriorityEXT") SetEvent = auto_cast GetDeviceProcAddr(device, "vkSetEvent") + SetGpaDeviceClockModeAMD = auto_cast GetDeviceProcAddr(device, "vkSetGpaDeviceClockModeAMD") SetHdrMetadataEXT = auto_cast GetDeviceProcAddr(device, "vkSetHdrMetadataEXT") SetLatencyMarkerNV = auto_cast GetDeviceProcAddr(device, "vkSetLatencyMarkerNV") SetLatencySleepModeNV = auto_cast GetDeviceProcAddr(device, "vkSetLatencySleepModeNV") SetLocalDimmingAMD = auto_cast GetDeviceProcAddr(device, "vkSetLocalDimmingAMD") SetPrivateData = auto_cast GetDeviceProcAddr(device, "vkSetPrivateData") SetPrivateDataEXT = auto_cast GetDeviceProcAddr(device, "vkSetPrivateDataEXT") + SetSwapchainPresentTimingQueueSizeEXT = auto_cast GetDeviceProcAddr(device, "vkSetSwapchainPresentTimingQueueSizeEXT") SignalSemaphore = auto_cast GetDeviceProcAddr(device, "vkSignalSemaphore") SignalSemaphoreKHR = auto_cast GetDeviceProcAddr(device, "vkSignalSemaphoreKHR") TransitionImageLayout = auto_cast GetDeviceProcAddr(device, "vkTransitionImageLayout") @@ -3956,6 +4540,7 @@ load_proc_addresses_device :: proc(device: Device) { UnmapMemory = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory") UnmapMemory2 = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory2") UnmapMemory2KHR = auto_cast GetDeviceProcAddr(device, "vkUnmapMemory2KHR") + UnregisterCustomBorderColorEXT = auto_cast GetDeviceProcAddr(device, "vkUnregisterCustomBorderColorEXT") UpdateDescriptorSetWithTemplate = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSetWithTemplate") UpdateDescriptorSetWithTemplateKHR = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSetWithTemplateKHR") UpdateDescriptorSets = auto_cast GetDeviceProcAddr(device, "vkUpdateDescriptorSets") @@ -3963,111 +4548,122 @@ load_proc_addresses_device :: proc(device: Device) { UpdateIndirectExecutionSetShaderEXT = auto_cast GetDeviceProcAddr(device, "vkUpdateIndirectExecutionSetShaderEXT") UpdateVideoSessionParametersKHR = auto_cast GetDeviceProcAddr(device, "vkUpdateVideoSessionParametersKHR") WaitForFences = auto_cast GetDeviceProcAddr(device, "vkWaitForFences") + WaitForPresent2KHR = auto_cast GetDeviceProcAddr(device, "vkWaitForPresent2KHR") WaitForPresentKHR = auto_cast GetDeviceProcAddr(device, "vkWaitForPresentKHR") WaitSemaphores = auto_cast GetDeviceProcAddr(device, "vkWaitSemaphores") WaitSemaphoresKHR = auto_cast GetDeviceProcAddr(device, "vkWaitSemaphoresKHR") WriteAccelerationStructuresPropertiesKHR = auto_cast GetDeviceProcAddr(device, "vkWriteAccelerationStructuresPropertiesKHR") WriteMicromapsPropertiesEXT = auto_cast GetDeviceProcAddr(device, "vkWriteMicromapsPropertiesEXT") + WriteResourceDescriptorsEXT = auto_cast GetDeviceProcAddr(device, "vkWriteResourceDescriptorsEXT") + WriteSamplerDescriptorsEXT = auto_cast GetDeviceProcAddr(device, "vkWriteSamplerDescriptorsEXT") } load_proc_addresses_instance :: proc(instance: Instance) { - AcquireDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT") - AcquireWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkAcquireWinrtDisplayNV") - CreateDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT") - CreateDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT") - CreateDevice = auto_cast GetInstanceProcAddr(instance, "vkCreateDevice") - CreateDisplayModeKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDisplayModeKHR") - CreateDisplayPlaneSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR") - CreateHeadlessSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT") - CreateIOSSurfaceMVK = auto_cast GetInstanceProcAddr(instance, "vkCreateIOSSurfaceMVK") - CreateMacOSSurfaceMVK = auto_cast GetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK") - CreateMetalSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT") - CreateWaylandSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR") - CreateWin32SurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR") - CreateXcbSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR") - CreateXlibSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR") - DebugReportMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkDebugReportMessageEXT") - DestroyDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT") - DestroyDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT") - DestroyInstance = auto_cast GetInstanceProcAddr(instance, "vkDestroyInstance") - DestroySurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroySurfaceKHR") - EnumerateDeviceExtensionProperties = auto_cast GetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties") - EnumerateDeviceLayerProperties = auto_cast GetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties") - EnumeratePhysicalDeviceGroups = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroups") - EnumeratePhysicalDeviceGroupsKHR = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHR") - EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR") - EnumeratePhysicalDevices = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices") - GetDisplayModeProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR") - GetDisplayModePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR") - GetDisplayPlaneCapabilities2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR") - GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR") - GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR") - GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT") - GetInstanceProcAddrLUNARG = auto_cast GetInstanceProcAddr(instance, "vkGetInstanceProcAddrLUNARG") - GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") - GetPhysicalDeviceCalibrateableTimeDomainsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR") - GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") - GetPhysicalDeviceCooperativeMatrixPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") - GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") - GetPhysicalDeviceCooperativeVectorPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") - GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") - GetPhysicalDeviceDisplayPlanePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") - GetPhysicalDeviceDisplayProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR") - GetPhysicalDeviceDisplayPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR") - GetPhysicalDeviceExternalBufferProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties") - GetPhysicalDeviceExternalBufferPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR") - GetPhysicalDeviceExternalFenceProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties") - GetPhysicalDeviceExternalFencePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR") - GetPhysicalDeviceExternalImageFormatPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV") - GetPhysicalDeviceExternalSemaphoreProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties") - GetPhysicalDeviceExternalSemaphorePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR") - GetPhysicalDeviceFeatures = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures") - GetPhysicalDeviceFeatures2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2") - GetPhysicalDeviceFeatures2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR") - GetPhysicalDeviceFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties") - GetPhysicalDeviceFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2") - GetPhysicalDeviceFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR") - GetPhysicalDeviceFragmentShadingRatesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFragmentShadingRatesKHR") - GetPhysicalDeviceImageFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties") - GetPhysicalDeviceImageFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2") - GetPhysicalDeviceImageFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR") - GetPhysicalDeviceMemoryProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties") - GetPhysicalDeviceMemoryProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2") - GetPhysicalDeviceMemoryProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR") - GetPhysicalDeviceMultisamplePropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT") - GetPhysicalDeviceOpticalFlowImageFormatsNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV") - GetPhysicalDevicePresentRectanglesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDevicePresentRectanglesKHR") - GetPhysicalDeviceProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties") - GetPhysicalDeviceProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2") - GetPhysicalDeviceProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR") - GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR") - GetPhysicalDeviceQueueFamilyProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties") - GetPhysicalDeviceQueueFamilyProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2") - GetPhysicalDeviceQueueFamilyProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR") - GetPhysicalDeviceSparseImageFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties") - GetPhysicalDeviceSparseImageFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2") - GetPhysicalDeviceSparseImageFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR") - GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV") - GetPhysicalDeviceSurfaceCapabilities2EXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT") - GetPhysicalDeviceSurfaceCapabilities2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR") - GetPhysicalDeviceSurfaceCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") - GetPhysicalDeviceSurfaceFormats2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR") - GetPhysicalDeviceSurfaceFormatsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR") - GetPhysicalDeviceSurfacePresentModes2EXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT") - GetPhysicalDeviceSurfacePresentModesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR") - GetPhysicalDeviceSurfaceSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR") - GetPhysicalDeviceToolProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolProperties") - GetPhysicalDeviceToolPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolPropertiesEXT") - GetPhysicalDeviceVideoCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR") - GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR") - GetPhysicalDeviceVideoFormatPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR") - GetPhysicalDeviceWaylandPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") - GetPhysicalDeviceWin32PresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR") - GetPhysicalDeviceXcbPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR") - GetPhysicalDeviceXlibPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR") - GetWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkGetWinrtDisplayNV") - ReleaseDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkReleaseDisplayEXT") - SubmitDebugUtilsMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT") + AcquireDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkAcquireDrmDisplayEXT") + AcquireWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkAcquireWinrtDisplayNV") + CreateDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT") + CreateDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT") + CreateDevice = auto_cast GetInstanceProcAddr(instance, "vkCreateDevice") + CreateDisplayModeKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDisplayModeKHR") + CreateDisplayPlaneSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR") + CreateHeadlessSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT") + CreateIOSSurfaceMVK = auto_cast GetInstanceProcAddr(instance, "vkCreateIOSSurfaceMVK") + CreateMacOSSurfaceMVK = auto_cast GetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK") + CreateMetalSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT") + CreateWaylandSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR") + CreateWin32SurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR") + CreateXcbSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR") + CreateXlibSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR") + DebugReportMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkDebugReportMessageEXT") + DestroyDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT") + DestroyDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT") + DestroyInstance = auto_cast GetInstanceProcAddr(instance, "vkDestroyInstance") + DestroySurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroySurfaceKHR") + EnumerateDeviceExtensionProperties = auto_cast GetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties") + EnumerateDeviceLayerProperties = auto_cast GetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties") + EnumeratePhysicalDeviceGroups = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroups") + EnumeratePhysicalDeviceGroupsKHR = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHR") + EnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceCountersByRegionARM") + EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR") + EnumeratePhysicalDeviceShaderInstrumentationMetricsARM = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceShaderInstrumentationMetricsARM") + EnumeratePhysicalDevices = auto_cast GetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices") + GetDisplayModeProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayModeProperties2KHR") + GetDisplayModePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR") + GetDisplayPlaneCapabilities2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilities2KHR") + GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR") + GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR") + GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT") + GetInstanceProcAddrLUNARG = auto_cast GetInstanceProcAddr(instance, "vkGetInstanceProcAddrLUNARG") + GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") + GetPhysicalDeviceCalibrateableTimeDomainsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR") + GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV") + GetPhysicalDeviceCooperativeMatrixPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR") + GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") + GetPhysicalDeviceCooperativeVectorPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeVectorPropertiesNV") + GetPhysicalDeviceDescriptorSizeEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDescriptorSizeEXT") + GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") + GetPhysicalDeviceDisplayPlanePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR") + GetPhysicalDeviceDisplayProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayProperties2KHR") + GetPhysicalDeviceDisplayPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR") + GetPhysicalDeviceExternalBufferProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferProperties") + GetPhysicalDeviceExternalBufferPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalBufferPropertiesKHR") + GetPhysicalDeviceExternalFenceProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFenceProperties") + GetPhysicalDeviceExternalFencePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR") + GetPhysicalDeviceExternalImageFormatPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV") + GetPhysicalDeviceExternalSemaphoreProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphoreProperties") + GetPhysicalDeviceExternalSemaphorePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR") + GetPhysicalDeviceExternalTensorPropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalTensorPropertiesARM") + GetPhysicalDeviceFeatures = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures") + GetPhysicalDeviceFeatures2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2") + GetPhysicalDeviceFeatures2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR") + GetPhysicalDeviceFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties") + GetPhysicalDeviceFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2") + GetPhysicalDeviceFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR") + GetPhysicalDeviceFragmentShadingRatesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFragmentShadingRatesKHR") + GetPhysicalDeviceImageFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties") + GetPhysicalDeviceImageFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2") + GetPhysicalDeviceImageFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties2KHR") + GetPhysicalDeviceMemoryProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties") + GetPhysicalDeviceMemoryProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2") + GetPhysicalDeviceMemoryProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties2KHR") + GetPhysicalDeviceMultisamplePropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMultisamplePropertiesEXT") + GetPhysicalDeviceOpticalFlowImageFormatsNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceOpticalFlowImageFormatsNV") + GetPhysicalDevicePresentRectanglesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDevicePresentRectanglesKHR") + GetPhysicalDeviceProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties") + GetPhysicalDeviceProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2") + GetPhysicalDeviceProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR") + GetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyDataGraphEngineOperationPropertiesARM") + GetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyDataGraphOpticalFlowImageFormatsARM") + GetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyDataGraphProcessingEnginePropertiesARM") + GetPhysicalDeviceQueueFamilyDataGraphPropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM") + GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR") + GetPhysicalDeviceQueueFamilyProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties") + GetPhysicalDeviceQueueFamilyProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2") + GetPhysicalDeviceQueueFamilyProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR") + GetPhysicalDeviceSparseImageFormatProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties") + GetPhysicalDeviceSparseImageFormatProperties2 = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2") + GetPhysicalDeviceSparseImageFormatProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR") + GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV") + GetPhysicalDeviceSurfaceCapabilities2EXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT") + GetPhysicalDeviceSurfaceCapabilities2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR") + GetPhysicalDeviceSurfaceCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") + GetPhysicalDeviceSurfaceFormats2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormats2KHR") + GetPhysicalDeviceSurfaceFormatsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR") + GetPhysicalDeviceSurfacePresentModes2EXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModes2EXT") + GetPhysicalDeviceSurfacePresentModesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR") + GetPhysicalDeviceSurfaceSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR") + GetPhysicalDeviceToolProperties = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolProperties") + GetPhysicalDeviceToolPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolPropertiesEXT") + GetPhysicalDeviceVideoCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR") + GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR") + GetPhysicalDeviceVideoFormatPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR") + GetPhysicalDeviceWaylandPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") + GetPhysicalDeviceWin32PresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR") + GetPhysicalDeviceXcbPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR") + GetPhysicalDeviceXlibPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR") + GetWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkGetWinrtDisplayNV") + ReleaseDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkReleaseDisplayEXT") + SubmitDebugUtilsMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT") // Device Procedures (may call into dispatch) AcquireFullScreenExclusiveModeEXT = auto_cast GetInstanceProcAddr(instance, "vkAcquireFullScreenExclusiveModeEXT") @@ -4084,15 +4680,23 @@ load_proc_addresses_instance :: proc(instance: Instance) { BindBufferMemory = auto_cast GetInstanceProcAddr(instance, "vkBindBufferMemory") BindBufferMemory2 = auto_cast GetInstanceProcAddr(instance, "vkBindBufferMemory2") BindBufferMemory2KHR = auto_cast GetInstanceProcAddr(instance, "vkBindBufferMemory2KHR") + BindDataGraphPipelineSessionMemoryARM = auto_cast GetInstanceProcAddr(instance, "vkBindDataGraphPipelineSessionMemoryARM") BindImageMemory = auto_cast GetInstanceProcAddr(instance, "vkBindImageMemory") BindImageMemory2 = auto_cast GetInstanceProcAddr(instance, "vkBindImageMemory2") BindImageMemory2KHR = auto_cast GetInstanceProcAddr(instance, "vkBindImageMemory2KHR") BindOpticalFlowSessionImageNV = auto_cast GetInstanceProcAddr(instance, "vkBindOpticalFlowSessionImageNV") + BindTensorMemoryARM = auto_cast GetInstanceProcAddr(instance, "vkBindTensorMemoryARM") BindVideoSessionMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkBindVideoSessionMemoryKHR") BuildAccelerationStructuresKHR = auto_cast GetInstanceProcAddr(instance, "vkBuildAccelerationStructuresKHR") BuildMicromapsEXT = auto_cast GetInstanceProcAddr(instance, "vkBuildMicromapsEXT") + ClearShaderInstrumentationMetricsARM = auto_cast GetInstanceProcAddr(instance, "vkClearShaderInstrumentationMetricsARM") + CmdBeginConditionalRendering2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginConditionalRendering2EXT") CmdBeginConditionalRenderingEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginConditionalRenderingEXT") + CmdBeginCustomResolveEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginCustomResolveEXT") CmdBeginDebugUtilsLabelEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT") + CmdBeginGpaSampleAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginGpaSampleAMD") + CmdBeginGpaSessionAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginGpaSessionAMD") + CmdBeginPerTileExecutionQCOM = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginPerTileExecutionQCOM") CmdBeginQuery = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginQuery") CmdBeginQueryIndexedEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginQueryIndexedEXT") CmdBeginRenderPass = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginRenderPass") @@ -4100,6 +4704,8 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdBeginRenderPass2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginRenderPass2KHR") CmdBeginRendering = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginRendering") CmdBeginRenderingKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginRenderingKHR") + CmdBeginShaderInstrumentationARM = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginShaderInstrumentationARM") + CmdBeginTransformFeedback2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginTransformFeedback2EXT") CmdBeginTransformFeedbackEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginTransformFeedbackEXT") CmdBeginVideoCodingKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBeginVideoCodingKHR") CmdBindDescriptorBufferEmbeddedSamplers2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindDescriptorBufferEmbeddedSamplers2EXT") @@ -4111,15 +4717,21 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdBindIndexBuffer = auto_cast GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer") CmdBindIndexBuffer2 = auto_cast GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer2") CmdBindIndexBuffer2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer2KHR") + CmdBindIndexBuffer3KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer3KHR") CmdBindInvocationMaskHUAWEI = auto_cast GetInstanceProcAddr(instance, "vkCmdBindInvocationMaskHUAWEI") CmdBindPipeline = auto_cast GetInstanceProcAddr(instance, "vkCmdBindPipeline") CmdBindPipelineShaderGroupNV = auto_cast GetInstanceProcAddr(instance, "vkCmdBindPipelineShaderGroupNV") + CmdBindResourceHeapEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindResourceHeapEXT") + CmdBindSamplerHeapEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindSamplerHeapEXT") CmdBindShadersEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindShadersEXT") CmdBindShadingRateImageNV = auto_cast GetInstanceProcAddr(instance, "vkCmdBindShadingRateImageNV") + CmdBindTileMemoryQCOM = auto_cast GetInstanceProcAddr(instance, "vkCmdBindTileMemoryQCOM") + CmdBindTransformFeedbackBuffers2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindTransformFeedbackBuffers2EXT") CmdBindTransformFeedbackBuffersEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindTransformFeedbackBuffersEXT") CmdBindVertexBuffers = auto_cast GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers") CmdBindVertexBuffers2 = auto_cast GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers2") CmdBindVertexBuffers2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers2EXT") + CmdBindVertexBuffers3KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers3KHR") CmdBlitImage = auto_cast GetInstanceProcAddr(instance, "vkCmdBlitImage") CmdBlitImage2 = auto_cast GetInstanceProcAddr(instance, "vkCmdBlitImage2") CmdBlitImage2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdBlitImage2KHR") @@ -4143,48 +4755,68 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdCopyBufferToImage = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage") CmdCopyBufferToImage2 = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage2") CmdCopyBufferToImage2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage2KHR") + CmdCopyGpaSessionResultsAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyGpaSessionResultsAMD") CmdCopyImage = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImage") CmdCopyImage2 = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImage2") CmdCopyImage2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImage2KHR") CmdCopyImageToBuffer = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer") CmdCopyImageToBuffer2 = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer2") CmdCopyImageToBuffer2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer2KHR") + CmdCopyImageToMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyImageToMemoryKHR") + CmdCopyMemoryIndirectKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryIndirectKHR") CmdCopyMemoryIndirectNV = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryIndirectNV") + CmdCopyMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryKHR") CmdCopyMemoryToAccelerationStructureKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryToAccelerationStructureKHR") + CmdCopyMemoryToImageIndirectKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryToImageIndirectKHR") CmdCopyMemoryToImageIndirectNV = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryToImageIndirectNV") + CmdCopyMemoryToImageKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryToImageKHR") CmdCopyMemoryToMicromapEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMemoryToMicromapEXT") CmdCopyMicromapEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMicromapEXT") CmdCopyMicromapToMemoryEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyMicromapToMemoryEXT") CmdCopyQueryPoolResults = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults") + CmdCopyQueryPoolResultsToMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResultsToMemoryKHR") + CmdCopyTensorARM = auto_cast GetInstanceProcAddr(instance, "vkCmdCopyTensorARM") CmdCuLaunchKernelNVX = auto_cast GetInstanceProcAddr(instance, "vkCmdCuLaunchKernelNVX") CmdCudaLaunchKernelNV = auto_cast GetInstanceProcAddr(instance, "vkCmdCudaLaunchKernelNV") CmdDebugMarkerBeginEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDebugMarkerBeginEXT") CmdDebugMarkerEndEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDebugMarkerEndEXT") CmdDebugMarkerInsertEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDebugMarkerInsertEXT") CmdDecodeVideoKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDecodeVideoKHR") + CmdDecompressMemoryEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDecompressMemoryEXT") + CmdDecompressMemoryIndirectCountEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDecompressMemoryIndirectCountEXT") CmdDecompressMemoryIndirectCountNV = auto_cast GetInstanceProcAddr(instance, "vkCmdDecompressMemoryIndirectCountNV") CmdDecompressMemoryNV = auto_cast GetInstanceProcAddr(instance, "vkCmdDecompressMemoryNV") CmdDispatch = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatch") CmdDispatchBase = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchBase") CmdDispatchBaseKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchBaseKHR") + CmdDispatchDataGraphARM = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchDataGraphARM") CmdDispatchGraphAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphAMDX") CmdDispatchGraphIndirectAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphIndirectAMDX") CmdDispatchGraphIndirectCountAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchGraphIndirectCountAMDX") CmdDispatchIndirect = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchIndirect") + CmdDispatchIndirect2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchIndirect2KHR") + CmdDispatchTileQCOM = auto_cast GetInstanceProcAddr(instance, "vkCmdDispatchTileQCOM") CmdDraw = auto_cast GetInstanceProcAddr(instance, "vkCmdDraw") CmdDrawClusterHUAWEI = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawClusterHUAWEI") CmdDrawClusterIndirectHUAWEI = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawClusterIndirectHUAWEI") CmdDrawIndexed = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexed") CmdDrawIndexedIndirect = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect") + CmdDrawIndexedIndirect2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect2KHR") CmdDrawIndexedIndirectCount = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCount") + CmdDrawIndexedIndirectCount2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCount2KHR") CmdDrawIndexedIndirectCountAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCountAMD") CmdDrawIndexedIndirectCountKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirectCountKHR") CmdDrawIndirect = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirect") + CmdDrawIndirect2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirect2KHR") + CmdDrawIndirectByteCount2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectByteCount2EXT") CmdDrawIndirectByteCountEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectByteCountEXT") CmdDrawIndirectCount = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectCount") + CmdDrawIndirectCount2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectCount2KHR") CmdDrawIndirectCountAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectCountAMD") CmdDrawIndirectCountKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawIndirectCountKHR") CmdDrawMeshTasksEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksEXT") + CmdDrawMeshTasksIndirect2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirect2EXT") + CmdDrawMeshTasksIndirectCount2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCount2EXT") CmdDrawMeshTasksIndirectCountEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountEXT") CmdDrawMeshTasksIndirectCountNV = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectCountNV") CmdDrawMeshTasksIndirectEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdDrawMeshTasksIndirectEXT") @@ -4195,19 +4827,27 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdEncodeVideoKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdEncodeVideoKHR") CmdEndConditionalRenderingEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndConditionalRenderingEXT") CmdEndDebugUtilsLabelEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT") + CmdEndGpaSampleAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdEndGpaSampleAMD") + CmdEndGpaSessionAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdEndGpaSessionAMD") + CmdEndPerTileExecutionQCOM = auto_cast GetInstanceProcAddr(instance, "vkCmdEndPerTileExecutionQCOM") CmdEndQuery = auto_cast GetInstanceProcAddr(instance, "vkCmdEndQuery") CmdEndQueryIndexedEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndQueryIndexedEXT") CmdEndRenderPass = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRenderPass") CmdEndRenderPass2 = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRenderPass2") CmdEndRenderPass2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRenderPass2KHR") CmdEndRendering = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRendering") + CmdEndRendering2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRendering2EXT") + CmdEndRendering2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRendering2KHR") CmdEndRenderingKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdEndRenderingKHR") + CmdEndShaderInstrumentationARM = auto_cast GetInstanceProcAddr(instance, "vkCmdEndShaderInstrumentationARM") + CmdEndTransformFeedback2EXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndTransformFeedback2EXT") CmdEndTransformFeedbackEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdEndTransformFeedbackEXT") CmdEndVideoCodingKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdEndVideoCodingKHR") CmdExecuteCommands = auto_cast GetInstanceProcAddr(instance, "vkCmdExecuteCommands") CmdExecuteGeneratedCommandsEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsEXT") CmdExecuteGeneratedCommandsNV = auto_cast GetInstanceProcAddr(instance, "vkCmdExecuteGeneratedCommandsNV") CmdFillBuffer = auto_cast GetInstanceProcAddr(instance, "vkCmdFillBuffer") + CmdFillMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdFillMemoryKHR") CmdInitializeGraphScratchMemoryAMDX = auto_cast GetInstanceProcAddr(instance, "vkCmdInitializeGraphScratchMemoryAMDX") CmdInsertDebugUtilsLabelEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT") CmdNextSubpass = auto_cast GetInstanceProcAddr(instance, "vkCmdNextSubpass") @@ -4222,6 +4862,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdPushConstants = auto_cast GetInstanceProcAddr(instance, "vkCmdPushConstants") CmdPushConstants2 = auto_cast GetInstanceProcAddr(instance, "vkCmdPushConstants2") CmdPushConstants2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdPushConstants2KHR") + CmdPushDataEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdPushDataEXT") CmdPushDescriptorSet = auto_cast GetInstanceProcAddr(instance, "vkCmdPushDescriptorSet") CmdPushDescriptorSet2 = auto_cast GetInstanceProcAddr(instance, "vkCmdPushDescriptorSet2") CmdPushDescriptorSet2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdPushDescriptorSet2KHR") @@ -4246,7 +4887,9 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdSetColorBlendAdvancedEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetColorBlendAdvancedEXT") CmdSetColorBlendEnableEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetColorBlendEnableEXT") CmdSetColorBlendEquationEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetColorBlendEquationEXT") + CmdSetColorWriteEnableEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetColorWriteEnableEXT") CmdSetColorWriteMaskEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetColorWriteMaskEXT") + CmdSetComputeOccupancyPriorityNV = auto_cast GetInstanceProcAddr(instance, "vkCmdSetComputeOccupancyPriorityNV") CmdSetConservativeRasterizationModeEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetConservativeRasterizationModeEXT") CmdSetCoverageModulationModeNV = auto_cast GetInstanceProcAddr(instance, "vkCmdSetCoverageModulationModeNV") CmdSetCoverageModulationTableEnableNV = auto_cast GetInstanceProcAddr(instance, "vkCmdSetCoverageModulationTableEnableNV") @@ -4280,6 +4923,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdSetDiscardRectangleEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEXT") CmdSetDiscardRectangleEnableEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleEnableEXT") CmdSetDiscardRectangleModeEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetDiscardRectangleModeEXT") + CmdSetDispatchParametersARM = auto_cast GetInstanceProcAddr(instance, "vkCmdSetDispatchParametersARM") CmdSetEvent = auto_cast GetInstanceProcAddr(instance, "vkCmdSetEvent") CmdSetEvent2 = auto_cast GetInstanceProcAddr(instance, "vkCmdSetEvent2") CmdSetEvent2KHR = auto_cast GetInstanceProcAddr(instance, "vkCmdSetEvent2KHR") @@ -4305,6 +4949,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdSetPolygonModeEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPolygonModeEXT") CmdSetPrimitiveRestartEnable = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPrimitiveRestartEnable") CmdSetPrimitiveRestartEnableEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPrimitiveRestartEnableEXT") + CmdSetPrimitiveRestartIndexEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPrimitiveRestartIndexEXT") CmdSetPrimitiveTopology = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPrimitiveTopology") CmdSetPrimitiveTopologyEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetPrimitiveTopologyEXT") CmdSetProvokingVertexModeEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdSetProvokingVertexModeEXT") @@ -4347,6 +4992,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdTraceRaysKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdTraceRaysKHR") CmdTraceRaysNV = auto_cast GetInstanceProcAddr(instance, "vkCmdTraceRaysNV") CmdUpdateBuffer = auto_cast GetInstanceProcAddr(instance, "vkCmdUpdateBuffer") + CmdUpdateMemoryKHR = auto_cast GetInstanceProcAddr(instance, "vkCmdUpdateMemoryKHR") CmdUpdatePipelineIndirectBufferNV = auto_cast GetInstanceProcAddr(instance, "vkCmdUpdatePipelineIndirectBufferNV") CmdWaitEvents = auto_cast GetInstanceProcAddr(instance, "vkCmdWaitEvents") CmdWaitEvents2 = auto_cast GetInstanceProcAddr(instance, "vkCmdWaitEvents2") @@ -4355,6 +5001,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CmdWriteAccelerationStructuresPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteAccelerationStructuresPropertiesNV") CmdWriteBufferMarker2AMD = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteBufferMarker2AMD") CmdWriteBufferMarkerAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteBufferMarkerAMD") + CmdWriteMarkerToMemoryAMD = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteMarkerToMemoryAMD") CmdWriteMicromapsPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteMicromapsPropertiesEXT") CmdWriteTimestamp = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteTimestamp") CmdWriteTimestamp2 = auto_cast GetInstanceProcAddr(instance, "vkCmdWriteTimestamp2") @@ -4373,6 +5020,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { CopyMemoryToMicromapEXT = auto_cast GetInstanceProcAddr(instance, "vkCopyMemoryToMicromapEXT") CopyMicromapEXT = auto_cast GetInstanceProcAddr(instance, "vkCopyMicromapEXT") CopyMicromapToMemoryEXT = auto_cast GetInstanceProcAddr(instance, "vkCopyMicromapToMemoryEXT") + CreateAccelerationStructure2KHR = auto_cast GetInstanceProcAddr(instance, "vkCreateAccelerationStructure2KHR") CreateAccelerationStructureKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateAccelerationStructureKHR") CreateAccelerationStructureNV = auto_cast GetInstanceProcAddr(instance, "vkCreateAccelerationStructureNV") CreateBuffer = auto_cast GetInstanceProcAddr(instance, "vkCreateBuffer") @@ -4383,6 +5031,8 @@ load_proc_addresses_instance :: proc(instance: Instance) { CreateCuModuleNVX = auto_cast GetInstanceProcAddr(instance, "vkCreateCuModuleNVX") CreateCudaFunctionNV = auto_cast GetInstanceProcAddr(instance, "vkCreateCudaFunctionNV") CreateCudaModuleNV = auto_cast GetInstanceProcAddr(instance, "vkCreateCudaModuleNV") + CreateDataGraphPipelineSessionARM = auto_cast GetInstanceProcAddr(instance, "vkCreateDataGraphPipelineSessionARM") + CreateDataGraphPipelinesARM = auto_cast GetInstanceProcAddr(instance, "vkCreateDataGraphPipelinesARM") CreateDeferredOperationKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDeferredOperationKHR") CreateDescriptorPool = auto_cast GetInstanceProcAddr(instance, "vkCreateDescriptorPool") CreateDescriptorSetLayout = auto_cast GetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout") @@ -4390,8 +5040,10 @@ load_proc_addresses_instance :: proc(instance: Instance) { CreateDescriptorUpdateTemplateKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateDescriptorUpdateTemplateKHR") CreateEvent = auto_cast GetInstanceProcAddr(instance, "vkCreateEvent") CreateExecutionGraphPipelinesAMDX = auto_cast GetInstanceProcAddr(instance, "vkCreateExecutionGraphPipelinesAMDX") + CreateExternalComputeQueueNV = auto_cast GetInstanceProcAddr(instance, "vkCreateExternalComputeQueueNV") CreateFence = auto_cast GetInstanceProcAddr(instance, "vkCreateFence") CreateFramebuffer = auto_cast GetInstanceProcAddr(instance, "vkCreateFramebuffer") + CreateGpaSessionAMD = auto_cast GetInstanceProcAddr(instance, "vkCreateGpaSessionAMD") CreateGraphicsPipelines = auto_cast GetInstanceProcAddr(instance, "vkCreateGraphicsPipelines") CreateImage = auto_cast GetInstanceProcAddr(instance, "vkCreateImage") CreateImageView = auto_cast GetInstanceProcAddr(instance, "vkCreateImageView") @@ -4415,10 +5067,13 @@ load_proc_addresses_instance :: proc(instance: Instance) { CreateSamplerYcbcrConversion = auto_cast GetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversion") CreateSamplerYcbcrConversionKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversionKHR") CreateSemaphore = auto_cast GetInstanceProcAddr(instance, "vkCreateSemaphore") + CreateShaderInstrumentationARM = auto_cast GetInstanceProcAddr(instance, "vkCreateShaderInstrumentationARM") CreateShaderModule = auto_cast GetInstanceProcAddr(instance, "vkCreateShaderModule") CreateShadersEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateShadersEXT") CreateSharedSwapchainsKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR") CreateSwapchainKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateSwapchainKHR") + CreateTensorARM = auto_cast GetInstanceProcAddr(instance, "vkCreateTensorARM") + CreateTensorViewARM = auto_cast GetInstanceProcAddr(instance, "vkCreateTensorViewARM") CreateValidationCacheEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateValidationCacheEXT") CreateVideoSessionKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateVideoSessionKHR") CreateVideoSessionParametersKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateVideoSessionParametersKHR") @@ -4434,6 +5089,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { DestroyCuModuleNVX = auto_cast GetInstanceProcAddr(instance, "vkDestroyCuModuleNVX") DestroyCudaFunctionNV = auto_cast GetInstanceProcAddr(instance, "vkDestroyCudaFunctionNV") DestroyCudaModuleNV = auto_cast GetInstanceProcAddr(instance, "vkDestroyCudaModuleNV") + DestroyDataGraphPipelineSessionARM = auto_cast GetInstanceProcAddr(instance, "vkDestroyDataGraphPipelineSessionARM") DestroyDeferredOperationKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroyDeferredOperationKHR") DestroyDescriptorPool = auto_cast GetInstanceProcAddr(instance, "vkDestroyDescriptorPool") DestroyDescriptorSetLayout = auto_cast GetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout") @@ -4441,8 +5097,10 @@ load_proc_addresses_instance :: proc(instance: Instance) { DestroyDescriptorUpdateTemplateKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroyDescriptorUpdateTemplateKHR") DestroyDevice = auto_cast GetInstanceProcAddr(instance, "vkDestroyDevice") DestroyEvent = auto_cast GetInstanceProcAddr(instance, "vkDestroyEvent") + DestroyExternalComputeQueueNV = auto_cast GetInstanceProcAddr(instance, "vkDestroyExternalComputeQueueNV") DestroyFence = auto_cast GetInstanceProcAddr(instance, "vkDestroyFence") DestroyFramebuffer = auto_cast GetInstanceProcAddr(instance, "vkDestroyFramebuffer") + DestroyGpaSessionAMD = auto_cast GetInstanceProcAddr(instance, "vkDestroyGpaSessionAMD") DestroyImage = auto_cast GetInstanceProcAddr(instance, "vkDestroyImage") DestroyImageView = auto_cast GetInstanceProcAddr(instance, "vkDestroyImageView") DestroyIndirectCommandsLayoutEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyIndirectCommandsLayoutEXT") @@ -4463,8 +5121,11 @@ load_proc_addresses_instance :: proc(instance: Instance) { DestroySamplerYcbcrConversionKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroySamplerYcbcrConversionKHR") DestroySemaphore = auto_cast GetInstanceProcAddr(instance, "vkDestroySemaphore") DestroyShaderEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyShaderEXT") + DestroyShaderInstrumentationARM = auto_cast GetInstanceProcAddr(instance, "vkDestroyShaderInstrumentationARM") DestroyShaderModule = auto_cast GetInstanceProcAddr(instance, "vkDestroyShaderModule") DestroySwapchainKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroySwapchainKHR") + DestroyTensorARM = auto_cast GetInstanceProcAddr(instance, "vkDestroyTensorARM") + DestroyTensorViewARM = auto_cast GetInstanceProcAddr(instance, "vkDestroyTensorViewARM") DestroyValidationCacheEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyValidationCacheEXT") DestroyVideoSessionKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroyVideoSessionKHR") DestroyVideoSessionParametersKHR = auto_cast GetInstanceProcAddr(instance, "vkDestroyVideoSessionParametersKHR") @@ -4494,6 +5155,10 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetCalibratedTimestampsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetCalibratedTimestampsKHR") GetClusterAccelerationStructureBuildSizesNV = auto_cast GetInstanceProcAddr(instance, "vkGetClusterAccelerationStructureBuildSizesNV") GetCudaModuleCacheNV = auto_cast GetInstanceProcAddr(instance, "vkGetCudaModuleCacheNV") + GetDataGraphPipelineAvailablePropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetDataGraphPipelineAvailablePropertiesARM") + GetDataGraphPipelinePropertiesARM = auto_cast GetInstanceProcAddr(instance, "vkGetDataGraphPipelinePropertiesARM") + GetDataGraphPipelineSessionBindPointRequirementsARM = auto_cast GetInstanceProcAddr(instance, "vkGetDataGraphPipelineSessionBindPointRequirementsARM") + GetDataGraphPipelineSessionMemoryRequirementsARM = auto_cast GetInstanceProcAddr(instance, "vkGetDataGraphPipelineSessionMemoryRequirementsARM") GetDeferredOperationMaxConcurrencyKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeferredOperationMaxConcurrencyKHR") GetDeferredOperationResultKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeferredOperationResultKHR") GetDescriptorEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDescriptorEXT") @@ -4506,7 +5171,10 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetDeviceAccelerationStructureCompatibilityKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceAccelerationStructureCompatibilityKHR") GetDeviceBufferMemoryRequirements = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceBufferMemoryRequirements") GetDeviceBufferMemoryRequirementsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceBufferMemoryRequirementsKHR") + GetDeviceCombinedImageSamplerIndexNVX = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceCombinedImageSamplerIndexNVX") + GetDeviceFaultDebugInfoKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceFaultDebugInfoKHR") GetDeviceFaultInfoEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceFaultInfoEXT") + GetDeviceFaultReportsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceFaultReportsKHR") GetDeviceGroupPeerMemoryFeatures = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceGroupPeerMemoryFeatures") GetDeviceGroupPeerMemoryFeaturesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceGroupPeerMemoryFeaturesKHR") GetDeviceGroupPresentCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceGroupPresentCapabilitiesKHR") @@ -4526,6 +5194,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetDeviceQueue = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceQueue") GetDeviceQueue2 = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceQueue2") GetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI") + GetDeviceTensorMemoryRequirementsARM = auto_cast GetInstanceProcAddr(instance, "vkGetDeviceTensorMemoryRequirementsARM") GetDynamicRenderingTilePropertiesQCOM = auto_cast GetInstanceProcAddr(instance, "vkGetDynamicRenderingTilePropertiesQCOM") GetEncodedVideoSessionParametersKHR = auto_cast GetInstanceProcAddr(instance, "vkGetEncodedVideoSessionParametersKHR") GetEventStatus = auto_cast GetInstanceProcAddr(instance, "vkGetEventStatus") @@ -4537,10 +5206,14 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetFramebufferTilePropertiesQCOM = auto_cast GetInstanceProcAddr(instance, "vkGetFramebufferTilePropertiesQCOM") GetGeneratedCommandsMemoryRequirementsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetGeneratedCommandsMemoryRequirementsEXT") GetGeneratedCommandsMemoryRequirementsNV = auto_cast GetInstanceProcAddr(instance, "vkGetGeneratedCommandsMemoryRequirementsNV") + GetGpaDeviceClockInfoAMD = auto_cast GetInstanceProcAddr(instance, "vkGetGpaDeviceClockInfoAMD") + GetGpaSessionResultsAMD = auto_cast GetInstanceProcAddr(instance, "vkGetGpaSessionResultsAMD") + GetGpaSessionStatusAMD = auto_cast GetInstanceProcAddr(instance, "vkGetGpaSessionStatusAMD") GetImageDrmFormatModifierPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetImageDrmFormatModifierPropertiesEXT") GetImageMemoryRequirements = auto_cast GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements") GetImageMemoryRequirements2 = auto_cast GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements2") GetImageMemoryRequirements2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements2KHR") + GetImageOpaqueCaptureDataEXT = auto_cast GetInstanceProcAddr(instance, "vkGetImageOpaqueCaptureDataEXT") GetImageOpaqueCaptureDescriptorDataEXT = auto_cast GetInstanceProcAddr(instance, "vkGetImageOpaqueCaptureDescriptorDataEXT") GetImageSparseMemoryRequirements = auto_cast GetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements") GetImageSparseMemoryRequirements2 = auto_cast GetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements2") @@ -4565,6 +5238,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetMemoryWin32HandlePropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetMemoryWin32HandlePropertiesKHR") GetMicromapBuildSizesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetMicromapBuildSizesEXT") GetPartitionedAccelerationStructuresBuildSizesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPartitionedAccelerationStructuresBuildSizesNV") + GetPastPresentationTimingEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPastPresentationTimingEXT") GetPastPresentationTimingGOOGLE = auto_cast GetInstanceProcAddr(instance, "vkGetPastPresentationTimingGOOGLE") GetPerformanceParameterINTEL = auto_cast GetInstanceProcAddr(instance, "vkGetPerformanceParameterINTEL") GetPipelineBinaryDataKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPipelineBinaryDataKHR") @@ -4596,11 +5270,18 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetSemaphoreWin32HandleKHR = auto_cast GetInstanceProcAddr(instance, "vkGetSemaphoreWin32HandleKHR") GetShaderBinaryDataEXT = auto_cast GetInstanceProcAddr(instance, "vkGetShaderBinaryDataEXT") GetShaderInfoAMD = auto_cast GetInstanceProcAddr(instance, "vkGetShaderInfoAMD") + GetShaderInstrumentationValuesARM = auto_cast GetInstanceProcAddr(instance, "vkGetShaderInstrumentationValuesARM") GetShaderModuleCreateInfoIdentifierEXT = auto_cast GetInstanceProcAddr(instance, "vkGetShaderModuleCreateInfoIdentifierEXT") GetShaderModuleIdentifierEXT = auto_cast GetInstanceProcAddr(instance, "vkGetShaderModuleIdentifierEXT") GetSwapchainCounterEXT = auto_cast GetInstanceProcAddr(instance, "vkGetSwapchainCounterEXT") GetSwapchainImagesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR") GetSwapchainStatusKHR = auto_cast GetInstanceProcAddr(instance, "vkGetSwapchainStatusKHR") + GetSwapchainTimeDomainPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetSwapchainTimeDomainPropertiesEXT") + GetSwapchainTimingPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkGetSwapchainTimingPropertiesEXT") + GetTensorMemoryRequirementsARM = auto_cast GetInstanceProcAddr(instance, "vkGetTensorMemoryRequirementsARM") + GetTensorOpaqueCaptureDataARM = auto_cast GetInstanceProcAddr(instance, "vkGetTensorOpaqueCaptureDataARM") + GetTensorOpaqueCaptureDescriptorDataARM = auto_cast GetInstanceProcAddr(instance, "vkGetTensorOpaqueCaptureDescriptorDataARM") + GetTensorViewOpaqueCaptureDescriptorDataARM = auto_cast GetInstanceProcAddr(instance, "vkGetTensorViewOpaqueCaptureDescriptorDataARM") GetValidationCacheDataEXT = auto_cast GetInstanceProcAddr(instance, "vkGetValidationCacheDataEXT") GetVideoSessionMemoryRequirementsKHR = auto_cast GetInstanceProcAddr(instance, "vkGetVideoSessionMemoryRequirementsKHR") ImportFenceFdKHR = auto_cast GetInstanceProcAddr(instance, "vkImportFenceFdKHR") @@ -4626,6 +5307,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { QueueSubmit2 = auto_cast GetInstanceProcAddr(instance, "vkQueueSubmit2") QueueSubmit2KHR = auto_cast GetInstanceProcAddr(instance, "vkQueueSubmit2KHR") QueueWaitIdle = auto_cast GetInstanceProcAddr(instance, "vkQueueWaitIdle") + RegisterCustomBorderColorEXT = auto_cast GetInstanceProcAddr(instance, "vkRegisterCustomBorderColorEXT") RegisterDeviceEventEXT = auto_cast GetInstanceProcAddr(instance, "vkRegisterDeviceEventEXT") RegisterDisplayEventEXT = auto_cast GetInstanceProcAddr(instance, "vkRegisterDisplayEventEXT") ReleaseCapturedPipelineDataKHR = auto_cast GetInstanceProcAddr(instance, "vkReleaseCapturedPipelineDataKHR") @@ -4633,23 +5315,27 @@ load_proc_addresses_instance :: proc(instance: Instance) { ReleasePerformanceConfigurationINTEL = auto_cast GetInstanceProcAddr(instance, "vkReleasePerformanceConfigurationINTEL") ReleaseProfilingLockKHR = auto_cast GetInstanceProcAddr(instance, "vkReleaseProfilingLockKHR") ReleaseSwapchainImagesEXT = auto_cast GetInstanceProcAddr(instance, "vkReleaseSwapchainImagesEXT") + ReleaseSwapchainImagesKHR = auto_cast GetInstanceProcAddr(instance, "vkReleaseSwapchainImagesKHR") ResetCommandBuffer = auto_cast GetInstanceProcAddr(instance, "vkResetCommandBuffer") ResetCommandPool = auto_cast GetInstanceProcAddr(instance, "vkResetCommandPool") ResetDescriptorPool = auto_cast GetInstanceProcAddr(instance, "vkResetDescriptorPool") ResetEvent = auto_cast GetInstanceProcAddr(instance, "vkResetEvent") ResetFences = auto_cast GetInstanceProcAddr(instance, "vkResetFences") + ResetGpaSessionAMD = auto_cast GetInstanceProcAddr(instance, "vkResetGpaSessionAMD") ResetQueryPool = auto_cast GetInstanceProcAddr(instance, "vkResetQueryPool") ResetQueryPoolEXT = auto_cast GetInstanceProcAddr(instance, "vkResetQueryPoolEXT") SetDebugUtilsObjectNameEXT = auto_cast GetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT") SetDebugUtilsObjectTagEXT = auto_cast GetInstanceProcAddr(instance, "vkSetDebugUtilsObjectTagEXT") SetDeviceMemoryPriorityEXT = auto_cast GetInstanceProcAddr(instance, "vkSetDeviceMemoryPriorityEXT") SetEvent = auto_cast GetInstanceProcAddr(instance, "vkSetEvent") + SetGpaDeviceClockModeAMD = auto_cast GetInstanceProcAddr(instance, "vkSetGpaDeviceClockModeAMD") SetHdrMetadataEXT = auto_cast GetInstanceProcAddr(instance, "vkSetHdrMetadataEXT") SetLatencyMarkerNV = auto_cast GetInstanceProcAddr(instance, "vkSetLatencyMarkerNV") SetLatencySleepModeNV = auto_cast GetInstanceProcAddr(instance, "vkSetLatencySleepModeNV") SetLocalDimmingAMD = auto_cast GetInstanceProcAddr(instance, "vkSetLocalDimmingAMD") SetPrivateData = auto_cast GetInstanceProcAddr(instance, "vkSetPrivateData") SetPrivateDataEXT = auto_cast GetInstanceProcAddr(instance, "vkSetPrivateDataEXT") + SetSwapchainPresentTimingQueueSizeEXT = auto_cast GetInstanceProcAddr(instance, "vkSetSwapchainPresentTimingQueueSizeEXT") SignalSemaphore = auto_cast GetInstanceProcAddr(instance, "vkSignalSemaphore") SignalSemaphoreKHR = auto_cast GetInstanceProcAddr(instance, "vkSignalSemaphoreKHR") TransitionImageLayout = auto_cast GetInstanceProcAddr(instance, "vkTransitionImageLayout") @@ -4660,6 +5346,7 @@ load_proc_addresses_instance :: proc(instance: Instance) { UnmapMemory = auto_cast GetInstanceProcAddr(instance, "vkUnmapMemory") UnmapMemory2 = auto_cast GetInstanceProcAddr(instance, "vkUnmapMemory2") UnmapMemory2KHR = auto_cast GetInstanceProcAddr(instance, "vkUnmapMemory2KHR") + UnregisterCustomBorderColorEXT = auto_cast GetInstanceProcAddr(instance, "vkUnregisterCustomBorderColorEXT") UpdateDescriptorSetWithTemplate = auto_cast GetInstanceProcAddr(instance, "vkUpdateDescriptorSetWithTemplate") UpdateDescriptorSetWithTemplateKHR = auto_cast GetInstanceProcAddr(instance, "vkUpdateDescriptorSetWithTemplateKHR") UpdateDescriptorSets = auto_cast GetInstanceProcAddr(instance, "vkUpdateDescriptorSets") @@ -4667,11 +5354,14 @@ load_proc_addresses_instance :: proc(instance: Instance) { UpdateIndirectExecutionSetShaderEXT = auto_cast GetInstanceProcAddr(instance, "vkUpdateIndirectExecutionSetShaderEXT") UpdateVideoSessionParametersKHR = auto_cast GetInstanceProcAddr(instance, "vkUpdateVideoSessionParametersKHR") WaitForFences = auto_cast GetInstanceProcAddr(instance, "vkWaitForFences") + WaitForPresent2KHR = auto_cast GetInstanceProcAddr(instance, "vkWaitForPresent2KHR") WaitForPresentKHR = auto_cast GetInstanceProcAddr(instance, "vkWaitForPresentKHR") WaitSemaphores = auto_cast GetInstanceProcAddr(instance, "vkWaitSemaphores") WaitSemaphoresKHR = auto_cast GetInstanceProcAddr(instance, "vkWaitSemaphoresKHR") WriteAccelerationStructuresPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkWriteAccelerationStructuresPropertiesKHR") WriteMicromapsPropertiesEXT = auto_cast GetInstanceProcAddr(instance, "vkWriteMicromapsPropertiesEXT") + WriteResourceDescriptorsEXT = auto_cast GetInstanceProcAddr(instance, "vkWriteResourceDescriptorsEXT") + WriteSamplerDescriptorsEXT = auto_cast GetInstanceProcAddr(instance, "vkWriteSamplerDescriptorsEXT") } load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr) { @@ -4683,6 +5373,7 @@ load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr) { EnumerateInstanceExtensionProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceExtensionProperties") EnumerateInstanceLayerProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceLayerProperties") EnumerateInstanceVersion = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceVersion") + GetExternalComputeQueueDataNV = auto_cast GetInstanceProcAddr(nil, "vkGetExternalComputeQueueDataNV") GetInstanceProcAddr = auto_cast GetInstanceProcAddr(nil, "vkGetInstanceProcAddr") } diff --git a/vendor/vulkan/structs.odin b/vendor/vulkan/structs.odin index 7ceac8c82..bae689c0a 100644 --- a/vendor/vulkan/structs.odin +++ b/vendor/vulkan/structs.odin @@ -1,6 +1,3 @@ -// -// Vulkan wrapper generated from "https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/master/include/vulkan/vulkan_core.h" -// package vulkan import "core:c" @@ -95,75 +92,6 @@ BaseOutStructure :: struct { pNext: ^BaseOutStructure, } -BufferMemoryBarrier :: struct { - sType: StructureType, - pNext: rawptr, - srcAccessMask: AccessFlags, - dstAccessMask: AccessFlags, - srcQueueFamilyIndex: u32, - dstQueueFamilyIndex: u32, - buffer: Buffer, - offset: DeviceSize, - size: DeviceSize, -} - -DispatchIndirectCommand :: struct { - x: u32, - y: u32, - z: u32, -} - -DrawIndexedIndirectCommand :: struct { - indexCount: u32, - instanceCount: u32, - firstIndex: u32, - vertexOffset: i32, - firstInstance: u32, -} - -DrawIndirectCommand :: struct { - vertexCount: u32, - instanceCount: u32, - firstVertex: u32, - firstInstance: u32, -} - -ImageSubresourceRange :: struct { - aspectMask: ImageAspectFlags, - baseMipLevel: u32, - levelCount: u32, - baseArrayLayer: u32, - layerCount: u32, -} - -ImageMemoryBarrier :: struct { - sType: StructureType, - pNext: rawptr, - srcAccessMask: AccessFlags, - dstAccessMask: AccessFlags, - oldLayout: ImageLayout, - newLayout: ImageLayout, - srcQueueFamilyIndex: u32, - dstQueueFamilyIndex: u32, - image: Image, - subresourceRange: ImageSubresourceRange, -} - -MemoryBarrier :: struct { - sType: StructureType, - pNext: rawptr, - srcAccessMask: AccessFlags, - dstAccessMask: AccessFlags, -} - -PipelineCacheHeaderVersionOne :: struct { - headerSize: u32, - headerVersion: PipelineCacheHeaderVersion, - vendorID: u32, - deviceID: u32, - pipelineCacheUUID: [UUID_SIZE]u8, -} - AllocationCallbacks :: struct { pUserData: rawptr, pfnAllocation: ProcAllocationFunction, @@ -486,6 +414,41 @@ MemoryRequirements :: struct { memoryTypeBits: u32, } +ImageSubresource :: struct { + aspectMask: ImageAspectFlags, + mipLevel: u32, + arrayLayer: u32, +} + +SparseImageFormatProperties :: struct { + aspectMask: ImageAspectFlags, + imageGranularity: Extent3D, + flags: SparseImageFormatFlags, +} + +SparseImageMemoryBind :: struct { + subresource: ImageSubresource, + offset: Offset3D, + extent: Extent3D, + memory: DeviceMemory, + memoryOffset: DeviceSize, + flags: SparseMemoryBindFlags, +} + +SparseImageMemoryBindInfo :: struct { + image: Image, + bindCount: u32, + pBinds: [^]SparseImageMemoryBind, +} + +SparseImageMemoryRequirements :: struct { + formatProperties: SparseImageFormatProperties, + imageMipTailFirstLod: u32, + imageMipTailSize: DeviceSize, + imageMipTailOffset: DeviceSize, + imageMipTailStride: DeviceSize, +} + SparseMemoryBind :: struct { resourceOffset: DeviceSize, size: DeviceSize, @@ -506,27 +469,6 @@ SparseImageOpaqueMemoryBindInfo :: struct { pBinds: [^]SparseMemoryBind, } -ImageSubresource :: struct { - aspectMask: ImageAspectFlags, - mipLevel: u32, - arrayLayer: u32, -} - -SparseImageMemoryBind :: struct { - subresource: ImageSubresource, - offset: Offset3D, - extent: Extent3D, - memory: DeviceMemory, - memoryOffset: DeviceSize, - flags: SparseMemoryBindFlags, -} - -SparseImageMemoryBindInfo :: struct { - image: Image, - bindCount: u32, - pBinds: [^]SparseImageMemoryBind, -} - BindSparseInfo :: struct { sType: StructureType, pNext: rawptr, @@ -542,20 +484,6 @@ BindSparseInfo :: struct { pSignalSemaphores: [^]Semaphore, } -SparseImageFormatProperties :: struct { - aspectMask: ImageAspectFlags, - imageGranularity: Extent3D, - flags: SparseImageFormatFlags, -} - -SparseImageMemoryRequirements :: struct { - formatProperties: SparseImageFormatProperties, - imageMipTailFirstLod: u32, - imageMipTailSize: DeviceSize, - imageMipTailOffset: DeviceSize, - imageMipTailStride: DeviceSize, -} - FenceCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -568,12 +496,6 @@ SemaphoreCreateInfo :: struct { flags: SemaphoreCreateFlags, } -EventCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: EventCreateFlags, -} - QueryPoolCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -594,16 +516,6 @@ BufferCreateInfo :: struct { pQueueFamilyIndices: [^]u32, } -BufferViewCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: BufferViewCreateFlags, - buffer: Buffer, - format: Format, - offset: DeviceSize, - range: DeviceSize, -} - ImageCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -637,6 +549,14 @@ ComponentMapping :: struct { a: ComponentSwizzle, } +ImageSubresourceRange :: struct { + aspectMask: ImageAspectFlags, + baseMipLevel: u32, + levelCount: u32, + baseArrayLayer: u32, + layerCount: u32, +} + ImageViewCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -648,6 +568,131 @@ ImageViewCreateInfo :: struct { subresourceRange: ImageSubresourceRange, } +CommandPoolCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: CommandPoolCreateFlags, + queueFamilyIndex: u32, +} + +CommandBufferAllocateInfo :: struct { + sType: StructureType, + pNext: rawptr, + commandPool: CommandPool, + level: CommandBufferLevel, + commandBufferCount: u32, +} + +CommandBufferInheritanceInfo :: struct { + sType: StructureType, + pNext: rawptr, + renderPass: RenderPass, + subpass: u32, + framebuffer: Framebuffer, + occlusionQueryEnable: b32, + queryFlags: QueryControlFlags, + pipelineStatistics: QueryPipelineStatisticFlags, +} + +CommandBufferBeginInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: CommandBufferUsageFlags, + pInheritanceInfo: ^CommandBufferInheritanceInfo, +} + +BufferCopy :: struct { + srcOffset: DeviceSize, + dstOffset: DeviceSize, + size: DeviceSize, +} + +ImageSubresourceLayers :: struct { + aspectMask: ImageAspectFlags, + mipLevel: u32, + baseArrayLayer: u32, + layerCount: u32, +} + +BufferImageCopy :: struct { + bufferOffset: DeviceSize, + bufferRowLength: u32, + bufferImageHeight: u32, + imageSubresource: ImageSubresourceLayers, + imageOffset: Offset3D, + imageExtent: Extent3D, +} + +ImageCopy :: struct { + srcSubresource: ImageSubresourceLayers, + srcOffset: Offset3D, + dstSubresource: ImageSubresourceLayers, + dstOffset: Offset3D, + extent: Extent3D, +} + +BufferMemoryBarrier :: struct { + sType: StructureType, + pNext: rawptr, + srcAccessMask: AccessFlags, + dstAccessMask: AccessFlags, + srcQueueFamilyIndex: u32, + dstQueueFamilyIndex: u32, + buffer: Buffer, + offset: DeviceSize, + size: DeviceSize, +} + +ImageMemoryBarrier :: struct { + sType: StructureType, + pNext: rawptr, + srcAccessMask: AccessFlags, + dstAccessMask: AccessFlags, + oldLayout: ImageLayout, + newLayout: ImageLayout, + srcQueueFamilyIndex: u32, + dstQueueFamilyIndex: u32, + image: Image, + subresourceRange: ImageSubresourceRange, +} + +MemoryBarrier :: struct { + sType: StructureType, + pNext: rawptr, + srcAccessMask: AccessFlags, + dstAccessMask: AccessFlags, +} + +DispatchIndirectCommand :: struct { + x: u32, + y: u32, + z: u32, +} + +PipelineCacheHeaderVersionOne :: struct { + headerSize: u32, + headerVersion: PipelineCacheHeaderVersion, + vendorID: u32, + deviceID: u32, + pipelineCacheUUID: [UUID_SIZE]u8, +} + +EventCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: EventCreateFlags, +} + +BufferViewCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: BufferViewCreateFlags, + buffer: Buffer, + format: Format, + offset: DeviceSize, + range: DeviceSize, +} + ShaderModuleCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -697,168 +742,6 @@ ComputePipelineCreateInfo :: struct { basePipelineIndex: i32, } -VertexInputBindingDescription :: struct { - binding: u32, - stride: u32, - inputRate: VertexInputRate, -} - -VertexInputAttributeDescription :: struct { - location: u32, - binding: u32, - format: Format, - offset: u32, -} - -PipelineVertexInputStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineVertexInputStateCreateFlags, - vertexBindingDescriptionCount: u32, - pVertexBindingDescriptions: [^]VertexInputBindingDescription, - vertexAttributeDescriptionCount: u32, - pVertexAttributeDescriptions: [^]VertexInputAttributeDescription, -} - -PipelineInputAssemblyStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineInputAssemblyStateCreateFlags, - topology: PrimitiveTopology, - primitiveRestartEnable: b32, -} - -PipelineTessellationStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineTessellationStateCreateFlags, - patchControlPoints: u32, -} - -Viewport :: struct { - x: f32, - y: f32, - width: f32, - height: f32, - minDepth: f32, - maxDepth: f32, -} - -PipelineViewportStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineViewportStateCreateFlags, - viewportCount: u32, - pViewports: [^]Viewport, - scissorCount: u32, - pScissors: [^]Rect2D, -} - -PipelineRasterizationStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineRasterizationStateCreateFlags, - depthClampEnable: b32, - rasterizerDiscardEnable: b32, - polygonMode: PolygonMode, - cullMode: CullModeFlags, - frontFace: FrontFace, - depthBiasEnable: b32, - depthBiasConstantFactor: f32, - depthBiasClamp: f32, - depthBiasSlopeFactor: f32, - lineWidth: f32, -} - -PipelineMultisampleStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineMultisampleStateCreateFlags, - rasterizationSamples: SampleCountFlags, - sampleShadingEnable: b32, - minSampleShading: f32, - pSampleMask: ^SampleMask, - alphaToCoverageEnable: b32, - alphaToOneEnable: b32, -} - -StencilOpState :: struct { - failOp: StencilOp, - passOp: StencilOp, - depthFailOp: StencilOp, - compareOp: CompareOp, - compareMask: u32, - writeMask: u32, - reference: u32, -} - -PipelineDepthStencilStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineDepthStencilStateCreateFlags, - depthTestEnable: b32, - depthWriteEnable: b32, - depthCompareOp: CompareOp, - depthBoundsTestEnable: b32, - stencilTestEnable: b32, - front: StencilOpState, - back: StencilOpState, - minDepthBounds: f32, - maxDepthBounds: f32, -} - -PipelineColorBlendAttachmentState :: struct { - blendEnable: b32, - srcColorBlendFactor: BlendFactor, - dstColorBlendFactor: BlendFactor, - colorBlendOp: BlendOp, - srcAlphaBlendFactor: BlendFactor, - dstAlphaBlendFactor: BlendFactor, - alphaBlendOp: BlendOp, - colorWriteMask: ColorComponentFlags, -} - -PipelineColorBlendStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineColorBlendStateCreateFlags, - logicOpEnable: b32, - logicOp: LogicOp, - attachmentCount: u32, - pAttachments: [^]PipelineColorBlendAttachmentState, - blendConstants: [4]f32, -} - -PipelineDynamicStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineDynamicStateCreateFlags, - dynamicStateCount: u32, - pDynamicStates: [^]DynamicState, -} - -GraphicsPipelineCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineCreateFlags, - stageCount: u32, - pStages: [^]PipelineShaderStageCreateInfo, - pVertexInputState: ^PipelineVertexInputStateCreateInfo, - pInputAssemblyState: ^PipelineInputAssemblyStateCreateInfo, - pTessellationState: ^PipelineTessellationStateCreateInfo, - pViewportState: ^PipelineViewportStateCreateInfo, - pRasterizationState: ^PipelineRasterizationStateCreateInfo, - pMultisampleState: ^PipelineMultisampleStateCreateInfo, - pDepthStencilState: ^PipelineDepthStencilStateCreateInfo, - pColorBlendState: ^PipelineColorBlendStateCreateInfo, - pDynamicState: ^PipelineDynamicStateCreateInfo, - layout: PipelineLayout, - renderPass: RenderPass, - subpass: u32, - basePipelineHandle: Pipeline, - basePipelineIndex: i32, -} - PushConstantRange :: struct { stageFlags: ShaderStageFlags, offset: u32, @@ -971,6 +854,189 @@ WriteDescriptorSet :: struct { pTexelBufferView: ^BufferView, } +ClearColorValue :: struct #raw_union { + float32: [4]f32, + int32: [4]i32, + uint32: [4]u32, +} + +DrawIndexedIndirectCommand :: struct { + indexCount: u32, + instanceCount: u32, + firstIndex: u32, + vertexOffset: i32, + firstInstance: u32, +} + +DrawIndirectCommand :: struct { + vertexCount: u32, + instanceCount: u32, + firstVertex: u32, + firstInstance: u32, +} + +StencilOpState :: struct { + failOp: StencilOp, + passOp: StencilOp, + depthFailOp: StencilOp, + compareOp: CompareOp, + compareMask: u32, + writeMask: u32, + reference: u32, +} + +VertexInputAttributeDescription :: struct { + location: u32, + binding: u32, + format: Format, + offset: u32, +} + +VertexInputBindingDescription :: struct { + binding: u32, + stride: u32, + inputRate: VertexInputRate, +} + +Viewport :: struct { + x: f32, + y: f32, + width: f32, + height: f32, + minDepth: f32, + maxDepth: f32, +} + +PipelineColorBlendAttachmentState :: struct { + blendEnable: b32, + srcColorBlendFactor: BlendFactor, + dstColorBlendFactor: BlendFactor, + colorBlendOp: BlendOp, + srcAlphaBlendFactor: BlendFactor, + dstAlphaBlendFactor: BlendFactor, + alphaBlendOp: BlendOp, + colorWriteMask: ColorComponentFlags, +} + +PipelineColorBlendStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineColorBlendStateCreateFlags, + logicOpEnable: b32, + logicOp: LogicOp, + attachmentCount: u32, + pAttachments: [^]PipelineColorBlendAttachmentState, + blendConstants: [4]f32, +} + +PipelineDepthStencilStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineDepthStencilStateCreateFlags, + depthTestEnable: b32, + depthWriteEnable: b32, + depthCompareOp: CompareOp, + depthBoundsTestEnable: b32, + stencilTestEnable: b32, + front: StencilOpState, + back: StencilOpState, + minDepthBounds: f32, + maxDepthBounds: f32, +} + +PipelineDynamicStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineDynamicStateCreateFlags, + dynamicStateCount: u32, + pDynamicStates: [^]DynamicState, +} + +PipelineInputAssemblyStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineInputAssemblyStateCreateFlags, + topology: PrimitiveTopology, + primitiveRestartEnable: b32, +} + +PipelineMultisampleStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineMultisampleStateCreateFlags, + rasterizationSamples: SampleCountFlags, + sampleShadingEnable: b32, + minSampleShading: f32, + pSampleMask: ^SampleMask, + alphaToCoverageEnable: b32, + alphaToOneEnable: b32, +} + +PipelineRasterizationStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineRasterizationStateCreateFlags, + depthClampEnable: b32, + rasterizerDiscardEnable: b32, + polygonMode: PolygonMode, + cullMode: CullModeFlags, + frontFace: FrontFace, + depthBiasEnable: b32, + depthBiasConstantFactor: f32, + depthBiasClamp: f32, + depthBiasSlopeFactor: f32, + lineWidth: f32, +} + +PipelineTessellationStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineTessellationStateCreateFlags, + patchControlPoints: u32, +} + +PipelineVertexInputStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineVertexInputStateCreateFlags, + vertexBindingDescriptionCount: u32, + pVertexBindingDescriptions: [^]VertexInputBindingDescription, + vertexAttributeDescriptionCount: u32, + pVertexAttributeDescriptions: [^]VertexInputAttributeDescription, +} + +PipelineViewportStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineViewportStateCreateFlags, + viewportCount: u32, + pViewports: [^]Viewport, + scissorCount: u32, + pScissors: [^]Rect2D, +} + +GraphicsPipelineCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineCreateFlags, + stageCount: u32, + pStages: [^]PipelineShaderStageCreateInfo, + pVertexInputState: ^PipelineVertexInputStateCreateInfo, + pInputAssemblyState: ^PipelineInputAssemblyStateCreateInfo, + pTessellationState: ^PipelineTessellationStateCreateInfo, + pViewportState: ^PipelineViewportStateCreateInfo, + pRasterizationState: ^PipelineRasterizationStateCreateInfo, + pMultisampleState: ^PipelineMultisampleStateCreateInfo, + pDepthStencilState: ^PipelineDepthStencilStateCreateInfo, + pColorBlendState: ^PipelineColorBlendStateCreateInfo, + pDynamicState: ^PipelineDynamicStateCreateInfo, + layout: PipelineLayout, + renderPass: RenderPass, + subpass: u32, + basePipelineHandle: Pipeline, + basePipelineIndex: i32, +} + AttachmentDescription :: struct { flags: AttachmentDescriptionFlags, format: Format, @@ -1000,6 +1066,16 @@ FramebufferCreateInfo :: struct { layers: u32, } +SubpassDependency :: struct { + srcSubpass: u32, + dstSubpass: u32, + srcStageMask: PipelineStageFlags, + dstStageMask: PipelineStageFlags, + srcAccessMask: AccessFlags, + dstAccessMask: AccessFlags, + dependencyFlags: DependencyFlags, +} + SubpassDescription :: struct { flags: SubpassDescriptionFlags, pipelineBindPoint: PipelineBindPoint, @@ -1013,16 +1089,6 @@ SubpassDescription :: struct { pPreserveAttachments: [^]u32, } -SubpassDependency :: struct { - srcSubpass: u32, - dstSubpass: u32, - srcStageMask: PipelineStageFlags, - dstStageMask: PipelineStageFlags, - srcAccessMask: AccessFlags, - dstAccessMask: AccessFlags, - dependencyFlags: DependencyFlags, -} - RenderPassCreateInfo :: struct { sType: StructureType, pNext: rawptr, @@ -1035,72 +1101,17 @@ RenderPassCreateInfo :: struct { pDependencies: [^]SubpassDependency, } -CommandPoolCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: CommandPoolCreateFlags, - queueFamilyIndex: u32, -} - -CommandBufferAllocateInfo :: struct { - sType: StructureType, - pNext: rawptr, - commandPool: CommandPool, - level: CommandBufferLevel, - commandBufferCount: u32, -} - -CommandBufferInheritanceInfo :: struct { - sType: StructureType, - pNext: rawptr, - renderPass: RenderPass, - subpass: u32, - framebuffer: Framebuffer, - occlusionQueryEnable: b32, - queryFlags: QueryControlFlags, - pipelineStatistics: QueryPipelineStatisticFlags, -} - -CommandBufferBeginInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: CommandBufferUsageFlags, - pInheritanceInfo: ^CommandBufferInheritanceInfo, -} - -BufferCopy :: struct { - srcOffset: DeviceSize, - dstOffset: DeviceSize, - size: DeviceSize, -} - -ImageSubresourceLayers :: struct { - aspectMask: ImageAspectFlags, - mipLevel: u32, - baseArrayLayer: u32, - layerCount: u32, -} - -BufferImageCopy :: struct { - bufferOffset: DeviceSize, - bufferRowLength: u32, - bufferImageHeight: u32, - imageSubresource: ImageSubresourceLayers, - imageOffset: Offset3D, - imageExtent: Extent3D, -} - -ClearColorValue :: struct #raw_union { - float32: [4]f32, - int32: [4]i32, - uint32: [4]u32, -} - ClearDepthStencilValue :: struct { depth: f32, stencil: u32, } +ClearRect :: struct { + rect: Rect2D, + baseArrayLayer: u32, + layerCount: u32, +} + ClearValue :: struct #raw_union { color: ClearColorValue, depthStencil: ClearDepthStencilValue, @@ -1112,12 +1123,6 @@ ClearAttachment :: struct { clearValue: ClearValue, } -ClearRect :: struct { - rect: Rect2D, - baseArrayLayer: u32, - layerCount: u32, -} - ImageBlit :: struct { srcSubresource: ImageSubresourceLayers, srcOffsets: [2]Offset3D, @@ -1125,14 +1130,6 @@ ImageBlit :: struct { dstOffsets: [2]Offset3D, } -ImageCopy :: struct { - srcSubresource: ImageSubresourceLayers, - srcOffset: Offset3D, - dstSubresource: ImageSubresourceLayers, - dstOffset: Offset3D, - extent: Extent3D, -} - ImageResolve :: struct { srcSubresource: ImageSubresourceLayers, srcOffset: Offset3D, @@ -1151,15 +1148,6 @@ RenderPassBeginInfo :: struct { pClearValues: [^]ClearValue, } -PhysicalDeviceSubgroupProperties :: struct { - sType: StructureType, - pNext: rawptr, - subgroupSize: u32, - supportedStages: ShaderStageFlags, - supportedOperations: SubgroupFeatureFlags, - quadOperationsInAllStages: b32, -} - BindBufferMemoryInfo :: struct { sType: StructureType, pNext: rawptr, @@ -1176,15 +1164,6 @@ BindImageMemoryInfo :: struct { memoryOffset: DeviceSize, } -PhysicalDevice16BitStorageFeatures :: struct { - sType: StructureType, - pNext: rawptr, - storageBuffer16BitAccess: b32, - uniformAndStorageBuffer16BitAccess: b32, - storagePushConstant16: b32, - storageInputOutput16: b32, -} - MemoryDedicatedRequirements :: struct { sType: StructureType, pNext: rawptr, @@ -1206,14 +1185,6 @@ MemoryAllocateFlagsInfo :: struct { deviceMask: u32, } -DeviceGroupRenderPassBeginInfo :: struct { - sType: StructureType, - pNext: rawptr, - deviceMask: u32, - deviceRenderAreaCount: u32, - pDeviceRenderAreas: [^]Rect2D, -} - DeviceGroupCommandBufferBeginInfo :: struct { sType: StructureType, pNext: rawptr, @@ -1361,70 +1332,12 @@ PhysicalDeviceSparseImageFormatInfo2 :: struct { tiling: ImageTiling, } -PhysicalDevicePointClippingProperties :: struct { - sType: StructureType, - pNext: rawptr, - pointClippingBehavior: PointClippingBehavior, -} - -InputAttachmentAspectReference :: struct { - subpass: u32, - inputAttachmentIndex: u32, - aspectMask: ImageAspectFlags, -} - -RenderPassInputAttachmentAspectCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - aspectReferenceCount: u32, - pAspectReferences: [^]InputAttachmentAspectReference, -} - ImageViewUsageCreateInfo :: struct { sType: StructureType, pNext: rawptr, usage: ImageUsageFlags, } -PipelineTessellationDomainOriginStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - domainOrigin: TessellationDomainOrigin, -} - -RenderPassMultiviewCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - subpassCount: u32, - pViewMasks: [^]u32, - dependencyCount: u32, - pViewOffsets: [^]i32, - correlationMaskCount: u32, - pCorrelationMasks: [^]u32, -} - -PhysicalDeviceMultiviewFeatures :: struct { - sType: StructureType, - pNext: rawptr, - multiview: b32, - multiviewGeometryShader: b32, - multiviewTessellationShader: b32, -} - -PhysicalDeviceMultiviewProperties :: struct { - sType: StructureType, - pNext: rawptr, - maxMultiviewViewCount: u32, - maxMultiviewInstanceIndex: u32, -} - -PhysicalDeviceVariablePointersFeatures :: struct { - sType: StructureType, - pNext: rawptr, - variablePointersStorageBuffer: b32, - variablePointers: b32, -} - PhysicalDeviceProtectedMemoryFeatures :: struct { sType: StructureType, pNext: rawptr, @@ -1451,25 +1364,6 @@ ProtectedSubmitInfo :: struct { protectedSubmit: b32, } -SamplerYcbcrConversionCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - format: Format, - ycbcrModel: SamplerYcbcrModelConversion, - ycbcrRange: SamplerYcbcrRange, - components: ComponentMapping, - xChromaOffset: ChromaLocation, - yChromaOffset: ChromaLocation, - chromaFilter: Filter, - forceExplicitReconstruction: b32, -} - -SamplerYcbcrConversionInfo :: struct { - sType: StructureType, - pNext: rawptr, - conversion: SamplerYcbcrConversion, -} - BindImagePlaneMemoryInfo :: struct { sType: StructureType, pNext: rawptr, @@ -1482,40 +1376,6 @@ ImagePlaneMemoryRequirementsInfo :: struct { planeAspect: ImageAspectFlags, } -PhysicalDeviceSamplerYcbcrConversionFeatures :: struct { - sType: StructureType, - pNext: rawptr, - samplerYcbcrConversion: b32, -} - -SamplerYcbcrConversionImageFormatProperties :: struct { - sType: StructureType, - pNext: rawptr, - combinedImageSamplerDescriptorCount: u32, -} - -DescriptorUpdateTemplateEntry :: struct { - dstBinding: u32, - dstArrayElement: u32, - descriptorCount: u32, - descriptorType: DescriptorType, - offset: int, - stride: int, -} - -DescriptorUpdateTemplateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: DescriptorUpdateTemplateCreateFlags, - descriptorUpdateEntryCount: u32, - pDescriptorUpdateEntries: [^]DescriptorUpdateTemplateEntry, - templateType: DescriptorUpdateTemplateType, - descriptorSetLayout: DescriptorSetLayout, - pipelineBindPoint: PipelineBindPoint, - pipelineLayout: PipelineLayout, - set: u32, -} - ExternalMemoryProperties :: struct { externalMemoryFeatures: ExternalMemoryFeatureFlags, exportFromImportedHandleTypes: ExternalMemoryHandleTypeFlags, @@ -1616,6 +1476,53 @@ ExternalSemaphoreProperties :: struct { externalSemaphoreFeatures: ExternalSemaphoreFeatureFlags, } +PhysicalDeviceSubgroupProperties :: struct { + sType: StructureType, + pNext: rawptr, + subgroupSize: u32, + supportedStages: ShaderStageFlags, + supportedOperations: SubgroupFeatureFlags, + quadOperationsInAllStages: b32, +} + +PhysicalDevice16BitStorageFeatures :: struct { + sType: StructureType, + pNext: rawptr, + storageBuffer16BitAccess: b32, + uniformAndStorageBuffer16BitAccess: b32, + storagePushConstant16: b32, + storageInputOutput16: b32, +} + +PhysicalDeviceVariablePointersFeatures :: struct { + sType: StructureType, + pNext: rawptr, + variablePointersStorageBuffer: b32, + variablePointers: b32, +} + +DescriptorUpdateTemplateEntry :: struct { + dstBinding: u32, + dstArrayElement: u32, + descriptorCount: u32, + descriptorType: DescriptorType, + offset: int, + stride: int, +} + +DescriptorUpdateTemplateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: DescriptorUpdateTemplateCreateFlags, + descriptorUpdateEntryCount: u32, + pDescriptorUpdateEntries: [^]DescriptorUpdateTemplateEntry, + templateType: DescriptorUpdateTemplateType, + descriptorSetLayout: DescriptorSetLayout, + pipelineBindPoint: PipelineBindPoint, + pipelineLayout: PipelineLayout, + set: u32, +} + PhysicalDeviceMaintenance3Properties :: struct { sType: StructureType, pNext: rawptr, @@ -1629,12 +1536,118 @@ DescriptorSetLayoutSupport :: struct { supported: b32, } +SamplerYcbcrConversionCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + format: Format, + ycbcrModel: SamplerYcbcrModelConversion, + ycbcrRange: SamplerYcbcrRange, + components: ComponentMapping, + xChromaOffset: ChromaLocation, + yChromaOffset: ChromaLocation, + chromaFilter: Filter, + forceExplicitReconstruction: b32, +} + +SamplerYcbcrConversionInfo :: struct { + sType: StructureType, + pNext: rawptr, + conversion: SamplerYcbcrConversion, +} + +PhysicalDeviceSamplerYcbcrConversionFeatures :: struct { + sType: StructureType, + pNext: rawptr, + samplerYcbcrConversion: b32, +} + +SamplerYcbcrConversionImageFormatProperties :: struct { + sType: StructureType, + pNext: rawptr, + combinedImageSamplerDescriptorCount: u32, +} + +DeviceGroupRenderPassBeginInfo :: struct { + sType: StructureType, + pNext: rawptr, + deviceMask: u32, + deviceRenderAreaCount: u32, + pDeviceRenderAreas: [^]Rect2D, +} + +PhysicalDevicePointClippingProperties :: struct { + sType: StructureType, + pNext: rawptr, + pointClippingBehavior: PointClippingBehavior, +} + +InputAttachmentAspectReference :: struct { + subpass: u32, + inputAttachmentIndex: u32, + aspectMask: ImageAspectFlags, +} + +RenderPassInputAttachmentAspectCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + aspectReferenceCount: u32, + pAspectReferences: [^]InputAttachmentAspectReference, +} + +PipelineTessellationDomainOriginStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + domainOrigin: TessellationDomainOrigin, +} + +RenderPassMultiviewCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + subpassCount: u32, + pViewMasks: [^]u32, + dependencyCount: u32, + pViewOffsets: [^]i32, + correlationMaskCount: u32, + pCorrelationMasks: [^]u32, +} + +PhysicalDeviceMultiviewFeatures :: struct { + sType: StructureType, + pNext: rawptr, + multiview: b32, + multiviewGeometryShader: b32, + multiviewTessellationShader: b32, +} + +PhysicalDeviceMultiviewProperties :: struct { + sType: StructureType, + pNext: rawptr, + maxMultiviewViewCount: u32, + maxMultiviewInstanceIndex: u32, +} + PhysicalDeviceShaderDrawParametersFeatures :: struct { sType: StructureType, pNext: rawptr, shaderDrawParameters: b32, } +ConformanceVersion :: struct { + major: u8, + minor: u8, + subminor: u8, + patch: u8, +} + +PhysicalDeviceDriverProperties :: struct { + sType: StructureType, + pNext: rawptr, + driverID: DriverId, + driverName: [MAX_DRIVER_NAME_SIZE]byte, + driverInfo: [MAX_DRIVER_INFO_SIZE]byte, + conformanceVersion: ConformanceVersion, +} + PhysicalDeviceVulkan11Features :: struct { sType: StructureType, pNext: rawptr, @@ -1724,13 +1737,6 @@ PhysicalDeviceVulkan12Features :: struct { subgroupBroadcastDynamicId: b32, } -ConformanceVersion :: struct { - major: u8, - minor: u8, - subminor: u8, - patch: u8, -} - PhysicalDeviceVulkan12Properties :: struct { sType: StructureType, pNext: rawptr, @@ -1795,80 +1801,94 @@ ImageFormatListCreateInfo :: struct { pViewFormats: [^]Format, } -AttachmentDescription2 :: struct { +PhysicalDeviceVulkanMemoryModelFeatures :: struct { + sType: StructureType, + pNext: rawptr, + vulkanMemoryModel: b32, + vulkanMemoryModelDeviceScope: b32, + vulkanMemoryModelAvailabilityVisibilityChains: b32, +} + +PhysicalDeviceHostQueryResetFeatures :: struct { sType: StructureType, pNext: rawptr, - flags: AttachmentDescriptionFlags, - format: Format, - samples: SampleCountFlags, - loadOp: AttachmentLoadOp, - storeOp: AttachmentStoreOp, - stencilLoadOp: AttachmentLoadOp, - stencilStoreOp: AttachmentStoreOp, - initialLayout: ImageLayout, - finalLayout: ImageLayout, + hostQueryReset: b32, } -AttachmentReference2 :: struct { - sType: StructureType, - pNext: rawptr, - attachment: u32, - layout: ImageLayout, - aspectMask: ImageAspectFlags, +PhysicalDeviceTimelineSemaphoreFeatures :: struct { + sType: StructureType, + pNext: rawptr, + timelineSemaphore: b32, } -SubpassDescription2 :: struct { - sType: StructureType, - pNext: rawptr, - flags: SubpassDescriptionFlags, - pipelineBindPoint: PipelineBindPoint, - viewMask: u32, - inputAttachmentCount: u32, - pInputAttachments: [^]AttachmentReference2, - colorAttachmentCount: u32, - pColorAttachments: [^]AttachmentReference2, - pResolveAttachments: [^]AttachmentReference2, - pDepthStencilAttachment: ^AttachmentReference2, - preserveAttachmentCount: u32, - pPreserveAttachments: [^]u32, +PhysicalDeviceTimelineSemaphoreProperties :: struct { + sType: StructureType, + pNext: rawptr, + maxTimelineSemaphoreValueDifference: u64, } -SubpassDependency2 :: struct { - sType: StructureType, - pNext: rawptr, - srcSubpass: u32, - dstSubpass: u32, - srcStageMask: PipelineStageFlags, - dstStageMask: PipelineStageFlags, - srcAccessMask: AccessFlags, - dstAccessMask: AccessFlags, - dependencyFlags: DependencyFlags, - viewOffset: i32, +SemaphoreTypeCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + semaphoreType: SemaphoreType, + initialValue: u64, } -RenderPassCreateInfo2 :: struct { - sType: StructureType, - pNext: rawptr, - flags: RenderPassCreateFlags, - attachmentCount: u32, - pAttachments: [^]AttachmentDescription2, - subpassCount: u32, - pSubpasses: [^]SubpassDescription2, - dependencyCount: u32, - pDependencies: [^]SubpassDependency2, - correlatedViewMaskCount: u32, - pCorrelatedViewMasks: [^]u32, +TimelineSemaphoreSubmitInfo :: struct { + sType: StructureType, + pNext: rawptr, + waitSemaphoreValueCount: u32, + pWaitSemaphoreValues: [^]u64, + signalSemaphoreValueCount: u32, + pSignalSemaphoreValues: [^]u64, } -SubpassBeginInfo :: struct { - sType: StructureType, - pNext: rawptr, - contents: SubpassContents, +SemaphoreWaitInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: SemaphoreWaitFlags, + semaphoreCount: u32, + pSemaphores: [^]Semaphore, + pValues: [^]u64, } -SubpassEndInfo :: struct { - sType: StructureType, - pNext: rawptr, +SemaphoreSignalInfo :: struct { + sType: StructureType, + pNext: rawptr, + semaphore: Semaphore, + value: u64, +} + +PhysicalDeviceBufferDeviceAddressFeatures :: struct { + sType: StructureType, + pNext: rawptr, + bufferDeviceAddress: b32, + bufferDeviceAddressCaptureReplay: b32, + bufferDeviceAddressMultiDevice: b32, +} + +BufferDeviceAddressInfo :: struct { + sType: StructureType, + pNext: rawptr, + buffer: Buffer, +} + +BufferOpaqueCaptureAddressCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + opaqueCaptureAddress: u64, +} + +MemoryOpaqueCaptureAddressAllocateInfo :: struct { + sType: StructureType, + pNext: rawptr, + opaqueCaptureAddress: u64, +} + +DeviceMemoryOpaqueCaptureAddressInfo :: struct { + sType: StructureType, + pNext: rawptr, + memory: DeviceMemory, } PhysicalDevice8BitStorageFeatures :: struct { @@ -1879,15 +1899,6 @@ PhysicalDevice8BitStorageFeatures :: struct { storagePushConstant8: b32, } -PhysicalDeviceDriverProperties :: struct { - sType: StructureType, - pNext: rawptr, - driverID: DriverId, - driverName: [MAX_DRIVER_NAME_SIZE]byte, - driverInfo: [MAX_DRIVER_INFO_SIZE]byte, - conformanceVersion: ConformanceVersion, -} - PhysicalDeviceShaderAtomicInt64Features :: struct { sType: StructureType, pNext: rawptr, @@ -1997,6 +2008,113 @@ DescriptorSetVariableDescriptorCountLayoutSupport :: struct { maxVariableDescriptorCount: u32, } +PhysicalDeviceScalarBlockLayoutFeatures :: struct { + sType: StructureType, + pNext: rawptr, + scalarBlockLayout: b32, +} + +SamplerReductionModeCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + reductionMode: SamplerReductionMode, +} + +PhysicalDeviceSamplerFilterMinmaxProperties :: struct { + sType: StructureType, + pNext: rawptr, + filterMinmaxSingleComponentFormats: b32, + filterMinmaxImageComponentMapping: b32, +} + +PhysicalDeviceUniformBufferStandardLayoutFeatures :: struct { + sType: StructureType, + pNext: rawptr, + uniformBufferStandardLayout: b32, +} + +PhysicalDeviceShaderSubgroupExtendedTypesFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderSubgroupExtendedTypes: b32, +} + +AttachmentDescription2 :: struct { + sType: StructureType, + pNext: rawptr, + flags: AttachmentDescriptionFlags, + format: Format, + samples: SampleCountFlags, + loadOp: AttachmentLoadOp, + storeOp: AttachmentStoreOp, + stencilLoadOp: AttachmentLoadOp, + stencilStoreOp: AttachmentStoreOp, + initialLayout: ImageLayout, + finalLayout: ImageLayout, +} + +AttachmentReference2 :: struct { + sType: StructureType, + pNext: rawptr, + attachment: u32, + layout: ImageLayout, + aspectMask: ImageAspectFlags, +} + +SubpassDescription2 :: struct { + sType: StructureType, + pNext: rawptr, + flags: SubpassDescriptionFlags, + pipelineBindPoint: PipelineBindPoint, + viewMask: u32, + inputAttachmentCount: u32, + pInputAttachments: [^]AttachmentReference2, + colorAttachmentCount: u32, + pColorAttachments: [^]AttachmentReference2, + pResolveAttachments: [^]AttachmentReference2, + pDepthStencilAttachment: ^AttachmentReference2, + preserveAttachmentCount: u32, + pPreserveAttachments: [^]u32, +} + +SubpassDependency2 :: struct { + sType: StructureType, + pNext: rawptr, + srcSubpass: u32, + dstSubpass: u32, + srcStageMask: PipelineStageFlags, + dstStageMask: PipelineStageFlags, + srcAccessMask: AccessFlags, + dstAccessMask: AccessFlags, + dependencyFlags: DependencyFlags, + viewOffset: i32, +} + +SubpassBeginInfo :: struct { + sType: StructureType, + pNext: rawptr, + contents: SubpassContents, +} + +SubpassEndInfo :: struct { + sType: StructureType, + pNext: rawptr, +} + +RenderPassCreateInfo2 :: struct { + sType: StructureType, + pNext: rawptr, + flags: RenderPassCreateFlags, + attachmentCount: u32, + pAttachments: [^]AttachmentDescription2, + subpassCount: u32, + pSubpasses: [^]SubpassDescription2, + dependencyCount: u32, + pDependencies: [^]SubpassDependency2, + correlatedViewMaskCount: u32, + pCorrelatedViewMasks: [^]u32, +} + SubpassDescriptionDepthStencilResolve :: struct { sType: StructureType, pNext: rawptr, @@ -2014,39 +2132,12 @@ PhysicalDeviceDepthStencilResolveProperties :: struct { independentResolve: b32, } -PhysicalDeviceScalarBlockLayoutFeatures :: struct { - sType: StructureType, - pNext: rawptr, - scalarBlockLayout: b32, -} - ImageStencilUsageCreateInfo :: struct { sType: StructureType, pNext: rawptr, stencilUsage: ImageUsageFlags, } -SamplerReductionModeCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - reductionMode: SamplerReductionMode, -} - -PhysicalDeviceSamplerFilterMinmaxProperties :: struct { - sType: StructureType, - pNext: rawptr, - filterMinmaxSingleComponentFormats: b32, - filterMinmaxImageComponentMapping: b32, -} - -PhysicalDeviceVulkanMemoryModelFeatures :: struct { - sType: StructureType, - pNext: rawptr, - vulkanMemoryModel: b32, - vulkanMemoryModelDeviceScope: b32, - vulkanMemoryModelAvailabilityVisibilityChains: b32, -} - PhysicalDeviceImagelessFramebufferFeatures :: struct { sType: StructureType, pNext: rawptr, @@ -2065,13 +2156,6 @@ FramebufferAttachmentImageInfo :: struct { pViewFormats: [^]Format, } -FramebufferAttachmentsCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - attachmentImageInfoCount: u32, - pAttachmentImageInfos: [^]FramebufferAttachmentImageInfo, -} - RenderPassAttachmentBeginInfo :: struct { sType: StructureType, pNext: rawptr, @@ -2079,16 +2163,11 @@ RenderPassAttachmentBeginInfo :: struct { pAttachments: [^]ImageView, } -PhysicalDeviceUniformBufferStandardLayoutFeatures :: struct { - sType: StructureType, - pNext: rawptr, - uniformBufferStandardLayout: b32, -} - -PhysicalDeviceShaderSubgroupExtendedTypesFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderSubgroupExtendedTypes: b32, +FramebufferAttachmentsCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + attachmentImageInfoCount: u32, + pAttachmentImageInfos: [^]FramebufferAttachmentImageInfo, } PhysicalDeviceSeparateDepthStencilLayoutsFeatures :: struct { @@ -2110,88 +2189,6 @@ AttachmentDescriptionStencilLayout :: struct { stencilFinalLayout: ImageLayout, } -PhysicalDeviceHostQueryResetFeatures :: struct { - sType: StructureType, - pNext: rawptr, - hostQueryReset: b32, -} - -PhysicalDeviceTimelineSemaphoreFeatures :: struct { - sType: StructureType, - pNext: rawptr, - timelineSemaphore: b32, -} - -PhysicalDeviceTimelineSemaphoreProperties :: struct { - sType: StructureType, - pNext: rawptr, - maxTimelineSemaphoreValueDifference: u64, -} - -SemaphoreTypeCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - semaphoreType: SemaphoreType, - initialValue: u64, -} - -TimelineSemaphoreSubmitInfo :: struct { - sType: StructureType, - pNext: rawptr, - waitSemaphoreValueCount: u32, - pWaitSemaphoreValues: [^]u64, - signalSemaphoreValueCount: u32, - pSignalSemaphoreValues: [^]u64, -} - -SemaphoreWaitInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: SemaphoreWaitFlags, - semaphoreCount: u32, - pSemaphores: [^]Semaphore, - pValues: [^]u64, -} - -SemaphoreSignalInfo :: struct { - sType: StructureType, - pNext: rawptr, - semaphore: Semaphore, - value: u64, -} - -PhysicalDeviceBufferDeviceAddressFeatures :: struct { - sType: StructureType, - pNext: rawptr, - bufferDeviceAddress: b32, - bufferDeviceAddressCaptureReplay: b32, - bufferDeviceAddressMultiDevice: b32, -} - -BufferDeviceAddressInfo :: struct { - sType: StructureType, - pNext: rawptr, - buffer: Buffer, -} - -BufferOpaqueCaptureAddressCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - opaqueCaptureAddress: u64, -} - -MemoryOpaqueCaptureAddressAllocateInfo :: struct { - sType: StructureType, - pNext: rawptr, - opaqueCaptureAddress: u64, -} - -DeviceMemoryOpaqueCaptureAddressInfo :: struct { - sType: StructureType, - pNext: rawptr, - memory: DeviceMemory, -} - PhysicalDeviceVulkan13Features :: struct { sType: StructureType, pNext: rawptr, @@ -2262,25 +2259,6 @@ PhysicalDeviceVulkan13Properties :: struct { maxBufferSize: DeviceSize, } -PipelineCreationFeedback :: struct { - flags: PipelineCreationFeedbackFlags, - duration: u64, -} - -PipelineCreationFeedbackCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - pPipelineCreationFeedback: ^PipelineCreationFeedback, - pipelineStageCreationFeedbackCount: u32, - pPipelineStageCreationFeedbacks: [^]PipelineCreationFeedback, -} - -PhysicalDeviceShaderTerminateInvocationFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderTerminateInvocation: b32, -} - PhysicalDeviceToolProperties :: struct { sType: StructureType, pNext: rawptr, @@ -2291,12 +2269,6 @@ PhysicalDeviceToolProperties :: struct { layer: [MAX_EXTENSION_NAME_SIZE]byte, } -PhysicalDeviceShaderDemoteToHelperInvocationFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderDemoteToHelperInvocation: b32, -} - PhysicalDevicePrivateDataFeatures :: struct { sType: StructureType, pNext: rawptr, @@ -2315,12 +2287,6 @@ PrivateDataSlotCreateInfo :: struct { flags: PrivateDataSlotCreateFlags, } -PhysicalDevicePipelineCreationCacheControlFeatures :: struct { - sType: StructureType, - pNext: rawptr, - pipelineCreationCacheControl: b32, -} - MemoryBarrier2 :: struct { sType: StructureType, pNext: rawptr, @@ -2405,18 +2371,6 @@ PhysicalDeviceSynchronization2Features :: struct { synchronization2: b32, } -PhysicalDeviceZeroInitializeWorkgroupMemoryFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderZeroInitializeWorkgroupMemory: b32, -} - -PhysicalDeviceImageRobustnessFeatures :: struct { - sType: StructureType, - pNext: rawptr, - robustImageAccess: b32, -} - BufferCopy2 :: struct { sType: StructureType, pNext: rawptr, @@ -2486,46 +2440,86 @@ CopyImageToBufferInfo2 :: struct { pRegions: [^]BufferImageCopy2, } -ImageBlit2 :: struct { - sType: StructureType, - pNext: rawptr, - srcSubresource: ImageSubresourceLayers, - srcOffsets: [2]Offset3D, - dstSubresource: ImageSubresourceLayers, - dstOffsets: [2]Offset3D, +PhysicalDeviceTextureCompressionASTCHDRFeatures :: struct { + sType: StructureType, + pNext: rawptr, + textureCompressionASTC_HDR: b32, } -BlitImageInfo2 :: struct { - sType: StructureType, - pNext: rawptr, - srcImage: Image, - srcImageLayout: ImageLayout, - dstImage: Image, - dstImageLayout: ImageLayout, - regionCount: u32, - pRegions: [^]ImageBlit2, - filter: Filter, +FormatProperties3 :: struct { + sType: StructureType, + pNext: rawptr, + linearTilingFeatures: FormatFeatureFlags2, + optimalTilingFeatures: FormatFeatureFlags2, + bufferFeatures: FormatFeatureFlags2, } -ImageResolve2 :: struct { - sType: StructureType, - pNext: rawptr, - srcSubresource: ImageSubresourceLayers, - srcOffset: Offset3D, - dstSubresource: ImageSubresourceLayers, - dstOffset: Offset3D, - extent: Extent3D, +PhysicalDeviceMaintenance4Features :: struct { + sType: StructureType, + pNext: rawptr, + maintenance4: b32, } -ResolveImageInfo2 :: struct { - sType: StructureType, - pNext: rawptr, - srcImage: Image, - srcImageLayout: ImageLayout, - dstImage: Image, - dstImageLayout: ImageLayout, - regionCount: u32, - pRegions: [^]ImageResolve2, +PhysicalDeviceMaintenance4Properties :: struct { + sType: StructureType, + pNext: rawptr, + maxBufferSize: DeviceSize, +} + +DeviceBufferMemoryRequirements :: struct { + sType: StructureType, + pNext: rawptr, + pCreateInfo: ^BufferCreateInfo, +} + +DeviceImageMemoryRequirements :: struct { + sType: StructureType, + pNext: rawptr, + pCreateInfo: ^ImageCreateInfo, + planeAspect: ImageAspectFlags, +} + +PipelineCreationFeedback :: struct { + flags: PipelineCreationFeedbackFlags, + duration: u64, +} + +PipelineCreationFeedbackCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + pPipelineCreationFeedback: ^PipelineCreationFeedback, + pipelineStageCreationFeedbackCount: u32, + pPipelineStageCreationFeedbacks: [^]PipelineCreationFeedback, +} + +PhysicalDeviceShaderTerminateInvocationFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderTerminateInvocation: b32, +} + +PhysicalDeviceShaderDemoteToHelperInvocationFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderDemoteToHelperInvocation: b32, +} + +PhysicalDevicePipelineCreationCacheControlFeatures :: struct { + sType: StructureType, + pNext: rawptr, + pipelineCreationCacheControl: b32, +} + +PhysicalDeviceZeroInitializeWorkgroupMemoryFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderZeroInitializeWorkgroupMemory: b32, +} + +PhysicalDeviceImageRobustnessFeatures :: struct { + sType: StructureType, + pNext: rawptr, + robustImageAccess: b32, } PhysicalDeviceSubgroupSizeControlFeatures :: struct { @@ -2580,10 +2574,96 @@ DescriptorPoolInlineUniformBlockCreateInfo :: struct { maxInlineUniformBlockBindings: u32, } -PhysicalDeviceTextureCompressionASTCHDRFeatures :: struct { - sType: StructureType, - pNext: rawptr, - textureCompressionASTC_HDR: b32, +PhysicalDeviceShaderIntegerDotProductFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderIntegerDotProduct: b32, +} + +PhysicalDeviceShaderIntegerDotProductProperties :: struct { + sType: StructureType, + pNext: rawptr, + integerDotProduct8BitUnsignedAccelerated: b32, + integerDotProduct8BitSignedAccelerated: b32, + integerDotProduct8BitMixedSignednessAccelerated: b32, + integerDotProduct4x8BitPackedUnsignedAccelerated: b32, + integerDotProduct4x8BitPackedSignedAccelerated: b32, + integerDotProduct4x8BitPackedMixedSignednessAccelerated: b32, + integerDotProduct16BitUnsignedAccelerated: b32, + integerDotProduct16BitSignedAccelerated: b32, + integerDotProduct16BitMixedSignednessAccelerated: b32, + integerDotProduct32BitUnsignedAccelerated: b32, + integerDotProduct32BitSignedAccelerated: b32, + integerDotProduct32BitMixedSignednessAccelerated: b32, + integerDotProduct64BitUnsignedAccelerated: b32, + integerDotProduct64BitSignedAccelerated: b32, + integerDotProduct64BitMixedSignednessAccelerated: b32, + integerDotProductAccumulatingSaturating8BitUnsignedAccelerated: b32, + integerDotProductAccumulatingSaturating8BitSignedAccelerated: b32, + integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated: b32, + integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated: b32, + integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated: b32, + integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated: b32, + integerDotProductAccumulatingSaturating16BitUnsignedAccelerated: b32, + integerDotProductAccumulatingSaturating16BitSignedAccelerated: b32, + integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated: b32, + integerDotProductAccumulatingSaturating32BitUnsignedAccelerated: b32, + integerDotProductAccumulatingSaturating32BitSignedAccelerated: b32, + integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated: b32, + integerDotProductAccumulatingSaturating64BitUnsignedAccelerated: b32, + integerDotProductAccumulatingSaturating64BitSignedAccelerated: b32, + integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated: b32, +} + +PhysicalDeviceTexelBufferAlignmentProperties :: struct { + sType: StructureType, + pNext: rawptr, + storageTexelBufferOffsetAlignmentBytes: DeviceSize, + storageTexelBufferOffsetSingleTexelAlignment: b32, + uniformTexelBufferOffsetAlignmentBytes: DeviceSize, + uniformTexelBufferOffsetSingleTexelAlignment: b32, +} + +ImageBlit2 :: struct { + sType: StructureType, + pNext: rawptr, + srcSubresource: ImageSubresourceLayers, + srcOffsets: [2]Offset3D, + dstSubresource: ImageSubresourceLayers, + dstOffsets: [2]Offset3D, +} + +BlitImageInfo2 :: struct { + sType: StructureType, + pNext: rawptr, + srcImage: Image, + srcImageLayout: ImageLayout, + dstImage: Image, + dstImageLayout: ImageLayout, + regionCount: u32, + pRegions: [^]ImageBlit2, + filter: Filter, +} + +ImageResolve2 :: struct { + sType: StructureType, + pNext: rawptr, + srcSubresource: ImageSubresourceLayers, + srcOffset: Offset3D, + dstSubresource: ImageSubresourceLayers, + dstOffset: Offset3D, + extent: Extent3D, +} + +ResolveImageInfo2 :: struct { + sType: StructureType, + pNext: rawptr, + srcImage: Image, + srcImageLayout: ImageLayout, + dstImage: Image, + dstImageLayout: ImageLayout, + regionCount: u32, + pRegions: [^]ImageResolve2, } RenderingAttachmentInfo :: struct { @@ -2640,89 +2720,6 @@ CommandBufferInheritanceRenderingInfo :: struct { rasterizationSamples: SampleCountFlags, } -PhysicalDeviceShaderIntegerDotProductFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderIntegerDotProduct: b32, -} - -PhysicalDeviceShaderIntegerDotProductProperties :: struct { - sType: StructureType, - pNext: rawptr, - integerDotProduct8BitUnsignedAccelerated: b32, - integerDotProduct8BitSignedAccelerated: b32, - integerDotProduct8BitMixedSignednessAccelerated: b32, - integerDotProduct4x8BitPackedUnsignedAccelerated: b32, - integerDotProduct4x8BitPackedSignedAccelerated: b32, - integerDotProduct4x8BitPackedMixedSignednessAccelerated: b32, - integerDotProduct16BitUnsignedAccelerated: b32, - integerDotProduct16BitSignedAccelerated: b32, - integerDotProduct16BitMixedSignednessAccelerated: b32, - integerDotProduct32BitUnsignedAccelerated: b32, - integerDotProduct32BitSignedAccelerated: b32, - integerDotProduct32BitMixedSignednessAccelerated: b32, - integerDotProduct64BitUnsignedAccelerated: b32, - integerDotProduct64BitSignedAccelerated: b32, - integerDotProduct64BitMixedSignednessAccelerated: b32, - integerDotProductAccumulatingSaturating8BitUnsignedAccelerated: b32, - integerDotProductAccumulatingSaturating8BitSignedAccelerated: b32, - integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated: b32, - integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated: b32, - integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated: b32, - integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated: b32, - integerDotProductAccumulatingSaturating16BitUnsignedAccelerated: b32, - integerDotProductAccumulatingSaturating16BitSignedAccelerated: b32, - integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated: b32, - integerDotProductAccumulatingSaturating32BitUnsignedAccelerated: b32, - integerDotProductAccumulatingSaturating32BitSignedAccelerated: b32, - integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated: b32, - integerDotProductAccumulatingSaturating64BitUnsignedAccelerated: b32, - integerDotProductAccumulatingSaturating64BitSignedAccelerated: b32, - integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated: b32, -} - -PhysicalDeviceTexelBufferAlignmentProperties :: struct { - sType: StructureType, - pNext: rawptr, - storageTexelBufferOffsetAlignmentBytes: DeviceSize, - storageTexelBufferOffsetSingleTexelAlignment: b32, - uniformTexelBufferOffsetAlignmentBytes: DeviceSize, - uniformTexelBufferOffsetSingleTexelAlignment: b32, -} - -FormatProperties3 :: struct { - sType: StructureType, - pNext: rawptr, - linearTilingFeatures: FormatFeatureFlags2, - optimalTilingFeatures: FormatFeatureFlags2, - bufferFeatures: FormatFeatureFlags2, -} - -PhysicalDeviceMaintenance4Features :: struct { - sType: StructureType, - pNext: rawptr, - maintenance4: b32, -} - -PhysicalDeviceMaintenance4Properties :: struct { - sType: StructureType, - pNext: rawptr, - maxBufferSize: DeviceSize, -} - -DeviceBufferMemoryRequirements :: struct { - sType: StructureType, - pNext: rawptr, - pCreateInfo: ^BufferCreateInfo, -} - -DeviceImageMemoryRequirements :: struct { - sType: StructureType, - pNext: rawptr, - pCreateInfo: ^ImageCreateInfo, - planeAspect: ImageAspectFlags, -} - PhysicalDeviceVulkan14Features :: struct { sType: StructureType, pNext: rawptr, @@ -2798,77 +2795,6 @@ QueueFamilyGlobalPriorityProperties :: struct { priorities: [MAX_GLOBAL_PRIORITY_SIZE]QueueGlobalPriority, } -PhysicalDeviceShaderSubgroupRotateFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderSubgroupRotate: b32, - shaderSubgroupRotateClustered: b32, -} - -PhysicalDeviceShaderFloatControls2Features :: struct { - sType: StructureType, - pNext: rawptr, - shaderFloatControls2: b32, -} - -PhysicalDeviceShaderExpectAssumeFeatures :: struct { - sType: StructureType, - pNext: rawptr, - shaderExpectAssume: b32, -} - -PhysicalDeviceLineRasterizationFeatures :: struct { - sType: StructureType, - pNext: rawptr, - rectangularLines: b32, - bresenhamLines: b32, - smoothLines: b32, - stippledRectangularLines: b32, - stippledBresenhamLines: b32, - stippledSmoothLines: b32, -} - -PhysicalDeviceLineRasterizationProperties :: struct { - sType: StructureType, - pNext: rawptr, - lineSubPixelPrecisionBits: u32, -} - -PipelineRasterizationLineStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - lineRasterizationMode: LineRasterizationMode, - stippledLineEnable: b32, - lineStippleFactor: u32, - lineStipplePattern: u16, -} - -PhysicalDeviceVertexAttributeDivisorProperties :: struct { - sType: StructureType, - pNext: rawptr, - maxVertexAttribDivisor: u32, - supportsNonZeroFirstInstance: b32, -} - -VertexInputBindingDivisorDescription :: struct { - binding: u32, - divisor: u32, -} - -PipelineVertexInputDivisorStateCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - vertexBindingDivisorCount: u32, - pVertexBindingDivisors: [^]VertexInputBindingDivisorDescription, -} - -PhysicalDeviceVertexAttributeDivisorFeatures :: struct { - sType: StructureType, - pNext: rawptr, - vertexAttributeInstanceRateDivisor: b32, - vertexAttributeInstanceRateZeroDivisor: b32, -} - PhysicalDeviceIndexTypeUint8Features :: struct { sType: StructureType, pNext: rawptr, @@ -2908,14 +2834,10 @@ PhysicalDeviceMaintenance5Properties :: struct { nonStrictWideLinesUseParallelogram: b32, } -RenderingAreaInfo :: struct { - sType: StructureType, - pNext: rawptr, - viewMask: u32, - colorAttachmentCount: u32, - pColorAttachmentFormats: [^]Format, - depthAttachmentFormat: Format, - stencilAttachmentFormat: Format, +SubresourceLayout2 :: struct { + sType: StructureType, + pNext: rawptr, + subresourceLayout: SubresourceLayout, } ImageSubresource2 :: struct { @@ -2931,52 +2853,12 @@ DeviceImageSubresourceInfo :: struct { pSubresource: ^ImageSubresource2, } -SubresourceLayout2 :: struct { - sType: StructureType, - pNext: rawptr, - subresourceLayout: SubresourceLayout, -} - -PipelineCreateFlags2CreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - flags: PipelineCreateFlags2, -} - BufferUsageFlags2CreateInfo :: struct { sType: StructureType, pNext: rawptr, usage: BufferUsageFlags2, } -PhysicalDevicePushDescriptorProperties :: struct { - sType: StructureType, - pNext: rawptr, - maxPushDescriptors: u32, -} - -PhysicalDeviceDynamicRenderingLocalReadFeatures :: struct { - sType: StructureType, - pNext: rawptr, - dynamicRenderingLocalRead: b32, -} - -RenderingAttachmentLocationInfo :: struct { - sType: StructureType, - pNext: rawptr, - colorAttachmentCount: u32, - pColorAttachmentLocations: [^]u32, -} - -RenderingInputAttachmentIndexInfo :: struct { - sType: StructureType, - pNext: rawptr, - colorAttachmentCount: u32, - pColorAttachmentInputIndices: [^]u32, - pDepthInputAttachmentIndex: ^u32, - pStencilInputAttachmentIndex: ^u32, -} - PhysicalDeviceMaintenance6Features :: struct { sType: StructureType, pNext: rawptr, @@ -2997,77 +2879,6 @@ BindMemoryStatus :: struct { pResult: ^Result, } -BindDescriptorSetsInfo :: struct { - sType: StructureType, - pNext: rawptr, - stageFlags: ShaderStageFlags, - layout: PipelineLayout, - firstSet: u32, - descriptorSetCount: u32, - pDescriptorSets: [^]DescriptorSet, - dynamicOffsetCount: u32, - pDynamicOffsets: [^]u32, -} - -PushConstantsInfo :: struct { - sType: StructureType, - pNext: rawptr, - layout: PipelineLayout, - stageFlags: ShaderStageFlags, - offset: u32, - size: u32, - pValues: rawptr, -} - -PushDescriptorSetInfo :: struct { - sType: StructureType, - pNext: rawptr, - stageFlags: ShaderStageFlags, - layout: PipelineLayout, - set: u32, - descriptorWriteCount: u32, - pDescriptorWrites: [^]WriteDescriptorSet, -} - -PushDescriptorSetWithTemplateInfo :: struct { - sType: StructureType, - pNext: rawptr, - descriptorUpdateTemplate: DescriptorUpdateTemplate, - layout: PipelineLayout, - set: u32, - pData: rawptr, -} - -PhysicalDevicePipelineProtectedAccessFeatures :: struct { - sType: StructureType, - pNext: rawptr, - pipelineProtectedAccess: b32, -} - -PhysicalDevicePipelineRobustnessFeatures :: struct { - sType: StructureType, - pNext: rawptr, - pipelineRobustness: b32, -} - -PhysicalDevicePipelineRobustnessProperties :: struct { - sType: StructureType, - pNext: rawptr, - defaultRobustnessStorageBuffers: PipelineRobustnessBufferBehavior, - defaultRobustnessUniformBuffers: PipelineRobustnessBufferBehavior, - defaultRobustnessVertexInputs: PipelineRobustnessBufferBehavior, - defaultRobustnessImages: PipelineRobustnessImageBehavior, -} - -PipelineRobustnessCreateInfo :: struct { - sType: StructureType, - pNext: rawptr, - storageBuffers: PipelineRobustnessBufferBehavior, - uniformBuffers: PipelineRobustnessBufferBehavior, - vertexInputs: PipelineRobustnessBufferBehavior, - images: PipelineRobustnessImageBehavior, -} - PhysicalDeviceHostImageCopyFeatures :: struct { sType: StructureType, pNext: rawptr, @@ -3161,6 +2972,192 @@ HostImageCopyDevicePerformanceQuery :: struct { identicalMemoryLayout: b32, } +PhysicalDeviceShaderSubgroupRotateFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderSubgroupRotate: b32, + shaderSubgroupRotateClustered: b32, +} + +PhysicalDeviceShaderFloatControls2Features :: struct { + sType: StructureType, + pNext: rawptr, + shaderFloatControls2: b32, +} + +PhysicalDeviceShaderExpectAssumeFeatures :: struct { + sType: StructureType, + pNext: rawptr, + shaderExpectAssume: b32, +} + +PipelineCreateFlags2CreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineCreateFlags2, +} + +PhysicalDevicePushDescriptorProperties :: struct { + sType: StructureType, + pNext: rawptr, + maxPushDescriptors: u32, +} + +BindDescriptorSetsInfo :: struct { + sType: StructureType, + pNext: rawptr, + stageFlags: ShaderStageFlags, + layout: PipelineLayout, + firstSet: u32, + descriptorSetCount: u32, + pDescriptorSets: [^]DescriptorSet, + dynamicOffsetCount: u32, + pDynamicOffsets: [^]u32, +} + +PushConstantsInfo :: struct { + sType: StructureType, + pNext: rawptr, + layout: PipelineLayout, + stageFlags: ShaderStageFlags, + offset: u32, + size: u32, + pValues: rawptr, +} + +PushDescriptorSetInfo :: struct { + sType: StructureType, + pNext: rawptr, + stageFlags: ShaderStageFlags, + layout: PipelineLayout, + set: u32, + descriptorWriteCount: u32, + pDescriptorWrites: [^]WriteDescriptorSet, +} + +PushDescriptorSetWithTemplateInfo :: struct { + sType: StructureType, + pNext: rawptr, + descriptorUpdateTemplate: DescriptorUpdateTemplate, + layout: PipelineLayout, + set: u32, + pData: rawptr, +} + +PhysicalDevicePipelineProtectedAccessFeatures :: struct { + sType: StructureType, + pNext: rawptr, + pipelineProtectedAccess: b32, +} + +PhysicalDevicePipelineRobustnessFeatures :: struct { + sType: StructureType, + pNext: rawptr, + pipelineRobustness: b32, +} + +PhysicalDevicePipelineRobustnessProperties :: struct { + sType: StructureType, + pNext: rawptr, + defaultRobustnessStorageBuffers: PipelineRobustnessBufferBehavior, + defaultRobustnessUniformBuffers: PipelineRobustnessBufferBehavior, + defaultRobustnessVertexInputs: PipelineRobustnessBufferBehavior, + defaultRobustnessImages: PipelineRobustnessImageBehavior, +} + +PipelineRobustnessCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + storageBuffers: PipelineRobustnessBufferBehavior, + uniformBuffers: PipelineRobustnessBufferBehavior, + vertexInputs: PipelineRobustnessBufferBehavior, + images: PipelineRobustnessImageBehavior, +} + +PhysicalDeviceLineRasterizationFeatures :: struct { + sType: StructureType, + pNext: rawptr, + rectangularLines: b32, + bresenhamLines: b32, + smoothLines: b32, + stippledRectangularLines: b32, + stippledBresenhamLines: b32, + stippledSmoothLines: b32, +} + +PhysicalDeviceLineRasterizationProperties :: struct { + sType: StructureType, + pNext: rawptr, + lineSubPixelPrecisionBits: u32, +} + +PipelineRasterizationLineStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + lineRasterizationMode: LineRasterizationMode, + stippledLineEnable: b32, + lineStippleFactor: u32, + lineStipplePattern: u16, +} + +PhysicalDeviceVertexAttributeDivisorProperties :: struct { + sType: StructureType, + pNext: rawptr, + maxVertexAttribDivisor: u32, + supportsNonZeroFirstInstance: b32, +} + +VertexInputBindingDivisorDescription :: struct { + binding: u32, + divisor: u32, +} + +PipelineVertexInputDivisorStateCreateInfo :: struct { + sType: StructureType, + pNext: rawptr, + vertexBindingDivisorCount: u32, + pVertexBindingDivisors: [^]VertexInputBindingDivisorDescription, +} + +PhysicalDeviceVertexAttributeDivisorFeatures :: struct { + sType: StructureType, + pNext: rawptr, + vertexAttributeInstanceRateDivisor: b32, + vertexAttributeInstanceRateZeroDivisor: b32, +} + +RenderingAreaInfo :: struct { + sType: StructureType, + pNext: rawptr, + viewMask: u32, + colorAttachmentCount: u32, + pColorAttachmentFormats: [^]Format, + depthAttachmentFormat: Format, + stencilAttachmentFormat: Format, +} + +PhysicalDeviceDynamicRenderingLocalReadFeatures :: struct { + sType: StructureType, + pNext: rawptr, + dynamicRenderingLocalRead: b32, +} + +RenderingAttachmentLocationInfo :: struct { + sType: StructureType, + pNext: rawptr, + colorAttachmentCount: u32, + pColorAttachmentLocations: [^]u32, +} + +RenderingInputAttachmentIndexInfo :: struct { + sType: StructureType, + pNext: rawptr, + colorAttachmentCount: u32, + pColorAttachmentInputIndices: [^]u32, + pDepthInputAttachmentIndex: ^u32, + pStencilInputAttachmentIndex: ^u32, +} + SurfaceCapabilitiesKHR :: struct { minImageCount: u32, maxImageCount: u32, @@ -4008,6 +4005,14 @@ DisplayPlaneCapabilities2KHR :: struct { capabilities: DisplayPlaneCapabilitiesKHR, } +PhysicalDeviceShaderBfloat16FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + shaderBFloat16Type: b32, + shaderBFloat16DotProduct: b32, + shaderBFloat16CooperativeMatrix: b32, +} + PhysicalDeviceShaderClockFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4120,6 +4125,31 @@ RenderingFragmentShadingRateAttachmentInfoKHR :: struct { shadingRateAttachmentTexelSize: Extent2D, } +PhysicalDeviceShaderConstantDataFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + shaderConstantData: b32, +} + +PhysicalDeviceShaderAbortFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + shaderAbort: b32, +} + +DeviceFaultShaderAbortMessageInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + messageDataSize: u64, + pMessageData: rawptr, +} + +PhysicalDeviceShaderAbortPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxShaderAbortMessageSize: u64, +} + PhysicalDeviceShaderQuadControlFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4304,6 +4334,154 @@ VideoEncodeSessionParametersFeedbackInfoKHR :: struct { hasOverrides: b32, } +DeviceAddressRangeKHR :: struct { + address: DeviceAddress, + size: DeviceSize, +} + +StridedDeviceAddressRangeKHR :: struct { + address: DeviceAddress, + size: DeviceSize, + stride: DeviceSize, +} + +DeviceMemoryCopyKHR :: struct { + sType: StructureType, + pNext: rawptr, + srcRange: DeviceAddressRangeKHR, + srcFlags: AddressCommandFlagsKHR, + dstRange: DeviceAddressRangeKHR, + dstFlags: AddressCommandFlagsKHR, +} + +CopyDeviceMemoryInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + regionCount: u32, + pRegions: [^]DeviceMemoryCopyKHR, +} + +DeviceMemoryImageCopyKHR :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + addressRowLength: u32, + addressImageHeight: u32, + imageSubresource: ImageSubresourceLayers, + imageLayout: ImageLayout, + imageOffset: Offset3D, + imageExtent: Extent3D, +} + +CopyDeviceMemoryImageInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + image: Image, + regionCount: u32, + pRegions: [^]DeviceMemoryImageCopyKHR, +} + +MemoryRangeBarrierKHR :: struct { + sType: StructureType, + pNext: rawptr, + srcStageMask: PipelineStageFlags2, + srcAccessMask: AccessFlags2, + dstStageMask: PipelineStageFlags2, + dstAccessMask: AccessFlags2, + srcQueueFamilyIndex: u32, + dstQueueFamilyIndex: u32, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, +} + +MemoryRangeBarriersInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + memoryRangeBarrierCount: u32, + pMemoryRangeBarriers: [^]MemoryRangeBarrierKHR, +} + +PhysicalDeviceDeviceAddressCommandsFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + deviceAddressCommands: b32, +} + +BindIndexBuffer3InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + indexType: IndexType, +} + +BindVertexBuffer3InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + setStride: b32, + addressRange: StridedDeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, +} + +DrawIndirect2InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: StridedDeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + drawCount: u32, +} + +DrawIndirectCount2InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: StridedDeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + countAddressRange: DeviceAddressRangeKHR, + countAddressFlags: AddressCommandFlagsKHR, + maxDrawCount: u32, +} + +DispatchIndirect2InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, +} + +ConditionalRenderingBeginInfo2EXT :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + flags: ConditionalRenderingFlagsEXT, +} + +BindTransformFeedbackBuffer2InfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, +} + +MemoryMarkerInfoAMD :: struct { + sType: StructureType, + pNext: rawptr, + stage: PipelineStageFlags2KHR, + dstRange: DeviceAddressRangeKHR, + dstFlags: AddressCommandFlagsKHR, + marker: u32, +} + +AccelerationStructureCreateInfo2KHR :: struct { + sType: StructureType, + pNext: rawptr, + createFlags: AccelerationStructureCreateFlagsKHR, + addressRange: DeviceAddressRangeKHR, + addressFlags: AddressCommandFlagsKHR, + type: AccelerationStructureTypeKHR, +} + PhysicalDeviceFragmentShaderBarycentricFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4355,12 +4533,56 @@ TraceRaysIndirectCommand2KHR :: struct { depth: u32, } +PhysicalDeviceShaderUntypedPointersFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + shaderUntypedPointers: b32, +} + PhysicalDeviceShaderMaximalReconvergenceFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, shaderMaximalReconvergence: b32, } +SurfaceCapabilitiesPresentId2KHR :: struct { + sType: StructureType, + pNext: rawptr, + presentId2Supported: b32, +} + +PresentId2KHR :: struct { + sType: StructureType, + pNext: rawptr, + swapchainCount: u32, + pPresentIds: [^]u64, +} + +PhysicalDevicePresentId2FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentId2: b32, +} + +SurfaceCapabilitiesPresentWait2KHR :: struct { + sType: StructureType, + pNext: rawptr, + presentWait2Supported: b32, +} + +PhysicalDevicePresentWait2FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentWait2: b32, +} + +PresentWait2InfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentId: u64, + timeout: u64, +} + PhysicalDeviceRayTracingPositionFetchFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4446,6 +4668,78 @@ PipelineBinaryHandlesInfoKHR :: struct { pPipelineBinaries: [^]PipelineBinaryKHR, } +SurfacePresentModeKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentMode: PresentModeKHR, +} + +SurfacePresentScalingCapabilitiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + supportedPresentScaling: PresentScalingFlagsKHR, + supportedPresentGravityX: PresentGravityFlagsKHR, + supportedPresentGravityY: PresentGravityFlagsKHR, + minScaledImageExtent: Extent2D, + maxScaledImageExtent: Extent2D, +} + +SurfacePresentModeCompatibilityKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentModeCount: u32, + pPresentModes: [^]PresentModeKHR, +} + +PhysicalDeviceSwapchainMaintenance1FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + swapchainMaintenance1: b32, +} + +SwapchainPresentFenceInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + swapchainCount: u32, + pFences: [^]Fence, +} + +SwapchainPresentModesCreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentModeCount: u32, + pPresentModes: [^]PresentModeKHR, +} + +SwapchainPresentModeInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + swapchainCount: u32, + pPresentModes: [^]PresentModeKHR, +} + +SwapchainPresentScalingCreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + scalingBehavior: PresentScalingFlagsKHR, + presentGravityX: PresentGravityFlagsKHR, + presentGravityY: PresentGravityFlagsKHR, +} + +ReleaseSwapchainImagesInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + swapchain: SwapchainKHR, + imageIndexCount: u32, + pImageIndices: [^]u32, +} + +PhysicalDeviceInternallySynchronizedQueuesFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + internallySynchronizedQueues: b32, +} + CooperativeMatrixPropertiesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4659,6 +4953,34 @@ VideoEncodeAV1RateControlLayerInfoKHR :: struct { maxFrameSize: VideoEncodeAV1FrameSizeKHR, } +PhysicalDeviceVideoDecodeVP9FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + videoDecodeVP9: b32, +} + +VideoDecodeVP9ProfileInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + stdProfile: VideoVP9Profile, +} + +VideoDecodeVP9CapabilitiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxLevel: VideoVP9Level, +} + +VideoDecodeVP9PictureInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + pStdPictureInfo: ^VideoDecodeVP9PictureInfo, + referenceNameSlotIndices: [MAX_VIDEO_VP9_REFERENCES_PER_FRAME_KHR]i32, + uncompressedHeaderOffset: u32, + compressedHeaderOffset: u32, + tilesOffset: u32, +} + PhysicalDeviceVideoMaintenance1FeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4673,6 +4995,19 @@ VideoInlineQueryInfoKHR :: struct { queryCount: u32, } +PhysicalDeviceUnifiedImageLayoutsFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + unifiedImageLayouts: b32, + unifiedImageLayoutsVideo: b32, +} + +AttachmentFeedbackLoopInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + feedbackLoopEnable: b32, +} + CalibratedTimestampInfoKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4698,6 +5033,89 @@ BindDescriptorBufferEmbeddedSamplersInfoEXT :: struct { set: u32, } +CopyMemoryIndirectCommandKHR :: struct { + srcAddress: DeviceAddress, + dstAddress: DeviceAddress, + size: DeviceSize, +} + +CopyMemoryIndirectInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + srcCopyFlags: AddressCopyFlagsKHR, + dstCopyFlags: AddressCopyFlagsKHR, + copyCount: u32, + copyAddressRange: StridedDeviceAddressRangeKHR, +} + +CopyMemoryToImageIndirectCommandKHR :: struct { + srcAddress: DeviceAddress, + bufferRowLength: u32, + bufferImageHeight: u32, + imageSubresource: ImageSubresourceLayers, + imageOffset: Offset3D, + imageExtent: Extent3D, +} + +CopyMemoryToImageIndirectInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + srcCopyFlags: AddressCopyFlagsKHR, + copyCount: u32, + copyAddressRange: StridedDeviceAddressRangeKHR, + dstImage: Image, + dstImageLayout: ImageLayout, + pImageSubresources: [^]ImageSubresourceLayers, +} + +PhysicalDeviceCopyMemoryIndirectFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + indirectMemoryCopy: b32, + indirectMemoryToImageCopy: b32, +} + +PhysicalDeviceCopyMemoryIndirectPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + supportedQueues: QueueFlags, +} + +VideoEncodeIntraRefreshCapabilitiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + intraRefreshModes: VideoEncodeIntraRefreshModeFlagsKHR, + maxIntraRefreshCycleDuration: u32, + maxIntraRefreshActiveReferencePictures: u32, + partitionIndependentIntraRefreshRegions: b32, + nonRectangularIntraRefreshRegions: b32, +} + +VideoEncodeSessionIntraRefreshCreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + intraRefreshMode: VideoEncodeIntraRefreshModeFlagsKHR, +} + +VideoEncodeIntraRefreshInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + intraRefreshCycleDuration: u32, + intraRefreshIndex: u32, +} + +VideoReferenceIntraRefreshInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + dirtyIntraRefreshRegions: u32, +} + +PhysicalDeviceVideoEncodeIntraRefreshFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + videoEncodeIntraRefresh: b32, +} + VideoEncodeQuantizationMapCapabilitiesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4809,10 +5227,63 @@ PhysicalDeviceLayeredApiVulkanPropertiesKHR :: struct { properties: PhysicalDeviceProperties2, } -PhysicalDeviceMaintenance8FeaturesKHR :: struct { - sType: StructureType, - pNext: rawptr, - maintenance8: b32, +PhysicalDeviceFaultFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + deviceFault: b32, + deviceFaultVendorBinary: b32, + deviceFaultReportMasked: b32, + deviceFaultDeviceLostOnMasked: b32, +} + +PhysicalDeviceFaultPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxDeviceFaultCount: u32, +} + +DeviceFaultAddressInfoKHR :: struct { + addressType: DeviceFaultAddressTypeKHR, + reportedAddress: DeviceAddress, + addressPrecision: DeviceSize, +} + +DeviceFaultVendorInfoKHR :: struct { + description: [MAX_DESCRIPTION_SIZE]byte, + vendorFaultCode: u64, + vendorFaultData: u64, +} + +DeviceFaultInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + flags: DeviceFaultFlagsKHR, + groupId: u64, + description: [MAX_DESCRIPTION_SIZE]byte, + faultAddressInfo: DeviceFaultAddressInfoKHR, + instructionAddressInfo: DeviceFaultAddressInfoKHR, + vendorInfo: DeviceFaultVendorInfoKHR, +} + +DeviceFaultDebugInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + vendorBinarySize: u32, + pVendorBinaryData: rawptr, +} + +DeviceFaultVendorBinaryHeaderVersionOneKHR :: struct { + headerSize: u32, + headerVersion: DeviceFaultVendorBinaryHeaderVersionKHR, + vendorID: u32, + deviceID: u32, + driverVersion: u32, + pipelineCacheUUID: [UUID_SIZE]u8, + applicationNameOffset: u32, + applicationVersion: u32, + engineNameOffset: u32, + engineVersion: u32, + apiVersion: u32, } MemoryBarrierAccessFlags3KHR :: struct { @@ -4822,6 +5293,39 @@ MemoryBarrierAccessFlags3KHR :: struct { dstAccessMask3: AccessFlags3KHR, } +PhysicalDeviceMaintenance8FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maintenance8: b32, +} + +PhysicalDeviceShaderFmaFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + shaderFmaFloat16: b32, + shaderFmaFloat32: b32, + shaderFmaFloat64: b32, +} + +PhysicalDeviceMaintenance9FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maintenance9: b32, +} + +PhysicalDeviceMaintenance9PropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + image2DViewOf3DSparse: b32, + defaultVertexAttributeValue: DefaultVertexAttributeValueKHR, +} + +QueueFamilyOwnershipTransferPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + optimalImageTransferToQueueFamilies: u32, +} + PhysicalDeviceVideoMaintenance2FeaturesKHR :: struct { sType: StructureType, pNext: rawptr, @@ -4849,12 +5353,190 @@ VideoDecodeAV1InlineSessionParametersInfoKHR :: struct { pStdSequenceHeader: ^VideoAV1SequenceHeader, } +PhysicalDeviceVideoEncodeFeedback2FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + videoEncodeFeedback2: b32, +} + +VideoEncodeFeedback2CapabilitiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxPerPartitionFeedbackEntries: u32, + supportedPerPartitionEncodeFeedbackFlags: VideoEncodePerPartitionFeedbackFlagsKHR, +} + +QueryPoolVideoEncodePerPartitionFeedbackCreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxPerPartitionFeedbackEntries: u32, + perPartitionEncodeFeedbackFlags: VideoEncodePerPartitionFeedbackFlagsKHR, +} + PhysicalDeviceDepthClampZeroOneFeaturesKHR :: struct { sType: StructureType, pNext: rawptr, depthClampZeroOne: b32, } +PhysicalDeviceRobustness2FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + robustBufferAccess2: b32, + robustImageAccess2: b32, + nullDescriptor: b32, +} + +PhysicalDeviceRobustness2PropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + robustStorageBufferAccessSizeAlignment: DeviceSize, + robustUniformBufferAccessSizeAlignment: DeviceSize, +} + +PhysicalDevicePresentModeFifoLatestReadyFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + presentModeFifoLatestReady: b32, +} + +MicromapUsageKHR :: struct { + count: u32, + subdivisionLevel: u32, + format: OpacityMicromapFormatKHR, +} + +AccelerationStructureGeometryMicromapDataKHR :: struct { + sType: StructureType, + pNext: rawptr, + usageCountsCount: u32, + pUsageCounts: [^]MicromapUsageKHR, + ppUsageCounts: ^[^]MicromapUsageKHR, + data: DeviceAddress, + triangleArray: DeviceAddress, + triangleArrayStride: DeviceSize, +} + +PhysicalDeviceOpacityMicromapFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + micromap: b32, +} + +PhysicalDeviceOpacityMicromapPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maxOpacity2StateSubdivisionLevel: u32, + maxOpacity4StateSubdivisionLevel: u32, + maxOpacityLossy4StateSubdivisionLevel: u32, + maxMicromapTriangles: u64, +} + +MicromapTriangleKHR :: struct { + dataOffset: u32, + subdivisionLevel: u16, + format: u16, +} + +AccelerationStructureTrianglesOpacityMicromapKHR :: struct { + sType: StructureType, + pNext: rawptr, + indexType: IndexType, + indexBuffer: DeviceAddress, + indexStride: DeviceSize, + baseTriangle: u32, + micromap: AccelerationStructureKHR, +} + +PhysicalDeviceMaintenance10FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maintenance10: b32, +} + +PhysicalDeviceMaintenance10PropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + rgba4OpaqueBlackSwizzled: b32, + resolveSrgbFormatAppliesTransferFunction: b32, + resolveSrgbFormatSupportsTransferFunctionControl: b32, +} + +RenderingEndInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, +} + +RenderingAttachmentFlagsInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + flags: RenderingAttachmentFlagsKHR, +} + +ResolveImageModeInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + flags: ResolveImageFlagsKHR, + resolveMode: ResolveModeFlags, + stencilResolveMode: ResolveModeFlags, +} + +PhysicalDeviceMaintenance11FeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + maintenance11: b32, +} + +QueueFamilyOptimalImageTransferGranularityPropertiesKHR :: struct { + sType: StructureType, + pNext: rawptr, + optimalImageTransferGranularity: Extent3D, +} + +FormatProperties4KHR :: struct { + sType: StructureType, + pNext: rawptr, + linearTilingFeatures: FormatFeatureFlags4KHR, + optimalTilingFeatures: FormatFeatureFlags4KHR, + bufferFeatures: FormatFeatureFlags4KHR, +} + +ImageUsageFlags2CreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + usage: ImageUsageFlags2KHR, +} + +ImageCreateFlags2CreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + flags: ImageCreateFlags2KHR, +} + +ImageViewUsage2CreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + usage: ImageUsageFlags2KHR, +} + +PhysicalDeviceExtendedFlagsFeaturesKHR :: struct { + sType: StructureType, + pNext: rawptr, + extendedFlags: b32, +} + +ImageStencilUsage2CreateInfoKHR :: struct { + sType: StructureType, + pNext: rawptr, + stencilUsage: ImageUsageFlags2KHR, +} + +SharedPresentSurfaceCapabilities2KHR :: struct { + sType: StructureType, + pNext: rawptr, + sharedPresentSupportedUsageFlags: ImageUsageFlags2KHR, +} + DebugReportCallbackCreateInfoEXT :: struct { sType: StructureType, pNext: rawptr, @@ -5312,6 +5994,332 @@ DebugUtilsObjectTagInfoEXT :: struct { pTag: rawptr, } +GpaPerfBlockPropertiesAMD :: struct { + blockType: GpaPerfBlockAMD, + flags: GpaPerfBlockPropertiesFlagsAMD, + instanceCount: u32, + maxEventID: u32, + maxGlobalOnlyCounters: u32, + maxGlobalSharedCounters: u32, + maxStreamingCounters: u32, +} + +PhysicalDeviceGpaFeaturesAMD :: struct { + sType: StructureType, + pNext: rawptr, + perfCounters: b32, + streamingPerfCounters: b32, + sqThreadTracing: b32, + clockModes: b32, +} + +PhysicalDeviceGpaPropertiesAMD :: struct { + sType: StructureType, + pNext: rawptr, + flags: PhysicalDeviceGpaPropertiesFlagsAMD, + maxSqttSeBufferSize: DeviceSize, + shaderEngineCount: u32, + perfBlockCount: u32, + pPerfBlocks: [^]GpaPerfBlockPropertiesAMD, +} + +PhysicalDeviceGpaProperties2AMD :: struct { + sType: StructureType, + pNext: rawptr, + revisionId: u32, +} + +GpaPerfCounterAMD :: struct { + blockType: GpaPerfBlockAMD, + blockInstance: u32, + eventID: u32, +} + +GpaSampleBeginInfoAMD :: struct { + sType: StructureType, + pNext: rawptr, + sampleType: GpaSampleTypeAMD, + sampleInternalOperations: b32, + cacheFlushOnCounterCollection: b32, + sqShaderMaskEnable: b32, + sqShaderMask: GpaSqShaderStageFlagsAMD, + perfCounterCount: u32, + pPerfCounters: [^]GpaPerfCounterAMD, + streamingPerfTraceSampleInterval: u32, + perfCounterDeviceMemoryLimit: DeviceSize, + sqThreadTraceEnable: b32, + sqThreadTraceSuppressInstructionTokens: b32, + sqThreadTraceDeviceMemoryLimit: DeviceSize, + timingPreSample: PipelineStageFlags, + timingPostSample: PipelineStageFlags, +} + +GpaDeviceClockModeInfoAMD :: struct { + sType: StructureType, + pNext: rawptr, + clockMode: GpaDeviceClockModeAMD, + memoryClockRatioToPeak: f32, + engineClockRatioToPeak: f32, +} + +GpaDeviceGetClockInfoAMD :: struct { + sType: StructureType, + pNext: rawptr, + memoryClockRatioToPeak: f32, + engineClockRatioToPeak: f32, + memoryClockFrequency: u32, + engineClockFrequency: u32, +} + +GpaSessionCreateInfoAMD :: struct { + sType: StructureType, + pNext: rawptr, + secondaryCopySource: GpaSessionAMD, +} + +HostAddressRangeEXT :: struct { + address: rawptr, + size: int, +} + +HostAddressRangeConstEXT :: struct { + address: rawptr, + size: int, +} + +TexelBufferDescriptorInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + format: Format, + addressRange: DeviceAddressRangeEXT, +} + +ImageDescriptorInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + pView: ^ImageViewCreateInfo, + layout: ImageLayout, +} + +TensorViewCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: TensorViewCreateFlagsARM, + tensor: TensorARM, + format: Format, +} + +ResourceDescriptorDataEXT :: struct #raw_union { + pImage: ^ImageDescriptorInfoEXT, + pTexelBuffer: ^TexelBufferDescriptorInfoEXT, + pAddressRange: ^DeviceAddressRangeEXT, + pTensorARM: ^TensorViewCreateInfoARM, +} + +ResourceDescriptorInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + type: DescriptorType, + data: ResourceDescriptorDataEXT, +} + +BindHeapInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + heapRange: DeviceAddressRangeEXT, + reservedRangeOffset: DeviceSize, + reservedRangeSize: DeviceSize, +} + +PushDataInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + offset: u32, + data: HostAddressRangeConstEXT, +} + +DescriptorMappingSourceConstantOffsetEXT :: struct { + heapOffset: u32, + heapArrayStride: u32, + pEmbeddedSampler: ^SamplerCreateInfo, + samplerHeapOffset: u32, + samplerHeapArrayStride: u32, +} + +DescriptorMappingSourcePushIndexEXT :: struct { + heapOffset: u32, + pushOffset: u32, + heapIndexStride: u32, + heapArrayStride: u32, + pEmbeddedSampler: ^SamplerCreateInfo, + useCombinedImageSamplerIndex: b32, + samplerHeapOffset: u32, + samplerPushOffset: u32, + samplerHeapIndexStride: u32, + samplerHeapArrayStride: u32, +} + +DescriptorMappingSourceIndirectIndexEXT :: struct { + heapOffset: u32, + pushOffset: u32, + addressOffset: u32, + heapIndexStride: u32, + heapArrayStride: u32, + pEmbeddedSampler: ^SamplerCreateInfo, + useCombinedImageSamplerIndex: b32, + samplerHeapOffset: u32, + samplerPushOffset: u32, + samplerAddressOffset: u32, + samplerHeapIndexStride: u32, + samplerHeapArrayStride: u32, +} + +DescriptorMappingSourceHeapDataEXT :: struct { + heapOffset: u32, + pushOffset: u32, +} + +DescriptorMappingSourceIndirectAddressEXT :: struct { + pushOffset: u32, + addressOffset: u32, +} + +DescriptorMappingSourceShaderRecordIndexEXT :: struct { + heapOffset: u32, + shaderRecordOffset: u32, + heapIndexStride: u32, + heapArrayStride: u32, + pEmbeddedSampler: ^SamplerCreateInfo, + useCombinedImageSamplerIndex: b32, + samplerHeapOffset: u32, + samplerShaderRecordOffset: u32, + samplerHeapIndexStride: u32, + samplerHeapArrayStride: u32, +} + +DescriptorMappingSourceIndirectIndexArrayEXT :: struct { + heapOffset: u32, + pushOffset: u32, + addressOffset: u32, + heapIndexStride: u32, + pEmbeddedSampler: ^SamplerCreateInfo, + useCombinedImageSamplerIndex: b32, + samplerHeapOffset: u32, + samplerPushOffset: u32, + samplerAddressOffset: u32, + samplerHeapIndexStride: u32, +} + +DescriptorMappingSourceDataEXT :: struct #raw_union { + constantOffset: DescriptorMappingSourceConstantOffsetEXT, + pushIndex: DescriptorMappingSourcePushIndexEXT, + indirectIndex: DescriptorMappingSourceIndirectIndexEXT, + indirectIndexArray: DescriptorMappingSourceIndirectIndexArrayEXT, + heapData: DescriptorMappingSourceHeapDataEXT, + pushDataOffset: u32, + pushAddressOffset: u32, + indirectAddress: DescriptorMappingSourceIndirectAddressEXT, + shaderRecordIndex: DescriptorMappingSourceShaderRecordIndexEXT, + shaderRecordDataOffset: u32, + shaderRecordAddressOffset: u32, +} + +DescriptorSetAndBindingMappingEXT :: struct { + sType: StructureType, + pNext: rawptr, + descriptorSet: u32, + firstBinding: u32, + bindingCount: u32, + resourceMask: SpirvResourceTypeFlagsEXT, + source: DescriptorMappingSourceEXT, + sourceData: DescriptorMappingSourceDataEXT, +} + +ShaderDescriptorSetAndBindingMappingInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + mappingCount: u32, + pMappings: [^]DescriptorSetAndBindingMappingEXT, +} + +OpaqueCaptureDataCreateInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + pData: ^HostAddressRangeConstEXT, +} + +PhysicalDeviceDescriptorHeapFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + descriptorHeap: b32, + descriptorHeapCaptureReplay: b32, +} + +PhysicalDeviceDescriptorHeapPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + samplerHeapAlignment: DeviceSize, + resourceHeapAlignment: DeviceSize, + maxSamplerHeapSize: DeviceSize, + maxResourceHeapSize: DeviceSize, + minSamplerHeapReservedRange: DeviceSize, + minSamplerHeapReservedRangeWithEmbedded: DeviceSize, + minResourceHeapReservedRange: DeviceSize, + samplerDescriptorSize: DeviceSize, + imageDescriptorSize: DeviceSize, + bufferDescriptorSize: DeviceSize, + samplerDescriptorAlignment: DeviceSize, + imageDescriptorAlignment: DeviceSize, + bufferDescriptorAlignment: DeviceSize, + maxPushDataSize: DeviceSize, + imageCaptureReplayOpaqueDataSize: int, + maxDescriptorHeapEmbeddedSamplers: u32, + samplerYcbcrConversionCount: u32, + sparseDescriptorHeaps: b32, + protectedDescriptorHeaps: b32, +} + +CommandBufferInheritanceDescriptorHeapInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + pSamplerHeapBindInfo: ^BindHeapInfoEXT, + pResourceHeapBindInfo: ^BindHeapInfoEXT, +} + +SamplerCustomBorderColorIndexCreateInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + index: u32, +} + +SamplerCustomBorderColorCreateInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + customBorderColor: ClearColorValue, + format: Format, +} + +IndirectCommandsLayoutPushDataTokenNV :: struct { + sType: StructureType, + pNext: rawptr, + pushDataOffset: u32, + pushDataSize: u32, +} + +SubsampledImageFormatPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + subsampledImageDescriptorCount: u32, +} + +PhysicalDeviceDescriptorHeapTensorPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorDescriptorSize: DeviceSize, + tensorDescriptorAlignment: DeviceSize, + tensorCaptureReplayOpaqueDataSize: int, +} + AttachmentSampleCountInfoAMD :: struct { sType: StructureType, pNext: rawptr, @@ -5617,7 +6625,7 @@ AccelerationStructureInfoNV :: struct { sType: StructureType, pNext: rawptr, type: AccelerationStructureTypeNV, - flags: BuildAccelerationStructureFlagsNV, + flags: BuildAccelerationStructureFlagsKHR, instanceCount: u32, geometryCount: u32, pGeometries: [^]GeometryNV, @@ -5718,6 +6726,18 @@ FilterCubicImageViewImageFormatPropertiesEXT :: struct { filterCubicMinmax: b32, } +PhysicalDeviceCooperativeMatrixConversionFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + cooperativeMatrixConversion: b32, +} + +PhysicalDeviceElapsedTimerQueryFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + elapsedTimerQuery: b32, +} + ImportMemoryHostPointerInfoEXT :: struct { sType: StructureType, pNext: rawptr, @@ -5849,6 +6869,96 @@ CheckpointData2NV :: struct { pCheckpointMarker: rawptr, } +PhysicalDevicePresentTimingFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + presentTiming: b32, + presentAtAbsoluteTime: b32, + presentAtRelativeTime: b32, +} + +PresentTimingSurfaceCapabilitiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + presentTimingSupported: b32, + presentAtAbsoluteTimeSupported: b32, + presentAtRelativeTimeSupported: b32, + presentStageQueries: PresentStageFlagsEXT, +} + +SwapchainCalibratedTimestampInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + swapchain: SwapchainKHR, + presentStage: PresentStageFlagsEXT, + timeDomainId: u64, +} + +SwapchainTimingPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + refreshDuration: u64, + refreshInterval: u64, +} + +SwapchainTimeDomainPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + timeDomainCount: u32, + pTimeDomains: [^]TimeDomainKHR, + pTimeDomainIds: [^]u64, +} + +PastPresentationTimingInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + flags: PastPresentationTimingFlagsEXT, + swapchain: SwapchainKHR, +} + +PresentStageTimeEXT :: struct { + stage: PresentStageFlagsEXT, + time: u64, +} + +PastPresentationTimingEXT :: struct { + sType: StructureType, + pNext: rawptr, + presentId: u64, + targetTime: u64, + presentStageCount: u32, + pPresentStages: [^]PresentStageTimeEXT, + timeDomain: TimeDomainKHR, + timeDomainId: u64, + reportComplete: b32, +} + +PastPresentationTimingPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + timingPropertiesCounter: u64, + timeDomainsCounter: u64, + presentationTimingCount: u32, + pPresentationTimings: [^]PastPresentationTimingEXT, +} + +PresentTimingInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + flags: PresentTimingInfoFlagsEXT, + targetTime: u64, + timeDomainId: u64, + presentStageQueries: PresentStageFlagsEXT, + targetTimeDomainPresentStage: PresentStageFlagsEXT, +} + +PresentTimingsInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + swapchainCount: u32, + pTimingInfos: [^]PresentTimingInfoEXT, +} + PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL :: struct { sType: StructureType, pNext: rawptr, @@ -6172,72 +7282,6 @@ PhysicalDeviceShaderAtomicFloat2FeaturesEXT :: struct { sparseImageFloat32AtomicMinMax: b32, } -SurfacePresentModeEXT :: struct { - sType: StructureType, - pNext: rawptr, - presentMode: PresentModeKHR, -} - -SurfacePresentScalingCapabilitiesEXT :: struct { - sType: StructureType, - pNext: rawptr, - supportedPresentScaling: PresentScalingFlagsEXT, - supportedPresentGravityX: PresentGravityFlagsEXT, - supportedPresentGravityY: PresentGravityFlagsEXT, - minScaledImageExtent: Extent2D, - maxScaledImageExtent: Extent2D, -} - -SurfacePresentModeCompatibilityEXT :: struct { - sType: StructureType, - pNext: rawptr, - presentModeCount: u32, - pPresentModes: [^]PresentModeKHR, -} - -PhysicalDeviceSwapchainMaintenance1FeaturesEXT :: struct { - sType: StructureType, - pNext: rawptr, - swapchainMaintenance1: b32, -} - -SwapchainPresentFenceInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - swapchainCount: u32, - pFences: [^]Fence, -} - -SwapchainPresentModesCreateInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - presentModeCount: u32, - pPresentModes: [^]PresentModeKHR, -} - -SwapchainPresentModeInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - swapchainCount: u32, - pPresentModes: [^]PresentModeKHR, -} - -SwapchainPresentScalingCreateInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - scalingBehavior: PresentScalingFlagsEXT, - presentGravityX: PresentGravityFlagsEXT, - presentGravityY: PresentGravityFlagsEXT, -} - -ReleaseSwapchainImagesInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - swapchain: SwapchainKHR, - imageIndexCount: u32, - pImageIndices: [^]u32, -} - PhysicalDeviceDeviceGeneratedCommandsPropertiesNV :: struct { sType: StructureType, pNext: rawptr, @@ -6440,28 +7484,6 @@ DeviceDeviceMemoryReportCreateInfoEXT :: struct { pUserData: rawptr, } -PhysicalDeviceRobustness2FeaturesEXT :: struct { - sType: StructureType, - pNext: rawptr, - robustBufferAccess2: b32, - robustImageAccess2: b32, - nullDescriptor: b32, -} - -PhysicalDeviceRobustness2PropertiesEXT :: struct { - sType: StructureType, - pNext: rawptr, - robustStorageBufferAccessSizeAlignment: DeviceSize, - robustUniformBufferAccessSizeAlignment: DeviceSize, -} - -SamplerCustomBorderColorCreateInfoEXT :: struct { - sType: StructureType, - pNext: rawptr, - customBorderColor: ClearColorValue, - format: Format, -} - PhysicalDeviceCustomBorderColorPropertiesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -6475,6 +7497,12 @@ PhysicalDeviceCustomBorderColorFeaturesEXT :: struct { customBorderColorWithoutFormat: b32, } +PhysicalDeviceTextureCompressionASTC3DFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + textureCompressionASTC_3D: b32, +} + PhysicalDevicePresentBarrierFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -6505,48 +7533,105 @@ DeviceDiagnosticsConfigCreateInfoNV :: struct { flags: DeviceDiagnosticsConfigFlagsNV, } -CudaModuleCreateInfoNV :: struct { - sType: StructureType, - pNext: rawptr, - dataSize: int, - pData: rawptr, +PerfHintInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, + type: PerfHintTypeQCOM, + scale: u32, } -CudaFunctionCreateInfoNV :: struct { - sType: StructureType, - pNext: rawptr, - module: CudaModuleNV, - pName: cstring, +PhysicalDeviceQueuePerfHintFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + queuePerfHint: b32, } -CudaLaunchInfoNV :: struct { - sType: StructureType, - pNext: rawptr, - function: CudaFunctionNV, - gridDimX: u32, - gridDimY: u32, - gridDimZ: u32, - blockDimX: u32, - blockDimY: u32, - blockDimZ: u32, - sharedMemBytes: u32, - paramCount: int, - pParams: [^]rawptr, - extraCount: int, - pExtras: [^]rawptr, +PhysicalDeviceQueuePerfHintPropertiesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + supportedQueues: QueueFlags, } -PhysicalDeviceCudaKernelLaunchFeaturesNV :: struct { +PhysicalDeviceImageProcessing3FeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + imageGatherLinear: b32, + imageGatherExtendedModes: b32, + blockMatchExtendedClampToEdge: b32, +} + +PhysicalDeviceShaderMultipleWaitQueuesFeaturesQCOM :: struct { sType: StructureType, pNext: rawptr, - cudaKernelLaunchFeatures: b32, + shaderMultipleWaitQueues: b32, } -PhysicalDeviceCudaKernelLaunchPropertiesNV :: struct { - sType: StructureType, - pNext: rawptr, - computeCapabilityMinor: u32, - computeCapabilityMajor: u32, +PhysicalDeviceShaderMultipleWaitQueuesPropertiesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + maxShaderWaitQueues: u32, +} + +PhysicalDeviceShaderSplitBarrierFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + shaderSplitBarrier: b32, +} + +PhysicalDeviceShaderSplitBarrierPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + splitBarrierReservedSharedMemory: u32, +} + +PhysicalDeviceTileShadingFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + tileShading: b32, + tileShadingFragmentStage: b32, + tileShadingColorAttachments: b32, + tileShadingDepthAttachments: b32, + tileShadingStencilAttachments: b32, + tileShadingInputAttachments: b32, + tileShadingSampledAttachments: b32, + tileShadingPerTileDraw: b32, + tileShadingPerTileDispatch: b32, + tileShadingDispatchTile: b32, + tileShadingApron: b32, + tileShadingAnisotropicApron: b32, + tileShadingAtomicOps: b32, + tileShadingImageProcessing: b32, +} + +PhysicalDeviceTileShadingPropertiesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + maxApronSize: u32, + preferNonCoherent: b32, + tileGranularity: Extent2D, + maxTileShadingRate: Extent2D, +} + +RenderPassTileShadingCreateInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, + flags: TileShadingRenderPassFlagsQCOM, + tileApronSize: Extent2D, +} + +PerTileBeginInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, +} + +PerTileEndInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, +} + +DispatchTileInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, } QueryLowLatencySupportNV :: struct { @@ -6593,12 +7678,6 @@ PhysicalDeviceDescriptorBufferPropertiesEXT :: struct { descriptorBufferAddressSpaceSize: DeviceSize, } -PhysicalDeviceDescriptorBufferDensityMapPropertiesEXT :: struct { - sType: StructureType, - pNext: rawptr, - combinedImageSamplerDensityMapDescriptorSize: int, -} - PhysicalDeviceDescriptorBufferFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -6686,6 +7765,12 @@ AccelerationStructureCaptureDescriptorDataInfoEXT :: struct { accelerationStructureNV: AccelerationStructureNV, } +PhysicalDeviceDescriptorBufferDensityMapPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + combinedImageSamplerDensityMapDescriptorSize: int, +} + PhysicalDeviceGraphicsPipelineLibraryFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -6893,41 +7978,15 @@ DeviceFaultCountsEXT :: struct { vendorBinarySize: DeviceSize, } -DeviceFaultAddressInfoEXT :: struct { - addressType: DeviceFaultAddressTypeEXT, - reportedAddress: DeviceAddress, - addressPrecision: DeviceSize, -} - -DeviceFaultVendorInfoEXT :: struct { - description: [MAX_DESCRIPTION_SIZE]byte, - vendorFaultCode: u64, - vendorFaultData: u64, -} - DeviceFaultInfoEXT :: struct { sType: StructureType, pNext: rawptr, description: [MAX_DESCRIPTION_SIZE]byte, - pAddressInfos: [^]DeviceFaultAddressInfoEXT, - pVendorInfos: [^]DeviceFaultVendorInfoEXT, + pAddressInfos: [^]DeviceFaultAddressInfoKHR, + pVendorInfos: [^]DeviceFaultVendorInfoKHR, pVendorBinaryData: rawptr, } -DeviceFaultVendorBinaryHeaderVersionOneEXT :: struct { - headerSize: u32, - headerVersion: DeviceFaultVendorBinaryHeaderVersionEXT, - vendorID: u32, - deviceID: u32, - driverVersion: u32, - pipelineCacheUUID: [UUID_SIZE]u8, - applicationNameOffset: u32, - applicationVersion: u32, - engineNameOffset: u32, - engineVersion: u32, - apiVersion: u32, -} - PhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -7029,12 +8088,6 @@ PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT :: struct { primitiveTopologyPatchListRestart: b32, } -PhysicalDevicePresentModeFifoLatestReadyFeaturesEXT :: struct { - sType: StructureType, - pNext: rawptr, - presentModeFifoLatestReady: b32, -} - SubpassShadingPipelineCreateInfoHUAWEI :: struct { sType: StructureType, pNext: rawptr, @@ -7153,6 +8206,36 @@ PhysicalDevicePrimitivesGeneratedQueryFeaturesEXT :: struct { primitivesGeneratedQueryWithNonZeroStreams: b32, } +PhysicalDeviceVideoEncodeRgbConversionFeaturesVALVE :: struct { + sType: StructureType, + pNext: rawptr, + videoEncodeRgbConversion: b32, +} + +VideoEncodeRgbConversionCapabilitiesVALVE :: struct { + sType: StructureType, + pNext: rawptr, + rgbModels: VideoEncodeRgbModelConversionFlagsVALVE, + rgbRanges: VideoEncodeRgbRangeCompressionFlagsVALVE, + xChromaOffsets: VideoEncodeRgbChromaOffsetFlagsVALVE, + yChromaOffsets: VideoEncodeRgbChromaOffsetFlagsVALVE, +} + +VideoEncodeProfileRgbConversionInfoVALVE :: struct { + sType: StructureType, + pNext: rawptr, + performEncodeRgbConversion: b32, +} + +VideoEncodeSessionRgbConversionCreateInfoVALVE :: struct { + sType: StructureType, + pNext: rawptr, + rgbModel: VideoEncodeRgbModelConversionFlagsVALVE, + rgbRange: VideoEncodeRgbRangeCompressionFlagsVALVE, + xChromaOffset: VideoEncodeRgbChromaOffsetFlagsVALVE, + yChromaOffset: VideoEncodeRgbChromaOffsetFlagsVALVE, +} + PhysicalDeviceImageViewMinLodFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -7315,12 +8398,6 @@ AccelerationStructureTrianglesOpacityMicromapEXT :: struct { micromap: MicromapEXT, } -MicromapTriangleEXT :: struct { - dataOffset: u32, - subdivisionLevel: u16, - format: u16, -} - PhysicalDeviceClusterCullingShaderFeaturesHUAWEI :: struct { sType: StructureType, pNext: rawptr, @@ -7389,6 +8466,22 @@ PhysicalDeviceSchedulingControlsPropertiesARM :: struct { schedulingControlsFlags: PhysicalDeviceSchedulingControlsFlagsARM, } +DispatchParametersARM :: struct { + sType: StructureType, + pNext: rawptr, + workGroupBatchSize: u32, + maxQueuedWorkGroupBatches: u32, + maxWarpsPerShaderCore: u32, +} + +PhysicalDeviceSchedulingControlsDispatchParametersPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + schedulingControlsMaxWarpsCount: u32, + schedulingControlsMaxQueuedBatchesCount: u32, + schedulingControlsMaxWorkGroupBatchSize: u32, +} + PhysicalDeviceImageSlicedViewOf3DFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -7461,70 +8554,49 @@ RenderPassStripeSubmitInfoARM :: struct { pStripeSemaphoreInfos: [^]SemaphoreSubmitInfo, } -PhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM :: struct { +PhysicalDeviceFragmentDensityMapOffsetFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, fragmentDensityMapOffset: b32, } -PhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM :: struct { +PhysicalDeviceFragmentDensityMapOffsetPropertiesEXT :: struct { sType: StructureType, pNext: rawptr, fragmentDensityOffsetGranularity: Extent2D, } -SubpassFragmentDensityMapOffsetEndInfoQCOM :: struct { +RenderPassFragmentDensityMapOffsetEndInfoEXT :: struct { sType: StructureType, pNext: rawptr, fragmentDensityOffsetCount: u32, pFragmentDensityOffsets: [^]Offset2D, } -CopyMemoryIndirectCommandNV :: struct { - srcAddress: DeviceAddress, - dstAddress: DeviceAddress, - size: DeviceSize, -} - -CopyMemoryToImageIndirectCommandNV :: struct { - srcAddress: DeviceAddress, - bufferRowLength: u32, - bufferImageHeight: u32, - imageSubresource: ImageSubresourceLayers, - imageOffset: Offset3D, - imageExtent: Extent3D, -} - PhysicalDeviceCopyMemoryIndirectFeaturesNV :: struct { sType: StructureType, pNext: rawptr, indirectCopy: b32, } -PhysicalDeviceCopyMemoryIndirectPropertiesNV :: struct { - sType: StructureType, - pNext: rawptr, - supportedQueues: QueueFlags, -} - DecompressMemoryRegionNV :: struct { srcAddress: DeviceAddress, dstAddress: DeviceAddress, compressedSize: DeviceSize, decompressedSize: DeviceSize, - decompressionMethod: MemoryDecompressionMethodFlagsNV, + decompressionMethod: MemoryDecompressionMethodFlagsEXT, } -PhysicalDeviceMemoryDecompressionFeaturesNV :: struct { +PhysicalDeviceMemoryDecompressionFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, memoryDecompression: b32, } -PhysicalDeviceMemoryDecompressionPropertiesNV :: struct { +PhysicalDeviceMemoryDecompressionPropertiesEXT :: struct { sType: StructureType, pNext: rawptr, - decompressionMethods: MemoryDecompressionMethodFlagsNV, + decompressionMethods: MemoryDecompressionMethodFlagsEXT, maxDecompressionIndirectCount: u64, } @@ -7757,6 +8829,192 @@ DirectDriverLoadingListLUNARG :: struct { pDrivers: [^]DirectDriverLoadingInfoLUNARG, } +TensorDescriptionARM :: struct { + sType: StructureType, + pNext: rawptr, + tiling: TensorTilingARM, + format: Format, + dimensionCount: u32, + pDimensions: [^]i64, + pStrides: [^]i64, + usage: TensorUsageFlagsARM, +} + +TensorCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: TensorCreateFlagsARM, + pDescription: ^TensorDescriptionARM, + sharingMode: SharingMode, + queueFamilyIndexCount: u32, + pQueueFamilyIndices: [^]u32, +} + +TensorMemoryRequirementsInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensor: TensorARM, +} + +BindTensorMemoryInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensor: TensorARM, + memory: DeviceMemory, + memoryOffset: DeviceSize, +} + +WriteDescriptorSetTensorARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorViewCount: u32, + pTensorViews: [^]TensorViewARM, +} + +TensorFormatPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + optimalTilingTensorFeatures: FormatFeatureFlags2, + linearTilingTensorFeatures: FormatFeatureFlags2, +} + +PhysicalDeviceTensorPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + maxTensorDimensionCount: u32, + maxTensorElements: u64, + maxPerDimensionTensorElements: u64, + maxTensorStride: i64, + maxTensorSize: u64, + maxTensorShaderAccessArrayLength: u32, + maxTensorShaderAccessSize: u32, + maxDescriptorSetStorageTensors: u32, + maxPerStageDescriptorSetStorageTensors: u32, + maxDescriptorSetUpdateAfterBindStorageTensors: u32, + maxPerStageDescriptorUpdateAfterBindStorageTensors: u32, + shaderStorageTensorArrayNonUniformIndexingNative: b32, + shaderTensorSupportedStages: ShaderStageFlags, +} + +TensorMemoryBarrierARM :: struct { + sType: StructureType, + pNext: rawptr, + srcStageMask: PipelineStageFlags2, + srcAccessMask: AccessFlags2, + dstStageMask: PipelineStageFlags2, + dstAccessMask: AccessFlags2, + srcQueueFamilyIndex: u32, + dstQueueFamilyIndex: u32, + tensor: TensorARM, +} + +TensorDependencyInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorMemoryBarrierCount: u32, + pTensorMemoryBarriers: [^]TensorMemoryBarrierARM, +} + +PhysicalDeviceTensorFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorNonPacked: b32, + shaderTensorAccess: b32, + shaderStorageTensorArrayDynamicIndexing: b32, + shaderStorageTensorArrayNonUniformIndexing: b32, + descriptorBindingStorageTensorUpdateAfterBind: b32, + tensors: b32, +} + +DeviceTensorMemoryRequirementsARM :: struct { + sType: StructureType, + pNext: rawptr, + pCreateInfo: ^TensorCreateInfoARM, +} + +TensorCopyARM :: struct { + sType: StructureType, + pNext: rawptr, + dimensionCount: u32, + pSrcOffset: ^u64, + pDstOffset: ^u64, + pExtent: ^u64, +} + +CopyTensorInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + srcTensor: TensorARM, + dstTensor: TensorARM, + regionCount: u32, + pRegions: [^]TensorCopyARM, +} + +MemoryDedicatedAllocateInfoTensorARM :: struct { + sType: StructureType, + pNext: rawptr, + tensor: TensorARM, +} + +PhysicalDeviceExternalTensorInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: TensorCreateFlagsARM, + pDescription: ^TensorDescriptionARM, + handleType: ExternalMemoryHandleTypeFlags, +} + +ExternalTensorPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + externalMemoryProperties: ExternalMemoryProperties, +} + +ExternalMemoryTensorCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + handleTypes: ExternalMemoryHandleTypeFlags, +} + +PhysicalDeviceDescriptorBufferTensorFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + descriptorBufferTensorDescriptors: b32, +} + +PhysicalDeviceDescriptorBufferTensorPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorCaptureReplayDescriptorDataSize: int, + tensorViewCaptureReplayDescriptorDataSize: int, + tensorDescriptorSize: int, +} + +DescriptorGetTensorInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorView: TensorViewARM, +} + +TensorCaptureDescriptorDataInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensor: TensorARM, +} + +TensorViewCaptureDescriptorDataInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorView: TensorViewARM, +} + +FrameBoundaryTensorsARM :: struct { + sType: StructureType, + pNext: rawptr, + tensorCount: u32, + pTensors: [^]TensorARM, +} + PhysicalDeviceShaderModuleIdentifierFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -7945,7 +9203,7 @@ PhysicalDeviceMultiviewPerViewViewportsFeaturesQCOM :: struct { PhysicalDeviceRayTracingInvocationReorderPropertiesNV :: struct { sType: StructureType, pNext: rawptr, - rayTracingInvocationReorderReorderingHint: RayTracingInvocationReorderModeNV, + rayTracingInvocationReorderReorderingHint: RayTracingInvocationReorderModeEXT, } PhysicalDeviceRayTracingInvocationReorderFeaturesNV :: struct { @@ -8138,6 +9396,185 @@ LatencySurfaceCapabilitiesNV :: struct { pPresentModes: [^]PresentModeKHR, } +PhysicalDeviceDataGraphFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + dataGraph: b32, + dataGraphUpdateAfterBind: b32, + dataGraphSpecializationConstants: b32, + dataGraphDescriptorBuffer: b32, + dataGraphShaderModule: b32, +} + +DataGraphPipelineConstantARM :: struct { + sType: StructureType, + pNext: rawptr, + id: u32, + pConstantData: rawptr, +} + +DataGraphPipelineResourceInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + descriptorSet: u32, + binding: u32, + arrayElement: u32, +} + +DataGraphPipelineCompilerControlCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + pVendorOptions: cstring, +} + +DataGraphPipelineCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: PipelineCreateFlags2, + layout: PipelineLayout, + resourceInfoCount: u32, + pResourceInfos: [^]DataGraphPipelineResourceInfoARM, +} + +DataGraphPipelineShaderModuleCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + module: ShaderModule, + pName: cstring, + pSpecializationInfo: ^SpecializationInfo, + constantCount: u32, + pConstants: [^]DataGraphPipelineConstantARM, +} + +DataGraphPipelineSessionCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: DataGraphPipelineSessionCreateFlagsARM, + dataGraphPipeline: Pipeline, +} + +DataGraphPipelineSessionBindPointRequirementsInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + session: DataGraphPipelineSessionARM, +} + +DataGraphPipelineSessionBindPointRequirementARM :: struct { + sType: StructureType, + pNext: rawptr, + bindPoint: DataGraphPipelineSessionBindPointARM, + bindPointType: DataGraphPipelineSessionBindPointTypeARM, + numObjects: u32, +} + +DataGraphPipelineSessionMemoryRequirementsInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + session: DataGraphPipelineSessionARM, + bindPoint: DataGraphPipelineSessionBindPointARM, + objectIndex: u32, +} + +BindDataGraphPipelineSessionMemoryInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + session: DataGraphPipelineSessionARM, + bindPoint: DataGraphPipelineSessionBindPointARM, + objectIndex: u32, + memory: DeviceMemory, + memoryOffset: DeviceSize, +} + +DataGraphPipelineInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + dataGraphPipeline: Pipeline, +} + +DataGraphPipelinePropertyQueryResultARM :: struct { + sType: StructureType, + pNext: rawptr, + property: DataGraphPipelinePropertyARM, + isText: b32, + dataSize: int, + pData: rawptr, +} + +DataGraphPipelineIdentifierCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + identifierSize: u32, + pIdentifier: ^u8, +} + +DataGraphPipelineDispatchInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: DataGraphPipelineDispatchFlagsARM, +} + +PhysicalDeviceDataGraphProcessingEngineARM :: struct { + type: PhysicalDeviceDataGraphProcessingEngineTypeARM, + isForeign: b32, +} + +PhysicalDeviceDataGraphOperationSupportARM :: struct { + operationType: PhysicalDeviceDataGraphOperationTypeARM, + name: [MAX_PHYSICAL_DEVICE_DATA_GRAPH_OPERATION_SET_NAME_SIZE_ARM]byte, + version: u32, +} + +QueueFamilyDataGraphPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + engine: PhysicalDeviceDataGraphProcessingEngineARM, + operation: PhysicalDeviceDataGraphOperationSupportARM, +} + +DataGraphProcessingEngineCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + processingEngineCount: u32, + pProcessingEngines: [^]PhysicalDeviceDataGraphProcessingEngineARM, +} + +PhysicalDeviceQueueFamilyDataGraphProcessingEngineInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + queueFamilyIndex: u32, + engineType: PhysicalDeviceDataGraphProcessingEngineTypeARM, +} + +QueueFamilyDataGraphProcessingEnginePropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + foreignSemaphoreHandleTypes: ExternalSemaphoreHandleTypeFlags, + foreignMemoryHandleTypes: ExternalMemoryHandleTypeFlags, +} + +DataGraphPipelineConstantTensorSemiStructuredSparsityInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + dimension: u32, + zeroCount: u32, + groupSize: u32, +} + +DataGraphTOSANameQualityARM :: struct { + name: [MAX_DATA_GRAPH_TOSA_NAME_SIZE_ARM]byte, + qualityFlags: DataGraphTOSAQualityFlagsARM, +} + +QueueFamilyDataGraphTOSAPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + profileCount: u32, + pProfiles: [^]DataGraphTOSANameQualityARM, + extensionCount: u32, + pExtensions: [^]DataGraphTOSANameQualityARM, + level: DataGraphTOSALevelARM, +} + PhysicalDeviceMultiviewPerViewRenderAreasFeaturesQCOM :: struct { sType: StructureType, pNext: rawptr, @@ -8232,6 +9669,53 @@ PhysicalDeviceDescriptorPoolOverallocationFeaturesNV :: struct { descriptorPoolOverallocation: b32, } +PhysicalDeviceTileMemoryHeapFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + tileMemoryHeap: b32, +} + +PhysicalDeviceTileMemoryHeapPropertiesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + queueSubmitBoundary: b32, + tileBufferTransfers: b32, +} + +TileMemoryRequirementsQCOM :: struct { + sType: StructureType, + pNext: rawptr, + size: DeviceSize, + alignment: DeviceSize, +} + +TileMemoryBindInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, + memory: DeviceMemory, +} + +TileMemorySizeInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, + size: DeviceSize, +} + +DecompressMemoryRegionEXT :: struct { + srcAddress: DeviceAddress, + dstAddress: DeviceAddress, + compressedSize: DeviceSize, + decompressedSize: DeviceSize, +} + +DecompressMemoryInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + decompressionMethod: MemoryDecompressionMethodFlagsEXT, + regionCount: u32, + pRegions: [^]DecompressMemoryRegionEXT, +} + DisplaySurfaceStereoCreateInfoNV :: struct { sType: StructureType, pNext: rawptr, @@ -8250,6 +9734,31 @@ PhysicalDeviceRawAccessChainsFeaturesNV :: struct { shaderRawAccessChains: b32, } +ExternalComputeQueueDeviceCreateInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + reservedExternalQueues: u32, +} + +ExternalComputeQueueCreateInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + preferredQueue: Queue, +} + +ExternalComputeQueueDataParamsNV :: struct { + sType: StructureType, + pNext: rawptr, + deviceIndex: u32, +} + +PhysicalDeviceExternalComputeQueuePropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + externalDataSize: u32, + maxExternalQueues: u32, +} + PhysicalDeviceCommandBufferInheritanceFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -8268,6 +9777,13 @@ PhysicalDeviceShaderReplicatedCompositesFeaturesEXT :: struct { shaderReplicatedComposites: b32, } +PhysicalDeviceShaderFloat8FeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + shaderFloat8: b32, + shaderFloat8CooperativeMatrix: b32, +} + PhysicalDeviceRayTracingValidationFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -8432,6 +9948,10 @@ ClusterAccelerationStructureInstantiateClusterInfoNV :: struct { vertexBuffer: StridedDeviceAddressNV, } +ClusterAccelerationStructureGetTemplateIndicesInfoNV :: struct { + clusterTemplateAddress: DeviceAddress, +} + AccelerationStructureBuildSizesInfoKHR :: struct { sType: StructureType, pNext: rawptr, @@ -8712,6 +10232,40 @@ ImageAlignmentControlCreateInfoMESA :: struct { maximumRequestedAlignment: u32, } +PushConstantBankInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + bank: u32, +} + +PhysicalDevicePushConstantBankFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + pushConstantBank: b32, +} + +PhysicalDevicePushConstantBankPropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + maxGraphicsPushConstantBanks: u32, + maxComputePushConstantBanks: u32, + maxGraphicsPushDataBanks: u32, + maxComputePushDataBanks: u32, +} + +PhysicalDeviceRayTracingInvocationReorderPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + rayTracingInvocationReorderReorderingHint: RayTracingInvocationReorderModeEXT, + maxShaderBindingTableRecordIndex: u32, +} + +PhysicalDeviceRayTracingInvocationReorderFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + rayTracingInvocationReorder: b32, +} + PhysicalDeviceDepthClampControlFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, @@ -8779,12 +10333,107 @@ PhysicalDevicePipelineOpacityMicromapFeaturesARM :: struct { pipelineOpacityMicromap: b32, } +PhysicalDevicePerformanceCountersByRegionFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + performanceCountersByRegion: b32, +} + +PhysicalDevicePerformanceCountersByRegionPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + maxPerRegionPerformanceCounters: u32, + performanceCounterRegionSize: Extent2D, + rowStrideAlignment: u32, + regionAlignment: u32, + identityTransformOrder: b32, +} + +PerformanceCounterARM :: struct { + sType: StructureType, + pNext: rawptr, + counterID: u32, +} + +PerformanceCounterDescriptionARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: PerformanceCounterDescriptionFlagsARM, + name: [MAX_DESCRIPTION_SIZE]byte, +} + +RenderPassPerformanceCountersByRegionBeginInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + counterAddressCount: u32, + pCounterAddresses: [^]DeviceAddress, + serializeRegions: b32, + counterIndexCount: u32, + pCounterIndices: [^]u32, +} + +PhysicalDeviceShaderInstrumentationFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + shaderInstrumentation: b32, +} + +PhysicalDeviceShaderInstrumentationPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + numMetrics: u32, + perBasicBlockGranularity: b32, +} + +ShaderInstrumentationCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, +} + +ShaderInstrumentationMetricDescriptionARM :: struct { + sType: StructureType, + pNext: rawptr, + name: [MAX_DESCRIPTION_SIZE]byte, + description: [MAX_DESCRIPTION_SIZE]byte, +} + +ShaderInstrumentationMetricDataHeaderARM :: struct { + resultIndex: u32, + resultSubIndex: u32, + stages: ShaderStageFlags, + basicBlockIndex: u32, +} + PhysicalDeviceVertexAttributeRobustnessFeaturesEXT :: struct { sType: StructureType, pNext: rawptr, vertexAttributeRobustness: b32, } +PhysicalDeviceFormatPackFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + formatPack: b32, +} + +PhysicalDeviceFragmentDensityMapLayeredFeaturesVALVE :: struct { + sType: StructureType, + pNext: rawptr, + fragmentDensityMapLayered: b32, +} + +PhysicalDeviceFragmentDensityMapLayeredPropertiesVALVE :: struct { + sType: StructureType, + pNext: rawptr, + maxFragmentDensityMapLayers: u32, +} + +PipelineFragmentDensityMapLayeredCreateInfoVALVE :: struct { + sType: StructureType, + pNext: rawptr, + maxFragmentDensityMapLayers: u32, +} + SetPresentConfigNV :: struct { sType: StructureType, pNext: rawptr, @@ -8798,6 +10447,239 @@ PhysicalDevicePresentMeteringFeaturesNV :: struct { presentMetering: b32, } +PhysicalDeviceMultisampledRenderToSwapchainFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + multisampledRenderToSwapchain: b32, +} + +SwapchainFlagsSurfaceCapabilitiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + swapchainSupportedFlags: SwapchainCreateFlagsKHR, +} + +PhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + zeroInitializeDeviceMemory: b32, +} + +PhysicalDeviceShader64BitIndexingFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + shader64BitIndexing: b32, +} + +PhysicalDeviceCustomResolveFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + customResolve: b32, +} + +BeginCustomResolveInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, +} + +CustomResolveCreateInfoEXT :: struct { + sType: StructureType, + pNext: rawptr, + customResolve: b32, + colorAttachmentCount: u32, + pColorAttachmentFormats: [^]Format, + depthAttachmentFormat: Format, + stencilAttachmentFormat: Format, +} + +PipelineCacheHeaderVersionDataGraphQCOM :: struct { + headerSize: u32, + headerVersion: PipelineCacheHeaderVersion, + cacheType: DataGraphModelCacheTypeQCOM, + cacheVersion: u32, + toolchainVersion: [DATA_GRAPH_MODEL_TOOLCHAIN_VERSION_LENGTH_QCOM]u32, +} + +DataGraphPipelineBuiltinModelCreateInfoQCOM :: struct { + sType: StructureType, + pNext: rawptr, + pOperation: ^PhysicalDeviceDataGraphOperationSupportARM, +} + +PhysicalDeviceDataGraphModelFeaturesQCOM :: struct { + sType: StructureType, + pNext: rawptr, + dataGraphModel: b32, +} + +PhysicalDeviceDataGraphOpticalFlowFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + dataGraphOpticalFlow: b32, +} + +QueueFamilyDataGraphOpticalFlowPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + supportedOutputGridSizes: DataGraphOpticalFlowGridSizeFlagsARM, + supportedHintGridSizes: DataGraphOpticalFlowGridSizeFlagsARM, + hintSupported: b32, + costSupported: b32, + minWidth: u32, + minHeight: u32, + maxWidth: u32, + maxHeight: u32, +} + +DataGraphPipelineOpticalFlowCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + width: u32, + height: u32, + imageFormat: Format, + flowVectorFormat: Format, + costFormat: Format, + outputGridSize: DataGraphOpticalFlowGridSizeFlagsARM, + hintGridSize: DataGraphOpticalFlowGridSizeFlagsARM, + performanceLevel: DataGraphOpticalFlowPerformanceLevelARM, + flags: DataGraphOpticalFlowCreateFlagsARM, +} + +DataGraphOpticalFlowImageFormatPropertiesARM :: struct { + sType: StructureType, + pNext: rawptr, + format: Format, +} + +DataGraphOpticalFlowImageFormatInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + usage: DataGraphOpticalFlowImageUsageFlagsARM, +} + +DataGraphPipelineOpticalFlowDispatchInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + flags: DataGraphOpticalFlowExecuteFlagsARM, + meanFlowL1NormHint: u32, +} + +DataGraphPipelineResourceInfoImageLayoutARM :: struct { + sType: StructureType, + pNext: rawptr, + layout: ImageLayout, +} + +DataGraphPipelineSingleNodeConnectionARM :: struct { + sType: StructureType, + pNext: rawptr, + set: u32, + binding: u32, + connection: DataGraphPipelineNodeConnectionTypeARM, +} + +DataGraphPipelineSingleNodeCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + nodeType: DataGraphPipelineNodeTypeARM, + connectionCount: u32, + pConnections: [^]DataGraphPipelineSingleNodeConnectionARM, +} + +PhysicalDeviceShaderLongVectorFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + longVector: b32, +} + +PhysicalDeviceShaderLongVectorPropertiesEXT :: struct { + sType: StructureType, + pNext: rawptr, + maxVectorComponents: u32, +} + +PhysicalDevicePipelineCacheIncrementalModeFeaturesSEC :: struct { + sType: StructureType, + pNext: rawptr, + pipelineCacheIncrementalMode: b32, +} + +PhysicalDeviceShaderUniformBufferUnsizedArrayFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + shaderUniformBufferUnsizedArray: b32, +} + +ComputeOccupancyPriorityParametersNV :: struct { + sType: StructureType, + pNext: rawptr, + occupancyPriority: f32, + occupancyThrottling: f32, +} + +PhysicalDeviceComputeOccupancyPriorityFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + computeOccupancyPriority: b32, +} + +PhysicalDeviceShaderSubgroupPartitionedFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + shaderSubgroupPartitioned: b32, +} + +PhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE :: struct { + sType: StructureType, + pNext: rawptr, + shaderMixedFloatDotProductFloat16AccFloat32: b32, + shaderMixedFloatDotProductFloat16AccFloat16: b32, + shaderMixedFloatDotProductBFloat16Acc: b32, + shaderMixedFloatDotProductFloat8AccFloat32: b32, +} + +ThrottleHintSubmitInfoSEC :: struct { + sType: StructureType, + pNext: rawptr, + throttleHint: ThrottleHintTypeSEC, +} + +PhysicalDeviceThrottleHintFeaturesSEC :: struct { + sType: StructureType, + pNext: rawptr, + throttleHint: b32, +} + +PhysicalDeviceDataGraphNeuralAcceleratorStatisticsFeaturesARM :: struct { + sType: StructureType, + pNext: rawptr, + dataGraphNeuralAcceleratorStatistics: b32, +} + +DataGraphPipelineNeuralStatisticsCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + allowNeuralStatistics: b32, +} + +DataGraphPipelineSessionNeuralStatisticsCreateInfoARM :: struct { + sType: StructureType, + pNext: rawptr, + mode: NeuralAcceleratorStatisticsModeARM, +} + +PhysicalDevicePrimitiveRestartIndexFeaturesEXT :: struct { + sType: StructureType, + pNext: rawptr, + primitiveRestartIndex: b32, +} + +PhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + cooperativeMatrixDecodeVector: b32, +} + AccelerationStructureBuildRangeInfoKHR :: struct { primitiveCount: u32, primitiveOffset: u32, @@ -9443,6 +11325,50 @@ PipelineShaderStageNodeCreateInfoAMDX :: struct { index: u32, } +CudaModuleCreateInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + dataSize: int, + pData: rawptr, +} + +CudaFunctionCreateInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + module: CudaModuleNV, + pName: cstring, +} + +CudaLaunchInfoNV :: struct { + sType: StructureType, + pNext: rawptr, + function: CudaFunctionNV, + gridDimX: u32, + gridDimY: u32, + gridDimZ: u32, + blockDimX: u32, + blockDimY: u32, + blockDimZ: u32, + sharedMemBytes: u32, + paramCount: int, + pParams: [^]rawptr, + extraCount: int, + pExtras: [^]rawptr, +} + +PhysicalDeviceCudaKernelLaunchFeaturesNV :: struct { + sType: StructureType, + pNext: rawptr, + cudaKernelLaunchFeatures: b32, +} + +PhysicalDeviceCudaKernelLaunchPropertiesNV :: struct { + sType: StructureType, + pNext: rawptr, + computeCapabilityMinor: u32, + computeCapabilityMajor: u32, +} + PhysicalDeviceDisplacementMicromapFeaturesNV :: struct { sType: StructureType, pNext: rawptr, @@ -9476,6 +11402,24 @@ AccelerationStructureTrianglesDisplacementMicromapNV :: struct { micromap: MicromapEXT, } +PhysicalDeviceDenseGeometryFormatFeaturesAMDX :: struct { + sType: StructureType, + pNext: rawptr, + denseGeometryFormat: b32, +} + +AccelerationStructureDenseGeometryFormatTrianglesDataAMDX :: struct { + sType: StructureType, + pNext: rawptr, + compressedData: DeviceOrHostAddressConstKHR, + dataSize: DeviceSize, + numTriangles: u32, + numVertices: u32, + maxPrimitiveIndex: u32, + maxGeometryIndex: u32, + format: CompressedTriangleFormatAMDX, +} + VideoAV1ColorConfigFlags :: distinct bit_set[VideoAV1ColorConfigFlag; u32] VideoAV1ColorConfigFlag :: enum u32 { mono_chrome, @@ -10598,6 +12542,85 @@ VideoEncodeH265ReferenceInfo :: struct { TemporalId: u8, } +VideoDecodeVP9PictureInfoFlags :: distinct bit_set[VideoDecodeVP9PictureInfoFlag; u32] +VideoDecodeVP9PictureInfoFlag :: enum u32 { + error_resilient_mode, + intra_only, + allow_high_precision_mv, + refresh_frame_context, + frame_parallel_decoding_mode, + segmentation_enabled, + show_frame, + UsePrevFrameMvs, +} + +VideoDecodeVP9PictureInfo :: struct { + flags: VideoDecodeVP9PictureInfoFlags, + profile: VideoVP9Profile, + frame_type: VideoVP9FrameType, + frame_context_idx: u8, + reset_frame_context: u8, + refresh_frame_flags: u8, + ref_frame_sign_bias_mask: u8, + interpolation_filter: VideoVP9InterpolationFilter, + base_q_idx: u8, + delta_q_y_dc: i8, + delta_q_uv_dc: i8, + delta_q_uv_ac: i8, + tile_cols_log2: u8, + tile_rows_log2: u8, + reserved1: [3]u16, + pColorConfig: ^VideoVP9ColorConfig, + pLoopFilter: ^VideoVP9LoopFilter, + pSegmentation: ^VideoVP9Segmentation, +} + +VideoVP9ColorConfigFlags :: distinct bit_set[VideoVP9ColorConfigFlag; u32] +VideoVP9ColorConfigFlag :: enum u32 { + color_range, +} + +VideoVP9ColorConfig :: struct { + flags: VideoVP9ColorConfigFlags, + BitDepth: u8, + subsampling_x: u8, + subsampling_y: u8, + reserved1: u8, + color_space: VideoVP9ColorSpace, +} + +VideoVP9LoopFilterFlags :: distinct bit_set[VideoVP9LoopFilterFlag; u32] +VideoVP9LoopFilterFlag :: enum u32 { + loop_filter_delta_enabled, + loop_filter_delta_update, +} + +VideoVP9LoopFilter :: struct { + flags: VideoVP9LoopFilterFlags, + loop_filter_level: u8, + loop_filter_sharpness: u8, + update_ref_delta: u8, + loop_filter_ref_deltas: [VIDEO_VP9_MAX_REF_FRAMES]i8, + update_mode_delta: u8, + loop_filter_mode_deltas: [VIDEO_VP9_LOOP_FILTER_ADJUSTMENTS]i8, +} + +VideoVP9SegmentationFlags :: distinct bit_set[VideoVP9SegmentationFlag; u32] +VideoVP9SegmentationFlag :: enum u32 { + segmentation_update_map, + segmentation_temporal_update, + segmentation_update_data, + segmentation_abs_or_delta_update, +} + +VideoVP9Segmentation :: struct { + flags: VideoVP9SegmentationFlags, + segmentation_tree_probs: [VIDEO_VP9_MAX_SEGMENTATION_TREE_PROBS]u8, + segmentation_pred_prob: [VIDEO_VP9_MAX_SEGMENTATION_PRED_PROB]u8, + FeatureEnabled: [VIDEO_VP9_MAX_SEGMENTS]u8, + FeatureData: [VIDEO_VP9_MAX_SEGMENTS][VIDEO_VP9_SEG_LVL_MAX]i16, +} + // Opaque structs wl_surface :: struct {} // Opaque struct defined by Wayland @@ -10833,6 +12856,12 @@ PushDescriptorSetInfoKHR :: PushDescriptorSet PushDescriptorSetWithTemplateInfoKHR :: PushDescriptorSetWithTemplateInfo AccessFlags3KHR :: Flags64 AccessFlag3KHR :: Flags64 +FormatFeatureFlags4KHR :: Flags64 +FormatFeatureFlag4KHR :: Flags64 +ImageUsageFlags2KHR :: Flags64 +ImageUsageFlag2KHR :: Flags64 +ImageCreateFlags2KHR :: Flags64 +ImageCreateFlag2KHR :: Flags64 PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT :: PhysicalDeviceTextureCompressionASTCHDRFeatures PipelineRobustnessBufferBehaviorEXT :: PipelineRobustnessBufferBehavior PipelineRobustnessImageBehaviorEXT :: PipelineRobustnessImageBehavior @@ -10842,6 +12871,9 @@ PipelineRobustnessCreateInfoEXT :: PipelineRobustnes SamplerReductionModeEXT :: SamplerReductionMode SamplerReductionModeCreateInfoEXT :: SamplerReductionModeCreateInfo PhysicalDeviceSamplerFilterMinmaxPropertiesEXT :: PhysicalDeviceSamplerFilterMinmaxProperties +TensorViewCreateFlagsARM :: Flags64 +TensorViewCreateFlagARM :: Flags64 +DeviceAddressRangeEXT :: DeviceAddressRangeKHR PhysicalDeviceInlineUniformBlockFeaturesEXT :: PhysicalDeviceInlineUniformBlockFeatures PhysicalDeviceInlineUniformBlockPropertiesEXT :: PhysicalDeviceInlineUniformBlockProperties WriteDescriptorSetInlineUniformBlockEXT :: WriteDescriptorSetInlineUniformBlock @@ -10862,8 +12894,8 @@ GeometryFlagsNV :: GeometryFlagsKHR GeometryFlagNV :: GeometryFlagKHR GeometryInstanceFlagsNV :: GeometryInstanceFlagsKHR GeometryInstanceFlagNV :: GeometryInstanceFlagKHR -BuildAccelerationStructureFlagsNV :: BuildAccelerationStructureFlagsKHR BuildAccelerationStructureFlagNV :: BuildAccelerationStructureFlagKHR +BuildAccelerationStructureFlagsNV :: BuildAccelerationStructureFlagsKHR TransformMatrixNV :: TransformMatrixKHR AabbPositionsNV :: AabbPositionsKHR AccelerationStructureInstanceNV :: AccelerationStructureInstanceKHR @@ -10913,8 +12945,23 @@ SubresourceHostMemcpySizeEXT :: SubresourceHostMe HostImageCopyDevicePerformanceQueryEXT :: HostImageCopyDevicePerformanceQuery SubresourceLayout2EXT :: SubresourceLayout2 ImageSubresource2EXT :: ImageSubresource2 +PresentScalingFlagEXT :: PresentScalingFlagKHR +PresentScalingFlagsEXT :: PresentScalingFlagsKHR +PresentGravityFlagEXT :: PresentGravityFlagKHR +PresentGravityFlagsEXT :: PresentGravityFlagsKHR +SurfacePresentModeEXT :: SurfacePresentModeKHR +SurfacePresentScalingCapabilitiesEXT :: SurfacePresentScalingCapabilitiesKHR +SurfacePresentModeCompatibilityEXT :: SurfacePresentModeCompatibilityKHR +PhysicalDeviceSwapchainMaintenance1FeaturesEXT :: PhysicalDeviceSwapchainMaintenance1FeaturesKHR +SwapchainPresentFenceInfoEXT :: SwapchainPresentFenceInfoKHR +SwapchainPresentModesCreateInfoEXT :: SwapchainPresentModesCreateInfoKHR +SwapchainPresentModeInfoEXT :: SwapchainPresentModeInfoKHR +SwapchainPresentScalingCreateInfoEXT :: SwapchainPresentScalingCreateInfoKHR +ReleaseSwapchainImagesInfoEXT :: ReleaseSwapchainImagesInfoKHR PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT :: PhysicalDeviceShaderDemoteToHelperInvocationFeatures PhysicalDeviceTexelBufferAlignmentPropertiesEXT :: PhysicalDeviceTexelBufferAlignmentProperties +PhysicalDeviceRobustness2FeaturesEXT :: PhysicalDeviceRobustness2FeaturesKHR +PhysicalDeviceRobustness2PropertiesEXT :: PhysicalDeviceRobustness2PropertiesKHR PrivateDataSlotEXT :: PrivateDataSlot PrivateDataSlotCreateFlagsEXT :: PrivateDataSlotCreateFlags PhysicalDevicePrivateDataFeaturesEXT :: PhysicalDevicePrivateDataFeatures @@ -10922,19 +12969,48 @@ DevicePrivateDataCreateInfoEXT :: DevicePrivateData PrivateDataSlotCreateInfoEXT :: PrivateDataSlotCreateInfo PhysicalDevicePipelineCreationCacheControlFeaturesEXT :: PhysicalDevicePipelineCreationCacheControlFeatures PhysicalDeviceImageRobustnessFeaturesEXT :: PhysicalDeviceImageRobustnessFeatures +DeviceFaultAddressTypeEXT :: DeviceFaultAddressTypeKHR +DeviceFaultVendorBinaryHeaderVersionEXT :: DeviceFaultVendorBinaryHeaderVersionKHR +DeviceFaultAddressInfoEXT :: DeviceFaultAddressInfoKHR +DeviceFaultVendorInfoEXT :: DeviceFaultVendorInfoKHR +DeviceFaultVendorBinaryHeaderVersionOneEXT :: DeviceFaultVendorBinaryHeaderVersionOneKHR PhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM :: PhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT PhysicalDeviceMutableDescriptorTypeFeaturesVALVE :: PhysicalDeviceMutableDescriptorTypeFeaturesEXT MutableDescriptorTypeListVALVE :: MutableDescriptorTypeListEXT MutableDescriptorTypeCreateInfoVALVE :: MutableDescriptorTypeCreateInfoEXT +PhysicalDevicePresentModeFifoLatestReadyFeaturesEXT :: PhysicalDevicePresentModeFifoLatestReadyFeaturesKHR PipelineInfoEXT :: PipelineInfoKHR PhysicalDeviceGlobalPriorityQueryFeaturesEXT :: PhysicalDeviceGlobalPriorityQueryFeatures QueueFamilyGlobalPriorityPropertiesEXT :: QueueFamilyGlobalPriorityProperties +OpacityMicromapFormatEXT :: OpacityMicromapFormatKHR +OpacityMicromapSpecialIndexEXT :: OpacityMicromapSpecialIndexKHR +MicromapTriangleEXT :: MicromapTriangleKHR PhysicalDeviceSchedulingControlsFlagsARM :: Flags64 PhysicalDeviceSchedulingControlsFlagARM :: Flags64 PhysicalDeviceDepthClampZeroOneFeaturesEXT :: PhysicalDeviceDepthClampZeroOneFeaturesKHR -MemoryDecompressionMethodFlagNV :: Flags64 -MemoryDecompressionMethodFlagsNV :: Flags64 +PhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM :: PhysicalDeviceFragmentDensityMapOffsetFeaturesEXT +PhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM :: PhysicalDeviceFragmentDensityMapOffsetPropertiesEXT +SubpassFragmentDensityMapOffsetEndInfoQCOM :: RenderPassFragmentDensityMapOffsetEndInfoEXT +CopyMemoryIndirectCommandNV :: CopyMemoryIndirectCommandKHR +CopyMemoryToImageIndirectCommandNV :: CopyMemoryToImageIndirectCommandKHR +PhysicalDeviceCopyMemoryIndirectPropertiesNV :: PhysicalDeviceCopyMemoryIndirectPropertiesKHR +MemoryDecompressionMethodFlagEXT :: Flags64 +MemoryDecompressionMethodFlagNV :: MemoryDecompressionMethodFlagEXT +MemoryDecompressionMethodFlagsEXT :: Flags64 +MemoryDecompressionMethodFlagsNV :: MemoryDecompressionMethodFlagsEXT +PhysicalDeviceMemoryDecompressionFeaturesNV :: PhysicalDeviceMemoryDecompressionFeaturesEXT +PhysicalDeviceMemoryDecompressionPropertiesNV :: PhysicalDeviceMemoryDecompressionPropertiesEXT +TensorCreateFlagsARM :: Flags64 +TensorCreateFlagARM :: Flags64 +TensorUsageFlagsARM :: Flags64 +TensorUsageFlagARM :: Flags64 PhysicalDevicePipelineProtectedAccessFeaturesEXT :: PhysicalDevicePipelineProtectedAccessFeatures ShaderRequiredSubgroupSizeCreateInfoEXT :: PipelineShaderStageRequiredSubgroupSizeCreateInfo +RayTracingInvocationReorderModeNV :: RayTracingInvocationReorderModeEXT +DataGraphPipelineSessionCreateFlagsARM :: Flags64 +DataGraphPipelineSessionCreateFlagARM :: Flags64 +DataGraphPipelineDispatchFlagsARM :: Flags64 +DataGraphPipelineDispatchFlagARM :: Flags64 +RenderingEndInfoEXT :: RenderingEndInfoKHR diff --git a/vendor/wasm/WebGL/webgl.odin b/vendor/wasm/WebGL/webgl.odin index 96d363ba2..6338d6271 100644 --- a/vendor/wasm/WebGL/webgl.odin +++ b/vendor/wasm/WebGL/webgl.odin @@ -3,6 +3,7 @@ package webgl foreign import "webgl" import glm "core:math/linalg/glsl" +import "base:runtime" Enum :: distinct u32 @@ -25,6 +26,12 @@ ContextAttribute :: enum u32 { } ContextAttributes :: distinct bit_set[ContextAttribute; u32] +ActiveInfo :: struct { + size: int, + type: Enum, + name: string, +} + DEFAULT_CONTEXT_ATTRIBUTES :: ContextAttributes{} @(default_calling_convention="contextless") @@ -45,6 +52,7 @@ foreign webgl { GetError :: proc() -> Enum --- IsExtensionSupported :: proc(name: string) -> bool --- + GetExtension :: proc(name: string) --- ActiveTexture :: proc(x: Enum) --- AttachShader :: proc(program: Program, shader: Shader) --- @@ -52,6 +60,7 @@ foreign webgl { BindBuffer :: proc(target: Enum, buffer: Buffer) --- BindFramebuffer :: proc(target: Enum, framebuffer: Framebuffer) --- BindTexture :: proc(target: Enum, texture: Texture) --- + BindRenderbuffer :: proc(target: Enum, renderbuffer: Renderbuffer) --- BlendColor :: proc(red, green, blue, alpha: f32) --- BlendEquation :: proc(mode: Enum) --- BlendEquationSeparate :: proc(modeRGB: Enum, modeAlpha: Enum) --- @@ -105,10 +114,12 @@ foreign webgl { Flush :: proc() --- FramebufferRenderbuffer :: proc(target, attachment, renderbufertarget: Enum, renderbuffer: Renderbuffer) --- FramebufferTexture2D :: proc(target, attachment, textarget: Enum, texture: Texture, level: i32) --- + CheckFramebufferStatus :: proc(target: Enum) -> Enum --- FrontFace :: proc(mode: Enum) --- GenerateMipmap :: proc(target: Enum) --- + GetBufferParameter :: proc(target, name: Enum) -> int --- GetAttribLocation :: proc(program: Program, name: string) -> i32 --- GetUniformLocation :: proc(program: Program, name: string) -> i32 --- GetVertexAttribOffset :: proc(index: i32, pname: Enum) -> uintptr --- @@ -172,14 +183,63 @@ foreign webgl { Viewport :: proc(x, y, w, h: i32) --- } -Uniform1fv :: proc "contextless" (location: i32, v: f32) { Uniform1f(location, v) } -Uniform2fv :: proc "contextless" (location: i32, v: glm.vec2) { Uniform2f(location, v.x, v.y) } -Uniform3fv :: proc "contextless" (location: i32, v: glm.vec3) { Uniform3f(location, v.x, v.y, v.z) } -Uniform4fv :: proc "contextless" (location: i32, v: glm.vec4) { Uniform4f(location, v.x, v.y, v.z, v.w) } -Uniform1iv :: proc "contextless" (location: i32, v: i32) { Uniform1i(location, v) } -Uniform2iv :: proc "contextless" (location: i32, v: glm.ivec2) { Uniform2i(location, v.x, v.y) } -Uniform3iv :: proc "contextless" (location: i32, v: glm.ivec3) { Uniform3i(location, v.x, v.y, v.z) } -Uniform4iv :: proc "contextless" (location: i32, v: glm.ivec4) { Uniform4i(location, v.x, v.y, v.z, v.w) } +Uniform1fv :: proc "contextless" (location: i32, v: []f32) { + foreign webgl { + @(link_name="Uniform1fv") + _Uniform1fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform1fv(location, len(v), &v[0]) +} +Uniform2fv :: proc "contextless" (location: i32, v: []glm.vec2) { + foreign webgl { + @(link_name="Uniform2fv") + _Uniform2fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform2fv(location, len(v), &v[0].x) +} +Uniform3fv :: proc "contextless" (location: i32, v: []glm.vec3) { + foreign webgl { + @(link_name="Uniform3fv") + _Uniform3fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform3fv(location, len(v), &v[0].x) +} +Uniform4fv :: proc "contextless" (location: i32, v: []glm.vec4) { + foreign webgl { + @(link_name="Uniform4fv") + _Uniform4fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform4fv(location, len(v), &v[0].x) +} + +Uniform1iv :: proc "contextless" (location: i32, v: []i32) { + foreign webgl { + @(link_name="Uniform1iv") + _Uniform1iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform1iv(location, len(v), &v[0]) +} +Uniform2iv :: proc "contextless" (location: i32, v: []glm.ivec2) { + foreign webgl { + @(link_name="Uniform2iv") + _Uniform2iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform2iv(location, len(v), &v[0].x) +} +Uniform3iv :: proc "contextless" (location: i32, v: []glm.ivec3) { + foreign webgl { + @(link_name="Uniform3iv") + _Uniform3iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform3iv(location, len(v), &v[0].x) +} +Uniform4iv :: proc "contextless" (location: i32, v: []glm.ivec4) { + foreign webgl { + @(link_name="Uniform4iv") + _Uniform4iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform4iv(location, len(v), &v[0].x) +} VertexAttrib1fv :: proc "contextless" (index: i32, v: f32) { VertexAttrib1f(index, v) } VertexAttrib2fv :: proc "contextless" (index: i32, v: glm.vec2){ VertexAttrib2f(index, v.x, v.y) } @@ -210,7 +270,6 @@ UniformMatrix4fv :: proc "contextless" (location: i32, m: glm.mat4) { value := transmute([4*4]f32)m _UniformMatrix4fv(location, &value[0]) } - GetShaderiv :: proc "contextless" (shader: Shader, pname: Enum) -> (p: i32) { foreign webgl { @(link_name="GetShaderiv") @@ -220,6 +279,79 @@ GetShaderiv :: proc "contextless" (shader: Shader, pname: Enum) -> (p: i32) { return } +GetActiveAttribBuf :: proc "contextless" (program: Program, index: u32, name_buf: []byte) -> (info: ActiveInfo) { + foreign webgl { + @(link_name="GetActiveAttrib") + _GetActiveAttrib :: proc "contextless" (shader: Program, index: u32, size: ^int, type: ^Enum, name_buf: []byte, name_len: ^int) --- + } + name_len: int + _GetActiveAttrib(program, index, &info.size, &info.type, name_buf, &name_len) + info.name = string(name_buf[:name_len]) + return +} + +GetActiveAttribAlloc :: proc(program: Program, index: u32, allocator: runtime.Allocator, loc := #caller_location) -> (info: ActiveInfo) { + foreign webgl { + @(link_name="GetActiveAttrib") + _GetActiveAttrib :: proc "contextless" (shader: Program, index: u32, size: ^int, type: ^Enum, name_buf: []byte, name_len: ^int) --- + } + + name_len: int + + // Passing {} to the buf but giving it a name_len ptr will write the needed len into that int + _GetActiveAttrib(program, index, &info.size, &info.type, {}, &name_len) + + if name_len > 0 { + name_buf := make([]byte, name_len, allocator, loc) + _GetActiveAttrib(program, index, &info.size, &info.type, name_buf, &name_len) + assert(name_len == len(name_buf)) + info.name = string(name_buf[:name_len]) + } + + return +} + +GetActiveAttrib :: proc { + GetActiveAttribBuf, + GetActiveAttribAlloc, +} + +GetActiveUniformBuf :: proc "contextless" (program: Program, index: u32, name_buf: []byte) -> (info: ActiveInfo) { + foreign webgl { + @(link_name="GetActiveUniform") + _GetActiveUniform :: proc "contextless" (shader: Program, index: u32, size: ^int, type: ^Enum, name_buf: []byte, name_len: ^int) --- + } + name_len: int + _GetActiveUniform(program, index, &info.size, &info.type, name_buf, &name_len) + info.name = string(name_buf[:name_len]) + return +} + +GetActiveUniformAlloc :: proc(program: Program, index: u32, allocator: runtime.Allocator, loc := #caller_location) -> (info: ActiveInfo) { + foreign webgl { + @(link_name="GetActiveUniform") + _GetActiveUniform :: proc "contextless" (shader: Program, index: u32, size: ^int, type: ^Enum, name_buf: []byte, name_len: ^int) --- + } + + name_len: int + + // Passing {} to the buf but giving it a name_len ptr will write the needed len into that int + _GetActiveUniform(program, index, &info.size, &info.type, {}, &name_len) + + if name_len > 0 { + name_buf := make([]byte, name_len, allocator, loc) + _GetActiveUniform(program, index, &info.size, &info.type, name_buf, &name_len) + assert(name_len == len(name_buf)) + info.name = string(name_buf[:name_len]) + } + + return +} + +GetActiveUniform :: proc { + GetActiveUniformBuf, + GetActiveUniformAlloc, +} GetProgramInfoLog :: proc "contextless" (program: Program, buf: []byte) -> string { foreign webgl { @@ -243,7 +375,21 @@ GetShaderInfoLog :: proc "contextless" (shader: Shader, buf: []byte) -> string { return string(buf[:length]) } +IterateSupportedExtensions :: proc(index: ^int, buf: []byte) -> (string, bool) { + foreign webgl { + @(link_name="GetSupportedExtensionFromIndex") + _GetSupportedExtensionFromIndex :: proc "contextless" (index: int, buf: []byte, length: ^int) -> bool --- + } + length: int + if !_GetSupportedExtensionFromIndex(index^, buf[:], &length) { + return "", false + } + + index^ += 1 + + return string(buf[:length]), true +} BufferDataSlice :: proc "contextless" (target: Enum, slice: $S/[]$E, usage: Enum) { BufferData(target, len(slice)*size_of(E), raw_data(slice), usage) diff --git a/vendor/wasm/WebGL/webgl2.odin b/vendor/wasm/WebGL/webgl2.odin index 74f0534d7..677287bd1 100644 --- a/vendor/wasm/WebGL/webgl2.odin +++ b/vendor/wasm/WebGL/webgl2.odin @@ -3,6 +3,7 @@ package webgl foreign import "webgl2" import "base:intrinsics" +import "base:runtime" import glm "core:math/linalg/glsl" Query :: distinct u32 @@ -34,9 +35,10 @@ foreign webgl2 { RenderbufferStorageMultisample :: proc(target: Enum, samples: i32, internalformat: Enum, width, height: i32) --- /* Texture objects */ + TexStorage2D :: proc(target: Enum, levels: i32, internalformat: Enum, width, height: i32) --- TexStorage3D :: proc(target: Enum, levels: i32, internalformat: Enum, width, height, depth: i32) --- TexImage3D :: proc(target: Enum, level: i32, internalformat: Enum, width, height, depth: i32, border: i32, format, type: Enum, size: int, data: rawptr) --- - TexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, width, height, depth: i32, format, type: Enum, size: int, data: rawptr) --- + TexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: Enum, size: int, data: rawptr) --- CompressedTexImage3D :: proc(target: Enum, level: i32, internalformat: Enum, width, height, depth: i32, border: i32, imageSize: int, data: rawptr) --- CompressedTexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset: i32, width, height, depth: i32, format: Enum, imageSize: int, data: rawptr) --- CopyTexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, zoffset: i32, x, y, width, height: i32) --- @@ -103,14 +105,21 @@ foreign webgl2 { GetUniformBlockIndex :: proc(program: Program, uniformBlockName: string) -> i32 --- UniformBlockBinding :: proc(program: Program, uniformBlockIndex: i32, uniformBlockBinding: i32) --- + // if `pname` is `UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES` then an array will be written at + // `params`, in that case the length `params` need to have is given first querying using `pname` + // `UNIFORM_BLOCK_ACTIVE_UNIFORMS`. + GetActiveUniformBlockParameter :: proc(program: Program, uniformBlockIndex: i32, pname: Enum, params: [^]i32) --- + GetActiveUniforms :: proc(program: Program, uniformIndices: []u32, pname: Enum, res: [^]i32) --- + CreateVertexArray :: proc() -> VertexArrayObject --- DeleteVertexArray :: proc(vertexArray: VertexArrayObject) --- IsVertexArray :: proc(vertexArray: VertexArrayObject) -> bool --- BindVertexArray :: proc(vertexArray: VertexArrayObject) --- } -GetActiveUniformBlockName :: proc(program: Program, uniformBlockIndex: i32, buf: []byte) -> string { +GetActiveUniformBlockNameBuf :: proc(program: Program, uniformBlockIndex: i32, buf: []byte) -> string { foreign webgl2 { + @(link_name="GetActiveUniformBlockName") _GetActiveUniformBlockName :: proc "contextless" (program: Program, uniformBlockIndex: i32, buf: []byte, length: ^int) --- } n: int @@ -118,6 +127,28 @@ GetActiveUniformBlockName :: proc(program: Program, uniformBlockIndex: i32, buf: return string(buf[:n]) } +GetActiveUniformBlockNameAlloc :: proc(program: Program, uniformBlockIndex: i32, allocator: runtime.Allocator, loc := #caller_location) -> string { + foreign webgl2 { + @(link_name="GetActiveUniformBlockName") + _GetActiveUniformBlockName :: proc "contextless" (program: Program, uniformBlockIndex: i32, buf: []byte, length: ^int) --- + } + n: int + _GetActiveUniformBlockName(program, uniformBlockIndex, {}, &n) + + if n > 0 { + buf := make([]byte, n, allocator, loc) + _GetActiveUniformBlockName(program, uniformBlockIndex, buf, &n) + assert(n == len(buf)) + return string(buf[:n]) + } + + return "" +} + +GetActiveUniformBlockName :: proc { + GetActiveUniformBlockNameBuf, + GetActiveUniformBlockNameAlloc, +} Uniform1uiv :: proc "contextless" (location: i32, v: u32) { Uniform1ui(location, v) @@ -134,6 +165,7 @@ Uniform4uiv :: proc "contextless" (location: i32, v: glm.uvec4) { UniformMatrix3x2fv :: proc "contextless" (location: i32, m: glm.mat3x2) { foreign webgl2 { + @(link_name="UniformMatrix3x2fv") _UniformMatrix3x2fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) @@ -141,6 +173,7 @@ UniformMatrix3x2fv :: proc "contextless" (location: i32, m: glm.mat3x2) { } UniformMatrix4x2fv :: proc "contextless" (location: i32, m: glm.mat4x2) { foreign webgl2 { + @(link_name="UniformMatrix4x2fv") _UniformMatrix4x2fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) @@ -148,6 +181,7 @@ UniformMatrix4x2fv :: proc "contextless" (location: i32, m: glm.mat4x2) { } UniformMatrix2x3fv :: proc "contextless" (location: i32, m: glm.mat2x3) { foreign webgl2 { + @(link_name="UniformMatrix2x3fv") _UniformMatrix2x3fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) @@ -155,6 +189,7 @@ UniformMatrix2x3fv :: proc "contextless" (location: i32, m: glm.mat2x3) { } UniformMatrix4x3fv :: proc "contextless" (location: i32, m: glm.mat4x3) { foreign webgl2 { + @(link_name="UniformMatrix4x3fv") _UniformMatrix4x3fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) @@ -162,6 +197,7 @@ UniformMatrix4x3fv :: proc "contextless" (location: i32, m: glm.mat4x3) { } UniformMatrix2x4fv :: proc "contextless" (location: i32, m: glm.mat2x4) { foreign webgl2 { + @(link_name="UniformMatrix2x4fv") _UniformMatrix2x4fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) @@ -169,6 +205,7 @@ UniformMatrix2x4fv :: proc "contextless" (location: i32, m: glm.mat2x4) { } UniformMatrix3x4fv :: proc "contextless" (location: i32, m: glm.mat3x4) { foreign webgl2 { + @(link_name="UniformMatrix3x4fv") _UniformMatrix3x4fv :: proc "contextless" (location: i32, addr: [^]f32) --- } array := intrinsics.matrix_flatten(m) diff --git a/vendor/wgpu/doc.odin b/vendor/wgpu/doc.odin index a538c53c1..5f72b9147 100644 --- a/vendor/wgpu/doc.odin +++ b/vendor/wgpu/doc.odin @@ -12,8 +12,8 @@ You can find a number of examples on [[Odin's official examples repository; http **Getting the wgpu-native libraries** For native support (not the browser), some libraries are required. Fortunately this is -extremely easy, just download them from the [[releases on GitHub; https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2]]. -the bindings are for v24.0.0.2 at the moment. +extremely easy, just download them from the [[releases on GitHub; https://github.com/gfx-rs/wgpu-native/releases/tag/v29.0.0.0]]. +the bindings are for v29.0.0.0 at the moment. These are expected in the `lib` folder under the same name as they are released (just unzipped). By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`), diff --git a/vendor/wgpu/glfwglue/doc.odin b/vendor/wgpu/glfwglue/doc.odin new file mode 100644 index 000000000..65716dd91 --- /dev/null +++ b/vendor/wgpu/glfwglue/doc.odin @@ -0,0 +1,2 @@ +// WGPU glue for GLFW. +package wgpu_glfw_glue \ No newline at end of file diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll index 7fa1c8398..574cdda82 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib index 072c4b234..33443a527 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll.lib differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib index 787feaede..7c089da19 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib differ diff --git a/vendor/wgpu/sdl2glue/doc.odin b/vendor/wgpu/sdl2glue/doc.odin new file mode 100644 index 000000000..13d7eb103 --- /dev/null +++ b/vendor/wgpu/sdl2glue/doc.odin @@ -0,0 +1,2 @@ +// WGPU glue for SDL2. +package wgpu_sdl2_glue diff --git a/vendor/wgpu/sdl3glue/doc.odin b/vendor/wgpu/sdl3glue/doc.odin new file mode 100644 index 000000000..e95ed5c47 --- /dev/null +++ b/vendor/wgpu/sdl3glue/doc.odin @@ -0,0 +1,2 @@ +// WGPU glue for SDL3. +package wgpu_sdl3_glue \ No newline at end of file diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 578c1aefc..671b4a258 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -4,7 +4,7 @@ const STATUS_SUCCESS = 1; const STATUS_ERROR = 2; const ENUMS = { - FeatureName: [undefined, "depth-clip-control", "depth32float-stencil8", "timestamp-query", "texture-compression-bc", "texture-compression-bc-sliced-3d", "texture-compression-etc2", "texture-compression-astc", "texture-compression-astc-sliced-3d", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", "float32-blendable", "clip-distances", "dual-source-blending" ], + FeatureName: [undefined, "core-features-and-limits", "depth-clip-control", "depth32float-stencil8", "texture-compression-bc", "texture-compression-bc-sliced-3d", "texture-compression-etc2", "texture-compression-astc", "texture-compression-astc-sliced-3d", "timestamp-query", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", "float32-blendable", "clip-distances", "dual-source-blending", "subgroups", "texture-formats-tier1", "texture-formats-tier2", "primitive-index", "texture-component-swizzle" ], StoreOp: [undefined, "store", "discard", ], LoadOp: [undefined, "load", "clear", ], BufferBindingType: [null, undefined, "uniform", "storage", "read-only-storage", ], @@ -12,9 +12,9 @@ const ENUMS = { TextureSampleType: [null, undefined, "float", "unfilterable-float", "depth", "sint", "uint", ], TextureViewDimension: [undefined, "1d", "2d", "2d-array", "cube", "cube-array", "3d", ], StorageTextureAccess: [null, undefined, "write-only", "read-only", "read-write", ], - TextureFormat: [undefined, "r8unorm", "r8snorm", "r8uint", "r8sint", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", ], + TextureFormat: [undefined, "r8unorm", "r8snorm", "r8uint", "r8sint", "r16unorm", "r16snorm", "r16uint", "r16sint", "r16float", "rg8unorm", "rg8snorm", "rg8uint", "rg8sint", "r32float", "r32uint", "r32sint", "rg16unorm", "rg16snorm", "rg16uint", "rg16sint", "rg16float", "rgba8unorm", "rgba8unorm-srgb", "rgba8snorm", "rgba8uint", "rgba8sint", "bgra8unorm", "bgra8unorm-srgb", "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rgb9e5ufloat", "rg32float", "rg32uint", "rg32sint", "rgba16unorm", "rgba16snorm", "rgba16uint", "rgba16sint", "rgba16float", "rgba32float", "rgba32uint", "rgba32sint", "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", "bc2-rgba-unorm-srgb", "bc3-rgba-unorm", "bc3-rgba-unorm-srgb", "bc4-r-unorm", "bc4-r-snorm", "bc5-rg-unorm", "bc5-rg-snorm", "bc6h-rgb-ufloat", "bc6h-rgb-float", "bc7-rgba-unorm", "bc7-rgba-unorm-srgb", "etc2-rgb8unorm", "etc2-rgb8unorm-srgb", "etc2-rgb8a1unorm", "etc2-rgb8a1unorm-srgb", "etc2-rgba8unorm", "etc2-rgba8unorm-srgb", "eac-r11unorm", "eac-r11snorm", "eac-rg11unorm", "eac-rg11snorm", "astc-4x4-unorm", "astc-4x4-unorm-srgb", "astc-5x4-unorm", "astc-5x4-unorm-srgb", "astc-5x5-unorm", "astc-5x5-unorm-srgb", "astc-6x5-unorm", "astc-6x5-unorm-srgb", "astc-6x6-unorm", "astc-6x6-unorm-srgb", "astc-8x5-unorm", "astc-8x5-unorm-srgb", "astc-8x6-unorm", "astc-8x6-unorm-srgb", "astc-8x8-unorm", "astc-8x8-unorm-srgb", "astc-10x5-unorm", "astc-10x5-unorm-srgb", "astc-10x6-unorm", "astc-10x6-unorm-srgb", "astc-10x8-unorm", "astc-10x8-unorm-srgb", "astc-10x10-unorm", "astc-10x10-unorm-srgb", "astc-12x10-unorm", "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", ], QueryType: [undefined, "occlusion", "timestamp", ], - VertexStepMode: [null, undefined, "vertex", "instance", ], + VertexStepMode: [undefined, "vertex", "instance", ], VertexFormat: [undefined, "uint8", "uint8x2", "uint8x4", "sint8", "sint8x2", "sint8x4", "unorm8", "unorm8x2", "unorm8x4", "snorm8", "snorm8x2", "snorm8x4", "uint16", "uint16x2", "uint16x4", "sint16", "sint16x2", "sint16x4", "unorm16", "unorm16x2", "unorm16x4", "snorm16", "snorm16x2", "snorm16x4", "float16", "float16x2", "float16x4", "float32", "float32x2", "float32x3", "float32x4", "uint32", "uint32x2", "uint32x3", "uint32x4", "sint32", "sint32x2", "sint32x3", "sint32x4", "unorm10-10-2", "unorm8x4-bgra" ], PrimitiveTopology: [undefined, "point-list", "line-list", "line-strip", "triangle-list", "triangle-strip", ], IndexFormat: [undefined, "uint16", "uint32", ], @@ -26,7 +26,7 @@ const ENUMS = { CompareFunction: [undefined, "never", "less", "equal", "less-equal", "greater", "not-equal", "greater-equal", "always", ], TextureDimension: [undefined, "1d", "2d", "3d", ], ErrorType: [undefined, "no-error", "validation", "out-of-memory", "internal", "unknown", ], - WGSLLanguageFeatureName: [undefined, "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", ], + WGSLLanguageFeatureName: [undefined, "readonly_and_readwrite_storage_textures", "packed_4x8_integer_dot_product", "unrestricted_pointer_parameters", "pointer_composite_access", "uniform_buffer_standard_layout", "subgroup_id", "texture_and_sampler_let", "subgroup_uniformity", "texture_formats_tier1" ], PowerPreference: [undefined, "low-power", "high-performance", ], CompositeAlphaMode: ["auto", "opaque", "premultiplied", "unpremultiplied", "inherit", ], StencilOperation: [undefined, "keep", "zero", "replace", "invert", "increment-clamp", "decrement-clamp", "increment-wrap", "decrement-wrap", ], @@ -34,20 +34,25 @@ const ENUMS = { BlendFactor: [undefined, "zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", "src1", "one-minus-src1", "src1-alpha", "one-minus-src1-alpha" ], PresentMode: [undefined, "fifo", "fifo-relaxed", "immediate", "mailbox", ], TextureAspect: [undefined, "all", "stencil-only", "depth-only"], - DeviceLostReason: [undefined, "unknown", "destroyed", "instance-dropped", "failed-creation"], + DeviceLostReason: [undefined, "unknown", "destroyed", "callback-cancelled", "failed-creation"], BufferMapState: [undefined, "unmapped", "pending", "mapped"], OptionalBool: [false, true, undefined], + ComponentSwizzle: [undefined, "0", "1", "r", "g", "b", "a"], + PredefinedColorSpace: [undefined, "srgb", "display-p3"], + ToneMappingMode: [undefined, "standard", "extended"], + FeatureLevel: [undefined, "compatibility", "core"], + TextureViewDimensions: [undefined, "1d", "2d", "2d-array", "cube", "cube-array", "3d"], // WARN: used with indexOf to pass to WASM, if we would pass to JS, this needs to use official naming convention (not like Odin enums) like the ones above. BackendType: [undefined, null, "WebGPU", "D3D11", "D3D12", "Metal", "Vulkan", "OpenGL", "OpenGLES"], AdapterType: [undefined, "DiscreteGPU", "IntegratedGPU", "CPU", "Unknown"], - RequestDeviceStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], - MapAsyncStatus: [undefined, "Success", "InstanceDropped", "Error", "Aborted", "Unknown"], - CreatePipelineAsyncStatus: [undefined, "Success", "InstanceDropped", "ValidationError", "InternalError", "Unknown"], - PopErrorScopeStatus: [undefined, "Success", "InstanceDropped", "EmptyStack"], - RequestAdapterStatus: [undefined, "Success", "InstanceDropped", "Unavailable", "Error", "Unknown"], - QueueWorkDoneStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], - CompilationInfoRequestStatus: [undefined, "Success", "InstanceDropped", "Error", "Unknown"], + RequestDeviceStatus: [undefined, "Success", "CallbackCancelled", "Error"], + MapAsyncStatus: [undefined, "Success", "CallbackCancelled", "Error", "Aborted"], + CreatePipelineAsyncStatus: [undefined, "Success", "CallbackCancelled", "ValidationError", "InternalError"], + PopErrorScopeStatus: [undefined, "Success", "CallbackCancelled", "Error"], + RequestAdapterStatus: [undefined, "Success", "CallbackCancelled", "Unavailable", "Error"], + QueueWorkDoneStatus: [undefined, "Success", "CallbackCancelled", "Error"], + CompilationInfoRequestStatus: [undefined, "Success", "CallbackCancelled"], }; /** @@ -71,7 +76,7 @@ class WebGPUInterface { StorageTextureBindingLayout: [16, 4], StringView: [2*this.mem.intSize, this.mem.intSize], ConstantEntry: [this.mem.intSize === 8 ? 32 : 24, 8], - ProgrammableStageDescriptor: [8 + this.mem.intSize*4, this.mem.intSize], + ComputeState: [8 + this.mem.intSize*4, this.mem.intSize], VertexBufferLayout: [16 + this.mem.intSize*2, 8], VertexAttribute: [24, 8], VertexState: [8 + this.mem.intSize*6, this.mem.intSize], @@ -87,7 +92,7 @@ class WebGPUInterface { UncapturedErrorCallbackInfo: [16, 4], RenderPassColorAttachment: [56, 8], BindGroupEntry: [40, 8], - BindGroupLayoutEntry: [80, 8], + BindGroupLayoutEntry: [88, 8], Extent3D: [12, 4], CompilationMessage: [this.mem.intSize == 8 ? 64 : 48, 8], }; @@ -158,6 +163,9 @@ class WebGPUInterface { /** @type {WebGPUObjectManager} */ this.textureViews = new WebGPUObjectManager("TextureView", this.mem); + /** @type {WebGPUObjectManager} */ + this.externalTextures = new WebGPUObjectManager("ExternalTexture", this.mem); + this.zeroMessageAddr = 0; } @@ -341,21 +349,38 @@ class WebGPUInterface { return STATUS_SUCCESS; } - genericGetAdapterInfo(infoPtr) { + /** + * @param {number} infoPtr + * @param {GPUAdapterInfo} info + */ + genericGetAdapterInfo(infoPtr, info) { this.assert(infoPtr != 0); const off = this.struct(infoPtr); off(4); // nextInChain - off(this.sizes.StringView); // vendor - off(this.sizes.StringView); // architecture - off(this.sizes.StringView); // device - off(this.sizes.StringView); // description + + const storeString = (start, str) => { + const len = new TextEncoder().encode(str).length; + const strAddr = this.mem.exports.wgpu_alloc(len); + this.mem.storeString(strAddr, str); + + this.mem.storeI32(start, strAddr); + this.mem.storeUint(start + this.mem.intSize, len); + }; + + storeString(off(this.sizes.StringView), info.vendor); + storeString(off(this.sizes.StringView), info.architecture); + storeString(off(this.sizes.StringView), info.device); + storeString(off(this.sizes.StringView), info.description); this.mem.storeI32(off(4), ENUMS.BackendType.indexOf("WebGPU")); this.mem.storeI32(off(4), ENUMS.AdapterType.indexOf("Unknown")); - // NOTE: I don't think getting the other fields in this struct is possible. - // `adapter.requestAdapterInfo` is deprecated. + off(4); // vendorID + off(4); // deviceID + + this.mem.storeI32(off(4), info.subGroupMinSize); + this.mem.storeI32(off(4), info.subGroupMaxSize); return STATUS_SUCCESS; } @@ -461,15 +486,15 @@ class WebGPUInterface { /** * @param {number} ptr - * @returns {GPUComputePassTimestampWrites} */ - ComputePassTimestampWritesPtr(ptr) { + PassTimestampWritesPtr(ptr) { const start = this.mem.loadPtr(ptr); if (start == 0) { return undefined; } const off = this.struct(start); + off(4); // nextInChain return { querySet: this.querySets.get(this.mem.loadPtr(off(4))), beginningOfPassWriteIndex: this.mem.loadU32(off(4)), @@ -529,7 +554,7 @@ class WebGPUInterface { } const off = this.struct(start); - + off(4); // nextInChain return { view: this.textureViews.get(this.mem.loadPtr(off(4))), depthLoadOp: this.enumeration("LoadOp", off(4)), @@ -556,14 +581,6 @@ class WebGPUInterface { return this.querySets.get(ptr); } - /** - * @param {number} ptr - * @returns {GPURenderPassTimestampWrites} - */ - RenderPassTimestampWritesPtr(ptr) { - return this.ComputePassTimestampWritesPtr(ptr); - } - /** * @param {number} start * @returns {GPUOrigin3D} @@ -626,12 +643,13 @@ class WebGPUInterface { off(4); const entry = { - binding: this.mem.loadU32(off(4)), - visibility: this.mem.loadU64(off(8)), - buffer: this.BufferBindingLayout(off(this.sizes.BufferBindingLayout)), - sampler: this.SamplerBindingLayout(off(this.sizes.SamplerBindingLayout)), - texture: this.TextureBindingLayout(off(this.sizes.TextureBindingLayout)), - storageTexture: this.StorageTextureBindingLayout(off(this.sizes.StorageTextureBindingLayout)), + binding: this.mem.loadU32(off(4)), + visibility: this.mem.loadU64(off(8)), + bindingArraySize: this.mem.loadU32(off(4)), + buffer: this.BufferBindingLayout(off(this.sizes.BufferBindingLayout)), + sampler: this.SamplerBindingLayout(off(this.sizes.SamplerBindingLayout)), + texture: this.TextureBindingLayout(off(this.sizes.TextureBindingLayout)), + storageTexture: this.StorageTextureBindingLayout(off(this.sizes.StorageTextureBindingLayout)), }; if (!entry.buffer.type) { entry.buffer = undefined; @@ -696,9 +714,9 @@ class WebGPUInterface { /** * @param {number} start - * @returns {GPUProgrammableStage} + * @returns {GPUComputeState} */ - ProgrammableStageDescriptor(start) { + ComputeState(start) { const off = this.struct(start); off(4); @@ -749,7 +767,7 @@ class WebGPUInterface { return { label: label, layout: layoutIdx > 0 ? this.pipelineLayouts.get(layoutIdx) : "auto", - compute: this.ProgrammableStageDescriptor(off(this.sizes.ProgrammableStageDescriptor)), + compute: this.ComputeState(off(this.sizes.ComputeState)), }; } @@ -793,11 +811,9 @@ class WebGPUInterface { */ VertexBufferLayout(start) { const off = this.struct(start); + off(4); // nextInChain const stepMode = this.enumeration("VertexStepMode", off(4)); - if (stepMode == null) { - return null; - } return { arrayStride: this.mem.loadU64(off(8)), @@ -817,6 +833,7 @@ class WebGPUInterface { */ VertexAttribute(start) { const off = this.struct(start); + off(4); // nextInChain return { format: this.enumeration("VertexFormat", off(4)), offset: this.mem.loadU64(off(8)), @@ -1117,12 +1134,26 @@ class WebGPUInterface { }, /** - * @param {number} capabilitiesPtr - * @returns {number} + * @param {number} featuresPtr */ - wgpuGetInstanceCapabilities: (capabilitiesPtr) => { + wgpuGetInstanceFeatures: (featuresPtr) => { // TODO: implement (futures). - return STATUS_ERROR; + }, + + /** + * @param {number} limitsPtr + */ + wgpuGetInstanceLimits: (limitsPtr) => { + // TODO: implement (futures). + }, + + /** + * @param {number} feature + * @returns {boolean} + */ + wgpuHasInstanceFeature: (feature) => { + // TODO: implement (futures). + return false; }, /** @@ -1389,6 +1420,30 @@ class WebGPUInterface { return BigInt(0); }, + /** + * @param {number} bufferIdx + * @param {number|BigInt} offset + * @param {number} ptr + * @param {number|BigInt} size + * @return {number} + */ + wgpuBufferReadMappedRange: (bufferIdx, offset, ptr, size) => { + const buffer = this.buffers.get(bufferIdx); + offset = this.unwrapBigInt(offset); + size = this.unwrapBigInt(size); + + this.assert(!buffer.mapping, "buffer already mapped"); + + const range = buffer.buffer.getMappedRange(offset, size); + + const mapping = new Uint8Array(this.mem.memory.buffer, ptr, size); + mapping.set(new Uint8Array(range)); + + buffer.mapping = { range: range, ptr: ptr, size: range.byteLength }; + + return STATUS_SUCCESS; + }, + /** * @param {number} bufferIdx * @param {number} labelPtr @@ -1415,6 +1470,30 @@ class WebGPUInterface { buffer.mapping = null; }, + /** + * @param {number} bufferIdx + * @param {number|BigInt} offset + * @param {number} ptr + * @param {number|BigInt} size + * @return {number} + */ + wgpuBufferWriteMappedRange: (bufferIdx, offset, ptr, size) => { + const buffer = this.buffers.get(bufferIdx); + offset = this.unwrapBigInt(offset); + size = this.unwrapBigInt(size); + + this.assert(!buffer.mapping, "buffer already mapped"); + + const range = buffer.buffer.getMappedRange(offset, size); + + const mapping = new Uint8Array(this.mem.memory.buffer, ptr, size); + (new Uint8Array(range)).set(mapping); + + buffer.mapping = { range: range, ptr: ptr, size: range.byteLength }; + + return STATUS_SUCCESS; + }, + ...this.buffers.interface(), /* ---------------------- CommandBuffer ---------------------- */ @@ -1438,7 +1517,7 @@ class WebGPUInterface { off(4); descriptor = { label: this.StringView(off(this.sizes.StringView)), - timestampWrites: this.ComputePassTimestampWritesPtr(off(4)), + timestampWrites: this.PassTimestampWritesPtr(off(4)), }; } @@ -1478,7 +1557,7 @@ class WebGPUInterface { ), depthStencilAttachment: this.RenderPassDepthStencilAttachmentPtr(off(4)), occlusionQuerySet: this.QuerySet(off(4)), - timestampWrites: this.RenderPassTimestampWritesPtr(off(4)), + timestampWrites: this.PassTimestampWritesPtr(off(4)), maxDrawCount: maxDrawCount, }; @@ -1881,7 +1960,7 @@ class WebGPUInterface { device.createComputePipelineAsync(this.ComputePipelineDescriptor(descriptorPtr)) .catch((e) => { const messageAddr = this.makeMessageArg(e.message); - this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("Unknown"), 0, messageAddr]); + this.callCallback(callbackInfo, [ENUMS.CreatePipelineAsyncStatus.indexOf("ValidationError"), 0, messageAddr]); this.mem.exports.wgpu_free(messageAddr); }) .then((computePipeline) => { @@ -2033,7 +2112,7 @@ class WebGPUInterface { addressModeW: this.enumeration("AddressMode", off(4)), magFilter: this.enumeration("FilterMode", off(4)), minFilter: this.enumeration("FilterMode", off(4)), - mipMapFilter: this.enumeration("MipmapFilterMode", off(4)), + mipmapFilter: this.enumeration("MipmapFilterMode", off(4)), lodMinClamp: this.mem.loadF32(off(4)), lodMaxClamp: this.mem.loadF32(off(4)), compare: this.enumeration("CompareFunction", off(4)), @@ -2185,6 +2264,11 @@ class WebGPUInterface { const callbackInfo = this.CallbackInfo(callbackInfoPtr); device.popErrorScope() + .catch((e) => { + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.PopErrorScopeStatus.indexOf("Error"), ENUMS.ErrorType.indexOf("unknown"), messageAddr]); + this.mem.exports.wgpu_free(messageAddr); + }) .then((error) => { if (!error) { this.callCallback(callbackInfo, [ENUMS.PopErrorScopeStatus.indexOf("Success"), ENUMS.ErrorType.indexOf("no-error"), this.zeroMessageArg()]); @@ -2222,6 +2306,10 @@ class WebGPUInterface { ...this.devices.interface(true), + /* ---------------------- ExternalTexture ---------------------- */ + + ...this.externalTextures.interface(true), + /* ---------------------- Instance ---------------------- */ /** @@ -2261,7 +2349,6 @@ class WebGPUInterface { /** * @param {number} instanceIdx * @param {number} featurePtr - * @returns {number} */ wgpuInstanceGetWGSLLanguageFeatures: (instanceIdx, featuresPtr) => { this.assert(featuresPtr != 0); @@ -2292,8 +2379,6 @@ class WebGPUInterface { for (let i = 0; i < availableFeatures.length; i += 1) { this.mem.storeI32(off(4), availableFeatures[i]); } - - return STATUS_SUCCESS; }, /** @@ -2325,11 +2410,22 @@ class WebGPUInterface { let options; if (optionsPtr != 0) { const off = this.struct(optionsPtr); - off(4); // nextInChain - off(4); // featureLevel + + let xrCompatible = undefined; + const nextInChain = this.mem.loadPtr(off(4)); + if (nextInChain != 0) { + const nextInChainType = this.mem.loadI32(nextInChain + 4); + // RequestAdapterWebXROptions = 0x0000000B, + if (nextInChainType == 0x0000000B) { + xrCompatible = this.mem.loadB32(nextInChain + 8); + } + } + options = { + featureLevel: this.enumeration("FeatureLevel", off(4)), powerPreference: this.enumeration("PowerPreference", off(4)), forceFallbackAdapter: this.mem.loadB32(off(4)), + xrCompatible: xrCompatible, }; } @@ -2405,10 +2501,12 @@ class WebGPUInterface { queue.onSubmittedWorkDone() .catch((e) => { console.warn(e); - this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Error")]); + const messageAddr = this.makeMessageArg(e.message); + this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Error"), messageAddr]); + this.mem.exports.wgpu_free(messageAddr); }) .then(() => { - this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Success")]); + this.callCallback(callbackInfo, [ENUMS.QueueWorkDoneStatus.indexOf("Success"), this.zeroMessageArg()]); }); // TODO: futures? @@ -2920,7 +3018,7 @@ class WebGPUInterface { shaderModule.getCompilationInfo() .catch((e) => { console.warn(e); - this.callCallback(callbackInfo, [ENUMS.CompilationInfoRequestStatus.indexOf("Error"), null]); + this.callCallback(callbackInfo, [ENUMS.CompilationInfoRequestStatus.indexOf("CallbackCancelled"), null]); }) .then((compilationInfo) => { const ptrsToFree = []; @@ -2975,6 +3073,11 @@ class WebGPUInterface { this.mem.exports.wgpu_free(supportedFeaturesPtr); }, + /* ---------------------- SupportedInstanceFeatures ---------------------- */ + + wgpuSupportedInstanceFeaturesFreeMembers: (supportedFeaturesCount, supportedFeaturesPtr) => { + }, + /* ---------------------- SupportedWGSLLanguageFeatures ---------------------- */ wgpuSupportedWGSLLanguageFeaturesFreeMembers: (supportedFeaturesCount, supportedFeaturesPtr) => { @@ -2992,7 +3095,23 @@ class WebGPUInterface { const context = surface.getContext("webgpu"); const off = this.struct(configPtr); - off(4); + + let colorSpace = undefined; + let toneMapping = undefined; + const nextInChain = this.mem.loadPtr(off(4)); + if (nextInChain != 0) { + const colorManagementOff = this.struct(nextInChain); + colorManagementOff(4); // next + const nextInChainType = this.mem.loadI32(colorManagementOff(4)); + // SurfaceColorManagement = 0x0000000A, + if (nextInChainType == 0x0000000A) { + colorSpace = this.enumeration("PredefinedColorSpace", colorManagementOff(4)) ?? "srgb"; + toneMapping = { + mode: this.enumeration("ToneMappingMode", colorManagementOff(4)) ?? "standard", + }; + } + } + const device = this.devices.get(this.mem.loadPtr(off(4))); const format = this.enumeration("TextureFormat", off(4)); const usage = this.mem.loadU64(off(8)); @@ -3019,6 +3138,8 @@ class WebGPUInterface { viewFormats: viewFormats, alphaMode: alphaMode, presentMode: presentMode, + colorSpace: colorSpace, + toneMapping: toneMapping, }; context.configure(config); @@ -3071,7 +3192,7 @@ class WebGPUInterface { const textureIdx = this.textures.create(texture); this.mem.storeI32(texturePtr + 4, textureIdx); - // TODO: determine suboptimal and/or status. + // TODO: determine status somehow? }, /** @@ -3130,7 +3251,27 @@ class WebGPUInterface { let descriptor; if (descriptorPtr != 0) { const off = this.struct(descriptorPtr); - off(4); + + let swizzle = undefined; + const nextInChain = this.mem.loadPtr(off(4)); + if (nextInChain != 0) { + const swizzleOff = this.struct(nextInChain); + swizzleOff(4); // next + const nextInChainType = this.mem.loadI32(swizzleOff(4)); + // TextureComponentSwizzle = 0x00000016, + if (nextInChainType == 0x00000016) { + const r = this.enumeration("ComponentSwizzle", swizzleOff(4)); + this.assert(r !== undefined); + const g = this.enumeration("ComponentSwizzle", swizzleOff(4)); + this.assert(g !== undefined); + const b = this.enumeration("ComponentSwizzle", swizzleOff(4)); + this.assert(b !== undefined); + const a = this.enumeration("ComponentSwizzle", swizzleOff(4)); + this.assert(a !== undefined); + swizzle = r + g + b + a; + } + } + descriptor = { label: this.StringView(off(this.sizes.StringView)), format: this.enumeration("TextureFormat", off(4)), @@ -3141,6 +3282,7 @@ class WebGPUInterface { arrayLayerCount: this.mem.loadU32(off(4)), aspect: this.enumeration("TextureAspect", off(4)), usage: this.mem.loadU64(off(8)), + swizzle: swizzle, }; if (descriptor.arrayLayerCount == 0xFFFFFFFF) { descriptor.arrayLayerCount = undefined; @@ -3166,7 +3308,7 @@ class WebGPUInterface { * @param {number} textureIdx * @returns {number} */ - wgpuTextureDepthOrArrayLayers: (textureIdx) => { + wgpuTextureGetDepthOrArrayLayers: (textureIdx) => { const texture = this.textures.get(textureIdx); return texture.depthOrArrayLayers; }, @@ -3216,6 +3358,15 @@ class WebGPUInterface { return texture.sampleCount; }, + /** + * @param {number} textureIdx + * @returns {number} + */ + wgpuTextureGetTextureBindingViewDimension: (textureIdx) => { + const texture = this.textures.get(textureIdx); + return ENUMS.TextureViewDimension.indexOf(texture.textureBindingViewDimension); + }, + /** * @param {number} textureIdx * @returns {number} @@ -3265,6 +3416,10 @@ class WebGPUObjectManager { * @returns {number} */ create(object) { + if (object === null) { + return 0; + } + this.objects[this.idx] = { references: 1, object }; this.idx += 1; return this.idx; @@ -3280,6 +3435,10 @@ class WebGPUObjectManager { /** @param {number} idx */ release(idx) { + if (idx === 0) { + return; + } + this.objects[idx-1].references -= 1; if (this.objects[idx-1].references == 0) { delete this.objects[idx-1]; @@ -3288,6 +3447,10 @@ class WebGPUObjectManager { /** @param {number} idx */ reference(idx) { + if (idx === 0) { + return; + } + this.objects[idx-1].references += 1; } diff --git a/vendor/wgpu/wgpu.odin b/vendor/wgpu/wgpu.odin index 4bbe67d1f..796cebec7 100644 --- a/vendor/wgpu/wgpu.odin +++ b/vendor/wgpu/wgpu.odin @@ -13,7 +13,7 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-windows-" + ARCH + "-msvc-" + TYPE + "/lib/wgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v29.0.0.0, make sure to read the docs at '" + #directory + "doc.odin'") } @(export) @@ -39,12 +39,13 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v29.0.0.0, make sure to read the docs at '" + #directory + "doc.odin'") } @(export) foreign import libwgpu { LIB, + "system:Foundation.framework", "system:CoreFoundation.framework", "system:QuartzCore.framework", "system:Metal.framework", @@ -55,7 +56,7 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v29.0.0.0, make sure to read the docs at '" + #directory + "doc.odin'") } @(export) @@ -80,6 +81,7 @@ WHOLE_MAP_SIZE :: max(uint) WHOLE_SIZE :: max(u64) Flags :: u64 +Bool :: b32 StringView :: string @@ -107,6 +109,7 @@ ShaderModule :: distinct rawptr Surface :: distinct rawptr Texture :: distinct rawptr TextureView :: distinct rawptr +ExternalTexture :: distinct rawptr AdapterType :: enum i32 { DiscreteGPU = 0x00000001, @@ -197,9 +200,7 @@ CompareFunction :: enum i32 { CompilationInfoRequestStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, - Error = 0x00000003, - Unknown = 0x00000004, + CallbackCancelled = 0x00000002, } CompilationMessageType :: enum i32 { @@ -208,6 +209,16 @@ CompilationMessageType :: enum i32 { Info = 0x00000003, } +ComponentSwizzle :: enum i32 { + Undefined, + Zero, + One, + R, + G, + B, + A, +} + CompositeAlphaMode :: enum i32 { Auto = 0x00000000, Opaque = 0x00000001, @@ -218,10 +229,9 @@ CompositeAlphaMode :: enum i32 { CreatePipelineAsyncStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, + CallbackCancelled = 0x00000002, ValidationError = 0x00000003, InternalError = 0x00000004, - Unknown = 0x00000005, } CullMode :: enum i32 { @@ -235,7 +245,7 @@ DeviceLostReason :: enum i32 { Undefined = 0x00000000, Unknown = 0x00000001, Destroyed = 0x00000002, - InstanceDropped = 0x00000003, + CallbackCancelled = 0x00000003, FailedCreation = 0x00000004, } @@ -254,6 +264,7 @@ ErrorType :: enum i32 { } FeatureLevel :: enum i32 { + Undefined, Compatibility = 0x00000001, Core = 0x00000002, } @@ -261,28 +272,33 @@ FeatureLevel :: enum i32 { FeatureName :: enum i32 { // WebGPU. Undefined = 0x00000000, - DepthClipControl = 0x00000001, - Depth32FloatStencil8 = 0x00000002, - TimestampQuery = 0x00000003, + CoreFeaturesAndLimits = 0x00000001, + DepthClipControl = 0x00000002, + Depth32FloatStencil8 = 0x00000003, TextureCompressionBC = 0x00000004, TextureCompressionBCSliced3D = 0x00000005, TextureCompressionETC2 = 0x00000006, TextureCompressionASTC = 0x00000007, TextureCompressionASTCSliced3D = 0x00000008, - IndirectFirstInstance = 0x00000009, - ShaderF16 = 0x0000000A, - RG11B10UfloatRenderable = 0x0000000B, - BGRA8UnormStorage = 0x0000000C, - Float32Filterable = 0x0000000D, - Float32Blendable = 0x0000000E, - ClipDistances = 0x0000000F, - DualSourceBlending = 0x00000010, + TimestampQuery = 0x00000009, + IndirectFirstInstance = 0x0000000A, + ShaderF16 = 0x0000000B, + RG11B10UfloatRenderable = 0x0000000C, + BGRA8UnormStorage = 0x0000000D, + Float32Filterable = 0x0000000E, + Float32Blendable = 0x0000000F, + ClipDistances = 0x00000010, + DualSourceBlending = 0x00000011, + Subgroups = 0x00000012, + TextureFormatsTier1 = 0x00000013, + TextureFormatsTier2 = 0x00000014, + PrimitiveIndex = 0x00000015, + TextureComponentSwizzle = 0x00000016, // Native. - PushConstants = 0x00030001, + Immediates = 0x00030001, TextureAdapterSpecificFormatFeatures, - MultiDrawIndirect, - MultiDrawIndirectCount, + MultiDrawIndirectCount = 0x00030004, VertexWritableStorage, TextureBindingArray, SampledTextureAndStorageBufferArrayNonUniformIndexing, @@ -297,25 +313,24 @@ FeatureName :: enum i32 { // TODO: requires wgpu.h api change // AddressModeClampToZero, // AddressModeClampToBorder, - // PolygonModeLine, - // PolygonModePoint, - // ConservativeRasterization, + PolygonModeLine = 0x00030013, + PolygonModePoint, + ConservativeRasterization, // ClearTexture, SpirvShaderPassthrough = 0x00030017, // MultiView, VertexAttribute64bit = 0x00030019, TextureFormatNv12, - RayTracingAccelarationStructure, - RayQuery, + RayQuery = 0x0003001C, ShaderF64, ShaderI16, - ShaderPrimitiveIndex, - ShaderEarlyDepthTest, + ShaderEarlyDepthTest = 0x00030020, Subgroup, SubgroupVertex, SubgroupBarrier, TimestampQueryInsideEncoders, TimestampQueryInsidePasses, + ShaderInt64, } FilterMode :: enum i32 { @@ -336,6 +351,12 @@ IndexFormat :: enum i32 { Uint32 = 0x00000002, } +InstanceFeatureName :: enum i32 { + TimedWaitAny = 1, + ShaderSourceSPIRV = 2, + MultipleDevicesPerAdapter = 3, +} + LoadOp :: enum i32 { Undefined = 0x00000000, Load = 0x00000001, @@ -344,10 +365,9 @@ LoadOp :: enum i32 { MapAsyncStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, + CallbackCancelled = 0x00000002, Error = 0x00000003, Aborted = 0x00000004, - Unknown = 0x00000005, } MipmapFilterMode :: enum i32 { @@ -364,8 +384,8 @@ OptionalBool :: enum i32 { PopErrorScopeStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, - EmptyStack = 0x00000003, + CallbackCancelled = 0x00000002, + Error = 0x00000003, } PowerPreference :: enum i32 { @@ -374,6 +394,11 @@ PowerPreference :: enum i32 { HighPerformance = 0x00000002, } +PredefinedColorSpace :: enum i32 { + SRGB = 1, + DisplayP3, +} + PresentMode :: enum i32 { Undefined = 0x00000000, Fifo = 0x00000001, @@ -402,52 +427,21 @@ QueryType :: enum i32 { QueueWorkDoneStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, + CallbackCancelled = 0x00000002, Error = 0x00000003, - Unknown = 0x00000004, } RequestAdapterStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, + CallbackCancelled = 0x00000002, Unavailable = 0x00000003, Error = 0x00000004, - Unknown = 0x00000005, } RequestDeviceStatus :: enum i32 { Success = 0x00000001, - InstanceDropped = 0x00000002, + CallbackCancelled = 0x00000002, Error = 0x00000003, - Unknown = 0x00000004, -} - -SType :: enum i32 { - // WebGPU. - ShaderSourceSPIRV = 0x00000001, - ShaderSourceWGSL = 0x00000002, - RenderPassMaxDrawCount = 0x00000003, - SurfaceSourceMetalLayer = 0x00000004, - SurfaceSourceWindowsHWND = 0x00000005, - SurfaceSourceXlibWindow = 0x00000006, - SurfaceSourceWaylandSurface = 0x00000007, - SurfaceSourceAndroidNativeWindow = 0x00000008, - SurfaceSourceXCBWindow = 0x00000009, - - // Native. - DeviceExtras = 0x00030001, - NativeLimits, - PipelineLayoutExtras, - ShaderModuleGLSLDescriptor, - SupportedLimitsExtras, - InstanceExtras, - BindGroupEntryExtras, - BindGroupLayoutEntryExtras, - QuerySetDescriptorExtras, - SurfaceConfigurationExtras, - - // Odin. - SurfaceSourceCanvasHTMLSelector = 0x00040001, } SamplerBindingType :: enum i32 { @@ -489,15 +483,53 @@ StoreOp :: enum i32 { Discard = 0x00000002, } +SType :: enum i32 { + // WebGPU. + ShaderSourceSPIRV = 0x00000001, + ShaderSourceWGSL = 0x00000002, + RenderPassMaxDrawCount = 0x00000003, + SurfaceSourceMetalLayer = 0x00000004, + SurfaceSourceWindowsHWND = 0x00000005, + SurfaceSourceXlibWindow = 0x00000006, + SurfaceSourceWaylandSurface = 0x00000007, + SurfaceSourceAndroidNativeWindow = 0x00000008, + SurfaceSourceXCBWindow = 0x00000009, + SurfaceColorManagement = 0x0000000A, + RequestAdapterWebXROptions = 0x0000000B, + TextureComponentSwizzleDescriptor = 0x0000000C, + ExternalTextureBindingLayout = 0x0000000D, + ExternalTextureBindingEntry = 0x0000000E, + CompatibilityModeLimits = 0x0000000F, + TextureBindingViewDimension = 0x00000010, + + // Native. + DeviceExtras = 0x00030001, + NativeLimits, + PipelineLayoutExtras, + ShaderSourceGLSL, + SupportedLimitsExtras, + InstanceExtras, + BindGroupEntryExtras, + BindGroupLayoutEntryExtras, + QuerySetDescriptorExtras, + SurfaceConfigurationExtras, + SurfaceSourceSwapChainPanel, + PrimitiveStateExtras, + + // Odin. + SurfaceSourceCanvasHTMLSelector = 0x00040001, +} + SurfaceGetCurrentTextureStatus :: enum i32 { SuccessOptimal = 0x00000001, SuccessSuboptimal = 0x00000002, Timeout = 0x00000003, Outdated = 0x00000004, Lost = 0x00000005, - OutOfMemory = 0x00000006, - DeviceLost = 0x00000007, - Error = 0x00000008, + Error = 0x00000006, + + // Native. + Occluded = 0x00030001, } TextureAspect :: enum i32 { @@ -520,109 +552,115 @@ TextureFormat :: enum i32 { R8Snorm = 0x00000002, R8Uint = 0x00000003, R8Sint = 0x00000004, - R16Uint = 0x00000005, - R16Sint = 0x00000006, - R16Float = 0x00000007, - RG8Unorm = 0x00000008, - RG8Snorm = 0x00000009, - RG8Uint = 0x0000000A, - RG8Sint = 0x0000000B, - R32Float = 0x0000000C, - R32Uint = 0x0000000D, - R32Sint = 0x0000000E, - RG16Uint = 0x0000000F, - RG16Sint = 0x00000010, - RG16Float = 0x00000011, - RGBA8Unorm = 0x00000012, - RGBA8UnormSrgb = 0x00000013, - RGBA8Snorm = 0x00000014, - RGBA8Uint = 0x00000015, - RGBA8Sint = 0x00000016, - BGRA8Unorm = 0x00000017, - BGRA8UnormSrgb = 0x00000018, - RGB10A2Uint = 0x00000019, - RGB10A2Unorm = 0x0000001A, - RG11B10Ufloat = 0x0000001B, - RGB9E5Ufloat = 0x0000001C, - RG32Float = 0x0000001D, - RG32Uint = 0x0000001E, - RG32Sint = 0x0000001F, - RGBA16Uint = 0x00000020, - RGBA16Sint = 0x00000021, - RGBA16Float = 0x00000022, - RGBA32Float = 0x00000023, - RGBA32Uint = 0x00000024, - RGBA32Sint = 0x00000025, - Stencil8 = 0x00000026, - Depth16Unorm = 0x00000027, - Depth24Plus = 0x00000028, - Depth24PlusStencil8 = 0x00000029, - Depth32Float = 0x0000002A, - Depth32FloatStencil8 = 0x0000002B, - BC1RGBAUnorm = 0x0000002C, - BC1RGBAUnormSrgb = 0x0000002D, - BC2RGBAUnorm = 0x0000002E, - BC2RGBAUnormSrgb = 0x0000002F, - BC3RGBAUnorm = 0x00000030, - BC3RGBAUnormSrgb = 0x00000031, - BC4RUnorm = 0x00000032, - BC4RSnorm = 0x00000033, - BC5RGUnorm = 0x00000034, - BC5RGSnorm = 0x00000035, - BC6HRGBUfloat = 0x00000036, - BC6HRGBFloat = 0x00000037, - BC7RGBAUnorm = 0x00000038, - BC7RGBAUnormSrgb = 0x00000039, - ETC2RGB8Unorm = 0x0000003A, - ETC2RGB8UnormSrgb = 0x0000003B, - ETC2RGB8A1Unorm = 0x0000003C, - ETC2RGB8A1UnormSrgb = 0x0000003D, - ETC2RGBA8Unorm = 0x0000003E, - ETC2RGBA8UnormSrgb = 0x0000003F, - EACR11Unorm = 0x00000040, - EACR11Snorm = 0x00000041, - EACRG11Unorm = 0x00000042, - EACRG11Snorm = 0x00000043, - ASTC4x4Unorm = 0x00000044, - ASTC4x4UnormSrgb = 0x00000045, - ASTC5x4Unorm = 0x00000046, - ASTC5x4UnormSrgb = 0x00000047, - ASTC5x5Unorm = 0x00000048, - ASTC5x5UnormSrgb = 0x00000049, - ASTC6x5Unorm = 0x0000004A, - ASTC6x5UnormSrgb = 0x0000004B, - ASTC6x6Unorm = 0x0000004C, - ASTC6x6UnormSrgb = 0x0000004D, - ASTC8x5Unorm = 0x0000004E, - ASTC8x5UnormSrgb = 0x0000004F, - ASTC8x6Unorm = 0x00000050, - ASTC8x6UnormSrgb = 0x00000051, - ASTC8x8Unorm = 0x00000052, - ASTC8x8UnormSrgb = 0x00000053, - ASTC10x5Unorm = 0x00000054, - ASTC10x5UnormSrgb = 0x00000055, - ASTC10x6Unorm = 0x00000056, - ASTC10x6UnormSrgb = 0x00000057, - ASTC10x8Unorm = 0x00000058, - ASTC10x8UnormSrgb = 0x00000059, - ASTC10x10Unorm = 0x0000005A, - ASTC10x10UnormSrgb = 0x0000005B, - ASTC12x10Unorm = 0x0000005C, - ASTC12x10UnormSrgb = 0x0000005D, - ASTC12x12Unorm = 0x0000005E, - ASTC12x12UnormSrgb = 0x0000005F, + R16Unorm = 0x00000005, + R16Snorm = 0x00000006, + R16Uint = 0x00000007, + R16Sint = 0x00000008, + R16Float = 0x00000009, + RG8Unorm = 0x0000000A, + RG8Snorm = 0x0000000B, + RG8Uint = 0x0000000C, + RG8Sint = 0x0000000D, + R32Float = 0x0000000E, + R32Uint = 0x0000000F, + R32Sint = 0x00000010, + RG16Unorm = 0x00000011, + RG16Snorm = 0x00000012, + RG16Uint = 0x00000013, + RG16Sint = 0x00000014, + RG16Float = 0x00000015, + RGBA8Unorm = 0x00000016, + RGBA8UnormSrgb = 0x00000017, + RGBA8Snorm = 0x00000018, + RGBA8Uint = 0x00000019, + RGBA8Sint = 0x0000001A, + BGRA8Unorm = 0x0000001B, + BGRA8UnormSrgb = 0x0000001C, + RGB10A2Uint = 0x0000001D, + RGB10A2Unorm = 0x0000001E, + RG11B10Ufloat = 0x0000001F, + RGB9E5Ufloat = 0x00000020, + RG32Float = 0x00000021, + RG32Uint = 0x00000022, + RG32Sint = 0x00000023, + RGBA16Unorm = 0x00000024, + RGBA16Snorm = 0x00000025, + RGBA16Uint = 0x00000026, + RGBA16Sint = 0x00000027, + RGBA16Float = 0x00000028, + RGBA32Float = 0x00000029, + RGBA32Uint = 0x0000002A, + RGBA32Sint = 0x0000002B, + Stencil8 = 0x0000002C, + Depth16Unorm = 0x0000002D, + Depth24Plus = 0x0000002E, + Depth24PlusStencil8 = 0x0000002F, + Depth32Float = 0x00000030, + Depth32FloatStencil8 = 0x00000031, + BC1RGBAUnorm = 0x00000032, + BC1RGBAUnormSrgb = 0x00000033, + BC2RGBAUnorm = 0x00000034, + BC2RGBAUnormSrgb = 0x00000035, + BC3RGBAUnorm = 0x00000036, + BC3RGBAUnormSrgb = 0x00000037, + BC4RUnorm = 0x00000038, + BC4RSnorm = 0x00000039, + BC5RGUnorm = 0x0000003A, + BC5RGSnorm = 0x0000003B, + BC6HRGBUfloat = 0x0000003C, + BC6HRGBFloat = 0x0000003D, + BC7RGBAUnorm = 0x0000003E, + BC7RGBAUnormSrgb = 0x0000003F, + ETC2RGB8Unorm = 0x00000040, + ETC2RGB8UnormSrgb = 0x00000041, + ETC2RGB8A1Unorm = 0x00000042, + ETC2RGB8A1UnormSrgb = 0x00000043, + ETC2RGBA8Unorm = 0x00000044, + ETC2RGBA8UnormSrgb = 0x00000045, + EACR11Unorm = 0x00000046, + EACR11Snorm = 0x00000047, + EACRG11Unorm = 0x00000048, + EACRG11Snorm = 0x00000049, + ASTC4x4Unorm = 0x0000004A, + ASTC4x4UnormSrgb = 0x0000004B, + ASTC5x4Unorm = 0x0000004C, + ASTC5x4UnormSrgb = 0x0000004D, + ASTC5x5Unorm = 0x0000004E, + ASTC5x5UnormSrgb = 0x0000004F, + ASTC6x5Unorm = 0x00000050, + ASTC6x5UnormSrgb = 0x00000051, + ASTC6x6Unorm = 0x00000052, + ASTC6x6UnormSrgb = 0x00000053, + ASTC8x5Unorm = 0x00000054, + ASTC8x5UnormSrgb = 0x00000055, + ASTC8x6Unorm = 0x00000056, + ASTC8x6UnormSrgb = 0x00000057, + ASTC8x8Unorm = 0x00000058, + ASTC8x8UnormSrgb = 0x00000059, + ASTC10x5Unorm = 0x0000005A, + ASTC10x5UnormSrgb = 0x0000005B, + ASTC10x6Unorm = 0x0000005C, + ASTC10x6UnormSrgb = 0x0000005D, + ASTC10x8Unorm = 0x0000005E, + ASTC10x8UnormSrgb = 0x0000005F, + ASTC10x10Unorm = 0x00000060, + ASTC10x10UnormSrgb = 0x00000061, + ASTC12x10Unorm = 0x00000062, + ASTC12x10UnormSrgb = 0x00000063, + ASTC12x12Unorm = 0x00000064, + ASTC12x12UnormSrgb = 0x00000065, // Native. // From FeatureName.TextureFormat16bitNorm - R16Unorm = 0x00030001, - R16Snorm, + NativeR16Unorm = 0x00030001, + NativeR16Snorm, Rg16Unorm, Rg16Snorm, Rgba16Unorm, Rgba16Snorm, - // From FeatureName.TextureFormatNv12 NV12, + P010, } TextureSampleType :: enum i32 { @@ -645,6 +683,11 @@ TextureViewDimension :: enum i32 { _3D = 0x00000006, } +ToneMappingMode :: enum i32 { + Standard = 1, + Extended, +} + VertexFormat :: enum i32 { Uint8 = 0x00000001, Uint8x2 = 0x00000002, @@ -690,10 +733,15 @@ VertexFormat :: enum i32 { } VertexStepMode :: enum i32 { - VertexBufferNotUsed = 0x00000000, - Undefined = 0x00000001, - Vertex = 0x00000002, - Instance = 0x00000003, + Undefined = 0x00000000, + Vertex = 0x00000001, + Instance = 0x00000002, +} + +WaitStatus :: enum i32 { + Success = 0x00000001, + TimedOut = 0x00000002, + Error = 0x00000003, } WGSLLanguageFeatureName :: enum i32 { @@ -701,14 +749,11 @@ WGSLLanguageFeatureName :: enum i32 { Packed4x8IntegerDotProduct = 0x00000002, UnrestrictedPointerParameters = 0x00000003, PointerCompositeAccess = 0x00000004, -} - -WaitStatus :: enum i32 { - Success = 0x00000001, - TimedOut = 0x00000002, - UnsupportedTimeout = 0x00000003, - UnsupportedCount = 0x00000004, - UnsupportedMixedSource = 0x00000005, + UniformBufferStandardLayout = 0x00000005, + SubgroupId = 0x00000006, + TextureAndSamplerLet = 0x00000007, + SubgroupUniformity = 0x00000008, + TextureFormatsTier1 = 0x00000009, } BufferUsage :: enum i32 { @@ -748,11 +793,12 @@ ShaderStage :: enum i32 { ShaderStageFlags :: bit_set[ShaderStage; Flags] TextureUsage :: enum i32 { - CopySrc = 0x00000000, - CopyDst = 0x00000001, - TextureBinding = 0x00000002, - StorageBinding = 0x00000003, - RenderAttachment = 0x00000004, + CopySrc, + CopyDst, + TextureBinding, + StorageBinding, + RenderAttachment, + TransientAttachment, } TextureUsageFlags :: bit_set[TextureUsage; Flags] @@ -764,7 +810,7 @@ CreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyn CreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: StringView, userdata1: rawptr, userdata2: rawptr) DeviceLostCallback :: #type proc "c" (device: ^Device, reason: DeviceLostReason, message: StringView, userdata1: rawptr, userdata2: rawptr) PopErrorScopeCallback :: #type proc "c" (status: PopErrorScopeStatus, type: ErrorType, message: StringView, userdata1: rawptr, userdata2: rawptr) -QueueWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, userdata1: rawptr, userdata2: rawptr) +QueueWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, message: StringView, userdata1: rawptr, userdata2: rawptr) RequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: StringView, userdata1: rawptr, userdata2: rawptr) RequestDeviceCallback :: #type proc "c" (status: RequestDeviceStatus, adapter: Device, message: StringView, userdata1: rawptr, userdata2: rawptr) UncapturedErrorCallback :: #type proc "c" (device: ^Device, type: ErrorType, message: StringView, userdata1: rawptr, userdata2: rawptr) @@ -774,11 +820,6 @@ ChainedStruct :: struct { sType: SType, } -ChainedStructOut :: struct { - next: ^ChainedStructOut, - sType: SType, -} - BufferMapCallbackInfo :: struct { nextInChain: /* const */ ^ChainedStruct, mode: CallbackMode, @@ -859,7 +900,7 @@ UncapturedErrorCallbackInfo :: struct { } AdapterInfo :: struct { - nextInChain: ^ChainedStructOut, + nextInChain: ^ChainedStruct, vendor: StringView, architecture: StringView, device: StringView, @@ -868,16 +909,8 @@ AdapterInfo :: struct { adapterType: AdapterType, vendorID: u32, deviceID: u32, -} - -BindGroupEntry :: struct { - nextInChain: ^ChainedStruct, - binding: u32, - /* NULLABLE */ buffer: Buffer, - offset: u64, - size: u64, - /* NULLABLE */ sampler: Sampler, - /* NULLABLE */ textureView: TextureView, + subgroupMinSize: u32, + subgroupMaxSize: u32, } BlendComponent :: struct { @@ -913,6 +946,14 @@ CommandEncoderDescriptor :: struct { label: StringView, } +CompatibilityModeLimits :: struct { + using chain: ChainedStruct, + maxStorageBuffersInVertexStage: u32, + maxStorageTexturesInVertexStage: u32, + maxStorageBuffersInFragmentStage: u32, + maxStorageTexturesInFragmentStage: u32, +} + CompilationMessage :: struct { nextInChain: ^ChainedStruct, message: StringView, @@ -923,12 +964,6 @@ CompilationMessage :: struct { length: u64, } -ComputePassTimestampWrites :: struct { - querySet: QuerySet, - beginningOfPassWriteIndex: u32, - endOfPassWriteIndex: u32, -} - ConstantEntry :: struct { nextInChain: /* const */ ^ChainedStruct, key: StringView, @@ -941,18 +976,383 @@ Extent3D :: struct { depthOrArrayLayers: u32, } +/* +Chained in a `BindGroupEntry`. +*/ +ExternalTextureBindingEntry :: struct { + using chain: ChainedStruct, + externalTexture: ExternalTexture, +} + +/* +Chained in a `BindGroupLayoutEntry`. +*/ +ExternalTextureBindingLayout :: struct { + using chain: ChainedStruct, +} + Future :: struct { id: u64, } -InstanceCapabilities :: struct { - nextInChain: ^ChainedStructOut, - timedWaitAnyEnable: b32, +InstanceLimits :: struct { + nextInChain: ^ChainedStruct, timedWaitAnyMaxCount: uint, } +MultisampleState :: struct { + nextInChain: ^ChainedStruct, + count: u32, + mask: u32, + alphaToCoverageEnabled: b32, +} + +Origin3D :: struct { + x: u32, + y: u32, + z: u32, +} + +PassTimestampWrites :: struct { + nextInChain: ^ChainedStruct, + querySet: QuerySet, + beginningOfPassWriteIndex: u32, + endOfPassWriteIndex: u32, +} + +PipelineLayoutDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + bindGroupLayoutCount: uint, + bindGroupLayouts: [^]BindGroupLayout `fmt:"v,bindGroupLayoutCount"`, + immediateSize: u32, +} + +PrimitiveState :: struct { + nextInChain: ^ChainedStruct, + topology: PrimitiveTopology, + stripIndexFormat: IndexFormat, + frontFace: FrontFace, + cullMode: CullMode, + unclippedDepth: b32, +} + +QuerySetDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + type: QueryType, + count: u32, +} + +QueueDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, +} + +RenderBundleDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, +} + +RenderBundleEncoderDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + colorFormatCount: uint, + colorFormats: /* const */ [^]TextureFormat `fmt:"v,colorFormatCount"`, + depthStencilFormat: TextureFormat, + sampleCount: u32, + depthReadOnly: b32, + stencilReadOnly: b32, +} + +RenderPassDepthStencilAttachment :: struct { + nextInChain: ^ChainedStruct, + view: TextureView, + depthLoadOp: LoadOp, + depthStoreOp: StoreOp, + depthClearValue: f32, + depthReadOnly: b32, + stencilLoadOp: LoadOp, + stencilStoreOp: StoreOp, + stencilClearValue: u32, + stencilReadOnly: b32, +} + +RenderPassMaxDrawCount :: struct { + using chain: ChainedStruct, + maxDrawCount: u64, +} + +/* +Chained in a `RequestAdapterOptions`. +*/ +RequestAdapterWebXROptions :: struct { + using chain: ChainedStruct, + xrCompatible: b32, +} + +SamplerBindingLayout :: struct { + nextInChain: ^ChainedStruct, + type: SamplerBindingType, +} + +SamplerDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + addressModeU: AddressMode, + addressModeV: AddressMode, + addressModeW: AddressMode, + magFilter: FilterMode, + minFilter: FilterMode, + mipmapFilter: MipmapFilterMode, + lodMinClamp: f32, + lodMaxClamp: f32, + compare: CompareFunction, + maxAnisotropy: u16, +} + +ShaderSourceSPIRV :: struct { + using chain: ChainedStruct, + codeSize: u32, + code: /* const */ [^]u32 `fmt:"v,codeSize"`, +} + +ShaderSourceWGSL :: struct { + using chain: ChainedStruct, + code: StringView, +} + +StencilFaceState :: struct { + compare: CompareFunction, + failOp: StencilOperation, + depthFailOp: StencilOperation, + passOp: StencilOperation, +} + +StorageTextureBindingLayout :: struct { + nextInChain: ^ChainedStruct, + access: StorageTextureAccess, + format: TextureFormat, + viewDimension: TextureViewDimension, +} + +SupportedFeatures :: struct { + featureCount: uint, + features: /* const */ [^]FeatureName `fmt:"v,featureCount"`, +} + +SupportedInstanceFeatures :: struct { + featureCount: uint, + features: /* const */ [^]InstanceFeatureName `fmt:"v,featureCount"`, +} + +SupportedWGSLLanguageFeatures :: struct { + featureCount: uint, + features: /* const */ [^]WGSLLanguageFeatureName `fmt:"v,featureCount"`, +} + +SurfaceCapabilities :: struct { + nextInChain: ^ChainedStruct, + usages: TextureUsageFlags, + formatCount: uint, + formats: /* const */ [^]TextureFormat `fmt:"v,formatCount"`, + presentModeCount: uint, + presentModes: /* const */ [^]PresentMode `fmt:"v,presentModeCount"`, + alphaModeCount: uint, + alphaModes: /* const */ [^]CompositeAlphaMode `fmt:"v,alphaModeCount"`, +} + +/* +Chained in a `SurfaceConfiguration`. +*/ +SurfaceColorManagement :: struct { + using chain: ChainedStruct, + colorSpace: PredefinedColorSpace, + toneMappingMode: ToneMappingMode, +} + +SurfaceConfiguration :: struct { + nextInChain: ^ChainedStruct, + device: Device, + format: TextureFormat, + usage: TextureUsageFlags, + width: u32, + height: u32, + viewFormatCount: uint, + viewFormats: /* const */ [^]TextureFormat `fmt:"v,viewFormatCount"`, + alphaMode: CompositeAlphaMode, + presentMode: PresentMode, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceAndroidNativeWindow :: struct { + using chain: ChainedStruct, + window: rawptr, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceCanvasHTMLSelector :: struct { + using chain: ChainedStruct, + selector: StringView, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceMetalLayer :: struct { + using chain: ChainedStruct, + layer: rawptr, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceWaylandSurface :: struct { + using chain: ChainedStruct, + display: rawptr, + surface: rawptr, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceWindowsHWND :: struct { + using chain: ChainedStruct, + hinstance: rawptr, + hwnd: rawptr, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceXcbWindow :: struct { + using chain: ChainedStruct, + connection: rawptr, + window: u32, +} + +/* +Chained in a `SurfaceDescriptor`. +*/ +SurfaceSourceXlibWindow :: struct { + using chain: ChainedStruct, + display: rawptr, + window: u64, +} + +SurfaceTexture :: struct { + nextInChain: ^ChainedStruct, + texture: Texture, + status: SurfaceGetCurrentTextureStatus, +} + +TexelCopyBufferLayout :: struct { + offset: u64, + bytesPerRow: u32, + rowsPerImage: u32, +} + +TextureBindingLayout :: struct { + nextInChain: ^ChainedStruct, + sampleType: TextureSampleType, + viewDimension: TextureViewDimension, + multisampled: b32, +} + +TextureBindingViewDimension :: struct { + using chain: ChainedStruct, + textureBindingViewDimension: TextureViewDimension, +} + +TextureComponentSwizzle :: struct { + r, g, b, a: ComponentSwizzle, +} + +VertexAttribute :: struct { + nextInChain: ^ChainedStruct, + format: VertexFormat, + offset: u64, + shaderLocation: u32, +} + +BindGroupEntry :: struct { + nextInChain: ^ChainedStruct, + binding: u32, + /* NULLABLE */ buffer: Buffer, + offset: u64, + size: u64, + /* NULLABLE */ sampler: Sampler, + /* NULLABLE */ textureView: TextureView, +} + +BindGroupLayoutEntry :: struct { + nextInChain: ^ChainedStruct, + binding: u32, + visibility: ShaderStageFlags, + bindingArraySize: u32, + buffer: BufferBindingLayout, + sampler: SamplerBindingLayout, + texture: TextureBindingLayout, + storageTexture: StorageTextureBindingLayout, +} + +BlendState :: struct { + color: BlendComponent, + alpha: BlendComponent, +} + +CompilationInfo :: struct { + nextInChain: ^ChainedStruct, + messageCount: uint, + messages: /* const */ [^]CompilationMessage `fmt:"v,messageCount"`, +} + +ComputePassDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + /* NULLABLE */ timestampWrites: /* const */ ^PassTimestampWrites, +} + +ComputeState :: struct { + nextInChain: ^ChainedStruct, + module: ShaderModule, + entryPoint: StringView, + constantCount: uint, + constants: [^]ConstantEntry `fmt:"v,constantCount"`, +} + +DepthStencilState :: struct { + nextInChain: ^ChainedStruct, + format: TextureFormat, + depthWriteEnabled: OptionalBool, + depthCompare: CompareFunction, + stencilFront: StencilFaceState, + stencilBack: StencilFaceState, + stencilReadMask: u32, + stencilWriteMask: u32, + depthBias: i32, + depthBiasSlopeScale: f32, + depthBiasClamp: f32, +} + +FutureWaitInfo :: struct { + future: Future, + completed: b32, +} + +InstanceDescriptor :: struct { + nextInChain: ^ChainedStruct, + requiredFeatureCount: uint, + requiredFeatures: [^]InstanceFeatureName `fmt:"v,requiredFeatureCount"`, + /* NULLABLE */ requiredLimits: ^InstanceLimits, +} + Limits :: struct { - nextInChain: ^ChainedStructOut, + nextInChain: ^ChainedStruct, maxTextureDimension1D: u32, maxTextureDimension2D: u32, maxTextureDimension3D: u32, @@ -984,90 +1384,21 @@ Limits :: struct { maxComputeWorkgroupSizeY: u32, maxComputeWorkgroupSizeZ: u32, maxComputeWorkgroupsPerDimension: u32, + maxImmediateSize: u32, } -MultisampleState :: struct { - nextInChain: /* const */ ^ChainedStruct, - count: u32, - mask: u32, - alphaToCoverageEnabled: b32, -} - -Origin3D :: struct { - x: u32, - y: u32, - z: u32, -} - -PipelineLayoutDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - bindGroupLayoutCount: uint, - bindGroupLayouts: [^]BindGroupLayout `fmt:"v,bindGroupLayoutCount"`, -} - -PrimitiveState :: struct { - nextInChain: /* const */ ^ChainedStruct, - topology: PrimitiveTopology, - stripIndexFormat: IndexFormat, - frontFace: FrontFace, - cullMode: CullMode, - unclippedDepth: b32, -} - -QuerySetDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - type: QueryType, - count: u32, -} - -QueueDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, -} - -RenderBundleDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, -} - -RenderBundleEncoderDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - colorFormatCount: uint, - colorFormats: /* const */ [^]TextureFormat `fmt:"v,colorFormatCount"`, - depthStencilFormat: TextureFormat, - sampleCount: u32, - depthReadOnly: b32, - stencilReadOnly: b32, -} - -RenderPassDepthStencilAttachment :: struct { - view: TextureView, - depthLoadOp: LoadOp, - depthStoreOp: StoreOp, - depthClearValue: f32, - depthReadOnly: b32, - stencilLoadOp: LoadOp, - stencilStoreOp: StoreOp, - stencilClearValue: u32, - stencilReadOnly: b32, -} - -RenderPassMaxDrawCount :: struct { - using chain: ChainedStruct, - maxDrawCount: u64, -} - -RenderPassTimestampWrites :: struct { - querySet: QuerySet, - beginningOfPassWriteIndex: u32, - endOfPassWriteIndex: u32, +RenderPassColorAttachment :: struct { + nextInChain: ^ChainedStruct, + /* NULLABLE */ view: TextureView, + depthSlice: u32, + /* NULLABLE */ resolveTarget: TextureView, + loadOp: LoadOp, + storeOp: StoreOp, + clearValue: Color, } RequestAdapterOptions :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, featureLevel: FeatureLevel, powerPreference: PowerPreference, forceFallbackAdapter: b32, @@ -1075,260 +1406,16 @@ RequestAdapterOptions :: struct { /* NULLABLE */ compatibleSurface: Surface, } -SamplerBindingLayout :: struct { - nextInChain: /* const */ ^ChainedStruct, - type: SamplerBindingType, -} - -SamplerDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - addressModeU: AddressMode, - addressModeV: AddressMode, - addressModeW: AddressMode, - magFilter: FilterMode, - minFilter: FilterMode, - mipmapFilter: MipmapFilterMode, - lodMinClamp: f32, - lodMaxClamp: f32, - compare: CompareFunction, - maxAnisotropy: u16, -} - ShaderModuleDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, } -ShaderSourceSPIRV :: struct { - using chain: ChainedStruct, - codeSize: u32, - code: /* const */ [^]u32 `fmt:"v,codeSize"`, -} - -ShaderSourceWGSL :: struct { - using chain: ChainedStruct, - code: StringView, -} - -StencilFaceState :: struct { - compare: CompareFunction, - failOp: StencilOperation, - depthFailOp: StencilOperation, - passOp: StencilOperation, -} - -StorageTextureBindingLayout :: struct { - nextInChain: /* const */ ^ChainedStruct, - access: StorageTextureAccess, - format: TextureFormat, - viewDimension: TextureViewDimension, -} - -SupportedFeatures :: struct { - featureCount: uint, - features: /* const */ [^]FeatureName `fmt:"v,featureCount"`, -} - -SupportedWGSLLanguageFeatures :: struct { - featureCount: uint, - features: /* const */ [^]WGSLLanguageFeatureName `fmt:"v,featureCount"`, -} - -SurfaceCapabilities :: struct { - nextInChain: ^ChainedStructOut, - usages: TextureUsageFlags, - formatCount: uint, - formats: /* const */ [^]TextureFormat `fmt:"v,formatCount"`, - presentModeCount: uint, - presentModes: /* const */ [^]PresentMode `fmt:"v,presentModeCount"`, - alphaModeCount: uint, - alphaModes: /* const */ [^]CompositeAlphaMode `fmt:"v,alphaModeCount"`, -} - -SurfaceConfiguration :: struct { - nextInChain: /* const */ ^ChainedStruct, - device: Device, - format: TextureFormat, - usage: TextureUsageFlags, - width: u32, - height: u32, - viewFormatCount: uint, - viewFormats: /* const */ [^]TextureFormat `fmt:"v,viewFormatCount"`, - alphaMode: CompositeAlphaMode, - presentMode: PresentMode, -} - SurfaceDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, } -SurfaceSourceAndroidNativeWindow :: struct { - using chain: ChainedStruct, - window: rawptr, -} - -SurfaceSourceCanvasHTMLSelector :: struct { - using chain: ChainedStruct, - selector: StringView, -} - -SurfaceSourceMetalLayer :: struct { - using chain: ChainedStruct, - layer: rawptr, -} - -SurfaceSourceWaylandSurface :: struct { - using chain: ChainedStruct, - display: rawptr, - surface: rawptr, -} - -SurfaceSourceWindowsHWND :: struct { - using chain: ChainedStruct, - hinstance: rawptr, - hwnd: rawptr, -} - -SurfaceSourceXcbWindow :: struct { - using chain: ChainedStruct, - connection: rawptr, - window: u32, -} - -SurfaceSourceXlibWindow :: struct { - using chain: ChainedStruct, - display: rawptr, - window: u64, -} - -SurfaceTexture :: struct { - nextInChain: ^ChainedStructOut, - texture: Texture, - status: SurfaceGetCurrentTextureStatus, -} - -TexelCopyBufferLayout :: struct { - offset: u64, - bytesPerRow: u32, - rowsPerImage: u32, -} - -TextureBindingLayout :: struct { - nextInChain: /* const */ ^ChainedStruct, - sampleType: TextureSampleType, - viewDimension: TextureViewDimension, - multisampled: b32, -} - -TextureViewDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - format: TextureFormat, - dimension: TextureViewDimension, - baseMipLevel: u32, - mipLevelCount: u32, - baseArrayLayer: u32, - arrayLayerCount: u32, - aspect: TextureAspect, - usage: TextureUsageFlags, -} - -VertexAttribute :: struct { - format: VertexFormat, - offset: u64, - shaderLocation: u32, -} - -BindGroupDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - layout: BindGroupLayout, - entryCount: uint, - entries: /* const */ [^]BindGroupEntry `fmt:"v,entryCount"`, -} - -BindGroupLayoutEntry :: struct { - nextInChain: /* const */ ^ChainedStruct, - binding: u32, - visibility: ShaderStageFlags, - buffer: BufferBindingLayout, - sampler: SamplerBindingLayout, - texture: TextureBindingLayout, - storageTexture: StorageTextureBindingLayout, -} - -BlendState :: struct { - color: BlendComponent, - alpha: BlendComponent, -} - -CompilationInfo :: struct { - nextInChain: /* const */ ^ChainedStruct, - messageCount: uint, - messages: /* const */ [^]CompilationMessage `fmt:"v,messageCount"`, -} - -ComputePassDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - /* NULLABLE */ timestampWrites: /* const */ ^ComputePassTimestampWrites, -} - -DepthStencilState :: struct { - nextInChain: /* const */ ^ChainedStruct, - format: TextureFormat, - depthWriteEnabled: OptionalBool, - depthCompare: CompareFunction, - stencilFront: StencilFaceState, - stencilBack: StencilFaceState, - stencilReadMask: u32, - stencilWriteMask: u32, - depthBias: i32, - depthBiasSlopeScale: f32, - depthBiasClamp: f32, -} - -DeviceDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - label: StringView, - requiredFeatureCount: uint, - requiredFeatures: /* const */ [^]FeatureName `fmt:"v,requiredFeatureCount"`, - /* NULLABLE */ requiredLimits: /* const */ ^Limits, - defaultQueue: QueueDescriptor, - deviceLostCallbackInfo: DeviceLostCallbackInfo, - uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo, -} - -FutureWaitInfo :: struct { - future: Future, - completed: b32, -} - -InstanceDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - features: InstanceCapabilities, -} - -ProgrammableStageDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, - module: ShaderModule, - entryPoint: StringView, - constantCount: uint, - constants: [^]ConstantEntry `fmt:"v,constantCount"`, -} - -RenderPassColorAttachment :: struct { - nextInChain: /* const */ ^ChainedStruct, - /* NULLABLE */ view: TextureView, - depthSlice: u32, - /* NULLABLE */ resolveTarget: TextureView, - loadOp: LoadOp, - storeOp: StoreOp, - clearValue: Color, -} - TexelCopyBufferInfo :: struct { layout: TexelCopyBufferLayout, buffer: Buffer, @@ -1341,8 +1428,16 @@ TexelCopyTextureInfo :: struct { aspect: TextureAspect, } +/* +Chained in a `TextureViewDescriptor`. +*/ +TextureComponentSwizzleDescriptor :: struct { + using chain: ChainedStruct, + swizzle: TextureComponentSwizzle, +} + TextureDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, usage: TextureUsageFlags, dimension: TextureDimension, @@ -1355,14 +1450,23 @@ TextureDescriptor :: struct { } VertexBufferLayout :: struct { + nextInChain: ^ChainedStruct, stepMode: VertexStepMode, arrayStride: u64, attributeCount: uint, attributes: /* const */ [^]VertexAttribute `fmt:"v,attributeCount"`, } +BindGroupDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + layout: BindGroupLayout, + entryCount: uint, + entries: /* const */ [^]BindGroupEntry `fmt:"v,entryCount"`, +} + BindGroupLayoutDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, entryCount: uint, entries: /* const */ [^]BindGroupLayoutEntry `fmt:"v,entryCount"`, @@ -1376,24 +1480,48 @@ ColorTargetState :: struct { } ComputePipelineDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, /* NULLABLE */ layout: PipelineLayout, - compute: ProgrammableStageDescriptor, + compute: ComputeState, +} + +DeviceDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + requiredFeatureCount: uint, + requiredFeatures: /* const */ [^]FeatureName `fmt:"v,requiredFeatureCount"`, + /* NULLABLE */ requiredLimits: /* const */ ^Limits, + defaultQueue: QueueDescriptor, + deviceLostCallbackInfo: DeviceLostCallbackInfo, + uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo, } RenderPassDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, colorAttachmentCount: uint, colorAttachments: /* const */ [^]RenderPassColorAttachment `fmt:"v,colorAttachmentCount"`, /* NULLABLE */ depthStencilAttachment: /* const */ ^RenderPassDepthStencilAttachment, /* NULLABLE */ occlusionQuerySet: QuerySet, - /* NULLABLE */ timestampWrites: /* const */ ^RenderPassTimestampWrites, + /* NULLABLE */ timestampWrites: /* const */ ^PassTimestampWrites, +} + +TextureViewDescriptor :: struct { + nextInChain: ^ChainedStruct, + label: StringView, + format: TextureFormat, + dimension: TextureViewDimension, + baseMipLevel: u32, + mipLevelCount: u32, + baseArrayLayer: u32, + arrayLayerCount: u32, + aspect: TextureAspect, + usage: TextureUsageFlags, } VertexState :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, module: ShaderModule, entryPoint: StringView, constantCount: uint, @@ -1403,7 +1531,7 @@ VertexState :: struct { } FragmentState :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, module: ShaderModule, entryPoint: StringView, constantCount: uint, @@ -1413,7 +1541,7 @@ FragmentState :: struct { } RenderPipelineDescriptor :: struct { - nextInChain: /* const */ ^ChainedStruct, + nextInChain: ^ChainedStruct, label: StringView, /* NULLABLE */ layout: PipelineLayout, vertex: VertexState, @@ -1427,8 +1555,10 @@ RenderPipelineDescriptor :: struct { foreign libwgpu { @(link_name="wgpuCreateInstance") RawCreateInstance :: proc(/* NULLABLE */ descriptor: /* const */ ^InstanceDescriptor = nil) -> Instance --- - @(link_name="wgpuGetInstanceCapabilities") - RawGetInstanceCapabilities :: proc(capabilities: ^InstanceCapabilities) -> Status --- + GetInstanceFeatures :: proc(features: ^SupportedInstanceFeatures) --- + @(link_name="wgpuGetInstanceLimits") + RawGetInstanceLimits :: proc(limits: ^InstanceLimits) -> Status --- + HasInstanceFeature :: proc(feature: InstanceFeatureName) -> b32 --- GetProcAddress :: proc(procName: StringView) -> Proc --- // Methods of Adapter @@ -1460,14 +1590,16 @@ foreign libwgpu { BufferDestroy :: proc(buffer: Buffer) --- @(link_name="wgpuBufferGetConstMappedRange") RawBufferGetConstMappedRange :: proc(buffer: Buffer, offset: uint, size: uint) -> /* const */ rawptr --- - BufferGetMapState :: proc(buffer: Buffer) -> BufferMapState --- @(link_name="wgpuBufferGetMappedRange") RawBufferGetMappedRange :: proc(buffer: Buffer, offset: uint, size: uint) -> rawptr --- + BufferGetMapState :: proc(buffer: Buffer) -> BufferMapState --- BufferGetSize :: proc(buffer: Buffer) -> u64 --- BufferGetUsage :: proc(buffer: Buffer) -> BufferUsageFlags --- BufferMapAsync :: proc(buffer: Buffer, mode: MapModeFlags, offset: uint, size: uint, callbackInfo: BufferMapCallbackInfo) -> Future --- + BufferReadMappedRange :: proc(buffer: Buffer, offset: uint, data: rawptr, size: uint) -> Status --- BufferSetLabel :: proc(buffer: Buffer, label: StringView) --- BufferUnmap :: proc(buffer: Buffer) --- + BufferWriteMappedRange :: proc(buffer: Buffer, offset: uint, data: rawptr, size: uint) -> Status --- BufferAddRef :: proc(buffer: Buffer) --- BufferRelease :: proc(buffer: Buffer) --- @@ -1545,10 +1677,14 @@ foreign libwgpu { DeviceAddRef :: proc(device: Device) --- DeviceRelease :: proc(device: Device) --- + // Methods of ExternalTexture + ExternalTextureSetLabel :: proc(externalTexture: ExternalTexture, label: StringView) --- + ExternalTextureAddRef :: proc(externalTexture: ExternalTexture) --- + ExternalTextureRelease :: proc(externalTexture: ExternalTexture) --- + // Methods of Instance InstanceCreateSurface :: proc(instance: Instance, descriptor: /* const */ ^SurfaceDescriptor) -> Surface --- - @(link_name="wgpuInstanceGetWGSLLanguageFeatures") - RawInstanceGetWGSLLanguageFeatures :: proc(instance: Instance, features: ^SupportedWGSLLanguageFeatures) -> Status --- + InstanceGetWGSLLanguageFeatures :: proc(instance: Instance, features: ^SupportedWGSLLanguageFeatures) --- InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLLanguageFeatureName) -> b32 --- InstanceProcessEvents :: proc(instance: Instance) --- InstanceRequestAdapter :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^RequestAdapterOptions, callbackInfo: RequestAdapterCallbackInfo) -> Future --- @@ -1648,6 +1784,9 @@ foreign libwgpu { // Methods of SupportedFeatures SupportedFeaturesFreeMembers :: proc(supportedFeatures: SupportedFeatures) --- + // Methods of SupportedInstanceFeatures + SupportedInstanceFeaturesFreeMembers :: proc(SupportedInstanceFeatures: SupportedInstanceFeatures) --- + // Methods of SupportedWGSLLanguageFeatures SupportedWGSLLanguageFeaturesFreeMembers :: proc(supportedWGSLLanguageFeatures: SupportedWGSLLanguageFeatures) --- @@ -1675,6 +1814,7 @@ foreign libwgpu { TextureGetHeight :: proc(texture: Texture) -> u32 --- TextureGetMipLevelCount :: proc(texture: Texture) -> u32 --- TextureGetSampleCount :: proc(texture: Texture) -> u32 --- + TextureGetTextureBindingViewDimension :: proc(texture: Texture) -> TextureViewDimension --- TextureGetUsage :: proc(texture: Texture) -> TextureUsageFlags --- TextureGetWidth :: proc(texture: Texture) -> u32 --- TextureSetLabel :: proc(texture: Texture, label: StringView) --- @@ -1706,13 +1846,8 @@ CreateInstance :: proc "c" (/* NULLABLE */ descriptor: /* const */ ^InstanceDesc return RawCreateInstance(descriptor) } -GetInstanceCapabilities :: proc "c" () -> (capabilities: InstanceCapabilities, status: Status) { - status = RawGetInstanceCapabilities(&capabilities) - return -} - -InstanceGetWGSLLanguageFeatures :: proc "c" (instance: Instance) -> (features: SupportedWGSLLanguageFeatures, status: Status) { - status = RawInstanceGetWGSLLanguageFeatures(instance, &features) +GetInstanceLimits :: proc "c" () -> (limits: InstanceLimits, status: Status) { + status = RawGetInstanceLimits(&limits) return } diff --git a/vendor/wgpu/wgpu_js.odin b/vendor/wgpu/wgpu_js.odin index 3c8375adb..3217a97dc 100644 --- a/vendor/wgpu/wgpu_js.odin +++ b/vendor/wgpu/wgpu_js.odin @@ -5,7 +5,7 @@ import "base:runtime" g_context: runtime.Context @(private="file", init) -wgpu_init_allocator :: proc() { +wgpu_init_allocator :: proc "contextless" () { if g_context.allocator.procedure == nil { g_context = runtime.default_context() } diff --git a/vendor/wgpu/wgpu_native.odin b/vendor/wgpu/wgpu_native.odin index def095e07..0fbd6338c 100644 --- a/vendor/wgpu/wgpu_native.odin +++ b/vendor/wgpu/wgpu_native.odin @@ -11,8 +11,10 @@ foreign libwgpu { @(link_name="wgpuQueueSubmitForIndex") RawQueueSubmitForIndex :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) -> SubmissionIndex --- + QueueGetTimestampPeriod :: proc(queue: Queue) -> f32 --- + // Returns true if the queue is empty, or false if there are more queue submissions still in flight. - DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ wrappedSubmissionIndex: /* const */ ^SubmissionIndex = nil) -> b32 --- + DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ submissionIndex: /* const */ ^SubmissionIndex = nil) -> b32 --- DeviceCreateShaderModuleSpirV :: proc(device: Device, descriptor: ^ShaderModuleDescriptorSpirV) -> ShaderModule --- SetLogCallback :: proc(callback: LogCallback, userdata: rawptr) --- @@ -21,9 +23,13 @@ foreign libwgpu { GetVersion :: proc() -> u32 --- - RenderPassEncoderSetPushConstants :: proc(encoder: RenderPassEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: rawptr) --- - ComputePassEncoderSetPushConstants :: proc(encoder: ComputePassEncoder, offset: u32, sizeBytes: u32, data: rawptr) --- - RenderBundleEncoderSetPushConstants :: proc(encoder: RenderBundleEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: rawptr) --- + DeviceGetNativeMetalDevice :: proc(device: Device) -> rawptr --- + DeviceGetNativeMetalCommandQueue :: proc(device: Device) -> rawptr --- + DeviceGetNativeMetalTexture :: proc(device: Device) -> rawptr --- + + RenderPassEncoderSetImmediates :: proc(encoder: RenderPassEncoder, offset: u32, sizeBytes: u32, data: rawptr) --- + ComputePassEncoderSetImmediates :: proc(encoder: ComputePassEncoder, offset: u32, sizeBytes: u32, data: rawptr) --- + RenderBundleEncoderSetImmediates :: proc(encoder: RenderBundleEncoder, offset: u32, sizeBytes: u32, data: rawptr) --- RenderPassEncoderMultiDrawIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- RenderPassEncoderMultiDrawIndexedIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) --- @@ -38,6 +44,9 @@ foreign libwgpu { ComputePassEncoderWriteTimestamp :: proc(computePassEncoder: ComputePassEncoder, querySet: QuerySet, queryIndex: u32) --- RenderPassEncoderWriteTimestamp :: proc(renderPassEncoder: RenderPassEncoder, querySet: QuerySet, queryIndex: u32) --- + + DeviceStartGraphicsDebuggerCapture :: proc(device: Device) -> b32 --- + DeviceStopGraphicsDebuggerCapture :: proc(device: Device) --- } GenerateReport :: proc "c" (instance: Instance) -> (report: GlobalReport) { diff --git a/vendor/wgpu/wgpu_native_types.odin b/vendor/wgpu/wgpu_native_types.odin index 025004c0c..931aa96db 100644 --- a/vendor/wgpu/wgpu_native_types.odin +++ b/vendor/wgpu/wgpu_native_types.odin @@ -2,8 +2,8 @@ package wgpu import "base:runtime" -BINDINGS_VERSION :: [4]u8{24, 0, 0, 2} -BINDINGS_VERSION_STRING :: "24.0.0.2" +BINDINGS_VERSION :: [4]u8{29, 0, 0, 0} +BINDINGS_VERSION_STRING :: "29.0.0.0" LogLevel :: enum i32 { Off, @@ -19,21 +19,29 @@ InstanceBackend :: enum i32 { GL, Metal, DX12, - DX11, - BrowserWebGPU, + // DX11, + BrowserWebGPU = 5, } InstanceBackendFlags :: bit_set[InstanceBackend; Flags] InstanceBackendFlags_All :: InstanceBackendFlags{} InstanceBackendFlags_Primary :: InstanceBackendFlags{ .Vulkan, .Metal, .DX12, .BrowserWebGPU } -InstanceBackendFlags_Secondary :: InstanceBackendFlags{ .GL, .DX11 } +InstanceBackendFlags_Secondary :: InstanceBackendFlags{ .GL } InstanceFlag :: enum i32 { Debug, Validation, DiscardHalLabels, + AllowUnderlyingNoncompliantAdapter, + GPUBasedValidation, + ValidationIndirectCall, + AutomaticTimestampNormalization, + Default = 24, + Debugging, + AdvancedDebugging, + WithEnv, } InstanceFlags :: bit_set[InstanceFlag; Flags] -InstanceFlags_Default :: InstanceFlags{} +InstanceFlags_Empty :: InstanceFlags{} Dx12Compiler :: enum i32 { Undefined, @@ -56,14 +64,71 @@ PipelineStatisticName :: enum i32 { ComputeShaderInvocations, } +DxcMaxShaderModel :: enum i32 { + V6_0, + V6_1, + V6_2, + V6_3, + V6_4, + V6_5, + V6_6, + V6_7, +} + +GLFenceBehaviour :: enum i32 { + Normal, + AutoFinish, +} + +Dx12SwapchainKind :: enum i32 { + Undefined, + DxgiFromHwnd, + DxgiFromVisual, +} + +NativeDisplayHandleType :: enum i32 { + None, + Xlib, + Xcb, + Wayland, +} + +XlibDisplayHandle :: struct { + display: rawptr, + screen: i32, +} + +XcbDisplayHandle :: struct { + connection: rawptr, + screen: i32, +} + +WaylandDisplayHandle :: struct { + display: rawptr, +} + +NativeDisplayHandle :: struct { + type: NativeDisplayHandleType, + using data: struct #raw_union { + xlib: XlibDisplayHandle, + xcb: XcbDisplayHandle, + wayland: WaylandDisplayHandle, + }, +} + InstanceExtras :: struct { using chain: ChainedStruct, backends: InstanceBackendFlags, flags: InstanceFlags, dx12ShaderCompiler: Dx12Compiler, gles3MinorVersion: Gles3MinorVersion, - dxilPath: StringView, + glFenceBehaviour: GLFenceBehaviour, dxcPath: StringView, + dcxMaxShaderModel: DxcMaxShaderModel, + dx12PresentationSystem: Dx12SwapchainKind, + budgetForDeviceCreation: ^u8, + budgetForDeviceLoss: ^u8, + displayHandle: NativeDisplayHandle, } DeviceExtras :: struct { @@ -72,21 +137,15 @@ DeviceExtras :: struct { } NativeLimits :: struct { - using chain: ChainedStructOut, - maxPushConstantSize: u32, + using chain: ChainedStruct, + maxImmediateSize: u32, maxNonSamplerBindings: u32, -} - -PushConstantRange :: struct { - stages: ShaderStageFlags, - start: u32, - end: u32, + maxBindingArrayElementsPerShaderStage: u32, } PipelineLayoutExtras :: struct { using chain: ChainedStruct, - pushConstantRangeCount: uint, - pushConstantRanges: [^]PushConstantRange `fmt:"v,pushConstantRangeCount"`, + immediateDataSize: u32, } SubmissionIndex :: distinct u64 @@ -96,7 +155,7 @@ ShaderDefine :: struct { value: StringView, } -ShaderModuleGLSLDescriptor :: struct { +ShaderSourceGLSL :: struct { using chain: ChainedStruct, stage: ShaderStage, code: StringView, @@ -173,6 +232,30 @@ SurfaceConfigurationExtras :: struct { desiredMaximumFrameLatency: u32, } +/** +* Chained in `SurfaceDescriptor` to make a `Surface` wrapping a WinUI [[ SwapChainPanel ; https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.swapchainpanel ]]. +*/ +SurfaceSourceSwapChainPanel :: struct { + using chain: ChainedStruct, + /** + * A pointer to the [[ ISwapChainPanelNative ; https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/win32/microsoft.ui.xaml.media.dxinterop/nn-microsoft-ui-xaml-media-dxinterop-iswapchainpanelnative ]] + * interface of the `SwapChainPanel` that will be wrapped by the `Surface`. + */ + panelNative: rawptr, +} + +PolygonMode :: enum i32 { + Fill, + Line, + Point, +} + +PrimitiveStateExtras :: struct { + using chain: ChainedStruct, + polygonMode: PolygonMode, + conservative: b32, +} + LogCallback :: #type proc "c" (level: LogLevel, message: StringView, userdata: rawptr) // Wrappers diff --git a/vendor/windows/GameInput/doc.odin b/vendor/windows/GameInput/doc.odin new file mode 100644 index 000000000..873062edf --- /dev/null +++ b/vendor/windows/GameInput/doc.odin @@ -0,0 +1,6 @@ +/* + Bindings for [[ Windows Game Input GDK ; https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/input/overviews/input-overview ]]. + + Windows SDK 10.0.26100.0 is at least required to link with. +*/ +package windows_game_input \ No newline at end of file diff --git a/vendor/windows/GameInput/windows_game_input.odin b/vendor/windows/GameInput/windows_game_input.odin index f4e7a4e3c..445a7c665 100644 --- a/vendor/windows/GameInput/windows_game_input.odin +++ b/vendor/windows/GameInput/windows_game_input.odin @@ -7,15 +7,115 @@ */ package windows_game_input -foreign import wgi { - "system:gameinput.lib", +foreign import wgi "system:gameinput.lib" + +import win "core:sys/windows" + +HRESULT :: win.HRESULT +HANDLE :: win.HANDLE +IUnknown :: win.IUnknown +IUnknown_VTable :: win.IUnknown_VTable +IID :: win.IID + +APP_LOCAL_DEVICE_ID :: distinct [32]byte + +Kind :: distinct bit_set[KindFlag; u32] +KindFlag :: enum u32 { + RawDeviceReport = 0, + ControllerAxis = 1, + ControllerButton = 2, + ControllerSwitch = 3, + Keyboard = 4, + Mouse = 5, + Touch = 8, + Motion = 12, + ArcadeStick = 16, + FlightStick = 17, + Gamepad = 18, + RacingWheel = 19, + UiNavigation = 20, +} +KindUnknown :: Kind{} +KindController :: Kind{ .ControllerAxis, .ControllerButton, .ControllerSwitch } + +EnumerationKind :: enum i32 { + NoEnumeration = 0, + AsyncEnumeration = 1, + BlockingEnumeration = 2, } -import "core:c" -import "core:sys/windows" +FocusPolicy :: distinct bit_set[FocusPolicyFlag; u32] +FocusPolicyFlag :: enum u32 { + DisableBackgroundInput = 0, + ExclusiveForegroundInput = 1, + DisableBackgroundGuideButton = 2, + ExclusiveForegroundGuideButton = 3, + DisableBackgroundShareButton = 4, + ExclusiveForegroundShareButton = 5, +} +DefaultFocusPolicy :: FocusPolicy{} -// Enums -ArcadeStickButtonsFlag :: enum c.int { +SwitchKind :: enum i32 { + UnknownSwitchKind = -1, + TwoWaySwitch = 0, + FourWaySwitch = 1, + EightWaySwitch = 2, +} + +SwitchPosition :: enum i32 { + Center = 0, + Up = 1, + UpRight = 2, + Right = 3, + DownRight = 4, + Down = 5, + DownLeft = 6, + Left = 7, + UpLeft = 8, +} + +KeyboardKind :: enum i32 { + UnknownKeyboard = -1, + AnsiKeyboard = 0, + IsoKeyboard = 1, + KsKeyboard = 2, + AbntKeyboard = 3, + JisKeyboard = 4, +} + +MouseButtons :: distinct bit_set[MouseButtonsFlag; u32] +MouseButtonsFlag :: enum u32 { + LeftButton = 0, + RightButton = 1, + MiddleButton = 2, + Button4 = 3, + Button5 = 4, + WheelTiltLeft = 5, + WheelTiltRight = 6, +} +MouseNone :: MouseButtons{} + +TouchShape :: enum i32 { + Unknown = -1, + Point = 0, + Linear1D = 1, + Radial1D = 2, + Irregular1D = 3, + Rectangular2D = 4, + Elliptical2D = 5, + Irregular2D = 6, +} + +MotionAccuracy :: enum i32 { + AccuracyUnknown = -1, + Unavailable = 0, + Unreliable = 1, + Approximate = 2, + Accurate = 3, +} + +ArcadeStickButtons :: distinct bit_set[ArcadeStickButtonsFlag; u32] +ArcadeStickButtonsFlag :: enum u32 { Menu = 0, View = 1, Up = 2, @@ -31,104 +131,19 @@ ArcadeStickButtonsFlag :: enum c.int { Special1 = 12, Special2 = 13, } -ArcadeStickButtons :: distinct bit_set[ArcadeStickButtonsFlag; c.int] +ArcadeStickNone :: ArcadeStickButtons{} -BatteryStatus :: enum c.int { - Unknown = -1, - NotPresent = 0, - Discharging = 1, - Idle = 2, - Charging = 3, +FlightStickButtons :: distinct bit_set[FlightStickButtonsFlag; u32] +FlightStickButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + FirePrimary = 2, + FireSecondary = 3, } +FlightStickNone :: FlightStickButtons{} -DeviceCapabilitiesFlag :: enum c.int { - Audio = 0, - PluginModule = 1, - PowerOff = 2, - Synchronization = 3, - Wireless = 4, -} -DeviceCapabilities :: distinct bit_set[DeviceCapabilitiesFlag; c.int] - -DeviceFamily :: enum c.int { - Virtual = -1, - Aggregate = 0, - XboxOne = 1, - Xbox360 = 2, - Hid = 3, - I8042 = 4, -} - -DeviceStatusFlag :: enum c.int { - Connected = 0, - InputEnabled = 1, - OutputEnabled = 2, - RawIoEnabled = 3, - AudioCapture = 4, - AudioRender = 5, - Synchronized = 6, - Wireless = 7, - UserIdle = 20, -} -DeviceStatus :: distinct bit_set[DeviceStatusFlag; c.int] - -EnumerationKind :: enum c.int { - NoEnumeration = 0, - AsyncEnumeration = 1, - BlockingEnumeration = 2, -} - -FeedbackAxesFlag :: enum c.int { - LinearX = 0, - LinearY = 1, - LinearZ = 2, - AngularX = 3, - AngularY = 4, - AngularZ = 5, - Normal = 6, -} -FeedbackAxes :: distinct bit_set[FeedbackAxesFlag; c.int] - -FeedbackEffectState :: enum c.int { - Stopped = 0, - Running = 1, - Paused = 2, -} - -FlightStickButtonsFlag :: enum c.int { - None = 0, - Menu = 1, - View = 2, - FirePrimary = 3, - FireSecondary = 4, -} -FlightStickButtons :: distinct bit_set[FlightStickButtonsFlag; c.int] - -FocusPolicyFlag :: enum c.int { - DisableBackgroundInput = 0, - ExclusiveForegroundInput = 1, - DisableBackgroundGuideButton = 2, - ExclusiveForegroundGuideButton = 3, - DisableBackgroundShareButton = 4, - ExclusiveForegroundShareButton = 5, -} -FocusPolicy :: distinct bit_set[FocusPolicyFlag; c.int] - -ForceFeedbackEffectKind :: enum c.int { - Constant = 0, - Ramp = 1, - SineWave = 2, - SquareWave = 3, - TriangleWave = 4, - SawtoothUpWave = 5, - SawtoothDownWave = 6, - Spring = 7, - Friction = 8, - Damper = 9, - Inertia = 10, -} - -GamepadButtonsFlag :: enum c.int { +GamepadButtons :: distinct bit_set[GamepadButtonsFlag; u32] +GamepadButtonsFlag :: enum u32 { Menu = 0, View = 1, A = 2, @@ -144,36 +159,156 @@ GamepadButtonsFlag :: enum c.int { LeftThumbstick = 12, RightThumbstick = 13, } -GamepadButtons :: distinct bit_set[GamepadButtonsFlag; c.int] +GamepadNone :: GamepadButtons{} -KeyboardKind :: enum c.int { - UnknownKeyboard = -1, - AnsiKeyboard = 0, - IsoKeyboard = 1, - KsKeyboard = 2, - AbntKeyboard = 3, - JisKeyboard = 4, +RacingWheelButtons :: distinct bit_set[RacingWheelButtonsFlag; u32] +RacingWheelButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + PreviousGear = 2, + NextGear = 3, + DpadUp = 4, + DpadDown = 5, + DpadLeft = 6, + DpadRight = 7, +} +RacingWheelNone :: RacingWheelButtons{} + +UiNavigationButtons :: distinct bit_set[UiNavigationButtonsFlag; u32] +UiNavigationButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + Accept = 2, + Cancel = 3, + Up = 4, + Down = 5, + Left = 6, + Right = 7, + Context1 = 8, + Context2 = 9, + Context3 = 10, + Context4 = 11, + PageUp = 12, + PageDown = 13, + PageLeft = 14, + PageRight = 15, + ScrollUp = 16, + ScrollDown = 17, + ScrollLeft = 18, + ScrollRight = 19, +} +UiNavigationNone :: UiNavigationButtons{} + +SystemButtons :: distinct bit_set[SystemButtonsFlag; u32] +SystemButtonsFlag :: enum u32 { + Guide = 0, + Share = 1, +} +SystemButtonNone :: SystemButtons{} + +DeviceStatus :: distinct bit_set[DeviceStatusFlag; u32] +DeviceStatusFlag :: enum u32 { + Connected = 0, + InputEnabled = 1, + OutputEnabled = 2, + RawIoEnabled = 3, + AudioCapture = 4, + AudioRender = 5, + Synchronized = 6, + Wireless = 7, + UserIdle = 20, +} +DeviceNoStatus :: DeviceStatus{} +//DeviceAnyStatus :: 0x00FFFFFF + +BatteryStatus :: enum i32 { + Unknown = -1, + NotPresent = 0, + Discharging = 1, + Idle = 2, + Charging = 3, } -KindFlag :: enum c.int { - RawDeviceReport = 0, - ControllerAxis = 1, - ControllerButton = 2, - ControllerSwitch = 3, - Keyboard = 4, - Mouse = 5, - Touch = 8, - Motion = 12, - ArcadeStick = 16, - FlightStick = 17, - Gamepad = 18, - RacingWheel = 19, - UiNavigation = 20, +DeviceFamily :: enum i32 { + Virtual = -1, + Aggregate = 0, + XboxOne = 1, + Xbox360 = 2, + Hid = 3, + I8042 = 4, } -Kind :: distinct bit_set[KindFlag; c.int] -Kind_Controller : Kind : { .ControllerAxis, .ControllerButton, .ControllerSwitch } -Label :: enum c.int { +DeviceCapabilities :: distinct bit_set[DeviceCapabilitiesFlag; u32] +DeviceCapabilitiesFlag :: enum u32 { + Audio = 0, + PluginModule = 1, + PowerOff = 2, + Synchronization = 3, + Wireless = 4, +} +DeviceCapabilityNone :: DeviceCapabilities{} + +RawDeviceReportKind :: enum i32 { + InputReport = 0, + OutputReport = 1, + FeatureReport = 2, +} + +RawDeviceReportItemFlags :: distinct bit_set[RawDeviceReportItemFlag; u32] +RawDeviceReportItemFlag :: enum u32 { + ConstantItem = 0, + ArrayItem = 1, + RelativeItem = 2, + WraparoundItem = 3, + NonlinearItem = 4, + StableItem = 5, + NullableItem = 6, + VolatileItem = 7, + BufferedItem = 8, +} +RawDeviceDefaultItem :: RawDeviceReportItemFlags{} + +RawDeviceItemCollectionKind :: enum i32 { + UnknownItemCollection = -1, + PhysicalItemCollection = 0, + ApplicationItemCollection = 1, + LogicalItemCollection = 2, + ReportItemCollection = 3, + NamedArrayItemCollection = 4, + UsageSwitchItemCollection = 5, + UsageModifierItemCollection = 6, +} + +RawDevicePhysicalUnitKind :: enum i32 { + Unknown = -1, + None = 0, + Time = 1, + Frequency = 2, + Length = 3, + Velocity = 4, + Acceleration = 5, + Mass = 6, + Momentum = 7, + Force = 8, + Pressure = 9, + Angle = 10, + AngularVelocity = 11, + AngularAcceleration = 12, + AngularMass = 13, + AngularMomentum = 14, + AngularTorque = 15, + ElectricCurrent = 16, + ElectricCharge = 17, + ElectricPotential = 18, + Energy = 19, + Power = 20, + Temperature = 21, + LuminousIntensity = 22, + LuminousFlux = 23, + Illuminance = 24, +} + +Label :: enum i32 { Unknown = -1, None = 0, XboxGuide = 1, @@ -301,7 +436,7 @@ Label :: enum c.int { P4 = 124, } -Location :: enum c.int { +Location :: enum i32 { Unknown = -1, Chassis = 0, Display = 1, @@ -312,189 +447,142 @@ Location :: enum c.int { TouchPad = 6, } -MotionAccuracy :: enum c.int { - AccuracyUnknown = -1, - Unavailable = 0, - Unreliable = 1, - Approximate = 2, - Accurate = 3, +FeedbackAxes :: distinct bit_set[FeedbackAxesFlag; u32] +FeedbackAxesFlag :: enum u32 { + LinearX = 0, + LinearY = 1, + LinearZ = 2, + AngularX = 3, + AngularY = 4, + AngularZ = 5, + Normal = 6, +} +FeedbackAxisNone :: FeedbackAxes{} + +FeedbackEffectState :: enum i32 { + Stopped = 0, + Running = 1, + Paused = 2, } -MouseButtonsFlag :: enum c.int { - LeftButton = 0, - RightButton = 1, - MiddleButton = 2, - Button4 = 3, - Button5 = 4, - WheelTiltLeft = 5, - WheelTiltRight = 6, -} -MouseButtons :: distinct bit_set[MouseButtonsFlag; c.int] - -RacingWheelButtonsFlag :: enum c.int { - Menu = 0, - View = 1, - PreviousGear = 2, - NextGear = 3, - DpadUp = 4, - DpadDown = 5, - DpadLeft = 6, - DpadRight = 7, -} -RacingWheelButtons :: distinct bit_set[RacingWheelButtonsFlag; c.int] - -RawDeviceItemCollectionKind :: enum c.int { - UnknownItemCollection = -1, - PhysicalItemCollection = 0, - ApplicationItemCollection = 1, - LogicalItemCollection = 2, - ReportItemCollection = 3, - NamedArrayItemCollection = 4, - UsageSwitchItemCollection = 5, - UsageModifierItemCollection = 6, +ForceFeedbackEffectKind :: enum i32 { + Constant = 0, + Ramp = 1, + SineWave = 2, + SquareWave = 3, + TriangleWave = 4, + SawtoothUpWave = 5, + SawtoothDownWave = 6, + Spring = 7, + Friction = 8, + Damper = 9, + Inertia = 10, } -RawDevicePhysicalUnitKind :: enum c.int { - Unknown = -1, - None = 0, - Time = 1, - Frequency = 2, - Length = 3, - Velocity = 4, - Acceleration = 5, - Mass = 6, - Momentum = 7, - Force = 8, - Pressure = 9, - Angle = 10, - AngularVelocity = 11, - AngularAcceleration = 12, - AngularMass = 13, - AngularMomentum = 14, - AngularTorque = 15, - ElectricCurrent = 16, - ElectricCharge = 17, - ElectricPotential = 18, - Energy = 19, - Power = 20, - Temperature = 21, - LuminousIntensity = 22, - LuminousFlux = 23, - Illuminance = 24, -} - -RawDeviceReportItemFlag :: enum c.int { - ConstantItem = 0, - ArrayItem = 1, - RelativeItem = 2, - WraparoundItem = 3, - NonlinearItem = 4, - StableItem = 5, - NullableItem = 6, - VolatileItem = 7, - BufferedItem = 8, -} -RawDeviceReportItemFlags :: distinct bit_set[RawDeviceReportItemFlag; c.int] - -RawDeviceReportKind :: enum c.int { - InputReport = 0, - OutputReport = 1, - FeatureReport = 2, -} - -RumbleMotorsFlag :: enum c.int { +RumbleMotors :: distinct bit_set[RumbleMotorsFlag; u32] +RumbleMotorsFlag :: enum u32 { LowFrequency = 0, HighFrequency = 1, LeftTrigger = 2, RightTrigger = 3, } -RumbleMotors :: distinct bit_set[RumbleMotorsFlag; c.int] +RumbleNone :: RumbleMotors{} -SwitchKind :: enum c.int { - UnknownSwitchKind = -1, - TwoWaySwitch = 0, - FourWaySwitch = 1, - EightWaySwitch = 2, +CallbackToken :: distinct u64 + +CURRENT_CALLBACK_TOKEN_VALUE :: CallbackToken(0xFFFFFFFFFFFFFFFF) +INVALID_CALLBACK_TOKEN_VALUE :: CallbackToken(0x0000000000000000) + +ReadingCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, reading: ^IReading, hasOverrunOccured: bool) +DeviceCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IDevice, timestamp: u64, currentStatus: DeviceStatus, previousStatus: DeviceStatus) +SystemButtonCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IDevice, timestamp: u64, currentButtons: SystemButtons, previousButtons: SystemButtons) +KeyboardLayoutCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IDevice, timestamp: u64, currentLayout: u32, previousLayout: u32) + +KeyState :: struct { + scanCode: u32, + codePoint: u32, + virtualKey: u8, + isDeadKey: bool, } -SwitchPosition :: enum c.int { - Center = 0, - Up = 1, - UpRight = 2, - Right = 3, - DownRight = 4, - Down = 5, - DownLeft = 6, - Left = 7, - UpLeft = 8, +MouseState :: struct { + buttons: MouseButtons, + positionX: i64, + positionY: i64, + wheelX: i64, + wheelY: i64, } -SystemButtonsFlag :: enum c.int { - Guide = 0, - Share = 1 , -} -SystemButtons :: distinct bit_set[SystemButtonsFlag; c.int] - -TouchShape :: enum c.int { - Unknown = -1, - Point = 0, - Shape1DLinear = 1, - Shape1DRadial = 2, - Shape1DIrregular = 3, - Shape2DRectangular = 4, - Shape2DElliptical = 5, - Shape2DIrregular = 6, +TouchState :: struct { + touchId: u64, + sensorIndex: u32, + positionX: f32, + positionY: f32, + pressure: f32, + proximity: f32, + contactRectTop: f32, + contactRectLeft: f32, + contactRectRight: f32, + contactRectBottom: f32, } -UiNavigationButtonsFlag :: enum c.int { - Menu = 0, - View = 1, - Accept = 2, - Cancel = 3, - Up = 4, - Down = 5, - Left = 6, - Right = 7, - Context1 = 8, - Context2 = 9, - Context3 = 10, - Context4 = 11, - PageUp = 12, - PageDown = 13, - PageLeft = 14, - PageRight = 15, - ScrollUp = 16, - ScrollDown = 17, - ScrollLeft = 18, - ScrollRight = 19, -} -UiNavigationButtons :: distinct bit_set[UiNavigationButtonsFlag; c.int] - -// Structs - -APP_LOCAL_DEVICE_ID :: distinct [32]byte - -ArcadeStickInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - stickUpLabel: Label, - stickDownLabel: Label, - stickLeftLabel: Label, - stickRightLabel: Label, - actionButton1Label: Label, - actionButton2Label: Label, - actionButton3Label: Label, - actionButton4Label: Label, - actionButton5Label: Label, - actionButton6Label: Label, - specialButton1Label: Label, - specialButton2Label: Label, +MotionState :: struct { + accelerationX: f32, + accelerationY: f32, + accelerationZ: f32, + angularVelocityX: f32, + angularVelocityY: f32, + angularVelocityZ: f32, + magneticFieldX: f32, + magneticFieldY: f32, + magneticFieldZ: f32, + orientationW: f32, + orientationX: f32, + orientationY: f32, + orientationZ: f32, + accelerometerAccuracy: MotionAccuracy, + gyroscopeAccuracy: MotionAccuracy, + magnetometerAccuracy: MotionAccuracy, + orientationAccuracy: MotionAccuracy, } ArcadeStickState :: struct { buttons: ArcadeStickButtons, } +FlightStickState :: struct { + buttons: FlightStickButtons, + hatSwitch: SwitchPosition, + roll: f32, + pitch: f32, + yaw: f32, + throttle: f32, +} + +GamepadState :: struct { + buttons: GamepadButtons, + leftTrigger: f32, + rightTrigger: f32, + leftThumbstickX: f32, + leftThumbstickY: f32, + rightThumbstickX: f32, + rightThumbstickY: f32, +} + +RacingWheelState :: struct { + buttons: RacingWheelButtons, + patternShifterGear: i32, + wheel: f32, + throttle: f32, + brake: f32, + clutch: f32, + handbrake: f32, +} + +UiNavigationState :: struct { + buttons: UiNavigationButtons, +} + BatteryState :: struct { chargeRate: f32, maxChargeRate: f32, @@ -503,6 +591,64 @@ BatteryState :: struct { status: BatteryStatus, } +String :: struct { + sizeInBytes: u32, + codePointCount: u32, + data: [^]byte, +} + +Usage :: struct { + page: u16, + id: u16, +} + +Version :: struct { + major: u16, + minor: u16, + build: u16, + revision: u16, +} + +RawDeviceItemCollectionInfo :: struct { + kind: RawDeviceItemCollectionKind, + childCount: u32, + siblingCount: u32, + usageCount: u32, + usages: [^]Usage `fmt:"v,usageCount"`, + parent: ^RawDeviceItemCollectionInfo, + firstSibling: ^RawDeviceItemCollectionInfo, + previousSibling: ^RawDeviceItemCollectionInfo, + nextSibling: ^RawDeviceItemCollectionInfo, + lastSibling: ^RawDeviceItemCollectionInfo, + firstChild: ^RawDeviceItemCollectionInfo, + lastChild: ^RawDeviceItemCollectionInfo, +} + +RawDeviceReportItemInfo :: struct { + bitOffset: u32, + bitSize: u32, + logicalMin: i64, + logicalMax: i64, + physicalMin: f64, + physicalMax: f64, + physicalUnits: RawDevicePhysicalUnitKind, + rawPhysicalUnits: u32, + rawPhysicalUnitsExponent: i32, + flags: RawDeviceReportItemFlags, + usageCount: u32, + usages: [^]Usage `fmt:"v,usageCount"`, + collection: ^RawDeviceItemCollectionInfo, + itemString: ^String, +} + +RawDeviceReportInfo :: struct { + kind: RawDeviceReportKind, + id: u32, + size: u32, + itemCount: u32, + items: [^]RawDeviceReportItemInfo `fmt:"v,itemCount"`, +} + ControllerAxisInfo :: struct { mappedInputKinds: Kind, label: Label, @@ -541,6 +687,166 @@ ControllerSwitchInfo :: struct { inputReportItem: ^RawDeviceReportItemInfo, } +KeyboardInfo :: struct { + kind: KeyboardKind, + layout: u32, + keyCount: u32, + functionKeyCount: u32, + maxSimultaneousKeys: u32, + platformType: u32, + platformSubtype: u32, + nativeLanguage: ^String, +} + +MouseInfo :: struct { + supportedButtons: MouseButtons, + sampleRate: u32, + sensorDpi: u32, + hasWheelX: bool, + hasWheelY: bool, +} + +TouchSensorInfo :: struct { + mappedInputKinds: Kind, + label: Label, + location: Location, + locationId: u32, + resolutionX: u64, + resolutionY: u64, + shape: TouchShape, + aspectRatio: f32, + orientation: f32, + physicalWidth: f32, + physicalHeight: f32, + maxPressure: f32, + maxProximity: f32, + maxTouchPoints: u32, +} + +MotionInfo :: struct { + maxAcceleration: f32, + maxAngularVelocity: f32, + maxMagneticFieldStrength: f32, +} + +ArcadeStickInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + stickUpLabel: Label, + stickDownLabel: Label, + stickLeftLabel: Label, + stickRightLabel: Label, + actionButton1Label: Label, + actionButton2Label: Label, + actionButton3Label: Label, + actionButton4Label: Label, + actionButton5Label: Label, + actionButton6Label: Label, + specialButton1Label: Label, + specialButton2Label: Label, +} + +FlightStickInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + firePrimaryButtonLabel: Label, + fireSecondaryButtonLabel: Label, + hatSwitchKind: SwitchKind, +} + +GamepadInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + aButtonLabel: Label, + bButtonLabel: Label, + xButtonLabel: Label, + yButtonLabel: Label, + dpadUpLabel: Label, + dpadDownLabel: Label, + dpadLeftLabel: Label, + dpadRightLabel: Label, + leftShoulderButtonLabel: Label, + rightShoulderButtonLabel: Label, + leftThumbstickButtonLabel: Label, + rightThumbstickButtonLabel: Label, +} + +RacingWheelInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + previousGearButtonLabel: Label, + nextGearButtonLabel: Label, + dpadUpLabel: Label, + dpadDownLabel: Label, + dpadLeftLabel: Label, + dpadRightLabel: Label, + hasClutch: bool, + hasHandbrake: bool, + hasPatternShifter: bool, + minPatternShifterGear: i32, + maxPatternShifterGear: i32, + maxWheelAngle: f32, +} + +UiNavigationInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + acceptButtonLabel: Label, + cancelButtonLabel: Label, + upButtonLabel: Label, + downButtonLabel: Label, + leftButtonLabel: Label, + rightButtonLabel: Label, + contextButton1Label: Label, + contextButton2Label: Label, + contextButton3Label: Label, + contextButton4Label: Label, + pageUpButtonLabel: Label, + pageDownButtonLabel: Label, + pageLeftButtonLabel: Label, + pageRightButtonLabel: Label, + scrollUpButtonLabel: Label, + scrollDownButtonLabel: Label, + scrollLeftButtonLabel: Label, + scrollRightButtonLabel: Label, + guideButtonLabel: Label, +} + +ForceFeedbackMotorInfo :: struct { + supportedAxes: FeedbackAxes, + location: Location, + locationId: u32, + maxSimultaneousEffects: u32, + isConstantEffectSupported: bool, + isRampEffectSupported: bool, + isSineWaveEffectSupported: bool, + isSquareWaveEffectSupported: bool, + isTriangleWaveEffectSupported: bool, + isSawtoothUpWaveEffectSupported: bool, + isSawtoothDownWaveEffectSupported: bool, + isSpringEffectSupported: bool, + isFrictionEffectSupported: bool, + isDamperEffectSupported: bool, + isInertiaEffectSupported: bool, +} + +HapticWaveformInfo :: struct { + usage: Usage, + isDurationSupported: bool, + isIntensitySupported: bool, + isRepeatSupported: bool, + isRepeatDelaySupported: bool, + defaultDuration: u64, +} + +HapticFeedbackMotorInfo :: struct { + mappedRumbleMotor: RumbleMotors, + location: Location, + locationId: u32, + waveformCount: u32, + waveformInfo: [^]HapticWaveformInfo `fmt:"v,waveformCount"`, +} + DeviceInfo :: struct { infoSize: u32, vendorId: u16, @@ -569,60 +875,28 @@ DeviceInfo :: struct { hapticFeedbackMotorCount: u32, deviceStringCount: u32, deviceDescriptorSize: u32, - inputReportInfo: ^RawDeviceReportInfo, - outputReportInfo: ^RawDeviceReportInfo, - featureReportInfo: ^RawDeviceReportInfo, - controllerAxisInfo: ^ControllerAxisInfo, - controllerButtonInfo: ^ControllerButtonInfo, - controllerSwitchInfo: ^ControllerSwitchInfo, + inputReportInfo: [^]RawDeviceReportInfo `fmt:"v,inputReportCount"`, + outputReportInfo: [^]RawDeviceReportInfo `fmt:"v,outputReportCount"`, + featureReportInfo: [^]RawDeviceReportInfo `fmt:"v,featureReportCount"`, + controllerAxisInfo: [^]ControllerAxisInfo `fmt:"v,controllerAxisCount"`, + controllerButtonInfo: [^]ControllerButtonInfo `fmt:"v,controllerButtonCount"`, + controllerSwitchInfo: [^]ControllerSwitchInfo `fmt:"v,controllerSwitchCount"`, keyboardInfo: ^KeyboardInfo, mouseInfo: ^MouseInfo, - touchSensorInfo: ^TouchSensorInfo, + touchSensorInfo: [^]TouchSensorInfo `fmt:"v,touchSensorCount"`, motionInfo: ^MotionInfo, arcadeStickInfo: ^ArcadeStickInfo, flightStickInfo: ^FlightStickInfo, gamepadInfo: ^GamepadInfo, racingWheelInfo: ^RacingWheelInfo, uiNavigationInfo: ^UiNavigationInfo, - forceFeedbackMotorInfo: ^ForceFeedbackMotorInfo, - hapticFeedbackMotorInfo: ^HapticFeedbackMotorInfo, + forceFeedbackMotorInfo: [^]ForceFeedbackMotorInfo `fmt:"v,forceFeedbackMotorCount"`, + hapticFeedbackMotorInfo: [^]HapticFeedbackMotorInfo `fmt:"v,hapticFeedbackMotorCount"`, displayName: ^String, - deviceStrings: ^String, + deviceStrings: [^]String `fmt:"v,deviceStringCount"`, deviceDescriptorData: rawptr, } -FlightStickInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - firePrimaryButtonLabel: Label, - fireSecondaryButtonLabel: Label, - hatSwitchKind: SwitchKind, -} - -FlightStickState :: struct { - buttons: FlightStickButtons, - hatSwitch: SwitchPosition, - roll: f32, - pitch: f32, - yaw: f32, - throttle: f32, -} - -ForceFeedbackConditionParams :: struct { - magnitude: ForceFeedbackMagnitude, - positiveCoefficient: f32, - negativeCoefficient: f32, - maxPositiveMagnitude: f32, - maxNegativeMagnitude: f32, - deadZone: f32, - bias: f32, -} - -ForceFeedbackConstantParams :: struct { - envelope: ForceFeedbackEnvelope, - magnitude: ForceFeedbackMagnitude, -} - ForceFeedbackEnvelope :: struct { attackDuration: u64, sustainDuration: u64, @@ -644,39 +918,19 @@ ForceFeedbackMagnitude :: struct { normal: f32, } -ForceFeedbackMotorInfo :: struct { - supportedAxes: FeedbackAxes, - location: Location, - locationId: u32, - maxSimultaneousEffects: u32, - isConstantEffectSupported: bool, - isRampEffectSupported: bool, - isSineWaveEffectSupported: bool, - isSquareWaveEffectSupported: bool, - isTriangleWaveEffectSupported: bool, - isSawtoothUpWaveEffectSupported: bool, - isSawtoothDownWaveEffectSupported: bool, - isSpringEffectSupported: bool, - isFrictionEffectSupported: bool, - isDamperEffectSupported: bool, - isInertiaEffectSupported: bool, +ForceFeedbackConditionParams :: struct { + magnitude: ForceFeedbackMagnitude, + positiveCoefficient: f32, + negativeCoefficient: f32, + maxPositiveMagnitude: f32, + maxNegativeMagnitude: f32, + deadZone: f32, + bias: f32, } -ForceFeedbackParams :: struct { - kind: ForceFeedbackEffectKind, - using _: struct #raw_union { - constant: ForceFeedbackConstantParams, - ramp: ForceFeedbackRampParams, - sineWave: ForceFeedbackPeriodicParams, - squareWave: ForceFeedbackPeriodicParams, - triangleWave: ForceFeedbackPeriodicParams, - sawtoothUpWave: ForceFeedbackPeriodicParams, - sawtoothDownWave: ForceFeedbackPeriodicParams, - spring: ForceFeedbackConditionParams, - friction: ForceFeedbackConditionParams, - damper: ForceFeedbackConditionParams, - inertia: ForceFeedbackConditionParams, - }, +ForceFeedbackConstantParams :: struct { + envelope: ForceFeedbackEnvelope, + magnitude: ForceFeedbackMagnitude, } ForceFeedbackPeriodicParams :: struct { @@ -693,39 +947,21 @@ ForceFeedbackRampParams :: struct { endMagnitude: ForceFeedbackMagnitude, } -GamepadInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - aButtonLabel: Label, - bButtonLabel: Label, - xButtonLabel: Label, - yButtonLabel: Label, - dpadUpLabel: Label, - dpadDownLabel: Label, - dpadLeftLabel: Label, - dpadRightLabel: Label, - leftShoulderButtonLabel: Label, - rightShoulderButtonLabel: Label, - leftThumbstickButtonLabel: Label, - rightThumbstickButtonLabel: Label, -} - -GamepadState :: struct { - buttons: GamepadButtons, - leftTrigger: f32, - rightTrigger: f32, - leftThumbstickX: f32, - leftThumbstickY: f32, - rightThumbstickX: f32, - rightThumbstickY: f32, -} - -HapticFeedbackMotorInfo :: struct { - mappedRumbleMotor: RumbleMotors, - location: Location, - locationId: u32, - waveformCount: u32, - waveformInfo: [^]HapticWaveformInfo `fmt:"v,waveformCount"`, +ForceFeedbackParams :: struct { + kind: ForceFeedbackEffectKind, + using data: struct #raw_union { + constant: ForceFeedbackConstantParams, + ramp: ForceFeedbackRampParams, + sineWave: ForceFeedbackPeriodicParams, + squareWave: ForceFeedbackPeriodicParams, + triangleWave: ForceFeedbackPeriodicParams, + sawtoothUpWave: ForceFeedbackPeriodicParams, + sawtoothDownWave: ForceFeedbackPeriodicParams, + spring: ForceFeedbackConditionParams, + friction: ForceFeedbackConditionParams, + damper: ForceFeedbackConditionParams, + inertia: ForceFeedbackConditionParams, + }, } HapticFeedbackParams :: struct { @@ -736,142 +972,6 @@ HapticFeedbackParams :: struct { repeatDelay: u64, } -HapticWaveformInfo :: struct { - usage: Usage, - isDurationSupported: bool, - isIntensitySupported: bool, - isRepeatSupported: bool, - isRepeatDelaySupported: bool, - defaultDuration: u64, -} - -KeyboardInfo :: struct { - kind: KeyboardKind, - layout: u32, - keyCount: u32, - functionKeyCount: u32, - maxSimultaneousKeys: u32, - platformType: u32, - platformSubtype: u32, - nativeLanguage: ^String, -} - -KeyState :: struct { - scanCode: u32, - codePoint: u32, - virtualKey: u8, - isDeadKey: bool, -} - -MotionInfo :: struct { - maxAcceleration: f32, - maxAngularVelocity: f32, - maxMagneticFieldStrength: f32, -} - -MotionState :: struct { - accelerationX: f32, - accelerationY: f32, - accelerationZ: f32, - angularVelocityX: f32, - angularVelocityY: f32, - angularVelocityZ: f32, - magneticFieldX: f32, - magneticFieldY: f32, - magneticFieldZ: f32, - orientationW: f32, - orientationX: f32, - orientationY: f32, - orientationZ: f32, - accelerometerAccuracy: MotionAccuracy, - gyroscopeAccuracy: MotionAccuracy, - magnetometerAccuracy: MotionAccuracy, - orientationAccuracy: MotionAccuracy, -} - -MouseInfo :: struct { - supportedButtons: MouseButtons, - sampleRate: u32, - sensorDpi: u32, - hasWheelX: bool, - hasWheelY: bool, -} - -MouseState :: struct { - buttons: MouseButtons, - positionX: i64, - positionY: i64, - wheelX: i64, - wheelY: i64, -} - -RacingWheelInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - previousGearButtonLabel: Label, - nextGearButtonLabel: Label, - dpadUpLabel: Label, - dpadDownLabel: Label, - dpadLeftLabel: Label, - dpadRightLabel: Label, - hasClutch: bool, - hasHandbrake: bool, - hasPatternShifter: bool, - minPatternShifterGear: i32, - maxPatternShifterGear: i32, - maxWheelAngle: f32, -} - -RacingWheelState :: struct { - buttons: RacingWheelButtons, - patternShifterGear: i32, - wheel: f32, - throttle: f32, - brake: f32, - clutch: f32, - handbrake: f32, -} - -RawDeviceItemCollectionInfo :: struct { - kind: RawDeviceItemCollectionKind, - childCount: u32, - siblingCount: u32, - usageCount: u32, - usages: [^]Usage `fmt:v,usageCount`, - parent: ^RawDeviceItemCollectionInfo, - firstSibling: ^RawDeviceItemCollectionInfo, - previousSibling: ^RawDeviceItemCollectionInfo, - nextSibling: ^RawDeviceItemCollectionInfo, - lastSibling: ^RawDeviceItemCollectionInfo, - firstChild: ^RawDeviceItemCollectionInfo, - lastChild: ^RawDeviceItemCollectionInfo, -} - -RawDeviceReportInfo :: struct { - kind: RawDeviceReportKind, - id: u32, - size: u32, - itemCount: u32, - items: [^]RawDeviceReportItemInfo `fmt:"v,itemCount"`, -} - -RawDeviceReportItemInfo :: struct { - bitOffset: u32, - bitSize: u32, - logicalMin: i64, - logicalMax: i64, - physicalMin: f64, - physicalMax: f64, - physicalUnits: RawDevicePhysicalUnitKind, - rawPhysicalUnits: u32, - rawPhysicalUnitsExponent: i32, - flags: RawDeviceReportItemFlags, - usageCount: u32, - usages: [^]Usage `fmt:"v,usageCount"`, - collection: ^RawDeviceItemCollectionInfo, - itemString: ^String, -} - RumbleParams :: struct { lowFrequency: f32, highFrequency: f32, @@ -879,88 +979,6 @@ RumbleParams :: struct { rightTrigger: f32, } -String :: struct { - sizeInBytes: u32, - codePointCount: u32, - data: [^]byte, -} - -TouchSensorInfo :: struct { - mappedInputKinds: Kind, - label: Label, - location: Location, - locationId: u32, - resolutionX: u64, - resolutionY: u64, - shape: TouchShape, - aspectRatio: f32, - orientation: f32, - physicalWidth: f32, - physicalHeight: f32, - maxPressure: f32, - maxProximity: f32, - maxTouchPoints: u32, -} - -TouchState :: struct { - touchId: u64, - sensorIndex: u32, - positionX: f32, - positionY: f32, - pressure: f32, - proximity: f32, - contactRectTop: f32, - contactRectLeft: f32, - contactRectRight: f32, - contactRectBottom: f32, -} - -UiNavigationInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - acceptButtonLabel: Label, - cancelButtonLabel: Label, - upButtonLabel: Label, - downButtonLabel: Label, - leftButtonLabel: Label, - rightButtonLabel: Label, - contextButton1Label: Label, - contextButton2Label: Label, - contextButton3Label: Label, - contextButton4Label: Label, - pageUpButtonLabel: Label, - pageDownButtonLabel: Label, - pageLeftButtonLabel: Label, - pageRightButtonLabel: Label, - scrollUpButtonLabel: Label, - scrollDownButtonLabel: Label, - scrollLeftButtonLabel: Label, - scrollRightButtonLabel: Label, - guideButtonLabel: Label, -} - -UiNavigationState :: struct { - buttons: UiNavigationButtons, -} - -Usage :: struct { - page: u16, - id: u16, -} - -Version :: struct { - major: u16, - minor: u16, - build: u16, - revision: u16, -} - -// COM Interfaces - -IUnknown :: windows.IUnknown -IUnknown_VTable :: windows.IUnknown_VTable -IID :: windows.GUID - IGameInput_UUID_STRING :: "11BE2A7E-4254-445A-9C09-FFC40F006918" IGameInput_UUID := &IID{0x11BE2A7E, 0x4254, 0x445A, {0x9C, 0x09, 0xFF, 0xC4, 0x0F, 0x00, 0x69, 0x18}} IGameInput :: struct #raw_union { @@ -970,139 +988,140 @@ IGameInput :: struct #raw_union { IGameInput_VTable :: struct { using iunknown_vtable: IUnknown_VTable, GetCurrentTimestamp: proc "system" (this: ^IGameInput) -> u64, - GetCurrentReading: proc "system" (this: ^IGameInput, inputKind: Kind, device: ^IGameInputDevice, reading: ^^IGameInputReading) -> HRESULT, - GetNextReading: proc "system" (this: ^IGameInput, referenceReading: ^IGameInputReading, inputKind: Kind, device: ^IGameInputDevice, reading: ^^IGameInputReading) -> HRESULT, - GetPreviousReading: proc "system" (this: ^IGameInput, referenceReading: ^IGameInputReading, inputKind: Kind, device: ^IGameInputDevice, reading: ^^IGameInputReading) -> HRESULT, - GetTemporalReading: proc "system" (this: ^IGameInput, timestamp: u64, device: ^IGameInputDevice, reading: ^^IGameInputReading) -> HRESULT, - RegisterReadingCallback: proc "system" (this: ^IGameInput, device: ^IGameInputDevice, inputKind: Kind, analogThreshold: f32, ctx: rawptr, callbackFunc: ReadingCallback, callbackToken: ^CallbackToken) -> HRESULT, - RegisterDeviceCallback: proc "system" (this: ^IGameInput, device: ^IGameInputDevice, inputKind: Kind, statusFilter: DeviceStatus, enumerationKind: EnumerationKind, ctx: rawptr, callbackFunc: DeviceCallback, callbackToken: ^CallbackToken) -> HRESULT, - RegisterSystemButtonCallback: proc "system" (this: ^IGameInput, device: ^IGameInputDevice, buttonFilter: SystemButtons, ctx: rawptr, callbackFunc: SystemButtonCallback, callbackToken: ^CallbackToken) -> HRESULT, - RegisterKeyboardLayoutCallback: proc "system" (this: ^IGameInput, device: ^IGameInputDevice, ctx: rawptr, callbackFunc: KeyboardLayoutCallback, callbackToken: ^CallbackToken) -> HRESULT, + GetCurrentReading: proc "system" (this: ^IGameInput, inputKind: Kind, device: ^IDevice, reading: ^^IReading) -> HRESULT, + GetNextReading: proc "system" (this: ^IGameInput, referenceReading: ^IReading, inputKind: Kind, device: ^IDevice, reading: ^^IReading) -> HRESULT, + GetPreviousReading: proc "system" (this: ^IGameInput, referenceReading: ^IReading, inputKind: Kind, device: ^IDevice, reading: ^^IReading) -> HRESULT, + GetTemporalReading: proc "system" (this: ^IGameInput, timestamp: u64, device: ^IDevice, reading: ^^IReading) -> HRESULT, + RegisterReadingCallback: proc "system" (this: ^IGameInput, device: ^IDevice, inputKind: Kind, analogThreshold: f32, ctx: rawptr, callbackFunc: ReadingCallback, callbackToken: ^CallbackToken) -> HRESULT, + RegisterDeviceCallback: proc "system" (this: ^IGameInput, device: ^IDevice, inputKind: Kind, statusFilter: DeviceStatus, enumerationKind: EnumerationKind, ctx: rawptr, callbackFunc: DeviceCallback, callbackToken: ^CallbackToken) -> HRESULT, + RegisterSystemButtonCallback: proc "system" (this: ^IGameInput, device: ^IDevice, buttonFilter: SystemButtons, ctx: rawptr, callbackFunc: SystemButtonCallback, callbackToken: ^CallbackToken) -> HRESULT, + RegisterKeyboardLayoutCallback: proc "system" (this: ^IGameInput, device: ^IDevice, ctx: rawptr, callbackFunc: KeyboardLayoutCallback, callbackToken: ^CallbackToken) -> HRESULT, StopCallback: proc "system" (this: ^IGameInput, callbackToken: CallbackToken), UnregisterCallback: proc "system" (this: ^IGameInput, callbackToken: CallbackToken, timeoutInMicroseconds: u64) -> bool, - CreateDispatcher: proc "system" (this: ^IGameInput, dispatcher: ^^IGameInputDispatcher) -> HRESULT, - CreateAggregateDevice: proc "system" (this: ^IGameInput, kind: Kind, device: ^^IGameInputDevice) -> HRESULT, - FindDeviceFromId: proc "system" (this: ^IGameInput, value: ^APP_LOCAL_DEVICE_ID, device: ^^IGameInputDevice) -> HRESULT, - FindDeviceFromObject: proc "system" (this: ^IGameInput, value: ^IUnknown, device: ^^IGameInputDevice) -> HRESULT, - FindDeviceFromPlatformHandle: proc "system" (this: ^IGameInput, value: HANDLE, device: ^^IGameInputDevice) -> HRESULT, - FindDeviceFromPlatformString: proc "system" (this: ^IGameInput, value: windows.LPCWSTR, device: ^^IGameInputDevice) -> HRESULT, + CreateDispatcher: proc "system" (this: ^IGameInput, dispatcher: ^^IDispatcher) -> HRESULT, + CreateAggregateDevice: proc "system" (this: ^IGameInput, kind: Kind, device: ^^IDevice) -> HRESULT, + FindDeviceFromId: proc "system" (this: ^IGameInput, value: ^APP_LOCAL_DEVICE_ID, device: ^^IDevice) -> HRESULT, + FindDeviceFromObject: proc "system" (this: ^IGameInput, value: ^IUnknown, device: ^^IDevice) -> HRESULT, + FindDeviceFromPlatformHandle: proc "system" (this: ^IGameInput, value: HANDLE, device: ^^IDevice) -> HRESULT, + FindDeviceFromPlatformString: proc "system" (this: ^IGameInput, value: win.LPCWSTR, device: ^^IDevice) -> HRESULT, EnableOemDeviceSupport: proc "system" (this: ^IGameInput, vendorId: u16, productId: u16, interfaceNumber: u8, collectionNumber: u8) -> HRESULT, SetFocusPolicy: proc "system" (this: ^IGameInput, policy: FocusPolicy), } -IGameInputReading_UUID_STRING :: "2156947A-E1FA-4DE0-A30B-D812931DBD8D" -IGameInputReading_UUID := &IID{0x2156947A, 0xE1FA, 0x4DE0, {0xA3, 0x0B, 0xD8, 0x12, 0x93, 0x1D, 0x0BD, 0x8D}} -IGameInputReading :: struct #raw_union { +IReading_UUID_STRING :: "2156947A-E1FA-4DE0-A30B-D812931DBD8D" +IReading_UUID := &IID{0x2156947A, 0xE1FA, 0x4DE0, {0xA3, 0x0B, 0xD8, 0x12, 0x93, 0x1D, 0x0BD, 0x8D}} +IReading :: struct #raw_union { #subtype iunknown: IUnknown, - using igameinputreading_vtable: ^IGameInputReading_VTable, + using igameinputreading_vtable: ^IReading_VTable, } -IGameInputReading_VTable :: struct { +IReading_VTable :: struct { using iunknown_vtable: IUnknown_VTable, - GetInputKind: proc "system" (this: ^IGameInputReading) -> Kind, - GetSequenceNumber: proc "system" (this: ^IGameInputReading) -> u64, - GetTimestamp: proc "system" (this: ^IGameInputReading) -> u64, - GetDevice: proc "system" (this: ^IGameInputReading, device: ^^IGameInputDevice), - GetRawReport: proc "system" (this: ^IGameInputReading, report: ^^IGameInputRawDeviceReport) -> bool, - GetControllerAxisCount: proc "system" (this: ^IGameInputReading) -> u32, - GetControllerAxisState: proc "system" (this: ^IGameInputReading, stateArrayCount: u32, stateArray: [^]f32) -> u32, - GetControllerButtonCount: proc "system" (this: ^IGameInputReading) -> u32, - GetControllerButtonState: proc "system" (this: ^IGameInputReading, stateArrayCount: u32, stateArray: [^]bool) -> u32, - GetControllerSwitchCount: proc "system" (this: ^IGameInputReading) -> u32, - GetControllerSwitchState: proc "system" (this: ^IGameInputReading, stateArrayCount: u32, stateArray: [^]SwitchPosition) -> u32, - GetKeyCount: proc "system" (this: ^IGameInputReading) -> u32, - GetKeyState: proc "system" (this: ^IGameInputReading, stateArrayCount: u32, stateArray: [^]KeyState) -> u32, - GetMouseState: proc "system" (this: ^IGameInputReading, state: ^MouseState) -> bool, - GetTouchCount: proc "system" (this: ^IGameInputReading) -> u32, - GetTouchState: proc "system" (this: ^IGameInputReading, stateArrayCount: u32, stateArray: [^]TouchState) -> u32, - GetMotionState: proc "system" (this: ^IGameInputReading, state: ^MotionState) -> bool, - GetArcadeStickState: proc "system" (this: ^IGameInputReading, state: ^ArcadeStickState) -> bool, - GetFlightStickState: proc "system" (this: ^IGameInputReading, state: ^FlightStickState) -> bool, - GetGamepadState: proc "system" (this: ^IGameInputReading, state: ^GamepadState) -> bool, - GetRacingWheelState: proc "system" (this: ^IGameInputReading, state: ^RacingWheelState) -> bool, - GetUiNavigationState: proc "system" (this: ^IGameInputReading, state: ^UiNavigationState) -> bool, + GetInputKind: proc "system" (this: ^IReading) -> Kind, + GetSequenceNumber: proc "system" (this: ^IReading, inputKind: Kind) -> u64, + GetTimestamp: proc "system" (this: ^IReading) -> u64, + GetDevice: proc "system" (this: ^IReading, device: ^^IDevice), + GetRawReport: proc "system" (this: ^IReading, report: ^^IRawDeviceReport) -> bool, + GetControllerAxisCount: proc "system" (this: ^IReading) -> u32, + GetControllerAxisState: proc "system" (this: ^IReading, stateArrayCount: u32, stateArray: [^]f32) -> u32, + GetControllerButtonCount: proc "system" (this: ^IReading) -> u32, + GetControllerButtonState: proc "system" (this: ^IReading, stateArrayCount: u32, stateArray: [^]bool) -> u32, + GetControllerSwitchCount: proc "system" (this: ^IReading) -> u32, + GetControllerSwitchState: proc "system" (this: ^IReading, stateArrayCount: u32, stateArray: [^]SwitchPosition) -> u32, + GetKeyCount: proc "system" (this: ^IReading) -> u32, + GetKeyState: proc "system" (this: ^IReading, stateArrayCount: u32, stateArray: [^]KeyState) -> u32, + GetMouseState: proc "system" (this: ^IReading, state: ^MouseState) -> bool, + GetTouchCount: proc "system" (this: ^IReading) -> u32, + GetTouchState: proc "system" (this: ^IReading, stateArrayCount: u32, stateArray: [^]TouchState) -> u32, + GetMotionState: proc "system" (this: ^IReading, state: ^MotionState) -> bool, + GetArcadeStickState: proc "system" (this: ^IReading, state: ^ArcadeStickState) -> bool, + GetFlightStickState: proc "system" (this: ^IReading, state: ^FlightStickState) -> bool, + GetGamepadState: proc "system" (this: ^IReading, state: ^GamepadState) -> bool, + GetRacingWheelState: proc "system" (this: ^IReading, state: ^RacingWheelState) -> bool, + GetUiNavigationState: proc "system" (this: ^IReading, state: ^UiNavigationState) -> bool, } -IGameInputDevice_UUID_STRING :: "31DD86FB-4C1B-408A-868F-439B3CD47125" -IGameInputDevice_UUID := &IID{0x31DD86FB, 0x4C1B, 0x408A, {0x86, 0x8F, 0x43, 0x9B, 0x3C, 0xD4, 0x71, 0x25}} -IGameInputDevice :: struct #raw_union { +IDevice_UUID_STRING :: "31DD86FB-4C1B-408A-868F-439B3CD47125" +IDevice_UUID := &IID{0x31DD86FB, 0x4C1B, 0x408A, {0x86, 0x8F, 0x43, 0x9B, 0x3C, 0xD4, 0x71, 0x25}} +IDevice :: struct #raw_union { #subtype iunknown: IUnknown, - using igameinputdevice_vtable: ^IGameInputDevice_Vtable, + using igameinputdevice_vtable: ^IDevice_Vtable, } -IGameInputDevice_Vtable :: struct { +IDevice_Vtable :: struct { using iunknown_vtable: IUnknown_VTable, - GetDeviceInfo: proc "system" (this: ^IGameInputDevice) -> ^DeviceInfo, - GetDeviceStatus: proc "system" (this: ^IGameInputDevice) -> DeviceStatus, - GetBatteryState: proc "system" (this: ^IGameInputDevice, state: ^BatteryState), - CreateForceFeedbackEffect: proc "system" (this: ^IGameInputDevice, motorIndex: u32, params: ^ForceFeedbackParams, effect: ^^IGameInputForceFeedbackEffect) -> HRESULT, - IsForceFeedbackMotorPoweredOn: proc "system" (this: ^IGameInputDevice, motorIndex: u32) -> bool, - SetForceFeedbackMotorGain: proc "system" (this: ^IGameInputDevice, motorIndex: u32, masterGain: f32), - SetHapticMotorState: proc "system" (this: ^IGameInputDevice, motorIndex: u32, params: ^HapticFeedbackParams) -> HRESULT, - SetRumbleState: proc "system" (this: ^IGameInputDevice, params: ^RumbleParams), - SetInputSynchronizationState: proc "system" (this: ^IGameInputDevice, enabled: bool), - SendInputSynchronizationHint: proc "system" (this: ^IGameInputDevice), - PowerOff: proc "system" (this: ^IGameInputDevice), - CreateRawDeviceReport: proc "system" (this: ^IGameInputDevice, reportId: u32, reportKind: RawDeviceReportKind, report: ^^IGameInputRawDeviceReport) -> HRESULT, - GetRawDeviceFeature: proc "system" (this: ^IGameInputDevice, reportId: u32, report: ^^IGameInputRawDeviceReport) -> HRESULT, - SetRawDeviceFeature: proc "system" (this: ^IGameInputDevice, report: ^IGameInputRawDeviceReport) -> HRESULT, - SendRawDeviceOutput: proc "system" (this: ^IGameInputDevice, report: ^IGameInputRawDeviceReport) -> HRESULT, - SendRawDeviceOutputWithResponse: proc "system" (this: ^IGameInputDevice, requestReport: ^IGameInputRawDeviceReport, responseReport: ^^IGameInputRawDeviceReport) -> HRESULT, - ExecuteRawDeviceIoControl: proc "system" (this: ^IGameInputDevice, controlCode: u32, inputBufferSize: c.size_t, inputBuffer: rawptr, outputBufferSize: c.size_t, outputBuffer: rawptr, outputSize: ^c.size_t) -> HRESULT, - AcquireExclusiveRawDeviceAccess: proc "system" (this: ^IGameInputDevice, timeoutInMicroseconds: u64) -> bool, - ReleaseExclusiveRawDeviceAccess: proc "system" (this: ^IGameInputDevice), + GetDeviceInfo: proc "system" (this: ^IDevice) -> ^DeviceInfo, + GetDeviceStatus: proc "system" (this: ^IDevice) -> DeviceStatus, + GetBatteryState: proc "system" (this: ^IDevice, state: ^BatteryState), + CreateForceFeedbackEffect: proc "system" (this: ^IDevice, motorIndex: u32, params: ^ForceFeedbackParams, effect: ^^IForceFeedbackEffect) -> HRESULT, + IsForceFeedbackMotorPoweredOn: proc "system" (this: ^IDevice, motorIndex: u32) -> bool, + SetForceFeedbackMotorGain: proc "system" (this: ^IDevice, motorIndex: u32, masterGain: f32), + SetHapticMotorState: proc "system" (this: ^IDevice, motorIndex: u32, params: ^HapticFeedbackParams) -> HRESULT, + SetRumbleState: proc "system" (this: ^IDevice, params: ^RumbleParams), + SetInputSynchronizationState: proc "system" (this: ^IDevice, enabled: bool), + SendInputSynchronizationHint: proc "system" (this: ^IDevice), + PowerOff: proc "system" (this: ^IDevice), + CreateRawDeviceReport: proc "system" (this: ^IDevice, reportId: u32, reportKind: RawDeviceReportKind, report: ^^IRawDeviceReport) -> HRESULT, + GetRawDeviceFeature: proc "system" (this: ^IDevice, reportId: u32, report: ^^IRawDeviceReport) -> HRESULT, + SetRawDeviceFeature: proc "system" (this: ^IDevice, report: ^IRawDeviceReport) -> HRESULT, + SendRawDeviceOutput: proc "system" (this: ^IDevice, report: ^IRawDeviceReport) -> HRESULT, + SendRawDeviceOutputWithResponse: proc "system" (this: ^IDevice, requestReport: ^IRawDeviceReport, responseReport: ^^IRawDeviceReport) -> HRESULT, + ExecuteRawDeviceIoControl: proc "system" (this: ^IDevice, controlCode: u32, inputBufferSize: win.SIZE_T, inputBuffer: rawptr, outputBufferSize: win.SIZE_T, outputBuffer: rawptr, outputSize: ^win.SIZE_T) -> HRESULT, + AcquireExclusiveRawDeviceAccess: proc "system" (this: ^IDevice, timeoutInMicroseconds: u64) -> bool, + ReleaseExclusiveRawDeviceAccess: proc "system" (this: ^IDevice), } -IGameInputDispatcher_UUID_STRING :: "415EED2E-98CB-42C2-8F28-B94601074E31" -IGameInputDispatcher_UUID := &IID{0x415EED2E, 0x98CB, 0x42C2, {0x8F, 0x28, 0xB9, 0x46, 0x01, 0x07, 0x4E, 0x31}} -IGameInputDispatcher :: struct #raw_union { +IDispatcher_UUID_STRING :: "415EED2E-98CB-42C2-8F28-B94601074E31" +IDispatcher_UUID := &IID{0x415EED2E, 0x98CB, 0x42C2, {0x8F, 0x28, 0xB9, 0x46, 0x01, 0x07, 0x4E, 0x31}} +IDispatcher :: struct #raw_union { #subtype iunknown: IUnknown, - using igameinputdispatcher_vtable: ^IGameInputDispatcher_Vtable, + using igameinputdispatcher_vtable: ^IDispatcher_Vtable, } -IGameInputDispatcher_Vtable :: struct { +IDispatcher_Vtable :: struct { using iunknown_vtable: IUnknown_VTable, - Dispatch: proc "system" (this: ^IGameInputDispatcher, quotaInMicroseconds: u64) -> bool, - OpenWaitHandle: proc "system" (this: ^IGameInputDispatcher, waitHandle: ^HANDLE) -> HRESULT, + Dispatch: proc "system" (this: ^IDispatcher, quotaInMicroseconds: u64) -> bool, + OpenWaitHandle: proc "system" (this: ^IDispatcher, waitHandle: ^HANDLE) -> HRESULT, } -IGameInputForceFeedbackEffect_UUID_STRING :: "51BDA05E-F742-45D9-B085-9444AE48381D" -IGameInputForceFeedbackEffect_UUID := &IID{0x51BDA05E, 0xF742, 0x45D9, {0xB0, 0x85, 0x94, 0x44, 0xAE, 0x48, 0x38, 0x1D}} -IGameInputForceFeedbackEffect :: struct #raw_union { +IForceFeedbackEffect_UUID_STRING :: "51BDA05E-F742-45D9-B085-9444AE48381D" +IForceFeedbackEffect_UUID := &IID{0x51BDA05E, 0xF742, 0x45D9, {0xB0, 0x85, 0x94, 0x44, 0xAE, 0x48, 0x38, 0x1D}} +IForceFeedbackEffect :: struct #raw_union { #subtype iunknown: IUnknown, - using igameinputforcefeedbackeffect_vtable: ^IGameInputForceFeedbackEffect_Vtable, + using igameinputforcefeedbackeffect_vtable: ^IForceFeedbackEffect_Vtable, } -IGameInputForceFeedbackEffect_Vtable :: struct { +IForceFeedbackEffect_Vtable :: struct { using iunknown_vtable: IUnknown_VTable, - GetDevice: proc "system" (this: ^IGameInputForceFeedbackEffect, device: ^^IGameInputDevice), - GetMotorIndex: proc "system" (this: ^IGameInputForceFeedbackEffect) -> u32, - GetGain: proc "system" (this: ^IGameInputForceFeedbackEffect) -> f32, - SetGain: proc "system" (this: ^IGameInputForceFeedbackEffect, gain: f32), - GetParams: proc "system" (this: ^IGameInputForceFeedbackEffect, params: ^ForceFeedbackParams), - SetParams: proc "system" (this: ^IGameInputForceFeedbackEffect, params: ^ForceFeedbackParams) -> bool, - GetState: proc "system" (this: ^IGameInputForceFeedbackEffect) -> FeedbackEffectState, - SetState: proc "system" (this: ^IGameInputForceFeedbackEffect, state: FeedbackEffectState), + GetDevice: proc "system" (this: ^IForceFeedbackEffect, device: ^^IDevice), + GetMotorIndex: proc "system" (this: ^IForceFeedbackEffect) -> u32, + GetGain: proc "system" (this: ^IForceFeedbackEffect) -> f32, + SetGain: proc "system" (this: ^IForceFeedbackEffect, gain: f32), + GetParams: proc "system" (this: ^IForceFeedbackEffect, params: ^ForceFeedbackParams), + SetParams: proc "system" (this: ^IForceFeedbackEffect, params: ^ForceFeedbackParams) -> bool, + GetState: proc "system" (this: ^IForceFeedbackEffect) -> FeedbackEffectState, + SetState: proc "system" (this: ^IForceFeedbackEffect, state: FeedbackEffectState), } -IGameInputRawDeviceReport_UUID_STRING :: "61F08CF1-1FFC-40CA-A2B8-E1AB8BC5B6DC" -IGameInputRawDeviceReport_UUID := &IID{0x61F08CF1, 0x1FFC, 0x40CA, {0xA2, 0xB8, 0xE1, 0xAB, 0x8B, 0xC5, 0xB6, 0xDC}} -IGameInputRawDeviceReport :: struct #raw_union { +IRawDeviceReport_UUID_STRING :: "61F08CF1-1FFC-40CA-A2B8-E1AB8BC5B6DC" +IRawDeviceReport_UUID := &IID{0x61F08CF1, 0x1FFC, 0x40CA, {0xA2, 0xB8, 0xE1, 0xAB, 0x8B, 0xC5, 0xB6, 0xDC}} +IRawDeviceReport :: struct #raw_union { #subtype iunknown: IUnknown, - using igameinputrawdevicereport_vtable: ^IGameInputRawDeviceReport_Vtable, + using igameinputrawdevicereport_vtable: ^IRawDeviceReport_Vtable, } -IGameInputRawDeviceReport_Vtable :: struct { +IRawDeviceReport_Vtable :: struct { using iunknown_vtable: IUnknown_VTable, - GetDevice: proc "system" (this: ^IGameInputRawDeviceReport, device: ^^IGameInputDevice), - GetReportInfo: proc "system" (this: ^IGameInputRawDeviceReport) -> ^RawDeviceReportInfo, - GetRawDataSize: proc "system" (this: ^IGameInputRawDeviceReport) -> c.size_t, - GetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: c.size_t, buffer: rawptr) -> c.size_t, - SetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: c.size_t, buffer: rawptr) -> bool, - GetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32, value: ^u64) -> bool, - SetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32, value: u64) -> bool, - ResetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32) -> bool, - ResetAllItems: proc "system" (this: ^IGameInputRawDeviceReport) -> bool, + GetDevice: proc "system" (this: ^IRawDeviceReport, device: ^^IDevice), + GetReportInfo: proc "system" (this: ^IRawDeviceReport) -> ^RawDeviceReportInfo, + GetRawDataSize: proc "system" (this: ^IRawDeviceReport) -> win.SIZE_T, + GetRawData: proc "system" (this: ^IRawDeviceReport, bufferSize: win.SIZE_T, buffer: rawptr) -> win.SIZE_T, + SetRawData: proc "system" (this: ^IRawDeviceReport, bufferSize: win.SIZE_T, buffer: rawptr) -> bool, + GetItemValue: proc "system" (this: ^IRawDeviceReport, itemIndex: u32, value: ^u64) -> bool, + SetItemValue: proc "system" (this: ^IRawDeviceReport, itemIndex: u32, value: u64) -> bool, + ResetItemValue: proc "system" (this: ^IRawDeviceReport, itemIndex: u32) -> bool, + ResetAllItems: proc "system" (this: ^IRawDeviceReport) -> bool, } -// Functions -HRESULT :: windows.HRESULT -HANDLE :: windows.HANDLE +@(default_calling_convention="system", link_prefix="GameInput") +foreign wgi { + Create :: proc(gameInput: ^^IGameInput) -> HRESULT --- +} DEVICE_DISCONNECTED :: HRESULT(-0x7C75FFFF) DEVICE_NOT_FOUND :: HRESULT(-0x7C75FFFE) @@ -1110,20 +1129,3 @@ READING_NOT_FOUND :: HRESULT(-0x7C75FFFD) REFERENCE_READING_TOO_OLD :: HRESULT(-0x7C75FFFC) TIMESTAMP_OUT_OF_RANGE :: HRESULT(-0x7C75FFFB) INSUFFICIENT_FORCE_FEEDBACK_RESOURCES :: HRESULT(-0x7C75FFFA) - -CallbackToken :: distinct u64 - -CURRENT_CALLBACK_TOKEN_VALUE :: CallbackToken(0xFFFFFFFFFFFFFFFF) -INVALID_CALLBACK_TOKEN_VALUE :: CallbackToken(0x0000000000000000) - -@(default_calling_convention="system", link_prefix="GameInput") -foreign wgi { - Create :: proc(gameInput: ^^IGameInput) -> HRESULT --- -} - -DeviceCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) -GuideButtonCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, isPressed: bool) -SystemButtonCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) -ReadingCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, reading: ^IGameInputReading, hasOverrunOccured: bool) -KeyboardLayoutCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) - diff --git a/vendor/windows/XAudio2/doc.odin b/vendor/windows/XAudio2/doc.odin new file mode 100644 index 000000000..84ab08c39 --- /dev/null +++ b/vendor/windows/XAudio2/doc.odin @@ -0,0 +1,6 @@ +/* + Bindings for [[ Windows XAudio2 ; https://learn.microsoft.com/en-us/windows/win32/xaudio2/xaudio2-introduction ]]. + + Compiling for Windows 10 RS5 (1809) and later +*/ +package windows_xaudio2 \ No newline at end of file diff --git a/vendor/windows/XAudio2/hrtfapoapi.odin b/vendor/windows/XAudio2/hrtfapoapi.odin new file mode 100644 index 000000000..45f1cdb42 --- /dev/null +++ b/vendor/windows/XAudio2/hrtfapoapi.odin @@ -0,0 +1,149 @@ +#+build windows + +package windows_xaudio2 + +import win "core:sys/windows" + +foreign import hrtf "system:hrtfapo.lib" + +HRTF_MAX_GAIN_LIMIT :: 12.0 +HRTF_MIN_GAIN_LIMIT :: -96.0 +HRTF_MIN_UNITY_GAIN_DISTANCE :: 0.05 +HRTF_DEFAULT_UNITY_GAIN_DISTANCE :: 1.0 +HRTF_DEFAULT_CUTOFF_DISTANCE :: 3.402823466e+38 + +//! Represents a position in 3D space, using a right-handed coordinate system. +HrtfPosition :: struct { + x: f32, + y: f32, + z: f32, +} + +//! Indicates the orientation of an HRTF directivity object. This is a row-major 3x3 rotation matrix. +HrtfOrientation :: struct { + element: [9]f32, +} + +//! Indicates one of several stock directivity patterns. +HrtfDirectivityType :: enum i32 { + //! The sound emission is in all directions. + OmniDirectional = 0, + //! The sound emission is a cardiod shape. + Cardioid, + //! The sound emission is a cone. + Cone, +} + +//! Indicates one of several stock environment types. +HrtfEnvironment :: enum i32 { + //! A small room. + Small = 0, + //! A medium-sized room. + Medium, + //! A large enclosed space. + Large, + //! An outdoor space. + Outdoors, +} + +//! Base directivity pattern descriptor. Describes the type of directivity applied to a sound. +//! The scaling parameter is used to interpolate between directivity behavior and omnidirectional, it determines how much attenuation is applied to the source outside of the directivity pattern and controls how directional the source is. +HrtfDirectivity :: struct { + //! Indicates the type of directivity. + type: HrtfDirectivityType, + //! A normalized value between zero and one. Specifies the amount of linear interpolation between omnidirectional sound and the full directivity pattern, where 0 is fully omnidirectional and 1 is fully directional. + scaling: f32, +} + +//! Describes a cardioid directivity pattern. +HrtfDirectivityCardioid :: struct { + //! Descriptor for the cardioid pattern. The type parameter must be set to HrtfDirectivityType.Cardioid. + directivity: HrtfDirectivity, + //! Order controls the shape of the cardioid. The higher order the shape, the narrower it is. Must be greater than 0 and less than or equal to 32. + order: f32, +} + +//! Describes a cone directivity. +//! Attenuation is 0 inside the inner cone. +//! Attenuation is linearly interpolated between the inner cone, which is defined by innerAngle, and the outer cone, which is defined by outerAngle. +HrtfDirectivityCone :: struct { + //! Descriptor for the cone pattern. The type parameter must be set to HrtfDirectivityType.Cone. + directivity: HrtfDirectivity, + //! Angle, in radians, that defines the inner cone. Must be between 0 and TAU. + innerAngle: f32, + //! Angle, in radians, that defines the outer cone. Must be between 0 and TAU. + outerAngle: f32, +} + +//! Indicates a distance-based decay type applied to a sound. +HrtfDistanceDecayType :: enum i32 { + //! Simulates natural decay with distance, as constrained by minimum and maximum gain distance limits. Drops to silence at rolloff distance. + NaturalDecay = 0, + //! Used to set up a custom gain curve, within the maximum and minimum gain limit. + CustomDecay, +} + +//! Describes a distance-based decay behavior. +HrtfDistanceDecay :: struct { + //! The type of decay behavior, natural or custom. + type: HrtfDistanceDecayType, + //! The maximum gain limit applied at any distance. Applies to both natural and custom decay. This value is specified in dB, with a range from -96 to 12 inclusive. The default value is 12 dB. + maxGain: f32, + //! The minimum gain limit applied at any distance. Applies to both natural and custom decay. This value is specified in dB, with a range from -96 to 12 inclusive. The default value is -96 dB. + minGain: f32, + //! The distance at which the gain is 0dB. Applies to natural decay only. This value is specified in meters, with a range from 0.05 to infinity (max(f32)). The default value is 1 meter. + unityGainDistance: f32, + //! The distance at which output is silent. Applies to natural decay only. This value is specified in meters, with a range from zero (non-inclusive) to infinity (max(f32)). The default value is infinity. + cutoffDistance: f32, +} + +//! Specifies parameters used to initialize HRTF. +//! Instances of the XAPO interface are created by using the CreateHrtfApo() API: +//! ```CreateHrtfApo :: proc(pInit: HrtfApoInit, ppXapo: ^^IXAPO) -> HRESULT``` +HrtfApoInit :: struct { + //! The decay type. If you pass in nil, the default value will be used. The default is natural decay. + distanceDecay: ^HrtfDistanceDecay, + //! The directivity type. If you pass in nil, the default value will be used. The default directivity is omni-directional. + directivity: ^HrtfDirectivity, +} + +//! Creates an instance of the XAPO object. +//! Format requirements: +//! * Input: mono, 48 kHz, 32-bit float PCM. +//! * Output: stereo, 48 kHz, 32-bit float PCM. +//! Audio is processed in blocks of 1024 samples. +//! Returns: +//! S_OK for success, any other value indicates failure. +//! Returns E_NOTIMPL on unsupported platforms. +@(default_calling_convention="system") +foreign hrtf { + CreateHrtfApo :: proc( + //! Pointer to an HrtfApoInit struct. Specifies parameters for XAPO interface initialization. + #by_ptr init: HrtfApoInit, + //! Returns the new instance of the XAPO interface. + xApo: ^^IXAPO, + ) -> HRESULT --- +} + +//! The interface used to set parameters that control how HRTF is applied to a sound. +IXAPOHrtfParameters_UUID_STRING :: "15B3CD66-E9DE-4464-B6E6-2BC3CF63D455" +IXAPOHrtfParameters_UUID := &win.IID{0x15B3CD66, 0xE9DE, 0x4464, {0xB6, 0xE6, 0x2B, 0xC3, 0xCF, 0x63, 0xD4, 0x55}} +IXAPOHrtfParameters :: struct #raw_union { + #subtype iunknown: IUnknown, + using ixapohrtfparameters_vtable: ^IXAPOHrtfParameters_VTable, +} +IXAPOHrtfParameters_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + + // HRTF params + //! The position of the sound relative to the listener. + SetSourcePosition: proc "system" (this: ^IXAPOHrtfParameters, position: ^HrtfPosition) -> HRESULT, + //! The rotation matrix for the source orientation, with respect to the listener's frame of reference (the listener's coordinate system). + SetSourceOrientation: proc "system" (this: ^IXAPOHrtfParameters, orientation: ^HrtfOrientation) -> HRESULT, + //! The custom direct path gain value for the current source position. Valid only for sounds played with the HrtfDistanceDecayType. Custom decay type. + SetSourceGain: proc "system" (this: ^IXAPOHrtfParameters, gain: f32) -> HRESULT, + + // Distance cue params + //! Selects the acoustic environment to simulate. + SetEnvironment: proc "system" (this: ^IXAPOHrtfParameters, environment: HrtfEnvironment) -> HRESULT, +} diff --git a/vendor/windows/XAudio2/x3daudio.odin b/vendor/windows/XAudio2/x3daudio.odin index 27c4dc9fa..c24e627e2 100644 --- a/vendor/windows/XAudio2/x3daudio.odin +++ b/vendor/windows/XAudio2/x3daudio.odin @@ -1,7 +1,7 @@ #+build windows /* NOTES: - 1. Definition of terms: + 1. Definition of terms: LFE: Low Frequency Effect -- always omnidirectional. LPF: Low Pass Filter, divided into two classifications: Direct -- Applied to the direct signal path, @@ -9,15 +9,15 @@ Reverb -- Applied to the reverb signal path, used for occlusion effects only. - 2. Volume level is expressed as a linear amplitude scaler: - 1.0f represents no attenuation applied to the original signal, - 0.5f denotes an attenuation of 6dB, and 0.0f results in silence. - Amplification (volume > 1.0f) is also allowed, and is not clamped. + 2. Volume level is expressed as a linear amplitude scaler: + 1.0 represents no attenuation applied to the original signal, + 0.5 denotes an attenuation of 6dB, and 0.0 results in silence. + Amplification (volume > 1.0) is also allowed, and is not clamped. - LPF values range from 1.0f representing all frequencies pass through, - to 0.0f which results in silence as all frequencies are filtered out. + LPF values range from 1.0 representing all frequencies pass through, + to 0.0 which results in silence as all frequencies are filtered out. - 3. X3DAudio uses a left-handed Cartesian coordinate system with values + 3. X3DAudio uses a left-handed Cartesian coordinate system with values on the x-axis increasing from left to right, on the y-axis from bottom to top, and on the z-axis from near to far. Azimuths are measured clockwise from a given reference direction. @@ -29,7 +29,7 @@ Metric constants are supplied only as a convenience. Distance is calculated using the Euclidean norm formula. - 4. Only real values are permissible with functions using 32-bit + 4. Only real values are permissible with functions using 32-bit float parameters -- NAN and infinite values are not accepted. All computation occurs in 32-bit precision mode. */ @@ -37,34 +37,13 @@ package windows_xaudio2 import "core:math" +import win "core:sys/windows" foreign import xa2 "system:xaudio2.lib" +SPEAKER_FLAGS :: win.SPEAKER_FLAGS + //---------------------------------------------------// -// speaker geometry configuration flags, specifies assignment of channels to speaker positions, defined as per WAVEFORMATEXTENSIBLE.dwChannelMask -SPEAKER_FLAGS :: distinct bit_set[SPEAKER_FLAG; u32] -SPEAKER_FLAG :: enum u32 { - FRONT_LEFT = 0, - FRONT_RIGHT = 1, - FRONT_CENTER = 2, - LOW_FREQUENCY = 3, - BACK_LEFT = 4, - BACK_RIGHT = 5, - FRONT_LEFT_OF_CENTER = 6, - FRONT_RIGHT_OF_CENTER = 7, - BACK_CENTER = 8, - SIDE_LEFT = 9, - SIDE_RIGHT = 10, - TOP_CENTER = 11, - TOP_FRONT_LEFT = 12, - TOP_FRONT_CENTER = 13, - TOP_FRONT_RIGHT = 14, - TOP_BACK_LEFT = 15, - TOP_BACK_CENTER = 16, - TOP_BACK_RIGHT = 17, - //RESERVED = 0x7FFC0000, // bit mask locations reserved for future use - ALL = 31, // used to specify that any possible permutation of speaker configurations -} // standard speaker geometry configurations, used with Initialize SPEAKER_MONO :: SPEAKER_FLAGS{.FRONT_CENTER} @@ -100,7 +79,7 @@ CALCULATE_FLAG :: enum u32 { } //-----------------------------------------------------// -VECTOR :: [3]f32 // float 3D vector +VECTOR :: distinct [3]f32 // float 3D vector // instance handle of precalculated constants HANDLE :: distinct [HANDLE_BYTESIZE]byte @@ -108,75 +87,74 @@ HANDLE :: distinct [HANDLE_BYTESIZE]byte // Distance curve point: // Defines a DSP setting at a given normalized distance. DISTANCE_CURVE_POINT :: struct #packed { - Distance: f32, // normalized distance, must be within [0.0f, 1.0f] + Distance: f32, // normalized distance, must be within [0.0, 1.0] DSPSetting: f32, // DSP setting } // Distance curve: // A piecewise curve made up of linear segments used to define DSP behaviour with respect to normalized distance. // -// Note that curve point distances are normalized within [0.0f, 1.0f]. +// Note that curve point distances are normalized within [0.0, 1.0]. // EMITTER.CurveDistanceScaler must be used to scale the normalized distances to user-defined world units. -// For distances beyond CurveDistanceScaler * 1.0f, pPoints[PointCount-1].DSPSetting is used as the DSP setting. +// For distances beyond CurveDistanceScaler * 1.0, pPoints[PointCount-1].DSPSetting is used as the DSP setting. // // All distance curve spans must be such that: // pPoints[k-1].DSPSetting + ((pPoints[k].DSPSetting-pPoints[k-1].DSPSetting) / (pPoints[k].Distance-pPoints[k-1].Distance)) * (pPoints[k].Distance-pPoints[k-1].Distance) != NAN or infinite values // For all points in the distance curve where 1 <= k < PointCount. DISTANCE_CURVE :: struct #packed { - pPoints: [^]DISTANCE_CURVE_POINT `fmt:"v,PointCount"`, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance - PointCount: u32, // number of distance curve points, must be >= 2 as all distance curves must have at least two endpoints, defining DSP settings at 0.0f and 1.0f normalized distance + pPoints: [^]DISTANCE_CURVE_POINT `fmt:"v,PointCount"`, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance + PointCount: u32, // number of distance curve points, must be >= 2 as all distance curves must have at least two endpoints, defining DSP settings at 0.0 and 1.0 normalized distance } Default_LinearCurvePoints := [2]DISTANCE_CURVE_POINT{{0.0, 1.0}, {1.0, 0.0}} Default_LinearCurve := DISTANCE_CURVE{&Default_LinearCurvePoints[0], 2} +// Cone: +// Specifies directionality for a listener or single-channel emitter by modifying DSP behaviour with respect to its front orientation. +// This is modeled using two sound cones: an inner cone and an outer cone. On/within the inner cone, DSP settings are scaled by the inner values. +// On/beyond the outer cone, DSP settings are scaled by the outer values. If on both the cones, DSP settings are scaled by the inner values only. +// Between the two cones, the scaler is linearly interpolated between the inner and outer values. Set both cone angles to 0 or TAU for omnidirectionality using only the outer or inner values respectively. CONE :: struct #packed { - InnerAngle: f32, // inner cone angle in radians, must be within [0.0f, TAU] - OuterAngle: f32, // outer cone angle in radians, must be within [InnerAngle, TAU] + InnerAngle: f32, // inner cone angle in radians, must be within [0.0, TAU] + OuterAngle: f32, // outer cone angle in radians, must be within [InnerAngle, TAU] - InnerVolume: f32, // volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used - OuterVolume: f32, // volume level scaler on/beyond outer cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used - InnerLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/within inner cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used - OuterLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/beyond outer cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used - InnerReverb: f32, // reverb send level scaler on/within inner cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used - OuterReverb: f32, // reverb send level scaler on/beyond outer cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used + InnerVolume: f32, // volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0, 2.0] when used + OuterVolume: f32, // volume level scaler on/beyond outer cone, used only for matrix calculations, must be within [0.0, 2.0] when used + InnerLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/within inner cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0, 1.0] when used + OuterLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/beyond outer cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0, 1.0] when used + InnerReverb: f32, // reverb send level scaler on/within inner cone, used only for reverb calculations, must be within [0.0, 2.0] when used + OuterReverb: f32, // reverb send level scaler on/beyond outer cone, used only for reverb calculations, must be within [0.0, 2.0] when used } Default_DirectionalCone := CONE{math.PI / 2, math.PI, 1.0, 0.708, 0.0, 0.25, 0.708, 1.0} // Listener: // Defines a point of 3D audio reception. -// // The cone is directed by the listener's front orientation. LISTENER :: struct #packed { - OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used - OrientTop: VECTOR, // orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used + OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used + OrientTop: VECTOR, // orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used - Position: VECTOR, // position in user-defined world units, does not affect Velocity - Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position + Position: VECTOR, // position in user-defined world units, does not affect Velocity + Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position - pCone: ^CONE, // sound cone, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality + pCone: ^CONE, // sound cone, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, nil specifies omnidirectionality } // Emitter: // Defines a 3D audio source, divided into two classifications: -// // Single-point -- For use with single-channel sounds. // Positioned at the emitter base, i.e. the channel radius and azimuth are ignored if the number of channels == 1. -// // May be omnidirectional or directional using a cone. // The cone originates from the emitter base position, and is directed by the emitter's front orientation. -// // Multi-point -- For use with multi-channel sounds. // Each non-LFE channel is positioned using an azimuth along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector. // An azimuth of TAU specifies a channel is an LFE. Such channels are positioned at the emitter base and are calculated with respect to pLFECurve only, never pVolumeCurve. -// // Multi-point emitters are always omnidirectional, i.e. the cone is ignored if the number of channels > 1. -// // Note that many properties are shared among all channel points, locking certain behaviour with respect to the emitter base position. // For example, doppler shift is always calculated with respect to the emitter base position and so is constant for all its channel points. // Distance curve calculations are also with respect to the emitter base position, with the curves being calculated independently of each other. // For instance, volume and LFE calculations do not affect one another. EMITTER :: struct #packed { - pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality + pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, nil specifies omnidirectionality OrientFront: VECTOR, // orientation of front direction, used only for emitter angle calculations or with multi-channel emitters for matrix calculations or single-channel emitters with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used OrientTop: VECTOR, // orientation of top direction, used only with multi-channel emitters for matrix calculations, must be orthonormal with OrientFront when used @@ -184,26 +162,25 @@ EMITTER :: struct #packed { Position: VECTOR, // position in user-defined world units, does not affect Velocity Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position - InnerRadius: f32, // inner radius, must be within [0.0f, max(f32)] - InnerRadiusAngle: f32, // inner radius angle, must be within [0.0f, PI/4.0) + InnerRadius: f32, // inner radius, must be within [0.0, max(f32)] + InnerRadiusAngle: f32, // inner radius angle, must be within [0.0, PI/4.0) - ChannelCount: u32, // number of sound channels, must be > 0 - ChannelRadius: f32, // channel radius, used only with multi-channel emitters for matrix calculations, must be >= 0.0f when used - pChannelAzimuths: [^]f32 `fmt:"v,ChannelCount"`, // channel azimuth array, used only with multi-channel emitters for matrix calculations, contains positions of each channel expressed in radians along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector, or TAU to specify an LFE channel, must have at least ChannelCount elements, all within [0.0f, TAU] when used + ChannelCount: u32, // number of sound channels, must be > 0 + ChannelRadius: f32, // channel radius, used only with multi-channel emitters for matrix calculations, must be >= 0.0 when used + pChannelAzimuths: [^]f32 `fmt:"v,ChannelCount"`, // channel azimuth array, used only with multi-channel emitters for matrix calculations, contains positions of each channel expressed in radians along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector, or TAU to specify an LFE channel, must have at least ChannelCount elements, all within [0.0, TAU] when used - pVolumeCurve: ^DISTANCE_CURVE, // volume level distance curve, used only for matrix calculations, NULL specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation - pLFECurve: ^DISTANCE_CURVE, // LFE level distance curve, used only for matrix calculations, NULL specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation - pLPFDirectCurve: ^DISTANCE_CURVE, // LPF direct-path coefficient distance curve, used only for LPF direct-path calculations, NULL specifies the default curve: [0.0f,1.0f], [1.0f,0.75f] - pLPFReverbCurve: ^DISTANCE_CURVE, // LPF reverb-path coefficient distance curve, used only for LPF reverb-path calculations, NULL specifies the default curve: [0.0f,0.75f], [1.0f,0.75f] - pReverbCurve: ^DISTANCE_CURVE, // reverb send level distance curve, used only for reverb calculations, NULL specifies the default curve: [0.0f,1.0f], [1.0f,0.0f] + pVolumeCurve: ^DISTANCE_CURVE, // volume level distance curve, used only for matrix calculations, nil specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation + pLFECurve: ^DISTANCE_CURVE, // LFE level distance curve, used only for matrix calculations, nil specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation + pLPFDirectCurve: ^DISTANCE_CURVE, // LPF direct-path coefficient distance curve, used only for LPF direct-path calculations, nil specifies the default curve: [0.0,1.0], [1.0,0.75] + pLPFReverbCurve: ^DISTANCE_CURVE, // LPF reverb-path coefficient distance curve, used only for LPF reverb-path calculations, nil specifies the default curve: [0.0,0.75], [1.0,0.75] + pReverbCurve: ^DISTANCE_CURVE, // reverb send level distance curve, used only for reverb calculations, nil specifies the default curve: [0.0,1.0], [1.0,0.0] CurveDistanceScaler: f32, // curve distance scaler, used to scale normalized distance curves to user-defined world units and/or exaggerate their effect, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, must be within [min(f32), max(f32)] when used - DopplerScaler: f32, // doppler shift scaler, used to exaggerate doppler shift effect, used only for doppler calculations, must be within [0.0f, max(f32)] when used + DopplerScaler: f32, // doppler shift scaler, used to exaggerate doppler shift effect, used only for doppler calculations, must be within [0.0, max(f32)] when used } // DSP settings: // Receives results from a call to Calculate to be sent to the low-level audio rendering API for 3D signal processing. -// // The user is responsible for allocating the matrix coefficient table, delay time array, and initializing the channel counts when used. DSP_SETTINGS :: struct #packed { pMatrixCoefficients: [^]f32, // [inout] matrix coefficient table, receives an array representing the volume level used to send from source channel S to destination channel D, stored as pMatrixCoefficients[SrcChannelCount * D + S], must have at least SrcChannelCount*DstChannelCount elements diff --git a/vendor/windows/XAudio2/xapo.odin b/vendor/windows/XAudio2/xapo.odin index 54fb420ca..510eeb514 100644 --- a/vendor/windows/XAudio2/xapo.odin +++ b/vendor/windows/XAudio2/xapo.odin @@ -1,75 +1,45 @@ #+build windows /* NOTES: - 1. Definition of terms: + 1. Definition of terms: DSP: Digital Signal Processing. - CBR: Constant BitRate -- DSP that consumes a constant number of - input samples to produce an output sample. - For example, a 22kHz to 44kHz resampler is CBR DSP. - Even though the number of input to output samples differ, - the ratio between input to output rate remains constant. - All user-defined XAPOs are assumed to be CBR as - XAudio2 only allows CBR DSP to be added to an effect chain. + CBR: Constant BitRate -- DSP that consumes a constant number of input samples to produce an output sample. + For example, a 22kHz to 44kHz resampler is CBR DSP. Even though the number of input to output samples differ, the ratio between input to output rate remains constant. + All user-defined XAPOs are assumed to be CBR as XAudio2 only allows CBR DSP to be added to an effect chain. XAPO: Cross-platform Audio Processing Object -- - a thin wrapper that manages DSP code, allowing it - to be easily plugged into an XAudio2 effect chain. + a thin wrapper that manages DSP code, allowing it to be easily plugged into an XAudio2 effect chain. - Frame: A block of samples, one per channel, - to be played simultaneously. + Frame: A block of samples, one per channel, to be played simultaneously. E.g. a mono stream has one sample per frame. - In-Place: Processing such that the input buffer equals the - output buffer (i.e. input data modified directly). - This form of processing is generally more efficient - than using separate memory for input and output. - However, an XAPO may not perform format conversion - when processing in-place. + In-Place: Processing such that the input buffer equals the output buffer (i.e. input data modified directly). + This form of processing is generally more efficient than using separate memory for input and output. + However, an XAPO may not perform format conversion when processing in-place. - 2. XAPO member variables are divided into three classifications: - Immutable: Set once via IXAPO.Initialize and remain - constant during the lifespan of the XAPO. + 2. XAPO member variables are divided into three classifications: + Immutable: Set once via IXAPO.Initialize and remain constant during the lifespan of the XAPO. Locked: May change before the XAPO is locked via - IXAPO.LockForProcess but remain constant - until IXAPO.UnlockForProcess is called. + IXAPO.LockForProcess but remain constant until IXAPO.UnlockForProcess is called. - Dynamic: May change from one processing pass to the next, - usually via IXAPOParameters.SetParameters. - XAPOs should assign reasonable defaults to their dynamic - variables during IXAPO.Initialize/LockForProcess so - that calling IXAPOParameters.SetParameters is not - required before processing begins. + Dynamic: May change from one processing pass to the next, usually via IXAPOParameters.SetParameters. + XAPOs should assign reasonable defaults to their dynamic variables during IXAPO.Initialize/LockForProcess so that calling IXAPOParameters.SetParameters is not required before processing begins. - When implementing an XAPO, determine the type of each variable and - initialize them in the appropriate method. Immutable variables are - generally preferable over locked which are preferable over dynamic. - That is, one should strive to minimize XAPO state changes for - best performance, maintainability, and ease of use. + When implementing an XAPO, determine the type of each variable and initialize them in the appropriate method. Immutable variables are generally preferable over locked which are preferable over dynamic. + That is, one should strive to minimize XAPO state changes for best performance, maintainability, and ease of use. - 3. To minimize glitches, the realtime audio processing thread must - not block. XAPO methods called by the realtime thread are commented - as non-blocking and therefore should not use blocking synchronization, - allocate memory, access the disk, etc. The XAPO interfaces were - designed to allow an effect implementer to move such operations - into other methods called on an application controlled thread. + 3. To minimize glitches, the realtime audio processing thread must not block. XAPO methods called by the realtime thread are commented as non-blocking and therefore should not use blocking synchronization, allocate memory, access the disk, etc. + The XAPO interfaces were designed to allow an effect implementer to move such operations into other methods called on an application controlled thread. - 4. Extending functionality is accomplished through the addition of new - COM interfaces. For example, if a new member is added to a parameter - structure, a new interface using the new structure should be added, - leaving the original interface unchanged. - This ensures consistent communication between future versions of - XAudio2 and various versions of XAPOs that may exist in an application. + 4. Extending functionality is accomplished through the addition of new COM interfaces. For example, if a new member is added to a parameter structure, a new interface using the new structure should be added, leaving the original interface unchanged. + This ensures consistent communication between future versions of XAudio2 and various versions of XAPOs that may exist in an application. - 5. All audio data is interleaved in XAudio2. + 5. All audio data is interleaved in XAudio2. The default audio format for an effect chain is WAVE_FORMAT_IEEE_FLOAT. - 6. User-defined XAPOs should assume all input and output buffers are - 16-byte aligned. - - 7. See XAPOBase.odin for an XAPO base class which provides a default - implementation for most of the interface methods defined below. */ + 6. User-defined XAPOs should assume all input and output buffers are 16-byte aligned. */ package windows_xaudio2 @@ -77,8 +47,7 @@ import win "core:sys/windows" //---------------------------------------------------// -// XAPO error codes -FORMAT_UNSUPPORTED := win.MAKE_HRESULT(win.SEVERITY.ERROR, 0x897, 0x01) // requested audio format unsupported +FORMAT_UNSUPPORTED := win.MAKE_HRESULT(win.SEVERITY.ERROR, win.FACILITY.XAPO, 0x01) // requested audio format unsupported // supported number of channels (samples per frame) range XAPO_MIN_CHANNELS :: 1 @@ -111,11 +80,11 @@ XAPO_FLAG :: enum u32 { // XAPO must be run in-place. Use this flag only if your DSP implementation cannot process separate input and output buffers. // If set, the following flags must also be set: - // XAPO_FLAG_CHANNELS_MUST_MATCH - // XAPO_FLAG_FRAMERATE_MUST_MATCH - // XAPO_FLAG_BITSPERSAMPLE_MUST_MATCH - // XAPO_FLAG_BUFFERCOUNT_MUST_MATCH - // XAPO_FLAG_INPLACE_SUPPORTED + // CHANNELS_MUST_MATCH + // FRAMERATE_MUST_MATCH + // BITSPERSAMPLE_MUST_MATCH + // BUFFERCOUNT_MUST_MATCH + // INPLACE_SUPPORTED // Multiple input and output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count. // When multiple input/output buffers are used, the XAPO may assume input buffer [N] equals output buffer [N] for in-place processing. INPLACE_REQUIRED = 5, @@ -139,18 +108,18 @@ XAPO_REGISTRATION_PROPERTIES :: struct #packed { Flags: XAPO_FLAGS, // XAPO property flags, describes supported input/output configuration MinInputBufferCount: u32, // minimum number of input buffers required for processing, can be 0 MaxInputBufferCount: u32, // maximum number of input buffers supported for processing, must be >= MinInputBufferCount - MinOutputBufferCount: u32, // minimum number of output buffers required for processing, can be 0, must match MinInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used - MaxOutputBufferCount: u32, // maximum number of output buffers supported for processing, must be >= MinOutputBufferCount, must match MaxInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used + MinOutputBufferCount: u32, // minimum number of output buffers required for processing, can be 0, must match MinInputBufferCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used + MaxOutputBufferCount: u32, // maximum number of output buffers supported for processing, must be >= MinOutputBufferCount, must match MaxInputBufferCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used } // LockForProcess buffer parameters: // Defines buffer parameters that remain constant while an XAPO is locked. -// Used with IXAPO::LockForProcess. +// Used with IXAPO.LockForProcess. // For CBR XAPOs, MaxFrameCount is the only number of frames -// IXAPO::Process would have to handle for the respective buffer. +// IXAPO.Process would have to handle for the respective buffer. XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS :: struct #packed { pFormat: ^WAVEFORMATEX, // buffer audio format - MaxFrameCount: u32, // maximum number of frames in respective buffer that IXAPO::Process would have to handle, irrespective of dynamic variable settings, can be 0 + MaxFrameCount: u32, // maximum number of frames in respective buffer that IXAPO.Process would have to handle, irrespective of dynamic variable settings, can be 0 } // Buffer flags: @@ -161,31 +130,25 @@ XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS :: struct #packed { // If silent, the XAPO may simply set the flag on the output buffer to silent and return, optimizing out the work of processing silent data: XAPOs that generate silence for any reason may set the buffer's flag accordingly rather than writing out silent frames to the buffer itself. // The flags represent what should be assumed is in the respective buffer. The flags may not reflect what is actually stored in memory. XAPO_BUFFER_FLAGS :: enum i32 { - XAPO_BUFFER_SILENT, // silent data should be assumed, respective memory may be uninitialized - XAPO_BUFFER_VALID, // arbitrary data should be assumed (may or may not be silent frames), respective memory initialized + SILENT, // silent data should be assumed, respective memory may be uninitialized + VALID, // arbitrary data should be assumed (may or may not be silent frames), respective memory initialized } // Process buffer parameters: -// Defines buffer parameters that may change from one -// processing pass to the next. Used with IXAPO::Process. -// +// Defines buffer parameters that may change from one processing pass to the next. Used with IXAPO.Process. // Note the byte size of the respective buffer must be at least: -// XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount * XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat->nBlockAlign -// -// Although the audio format and maximum size of the respective -// buffer is locked (defined by XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS), -// the actual memory address of the buffer given is permitted to change -// from one processing pass to the next. -// -// For CBR XAPOs, ValidFrameCount is constant while locked and equals -// the respective XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount. +// XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount * XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat.nBlockAlign +// Although the audio format and maximum size of the respective buffer is locked (defined by XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS), the actual memory address of the buffer given is permitted to change from one processing pass to the next. +// For CBR XAPOs, ValidFrameCount is constant while locked and equals the respective XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount. XAPO_PROCESS_BUFFER_PARAMETERS :: struct #packed { - pBuffer: rawptr, // audio data buffer, must be non-NULL + pBuffer: rawptr, // audio data buffer, must be non-nil BufferFlags: XAPO_BUFFER_FLAGS, // describes assumed content of pBuffer, does not affect ValidFrameCount ValidFrameCount: u32, // number of frames of valid data, must be within respective [0, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount], always XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount for CBR/user-defined XAPOs, does not affect BufferFlags } -XAPOFree :: win.CoTaskMemFree +// Used by IXAPO methods that must allocate arbitrary sized structures such as WAVEFORMATEX that are subsequently returned to the application. +XAPOAlloc :: win.CoTaskMemAlloc +XAPOFree :: win.CoTaskMemFree IXAPO_UUID_STRING :: "A410B984-9839-4819-A0BE-2856AE6B3ADB" IXAPO_UUID := &win.IID{0xA410B984, 0x9839, 0x4819, {0xA0, 0xBE, 0x28, 0x56, 0xAE, 0x6B, 0x3A, 0xDB}} @@ -214,11 +177,11 @@ IXAPO_VTable :: struct { // PARAMETERS: // pOutputFormat - [in] output format known to be supported // pRequestedInputFormat - [in] input format to examine - // ppSupportedInputFormat - [out] receives pointer to nearest input format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED + // ppSupportedInputFormat - [out] receives pointer to nearest input format supported if not nil and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except FORMAT_UNSUPPORTED // RETURN VALUE: // COM error code, including: // S_OK - input/output configuration supported, ppSupportedInputFormat left untouched - // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedInputFormat receives pointer to nearest input format supported if not NULL + // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedInputFormat receives pointer to nearest input format supported if not nil // E_INVALIDARG - either audio format invalid, ppSupportedInputFormat left untouched IsInputFormatSupported: proc "system" (this: ^IXAPO, pOutputFormat: ^WAVEFORMATEX, pRequestedInputFormat: ^WAVEFORMATEX, ppSupportedInputFormat: ^^WAVEFORMATEX) -> HRESULT, @@ -232,11 +195,11 @@ IXAPO_VTable :: struct { // PARAMETERS: // pInputFormat - [in] input format known to be supported // pRequestedOutputFormat - [in] output format to examine - // ppSupportedOutputFormat - [out] receives pointer to nearest output format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED + // ppSupportedOutputFormat - [out] receives pointer to nearest output format supported if not nil and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except FORMAT_UNSUPPORTED // RETURN VALUE: // COM error code, including: // S_OK - input/output configuration supported, ppSupportedOutputFormat left untouched - // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedOutputFormat receives pointer to nearest output format supported if not NULL + // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedOutputFormat receives pointer to nearest output format supported if not nil // E_INVALIDARG - either audio format invalid, ppSupportedOutputFormat left untouched IsOutputFormatSupported: proc "system" (this: ^IXAPO, pInputFormat: ^WAVEFORMATEX, pRequestedOutputFormat: ^WAVEFORMATEX, ppSupportedOutputFormat: ^^WAVEFORMATEX) -> HRESULT, @@ -246,10 +209,10 @@ IXAPO_VTable :: struct { // The contents of pData are defined by the XAPO. // Immutable variables (constant during the lifespan of the XAPO) should be set once via this method. // Once initialized, an XAPO cannot be initialized again. - // An XAPO should be initialized before passing it to XAudio2 as part of an effect chain. XAudio2 will not call this method; it exists for future content-driven initialization. + // An XAPO should be initialized before passing it to XAudio2 as part of an effect chain. XAudio2 will not call this method; it exists for future content-driven initialization. // PARAMETERS: - // pData - [in] effect-specific initialization parameters, may be NULL if DataByteSize == 0 - // DataByteSize - [in] size of pData in bytes, may be 0 if pData is NULL + // pData - [in] effect-specific initialization parameters, may be nil if DataByteSize == 0 + // DataByteSize - [in] size of pData in bytes, may be 0 if pData is nil // RETURN VALUE: // COM error code Initialize: proc "system" (this: ^IXAPO, pData: rawptr, DataByteSize: u32) -> HRESULT, @@ -279,9 +242,9 @@ IXAPO_VTable :: struct { // Once locked, an XAPO cannot be locked again until UnLockForProcess is called. // PARAMETERS: // InputLockedParameterCount - [in] number of input buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinInputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxInputBufferCount] - // pInputLockedParameters - [in] array of input locked buffer parameter structures, may be NULL if InputLockedParameterCount == 0, otherwise must have InputLockedParameterCount elements - // OutputLockedParameterCount - [in] number of output buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount], must match InputLockedParameterCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used - // pOutputLockedParameters - [in] array of output locked buffer parameter structures, may be NULL if OutputLockedParameterCount == 0, otherwise must have OutputLockedParameterCount elements + // pInputLockedParameters - [in] array of input locked buffer parameter structures, may be nil if InputLockedParameterCount == 0, otherwise must have InputLockedParameterCount elements + // OutputLockedParameterCount - [in] number of output buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount], must match InputLockedParameterCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used + // pOutputLockedParameters - [in] array of output locked buffer parameter structures, may be nil if OutputLockedParameterCount == 0, otherwise must have OutputLockedParameterCount elements // RETURN VALUE: // COM error code LockForProcess: proc "system" (this: ^IXAPO, InputLockedParameterCount: u32, pInputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS, OutputLockedParameterCount: u32, pOutputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS) -> HRESULT, @@ -303,16 +266,16 @@ IXAPO_VTable :: struct { // ppInputProcessParameters will not necessarily be the same as ppOutputProcessParameters for in-place processing, rather the pBuffer members of each will point to the same memory. // Multiple input/output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count. // When multiple input/output buffers are used with in-place XAPOs, the XAPO may assume input buffer [N] equals output buffer [N]. - // When IsEnabled is FALSE, the XAPO should process thru. Thru processing means an XAPO should not apply its normal processing to the given input/output buffers during Process. - // It should instead pass data from input to output with as little modification possible. Effects that perform format conversion should continue to do so. + // When IsEnabled is false, the XAPO should process thru. Thru processing means an XAPO should not apply its normal processing to the given input/output buffers during Process. + // It should instead pass data from input to output with as little modification possible. Effects that perform format conversion should continue to do so. // The effect must ensure transitions between normal and thru processing do not introduce discontinuities into the signal. // XAudio2 calls this method only if the XAPO is locked. This method should not block as it is called from the realtime thread. // PARAMETERS: // InputProcessParameterCount - [in] number of input buffers, matches respective InputLockedParameterCount parameter given to LockForProcess - // pInputProcessParameters - [in] array of input process buffer parameter structures, may be NULL if InputProcessParameterCount == 0, otherwise must have InputProcessParameterCount elements + // pInputProcessParameters - [in] array of input process buffer parameter structures, may be nil if InputProcessParameterCount == 0, otherwise must have InputProcessParameterCount elements // OutputProcessParameterCount - [in] number of output buffers, matches respective OutputLockedParameterCount parameter given to LockForProcess - // pOutputProcessParameters - [in/out] array of output process buffer parameter structures, may be NULL if OutputProcessParameterCount == 0, otherwise must have OutputProcessParameterCount elements - // IsEnabled - [in] TRUE to process normally, FALSE to process thru + // pOutputProcessParameters - [in/out] array of output process buffer parameter structures, may be nil if OutputProcessParameterCount == 0, otherwise must have OutputProcessParameterCount elements + // IsEnabled - [in] true to process normally, false to process thru // RETURN VALUE: // void Process: proc "system" (this: ^IXAPO, InputProcessParameterCount: u32, pInputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, OutputProcessParameterCount: u32, pOutputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, IsEnabled: b32), @@ -358,7 +321,7 @@ IXAPOParameters_VTable :: struct { // This method may only be called on the realtime thread; no synchronization between it and IXAPO.Process is necessary. // This method should not block as it is called from the realtime thread. // PARAMETERS: - // pParameters - [in] effect-specific parameter block, must be != NULL + // pParameters - [in] effect-specific parameter block, must be != nil // ParameterByteSize - [in] size of pParameters in bytes, must be > 0 // RETURN VALUE: // void @@ -369,7 +332,7 @@ IXAPOParameters_VTable :: struct { // REMARKS: // Unlike SetParameters, XAudio2 does not call this method on the realtime thread. Thus, the XAPO must protect variables shared with SetParameters/Process using appropriate synchronization. // PARAMETERS: - // pParameters - [out] receives effect-specific parameter block, must be != NULL + // pParameters - [out] receives effect-specific parameter block, must be != nil // ParameterByteSize - [in] size of pParameters in bytes, must be > 0 // RETURN VALUE: // void diff --git a/vendor/windows/XAudio2/xapofx.odin b/vendor/windows/XAudio2/xapofx.odin index 5c4c8c7ec..5ab9d57a8 100644 --- a/vendor/windows/XAudio2/xapofx.odin +++ b/vendor/windows/XAudio2/xapofx.odin @@ -132,7 +132,7 @@ FXECHO_PARAMETERS :: struct #packed { @(default_calling_convention="cdecl") foreign xa2 { // creates instance of requested XAPO, use Release to free instance - // pInitData - [in] effect-specific initialization parameters, may be NULL if InitDataByteSize == 0 - // InitDataByteSize - [in] size of pInitData in bytes, may be 0 if pInitData is NULL + // pInitData - [in] effect-specific initialization parameters, may be nil if InitDataByteSize == 0 + // InitDataByteSize - [in] size of pInitData in bytes, may be 0 if pInitData is nil CreateFX :: proc(clsid: win.REFCLSID, pEffect: ^^IUnknown, pInitDat: rawptr = nil, InitDataByteSize: u32 = 0) -> HRESULT --- } diff --git a/vendor/windows/XAudio2/xaudio2.odin b/vendor/windows/XAudio2/xaudio2.odin index 178463b64..6187b63fe 100644 --- a/vendor/windows/XAudio2/xaudio2.odin +++ b/vendor/windows/XAudio2/xaudio2.odin @@ -11,6 +11,8 @@ package windows_xaudio2 import win "core:sys/windows" import "core:math" +foreign import xa2 "system:xaudio2.lib" + HRESULT :: win.HRESULT IUnknown :: win.IUnknown IUnknown_VTable :: win.IUnknown_VTable @@ -93,8 +95,8 @@ DEVICE_INVALIDATED :: HRESULT(-2003435516) // 0x88960004 An audio device be **************************************************************************/ // Used in Create, specifies which CPU(s) to use. -PROCESSOR_FLAGS :: distinct bit_set[PROCESOR_FLAG; u32] -PROCESOR_FLAG :: enum u32 { +PROCESSOR_FLAGS :: distinct bit_set[PROCESSOR_FLAG; u32] +PROCESSOR_FLAG :: enum u32 { Processor1 = 0, Processor2 = 1, Processor3 = 2, @@ -128,7 +130,7 @@ PROCESOR_FLAG :: enum u32 { Processor31 = 30, Processor32 = 31, } - +//ANY_PROCESSOR :: 0xffffffff USE_DEFAULT_PROCESSOR :: PROCESSOR_FLAGS{} // Returned by IXAudio2Voice.GetVoiceDetails @@ -147,8 +149,8 @@ SEND_DESCRIPTOR :: struct #packed { // Used in the voice creation functions and in IXAudio2Voice.SetOutputVoices VOICE_SENDS :: struct #packed { - SendCount: u32, // Number of sends from this voice. - pSends: [^]SEND_DESCRIPTOR, // Array of SendCount send descriptors. + SendCount: u32, // Number of sends from this voice. + pSends: [^]SEND_DESCRIPTOR `fmt:"v,SendCount"`, // Array of SendCount send descriptors. } // Used in EFFECT_CHAIN below @@ -160,8 +162,8 @@ EFFECT_DESCRIPTOR :: struct #packed { // Used in the voice creation functions and in IXAudio2Voice.SetEffectChain EFFECT_CHAIN :: struct #packed { - EffectCount: u32, // Number of effects in this voice's effect chain. - pEffectDescriptors: [^]EFFECT_DESCRIPTOR, // Array of effect descriptors. + EffectCount: u32, // Number of effects in this voice's effect chain. + pEffectDescriptors: [^]EFFECT_DESCRIPTOR `fmt:"v,EffectCount"`, // Array of effect descriptors. } // Used in FILTER_PARAMETERS below @@ -183,28 +185,28 @@ FILTER_PARAMETERS :: struct #packed { // Used in IXAudio2SourceVoice.SubmitSourceBuffer BUFFER :: struct #packed { - Flags: FLAGS, // Either 0 or END_OF_STREAM. - AudioBytes: u32, // Size of the audio data buffer in bytes. - pAudioData: [^]byte, // Pointer to the audio data buffer. - PlayBegin: u32, // First sample in this buffer to be played. - PlayLength: u32, // Length of the region to be played in samples, or 0 to play the whole buffer. - LoopBegin: u32, // First sample of the region to be looped. - LoopLength: u32, // Length of the desired loop region in samples, or 0 to loop the entire buffer. - LoopCount: u32, // Number of times to repeat the loop region, or LOOP_INFINITE to loop forever. - pContext: rawptr, // Context value to be passed back in callbacks. + Flags: FLAGS, // Either 0 or END_OF_STREAM. + AudioBytes: u32, // Size of the audio data buffer in bytes. + pAudioData: [^]byte `fmt:"v,AudioBytes"`, // Pointer to the audio data buffer. + PlayBegin: u32, // First sample in this buffer to be played. + PlayLength: u32, // Length of the region to be played in samples, or 0 to play the whole buffer. + LoopBegin: u32, // First sample of the region to be looped. + LoopLength: u32, // Length of the desired loop region in samples, or 0 to loop the entire buffer. + LoopCount: u32, // Number of times to repeat the loop region, or LOOP_INFINITE to loop forever. + pContext: rawptr, // Context value to be passed back in callbacks. } // Used in IXAudio2SourceVoice.SubmitSourceBuffer when submitting XWMA data. // NOTE: If an XWMA sound is submitted in more than one buffer, each buffer's pDecodedPacketCumulativeBytes[PacketCount-1] value must be subtracted from all the entries in the next buffer's pDecodedPacketCumulativeBytes array. // And whether a sound is submitted in more than one buffer or not, the final buffer of the sound should use the END_OF_STREAM flag, or else the client must call IXAudio2SourceVoice.Discontinuity after submitting it. BUFFER_WMA :: struct #packed { - pDecodedPacketCumulativeBytes: [^]u32, // Decoded packet's cumulative size array. Each element is the number of bytes accumulated when the corresponding XWMA packet is decoded in order. The array must have PacketCount elements. - PacketCount: u32, // Number of XWMA packets submitted. Must be >= 1 and divide evenly into BUFFER.AudioBytes. + pDecodedPacketCumulativeBytes: [^]u32 `fmt:"v,PacketCount"`, // Decoded packet's cumulative size array. Each element is the number of bytes accumulated when the corresponding XWMA packet is decoded in order. The array must have PacketCount elements. + PacketCount: u32, // Number of XWMA packets submitted. Must be >= 1 and divide evenly into BUFFER.AudioBytes. } // Returned by IXAudio2SourceVoice.GetState VOICE_STATE :: struct #packed { - pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or NULL if there are no buffers in the queue. + pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or nil if there are no buffers in the queue. BuffersQueued: u32, // Number of buffers currently queued on the voice (including the one that is being processed). SamplesPlayed: u64, // Total number of samples produced by the voice since it began processing the current audio stream. If VOICE_NOSAMPLESPLAYED is specified in the call to IXAudio2SourceVoice.GetState, this member will not be calculated, saving CPU. } @@ -336,8 +338,7 @@ IXAudio2_VTable :: struct { StopEngine: proc "system" (this: ^IXAudio2), // NAME: IXAudio2.CommitChanges - // DESCRIPTION: Atomically applies a set of operations previously tagged - // with a given identifier. + // DESCRIPTION: Atomically applies a set of operations previously tagged with a given identifier. // ARGUMENTS: // OperationSet - Identifier of the set of operations to be applied. CommitChanges: proc "system" (this: ^IXAudio2, OperationSet: u32) -> HRESULT, @@ -352,7 +353,7 @@ IXAudio2_VTable :: struct { // DESCRIPTION: Configures XAudio2's debug output (in debug builds only). // ARGUMENTS: // pDebugConfiguration - Structure describing the debug output behavior. - // pReserved - Optional parameter; must be NULL. + // pReserved - Optional parameter; must be nil. SetDebugConfiguration: proc "system" (this: ^IXAudio2, pDebugConfiguration: ^DEBUG_CONFIGURATION, pReserved: rawptr = nil), } @@ -399,8 +400,7 @@ IXAudio2Voice_VTable :: struct { GetVoiceDetails: proc "system" (this: ^IXAudio2Voice, pVoiceDetails: ^VOICE_DETAILS), // NAME: IXAudio2Voice.SetOutputVoices - // DESCRIPTION: Replaces the set of submix/mastering voices that receive - // this voice's output. + // DESCRIPTION: Replaces the set of submix/mastering voices that receive this voice's output. // ARGUMENTS: // pSendList - Optional list of voices this voice should send audio to. SetOutputVoices: proc "system" (this: ^IXAudio2Voice, pSendList: [^]VOICE_SENDS) -> HRESULT, @@ -709,37 +709,15 @@ IXAudio2VoiceCallback_VTable :: struct { * * Flags - Flags specifying the XAudio2 object's behavior. * - * XAudio2Processor - A PROCESSOR_FLAGS value that specifies the hardware threads (Xbox) or processors (Windows) that XAudio2 will use. + * Processor - A PROCESSOR_FLAGS value that specifies the hardware threads (Xbox) or processors (Windows) that XAudio2 will use. * Note that XAudio2 supports concurrent processing on multiple threads, using any combination of PROCESSOR_FLAGS flags. * The values are platform-specific; platform-independent code can use USE_DEFAULT_PROCESSOR to use the default on each platform. * **************************************************************************/ -Create :: proc "stdcall" (ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT { - CreateWithVersionInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS, a3: win.DWORD) -> HRESULT - CreateInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS) -> HRESULT - - dll_Instance: win.HMODULE - create_with_version_info: CreateWithVersionInfoFunc - create_info: CreateInfoFunc - - if dll_Instance == nil { - dll_Instance = win.LoadLibraryExW(win.L("xaudio2_9.dll"), nil, {.LOAD_LIBRARY_SEARCH_SYSTEM32}) - if dll_Instance == nil { - return HRESULT(win.GetLastError()) - } - create_with_version_info = cast(CreateWithVersionInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2CreateWithVersionInfo") - if create_with_version_info == nil { - create_info = cast(CreateInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2Create") - if create_info == nil { - return HRESULT(win.GetLastError()) - } - } - } - if create_with_version_info != nil { - return create_with_version_info(ppXAudio2, Flags, XAudio2Processor, 0x0A000010) - } - return create_info(ppXAudio2, Flags, XAudio2Processor) +@(default_calling_convention="system", link_prefix="XAudio2") +foreign xa2 { + Create :: proc(ppXaudio2: ^^IXAudio2, Flags: FLAGS = {}, Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT --- } /************************************************************************** @@ -749,12 +727,12 @@ Create :: proc "stdcall" (ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Proce **************************************************************************/ // Calculate the argument to SetVolume from a decibel value -DecibelsToAmplitudeRatio :: proc "contextless" (Decibels: f32) -> f32 { +DecibelsToAmplitudeRatio :: #force_inline proc "contextless" (Decibels: f32) -> f32 { return math.pow_f32(10.0, Decibels / 20.0) } // Recover a volume in decibels from an amplitude factor -AmplitudeRatioToDecibels :: proc "contextless" (Volume: f32) -> f32 { +AmplitudeRatioToDecibels :: #force_inline proc "contextless" (Volume: f32) -> f32 { if Volume == 0 { return min(f32) } @@ -762,14 +740,14 @@ AmplitudeRatioToDecibels :: proc "contextless" (Volume: f32) -> f32 { } // Calculate the argument to SetFrequencyRatio from a semitone value -SemitonesToFrequencyRatio :: proc "contextless" (Semitones: f32) -> f32 { +SemitonesToFrequencyRatio :: #force_inline proc "contextless" (Semitones: f32) -> f32 { // FrequencyRatio = 2 ^ Octaves // = 2 ^ (Semitones / 12) return math.pow_f32(2.0, Semitones / 12.0) } // Recover a pitch in semitones from a frequency ratio -FrequencyRatioToSemitones :: proc "contextless" (FrequencyRatio: f32) -> f32 { +FrequencyRatioToSemitones :: #force_inline proc "contextless" (FrequencyRatio: f32) -> f32 { // Semitones = 12 * log2(FrequencyRatio) // = 12 * log2(10) * log10(FrequencyRatio) return 12.0 * math.log2_f32(FrequencyRatio) @@ -779,7 +757,7 @@ FrequencyRatioToSemitones :: proc "contextless" (FrequencyRatio: f32) -> f32 { // Use CutoffFrequencyToOnePoleCoefficient() for one-pole filter types. // Note that the highest CutoffFrequency supported is SampleRate/6. // Higher values of CutoffFrequency will return MAX_FILTER_FREQUENCY. -CutoffFrequencyToRadians :: proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { +CutoffFrequencyToRadians :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { if u32(CutoffFrequency * 6.0) >= SampleRate { return MAX_FILTER_FREQUENCY } @@ -787,14 +765,14 @@ CutoffFrequencyToRadians :: proc "contextless" (CutoffFrequency: f32, SampleRate } // Convert from radian frequencies back to absolute frequencies in Hertz -RadiansToCutoffFrequency :: proc "contextless" (Radians: f32, SampleRate: f32) -> f32 { +RadiansToCutoffFrequency :: #force_inline proc "contextless" (Radians: f32, SampleRate: f32) -> f32 { return SampleRate * math.asin_f32(Radians / 2.0) / math.PI } // Convert from filter cutoff frequencies expressed in Hertz to the filter coefficients used with FILTER_PARAMETERS.Frequency, // LowPassOnePoleFilter and HighPassOnePoleFilter filter types only. // Use CutoffFrequencyToRadians() for state-variable filter types. -CutoffFrequencyToOnePoleCoefficient :: proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { +CutoffFrequencyToOnePoleCoefficient :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { if u32(CutoffFrequency) >= SampleRate { return MAX_FILTER_FREQUENCY } diff --git a/vendor/windows/XAudio2/xaudio2fx.odin b/vendor/windows/XAudio2/xaudio2fx.odin index 1449ed4ea..90bd9745b 100644 --- a/vendor/windows/XAudio2/xaudio2fx.odin +++ b/vendor/windows/XAudio2/xaudio2fx.odin @@ -10,8 +10,7 @@ foreign import xa2 "system:xaudio2.lib" * * Effect creation functions. * - * On Xbox the application can link with the debug library to use the debug - * functionality. + * On Xbox the application can link with the debug library to use the debug functionality. * **************************************************************************/ @@ -32,9 +31,9 @@ foreign xa2 { // The user is responsible for allocating pPeakLevels, pRMSLevels, and initializing ChannelCount accordingly. // The volume meter does not support SetEffectParameters(). VOLUMEMETER_LEVELS :: struct #packed { - pPeakLevels: [^]f32 `fmt:"v,ChannelCount"`, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be NULL if pRMSLevls != NULL, otherwise must have at least ChannelCount elements. - pRMSLevels: [^]f32 `fmt:"v,ChannelCount"`, // Root mean square levels table: receives RMS level for each channel over a processing pass, may be NULL if pPeakLevels != NULL, otherwise must have at least ChannelCount elements. - ChannelCount: u32, // Number of channels being processed by the volume meter APO + pPeakLevels: [^]f32 `fmt:"v,ChannelCount"`, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be nil if pRMSLevls != nil, otherwise must have at least ChannelCount elements. + pRMSLevels: [^]f32 `fmt:"v,ChannelCount"`, // Root mean square levels table: receives RMS level for each channel over a processing pass, may be nil if pPeakLevels != nil, otherwise must have at least ChannelCount elements. + ChannelCount: u32, // Number of channels being processed by the volume meter APO } /************************************************************************** @@ -87,7 +86,7 @@ REVERB_PARAMETERS :: struct #packed { Density: f32, // [0, 100] (percentage) RoomSize: f32, // [1, 100] in feet // component control - DisableLateField: b32, // TRUE to disable late field reflections + DisableLateField: b32, // true to disable late field reflections } // Maximum, minimum and default values for the parameters above @@ -244,13 +243,13 @@ ReverbConvertI3DL2ToNative :: proc "contextless" (pI3DL2: ^REVERB_I3DL2_PARAMETE if pI3DL2.DecayHFRatio >= 1.0 { index := i32(-4.0 * math.log10_f32(pI3DL2.DecayHFRatio)) - if index < -8 { index = -8 } + if index < -8 {index = -8} pNative.LowEQGain = byte((index < 0) ? index + 8 : 8) pNative.HighEQGain = 8 pNative.DecayTime = pI3DL2.DecayTime * pI3DL2.DecayHFRatio } else { index := i32(4.0 * math.log10_f32(pI3DL2.DecayHFRatio)) - if index < -8 { index = -8 } + if index < -8 {index = -8} pNative.LowEQGain = 8 pNative.HighEQGain = byte((index < 0) ? index + 8 : 8) pNative.DecayTime = pI3DL2.DecayTime diff --git a/vendor/windows/wasapi/wasapi.odin b/vendor/windows/wasapi/wasapi.odin new file mode 100644 index 000000000..2cc07aeb8 --- /dev/null +++ b/vendor/windows/wasapi/wasapi.odin @@ -0,0 +1,326 @@ +// Windows Audio Session API Bindings Package +package wasapi + +import "core:sys/windows" + + +KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRING :: "00000003-0000-0010-8000-00aa00389b71" +KSDATAFORMAT_SUBTYPE_IEEE_FLOAT := windows.GUID{0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} + +// MARK: IMMDeviceEnumerator + +CLSID_MMDeviceEnumerator_STRING :: "BCDE0395-E52F-467C-8E3D-C4579291692E" +CLSID_MMDeviceEnumerator := &windows.IID{0xBCDE0395, 0xE52F, 0x467C, {0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E}} + +IID_IMMDeviceEnumerator_STRING :: "A95664D2-9614-4F35-A746-DE8DB63617E6" +IID_IMMDeviceEnumerator := &windows.IID{0xA95664D2, 0x9614, 0x4F35, {0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6}} + +IID_IAudioClient_STRING :: "1CB9AD4C-DBFA-4c32-B178-C2F568A703B2" +IID_IAudioClient := &windows.IID{0x1CB9AD4C, 0xDBFA, 0x4c32, {0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}} + +IID_IAudioRenderClient_STRING :: "F294ACFC-3146-4483-A7BF-ADDCA7C260E2" +IID_IAudioRenderClient := &windows.IID{0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}} + + +IMMDeviceEnumerator :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using immdeviceenumerator_vtable: ^IMMDeviceEnumerator_VTable, +} + +IMMDeviceEnumerator_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + EnumAudioEndpoints: proc "system" ( + This: ^IMMDeviceEnumerator, + dataFlow: EDataFlow, + dwStateMask: windows.DWORD, + ppDevices: [^]IMMDeviceCollection, // Out + ) -> windows.HRESULT, + + GetDefaultAudioEndpoint: proc "system" ( + This: ^IMMDeviceEnumerator, + dataFlow: EDataFlow, + role: ERole, + ppEndpoint: ^^IMMDevice, // Out + ) -> windows.HRESULT, + + GetDevice: proc "system" ( + This: ^IMMDeviceEnumerator, + pwstrId: windows.LPCWSTR, + ppDevice: ^^IMMDevice, // Out + ) -> windows.HRESULT, + + RegisterEndpointNotificationCallback: proc "system" ( + This: ^IMMDeviceEnumerator, + pClient: ^IMMNotificationClient, // In + ) -> windows.HRESULT, + + UnregisterEndpointNotificationCallback: proc "system" ( + This: ^IMMDeviceEnumerator, + pClient: ^IMMNotificationClient, // In + ) -> windows.HRESULT, +} + + + +// MARK: IMMDeviceCollection + +IMMDeviceCollection :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using immdevicecollection_vtable: ^IMMDeviceCollection_VTable, +} + +IMMDeviceCollection_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + GetCount: proc "system" ( + This: ^IMMDeviceCollection, + pcDevices: ^windows.UINT, // Out + ) -> windows.HRESULT, + + Item: proc "system" ( + This: ^IMMDeviceCollection, + nDevice: windows.UINT, + ppDevice: ^^IMMDevice, + ) -> windows.HRESULT, +} + +// MARK: IMMDevice + +IMMDevice :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using immdevice_vtable: ^IMMDevice_VTable, +} + +IMMDevice_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + Activate: proc "system" ( + This: ^IMMDevice, + iid: windows.REFIID, // In + dwClsCtx: windows.DWORD, // In + pActivationParams: ^rawptr, // In Optional PROPVARIANT + ppInterface: [^]rawptr, // Out + ) -> windows.HRESULT, + + OpenPropertyStore: proc "system" ( + This: ^IMMDevice, + stgmAccess: windows.DWORD, // In + ppProperties: [^]^windows.IPropertyStore, // Out + ) -> windows.HRESULT, + + GetId: proc "system" ( + This: ^IMMDevice, + ppstrId: ^windows.LPWSTR, // Out + ) -> windows.HRESULT, + + GetState: proc "system" ( + This: ^IMMDevice, + pdwState: ^windows.DWORD, // Out + ) -> windows.HRESULT, +} + + + +// MARK: IMMNotificationClient + +IMMNotificationClient :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using immnotificationclient_vtable: ^IMMNotificationClient_VTable, +} + +IMMNotificationClient_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + OnDeviceStateChanged: proc "system" ( + This: ^IMMNotificationClient, + pwstrDeviceId: windows.LPCWSTR, + dwNewState: windows.DWORD, + ) -> windows.HRESULT, + + OnDeviceAdded: proc "system" ( + This: ^IMMNotificationClient, + pwstrDeviceId: windows.LPCWSTR, + ) -> windows.HRESULT, + + OnDeviceRemoved: proc "system" ( + This: ^IMMNotificationClient, + pwstrDeviceId: windows.LPCWSTR, + ) -> windows.HRESULT, + + OnDefaultDeviceChanged: proc "system" ( + This: ^IMMNotificationClient, + flow: EDataFlow, + role: ERole, + pwstrDefaultDeviceId: windows.LPCWSTR, // Optional + ) -> windows.HRESULT, + + OnPropertyValueChanged: proc "system" ( + This: ^IMMNotificationClient, + pwstrDeviceId: windows.LPCWSTR, + key: windows.PROPERTYKEY, + ) -> windows.HRESULT, +} + + +// MARK: IAudioClient + +IAudioClient :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using iaudioclient_vtable: ^IAudioClient_VTable, +} + +IAudioClient_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + Initialize: proc "system" ( + This: ^IAudioClient, + ShareMode: AUDCLNT_SHAREMODE, + StreamFlags: windows.DWORD, + hnsBufferDuration: REFERENCE_TIME, + hnsPeriodicity: REFERENCE_TIME, + pFormat: ^WAVEFORMATEX, // Const In + AudioSessionGuid: windows.LPCGUID, // In Optional + ) -> windows.HRESULT, + + GetBufferSize: proc "system" ( + This: ^IAudioClient, + pNumBufferFrames: ^u32, // Out + ) -> windows.HRESULT, + + GetStreamLatency: proc "system" ( + This: ^IAudioClient, + phnsLatency: ^REFERENCE_TIME, // Out + ) -> windows.HRESULT, + + GetCurrentPadding: proc "system" ( + This: ^IAudioClient, + pNumPaddingFrames: ^u32, // Out + ) -> windows.HRESULT, + + IsFormatSupported: proc "system" ( + This: ^IAudioClient, + ShareMode: AUDCLNT_SHAREMODE, // In + pFormat: ^WAVEFORMATEX, // Const In + ppClosestMatch: ^^WAVEFORMATEX, // Out Optional + ) -> windows.HRESULT, + + GetMixFormat: proc "system" ( + This: ^IAudioClient, + ppDeviceFormat: ^^WAVEFORMATEX, // Out + ) -> windows.HRESULT, + + GetDevicePeriod: proc "system" ( + This: ^IAudioClient, + phnsDefaultDevicePeriod: ^REFERENCE_TIME, // Out Optional + phnsMinimumDevicePeriod: ^REFERENCE_TIME, // Out Optional + ) -> windows.HRESULT, + + Start: proc "system" (This: ^IAudioClient) -> windows.HRESULT, + Stop: proc "system" (This: ^IAudioClient) -> windows.HRESULT, + Reset: proc "system" (This: ^IAudioClient) -> windows.HRESULT, + + SetEventHandle: proc "system" ( + This: ^IAudioClient, + eventHandle: windows.HANDLE, + ) -> windows.HRESULT, + + GetService: proc "system" ( + This: ^IAudioClient, + riid: windows.REFIID, // In + ppv: ^rawptr, // Out + ) -> windows.HRESULT, +} + + + +// MARK: IAudioClient2 + +IAudioClient2 :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using iaudioclient2_vtable: ^IAudioClient2_VTable, +} + +IAudioClient2_VTable :: struct { + using iaudioclient_vtable: IAudioClient_VTable, + + IsOffloadCapable: proc "system" ( + This: ^IAudioClient2, + Category: AUDIO_STREAM_CATEGORY, + pbOffloadCapable: ^windows.BOOL, // Out + ) -> windows.HRESULT, + + SetClientProperties: proc "system" ( + This: ^IAudioClient2, + pProperties: ^AudioClientProperties, // Const In + ) -> windows.HRESULT, + + GetBufferSizeLimits: proc "system" ( + This: ^IAudioClient2, + pFormat: ^WAVEFORMATEX, // Const In + bEventDriven: windows.BOOL, + phnsMinBufferDuration: ^REFERENCE_TIME, // Out + phnsMaxBufferDuration: ^REFERENCE_TIME, // Out + ) -> windows.HRESULT, +} + + + +// MARK: IAudioClient3 + +IAudioClient3 :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using iaudioclient3_vtable: ^IAudioClient3_VTable, +} + +IAudioClient3_VTable :: struct { + using iaudioclient2_vtable: IAudioClient2_VTable, + + GetSharedModeEnginePeriod: proc "system" ( + This: ^IAudioClient3, + pFormat: ^WAVEFORMATEX, // Const In + pDefaultPeriodInFrames: ^u32, // Out + pFundamentalPeriodInFrames: ^u32, // Out + pMinPeriodInFrames: ^u32, // Out + pMaxPeriodInFrames: ^u32, // Out + ) -> windows.HRESULT, + + GetCurrentSharedModeEnginePeriod: proc "system" ( + This: ^IAudioClient3, + ppFormat: ^^WAVEFORMATEX, // Out + pCurrentPeriodInFrames: ^u32, // Out + ) -> windows.HRESULT, + + InitializeSharedAudioStream: proc "system" ( + This: ^IAudioClient3, + StreamFlags: windows.DWORD, + PeriodInFrames: u32, + pFormat: ^WAVEFORMATEX, // Const In + AudioSessionGuid: windows.LPCGUID, // In Optional + ) -> windows.HRESULT, +} + + + +// MARK: IAudioRenderClient + +IAudioRenderClient :: struct #raw_union { + #subtype iunknown: windows.IUnknown, + using iaudiorenderclient_vtable: ^IAudioRenderClient_VTable, +} + +IAudioRenderClient_VTable :: struct { + using iunknown_vtable: windows.IUnknown_VTable, + + GetBuffer: proc "system" ( + This: ^IAudioRenderClient, + NumFramesRequested: u32, + ppData: ^[^]byte, // NumFramesRequested * pFormat->nBlockAlign + ) -> windows.HRESULT, + + ReleaseBuffer: proc "system" ( + This: ^IAudioRenderClient, + NumFramesWritten: u32, + dwFlags: windows.DWORD, + ) -> windows.HRESULT, +} diff --git a/vendor/windows/wasapi/wasapi_hresult.odin b/vendor/windows/wasapi/wasapi_hresult.odin new file mode 100644 index 000000000..75343ac3b --- /dev/null +++ b/vendor/windows/wasapi/wasapi_hresult.odin @@ -0,0 +1,58 @@ +package wasapi + +// MAKE_HRESULT(sev,fac,code) ((sev<<31) | (fac<<16) | (code)) + +// Binary compatible with HRESULT +Result :: enum u32 { + // Error + + AUDCLNT_E_NOT_INITIALIZED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x001, + AUDCLNT_E_ALREADY_INITIALIZED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x002, + AUDCLNT_E_WRONG_ENDPOINT_TYPE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x003, + AUDCLNT_E_DEVICE_INVALIDATED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x004, + AUDCLNT_E_NOT_STOPPED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x005, + AUDCLNT_E_BUFFER_TOO_LARGE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x006, + AUDCLNT_E_OUT_OF_ORDER = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x007, + AUDCLNT_E_UNSUPPORTED_FORMAT = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x008, + AUDCLNT_E_INVALID_SIZE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x009, + AUDCLNT_E_DEVICE_IN_USE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x00a, + AUDCLNT_E_BUFFER_OPERATION_PENDING = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x00b, + AUDCLNT_E_THREAD_NOT_REGISTERED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x00c, + AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x00e, + AUDCLNT_E_ENDPOINT_CREATE_FAILED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x00f, + AUDCLNT_E_SERVICE_NOT_RUNNING = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x010, + AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x011, + AUDCLNT_E_EXCLUSIVE_MODE_ONLY = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x012, + AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x013, + AUDCLNT_E_EVENTHANDLE_NOT_SET = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x014, + AUDCLNT_E_INCORRECT_BUFFER_SIZE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x015, + AUDCLNT_E_BUFFER_SIZE_ERROR = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x016, + AUDCLNT_E_CPUUSAGE_EXCEEDED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x017, + AUDCLNT_E_BUFFER_ERROR = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x018, + AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x019, + AUDCLNT_E_INVALID_DEVICE_PERIOD = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x020, + AUDCLNT_E_INVALID_STREAM_FLAG = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x021, + AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x022, + AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x023, + AUDCLNT_E_OFFLOAD_MODE_ONLY = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x024, + AUDCLNT_E_NONOFFLOAD_MODE_ONLY = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x025, + AUDCLNT_E_RESOURCES_INVALIDATED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x026, + AUDCLNT_E_RAW_MODE_UNSUPPORTED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x027, + AUDCLNT_E_ENGINE_PERIODICITY_LOCKED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x028, + AUDCLNT_E_ENGINE_FORMAT_LOCKED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x029, + AUDCLNT_E_HEADTRACKING_ENABLED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x030, + AUDCLNT_E_HEADTRACKING_UNSUPPORTED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x040, + AUDCLNT_E_EFFECT_NOT_AVAILABLE = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x041, + AUDCLNT_E_EFFECT_STATE_READ_ONLY = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x042, + AUDCLNT_E_POST_VOLUME_LOOPBACK_UNSUPPORTED = _SEVERITY_ERROR << 31 | _FACILITY_AUDCLNT<<16 | 0x043, + + // Success + + AUDCLNT_S_BUFFER_EMPTY = _SEVERITY_SUCCESS<<31 | _FACILITY_AUDCLNT<<16 | 0x001, + AUDCLNT_S_THREAD_ALREADY_REGISTERED = _SEVERITY_SUCCESS<<31 | _FACILITY_AUDCLNT<<16 | 0x002, + AUDCLNT_S_POSITION_STALLED = _SEVERITY_SUCCESS<<31 | _FACILITY_AUDCLNT<<16 | 0x003, +} + +_SEVERITY_ERROR :: 1 +_SEVERITY_SUCCESS :: 0 +_FACILITY_AUDCLNT :: 2185 diff --git a/vendor/windows/wasapi/wasapi_types.odin b/vendor/windows/wasapi/wasapi_types.odin new file mode 100644 index 000000000..1821b1fb3 --- /dev/null +++ b/vendor/windows/wasapi/wasapi_types.odin @@ -0,0 +1,472 @@ +package wasapi + +import "core:sys/windows" + +REFERENCE_TIME :: windows.LONGLONG + +//------------------------------------------------------------------------- +// Description: AudioClient share mode +// +// AUDCLNT_SHAREMODE_SHARED - The device will be opened in shared mode and use the +// WAS format. +// AUDCLNT_SHAREMODE_EXCLUSIVE - The device will be opened in exclusive mode and use the +// application specified format. +// +AUDCLNT_SHAREMODE :: enum u32 { + SHARED, + EXCLUSIVE +} + +//------------------------------------------------------------------------- +// Description: Audio stream categories +// +// ForegroundOnlyMedia - (deprecated for Win10) Music, Streaming audio +// BackgroundCapableMedia - (deprecated for Win10) Video with audio +// Communications - VOIP, chat, phone call +// Alerts - Alarm, Ring tones +// SoundEffects - Sound effects, clicks, dings +// GameEffects - Game sound effects +// GameMedia - Background audio for games +// GameChat - In game player chat +// Speech - Speech recognition +// Media - Music, Streaming audio +// Movie - Video with audio +// FarFieldSpeech - Capture of far field speech +// UniformSpeech - Uniform, device agnostic speech processing +// VoiceTyping - Dictation, typing by voice +// Other - All other streams (default) +AUDIO_STREAM_CATEGORY :: enum u32 { + Other = 0, + ForegroundOnlyMedia = 1, + BackgroundCapableMedia = 2, // #if NTDDI_VERSION < NTDDI_WINTHRESHOLD + Communications = 3, + Alerts = 4, + SoundEffects = 5, + GameEffects = 6, + GameMedia = 7, + GameChat = 8, + Speech = 9, + Movie = 10, + Media = 11, + FarFieldSpeech = 12, // #if NTDDI_VERSION >= NTDDI_WIN10_FE + UniformSpeech = 13, // #if NTDDI_VERSION >= NTDDI_WIN10_FE + VoiceTyping = 14, // #if NTDDI_VERSION >= NTDDI_WIN10_FE +} + + +//------------------------------------------------------------------------- +// Description: AudioClient stream flags +// +// Can be a combination of AUDCLNT_STREAMFLAGS and AUDCLNT_SYSFXFLAGS: +// +// AUDCLNT_STREAMFLAGS (this group of flags uses the high word, +// w/exception of high-bit which is reserved, 0x7FFF0000): +// +// +// AUDCLNT_STREAMFLAGS_CROSSPROCESS - Audio policy control for this stream will be shared with +// with other process sessions that use the same audio session +// GUID. +// +// AUDCLNT_STREAMFLAGS_LOOPBACK - Initializes a renderer endpoint for a loopback audio application. +// In this mode, a capture stream will be opened on the specified +// renderer endpoint. Shared mode and a renderer endpoint is required. +// Otherwise the IAudioClient::Initialize call will fail. If the +// initialize is successful, a capture stream will be available +// from the IAudioClient object. +// +// AUDCLNT_STREAMFLAGS_EVENTCALLBACK - An exclusive mode client will supply an event handle that will be +// signaled when an IRP completes (or a waveRT buffer completes) telling +// it to fill the next buffer +// +// AUDCLNT_STREAMFLAGS_NOPERSIST - Session state will not be persisted +// +// AUDCLNT_STREAMFLAGS_RATEADJUST - The sample rate of the stream is adjusted to a rate specified by an application. +// +// AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY - When used with AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM, a sample rate +// converter with better quality than the default conversion but with a +// higher performance cost is used. This should be used if the audio is +// ultimately intended to be heard by humans as opposed to other +// scenarios such as pumping silence or populating a meter. +// +// AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM - A channel matrixer and a sample rate converter are inserted as necessary +// to convert between the uncompressed format supplied to +// IAudioClient::Initialize and the audio engine mix format. +// +// AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED - Session expires when there are no streams and no owning +// session controls. +// +// AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE - Don't show volume control in the Volume Mixer. +// +// AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED - Don't show volume control in the Volume Mixer after the +// session expires. +// +// +// AUDCLNT_SYSFXFLAGS (these flags use low word 0x0000FFFF): +// +// none defined currently +// +AUDCLNT_FLAG :: enum windows.DWORD { + STREAM_CROSSPROCESS = 0x00010000, + STREAM_LOOPBACK = 0x00020000, + STREAM_EVENTCALLBACK = 0x00040000, + STREAM_NOPERSIST = 0x00080000, + STREAM_RATEADJUST = 0x00100000, + STREAM_SRC_DEFAULT_QUALITY = 0x08000000, + STREAM_AUTOCONVERTPCM = 0x80000000, + SESSION_EXPIREWHENUNOWNED = 0x10000000, + SESSION_DISPLAY_HIDE = 0x20000000, + SESSION_DISPLAY_HIDEWHENEXPIRED = 0x40000000, +} + +EDataFlow :: enum u32 { + Render, + Capture, + All, +} + +ERole :: enum u32 { + Console, + Multimedia, + Communications, +} + +AudioClientProperties :: struct { + cbSize: u32, + bIsOffload: windows.BOOL, + eCategory: AUDIO_STREAM_CATEGORY, + Options: bit_set[AUDCLNT_STREAMOPTION], +} + +AUDCLNT_STREAMOPTIONS_NONE :: bit_set[AUDCLNT_STREAMOPTION]{} +AUDCLNT_STREAMOPTION :: enum u32 { + RAW, + MATCH_FORMAT, + AMBISONICS, + POST_VOLUME_LOOPBACK, +} + +// Used to specify that any possible permutation of speaker configurations +SPEAKERS_ALL :: transmute(bit_set[SPEAKER])u32(0x80000000) + +SPEAKER :: enum windows.DWORD { + FRONT_LEFT, + FRONT_RIGHT, + FRONT_CENTER, + LOW_FREQUENCY, + BACK_LEFT, + BACK_RIGHT, + FRONT_LEFT_OF_CENTER, + FRONT_RIGHT_OF_CENTER, + BACK_CENTER, + SIDE_LEFT, + SIDE_RIGHT, + TOP_CENTER, + TOP_FRONT_LEFT, + TOP_FRONT_CENTER, + TOP_FRONT_RIGHT, + TOP_BACK_LEFT, + TOP_BACK_CENTER, + TOP_BACK_RIGHT, +} + +// extended waveform format structure used for all non-PCM formats. this +// structure is common to all non-PCM formats. +WAVEFORMATEX :: struct #packed { + wFormatTag: WAVE_FORMAT, // format type + nChannels: windows.WORD, // number of channels (i.e. mono, stereo...) + nSamplesPerSec: windows.DWORD, // sample rate + nAvgBytesPerSec: windows.DWORD, // for buffer estimation + nBlockAlign: windows.WORD, // block size of data + wBitsPerSample: windows.WORD, // number of bits per sample of mono data + cbSize: windows.WORD, // the count in bytes of the size of extra information (after cbSize) +} + + +// New wave format development should be based on the +// WAVEFORMATEXTENSIBLE structure. WAVEFORMATEXTENSIBLE allows you to +// avoid having to register a new format tag with Microsoft. Simply +// define a new GUID value for the WAVEFORMATEXTENSIBLE.SubFormat field +// and use WAVE_FORMAT_EXTENSIBLE in the +// WAVEFORMATEXTENSIBLE.Format.wFormatTag field. +WAVEFORMATEXTENSIBLE :: struct { + Format: WAVEFORMATEX, + using Samples: struct #raw_union { + wValidBitsPerSample: windows.WORD, // bits of precision + wSamplesPerBlock: windows.WORD, // valid if wBitsPerSample==0 + wReserved: windows.WORD, // If neither applies, set to zero. + }, + dwChannelMask: bit_set[SPEAKER], // which channels are present in stream + SubFormat: windows.GUID, +} + + +// WAVE form wFormatTag IDs +WAVE_FORMAT :: enum windows.WORD { + UNKNOWN = 0x0000, /* Microsoft Corporation */ + ADPCM = 0x0002, /* Microsoft Corporation */ + IEEE_FLOAT = 0x0003, /* Microsoft Corporation */ + VSELP = 0x0004, /* Compaq Computer Corp. */ + IBM_CVSD = 0x0005, /* IBM Corporation */ + ALAW = 0x0006, /* Microsoft Corporation */ + MULAW = 0x0007, /* Microsoft Corporation */ + DTS = 0x0008, /* Microsoft Corporation */ + DRM = 0x0009, /* Microsoft Corporation */ + WMAVOICE9 = 0x000A, /* Microsoft Corporation */ + WMAVOICE10 = 0x000B, /* Microsoft Corporation */ + OKI_ADPCM = 0x0010, /* OKI */ + DVI_ADPCM = 0x0011, /* Intel Corporation */ + IMA_ADPCM = DVI_ADPCM, /* Intel Corporation */ + MEDIASPACE_ADPCM = 0x0012, /* Videologic */ + SIERRA_ADPCM = 0x0013, /* Sierra Semiconductor Corp */ + G723_ADPCM = 0x0014, /* Antex Electronics Corporation */ + DIGISTD = 0x0015, /* DSP Solutions, Inc. */ + DIGIFIX = 0x0016, /* DSP Solutions, Inc. */ + DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic Corporation */ + MEDIAVISION_ADPCM = 0x0018, /* Media Vision, Inc. */ + CU_CODEC = 0x0019, /* Hewlett-Packard Company */ + HP_DYN_VOICE = 0x001A, /* Hewlett-Packard Company */ + YAMAHA_ADPCM = 0x0020, /* Yamaha Corporation of America */ + SONARC = 0x0021, /* Speech Compression */ + DSPGROUP_TRUESPEECH = 0x0022, /* DSP Group, Inc */ + ECHOSC1 = 0x0023, /* Echo Speech Corporation */ + AUDIOFILE_AF36 = 0x0024, /* Virtual Music, Inc. */ + APTX = 0x0025, /* Audio Processing Technology */ + AUDIOFILE_AF10 = 0x0026, /* Virtual Music, Inc. */ + PROSODY_1612 = 0x0027, /* Aculab plc */ + LRC = 0x0028, /* Merging Technologies S.A. */ + DOLBY_AC2 = 0x0030, /* Dolby Laboratories */ + GSM610 = 0x0031, /* Microsoft Corporation */ + MSNAUDIO = 0x0032, /* Microsoft Corporation */ + ANTEX_ADPCME = 0x0033, /* Antex Electronics Corporation */ + CONTROL_RES_VQLPC = 0x0034, /* Control Resources Limited */ + DIGIREAL = 0x0035, /* DSP Solutions, Inc. */ + DIGIADPCM = 0x0036, /* DSP Solutions, Inc. */ + CONTROL_RES_CR10 = 0x0037, /* Control Resources Limited */ + NMS_VBXADPCM = 0x0038, /* Natural MicroSystems */ + CS_IMAADPCM = 0x0039, /* Crystal Semiconductor IMA ADPCM */ + ECHOSC3 = 0x003A, /* Echo Speech Corporation */ + ROCKWELL_ADPCM = 0x003B, /* Rockwell International */ + ROCKWELL_DIGITALK = 0x003C, /* Rockwell International */ + XEBEC = 0x003D, /* Xebec Multimedia Solutions Limited */ + G721_ADPCM = 0x0040, /* Antex Electronics Corporation */ + G728_CELP = 0x0041, /* Antex Electronics Corporation */ + MSG723 = 0x0042, /* Microsoft Corporation */ + INTEL_G723_1 = 0x0043, /* Intel Corp. */ + INTEL_G729 = 0x0044, /* Intel Corp. */ + SHARP_G726 = 0x0045, /* Sharp */ + MPEG = 0x0050, /* Microsoft Corporation */ + RT24 = 0x0052, /* InSoft, Inc. */ + PAC = 0x0053, /* InSoft, Inc. */ + MPEGLAYER3 = 0x0055, /* ISO/MPEG Layer3 Format Tag */ + LUCENT_G723 = 0x0059, /* Lucent Technologies */ + CIRRUS = 0x0060, /* Cirrus Logic */ + ESPCM = 0x0061, /* ESS Technology */ + VOXWARE = 0x0062, /* Voxware Inc */ + CANOPUS_ATRAC = 0x0063, /* Canopus, co., Ltd. */ + G726_ADPCM = 0x0064, /* APICOM */ + G722_ADPCM = 0x0065, /* APICOM */ + DSAT = 0x0066, /* Microsoft Corporation */ + DSAT_DISPLAY = 0x0067, /* Microsoft Corporation */ + VOXWARE_BYTE_ALIGNED = 0x0069, /* Voxware Inc */ + VOXWARE_AC8 = 0x0070, /* Voxware Inc */ + VOXWARE_AC10 = 0x0071, /* Voxware Inc */ + VOXWARE_AC16 = 0x0072, /* Voxware Inc */ + VOXWARE_AC20 = 0x0073, /* Voxware Inc */ + VOXWARE_RT24 = 0x0074, /* Voxware Inc */ + VOXWARE_RT29 = 0x0075, /* Voxware Inc */ + VOXWARE_RT29HW = 0x0076, /* Voxware Inc */ + VOXWARE_VR12 = 0x0077, /* Voxware Inc */ + VOXWARE_VR18 = 0x0078, /* Voxware Inc */ + VOXWARE_TQ40 = 0x0079, /* Voxware Inc */ + VOXWARE_SC3 = 0x007A, /* Voxware Inc */ + VOXWARE_SC3_1 = 0x007B, /* Voxware Inc */ + SOFTSOUND = 0x0080, /* Softsound, Ltd. */ + VOXWARE_TQ60 = 0x0081, /* Voxware Inc */ + MSRT24 = 0x0082, /* Microsoft Corporation */ + G729A = 0x0083, /* AT&T Labs, Inc. */ + MVI_MVI2 = 0x0084, /* Motion Pixels */ + DF_G726 = 0x0085, /* DataFusion Systems (Pty) (Ltd) */ + DF_GSM610 = 0x0086, /* DataFusion Systems (Pty) (Ltd) */ + ISIAUDIO = 0x0088, /* Iterated Systems, Inc. */ + ONLIVE = 0x0089, /* OnLive! Technologies, Inc. */ + MULTITUDE_FT_SX20 = 0x008A, /* Multitude Inc. */ + INFOCOM_ITS_G721_ADPCM = 0x008B, /* Infocom */ + CONVEDIA_G729 = 0x008C, /* Convedia Corp. */ + CONGRUENCY = 0x008D, /* Congruency Inc. */ + SBC24 = 0x0091, /* Siemens Business Communications Sys */ + DOLBY_AC3_SPDIF = 0x0092, /* Sonic Foundry */ + MEDIASONIC_G723 = 0x0093, /* MediaSonic */ + PROSODY_8KBPS = 0x0094, /* Aculab plc */ + ZYXEL_ADPCM = 0x0097, /* ZyXEL Communications, Inc. */ + PHILIPS_LPCBB = 0x0098, /* Philips Speech Processing */ + PACKED = 0x0099, /* Studer Professional Audio AG */ + MALDEN_PHONYTALK = 0x00A0, /* Malden Electronics Ltd. */ + RACAL_RECORDER_GSM = 0x00A1, /* Racal recorders */ + RACAL_RECORDER_G720_A = 0x00A2, /* Racal recorders */ + RACAL_RECORDER_G723_1 = 0x00A3, /* Racal recorders */ + RACAL_RECORDER_TETRA_ACELP = 0x00A4, /* Racal recorders */ + NEC_AAC = 0x00B0, /* NEC Corp. */ + RAW_AAC1 = 0x00FF, /* For Raw AAC, with format block AudioSpecificConfig() (as defined by MPEG-4), that follows WAVEFORMATEX */ + RHETOREX_ADPCM = 0x0100, /* Rhetorex Inc. */ + IRAT = 0x0101, /* BeCubed Software Inc. */ + VIVO_G723 = 0x0111, /* Vivo Software */ + VIVO_SIREN = 0x0112, /* Vivo Software */ + PHILIPS_CELP = 0x0120, /* Philips Speech Processing */ + PHILIPS_GRUNDIG = 0x0121, /* Philips Speech Processing */ + DIGITAL_G723 = 0x0123, /* Digital Equipment Corporation */ + SANYO_LD_ADPCM = 0x0125, /* Sanyo Electric Co., Ltd. */ + SIPROLAB_ACEPLNET = 0x0130, /* Sipro Lab Telecom Inc. */ + SIPROLAB_ACELP4800 = 0x0131, /* Sipro Lab Telecom Inc. */ + SIPROLAB_ACELP8V3 = 0x0132, /* Sipro Lab Telecom Inc. */ + SIPROLAB_G729 = 0x0133, /* Sipro Lab Telecom Inc. */ + SIPROLAB_G729A = 0x0134, /* Sipro Lab Telecom Inc. */ + SIPROLAB_KELVIN = 0x0135, /* Sipro Lab Telecom Inc. */ + VOICEAGE_AMR = 0x0136, /* VoiceAge Corp. */ + G726ADPCM = 0x0140, /* Dictaphone Corporation */ + DICTAPHONE_CELP68 = 0x0141, /* Dictaphone Corporation */ + DICTAPHONE_CELP54 = 0x0142, /* Dictaphone Corporation */ + QUALCOMM_PUREVOICE = 0x0150, /* Qualcomm, Inc. */ + QUALCOMM_HALFRATE = 0x0151, /* Qualcomm, Inc. */ + TUBGSM = 0x0155, /* Ring Zero Systems, Inc. */ + MSAUDIO1 = 0x0160, /* Microsoft Corporation */ + WMAUDIO2 = 0x0161, /* Microsoft Corporation */ + WMAUDIO3 = 0x0162, /* Microsoft Corporation */ + WMAUDIO_LOSSLESS = 0x0163, /* Microsoft Corporation */ + WMASPDIF = 0x0164, /* Microsoft Corporation */ + UNISYS_NAP_ADPCM = 0x0170, /* Unisys Corp. */ + UNISYS_NAP_ULAW = 0x0171, /* Unisys Corp. */ + UNISYS_NAP_ALAW = 0x0172, /* Unisys Corp. */ + UNISYS_NAP_16K = 0x0173, /* Unisys Corp. */ + SYCOM_ACM_SYC008 = 0x0174, /* SyCom Technologies */ + SYCOM_ACM_SYC701_G726L = 0x0175, /* SyCom Technologies */ + SYCOM_ACM_SYC701_CELP54 = 0x0176, /* SyCom Technologies */ + SYCOM_ACM_SYC701_CELP68 = 0x0177, /* SyCom Technologies */ + KNOWLEDGE_ADVENTURE_ADPCM = 0x0178, /* Knowledge Adventure, Inc. */ + FRAUNHOFER_IIS_MPEG2_AAC = 0x0180, /* Fraunhofer IIS */ + DTS_DS = 0x0190, /* Digital Theatre Systems, Inc. */ + CREATIVE_ADPCM = 0x0200, /* Creative Labs, Inc */ + CREATIVE_FASTSPEECH8 = 0x0202, /* Creative Labs, Inc */ + CREATIVE_FASTSPEECH10 = 0x0203, /* Creative Labs, Inc */ + UHER_ADPCM = 0x0210, /* UHER informatic GmbH */ + ULEAD_DV_AUDIO = 0x0215, /* Ulead Systems, Inc. */ + ULEAD_DV_AUDIO_1 = 0x0216, /* Ulead Systems, Inc. */ + QUARTERDECK = 0x0220, /* Quarterdeck Corporation */ + ILINK_VC = 0x0230, /* I-link Worldwide */ + RAW_SPORT = 0x0240, /* Aureal Semiconductor */ + ESST_AC3 = 0x0241, /* ESS Technology, Inc. */ + GENERIC_PASSTHRU = 0x0249, + IPI_HSX = 0x0250, /* Interactive Products, Inc. */ + IPI_RPELP = 0x0251, /* Interactive Products, Inc. */ + CS2 = 0x0260, /* Consistent Software */ + SONY_SCX = 0x0270, /* Sony Corp. */ + SONY_SCY = 0x0271, /* Sony Corp. */ + SONY_ATRAC3 = 0x0272, /* Sony Corp. */ + SONY_SPC = 0x0273, /* Sony Corp. */ + TELUM_AUDIO = 0x0280, /* Telum Inc. */ + TELUM_IA_AUDIO = 0x0281, /* Telum Inc. */ + NORCOM_VOICE_SYSTEMS_ADPCM = 0x0285, /* Norcom Electronics Corp. */ + FM_TOWNS_SND = 0x0300, /* Fujitsu Corp. */ + MICRONAS = 0x0350, /* Micronas Semiconductors, Inc. */ + MICRONAS_CELP833 = 0x0351, /* Micronas Semiconductors, Inc. */ + BTV_DIGITAL = 0x0400, /* Brooktree Corporation */ + INTEL_MUSIC_CODER = 0x0401, /* Intel Corp. */ + INDEO_AUDIO = 0x0402, /* Ligos */ + QDESIGN_MUSIC = 0x0450, /* QDesign Corporation */ + ON2_VP7_AUDIO = 0x0500, /* On2 Technologies */ + ON2_VP6_AUDIO = 0x0501, /* On2 Technologies */ + VME_VMPCM = 0x0680, /* AT&T Labs, Inc. */ + TPC = 0x0681, /* AT&T Labs, Inc. */ + LIGHTWAVE_LOSSLESS = 0x08AE, /* Clearjump */ + OLIGSM = 0x1000, /* Ing C. Olivetti & C., S.p.A. */ + OLIADPCM = 0x1001, /* Ing C. Olivetti & C., S.p.A. */ + OLICELP = 0x1002, /* Ing C. Olivetti & C., S.p.A. */ + OLISBC = 0x1003, /* Ing C. Olivetti & C., S.p.A. */ + OLIOPR = 0x1004, /* Ing C. Olivetti & C., S.p.A. */ + LH_CODEC = 0x1100, /* Lernout & Hauspie */ + LH_CODEC_CELP = 0x1101, /* Lernout & Hauspie */ + LH_CODEC_SBC8 = 0x1102, /* Lernout & Hauspie */ + LH_CODEC_SBC12 = 0x1103, /* Lernout & Hauspie */ + LH_CODEC_SBC16 = 0x1104, /* Lernout & Hauspie */ + NORRIS = 0x1400, /* Norris Communications, Inc. */ + ISIAUDIO_2 = 0x1401, /* ISIAudio */ + SOUNDSPACE_MUSICOMPRESS = 0x1500, /* AT&T Labs, Inc. */ + MPEG_ADTS_AAC = 0x1600, /* Microsoft Corporation */ + MPEG_RAW_AAC = 0x1601, /* Microsoft Corporation */ + MPEG_LOAS = 0x1602, /* Microsoft Corporation (MPEG-4 Audio Transport Streams (LOAS/LATM) */ + NOKIA_MPEG_ADTS_AAC = 0x1608, /* Microsoft Corporation */ + NOKIA_MPEG_RAW_AAC = 0x1609, /* Microsoft Corporation */ + VODAFONE_MPEG_ADTS_AAC = 0x160A, /* Microsoft Corporation */ + VODAFONE_MPEG_RAW_AAC = 0x160B, /* Microsoft Corporation */ + MPEG_HEAAC = 0x1610, /* Microsoft Corporation (MPEG-2 AAC or MPEG-4 HE-AAC v1/v2 streams with any payload (ADTS, ADIF, LOAS/LATM, RAW). Format block includes MP4 AudioSpecificConfig() -- see HEAACWAVEFORMAT below */ + VOXWARE_RT24_SPEECH = 0x181C, /* Voxware Inc. */ + SONICFOUNDRY_LOSSLESS = 0x1971, /* Sonic Foundry */ + INNINGS_TELECOM_ADPCM = 0x1979, /* Innings Telecom Inc. */ + LUCENT_SX8300P = 0x1C07, /* Lucent Technologies */ + LUCENT_SX5363S = 0x1C0C, /* Lucent Technologies */ + CUSEEME = 0x1F03, /* CUSeeMe */ + NTCSOFT_ALF2CM_ACM = 0x1FC4, /* NTCSoft */ + DVM = 0x2000, /* FAST Multimedia AG */ + DTS2 = 0x2001, + MAKEAVIS = 0x3313, + DIVIO_MPEG4_AAC = 0x4143, /* Divio, Inc. */ + NOKIA_ADAPTIVE_MULTIRATE = 0x4201, /* Nokia */ + DIVIO_G726 = 0x4243, /* Divio, Inc. */ + LEAD_SPEECH = 0x434C, /* LEAD Technologies */ + LEAD_VORBIS = 0x564C, /* LEAD Technologies */ + WAVPACK_AUDIO = 0x5756, /* xiph.org */ + ALAC = 0x6C61, /* Apple Lossless */ + OGG_VORBIS_MODE_1 = 0x674F, /* Ogg Vorbis */ + OGG_VORBIS_MODE_2 = 0x6750, /* Ogg Vorbis */ + OGG_VORBIS_MODE_3 = 0x6751, /* Ogg Vorbis */ + OGG_VORBIS_MODE_1_PLUS = 0x676F, /* Ogg Vorbis */ + OGG_VORBIS_MODE_2_PLUS = 0x6770, /* Ogg Vorbis */ + OGG_VORBIS_MODE_3_PLUS = 0x6771, /* Ogg Vorbis */ + _3COM_NBX = 0x7000, /* 3COM Corp. */ + OPUS = 0x704F, /* Opus */ + FAAD_AAC = 0x706D, + AMR_NB = 0x7361, /* AMR Narrowband */ + AMR_WB = 0x7362, /* AMR Wideband */ + AMR_WP = 0x7363, /* AMR Wideband Plus */ + GSM_AMR_CBR = 0x7A21, /* GSMA/3GPP */ + GSM_AMR_VBR_SID = 0x7A22, /* GSMA/3GPP */ + COMVERSE_INFOSYS_G723_1 = 0xA100, /* Comverse Infosys */ + COMVERSE_INFOSYS_AVQSBC = 0xA101, /* Comverse Infosys */ + COMVERSE_INFOSYS_SBC = 0xA102, /* Comverse Infosys */ + SYMBOL_G729_A = 0xA103, /* Symbol Technologies */ + VOICEAGE_AMR_WB = 0xA104, /* VoiceAge Corp. */ + INGENIENT_G726 = 0xA105, /* Ingenient Technologies, Inc. */ + MPEG4_AAC = 0xA106, /* ISO/MPEG-4 */ + ENCORE_G726 = 0xA107, /* Encore Software */ + ZOLL_ASAO = 0xA108, /* ZOLL Medical Corp. */ + SPEEX_VOICE = 0xA109, /* xiph.org */ + VIANIX_MASC = 0xA10A, /* Vianix LLC */ + WM9_SPECTRUM_ANALYZER = 0xA10B, /* Microsoft */ + WMF_SPECTRUM_ANAYZER = 0xA10C, /* Microsoft */ + GSM_610 = 0xA10D, + GSM_620 = 0xA10E, + GSM_660 = 0xA10F, + GSM_690 = 0xA110, + GSM_ADAPTIVE_MULTIRATE_WB = 0xA111, + POLYCOM_G722 = 0xA112, /* Polycom */ + POLYCOM_G728 = 0xA113, /* Polycom */ + POLYCOM_G729_A = 0xA114, /* Polycom */ + POLYCOM_SIREN = 0xA115, /* Polycom */ + GLOBAL_IP_ILBC = 0xA116, /* Global IP */ + RADIOTIME_TIME_SHIFT_RADIO = 0xA117, /* RadioTime */ + NICE_ACA = 0xA118, /* Nice Systems */ + NICE_ADPCM = 0xA119, /* Nice Systems */ + VOCORD_G721 = 0xA11A, /* Vocord Telecom */ + VOCORD_G726 = 0xA11B, /* Vocord Telecom */ + VOCORD_G722_1 = 0xA11C, /* Vocord Telecom */ + VOCORD_G728 = 0xA11D, /* Vocord Telecom */ + VOCORD_G729 = 0xA11E, /* Vocord Telecom */ + VOCORD_G729_A = 0xA11F, /* Vocord Telecom */ + VOCORD_G723_1 = 0xA120, /* Vocord Telecom */ + VOCORD_LBC = 0xA121, /* Vocord Telecom */ + NICE_G728 = 0xA122, /* Nice Systems */ + FRACE_TELECOM_G729 = 0xA123, /* France Telecom */ + CODIAN = 0xA124, /* CODIAN */ + DOLBY_AC4 = 0xAC40, /* Dolby AC-4 */ + FLAC = 0xF1AC, /* flac.sourceforge.net */ + EXTENSIBLE = 0xFFFE, /* Microsoft */ +} diff --git a/vendor/x11/xlib/xlib.odin b/vendor/x11/xlib/xlib.odin index bd9ba3b59..c4071055a 100644 --- a/vendor/x11/xlib/xlib.odin +++ b/vendor/x11/xlib/xlib.odin @@ -1,3 +1,4 @@ +// Bindings for [[ X11's Xlib (PDF) ; https://xorg.freedesktop.org/archive/current/doc/libX11/libX11/libX11.pdf ]]. package xlib // Value, specifying whether `vendor:x11/xlib` is available on the current platform. diff --git a/vendor/x11/xlib/xlib_const.odin b/vendor/x11/xlib/xlib_const.odin index 27af6a2d8..9163d1830 100644 --- a/vendor/x11/xlib/xlib_const.odin +++ b/vendor/x11/xlib/xlib_const.odin @@ -1,6 +1,15 @@ #+build linux, freebsd, openbsd package xlib +XNClientWindow: cstring : "clientWindow" +XNInputStyle: cstring : "inputStyle" +XNFocusWindow: cstring : "focusWindow" +XNSpotLocation: cstring : "spotLocation" +XNPreeditAttributes: cstring : "preeditAttributes" + +XIMPreeditNothing :: 0x0008 +XIMStatusNothing :: 0x0400 + /* ---- X11/extensions/XKB.h ---------------------------------------------------------*/ XkbMinLegalKeyCode :: 8 @@ -101,6 +110,8 @@ PropModePrepend :: 1 PropModeAppend :: 2 XA_ATOM :: Atom(4) +XA_CARDINAL :: Atom(6) +XA_INTEGER :: Atom(19) XA_WM_CLASS :: Atom(67) XA_WM_CLIENT_MACHINE :: Atom(36) XA_WM_COMMAND :: Atom(34) @@ -138,6 +149,14 @@ Status :: enum i32 { LastExtensionError = 255, } +LookupStringStatus :: enum i32 { + BufferOverflow = -1, + LookupNone = 1, + LookupChars = 2, + LookupKeySym = 3, + LookupBoth = 4, +} + ByteOrder :: enum i32 { LSBFirst = 0, MSBFirst = 1, @@ -694,7 +713,7 @@ AllHints :: WMHints{ .WindowGroupHint, } -SizeHints :: bit_set[SizeHintsBits; uint] +SizeHints :: bit_set[SizeHintsBits; int] SizeHintsBits :: enum { USPosition = 0, USSize = 1, diff --git a/vendor/x11/xlib/xlib_keysym.odin b/vendor/x11/xlib/xlib_keysym.odin index 61284c723..267b77b1c 100644 --- a/vendor/x11/xlib/xlib_keysym.odin +++ b/vendor/x11/xlib/xlib_keysym.odin @@ -1,7 +1,7 @@ #+build linux, freebsd, openbsd package xlib -KeySym :: enum u32 { +KeySym :: enum uint { XK_BackSpace = 0xff08, /* Back space, back char */ XK_Tab = 0xff09, XK_Linefeed = 0xff0a, /* Linefeed, LF */ diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index 2a8d6832b..d9992721e 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -13,7 +13,8 @@ foreign xcursor { cursorGetDefaultSize :: proc(display: ^Display) -> i32 --- cursorLibraryLoadCursor :: proc(display: ^Display, name: cstring) -> Cursor --- cursorLibraryLoadImage :: proc(name: cstring, theme: cstring, size: i32) -> rawptr --- - cursorImageLoadCursor :: proc(display: ^Display, img: rawptr) -> Cursor --- + cursorImageCreate :: proc(width: i32, height: i32) -> ^CursorImage --- + cursorImageLoadCursor :: proc(display: ^Display, img: ^CursorImage) -> Cursor --- cursorImageDestroy :: proc(img: rawptr) --- } @@ -180,11 +181,11 @@ foreign xlib { DestroyWindow :: proc(display: ^Display, window: Window) --- DestroySubwindows :: proc(display: ^Display, window: Window) --- // Windows: mapping/unmapping - MapWindow :: proc(display: ^Display, window: Window) --- - MapRaised :: proc(display: ^Display, window: Window) --- - MapSubwindows :: proc(display: ^Display, window: Window) --- - UnmapWindow :: proc(display: ^Display, window: Window) --- - UnmapSubwindows :: proc(display: ^Display, window: Window) --- + MapWindow :: proc(display: ^Display, window: Window) -> b32 --- + MapRaised :: proc(display: ^Display, window: Window) -> b32 --- + MapSubwindows :: proc(display: ^Display, window: Window) -> b32 --- + UnmapWindow :: proc(display: ^Display, window: Window) -> b32 --- + UnmapSubwindows :: proc(display: ^Display, window: Window) -> b32 --- // Windows: configuring ConfigureWindow :: proc( display: ^Display, @@ -234,14 +235,14 @@ foreign xlib { display: ^Display, window: Window, attr_mask: WindowAttributeMask, - attr: XWindowAttributes, + attr: ^XSetWindowAttributes, ) --- SetWindowBackground :: proc( display: ^Display, window: Window, pixel: uint, ) --- - SetWindowBackgroundMap :: proc( + SetWindowBackgroundPixmap :: proc( display: ^Display, window: Window, pixmap: Pixmap, @@ -294,6 +295,7 @@ foreign xlib { src_y: i32, dst_x: ^i32, dst_y: ^i32, + dst_child: ^Window, ) -> b32 --- QueryPointer :: proc( display: ^Display, @@ -313,10 +315,11 @@ foreign xlib { existing: b32, ) -> Atom --- InternAtoms :: proc( - display: ^Display, - names: [^]cstring, - count: i32, - atoms: [^]Atom, + display: ^Display, + names: [^]cstring, + count: i32, + only_if_exists: b32, + atoms_return: [^]Atom, ) -> Status --- GetAtomName :: proc( display: ^Display, @@ -337,10 +340,10 @@ foreign xlib { long_len: int, delete: b32, req_type: Atom, - act_type: [^]Atom, - act_format: [^]i32, - nitems: [^]uint, - bytes_after: [^]uint, + act_type: ^Atom, + act_format: ^i32, + nitems: ^uint, + bytes_after: ^uint, props: ^rawptr, ) -> i32 --- ListProperties :: proc( @@ -374,7 +377,7 @@ foreign xlib { SetSelectionOwner :: proc( display: ^Display, selection: Atom, - owber: Window, + owner: Window, time: Time, ) --- GetSelectionOwner :: proc( @@ -389,6 +392,18 @@ foreign xlib { requestor: Window, time: Time, ) --- + GetTextProperty :: proc( + display: ^Display, + window: Window, + text_prop_return: ^XTextProperty, + property: Atom, + ) -> Status --- + SetTextProperty :: proc( + display: ^Display, + window: Window, + text_prop: ^XTextProperty, + property: Atom, + ) --- // Creating and freeing pixmaps CreatePixmap :: proc( display: ^Display, @@ -643,12 +658,12 @@ foreign xlib { SetGraphicsExposures :: proc(display: ^Display, gc: GC, exp: b32) --- // Graphics functions ClearArea :: proc( - display: ^Display, - window: Window, - x: i32, - y: i32, - width: u32, - height: u32, + display: ^Display, + window: Window, + x: i32, + y: i32, + width: u32, + height: u32, exp: b32, ) --- ClearWindow :: proc( @@ -1013,11 +1028,12 @@ foreign xlib { // Events SelectInput :: proc(display: ^Display, window: Window, mask: EventMask) --- Flush :: proc(display: ^Display) -> i32 --- - Sync :: proc(display: ^Display, discard: bool) -> i32 --- + Sync :: proc(display: ^Display, discard: b32) -> i32 --- EventsQueued :: proc(display: ^Display, mode: EventQueueMode) -> i32 --- Pending :: proc(display: ^Display) -> i32 --- NextEvent :: proc(display: ^Display, event: ^XEvent) --- PeekEvent :: proc(display: ^Display, event: ^XEvent) --- + FilterEvent :: proc(event: ^XEvent, window: Window) -> b32 --- GetEventData :: proc(display: ^Display, cookie: ^XGenericEventCookie) -> b32 --- FreeEventData :: proc(display: ^Display, cookie: ^XGenericEventCookie) --- // Selecting events using a predicate procedure @@ -1099,15 +1115,15 @@ foreign xlib { SetAfterFunction :: proc( display: ^Display, procedure: #type proc "c" (display: ^Display) -> i32, - ) -> i32 --- + ) -> proc "c" (display: ^Display) -> i32 --- Synchronize :: proc( display: ^Display, onoff: b32, - ) -> i32 --- + ) -> proc "c" (display: ^Display) -> i32 --- // Error handling SetErrorHandler :: proc( handler: #type proc "c" (display: ^Display, event: ^XErrorEvent) -> i32, - ) -> i32 --- + ) -> proc "c" (display: ^Display, event: ^XErrorEvent) -> i32 --- GetErrorText :: proc( display: ^Display, code: i32, @@ -1125,7 +1141,7 @@ foreign xlib { DisplayName :: proc(string: cstring) -> cstring --- SetIOErrorHandler :: proc( handler: #type proc "c" (display: ^Display) -> i32, - ) -> i32 --- + ) -> proc "c" (display: ^Display) -> i32 --- // Pointer grabbing GrabPointer :: proc( display: ^Display, @@ -1287,7 +1303,7 @@ foreign xlib { dipslay: ^Display, window: Window, screen_no: i32, - ) -> Status --- + ) -> b32 --- WithdrawWindow :: proc( dipslay: ^Display, window: Window, @@ -1352,7 +1368,7 @@ foreign xlib { display: ^Display, window: Window, ) -> ^XWMHints --- - // Setting and reading MW_NORMAL_HINTS property + // Setting and reading WM_NORMAL_HINTS property AllocSizeHints :: proc() -> ^XSizeHints --- SetWMNormalHints :: proc( display: ^Display, @@ -1685,6 +1701,24 @@ foreign xlib { res_class: cstring, ) -> XIM --- SetLocaleModifiers :: proc(modifiers: cstring) -> cstring --- + CreateIC :: proc( + im: XIM, + #c_vararg args: ..any, + ) -> XIC --- + SetICFocus :: proc( + ic: XIC, + ) --- + UnsetICFocus :: proc( + ic: XIC, + ) --- + SetICValues :: proc( + ic: XIC, + #c_vararg args: ..any, + ) -> cstring --- + VaCreateNestedList :: proc( + unused: i32, + #c_vararg args: ..any, + ) -> XVaNestedList --- } @(default_calling_convention="c") @@ -2034,4 +2068,12 @@ foreign xlib { num: u32, xkb: XkbDescPtr, ) -> Status --- + Xutf8LookupString :: proc( + ic: XIC, + event: ^XKeyPressedEvent, + buffer_return: cstring, + bytes_buffer: i32, + keysym_return: ^KeySym, + status_return: ^LookupStringStatus, + ) -> i32 --- } diff --git a/vendor/x11/xlib/xlib_types.odin b/vendor/x11/xlib/xlib_types.odin index a73b8e8b8..bdbaf441e 100644 --- a/vendor/x11/xlib/xlib_types.odin +++ b/vendor/x11/xlib/xlib_types.odin @@ -2257,3 +2257,16 @@ XIRawEvent :: struct { raw_values: [^]f64, } +CursorUInt :: u32 +CursorDim :: u32 +CursorPixel :: u32 +CursorImage :: struct { + version: CursorDim, + size: CursorDim, + width: CursorDim, + height: CursorDim, + xhot: CursorDim, + yhot: CursorDim, + delay: CursorUInt, + pixels: ^CursorPixel, // ARGB +} diff --git a/vendor/zlib/zlib.odin b/vendor/zlib/zlib.odin index 021449813..bc6b22cb7 100644 --- a/vendor/zlib/zlib.odin +++ b/vendor/zlib/zlib.odin @@ -1,3 +1,4 @@ +// Bindings for [[ libz ; https://zlib.net ]] ZLIB compression library. package vendor_zlib import "core:c" @@ -221,7 +222,7 @@ foreign zlib { @(default_calling_convention="c") foreign zlib { deflateInit_ :: proc(strm: z_streamp, level: c.int, version: cstring, stream_size: c.int) -> c.int --- - inflateInit_ :: proc(strm: z_streamp, level: c.int, version: cstring, stream_size: c.int) -> c.int --- + inflateInit_ :: proc(strm: z_streamp, version: cstring, stream_size: c.int) -> c.int --- deflateInit2_ :: proc(strm: z_streamp, level, method, windowBits, memLevel, strategy: c.int, version: cstring, stream_size: c.int) -> c.int --- inflateInit2_ :: proc(strm: z_streamp, windowBits: c.int, version: cstring, stream_size: c.int) -> c.int --- inflateBackInit_ :: proc(strm: z_streamp, windowBits: c.int, window: [^]c.uchar, version: cstring, stream_size: c.int) -> c.int --- @@ -235,8 +236,8 @@ deflateInit :: #force_inline proc "c" (strm: z_streamp, level: c.int) -> c.int { return deflateInit_(strm, level, VERSION, c.int(size_of(z_stream))) } -inflateInit :: #force_inline proc "c" (strm: z_streamp, level: c.int) -> c.int { - return inflateInit_(strm, level, VERSION, c.int(size_of(z_stream))) +inflateInit :: #force_inline proc "c" (strm: z_streamp) -> c.int { + return inflateInit_(strm, VERSION, c.int(size_of(z_stream))) } deflateInit2 :: #force_inline proc "c" (strm: z_streamp, level, method, windowBits, memLevel, strategy: c.int) -> c.int {